From c47fc6022d76aef014432608b796290528aa6627 Mon Sep 17 00:00:00 2001 From: Gautam Date: Wed, 28 Sep 2016 15:14:08 +0530 Subject: [PATCH 0001/1765] Update gradiesnt_descent.py --- tensorflow/python/training/gradient_descent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/python/training/gradient_descent.py b/tensorflow/python/training/gradient_descent.py index 3e3f573563..e60949ca87 100644 --- a/tensorflow/python/training/gradient_descent.py +++ b/tensorflow/python/training/gradient_descent.py @@ -47,7 +47,7 @@ class GradientDescentOptimizer(optimizer.Optimizer): return training_ops.apply_gradient_descent( var, math_ops.cast(self._learning_rate_tensor, var.dtype.base_dtype), - grad, + grad.indices, use_locking=self._use_locking).op def _apply_sparse(self, grad, var): -- GitLab From 970972d242e26d0cdf635d3af646df1a519dc677 Mon Sep 17 00:00:00 2001 From: ThisIsPIRI <34787507+ThisIsPIRI@users.noreply.github.com> Date: Mon, 6 Aug 2018 14:41:37 +0900 Subject: [PATCH 0002/1765] Clarify what happens when a new value is input to some methods --- tensorflow/contrib/training/python/training/hparam.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tensorflow/contrib/training/python/training/hparam.py b/tensorflow/contrib/training/python/training/hparam.py index 3beb7bfe30..9f5059b4b1 100644 --- a/tensorflow/contrib/training/python/training/hparam.py +++ b/tensorflow/contrib/training/python/training/hparam.py @@ -494,6 +494,7 @@ class HParams(object): value: New value of the hyperparameter. Raises: + KeyError: If the hyperparameter doesn't exist. ValueError: If there is a type mismatch. """ param_type, is_list = self._hparam_types[name] @@ -510,7 +511,7 @@ class HParams(object): setattr(self, name, _cast_to_type_if_compatible(name, param_type, value)) def del_hparam(self, name): - """Removes the hyperparameter with key 'name'. + """Removes the hyperparameter with key 'name'. Does nothing if it isn't present. Args: name: Name of the hyperparameter. @@ -532,7 +533,7 @@ class HParams(object): The `HParams` instance. Raises: - ValueError: If `values` cannot be parsed. + ValueError: If `values` cannot be parsed or a hyperparameter in `values` doesn't exist. """ type_map = dict() for name, t in self._hparam_types.items(): @@ -543,7 +544,7 @@ class HParams(object): return self.override_from_dict(values_map) def override_from_dict(self, values_dict): - """Override hyperparameter values, parsing new values from a dictionary. + """Override existing hyperparameter values, parsing new values from a dictionary. Args: values_dict: Dictionary of name:value pairs. @@ -552,6 +553,7 @@ class HParams(object): The `HParams` instance. Raises: + KeyError: If a hyperparameter in `values_dict` doesn't exist. ValueError: If `values_dict` cannot be parsed. """ for name, value in values_dict.items(): @@ -591,7 +593,7 @@ class HParams(object): sort_keys=sort_keys) def parse_json(self, values_json): - """Override hyperparameter values, parsing new values from a json object. + """Override existing hyperparameter values, parsing new values from a json object. Args: values_json: String containing a json object of name:value pairs. @@ -600,6 +602,7 @@ class HParams(object): The `HParams` instance. Raises: + KeyError: If a hyperparameter in `values_json` doesn't exist. ValueError: If `values_json` cannot be parsed. """ values_map = json.loads(values_json) -- GitLab From 26368188c018cdcc1bbb80ce8205fb04305816c2 Mon Sep 17 00:00:00 2001 From: ThisIsPIRI <34787507+ThisIsPIRI@users.noreply.github.com> Date: Mon, 6 Aug 2018 14:56:38 +0900 Subject: [PATCH 0003/1765] Add 'existing' to parse's docstring --- tensorflow/contrib/training/python/training/hparam.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/contrib/training/python/training/hparam.py b/tensorflow/contrib/training/python/training/hparam.py index 9f5059b4b1..372630df81 100644 --- a/tensorflow/contrib/training/python/training/hparam.py +++ b/tensorflow/contrib/training/python/training/hparam.py @@ -521,7 +521,7 @@ class HParams(object): del self._hparam_types[name] def parse(self, values): - """Override hyperparameter values, parsing new values from a string. + """Override existing hyperparameter values, parsing new values from a string. See parse_values for more detail on the allowed format for values. -- GitLab From 95101fc48725b70a596274537b00d961c28bca59 Mon Sep 17 00:00:00 2001 From: Clayne Robison Date: Fri, 5 Oct 2018 16:20:18 -0700 Subject: [PATCH 0004/1765] [Intel MKL] Adding support for Depthwise 2D Convolution (fwd) --- tensorflow/core/graph/mkl_layout_pass.cc | 29 ++++++ tensorflow/core/graph/mkl_layout_pass_test.cc | 23 +++++ .../core/kernels/mkl_conv_grad_filter_ops.cc | 10 +- .../core/kernels/mkl_conv_grad_input_ops.cc | 8 +- tensorflow/core/kernels/mkl_conv_ops.cc | 42 ++++++--- tensorflow/core/kernels/mkl_conv_ops.h | 92 ++++++++++++------- tensorflow/core/ops/nn_ops.cc | 17 +++- tensorflow/core/util/mkl_util.h | 10 ++ 8 files changed, 176 insertions(+), 55 deletions(-) diff --git a/tensorflow/core/graph/mkl_layout_pass.cc b/tensorflow/core/graph/mkl_layout_pass.cc index 7394b1cddf..075aa80498 100644 --- a/tensorflow/core/graph/mkl_layout_pass.cc +++ b/tensorflow/core/graph/mkl_layout_pass.cc @@ -2430,6 +2430,7 @@ class MklLayoutRewritePass : public GraphOptimizationPass { csinfo_.conv3d = "Conv3D"; csinfo_.conv3d_grad_input = "Conv3DBackpropInputV2"; csinfo_.conv3d_grad_filter = "Conv3DBackpropFilterV2"; + csinfo_.depthwise_conv2d = "DepthwiseConv2dNative"; csinfo_.fused_batch_norm = "FusedBatchNorm"; csinfo_.fused_batch_norm_grad = "FusedBatchNormGrad"; csinfo_.identity = "Identity"; @@ -2510,6 +2511,9 @@ class MklLayoutRewritePass : public GraphOptimizationPass { rinfo_.push_back({csinfo_.conv3d_grad_input, mkl_op_registry::GetMklOpName(csinfo_.conv3d_grad_input), CopyAttrsConv, AlwaysRewrite}); + rinfo_.push_back({csinfo_.depthwise_conv2d, + mkl_op_registry::GetMklOpName(csinfo_.depthwise_conv2d), + CopyAttrsConv2DDepthwise, AlwaysRewrite}); rinfo_.push_back({csinfo_.fused_batch_norm, mkl_op_registry::GetMklOpName(csinfo_.fused_batch_norm), CopyAttrsFusedBatchNorm, AlwaysRewrite}); @@ -2659,6 +2663,7 @@ class MklLayoutRewritePass : public GraphOptimizationPass { string conv3d; string conv3d_grad_input; string conv3d_grad_filter; + string depthwise_conv2d; string fused_batch_norm; string fused_batch_norm_grad; string identity; @@ -3134,6 +3139,7 @@ class MklLayoutRewritePass : public GraphOptimizationPass { static void CopyAttrsBiasAddGrad(const Node* orig_node, NodeBuilder* nb); static void CopyAttrsConcat(const Node* orig_node, NodeBuilder* nb); static void CopyAttrsConcatV2(const Node* orig_node, NodeBuilder* nb); + static void CopyAttrsConv2DDepthwise(const Node* orig_node, NodeBuilder* nb); static void CopyAttrsConv(const Node* orig_node, NodeBuilder* nb); static void CopyAttrsDataType(const Node* orig_node, NodeBuilder* nb); static void CopyAttrsFusedBatchNorm(const Node* orig_node, NodeBuilder* nb); @@ -3646,6 +3652,29 @@ void MklLayoutRewritePass::CopyAttrsConv(const Node* orig_node, nb->Attr("data_format", data_format); } +void MklLayoutRewritePass::CopyAttrsConv2DDepthwise(const Node* orig_node, + NodeBuilder* nb) { + DataType T; + string data_format; + string padding; + std::vector strides; + std::vector dilations; + + // Get all attributes from old node. + TF_CHECK_OK(GetNodeAttr(orig_node->def(), "T", &T)); + TF_CHECK_OK(GetNodeAttr(orig_node->def(), "strides", &strides)); + TF_CHECK_OK(GetNodeAttr(orig_node->def(), "dilations", &dilations)); + TF_CHECK_OK(GetNodeAttr(orig_node->def(), "padding", &padding)); + TF_CHECK_OK(GetNodeAttr(orig_node->def(), "data_format", &data_format)); + + // Add attributes to new node. + nb->Attr("T", T); + nb->Attr("strides", strides); + nb->Attr("dilations", dilations); + nb->Attr("padding", padding); + nb->Attr("data_format", data_format); +} + void MklLayoutRewritePass::CopyAttrsAddN(const Node* orig_node, NodeBuilder* nb) { DataType T; diff --git a/tensorflow/core/graph/mkl_layout_pass_test.cc b/tensorflow/core/graph/mkl_layout_pass_test.cc index 77640e287c..c42ee0f9ef 100644 --- a/tensorflow/core/graph/mkl_layout_pass_test.cc +++ b/tensorflow/core/graph/mkl_layout_pass_test.cc @@ -2345,6 +2345,29 @@ TEST_F(MklLayoutPassTest, NodeRewrite_Conv2D_Basic) { "DMT/_1->C:3"); } +// Test case for the Depthwise FWD pass +TEST_F(MklLayoutPassTest, NodeRewrite_DepthwiseConv2dNative_Basic) { + InitGraph( + "node { name: 'A' op: 'Input'}" + "node { name: 'B' op: 'Input'}" + "node { name: 'C' op: 'DepthwiseConv2dNative'" + " attr { key: 'T' value { type: DT_FLOAT } }" + " attr { key: 'data_format' value { s: 'NCHW' } }" + " attr { key: 'use_cudnn_on_gpu' value { b: false } }" + " attr { key: 'strides' value { list: {i: 1, i:1, i:1, i:1} } }" + " attr { key: 'padding' value { s: 'SAME' } }" + " attr { key: 'dilations' value { list: {i: 1, i:1, i:1, i:1} } }" + " input: ['A', 'B']}" + "node { name: 'D' op: 'Zeta' attr { key: 'T' value { type: DT_FLOAT } }" + " input: ['B', 'C'] }"); + EXPECT_EQ(DoMklLayoutOptimizationPass(), + "A(Input);B(Input);C(_MklDepthwiseConv2dNative);D(Zeta);DMT/_0(Const);" + "DMT/_1(Const)|A->C;A:control->DMT/_0:control;" + "A:control->DMT/_1:control;B->C:1;B->D;C->D:1;DMT/_0->C:2;" + "DMT/_1->C:3"); +} + + // 2 Conv2D Ops in sequence. Both should get transformed and 1st Conv2D will // have 2 outputs, both of which will be inputs to next Conv2D. TEST_F(MklLayoutPassTest, NodeRewrite_Conv2D_Positive1) { diff --git a/tensorflow/core/kernels/mkl_conv_grad_filter_ops.cc b/tensorflow/core/kernels/mkl_conv_grad_filter_ops.cc index f406ad2ab5..083d9352ef 100644 --- a/tensorflow/core/kernels/mkl_conv_grad_filter_ops.cc +++ b/tensorflow/core/kernels/mkl_conv_grad_filter_ops.cc @@ -756,7 +756,7 @@ class MklConvCustomBackpropFilterOp MklDnnData diff_filter(&cpu_engine_); // output // This flag indicates Conv2D or Conv3D - bool isConv2D = (this->strides_.size() == 4); + bool is_Conv2D = (this->strides_.size() == 4); // Input tensors const int kInputIdx = 0, kFilterIdx = 1, kOutbpropIdx = 2; @@ -815,10 +815,10 @@ class MklConvCustomBackpropFilterOp conv_utl.GetConvFwdSizesInMklOrder( src_tf_shape, filter_tf_shape, &fwd_src_dims, &fwd_filter_dims, &strides, &dilations, &fwd_dst_dims_tf_order, - &fwd_dst_dims, &padding_left, &padding_right); + &fwd_dst_dims, &padding_left, &padding_right, false); if (!context->status().ok()) return; - auto tf_fmt = isConv2D + auto tf_fmt = is_Conv2D ? TFDataFormatToMklDnnDataFormat(this->data_format_) : TFDataFormatToMklDnn3DDataFormat(this->data_format_); @@ -841,7 +841,7 @@ class MklConvCustomBackpropFilterOp TensorShape obp_tf_shape = GetTfShape(context, 2); depth = (this->data_format_ == FORMAT_NCHW) ? obp_tf_shape.dim_size(1) - : obp_tf_shape.dim_size(isConv2D ? 3 : 4); + : obp_tf_shape.dim_size(is_Conv2D ? 3 : 4); diff_bias_dims = {static_cast(depth)}; } for (int i = 0; i < dilations.size(); i++) dilations[i] -= 1; @@ -866,7 +866,7 @@ class MklConvCustomBackpropFilterOp MklDnnShape diff_filter_mkl_shape; diff_filter_mkl_shape.SetMklTensor(false); - if (isConv2D) { + if (is_Conv2D) { // Conv2D: output_dims_mkl_order is in OIHW format. TensorShape diff_filter_tf_shape({bwd_output_dims[MklDnnDims::Dim_H], bwd_output_dims[MklDnnDims::Dim_W], diff --git a/tensorflow/core/kernels/mkl_conv_grad_input_ops.cc b/tensorflow/core/kernels/mkl_conv_grad_input_ops.cc index a501ce2c93..7ef8d885e7 100644 --- a/tensorflow/core/kernels/mkl_conv_grad_input_ops.cc +++ b/tensorflow/core/kernels/mkl_conv_grad_input_ops.cc @@ -621,7 +621,7 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { MklDnnData diff_dst(&cpu_engine); // This flag indicate Conv2D or Conv3D - bool isConv2D = (this->strides_.size() == 4); + bool is_Conv2D = (this->strides_.size() == 4); // Input tensors const int kInputIdx = 0, kFilterIdx = 1, kOutbpropIdx = 2; @@ -680,13 +680,13 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { conv_utl.GetConvFwdSizesInMklOrder( src_tf_shape, filter_tf_shape, &fwd_src_dims, &fwd_filter_dims, &strides, &dilations, &fwd_output_dims_tf_order, &fwd_output_dims, - &padding_left, &padding_right); + &padding_left, &padding_right, false); if (!context->status().ok()) return; // Create Convolution forward descriptor since Convolution backward // API needs it. For that, we first need to create input, filter // and output memory descriptors. - auto tf_fmt = isConv2D + auto tf_fmt = is_Conv2D ? TFDataFormatToMklDnnDataFormat(this->data_format_) : TFDataFormatToMklDnn3DDataFormat(this->data_format_); @@ -696,7 +696,7 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { auto fwd_filter_md = filter_mkl_shape.IsMklTensor() ? filter_mkl_shape.GetMklLayout() : memory::desc(fwd_filter_dims, MklDnnType(), - isConv2D ? memory::format::hwio + is_Conv2D ? memory::format::hwio : memory::format::dhwio); conv_utl.GetInputSizeInMklOrder(diff_dst_tf_shape, &diff_dst_dims); diff --git a/tensorflow/core/kernels/mkl_conv_ops.cc b/tensorflow/core/kernels/mkl_conv_ops.cc index b332edad0a..be3641d936 100644 --- a/tensorflow/core/kernels/mkl_conv_ops.cc +++ b/tensorflow/core/kernels/mkl_conv_ops.cc @@ -760,7 +760,7 @@ class MklConvOp : public OpKernel { #else // Base class for convolution forward operations -template +template class MklConvOp : public OpKernel { public: ~MklConvOp() {} @@ -846,7 +846,7 @@ class MklConvOp : public OpKernel { conv_utl.GetConvFwdSizesInMklOrder( src_tf_shape, filter_tf_shape, &src_dims, &filter_dims, &strides, &dilations, &dst_dims_tf_order, &dst_dims_mkl_order, - &padding_left, &padding_right); + &padding_left, &padding_right, is_Depthwise); if (!context->status().ok()) return; // Check for corner case - if there is nothing to compute, return. @@ -871,12 +871,19 @@ class MklConvOp : public OpKernel { return; } - bool isConv2D = (strides_.size() == 4); + bool is_Conv2D = (strides_.size() == 4); + + //TODO 3-D support for Depthwise is not there + if (is_Depthwise) { + OP_REQUIRES(context, is_Conv2D, + errors::InvalidArgument( + "Only 2D convolution is supported for depthwise.")); + } // Create memory for user data. // Describe how the inputs and outputs of Convolution look like. Also // specify buffers containing actual input and output data. - auto tf_fmt = isConv2D ? TFDataFormatToMklDnnDataFormat(data_format_) + auto tf_fmt = is_Conv2D ? TFDataFormatToMklDnnDataFormat(data_format_) : TFDataFormatToMklDnn3DDataFormat(data_format_); // If input is in MKL layout, then simply grab input layout; otherwise, @@ -890,12 +897,18 @@ class MklConvOp : public OpKernel { : memory::desc(src_dims, MklDnnType(), tf_fmt); // Although filter shape (filter_dims) required is in MKL-DNN order, - // the layout is Tensorflow's layout (HWIO). - auto filter_md = filter_mkl_shape.IsMklTensor() // Should NEVER be true - ? filter_mkl_shape.GetMklLayout() + // the layout is Tensorflow's layout (HWIO) and (HWIGO)for depthwise/group + // convolutions + + auto filter_format = is_Conv2D ? (is_Depthwise ? memory::format::hwigo + : memory::format::hwio) + : memory::format::dhwio; + + auto filter_md = filter_mkl_shape.IsMklTensor() // Should NEVER be true + ? filter_mkl_shape.GetMklLayout() : memory::desc(filter_dims, MklDnnType(), - isConv2D ? memory::format::hwio - : memory::format::dhwio); + filter_format); + // MKLDNN dilation starts from 0. for (int i = 0; i < dilations.size(); i++) dilations[i] -= 1; @@ -1088,12 +1101,17 @@ class MklConvOp : public OpKernel { .Device(DEVICE_CPU) \ .TypeConstraint("T") \ .Label(mkl_op_registry::kMklOpLabel), \ - MklConvOp); \ + MklConvOp); \ + REGISTER_KERNEL_BUILDER(Name("_MklDepthwiseConv2dNative") \ + .Device(DEVICE_CPU) \ + .TypeConstraint("T") \ + .Label(mkl_op_registry::kMklOpLabel), \ + MklConvOp); \ REGISTER_KERNEL_BUILDER(Name("_MklConv2DWithBias") \ .Device(DEVICE_CPU) \ .TypeConstraint("T") \ .Label(mkl_op_registry::kMklOpLabel), \ - MklConvOp); \ + MklConvOp); \ REGISTER_KERNEL_BUILDER(Name("__MklDummyConv2DWithBias") \ .Device(DEVICE_CPU) \ .TypeConstraint("T") \ @@ -1108,7 +1126,7 @@ TF_CALL_float(REGISTER_MKL_CPU_2D); .Device(DEVICE_CPU) \ .TypeConstraint("T") \ .Label(mkl_op_registry::kMklOpLabel), \ - MklConvOp); + MklConvOp); TF_CALL_float(REGISTER_MKL_CPU_3D); } // namespace tensorflow diff --git a/tensorflow/core/kernels/mkl_conv_ops.h b/tensorflow/core/kernels/mkl_conv_ops.h index 01cc606f41..2be3594fce 100644 --- a/tensorflow/core/kernels/mkl_conv_ops.h +++ b/tensorflow/core/kernels/mkl_conv_ops.h @@ -192,7 +192,8 @@ class MklDnnConvUtil { // TODO(nhasabni): Add similar function for input and filter in MklShape. virtual inline void GetFilterSizeInMklOrder(const TensorShape& input_shape, const TensorShape& filter_shape, - memory::dims* filter_dims) { + memory::dims* filter_dims, + bool is_Depthwise) { CHECK_NOTNULL(filter_dims); OP_REQUIRES(context_, filter_shape.dims() == strides_.size(), @@ -210,6 +211,7 @@ class MklDnnConvUtil { int input_depth = GetTensorDim(input_shape, data_format_, 'C'); + if (strides_.size() == 4) { // Conv2D OP_REQUIRES(context_, input_depth == filter_shape.dim_size(2), errors::InvalidArgument( @@ -221,16 +223,29 @@ class MklDnnConvUtil { int filter_cols = static_cast(filter_shape.dim_size(1)); int in_depth = static_cast(filter_shape.dim_size(2)); int out_depth = static_cast(filter_shape.dim_size(3)); - - // MKL-DNN always needs filter in OIHW format. + // MKL-DNN always needs filter in OIHW format for regular convolutions + // and GOIHW for grouped/depthwise convolutions, // OIHW = (out_depth, in_depth, rows, cols) - std::vector mkldnn_sizes(4, -1); - mkldnn_sizes[MklDnnDims::Dim_O] = out_depth; - mkldnn_sizes[MklDnnDims::Dim_I] = in_depth; - mkldnn_sizes[MklDnnDims::Dim_H] = filter_rows; - mkldnn_sizes[MklDnnDims::Dim_W] = filter_cols; - - *filter_dims = mkldnn_sizes; + // GOIHW = (group, out_depth, in_depth, rows, cols) + // Specifcally for depthwise G=filter_indepth, O=filter_outdepth, I=1 + if (is_Depthwise) { + std::vector mkldnn_sizes(5, -1); + mkldnn_sizes[MklDnnDimsGroup::DimGroup_G] = in_depth; + mkldnn_sizes[MklDnnDimsGroup::DimGroup_O] = out_depth; + mkldnn_sizes[MklDnnDimsGroup::DimGroup_I] = 1; + mkldnn_sizes[MklDnnDimsGroup::DimGroup_H] = filter_rows; + mkldnn_sizes[MklDnnDimsGroup::DimGroup_W] = filter_cols; + + *filter_dims = mkldnn_sizes; + } else { + std::vector mkldnn_sizes(4, -1); + mkldnn_sizes[MklDnnDims::Dim_O] = out_depth; + mkldnn_sizes[MklDnnDims::Dim_I] = in_depth; + mkldnn_sizes[MklDnnDims::Dim_H] = filter_rows; + mkldnn_sizes[MklDnnDims::Dim_W] = filter_cols; + + *filter_dims = mkldnn_sizes; + } } else { // Conv3D OP_REQUIRES(context_, input_depth == filter_shape.dim_size(3), errors::InvalidArgument( @@ -263,10 +278,12 @@ class MklDnnConvUtil { // checks are returned in context's status. virtual inline void GetFilterSizeInMklOrder(size_t src_index, size_t filter_index, - memory::dims* filter_dims) { + memory::dims* filter_dims, + bool is_Depthwise) { CHECK_NOTNULL(filter_dims); GetFilterSizeInMklOrder(GetTfShape(context_, src_index), - GetTfShape(context_, filter_index), filter_dims); + GetTfShape(context_, filter_index), filter_dims, + is_Depthwise); } // Calculate Bias size for 2D or 3D Convolution. Function does not @@ -295,15 +312,15 @@ class MklDnnConvUtil { const TensorShape& input_shape, const TensorShape& filter_shape, const memory::dims& strides, const memory::dims& dilations, memory::dims* output_dims_tf_order, memory::dims* output_dims_mkl_order, - memory::dims* pad_l, memory::dims* pad_r) { + memory::dims* pad_l, memory::dims* pad_r, bool is_Depthwise) { CHECK_NOTNULL(output_dims_tf_order); CHECK_NOTNULL(output_dims_mkl_order); CHECK_NOTNULL(pad_l); CHECK_NOTNULL(pad_r); - bool isConv2D = (strides_.size() == 4); + bool is_Conv2D = (strides_.size() == 4); int input_planes, input_rows, input_cols; - if (isConv2D) { + if (is_Conv2D) { input_rows = GetTensorDim(input_shape, data_format_, 'H'); input_cols = GetTensorDim(input_shape, data_format_, 'W'); } else { @@ -322,7 +339,7 @@ class MklDnnConvUtil { // Third dimension: cols/width. int filter_planes, filter_rows, filter_cols; - if (isConv2D) { + if (is_Conv2D) { filter_rows = filter_shape.dim_size(0); filter_cols = filter_shape.dim_size(1); } else { @@ -333,7 +350,7 @@ class MklDnnConvUtil { int stride_planes, stride_rows, stride_cols; int dilation_planes, dilation_rows, dilation_cols; - if (isConv2D) { + if (is_Conv2D) { // Conv2D stride is a vector of 2 elements: {s_r, s_c} stride_rows = strides[0]; stride_cols = strides[1]; @@ -351,15 +368,23 @@ class MklDnnConvUtil { // Output batch is same as input batch. int out_batch = GetTensorDim(input_shape, data_format_, 'N'); - - // Output depth is same as last dimension for filter. - int out_depth = filter_shape.dim_size(isConv2D ? 3 : 4); + int out_depth; + + // TODO add support for 3-D Depthwise + + // Output depth is same as last dimension for filters for regular + // convolutions. For depthwise it is in_depth*channel_muliplier + if (is_Depthwise) { + out_depth = (filter_shape.dim_size(2)*filter_shape.dim_size(3)); + } else { + out_depth = filter_shape.dim_size(is_Conv2D ? 3 : 4); + } int64 out_rows = 0, out_cols = 0, out_planes = 0; int64 pad_top = 0, pad_bottom = 0, pad_left, pad_right; int64 pad_D1, pad_D2; - if (isConv2D) { + if (is_Conv2D) { OP_REQUIRES_OK(context_, GetWindowedOutputSizeVerboseV2( input_rows, filter_rows, dilation_rows, stride_rows, @@ -385,14 +410,14 @@ class MklDnnConvUtil { // Conv3D: NDHWC or NCDHW // MKL-DNN uses asymetric padding. TensorShape out_shape = - isConv2D + is_Conv2D ? ShapeFromFormat(data_format_, out_batch, out_rows, out_cols, out_depth) : ShapeFromFormat(data_format_, out_batch, {{out_planes, out_rows, out_cols}}, out_depth); *output_dims_tf_order = TFShapeToMklDnnDims(out_shape); - if (isConv2D) { + if (is_Conv2D) { // For Conv2D, MKL-DNN always needs output in NCHW format. std::vector mkldnn_sizes(4, -1); mkldnn_sizes[MklDnnDims::Dim_N] = out_batch; @@ -427,7 +452,7 @@ class MklDnnConvUtil { size_t src_index, size_t filter_index, const memory::dims& strides, const memory::dims& dilations, memory::dims* output_dims_tf_order, memory::dims* output_dims_mkl_order, memory::dims* pad_l, - memory::dims* pad_r) { + memory::dims* pad_r, bool is_Depthwise) { CHECK_NOTNULL(output_dims_tf_order); CHECK_NOTNULL(output_dims_mkl_order); CHECK_NOTNULL(pad_l); @@ -448,9 +473,10 @@ class MklDnnConvUtil { input_tf_shape.DebugString())); } - GetOutputAndPadSizeInMklOrder(input_tf_shape, filter_tf_shape, - strides, dilations, output_dims_tf_order, - output_dims_mkl_order, pad_l, pad_r); + GetOutputAndPadSizeInMklOrder(input_tf_shape, filter_tf_shape, strides, + dilations, output_dims_tf_order, + output_dims_mkl_order, pad_l, pad_r, + is_Depthwise); } // Wrapper function to calculate input, filter, and output sizes of @@ -467,7 +493,7 @@ class MklDnnConvUtil { memory::dims* strides, memory::dims *dilations, memory::dims* output_dims_tf_order, memory::dims* output_dims_mkl_order, memory::dims* pad_l, - memory::dims* pad_r) { + memory::dims* pad_r, bool is_Depthwise) { CHECK_NOTNULL(input_dims); CHECK_NOTNULL(filter_dims); CHECK_NOTNULL(strides); @@ -479,14 +505,14 @@ class MklDnnConvUtil { GetInputSizeInMklOrder(input_shape, input_dims); if (!context_->status().ok()) return; - GetFilterSizeInMklOrder(input_shape, filter_shape, filter_dims); + GetFilterSizeInMklOrder(input_shape, filter_shape, filter_dims, + is_Depthwise); if (!context_->status().ok()) return; GetStridesInMklOrder(strides); GetDilationsInMklOrder(dilations); - GetOutputAndPadSizeInMklOrder(input_shape, filter_shape, - *strides, *dilations, - output_dims_tf_order, output_dims_mkl_order, - pad_l, pad_r); + GetOutputAndPadSizeInMklOrder( + input_shape, filter_shape, *strides, *dilations, output_dims_tf_order, + output_dims_mkl_order, pad_l, pad_r, is_Depthwise); if (!context_->status().ok()) return; } }; diff --git a/tensorflow/core/ops/nn_ops.cc b/tensorflow/core/ops/nn_ops.cc index d1d81b27cc..1691148848 100644 --- a/tensorflow/core/ops/nn_ops.cc +++ b/tensorflow/core/ops/nn_ops.cc @@ -1503,6 +1503,22 @@ REGISTER_OP("QuantizedBatchNormWithGlobalNormalization") }); #ifdef INTEL_MKL +REGISTER_OP("_MklDepthwiseConv2dNative") + .Input("input: T") + .Input("filter: T") + .Input("mkl_input: uint8") + .Input("mkl_filter: uint8") + .Output("output: T") + .Output("filter_output: T") + .Output("mkl_output: uint8") + .Output("mkl_filter_output: uint8") + .Attr("T: {half, bfloat16, float, double}") + .Attr("strides: list(int)") + .Attr(GetPaddingAttrString()) + .Attr(GetConvnetDataFormatAttrString()) + .Attr("dilations: list(int) = [1, 1, 1, 1]") + .SetShapeFn(shape_inference::DepthwiseConv2DNativeShape); + REGISTER_OP("_MklConv2D") .Input("input: T") .Input("filter: T") @@ -2043,7 +2059,6 @@ NOTE Do not invoke this operator directly in Python. Graph rewrite pass is expected to invoke these operators. )doc"); - REGISTER_OP("_MklAvgPool3DGrad") .Input("orig_input_shape: int32") .Input("grad: T") diff --git a/tensorflow/core/util/mkl_util.h b/tensorflow/core/util/mkl_util.h index 04aaea4f89..598532b5bf 100644 --- a/tensorflow/core/util/mkl_util.h +++ b/tensorflow/core/util/mkl_util.h @@ -84,6 +84,7 @@ namespace tensorflow { // Tensorflow tensor. typedef enum { W = 0, H = 1, C = 2, N = 3 } MklDims; + typedef enum { Dim_N = 0, Dim_C = 1, @@ -103,6 +104,15 @@ typedef enum { Dim3d_I = 1 } MklDnnDims3D; +// Filter Dimensions for grouped convolution. +typedef enum { + DimGroup_G = 0, + DimGroup_O = 1, + DimGroup_I = 2, + DimGroup_H = 3, + DimGroup_W = 4 +} MklDnnDimsGroup; + static const int kSmallBatchSize = 32; #ifdef INTEL_MKL_ML_ONLY -- GitLab From bd6c11f878e1820417d1ceff1b02222178f60c16 Mon Sep 17 00:00:00 2001 From: Guozhong Zhuang Date: Fri, 12 Oct 2018 10:10:21 -0700 Subject: [PATCH 0005/1765] Clean out MKL_ML code from batchnorm ops --- .../core/kernels/mkl_fused_batch_norm_op.cc | 658 +----------------- 1 file changed, 2 insertions(+), 656 deletions(-) diff --git a/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc b/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc index 2ec6c8fa89..4b8c066902 100644 --- a/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc +++ b/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc @@ -20,671 +20,19 @@ limitations under the License. #include "tensorflow/core/framework/tensor.h" #include "tensorflow/core/framework/tensor_types.h" #include "tensorflow/core/util/tensor_format.h" - -#ifndef INTEL_MKL_ML_ONLY +#include "tensorflow/core/util/mkl_util.h" #include "mkldnn.hpp" + using mkldnn::batch_normalization_backward; using mkldnn::batch_normalization_forward; using mkldnn::prop_kind; using mkldnn::stream; using mkldnn::use_global_stats; using mkldnn::use_scale_shift; -#else -#include "mkl_dnn.h" -#include "mkl_dnn_types.h" -#endif - -#include "tensorflow/core/util/mkl_util.h" -// TODO(inteltf) Address comments from PR 8968. namespace tensorflow { using CPUDevice = Eigen::ThreadPoolDevice; -#ifdef INTEL_MKL_ML_ONLY - -template -class MklFusedBatchNormOp : public OpKernel { - public: - explicit MklFusedBatchNormOp(OpKernelConstruction* context) - : OpKernel(context) { - float epsilon; - OP_REQUIRES_OK(context, context->GetAttr("epsilon", &epsilon)); - epsilon_ = T(epsilon); - string tensor_format; - OP_REQUIRES_OK(context, context->GetAttr("data_format", &tensor_format)); - OP_REQUIRES(context, FormatFromString(tensor_format, &tensor_format_), - errors::InvalidArgument("Invalid data format")); - OP_REQUIRES_OK(context, context->GetAttr("is_training", &is_training_)); - } - - void Compute(OpKernelContext* context) override { - MklFusedBatchNormOpContext mkl_context; - const Tensor& input = MklGetInput(context, 0); - const Tensor& scale = MklGetInput(context, 1); - const Tensor& shift = MklGetInput(context, 2); - const Tensor& est_mean = MklGetInput(context, 3); - const Tensor& est_variance = MklGetInput(context, 4); - - GetMklShape(context, 0, &(mkl_context.mkl_shape_input_shape)); - bool input_in_mkl_format = mkl_context.mkl_shape_input_shape.IsMklTensor(); - - if (!input_in_mkl_format) { - OP_REQUIRES(context, input.dims() == 4, - errors::InvalidArgument("input must be 4-dimensional", - input.shape().DebugString())); - } - OP_REQUIRES(context, scale.dims() == 1, - errors::InvalidArgument("scale must be 1-dimensional", - scale.shape().DebugString())); - OP_REQUIRES(context, shift.dims() == 1, - errors::InvalidArgument("offset must be 1-dimensional", - shift.shape().DebugString())); - OP_REQUIRES(context, est_mean.dims() == 1, - errors::InvalidArgument("estimated_mean must be 1-dimensional", - est_mean.shape().DebugString())); - - OP_REQUIRES( - context, est_variance.dims() == 1, - errors::InvalidArgument("estimated_variance must be 1-dimensional", - est_variance.shape().DebugString())); - - if (is_training_) { - OP_REQUIRES(context, est_mean.dim_size(0) == 0, - errors::InvalidArgument("estimated_mean empty for training", - est_mean.shape().DebugString())); - OP_REQUIRES(context, est_variance.dim_size(0) == 0, - errors::InvalidArgument( - "estimated_variance must be empty for training", - est_variance.shape().DebugString())); - } - - unsigned int flag_batch_norm = - is_training_ ? dnnUseScaleShift - : (dnnUseInputMeanVariance | dnnUseScaleShift); - - mkl_context.MklExtractParams(context, tensor_format_); - - // Create layout only for input data as it is used in Op primitive. - mkl_context.MklCreateInputLayout(context); - - // Create Op primitive. - CHECK_EQ(dnnBatchNormalizationCreateForward_v2_F32( - &(mkl_context.mkl_prim_batchnorm), nullptr, - mkl_context.mkl_lt_input, static_cast(epsilon_), - flag_batch_norm), - E_SUCCESS); - - // Temporary tensors with buffers for the context inputs, if - // conversion to MKL-Op specific layouts are required. It is assumed here - // that TF's 1D tensors (scale, shift, est_mean, and est_variance) won't - // require any conversion. - // Since scale-shift is combined in MKL, a buffer is required. - Tensor mkl_tmp_input_buf_tensor, mkl_tmp_scale_shift_buf_tensor; - mkl_context.MklPrepareContextInputs(context, &mkl_tmp_input_buf_tensor, - &mkl_tmp_scale_shift_buf_tensor); - - // Output data in MKL layout - Tensor* output = nullptr; - TensorShape tf_shape_output; - MklShape mkl_shape_output; - mkl_shape_output.SetMklTensor(true); - mkl_shape_output.SetMklLayout(mkl_context.mkl_prim_batchnorm, - dnnResourceDst); - mkl_shape_output.SetTfLayout(mkl_context.mkl_params.in_dim, - mkl_context.mkl_params.in_sizes, - mkl_context.mkl_params.in_strides); - mkl_shape_output.SetTfDimOrder(mkl_context.mkl_params.in_dim, - tensor_format_); - tf_shape_output.AddDim(dnnLayoutGetMemorySize_F32(static_cast( - mkl_shape_output.GetMklLayout())) / - sizeof(T)); - AllocateOutputSetMklShape(context, 0, &output, tf_shape_output, - mkl_shape_output); - mkl_context.mkl_res_batchnorm[dnnResourceDst] = - static_cast(output->flat().data()); - - // Batch mean in TF layout - Tensor* batch_mean = nullptr; - MklShape mkl_shape_batch_mean; - mkl_shape_batch_mean.SetMklTensor(false); - AllocateOutputSetMklShape(context, 1, &batch_mean, scale.shape(), - mkl_shape_batch_mean); - // Batch variance in TF layout - Tensor* batch_variance = nullptr; - MklShape mkl_shape_batch_variance; - mkl_shape_batch_variance.SetMklTensor(false); - AllocateOutputSetMklShape(context, 2, &batch_variance, scale.shape(), - mkl_shape_batch_variance); - // If training mode, set dnnResourceMean and dnnResourceVariance to - // output tensors for batch mean and variance. - // Otherwise, set dnnResourceMean and dnnResourceVariance to - // estimated mean and variance. - if (is_training_) - mkl_context.MklSetMeanVariance(*batch_mean, *batch_variance); - else - mkl_context.MklSetMeanVariance(est_mean, est_variance); - - // Now that all resources are set, it is ready for dnnExecute - CHECK_EQ(dnnExecute_F32(mkl_context.mkl_prim_batchnorm, - mkl_context.mkl_res_batchnorm), - E_SUCCESS); - - // Mean and variance (without Bessel's correction) saved for backward - // computation to serve as pre-computed mean and variance. - Tensor* saved_mean = nullptr; - MklShape mkl_shape_saved_mean; - mkl_shape_saved_mean.SetMklTensor(false); - AllocateOutputSetMklShape(context, 3, &saved_mean, scale.shape(), - mkl_shape_saved_mean); - std::memcpy( - reinterpret_cast(saved_mean->flat().data()), - reinterpret_cast(mkl_context.mkl_res_batchnorm[dnnResourceMean]), - scale.NumElements() * sizeof(float)); - Tensor* saved_variance = nullptr; - MklShape mkl_shape_saved_variance; - mkl_shape_saved_variance.SetMklTensor(false); - AllocateOutputSetMklShape(context, 4, &saved_variance, scale.shape(), - mkl_shape_saved_variance); - std::memcpy(reinterpret_cast(saved_variance->flat().data()), - reinterpret_cast( - mkl_context.mkl_res_batchnorm[dnnResourceVariance]), - scale.NumElements() * sizeof(float)); - - // Bessel's correction on variance, if training mode is on - if (is_training_) { - float* p_var = static_cast(batch_variance->flat().data()); - auto depth = mkl_context.mkl_params.depth; - size_t orig_size = mkl_context.mkl_params.in_sizes[0] * - mkl_context.mkl_params.in_sizes[1] * - mkl_context.mkl_params.in_sizes[3]; - size_t adjust_size = orig_size - 1; - float adjust_factor = (static_cast(orig_size)) / adjust_size; - for (int i = 0; i < depth; i++) p_var[i] = adjust_factor * p_var[i]; - } - - mkl_context.MklCleanup(); - } - - private: - T epsilon_; - TensorFormat tensor_format_; - bool is_training_; - - // Structure containing all info for MklOp - typedef struct { - // Parameters used for input and output layouts - struct MklBatchNormParams { - // BatchNormOp src and - size_t in_dim; - size_t in_sizes[4]; - size_t in_strides[4]; - size_t depth; // Batch normalization is done for per channel. - } mkl_params; - - MklShape mkl_shape_input_shape; - - // MKL primitive and resources for BatchNormOp - dnnPrimitive_t mkl_prim_batchnorm = nullptr; - void* mkl_res_batchnorm[dnnResourceNumber]; - - // MKL layouts for inputs in the context - dnnLayout_t mkl_lt_input = nullptr; - - void MklCleanup() { - bool input_in_mkl_format = mkl_shape_input_shape.IsMklTensor(); - if (!input_in_mkl_format) dnnLayoutDelete_F32(mkl_lt_input); - if (mkl_prim_batchnorm != nullptr) dnnDelete_F32(mkl_prim_batchnorm); - } - - void MklExtractParams(OpKernelContext* context, - const TensorFormat& tensor_format) { - const Tensor& input = MklGetInput(context, 0); - bool input_in_mkl_format = mkl_shape_input_shape.IsMklTensor(); - mkl_params.in_dim = input_in_mkl_format - ? mkl_shape_input_shape.GetDimension() - : input.dims(); - mkl_params.in_sizes[0] = static_cast( - input_in_mkl_format ? mkl_shape_input_shape.GetSizes()[0] - : GetTensorDim(input, tensor_format, 'W')); - mkl_params.in_sizes[1] = static_cast( - input_in_mkl_format ? mkl_shape_input_shape.GetSizes()[1] - : GetTensorDim(input, tensor_format, 'H')); - mkl_params.in_sizes[2] = static_cast( - input_in_mkl_format ? mkl_shape_input_shape.GetSizes()[2] - : GetTensorDim(input, tensor_format, 'C')); - mkl_params.in_sizes[3] = static_cast( - input_in_mkl_format ? mkl_shape_input_shape.GetSizes()[3] - : GetTensorDim(input, tensor_format, 'N')); - mkl_params.depth = mkl_params.in_sizes[2]; - GetStridesFromSizes(tensor_format, mkl_params.in_strides, - mkl_params.in_sizes); - } - - void MklCreateInputLayout(OpKernelContext* context) { - const Tensor& input = MklGetInput(context, 0); - bool input_in_mkl_format = mkl_shape_input_shape.IsMklTensor(); - if (input_in_mkl_format) { - mkl_lt_input = - static_cast(mkl_shape_input_shape.GetCurLayout()); - } else { - CHECK_EQ( - dnnLayoutCreate_F32(&mkl_lt_input, mkl_params.in_dim, - mkl_params.in_sizes, mkl_params.in_strides), - E_SUCCESS); - } - } - void MklPrepareContextInputs(OpKernelContext* context, - Tensor* mkl_tmp_input_buf_tensor, - Tensor* mkl_tmp_scale_shift_buf_tensor) { - bool mkl_convert_input; - dnnPrimitive_t mkl_prim_convert_input = nullptr; - dnnLayout_t mkl_lt_internal_input = nullptr; - void* mkl_buf_converted_input = nullptr; - // Compare with internal layouts and convert if needed - const Tensor& input = MklGetInput(context, 0); - void* mkl_buf_input = - const_cast(static_cast(input.flat().data())); - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32( - &mkl_lt_internal_input, mkl_prim_batchnorm, dnnResourceSrc), - E_SUCCESS); - mkl_convert_input = - !dnnLayoutCompare_F32(mkl_lt_internal_input, mkl_lt_input); - if (mkl_convert_input) { - CHECK_EQ(dnnConversionCreate_F32(&mkl_prim_convert_input, mkl_lt_input, - mkl_lt_internal_input), - E_SUCCESS); - AllocTmpBuffer(context, mkl_tmp_input_buf_tensor, mkl_lt_internal_input, - &mkl_buf_converted_input); - CHECK_EQ(dnnConversionExecute_F32(mkl_prim_convert_input, mkl_buf_input, - mkl_buf_converted_input), - E_SUCCESS); - dnnDelete_F32(mkl_prim_convert_input); - } - dnnLayoutDelete_F32(mkl_lt_internal_input); - mkl_res_batchnorm[dnnResourceSrc] = - (mkl_convert_input) ? mkl_buf_converted_input : mkl_buf_input; - - // scale-shift layout is created from primitive. So no conversion - // is needed, however, a buffer has to be allocated. - dnnLayout_t mkl_lt_scale_shift = nullptr; - void* mkl_buf_scale_shift = nullptr; - CHECK_EQ( - dnnLayoutCreateFromPrimitive_F32( - &mkl_lt_scale_shift, mkl_prim_batchnorm, dnnResourceScaleShift), - E_SUCCESS); - AllocTmpBuffer(context, mkl_tmp_scale_shift_buf_tensor, - mkl_lt_scale_shift, &mkl_buf_scale_shift); - // Fill the scale-shift buffer with data, presumably buffer is 2D array - const Tensor& scale = MklGetInput(context, 1); - const Tensor& shift = MklGetInput(context, 2); - float* buf_scale_shift = static_cast(mkl_buf_scale_shift); - float* buf_scale = const_cast( - static_cast(scale.flat().data())); - float* buf_shift = const_cast( - static_cast(shift.flat().data())); - auto depth = mkl_params.depth; - for (int i = 0; i < depth; i++) { - buf_scale_shift[i] = buf_scale[i]; - buf_scale_shift[i + depth] = buf_shift[i]; - } - mkl_res_batchnorm[dnnResourceScaleShift] = mkl_buf_scale_shift; - } - - inline void MklSetMeanVariance(const Tensor& mean, const Tensor& variance) { - mkl_res_batchnorm[dnnResourceMean] = const_cast( - static_cast(mean.flat().data())); - mkl_res_batchnorm[dnnResourceVariance] = const_cast( - static_cast(variance.flat().data())); - } - } MklFusedBatchNormOpContext; -}; - -template -class MklFusedBatchNormGradOp : public OpKernel { - public: - explicit MklFusedBatchNormGradOp(OpKernelConstruction* context) - : OpKernel(context) { - float epsilon; - OP_REQUIRES_OK(context, context->GetAttr("epsilon", &epsilon)); - epsilon_ = T(epsilon); - string tensor_format; - OP_REQUIRES_OK(context, context->GetAttr("data_format", &tensor_format)); - OP_REQUIRES(context, FormatFromString(tensor_format, &tensor_format_), - errors::InvalidArgument("Invalid data format")); - } - - void Compute(OpKernelContext* context) override { - MklFusedBatchNormGradOpContext mkl_context; - - const Tensor& out_backprop = MklGetInput(context, 0); - const Tensor& input = MklGetInput(context, 1); - const Tensor& scale = MklGetInput(context, 2); - const Tensor& saved_mean = MklGetInput(context, 3); - const Tensor& saved_var = MklGetInput(context, 4); - - // Here scale, mean, and variance are 1D and considered - // those having same layout in MKL and TF - GetMklShape(context, 0, &(mkl_context.mkl_shape_out_backprop)); - GetMklShape(context, 1, &(mkl_context.mkl_shape_input_shape)); - - bool input_in_mkl_format = mkl_context.mkl_shape_input_shape.IsMklTensor(); - bool out_backprop_in_mkl_format = - mkl_context.mkl_shape_out_backprop.IsMklTensor(); - if (!out_backprop_in_mkl_format) { - OP_REQUIRES(context, out_backprop.dims() == 4, - errors::InvalidArgument("input must be 4-dimensional", - out_backprop.shape().DebugString())); - } - if (!input_in_mkl_format) { - OP_REQUIRES(context, input.dims() == 4, - errors::InvalidArgument("input must be 4-dimensional", - input.shape().DebugString())); - } - OP_REQUIRES(context, scale.dims() == 1, - errors::InvalidArgument("scale must be 1-dimensional", - scale.shape().DebugString())); - OP_REQUIRES(context, saved_mean.dims() == 1, - errors::InvalidArgument("saved mean must be 1-dimensional", - saved_mean.shape().DebugString())); - OP_REQUIRES(context, saved_var.dims() == 1, - errors::InvalidArgument("saved variance must be 1-dimensional", - saved_var.shape().DebugString())); - - mkl_context.MklExtractParams(context, tensor_format_); - - mkl_context.MklCreateInputLayout(context); - - unsigned int flag_batch_norm_grad = dnnUseScaleShift; - - // Create Backward Op primitive. - CHECK_EQ(dnnBatchNormalizationCreateBackward_v2_F32( - &(mkl_context.mkl_prim_batchnorm_bwd), nullptr, - mkl_context.mkl_lt_input, static_cast(epsilon_), - flag_batch_norm_grad), - E_SUCCESS); - - // Temporary tensors and their buffers if conversion is required - Tensor mkl_tmp_input_buf_tensor, mkl_tmp_outbackprop_buf_tensor, - mkl_tmp_scaleshift_buf_tensor; - mkl_context.MklPrepareContextInputs(context, &mkl_tmp_input_buf_tensor, - &mkl_tmp_outbackprop_buf_tensor, - &mkl_tmp_scaleshift_buf_tensor); - - // Allocate tensor for grad w.r.t. input(x) - Tensor* in_backprop = nullptr; - TensorShape tf_shape_in_backprop; - MklShape mkl_shape_in_backprop; - mkl_shape_in_backprop.SetMklTensor(true); - mkl_shape_in_backprop.SetMklLayout(mkl_context.mkl_prim_batchnorm_bwd, - dnnResourceDiffSrc); - mkl_shape_in_backprop.SetTfLayout(mkl_context.mkl_params.in_dims, - mkl_context.mkl_params.in_sizes, - mkl_context.mkl_params.in_strides); - mkl_shape_in_backprop.SetTfDimOrder(mkl_context.mkl_params.in_dims, - tensor_format_); - tf_shape_in_backprop.AddDim( - dnnLayoutGetMemorySize_F32( - static_cast(mkl_shape_in_backprop.GetMklLayout())) / - sizeof(T)); - AllocateOutputSetMklShape(context, 0, &in_backprop, tf_shape_in_backprop, - mkl_shape_in_backprop); - mkl_context.mkl_res_batchnorm_bwd[dnnResourceDiffSrc] = - static_cast(in_backprop->flat().data()); - - // grad_scale and grad_shift are combined together in MKL - // So create a single temporary buffer for those. - // Also set dnnResourceDiffScaleShift to the temporary buffer - Tensor mkl_tmp_grad_scale_shift_buf_tensor; - mkl_context.MklPrepareGradScaleShift(context, - &mkl_tmp_grad_scale_shift_buf_tensor); - - // All dnn resources are set now, ready to execute - CHECK_EQ(dnnExecute_F32(mkl_context.mkl_prim_batchnorm_bwd, - mkl_context.mkl_res_batchnorm_bwd), - E_SUCCESS); - - // Now separate out scale and shift grad and copy to individual tensors - const TensorShape& tf_shape_scale_shift = scale.shape(); - // Allocate tensor for grad w.r.t. scale (beta) - Tensor* scale_backprop = nullptr; - MklShape mkl_shape_scale_backprop; - AllocateOutputSetMklShape(context, 1, &scale_backprop, tf_shape_scale_shift, - mkl_shape_scale_backprop); - - // Allocate tensor for grad w.r.t. shift(gamma) - Tensor* shift_backprop = nullptr; - MklShape mkl_shape_shift_backprop; - AllocateOutputSetMklShape(context, 2, &shift_backprop, tf_shape_scale_shift, - mkl_shape_shift_backprop); - - // copy scale and shift grads to tensors - float* mkl_buf_scale_shift = const_cast(static_cast( - mkl_tmp_grad_scale_shift_buf_tensor.flat().data())); - float* tf_buf_scale = const_cast( - static_cast(scale_backprop->flat().data())); - float* tf_buf_shift = const_cast( - static_cast(shift_backprop->flat().data())); - auto depth = mkl_context.mkl_params.depth; - for (int i = 0; i < depth; i++) { - tf_buf_scale[i] = mkl_buf_scale_shift[i]; - tf_buf_shift[i] = mkl_buf_scale_shift[i + depth]; - } - - // Two placeholders for estimated_mean and estimated_variance, which are - // used for inference and thus not needed here for gradient computation. - Tensor* placeholder_1 = nullptr; - MklShape mkl_shape_placeholder_1; - AllocateOutputSetMklShape(context, 3, &placeholder_1, TensorShape({}), - mkl_shape_placeholder_1); - Tensor* placeholder_2 = nullptr; - MklShape mkl_shape_placeholder_2; - AllocateOutputSetMklShape(context, 4, &placeholder_2, TensorShape({}), - mkl_shape_placeholder_2); - - mkl_context.MklCleanup(); - } - - private: - T epsilon_; - TensorFormat tensor_format_; - - // Structure containing all info for MklOp - typedef struct { - // Parameters used for input and output layouts - struct MklBatchNormParams { - // BatchNormOp src and - size_t in_dims; - size_t in_sizes[4]; - size_t in_strides[4]; - size_t depth; // Batch normalization is done for per channel. - } mkl_params; - - MklShape mkl_shape_out_backprop; - MklShape mkl_shape_input_shape; - - // MKL primitive and resources for BatchNormOp - dnnPrimitive_t mkl_prim_batchnorm_bwd = nullptr; - void* mkl_res_batchnorm_bwd[dnnResourceNumber]; - - // MKL layouts for inputs in the context - dnnLayout_t mkl_lt_out_backprop = nullptr; - dnnLayout_t mkl_lt_input = nullptr; - - void MklCleanup() { - bool input_in_mkl_format = mkl_shape_input_shape.IsMklTensor(); - bool out_backprop_in_mkl_format = mkl_shape_out_backprop.IsMklTensor(); - if (!input_in_mkl_format) dnnLayoutDelete_F32(mkl_lt_input); - if (!out_backprop_in_mkl_format) dnnLayoutDelete_F32(mkl_lt_out_backprop); - - dnnDelete_F32(mkl_prim_batchnorm_bwd); - } - - void MklExtractParams(OpKernelContext* context, - const TensorFormat& tensor_format) { - const Tensor& input = MklGetInput(context, 1); - bool input_in_mkl_format = mkl_shape_input_shape.IsMklTensor(); - mkl_params.in_dims = input_in_mkl_format - ? mkl_shape_input_shape.GetDimension() - : input.dims(); - mkl_params.in_sizes[0] = static_cast( - input_in_mkl_format ? mkl_shape_input_shape.GetSizes()[0] - : GetTensorDim(input, tensor_format, 'W')); - mkl_params.in_sizes[1] = static_cast( - input_in_mkl_format ? mkl_shape_input_shape.GetSizes()[1] - : GetTensorDim(input, tensor_format, 'H')); - mkl_params.in_sizes[2] = static_cast( - input_in_mkl_format ? mkl_shape_input_shape.GetSizes()[2] - : GetTensorDim(input, tensor_format, 'C')); - mkl_params.in_sizes[3] = static_cast( - input_in_mkl_format ? mkl_shape_input_shape.GetSizes()[3] - : GetTensorDim(input, tensor_format, 'N')); - mkl_params.depth = mkl_params.in_sizes[2]; - GetStridesFromSizes(tensor_format, mkl_params.in_strides, - mkl_params.in_sizes); - } - - void MklCreateInputLayout(OpKernelContext* context) { - const Tensor& input = MklGetInput(context, 0); - bool input_in_mkl_format = mkl_shape_input_shape.IsMklTensor(); - if (input_in_mkl_format) { - mkl_lt_input = - static_cast(mkl_shape_input_shape.GetCurLayout()); - } else { - CHECK_EQ( - dnnLayoutCreate_F32(&mkl_lt_input, mkl_params.in_dims, - mkl_params.in_sizes, mkl_params.in_strides), - E_SUCCESS); - } - - bool out_backprop_in_mkl_format = mkl_shape_out_backprop.IsMklTensor(); - if (out_backprop_in_mkl_format) { - mkl_lt_out_backprop = - static_cast(mkl_shape_out_backprop.GetCurLayout()); - } else { - CHECK_EQ( - dnnLayoutCreate_F32(&mkl_lt_out_backprop, mkl_params.in_dims, - mkl_params.in_sizes, mkl_params.in_strides), - E_SUCCESS); - } - } - - void MklPrepareContextInputs(OpKernelContext* context, - Tensor* mkl_tmp_input_buf_tensor, - Tensor* mkl_tmp_outbackprop_buf_tensor, - Tensor* mkl_tmp_scaleshift_buf_tensor) { - bool mkl_convert_input; - dnnPrimitive_t mkl_prim_convert_input = nullptr; - dnnLayout_t mkl_lt_internal_input = nullptr; - void* mkl_buf_converted_input = nullptr; - // Compare with internal layouts and convert if needed - const Tensor& input = MklGetInput(context, 1); - void* mkl_buf_input = - const_cast(static_cast(input.flat().data())); - CHECK_EQ( - dnnLayoutCreateFromPrimitive_F32( - &mkl_lt_internal_input, mkl_prim_batchnorm_bwd, dnnResourceSrc), - E_SUCCESS); - mkl_convert_input = - !dnnLayoutCompare_F32(mkl_lt_internal_input, mkl_lt_input); - if (mkl_convert_input) { - CHECK_EQ(dnnConversionCreate_F32(&mkl_prim_convert_input, mkl_lt_input, - mkl_lt_internal_input), - E_SUCCESS); - AllocTmpBuffer(context, mkl_tmp_input_buf_tensor, mkl_lt_internal_input, - &mkl_buf_converted_input); - CHECK_EQ(dnnConversionExecute_F32(mkl_prim_convert_input, mkl_buf_input, - mkl_buf_converted_input), - E_SUCCESS); - dnnDelete_F32(mkl_prim_convert_input); - } - dnnLayoutDelete_F32(mkl_lt_internal_input); - mkl_res_batchnorm_bwd[dnnResourceSrc] = - (mkl_convert_input) ? mkl_buf_converted_input : mkl_buf_input; - - bool mkl_convert_out_backprop; - dnnPrimitive_t mkl_prim_convert_out_backprop = nullptr; - dnnLayout_t mkl_lt_internal_out_backprop = nullptr; - void* mkl_buf_converted_out_backprop = nullptr; - // Compare with internal layouts and convert if needed - const Tensor& out_backprop = MklGetInput(context, 0); - void* mkl_buf_out_backprop = const_cast( - static_cast(out_backprop.flat().data())); - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32(&mkl_lt_internal_out_backprop, - mkl_prim_batchnorm_bwd, - dnnResourceDiffDst), - E_SUCCESS); - mkl_convert_out_backprop = !dnnLayoutCompare_F32( - mkl_lt_internal_out_backprop, mkl_lt_out_backprop); - if (mkl_convert_out_backprop) { - CHECK_EQ(dnnConversionCreate_F32(&mkl_prim_convert_out_backprop, - mkl_lt_out_backprop, - mkl_lt_internal_out_backprop), - E_SUCCESS); - AllocTmpBuffer(context, mkl_tmp_outbackprop_buf_tensor, - mkl_lt_internal_out_backprop, - &mkl_buf_converted_out_backprop); - CHECK_EQ(dnnConversionExecute_F32(mkl_prim_convert_out_backprop, - mkl_buf_out_backprop, - mkl_buf_converted_out_backprop), - E_SUCCESS); - dnnDelete_F32(mkl_prim_convert_out_backprop); - } - dnnLayoutDelete_F32(mkl_lt_internal_out_backprop); - mkl_res_batchnorm_bwd[dnnResourceDiffDst] = - (mkl_convert_out_backprop) ? mkl_buf_converted_out_backprop - : mkl_buf_out_backprop; - - // Set dnnResourceMean and dnnResourceVariance - const Tensor& saved_mean = MklGetInput(context, 3); - const Tensor& saved_var = MklGetInput(context, 4); - void* mkl_buf_saved_mean = const_cast( - static_cast(saved_mean.flat().data())); - void* mkl_buf_saved_var = const_cast( - static_cast(saved_var.flat().data())); - mkl_res_batchnorm_bwd[dnnResourceMean] = mkl_buf_saved_mean; - mkl_res_batchnorm_bwd[dnnResourceVariance] = mkl_buf_saved_var; - - // Set dnnResourceScaleShift - // Note backward Op needs only current values of scale parameters, - // shift parameters could be garbage and won't be used - const Tensor& scale = MklGetInput(context, 2); - dnnLayout_t mkl_lt_scale_shift = nullptr; - void* mkl_buf_scale_shift = nullptr; - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32(&mkl_lt_scale_shift, - mkl_prim_batchnorm_bwd, - dnnResourceScaleShift), - E_SUCCESS); - AllocTmpBuffer(context, mkl_tmp_scaleshift_buf_tensor, mkl_lt_scale_shift, - &mkl_buf_scale_shift); - float* pscale = - const_cast(static_cast(scale.flat().data())); - float* pscale_shift = static_cast(mkl_buf_scale_shift); - auto depth = mkl_params.depth; - for (int i = 0; i < depth; i++) pscale_shift[i] = pscale[i]; - mkl_res_batchnorm_bwd[dnnResourceScaleShift] = mkl_buf_scale_shift; - dnnLayoutDelete_F32(mkl_lt_scale_shift); - } - - void MklPrepareGradScaleShift(OpKernelContext* context, - Tensor* mkl_tmp_grad_scale_shift_buf_tensor) { - dnnLayout_t mkl_lt_grad_scaleshift = nullptr; - void* mkl_buf_grad_scaleshift = nullptr; - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32(&mkl_lt_grad_scaleshift, - mkl_prim_batchnorm_bwd, - dnnResourceDiffScaleShift), - E_SUCCESS); - AllocTmpBuffer(context, mkl_tmp_grad_scale_shift_buf_tensor, - mkl_lt_grad_scaleshift, &mkl_buf_grad_scaleshift); - mkl_res_batchnorm_bwd[dnnResourceDiffScaleShift] = - mkl_buf_grad_scaleshift; - dnnLayoutDelete_F32(mkl_lt_grad_scaleshift); - } - } MklFusedBatchNormGradOpContext; -}; -#endif - -#ifndef INTEL_MKL_ML_ONLY - struct MklBatchNormFwdParams { memory::dims src_dims; int depth; @@ -1765,8 +1113,6 @@ class MklFusedBatchNormGradOp : public OpKernel { memory::dims GetMeanVarianceDims() { return memory::dims({1, depth_}); } }; -#endif - #define REGISTER_MKL_CPU(T) \ REGISTER_KERNEL_BUILDER(Name("_MklFusedBatchNorm") \ .Device(DEVICE_CPU) \ -- GitLab From cb9dccae23f34edb15cdbe58ad6fceab702138fb Mon Sep 17 00:00:00 2001 From: Guozhong Zhuang Date: Fri, 12 Oct 2018 10:41:32 -0700 Subject: [PATCH 0006/1765] adjust headers inclusion order per review suggestion of another PR --- tensorflow/core/kernels/mkl_fused_batch_norm_op.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc b/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc index 4b8c066902..ff46e75a36 100644 --- a/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc +++ b/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc @@ -19,8 +19,8 @@ limitations under the License. #include "tensorflow/core/framework/register_types.h" #include "tensorflow/core/framework/tensor.h" #include "tensorflow/core/framework/tensor_types.h" -#include "tensorflow/core/util/tensor_format.h" #include "tensorflow/core/util/mkl_util.h" +#include "tensorflow/core/util/tensor_format.h" #include "mkldnn.hpp" using mkldnn::batch_normalization_backward; -- GitLab From bae74d26f93872374b48c60a73d189df148a6f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yan=20Facai=20=28=E9=A2=9C=E5=8F=91=E6=89=8D=29?= Date: Tue, 16 Oct 2018 09:45:45 +0800 Subject: [PATCH 0007/1765] CLN: remove reshape in conv3d, becasue bias_add has supported 5-dim --- .../python/keras/layers/convolutional.py | 33 ++----------------- .../python/keras/layers/convolutional_test.py | 16 +++++++++ 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/tensorflow/python/keras/layers/convolutional.py b/tensorflow/python/keras/layers/convolutional.py index 58024677ee..f8afa0d430 100644 --- a/tensorflow/python/keras/layers/convolutional.py +++ b/tensorflow/python/keras/layers/convolutional.py @@ -199,21 +199,8 @@ class Conv(Layer): # nn.bias_add does not accept a 1D input tensor. bias = array_ops.reshape(self.bias, (1, self.filters, 1)) outputs += bias - if self.rank == 2: + else: outputs = nn.bias_add(outputs, self.bias, data_format='NCHW') - if self.rank == 3: - # As of Mar 2017, direct addition is significantly slower than - # bias_add when computing gradients. To use bias_add, we collapse Z - # and Y into a single dimension to obtain a 4D input tensor. - outputs_shape = outputs.shape.as_list() - if outputs_shape[0] is None: - outputs_shape[0] = -1 - outputs_4d = array_ops.reshape(outputs, - [outputs_shape[0], outputs_shape[1], - outputs_shape[2] * outputs_shape[3], - outputs_shape[4]]) - outputs_4d = nn.bias_add(outputs_4d, self.bias, data_format='NCHW') - outputs = array_ops.reshape(outputs_4d, outputs_shape) else: outputs = nn.bias_add(outputs, self.bias, data_format='NHWC') @@ -1127,24 +1114,10 @@ class Conv3DTranspose(Conv3D): outputs.set_shape(out_shape) if self.use_bias: - outputs_shape = outputs.shape.as_list() - if outputs_shape[0] is None: - outputs_shape[0] = -1 - if self.data_format == 'channels_first': - outputs_4d = array_ops.reshape(outputs, [ - outputs_shape[0], outputs_shape[1], - outputs_shape[2] * outputs_shape[3], outputs_shape[4] - ]) - else: - outputs_4d = array_ops.reshape(outputs, [ - outputs_shape[0], outputs_shape[1] * outputs_shape[2], - outputs_shape[3], outputs_shape[4] - ]) - outputs_4d = nn.bias_add( - outputs_4d, + outputs = nn.bias_add( + outputs, self.bias, data_format=conv_utils.convert_data_format(self.data_format, ndim=4)) - outputs = array_ops.reshape(outputs_4d, outputs_shape) if self.activation is not None: return self.activation(outputs) diff --git a/tensorflow/python/keras/layers/convolutional_test.py b/tensorflow/python/keras/layers/convolutional_test.py index 4afddbc8cc..63fb60ebaf 100644 --- a/tensorflow/python/keras/layers/convolutional_test.py +++ b/tensorflow/python/keras/layers/convolutional_test.py @@ -336,6 +336,14 @@ class Conv3DTransposeTest(test.TestCase): self.assertEqual(layer.kernel.constraint, k_constraint) self.assertEqual(layer.bias.constraint, b_constraint) + def test_conv3dtranspose_dynamic_shape(self): + with self.session(use_gpu=True): + # Won't raise error here. + layer = keras.layers.Conv3DTranspose(3, 3, data_format='channels_last') + layer.build((None, None, None, None, 1)) + layer1 = keras.layers.Conv3DTranspose(3, 3, data_format='channels_first') + layer1.build((None, 1, None, None, None)) + class SeparableConv1DTest(test.TestCase): @@ -557,6 +565,14 @@ class Conv3DTest(test.TestCase): self.assertEqual(layer.kernel.constraint, k_constraint) self.assertEqual(layer.bias.constraint, b_constraint) + def test_conv3d_dynamic_shape(self): + with self.session(use_gpu=True): + # Won't raise error here. + layer = keras.layers.Conv3D(3, 3, data_format='channels_last') + layer.build((None, None, None, None, 1)) + layer1 = keras.layers.Conv3D(3, 3, data_format='channels_first') + layer1.build((None, 1, None, None, None)) + class ZeroPaddingTest(test.TestCase): -- GitLab From 02e52ca65a91f12b9f352ffa1d0ed86a1c6dd276 Mon Sep 17 00:00:00 2001 From: Palmer Lao Date: Thu, 18 Oct 2018 16:42:15 -0700 Subject: [PATCH 0008/1765] Make shared S3 lib linkable --- tensorflow/core/platform/s3/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/core/platform/s3/BUILD b/tensorflow/core/platform/s3/BUILD index 41184b6fd9..7bc4d80db5 100644 --- a/tensorflow/core/platform/s3/BUILD +++ b/tensorflow/core/platform/s3/BUILD @@ -14,7 +14,7 @@ load( ) tf_cc_binary( - name = "s3_file_system.so", + name = "libs3_file_system_shared.so", srcs = [ "aws_crypto.cc", "aws_crypto.h", -- GitLab From 4182fe444d0eed807403482a165c1b547d1c25ce Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Fri, 19 Oct 2018 03:16:59 +0000 Subject: [PATCH 0009/1765] Add uint8 support for Pad with GPU This fix tries to address some of the issue raised in 17823 where Pad with GPU does not support uint8. This fix adds the uint8 support. Signed-off-by: Yong Tang --- tensorflow/core/kernels/pad_op.cc | 2 ++ tensorflow/core/kernels/pad_op_gpu.cu.cc | 1 + 2 files changed, 3 insertions(+) diff --git a/tensorflow/core/kernels/pad_op.cc b/tensorflow/core/kernels/pad_op.cc index 3b9133ed7e..691430ebaf 100644 --- a/tensorflow/core/kernels/pad_op.cc +++ b/tensorflow/core/kernels/pad_op.cc @@ -322,6 +322,7 @@ namespace functor { TF_CALL_GPU_ALL_TYPES(DECLARE_GPU_SPECS); TF_CALL_int8(DECLARE_GPU_SPECS); +TF_CALL_uint8(DECLARE_GPU_SPECS); } // namespace functor // Registration of the GPU implementations. @@ -355,6 +356,7 @@ TF_CALL_int8(DECLARE_GPU_SPECS); TF_CALL_GPU_ALL_TYPES(REGISTER_GPU_KERNEL); TF_CALL_int8(REGISTER_GPU_KERNEL); +TF_CALL_uint8(REGISTER_GPU_KERNEL); // A special GPU kernel for int32. // TODO(b/25387198): Also enable int32 in device memory. This kernel diff --git a/tensorflow/core/kernels/pad_op_gpu.cu.cc b/tensorflow/core/kernels/pad_op_gpu.cu.cc index 00ec44adc2..0cd8ef17ba 100644 --- a/tensorflow/core/kernels/pad_op_gpu.cu.cc +++ b/tensorflow/core/kernels/pad_op_gpu.cu.cc @@ -41,6 +41,7 @@ typedef Eigen::GpuDevice GPUDevice; TF_CALL_GPU_ALL_TYPES(DEFINE_GPU_SPECS); TF_CALL_int8(DEFINE_GPU_SPECS); +TF_CALL_uint8(DEFINE_GPU_SPECS); } // namespace tensorflow -- GitLab From e18fba2d7eb0ba9e01ff998ee413932ead712eb7 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Fri, 19 Oct 2018 03:18:06 +0000 Subject: [PATCH 0010/1765] Adds test case of uint8 support for Pad with GPU Signed-off-by: Yong Tang --- tensorflow/python/kernel_tests/pad_op_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/python/kernel_tests/pad_op_test.py b/tensorflow/python/kernel_tests/pad_op_test.py index fc302c4141..e875bb9d65 100644 --- a/tensorflow/python/kernel_tests/pad_op_test.py +++ b/tensorflow/python/kernel_tests/pad_op_test.py @@ -215,7 +215,7 @@ class PadOpTest(test.TestCase): def testIntTypes(self): # TODO(touts): Figure out why the padding tests do not work on GPU # for int types and rank > 2. - for t in [np.int8, np.int32, np.int64]: + for t in [np.int8, np.uint8, np.int32, np.int64]: self._testAll( np.random.randint(-100, 100, (4, 4, 3)).astype(t), [[1, 0], [2, 3], [0, 2]], 0) -- GitLab From d31e6ad81cf0c88e08a00a6ab16c2ac2419e7b10 Mon Sep 17 00:00:00 2001 From: Matt Conley Date: Wed, 24 Oct 2018 13:57:20 -0700 Subject: [PATCH 0011/1765] Update Cast Op test for ARM behavior --- tensorflow/python/kernel_tests/cast_op_test.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tensorflow/python/kernel_tests/cast_op_test.py b/tensorflow/python/kernel_tests/cast_op_test.py index a5dff5df62..90c2bd0294 100644 --- a/tensorflow/python/kernel_tests/cast_op_test.py +++ b/tensorflow/python/kernel_tests/cast_op_test.py @@ -151,7 +151,7 @@ class CastOpTest(test.TestCase): # np.float64("np.inf").astype(np.int32) is negative on x86 but positive on ppc64le # Numpy link to relevant discussion - https://github.com/numpy/numpy/issues/9040 # Tensorflow link to relevant discussion - https://github.com/tensorflow/tensorflow/issues/9360 - if platform.machine() == "ppc64le": + if platform.machine() == "ppc64le" or platform.machine() == "aarch64": self._compare(-np.inf, np.int32, i4.min, False) self._compare(-np.inf, np.int64, i8.min, False) else: @@ -163,8 +163,13 @@ class CastOpTest(test.TestCase): self._compare(-np.inf, np.int64, i8.min, False) self.assertAllEqual(np.isnan(self._cast(np.nan, np.float32, False)), True) self.assertAllEqual(np.isnan(self._cast(np.nan, np.float64, False)), True) - self._compare(np.nan, np.int32, i4.min, False) - self._compare(np.nan, np.int64, i8.min, False) + # np.float64(np.nan).astype(np.int32) is 0 on ARM + if platform.machine() == "aarch64": + self._compare(np.nan, np.int32, 0, False) + self._compare(np.nan, np.int64, 0, False) + else: + self._compare(np.nan, np.int32, i4.min, False) + self._compare(np.nan, np.int64, i8.min, False) self._compare(np.inf, np.float32, np.inf, True) self._compare(np.inf, np.float64, np.inf, True) -- GitLab From 65344d0a7ebd21c71b3f3ed7cb091541504b659a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yan=20Facai=20=28=E9=A2=9C=E5=8F=91=E6=89=8D=29?= Date: Thu, 1 Nov 2018 09:36:09 +0800 Subject: [PATCH 0012/1765] TST: use testing_utils.layer_test instead --- .../python/keras/layers/convolutional_test.py | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/tensorflow/python/keras/layers/convolutional_test.py b/tensorflow/python/keras/layers/convolutional_test.py index 63fb60ebaf..7d8051e596 100644 --- a/tensorflow/python/keras/layers/convolutional_test.py +++ b/tensorflow/python/keras/layers/convolutional_test.py @@ -339,10 +339,16 @@ class Conv3DTransposeTest(test.TestCase): def test_conv3dtranspose_dynamic_shape(self): with self.session(use_gpu=True): # Won't raise error here. - layer = keras.layers.Conv3DTranspose(3, 3, data_format='channels_last') - layer.build((None, None, None, None, 1)) - layer1 = keras.layers.Conv3DTranspose(3, 3, data_format='channels_first') - layer1.build((None, 1, None, None, None)) + testing_utils.layer_test( + keras.layers.Conv3DTranspose, + kwargs={'data_format': 'channels_first', + 'filters': 3, 'kernel_size': 3}, + input_shape=(None, 1, None, None, None)) + testing_utils.layer_test( + keras.layers.Conv3DTranspose, + kwargs={'data_format': 'channels_last', + 'filters': 3, 'kernel_size': 3}, + input_shape=(None, None, None, None, 1)) class SeparableConv1DTest(test.TestCase): @@ -568,10 +574,16 @@ class Conv3DTest(test.TestCase): def test_conv3d_dynamic_shape(self): with self.session(use_gpu=True): # Won't raise error here. - layer = keras.layers.Conv3D(3, 3, data_format='channels_last') - layer.build((None, None, None, None, 1)) - layer1 = keras.layers.Conv3D(3, 3, data_format='channels_first') - layer1.build((None, 1, None, None, None)) + testing_utils.layer_test( + keras.layers.Conv3D, + kwargs={'data_format': 'channels_first', + 'filters': 3, 'kernel_size': 3}, + input_shape=(None, 1, None, None, None)) + testing_utils.layer_test( + keras.layers.Conv3D, + kwargs={'data_format': 'channels_last', + 'filters': 3, 'kernel_size': 3}, + input_shape=(None, None, None, None, 1)) class ZeroPaddingTest(test.TestCase): -- GitLab From 35f20ca9e794b455777a52bf70b5f7d79ae60455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yan=20Facai=20=28=E9=A2=9C=E5=8F=91=E6=89=8D=29?= Date: Thu, 1 Nov 2018 10:11:14 +0800 Subject: [PATCH 0013/1765] TST: add input_data --- .../python/keras/layers/convolutional_test.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tensorflow/python/keras/layers/convolutional_test.py b/tensorflow/python/keras/layers/convolutional_test.py index 7d8051e596..737e12a2bd 100644 --- a/tensorflow/python/keras/layers/convolutional_test.py +++ b/tensorflow/python/keras/layers/convolutional_test.py @@ -337,18 +337,21 @@ class Conv3DTransposeTest(test.TestCase): self.assertEqual(layer.bias.constraint, b_constraint) def test_conv3dtranspose_dynamic_shape(self): + input_data = np.random.random((1, 3, 3, 3, 3)) with self.session(use_gpu=True): # Won't raise error here. testing_utils.layer_test( keras.layers.Conv3DTranspose, kwargs={'data_format': 'channels_first', 'filters': 3, 'kernel_size': 3}, - input_shape=(None, 1, None, None, None)) + input_shape=(None, 3, None, None, None), + input_data=input_data) testing_utils.layer_test( keras.layers.Conv3DTranspose, kwargs={'data_format': 'channels_last', 'filters': 3, 'kernel_size': 3}, - input_shape=(None, None, None, None, 1)) + input_shape=(None, None, None, None, 3), + input_data=input_data) class SeparableConv1DTest(test.TestCase): @@ -572,18 +575,21 @@ class Conv3DTest(test.TestCase): self.assertEqual(layer.bias.constraint, b_constraint) def test_conv3d_dynamic_shape(self): + input_data = np.random.random((1, 3, 3, 3, 3)) with self.session(use_gpu=True): # Won't raise error here. testing_utils.layer_test( keras.layers.Conv3D, kwargs={'data_format': 'channels_first', 'filters': 3, 'kernel_size': 3}, - input_shape=(None, 1, None, None, None)) + input_shape=(None, 3, None, None, None), + input_data=input_data) testing_utils.layer_test( keras.layers.Conv3D, kwargs={'data_format': 'channels_last', 'filters': 3, 'kernel_size': 3}, - input_shape=(None, None, None, None, 1)) + input_shape=(None, None, None, None, 3), + input_data=input_data) class ZeroPaddingTest(test.TestCase): -- GitLab From 8de3a6ee6c7b498e32e8c22c6631a3c0a7a4af86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yan=20Facai=20=28=E9=A2=9C=E5=8F=91=E6=89=8D=29?= Date: Thu, 1 Nov 2018 10:35:48 +0800 Subject: [PATCH 0014/1765] TST: data_format=first only run for gpu --- .../python/keras/layers/convolutional_test.py | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/tensorflow/python/keras/layers/convolutional_test.py b/tensorflow/python/keras/layers/convolutional_test.py index 737e12a2bd..ecee080937 100644 --- a/tensorflow/python/keras/layers/convolutional_test.py +++ b/tensorflow/python/keras/layers/convolutional_test.py @@ -337,21 +337,22 @@ class Conv3DTransposeTest(test.TestCase): self.assertEqual(layer.bias.constraint, b_constraint) def test_conv3dtranspose_dynamic_shape(self): - input_data = np.random.random((1, 3, 3, 3, 3)) + input_data = np.random.random((1, 3, 3, 3, 3)).astype(np.float32) with self.session(use_gpu=True): # Won't raise error here. - testing_utils.layer_test( - keras.layers.Conv3DTranspose, - kwargs={'data_format': 'channels_first', - 'filters': 3, 'kernel_size': 3}, - input_shape=(None, 3, None, None, None), - input_data=input_data) testing_utils.layer_test( keras.layers.Conv3DTranspose, kwargs={'data_format': 'channels_last', 'filters': 3, 'kernel_size': 3}, input_shape=(None, None, None, None, 3), input_data=input_data) + if test.is_gpu_available(cuda_only=True): + testing_utils.layer_test( + keras.layers.Conv3DTranspose, + kwargs={'data_format': 'channels_first', + 'filters': 3, 'kernel_size': 3}, + input_shape=(None, 3, None, None, None), + input_data=input_data) class SeparableConv1DTest(test.TestCase): @@ -575,21 +576,22 @@ class Conv3DTest(test.TestCase): self.assertEqual(layer.bias.constraint, b_constraint) def test_conv3d_dynamic_shape(self): - input_data = np.random.random((1, 3, 3, 3, 3)) + input_data = np.random.random((1, 3, 3, 3, 3)).astype(np.float32) with self.session(use_gpu=True): # Won't raise error here. - testing_utils.layer_test( - keras.layers.Conv3D, - kwargs={'data_format': 'channels_first', - 'filters': 3, 'kernel_size': 3}, - input_shape=(None, 3, None, None, None), - input_data=input_data) testing_utils.layer_test( keras.layers.Conv3D, kwargs={'data_format': 'channels_last', 'filters': 3, 'kernel_size': 3}, input_shape=(None, None, None, None, 3), input_data=input_data) + if test.is_gpu_available(cuda_only=True): + testing_utils.layer_test( + keras.layers.Conv3D, + kwargs={'data_format': 'channels_first', + 'filters': 3, 'kernel_size': 3}, + input_shape=(None, 3, None, None, None), + input_data=input_data) class ZeroPaddingTest(test.TestCase): -- GitLab From ec727016282383aacf9d26386b01f6bdbd65b14b Mon Sep 17 00:00:00 2001 From: Pavel Samolysov Date: Thu, 1 Nov 2018 13:39:52 +0300 Subject: [PATCH 0015/1765] Fix the C2678 MSVC compilation error MSVC 14.15 returns the C2678 error during a compilation of the 'tensorflow/core/kernels/data/scan_dataset_op.cc' unit: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\xmemory(217): error C2678: binary '*': no operator found which takes a left-hand operand of type 'const _Iter' (or there is no acceptable conversion) with [ _Iter=tensorflow::OpInputList::Iterator ] .\tensorflow/core/framework/op_kernel.h(405): note: could be 'const tensorflow::Tensor &tensorflow::OpArgIterator::operator *(void)' Two const operator functions: 'operator*() const' and 'operator->() const', returning a const pointer or const reference respectively, have been added to the 'OpArgIterator' template class. Signed-off-by: Pavel Samolysov --- tensorflow/core/framework/op_kernel.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tensorflow/core/framework/op_kernel.h b/tensorflow/core/framework/op_kernel.h index 6c71e118c0..c8e5220028 100644 --- a/tensorflow/core/framework/op_kernel.h +++ b/tensorflow/core/framework/op_kernel.h @@ -376,7 +376,9 @@ class OpArgIterator { using iterator_category = std::forward_iterator_tag; using value_type = ElementType; using pointer = ElementType*; + using const_pointer = const ElementType*; using reference = ElementType&; + using const_reference = const ElementType&; using difference_type = ptrdiff_t; OpArgIterator(const ListType* list, int i) : list_(list), i_(i) {} @@ -405,6 +407,9 @@ class OpArgIterator { reference operator*() { return (*list_)[i_]; } pointer operator->() { return &(*list_)[i_]; } + const_reference operator*() const { return (*list_)[i_]; } + const_pointer operator->() const { return &(*list_)[i_]; } + private: const ListType* const list_; int i_; -- GitLab From 470d0b4bac05151a5761fd3351deba3bcad10994 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Sun, 4 Nov 2018 10:58:02 -0600 Subject: [PATCH 0016/1765] Added CMSIS preprocessor files --- .../micro/examples/micro_speech/CMSIS/hann.h | 1 + .../micro_speech/CMSIS/no_30ms_sample_data.cc | 66 ++++++++++++++++ .../micro_speech/CMSIS/no_30ms_sample_data.h | 32 ++++++++ .../CMSIS/no_power_spectrum_data.cc | 23 ++++++ .../CMSIS/no_power_spectrum_data.h | 29 +++++++ .../micro_speech/CMSIS/preprocessor.cc | 76 +++++++++++++++++++ .../micro_speech/CMSIS/preprocessor.h | 26 +++++++ .../micro_speech/CMSIS/preprocessor_test.cc | 63 +++++++++++++++ .../CMSIS/yes_30ms_sample_data.cc | 70 +++++++++++++++++ .../micro_speech/CMSIS/yes_30ms_sample_data.h | 32 ++++++++ .../CMSIS/yes_power_spectrum_data.cc | 23 ++++++ .../CMSIS/yes_power_spectrum_data.h | 29 +++++++ 12 files changed, 470 insertions(+) create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h new file mode 100644 index 0000000000..b610f79190 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h @@ -0,0 +1 @@ +q15_t hann[480] = {0, 1, 5, 12, 22, 35, 50, 69, 90, 114, 140, 170, 202, 237, 275, 316, 359, 405, 454, 506, 560, 617, 677, 739, 805, 873, 943, 1016, 1092, 1171, 1252, 1335, 1422, 1511, 1602, 1696, 1793, 1892, 1993, 2097, 2203, 2312, 2424, 2537, 2653, 2772, 2893, 3016, 3141, 3269, 3399, 3531, 3665, 3802, 3941, 4081, 4224, 4370, 4517, 4666, 4817, 4970, 5125, 5283, 5442, 5603, 5765, 5930, 6096, 6264, 6434, 6606, 6779, 6954, 7131, 7309, 7488, 7670, 7852, 8037, 8222, 8409, 8598, 8788, 8979, 9171, 9364, 9559, 9755, 9952, 10151, 10350, 10550, 10751, 10954, 11157, 11361, 11566, 11772, 11979, 12186, 12394, 12603, 12812, 13022, 13233, 13444, 13656, 13868, 14080, 14293, 14507, 14720, 14934, 15148, 15363, 15577, 15792, 16007, 16222, 16437, 16652, 16866, 17081, 17296, 17510, 17725, 17939, 18153, 18366, 18579, 18792, 19004, 19216, 19428, 19639, 19849, 20059, 20268, 20476, 20684, 20891, 21097, 21302, 21507, 21711, 21913, 22115, 22316, 22516, 22715, 22912, 23109, 23304, 23498, 23691, 23883, 24074, 24263, 24450, 24637, 24822, 25005, 25187, 25368, 25547, 25724, 25900, 26074, 26246, 26417, 26586, 26753, 26919, 27082, 27244, 27404, 27562, 27718, 27873, 28025, 28175, 28323, 28469, 28613, 28755, 28895, 29033, 29168, 29301, 29433, 29561, 29688, 29812, 29934, 30054, 30171, 30286, 30398, 30508, 30616, 30721, 30824, 30924, 31022, 31117, 31210, 31300, 31388, 31473, 31555, 31635, 31712, 31787, 31858, 31928, 31994, 32058, 32119, 32178, 32233, 32286, 32337, 32384, 32429, 32471, 32510, 32547, 32580, 32611, 32639, 32665, 32687, 32707, 32724, 32738, 32749, 32758, 32763, 32766, 32766, 32763, 32758, 32749, 32738, 32724, 32707, 32687, 32665, 32639, 32611, 32580, 32547, 32510, 32471, 32429, 32384, 32337, 32286, 32233, 32178, 32119, 32058, 31994, 31928, 31858, 31787, 31712, 31635, 31555, 31473, 31388, 31300, 31210, 31117, 31022, 30924, 30824, 30721, 30616, 30508, 30398, 30286, 30171, 30054, 29934, 29812, 29688, 29561, 29433, 29301, 29168, 29033, 28895, 28755, 28613, 28469, 28323, 28175, 28025, 27873, 27718, 27562, 27404, 27244, 27082, 26919, 26753, 26586, 26417, 26246, 26074, 25900, 25724, 25547, 25368, 25187, 25005, 24822, 24637, 24450, 24263, 24074, 23883, 23691, 23498, 23304, 23109, 22912, 22715, 22516, 22316, 22115, 21913, 21711, 21507, 21302, 21097, 20891, 20684, 20476, 20268, 20059, 19849, 19639, 19428, 19216, 19004, 18792, 18579, 18366, 18153, 17939, 17725, 17510, 17296, 17081, 16866, 16652, 16437, 16222, 16007, 15792, 15577, 15363, 15148, 14934, 14720, 14507, 14293, 14080, 13868, 13656, 13444, 13233, 13022, 12812, 12603, 12394, 12186, 11979, 11772, 11566, 11361, 11157, 10954, 10751, 10550, 10350, 10151, 9952, 9755, 9559, 9364, 9171, 8979, 8788, 8598, 8409, 8222, 8037, 7852, 7670, 7488, 7309, 7131, 6954, 6779, 6606, 6434, 6264, 6096, 5930, 5765, 5603, 5442, 5283, 5125, 4970, 4817, 4666, 4517, 4370, 4224, 4081, 3941, 3802, 3665, 3531, 3399, 3269, 3141, 3016, 2893, 2772, 2653, 2537, 2424, 2312, 2203, 2097, 1993, 1892, 1793, 1696, 1602, 1511, 1422, 1335, 1252, 1171, 1092, 1016, 943, 873, 805, 739, 677, 617, 560, 506, 454, 405, 359, 316, 275, 237, 202, 170, 140, 114, 90, 69, 50, 35, 22, 12, 5, 1, 0}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc new file mode 100644 index 0000000000..924f16f285 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc @@ -0,0 +1,66 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// See the header for documentation on the meaning of this data. + +#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h" + +const int g_no_30ms_sample_data_size = 480; +const int16_t g_no_30ms_sample_data[480] = { + 5713, 5735, 5735, 5737, 5701, 5691, 5656, 5633, 5611, 5552, 5475, + 5394, 5293, 5177, 5064, 4924, 4737, 4599, 4420, 4237, 4048, 3828, + 3623, 3413, 3183, 2915, 2622, 2308, 1980, 1657, 1261, 901, 549, + 205, -85, -383, -688, -969, -1246, -1530, -1850, -2206, -2561, -2915, + -3224, -3482, -3713, -3921, -4107, -4287, -4470, -4660, -4850, -5057, -5239, + -5395, -5540, -5619, -5697, -5724, -5697, -5675, -5633, -5590, -5579, -5530, + -5486, -5442, -5426, -5391, -5348, -5276, -5197, -5124, -5039, -4925, -4808, + -4677, -4581, -4479, -4343, -4218, -4087, -3970, -3858, -3729, -3570, -3384, + -3206, -3020, -2839, -2636, -2453, -2287, -2185, -2154, -1926, -1562, -1223, + -758, -473, -64, 395, 599, 880, 814, 938, 1172, 1498, 1928, + 2127, 2422, 2608, 2841, 2937, 2886, 2815, 2985, 3324, 3757, 4152, + 4481, 4652, 4917, 4965, 4766, 4583, 4328, 4503, 4815, 5118, 5408, + 5682, 5956, 6082, 6055, 5744, 5426, 5341, 5427, 5606, 5882, 6065, + 6226, 6428, 6477, 6385, 6009, 5728, 5552, 5439, 5339, 5200, 5008, + 4947, 4835, 4614, 4330, 3887, 3521, 3111, 2460, 1983, 1297, 650, + 279, -353, -720, -1044, -1518, -1668, -2117, -2496, -2743, -3266, -3607, + -3790, -4149, -4075, -4042, -4096, -3981, -4138, -4226, -4214, -4503, -4455, + -4577, -4642, -4346, -4351, -4270, -4263, -4522, -4521, -4673, -4814, -4731, + -4950, -5011, -5004, -5288, -5341, -5566, -5833, -5783, -5929, -5847, -5765, + -5828, -5644, -5613, -5615, -5428, -5291, -5014, -4554, -4277, -3964, -3854, + -3829, -3612, -3603, -3438, -3137, -2831, -2164, -1438, -939, -330, -156, + 46, 242, 73, 242, 220, 239, 542, 565, 739, 872, 801, + 857, 676, 543, 586, 567, 828, 1142, 1490, 1985, 2508, 2982, + 3438, 3699, 3939, 4069, 4178, 4420, 4622, 4917, 5338, 5801, 6285, + 6658, 6963, 7213, 7233, 7328, 7176, 7038, 7031, 6860, 6957, 6767, + 6599, 6523, 6212, 6147, 6063, 5860, 6020, 6015, 6033, 6184, 5722, + 5607, 5016, 4337, 4063, 3229, 3080, 3006, 2804, 3035, 2541, 2136, + 1879, 1012, 401, -575, -1584, -1930, -2278, -2485, -2477, -2712, -2747, + -2766, -3320, -3592, -4188, -4669, -4672, -4939, -4789, -4426, -4203, -3674, + -3563, -3656, -3759, -4067, -4257, -4522, -4970, -5204, -5237, -5139, -4907, + -4911, -4917, -4921, -5007, -5230, -5654, -6122, -6464, -6733, -6948, -7067, + -6972, -6800, -6520, -6132, -5830, -5382, -5091, -4797, -4546, -4472, -4362, + -4350, -4235, -3851, -3454, -3144, -2735, -2341, -1845, -1262, -958, -549, + -166, 66, 382, 366, 352, 341, 85, -13, -176, -303, -235, + -341, -309, -227, -249, -50, 143, 384, 874, 1149, 1552, 2155, + 2767, 3499, 3994, 4460, 4920, 5288, 5569, 5704, 5881, 6094, 6461, + 6653, 6803, 7115, 7311, 7521, 7612, 7443, 7380, 7124, 6742, 6495, + 5964, 5656, 5415, 5167, 5656, 5813, 6027, 6401, 6351, 6787, 7019, + 6581, 6512, 5965, 5308, 5140, 4336, 4147, 3899, 3398, 3360, 2830, + 2624, 1968, 1026, 395, -699, -1424, -2327, -3006, -3192, -3435, -3337, + -3686, -3513, -3350, -3502, -3261, -3878, -4005, -4063, -4187, -3767, -3598, + -3384, -3300, -3094, -2857, -3023, -3274, -3851, -4352, -4523, -4943, -5477, + -5612, -5682, -5733, -5714, -5965, -6110, -5950, -6158, -6548, -6897, -7165, + -7281, -7352, -7258, -7185, -6659, -5946, -5470, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h new file mode 100644 index 0000000000..5299930659 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h @@ -0,0 +1,32 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This data was created from the PCM data in a WAV file held in v2 of the +// Speech Commands test dataset, at the path: +// speech_commands_test_set_v0.02/no/f9643d42_nohash_4.wav +// The data was extracted starting at an offset of 8,960, which corresponds to +// the 29th spectrogram slice. It's designed to be used to test the +// preprocessing pipeline, to ensure that the expected spectrogram slice is +// produced given this input. + +#ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_30MS_SAMPLE_DATA_H_ +#define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_30MS_SAMPLE_DATA_H_ + +#include + +extern const int g_no_30ms_sample_data_size; +extern const int16_t g_no_30ms_sample_data[]; + +#endif // TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_30MS_SAMPLE_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc new file mode 100644 index 0000000000..064363e584 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc @@ -0,0 +1,23 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// See the header for documentation on the meaning of this data. + +#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" + +const uint8_t g_no_power_spectrum_data[g_no_power_spectrum_data_size] = { + 255, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h new file mode 100644 index 0000000000..c19566bfb6 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h @@ -0,0 +1,29 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This data was extracted from the larger feature data held in +// no_features_data.cc and consists of the 29th spectrogram slice of 43 values. +// This is the expected result of running the sample data in +// no_30ms_sample_data.cc through through the preprocessing pipeline. + +#ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_POWER_SPECTRUM_DATA_H_ +#define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_POWER_SPECTRUM_DATA_H_ + +#include + +constexpr int g_no_power_spectrum_data_size = 43; +extern const uint8_t g_no_power_spectrum_data[]; + +#endif // TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_POWER_SPECTRUM_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc new file mode 100644 index 0000000000..7932258a5d --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc @@ -0,0 +1,76 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +extern "C" { + #define ARM_MATH_CM4 + #define IFFT_FLAG_R 0 + #define BIT_REVERSE_FLAG 1 + #define FFT_SIZE 512 + #include + #include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h" +} + + #include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h" + +q15_t bufA[FFT_SIZE]; +q15_t bufB[FFT_SIZE]; +arm_rfft_instance_q15 S_arm_fft; +arm_status arm_math_status; + +namespace { +// These constants allow us to allocate fixed-sized arrays on the stack for our +// working memory. +constexpr int kInputSize = 512; +constexpr int kAverageWindowSize = 6; +constexpr int kOutputSize = + ((kInputSize / 2) + (kAverageWindowSize - 1)) / kAverageWindowSize; +} //namespace + +TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, + const int16_t* input, int input_size, int output_size, + uint8_t* output) { + if (input_size > kInputSize) { + error_reporter->Report("Input size %d larger than %d", input_size, + kInputSize); + return kTfLiteError; + } + if (output_size != kOutputSize) { + error_reporter->Report("Requested output size %d doesn't match %d", + output_size, kOutputSize); + return kTfLiteError; + } + + arm_mult_q15((q15_t *) input, hann, bufB, 512); + + // Should move init code outside of Preprocess() function + arm_math_status = arm_rfft_init_q15(&S_arm_fft, FFT_SIZE, IFFT_FLAG_R, BIT_REVERSE_FLAG); + arm_rfft_q15(&S_arm_fft, bufB, bufA); + arm_shift_q15(bufA, 5, bufB, FFT_SIZE); + + arm_cmplx_mag_squared_q15(bufB, bufA, 256); + arm_shift_q15(bufA, 1, bufB, 256); + + int i; + for (i=0; i<42; i++) { + arm_mean_q15(bufB+6*i, 6, bufA+i); + } + arm_mean_q15(bufB+252, 4, bufA+42); + + for (i=0; i<43; i++) { + output[i] = (uint8_t) (bufA[i] >> 5); + } + + return kTfLiteOk; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h new file mode 100644 index 0000000000..571eb5921b --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h @@ -0,0 +1,26 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ +#define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ + +#include "tensorflow/contrib/lite/c/c_api_internal.h" +#include "tensorflow/contrib/lite/experimental/micro/micro_error_reporter.h" + +TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, + const int16_t* input, int input_size, int output_size, + uint8_t* output); + +#endif // TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc new file mode 100644 index 0000000000..ef82707b12 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc @@ -0,0 +1,63 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h" +#include "tensorflow/contrib/lite/c/c_api_internal.h" +#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h" +#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" +#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h" +#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" +#include "tensorflow/contrib/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/contrib/lite/experimental/micro/testing/micro_test.h" + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(TestPreprocessor) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + uint8_t yes_calculated_data[g_yes_power_spectrum_data_size]; + TfLiteStatus yes_status = Preprocess( + error_reporter, g_yes_30ms_sample_data, g_yes_30ms_sample_data_size, + g_yes_power_spectrum_data_size, yes_calculated_data); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, yes_status); + + for (int i = 0; i < g_yes_power_spectrum_data_size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(g_yes_power_spectrum_data[i], + yes_calculated_data[i]); + if (g_yes_power_spectrum_data[i] != yes_calculated_data[i]) { + error_reporter->Report("Expected value %d but found %d", + g_yes_power_spectrum_data[i], + yes_calculated_data[i]); + } + } + + uint8_t no_calculated_data[g_yes_power_spectrum_data_size]; + TfLiteStatus no_status = Preprocess( + error_reporter, g_no_30ms_sample_data, g_no_30ms_sample_data_size, + g_no_power_spectrum_data_size, no_calculated_data); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, no_status); + + for (int i = 0; i < g_no_power_spectrum_data_size; ++i) { + TF_LITE_MICRO_EXPECT_EQ(g_no_power_spectrum_data[i], no_calculated_data[i]); + if (g_no_power_spectrum_data[i] != no_calculated_data[i]) { + error_reporter->Report("Expected value %d but found %d", + g_no_power_spectrum_data[i], + no_calculated_data[i]); + } + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc new file mode 100644 index 0000000000..22a44e756d --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc @@ -0,0 +1,70 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// See the header for documentation on the meaning of this data. + +#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h" + +const int g_yes_30ms_sample_data_size = 480; +const int16_t g_yes_30ms_sample_data[480] = { + -876, -470, 510, 803, 170, -787, -1568, -1893, -1598, -1027, + -992, -1803, -2610, -2484, -1905, -2113, -3113, -3399, -2267, -1261, + -2007, -3637, -3909, -2340, -893, -1158, -2272, -2486, -1639, -915, + -777, -596, -91, 196, 85, 210, 875, 1373, 1247, 1219, + 1958, 2718, 2328, 1196, 1008, 2350, 3677, 3269, 1503, 366, + 922, 2264, 2810, 1996, 608, -168, 75, 680, 811, 395, + -56, -318, -607, -966, -1108, -925, -613, -368, -369, -919, + -1926, -2460, -1685, -300, 155, -611, -1524, -2204, -3227, -3859, + -2037, 1622, 2382, -2583, -8448, -7544, -84, 4814, 915, -6423, + -7558, -1746, 2515, -59, -4587, -3858, 1260, 3625, 187, -4148, + -3500, 1542, 5467, 4780, 1256, -1127, -403, 2481, 5332, 6346, + 5014, 2536, 1216, 2467, 5039, 6238, 5070, 3381, 3269, 4173, + 3905, 2248, 1586, 3299, 5240, 4362, 1004, -1382, -489, 2113, + 3168, 1620, -742, -1824, -1435, -897, -1058, -1500, -1545, -1398, + -1965, -3266, -4136, -3756, -2609, -1804, -1986, -3087, -4599, -5296, + -4051, -1731, -781, -2228, -4092, -3977, -2325, -1353, -1568, -1490, + -428, 178, -672, -1650, -1058, 749, 2039, 2079, 1540, 897, + 310, 572, 2266, 4265, 4265, 1869, -231, 559, 3332, 4752, + 3229, 768, 101, 1364, 2463, 1984, 819, 411, 723, 675, + -162, -923, -743, -32, 185, -516, -1653, -2359, -2103, -986, + 42, -205, -1702, -2870, -2337, -809, -221, -982, -1544, -946, + -598, -2117, -4291, -4100, -857, 1948, 338, -4799, -7972, -5403, + 173, 2371, -1063, -5533, -5578, -1777, 605, -985, -3249, -2213, + 1184, 2691, 560, -2356, -2288, 1233, 5244, 6441, 4004, 370, + -663, 2555, 7404, 9282, 6573, 2612, 1836, 4662, 7467, 7393, + 5421, 4262, 4741, 5362, 4705, 3163, 2397, 3337, 4887, 4810, + 2254, -749, -1316, 772, 2706, 2016, -573, -2552, -2746, -2012, + -1647, -1978, -2579, -3105, -3473, -3911, -4484, -4891, -4795, -4163, + -3543, -3538, -4275, -5356, -5743, -4637, -2614, -1301, -1825, -3341, + -4011, -2937, -751, 1007, 1245, 235, -639, -61, 1626, 2864, + 2967, 2734, 3013, 3329, 2914, 2312, 2666, 3839, 4308, 3162, + 1453, 768, 1255, 1887, 2006, 1715, 1031, -297, -1660, -1690, + -277, 813, -30, -2137, -3370, -2854, -1553, -593, -413, -1146, + -2567, -3440, -2369, -205, 379, -1258, -2315, -812, 262, -3205, + -8576, -7894, 738, 7492, 1951, -11595, -17098, -6934, 7139, 8065, + -4575, -14199, -8946, 3606, 7504, -547, -8242, -5113, 4406, 8113, + 2134, -5040, -4089, 4157, 10934, 10158, 4167, -565, -192, 4428, + 9765, 12201, 9861, 4512, 1225, 3451, 8483, 10133, 6497, 2574, + 3333, 6806, 6986, 2487, -1214, 623, 5416, 6647, 2204, -3289, + -4556, -1565, 1544, 1525, -1236, -4293, -5695, -5174, -3995, -3403, + -3449, -3750, -4505, -6014, -7296, -6523, -3849, -2096, -3288, -5722, + -6004, -3581, -1497, -1960, -3330, -2800, -434, 964, -111, -1739, + -1136, 1736, 4151, 3736, 1274, -451, 469, 3386, 5833, 5898, + 3646, 1085, 272, 1743, 4061, 5108, 3837, 1490, 246, 967, + 1866, 859, -1069, -974, 1542, 2835, 47, -4285, -5068, -1567, + 1781, 1223, -1997, -4227, -3747, -1720, 41, 245, -1228, -2972, + -2673, 22, 1980, -930, -7721, -11271, -5725, 4974, 8484, -2007, + -16979, -19255, -4670, 11057, 9690, -6417, -17537, -10841, 4262, 9292, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h new file mode 100644 index 0000000000..cb757e84ba --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h @@ -0,0 +1,32 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This data was created from the PCM data in a WAV file held in v2 of the +// Speech Commands test dataset, at the path: +// speech_commands_test_set_v0.02/yes/f2e59fea_nohash_1.wav +// The data was extracted starting at an offset of 8,000, which corresponds to +// the 26th spectrogram slice. It's designed to be used to test the +// preprocessing pipeline, to ensure that the expected spectrogram slice is +// produced given this input. + +#ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_30MS_SAMPLE_DATA_H_ +#define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_30MS_SAMPLE_DATA_H_ + +#include + +extern const int g_yes_30ms_sample_data_size; +extern const int16_t g_yes_30ms_sample_data[]; + +#endif // TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_30MS_SAMPLE_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc new file mode 100644 index 0000000000..96a84e5eaa --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc @@ -0,0 +1,23 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// See the header for documentation on the meaning of this data. + +#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" + +const uint8_t g_yes_power_spectrum_data[g_yes_power_spectrum_data_size] = { + 8, 89, 8, 0, 0, 0, 0, 0, 0, 0, 0, 4, 13, 1, 6, 23, 20, 6, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h new file mode 100644 index 0000000000..b02853f2ea --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h @@ -0,0 +1,29 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// This data was extracted from the larger feature data held in +// no_features_data.cc and consists of the 26th spectrogram slice of 43 values. +// This is the expected result of running the sample data in +// yes_30ms_sample_data.cc through through the preprocessing pipeline. + +#ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_POWER_SPECTRUM_DATA_H_ +#define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_POWER_SPECTRUM_DATA_H_ + +#include + +constexpr int g_yes_power_spectrum_data_size = 43; +extern const uint8_t g_yes_power_spectrum_data[]; + +#endif // TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_POWER_SPECTRUM_DATA_H_ -- GitLab From dd64bc646851fd9d2479e596274b2bea854c7af0 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Sun, 4 Nov 2018 11:14:45 -0600 Subject: [PATCH 0017/1765] Initial add of cmsis-dsp makefile and modification of apollo3evb_makefile; Added *.bin rule to Mkaefile --- .../experimental/micro/tools/make/Makefile | 5 ++++ .../make/targets/apollo3evb_makefile.inc | 25 +++++++++++-------- .../tools/make/targets/cmsis-dsp_makefile.inc | 9 +++++++ 3 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc diff --git a/tensorflow/lite/experimental/micro/tools/make/Makefile b/tensorflow/lite/experimental/micro/tools/make/Makefile index 5492003e5a..b80ace859a 100644 --- a/tensorflow/lite/experimental/micro/tools/make/Makefile +++ b/tensorflow/lite/experimental/micro/tools/make/Makefile @@ -180,6 +180,11 @@ $(BINDIR)%_test : $(OBJDIR)%_test.o $(MICROLITE_LIB_PATH) $(BINDIR)%.test_target: $(BINDIR)%_test $(TEST_SCRIPT) $< '~~~ALL TESTS PASSED~~~' +# snease: Add %.bin rule here since BINDIR is now defined +$(BINDIR)%.bin: $(BINDIR)% + @mkdir -p $(dir $@) + $(OBJCOPY) $< $@ -O binary + $(info $(MICROLITE_TEST_TARGETS)) test: test_micro_speech $(MICROLITE_TEST_TARGETS) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc index f722204fea..6a5fc7895c 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc @@ -4,10 +4,10 @@ ifeq ($(TARGET), apollo3evb) TARGET_TOOLCHAIN_PREFIX := arm-none-eabi- # Download the Ambiq Apollo3 SDK and set this variable to find the header # files: - APOLLO3_SDK := /ssd/ambiq/AmbiqSuite\ SDK\ for\ Apollo3/Apollo3-SDK-2018.08.13/ + APOLLO3_SDK := /home/snease/work/Apollo3-SDK-2018.08.13 # Need a pointer to the GNU ARM toolchain for crtbegin.o for the fp functions # with the softfp interfaces. - GCC_ARM := /ssd/gnu_arm_toolchain/gcc-arm-none-eabi-7-2018-q2-update/ + GCC_ARM := /home/snease/work/gcc-arm-none-eabi-7-2018-q2-update/ PLATFORM_FLAGS = \ -DPART_apollo3 \ @@ -16,6 +16,7 @@ ifeq ($(TARGET), apollo3evb) -DGEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK \ -DTF_LITE_STATIC_MEMORY \ -DTF_LITE_MCU_DEBUG_LOG \ + -D __FPU_PRESENT=1 \ -fno-rtti \ -fmessage-length=0 \ -fno-exceptions \ @@ -28,7 +29,7 @@ ifeq ($(TARGET), apollo3evb) -mcpu=cortex-m4 \ -mthumb \ -mfpu=fpv4-sp-d16 \ - -mfloat-abi=softfp \ + -mfloat-abi=softfp\ -std=gnu++11 \ -Wvla \ -Wall \ @@ -46,7 +47,7 @@ ifeq ($(TARGET), apollo3evb) CXXFLAGS += $(PLATFORM_FLAGS) CCFLAGS += $(PLATFORM_FLAGS) LDFLAGS += \ - -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp \ + -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp\ -nostartfiles -static \ -Wl,--gc-sections -Wl,--entry,Reset_Handler \ -Wl,--start-group -lm -lc -lgcc -Wl,--end-group \ @@ -59,10 +60,12 @@ ifeq ($(TARGET), apollo3evb) MICROLITE_LIBS := \ $(MAKEFILE_DIR)/targets/apollo3evb/libam_bsp.a \ $(MAKEFILE_DIR)/targets/apollo3evb/libam_hal.a \ + $(MAKEFILE_DIR)/downloads/cmsis/CMSIS/Lib/GCC/libarm_cortexM4lf_math_softfp.a \ $(GCC_ARM)/lib/gcc/arm-none-eabi/7.3.1/thumb/v7e-m/fpv4-sp/softfp/crtbegin.o \ -lm INCLUDES += \ -isystem$(MAKEFILE_DIR)/downloads/cmsis/CMSIS/Core/Include/ \ + -isystem$(MAKEFILE_DIR)/downloads/cmsis/CMSIS/DSP/Include/ \ -I$(GCC_ARM)/arm-none-eabi/ \ -I$(APOLLO3_SDK)/mcu/apollo3/ \ -I$(APOLLO3_SDK)/CMSIS/AmbiqMicro/Include/ \ @@ -86,19 +89,21 @@ ifeq ($(TARGET), apollo3evb) $(MAKEFILE_DIR)/targets/apollo3evb/am_util_id.c \ $(MAKEFILE_DIR)/targets/apollo3evb/am_util_stdio.c - TEST_SCRIPT := tensorflow/lite/experimental/log_test/test_apollo3evb_binary.sh + TEST_SCRIPT := tensorflow/contrib/lite/experimental/log_test/test_apollo3evb_binary.sh # These are tests that don't currently work on the blue pill. EXCLUDED_TESTS := \ - tensorflow/lite/experimental/micro/micro_interpreter_test.cc \ - tensorflow/lite/experimental/micro/simple_tensor_allocator_test.cc + tensorflow/contrib/lite/experimental/micro/micro_interpreter_test.cc \ + tensorflow/contrib/lite/experimental/micro/simple_tensor_allocator_test.cc MICROLITE_TEST_SRCS := $(filter-out $(EXCLUDED_TESTS), $(MICROLITE_TEST_SRCS)) # These are microcontroller-specific rules for converting the ELF output # of the linker into a binary image that can be loaded directly. OBJCOPY := $(TARGET_TOOLCHAIN_PREFIX)objcopy -$(BINDIR)/%.bin: $(BINDIR)/% - @mkdir -p $(dir $@) - $(OBJCOPY) $< $@ -O binary +# BINDIR isn't defined yet +# Put this at the end of the main makefile +# $(BINDIR)/%.bin: $(BINDIR)/% +# @mkdir -p $(dir $@) +# $(OBJCOPY) $< $@ -O binary endif diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc new file mode 100644 index 0000000000..9bbb7c12a3 --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc @@ -0,0 +1,9 @@ +ifeq ($(VENDORLIB), cmsis-dsp) +PREPROCESSOR_TEST_SRCS := \ +tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc \ +tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc \ +tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc \ +tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc \ +tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc \ +tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc +endif -- GitLab From 2d7b55a9aa4abab59a88821ec05f6e3318cd499a Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Sun, 4 Nov 2018 15:55:24 -0600 Subject: [PATCH 0018/1765] gitignore for some subdirectories of make; CMSIS files fixed for new location of lite --- .../micro_speech/CMSIS/no_30ms_sample_data.cc | 2 +- .../micro_speech/CMSIS/no_power_spectrum_data.cc | 2 +- .../examples/micro_speech/CMSIS/preprocessor.cc | 4 ++-- .../examples/micro_speech/CMSIS/preprocessor.h | 4 ++-- .../micro_speech/CMSIS/preprocessor_test.cc | 16 ++++++++-------- .../micro_speech/CMSIS/yes_30ms_sample_data.cc | 2 +- .../CMSIS/yes_power_spectrum_data.cc | 2 +- .../lite/experimental/micro/tools/make/Makefile | 3 +++ .../tools/make/targets/apollo3evb_makefile.inc | 16 ++++------------ .../tools/make/targets/cmsis-dsp_makefile.inc | 12 ++++++------ 10 files changed, 29 insertions(+), 34 deletions(-) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc index 924f16f285..6d9147bd44 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc @@ -15,7 +15,7 @@ limitations under the License. // See the header for documentation on the meaning of this data. -#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h" const int g_no_30ms_sample_data_size = 480; const int16_t g_no_30ms_sample_data[480] = { diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc index 064363e584..cdd7d46c8c 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc @@ -15,7 +15,7 @@ limitations under the License. // See the header for documentation on the meaning of this data. -#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" const uint8_t g_no_power_spectrum_data[g_no_power_spectrum_data_size] = { 255, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc index 7932258a5d..24119cbdda 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc @@ -19,10 +19,10 @@ extern "C" { #define BIT_REVERSE_FLAG 1 #define FFT_SIZE 512 #include - #include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h" + #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h" } - #include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h" + #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h" q15_t bufA[FFT_SIZE]; q15_t bufB[FFT_SIZE]; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h index 571eb5921b..3d02406371 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h @@ -16,8 +16,8 @@ limitations under the License. #ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ #define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ -#include "tensorflow/contrib/lite/c/c_api_internal.h" -#include "tensorflow/contrib/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, const int16_t* input, int input_size, int output_size, diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc index ef82707b12..3560a17cd4 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc @@ -13,14 +13,14 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h" -#include "tensorflow/contrib/lite/c/c_api_internal.h" -#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h" -#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" -#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h" -#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" -#include "tensorflow/contrib/lite/experimental/micro/micro_error_reporter.h" -#include "tensorflow/contrib/lite/experimental/micro/testing/micro_test.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" TF_LITE_MICRO_TESTS_BEGIN diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc index 22a44e756d..056ee544da 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc @@ -15,7 +15,7 @@ limitations under the License. // See the header for documentation on the meaning of this data. -#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h" const int g_yes_30ms_sample_data_size = 480; const int16_t g_yes_30ms_sample_data[480] = { diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc index 96a84e5eaa..235a853e68 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc @@ -15,7 +15,7 @@ limitations under the License. // See the header for documentation on the meaning of this data. -#include "tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" const uint8_t g_yes_power_spectrum_data[g_yes_power_spectrum_data_size] = { 8, 89, 8, 0, 0, 0, 0, 0, 0, 0, 0, 4, 13, 1, 6, 23, 20, 6, 4, 0, 0, 0, diff --git a/tensorflow/lite/experimental/micro/tools/make/Makefile b/tensorflow/lite/experimental/micro/tools/make/Makefile index b80ace859a..4dbfc629a2 100644 --- a/tensorflow/lite/experimental/micro/tools/make/Makefile +++ b/tensorflow/lite/experimental/micro/tools/make/Makefile @@ -181,6 +181,9 @@ $(BINDIR)%.test_target: $(BINDIR)%_test $(TEST_SCRIPT) $< '~~~ALL TESTS PASSED~~~' # snease: Add %.bin rule here since BINDIR is now defined +# These are microcontroller-specific rules for converting the ELF output +# of the linker into a binary image that can be loaded directly. +OBJCOPY := $(TARGET_TOOLCHAIN_PREFIX)objcopy $(BINDIR)%.bin: $(BINDIR)% @mkdir -p $(dir $@) $(OBJCOPY) $< $@ -O binary diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc index 6a5fc7895c..f1353c6150 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc @@ -4,10 +4,10 @@ ifeq ($(TARGET), apollo3evb) TARGET_TOOLCHAIN_PREFIX := arm-none-eabi- # Download the Ambiq Apollo3 SDK and set this variable to find the header # files: - APOLLO3_SDK := /home/snease/work/Apollo3-SDK-2018.08.13 + APOLLO3_SDK := ../Apollo3-SDK-2018.08.13 # Need a pointer to the GNU ARM toolchain for crtbegin.o for the fp functions # with the softfp interfaces. - GCC_ARM := /home/snease/work/gcc-arm-none-eabi-7-2018-q2-update/ + GCC_ARM := ../gcc-arm-none-eabi-7-2018-q2-update/ PLATFORM_FLAGS = \ -DPART_apollo3 \ @@ -73,6 +73,8 @@ ifeq ($(TARGET), apollo3evb) -I$(APOLLO3_SDK)/devices/ \ -I$(APOLLO3_SDK)/utils/ +$(warning INCLUDES IS $(INCLUDES)) + # The startup_gcc.c file is an altered version of the examples/hello_world/gcc/startup_gcc.c # file from Ambiq: # - Increase the stack size from 1k to 20k @@ -96,14 +98,4 @@ ifeq ($(TARGET), apollo3evb) tensorflow/contrib/lite/experimental/micro/simple_tensor_allocator_test.cc MICROLITE_TEST_SRCS := $(filter-out $(EXCLUDED_TESTS), $(MICROLITE_TEST_SRCS)) -# These are microcontroller-specific rules for converting the ELF output -# of the linker into a binary image that can be loaded directly. -OBJCOPY := $(TARGET_TOOLCHAIN_PREFIX)objcopy - -# BINDIR isn't defined yet -# Put this at the end of the main makefile -# $(BINDIR)/%.bin: $(BINDIR)/% -# @mkdir -p $(dir $@) -# $(OBJCOPY) $< $@ -O binary - endif diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc index 9bbb7c12a3..fecb98de7c 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc @@ -1,9 +1,9 @@ ifeq ($(VENDORLIB), cmsis-dsp) PREPROCESSOR_TEST_SRCS := \ -tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc \ -tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc \ -tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc \ -tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc \ -tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc \ -tensorflow/contrib/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc +tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc endif -- GitLab From c5e00121e50ca8a52837d205e6da766bd3360f55 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Sun, 4 Nov 2018 15:56:51 -0600 Subject: [PATCH 0019/1765] Forgot to add .gitignores in previous commit, adding now; script to copy apollo3 files --- .../experimental/micro/tools/make/.gitignore | 2 ++ .../tools/make/targets/apollo3evb/.gitignore | 4 +++ .../tools/make/targets/copy_apollo3files.sh | 30 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 tensorflow/lite/experimental/micro/tools/make/.gitignore create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/.gitignore create mode 100755 tensorflow/lite/experimental/micro/tools/make/targets/copy_apollo3files.sh diff --git a/tensorflow/lite/experimental/micro/tools/make/.gitignore b/tensorflow/lite/experimental/micro/tools/make/.gitignore new file mode 100644 index 0000000000..752f078fb5 --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/.gitignore @@ -0,0 +1,2 @@ +downloads +gen diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/.gitignore b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/.gitignore new file mode 100644 index 0000000000..cb646e29d9 --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/.gitignore @@ -0,0 +1,4 @@ +startup_gcc.c +am_*.c +libam*.a + diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/copy_apollo3files.sh b/tensorflow/lite/experimental/micro/tools/make/targets/copy_apollo3files.sh new file mode 100755 index 0000000000..1bab307a73 --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/copy_apollo3files.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +if [ ! -d "../Apollo3-SDK-2018.08.13" ]; then + echo "Apollo 3 SDK does not exist" + echo "Either the SDK has not been downloaded, or this script is not being done from the root of the repository" +else + DEST_DIR="tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb" + AP3_DIR="../Apollo3-SDK-2018.08.13" + cp "$AP3_DIR/boards/apollo3_evb/examples/hello_world/gcc/startup_gcc.c" "$DEST_DIR" + cp "$AP3_DIR/utils/am_util_delay.c" "$DEST_DIR" + cp "$AP3_DIR/utils/am_util_faultisr.c" "$DEST_DIR" + cp "$AP3_DIR/utils/am_util_id.c" "$DEST_DIR" + cp "$AP3_DIR/utils/am_util_stdio.c" "$DEST_DIR" + cp "$AP3_DIR/boards/apollo3_evb/bsp/gcc/bin/libam_bsp.a" "$DEST_DIR" + cp "$AP3_DIR/mcu/apollo3/hal/gcc/bin/libam_hal.a" "$DEST_DIR" +fi -- GitLab From 061415d20914f6ee09b7fec12a8d59f6d81e37df Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Mon, 5 Nov 2018 14:46:41 -0600 Subject: [PATCH 0020/1765] cmd file and py file to update yes/no data; also added the data itself --- .../CMSIS/no_power_spectrum_data.cc | 5 +-- .../CMSIS/yes_power_spectrum_data.cc | 5 +-- .../targets/apollo3evb/get_yesno_data.cmd | 10 ++++++ .../apollo3evb/replace_calculated_data.py | 33 +++++++++++++++++++ 4 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/get_yesno_data.cmd create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/replace_calculated_data.py diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc index cdd7d46c8c..a3e561a8b5 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc @@ -17,7 +17,4 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" -const uint8_t g_no_power_spectrum_data[g_no_power_spectrum_data_size] = { - 255, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; +const uint8_t g_no_power_spectrum_data[g_no_power_spectrum_data_size] = {233,6,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,40}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc index 235a853e68..89edb51040 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc @@ -17,7 +17,4 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" -const uint8_t g_yes_power_spectrum_data[g_yes_power_spectrum_data_size] = { - 8, 89, 8, 0, 0, 0, 0, 0, 0, 0, 0, 4, 13, 1, 6, 23, 20, 6, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; +const uint8_t g_yes_power_spectrum_data[g_yes_power_spectrum_data_size] = {8,88,8,0,0,0,0,0,0,0,0,3,12,0,5,22,19,5,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,1}; diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/get_yesno_data.cmd b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/get_yesno_data.cmd new file mode 100644 index 0000000000..71d5389ee3 --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/get_yesno_data.cmd @@ -0,0 +1,10 @@ +file ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test +target remote localhost:2331 +load ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test +monitor reset +break preprocessor_test.cc:35 +break preprocessor_test.cc:51 +c +dump verilog value yes_calculated_data.txt yes_calculated_data +c +dump verilog value no_calculated_data.txt no_calculated_data diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/replace_calculated_data.py b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/replace_calculated_data.py new file mode 100644 index 0000000000..3c1b0110fc --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/replace_calculated_data.py @@ -0,0 +1,33 @@ +import numpy as np +import re + +# This should be run from make/targets/apollo3evb + +def new_data_to_array(fn): + vals = [] + with open(fn) as f: + for n, line in enumerate(f): + if n is not 0: + vals.extend([str(int(v, 16)) for v in line.split()]) + + return ','.join(vals) + +def replace_data(fn_old, new_data): + patt = '(?<=\{).+?(?=\})' + with open(fn_old,'r') as f: + str_old = f.read() + str_new = re.sub(patt, new_data, str_old, flags=re.DOTALL) + with open(fn_old,'w') as f: + f.write(str_new) + + +yes_old = '../../../../examples/micro_speech/CMSIS/yes_power_spectrum_data.cc' +no_old = '../../../../examples/micro_speech/CMSIS/no_power_spectrum_data.cc' +yes_new = 'yes_calculated_data.txt' +no_new = 'no_calculated_data.txt' + +yes_new_vals = new_data_to_array(yes_new) +no_new_vals = new_data_to_array(no_new) + +replace_data(yes_old, yes_new_vals) +replace_data(no_old, no_new_vals) -- GitLab From 2d8fce07dc8604c29f566418dd2610573f77cc05 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Mon, 5 Nov 2018 14:47:17 -0600 Subject: [PATCH 0021/1765] added script to copy ap3 files to project --- .../targets/apollo3evb/copy_apollo3files.sh | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100755 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/copy_apollo3files.sh diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/copy_apollo3files.sh b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/copy_apollo3files.sh new file mode 100755 index 0000000000..1bab307a73 --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/copy_apollo3files.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +if [ ! -d "../Apollo3-SDK-2018.08.13" ]; then + echo "Apollo 3 SDK does not exist" + echo "Either the SDK has not been downloaded, or this script is not being done from the root of the repository" +else + DEST_DIR="tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb" + AP3_DIR="../Apollo3-SDK-2018.08.13" + cp "$AP3_DIR/boards/apollo3_evb/examples/hello_world/gcc/startup_gcc.c" "$DEST_DIR" + cp "$AP3_DIR/utils/am_util_delay.c" "$DEST_DIR" + cp "$AP3_DIR/utils/am_util_faultisr.c" "$DEST_DIR" + cp "$AP3_DIR/utils/am_util_id.c" "$DEST_DIR" + cp "$AP3_DIR/utils/am_util_stdio.c" "$DEST_DIR" + cp "$AP3_DIR/boards/apollo3_evb/bsp/gcc/bin/libam_bsp.a" "$DEST_DIR" + cp "$AP3_DIR/mcu/apollo3/hal/gcc/bin/libam_hal.a" "$DEST_DIR" +fi -- GitLab From 62d708c3bd3377e8588eddbb8d7940d2a55ca530 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Mon, 5 Nov 2018 14:49:02 -0600 Subject: [PATCH 0022/1765] Using O3 instead of Os since Os was causing stalls --- .../micro/tools/make/targets/apollo3evb_makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc index f1353c6150..0116670615 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc @@ -43,7 +43,7 @@ ifeq ($(TARGET), apollo3evb) -fpermissive \ -nostdlib \ -g \ - -Os + -O3 CXXFLAGS += $(PLATFORM_FLAGS) CCFLAGS += $(PLATFORM_FLAGS) LDFLAGS += \ -- GitLab From e19bd69fa17f2f4b881ca23f46203c241c4f435b Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Mon, 5 Nov 2018 14:49:46 -0600 Subject: [PATCH 0023/1765] moved copy_apollo3files.sh and added gdb *.cmd file for running the preprocessor test --- .../targets/apollo3evb/preprocessor_test.cmd | 4 +++ .../tools/make/targets/copy_apollo3files.sh | 30 ------------------- 2 files changed, 4 insertions(+), 30 deletions(-) create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/preprocessor_test.cmd delete mode 100755 tensorflow/lite/experimental/micro/tools/make/targets/copy_apollo3files.sh diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/preprocessor_test.cmd b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/preprocessor_test.cmd new file mode 100644 index 0000000000..1b1db457fe --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/preprocessor_test.cmd @@ -0,0 +1,4 @@ +file ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test +target remote localhost:2331 +load ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test +monitor reset diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/copy_apollo3files.sh b/tensorflow/lite/experimental/micro/tools/make/targets/copy_apollo3files.sh deleted file mode 100755 index 1bab307a73..0000000000 --- a/tensorflow/lite/experimental/micro/tools/make/targets/copy_apollo3files.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== - -if [ ! -d "../Apollo3-SDK-2018.08.13" ]; then - echo "Apollo 3 SDK does not exist" - echo "Either the SDK has not been downloaded, or this script is not being done from the root of the repository" -else - DEST_DIR="tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb" - AP3_DIR="../Apollo3-SDK-2018.08.13" - cp "$AP3_DIR/boards/apollo3_evb/examples/hello_world/gcc/startup_gcc.c" "$DEST_DIR" - cp "$AP3_DIR/utils/am_util_delay.c" "$DEST_DIR" - cp "$AP3_DIR/utils/am_util_faultisr.c" "$DEST_DIR" - cp "$AP3_DIR/utils/am_util_id.c" "$DEST_DIR" - cp "$AP3_DIR/utils/am_util_stdio.c" "$DEST_DIR" - cp "$AP3_DIR/boards/apollo3_evb/bsp/gcc/bin/libam_bsp.a" "$DEST_DIR" - cp "$AP3_DIR/mcu/apollo3/hal/gcc/bin/libam_hal.a" "$DEST_DIR" -fi -- GitLab From 47c17d63fc1d32c6561874422cd6d5920c4f15f8 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Mon, 5 Nov 2018 17:12:47 -0600 Subject: [PATCH 0024/1765] Added README and added text substitution to prep_apollo3_files.sh --- .../micro/tools/make/targets/apollo3evb/README.md | 13 +++++++++++++ .../{copy_apollo3files.sh => prep_apollo3_files.sh} | 2 ++ 2 files changed, 15 insertions(+) create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md rename tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/{copy_apollo3files.sh => prep_apollo3_files.sh} (92%) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md new file mode 100644 index 0000000000..6108c3c498 --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md @@ -0,0 +1,13 @@ +Follow these steps to get the preprocessor test working on Apollo 3: + +1) Download the SDK to the be at the same level as tensorflow.git +2) Copy and prepare files by running tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh +3) Recompile libarm_cortexM4lf_math.a with the softfp option, and call it libarm_cartexM4lf_math_softfp.a. The original version was compiled with the hard option, and this caused conflicts with existing software. We might be able to fix this in the future +4) Install Segger JLink tools from https://www.segger.com/downloads/jlink/ +5) Compile the preprocessor_test_bin project with the following command: make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=apollo3evb VENDORLIB=cmsis-dsp preprocessor_test_bin +6) Download to the target with JFlashLiteExe with the following settings: + a) Device = AMA3B1KK-KBR + b) Interface = SWD at 1000 kHz + c) Data file = tensorflow/lite/experimental/micro/tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_test.bin + d) Prog Addr = 0x0000C000 +7) Connect to device via serial port (115200 baud) and press reset button. Should see all tests passed. Seeing a discrepance between Windows and Linux testing --> need to debug diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/copy_apollo3files.sh b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh similarity index 92% rename from tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/copy_apollo3files.sh rename to tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh index 1bab307a73..79ce18f11f 100755 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/copy_apollo3files.sh +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh @@ -27,4 +27,6 @@ else cp "$AP3_DIR/utils/am_util_stdio.c" "$DEST_DIR" cp "$AP3_DIR/boards/apollo3_evb/bsp/gcc/bin/libam_bsp.a" "$DEST_DIR" cp "$AP3_DIR/mcu/apollo3/hal/gcc/bin/libam_hal.a" "$DEST_DIR" + sed -i -e '131s/1024/1024\*20/g' "$DEST_DIR/startup_gcc.c" + sed -i -e 's/main/_main/g' "$DEST_DIR/startup_gcc.c" fi -- GitLab From 2b2b01f7ba2a7b131a3015ef9164b85823c8e2bf Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Mon, 5 Nov 2018 17:18:47 -0600 Subject: [PATCH 0025/1765] fixed some markup --- .../tools/make/targets/apollo3evb/README.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md index 6108c3c498..fec4923e0e 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md @@ -1,13 +1,13 @@ Follow these steps to get the preprocessor test working on Apollo 3: -1) Download the SDK to the be at the same level as tensorflow.git -2) Copy and prepare files by running tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh -3) Recompile libarm_cortexM4lf_math.a with the softfp option, and call it libarm_cartexM4lf_math_softfp.a. The original version was compiled with the hard option, and this caused conflicts with existing software. We might be able to fix this in the future -4) Install Segger JLink tools from https://www.segger.com/downloads/jlink/ -5) Compile the preprocessor_test_bin project with the following command: make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=apollo3evb VENDORLIB=cmsis-dsp preprocessor_test_bin -6) Download to the target with JFlashLiteExe with the following settings: - a) Device = AMA3B1KK-KBR - b) Interface = SWD at 1000 kHz - c) Data file = tensorflow/lite/experimental/micro/tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_test.bin - d) Prog Addr = 0x0000C000 -7) Connect to device via serial port (115200 baud) and press reset button. Should see all tests passed. Seeing a discrepance between Windows and Linux testing --> need to debug +1. Download the SDK to the be at the same level as tensorflow.git +2. Copy and prepare files by running tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh +3. Recompile libarm_cortexM4lf_math.a with the softfp option, and call it libarm_cartexM4lf_math_softfp.a. The original version was compiled with the hard option, and this caused conflicts with existing software. We might be able to fix this in the future +4. Install Segger JLink tools from https://www.segger.com/downloads/jlink/ +5. Compile the preprocessor_test_bin project with the following command: make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=apollo3evb VENDORLIB=cmsis-dsp preprocessor_test_bin +6. Download to the target with JFlashLiteExe with the following settings: + 1. Device = AMA3B1KK-KBR + 2. Interface = SWD at 1000 kHz + 3. Data file = tensorflow/lite/experimental/micro/tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_test.bin + 4. Prog Addr = 0x0000C000 +7. Connect to device via serial port (115200 baud) and press reset button. Should see all tests passed. Seeing a discrepance between Windows and Linux testing --> need to debug -- GitLab From 75ef9f1888867cb2943fc0ce75c258c2cdd8f8aa Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Mon, 5 Nov 2018 17:34:03 -0600 Subject: [PATCH 0026/1765] Removed redundant yes/no sample data from the CMSIS directory and changed the Makefile and source to point to the original raw sample data --- .../micro_speech/CMSIS/no_30ms_sample_data.cc | 66 ----------------- .../micro_speech/CMSIS/no_30ms_sample_data.h | 32 --------- .../micro_speech/CMSIS/preprocessor_test.cc | 4 +- .../CMSIS/yes_30ms_sample_data.cc | 70 ------------------- .../micro_speech/CMSIS/yes_30ms_sample_data.h | 32 --------- .../tools/make/targets/cmsis-dsp_makefile.inc | 4 +- 6 files changed, 4 insertions(+), 204 deletions(-) delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc deleted file mode 100644 index 6d9147bd44..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -// See the header for documentation on the meaning of this data. - -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h" - -const int g_no_30ms_sample_data_size = 480; -const int16_t g_no_30ms_sample_data[480] = { - 5713, 5735, 5735, 5737, 5701, 5691, 5656, 5633, 5611, 5552, 5475, - 5394, 5293, 5177, 5064, 4924, 4737, 4599, 4420, 4237, 4048, 3828, - 3623, 3413, 3183, 2915, 2622, 2308, 1980, 1657, 1261, 901, 549, - 205, -85, -383, -688, -969, -1246, -1530, -1850, -2206, -2561, -2915, - -3224, -3482, -3713, -3921, -4107, -4287, -4470, -4660, -4850, -5057, -5239, - -5395, -5540, -5619, -5697, -5724, -5697, -5675, -5633, -5590, -5579, -5530, - -5486, -5442, -5426, -5391, -5348, -5276, -5197, -5124, -5039, -4925, -4808, - -4677, -4581, -4479, -4343, -4218, -4087, -3970, -3858, -3729, -3570, -3384, - -3206, -3020, -2839, -2636, -2453, -2287, -2185, -2154, -1926, -1562, -1223, - -758, -473, -64, 395, 599, 880, 814, 938, 1172, 1498, 1928, - 2127, 2422, 2608, 2841, 2937, 2886, 2815, 2985, 3324, 3757, 4152, - 4481, 4652, 4917, 4965, 4766, 4583, 4328, 4503, 4815, 5118, 5408, - 5682, 5956, 6082, 6055, 5744, 5426, 5341, 5427, 5606, 5882, 6065, - 6226, 6428, 6477, 6385, 6009, 5728, 5552, 5439, 5339, 5200, 5008, - 4947, 4835, 4614, 4330, 3887, 3521, 3111, 2460, 1983, 1297, 650, - 279, -353, -720, -1044, -1518, -1668, -2117, -2496, -2743, -3266, -3607, - -3790, -4149, -4075, -4042, -4096, -3981, -4138, -4226, -4214, -4503, -4455, - -4577, -4642, -4346, -4351, -4270, -4263, -4522, -4521, -4673, -4814, -4731, - -4950, -5011, -5004, -5288, -5341, -5566, -5833, -5783, -5929, -5847, -5765, - -5828, -5644, -5613, -5615, -5428, -5291, -5014, -4554, -4277, -3964, -3854, - -3829, -3612, -3603, -3438, -3137, -2831, -2164, -1438, -939, -330, -156, - 46, 242, 73, 242, 220, 239, 542, 565, 739, 872, 801, - 857, 676, 543, 586, 567, 828, 1142, 1490, 1985, 2508, 2982, - 3438, 3699, 3939, 4069, 4178, 4420, 4622, 4917, 5338, 5801, 6285, - 6658, 6963, 7213, 7233, 7328, 7176, 7038, 7031, 6860, 6957, 6767, - 6599, 6523, 6212, 6147, 6063, 5860, 6020, 6015, 6033, 6184, 5722, - 5607, 5016, 4337, 4063, 3229, 3080, 3006, 2804, 3035, 2541, 2136, - 1879, 1012, 401, -575, -1584, -1930, -2278, -2485, -2477, -2712, -2747, - -2766, -3320, -3592, -4188, -4669, -4672, -4939, -4789, -4426, -4203, -3674, - -3563, -3656, -3759, -4067, -4257, -4522, -4970, -5204, -5237, -5139, -4907, - -4911, -4917, -4921, -5007, -5230, -5654, -6122, -6464, -6733, -6948, -7067, - -6972, -6800, -6520, -6132, -5830, -5382, -5091, -4797, -4546, -4472, -4362, - -4350, -4235, -3851, -3454, -3144, -2735, -2341, -1845, -1262, -958, -549, - -166, 66, 382, 366, 352, 341, 85, -13, -176, -303, -235, - -341, -309, -227, -249, -50, 143, 384, 874, 1149, 1552, 2155, - 2767, 3499, 3994, 4460, 4920, 5288, 5569, 5704, 5881, 6094, 6461, - 6653, 6803, 7115, 7311, 7521, 7612, 7443, 7380, 7124, 6742, 6495, - 5964, 5656, 5415, 5167, 5656, 5813, 6027, 6401, 6351, 6787, 7019, - 6581, 6512, 5965, 5308, 5140, 4336, 4147, 3899, 3398, 3360, 2830, - 2624, 1968, 1026, 395, -699, -1424, -2327, -3006, -3192, -3435, -3337, - -3686, -3513, -3350, -3502, -3261, -3878, -4005, -4063, -4187, -3767, -3598, - -3384, -3300, -3094, -2857, -3023, -3274, -3851, -4352, -4523, -4943, -5477, - -5612, -5682, -5733, -5714, -5965, -6110, -5950, -6158, -6548, -6897, -7165, - -7281, -7352, -7258, -7185, -6659, -5946, -5470, -}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h deleted file mode 100644 index 5299930659..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -// This data was created from the PCM data in a WAV file held in v2 of the -// Speech Commands test dataset, at the path: -// speech_commands_test_set_v0.02/no/f9643d42_nohash_4.wav -// The data was extracted starting at an offset of 8,960, which corresponds to -// the 29th spectrogram slice. It's designed to be used to test the -// preprocessing pipeline, to ensure that the expected spectrogram slice is -// produced given this input. - -#ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_30MS_SAMPLE_DATA_H_ -#define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_30MS_SAMPLE_DATA_H_ - -#include - -extern const int g_no_30ms_sample_data_size; -extern const int16_t g_no_30ms_sample_data[]; - -#endif // TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_30MS_SAMPLE_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc index 3560a17cd4..5986fb4913 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc @@ -15,9 +15,9 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h" #include "tensorflow/lite/c/c_api_internal.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.h" #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.h" #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/testing/micro_test.h" diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc deleted file mode 100644 index 056ee544da..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -// See the header for documentation on the meaning of this data. - -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h" - -const int g_yes_30ms_sample_data_size = 480; -const int16_t g_yes_30ms_sample_data[480] = { - -876, -470, 510, 803, 170, -787, -1568, -1893, -1598, -1027, - -992, -1803, -2610, -2484, -1905, -2113, -3113, -3399, -2267, -1261, - -2007, -3637, -3909, -2340, -893, -1158, -2272, -2486, -1639, -915, - -777, -596, -91, 196, 85, 210, 875, 1373, 1247, 1219, - 1958, 2718, 2328, 1196, 1008, 2350, 3677, 3269, 1503, 366, - 922, 2264, 2810, 1996, 608, -168, 75, 680, 811, 395, - -56, -318, -607, -966, -1108, -925, -613, -368, -369, -919, - -1926, -2460, -1685, -300, 155, -611, -1524, -2204, -3227, -3859, - -2037, 1622, 2382, -2583, -8448, -7544, -84, 4814, 915, -6423, - -7558, -1746, 2515, -59, -4587, -3858, 1260, 3625, 187, -4148, - -3500, 1542, 5467, 4780, 1256, -1127, -403, 2481, 5332, 6346, - 5014, 2536, 1216, 2467, 5039, 6238, 5070, 3381, 3269, 4173, - 3905, 2248, 1586, 3299, 5240, 4362, 1004, -1382, -489, 2113, - 3168, 1620, -742, -1824, -1435, -897, -1058, -1500, -1545, -1398, - -1965, -3266, -4136, -3756, -2609, -1804, -1986, -3087, -4599, -5296, - -4051, -1731, -781, -2228, -4092, -3977, -2325, -1353, -1568, -1490, - -428, 178, -672, -1650, -1058, 749, 2039, 2079, 1540, 897, - 310, 572, 2266, 4265, 4265, 1869, -231, 559, 3332, 4752, - 3229, 768, 101, 1364, 2463, 1984, 819, 411, 723, 675, - -162, -923, -743, -32, 185, -516, -1653, -2359, -2103, -986, - 42, -205, -1702, -2870, -2337, -809, -221, -982, -1544, -946, - -598, -2117, -4291, -4100, -857, 1948, 338, -4799, -7972, -5403, - 173, 2371, -1063, -5533, -5578, -1777, 605, -985, -3249, -2213, - 1184, 2691, 560, -2356, -2288, 1233, 5244, 6441, 4004, 370, - -663, 2555, 7404, 9282, 6573, 2612, 1836, 4662, 7467, 7393, - 5421, 4262, 4741, 5362, 4705, 3163, 2397, 3337, 4887, 4810, - 2254, -749, -1316, 772, 2706, 2016, -573, -2552, -2746, -2012, - -1647, -1978, -2579, -3105, -3473, -3911, -4484, -4891, -4795, -4163, - -3543, -3538, -4275, -5356, -5743, -4637, -2614, -1301, -1825, -3341, - -4011, -2937, -751, 1007, 1245, 235, -639, -61, 1626, 2864, - 2967, 2734, 3013, 3329, 2914, 2312, 2666, 3839, 4308, 3162, - 1453, 768, 1255, 1887, 2006, 1715, 1031, -297, -1660, -1690, - -277, 813, -30, -2137, -3370, -2854, -1553, -593, -413, -1146, - -2567, -3440, -2369, -205, 379, -1258, -2315, -812, 262, -3205, - -8576, -7894, 738, 7492, 1951, -11595, -17098, -6934, 7139, 8065, - -4575, -14199, -8946, 3606, 7504, -547, -8242, -5113, 4406, 8113, - 2134, -5040, -4089, 4157, 10934, 10158, 4167, -565, -192, 4428, - 9765, 12201, 9861, 4512, 1225, 3451, 8483, 10133, 6497, 2574, - 3333, 6806, 6986, 2487, -1214, 623, 5416, 6647, 2204, -3289, - -4556, -1565, 1544, 1525, -1236, -4293, -5695, -5174, -3995, -3403, - -3449, -3750, -4505, -6014, -7296, -6523, -3849, -2096, -3288, -5722, - -6004, -3581, -1497, -1960, -3330, -2800, -434, 964, -111, -1739, - -1136, 1736, 4151, 3736, 1274, -451, 469, 3386, 5833, 5898, - 3646, 1085, 272, 1743, 4061, 5108, 3837, 1490, 246, 967, - 1866, 859, -1069, -974, 1542, 2835, 47, -4285, -5068, -1567, - 1781, 1223, -1997, -4227, -3747, -1720, 41, 245, -1228, -2972, - -2673, 22, 1980, -930, -7721, -11271, -5725, 4974, 8484, -2007, - -16979, -19255, -4670, 11057, 9690, -6417, -17537, -10841, 4262, 9292, -}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h deleted file mode 100644 index cb757e84ba..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -// This data was created from the PCM data in a WAV file held in v2 of the -// Speech Commands test dataset, at the path: -// speech_commands_test_set_v0.02/yes/f2e59fea_nohash_1.wav -// The data was extracted starting at an offset of 8,000, which corresponds to -// the 26th spectrogram slice. It's designed to be used to test the -// preprocessing pipeline, to ensure that the expected spectrogram slice is -// produced given this input. - -#ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_30MS_SAMPLE_DATA_H_ -#define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_30MS_SAMPLE_DATA_H_ - -#include - -extern const int g_yes_30ms_sample_data_size; -extern const int16_t g_yes_30ms_sample_data[]; - -#endif // TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_30MS_SAMPLE_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc index fecb98de7c..54b3393229 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc @@ -1,9 +1,9 @@ ifeq ($(VENDORLIB), cmsis-dsp) PREPROCESSOR_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_30ms_sample_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_30ms_sample_data.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc endif -- GitLab From 9bf90b543f6a00d0f8eb1ab980bb4cbca9036491 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Mon, 5 Nov 2018 17:38:12 -0600 Subject: [PATCH 0027/1765] removed unnecessary debug command in .inc --- .../micro/tools/make/targets/apollo3evb_makefile.inc | 2 -- 1 file changed, 2 deletions(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc index 0116670615..0674f48c6d 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc @@ -73,8 +73,6 @@ ifeq ($(TARGET), apollo3evb) -I$(APOLLO3_SDK)/devices/ \ -I$(APOLLO3_SDK)/utils/ -$(warning INCLUDES IS $(INCLUDES)) - # The startup_gcc.c file is an altered version of the examples/hello_world/gcc/startup_gcc.c # file from Ambiq: # - Increase the stack size from 1k to 20k -- GitLab From 38a3d5ea22ad41eeece92624951132b79357b5a0 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Mon, 5 Nov 2018 17:42:33 -0600 Subject: [PATCH 0028/1765] removed contrib paths in makefile --- .../micro/tools/make/targets/apollo3evb_makefile.inc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc index 0674f48c6d..153a19fcd4 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc @@ -29,7 +29,7 @@ ifeq ($(TARGET), apollo3evb) -mcpu=cortex-m4 \ -mthumb \ -mfpu=fpv4-sp-d16 \ - -mfloat-abi=softfp\ + -mfloat-abi=softfp \ -std=gnu++11 \ -Wvla \ -Wall \ @@ -47,7 +47,7 @@ ifeq ($(TARGET), apollo3evb) CXXFLAGS += $(PLATFORM_FLAGS) CCFLAGS += $(PLATFORM_FLAGS) LDFLAGS += \ - -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp\ + -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp \ -nostartfiles -static \ -Wl,--gc-sections -Wl,--entry,Reset_Handler \ -Wl,--start-group -lm -lc -lgcc -Wl,--end-group \ @@ -89,11 +89,11 @@ ifeq ($(TARGET), apollo3evb) $(MAKEFILE_DIR)/targets/apollo3evb/am_util_id.c \ $(MAKEFILE_DIR)/targets/apollo3evb/am_util_stdio.c - TEST_SCRIPT := tensorflow/contrib/lite/experimental/log_test/test_apollo3evb_binary.sh + TEST_SCRIPT := tensorflow/lite/experimental/log_test/test_apollo3evb_binary.sh # These are tests that don't currently work on the blue pill. EXCLUDED_TESTS := \ - tensorflow/contrib/lite/experimental/micro/micro_interpreter_test.cc \ - tensorflow/contrib/lite/experimental/micro/simple_tensor_allocator_test.cc + tensorflow/lite/experimental/micro/micro_interpreter_test.cc \ + tensorflow/lite/experimental/micro/simple_tensor_allocator_test.cc MICROLITE_TEST_SRCS := $(filter-out $(EXCLUDED_TESTS), $(MICROLITE_TEST_SRCS)) endif -- GitLab From 42321707242771cf28deb1d577dfdd6a17e9eae9 Mon Sep 17 00:00:00 2001 From: Guozhong Zhuang Date: Mon, 12 Nov 2018 15:24:22 -0800 Subject: [PATCH 0029/1765] fix issues related to clang format check --- .../core/kernels/mkl_fused_batch_norm_op.cc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc b/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc index ff46e75a36..685db657e2 100644 --- a/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc +++ b/tensorflow/core/kernels/mkl_fused_batch_norm_op.cc @@ -13,15 +13,14 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ #ifdef INTEL_MKL - -#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" +#include "mkldnn.hpp" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/framework/register_types.h" #include "tensorflow/core/framework/tensor.h" #include "tensorflow/core/framework/tensor_types.h" #include "tensorflow/core/util/mkl_util.h" #include "tensorflow/core/util/tensor_format.h" -#include "mkldnn.hpp" +#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" using mkldnn::batch_normalization_backward; using mkldnn::batch_normalization_forward; @@ -705,9 +704,9 @@ class MklFusedBatchNormOp : public OpKernel { std::memcpy(batch_variance_data, variance_data, depth_ * sizeof(T)); } } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK( context, errors::Aborted("Operation received an exception:", error_msg)); @@ -1029,9 +1028,9 @@ class MklFusedBatchNormGradOp : public OpKernel { reinterpret_cast(diff_weights_data + depth_), depth_ * sizeof(T)); } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK( context, errors::Aborted("Operation received an exception:", error_msg)); -- GitLab From 7b712dcdccb45b958e415166b0a2460dbcda85f4 Mon Sep 17 00:00:00 2001 From: olicht <29300900+olicht@users.noreply.github.com> Date: Sun, 18 Nov 2018 12:29:30 +0200 Subject: [PATCH 0030/1765] Preventing crash when building with local MKL Preventing crash when MKL include dir. contains something else (e.g. fortran defs.). --- third_party/mkl/mkl.BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/mkl/mkl.BUILD b/third_party/mkl/mkl.BUILD index c3a71e4ff9..78c1ed52f4 100644 --- a/third_party/mkl/mkl.BUILD +++ b/third_party/mkl/mkl.BUILD @@ -12,7 +12,7 @@ filegroup( cc_library( name = "mkl_headers", - srcs = glob(["include/*"]), + srcs = glob(["include/*[.cc|.cpp|.cxx|.c++|.C|.c|.h|.hh|.hpp|.ipp|.hxx|.inc|.S|.s|.asm|.a|.lib|.pic.a|.lo|.lo.lib|.pic.lo|.so|.dylib|.dll|.o|.obj|.pic.o]"]), includes = ["include"], visibility = ["//visibility:public"], ) -- GitLab From b3adae061cbea550d63e59b1150bcb092db6cc20 Mon Sep 17 00:00:00 2001 From: olicht <29300900+olicht@users.noreply.github.com> Date: Sun, 18 Nov 2018 12:31:56 +0200 Subject: [PATCH 0031/1765] oops... used `[]` instead of `()` --- third_party/mkl/mkl.BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/mkl/mkl.BUILD b/third_party/mkl/mkl.BUILD index 78c1ed52f4..3f3c9e9336 100644 --- a/third_party/mkl/mkl.BUILD +++ b/third_party/mkl/mkl.BUILD @@ -12,7 +12,7 @@ filegroup( cc_library( name = "mkl_headers", - srcs = glob(["include/*[.cc|.cpp|.cxx|.c++|.C|.c|.h|.hh|.hpp|.ipp|.hxx|.inc|.S|.s|.asm|.a|.lib|.pic.a|.lo|.lo.lib|.pic.lo|.so|.dylib|.dll|.o|.obj|.pic.o]"]), + srcs = glob(["include/*(.cc|.cpp|.cxx|.c++|.C|.c|.h|.hh|.hpp|.ipp|.hxx|.inc|.S|.s|.asm|.a|.lib|.pic.a|.lo|.lo.lib|.pic.lo|.so|.dylib|.dll|.o|.obj|.pic.o)"]), includes = ["include"], visibility = ["//visibility:public"], ) -- GitLab From 16c44a349b1a7c6d3b4e9cfd6094009b4c2e47f1 Mon Sep 17 00:00:00 2001 From: AG Ramesh Date: Fri, 23 Nov 2018 13:08:38 -0800 Subject: [PATCH 0032/1765] Clang format fixes --- tensorflow/core/graph/mkl_layout_pass_test.cc | 1 - tensorflow/core/kernels/mkl_conv_ops.h | 117 ++++++++++-------- 2 files changed, 64 insertions(+), 54 deletions(-) diff --git a/tensorflow/core/graph/mkl_layout_pass_test.cc b/tensorflow/core/graph/mkl_layout_pass_test.cc index 5dbae02889..678864c523 100644 --- a/tensorflow/core/graph/mkl_layout_pass_test.cc +++ b/tensorflow/core/graph/mkl_layout_pass_test.cc @@ -490,7 +490,6 @@ TEST_F(MklLayoutPassTest, NodeRewrite_DepthwiseConv2dNative_Basic) { "node { name: 'C' op: 'DepthwiseConv2dNative'" " attr { key: 'T' value { type: DT_FLOAT } }" " attr { key: 'data_format' value { s: 'NCHW' } }" - " attr { key: 'use_cudnn_on_gpu' value { b: false } }" " attr { key: 'strides' value { list: {i: 1, i:1, i:1, i:1} } }" " attr { key: 'padding' value { s: 'SAME' } }" " attr { key: 'dilations' value { list: {i: 1, i:1, i:1, i:1} } }" diff --git a/tensorflow/core/kernels/mkl_conv_ops.h b/tensorflow/core/kernels/mkl_conv_ops.h index 8caa50d776..3ce54ff093 100644 --- a/tensorflow/core/kernels/mkl_conv_ops.h +++ b/tensorflow/core/kernels/mkl_conv_ops.h @@ -85,7 +85,7 @@ class MklDnnConvUtil { } // Calculate Convolution dilations - virtual inline void GetDilationsInMklOrder(memory::dims *dilations) { + virtual inline void GetDilationsInMklOrder(memory::dims* dilations) { // For now we take the dilation from the second and third dimensions only // (we do not support dilation on the batch or depth dimension). CHECK_NOTNULL(dilations); @@ -196,15 +196,13 @@ class MklDnnConvUtil { filter_shape.DebugString())); for (int i = 0; i < ((strides_.size() == 4) ? 3 : 5); i++) { - OP_REQUIRES(context_, - FastBoundsCheck(filter_shape.dim_size(i), - std::numeric_limits::max()), + OP_REQUIRES(context_, FastBoundsCheck(filter_shape.dim_size(i), + std::numeric_limits::max()), errors::InvalidArgument("filter too large")); } int input_depth = GetTensorDim(input_shape, data_format_, 'C'); - if (strides_.size() == 4) { // Conv2D OP_REQUIRES(context_, input_depth == filter_shape.dim_size(2), errors::InvalidArgument( @@ -212,28 +210,32 @@ class MklDnnConvUtil { input_depth, " vs ", filter_shape.dim_size(2))); // TF filter is always in (rows, cols, in_depth, out_depth) order. - int filter_rows = static_cast(filter_shape.dim_size(0)); - int filter_cols = static_cast(filter_shape.dim_size(1)); - int in_depth = static_cast(filter_shape.dim_size(2)); - int out_depth = static_cast(filter_shape.dim_size(3)); + int filter_rows = + static_cast(filter_shape.dim_size(TF_2DFILTER_DIM_H)); + int filter_cols = + static_cast(filter_shape.dim_size(TF_2DFILTER_DIM_W)); + int filter_in_depth = + static_cast(filter_shape.dim_size(TF_2DFILTER_DIM_I)); + int filter_out_depth = + static_cast(filter_shape.dim_size(TF_2DFILTER_DIM_O)); // MKL-DNN always needs filter in OIHW format for regular convolutions // and GOIHW for grouped/depthwise convolutions, // OIHW = (out_depth, in_depth, rows, cols) // GOIHW = (group, out_depth, in_depth, rows, cols) - // Specifcally for depthwise G=filter_indepth, O=filter_outdepth, I=1 + // Specifically for depthwise G=filer_indepth, O=filter_outdepth, I=1 if (is_Depthwise) { std::vector mkldnn_sizes(5, -1); - mkldnn_sizes[MklDnnDimsGroup::DimGroup_G] = in_depth; - mkldnn_sizes[MklDnnDimsGroup::DimGroup_O] = out_depth; - mkldnn_sizes[MklDnnDimsGroup::DimGroup_I] = 1; - mkldnn_sizes[MklDnnDimsGroup::DimGroup_H] = filter_rows; - mkldnn_sizes[MklDnnDimsGroup::DimGroup_W] = filter_cols; + mkldnn_sizes[MKL_GROUP_FILTER_DIM_G] = filter_in_depth; + mkldnn_sizes[MKL_GROUP_FILTER_DIM_O] = filter_out_depth; + mkldnn_sizes[MKL_GROUP_FILTER_DIM_I] = 1; + mkldnn_sizes[MKL_GROUP_FILTER_DIM_H] = filter_rows; + mkldnn_sizes[MKL_GROUP_FILTER_DIM_W] = filter_cols; *filter_dims = mkldnn_sizes; } else { std::vector mkldnn_sizes(4, -1); - mkldnn_sizes[MklDnnDims::Dim_O] = out_depth; - mkldnn_sizes[MklDnnDims::Dim_I] = in_depth; + mkldnn_sizes[MklDnnDims::Dim_O] = filter_out_depth; + mkldnn_sizes[MklDnnDims::Dim_I] = filter_in_depth; mkldnn_sizes[MklDnnDims::Dim_H] = filter_rows; mkldnn_sizes[MklDnnDims::Dim_W] = filter_cols; @@ -246,17 +248,22 @@ class MklDnnConvUtil { input_depth, " vs ", filter_shape.dim_size(3))); // TF filter is always in (planes, rows, cols, in_depth, out_depth) order. - int filter_planes = static_cast(filter_shape.dim_size(0)); - int filter_rows = static_cast(filter_shape.dim_size(1)); - int filter_cols = static_cast(filter_shape.dim_size(2)); - int in_depth = static_cast(filter_shape.dim_size(3)); - int out_depth = static_cast(filter_shape.dim_size(4)); + int filter_planes = + static_cast(filter_shape.dim_size(TF_3DFILTER_DIM_P)); + int filter_rows = + static_cast(filter_shape.dim_size(TF_3DFILTER_DIM_H)); + int filter_cols = + static_cast(filter_shape.dim_size(TF_3DFILTER_DIM_W)); + int filter_in_depth = + static_cast(filter_shape.dim_size(TF_3DFILTER_DIM_I)); + int filter_out_depth = + static_cast(filter_shape.dim_size(TF_3DFILTER_DIM_O)); // MKL-DNN always needs filter in OIDHW format. // OIDHW = (out_depth, in_depth, planes, rows, cols) std::vector mkldnn_sizes(5, -1); - mkldnn_sizes[MklDnnDims3D::Dim3d_O] = out_depth; - mkldnn_sizes[MklDnnDims3D::Dim3d_I] = in_depth; + mkldnn_sizes[MklDnnDims3D::Dim3d_O] = filter_out_depth; + mkldnn_sizes[MklDnnDims3D::Dim3d_I] = filter_in_depth; mkldnn_sizes[MklDnnDims3D::Dim3d_D] = filter_planes; mkldnn_sizes[MklDnnDims3D::Dim3d_H] = filter_rows; mkldnn_sizes[MklDnnDims3D::Dim3d_W] = filter_cols; @@ -333,12 +340,12 @@ class MklDnnConvUtil { int filter_planes, filter_rows, filter_cols; if (is_Conv2D) { - filter_rows = filter_shape.dim_size(0); - filter_cols = filter_shape.dim_size(1); + filter_rows = filter_shape.dim_size(TF_2DFILTER_DIM_H); + filter_cols = filter_shape.dim_size(TF_2DFILTER_DIM_W); } else { - filter_planes = filter_shape.dim_size(0); - filter_rows = filter_shape.dim_size(1); - filter_cols = filter_shape.dim_size(2); + filter_planes = filter_shape.dim_size(TF_3DFILTER_DIM_P); + filter_rows = filter_shape.dim_size(TF_3DFILTER_DIM_H); + filter_cols = filter_shape.dim_size(TF_3DFILTER_DIM_W); } int stride_planes, stride_rows, stride_cols; @@ -362,15 +369,20 @@ class MklDnnConvUtil { // Output batch is same as input batch. int out_batch = GetTensorDim(input_shape, data_format_, 'N'); int out_depth; - + // TODO add support for 3-D Depthwise - // Output depth is same as last dimension for filters for regular - // convolutions. For depthwise it is in_depth*channel_muliplier + // Output depth is same as last dimension for filters for regular + // convolutions. + // For depthwise it is in_depth * channel_multiplier. The channel_miltipler + // is the last dimension of TF filter for depthwise convolutions. if (is_Depthwise) { - out_depth = (filter_shape.dim_size(2)*filter_shape.dim_size(3)); + out_depth = (filter_shape.dim_size(TF_2DFILTER_DIM_I) * + filter_shape.dim_size(TF_2DFILTER_DIM_O)); } else { - out_depth = filter_shape.dim_size(is_Conv2D ? 3 : 4); + out_depth = filter_shape.dim_size( + is_Conv2D ? static_cast(TF_2DFILTER_DIM_O) + : static_cast(TF_3DFILTER_DIM_O)); } int64 out_rows = 0, out_cols = 0, out_planes = 0; @@ -466,9 +478,9 @@ class MklDnnConvUtil { input_tf_shape.DebugString())); } - GetOutputAndPadSizeInMklOrder(input_tf_shape, filter_tf_shape, strides, + GetOutputAndPadSizeInMklOrder(input_tf_shape, filter_tf_shape, strides, dilations, output_dims_tf_order, - output_dims_mkl_order, pad_l, pad_r, + output_dims_mkl_order, pad_l, pad_r, is_Depthwise); } @@ -483,10 +495,9 @@ class MklDnnConvUtil { inline void GetConvFwdSizesInMklOrder( const TensorShape& input_shape, const TensorShape& filter_shape, memory::dims* input_dims, memory::dims* filter_dims, - memory::dims* strides, memory::dims *dilations, - memory::dims* output_dims_tf_order, - memory::dims* output_dims_mkl_order, memory::dims* pad_l, - memory::dims* pad_r, bool is_Depthwise) { + memory::dims* strides, memory::dims* dilations, + memory::dims* output_dims_tf_order, memory::dims* output_dims_mkl_order, + memory::dims* pad_l, memory::dims* pad_r, bool is_Depthwise) { CHECK_NOTNULL(input_dims); CHECK_NOTNULL(filter_dims); CHECK_NOTNULL(strides); @@ -498,14 +509,14 @@ class MklDnnConvUtil { GetInputSizeInMklOrder(input_shape, input_dims); if (!context_->status().ok()) return; - GetFilterSizeInMklOrder(input_shape, filter_shape, filter_dims, + GetFilterSizeInMklOrder(input_shape, filter_shape, filter_dims, is_Depthwise); if (!context_->status().ok()) return; GetStridesInMklOrder(strides); GetDilationsInMklOrder(dilations); GetOutputAndPadSizeInMklOrder( - input_shape, filter_shape, *strides, *dilations, output_dims_tf_order, - output_dims_mkl_order, pad_l, pad_r, is_Depthwise); + input_shape, filter_shape, *strides, *dilations, output_dims_tf_order, + output_dims_mkl_order, pad_l, pad_r, is_Depthwise); if (!context_->status().ok()) return; } }; @@ -527,17 +538,18 @@ class MklConvBackpropCommonOp : public OpKernel { OP_REQUIRES_OK(context, context->GetAttr("strides", &strides_)); int stride_n = GetTensorDim(strides_, data_format_, 'N'); int stride_c = GetTensorDim(strides_, data_format_, 'C'); - OP_REQUIRES( - context, (stride_n == 1 && stride_c == 1), - errors::InvalidArgument("Current implementation does not yet support " - "strides in the batch and depth dimensions.")); + OP_REQUIRES(context, (stride_n == 1 && stride_c == 1), + errors::InvalidArgument( + "Current implementation does not yet support " + "strides in the batch and depth dimensions.")); OP_REQUIRES_OK(context, context->GetAttr("dilations", &dilations_)); if (strides_.size() == 4) { // Check Conv2D dilations OP_REQUIRES(context, dilations_.size() == 4, - errors::InvalidArgument("Sliding window dilations field must " - "specify 4 dimensions")); + errors::InvalidArgument( + "Sliding window dilations field must " + "specify 4 dimensions")); int dilation_n = GetTensorDim(dilations_, data_format_, 'N'); int dilation_c = GetTensorDim(dilations_, data_format_, 'C'); int dilation_h = GetTensorDim(dilations_, data_format_, 'H'); @@ -562,7 +574,6 @@ class MklConvBackpropCommonOp : public OpKernel { TensorFormat data_format_; // NCHW or NHWC }; - ///////////////////////////////////////////////////////////////////// /// Dummy Mkl op that is just used for operators that are intermediate /// output of node fusion in the graph @@ -576,9 +587,9 @@ class MklDummyOp : public OpKernel { explicit MklDummyOp(OpKernelConstruction* context) : OpKernel(context) {} void Compute(OpKernelContext* context) override { - TF_CHECK_OK( - errors::Unimplemented("This is a dummy op." - "It should not have been invoked.")); + TF_CHECK_OK(errors::Unimplemented( + "This is a dummy op." + "It should not have been invoked.")); } }; -- GitLab From 60b303fcd3c5f21481de7dfa1cbe154739ded5fb Mon Sep 17 00:00:00 2001 From: AG Ramesh Date: Fri, 23 Nov 2018 13:18:47 -0800 Subject: [PATCH 0033/1765] Fixed error caused by merge --- tensorflow/core/util/mkl_util.h | 38 ++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/tensorflow/core/util/mkl_util.h b/tensorflow/core/util/mkl_util.h index 6ce8c2cbeb..7c183d30ab 100644 --- a/tensorflow/core/util/mkl_util.h +++ b/tensorflow/core/util/mkl_util.h @@ -86,12 +86,9 @@ namespace tensorflow { // For use with MKL ML, has been deprecated typedef enum { W = 0, H = 1, C = 2, N = 3 } MklDims; -<<<<<<< HEAD -======= // The dimensions order that MKL DNN internally uses for 2D activations // [Batch, Channel, Height, Width] and // for 2D filters [Out_Channel, In_Channel, Height, Width]. ->>>>>>> master typedef enum { Dim_N = 0, Dim_C = 1, @@ -114,23 +111,38 @@ typedef enum { Dim3d_I = 1 } MklDnnDims3D; -<<<<<<< HEAD -// Filter Dimensions for grouped convolution. +// Enum for the order of dimensions of a TF 2D filter with shape [filter_height, filter_width, in_channels, out_channels] typedef enum { - DimGroup_G = 0, - DimGroup_O = 1, - DimGroup_I = 2, - DimGroup_H = 3, - DimGroup_W = 4 -} MklDnnDimsGroup; -======= + TF_2DFILTER_DIM_H = 0, + TF_2DFILTER_DIM_W = 1, + TF_2DFILTER_DIM_I = 2, + TF_2DFILTER_DIM_O = 3 +} TFFilterDims2d; + +// Enum for the order of dimensions of a TF 3D filter with shape [filter_depth, filter_height, filter_width, in_channels, out_channels] +typedef enum { + TF_3DFILTER_DIM_P = 0, + TF_3DFILTER_DIM_H = 1, + TF_3DFILTER_DIM_W = 2, + TF_3DFILTER_DIM_I = 3, + TF_3DFILTER_DIM_O = 4 +} TFFilterDims3d; + +// The dimensions order that MKL DNN requires for the filter in a grouped convolution (2D only) +typedef enum { + MKL_GROUP_FILTER_DIM_G = 0, + MKL_GROUP_FILTER_DIM_O = 1, + MKL_GROUP_FILTER_DIM_I = 2, + MKL_GROUP_FILTER_DIM_H = 3, + MKL_GROUP_FILTER_DIM_W = 4 +} MklDnnFilterGroupDims; + // Enum used to templatize MklOp kernel implementations // that support both fp32 and int8 versions. enum class MklQuantization { QUANTIZED_VERSION, FP_VERSION, }; ->>>>>>> master static const int kSmallBatchSize = 32; -- GitLab From 6457987ba81af02eee61283e321a2e6184fb5419 Mon Sep 17 00:00:00 2001 From: AG Ramesh Date: Fri, 23 Nov 2018 15:04:27 -0800 Subject: [PATCH 0034/1765] More clang format fixes --- tensorflow/core/graph/mkl_layout_pass.cc | 2 +- tensorflow/core/graph/mkl_layout_pass_test.cc | 12 +- .../core/kernels/mkl_conv_grad_filter_ops.cc | 209 +++++++++--------- .../core/kernels/mkl_conv_grad_input_ops.cc | 161 +++++++------- tensorflow/core/kernels/mkl_conv_ops.cc | 75 +++---- tensorflow/core/kernels/mkl_conv_ops.h | 21 +- tensorflow/core/util/mkl_util.h | 59 ++--- 7 files changed, 279 insertions(+), 260 deletions(-) diff --git a/tensorflow/core/graph/mkl_layout_pass.cc b/tensorflow/core/graph/mkl_layout_pass.cc index 089d3f0ae0..b8b2354ce4 100644 --- a/tensorflow/core/graph/mkl_layout_pass.cc +++ b/tensorflow/core/graph/mkl_layout_pass.cc @@ -1616,7 +1616,7 @@ void MklLayoutRewritePass::CopyAttrsConv(const Node* orig_node, } void MklLayoutRewritePass::CopyAttrsConv2DDepthwise(const Node* orig_node, - NodeBuilder* nb) { + NodeBuilder* nb) { DataType T; string data_format; string padding; diff --git a/tensorflow/core/graph/mkl_layout_pass_test.cc b/tensorflow/core/graph/mkl_layout_pass_test.cc index 678864c523..4403c6d0b0 100644 --- a/tensorflow/core/graph/mkl_layout_pass_test.cc +++ b/tensorflow/core/graph/mkl_layout_pass_test.cc @@ -496,14 +496,14 @@ TEST_F(MklLayoutPassTest, NodeRewrite_DepthwiseConv2dNative_Basic) { " input: ['A', 'B']}" "node { name: 'D' op: 'Zeta' attr { key: 'T' value { type: DT_FLOAT } }" " input: ['B', 'C'] }"); - EXPECT_EQ(DoMklLayoutOptimizationPass(), - "A(Input);B(Input);C(_MklDepthwiseConv2dNative);D(Zeta);DMT/_0(Const);" - "DMT/_1(Const)|A->C;A:control->DMT/_0:control;" - "A:control->DMT/_1:control;B->C:1;B->D;C->D:1;DMT/_0->C:2;" - "DMT/_1->C:3"); + EXPECT_EQ( + DoMklLayoutOptimizationPass(), + "A(Input);B(Input);C(_MklDepthwiseConv2dNative);D(Zeta);DMT/_0(Const);" + "DMT/_1(Const)|A->C;A:control->DMT/_0:control;" + "A:control->DMT/_1:control;B->C:1;B->D;C->D:1;DMT/_0->C:2;" + "DMT/_1->C:3"); } - // 2 Conv2D Ops in sequence. Both should get transformed and 1st Conv2D will // have 2 outputs, both of which will be inputs to next Conv2D. TEST_F(MklLayoutPassTest, NodeRewrite_Conv2D_Positive1) { diff --git a/tensorflow/core/kernels/mkl_conv_grad_filter_ops.cc b/tensorflow/core/kernels/mkl_conv_grad_filter_ops.cc index 031176022f..731df00c94 100644 --- a/tensorflow/core/kernels/mkl_conv_grad_filter_ops.cc +++ b/tensorflow/core/kernels/mkl_conv_grad_filter_ops.cc @@ -59,17 +59,20 @@ struct MklConvBwdFilterParams { memory::dims padding_right; padding_kind padding; - MklConvBwdFilterParams(memory::dims src_dims, - memory::dims diff_filter_dims, memory::dims diff_bias_dims, - memory::dims diff_dst_dims, memory::dims strides, - memory::dims dilations, memory::dims padding_left, - memory::dims padding_right, padding_kind padding) : - src_dims(src_dims), diff_filter_dims(diff_filter_dims), - diff_bias_dims(diff_bias_dims), diff_dst_dims(diff_dst_dims), - strides(strides), dilations(dilations), - padding_left(padding_left), padding_right(padding_right), - padding(padding) { - } + MklConvBwdFilterParams(memory::dims src_dims, memory::dims diff_filter_dims, + memory::dims diff_bias_dims, + memory::dims diff_dst_dims, memory::dims strides, + memory::dims dilations, memory::dims padding_left, + memory::dims padding_right, padding_kind padding) + : src_dims(src_dims), + diff_filter_dims(diff_filter_dims), + diff_bias_dims(diff_bias_dims), + diff_dst_dims(diff_dst_dims), + strides(strides), + dilations(dilations), + padding_left(padding_left), + padding_right(padding_right), + padding(padding) {} }; template @@ -93,7 +96,7 @@ class MklConvBwdFilterPrimitive : public MklPrimitive { // diff_bias_data: output data buffer of diff_bias // diff_dst_data: input data buffer of diff_dst void Execute(const T* src_data, const T* diff_filter_data, - const T* diff_bias_data, const T* diff_dst_data) { + const T* diff_bias_data, const T* diff_dst_data) { context_.src_mem->set_data_handle( static_cast(const_cast(src_data))); context_.diff_filter_mem->set_data_handle( @@ -116,8 +119,8 @@ class MklConvBwdFilterPrimitive : public MklPrimitive { // src_data: input data buffer of src // diff_filter_data: output data buffer of diff_filter // diff_dst_data: input data buffer of diff_dst - void Execute(const T* src_data, - const T* diff_filter_data, const T* diff_dst_data) { + void Execute(const T* src_data, const T* diff_filter_data, + const T* diff_dst_data) { context_.src_mem->set_data_handle( static_cast(const_cast(src_data))); context_.diff_filter_mem->set_data_handle( @@ -133,9 +136,7 @@ class MklConvBwdFilterPrimitive : public MklPrimitive { return; } - memory::format GetSrcMemoryFormat() const { - return context_.src_fmt; - } + memory::format GetSrcMemoryFormat() const { return context_.src_fmt; } memory::format GetDiffDstMemoryFormat() const { return context_.diff_dst_fmt; @@ -185,37 +186,42 @@ class MklConvBwdFilterPrimitive : public MklPrimitive { std::shared_ptr bwd_filter_stream; std::vector bwd_filter_primitives; - ConvBwdFilterContext() : - src_fmt(memory::format::any), - diff_dst_fmt(memory::format::any), - diff_filter_fmt(memory::format::any), - src_mem(nullptr), diff_filter_mem(nullptr), - diff_bias_mem(nullptr), diff_dst_mem(nullptr), - bwd_filter_desc(nullptr), fwd_desc(nullptr), fwd_pd(nullptr), - src_md(nullptr), diff_filter_md(nullptr), - diff_bias_md(nullptr), diff_dst_md(nullptr), - bwd_filter_stream(nullptr) { - } + ConvBwdFilterContext() + : src_fmt(memory::format::any), + diff_dst_fmt(memory::format::any), + diff_filter_fmt(memory::format::any), + src_mem(nullptr), + diff_filter_mem(nullptr), + diff_bias_mem(nullptr), + diff_dst_mem(nullptr), + bwd_filter_desc(nullptr), + fwd_desc(nullptr), + fwd_pd(nullptr), + src_md(nullptr), + diff_filter_md(nullptr), + diff_bias_md(nullptr), + diff_dst_md(nullptr), + bwd_filter_stream(nullptr) {} }; // Setup Conv2d backward filter (weights) primitives. void Setup(const MklConvBwdFilterParams& convBwdFilterDims) { // create memory descriptors for convolution data w/ no specified format - context_.src_md.reset(new memory::desc({convBwdFilterDims.src_dims}, - MklDnnType(), memory::format::any)); + context_.src_md.reset(new memory::desc( + {convBwdFilterDims.src_dims}, MklDnnType(), memory::format::any)); - context_.diff_dst_md.reset(new memory::desc( - {convBwdFilterDims.diff_dst_dims}, - MklDnnType(), memory::format::any)); + context_.diff_dst_md.reset( + new memory::desc({convBwdFilterDims.diff_dst_dims}, MklDnnType(), + memory::format::any)); - context_.diff_filter_md.reset(new memory::desc( - {convBwdFilterDims.diff_filter_dims}, - MklDnnType(), memory::format::any)); + context_.diff_filter_md.reset( + new memory::desc({convBwdFilterDims.diff_filter_dims}, MklDnnType(), + memory::format::any)); if (!convBwdFilterDims.diff_bias_dims.empty()) - context_.diff_bias_md.reset(new memory::desc( - {convBwdFilterDims.diff_bias_dims}, - MklDnnType(), memory::format::x)); + context_.diff_bias_md.reset( + new memory::desc({convBwdFilterDims.diff_bias_dims}, MklDnnType(), + memory::format::x)); // create a convolution if (!convBwdFilterDims.diff_bias_dims.empty()) { @@ -226,8 +232,7 @@ class MklConvBwdFilterPrimitive : public MklPrimitive { convBwdFilterDims.padding_left, convBwdFilterDims.padding_right, convBwdFilterDims.padding)); } else { - context_.bwd_filter_desc.reset( - new convolution_backward_weights::desc( + context_.bwd_filter_desc.reset(new convolution_backward_weights::desc( convolution_direct, *context_.src_md, *context_.diff_filter_md, *context_.diff_dst_md, convBwdFilterDims.strides, convBwdFilterDims.dilations, convBwdFilterDims.padding_left, @@ -236,18 +241,18 @@ class MklConvBwdFilterPrimitive : public MklPrimitive { // create fwd primitive_desc context_.fwd_desc.reset(new convolution_forward::desc( - prop_kind::forward, convolution_direct, - *context_.src_md, *context_.diff_filter_md, *context_.diff_dst_md, - convBwdFilterDims.strides, - convBwdFilterDims.dilations, convBwdFilterDims.padding_left, - convBwdFilterDims.padding_right, convBwdFilterDims.padding)); + prop_kind::forward, convolution_direct, *context_.src_md, + *context_.diff_filter_md, *context_.diff_dst_md, + convBwdFilterDims.strides, convBwdFilterDims.dilations, + convBwdFilterDims.padding_left, convBwdFilterDims.padding_right, + convBwdFilterDims.padding)); context_.fwd_pd.reset(new convolution_forward::primitive_desc( *context_.fwd_desc, cpu_engine_)); // create backward conv primitive_desc context_.bwd_filter_pd.reset( new convolution_backward_weights::primitive_desc( - *context_.bwd_filter_desc, cpu_engine_, *context_.fwd_pd)); + *context_.bwd_filter_desc, cpu_engine_, *context_.fwd_pd)); // store the expected memory format auto bwd_filter_pd = context_.bwd_filter_pd.get(); @@ -259,25 +264,28 @@ class MklConvBwdFilterPrimitive : public MklPrimitive { bwd_filter_pd->diff_dst_primitive_desc().desc().data.format); // create memory primitive based on dummy data - context_.src_mem.reset(new memory( - bwd_filter_pd->src_primitive_desc(), DummyData)); - context_.diff_filter_mem.reset(new memory( - bwd_filter_pd->diff_weights_primitive_desc(), DummyData)); - context_.diff_dst_mem.reset(new memory( - bwd_filter_pd->diff_dst_primitive_desc(), DummyData)); + context_.src_mem.reset( + new memory(bwd_filter_pd->src_primitive_desc(), DummyData)); + context_.diff_filter_mem.reset( + new memory(bwd_filter_pd->diff_weights_primitive_desc(), DummyData)); + context_.diff_dst_mem.reset( + new memory(bwd_filter_pd->diff_dst_primitive_desc(), DummyData)); // create convolution primitive and add it to net if (!convBwdFilterDims.diff_bias_dims.empty()) { - context_.diff_bias_mem.reset(new memory( - {{{convBwdFilterDims.diff_bias_dims}, MklDnnType(), - memory::format::x}, cpu_engine_}, DummyData)); + context_.diff_bias_mem.reset( + new memory({{{convBwdFilterDims.diff_bias_dims}, + MklDnnType(), + memory::format::x}, + cpu_engine_}, + DummyData)); context_.conv_bwd_filter.reset(new convolution_backward_weights( *context_.bwd_filter_pd, *context_.src_mem, *context_.diff_dst_mem, *context_.diff_filter_mem, *context_.diff_bias_mem)); } else { context_.conv_bwd_filter.reset(new convolution_backward_weights( - *context_.bwd_filter_pd, *context_.src_mem, - *context_.diff_dst_mem, *context_.diff_filter_mem)); + *context_.bwd_filter_pd, *context_.src_mem, *context_.diff_dst_mem, + *context_.diff_filter_mem)); } context_.bwd_filter_primitives.push_back(*context_.conv_bwd_filter); @@ -298,13 +306,13 @@ class MklConvBwdFilterPrimitiveFactory : public MklPrimitiveFactory { conv_bwd_filter = new MklConvBwdFilterPrimitive(convBwdFilterDims); } else { // look into the pool for reusable primitive - conv_bwd_filter = dynamic_cast*> ( - MklConvBwdFilterPrimitiveFactory::GetInstance().GetConvBwdFilter( - convBwdFilterDims)); + conv_bwd_filter = dynamic_cast*>( + MklConvBwdFilterPrimitiveFactory::GetInstance().GetConvBwdFilter( + convBwdFilterDims)); - if (conv_bwd_filter == nullptr) { - conv_bwd_filter = new MklConvBwdFilterPrimitive(convBwdFilterDims); - MklConvBwdFilterPrimitiveFactory::GetInstance().SetConvBwdFilter( + if (conv_bwd_filter == nullptr) { + conv_bwd_filter = new MklConvBwdFilterPrimitive(convBwdFilterDims); + MklConvBwdFilterPrimitiveFactory::GetInstance().SetConvBwdFilter( convBwdFilterDims, conv_bwd_filter); } } @@ -396,8 +404,8 @@ class MklConvCustomBackpropFilterOp diff_dst_tf_shape.num_elements() == 0) { MklDnnShape diff_filter_mkl_shape; diff_filter_mkl_shape.SetMklTensor(false); - TensorShape diff_filter_tf_shape = GetOutputTfShape( - src_tf_shape, filter_tf_shape, diff_dst_tf_shape); + TensorShape diff_filter_tf_shape = + GetOutputTfShape(src_tf_shape, filter_tf_shape, diff_dst_tf_shape); const int kOutputIdx = 0; AllocateOutputSetMklShape(context, kOutputIdx, &diff_filter_tensor, diff_filter_tf_shape, diff_filter_mkl_shape); @@ -414,17 +422,17 @@ class MklConvCustomBackpropFilterOp // By default, all dims are in MKL order. Only dims in TF order // are those with prefix tf_order. memory::dims diff_dst_dims, fwd_src_dims, fwd_filter_dims; - memory::dims padding_left, padding_right, dilations, - strides, fwd_dst_dims; + memory::dims padding_left, padding_right, dilations, strides, + fwd_dst_dims; memory::dims fwd_dst_dims_tf_order; // Get forward convolution parameters. MklDnnConvUtil conv_utl(context, this->strides_, this->padding_, - this->data_format_, this->dilations_); + this->data_format_, this->dilations_); conv_utl.GetConvFwdSizesInMklOrder( src_tf_shape, filter_tf_shape, &fwd_src_dims, &fwd_filter_dims, - &strides, &dilations, &fwd_dst_dims_tf_order, - &fwd_dst_dims, &padding_left, &padding_right, false); + &strides, &dilations, &fwd_dst_dims_tf_order, &fwd_dst_dims, + &padding_left, &padding_right, false); if (!context->status().ok()) return; auto tf_fmt = is_Conv2D @@ -439,10 +447,10 @@ class MklConvCustomBackpropFilterOp conv_utl.GetInputSizeInMklOrder(diff_dst_tf_shape, &diff_dst_dims); if (!context->status().ok()) return; - auto diff_dst_md = diff_dst_mkl_shape.IsMklTensor() - ? diff_dst_mkl_shape.GetMklLayout() - : memory::desc(diff_dst_dims, - MklDnnType(), tf_fmt); + auto diff_dst_md = + diff_dst_mkl_shape.IsMklTensor() + ? diff_dst_mkl_shape.GetMklLayout() + : memory::desc(diff_dst_dims, MklDnnType(), tf_fmt); memory::dims diff_bias_dims = {}; int64 depth = 0; @@ -456,9 +464,10 @@ class MklConvCustomBackpropFilterOp for (int i = 0; i < dilations.size(); i++) dilations[i] -= 1; MklConvBwdFilterPrimitive* conv_bwd_filter = nullptr; - MklConvBwdFilterParams convBwdFilterDims(fwd_src_dims, fwd_filter_dims, - diff_bias_dims, diff_dst_dims, strides, dilations, padding_left, - padding_right, TFPaddingToMklDnnPadding(this->padding_)); + MklConvBwdFilterParams convBwdFilterDims( + fwd_src_dims, fwd_filter_dims, diff_bias_dims, diff_dst_dims, strides, + dilations, padding_left, padding_right, + TFPaddingToMklDnnPadding(this->padding_)); // MKL DNN allocates large buffers when a conv gradient filter primtive is // created. So we don't cache conv backward primitives when the env @@ -502,32 +511,30 @@ class MklConvCustomBackpropFilterOp } // check if src and diff_dst need reorder - T *src_data = nullptr; + T* src_data = nullptr; if (fwd_src_md.data.format != conv_bwd_filter->GetSrcMemoryFormat()) { src.SetUsrMem(fwd_src_md, &src_tensor); src.CheckReorderToOpMem(bwd_filter_pd->src_primitive_desc()); src_data = static_cast(src.GetOpMem().get_data_handle()); } else { - src_data = static_cast(const_cast( - src_tensor.flat().data())); + src_data = static_cast(const_cast(src_tensor.flat().data())); } - T *diff_dst_data = nullptr; + T* diff_dst_data = nullptr; if (diff_dst_md.data.format != conv_bwd_filter->GetDiffDstMemoryFormat()) { diff_dst.SetUsrMem(diff_dst_md, &diff_dst_tensor); diff_dst.CheckReorderToOpMem(bwd_filter_pd->diff_dst_primitive_desc()); - diff_dst_data = static_cast( - diff_dst.GetOpMem().get_data_handle()); + diff_dst_data = static_cast(diff_dst.GetOpMem().get_data_handle()); } else { - diff_dst_data = static_cast(const_cast( - diff_dst_tensor.flat().data())); + diff_dst_data = + static_cast(const_cast(diff_dst_tensor.flat().data())); } // For backward filter, convert diff_filter back to Tensorflow layout // Here we prepare to reorder op memory back to user memory bool diff_filter_reorder_required = false; - T *diff_filter_data = nullptr; + T* diff_filter_data = nullptr; if (GetOutputFormat(tf_fmt) != conv_bwd_filter->GetDiffFilterMemoryFormat()) { // Allocate diff filter tensor as Tensorflow layout @@ -535,18 +542,18 @@ class MklConvCustomBackpropFilterOp diff_filter_tensor); diff_filter_reorder_required = true; diff_filter.PrepareReorderToUserMemIfReq( - bwd_filter_pd->diff_weights_primitive_desc()); - diff_filter_data = static_cast( - diff_filter.GetOpMem().get_data_handle()); + bwd_filter_pd->diff_weights_primitive_desc()); + diff_filter_data = + static_cast(diff_filter.GetOpMem().get_data_handle()); } else { - diff_filter_data = static_cast(const_cast( - diff_filter_tensor->flat().data())); + diff_filter_data = static_cast( + const_cast(diff_filter_tensor->flat().data())); } // Execute convolution filter bwd if (biasEnabled) { - T* diff_bias_data = static_cast(const_cast( - diff_bias_tensor->flat().data())); + T* diff_bias_data = + static_cast(const_cast(diff_bias_tensor->flat().data())); conv_bwd_filter->Execute(src_data, diff_filter_data, diff_bias_data, diff_dst_data); } else { @@ -561,9 +568,9 @@ class MklConvCustomBackpropFilterOp // delete primitive since it is not cached. if (do_not_cache) delete conv_bwd_filter; } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK( context, errors::Aborted("Operation received an exception:", error_msg)); @@ -598,7 +605,9 @@ class MklConvCustomBackpropFilterOp TensorShape filter_tf_shape; CHECK_EQ(TensorShapeUtils::IsVector(filter_tensor.shape()), true); CHECK_EQ(TensorShapeUtils::MakeShape(filter_tensor.vec(), - &filter_tf_shape).ok(), true); + &filter_tf_shape) + .ok(), + true); return filter_tf_shape; } @@ -659,8 +668,8 @@ class MklConvCustomBackpropFilterOp MklDnnShape bias_grad_mkl_shape; bias_grad_mkl_shape.SetMklTensor(false); - AllocateOutputSetMklShape(context, 1, bias_grad_tensor, - bias_grad_shape, bias_grad_mkl_shape); + AllocateOutputSetMklShape(context, 1, bias_grad_tensor, bias_grad_shape, + bias_grad_mkl_shape); } }; diff --git a/tensorflow/core/kernels/mkl_conv_grad_input_ops.cc b/tensorflow/core/kernels/mkl_conv_grad_input_ops.cc index 3a66af4233..e9236656fb 100644 --- a/tensorflow/core/kernels/mkl_conv_grad_input_ops.cc +++ b/tensorflow/core/kernels/mkl_conv_grad_input_ops.cc @@ -61,16 +61,18 @@ struct MklConvBwdInputParams { memory::dims padding_right; padding_kind padding; - MklConvBwdInputParams(memory::dims diff_src_dims, - memory::dims filter_dims, memory::dims diff_dst_dims, - memory::dims strides, memory::dims dilations, - memory::dims padding_left, memory::dims padding_right, - padding_kind padding) : - diff_src_dims(diff_src_dims), filter_dims(filter_dims), - diff_dst_dims(diff_dst_dims), strides(strides), - dilations(dilations), padding_left(padding_left), - padding_right(padding_right), padding(padding) { - } + MklConvBwdInputParams(memory::dims diff_src_dims, memory::dims filter_dims, + memory::dims diff_dst_dims, memory::dims strides, + memory::dims dilations, memory::dims padding_left, + memory::dims padding_right, padding_kind padding) + : diff_src_dims(diff_src_dims), + filter_dims(filter_dims), + diff_dst_dims(diff_dst_dims), + strides(strides), + dilations(dilations), + padding_left(padding_left), + padding_right(padding_right), + padding(padding) {} }; template @@ -93,8 +95,8 @@ class MklConvBwdInputPrimitive : public MklPrimitive { // filter_data: input data buffer of filter (weights) // diff_dst_data: input data buffer of dst // Bias does not matter here - void Execute(const T* diff_src_data, - const T* filter_data, const T* diff_dst_data) { + void Execute(const T* diff_src_data, const T* filter_data, + const T* diff_dst_data) { context_.diff_src_mem->set_data_handle( static_cast(const_cast(diff_src_data))); context_.filter_mem->set_data_handle( @@ -111,9 +113,7 @@ class MklConvBwdInputPrimitive : public MklPrimitive { return; } - memory::format GetFilterMemoryFormat() const { - return context_.filter_fmt; - } + memory::format GetFilterMemoryFormat() const { return context_.filter_fmt; } memory::format GetDiffDstMemoryFormat() const { return context_.diff_dst_fmt; @@ -155,27 +155,33 @@ class MklConvBwdInputPrimitive : public MklPrimitive { std::shared_ptr bwd_input_stream; std::vector bwd_input_primitives; - ConvBwdInputContext() : - filter_fmt(memory::format::any), diff_dst_fmt(memory::format::any), - diff_src_mem(nullptr), filter_mem(nullptr), diff_dst_mem(nullptr), - bwd_input_pd(nullptr), conv_bwd_input(nullptr), - bwd_input_desc(nullptr), fwd_desc(nullptr), fwd_pd(nullptr), - diff_src_md(nullptr), filter_md(nullptr), diff_dst_md(nullptr), - bwd_input_stream(nullptr) { - } + ConvBwdInputContext() + : filter_fmt(memory::format::any), + diff_dst_fmt(memory::format::any), + diff_src_mem(nullptr), + filter_mem(nullptr), + diff_dst_mem(nullptr), + bwd_input_pd(nullptr), + conv_bwd_input(nullptr), + bwd_input_desc(nullptr), + fwd_desc(nullptr), + fwd_pd(nullptr), + diff_src_md(nullptr), + filter_md(nullptr), + diff_dst_md(nullptr), + bwd_input_stream(nullptr) {} }; void Setup(const MklConvBwdInputParams& convBwdInputDims) { // create memory descriptors for convolution data w/ no specified format - context_.diff_src_md.reset(new memory::desc( - {convBwdInputDims.diff_src_dims}, - MklDnnType(), memory::format::any)); + context_.diff_src_md.reset( + new memory::desc({convBwdInputDims.diff_src_dims}, MklDnnType(), + memory::format::any)); context_.filter_md.reset(new memory::desc( - {convBwdInputDims.filter_dims}, - MklDnnType(), memory::format::any)); - context_.diff_dst_md.reset(new memory::desc( - {convBwdInputDims.diff_dst_dims}, - MklDnnType(), memory::format::any)); + {convBwdInputDims.filter_dims}, MklDnnType(), memory::format::any)); + context_.diff_dst_md.reset( + new memory::desc({convBwdInputDims.diff_dst_dims}, MklDnnType(), + memory::format::any)); // create convolution primitives context_.bwd_input_desc.reset(new convolution_backward_data::desc( @@ -184,9 +190,9 @@ class MklConvBwdInputPrimitive : public MklPrimitive { convBwdInputDims.dilations, convBwdInputDims.padding_left, convBwdInputDims.padding_right, convBwdInputDims.padding)); - context_.fwd_desc.reset(new convolution_forward::desc(prop_kind::forward, - convolution_direct, *context_.diff_src_md, *context_.filter_md, - *context_.diff_dst_md, convBwdInputDims.strides, + context_.fwd_desc.reset(new convolution_forward::desc( + prop_kind::forward, convolution_direct, *context_.diff_src_md, + *context_.filter_md, *context_.diff_dst_md, convBwdInputDims.strides, convBwdInputDims.dilations, convBwdInputDims.padding_left, convBwdInputDims.padding_right, convBwdInputDims.padding)); @@ -194,8 +200,7 @@ class MklConvBwdInputPrimitive : public MklPrimitive { *context_.fwd_desc, cpu_engine_)); // create backward conv prim desc - context_.bwd_input_pd.reset( - new convolution_backward_data::primitive_desc( + context_.bwd_input_pd.reset(new convolution_backward_data::primitive_desc( *context_.bwd_input_desc, cpu_engine_, *context_.fwd_pd)); // create memory primitive based on dummy data @@ -207,15 +212,21 @@ class MklConvBwdInputPrimitive : public MklPrimitive { context_.bwd_input_pd.get()->diff_dst_primitive_desc(), DummyData)); // store the expected memory format - context_.filter_fmt = static_cast( - context_.bwd_input_pd.get()->weights_primitive_desc().desc().data.format); - context_.diff_dst_fmt = static_cast( - context_.bwd_input_pd.get()->diff_dst_primitive_desc().desc().data.format); + context_.filter_fmt = + static_cast(context_.bwd_input_pd.get() + ->weights_primitive_desc() + .desc() + .data.format); + context_.diff_dst_fmt = + static_cast(context_.bwd_input_pd.get() + ->diff_dst_primitive_desc() + .desc() + .data.format); // create convolution primitive and add it to net context_.conv_bwd_input.reset(new convolution_backward_data( - *context_.bwd_input_pd, *context_.diff_dst_mem, - *context_.filter_mem, *context_.diff_src_mem)); + *context_.bwd_input_pd, *context_.diff_dst_mem, *context_.filter_mem, + *context_.diff_src_mem)); context_.bwd_input_primitives.push_back(*context_.conv_bwd_input); } @@ -311,8 +322,7 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { GetMklShape(context, kFilterIdx, &filter_mkl_shape); GetMklShape(context, kOutbpropIdx, &diff_dst_mkl_shape); // Allow operator-specific sanity checking of shapes. - ValidateMklShapes(src_mkl_shape, filter_mkl_shape, - diff_dst_mkl_shape); + ValidateMklShapes(src_mkl_shape, filter_mkl_shape, diff_dst_mkl_shape); // Allow operator-specific generation of shapes. // E.g., ConvBackpropFilter gets filter as filter_sizes. It is a @@ -330,11 +340,11 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { diff_dst_tf_shape.num_elements() == 0) { MklDnnShape diff_src_mkl_shape; diff_src_mkl_shape.SetMklTensor(false); - TensorShape diff_src_tf_shape = GetOutputTfShape( - src_tf_shape, filter_tf_shape, diff_dst_tf_shape); + TensorShape diff_src_tf_shape = + GetOutputTfShape(src_tf_shape, filter_tf_shape, diff_dst_tf_shape); const int kOutputIdx = 0; AllocateOutputSetMklShape(context, kOutputIdx, &diff_src_tensor, - diff_src_tf_shape, diff_src_mkl_shape); + diff_src_tf_shape, diff_src_mkl_shape); CHECK_NOTNULL(diff_src_tensor); // if output tensor has more than 0 elements, we need to 0 them out. @@ -353,7 +363,7 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { // Get forward convolution parameters. MklDnnConvUtil conv_utl(context, this->strides_, this->padding_, - this->data_format_, this->dilations_); + this->data_format_, this->dilations_); conv_utl.GetConvFwdSizesInMklOrder( src_tf_shape, filter_tf_shape, &fwd_src_dims, &fwd_filter_dims, &strides, &dilations, &fwd_output_dims_tf_order, &fwd_output_dims, @@ -370,23 +380,25 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { // If filter is in MKL layout, then simply grab filter layout; // otherwise, construct filter in TF layout. // For TF layout, filter is in HWIO format. - auto fwd_filter_md = filter_mkl_shape.IsMklTensor() - ? filter_mkl_shape.GetMklLayout() - : memory::desc(fwd_filter_dims, MklDnnType(), - is_Conv2D ? memory::format::hwio - : memory::format::dhwio); + auto fwd_filter_md = + filter_mkl_shape.IsMklTensor() + ? filter_mkl_shape.GetMklLayout() + : memory::desc( + fwd_filter_dims, MklDnnType(), + is_Conv2D ? memory::format::hwio : memory::format::dhwio); conv_utl.GetInputSizeInMklOrder(diff_dst_tf_shape, &diff_dst_dims); if (!context->status().ok()) return; - auto diff_dst_md = diff_dst_mkl_shape.IsMklTensor() - ? diff_dst_mkl_shape.GetMklLayout() - : memory::desc(diff_dst_dims, - MklDnnType(), tf_fmt); + auto diff_dst_md = + diff_dst_mkl_shape.IsMklTensor() + ? diff_dst_mkl_shape.GetMklLayout() + : memory::desc(diff_dst_dims, MklDnnType(), tf_fmt); for (int i = 0; i < dilations.size(); i++) dilations[i] -= 1; MklConvBwdInputPrimitive* conv_bwd_input = nullptr; - MklConvBwdInputParams convBwdInputDims(fwd_src_dims, fwd_filter_dims, - diff_dst_dims, strides, dilations, padding_left, padding_right, + MklConvBwdInputParams convBwdInputDims( + fwd_src_dims, fwd_filter_dims, diff_dst_dims, strides, dilations, + padding_left, padding_right, TFPaddingToMklDnnPadding(this->padding_)); // We don't cache those primitves if the env variable @@ -396,8 +408,8 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { // 1. Legacy CPU without AVX512/AVX2, or // 2. 1x1 convolution with stride != 1 bool do_not_cache = MklPrimitiveFactory::IsPrimitiveMemOptEnabled() && - (MklPrimitiveFactory::IsLegacyPlatform() || - IsConv1x1StrideNot1(fwd_filter_dims, strides)); + (MklPrimitiveFactory::IsLegacyPlatform() || + IsConv1x1StrideNot1(fwd_filter_dims, strides)); conv_bwd_input = MklConvBwdInputPrimitiveFactory::Get(convBwdInputDims, do_not_cache); auto bwd_input_pd = conv_bwd_input->GetPrimitiveDesc(); @@ -411,14 +423,14 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { diff_src_mkl_shape.SetMklLayout(&diff_src_pd); diff_src_mkl_shape.SetElemType(MklDnnType()); diff_src_mkl_shape.SetTfLayout(bwd_diff_src_dims.size(), - bwd_diff_src_dims, bwd_diff_src_format); + bwd_diff_src_dims, bwd_diff_src_format); TensorShape diff_src_tf_shape; diff_src_tf_shape.AddDim(diff_src_pd.get_size() / sizeof(T)); - AllocateOutputSetMklShape(context, 0, &diff_src_tensor, - diff_src_tf_shape, diff_src_mkl_shape); + AllocateOutputSetMklShape(context, 0, &diff_src_tensor, diff_src_tf_shape, + diff_src_mkl_shape); - T *diff_src_data = static_cast(const_cast( - diff_src_tensor->flat().data())); + T* diff_src_data = + static_cast(const_cast(diff_src_tensor->flat().data())); // check if filter and diff_dst need reorder T* filter_data = nullptr; @@ -428,19 +440,18 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { filter.CheckReorderToOpMem(bwd_input_pd->weights_primitive_desc()); filter_data = static_cast(filter.GetOpMem().get_data_handle()); } else { - filter_data = static_cast(const_cast( - filter_tensor.flat().data())); + filter_data = + static_cast(const_cast(filter_tensor.flat().data())); } T* diff_dst_data = nullptr; if (diff_dst_md.data.format != conv_bwd_input->GetDiffDstMemoryFormat()) { diff_dst.SetUsrMem(diff_dst_md, &diff_dst_tensor); diff_dst.CheckReorderToOpMem(bwd_input_pd->diff_dst_primitive_desc()); - diff_dst_data = static_cast( - diff_dst.GetOpMem().get_data_handle()); + diff_dst_data = static_cast(diff_dst.GetOpMem().get_data_handle()); } else { - diff_dst_data = static_cast(const_cast( - diff_dst_tensor.flat().data())); + diff_dst_data = + static_cast(const_cast(diff_dst_tensor.flat().data())); } // execute convolution input bwd @@ -451,9 +462,9 @@ class MklConvCustomBackpropInputOp : public MklConvBackpropCommonOp { delete conv_bwd_input; } } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK( context, errors::Aborted("Operation received an exception:", error_msg)); diff --git a/tensorflow/core/kernels/mkl_conv_ops.cc b/tensorflow/core/kernels/mkl_conv_ops.cc index 4892c6bbce..c9cb414dd1 100644 --- a/tensorflow/core/kernels/mkl_conv_ops.cc +++ b/tensorflow/core/kernels/mkl_conv_ops.cc @@ -323,7 +323,7 @@ class MklConvFwdPrimitiveFactory : public MklPrimitiveFactory { const MklConvFwdParams& convFwdDims, bool do_not_cache) { MklConvFwdPrimitive* conv_fwd = nullptr; - if (do_not_cache) {/* Always create new primitive */ + if (do_not_cache) { /* Always create new primitive */ conv_fwd = new MklConvFwdPrimitive( convFwdDims); } else { @@ -423,16 +423,15 @@ class MklConvOp : public OpKernel { OP_REQUIRES(context, FormatFromString(data_format, &data_format_), errors::InvalidArgument("Invalid data format")); OP_REQUIRES(context, strides_.size() == 4, - errors::InvalidArgument( - "Sliding window strides field must " - "specify 4 dimensions")); + errors::InvalidArgument("Sliding window strides field must " + "specify 4 dimensions")); const int64 stride_n = GetTensorDim(strides_, data_format_, 'N'); const int64 stride_c = GetTensorDim(strides_, data_format_, 'C'); - OP_REQUIRES(context, stride_n == 1 && stride_c == 1, - errors::InvalidArgument( - "Current implementation does not yet support " - "strides in the batch and depth dimensions.")); + OP_REQUIRES( + context, stride_n == 1 && stride_c == 1, + errors::InvalidArgument("Current implementation does not yet support " + "strides in the batch and depth dimensions.")); OP_REQUIRES_OK(context, context->GetAttr("padding", &padding_)); } @@ -727,7 +726,7 @@ class MklConvOp : public OpKernel { mkl_prim_convert_input; dnnLayout_t mkl_lt_internal_filter, mkl_lt_internal_bias, mkl_lt_internal_input; - void* mkl_buf_convert_input, *mkl_buf_convert_filter, + void *mkl_buf_convert_input, *mkl_buf_convert_filter, *mkl_buf_convert_bias; mkl_prim_convert_filter = nullptr; mkl_prim_convert_bias = nullptr; @@ -861,23 +860,21 @@ class MklConvOp : public OpKernel { OP_REQUIRES(context, FormatFromString(data_format, &data_format_), errors::InvalidArgument("Invalid data format")); OP_REQUIRES(context, (strides_.size() == 4 || strides_.size() == 5), - errors::InvalidArgument( - "Sliding window strides field must " - "specify 4 or 5 dimensions")); + errors::InvalidArgument("Sliding window strides field must " + "specify 4 or 5 dimensions")); const int64 stride_n = GetTensorDim(strides_, data_format_, 'N'); const int64 stride_c = GetTensorDim(strides_, data_format_, 'C'); - OP_REQUIRES(context, stride_n == 1 && stride_c == 1, - errors::InvalidArgument( - "Current implementation does not yet support " - "strides in the batch and depth dimensions.")); + OP_REQUIRES( + context, stride_n == 1 && stride_c == 1, + errors::InvalidArgument("Current implementation does not yet support " + "strides in the batch and depth dimensions.")); OP_REQUIRES_OK(context, context->GetAttr("padding", &padding_)); if (strides_.size() == 4) { OP_REQUIRES(context, dilations_.size() == 4, - errors::InvalidArgument( - "Sliding window dilations field must " - "specify 4 dimensions")); + errors::InvalidArgument("Sliding window dilations field must " + "specify 4 dimensions")); const int64 dilation_n = GetTensorDim(dilations_, data_format_, 'N'); const int64 dilation_c = GetTensorDim(dilations_, data_format_, 'C'); const int64 dilation_h = GetTensorDim(dilations_, data_format_, 'H'); @@ -891,9 +888,8 @@ class MklConvOp : public OpKernel { errors::InvalidArgument("Dilated rates should be larger than 0.")); } else if (strides_.size() == 5) { OP_REQUIRES(context, dilations_.size() == 5, - errors::InvalidArgument( - "Dilation rates field must " - "specify 5 dimensions")); + errors::InvalidArgument("Dilation rates field must " + "specify 5 dimensions")); OP_REQUIRES(context, (GetTensorDim(dilations_, data_format_, 'N') == 1 && GetTensorDim(dilations_, data_format_, 'C') == 1), errors::InvalidArgument( @@ -917,9 +913,8 @@ class MklConvOp : public OpKernel { GetMklShape(context, kInputIndex_Src, &src_mkl_shape); GetMklShape(context, kInputIndex_Filter, &filter_mkl_shape); OP_REQUIRES(context, filter_mkl_shape.IsMklTensor() == false, - errors::InvalidArgument( - "Filter should not be in " - "Mkl Layout")); + errors::InvalidArgument("Filter should not be in " + "Mkl Layout")); MklDnnData src(&cpu_engine_); MklDnnData filter(&cpu_engine_); @@ -955,8 +950,9 @@ class MklConvOp : public OpKernel { filter_mkl_shape.SetMklTensor(false); Tensor* output_filter_tensor = nullptr; // MklConv2D also outputs converted filter as 2nd output. - if (typeid(Tinput) == typeid(float)&&typeid(Tfilter) == - typeid(float)&&typeid(Toutput) == typeid(float)) { + if (typeid(Tinput) == typeid(float) && + typeid(Tfilter) == typeid(float) && + typeid(Toutput) == typeid(float)) { filter_mkl_shape.SetMklTensor(false); AllocateOutputSetMklShape(context, kOutputIndex_Filter, &output_filter_tensor, filter_tf_shape, @@ -969,7 +965,6 @@ class MklConvOp : public OpKernel { // TODO 3-D support for Depthwise is not there if (is_Depthwise) { - OP_REQUIRES(context, is_Conv2D, errors::InvalidArgument( "Only 2D convolution is supported for depthwise.")); @@ -1056,8 +1051,8 @@ class MklConvOp : public OpKernel { AllocateOutputTensor(context, *conv_fwd_pd, dst_dims_mkl_order, tf_fmt, &dst_tensor); Tensor* filter_out_tensor = nullptr; - if (typeid(Tinput) == typeid(float)&&typeid(Tfilter) == - typeid(float)&&typeid(Toutput) == typeid(float)) { + if (typeid(Tinput) == typeid(float) && typeid(Tfilter) == typeid(float) && + typeid(Toutput) == typeid(float)) { AllocateFilterOutputTensor(context, *conv_fwd_pd, TFShapeToMklDnnDims(filter_tf_shape), &filter_out_tensor); @@ -1100,8 +1095,7 @@ class MklConvOp : public OpKernel { // delete primitive since it is not cached. if (do_not_cache) delete conv_fwd; - } - catch (mkldnn::error& e) { + } catch (mkldnn::error& e) { string error_msg = tensorflow::strings::StrCat( "Status: ", e.status, ", message: ", string(e.message), ", in file ", __FILE__, ":", __LINE__); @@ -1798,8 +1792,10 @@ REGISTER_KERNEL_BUILDER( // Register 2D operations #define REGISTER_MKL_CPU_2D(T) \ REGISTER_KERNEL_BUILDER( \ - Name("_MklConv2D").Device(DEVICE_CPU).TypeConstraint("T").Label( \ - mkl_op_registry::kMklOpLabel), \ + Name("_MklConv2D") \ + .Device(DEVICE_CPU) \ + .TypeConstraint("T") \ + .Label(mkl_op_registry::kMklOpLabel), \ MklConvOp); \ REGISTER_KERNEL_BUILDER( \ Name("_MklDepthwiseConv2dNative") \ @@ -1822,11 +1818,12 @@ REGISTER_KERNEL_BUILDER( TF_CALL_float(REGISTER_MKL_CPU_2D); // Register 3D operations -#define REGISTER_MKL_CPU_3D(T) \ - REGISTER_KERNEL_BUILDER( \ - Name("_MklConv3D").Device(DEVICE_CPU).TypeConstraint("T").Label( \ - mkl_op_registry::kMklOpLabel), \ - MklConvOp); +#define REGISTER_MKL_CPU_3D(T) \ + REGISTER_KERNEL_BUILDER(Name("_MklConv3D") \ + .Device(DEVICE_CPU) \ + .TypeConstraint("T") \ + .Label(mkl_op_registry::kMklOpLabel), \ + MklConvOp); TF_CALL_float(REGISTER_MKL_CPU_3D); } // namespace tensorflow diff --git a/tensorflow/core/kernels/mkl_conv_ops.h b/tensorflow/core/kernels/mkl_conv_ops.h index 3ce54ff093..5e4163890d 100644 --- a/tensorflow/core/kernels/mkl_conv_ops.h +++ b/tensorflow/core/kernels/mkl_conv_ops.h @@ -17,8 +17,8 @@ limitations under the License. #define TENSORFLOW_CORE_KERNELS_MKL_CONV_OPS_H_ #include -#include #include +#include #include "mkldnn.hpp" #include "tensorflow/core/framework/numeric_op.h" @@ -538,18 +538,17 @@ class MklConvBackpropCommonOp : public OpKernel { OP_REQUIRES_OK(context, context->GetAttr("strides", &strides_)); int stride_n = GetTensorDim(strides_, data_format_, 'N'); int stride_c = GetTensorDim(strides_, data_format_, 'C'); - OP_REQUIRES(context, (stride_n == 1 && stride_c == 1), - errors::InvalidArgument( - "Current implementation does not yet support " - "strides in the batch and depth dimensions.")); + OP_REQUIRES( + context, (stride_n == 1 && stride_c == 1), + errors::InvalidArgument("Current implementation does not yet support " + "strides in the batch and depth dimensions.")); OP_REQUIRES_OK(context, context->GetAttr("dilations", &dilations_)); if (strides_.size() == 4) { // Check Conv2D dilations OP_REQUIRES(context, dilations_.size() == 4, - errors::InvalidArgument( - "Sliding window dilations field must " - "specify 4 dimensions")); + errors::InvalidArgument("Sliding window dilations field must " + "specify 4 dimensions")); int dilation_n = GetTensorDim(dilations_, data_format_, 'N'); int dilation_c = GetTensorDim(dilations_, data_format_, 'C'); int dilation_h = GetTensorDim(dilations_, data_format_, 'H'); @@ -587,9 +586,9 @@ class MklDummyOp : public OpKernel { explicit MklDummyOp(OpKernelConstruction* context) : OpKernel(context) {} void Compute(OpKernelContext* context) override { - TF_CHECK_OK(errors::Unimplemented( - "This is a dummy op." - "It should not have been invoked.")); + TF_CHECK_OK( + errors::Unimplemented("This is a dummy op." + "It should not have been invoked.")); } }; diff --git a/tensorflow/core/util/mkl_util.h b/tensorflow/core/util/mkl_util.h index 7c183d30ab..9520ac372e 100644 --- a/tensorflow/core/util/mkl_util.h +++ b/tensorflow/core/util/mkl_util.h @@ -111,7 +111,8 @@ typedef enum { Dim3d_I = 1 } MklDnnDims3D; -// Enum for the order of dimensions of a TF 2D filter with shape [filter_height, filter_width, in_channels, out_channels] +// Enum for the order of dimensions of a TF 2D filter with shape [filter_height, +// filter_width, in_channels, out_channels] typedef enum { TF_2DFILTER_DIM_H = 0, TF_2DFILTER_DIM_W = 1, @@ -119,7 +120,8 @@ typedef enum { TF_2DFILTER_DIM_O = 3 } TFFilterDims2d; -// Enum for the order of dimensions of a TF 3D filter with shape [filter_depth, filter_height, filter_width, in_channels, out_channels] +// Enum for the order of dimensions of a TF 3D filter with shape [filter_depth, +// filter_height, filter_width, in_channels, out_channels] typedef enum { TF_3DFILTER_DIM_P = 0, TF_3DFILTER_DIM_H = 1, @@ -128,13 +130,14 @@ typedef enum { TF_3DFILTER_DIM_O = 4 } TFFilterDims3d; -// The dimensions order that MKL DNN requires for the filter in a grouped convolution (2D only) +// The dimensions order that MKL DNN requires for the filter in a grouped +// convolution (2D only) typedef enum { - MKL_GROUP_FILTER_DIM_G = 0, - MKL_GROUP_FILTER_DIM_O = 1, - MKL_GROUP_FILTER_DIM_I = 2, - MKL_GROUP_FILTER_DIM_H = 3, - MKL_GROUP_FILTER_DIM_W = 4 + MKL_GROUP_FILTER_DIM_G = 0, + MKL_GROUP_FILTER_DIM_O = 1, + MKL_GROUP_FILTER_DIM_I = 2, + MKL_GROUP_FILTER_DIM_H = 3, + MKL_GROUP_FILTER_DIM_W = 4 } MklDnnFilterGroupDims; // Enum used to templatize MklOp kernel implementations @@ -292,32 +295,32 @@ class MklShape { CHECK_EQ(dnnDelete_F32(convert), E_SUCCESS); } - // The following methods are used for serializing and de-serializing the - // contents of the mklshape object. - // The data is serialized in this order - // isMklTensor_ - // dimension_ - // sizes_ - // strides_ - // mklLayout_ - // tfLayout_ - // tf_to_mkl_dim_map_ +// The following methods are used for serializing and de-serializing the +// contents of the mklshape object. +// The data is serialized in this order +// isMklTensor_ +// dimension_ +// sizes_ +// strides_ +// mklLayout_ +// tfLayout_ +// tf_to_mkl_dim_map_ #define SIZE_OF_MKL_DNN_BUF \ (dnnLayoutSerializationBufferSize_F32()) // Size of buffer needed to // serialize dnn_layout pointer - // Size of buffer to hold the serialized object, the size is computed as - // follows sizeof(isMklTensor_) + sizeof(dimension_) + sizeof(sizes_) + - // sizeof(strides_) - // + sizeof(mklLayout_ buffer) + sizeof(tfLayout_ buffer) - // + sizeof(tf_to_mkl_dim_map_) +// Size of buffer to hold the serialized object, the size is computed as +// follows sizeof(isMklTensor_) + sizeof(dimension_) + sizeof(sizes_) + +// sizeof(strides_) +// + sizeof(mklLayout_ buffer) + sizeof(tfLayout_ buffer) +// + sizeof(tf_to_mkl_dim_map_) #define SIZE_OF_MKL_SERIAL_DATA(dims) \ (2 * sizeof(size_t) + 3 * dims * sizeof(size_t) + 2 * SIZE_OF_MKL_DNN_BUF) - // First we need to define some macro for offsets into the serial buffer where - // different elements of Mklshape is written/read from +// First we need to define some macro for offsets into the serial buffer where +// different elements of Mklshape is written/read from #define IS_MKL_TENSOR_OFFSET 0 // Location from start of buffer where isMklTensor_ is serialized @@ -860,9 +863,9 @@ inline Tensor ConvertMklToTF(OpKernelContext* context, const Tensor& mkl_tensor, CHECK(output_tensor.CopyFrom(mkl_tensor, output_shape)); } } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); LOG(FATAL) << "Operation received an exception: " << error_msg; } return output_tensor; -- GitLab From 8c9dc06e8e2566de4e3c2d6067d8f1b8bc077307 Mon Sep 17 00:00:00 2001 From: Karl Lessard Date: Mon, 26 Nov 2018 09:34:16 -0500 Subject: [PATCH 0035/1765] Define API defs for Java --- tensorflow/core/api_def/java_api/api_def_Abort.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Abs.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_AccumulateNV2.pbtxt | 6 ++++++ .../api_def/java_api/api_def_AccumulatorApplyGradient.pbtxt | 6 ++++++ .../java_api/api_def_AccumulatorNumAccumulated.pbtxt | 6 ++++++ .../api_def/java_api/api_def_AccumulatorSetGlobalStep.pbtxt | 6 ++++++ .../api_def/java_api/api_def_AccumulatorTakeGradient.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Acos.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Acosh.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Add.pbtxt | 6 ++++++ .../java_api/api_def_AddManySparseToTensorsMap.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_AddN.pbtxt | 6 ++++++ .../api_def/java_api/api_def_AddSparseToTensorsMap.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_AdjustContrast.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_AdjustContrastv2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_AdjustHue.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_AdjustSaturation.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_All.pbtxt | 3 +++ .../core/api_def/java_api/api_def_AllCandidateSampler.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Angle.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_AnonymousIterator.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Any.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ApplyAdaMax.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ApplyAdadelta.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ApplyAdagrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ApplyAdam.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ApplyAddSign.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ApplyGradientDescent.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ApplyMomentum.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ApplyPowerSign.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ApplyProximalAdagrad.pbtxt | 6 ++++++ .../java_api/api_def_ApplyProximalGradientDescent.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ApproximateEqual.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ArgMax.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ArgMin.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_AsString.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Asin.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Asinh.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Assert.pbtxt | 6 ++++-- tensorflow/core/api_def/java_api/api_def_Assign.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_AssignAdd.pbtxt | 3 +++ .../core/api_def/java_api/api_def_AssignAddVariableOp.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_AssignSub.pbtxt | 3 +++ .../core/api_def/java_api/api_def_AssignSubVariableOp.pbtxt | 3 +++ .../core/api_def/java_api/api_def_AssignVariableOp.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Atan.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Atan2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Atanh.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_AudioSpectrogram.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_AudioSummaryV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_AvgPool.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_AvgPool3D.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_AvgPoolGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Barrier.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_BarrierClose.pbtxt | 3 +++ .../api_def/java_api/api_def_BarrierIncompleteSize.pbtxt | 3 +++ .../core/api_def/java_api/api_def_BarrierInsertMany.pbtxt | 3 +++ .../core/api_def/java_api/api_def_BarrierReadySize.pbtxt | 3 +++ .../core/api_def/java_api/api_def_BarrierTakeMany.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Batch.pbtxt | 3 +++ .../core/api_def/java_api/api_def_BatchCholesky.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchCholeskyGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchDatasetV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchFunction.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BatchMatMul.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchMatrixBandPart.pbtxt | 6 ++++++ .../api_def/java_api/api_def_BatchMatrixDeterminant.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchMatrixDiag.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchMatrixDiagPart.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchMatrixInverse.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchMatrixSetDiag.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchMatrixSolve.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchMatrixSolveLs.pbtxt | 6 ++++++ .../java_api/api_def_BatchMatrixTriangularSolve.pbtxt | 6 ++++++ .../java_api/api_def_BatchNormWithGlobalNormalization.pbtxt | 6 ++++++ .../api_def_BatchNormWithGlobalNormalizationGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt | 6 ++++++ .../api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BatchSvd.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BatchToSpace.pbtxt | 3 +++ .../core/api_def/java_api/api_def_BatchToSpaceND.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BesselI0e.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BesselI1e.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Betainc.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BiasAdd.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BiasAddGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_BigQueryReader.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Bincount.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Bitcast.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_BitwiseAnd.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BitwiseOr.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_BitwiseXor.pbtxt | 6 ++++++ .../api_def/java_api/api_def_BoostedTreesBucketize.pbtxt | 3 +++ .../api_def_BoostedTreesCalculateBestGainsPerFeature.pbtxt | 3 +++ .../api_def/java_api/api_def_BoostedTreesCenterBias.pbtxt | 3 +++ .../java_api/api_def_BoostedTreesCreateEnsemble.pbtxt | 3 +++ .../api_def_BoostedTreesCreateQuantileStreamResource.pbtxt | 3 +++ .../java_api/api_def_BoostedTreesDeserializeEnsemble.pbtxt | 3 +++ .../api_def_BoostedTreesEnsembleResourceHandleOp.pbtxt | 3 +++ .../java_api/api_def_BoostedTreesExampleDebugOutputs.pbtxt | 3 +++ .../java_api/api_def_BoostedTreesGetEnsembleStates.pbtxt | 3 +++ .../api_def_BoostedTreesMakeQuantileSummaries.pbtxt | 3 +++ .../java_api/api_def_BoostedTreesMakeStatsSummary.pbtxt | 3 +++ .../core/api_def/java_api/api_def_BoostedTreesPredict.pbtxt | 3 +++ ...def_BoostedTreesQuantileStreamResourceAddSummaries.pbtxt | 3 +++ ..._def_BoostedTreesQuantileStreamResourceDeserialize.pbtxt | 3 +++ .../api_def_BoostedTreesQuantileStreamResourceFlush.pbtxt | 3 +++ ...stedTreesQuantileStreamResourceGetBucketBoundaries.pbtxt | 3 +++ ...api_def_BoostedTreesQuantileStreamResourceHandleOp.pbtxt | 3 +++ .../java_api/api_def_BoostedTreesSerializeEnsemble.pbtxt | 3 +++ .../java_api/api_def_BoostedTreesTrainingPredict.pbtxt | 3 +++ .../java_api/api_def_BoostedTreesUpdateEnsemble.pbtxt | 3 +++ .../core/api_def/java_api/api_def_BroadcastArgs.pbtxt | 3 +++ .../api_def/java_api/api_def_BroadcastGradientArgs.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_BroadcastTo.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Bucketize.pbtxt | 3 +++ .../java_api/api_def_BytesProducedStatsDataset.pbtxt | 6 ++++++ .../api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_CacheDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Cast.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Ceil.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CheckNumerics.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Cholesky.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_CholeskyGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ClipByValue.pbtxt | 3 +++ .../core/api_def/java_api/api_def_CloseSummaryWriter.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CollectiveBcastRecv.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CollectiveBcastSend.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CollectiveReduce.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CompareAndBitpack.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Complex.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ComplexAbs.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ComputeAccidentalHits.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Concat.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ConcatOffset.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ConcatenateDataset.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ConditionalAccumulator.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Conj.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ConjugateTranspose.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Const.pbtxt | 4 ++-- .../core/api_def/java_api/api_def_ConsumeMutexLock.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ControlTrigger.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt | 6 ++++++ .../api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt | 6 ++++++ .../api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt | 6 ++++++ .../api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt | 6 ++++++ .../api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Cos.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Cosh.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_CountUpTo.pbtxt | 3 +++ .../api_def/java_api/api_def_CreateSummaryDbWriter.pbtxt | 6 ++++++ .../api_def/java_api/api_def_CreateSummaryFileWriter.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CropAndResize.pbtxt | 6 ++++++ .../api_def/java_api/api_def_CropAndResizeGradBoxes.pbtxt | 6 ++++++ .../api_def/java_api/api_def_CropAndResizeGradImage.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Cross.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt | 6 ++++++ .../java_api/api_def_CudnnRNNCanonicalToParams.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt | 6 ++++++ .../java_api/api_def_CudnnRNNParamsToCanonical.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Cumprod.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Cumsum.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DataFormatDimMap.pbtxt | 6 ++++++ .../api_def/java_api/api_def_DataFormatVecPermute.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DatasetToGraph.pbtxt | 6 ++++++ .../api_def/java_api/api_def_DatasetToSingleElement.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt | 6 ++++++ .../api_def/java_api/api_def_DebugGradientIdentity.pbtxt | 4 ++++ .../api_def/java_api/api_def_DebugGradientRefIdentity.pbtxt | 4 ++++ .../core/api_def/java_api/api_def_DecodeAndCropJpeg.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DecodeBase64.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DecodeBmp.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DecodeCompressed.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DecodeGif.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DecodeJSONExample.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DecodeJpeg.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DecodePng.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DecodeProtoV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_DecodeRaw.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DecodeWav.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DeepCopy.pbtxt | 3 +++ .../core/api_def/java_api/api_def_DeleteSessionTensor.pbtxt | 3 +++ .../api_def/java_api/api_def_DenseToDenseSetOperation.pbtxt | 6 ++++++ .../java_api/api_def_DenseToSparseBatchDataset.pbtxt | 6 ++++++ .../java_api/api_def_DenseToSparseSetOperation.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DepthToSpace.pbtxt | 6 ++++++ .../api_def/java_api/api_def_DepthwiseConv2dNative.pbtxt | 6 ++++++ .../api_def_DepthwiseConv2dNativeBackpropFilter.pbtxt | 6 ++++++ .../api_def_DepthwiseConv2dNativeBackpropInput.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Dequantize.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DeserializeIterator.pbtxt | 6 ++++++ .../api_def/java_api/api_def_DeserializeManySparse.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DeserializeSparse.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DestroyResourceOp.pbtxt | 3 +++ .../api_def/java_api/api_def_DestroyTemporaryVariable.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Diag.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DiagPart.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Digamma.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Dilation2D.pbtxt | 6 ++++++ .../api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt | 6 ++++++ .../api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Div.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_DivNoNan.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DrawBoundingBoxes.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_DynamicPartition.pbtxt | 3 +++ .../core/api_def/java_api/api_def_DynamicStitch.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_EagerPyFunc.pbtxt | 4 ++++ tensorflow/core/api_def/java_api/api_def_EditDistance.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Elu.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_EluGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Empty.pbtxt | 3 +++ .../core/api_def/java_api/api_def_EmptyTensorList.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_EncodeBase64.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_EncodeJpeg.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_EncodePng.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_EncodeProto.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_EncodeWav.pbtxt | 6 ++++++ .../api_def/java_api/api_def_EnqueueInQueueDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_EnsureShape.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Enter.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Equal.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Erf.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Erfc.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Exit.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Exp.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ExpandDims.pbtxt | 3 +++ .../java_api/api_def_ExperimentalAssertNextDataset.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt | 6 ++++++ .../api_def_ExperimentalDirectedInterleaveDataset.pbtxt | 6 ++++++ .../api_def_ExperimentalFunctionBufferingResource.pbtxt | 6 ++++++ ...i_def_ExperimentalFunctionBufferingResourceGetNext.pbtxt | 6 ++++++ ...api_def_ExperimentalFunctionBufferingResourceReset.pbtxt | 6 ++++++ .../api_def_ExperimentalIdentityIndexedDataset.pbtxt | 6 ++++++ .../java_api/api_def_ExperimentalIgnoreErrorsDataset.pbtxt | 6 ++++++ .../java_api/api_def_ExperimentalIndexedDatasetGet.pbtxt | 6 ++++++ .../api_def_ExperimentalIndexedDatasetMaterialize.pbtxt | 6 ++++++ .../java_api/api_def_ExperimentalIteratorGetDevice.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ExperimentalMapDataset.pbtxt | 6 ++++++ ...api_def_ExperimentalMaterializedIndexDatasetHandle.pbtxt | 6 ++++++ .../api_def_ExperimentalNonSerializableDataset.pbtxt | 6 ++++++ .../api_def_ExperimentalNumaMapAndBatchDataset.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ExperimentalSleepDataset.pbtxt | 6 ++++++ .../java_api/api_def_ExperimentalThreadPoolDataset.pbtxt | 6 ++++++ .../java_api/api_def_ExperimentalThreadPoolHandle.pbtxt | 6 ++++++ .../java_api/api_def_ExperimentalUniqueDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Expm1.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ExtractGlimpse.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ExtractImagePatches.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ExtractJpegShape.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ExtractVolumePatches.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_FFT.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_FFT2D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_FFT3D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Fact.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_FakeParam.pbtxt | 3 +++ .../api_def/java_api/api_def_FakeQuantWithMinMaxArgs.pbtxt | 6 ++++++ .../java_api/api_def_FakeQuantWithMinMaxArgsGradient.pbtxt | 6 ++++++ .../api_def/java_api/api_def_FakeQuantWithMinMaxVars.pbtxt | 6 ++++++ .../java_api/api_def_FakeQuantWithMinMaxVarsGradient.pbtxt | 6 ++++++ .../api_def_FakeQuantWithMinMaxVarsPerChannel.pbtxt | 6 ++++++ .../api_def_FakeQuantWithMinMaxVarsPerChannelGradient.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_FakeQueue.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Fill.pbtxt | 3 +++ .../java_api/api_def_FilterByLastComponentDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_FilterDataset.pbtxt | 6 ++++++ .../api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt | 6 ++++++ .../java_api/api_def_FixedLengthRecordDatasetV2.pbtxt | 6 ++++++ .../api_def/java_api/api_def_FixedLengthRecordReader.pbtxt | 6 ++++++ .../java_api/api_def_FixedLengthRecordReaderV2.pbtxt | 6 ++++++ .../java_api/api_def_FixedUnigramCandidateSampler.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_FlatMapDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Floor.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_FloorDiv.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_FloorMod.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_FlushSummaryWriter.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_For.pbtxt | 3 +++ .../core/api_def/java_api/api_def_FractionalAvgPool.pbtxt | 6 ++++++ .../api_def/java_api/api_def_FractionalAvgPoolGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_FractionalMaxPool.pbtxt | 6 ++++++ .../api_def/java_api/api_def_FractionalMaxPoolGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_FusedBatchNorm.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt | 6 ++++++ .../api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_FusedPadConv2D.pbtxt | 6 ++++++ .../api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Gather.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_GatherNd.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt | 3 +++ .../api_def/java_api/api_def_GcsConfigureBlockCache.pbtxt | 3 +++ .../api_def/java_api/api_def_GcsConfigureCredentials.pbtxt | 3 +++ .../java_api/api_def_GenerateBigQueryReaderPartitions.pbtxt | 3 +++ .../api_def/java_api/api_def_GenerateVocabRemapping.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_GeneratorDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_GetSessionHandle.pbtxt | 3 +++ .../core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_GetSessionTensor.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Greater.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_GreaterEqual.pbtxt | 6 ++++++ .../api_def/java_api/api_def_GroupByReducerDataset.pbtxt | 3 +++ .../api_def/java_api/api_def_GroupByWindowDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_GuaranteeConst.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_HSVToRGB.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_HistogramFixedWidth.pbtxt | 3 +++ .../core/api_def/java_api/api_def_HistogramSummary.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_HostConst.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_IFFT.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_IFFT2D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_IFFT3D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Identity.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_IdentityN.pbtxt | 3 +++ .../core/api_def/java_api/api_def_IdentityReader.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_IdentityReaderV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_If.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Igamma.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_IgammaGradA.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Igammac.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Imag.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ImageSummary.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ImmutableConst.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ImportEvent.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_InitializeTable.pbtxt | 3 +++ .../java_api/api_def_InitializeTableFromTextFile.pbtxt | 3 +++ .../java_api/api_def_InitializeTableFromTextFileV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_InitializeTableV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_InplaceAdd.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_InplaceSub.pbtxt | 3 +++ .../core/api_def/java_api/api_def_InplaceUpdate.pbtxt | 3 +++ .../core/api_def/java_api/api_def_InterleaveDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Inv.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_InvGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Invert.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_InvertPermutation.pbtxt | 6 ++++++ .../api_def_IsBoostedTreesEnsembleInitialized.pbtxt | 3 +++ ...ef_IsBoostedTreesQuantileStreamResourceInitialized.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_IsFinite.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_IsInf.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_IsNan.pbtxt | 6 ++++++ .../api_def/java_api/api_def_IsVariableInitialized.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt | 6 ++++++ .../api_def/java_api/api_def_IteratorFromStringHandle.pbtxt | 6 ++++++ .../java_api/api_def_IteratorFromStringHandleV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_IteratorGetNext.pbtxt | 6 ++++++ .../java_api/api_def_IteratorGetNextAsOptional.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_IteratorGetNextSync.pbtxt | 6 ++++++ .../api_def/java_api/api_def_IteratorToStringHandle.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_L2Loss.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LRN.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LRNGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_LatencyStatsDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LeakyRelu.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_LeakyReluGrad.pbtxt | 6 ++++++ .../java_api/api_def_LearnedUnigramCandidateSampler.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LeftShift.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Less.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LessEqual.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Lgamma.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LinSpace.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LoadAndRemapMatrix.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Log.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Log1p.pbtxt | 6 ++++++ .../api_def/java_api/api_def_LogMatrixDeterminant.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LogSoftmax.pbtxt | 6 ++++++ .../java_api/api_def_LogUniformCandidateSampler.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LogicalAnd.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LogicalNot.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_LogicalOr.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_LookupTableExport.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableExportV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableFind.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableFindV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableImport.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableImportV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableInsert.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableSize.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_LoopCond.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_LowerBound.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MakeIterator.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt | 6 ++++++ .../api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MapClear.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MapDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_MapDefun.pbtxt | 3 +++ .../core/api_def/java_api/api_def_MapIncompleteSize.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MapPeek.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MapSize.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MapStage.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MapUnstage.pbtxt | 3 +++ .../core/api_def/java_api/api_def_MapUnstageNoKey.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MatMul.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatchingFiles.pbtxt | 6 ++++++ .../api_def/java_api/api_def_MatchingFilesDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatrixBandPart.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatrixDeterminant.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_MatrixDiag.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatrixDiagPart.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatrixExponential.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatrixInverse.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatrixLogarithm.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatrixSetDiag.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_MatrixSolve.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatrixSolveLs.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MatrixSquareRoot.pbtxt | 6 ++++++ .../api_def/java_api/api_def_MatrixTriangularSolve.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Max.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_MaxPool3D.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt | 6 ++++++ .../java_api/api_def_MaxPoolGradGradWithArgmax.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt | 6 ++++++ .../api_def/java_api/api_def_MaxPoolGradWithArgmax.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MaxPoolWithArgmax.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Maximum.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Mean.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Merge.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MergeSummary.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MergeV2Checkpoints.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Mfcc.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Min.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Minimum.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_MirrorPad.pbtxt | 3 +++ .../core/api_def/java_api/api_def_MirrorPadGrad.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Mod.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ModelDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Mul.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_MultiDeviceIterator.pbtxt | 6 ++++++ .../api_def_MultiDeviceIteratorFromStringHandle.pbtxt | 6 ++++++ .../api_def_MultiDeviceIteratorGetNextFromShard.pbtxt | 6 ++++++ .../api_def/java_api/api_def_MultiDeviceIteratorInit.pbtxt | 6 ++++++ .../api_def_MultiDeviceIteratorToStringHandle.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Multinomial.pbtxt | 6 ++++++ .../api_def/java_api/api_def_MutableDenseHashTable.pbtxt | 3 +++ .../api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_MutableHashTable.pbtxt | 3 +++ .../java_api/api_def_MutableHashTableOfTensors.pbtxt | 3 +++ .../java_api/api_def_MutableHashTableOfTensorsV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_MutableHashTableV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MutexLock.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_NcclAllReduce.pbtxt | 3 +++ .../core/api_def/java_api/api_def_NcclBroadcast.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_NcclReduce.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Neg.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_NegTrain.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_NextIteration.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_NoOp.pbtxt | 3 +++ .../core/api_def/java_api/api_def_NonMaxSuppression.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt | 6 ++++++ .../java_api/api_def_NonMaxSuppressionWithOverlaps.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_NotEqual.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_NthElement.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_OneHot.pbtxt | 3 +++ .../core/api_def/java_api/api_def_OneShotIterator.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_OnesLike.pbtxt | 3 +++ .../core/api_def/java_api/api_def_OptimizeDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_OptionalFromValue.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_OptionalGetValue.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_OptionalHasValue.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_OptionalNone.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_OrderedMapClear.pbtxt | 3 +++ .../api_def/java_api/api_def_OrderedMapIncompleteSize.pbtxt | 3 +++ .../core/api_def/java_api/api_def_OrderedMapPeek.pbtxt | 3 +++ .../core/api_def/java_api/api_def_OrderedMapSize.pbtxt | 3 +++ .../core/api_def/java_api/api_def_OrderedMapStage.pbtxt | 3 +++ .../core/api_def/java_api/api_def_OrderedMapUnstage.pbtxt | 3 +++ .../api_def/java_api/api_def_OrderedMapUnstageNoKey.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Pack.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Pad.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt | 6 ++++++ .../api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ParallelConcat.pbtxt | 3 +++ .../api_def/java_api/api_def_ParallelDynamicStitch.pbtxt | 3 +++ .../java_api/api_def_ParallelInterleaveDataset.pbtxt | 6 ++++++ .../java_api/api_def_ParallelInterleaveDatasetV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ParallelMapDataset.pbtxt | 6 ++++++ .../java_api/api_def_ParameterizedTruncatedNormal.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ParseExample.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ParseExampleDataset.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ParseSequenceExample.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ParseSingleExample.pbtxt | 6 ++++++ .../java_api/api_def_ParseSingleSequenceExample.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ParseTensor.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_PartitionedCall.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt | 3 +++ .../core/api_def/java_api/api_def_PlaceholderV2.pbtxt | 3 +++ .../api_def/java_api/api_def_PlaceholderWithDefault.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Polygamma.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_PopulationCount.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Pow.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_PrefetchDataset.pbtxt | 6 ++++++ .../api_def_PrependFromQueueAndPaddedBatchDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_PreventGradient.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Print.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_PriorityQueue.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_PriorityQueueV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Prod.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_PyFunc.pbtxt | 4 ++++ .../core/api_def/java_api/api_def_PyFuncStateless.pbtxt | 4 ++++ tensorflow/core/api_def/java_api/api_def_Qr.pbtxt | 6 ++++++ .../api_def/java_api/api_def_QuantizeAndDequantize.pbtxt | 6 ++++++ .../api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt | 6 ++++++ .../api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt | 6 ++++++ .../java_api/api_def_QuantizeDownAndShrinkRange.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_QuantizedAdd.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QuantizedAvgPool.pbtxt | 6 ++++++ .../api_def_QuantizedBatchNormWithGlobalNormalization.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QuantizedBiasAdd.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QuantizedConcat.pbtxt | 3 +++ .../core/api_def/java_api/api_def_QuantizedConv2D.pbtxt | 6 ++++++ .../api_def/java_api/api_def_QuantizedInstanceNorm.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QuantizedMatMul.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QuantizedMaxPool.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_QuantizedMul.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QuantizedRelu.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QuantizedRelu6.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QuantizedReluX.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QuantizedReshape.pbtxt | 3 +++ .../api_def/java_api/api_def_QuantizedResizeBilinear.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueDequeueMany.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueDequeueV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueIsClosed.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RGBToHSV.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RaggedGather.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_RaggedRange.pbtxt | 3 +++ .../api_def/java_api/api_def_RaggedTensorToSparse.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_RandomCrop.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_RandomDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RandomGamma.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_RandomGammaGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_RandomPoisson.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_RandomPoissonV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_RandomShuffle.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt | 6 ++++++ .../api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt | 6 ++++++ .../api_def/java_api/api_def_RandomStandardNormal.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_RandomUniform.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_RandomUniformInt.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Range.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_RangeDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Rank.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ReadFile.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ReadVariableOp.pbtxt | 3 +++ .../api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt | 6 ++++++ .../java_api/api_def_ReaderNumRecordsProducedV2.pbtxt | 6 ++++++ .../java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt | 6 ++++++ .../java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ReaderResetV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ReaderRestoreState.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ReaderSerializeState.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Real.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RealDiv.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Reciprocal.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ReciprocalGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RecordInput.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ReduceDataset.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ReduceJoin.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RefEnter.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_RefExit.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_RefIdentity.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_RefMerge.pbtxt | 3 +++ .../core/api_def/java_api/api_def_RefNextIteration.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_RefSelect.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_RefSwitch.pbtxt | 3 +++ .../core/api_def/java_api/api_def_RegexFullMatch.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RegexReplace.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Relu.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Relu6.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Relu6Grad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ReluGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RemoteCall.pbtxt | 3 +++ .../api_def/java_api/api_def_RemoteFusedGraphExecute.pbtxt | 3 +++ .../core/api_def/java_api/api_def_RepeatDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_RequantizationRange.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Requantize.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Reshape.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ResizeArea.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ResizeBicubic.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ResizeBicubicGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ResizeBilinear.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ResizeBilinearGrad.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ResizeNearestNeighbor.pbtxt | 6 ++++++ .../java_api/api_def_ResizeNearestNeighborGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ResourceApplyAdaMax.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ResourceApplyAdadelta.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ResourceApplyAdagrad.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ResourceApplyAdam.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ResourceApplyAddSign.pbtxt | 6 ++++++ .../java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt | 6 ++++++ .../java_api/api_def_ResourceApplyGradientDescent.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ResourceApplyMomentum.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ResourceApplyPowerSign.pbtxt | 6 ++++++ .../java_api/api_def_ResourceApplyProximalAdagrad.pbtxt | 6 ++++++ .../api_def_ResourceApplyProximalGradientDescent.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ResourceCountUpTo.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ResourceGather.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ResourceScatterAdd.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ResourceScatterDiv.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ResourceScatterMax.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ResourceScatterMin.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ResourceScatterMul.pbtxt | 3 +++ .../api_def/java_api/api_def_ResourceScatterNdAdd.pbtxt | 3 +++ .../api_def/java_api/api_def_ResourceScatterNdUpdate.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ResourceScatterSub.pbtxt | 3 +++ .../api_def/java_api/api_def_ResourceScatterUpdate.pbtxt | 3 +++ .../java_api/api_def_ResourceSparseApplyAdadelta.pbtxt | 6 ++++++ .../java_api/api_def_ResourceSparseApplyAdagrad.pbtxt | 6 ++++++ .../java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt | 6 ++++++ .../api_def_ResourceSparseApplyCenteredRMSProp.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt | 6 ++++++ .../java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt | 6 ++++++ .../java_api/api_def_ResourceSparseApplyMomentum.pbtxt | 6 ++++++ .../api_def_ResourceSparseApplyProximalAdagrad.pbtxt | 6 ++++++ ...api_def_ResourceSparseApplyProximalGradientDescent.pbtxt | 6 ++++++ .../java_api/api_def_ResourceSparseApplyRMSProp.pbtxt | 6 ++++++ .../java_api/api_def_ResourceStridedSliceAssign.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Restore.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RestoreSlice.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ReverseSequence.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ReverseV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RightShift.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Rint.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Roll.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Round.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Rpc.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Rsqrt.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_RsqrtGrad.pbtxt | 6 ++++++ .../java_api/api_def_SampleDistortedBoundingBox.pbtxt | 6 ++++++ .../java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Save.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SaveSlices.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ScalarSummary.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ScanDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ScatterAdd.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ScatterDiv.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ScatterMax.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ScatterMin.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ScatterMul.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ScatterNd.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ScatterNdAdd.pbtxt | 3 +++ .../api_def/java_api/api_def_ScatterNdNonAliasingAdd.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ScatterNdSub.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ScatterNdUpdate.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ScatterSub.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ScatterUpdate.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_SdcaFprint.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SdcaOptimizer.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SdcaShrinkL1.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SegmentMax.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SegmentMean.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SegmentMin.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SegmentProd.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SegmentSum.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Select.pbtxt | 3 +++ .../core/api_def/java_api/api_def_SelfAdjointEig.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Selu.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SeluGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SerializeIterator.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SerializeManySparse.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SerializeSparse.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SerializeTensor.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SetSize.pbtxt | 3 +++ .../java_api/api_def_SetStatsAggregatorDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Shape.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_ShapeN.pbtxt | 3 +++ .../core/api_def/java_api/api_def_ShardedFilename.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ShardedFilespec.pbtxt | 6 ++++++ .../api_def/java_api/api_def_ShuffleAndRepeatDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_ShuffleDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Sigmoid.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SigmoidGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Sign.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Sin.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Sinh.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Size.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_SkipDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Skipgram.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Slice.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_SlideDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Snapshot.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Softmax.pbtxt | 6 ++++++ .../java_api/api_def_SoftmaxCrossEntropyWithLogits.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Softplus.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SoftplusGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Softsign.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SoftsignGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SpaceToBatch.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SpaceToBatchND.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SpaceToDepth.pbtxt | 6 ++++++ .../java_api/api_def_SparseAccumulatorApplyGradient.pbtxt | 6 ++++++ .../java_api/api_def_SparseAccumulatorTakeGradient.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SparseAdd.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseAddGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseApplyAdadelta.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseApplyAdagrad.pbtxt | 6 ++++++ .../api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt | 6 ++++++ .../java_api/api_def_SparseApplyCenteredRMSProp.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseApplyMomentum.pbtxt | 6 ++++++ .../java_api/api_def_SparseApplyProximalAdagrad.pbtxt | 6 ++++++ .../api_def_SparseApplyProximalGradientDescent.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SparseConcat.pbtxt | 6 ++++++ .../java_api/api_def_SparseConditionalAccumulator.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SparseCross.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseDenseCwiseAdd.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseDenseCwiseDiv.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseDenseCwiseMul.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseFillEmptyRows.pbtxt | 6 ++++++ .../api_def/java_api/api_def_SparseFillEmptyRowsGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SparseMatMul.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseReduceMax.pbtxt | 6 ++++++ .../api_def/java_api/api_def_SparseReduceMaxSparse.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseReduceSum.pbtxt | 6 ++++++ .../api_def/java_api/api_def_SparseReduceSumSparse.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseReorder.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseReshape.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseSegmentMean.pbtxt | 6 ++++++ .../api_def/java_api/api_def_SparseSegmentMeanGrad.pbtxt | 6 ++++++ .../java_api/api_def_SparseSegmentMeanWithNumSegments.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseSegmentSqrtN.pbtxt | 6 ++++++ .../api_def/java_api/api_def_SparseSegmentSqrtNGrad.pbtxt | 6 ++++++ .../api_def_SparseSegmentSqrtNWithNumSegments.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseSegmentSum.pbtxt | 6 ++++++ .../java_api/api_def_SparseSegmentSumWithNumSegments.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SparseSlice.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseSliceGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseSoftmax.pbtxt | 6 ++++++ .../api_def_SparseSoftmaxCrossEntropyWithLogits.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseSparseMaximum.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseSparseMinimum.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SparseSplit.pbtxt | 6 ++++++ .../api_def/java_api/api_def_SparseTensorDenseAdd.pbtxt | 6 ++++++ .../api_def/java_api/api_def_SparseTensorDenseMatMul.pbtxt | 6 ++++++ .../api_def/java_api/api_def_SparseTensorSliceDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SparseToDense.pbtxt | 6 ++++++ .../java_api/api_def_SparseToSparseSetOperation.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Split.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_SplitV.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_SqlDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Sqrt.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_SqrtGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Square.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_SquaredDifference.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Squeeze.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Stack.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Stage.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StageClear.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StagePeek.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StageSize.pbtxt | 3 +++ .../api_def/java_api/api_def_StatefulPartitionedCall.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StatelessIf.pbtxt | 3 +++ .../api_def/java_api/api_def_StatelessMultinomial.pbtxt | 6 ++++++ .../api_def/java_api/api_def_StatelessRandomNormal.pbtxt | 6 ++++++ .../api_def/java_api/api_def_StatelessRandomUniform.pbtxt | 6 ++++++ .../java_api/api_def_StatelessRandomUniformInt.pbtxt | 6 ++++++ .../api_def/java_api/api_def_StatelessTruncatedNormal.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_StatelessWhile.pbtxt | 3 +++ .../api_def/java_api/api_def_StaticRegexFullMatch.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_StaticRegexReplace.pbtxt | 6 ++++++ .../api_def/java_api/api_def_StatsAggregatorHandle.pbtxt | 6 ++++++ .../api_def/java_api/api_def_StatsAggregatorSummary.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_StopGradient.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StridedSlice.pbtxt | 3 +++ .../core/api_def/java_api/api_def_StridedSliceAssign.pbtxt | 3 +++ .../core/api_def/java_api/api_def_StridedSliceGrad.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StringFormat.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_StringJoin.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_StringLength.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_StringSplitV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_StringStrip.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_StringToHashBucket.pbtxt | 6 ++++++ .../api_def/java_api/api_def_StringToHashBucketFast.pbtxt | 6 ++++++ .../api_def/java_api/api_def_StringToHashBucketStrong.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_StringToNumber.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Sub.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Substr.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Sum.pbtxt | 3 +++ .../core/api_def/java_api/api_def_SummaryWriter.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Svd.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Switch.pbtxt | 6 ++++-- .../core/api_def/java_api/api_def_SymbolicGradient.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TFRecordDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TFRecordReader.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_TakeDataset.pbtxt | 6 ++++++ .../java_api/api_def_TakeManySparseFromTensorsMap.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Tan.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Tanh.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_TanhGrad.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TemporaryVariable.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayClose.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayConcat.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayGather.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayGrad.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt | 3 +++ .../api_def/java_api/api_def_TensorArrayGradWithShape.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayPack.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayRead.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayScatter.pbtxt | 3 +++ .../api_def/java_api/api_def_TensorArrayScatterV2.pbtxt | 3 +++ .../api_def/java_api/api_def_TensorArrayScatterV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArraySize.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArraySplit.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayUnpack.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayWrite.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorDataset.pbtxt | 6 ++++++ .../java_api/api_def_TensorForestCreateTreeVariable.pbtxt | 3 +++ .../java_api/api_def_TensorForestTreeDeserialize.pbtxt | 3 +++ .../java_api/api_def_TensorForestTreeIsInitializedOp.pbtxt | 3 +++ .../api_def/java_api/api_def_TensorForestTreePredict.pbtxt | 3 +++ .../java_api/api_def_TensorForestTreeResourceHandleOp.pbtxt | 3 +++ .../java_api/api_def_TensorForestTreeSerialize.pbtxt | 3 +++ .../api_def/java_api/api_def_TensorForestTreeSize.pbtxt | 3 +++ .../api_def/java_api/api_def_TensorListConcatLists.pbtxt | 3 +++ .../api_def/java_api/api_def_TensorListElementShape.pbtxt | 3 +++ .../api_def/java_api/api_def_TensorListFromTensor.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorListGather.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorListGetItem.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorListLength.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorListPopBack.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorListPushBack.pbtxt | 3 +++ .../api_def/java_api/api_def_TensorListPushBackBatch.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorListReserve.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorListScatter.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorListSetItem.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorListStack.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorSliceDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TensorSummary.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TensorSummaryV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TextLineDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TextLineReader.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TextLineReaderV2.pbtxt | 6 ++++++ .../api_def_ThreadUnsafeUnigramCandidateSampler.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Tile.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_TileGrad.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Timestamp.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_TopK.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Transpose.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_TruncateDiv.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_TruncateMod.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_TruncatedNormal.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_TryRpc.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Unbatch.pbtxt | 3 +++ .../core/api_def/java_api/api_def_UnbatchDataset.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_UnbatchGrad.pbtxt | 3 +++ .../api_def/java_api/api_def_UnicodeDecodeWithOffsets.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_UnicodeScript.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_UnicodeTranscode.pbtxt | 6 ++++++ .../api_def/java_api/api_def_UniformCandidateSampler.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Unique.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_UniqueWithCounts.pbtxt | 3 +++ .../core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Unpack.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_UnravelIndex.pbtxt | 3 +++ .../core/api_def/java_api/api_def_UnsortedSegmentMax.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_UnsortedSegmentMin.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_UnsortedSegmentProd.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_UnsortedSegmentSum.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Unstage.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_UpperBound.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_VarHandleOp.pbtxt | 3 +++ .../core/api_def/java_api/api_def_VarIsInitializedOp.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Variable.pbtxt | 3 +++ .../core/api_def/java_api/api_def_VariableShape.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Where.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_While.pbtxt | 3 +++ .../core/api_def/java_api/api_def_WholeFileReader.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_WindowDataset.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_WriteAudioSummary.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_WriteFile.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_WriteGraphSummary.pbtxt | 6 ++++++ .../api_def/java_api/api_def_WriteHistogramSummary.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_WriteImageSummary.pbtxt | 6 ++++++ .../core/api_def/java_api/api_def_WriteScalarSummary.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_WriteSummary.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Xdivy.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_Xlogy.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ZerosLike.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Zeta.pbtxt | 6 ++++++ tensorflow/core/api_def/java_api/api_def_ZipDataset.pbtxt | 6 ++++++ 997 files changed, 5031 insertions(+), 6 deletions(-) create mode 100644 tensorflow/core/api_def/java_api/api_def_Abort.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Abs.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AccumulateNV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AccumulatorApplyGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AccumulatorNumAccumulated.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AccumulatorSetGlobalStep.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AccumulatorTakeGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Acos.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Acosh.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Add.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AddManySparseToTensorsMap.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AddN.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AddSparseToTensorsMap.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AdjustContrast.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AdjustContrastv2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AdjustHue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AdjustSaturation.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_All.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AllCandidateSampler.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Angle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AnonymousIterator.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Any.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyAdaMax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyAdadelta.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyAdagrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyAdam.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyAddSign.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyGradientDescent.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyMomentum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyPowerSign.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyProximalAdagrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyProximalGradientDescent.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ApproximateEqual.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ArgMax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ArgMin.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AsString.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Asin.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Asinh.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Assign.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AssignAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AssignAddVariableOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AssignSub.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AssignSubVariableOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AssignVariableOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Atan.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Atan2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Atanh.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AudioSpectrogram.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AudioSummaryV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AvgPool.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AvgPool3D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_AvgPoolGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Barrier.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BarrierClose.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BarrierIncompleteSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BarrierInsertMany.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BarrierReadySize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BarrierTakeMany.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Batch.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchCholesky.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchCholeskyGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchDatasetV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchFunction.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatMul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatrixBandPart.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatrixDeterminant.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatrixDiag.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatrixDiagPart.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatrixInverse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatrixSetDiag.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatrixSolve.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatrixSolveLs.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchMatrixTriangularSolve.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchNormWithGlobalNormalization.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchNormWithGlobalNormalizationGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchSvd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchToSpace.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BatchToSpaceND.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BesselI0e.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BesselI1e.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Betainc.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BiasAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BiasAddGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BigQueryReader.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Bincount.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Bitcast.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BitwiseAnd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BitwiseOr.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BitwiseXor.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesBucketize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesCalculateBestGainsPerFeature.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesCenterBias.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesCreateEnsemble.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesCreateQuantileStreamResource.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesDeserializeEnsemble.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesEnsembleResourceHandleOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesExampleDebugOutputs.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesGetEnsembleStates.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesMakeQuantileSummaries.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesMakeStatsSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesPredict.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceAddSummaries.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceDeserialize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceFlush.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceGetBucketBoundaries.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceHandleOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesSerializeEnsemble.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesTrainingPredict.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BoostedTreesUpdateEnsemble.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BroadcastArgs.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BroadcastGradientArgs.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BroadcastTo.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Bucketize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_BytesProducedStatsDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CacheDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Cast.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Ceil.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CheckNumerics.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Cholesky.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CholeskyGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ClipByValue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CloseSummaryWriter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CollectiveBcastRecv.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CollectiveBcastSend.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CollectiveReduce.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CompareAndBitpack.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Complex.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ComplexAbs.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ComputeAccidentalHits.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Concat.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ConcatOffset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ConcatenateDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ConditionalAccumulator.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Conj.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ConjugateTranspose.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ConsumeMutexLock.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ControlTrigger.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Cos.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Cosh.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CountUpTo.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CreateSummaryDbWriter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CreateSummaryFileWriter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CropAndResize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CropAndResizeGradBoxes.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CropAndResizeGradImage.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Cross.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CudnnRNNCanonicalToParams.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsToCanonical.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Cumprod.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Cumsum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DataFormatDimMap.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DataFormatVecPermute.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DatasetToGraph.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DatasetToSingleElement.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DebugGradientIdentity.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DebugGradientRefIdentity.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeAndCropJpeg.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeBase64.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeBmp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeCompressed.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeGif.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeJSONExample.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeJpeg.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodePng.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeProtoV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeRaw.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DecodeWav.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DeepCopy.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DeleteSessionTensor.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DenseToDenseSetOperation.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DenseToSparseBatchDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DenseToSparseSetOperation.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DepthToSpace.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNative.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNativeBackpropFilter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNativeBackpropInput.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Dequantize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DeserializeIterator.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DeserializeManySparse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DeserializeSparse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DestroyResourceOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DestroyTemporaryVariable.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Diag.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DiagPart.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Digamma.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Dilation2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Div.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DivNoNan.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DrawBoundingBoxes.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DynamicPartition.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_DynamicStitch.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EagerPyFunc.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EditDistance.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Elu.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EluGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Empty.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EmptyTensorList.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EncodeBase64.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EncodeJpeg.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EncodePng.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EncodeProto.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EncodeWav.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EnqueueInQueueDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_EnsureShape.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Enter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Equal.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Erf.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Erfc.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Exit.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Exp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExpandDims.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalAssertNextDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalDirectedInterleaveDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResource.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResourceGetNext.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResourceReset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalIdentityIndexedDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalIgnoreErrorsDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalIndexedDatasetGet.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalIndexedDatasetMaterialize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalIteratorGetDevice.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalMapDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalMaterializedIndexDatasetHandle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalNonSerializableDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalNumaMapAndBatchDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalSleepDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalThreadPoolDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalThreadPoolHandle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExperimentalUniqueDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Expm1.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExtractGlimpse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExtractImagePatches.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExtractJpegShape.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ExtractVolumePatches.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FFT.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FFT2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FFT3D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Fact.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FakeParam.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxArgs.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxArgsGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVars.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsPerChannel.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsPerChannelGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FakeQueue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Fill.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FilterByLastComponentDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FilterDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDatasetV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReader.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReaderV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FixedUnigramCandidateSampler.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FlatMapDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Floor.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FloorDiv.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FloorMod.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FlushSummaryWriter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_For.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FractionalAvgPool.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FractionalAvgPoolGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FractionalMaxPool.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FractionalMaxPoolGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FusedBatchNorm.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FusedPadConv2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Gather.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GatherNd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GcsConfigureBlockCache.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GcsConfigureCredentials.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GenerateBigQueryReaderPartitions.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GenerateVocabRemapping.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GeneratorDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GetSessionHandle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GetSessionTensor.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Greater.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GreaterEqual.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GroupByReducerDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GroupByWindowDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_GuaranteeConst.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_HSVToRGB.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_HistogramFixedWidth.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_HistogramSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_HostConst.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IFFT.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IFFT2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IFFT3D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Identity.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IdentityN.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IdentityReader.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IdentityReaderV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_If.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Igamma.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IgammaGradA.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Igammac.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Imag.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ImageSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ImmutableConst.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ImportEvent.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InitializeTable.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFile.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFileV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InitializeTableV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InplaceAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InplaceSub.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InplaceUpdate.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InterleaveDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Inv.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InvGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Invert.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_InvertPermutation.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IsBoostedTreesEnsembleInitialized.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IsBoostedTreesQuantileStreamResourceInitialized.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IsFinite.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IsInf.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IsNan.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IsVariableInitialized.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandleV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IteratorGetNext.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IteratorGetNextAsOptional.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IteratorGetNextSync.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IteratorToStringHandle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_L2Loss.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LRN.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LRNGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LatencyStatsDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LeakyRelu.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LeakyReluGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LearnedUnigramCandidateSampler.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LeftShift.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Less.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LessEqual.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Lgamma.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LinSpace.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LoadAndRemapMatrix.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Log.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Log1p.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LogMatrixDeterminant.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LogSoftmax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LogUniformCandidateSampler.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LogicalAnd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LogicalNot.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LogicalOr.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableExport.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableExportV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableFind.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableFindV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableImport.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableImportV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableInsert.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LoopCond.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_LowerBound.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MakeIterator.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapClear.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapDefun.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapIncompleteSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapPeek.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapStage.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapUnstage.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MapUnstageNoKey.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatMul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatchingFiles.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatchingFilesDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixBandPart.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixDeterminant.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixDiag.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixDiagPart.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixExponential.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixInverse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixLogarithm.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixSetDiag.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixSolve.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixSolveLs.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixSquareRoot.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MatrixTriangularSolve.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Max.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPool3D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradWithArgmax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPoolGradWithArgmax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MaxPoolWithArgmax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Maximum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Mean.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Merge.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MergeSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MergeV2Checkpoints.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Mfcc.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Min.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Minimum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MirrorPad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MirrorPadGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Mod.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ModelDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Mul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MultiDeviceIterator.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorFromStringHandle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorGetNextFromShard.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorInit.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorToStringHandle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Multinomial.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MutableDenseHashTable.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MutableHashTable.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensors.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensorsV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MutableHashTableV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MutexLock.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NcclAllReduce.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NcclBroadcast.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NcclReduce.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Neg.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NegTrain.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NextIteration.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NoOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NonMaxSuppression.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionWithOverlaps.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NotEqual.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_NthElement.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OneHot.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OneShotIterator.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OnesLike.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OptimizeDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OptionalFromValue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OptionalGetValue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OptionalHasValue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OptionalNone.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OrderedMapClear.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OrderedMapIncompleteSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OrderedMapPeek.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OrderedMapSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OrderedMapStage.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OrderedMapUnstage.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_OrderedMapUnstageNoKey.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Pack.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Pad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParallelConcat.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParallelDynamicStitch.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDatasetV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParallelMapDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParameterizedTruncatedNormal.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParseExample.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParseExampleDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParseSequenceExample.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParseSingleExample.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParseSingleSequenceExample.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ParseTensor.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PartitionedCall.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PlaceholderWithDefault.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Polygamma.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PopulationCount.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Pow.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PrefetchDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PrependFromQueueAndPaddedBatchDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PreventGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Print.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PriorityQueue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PriorityQueueV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Prod.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PyFunc.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_PyFuncStateless.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Qr.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizeDownAndShrinkRange.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedAvgPool.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedBatchNormWithGlobalNormalization.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedBiasAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedConcat.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedConv2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedInstanceNorm.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedMatMul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedMaxPool.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedMul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedRelu.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedRelu6.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedReluX.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedReshape.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QuantizedResizeBilinear.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueDequeueMany.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueDequeueV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueIsClosed.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RGBToHSV.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RaggedGather.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RaggedRange.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RaggedTensorToSparse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomCrop.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomGamma.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomGammaGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomPoisson.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomPoissonV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomShuffle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomStandardNormal.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomUniform.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RandomUniformInt.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Range.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RangeDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Rank.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReadFile.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReadVariableOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProducedV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderResetV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderRestoreState.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderSerializeState.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Real.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RealDiv.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Reciprocal.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReciprocalGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RecordInput.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReduceDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReduceJoin.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RefEnter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RefExit.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RefIdentity.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RefMerge.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RefNextIteration.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RefSelect.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RefSwitch.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RegexFullMatch.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RegexReplace.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Relu.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Relu6.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Relu6Grad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReluGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RemoteCall.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RemoteFusedGraphExecute.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RepeatDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RequantizationRange.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Requantize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Reshape.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResizeArea.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResizeBicubic.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResizeBicubicGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResizeBilinear.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResizeBilinearGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResizeNearestNeighbor.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResizeNearestNeighborGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyAdaMax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyAdadelta.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyAdam.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyAddSign.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyGradientDescent.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyMomentum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyPowerSign.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyProximalAdagrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyProximalGradientDescent.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceCountUpTo.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceGather.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceScatterAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceScatterDiv.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceScatterMax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceScatterMin.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceScatterMul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceScatterNdAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceScatterNdUpdate.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceScatterSub.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceScatterUpdate.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdadelta.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyCenteredRMSProp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyMomentum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyProximalAdagrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyProximalGradientDescent.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyRMSProp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ResourceStridedSliceAssign.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Restore.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RestoreSlice.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReverseSequence.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ReverseV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RightShift.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Rint.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Roll.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Round.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Rpc.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Rsqrt.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_RsqrtGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBox.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Save.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SaveSlices.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScalarSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScanDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterDiv.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterMax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterMin.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterMul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterNd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterNdAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterNdNonAliasingAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterNdSub.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterNdUpdate.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterSub.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ScatterUpdate.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SdcaFprint.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SdcaOptimizer.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SdcaShrinkL1.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SegmentMax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SegmentMean.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SegmentMin.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SegmentProd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SegmentSum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Select.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SelfAdjointEig.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Selu.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SeluGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SerializeIterator.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SerializeManySparse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SerializeSparse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SerializeTensor.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SetSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SetStatsAggregatorDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Shape.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ShapeN.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ShardedFilename.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ShardedFilespec.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ShuffleAndRepeatDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ShuffleDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Sigmoid.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SigmoidGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Sign.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Sin.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Sinh.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Size.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SkipDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Skipgram.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Slice.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SlideDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Snapshot.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Softmax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SoftmaxCrossEntropyWithLogits.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Softplus.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SoftplusGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Softsign.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SoftsignGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SpaceToBatch.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SpaceToBatchND.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SpaceToDepth.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseAccumulatorApplyGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseAccumulatorTakeGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseAddGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyAdadelta.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyAdagrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyCenteredRMSProp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyMomentum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyProximalAdagrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyProximalGradientDescent.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseConcat.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseConditionalAccumulator.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseCross.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseDiv.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseMul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseFillEmptyRows.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseFillEmptyRowsGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseMatMul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseReduceMax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseReduceMaxSparse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseReduceSum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseReduceSumSparse.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseReorder.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseReshape.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSegmentMean.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSegmentMeanGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSegmentMeanWithNumSegments.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtN.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtNGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtNWithNumSegments.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSegmentSum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSegmentSumWithNumSegments.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSlice.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSliceGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSoftmax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSoftmaxCrossEntropyWithLogits.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSparseMaximum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSparseMinimum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseSplit.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseTensorDenseAdd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseTensorDenseMatMul.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseTensorSliceDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseToDense.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SparseToSparseSetOperation.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Split.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SplitV.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SqlDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Sqrt.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SqrtGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Square.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SquaredDifference.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Squeeze.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Stack.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Stage.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StageClear.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StagePeek.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StageSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatefulPartitionedCall.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatelessIf.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatelessMultinomial.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatelessRandomNormal.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatelessRandomUniform.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatelessRandomUniformInt.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatelessTruncatedNormal.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatelessWhile.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StaticRegexFullMatch.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StaticRegexReplace.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatsAggregatorHandle.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StatsAggregatorSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StopGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StridedSlice.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StridedSliceAssign.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StridedSliceGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringFormat.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringJoin.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringLength.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringSplitV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringStrip.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringToHashBucket.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringToHashBucketFast.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringToHashBucketStrong.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_StringToNumber.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Sub.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Substr.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Sum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SummaryWriter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Svd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_SymbolicGradient.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TFRecordDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TakeDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TakeManySparseFromTensorsMap.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Tan.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Tanh.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TanhGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TemporaryVariable.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayClose.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayConcat.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayGather.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayGradWithShape.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayPack.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayRead.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayScatter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArraySize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArraySplit.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayUnpack.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayWrite.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorForestCreateTreeVariable.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorForestTreeDeserialize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorForestTreeIsInitializedOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorForestTreePredict.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorForestTreeResourceHandleOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorForestTreeSerialize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorForestTreeSize.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListConcatLists.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListElementShape.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListFromTensor.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListGather.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListGetItem.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListLength.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListPopBack.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListPushBack.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListPushBackBatch.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListReserve.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListScatter.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListSetItem.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorListStack.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorSliceDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TensorSummaryV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TextLineDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TextLineReader.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TextLineReaderV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ThreadUnsafeUnigramCandidateSampler.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Tile.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TileGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Timestamp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TopK.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Transpose.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TruncateDiv.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TruncateMod.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TruncatedNormal.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_TryRpc.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Unbatch.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnbatchDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnbatchGrad.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnicodeDecodeWithOffsets.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnicodeScript.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnicodeTranscode.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UniformCandidateSampler.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Unique.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UniqueWithCounts.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Unpack.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnravelIndex.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnsortedSegmentMax.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnsortedSegmentMin.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnsortedSegmentProd.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UnsortedSegmentSum.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Unstage.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_UpperBound.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_VarHandleOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_VarIsInitializedOp.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Variable.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_VariableShape.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Where.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_While.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WholeFileReader.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WindowDataset.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WriteAudioSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WriteFile.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WriteGraphSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WriteHistogramSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WriteImageSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WriteScalarSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_WriteSummary.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Xdivy.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Xlogy.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ZerosLike.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_Zeta.pbtxt create mode 100644 tensorflow/core/api_def/java_api/api_def_ZipDataset.pbtxt diff --git a/tensorflow/core/api_def/java_api/api_def_Abort.pbtxt b/tensorflow/core/api_def/java_api/api_def_Abort.pbtxt new file mode 100644 index 0000000000..58448c2d17 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Abort.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Abort" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Abs.pbtxt b/tensorflow/core/api_def/java_api/api_def_Abs.pbtxt new file mode 100644 index 0000000000..ece45cf73f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Abs.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Abs" + endpoint { + name: "math.Abs" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AccumulateNV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_AccumulateNV2.pbtxt new file mode 100644 index 0000000000..09e7a155e0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AccumulateNV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AccumulateNV2" + endpoint { + name: "math.AccumulateNV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AccumulatorApplyGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_AccumulatorApplyGradient.pbtxt new file mode 100644 index 0000000000..49b7acad7d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AccumulatorApplyGradient.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AccumulatorApplyGradient" + endpoint { + name: "train.AccumulatorApplyGradient" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AccumulatorNumAccumulated.pbtxt b/tensorflow/core/api_def/java_api/api_def_AccumulatorNumAccumulated.pbtxt new file mode 100644 index 0000000000..1c42e819bf --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AccumulatorNumAccumulated.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AccumulatorNumAccumulated" + endpoint { + name: "train.AccumulatorNumAccumulated" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AccumulatorSetGlobalStep.pbtxt b/tensorflow/core/api_def/java_api/api_def_AccumulatorSetGlobalStep.pbtxt new file mode 100644 index 0000000000..ca85302cdb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AccumulatorSetGlobalStep.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AccumulatorSetGlobalStep" + endpoint { + name: "train.AccumulatorSetGlobalStep" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AccumulatorTakeGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_AccumulatorTakeGradient.pbtxt new file mode 100644 index 0000000000..4883802c63 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AccumulatorTakeGradient.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AccumulatorTakeGradient" + endpoint { + name: "train.AccumulatorTakeGradient" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Acos.pbtxt b/tensorflow/core/api_def/java_api/api_def_Acos.pbtxt new file mode 100644 index 0000000000..847986b429 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Acos.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Acos" + endpoint { + name: "math.Acos" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Acosh.pbtxt b/tensorflow/core/api_def/java_api/api_def_Acosh.pbtxt new file mode 100644 index 0000000000..76d8f5fad0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Acosh.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Acosh" + endpoint { + name: "math.Acosh" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Add.pbtxt b/tensorflow/core/api_def/java_api/api_def_Add.pbtxt new file mode 100644 index 0000000000..4f78ccc9ea --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Add.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Add" + endpoint { + name: "math.Add" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AddManySparseToTensorsMap.pbtxt b/tensorflow/core/api_def/java_api/api_def_AddManySparseToTensorsMap.pbtxt new file mode 100644 index 0000000000..e009ba19d3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AddManySparseToTensorsMap.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AddManySparseToTensorsMap" + endpoint { + name: "sparse.AddManySparseToTensorsMap" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AddN.pbtxt b/tensorflow/core/api_def/java_api/api_def_AddN.pbtxt new file mode 100644 index 0000000000..20d469ae73 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AddN.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AddN" + endpoint { + name: "math.AddN" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AddSparseToTensorsMap.pbtxt b/tensorflow/core/api_def/java_api/api_def_AddSparseToTensorsMap.pbtxt new file mode 100644 index 0000000000..0bb20186de --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AddSparseToTensorsMap.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AddSparseToTensorsMap" + endpoint { + name: "sparse.AddSparseToTensorsMap" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt new file mode 100644 index 0000000000..f42a2add07 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AddV2" + endpoint { + name: "math.AddV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AdjustContrast.pbtxt b/tensorflow/core/api_def/java_api/api_def_AdjustContrast.pbtxt new file mode 100644 index 0000000000..ff49aec2db --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AdjustContrast.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AdjustContrast" + endpoint { + name: "image.AdjustContrast" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AdjustContrastv2.pbtxt b/tensorflow/core/api_def/java_api/api_def_AdjustContrastv2.pbtxt new file mode 100644 index 0000000000..dd6647b137 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AdjustContrastv2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AdjustContrastv2" + endpoint { + name: "image.AdjustContrastv2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AdjustHue.pbtxt b/tensorflow/core/api_def/java_api/api_def_AdjustHue.pbtxt new file mode 100644 index 0000000000..0847cad403 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AdjustHue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AdjustHue" + endpoint { + name: "image.AdjustHue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AdjustSaturation.pbtxt b/tensorflow/core/api_def/java_api/api_def_AdjustSaturation.pbtxt new file mode 100644 index 0000000000..d685636eb1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AdjustSaturation.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AdjustSaturation" + endpoint { + name: "image.AdjustSaturation" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_All.pbtxt b/tensorflow/core/api_def/java_api/api_def_All.pbtxt new file mode 100644 index 0000000000..a6459c56b7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_All.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "All" +} diff --git a/tensorflow/core/api_def/java_api/api_def_AllCandidateSampler.pbtxt b/tensorflow/core/api_def/java_api/api_def_AllCandidateSampler.pbtxt new file mode 100644 index 0000000000..607c208a46 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AllCandidateSampler.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AllCandidateSampler" + endpoint { + name: "random.AllCandidateSampler" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Angle.pbtxt b/tensorflow/core/api_def/java_api/api_def_Angle.pbtxt new file mode 100644 index 0000000000..a92ccf357d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Angle.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Angle" + endpoint { + name: "math.Angle" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AnonymousIterator.pbtxt b/tensorflow/core/api_def/java_api/api_def_AnonymousIterator.pbtxt new file mode 100644 index 0000000000..894f85ae88 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AnonymousIterator.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AnonymousIterator" + endpoint { + name: "data.AnonymousIterator" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Any.pbtxt b/tensorflow/core/api_def/java_api/api_def_Any.pbtxt new file mode 100644 index 0000000000..20b36eda3f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Any.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Any" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyAdaMax.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyAdaMax.pbtxt new file mode 100644 index 0000000000..583f164e06 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyAdaMax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyAdaMax" + endpoint { + name: "train.ApplyAdaMax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyAdadelta.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyAdadelta.pbtxt new file mode 100644 index 0000000000..e672a8ef03 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyAdadelta.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyAdadelta" + endpoint { + name: "train.ApplyAdadelta" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyAdagrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyAdagrad.pbtxt new file mode 100644 index 0000000000..980c57c5fe --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyAdagrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyAdagrad" + endpoint { + name: "train.ApplyAdagrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt new file mode 100644 index 0000000000..d2b38707fb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyAdagradDA" + endpoint { + name: "train.ApplyAdagradDA" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyAdam.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyAdam.pbtxt new file mode 100644 index 0000000000..56461b1d3d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyAdam.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyAdam" + endpoint { + name: "train.ApplyAdam" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyAddSign.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyAddSign.pbtxt new file mode 100644 index 0000000000..b54ff6eca4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyAddSign.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyAddSign" + endpoint { + name: "train.ApplyAddSign" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt new file mode 100644 index 0000000000..6ed0660165 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyCenteredRMSProp" + endpoint { + name: "train.ApplyCenteredRMSProp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt new file mode 100644 index 0000000000..388e39c6ba --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyFtrl" + endpoint { + name: "train.ApplyFtrl" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt new file mode 100644 index 0000000000..8463ad163b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyFtrlV2" + endpoint { + name: "train.ApplyFtrlV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyGradientDescent.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyGradientDescent.pbtxt new file mode 100644 index 0000000000..1fa569ed32 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyGradientDescent.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyGradientDescent" + endpoint { + name: "train.ApplyGradientDescent" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyMomentum.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyMomentum.pbtxt new file mode 100644 index 0000000000..96c21199f0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyMomentum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyMomentum" + endpoint { + name: "train.ApplyMomentum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyPowerSign.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyPowerSign.pbtxt new file mode 100644 index 0000000000..e5c2234755 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyPowerSign.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyPowerSign" + endpoint { + name: "train.ApplyPowerSign" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyProximalAdagrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyProximalAdagrad.pbtxt new file mode 100644 index 0000000000..a52d8c3591 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyProximalAdagrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyProximalAdagrad" + endpoint { + name: "train.ApplyProximalAdagrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyProximalGradientDescent.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyProximalGradientDescent.pbtxt new file mode 100644 index 0000000000..74ea29cf88 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyProximalGradientDescent.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyProximalGradientDescent" + endpoint { + name: "train.ApplyProximalGradientDescent" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt new file mode 100644 index 0000000000..a1397b16fc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApplyRMSProp" + endpoint { + name: "train.ApplyRMSProp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ApproximateEqual.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApproximateEqual.pbtxt new file mode 100644 index 0000000000..029dc6d293 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ApproximateEqual.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ApproximateEqual" + endpoint { + name: "math.ApproximateEqual" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ArgMax.pbtxt b/tensorflow/core/api_def/java_api/api_def_ArgMax.pbtxt new file mode 100644 index 0000000000..f9effd49c4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ArgMax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ArgMax" + endpoint { + name: "math.ArgMax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ArgMin.pbtxt b/tensorflow/core/api_def/java_api/api_def_ArgMin.pbtxt new file mode 100644 index 0000000000..5ff04c0d1a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ArgMin.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ArgMin" + endpoint { + name: "math.ArgMin" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AsString.pbtxt b/tensorflow/core/api_def/java_api/api_def_AsString.pbtxt new file mode 100644 index 0000000000..e8c875ea81 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AsString.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AsString" + endpoint { + name: "dtypes.AsString" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Asin.pbtxt b/tensorflow/core/api_def/java_api/api_def_Asin.pbtxt new file mode 100644 index 0000000000..8ffc8e3e57 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Asin.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Asin" + endpoint { + name: "math.Asin" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Asinh.pbtxt b/tensorflow/core/api_def/java_api/api_def_Asinh.pbtxt new file mode 100644 index 0000000000..e3b30dd512 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Asinh.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Asinh" + endpoint { + name: "math.Asinh" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Assert.pbtxt b/tensorflow/core/api_def/java_api/api_def_Assert.pbtxt index b1f868897d..a9e107b478 100644 --- a/tensorflow/core/api_def/java_api/api_def_Assert.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Assert.pbtxt @@ -1,4 +1,6 @@ op { - graph_op_name: "Assert" #TODO(karllessard) escape that reserved name - visibility: HIDDEN + graph_op_name: "Assert" + endpoint { + name: "AssertThat" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_Assign.pbtxt b/tensorflow/core/api_def/java_api/api_def_Assign.pbtxt new file mode 100644 index 0000000000..15d778f61e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Assign.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Assign" +} diff --git a/tensorflow/core/api_def/java_api/api_def_AssignAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_AssignAdd.pbtxt new file mode 100644 index 0000000000..a4118b64af --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AssignAdd.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "AssignAdd" +} diff --git a/tensorflow/core/api_def/java_api/api_def_AssignAddVariableOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_AssignAddVariableOp.pbtxt new file mode 100644 index 0000000000..05fecb191b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AssignAddVariableOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "AssignAddVariableOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_AssignSub.pbtxt b/tensorflow/core/api_def/java_api/api_def_AssignSub.pbtxt new file mode 100644 index 0000000000..aaf9246a6a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AssignSub.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "AssignSub" +} diff --git a/tensorflow/core/api_def/java_api/api_def_AssignSubVariableOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_AssignSubVariableOp.pbtxt new file mode 100644 index 0000000000..6e8791aed2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AssignSubVariableOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "AssignSubVariableOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_AssignVariableOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_AssignVariableOp.pbtxt new file mode 100644 index 0000000000..980e696826 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AssignVariableOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "AssignVariableOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Atan.pbtxt b/tensorflow/core/api_def/java_api/api_def_Atan.pbtxt new file mode 100644 index 0000000000..e51aee9abc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Atan.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Atan" + endpoint { + name: "math.Atan" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Atan2.pbtxt b/tensorflow/core/api_def/java_api/api_def_Atan2.pbtxt new file mode 100644 index 0000000000..302b05f9dc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Atan2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Atan2" + endpoint { + name: "math.Atan2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Atanh.pbtxt b/tensorflow/core/api_def/java_api/api_def_Atanh.pbtxt new file mode 100644 index 0000000000..b9c4a41154 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Atanh.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Atanh" + endpoint { + name: "math.Atanh" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AudioSpectrogram.pbtxt b/tensorflow/core/api_def/java_api/api_def_AudioSpectrogram.pbtxt new file mode 100644 index 0000000000..bd8f3a5e33 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AudioSpectrogram.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AudioSpectrogram" + endpoint { + name: "audio.AudioSpectrogram" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt new file mode 100644 index 0000000000..026ec79dd9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AudioSummary" + endpoint { + name: "summary.AudioSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AudioSummaryV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_AudioSummaryV2.pbtxt new file mode 100644 index 0000000000..07d24ec3a3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AudioSummaryV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AudioSummaryV2" + endpoint { + name: "summary.AudioSummaryV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AvgPool.pbtxt b/tensorflow/core/api_def/java_api/api_def_AvgPool.pbtxt new file mode 100644 index 0000000000..10d87802f0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AvgPool.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AvgPool" + endpoint { + name: "nn.AvgPool" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AvgPool3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_AvgPool3D.pbtxt new file mode 100644 index 0000000000..1ae2794f48 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AvgPool3D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AvgPool3D" + endpoint { + name: "nn.AvgPool3d" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt new file mode 100644 index 0000000000..ac51715095 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AvgPool3DGrad" + endpoint { + name: "nn.AvgPool3DGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_AvgPoolGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_AvgPoolGrad.pbtxt new file mode 100644 index 0000000000..fc8fec89b9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_AvgPoolGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "AvgPoolGrad" + endpoint { + name: "nn.AvgPoolGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Barrier.pbtxt b/tensorflow/core/api_def/java_api/api_def_Barrier.pbtxt new file mode 100644 index 0000000000..6e282ca7b3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Barrier.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Barrier" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BarrierClose.pbtxt b/tensorflow/core/api_def/java_api/api_def_BarrierClose.pbtxt new file mode 100644 index 0000000000..0307318763 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BarrierClose.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BarrierClose" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BarrierIncompleteSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_BarrierIncompleteSize.pbtxt new file mode 100644 index 0000000000..fb11b18e95 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BarrierIncompleteSize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BarrierIncompleteSize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BarrierInsertMany.pbtxt b/tensorflow/core/api_def/java_api/api_def_BarrierInsertMany.pbtxt new file mode 100644 index 0000000000..32e29f0015 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BarrierInsertMany.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BarrierInsertMany" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BarrierReadySize.pbtxt b/tensorflow/core/api_def/java_api/api_def_BarrierReadySize.pbtxt new file mode 100644 index 0000000000..0ed50b2579 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BarrierReadySize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BarrierReadySize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BarrierTakeMany.pbtxt b/tensorflow/core/api_def/java_api/api_def_BarrierTakeMany.pbtxt new file mode 100644 index 0000000000..21f08878c6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BarrierTakeMany.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BarrierTakeMany" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Batch.pbtxt b/tensorflow/core/api_def/java_api/api_def_Batch.pbtxt new file mode 100644 index 0000000000..2c21faf72d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Batch.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Batch" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchCholesky.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchCholesky.pbtxt new file mode 100644 index 0000000000..15048109fd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchCholesky.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchCholesky" + endpoint { + name: "linalg.BatchCholesky" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchCholeskyGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchCholeskyGrad.pbtxt new file mode 100644 index 0000000000..eb0e2c6bc8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchCholeskyGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchCholeskyGrad" + endpoint { + name: "linalg.BatchCholeskyGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt new file mode 100644 index 0000000000..fe47605f37 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchDataset" + endpoint { + name: "data.BatchDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchDatasetV2.pbtxt new file mode 100644 index 0000000000..079efe146f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchDatasetV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BatchDatasetV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt new file mode 100644 index 0000000000..62bc804c7e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchFFT" + endpoint { + name: "signal.BatchFFT" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt new file mode 100644 index 0000000000..89479537a2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchFFT2D" + endpoint { + name: "signal.BatchFFT2D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt new file mode 100644 index 0000000000..e9cff897bb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchFFT3D" + endpoint { + name: "signal.BatchFFT3D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchFunction.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchFunction.pbtxt new file mode 100644 index 0000000000..8789dc6acb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchFunction.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BatchFunction" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt new file mode 100644 index 0000000000..f156a6df39 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchIFFT" + endpoint { + name: "signal.BatchIFFT" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt new file mode 100644 index 0000000000..7cce88f8f7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchIFFT2D" + endpoint { + name: "signal.BatchIFFT2D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt new file mode 100644 index 0000000000..b30e596d75 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchIFFT3D" + endpoint { + name: "signal.BatchIFFT3D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatMul.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatMul.pbtxt new file mode 100644 index 0000000000..95aa644615 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatMul.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatMul" + endpoint { + name: "linalg.BatchMatMul" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatrixBandPart.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatrixBandPart.pbtxt new file mode 100644 index 0000000000..de989c6d52 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatrixBandPart.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatrixBandPart" + endpoint { + name: "linalg.BatchMatrixBandPart" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatrixDeterminant.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatrixDeterminant.pbtxt new file mode 100644 index 0000000000..a45fe25d10 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatrixDeterminant.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatrixDeterminant" + endpoint { + name: "linalg.BatchMatrixDeterminant" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatrixDiag.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatrixDiag.pbtxt new file mode 100644 index 0000000000..d85d76f02f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatrixDiag.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatrixDiag" + endpoint { + name: "linalg.BatchMatrixDiag" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatrixDiagPart.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatrixDiagPart.pbtxt new file mode 100644 index 0000000000..4b5350b11e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatrixDiagPart.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatrixDiagPart" + endpoint { + name: "linalg.BatchMatrixDiagPart" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatrixInverse.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatrixInverse.pbtxt new file mode 100644 index 0000000000..f40ea50d4b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatrixInverse.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatrixInverse" + endpoint { + name: "linalg.BatchMatrixInverse" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatrixSetDiag.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatrixSetDiag.pbtxt new file mode 100644 index 0000000000..ac4cd6889b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatrixSetDiag.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatrixSetDiag" + endpoint { + name: "linalg.BatchMatrixSetDiag" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatrixSolve.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatrixSolve.pbtxt new file mode 100644 index 0000000000..97435acb4e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatrixSolve.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatrixSolve" + endpoint { + name: "linalg.BatchMatrixSolve" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatrixSolveLs.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatrixSolveLs.pbtxt new file mode 100644 index 0000000000..aee0b4add3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatrixSolveLs.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatrixSolveLs" + endpoint { + name: "linalg.BatchMatrixSolveLs" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchMatrixTriangularSolve.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchMatrixTriangularSolve.pbtxt new file mode 100644 index 0000000000..554eff1574 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchMatrixTriangularSolve.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchMatrixTriangularSolve" + endpoint { + name: "linalg.BatchMatrixTriangularSolve" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchNormWithGlobalNormalization.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchNormWithGlobalNormalization.pbtxt new file mode 100644 index 0000000000..8285ac284d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchNormWithGlobalNormalization.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchNormWithGlobalNormalization" + endpoint { + name: "nn.BatchNormWithGlobalNormalization" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchNormWithGlobalNormalizationGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchNormWithGlobalNormalizationGrad.pbtxt new file mode 100644 index 0000000000..7b18bf52ac --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchNormWithGlobalNormalizationGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchNormWithGlobalNormalizationGrad" + endpoint { + name: "nn.BatchNormWithGlobalNormalizationGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt new file mode 100644 index 0000000000..58d60fa962 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchSelfAdjointEig" + endpoint { + name: "linalg.BatchSelfAdjointEig" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt new file mode 100644 index 0000000000..fb18b2a000 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchSelfAdjointEigV2" + endpoint { + name: "linalg.BatchSelfAdjointEigV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchSvd.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchSvd.pbtxt new file mode 100644 index 0000000000..8696359df8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchSvd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchSvd" + endpoint { + name: "linalg.BatchSvd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchToSpace.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchToSpace.pbtxt new file mode 100644 index 0000000000..affbc519e5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchToSpace.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BatchToSpace" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BatchToSpaceND.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchToSpaceND.pbtxt new file mode 100644 index 0000000000..6c7d2fbdb9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BatchToSpaceND.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BatchToSpaceND" + endpoint { + name: "BatchToSpaceNd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BesselI0e.pbtxt b/tensorflow/core/api_def/java_api/api_def_BesselI0e.pbtxt new file mode 100644 index 0000000000..84eb3b5e71 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BesselI0e.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BesselI0e" + endpoint { + name: "math.BesselI0e" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BesselI1e.pbtxt b/tensorflow/core/api_def/java_api/api_def_BesselI1e.pbtxt new file mode 100644 index 0000000000..43f9113b0b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BesselI1e.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BesselI1e" + endpoint { + name: "math.BesselI1e" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Betainc.pbtxt b/tensorflow/core/api_def/java_api/api_def_Betainc.pbtxt new file mode 100644 index 0000000000..6e9956d9ec --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Betainc.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Betainc" + endpoint { + name: "math.Betainc" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BiasAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_BiasAdd.pbtxt new file mode 100644 index 0000000000..eb3be23bd9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BiasAdd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BiasAdd" + endpoint { + name: "nn.BiasAdd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BiasAddGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_BiasAddGrad.pbtxt new file mode 100644 index 0000000000..4e040bf6df --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BiasAddGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BiasAddGrad" + endpoint { + name: "nn.BiasAddGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt b/tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt new file mode 100644 index 0000000000..76ae8ec8ff --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BiasAddV1" + endpoint { + name: "nn.BiasAddV1" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BigQueryReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_BigQueryReader.pbtxt new file mode 100644 index 0000000000..5b6e11687a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BigQueryReader.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BigQueryReader" + endpoint { + name: "io.BigQueryReader" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Bincount.pbtxt b/tensorflow/core/api_def/java_api/api_def_Bincount.pbtxt new file mode 100644 index 0000000000..b894fd6ec5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Bincount.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Bincount" + endpoint { + name: "math.Bincount" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Bitcast.pbtxt b/tensorflow/core/api_def/java_api/api_def_Bitcast.pbtxt new file mode 100644 index 0000000000..9d2db26851 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Bitcast.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Bitcast" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BitwiseAnd.pbtxt b/tensorflow/core/api_def/java_api/api_def_BitwiseAnd.pbtxt new file mode 100644 index 0000000000..db5fada246 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BitwiseAnd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BitwiseAnd" + endpoint { + name: "bitwise.BitwiseAnd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BitwiseOr.pbtxt b/tensorflow/core/api_def/java_api/api_def_BitwiseOr.pbtxt new file mode 100644 index 0000000000..8f9d1bc2fe --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BitwiseOr.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BitwiseOr" + endpoint { + name: "bitwise.BitwiseOr" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BitwiseXor.pbtxt b/tensorflow/core/api_def/java_api/api_def_BitwiseXor.pbtxt new file mode 100644 index 0000000000..28f405b8ad --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BitwiseXor.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BitwiseXor" + endpoint { + name: "bitwise.BitwiseXor" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesBucketize.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesBucketize.pbtxt new file mode 100644 index 0000000000..acec845ca4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesBucketize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesBucketize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesCalculateBestGainsPerFeature.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesCalculateBestGainsPerFeature.pbtxt new file mode 100644 index 0000000000..fa22216ed5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesCalculateBestGainsPerFeature.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesCalculateBestGainsPerFeature" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesCenterBias.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesCenterBias.pbtxt new file mode 100644 index 0000000000..1b65775a12 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesCenterBias.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesCenterBias" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesCreateEnsemble.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesCreateEnsemble.pbtxt new file mode 100644 index 0000000000..194251d433 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesCreateEnsemble.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesCreateEnsemble" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesCreateQuantileStreamResource.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesCreateQuantileStreamResource.pbtxt new file mode 100644 index 0000000000..7d9c8c9229 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesCreateQuantileStreamResource.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesCreateQuantileStreamResource" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesDeserializeEnsemble.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesDeserializeEnsemble.pbtxt new file mode 100644 index 0000000000..2ed17ca30f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesDeserializeEnsemble.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesDeserializeEnsemble" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesEnsembleResourceHandleOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesEnsembleResourceHandleOp.pbtxt new file mode 100644 index 0000000000..a44c86614a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesEnsembleResourceHandleOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesEnsembleResourceHandleOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesExampleDebugOutputs.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesExampleDebugOutputs.pbtxt new file mode 100644 index 0000000000..4d6f276911 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesExampleDebugOutputs.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesExampleDebugOutputs" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesGetEnsembleStates.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesGetEnsembleStates.pbtxt new file mode 100644 index 0000000000..a591013fb7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesGetEnsembleStates.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesGetEnsembleStates" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesMakeQuantileSummaries.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesMakeQuantileSummaries.pbtxt new file mode 100644 index 0000000000..4e147765a7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesMakeQuantileSummaries.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesMakeQuantileSummaries" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesMakeStatsSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesMakeStatsSummary.pbtxt new file mode 100644 index 0000000000..bbee8bb47c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesMakeStatsSummary.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesMakeStatsSummary" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesPredict.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesPredict.pbtxt new file mode 100644 index 0000000000..e25d43a18f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesPredict.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesPredict" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceAddSummaries.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceAddSummaries.pbtxt new file mode 100644 index 0000000000..d9fe96d3cd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceAddSummaries.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesQuantileStreamResourceAddSummaries" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceDeserialize.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceDeserialize.pbtxt new file mode 100644 index 0000000000..86e8090241 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceDeserialize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesQuantileStreamResourceDeserialize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceFlush.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceFlush.pbtxt new file mode 100644 index 0000000000..c98375bb24 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceFlush.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesQuantileStreamResourceFlush" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceGetBucketBoundaries.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceGetBucketBoundaries.pbtxt new file mode 100644 index 0000000000..e0421be40a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceGetBucketBoundaries.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesQuantileStreamResourceGetBucketBoundaries" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceHandleOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceHandleOp.pbtxt new file mode 100644 index 0000000000..b7f5e8aa65 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesQuantileStreamResourceHandleOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesQuantileStreamResourceHandleOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesSerializeEnsemble.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesSerializeEnsemble.pbtxt new file mode 100644 index 0000000000..db5807344b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesSerializeEnsemble.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesSerializeEnsemble" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesTrainingPredict.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesTrainingPredict.pbtxt new file mode 100644 index 0000000000..b722233953 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesTrainingPredict.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesTrainingPredict" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BoostedTreesUpdateEnsemble.pbtxt b/tensorflow/core/api_def/java_api/api_def_BoostedTreesUpdateEnsemble.pbtxt new file mode 100644 index 0000000000..fb642dd430 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BoostedTreesUpdateEnsemble.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BoostedTreesUpdateEnsemble" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BroadcastArgs.pbtxt b/tensorflow/core/api_def/java_api/api_def_BroadcastArgs.pbtxt new file mode 100644 index 0000000000..484742a2d0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BroadcastArgs.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BroadcastArgs" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BroadcastGradientArgs.pbtxt b/tensorflow/core/api_def/java_api/api_def_BroadcastGradientArgs.pbtxt new file mode 100644 index 0000000000..50f631b2a6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BroadcastGradientArgs.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BroadcastGradientArgs" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BroadcastTo.pbtxt b/tensorflow/core/api_def/java_api/api_def_BroadcastTo.pbtxt new file mode 100644 index 0000000000..127458816c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BroadcastTo.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "BroadcastTo" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Bucketize.pbtxt b/tensorflow/core/api_def/java_api/api_def_Bucketize.pbtxt new file mode 100644 index 0000000000..5a99712fd6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Bucketize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Bucketize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_BytesProducedStatsDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_BytesProducedStatsDataset.pbtxt new file mode 100644 index 0000000000..cd7f24d961 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_BytesProducedStatsDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "BytesProducedStatsDataset" + endpoint { + name: "data.BytesProducedStatsDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt b/tensorflow/core/api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt new file mode 100644 index 0000000000..79dae81df9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CTCBeamSearchDecoder" + endpoint { + name: "nn.CTCBeamSearchDecoder" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt b/tensorflow/core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt new file mode 100644 index 0000000000..6a58e628bd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CTCGreedyDecoder" + endpoint { + name: "nn.CTCGreedyDecoder" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt b/tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt new file mode 100644 index 0000000000..361270e1f7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CTCLoss" + endpoint { + name: "nn.CTCLoss" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CacheDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_CacheDataset.pbtxt new file mode 100644 index 0000000000..11c26c1dfc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CacheDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CacheDataset" + endpoint { + name: "data.CacheDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Cast.pbtxt b/tensorflow/core/api_def/java_api/api_def_Cast.pbtxt new file mode 100644 index 0000000000..ea9f812e2a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Cast.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Cast" + endpoint { + name: "dtypes.Cast" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Ceil.pbtxt b/tensorflow/core/api_def/java_api/api_def_Ceil.pbtxt new file mode 100644 index 0000000000..d1a75f27d9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Ceil.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Ceil" + endpoint { + name: "math.Ceil" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CheckNumerics.pbtxt b/tensorflow/core/api_def/java_api/api_def_CheckNumerics.pbtxt new file mode 100644 index 0000000000..731e9030a0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CheckNumerics.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CheckNumerics" + endpoint { + name: "math.CheckNumerics" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Cholesky.pbtxt b/tensorflow/core/api_def/java_api/api_def_Cholesky.pbtxt new file mode 100644 index 0000000000..a60c4e3663 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Cholesky.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Cholesky" + endpoint { + name: "linalg.Cholesky" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CholeskyGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_CholeskyGrad.pbtxt new file mode 100644 index 0000000000..2601d41554 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CholeskyGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CholeskyGrad" + endpoint { + name: "linalg.CholeskyGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ClipByValue.pbtxt b/tensorflow/core/api_def/java_api/api_def_ClipByValue.pbtxt new file mode 100644 index 0000000000..c4e055c117 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ClipByValue.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ClipByValue" +} diff --git a/tensorflow/core/api_def/java_api/api_def_CloseSummaryWriter.pbtxt b/tensorflow/core/api_def/java_api/api_def_CloseSummaryWriter.pbtxt new file mode 100644 index 0000000000..d5fbe557db --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CloseSummaryWriter.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CloseSummaryWriter" + endpoint { + name: "summary.CloseSummaryWriter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CollectiveBcastRecv.pbtxt b/tensorflow/core/api_def/java_api/api_def_CollectiveBcastRecv.pbtxt new file mode 100644 index 0000000000..8ada333e44 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CollectiveBcastRecv.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CollectiveBcastRecv" + endpoint { + name: "collective.BroadcastRecv" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CollectiveBcastSend.pbtxt b/tensorflow/core/api_def/java_api/api_def_CollectiveBcastSend.pbtxt new file mode 100644 index 0000000000..18b4bef345 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CollectiveBcastSend.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CollectiveBcastSend" + endpoint { + name: "collective.BroadcastSend" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CollectiveReduce.pbtxt b/tensorflow/core/api_def/java_api/api_def_CollectiveReduce.pbtxt new file mode 100644 index 0000000000..6226cc05ec --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CollectiveReduce.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CollectiveReduce" + endpoint { + name: "collective.AllReduce" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CompareAndBitpack.pbtxt b/tensorflow/core/api_def/java_api/api_def_CompareAndBitpack.pbtxt new file mode 100644 index 0000000000..d744fbbc90 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CompareAndBitpack.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CompareAndBitpack" + endpoint { + name: "math.CompareAndBitpack" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Complex.pbtxt b/tensorflow/core/api_def/java_api/api_def_Complex.pbtxt new file mode 100644 index 0000000000..4889360a96 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Complex.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Complex" + endpoint { + name: "dtypes.Complex" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ComplexAbs.pbtxt b/tensorflow/core/api_def/java_api/api_def_ComplexAbs.pbtxt new file mode 100644 index 0000000000..42a6a3c6a1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ComplexAbs.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ComplexAbs" + endpoint { + name: "math.ComplexAbs" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ComputeAccidentalHits.pbtxt b/tensorflow/core/api_def/java_api/api_def_ComputeAccidentalHits.pbtxt new file mode 100644 index 0000000000..ca9e590fbc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ComputeAccidentalHits.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ComputeAccidentalHits" + endpoint { + name: "nn.ComputeAccidentalHits" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Concat.pbtxt b/tensorflow/core/api_def/java_api/api_def_Concat.pbtxt new file mode 100644 index 0000000000..b13eb820ec --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Concat.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Concat" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ConcatOffset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ConcatOffset.pbtxt new file mode 100644 index 0000000000..e8e23cf559 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ConcatOffset.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ConcatOffset" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt new file mode 100644 index 0000000000..a600c31ed9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ConcatV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ConcatenateDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ConcatenateDataset.pbtxt new file mode 100644 index 0000000000..ec8253e9b5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ConcatenateDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ConcatenateDataset" + endpoint { + name: "data.ConcatenateDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ConditionalAccumulator.pbtxt b/tensorflow/core/api_def/java_api/api_def_ConditionalAccumulator.pbtxt new file mode 100644 index 0000000000..08431982da --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ConditionalAccumulator.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ConditionalAccumulator" + endpoint { + name: "train.ConditionalAccumulator" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Conj.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conj.pbtxt new file mode 100644 index 0000000000..7de199b55f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Conj.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Conj" + endpoint { + name: "math.Conj" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ConjugateTranspose.pbtxt b/tensorflow/core/api_def/java_api/api_def_ConjugateTranspose.pbtxt new file mode 100644 index 0000000000..42173088ae --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ConjugateTranspose.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ConjugateTranspose" + endpoint { + name: "linalg.ConjugateTranspose" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Const.pbtxt b/tensorflow/core/api_def/java_api/api_def_Const.pbtxt index 2dbdca34e0..a73f1e6c3a 100644 --- a/tensorflow/core/api_def/java_api/api_def_Const.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Const.pbtxt @@ -1,4 +1,4 @@ op { - graph_op_name: "Const" #TODO(karllessard) escape that reserved name - visibility: HIDDEN + graph_op_name: "Const" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ConsumeMutexLock.pbtxt b/tensorflow/core/api_def/java_api/api_def_ConsumeMutexLock.pbtxt new file mode 100644 index 0000000000..1e0d136bc2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ConsumeMutexLock.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ConsumeMutexLock" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ControlTrigger.pbtxt b/tensorflow/core/api_def/java_api/api_def_ControlTrigger.pbtxt new file mode 100644 index 0000000000..4517b4373f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ControlTrigger.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ControlTrigger" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt new file mode 100644 index 0000000000..04c4fcec16 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Conv2D" + endpoint { + name: "nn.Conv2D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt new file mode 100644 index 0000000000..990a54262e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Conv2DBackpropFilter" + endpoint { + name: "nn.Conv2DBackpropFilter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt new file mode 100644 index 0000000000..11bbaa455c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Conv2DBackpropInput" + endpoint { + name: "nn.Conv2DBackpropInput" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt new file mode 100644 index 0000000000..0d97065704 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Conv3D" + endpoint { + name: "nn.Conv3D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt new file mode 100644 index 0000000000..279cd5867e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Conv3DBackpropFilter" + endpoint { + name: "nn.Conv3DBackpropFilter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt new file mode 100644 index 0000000000..0643cc14a9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Conv3DBackpropFilterV2" + endpoint { + name: "nn.Conv3dBackpropFilter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt new file mode 100644 index 0000000000..5be32ebe3c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Conv3DBackpropInput" + endpoint { + name: "nn.Conv3DBackpropInput" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt new file mode 100644 index 0000000000..2ce9cf134b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Conv3DBackpropInputV2" + endpoint { + name: "nn.Conv3DBackpropInputV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Cos.pbtxt b/tensorflow/core/api_def/java_api/api_def_Cos.pbtxt new file mode 100644 index 0000000000..db1f62806e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Cos.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Cos" + endpoint { + name: "math.Cos" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Cosh.pbtxt b/tensorflow/core/api_def/java_api/api_def_Cosh.pbtxt new file mode 100644 index 0000000000..a4b5e752bf --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Cosh.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Cosh" + endpoint { + name: "math.Cosh" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CountUpTo.pbtxt b/tensorflow/core/api_def/java_api/api_def_CountUpTo.pbtxt new file mode 100644 index 0000000000..eb9f328ce0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CountUpTo.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "CountUpTo" +} diff --git a/tensorflow/core/api_def/java_api/api_def_CreateSummaryDbWriter.pbtxt b/tensorflow/core/api_def/java_api/api_def_CreateSummaryDbWriter.pbtxt new file mode 100644 index 0000000000..299f881dd4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CreateSummaryDbWriter.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CreateSummaryDbWriter" + endpoint { + name: "summary.CreateSummaryDbWriter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CreateSummaryFileWriter.pbtxt b/tensorflow/core/api_def/java_api/api_def_CreateSummaryFileWriter.pbtxt new file mode 100644 index 0000000000..26c7941ce5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CreateSummaryFileWriter.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CreateSummaryFileWriter" + endpoint { + name: "summary.CreateSummaryFileWriter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CropAndResize.pbtxt b/tensorflow/core/api_def/java_api/api_def_CropAndResize.pbtxt new file mode 100644 index 0000000000..cbf9aa8f99 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CropAndResize.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CropAndResize" + endpoint { + name: "image.CropAndResize" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CropAndResizeGradBoxes.pbtxt b/tensorflow/core/api_def/java_api/api_def_CropAndResizeGradBoxes.pbtxt new file mode 100644 index 0000000000..44354bdfa0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CropAndResizeGradBoxes.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CropAndResizeGradBoxes" + endpoint { + name: "image.CropAndResizeGradBoxes" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CropAndResizeGradImage.pbtxt b/tensorflow/core/api_def/java_api/api_def_CropAndResizeGradImage.pbtxt new file mode 100644 index 0000000000..0618db9a8d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CropAndResizeGradImage.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CropAndResizeGradImage" + endpoint { + name: "image.CropAndResizeGradImage" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Cross.pbtxt b/tensorflow/core/api_def/java_api/api_def_Cross.pbtxt new file mode 100644 index 0000000000..c027884250 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Cross.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Cross" + endpoint { + name: "linalg.Cross" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt new file mode 100644 index 0000000000..c3d7f17596 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CudnnRNN" + endpoint { + name: "nn.CudnnRNN" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt new file mode 100644 index 0000000000..371b6a18db --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CudnnRNNBackprop" + endpoint { + name: "nn.CudnnRNNBackprop" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt new file mode 100644 index 0000000000..756abdb71f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CudnnRNNBackpropV2" + endpoint { + name: "nn.CudnnRNNBackpropV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNCanonicalToParams.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNCanonicalToParams.pbtxt new file mode 100644 index 0000000000..86d7045db7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNCanonicalToParams.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CudnnRNNCanonicalToParams" + endpoint { + name: "nn.CudnnRNNCanonicalToParams" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt new file mode 100644 index 0000000000..73922b0343 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CudnnRNNParamsSize" + endpoint { + name: "nn.CudnnRNNParamsSize" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsToCanonical.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsToCanonical.pbtxt new file mode 100644 index 0000000000..e1c567163a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsToCanonical.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CudnnRNNParamsToCanonical" + endpoint { + name: "nn.CudnnRNNParamsToCanonical" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt new file mode 100644 index 0000000000..d535f35459 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "CudnnRNNV2" + endpoint { + name: "nn.CudnnRNNV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Cumprod.pbtxt b/tensorflow/core/api_def/java_api/api_def_Cumprod.pbtxt new file mode 100644 index 0000000000..0cb7862413 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Cumprod.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Cumprod" + endpoint { + name: "math.Cumprod" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Cumsum.pbtxt b/tensorflow/core/api_def/java_api/api_def_Cumsum.pbtxt new file mode 100644 index 0000000000..e7d9076532 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Cumsum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Cumsum" + endpoint { + name: "math.Cumsum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DataFormatDimMap.pbtxt b/tensorflow/core/api_def/java_api/api_def_DataFormatDimMap.pbtxt new file mode 100644 index 0000000000..36ea17793f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DataFormatDimMap.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DataFormatDimMap" + endpoint { + name: "nn.DataFormatDimMap" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DataFormatVecPermute.pbtxt b/tensorflow/core/api_def/java_api/api_def_DataFormatVecPermute.pbtxt new file mode 100644 index 0000000000..b6b7e2dc76 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DataFormatVecPermute.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DataFormatVecPermute" + endpoint { + name: "nn.DataFormatVecPermute" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DatasetToGraph.pbtxt b/tensorflow/core/api_def/java_api/api_def_DatasetToGraph.pbtxt new file mode 100644 index 0000000000..2e7d48961d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DatasetToGraph.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DatasetToGraph" + endpoint { + name: "data.DatasetToGraph" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DatasetToSingleElement.pbtxt b/tensorflow/core/api_def/java_api/api_def_DatasetToSingleElement.pbtxt new file mode 100644 index 0000000000..0ac42e0e93 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DatasetToSingleElement.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DatasetToSingleElement" + endpoint { + name: "data.DatasetToSingleElement" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt b/tensorflow/core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt new file mode 100644 index 0000000000..5884fe960d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DatasetToTFRecord" + endpoint { + name: "data.DatasetToTFRecord" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DebugGradientIdentity.pbtxt b/tensorflow/core/api_def/java_api/api_def_DebugGradientIdentity.pbtxt new file mode 100644 index 0000000000..7d50c5c868 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DebugGradientIdentity.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "DebugGradientIdentity" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/java_api/api_def_DebugGradientRefIdentity.pbtxt b/tensorflow/core/api_def/java_api/api_def_DebugGradientRefIdentity.pbtxt new file mode 100644 index 0000000000..5e14e5fffd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DebugGradientRefIdentity.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "DebugGradientRefIdentity" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeAndCropJpeg.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeAndCropJpeg.pbtxt new file mode 100644 index 0000000000..c07bb7a1bd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeAndCropJpeg.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeAndCropJpeg" + endpoint { + name: "image.DecodeAndCropJpeg" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeBase64.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeBase64.pbtxt new file mode 100644 index 0000000000..49c93453f7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeBase64.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeBase64" + endpoint { + name: "io.DecodeBase64" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeBmp.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeBmp.pbtxt new file mode 100644 index 0000000000..049cfa153d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeBmp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeBmp" + endpoint { + name: "image.DecodeBmp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt new file mode 100644 index 0000000000..2c738cf4dd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeCSV" + endpoint { + name: "io.DecodeCSV" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeCompressed.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeCompressed.pbtxt new file mode 100644 index 0000000000..91327a92ec --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeCompressed.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeCompressed" + endpoint { + name: "io.DecodeCompressed" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeGif.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeGif.pbtxt new file mode 100644 index 0000000000..355643ff77 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeGif.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeGif" + endpoint { + name: "image.DecodeGif" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeJSONExample.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeJSONExample.pbtxt new file mode 100644 index 0000000000..6ecba5ab05 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeJSONExample.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeJSONExample" + endpoint { + name: "io.DecodeJsonExample" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeJpeg.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeJpeg.pbtxt new file mode 100644 index 0000000000..c0ebf2e315 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeJpeg.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeJpeg" + endpoint { + name: "image.DecodeJpeg" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodePng.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodePng.pbtxt new file mode 100644 index 0000000000..d94537dc92 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodePng.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodePng" + endpoint { + name: "image.DecodePng" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeProtoV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeProtoV2.pbtxt new file mode 100644 index 0000000000..ff6531a3ac --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeProtoV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "DecodeProtoV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeRaw.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeRaw.pbtxt new file mode 100644 index 0000000000..73067173ed --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeRaw.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeRaw" + endpoint { + name: "io.DecodeRaw" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeWav.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeWav.pbtxt new file mode 100644 index 0000000000..9b249cc6e9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DecodeWav.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DecodeWav" + endpoint { + name: "audio.DecodeWav" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DeepCopy.pbtxt b/tensorflow/core/api_def/java_api/api_def_DeepCopy.pbtxt new file mode 100644 index 0000000000..88a87c9291 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DeepCopy.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "DeepCopy" +} diff --git a/tensorflow/core/api_def/java_api/api_def_DeleteSessionTensor.pbtxt b/tensorflow/core/api_def/java_api/api_def_DeleteSessionTensor.pbtxt new file mode 100644 index 0000000000..1865b461de --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DeleteSessionTensor.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "DeleteSessionTensor" +} diff --git a/tensorflow/core/api_def/java_api/api_def_DenseToDenseSetOperation.pbtxt b/tensorflow/core/api_def/java_api/api_def_DenseToDenseSetOperation.pbtxt new file mode 100644 index 0000000000..f85def92ee --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DenseToDenseSetOperation.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DenseToDenseSetOperation" + endpoint { + name: "sparse.DenseToDenseSetOperation" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DenseToSparseBatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_DenseToSparseBatchDataset.pbtxt new file mode 100644 index 0000000000..76f6ba0b8a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DenseToSparseBatchDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DenseToSparseBatchDataset" + endpoint { + name: "data.DenseToSparseBatchDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DenseToSparseSetOperation.pbtxt b/tensorflow/core/api_def/java_api/api_def_DenseToSparseSetOperation.pbtxt new file mode 100644 index 0000000000..11fbef8ff1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DenseToSparseSetOperation.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DenseToSparseSetOperation" + endpoint { + name: "sparse.DenseToSparseSetOperation" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DepthToSpace.pbtxt b/tensorflow/core/api_def/java_api/api_def_DepthToSpace.pbtxt new file mode 100644 index 0000000000..0d2cbd2b90 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DepthToSpace.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DepthToSpace" + endpoint { + name: "nn.DepthToSpace" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNative.pbtxt b/tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNative.pbtxt new file mode 100644 index 0000000000..1aaa480fef --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNative.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DepthwiseConv2dNative" + endpoint { + name: "nn.DepthwiseConv2dNative" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNativeBackpropFilter.pbtxt b/tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNativeBackpropFilter.pbtxt new file mode 100644 index 0000000000..1a62d8cf63 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNativeBackpropFilter.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DepthwiseConv2dNativeBackpropFilter" + endpoint { + name: "nn.DepthwiseConv2dNativeBackpropFilter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNativeBackpropInput.pbtxt b/tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNativeBackpropInput.pbtxt new file mode 100644 index 0000000000..9106dd2f8f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DepthwiseConv2dNativeBackpropInput.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DepthwiseConv2dNativeBackpropInput" + endpoint { + name: "nn.DepthwiseConv2dNativeBackpropInput" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Dequantize.pbtxt b/tensorflow/core/api_def/java_api/api_def_Dequantize.pbtxt new file mode 100644 index 0000000000..8ee4daa2f7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Dequantize.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Dequantize" + endpoint { + name: "quantization.Dequantize" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DeserializeIterator.pbtxt b/tensorflow/core/api_def/java_api/api_def_DeserializeIterator.pbtxt new file mode 100644 index 0000000000..bdd03f5dc6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DeserializeIterator.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DeserializeIterator" + endpoint { + name: "data.DeserializeIterator" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DeserializeManySparse.pbtxt b/tensorflow/core/api_def/java_api/api_def_DeserializeManySparse.pbtxt new file mode 100644 index 0000000000..826d49f546 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DeserializeManySparse.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DeserializeManySparse" + endpoint { + name: "io.DeserializeManySparse" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DeserializeSparse.pbtxt b/tensorflow/core/api_def/java_api/api_def_DeserializeSparse.pbtxt new file mode 100644 index 0000000000..e6f24bb625 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DeserializeSparse.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DeserializeSparse" + endpoint { + name: "sparse.DeserializeSparse" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DestroyResourceOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_DestroyResourceOp.pbtxt new file mode 100644 index 0000000000..733e5e5029 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DestroyResourceOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "DestroyResourceOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_DestroyTemporaryVariable.pbtxt b/tensorflow/core/api_def/java_api/api_def_DestroyTemporaryVariable.pbtxt new file mode 100644 index 0000000000..bd416eb68f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DestroyTemporaryVariable.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "DestroyTemporaryVariable" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Diag.pbtxt b/tensorflow/core/api_def/java_api/api_def_Diag.pbtxt new file mode 100644 index 0000000000..374b3c97e1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Diag.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Diag" + endpoint { + name: "linalg.TensorDiag" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DiagPart.pbtxt b/tensorflow/core/api_def/java_api/api_def_DiagPart.pbtxt new file mode 100644 index 0000000000..70db2357d0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DiagPart.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DiagPart" + endpoint { + name: "linalg.TensorDiagPart" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Digamma.pbtxt b/tensorflow/core/api_def/java_api/api_def_Digamma.pbtxt new file mode 100644 index 0000000000..68dc74c64e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Digamma.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Digamma" + endpoint { + name: "math.Digamma" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Dilation2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_Dilation2D.pbtxt new file mode 100644 index 0000000000..914ea29812 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Dilation2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Dilation2D" + endpoint { + name: "nn.Dilation2d" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt b/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt new file mode 100644 index 0000000000..ab8b79d681 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Dilation2DBackpropFilter" + endpoint { + name: "nn.Dilation2DBackpropFilter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt b/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt new file mode 100644 index 0000000000..9dece4569c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Dilation2DBackpropInput" + endpoint { + name: "nn.Dilation2DBackpropInput" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Div.pbtxt b/tensorflow/core/api_def/java_api/api_def_Div.pbtxt new file mode 100644 index 0000000000..2abba7f05f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Div.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Div" + endpoint { + name: "math.Div" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DivNoNan.pbtxt b/tensorflow/core/api_def/java_api/api_def_DivNoNan.pbtxt new file mode 100644 index 0000000000..c124044604 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DivNoNan.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DivNoNan" + endpoint { + name: "math.DivNoNan" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DrawBoundingBoxes.pbtxt b/tensorflow/core/api_def/java_api/api_def_DrawBoundingBoxes.pbtxt new file mode 100644 index 0000000000..2e7954e2b7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DrawBoundingBoxes.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "DrawBoundingBoxes" + endpoint { + name: "image.DrawBoundingBoxes" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_DynamicPartition.pbtxt b/tensorflow/core/api_def/java_api/api_def_DynamicPartition.pbtxt new file mode 100644 index 0000000000..cc585676e4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DynamicPartition.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "DynamicPartition" +} diff --git a/tensorflow/core/api_def/java_api/api_def_DynamicStitch.pbtxt b/tensorflow/core/api_def/java_api/api_def_DynamicStitch.pbtxt new file mode 100644 index 0000000000..ac1fef4b6a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_DynamicStitch.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "DynamicStitch" +} diff --git a/tensorflow/core/api_def/java_api/api_def_EagerPyFunc.pbtxt b/tensorflow/core/api_def/java_api/api_def_EagerPyFunc.pbtxt new file mode 100644 index 0000000000..e097041d73 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EagerPyFunc.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "EagerPyFunc" + visibility: SKIP +} diff --git a/tensorflow/core/api_def/java_api/api_def_EditDistance.pbtxt b/tensorflow/core/api_def/java_api/api_def_EditDistance.pbtxt new file mode 100644 index 0000000000..ca65c2c6e5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EditDistance.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "EditDistance" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Elu.pbtxt b/tensorflow/core/api_def/java_api/api_def_Elu.pbtxt new file mode 100644 index 0000000000..bfe8d972cf --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Elu.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Elu" + endpoint { + name: "nn.Elu" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_EluGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_EluGrad.pbtxt new file mode 100644 index 0000000000..3757357c00 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EluGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "EluGrad" + endpoint { + name: "nn.EluGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Empty.pbtxt b/tensorflow/core/api_def/java_api/api_def_Empty.pbtxt new file mode 100644 index 0000000000..6522f51d9d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Empty.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Empty" +} diff --git a/tensorflow/core/api_def/java_api/api_def_EmptyTensorList.pbtxt b/tensorflow/core/api_def/java_api/api_def_EmptyTensorList.pbtxt new file mode 100644 index 0000000000..ef3f533964 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EmptyTensorList.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "EmptyTensorList" +} diff --git a/tensorflow/core/api_def/java_api/api_def_EncodeBase64.pbtxt b/tensorflow/core/api_def/java_api/api_def_EncodeBase64.pbtxt new file mode 100644 index 0000000000..66f19def9a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EncodeBase64.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "EncodeBase64" + endpoint { + name: "io.EncodeBase64" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_EncodeJpeg.pbtxt b/tensorflow/core/api_def/java_api/api_def_EncodeJpeg.pbtxt new file mode 100644 index 0000000000..1e151665f8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EncodeJpeg.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "EncodeJpeg" + endpoint { + name: "image.EncodeJpeg" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_EncodePng.pbtxt b/tensorflow/core/api_def/java_api/api_def_EncodePng.pbtxt new file mode 100644 index 0000000000..7a8d713c86 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EncodePng.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "EncodePng" + endpoint { + name: "image.EncodePng" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_EncodeProto.pbtxt b/tensorflow/core/api_def/java_api/api_def_EncodeProto.pbtxt new file mode 100644 index 0000000000..ac6a04b4bc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EncodeProto.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "EncodeProto" +} diff --git a/tensorflow/core/api_def/java_api/api_def_EncodeWav.pbtxt b/tensorflow/core/api_def/java_api/api_def_EncodeWav.pbtxt new file mode 100644 index 0000000000..f3b22fde66 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EncodeWav.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "EncodeWav" + endpoint { + name: "audio.EncodeWav" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_EnqueueInQueueDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_EnqueueInQueueDataset.pbtxt new file mode 100644 index 0000000000..26051ab446 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EnqueueInQueueDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "EnqueueInQueueDataset" + endpoint { + name: "data.EnqueueInQueueDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_EnsureShape.pbtxt b/tensorflow/core/api_def/java_api/api_def_EnsureShape.pbtxt new file mode 100644 index 0000000000..6238947598 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_EnsureShape.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "EnsureShape" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Enter.pbtxt b/tensorflow/core/api_def/java_api/api_def_Enter.pbtxt new file mode 100644 index 0000000000..ffc10c91be --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Enter.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Enter" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Equal.pbtxt b/tensorflow/core/api_def/java_api/api_def_Equal.pbtxt new file mode 100644 index 0000000000..c2256c2433 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Equal.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Equal" + endpoint { + name: "math.Equal" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Erf.pbtxt b/tensorflow/core/api_def/java_api/api_def_Erf.pbtxt new file mode 100644 index 0000000000..9efcc3983c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Erf.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Erf" + endpoint { + name: "math.Erf" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Erfc.pbtxt b/tensorflow/core/api_def/java_api/api_def_Erfc.pbtxt new file mode 100644 index 0000000000..c0f4db61ff --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Erfc.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Erfc" + endpoint { + name: "math.Erfc" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Exit.pbtxt b/tensorflow/core/api_def/java_api/api_def_Exit.pbtxt new file mode 100644 index 0000000000..6215cd2229 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Exit.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Exit" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Exp.pbtxt b/tensorflow/core/api_def/java_api/api_def_Exp.pbtxt new file mode 100644 index 0000000000..b2790c8306 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Exp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Exp" + endpoint { + name: "math.Exp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExpandDims.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExpandDims.pbtxt new file mode 100644 index 0000000000..66902ccb5b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExpandDims.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ExpandDims" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalAssertNextDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalAssertNextDataset.pbtxt new file mode 100644 index 0000000000..cec4c229e4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalAssertNextDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalAssertNextDataset" + endpoint { + name: "data.ExperimentalAssertNextDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt new file mode 100644 index 0000000000..2c555c3f1a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalCSVDataset" + endpoint { + name: "data.ExperimentalCSVDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalDirectedInterleaveDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalDirectedInterleaveDataset.pbtxt new file mode 100644 index 0000000000..77fe42fd94 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalDirectedInterleaveDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalDirectedInterleaveDataset" + endpoint { + name: "data.ExperimentalDirectedInterleaveDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResource.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResource.pbtxt new file mode 100644 index 0000000000..320f4affb5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResource.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalFunctionBufferingResource" + endpoint { + name: "data.ExperimentalFunctionBufferingResource" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResourceGetNext.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResourceGetNext.pbtxt new file mode 100644 index 0000000000..d3dbe7600a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResourceGetNext.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalFunctionBufferingResourceGetNext" + endpoint { + name: "data.ExperimentalFunctionBufferingResourceGetNext" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResourceReset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResourceReset.pbtxt new file mode 100644 index 0000000000..6909e8678a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalFunctionBufferingResourceReset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalFunctionBufferingResourceReset" + endpoint { + name: "data.ExperimentalFunctionBufferingResourceReset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalIdentityIndexedDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalIdentityIndexedDataset.pbtxt new file mode 100644 index 0000000000..c49c6de217 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalIdentityIndexedDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalIdentityIndexedDataset" + endpoint { + name: "data.ExperimentalIdentityIndexedDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalIgnoreErrorsDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalIgnoreErrorsDataset.pbtxt new file mode 100644 index 0000000000..7750a43de2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalIgnoreErrorsDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalIgnoreErrorsDataset" + endpoint { + name: "data.ExperimentalIgnoreErrorsDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalIndexedDatasetGet.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalIndexedDatasetGet.pbtxt new file mode 100644 index 0000000000..96a3befe8b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalIndexedDatasetGet.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalIndexedDatasetGet" + endpoint { + name: "data.ExperimentalIndexedDatasetGet" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalIndexedDatasetMaterialize.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalIndexedDatasetMaterialize.pbtxt new file mode 100644 index 0000000000..731309d329 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalIndexedDatasetMaterialize.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalIndexedDatasetMaterialize" + endpoint { + name: "data.ExperimentalIndexedDatasetMaterialize" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalIteratorGetDevice.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalIteratorGetDevice.pbtxt new file mode 100644 index 0000000000..838d579ef7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalIteratorGetDevice.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalIteratorGetDevice" + endpoint { + name: "data.ExperimentalIteratorGetDevice" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt new file mode 100644 index 0000000000..dd24ff544f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalLMDBDataset" + endpoint { + name: "data.ExperimentalLMDBDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalMapDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalMapDataset.pbtxt new file mode 100644 index 0000000000..bea6dffd9c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalMapDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalMapDataset" + endpoint { + name: "data.ExperimentalMapDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalMaterializedIndexDatasetHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalMaterializedIndexDatasetHandle.pbtxt new file mode 100644 index 0000000000..06632e9041 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalMaterializedIndexDatasetHandle.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalMaterializedIndexDatasetHandle" + endpoint { + name: "data.ExperimentalMaterializedIndexDatasetHandle" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalNonSerializableDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalNonSerializableDataset.pbtxt new file mode 100644 index 0000000000..7b26cf129c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalNonSerializableDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalNonSerializableDataset" + endpoint { + name: "data.ExperimentalNonSerializableDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalNumaMapAndBatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalNumaMapAndBatchDataset.pbtxt new file mode 100644 index 0000000000..a2c0d92f89 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalNumaMapAndBatchDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalNumaMapAndBatchDataset" + endpoint { + name: "data.ExperimentalNumaMapAndBatchDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalSleepDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalSleepDataset.pbtxt new file mode 100644 index 0000000000..9e95c55ac2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalSleepDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalSleepDataset" + endpoint { + name: "data.ExperimentalSleepDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalThreadPoolDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalThreadPoolDataset.pbtxt new file mode 100644 index 0000000000..3e4aef1c68 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalThreadPoolDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalThreadPoolDataset" + endpoint { + name: "data.ExperimentalThreadPoolDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalThreadPoolHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalThreadPoolHandle.pbtxt new file mode 100644 index 0000000000..73cf6767b3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalThreadPoolHandle.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalThreadPoolHandle" + endpoint { + name: "data.ExperimentalThreadPoolHandle" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalUniqueDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalUniqueDataset.pbtxt new file mode 100644 index 0000000000..0d834193dd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalUniqueDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExperimentalUniqueDataset" + endpoint { + name: "data.ExperimentalUniqueDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Expm1.pbtxt b/tensorflow/core/api_def/java_api/api_def_Expm1.pbtxt new file mode 100644 index 0000000000..71a8fcf022 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Expm1.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Expm1" + endpoint { + name: "math.Expm1" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExtractGlimpse.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExtractGlimpse.pbtxt new file mode 100644 index 0000000000..3591f93f71 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExtractGlimpse.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExtractGlimpse" + endpoint { + name: "image.ExtractGlimpse" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExtractImagePatches.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExtractImagePatches.pbtxt new file mode 100644 index 0000000000..7cdcfd7528 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExtractImagePatches.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExtractImagePatches" + endpoint { + name: "image.ExtractImagePatches" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExtractJpegShape.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExtractJpegShape.pbtxt new file mode 100644 index 0000000000..c95fcc9cef --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExtractJpegShape.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ExtractJpegShape" + endpoint { + name: "image.ExtractJpegShape" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ExtractVolumePatches.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExtractVolumePatches.pbtxt new file mode 100644 index 0000000000..6f61c83210 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ExtractVolumePatches.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ExtractVolumePatches" +} diff --git a/tensorflow/core/api_def/java_api/api_def_FFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_FFT.pbtxt new file mode 100644 index 0000000000..d965590308 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FFT.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FFT" + endpoint { + name: "signal.Fft" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_FFT2D.pbtxt new file mode 100644 index 0000000000..474103076b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FFT2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FFT2D" + endpoint { + name: "signal.Fft2d" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_FFT3D.pbtxt new file mode 100644 index 0000000000..8e1606b8f9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FFT3D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FFT3D" + endpoint { + name: "signal.Fft3d" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt new file mode 100644 index 0000000000..e1760b685b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FIFOQueue" + endpoint { + name: "io.FIFOQueue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt new file mode 100644 index 0000000000..fe260ca2be --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FIFOQueueV2" + endpoint { + name: "io.FIFOQueueV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Fact.pbtxt b/tensorflow/core/api_def/java_api/api_def_Fact.pbtxt new file mode 100644 index 0000000000..436664e554 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Fact.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Fact" + endpoint { + name: "math.Fact" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FakeParam.pbtxt b/tensorflow/core/api_def/java_api/api_def_FakeParam.pbtxt new file mode 100644 index 0000000000..ac8f751442 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FakeParam.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "FakeParam" +} diff --git a/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxArgs.pbtxt b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxArgs.pbtxt new file mode 100644 index 0000000000..809d231a55 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxArgs.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FakeQuantWithMinMaxArgs" + endpoint { + name: "quantization.FakeQuantWithMinMaxArgs" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxArgsGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxArgsGradient.pbtxt new file mode 100644 index 0000000000..50d0f51a14 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxArgsGradient.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FakeQuantWithMinMaxArgsGradient" + endpoint { + name: "quantization.FakeQuantWithMinMaxArgsGradient" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVars.pbtxt b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVars.pbtxt new file mode 100644 index 0000000000..b86258aab2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVars.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FakeQuantWithMinMaxVars" + endpoint { + name: "quantization.FakeQuantWithMinMaxVars" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsGradient.pbtxt new file mode 100644 index 0000000000..3c1343423c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsGradient.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FakeQuantWithMinMaxVarsGradient" + endpoint { + name: "quantization.FakeQuantWithMinMaxVarsGradient" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsPerChannel.pbtxt b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsPerChannel.pbtxt new file mode 100644 index 0000000000..afe45a290d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsPerChannel.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FakeQuantWithMinMaxVarsPerChannel" + endpoint { + name: "quantization.FakeQuantWithMinMaxVarsPerChannel" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsPerChannelGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsPerChannelGradient.pbtxt new file mode 100644 index 0000000000..9dd62fdffd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FakeQuantWithMinMaxVarsPerChannelGradient.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FakeQuantWithMinMaxVarsPerChannelGradient" + endpoint { + name: "quantization.FakeQuantWithMinMaxVarsPerChannelGradient" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FakeQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_FakeQueue.pbtxt new file mode 100644 index 0000000000..8960966f08 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FakeQueue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FakeQueue" + endpoint { + name: "io.FakeQueue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Fill.pbtxt b/tensorflow/core/api_def/java_api/api_def_Fill.pbtxt new file mode 100644 index 0000000000..3997328ed3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Fill.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Fill" +} diff --git a/tensorflow/core/api_def/java_api/api_def_FilterByLastComponentDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_FilterByLastComponentDataset.pbtxt new file mode 100644 index 0000000000..b7111f48fa --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FilterByLastComponentDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FilterByLastComponentDataset" + endpoint { + name: "data.FilterByLastComponentDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FilterDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_FilterDataset.pbtxt new file mode 100644 index 0000000000..930fff4191 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FilterDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FilterDataset" + endpoint { + name: "data.FilterDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt new file mode 100644 index 0000000000..8f38364f85 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FixedLengthRecordDataset" + endpoint { + name: "data.FixedLengthRecordDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDatasetV2.pbtxt new file mode 100644 index 0000000000..723248019d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDatasetV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FixedLengthRecordDatasetV2" + endpoint { + name: "data.FixedLengthRecordDatasetV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReader.pbtxt new file mode 100644 index 0000000000..295526d074 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReader.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FixedLengthRecordReader" + endpoint { + name: "io.FixedLengthRecordReader" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReaderV2.pbtxt new file mode 100644 index 0000000000..0cfefe2075 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReaderV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FixedLengthRecordReaderV2" + endpoint { + name: "io.FixedLengthRecordReaderV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FixedUnigramCandidateSampler.pbtxt b/tensorflow/core/api_def/java_api/api_def_FixedUnigramCandidateSampler.pbtxt new file mode 100644 index 0000000000..eb9c68d4db --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FixedUnigramCandidateSampler.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FixedUnigramCandidateSampler" + endpoint { + name: "nn.FixedUnigramCandidateSampler" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FlatMapDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_FlatMapDataset.pbtxt new file mode 100644 index 0000000000..d6e96cb4e0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FlatMapDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FlatMapDataset" + endpoint { + name: "data.FlatMapDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Floor.pbtxt b/tensorflow/core/api_def/java_api/api_def_Floor.pbtxt new file mode 100644 index 0000000000..a2b80f97e0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Floor.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Floor" + endpoint { + name: "math.Floor" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FloorDiv.pbtxt b/tensorflow/core/api_def/java_api/api_def_FloorDiv.pbtxt new file mode 100644 index 0000000000..054d85f55c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FloorDiv.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FloorDiv" + endpoint { + name: "math.FloorDiv" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FloorMod.pbtxt b/tensorflow/core/api_def/java_api/api_def_FloorMod.pbtxt new file mode 100644 index 0000000000..ff2216a935 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FloorMod.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FloorMod" + endpoint { + name: "math.FloorMod" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FlushSummaryWriter.pbtxt b/tensorflow/core/api_def/java_api/api_def_FlushSummaryWriter.pbtxt new file mode 100644 index 0000000000..feaa3a6dc2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FlushSummaryWriter.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FlushSummaryWriter" + endpoint { + name: "summary.FlushSummaryWriter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_For.pbtxt b/tensorflow/core/api_def/java_api/api_def_For.pbtxt new file mode 100644 index 0000000000..30363d1e96 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_For.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "For" +} diff --git a/tensorflow/core/api_def/java_api/api_def_FractionalAvgPool.pbtxt b/tensorflow/core/api_def/java_api/api_def_FractionalAvgPool.pbtxt new file mode 100644 index 0000000000..fc2e6ca54b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FractionalAvgPool.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FractionalAvgPool" + endpoint { + name: "nn.FractionalAvgPool" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FractionalAvgPoolGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_FractionalAvgPoolGrad.pbtxt new file mode 100644 index 0000000000..4e11d5e395 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FractionalAvgPoolGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FractionalAvgPoolGrad" + endpoint { + name: "nn.FractionalAvgPoolGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FractionalMaxPool.pbtxt b/tensorflow/core/api_def/java_api/api_def_FractionalMaxPool.pbtxt new file mode 100644 index 0000000000..061b358ec2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FractionalMaxPool.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FractionalMaxPool" + endpoint { + name: "nn.FractionalMaxPool" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FractionalMaxPoolGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_FractionalMaxPoolGrad.pbtxt new file mode 100644 index 0000000000..c70e6d721e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FractionalMaxPoolGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FractionalMaxPoolGrad" + endpoint { + name: "nn.FractionalMaxPoolGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FusedBatchNorm.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedBatchNorm.pbtxt new file mode 100644 index 0000000000..058c82c177 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FusedBatchNorm.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FusedBatchNorm" + endpoint { + name: "nn.FusedBatchNorm" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt new file mode 100644 index 0000000000..69baf2a8e3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FusedBatchNormGrad" + endpoint { + name: "nn.FusedBatchNormGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt new file mode 100644 index 0000000000..81da6f4bb2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FusedBatchNormGradV2" + endpoint { + name: "nn.FusedBatchNormGradV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt new file mode 100644 index 0000000000..e81d78ef5c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FusedBatchNormV2" + endpoint { + name: "nn.FusedBatchNormV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FusedPadConv2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedPadConv2D.pbtxt new file mode 100644 index 0000000000..e4836df290 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FusedPadConv2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FusedPadConv2D" + endpoint { + name: "nn.FusedPadConv2D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt new file mode 100644 index 0000000000..6cd0caa088 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "FusedResizeAndPadConv2D" + endpoint { + name: "nn.FusedResizeAndPadConv2D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Gather.pbtxt b/tensorflow/core/api_def/java_api/api_def_Gather.pbtxt new file mode 100644 index 0000000000..6848641714 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Gather.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Gather" +} diff --git a/tensorflow/core/api_def/java_api/api_def_GatherNd.pbtxt b/tensorflow/core/api_def/java_api/api_def_GatherNd.pbtxt new file mode 100644 index 0000000000..257c0316ea --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GatherNd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "GatherNd" + endpoint { + name: "GatherNd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt new file mode 100644 index 0000000000..f5b2cb92f6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "GatherV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_GcsConfigureBlockCache.pbtxt b/tensorflow/core/api_def/java_api/api_def_GcsConfigureBlockCache.pbtxt new file mode 100644 index 0000000000..1ba3044d4c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GcsConfigureBlockCache.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "GcsConfigureBlockCache" +} diff --git a/tensorflow/core/api_def/java_api/api_def_GcsConfigureCredentials.pbtxt b/tensorflow/core/api_def/java_api/api_def_GcsConfigureCredentials.pbtxt new file mode 100644 index 0000000000..98bd555fb8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GcsConfigureCredentials.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "GcsConfigureCredentials" +} diff --git a/tensorflow/core/api_def/java_api/api_def_GenerateBigQueryReaderPartitions.pbtxt b/tensorflow/core/api_def/java_api/api_def_GenerateBigQueryReaderPartitions.pbtxt new file mode 100644 index 0000000000..956f40762d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GenerateBigQueryReaderPartitions.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "GenerateBigQueryReaderPartitions" +} diff --git a/tensorflow/core/api_def/java_api/api_def_GenerateVocabRemapping.pbtxt b/tensorflow/core/api_def/java_api/api_def_GenerateVocabRemapping.pbtxt new file mode 100644 index 0000000000..9aac3b17f3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GenerateVocabRemapping.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "GenerateVocabRemapping" + endpoint { + name: "train.GenerateVocabRemapping" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_GeneratorDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_GeneratorDataset.pbtxt new file mode 100644 index 0000000000..b1719005e9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GeneratorDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "GeneratorDataset" + endpoint { + name: "data.GeneratorDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_GetSessionHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_GetSessionHandle.pbtxt new file mode 100644 index 0000000000..84b14a3335 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GetSessionHandle.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "GetSessionHandle" +} diff --git a/tensorflow/core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt new file mode 100644 index 0000000000..28488ac79a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "GetSessionHandleV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_GetSessionTensor.pbtxt b/tensorflow/core/api_def/java_api/api_def_GetSessionTensor.pbtxt new file mode 100644 index 0000000000..34b6e627cd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GetSessionTensor.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "GetSessionTensor" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Greater.pbtxt b/tensorflow/core/api_def/java_api/api_def_Greater.pbtxt new file mode 100644 index 0000000000..594f9276be --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Greater.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Greater" + endpoint { + name: "math.Greater" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_GreaterEqual.pbtxt b/tensorflow/core/api_def/java_api/api_def_GreaterEqual.pbtxt new file mode 100644 index 0000000000..17ea8696b0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GreaterEqual.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "GreaterEqual" + endpoint { + name: "math.GreaterEqual" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_GroupByReducerDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_GroupByReducerDataset.pbtxt new file mode 100644 index 0000000000..1bd2c8f531 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GroupByReducerDataset.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "GroupByReducerDataset" +} diff --git a/tensorflow/core/api_def/java_api/api_def_GroupByWindowDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_GroupByWindowDataset.pbtxt new file mode 100644 index 0000000000..9e4c4cd4ff --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GroupByWindowDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "GroupByWindowDataset" + endpoint { + name: "data.GroupByWindowDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_GuaranteeConst.pbtxt b/tensorflow/core/api_def/java_api/api_def_GuaranteeConst.pbtxt new file mode 100644 index 0000000000..8cac25787d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_GuaranteeConst.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "GuaranteeConst" +} diff --git a/tensorflow/core/api_def/java_api/api_def_HSVToRGB.pbtxt b/tensorflow/core/api_def/java_api/api_def_HSVToRGB.pbtxt new file mode 100644 index 0000000000..95b042d5d6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_HSVToRGB.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "HSVToRGB" + endpoint { + name: "image.HsvToRgb" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt b/tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt new file mode 100644 index 0000000000..f733b277ea --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "HashTable" +} diff --git a/tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt new file mode 100644 index 0000000000..74fda0380a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "HashTableV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_HistogramFixedWidth.pbtxt b/tensorflow/core/api_def/java_api/api_def_HistogramFixedWidth.pbtxt new file mode 100644 index 0000000000..f64d9ae1d2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_HistogramFixedWidth.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "HistogramFixedWidth" +} diff --git a/tensorflow/core/api_def/java_api/api_def_HistogramSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_HistogramSummary.pbtxt new file mode 100644 index 0000000000..97f28335bb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_HistogramSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "HistogramSummary" + endpoint { + name: "summary.HistogramSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_HostConst.pbtxt b/tensorflow/core/api_def/java_api/api_def_HostConst.pbtxt new file mode 100644 index 0000000000..ba589e73e7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_HostConst.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "HostConst" +} diff --git a/tensorflow/core/api_def/java_api/api_def_IFFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_IFFT.pbtxt new file mode 100644 index 0000000000..4a15ebec7f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IFFT.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IFFT" + endpoint { + name: "signal.Ifft" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IFFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_IFFT2D.pbtxt new file mode 100644 index 0000000000..35d696ee73 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IFFT2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IFFT2D" + endpoint { + name: "signal.Ifft2d" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IFFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_IFFT3D.pbtxt new file mode 100644 index 0000000000..76a3164e6a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IFFT3D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IFFT3D" + endpoint { + name: "signal.Ifft3d" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt new file mode 100644 index 0000000000..d2ade5b16e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IRFFT" + endpoint { + name: "signal.IRFFT" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt new file mode 100644 index 0000000000..3a5a5b0c71 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IRFFT2D" + endpoint { + name: "signal.IRFFT2D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt new file mode 100644 index 0000000000..fc5a5451b4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IRFFT3D" + endpoint { + name: "signal.IRFFT3D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Identity.pbtxt b/tensorflow/core/api_def/java_api/api_def_Identity.pbtxt new file mode 100644 index 0000000000..b6df3c6cfe --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Identity.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Identity" +} diff --git a/tensorflow/core/api_def/java_api/api_def_IdentityN.pbtxt b/tensorflow/core/api_def/java_api/api_def_IdentityN.pbtxt new file mode 100644 index 0000000000..827df10c65 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IdentityN.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "IdentityN" +} diff --git a/tensorflow/core/api_def/java_api/api_def_IdentityReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_IdentityReader.pbtxt new file mode 100644 index 0000000000..1e1314213d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IdentityReader.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IdentityReader" + endpoint { + name: "io.IdentityReader" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IdentityReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_IdentityReaderV2.pbtxt new file mode 100644 index 0000000000..2973807a9c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IdentityReaderV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IdentityReaderV2" + endpoint { + name: "io.IdentityReaderV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_If.pbtxt b/tensorflow/core/api_def/java_api/api_def_If.pbtxt new file mode 100644 index 0000000000..a3bc33ac2c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_If.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "If" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Igamma.pbtxt b/tensorflow/core/api_def/java_api/api_def_Igamma.pbtxt new file mode 100644 index 0000000000..cbdd8b984c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Igamma.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Igamma" + endpoint { + name: "math.Igamma" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IgammaGradA.pbtxt b/tensorflow/core/api_def/java_api/api_def_IgammaGradA.pbtxt new file mode 100644 index 0000000000..0659c80c39 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IgammaGradA.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IgammaGradA" + endpoint { + name: "math.IgammaGradA" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Igammac.pbtxt b/tensorflow/core/api_def/java_api/api_def_Igammac.pbtxt new file mode 100644 index 0000000000..94f6085e1a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Igammac.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Igammac" + endpoint { + name: "math.Igammac" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Imag.pbtxt b/tensorflow/core/api_def/java_api/api_def_Imag.pbtxt new file mode 100644 index 0000000000..4227c7078f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Imag.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Imag" + endpoint { + name: "math.Imag" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ImageSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_ImageSummary.pbtxt new file mode 100644 index 0000000000..1871e6b655 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ImageSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ImageSummary" + endpoint { + name: "summary.ImageSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ImmutableConst.pbtxt b/tensorflow/core/api_def/java_api/api_def_ImmutableConst.pbtxt new file mode 100644 index 0000000000..fd0384dc45 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ImmutableConst.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ImmutableConst" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ImportEvent.pbtxt b/tensorflow/core/api_def/java_api/api_def_ImportEvent.pbtxt new file mode 100644 index 0000000000..c2d8d2eba3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ImportEvent.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ImportEvent" + endpoint { + name: "summary.ImportEvent" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt b/tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt new file mode 100644 index 0000000000..1cca92e0ea --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "InTopK" + endpoint { + name: "nn.InTopK" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt new file mode 100644 index 0000000000..3dc9bff289 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "InTopKV2" + endpoint { + name: "nn.InTopKV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_InitializeTable.pbtxt b/tensorflow/core/api_def/java_api/api_def_InitializeTable.pbtxt new file mode 100644 index 0000000000..49496f29a0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InitializeTable.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "InitializeTable" +} diff --git a/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFile.pbtxt b/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFile.pbtxt new file mode 100644 index 0000000000..8cc206b0f0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFile.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "InitializeTableFromTextFile" +} diff --git a/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFileV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFileV2.pbtxt new file mode 100644 index 0000000000..2a665348a7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFileV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "InitializeTableFromTextFileV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_InitializeTableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_InitializeTableV2.pbtxt new file mode 100644 index 0000000000..8d9bec2f2f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InitializeTableV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "InitializeTableV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_InplaceAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_InplaceAdd.pbtxt new file mode 100644 index 0000000000..3d157ab7f8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InplaceAdd.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "InplaceAdd" +} diff --git a/tensorflow/core/api_def/java_api/api_def_InplaceSub.pbtxt b/tensorflow/core/api_def/java_api/api_def_InplaceSub.pbtxt new file mode 100644 index 0000000000..b2ed549643 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InplaceSub.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "InplaceSub" +} diff --git a/tensorflow/core/api_def/java_api/api_def_InplaceUpdate.pbtxt b/tensorflow/core/api_def/java_api/api_def_InplaceUpdate.pbtxt new file mode 100644 index 0000000000..91041b43ab --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InplaceUpdate.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "InplaceUpdate" +} diff --git a/tensorflow/core/api_def/java_api/api_def_InterleaveDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_InterleaveDataset.pbtxt new file mode 100644 index 0000000000..25e40ac2db --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InterleaveDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "InterleaveDataset" + endpoint { + name: "data.InterleaveDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Inv.pbtxt b/tensorflow/core/api_def/java_api/api_def_Inv.pbtxt new file mode 100644 index 0000000000..49f3e6c042 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Inv.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Inv" + endpoint { + name: "linalg.Inv" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_InvGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_InvGrad.pbtxt new file mode 100644 index 0000000000..d3bfa78e99 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InvGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "InvGrad" + endpoint { + name: "nn.InvGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Invert.pbtxt b/tensorflow/core/api_def/java_api/api_def_Invert.pbtxt new file mode 100644 index 0000000000..9898bfa003 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Invert.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Invert" + endpoint { + name: "bitwise.Invert" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_InvertPermutation.pbtxt b/tensorflow/core/api_def/java_api/api_def_InvertPermutation.pbtxt new file mode 100644 index 0000000000..9ee103f554 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_InvertPermutation.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "InvertPermutation" + endpoint { + name: "math.InvertPermutation" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IsBoostedTreesEnsembleInitialized.pbtxt b/tensorflow/core/api_def/java_api/api_def_IsBoostedTreesEnsembleInitialized.pbtxt new file mode 100644 index 0000000000..35f17b7924 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IsBoostedTreesEnsembleInitialized.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "IsBoostedTreesEnsembleInitialized" +} diff --git a/tensorflow/core/api_def/java_api/api_def_IsBoostedTreesQuantileStreamResourceInitialized.pbtxt b/tensorflow/core/api_def/java_api/api_def_IsBoostedTreesQuantileStreamResourceInitialized.pbtxt new file mode 100644 index 0000000000..d6cd2dcc45 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IsBoostedTreesQuantileStreamResourceInitialized.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "IsBoostedTreesQuantileStreamResourceInitialized" +} diff --git a/tensorflow/core/api_def/java_api/api_def_IsFinite.pbtxt b/tensorflow/core/api_def/java_api/api_def_IsFinite.pbtxt new file mode 100644 index 0000000000..fce5890399 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IsFinite.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IsFinite" + endpoint { + name: "math.IsFinite" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IsInf.pbtxt b/tensorflow/core/api_def/java_api/api_def_IsInf.pbtxt new file mode 100644 index 0000000000..823c1d7281 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IsInf.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IsInf" + endpoint { + name: "math.IsInf" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IsNan.pbtxt b/tensorflow/core/api_def/java_api/api_def_IsNan.pbtxt new file mode 100644 index 0000000000..58805bf99f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IsNan.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IsNan" + endpoint { + name: "math.IsNan" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IsVariableInitialized.pbtxt b/tensorflow/core/api_def/java_api/api_def_IsVariableInitialized.pbtxt new file mode 100644 index 0000000000..7bf51da2da --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IsVariableInitialized.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "IsVariableInitialized" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt b/tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt new file mode 100644 index 0000000000..7d4b5e6328 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Iterator" + endpoint { + name: "data.Iterator" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandle.pbtxt new file mode 100644 index 0000000000..b2fe71a0c1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandle.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IteratorFromStringHandle" + endpoint { + name: "data.IteratorFromStringHandle" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandleV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandleV2.pbtxt new file mode 100644 index 0000000000..c77959f34c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandleV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IteratorFromStringHandleV2" + endpoint { + name: "data.IteratorFromStringHandleV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorGetNext.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorGetNext.pbtxt new file mode 100644 index 0000000000..2248ff9f5f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IteratorGetNext.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IteratorGetNext" + endpoint { + name: "data.IteratorGetNext" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorGetNextAsOptional.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorGetNextAsOptional.pbtxt new file mode 100644 index 0000000000..ae02a0e017 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IteratorGetNextAsOptional.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IteratorGetNextAsOptional" + endpoint { + name: "data.IteratorGetNextAsOptional" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorGetNextSync.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorGetNextSync.pbtxt new file mode 100644 index 0000000000..4aa7c07a77 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IteratorGetNextSync.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IteratorGetNextSync" + endpoint { + name: "data.IteratorGetNextSync" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorToStringHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorToStringHandle.pbtxt new file mode 100644 index 0000000000..7413ec846e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IteratorToStringHandle.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IteratorToStringHandle" + endpoint { + name: "data.IteratorToStringHandle" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt new file mode 100644 index 0000000000..7892b096fe --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "IteratorV2" + endpoint { + name: "data.IteratorV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_L2Loss.pbtxt b/tensorflow/core/api_def/java_api/api_def_L2Loss.pbtxt new file mode 100644 index 0000000000..c348e0f0e0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_L2Loss.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "L2Loss" + endpoint { + name: "nn.L2Loss" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt new file mode 100644 index 0000000000..226fa21953 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LMDBReader" + endpoint { + name: "io.LMDBReader" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LRN.pbtxt b/tensorflow/core/api_def/java_api/api_def_LRN.pbtxt new file mode 100644 index 0000000000..d16fea3184 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LRN.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LRN" + endpoint { + name: "nn.LocalResponseNormalization" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LRNGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_LRNGrad.pbtxt new file mode 100644 index 0000000000..a50e738d78 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LRNGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LRNGrad" + endpoint { + name: "nn.LocalResponseNormalizationGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LatencyStatsDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_LatencyStatsDataset.pbtxt new file mode 100644 index 0000000000..bf0bf2a5ed --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LatencyStatsDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LatencyStatsDataset" + endpoint { + name: "data.LatencyStatsDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LeakyRelu.pbtxt b/tensorflow/core/api_def/java_api/api_def_LeakyRelu.pbtxt new file mode 100644 index 0000000000..31a4f01167 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LeakyRelu.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LeakyRelu" + endpoint { + name: "nn.LeakyRelu" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LeakyReluGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_LeakyReluGrad.pbtxt new file mode 100644 index 0000000000..9899c64c13 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LeakyReluGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LeakyReluGrad" + endpoint { + name: "data.LeakyReluGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LearnedUnigramCandidateSampler.pbtxt b/tensorflow/core/api_def/java_api/api_def_LearnedUnigramCandidateSampler.pbtxt new file mode 100644 index 0000000000..5f193da1be --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LearnedUnigramCandidateSampler.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LearnedUnigramCandidateSampler" + endpoint { + name: "nn.LearnedUnigramCandidateSampler" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LeftShift.pbtxt b/tensorflow/core/api_def/java_api/api_def_LeftShift.pbtxt new file mode 100644 index 0000000000..44a8727e40 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LeftShift.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LeftShift" + endpoint { + name: "bitwise.LeftShift" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Less.pbtxt b/tensorflow/core/api_def/java_api/api_def_Less.pbtxt new file mode 100644 index 0000000000..577d2556b8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Less.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Less" + endpoint { + name: "math.Less" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LessEqual.pbtxt b/tensorflow/core/api_def/java_api/api_def_LessEqual.pbtxt new file mode 100644 index 0000000000..6cad35c622 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LessEqual.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LessEqual" + endpoint { + name: "math.LessEqual" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Lgamma.pbtxt b/tensorflow/core/api_def/java_api/api_def_Lgamma.pbtxt new file mode 100644 index 0000000000..eb7bc9660c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Lgamma.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Lgamma" + endpoint { + name: "math.Lgamma" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LinSpace.pbtxt b/tensorflow/core/api_def/java_api/api_def_LinSpace.pbtxt new file mode 100644 index 0000000000..599c310021 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LinSpace.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LinSpace" + endpoint { + name: "LinSpace" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt b/tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt new file mode 100644 index 0000000000..bbbd3bb3ec --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ListDiff" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LoadAndRemapMatrix.pbtxt b/tensorflow/core/api_def/java_api/api_def_LoadAndRemapMatrix.pbtxt new file mode 100644 index 0000000000..54ee68fde4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LoadAndRemapMatrix.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LoadAndRemapMatrix" + endpoint { + name: "linalg.LoadAndRemapMatrix" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Log.pbtxt b/tensorflow/core/api_def/java_api/api_def_Log.pbtxt new file mode 100644 index 0000000000..9d11c26c71 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Log.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Log" + endpoint { + name: "math.Log" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Log1p.pbtxt b/tensorflow/core/api_def/java_api/api_def_Log1p.pbtxt new file mode 100644 index 0000000000..6cc1d6e6c8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Log1p.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Log1p" + endpoint { + name: "math.Log1p" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LogMatrixDeterminant.pbtxt b/tensorflow/core/api_def/java_api/api_def_LogMatrixDeterminant.pbtxt new file mode 100644 index 0000000000..5e52d9eced --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LogMatrixDeterminant.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LogMatrixDeterminant" + endpoint { + name: "linalg.LogMatrixDeterminant" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LogSoftmax.pbtxt b/tensorflow/core/api_def/java_api/api_def_LogSoftmax.pbtxt new file mode 100644 index 0000000000..19518a71ea --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LogSoftmax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LogSoftmax" + endpoint { + name: "nn.LogSoftmax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LogUniformCandidateSampler.pbtxt b/tensorflow/core/api_def/java_api/api_def_LogUniformCandidateSampler.pbtxt new file mode 100644 index 0000000000..bdcf01c20f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LogUniformCandidateSampler.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LogUniformCandidateSampler" + endpoint { + name: "random.LogUniformCandidateSampler" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LogicalAnd.pbtxt b/tensorflow/core/api_def/java_api/api_def_LogicalAnd.pbtxt new file mode 100644 index 0000000000..12921dd932 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LogicalAnd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LogicalAnd" + endpoint { + name: "math.LogicalAnd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LogicalNot.pbtxt b/tensorflow/core/api_def/java_api/api_def_LogicalNot.pbtxt new file mode 100644 index 0000000000..9e0960958e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LogicalNot.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LogicalNot" + endpoint { + name: "math.LogicalNot" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LogicalOr.pbtxt b/tensorflow/core/api_def/java_api/api_def_LogicalOr.pbtxt new file mode 100644 index 0000000000..6c834e4641 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LogicalOr.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "LogicalOr" + endpoint { + name: "math.LogicalOr" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableExport.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableExport.pbtxt new file mode 100644 index 0000000000..49637da997 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableExport.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableExport" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableExportV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableExportV2.pbtxt new file mode 100644 index 0000000000..fce8a6e3cc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableExportV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableExportV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableFind.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableFind.pbtxt new file mode 100644 index 0000000000..f8637744ae --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableFind.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableFind" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableFindV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableFindV2.pbtxt new file mode 100644 index 0000000000..cb78732e9c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableFindV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableFindV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableImport.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableImport.pbtxt new file mode 100644 index 0000000000..4cf7971f56 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableImport.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableImport" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableImportV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableImportV2.pbtxt new file mode 100644 index 0000000000..3216346961 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableImportV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableImportV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableInsert.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableInsert.pbtxt new file mode 100644 index 0000000000..51fe22ba60 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableInsert.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableInsert" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt new file mode 100644 index 0000000000..429bf25b0a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableInsertV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt new file mode 100644 index 0000000000..274dd236e3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableRemoveV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableSize.pbtxt new file mode 100644 index 0000000000..70329e9e90 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableSize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableSize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt new file mode 100644 index 0000000000..d5681c3fa0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LookupTableSizeV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LoopCond.pbtxt b/tensorflow/core/api_def/java_api/api_def_LoopCond.pbtxt new file mode 100644 index 0000000000..492f78f62e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LoopCond.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LoopCond" +} diff --git a/tensorflow/core/api_def/java_api/api_def_LowerBound.pbtxt b/tensorflow/core/api_def/java_api/api_def_LowerBound.pbtxt new file mode 100644 index 0000000000..31f1d3038c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_LowerBound.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "LowerBound" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MakeIterator.pbtxt b/tensorflow/core/api_def/java_api/api_def_MakeIterator.pbtxt new file mode 100644 index 0000000000..9dfa761370 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MakeIterator.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MakeIterator" + endpoint { + name: "data.MakeIterator" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt new file mode 100644 index 0000000000..b8f23009d7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MapAndBatchDataset" + endpoint { + name: "data.MapAndBatchDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt new file mode 100644 index 0000000000..a0bc306c52 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MapAndBatchDatasetV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapClear.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapClear.pbtxt new file mode 100644 index 0000000000..3ed9bf8a5d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapClear.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MapClear" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapDataset.pbtxt new file mode 100644 index 0000000000..fdec9eb857 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MapDataset" + endpoint { + name: "data.MapDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapDefun.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapDefun.pbtxt new file mode 100644 index 0000000000..43b1dc722c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapDefun.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MapDefun" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapIncompleteSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapIncompleteSize.pbtxt new file mode 100644 index 0000000000..659993e42b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapIncompleteSize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MapIncompleteSize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapPeek.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapPeek.pbtxt new file mode 100644 index 0000000000..eb1bd158f0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapPeek.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MapPeek" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapSize.pbtxt new file mode 100644 index 0000000000..4da151152c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapSize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MapSize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapStage.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapStage.pbtxt new file mode 100644 index 0000000000..6d9f66cfc4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapStage.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MapStage" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapUnstage.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapUnstage.pbtxt new file mode 100644 index 0000000000..bb118f0fcb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapUnstage.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MapUnstage" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MapUnstageNoKey.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapUnstageNoKey.pbtxt new file mode 100644 index 0000000000..1004e96482 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MapUnstageNoKey.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MapUnstageNoKey" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatMul.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatMul.pbtxt new file mode 100644 index 0000000000..fe4b8405b9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatMul.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatMul" + endpoint { + name: "linalg.MatMul" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatchingFiles.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatchingFiles.pbtxt new file mode 100644 index 0000000000..bb7b096895 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatchingFiles.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatchingFiles" + endpoint { + name: "io.MatchingFiles" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatchingFilesDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatchingFilesDataset.pbtxt new file mode 100644 index 0000000000..749257c37b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatchingFilesDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatchingFilesDataset" + endpoint { + name: "data.MatchingFilesDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixBandPart.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixBandPart.pbtxt new file mode 100644 index 0000000000..eaf426c00e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixBandPart.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixBandPart" + endpoint { + name: "linalg.BandPart" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixDeterminant.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixDeterminant.pbtxt new file mode 100644 index 0000000000..b56d2dad3a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixDeterminant.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixDeterminant" + endpoint { + name: "linalg.Det" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixDiag.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixDiag.pbtxt new file mode 100644 index 0000000000..839cd82b89 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixDiag.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixDiag" + endpoint { + name: "linalg.Diag" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixDiagPart.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixDiagPart.pbtxt new file mode 100644 index 0000000000..008f75c1e9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixDiagPart.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixDiagPart" + endpoint { + name: "linalg.DiagPart" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixExponential.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixExponential.pbtxt new file mode 100644 index 0000000000..fb232dab98 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixExponential.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixExponential" + endpoint { + name: "linalg.MatrixExponential" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixInverse.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixInverse.pbtxt new file mode 100644 index 0000000000..68721fc78d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixInverse.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixInverse" + endpoint { + name: "linalg.Inv" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixLogarithm.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixLogarithm.pbtxt new file mode 100644 index 0000000000..04137ffae7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixLogarithm.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixLogarithm" + endpoint { + name: "linalg.MatrixLogarithm" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixSetDiag.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixSetDiag.pbtxt new file mode 100644 index 0000000000..61001fa38c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixSetDiag.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixSetDiag" + endpoint { + name: "linalg.SetDiag" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixSolve.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixSolve.pbtxt new file mode 100644 index 0000000000..02c21448bb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixSolve.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixSolve" + endpoint { + name: "linalg.Solve" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixSolveLs.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixSolveLs.pbtxt new file mode 100644 index 0000000000..9cee578ec2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixSolveLs.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixSolveLs" + endpoint { + name: "linalg.MatrixSolveLs" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixSquareRoot.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixSquareRoot.pbtxt new file mode 100644 index 0000000000..14c7624fe3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixSquareRoot.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixSquareRoot" + endpoint { + name: "linalg.Sqrtm" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MatrixTriangularSolve.pbtxt b/tensorflow/core/api_def/java_api/api_def_MatrixTriangularSolve.pbtxt new file mode 100644 index 0000000000..1f61e99efe --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MatrixTriangularSolve.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MatrixTriangularSolve" + endpoint { + name: "linalg.TriangularSolve" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Max.pbtxt b/tensorflow/core/api_def/java_api/api_def_Max.pbtxt new file mode 100644 index 0000000000..03868720ed --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Max.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Max" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt new file mode 100644 index 0000000000..17c17b5699 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPool" + endpoint { + name: "nn.MaxPool" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPool3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPool3D.pbtxt new file mode 100644 index 0000000000..17aeb6a8c9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPool3D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPool3D" + endpoint { + name: "nn.MaxPool3d" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt new file mode 100644 index 0000000000..7f5ab71845 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPool3DGrad" + endpoint { + name: "nn.MaxPool3DGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt new file mode 100644 index 0000000000..4d7211add2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPool3DGradGrad" + endpoint { + name: "nn.MaxPool3DGradGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt new file mode 100644 index 0000000000..c8b783ee7a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPoolGrad" + endpoint { + name: "nn.MaxPoolGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt new file mode 100644 index 0000000000..2dd7fdf229 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPoolGradGrad" + endpoint { + name: "nn.MaxPoolGradGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt new file mode 100644 index 0000000000..e2cf7927ca --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPoolGradGradV2" + endpoint { + name: "nn.MaxPoolGradGradV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradWithArgmax.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradWithArgmax.pbtxt new file mode 100644 index 0000000000..d43cf7447c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradWithArgmax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPoolGradGradWithArgmax" + endpoint { + name: "nn.MaxPoolGradGradWithArgmax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt new file mode 100644 index 0000000000..1e47cd13e3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPoolGradV2" + endpoint { + name: "nn.MaxPoolGradV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradWithArgmax.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradWithArgmax.pbtxt new file mode 100644 index 0000000000..c10701f555 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradWithArgmax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPoolGradWithArgmax" + endpoint { + name: "nn.MaxPoolGradWithArgmax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt new file mode 100644 index 0000000000..bd885135d5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPoolV2" + endpoint { + name: "nn.MaxPoolV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolWithArgmax.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolWithArgmax.pbtxt new file mode 100644 index 0000000000..43630534cb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolWithArgmax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MaxPoolWithArgmax" + endpoint { + name: "nn.MaxPoolWithArgmax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Maximum.pbtxt b/tensorflow/core/api_def/java_api/api_def_Maximum.pbtxt new file mode 100644 index 0000000000..1df9c60530 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Maximum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Maximum" + endpoint { + name: "math.Maximum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Mean.pbtxt b/tensorflow/core/api_def/java_api/api_def_Mean.pbtxt new file mode 100644 index 0000000000..7bdcdc3d74 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Mean.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Mean" + endpoint { + name: "math.Mean" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Merge.pbtxt b/tensorflow/core/api_def/java_api/api_def_Merge.pbtxt new file mode 100644 index 0000000000..954d5085ad --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Merge.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Merge" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MergeSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_MergeSummary.pbtxt new file mode 100644 index 0000000000..f52c7c0996 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MergeSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MergeSummary" + endpoint { + name: "summary.MergeSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MergeV2Checkpoints.pbtxt b/tensorflow/core/api_def/java_api/api_def_MergeV2Checkpoints.pbtxt new file mode 100644 index 0000000000..8899c8c4ed --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MergeV2Checkpoints.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MergeV2Checkpoints" + endpoint { + name: "train.MergeV2Checkpoints" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Mfcc.pbtxt b/tensorflow/core/api_def/java_api/api_def_Mfcc.pbtxt new file mode 100644 index 0000000000..6cb04e73ff --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Mfcc.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Mfcc" + endpoint { + name: "audio.Mfcc" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Min.pbtxt b/tensorflow/core/api_def/java_api/api_def_Min.pbtxt new file mode 100644 index 0000000000..72894c1ffd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Min.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Min" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Minimum.pbtxt b/tensorflow/core/api_def/java_api/api_def_Minimum.pbtxt new file mode 100644 index 0000000000..69f76a9829 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Minimum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Minimum" + endpoint { + name: "math.Minimum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MirrorPad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MirrorPad.pbtxt new file mode 100644 index 0000000000..e1cb766f8f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MirrorPad.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MirrorPad" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MirrorPadGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MirrorPadGrad.pbtxt new file mode 100644 index 0000000000..ddd8ab3ba1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MirrorPadGrad.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MirrorPadGrad" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Mod.pbtxt b/tensorflow/core/api_def/java_api/api_def_Mod.pbtxt new file mode 100644 index 0000000000..76fbbe97a8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Mod.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Mod" + endpoint { + name: "math.Mod" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ModelDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ModelDataset.pbtxt new file mode 100644 index 0000000000..143c7afd72 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ModelDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ModelDataset" + endpoint { + name: "data.ModelDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Mul.pbtxt b/tensorflow/core/api_def/java_api/api_def_Mul.pbtxt new file mode 100644 index 0000000000..605e110931 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Mul.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Mul" + endpoint { + name: "math.Mul" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MultiDeviceIterator.pbtxt b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIterator.pbtxt new file mode 100644 index 0000000000..81eabf9bdc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIterator.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MultiDeviceIterator" + endpoint { + name: "data.MultiDeviceIterator" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorFromStringHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorFromStringHandle.pbtxt new file mode 100644 index 0000000000..4006f72d52 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorFromStringHandle.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MultiDeviceIteratorFromStringHandle" + endpoint { + name: "data.MultiDeviceIteratorFromStringHandle" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorGetNextFromShard.pbtxt b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorGetNextFromShard.pbtxt new file mode 100644 index 0000000000..a7e6fc1508 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorGetNextFromShard.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MultiDeviceIteratorGetNextFromShard" + endpoint { + name: "data.MultiDeviceIteratorGetNextFromShard" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorInit.pbtxt b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorInit.pbtxt new file mode 100644 index 0000000000..1663bc5c22 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorInit.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MultiDeviceIteratorInit" + endpoint { + name: "data.MultiDeviceIteratorInit" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorToStringHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorToStringHandle.pbtxt new file mode 100644 index 0000000000..ff061da390 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MultiDeviceIteratorToStringHandle.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "MultiDeviceIteratorToStringHandle" + endpoint { + name: "data.MultiDeviceIteratorToStringHandle" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Multinomial.pbtxt b/tensorflow/core/api_def/java_api/api_def_Multinomial.pbtxt new file mode 100644 index 0000000000..bd98bb10b4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Multinomial.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Multinomial" + endpoint { + name: "random.Multinomial" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTable.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTable.pbtxt new file mode 100644 index 0000000000..15803468ff --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTable.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MutableDenseHashTable" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt new file mode 100644 index 0000000000..03fdeddb95 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MutableDenseHashTableV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MutableHashTable.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableHashTable.pbtxt new file mode 100644 index 0000000000..1a80874495 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MutableHashTable.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MutableHashTable" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensors.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensors.pbtxt new file mode 100644 index 0000000000..bf2fa065dc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensors.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MutableHashTableOfTensors" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensorsV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensorsV2.pbtxt new file mode 100644 index 0000000000..53d780e925 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensorsV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MutableHashTableOfTensorsV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MutableHashTableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableHashTableV2.pbtxt new file mode 100644 index 0000000000..99007df253 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MutableHashTableV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MutableHashTableV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MutexLock.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutexLock.pbtxt new file mode 100644 index 0000000000..75c7be5286 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MutexLock.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MutexLock" +} diff --git a/tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt new file mode 100644 index 0000000000..93988914aa --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "MutexV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_NcclAllReduce.pbtxt b/tensorflow/core/api_def/java_api/api_def_NcclAllReduce.pbtxt new file mode 100644 index 0000000000..c7133d4a4a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NcclAllReduce.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "NcclAllReduce" +} diff --git a/tensorflow/core/api_def/java_api/api_def_NcclBroadcast.pbtxt b/tensorflow/core/api_def/java_api/api_def_NcclBroadcast.pbtxt new file mode 100644 index 0000000000..b9b1a345c9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NcclBroadcast.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "NcclBroadcast" +} diff --git a/tensorflow/core/api_def/java_api/api_def_NcclReduce.pbtxt b/tensorflow/core/api_def/java_api/api_def_NcclReduce.pbtxt new file mode 100644 index 0000000000..18dc890177 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NcclReduce.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "NcclReduce" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Neg.pbtxt b/tensorflow/core/api_def/java_api/api_def_Neg.pbtxt new file mode 100644 index 0000000000..c7e9ede2a5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Neg.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Neg" + endpoint { + name: "math.Neg" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_NegTrain.pbtxt b/tensorflow/core/api_def/java_api/api_def_NegTrain.pbtxt new file mode 100644 index 0000000000..eb62186362 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NegTrain.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "NegTrain" + endpoint { + name: "train.NegTrain" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_NextIteration.pbtxt b/tensorflow/core/api_def/java_api/api_def_NextIteration.pbtxt new file mode 100644 index 0000000000..bc63f6ada1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NextIteration.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "NextIteration" +} diff --git a/tensorflow/core/api_def/java_api/api_def_NoOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_NoOp.pbtxt new file mode 100644 index 0000000000..337fb5da14 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NoOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "NoOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppression.pbtxt b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppression.pbtxt new file mode 100644 index 0000000000..d7156b0a3a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppression.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "NonMaxSuppression" + endpoint { + name: "image.NonMaxSuppression" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt new file mode 100644 index 0000000000..d78eb9745d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "NonMaxSuppressionV2" + endpoint { + name: "image.NonMaxSuppressionV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt new file mode 100644 index 0000000000..e3fde0a566 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "NonMaxSuppressionV3" + endpoint { + name: "image.NonMaxSuppressionV3" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt new file mode 100644 index 0000000000..98776e8e7f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "NonMaxSuppressionV4" + endpoint { + name: "image.NonMaxSuppressionV4" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionWithOverlaps.pbtxt b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionWithOverlaps.pbtxt new file mode 100644 index 0000000000..06fa52920d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionWithOverlaps.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "NonMaxSuppressionWithOverlaps" + endpoint { + name: "image.NonMaxSuppressionWithOverlaps" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_NotEqual.pbtxt b/tensorflow/core/api_def/java_api/api_def_NotEqual.pbtxt new file mode 100644 index 0000000000..0d99af40b5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NotEqual.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "NotEqual" + endpoint { + name: "math.NotEqual" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_NthElement.pbtxt b/tensorflow/core/api_def/java_api/api_def_NthElement.pbtxt new file mode 100644 index 0000000000..57097e634a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_NthElement.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "NthElement" + endpoint { + name: "nn.NthElement" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_OneHot.pbtxt b/tensorflow/core/api_def/java_api/api_def_OneHot.pbtxt new file mode 100644 index 0000000000..66872d5eb8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OneHot.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "OneHot" +} diff --git a/tensorflow/core/api_def/java_api/api_def_OneShotIterator.pbtxt b/tensorflow/core/api_def/java_api/api_def_OneShotIterator.pbtxt new file mode 100644 index 0000000000..39af8cefde --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OneShotIterator.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "OneShotIterator" + endpoint { + name: "data.OneShotIterator" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_OnesLike.pbtxt b/tensorflow/core/api_def/java_api/api_def_OnesLike.pbtxt new file mode 100644 index 0000000000..97abe0814a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OnesLike.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "OnesLike" +} diff --git a/tensorflow/core/api_def/java_api/api_def_OptimizeDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_OptimizeDataset.pbtxt new file mode 100644 index 0000000000..e7ddf97d1a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OptimizeDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "OptimizeDataset" + endpoint { + name: "data.OptimizeDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_OptionalFromValue.pbtxt b/tensorflow/core/api_def/java_api/api_def_OptionalFromValue.pbtxt new file mode 100644 index 0000000000..d251fd5d94 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OptionalFromValue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "OptionalFromValue" + endpoint { + name: "data.OptionalFromValue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_OptionalGetValue.pbtxt b/tensorflow/core/api_def/java_api/api_def_OptionalGetValue.pbtxt new file mode 100644 index 0000000000..7fcdb5ac69 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OptionalGetValue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "OptionalGetValue" + endpoint { + name: "data.OptionalGetValue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_OptionalHasValue.pbtxt b/tensorflow/core/api_def/java_api/api_def_OptionalHasValue.pbtxt new file mode 100644 index 0000000000..4ffa15b564 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OptionalHasValue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "OptionalHasValue" + endpoint { + name: "data.OptionalHasValue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_OptionalNone.pbtxt b/tensorflow/core/api_def/java_api/api_def_OptionalNone.pbtxt new file mode 100644 index 0000000000..cec29a42ae --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OptionalNone.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "OptionalNone" + endpoint { + name: "data.OptionalNone" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_OrderedMapClear.pbtxt b/tensorflow/core/api_def/java_api/api_def_OrderedMapClear.pbtxt new file mode 100644 index 0000000000..e36b2aa3e4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OrderedMapClear.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "OrderedMapClear" +} diff --git a/tensorflow/core/api_def/java_api/api_def_OrderedMapIncompleteSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_OrderedMapIncompleteSize.pbtxt new file mode 100644 index 0000000000..c609e9e50a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OrderedMapIncompleteSize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "OrderedMapIncompleteSize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_OrderedMapPeek.pbtxt b/tensorflow/core/api_def/java_api/api_def_OrderedMapPeek.pbtxt new file mode 100644 index 0000000000..06fc218277 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OrderedMapPeek.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "OrderedMapPeek" +} diff --git a/tensorflow/core/api_def/java_api/api_def_OrderedMapSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_OrderedMapSize.pbtxt new file mode 100644 index 0000000000..7beef3f376 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OrderedMapSize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "OrderedMapSize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_OrderedMapStage.pbtxt b/tensorflow/core/api_def/java_api/api_def_OrderedMapStage.pbtxt new file mode 100644 index 0000000000..8b579d21a0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OrderedMapStage.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "OrderedMapStage" +} diff --git a/tensorflow/core/api_def/java_api/api_def_OrderedMapUnstage.pbtxt b/tensorflow/core/api_def/java_api/api_def_OrderedMapUnstage.pbtxt new file mode 100644 index 0000000000..d3d6862fbe --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OrderedMapUnstage.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "OrderedMapUnstage" +} diff --git a/tensorflow/core/api_def/java_api/api_def_OrderedMapUnstageNoKey.pbtxt b/tensorflow/core/api_def/java_api/api_def_OrderedMapUnstageNoKey.pbtxt new file mode 100644 index 0000000000..3d275c85d9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_OrderedMapUnstageNoKey.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "OrderedMapUnstageNoKey" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Pack.pbtxt b/tensorflow/core/api_def/java_api/api_def_Pack.pbtxt new file mode 100644 index 0000000000..d9e9897d77 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Pack.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Pack" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Pad.pbtxt b/tensorflow/core/api_def/java_api/api_def_Pad.pbtxt new file mode 100644 index 0000000000..a9de5541ac --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Pad.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Pad" +} diff --git a/tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt new file mode 100644 index 0000000000..1554cd0b64 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "PadV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt new file mode 100644 index 0000000000..2d734539da --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PaddedBatchDataset" + endpoint { + name: "data.PaddedBatchDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt new file mode 100644 index 0000000000..d4b85550e9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PaddedBatchDatasetV2" + endpoint { + name: "data.PaddedBatchDatasetV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt new file mode 100644 index 0000000000..151ab0f872 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PaddingFIFOQueue" + endpoint { + name: "io.PaddingFIFOQueue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt new file mode 100644 index 0000000000..4b589a9afb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PaddingFIFOQueueV2" + endpoint { + name: "io.PaddingFIFOQueueV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParallelConcat.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParallelConcat.pbtxt new file mode 100644 index 0000000000..0b17c7d256 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParallelConcat.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ParallelConcat" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParallelDynamicStitch.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParallelDynamicStitch.pbtxt new file mode 100644 index 0000000000..79a55b763f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParallelDynamicStitch.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ParallelDynamicStitch" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDataset.pbtxt new file mode 100644 index 0000000000..3ccc2a6bf7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ParallelInterleaveDataset" + endpoint { + name: "data.ParallelInterleaveDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDatasetV2.pbtxt new file mode 100644 index 0000000000..56b05cc2f6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDatasetV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ParallelInterleaveDatasetV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParallelMapDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParallelMapDataset.pbtxt new file mode 100644 index 0000000000..5091bb9cec --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParallelMapDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ParallelMapDataset" + endpoint { + name: "data.ParallelMapDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParameterizedTruncatedNormal.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParameterizedTruncatedNormal.pbtxt new file mode 100644 index 0000000000..26ca2fc86f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParameterizedTruncatedNormal.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ParameterizedTruncatedNormal" + endpoint { + name: "random.ParameterizedTruncatedNormal" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParseExample.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParseExample.pbtxt new file mode 100644 index 0000000000..6e7384f2e3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParseExample.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ParseExample" + endpoint { + name: "io.ParseExample" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParseExampleDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParseExampleDataset.pbtxt new file mode 100644 index 0000000000..4309645093 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParseExampleDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ParseExampleDataset" + endpoint { + name: "data.ParseExampleDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParseSequenceExample.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParseSequenceExample.pbtxt new file mode 100644 index 0000000000..09ee715ac7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParseSequenceExample.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ParseSequenceExample" + endpoint { + name: "io.ParseSequenceExample" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParseSingleExample.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParseSingleExample.pbtxt new file mode 100644 index 0000000000..7559957b35 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParseSingleExample.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ParseSingleExample" + endpoint { + name: "io.ParseSingleExample" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParseSingleSequenceExample.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParseSingleSequenceExample.pbtxt new file mode 100644 index 0000000000..00eb325b2a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParseSingleSequenceExample.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ParseSingleSequenceExample" + endpoint { + name: "io.ParseSingleSequenceExample" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ParseTensor.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParseTensor.pbtxt new file mode 100644 index 0000000000..a78cdc7f5c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ParseTensor.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ParseTensor" + endpoint { + name: "io.ParseTensor" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_PartitionedCall.pbtxt b/tensorflow/core/api_def/java_api/api_def_PartitionedCall.pbtxt new file mode 100644 index 0000000000..1ac10b6028 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PartitionedCall.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "PartitionedCall" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt b/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt new file mode 100644 index 0000000000..5e6daa2ae4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Placeholder" +} diff --git a/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt new file mode 100644 index 0000000000..39012d4aa2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "PlaceholderV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_PlaceholderWithDefault.pbtxt b/tensorflow/core/api_def/java_api/api_def_PlaceholderWithDefault.pbtxt new file mode 100644 index 0000000000..59067a9c68 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PlaceholderWithDefault.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "PlaceholderWithDefault" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Polygamma.pbtxt b/tensorflow/core/api_def/java_api/api_def_Polygamma.pbtxt new file mode 100644 index 0000000000..746b3375a0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Polygamma.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Polygamma" + endpoint { + name: "math.Polygamma" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_PopulationCount.pbtxt b/tensorflow/core/api_def/java_api/api_def_PopulationCount.pbtxt new file mode 100644 index 0000000000..6aacdf4d12 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PopulationCount.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PopulationCount" + endpoint { + name: "math.PopulationCount" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Pow.pbtxt b/tensorflow/core/api_def/java_api/api_def_Pow.pbtxt new file mode 100644 index 0000000000..e7eaaed695 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Pow.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Pow" + endpoint { + name: "math.Pow" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_PrefetchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_PrefetchDataset.pbtxt new file mode 100644 index 0000000000..beaad84d15 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PrefetchDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PrefetchDataset" + endpoint { + name: "data.PrefetchDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_PrependFromQueueAndPaddedBatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_PrependFromQueueAndPaddedBatchDataset.pbtxt new file mode 100644 index 0000000000..7c9d509b16 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PrependFromQueueAndPaddedBatchDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PrependFromQueueAndPaddedBatchDataset" + endpoint { + name: "data.PrependFromQueueAndPaddedBatchDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_PreventGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_PreventGradient.pbtxt new file mode 100644 index 0000000000..4731f21af4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PreventGradient.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PreventGradient" + endpoint { + name: "train.PreventGradient" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Print.pbtxt b/tensorflow/core/api_def/java_api/api_def_Print.pbtxt new file mode 100644 index 0000000000..5b837135fd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Print.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Print" +} diff --git a/tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt new file mode 100644 index 0000000000..c6e406d08f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "PrintV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_PriorityQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_PriorityQueue.pbtxt new file mode 100644 index 0000000000..cee973139d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PriorityQueue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PriorityQueue" + endpoint { + name: "io.PriorityQueue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_PriorityQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PriorityQueueV2.pbtxt new file mode 100644 index 0000000000..27e89f92be --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PriorityQueueV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "PriorityQueueV2" + endpoint { + name: "io.PriorityQueueV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Prod.pbtxt b/tensorflow/core/api_def/java_api/api_def_Prod.pbtxt new file mode 100644 index 0000000000..7a98972a87 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Prod.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Prod" +} diff --git a/tensorflow/core/api_def/java_api/api_def_PyFunc.pbtxt b/tensorflow/core/api_def/java_api/api_def_PyFunc.pbtxt new file mode 100644 index 0000000000..5f1f7c47ca --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PyFunc.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "PyFunc" + visibility: SKIP +} diff --git a/tensorflow/core/api_def/java_api/api_def_PyFuncStateless.pbtxt b/tensorflow/core/api_def/java_api/api_def_PyFuncStateless.pbtxt new file mode 100644 index 0000000000..684ef58d1b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_PyFuncStateless.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "PyFuncStateless" + visibility: SKIP +} diff --git a/tensorflow/core/api_def/java_api/api_def_Qr.pbtxt b/tensorflow/core/api_def/java_api/api_def_Qr.pbtxt new file mode 100644 index 0000000000..c0d31e7977 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Qr.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Qr" + endpoint { + name: "linalg.Qr" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantize.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantize.pbtxt new file mode 100644 index 0000000000..fe8401d8f9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantize.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizeAndDequantize" + endpoint { + name: "quantization.QuantizeAndDequantize" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt new file mode 100644 index 0000000000..0535993d40 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizeAndDequantizeV2" + endpoint { + name: "quantization.QuantizeAndDequantize" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt new file mode 100644 index 0000000000..d056b320c8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizeAndDequantizeV3" + endpoint { + name: "quantization.QuantizeAndDequantizeV3" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizeDownAndShrinkRange.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizeDownAndShrinkRange.pbtxt new file mode 100644 index 0000000000..7119f53cb2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizeDownAndShrinkRange.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizeDownAndShrinkRange" + endpoint { + name: "quantization.QuantizeDownAndShrinkRange" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt new file mode 100644 index 0000000000..d04a01726f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizeV2" + endpoint { + name: "quantization.QuantizeV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedAdd.pbtxt new file mode 100644 index 0000000000..1a2bfa36ed --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedAdd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedAdd" + endpoint { + name: "math.QuantizedAdd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedAvgPool.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedAvgPool.pbtxt new file mode 100644 index 0000000000..7f16fb046d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedAvgPool.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedAvgPool" + endpoint { + name: "nn.QuantizedAvgPool" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedBatchNormWithGlobalNormalization.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedBatchNormWithGlobalNormalization.pbtxt new file mode 100644 index 0000000000..2101ce5d69 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedBatchNormWithGlobalNormalization.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedBatchNormWithGlobalNormalization" + endpoint { + name: "nn.QuantizedBatchNormWithGlobalNormalization" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedBiasAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedBiasAdd.pbtxt new file mode 100644 index 0000000000..c18fb1c574 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedBiasAdd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedBiasAdd" + endpoint { + name: "nn.QuantizedBiasAdd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedConcat.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedConcat.pbtxt new file mode 100644 index 0000000000..cb5d0c0fda --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedConcat.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "QuantizedConcat" +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedConv2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedConv2D.pbtxt new file mode 100644 index 0000000000..8345892762 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedConv2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedConv2D" + endpoint { + name: "nn.QuantizedConv2D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedInstanceNorm.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedInstanceNorm.pbtxt new file mode 100644 index 0000000000..bbd2e7fc5e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedInstanceNorm.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedInstanceNorm" + endpoint { + name: "nn.QuantizedInstanceNorm" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedMatMul.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedMatMul.pbtxt new file mode 100644 index 0000000000..7962cbade6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedMatMul.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedMatMul" + endpoint { + name: "linalg.QuantizedMatMul" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedMaxPool.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedMaxPool.pbtxt new file mode 100644 index 0000000000..57e900494e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedMaxPool.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedMaxPool" + endpoint { + name: "nn.QuantizedMaxPool" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedMul.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedMul.pbtxt new file mode 100644 index 0000000000..be23ef706e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedMul.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedMul" + endpoint { + name: "math.QuantizedMul" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedRelu.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedRelu.pbtxt new file mode 100644 index 0000000000..7b9a11640b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedRelu.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedRelu" + endpoint { + name: "nn.QuantizedRelu" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedRelu6.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedRelu6.pbtxt new file mode 100644 index 0000000000..6a60e2112e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedRelu6.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedRelu6" + endpoint { + name: "nn.QuantizedRelu6" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedReluX.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedReluX.pbtxt new file mode 100644 index 0000000000..cc47d322b2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedReluX.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedReluX" + endpoint { + name: "nn.QuantizedReluX" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedReshape.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedReshape.pbtxt new file mode 100644 index 0000000000..4557853d94 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedReshape.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "QuantizedReshape" +} diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedResizeBilinear.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedResizeBilinear.pbtxt new file mode 100644 index 0000000000..81dca49094 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedResizeBilinear.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QuantizedResizeBilinear" + endpoint { + name: "image.QuantizedResizeBilinear" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt new file mode 100644 index 0000000000..70e559c773 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueClose" + endpoint { + name: "io.QueueClose" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt new file mode 100644 index 0000000000..01460f27e2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueCloseV2" + endpoint { + name: "io.QueueCloseV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt new file mode 100644 index 0000000000..9cd77b4ca3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueDequeue" + endpoint { + name: "io.QueueDequeue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueMany.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueMany.pbtxt new file mode 100644 index 0000000000..ceb2e82394 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueMany.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueDequeueMany" + endpoint { + name: "io.QueueDequeueMany" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt new file mode 100644 index 0000000000..ac27fcb620 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueDequeueManyV2" + endpoint { + name: "io.QueueDequeueManyV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt new file mode 100644 index 0000000000..657c63363f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueDequeueUpTo" + endpoint { + name: "io.QueueDequeueUpTo" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt new file mode 100644 index 0000000000..19b3fff653 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueDequeueUpToV2" + endpoint { + name: "io.QueueDequeueUpToV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueV2.pbtxt new file mode 100644 index 0000000000..8aca207816 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueDequeueV2" + endpoint { + name: "io.QueueDequeueV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt new file mode 100644 index 0000000000..e516dab297 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueEnqueue" + endpoint { + name: "io.QueueEnqueue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt new file mode 100644 index 0000000000..b9c0e4fd84 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueEnqueueMany" + endpoint { + name: "io.QueueEnqueueMany" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt new file mode 100644 index 0000000000..153700a646 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueEnqueueManyV2" + endpoint { + name: "io.QueueEnqueueManyV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt new file mode 100644 index 0000000000..68bacd7b5b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueEnqueueV2" + endpoint { + name: "io.QueueEnqueueV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueIsClosed.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueIsClosed.pbtxt new file mode 100644 index 0000000000..86914c7124 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueIsClosed.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueIsClosed" + endpoint { + name: "io.QueueIsClosed" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt new file mode 100644 index 0000000000..ce33b2498b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueIsClosedV2" + endpoint { + name: "io.QueueIsClosedV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt new file mode 100644 index 0000000000..5592d58f9f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueSize" + endpoint { + name: "io.QueueSize" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt new file mode 100644 index 0000000000..68364aa605 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "QueueSizeV2" + endpoint { + name: "io.QueueSizeV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt new file mode 100644 index 0000000000..e56a0ba30a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RFFT" + endpoint { + name: "signal.RFFT" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt new file mode 100644 index 0000000000..eb193e638d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RFFT2D" + endpoint { + name: "signal.RFFT2D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt new file mode 100644 index 0000000000..292b957f3e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RFFT3D" + endpoint { + name: "signal.RFFT3D" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RGBToHSV.pbtxt b/tensorflow/core/api_def/java_api/api_def_RGBToHSV.pbtxt new file mode 100644 index 0000000000..1b35891ae2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RGBToHSV.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RGBToHSV" + endpoint { + name: "image.RgbToHsv" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RaggedGather.pbtxt b/tensorflow/core/api_def/java_api/api_def_RaggedGather.pbtxt new file mode 100644 index 0000000000..f060daeb65 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RaggedGather.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RaggedGather" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RaggedRange.pbtxt b/tensorflow/core/api_def/java_api/api_def_RaggedRange.pbtxt new file mode 100644 index 0000000000..b1a5bab0ac --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RaggedRange.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RaggedRange" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RaggedTensorToSparse.pbtxt b/tensorflow/core/api_def/java_api/api_def_RaggedTensorToSparse.pbtxt new file mode 100644 index 0000000000..f049f47b46 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RaggedTensorToSparse.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RaggedTensorToSparse" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomCrop.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomCrop.pbtxt new file mode 100644 index 0000000000..a3b8a3cecd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomCrop.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomCrop" + endpoint { + name: "image.RandomCrop" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomDataset.pbtxt new file mode 100644 index 0000000000..43921e6eaf --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomDataset" + endpoint { + name: "data.RandomDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomGamma.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomGamma.pbtxt new file mode 100644 index 0000000000..927f2c5693 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomGamma.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomGamma" + endpoint { + name: "random.RandomGamma" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomGammaGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomGammaGrad.pbtxt new file mode 100644 index 0000000000..9257495c9b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomGammaGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomGammaGrad" + endpoint { + name: "random.RandomGammaGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomPoisson.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomPoisson.pbtxt new file mode 100644 index 0000000000..42ce1a5fb1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomPoisson.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomPoisson" + endpoint { + name: "random.RandomPoisson" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomPoissonV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomPoissonV2.pbtxt new file mode 100644 index 0000000000..adc5441abc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomPoissonV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomPoissonV2" + endpoint { + name: "random.RandomPoissonV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomShuffle.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomShuffle.pbtxt new file mode 100644 index 0000000000..6dcd12fd37 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomShuffle.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomShuffle" + endpoint { + name: "random.RandomShuffle" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt new file mode 100644 index 0000000000..f622eb4e0d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomShuffleQueue" + endpoint { + name: "io.RandomShuffleQueue" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt new file mode 100644 index 0000000000..c88c2a4631 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomShuffleQueueV2" + endpoint { + name: "io.RandomShuffleQueueV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomStandardNormal.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomStandardNormal.pbtxt new file mode 100644 index 0000000000..413fc87bdf --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomStandardNormal.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomStandardNormal" + endpoint { + name: "random.RandomStandardNormal" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomUniform.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomUniform.pbtxt new file mode 100644 index 0000000000..2a93df83df --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomUniform.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomUniform" + endpoint { + name: "random.RandomUniform" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RandomUniformInt.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomUniformInt.pbtxt new file mode 100644 index 0000000000..a1383f406a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RandomUniformInt.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RandomUniformInt" + endpoint { + name: "random.RandomUniformInt" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Range.pbtxt b/tensorflow/core/api_def/java_api/api_def_Range.pbtxt new file mode 100644 index 0000000000..24f3787a8e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Range.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Range" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RangeDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_RangeDataset.pbtxt new file mode 100644 index 0000000000..b6180261b0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RangeDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RangeDataset" + endpoint { + name: "data.RangeDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Rank.pbtxt b/tensorflow/core/api_def/java_api/api_def_Rank.pbtxt new file mode 100644 index 0000000000..baa84aab10 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Rank.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Rank" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReadFile.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReadFile.pbtxt new file mode 100644 index 0000000000..f74250d42f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReadFile.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReadFile" + endpoint { + name: "io.ReadFile" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReadVariableOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReadVariableOp.pbtxt new file mode 100644 index 0000000000..018886d5b8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReadVariableOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ReadVariableOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt new file mode 100644 index 0000000000..67dbe1035e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderNumRecordsProduced" + endpoint { + name: "io.ReaderNumRecordsProduced" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProducedV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProducedV2.pbtxt new file mode 100644 index 0000000000..5063706eb0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProducedV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderNumRecordsProducedV2" + endpoint { + name: "io.ReaderNumRecordsProducedV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt new file mode 100644 index 0000000000..63bb2d4108 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderNumWorkUnitsCompleted" + endpoint { + name: "io.ReaderNumWorkUnitsCompleted" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt new file mode 100644 index 0000000000..cf72ecc562 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderNumWorkUnitsCompletedV2" + endpoint { + name: "io.ReaderNumWorkUnitsCompletedV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt new file mode 100644 index 0000000000..47e9679f80 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderRead" + endpoint { + name: "io.ReaderRead" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt new file mode 100644 index 0000000000..985d0035b0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderReadUpTo" + endpoint { + name: "io.ReaderReadUpTo" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt new file mode 100644 index 0000000000..a001349e2d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderReadUpToV2" + endpoint { + name: "io.ReaderReadUpToV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt new file mode 100644 index 0000000000..a64349d15e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderReadV2" + endpoint { + name: "io.ReaderReadV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt new file mode 100644 index 0000000000..9a387753f5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderReset" + endpoint { + name: "io.ReaderReset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderResetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderResetV2.pbtxt new file mode 100644 index 0000000000..6e31d5a8ff --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderResetV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderResetV2" + endpoint { + name: "io.ReaderResetV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderRestoreState.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderRestoreState.pbtxt new file mode 100644 index 0000000000..d148adde6a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderRestoreState.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderRestoreState" + endpoint { + name: "io.ReaderRestoreState" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt new file mode 100644 index 0000000000..3d78d8eb00 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderRestoreStateV2" + endpoint { + name: "io.ReaderRestoreStateV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderSerializeState.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderSerializeState.pbtxt new file mode 100644 index 0000000000..fd12a4c784 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderSerializeState.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderSerializeState" + endpoint { + name: "io.ReaderSerializeState" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt new file mode 100644 index 0000000000..28c5048fc9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReaderSerializeStateV2" + endpoint { + name: "io.ReaderSerializeStateV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Real.pbtxt b/tensorflow/core/api_def/java_api/api_def_Real.pbtxt new file mode 100644 index 0000000000..3aaea928de --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Real.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Real" + endpoint { + name: "math.Real" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RealDiv.pbtxt b/tensorflow/core/api_def/java_api/api_def_RealDiv.pbtxt new file mode 100644 index 0000000000..415bd29da0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RealDiv.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RealDiv" + endpoint { + name: "math.RealDiv" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Reciprocal.pbtxt b/tensorflow/core/api_def/java_api/api_def_Reciprocal.pbtxt new file mode 100644 index 0000000000..1c0d787c24 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Reciprocal.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Reciprocal" + endpoint { + name: "math.Reciprocal" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReciprocalGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReciprocalGrad.pbtxt new file mode 100644 index 0000000000..68879669b5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReciprocalGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReciprocalGrad" + endpoint { + name: "math.ReciprocalGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RecordInput.pbtxt b/tensorflow/core/api_def/java_api/api_def_RecordInput.pbtxt new file mode 100644 index 0000000000..c4807c68de --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RecordInput.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RecordInput" + endpoint { + name: "random.RecordInput" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReduceDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReduceDataset.pbtxt new file mode 100644 index 0000000000..b16c5dbb96 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReduceDataset.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ReduceDataset" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReduceJoin.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReduceJoin.pbtxt new file mode 100644 index 0000000000..7919322201 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReduceJoin.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReduceJoin" + endpoint { + name: "strings.ReduceJoin" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RefEnter.pbtxt b/tensorflow/core/api_def/java_api/api_def_RefEnter.pbtxt new file mode 100644 index 0000000000..9cd2281bc6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RefEnter.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RefEnter" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RefExit.pbtxt b/tensorflow/core/api_def/java_api/api_def_RefExit.pbtxt new file mode 100644 index 0000000000..67e8d39c9a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RefExit.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RefExit" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RefIdentity.pbtxt b/tensorflow/core/api_def/java_api/api_def_RefIdentity.pbtxt new file mode 100644 index 0000000000..53483bd1bb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RefIdentity.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RefIdentity" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RefMerge.pbtxt b/tensorflow/core/api_def/java_api/api_def_RefMerge.pbtxt new file mode 100644 index 0000000000..6ea3145841 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RefMerge.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RefMerge" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RefNextIteration.pbtxt b/tensorflow/core/api_def/java_api/api_def_RefNextIteration.pbtxt new file mode 100644 index 0000000000..5d008204b7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RefNextIteration.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RefNextIteration" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RefSelect.pbtxt b/tensorflow/core/api_def/java_api/api_def_RefSelect.pbtxt new file mode 100644 index 0000000000..d7cda2d5b3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RefSelect.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RefSelect" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RefSwitch.pbtxt b/tensorflow/core/api_def/java_api/api_def_RefSwitch.pbtxt new file mode 100644 index 0000000000..78261d8b7e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RefSwitch.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RefSwitch" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RegexFullMatch.pbtxt b/tensorflow/core/api_def/java_api/api_def_RegexFullMatch.pbtxt new file mode 100644 index 0000000000..7f88e24eac --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RegexFullMatch.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RegexFullMatch" + endpoint { + name: "strings.RegexFullMatch" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RegexReplace.pbtxt b/tensorflow/core/api_def/java_api/api_def_RegexReplace.pbtxt new file mode 100644 index 0000000000..01c9e93cab --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RegexReplace.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RegexReplace" + endpoint { + name: "strings.RegexReplace" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Relu.pbtxt b/tensorflow/core/api_def/java_api/api_def_Relu.pbtxt new file mode 100644 index 0000000000..39d7fec452 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Relu.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Relu" + endpoint { + name: "nn.Relu" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Relu6.pbtxt b/tensorflow/core/api_def/java_api/api_def_Relu6.pbtxt new file mode 100644 index 0000000000..fcc012b503 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Relu6.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Relu6" + endpoint { + name: "nn.Relu6" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Relu6Grad.pbtxt b/tensorflow/core/api_def/java_api/api_def_Relu6Grad.pbtxt new file mode 100644 index 0000000000..33e959cc7b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Relu6Grad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Relu6Grad" + endpoint { + name: "nn.Relu6Grad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReluGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReluGrad.pbtxt new file mode 100644 index 0000000000..ec4a8b5f97 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReluGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReluGrad" + endpoint { + name: "nn.ReluGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RemoteCall.pbtxt b/tensorflow/core/api_def/java_api/api_def_RemoteCall.pbtxt new file mode 100644 index 0000000000..a0ddb01784 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RemoteCall.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RemoteCall" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RemoteFusedGraphExecute.pbtxt b/tensorflow/core/api_def/java_api/api_def_RemoteFusedGraphExecute.pbtxt new file mode 100644 index 0000000000..b73e633ef2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RemoteFusedGraphExecute.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "RemoteFusedGraphExecute" +} diff --git a/tensorflow/core/api_def/java_api/api_def_RepeatDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_RepeatDataset.pbtxt new file mode 100644 index 0000000000..871824f886 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RepeatDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RepeatDataset" + endpoint { + name: "data.RepeatDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RequantizationRange.pbtxt b/tensorflow/core/api_def/java_api/api_def_RequantizationRange.pbtxt new file mode 100644 index 0000000000..d365e89925 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RequantizationRange.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RequantizationRange" + endpoint { + name: "quantization.RequantizationRange" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Requantize.pbtxt b/tensorflow/core/api_def/java_api/api_def_Requantize.pbtxt new file mode 100644 index 0000000000..d397cde4db --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Requantize.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Requantize" + endpoint { + name: "quantization.Requantize" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Reshape.pbtxt b/tensorflow/core/api_def/java_api/api_def_Reshape.pbtxt new file mode 100644 index 0000000000..4bf3a409d1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Reshape.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Reshape" + endpoint { + name: "Reshape" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResizeArea.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResizeArea.pbtxt new file mode 100644 index 0000000000..5358c18d4b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResizeArea.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResizeArea" + endpoint { + name: "image.ResizeArea" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResizeBicubic.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResizeBicubic.pbtxt new file mode 100644 index 0000000000..0d0942e266 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResizeBicubic.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResizeBicubic" + endpoint { + name: "image.ResizeBicubic" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResizeBicubicGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResizeBicubicGrad.pbtxt new file mode 100644 index 0000000000..12e61dc823 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResizeBicubicGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResizeBicubicGrad" + endpoint { + name: "image.ResizeBicubicGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResizeBilinear.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResizeBilinear.pbtxt new file mode 100644 index 0000000000..ad123744a9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResizeBilinear.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResizeBilinear" + endpoint { + name: "image.ResizeBilinear" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResizeBilinearGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResizeBilinearGrad.pbtxt new file mode 100644 index 0000000000..04f3e9f19e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResizeBilinearGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResizeBilinearGrad" + endpoint { + name: "image.ResizeBilinearGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResizeNearestNeighbor.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResizeNearestNeighbor.pbtxt new file mode 100644 index 0000000000..86ad39a517 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResizeNearestNeighbor.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResizeNearestNeighbor" + endpoint { + name: "image.ResizeNearestNeighbor" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResizeNearestNeighborGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResizeNearestNeighborGrad.pbtxt new file mode 100644 index 0000000000..70eeb906fa --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResizeNearestNeighborGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResizeNearestNeighborGrad" + endpoint { + name: "image.ResizeNearestNeighborGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdaMax.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdaMax.pbtxt new file mode 100644 index 0000000000..ff57bd5849 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdaMax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyAdaMax" + endpoint { + name: "train.ResourceApplyAdaMax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdadelta.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdadelta.pbtxt new file mode 100644 index 0000000000..d4369f0ead --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdadelta.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyAdadelta" + endpoint { + name: "train.ResourceApplyAdadelta" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagrad.pbtxt new file mode 100644 index 0000000000..9bf7c20ee7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyAdagrad" + endpoint { + name: "train.ResourceApplyAdagrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt new file mode 100644 index 0000000000..904e434b8a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyAdagradDA" + endpoint { + name: "train.ResourceApplyAdagradDA" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdam.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdam.pbtxt new file mode 100644 index 0000000000..390bd999c4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdam.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyAdam" + endpoint { + name: "train.ResourceApplyAdam" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyAddSign.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAddSign.pbtxt new file mode 100644 index 0000000000..bf944477be --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAddSign.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyAddSign" + endpoint { + name: "train.ResourceApplyAddSign" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt new file mode 100644 index 0000000000..58027823e0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyCenteredRMSProp" + endpoint { + name: "train.ResourceApplyCenteredRMSProp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt new file mode 100644 index 0000000000..db64e86fd4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyFtrl" + endpoint { + name: "train.ResourceApplyFtrl" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt new file mode 100644 index 0000000000..547041e649 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyFtrlV2" + endpoint { + name: "train.ResourceApplyFtrlV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyGradientDescent.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyGradientDescent.pbtxt new file mode 100644 index 0000000000..a54fed14d1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyGradientDescent.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyGradientDescent" + endpoint { + name: "train.ResourceApplyGradientDescent" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyMomentum.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyMomentum.pbtxt new file mode 100644 index 0000000000..debb0a8131 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyMomentum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyMomentum" + endpoint { + name: "train.ResourceApplyMomentum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyPowerSign.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyPowerSign.pbtxt new file mode 100644 index 0000000000..96df22c81f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyPowerSign.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyPowerSign" + endpoint { + name: "train.ResourceApplyPowerSign" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyProximalAdagrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyProximalAdagrad.pbtxt new file mode 100644 index 0000000000..809b8b3af3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyProximalAdagrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyProximalAdagrad" + endpoint { + name: "train.ResourceApplyProximalAdagrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyProximalGradientDescent.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyProximalGradientDescent.pbtxt new file mode 100644 index 0000000000..c9ff5a499d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyProximalGradientDescent.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyProximalGradientDescent" + endpoint { + name: "train.ResourceApplyProximalGradientDescent" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt new file mode 100644 index 0000000000..74a3d77531 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceApplyRMSProp" + endpoint { + name: "train.ResourceApplyRMSProp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceCountUpTo.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceCountUpTo.pbtxt new file mode 100644 index 0000000000..439c1f1755 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceCountUpTo.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceCountUpTo" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceGather.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceGather.pbtxt new file mode 100644 index 0000000000..79c6e8abbc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceGather.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceGather" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceScatterAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceScatterAdd.pbtxt new file mode 100644 index 0000000000..e4184e33bf --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceScatterAdd.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceScatterAdd" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceScatterDiv.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceScatterDiv.pbtxt new file mode 100644 index 0000000000..3e21c24a58 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceScatterDiv.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceScatterDiv" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceScatterMax.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceScatterMax.pbtxt new file mode 100644 index 0000000000..d25b14272d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceScatterMax.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceScatterMax" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceScatterMin.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceScatterMin.pbtxt new file mode 100644 index 0000000000..6243cc1ae3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceScatterMin.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceScatterMin" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceScatterMul.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceScatterMul.pbtxt new file mode 100644 index 0000000000..393e5556c0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceScatterMul.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceScatterMul" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceScatterNdAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceScatterNdAdd.pbtxt new file mode 100644 index 0000000000..2fd38f7be8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceScatterNdAdd.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceScatterNdAdd" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceScatterNdUpdate.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceScatterNdUpdate.pbtxt new file mode 100644 index 0000000000..732de5f1cc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceScatterNdUpdate.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceScatterNdUpdate" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceScatterSub.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceScatterSub.pbtxt new file mode 100644 index 0000000000..77081dda4d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceScatterSub.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceScatterSub" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceScatterUpdate.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceScatterUpdate.pbtxt new file mode 100644 index 0000000000..9c2cc0ec21 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceScatterUpdate.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceScatterUpdate" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdadelta.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdadelta.pbtxt new file mode 100644 index 0000000000..c6e3ae2219 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdadelta.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyAdadelta" + endpoint { + name: "train.ResourceSparseApplyAdadelta" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagrad.pbtxt new file mode 100644 index 0000000000..5be4d6199b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyAdagrad" + endpoint { + name: "train.ResourceSparseApplyAdagrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt new file mode 100644 index 0000000000..bd66d64160 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyAdagradDA" + endpoint { + name: "train.ResourceSparseApplyAdagradDA" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyCenteredRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyCenteredRMSProp.pbtxt new file mode 100644 index 0000000000..afda4adb0d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyCenteredRMSProp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyCenteredRMSProp" + endpoint { + name: "train.ResourceSparseApplyCenteredRMSProp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt new file mode 100644 index 0000000000..195198fc9a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyFtrl" + endpoint { + name: "train.ResourceSparseApplyFtrl" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt new file mode 100644 index 0000000000..49c6d34dcc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyFtrlV2" + endpoint { + name: "train.ResourceSparseApplyFtrlV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyMomentum.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyMomentum.pbtxt new file mode 100644 index 0000000000..7e00039e01 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyMomentum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyMomentum" + endpoint { + name: "train.ResourceSparseApplyMomentum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyProximalAdagrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyProximalAdagrad.pbtxt new file mode 100644 index 0000000000..04fe8504e5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyProximalAdagrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyProximalAdagrad" + endpoint { + name: "train.ResourceSparseApplyProximalAdagrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyProximalGradientDescent.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyProximalGradientDescent.pbtxt new file mode 100644 index 0000000000..27df43c9c5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyProximalGradientDescent.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyProximalGradientDescent" + endpoint { + name: "train.ResourceSparseApplyProximalGradientDescent" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyRMSProp.pbtxt new file mode 100644 index 0000000000..3e78f6f06d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyRMSProp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ResourceSparseApplyRMSProp" + endpoint { + name: "train.ResourceSparseApplyRMSProp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceStridedSliceAssign.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceStridedSliceAssign.pbtxt new file mode 100644 index 0000000000..83805389b9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ResourceStridedSliceAssign.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ResourceStridedSliceAssign" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Restore.pbtxt b/tensorflow/core/api_def/java_api/api_def_Restore.pbtxt new file mode 100644 index 0000000000..ca79fc10db --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Restore.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Restore" + endpoint { + name: "train.Restore" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RestoreSlice.pbtxt b/tensorflow/core/api_def/java_api/api_def_RestoreSlice.pbtxt new file mode 100644 index 0000000000..0728f5908b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RestoreSlice.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RestoreSlice" + endpoint { + name: "train.RestoreSlice" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt new file mode 100644 index 0000000000..e877ff9869 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RestoreV2" + endpoint { + name: "train.RestoreV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt b/tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt new file mode 100644 index 0000000000..2bd25417aa --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Reverse" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReverseSequence.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReverseSequence.pbtxt new file mode 100644 index 0000000000..87638c0dcc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReverseSequence.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ReverseSequence" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ReverseV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReverseV2.pbtxt new file mode 100644 index 0000000000..71efbe1892 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ReverseV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ReverseV2" + endpoint { + name: "Reverse" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RightShift.pbtxt b/tensorflow/core/api_def/java_api/api_def_RightShift.pbtxt new file mode 100644 index 0000000000..68fab3e8cf --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RightShift.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RightShift" + endpoint { + name: "bitwise.RightShift" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Rint.pbtxt b/tensorflow/core/api_def/java_api/api_def_Rint.pbtxt new file mode 100644 index 0000000000..48fbcc7c34 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Rint.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Rint" + endpoint { + name: "math.Rint" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Roll.pbtxt b/tensorflow/core/api_def/java_api/api_def_Roll.pbtxt new file mode 100644 index 0000000000..50f7915a65 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Roll.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Roll" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Round.pbtxt b/tensorflow/core/api_def/java_api/api_def_Round.pbtxt new file mode 100644 index 0000000000..dd612a33d6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Round.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Round" + endpoint { + name: "math.Round" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Rpc.pbtxt b/tensorflow/core/api_def/java_api/api_def_Rpc.pbtxt new file mode 100644 index 0000000000..0d1e2b90e6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Rpc.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Rpc" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Rsqrt.pbtxt b/tensorflow/core/api_def/java_api/api_def_Rsqrt.pbtxt new file mode 100644 index 0000000000..06b1b81ecd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Rsqrt.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Rsqrt" + endpoint { + name: "math.Rsqrt" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_RsqrtGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_RsqrtGrad.pbtxt new file mode 100644 index 0000000000..88073b6f25 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_RsqrtGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "RsqrtGrad" + endpoint { + name: "math.RsqrtGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBox.pbtxt b/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBox.pbtxt new file mode 100644 index 0000000000..e7c1c90ea6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBox.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SampleDistortedBoundingBox" + endpoint { + name: "image.SampleDistortedBoundingBox" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt new file mode 100644 index 0000000000..8656977bf6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SampleDistortedBoundingBoxV2" + endpoint { + name: "image.SampleDistortedBoundingBoxV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Save.pbtxt b/tensorflow/core/api_def/java_api/api_def_Save.pbtxt new file mode 100644 index 0000000000..87dab6dc1f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Save.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Save" + endpoint { + name: "train.Save" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SaveSlices.pbtxt b/tensorflow/core/api_def/java_api/api_def_SaveSlices.pbtxt new file mode 100644 index 0000000000..b336035680 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SaveSlices.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SaveSlices" + endpoint { + name: "train.SaveSlices" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt new file mode 100644 index 0000000000..6417252f45 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SaveV2" + endpoint { + name: "train.SaveV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScalarSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScalarSummary.pbtxt new file mode 100644 index 0000000000..c339ce0a7a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScalarSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ScalarSummary" + endpoint { + name: "summary.ScalarSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScanDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScanDataset.pbtxt new file mode 100644 index 0000000000..89b63c53f7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScanDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ScanDataset" + endpoint { + name: "data.ScanDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterAdd.pbtxt new file mode 100644 index 0000000000..41c63dc0a4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterAdd.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterAdd" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterDiv.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterDiv.pbtxt new file mode 100644 index 0000000000..5754249eaf --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterDiv.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterDiv" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterMax.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterMax.pbtxt new file mode 100644 index 0000000000..aa6375cbd7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterMax.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterMax" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterMin.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterMin.pbtxt new file mode 100644 index 0000000000..ea007120c3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterMin.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterMin" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterMul.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterMul.pbtxt new file mode 100644 index 0000000000..f1d91258e4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterMul.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterMul" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterNd.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterNd.pbtxt new file mode 100644 index 0000000000..8ef01b2fca --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterNd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ScatterNd" + endpoint { + name: "ScatterNd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterNdAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterNdAdd.pbtxt new file mode 100644 index 0000000000..bea152a9da --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterNdAdd.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterNdAdd" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterNdNonAliasingAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterNdNonAliasingAdd.pbtxt new file mode 100644 index 0000000000..4dd756bfc0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterNdNonAliasingAdd.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterNdNonAliasingAdd" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterNdSub.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterNdSub.pbtxt new file mode 100644 index 0000000000..384e79d64e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterNdSub.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterNdSub" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterNdUpdate.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterNdUpdate.pbtxt new file mode 100644 index 0000000000..92fce7f0ac --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterNdUpdate.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterNdUpdate" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterSub.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterSub.pbtxt new file mode 100644 index 0000000000..5baaa4f604 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterSub.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterSub" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ScatterUpdate.pbtxt b/tensorflow/core/api_def/java_api/api_def_ScatterUpdate.pbtxt new file mode 100644 index 0000000000..83ac128ed6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ScatterUpdate.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ScatterUpdate" +} diff --git a/tensorflow/core/api_def/java_api/api_def_SdcaFprint.pbtxt b/tensorflow/core/api_def/java_api/api_def_SdcaFprint.pbtxt new file mode 100644 index 0000000000..ce179918cd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SdcaFprint.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SdcaFprint" + endpoint { + name: "train.SdcaFprint" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SdcaOptimizer.pbtxt b/tensorflow/core/api_def/java_api/api_def_SdcaOptimizer.pbtxt new file mode 100644 index 0000000000..68eb8cf1f0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SdcaOptimizer.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SdcaOptimizer" + endpoint { + name: "train.SdcaOptimizer" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt new file mode 100644 index 0000000000..4e90531060 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SdcaOptimizerV2" + endpoint { + name: "train.SdcaOptimizerV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SdcaShrinkL1.pbtxt b/tensorflow/core/api_def/java_api/api_def_SdcaShrinkL1.pbtxt new file mode 100644 index 0000000000..83993bcf14 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SdcaShrinkL1.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SdcaShrinkL1" + endpoint { + name: "train.SdcaShrinkL1" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SegmentMax.pbtxt b/tensorflow/core/api_def/java_api/api_def_SegmentMax.pbtxt new file mode 100644 index 0000000000..6ac26c9e9e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SegmentMax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SegmentMax" + endpoint { + name: "math.SegmentMax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SegmentMean.pbtxt b/tensorflow/core/api_def/java_api/api_def_SegmentMean.pbtxt new file mode 100644 index 0000000000..982db87bf0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SegmentMean.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SegmentMean" + endpoint { + name: "math.SegmentMean" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SegmentMin.pbtxt b/tensorflow/core/api_def/java_api/api_def_SegmentMin.pbtxt new file mode 100644 index 0000000000..7a403b6c63 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SegmentMin.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SegmentMin" + endpoint { + name: "math.SegmentMin" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SegmentProd.pbtxt b/tensorflow/core/api_def/java_api/api_def_SegmentProd.pbtxt new file mode 100644 index 0000000000..1bf280edc4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SegmentProd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SegmentProd" + endpoint { + name: "math.SegmentProd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SegmentSum.pbtxt b/tensorflow/core/api_def/java_api/api_def_SegmentSum.pbtxt new file mode 100644 index 0000000000..3dcbc35225 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SegmentSum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SegmentSum" + endpoint { + name: "math.SegmentSum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Select.pbtxt b/tensorflow/core/api_def/java_api/api_def_Select.pbtxt new file mode 100644 index 0000000000..eeff79284c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Select.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Select" +} diff --git a/tensorflow/core/api_def/java_api/api_def_SelfAdjointEig.pbtxt b/tensorflow/core/api_def/java_api/api_def_SelfAdjointEig.pbtxt new file mode 100644 index 0000000000..552d397ad8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SelfAdjointEig.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SelfAdjointEig" + endpoint { + name: "linalg.SelfAdjointEig" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt new file mode 100644 index 0000000000..4b610f437c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SelfAdjointEigV2" + endpoint { + name: "linalg.SelfAdjointEigV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Selu.pbtxt b/tensorflow/core/api_def/java_api/api_def_Selu.pbtxt new file mode 100644 index 0000000000..7002d5be12 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Selu.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Selu" + endpoint { + name: "nn.Selu" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SeluGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SeluGrad.pbtxt new file mode 100644 index 0000000000..b34e2f2239 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SeluGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SeluGrad" + endpoint { + name: "nn.SeluGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SerializeIterator.pbtxt b/tensorflow/core/api_def/java_api/api_def_SerializeIterator.pbtxt new file mode 100644 index 0000000000..37789c753b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SerializeIterator.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SerializeIterator" + endpoint { + name: "data.SerializeIterator" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SerializeManySparse.pbtxt b/tensorflow/core/api_def/java_api/api_def_SerializeManySparse.pbtxt new file mode 100644 index 0000000000..567a8e4b7f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SerializeManySparse.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SerializeManySparse" + endpoint { + name: "io.SerializeManySparse" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SerializeSparse.pbtxt b/tensorflow/core/api_def/java_api/api_def_SerializeSparse.pbtxt new file mode 100644 index 0000000000..ad86c7095c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SerializeSparse.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SerializeSparse" + endpoint { + name: "io.SerializeSparse" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SerializeTensor.pbtxt b/tensorflow/core/api_def/java_api/api_def_SerializeTensor.pbtxt new file mode 100644 index 0000000000..169120a063 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SerializeTensor.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SerializeTensor" + endpoint { + name: "io.SerializeTensor" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SetSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_SetSize.pbtxt new file mode 100644 index 0000000000..1c000e9c8a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SetSize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "SetSize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_SetStatsAggregatorDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_SetStatsAggregatorDataset.pbtxt new file mode 100644 index 0000000000..f57abe5a66 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SetStatsAggregatorDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SetStatsAggregatorDataset" + endpoint { + name: "data.SetStatsAggregatorDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Shape.pbtxt b/tensorflow/core/api_def/java_api/api_def_Shape.pbtxt new file mode 100644 index 0000000000..5074000b53 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Shape.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Shape" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ShapeN.pbtxt b/tensorflow/core/api_def/java_api/api_def_ShapeN.pbtxt new file mode 100644 index 0000000000..b4bfb91118 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ShapeN.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ShapeN" +} diff --git a/tensorflow/core/api_def/java_api/api_def_ShardedFilename.pbtxt b/tensorflow/core/api_def/java_api/api_def_ShardedFilename.pbtxt new file mode 100644 index 0000000000..8efd0afb8b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ShardedFilename.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ShardedFilename" + endpoint { + name: "io.ShardedFilename" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ShardedFilespec.pbtxt b/tensorflow/core/api_def/java_api/api_def_ShardedFilespec.pbtxt new file mode 100644 index 0000000000..e31cac1040 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ShardedFilespec.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ShardedFilespec" + endpoint { + name: "io.ShardedFilespec" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ShuffleAndRepeatDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ShuffleAndRepeatDataset.pbtxt new file mode 100644 index 0000000000..543d5a109c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ShuffleAndRepeatDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ShuffleAndRepeatDataset" + endpoint { + name: "data.ShuffleAndRepeatDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ShuffleDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ShuffleDataset.pbtxt new file mode 100644 index 0000000000..36f4979c96 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ShuffleDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ShuffleDataset" + endpoint { + name: "data.ShuffleDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Sigmoid.pbtxt b/tensorflow/core/api_def/java_api/api_def_Sigmoid.pbtxt new file mode 100644 index 0000000000..b6e16a4110 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Sigmoid.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Sigmoid" + endpoint { + name: "math.Sigmoid" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SigmoidGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SigmoidGrad.pbtxt new file mode 100644 index 0000000000..bb141abe3b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SigmoidGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SigmoidGrad" + endpoint { + name: "math.SigmoidGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Sign.pbtxt b/tensorflow/core/api_def/java_api/api_def_Sign.pbtxt new file mode 100644 index 0000000000..435fb9e825 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Sign.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Sign" + endpoint { + name: "math.Sign" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Sin.pbtxt b/tensorflow/core/api_def/java_api/api_def_Sin.pbtxt new file mode 100644 index 0000000000..2fc95755ba --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Sin.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Sin" + endpoint { + name: "math.Sin" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Sinh.pbtxt b/tensorflow/core/api_def/java_api/api_def_Sinh.pbtxt new file mode 100644 index 0000000000..f343685e80 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Sinh.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Sinh" + endpoint { + name: "math.Sinh" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Size.pbtxt b/tensorflow/core/api_def/java_api/api_def_Size.pbtxt new file mode 100644 index 0000000000..a41cddd8ac --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Size.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Size" +} diff --git a/tensorflow/core/api_def/java_api/api_def_SkipDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_SkipDataset.pbtxt new file mode 100644 index 0000000000..39bce67a3e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SkipDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SkipDataset" + endpoint { + name: "data.SkipDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Skipgram.pbtxt b/tensorflow/core/api_def/java_api/api_def_Skipgram.pbtxt new file mode 100644 index 0000000000..d095c7b61b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Skipgram.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Skipgram" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Slice.pbtxt b/tensorflow/core/api_def/java_api/api_def_Slice.pbtxt new file mode 100644 index 0000000000..adfe6fa4fd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Slice.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Slice" +} diff --git a/tensorflow/core/api_def/java_api/api_def_SlideDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_SlideDataset.pbtxt new file mode 100644 index 0000000000..bc284c2833 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SlideDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SlideDataset" + endpoint { + name: "data.SlideDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Snapshot.pbtxt b/tensorflow/core/api_def/java_api/api_def_Snapshot.pbtxt new file mode 100644 index 0000000000..6e49c1a543 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Snapshot.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Snapshot" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Softmax.pbtxt b/tensorflow/core/api_def/java_api/api_def_Softmax.pbtxt new file mode 100644 index 0000000000..cb27a04d21 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Softmax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Softmax" + endpoint { + name: "nn.Softmax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SoftmaxCrossEntropyWithLogits.pbtxt b/tensorflow/core/api_def/java_api/api_def_SoftmaxCrossEntropyWithLogits.pbtxt new file mode 100644 index 0000000000..e064562c0f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SoftmaxCrossEntropyWithLogits.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SoftmaxCrossEntropyWithLogits" + endpoint { + name: "nn.SoftmaxCrossEntropyWithLogits" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Softplus.pbtxt b/tensorflow/core/api_def/java_api/api_def_Softplus.pbtxt new file mode 100644 index 0000000000..671656c287 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Softplus.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Softplus" + endpoint { + name: "math.Softplus" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SoftplusGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SoftplusGrad.pbtxt new file mode 100644 index 0000000000..d1b074a9b7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SoftplusGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SoftplusGrad" + endpoint { + name: "math.SoftplusGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Softsign.pbtxt b/tensorflow/core/api_def/java_api/api_def_Softsign.pbtxt new file mode 100644 index 0000000000..23aa1e3c58 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Softsign.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Softsign" + endpoint { + name: "nn.Softsign" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SoftsignGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SoftsignGrad.pbtxt new file mode 100644 index 0000000000..73faf74511 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SoftsignGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SoftsignGrad" + endpoint { + name: "nn.SoftsignGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SpaceToBatch.pbtxt b/tensorflow/core/api_def/java_api/api_def_SpaceToBatch.pbtxt new file mode 100644 index 0000000000..4fe7232e54 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SpaceToBatch.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SpaceToBatch" + endpoint { + name: "nn.SpaceToBatch" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SpaceToBatchND.pbtxt b/tensorflow/core/api_def/java_api/api_def_SpaceToBatchND.pbtxt new file mode 100644 index 0000000000..6612b48286 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SpaceToBatchND.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SpaceToBatchND" + endpoint { + name: "SpaceToBatchNd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SpaceToDepth.pbtxt b/tensorflow/core/api_def/java_api/api_def_SpaceToDepth.pbtxt new file mode 100644 index 0000000000..cb421c75db --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SpaceToDepth.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SpaceToDepth" + endpoint { + name: "nn.SpaceToDepth" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseAccumulatorApplyGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseAccumulatorApplyGradient.pbtxt new file mode 100644 index 0000000000..cdb0b14b67 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseAccumulatorApplyGradient.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseAccumulatorApplyGradient" + endpoint { + name: "sparse.SparseAccumulatorApplyGradient" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseAccumulatorTakeGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseAccumulatorTakeGradient.pbtxt new file mode 100644 index 0000000000..8fc1e70959 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseAccumulatorTakeGradient.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseAccumulatorTakeGradient" + endpoint { + name: "sparse.SparseAccumulatorTakeGradient" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseAdd.pbtxt new file mode 100644 index 0000000000..0761f2ed16 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseAdd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseAdd" + endpoint { + name: "sparse.SparseAdd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseAddGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseAddGrad.pbtxt new file mode 100644 index 0000000000..6529c46a17 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseAddGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseAddGrad" + endpoint { + name: "sparse.SparseAddGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyAdadelta.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyAdadelta.pbtxt new file mode 100644 index 0000000000..7122f210a4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyAdadelta.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyAdadelta" + endpoint { + name: "train.SparseApplyAdadelta" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagrad.pbtxt new file mode 100644 index 0000000000..184a8cfb2f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyAdagrad" + endpoint { + name: "train.SparseApplyAdagrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt new file mode 100644 index 0000000000..56d9b1c49b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyAdagradDA" + endpoint { + name: "train.SparseApplyAdagradDA" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyCenteredRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyCenteredRMSProp.pbtxt new file mode 100644 index 0000000000..fa35db29b0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyCenteredRMSProp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyCenteredRMSProp" + endpoint { + name: "train.SparseApplyCenteredRMSProp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt new file mode 100644 index 0000000000..bb669aa773 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyFtrl" + endpoint { + name: "train.SparseApplyFtrl" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt new file mode 100644 index 0000000000..673f71c34b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyFtrlV2" + endpoint { + name: "train.SparseApplyFtrlV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyMomentum.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyMomentum.pbtxt new file mode 100644 index 0000000000..f7e79c5e7e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyMomentum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyMomentum" + endpoint { + name: "train.SparseApplyMomentum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyProximalAdagrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyProximalAdagrad.pbtxt new file mode 100644 index 0000000000..8ac6cf771c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyProximalAdagrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyProximalAdagrad" + endpoint { + name: "train.SparseApplyProximalAdagrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyProximalGradientDescent.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyProximalGradientDescent.pbtxt new file mode 100644 index 0000000000..926ed2c1d4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyProximalGradientDescent.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyProximalGradientDescent" + endpoint { + name: "train.SparseApplyProximalGradientDescent" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt new file mode 100644 index 0000000000..94646093af --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseApplyRMSProp" + endpoint { + name: "train.SparseApplyRMSProp" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseConcat.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseConcat.pbtxt new file mode 100644 index 0000000000..8ceb600a42 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseConcat.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseConcat" + endpoint { + name: "sparse.SparseConcat" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseConditionalAccumulator.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseConditionalAccumulator.pbtxt new file mode 100644 index 0000000000..3dc2c1ea8a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseConditionalAccumulator.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseConditionalAccumulator" + endpoint { + name: "sparse.SparseConditionalAccumulator" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseCross.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseCross.pbtxt new file mode 100644 index 0000000000..130f333d35 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseCross.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseCross" + endpoint { + name: "sparse.SparseCross" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseAdd.pbtxt new file mode 100644 index 0000000000..013b7eede9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseAdd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseDenseCwiseAdd" + endpoint { + name: "sparse.SparseDenseCwiseAdd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseDiv.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseDiv.pbtxt new file mode 100644 index 0000000000..8cf56d7b41 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseDiv.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseDenseCwiseDiv" + endpoint { + name: "sparse.SparseDenseCwiseDiv" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseMul.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseMul.pbtxt new file mode 100644 index 0000000000..37c50f2327 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseDenseCwiseMul.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseDenseCwiseMul" + endpoint { + name: "sparse.SparseDenseCwiseMul" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseFillEmptyRows.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseFillEmptyRows.pbtxt new file mode 100644 index 0000000000..3adddbd34b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseFillEmptyRows.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseFillEmptyRows" + endpoint { + name: "sparse.SparseFillEmptyRows" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseFillEmptyRowsGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseFillEmptyRowsGrad.pbtxt new file mode 100644 index 0000000000..708069d028 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseFillEmptyRowsGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseFillEmptyRowsGrad" + endpoint { + name: "sparse.SparseFillEmptyRowsGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseMatMul.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseMatMul.pbtxt new file mode 100644 index 0000000000..445d53b023 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseMatMul.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseMatMul" + endpoint { + name: "sparse.SparseMatMul" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseReduceMax.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseReduceMax.pbtxt new file mode 100644 index 0000000000..a7467b9b47 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseReduceMax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseReduceMax" + endpoint { + name: "sparse.SparseReduceMax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseReduceMaxSparse.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseReduceMaxSparse.pbtxt new file mode 100644 index 0000000000..987e98467e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseReduceMaxSparse.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseReduceMaxSparse" + endpoint { + name: "sparse.SparseReduceMaxSparse" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseReduceSum.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseReduceSum.pbtxt new file mode 100644 index 0000000000..739fb5fb95 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseReduceSum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseReduceSum" + endpoint { + name: "sparse.SparseReduceSum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseReduceSumSparse.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseReduceSumSparse.pbtxt new file mode 100644 index 0000000000..64d6d45f1a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseReduceSumSparse.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseReduceSumSparse" + endpoint { + name: "sparse.SparseReduceSumSparse" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseReorder.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseReorder.pbtxt new file mode 100644 index 0000000000..202066e76f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseReorder.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseReorder" + endpoint { + name: "sparse.SparseReorder" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseReshape.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseReshape.pbtxt new file mode 100644 index 0000000000..0a393a6105 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseReshape.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseReshape" + endpoint { + name: "sparse.SparseReshape" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSegmentMean.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSegmentMean.pbtxt new file mode 100644 index 0000000000..9187dbed67 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSegmentMean.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSegmentMean" + endpoint { + name: "sparse.SparseSegmentMean" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSegmentMeanGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSegmentMeanGrad.pbtxt new file mode 100644 index 0000000000..1b7d5bbcf0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSegmentMeanGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSegmentMeanGrad" + endpoint { + name: "sparse.SparseSegmentMeanGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSegmentMeanWithNumSegments.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSegmentMeanWithNumSegments.pbtxt new file mode 100644 index 0000000000..bb3ac2256d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSegmentMeanWithNumSegments.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSegmentMeanWithNumSegments" + endpoint { + name: "sparse.SparseSegmentMeanWithNumSegments" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtN.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtN.pbtxt new file mode 100644 index 0000000000..2cecff503f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtN.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSegmentSqrtN" + endpoint { + name: "sparse.SparseSegmentSqrtN" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtNGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtNGrad.pbtxt new file mode 100644 index 0000000000..e6973eb773 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtNGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSegmentSqrtNGrad" + endpoint { + name: "sparse.SparseSegmentSqrtNGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtNWithNumSegments.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtNWithNumSegments.pbtxt new file mode 100644 index 0000000000..78aed85f0a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSqrtNWithNumSegments.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSegmentSqrtNWithNumSegments" + endpoint { + name: "sparse.SparseSegmentSqrtNWithNumSegments" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSegmentSum.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSum.pbtxt new file mode 100644 index 0000000000..f18f351667 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSegmentSum" + endpoint { + name: "sparse.SparseSegmentSum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSegmentSumWithNumSegments.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSumWithNumSegments.pbtxt new file mode 100644 index 0000000000..8e384857cc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSegmentSumWithNumSegments.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSegmentSumWithNumSegments" + endpoint { + name: "sparse.SparseSegmentSumWithNumSegments" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSlice.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSlice.pbtxt new file mode 100644 index 0000000000..1d794df925 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSlice.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSlice" + endpoint { + name: "sparse.SparseSlice" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSliceGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSliceGrad.pbtxt new file mode 100644 index 0000000000..979326c0fc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSliceGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSliceGrad" + endpoint { + name: "sparse.SparseSliceGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSoftmax.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSoftmax.pbtxt new file mode 100644 index 0000000000..56c96640cb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSoftmax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSoftmax" + endpoint { + name: "sparse.SparseSoftmax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSoftmaxCrossEntropyWithLogits.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSoftmaxCrossEntropyWithLogits.pbtxt new file mode 100644 index 0000000000..7627d5f607 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSoftmaxCrossEntropyWithLogits.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSoftmaxCrossEntropyWithLogits" + endpoint { + name: "nn.SparseSoftmaxCrossEntropyWithLogits" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSparseMaximum.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSparseMaximum.pbtxt new file mode 100644 index 0000000000..3143096213 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSparseMaximum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSparseMaximum" + endpoint { + name: "sparse.SparseSparseMaximum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSparseMinimum.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSparseMinimum.pbtxt new file mode 100644 index 0000000000..fc04bb4fed --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSparseMinimum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSparseMinimum" + endpoint { + name: "sparse.SparseSparseMinimum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseSplit.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseSplit.pbtxt new file mode 100644 index 0000000000..0afc95199a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseSplit.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseSplit" + endpoint { + name: "sparse.SparseSplit" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseTensorDenseAdd.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseTensorDenseAdd.pbtxt new file mode 100644 index 0000000000..fc5c882f83 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseTensorDenseAdd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseTensorDenseAdd" + endpoint { + name: "sparse.SparseTensorDenseAdd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseTensorDenseMatMul.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseTensorDenseMatMul.pbtxt new file mode 100644 index 0000000000..cd1f1e09e9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseTensorDenseMatMul.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseTensorDenseMatMul" + endpoint { + name: "sparse.SparseTensorDenseMatMul" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseTensorSliceDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseTensorSliceDataset.pbtxt new file mode 100644 index 0000000000..bb0d1d7a94 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseTensorSliceDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseTensorSliceDataset" + endpoint { + name: "data.SparseTensorSliceDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseToDense.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseToDense.pbtxt new file mode 100644 index 0000000000..68df155e46 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseToDense.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseToDense" + endpoint { + name: "sparse.SparseToDense" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SparseToSparseSetOperation.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseToSparseSetOperation.pbtxt new file mode 100644 index 0000000000..fb04366fea --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SparseToSparseSetOperation.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SparseToSparseSetOperation" + endpoint { + name: "sparse.SparseToSparseSetOperation" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Split.pbtxt b/tensorflow/core/api_def/java_api/api_def_Split.pbtxt new file mode 100644 index 0000000000..ffb7b52e09 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Split.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Split" +} diff --git a/tensorflow/core/api_def/java_api/api_def_SplitV.pbtxt b/tensorflow/core/api_def/java_api/api_def_SplitV.pbtxt new file mode 100644 index 0000000000..94f4a08d70 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SplitV.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "SplitV" +} diff --git a/tensorflow/core/api_def/java_api/api_def_SqlDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_SqlDataset.pbtxt new file mode 100644 index 0000000000..8764e81af2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SqlDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SqlDataset" + endpoint { + name: "data.SqlDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Sqrt.pbtxt b/tensorflow/core/api_def/java_api/api_def_Sqrt.pbtxt new file mode 100644 index 0000000000..daa2a1ee86 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Sqrt.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Sqrt" + endpoint { + name: "math.Sqrt" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SqrtGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_SqrtGrad.pbtxt new file mode 100644 index 0000000000..8eca1b89b3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SqrtGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SqrtGrad" + endpoint { + name: "math.SqrtGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Square.pbtxt b/tensorflow/core/api_def/java_api/api_def_Square.pbtxt new file mode 100644 index 0000000000..561e10e020 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Square.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Square" + endpoint { + name: "math.Square" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_SquaredDifference.pbtxt b/tensorflow/core/api_def/java_api/api_def_SquaredDifference.pbtxt new file mode 100644 index 0000000000..752dbcce7b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SquaredDifference.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SquaredDifference" + endpoint { + name: "math.SquaredDifference" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Squeeze.pbtxt b/tensorflow/core/api_def/java_api/api_def_Squeeze.pbtxt new file mode 100644 index 0000000000..264c384603 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Squeeze.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Squeeze" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Stack.pbtxt b/tensorflow/core/api_def/java_api/api_def_Stack.pbtxt new file mode 100644 index 0000000000..522e5efec5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Stack.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Stack" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt new file mode 100644 index 0000000000..1cba682de9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StackClose" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt new file mode 100644 index 0000000000..be5a0f535a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StackCloseV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt new file mode 100644 index 0000000000..4439e73843 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StackPop" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt new file mode 100644 index 0000000000..b8babb4c56 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StackPopV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt new file mode 100644 index 0000000000..41792e327f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StackPush" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt new file mode 100644 index 0000000000..4920152259 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StackPushV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt new file mode 100644 index 0000000000..5232e0425e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StackV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Stage.pbtxt b/tensorflow/core/api_def/java_api/api_def_Stage.pbtxt new file mode 100644 index 0000000000..87e0c7d981 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Stage.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Stage" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StageClear.pbtxt b/tensorflow/core/api_def/java_api/api_def_StageClear.pbtxt new file mode 100644 index 0000000000..26890a55b3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StageClear.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StageClear" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StagePeek.pbtxt b/tensorflow/core/api_def/java_api/api_def_StagePeek.pbtxt new file mode 100644 index 0000000000..7c3ed3dc91 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StagePeek.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StagePeek" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StageSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_StageSize.pbtxt new file mode 100644 index 0000000000..d8188c3e0b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StageSize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StageSize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatefulPartitionedCall.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatefulPartitionedCall.pbtxt new file mode 100644 index 0000000000..2e6decf19a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatefulPartitionedCall.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StatefulPartitionedCall" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatelessIf.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatelessIf.pbtxt new file mode 100644 index 0000000000..37c7b9a962 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatelessIf.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StatelessIf" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatelessMultinomial.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatelessMultinomial.pbtxt new file mode 100644 index 0000000000..8cfbbfb2c2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatelessMultinomial.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StatelessMultinomial" + endpoint { + name: "random.StatelessMultinomial" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatelessRandomNormal.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatelessRandomNormal.pbtxt new file mode 100644 index 0000000000..4e648cfa69 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatelessRandomNormal.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StatelessRandomNormal" + endpoint { + name: "random.StatelessRandomNormal" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatelessRandomUniform.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatelessRandomUniform.pbtxt new file mode 100644 index 0000000000..6f8f328b41 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatelessRandomUniform.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StatelessRandomUniform" + endpoint { + name: "random.StatelessRandomUniform" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatelessRandomUniformInt.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatelessRandomUniformInt.pbtxt new file mode 100644 index 0000000000..2fec4a7cc6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatelessRandomUniformInt.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StatelessRandomUniformInt" + endpoint { + name: "random.StatelessRandomUniformInt" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatelessTruncatedNormal.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatelessTruncatedNormal.pbtxt new file mode 100644 index 0000000000..c05071dd73 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatelessTruncatedNormal.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StatelessTruncatedNormal" + endpoint { + name: "random.StatelessTruncatedNormal" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatelessWhile.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatelessWhile.pbtxt new file mode 100644 index 0000000000..1a4252c90a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatelessWhile.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StatelessWhile" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StaticRegexFullMatch.pbtxt b/tensorflow/core/api_def/java_api/api_def_StaticRegexFullMatch.pbtxt new file mode 100644 index 0000000000..66b841ad74 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StaticRegexFullMatch.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StaticRegexFullMatch" + endpoint { + name: "strings.StaticRegexFullMatch" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StaticRegexReplace.pbtxt b/tensorflow/core/api_def/java_api/api_def_StaticRegexReplace.pbtxt new file mode 100644 index 0000000000..305bc8a3ca --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StaticRegexReplace.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StaticRegexReplace" + endpoint { + name: "strings.StaticRegexReplace" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatsAggregatorHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatsAggregatorHandle.pbtxt new file mode 100644 index 0000000000..301dc982e3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatsAggregatorHandle.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StatsAggregatorHandle" + endpoint { + name: "data.StatsAggregatorHandle" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StatsAggregatorSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_StatsAggregatorSummary.pbtxt new file mode 100644 index 0000000000..f83c8f5a4f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StatsAggregatorSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StatsAggregatorSummary" + endpoint { + name: "summary.StatsAggregatorSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StopGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_StopGradient.pbtxt new file mode 100644 index 0000000000..ad8473e816 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StopGradient.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StopGradient" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StridedSlice.pbtxt b/tensorflow/core/api_def/java_api/api_def_StridedSlice.pbtxt new file mode 100644 index 0000000000..b0c301dab1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StridedSlice.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StridedSlice" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StridedSliceAssign.pbtxt b/tensorflow/core/api_def/java_api/api_def_StridedSliceAssign.pbtxt new file mode 100644 index 0000000000..6850dc2d1b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StridedSliceAssign.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StridedSliceAssign" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StridedSliceGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_StridedSliceGrad.pbtxt new file mode 100644 index 0000000000..b03204bcc4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StridedSliceGrad.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "StridedSliceGrad" +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringFormat.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringFormat.pbtxt new file mode 100644 index 0000000000..cdd0313996 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringFormat.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringFormat" + endpoint { + name: "strings.StringFormat" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringJoin.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringJoin.pbtxt new file mode 100644 index 0000000000..b43ff157cd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringJoin.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringJoin" + endpoint { + name: "strings.Join" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringLength.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringLength.pbtxt new file mode 100644 index 0000000000..c8eb48cc3c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringLength.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringLength" + endpoint { + name: "strings.StringLength" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt new file mode 100644 index 0000000000..f16e196a6f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringSplit" + endpoint { + name: "strings.StringSplit" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringSplitV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringSplitV2.pbtxt new file mode 100644 index 0000000000..0779eb7f71 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringSplitV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringSplitV2" + endpoint { + name: "strings.StringSplitV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringStrip.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringStrip.pbtxt new file mode 100644 index 0000000000..01691211ff --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringStrip.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringStrip" + endpoint { + name: "strings.Strip" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringToHashBucket.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringToHashBucket.pbtxt new file mode 100644 index 0000000000..765517578d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringToHashBucket.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringToHashBucket" + endpoint { + name: "strings.ToHashBucket" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringToHashBucketFast.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringToHashBucketFast.pbtxt new file mode 100644 index 0000000000..de08bc2d36 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringToHashBucketFast.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringToHashBucketFast" + endpoint { + name: "strings.ToHashBucketFast" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringToHashBucketStrong.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringToHashBucketStrong.pbtxt new file mode 100644 index 0000000000..15b9138238 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringToHashBucketStrong.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringToHashBucketStrong" + endpoint { + name: "strings.ToHashBucketStrong" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_StringToNumber.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringToNumber.pbtxt new file mode 100644 index 0000000000..196f694da5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_StringToNumber.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "StringToNumber" + endpoint { + name: "strings.ToNumber" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Sub.pbtxt b/tensorflow/core/api_def/java_api/api_def_Sub.pbtxt new file mode 100644 index 0000000000..e79c6a0036 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Sub.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Sub" + endpoint { + name: "math.Sub" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Substr.pbtxt b/tensorflow/core/api_def/java_api/api_def_Substr.pbtxt new file mode 100644 index 0000000000..78f34550a5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Substr.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Substr" + endpoint { + name: "strings.Substr" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Sum.pbtxt b/tensorflow/core/api_def/java_api/api_def_Sum.pbtxt new file mode 100644 index 0000000000..3999fa6ed1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Sum.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Sum" +} diff --git a/tensorflow/core/api_def/java_api/api_def_SummaryWriter.pbtxt b/tensorflow/core/api_def/java_api/api_def_SummaryWriter.pbtxt new file mode 100644 index 0000000000..8338c0fa18 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SummaryWriter.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SummaryWriter" + endpoint { + name: "summary.SummaryWriter" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Svd.pbtxt b/tensorflow/core/api_def/java_api/api_def_Svd.pbtxt new file mode 100644 index 0000000000..889d416281 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Svd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Svd" + endpoint { + name: "linalg.Svd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Switch.pbtxt b/tensorflow/core/api_def/java_api/api_def_Switch.pbtxt index 0d3362a91e..edd9255452 100644 --- a/tensorflow/core/api_def/java_api/api_def_Switch.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Switch.pbtxt @@ -1,4 +1,6 @@ op { - graph_op_name: "Switch" #TODO(karllessard) escape that reserved name - visibility: HIDDEN + graph_op_name: "Switch" + endpoint { + name: "SwitchCond" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_SymbolicGradient.pbtxt b/tensorflow/core/api_def/java_api/api_def_SymbolicGradient.pbtxt new file mode 100644 index 0000000000..6c6e68ae74 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_SymbolicGradient.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "SymbolicGradient" + endpoint { + name: "train.SymbolicGradient" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TFRecordDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_TFRecordDataset.pbtxt new file mode 100644 index 0000000000..76c077f452 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TFRecordDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TFRecordDataset" + endpoint { + name: "data.TFRecordDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt new file mode 100644 index 0000000000..72d02db279 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TFRecordReader" + endpoint { + name: "io.TFRecordReader" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt new file mode 100644 index 0000000000..beb7f58862 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TFRecordReaderV2" + endpoint { + name: "io.TFRecordReaderV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TakeDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_TakeDataset.pbtxt new file mode 100644 index 0000000000..2b0c0544fb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TakeDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TakeDataset" + endpoint { + name: "data.TakeDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TakeManySparseFromTensorsMap.pbtxt b/tensorflow/core/api_def/java_api/api_def_TakeManySparseFromTensorsMap.pbtxt new file mode 100644 index 0000000000..620e9fb012 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TakeManySparseFromTensorsMap.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TakeManySparseFromTensorsMap" + endpoint { + name: "sparse.TakeManySparseFromTensorsMap" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Tan.pbtxt b/tensorflow/core/api_def/java_api/api_def_Tan.pbtxt new file mode 100644 index 0000000000..560ca546b7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Tan.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Tan" + endpoint { + name: "math.Tan" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Tanh.pbtxt b/tensorflow/core/api_def/java_api/api_def_Tanh.pbtxt new file mode 100644 index 0000000000..90e441808f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Tanh.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Tanh" + endpoint { + name: "math.Tanh" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TanhGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_TanhGrad.pbtxt new file mode 100644 index 0000000000..c0837d0487 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TanhGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TanhGrad" + endpoint { + name: "math.TanhGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TemporaryVariable.pbtxt b/tensorflow/core/api_def/java_api/api_def_TemporaryVariable.pbtxt new file mode 100644 index 0000000000..8ce760f9c9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TemporaryVariable.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TemporaryVariable" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt new file mode 100644 index 0000000000..7eaa468130 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArray" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayClose.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayClose.pbtxt new file mode 100644 index 0000000000..e866250d3a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayClose.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayClose" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt new file mode 100644 index 0000000000..5add953e66 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayCloseV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt new file mode 100644 index 0000000000..b881089718 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayCloseV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayConcat.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcat.pbtxt new file mode 100644 index 0000000000..e72b58de1c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcat.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayConcat" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt new file mode 100644 index 0000000000..abc3e60f0c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayConcatV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt new file mode 100644 index 0000000000..d1a91e90d7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayConcatV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGather.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGather.pbtxt new file mode 100644 index 0000000000..d4d179874f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGather.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayGather" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt new file mode 100644 index 0000000000..dd94fc4ef5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayGatherV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt new file mode 100644 index 0000000000..b8f01e6ac1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayGatherV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGrad.pbtxt new file mode 100644 index 0000000000..517461edba --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGrad.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayGrad" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt new file mode 100644 index 0000000000..b7278b5ffa --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayGradV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt new file mode 100644 index 0000000000..b7c3f143ef --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayGradV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGradWithShape.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradWithShape.pbtxt new file mode 100644 index 0000000000..d6804fb697 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradWithShape.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayGradWithShape" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayPack.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayPack.pbtxt new file mode 100644 index 0000000000..030950b06f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayPack.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayPack" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayRead.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayRead.pbtxt new file mode 100644 index 0000000000..1b62f7fac7 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayRead.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayRead" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt new file mode 100644 index 0000000000..ba02f61028 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayReadV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt new file mode 100644 index 0000000000..c30428c23a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayReadV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayScatter.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatter.pbtxt new file mode 100644 index 0000000000..a3e8d1625e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatter.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayScatter" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV2.pbtxt new file mode 100644 index 0000000000..38080410e6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayScatterV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV3.pbtxt new file mode 100644 index 0000000000..6f42524af8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayScatterV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySize.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySize.pbtxt new file mode 100644 index 0000000000..fb3a6fae1c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArraySize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt new file mode 100644 index 0000000000..03bf061f8b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArraySizeV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt new file mode 100644 index 0000000000..0c14360641 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArraySizeV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySplit.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySplit.pbtxt new file mode 100644 index 0000000000..3eb8d6c7ff --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySplit.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArraySplit" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt new file mode 100644 index 0000000000..34740aa2ef --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArraySplitV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt new file mode 100644 index 0000000000..4b22f2bdf6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArraySplitV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayUnpack.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayUnpack.pbtxt new file mode 100644 index 0000000000..a9011de23e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayUnpack.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayUnpack" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayV2.pbtxt new file mode 100644 index 0000000000..d18517725e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayV3.pbtxt new file mode 100644 index 0000000000..06e65ef93c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayWrite.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayWrite.pbtxt new file mode 100644 index 0000000000..92ab1764ec --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayWrite.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayWrite" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt new file mode 100644 index 0000000000..10c505cff4 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayWriteV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt new file mode 100644 index 0000000000..2fe2d02127 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorArrayWriteV3" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorDataset.pbtxt new file mode 100644 index 0000000000..ed0ead6e7a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TensorDataset" + endpoint { + name: "data.TensorDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorForestCreateTreeVariable.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorForestCreateTreeVariable.pbtxt new file mode 100644 index 0000000000..8e2410a0dd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorForestCreateTreeVariable.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorForestCreateTreeVariable" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorForestTreeDeserialize.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeDeserialize.pbtxt new file mode 100644 index 0000000000..724bdb282d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeDeserialize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorForestTreeDeserialize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorForestTreeIsInitializedOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeIsInitializedOp.pbtxt new file mode 100644 index 0000000000..7e93af8508 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeIsInitializedOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorForestTreeIsInitializedOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorForestTreePredict.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorForestTreePredict.pbtxt new file mode 100644 index 0000000000..73770fa291 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorForestTreePredict.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorForestTreePredict" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorForestTreeResourceHandleOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeResourceHandleOp.pbtxt new file mode 100644 index 0000000000..c2ef0ee5dd --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeResourceHandleOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorForestTreeResourceHandleOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorForestTreeSerialize.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeSerialize.pbtxt new file mode 100644 index 0000000000..d10f9e632b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeSerialize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorForestTreeSerialize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorForestTreeSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeSize.pbtxt new file mode 100644 index 0000000000..9d81f1ea8c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorForestTreeSize.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorForestTreeSize" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListConcatLists.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListConcatLists.pbtxt new file mode 100644 index 0000000000..3fa6265e10 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListConcatLists.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListConcatLists" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListElementShape.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListElementShape.pbtxt new file mode 100644 index 0000000000..396a0cfa8f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListElementShape.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListElementShape" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListFromTensor.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListFromTensor.pbtxt new file mode 100644 index 0000000000..3179feddd6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListFromTensor.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListFromTensor" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListGather.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListGather.pbtxt new file mode 100644 index 0000000000..580d34b68f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListGather.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListGather" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListGetItem.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListGetItem.pbtxt new file mode 100644 index 0000000000..2c47208fa0 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListGetItem.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListGetItem" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListLength.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListLength.pbtxt new file mode 100644 index 0000000000..2ec689d71c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListLength.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListLength" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListPopBack.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListPopBack.pbtxt new file mode 100644 index 0000000000..8d0d6ed55b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListPopBack.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListPopBack" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListPushBack.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListPushBack.pbtxt new file mode 100644 index 0000000000..285351cf4f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListPushBack.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListPushBack" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListPushBackBatch.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListPushBackBatch.pbtxt new file mode 100644 index 0000000000..1f33d49260 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListPushBackBatch.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListPushBackBatch" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListReserve.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListReserve.pbtxt new file mode 100644 index 0000000000..5336600688 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListReserve.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListReserve" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListScatter.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListScatter.pbtxt new file mode 100644 index 0000000000..f3a56f1292 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListScatter.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListScatter" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListSetItem.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListSetItem.pbtxt new file mode 100644 index 0000000000..002e2a9bd3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListSetItem.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListSetItem" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorListStack.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorListStack.pbtxt new file mode 100644 index 0000000000..b4b03c86e5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorListStack.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TensorListStack" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorSliceDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorSliceDataset.pbtxt new file mode 100644 index 0000000000..3729a025e6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorSliceDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TensorSliceDataset" + endpoint { + name: "data.TensorSliceDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorSummary.pbtxt new file mode 100644 index 0000000000..a720ca9076 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TensorSummary" + endpoint { + name: "summary.TensorSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TensorSummaryV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorSummaryV2.pbtxt new file mode 100644 index 0000000000..ba5131c85e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TensorSummaryV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TensorSummaryV2" + endpoint { + name: "summary.TensorSummaryV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TextLineDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_TextLineDataset.pbtxt new file mode 100644 index 0000000000..c3c75d5703 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TextLineDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TextLineDataset" + endpoint { + name: "data.TextLineDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TextLineReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_TextLineReader.pbtxt new file mode 100644 index 0000000000..17eb20cffe --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TextLineReader.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TextLineReader" + endpoint { + name: "io.TextLineReader" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TextLineReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TextLineReaderV2.pbtxt new file mode 100644 index 0000000000..745c85fac9 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TextLineReaderV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TextLineReaderV2" + endpoint { + name: "io.TextLineReaderV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ThreadUnsafeUnigramCandidateSampler.pbtxt b/tensorflow/core/api_def/java_api/api_def_ThreadUnsafeUnigramCandidateSampler.pbtxt new file mode 100644 index 0000000000..2ef4a83478 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ThreadUnsafeUnigramCandidateSampler.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ThreadUnsafeUnigramCandidateSampler" + endpoint { + name: "random.ThreadUnsafeUnigramCandidateSampler" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Tile.pbtxt b/tensorflow/core/api_def/java_api/api_def_Tile.pbtxt new file mode 100644 index 0000000000..8e4e63a222 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Tile.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Tile" + endpoint { + name: "Tile" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TileGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_TileGrad.pbtxt new file mode 100644 index 0000000000..7cd975c02f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TileGrad.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TileGrad" + endpoint { + name: "train.TileGrad" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Timestamp.pbtxt b/tensorflow/core/api_def/java_api/api_def_Timestamp.pbtxt new file mode 100644 index 0000000000..9ebc664ae1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Timestamp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Timestamp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_TopK.pbtxt b/tensorflow/core/api_def/java_api/api_def_TopK.pbtxt new file mode 100644 index 0000000000..108701adf1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TopK.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TopK" + endpoint { + name: "nn.TopK" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt new file mode 100644 index 0000000000..2aa89adcce --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TopKV2" + endpoint { + name: "nn.TopKV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Transpose.pbtxt b/tensorflow/core/api_def/java_api/api_def_Transpose.pbtxt new file mode 100644 index 0000000000..ad7900c00b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Transpose.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Transpose" + endpoint { + name: "linalg.Transpose" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TruncateDiv.pbtxt b/tensorflow/core/api_def/java_api/api_def_TruncateDiv.pbtxt new file mode 100644 index 0000000000..4fbd682340 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TruncateDiv.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TruncateDiv" + endpoint { + name: "math.TruncateDiv" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TruncateMod.pbtxt b/tensorflow/core/api_def/java_api/api_def_TruncateMod.pbtxt new file mode 100644 index 0000000000..7d1ae9a14f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TruncateMod.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TruncateMod" + endpoint { + name: "math.TruncateMod" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TruncatedNormal.pbtxt b/tensorflow/core/api_def/java_api/api_def_TruncatedNormal.pbtxt new file mode 100644 index 0000000000..b2dd52c955 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TruncatedNormal.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "TruncatedNormal" + endpoint { + name: "random.TruncatedNormal" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_TryRpc.pbtxt b/tensorflow/core/api_def/java_api/api_def_TryRpc.pbtxt new file mode 100644 index 0000000000..7ca476086a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_TryRpc.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "TryRpc" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Unbatch.pbtxt b/tensorflow/core/api_def/java_api/api_def_Unbatch.pbtxt new file mode 100644 index 0000000000..513b05593a --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Unbatch.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Unbatch" +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnbatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnbatchDataset.pbtxt new file mode 100644 index 0000000000..24907c804b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnbatchDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "UnbatchDataset" + endpoint { + name: "data.UnbatchDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnbatchGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnbatchGrad.pbtxt new file mode 100644 index 0000000000..ce612f84f6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnbatchGrad.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "UnbatchGrad" +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnicodeDecodeWithOffsets.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnicodeDecodeWithOffsets.pbtxt new file mode 100644 index 0000000000..16cc033140 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnicodeDecodeWithOffsets.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "UnicodeDecodeWithOffsets" + endpoint { + name: "strings.UnicodeDecodeWithOffsets" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnicodeScript.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnicodeScript.pbtxt new file mode 100644 index 0000000000..a873151d5f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnicodeScript.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "UnicodeScript" + endpoint { + name: "strings.UnicodeScript" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnicodeTranscode.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnicodeTranscode.pbtxt new file mode 100644 index 0000000000..131cc6169c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnicodeTranscode.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "UnicodeTranscode" + endpoint { + name: "strings.UnicodeTranscode" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_UniformCandidateSampler.pbtxt b/tensorflow/core/api_def/java_api/api_def_UniformCandidateSampler.pbtxt new file mode 100644 index 0000000000..d7a56c2a6e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UniformCandidateSampler.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "UniformCandidateSampler" + endpoint { + name: "random.UniformCandidateSampler" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Unique.pbtxt b/tensorflow/core/api_def/java_api/api_def_Unique.pbtxt new file mode 100644 index 0000000000..5c4262b5fb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Unique.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Unique" +} diff --git a/tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt new file mode 100644 index 0000000000..4d43500a0d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "UniqueV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_UniqueWithCounts.pbtxt b/tensorflow/core/api_def/java_api/api_def_UniqueWithCounts.pbtxt new file mode 100644 index 0000000000..1ce5314157 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UniqueWithCounts.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "UniqueWithCounts" +} diff --git a/tensorflow/core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt new file mode 100644 index 0000000000..abfd496b8e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "UniqueWithCountsV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Unpack.pbtxt b/tensorflow/core/api_def/java_api/api_def_Unpack.pbtxt new file mode 100644 index 0000000000..c3ad63e8f8 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Unpack.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Unpack" +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnravelIndex.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnravelIndex.pbtxt new file mode 100644 index 0000000000..1a08dc8f1e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnravelIndex.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "UnravelIndex" +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentMax.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentMax.pbtxt new file mode 100644 index 0000000000..a58d8740d5 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentMax.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "UnsortedSegmentMax" + endpoint { + name: "math.UnsortedSegmentMax" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentMin.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentMin.pbtxt new file mode 100644 index 0000000000..2f17ab4624 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentMin.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "UnsortedSegmentMin" + endpoint { + name: "math.UnsortedSegmentMin" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentProd.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentProd.pbtxt new file mode 100644 index 0000000000..c594941bcc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentProd.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "UnsortedSegmentProd" + endpoint { + name: "math.UnsortedSegmentProd" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentSum.pbtxt b/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentSum.pbtxt new file mode 100644 index 0000000000..e10cf8a6c2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UnsortedSegmentSum.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "UnsortedSegmentSum" + endpoint { + name: "math.UnsortedSegmentSum" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Unstage.pbtxt b/tensorflow/core/api_def/java_api/api_def_Unstage.pbtxt new file mode 100644 index 0000000000..31a97cf84d --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Unstage.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Unstage" +} diff --git a/tensorflow/core/api_def/java_api/api_def_UpperBound.pbtxt b/tensorflow/core/api_def/java_api/api_def_UpperBound.pbtxt new file mode 100644 index 0000000000..229a6ddfc3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_UpperBound.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "UpperBound" +} diff --git a/tensorflow/core/api_def/java_api/api_def_VarHandleOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_VarHandleOp.pbtxt new file mode 100644 index 0000000000..30bdace0e6 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_VarHandleOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "VarHandleOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_VarIsInitializedOp.pbtxt b/tensorflow/core/api_def/java_api/api_def_VarIsInitializedOp.pbtxt new file mode 100644 index 0000000000..a3992019bc --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_VarIsInitializedOp.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "VarIsInitializedOp" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Variable.pbtxt b/tensorflow/core/api_def/java_api/api_def_Variable.pbtxt new file mode 100644 index 0000000000..abc2f9c954 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Variable.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Variable" +} diff --git a/tensorflow/core/api_def/java_api/api_def_VariableShape.pbtxt b/tensorflow/core/api_def/java_api/api_def_VariableShape.pbtxt new file mode 100644 index 0000000000..38c63b5b70 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_VariableShape.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "VariableShape" +} diff --git a/tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt new file mode 100644 index 0000000000..221a80f760 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "VariableV2" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Where.pbtxt b/tensorflow/core/api_def/java_api/api_def_Where.pbtxt new file mode 100644 index 0000000000..f130181a6e --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Where.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "Where" +} diff --git a/tensorflow/core/api_def/java_api/api_def_While.pbtxt b/tensorflow/core/api_def/java_api/api_def_While.pbtxt new file mode 100644 index 0000000000..9d0f3b0763 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_While.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "While" +} diff --git a/tensorflow/core/api_def/java_api/api_def_WholeFileReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_WholeFileReader.pbtxt new file mode 100644 index 0000000000..67a8933efb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WholeFileReader.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WholeFileReader" + endpoint { + name: "io.WholeFileReader" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt new file mode 100644 index 0000000000..172268a122 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WholeFileReaderV2" + endpoint { + name: "io.WholeFileReaderV2" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_WindowDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_WindowDataset.pbtxt new file mode 100644 index 0000000000..69f12c55e1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WindowDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WindowDataset" + endpoint { + name: "data.WindowDataset" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_WriteAudioSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_WriteAudioSummary.pbtxt new file mode 100644 index 0000000000..fcd0df85c2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WriteAudioSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WriteAudioSummary" + endpoint { + name: "summary.WriteAudioSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_WriteFile.pbtxt b/tensorflow/core/api_def/java_api/api_def_WriteFile.pbtxt new file mode 100644 index 0000000000..a2d6a5bace --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WriteFile.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WriteFile" + endpoint { + name: "io.WriteFile" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_WriteGraphSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_WriteGraphSummary.pbtxt new file mode 100644 index 0000000000..8e461bbba3 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WriteGraphSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WriteGraphSummary" + endpoint { + name: "summary.WriteGraphSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_WriteHistogramSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_WriteHistogramSummary.pbtxt new file mode 100644 index 0000000000..c991079032 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WriteHistogramSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WriteHistogramSummary" + endpoint { + name: "summary.WriteHistogramSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_WriteImageSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_WriteImageSummary.pbtxt new file mode 100644 index 0000000000..08bf0adb2f --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WriteImageSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WriteImageSummary" + endpoint { + name: "summary.WriteImageSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_WriteScalarSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_WriteScalarSummary.pbtxt new file mode 100644 index 0000000000..7bc7c16a0c --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WriteScalarSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WriteScalarSummary" + endpoint { + name: "summary.WriteScalarSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_WriteSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_WriteSummary.pbtxt new file mode 100644 index 0000000000..1141cb6dbb --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_WriteSummary.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "WriteSummary" + endpoint { + name: "summary.WriteSummary" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Xdivy.pbtxt b/tensorflow/core/api_def/java_api/api_def_Xdivy.pbtxt new file mode 100644 index 0000000000..13a94b8a56 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Xdivy.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Xdivy" + endpoint { + name: "math.Xdivy" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_Xlogy.pbtxt b/tensorflow/core/api_def/java_api/api_def_Xlogy.pbtxt new file mode 100644 index 0000000000..52f457d645 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Xlogy.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Xlogy" + endpoint { + name: "math.Xlogy" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ZerosLike.pbtxt b/tensorflow/core/api_def/java_api/api_def_ZerosLike.pbtxt new file mode 100644 index 0000000000..8ef17aba9b --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ZerosLike.pbtxt @@ -0,0 +1,3 @@ +op { + graph_op_name: "ZerosLike" +} diff --git a/tensorflow/core/api_def/java_api/api_def_Zeta.pbtxt b/tensorflow/core/api_def/java_api/api_def_Zeta.pbtxt new file mode 100644 index 0000000000..b602bbc7e1 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_Zeta.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "Zeta" + endpoint { + name: "math.Zeta" + } +} diff --git a/tensorflow/core/api_def/java_api/api_def_ZipDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ZipDataset.pbtxt new file mode 100644 index 0000000000..e32362bef2 --- /dev/null +++ b/tensorflow/core/api_def/java_api/api_def_ZipDataset.pbtxt @@ -0,0 +1,6 @@ +op { + graph_op_name: "ZipDataset" + endpoint { + name: "data.ZipDataset" + } +} -- GitLab From b381d3c10bef3d3bd87cf691a40502986b3f35dc Mon Sep 17 00:00:00 2001 From: Karl Lessard Date: Mon, 26 Nov 2018 22:45:29 -0500 Subject: [PATCH 0036/1765] Use lower-camelcase in ops names and fix uniqueness --- tensorflow/core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt | 2 +- .../core/api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt | 2 +- .../core/api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt | 2 +- .../core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt | 2 +- .../core/api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt | 2 +- .../core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt | 2 +- .../core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt | 2 +- .../core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt | 2 +- .../core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt | 2 +- .../core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt | 2 +- .../core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt | 2 +- .../api_def/java_api/api_def_CudnnRNNCanonicalToParams.pbtxt | 2 +- .../core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt | 2 +- .../api_def/java_api/api_def_CudnnRNNParamsToCanonical.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt | 2 +- .../api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt | 2 +- .../api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt | 2 +- .../core/api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt | 2 +- .../api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_FusedPadConv2D.pbtxt | 2 +- .../api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt | 2 +- .../core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt | 2 +- .../core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt | 2 +- .../core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_QuantizedConv2D.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt | 2 +- .../core/api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt | 2 +- .../java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt | 2 +- .../core/api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt | 2 +- .../java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt | 2 +- .../java_api/api_def_ResourceSparseApplyCenteredRMSProp.pbtxt | 2 +- .../api_def/java_api/api_def_ResourceSparseApplyRMSProp.pbtxt | 2 +- .../core/api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt | 2 +- .../api_def/java_api/api_def_SparseApplyCenteredRMSProp.pbtxt | 2 +- .../core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_TFRecordDataset.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt | 2 +- .../core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt | 2 +- 63 files changed, 65 insertions(+), 62 deletions(-) diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt index d2b38707fb..815df985ef 100644 --- a/tensorflow/core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ApplyAdagradDA.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ApplyAdagradDA" endpoint { - name: "train.ApplyAdagradDA" + name: "train.ApplyAdagradDa" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt index 6ed0660165..1b831bca43 100644 --- a/tensorflow/core/api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ApplyCenteredRMSProp.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ApplyCenteredRMSProp" endpoint { - name: "train.ApplyCenteredRMSProp" + name: "train.ApplyCenteredRmsProp" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt index a1397b16fc..90171ccc75 100644 --- a/tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ApplyRMSProp.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ApplyRMSProp" endpoint { - name: "train.ApplyRMSProp" + name: "train.ApplyRmsProp" } } diff --git a/tensorflow/core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt index ac51715095..09aba78ca2 100644 --- a/tensorflow/core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_AvgPool3DGrad.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "AvgPool3DGrad" endpoint { - name: "nn.AvgPool3DGrad" + name: "nn.AvgPool3dGrad" } } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt index 62bc804c7e..4dda7c1fb6 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchFFT.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "BatchFFT" endpoint { - name: "signal.BatchFFT" + name: "signal.BatchFft" } } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt index 89479537a2..e11860138a 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchFFT2D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "BatchFFT2D" endpoint { - name: "signal.BatchFFT2D" + name: "signal.BatchFft2d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt index e9cff897bb..3be0b516d0 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchFFT3D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "BatchFFT3D" endpoint { - name: "signal.BatchFFT3D" + name: "signal.BatchFft3d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt index f156a6df39..de37ada148 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchIFFT.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "BatchIFFT" endpoint { - name: "signal.BatchIFFT" + name: "signal.BatchIfft" } } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt index 7cce88f8f7..4ae7fb4cb0 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchIFFT2D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "BatchIFFT2D" endpoint { - name: "signal.BatchIFFT2D" + name: "signal.BatchIfft2d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt index b30e596d75..0ecb52714b 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchIFFT3D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "BatchIFFT3D" endpoint { - name: "signal.BatchIFFT3D" + name: "signal.BatchIfft3d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt b/tensorflow/core/api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt index 79dae81df9..39739f03a3 100644 --- a/tensorflow/core/api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CTCBeamSearchDecoder.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CTCBeamSearchDecoder" endpoint { - name: "nn.CTCBeamSearchDecoder" + name: "nn.CtcBeamSearchDecoder" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt b/tensorflow/core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt index 6a58e628bd..009742f097 100644 --- a/tensorflow/core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CTCGreedyDecoder.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CTCGreedyDecoder" endpoint { - name: "nn.CTCGreedyDecoder" + name: "nn.CtcGreedyDecoder" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt b/tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt index 361270e1f7..dbeefa4017 100644 --- a/tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CTCLoss.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CTCLoss" endpoint { - name: "nn.CTCLoss" + name: "nn.CtcLoss" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt index 04c4fcec16..21d1398e09 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv2D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv2D" endpoint { - name: "nn.Conv2D" + name: "nn.Conv2d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt index 990a54262e..30eb55c6f2 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropFilter.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv2DBackpropFilter" endpoint { - name: "nn.Conv2DBackpropFilter" + name: "nn.Conv2dBackpropFilter" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt index 11bbaa455c..7c98646c13 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv2DBackpropInput.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv2DBackpropInput" endpoint { - name: "nn.Conv2DBackpropInput" + name: "nn.Conv2dBackpropInput" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt index 0d97065704..6ee1befcff 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv3D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv3D" endpoint { - name: "nn.Conv3D" + name: "nn.Conv3d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt index 279cd5867e..f66034aec1 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv3DBackpropFilter" endpoint { - name: "nn.Conv3DBackpropFilter" + name: "nn.Conv3dBackpropFilter" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt index 0643cc14a9..13db85238f 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv3DBackpropFilterV2" endpoint { - name: "nn.Conv3dBackpropFilter" + name: "nn.Conv3dBackpropFilterV2" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt index 5be32ebe3c..fdb2a9d66c 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv3DBackpropInput" endpoint { - name: "nn.Conv3DBackpropInput" + name: "nn.Conv3dBackpropInput" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt index 2ce9cf134b..7f25b7b9af 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv3DBackpropInputV2" endpoint { - name: "nn.Conv3DBackpropInputV2" + name: "nn.Conv3dBackpropInputV2" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt index c3d7f17596..4cd8e4fa0f 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CudnnRNN" endpoint { - name: "nn.CudnnRNN" + name: "nn.CudnnRnn" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt index 371b6a18db..b2a222e03a 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CudnnRNNBackprop" endpoint { - name: "nn.CudnnRNNBackprop" + name: "nn.CudnnRnnBackprop" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt index 756abdb71f..880a3b2bc4 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CudnnRNNBackpropV2" endpoint { - name: "nn.CudnnRNNBackpropV2" + name: "nn.CudnnRnnBackpropV2" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNCanonicalToParams.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNCanonicalToParams.pbtxt index 86d7045db7..8d351fa860 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNNCanonicalToParams.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNCanonicalToParams.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CudnnRNNCanonicalToParams" endpoint { - name: "nn.CudnnRNNCanonicalToParams" + name: "nn.CudnnRnnCanonicalToParams" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt index 73922b0343..3f1193fe60 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsSize.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CudnnRNNParamsSize" endpoint { - name: "nn.CudnnRNNParamsSize" + name: "nn.CudnnRnnParamsSize" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsToCanonical.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsToCanonical.pbtxt index e1c567163a..d2e4c6201e 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsToCanonical.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNParamsToCanonical.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CudnnRNNParamsToCanonical" endpoint { - name: "nn.CudnnRNNParamsToCanonical" + name: "nn.CudnnRnnParamsToCanonical" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt index d535f35459..7086d3c9d2 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CudnnRNNV2" endpoint { - name: "nn.CudnnRNNV2" + name: "nn.CudnnRnnV2" } } diff --git a/tensorflow/core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt b/tensorflow/core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt index 5884fe960d..3d38857063 100644 --- a/tensorflow/core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_DatasetToTFRecord.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "DatasetToTFRecord" endpoint { - name: "data.DatasetToTFRecord" + name: "data.DatasetToTfRecord" } } diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt index 2c738cf4dd..1d60107ada 100644 --- a/tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_DecodeCSV.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "DecodeCSV" endpoint { - name: "io.DecodeCSV" + name: "io.DecodeCsv" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt b/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt index ab8b79d681..db3c68e088 100644 --- a/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropFilter.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Dilation2DBackpropFilter" endpoint { - name: "nn.Dilation2DBackpropFilter" + name: "nn.Dilation2dBackpropFilter" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt b/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt index 9dece4569c..c935144f7a 100644 --- a/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Dilation2DBackpropInput.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Dilation2DBackpropInput" endpoint { - name: "nn.Dilation2DBackpropInput" + name: "nn.Dilation2dBackpropInput" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt index 2c555c3f1a..51fdd9f0b0 100644 --- a/tensorflow/core/api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalCSVDataset.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ExperimentalCSVDataset" endpoint { - name: "data.ExperimentalCSVDataset" + name: "data.ExperimentalCsvDataset" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt index dd24ff544f..a092b1cf39 100644 --- a/tensorflow/core/api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ExperimentalLMDBDataset.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ExperimentalLMDBDataset" endpoint { - name: "data.ExperimentalLMDBDataset" + name: "data.ExperimentalLmdbDataset" } } diff --git a/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt index e1760b685b..18c3ed4979 100644 --- a/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "FIFOQueue" endpoint { - name: "io.FIFOQueue" + name: "io.FifoQueue" } } diff --git a/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt index fe260ca2be..f892d7291d 100644 --- a/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "FIFOQueueV2" endpoint { - name: "io.FIFOQueueV2" + name: "io.FifoQueueV2" } } diff --git a/tensorflow/core/api_def/java_api/api_def_FusedPadConv2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedPadConv2D.pbtxt index e4836df290..e7ee10e0c5 100644 --- a/tensorflow/core/api_def/java_api/api_def_FusedPadConv2D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FusedPadConv2D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "FusedPadConv2D" endpoint { - name: "nn.FusedPadConv2D" + name: "nn.FusedPadConv2d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt index 6cd0caa088..6948fc1b87 100644 --- a/tensorflow/core/api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FusedResizeAndPadConv2D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "FusedResizeAndPadConv2D" endpoint { - name: "nn.FusedResizeAndPadConv2D" + name: "nn.FusedResizeAndPadConv2d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt index d2ade5b16e..7a68b01524 100644 --- a/tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_IRFFT.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "IRFFT" endpoint { - name: "signal.IRFFT" + name: "signal.Irfft" } } diff --git a/tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt index 3a5a5b0c71..239ec445d0 100644 --- a/tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_IRFFT2D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "IRFFT2D" endpoint { - name: "signal.IRFFT2D" + name: "signal.Irfft2d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt index fc5a5451b4..87969436b7 100644 --- a/tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_IRFFT3D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "IRFFT3D" endpoint { - name: "signal.IRFFT3D" + name: "signal.Irfft3d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt index 226fa21953..b6cd7bdbb7 100644 --- a/tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LMDBReader.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "LMDBReader" endpoint { - name: "io.LMDBReader" + name: "io.LmdbReader" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt b/tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt index bbbd3bb3ec..aa94c958f1 100644 --- a/tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ListDiff.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "ListDiff" + endpoint { + name: "SetDiff1d" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt index 7f5ab71845..ca7a7be835 100644 --- a/tensorflow/core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MaxPool3DGrad.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "MaxPool3DGrad" endpoint { - name: "nn.MaxPool3DGrad" + name: "nn.MaxPool3dGrad" } } diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt index 4d7211add2..c70aa3fe30 100644 --- a/tensorflow/core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MaxPool3DGradGrad.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "MaxPool3DGradGrad" endpoint { - name: "nn.MaxPool3DGradGrad" + name: "nn.MaxPool3dGradGrad" } } diff --git a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt index 151ab0f872..952516cfff 100644 --- a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "PaddingFIFOQueue" endpoint { - name: "io.PaddingFIFOQueue" + name: "io.PaddingFifoQueue" } } diff --git a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt index 4b589a9afb..80c53e7ee9 100644 --- a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "PaddingFIFOQueueV2" endpoint { - name: "io.PaddingFIFOQueueV2" + name: "io.PaddingFifoQueueV2" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizedConv2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizedConv2D.pbtxt index 8345892762..9909157603 100644 --- a/tensorflow/core/api_def/java_api/api_def_QuantizedConv2D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QuantizedConv2D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QuantizedConv2D" endpoint { - name: "nn.QuantizedConv2D" + name: "nn.QuantizedConv2d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt b/tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt index e56a0ba30a..9576600e75 100644 --- a/tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_RFFT.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "RFFT" endpoint { - name: "signal.RFFT" + name: "signal.Rfft" } } diff --git a/tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt b/tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt index eb193e638d..41d638b26a 100644 --- a/tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_RFFT2D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "RFFT2D" endpoint { - name: "signal.RFFT2D" + name: "signal.Rfft2d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt b/tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt index 292b957f3e..7a762d22e5 100644 --- a/tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_RFFT3D.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "RFFT3D" endpoint { - name: "signal.RFFT3D" + name: "signal.Rfft3d" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt index 904e434b8a..afddaaff57 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyAdagradDA.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ResourceApplyAdagradDA" endpoint { - name: "train.ResourceApplyAdagradDA" + name: "train.ResourceApplyAdagradDa" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt index 58027823e0..85c97b430a 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyCenteredRMSProp.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ResourceApplyCenteredRMSProp" endpoint { - name: "train.ResourceApplyCenteredRMSProp" + name: "train.ResourceApplyCenteredRmsProp" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt index 74a3d77531..fa3adf759e 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyRMSProp.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ResourceApplyRMSProp" endpoint { - name: "train.ResourceApplyRMSProp" + name: "train.ResourceApplyRmsProp" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt index bd66d64160..0547687d64 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyAdagradDA.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ResourceSparseApplyAdagradDA" endpoint { - name: "train.ResourceSparseApplyAdagradDA" + name: "train.ResourceSparseApplyAdagradDa" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyCenteredRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyCenteredRMSProp.pbtxt index afda4adb0d..632b0ab4c2 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyCenteredRMSProp.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyCenteredRMSProp.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ResourceSparseApplyCenteredRMSProp" endpoint { - name: "train.ResourceSparseApplyCenteredRMSProp" + name: "train.ResourceSparseApplyCenteredRmsProp" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyRMSProp.pbtxt index 3e78f6f06d..ec8910a88a 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyRMSProp.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyRMSProp.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ResourceSparseApplyRMSProp" endpoint { - name: "train.ResourceSparseApplyRMSProp" + name: "train.ResourceSparseApplyRmsProp" } } diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt index 56d9b1c49b..950dc00dd3 100644 --- a/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyAdagradDA.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "SparseApplyAdagradDA" endpoint { - name: "train.SparseApplyAdagradDA" + name: "train.SparseApplyAdagradDa" } } diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyCenteredRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyCenteredRMSProp.pbtxt index fa35db29b0..090536f5eb 100644 --- a/tensorflow/core/api_def/java_api/api_def_SparseApplyCenteredRMSProp.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyCenteredRMSProp.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "SparseApplyCenteredRMSProp" endpoint { - name: "train.SparseApplyCenteredRMSProp" + name: "train.SparseApplyCenteredRmsProp" } } diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt index 94646093af..3e39f4ffa5 100644 --- a/tensorflow/core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyRMSProp.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "SparseApplyRMSProp" endpoint { - name: "train.SparseApplyRMSProp" + name: "train.SparseApplyRmsProp" } } diff --git a/tensorflow/core/api_def/java_api/api_def_TFRecordDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_TFRecordDataset.pbtxt index 76c077f452..f1d42edd63 100644 --- a/tensorflow/core/api_def/java_api/api_def_TFRecordDataset.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TFRecordDataset.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "TFRecordDataset" endpoint { - name: "data.TFRecordDataset" + name: "data.TfRecordDataset" } } diff --git a/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt index 72d02db279..c93d53fa1a 100644 --- a/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "TFRecordReader" endpoint { - name: "io.TFRecordReader" + name: "io.TfRecordReader" } } diff --git a/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt index beb7f58862..84df23f6e2 100644 --- a/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "TFRecordReaderV2" endpoint { - name: "io.TFRecordReaderV2" + name: "io.TfRecordReaderV2" } } -- GitLab From d249cbc1bba5fca15c732a7abd2600cfae56a4d6 Mon Sep 17 00:00:00 2001 From: Clayne Robison Date: Wed, 28 Nov 2018 09:03:33 -0700 Subject: [PATCH 0037/1765] Fixing typos; tweaking line length per approver request --- tensorflow/core/kernels/mkl_conv_ops.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tensorflow/core/kernels/mkl_conv_ops.h b/tensorflow/core/kernels/mkl_conv_ops.h index 5e4163890d..f28d8b6c74 100644 --- a/tensorflow/core/kernels/mkl_conv_ops.h +++ b/tensorflow/core/kernels/mkl_conv_ops.h @@ -222,7 +222,7 @@ class MklDnnConvUtil { // and GOIHW for grouped/depthwise convolutions, // OIHW = (out_depth, in_depth, rows, cols) // GOIHW = (group, out_depth, in_depth, rows, cols) - // Specifically for depthwise G=filer_indepth, O=filter_outdepth, I=1 + // Specifically for depthwise G=filter_indepth, O=filter_outdepth, I=1 if (is_Depthwise) { std::vector mkldnn_sizes(5, -1); mkldnn_sizes[MKL_GROUP_FILTER_DIM_G] = filter_in_depth; @@ -373,9 +373,9 @@ class MklDnnConvUtil { // TODO add support for 3-D Depthwise // Output depth is same as last dimension for filters for regular - // convolutions. - // For depthwise it is in_depth * channel_multiplier. The channel_miltipler - // is the last dimension of TF filter for depthwise convolutions. + // convolutions. For depthwise it is in_depth * channel_multiplier. + // The channel_multiplier is the last dimension of TF filter for + // depthwise convolutions. if (is_Depthwise) { out_depth = (filter_shape.dim_size(TF_2DFILTER_DIM_I) * filter_shape.dim_size(TF_2DFILTER_DIM_O)); -- GitLab From 046d08eff5cad0231c738dd362c85abf0877aa1d Mon Sep 17 00:00:00 2001 From: Karl Lessard Date: Wed, 28 Nov 2018 23:02:18 -0500 Subject: [PATCH 0038/1765] Only keep latest version available for each ops, skipping others. --- tensorflow/core/api_def/java_api/api_def_AccumulateNV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Add.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_AdjustContrast.pbtxt | 4 +--- .../core/api_def/java_api/api_def_AdjustContrastv2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_AudioSummaryV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_BatchDatasetV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt | 4 +--- .../core/api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_Concat.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt | 4 +--- .../api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt | 4 +--- .../core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt | 4 +--- .../core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt | 4 +--- .../core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_DecodeProtoV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt | 2 +- .../api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt | 4 +--- .../api_def/java_api/api_def_FixedLengthRecordDatasetV2.pbtxt | 2 +- .../api_def/java_api/api_def_FixedLengthRecordReader.pbtxt | 4 +--- .../api_def/java_api/api_def_FixedLengthRecordReaderV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_FusedBatchNorm.pbtxt | 4 +--- .../core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt | 4 +--- .../core/api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Gather.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_GetSessionHandle.pbtxt | 1 + .../core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_IdentityReader.pbtxt | 4 +--- .../core/api_def/java_api/api_def_IdentityReaderV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_InitializeTable.pbtxt | 1 + .../java_api/api_def_InitializeTableFromTextFile.pbtxt | 1 + .../java_api/api_def_InitializeTableFromTextFileV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_InitializeTableV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt | 4 +--- .../api_def/java_api/api_def_IteratorFromStringHandle.pbtxt | 4 +--- .../api_def/java_api/api_def_IteratorFromStringHandleV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_LookupTableExport.pbtxt | 1 + .../core/api_def/java_api/api_def_LookupTableExportV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableFind.pbtxt | 1 + .../core/api_def/java_api/api_def_LookupTableFindV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableImport.pbtxt | 1 + .../core/api_def/java_api/api_def_LookupTableImportV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableInsert.pbtxt | 1 + .../core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_LookupTableSize.pbtxt | 1 + .../core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt | 4 +--- .../core/api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt | 4 +--- .../core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt | 4 +--- .../core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_MutableDenseHashTable.pbtxt | 1 + .../api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_MutableHashTable.pbtxt | 1 + .../api_def/java_api/api_def_MutableHashTableOfTensors.pbtxt | 1 + .../java_api/api_def_MutableHashTableOfTensorsV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_MutableHashTableV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_NonMaxSuppression.pbtxt | 4 +--- .../core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt | 4 +--- .../core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt | 4 +--- .../core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Pad.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt | 4 +--- .../core/api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt | 4 +--- .../core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt | 2 +- .../api_def/java_api/api_def_ParallelInterleaveDataset.pbtxt | 4 +--- .../java_api/api_def_ParallelInterleaveDatasetV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Print.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_PriorityQueue.pbtxt | 4 +--- .../core/api_def/java_api/api_def_PriorityQueueV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_QuantizeAndDequantize.pbtxt | 4 +--- .../api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt | 4 +--- .../api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt | 4 +--- .../core/api_def/java_api/api_def_QueueDequeueMany.pbtxt | 4 +--- .../core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt | 4 +--- .../core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_QueueDequeueV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt | 4 +--- .../core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt | 4 +--- .../core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_QueueIsClosed.pbtxt | 4 +--- .../core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_RandomPoisson.pbtxt | 4 +--- .../core/api_def/java_api/api_def_RandomPoissonV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt | 4 +--- .../core/api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt | 2 +- .../api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt | 4 +--- .../api_def/java_api/api_def_ReaderNumRecordsProducedV2.pbtxt | 2 +- .../java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt | 4 +--- .../java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt | 4 +--- .../core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_ReaderResetV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_ReaderRestoreState.pbtxt | 4 +--- .../core/api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_ReaderSerializeState.pbtxt | 4 +--- .../api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt | 4 +--- .../core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt | 2 +- .../api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt | 4 +--- .../api_def/java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Restore.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt | 1 + .../api_def/java_api/api_def_SampleDistortedBoundingBox.pbtxt | 4 +--- .../java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Save.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_SdcaOptimizer.pbtxt | 4 +--- .../core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_SelfAdjointEig.pbtxt | 4 +--- .../core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt | 2 +- .../core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt | 4 +--- .../core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Stack.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_StringSplitV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt | 4 +--- .../core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayClose.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayConcat.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayGather.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayGrad.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayRead.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayScatter.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayScatterV2.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayScatterV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArraySize.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArraySplit.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_TensorArrayV2.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_TensorArrayV3.pbtxt | 3 +++ .../core/api_def/java_api/api_def_TensorArrayWrite.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt | 1 + .../core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_TensorSummary.pbtxt | 4 +--- .../core/api_def/java_api/api_def_TensorSummaryV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_TextLineReader.pbtxt | 4 +--- .../core/api_def/java_api/api_def_TextLineReaderV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_TopK.pbtxt | 4 +--- tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt | 2 +- tensorflow/core/api_def/java_api/api_def_Unique.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_UniqueWithCounts.pbtxt | 1 + .../core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt | 3 +++ tensorflow/core/api_def/java_api/api_def_Variable.pbtxt | 1 + tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt | 3 +++ .../core/api_def/java_api/api_def_WholeFileReader.pbtxt | 4 +--- .../core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt | 2 +- 208 files changed, 288 insertions(+), 251 deletions(-) diff --git a/tensorflow/core/api_def/java_api/api_def_AccumulateNV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_AccumulateNV2.pbtxt index 09e7a155e0..0c7a080c11 100644 --- a/tensorflow/core/api_def/java_api/api_def_AccumulateNV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_AccumulateNV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "AccumulateNV2" endpoint { - name: "math.AccumulateNV2" + name: "math.AccumulateN" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Add.pbtxt b/tensorflow/core/api_def/java_api/api_def_Add.pbtxt index 4f78ccc9ea..b082b055bf 100644 --- a/tensorflow/core/api_def/java_api/api_def_Add.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Add.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "Add" - endpoint { - name: "math.Add" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt index f42a2add07..863ec4f33c 100644 --- a/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "AddV2" endpoint { - name: "math.AddV2" + name: "math.Add" } } diff --git a/tensorflow/core/api_def/java_api/api_def_AdjustContrast.pbtxt b/tensorflow/core/api_def/java_api/api_def_AdjustContrast.pbtxt index ff49aec2db..daad141027 100644 --- a/tensorflow/core/api_def/java_api/api_def_AdjustContrast.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_AdjustContrast.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "AdjustContrast" - endpoint { - name: "image.AdjustContrast" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_AdjustContrastv2.pbtxt b/tensorflow/core/api_def/java_api/api_def_AdjustContrastv2.pbtxt index dd6647b137..81f565c1d5 100644 --- a/tensorflow/core/api_def/java_api/api_def_AdjustContrastv2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_AdjustContrastv2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "AdjustContrastv2" endpoint { - name: "image.AdjustContrastv2" + name: "image.AdjustContrast" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt index 388e39c6ba..176de19a9a 100644 --- a/tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ApplyFtrl.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ApplyFtrl" - endpoint { - name: "train.ApplyFtrl" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt index 8463ad163b..da0fc8fcbf 100644 --- a/tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ApplyFtrlV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ApplyFtrlV2" endpoint { - name: "train.ApplyFtrlV2" + name: "train.ApplyFtrl" } } diff --git a/tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt index 026ec79dd9..13d30de29d 100644 --- a/tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_AudioSummary.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "AudioSummary" - endpoint { - name: "summary.AudioSummary" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_AudioSummaryV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_AudioSummaryV2.pbtxt index 07d24ec3a3..e4eda8b09a 100644 --- a/tensorflow/core/api_def/java_api/api_def_AudioSummaryV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_AudioSummaryV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "AudioSummaryV2" endpoint { - name: "summary.AudioSummaryV2" + name: "summary.AudioSummary" } } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt index fe47605f37..0bb7298ba9 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchDataset.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "BatchDataset" - endpoint { - name: "data.BatchDataset" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchDatasetV2.pbtxt index 079efe146f..cd81b0b1cf 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchDatasetV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchDatasetV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "BatchDatasetV2" + endpoint { + name: "data.BatchDataset" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt index 58d60fa962..517030fd69 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEig.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "BatchSelfAdjointEig" - endpoint { - name: "linalg.BatchSelfAdjointEig" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt index fb18b2a000..9c97344390 100644 --- a/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BatchSelfAdjointEigV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "BatchSelfAdjointEigV2" endpoint { - name: "linalg.BatchSelfAdjointEigV2" + name: "linalg.BatchSelfAdjointEig" } } diff --git a/tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt b/tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt index 76ae8ec8ff..651c434e64 100644 --- a/tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_BiasAddV1.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "BiasAddV1" - endpoint { - name: "nn.BiasAddV1" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_Concat.pbtxt b/tensorflow/core/api_def/java_api/api_def_Concat.pbtxt index b13eb820ec..e2fc7eef88 100644 --- a/tensorflow/core/api_def/java_api/api_def_Concat.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Concat.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "Concat" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt index a600c31ed9..7035796981 100644 --- a/tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ConcatV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "ConcatV2" + endpoint { + name: "Concat" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt index f66034aec1..2e5f6c99d5 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilter.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "Conv3DBackpropFilter" - endpoint { - name: "nn.Conv3dBackpropFilter" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt index 13db85238f..0643cc14a9 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropFilterV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv3DBackpropFilterV2" endpoint { - name: "nn.Conv3dBackpropFilterV2" + name: "nn.Conv3dBackpropFilter" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt index fdb2a9d66c..cbb2c9f136 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInput.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "Conv3DBackpropInput" - endpoint { - name: "nn.Conv3dBackpropInput" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt index 7f25b7b9af..33c8f5a3ce 100644 --- a/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Conv3DBackpropInputV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "Conv3DBackpropInputV2" endpoint { - name: "nn.Conv3dBackpropInputV2" + name: "nn.Conv3dBackpropInput" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt index 4cd8e4fa0f..7e88d20713 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNN.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "CudnnRNN" - endpoint { - name: "nn.CudnnRnn" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt index b2a222e03a..9c9fc5f029 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackprop.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "CudnnRNNBackprop" - endpoint { - name: "nn.CudnnRnnBackprop" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt index 880a3b2bc4..c2e7ebc27d 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNBackpropV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CudnnRNNBackpropV2" endpoint { - name: "nn.CudnnRnnBackpropV2" + name: "nn.CudnnRnnBackprop" } } diff --git a/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt index 7086d3c9d2..e6dd5f42fc 100644 --- a/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_CudnnRNNV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "CudnnRNNV2" endpoint { - name: "nn.CudnnRnnV2" + name: "nn.CudnnRnn" } } diff --git a/tensorflow/core/api_def/java_api/api_def_DecodeProtoV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_DecodeProtoV2.pbtxt index ff6531a3ac..4ba118cb0e 100644 --- a/tensorflow/core/api_def/java_api/api_def_DecodeProtoV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_DecodeProtoV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "DecodeProtoV2" + endpoint { + name: "DecodeProto" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt index 18c3ed4979..e5b2f73c55 100644 --- a/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FIFOQueue.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "FIFOQueue" - endpoint { - name: "io.FifoQueue" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt index f892d7291d..c0861a6e8d 100644 --- a/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FIFOQueueV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "FIFOQueueV2" endpoint { - name: "io.FifoQueueV2" + name: "io.FifoQueue" } } diff --git a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt index 8f38364f85..d4f23d94c0 100644 --- a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDataset.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "FixedLengthRecordDataset" - endpoint { - name: "data.FixedLengthRecordDataset" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDatasetV2.pbtxt index 723248019d..b8012bbe16 100644 --- a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDatasetV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordDatasetV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "FixedLengthRecordDatasetV2" endpoint { - name: "data.FixedLengthRecordDatasetV2" + name: "data.FixedLengthRecordDataset" } } diff --git a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReader.pbtxt index 295526d074..f76cd49456 100644 --- a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReader.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReader.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "FixedLengthRecordReader" - endpoint { - name: "io.FixedLengthRecordReader" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReaderV2.pbtxt index 0cfefe2075..f897c21365 100644 --- a/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReaderV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FixedLengthRecordReaderV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "FixedLengthRecordReaderV2" endpoint { - name: "io.FixedLengthRecordReaderV2" + name: "io.FixedLengthRecordReader" } } diff --git a/tensorflow/core/api_def/java_api/api_def_FusedBatchNorm.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedBatchNorm.pbtxt index 058c82c177..9d6166fe81 100644 --- a/tensorflow/core/api_def/java_api/api_def_FusedBatchNorm.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FusedBatchNorm.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "FusedBatchNorm" - endpoint { - name: "nn.FusedBatchNorm" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt index 69baf2a8e3..5e1d066d8d 100644 --- a/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGrad.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "FusedBatchNormGrad" - endpoint { - name: "nn.FusedBatchNormGrad" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt index 81da6f4bb2..8f333c91f4 100644 --- a/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormGradV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "FusedBatchNormGradV2" endpoint { - name: "nn.FusedBatchNormGradV2" + name: "nn.FusedBatchNormGrad" } } diff --git a/tensorflow/core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt index e81d78ef5c..8a4e76c949 100644 --- a/tensorflow/core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_FusedBatchNormV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "FusedBatchNormV2" endpoint { - name: "nn.FusedBatchNormV2" + name: "nn.FusedBatchNorm" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Gather.pbtxt b/tensorflow/core/api_def/java_api/api_def_Gather.pbtxt index 6848641714..5c4ccda48b 100644 --- a/tensorflow/core/api_def/java_api/api_def_Gather.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Gather.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "Gather" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt index f5b2cb92f6..0927e77a96 100644 --- a/tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_GatherV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "GatherV2" + endpoint { + name: "Gather" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_GetSessionHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_GetSessionHandle.pbtxt index 84b14a3335..0ee6fe18a2 100644 --- a/tensorflow/core/api_def/java_api/api_def_GetSessionHandle.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_GetSessionHandle.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "GetSessionHandle" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt index 28488ac79a..ba89942d77 100644 --- a/tensorflow/core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_GetSessionHandleV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "GetSessionHandleV2" + endpoint { + name: "GetSessionHandle" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt b/tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt index f733b277ea..d48c2224f6 100644 --- a/tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_HashTable.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "HashTable" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt index 74fda0380a..38cc5818d3 100644 --- a/tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_HashTableV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "HashTableV2" + endpoint { + name: "HashTable" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_IdentityReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_IdentityReader.pbtxt index 1e1314213d..42fe85a567 100644 --- a/tensorflow/core/api_def/java_api/api_def_IdentityReader.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_IdentityReader.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "IdentityReader" - endpoint { - name: "io.IdentityReader" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_IdentityReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_IdentityReaderV2.pbtxt index 2973807a9c..8081ac26b3 100644 --- a/tensorflow/core/api_def/java_api/api_def_IdentityReaderV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_IdentityReaderV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "IdentityReaderV2" endpoint { - name: "io.IdentityReaderV2" + name: "io.IdentityReader" } } diff --git a/tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt b/tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt index 1cca92e0ea..bf90fd0f81 100644 --- a/tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_InTopK.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "InTopK" - endpoint { - name: "nn.InTopK" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt index 3dc9bff289..400ee71462 100644 --- a/tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_InTopKV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "InTopKV2" endpoint { - name: "nn.InTopKV2" + name: "nn.InTopK" } } diff --git a/tensorflow/core/api_def/java_api/api_def_InitializeTable.pbtxt b/tensorflow/core/api_def/java_api/api_def_InitializeTable.pbtxt index 49496f29a0..30e3d66bfe 100644 --- a/tensorflow/core/api_def/java_api/api_def_InitializeTable.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_InitializeTable.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "InitializeTable" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFile.pbtxt b/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFile.pbtxt index 8cc206b0f0..786e22cd47 100644 --- a/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFile.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFile.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "InitializeTableFromTextFile" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFileV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFileV2.pbtxt index 2a665348a7..9a4f702201 100644 --- a/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFileV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_InitializeTableFromTextFileV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "InitializeTableFromTextFileV2" + endpoint { + name: "InitializeTableFromTextFile" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_InitializeTableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_InitializeTableV2.pbtxt index 8d9bec2f2f..d7a9a813d0 100644 --- a/tensorflow/core/api_def/java_api/api_def_InitializeTableV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_InitializeTableV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "InitializeTableV2" + endpoint { + name: "InitializeTable" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt b/tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt index 7d4b5e6328..0f4d9967c3 100644 --- a/tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Iterator.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "Iterator" - endpoint { - name: "data.Iterator" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandle.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandle.pbtxt index b2fe71a0c1..0a4e443cde 100644 --- a/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandle.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandle.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "IteratorFromStringHandle" - endpoint { - name: "data.IteratorFromStringHandle" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandleV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandleV2.pbtxt index c77959f34c..86745a3a56 100644 --- a/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandleV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_IteratorFromStringHandleV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "IteratorFromStringHandleV2" endpoint { - name: "data.IteratorFromStringHandleV2" + name: "data.IteratorFromStringHandle" } } diff --git a/tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt index 7892b096fe..87720d441b 100644 --- a/tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_IteratorV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "IteratorV2" endpoint { - name: "data.IteratorV2" + name: "data.Iterator" } } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableExport.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableExport.pbtxt index 49637da997..29885222a4 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableExport.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableExport.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "LookupTableExport" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableExportV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableExportV2.pbtxt index fce8a6e3cc..d780f2a21d 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableExportV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableExportV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "LookupTableExportV2" + endpoint { + name: "LookupTableExport" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableFind.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableFind.pbtxt index f8637744ae..23f7facaa2 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableFind.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableFind.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "LookupTableFind" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableFindV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableFindV2.pbtxt index cb78732e9c..2247547b62 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableFindV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableFindV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "LookupTableFindV2" + endpoint { + name: "LookupTableFind" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableImport.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableImport.pbtxt index 4cf7971f56..f87ea9c073 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableImport.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableImport.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "LookupTableImport" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableImportV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableImportV2.pbtxt index 3216346961..a39cffa12d 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableImportV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableImportV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "LookupTableImportV2" + endpoint { + name: "LookupTableImport" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableInsert.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableInsert.pbtxt index 51fe22ba60..a45b3f52a5 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableInsert.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableInsert.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "LookupTableInsert" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt index 429bf25b0a..037b743b6b 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableInsertV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "LookupTableInsertV2" + endpoint { + name: "LookupTableInsert" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt index 274dd236e3..61f6d8db36 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableRemoveV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "LookupTableRemoveV2" + endpoint { + name: "LookupTableRemove" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableSize.pbtxt index 70329e9e90..391dc5dfad 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableSize.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableSize.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "LookupTableSize" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt index d5681c3fa0..ad646e25a6 100644 --- a/tensorflow/core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_LookupTableSizeV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "LookupTableSizeV2" + endpoint { + name: "LookupTableSize" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt index b8f23009d7..cb96bf63d8 100644 --- a/tensorflow/core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MapAndBatchDataset.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "MapAndBatchDataset" - endpoint { - name: "data.MapAndBatchDataset" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt index a0bc306c52..b29c21888f 100644 --- a/tensorflow/core/api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MapAndBatchDatasetV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "MapAndBatchDatasetV2" + endpoint { + name: "data.MapAndBatchDataset" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt index 17c17b5699..5ebc9e6a6f 100644 --- a/tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MaxPool.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "MaxPool" - endpoint { - name: "nn.MaxPool" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt index c8b783ee7a..9ad85fa08e 100644 --- a/tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGrad.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "MaxPoolGrad" - endpoint { - name: "nn.MaxPoolGrad" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt index 2dd7fdf229..3375ebc77d 100644 --- a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGrad.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "MaxPoolGradGrad" - endpoint { - name: "nn.MaxPoolGradGrad" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt index e2cf7927ca..2ca8a7b022 100644 --- a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradGradV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "MaxPoolGradGradV2" endpoint { - name: "nn.MaxPoolGradGradV2" + name: "nn.MaxPoolGradGrad" } } diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt index 1e47cd13e3..556dd0be50 100644 --- a/tensorflow/core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolGradV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "MaxPoolGradV2" endpoint { - name: "nn.MaxPoolGradV2" + name: "nn.MaxPoolGrad" } } diff --git a/tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt index bd885135d5..8463494355 100644 --- a/tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MaxPoolV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "MaxPoolV2" endpoint { - name: "nn.MaxPoolV2" + name: "nn.MaxPool" } } diff --git a/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTable.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTable.pbtxt index 15803468ff..d7494815d8 100644 --- a/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTable.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTable.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "MutableDenseHashTable" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt index 03fdeddb95..d1f7f26848 100644 --- a/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MutableDenseHashTableV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "MutableDenseHashTableV2" + endpoint { + name: "MutableDenseHashTable" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_MutableHashTable.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableHashTable.pbtxt index 1a80874495..c446ff8b27 100644 --- a/tensorflow/core/api_def/java_api/api_def_MutableHashTable.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MutableHashTable.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "MutableHashTable" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensors.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensors.pbtxt index bf2fa065dc..76df883d7d 100644 --- a/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensors.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensors.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "MutableHashTableOfTensors" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensorsV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensorsV2.pbtxt index 53d780e925..f6d7451267 100644 --- a/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensorsV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MutableHashTableOfTensorsV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "MutableHashTableOfTensorsV2" + endpoint { + name: "MutableHashTableOfTensors" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_MutableHashTableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutableHashTableV2.pbtxt index 99007df253..45d619d674 100644 --- a/tensorflow/core/api_def/java_api/api_def_MutableHashTableV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MutableHashTableV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "MutableHashTableV2" + endpoint { + name: "MutableHashTable" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt index 93988914aa..f89cd10643 100644 --- a/tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_MutexV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "MutexV2" + endpoint { + name: "Mutex" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppression.pbtxt b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppression.pbtxt index d7156b0a3a..49ac0de4ce 100644 --- a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppression.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppression.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "NonMaxSuppression" - endpoint { - name: "image.NonMaxSuppression" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt index d78eb9745d..fabf5c6215 100644 --- a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV2.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "NonMaxSuppressionV2" - endpoint { - name: "image.NonMaxSuppressionV2" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt index e3fde0a566..0aefcb5509 100644 --- a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV3.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "NonMaxSuppressionV3" - endpoint { - name: "image.NonMaxSuppressionV3" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt index 98776e8e7f..e71de7f4a6 100644 --- a/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_NonMaxSuppressionV4.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "NonMaxSuppressionV4" endpoint { - name: "image.NonMaxSuppressionV4" + name: "image.NonMaxSuppression" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Pad.pbtxt b/tensorflow/core/api_def/java_api/api_def_Pad.pbtxt index a9de5541ac..f83f451552 100644 --- a/tensorflow/core/api_def/java_api/api_def_Pad.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Pad.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "Pad" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt index 1554cd0b64..ffc1216456 100644 --- a/tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PadV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "PadV2" + endpoint { + name: "Pad" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt index 2d734539da..7cec77427c 100644 --- a/tensorflow/core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PaddedBatchDataset.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "PaddedBatchDataset" - endpoint { - name: "data.PaddedBatchDataset" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt index d4b85550e9..22dfe84f0c 100644 --- a/tensorflow/core/api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PaddedBatchDatasetV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "PaddedBatchDatasetV2" endpoint { - name: "data.PaddedBatchDatasetV2" + name: "data.PaddedBatchDataset" } } diff --git a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt index 952516cfff..03db4bf185 100644 --- a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueue.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "PaddingFIFOQueue" - endpoint { - name: "io.PaddingFifoQueue" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt index 80c53e7ee9..605025be79 100644 --- a/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PaddingFIFOQueueV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "PaddingFIFOQueueV2" endpoint { - name: "io.PaddingFifoQueueV2" + name: "io.PaddingFifoQueue" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDataset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDataset.pbtxt index 3ccc2a6bf7..6a985d24fa 100644 --- a/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDataset.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDataset.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ParallelInterleaveDataset" - endpoint { - name: "data.ParallelInterleaveDataset" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDatasetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDatasetV2.pbtxt index 56b05cc2f6..6c74149a6c 100644 --- a/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDatasetV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ParallelInterleaveDatasetV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "ParallelInterleaveDatasetV2" + endpoint { + name: "ParallelInterleaveDataset" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt b/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt index 5e6daa2ae4..efea7bd2b1 100644 --- a/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "Placeholder" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt index 39012d4aa2..a61f6f4d1e 100644 --- a/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "PlaceholderV2" + endpoint { + name: "Placeholder" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_Print.pbtxt b/tensorflow/core/api_def/java_api/api_def_Print.pbtxt index 5b837135fd..21a085a1c2 100644 --- a/tensorflow/core/api_def/java_api/api_def_Print.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Print.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "Print" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt index c6e406d08f..d1e4d74b1e 100644 --- a/tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PrintV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "PrintV2" + endpoint { + name: "Print" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_PriorityQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_PriorityQueue.pbtxt index cee973139d..0a9909d122 100644 --- a/tensorflow/core/api_def/java_api/api_def_PriorityQueue.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PriorityQueue.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "PriorityQueue" - endpoint { - name: "io.PriorityQueue" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_PriorityQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PriorityQueueV2.pbtxt index 27e89f92be..1f6a6f2906 100644 --- a/tensorflow/core/api_def/java_api/api_def_PriorityQueueV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PriorityQueueV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "PriorityQueueV2" endpoint { - name: "io.PriorityQueueV2" + name: "io.PriorityQueue" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantize.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantize.pbtxt index fe8401d8f9..e6ba0ce8b8 100644 --- a/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantize.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantize.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QuantizeAndDequantize" - endpoint { - name: "quantization.QuantizeAndDequantize" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt index 0535993d40..678a77113c 100644 --- a/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV2.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QuantizeAndDequantizeV2" - endpoint { - name: "quantization.QuantizeAndDequantize" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt index d056b320c8..c9e52e770a 100644 --- a/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QuantizeAndDequantizeV3.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QuantizeAndDequantizeV3" endpoint { - name: "quantization.QuantizeAndDequantizeV3" + name: "quantization.QuantizeAndDequantize" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt index d04a01726f..25c9c3bdce 100644 --- a/tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QuantizeV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QuantizeV2" endpoint { - name: "quantization.QuantizeV2" + name: "quantization.Quantize" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt index 70e559c773..4a6bada741 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueClose.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QueueClose" - endpoint { - name: "io.QueueClose" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt index 01460f27e2..ce779650e5 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueCloseV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QueueCloseV2" endpoint { - name: "io.QueueCloseV2" + name: "io.QueueClose" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt index 9cd77b4ca3..45c811a6b4 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeue.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QueueDequeue" - endpoint { - name: "io.QueueDequeue" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueMany.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueMany.pbtxt index ceb2e82394..9e088ef258 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueDequeueMany.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueMany.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QueueDequeueMany" - endpoint { - name: "io.QueueDequeueMany" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt index ac27fcb620..10fe198ff2 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueManyV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QueueDequeueManyV2" endpoint { - name: "io.QueueDequeueManyV2" + name: "io.QueueDequeueMany" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt index 657c63363f..b96e568c41 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpTo.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QueueDequeueUpTo" - endpoint { - name: "io.QueueDequeueUpTo" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt index 19b3fff653..fadea0926b 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueUpToV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QueueDequeueUpToV2" endpoint { - name: "io.QueueDequeueUpToV2" + name: "io.QueueDequeueUpTo" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueDequeueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueDequeueV2.pbtxt index 8aca207816..7ba03afbfe 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueDequeueV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueDequeueV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QueueDequeueV2" endpoint { - name: "io.QueueDequeueV2" + name: "io.QueueDequeue" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt index e516dab297..2945c46d6e 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueEnqueue.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QueueEnqueue" - endpoint { - name: "io.QueueEnqueue" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt index b9c0e4fd84..442ddcbc03 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueMany.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QueueEnqueueMany" - endpoint { - name: "io.QueueEnqueueMany" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt index 153700a646..be3fed4789 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueManyV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QueueEnqueueManyV2" endpoint { - name: "io.QueueEnqueueManyV2" + name: "io.QueueEnqueueMany" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt index 68bacd7b5b..e71a2211e1 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueEnqueueV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QueueEnqueueV2" endpoint { - name: "io.QueueEnqueueV2" + name: "io.QueueEnqueue" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueIsClosed.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueIsClosed.pbtxt index 86914c7124..0b51b208b7 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueIsClosed.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueIsClosed.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QueueIsClosed" - endpoint { - name: "io.QueueIsClosed" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt index ce33b2498b..148d313a6d 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueIsClosedV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QueueIsClosedV2" endpoint { - name: "io.QueueIsClosedV2" + name: "io.QueueIsClosed" } } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt index 5592d58f9f..9bd7244d68 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueSize.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "QueueSize" - endpoint { - name: "io.QueueSize" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt index 68364aa605..e93e07a2b3 100644 --- a/tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_QueueSizeV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "QueueSizeV2" endpoint { - name: "io.QueueSizeV2" + name: "io.QueueSize" } } diff --git a/tensorflow/core/api_def/java_api/api_def_RandomPoisson.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomPoisson.pbtxt index 42ce1a5fb1..d1ea795024 100644 --- a/tensorflow/core/api_def/java_api/api_def_RandomPoisson.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_RandomPoisson.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "RandomPoisson" - endpoint { - name: "random.RandomPoisson" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_RandomPoissonV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomPoissonV2.pbtxt index adc5441abc..5efe01bf40 100644 --- a/tensorflow/core/api_def/java_api/api_def_RandomPoissonV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_RandomPoissonV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "RandomPoissonV2" endpoint { - name: "random.RandomPoissonV2" + name: "random.RandomPoisson" } } diff --git a/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt index f622eb4e0d..9660121a07 100644 --- a/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueue.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "RandomShuffleQueue" - endpoint { - name: "io.RandomShuffleQueue" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt index c88c2a4631..779363303c 100644 --- a/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_RandomShuffleQueueV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "RandomShuffleQueueV2" endpoint { - name: "io.RandomShuffleQueueV2" + name: "io.RandomShuffleQueue" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt index 67dbe1035e..b087d11182 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProduced.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ReaderNumRecordsProduced" - endpoint { - name: "io.ReaderNumRecordsProduced" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProducedV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProducedV2.pbtxt index 5063706eb0..54a30abe18 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProducedV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderNumRecordsProducedV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ReaderNumRecordsProducedV2" endpoint { - name: "io.ReaderNumRecordsProducedV2" + name: "io.ReaderNumRecordsProduced" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt index 63bb2d4108..e30e97fd08 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompleted.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ReaderNumWorkUnitsCompleted" - endpoint { - name: "io.ReaderNumWorkUnitsCompleted" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt index cf72ecc562..0904ba19e5 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderNumWorkUnitsCompletedV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ReaderNumWorkUnitsCompletedV2" endpoint { - name: "io.ReaderNumWorkUnitsCompletedV2" + name: "io.ReaderNumWorkUnitsCompleted" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt index 47e9679f80..8f98d88bda 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderRead.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ReaderRead" - endpoint { - name: "io.ReaderRead" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt index 985d0035b0..d418b00b27 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderReadUpTo.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ReaderReadUpTo" - endpoint { - name: "io.ReaderReadUpTo" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt index a001349e2d..777d09fa2c 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderReadUpToV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ReaderReadUpToV2" endpoint { - name: "io.ReaderReadUpToV2" + name: "io.ReaderReadUpTo" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt index a64349d15e..a5d45bd1db 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderReadV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ReaderReadV2" endpoint { - name: "io.ReaderReadV2" + name: "io.ReaderRead" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt index 9a387753f5..e6041caabd 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderReset.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ReaderReset" - endpoint { - name: "io.ReaderReset" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderResetV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderResetV2.pbtxt index 6e31d5a8ff..265a3442f5 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderResetV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderResetV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ReaderResetV2" endpoint { - name: "io.ReaderResetV2" + name: "io.ReaderReset" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderRestoreState.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderRestoreState.pbtxt index d148adde6a..0aa0ec595d 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderRestoreState.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderRestoreState.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ReaderRestoreState" - endpoint { - name: "io.ReaderRestoreState" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt index 3d78d8eb00..4728ce7796 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderRestoreStateV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ReaderRestoreStateV2" endpoint { - name: "io.ReaderRestoreStateV2" + name: "io.ReaderRestoreState" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderSerializeState.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderSerializeState.pbtxt index fd12a4c784..5e23e285fb 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderSerializeState.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderSerializeState.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ReaderSerializeState" - endpoint { - name: "io.ReaderSerializeState" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt index 28c5048fc9..aa396095b1 100644 --- a/tensorflow/core/api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ReaderSerializeStateV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ReaderSerializeStateV2" endpoint { - name: "io.ReaderSerializeStateV2" + name: "io.ReaderSerializeState" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt index db64e86fd4..61bec5bb10 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrl.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ResourceApplyFtrl" - endpoint { - name: "train.ResourceApplyFtrl" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt index 547041e649..8209fd607e 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceApplyFtrlV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ResourceApplyFtrlV2" endpoint { - name: "train.ResourceApplyFtrlV2" + name: "train.ResourceApplyFtrl" } } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt index 195198fc9a..2e6fed9469 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrl.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "ResourceSparseApplyFtrl" - endpoint { - name: "train.ResourceSparseApplyFtrl" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt index 49c6d34dcc..cd126d78ab 100644 --- a/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_ResourceSparseApplyFtrlV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "ResourceSparseApplyFtrlV2" endpoint { - name: "train.ResourceSparseApplyFtrlV2" + name: "train.ResourceSparseApplyFtrl" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Restore.pbtxt b/tensorflow/core/api_def/java_api/api_def_Restore.pbtxt index ca79fc10db..5e5b021b08 100644 --- a/tensorflow/core/api_def/java_api/api_def_Restore.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Restore.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "Restore" - endpoint { - name: "train.Restore" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt index e877ff9869..909968873f 100644 --- a/tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_RestoreV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "RestoreV2" endpoint { - name: "train.RestoreV2" + name: "train.Restore" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt b/tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt index 2bd25417aa..d2a199d2fc 100644 --- a/tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Reverse.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "Reverse" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBox.pbtxt b/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBox.pbtxt index e7c1c90ea6..3dffd53b05 100644 --- a/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBox.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBox.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "SampleDistortedBoundingBox" - endpoint { - name: "image.SampleDistortedBoundingBox" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt index 8656977bf6..6557314137 100644 --- a/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SampleDistortedBoundingBoxV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "SampleDistortedBoundingBoxV2" endpoint { - name: "image.SampleDistortedBoundingBoxV2" + name: "image.SampleDistortedBoundingBox" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Save.pbtxt b/tensorflow/core/api_def/java_api/api_def_Save.pbtxt index 87dab6dc1f..36d44001d5 100644 --- a/tensorflow/core/api_def/java_api/api_def_Save.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Save.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "Save" - endpoint { - name: "train.Save" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt index 6417252f45..644d1824aa 100644 --- a/tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SaveV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "SaveV2" endpoint { - name: "train.SaveV2" + name: "train.Save" } } diff --git a/tensorflow/core/api_def/java_api/api_def_SdcaOptimizer.pbtxt b/tensorflow/core/api_def/java_api/api_def_SdcaOptimizer.pbtxt index 68eb8cf1f0..fab6393f60 100644 --- a/tensorflow/core/api_def/java_api/api_def_SdcaOptimizer.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SdcaOptimizer.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "SdcaOptimizer" - endpoint { - name: "train.SdcaOptimizer" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt index 4e90531060..b72ee64e50 100644 --- a/tensorflow/core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SdcaOptimizerV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "SdcaOptimizerV2" endpoint { - name: "train.SdcaOptimizerV2" + name: "train.SdcaOptimizer" } } diff --git a/tensorflow/core/api_def/java_api/api_def_SelfAdjointEig.pbtxt b/tensorflow/core/api_def/java_api/api_def_SelfAdjointEig.pbtxt index 552d397ad8..dc25ae9de2 100644 --- a/tensorflow/core/api_def/java_api/api_def_SelfAdjointEig.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SelfAdjointEig.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "SelfAdjointEig" - endpoint { - name: "linalg.SelfAdjointEig" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt index 4b610f437c..c79f08ac32 100644 --- a/tensorflow/core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SelfAdjointEigV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "SelfAdjointEigV2" endpoint { - name: "linalg.SelfAdjointEigV2" + name: "linalg.SelfAdjointEig" } } diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt index bb669aa773..e961fb7f6b 100644 --- a/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrl.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "SparseApplyFtrl" - endpoint { - name: "train.SparseApplyFtrl" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt index 673f71c34b..43b9833451 100644 --- a/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_SparseApplyFtrlV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "SparseApplyFtrlV2" endpoint { - name: "train.SparseApplyFtrlV2" + name: "train.SparseApplyFtrl" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Stack.pbtxt b/tensorflow/core/api_def/java_api/api_def_Stack.pbtxt index 522e5efec5..8370beee63 100644 --- a/tensorflow/core/api_def/java_api/api_def_Stack.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Stack.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "Stack" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt index 1cba682de9..ac3c410c1c 100644 --- a/tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_StackClose.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "StackClose" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt index be5a0f535a..28aff9e191 100644 --- a/tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_StackCloseV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "StackCloseV2" + endpoint { + name: "StackClose" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt index 4439e73843..b8658ecbad 100644 --- a/tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_StackPop.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "StackPop" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt index b8babb4c56..d2ecf4e5a8 100644 --- a/tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_StackPopV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "StackPopV2" + endpoint { + name: "StackPop" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt index 41792e327f..d08fa27b21 100644 --- a/tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_StackPush.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "StackPush" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt index 4920152259..519fd6c6b2 100644 --- a/tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_StackPushV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "StackPushV2" + endpoint { + name: "StackPush" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt index 5232e0425e..725e469a03 100644 --- a/tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_StackV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "StackV2" + endpoint { + name: "Stack" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt index f16e196a6f..0e6d1851df 100644 --- a/tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_StringSplit.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "StringSplit" - endpoint { - name: "strings.StringSplit" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_StringSplitV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_StringSplitV2.pbtxt index 0779eb7f71..18c71d6bd7 100644 --- a/tensorflow/core/api_def/java_api/api_def_StringSplitV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_StringSplitV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "StringSplitV2" endpoint { - name: "strings.StringSplitV2" + name: "strings.StringSplit" } } diff --git a/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt index c93d53fa1a..9ffbeba0ec 100644 --- a/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TFRecordReader.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "TFRecordReader" - endpoint { - name: "io.TfRecordReader" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt index 84df23f6e2..7d252e4942 100644 --- a/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TFRecordReaderV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "TFRecordReaderV2" endpoint { - name: "io.TfRecordReaderV2" + name: "io.TfRecordReader" } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt index 7eaa468130..e315486af2 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArray.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArray" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayClose.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayClose.pbtxt index e866250d3a..951ace8005 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayClose.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayClose.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayClose" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt index 5add953e66..6fd2d02592 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayCloseV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt index b881089718..4a06577979 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayCloseV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArrayCloseV3" + endpoint { + name: "TensorArrayClose" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayConcat.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcat.pbtxt index e72b58de1c..f507111093 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayConcat.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcat.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayConcat" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt index abc3e60f0c..e92cebf2a7 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayConcatV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt index d1a91e90d7..34d09c901a 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayConcatV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArrayConcatV3" + endpoint { + name: "TensorArrayConcat" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGather.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGather.pbtxt index d4d179874f..95866b9778 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayGather.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGather.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayGather" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt index dd94fc4ef5..f75b50c667 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayGatherV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt index b8f01e6ac1..b792ee9882 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGatherV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArrayGatherV3" + endpoint { + name: "TensorArrayGather" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGrad.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGrad.pbtxt index 517461edba..beb9b5ca12 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayGrad.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGrad.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayGrad" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt index b7278b5ffa..41d25a4910 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayGradV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt index b7c3f143ef..2c9adebd04 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayGradV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArrayGradV3" + endpoint { + name: "TensorArrayGrad" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayRead.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayRead.pbtxt index 1b62f7fac7..72704746a5 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayRead.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayRead.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayRead" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt index ba02f61028..43cd0a2b78 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayReadV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt index c30428c23a..e6d38d64df 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayReadV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArrayReadV3" + endpoint { + name: "TensorArrayRead" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayScatter.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatter.pbtxt index a3e8d1625e..76092a45ed 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayScatter.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatter.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayScatter" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV2.pbtxt index 38080410e6..7dba0fab4c 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayScatterV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV3.pbtxt index 6f42524af8..179c9611f5 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayScatterV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArrayScatterV3" + endpoint { + name: "TensorArrayScatter" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySize.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySize.pbtxt index fb3a6fae1c..fb2be098c6 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArraySize.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySize.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArraySize" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt index 03bf061f8b..8e8e44cfe2 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArraySizeV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt index 0c14360641..2df9a2d3f1 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySizeV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArraySizeV3" + endpoint { + name: "TensorArraySize" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySplit.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySplit.pbtxt index 3eb8d6c7ff..105031eb98 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArraySplit.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySplit.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArraySplit" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt index 34740aa2ef..ef5d88832a 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArraySplitV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt index 4b22f2bdf6..721af074d0 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArraySplitV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArraySplitV3" + endpoint { + name: "TensorArraySplit" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayV2.pbtxt index d18517725e..43a441a071 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayV3.pbtxt index 06e65ef93c..2b87617a1f 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArrayV3" + endpoint { + name: "TensorArray" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayWrite.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayWrite.pbtxt index 92ab1764ec..2462dae80d 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayWrite.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayWrite.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayWrite" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt index 10c505cff4..9f670ae181 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV2.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "TensorArrayWriteV2" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt index 2fe2d02127..7321057b2f 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorArrayWriteV3.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "TensorArrayWriteV3" + endpoint { + name: "TensorArrayWrite" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorSummary.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorSummary.pbtxt index a720ca9076..165478d3a0 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorSummary.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorSummary.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "TensorSummary" - endpoint { - name: "summary.TensorSummary" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TensorSummaryV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TensorSummaryV2.pbtxt index ba5131c85e..c285ada012 100644 --- a/tensorflow/core/api_def/java_api/api_def_TensorSummaryV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TensorSummaryV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "TensorSummaryV2" endpoint { - name: "summary.TensorSummaryV2" + name: "summary.TensorSummary" } } diff --git a/tensorflow/core/api_def/java_api/api_def_TextLineReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_TextLineReader.pbtxt index 17eb20cffe..f86b15cf86 100644 --- a/tensorflow/core/api_def/java_api/api_def_TextLineReader.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TextLineReader.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "TextLineReader" - endpoint { - name: "io.TextLineReader" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TextLineReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TextLineReaderV2.pbtxt index 745c85fac9..ee57dd8408 100644 --- a/tensorflow/core/api_def/java_api/api_def_TextLineReaderV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TextLineReaderV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "TextLineReaderV2" endpoint { - name: "io.TextLineReaderV2" + name: "io.TextLineReader" } } diff --git a/tensorflow/core/api_def/java_api/api_def_TopK.pbtxt b/tensorflow/core/api_def/java_api/api_def_TopK.pbtxt index 108701adf1..bb090aa6f1 100644 --- a/tensorflow/core/api_def/java_api/api_def_TopK.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TopK.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "TopK" - endpoint { - name: "nn.TopK" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt index 2aa89adcce..2b0dcf7c2a 100644 --- a/tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_TopKV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "TopKV2" endpoint { - name: "nn.TopKV2" + name: "nn.TopK" } } diff --git a/tensorflow/core/api_def/java_api/api_def_Unique.pbtxt b/tensorflow/core/api_def/java_api/api_def_Unique.pbtxt index 5c4262b5fb..8cc8ec0fed 100644 --- a/tensorflow/core/api_def/java_api/api_def_Unique.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Unique.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "Unique" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt index 4d43500a0d..6fe22cb102 100644 --- a/tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_UniqueV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "UniqueV2" + endpoint { + name: "Unique" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_UniqueWithCounts.pbtxt b/tensorflow/core/api_def/java_api/api_def_UniqueWithCounts.pbtxt index 1ce5314157..0248fab17e 100644 --- a/tensorflow/core/api_def/java_api/api_def_UniqueWithCounts.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_UniqueWithCounts.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "UniqueWithCounts" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt index abfd496b8e..eb15745114 100644 --- a/tensorflow/core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_UniqueWithCountsV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "UniqueWithCountsV2" + endpoint { + name: "UniqueWithCounts" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_Variable.pbtxt b/tensorflow/core/api_def/java_api/api_def_Variable.pbtxt index abc2f9c954..0978e61451 100644 --- a/tensorflow/core/api_def/java_api/api_def_Variable.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Variable.pbtxt @@ -1,3 +1,4 @@ op { graph_op_name: "Variable" + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt index 221a80f760..c566dd1e79 100644 --- a/tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_VariableV2.pbtxt @@ -1,3 +1,6 @@ op { graph_op_name: "VariableV2" + endpoint { + name: "Variable" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_WholeFileReader.pbtxt b/tensorflow/core/api_def/java_api/api_def_WholeFileReader.pbtxt index 67a8933efb..aa839ed380 100644 --- a/tensorflow/core/api_def/java_api/api_def_WholeFileReader.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_WholeFileReader.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "WholeFileReader" - endpoint { - name: "io.WholeFileReader" - } + visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt index 172268a122..e031d705fb 100644 --- a/tensorflow/core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_WholeFileReaderV2.pbtxt @@ -1,6 +1,6 @@ op { graph_op_name: "WholeFileReaderV2" endpoint { - name: "io.WholeFileReaderV2" + name: "io.WholeFileReader" } } -- GitLab From 937ec3a54b5a6d35a61e690b24c040bb52fc9a9d Mon Sep 17 00:00:00 2001 From: Karl Lessard Date: Thu, 29 Nov 2018 00:10:31 -0500 Subject: [PATCH 0039/1765] Replace PlaceholderV2 by Placeholder, since V2 is not supported anymore. --- tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt | 1 - tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt b/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt index efea7bd2b1..5e6daa2ae4 100644 --- a/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Placeholder.pbtxt @@ -1,4 +1,3 @@ op { graph_op_name: "Placeholder" - visibility: SKIP } diff --git a/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt index a61f6f4d1e..419bdf10f7 100644 --- a/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_PlaceholderV2.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "PlaceholderV2" - endpoint { - name: "Placeholder" - } + visibility: SKIP } -- GitLab From 797c781499552cdd6790be0e73e06811fce78be7 Mon Sep 17 00:00:00 2001 From: Karl Lessard Date: Thu, 29 Nov 2018 00:15:55 -0500 Subject: [PATCH 0040/1765] Restore Add over AddV2, since gradients are not computed for the later. --- tensorflow/core/api_def/java_api/api_def_Add.pbtxt | 4 +++- tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tensorflow/core/api_def/java_api/api_def_Add.pbtxt b/tensorflow/core/api_def/java_api/api_def_Add.pbtxt index b082b055bf..4f78ccc9ea 100644 --- a/tensorflow/core/api_def/java_api/api_def_Add.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_Add.pbtxt @@ -1,4 +1,6 @@ op { graph_op_name: "Add" - visibility: SKIP + endpoint { + name: "math.Add" + } } diff --git a/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt b/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt index 863ec4f33c..a070c6a519 100644 --- a/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt +++ b/tensorflow/core/api_def/java_api/api_def_AddV2.pbtxt @@ -1,6 +1,4 @@ op { graph_op_name: "AddV2" - endpoint { - name: "math.Add" - } + visibility: SKIP } -- GitLab From d45cd461242e3a27e505a67c17d5ddb7f4a84641 Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Fri, 30 Nov 2018 14:46:12 +0100 Subject: [PATCH 0041/1765] Add drop_remainder argument to bucket_by_sequence_length `tf.data.experimental.bucket_by_sequence_length` does not allow to drop the last batch in case it has fewer than `batch_size` elements. This patch does implement `drop_remainder` for `bucket_by_sequence_length` to enable thhis behaviour. `drop_remainder` is optinal and set to `False` by default to maintain compatibility. --- tensorflow/python/data/experimental/ops/grouping.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tensorflow/python/data/experimental/ops/grouping.py b/tensorflow/python/data/experimental/ops/grouping.py index db10ea3b7f..71e4b3391f 100644 --- a/tensorflow/python/data/experimental/ops/grouping.py +++ b/tensorflow/python/data/experimental/ops/grouping.py @@ -130,7 +130,8 @@ def bucket_by_sequence_length(element_length_func, padded_shapes=None, padding_values=None, pad_to_bucket_boundary=False, - no_padding=False): + no_padding=False, + drop_remainder=False): """A transformation that buckets elements in a `Dataset` by length. Elements of the `Dataset` are grouped together by length and then are padded @@ -160,6 +161,10 @@ def bucket_by_sequence_length(element_length_func, any elements with length longer than `max(bucket_boundaries)`. no_padding: `bool`, indicates whether to pad the batch features (features need to be either of type `tf.SparseTensor` or of same shape). + drop_remainder: (Optional.) A `tf.bool` scalar `tf.Tensor`, representing + whether the last batch should be dropped in the case its has fewer than + batch_size` elements; the default behavior is not to drop the smaller + batch. Returns: A `Dataset` transformation function, which can be passed to @@ -209,7 +214,7 @@ def bucket_by_sequence_length(element_length_func, """Batch elements in dataset.""" batch_size = window_size_fn(bucket_id) if no_padding: - return grouped_dataset.batch(batch_size) + return grouped_dataset.batch(batch_size, drop_remainder=drop_remainder) none_filler = None if pad_to_bucket_boundary: err_msg = ("When pad_to_bucket_boundary=True, elements must have " @@ -227,7 +232,8 @@ def bucket_by_sequence_length(element_length_func, shapes = make_padded_shapes( padded_shapes or grouped_dataset.output_shapes, none_filler=none_filler) - return grouped_dataset.padded_batch(batch_size, shapes, padding_values) + return grouped_dataset.padded_batch(batch_size, shapes, padding_values, + drop_remainder=drop_remainder) def _apply_fn(dataset): return dataset.apply( -- GitLab From 8c438f4a2dfeaa4622fce5d034791f05af8f7db7 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Sat, 1 Dec 2018 22:11:18 +0000 Subject: [PATCH 0042/1765] Fix warning caused by keep_dims in sparse_grad.py While running tests, noticed the following warning: ``` ... tensorflow/python/ops/sparse_grad.py:281: calling sparse_reduce_sum (from tensorflow.python.ops.sparse_ops) with keep_dims is deprecated and will be removed in a future version. Instructions for updating: keep_dims is deprecated, use keepdims instead ``` This fix fixes the warning. Signed-off-by: Yong Tang --- tensorflow/python/ops/sparse_grad.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/python/ops/sparse_grad.py b/tensorflow/python/ops/sparse_grad.py index 2ca9c0c647..bef0a8ea4e 100644 --- a/tensorflow/python/ops/sparse_grad.py +++ b/tensorflow/python/ops/sparse_grad.py @@ -278,7 +278,7 @@ def _SparseSoftmaxGrad(op, grad): indices, sp_output.values * sp_grad.values, shape) # [..., B, 1], dense. - sum_reduced = -sparse_ops.sparse_reduce_sum(sp_product, [-1], keep_dims=True) + sum_reduced = -sparse_ops.sparse_reduce_sum(sp_product, [-1], keepdims=True) # sparse [..., B, C] + dense [..., B, 1] with broadcast; outputs sparse. sp_sum = sparse_ops.sparse_dense_cwise_add(sp_grad, sum_reduced) -- GitLab From 916c5238d864e04861a58b3f77b9d29cca03b0e0 Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Sun, 2 Dec 2018 18:27:55 +0100 Subject: [PATCH 0043/1765] Add drop_reminder support to the test of bucketing of sparse tensors --- .../bucket_by_sequence_length_test.py | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py index af20e50fb9..fb2d1cf63c 100644 --- a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py @@ -274,11 +274,16 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): dataset = dataset.map(_to_sparse_tensor) return dataset - def _compute_expected_batches(): + def _compute_expected_batches(drop_remainder): """Computes expected batch outputs and stores in a set.""" all_expected_sparse_tensors = set() for bucket_start_len in range(min_len, max_len, bucket_size): - for batch_offset in range(0, bucket_size, batch_size): + if drop_remainder: + batch_offsets = [0] + else: + batch_offsets = range(0, bucket_size, batch_size) + + for batch_offset in batch_offsets: batch_start_len = bucket_start_len + batch_offset batch_end_len = min(batch_start_len + batch_size, bucket_start_len + bucket_size) @@ -306,16 +311,18 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): all_sparse_tensors.add(sprs_tensor) return all_sparse_tensors - dataset = _build_dataset() - boundaries = range(min_len + bucket_size + 1, max_len, bucket_size) - dataset = dataset.apply(grouping.bucket_by_sequence_length( - _element_length_fn, - boundaries, - [batch_size] * (len(boundaries) + 1), - no_padding=True)) - batches = _compute_batches(dataset) - expected_batches = _compute_expected_batches() - self.assertEqual(batches, expected_batches) + for drop_remainder in (True, False): + dataset = _build_dataset() + boundaries = range(min_len + bucket_size + 1, max_len, bucket_size) + dataset = dataset.apply(grouping.bucket_by_sequence_length( + _element_length_fn, + boundaries, + [batch_size] * (len(boundaries) + 1), + no_padding=True, + drop_remainder=drop_remainder)) + batches = _compute_batches(dataset) + expected_batches = _compute_expected_batches() + self.assertEqual(batches, expected_batches) if __name__ == "__main__": -- GitLab From d372f19f132e8f037390a9a2a6fde7bafa2620b9 Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Sun, 2 Dec 2018 18:29:03 +0100 Subject: [PATCH 0044/1765] Add a drop_reminder version of the testBucket test Squeezing both cases into a single test would make it way to complicated. Therefore, I created a separate test. --- .../bucket_by_sequence_length_test.py | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py index fb2d1cf63c..7b2e922d55 100644 --- a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py @@ -71,6 +71,117 @@ def _get_record_shape(sparse): class BucketBySequenceLengthTest(test_base.DatasetTestBase): + def testBucketDropReminder(self): + + boundaries = [10, 20, 30] + batch_sizes = [10, 8, 4, 2] + lengths = [8, 13, 25, 35] + + n_bucket_elements = [28, 7, 6, 5] + n_expected_batches = 5 + + # Expected sequence lengths of the individual batches. + expected_lengths = [] + + # Expected sum of all batches with an equal sequence length. + # : + expected_sums = dict() + + # Expected batch sizes of batches depending on the sequence length. + # : [batch1_size, ..., batchN_size] + expected_batch_sizes = dict() + + for length, batch_size, bucket_elements in zip(lengths, batch_sizes, n_bucket_elements): + # Calculate the expected sum across all batches of a specific sequence length. + expected_sums[length] = (bucket_elements - bucket_elements % batch_size) * length + # Calculate the expected occurrence of individual batch sizes. + expected_batch_sizes[length] = [batch_size] * (bucket_elements // batch_size) + # Calculate the expected occurence of individual sequence lengths. + expected_lengths.extend([length] * (bucket_elements // batch_size)) + + def build_dataset(sparse): + def _generator(): + # Produce 1 batch for each bucket + elements = [] + for bucket_elements, length in zip(n_bucket_elements, lengths): + # Using only full sequences (opposed to the strategy employed in `testBucket`) makes + # checking the sum a lot easier. + record_len = length + for _ in range(bucket_elements): + elements.append([1] * record_len) + random.shuffle(elements) + for el in elements: + yield (_format_record(el, sparse),) + dataset = dataset_ops.Dataset.from_generator( + _generator, + (_get_record_type(sparse),), + (_get_record_shape(sparse),)) + if sparse: + dataset = dataset.map(lambda x: (_to_sparse_tensor(x),)) + return dataset + + def _test_bucket_by_padding(no_padding): + dataset = build_dataset(sparse=no_padding) + dataset = dataset.apply( + grouping.bucket_by_sequence_length( + _element_length_fn, + boundaries, + batch_sizes, + no_padding=no_padding, + drop_remainder=True)) + batch, = dataset.make_one_shot_iterator().get_next() + + with self.cached_session() as sess: + batches = [] + for _ in range(n_expected_batches): + batches.append(self.evaluate(batch)) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(batch) + + generated_lengths = [] + + # : + generated_sums = dict() + + # : [, ...] + generated_batch_sizes = dict() + + for length, batch_size, bucket_elements in zip(lengths, batch_sizes, n_bucket_elements): + # Initialize the sum across all batches. + expected_sums[length] = 0 + # Initialize the individual batch sizes. + expected_batch_sizes[length] = [] + + for batch in batches: + shape = batch.dense_shape if no_padding else batch.shape + length = shape[1] + generated_lengths.append(length) + + batch_size = shape[0] + generated_batch_sizes[length].append(batch_size) + + batch_sum = batch.values.sum() if no_padding else batch.sum() + generated_sums[length] += batch_sum + + for l in lengths: + # Make sure the sum of the batch contents is correct for the individual sequence lengths. + self.assertEqual(generated_sums[l], expected_sums[l], + 'Tensor sums did not match! expected: {}, generated: {}' + .format(expected_sums, generated_sums)) + + # Make sure the individual batch sizes are generated as expected. + self.assertEqual(sorted(generated_batch_sizes[l]), sorted(expected_batch_sizes[l]), + 'Batch-sizes did not match! expected: {}, generated: {}' + .format(sorted(expected_batch_sizes[l]), sorted(generated_batch_sizes[l]))) + + # Make sure the generated sequence lengths appear as often as expected. + self.assertEqual(sorted(generated_lengths), sorted(expected_lengths), + 'The generated sequence lengths did not match! expected: {}, generated: {}' + .format(sorted(expected_lengths), sorted(generated_lengths))) + + for no_padding in (True, False): + _test_bucket_by_padding(no_padding) + def testBucket(self): boundaries = [10, 20, 30] -- GitLab From 68426789549cb9d2edc8726fc5edabf4f221bd9b Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Sun, 2 Dec 2018 18:40:12 +0100 Subject: [PATCH 0045/1765] Fix pylint warnings * Missing argument drop_remainder in the testBucketSparse test. * Insert line breaks --- .../bucket_by_sequence_length_test.py | 45 ++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py index 7b2e922d55..5b96101b7c 100644 --- a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py @@ -91,11 +91,15 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): # : [batch1_size, ..., batchN_size] expected_batch_sizes = dict() - for length, batch_size, bucket_elements in zip(lengths, batch_sizes, n_bucket_elements): + for length, batch_size, bucket_elements in zip(lengths, + batch_sizes, + n_bucket_elements): # Calculate the expected sum across all batches of a specific sequence length. - expected_sums[length] = (bucket_elements - bucket_elements % batch_size) * length + expected_sums[length] = \ + (bucket_elements - bucket_elements % batch_size) * length # Calculate the expected occurrence of individual batch sizes. - expected_batch_sizes[length] = [batch_size] * (bucket_elements // batch_size) + expected_batch_sizes[length] = \ + [batch_size] * (bucket_elements // batch_size) # Calculate the expected occurence of individual sequence lengths. expected_lengths.extend([length] * (bucket_elements // batch_size)) @@ -146,11 +150,13 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): # : [, ...] generated_batch_sizes = dict() - for length, batch_size, bucket_elements in zip(lengths, batch_sizes, n_bucket_elements): - # Initialize the sum across all batches. - expected_sums[length] = 0 - # Initialize the individual batch sizes. - expected_batch_sizes[length] = [] + for length, batch_size, bucket_elements in zip(lengths, + batch_sizes, + n_bucket_elements): + # Initialize the sum across all batches. + expected_sums[length] = 0 + # Initialize the individual batch sizes. + expected_batch_sizes[length] = [] for batch in batches: shape = batch.dense_shape if no_padding else batch.shape @@ -165,19 +171,26 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): for l in lengths: # Make sure the sum of the batch contents is correct for the individual sequence lengths. - self.assertEqual(generated_sums[l], expected_sums[l], - 'Tensor sums did not match! expected: {}, generated: {}' + self.assertEqual(generated_sums[l], + expected_sums[l], + 'Tensor sums did not match! ' + 'expected: {}, generated: {}' .format(expected_sums, generated_sums)) # Make sure the individual batch sizes are generated as expected. - self.assertEqual(sorted(generated_batch_sizes[l]), sorted(expected_batch_sizes[l]), - 'Batch-sizes did not match! expected: {}, generated: {}' - .format(sorted(expected_batch_sizes[l]), sorted(generated_batch_sizes[l]))) + self.assertEqual(sorted(generated_batch_sizes[l]), + sorted(expected_batch_sizes[l]), + 'Batch-sizes did not match! ' + 'expected: {}, generated: {}' + .format(sorted(expected_batch_sizes[l]), + sorted(generated_batch_sizes[l]))) # Make sure the generated sequence lengths appear as often as expected. self.assertEqual(sorted(generated_lengths), sorted(expected_lengths), - 'The generated sequence lengths did not match! expected: {}, generated: {}' - .format(sorted(expected_lengths), sorted(generated_lengths))) + 'The generated sequence lengths did not match! ' + 'expected: {}, generated: {}' + .format(sorted(expected_lengths), + sorted(generated_lengths))) for no_padding in (True, False): _test_bucket_by_padding(no_padding) @@ -432,7 +445,7 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): no_padding=True, drop_remainder=drop_remainder)) batches = _compute_batches(dataset) - expected_batches = _compute_expected_batches() + expected_batches = _compute_expected_batches(drop_remainder) self.assertEqual(batches, expected_batches) -- GitLab From 4ddd2ab07fdfea81a53d110fee19bb88c41251a0 Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Mon, 3 Dec 2018 13:58:58 +0100 Subject: [PATCH 0046/1765] Fix copy paste bug Pasted the wrong variable names from the docker test image. --- .../kernel_tests/bucket_by_sequence_length_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py index 5b96101b7c..fab79619a0 100644 --- a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py @@ -154,9 +154,9 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): batch_sizes, n_bucket_elements): # Initialize the sum across all batches. - expected_sums[length] = 0 + generated_sums[length] = 0 # Initialize the individual batch sizes. - expected_batch_sizes[length] = [] + generated_batch_sizes[length] = [] for batch in batches: shape = batch.dense_shape if no_padding else batch.shape -- GitLab From 4925226ba86fcd62431de2ea7eee9ce8c5ee91e1 Mon Sep 17 00:00:00 2001 From: Jakub Lipinski Date: Wed, 5 Dec 2018 13:30:24 +0100 Subject: [PATCH 0047/1765] remove hardcoded output size calculate output size based on the output tensor dimensions --- .../examples/ios/camera/CameraExampleViewController.mm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tensorflow/lite/examples/ios/camera/CameraExampleViewController.mm b/tensorflow/lite/examples/ios/camera/CameraExampleViewController.mm index a3e6e11095..8b192fb5a4 100644 --- a/tensorflow/lite/examples/ios/camera/CameraExampleViewController.mm +++ b/tensorflow/lite/examples/ios/camera/CameraExampleViewController.mm @@ -326,7 +326,13 @@ void ProcessInputWithQuantizedModel( NSLog(@"Time: %.4lf, avg: %.4lf, count: %d", end - start, total_latency / total_count, total_count); - const int output_size = 1000; + // read output size from the output sensor + const int output_tensor_index = interpreter->outputs()[0]; + TfLiteTensor* output_tensor = interpreter->tensor(output_tensor_index); + TfLiteIntArray* output_dims = output_tensor->dims; + assert(output_dims->size == 2); + const int output_size = output_dims->data[1]-output_dims->data[0]; + const int kNumResults = 5; const float kThreshold = 0.1f; -- GitLab From 9caf68cf7b47fb94ac4f574772bf5efdb5785555 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Tue, 6 Nov 2018 12:47:02 -0600 Subject: [PATCH 0048/1765] Ambiq squashed commits --- .../ISSUE_TEMPLATE/40-tflite-op-request.md | 24 + README.md | 6 +- WORKSPACE | 22 +- configure.py | 22 +- tensorflow/BUILD | 38 +- tensorflow/api_template.__init__.py | 12 +- tensorflow/c/BUILD | 62 +- tensorflow/c/c_api_experimental.cc | 130 +- tensorflow/c/c_api_experimental.h | 37 + tensorflow/c/c_api_experimental_test.cc | 134 + tensorflow/c/c_api_function.cc | 22 +- tensorflow/c/eager/BUILD | 2 + tensorflow/c/eager/c_api.cc | 49 +- tensorflow/c/eager/c_api.h | 23 + tensorflow/c/eager/c_api_internal.h | 7 +- tensorflow/c/eager/c_api_test.cc | 80 +- tensorflow/c/eager/c_api_test_util.cc | 13 + tensorflow/c/eager/c_api_test_util.h | 3 + tensorflow/c/eager/tape.h | 23 +- tensorflow/c/kernels.cc | 143 + tensorflow/c/kernels.h | 110 + tensorflow/c/kernels_test.cc | 194 + tensorflow/c/python_api.cc | 13 + tensorflow/c/python_api.h | 8 + tensorflow/cc/BUILD | 1 + tensorflow/cc/saved_model/BUILD | 1 + tensorflow/cc/saved_model/constants.h | 9 +- tensorflow/cc/saved_model/loader.cc | 84 +- tensorflow/cc/saved_model/loader_test.cc | 14 + .../half_plus_two_v2/00000123/assets/foo.txt | 1 + .../half_plus_two_v2/00000123/saved_model.pb | Bin 0 -> 10774 bytes .../variables/variables.data-00000-of-00001 | Bin 0 -> 12 bytes .../00000123/variables/variables.index | Bin 0 -> 151 bytes tensorflow/compiler/aot/codegen.cc | 30 +- tensorflow/compiler/aot/codegen.h | 2 +- tensorflow/compiler/aot/codegen_test.cc | 16 +- tensorflow/compiler/aot/codegen_test_h.golden | 16 +- tensorflow/compiler/aot/codegen_test_o.golden | Bin 712 -> 720 bytes tensorflow/compiler/aot/compile.cc | 20 +- tensorflow/compiler/aot/compile.h | 6 +- .../compiler/aot/tests/tfcompile_test.cc | 10 +- tensorflow/compiler/jit/BUILD | 28 +- tensorflow/compiler/jit/build_xla_ops_pass.cc | 10 +- .../compiler/jit/build_xla_ops_pass_test.cc | 8 +- .../compiler/jit/create_xla_launch_op_test.cc | 6 +- tensorflow/compiler/jit/encapsulate_util.cc | 325 +- tensorflow/compiler/jit/encapsulate_util.h | 97 +- .../compiler/jit/encapsulate_util_test.cc | 67 +- .../jit/encapsulate_xla_computations_pass.cc | 7 +- .../jit/extract_outside_compilation_pass.cc | 16 +- .../extract_outside_compilation_pass_test.cc | 15 +- tensorflow/compiler/jit/flags.cc | 152 + ...k_for_compilation_pass_flags.h => flags.h} | 65 +- .../increase_dynamism_for_auto_jit_pass.cc | 56 +- ...ncrease_dynamism_for_auto_jit_pass_test.cc | 130 +- tensorflow/compiler/jit/kernels/BUILD | 2 +- tensorflow/compiler/jit/kernels/xla_ops.cc | 4 +- tensorflow/compiler/jit/legacy_flags/BUILD | 65 - .../legacy_flags/build_xla_ops_pass_flags.cc | 47 - .../legacy_flags/build_xla_ops_pass_flags.h | 37 - .../mark_for_compilation_pass_flags.cc | 98 - .../jit/legacy_flags/xla_device_flags.cc | 56 - .../jit/legacy_flags/xla_device_flags.h | 47 - .../jit/legacy_flags/xla_ops_common_flags.cc | 52 - .../jit/legacy_flags/xla_ops_common_flags.h | 36 - .../compiler/jit/mark_for_compilation_pass.cc | 53 +- .../jit/mark_for_compilation_pass_test.cc | 76 + .../mark_for_compilation_pass_test_helper.cc | 8 +- tensorflow/compiler/jit/ops/BUILD | 6 + .../jit/ops/xla_ops_grad.py} | 19 +- .../compiler/jit/partially_decluster_pass.cc | 19 +- .../jit/partially_decluster_pass_test.cc | 6 +- tensorflow/compiler/jit/xla_cpu_device.cc | 15 +- tensorflow/compiler/jit/xla_device.cc | 82 +- tensorflow/compiler/jit/xla_device.h | 29 + tensorflow/compiler/jit/xla_gpu_device.cc | 10 +- .../compiler/jit/xla_interpreter_device.cc | 7 +- tensorflow/compiler/tests/BUILD | 22 - tensorflow/compiler/tests/adagrad_da_test.py | 32 +- tensorflow/compiler/tests/adagrad_test.py | 30 +- tensorflow/compiler/tests/adam_test.py | 39 +- tensorflow/compiler/tests/adamax_test.py | 24 +- tensorflow/compiler/tests/addsign_test.py | 8 +- tensorflow/compiler/tests/binary_ops_test.py | 15 + .../compiler/tests/categorical_op_test.py | 68 +- tensorflow/compiler/tests/clustering_test.py | 4 +- tensorflow/compiler/tests/concat_ops_test.py | 32 +- tensorflow/compiler/tests/conv3d_test.py | 6 +- tensorflow/compiler/tests/dense_layer_test.py | 8 +- .../compiler/tests/dynamic_stitch_test.py | 9 + tensorflow/compiler/tests/eager_test.py | 4 +- tensorflow/compiler/tests/fft_test.py | 68 +- tensorflow/compiler/tests/fifo_queue_test.py | 6 +- tensorflow/compiler/tests/ftrl_test.py | 84 +- tensorflow/compiler/tests/function_test.py | 12 +- tensorflow/compiler/tests/jit_test.py | 2 +- tensorflow/compiler/tests/listdiff_op_test.py | 4 +- tensorflow/compiler/tests/lrn_ops_test.py | 4 +- tensorflow/compiler/tests/lstm_test.py | 8 +- tensorflow/compiler/tests/momentum_test.py | 64 +- tensorflow/compiler/tests/placeholder_test.py | 2 +- tensorflow/compiler/tests/powersign_test.py | 8 +- .../compiler/tests/proximal_adagrad_test.py | 40 +- .../tests/proximal_gradient_descent_test.py | 38 +- tensorflow/compiler/tests/qr_op_test.py | 2 +- tensorflow/compiler/tests/random_ops_test.py | 16 +- tensorflow/compiler/tests/randomized_tests.cc | 4 +- tensorflow/compiler/tests/reduce_ops_test.py | 6 + tensorflow/compiler/tests/rmsprop_test.py | 24 +- tensorflow/compiler/tests/scan_ops_test.py | 4 +- .../tests/stateless_random_ops_test.py | 2 +- .../compiler/tests/tensor_array_ops_test.py | 27 +- tensorflow/compiler/tests/unary_ops_test.py | 66 + .../compiler/tests/variable_ops_test.py | 42 +- tensorflow/compiler/tests/xla_device_test.py | 2 +- tensorflow/compiler/tf2xla/BUILD | 16 +- tensorflow/compiler/tf2xla/dump_graph.cc | 77 +- .../compiler/tf2xla/dump_graph_flags.cc | 63 - tensorflow/compiler/tf2xla/dump_graph_flags.h | 48 - .../tf2xla/functionalize_control_flow.cc | 19 + .../tf2xla/functionalize_control_flow.h | 6 + .../tf2xla/functionalize_control_flow_test.cc | 1013 +- tensorflow/compiler/tf2xla/kernels/BUILD | 5 +- tensorflow/compiler/tf2xla/kernels/arg_op.cc | 2 +- .../tf2xla/kernels/batch_matmul_op.cc | 12 +- .../compiler/tf2xla/kernels/batch_norm_op.cc | 15 +- .../compiler/tf2xla/kernels/bias_ops.cc | 4 +- .../compiler/tf2xla/kernels/binary_ops.cc | 19 +- .../compiler/tf2xla/kernels/categorical_op.cc | 68 +- .../tf2xla/kernels/conv_op_helpers.cc | 78 +- .../compiler/tf2xla/kernels/conv_ops.cc | 2 +- tensorflow/compiler/tf2xla/kernels/diag_op.cc | 2 +- .../tf2xla/kernels/dynamic_stitch_op.cc | 25 +- .../kernels/extract_image_patches_op.cc | 1 - .../tf2xla/kernels/fake_quantize_ops.cc | 8 +- tensorflow/compiler/tf2xla/kernels/fft_ops.cc | 28 +- tensorflow/compiler/tf2xla/kernels/if_op.cc | 2 +- .../compiler/tf2xla/kernels/image_ops.cc | 5 +- .../tf2xla/kernels/image_resize_ops.cc | 1 - .../compiler/tf2xla/kernels/index_ops_cpu.cc | 70 +- .../compiler/tf2xla/kernels/l2loss_op.cc | 5 +- tensorflow/compiler/tf2xla/kernels/lrn_ops.cc | 17 +- .../tf2xla/kernels/matrix_band_part_op.cc | 10 +- .../tf2xla/kernels/matrix_set_diag_op.cc | 1 - .../compiler/tf2xla/kernels/permute_op.cc | 3 +- .../compiler/tf2xla/kernels/pooling_ops.cc | 31 +- .../kernels/quantize_and_dequantize_op.cc | 43 +- .../compiler/tf2xla/kernels/random_ops.cc | 1 - .../compiler/tf2xla/kernels/reduction_ops.cc | 21 +- .../compiler/tf2xla/kernels/reduction_ops.h | 15 +- .../tf2xla/kernels/reduction_ops_common.cc | 18 +- .../compiler/tf2xla/kernels/resampler_ops.cc | 83 +- .../compiler/tf2xla/kernels/retval_op.cc | 3 +- .../tf2xla/kernels/reverse_sequence_op.cc | 1 - .../compiler/tf2xla/kernels/scan_ops.cc | 11 +- .../compiler/tf2xla/kernels/sendrecv_ops.cc | 4 +- .../compiler/tf2xla/kernels/sequence_ops.cc | 2 +- .../compiler/tf2xla/kernels/softmax_op.cc | 15 +- .../compiler/tf2xla/kernels/stack_ops.cc | 19 +- .../tf2xla/kernels/stateless_random_ops.cc | 1 - .../tf2xla/kernels/tensor_array_ops.cc | 33 +- tensorflow/compiler/tf2xla/kernels/topk_op.cc | 1 - .../compiler/tf2xla/kernels/training_ops.cc | 3 +- .../compiler/tf2xla/kernels/while_op.cc | 2 +- .../tf2xla/kernels/xla_broadcast_helper_op.cc | 7 +- tensorflow/compiler/tf2xla/lib/BUILD | 49 +- tensorflow/compiler/tf2xla/lib/batch_dot.cc | 115 - tensorflow/compiler/tf2xla/lib/batch_dot.h | 54 - tensorflow/compiler/tf2xla/lib/broadcast.cc | 6 +- tensorflow/compiler/tf2xla/lib/cholesky.cc | 17 +- tensorflow/compiler/tf2xla/lib/qr.cc | 35 +- .../compiler/tf2xla/lib/triangular_solve.cc | 28 +- tensorflow/compiler/tf2xla/lib/util.cc | 126 - tensorflow/compiler/tf2xla/lib/util.h | 34 - tensorflow/compiler/tf2xla/python/BUILD | 10 +- tensorflow/compiler/tf2xla/shape_util.h | 1 + .../tf2xla/xla_compiled_cpu_function.h | 25 +- tensorflow/compiler/tf2xla/xla_compiler.cc | 81 +- tensorflow/compiler/tf2xla/xla_compiler.h | 2 +- .../compiler/tf2xla/xla_compiler_test.cc | 83 +- tensorflow/compiler/tf2xla/xla_context.cc | 35 +- tensorflow/compiler/tf2xla/xla_context.h | 32 +- tensorflow/compiler/tf2xla/xla_helpers.cc | 4 +- tensorflow/compiler/tf2xla/xla_helpers.h | 3 +- .../tf2xla/xla_jit_compiled_cpu_function.cc | 3 +- .../tf2xla/xla_jit_compiled_cpu_function.h | 6 +- .../xla_jit_compiled_cpu_function_test.cc | 12 +- tensorflow/compiler/tf2xla/xla_op_kernel.cc | 55 +- tensorflow/compiler/tf2xla/xla_op_kernel.h | 2 + tensorflow/compiler/tf2xla/xla_op_registry.cc | 5 +- tensorflow/compiler/tf2xla/xla_resource.cc | 35 +- tensorflow/compiler/tf2xla/xla_resource.h | 19 +- tensorflow/compiler/xla/BUILD | 21 + tensorflow/compiler/xla/array2d.h | 2 +- tensorflow/compiler/xla/client/BUILD | 5 +- tensorflow/compiler/xla/client/client.cc | 18 +- .../xla/client/executable_build_options.cc | 68 +- .../xla/client/executable_build_options.h | 50 +- tensorflow/compiler/xla/client/lib/BUILD | 57 +- tensorflow/compiler/xla/client/lib/math.cc | 26 +- tensorflow/compiler/xla/client/lib/math.h | 4 + tensorflow/compiler/xla/client/lib/matrix.cc | 185 + .../xla/client/lib/{numeric.h => matrix.h} | 37 +- .../lib/{numeric_test.cc => matrix_test.cc} | 51 +- tensorflow/compiler/xla/client/lib/numeric.cc | 89 - tensorflow/compiler/xla/client/lib/prng.cc | 1 - tensorflow/compiler/xla/client/lib/slicing.cc | 134 + tensorflow/compiler/xla/client/lib/slicing.h | 48 + .../client/lib/slicing_test.cc} | 48 +- tensorflow/compiler/xla/client/lib/sorting.cc | 13 +- .../compiler/xla/client/lib/sorting_test.cc | 33 + tensorflow/compiler/xla/client/lib/testing.cc | 6 +- .../compiler/xla/client/local_client.cc | 24 + tensorflow/compiler/xla/client/local_client.h | 4 + .../compiler/xla/client/sharding_builder.cc | 4 +- tensorflow/compiler/xla/client/xla_builder.cc | 353 +- tensorflow/compiler/xla/client/xla_builder.h | 320 +- .../compiler/xla/client/xla_builder_test.cc | 13 +- .../compiler/xla/client/xla_computation.cc | 2 +- .../compiler/xla/client/xla_computation.h | 1 + .../compiler/xla/debug_options_flags.cc | 14 +- .../experimental/xla_sharding/xla_sharding.py | 30 +- tensorflow/compiler/xla/g3doc/_book.yaml | 12 +- tensorflow/compiler/xla/g3doc/_index.yaml | 4 +- .../g3doc/images/xla_array_layout_figure1.png | Bin 0 -> 20398 bytes .../g3doc/images/xla_array_layout_figure2.png | Bin 0 -> 7913 bytes tensorflow/compiler/xla/g3doc/jit.md | 4 +- .../compiler/xla/g3doc/layout_with_tiling.md | 159 + .../compiler/xla/g3doc/operation_semantics.md | 55 +- .../xla/g3doc/tutorials/xla_compile.ipynb | 301 +- tensorflow/compiler/xla/index_util.h | 1 + tensorflow/compiler/xla/layout_util.cc | 7 + tensorflow/compiler/xla/layout_util.h | 1 + tensorflow/compiler/xla/literal.cc | 318 +- tensorflow/compiler/xla/literal.h | 2 +- tensorflow/compiler/xla/literal_test.cc | 201 +- .../compiler/xla/parse_flags_from_env.cc | 116 +- .../compiler/xla/parse_flags_from_env.h | 56 +- .../compiler/xla/parse_flags_from_env_test.cc | 20 +- tensorflow/compiler/xla/protobuf_util.cc | 10 - .../xla/python/local_computation_builder.cc | 174 +- .../xla/python/local_computation_builder.h | 12 +- .../xla/python/local_computation_builder.i | 43 +- tensorflow/compiler/xla/python/xla_client.py | 138 +- .../compiler/xla/python_api/xla_shape.py | 7 +- tensorflow/compiler/xla/rpc/BUILD | 1 - tensorflow/compiler/xla/rpc/xla_service.proto | 1 - tensorflow/compiler/xla/service/BUILD | 148 +- .../xla/service/algebraic_simplifier.cc | 360 +- .../xla/service/algebraic_simplifier.h | 79 +- ..._simplifier_proof_distributive_property.py | 82 + .../xla/service/algebraic_simplifier_test.cc | 1176 +- .../compiler/xla/service/ar_crs_combiner.cc | 286 + .../compiler/xla/service/ar_crs_combiner.h | 88 + .../xla/service/ar_crs_combiner_test.cc | 415 + .../xla/service/batchnorm_expander.cc | 65 +- .../xla/service/batchnorm_expander_test.cc | 18 +- .../compiler/xla/service/buffer_assignment.cc | 56 +- .../compiler/xla/service/buffer_assignment.h | 10 +- .../xla/service/buffer_assignment_test.cc | 18 +- .../xla/service/buffer_liveness_test.cc | 28 +- tensorflow/compiler/xla/service/call_graph.cc | 9 + tensorflow/compiler/xla/service/call_graph.h | 4 + .../xla/service/compile_only_service.cc | 8 +- .../compiler/xla/service/computation_placer.h | 2 - .../convolution_feature_group_converter.cc | 253 +- ...onvolution_feature_group_converter_test.cc | 20 +- .../compiler/xla/service/copy_insertion.cc | 2 - .../xla/service/copy_insertion_test.cc | 44 +- tensorflow/compiler/xla/service/cpu/BUILD | 1 + .../xla/service/cpu/compiler_functor.cc | 16 +- .../compiler/xla/service/cpu/cpu_compiler.cc | 27 +- .../xla/service/cpu/cpu_executable.cc | 3 +- .../compiler/xla/service/cpu/cpu_executable.h | 2 +- .../xla/service/cpu/cpu_instruction_fusion.cc | 7 +- .../cpu/cpu_instruction_fusion_test.cc | 50 +- .../service/cpu/cpu_layout_assignment_test.cc | 22 +- .../compiler/xla/service/cpu/cpu_options.cc | 1 - .../compiler/xla/service/cpu/ir_emitter.cc | 52 +- .../compiler/xla/service/cpu/ir_emitter.h | 13 +- .../xla/service/cpu/runtime_key_value_sort.cc | 82 +- .../xla/service/cpu/simple_orc_jit.cc | 12 +- .../cpu/tests/cpu_eigen_dot_operation_test.cc | 2 +- .../cpu/tests/cpu_external_constants_test.cc | 2 +- .../service/cpu/tests/cpu_intrinsic_test.cc | 2 +- .../cpu/tests/cpu_literal_caching_test.cc | 8 +- .../xla/service/cpu/tests/cpu_noalias_test.cc | 2 +- .../compiler/xla/service/cpu/xfeed_manager.h | 1 + .../compiler/xla/service/dfs_hlo_visitor.h | 1 + .../service/dfs_hlo_visitor_with_default.h | 3 + .../xla/service/dynamic_parameter_binding.cc | 138 + .../xla/service/dynamic_parameter_binding.h | 125 + .../service/dynamic_parameter_binding_test.cc | 153 + .../xla/service/elemental_ir_emitter.cc | 71 +- tensorflow/compiler/xla/service/executable.h | 6 +- tensorflow/compiler/xla/service/gpu/BUILD | 1 + .../xla/service/gpu/cudnn_conv_rewriter.cc | 6 +- .../xla/service/gpu/cudnn_conv_runner.cc | 15 +- .../xla/service/gpu/elemental_ir_emitter.cc | 10 + .../compiler/xla/service/gpu/fusion_merger.cc | 2 +- .../xla/service/gpu/gpu_executable.cc | 2 +- .../compiler/xla/service/gpu/gpu_executable.h | 2 +- .../compiler/xla/service/gpu/gpu_fusible.cc | 71 +- .../compiler/xla/service/gpu/gpu_fusible.h | 21 +- .../xla/service/gpu/gpu_fusible_test.cc | 319 +- .../xla/service/gpu/gpu_hlo_schedule.cc | 18 +- .../xla/service/gpu/gpu_hlo_schedule.h | 4 +- .../xla/service/gpu/gpu_hlo_schedule_test.cc | 12 +- .../xla/service/gpu/gpu_layout_assignment.cc | 20 +- .../service/gpu/gpu_layout_assignment_test.cc | 8 +- .../xla/service/gpu/instruction_fusion.cc | 5 +- .../service/gpu/instruction_fusion_test.cc | 29 +- .../compiler/xla/service/gpu/ir_emitter.cc | 15 +- .../compiler/xla/service/gpu/ir_emitter.h | 1 + .../xla/service/gpu/ir_emitter_unnested.cc | 2459 +- .../xla/service/gpu/ir_emitter_unnested.h | 226 +- .../gpu/llvm_gpu_backend/nvptx_backend_lib.cc | 16 +- .../xla/service/gpu/multi_output_fusion.cc | 47 +- .../service/gpu/multi_output_fusion_test.cc | 2 +- .../xla/service/gpu/nvptx_compiler.cc | 16 +- .../xla/service/gpu/stream_assignment_test.cc | 8 +- .../xla/service/gpu/tests/gpu_codegen_test.h | 2 +- .../xla/service/gpu/tests/gpu_copy_test.cc | 2 +- .../xla/service/gpu/tests/gpu_ftz_test.cc | 12 +- .../xla/service/gpu/tests/gpu_index_test.cc | 2 +- .../xla/service/gpu/tests/gpu_ldg_test.cc | 6 +- .../xla/service/gpu/tests/gpu_noalias_test.cc | 2 +- .../xla/service/gpu/thunk_schedule.cc | 4 +- .../compiler/xla/service/gpu/thunk_schedule.h | 2 +- .../xla/service/gpu/while_transformer_test.cc | 2 +- .../xla/service/heap_simulator_test.cc | 6 +- tensorflow/compiler/xla/service/hlo.proto | 48 +- .../compiler/xla/service/hlo_computation.cc | 10 +- .../compiler/xla/service/hlo_computation.h | 8 +- .../xla/service/hlo_computation_test.cc | 34 +- .../xla/service/hlo_constant_folding_test.cc | 33 +- .../compiler/xla/service/hlo_cost_analysis.cc | 15 + .../compiler/xla/service/hlo_cost_analysis.h | 1 + .../xla/service/hlo_cost_analysis_test.cc | 6 +- .../xla/service/hlo_dataflow_analysis.cc | 18 + .../xla/service/hlo_dataflow_analysis.h | 1 + .../xla/service/hlo_dataflow_analysis_test.cc | 26 +- .../compiler/xla/service/hlo_dce_test.cc | 10 +- .../compiler/xla/service/hlo_evaluator.cc | 30 +- .../compiler/xla/service/hlo_evaluator.h | 17 +- .../xla/service/hlo_evaluator_test.cc | 29 + .../xla/service/hlo_evaluator_typed_visitor.h | 57 +- .../hlo_get_dimension_size_rewriter.cc | 61 + .../service/hlo_get_dimension_size_rewriter.h | 36 + .../hlo_get_dimension_size_rewriter_test.cc | 83 + .../compiler/xla/service/hlo_graph_dumper.cc | 141 +- .../compiler/xla/service/hlo_graph_dumper.h | 16 +- .../compiler/xla/service/hlo_instruction.cc | 233 +- .../compiler/xla/service/hlo_instruction.h | 34 +- .../compiler/xla/service/hlo_instructions.cc | 13 +- .../compiler/xla/service/hlo_instructions.h | 5 + tensorflow/compiler/xla/service/hlo_lexer.h | 1 + .../compiler/xla/service/hlo_matchers.cc | 4 - .../compiler/xla/service/hlo_matchers.h | 1 - .../xla/service/hlo_memory_scheduler.cc | 82 +- .../xla/service/hlo_memory_scheduler.h | 14 +- .../xla/service/hlo_memory_scheduler_test.cc | 41 +- tensorflow/compiler/xla/service/hlo_module.cc | 14 +- tensorflow/compiler/xla/service/hlo_module.h | 26 +- .../compiler/xla/service/hlo_module_test.cc | 16 +- tensorflow/compiler/xla/service/hlo_opcode.h | 3 +- .../compiler/xla/service/hlo_ordering.cc | 3 +- .../compiler/xla/service/hlo_ordering_test.cc | 12 +- tensorflow/compiler/xla/service/hlo_parser.cc | 15 +- .../compiler/xla/service/hlo_parser_test.cc | 69 +- .../compiler/xla/service/hlo_proto_util.cc | 9 +- .../compiler/xla/service/hlo_proto_util.h | 5 +- .../xla/service/hlo_rematerialization.cc | 19 +- .../xla/service/hlo_rematerialization.h | 5 +- tensorflow/compiler/xla/service/hlo_runner.cc | 34 + tensorflow/compiler/xla/service/hlo_runner.h | 20 +- .../compiler/xla/service/hlo_schedule.cc | 25 +- .../compiler/xla/service/hlo_schedule.h | 12 +- .../compiler/xla/service/hlo_schedule_test.cc | 14 +- .../xla/service/hlo_sharding_metadata.cc | 2 +- .../hlo_subcomputation_unification_test.cc | 6 +- tensorflow/compiler/xla/service/hlo_value.h | 3 - .../compiler/xla/service/hlo_verifier.cc | 21 +- .../compiler/xla/service/hlo_verifier.h | 1 + .../compiler/xla/service/hlo_verifier_test.cc | 16 +- .../service/indexed_array_analysis_test.cc | 8 +- .../xla/service/instruction_fusion.cc | 19 +- .../xla/service/instruction_fusion_test.cc | 56 +- .../xla/service/interpreter/executable.cc | 2 +- .../xla/service/interpreter/executable.h | 2 +- .../xla/service/interpreter/executor.cc | 11 +- .../xla/service/interpreter/executor.h | 3 +- .../compiler/xla/service/layout_assignment.cc | 1 + .../xla/service/layout_assignment_test.cc | 63 +- .../compiler/xla/service/llvm_ir/ir_array.h | 9 + .../xla/service/llvm_ir/kernel_tiling.cc | 187 +- .../xla/service/llvm_ir/kernel_tiling.h | 168 +- .../compiler/xla/service/llvm_ir/llvm_util.cc | 7 +- .../compiler/xla/service/llvm_ir/sort_util.cc | 85 +- .../compiler/xla/service/llvm_ir/sort_util.h | 5 +- .../compiler/xla/service/local_service.cc | 46 +- .../compiler/xla/service/local_service.h | 5 + .../xla/service/logical_buffer_analysis.cc | 7 + .../xla/service/logical_buffer_analysis.h | 1 + .../compiler/xla/service/pattern_matcher.h | 1352 +- .../xla/service/pattern_matcher_gmock.h | 92 + .../xla/service/pattern_matcher_gmock_test.cc | 76 + .../xla/service/pattern_matcher_test.cc | 530 +- .../reduce_precision_insertion_test.cc | 28 +- tensorflow/compiler/xla/service/service.cc | 69 +- .../compiler/xla/service/shape_inference.cc | 24 +- .../compiler/xla/service/shape_inference.h | 7 - .../xla/service/transpose_folding_test.cc | 10 +- .../xla/service/tuple_points_to_analysis.cc | 7 + .../xla/service/tuple_points_to_analysis.h | 1 + .../service/tuple_points_to_analysis_test.cc | 16 + .../while_loop_invariant_code_motion.cc | 32 + .../while_loop_invariant_code_motion.h | 11 +- .../while_loop_invariant_code_motion_test.cc | 54 + .../xla/service/while_loop_simplifier.cc | 447 +- .../xla/service/while_loop_simplifier_test.cc | 190 +- tensorflow/compiler/xla/shape.cc | 107 + tensorflow/compiler/xla/shape.h | 204 + tensorflow/compiler/xla/shape_test.cc | 149 + tensorflow/compiler/xla/shape_tree.h | 11 +- tensorflow/compiler/xla/shape_tree_test.cc | 4 +- tensorflow/compiler/xla/shape_util.cc | 43 +- tensorflow/compiler/xla/shape_util.h | 31 +- tensorflow/compiler/xla/shape_util_test.cc | 72 +- tensorflow/compiler/xla/tests/BUILD | 54 + .../xla/tests/array_elementwise_ops_test.cc | 50 +- .../xla/tests/broadcast_simple_test.cc | 17 +- .../xla/tests/client_library_test_base.cc | 4 +- .../xla/tests/client_library_test_base.h | 2 +- tensorflow/compiler/xla/tests/client_test.cc | 6 +- tensorflow/compiler/xla/tests/concat_test.cc | 26 + .../compiler/xla/tests/conv_depthwise_test.cc | 234 + .../compiler/xla/tests/convolution_test.cc | 826 +- .../compiler/xla/tests/dot_operation_test.cc | 70 + .../xla/tests/grouped_convolution_test.cc | 245 + .../compiler/xla/tests/hlo_test_base.cc | 10 +- tensorflow/compiler/xla/tests/hlo_test_base.h | 8 +- tensorflow/compiler/xla/tests/iota_test.cc | 21 + tensorflow/compiler/xla/tests/replay_test.cc | 9 +- tensorflow/compiler/xla/tests/reshape_test.cc | 6 +- tensorflow/compiler/xla/tests/scatter_test.cc | 36 + tensorflow/compiler/xla/tests/test_utils.cc | 147 +- .../compiler/xla/tests/test_utils_test.cc | 23 + .../compiler/xla/tests/token_hlo_test.cc | 111 +- .../xla/tests/xla_hlo_profile_test.cc | 6 +- .../compiler/xla/tools/replay_computation.cc | 21 +- tensorflow/compiler/xla/util.h | 20 + tensorflow/compiler/xla/window_util.cc | 11 + tensorflow/compiler/xla/window_util.h | 1 + tensorflow/compiler/xla/xla.proto | 20 +- tensorflow/compiler/xla/xla_data.proto | 38 +- tensorflow/compiler/xrt/BUILD | 6 + .../compiler/xrt/kernels/xrt_compile_ops.cc | 27 +- .../compiler/xrt/kernels/xrt_execute_op.cc | 37 +- .../compiler/xrt/kernels/xrt_state_ops.cc | 13 + .../compiler/xrt/kernels/xrt_state_ops.h | 50 + tensorflow/compiler/xrt/ops/xrt_state_ops.cc | 14 + tensorflow/compiler/xrt/tests/raw_api_test.cc | 203 +- tensorflow/compiler/xrt/xrt.proto | 11 +- tensorflow/compiler/xrt/xrt_state.cc | 14 + tensorflow/compiler/xrt/xrt_state.h | 3 + tensorflow/compiler/xrt/xrt_util.cc | 76 + tensorflow/compiler/xrt/xrt_util.h | 34 + tensorflow/contrib/all_reduce/BUILD | 27 +- .../contrib/all_reduce/python/all_reduce.py | 841 +- .../autograph/examples/benchmarks/BUILD | 36 + .../examples/benchmarks/benchmark_base.py | 62 + .../examples/benchmarks/cartpole_benchmark.py | 492 + .../contrib/batching/python/ops/batch_ops.py | 12 +- .../batching/python/ops/batch_ops_test.py | 1 + .../python/kernel_tests/monte_carlo_test.py | 2 +- .../bayesflow/python/ops/monte_carlo_impl.py | 4 +- tensorflow/contrib/bigtable/README.md | 23 +- .../test_kernels/bigtable_test_client.cc | 33 + .../test_kernels/bigtable_test_client.h | 19 + .../python/kernel_tests/bigtable_ops_test.py | 18 +- .../bigtable/python/ops/bigtable_api.py | 16 +- .../boosted_trees/estimator_batch/BUILD | 1 + .../estimator_batch/custom_export_strategy.py | 9 +- .../dnn_tree_combined_estimator.py | 2 +- .../estimator_batch/estimator.py | 240 +- .../estimator_batch/estimator_test.py | 316 +- .../contrib/boosted_trees/examples/boston.py | 4 +- .../boosted_trees/examples/boston_combined.py | 4 +- .../kernels/split_handler_ops.cc | 11 +- .../batch/categorical_split_handler.py | 2 +- .../batch/categorical_split_handler_test.py | 8 +- .../learner/batch/ordinal_split_handler.py | 12 +- .../batch/ordinal_split_handler_test.py | 13 +- .../python/training/functions/gbdt_batch.py | 11 +- .../boosted_trees/python/utils/losses.py | 44 +- .../contrib/checkpoint/python/containers.py | 4 + tensorflow/contrib/cluster_resolver/BUILD | 162 +- .../contrib/cluster_resolver/__init__.py | 16 +- .../cluster_resolver_initialization_test.py | 53 + .../python/training/__init__.py | 41 +- .../python/training/cluster_resolver.py | 338 +- .../python/training/gce_cluster_resolver.py | 199 +- .../training/kubernetes_cluster_resolver.py | 120 +- .../python/training/slurm_cluster_resolver.py | 185 +- .../training/tfconfig_cluster_resolver.py | 80 +- .../python/training/tpu_cluster_resolver.py | 343 +- tensorflow/contrib/cmake/CMakeLists.txt | 33 +- tensorflow/contrib/cmake/README.md | 162 +- .../contrib/cmake/TensorflowConfig.cmake.in | 16 + .../cmake/TensorflowConfigVersion.cmake.in | 11 + .../contrib/cmake/external/abseil_cpp.cmake | 22 +- tensorflow/contrib/cmake/external/png.cmake | 1 + .../contrib/cmake/modules/FindAbseilCpp.cmake | 6 +- tensorflow/contrib/cmake/tf_c.cmake | 1 + tensorflow/contrib/cmake/tf_core_cpu.cmake | 2 + .../contrib/cmake/tf_core_eager_runtime.cmake | 57 + .../contrib/cmake/tf_core_framework.cmake | 8 +- tensorflow/contrib/cmake/tf_core_ops.cmake | 9 +- tensorflow/contrib/cmake/tf_python.cmake | 41 +- tensorflow/contrib/cmake/tf_shared_lib.cmake | 86 +- tensorflow/contrib/compiler/BUILD | 1 + tensorflow/contrib/compiler/xla.py | 1 + .../constrained_minimization_problem.py | 4 +- tensorflow/contrib/crf/python/ops/crf.py | 10 +- tensorflow/contrib/cudnn_rnn/BUILD | 5 +- .../python/kernel_tests/cudnn_rnn_ops_test.py | 1625 +- .../python/kernel_tests/cudnn_rnn_test.py | 16 +- .../cudnn_rnn/python/layers/cudnn_rnn.py | 3 +- .../cudnn_rnn/python/ops/cudnn_rnn_ops.py | 2 +- .../kernel_tests/assert_element_shape_test.py | 18 +- .../kernel_tests/lmdb_dataset_op_test.py | 3 +- .../kernel_tests/slide_dataset_op_test.py | 34 +- tensorflow/contrib/data/python/ops/BUILD | 3 +- tensorflow/contrib/data/python/ops/readers.py | 14 +- tensorflow/contrib/data/python/ops/sliding.py | 25 +- tensorflow/contrib/distribute/BUILD | 2 +- tensorflow/contrib/distribute/README.md | 6 +- tensorflow/contrib/distribute/__init__.py | 4 +- tensorflow/contrib/distribute/python/BUILD | 250 +- .../python/checkpoint_utils_test.py | 4 +- .../python/collective_all_reduce_strategy.py | 124 +- .../collective_all_reduce_strategy_test.py | 152 +- .../contrib/distribute/python/combinations.py | 42 +- ...r_ops_test.py => cross_device_ops_test.py} | 173 +- ...ils_test.py => cross_device_utils_test.py} | 28 +- .../python/estimator_integration_test.py | 10 +- .../python/estimator_training_test.py | 198 +- .../distribute/python/examples/keras_mnist.py | 13 +- .../python/keras_optimizer_v2_test.py | 102 +- .../contrib/distribute/python/keras_test.py | 666 +- .../distribute/python/metrics_v1_test.py | 13 +- .../distribute/python/minimize_loss_test.py | 73 +- .../distribute/python/mirrored_strategy.py | 788 +- .../python/mirrored_strategy_multigpu_test.py | 1346 +- .../python/mirrored_strategy_test.py | 107 - .../distribute/python/moving_averages_test.py | 3 +- .../python/multi_worker_test_base.py | 102 +- .../distribute/python/one_device_strategy.py | 92 +- .../python/one_device_strategy_test.py | 18 +- .../python/parameter_server_strategy.py | 152 +- .../python/parameter_server_strategy_test.py | 159 +- .../contrib/distribute/python/step_fn.py | 2 +- .../distribute/python/strategy_test_lib.py | 122 +- .../contrib/distribute/python/tpu_strategy.py | 224 +- .../contrib/distribute/python/values_test.py | 380 +- .../python/warm_starting_util_test.py | 4 +- tensorflow/contrib/distributions/BUILD | 2 +- .../normal_conjugate_posteriors_test.py | 2 +- .../python/kernel_tests/wishart_test.py | 5 +- .../python/ops/bijectors/softmax_centered.py | 2 +- .../distributions/python/ops/sample_stats.py | 6 +- tensorflow/contrib/eager/python/datasets.py | 6 - .../contrib/eager/python/datasets_test.py | 13 - tensorflow/contrib/eager/python/evaluator.py | 5 +- .../eager/python/examples/densenet/BUILD | 1 + .../examples/densenet/densenet_graph_test.py | 3 +- .../python/examples/gan/mnist_graph_test.py | 3 +- .../examples/generative_examples/cvae.ipynb | 2 +- .../image_captioning_with_attention.ipynb | 2284 +- .../linear_regression_graph_test.py | 2 +- .../nmt_with_attention.ipynb | 8 +- .../examples/resnet50/resnet50_graph_test.py | 3 +- .../eager/python/examples/revnet/main.py | 13 +- .../examples/rnn_ptb/rnn_ptb_graph_test.py | 5 +- .../contrib/eager/python/metrics_impl.py | 6 +- .../contrib/eager/python/metrics_test.py | 12 - tensorflow/contrib/eager/python/network.py | 4 +- tensorflow/contrib/eager/python/saver.py | 5 + tensorflow/contrib/eager/python/tfe_test.py | 4 +- tensorflow/contrib/estimator/BUILD | 25 - tensorflow/contrib/estimator/__init__.py | 2 - .../python/estimator/dnn_linear_combined.py | 34 - .../factorization/python/ops/kmeans.py | 2 +- .../factorization/python/ops/kmeans_test.py | 2 +- tensorflow/contrib/feature_column/BUILD | 11 +- .../feature_column/sequence_feature_column.py | 16 +- ...equence_feature_column_integration_test.py | 17 +- .../sequence_feature_column_test.py | 62 +- .../sequence_feature_column_v2.py | 20 +- .../sequence_feature_column_v2_test.py | 59 +- tensorflow/contrib/framework/BUILD | 20 +- .../contrib/framework/python/ops/sort_ops.py | 172 +- .../estimator/python/gan_estimator_impl.py | 15 +- .../estimator/python/gan_estimator_test.py | 35 +- .../gan/python/losses/python/losses_impl.py | 15 +- tensorflow/contrib/gan/python/namedtuples.py | 12 +- tensorflow/contrib/gan/python/train.py | 37 +- tensorflow/contrib/gan/python/train_test.py | 84 +- tensorflow/contrib/gdr/gdr_rendezvous_mgr.cc | 8 + .../hadoop/python/kernel_tests/hadoop_test.py | 3 +- .../hadoop/python/ops/hadoop_dataset_ops.py | 11 +- tensorflow/contrib/ignite/README.md | 45 +- .../python/tests/ignite_dataset_test.py | 3 +- .../image/kernels/adjust_hsv_in_yiq_op.cc | 2 +- .../image/python/ops/dense_image_warp.py | 79 +- .../keras/api/keras/layers/__init__.py | 2 +- .../contrib/keras/api/keras/utils/__init__.py | 1 + .../python/kernel_estimators.py | 2 +- .../kinesis/python/ops/kinesis_dataset_ops.py | 11 +- tensorflow/contrib/layers/BUILD | 9 +- .../python/layers/embedding_ops_test.py | 52 +- .../contrib/layers/python/layers/encoders.py | 3 +- .../layers/python/layers/feature_column.py | 3 +- .../python/layers/feature_column_ops_test.py | 2 +- .../python/layers/feature_column_test.py | 2 +- .../contrib/layers/python/layers/layers.py | 5 +- .../layers/python/layers/layers_test.py | 4 +- .../layers/python/layers/regularizers_test.py | 2 +- tensorflow/contrib/learn/BUILD | 6 + .../learn/python/learn/estimators/dnn.py | 8 +- .../learn/estimators/dnn_linear_combined.py | 10 +- .../estimators/dnn_linear_combined_test.py | 2 +- .../learn/python/learn/estimators/dnn_test.py | 2 +- .../estimators/dynamic_rnn_estimator_test.py | 6 +- .../python/learn/estimators/estimator.py | 6 +- .../learn/python/learn/estimators/linear.py | 6 +- .../python/learn/estimators/linear_test.py | 4 +- .../learn/python/learn/learn_io/numpy_io.py | 2 +- .../learn/python/learn/learn_io/pandas_io.py | 2 +- .../python/sdca_estimator_test.py | 2 +- tensorflow/contrib/lookup/lookup_ops_test.py | 5 +- .../contrib/losses/python/losses/loss_ops.py | 61 +- .../contrib/makefile/download_dependencies.sh | 2 +- tensorflow/contrib/makefile/tf_op_files.txt | 2 + .../metrics/python/metrics/classification.py | 2 +- .../python/metrics/classification_test.py | 11 +- .../contrib/metrics/python/ops/metric_ops.py | 54 +- .../python/loss_scale_manager_test.py | 2 +- .../python/loss_scale_optimizer_test.py | 4 +- .../python/layers/core_layers.py | 9 +- .../opt/python/training/lars_optimizer.py | 12 + .../opt/python/training/nadam_optimizer.py | 9 +- .../python/training/nadam_optimizer_test.py | 37 +- tensorflow/contrib/optimizer_v2/BUILD | 3 +- .../contrib/optimizer_v2/optimizer_v2.py | 44 +- tensorflow/contrib/predictor/BUILD | 1 + tensorflow/contrib/quantize/README.md | 4 +- .../contrib/quantize/python/quant_ops.py | 8 +- .../contrib/quantize/python/quantize.py | 4 +- tensorflow/contrib/resampler/BUILD | 32 +- .../resampler/xla/resampler_ops_xla_test.py} | 53 +- .../python/kernel_tests/core_rnn_cell_test.py | 6 +- .../rnn/python/kernel_tests/core_rnn_test.py | 2 +- tensorflow/contrib/rnn/python/ops/gru_ops.py | 4 +- tensorflow/contrib/rnn/python/ops/lstm_ops.py | 5 +- tensorflow/contrib/rnn/python/ops/rnn_cell.py | 14 +- tensorflow/contrib/saved_model/BUILD | 5 +- .../python/saved_model/keras_saved_model.py | 35 +- .../saved_model/keras_saved_model_test.py | 39 +- .../kernel_tests/attention_wrapper_test.py | 4 +- .../contrib/summary/summary_ops_test.py | 30 +- .../tensorboard/db/summary_file_writer.cc | 11 +- .../db/summary_file_writer_test.cc | 18 + tensorflow/contrib/tensorrt/BUILD | 29 + .../contrib/tensorrt/convert/convert_graph.cc | 201 +- .../contrib/tensorrt/convert/convert_graph.h | 10 +- .../tensorrt/convert/convert_graph_test.cc | 43 +- .../contrib/tensorrt/convert/convert_nodes.cc | 1130 +- .../contrib/tensorrt/convert/convert_nodes.h | 81 +- .../tensorrt/convert/convert_nodes_test.cc | 1293 +- .../tensorrt/convert/trt_optimization_pass.cc | 10 + .../tensorrt/convert/trt_optimization_pass.h | 4 +- .../contrib/tensorrt/kernels/trt_engine_op.cc | 27 +- .../contrib/tensorrt/kernels/trt_engine_op.h | 4 + .../contrib/tensorrt/ops/trt_engine_op.cc | 22 +- .../contrib/tensorrt/python/trt_convert.py | 79 +- .../tensorrt/python/trt_convert_test.py | 13 +- .../tensorrt/resources/trt_resources.h | 3 +- .../contrib/tensorrt/segment/segment.cc | 35 +- tensorflow/contrib/tensorrt/test/base_test.py | 77 +- .../tensorrt/test/batch_matmul_test.py | 6 +- .../tensorrt/test/biasadd_matmul_test.py | 34 +- .../binary_tensor_weight_broadcast_test.py | 7 +- .../tensorrt/test/concatenation_test.py | 2 +- .../tensorrt/test/const_broadcast_test.py | 2 +- .../tensorrt/test/memory_alignment_test.py | 2 +- .../multi_connection_neighbor_engine_test.py | 10 +- .../tensorrt/test/neighboring_engine_test.py | 4 +- .../tensorrt/test/quantization_mnist_test.py | 290 + .../tensorrt/test/quantization_test.py | 144 + .../contrib/tensorrt/test/rank_two_test.py | 4 +- .../tensorrt/test/reshape_transpose_test.py | 8 +- .../contrib/tensorrt/test/testdata/checkpoint | 3 + .../model.ckpt-46900.data-00000-of-00001 | Bin 0 -> 686728 bytes .../test/testdata/model.ckpt-46900.index | Bin 0 -> 652 bytes .../test/tf_trt_integration_test_base.py | 112 +- .../contrib/tensorrt/test/unary_test.py | 4 +- .../tensorrt/test/vgg_block_nchw_test.py | 2 +- .../contrib/tensorrt/test/vgg_block_test.py | 2 +- .../timeseries/python/timeseries/BUILD | 2 + .../python/timeseries/estimators.py | 2 +- .../python/timeseries/estimators_test.py | 2 +- .../timeseries/python/timeseries/head_test.py | 2 +- .../python/timeseries/math_utils.py | 14 +- .../timeseries/python/timeseries/model.py | 2 +- .../timeseries/state_space_models/BUILD | 5 +- tensorflow/contrib/tpu/BUILD | 5 +- .../pip_package/cloud_tpu_profiler/main.py | 6 +- .../tpu/python/tpu/async_checkpoint.py | 7 +- tensorflow/contrib/tpu/python/tpu/datasets.py | 4 +- .../contrib/tpu/python/tpu/datasets_test.py | 10 +- .../contrib/tpu/python/tpu/keras_support.py | 54 +- .../tpu/python/tpu/keras_tpu_variables.py | 4 + tensorflow/contrib/tpu/python/tpu/tpu.py | 6 +- .../contrib/tpu/python/tpu/tpu_context.py | 2 +- .../contrib/tpu/python/tpu/tpu_embedding.py | 11 +- .../contrib/tpu/python/tpu/tpu_estimator.py | 17 +- .../python/tpu/tpu_estimator_signals_test.py | 2 +- tensorflow/contrib/tpu/python/tpu/tpu_feed.py | 69 +- .../contrib/tpu/python/tpu/training_loop.py | 4 +- tensorflow/contrib/tpu/tpu_estimator.md | 9 +- tensorflow/contrib/training/BUILD | 23 - tensorflow/contrib/training/__init__.py | 5 +- .../python/training/tensor_queue_dataset.py | 201 - .../training/tensor_queue_dataset_test.py | 355 - tensorflow/contrib/verbs/rdma.cc | 6 +- tensorflow/core/BUILD | 108 +- tensorflow/core/api_def/api_test.cc | 13 +- .../base_api/api_def_BatchDataset.pbtxt | 1 + .../base_api/api_def_CacheDataset.pbtxt | 1 + .../base_api/api_def_ConcatenateDataset.pbtxt | 1 + .../api_def_DatasetToSingleElement.pbtxt | 1 + .../api_def_EnqueueInQueueDataset.pbtxt | 3 - ...perimentalBytesProducedStatsDataset.pbtxt} | 3 +- ...i_def_ExperimentalDatasetCardinality.pbtxt | 21 + ...i_def_ExperimentalDatasetToTFRecord.pbtxt} | 2 +- ...perimentalDenseToSparseBatchDataset.pbtxt} | 3 +- ...xperimentalFunctionBufferingResource.pbtxt | 58 - ...ntalFunctionBufferingResourceGetNext.pbtxt | 25 - ...mentalFunctionBufferingResourceReset.pbtxt | 13 - ...f_ExperimentalGroupByReducerDataset.pbtxt} | 2 +- ...ef_ExperimentalGroupByWindowDataset.pbtxt} | 3 +- ...def_ExperimentalLatencyStatsDataset.pbtxt} | 3 +- ..._def_ExperimentalMapAndBatchDataset.pbtxt} | 2 +- ...def_ExperimentalMatchingFilesDataset.pbtxt | 4 + ...rimentalMaxIntraOpParallelismDataset.pbtxt | 13 + ...perimentalParallelInterleaveDataset.pbtxt} | 3 +- ...def_ExperimentalParseExampleDataset.pbtxt} | 3 +- ...ExperimentalPrivateThreadPoolDataset.pbtxt | 13 + ...> api_def_ExperimentalRandomDataset.pbtxt} | 3 +- ... => api_def_ExperimentalScanDataset.pbtxt} | 3 +- ...xperimentalSetStatsAggregatorDataset.pbtxt | 4 + ...ef_ExperimentalSlidingWindowDataset.pbtxt} | 3 +- ...t => api_def_ExperimentalSqlDataset.pbtxt} | 3 +- ...ef_ExperimentalStatsAggregatorHandle.pbtxt | 5 + ..._ExperimentalStatsAggregatorSummary.pbtxt} | 3 +- ... api_def_ExperimentalUnbatchDataset.pbtxt} | 3 +- .../core/api_def/base_api/api_def_FFT.pbtxt | 4 +- .../core/api_def/base_api/api_def_FFT2D.pbtxt | 4 +- .../base_api/api_def_FilterDataset.pbtxt | 1 + .../api_def_FixedLengthRecordDataset.pbtxt | 1 + .../api_def_FixedLengthRecordDatasetV2.pbtxt | 1 + .../base_api/api_def_FlatMapDataset.pbtxt | 1 + .../base_api/api_def_GeneratorDataset.pbtxt | 1 + .../core/api_def/base_api/api_def_IFFT.pbtxt | 4 +- .../api_def/base_api/api_def_IFFT2D.pbtxt | 4 +- .../base_api/api_def_InterleaveDataset.pbtxt | 1 + .../base_api/api_def_MapAndBatchDataset.pbtxt | 53 - .../api_def/base_api/api_def_MapDataset.pbtxt | 1 + .../api_def_MatchingFilesDataset.pbtxt | 4 - .../base_api/api_def_PaddedBatchDataset.pbtxt | 1 + .../base_api/api_def_ParallelMapDataset.pbtxt | 1 + .../base_api/api_def_PrefetchDataset.pbtxt | 1 + ...rependFromQueueAndPaddedBatchDataset.pbtxt | 3 - .../api_def_QuantizeAndDequantizeV2.pbtxt | 15 +- .../base_api/api_def_RangeDataset.pbtxt | 1 + .../base_api/api_def_RepeatDataset.pbtxt | 1 + ...api_def_ResourceApplyAdamWithAmsgrad.pbtxt | 85 + .../api_def_ResourceApplyKerasMomentum.pbtxt | 56 + ...def_ResourceSparseApplyKerasMomentum.pbtxt | 64 + .../api_def/base_api/api_def_ScatterNd.pbtxt | 4 + .../api_def_SetStatsAggregatorDataset.pbtxt | 3 - .../api_def_ShuffleAndRepeatDataset.pbtxt | 1 + .../base_api/api_def_ShuffleDataset.pbtxt | 1 + .../base_api/api_def_SkipDataset.pbtxt | 1 + .../api_def_SparseTensorSliceDataset.pbtxt | 1 + .../api_def_StatsAggregatorHandle.pbtxt | 4 - .../base_api/api_def_TFRecordDataset.pbtxt | 1 + .../base_api/api_def_TakeDataset.pbtxt | 1 + .../base_api/api_def_TensorDataset.pbtxt | 1 + ...i_def_TensorForestCreateTreeVariable.pbtxt | 17 + .../api_def_TensorForestTreeDeserialize.pbtxt | 17 + ..._def_TensorForestTreeIsInitializedOp.pbtxt | 17 + .../api_def_TensorForestTreePredict.pbtxt | 29 + ...def_TensorForestTreeResourceHandleOp.pbtxt | 5 + .../api_def_TensorForestTreeSerialize.pbtxt | 17 + .../api_def_TensorForestTreeSize.pbtxt | 17 + .../base_api/api_def_TensorListConcat.pbtxt | 12 + .../base_api/api_def_TensorListSplit.pbtxt | 13 + .../base_api/api_def_TensorScatterAdd.pbtxt | 94 + .../base_api/api_def_TensorScatterSub.pbtxt | 94 + .../api_def_TensorScatterUpdate.pbtxt | 106 + .../base_api/api_def_TensorSliceDataset.pbtxt | 1 + .../base_api/api_def_TextLineDataset.pbtxt | 1 + .../api_def_UnicodeDecodeWithOffsets.pbtxt | 87 + .../base_api/api_def_UnicodeEncode.pbtxt | 73 + .../api_def/base_api/api_def_ZipDataset.pbtxt | 1 + .../python_api/api_def_BatchDataset.pbtxt | 4 - .../python_api/api_def_BatchToSpaceND.pbtxt | 2 + .../python_api/api_def_BesselI0e.pbtxt | 4 +- .../python_api/api_def_BesselI1e.pbtxt | 4 +- .../api_def_BytesProducedStatsDataset.pbtxt | 4 - .../python_api/api_def_CacheDataset.pbtxt | 4 - .../python_api/api_def_CheckNumerics.pbtxt | 2 + .../api_def_ConcatenateDataset.pbtxt | 4 - .../api_def/python_api/api_def_Conv2D.pbtxt | 4 +- .../api_def_Conv2DBackpropFilter.pbtxt | 4 +- .../api_def_Conv2DBackpropInput.pbtxt | 4 +- .../api_def/python_api/api_def_Conv3D.pbtxt | 4 +- .../api_def_Conv3DBackpropFilterV2.pbtxt | 4 + .../python_api/api_def_CropAndResize.pbtxt | 4 +- .../api_def_DatasetToSingleElement.pbtxt | 4 - .../api_def_DecodeAndCropJpeg.pbtxt | 4 +- .../python_api/api_def_DecodeBmp.pbtxt | 4 +- .../python_api/api_def_DecodeGif.pbtxt | 4 +- .../python_api/api_def_DecodeJpeg.pbtxt | 4 +- .../python_api/api_def_DecodePng.pbtxt | 4 +- .../api_def_DenseToSparseBatchDataset.pbtxt | 4 - .../api_def_DepthwiseConv2dNative.pbtxt | 2 + ..._DepthwiseConv2dNativeBackpropFilter.pbtxt | 5 + ...f_DepthwiseConv2dNativeBackpropInput.pbtxt | 5 + .../python_api/api_def_Dilation2D.pbtxt | 1 + .../python_api/api_def_EncodeJpeg.pbtxt | 4 +- .../api_def_EnqueueInQueueDataset.pbtxt | 4 - .../core/api_def/python_api/api_def_Erf.pbtxt | 8 +- .../api_def_ExtractImagePatches.pbtxt | 8 +- .../python_api/api_def_ExtractJpegShape.pbtxt | 4 +- .../python_api/api_def_FilterDataset.pbtxt | 4 - .../api_def_FixedLengthRecordDataset.pbtxt | 4 - .../api_def_FixedLengthRecordDatasetV2.pbtxt | 4 - .../python_api/api_def_FlatMapDataset.pbtxt | 4 - .../api_def_FractionalAvgPool.pbtxt | 4 +- .../api_def_FractionalMaxPool.pbtxt | 4 +- .../python_api/api_def_GeneratorDataset.pbtxt | 4 - .../api_def_GroupByWindowDataset.pbtxt | 4 - .../api_def_InterleaveDataset.pbtxt | 4 - .../api_def/python_api/api_def_IsFinite.pbtxt | 4 + .../api_def/python_api/api_def_IsInf.pbtxt | 4 + .../api_def/python_api/api_def_IsNan.pbtxt | 4 + .../api_def_LatencyStatsDataset.pbtxt | 4 - .../api_def/python_api/api_def_LinSpace.pbtxt | 1 + .../core/api_def/python_api/api_def_Log.pbtxt | 1 + .../api_def/python_api/api_def_Log1p.pbtxt | 1 + .../api_def_MapAndBatchDataset.pbtxt | 4 - .../python_api/api_def_MapDataset.pbtxt | 4 - .../api_def_MaxPoolWithArgmax.pbtxt | 1 + .../core/api_def/python_api/api_def_Neg.pbtxt | 7 +- .../api_def_PaddedBatchDataset.pbtxt | 4 - .../api_def_ParallelInterleaveDataset.pbtxt | 4 - .../api_def_ParallelMapDataset.pbtxt | 4 - .../api_def_ParseExampleDataset.pbtxt | 4 - .../python_api/api_def_PrefetchDataset.pbtxt | 4 - ...rependFromQueueAndPaddedBatchDataset.pbtxt | 4 - .../python_api/api_def_QuantizedAvgPool.pbtxt | 2 + .../python_api/api_def_QuantizedConv2D.pbtxt | 2 + .../python_api/api_def_QuantizedMaxPool.pbtxt | 2 + .../python_api/api_def_QuantizedReluX.pbtxt | 2 + .../python_api/api_def_RandomDataset.pbtxt | 4 - .../python_api/api_def_RangeDataset.pbtxt | 4 - .../python_api/api_def_RepeatDataset.pbtxt | 4 - .../python_api/api_def_ResizeArea.pbtxt | 4 +- .../python_api/api_def_ResizeBicubic.pbtxt | 4 +- .../python_api/api_def_ResizeBilinear.pbtxt | 4 +- .../api_def_ResizeNearestNeighbor.pbtxt | 4 +- ...api_def_ResourceApplyAdamWithAmsgrad.pbtxt | 4 + .../api_def_ResourceApplyKerasMomentum.pbtxt | 4 + ...def_ResourceSparseApplyKerasMomentum.pbtxt | 4 + .../python_api/api_def_ScanDataset.pbtxt | 4 - .../api_def_SetStatsAggregatorDataset.pbtxt | 4 - .../api_def_ShuffleAndRepeatDataset.pbtxt | 4 - .../python_api/api_def_ShuffleDataset.pbtxt | 4 - .../api_def/python_api/api_def_Sign.pbtxt | 7 +- .../python_api/api_def_SkipDataset.pbtxt | 4 - .../python_api/api_def_SlideDataset.pbtxt | 4 - .../api_def_SparseTensorSliceDataset.pbtxt | 4 - .../python_api/api_def_SqlDataset.pbtxt | 4 - .../api_def/python_api/api_def_Sqrt.pbtxt | 7 +- .../api_def/python_api/api_def_Square.pbtxt | 7 +- .../api_def_StatsAggregatorHandle.pbtxt | 4 - .../api_def_StatsAggregatorSummary.pbtxt | 4 - .../api_def_StringToHashBucket.pbtxt | 8 +- .../python_api/api_def_StringToNumber.pbtxt | 8 +- .../python_api/api_def_TFRecordDataset.pbtxt | 4 - .../python_api/api_def_TakeDataset.pbtxt | 4 - .../api_def/python_api/api_def_Tanh.pbtxt | 10 +- .../python_api/api_def_TensorDataset.pbtxt | 4 - .../python_api/api_def_TensorListConcat.pbtxt | 4 + ... => api_def_TensorListPushBackBatch.pbtxt} | 0 .../python_api/api_def_TensorListSplit.pbtxt | 4 + .../api_def_TensorSliceDataset.pbtxt | 4 - .../python_api/api_def_TextLineDataset.pbtxt | 4 - .../python_api/api_def_UnbatchDataset.pbtxt | 4 - .../python_api/api_def_ZipDataset.pbtxt | 4 - .../common_runtime/accumulate_n_optimizer.cc | 5 +- .../collective_executor_mgr_test.cc | 6 +- .../collective_param_resolver_local.cc | 4 +- .../collective_param_resolver_local_test.cc | 6 +- .../common_runtime/collective_rma_local.cc | 2 +- .../collective_rma_local_test.cc | 6 +- .../core/common_runtime/constant_folding.cc | 26 +- .../common_runtime/constant_folding_test.cc | 46 + tensorflow/core/common_runtime/device.cc | 2 + tensorflow/core/common_runtime/device.h | 10 + .../core/common_runtime/device_factory.cc | 24 +- .../core/common_runtime/device_factory.h | 13 +- tensorflow/core/common_runtime/device_mgr.cc | 37 +- tensorflow/core/common_runtime/device_mgr.h | 15 +- .../device_resolver_local_test.cc | 6 +- .../core/common_runtime/device_set_test.cc | 2 +- .../core/common_runtime/direct_session.cc | 28 +- .../core/common_runtime/direct_session.h | 6 +- tensorflow/core/common_runtime/eager/BUILD | 1 + .../core/common_runtime/eager/attr_builder.cc | 32 +- .../core/common_runtime/eager/attr_builder.h | 16 +- .../common_runtime/eager/attr_builder_test.cc | 17 +- .../core/common_runtime/eager/context.cc | 14 +- .../core/common_runtime/eager/context.h | 2 + .../common_runtime/eager/eager_operation.h | 14 +- .../core/common_runtime/eager/execute.cc | 15 +- .../eager/kernel_and_device_test.cc | 14 +- tensorflow/core/common_runtime/executor.cc | 44 +- .../core/common_runtime/executor_test.cc | 8 +- .../core/common_runtime/function_test.cc | 11 +- .../function_threadpool_test.cc | 12 +- .../core/common_runtime/gpu/gpu_device.cc | 20 +- .../core/common_runtime/gpu/gpu_device.h | 18 +- .../common_runtime/gpu/gpu_device_factory.cc | 21 +- .../gpu/gpu_device_on_non_gpu_machine_test.cc | 2 +- .../common_runtime/gpu/gpu_device_test.cc | 32 +- .../common_runtime/gpu/gpu_process_state.cc | 27 +- .../common_runtime/gpu/gpu_process_state.h | 22 +- .../common_runtime/graph_execution_state.cc | 96 +- .../hierarchical_tree_broadcaster_test.cc | 11 +- .../kernel_benchmark_testlib.cc | 8 +- .../common_runtime/kernel_benchmark_testlib.h | 2 +- .../core/common_runtime/local_device.cc | 73 +- tensorflow/core/common_runtime/local_device.h | 7 + tensorflow/core/common_runtime/lower_if_op.cc | 10 +- tensorflow/core/common_runtime/metrics.cc | 16 +- tensorflow/core/common_runtime/metrics.h | 4 +- .../common_runtime/optimization_registry.cc | 14 + tensorflow/core/common_runtime/placer.cc | 2 +- tensorflow/core/common_runtime/placer_test.cc | 2 +- .../core/common_runtime/pool_allocator.cc | 14 +- .../core/common_runtime/pool_allocator.h | 1 - .../process_function_library_runtime_test.cc | 18 +- .../core/common_runtime/process_state.cc | 28 +- .../core/common_runtime/process_state.h | 8 +- .../core/common_runtime/renamed_device.cc | 14 +- .../core/common_runtime/renamed_device.h | 7 +- .../core/common_runtime/ring_reducer.cc | 2 +- .../core/common_runtime/ring_reducer_test.cc | 11 +- .../core/common_runtime/threadpool_device.cc | 2 +- .../threadpool_device_factory.cc | 36 +- tensorflow/core/distributed_runtime/BUILD | 13 +- ...lective_param_resolver_distributed_test.cc | 11 +- .../collective_rma_distributed_test.cc | 11 +- .../device_resolver_distributed_test.cc | 13 +- .../core/distributed_runtime/eager/BUILD | 1 + .../eager/eager_service_impl.cc | 35 +- .../eager/eager_service_impl_test.cc | 9 +- .../core/distributed_runtime/graph_mgr.cc | 8 +- tensorflow/core/distributed_runtime/rpc/BUILD | 1 + .../rpc/eager/grpc_eager_client.cc | 2 +- .../distributed_runtime/rpc/grpc_channel.cc | 44 +- .../distributed_runtime/rpc/grpc_channel.h | 8 +- .../rpc/grpc_channel_test.cc | 45 +- .../rpc/grpc_remote_worker.cc | 14 +- .../rpc/grpc_remote_worker.h | 3 +- .../rpc/grpc_rpc_factory.cc | 10 +- .../rpc/grpc_server_lib.cc | 11 +- .../distributed_runtime/rpc/grpc_session.cc | 20 +- .../distributed_runtime/rpc/grpc_session.h | 3 + .../rpc/grpc_session_test.cc | 27 + .../core/distributed_runtime/rpc/grpc_state.h | 36 +- .../rpc/grpc_worker_cache.cc | 16 +- .../rpc/rpc_rendezvous_mgr.cc | 9 + .../rpc_collective_executor_mgr_test.cc | 6 +- .../core/distributed_runtime/server_lib.cc | 10 +- .../distributed_runtime/server_lib_test.cc | 56 + .../core/distributed_runtime/session_mgr.cc | 8 +- .../distributed_runtime/session_mgr_test.cc | 8 +- tensorflow/core/distributed_runtime/worker.cc | 4 +- tensorflow/core/framework/allocator.cc | 2 + tensorflow/core/framework/allocator.h | 2 + tensorflow/core/framework/common_shape_fns.cc | 45 + tensorflow/core/framework/common_shape_fns.h | 3 + tensorflow/core/framework/dataset.cc | 3 + tensorflow/core/framework/dataset.h | 32 +- tensorflow/core/framework/device_base.cc | 6 +- tensorflow/core/framework/function.cc | 187 +- tensorflow/core/framework/function.h | 8 + .../core/framework/function_handle_cache.cc | 66 + .../core/framework/function_handle_cache.h | 53 + tensorflow/core/framework/function_test.cc | 84 + tensorflow/core/framework/node_def_util.cc | 4 + tensorflow/core/framework/node_def_util.h | 1 + tensorflow/core/framework/op_kernel.cc | 65 +- tensorflow/core/framework/resource_mgr.cc | 9 +- tensorflow/core/framework/tensor.h | 91 +- tensorflow/core/framework/tensor_test.cc | 11 +- tensorflow/core/graph/edgeset.cc | 2 +- tensorflow/core/graph/edgeset.h | 20 +- tensorflow/core/graph/graph.cc | 24 + tensorflow/core/graph/graph.h | 21 +- tensorflow/core/graph/graph_partition.cc | 4 +- tensorflow/core/graph/graph_partition_test.cc | 10 +- tensorflow/core/graph/graph_test.cc | 39 - tensorflow/core/graph/mkl_layout_pass.cc | 490 +- tensorflow/core/graph/mkl_layout_pass_test.cc | 311 + tensorflow/core/graph/node_builder.cc | 2 + tensorflow/core/graph/node_builder.h | 1 + tensorflow/core/graph/optimizer_cse_test.cc | 10 +- tensorflow/core/graph/testlib.cc | 11 + tensorflow/core/graph/testlib.h | 4 + tensorflow/core/grappler/BUILD | 4 + .../core/grappler/costs/graph_properties.cc | 5 + .../costs/op_level_cost_estimator_test.cc | 2 +- .../core/grappler/costs/virtual_scheduler.cc | 20 +- .../core/grappler/costs/virtual_scheduler.h | 8 +- .../core/grappler/graph_analyzer/sig_node.h | 2 +- tensorflow/core/grappler/graph_view.cc | 6 + tensorflow/core/grappler/graph_view.h | 5 +- tensorflow/core/grappler/grappler_item.cc | 64 +- tensorflow/core/grappler/grappler_item.h | 35 +- .../core/grappler/grappler_item_builder.cc | 11 +- .../core/grappler/grappler_item_test.cc | 28 + tensorflow/core/grappler/op_types.cc | 17 +- tensorflow/core/grappler/op_types.h | 6 +- tensorflow/core/grappler/optimizers/BUILD | 29 +- .../optimizers/arithmetic_optimizer.cc | 24 +- .../optimizers/arithmetic_optimizer_test.cc | 27 + .../optimizers/constant_folding_test.cc | 326 +- .../core/grappler/optimizers/data/BUILD | 1 + .../optimizers/data/graph_test_utils.cc | 2 +- .../optimizers/data/hoist_random_uniform.cc | 2 +- .../data/hoist_random_uniform_test.cc | 2 +- .../optimizers/data/latency_all_edges.cc | 2 +- .../optimizers/data/latency_all_edges_test.cc | 7 +- .../optimizers/data/make_numa_aware.cc | 2 +- .../optimizers/data/make_numa_aware_test.cc | 6 +- .../optimizers/data/map_and_batch_fusion.cc | 2 +- .../data/map_and_batch_fusion_test.cc | 21 +- .../experimental_implementation_selector.cc | 114 +- ...perimental_implementation_selector_test.cc | 95 + .../grappler/optimizers/function_api_info.cc | 180 +- .../grappler/optimizers/function_api_info.h | 38 +- .../optimizers/function_api_info_test.cc | 118 +- .../grappler/optimizers/function_optimizer.cc | 848 +- .../optimizers/function_optimizer_test.cc | 235 + .../optimizers/graph_optimizer_stage.h | 3 +- .../grappler/optimizers/graph_rewriter.cc | 214 - .../core/grappler/optimizers/graph_rewriter.h | 102 - .../grappler/optimizers/layout_optimizer.cc | 4 + .../grappler/optimizers/memory_optimizer.cc | 1 - .../grappler/optimizers/meta_optimizer.cc | 66 +- .../core/grappler/optimizers/meta_optimizer.h | 10 +- .../optimizers/meta_optimizer_test.cc | 65 +- .../core/grappler/optimizers/model_pruner.cc | 164 +- .../core/grappler/optimizers/remapper.cc | 447 +- .../core/grappler/optimizers/remapper_test.cc | 244 +- tensorflow/core/grappler/utils.cc | 4 +- tensorflow/core/grappler/utils/BUILD | 1 - tensorflow/core/grappler/utils/functions.cc | 124 +- tensorflow/core/grappler/utils/functions.h | 30 +- .../core/grappler/utils/functions_test.cc | 86 +- .../core/grappler/utils/grappler_test.cc | 6 +- tensorflow/core/grappler/utils_test.cc | 23 + tensorflow/core/kernels/BUILD | 90 +- tensorflow/core/kernels/adjust_contrast_op.cc | 4 +- tensorflow/core/kernels/adjust_hue_op.cc | 4 +- tensorflow/core/kernels/barrier_ops.cc | 2 +- .../kernels/boosted_trees/boosted_trees.proto | 14 + tensorflow/core/kernels/control_flow_ops.cc | 4 + tensorflow/core/kernels/conv_2d.h | 2 +- .../{conv_ops_gpu_3.cu.cc => conv_2d_gpu.h} | 126 +- .../core/kernels/conv_2d_gpu_double.cu.cc | 50 + .../core/kernels/conv_2d_gpu_float.cu.cc | 63 + .../core/kernels/conv_2d_gpu_half.cu.cc | 57 + .../kernels/conv_2d_gpu_int.cu.cc} | 28 +- .../core/kernels/conv_2d_gpu_uint16.cu.cc | 38 + .../core/kernels/conv_2d_gpu_uint32.cu.cc | 38 + .../core/kernels/conv_2d_gpu_uint64.cu.cc | 38 + .../core/kernels/conv_2d_gpu_uint8.cu.cc | 38 + tensorflow/core/kernels/conv_grad_ops_3d.cc | 2 + tensorflow/core/kernels/conv_ops_3d.cc | 14 +- tensorflow/core/kernels/conv_ops_fused.cc | 1185 +- .../kernels/conv_ops_fused_image_transform.cc | 902 + tensorflow/core/kernels/conv_ops_test.cc | 735 +- tensorflow/core/kernels/cwise_ops.h | 21 + tensorflow/core/kernels/data/BUILD | 215 +- .../core/kernels/data/batch_dataset_op.cc | 9 + .../core/kernels/data/cache_dataset_ops.cc | 4 + .../core/kernels/data/captured_function.cc | 214 +- .../core/kernels/data/captured_function.h | 127 +- .../kernels/data/concatenate_dataset_op.cc | 12 + tensorflow/core/kernels/data/dataset_ops.cc | 17 + tensorflow/core/kernels/data/dataset_utils.cc | 8 +- tensorflow/core/kernels/data/dataset_utils.h | 4 +- .../core/kernels/data/experimental/BUILD | 253 +- .../experimental/assert_next_dataset_op.cc | 2 + .../dense_to_sparse_batch_dataset_op.cc | 13 +- .../group_by_reducer_dataset_op.cc | 36 +- .../group_by_window_dataset_op.cc | 30 +- .../experimental/identity_indexed_dataset.cc | 163 - .../experimental/ignore_errors_dataset_op.cc | 2 + .../data/experimental/indexed_dataset.h | 119 - ...dexed_dataset.cc => indexed_dataset_op.cc} | 249 +- .../map_and_batch_dataset_op.cc | 90 +- .../matching_files_dataset_op.cc | 5 +- .../non_serializable_dataset_op.cc | 2 + .../numa_map_and_batch_dataset_op.cc | 17 +- .../parallel_interleave_dataset_op.cc | 1085 + .../parse_example_dataset_op.cc | 206 +- .../data/experimental/prefetching_kernels.cc | 428 - .../{ => experimental}/random_dataset_op.cc | 4 +- .../{ => experimental}/scan_dataset_op.cc | 15 +- .../set_stats_aggregator_dataset_op.cc} | 7 +- .../data/experimental/sleep_dataset_op.cc | 2 + .../sliding_window_dataset_op.cc} | 19 +- .../kernels/data/{ => experimental}/sql/BUILD | 0 .../{ => experimental}/sql/driver_manager.cc | 4 +- .../{ => experimental}/sql/driver_manager.h | 8 +- .../{ => experimental}/sql/query_connection.h | 6 +- .../sql/sqlite_query_connection.cc | 4 +- .../sql/sqlite_query_connection.h | 8 +- .../sql_dataset_op.cc} | 7 +- .../stats_aggregator_ops.cc | 10 +- .../{ => experimental}/stats_dataset_ops.cc | 14 +- .../experimental/threadpool_dataset_op.cc | 238 +- .../to_tf_record_op.cc} | 21 +- .../{ => experimental}/unbatch_dataset_op.cc | 4 +- .../core/kernels/data/filter_dataset_op.cc | 20 +- .../core/kernels/data/flat_map_dataset_op.cc | 7 +- .../core/kernels/data/generator_dataset_op.cc | 33 +- .../kernels/data/interleave_dataset_op.cc | 8 +- tensorflow/core/kernels/data/iterator_ops.cc | 307 +- .../core/kernels/data/map_dataset_op.cc | 29 +- .../core/kernels/data/model_dataset_op.cc | 2 + .../kernels/data/multi_device_iterator_ops.cc | 50 +- .../core/kernels/data/optimize_dataset_op.cc | 81 +- tensorflow/core/kernels/data/optional_ops.cc | 132 +- .../core/kernels/data/optional_ops.cu.cc | 37 + tensorflow/core/kernels/data/optional_ops.h | 119 + .../kernels/data/padded_batch_dataset_op.cc | 9 + .../data/parallel_interleave_dataset_op.cc | 1058 +- .../kernels/data/parallel_map_dataset_op.cc | 135 +- .../kernels/data/parallel_map_iterator.cc | 35 +- .../core/kernels/data/parallel_map_iterator.h | 43 +- .../core/kernels/data/prefetch_dataset_op.cc | 7 +- .../core/kernels/data/range_dataset_op.cc | 8 + .../core/kernels/data/repeat_dataset_op.cc | 17 + .../core/kernels/data/shuffle_dataset_op.cc | 2 + .../kernels/data/single_threaded_executor.cc | 15 +- .../data/single_threaded_executor_test.cc | 8 +- .../core/kernels/data/skip_dataset_op.cc | 8 + .../data/sparse_tensor_slice_dataset_op.cc | 2 + .../core/kernels/data/take_dataset_op.cc | 11 + .../core/kernels/data/tensor_dataset_op.cc | 2 + .../kernels/data/tensor_queue_dataset_op.cc | 657 - .../kernels/data/tensor_slice_dataset_op.cc | 2 + .../core/kernels/data/window_dataset.cc | 2 + .../core/kernels/data/window_dataset_op.cc | 9 + .../core/kernels/data/zip_dataset_op.cc | 15 + tensorflow/core/kernels/data_format_ops.cc | 10 + tensorflow/core/kernels/deep_conv2d.cc | 21 +- .../core/kernels/depthwise_conv_op_gpu.cu.cc | 8 +- .../core/kernels/dynamic_partition_op.cc | 2 +- .../core/kernels/eigen_spatial_convolutions.h | 194 +- .../eigen_spatial_convolutions_test.cc | 103 +- .../core/kernels/fractional_avg_pool_op.cc | 2 +- tensorflow/core/kernels/functional_ops.cc | 31 +- .../core/kernels/fused_batch_norm_op.cc | 4 +- tensorflow/core/kernels/fuzzing/BUILD | 22 + .../012e3ad384a4a1165f8498b5c94ba0d32a73e187 | Bin 0 -> 420 bytes .../055d77f7810048caa28323f6eb552a53d156040b | Bin 0 -> 594 bytes .../131e251bfb82c681cb075d32b99f18fceaca115d | Bin 0 -> 287 bytes .../1399ab0bd9f2c91d270cb43251bdc5729bef3526 | Bin 0 -> 1684 bytes .../16a6ce88f66d2e9686c8354cad8ba915cf0c11de | Bin 0 -> 207 bytes .../185097ed0588195164619ea930ddd8274a5f32ad | Bin 0 -> 3648 bytes .../27711a87e06a50c81571c27c3aa403a6ad5dc55c | Bin 0 -> 2218 bytes .../298c3787ad1722b22569cbc405c464d2 | Bin 0 -> 4234 bytes .../2b95ba6d8141ce0d29ff279770903922 | Bin 0 -> 4234 bytes .../321fb3d758b86e37fc340ae2b09b8ed9fa73a4cb | Bin 0 -> 4234 bytes .../331a98b4e4c87840efea69223766ebd0e1736542 | Bin 0 -> 420 bytes .../352d73f841223ecb630b5836585d2ba7b0f9d883 | Bin 0 -> 2249 bytes .../3a84f409d4c117edfdebc508cd23e8fc | Bin 0 -> 3194 bytes .../3ef5cc982c0b45f69a26fd0f7d376415fdebabd1 | Bin 0 -> 220 bytes .../401c7de8e122018a0e17f57c93db7ee49ab0e906 | Bin 0 -> 865 bytes .../52fee71bb8c9c79068e1fe580677ad739a2d0415 | Bin 0 -> 361 bytes .../57b11507813d5727b7789354d888eda83d5f3d86 | Bin 0 -> 2846 bytes .../57dff0fa53ee0ef24a43cca6ab0523bfdc1f720d | Bin 0 -> 864 bytes .../5c42d3df0dc400a7a4175b8d4eec6cc8ee2437b2 | Bin 0 -> 2246 bytes .../5cca20637ae75fddad9370ee930837baef8aeb43 | Bin 0 -> 4234 bytes .../5d34bc9cef0c844b9c5ebe948145c4ca11b5ca09 | Bin 0 -> 2639 bytes .../5e162fe883bd12fb1c4131d4e0c979a12bd15eac | Bin 0 -> 76 bytes .../5e83f8faab9c1a51a33d5e29edbb9dcec23c6092 | Bin 0 -> 1412 bytes .../61b29dc2fcef7b6fbe3e0cc88769a7ef | Bin 0 -> 3194 bytes .../6361eca190157ece389665ee523ccc3aefcd957f | Bin 0 -> 3708 bytes .../65150515ab3b11d657519b22bb887d74e94b2d7f | Bin 0 -> 4234 bytes .../656f38ef6dcd58c6a909d61db11f777def69c394 | Bin 0 -> 1406 bytes .../66e0d2cafd592bf9d61ad900fade8ee530d5f3d7 | Bin 0 -> 203 bytes .../6b5b42cb105a2c4c5fd6034e9885cbe457f1b50c | Bin 0 -> 361 bytes .../722ed0197cb92ecbf9745edb38275e7a9aaf322f | Bin 0 -> 454 bytes .../77bdd2efdf328366cbbf3c5688768dc0a88d02b1 | Bin 0 -> 16 bytes .../7841bfa002c05c61d5a5d9241f214cc17a336166 | Bin 0 -> 864 bytes .../7899e22fc83f6be28e9130c4a1c91a48 | Bin 0 -> 4234 bytes .../7dddccaebd16ae0c26daeffc42df50f529891119 | Bin 0 -> 2249 bytes .../8157442eee4bbfdd9716e264b11085d61a9955b7 | Bin 0 -> 48 bytes .../81ff28ed63d5435ddc4c8771dd5d40aa658cbbe0 | Bin 0 -> 2052 bytes .../820c8c0d33c18f6c4d9edd314e91289186931ad0 | Bin 0 -> 1318 bytes .../849e9d7cee1c52105242327086997296e452b981 | Bin 0 -> 1237 bytes .../84ddb92c63e0fad7018f6069daf8779ce11501e2 | Bin 0 -> 1167 bytes .../86bc3d5dbb9313137502080e58551edd2e649c70 | Bin 0 -> 929 bytes .../87d94d88fe29d277c76e1a52042b02c092d5ae14 | Bin 0 -> 420 bytes .../8c4646f3357945c4e19a59ff79fffe3c874dbf16 | Bin 0 -> 189 bytes .../90632bc6dee4eb836f3d7db1d16446a9c8510080 | Bin 0 -> 3895 bytes .../94d06016aa949e8e7203217e4cc6625ded7f4244 | Bin 0 -> 3102 bytes .../9875819b9e5783e7489c29a81cc9d4279209956a | Bin 0 -> 22 bytes .../9c1cc734114b29aac6c51782d5c17e9dbe1faca2 | Bin 0 -> 3194 bytes .../9d2961871eeb201ef8a6f5503d8a8b62 | Bin 0 -> 3194 bytes .../9f39e11cdd88344a4894b678e5a04a810880064d | Bin 0 -> 972 bytes .../a350588a6dabe4376a066aed44ef8786d8e752e7 | Bin 0 -> 861 bytes .../a6101a79919d444e1fc50aefab5837c39e3f4a19 | Bin 0 -> 1237 bytes .../a9c8793f8fb063bec839ee1280406fe5396545e5 | Bin 0 -> 420 bytes .../ad4e9d2234e8599bdf12607c6b8cab4edae82c4e | Bin 0 -> 420 bytes .../b90b6830917919e94186d312f06481bd | Bin 0 -> 3194 bytes .../b98fd4cb1d7031240414301c19b03097c0035c6b | Bin 0 -> 857 bytes .../ba976fcdb4daf092ef17ce43bf2b78d9d8bc2aeb | Bin 0 -> 2262 bytes .../bc112b571eafee0f5a031f3c9cce6244216d128d | Bin 0 -> 4234 bytes .../c42b981c28a1715c375050f6fcf53f1d | Bin 0 -> 3194 bytes .../c6049874b33eadb016fccf0c5fa66e556ae069b9 | Bin 0 -> 3194 bytes .../c8697bf2369f6ab85f501376c4d93bb8a56974a3 | Bin 0 -> 420 bytes .../c8daf283e0aef2fd7b630c0430e05dc28f24ecf6 | Bin 0 -> 220 bytes .../cacff56e1af4b8fde912822da06b10fb8c545a19 | Bin 0 -> 1033 bytes .../ce4dcc22b1d595c49a25121c0b580104 | Bin 0 -> 4234 bytes .../d0cd71dbf039fd64cf42eff30da92a71a919226a | Bin 0 -> 587 bytes .../d5ce626ac3264bed6af5580e341a89406857cbb9 | Bin 0 -> 1760 bytes .../d77ada02e9bc8c24b2711eca6a8f52ae356bfc21 | Bin 0 -> 361 bytes .../d7eb9c5a0f9803df4c00390793b8ab57bd7c9484 | Bin 0 -> 3792 bytes .../dc1efccdeec17e151a1ec8228c09ab61c3040b33 | Bin 0 -> 35 bytes .../dcea22c66c60088165a2f1772036473f | Bin 0 -> 4234 bytes .../de539ae7442fa05dafcfe1a021f0186ef74a2b0e | Bin 0 -> 103 bytes .../e2306b1d6b88d0ccc4e2c3a9edb07462a5a32215 | Bin 0 -> 110 bytes .../e2778da0240fdd15ef5844905d81c4e05f34a8bd | Bin 0 -> 3194 bytes .../e6642e9266875f9d908942e534bf898103a2c794 | Bin 0 -> 2186 bytes .../ec6cdb929c08d8daf2bd7fc185fbf4d787b45120 | Bin 0 -> 1942 bytes .../ed8636357f79439b6a03eb14469b686cc401a1c9 | Bin 0 -> 3895 bytes .../ee313e9acecb5c688ce8c9bb10e70e136fbb9c6d | Bin 0 -> 3616 bytes .../ef689af320e7d9e22231109faae2e8149cb86e1c | Bin 0 -> 834 bytes .../fda6b9a9f6ffdf4765c00465619c7ceb3f7db2e4 | Bin 0 -> 1136 bytes .../ffe829bb0adac20d9c0756f68a22d1255e4fdb54 | Bin 0 -> 3194 bytes .../013a29ea098a178f8a36741c9fd91144 | 48 + .../0875575fb76d630ccb19c5da8aab66b2 | 1 + .../7e7f58fc443a11a0a2c5d9b643b7e99b | 1 + .../849a23936269a261c0370b5e9abe2416 | 1 + .../85282c1696d98b9843ce3e8bd1cd899f | 1 + .../90388b9c8093d8adedad0644b618da87 | 33 + .../9fa2f86ea6d3ade36e961247c3026f8d | 33 + .../c4f18ca60a84e9869a28faf6f65dc758 | 32 + .../d456ee029700adef5d28438593010223 | 1 + .../e9f0ff6ee8d691ae69d2ecb4710030a2 | 36 + .../010dc3d4b05288fcc40de2721052b3dc699f1cb3 | Bin 0 -> 233 bytes .../0555cd5e9d99629819cc985285f80da0f00be1e9 | Bin 0 -> 474 bytes .../0a0352aa168803ff65455792d9f6ee555c3e7c3f | Bin 0 -> 232 bytes .../0ed54162df93ef8d00f993ce6b59ba422903d381 | Bin 0 -> 221 bytes .../1547b448171c700613c3946d730de496c9b9863f | Bin 0 -> 260 bytes .../17859046cbe4ac598a645173d679ce2a52c6afba | Bin 0 -> 525 bytes .../1df76c07817fbc3653a26f34d97658e9973627c2 | Bin 0 -> 666 bytes .../1f0717f8856d7782e3ab7992d3a72d783a018443 | Bin 0 -> 122 bytes .../23b911e4ce936def88bc9a46b8b433c0e83fba2a | Bin 0 -> 375 bytes .../25592201c3edff0578dbdac6b0e4f2be109ce151 | Bin 0 -> 329 bytes .../266fd8495e0b8eb64387c1a62264185e061fee73 | Bin 0 -> 360 bytes .../27f178cf415b4ff8671131ddf1d042dafac2fb3e | Bin 0 -> 677 bytes .../2a0bdc4d9cc5ea5bb21dd256d6ac96075376a94f | Bin 0 -> 246 bytes .../2e5d25add6adc68e0457b358c7a34abf3d41c938 | Bin 0 -> 165 bytes .../2e6c5b6a766dd5e9bd41eacfd0a36572bd2f7544 | Bin 0 -> 320 bytes .../2e9c935cf82f6ca640e9a9abc3c30a578ad46176 | Bin 0 -> 666 bytes .../2fcf1ed4477f7eaee028f5b3f9edeb5f1a737826 | Bin 0 -> 507 bytes .../3480713774f590908ca5dba16d121cdfb8fba62b | Bin 0 -> 665 bytes .../39289afcec60d98802b333e0fbb1da4d7aed4ce5 | Bin 0 -> 247 bytes .../3adc488e21d4aca7bed9422f0241a42d0f93e7d9 | Bin 0 -> 366 bytes .../3cbf274da522483dc991fad9df43a22ac4fb3173 | Bin 0 -> 474 bytes .../3d840cdff7f5ad16fe8bcb985ed4946c03459432 | Bin 0 -> 666 bytes .../3f1e6753c1fca958e859189857449746592158ea | Bin 0 -> 94 bytes .../3fa4075993cb0f9bfa8eea785174a2038a69aa1b | Bin 0 -> 343 bytes .../4023a373e977be58413e55350380310c5dd1fd6a | Bin 0 -> 241 bytes .../40caba69dce1cfc48e0e43184d2bfbc6daa4399a | Bin 0 -> 470 bytes .../41841e9561d8135945c1c1e55ab9e9a1e933653b | Bin 0 -> 247 bytes .../41d40f2d66fa43e34537385594ee9911e65deadf | Bin 0 -> 677 bytes .../421bd39810b50309a71adb2dadc3b19f01a52312 | Bin 0 -> 221 bytes .../446c305b2c0665736f94fb2b62dbdef445eff0cf | Bin 0 -> 174 bytes .../449cee952bb645f6f4241a6665d3c6028c073c7a | Bin 0 -> 374 bytes .../45520b07609978c5aa3516d803527438b93fbadb | Bin 0 -> 158 bytes .../4da74a34bcede234b0415f77fbd87d70bf9a777e | Bin 0 -> 94 bytes .../51db5d31d2c5300d34831d9f23bcdd0aff9a998b | Bin 0 -> 677 bytes .../5cde2a9167798cb77f10abbfb2640a5c357f99fc | Bin 0 -> 507 bytes .../5e352fc10ac476cfbe1d755f092e069820223249 | Bin 0 -> 169 bytes .../63661677dd1306cec4b5a565190e65adf2446e52 | Bin 0 -> 374 bytes .../65887ed3db382aab1d9485c500f4401318d303b9 | Bin 0 -> 224 bytes .../67b5181f8f0644597e9bde539e8f083b5cacd0e7 | Bin 0 -> 165 bytes .../74c9dcf7afee2a6cb1ab3a2c0de744d1b03c1466 | Bin 0 -> 307 bytes .../792181ca19e6ded261434e588bb7fc2a4816d4ce | Bin 0 -> 544 bytes .../79f0e2a475487f8fa69e68c1cc947c5851bda741 | Bin 0 -> 355 bytes .../7e5fcdfeb557ce379ed96925c68505eaac0112db | Bin 0 -> 315 bytes .../7eec7530acf34b3a96fa9189783453999f7b6838 | Bin 0 -> 671 bytes .../80114bf9781bffc9db411413d83541d8deaaf7c1 | Bin 0 -> 343 bytes .../80425fb92bb86627e854892f23823fa804e5fdc3 | Bin 0 -> 441 bytes .../821cdd6eeb919a8dd7f35289abbd583828dd4945 | Bin 0 -> 677 bytes .../83e1a31785285338b0ddb3334b0ed098e63dedde | Bin 0 -> 285 bytes .../8a4c8100dedd0fb5f2a8b468c678f7ad8269deeb | Bin 0 -> 666 bytes .../8ae8268c24dc866c1edb3826b93a1c75dbf74ff4 | Bin 0 -> 677 bytes .../90f72038cc627f34f074ea72eadbba87a5e3e288 | Bin 0 -> 677 bytes .../92b67faee4a49df2cdbed785e27b4a1cddcfffa3 | Bin 0 -> 507 bytes .../9463810467aacdc9923b2b20a2236116b760d75b | Bin 0 -> 258 bytes .../94d7c96aea32ad41ce643d35b951a6d8990b81d6 | Bin 0 -> 546 bytes .../98cc7e9fe87df914d89a0aef008930f27b3c26f5 | Bin 0 -> 311 bytes .../99172dfdb4f59aaced29c7681ac6e6ce8356e814 | Bin 0 -> 104 bytes .../9ae3b647d895af97fe872c0b1442df7b5b767160 | Bin 0 -> 332 bytes .../9d2b1d2121b0508a4fa8d1508adb9d05633fdac3 | Bin 0 -> 222 bytes .../a335af37917ccf0c8b11bb884a3a74f3f1d2a7c6 | Bin 0 -> 677 bytes .../a738609112d3a6772c50a71e2c3504ebc515b709 | Bin 0 -> 337 bytes .../a8cecab5d917da5a4729632a7a18c564d7e1607d | Bin 0 -> 258 bytes .../ade919ab2b4a458e806575c941dfe50ae3fd3621 | Bin 0 -> 677 bytes .../b1251621a5eb5e7fda9cac9baead1c993a285c36 | Bin 0 -> 277 bytes .../b1516b78c3dfe77eeb554985fd7344c0478fbbcb | Bin 0 -> 258 bytes .../b41241740f5f8ad2c1d408f7bb6a313bd863c158 | Bin 0 -> 133 bytes .../b799c8596523a7ebeb8e11ada08818c10f7eabfc | Bin 0 -> 582 bytes .../ba48d0521a111222dc95a3a997c7c92dea5f4443 | Bin 0 -> 249 bytes .../c01457c6889fb1b597d308363a36412c0b7f90e7 | Bin 0 -> 497 bytes .../c82ebc0d6688d104af04fd20d6d3da591dc391f7 | Bin 0 -> 198 bytes .../c9a03eb758dd84e954e3d70916e2311e8fd21f3c | Bin 0 -> 249 bytes .../cf892756b33578a54ab20044514e573328d2f1d7 | Bin 0 -> 249 bytes .../d3bc3f158a63f1d50b474addd3f7b3d17f23e8e9 | Bin 0 -> 507 bytes .../d4906950aa9d60ad09dc0f5413c3d88080c3bc37 | Bin 0 -> 262 bytes .../da31578a8068bad65e1c7a3d06e8f543a2a0bc65 | Bin 0 -> 332 bytes .../dd4a9b5d0740679c249fc884efc499433b29436b | Bin 0 -> 666 bytes .../deea4ecc6f0b2a6d89fd25ff76762299f21602fb | Bin 0 -> 677 bytes .../e1040c7ffcb39915e0f539018c81f9798924cba6 | Bin 0 -> 94 bytes .../e381dc85682cc33ad99f622b89d145b47f7d6392 | Bin 0 -> 485 bytes .../ea24498fc7a144fccc6f1665ebf7020df803dd1a | Bin 0 -> 677 bytes .../eaa5d677e797c07bac98c3c7051abad91852e7c6 | Bin 0 -> 507 bytes .../ed7871269315725535d8bffec7836c45a3fc5c26 | Bin 0 -> 527 bytes .../ee8460f4077064c5a2137075b48eba7d3db5c570 | Bin 0 -> 94 bytes .../ef09f26e0ee61329f84a9f589629a865ae9ee0a6 | Bin 0 -> 276 bytes .../f477da4d7d8ff2066041e1dd5ee4e833b7111a1a | Bin 0 -> 527 bytes .../f8a379b2498a4eb452a85791a49adf065dab59ae | Bin 0 -> 666 bytes .../fe67bccb06f2174523943cc684518fcf1f7f8046 | Bin 0 -> 80 bytes .../ff1e67d17c1c27ef0d97900d0ea276b563a64628 | Bin 0 -> 271 bytes .../02cc44cdfec1d9d0d0c66c5a5f40d3d20e4c4c3a | Bin 0 -> 11564 bytes .../087e1d7fae1c1ddcbaa3b5f822a171ad15498186 | Bin 0 -> 146 bytes .../0f61c33027394a0f14d29dcd22f405cad943b7cf | Bin 0 -> 29936 bytes .../10cdebea1659c21a0248f88654ae41f62786abf1 | Bin 0 -> 58657 bytes .../126e68def9fd973a100e0f66cadf09448a716b57 | Bin 0 -> 9209 bytes .../1275d41ebf8788ce3a949352e4bc654b04012da3 | Bin 0 -> 70 bytes .../1a7f1c407fb3864ddb559f88f373a21d1be51584 | Bin 0 -> 35640 bytes .../1c3e1c91f187f6bcea86f172ff5bbbd955a9654d | Bin 0 -> 57 bytes .../300fe1e0a47543037cbf0243b6756c9aa48799c4 | Bin 0 -> 72238 bytes .../31ec5b0134bedcfe283f4978e6e65b7d35d5d4ad | Bin 0 -> 26123 bytes .../4e7cbb27667bcfca92838aa8020749990013a9b1 | Bin 0 -> 66423 bytes .../585e469231d202812bfba8285fb30c8e31c857b9 | Bin 0 -> 70833 bytes .../58eab6bc2386e2ef43fe4f55cb6ad3611399d5de | Bin 0 -> 22 bytes .../63448c6a9feb8c72b3e82af4d735ec2e62ddd328 | Bin 0 -> 58203 bytes .../6874d5b1c7a64b596c61f24877d422e89bebe58b | Bin 0 -> 25086 bytes .../7501f79cb067da108020579ed654349c7933d22f | Bin 0 -> 54715 bytes .../782051f8120182b860c7fe1b265179cfa2fe03fd | Bin 0 -> 66439 bytes .../793feab2deb35e284a975f6527d76a8be5540fe6 | Bin 0 -> 61 bytes .../7f41ec3a9805c6b8f3656c4f9f6d0ff7dbf8a329 | Bin 0 -> 6150 bytes .../8210dc595a2652f2f812093b01e239e7918ea065 | Bin 0 -> 55329 bytes .../8dffe4c5c26d891b578fd2ea4b9adfc0c96ad5f7 | Bin 0 -> 71409 bytes .../91d787a9298ddc015efa783a92c4bdba8af0d7de | Bin 0 -> 44 bytes .../92c065286f956f086e977556358f6b54b12bcacc | Bin 0 -> 315 bytes .../a35c9bb71792b60a13dea23a41b41847ad4b93d6 | Bin 0 -> 44 bytes .../a6ea960c7b4d42772888280277b26e645ceee904 | Bin 0 -> 22470 bytes .../aa526aa853333f0bb11804b5243df411452cecd2 | Bin 0 -> 21331 bytes .../ca533cd26c7ca6bf69e62351b265ded496fdf1d9 | Bin 0 -> 52741 bytes .../f38c61da15f2cb7a39ff02e69f0b00e99f37ec86 | Bin 0 -> 66555 bytes .../f88f1012473e6cfcc9b39b2552f682b2f73eff8c | Bin 0 -> 54757 bytes .../fa79819c5de04bc06c69bec3fa7f2e982826ea2f | Bin 0 -> 20280 bytes .../fce08de222896ac3a20657a3b4f42d5b6c54a96a | Bin 0 -> 69522 bytes .../4c01a1504da9de2216894743ecc44424 | 1 + .../5bf16424630b5afbcffe711fb9834440 | 1 + .../a7185605aef0a8fd682fcb4656e4a736 | 1 + .../d5606def44fdbb9385dd764612069db0 | Bin 0 -> 42 bytes .../dbac766f3160de65894bf5153f478146 | 1 + .../e85ff62f6d457666f54a37a19a115a24 | 1 + .../00fd47bf73afcb72e7ed51bffd5f5fec | 1 + .../14908973e6720513a5f37676cb9fcc29 | 1 + .../2779ba7c4d23eee9f79efa3660084c5d | 1 + .../5bf16424630b5afbcffe711fb9834440 | 1 + .../89734a96b93275e495a9498b806fafe1 | 1 + .../d5606def44fdbb9385dd764612069db0 | Bin 0 -> 42 bytes .../2db83ea58639b6d7d585fa12e3947a82 | 1 + .../36b4a931886b941dc41180050d12ca94 | 1 + .../50a2fabfdd276f573ff97ace8b11c5f4 | 1 + .../62edb2a1eee34b001652cd86584becf2 | 1 + .../90013d1ec28c46a5c00574e60c70b6fc | 1 + .../94f3e3cee6957ce5815326d6788c85f4 | 1 + .../96f547bc04bb913da0bc08915238ebd8 | 1 + .../d3a903d18fc11e1f35c572ad4da690ed | 1 + .../e3b629c92af44260c189deb32d6f06f3 | 1 + .../f03eecf3bcfe4967a1888156a3115c8d | 1 + .../fa54ca9186f77122ae2a82684a062e16 | 1 + .../dictionaries/decode_json_example.dict | 6 + .../fuzzing/dictionaries/decode_png.dict | 50 + .../fuzzing/dictionaries/decode_wav.dict | 4 + .../kernels/fuzzing/encode_base64_fuzz.cc | 2 +- .../core/kernels/fuzzing/fuzz_session.h | 4 +- .../core/kernels/fuzzing/string_split_fuzz.cc | 3 +- .../fuzzing/tf_ops_fuzz_target_lib.bzl | 32 +- tensorflow/core/kernels/list_kernels.cc | 44 +- tensorflow/core/kernels/list_kernels.cu.cc | 15 +- tensorflow/core/kernels/list_kernels.h | 384 +- .../core/kernels/maxpooling_op_gpu.cu.cc | 12 + tensorflow/core/kernels/mkl_avgpooling_op.cc | 129 +- tensorflow/core/kernels/mkl_conv_ops.cc | 64 +- tensorflow/core/kernels/mkl_lrn_op.cc | 722 +- tensorflow/core/kernels/mkl_maxpooling_op.cc | 161 +- .../core/kernels/mkl_pooling_ops_common.cc | 30 +- .../core/kernels/mkl_pooling_ops_common.h | 29 +- .../kernels/mkl_quantized_pooling_ops_test.cc | 201 + tensorflow/core/kernels/mkl_softmax_op.cc | 4 +- .../core/kernels/partitioned_function_ops.cc | 43 +- .../kernels/quantize_and_dequantize_op.cc | 29 +- .../core/kernels/quantize_and_dequantize_op.h | 81 +- .../quantize_and_dequantize_op_gpu.cu.cc | 4 +- .../quantize_and_dequantize_op_test.cc | 136 +- .../quantized_resize_bilinear_op_test.cc | 2 +- tensorflow/core/kernels/ragged_gather_op.cc | 6 +- tensorflow/core/kernels/scan_ops_gpu.cu.cc | 266 +- tensorflow/core/kernels/scan_ops_test.cc | 146 + tensorflow/core/kernels/scatter_nd_op.cc | 164 + tensorflow/core/kernels/stage_op.cc | 2 +- tensorflow/core/kernels/tensor_array_ops.cc | 6 +- tensorflow/core/kernels/tensor_forest/BUILD | 53 + .../kernels/tensor_forest/prediction_ops.cc | 93 + .../kernels/tensor_forest/resource_ops.cc | 135 + .../core/kernels/tensor_forest/resources.cc | 59 + .../core/kernels/tensor_forest/resources.h | 63 + tensorflow/core/kernels/training_ops.cc | 390 + tensorflow/core/kernels/training_ops.h | 23 + .../core/kernels/training_ops_gpu.cu.cc | 62 + tensorflow/core/kernels/training_ops_test.cc | 78 + tensorflow/core/kernels/unicode_ops.cc | 355 +- tensorflow/core/lib/core/threadpool.cc | 21 +- tensorflow/core/lib/core/threadpool.h | 6 +- tensorflow/core/lib/png/png_io.cc | 6 +- tensorflow/core/nccl/BUILD | 38 +- tensorflow/core/nccl/nccl_manager.cc | 66 +- tensorflow/core/nccl/nccl_manager.h | 8 +- tensorflow/core/nccl/nccl_manager_test.cc | 49 +- tensorflow/core/ops/array_ops.cc | 61 +- .../core/ops/compat/ops_history.v1.pbtxt | 4080 +-- tensorflow/core/ops/dataset_ops.cc | 300 - .../core/ops/experimental_dataset_ops.cc | 294 +- tensorflow/core/ops/functional_ops.cc | 4 +- tensorflow/core/ops/list_ops.cc | 249 +- tensorflow/core/ops/nn_ops.cc | 11 +- tensorflow/core/ops/ops.pbtxt | 2419 +- tensorflow/core/ops/sparse_ops.cc | 4 +- tensorflow/core/ops/sparse_ops_test.cc | 7 + tensorflow/core/ops/string_ops.cc | 60 + tensorflow/core/ops/tensor_forest_ops.cc | 79 + tensorflow/core/ops/training_ops.cc | 66 + tensorflow/core/platform/cpu_feature_guard.cc | 2 +- .../core/platform/default/build_config.bzl | 3 + .../core/platform/default/device_tracer.cc | 55 +- tensorflow/core/platform/default/logger.cc | 34 + tensorflow/core/platform/default/logging.cc | 147 +- tensorflow/core/platform/default/logging.h | 44 +- tensorflow/core/platform/env.h | 2 + tensorflow/core/platform/logger.h | 51 + tensorflow/core/platform/numa_test.cc | 2 +- tensorflow/core/platform/platform_strings.cc | 64 + tensorflow/core/platform/platform_strings.h | 364 + .../core/platform/platform_strings_computed.h | 735 + .../core/platform/platform_strings_test.cc | 146 + .../core/platform/posix/posix_file_system.cc | 11 +- tensorflow/core/platform/regexp.h | 3 +- .../platform/windows/windows_file_system.cc | 3 + .../core/profiler/internal/tfprof_code.cc | 2 +- .../core/profiler/internal/tfprof_node.cc | 2 +- tensorflow/core/protobuf/config.proto | 12 + tensorflow/core/protobuf/master.proto | 2 +- .../core/protobuf/rewriter_config.proto | 2 +- tensorflow/core/util/dump_graph.cc | 131 + tensorflow/core/util/dump_graph.h | 52 + tensorflow/core/util/dump_graph_test.cc | 62 + tensorflow/core/util/mkl_util.h | 3 + .../core/util/permutation_input_iterator.h | 6 +- .../core/util/permutation_output_iterator.h | 129 + tensorflow/core/util/sparse/sparse_tensor.h | 50 +- tensorflow/core/util/stats_calculator.cc | 4 +- tensorflow/core/util/strided_slice_op.cc | 21 +- .../core/util/tensor_bundle/tensor_bundle.cc | 4 +- tensorflow/core/util/tensor_format.h | 3 +- tensorflow/core/util/tensor_ops_util.h | 128 + tensorflow/examples/adding_an_op/fact_test.py | 2 + .../examples/adding_an_op/zero_out_1_test.py | 2 + .../examples/adding_an_op/zero_out_2_test.py | 5 + .../examples/adding_an_op/zero_out_3_test.py | 9 +- .../autograph/integration_tests/BUILD | 2 - .../autograph/integration_tests/keras_test.py | 6 +- .../integration_tests/list_literals_test.py | 2 +- .../regression/custom_regression.py | 5 +- .../get_started/regression/dnn_regression.py | 5 +- .../linear_regression_categorical.py | 5 +- .../reading_data/fully_connected_reader.py | 2 +- .../examples/learn/iris_custom_decay_dnn.py | 4 +- .../examples/learn/iris_custom_model.py | 4 +- .../examples/speech_commands/freeze_test.py | 4 + .../speech_commands/input_data_test.py | 11 +- .../speech_commands/label_wav_test.py | 2 +- .../examples/speech_commands/models_test.py | 6 + .../speech_commands/wav_to_features_test.py | 4 +- .../examples/tutorials/layers/cnn_mnist.py | 9 +- tensorflow/go/README.md | 2 +- tensorflow/go/graph.go | 76 +- tensorflow/go/graph_test.go | 258 + tensorflow/go/op/gradients.go | 50 + tensorflow/go/op/gradients_test.go | 246 + tensorflow/go/op/wrappers.go | 2763 +- tensorflow/java/README.md | 2 +- .../test/java/org/tensorflow/TensorTest.java | 46 +- tensorflow/lite/BUILD | 2 + tensorflow/lite/build_def.bzl | 10 + tensorflow/lite/builtin_ops.h | 5 + tensorflow/lite/c/builtin_op_data.h | 18 + tensorflow/lite/c/builtin_op_data_test.cc | 1 + tensorflow/lite/c/c_api_internal.c | 15 +- tensorflow/lite/c/c_api_internal.h | 21 +- tensorflow/lite/c/c_api_internal_test.cc | 1 + .../lite/core/api/flatbuffer_conversions.cc | 35 + tensorflow/lite/core/subgraph.cc | 970 + tensorflow/lite/core/subgraph.h | 501 + tensorflow/lite/delegates/flex/BUILD | 3 + tensorflow/lite/delegates/flex/buffer_map.cc | 5 + tensorflow/lite/delegates/flex/delegate.cc | 54 +- .../lite/delegates/flex/delegate_data.cc | 7 +- .../lite/delegates/flex/delegate_test.cc | 19 + tensorflow/lite/delegates/flex/kernel.cc | 24 +- tensorflow/lite/delegates/flex/kernel_test.cc | 4 +- tensorflow/lite/delegates/flex/test_util.cc | 45 +- tensorflow/lite/delegates/flex/test_util.h | 2 + tensorflow/lite/delegates/flex/util.cc | 4 + .../lite/delegates/nnapi/nnapi_delegate.cc | 2 +- .../delegates/nnapi/nnapi_delegate_test.cc | 16 + .../ios/camera/CameraExampleViewController.h | 4 +- .../ios/camera/CameraExampleViewController.mm | 8 +- tensorflow/lite/examples/ios/camera/Podfile | 2 +- tensorflow/lite/examples/ios/simple/Podfile | 2 +- .../ios/simple/RunModelViewController.mm | 8 +- .../lstm/unidirectional_sequence_lstm_test.py | 2 +- tensorflow/lite/experimental/micro/README.md | 42 + .../micro/examples/micro_speech/.gitignore | 1 + .../micro/examples/micro_speech/BUILD | 211 +- .../examples/micro_speech/CMSIS/README.md | 10 + .../CMSIS/arm_cmplx_mag_squared_q10p6.c | 141 + .../CMSIS/arm_cmplx_mag_squared_q10p6.h | 33 + .../micro_speech/CMSIS/create_constants.py | 62 + .../micro/examples/micro_speech/CMSIS/hann.h | 1 - .../examples/micro_speech/CMSIS/hanning.cc | 67 + .../examples/micro_speech/CMSIS/hanning.h | 24 + .../CMSIS/no_power_spectrum_data.h | 29 - .../micro_speech/CMSIS/preprocessor.cc | 44 +- .../micro_speech/CMSIS/preprocessor_test.cc | 63 - .../examples/micro_speech/CMSIS/sin_1k.cc | 67 + .../examples/micro_speech/CMSIS/sin_1k.h | 24 + .../CMSIS/yes_power_spectrum_data.h | 29 - .../examples/micro_speech/apollo3/.gitignore | 4 + .../examples/micro_speech/apollo3/README.md | 72 + .../micro_speech/apollo3}/_main.c | 0 .../examples/micro_speech/apollo3/apollo3.h | 23332 ++++++++++++++++ .../apollo3/captured_data_to_wav.py | 40 + .../micro_speech/apollo3/compare_1k.py | 153 + .../micro_speech/apollo3/preprocessor_1k.cc | 57 + .../apollo3/preprocessor_1k_cmsis_test.cmd | 44 + .../apollo3/preprocessor_1k_micro_test.cmd | 32 + .../apollo3/preprocessor_test.cmd | 18 + .../apollo3/pushbutton_cmsis_scores.cmd | 33 + .../apollo3/pushbutton_cmsis_voice.cmd | 24 + .../micro_speech/apollo3/pushbutton_main.c | 339 + .../micro_speech/apollo3/pushbutton_test.cc | 120 + .../micro_speech/apollo3/system_apollo3.c | 116 + .../micro_speech/apollo3/system_apollo3.h | 72 + .../examples/micro_speech/audio_provider.cc | 33 + .../examples/micro_speech/audio_provider.h | 36 + .../micro_speech/audio_provider_test.cc | 44 + .../examples/micro_speech/feature_provider.cc | 121 + .../examples/micro_speech/feature_provider.h | 48 + .../micro_speech/feature_provider_test.cc | 38 + .../micro_speech/fixed_point/preprocessor.cc | 44 +- .../micro/examples/micro_speech/main.cc | 112 + ...wer_spectrum_data.cc => model_settings.cc} | 11 +- .../examples/micro_speech/model_settings.h | 42 + .../examples/micro_speech/preprocessor.cc | 46 +- .../examples/micro_speech/preprocessor.h | 8 + .../micro_speech/preprocessor_test.cc | 1 + .../yes_power_spectrum_data.cc => timer.cc} | 10 +- .../micro/examples/micro_speech/timer.h | 31 + .../micro/examples/micro_speech/timer_test.cc | 49 + .../experimental/micro/testing/micro_test.h | 18 + .../experimental/micro/tools/make/Makefile | 63 +- .../tools/make/targets/apollo3evb/README.md | 13 - .../targets/apollo3evb/get_yesno_data.cmd | 10 - .../targets/apollo3evb/prep_apollo3_files.sh | 21 +- .../targets/apollo3evb/preprocessor_test.cmd | 4 - .../apollo3evb/replace_calculated_data.py | 33 - .../make/targets/apollo3evb_makefile.inc | 76 +- .../tools/make/targets/cmsis-dsp_makefile.inc | 9 - .../audio_microfrontend_op_test.py | 4 +- tensorflow/lite/experimental/writer/BUILD | 9 +- .../writer/option_writer_generator.cc | 4 + tensorflow/lite/g3doc/_book.yaml | 6 +- tensorflow/lite/g3doc/_index.yaml | 6 +- tensorflow/lite/g3doc/convert/index.md | 14 +- tensorflow/lite/g3doc/convert/python_api.md | 29 +- tensorflow/lite/g3doc/devguide.md | 181 +- tensorflow/lite/g3doc/models.md | 7 +- tensorflow/lite/g3doc/tf_ops_compatibility.md | 260 +- tensorflow/lite/g3doc/using_select_tf_ops.md | 249 + tensorflow/lite/interpreter.cc | 931 +- tensorflow/lite/interpreter.h | 320 +- tensorflow/lite/interpreter_test.cc | 16 +- .../java/org/tensorflow/lite/DataType.java | 9 +- .../main/java/org/tensorflow/lite/Tensor.java | 2 + tensorflow/lite/java/src/main/native/BUILD | 1 + .../native/nativeinterpreterwrapper_jni.cc | 2 + .../lite/java/src/main/native/tensor_jni.cc | 115 +- .../org/tensorflow/lite/DataTypeTest.java | 1 + .../lite/NativeInterpreterWrapperTest.java | 47 + tensorflow/lite/java/src/testdata/string.bin | Bin 0 -> 584 bytes tensorflow/lite/kernels/BUILD | 57 + tensorflow/lite/kernels/activations.cc | 138 +- tensorflow/lite/kernels/activations_test.cc | 137 +- tensorflow/lite/kernels/conv.cc | 16 +- tensorflow/lite/kernels/eigen_support.cc | 13 +- tensorflow/lite/kernels/elementwise.cc | 13 + tensorflow/lite/kernels/elementwise_test.cc | 13 + tensorflow/lite/kernels/fill.cc | 141 + tensorflow/lite/kernels/fill_test.cc | 94 + tensorflow/lite/kernels/fully_connected.cc | 2 +- tensorflow/lite/kernels/gather.cc | 2 +- tensorflow/lite/kernels/hashtable_lookup.cc | 2 +- tensorflow/lite/kernels/internal/BUILD | 2 - .../kernels/internal/optimized/cblas_conv.h | 109 - .../internal/optimized/cblas_reference.h | 69 - .../internal/optimized/depthwiseconv_float.h | 28 +- .../internal/optimized/depthwiseconv_uint8.h | 28 +- .../depthwiseconv_uint8_3x3_filter.h | 168 +- .../internal/optimized/optimized_ops.h | 58 +- .../internal/reference/reference_ops.h | 79 +- .../lite/kernels/internal/tensor_ctypes.h | 10 + tensorflow/lite/kernels/internal/types.h | 12 + tensorflow/lite/kernels/mirror_pad.cc | 374 + tensorflow/lite/kernels/mirror_pad_test.cc | 189 + tensorflow/lite/kernels/pooling_test.cc | 43 + tensorflow/lite/kernels/reduce.cc | 36 +- tensorflow/lite/kernels/register.cc | 12 + tensorflow/lite/kernels/register.h | 1 - tensorflow/lite/kernels/skip_gram.cc | 4 +- tensorflow/lite/kernels/split_v.cc | 207 + tensorflow/lite/kernels/split_v_test.cc | 175 + tensorflow/lite/kernels/squared_difference.cc | 129 + .../lite/kernels/squared_difference_test.cc | 157 + tensorflow/lite/kernels/test_util.h | 3 +- .../lite/lib_package/create_ios_frameworks.sh | 6 +- .../android/smartreply/SmartReplyClient.java | 21 +- .../lite/models/smartreply/ops/normalize.cc | 2 +- .../lite/models/smartreply/predictor.cc | 2 +- tensorflow/lite/nnapi_delegate.cc | 92 +- tensorflow/lite/nnapi_delegate.h | 5 +- tensorflow/lite/nnapi_delegate_disabled.cc | 6 +- tensorflow/lite/optional_debug_tools.cc | 2 + tensorflow/lite/python/BUILD | 2 + tensorflow/lite/python/convert.py | 60 +- tensorflow/lite/python/convert_saved_model.py | 21 +- .../lite/python/convert_saved_model_test.py | 24 +- tensorflow/lite/python/convert_test.py | 58 + .../interpreter_wrapper.cc | 4 + tensorflow/lite/python/lite.py | 17 +- tensorflow/lite/python/lite_constants.py | 25 +- tensorflow/lite/python/lite_test.py | 30 +- tensorflow/lite/python/op_hint.py | 6 +- tensorflow/lite/python/tflite_convert.py | 33 +- tensorflow/lite/schema/schema.fbs | 36 + tensorflow/lite/schema/schema_generated.h | 652 +- tensorflow/lite/string_util.cc | 7 +- tensorflow/lite/string_util.h | 12 +- tensorflow/lite/string_util_test.cc | 37 +- tensorflow/lite/testing/generate_examples.py | 427 +- .../testing/generated_examples_zip_test.cc | 4 + tensorflow/lite/testing/tflite_driver.cc | 11 +- tensorflow/lite/testing/tflite_driver.h | 14 +- tensorflow/lite/toco/BUILD | 46 + tensorflow/lite/toco/README.md | 8 +- tensorflow/lite/toco/export_tensorflow.cc | 48 +- .../fuse_binary_into_following_affine.cc | 10 +- .../propagate_array_data_types.cc | 7 + .../propagate_fixed_sizes.cc | 147 + .../toco/graph_transformations/quantize.cc | 5 +- .../resolve_constant_gather.cc | 4 + .../resolve_reduce_attributes.cc | 5 + .../unroll_batch_matmul.cc | 3 +- tensorflow/lite/toco/import_tensorflow.cc | 72 +- tensorflow/lite/toco/model.h | 65 +- tensorflow/lite/toco/tflite/export.cc | 31 +- tensorflow/lite/toco/tflite/export_test.cc | 40 +- tensorflow/lite/toco/tflite/operator.cc | 95 +- tensorflow/lite/toco/tflite/operator_test.cc | 32 + .../lite/toco/tflite/whitelisted_flex_ops.cc | 1 + tensorflow/lite/toco/toco.cc | 82 +- tensorflow/lite/toco/toco_convert.cc | 108 + tensorflow/lite/toco/toco_convert.h | 34 + tensorflow/lite/toco/toco_convert_test.cc | 173 + tensorflow/lite/toco/toco_tooling.cc | 7 +- tensorflow/lite/toco/tooling_util.cc | 52 +- tensorflow/lite/toco/types.proto | 3 + .../lite/tools/benchmark/benchmark_model.cc | 49 +- .../lite/tools/benchmark/benchmark_model.h | 3 +- .../lite/tools/benchmark/benchmark_test.cc | 2 + .../tools/benchmark/benchmark_tflite_model.cc | 11 +- .../tools/benchmark/benchmark_tflite_model.h | 7 +- .../TFLiteBenchmark.xcodeproj/project.pbxproj | 30 +- tensorflow/lite/tools/make/Makefile | 8 + .../lite/tools/make/targets/ios_makefile.inc | 2 +- .../tools/optimize/g3doc/quantize_weights.md | 2 +- tensorflow/lite/tools/pip_package/MANIFEST.in | 1 + tensorflow/lite/tools/pip_package/README.md | 33 + .../tools/pip_package/build_pip_package.sh | 54 + tensorflow/lite/tools/pip_package/setup.py | 150 + tensorflow/lite/tutorials/mnist_tflite.py | 4 +- tensorflow/lite/util.h | 6 + tensorflow/opensource_only.files | 17 + tensorflow/python/BUILD | 199 +- tensorflow/python/__init__.py | 6 +- tensorflow/python/autograph/converters/BUILD | 2 - .../autograph/converters/asserts_test.py | 4 +- .../converters/builtin_functions_test.py | 4 + .../python/autograph/converters/call_trees.py | 22 +- .../autograph/converters/call_trees_test.py | 34 +- .../converters/continue_statements.py | 91 +- .../autograph/converters/control_flow.py | 42 +- .../autograph/converters/control_flow_test.py | 13 + .../converters/function_scopes_test.py | 5 + .../python/autograph/converters/lists_test.py | 8 +- .../converters/logical_expressions_test.py | 4 + .../converters/side_effect_guards_test.py | 33 +- .../autograph/converters/slices_test.py | 2 +- tensorflow/python/autograph/core/converter.py | 13 +- .../autograph/core/converter_testing.py | 6 +- .../python/autograph/core/errors_test.py | 10 +- .../autograph/core/function_wrapping_test.py | 2 + tensorflow/python/autograph/core/naming.py | 5 +- tensorflow/python/autograph/impl/BUILD | 2 - tensorflow/python/autograph/impl/api.py | 11 + tensorflow/python/autograph/impl/api_test.py | 77 +- .../python/autograph/impl/conversion.py | 35 +- .../autograph/lang/special_functions_test.py | 12 +- .../autograph/operators/control_flow.py | 4 +- .../autograph/operators/control_flow_test.py | 20 +- .../operators/data_structures_test.py | 27 +- .../autograph/operators/exceptions_test.py | 9 +- .../autograph/operators/logical_test.py | 17 +- .../autograph/operators/py_builtins_test.py | 32 +- .../python/autograph/operators/slices_test.py | 8 +- tensorflow/python/autograph/pyct/BUILD | 2 - .../python/autograph/pyct/inspect_utils.py | 22 + .../autograph/pyct/inspect_utils_test.py | 37 +- .../autograph/pyct/static_analysis/BUILD | 2 - .../pyct/static_analysis/liveness.py | 14 + .../python/autograph/utils/misc_test.py | 7 +- .../python/autograph/utils/py_func_test.py | 18 +- .../autograph/utils/tensor_list_test.py | 33 +- .../python/autograph/utils/type_check.py | 2 +- .../python/autograph/utils/type_check_test.py | 1 + tensorflow/python/client/device_lib.i | 7 +- tensorflow/python/client/session.py | 4 +- .../client/session_clusterspec_prop_test.py | 6 +- .../python/client/session_partial_run_test.py | 26 +- tensorflow/python/client/timeline_test.py | 5 +- tensorflow/python/client/virtual_gpu_test.py | 2 +- tensorflow/python/compat/BUILD | 5 +- tensorflow/python/compat/compat.py | 45 +- tensorflow/python/data/__init__.py | 2 + tensorflow/python/data/benchmarks/BUILD | 55 + .../python/data/benchmarks/batch_benchmark.py | 85 + .../data/benchmarks/filter_benchmark.py | 69 + .../from_tensor_slices_benchmark.py | 188 + .../python/data/benchmarks/map_benchmark.py | 135 + .../python/data/benchmarks/range_benchmark.py | 2 +- .../python/data/experimental/__init__.py | 15 +- .../python/data/experimental/benchmarks/BUILD | 96 +- .../benchmarks/autotune_benchmark.py | 187 + .../benchmarks/csv_dataset_benchmark.py | 130 + .../benchmarks/map_and_batch_benchmark.py | 131 +- .../experimental/benchmarks/map_benchmark.py | 245 - .../benchmarks/map_vectorization_benchmark.py | 194 + .../benchmarks/matching_files_benchmark.py | 102 + .../benchmarks/optimize_benchmark.py | 120 + .../benchmarks/unbatch_benchmark.py | 107 + .../data/experimental/kernel_tests/BUILD | 60 +- .../kernel_tests/batch_dataset_op_test.py | 688 - .../bucket_by_sequence_length_test.py | 22 +- .../kernel_tests/cardinality_test.py | 158 + .../kernel_tests/copy_to_device_test.py | 238 +- .../experimental/kernel_tests/counter_test.py | 23 +- .../kernel_tests/csv_dataset_test.py | 99 - .../dense_to_sparse_batch_test.py | 41 +- .../directed_interleave_dataset_test.py | 24 +- .../kernel_tests/enumerate_dataset_test.py | 15 +- .../kernel_tests/filter_dataset_op_test.py | 6 +- .../function_buffering_resource_test.py | 248 - .../kernel_tests/get_single_element_test.py | 13 + .../kernel_tests/group_by_reducer_test.py | 22 +- .../kernel_tests/group_by_window_test.py | 102 +- .../kernel_tests/ignore_errors_test.py | 34 +- .../kernel_tests/indexed_dataset_ops_test.py | 14 +- .../make_batched_features_dataset_test.py | 103 +- .../kernel_tests/make_csv_dataset_test.py | 32 +- .../make_tf_record_dataset_test.py | 32 +- .../kernel_tests/map_and_batch_test.py | 109 +- .../kernel_tests/map_defun_op_test.py | 6 +- .../kernel_tests/matching_files_test.py} | 125 +- .../kernel_tests/optimization/BUILD | 25 +- .../optimization/assert_next_dataset_test.py | 36 +- .../optimization/filter_fusion_test.py | 41 +- .../optimization/hoist_random_uniform_test.py | 41 +- .../optimization/latency_all_edges_test.py | 58 +- .../optimization/make_numa_aware_test.py | 12 +- .../optimization/map_and_batch_fusion_test.py | 16 +- .../map_and_filter_fusion_test.py | 34 +- .../optimization/map_fusion_test.py | 32 +- .../optimization/map_parallelization_test.py | 25 +- .../optimization/map_vectorization_test.py | 118 +- .../optimization/model_dataset_test.py | 171 +- .../optimization/noop_elimination_test.py | 18 +- .../optimization/optimize_dataset_test.py | 197 +- .../shuffle_and_repeat_fusion_test.py | 26 +- .../kernel_tests/override_threadpool_test.py | 108 +- .../kernel_tests/parallel_interleave_test.py | 85 +- .../parse_example_dataset_test.py | 4 + .../kernel_tests/prefetch_to_device_test.py | 116 +- .../kernel_tests/rejection_resample_test.py | 14 +- .../kernel_tests/restructured_dataset_test.py | 2 + .../experimental/kernel_tests/scan_test.py | 32 +- .../kernel_tests/serialization/BUILD | 11 +- .../checkpoint_input_pipeline_hook_test.py | 8 +- .../dataset_serialization_test_base.py | 3 +- .../filter_dataset_serialization_test.py | 6 +- ...tching_files_dataset_serialization_test.py | 4 +- .../range_dataset_serialization_test.py | 34 +- .../serialization_integration_test.py | 6 +- .../shuffle_dataset_serialization_test.py | 4 +- .../kernel_tests/shuffle_and_repeat_test.py | 15 +- .../experimental/kernel_tests/sleep_test.py | 10 +- .../kernel_tests/sql_dataset_test.py | 169 +- .../kernel_tests/sql_dataset_test_base.py | 3 +- .../kernel_tests/stats_dataset_ops_test.py | 200 +- .../kernel_tests/stats_dataset_test_base.py | 3 +- .../experimental/kernel_tests/unbatch_test.py | 137 +- .../experimental/kernel_tests/unique_test.py | 11 +- tensorflow/python/data/experimental/ops/BUILD | 90 +- .../python/data/experimental/ops/batching.py | 54 +- .../data/experimental/ops/cardinality.py | 50 + .../python/data/experimental/ops/counter.py | 14 +- .../data/experimental/ops/enumerate_ops.py | 4 +- .../python/data/experimental/ops/error_ops.py | 14 +- .../experimental/ops/filter_for_shard_ops.py | 106 + .../experimental/ops/get_single_element.py | 2 +- .../python/data/experimental/ops/grouping.py | 142 +- .../experimental/ops/indexed_dataset_ops.py | 2 + .../data/experimental/ops/interleave_ops.py | 30 +- .../data/experimental/ops/matching_files.py | 51 + .../data/experimental/ops/optimization.py | 28 +- .../experimental/ops/optimization_options.py | 83 + .../data/experimental/ops/parsing_ops.py | 8 +- .../data/experimental/ops/prefetching_ops.py | 342 +- .../data/experimental/ops/random_ops.py | 27 +- .../python/data/experimental/ops/readers.py | 176 +- .../python/data/experimental/ops/scan_ops.py | 15 +- .../data/experimental/ops/shuffle_ops.py | 14 +- .../python/data/experimental/ops/sleep.py | 2 +- .../data/experimental/ops/stats_aggregator.py | 7 +- .../python/data/experimental/ops/stats_ops.py | 26 +- .../data/experimental/ops/stats_options.py | 84 +- .../experimental/ops/threading_options.py | 50 + .../data/experimental/ops/threadpool.py | 14 +- .../python/data/experimental/ops/unique.py | 14 +- .../python/data/experimental/ops/writers.py | 6 +- tensorflow/python/data/kernel_tests/BUILD | 422 +- .../kernel_tests/batch_dataset_op_test.py | 515 - .../python/data/kernel_tests/batch_test.py | 173 + .../kernel_tests/cache_dataset_op_test.py | 318 - .../python/data/kernel_tests/cache_test.py | 253 + ...dataset_op_test.py => concatenate_test.py} | 66 +- ..._op_test.py => dataset_checkpoint_test.py} | 71 +- .../dataset_constructor_op_test.py | 650 - .../{dataset_ops_test.py => dataset_test.py} | 87 +- .../kernel_tests/filter_dataset_op_test.py | 220 - .../python/data/kernel_tests/filter_test.py | 128 + .../fixed_length_record_dataset_test.py | 171 + ...ap_dataset_op_test.py => flat_map_test.py} | 104 +- ...ator_op_test.py => from_generator_test.py} | 103 +- .../from_sparse_tensor_slices_test.py | 86 + .../kernel_tests/from_tensor_slices_test.py | 177 + .../data/kernel_tests/from_tensors_test.py | 259 + .../python/data/kernel_tests/inputs_test.py | 149 - ..._dataset_op_test.py => interleave_test.py} | 77 +- .../kernel_tests/iterator_checkpoint_test.py | 129 + ...uster_test.py => iterator_cluster_test.py} | 8 +- ...{iterator_ops_test.py => iterator_test.py} | 208 +- .../list_files_dataset_op_test.py | 291 - .../data/kernel_tests/list_files_test.py | 214 + .../{map_dataset_op_test.py => map_test.py} | 272 +- .../multi_device_iterator_test.py | 122 +- ...{optional_ops_test.py => optional_test.py} | 137 +- .../data/kernel_tests/padded_batch_test.py | 243 + ...ch_dataset_op_test.py => prefetch_test.py} | 34 +- .../python/data/kernel_tests/range_test.py | 72 + .../kernel_tests/reader_dataset_ops_test.py | 846 - ...duce_dataset_op_test.py => reduce_test.py} | 45 +- .../python/data/kernel_tests/repeat_test.py | 84 + .../kernel_tests/sequence_dataset_op_test.py | 210 - ...shard_dataset_op_test.py => shard_test.py} | 58 +- .../kernel_tests/shuffle_dataset_op_test.py | 278 - .../python/data/kernel_tests/shuffle_test.py | 249 + .../python/data/kernel_tests/skip_test.py | 62 + .../python/data/kernel_tests/take_test.py | 55 + .../python/data/kernel_tests/test_base.py | 102 +- .../kernel_tests/text_line_dataset_test.py | 165 + .../kernel_tests/tf_record_dataset_test.py | 170 + .../kernel_tests/window_dataset_op_test.py | 291 - .../python/data/kernel_tests/window_test.py | 231 + .../data/kernel_tests/zip_dataset_op_test.py | 115 - .../python/data/kernel_tests/zip_test.py | 101 + tensorflow/python/data/ops/BUILD | 5 + tensorflow/python/data/ops/dataset_ops.py | 1569 +- tensorflow/python/data/ops/iterator_ops.py | 2 +- tensorflow/python/data/ops/optional_ops.py | 16 +- tensorflow/python/data/ops/readers.py | 126 +- tensorflow/python/data/util/BUILD | 17 + tensorflow/python/data/util/convert_test.py | 150 +- tensorflow/python/data/util/options.py | 131 + tensorflow/python/data/util/options_test.py | 96 + tensorflow/python/data/util/sparse.py | 2 +- tensorflow/python/data/util/sparse_test.py | 9 +- tensorflow/python/data/util/structure.py | 69 +- tensorflow/python/data/util/structure_test.py | 71 +- tensorflow/python/debug/BUILD | 2 + .../python/debug/cli/analyzer_cli_test.py | 35 +- .../python/debug/cli/cli_shared_test.py | 11 + .../debug/cli/profile_analyzer_cli_test.py | 5 + tensorflow/python/debug/lib/common_test.py | 3 + .../python/debug/lib/debug_gradients_test.py | 14 + .../lib/debug_graph_reconstruction_test.py | 14 +- .../python/debug/lib/debug_utils_test.py | 10 + .../debug/lib/session_debug_file_test.py | 2 + .../debug/lib/session_debug_multi_gpu_test.py | 2 +- .../python/debug/lib/source_utils_test.py | 5 +- .../python/debug/wrappers/framework_test.py | 2 +- tensorflow/python/distribute/BUILD | 240 +- tensorflow/python/distribute/all_reduce.py | 860 + .../distribute}/all_reduce_test.py | 11 +- .../python/distribute/cluster_resolver/BUILD | 180 + .../distribute}/cluster_resolver/README.md | 0 .../distribute/cluster_resolver}/README.slurm | 0 .../distribute/cluster_resolver/__init__.py | 57 + .../cluster_resolver/cluster_resolver.py | 374 + .../cluster_resolver_test.py | 4 +- .../cluster_resolver/gce_cluster_resolver.py | 206 + .../gce_cluster_resolver_test.py | 4 +- .../kubernetes_cluster_resolver.py | 173 + .../kubernetes_cluster_resolver_test.py | 19 +- .../slurm_cluster_resolver.py | 226 + .../slurm_cluster_resolver_test.py | 27 +- .../tfconfig_cluster_resolver.py | 171 + .../tfconfig_cluster_resolver_test.py | 54 +- .../cluster_resolver/tpu_cluster_resolver.py | 423 + .../tpu_cluster_resolver_test.py | 64 +- .../distribute/cross_device_ops.py} | 161 +- .../distribute/cross_device_utils.py} | 8 +- .../{training => distribute}/device_util.py | 2 +- .../device_util_test.py | 5 +- .../distribute/distribute_coordinator.py | 27 +- .../distribute/distribute_coordinator_test.py | 78 +- .../python/distribute/distribute_lib.py | 1682 ++ .../distribute_lib_test.py} | 47 +- .../distribution_strategy_context.py | 236 + .../python/distribute/estimator_training.py | 4 +- .../python => python/distribute}/input_ops.py | 20 +- .../distribute}/input_ops_test.py | 35 +- .../python/distribute/mirrored_strategy.py | 908 + .../python/distribute/multi_worker_util.py | 98 +- .../distribute/multi_worker_util_test.py | 91 +- tensorflow/python/distribute/reduce_util.py | 53 + .../distribute}/shared_variable_creator.py | 0 .../shared_variable_creator_test.py | 2 +- .../python => python/distribute}/values.py | 454 +- tensorflow/python/eager/BUILD | 32 +- tensorflow/python/eager/backprop.py | 231 +- tensorflow/python/eager/backprop_test.py | 253 +- tensorflow/python/eager/benchmarks_test.py | 58 +- tensorflow/python/eager/context.py | 55 +- tensorflow/python/eager/def_function.py | 8 +- tensorflow/python/eager/def_function_test.py | 21 +- .../python/eager/execution_callbacks.py | 45 +- .../python/eager/execution_callbacks_test.py | 55 + tensorflow/python/eager/function.py | 151 +- .../python/eager/function_gradients_test.py | 756 + tensorflow/python/eager/function_test.py | 745 +- .../python/eager/graph_only_ops_test.py | 4 +- tensorflow/python/eager/pywrap_tensor.cc | 30 +- tensorflow/python/eager/pywrap_tfe_src.cc | 32 +- tensorflow/python/eager/tape.py | 4 +- tensorflow/python/eager/tape_test.py | 8 +- tensorflow/python/eager/tensor_test.py | 47 +- tensorflow/python/eager/test.py | 2 +- tensorflow/python/eager/wrap_function.py | 18 + .../python/feature_column/feature_column.py | 242 +- .../feature_column/feature_column_lib.py | 1 + .../feature_column/feature_column_test.py | 1881 +- .../feature_column/feature_column_v2.py | 491 +- .../feature_column/feature_column_v2_test.py | 3191 ++- .../python/framework/auto_control_deps.py | 13 + tensorflow/python/framework/constant_op.py | 81 +- tensorflow/python/framework/device.py | 2 +- tensorflow/python/framework/dtypes.py | 10 +- tensorflow/python/framework/dtypes_test.py | 4 +- .../python/framework/file_system_test.py | 4 +- tensorflow/python/framework/func_graph.py | 72 +- tensorflow/python/framework/function.py | 4 +- .../framework/function_def_to_graph_test.py | 3 + tensorflow/python/framework/function_test.py | 92 +- .../python/framework/graph_util_test.py | 14 +- tensorflow/python/framework/importer.py | 24 +- tensorflow/python/framework/importer_test.py | 20 +- tensorflow/python/framework/load_library.py | 4 +- .../python/framework/meta_graph_test.py | 39 +- tensorflow/python/framework/op_def_library.py | 2 +- tensorflow/python/framework/ops.py | 355 +- tensorflow/python/framework/ops_test.py | 254 +- tensorflow/python/framework/python_op_gen.cc | 28 +- .../framework/python_op_gen_internal.cc | 6 +- tensorflow/python/framework/random_seed.py | 108 +- tensorflow/python/framework/registry.py | 11 +- tensorflow/python/framework/registry_test.py | 4 +- .../python/framework/smart_cond_test.py | 13 +- .../python/framework/sparse_tensor_test.py | 8 +- tensorflow/python/framework/subscribe_test.py | 38 +- tensorflow/python/framework/tensor_shape.py | 2 +- tensorflow/python/framework/tensor_spec.py | 40 +- .../python/framework/tensor_spec_test.py | 25 +- tensorflow/python/framework/tensor_util.py | 28 +- .../python/framework/tensor_util_test.py | 14 +- tensorflow/python/framework/test_util.py | 301 +- tensorflow/python/framework/test_util_test.py | 7 +- .../python/grappler/constant_folding_test.py | 2 +- .../python/grappler/cost_analyzer_test.py | 8 +- .../python/grappler/cost_analyzer_tool.py | 9 +- tensorflow/python/grappler/datasets_test.py | 20 +- tensorflow/python/grappler/graph_placer.py | 6 +- tensorflow/python/grappler/item_test.py | 2 + .../python/grappler/layout_optimizer_test.py | 71 +- .../python/grappler/memory_optimizer_test.py | 80 +- .../python/grappler/model_analyzer_test.py | 3 + tensorflow/python/grappler/tf_optimizer.i | 19 +- tensorflow/python/grappler/tf_optimizer.py | 8 +- .../python/grappler/tf_optimizer_test.py | 36 +- tensorflow/python/keras/BUILD | 67 +- tensorflow/python/keras/activations_test.py | 4 + tensorflow/python/keras/backend.py | 135 +- tensorflow/python/keras/backend_test.py | 139 +- tensorflow/python/keras/callbacks.py | 80 +- tensorflow/python/keras/callbacks_test.py | 84 +- tensorflow/python/keras/engine/__init__.py | 2 +- tensorflow/python/keras/engine/base_layer.py | 2093 +- .../python/keras/engine/base_layer_test.py | 8 +- .../python/keras/engine/base_layer_utils.py | 236 + .../engine/distributed_training_utils.py | 273 +- .../feature_columns_integration_test.py | 29 +- tensorflow/python/keras/engine/input_layer.py | 29 +- tensorflow/python/keras/engine/input_spec.py | 170 + tensorflow/python/keras/engine/network.py | 317 +- tensorflow/python/keras/engine/saving.py | 10 +- tensorflow/python/keras/engine/saving_test.py | 62 +- tensorflow/python/keras/engine/sequential.py | 65 +- .../python/keras/engine/sequential_test.py | 28 +- .../python/keras/engine/topology_test.py | 10 + tensorflow/python/keras/engine/training.py | 980 +- .../python/keras/engine/training_arrays.py | 215 +- .../keras/engine/training_dataset_test.py | 344 + .../keras/engine/training_distributed.py | 633 +- .../python/keras/engine/training_eager.py | 696 +- .../keras/engine/training_eager_test.py | 63 +- .../python/keras/engine/training_generator.py | 789 +- .../keras/engine/training_generator_test.py | 446 +- .../python/keras/engine/training_gpu_test.py | 2 +- .../python/keras/engine/training_test.py | 787 +- .../python/keras/engine/training_utils.py | 391 +- .../keras/engine/training_utils_test.py | 178 +- tensorflow/python/keras/estimator/__init__.py | 61 +- tensorflow/python/keras/initializers_test.py | 11 + tensorflow/python/keras/integration_test.py | 17 + tensorflow/python/keras/layers/__init__.py | 2 +- .../keras/layers/advanced_activations.py | 8 +- .../python/keras/layers/convolutional.py | 12 +- .../keras/layers/convolutional_recurrent.py | 2 +- tensorflow/python/keras/layers/core.py | 11 +- .../python/keras/layers/cudnn_recurrent.py | 16 +- tensorflow/python/keras/layers/embeddings.py | 7 +- tensorflow/python/keras/layers/local.py | 4 +- tensorflow/python/keras/layers/local_test.py | 280 +- tensorflow/python/keras/layers/lstm_test.py | 23 +- tensorflow/python/keras/layers/merge.py | 9 +- tensorflow/python/keras/layers/merge_test.py | 1 + tensorflow/python/keras/layers/noise.py | 3 - .../python/keras/layers/normalization.py | 126 +- .../python/keras/layers/normalization_test.py | 114 +- tensorflow/python/keras/layers/pooling.py | 8 +- tensorflow/python/keras/layers/recurrent.py | 482 +- .../python/keras/layers/recurrent_test.py | 30 +- .../python/keras/layers/simplernn_test.py | 3 + .../python/keras/layers/unified_lstm_test.py | 724 + tensorflow/python/keras/layers/wrappers.py | 6 +- .../python/keras/layers/wrappers_test.py | 36 +- tensorflow/python/keras/losses.py | 420 +- tensorflow/python/keras/losses_test.py | 633 + tensorflow/python/keras/metrics.py | 1113 +- tensorflow/python/keras/metrics_test.py | 997 +- .../python/keras/model_subclassing_test.py | 132 +- tensorflow/python/keras/models.py | 36 +- tensorflow/python/keras/models_test.py | 55 +- tensorflow/python/keras/optimizer_v2/BUILD | 150 +- .../python/keras/optimizer_v2/adadelta.py | 148 + .../keras/optimizer_v2/adadelta_test.py | 170 + .../python/keras/optimizer_v2/adagrad.py | 171 + .../python/keras/optimizer_v2/adagrad_test.py | 400 + tensorflow/python/keras/optimizer_v2/adam.py | 182 +- .../python/keras/optimizer_v2/adam_test.py | 508 + .../python/keras/optimizer_v2/adamax.py | 159 + .../python/keras/optimizer_v2/adamax_test.py | 367 + tensorflow/python/keras/optimizer_v2/ftrl.py | 210 + .../python/keras/optimizer_v2/ftrl_test.py | 440 + .../keras/optimizer_v2/gradient_descent.py | 39 +- .../optimizer_v2/gradient_descent_test.py | 212 +- tensorflow/python/keras/optimizer_v2/nadam.py | 143 + .../python/keras/optimizer_v2/nadam_test.py | 213 + .../python/keras/optimizer_v2/optimizer_v2.py | 82 +- .../keras/optimizer_v2/optimizer_v2_test.py | 259 +- .../python/keras/optimizer_v2/rmsprop.py | 196 + .../python/keras/optimizer_v2/rmsprop_test.py | 410 + tensorflow/python/keras/optimizers.py | 54 +- tensorflow/python/keras/optimizers_test.py | 47 + tensorflow/python/keras/regularizers_test.py | 2 + tensorflow/python/keras/testing_utils.py | 4 + tensorflow/python/keras/utils/__init__.py | 1 + .../python/keras/utils/generic_utils.py | 12 +- tensorflow/python/keras/utils/layer_utils.py | 2 +- tensorflow/python/keras/utils/losses_utils.py | 189 + .../keras/utils/multi_gpu_utils_test.py | 2 +- tensorflow/python/keras/utils/tf_utils.py | 44 +- .../python/keras/utils/tf_utils_test.py | 134 + tensorflow/python/kernel_tests/BUILD | 82 +- .../python/kernel_tests/accumulate_n_test.py | 10 +- .../python/kernel_tests/ackermann_test.py | 2 + .../python/kernel_tests/aggregate_ops_test.py | 5 +- .../python/kernel_tests/argmax_op_test.py | 11 +- .../python/kernel_tests/array_ops_test.py | 151 +- .../python/kernel_tests/as_string_op_test.py | 7 + .../python/kernel_tests/atrous_conv2d_test.py | 18 +- .../python/kernel_tests/attention_ops_test.py | 5 +- .../python/kernel_tests/barrier_ops_test.py | 24 +- .../python/kernel_tests/base64_ops_test.py | 2 +- .../python/kernel_tests/basic_gpu_test.py | 13 +- .../kernel_tests/batch_gather_op_test.py | 10 +- .../kernel_tests/batch_matmul_op_test.py | 2 +- .../kernel_tests/batch_scatter_ops_test.py | 6 +- .../kernel_tests/batchtospace_op_test.py | 21 + .../python/kernel_tests/bcast_ops_test.py | 6 + .../python/kernel_tests/benchmark_test.py | 15 +- .../python/kernel_tests/betainc_op_test.py | 10 +- .../python/kernel_tests/bias_op_test.py | 12 + .../python/kernel_tests/bincount_op_test.py | 7 + .../python/kernel_tests/bitcast_op_test.py | 7 +- .../boosted_trees/prediction_ops_test.py | 15 + .../boosted_trees/quantile_ops_test.py | 18 +- .../boosted_trees/resource_ops_test.py | 45 +- .../boosted_trees/stats_ops_test.py | 65 +- .../boosted_trees/training_ops_test.py | 10 + .../kernel_tests/broadcast_to_ops_test.py | 11 + .../python/kernel_tests/bucketize_op_test.py | 10 +- .../candidate_sampler_ops_test.py | 13 +- .../python/kernel_tests/cast_op_test.py | 17 +- .../python/kernel_tests/check_ops_test.py | 109 + .../kernel_tests/checkpoint_ops_test.py | 53 +- .../python/kernel_tests/cholesky_op_test.py | 15 +- .../python/kernel_tests/clip_ops_test.py | 74 +- .../compare_and_bitpack_op_test.py | 7 +- .../python/kernel_tests/concat_op_test.py | 176 +- .../python/kernel_tests/cond_v2_test.py | 130 +- .../conditional_accumulator_test.py | 66 +- .../kernel_tests/confusion_matrix_test.py | 57 +- .../python/kernel_tests/constant_op_test.py | 114 +- .../kernel_tests/control_flow_ops_py_test.py | 555 +- tensorflow/python/kernel_tests/conv1d_test.py | 4 +- .../conv2d_backprop_filter_grad_test.py | 2 + .../kernel_tests/conv2d_transpose_test.py | 14 +- .../conv3d_backprop_filter_v2_grad_test.py | 2 + .../kernel_tests/conv3d_transpose_test.py | 11 +- .../python/kernel_tests/conv_ops_3d_test.py | 31 +- .../python/kernel_tests/conv_ops_test.py | 18 +- .../python/kernel_tests/cross_grad_test.py | 2 + .../kernel_tests/ctc_decoder_ops_test.py | 3 + .../python/kernel_tests/ctc_loss_op_test.py | 584 +- .../kernel_tests/cwise_ops_binary_test.py | 123 +- .../python/kernel_tests/cwise_ops_test.py | 133 +- .../kernel_tests/cwise_ops_unary_test.py | 30 +- .../python/kernel_tests/decode_bmp_op_test.py | 4 +- .../kernel_tests/decode_compressed_op_test.py | 3 + .../kernel_tests/decode_image_op_test.py | 18 +- .../kernel_tests/decode_jpeg_op_test.py | 6 +- .../python/kernel_tests/decode_png_op_test.py | 2 +- .../python/kernel_tests/decode_raw_op_test.py | 7 + .../python/kernel_tests/denormal_test.py | 3 + .../dense_update_ops_no_tsan_test.py | 21 +- .../kernel_tests/dense_update_ops_test.py | 21 +- .../kernel_tests/depthtospace_op_test.py | 31 +- .../kernel_tests/depthwise_conv_op_test.py | 14 +- .../kernel_tests/determinant_op_test.py | 11 +- .../python/kernel_tests/diag_op_test.py | 44 +- .../distributions/bernoulli_test.py | 5 + .../distributions/bijector_test.py | 2 + .../distributions/categorical_test.py | 39 +- .../dirichlet_multinomial_test.py | 43 +- .../distributions/identity_bijector_test.py | 2 + .../distributions/kullback_leibler_test.py | 10 +- .../distributions/multinomial_test.py | 12 +- .../kernel_tests/distributions/normal_test.py | 1 + .../distributions/special_math_test.py | 15 +- .../kernel_tests/distributions/util_test.py | 52 +- .../kernel_tests/division_future_test.py | 2 +- .../python/kernel_tests/division_past_test.py | 2 +- .../kernel_tests/draw_bounding_box_op_test.py | 2 +- .../python/kernel_tests/duplicate_op_test.py | 2 + .../kernel_tests/dynamic_partition_op_test.py | 40 +- .../kernel_tests/dynamic_stitch_op_test.py | 49 +- .../kernel_tests/edit_distance_op_test.py | 4 +- .../python/kernel_tests/embedding_ops_test.py | 64 +- .../extract_image_patches_grad_test.py | 3 + .../extract_image_patches_op_test.py | 5 +- .../extract_volume_patches_op_test.py | 5 +- .../python/kernel_tests/fifo_queue_test.py | 190 +- .../fractional_avg_pool_op_test.py | 95 +- .../fractional_max_pool_op_test.py | 67 +- .../kernel_tests/functional_ops_test.py | 90 +- .../python/kernel_tests/gather_nd_op_test.py | 57 +- .../python/kernel_tests/gather_op_test.py | 21 +- .../kernel_tests/gradient_correctness_test.py | 19 +- .../python/kernel_tests/huge_slice_op_test.py | 4 +- .../kernel_tests/identity_n_op_py_test.py | 4 + .../kernel_tests/identity_op_py_test.py | 5 + .../python/kernel_tests/in_topk_op_test.py | 4 +- .../python/kernel_tests/init_ops_test.py | 102 +- .../python/kernel_tests/inplace_ops_test.py | 9 +- tensorflow/python/kernel_tests/io_ops_test.py | 7 +- .../kernel_tests/large_concat_op_test.py | 2 +- tensorflow/python/kernel_tests/linalg/BUILD | 63 +- .../linalg/linear_operator_addition_test.py | 13 + .../linalg/linear_operator_adjoint_test.py | 118 + .../linalg/linear_operator_algebra_test.py | 133 + .../linalg/linear_operator_block_diag_test.py | 45 +- .../linalg/linear_operator_circulant_test.py | 116 +- .../linear_operator_composition_test.py | 10 +- .../linalg/linear_operator_diag_test.py | 61 +- .../linear_operator_full_matrix_test.py | 27 +- .../linalg/linear_operator_identity_test.py | 97 +- .../linalg/linear_operator_inversion_test.py | 130 + .../linalg/linear_operator_kronecker_test.py | 54 +- .../linear_operator_low_rank_update_test.py | 13 +- .../linear_operator_lower_triangular_test.py | 30 + .../linalg/linear_operator_test.py | 86 +- .../linalg/linear_operator_util_test.py | 53 +- .../linalg/linear_operator_zeros_test.py | 25 +- .../python/kernel_tests/linalg_grad_test.py | 6 +- .../python/kernel_tests/linalg_ops_test.py | 21 +- .../python/kernel_tests/list_ops_test.py | 408 +- .../python/kernel_tests/listdiff_op_test.py | 2 +- .../python/kernel_tests/logging_ops_test.py | 12 +- .../python/kernel_tests/lookup_ops_test.py | 216 +- tensorflow/python/kernel_tests/losses_test.py | 219 +- tensorflow/python/kernel_tests/lrn_op_test.py | 4 + .../python/kernel_tests/manip_ops_test.py | 12 + .../python/kernel_tests/map_stage_op_test.py | 13 + .../python/kernel_tests/matmul_op_test.py | 10 +- .../kernel_tests/matrix_band_part_op_test.py | 2 +- .../matrix_exponential_op_test.py | 11 +- .../kernel_tests/matrix_inverse_op_test.py | 4 +- .../kernel_tests/matrix_logarithm_op_test.py | 7 +- .../kernel_tests/matrix_solve_ls_op_test.py | 4 + .../kernel_tests/matrix_solve_op_test.py | 10 +- .../matrix_square_root_op_test.py | 20 +- .../matrix_triangular_solve_op_test.py | 9 +- .../python/kernel_tests/metrics_test.py | 683 +- .../kernel_tests/morphological_ops_test.py | 11 +- .../neon_depthwise_conv_op_test.py | 9 +- .../python/kernel_tests/norm_op_test.py | 2 +- .../kernel_tests/nth_element_op_test.py | 10 +- .../python/kernel_tests/numerics_test.py | 26 +- .../python/kernel_tests/one_hot_op_test.py | 4 +- tensorflow/python/kernel_tests/pad_op_test.py | 41 +- .../kernel_tests/padding_fifo_queue_test.py | 182 +- .../parameterized_truncated_normal_op_test.py | 11 + .../parse_single_example_op_test.py | 9 +- .../python/kernel_tests/parsing_ops_test.py | 28 +- .../partitioned_variables_test.py | 29 +- tensorflow/python/kernel_tests/pool_test.py | 6 +- .../kernel_tests/pooling_ops_3d_test.py | 22 +- .../python/kernel_tests/pooling_ops_test.py | 44 +- .../kernel_tests/priority_queue_test.py | 22 +- .../python/kernel_tests/py_func_test.py | 22 +- tensorflow/python/kernel_tests/qr_op_test.py | 8 +- .../random/multinomial_op_big_test.py | 8 +- .../random/multinomial_op_test.py | 40 +- .../kernel_tests/random/random_crop_test.py | 7 +- .../kernel_tests/random/random_gamma_test.py | 8 +- .../kernel_tests/random/random_grad_test.py | 11 + .../kernel_tests/random/random_ops_test.py | 34 +- .../random/random_poisson_test.py | 10 +- .../random/random_shuffle_queue_test.py | 150 +- .../random/stateless_random_ops_test.py | 11 +- .../python/kernel_tests/reader_ops_test.py | 663 +- .../python/kernel_tests/record_input_test.py | 20 +- .../kernel_tests/reduce_benchmark_test.py | 4 +- .../kernel_tests/reduce_join_op_test.py | 20 +- .../python/kernel_tests/reduction_ops_test.py | 87 +- .../kernel_tests/regex_full_match_op_test.py | 9 +- .../kernel_tests/regex_replace_op_test.py | 11 +- .../python/kernel_tests/relu_op_test.py | 282 +- .../python/kernel_tests/reshape_op_test.py | 8 +- .../resource_variable_ops_test.py | 54 +- .../kernel_tests/reverse_sequence_op_test.py | 7 +- tensorflow/python/kernel_tests/rnn_test.py | 10 + .../kernel_tests/save_restore_ops_test.py | 19 + .../python/kernel_tests/scan_ops_test.py | 29 + .../kernel_tests/scatter_nd_ops_test.py | 130 +- .../python/kernel_tests/scatter_ops_test.py | 39 +- .../segment_reduction_ops_test.py | 103 +- .../kernel_tests/self_adjoint_eig_op_test.py | 8 +- .../python/kernel_tests/session_ops_test.py | 46 +- tensorflow/python/kernel_tests/sets_test.py | 24 +- .../python/kernel_tests/shape_ops_test.py | 77 +- tensorflow/python/kernel_tests/signal/BUILD | 31 +- .../kernel_tests/{ => signal}/dct_ops_test.py | 70 +- .../kernel_tests/{ => signal}/fft_ops_test.py | 42 +- .../kernel_tests/signal/mel_ops_test.py | 6 +- .../kernel_tests/signal/mfcc_ops_test.py | 4 + .../signal/reconstruction_ops_test.py | 82 +- .../kernel_tests/signal/shape_ops_test.py | 20 +- .../kernel_tests/signal/spectral_ops_test.py | 18 +- .../python/kernel_tests/signal/test_util.py | 14 +- .../kernel_tests/signal/window_ops_test.py | 3 + .../python/kernel_tests/slice_op_test.py | 54 +- .../python/kernel_tests/softmax_op_test.py | 7 +- .../python/kernel_tests/softplus_op_test.py | 7 +- .../python/kernel_tests/softsign_op_test.py | 5 +- .../kernel_tests/spacetobatch_op_test.py | 36 + .../kernel_tests/spacetodepth_op_test.py | 43 +- .../python/kernel_tests/sparse_add_op_test.py | 34 +- .../kernel_tests/sparse_concat_op_test.py | 21 +- .../sparse_conditional_accumulator_test.py | 60 +- .../kernel_tests/sparse_cross_op_test.py | 54 +- .../kernel_tests/sparse_matmul_op_test.py | 9 +- .../python/kernel_tests/sparse_ops_test.py | 121 +- .../kernel_tests/sparse_reorder_op_test.py | 8 +- .../kernel_tests/sparse_reshape_op_test.py | 22 +- .../sparse_serialization_ops_test.py | 27 +- .../kernel_tests/sparse_slice_op_test.py | 8 + .../kernel_tests/sparse_split_op_test.py | 8 + .../sparse_tensor_dense_matmul_grad_test.py | 2 + .../sparse_tensor_dense_matmul_op_test.py | 6 +- .../sparse_tensors_map_ops_test.py | 21 +- .../sparse_to_dense_op_py_test.py | 36 +- .../kernel_tests/sparse_xent_op_test.py | 22 +- .../python/kernel_tests/sparsemask_op_test.py | 2 + .../python/kernel_tests/split_op_test.py | 9 +- .../python/kernel_tests/stack_op_test.py | 29 +- .../python/kernel_tests/stack_ops_test.py | 43 +- .../python/kernel_tests/stage_op_test.py | 8 + .../kernel_tests/string_join_op_test.py | 2 + .../kernel_tests/string_length_op_test.py | 9 +- .../kernel_tests/string_split_op_test.py | 33 +- .../kernel_tests/string_strip_op_test.py | 6 +- .../string_to_hash_bucket_op_test.py | 9 +- .../kernel_tests/string_to_number_op_test.py | 5 + .../python/kernel_tests/substr_op_test.py | 45 +- .../kernel_tests/summary_v1_audio_op_test.py | 2 +- .../kernel_tests/summary_v1_image_op_test.py | 7 +- .../kernel_tests/summary_v1_ops_test.py | 8 +- .../kernel_tests/summary_v1_tensor_op_test.py | 14 +- tensorflow/python/kernel_tests/svd_op_test.py | 8 +- .../python/kernel_tests/template_test.py | 13 +- .../kernel_tests/tensor_array_ops_test.py | 308 +- .../python/kernel_tests/topk_op_test.py | 6 +- .../python/kernel_tests/trace_op_test.py | 2 + .../python/kernel_tests/transpose_op_test.py | 18 +- .../kernel_tests/unicode_decode_op_test.py | 153 + .../kernel_tests/unicode_encode_op_test.py | 301 + .../kernel_tests/unicode_script_op_test.py | 3 + .../kernel_tests/unicode_transcode_op_test.py | 119 +- .../python/kernel_tests/unique_op_test.py | 24 +- .../python/kernel_tests/unstack_op_test.py | 30 +- .../python/kernel_tests/variable_ops_test.py | 57 +- .../kernel_tests/variable_scope_test.py | 85 +- .../python/kernel_tests/variables_test.py | 263 +- .../kernel_tests/weights_broadcast_test.py | 33 +- .../python/kernel_tests/where_op_test.py | 21 +- .../python/kernel_tests/while_v2_test.py | 179 +- .../python/kernel_tests/xent_op_test.py | 17 +- .../python/kernel_tests/zero_division_test.py | 6 +- tensorflow/python/layers/base.py | 15 +- tensorflow/python/layers/base_test.py | 17 +- .../python/layers/convolutional_test.py | 72 +- tensorflow/python/layers/core_test.py | 21 +- tensorflow/python/layers/layers.py | 2 +- .../python/layers/normalization_test.py | 176 +- tensorflow/python/layers/pooling_test.py | 4 + tensorflow/python/lib/io/file_io.py | 258 +- tensorflow/python/lib/io/tf_record.py | 9 +- tensorflow/python/ops/array_grad.py | 32 +- tensorflow/python/ops/array_ops.py | 518 +- tensorflow/python/ops/bitwise_ops_test.py | 13 +- .../python/ops/candidate_sampling_ops.py | 7 +- tensorflow/python/ops/check_ops.py | 543 +- tensorflow/python/ops/clip_ops.py | 7 +- tensorflow/python/ops/clip_ops_test.py | 6 +- tensorflow/python/ops/collective_ops_test.py | 5 + tensorflow/python/ops/cond_v2.py | 316 +- tensorflow/python/ops/confusion_matrix.py | 77 +- tensorflow/python/ops/control_flow_ops.py | 307 +- .../python/ops/control_flow_ops_test.py | 30 +- tensorflow/python/ops/control_flow_util.py | 5 + tensorflow/python/ops/control_flow_util_v2.py | 30 + tensorflow/python/ops/ctc_ops.py | 793 +- tensorflow/python/ops/data_flow_ops.py | 15 +- tensorflow/python/ops/dequantize_op_test.py | 2 +- tensorflow/python/ops/distributions/util.py | 2 +- tensorflow/python/ops/embedding_ops.py | 5 +- tensorflow/python/ops/functional_ops.py | 19 +- tensorflow/python/ops/gradient_checker.py | 78 +- .../python/ops/gradient_checker_test.py | 14 + tensorflow/python/ops/gradient_checker_v2.py | 318 + .../python/ops/gradient_checker_v2_test.py | 300 + tensorflow/python/ops/gradients_impl.py | 140 +- tensorflow/python/ops/gradients_test.py | 46 +- tensorflow/python/ops/histogram_ops_test.py | 22 +- tensorflow/python/ops/image_grad_test.py | 20 +- tensorflow/python/ops/image_ops_impl.py | 272 +- tensorflow/python/ops/image_ops_test.py | 344 +- tensorflow/python/ops/init_ops.py | 189 +- tensorflow/python/ops/init_ops_test.py | 4 +- tensorflow/python/ops/linalg/BUILD | 1 + .../ops/linalg/cholesky_registrations.py | 101 + tensorflow/python/ops/linalg/linalg.py | 3 + tensorflow/python/ops/linalg/linalg_impl.py | 2 +- .../python/ops/linalg/linear_operator.py | 67 +- .../ops/linalg/linear_operator_adjoint.py | 207 + .../ops/linalg/linear_operator_algebra.py | 191 + .../ops/linalg/linear_operator_block_diag.py | 4 +- .../ops/linalg/linear_operator_circulant.py | 15 +- .../ops/linalg/linear_operator_composition.py | 3 - .../python/ops/linalg/linear_operator_diag.py | 4 +- .../ops/linalg/linear_operator_inversion.py | 207 + .../ops/linalg/linear_operator_kronecker.py | 4 +- .../linalg/linear_operator_low_rank_update.py | 2 +- .../linear_operator_lower_triangular.py | 4 +- .../ops/linalg/linear_operator_test_util.py | 26 +- .../python/ops/linalg/matmul_registrations.py | 252 + tensorflow/python/ops/linalg_ops.py | 73 +- tensorflow/python/ops/list_ops.py | 98 +- tensorflow/python/ops/lookup_ops.py | 11 +- tensorflow/python/ops/losses/losses_impl.py | 111 +- tensorflow/python/ops/losses/util_test.py | 2 + tensorflow/python/ops/math_grad.py | 7 +- tensorflow/python/ops/math_grad_test.py | 49 + tensorflow/python/ops/math_ops.py | 1198 +- tensorflow/python/ops/math_ops_test.py | 45 +- tensorflow/python/ops/metrics_impl.py | 136 +- tensorflow/python/ops/nccl_ops_test.py | 2 +- tensorflow/python/ops/nn_batchnorm_test.py | 31 +- .../python/ops/nn_fused_batchnorm_test.py | 12 +- tensorflow/python/ops/nn_grad.py | 14 +- tensorflow/python/ops/nn_grad_test.py | 2 + tensorflow/python/ops/nn_impl.py | 408 +- tensorflow/python/ops/nn_ops.py | 1201 +- tensorflow/python/ops/nn_test.py | 767 +- tensorflow/python/ops/nn_xent_test.py | 14 +- tensorflow/python/ops/numerics.py | 29 +- .../ops/optional_grad.py} | 23 +- .../ops/parallel_for/control_flow_ops.py | 119 +- .../ops/parallel_for/control_flow_ops_test.py | 264 +- .../python/ops/parallel_for/gradients.py | 25 +- .../python/ops/parallel_for/gradients_test.py | 23 +- tensorflow/python/ops/parallel_for/pfor.py | 10 +- tensorflow/python/ops/parsing_ops.py | 314 +- .../python/ops/partitioned_variables.py | 24 +- .../python/ops/quantized_conv_ops_test.py | 2 +- tensorflow/python/ops/quantized_ops_test.py | 4 +- tensorflow/python/ops/ragged/BUILD | 59 + tensorflow/python/ops/ragged/__init__.py | 10 + ...vert_to_tensor_or_ragged_tensor_op_test.py | 4 +- .../python/ops/ragged/ragged_array_ops.py | 100 +- .../ops/ragged/ragged_batch_gather_op_test.py | 3 + .../ops/ragged/ragged_boolean_mask_op_test.py | 2 + .../ops/ragged/ragged_concat_op_test.py | 10 + .../python/ops/ragged/ragged_const_op_test.py | 8 +- .../ops/ragged/ragged_conversion_ops.py | 29 +- .../ops/ragged/ragged_elementwise_ops.py | 62 +- .../ops/ragged/ragged_elementwise_ops_test.py | 56 +- .../ops/ragged/ragged_expand_dims_op_test.py | 1 + .../python/ops/ragged/ragged_factory_ops.py | 30 + .../ops/ragged/ragged_from_sparse_op_test.py | 19 + .../ops/ragged/ragged_from_tensor_op_test.py | 7 +- .../ops/ragged/ragged_gather_nd_op_test.py | 5 +- .../ops/ragged/ragged_gather_op_test.py | 10 + .../ops/ragged/ragged_map_fn_op_test.py | 11 +- .../ragged/ragged_map_inner_values_op_test.py | 13 + .../ops/ragged/ragged_operators_test.py | 3 + .../python/ops/ragged/ragged_range_op_test.py | 9 + .../ops/ragged/ragged_reduce_op_test.py | 4 + .../ops/ragged/ragged_row_lengths_op_test.py | 1 + ...agged_row_splits_to_segment_ids_op_test.py | 3 + ...agged_segment_ids_to_row_splits_op_test.py | 4 + .../ops/ragged/ragged_segment_op_test.py | 24 +- .../python/ops/ragged/ragged_stack_op_test.py | 2 + .../python/ops/ragged/ragged_string_ops.py | 119 + tensorflow/python/ops/ragged/ragged_tensor.py | 3 +- .../ragged_tensor_bounding_shape_op_test.py | 32 +- .../python/ops/ragged/ragged_tensor_shape.py | 570 + .../ops/ragged/ragged_tensor_shape_test.py | 487 + .../python/ops/ragged/ragged_tensor_test.py | 466 +- .../python/ops/ragged/ragged_tile_op_test.py | 11 + .../ops/ragged/ragged_to_sparse_op_test.py | 10 +- .../ops/ragged/ragged_to_tensor_op_test.py | 50 +- tensorflow/python/ops/ragged/ragged_util.py | 49 + .../python/ops/ragged/ragged_where_op_test.py | 3 +- tensorflow/python/ops/random_ops.py | 94 +- .../python/ops/resource_variable_ops.py | 57 +- tensorflow/python/ops/resources.py | 4 +- tensorflow/python/ops/rnn.py | 12 +- tensorflow/python/ops/rnn_cell_impl.py | 16 +- tensorflow/python/ops/sets_impl.py | 11 +- tensorflow/python/ops/signal/BUILD | 17 +- tensorflow/python/ops/signal/__init__.py | 37 - tensorflow/python/ops/signal/dct_ops.py | 192 + .../{spectral_ops.py => signal/fft_ops.py} | 328 +- tensorflow/python/ops/signal/mfcc_ops.py | 4 +- .../python/ops/signal/reconstruction_ops.py | 173 +- tensorflow/python/ops/signal/shape_ops.py | 2 +- tensorflow/python/ops/signal/signal.py | 65 + tensorflow/python/ops/signal/spectral_ops.py | 8 +- tensorflow/python/ops/sort_ops.py | 197 + .../python/ops/sort_ops_test.py | 16 +- tensorflow/python/ops/sparse_grad.py | 2 +- tensorflow/python/ops/sparse_ops.py | 410 +- tensorflow/python/ops/sparse_ops_test.py | 22 +- tensorflow/python/ops/special_math_ops.py | 7 +- .../python/ops/special_math_ops_test.py | 7 + tensorflow/python/ops/spectral_grad.py | 185 - tensorflow/python/ops/standard_ops.py | 3 +- tensorflow/python/ops/stateless_random_ops.py | 58 +- tensorflow/python/ops/string_ops.py | 77 +- tensorflow/python/ops/summary_op_util.py | 21 +- tensorflow/python/ops/summary_ops_v2.py | 93 +- tensorflow/python/ops/tensor_array_ops.py | 295 +- tensorflow/python/ops/tensor_forest_ops.py | 110 + tensorflow/python/ops/variable_scope.py | 185 +- tensorflow/python/ops/variables.py | 149 +- tensorflow/python/ops/while_v2.py | 79 +- tensorflow/python/platform/__init__.py | 0 tensorflow/python/platform/app.py | 2 +- tensorflow/python/platform/benchmark.py | 13 + tensorflow/python/platform/gfile.py | 4 +- tensorflow/python/platform/googletest.py | 11 +- tensorflow/python/platform/test.py | 4 +- tensorflow/python/platform/tf_logging.py | 65 +- .../profiler/internal/run_metadata_test.py | 3 + tensorflow/python/profiler/model_analyzer.py | 6 +- .../python/profiler/model_analyzer_test.py | 30 +- tensorflow/python/profiler/option_builder.py | 2 +- .../python/profiler/pprof_profiler_test.py | 2 + .../python/profiler/profile_context_test.py | 24 +- tensorflow/python/profiler/profiler.py | 8 +- tensorflow/python/profiler/profiler_test.py | 3 + tensorflow/python/profiler/tfprof_logger.py | 2 +- tensorflow/python/saved_model/BUILD | 63 +- tensorflow/python/saved_model/builder.py | 1 + tensorflow/python/saved_model/builder_impl.py | 465 +- tensorflow/python/saved_model/constants.py | 12 +- tensorflow/python/saved_model/load.py | 61 + tensorflow/python/saved_model/load_test.py | 51 + tensorflow/python/saved_model/loader_impl.py | 113 +- tensorflow/python/saved_model/loader_test.py | 130 +- tensorflow/python/saved_model/save.py | 364 +- tensorflow/python/saved_model/save_test.py | 156 +- .../python/saved_model/saved_model_test.py | 726 +- .../saved_model/saved_object_graph.proto | 38 + .../python/saved_model/signature_constants.py | 2 +- .../python/saved_model/signature_def_utils.py | 2 + .../saved_model/signature_def_utils_impl.py | 51 +- .../saved_model/signature_def_utils_test.py | 27 + .../python/saved_model/simple_save_test.py | 6 +- tensorflow/python/saved_model/utils_impl.py | 21 + tensorflow/python/summary/summary.py | 18 +- tensorflow/python/summary/summary_test.py | 13 + .../python/summary/writer/writer_test.py | 22 +- tensorflow/python/tf2.py | 17 +- tensorflow/python/tools/BUILD | 2 + .../python/tools/api/generator/api_gen.bzl | 11 +- .../tools/api/generator/api_init_files.bzl | 7 +- .../tools/api/generator/api_init_files_v1.bzl | 2 + .../tools/api/generator/create_python_api.py | 9 +- .../python/tools/api/generator/doc_srcs.py | 6 +- tensorflow/python/tools/freeze_graph_test.py | 2 + tensorflow/python/tools/inspect_checkpoint.py | 2 +- .../tools/optimize_for_inference_test.py | 5 + tensorflow/python/tools/strip_unused_test.py | 4 +- tensorflow/python/training/adadelta.py | 2 +- tensorflow/python/training/adadelta_test.py | 6 +- tensorflow/python/training/adagrad.py | 2 +- tensorflow/python/training/adagrad_da.py | 2 +- tensorflow/python/training/adagrad_da_test.py | 30 +- tensorflow/python/training/adagrad_test.py | 58 +- tensorflow/python/training/adam.py | 2 +- tensorflow/python/training/adam_test.py | 49 +- .../python/training/basic_loops_test.py | 4 + .../training/basic_session_run_hooks.py | 8 +- .../training/basic_session_run_hooks_test.py | 209 +- .../training/checkpoint_management_test.py | 9 +- .../python/training/checkpoint_ops_test.py | 5 +- .../python/training/checkpoint_utils.py | 4 +- .../python/training/checkpointable/BUILD | 2 +- .../checkpointable/data_structures.py | 50 +- .../checkpointable/data_structures_test.py | 21 + .../training/checkpointable/tracking.py | 37 + .../python/training/checkpointable/util.py | 85 +- .../training/checkpointable/util_test.py | 16 +- tensorflow/python/training/coordinator.py | 2 +- tensorflow/python/training/device_setter.py | 2 +- .../python/training/device_setter_test.py | 11 + tensorflow/python/training/distribute.py | 1229 +- .../training/distribution_strategy_context.py | 190 +- tensorflow/python/training/evaluation.py | 2 +- tensorflow/python/training/ftrl.py | 2 +- tensorflow/python/training/ftrl_test.py | 56 +- .../python/training/gradient_descent.py | 2 +- .../python/training/gradient_descent_test.py | 78 +- tensorflow/python/training/input_test.py | 264 +- .../python/training/learning_rate_decay.py | 2 +- .../training/learning_rate_decay_test.py | 35 +- .../python/training/learning_rate_decay_v2.py | 2 +- .../training/learning_rate_decay_v2_test.py | 34 +- tensorflow/python/training/momentum.py | 2 +- tensorflow/python/training/momentum_test.py | 126 +- .../python/training/monitored_session.py | 20 +- .../python/training/monitored_session_test.py | 75 +- tensorflow/python/training/moving_averages.py | 7 +- .../python/training/moving_averages_test.py | 73 +- tensorflow/python/training/optimizer.py | 47 +- tensorflow/python/training/optimizer_test.py | 28 +- .../python/training/proximal_adagrad.py | 2 +- .../python/training/proximal_adagrad_test.py | 36 +- .../proximal_gradient_descent_test.py | 31 +- .../python/training/quantize_training_test.py | 6 +- .../python/training/queue_runner_test.py | 34 +- tensorflow/python/training/rmsprop.py | 2 +- tensorflow/python/training/rmsprop_test.py | 155 +- tensorflow/python/training/saver.py | 58 +- .../saver_large_partitioned_variable_test.py | 9 +- tensorflow/python/training/saver_test.py | 173 +- .../server_lib_multiple_containers_test.py | 2 + ...lib_same_variables_clear_container_test.py | 10 +- .../server_lib_same_variables_clear_test.py | 2 + ...server_lib_same_variables_no_clear_test.py | 2 + .../training/server_lib_sparse_job_test.py | 4 +- tensorflow/python/training/server_lib_test.py | 2 +- tensorflow/python/training/session_manager.py | 2 +- .../python/training/session_manager_test.py | 15 + .../python/training/session_run_hook.py | 6 +- .../python/training/slot_creator_test.py | 20 +- tensorflow/python/training/supervisor.py | 2 +- tensorflow/python/training/supervisor_test.py | 26 +- .../training/sync_replicas_optimizer.py | 9 +- .../python/training/training_ops_test.py | 57 +- .../python/training/training_util_test.py | 3 + .../python/training/warm_starting_util.py | 10 +- .../training/warm_starting_util_test.py | 82 +- tensorflow/python/util/deprecation.py | 19 +- tensorflow/python/util/deprecation_test.py | 16 + tensorflow/python/util/dispatch.py | 192 + tensorflow/python/util/dispatch_test.py | 120 + tensorflow/python/util/nest_test.py | 1 + tensorflow/python/util/py_checkpoint_reader.i | 1 - tensorflow/python/util/tf_export.py | 40 + tensorflow/python/util/tf_export_test.py | 20 + tensorflow/python/util/tf_should_use_test.py | 9 +- tensorflow/stream_executor/BUILD | 15 +- tensorflow/stream_executor/cuda/cuda_blas.cc | 122 +- tensorflow/stream_executor/cuda/cuda_dnn.cc | 247 +- tensorflow/stream_executor/cuda/cuda_dnn.h | 13 +- tensorflow/stream_executor/cuda/cuda_fft.cc | 81 +- .../stream_executor/cuda/cuda_gpu_executor.cc | 9 +- .../stream_executor/cuda/cuda_gpu_executor.h | 3 +- tensorflow/stream_executor/cuda/cuda_rng.cc | 36 + .../stream_executor/device_description.cc | 12 +- tensorflow/stream_executor/dnn.cc | 133 +- tensorflow/stream_executor/dnn.h | 272 +- tensorflow/stream_executor/dnn.proto | 103 + .../stream_executor/host/host_gpu_executor.cc | 9 +- .../stream_executor/host/host_gpu_executor.h | 3 +- tensorflow/stream_executor/stream.cc | 5 +- tensorflow/stream_executor/stream.h | 16 +- .../stream_executor_internal.cc | 19 +- .../stream_executor_internal.h | 4 +- tensorflow/tensorflow.bzl | 27 +- ...nsorflow.-config-proto.-experimental.pbtxt | 8 +- .../golden/v1/tensorflow.-config-proto.pbtxt | 6 + .../golden/v1/tensorflow.-gradient-tape.pbtxt | 8 + .../golden/v1/tensorflow.-tensor-spec.pbtxt | 33 + .../golden/v1/tensorflow.data.-dataset.pbtxt | 3 +- ...ow.data.-fixed-length-record-dataset.pbtxt | 7 +- .../golden/v1/tensorflow.data.-options.pbtxt | 37 +- .../tensorflow.data.-t-f-record-dataset.pbtxt | 6 +- .../tensorflow.data.-text-line-dataset.pbtxt | 7 +- ...rflow.data.experimental.-csv-dataset.pbtxt | 7 +- ...a.experimental.-optimization-options.pbtxt | 46 + ...ow.data.experimental.-random-dataset.pbtxt | 7 +- ...rflow.data.experimental.-sql-dataset.pbtxt | 7 +- ...low.data.experimental.-stats-options.pbtxt | 3 +- ...data.experimental.-threading-options.pbtxt | 18 + .../v1/tensorflow.data.experimental.pbtxt | 26 +- .../tools/api/golden/v1/tensorflow.data.pbtxt | 8 + .../api/golden/v1/tensorflow.debugging.pbtxt | 2 +- ...tensorflow.distribute.-input-context.pbtxt | 25 + ...w.distribute.-input-replication-mode.pbtxt | 8 + .../v1/tensorflow.distribute.-reduce-op.pbtxt | 12 + ...nsorflow.distribute.-replica-context.pbtxt | 33 + ...orflow.distribute.-strategy-extended.pbtxt | 81 + .../v1/tensorflow.distribute.-strategy.pbtxt | 137 + .../api/golden/v1/tensorflow.distribute.pbtxt | 47 + ...rflow.estimator.-baseline-classifier.pbtxt | 7 +- ...orflow.estimator.-baseline-estimator.pbtxt | 7 +- ...orflow.estimator.-baseline-regressor.pbtxt | 7 +- ....estimator.-boosted-trees-classifier.pbtxt | 7 +- ...w.estimator.-boosted-trees-regressor.pbtxt | 7 +- ...nsorflow.estimator.-d-n-n-classifier.pbtxt | 7 +- ...ensorflow.estimator.-d-n-n-estimator.pbtxt | 7 +- ...or.-d-n-n-linear-combined-classifier.pbtxt | 7 +- ...tor.-d-n-n-linear-combined-estimator.pbtxt | 7 +- ...tor.-d-n-n-linear-combined-regressor.pbtxt | 7 +- ...ensorflow.estimator.-d-n-n-regressor.pbtxt | 7 +- .../v1/tensorflow.estimator.-estimator.pbtxt | 7 +- ...sorflow.estimator.-linear-classifier.pbtxt | 7 +- ...nsorflow.estimator.-linear-estimator.pbtxt | 7 +- ...nsorflow.estimator.-linear-regressor.pbtxt | 7 +- ...erimental.-in-memory-evaluator-hook.pbtxt} | 6 +- .../tensorflow.estimator.experimental.pbtxt | 12 + .../api/golden/v1/tensorflow.image.pbtxt | 8 + .../api/golden/v1/tensorflow.io.gfile.pbtxt | 51 + .../tools/api/golden/v1/tensorflow.io.pbtxt | 40 + .../golden/v1/tensorflow.keras.-model.pbtxt | 26 +- .../v1/tensorflow.keras.-sequential.pbtxt | 26 +- .../golden/v1/tensorflow.keras.backend.pbtxt | 6 +- ....experimental.-peephole-l-s-t-m-cell.pbtxt | 4 + .../tensorflow.keras.layers.-activation.pbtxt | 4 + ...eras.layers.-activity-regularization.pbtxt | 4 + .../v1/tensorflow.keras.layers.-add.pbtxt | 4 + ...nsorflow.keras.layers.-alpha-dropout.pbtxt | 4 + ...low.keras.layers.-average-pooling1-d.pbtxt | 4 + ...low.keras.layers.-average-pooling2-d.pbtxt | 4 + ...low.keras.layers.-average-pooling3-d.pbtxt | 4 + .../v1/tensorflow.keras.layers.-average.pbtxt | 4 + ...tensorflow.keras.layers.-avg-pool1-d.pbtxt | 4 + ...tensorflow.keras.layers.-avg-pool2-d.pbtxt | 4 + ...tensorflow.keras.layers.-avg-pool3-d.pbtxt | 4 + ...ow.keras.layers.-batch-normalization.pbtxt | 7 +- ...nsorflow.keras.layers.-bidirectional.pbtxt | 4 + ...tensorflow.keras.layers.-concatenate.pbtxt | 4 + ...orflow.keras.layers.-conv-l-s-t-m2-d.pbtxt | 4 + .../v1/tensorflow.keras.layers.-conv1-d.pbtxt | 4 + ...flow.keras.layers.-conv2-d-transpose.pbtxt | 4 + .../v1/tensorflow.keras.layers.-conv2-d.pbtxt | 4 + ...flow.keras.layers.-conv3-d-transpose.pbtxt | 4 + .../v1/tensorflow.keras.layers.-conv3-d.pbtxt | 4 + ...sorflow.keras.layers.-convolution1-d.pbtxt | 4 + ...ras.layers.-convolution2-d-transpose.pbtxt | 4 + ...sorflow.keras.layers.-convolution2-d.pbtxt | 4 + ...ras.layers.-convolution3-d-transpose.pbtxt | 4 + ...sorflow.keras.layers.-convolution3-d.pbtxt | 4 + ...tensorflow.keras.layers.-cropping1-d.pbtxt | 4 + ...tensorflow.keras.layers.-cropping2-d.pbtxt | 4 + ...tensorflow.keras.layers.-cropping3-d.pbtxt | 4 + ...sorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt | 4 + ...rflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt | 4 + .../v1/tensorflow.keras.layers.-dense.pbtxt | 4 + ...flow.keras.layers.-depthwise-conv2-d.pbtxt | 4 + .../v1/tensorflow.keras.layers.-dot.pbtxt | 4 + .../v1/tensorflow.keras.layers.-dropout.pbtxt | 4 + .../v1/tensorflow.keras.layers.-e-l-u.pbtxt | 4 + .../tensorflow.keras.layers.-embedding.pbtxt | 4 + .../v1/tensorflow.keras.layers.-flatten.pbtxt | 4 + .../tensorflow.keras.layers.-g-r-u-cell.pbtxt | 4 + .../v1/tensorflow.keras.layers.-g-r-u.pbtxt | 4 + ...rflow.keras.layers.-gaussian-dropout.pbtxt | 4 + ...sorflow.keras.layers.-gaussian-noise.pbtxt | 4 + ...as.layers.-global-average-pooling1-d.pbtxt | 4 + ...as.layers.-global-average-pooling2-d.pbtxt | 4 + ...as.layers.-global-average-pooling3-d.pbtxt | 4 + ...low.keras.layers.-global-avg-pool1-d.pbtxt | 4 + ...low.keras.layers.-global-avg-pool2-d.pbtxt | 4 + ...low.keras.layers.-global-avg-pool3-d.pbtxt | 4 + ...low.keras.layers.-global-max-pool1-d.pbtxt | 4 + ...low.keras.layers.-global-max-pool2-d.pbtxt | 4 + ...low.keras.layers.-global-max-pool3-d.pbtxt | 4 + ....keras.layers.-global-max-pooling1-d.pbtxt | 4 + ....keras.layers.-global-max-pooling2-d.pbtxt | 4 + ....keras.layers.-global-max-pooling3-d.pbtxt | 4 + ...tensorflow.keras.layers.-input-layer.pbtxt | 4 + .../tensorflow.keras.layers.-input-spec.pbtxt | 2 +- ...ensorflow.keras.layers.-l-s-t-m-cell.pbtxt | 4 + .../v1/tensorflow.keras.layers.-l-s-t-m.pbtxt | 4 + .../v1/tensorflow.keras.layers.-lambda.pbtxt | 4 + .../v1/tensorflow.keras.layers.-layer.pbtxt | 4 + ...ensorflow.keras.layers.-leaky-re-l-u.pbtxt | 4 + ...w.keras.layers.-locally-connected1-d.pbtxt | 4 + ...w.keras.layers.-locally-connected2-d.pbtxt | 4 + .../v1/tensorflow.keras.layers.-masking.pbtxt | 4 + ...tensorflow.keras.layers.-max-pool1-d.pbtxt | 4 + ...tensorflow.keras.layers.-max-pool2-d.pbtxt | 4 + ...tensorflow.keras.layers.-max-pool3-d.pbtxt | 4 + ...sorflow.keras.layers.-max-pooling1-d.pbtxt | 4 + ...sorflow.keras.layers.-max-pooling2-d.pbtxt | 4 + ...sorflow.keras.layers.-max-pooling3-d.pbtxt | 4 + .../v1/tensorflow.keras.layers.-maximum.pbtxt | 4 + .../v1/tensorflow.keras.layers.-minimum.pbtxt | 4 + .../tensorflow.keras.layers.-multiply.pbtxt | 4 + .../tensorflow.keras.layers.-p-re-l-u.pbtxt | 4 + .../v1/tensorflow.keras.layers.-permute.pbtxt | 4 + .../v1/tensorflow.keras.layers.-r-n-n.pbtxt | 4 + .../v1/tensorflow.keras.layers.-re-l-u.pbtxt | 4 + ...nsorflow.keras.layers.-repeat-vector.pbtxt | 4 + .../v1/tensorflow.keras.layers.-reshape.pbtxt | 4 + ...flow.keras.layers.-separable-conv1-d.pbtxt | 4 + ...flow.keras.layers.-separable-conv2-d.pbtxt | 4 + ...ras.layers.-separable-convolution1-d.pbtxt | 4 + ...ras.layers.-separable-convolution2-d.pbtxt | 4 + ...flow.keras.layers.-simple-r-n-n-cell.pbtxt | 4 + ...ensorflow.keras.layers.-simple-r-n-n.pbtxt | 4 + .../v1/tensorflow.keras.layers.-softmax.pbtxt | 4 + ...low.keras.layers.-spatial-dropout1-d.pbtxt | 4 + ...low.keras.layers.-spatial-dropout2-d.pbtxt | 4 + ...low.keras.layers.-spatial-dropout3-d.pbtxt | 4 + ...ow.keras.layers.-stacked-r-n-n-cells.pbtxt | 4 + .../tensorflow.keras.layers.-subtract.pbtxt | 4 + ...low.keras.layers.-thresholded-re-l-u.pbtxt | 4 + ...rflow.keras.layers.-time-distributed.pbtxt | 4 + ...sorflow.keras.layers.-up-sampling1-d.pbtxt | 4 + ...sorflow.keras.layers.-up-sampling2-d.pbtxt | 4 + ...sorflow.keras.layers.-up-sampling3-d.pbtxt | 4 + .../v1/tensorflow.keras.layers.-wrapper.pbtxt | 4 + ...orflow.keras.layers.-zero-padding1-d.pbtxt | 4 + ...orflow.keras.layers.-zero-padding2-d.pbtxt | 4 + ...orflow.keras.layers.-zero-padding3-d.pbtxt | 4 + ...ow.keras.losses.-binary-crossentropy.pbtxt | 22 + ...ras.losses.-categorical-crossentropy.pbtxt | 22 + ...ow.keras.losses.-mean-absolute-error.pbtxt | 22 + ...sses.-mean-absolute-percentage-error.pbtxt | 22 + ...low.keras.losses.-mean-squared-error.pbtxt | 22 + ...sses.-mean-squared-logarithmic-error.pbtxt | 22 + .../golden/v1/tensorflow.keras.losses.pbtxt | 30 +- .../tensorflow.keras.metrics.-accuracy.pbtxt | 194 + ...rflow.keras.metrics.-binary-accuracy.pbtxt | 194 + ....keras.metrics.-categorical-accuracy.pbtxt | 194 + ...rflow.keras.metrics.-false-negatives.pbtxt | 193 + ...rflow.keras.metrics.-false-positives.pbtxt | 193 + .../v1/tensorflow.keras.metrics.-mean.pbtxt | 192 + .../tensorflow.keras.metrics.-precision.pbtxt | 192 + .../v1/tensorflow.keras.metrics.-recall.pbtxt | 192 + ...metrics.-sparse-categorical-accuracy.pbtxt | 194 + ...orflow.keras.metrics.-true-negatives.pbtxt | 193 + ...orflow.keras.metrics.-true-positives.pbtxt | 193 + .../golden/v1/tensorflow.keras.metrics.pbtxt | 50 +- .../v1/tensorflow.keras.models.-model.pbtxt | 26 +- .../tensorflow.keras.models.-sequential.pbtxt | 26 +- .../v1/tensorflow.keras.utils.-progbar.pbtxt | 2 +- ...ensorflow.layers.-average-pooling1-d.pbtxt | 4 + ...ensorflow.layers.-average-pooling2-d.pbtxt | 4 + ...ensorflow.layers.-average-pooling3-d.pbtxt | 4 + ...nsorflow.layers.-batch-normalization.pbtxt | 7 +- .../v1/tensorflow.layers.-conv1-d.pbtxt | 4 + ...tensorflow.layers.-conv2-d-transpose.pbtxt | 4 + .../v1/tensorflow.layers.-conv2-d.pbtxt | 4 + ...tensorflow.layers.-conv3-d-transpose.pbtxt | 4 + .../v1/tensorflow.layers.-conv3-d.pbtxt | 4 + .../golden/v1/tensorflow.layers.-dense.pbtxt | 4 + .../v1/tensorflow.layers.-dropout.pbtxt | 4 + .../v1/tensorflow.layers.-flatten.pbtxt | 4 + .../v1/tensorflow.layers.-input-spec.pbtxt | 2 +- .../golden/v1/tensorflow.layers.-layer.pbtxt | 4 + .../tensorflow.layers.-max-pooling1-d.pbtxt | 4 + .../tensorflow.layers.-max-pooling2-d.pbtxt | 4 + .../tensorflow.layers.-max-pooling3-d.pbtxt | 4 + ...tensorflow.layers.-separable-conv1-d.pbtxt | 4 + ...tensorflow.layers.-separable-conv2-d.pbtxt | 4 + ...w.linalg.-linear-operator-block-diag.pbtxt | 4 + ...ow.linalg.-linear-operator-circulant.pbtxt | 4 + ...linalg.-linear-operator-circulant2-d.pbtxt | 4 + ...linalg.-linear-operator-circulant3-d.pbtxt | 4 + ....linalg.-linear-operator-composition.pbtxt | 4 + ...sorflow.linalg.-linear-operator-diag.pbtxt | 4 + ....linalg.-linear-operator-full-matrix.pbtxt | 4 + ...low.linalg.-linear-operator-identity.pbtxt | 4 + ...ow.linalg.-linear-operator-kronecker.pbtxt | 4 + ...alg.-linear-operator-low-rank-update.pbtxt | 4 + ...lg.-linear-operator-lower-triangular.pbtxt | 4 + ...alg.-linear-operator-scaled-identity.pbtxt | 4 + ...orflow.linalg.-linear-operator-zeros.pbtxt | 4 + .../tensorflow.linalg.-linear-operator.pbtxt | 4 + .../golden/v1/tensorflow.lite.constants.pbtxt | 10 +- .../tools/api/golden/v1/tensorflow.math.pbtxt | 26 +- .../v1/tensorflow.metrics.-accuracy.pbtxt | 194 + .../tensorflow.metrics.-binary-accuracy.pbtxt | 194 + ...orflow.metrics.-categorical-accuracy.pbtxt | 194 + .../tensorflow.metrics.-false-negatives.pbtxt | 193 + .../tensorflow.metrics.-false-positives.pbtxt | 193 + .../golden/v1/tensorflow.metrics.-mean.pbtxt | 192 + .../v1/tensorflow.metrics.-precision.pbtxt | 192 + .../v1/tensorflow.metrics.-recall.pbtxt | 192 + ...metrics.-sparse-categorical-accuracy.pbtxt | 194 + .../tensorflow.metrics.-true-negatives.pbtxt | 193 + .../tensorflow.metrics.-true-positives.pbtxt | 193 + .../api/golden/v1/tensorflow.metrics.pbtxt | 44 + .../tools/api/golden/v1/tensorflow.nn.pbtxt | 28 +- ...flow.nn.rnn_cell.-basic-l-s-t-m-cell.pbtxt | 4 + ...orflow.nn.rnn_cell.-basic-r-n-n-cell.pbtxt | 4 + ...nsorflow.nn.rnn_cell.-device-wrapper.pbtxt | 4 + ...sorflow.nn.rnn_cell.-dropout-wrapper.pbtxt | 4 + .../tensorflow.nn.rnn_cell.-g-r-u-cell.pbtxt | 4 + ...tensorflow.nn.rnn_cell.-l-s-t-m-cell.pbtxt | 4 + ...orflow.nn.rnn_cell.-multi-r-n-n-cell.pbtxt | 4 + .../tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt | 4 + ...orflow.nn.rnn_cell.-residual-wrapper.pbtxt | 4 + .../tools/api/golden/v1/tensorflow.pbtxt | 56 +- .../golden/v1/tensorflow.quantization.pbtxt | 2 +- .../api/golden/v1/tensorflow.random.pbtxt | 8 + .../v1/tensorflow.saved_model.-builder.pbtxt | 1 + ...d_model.builder.-saved-model-builder.pbtxt | 1 + .../golden/v1/tensorflow.saved_model.pbtxt | 4 + .../tools/api/golden/v1/tensorflow.sets.pbtxt | 16 + .../api/golden/v1/tensorflow.signal.pbtxt | 32 + .../api/golden/v1/tensorflow.sparse.pbtxt | 6 +- .../api/golden/v1/tensorflow.strings.pbtxt | 4 + .../v1/tensorflow.test.-benchmark.pbtxt | 4 + .../api/golden/v1/tensorflow.train.pbtxt | 4 + ...orflow.-conditional-accumulator-base.pbtxt | 29 - .../tensorflow.-conditional-accumulator.pbtxt | 38 - ...nsorflow.-config-proto.-experimental.pbtxt | 6 + .../golden/v2/tensorflow.-config-proto.pbtxt | 6 + .../golden/v2/tensorflow.-device-spec.pbtxt | 37 - .../api/golden/v2/tensorflow.-dimension.pbtxt | 25 - .../golden/v2/tensorflow.-gradient-tape.pbtxt | 8 + .../golden/v2/tensorflow.-graph-keys.pbtxt | 140 - .../tensorflow.-tensor-info.-coo-sparse.pbtxt | 24 - .../golden/v2/tensorflow.-tensor-info.pbtxt | 59 - .../golden/v2/tensorflow.-tensor-spec.pbtxt | 33 + .../tools/api/golden/v2/tensorflow.app.pbtxt | 7 - .../golden/v2/tensorflow.data.-dataset.pbtxt | 19 +- ...ow.data.-fixed-length-record-dataset.pbtxt | 20 +- .../golden/v2/tensorflow.data.-iterator.pbtxt | 46 - .../golden/v2/tensorflow.data.-options.pbtxt | 37 +- .../tensorflow.data.-t-f-record-dataset.pbtxt | 20 +- .../tensorflow.data.-text-line-dataset.pbtxt | 20 +- ...rflow.data.experimental.-csv-dataset.pbtxt | 20 +- ...a.experimental.-optimization-options.pbtxt | 46 + ...ow.data.experimental.-random-dataset.pbtxt | 20 +- ...rflow.data.experimental.-sql-dataset.pbtxt | 20 +- ...low.data.experimental.-stats-options.pbtxt | 3 +- ...data.experimental.-threading-options.pbtxt | 18 + .../v2/tensorflow.data.experimental.pbtxt | 26 +- .../tools/api/golden/v2/tensorflow.data.pbtxt | 4 - .../api/golden/v2/tensorflow.debugging.pbtxt | 52 +- ...tensorflow.distribute.-input-context.pbtxt | 25 + ...w.distribute.-input-replication-mode.pbtxt | 8 + .../v2/tensorflow.distribute.-reduce-op.pbtxt | 12 + ...nsorflow.distribute.-replica-context.pbtxt | 33 + ...orflow.distribute.-strategy-extended.pbtxt | 81 + .../v2/tensorflow.distribute.-strategy.pbtxt | 137 + .../api/golden/v2/tensorflow.distribute.pbtxt | 47 + ...rflow.estimator.-baseline-classifier.pbtxt | 14 +- ...orflow.estimator.-baseline-estimator.pbtxt | 12 +- ...orflow.estimator.-baseline-regressor.pbtxt | 14 +- ....estimator.-boosted-trees-classifier.pbtxt | 7 +- ...w.estimator.-boosted-trees-regressor.pbtxt | 7 +- ...nsorflow.estimator.-d-n-n-classifier.pbtxt | 14 +- ...ensorflow.estimator.-d-n-n-estimator.pbtxt | 12 +- ...or.-d-n-n-linear-combined-classifier.pbtxt | 14 +- ...tor.-d-n-n-linear-combined-estimator.pbtxt | 12 +- ...tor.-d-n-n-linear-combined-regressor.pbtxt | 14 +- ...ensorflow.estimator.-d-n-n-regressor.pbtxt | 14 +- .../v2/tensorflow.estimator.-estimator.pbtxt | 10 +- ...sorflow.estimator.-linear-classifier.pbtxt | 10 +- ...nsorflow.estimator.-linear-estimator.pbtxt | 12 +- ...nsorflow.estimator.-linear-regressor.pbtxt | 14 +- ...perimental.-in-memory-evaluator-hook.pbtxt | 30 + .../tensorflow.estimator.experimental.pbtxt | 12 + .../golden/v2/tensorflow.feature_column.pbtxt | 10 +- .../v2/tensorflow.gfile.-fast-g-file.pbtxt | 58 - .../golden/v2/tensorflow.gfile.-g-file.pbtxt | 58 - .../golden/v2/tensorflow.gfile.-open.pbtxt | 58 - .../api/golden/v2/tensorflow.gfile.pbtxt | 63 - .../api/golden/v2/tensorflow.image.pbtxt | 30 +- .../api/golden/v2/tensorflow.io.gfile.pbtxt | 51 + .../tools/api/golden/v2/tensorflow.io.pbtxt | 54 +- .../golden/v2/tensorflow.keras.-model.pbtxt | 26 +- .../v2/tensorflow.keras.-sequential.pbtxt | 26 +- .../golden/v2/tensorflow.keras.backend.pbtxt | 6 +- ....experimental.-peephole-l-s-t-m-cell.pbtxt | 4 + .../tensorflow.keras.layers.-activation.pbtxt | 4 + ...eras.layers.-activity-regularization.pbtxt | 4 + .../v2/tensorflow.keras.layers.-add.pbtxt | 4 + ...nsorflow.keras.layers.-alpha-dropout.pbtxt | 4 + ...low.keras.layers.-average-pooling1-d.pbtxt | 4 + ...low.keras.layers.-average-pooling2-d.pbtxt | 4 + ...low.keras.layers.-average-pooling3-d.pbtxt | 4 + .../v2/tensorflow.keras.layers.-average.pbtxt | 4 + ...tensorflow.keras.layers.-avg-pool1-d.pbtxt | 4 + ...tensorflow.keras.layers.-avg-pool2-d.pbtxt | 4 + ...tensorflow.keras.layers.-avg-pool3-d.pbtxt | 4 + ...ow.keras.layers.-batch-normalization.pbtxt | 6 +- ...nsorflow.keras.layers.-bidirectional.pbtxt | 4 + ...tensorflow.keras.layers.-concatenate.pbtxt | 4 + ...orflow.keras.layers.-conv-l-s-t-m2-d.pbtxt | 4 + .../v2/tensorflow.keras.layers.-conv1-d.pbtxt | 4 + ...flow.keras.layers.-conv2-d-transpose.pbtxt | 4 + .../v2/tensorflow.keras.layers.-conv2-d.pbtxt | 4 + ...flow.keras.layers.-conv3-d-transpose.pbtxt | 4 + .../v2/tensorflow.keras.layers.-conv3-d.pbtxt | 4 + ...sorflow.keras.layers.-convolution1-d.pbtxt | 4 + ...ras.layers.-convolution2-d-transpose.pbtxt | 4 + ...sorflow.keras.layers.-convolution2-d.pbtxt | 4 + ...ras.layers.-convolution3-d-transpose.pbtxt | 4 + ...sorflow.keras.layers.-convolution3-d.pbtxt | 4 + ...tensorflow.keras.layers.-cropping1-d.pbtxt | 4 + ...tensorflow.keras.layers.-cropping2-d.pbtxt | 4 + ...tensorflow.keras.layers.-cropping3-d.pbtxt | 4 + ...sorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt | 4 + ...rflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt | 4 + ...orflow.keras.layers.-dense-features.pbtxt} | 40 +- .../v2/tensorflow.keras.layers.-dense.pbtxt | 4 + ...flow.keras.layers.-depthwise-conv2-d.pbtxt | 4 + .../v2/tensorflow.keras.layers.-dot.pbtxt | 4 + .../v2/tensorflow.keras.layers.-dropout.pbtxt | 4 + .../v2/tensorflow.keras.layers.-e-l-u.pbtxt | 4 + .../tensorflow.keras.layers.-embedding.pbtxt | 4 + .../v2/tensorflow.keras.layers.-flatten.pbtxt | 4 + .../tensorflow.keras.layers.-g-r-u-cell.pbtxt | 4 + .../v2/tensorflow.keras.layers.-g-r-u.pbtxt | 4 + ...rflow.keras.layers.-gaussian-dropout.pbtxt | 4 + ...sorflow.keras.layers.-gaussian-noise.pbtxt | 4 + ...as.layers.-global-average-pooling1-d.pbtxt | 4 + ...as.layers.-global-average-pooling2-d.pbtxt | 4 + ...as.layers.-global-average-pooling3-d.pbtxt | 4 + ...low.keras.layers.-global-avg-pool1-d.pbtxt | 4 + ...low.keras.layers.-global-avg-pool2-d.pbtxt | 4 + ...low.keras.layers.-global-avg-pool3-d.pbtxt | 4 + ...low.keras.layers.-global-max-pool1-d.pbtxt | 4 + ...low.keras.layers.-global-max-pool2-d.pbtxt | 4 + ...low.keras.layers.-global-max-pool3-d.pbtxt | 4 + ....keras.layers.-global-max-pooling1-d.pbtxt | 4 + ....keras.layers.-global-max-pooling2-d.pbtxt | 4 + ....keras.layers.-global-max-pooling3-d.pbtxt | 4 + ...tensorflow.keras.layers.-input-layer.pbtxt | 4 + .../tensorflow.keras.layers.-input-spec.pbtxt | 2 +- ...ensorflow.keras.layers.-l-s-t-m-cell.pbtxt | 4 + .../v2/tensorflow.keras.layers.-l-s-t-m.pbtxt | 4 + .../v2/tensorflow.keras.layers.-lambda.pbtxt | 4 + .../v2/tensorflow.keras.layers.-layer.pbtxt | 4 + ...ensorflow.keras.layers.-leaky-re-l-u.pbtxt | 4 + ...ensorflow.keras.layers.-linear-model.pbtxt | 289 + ...w.keras.layers.-locally-connected1-d.pbtxt | 4 + ...w.keras.layers.-locally-connected2-d.pbtxt | 4 + .../v2/tensorflow.keras.layers.-masking.pbtxt | 4 + ...tensorflow.keras.layers.-max-pool1-d.pbtxt | 4 + ...tensorflow.keras.layers.-max-pool2-d.pbtxt | 4 + ...tensorflow.keras.layers.-max-pool3-d.pbtxt | 4 + ...sorflow.keras.layers.-max-pooling1-d.pbtxt | 4 + ...sorflow.keras.layers.-max-pooling2-d.pbtxt | 4 + ...sorflow.keras.layers.-max-pooling3-d.pbtxt | 4 + .../v2/tensorflow.keras.layers.-maximum.pbtxt | 4 + .../v2/tensorflow.keras.layers.-minimum.pbtxt | 4 + .../tensorflow.keras.layers.-multiply.pbtxt | 4 + .../tensorflow.keras.layers.-p-re-l-u.pbtxt | 4 + .../v2/tensorflow.keras.layers.-permute.pbtxt | 4 + .../v2/tensorflow.keras.layers.-r-n-n.pbtxt | 4 + .../v2/tensorflow.keras.layers.-re-l-u.pbtxt | 4 + ...nsorflow.keras.layers.-repeat-vector.pbtxt | 4 + .../v2/tensorflow.keras.layers.-reshape.pbtxt | 4 + ...flow.keras.layers.-separable-conv1-d.pbtxt | 4 + ...flow.keras.layers.-separable-conv2-d.pbtxt | 4 + ...ras.layers.-separable-convolution1-d.pbtxt | 4 + ...ras.layers.-separable-convolution2-d.pbtxt | 4 + ...flow.keras.layers.-simple-r-n-n-cell.pbtxt | 4 + ...ensorflow.keras.layers.-simple-r-n-n.pbtxt | 4 + .../v2/tensorflow.keras.layers.-softmax.pbtxt | 4 + ...low.keras.layers.-spatial-dropout1-d.pbtxt | 4 + ...low.keras.layers.-spatial-dropout2-d.pbtxt | 4 + ...low.keras.layers.-spatial-dropout3-d.pbtxt | 4 + ...ow.keras.layers.-stacked-r-n-n-cells.pbtxt | 4 + .../tensorflow.keras.layers.-subtract.pbtxt | 4 + ...low.keras.layers.-thresholded-re-l-u.pbtxt | 4 + ...rflow.keras.layers.-time-distributed.pbtxt | 4 + ...sorflow.keras.layers.-up-sampling1-d.pbtxt | 4 + ...sorflow.keras.layers.-up-sampling2-d.pbtxt | 4 + ...sorflow.keras.layers.-up-sampling3-d.pbtxt | 4 + .../v2/tensorflow.keras.layers.-wrapper.pbtxt | 4 + ...orflow.keras.layers.-zero-padding1-d.pbtxt | 4 + ...orflow.keras.layers.-zero-padding2-d.pbtxt | 4 + ...orflow.keras.layers.-zero-padding3-d.pbtxt | 4 + .../golden/v2/tensorflow.keras.layers.pbtxt | 8 + ...ow.keras.losses.-binary-crossentropy.pbtxt | 22 + ...ras.losses.-categorical-crossentropy.pbtxt | 22 + ...ow.keras.losses.-mean-absolute-error.pbtxt | 22 + ...sses.-mean-absolute-percentage-error.pbtxt | 22 + ...low.keras.losses.-mean-squared-error.pbtxt | 22 + ...sses.-mean-squared-logarithmic-error.pbtxt | 22 + .../tensorflow.keras.losses.-reduction.pbtxt | 28 + .../golden/v2/tensorflow.keras.losses.pbtxt | 34 +- .../tensorflow.keras.metrics.-accuracy.pbtxt | 194 + ...rflow.keras.metrics.-binary-accuracy.pbtxt | 194 + ....keras.metrics.-categorical-accuracy.pbtxt | 194 + ...rflow.keras.metrics.-false-negatives.pbtxt | 193 + ...rflow.keras.metrics.-false-positives.pbtxt | 193 + .../v2/tensorflow.keras.metrics.-mean.pbtxt | 192 + .../tensorflow.keras.metrics.-precision.pbtxt | 192 + .../v2/tensorflow.keras.metrics.-recall.pbtxt | 192 + ...metrics.-sparse-categorical-accuracy.pbtxt | 194 + ...orflow.keras.metrics.-true-negatives.pbtxt | 193 + ...orflow.keras.metrics.-true-positives.pbtxt | 193 + .../golden/v2/tensorflow.keras.metrics.pbtxt | 50 +- .../v2/tensorflow.keras.models.-model.pbtxt | 26 +- .../tensorflow.keras.models.-sequential.pbtxt | 26 +- .../v2/tensorflow.keras.utils.-progbar.pbtxt | 2 +- ...w.linalg.-linear-operator-block-diag.pbtxt | 4 + ...ow.linalg.-linear-operator-circulant.pbtxt | 4 + ...linalg.-linear-operator-circulant2-d.pbtxt | 4 + ...linalg.-linear-operator-circulant3-d.pbtxt | 4 + ....linalg.-linear-operator-composition.pbtxt | 4 + ...sorflow.linalg.-linear-operator-diag.pbtxt | 4 + ....linalg.-linear-operator-full-matrix.pbtxt | 4 + ...low.linalg.-linear-operator-identity.pbtxt | 4 + ...ow.linalg.-linear-operator-kronecker.pbtxt | 4 + ...alg.-linear-operator-low-rank-update.pbtxt | 4 + ...lg.-linear-operator-lower-triangular.pbtxt | 4 + ...alg.-linear-operator-scaled-identity.pbtxt | 4 + ...orflow.linalg.-linear-operator-zeros.pbtxt | 4 + .../tensorflow.linalg.-linear-operator.pbtxt | 4 + .../api/golden/v2/tensorflow.linalg.pbtxt | 4 +- .../golden/v2/tensorflow.lite.constants.pbtxt | 20 - .../api/golden/v2/tensorflow.logging.pbtxt | 83 - .../v2/tensorflow.losses.-reduction.pbtxt | 14 +- .../api/golden/v2/tensorflow.losses.pbtxt | 44 - .../tools/api/golden/v2/tensorflow.math.pbtxt | 54 +- .../v2/tensorflow.metrics.-accuracy.pbtxt | 194 + .../tensorflow.metrics.-binary-accuracy.pbtxt | 194 + ...orflow.metrics.-categorical-accuracy.pbtxt | 194 + .../tensorflow.metrics.-false-negatives.pbtxt | 193 + .../tensorflow.metrics.-false-positives.pbtxt | 193 + .../golden/v2/tensorflow.metrics.-mean.pbtxt | 192 + .../v2/tensorflow.metrics.-precision.pbtxt | 192 + .../v2/tensorflow.metrics.-recall.pbtxt | 192 + ...metrics.-sparse-categorical-accuracy.pbtxt | 194 + .../tensorflow.metrics.-true-negatives.pbtxt | 193 + .../tensorflow.metrics.-true-positives.pbtxt | 193 + .../api/golden/v2/tensorflow.metrics.pbtxt | 154 +- .../tools/api/golden/v2/tensorflow.nn.pbtxt | 102 +- ...nsorflow.nn.rnn_cell.-device-wrapper.pbtxt | 4 + ...sorflow.nn.rnn_cell.-dropout-wrapper.pbtxt | 4 + .../tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt | 4 + ...orflow.nn.rnn_cell.-residual-wrapper.pbtxt | 4 + .../golden/v2/tensorflow.nn.rnn_cell.pbtxt | 4 - .../tools/api/golden/v2/tensorflow.pbtxt | 258 +- ...flow.profiler.-advice-proto.-checker.pbtxt | 12 - ...ofiler.-advice-proto.-checkers-entry.pbtxt | 22 - .../tensorflow.profiler.-advice-proto.pbtxt | 41 - ...graph-node-proto.-input-shapes-entry.pbtxt | 22 - ...ensorflow.profiler.-graph-node-proto.pbtxt | 191 - ...low.profiler.-multi-graph-node-proto.pbtxt | 134 - ...er.-op-log-proto.-id-to-string-entry.pbtxt | 21 - .../tensorflow.profiler.-op-log-proto.pbtxt | 38 - ...low.profiler.-profile-option-builder.pbtxt | 93 - .../v2/tensorflow.profiler.-profiler.pbtxt | 37 - .../api/golden/v2/tensorflow.profiler.pbtxt | 39 - .../golden/v2/tensorflow.quantization.pbtxt | 2 +- .../api/golden/v2/tensorflow.random.pbtxt | 28 +- .../golden/v2/tensorflow.saved_model.pbtxt | 16 +- .../tools/api/golden/v2/tensorflow.sets.pbtxt | 8 +- .../api/golden/v2/tensorflow.signal.pbtxt | 32 + .../api/golden/v2/tensorflow.sparse.pbtxt | 36 +- .../api/golden/v2/tensorflow.spectral.pbtxt | 35 - .../api/golden/v2/tensorflow.strings.pbtxt | 14 +- .../tensorflow.summary.-summary-writer.pbtxt | 29 + .../api/golden/v2/tensorflow.summary.pbtxt | 40 +- .../v2/tensorflow.test.-benchmark.pbtxt | 4 + .../tools/api/golden/v2/tensorflow.test.pbtxt | 14 +- ...tensorflow.train.-adadelta-optimizer.pbtxt | 51 - ...sorflow.train.-adagrad-d-a-optimizer.pbtxt | 51 - .../tensorflow.train.-adagrad-optimizer.pbtxt | 51 - .../v2/tensorflow.train.-adam-optimizer.pbtxt | 51 - ...low.train.-checkpoint-saver-listener.pbtxt | 24 - ...sorflow.train.-chief-session-creator.pbtxt | 14 - .../v2/tensorflow.train.-ftrl-optimizer.pbtxt | 51 - ...ow.train.-gradient-descent-optimizer.pbtxt | 51 - .../v2/tensorflow.train.-looper-thread.pbtxt | 73 - ...tensorflow.train.-momentum-optimizer.pbtxt | 51 - ...ain.-monitored-session.-step-context.pbtxt | 21 - .../tensorflow.train.-monitored-session.pbtxt | 34 - ...rain.-nan-loss-during-training-error.pbtxt | 12 - .../v2/tensorflow.train.-optimizer.pbtxt | 50 - ...ow.train.-proximal-adagrad-optimizer.pbtxt | 51 - ...nsorflow.train.-r-m-s-prop-optimizer.pbtxt | 51 - .../v2/tensorflow.train.-scaffold.pbtxt | 53 - ...nsorflow.train.-second-or-step-timer.pbtxt | 26 - .../tensorflow.train.-session-creator.pbtxt | 12 - .../tensorflow.train.-session-manager.pbtxt | 21 - .../tensorflow.train.-session-run-args.pbtxt | 27 - ...ensorflow.train.-session-run-context.pbtxt | 25 - ...tensorflow.train.-session-run-values.pbtxt | 27 - ...ular-monitored-session.-step-context.pbtxt | 21 - ...ow.train.-singular-monitored-session.pbtxt | 38 - .../v2/tensorflow.train.-supervisor.pbtxt | 153 - .../v2/tensorflow.train.-vocab-info.pbtxt | 43 - ...orflow.train.-worker-session-creator.pbtxt | 14 - .../api/golden/v2/tensorflow.train.pbtxt | 126 +- .../tools/api/tests/api_compatibility_test.py | 9 +- ...Dockerfile.rbe.cuda10.0-cudnn7-ubuntu14.04 | 75 + .../tools/ci_build/builds/libtensorflow.sh | 1 + .../windows/cpu/pip/build_tf_windows.sh | 31 +- .../windows/gpu/pip/build_tf_windows.sh | 26 +- tensorflow/tools/compatibility/BUILD | 46 +- tensorflow/tools/compatibility/README.md | 63 +- tensorflow/tools/compatibility/ast_edits.py | 60 +- .../tools/compatibility/ast_edits_test.py | 420 + tensorflow/tools/compatibility/renames_v2.py | 303 +- .../compatibility/testdata/test_file_v1_12.py | 71 + .../tools/compatibility/tf_upgrade_v2.py | 893 +- .../tools/compatibility/tf_upgrade_v2_main.py | 104 + .../tools/compatibility/tf_upgrade_v2_test.py | 369 +- tensorflow/tools/compatibility/update/BUILD | 1 + .../update/generate_v2_renames_map.py | 92 +- tensorflow/tools/docker/Dockerfile | 4 +- tensorflow/tools/docker/Dockerfile.devel | 4 +- tensorflow/tools/docker/Dockerfile.devel-mkl | 4 +- .../tools/docker/Dockerfile.devel-mkl-horovod | 4 +- tensorflow/tools/docker/Dockerfile.mkl | 4 +- .../tools/docker/Dockerfile.mkl-horovod | 4 +- tensorflow/tools/dockerfiles/.gitignore | 1 + tensorflow/tools/dockerfiles/README.md | 49 +- tensorflow/tools/dockerfiles/assembler.py | 887 +- .../dockerfiles/cpu-devel-jupyter.Dockerfile | 64 +- .../dockerfiles/cpu-devel.Dockerfile | 46 +- .../dockerfiles/cpu-jupyter.Dockerfile | 53 +- .../dockerfiles/dockerfiles/cpu.Dockerfile | 35 +- ...ockerfile => gpu-devel-jupyter.Dockerfile} | 76 +- ...-devel.Dockerfile => gpu-devel.Dockerfile} | 58 +- ...yter.Dockerfile => gpu-jupyter.Dockerfile} | 62 +- .../{nvidia.Dockerfile => gpu.Dockerfile} | 44 +- .../partials/jupyter.partial.Dockerfile | 16 +- .../partials/tensorflow.partial.Dockerfile | 7 +- .../partials/test-import.partial.Dockerfile | 0 .../partials/ubuntu.partial.Dockerfile | 2 - .../{ => ubuntu}/bazel.partial.Dockerfile | 14 + .../cpu-devel.partial.Dockerfile} | 7 +- .../partials/ubuntu/cpu.partial.Dockerfile | 1 + .../nvidia-devel.partial.Dockerfile | 18 +- .../{ => ubuntu}/nvidia.partial.Dockerfile | 8 +- .../{ => ubuntu}/python.partial.Dockerfile | 5 +- .../ubuntu/test-devel.partial.Dockerfile | 0 .../ubuntu/version.partial.Dockerfile | 1 + .../tools/dockerfiles/readme-for-jupyter.md | 3 + tensorflow/tools/dockerfiles/spec.yml | 320 +- .../tools/dockerfiles/tests/build-cpu.sh | 37 + .../tools/dockerfiles/tests/build-gpu.sh | 36 + .../tools/dockerfiles/tests/import-gpu.sh | 18 + tensorflow/tools/dockerfiles/tests/import.sh | 19 + ...{assembler.Dockerfile => tools.Dockerfile} | 5 +- tensorflow/tools/docs/BUILD | 25 +- tensorflow/tools/docs/generate2.py | 82 + .../docs/generate2_test.py} | 29 +- tensorflow/tools/docs/generate_1_0.py | 92 - tensorflow/tools/docs/parser.py | 2 +- tensorflow/tools/lib_package/BUILD | 2 + tensorflow/tools/pip_package/BUILD | 12 +- tensorflow/tools/pip_package/setup.py | 4 +- tensorflow/workspace.bzl | 73 +- .../clang_toolchain/download_clang.bzl | 8 +- third_party/eigen_reshaped.patch | 48 - third_party/googleapis.BUILD | 14 +- third_party/gpus/crosstool/CROSSTOOL.tpl | 3 +- third_party/gpus/cuda_configure.bzl | 9 + third_party/gpus/rocm_configure.bzl | 2 +- third_party/icu/data/BUILD.bazel | 46 + third_party/icu/data/LICENSE | 414 + .../icu/data/icu_conversion_data.c.gz.aa | Bin 0 -> 177696 bytes .../icu/data/icu_conversion_data.c.gz.ab | Bin 0 -> 177696 bytes .../icu/data/icu_conversion_data.c.gz.ac | Bin 0 -> 177696 bytes .../icu/data/icu_conversion_data.c.gz.ad | Bin 0 -> 177696 bytes .../icu/data/icu_conversion_data.c.gz.ae | Bin 0 -> 177696 bytes .../icu/data/icu_conversion_data.c.gz.af | Bin 0 -> 177696 bytes .../icu/data/icu_conversion_data.c.gz.ag | Bin 0 -> 177696 bytes .../icu/data/icu_conversion_data.c.gz.ah | Bin 0 -> 177696 bytes .../icu/data/icu_conversion_data.c.gz.ai | Bin 0 -> 177696 bytes .../icu/data/icu_conversion_data.c.gz.aj | Bin 0 -> 177689 bytes third_party/icu/udata.patch | 53 + third_party/icu/workspace.bzl | 6 + third_party/libxsmm.BUILD | 2 +- third_party/llvm/llvm.autogenerated.BUILD | 2 + third_party/llvm/llvm.bzl | 1 + third_party/mkl_dnn/mkldnn.BUILD | 2 +- third_party/nccl/archive.BUILD | 26 +- third_party/ngraph/ngraph.BUILD | 26 +- third_party/ngraph/ngraph_tf.BUILD | 40 +- third_party/ngraph/tbb.BUILD | 10 +- third_party/png.BUILD | 2 +- third_party/repo.bzl | 4 +- third_party/toolchains/BUILD | 13 + .../preconfig/generate/containers.bzl | 2 +- .../ubuntu14.04/cuda10.0-cudnn7/WORKSPACE | 2 + .../ubuntu14.04/cuda10.0-cudnn7/cuda/BUILD | 1275 + .../cuda10.0-cudnn7/cuda/build_defs.bzl | 31 + .../cuda10.0-cudnn7/cuda/cuda/cuda_config.h | 26 + .../ubuntu14.04/cuda9.0-cudnn7/cuda/BUILD | 10 +- .../cuda9.0-cudnn7/cuda/build_defs.bzl | 6 +- .../ubuntu14.04/gcc-nvcc-cuda10.0/BUILD | 87 + .../ubuntu14.04/gcc-nvcc-cuda10.0/CROSSTOOL | 1431 + .../bin/crosstool_wrapper_driver_is_not_gcc | 264 + .../windows/msvc_wrapper_for_nvcc.bat | 20 + .../windows/msvc_wrapper_for_nvcc.py | 192 + .../ubuntu14.04/gcc-nvcc-cuda9.0/BUILD | 87 + .../ubuntu14.04/gcc-nvcc-cuda9.0/CROSSTOOL | 1431 + .../bin/crosstool_wrapper_driver_is_not_gcc | 264 + .../windows/msvc_wrapper_for_nvcc.bat | 20 + .../windows/msvc_wrapper_for_nvcc.py | 192 + .../preconfig/ubuntu14.04/py3/BUILD | 4 +- .../toolchains/preconfig/win_1803/BUILD | 2 +- tools/bazel.rc | 1 + 3376 files changed, 171721 insertions(+), 66372 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/40-tflite-op-request.md create mode 100644 tensorflow/c/kernels.cc create mode 100644 tensorflow/c/kernels.h create mode 100644 tensorflow/c/kernels_test.cc create mode 100644 tensorflow/cc/saved_model/testdata/half_plus_two_v2/00000123/assets/foo.txt create mode 100644 tensorflow/cc/saved_model/testdata/half_plus_two_v2/00000123/saved_model.pb create mode 100644 tensorflow/cc/saved_model/testdata/half_plus_two_v2/00000123/variables/variables.data-00000-of-00001 create mode 100644 tensorflow/cc/saved_model/testdata/half_plus_two_v2/00000123/variables/variables.index create mode 100644 tensorflow/compiler/jit/flags.cc rename tensorflow/compiler/jit/{legacy_flags/mark_for_compilation_pass_flags.h => flags.h} (57%) delete mode 100644 tensorflow/compiler/jit/legacy_flags/BUILD delete mode 100644 tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.cc delete mode 100644 tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.h delete mode 100644 tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.cc delete mode 100644 tensorflow/compiler/jit/legacy_flags/xla_device_flags.cc delete mode 100644 tensorflow/compiler/jit/legacy_flags/xla_device_flags.h delete mode 100644 tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.cc delete mode 100644 tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.h rename tensorflow/{contrib/estimator/python/estimator/dnn.py => compiler/jit/ops/xla_ops_grad.py} (62%) delete mode 100644 tensorflow/compiler/tf2xla/dump_graph_flags.cc delete mode 100644 tensorflow/compiler/tf2xla/dump_graph_flags.h delete mode 100644 tensorflow/compiler/tf2xla/lib/batch_dot.cc delete mode 100644 tensorflow/compiler/tf2xla/lib/batch_dot.h create mode 100644 tensorflow/compiler/xla/client/lib/matrix.cc rename tensorflow/compiler/xla/client/lib/{numeric.h => matrix.h} (56%) rename tensorflow/compiler/xla/client/lib/{numeric_test.cc => matrix_test.cc} (53%) delete mode 100644 tensorflow/compiler/xla/client/lib/numeric.cc create mode 100644 tensorflow/compiler/xla/client/lib/slicing.cc create mode 100644 tensorflow/compiler/xla/client/lib/slicing.h rename tensorflow/compiler/{tf2xla/lib/util_test.cc => xla/client/lib/slicing_test.cc} (67%) create mode 100644 tensorflow/compiler/xla/g3doc/images/xla_array_layout_figure1.png create mode 100644 tensorflow/compiler/xla/g3doc/images/xla_array_layout_figure2.png create mode 100644 tensorflow/compiler/xla/g3doc/layout_with_tiling.md create mode 100644 tensorflow/compiler/xla/service/algebraic_simplifier_proof_distributive_property.py create mode 100644 tensorflow/compiler/xla/service/ar_crs_combiner.cc create mode 100644 tensorflow/compiler/xla/service/ar_crs_combiner.h create mode 100644 tensorflow/compiler/xla/service/ar_crs_combiner_test.cc create mode 100644 tensorflow/compiler/xla/service/dynamic_parameter_binding.cc create mode 100644 tensorflow/compiler/xla/service/dynamic_parameter_binding.h create mode 100644 tensorflow/compiler/xla/service/dynamic_parameter_binding_test.cc create mode 100644 tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.cc create mode 100644 tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.h create mode 100644 tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter_test.cc create mode 100644 tensorflow/compiler/xla/service/pattern_matcher_gmock.h create mode 100644 tensorflow/compiler/xla/service/pattern_matcher_gmock_test.cc create mode 100644 tensorflow/compiler/xla/shape.cc create mode 100644 tensorflow/compiler/xla/shape.h create mode 100644 tensorflow/compiler/xla/shape_test.cc create mode 100644 tensorflow/compiler/xla/tests/conv_depthwise_test.cc create mode 100644 tensorflow/compiler/xla/tests/grouped_convolution_test.cc create mode 100644 tensorflow/compiler/xrt/xrt_util.cc create mode 100644 tensorflow/compiler/xrt/xrt_util.h create mode 100644 tensorflow/contrib/autograph/examples/benchmarks/BUILD create mode 100644 tensorflow/contrib/autograph/examples/benchmarks/benchmark_base.py create mode 100644 tensorflow/contrib/autograph/examples/benchmarks/cartpole_benchmark.py create mode 100644 tensorflow/contrib/cluster_resolver/cluster_resolver_initialization_test.py create mode 100644 tensorflow/contrib/cmake/TensorflowConfig.cmake.in create mode 100644 tensorflow/contrib/cmake/TensorflowConfigVersion.cmake.in create mode 100644 tensorflow/contrib/cmake/tf_core_eager_runtime.cmake rename tensorflow/contrib/distribute/python/{cross_tower_ops_test.py => cross_device_ops_test.py} (79%) rename tensorflow/contrib/distribute/python/{cross_tower_utils_test.py => cross_device_utils_test.py} (83%) delete mode 100644 tensorflow/contrib/distribute/python/mirrored_strategy_test.py delete mode 100644 tensorflow/contrib/estimator/python/estimator/dnn_linear_combined.py rename tensorflow/{compiler/tests/resampler_ops_test.py => contrib/resampler/xla/resampler_ops_xla_test.py} (76%) create mode 100644 tensorflow/contrib/tensorrt/test/quantization_mnist_test.py create mode 100644 tensorflow/contrib/tensorrt/test/quantization_test.py create mode 100644 tensorflow/contrib/tensorrt/test/testdata/checkpoint create mode 100644 tensorflow/contrib/tensorrt/test/testdata/model.ckpt-46900.data-00000-of-00001 create mode 100644 tensorflow/contrib/tensorrt/test/testdata/model.ckpt-46900.index delete mode 100644 tensorflow/contrib/training/python/training/tensor_queue_dataset.py delete mode 100644 tensorflow/contrib/training/python/training/tensor_queue_dataset_test.py delete mode 100644 tensorflow/core/api_def/base_api/api_def_EnqueueInQueueDataset.pbtxt rename tensorflow/core/api_def/base_api/{api_def_BytesProducedStatsDataset.pbtxt => api_def_ExperimentalBytesProducedStatsDataset.pbtxt} (56%) create mode 100644 tensorflow/core/api_def/base_api/api_def_ExperimentalDatasetCardinality.pbtxt rename tensorflow/core/api_def/base_api/{api_def_DatasetToTFRecord.pbtxt => api_def_ExperimentalDatasetToTFRecord.pbtxt} (91%) rename tensorflow/core/api_def/base_api/{api_def_DenseToSparseBatchDataset.pbtxt => api_def_ExperimentalDenseToSparseBatchDataset.pbtxt} (89%) delete mode 100644 tensorflow/core/api_def/base_api/api_def_ExperimentalFunctionBufferingResource.pbtxt delete mode 100644 tensorflow/core/api_def/base_api/api_def_ExperimentalFunctionBufferingResourceGetNext.pbtxt delete mode 100644 tensorflow/core/api_def/base_api/api_def_ExperimentalFunctionBufferingResourceReset.pbtxt rename tensorflow/core/api_def/base_api/{api_def_GroupByReducerDataset.pbtxt => api_def_ExperimentalGroupByReducerDataset.pbtxt} (97%) rename tensorflow/core/api_def/base_api/{api_def_GroupByWindowDataset.pbtxt => api_def_ExperimentalGroupByWindowDataset.pbtxt} (82%) rename tensorflow/core/api_def/base_api/{api_def_LatencyStatsDataset.pbtxt => api_def_ExperimentalLatencyStatsDataset.pbtxt} (58%) rename tensorflow/core/api_def/base_api/{api_def_MapAndBatchDatasetV2.pbtxt => api_def_ExperimentalMapAndBatchDataset.pbtxt} (96%) create mode 100644 tensorflow/core/api_def/base_api/api_def_ExperimentalMatchingFilesDataset.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_ExperimentalMaxIntraOpParallelismDataset.pbtxt rename tensorflow/core/api_def/base_api/{api_def_ParallelInterleaveDataset.pbtxt => api_def_ExperimentalParallelInterleaveDataset.pbtxt} (90%) rename tensorflow/core/api_def/base_api/{api_def_ParseExampleDataset.pbtxt => api_def_ExperimentalParseExampleDataset.pbtxt} (96%) create mode 100644 tensorflow/core/api_def/base_api/api_def_ExperimentalPrivateThreadPoolDataset.pbtxt rename tensorflow/core/api_def/base_api/{api_def_RandomDataset.pbtxt => api_def_ExperimentalRandomDataset.pbtxt} (86%) rename tensorflow/core/api_def/base_api/{api_def_ScanDataset.pbtxt => api_def_ExperimentalScanDataset.pbtxt} (61%) create mode 100644 tensorflow/core/api_def/base_api/api_def_ExperimentalSetStatsAggregatorDataset.pbtxt rename tensorflow/core/api_def/base_api/{api_def_SlideDataset.pbtxt => api_def_ExperimentalSlidingWindowDataset.pbtxt} (88%) rename tensorflow/core/api_def/base_api/{api_def_SqlDataset.pbtxt => api_def_ExperimentalSqlDataset.pbtxt} (87%) create mode 100644 tensorflow/core/api_def/base_api/api_def_ExperimentalStatsAggregatorHandle.pbtxt rename tensorflow/core/api_def/base_api/{api_def_StatsAggregatorSummary.pbtxt => api_def_ExperimentalStatsAggregatorSummary.pbtxt} (56%) rename tensorflow/core/api_def/base_api/{api_def_UnbatchDataset.pbtxt => api_def_ExperimentalUnbatchDataset.pbtxt} (57%) delete mode 100644 tensorflow/core/api_def/base_api/api_def_MapAndBatchDataset.pbtxt delete mode 100644 tensorflow/core/api_def/base_api/api_def_MatchingFilesDataset.pbtxt delete mode 100644 tensorflow/core/api_def/base_api/api_def_PrependFromQueueAndPaddedBatchDataset.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_ResourceApplyAdamWithAmsgrad.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_ResourceApplyKerasMomentum.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_ResourceSparseApplyKerasMomentum.pbtxt delete mode 100644 tensorflow/core/api_def/base_api/api_def_SetStatsAggregatorDataset.pbtxt delete mode 100644 tensorflow/core/api_def/base_api/api_def_StatsAggregatorHandle.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorForestCreateTreeVariable.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorForestTreeDeserialize.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorForestTreeIsInitializedOp.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorForestTreePredict.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorForestTreeResourceHandleOp.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorForestTreeSerialize.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorForestTreeSize.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorListConcat.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorListSplit.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorScatterAdd.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorScatterSub.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_TensorScatterUpdate.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_UnicodeDecodeWithOffsets.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_UnicodeEncode.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_BatchDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_BytesProducedStatsDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_CacheDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_ConcatenateDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_DatasetToSingleElement.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_DenseToSparseBatchDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_EnqueueInQueueDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_FilterDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_FixedLengthRecordDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_FixedLengthRecordDatasetV2.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_FlatMapDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_GeneratorDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_GroupByWindowDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_InterleaveDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_LatencyStatsDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_MapAndBatchDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_MapDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_PaddedBatchDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_ParallelInterleaveDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_ParallelMapDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_ParseExampleDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_PrefetchDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_PrependFromQueueAndPaddedBatchDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_RandomDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_RangeDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_RepeatDataset.pbtxt create mode 100644 tensorflow/core/api_def/python_api/api_def_ResourceApplyAdamWithAmsgrad.pbtxt create mode 100644 tensorflow/core/api_def/python_api/api_def_ResourceApplyKerasMomentum.pbtxt create mode 100644 tensorflow/core/api_def/python_api/api_def_ResourceSparseApplyKerasMomentum.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_ScanDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_SetStatsAggregatorDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_ShuffleAndRepeatDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_ShuffleDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_SkipDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_SlideDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_SparseTensorSliceDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_SqlDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_StatsAggregatorHandle.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_StatsAggregatorSummary.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_TFRecordDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_TakeDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_TensorDataset.pbtxt create mode 100644 tensorflow/core/api_def/python_api/api_def_TensorListConcat.pbtxt rename tensorflow/core/api_def/python_api/{api_defTensorListPushBackBatch.pbtxt => api_def_TensorListPushBackBatch.pbtxt} (100%) create mode 100644 tensorflow/core/api_def/python_api/api_def_TensorListSplit.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_TensorSliceDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_TextLineDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_UnbatchDataset.pbtxt delete mode 100644 tensorflow/core/api_def/python_api/api_def_ZipDataset.pbtxt create mode 100644 tensorflow/core/distributed_runtime/server_lib_test.cc create mode 100644 tensorflow/core/framework/function_handle_cache.cc create mode 100644 tensorflow/core/framework/function_handle_cache.h delete mode 100644 tensorflow/core/grappler/optimizers/graph_rewriter.cc delete mode 100644 tensorflow/core/grappler/optimizers/graph_rewriter.h rename tensorflow/core/kernels/{conv_ops_gpu_3.cu.cc => conv_2d_gpu.h} (91%) create mode 100644 tensorflow/core/kernels/conv_2d_gpu_double.cu.cc create mode 100644 tensorflow/core/kernels/conv_2d_gpu_float.cu.cc create mode 100644 tensorflow/core/kernels/conv_2d_gpu_half.cu.cc rename tensorflow/{lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h => core/kernels/conv_2d_gpu_int.cu.cc} (54%) create mode 100644 tensorflow/core/kernels/conv_2d_gpu_uint16.cu.cc create mode 100644 tensorflow/core/kernels/conv_2d_gpu_uint32.cu.cc create mode 100644 tensorflow/core/kernels/conv_2d_gpu_uint64.cu.cc create mode 100644 tensorflow/core/kernels/conv_2d_gpu_uint8.cu.cc create mode 100644 tensorflow/core/kernels/conv_ops_fused_image_transform.cc rename tensorflow/core/kernels/data/{ => experimental}/dense_to_sparse_batch_dataset_op.cc (97%) rename tensorflow/core/kernels/data/{ => experimental}/group_by_reducer_dataset_op.cc (93%) rename tensorflow/core/kernels/data/{ => experimental}/group_by_window_dataset_op.cc (95%) delete mode 100644 tensorflow/core/kernels/data/experimental/identity_indexed_dataset.cc delete mode 100644 tensorflow/core/kernels/data/experimental/indexed_dataset.h rename tensorflow/core/kernels/data/experimental/{indexed_dataset.cc => indexed_dataset_op.cc} (62%) rename tensorflow/core/kernels/data/{ => experimental}/map_and_batch_dataset_op.cc (90%) rename tensorflow/core/kernels/data/{ => experimental}/matching_files_dataset_op.cc (99%) create mode 100644 tensorflow/core/kernels/data/experimental/parallel_interleave_dataset_op.cc rename tensorflow/core/kernels/data/{ => experimental}/parse_example_dataset_op.cc (85%) rename tensorflow/core/kernels/data/{ => experimental}/random_dataset_op.cc (97%) rename tensorflow/core/kernels/data/{ => experimental}/scan_dataset_op.cc (94%) rename tensorflow/core/kernels/data/{stats_aggregator_dataset_op.cc => experimental/set_stats_aggregator_dataset_op.cc} (97%) rename tensorflow/core/kernels/data/{slide_dataset_op.cc => experimental/sliding_window_dataset_op.cc} (95%) rename tensorflow/core/kernels/data/{ => experimental}/sql/BUILD (100%) rename tensorflow/core/kernels/data/{ => experimental}/sql/driver_manager.cc (88%) rename tensorflow/core/kernels/data/{ => experimental}/sql/driver_manager.h (81%) rename tensorflow/core/kernels/data/{ => experimental}/sql/query_connection.h (92%) rename tensorflow/core/kernels/data/{ => experimental}/sql/sqlite_query_connection.cc (97%) rename tensorflow/core/kernels/data/{ => experimental}/sql/sqlite_query_connection.h (84%) rename tensorflow/core/kernels/data/{sql_dataset_ops.cc => experimental/sql_dataset_op.cc} (96%) rename tensorflow/core/kernels/data/{ => experimental}/stats_aggregator_ops.cc (95%) rename tensorflow/core/kernels/data/{ => experimental}/stats_dataset_ops.cc (95%) rename tensorflow/core/kernels/data/{writer_ops.cc => experimental/to_tf_record_op.cc} (84%) rename tensorflow/core/kernels/data/{ => experimental}/unbatch_dataset_op.cc (98%) create mode 100644 tensorflow/core/kernels/data/optional_ops.cu.cc delete mode 100644 tensorflow/core/kernels/data/tensor_queue_dataset_op.cc create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/012e3ad384a4a1165f8498b5c94ba0d32a73e187 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/055d77f7810048caa28323f6eb552a53d156040b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/131e251bfb82c681cb075d32b99f18fceaca115d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/1399ab0bd9f2c91d270cb43251bdc5729bef3526 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/16a6ce88f66d2e9686c8354cad8ba915cf0c11de create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/185097ed0588195164619ea930ddd8274a5f32ad create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/27711a87e06a50c81571c27c3aa403a6ad5dc55c create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/298c3787ad1722b22569cbc405c464d2 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/2b95ba6d8141ce0d29ff279770903922 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/321fb3d758b86e37fc340ae2b09b8ed9fa73a4cb create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/331a98b4e4c87840efea69223766ebd0e1736542 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/352d73f841223ecb630b5836585d2ba7b0f9d883 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/3a84f409d4c117edfdebc508cd23e8fc create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/3ef5cc982c0b45f69a26fd0f7d376415fdebabd1 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/401c7de8e122018a0e17f57c93db7ee49ab0e906 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/52fee71bb8c9c79068e1fe580677ad739a2d0415 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/57b11507813d5727b7789354d888eda83d5f3d86 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/57dff0fa53ee0ef24a43cca6ab0523bfdc1f720d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/5c42d3df0dc400a7a4175b8d4eec6cc8ee2437b2 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/5cca20637ae75fddad9370ee930837baef8aeb43 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/5d34bc9cef0c844b9c5ebe948145c4ca11b5ca09 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/5e162fe883bd12fb1c4131d4e0c979a12bd15eac create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/5e83f8faab9c1a51a33d5e29edbb9dcec23c6092 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/61b29dc2fcef7b6fbe3e0cc88769a7ef create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/6361eca190157ece389665ee523ccc3aefcd957f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/65150515ab3b11d657519b22bb887d74e94b2d7f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/656f38ef6dcd58c6a909d61db11f777def69c394 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/66e0d2cafd592bf9d61ad900fade8ee530d5f3d7 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/6b5b42cb105a2c4c5fd6034e9885cbe457f1b50c create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/722ed0197cb92ecbf9745edb38275e7a9aaf322f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/77bdd2efdf328366cbbf3c5688768dc0a88d02b1 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/7841bfa002c05c61d5a5d9241f214cc17a336166 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/7899e22fc83f6be28e9130c4a1c91a48 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/7dddccaebd16ae0c26daeffc42df50f529891119 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/8157442eee4bbfdd9716e264b11085d61a9955b7 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/81ff28ed63d5435ddc4c8771dd5d40aa658cbbe0 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/820c8c0d33c18f6c4d9edd314e91289186931ad0 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/849e9d7cee1c52105242327086997296e452b981 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/84ddb92c63e0fad7018f6069daf8779ce11501e2 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/86bc3d5dbb9313137502080e58551edd2e649c70 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/87d94d88fe29d277c76e1a52042b02c092d5ae14 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/8c4646f3357945c4e19a59ff79fffe3c874dbf16 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/90632bc6dee4eb836f3d7db1d16446a9c8510080 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/94d06016aa949e8e7203217e4cc6625ded7f4244 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/9875819b9e5783e7489c29a81cc9d4279209956a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/9c1cc734114b29aac6c51782d5c17e9dbe1faca2 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/9d2961871eeb201ef8a6f5503d8a8b62 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/9f39e11cdd88344a4894b678e5a04a810880064d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/a350588a6dabe4376a066aed44ef8786d8e752e7 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/a6101a79919d444e1fc50aefab5837c39e3f4a19 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/a9c8793f8fb063bec839ee1280406fe5396545e5 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/ad4e9d2234e8599bdf12607c6b8cab4edae82c4e create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/b90b6830917919e94186d312f06481bd create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/b98fd4cb1d7031240414301c19b03097c0035c6b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/ba976fcdb4daf092ef17ce43bf2b78d9d8bc2aeb create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/bc112b571eafee0f5a031f3c9cce6244216d128d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/c42b981c28a1715c375050f6fcf53f1d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/c6049874b33eadb016fccf0c5fa66e556ae069b9 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/c8697bf2369f6ab85f501376c4d93bb8a56974a3 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/c8daf283e0aef2fd7b630c0430e05dc28f24ecf6 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/cacff56e1af4b8fde912822da06b10fb8c545a19 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/ce4dcc22b1d595c49a25121c0b580104 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/d0cd71dbf039fd64cf42eff30da92a71a919226a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/d5ce626ac3264bed6af5580e341a89406857cbb9 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/d77ada02e9bc8c24b2711eca6a8f52ae356bfc21 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/d7eb9c5a0f9803df4c00390793b8ab57bd7c9484 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/dc1efccdeec17e151a1ec8228c09ab61c3040b33 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/dcea22c66c60088165a2f1772036473f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/de539ae7442fa05dafcfe1a021f0186ef74a2b0e create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/e2306b1d6b88d0ccc4e2c3a9edb07462a5a32215 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/e2778da0240fdd15ef5844905d81c4e05f34a8bd create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/e6642e9266875f9d908942e534bf898103a2c794 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/ec6cdb929c08d8daf2bd7fc185fbf4d787b45120 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/ed8636357f79439b6a03eb14469b686cc401a1c9 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/ee313e9acecb5c688ce8c9bb10e70e136fbb9c6d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/ef689af320e7d9e22231109faae2e8149cb86e1c create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/fda6b9a9f6ffdf4765c00465619c7ceb3f7db2e4 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_bmp/ffe829bb0adac20d9c0756f68a22d1255e4fdb54 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/013a29ea098a178f8a36741c9fd91144 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/0875575fb76d630ccb19c5da8aab66b2 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/7e7f58fc443a11a0a2c5d9b643b7e99b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/849a23936269a261c0370b5e9abe2416 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/85282c1696d98b9843ce3e8bd1cd899f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/90388b9c8093d8adedad0644b618da87 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/9fa2f86ea6d3ade36e961247c3026f8d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/c4f18ca60a84e9869a28faf6f65dc758 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/d456ee029700adef5d28438593010223 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_json_example/e9f0ff6ee8d691ae69d2ecb4710030a2 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/010dc3d4b05288fcc40de2721052b3dc699f1cb3 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/0555cd5e9d99629819cc985285f80da0f00be1e9 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/0a0352aa168803ff65455792d9f6ee555c3e7c3f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/0ed54162df93ef8d00f993ce6b59ba422903d381 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/1547b448171c700613c3946d730de496c9b9863f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/17859046cbe4ac598a645173d679ce2a52c6afba create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/1df76c07817fbc3653a26f34d97658e9973627c2 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/1f0717f8856d7782e3ab7992d3a72d783a018443 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/23b911e4ce936def88bc9a46b8b433c0e83fba2a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/25592201c3edff0578dbdac6b0e4f2be109ce151 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/266fd8495e0b8eb64387c1a62264185e061fee73 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/27f178cf415b4ff8671131ddf1d042dafac2fb3e create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/2a0bdc4d9cc5ea5bb21dd256d6ac96075376a94f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/2e5d25add6adc68e0457b358c7a34abf3d41c938 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/2e6c5b6a766dd5e9bd41eacfd0a36572bd2f7544 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/2e9c935cf82f6ca640e9a9abc3c30a578ad46176 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/2fcf1ed4477f7eaee028f5b3f9edeb5f1a737826 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/3480713774f590908ca5dba16d121cdfb8fba62b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/39289afcec60d98802b333e0fbb1da4d7aed4ce5 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/3adc488e21d4aca7bed9422f0241a42d0f93e7d9 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/3cbf274da522483dc991fad9df43a22ac4fb3173 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/3d840cdff7f5ad16fe8bcb985ed4946c03459432 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/3f1e6753c1fca958e859189857449746592158ea create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/3fa4075993cb0f9bfa8eea785174a2038a69aa1b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/4023a373e977be58413e55350380310c5dd1fd6a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/40caba69dce1cfc48e0e43184d2bfbc6daa4399a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/41841e9561d8135945c1c1e55ab9e9a1e933653b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/41d40f2d66fa43e34537385594ee9911e65deadf create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/421bd39810b50309a71adb2dadc3b19f01a52312 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/446c305b2c0665736f94fb2b62dbdef445eff0cf create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/449cee952bb645f6f4241a6665d3c6028c073c7a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/45520b07609978c5aa3516d803527438b93fbadb create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/4da74a34bcede234b0415f77fbd87d70bf9a777e create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/51db5d31d2c5300d34831d9f23bcdd0aff9a998b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/5cde2a9167798cb77f10abbfb2640a5c357f99fc create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/5e352fc10ac476cfbe1d755f092e069820223249 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/63661677dd1306cec4b5a565190e65adf2446e52 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/65887ed3db382aab1d9485c500f4401318d303b9 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/67b5181f8f0644597e9bde539e8f083b5cacd0e7 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/74c9dcf7afee2a6cb1ab3a2c0de744d1b03c1466 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/792181ca19e6ded261434e588bb7fc2a4816d4ce create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/79f0e2a475487f8fa69e68c1cc947c5851bda741 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/7e5fcdfeb557ce379ed96925c68505eaac0112db create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/7eec7530acf34b3a96fa9189783453999f7b6838 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/80114bf9781bffc9db411413d83541d8deaaf7c1 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/80425fb92bb86627e854892f23823fa804e5fdc3 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/821cdd6eeb919a8dd7f35289abbd583828dd4945 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/83e1a31785285338b0ddb3334b0ed098e63dedde create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/8a4c8100dedd0fb5f2a8b468c678f7ad8269deeb create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/8ae8268c24dc866c1edb3826b93a1c75dbf74ff4 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/90f72038cc627f34f074ea72eadbba87a5e3e288 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/92b67faee4a49df2cdbed785e27b4a1cddcfffa3 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/9463810467aacdc9923b2b20a2236116b760d75b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/94d7c96aea32ad41ce643d35b951a6d8990b81d6 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/98cc7e9fe87df914d89a0aef008930f27b3c26f5 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/99172dfdb4f59aaced29c7681ac6e6ce8356e814 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/9ae3b647d895af97fe872c0b1442df7b5b767160 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/9d2b1d2121b0508a4fa8d1508adb9d05633fdac3 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/a335af37917ccf0c8b11bb884a3a74f3f1d2a7c6 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/a738609112d3a6772c50a71e2c3504ebc515b709 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/a8cecab5d917da5a4729632a7a18c564d7e1607d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/ade919ab2b4a458e806575c941dfe50ae3fd3621 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/b1251621a5eb5e7fda9cac9baead1c993a285c36 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/b1516b78c3dfe77eeb554985fd7344c0478fbbcb create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/b41241740f5f8ad2c1d408f7bb6a313bd863c158 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/b799c8596523a7ebeb8e11ada08818c10f7eabfc create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/ba48d0521a111222dc95a3a997c7c92dea5f4443 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/c01457c6889fb1b597d308363a36412c0b7f90e7 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/c82ebc0d6688d104af04fd20d6d3da591dc391f7 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/c9a03eb758dd84e954e3d70916e2311e8fd21f3c create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/cf892756b33578a54ab20044514e573328d2f1d7 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/d3bc3f158a63f1d50b474addd3f7b3d17f23e8e9 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/d4906950aa9d60ad09dc0f5413c3d88080c3bc37 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/da31578a8068bad65e1c7a3d06e8f543a2a0bc65 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/dd4a9b5d0740679c249fc884efc499433b29436b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/deea4ecc6f0b2a6d89fd25ff76762299f21602fb create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/e1040c7ffcb39915e0f539018c81f9798924cba6 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/e381dc85682cc33ad99f622b89d145b47f7d6392 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/ea24498fc7a144fccc6f1665ebf7020df803dd1a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/eaa5d677e797c07bac98c3c7051abad91852e7c6 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/ed7871269315725535d8bffec7836c45a3fc5c26 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/ee8460f4077064c5a2137075b48eba7d3db5c570 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/ef09f26e0ee61329f84a9f589629a865ae9ee0a6 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/f477da4d7d8ff2066041e1dd5ee4e833b7111a1a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/f8a379b2498a4eb452a85791a49adf065dab59ae create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/fe67bccb06f2174523943cc684518fcf1f7f8046 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_png/ff1e67d17c1c27ef0d97900d0ea276b563a64628 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/02cc44cdfec1d9d0d0c66c5a5f40d3d20e4c4c3a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/087e1d7fae1c1ddcbaa3b5f822a171ad15498186 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/0f61c33027394a0f14d29dcd22f405cad943b7cf create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/10cdebea1659c21a0248f88654ae41f62786abf1 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/126e68def9fd973a100e0f66cadf09448a716b57 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/1275d41ebf8788ce3a949352e4bc654b04012da3 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/1a7f1c407fb3864ddb559f88f373a21d1be51584 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/1c3e1c91f187f6bcea86f172ff5bbbd955a9654d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/300fe1e0a47543037cbf0243b6756c9aa48799c4 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/31ec5b0134bedcfe283f4978e6e65b7d35d5d4ad create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/4e7cbb27667bcfca92838aa8020749990013a9b1 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/585e469231d202812bfba8285fb30c8e31c857b9 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/58eab6bc2386e2ef43fe4f55cb6ad3611399d5de create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/63448c6a9feb8c72b3e82af4d735ec2e62ddd328 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/6874d5b1c7a64b596c61f24877d422e89bebe58b create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/7501f79cb067da108020579ed654349c7933d22f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/782051f8120182b860c7fe1b265179cfa2fe03fd create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/793feab2deb35e284a975f6527d76a8be5540fe6 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/7f41ec3a9805c6b8f3656c4f9f6d0ff7dbf8a329 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/8210dc595a2652f2f812093b01e239e7918ea065 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/8dffe4c5c26d891b578fd2ea4b9adfc0c96ad5f7 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/91d787a9298ddc015efa783a92c4bdba8af0d7de create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/92c065286f956f086e977556358f6b54b12bcacc create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/a35c9bb71792b60a13dea23a41b41847ad4b93d6 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/a6ea960c7b4d42772888280277b26e645ceee904 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/aa526aa853333f0bb11804b5243df411452cecd2 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/ca533cd26c7ca6bf69e62351b265ded496fdf1d9 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/f38c61da15f2cb7a39ff02e69f0b00e99f37ec86 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/f88f1012473e6cfcc9b39b2552f682b2f73eff8c create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/fa79819c5de04bc06c69bec3fa7f2e982826ea2f create mode 100644 tensorflow/core/kernels/fuzzing/corpus/decode_wav/fce08de222896ac3a20657a3b4f42d5b6c54a96a create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split/4c01a1504da9de2216894743ecc44424 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split/5bf16424630b5afbcffe711fb9834440 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split/a7185605aef0a8fd682fcb4656e4a736 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split/d5606def44fdbb9385dd764612069db0 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split/dbac766f3160de65894bf5153f478146 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split/e85ff62f6d457666f54a37a19a115a24 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split_v2/00fd47bf73afcb72e7ed51bffd5f5fec create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split_v2/14908973e6720513a5f37676cb9fcc29 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split_v2/2779ba7c4d23eee9f79efa3660084c5d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split_v2/5bf16424630b5afbcffe711fb9834440 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split_v2/89734a96b93275e495a9498b806fafe1 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_split_v2/d5606def44fdbb9385dd764612069db0 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/2db83ea58639b6d7d585fa12e3947a82 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/36b4a931886b941dc41180050d12ca94 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/50a2fabfdd276f573ff97ace8b11c5f4 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/62edb2a1eee34b001652cd86584becf2 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/90013d1ec28c46a5c00574e60c70b6fc create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/94f3e3cee6957ce5815326d6788c85f4 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/96f547bc04bb913da0bc08915238ebd8 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/d3a903d18fc11e1f35c572ad4da690ed create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/e3b629c92af44260c189deb32d6f06f3 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/f03eecf3bcfe4967a1888156a3115c8d create mode 100644 tensorflow/core/kernels/fuzzing/corpus/string_to_number/fa54ca9186f77122ae2a82684a062e16 create mode 100644 tensorflow/core/kernels/fuzzing/dictionaries/decode_json_example.dict create mode 100644 tensorflow/core/kernels/fuzzing/dictionaries/decode_png.dict create mode 100644 tensorflow/core/kernels/fuzzing/dictionaries/decode_wav.dict create mode 100644 tensorflow/core/kernels/mkl_quantized_pooling_ops_test.cc create mode 100644 tensorflow/core/kernels/scan_ops_test.cc create mode 100644 tensorflow/core/kernels/tensor_forest/BUILD create mode 100644 tensorflow/core/kernels/tensor_forest/prediction_ops.cc create mode 100644 tensorflow/core/kernels/tensor_forest/resource_ops.cc create mode 100644 tensorflow/core/kernels/tensor_forest/resources.cc create mode 100644 tensorflow/core/kernels/tensor_forest/resources.h create mode 100644 tensorflow/core/ops/tensor_forest_ops.cc create mode 100644 tensorflow/core/platform/default/logger.cc create mode 100644 tensorflow/core/platform/logger.h create mode 100644 tensorflow/core/platform/platform_strings.cc create mode 100644 tensorflow/core/platform/platform_strings.h create mode 100644 tensorflow/core/platform/platform_strings_computed.h create mode 100644 tensorflow/core/platform/platform_strings_test.cc create mode 100644 tensorflow/core/util/dump_graph.cc create mode 100644 tensorflow/core/util/dump_graph.h create mode 100644 tensorflow/core/util/dump_graph_test.cc create mode 100644 tensorflow/core/util/permutation_output_iterator.h create mode 100644 tensorflow/core/util/tensor_ops_util.h create mode 100644 tensorflow/go/op/gradients.go create mode 100644 tensorflow/go/op/gradients_test.go create mode 100644 tensorflow/lite/core/subgraph.cc create mode 100644 tensorflow/lite/core/subgraph.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/.gitignore create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/README.md create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.c create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h create mode 100755 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/create_constants.py delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/.gitignore create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md rename tensorflow/lite/experimental/micro/{tools/make/targets/apollo3evb => examples/micro_speech/apollo3}/_main.c (100%) create mode 100755 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/captured_data_to_wav.py create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/compare_1k.py create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_micro_test.cmd create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_test.cmd create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc create mode 100755 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c create mode 100755 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_test.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/main.cc rename tensorflow/lite/experimental/micro/examples/micro_speech/{CMSIS/no_power_spectrum_data.cc => model_settings.cc} (73%) create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h rename tensorflow/lite/experimental/micro/examples/micro_speech/{CMSIS/yes_power_spectrum_data.cc => timer.cc} (73%) create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/timer.h create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/timer_test.cc delete mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md delete mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/get_yesno_data.cmd delete mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/preprocessor_test.cmd delete mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/replace_calculated_data.py delete mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc create mode 100644 tensorflow/lite/g3doc/using_select_tf_ops.md create mode 100644 tensorflow/lite/java/src/testdata/string.bin create mode 100644 tensorflow/lite/kernels/fill.cc create mode 100644 tensorflow/lite/kernels/fill_test.cc delete mode 100644 tensorflow/lite/kernels/internal/optimized/cblas_conv.h delete mode 100644 tensorflow/lite/kernels/internal/optimized/cblas_reference.h create mode 100644 tensorflow/lite/kernels/mirror_pad.cc create mode 100644 tensorflow/lite/kernels/mirror_pad_test.cc create mode 100644 tensorflow/lite/kernels/split_v.cc create mode 100644 tensorflow/lite/kernels/split_v_test.cc create mode 100644 tensorflow/lite/kernels/squared_difference.cc create mode 100644 tensorflow/lite/kernels/squared_difference_test.cc create mode 100644 tensorflow/lite/toco/toco_convert.cc create mode 100644 tensorflow/lite/toco/toco_convert.h create mode 100644 tensorflow/lite/toco/toco_convert_test.cc create mode 100644 tensorflow/lite/tools/pip_package/MANIFEST.in create mode 100644 tensorflow/lite/tools/pip_package/README.md create mode 100644 tensorflow/lite/tools/pip_package/build_pip_package.sh create mode 100644 tensorflow/lite/tools/pip_package/setup.py create mode 100644 tensorflow/opensource_only.files create mode 100644 tensorflow/python/data/benchmarks/batch_benchmark.py create mode 100644 tensorflow/python/data/benchmarks/filter_benchmark.py create mode 100644 tensorflow/python/data/benchmarks/from_tensor_slices_benchmark.py create mode 100644 tensorflow/python/data/benchmarks/map_benchmark.py create mode 100644 tensorflow/python/data/experimental/benchmarks/autotune_benchmark.py create mode 100644 tensorflow/python/data/experimental/benchmarks/csv_dataset_benchmark.py delete mode 100644 tensorflow/python/data/experimental/benchmarks/map_benchmark.py create mode 100644 tensorflow/python/data/experimental/benchmarks/map_vectorization_benchmark.py create mode 100644 tensorflow/python/data/experimental/benchmarks/matching_files_benchmark.py create mode 100644 tensorflow/python/data/experimental/benchmarks/optimize_benchmark.py create mode 100644 tensorflow/python/data/experimental/benchmarks/unbatch_benchmark.py delete mode 100644 tensorflow/python/data/experimental/kernel_tests/batch_dataset_op_test.py create mode 100644 tensorflow/python/data/experimental/kernel_tests/cardinality_test.py delete mode 100644 tensorflow/python/data/experimental/kernel_tests/function_buffering_resource_test.py rename tensorflow/python/data/{kernel_tests/matching_files_dataset_op_test.py => experimental/kernel_tests/matching_files_test.py} (57%) create mode 100644 tensorflow/python/data/experimental/ops/cardinality.py create mode 100644 tensorflow/python/data/experimental/ops/filter_for_shard_ops.py create mode 100644 tensorflow/python/data/experimental/ops/matching_files.py create mode 100644 tensorflow/python/data/experimental/ops/optimization_options.py create mode 100644 tensorflow/python/data/experimental/ops/threading_options.py delete mode 100644 tensorflow/python/data/kernel_tests/batch_dataset_op_test.py create mode 100644 tensorflow/python/data/kernel_tests/batch_test.py delete mode 100644 tensorflow/python/data/kernel_tests/cache_dataset_op_test.py create mode 100644 tensorflow/python/data/kernel_tests/cache_test.py rename tensorflow/python/data/kernel_tests/{concatenate_dataset_op_test.py => concatenate_test.py} (75%) rename tensorflow/python/data/kernel_tests/{range_dataset_op_test.py => dataset_checkpoint_test.py} (84%) delete mode 100644 tensorflow/python/data/kernel_tests/dataset_constructor_op_test.py rename tensorflow/python/data/kernel_tests/{dataset_ops_test.py => dataset_test.py} (69%) delete mode 100644 tensorflow/python/data/kernel_tests/filter_dataset_op_test.py create mode 100644 tensorflow/python/data/kernel_tests/filter_test.py create mode 100644 tensorflow/python/data/kernel_tests/fixed_length_record_dataset_test.py rename tensorflow/python/data/kernel_tests/{flat_map_dataset_op_test.py => flat_map_test.py} (57%) rename tensorflow/python/data/kernel_tests/{dataset_from_generator_op_test.py => from_generator_test.py} (85%) create mode 100644 tensorflow/python/data/kernel_tests/from_sparse_tensor_slices_test.py create mode 100644 tensorflow/python/data/kernel_tests/from_tensor_slices_test.py create mode 100644 tensorflow/python/data/kernel_tests/from_tensors_test.py delete mode 100644 tensorflow/python/data/kernel_tests/inputs_test.py rename tensorflow/python/data/kernel_tests/{interleave_dataset_op_test.py => interleave_test.py} (85%) create mode 100644 tensorflow/python/data/kernel_tests/iterator_checkpoint_test.py rename tensorflow/python/data/kernel_tests/{iterator_ops_cluster_test.py => iterator_cluster_test.py} (96%) rename tensorflow/python/data/kernel_tests/{iterator_ops_test.py => iterator_test.py} (83%) delete mode 100644 tensorflow/python/data/kernel_tests/list_files_dataset_op_test.py create mode 100644 tensorflow/python/data/kernel_tests/list_files_test.py rename tensorflow/python/data/kernel_tests/{map_dataset_op_test.py => map_test.py} (80%) rename tensorflow/python/data/kernel_tests/{optional_ops_test.py => optional_test.py} (64%) create mode 100644 tensorflow/python/data/kernel_tests/padded_batch_test.py rename tensorflow/python/data/kernel_tests/{prefetch_dataset_op_test.py => prefetch_test.py} (52%) create mode 100644 tensorflow/python/data/kernel_tests/range_test.py delete mode 100644 tensorflow/python/data/kernel_tests/reader_dataset_ops_test.py rename tensorflow/python/data/kernel_tests/{reduce_dataset_op_test.py => reduce_test.py} (72%) create mode 100644 tensorflow/python/data/kernel_tests/repeat_test.py delete mode 100644 tensorflow/python/data/kernel_tests/sequence_dataset_op_test.py rename tensorflow/python/data/kernel_tests/{shard_dataset_op_test.py => shard_test.py} (52%) delete mode 100644 tensorflow/python/data/kernel_tests/shuffle_dataset_op_test.py create mode 100644 tensorflow/python/data/kernel_tests/shuffle_test.py create mode 100644 tensorflow/python/data/kernel_tests/skip_test.py create mode 100644 tensorflow/python/data/kernel_tests/take_test.py create mode 100644 tensorflow/python/data/kernel_tests/text_line_dataset_test.py create mode 100644 tensorflow/python/data/kernel_tests/tf_record_dataset_test.py delete mode 100644 tensorflow/python/data/kernel_tests/window_dataset_op_test.py create mode 100644 tensorflow/python/data/kernel_tests/window_test.py delete mode 100644 tensorflow/python/data/kernel_tests/zip_dataset_op_test.py create mode 100644 tensorflow/python/data/kernel_tests/zip_test.py create mode 100644 tensorflow/python/data/util/options.py create mode 100644 tensorflow/python/data/util/options_test.py create mode 100644 tensorflow/python/distribute/all_reduce.py rename tensorflow/{contrib/all_reduce/python => python/distribute}/all_reduce_test.py (97%) create mode 100644 tensorflow/python/distribute/cluster_resolver/BUILD rename tensorflow/{contrib => python/distribute}/cluster_resolver/README.md (100%) rename tensorflow/{contrib/cluster_resolver/python/training => python/distribute/cluster_resolver}/README.slurm (100%) create mode 100644 tensorflow/python/distribute/cluster_resolver/__init__.py create mode 100644 tensorflow/python/distribute/cluster_resolver/cluster_resolver.py rename tensorflow/{contrib/cluster_resolver/python/training => python/distribute/cluster_resolver}/cluster_resolver_test.py (98%) create mode 100644 tensorflow/python/distribute/cluster_resolver/gce_cluster_resolver.py rename tensorflow/{contrib/cluster_resolver/python/training => python/distribute/cluster_resolver}/gce_cluster_resolver_test.py (98%) create mode 100644 tensorflow/python/distribute/cluster_resolver/kubernetes_cluster_resolver.py rename tensorflow/{contrib/cluster_resolver/python/training => python/distribute/cluster_resolver}/kubernetes_cluster_resolver_test.py (87%) create mode 100644 tensorflow/python/distribute/cluster_resolver/slurm_cluster_resolver.py rename tensorflow/{contrib/cluster_resolver/python/training => python/distribute/cluster_resolver}/slurm_cluster_resolver_test.py (85%) create mode 100644 tensorflow/python/distribute/cluster_resolver/tfconfig_cluster_resolver.py rename tensorflow/{contrib/cluster_resolver/python/training => python/distribute/cluster_resolver}/tfconfig_cluster_resolver_test.py (72%) create mode 100644 tensorflow/python/distribute/cluster_resolver/tpu_cluster_resolver.py rename tensorflow/{contrib/cluster_resolver/python/training => python/distribute/cluster_resolver}/tpu_cluster_resolver_test.py (86%) rename tensorflow/{contrib/distribute/python/cross_tower_ops.py => python/distribute/cross_device_ops.py} (86%) rename tensorflow/{contrib/distribute/python/cross_tower_utils.py => python/distribute/cross_device_utils.py} (99%) rename tensorflow/python/{training => distribute}/device_util.py (98%) rename tensorflow/python/{training => distribute}/device_util_test.py (95%) create mode 100644 tensorflow/python/distribute/distribute_lib.py rename tensorflow/python/{training/distribute_test.py => distribute/distribute_lib_test.py} (75%) create mode 100644 tensorflow/python/distribute/distribution_strategy_context.py rename tensorflow/{contrib/distribute/python => python/distribute}/input_ops.py (89%) rename tensorflow/{contrib/distribute/python => python/distribute}/input_ops_test.py (89%) create mode 100644 tensorflow/python/distribute/mirrored_strategy.py create mode 100644 tensorflow/python/distribute/reduce_util.py rename tensorflow/{contrib/distribute/python => python/distribute}/shared_variable_creator.py (100%) rename tensorflow/{contrib/distribute/python => python/distribute}/shared_variable_creator_test.py (97%) rename tensorflow/{contrib/distribute/python => python/distribute}/values.py (77%) create mode 100644 tensorflow/python/eager/execution_callbacks_test.py create mode 100644 tensorflow/python/eager/function_gradients_test.py create mode 100644 tensorflow/python/keras/engine/base_layer_utils.py create mode 100644 tensorflow/python/keras/engine/input_spec.py create mode 100644 tensorflow/python/keras/engine/training_dataset_test.py create mode 100644 tensorflow/python/keras/layers/unified_lstm_test.py create mode 100644 tensorflow/python/keras/optimizer_v2/adadelta.py create mode 100644 tensorflow/python/keras/optimizer_v2/adadelta_test.py create mode 100644 tensorflow/python/keras/optimizer_v2/adagrad.py create mode 100644 tensorflow/python/keras/optimizer_v2/adagrad_test.py create mode 100644 tensorflow/python/keras/optimizer_v2/adam_test.py create mode 100644 tensorflow/python/keras/optimizer_v2/adamax.py create mode 100644 tensorflow/python/keras/optimizer_v2/adamax_test.py create mode 100644 tensorflow/python/keras/optimizer_v2/ftrl.py create mode 100644 tensorflow/python/keras/optimizer_v2/ftrl_test.py create mode 100644 tensorflow/python/keras/optimizer_v2/nadam.py create mode 100644 tensorflow/python/keras/optimizer_v2/nadam_test.py create mode 100644 tensorflow/python/keras/optimizer_v2/rmsprop.py create mode 100644 tensorflow/python/keras/optimizer_v2/rmsprop_test.py create mode 100644 tensorflow/python/keras/utils/losses_utils.py create mode 100644 tensorflow/python/keras/utils/tf_utils_test.py create mode 100644 tensorflow/python/kernel_tests/linalg/linear_operator_adjoint_test.py create mode 100644 tensorflow/python/kernel_tests/linalg/linear_operator_algebra_test.py create mode 100644 tensorflow/python/kernel_tests/linalg/linear_operator_inversion_test.py rename tensorflow/python/kernel_tests/{ => signal}/dct_ops_test.py (67%) rename tensorflow/python/kernel_tests/{ => signal}/fft_ops_test.py (96%) create mode 100644 tensorflow/python/kernel_tests/unicode_decode_op_test.py create mode 100644 tensorflow/python/kernel_tests/unicode_encode_op_test.py create mode 100644 tensorflow/python/ops/gradient_checker_v2.py create mode 100644 tensorflow/python/ops/gradient_checker_v2_test.py create mode 100644 tensorflow/python/ops/linalg/cholesky_registrations.py create mode 100644 tensorflow/python/ops/linalg/linear_operator_adjoint.py create mode 100644 tensorflow/python/ops/linalg/linear_operator_algebra.py create mode 100644 tensorflow/python/ops/linalg/linear_operator_inversion.py create mode 100644 tensorflow/python/ops/linalg/matmul_registrations.py rename tensorflow/{tools/compatibility/testdata/test_file_v1_10.py => python/ops/optional_grad.py} (62%) create mode 100644 tensorflow/python/ops/ragged/ragged_string_ops.py create mode 100644 tensorflow/python/ops/ragged/ragged_tensor_shape.py create mode 100644 tensorflow/python/ops/ragged/ragged_tensor_shape_test.py delete mode 100644 tensorflow/python/ops/signal/__init__.py create mode 100644 tensorflow/python/ops/signal/dct_ops.py rename tensorflow/python/ops/{spectral_ops.py => signal/fft_ops.py} (51%) create mode 100644 tensorflow/python/ops/signal/signal.py create mode 100644 tensorflow/python/ops/sort_ops.py rename tensorflow/{contrib/framework => }/python/ops/sort_ops_test.py (90%) delete mode 100644 tensorflow/python/ops/spectral_grad.py create mode 100644 tensorflow/python/ops/tensor_forest_ops.py create mode 100644 tensorflow/python/platform/__init__.py create mode 100644 tensorflow/python/saved_model/load.py create mode 100644 tensorflow/python/saved_model/load_test.py create mode 100644 tensorflow/python/saved_model/saved_object_graph.proto create mode 100644 tensorflow/python/util/dispatch.py create mode 100644 tensorflow/python/util/dispatch_test.py create mode 100644 tensorflow/stream_executor/dnn.proto create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.-tensor-spec.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-optimization-options.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-threading-options.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.distribute.-input-context.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.distribute.-input-replication-mode.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.distribute.-reduce-op.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.distribute.-replica-context.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.distribute.-strategy-extended.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.distribute.-strategy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.distribute.pbtxt rename tensorflow/tools/api/golden/{v2/tensorflow.train.-profiler-hook.pbtxt => v1/tensorflow.estimator.experimental.-in-memory-evaluator-hook.pbtxt} (71%) create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.io.gfile.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-binary-crossentropy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-categorical-crossentropy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-absolute-error.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-absolute-percentage-error.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-squared-error.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-squared-logarithmic-error.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-binary-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-categorical-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-false-negatives.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-false-positives.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-mean.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-precision.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-recall.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-sparse-categorical-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-true-negatives.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-true-positives.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-binary-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-categorical-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-false-negatives.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-false-positives.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-mean.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-precision.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-recall.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-sparse-categorical-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-true-negatives.pbtxt create mode 100644 tensorflow/tools/api/golden/v1/tensorflow.metrics.-true-positives.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.-conditional-accumulator-base.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.-conditional-accumulator.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.-device-spec.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.-dimension.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.-graph-keys.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.-tensor-info.-coo-sparse.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.-tensor-info.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.-tensor-spec.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.app.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.data.-iterator.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-optimization-options.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-threading-options.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.distribute.-input-context.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.distribute.-input-replication-mode.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.distribute.-reduce-op.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.distribute.-replica-context.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.distribute.-strategy-extended.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.distribute.-strategy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.distribute.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.-in-memory-evaluator-hook.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.gfile.-fast-g-file.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.gfile.-g-file.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.gfile.-open.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.gfile.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.io.gfile.pbtxt rename tensorflow/tools/api/golden/v2/{tensorflow.nn.rnn_cell.-multi-r-n-n-cell.pbtxt => tensorflow.keras.layers.-dense-features.pbtxt} (77%) create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-linear-model.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-binary-crossentropy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-categorical-crossentropy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-absolute-error.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-absolute-percentage-error.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-squared-error.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-squared-logarithmic-error.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-reduction.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-binary-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-categorical-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-false-negatives.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-false-positives.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-mean.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-precision.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-recall.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-sparse-categorical-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-true-negatives.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-true-positives.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.logging.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-binary-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-categorical-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-false-negatives.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-false-positives.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-mean.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-precision.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-recall.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-sparse-categorical-accuracy.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-true-negatives.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.metrics.-true-positives.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.-checker.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.-checkers-entry.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-graph-node-proto.-input-shapes-entry.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-graph-node-proto.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-multi-graph-node-proto.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-op-log-proto.-id-to-string-entry.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-op-log-proto.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-profile-option-builder.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.-profiler.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.profiler.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.spectral.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.summary.-summary-writer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-adadelta-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-adagrad-d-a-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-adagrad-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-adam-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-checkpoint-saver-listener.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-chief-session-creator.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-ftrl-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-gradient-descent-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-looper-thread.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-momentum-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-monitored-session.-step-context.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-monitored-session.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-nan-loss-during-training-error.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-proximal-adagrad-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-r-m-s-prop-optimizer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-scaffold.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-second-or-step-timer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-session-creator.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-session-manager.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-args.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-context.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-values.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-singular-monitored-session.-step-context.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-singular-monitored-session.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-supervisor.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-vocab-info.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.train.-worker-session-creator.pbtxt create mode 100644 tensorflow/tools/ci_build/Dockerfile.rbe.cuda10.0-cudnn7-ubuntu14.04 create mode 100644 tensorflow/tools/compatibility/ast_edits_test.py create mode 100644 tensorflow/tools/compatibility/testdata/test_file_v1_12.py create mode 100644 tensorflow/tools/compatibility/tf_upgrade_v2_main.py create mode 100644 tensorflow/tools/dockerfiles/.gitignore rename tensorflow/tools/dockerfiles/dockerfiles/{nvidia-devel-jupyter.Dockerfile => gpu-devel-jupyter.Dockerfile} (66%) rename tensorflow/tools/dockerfiles/dockerfiles/{nvidia-devel.Dockerfile => gpu-devel.Dockerfile} (76%) rename tensorflow/tools/dockerfiles/dockerfiles/{nvidia-jupyter.Dockerfile => gpu-jupyter.Dockerfile} (62%) rename tensorflow/tools/dockerfiles/dockerfiles/{nvidia.Dockerfile => gpu.Dockerfile} (69%) create mode 100644 tensorflow/tools/dockerfiles/partials/test-import.partial.Dockerfile delete mode 100644 tensorflow/tools/dockerfiles/partials/ubuntu.partial.Dockerfile rename tensorflow/tools/dockerfiles/partials/{ => ubuntu}/bazel.partial.Dockerfile (58%) rename tensorflow/tools/dockerfiles/partials/{ubuntu-devel.partial.Dockerfile => ubuntu/cpu-devel.partial.Dockerfile} (86%) create mode 100644 tensorflow/tools/dockerfiles/partials/ubuntu/cpu.partial.Dockerfile rename tensorflow/tools/dockerfiles/partials/{ => ubuntu}/nvidia-devel.partial.Dockerfile (78%) rename tensorflow/tools/dockerfiles/partials/{ => ubuntu}/nvidia.partial.Dockerfile (78%) rename tensorflow/tools/dockerfiles/partials/{ => ubuntu}/python.partial.Dockerfile (66%) create mode 100644 tensorflow/tools/dockerfiles/partials/ubuntu/test-devel.partial.Dockerfile create mode 100644 tensorflow/tools/dockerfiles/partials/ubuntu/version.partial.Dockerfile create mode 100644 tensorflow/tools/dockerfiles/readme-for-jupyter.md create mode 100755 tensorflow/tools/dockerfiles/tests/build-cpu.sh create mode 100755 tensorflow/tools/dockerfiles/tests/build-gpu.sh create mode 100755 tensorflow/tools/dockerfiles/tests/import-gpu.sh create mode 100755 tensorflow/tools/dockerfiles/tests/import.sh rename tensorflow/tools/dockerfiles/{assembler.Dockerfile => tools.Dockerfile} (95%) create mode 100644 tensorflow/tools/docs/generate2.py rename tensorflow/{contrib/estimator/python/estimator/linear.py => tools/docs/generate2_test.py} (60%) delete mode 100644 tensorflow/tools/docs/generate_1_0.py delete mode 100644 third_party/eigen_reshaped.patch create mode 100644 third_party/icu/data/BUILD.bazel create mode 100644 third_party/icu/data/LICENSE create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.aa create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.ab create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.ac create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.ad create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.ae create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.af create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.ag create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.ah create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.ai create mode 100644 third_party/icu/data/icu_conversion_data.c.gz.aj create mode 100644 third_party/icu/udata.patch create mode 100644 third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/WORKSPACE create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/BUILD create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/build_defs.bzl create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/cuda/cuda_config.h create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/BUILD create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/CROSSTOOL create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/clang/bin/crosstool_wrapper_driver_is_not_gcc create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/windows/msvc_wrapper_for_nvcc.bat create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/windows/msvc_wrapper_for_nvcc.py create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/BUILD create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/CROSSTOOL create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/clang/bin/crosstool_wrapper_driver_is_not_gcc create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/windows/msvc_wrapper_for_nvcc.bat create mode 100755 third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/windows/msvc_wrapper_for_nvcc.py diff --git a/.github/ISSUE_TEMPLATE/40-tflite-op-request.md b/.github/ISSUE_TEMPLATE/40-tflite-op-request.md new file mode 100644 index 0000000000..7b391279e4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/40-tflite-op-request.md @@ -0,0 +1,24 @@ +--- +name: TensorFlow Lite Op Request +about: Use this template for reporting ops you are using or missing. + +--- + + +**System information** +- OS Platform and Distribution (e.g., Linux Ubuntu 16.04): +- TensorFlow installed from (source or binary): +- TensorFlow version (or github SHA if from source): + + +**Provide the text output from tflite_convert** + +``` +# Copy and paste here +``` + +Also, please include a link to a GraphDef or the model if possible. + +**Any other info / logs** + +Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached. diff --git a/README.md b/README.md index 8af5370bef..6fefdd3224 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ data flow graphs. The graph nodes represent mathematical operations, while the graph edges represent the multidimensional data arrays (tensors) that flow between them. This flexible architecture enables you to deploy computation to one or more CPUs or GPUs in a desktop, server, or mobile device without rewriting -code. TensorFlow also includes [TensorBoard](https://www.tensorflow.org/guide/summaries_and_tensorboard), a data visualization toolkit. +code. TensorFlow also includes [TensorBoard](https://github.com/tensorflow/tensorboard), +a data visualization toolkit. TensorFlow was originally developed by researchers and engineers working on the Google Brain team within Google's Machine Intelligence Research @@ -111,7 +112,7 @@ The TensorFlow project strives to abide by generally accepted best practices in Build Type | Status | Artifacts ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- **IBM s390x** | [![Build Status](http://ibmz-ci.osuosl.org/job/TensorFlow_IBMZ_CI/badge/icon)](http://ibmz-ci.osuosl.org/job/TensorFlow_IBMZ_CI/) | TBA -**IBM ppc64le CPU** | [![Build Status](http://powerci.osuosl.org/job/TensorFlow_Ubuntu_16.04_CPU/badge/icon)](http://powerci.osuosl.org/job/TensorFlow_Ubuntu_16.04_CPU/) | TBA +**IBM ppc64le CPU** | [![Build Status](http://powerci.osuosl.org/job/TensorFlow_PPC64LE_CPU_Build/badge/icon)](http://powerci.osuosl.org/job/TensorFlow_PPC64LE_CPU_Build/) | TBA **IBM ppc64le GPU** Nightly | [![Build Status](https://powerci.osuosl.org/job/TensorFlow_PPC64LE_GPU_Nightly_Artifact/badge/icon)](https://powerci.osuosl.org/job/TensorFlow_PPC64LE_GPU_Nightly_Artifact/) | [Nightly](https://powerci.osuosl.org/job/TensorFlow_PPC64LE_GPU_Nightly_Artifact/) **IBM ppc64le GPU** Stable Release | [![Build Status](https://powerci.osuosl.org/job/TensorFlow_PPC64LE_GPU_Release_Build/badge/icon)](https://powerci.osuosl.org/job/TensorFlow_PPC64LE_GPU_Release_Build/) | [Release](https://powerci.osuosl.org/job/TensorFlow_PPC64LE_GPU_Release_Build/) **Linux CPU with Intel® MKL-DNN** Nightly | [![Build Status](https://tensorflow-ci.intel.com/job/tensorflow-mkl-linux-cpu/badge/icon)](https://tensorflow-ci.intel.com/job/tensorflow-mkl-linux-cpu/) | [Nightly](https://tensorflow-ci.intel.com/job/tensorflow-mkl-build-whl-nightly/) @@ -127,6 +128,7 @@ Build Type * [TensorFlow Roadmap](https://www.tensorflow.org/community/roadmap) * [TensorFlow White Papers](https://www.tensorflow.org/about/bib) * [TensorFlow YouTube Channel](https://www.youtube.com/channel/UC0rqucBdTuFTjJiefW5t-IQ) +* [TensorFlow Visualization Toolkit](https://github.com/tensorflow/tensorboard) Learn more about the TensorFlow community at the [community page of tensorflow.org](https://www.tensorflow.org/community) for a few ways to participate. diff --git a/WORKSPACE b/WORKSPACE index 0c7bc085b5..7cc08e0164 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,5 +1,7 @@ workspace(name = "org_tensorflow") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + http_archive( name = "io_bazel_rules_closure", sha256 = "a38539c5b5c358548e75b44141b4ab637bba7c4dc02b46b1f62a96d6433f56ae", @@ -57,9 +59,9 @@ android_workspace() # Please add all new TensorFlow dependencies in workspace.bzl. tf_workspace() -new_http_archive( +http_archive( name = "inception_v1", - build_file = "models.BUILD", + build_file = "//:models.BUILD", sha256 = "7efe12a8363f09bc24d7b7a450304a15655a57a7751929b2c1593a71183bb105", urls = [ "http://storage.googleapis.com/download.tensorflow.org/models/inception_v1.zip", @@ -67,9 +69,9 @@ new_http_archive( ], ) -new_http_archive( +http_archive( name = "mobile_ssd", - build_file = "models.BUILD", + build_file = "//:models.BUILD", sha256 = "bddd81ea5c80a97adfac1c9f770e6f55cbafd7cce4d3bbe15fbeb041e6b8f3e8", urls = [ "http://storage.googleapis.com/download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_android_export.zip", @@ -77,9 +79,9 @@ new_http_archive( ], ) -new_http_archive( +http_archive( name = "mobile_multibox", - build_file = "models.BUILD", + build_file = "//:models.BUILD", sha256 = "859edcddf84dddb974c36c36cfc1f74555148e9c9213dedacf1d6b613ad52b96", urls = [ "http://storage.googleapis.com/download.tensorflow.org/models/mobile_multibox_v1a.zip", @@ -87,9 +89,9 @@ new_http_archive( ], ) -new_http_archive( +http_archive( name = "stylize", - build_file = "models.BUILD", + build_file = "//:models.BUILD", sha256 = "3d374a730aef330424a356a8d4f04d8a54277c425e274ecb7d9c83aa912c6bfa", urls = [ "http://storage.googleapis.com/download.tensorflow.org/models/stylize_v1.zip", @@ -97,9 +99,9 @@ new_http_archive( ], ) -new_http_archive( +http_archive( name = "speech_commands", - build_file = "models.BUILD", + build_file = "//:models.BUILD", sha256 = "c3ec4fea3158eb111f1d932336351edfe8bd515bb6e87aad4f25dbad0a600d0c", urls = [ "http://storage.googleapis.com/download.tensorflow.org/models/speech_commands_v0.01.zip", diff --git a/configure.py b/configure.py index 234561d94a..5f429c3de8 100644 --- a/configure.py +++ b/configure.py @@ -238,6 +238,13 @@ def setup_python(environ_cp): write_to_bazelrc('build --python_path=\"%s"' % python_bin_path) environ_cp['PYTHON_BIN_PATH'] = python_bin_path + # If choosen python_lib_path is from a path specified in the PYTHONPATH + # variable, need to tell bazel to include PYTHONPATH + if environ_cp.get('PYTHONPATH'): + python_paths = environ_cp.get('PYTHONPATH').split(':') + if python_lib_path in python_paths: + write_action_env_to_bazelrc('PYTHONPATH', environ_cp.get('PYTHONPATH')) + # Write tools/python_bin_path.sh with open( os.path.join(_TF_WORKSPACE_ROOT, 'tools', 'python_bin_path.sh'), @@ -445,11 +452,12 @@ def convert_version_to_int(version): return int(version_str) -def check_bazel_version(min_version): - """Check installed bazel version is at least min_version. +def check_bazel_version(min_version, max_version): + """Check installed bazel version is between min_version and max_version. Args: min_version: string for minimum bazel version. + max_version: string for maximum bazel version. Returns: The bazel version detected. @@ -467,6 +475,7 @@ def check_bazel_version(min_version): min_version_int = convert_version_to_int(min_version) curr_version_int = convert_version_to_int(curr_version) + max_version_int = convert_version_to_int(max_version) # Check if current bazel version can be detected properly. if not curr_version_int: @@ -480,6 +489,10 @@ def check_bazel_version(min_version): print('Please upgrade your bazel installation to version %s or higher to ' 'build TensorFlow!' % min_version) sys.exit(0) + if curr_version_int > max_version_int: + print('Please downgrade your bazel installation to version %s or lower to ' + 'build TensorFlow!' % max_version) + sys.exit(0) return curr_version @@ -859,7 +872,7 @@ def set_tf_cuda_version(environ_cp): cuda_toolkit_paths_full = [ os.path.join(cuda_toolkit_path, x) for x in cuda_rt_lib_paths ] - if any([os.path.exists(x) for x in cuda_toolkit_paths_full]): + if any(os.path.exists(x) for x in cuda_toolkit_paths_full): break # Reset and retry @@ -1552,7 +1565,7 @@ def main(): # environment variables. environ_cp = dict(os.environ) - check_bazel_version('0.15.0') + check_bazel_version('0.15.0', '0.20.0') reset_tf_configure_bazelrc() # Explicitly import tools/bazel.rc, this is needed for Bazel 0.19.0 or later @@ -1694,6 +1707,7 @@ def main(): config_info_line('nohdfs', 'Disable HDFS support.') config_info_line('noignite', 'Disable Apacha Ignite support.') config_info_line('nokafka', 'Disable Apache Kafka support.') + config_info_line('nonccl', 'Disable NVIDIA NCCL support.') if __name__ == '__main__': diff --git a/tensorflow/BUILD b/tensorflow/BUILD index 859dc3b8d7..fd4b94202a 100644 --- a/tensorflow/BUILD +++ b/tensorflow/BUILD @@ -43,6 +43,11 @@ TENSORFLOW_API_INIT_FILES_V2 = ( TENSORFLOW_API_INIT_FILES + get_compat_files(TENSORFLOW_API_INIT_FILES_V1, 1) ) +# @unused +TENSORFLOW_API_INIT_FILES_V1_WITH_COMPAT = ( + TENSORFLOW_API_INIT_FILES_V1 + get_compat_files(TENSORFLOW_API_INIT_FILES_V1, 1) +) + # Config setting used when building for products # which requires restricted licenses to be avoided. config_setting( @@ -213,31 +218,37 @@ config_setting( # config_setting( name = "no_aws_support", - define_values = {"no_aws_support": "false"}, + define_values = {"no_aws_support": "true"}, visibility = ["//visibility:public"], ) config_setting( name = "no_gcp_support", - define_values = {"no_gcp_support": "false"}, + define_values = {"no_gcp_support": "true"}, visibility = ["//visibility:public"], ) config_setting( name = "no_hdfs_support", - define_values = {"no_hdfs_support": "false"}, + define_values = {"no_hdfs_support": "true"}, visibility = ["//visibility:public"], ) config_setting( name = "no_ignite_support", - define_values = {"no_ignite_support": "false"}, + define_values = {"no_ignite_support": "true"}, visibility = ["//visibility:public"], ) config_setting( name = "no_kafka_support", - define_values = {"no_kafka_support": "false"}, + define_values = {"no_kafka_support": "true"}, + visibility = ["//visibility:public"], +) + +config_setting( + name = "no_nccl_support", + define_values = {"no_nccl_support": "true"}, visibility = ["//visibility:public"], ) @@ -350,7 +361,7 @@ package_group( "-//third_party/tensorflow/python/estimator", "//learning/meta_rank/...", "//tensorflow/...", - "//tensorflow_estimator/...", + "//tensorflow_estimator/contrib/...", "//tensorflow_fold/llgtm/...", "//tensorflow_text/...", "//third_party/py/tensor2tensor/...", @@ -554,18 +565,24 @@ genrule( }), outs = ["__init__.py"], cmd = select({ - "api_version_2": "cp $(@D)/_api/v2/__init__.py $(OUTS)", - "//conditions:default": "cp $(@D)/_api/v1/__init__.py $(OUTS)", + "api_version_2": "cp $(@D)/_api/v2/v2.py $(OUTS)", + "//conditions:default": "cp $(@D)/_api/v1/v1.py $(OUTS)", }), ) gen_api_init_files( name = "tf_python_api_gen_v1", - srcs = ["api_template_v1.__init__.py"], + srcs = [ + "api_template_v1.__init__.py", + "compat_template_v1.__init__.py", + ], api_version = 1, + compat_api_versions = [1], + compat_init_templates = ["compat_template_v1.__init__.py"], output_dir = "_api/v1/", - output_files = TENSORFLOW_API_INIT_FILES_V1, + output_files = TENSORFLOW_API_INIT_FILES_V1_WITH_COMPAT, output_package = "tensorflow._api.v1", + root_file_name = "v1.py", root_init_template = "api_template_v1.__init__.py", ) @@ -581,6 +598,7 @@ gen_api_init_files( output_dir = "_api/v2/", output_files = TENSORFLOW_API_INIT_FILES_V2, output_package = "tensorflow._api.v2", + root_file_name = "v2.py", root_init_template = "api_template.__init__.py", ) diff --git a/tensorflow/api_template.__init__.py b/tensorflow/api_template.__init__.py index 0d49756838..d81cf067eb 100644 --- a/tensorflow/api_template.__init__.py +++ b/tensorflow/api_template.__init__.py @@ -21,8 +21,6 @@ from __future__ import print_function as _print_function import os as _os # pylint: disable=g-bad-import-order -from tensorflow.python import pywrap_tensorflow # pylint: disable=unused-import - from tensorflow.python.tools import component_api_helper as _component_api_helper _component_api_helper.package_hook( parent_package_str=__name__, @@ -30,16 +28,16 @@ _component_api_helper.package_hook( # API IMPORTS PLACEHOLDER -from tensorflow.python.platform import flags # pylint: disable=g-import-not-at-top - # Make sure directory containing top level submodules is in # the __path__ so that "from tensorflow.foo import bar" works. -_tf_api_dir = _os.path.dirname(_os.path.dirname(app.__file__)) # pylint: disable=undefined-variable +# We're using bitwise, but there's nothing special about that. +_tf_api_dir = _os.path.dirname(_os.path.dirname(bitwise.__file__)) # pylint: disable=undefined-variable if _tf_api_dir not in __path__: __path__.append(_tf_api_dir) -# Calls to enable and disable features. -enable_eager_execution() # pylint: disable=undefined-variable +# Enable TF2 behaviors +from tensorflow.python.compat import compat as _compat # pylint: disable=g-import-not-at-top +_compat.enable_v2_behavior() # These symbols appear because we import the python package which # in turn imports from tensorflow.core and tensorflow.python. They diff --git a/tensorflow/c/BUILD b/tensorflow/c/BUILD index b8db1b2144..59c23e7c18 100644 --- a/tensorflow/c/BUILD +++ b/tensorflow/c/BUILD @@ -60,6 +60,7 @@ tf_cuda_library( "//tensorflow/core:framework", "//tensorflow/core:lib", "//tensorflow/core:op_gen_lib", + "//tensorflow/core/distributed_runtime:server_lib", ], }), ) @@ -120,7 +121,8 @@ tf_cuda_library( ":c_api", ":c_api_internal", "//tensorflow/c/eager:c_api", - "//tensorflow/compiler/jit/legacy_flags:mark_for_compilation_pass_flags", + "//tensorflow/c/eager:c_api_internal", + "//tensorflow/compiler/jit:flags", "//tensorflow/contrib/tpu:all_ops", "//tensorflow/core:core_cpu", "//tensorflow/core:framework", @@ -173,6 +175,30 @@ tf_cuda_library( ], ) +tf_cuda_library( + name = "kernels", + srcs = [ + "kernels.cc", + ], + hdrs = [ + "kernels.h", + ], + copts = tf_copts(), + visibility = ["//visibility:public"], + deps = select({ + "//tensorflow:android": [ + ":c_api", + ":c_api_internal", + "//tensorflow/core:android_tensorflow_lib_lite", + ], + "//conditions:default": [ + ":c_api", + ":c_api_internal", + "//tensorflow/core:framework", + ], + }), +) + # ----------------------------------------------------------------------------- # Tests @@ -208,7 +234,10 @@ tf_cuda_cc_test( "//tensorflow:darwin": ["-headerpad_max_install_names"], "//conditions:default": [], }), - tags = ["noasan"], + tags = [ + "no_oss", # http://b/119522529 + "noasan", + ], # We must ensure that the dependencies can be dynamically linked since # the shared library must be able to use core:framework. # linkstatic = tf_kernel_tests_linkstatic(), @@ -237,7 +266,7 @@ tf_cuda_cc_test( tf_cc_test( name = "c_api_experimental_test", - size = "small", + size = "medium", srcs = ["c_api_experimental_test.cc"], data = ["testdata/tf_record"], linkopts = select({ @@ -248,8 +277,11 @@ tf_cc_test( # the shared library must be able to use core:framework. # linkstatic = tf_kernel_tests_linkstatic(), deps = [ + ":c_api", ":c_api_experimental", ":c_test_util", + "//tensorflow/c/eager:c_api", + "//tensorflow/c/eager:c_api_test_util", "//tensorflow/core:lib", "//tensorflow/core:protos_all_cc", "//tensorflow/core:test", @@ -300,6 +332,30 @@ tf_kernel_library( alwayslink = 1, ) +tf_cuda_cc_test( + name = "kernels_test", + size = "small", + srcs = ["kernels_test.cc"], + linkopts = select({ + "//tensorflow:darwin": ["-headerpad_max_install_names"], + "//conditions:default": [], + }), + tags = ["noasan"], + # We must ensure that the dependencies can be dynamically linked since + # the shared library must be able to use core:framework. + # linkstatic = tf_kernel_tests_linkstatic(), + deps = [ + ":c_api", + ":kernels", + "//tensorflow/core:framework", + "//tensorflow/core:lib", + "//tensorflow/core:proto_text", + "//tensorflow/core:protos_all_cc", + "//tensorflow/core:test", + "//tensorflow/core:test_main", + ], +) + # ----------------------------------------------------------------------------- # Python API target diff --git a/tensorflow/c/c_api_experimental.cc b/tensorflow/c/c_api_experimental.cc index fabe2fa0f6..38e29aa74a 100644 --- a/tensorflow/c/c_api_experimental.cc +++ b/tensorflow/c/c_api_experimental.cc @@ -15,13 +15,18 @@ limitations under the License. #include "tensorflow/c/c_api_experimental.h" +#include "tensorflow/c/c_api.h" #include "tensorflow/c/c_api_internal.h" -#include "tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.h" +#include "tensorflow/c/eager/c_api.h" +#include "tensorflow/c/eager/c_api_internal.h" +#include "tensorflow/compiler/jit/flags.h" #include "tensorflow/core/common_runtime/eager/attr_builder.h" #include "tensorflow/core/framework/tensor.pb.h" #include "tensorflow/core/graph/graph.h" #include "tensorflow/core/graph/node_builder.h" #include "tensorflow/core/lib/strings/strcat.h" +#include "tensorflow/core/platform/init_main.h" +#include "tensorflow/core/platform/net.h" #include "tensorflow/core/platform/platform.h" #include "tensorflow/core/protobuf/config.pb.h" #include "tensorflow/core/protobuf/tensorflow_server.pb.h" @@ -51,8 +56,8 @@ void TF_EnableXLACompilation(TF_SessionOptions* options, unsigned char enable) { // These XLA flags are needed to trigger XLA properly from C (more generally // non-Python) clients. If this API is called again with `enable` set to // false, it is safe to keep these flag values as is. - tensorflow::legacy_flags::MarkForCompilationPassFlags* flags = - tensorflow::legacy_flags::GetMarkForCompilationPassFlags(); + tensorflow::MarkForCompilationPassFlags* flags = + tensorflow::GetMarkForCompilationPassFlags(); flags->tf_xla_cpu_global_jit = true; flags->tf_xla_min_cluster_size = 1; } else { @@ -71,8 +76,8 @@ TF_Buffer* TF_CreateConfig(unsigned char enable_xla_compilation, // These XLA flags are needed to trigger XLA properly from C (more generally // non-Python) clients. If this API is called again with `enable` set to // false, it is safe to keep these flag values as is. - tensorflow::legacy_flags::MarkForCompilationPassFlags* flags = - tensorflow::legacy_flags::GetMarkForCompilationPassFlags(); + tensorflow::MarkForCompilationPassFlags* flags = + tensorflow::GetMarkForCompilationPassFlags(); flags->tf_xla_cpu_global_jit = true; flags->tf_xla_min_cluster_size = 1; } else { @@ -6525,7 +6530,7 @@ library { } } node_def { - name: "ParallelInterleaveDataset/cycle_length" + name: "ExperimentalParallelInterleaveDataset/cycle_length" op: "Const" attr { key: "dtype" @@ -6546,7 +6551,7 @@ library { } } node_def { - name: "ParallelInterleaveDataset/block_length" + name: "ExperimentalParallelInterleaveDataset/block_length" op: "Const" attr { key: "dtype" @@ -6567,7 +6572,7 @@ library { } } node_def { - name: "ParallelInterleaveDataset/sloppy" + name: "ExperimentalParallelInterleaveDataset/sloppy" op: "Const" attr { key: "dtype" @@ -6588,7 +6593,7 @@ library { } } node_def { - name: "ParallelInterleaveDataset/buffer_output_elements" + name: "ExperimentalParallelInterleaveDataset/buffer_output_elements" op: "Const" attr { key: "dtype" @@ -6609,7 +6614,7 @@ library { } } node_def { - name: "ParallelInterleaveDataset/prefetch_input_elements" + name: "ExperimentalParallelInterleaveDataset/prefetch_input_elements" op: "Const" attr { key: "dtype" @@ -6630,14 +6635,14 @@ library { } } node_def { - name: "ParallelInterleaveDataset" - op: "ParallelInterleaveDataset" + name: "ExperimentalParallelInterleaveDataset" + op: "ExperimentalParallelInterleaveDataset" input: "RepeatDataset:handle:0" - input: "ParallelInterleaveDataset/cycle_length:output:0" - input: "ParallelInterleaveDataset/block_length:output:0" - input: "ParallelInterleaveDataset/sloppy:output:0" - input: "ParallelInterleaveDataset/buffer_output_elements:output:0" - input: "ParallelInterleaveDataset/prefetch_input_elements:output:0" + input: "ExperimentalParallelInterleaveDataset/cycle_length:output:0" + input: "ExperimentalParallelInterleaveDataset/block_length:output:0" + input: "ExperimentalParallelInterleaveDataset/sloppy:output:0" + input: "ExperimentalParallelInterleaveDataset/buffer_output_elements:output:0" + input: "ExperimentalParallelInterleaveDataset/prefetch_input_elements:output:0" attr { key: "Targuments" value { @@ -6737,7 +6742,7 @@ library { node_def { name: "ShuffleDataset_2" op: "ShuffleDataset" - input: "ParallelInterleaveDataset:handle:0" + input: "ExperimentalParallelInterleaveDataset:handle:0" input: "ShuffleDataset_2/buffer_size_1:output:0" input: "ShuffleDataset_2/seed_2:output:0" input: "ShuffleDataset_2/seed2_2:output:0" @@ -8739,14 +8744,65 @@ void TFE_TensorHandlePrintDebugString(TFE_TensorHandle* handle) { TF_DeleteStatus(status); } -TF_CAPI_EXPORT extern void TF_MakeInternalErrorStatus(TF_Status* status, - const char* errMsg) { +struct TFE_ExecuteOpNotification { + TFE_ExecuteOpNotification() : status(TF_NewStatus(), TF_DeleteStatus) {} + tensorflow::Notification n; + std::unique_ptr thread; + std::unique_ptr status; +}; + +TFE_ExecuteOpNotification* TFE_ExecuteOpInNewThread(TFE_Op* op, + TFE_TensorHandle** retvals, + int* num_retvals, + TF_Status* status) { + TFE_ExecuteOpNotification* n = new TFE_ExecuteOpNotification; + + n->thread.reset(op->operation.EagerContext()->TFEnv()->StartThread( + tensorflow::ThreadOptions(), "ExecuteOpThread", + [op, retvals, num_retvals, n]() { + TFE_Execute(op, retvals, num_retvals, n->status.get()); + n->n.Notify(); + })); + + return n; +} + +void TFE_ExecuteOpNotificationWaitAndDelete( + TFE_ExecuteOpNotification* notification, TF_Status* status) { + if (notification == nullptr) { + status->status = tensorflow::errors::InvalidArgument( + "Passed in notification is a nullptr."); + + return; + } + if (notification->thread == nullptr) { + status->status = tensorflow::errors::InvalidArgument( + "Passed in notification didn't start a thread correctly. Cleaning up " + "this notification. Please re-execute the operation to get a new " + "notification."); + + delete notification; + return; + } + + notification->n.WaitForNotification(); + + status->status = notification->status->status; + + delete notification; +} + +void TF_MakeInternalErrorStatus(TF_Status* status, const char* errMsg) { status->status = tensorflow::errors::Internal(errMsg); } // This builder is used in the eager API to build a NodeDef. struct TF_AttrBuilder : public tensorflow::AttrBuilder { using tensorflow::AttrBuilder::AttrBuilder; + // The string buffers to make sure that any `attr_name` we pass into + // `builder->Set()` will outlive the subsequent + // `TF_AttrBuilderCheckCanRunOnDevice()` call(s) on the same `builder`. + std::set attr_names; }; TF_AttrBuilder* TF_NewAttrBuilder(const char* op_name) { @@ -8757,13 +8813,15 @@ void TF_DeleteAttrBuilder(TF_AttrBuilder* builder) { delete builder; } void TF_AttrBuilderSetType(TF_AttrBuilder* builder, const char* attr_name, TF_DataType value) { - builder->Set(attr_name, static_cast(value)); + auto iter = builder->attr_names.insert(attr_name).first; + builder->Set((*iter).c_str(), static_cast(value)); } void TF_AttrBuilderSetTypeList(TF_AttrBuilder* builder, const char* attr_name, const TF_DataType* values, int num_values) { + auto iter = builder->attr_names.insert(attr_name).first; builder->Set( - attr_name, + (*iter).c_str(), tensorflow::gtl::ArraySlice( reinterpret_cast(values), num_values)); } @@ -8800,3 +8858,31 @@ const char* TF_GetNumberAttrForOpListInput(const char* op_name, int input_index, // The returned string is owned by OpRegistry, so liveness is not a concern. return input_arg.number_attr().c_str(); } + +int TF_OpIsStateful(const char* op_type, TF_Status* status) { + const tensorflow::OpRegistrationData* op_reg_data; + status->status = + tensorflow::OpRegistry::Global()->LookUp(op_type, &op_reg_data); + if (!status->status.ok()) { + return 0; + } + return op_reg_data->op_def.is_stateful(); +} + +void TF_InitMain(const char* usage, int* argc, char*** argv) { + tensorflow::port::InitMain(usage, argc, argv); +} + +int TF_PickUnusedPortOrDie() { + return tensorflow::internal::PickUnusedPortOrDie(); +} + +TFE_TensorHandle* TFE_NewTensorHandleFromScalar(TF_DataType dtype_arg, + void* data, size_t len) { + auto dtype = static_cast(dtype_arg); + DCHECK(tensorflow::DataTypeCanUseMemcpy(dtype)); + + tensorflow::Tensor tensor(dtype, tensorflow::TensorShape({})); + std::memcpy(tensorflow::TensorCApi::Buffer(tensor)->data(), data, len); + return new TFE_TensorHandle(tensor, nullptr, nullptr); +} diff --git a/tensorflow/c/c_api_experimental.h b/tensorflow/c/c_api_experimental.h index 6639b0be72..80c8bfe594 100644 --- a/tensorflow/c/c_api_experimental.h +++ b/tensorflow/c/c_api_experimental.h @@ -180,6 +180,25 @@ TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_DequeueVariantTensor( TF_CAPI_EXPORT extern void TFE_TensorHandlePrintDebugString( TFE_TensorHandle* handle); +typedef struct TFE_ExecuteOpNotification TFE_ExecuteOpNotification; + +// Allows invoking a kernel asynchronously, and explicitly returns a +// notification that can be waited upon. This always executes the kernel in a +// new thread. +// 1. `retvals` and `num_retvals` can only be consumed after +// `TFE_ExecuteOp` returns successfully. They shouldn't be used +// if the return is unsuccessful +// 2. These new APIs cannot be used together with the TFE context level async +// support. +TF_CAPI_EXPORT extern TFE_ExecuteOpNotification* TFE_ExecuteOpInNewThread( + TFE_Op* op, TFE_TensorHandle** retvals, int* num_retvals, + TF_Status* status); + +// Waits to complete the op execution, and cleans up the notification. +// Errors reported by op execution are set in `status`. +TF_CAPI_EXPORT extern void TFE_ExecuteOpNotificationWaitAndDelete( + TFE_ExecuteOpNotification* notification, TF_Status* status); + TF_CAPI_EXPORT extern void TF_MakeInternalErrorStatus(TF_Status* status, const char* errMsg); @@ -209,6 +228,24 @@ TF_CAPI_EXPORT extern void TF_AttrBuilderCheckCanRunOnDevice( TF_CAPI_EXPORT extern const char* TF_GetNumberAttrForOpListInput( const char* op_name, int input_index, TF_Status* status); +// Returns 1 if the op is stateful, 0 otherwise. The return value is undefined +// if the status is not ok. +TF_CAPI_EXPORT extern int TF_OpIsStateful(const char* op_type, + TF_Status* status); + +// Platform specific initialization routine. Very few platforms actually require +// this to be called. +TF_CAPI_EXPORT void TF_InitMain(const char* usage, int* argc, char*** argv); + +// Platform-specific implementation to return an unused port. (This should used +// in tests only.) +TF_CAPI_EXPORT int TF_PickUnusedPortOrDie(); + +// Fast path method that makes constructing a single scalar tensor require less +// overhead and copies. +TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_NewTensorHandleFromScalar( + TF_DataType dtype, void* scalar, size_t len); + #ifdef __cplusplus } /* end extern "C" */ #endif diff --git a/tensorflow/c/c_api_experimental_test.cc b/tensorflow/c/c_api_experimental_test.cc index c6effd3969..daa7701b7f 100644 --- a/tensorflow/c/c_api_experimental_test.cc +++ b/tensorflow/c/c_api_experimental_test.cc @@ -15,6 +15,8 @@ limitations under the License. #include "tensorflow/c/c_api_experimental.h" #include "tensorflow/c/c_test_util.h" +#include "tensorflow/c/eager/c_api.h" +#include "tensorflow/c/eager/c_api_test_util.h" #include "tensorflow/core/lib/io/path.h" #include "tensorflow/core/platform/env.h" #include "tensorflow/core/platform/logging.h" @@ -162,5 +164,137 @@ protocol: "grpc" TF_DeleteStatus(status); } +TEST(CAPI_EXPERIMENTAL, IsStateful) { + std::unique_ptr status( + TF_NewStatus(), TF_DeleteStatus); + int assign = TF_OpIsStateful("AssignAddVariableOp", status.get()); + ASSERT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); + EXPECT_EQ(assign, 1); + int id = TF_OpIsStateful("Identity", status.get()); + ASSERT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); + EXPECT_EQ(id, 0); +} + +TEST(CAPI_EXPERIMENTAL, TFE_ExecuteOpInNewThreadTest_Simple) { + TF_Status* status = TF_NewStatus(); + TFE_ContextOptions* opts = TFE_NewContextOptions(); + TFE_Context* ctx = TFE_NewContext(opts, status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + TFE_DeleteContextOptions(opts); + + TFE_TensorHandle* m = TestMatrixTensorHandle(); + + TFE_Op* matmul_op = MatMulOp(ctx, m, m); + + TFE_TensorHandle* retvals[1] = {nullptr}; + int num_retvals = 1; + + auto* r = + TFE_ExecuteOpInNewThread(matmul_op, &retvals[0], &num_retvals, status); + + TFE_ExecuteOpNotificationWaitAndDelete(r, status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + + TF_Tensor* t = TFE_TensorHandleResolve(retvals[0], status); + ASSERT_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + float product[4] = {0}; + EXPECT_EQ(sizeof(product), TF_TensorByteSize(t)); + memcpy(&product[0], TF_TensorData(t), TF_TensorByteSize(t)); + TF_DeleteTensor(t); + EXPECT_EQ(7, product[0]); + EXPECT_EQ(10, product[1]); + EXPECT_EQ(15, product[2]); + EXPECT_EQ(22, product[3]); + + TFE_DeleteOp(matmul_op); + TFE_DeleteTensorHandle(m); + + TFE_DeleteTensorHandle(retvals[0]); + TFE_DeleteContext(ctx); + TF_DeleteStatus(status); +} + +// Perform a send/recv test. Recv blocks, so they need to be executed +// asynchronously. +TEST(CAPI_EXPERIMENTAL, TFE_ExecuteOpInNewThreadTest_Blocking) { + TF_Status* status = TF_NewStatus(); + TFE_ContextOptions* opts = TFE_NewContextOptions(); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + TFE_Context* ctx = TFE_NewContext(opts, status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + TFE_DeleteContextOptions(opts); + + // Returns a 2x2 float32 Tensor on the CPU, with data 1., 2., 3., 4. + TFE_TensorHandle* m = TestMatrixTensorHandle(); + + // Build a send op. + TFE_Op* send_op = TFE_NewOp(ctx, "_Send", status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + TFE_OpAddInput(send_op, m, status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + + string tensor_name = "Tensor"; + TFE_OpSetAttrType(send_op, "T", TF_FLOAT); + TFE_OpSetAttrString(send_op, "tensor_name", tensor_name.c_str(), + tensor_name.size()); + string send_device = "/job:localhost/replica:0/task:0/device:CPU:0"; + TFE_OpSetAttrString(send_op, "send_device", send_device.c_str(), + send_device.size()); + TFE_OpSetAttrInt(send_op, "send_device_incarnation", 1234); + string recv_device = "/job:localhost/replica:0/task:0/device:CPU:0"; + TFE_OpSetAttrString(send_op, "recv_device", recv_device.c_str(), + recv_device.size()); + TFE_OpSetAttrBool(send_op, "client_terminated", true); + + // Build a recv op. + TFE_Op* recv_op = TFE_NewOp(ctx, "_Recv", status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + + TFE_OpSetAttrType(recv_op, "tensor_type", TF_FLOAT); + TFE_OpSetAttrString(recv_op, "tensor_name", tensor_name.c_str(), + tensor_name.size()); + TFE_OpSetAttrString(recv_op, "send_device", send_device.c_str(), + send_device.size()); + TFE_OpSetAttrInt(recv_op, "send_device_incarnation", 1234); + TFE_OpSetAttrString(recv_op, "recv_device", recv_device.c_str(), + recv_device.size()); + TFE_OpSetAttrBool(recv_op, "client_terminated", true); + + TFE_TensorHandle* send_retvals; + int send_num_retvals = 0; + auto* send_result = TFE_ExecuteOpInNewThread(send_op, &send_retvals, + &send_num_retvals, status); + + TFE_TensorHandle* recv_retvals[1] = {nullptr}; + int recv_num_retvals = 1; + auto* recv_result = TFE_ExecuteOpInNewThread(recv_op, &recv_retvals[0], + &recv_num_retvals, status); + + TFE_ExecuteOpNotificationWaitAndDelete(send_result, status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + TFE_ExecuteOpNotificationWaitAndDelete(recv_result, status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + + TF_Tensor* t = TFE_TensorHandleResolve(recv_retvals[0], status); + ASSERT_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + + float product[4] = {0}; + EXPECT_EQ(sizeof(product), TF_TensorByteSize(t)); + memcpy(&product[0], TF_TensorData(t), TF_TensorByteSize(t)); + TF_DeleteTensor(t); + EXPECT_EQ(1, product[0]); + EXPECT_EQ(2, product[1]); + EXPECT_EQ(3, product[2]); + EXPECT_EQ(4, product[3]); + + TFE_DeleteOp(send_op); + TFE_DeleteOp(recv_op); + TFE_DeleteTensorHandle(m); + + TFE_DeleteTensorHandle(recv_retvals[0]); + TFE_DeleteContext(ctx); + TF_DeleteStatus(status); +} + } // namespace } // namespace tensorflow diff --git a/tensorflow/c/c_api_function.cc b/tensorflow/c/c_api_function.cc index f68f8a3e90..28b9f8df9c 100644 --- a/tensorflow/c/c_api_function.cc +++ b/tensorflow/c/c_api_function.cc @@ -392,26 +392,26 @@ Status ProcessInputs( EXCLUSIVE_LOCKS_REQUIRED(fn_body->mu) { input_tensors->reserve(ninputs); for (int i = 0; i < ninputs; ++i) { - const Node& node = inputs[i].oper->node; + Node* node = &inputs[i].oper->node; int idx = inputs[i].index; TF_RETURN_WITH_CONTEXT_IF_ERROR( - fn_body->graph.IsValidOutputTensor(&node, idx), + fn_body->graph.IsValidOutputTensor(node, idx), "Encountered while processing input ", i, " into function '", fn_name, "'"); - TF_RETURN_WITH_CONTEXT_IF_ERROR(ValidateNonRefOutput(&node, idx), + TF_RETURN_WITH_CONTEXT_IF_ERROR(ValidateNonRefOutput(node, idx), "Encountered while processing input ", i, " into function '", fn_name, "'"); - input_tensors->emplace_back(&node, idx); + input_tensors->emplace_back(node, idx); - const auto& iter = input_nodes->find(&node); + const auto& iter = input_nodes->find(node); if (iter == input_nodes->end()) { - input_nodes->insert({&node, {idx}}); + input_nodes->insert({node, {idx}}); } else { auto& indices = iter->second; if (std::find(indices.begin(), indices.end(), idx) != indices.end()) { - return InvalidArgument("TF_Output ", node.name(), ":", idx, + return InvalidArgument("TF_Output ", node->name(), ":", idx, " appears more than once in the input list"); } indices.push_back(idx); @@ -428,16 +428,16 @@ Status ProcessOutputs(const TF_Graph* fn_body, const char* fn_name, EXCLUSIVE_LOCKS_REQUIRED(fn_body->mu) { output_tensors->reserve(noutputs); for (int i = 0; i < noutputs; ++i) { - const Node& node = outputs[i].oper->node; + Node* node = &outputs[i].oper->node; int idx = outputs[i].index; TF_RETURN_WITH_CONTEXT_IF_ERROR( - fn_body->graph.IsValidOutputTensor(&node, idx), + fn_body->graph.IsValidOutputTensor(node, idx), "Encountered while processing output ", i, " from function '", fn_name, "'"); - TF_RETURN_WITH_CONTEXT_IF_ERROR(ValidateNonRefOutput(&node, idx), + TF_RETURN_WITH_CONTEXT_IF_ERROR(ValidateNonRefOutput(node, idx), "Encountered while creating function '", fn_name, "'"); - output_tensors->emplace_back(&node, idx); + output_tensors->emplace_back(node, idx); } return Status::OK(); } diff --git a/tensorflow/c/eager/BUILD b/tensorflow/c/eager/BUILD index ba3d8533db..c34a84fcfe 100644 --- a/tensorflow/c/eager/BUILD +++ b/tensorflow/c/eager/BUILD @@ -50,6 +50,7 @@ tf_cuda_library( ], "//conditions:default": [], }) + [ + "@com_google_absl//absl/memory", "//tensorflow/core/common_runtime/eager:eager_operation", "//tensorflow/core/distributed_runtime/eager:eager_client", "//tensorflow/core/distributed_runtime/rpc/eager:grpc_eager_client", @@ -143,6 +144,7 @@ tf_cuda_cc_test( "//tensorflow/core:test", "//tensorflow/core:test_main", "//tensorflow/core/distributed_runtime/rpc:grpc_server_lib", + "@com_google_absl//absl/strings", ], ) diff --git a/tensorflow/c/eager/c_api.cc b/tensorflow/c/eager/c_api.cc index 408277468d..027d752f42 100755 --- a/tensorflow/c/eager/c_api.cc +++ b/tensorflow/c/eager/c_api.cc @@ -21,9 +21,11 @@ limitations under the License. #include #include +#include "absl/memory/memory.h" #include "tensorflow/c/c_api.h" #include "tensorflow/c/c_api_internal.h" #include "tensorflow/c/eager/c_api_internal.h" +#include "tensorflow/core/platform/host_info.h" #ifdef TENSORFLOW_EAGER_USE_XLA #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #endif // TENSORFLOW_EAGER_USE_XLA @@ -79,7 +81,7 @@ tensorflow::Status GetAllRemoteDevices( const std::vector& remote_workers, tensorflow::WorkerCacheInterface* worker_cache, std::unique_ptr* device_mgr) { - std::vector remote_devices; + std::vector> remote_devices; tensorflow::Status status; // TODO(nareshmodi) do this in parallel instead of serially. for (const string& remote_worker : remote_workers) { @@ -92,7 +94,7 @@ tensorflow::Status GetAllRemoteDevices( status = s; if (s.ok()) { for (tensorflow::Device* d : *devices) { - remote_devices.push_back(d); + remote_devices.emplace_back(d); } } n.Notify(); @@ -100,7 +102,7 @@ tensorflow::Status GetAllRemoteDevices( n.WaitForNotification(); } std::unique_ptr remote_device_mgr( - new tensorflow::DeviceMgr(remote_devices)); + new tensorflow::DeviceMgr(std::move(remote_devices))); TF_RETURN_IF_ERROR(status); @@ -261,13 +263,13 @@ TF_CAPI_EXPORT extern void TFE_ContextSetAsyncForThread(TFE_Context* ctx, void TFE_DeleteContextOptions(TFE_ContextOptions* options) { delete options; } TFE_Context* TFE_NewContext(const TFE_ContextOptions* opts, TF_Status* status) { - std::vector devices; + std::vector> devices; status->status = tensorflow::DeviceFactory::AddDevices( opts->session_options.options, "/job:localhost/replica:0/task:0", &devices); if (!status->status.ok()) return nullptr; std::unique_ptr device_mgr( - new tensorflow::DeviceMgr(devices)); + new tensorflow::DeviceMgr(std::move(devices))); tensorflow::Rendezvous* r = new tensorflow::IntraProcessRendezvous(device_mgr.get()); @@ -409,6 +411,18 @@ const char* TFE_TensorHandleDeviceName(TFE_TensorHandle* h, TF_Status* status) { : d->name().c_str(); } +const char* TFE_TensorHandleBackingDeviceName(TFE_TensorHandle* h, + TF_Status* status) { + if (h == nullptr || h->handle == nullptr) { + status->status = tensorflow::errors::InvalidArgument( + "The passed in handle is a nullptr"); + return nullptr; + } + tensorflow::Device* d = h->handle->device(); + return (d == nullptr) ? "/job:localhost/replica:0/task:0/device:CPU:0" + : d->name().c_str(); +} + TF_CAPI_EXPORT extern TFE_TensorHandle* TFE_TensorHandleCopySharingTensor( TFE_TensorHandle* h, TF_Status* status) { if (h == nullptr || h->handle == nullptr) { @@ -458,13 +472,20 @@ TFE_Op* TFE_NewOp(TFE_Context* ctx, const char* op_or_function_name, TF_Status* status) { const char* name = op_or_function_name; // Shorthand const tensorflow::AttrTypeMap* types; - status->status = tensorflow::AttrTypeMapForOp(name, &types); - if (status->status.ok()) return new TFE_Op(ctx, name, types); - if (TF_GetCode(status) == TF_NOT_FOUND) { - if (ctx->context.FindFunctionByName(name)) { - status->status = tensorflow::Status::OK(); - return new TFE_Op(ctx, name, nullptr); + bool is_function = false; + status->status = tensorflow::AttrTypeMapForOp(name, &types, &is_function); + if (status->status.ok()) { + if (is_function && !ctx->context.FindFunctionByName(name)) { + status->status = tensorflow::errors::NotFound( + "'", name, + "' is neither a type of a primitive operation nor a name " + "of a function registered in binary running on ", + tensorflow::port::Hostname(), + ". Make sure the operation or function is " + "registered in the binary running in this process."); + return nullptr; } + return new TFE_Op(ctx, name, is_function, types); } return nullptr; } @@ -497,12 +518,6 @@ void TFE_OpAddInput(TFE_Op* op, TFE_TensorHandle* h, TF_Status* status) { TF_AttrType TFE_OpGetAttrType(TFE_Op* op, const char* attr_name, unsigned char* is_list, TF_Status* status) { TF_AttrType ret; - if (op->operation.is_function()) { - status->status = tensorflow::errors::Unimplemented( - "TODO(apassos): Support for attributes for TensorFlow functions is not " - "ready yet."); - return TF_ATTR_INT; // The compiler requires that we return something. - } status->status = tensorflow::AttrTypeByName(*op->operation.AttrTypes(), attr_name, &ret, is_list); return ret; diff --git a/tensorflow/c/eager/c_api.h b/tensorflow/c/eager/c_api.h index b2454d8722..8d6c8d958d 100755 --- a/tensorflow/c/eager/c_api.h +++ b/tensorflow/c/eager/c_api.h @@ -169,10 +169,33 @@ TF_CAPI_EXPORT extern int64_t TFE_TensorHandleNumElements(TFE_TensorHandle* h, TF_CAPI_EXPORT extern int64_t TFE_TensorHandleDim(TFE_TensorHandle* h, int dim_index, TF_Status* status); + +// Returns the device of the operation that produced `h`. +// If `h` was produced by a copy, returns the destination device of +// the copy. Note that returned device name is not always the device +// holding the tensor handle's memory. If you want the latter, use +// TFE_TensorHandleBackingDeviceName. +// This function will block till the operation that produces `h` has completed. +// +// Device on which the kernel of the operation that produced `h` ran. +// +// If `h` was produced by a copy, returns the destination device of +// the copy. +// +// Note that returned device name is not always the device that owns the memory +// that backs the tensor handle. For the latter see +// TFE_TensorHandleBackingDeviceName. +// // This function will block till the operation that produces `h` has completed. TF_CAPI_EXPORT extern const char* TFE_TensorHandleDeviceName( TFE_TensorHandle* h, TF_Status* status); +// Returns the name of the device in whose memory `h` resides. +// +// This function will block till the operation that produces `h` has completed. +TF_CAPI_EXPORT extern const char* TFE_TensorHandleBackingDeviceName( + TFE_TensorHandle* h, TF_Status* status); + // Return a pointer to a new TFE_TensorHandle that shares the underlying tensor // with `h`. On success, `status` is set to OK. On failure, `status` reflects // the error and a nullptr is returned. diff --git a/tensorflow/c/eager/c_api_internal.h b/tensorflow/c/eager/c_api_internal.h index fa1b22e3af..67bc1bcd24 100644 --- a/tensorflow/c/eager/c_api_internal.h +++ b/tensorflow/c/eager/c_api_internal.h @@ -93,10 +93,9 @@ struct TFE_TensorDebugInfo { }; struct TFE_Op { - // t is NULL iff the TFE_Op corresponds to a TensorFlow function instead of a - // primitive operation. - TFE_Op(TFE_Context* ctx, const char* op, const tensorflow::AttrTypeMap* t) - : operation(&ctx->context, op, t) {} + TFE_Op(TFE_Context* ctx, const char* op, bool is_function, + const tensorflow::AttrTypeMap* t) + : operation(&ctx->context, op, is_function, t) {} tensorflow::EagerOperation operation; }; diff --git a/tensorflow/c/eager/c_api_test.cc b/tensorflow/c/eager/c_api_test.cc index 55331022b9..6b39b79ee8 100644 --- a/tensorflow/c/eager/c_api_test.cc +++ b/tensorflow/c/eager/c_api_test.cc @@ -16,6 +16,7 @@ limitations under the License. #include "tensorflow/c/eager/c_api.h" #include +#include "absl/strings/match.h" #include "tensorflow/c/eager/c_api_test_util.h" #include "tensorflow/core/distributed_runtime/rpc/grpc_server_lib.h" #include "tensorflow/core/framework/function.pb.h" @@ -589,9 +590,22 @@ void TensorHandleCopyBetweenTwoGPUDevices(bool async) { TF_DeviceList* devices = TFE_ContextListDevices(ctx, status.get()); ASSERT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); const int num_devices = TF_DeviceListCount(devices); + bool has_gpu0 = false; + bool has_gpu1 = false; + for (int i = 0; i < num_devices; ++i) { + const char* dev = TF_DeviceListName(devices, i, status.get()); + ASSERT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); + string device_name(dev); + if (device_name.find("GPU:0") != string::npos) { + has_gpu0 = true; + } + if (device_name.find("GPU:1") != string::npos) { + has_gpu1 = true; + } + } const char* kCPUDevice = "CPU:0"; - if (num_devices < 3) { + if (!has_gpu0 || !has_gpu1) { TF_DeleteDeviceList(devices); TF_DeleteTensor(t); TFE_DeleteTensorHandle(hcpu); @@ -781,6 +795,14 @@ TEST(CAPI, TensorHandleNullptr) { TF_SetStatus(status.get(), TF_OK, ""); + device_name = TFE_TensorHandleBackingDeviceName(h, status.get()); + ASSERT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(status.get())); + ASSERT_EQ(device_name, nullptr); + ASSERT_EQ("The passed in handle is a nullptr", + string(TF_Message(status.get()))); + + TF_SetStatus(status.get(), TF_OK, ""); + int num_dims = TFE_TensorHandleNumDims(h, status.get()); ASSERT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(status.get())); ASSERT_EQ(num_dims, -1); @@ -796,6 +818,62 @@ TEST(CAPI, TensorHandleNullptr) { string(TF_Message(status.get()))); } +TEST(CAPI, TensorHandleDevices) { + std::unique_ptr status( + TF_NewStatus(), TF_DeleteStatus); + TFE_ContextOptions* opts = TFE_NewContextOptions(); + TFE_Context* ctx = TFE_NewContext(opts, status.get()); + TFE_DeleteContextOptions(opts); + ASSERT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); + + TFE_TensorHandle* hcpu = TestMatrixTensorHandle(); + const char* device_name = TFE_TensorHandleDeviceName(hcpu, status.get()); + ASSERT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); + ASSERT_TRUE(absl::StrContains(device_name, "CPU:0")) << device_name; + const char* backing_device_name = + TFE_TensorHandleBackingDeviceName(hcpu, status.get()); + ASSERT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); + ASSERT_TRUE(absl::StrContains(backing_device_name, "CPU:0")) + << backing_device_name; + + // Disable the test if no GPU is present. + string gpu_device_name; + if (GetDeviceName(ctx, &gpu_device_name, "GPU")) { + TFE_TensorHandle* hgpu = TFE_TensorHandleCopyToDevice( + hcpu, ctx, gpu_device_name.c_str(), status.get()); + ASSERT_TRUE(TF_GetCode(status.get()) == TF_OK) << TF_Message(status.get()); + + TFE_Op* shape_op = ShapeOp(ctx, hgpu); + TFE_OpSetDevice(shape_op, gpu_device_name.c_str(), status.get()); + ASSERT_TRUE(TF_GetCode(status.get()) == TF_OK) << TF_Message(status.get()); + TFE_TensorHandle* retvals[1]; + int num_retvals = 1; + TFE_Execute(shape_op, &retvals[0], &num_retvals, status.get()); + ASSERT_TRUE(TF_GetCode(status.get()) == TF_OK) << TF_Message(status.get()); + + // .device of shape is GPU since the op is executed on GPU + device_name = TFE_TensorHandleDeviceName(retvals[0], status.get()); + ASSERT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); + ASSERT_TRUE(absl::StrContains(device_name, "GPU:0")) << device_name; + + // .backing_device of shape is CPU since the tensor is backed by CPU + backing_device_name = + TFE_TensorHandleBackingDeviceName(retvals[0], status.get()); + ASSERT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); + ASSERT_TRUE(absl::StrContains(backing_device_name, "CPU:0")) + << backing_device_name; + + TFE_DeleteOp(shape_op); + TFE_DeleteTensorHandle(retvals[0]); + TFE_DeleteTensorHandle(hgpu); + } + + TFE_DeleteTensorHandle(hcpu); + TFE_ContextAsyncWait(ctx, status.get()); + EXPECT_EQ(TF_OK, TF_GetCode(status.get())) << TF_Message(status.get()); + TFE_DeleteContext(ctx); +} + void Execute_MatMul_CPU(bool async) { TF_Status* status = TF_NewStatus(); TFE_ContextOptions* opts = TFE_NewContextOptions(); diff --git a/tensorflow/c/eager/c_api_test_util.cc b/tensorflow/c/eager/c_api_test_util.cc index 008f088c2d..bd38127d50 100644 --- a/tensorflow/c/eager/c_api_test_util.cc +++ b/tensorflow/c/eager/c_api_test_util.cc @@ -104,6 +104,19 @@ TFE_Op* MatMulOp(TFE_Context* ctx, TFE_TensorHandle* a, TFE_TensorHandle* b) { return op; } +TFE_Op* ShapeOp(TFE_Context* ctx, TFE_TensorHandle* a) { + TF_Status* status = TF_NewStatus(); + + TFE_Op* op = TFE_NewOp(ctx, "Shape", status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + TFE_OpAddInput(op, a, status); + CHECK_EQ(TF_OK, TF_GetCode(status)) << TF_Message(status); + TF_DeleteStatus(status); + TFE_OpSetAttrType(op, "T", TFE_TensorHandleDataType(a)); + + return op; +} + TFE_TensorHandle* TestAxisTensorHandle() { int64_t dims[] = {1}; int data[] = {1}; diff --git a/tensorflow/c/eager/c_api_test_util.h b/tensorflow/c/eager/c_api_test_util.h index 474cae67c8..75ef9459e9 100644 --- a/tensorflow/c/eager/c_api_test_util.h +++ b/tensorflow/c/eager/c_api_test_util.h @@ -37,6 +37,9 @@ TFE_TensorHandle* TestMatrixTensorHandle3X2(); // Return a matmul op multiplying `a` by `b`. TFE_Op* MatMulOp(TFE_Context* ctx, TFE_TensorHandle* a, TFE_TensorHandle* b); +// Return a shape op fetching the shape of `a`. +TFE_Op* ShapeOp(TFE_Context* ctx, TFE_TensorHandle* a); + // Return an 1-D INT32 tensor containing a single value 1. TFE_TensorHandle* TestAxisTensorHandle(); diff --git a/tensorflow/c/eager/tape.h b/tensorflow/c/eager/tape.h index 5ba55a203f..5c11f51e87 100644 --- a/tensorflow/c/eager/tape.h +++ b/tensorflow/c/eager/tape.h @@ -141,8 +141,9 @@ class GradientTape { // null. The result is populated with one tensor per target element. Status ComputeGradient( const VSpace& vspace, - gtl::ArraySlice target_tensor_ids, - gtl::ArraySlice source_tensor_id, + const gtl::ArraySlice target_tensor_ids, + const gtl::ArraySlice source_tensor_ids, + const gtl::FlatMap sources_that_are_targets, gtl::ArraySlice output_gradients, std::vector* result); @@ -396,6 +397,7 @@ template Status InitialGradients( const VSpace& vspace, gtl::ArraySlice target_tensor_ids, + gtl::FlatMap sources_that_are_targets, gtl::ArraySlice output_gradients, const TensorTape& tensor_tape, const OpTape& op_tape, gtl::FlatMap>* result) { @@ -425,8 +427,13 @@ Status InitialGradients( "none of operations outputs match expected tensor"); } } else { - // No record of the target tensor found on the tape, so no gradient - // needs to be computed from it. Do nothing. + // This target tensor was not generated by any operation recorded on + // the tape, so no gradient needs to be computed from it unless this + // target is also a source. + auto source_tensor = sources_that_are_targets.find(id); + if (source_tensor != sources_that_are_targets.end()) { + (*result)[id].push_back(vspace.Ones(source_tensor->second)); + } } } else { (*result)[id].push_back(output_gradients[i]); @@ -467,8 +474,9 @@ constexpr int kMinAggregateBytes = 128 * 1024 * 1024; template Status GradientTape::ComputeGradient( const VSpace& vspace, - gtl::ArraySlice target_tensor_ids, - gtl::ArraySlice source_tensor_ids, + const gtl::ArraySlice target_tensor_ids, + const gtl::ArraySlice source_tensor_ids, + const gtl::FlatMap sources_that_are_targets, gtl::ArraySlice output_gradients, std::vector* result) { gtl::FlatSet sources_set(source_tensor_ids.begin(), @@ -478,7 +486,8 @@ Status GradientTape::ComputeGradient( std::vector op_stack = InitialStack(state.op_tape, state.op_missing_tensor); gtl::FlatMap> gradients; - Status s = InitialGradients(vspace, target_tensor_ids, output_gradients, + Status s = InitialGradients(vspace, target_tensor_ids, + sources_that_are_targets, output_gradients, tensor_tape_, state.op_tape, &gradients); auto cleanup = [this, &state]() { if (!persistent_) { diff --git a/tensorflow/c/kernels.cc b/tensorflow/c/kernels.cc new file mode 100644 index 0000000000..3caa5bcb03 --- /dev/null +++ b/tensorflow/c/kernels.cc @@ -0,0 +1,143 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "tensorflow/c/c_api_internal.h" +#include "tensorflow/c/kernels.h" +#include "tensorflow/core/framework/kernel_def_builder.h" +#include "tensorflow/core/framework/op_kernel.h" + +// This file forms the basis of a stable ABI for third-party kernel +// implementations. It is crucial that changes to this file are made cautiously +// and with a focus on maintaining both source and binary compatibility. + +struct TF_KernelBuilder { + ::tensorflow::KernelDefBuilder* cc_builder; + + void* (*create_function)(TF_OpKernelConstruction*); + void (*compute_function)(void*, TF_OpKernelContext*); + void (*delete_function)(void*); +}; + +TF_KernelBuilder* TF_NewKernelBuilder( + const char* op_name, const char* device_name, + void* (*create_func)(TF_OpKernelConstruction*), + void (*compute_func)(void*, TF_OpKernelContext*), + void (*delete_func)(void*)) { + TF_KernelBuilder* result = new TF_KernelBuilder; + result->cc_builder = new ::tensorflow::KernelDefBuilder(op_name); + result->cc_builder->Device(device_name); + result->create_function = create_func; + result->compute_function = compute_func; + result->delete_function = delete_func; + return result; +} + +void TF_DeleteKernelBuilder(TF_KernelBuilder* builder) { + DCHECK_NE(builder, nullptr); + delete builder->cc_builder; + delete builder; +} + +namespace tensorflow { +namespace { + +// An OpKernel whose methods delegate to C function pointers. +class COpKernel : public OpKernel { + public: + explicit COpKernel(OpKernelConstruction* ctx, + void* (*create_func)(TF_OpKernelConstruction*), + void (*compute_func)(void*, TF_OpKernelContext*), + void (*delete_func)(void*)) + : OpKernel(ctx), compute_func_(compute_func), delete_func_(delete_func) { + if (create_func != nullptr) { + c_kernel_ = + (*create_func)(reinterpret_cast(ctx)); + } else { + c_kernel_ = nullptr; + } + } + + void Compute(OpKernelContext* ctx) override { + (*compute_func_)(c_kernel_, reinterpret_cast(ctx)); + } + + ~COpKernel() override { + if (delete_func_ != nullptr) { + (*delete_func_)(c_kernel_); + } + } + + private: + void (*compute_func_)(void*, TF_OpKernelContext* context); + void (*delete_func_)(void*); + void* c_kernel_; +}; + +// A KernelFactory that returns COpKernel instances. +class KernelBuilderFactory + : public ::tensorflow::kernel_factory::OpKernelFactory { + public: + explicit KernelBuilderFactory(TF_KernelBuilder* builder) + : builder_(builder) {} + ::tensorflow::OpKernel* Create( + ::tensorflow::OpKernelConstruction* context) override { + return new ::tensorflow::COpKernel(context, builder_->create_function, + builder_->compute_function, + builder_->delete_function); + } + ~KernelBuilderFactory() override { TF_DeleteKernelBuilder(builder_); } + + private: + TF_KernelBuilder* builder_; +}; +} // namespace +} // namespace tensorflow + +void TF_RegisterKernelBuilder(const char* name, TF_KernelBuilder* builder, + TF_Status* status) { + using tensorflow::register_kernel::Name; + + tensorflow::kernel_factory::OpKernelRegistrar( + builder->cc_builder->Build(), name, + absl::make_unique(builder)); + + TF_SetStatus(status, TF_OK, ""); +} + +int TF_NumInputs(TF_OpKernelContext* ctx) { + auto* cc_ctx = reinterpret_cast<::tensorflow::OpKernelContext*>(ctx); + return cc_ctx->num_inputs(); +} + +int TF_NumOutputs(TF_OpKernelContext* ctx) { + auto* cc_ctx = reinterpret_cast<::tensorflow::OpKernelContext*>(ctx); + return cc_ctx->num_outputs(); +} + +void TF_GetInput(TF_OpKernelContext* ctx, int i, TF_Tensor** tensor, + TF_Status* status) { + auto* cc_ctx = reinterpret_cast<::tensorflow::OpKernelContext*>(ctx); + if (i < 0 || i >= cc_ctx->num_inputs()) { + TF_SetStatus(status, TF_OUT_OF_RANGE, "input index out of range"); + return; + } + const ::tensorflow::Tensor& cc_tensor(cc_ctx->input(i)); + TF_Tensor* result = ::tensorflow::TF_TensorFromTensor(cc_tensor, status); + if (TF_GetCode(status) == TF_OK) { + *tensor = result; + } +} diff --git a/tensorflow/c/kernels.h b/tensorflow/c/kernels.h new file mode 100644 index 0000000000..d7778829bc --- /dev/null +++ b/tensorflow/c/kernels.h @@ -0,0 +1,110 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_C_KERNELS_H_ +#define TENSORFLOW_C_KERNELS_H_ + +#include "tensorflow/c/c_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// -------------------------------------------------------------------------- +// C API for TensorFlow Kernels. +// +// This API allows developers to register custom kernel implementations for +// TensorFlow. +// +// See c_api.h header comments for a discussion about API conventions. +// +// Users wishing to extend TensorFlow with new kernels will call +// `TF_NewKernelBuilder`. The resulting kernel builder can be registered with +// `TF_RegisterKernelBuilder`, which will allow TF to construct user-provided +// kernels when necessary. + +struct TF_KernelBuilder; +struct TF_OpKernelConstruction; +struct TF_OpKernelContext; + +// Allocates a new kernel builder and returns a pointer to it. +// +// If non-null, TensorFlow will call create_func when it needs to instantiate +// the kernel. The pointer returned by create_func will be passed to +// compute_func and delete_func, thereby functioning as a "this" pointer for +// referring to kernel instances. +// +// The TF_OpKernelConstruction pointer passed to create_func is owned by +// TensorFlow and will be deleted once create_func returns. It must not be used +// after this. +// +// When TensorFlow needs to perform a computation with this kernel, it will +// call compute_func. This function will receive the pointer returned by +// create_func (or null if no create_func was provided), along with the inputs +// to the computation. +// +// The TF_OpKernelContext pointer received by compute_func is owned by +// TensorFlow and will be deleted once compute_func returns. It must not be used +// after this. +// +// Finally, when TensorFlow no longer needs the kernel, it will call +// delete_func if one is provided. This function will receive the pointer +// returned in `create_func` or nullptr if no `create_func` was provided. +// +// The caller should pass the result of this function to +// TF_RegisterKernelBuilder, which will take ownership of the pointer. If, for +// some reason, the kernel builder will not be registered, the caller should +// delete it with TF_DeleteKernelBuilder. +TF_CAPI_EXPORT extern TF_KernelBuilder* TF_NewKernelBuilder( + const char* op_name, const char* device_name, + void* (*create_func)(TF_OpKernelConstruction*), + void (*compute_func)(void*, TF_OpKernelContext*), + void (*delete_func)(void*)); + +// Register the given kernel builder with the TensorFlow runtime. If +// registration fails, the given status will be populated. +// +// This call takes ownership of the `builder` pointer. +TF_CAPI_EXPORT extern void TF_RegisterKernelBuilder(const char* kernel_name, + TF_KernelBuilder* builder, + TF_Status* status); + +// Deletes the given TF_KernelBuilder. This should be called only if the kernel +// builder is not registered with TensorFlow via TF_RegisterKernelBuilder. +TF_CAPI_EXPORT extern void TF_DeleteKernelBuilder(TF_KernelBuilder* builder); + +// -------------------------------------------------------------------------- +// OpKernelContext routines + +// TF_NumInputs returns the number of inputs available in ctx. +TF_CAPI_EXPORT extern int TF_NumInputs(TF_OpKernelContext* ctx); + +// TF_NumOutputs returns the number of outputs to be placed in *ctx by the +// kernel. +TF_CAPI_EXPORT extern int TF_NumOutputs(TF_OpKernelContext* ctx); + +// Retrieves the ith input from ctx. If TF_GetCode(status) is TF_OK, *tensor is +// populated and its ownership is passed to the caller. In any other case, +// *tensor is not modified. +// +// If i < 0 or i >= TF_NumInputs(ctx), *status is set to TF_OUT_OF_RANGE. +TF_CAPI_EXPORT extern void TF_GetInput(TF_OpKernelContext* ctx, int i, + TF_Tensor** tensor, TF_Status* status); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // TENSORFLOW_C_KERNELS_H_ diff --git a/tensorflow/c/kernels_test.cc b/tensorflow/c/kernels_test.cc new file mode 100644 index 0000000000..80bf12c096 --- /dev/null +++ b/tensorflow/c/kernels_test.cc @@ -0,0 +1,194 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/c/kernels.h" + +#include "tensorflow/c/c_api.h" +#include "tensorflow/core/framework/kernel_def.pb.h" +#include "tensorflow/core/framework/node_def.pb_text.h" +#include "tensorflow/core/framework/op.h" +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/types.h" +#include "tensorflow/core/lib/core/status_test_util.h" +#include "tensorflow/core/platform/test.h" + +struct MyCustomKernel { + bool created; + bool compute_called; +}; + +static bool delete_called = false; + +static void* MyCreateFunc(TF_OpKernelConstruction* ctx) { + struct MyCustomKernel* s = new struct MyCustomKernel; + s->created = true; + s->compute_called = false; + return s; +} + +static void MyComputeFunc(void* kernel, TF_OpKernelContext* ctx) { + struct MyCustomKernel* s = static_cast(kernel); + s->compute_called = true; +} + +static void MyDeleteFunc(void* kernel) { + struct MyCustomKernel* s = static_cast(kernel); + EXPECT_TRUE(s->created); + EXPECT_TRUE(s->compute_called); + delete_called = true; + delete s; +} + +namespace tensorflow { + +static std::unique_ptr GetFakeKernel(const char* device_name, + const char* op_name, + Status* status) { + NodeDef def; + def.set_op(op_name); + def.set_device(device_name); + def.add_input("input1"); + def.add_input("input2"); + return CreateOpKernel(DeviceType(device_name), nullptr, nullptr, def, 1, + status); +} + +// Tests registration of a single C kernel and checks that calls through the +// C/C++ boundary are being made. +TEST(TestKernel, TestRegisterKernelBuilder) { + const char* kernel_name = "SomeKernelName"; + const char* op_name = "FooOp"; + const char* device_name = "FakeDeviceName1"; + + REGISTER_OP(op_name) + .Input("input1: double") + .Input("input2: uint8") + .Output("output1: uint8"); + + TF_KernelBuilder* builder = TF_NewKernelBuilder( + op_name, device_name, &MyCreateFunc, &MyComputeFunc, &MyDeleteFunc); + + { + TF_Status* status = TF_NewStatus(); + TF_RegisterKernelBuilder(kernel_name, builder, status); + EXPECT_EQ(TF_OK, TF_GetCode(status)); + TF_Buffer* buf = TF_GetRegisteredKernelsForOp(op_name, status); + EXPECT_EQ(TF_OK, TF_GetCode(status)); + KernelList list; + list.ParseFromArray(buf->data, buf->length); + ASSERT_EQ(1, list.kernel_size()); + ASSERT_EQ(device_name, list.kernel(0).device_type()); + TF_DeleteBuffer(buf); + TF_DeleteStatus(status); + } + + { + Status status; + std::unique_ptr kernel = + GetFakeKernel(device_name, op_name, &status); + TF_EXPECT_OK(status); + ASSERT_NE(nullptr, kernel.get()); + kernel->Compute(nullptr); + } + + ASSERT_TRUE(delete_called); +} + +class DummyDevice : public DeviceBase { + public: + DummyDevice(Env* env, bool save) : DeviceBase(env), save_(save) {} + bool RequiresRecordingAccessedTensors() const override { return save_; } + Allocator* GetAllocator(AllocatorAttributes /*attr*/) override { + return cpu_allocator(); + } + + private: + bool save_; +}; + +TEST(TestKernel, TestInputAndOutputCount) { + const char* kernel_name = "InputOutputCounterKernel"; + const char* op_name = "BarOp"; + const char* device_name = "FakeDeviceName2"; + + REGISTER_OP(op_name) + .Input("input1: double") + .Input("input2: uint8") + .Output("output1: uint8"); + + static int num_inputs = 0; + static int num_outputs = 0; + + // A kernel whose Compute function has a side-effect of updating num_inputs + // and num_outputs. Various functions on TF_OpKernelContext are also + // exercised. + auto my_compute_func = [](void* kernel, TF_OpKernelContext* ctx) { + num_inputs = TF_NumInputs(ctx); + num_outputs = TF_NumOutputs(ctx); + + TF_Tensor* input = nullptr; + TF_Status* s = TF_NewStatus(); + TF_GetInput(ctx, 0, &input, s); + EXPECT_EQ(TF_OK, TF_GetCode(s)) << "Failed to get input: " << TF_Message(s); + EXPECT_EQ(123, *static_cast(TF_TensorData(input))); + TF_GetInput(ctx, -1, &input, s); + EXPECT_EQ(TF_OUT_OF_RANGE, TF_GetCode(s)); + TF_GetInput(ctx, 3, &input, s); + EXPECT_EQ(TF_OUT_OF_RANGE, TF_GetCode(s)); + TF_DeleteStatus(s); + if (input != nullptr) { + TF_DeleteTensor(input); + } + }; + + TF_KernelBuilder* builder = TF_NewKernelBuilder(op_name, device_name, nullptr, + my_compute_func, nullptr); + + { + TF_Status* status = TF_NewStatus(); + TF_RegisterKernelBuilder(kernel_name, builder, status); + EXPECT_EQ(TF_OK, TF_GetCode(status)); + TF_DeleteStatus(status); + } + + { + OpKernelContext::Params p; + DummyDevice dummy_device(nullptr, false); + p.device = &dummy_device; + + Tensor t(tensorflow::uint8(123)); + + gtl::InlinedVector inputs; + // Simulate 2 inputs + inputs.emplace_back(&t); + inputs.emplace_back(); + p.inputs = &inputs; + + Status status; + std::unique_ptr kernel = + GetFakeKernel(device_name, op_name, &status); + TF_EXPECT_OK(status); + ASSERT_NE(nullptr, kernel.get()); + + p.op_kernel = kernel.get(); + OpKernelContext ctx(&p); + kernel->Compute(&ctx); + + ASSERT_EQ(2, num_inputs); + ASSERT_EQ(1, num_outputs); + } +} + +} // namespace tensorflow diff --git a/tensorflow/c/python_api.cc b/tensorflow/c/python_api.cc index 247236b760..98d8393332 100644 --- a/tensorflow/c/python_api.cc +++ b/tensorflow/c/python_api.cc @@ -160,4 +160,17 @@ void SetHandleShapeAndType(TF_Graph* graph, TF_Output output, const void* proto, ic->set_output_handle_shapes_and_types(output.index, shapes_and_types); } +void AddWhileInputHack(TF_Graph* graph, TF_Output new_src, TF_Operation* dst, + TF_Status* status) { + mutex_lock l(graph->mu); + status->status = graph->graph.AddWhileInputHack(&new_src.oper->node, + new_src.index, &dst->node); + if (status->status.ok()) { + // This modification only updates the destination node for + // the purposes of running this graph in a session. Thus, we don't + // record the source node as being modified. + RecordMutation(graph, *dst, "adding input tensor"); + } +} + } // namespace tensorflow diff --git a/tensorflow/c/python_api.h b/tensorflow/c/python_api.h index 5cce84020b..44779ca656 100644 --- a/tensorflow/c/python_api.h +++ b/tensorflow/c/python_api.h @@ -34,6 +34,7 @@ void SetAttr(TF_Graph* graph, TF_Operation* op, const char* attr_name, void SetRequestedDevice(TF_Graph* graph, TF_Operation* op, const char* device); +// Updates 'dst' to consume 'new_src'. void UpdateEdge(TF_Graph* graph, TF_Output new_src, TF_Input dst, TF_Status* status); @@ -65,6 +66,13 @@ std::string GetHandleShapeAndType(TF_Graph* graph, TF_Output output); // because I couldn't get SWIG to work otherwise. void SetHandleShapeAndType(TF_Graph* graph, TF_Output output, const void* proto, size_t proto_len, TF_Status* status); + +// This method is used to add a new input edge to 'dst', which must be a While +// op. The While op's "T" attribute must have already been updated to include +// the new edge. This is used to construct tf.while_loop gradients. +void AddWhileInputHack(TF_Graph* graph, TF_Output new_src, TF_Operation* dst, + TF_Status* status); + } // namespace tensorflow #endif // TENSORFLOW_C_PYTHON_API_H_ diff --git a/tensorflow/cc/BUILD b/tensorflow/cc/BUILD index 83353b79f7..a09becc49b 100644 --- a/tensorflow/cc/BUILD +++ b/tensorflow/cc/BUILD @@ -489,6 +489,7 @@ tf_gen_op_wrappers_cc( "image_ops", "io_ops", "linalg_ops", + "list_ops", "logging_ops", "lookup_ops", "manip_ops", diff --git a/tensorflow/cc/saved_model/BUILD b/tensorflow/cc/saved_model/BUILD index 3d3895c8fa..52345a376c 100644 --- a/tensorflow/cc/saved_model/BUILD +++ b/tensorflow/cc/saved_model/BUILD @@ -133,5 +133,6 @@ filegroup( "testdata/half_plus_two_pbtxt/**", "testdata/half_plus_two_main_op/**", "testdata/half_plus_two/**", + "testdata/half_plus_two_v2/**", ]), ) diff --git a/tensorflow/cc/saved_model/constants.h b/tensorflow/cc/saved_model/constants.h index 645a3f101d..6f00dc324b 100644 --- a/tensorflow/cc/saved_model/constants.h +++ b/tensorflow/cc/saved_model/constants.h @@ -33,10 +33,10 @@ constexpr char kSavedModelFilenamePb[] = "saved_model.pb"; /// SavedModel text format proto filename. constexpr char kSavedModelFilenamePbTxt[] = "saved_model.pbtxt"; -/// SavedModel legacy init op key. +/// SavedModel legacy init op collection key. Used in v1 SavedModels. constexpr char kSavedModelLegacyInitOpKey[] = "legacy_init_op"; -/// SavedModel main op key. +/// SavedModel main op collection key. Used in v1 SavedModels. constexpr char kSavedModelMainOpKey[] = "saved_model_main_op"; /// Directory in which to save the SavedModel variables. @@ -45,6 +45,11 @@ constexpr char kSavedModelVariablesDirectory[] = "variables"; /// SavedModel variables filename. constexpr char kSavedModelVariablesFilename[] = "variables"; +/// SavedModel SignatureDef keys for the initialization and train ops. Used in +/// V2 SavedModels. +constexpr char kSavedModelInitOpSignatureKey[] = "__saved_model_init_op"; +constexpr char kSavedModelTrainOpSignatureKey[] = "__saved_model_train_op"; + } // namespace tensorflow #endif // TENSORFLOW_CC_SAVED_MODEL_CONSTANTS_H_ diff --git a/tensorflow/cc/saved_model/loader.cc b/tensorflow/cc/saved_model/loader.cc index c6abe2f41b..85d3dd01fa 100644 --- a/tensorflow/cc/saved_model/loader.cc +++ b/tensorflow/cc/saved_model/loader.cc @@ -122,34 +122,54 @@ Status RunOnce(const RunOptions& run_options, return run_status; } -bool HasMainOp(const MetaGraphDef& meta_graph_def) { +// RunInitOp will return OK if the initialization op was run successfully. +// An empty init_op_name indicates that there are no init ops to run. +Status RunInitOp(const RunOptions& run_options, const string& export_dir, + const MetaGraphDef& meta_graph_def, + const std::vector& asset_file_defs, + Session* session, const string& init_op_name) { + if (!init_op_name.empty()) { + LOG(INFO) << "Running initialization op on SavedModel bundle."; + std::vector> inputs; + AddAssetsTensorsToInputs(export_dir, asset_file_defs, &inputs); + RunMetadata run_metadata; + return RunOnce(run_options, inputs, {}, {init_op_name}, + nullptr /* outputs */, &run_metadata, session); + } + return Status::OK(); +} + +// A SavedModel may store the name of the initialization op to run in the +// in the SignatureDef (v2) or a collection (v1). If an init_op collection +// exists, then the collection must contain exactly one op. +Status GetInitOp(const string& export_dir, const MetaGraphDef& meta_graph_def, + string* init_op_name) { + const auto& sig_def_map = meta_graph_def.signature_def(); + const auto& init_op_sig_it = + meta_graph_def.signature_def().find(kSavedModelInitOpSignatureKey); + if (init_op_sig_it != sig_def_map.end()) { + *init_op_name = init_op_sig_it->second.outputs() + .find(kSavedModelInitOpSignatureKey) + ->second.name(); + return Status::OK(); + } + const auto& collection_def_map = meta_graph_def.collection_def(); + string init_op_collection_key; if (collection_def_map.find(kSavedModelMainOpKey) != collection_def_map.end()) { - return true; + init_op_collection_key = kSavedModelMainOpKey; + } else { + init_op_collection_key = kSavedModelLegacyInitOpKey; } - return false; -} -Status RunMainOp(const RunOptions& run_options, const string& export_dir, - const MetaGraphDef& meta_graph_def, - const std::vector& asset_file_defs, - Session* session, const string& main_op_key) { - LOG(INFO) << "Running MainOp with key " << main_op_key - << " on SavedModel bundle."; - const auto& collection_def_map = meta_graph_def.collection_def(); - const auto main_op_it = collection_def_map.find(main_op_key); - if (main_op_it != collection_def_map.end()) { - if (main_op_it->second.node_list().value_size() != 1) { + const auto init_op_it = collection_def_map.find(init_op_collection_key); + if (init_op_it != collection_def_map.end()) { + if (init_op_it->second.node_list().value_size() != 1) { return errors::FailedPrecondition( strings::StrCat("Expected exactly one main op in : ", export_dir)); } - std::vector> inputs; - AddAssetsTensorsToInputs(export_dir, asset_file_defs, &inputs); - RunMetadata run_metadata; - const StringPiece main_op_name = main_op_it->second.node_list().value(0); - return RunOnce(run_options, inputs, {}, {string(main_op_name)}, - nullptr /* outputs */, &run_metadata, session); + *init_op_name = init_op_it->second.node_list().value(0); } return Status::OK(); } @@ -193,6 +213,15 @@ Status RunRestore(const RunOptions& run_options, const string& export_dir, Status GetAssetFileDefs(const MetaGraphDef& meta_graph_def, std::vector* asset_file_defs) { + // With SavedModel v2, we write asset file def into metagraph instead of + // collection, so read from metagraph first. + if (meta_graph_def.asset_file_def_size() > 0) { + for (const auto& asset : meta_graph_def.asset_file_def()) { + asset_file_defs->push_back(asset); + } + return Status::OK(); + } + // Fall back to read from collection to be backward compatible with v1. const auto& collection_def_map = meta_graph_def.collection_def(); const auto assets_it = collection_def_map.find(kSavedModelAssetsKey); if (assets_it == collection_def_map.end()) { @@ -227,15 +256,12 @@ Status LoadSavedModelInternal(const SessionOptions& session_options, bundle->meta_graph_def.saver_def().restore_op_name(), bundle->meta_graph_def.saver_def().filename_tensor_name(), asset_file_defs, bundle->session.get())); - if (HasMainOp(bundle->meta_graph_def)) { - TF_RETURN_IF_ERROR(RunMainOp(run_options, export_dir, - bundle->meta_graph_def, asset_file_defs, - bundle->session.get(), kSavedModelMainOpKey)); - } else { - TF_RETURN_IF_ERROR(RunMainOp( - run_options, export_dir, bundle->meta_graph_def, asset_file_defs, - bundle->session.get(), kSavedModelLegacyInitOpKey)); - } + string init_op_name; + TF_RETURN_IF_ERROR( + GetInitOp(export_dir, bundle->meta_graph_def, &init_op_name)); + TF_RETURN_IF_ERROR(RunInitOp(run_options, export_dir, bundle->meta_graph_def, + asset_file_defs, bundle->session.get(), + init_op_name)); return Status::OK(); } diff --git a/tensorflow/cc/saved_model/loader_test.cc b/tensorflow/cc/saved_model/loader_test.cc index 72b8bc1871..597e42bb65 100644 --- a/tensorflow/cc/saved_model/loader_test.cc +++ b/tensorflow/cc/saved_model/loader_test.cc @@ -36,6 +36,8 @@ constexpr char kTestDataMainOp[] = "cc/saved_model/testdata/half_plus_two_main_op/00000123"; constexpr char kTestDataSharded[] = "cc/saved_model/testdata/half_plus_two/00000123"; +constexpr char kTestDataInitOpV2[] = + "cc/saved_model/testdata/half_plus_two_v2/00000123"; class LoaderTest : public ::testing::Test { protected: @@ -227,5 +229,17 @@ TEST_F(LoaderTest, MaybeSavedModelDirectory) { EXPECT_FALSE(MaybeSavedModelDirectory(invalid_export_dir)); } +TEST_F(LoaderTest, SavedModelInitOpV2Format) { + SavedModelBundle bundle; + SessionOptions session_options; + RunOptions run_options; + + const string export_dir = + io::JoinPath(testing::TensorFlowSrcRoot(), kTestDataInitOpV2); + TF_ASSERT_OK(LoadSavedModel(session_options, run_options, export_dir, + {kSavedModelTagServe}, &bundle)); + CheckSavedModelBundle(export_dir, bundle); +} + } // namespace } // namespace tensorflow diff --git a/tensorflow/cc/saved_model/testdata/half_plus_two_v2/00000123/assets/foo.txt b/tensorflow/cc/saved_model/testdata/half_plus_two_v2/00000123/assets/foo.txt new file mode 100644 index 0000000000..f9ff036688 --- /dev/null +++ b/tensorflow/cc/saved_model/testdata/half_plus_two_v2/00000123/assets/foo.txt @@ -0,0 +1 @@ +asset-file-contents \ No newline at end of file diff --git a/tensorflow/cc/saved_model/testdata/half_plus_two_v2/00000123/saved_model.pb b/tensorflow/cc/saved_model/testdata/half_plus_two_v2/00000123/saved_model.pb new file mode 100644 index 0000000000000000000000000000000000000000..a10bbf8fb6bca0fcee6414b2927d2f706de85ebc GIT binary patch literal 10774 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 rewrites; - TF_RETURN_IF_ERROR(AddRewritesForShape(i, ps.parameters(i), &rewrites)); + TF_RETURN_IF_ERROR( + AddRewritesForShape(i, xla::Shape(ps.parameters(i)), &rewrites)); const string code = R"( - void set_arg{{NAME}}_data(void* data) { + void set_arg{{NAME}}_data(const void* data) { set_arg_data({{I}}, data); } {{TYPE}}* arg{{NAME}}_data() { @@ -204,7 +206,7 @@ Status GenArgMethods(const tf2xla::Config& config, const xla::ProgramShape& ps, // Generate methods for results (outputs). Status GenResultMethods(const tf2xla::Config& config, - const xla::ProgramShape& ps, string* methods) { + const xla::ProgramShapeProto& ps, string* methods) { if (ps.result().element_type() != xla::TUPLE) { // The XlaCompiler we use to build the xla computation always generates a // tuple result, and we rely on this to simplify code generation. @@ -217,8 +219,8 @@ Status GenResultMethods(const tf2xla::Config& config, } for (int i = 0; i < ps.result().tuple_shapes_size(); ++i) { std::vector> rewrites; - TF_RETURN_IF_ERROR( - AddRewritesForShape(i, ps.result().tuple_shapes(i), &rewrites)); + TF_RETURN_IF_ERROR(AddRewritesForShape( + i, xla::Shape(ps.result().tuple_shapes(i)), &rewrites)); string code = R"( {{TYPE}}* result{{NAME}}_data() { return static_cast<{{TYPE}}*>(result_data({{I}})); @@ -336,7 +338,7 @@ Status GenerateHeader(const CodegenOpts& opts, const tf2xla::Config& config, ExtractEntryParamBufferInfos(buffer_infos); std::vector buffer_infos_for_temps = ExtractTempBufferInfos(buffer_infos); - const xla::ProgramShape& ps = compile_result.program_shape; + const xla::ProgramShapeProto& ps = compile_result.program_shape; string methods_arg, methods_result; TF_RETURN_IF_ERROR(GenArgMethods(config, ps, compile_result, &methods_arg)); TF_RETURN_IF_ERROR(GenResultMethods(config, ps, &methods_result)); @@ -548,8 +550,8 @@ class {{CLASS}} : public tensorflow::XlaCompiledCpuFunction { static const char** StaticResultNames() {{RESULT_NAMES_CODE}} // Shape of the args and results. - static const xla::ProgramShape* StaticProgramShape() { - static const xla::ProgramShape* kShape = {{PROGRAM_SHAPE_SHIM_EXPRESSION}}; + static const xla::ProgramShapeProto* StaticProgramShape() { + static const xla::ProgramShapeProto* kShape = {{PROGRAM_SHAPE_SHIM_EXPRESSION}}; return kShape; } @@ -587,7 +589,7 @@ class {{CLASS}} : public tensorflow::XlaCompiledCpuFunction { {"{{METHODS_RESULT}}\n", methods_result}, {"{{NS_END}}\n", ns_end}, {"{{NS_START}}\n", ns_start}, - {"{{PROGRAM_SHAPE}}", xla::ShapeUtil::HumanString(ps)}, + {"{{PROGRAM_SHAPE}}", xla::ShapeUtil::HumanString(xla::ProgramShape(ps))}, {"{{PROGRAM_SHAPE_SHIM_EXPRESSION}}", metadata_result.program_shape_access_shim}, {"{{RESULT_INDEX}}", absl::StrCat(result_index)}, @@ -615,11 +617,11 @@ static string CreateUniqueIdentifier(const CodegenOpts& opts, Status GenerateMetadata(const CodegenOpts& opts, const CompileResult& compile_result, MetadataResult* metadata_result) { - std::unique_ptr program_shape; + std::unique_ptr program_shape; if (opts.gen_program_shape) { program_shape = - absl::make_unique(compile_result.program_shape); + absl::make_unique(compile_result.program_shape); // The parameter names are currently meaningless, and redundant with the // rest of our metadata, so clear them out to avoid confusion and save @@ -631,8 +633,8 @@ Status GenerateMetadata(const CodegenOpts& opts, // a shim that evaluates to nullptr, which is what we want. ProtobufToEmbed program_shape_protobuf{ - CreateUniqueIdentifier(opts, "ProgramShape"), "xla::ProgramShape", - program_shape.get()}; + CreateUniqueIdentifier(opts, "ProgramShapeProto"), + "xla::ProgramShapeProto", program_shape.get()}; ProtobufToEmbed hlo_profile_printer_data_protobuf{ CreateUniqueIdentifier(opts, "HloProfilePrinterData"), diff --git a/tensorflow/compiler/aot/codegen.h b/tensorflow/compiler/aot/codegen.h index 90410c46a8..9485e86b10 100644 --- a/tensorflow/compiler/aot/codegen.h +++ b/tensorflow/compiler/aot/codegen.h @@ -57,7 +57,7 @@ struct MetadataResult { std::vector header_variable_decls; // program_shape_access_shim is a C++ expression that constructs the - // xla::ProgramShape instance for the CompileResult passed to + // xla::ProgramShapeProto instance for the CompileResult passed to // GenerateMetadata. string program_shape_access_shim; diff --git a/tensorflow/compiler/aot/codegen_test.cc b/tensorflow/compiler/aot/codegen_test.cc index bb288d2300..c1788ca32a 100644 --- a/tensorflow/compiler/aot/codegen_test.cc +++ b/tensorflow/compiler/aot/codegen_test.cc @@ -181,13 +181,15 @@ TEST(CodegenTest, Golden) { BufferInfo::MakeEntryParameter(/*size=*/96, /*param_number=*/1), BufferInfo::MakeTempBuffer(3), BufferInfo::MakeTempBuffer(120)}, 5, {})); - compile_result.program_shape = xla::ShapeUtil::MakeProgramShape( - { - xla::ShapeUtil::MakeShape(xla::F32, {1, 2}), - xla::ShapeUtil::MakeShape(xla::S64, {3, 4}), - }, - xla::ShapeUtil::MakeTupleShape( - {xla::ShapeUtil::MakeShape(xla::U32, {5, 6})})); + compile_result.program_shape = + xla::ShapeUtil::MakeProgramShape( + { + xla::ShapeUtil::MakeShape(xla::F32, {1, 2}), + xla::ShapeUtil::MakeShape(xla::S64, {3, 4}), + }, + xla::ShapeUtil::MakeTupleShape( + {xla::ShapeUtil::MakeShape(xla::U32, {5, 6})})) + .ToProto(); compile_result.entry_point = "entry_point"; compile_result.pointer_size = 8; diff --git a/tensorflow/compiler/aot/codegen_test_h.golden b/tensorflow/compiler/aot/codegen_test_h.golden index e4d8a02877..968afad65e 100644 --- a/tensorflow/compiler/aot/codegen_test_h.golden +++ b/tensorflow/compiler/aot/codegen_test_h.golden @@ -22,7 +22,7 @@ extern "C" void entry_point( void* result, const xla::ExecutableRunOptions* run_options, const void** args, void** temps, tensorflow::int64* profile_counters); -extern "C" char __tfcompile_foo_bar_MyClass_ProgramShape_protobuf_array_contents[]; +extern "C" char __tfcompile_foo_bar_MyClass_ProgramShapeProto_protobuf_array_contents[]; namespace foo { @@ -114,7 +114,7 @@ class MyClass : public tensorflow::XlaCompiledCpuFunction { // with dim indices specifying which value. No bounds checking is performed // on dim indices. - void set_arg0_data(void* data) { + void set_arg0_data(const void* data) { set_arg_data(0, data); } float* arg0_data() { @@ -132,7 +132,7 @@ class MyClass : public tensorflow::XlaCompiledCpuFunction { arg_data(0)))[dim0][dim1]; } - void set_arg_myfeed_data(void* data) { + void set_arg_myfeed_data(const void* data) { set_arg_data(0, data); } float* arg_myfeed_data() { @@ -150,7 +150,7 @@ class MyClass : public tensorflow::XlaCompiledCpuFunction { arg_data(0)))[dim0][dim1]; } - void set_arg1_data(void* data) { + void set_arg1_data(const void* data) { set_arg_data(1, data); } tensorflow::int64* arg1_data() { @@ -253,10 +253,10 @@ class MyClass : public tensorflow::XlaCompiledCpuFunction { } // Shape of the args and results. - static const xla::ProgramShape* StaticProgramShape() { - static const xla::ProgramShape* kShape = []() { - xla::ProgramShape* proto = new xla::ProgramShape; - proto->ParseFromArray(&__tfcompile_foo_bar_MyClass_ProgramShape_protobuf_array_contents[0], 52); + static const xla::ProgramShapeProto* StaticProgramShape() { + static const xla::ProgramShapeProto* kShape = []() { + xla::ProgramShapeProto* proto = new xla::ProgramShapeProto; + proto->ParseFromArray(&__tfcompile_foo_bar_MyClass_ProgramShapeProto_protobuf_array_contents[0], 52); return proto; }(); return kShape; diff --git a/tensorflow/compiler/aot/codegen_test_o.golden b/tensorflow/compiler/aot/codegen_test_o.golden index eb001c5d45bdfefc76629d7303d89f5480432235..ce8e5ec8c96a2c3696f14b8eea206d648182ecb5 100644 GIT binary patch delta 82 zcmX@XdVzI<24lcP&2+}ti4)^k1B&uX@+ZEZ$-%(DP{hE%z&tsSQF!tKMh?cV$txM- g8Ji|^GTF2GGB7YOf@KnzG+3(`7#Ntqyah}e0OJr9Qvd(} delta 49 zcmcb>dV+O=2BXJB&2+|yi4)@{ewoRbJ9#3bJY(zRjg0Y(wUY&z>=`{K2Qt|+mQJ3? GWDfwepb$g= diff --git a/tensorflow/compiler/aot/compile.cc b/tensorflow/compiler/aot/compile.cc index 2b5f97b34c..9fc223bdc7 100644 --- a/tensorflow/compiler/aot/compile.cc +++ b/tensorflow/compiler/aot/compile.cc @@ -56,17 +56,23 @@ Status CompileXla(xla::CompileOnlyClient* client, return errors::Unknown("Couldn't get XLA program shape: ", pshape_or.status().error_message()); } - compile_result->program_shape = *pshape_or.ValueOrDie(); - xla::ProgramShape* pshape = &compile_result->program_shape; - std::vector arg_layouts; - arg_layouts.reserve(pshape->parameters_size()); + compile_result->program_shape = pshape_or.ValueOrDie()->ToProto(); + xla::ProgramShapeProto* pshape = &compile_result->program_shape; + + // AotXlaComputationInstance::argument_layouts is a vector of Shape + // pointers. Accumulate the Shape objects themselves in a separate vector + // while building the vector of pointers. + std::vector arg_layout_ptrs(pshape->parameters_size()); + std::vector arg_layouts(pshape->parameters_size()); for (int i = 0; i < pshape->parameters_size(); ++i) { - arg_layouts.push_back(pshape->mutable_parameters(i)); + arg_layouts[i] = xla::Shape(*pshape->mutable_parameters(i)); + arg_layout_ptrs[i] = &arg_layouts[i]; } xla::CompileOnlyClient::AotXlaComputationInstance instance; instance.computation = &computation; - instance.argument_layouts = std::move(arg_layouts); - instance.result_layout = &pshape->result(); + instance.argument_layouts = std::move(arg_layout_ptrs); + xla::Shape result_shape(pshape->result()); + instance.result_layout = &result_shape; xla::StatusOr>> aot_or = client->CompileAheadOfTime({instance}, aot_opts); if (!aot_or.ok()) { diff --git a/tensorflow/compiler/aot/compile.h b/tensorflow/compiler/aot/compile.h index e03c5b1aa7..ee7bb26fab 100644 --- a/tensorflow/compiler/aot/compile.h +++ b/tensorflow/compiler/aot/compile.h @@ -33,9 +33,9 @@ namespace tfcompile { struct CompileResult { // Contains object file and meta-info. std::unique_ptr aot; - xla::ProgramShape program_shape; // Static shape of args and results. - string entry_point; // Name of generated function. - int pointer_size = 0; // Size of a pointer in bytes. + xla::ProgramShapeProto program_shape; // Static shape of args and results. + string entry_point; // Name of generated function. + int pointer_size = 0; // Size of a pointer in bytes. }; // CompileGraph compiles the graph_def into an object file containing a function diff --git a/tensorflow/compiler/aot/tests/tfcompile_test.cc b/tensorflow/compiler/aot/tests/tfcompile_test.cc index f10852c785..4dd79e5882 100644 --- a/tensorflow/compiler/aot/tests/tfcompile_test.cc +++ b/tensorflow/compiler/aot/tests/tfcompile_test.cc @@ -526,13 +526,15 @@ TEST(TFCompileTest, ProgramShape) { // muladd has the program shape defined. MatMulAndAddComp muladd; - const xla::ProgramShape* muladd_shape = muladd.ProgramShape(); + const xla::ProgramShapeProto* muladd_shape = muladd.ProgramShape(); ASSERT_TRUE(muladd_shape != nullptr); ASSERT_EQ(muladd_shape->parameters_size(), 2); - EXPECT_TRUE(ShapeUtil::Compatible(muladd_shape->parameters(0), f32_2x2)); - EXPECT_TRUE(ShapeUtil::Compatible(muladd_shape->parameters(1), f32_2x2)); + EXPECT_TRUE( + ShapeUtil::Compatible(xla::Shape(muladd_shape->parameters(0)), f32_2x2)); + EXPECT_TRUE( + ShapeUtil::Compatible(xla::Shape(muladd_shape->parameters(1)), f32_2x2)); - const xla::Shape& muladd_result = muladd_shape->result(); + const xla::Shape muladd_result(muladd_shape->result()); ASSERT_EQ(muladd_result.element_type(), xla::TUPLE); ASSERT_EQ(ShapeUtil::TupleElementCount(muladd_result), 2); const xla::Shape& muladd_result0 = diff --git a/tensorflow/compiler/jit/BUILD b/tensorflow/compiler/jit/BUILD index 5f25e4626a..be91ed4f43 100644 --- a/tensorflow/compiler/jit/BUILD +++ b/tensorflow/compiler/jit/BUILD @@ -23,7 +23,6 @@ package( load("//tensorflow:tensorflow.bzl", "cc_header_only_library") load("//tensorflow:tensorflow.bzl", "tf_cc_test") load("@local_config_cuda//cuda:build_defs.bzl", "if_cuda") -load("@local_config_cuda//cuda:build_defs.bzl", "if_cuda_is_configured") load("//tensorflow:tensorflow.bzl", "tf_cuda_cc_test") load("//tensorflow:tensorflow.bzl", "tf_custom_op_py_library") @@ -38,7 +37,7 @@ cc_library( ":xla_cpu_device", ":xla_cpu_jit", "//tensorflow/compiler/plugin", - ] + if_cuda_is_configured([ + ] + if_cuda([ ":xla_gpu_device", ":xla_gpu_jit", ]), @@ -51,6 +50,7 @@ cc_library( deps = [ ":jit_compilation_passes", "//tensorflow/compiler/jit/kernels:xla_ops", + "//tensorflow/compiler/tf2xla/kernels:xla_cpu_only_ops", "//tensorflow/compiler/tf2xla/kernels:xla_dummy_ops", "//tensorflow/compiler/tf2xla/kernels:xla_ops", "//tensorflow/compiler/xla/service:cpu_plugin", @@ -76,10 +76,10 @@ cc_library( srcs = ["xla_cpu_device.cc"], visibility = [":friends"], deps = [ + ":flags", ":jit_compilation_passes", ":xla_device", "//tensorflow/compiler/jit/kernels:xla_ops", - "//tensorflow/compiler/jit/legacy_flags:xla_device_flags", "//tensorflow/compiler/tf2xla:xla_compiler", "//tensorflow/compiler/tf2xla/kernels:xla_ops", "//tensorflow/compiler/xla/service:cpu_plugin", # buildcleaner: keep @@ -210,6 +210,18 @@ cc_library( # Internal targets below this point. +cc_library( + name = "flags", + srcs = ["flags.cc"], + hdrs = ["flags.h"], + visibility = [":friends"], + deps = [ + "//tensorflow/compiler/xla:parse_flags_from_env", + "//tensorflow/core:framework_internal", + "//tensorflow/core:lib", + ], +) + cc_library( name = "common", srcs = [ @@ -256,6 +268,7 @@ cc_library( "//tensorflow/compiler/tf2xla:common", "//tensorflow/compiler/tf2xla:dump_graph", "//tensorflow/compiler/tf2xla:xla_compiler", + "//tensorflow/compiler/xla:debug_options_flags", "//tensorflow/compiler/xla:statusor", "//tensorflow/compiler/xla/client:client_library", "//tensorflow/compiler/xla/client:local_client", @@ -268,6 +281,7 @@ cc_library( "//tensorflow/core/kernels:variable_ops", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/strings", + "@com_google_absl//absl/types:optional", "@com_google_absl//absl/types:span", ], ) @@ -487,6 +501,7 @@ cc_library( deps = [ ":common", ":encapsulate_util", + ":flags", ":shape_inference_helpers", ":union_find", ":xla_cluster_util", @@ -494,8 +509,6 @@ cc_library( "//tensorflow/cc:ops", "//tensorflow/cc:scope_internal", "//tensorflow/compiler/jit/graphcycles", - "//tensorflow/compiler/jit/legacy_flags:build_xla_ops_pass_flags", - "//tensorflow/compiler/jit/legacy_flags:mark_for_compilation_pass_flags", "//tensorflow/compiler/jit/ops:xla_ops", "//tensorflow/compiler/tf2xla:dump_graph", "//tensorflow/compiler/tf2xla:resource_operation_table", @@ -724,7 +737,10 @@ tf_custom_op_py_library( visibility = [ ":friends", ], - deps = ["//tensorflow/compiler/jit/ops:xla_ops_wrapper_py"], + deps = [ + "//tensorflow/compiler/jit/ops:xla_ops_grad", + "//tensorflow/compiler/jit/ops:xla_ops_wrapper_py", + ], ) # This target can be used by XLA device plugins to prevent circular dependencies, and provides access to all of the required headers for building a device library. diff --git a/tensorflow/compiler/jit/build_xla_ops_pass.cc b/tensorflow/compiler/jit/build_xla_ops_pass.cc index 93637a69d5..9f4042630e 100644 --- a/tensorflow/compiler/jit/build_xla_ops_pass.cc +++ b/tensorflow/compiler/jit/build_xla_ops_pass.cc @@ -23,7 +23,7 @@ limitations under the License. #include "tensorflow/cc/ops/control_flow_ops.h" #include "tensorflow/compiler/jit/defs.h" #include "tensorflow/compiler/jit/encapsulate_subgraphs_pass.h" -#include "tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.h" +#include "tensorflow/compiler/jit/flags.h" #include "tensorflow/compiler/jit/xla_cluster_util.h" #include "tensorflow/compiler/tf2xla/cc/ops/xla_jit_ops.h" #include "tensorflow/compiler/tf2xla/dump_graph.h" @@ -320,10 +320,10 @@ Status BuildXlaOpsPass::Run(const GraphOptimizationPassOptions& options) { return IsXlaCompiledKernel(*n); }); - bool lazy_compilation_enabled = enable_lazy_compilation_ - ? *enable_lazy_compilation_ - : legacy_flags::GetBuildXlaOpsPassFlags() - .tf_xla_enable_lazy_compilation; + bool lazy_compilation_enabled = + enable_lazy_compilation_ + ? *enable_lazy_compilation_ + : GetBuildXlaOpsPassFlags().tf_xla_enable_lazy_compilation; for (Node* n : xla_compiled_kernels) { TF_RETURN_IF_ERROR(ReplaceNodeWithXlaCompileAndXlaRun( diff --git a/tensorflow/compiler/jit/build_xla_ops_pass_test.cc b/tensorflow/compiler/jit/build_xla_ops_pass_test.cc index 11df946cc1..48a23a4c17 100644 --- a/tensorflow/compiler/jit/build_xla_ops_pass_test.cc +++ b/tensorflow/compiler/jit/build_xla_ops_pass_test.cc @@ -42,14 +42,8 @@ class BuildXlaOpsTest : public ::testing::Test { .ok()); } - void TearDown() override { - for (Device* device : devices_) { - delete device; - } - } - private: - std::vector devices_; + std::vector> devices_; }; using ::tensorflow::testing::FindNodeByName; diff --git a/tensorflow/compiler/jit/create_xla_launch_op_test.cc b/tensorflow/compiler/jit/create_xla_launch_op_test.cc index 7386660762..0f872a480f 100644 --- a/tensorflow/compiler/jit/create_xla_launch_op_test.cc +++ b/tensorflow/compiler/jit/create_xla_launch_op_test.cc @@ -59,8 +59,9 @@ class CreateXlaLaunchOpTest : public ::testing::Test { SessionOptions options; auto* device_count = options.config.mutable_device_count(); device_count->insert({"CPU", 1}); + std::vector> devices; TF_CHECK_OK(DeviceFactory::AddDevices( - options, "/job:localhost/replica:0/task:0", &devices_)); + options, "/job:localhost/replica:0/task:0", &devices)); FunctionDefLibrary proto; for (const auto& fdef : flib) { @@ -69,7 +70,7 @@ class CreateXlaLaunchOpTest : public ::testing::Test { lib_def_ = absl::make_unique( OpRegistry::Global(), proto); OptimizerOptions opts; - device_mgr_ = absl::make_unique(devices_); + device_mgr_ = absl::make_unique(std::move(devices)); pflr_ = absl::make_unique( device_mgr_.get(), Env::Default(), TF_GRAPH_DEF_VERSION, lib_def_.get(), opts, /*default_thread_pool=*/nullptr, /*cluster_flr=*/nullptr); @@ -77,7 +78,6 @@ class CreateXlaLaunchOpTest : public ::testing::Test { } FunctionLibraryRuntime* flr_; - std::vector devices_; std::unique_ptr device_mgr_; std::unique_ptr lib_def_; std::unique_ptr pflr_; diff --git a/tensorflow/compiler/jit/encapsulate_util.cc b/tensorflow/compiler/jit/encapsulate_util.cc index 28ec37b1b9..1f4b9c90a4 100644 --- a/tensorflow/compiler/jit/encapsulate_util.cc +++ b/tensorflow/compiler/jit/encapsulate_util.cc @@ -86,7 +86,7 @@ Status ProcessControlEdges(Graph* g, const string& xla_computation_attr_name, continue; } else if (src_xla_computation && !dst_xla_computation) { if (src_outside_compilation) { - // Case 1d: outside compilation to host computation control edge. + // Case 1c: outside compilation to host computation control edge. edges_to_remove.push_back(e); TF_RETURN_IF_ERROR(AppendToListAttr( @@ -94,7 +94,7 @@ Status ProcessControlEdges(Graph* g, const string& xla_computation_attr_name, } } else if (!src_xla_computation && dst_xla_computation) { if (dst_outside_compilation) { - // Case 1d: host computation control to outside compilation edge. + // Case 1c: host computation control to outside compilation edge. edges_to_remove.push_back(e); TF_RETURN_IF_ERROR(AppendToListAttr( @@ -103,40 +103,24 @@ Status ProcessControlEdges(Graph* g, const string& xla_computation_attr_name, } else { // src_xla_computation && dst_xla_computation if (*src_xla_computation != *dst_xla_computation) { if (src_outside_compilation && dst_outside_compilation) { - // Case 1c: outside compilation to outside compilation control edge. + // Case 1b: outside compilation to outside compilation control edge. edges_to_remove.push_back(e); TF_RETURN_IF_ERROR(AppendToListAttr( e->dst(), kXlaControlDependenciesAttrName, e->src()->name())); } else if (src_outside_compilation && !dst_outside_compilation) { - // Case 1b: outside compilation to another XLA computaition control + // Case 1a: outside compilation to another XLA computaition control // edge. TF_RETURN_IF_ERROR(AppendToListAttr( e->src(), kXlaConnectedToOtherXlaComputationAttrName, *dst_xla_computation)); } else if (!src_outside_compilation && dst_outside_compilation) { - // Case 1b: another XLA computaition to outside compilation control + // Case 1a: another XLA computaition to outside compilation control // edge. TF_RETURN_IF_ERROR(AppendToListAttr( e->dst(), kXlaConnectedFromOtherXlaComputationAttrName, *src_xla_computation)); } - } else { // *src_xla_computation == *dst_xla_computation - if (src_outside_compilation && dst_outside_compilation) { - if (*src_outside_compilation != *dst_outside_compilation) { - // Case 1c: outside compilation to outside compilation control edge. - edges_to_remove.push_back(e); - - TF_RETURN_IF_ERROR(AppendToListAttr( - e->dst(), kXlaControlDependenciesAttrName, e->src()->name())); - } - } else if (src_outside_compilation && !dst_outside_compilation) { - // Case 1a: outside compilation to its XLA computation control edge. - ReplaceAttr(e->src(), kXlaConnectedToXlaComputationAttrName, true); - } else if (!src_outside_compilation && dst_outside_compilation) { - // Case 1a: XLA computation to outside compilation in it control edge. - ReplaceAttr(e->dst(), kXlaConnectedFromXlaComputationAttrName, true); - } } } } @@ -181,12 +165,6 @@ Status ProcessXlaToXlaDataEdges(Graph* g, edges.push_back(EdgeInfo{e->dst_input(), e->dst()->id()}); VLOG(4) << "XLA -> XLA edge: " << e->DebugString(); } - } else { // *src_xla_computation == *dst_xla_computation - if (src_outside_compilation && dst_outside_compilation && - *src_outside_compilation != *dst_outside_compilation) { - edges.push_back(EdgeInfo{e->dst_input(), e->dst()->id()}); - VLOG(4) << "XLA -> XLA edge: " << e->DebugString(); - } } } @@ -263,7 +241,7 @@ Status ProcessDataEdgeBetweenOutsideCompilationAndHostComputation( // Remove the edge from host to outside compilation. Add a placeholder as // outside compilation node input. - std::map placeholders; + std::map, Node*> placeholders; for (int i = 0; i < edges.size(); i++) { Node* dst = g->FindNodeId(edges[i].dst_node_id); const Edge* e; @@ -275,9 +253,10 @@ Status ProcessDataEdgeBetweenOutsideCompilationAndHostComputation( // Find or create placeholder node. string new_name = edges[i].is_host_to_outside_compilation - ? absl::StrCat(src->name(), "_host_to_oc_placeholder") - : absl::StrCat(src->name(), "_oc_to_host_placeholder"); - auto iter = placeholders.find(new_name); + ? absl::StrCat(src->name(), "_host_to_oc_placeholder_", src_output) + : absl::StrCat(src->name(), "_oc_to_host_placeholder_", src_output); + auto placeholder_index = std::make_pair(src->name(), src_output); + auto iter = placeholders.find(placeholder_index); Node* placeholder_node; if (iter == placeholders.end()) { NodeDefBuilder placeholder_builder(new_name, "Placeholder"); @@ -310,7 +289,7 @@ Status ProcessDataEdgeBetweenOutsideCompilationAndHostComputation( Status s; placeholder_node = g->AddNode(placeholder_def, &s); TF_RETURN_IF_ERROR(s); - placeholders[new_name] = placeholder_node; + placeholders[placeholder_index] = placeholder_node; } else { placeholder_node = iter->second; } @@ -594,14 +573,244 @@ Status AddControlDependencies( return Status::OK(); } +// Step 1 for `PreprocessEdgesBetweenOutsideCompilations`. See comments of +// `PreprocessEdgesBetweenOutsideCompilations` for details. +Status PreprocessControlEdgesBetweenOutsideCompilations( + Graph* g, const string& outside_compilation_attr_name) { + // Gather edges to remove. We should not remove the edge while iterating. + std::vector edges_to_remove; + for (const Edge* e : g->edges()) { + if (!e->IsControlEdge()) { + continue; + } + + auto src_outside_compilation = + GetStringAttr(*e->src(), outside_compilation_attr_name); + auto dst_outside_compilation = + GetStringAttr(*e->dst(), outside_compilation_attr_name); + + if (src_outside_compilation && dst_outside_compilation) { + if (*src_outside_compilation != *dst_outside_compilation) { + // Case 1a: outside compilation to outside compilation control edge. + edges_to_remove.push_back(e); + + TF_RETURN_IF_ERROR(AppendToListAttr( + e->dst(), kXlaControlDependenciesWithinXlaClusterAttrName, + e->src()->name())); + } + } else if (src_outside_compilation && !dst_outside_compilation) { + // Case 1b: outside compilation to its XLA computation control edge. + ReplaceAttr(e->src(), kXlaConnectedToXlaComputationAttrName, true); + } else if (!src_outside_compilation && dst_outside_compilation) { + // Case 1b: XLA computation to outside compilation in it control edge. + ReplaceAttr(e->dst(), kXlaConnectedFromXlaComputationAttrName, true); + } + } + + for (auto e : edges_to_remove) { + g->RemoveEdge(e); + } + return Status::OK(); +} + +// Step 2 for `PreprocessEdgesBetweenOutsideCompilations`. See comments of +// `PreprocessEdgesBetweenOutsideCompilations` for details. +Status PreprocessDataEdgesBetweenOutsideCompilations( + Graph* g, const string& outside_compilation_attr_name) { + // Gather edges between outside compilation and host computation. Notice that + // we do not store `Edge*` directly because we remove some nodes while adding + // Identity nodes, and those Edge pointers might be invalidated. + struct EdgeInfo { + int dst_input, dst_node_id; + }; + std::vector edges; + for (const Edge* e : g->edges()) { + if (e->IsControlEdge()) { + continue; + } + + auto src_outside_compilation = + GetStringAttr(*e->src(), outside_compilation_attr_name); + auto dst_outside_compilation = + GetStringAttr(*e->dst(), outside_compilation_attr_name); + + if (src_outside_compilation && dst_outside_compilation && + *src_outside_compilation != *dst_outside_compilation) { + edges.push_back(EdgeInfo{e->dst_input(), e->dst()->id()}); + VLOG(4) << "Oc -> oc edge: " << e->DebugString(); + } + } + + // Remove the edge from host to outside compilation. Add a placeholder as + // outside compilation node input. + std::map, Node*> placeholders; + for (int i = 0; i < edges.size(); i++) { + Node* dst = g->FindNodeId(edges[i].dst_node_id); + const Edge* e; + TF_RETURN_IF_ERROR(dst->input_edge(edges[i].dst_input, &e)); + Node* src = e->src(); + int src_output = e->src_output(), dst_input = e->dst_input(); + g->RemoveEdge(e); + + // Find or create placeholder node. + string new_name = + absl::StrCat(src->name(), "_oc_to_oc_placeholder_", src_output); + auto placeholder_index = std::make_pair(src->name(), src_output); + auto iter = placeholders.find(placeholder_index); + Node* placeholder_node; + if (iter == placeholders.end()) { + NodeDefBuilder placeholder_builder(new_name, "Placeholder"); + placeholder_builder.Attr("dtype", src->output_type(src_output)); + string outside_compilation_attr; + TF_RETURN_IF_ERROR(GetNodeAttr(dst->attrs(), + outside_compilation_attr_name, + &outside_compilation_attr)); + placeholder_builder.Attr(outside_compilation_attr_name, + outside_compilation_attr); + placeholder_builder.Attr(kOutsideCompilationOriginalNodeAttrName, + src->name()); + placeholder_builder.Attr(kOutsideCompilationSrcOutputAttrName, + src_output); + NodeDef placeholder_def; + TF_RETURN_IF_ERROR(placeholder_builder.Finalize(&placeholder_def)); + Status s; + placeholder_node = g->AddNode(placeholder_def, &s); + TF_RETURN_IF_ERROR(s); + placeholders[placeholder_index] = placeholder_node; + } else { + placeholder_node = iter->second; + } + g->AddEdge(placeholder_node, 0, dst, dst_input); + + // Replace `e->dst()` because its input node changed. + NodeDef new_def = dst->def(); + *new_def.mutable_input(dst_input) = placeholder_node->name(); + TF_ASSIGN_OR_RETURN(Node * dst_replace_node, ReplaceNode(g, dst, new_def)); + + // Other edge in `edges` might have `e->dst()` as src or dst + // node. Before removing `e->dst()`, replace those edges with + // corresponding edges for `dst_replace_node`. + for (int j = i + 1; j < edges.size(); j++) { + if (edges[j].dst_node_id == edges[i].dst_node_id) { + edges[j].dst_node_id = dst_replace_node->id(); + } + } + } + return Status::OK(); +} + +// Step 1 for `PostprocessEdgesBetweenOutsideCompilations`. See comments of +// `PostprocessEdgesBetweenOutsideCompilations` for details. +Status PostprocessDataEdgesBetweenOutsideCompilations( + Graph* g, const string& outside_compilation_attr_name) { + // Gather all outside compilation to outside compilation nodes. + std::vector placeholder_nodes; + for (Node* n : g->nodes()) { + if (n->type_string() == "Placeholder" && + HasNodeAttr(n->def(), kOutsideCompilationOriginalNodeAttrName)) { + placeholder_nodes.push_back(n); + } + } + + // Remove the placeholder nodes, and reconnect original edge. + auto node_name_index = g->BuildNodeNameIndex(); + for (auto n : placeholder_nodes) { + string node_name; + int node_src_output; + TF_RETURN_IF_ERROR(GetNodeAttr( + n->attrs(), kOutsideCompilationOriginalNodeAttrName, &node_name)); + TF_RETURN_IF_ERROR(GetNodeAttr( + n->attrs(), kOutsideCompilationSrcOutputAttrName, &node_src_output)); + auto iter = node_name_index.find(node_name); + if (iter == node_name_index.end()) { + return errors::Internal( + "Cannot find original node for oc -> host placeholder node ", + node_name); + } + + // Change all usage node to use the original node instead. + Node* original_node = iter->second; + std::vector control_edges; + std::vector data_edges; + for (auto e : n->out_edges()) { + if (e->IsControlEdge()) { + control_edges.push_back(e); + } else { + data_edges.push_back({e->dst(), e->src_output(), e->dst_input()}); + } + } + for (const Edge* e : control_edges) { + g->AddControlEdge(original_node, e->dst()); + g->RemoveEdge(e); + } + for (int i = 0; i < data_edges.size(); i++) { + Node* dst = data_edges[i].dst; + NodeDef new_def = dst->def(); + int dst_input = data_edges[i].dst_input; + *new_def.mutable_input(dst_input) = + absl::StrCat(original_node->name(), ":", node_src_output); + TF_ASSIGN_OR_RETURN(Node * replace_node, ReplaceNode(g, dst, new_def)); + + const Edge* edge_to_replace = nullptr; + TF_RETURN_IF_ERROR(replace_node->input_edge(dst_input, &edge_to_replace)); + g->RemoveEdge(edge_to_replace); + g->AddEdge(original_node, node_src_output, replace_node, dst_input); + + // Other edges might have `dst` as dst node. Update those edges with + // `replace_node`. + for (int j = i + 1; j < data_edges.size(); j++) { + if (data_edges[j].dst == dst) { + data_edges[j].dst = replace_node; + } + } + + // Other placeholder node might have `dst` as original node. Update + // `node_name_index` with `replace_node`. + node_name_index[replace_node->name()] = replace_node; + } + + // Remove placeholder node. + g->RemoveNode(n); + } + return Status::OK(); +} + +// Step 2 for `PostprocessEdgesBetweenOutsideCompilations`. See comments of +// `PostprocessEdgesBetweenOutsideCompilations` for details. +Status PostprocessControlEdgesBetweenOutsideCompilations( + Graph* g, const string& outside_compilation_attr_name) { + auto node_name_index = g->BuildNodeNameIndex(); + + // Reconnect outside compilation to outside compilation control edge. + for (Node* n : g->nodes()) { + std::vector control_deps; + Status s = + GetNodeAttr(n->attrs(), kXlaControlDependenciesWithinXlaClusterAttrName, + &control_deps); + if (!s.ok()) { + if (s.code() != error::NOT_FOUND) { + return s; + } else { + continue; + } + } else { + n->ClearAttr(kXlaControlDependenciesWithinXlaClusterAttrName); + for (const string& control_input : control_deps) { + auto iter = node_name_index.find(control_input); + if (iter == node_name_index.end()) { + return errors::Internal("Cannot find original node for ", + control_input); + } + g->AddControlEdge(iter->second, n); + } + } + } + return Status::OK(); +} } // namespace const char kXlaInferredShapesAttrName[] = "_xla_inferred_shapes"; -const char kXlaConnectedToXlaComputationAttrName[] = - "_xla_connected_to_xla_computation"; -const char kXlaConnectedFromXlaComputationAttrName[] = - "_xla_connected_from_xla_computation"; const char kXlaConnectedToOtherXlaComputationAttrName[] = "_xla_connected_to_other_xla_computation"; const char kXlaConnectedFromOtherXlaComputationAttrName[] = @@ -616,6 +825,15 @@ const char kHostToOutsideCompilationOriginalNodeAttrName[] = "_xla_host_to_oc_node_name"; const char kHostToOutsideCompilationSrcOutputAttrName[] = "_xla_host_to_oc_src_output"; +const char kXlaConnectedToXlaComputationAttrName[] = + "_xla_connected_to_xla_computation"; +const char kXlaConnectedFromXlaComputationAttrName[] = + "_xla_connected_from_xla_computation"; +const char kOutsideCompilationOriginalNodeAttrName[] = + "_xla_oc_to_oc_node_name"; +const char kOutsideCompilationSrcOutputAttrName[] = "_xla_oc_to_oc_src_output"; +const char kXlaControlDependenciesWithinXlaClusterAttrName[] = + "_xla_control_dependencies_within_xla_cluster"; Status PerformStaticShapeInferenceBeforeEncapsulation( Graph* g, const string& xla_computation_attr_name, @@ -699,4 +917,39 @@ Status PostprocessForEncapsulation( return Status::OK(); } +Status PreprocessEdgesBetweenOutsideCompilations( + Graph* g, const string& outside_compilation_attr_name) { + // Remove edges from source node to outside compilation nodes, and edges + // from outside compilation nodes to sink node. + std::vector edges_to_remove; + for (const Edge* e : g->source_node()->out_edges()) { + if (HasNodeAttr(e->dst()->def(), outside_compilation_attr_name)) { + edges_to_remove.push_back(e); + } + } + for (const Edge* e : g->sink_node()->in_edges()) { + if (HasNodeAttr(e->src()->def(), outside_compilation_attr_name)) { + edges_to_remove.push_back(e); + } + } + for (auto e : edges_to_remove) { + g->RemoveEdge(e); + } + + TF_RETURN_IF_ERROR(PreprocessControlEdgesBetweenOutsideCompilations( + g, outside_compilation_attr_name)); + TF_RETURN_IF_ERROR(PreprocessDataEdgesBetweenOutsideCompilations( + g, outside_compilation_attr_name)); + return Status::OK(); +} + +Status PostprocessEdgesBetweenOutsideCompilations( + Graph* g, const string& outside_compilation_attr_name) { + TF_RETURN_IF_ERROR(PostprocessDataEdgesBetweenOutsideCompilations( + g, outside_compilation_attr_name)); + TF_RETURN_IF_ERROR(PostprocessControlEdgesBetweenOutsideCompilations( + g, outside_compilation_attr_name)); + return Status::OK(); +} + } // namespace tensorflow diff --git a/tensorflow/compiler/jit/encapsulate_util.h b/tensorflow/compiler/jit/encapsulate_util.h index 5e0c4bf6a0..e363bc5754 100644 --- a/tensorflow/compiler/jit/encapsulate_util.h +++ b/tensorflow/compiler/jit/encapsulate_util.h @@ -44,14 +44,6 @@ Status PerformStaticShapeInferenceBeforeEncapsulation( Graph* g, const string& xla_computation_attr_name, const string& outside_compilation_attr_name); -// Attribute indicating that some ops in this node's XLA computation has control -// dependency on this node. Attribute value will always be "true". -extern const char kXlaConnectedToXlaComputationAttrName[]; - -// Attribute indicating that this node has control dependency on some ops in -// this node's XLA computation. Attribute value will always be "true". -extern const char kXlaConnectedFromXlaComputationAttrName[]; - // Attribute indicating that some ops in other XLA computation has control // dependency on this node. Attribute value will be a list of string (XLA // computation names). @@ -81,6 +73,14 @@ extern const char kOutsideCompilationToHostOriginalNodeAttrName[]; // int (src_output for original edge). extern const char kOutsideCompilationToHostSrcOutputAttrName[]; +// Attribute indicating that some ops in this node's XLA computation has control +// dependency on this node. Attribute value will always be "true". +extern const char kXlaConnectedToXlaComputationAttrName[]; + +// Attribute indicating that this node has control dependency on some ops in +// this node's XLA computation. Attribute value will always be "true". +extern const char kXlaConnectedFromXlaComputationAttrName[]; + // Attribute indicating that this is an Placeholder node added to act as a // temporary input node for an host node. Attribute value will be string // (original input node name). @@ -91,19 +91,31 @@ extern const char kHostToOutsideCompilationOriginalNodeAttrName[]; // for original edge). extern const char kHostToOutsideCompilationSrcOutputAttrName[]; -// Preprocesses the graph for encapsulation. It will perform the following -// operations in order: +// Attribute indicating that this is an Placeholder node added to act as a +// temporary input node for an outside compilation node. Attribute value will be +// string (original input node name). +extern const char kOutsideCompilationOriginalNodeAttrName[]; + +// Attribute indicating that this is an Placeholder node added to act as a +// temporary input node for an outside compilation node. Attribute value will be +// int (src_output for original edge). +extern const char kOutsideCompilationSrcOutputAttrName[]; + +// Attribute indicating that this node has control dependencies on some other +// nodes within the same XLA cluster. Attribute value will be a list of string +// (node names). +extern const char kXlaControlDependenciesWithinXlaClusterAttrName[]; + +// Preprocesses edges between different XLA clusters for encapsulation. It will +// perform the following operations in order: // -// 1a. For control edges between outside compilation and its XLA computation, -// add attr "kXlaConnected{From, To}XlaComputationAttrName = true" to the -// outside compilation node. -// 1b. For control edges between outside compilation and another XLA +// 1a. For control edges between outside compilation and another XLA // computation, add attr "kXlaConnected{From, To}OtherXlaComputationAttrName // = XLA computation node name" to the outside compilation node. -// 1c. For control edges between different outside compilations, remove the edge -// and add attr "kXlaControlDependenciesAttrName = src node name" to dst -// node. -// 1d. For control edges between outside compilation and host computation, +// 1b. For control edges between different outside compilations (in different +// XLA computations), remove the edge and add attr +// "kXlaControlDependenciesAttrName = src node name" to dst node. +// 1c. For control edges between outside compilation and host computation, // remove the edge and add attr "kXlaControlDependenciesAttrName = src node // name" to dst node. // 2. For data edges between different XLA computations, if either src or dst @@ -146,26 +158,53 @@ struct XlaClusterInfo { const std::map host_compute_core; }; -// Postprocesses the graph for encapsulation. This function reverts what -// `PreprocessForEncapsulation` did. It will perform the following operations in -// order: +// Postprocesses edges between different XLA clusters for encapsulation. This +// function reverts what `PreprocessForEncapsulation` did. It will perform the +// following operations in order: // // 1. Remove Placeholder nodes between outside compilation and host computation // (created in `PreprocessForEncapsulation` step 3). // 2. Remove Identity nodes created in `PreprocessForEncapsulation` step 2. -// 3a. Reconnect control edges between different outside compilations (marked by -// `PreprocessForEncapsulation` step 1c) and control edges between outside -// compilation and host computation (marked by `PreprocessForEncapsulation` -// step 1d). -// 3b. Reconnect control edges between outside compilation and another XLA -// computation (marked by `PreprocessForEncapsulation` step 1b). -// Notice that control edges marked by `PreprocessForEncapsulation` step 1a are -// not handled here. They are handled in `RewriteOutsideCompilationSubgraphFn`. +// 3a. Reconnect control edges between outside compilation and another XLA +// computation (marked by `PreprocessForEncapsulation` step 1a). +// 3b. Reconnect control edges between different outside compilations (marked by +// `PreprocessForEncapsulation` step 1b). +// 3c. Reconnect control edges between outside compilation and host computation +// (marked by `PreprocessForEncapsulation` step 1c). Status PostprocessForEncapsulation( Graph* g, const string& xla_computation_attr_name, const string& outside_compilation_attr_name, const std::unordered_map& clusters); +// Preprocesses edges within the same XLA cluster. It will perform the following +// operations in order: +// +// 0. Remove edges from source node to outside compilation nodes, and edges +// from outside compilation nodes to sink node. +// 1a. For edges between different outside compilation clusters, remove the edge +// and add attr "kXlaControlDependenciesWithinXlaClusterAttrName = src node +// name" to dst node. +// 1b. For control edges between outside compilation and its XLA computation, +// add attr "kXlaConnected{From, To}XlaComputationAttrName = true" to the +// outside compilation node. +// 2. For data edges between different outside compilations, remove the edge +// and create a Placeholder node as dst node's input. +Status PreprocessEdgesBetweenOutsideCompilations( + Graph* g, const string& outside_compilation_attr_name); + +// Postprocesses edges within the same XLA cluster. This function reverts what +// `PreprocessEdgesBetweenOutsideCompilations` did. It will perform the +// following operations in order: +// +// 1. Remove Placeholder nodes between different outside compilations (created +// in `PreprocessEdgesBetweenOutsideCompilations` step 2). +// 2a. Reconnect control edges between different outside compilations (marked by +// `PreprocessEdgesBetweenOutsideCompilations` step 1a). +// Notice that control edges marked by +// `PreprocessEdgesBetweenOutsideCompilations` step 1b are not handled here. +// They are handled in `RewriteOutsideCompilationSubgraphFn`. +Status PostprocessEdgesBetweenOutsideCompilations( + Graph* g, const string& outside_compilation_attr_name); } // namespace tensorflow #endif // TENSORFLOW_COMPILER_JIT_ENCAPSULATE_UTIL_H_ diff --git a/tensorflow/compiler/jit/encapsulate_util_test.cc b/tensorflow/compiler/jit/encapsulate_util_test.cc index 7255df3112..3b8b49cb92 100644 --- a/tensorflow/compiler/jit/encapsulate_util_test.cc +++ b/tensorflow/compiler/jit/encapsulate_util_test.cc @@ -107,28 +107,19 @@ TEST(PreprocessForEncapsulationTest, ControlEdges) { identity4_node->AddAttr("_xla", "1"); identity4_node->AddAttr("_oc", "0"); identity5_node->AddAttr("_xla", "1"); - // Case 1a: control edges between outside compilation and its XLA computation. - g.AddControlEdge(add_node, identity0_node); - g.AddControlEdge(identity0_node, identity1_node); - // Case 1b: control edges between outside compilation and another XLA + // Case 1a: control edges between outside compilation and another XLA // computation. g.AddControlEdge(identity0_node, identity3_node); g.AddControlEdge(identity1_node, identity4_node); - // Case 1c: control edges between different outside compilations. + // Case 1b: control edges between different outside compilations. g.AddControlEdge(identity0_node, identity4_node); - // Case 1d: control edges between outside compilation and host computation. + // Case 1c: control edges between outside compilation and host computation. g.AddControlEdge(const0_node, identity0_node); g.AddControlEdge(identity0_node, identity2_node); TF_CHECK_OK(PreprocessForEncapsulation(&g, "_xla", "_oc")); - // Case 1a: add attr "_xla_connected_{from/to}_xla_computation = true" to the - // outside compilation node. - EXPECT_TRUE(HasNodeAttr(identity0_node->def(), - kXlaConnectedFromXlaComputationAttrName)); - EXPECT_TRUE(HasNodeAttr(identity0_node->def(), - kXlaConnectedToXlaComputationAttrName)); - // Case 1b: add attr "_xla_control_deps_{from/to} = XLA computation node name" + // Case 1a: add attr "_xla_control_deps_{from/to} = XLA computation node name" // to the outside compilation node. std::vector attr; TF_CHECK_OK(GetNodeAttr(identity0_node->def(), @@ -140,13 +131,13 @@ TEST(PreprocessForEncapsulationTest, ControlEdges) { kXlaConnectedFromOtherXlaComputationAttrName, &attr)); EXPECT_EQ(attr.size(), 1); EXPECT_EQ(attr[0], "0"); - // Case 1c: add attr "_xla_control_deps = src node name" to dst node. + // Case 1b: add attr "_xla_control_deps = src node name" to dst node. attr.clear(); TF_CHECK_OK(GetNodeAttr(identity4_node->def(), kXlaControlDependenciesAttrName, &attr)); EXPECT_EQ(attr.size(), 1); EXPECT_EQ(attr[0], "identity0"); - // Case 1d: add attr "_xla_control_deps = src node name" to dst node. + // Case 1c: add attr "_xla_control_deps = src node name" to dst node. attr.clear(); TF_CHECK_OK(GetNodeAttr(identity0_node->def(), kXlaControlDependenciesAttrName, &attr)); @@ -162,23 +153,33 @@ TEST(PreprocessForEncapsulationTest, ControlEdges) { TEST(PreprocessForEncapsulationTest, DataEdges) { // Build the graph: // "const_0" and "const_1" in host computation + // "identityn0" = ("const_0", "const_1") in host computation 0 // "add0" = "const_0" + "const_1" in XLA computation 0 // "add1" = "add0" + "const_0" in XLA computation 0 & outside compilation 0 // "identity0" = "add1" in XLA computation 0 // "add2" = "add1" + "identity0" in host computation // "add3" = "add1" + "add2" in XLA computation 1 - // "add4" = "identity0" + "add2" in XLA computation 1 & outside compilation 1 + // "add4" = "identity0" + "add2" in XLA computation 1 & outside compilation 0 + // "add5" = "identityn0"[0] + "identityn0"[1] in XLA computation 1 & + // outside compilation 0 + // "identityn1" = ("identityn0"[0], "identityn0"[1]) in XLA computation 1 & + // outside compilation 0 // "identity1" = "add4" in XLA computation 1 // "identity2" = "identity1" in host computation tensorflow::Scope s = tensorflow::Scope::NewRootScope(); Output const_0 = ops::Const(s.WithOpName("const_0"), 1, {}); Output const_1 = ops::Const(s.WithOpName("const_1"), 2, {}); + auto identityn0 = + ops::IdentityN(s.WithOpName("identityn_0"), {const_0, const_1}); Output add0 = ops::Add(s.WithOpName("add0"), const_0, const_1); Output add1 = ops::Add(s.WithOpName("add1"), add0, const_0); Output identity0 = ops::Identity(s.WithOpName("identity0"), add1); Output add2 = ops::Add(s.WithOpName("add2"), add1, identity0); Output add3 = ops::Add(s.WithOpName("add3"), add1, add2); Output add4 = ops::Add(s.WithOpName("add4"), identity0, add2); + Output add5 = ops::Add(s.WithOpName("add5"), identityn0[0], identityn0[1]); + auto identityn1 = ops::IdentityN(s.WithOpName("identityn_1"), + {identityn0[0], identityn0[1]}); Output identity1 = ops::Identity(s.WithOpName("identity1"), add4); Output identity2 = ops::Identity(s.WithOpName("identity2"), add4); Graph g(OpRegistry::Global()); @@ -189,6 +190,8 @@ TEST(PreprocessForEncapsulationTest, DataEdges) { Node *add0_node = node_index["add0"], *add1_node = node_index["add1"], *identity0_node = node_index["identity0"], *add3_node = node_index["add3"], *add4_node = node_index["add4"], + *add5_node = node_index["add5"], + *identityn1_node = node_index["identityn_1"], *identity1_node = node_index["identity1"]; add0_node->AddAttr("_xla", "0"); add1_node->AddAttr("_xla", "0"); @@ -197,6 +200,10 @@ TEST(PreprocessForEncapsulationTest, DataEdges) { add3_node->AddAttr("_xla", "1"); add4_node->AddAttr("_xla", "1"); add4_node->AddAttr("_oc", "0"); + add5_node->AddAttr("_xla", "1"); + add5_node->AddAttr("_oc", "0"); + identityn1_node->AddAttr("_xla", "1"); + identityn1_node->AddAttr("_oc", "0"); identity1_node->AddAttr("_xla", "1"); TF_CHECK_OK(PreprocessForEncapsulation(&g, "_xla", "_oc")); @@ -214,8 +221,9 @@ TEST(PreprocessForEncapsulationTest, DataEdges) { EXPECT_NE(bridge_identity0_add4, nullptr); // Step 3: add placeholder for edges between host computation and outside // compilation. - EXPECT_EQ(bridge_add1_add3->def().input(0), "add1_oc_to_host_placeholder"); - Node *add1_oc_to_host_placeholder = node_index["add1_oc_to_host_placeholder"]; + EXPECT_EQ(bridge_add1_add3->def().input(0), "add1_oc_to_host_placeholder_0"); + Node *add1_oc_to_host_placeholder = + node_index["add1_oc_to_host_placeholder_0"]; TF_CHECK_OK(GetNodeAttr(add1_oc_to_host_placeholder->attrs(), kOutsideCompilationToHostOriginalNodeAttrName, &str)); EXPECT_EQ(str, "add1"); @@ -226,15 +234,34 @@ TEST(PreprocessForEncapsulationTest, DataEdges) { add4_node = node_index["add4"]; ASSERT_NE(add4_node, nullptr); EXPECT_EQ(add4_node->def().input(0), - "bridge_identity0_add4_host_to_oc_placeholder"); + "bridge_identity0_add4_host_to_oc_placeholder_0"); Node *identity0_host_to_oc_placeholder = - node_index["bridge_identity0_add4_host_to_oc_placeholder"]; + node_index["bridge_identity0_add4_host_to_oc_placeholder_0"]; TF_CHECK_OK(GetNodeAttr(identity0_host_to_oc_placeholder->attrs(), kHostToOutsideCompilationOriginalNodeAttrName, &str)); EXPECT_EQ(str, "bridge_identity0_add4"); TF_CHECK_OK(GetNodeAttr(identity0_host_to_oc_placeholder->attrs(), kHostToOutsideCompilationSrcOutputAttrName, &i)); EXPECT_EQ(i, 0); + + // Check different placeholder nodes are created for different src_output. + Node *placeholder0 = node_index["identityn_0_host_to_oc_placeholder_0"], + *placeholder1 = node_index["identityn_0_host_to_oc_placeholder_1"]; + EXPECT_NE(placeholder0, nullptr); + EXPECT_NE(placeholder1, nullptr); + // Check we only have 2 placeholder nodes created for "identityn_0". + int placeholder_count = 0; + for (Node *n : g.nodes()) { + if (HasNodeAttr(n->def(), kHostToOutsideCompilationOriginalNodeAttrName)) { + string attr; + TF_CHECK_OK(GetNodeAttr( + n->attrs(), kHostToOutsideCompilationOriginalNodeAttrName, &attr)); + if (attr == "identityn_0") { + ++placeholder_count; + } + } + } + EXPECT_EQ(placeholder_count, 2); } TEST(PostprocessForEncapsulationTest, ControlEdges) { diff --git a/tensorflow/compiler/jit/encapsulate_xla_computations_pass.cc b/tensorflow/compiler/jit/encapsulate_xla_computations_pass.cc index 2ce6fa73fc..d334100aa4 100644 --- a/tensorflow/compiler/jit/encapsulate_xla_computations_pass.cc +++ b/tensorflow/compiler/jit/encapsulate_xla_computations_pass.cc @@ -195,8 +195,11 @@ Status RewriteSubgraph(const std::vector& arg_source_tensors, e->dst()->attrs().Find(kXlaClusterAttr) == nullptr && e->dst()->type_string() != kXlaClusterOutput) { return errors::InvalidArgument( - "Undeclared output of XLA computation. A common cause of this error " - "is variable initializers that depend on the XLA computation. Edge: ", + "Undeclared output of XLA computation. Some common causes of this " + "error are: 1) variable initializers that depend on the XLA " + "computation; 2) gradient computations that depend on the XLA " + "computation, which can be mitigated by moving gradient computations " + "inside XLA computation. Offending edge: ", e->src()->name(), ":", e->src_output(), " -> ", e->dst()->name(), ":", e->dst_input()); } diff --git a/tensorflow/compiler/jit/extract_outside_compilation_pass.cc b/tensorflow/compiler/jit/extract_outside_compilation_pass.cc index 8b3587c508..e3c7e2f89b 100644 --- a/tensorflow/compiler/jit/extract_outside_compilation_pass.cc +++ b/tensorflow/compiler/jit/extract_outside_compilation_pass.cc @@ -366,7 +366,7 @@ Status ReplaceOrRemoveOutsideCompilationCallNode( // replace this node with compilation result node. // 3) all outside compilation graphs. Status ConstructHostGraph( - const string& xla_cluster_name, + const string& xla_cluster_name, const string& outside_compilation_attr_name, const std::vector& outside_compilation_host_graphs, FunctionLibraryDefinition* fld, std::unique_ptr* host_graph) { host_graph->reset(new Graph(fld)); @@ -476,6 +476,10 @@ Status ConstructHostGraph( host_graph->get(), std::unordered_set{(*host_graph)->sink_node()}); + // Postprocess edges between different outside compilations. + TF_RETURN_IF_ERROR(PostprocessEdgesBetweenOutsideCompilations( + host_graph->get(), outside_compilation_attr_name)); + if (VLOG_IS_ON(4)) { dump_graph::DumpGraphToFile( absl::StrCat("extract_outside_compilation_host_graph_for_", @@ -801,6 +805,11 @@ Status ExtractOutsideCompilationForFunction( }, &fbody)); std::unique_ptr fbody_deleter(fbody); + + // Preprocess edges between different outside compilations. They will be + // restored in `ConstructHostGraph()`. + TF_RETURN_IF_ERROR(PreprocessEdgesBetweenOutsideCompilations( + fbody->graph, outside_compilation_attr_name)); if (VLOG_IS_ON(4)) { dump_graph::DumpGraphToFile( absl::StrCat("extract_outside_compilation_for_func_before_", func_name), @@ -860,8 +869,9 @@ Status ExtractOutsideCompilationForFunction( // Construct host graph. if (!outside_compilation_host_graphs.empty()) { - TF_RETURN_IF_ERROR(ConstructHostGraph( - xla_cluster_name, outside_compilation_host_graphs, fld, host_graph)); + TF_RETURN_IF_ERROR( + ConstructHostGraph(xla_cluster_name, outside_compilation_attr_name, + outside_compilation_host_graphs, fld, host_graph)); } // Remove the outside compilation graphs from function library. diff --git a/tensorflow/compiler/jit/extract_outside_compilation_pass_test.cc b/tensorflow/compiler/jit/extract_outside_compilation_pass_test.cc index c5bd64f004..bff956100d 100644 --- a/tensorflow/compiler/jit/extract_outside_compilation_pass_test.cc +++ b/tensorflow/compiler/jit/extract_outside_compilation_pass_test.cc @@ -290,21 +290,18 @@ TEST(ExtractOutsideCompilationForFunctionTest, Basic) { TF_CHECK_OK(GetNodeAttr(host_compute_1->attrs(), "shapes", &shapes)); EXPECT_EQ(shapes.size(), 1); EXPECT_EQ(shapes[0].dim_size(), 1); - // Check XlaHostCompute nodes' "shape_inference_graph" attr. "0" should have a - // non-empty value, and "1" should have an empty value. + // Check XlaHostCompute nodes' "shape_inference_graph" attr. Both should have + // empty values. string shape_inference_graph; TF_CHECK_OK(GetNodeAttr(host_compute_0->attrs(), "shape_inference_graph", &shape_inference_graph)); - EXPECT_EQ(shape_inference_graph, - "_outside_compilation_shape_inference_cluster_0"); + EXPECT_EQ(shape_inference_graph, ""); TF_CHECK_OK(GetNodeAttr(host_compute_1->attrs(), "shape_inference_graph", &shape_inference_graph)); EXPECT_EQ(shape_inference_graph, ""); // Check `shape_inference_graphs`. - EXPECT_EQ(shape_inference_graphs.size(), 1); - EXPECT_EQ(shape_inference_graphs[0], - "_outside_compilation_shape_inference_cluster_0"); + EXPECT_EQ(shape_inference_graphs.size(), 0); // Check `host_graph`: verify we have key placeholder and sequencer. Node *key_placeholder = nullptr, *sequencer = nullptr; @@ -333,8 +330,8 @@ TEST(ExtractOutsideCompilationForFunctionTest, Basic) { send_recv_nodes.push_back(n); } } - EXPECT_EQ(num_send_from_host, 2); - EXPECT_EQ(num_recv_at_host, 2); + EXPECT_EQ(num_send_from_host, 1); + EXPECT_EQ(num_recv_at_host, 1); for (Node *n : send_recv_nodes) { Node *input_node; TF_CHECK_OK(n->input_node(n->num_inputs() - 1, &input_node)); diff --git a/tensorflow/compiler/jit/flags.cc b/tensorflow/compiler/jit/flags.cc new file mode 100644 index 0000000000..98e344b3a0 --- /dev/null +++ b/tensorflow/compiler/jit/flags.cc @@ -0,0 +1,152 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include // NOLINT + +#include "tensorflow/compiler/jit/flags.h" +#include "tensorflow/compiler/xla/parse_flags_from_env.h" +#include "tensorflow/core/util/command_line_flags.h" + +namespace tensorflow { +namespace { + +BuildXlaOpsPassFlags* build_ops_flags; +DumpGraphFlags* dump_graph_flags; +MarkForCompilationPassFlags* mark_for_compilation_flags; +XlaDeviceFlags* device_flags; +XlaOpsCommonFlags* ops_flags; + +std::vector* flag_list; +std::once_flag flags_init; + +void AppendDumpGraphFlagsInternal(std::vector* flag_list) { + std::vector new_flags = { + Flag("tf_dump_graph_prefix", &dump_graph_flags->tf_dump_graph_prefix, + "Path prefix to which graphs dumped during debugging should be " + "written."), + }; + flag_list->insert(flag_list->end(), new_flags.begin(), new_flags.end()); +} + +void AppendMarkForCompilationPassFlagsInternal(std::vector* flag_list) { + std::vector new_flags = { + Flag("tf_xla_auto_jit", &mark_for_compilation_flags->tf_xla_auto_jit, + "Control compilation of operators into XLA computations on CPU and " + "GPU devices. 0 = use ConfigProto setting; -1 = off; 1 = on for " + "things very likely to be improved; 2 = on for everything. " + "Experimental."), + Flag("tf_xla_min_cluster_size", + &mark_for_compilation_flags->tf_xla_min_cluster_size, + "Minimum number of operators in an XLA compilation. Ignored for " + "operators placed on an XLA device or operators explicitly marked " + "for compilation."), + Flag("tf_xla_max_cluster_size", + &mark_for_compilation_flags->tf_xla_max_cluster_size, + "Maximum number of operators in an XLA compilation."), + Flag("tf_xla_clustering_debug", + &mark_for_compilation_flags->tf_xla_clustering_debug, + "Dump graphs during XLA compilation."), + Flag("tf_xla_cpu_global_jit", + &mark_for_compilation_flags->tf_xla_cpu_global_jit, + "Enables global JIT compilation for CPU via SessionOptions."), + Flag("tf_xla_clustering_fuel", + &mark_for_compilation_flags->tf_xla_clustering_fuel, + "Places an artificial limit on the number of ops marked as " + "eligible for clustering."), + Flag("tf_xla_fusion_only", + &mark_for_compilation_flags->tf_xla_fusion_only, + "enable fusion of element-wise operations only using XLA when " + "global_jit_level is ON*.")}; + flag_list->insert(flag_list->end(), new_flags.begin(), new_flags.end()); +} + +void AllocateAndParseFlags() { + build_ops_flags = new BuildXlaOpsPassFlags; + build_ops_flags->tf_xla_enable_lazy_compilation = true; + + dump_graph_flags = new DumpGraphFlags; + dump_graph_flags->tf_dump_graph_prefix = "/tmp/"; + + mark_for_compilation_flags = new MarkForCompilationPassFlags; + mark_for_compilation_flags->tf_xla_auto_jit = 0; + mark_for_compilation_flags->tf_xla_min_cluster_size = 2; + mark_for_compilation_flags->tf_xla_max_cluster_size = + std::numeric_limits::max(); + mark_for_compilation_flags->tf_xla_clustering_debug = false; + mark_for_compilation_flags->tf_xla_cpu_global_jit = false; + mark_for_compilation_flags->tf_xla_clustering_fuel = + std::numeric_limits::max(); + mark_for_compilation_flags->tf_xla_fusion_only = false; + + device_flags = new XlaDeviceFlags; + device_flags->tf_xla_compile_on_demand = false; + + ops_flags = new XlaOpsCommonFlags; + ops_flags->tf_xla_always_defer_compilation = false; + + flag_list = new std::vector({ + Flag("tf_xla_enable_lazy_compilation", + &build_ops_flags->tf_xla_enable_lazy_compilation, ""), + + Flag("tf_xla_compile_on_demand", &device_flags->tf_xla_compile_on_demand, + "Switch a device into 'on-demand' mode, where instead of " + "autoclustering ops are compiled one by one just-in-time."), + + Flag("tf_xla_always_defer_compilation", + &ops_flags->tf_xla_always_defer_compilation, ""), + }); + AppendDumpGraphFlagsInternal(flag_list); + AppendMarkForCompilationPassFlagsInternal(flag_list); + xla::ParseFlagsFromEnvAndDieIfUnknown("TF_XLA_FLAGS", *flag_list); +} + +} // namespace + +const BuildXlaOpsPassFlags& GetBuildXlaOpsPassFlags() { + std::call_once(flags_init, &AllocateAndParseFlags); + return *build_ops_flags; +} + +DumpGraphFlags* GetDumpGraphFlags() { + std::call_once(flags_init, &AllocateAndParseFlags); + return dump_graph_flags; +} + +MarkForCompilationPassFlags* GetMarkForCompilationPassFlags() { + std::call_once(flags_init, &AllocateAndParseFlags); + return mark_for_compilation_flags; +} + +XlaDeviceFlags* GetXlaDeviceFlags() { + std::call_once(flags_init, &AllocateAndParseFlags); + return device_flags; +} + +const XlaOpsCommonFlags& GetXlaOpsCommonFlags() { + std::call_once(flags_init, &AllocateAndParseFlags); + return *ops_flags; +} + +void AppendMarkForCompilationPassFlags(std::vector* flag_list) { + std::call_once(flags_init, &AllocateAndParseFlags); + AppendMarkForCompilationPassFlagsInternal(flag_list); +} + +void AppendDumpGraphFlags(std::vector* flag_list) { + std::call_once(flags_init, &AllocateAndParseFlags); + AppendDumpGraphFlagsInternal(flag_list); +} + +} // namespace tensorflow diff --git a/tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.h b/tensorflow/compiler/jit/flags.h similarity index 57% rename from tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.h rename to tensorflow/compiler/jit/flags.h index 79b47357a1..5ddea588ee 100644 --- a/tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.h +++ b/tensorflow/compiler/jit/flags.h @@ -13,10 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#ifndef TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_MARK_FOR_COMPILATION_PASS_FLAGS_H_ -#define TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_MARK_FOR_COMPILATION_PASS_FLAGS_H_ - -// Legacy flags for the XLA bridge's mark_for_compilation_pass module. +#ifndef TENSORFLOW_COMPILER_JIT_FLAGS_H_ +#define TENSORFLOW_COMPILER_JIT_FLAGS_H_ #include @@ -24,15 +22,8 @@ limitations under the License. #include "tensorflow/core/util/command_line_flags.h" namespace tensorflow { -namespace legacy_flags { - -// Append to *flag_list flag definitions associated with the XLA bridge's -// mark_for_compilation_pass module. -void AppendMarkForCompilationPassFlags( - std::vector* flag_list); -// The values of flags associated with the XLA bridge's -// mark_for_compilation_pass module. +// Flags associated with the XLA bridge's mark_for_compilation_pass module. struct MarkForCompilationPassFlags { int32 tf_xla_auto_jit; // Control compilation of operators into XLA // computations on CPU and GPU devices. 0 = use @@ -57,12 +48,56 @@ struct MarkForCompilationPassFlags { // only using XLA. }; -// Return a pointer to the MarkForCompilationPassFlags struct; +// Flags associated with the XLA bridge's xla_device module. +struct XlaDeviceFlags { + // Switch the CPU device into "on-demand" mode, where instead of + // autoclustering ops are compiled one by one just-in-time. + // Enabling this mode by a legacy flag is a temporary mechanism. When this + // feature is battle-tested, we will switch this to be a session option. + bool tf_xla_compile_on_demand; +}; + +// Flags common to the _Xla* ops and their kernels. +struct XlaOpsCommonFlags { + // If true, _XlaCompile always refuses to compile the cluster, which means the + // XLA clusters always run in the TF executor. Defaults to false. + bool tf_xla_always_defer_compilation; +}; + +// Flags for the build_xla_ops pass. +struct BuildXlaOpsPassFlags { + // Enables lazy compilation for TF/XLA (only when auto-clustering) if true. + // Defaults to true. + bool tf_xla_enable_lazy_compilation; +}; + +// Flags for the XLA bridge's dump_graph module. +struct DumpGraphFlags { + // Path prefix to which graphs dumped during debugging should be written. + string tf_dump_graph_prefix; +}; + +// Return a pointer to the DumpGraphFlags struct; // repeated calls return the same pointer. // This should be called only after Flags::Parse() has returned. + +// Getters for flags structs defined above. The first call to any of these +// parses TF_XLA_FLAGS for all of them. Those functions which return a pointer +// always return the same pointer. MarkForCompilationPassFlags* GetMarkForCompilationPassFlags(); +const BuildXlaOpsPassFlags& GetBuildXlaOpsPassFlags(); +XlaDeviceFlags* GetXlaDeviceFlags(); +const XlaOpsCommonFlags& GetXlaOpsCommonFlags(); +DumpGraphFlags* GetDumpGraphFlags(); + +// Appends the flag definitions associated with +// MarkForCompilationPassFlags/DumpGraphFlags to `flag_list`. +// +// Has the side-effect of parsing TF_XLA_FLAGS if that hasn't happened yet. +void AppendMarkForCompilationPassFlags( + std::vector* flag_list); +void AppendDumpGraphFlags(std::vector* flag_list); -} // namespace legacy_flags } // namespace tensorflow -#endif // TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_MARK_FOR_COMPILATION_PASS_FLAGS_H_ +#endif // TENSORFLOW_COMPILER_JIT_FLAGS_H_ diff --git a/tensorflow/compiler/jit/increase_dynamism_for_auto_jit_pass.cc b/tensorflow/compiler/jit/increase_dynamism_for_auto_jit_pass.cc index d984ca15cb..ce53f70b79 100644 --- a/tensorflow/compiler/jit/increase_dynamism_for_auto_jit_pass.cc +++ b/tensorflow/compiler/jit/increase_dynamism_for_auto_jit_pass.cc @@ -23,7 +23,7 @@ limitations under the License. #include "tensorflow/cc/ops/array_ops.h" #include "tensorflow/cc/ops/const_op.h" #include "tensorflow/cc/ops/math_ops.h" -#include "tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.h" +#include "tensorflow/compiler/jit/flags.h" #include "tensorflow/compiler/jit/xla_cluster_util.h" #include "tensorflow/compiler/tf2xla/cc/ops/xla_ops.h" #include "tensorflow/compiler/tf2xla/dump_graph.h" @@ -208,8 +208,12 @@ Status ComputeSliceSize(const Scope& host_scope, DCHECK_EQ(slice_size.back().type(), DT_INT64); } - *size = ops::Concat(host_scope.WithOpName("slice_size"), slice_size, - ops::Const(host_scope.WithOpName("concat_axis"), 0)); + // Trivial ConcatV2 nodes (with exactly one input) are disallowed. + *size = + slice_size.size() == 1 + ? slice_size[0] + : ops::Concat(host_scope.WithOpName("slice_size"), slice_size, + ops::Const(host_scope.WithOpName("concat_axis"), 0)); return Status::OK(); } @@ -242,6 +246,9 @@ Status ConvertTensorFlowSliceToStaticShapedSlice( .WithOpName("static_shaped_slice"), slice_inputs_int64.input, slice_inputs_int64.begin, slice_size) .node(); + + TF_RETURN_IF_ERROR(main_scope.status()); + std::vector compile_time_const_inputs; compile_time_const_inputs.push_back("size"); (*result)->AddAttr(kXlaCompileTimeConstantInputsAttr, @@ -284,49 +291,45 @@ Status RewriteSlice(Graph* g, Node* slice, const SliceInputs& slice_inputs, return Status::OK(); } -// If `n` is a slice we can rewrite to have a static shape (i.e. have the output -// shape only depend on the "size" input) then returns the a SliceInputs -// representing the inputs to `n`. Otherwise returns nullopt. -StatusOrOptional IsRewritableSlice(Node* n) { +// Return true if `n` is a slice we can rewrite to have a static shape +// (i.e. have the output shape only depend on the "size" input). +xla::StatusOr IsRewritableSlice(Node* n) { if (n->type_string() != "Slice") { - return {absl::nullopt}; + return false; } if (!GetXlaClusterForNode(*n).has_value()) { // There is no need to change slice ops outside XLA clusters. - return {absl::nullopt}; + return false; } TF_ASSIGN_OR_RETURN(absl::optional slice_inputs, GetSliceInputs(n)); if (!slice_inputs.has_value()) { - return {absl::nullopt}; + return false; } // If slice_size[i] < -1 for any i then executing the slice will throw an // error, and we don't do anything here. - bool slice_is_ok = absl::c_all_of(slice_inputs->size_as_vector, - [](int64 size_i) { return size_i >= -1; }); - if (!slice_is_ok) { - return {absl::nullopt}; - } - - return slice_inputs; + return absl::c_all_of(slice_inputs->size_as_vector, + [](int64 size_i) { return size_i >= -1; }); } Status FindAndRewriteSlices(Graph* g, bool* changed) { - std::vector> slices_to_rewrite; + std::vector slices_to_rewrite; for (Node* n : g->nodes()) { - TF_ASSIGN_OR_RETURN(absl::optional slice_inputs, - IsRewritableSlice(n)); - if (slice_inputs.has_value()) { - slices_to_rewrite.push_back({n, std::move(*slice_inputs)}); + TF_ASSIGN_OR_RETURN(bool is_rewritable, IsRewritableSlice(n)); + if (is_rewritable) { + slices_to_rewrite.push_back(n); } } - for (const auto& pair : slices_to_rewrite) { - TF_RETURN_IF_ERROR(RewriteSlice(g, pair.first, pair.second, - *GetXlaClusterForNode(*pair.first))); + for (Node* n : slices_to_rewrite) { + TF_ASSIGN_OR_RETURN(absl::optional slice_inputs, + GetSliceInputs(n)); + TF_RET_CHECK(slice_inputs.has_value()); + TF_RETURN_IF_ERROR( + RewriteSlice(g, n, *slice_inputs, *GetXlaClusterForNode(*n))); } if (!slices_to_rewrite.empty()) { @@ -342,8 +345,7 @@ Status FindAndRewriteSlices(Graph* g, bool* changed) { Status IncreaseDynamismForAutoJitPass::Run( const GraphOptimizationPassOptions& options) { - legacy_flags::MarkForCompilationPassFlags* flags = - legacy_flags::GetMarkForCompilationPassFlags(); + MarkForCompilationPassFlags* flags = GetMarkForCompilationPassFlags(); if (flags->tf_xla_clustering_debug) { dump_graph::DumpGraphToFile("before_increase_dynamism_for_auto_jit_pass", **options.graph, options.flib_def); diff --git a/tensorflow/compiler/jit/increase_dynamism_for_auto_jit_pass_test.cc b/tensorflow/compiler/jit/increase_dynamism_for_auto_jit_pass_test.cc index 0f6f612e96..a2f1b831ad 100644 --- a/tensorflow/compiler/jit/increase_dynamism_for_auto_jit_pass_test.cc +++ b/tensorflow/compiler/jit/increase_dynamism_for_auto_jit_pass_test.cc @@ -27,6 +27,7 @@ limitations under the License. namespace tensorflow { namespace { +using ::testing::_; using testing::matchers::AssignedDevice; using testing::matchers::Attr; using testing::matchers::Const; @@ -142,6 +143,26 @@ TEST(SliceToDynamicSliceRewriteTest, Basic) { EXPECT_THAT(static_shaped_slice, m_dynamic_slice); } +TEST(SliceToDynamicSliceRewriteTest, SliceFromVector) { + Scope root = Scope::NewRootScope() + .ExitOnError() + .WithAssignedDevice(kDeviceName) + .WithXlaCluster("cluster_0"); + + Output input = ops::Placeholder(root.WithOpName("input"), DT_FLOAT); + Output begin = ops::Placeholder(root.WithOpName("begin"), DT_INT32); + Output size = ops::Const(root.WithOpName("size"), {-1}); + Output slice = ops::Slice(root.WithOpName("slice"), input, begin, size); + + std::unique_ptr result; + TF_ASSERT_OK(IncreaseDynamismForAutoJit(root, &result)); + + Node* static_shaped_slice = testing::FindNodeByName( + result.get(), "slice/static_shaped_slice/static_shaped_slice"); + EXPECT_NE(static_shaped_slice, nullptr); + EXPECT_THAT(result->nodes(), Not(Contains(NodeWith(Op("ConcatV2"))))); +} + TEST(SliceToDynamicSliceRewriteTest, ControlDependencePreserved) { Scope root = Scope::NewRootScope() .ExitOnError() @@ -166,18 +187,18 @@ TEST(SliceToDynamicSliceRewriteTest, ControlDependencePreserved) { CtrlDeps(NodeWith(Op("Placeholder"), Name("control"))))); } +int64 ToInt64(int v) { return static_cast(v); } + TEST(SliceToDynamicSliceRewriteTest, Int64Indices) { Scope root = Scope::NewRootScope() .ExitOnError() .WithAssignedDevice(kDeviceName) .WithXlaCluster("cluster_0"); - auto to_int64 = [](int v) { return static_cast(v); }; - Output input = ops::Placeholder(root.WithOpName("input"), DT_FLOAT); Output begin = ops::Placeholder(root.WithOpName("begin"), DT_INT64); Output size = - ops::Const(root.WithOpName("size"), {to_int64(-1), to_int64(500)}); + ops::Const(root.WithOpName("size"), {ToInt64(-1), ToInt64(500)}); Output slice = ops::Slice(root.WithOpName("slice"), input, begin, size); std::unique_ptr result; @@ -252,13 +273,35 @@ TEST(SliceToDynamicSliceRewriteTest, DontRewriteSliceWithNonConstSize) { Attr(kXlaCompileTimeConstantInputsAttr))))); } +TEST(SliceToDynamicSliceRewriteTest, ScalarSlice) { + Scope root = Scope::NewRootScope() + .ExitOnError() + .WithAssignedDevice(kDeviceName) + .WithXlaCluster("cluster_0"); + + Output input = ops::Placeholder(root.WithOpName("input"), DT_FLOAT); + Output begin = ops::Placeholder(root.WithOpName("begin"), DT_INT64); + Output size = ops::Const(root.WithOpName("size"), {}); + Output slice = ops::Slice(root.WithOpName("slice"), input, begin, size); + + std::unique_ptr result; + TF_ASSERT_OK(IncreaseDynamismForAutoJit(root, &result)); + + Node* static_shaped_slice = testing::FindNodeByName( + result.get(), "slice/static_shaped_slice/static_shaped_slice"); + ASSERT_NE(static_shaped_slice, nullptr); + EXPECT_THAT(static_shaped_slice, + NodeWith(Op("Slice"), Attr(kXlaCompileTimeConstantInputsAttr), + Inputs(_, _, Out(NodeWith(Name(size.node()->name())))))); +} + TEST(SliceToDynamicSliceRewriteTest, IndicesNotVector) { Scope root = Scope::NewRootScope() .ExitOnError() .WithAssignedDevice(kDeviceName) .WithXlaCluster("cluster_0"); - auto to_int64 = [](int v) { return static_cast(v); }; + auto ToInt64 = [](int v) { return static_cast(v); }; Output input = ops::Placeholder(root.WithOpName("input"), DT_FLOAT); Output begin = ops::Placeholder(root.WithOpName("begin"), DT_INT64); @@ -271,7 +314,7 @@ TEST(SliceToDynamicSliceRewriteTest, IndicesNotVector) { ops::Slice(root.WithOpName("slice"), input, begin, size_placeholder); Output size = - ops::Const(root.WithOpName("size"), {{to_int64(-1)}, {to_int64(500)}}); + ops::Const(root.WithOpName("size"), {{ToInt64(-1)}, {ToInt64(500)}}); TF_ASSERT_OK(root.graph()->UpdateEdge(size.node(), 0, slice.node(), 2)); std::unique_ptr result; @@ -281,5 +324,82 @@ TEST(SliceToDynamicSliceRewriteTest, IndicesNotVector) { Not(Contains(NodeWith(Op("Slice"), Attr(kXlaCompileTimeConstantInputsAttr))))); } + +TEST(SliceToDynamicSliceRewriteTest, SliceWithSliceInput) { + Scope root = Scope::NewRootScope() + .ExitOnError() + .WithAssignedDevice(kDeviceName) + .WithXlaCluster("cluster_0"); + + Output input = ops::Placeholder(root.WithOpName("input"), DT_FLOAT); + Output begin = ops::Placeholder(root.WithOpName("begin"), DT_INT32); + Output size_a = ops::Const(root.WithOpName("size_a"), {-1, 500}); + Output slice = ops::Slice(root.WithOpName("slice"), input, begin, size_a); + + Output size_b = ops::Const(root.WithOpName("size_a"), {-1, 200}); + Output slice_with_slice_input = ops::Slice( + root.WithOpName("slice_with_slice_input"), slice, begin, size_b); + + std::unique_ptr result; + TF_ASSERT_OK(IncreaseDynamismForAutoJit(root, &result)); + + Node* static_shaped_slice = testing::FindNodeByName( + result.get(), + "slice_with_slice_input/static_shaped_slice/static_shaped_slice"); + ASSERT_NE(static_shaped_slice, nullptr); + EXPECT_EQ(static_shaped_slice->output_type(0), DT_FLOAT) + << "Expected DT_FLOAT, was " + << DataType_Name(static_shaped_slice->output_type(0)); + EXPECT_THAT( + static_shaped_slice, + NodeWith( + Op("Slice"), + Inputs(Out(NodeWith( + Op("Slice"), + Name("slice/static_shaped_slice/static_shaped_slice"))), + _, _))); +} + +TEST(SliceToDynamicSliceRewriteTest, SliceWithSliceBegin) { + Scope root = Scope::NewRootScope() + .ExitOnError() + .WithAssignedDevice(kDeviceName) + .WithXlaCluster("cluster_0"); + + Output input_float = + ops::Placeholder(root.WithOpName("input_float"), DT_FLOAT); + Output input_i64 = ops::Placeholder(root.WithOpName("input_i64"), DT_INT64); + + Output begin_begin = + ops::Placeholder(root.WithOpName("begin_begin"), DT_INT32); + Output begin_size = ops::Const(root.WithOpName("begin_size"), {-1}); + Output begin = + ops::Slice(root.WithOpName("begin"), input_i64, begin_begin, begin_size); + + Output size = + ops::Const(root.WithOpName("size"), {ToInt64(-1), ToInt64(200)}); + Output slice_with_slice_begin = ops::Slice( + root.WithOpName("slice_with_slice_begin"), input_float, begin, size); + + std::unique_ptr result; + TF_ASSERT_OK(IncreaseDynamismForAutoJit(root, &result)); + + Node* static_shaped_slice = testing::FindNodeByName( + result.get(), + "slice_with_slice_begin/static_shaped_slice/static_shaped_slice"); + ASSERT_NE(static_shaped_slice, nullptr); + EXPECT_EQ(static_shaped_slice->output_type(0), DT_FLOAT) + << "Expected DT_FLOAT, was " + << DataType_Name(static_shaped_slice->output_type(0)); + EXPECT_THAT( + static_shaped_slice, + NodeWith( + Op("Slice"), + Inputs(_, + Out(NodeWith( + Op("Slice"), + Name("begin/static_shaped_slice/static_shaped_slice"))), + _))); +} } // namespace } // namespace tensorflow diff --git a/tensorflow/compiler/jit/kernels/BUILD b/tensorflow/compiler/jit/kernels/BUILD index 830db9ebdd..0583774714 100644 --- a/tensorflow/compiler/jit/kernels/BUILD +++ b/tensorflow/compiler/jit/kernels/BUILD @@ -12,10 +12,10 @@ cc_library( hdrs = ["xla_ops.h"], deps = [ "//tensorflow/compiler/jit:common", + "//tensorflow/compiler/jit:flags", "//tensorflow/compiler/jit:xla_compilation_cache", "//tensorflow/compiler/jit:xla_device", "//tensorflow/compiler/jit:xla_launch_util", - "//tensorflow/compiler/jit/legacy_flags:xla_ops_common_flags", "//tensorflow/compiler/tf2xla:common", "//tensorflow/compiler/tf2xla:tf2xla_util", "//tensorflow/compiler/tf2xla:xla_compiler", diff --git a/tensorflow/compiler/jit/kernels/xla_ops.cc b/tensorflow/compiler/jit/kernels/xla_ops.cc index 055de7afcc..ad71df5a69 100644 --- a/tensorflow/compiler/jit/kernels/xla_ops.cc +++ b/tensorflow/compiler/jit/kernels/xla_ops.cc @@ -18,7 +18,7 @@ limitations under the License. #include "absl/container/flat_hash_map.h" #include "absl/memory/memory.h" #include "tensorflow/compiler/jit/defs.h" -#include "tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.h" +#include "tensorflow/compiler/jit/flags.h" #include "tensorflow/compiler/tf2xla/shape_util.h" #include "tensorflow/compiler/tf2xla/tf2xla_util.h" #include "tensorflow/compiler/tf2xla/xla_compiler.h" @@ -418,7 +418,7 @@ void XlaCompileOp::Compute(OpKernelContext* ctx) { cannot_compile_cluster = cannot_compile_cluster_; } - if (legacy_flags::GetXlaOpsCommonFlags().tf_xla_always_defer_compilation || + if (GetXlaOpsCommonFlags().tf_xla_always_defer_compilation || cannot_compile_cluster) { executable = nullptr; } else { diff --git a/tensorflow/compiler/jit/legacy_flags/BUILD b/tensorflow/compiler/jit/legacy_flags/BUILD deleted file mode 100644 index 5fa6c85f06..0000000000 --- a/tensorflow/compiler/jit/legacy_flags/BUILD +++ /dev/null @@ -1,65 +0,0 @@ -# Legacy command line flags for the XLA bridge libraries. - -# Please do not add more flags to this package. - -# The XLA bridge libraries were written in an environment that allowed -# command-line flags to be scattered freely throughout the libraries. This -# model, while initially convenient, leads to a proliferation in unused command -# line flags in tests and binaries, and serious problems in servers, where one -# might wish parameters to be different in independent RPC calls to the same -# routine. -# -# Please don't add more flags. If you're a library author, pass options and -# parameters explicitly through the library's interface. - -licenses(["notice"]) # Apache 2.0 - -package(default_visibility = ["//tensorflow:internal"]) - -cc_library( - name = "mark_for_compilation_pass_flags", - srcs = ["mark_for_compilation_pass_flags.cc"], - hdrs = ["mark_for_compilation_pass_flags.h"], - deps = - [ - "//tensorflow/compiler/xla:parse_flags_from_env", - "//tensorflow/core:framework_internal", - "//tensorflow/core:lib", - ], -) - -cc_library( - name = "xla_device_flags", - srcs = ["xla_device_flags.cc"], - hdrs = ["xla_device_flags.h"], - deps = - [ - "//tensorflow/compiler/xla:parse_flags_from_env", - "//tensorflow/core:framework_internal", - "//tensorflow/core:lib", - ], -) - -cc_library( - name = "build_xla_ops_pass_flags", - srcs = ["build_xla_ops_pass_flags.cc"], - hdrs = ["build_xla_ops_pass_flags.h"], - deps = - [ - "//tensorflow/compiler/xla:parse_flags_from_env", - "//tensorflow/core:framework_internal", - "//tensorflow/core:lib", - ], -) - -cc_library( - name = "xla_ops_common_flags", - srcs = ["xla_ops_common_flags.cc"], - hdrs = ["xla_ops_common_flags.h"], - deps = - [ - "//tensorflow/compiler/xla:parse_flags_from_env", - "//tensorflow/core:framework_internal", - "//tensorflow/core:lib", - ], -) diff --git a/tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.cc b/tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.cc deleted file mode 100644 index 961c17c17e..0000000000 --- a/tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.cc +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include // NOLINT - -#include "tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.h" -#include "tensorflow/compiler/xla/parse_flags_from_env.h" -#include "tensorflow/core/util/command_line_flags.h" - -namespace tensorflow { -namespace legacy_flags { -namespace { - -BuildXlaOpsPassFlags* flags; -std::vector* flag_list; -std::once_flag flags_init; - -void AllocateAndParseFlags() { - flags = new BuildXlaOpsPassFlags; - flags->tf_xla_enable_lazy_compilation = true; - flag_list = new std::vector({ - Flag("tf_xla_enable_lazy_compilation", - &flags->tf_xla_enable_lazy_compilation, ""), - }); - xla::ParseFlagsFromEnv(*flag_list); -} - -} // namespace - -const BuildXlaOpsPassFlags& GetBuildXlaOpsPassFlags() { - std::call_once(flags_init, &AllocateAndParseFlags); - return *flags; -} -} // namespace legacy_flags -} // namespace tensorflow diff --git a/tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.h b/tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.h deleted file mode 100644 index 9aa5cf64d6..0000000000 --- a/tensorflow/compiler/jit/legacy_flags/build_xla_ops_pass_flags.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#ifndef TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_BUILD_XLA_OPS_PASS_FLAGS_H_ -#define TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_BUILD_XLA_OPS_PASS_FLAGS_H_ - -namespace tensorflow { -namespace legacy_flags { - -// Flags for the build_xla_ops pass. -struct BuildXlaOpsPassFlags { - // Enables lazy compilation for TF/XLA (only when auto-clustering) if true. - // Defaults to true. - bool tf_xla_enable_lazy_compilation; -}; - -// Parses the flags in BuildXlaOpsPassFlags from the TF_XLA_FLAGS environment -// variable and returns a reference to the parsed copy. Parses TF_XLA_FLAGS -// only the first time this routine is called. -const BuildXlaOpsPassFlags& GetBuildXlaOpsPassFlags(); - -} // namespace legacy_flags -} // namespace tensorflow - -#endif // TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_BUILD_XLA_OPS_PASS_FLAGS_H_ diff --git a/tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.cc b/tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.cc deleted file mode 100644 index bad306e0b0..0000000000 --- a/tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.cc +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -// Legacy flags for the XLA bridge's mark_for_compilation_pass module. - -#include -#include - -#include "tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.h" -#include "tensorflow/compiler/xla/parse_flags_from_env.h" -#include "tensorflow/core/platform/logging.h" -#include "tensorflow/core/platform/types.h" -#include "tensorflow/core/util/command_line_flags.h" - -namespace tensorflow { -namespace legacy_flags { - -// Pointers to the parsed value of the flags and flag descriptors, initialized -// via flags_init. -static MarkForCompilationPassFlags* flags; -static std::vector* flag_list; -static std::once_flag flags_init; - -// Allocate *flags. Called via call_once(&flags_init,...). -static void AllocateFlags() { - flags = new MarkForCompilationPassFlags; - flags->tf_xla_auto_jit = 0; - flags->tf_xla_min_cluster_size = 2; - flags->tf_xla_max_cluster_size = std::numeric_limits::max(); - flags->tf_xla_clustering_debug = false; - flags->tf_xla_cpu_global_jit = false; - flags->tf_xla_clustering_fuel = std::numeric_limits::max(); - flags->tf_xla_fusion_only = false; - flag_list = new std::vector( - {Flag("tf_xla_auto_jit", &flags->tf_xla_auto_jit, - "Control compilation of operators into XLA computations on CPU and " - "GPU devices. 0 = use ConfigProto setting; -1 = off; 1 = on for " - "things very likely to be improved; 2 = on for everything. " - "Experimental."), - Flag("tf_xla_min_cluster_size", &flags->tf_xla_min_cluster_size, - "Minimum number of operators in an XLA compilation. Ignored for " - "operators placed on an XLA device or operators explicitly marked " - "for compilation."), - Flag("tf_xla_max_cluster_size", &flags->tf_xla_max_cluster_size, - "Maximum number of operators in an XLA compilation."), - Flag("tf_xla_clustering_debug", &flags->tf_xla_clustering_debug, - "Dump graphs during XLA compilation."), - Flag("tf_xla_cpu_global_jit", &flags->tf_xla_cpu_global_jit, - "Enables global JIT compilation for CPU via SessionOptions."), - Flag("tf_xla_clustering_fuel", &flags->tf_xla_clustering_fuel, - "Places an artificial limit on the number of ops marked as " - "eligible for clustering."), - Flag("tf_xla_fusion_only", &flags->tf_xla_fusion_only, - "enable fusion of element-wise operations only using XLA when " - "global_jit_level is ON*.")}); - xla::ParseFlagsFromEnv(*flag_list); - - if (VLOG_IS_ON(1)) { - VLOG(1) << "Parsed MarkForCompilationPassFlags:"; - VLOG(1) << " tf_xla_auto_jit = " << flags->tf_xla_auto_jit; - VLOG(1) << " tf_xla_min_cluster_size = " << flags->tf_xla_min_cluster_size; - VLOG(1) << " tf_xla_max_cluster_size = " << flags->tf_xla_max_cluster_size; - VLOG(1) << " tf_xla_clustering_debug = " << flags->tf_xla_clustering_debug; - VLOG(1) << " tf_xla_cpu_global_jit = " << flags->tf_xla_cpu_global_jit; - VLOG(1) << " tf_xla_clustering_fuel = " << flags->tf_xla_clustering_fuel; - VLOG(1) << " tf_xla_fusion_only = " << flags->tf_xla_fusion_only; - } -} - -// Append to *append_to flag definitions associated with the XLA bridge's -// mark_for_compilation_pass module. -void AppendMarkForCompilationPassFlags(std::vector* append_to) { - std::call_once(flags_init, &AllocateFlags); - append_to->insert(append_to->end(), flag_list->begin(), flag_list->end()); -} - -// Return a pointer to the MarkForCompilationPassFlags struct; -// repeated calls return the same pointer. -// This should be called only after Flags::Parse() has returned. -MarkForCompilationPassFlags* GetMarkForCompilationPassFlags() { - std::call_once(flags_init, &AllocateFlags); - return flags; -} - -} // namespace legacy_flags -} // namespace tensorflow diff --git a/tensorflow/compiler/jit/legacy_flags/xla_device_flags.cc b/tensorflow/compiler/jit/legacy_flags/xla_device_flags.cc deleted file mode 100644 index 76b80d3034..0000000000 --- a/tensorflow/compiler/jit/legacy_flags/xla_device_flags.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -// Legacy flags for the XLA bridge's xla_device module. - -#include -#include - -#include "tensorflow/compiler/jit/legacy_flags/xla_device_flags.h" -#include "tensorflow/compiler/xla/parse_flags_from_env.h" -#include "tensorflow/core/platform/types.h" -#include "tensorflow/core/util/command_line_flags.h" - -namespace tensorflow { -namespace legacy_flags { - -// Pointers to the parsed value of the flags and flag descriptors, initialized -// via flags_init. -static XlaDeviceFlags* flags; -static std::vector* flag_list; -static std::once_flag flags_init; - -// Allocate *flags. Called via call_once(&flags_init,...). -static void AllocateFlags() { - flags = new XlaDeviceFlags; - flags->tf_xla_compile_on_demand = false; - flag_list = new std::vector({ - Flag("tf_xla_compile_on_demand", &flags->tf_xla_compile_on_demand, - "Switch a device into 'on-demand' mode, where instead of " - "autoclustering ops are compiled one by one just-in-time."), - }); - xla::ParseFlagsFromEnv(*flag_list); -} - -// Return a pointer to the XlaDeviceFlags struct; -// repeated calls return the same pointer. -// This should be called only after Flags::Parse() has returned. -XlaDeviceFlags* GetXlaDeviceFlags() { - std::call_once(flags_init, &AllocateFlags); - return flags; -} - -} // namespace legacy_flags -} // namespace tensorflow diff --git a/tensorflow/compiler/jit/legacy_flags/xla_device_flags.h b/tensorflow/compiler/jit/legacy_flags/xla_device_flags.h deleted file mode 100644 index 27b22121ac..0000000000 --- a/tensorflow/compiler/jit/legacy_flags/xla_device_flags.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#ifndef TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_XLA_DEVICE_FLAGS_H_ -#define TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_XLA_DEVICE_FLAGS_H_ - -// Legacy flags for the XLA bridge's xla_device module. - -#include - -#include "tensorflow/core/platform/types.h" -#include "tensorflow/core/util/command_line_flags.h" - -namespace tensorflow { -namespace legacy_flags { - -// The values of flags associated with the XLA bridge's -// xla_device module. -typedef struct { - // Switch the CPU device into "on-demand" mode, where instead of - // autoclustering ops are compiled one by one just-in-time. - // Enabling this mode by a legacy flag is a temporary mechanism. When this - // feature is battle-tested, we will switch this to be a session option. - bool tf_xla_compile_on_demand; -} XlaDeviceFlags; - -// Return a pointer to the XlaDeviceFlags struct; -// repeated calls return the same pointer. -// This should be called only after Flags::Parse() has returned. -XlaDeviceFlags* GetXlaDeviceFlags(); - -} // namespace legacy_flags -} // namespace tensorflow - -#endif // TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_XLA_DEVICE_FLAGS_H_ diff --git a/tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.cc b/tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.cc deleted file mode 100644 index 1443d48a73..0000000000 --- a/tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.cc +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include // NOLINT -#include - -#include "tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.h" -#include "tensorflow/compiler/xla/parse_flags_from_env.h" -#include "tensorflow/core/platform/logging.h" -#include "tensorflow/core/util/command_line_flags.h" - -namespace tensorflow { -namespace legacy_flags { - -XlaOpsCommonFlags* flags; -std::vector* flag_list; -std::once_flag flags_init; - -void AllocateAndParseFlags() { - flags = new XlaOpsCommonFlags; - flags->tf_xla_always_defer_compilation = false; - flag_list = new std::vector({ - Flag("tf_xla_always_defer_compilation", - &flags->tf_xla_always_defer_compilation, ""), - }); - xla::ParseFlagsFromEnv(*flag_list); - - if (VLOG_IS_ON(1)) { - VLOG(1) << "Parsed XlaOpsCommonFlags:"; - VLOG(1) << " tf_xla_always_defer_compilation = " - << flags->tf_xla_always_defer_compilation; - } -} - -const XlaOpsCommonFlags& GetXlaOpsCommonFlags() { - std::call_once(flags_init, &AllocateAndParseFlags); - return *flags; -} -} // namespace legacy_flags -} // namespace tensorflow diff --git a/tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.h b/tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.h deleted file mode 100644 index 7c5c1818ef..0000000000 --- a/tensorflow/compiler/jit/legacy_flags/xla_ops_common_flags.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -#ifndef TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_XLA_OPS_COMMON_FLAGS_H_ -#define TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_XLA_OPS_COMMON_FLAGS_H_ - -namespace tensorflow { -namespace legacy_flags { - -// Flags common to the _Xla* ops and their kernels. -struct XlaOpsCommonFlags { - // If true, _XlaCompile always refuses to compile the cluster, which means the - // XLA clusters always run in the TF executor. Defaults to false. - bool tf_xla_always_defer_compilation; -}; - -// Parses the flags in XlaOpsCommonFlags from the TF_XLA_FLAGS environment -// variable and returns a reference to the parsed copy. Parses TF_XLA_FLAGS -// only the first time this routine is called. -const XlaOpsCommonFlags& GetXlaOpsCommonFlags(); - -} // namespace legacy_flags -} // namespace tensorflow - -#endif // TENSORFLOW_COMPILER_JIT_LEGACY_FLAGS_XLA_OPS_COMMON_FLAGS_H_ diff --git a/tensorflow/compiler/jit/mark_for_compilation_pass.cc b/tensorflow/compiler/jit/mark_for_compilation_pass.cc index 70033cae0a..6618e3a58a 100644 --- a/tensorflow/compiler/jit/mark_for_compilation_pass.cc +++ b/tensorflow/compiler/jit/mark_for_compilation_pass.cc @@ -24,8 +24,8 @@ limitations under the License. #include "absl/container/flat_hash_set.h" #include "tensorflow/compiler/jit/deadness_analysis.h" #include "tensorflow/compiler/jit/defs.h" +#include "tensorflow/compiler/jit/flags.h" #include "tensorflow/compiler/jit/graphcycles/graphcycles.h" -#include "tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.h" #include "tensorflow/compiler/jit/union_find.h" #include "tensorflow/compiler/jit/xla_cluster_util.h" #include "tensorflow/compiler/tf2xla/const_analysis.h" @@ -72,6 +72,11 @@ struct OperationFilter { // to resort to a dummy implementation. Currently Assert and CheckNumerics ops // have dummy XLA implementations. bool allow_dummy_ops; + + // Whether ops that produce or consume DT_VARIANT values are allowed. We + // don't auto-cluster these ops because we don't yet support live-in or + // live-out DT_VARIANT values. + bool allow_ops_producing_or_consuming_variant; }; bool IsDummyImplOp(absl::string_view op_name) { @@ -81,7 +86,13 @@ bool IsDummyImplOp(absl::string_view op_name) { bool IsStatefulRandomOp(absl::string_view op_name) { return op_name == "RandomUniform" || op_name == "RandomShuffle" || op_name == "RandomUniformInt" || op_name == "RandomStandardNormal" || - op_name == "TruncatedNormal"; + op_name == "TruncatedNormal" || op_name == "Multinomial"; +} + +bool OpProducesOrConsumesVariant(const Node& node) { + auto is_variant = [](DataType dtype) { return dtype == DT_VARIANT; }; + return absl::c_any_of(node.input_types(), is_variant) || + absl::c_any_of(node.output_types(), is_variant); } bool HasXLAKernel(const Node& node, const DeviceType& jit_device_type) { @@ -246,6 +257,10 @@ bool IsCompilableCall(const NodeDef& call_def, if (!op_filter.allow_dummy_ops && IsDummyImplOp(node->type_string())) { return false; } + if (!op_filter.allow_ops_producing_or_consuming_variant && + OpProducesOrConsumesVariant(*node)) { + return false; + } if (!HasXLAKernel(*node, jit_device_type) && !IsCompilableCall(node->def(), jit_device_type, op_filter, depth + 1, lib_runtime)) { @@ -427,8 +442,7 @@ Status FindCompilationCandidates( BackwardsConstAnalysis(graph, /*compile_time_const_arg_indices=*/nullptr, &compile_time_const_nodes)); - int64& fuel = - legacy_flags::GetMarkForCompilationPassFlags()->tf_xla_clustering_fuel; + int64& fuel = GetMarkForCompilationPassFlags()->tf_xla_clustering_fuel; // Iterate over nodes in sorted order so that compiler fuel is deterministic. // We can't simply pass op_nodes().begin() and op_nodes().end to the @@ -471,16 +485,15 @@ Status FindCompilationCandidates( XlaOpRegistry::GetCompilationDevice(device_type.type(), ®istration)); DeviceType jit_device_type(registration->compilation_device_name); + bool always_auto_cluster = registration->autoclustering_policy == + XlaOpRegistry::AutoclusteringPolicy::kAlways; + OperationFilter op_filter; op_filter.allow_resource_ops = registration->compile_resource_ops; - op_filter.allow_stateful_rng_ops = - (registration->autoclustering_policy == - XlaOpRegistry::AutoclusteringPolicy::kAlways); - op_filter.allow_control_trigger = - (registration->autoclustering_policy == - XlaOpRegistry::AutoclusteringPolicy::kAlways); - op_filter.allow_dummy_ops = (registration->autoclustering_policy == - XlaOpRegistry::AutoclusteringPolicy::kAlways); + op_filter.allow_stateful_rng_ops = always_auto_cluster; + op_filter.allow_control_trigger = always_auto_cluster; + op_filter.allow_dummy_ops = always_auto_cluster; + op_filter.allow_ops_producing_or_consuming_variant = always_auto_cluster; if (!HasXLAKernel(*node, jit_device_type) && !IsCompilableCall(node->def(), jit_device_type, op_filter, 0, @@ -504,6 +517,12 @@ Status FindCompilationCandidates( << node->type_string() << ")"; continue; } + if (!op_filter.allow_ops_producing_or_consuming_variant && + OpProducesOrConsumesVariant(*node)) { + VLOG(2) << "Rejecting " << node->name() + << ": produces or consumes DT_VARIANT"; + continue; + } if (!op_filter.allow_resource_ops && (HasResourceOutput(*node) || IsNonResourceVarResourceOp(*node))) { @@ -607,8 +626,7 @@ OptimizerOptions::GlobalJitLevel GetGlobalJitLevel( // To set compilation to be on by default, change the following line. global_jit_level = OptimizerOptions::OFF; } - legacy_flags::MarkForCompilationPassFlags* flags = - legacy_flags::GetMarkForCompilationPassFlags(); + MarkForCompilationPassFlags* flags = GetMarkForCompilationPassFlags(); if (flags->tf_xla_auto_jit == -1 || (1 <= flags->tf_xla_auto_jit && flags->tf_xla_auto_jit <= 2)) { // If the flag tf_xla_auto_jit is a valid, non-zero setting, it overrides @@ -641,6 +659,7 @@ bool IsCompilable(FunctionLibraryRuntime* flr, const NodeDef& ndef) { op_filter.allow_stateful_rng_ops = true; op_filter.allow_control_trigger = true; op_filter.allow_dummy_ops = true; + op_filter.allow_ops_producing_or_consuming_variant = true; return IsCompilableCall(ndef, jit_device_type, op_filter, 0, flr); } @@ -651,8 +670,7 @@ Status MarkForCompilationPass::Run( // device ahead of time. OptimizerOptions::GlobalJitLevel global_jit_level = GetGlobalJitLevel(options); - legacy_flags::MarkForCompilationPassFlags* flags = - legacy_flags::GetMarkForCompilationPassFlags(); + MarkForCompilationPassFlags* flags = GetMarkForCompilationPassFlags(); bool fusion_only = flags->tf_xla_fusion_only; VLOG(1) << "flags->tf_xla_fusion_only = " << flags->tf_xla_fusion_only; @@ -953,8 +971,7 @@ Status MarkForCompilationPass::RunImpl( OptimizerOptions::GlobalJitLevel global_jit_level = GetGlobalJitLevel(options); - legacy_flags::MarkForCompilationPassFlags* flags = - legacy_flags::GetMarkForCompilationPassFlags(); + MarkForCompilationPassFlags* flags = GetMarkForCompilationPassFlags(); // Repeatedly contract edges between clusters that are on the same device, // provided the contraction would not create a cycle. diff --git a/tensorflow/compiler/jit/mark_for_compilation_pass_test.cc b/tensorflow/compiler/jit/mark_for_compilation_pass_test.cc index 24d78c0772..bf2c5508ea 100644 --- a/tensorflow/compiler/jit/mark_for_compilation_pass_test.cc +++ b/tensorflow/compiler/jit/mark_for_compilation_pass_test.cc @@ -22,6 +22,7 @@ limitations under the License. #include "tensorflow/cc/ops/array_ops.h" #include "tensorflow/cc/ops/control_flow_ops_internal.h" #include "tensorflow/cc/ops/function_ops.h" +#include "tensorflow/cc/ops/list_ops.h" #include "tensorflow/cc/ops/resource_variable_ops.h" #include "tensorflow/cc/ops/sendrecv_ops.h" #include "tensorflow/cc/ops/standard_ops.h" @@ -1147,5 +1148,80 @@ TEST(XlaCompilationTest, DontAutoClusterDummyOps) { EXPECT_EQ(clusters["test/check"], ""); } +TEST(XlaCompilationTest, DontAutoClusterOpsProducingVariant) { + Scope root = Scope::NewRootScope().ExitOnError(); + Output a = ops::Placeholder(root.WithOpName("test/a"), DT_INT64); + Output b = ops::Placeholder(root.WithOpName("test/b"), DT_INT64); + + Output cast_a = ops::Cast(root.WithOpName("test/cast_a"), a, DT_INT32); + Output cast_b = ops::Cast(root.WithOpName("test/cast_b"), b, DT_INT32); + + Output tensor_list_reserve = ops::TensorListReserve( + root.WithOpName("test/tensor_list_reserve"), cast_a, cast_b, DT_FLOAT); + + std::unique_ptr graph(new Graph(OpRegistry::Global())); + TF_ASSERT_OK(root.ToGraph(graph.get())); + + TF_ASSERT_OK(MarkForCompilationPassTestHelper::MarkForCompilation(&graph)); + + std::unordered_map clusters = GetClusters(*graph); + EXPECT_EQ(clusters["test/tensor_list_reserve"], ""); +} + +TEST(XlaCompilationTest, DontAutoClusterOpsConsumingVariant) { + Scope root = Scope::NewRootScope().ExitOnError(); + Output dummy_input = + ops::Placeholder(root.WithOpName("test/dummy_input"), DT_INT64); + Output variant_input = + ops::Placeholder(root.WithOpName("test/variant_input"), DT_VARIANT); + + // Create one more node so that we don't avoid creating a cluster solely + // because it would be trivial. + Output dummy_cast = + ops::Cast(root.WithOpName("test/dummy_cast"), dummy_input, DT_INT32); + + Output tensor_list_element_shape = ops::TensorListElementShape( + root.WithOpName("test/tensor_list_element_shape"), variant_input, + DT_INT32); + + root.graph()->AddControlEdge(dummy_cast.node(), + tensor_list_element_shape.node()); + + std::unique_ptr graph(new Graph(OpRegistry::Global())); + TF_ASSERT_OK(root.ToGraph(graph.get())); + + TF_ASSERT_OK(MarkForCompilationPassTestHelper::MarkForCompilation(&graph)); + + std::unordered_map clusters = GetClusters(*graph); + EXPECT_EQ(clusters["test/tensor_list_element_shape"], ""); +} + +TEST(XlaCompilationTest, ClusterOpsProducingVariantIfOnXlaDevice) { + Scope root = Scope::NewRootScope().ExitOnError(); + Output a = ops::Placeholder(root.WithOpName("test/a"), DT_INT64); + Output b = ops::Placeholder(root.WithOpName("test/b"), DT_INT64); + + Output cast_a = ops::Cast(root.WithOpName("test/cast_a"), a, DT_INT32); + Output cast_b = ops::Cast(root.WithOpName("test/cast_b"), b, DT_INT32); + + Output tensor_list_reserve = ops::TensorListReserve( + root.WithOpName("test/tensor_list_reserve"), cast_a, cast_b, DT_FLOAT); + + std::unique_ptr graph(new Graph(OpRegistry::Global())); + TF_ASSERT_OK(root.ToGraph(graph.get())); + + string xla_cpu_device = "/job:worker/replica:0/task:0/device:XLA_CPU:0"; + for (Node* n : graph->nodes()) { + if (absl::StartsWith(n->name(), /*prefix=*/"test/")) { + n->set_assigned_device_name(xla_cpu_device); + } + } + + TF_ASSERT_OK(MarkForCompilationPassTestHelper::MarkForCompilation(&graph)); + + std::unordered_map clusters = GetClusters(*graph); + EXPECT_NE(clusters["test/tensor_list_reserve"], ""); +} + } // namespace } // namespace tensorflow diff --git a/tensorflow/compiler/jit/mark_for_compilation_pass_test_helper.cc b/tensorflow/compiler/jit/mark_for_compilation_pass_test_helper.cc index d56d0f8ccf..64a3301745 100644 --- a/tensorflow/compiler/jit/mark_for_compilation_pass_test_helper.cc +++ b/tensorflow/compiler/jit/mark_for_compilation_pass_test_helper.cc @@ -34,15 +34,9 @@ namespace tensorflow { // // It may be worth refactoring out XlaOpRegistry::RegisterCompilationDevice to // make this more direct, but probably not worth it solely for this test. - std::vector devices; + std::vector> devices; TF_RETURN_IF_ERROR(DeviceFactory::AddDevices(*session_options, "", &devices)); - auto delete_devices = gtl::MakeCleanup([&] { - for (Device* d : devices) { - delete d; - } - }); - GraphOptimizationPassOptions opt_options; opt_options.graph = graph; opt_options.session_options = session_options; diff --git a/tensorflow/compiler/jit/ops/BUILD b/tensorflow/compiler/jit/ops/BUILD index f72224545b..64409d9334 100644 --- a/tensorflow/compiler/jit/ops/BUILD +++ b/tensorflow/compiler/jit/ops/BUILD @@ -18,3 +18,9 @@ tf_gen_op_wrapper_py( out = "xla_ops.py", deps = ["//tensorflow/compiler/jit/ops:xla_ops"], ) + +py_library( + name = "xla_ops_grad", + srcs = ["xla_ops_grad.py"], + deps = ["//tensorflow/python:framework_ops"], +) diff --git a/tensorflow/contrib/estimator/python/estimator/dnn.py b/tensorflow/compiler/jit/ops/xla_ops_grad.py similarity index 62% rename from tensorflow/contrib/estimator/python/estimator/dnn.py rename to tensorflow/compiler/jit/ops/xla_ops_grad.py index 10f657df8d..2d31d8dc71 100644 --- a/tensorflow/contrib/estimator/python/estimator/dnn.py +++ b/tensorflow/compiler/jit/ops/xla_ops_grad.py @@ -1,3 +1,4 @@ +"""Gradients for XLA ops.""" # Copyright 2018 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -12,21 +13,17 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""dnn python module. - -Importing from tensorflow.python.estimator is unsupported -and will soon break! -""" -# pylint: disable=unused-import,g-bad-import-order,g-import-not-at-top,wildcard-import from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow_estimator.contrib.estimator.python.estimator import dnn +from tensorflow.python.framework import ops -# Include attrs that start with single underscore. -_HAS_DYNAMIC_ATTRIBUTES = True -dnn.__all__ = [s for s in dir(dnn) if not s.startswith('__')] -from tensorflow_estimator.contrib.estimator.python.estimator.dnn import * +@ops.RegisterGradient("XlaClusterOutput") +def _XlaClusterOutputGrad(_, grad): + del grad # unused + raise RuntimeError("Gradient computation of graph in xla.compile() is " + "prohibited because it can cause performance degradation." + "Please move gradient computation inside xla.compile().") diff --git a/tensorflow/compiler/jit/partially_decluster_pass.cc b/tensorflow/compiler/jit/partially_decluster_pass.cc index 36b345ecbf..42ea3926e1 100644 --- a/tensorflow/compiler/jit/partially_decluster_pass.cc +++ b/tensorflow/compiler/jit/partially_decluster_pass.cc @@ -26,6 +26,10 @@ limitations under the License. namespace tensorflow { namespace { + +bool NotBackedge(const Edge& edge) { return !edge.src()->IsNextIteration(); } + +namespace reduce_device_to_host_copies { Status FindNodesToDecluster(const Graph& graph, absl::flat_hash_set* result, absl::Span post_order) { @@ -140,8 +144,6 @@ Status PartiallyDeclusterNode(Graph* graph, Node* n) { return Status::OK(); } -bool NotBackedge(const Edge& edge) { return !edge.src()->IsNextIteration(); } - // Clones nodes to outside their cluster to avoid device-to-host copies. For // instance, converts this: // @@ -168,7 +170,7 @@ bool NotBackedge(const Edge& edge) { return !edge.src()->IsNextIteration(); } // where the ===> arrow has a hostmem source and destination and would entail a // device to host copy if the source and destination were not in the same XLA // cluster. -Status PartiallyDeclusterToRemoveDeviceToHostCopies(Graph* graph) { +Status PartiallyDeclusterGraph(Graph* graph) { // When deciding whether to decluster a particular node, we base our decision // on if we've decided that some of its consumers have to be declustered too. // Iterating the graph in post-order guarantees that consumers have been @@ -206,7 +208,9 @@ Status PartiallyDeclusterToRemoveDeviceToHostCopies(Graph* graph) { return Status::OK(); } +} // namespace reduce_device_to_host_copies +namespace reduce_recompilation { bool IsIntraClusterEdge(const Edge& edge) { absl::optional src_cluster_name = GetXlaClusterForNode(*edge.src()); @@ -269,7 +273,7 @@ Status MustCompileNode(const Node* n, bool* must_compile) { // regress performance in any significant manner. We will have to revisit this // algorith with a more complex cost model if this assumption turns out to be // incorrect. -Status DeclusterNodesToReduceRecompilations(Graph* graph) { +Status PartiallyDeclusterGraph(Graph* graph) { std::vector compile_time_const_nodes(graph->num_node_ids()); TF_RETURN_IF_ERROR(BackwardsConstAnalysis( *graph, nullptr, &compile_time_const_nodes, IsIntraClusterEdge)); @@ -322,7 +326,7 @@ Status DeclusterNodesToReduceRecompilations(Graph* graph) { return Status::OK(); } - +} // namespace reduce_recompilation } // namespace Status PartiallyDeclusterPass::Run( @@ -334,8 +338,9 @@ Status PartiallyDeclusterPass::Run( Graph* graph = options.graph->get(); - TF_RETURN_IF_ERROR(PartiallyDeclusterToRemoveDeviceToHostCopies(graph)); - TF_RETURN_IF_ERROR(DeclusterNodesToReduceRecompilations(graph)); + TF_RETURN_IF_ERROR( + reduce_device_to_host_copies::PartiallyDeclusterGraph(graph)); + TF_RETURN_IF_ERROR(reduce_recompilation::PartiallyDeclusterGraph(graph)); return Status::OK(); } diff --git a/tensorflow/compiler/jit/partially_decluster_pass_test.cc b/tensorflow/compiler/jit/partially_decluster_pass_test.cc index 1fc5da5071..38a54cc5ef 100644 --- a/tensorflow/compiler/jit/partially_decluster_pass_test.cc +++ b/tensorflow/compiler/jit/partially_decluster_pass_test.cc @@ -386,7 +386,7 @@ TEST(PartiallyDeclusterPassTest, DontDeclusterXlaDeviceOps) { TF_ASSERT_OK(s.ToGraph(graph.get())); // This is needed to register the XLA_GPU device. - std::vector devices; + std::vector> devices; TF_ASSERT_OK(DeviceFactory::AddDevices( SessionOptions(), "/job:localhost/replica:0/task:0", &devices)); @@ -400,10 +400,6 @@ TEST(PartiallyDeclusterPassTest, DontDeclusterXlaDeviceOps) { TF_ASSERT_OK(PartiallyDecluster(&graph)); EXPECT_EQ(GetXlaClusterForNode(*n), "cluster_0"); - - for (Device* d : devices) { - delete d; - } } TEST(PartiallyDeclusterPassTest, DontDeclusterNonTensorFlowOps) { diff --git a/tensorflow/compiler/jit/xla_cpu_device.cc b/tensorflow/compiler/jit/xla_cpu_device.cc index 116e075603..7df898ad12 100644 --- a/tensorflow/compiler/jit/xla_cpu_device.cc +++ b/tensorflow/compiler/jit/xla_cpu_device.cc @@ -17,8 +17,8 @@ limitations under the License. // operators using XLA via the XLA "Host" (CPU) backend. #include "absl/memory/memory.h" +#include "tensorflow/compiler/jit/flags.h" #include "tensorflow/compiler/jit/kernels/xla_ops.h" -#include "tensorflow/compiler/jit/legacy_flags/xla_device_flags.h" #include "tensorflow/compiler/jit/xla_compile_on_demand_op.h" #include "tensorflow/compiler/jit/xla_device.h" #include "tensorflow/compiler/jit/xla_device_ops.h" @@ -31,13 +31,13 @@ namespace tensorflow { class XlaCpuDeviceFactory : public DeviceFactory { public: Status CreateDevices(const SessionOptions& options, const string& name_prefix, - std::vector* devices) override; + std::vector>* devices) override; }; -Status XlaCpuDeviceFactory::CreateDevices(const SessionOptions& session_options, - const string& name_prefix, - std::vector* devices) { - legacy_flags::XlaDeviceFlags* flags = legacy_flags::GetXlaDeviceFlags(); +Status XlaCpuDeviceFactory::CreateDevices( + const SessionOptions& session_options, const string& name_prefix, + std::vector>* devices) { + XlaDeviceFlags* flags = GetXlaDeviceFlags(); bool compile_on_demand = flags->tf_xla_compile_on_demand; XlaOpRegistry::DeviceRegistration registration; @@ -63,8 +63,7 @@ Status XlaCpuDeviceFactory::CreateDevices(const SessionOptions& session_options, options.device_ordinal = 0; options.compilation_device_name = DEVICE_CPU_XLA_JIT; options.use_multiple_streams = false; - auto device = absl::make_unique(session_options, options); - devices->push_back(device.release()); + devices->push_back(absl::make_unique(session_options, options)); return Status::OK(); } diff --git a/tensorflow/compiler/jit/xla_device.cc b/tensorflow/compiler/jit/xla_device.cc index 5c1b55cb57..4201ff91a8 100644 --- a/tensorflow/compiler/jit/xla_device.cc +++ b/tensorflow/compiler/jit/xla_device.cc @@ -218,6 +218,9 @@ XlaDevice::XlaDevice(const SessionOptions& session_options, XlaDevice::~XlaDevice() { VLOG(1) << "Destroying XLA device " << jit_device_name_ << " " << this; mutex_lock lock(mu_); + while (outstanding_asynchronous_operations_ > 0) { + outstanding_asynchronous_operations_cv_.wait(lock); + } if (device_context_) { device_context_->Unref(); } @@ -384,6 +387,7 @@ void XlaDevice::ComputeAsync(AsyncOpKernel* op_kernel, OpKernelContext* context, Status XlaDevice::Sync() { VLOG(1) << "XlaDevice::Sync"; + tracing::ScopedActivity activity("XlaDevice::Sync", /*is_expensive=*/true); std::shared_ptr stream; { mutex_lock lock(mu_); @@ -391,13 +395,46 @@ Status XlaDevice::Sync() { } if (!stream) return Status::OK(); - if (!stream->parent()->SynchronizeAllActivity() || !stream->ok()) { + Status status = stream->BlockHostUntilDone(); + { + mutex_lock lock(mu_); + while (outstanding_asynchronous_operations_ > 0) { + outstanding_asynchronous_operations_cv_.wait(lock); + } + } + TF_RETURN_IF_ERROR(status); + if (!stream->ok()) { return errors::Internal("XlaDevice::Sync() failed."); } VLOG(1) << "XlaDevice::Sync completed"; return Status::OK(); } +void XlaDevice::Sync(const DoneCallback& done) { + VLOG(1) << "XlaDevice::Sync (asynchronous)"; + std::shared_ptr stream; + { + mutex_lock lock(mu_); + stream = stream_; + } + if (!stream) { + done(Status::OK()); + return; + } + + stream->ThenEnqueueOnBackgroundThread( + [this, stream, done](se::StreamExecutor*) { + tracing::ScopedActivity activity("XlaDevice::Sync::Callback", + /*is_expensive=*/true); + mutex_lock lock(mu_); + while (outstanding_asynchronous_operations_ > 0) { + outstanding_asynchronous_operations_cv_.wait(lock); + } + done(stream->ok() ? Status::OK() + : errors::Internal("XlaDevice::Sync() failed.")); + }); +} + Status XlaDevice::MakeTensorFromProto(const TensorProto& tensor_proto, const AllocatorAttributes alloc_attrs, Tensor* tensor) { @@ -441,6 +478,49 @@ bool XlaDevice::RequiresSyncOnCompletion() const { return sync_on_completion_; } +XlaDevice::AsynchronousOperationHandle::AsynchronousOperationHandle( + XlaDevice* device) + : device_(device) { + mutex_lock lock(device_->mu_); + ++device_->outstanding_asynchronous_operations_; +} + +XlaDevice::AsynchronousOperationHandle::~AsynchronousOperationHandle() { + if (device_) { + mutex_lock lock(device_->mu_); + --device_->outstanding_asynchronous_operations_; + device_->outstanding_asynchronous_operations_cv_.notify_all(); + } +} + +XlaDevice::AsynchronousOperationHandle::AsynchronousOperationHandle( + const XlaDevice::AsynchronousOperationHandle& other) + : device_(other.device_) { + mutex_lock lock(device_->mu_); + ++device_->outstanding_asynchronous_operations_; +} + +XlaDevice::AsynchronousOperationHandle::AsynchronousOperationHandle( + XlaDevice::AsynchronousOperationHandle&& other) + : device_(other.device_) { + other.device_ = nullptr; +} + +XlaDevice::AsynchronousOperationHandle& XlaDevice::AsynchronousOperationHandle:: +operator=(const XlaDevice::AsynchronousOperationHandle& other) { + device_ = other.device_; + mutex_lock lock(device_->mu_); + ++device_->outstanding_asynchronous_operations_; + return *this; +} + +XlaDevice::AsynchronousOperationHandle& XlaDevice::AsynchronousOperationHandle:: +operator=(XlaDevice::AsynchronousOperationHandle&& other) { + device_ = other.device_; + other.device_ = nullptr; + return *this; +} + XlaDeviceOpRegistrations* RegisterXlaDeviceKernels(const char* device, const char* jit_device) { // Any op assigned to the device that isn't rewritten by the graph rewriter diff --git a/tensorflow/compiler/jit/xla_device.h b/tensorflow/compiler/jit/xla_device.h index 49f53b477e..c8bb276cdb 100644 --- a/tensorflow/compiler/jit/xla_device.h +++ b/tensorflow/compiler/jit/xla_device.h @@ -135,6 +135,7 @@ class XlaDevice : public LocalDevice { void ComputeAsync(AsyncOpKernel* op_kernel, OpKernelContext* context, AsyncOpKernel::DoneCallback done) override; Status Sync() override; + void Sync(const DoneCallback& done) override; Status FillContextMap(const Graph* graph, DeviceContextMap* device_context_map) override @@ -164,7 +165,30 @@ class XlaDevice : public LocalDevice { bool RequiresSyncOnCompletion() const override LOCKS_EXCLUDED(mu_); + // A simple RAII handle. On construction the device's + // outstanding_asynchronous_operations_ field is incremented; on destruction + // it is decremented. + class AsynchronousOperationHandle { + public: + AsynchronousOperationHandle(XlaDevice* device); + ~AsynchronousOperationHandle(); + AsynchronousOperationHandle(const AsynchronousOperationHandle& other); + AsynchronousOperationHandle(AsynchronousOperationHandle&& other); + AsynchronousOperationHandle& operator=( + const AsynchronousOperationHandle& other); + AsynchronousOperationHandle& operator=(AsynchronousOperationHandle&& other); + + private: + XlaDevice* device_ = nullptr; + }; + + AsynchronousOperationHandle CreateAsynchronousOperationHandle() { + return AsynchronousOperationHandle(this); + } + private: + friend class AsynchronousOperationHandle; + xla::LocalClient* client() const; Allocator* GetAllocatorLocked(AllocatorAttributes attr) EXCLUSIVE_LOCKS_REQUIRED(mu_); @@ -227,6 +251,11 @@ class XlaDevice : public LocalDevice { // True if the device requires XlaDevice::Sync to be called on completion // regardless of status. bool sync_on_completion_ GUARDED_BY(mu_) = false; + + // Count of outstanding asynchronous operations which must be zero on Sync() + // completion. + int64 outstanding_asynchronous_operations_ GUARDED_BY(mu_) = 0; + condition_variable outstanding_asynchronous_operations_cv_; }; // Builds OpKernel registrations on 'device' for the JIT operators diff --git a/tensorflow/compiler/jit/xla_gpu_device.cc b/tensorflow/compiler/jit/xla_gpu_device.cc index 4419701695..944f732b99 100644 --- a/tensorflow/compiler/jit/xla_gpu_device.cc +++ b/tensorflow/compiler/jit/xla_gpu_device.cc @@ -29,12 +29,12 @@ namespace tensorflow { class XlaGpuDeviceFactory : public DeviceFactory { public: Status CreateDevices(const SessionOptions& options, const string& name_prefix, - std::vector* devices) override; + std::vector>* devices) override; }; -Status XlaGpuDeviceFactory::CreateDevices(const SessionOptions& session_options, - const string& name_prefix, - std::vector* devices) { +Status XlaGpuDeviceFactory::CreateDevices( + const SessionOptions& session_options, const string& name_prefix, + std::vector>* devices) { XlaOpRegistry::DeviceRegistration registration; registration.compilation_device_name = DEVICE_GPU_XLA_JIT; registration.autoclustering_policy = @@ -70,7 +70,7 @@ Status XlaGpuDeviceFactory::CreateDevices(const SessionOptions& session_options, return status; } - devices->push_back(device.release()); + devices->push_back(std::move(device)); } return Status::OK(); } diff --git a/tensorflow/compiler/jit/xla_interpreter_device.cc b/tensorflow/compiler/jit/xla_interpreter_device.cc index e828bae865..4007309ed1 100644 --- a/tensorflow/compiler/jit/xla_interpreter_device.cc +++ b/tensorflow/compiler/jit/xla_interpreter_device.cc @@ -33,12 +33,12 @@ constexpr std::array kExecAllTypes = { class XlaInterpreterDeviceFactory : public DeviceFactory { public: Status CreateDevices(const SessionOptions& options, const string& name_prefix, - std::vector* devices) override; + std::vector>* devices) override; }; Status XlaInterpreterDeviceFactory::CreateDevices( const SessionOptions& session_options, const string& name_prefix, - std::vector* devices) { + std::vector>* devices) { static XlaDeviceOpRegistrations* registrations = RegisterXlaDeviceKernels( DEVICE_XLA_INTERPRETER, DEVICE_INTERPRETER_XLA_JIT); (void)registrations; @@ -61,8 +61,7 @@ Status XlaInterpreterDeviceFactory::CreateDevices( options.device_ordinal = 0; options.compilation_device_name = DEVICE_INTERPRETER_XLA_JIT; options.use_multiple_streams = false; - auto device = absl::make_unique(session_options, options); - devices->push_back(device.release()); + devices->push_back(absl::make_unique(session_options, options)); return Status::OK(); } diff --git a/tensorflow/compiler/tests/BUILD b/tensorflow/compiler/tests/BUILD index 6b8e6bba1e..bc3d60b90e 100644 --- a/tensorflow/compiler/tests/BUILD +++ b/tensorflow/compiler/tests/BUILD @@ -375,27 +375,6 @@ tf_xla_py_test( ], ) -tf_xla_py_test( - name = "resampler_ops_test", - size = "small", - srcs = ["resampler_ops_test.py"], - disabled_backends = [ - # TODO(b/74459949) Support BatchDot in CPU backend. - "cpu", - "cpu_ondemand", - ], - # TODO(b/112295522): figure out how to make OSS build pass. - tags = ["no_oss"], - deps = [ - ":xla_test", - "//tensorflow/contrib/resampler:resampler_ops", - "//tensorflow/contrib/resampler:resampler_py", - "//tensorflow/python:array_ops", - "//tensorflow/python:client_testlib", - "//tensorflow/python:platform_test", - ], -) - tf_xla_py_test( name = "dynamic_stitch_test", size = "small", @@ -474,7 +453,6 @@ tf_xla_py_test( "//tensorflow/python:extra_py_tests_deps", "//tensorflow/python:framework", "//tensorflow/python:platform_test", - "//tensorflow/python:spectral_ops", "//tensorflow/python/ops/signal", ], ) diff --git a/tensorflow/compiler/tests/adagrad_da_test.py b/tensorflow/compiler/tests/adagrad_da_test.py index 69fb3ec296..e9c2d363ac 100644 --- a/tensorflow/compiler/tests/adagrad_da_test.py +++ b/tensorflow/compiler/tests/adagrad_da_test.py @@ -50,8 +50,8 @@ class AdagradDAOptimizerTest(xla_test.XLATestCase): zip([grads0, grads1], [var0, var1]), global_step=global_step) variables.global_variables_initializer().run() - self.assertAllClose([0.0, 0.0], var0.eval()) - self.assertAllClose([0.0, 0.0], var1.eval()) + self.assertAllClose([0.0, 0.0], self.evaluate(var0)) + self.assertAllClose([0.0, 0.0], self.evaluate(var1)) # Run a step of AdagradDA update.run() @@ -63,9 +63,9 @@ class AdagradDAOptimizerTest(xla_test.XLATestCase): # For -0.1*3.0*(0.1 - 0)/(0 + sqrt(0.1 + 0.1*0.1)) = -0.904534 # similarly for others. self.assertAllCloseAccordingToType( - np.array([-0.904534, -1.603567]), var0.eval()) + np.array([-0.904534, -1.603567]), self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([-0.094821, -0.189358]), var1.eval()) + np.array([-0.094821, -0.189358]), self.evaluate(var1)) def testAdagradDAwithoutRegularizationBasic2(self): for dtype in self.float_types: @@ -87,16 +87,16 @@ class AdagradDAOptimizerTest(xla_test.XLATestCase): zip([grads0, grads1], [var0, var1]), global_step=global_step) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([4.0, 3.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([4.0, 3.0], self.evaluate(var1)) # Run a step of AdagradDA update.run() self.assertAllCloseAccordingToType( - np.array([-0.904534, -1.603567]), var0.eval()) + np.array([-0.904534, -1.603567]), self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([-0.094821, -0.189358]), var1.eval()) + np.array([-0.094821, -0.189358]), self.evaluate(var1)) def testAdagradDAWithL1(self): for dtype in self.float_types: @@ -118,16 +118,16 @@ class AdagradDAOptimizerTest(xla_test.XLATestCase): zip([grads0, grads1], [var0, var1]), global_step=global_step) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([4.0, 3.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([4.0, 3.0], self.evaluate(var1)) # Run a step of AdagradDA update.run() self.assertAllCloseAccordingToType( - np.array([-0.895489, -1.59555]), var0.eval()) + np.array([-0.895489, -1.59555]), self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([-0.085339, -0.17989]), var1.eval()) + np.array([-0.085339, -0.17989]), self.evaluate(var1)) def testAdagradDAWithL1_L2(self): for dtype in self.float_types: @@ -149,16 +149,16 @@ class AdagradDAOptimizerTest(xla_test.XLATestCase): zip([grads0, grads1], [var0, var1]), global_step=global_step) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([4.0, 3.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([4.0, 3.0], self.evaluate(var1)) # Run a step of AdagradDA update.run() self.assertAllCloseAccordingToType( - np.array([-0.046907, -0.093659]), var0.eval()) + np.array([-0.046907, -0.093659]), self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([-0.004275, -0.009023]), var1.eval()) + np.array([-0.004275, -0.009023]), self.evaluate(var1)) if __name__ == "__main__": diff --git a/tensorflow/compiler/tests/adagrad_test.py b/tensorflow/compiler/tests/adagrad_test.py index ab69319c59..e26483303c 100644 --- a/tensorflow/compiler/tests/adagrad_test.py +++ b/tensorflow/compiler/tests/adagrad_test.py @@ -42,17 +42,19 @@ class AdagradOptimizerTest(xla_test.XLATestCase): zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 3 steps of adagrad for _ in range(3): ada_update.run() # Validate updated params self.assertAllCloseAccordingToType( - np.array([-1.6026098728179932, -0.6026098728179932]), var0.eval(), + np.array([-1.6026098728179932, -0.6026098728179932]), + self.evaluate(var0), float_rtol=1e-5) self.assertAllCloseAccordingToType( - np.array([2.715679168701172, 3.715679168701172]), var1.eval(), + np.array([2.715679168701172, 3.715679168701172]), + self.evaluate(var1), float_rtol=1e-5) def testTensorLearningRate(self): @@ -68,17 +70,19 @@ class AdagradOptimizerTest(xla_test.XLATestCase): zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 3 steps of adagrad for _ in range(3): ada_update.run() # Validate updated params self.assertAllCloseAccordingToType( - np.array([-1.6026098728179932, -0.6026098728179932]), var0.eval(), + np.array([-1.6026098728179932, -0.6026098728179932]), + self.evaluate(var0), float_rtol=1e-5) self.assertAllCloseAccordingToType( - np.array([2.715679168701172, 3.715679168701172]), var1.eval(), + np.array([2.715679168701172, 3.715679168701172]), + self.evaluate(var1), float_rtol=1e-5) def testSharing(self): @@ -103,18 +107,20 @@ class AdagradOptimizerTest(xla_test.XLATestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values. - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Mix the first and the second adagrad for 3 steps. ada_update1.run() ada_update2.run() ada_update1.run() # Validate updated params (the same as with only 1 Adagrad). self.assertAllCloseAccordingToType( - np.array([-1.6026098728179932, -0.6026098728179932]), var0.eval(), + np.array([-1.6026098728179932, -0.6026098728179932]), + self.evaluate(var0), float_rtol=1e-5) self.assertAllCloseAccordingToType( - np.array([2.715679168701172, 3.715679168701172]), var1.eval(), + np.array([2.715679168701172, 3.715679168701172]), + self.evaluate(var1), float_rtol=1e-5) diff --git a/tensorflow/compiler/tests/adam_test.py b/tensorflow/compiler/tests/adam_test.py index 058576b3d4..8bcff9d379 100644 --- a/tensorflow/compiler/tests/adam_test.py +++ b/tensorflow/compiler/tests/adam_test.py @@ -75,23 +75,24 @@ class AdamOptimizerTest(xla_test.XLATestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) beta1_power, beta2_power = opt._get_beta_accumulators() # Run 3 steps of Adam for t in range(1, 4): - self.assertAllCloseAccordingToType(0.9**t, beta1_power.eval()) - self.assertAllCloseAccordingToType(0.999**t, beta2_power.eval()) + self.assertAllCloseAccordingToType(0.9**t, self.evaluate(beta1_power)) + self.assertAllCloseAccordingToType(0.999**t, + self.evaluate(beta2_power)) update.run(feed_dict={grads0: grads0_np, grads1: grads1_np}) var0_np, m0, v0 = adam_update_numpy(var0_np, grads0_np, t, m0, v0) var1_np, m1, v1 = adam_update_numpy(var1_np, grads1_np, t, m1, v1) # Validate updated params - self.assertAllCloseAccordingToType(var0_np, var0.eval()) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) def testTensorLearningRate(self): for dtype in self.float_types: @@ -117,23 +118,24 @@ class AdamOptimizerTest(xla_test.XLATestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) beta1_power, beta2_power = opt._get_beta_accumulators() # Run 3 steps of Adam for t in range(1, 4): - self.assertAllCloseAccordingToType(0.9**t, beta1_power.eval()) - self.assertAllCloseAccordingToType(0.999**t, beta2_power.eval()) + self.assertAllCloseAccordingToType(0.9**t, self.evaluate(beta1_power)) + self.assertAllCloseAccordingToType(0.999**t, + self.evaluate(beta2_power)) update.run(feed_dict={grads0: grads0_np, grads1: grads1_np}) var0_np, m0, v0 = adam_update_numpy(var0_np, grads0_np, t, m0, v0) var1_np, m1, v1 = adam_update_numpy(var1_np, grads1_np, t, m1, v1) # Validate updated params - self.assertAllCloseAccordingToType(var0_np, var0.eval()) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) def testSharing(self): for dtype in self.float_types: @@ -162,13 +164,14 @@ class AdamOptimizerTest(xla_test.XLATestCase): beta1_power, beta2_power = opt._get_beta_accumulators() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 3 steps of intertwined Adam1 and Adam2. for t in range(1, 4): - self.assertAllCloseAccordingToType(0.9**t, beta1_power.eval()) - self.assertAllCloseAccordingToType(0.999**t, beta2_power.eval()) + self.assertAllCloseAccordingToType(0.9**t, self.evaluate(beta1_power)) + self.assertAllCloseAccordingToType(0.999**t, + self.evaluate(beta2_power)) if t % 2 == 0: update1.run(feed_dict={grads0: grads0_np, grads1: grads1_np}) else: @@ -178,8 +181,8 @@ class AdamOptimizerTest(xla_test.XLATestCase): var1_np, m1, v1 = adam_update_numpy(var1_np, grads1_np, t, m1, v1) # Validate updated params - self.assertAllCloseAccordingToType(var0_np, var0.eval()) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) if __name__ == "__main__": diff --git a/tensorflow/compiler/tests/adamax_test.py b/tensorflow/compiler/tests/adamax_test.py index 3ed1d41b71..961b46375c 100644 --- a/tensorflow/compiler/tests/adamax_test.py +++ b/tensorflow/compiler/tests/adamax_test.py @@ -78,8 +78,8 @@ class AdaMaxOptimizerTest(xla_test.XLATestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) beta1_power = opt._get_beta_accumulators() @@ -87,14 +87,17 @@ class AdaMaxOptimizerTest(xla_test.XLATestCase): for t in range(1, 4): update.run() - self.assertAllCloseAccordingToType(0.9**(t + 1), beta1_power.eval()) + self.assertAllCloseAccordingToType(0.9**(t + 1), + self.evaluate(beta1_power)) var0_np, m0, v0 = adamax_update_numpy(var0_np, grads0_np, t, m0, v0) var1_np, m1, v1 = adamax_update_numpy(var1_np, grads1_np, t, m1, v1) # Validate updated params - self.assertAllCloseAccordingToType(var0_np, var0.eval(), rtol=1e-2) - self.assertAllCloseAccordingToType(var1_np, var1.eval(), rtol=1e-2) + self.assertAllCloseAccordingToType( + var0_np, self.evaluate(var0), rtol=1e-2) + self.assertAllCloseAccordingToType( + var1_np, self.evaluate(var1), rtol=1e-2) self.assertEqual("var0_%d/AdaMax:0" % (i,), opt.get_slot(var=var0, name="m").name) @@ -118,22 +121,23 @@ class AdaMaxOptimizerTest(xla_test.XLATestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) beta1_power = opt._get_beta_accumulators() # Run 3 steps of AdaMax for t in range(1, 4): - self.assertAllCloseAccordingToType(0.9**t, beta1_power.eval()) + self.assertAllCloseAccordingToType(0.9**t, self.evaluate(beta1_power)) update.run() var0_np, m0, v0 = adamax_update_numpy(var0_np, grads0_np, t, m0, v0) var1_np, m1, v1 = adamax_update_numpy(var1_np, grads1_np, t, m1, v1) # Validate updated params - self.assertAllCloseAccordingToType(var0_np, var0.eval()) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + if __name__ == "__main__": test.main() diff --git a/tensorflow/compiler/tests/addsign_test.py b/tensorflow/compiler/tests/addsign_test.py index 1bc07ace23..a37c97e6d3 100644 --- a/tensorflow/compiler/tests/addsign_test.py +++ b/tensorflow/compiler/tests/addsign_test.py @@ -90,8 +90,8 @@ class AddSignTest(xla_test.XLATestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 7 steps of AddSign # first 4 steps with positive gradient @@ -125,8 +125,8 @@ class AddSignTest(xla_test.XLATestCase): # Validate updated params self.assertAllCloseAccordingToType( - var0_np, var0.eval(), half_rtol=1e-2) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) + var0_np, self.evaluate(var0), half_rtol=1e-2) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) def testDense(self): decay_steps = 10 diff --git a/tensorflow/compiler/tests/binary_ops_test.py b/tensorflow/compiler/tests/binary_ops_test.py index 332381c59e..9a5423c1b2 100644 --- a/tensorflow/compiler/tests/binary_ops_test.py +++ b/tensorflow/compiler/tests/binary_ops_test.py @@ -218,6 +218,21 @@ class BinaryOpsTest(xla_test.XLATestCase): ], equality_test=self.ListsAreClose) + # TF doesn't define these for bf16. + if dtype != dtypes.bfloat16.as_numpy_dtype: + self._testBinary( + gen_math_ops.xdivy, + np.array([0, 4, 3, 2, 1, 0], dtype=dtype), + np.array([0, 5, 6, 7, 8, float("NaN")], dtype=dtype), + expected=np.array([0, 0.8, 0.5, 0.285714, 0.125, 0], dtype=dtype)) + + self._testBinary( + gen_math_ops.xlogy, + np.array([0, 4, 3, 2, 1, 0], dtype=dtype), + np.array([0, 5, 6, 7, 8, float("NaN")], dtype=dtype), + expected=np.array([0, 6.437752, 5.375278, 3.89182, 2.079442, 0], + dtype=dtype)) + def testIntOps(self): for dtype in self.signed_int_types: self._testBinary( diff --git a/tensorflow/compiler/tests/categorical_op_test.py b/tensorflow/compiler/tests/categorical_op_test.py index a57d1dc81e..5d5e486f61 100644 --- a/tensorflow/compiler/tests/categorical_op_test.py +++ b/tensorflow/compiler/tests/categorical_op_test.py @@ -27,6 +27,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import random_seed from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops +from tensorflow.python.ops import stateless_random_ops from tensorflow.python.platform import googletest @@ -56,11 +57,11 @@ class CategoricalTest(xla_test.XLATestCase): Returns: Frequencies from sampled classes; shape [batch_size, num_classes]. """ - with self.cached_session() as sess, self.test_scope(): + with self.cached_session(), self.test_scope(): random_seed.set_random_seed(1618) op = random_ops.multinomial(logits, num_samples, output_dtype=dtypes.int32) - d = sess.run(op) + d = self.evaluate(op) batch_size, num_classes = logits.shape freqs_mat = [] @@ -79,15 +80,15 @@ class CategoricalTest(xla_test.XLATestCase): def _testRngIsNotConstant(self, rng, dtype, output_dtype): # Tests that 'rng' does not always return the same value. - with self.cached_session() as sess: + with self.cached_session(): with self.test_scope(): x = rng(dtype, output_dtype) # The random-number generator, if working correctly, should produce the # same output multiple times with low probability. - y = sess.run(x) - z = sess.run(x) - w = sess.run(x) + y = self.evaluate(x) + z = self.evaluate(x) + w = self.evaluate(x) # We use exact equality here. If the random-number generator is producing # deterministic output, all three outputs will be bitwise identical. @@ -107,12 +108,12 @@ class CategoricalTest(xla_test.XLATestCase): def testCategoricalIsInRange(self): for dtype in self.float_types: for output_dtype in self.output_dtypes(): - with self.cached_session() as sess: + with self.cached_session(): with self.test_scope(): x = random_ops.multinomial( array_ops.ones(shape=[1, 20], dtype=dtype), 1000, output_dtype=output_dtype) - y = sess.run(x) + y = self.evaluate(x) self.assertTrue((y >= 0).sum() == 1000) self.assertTrue((y < 20).sum() == 1000) @@ -138,6 +139,57 @@ class CategoricalTest(xla_test.XLATestCase): chi2 = self._chi2(probs, freqs) self.assertLess(chi2, 1e-3) + def testStatelessMultinomialIsInRange(self): + for dtype in self.float_types: + for output_dtype in self.output_dtypes(): + with self.cached_session() as sess: + with self.test_scope(): + seed_t = array_ops.placeholder(dtypes.int32, shape=[2]) + x = stateless_random_ops.stateless_multinomial( + array_ops.ones(shape=[1, 20], dtype=dtype), + 1000, + seed_t, + output_dtype=output_dtype) + y = sess.run(x, {seed_t: [0x12345678, 0xabcdef12]}) + self.assertTrue((y >= 0).sum() == 1000) + self.assertTrue((y < 20).sum() == 1000) + + def testDeterminismMultinomial(self): + # Stateless values should be equal iff the seeds are equal (roughly) + num_samples = 10 + with self.cached_session(), self.test_scope(): + seed_t = array_ops.placeholder(dtypes.int32, shape=[2]) + seeds = [(x, y) for x in range(5) for y in range(5)] * 3 + for logits in ([[0.1, 0.25, 0.5, 0.15]], [[0.5, 0.5], [0.8, 0.2], + [0.25, 0.75]]): + pure = stateless_random_ops.stateless_multinomial( + logits, num_samples, seed=seed_t) + values = [(seed, pure.eval(feed_dict={seed_t: seed})) for seed in seeds] + for s0, v0 in values: + for s1, v1 in values: + self.assertEqual(s0 == s1, np.all(v0 == v1)) + + def testEmpty(self): + with self.cached_session(): + with self.test_scope(): + x = random_ops.multinomial( + array_ops.zeros([42, 40]), 0, output_dtype=dtypes.int32) + y = self.evaluate(x) + self.assertEqual(y.shape, (42, 0)) + + def testEmptyStateless(self): + with self.cached_session() as sess: + with self.test_scope(): + seed_t = array_ops.placeholder(dtypes.int32, shape=[2]) + x = stateless_random_ops.stateless_multinomial( + array_ops.zeros([42, 40]), + 0, + seed=seed_t, + output_dtype=dtypes.int32) + y = sess.run(x, {seed_t: [0x12345678, 0xabcdef12]}) + self.assertEqual(y.shape, (42, 0)) + + if __name__ == '__main__': googletest.main() diff --git a/tensorflow/compiler/tests/clustering_test.py b/tensorflow/compiler/tests/clustering_test.py index 88bd58b2da..ef2d7af69d 100644 --- a/tensorflow/compiler/tests/clustering_test.py +++ b/tensorflow/compiler/tests/clustering_test.py @@ -43,7 +43,7 @@ class ClusteringTest(xla_test.XLATestCase): input1 = constant_op.constant(val1, name="const1") input2 = constant_op.constant(val2, name="const2") output = math_ops.add(input1, input2) - result = output.eval() + result = self.evaluate(output) self.assertAllClose(result, expected, rtol=1e-3) def testAddFromCpuMultiple(self): @@ -57,7 +57,7 @@ class ClusteringTest(xla_test.XLATestCase): with self.test_scope(): output = math_ops.add(input1, input2) for _ in xrange(10): - result = output.eval() + result = self.evaluate(output) self.assertAllClose(result, expected, rtol=1e-3) def testDeadlock(self): diff --git a/tensorflow/compiler/tests/concat_ops_test.py b/tensorflow/compiler/tests/concat_ops_test.py index 2d225ad226..2187f57960 100644 --- a/tensorflow/compiler/tests/concat_ops_test.py +++ b/tensorflow/compiler/tests/concat_ops_test.py @@ -72,7 +72,7 @@ class ConcatTest(xla_test.XLATestCase): x2 = constant_op.constant(p2) with self.test_scope(): c = array_ops.concat([x1, x2], 0) - result = c.eval() + result = self.evaluate(c) self.assertAllEqual(result[:2, :], p1) self.assertAllEqual(result[2:, :], p2) @@ -150,7 +150,7 @@ class ConcatTest(xla_test.XLATestCase): [float(x) for x in grad_inp.flatten()], shape=output_shape) grad = gradients_impl.gradients([c], inp_tensors, [grad_tensor]) concated_grad = array_ops.concat(grad, 1) - result = concated_grad.eval() + result = self.evaluate(concated_grad) self.assertAllEqual(result, grad_inp) def testGradientsSimpleAll(self): @@ -177,7 +177,7 @@ class ConcatTest(xla_test.XLATestCase): [float(x) for x in grad_inp.flatten()], shape=output_shape) grad = gradients_impl.gradients([c], inp_tensors, [grad_tensor]) concated_grad = array_ops.concat(grad, 0) - result = concated_grad.eval() + result = self.evaluate(concated_grad) self.assertAllEqual(result, grad_inp) @@ -205,7 +205,7 @@ class ConcatTest(xla_test.XLATestCase): [float(x) for x in grad_inp.flatten()], shape=output_shape) grad = gradients_impl.gradients([c], inp_tensors, [grad_tensor]) concated_grad = array_ops.concat(grad, 2) - result = concated_grad.eval() + result = self.evaluate(concated_grad) self.assertAllEqual(result, grad_inp) @@ -242,7 +242,7 @@ class ConcatTest(xla_test.XLATestCase): [float(x) for x in grad_inp.flatten()], shape=output_shape) grad = gradients_impl.gradients([c], inp_tensors, [grad_tensor]) concated_grad = array_ops.concat(grad, concat_dim) - result = concated_grad.eval() + result = self.evaluate(concated_grad) self.assertAllEqual(result, grad_inp) @@ -254,7 +254,7 @@ class ConcatTest(xla_test.XLATestCase): def DISABLED_testZeroSize(self): # Verify that concat doesn't crash and burn for zero size inputs np.random.seed(7) - with self.cached_session() as sess: + with self.cached_session(): with self.test_scope(): for shape0 in (), (2,): axis = len(shape0) @@ -270,7 +270,7 @@ class ConcatTest(xla_test.XLATestCase): self.assertAllEqual(c.eval(), correct) # Check gradients dc = np.random.randn(*c.get_shape().as_list()) - dxs = sess.run(gradients_impl.gradients(c, xs, dc)) + dxs = self.evaluate(gradients_impl.gradients(c, xs, dc)) self.assertAllEqual(dc, np.concatenate(dxs, axis=axis)) def testConcatTuple(self): @@ -280,7 +280,7 @@ class ConcatTest(xla_test.XLATestCase): with self.test_scope(): concat_list_t = array_ops.concat([c1, c2], 0) concat_tuple_t = array_ops.concat((c1, c2), 0) - self.assertAllEqual(concat_list_t.eval(), concat_tuple_t.eval()) + self.assertAllEqual(concat_list_t.eval(), self.evaluate(concat_tuple_t)) def testConcatNoScalars(self): with self.cached_session(): @@ -330,47 +330,47 @@ class ConcatTest(xla_test.XLATestCase): class ConcatOffsetTest(xla_test.XLATestCase): def testBasic(self): - with self.cached_session() as sess: + with self.cached_session(): with self.test_scope(): cdim = constant_op.constant(1, dtypes.int32) s0 = constant_op.constant([2, 3, 5], dtypes.int32) s1 = constant_op.constant([2, 7, 5], dtypes.int32) s2 = constant_op.constant([2, 20, 5], dtypes.int32) off = gen_array_ops.concat_offset(cdim, [s0, s1, s2]) - ans = sess.run(off) + ans = self.evaluate(off) self.assertAllEqual(ans, [[0, 0, 0], [0, 3, 0], [0, 10, 0]]) class PackTest(xla_test.XLATestCase): def testBasic(self): - with self.cached_session() as sess: + with self.cached_session(): with self.test_scope(): s0 = constant_op.constant([2, 3, 5], dtypes.int32) s1 = constant_op.constant([2, 7, 5], dtypes.int32) s2 = constant_op.constant([2, 20, 5], dtypes.int32) packed = array_ops.stack([s0, s1, s2]) - ans = sess.run(packed) + ans = self.evaluate(packed) self.assertAllEqual(ans, [[2, 3, 5], [2, 7, 5], [2, 20, 5]]) def testScalars(self): - with self.cached_session() as sess: + with self.cached_session(): with self.test_scope(): s0 = constant_op.constant(2, dtypes.int32) s1 = constant_op.constant(3, dtypes.int32) s2 = constant_op.constant(5, dtypes.int32) packed = array_ops.stack([s0, s1, s2]) - ans = sess.run(packed) + ans = self.evaluate(packed) self.assertAllEqual(ans, [2, 3, 5]) def testEmpty(self): - with self.cached_session() as sess: + with self.cached_session(): with self.test_scope(): s0 = constant_op.constant([[]], dtypes.int32) s1 = constant_op.constant([[]], dtypes.int32) s2 = constant_op.constant([[]], dtypes.int32) packed = array_ops.stack([s0, s1, s2]) - ans = sess.run(packed) + ans = self.evaluate(packed) self.assertAllEqual(ans, [[[]], [[]], [[]]]) diff --git a/tensorflow/compiler/tests/conv3d_test.py b/tensorflow/compiler/tests/conv3d_test.py index d59fd0236f..01cc1b6392 100644 --- a/tensorflow/compiler/tests/conv3d_test.py +++ b/tensorflow/compiler/tests/conv3d_test.py @@ -85,7 +85,7 @@ class Conv3DTransposeTest(xla_test.XLATestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv3d_transpose( x, f, y_shape, strides=strides, padding="SAME") - value = output.eval() + value = self.evaluate(output) # We count the number of cells being added at the locations in the output. # At the center, #cells = kernel_depth * kernel_height * kernel_width @@ -135,7 +135,7 @@ class Conv3DTransposeTest(xla_test.XLATestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv3d_transpose( x, f, y_shape, strides=strides, padding="SAME") - value = output.eval() + value = self.evaluate(output) for n in xrange(x_shape[0]): for k in xrange(f_shape[3]): @@ -173,7 +173,7 @@ class Conv3DTransposeTest(xla_test.XLATestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv3d_transpose( x, f, y_shape, strides=strides, padding="VALID") - value = output.eval() + value = self.evaluate(output) cache_values = np.zeros(y_shape, dtype=np.float32) diff --git a/tensorflow/compiler/tests/dense_layer_test.py b/tensorflow/compiler/tests/dense_layer_test.py index d1b90f098d..bf5ea7b1fb 100644 --- a/tensorflow/compiler/tests/dense_layer_test.py +++ b/tensorflow/compiler/tests/dense_layer_test.py @@ -42,7 +42,7 @@ def GetRunMetadataLabels(run_metadata): def InLabels(labels, substr): """Returns true iff one of the labels contains substr.""" - return any([substr in x for x in labels]) + return any(substr in x for x in labels) class DenseLayerTest(test.TestCase): @@ -72,7 +72,7 @@ class DenseLayerTest(test.TestCase): x = array_ops.placeholder(shape=[None, None, 3], dtype=np.float32) y = layers.dense(x, 3) - sess.run(variables.initialize_all_variables()) + self.evaluate(variables.initialize_all_variables()) run_metadata = config_pb2.RunMetadata() test_utils.RunWithWarmup( sess, @@ -97,7 +97,7 @@ class DenseLayerTest(test.TestCase): with jit_scope(): y = layers.dense(x, 3) - sess.run(variables.initialize_all_variables()) + self.evaluate(variables.initialize_all_variables()) run_metadata = config_pb2.RunMetadata() test_utils.RunWithWarmup( sess, @@ -126,7 +126,7 @@ class DenseLayerTest(test.TestCase): with jit_scope(): y = layers.dense(x, 3) - sess.run(variables.initialize_all_variables()) + self.evaluate(variables.initialize_all_variables()) run_metadata = config_pb2.RunMetadata() test_utils.RunWithWarmup( sess, diff --git a/tensorflow/compiler/tests/dynamic_stitch_test.py b/tensorflow/compiler/tests/dynamic_stitch_test.py index 50b04daa6b..e89cf975f5 100644 --- a/tensorflow/compiler/tests/dynamic_stitch_test.py +++ b/tensorflow/compiler/tests/dynamic_stitch_test.py @@ -58,6 +58,15 @@ class DynamicStitchTest(xla_test.XLATestCase): [idx1, idx2], [val1, val2], expected=np.array([[], [], [], []], np.int32)) + def testEmptyIndex(self): + idx1 = np.array([], dtype=np.int32) + idx2 = np.array([[], []], dtype=np.int32) + val1 = np.ndarray(shape=(0, 9), dtype=np.int32) + val2 = np.ndarray(shape=(2, 0, 9), dtype=np.int32) + self._AssertDynamicStitchResultIs([idx1, idx2], [val1, val2], + expected=np.ndarray( + shape=(0, 9), dtype=np.int32)) + def testSimple1D(self): val1 = np.array([0, 4, 7], dtype=np.int32) val2 = np.array([1, 6, 2, 3, 5], dtype=np.int32) diff --git a/tensorflow/compiler/tests/eager_test.py b/tensorflow/compiler/tests/eager_test.py index 63cee550fd..2af32b537b 100644 --- a/tensorflow/compiler/tests/eager_test.py +++ b/tensorflow/compiler/tests/eager_test.py @@ -101,12 +101,12 @@ class EagerTest(xla_test.XLATestCase): self.assertAllEqual(15, product) # Run some ops graphly - with context.graph_mode(), self.cached_session() as sess: + with context.graph_mode(), self.cached_session(): with self.test_scope(): three = constant_op.constant(3) five = constant_op.constant(5) product = three * five - self.assertAllEqual(15, sess.run(product)) + self.assertAllEqual(15, self.evaluate(product)) def testDegenerateSlices(self): with self.test_scope(): diff --git a/tensorflow/compiler/tests/fft_test.py b/tensorflow/compiler/tests/fft_test.py index e92afd5d6f..0edd0c35aa 100644 --- a/tensorflow/compiler/tests/fft_test.py +++ b/tensorflow/compiler/tests/fft_test.py @@ -27,8 +27,7 @@ from tensorflow.compiler.tests import xla_test from tensorflow.python.framework import dtypes from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl -from tensorflow.python.ops import signal -from tensorflow.python.ops import spectral_ops +from tensorflow.python.ops.signal import signal from tensorflow.python.platform import googletest BATCH_DIMS = (3, 5) @@ -107,39 +106,39 @@ class FFTTest(xla_test.XLATestCase): def testFFT(self): self._VerifyFftMethod(INNER_DIMS_1D, lambda x: x, np.fft.fft, - spectral_ops.fft) + signal.fft) def testFFT2D(self): self._VerifyFftMethod(INNER_DIMS_2D, lambda x: x, np.fft.fft2, - spectral_ops.fft2d) + signal.fft2d) def testFFT3D(self): self._VerifyFftMethod(INNER_DIMS_3D, lambda x: x, lambda x: np.fft.fftn(x, axes=(-3, -2, -1)), - spectral_ops.fft3d) + signal.fft3d) def testIFFT(self): self._VerifyFftMethod(INNER_DIMS_1D, lambda x: x, np.fft.ifft, - spectral_ops.ifft) + signal.ifft) def testIFFT2D(self): self._VerifyFftMethod(INNER_DIMS_2D, lambda x: x, np.fft.ifft2, - spectral_ops.ifft2d) + signal.ifft2d) def testIFFT3D(self): self._VerifyFftMethod(INNER_DIMS_3D, lambda x: x, lambda x: np.fft.ifftn(x, axes=(-3, -2, -1)), - spectral_ops.ifft3d) + signal.ifft3d) def testRFFT(self): self._VerifyFftMethod( INNER_DIMS_1D, np.real, lambda x: np.fft.rfft(x, n=x.shape[-1]), - lambda x: spectral_ops.rfft(x, fft_length=[x.shape[-1].value])) + lambda x: signal.rfft(x, fft_length=[x.shape[-1].value])) def testRFFT2D(self): def _tf_fn(x): - return spectral_ops.rfft2d( + return signal.rfft2d( x, fft_length=[x.shape[-2].value, x.shape[-1].value]) self._VerifyFftMethod( @@ -153,16 +152,33 @@ class FFTTest(xla_test.XLATestCase): x, axes=(-3, -2, -1), s=[x.shape[-3], x.shape[-2], x.shape[-1]]) def _tf_fn(x): - return spectral_ops.rfft3d( + return signal.rfft3d( x, fft_length=[x.shape[-3].value, x.shape[-2].value, x.shape[-1].value]) self._VerifyFftMethod(INNER_DIMS_3D, np.real, _to_expected, _tf_fn) + def testRFFT3DMismatchedSize(self): + + def _to_expected(x): + return np.fft.rfftn( + x, + axes=(-3, -2, -1), + s=[x.shape[-3] // 2, x.shape[-2], x.shape[-1] * 2]) + + def _tf_fn(x): + return signal.rfft3d( + x, + fft_length=[ + x.shape[-3].value // 2, x.shape[-2].value, x.shape[-1].value * 2 + ]) + + self._VerifyFftMethod(INNER_DIMS_3D, np.real, _to_expected, _tf_fn) + def testIRFFT(self): def _tf_fn(x): - return spectral_ops.irfft(x, fft_length=[2 * (x.shape[-1].value - 1)]) + return signal.irfft(x, fft_length=[2 * (x.shape[-1].value - 1)]) self._VerifyFftMethod( INNER_DIMS_1D, lambda x: np.fft.rfft(np.real(x), n=x.shape[-1]), @@ -171,7 +187,7 @@ class FFTTest(xla_test.XLATestCase): def testIRFFT2D(self): def _tf_fn(x): - return spectral_ops.irfft2d( + return signal.irfft2d( x, fft_length=[x.shape[-2].value, 2 * (x.shape[-1].value - 1)]) self._VerifyFftMethod( @@ -195,7 +211,7 @@ class FFTTest(xla_test.XLATestCase): s=[x.shape[-3], x.shape[-2], 2 * (x.shape[-1] - 1)]) def _tf_fn(x): - return spectral_ops.irfft3d( + return signal.irfft3d( x, fft_length=[ x.shape[-3].value, x.shape[-2].value, 2 * (x.shape[-1].value - 1) @@ -203,6 +219,30 @@ class FFTTest(xla_test.XLATestCase): self._VerifyFftMethod(INNER_DIMS_3D, _to_input, _to_expected, _tf_fn) + def testIRFFT3DMismatchedSize(self): + + def _to_input(x): + return np.fft.rfftn( + np.real(x), + axes=(-3, -2, -1), + s=[x.shape[-3] // 2, x.shape[-2], x.shape[-1] * 2]) + + def _to_expected(x): + return np.fft.irfftn( + x, + axes=(-3, -2, -1), + s=[x.shape[-3] // 2, x.shape[-2], x.shape[-1] * 2]) + + def _tf_fn(x): + return signal.irfft3d( + x, + fft_length=[ + x.shape[-3].value // 2, x.shape[-2].value, x.shape[-1].value * 2 + ]) + + self._VerifyFftMethod(INNER_DIMS_3D, _to_input, _to_expected, _tf_fn) + + if __name__ == "__main__": googletest.main() diff --git a/tensorflow/compiler/tests/fifo_queue_test.py b/tensorflow/compiler/tests/fifo_queue_test.py index 8c7edfd277..91d77d2f79 100644 --- a/tensorflow/compiler/tests/fifo_queue_test.py +++ b/tensorflow/compiler/tests/fifo_queue_test.py @@ -129,7 +129,7 @@ class FIFOQueueTest(xla_test.XLATestCase): enqueue_op.run() for i in xrange(len(elems)): - vals = dequeued_t.eval() + vals = self.evaluate(dequeued_t) self.assertEqual([elems[i]], vals) def testEnqueueAndBlockingDequeue(self): @@ -192,9 +192,9 @@ class FIFOQueueTest(xla_test.XLATestCase): self.assertEqual([], size.get_shape()) enqueue_op.run() - self.assertEqual(1, size.eval()) + self.assertEqual(1, self.evaluate(size)) dequeued_t.op.run() - self.assertEqual(0, size.eval()) + self.assertEqual(0, self.evaluate(size)) if __name__ == "__main__": diff --git a/tensorflow/compiler/tests/ftrl_test.py b/tensorflow/compiler/tests/ftrl_test.py index 5b197afd65..b078053cdb 100644 --- a/tensorflow/compiler/tests/ftrl_test.py +++ b/tensorflow/compiler/tests/ftrl_test.py @@ -50,14 +50,14 @@ class FtrlOptimizerTest(xla_test.XLATestCase): ftrl_update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([0.0, 0.0], var0.eval()) - self.assertAllClose([0.0, 0.0], var1.eval()) + self.assertAllClose([0.0, 0.0], self.evaluate(var0)) + self.assertAllClose([0.0, 0.0], self.evaluate(var1)) # Run Ftrl for a few steps for _ in range(steps): ftrl_update.run() - return var0.eval(), var1.eval() + return self.evaluate(var0), self.evaluate(var1) def equivAdagradTest_AdagradPart(self, steps, dtype): var0, var1, grads0, grads1 = self.initVariableAndGradient(dtype) @@ -65,14 +65,14 @@ class FtrlOptimizerTest(xla_test.XLATestCase): adagrad_update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([0.0, 0.0], var0.eval()) - self.assertAllClose([0.0, 0.0], var1.eval()) + self.assertAllClose([0.0, 0.0], self.evaluate(var0)) + self.assertAllClose([0.0, 0.0], self.evaluate(var1)) # Run Adagrad for a few steps for _ in range(steps): adagrad_update.run() - return var0.eval(), var1.eval() + return self.evaluate(var0), self.evaluate(var1) def equivGradientDescentTest_FtrlPart(self, steps, dtype): var0, var1, grads0, grads1 = self.initVariableAndGradient(dtype) @@ -85,14 +85,14 @@ class FtrlOptimizerTest(xla_test.XLATestCase): ftrl_update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([0.0, 0.0], var0.eval()) - self.assertAllClose([0.0, 0.0], var1.eval()) + self.assertAllClose([0.0, 0.0], self.evaluate(var0)) + self.assertAllClose([0.0, 0.0], self.evaluate(var1)) # Run Ftrl for a few steps for _ in range(steps): ftrl_update.run() - return var0.eval(), var1.eval() + return self.evaluate(var0), self.evaluate(var1) def equivGradientDescentTest_GradientDescentPart(self, steps, dtype): var0, var1, grads0, grads1 = self.initVariableAndGradient(dtype) @@ -100,14 +100,14 @@ class FtrlOptimizerTest(xla_test.XLATestCase): sgd_update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([0.0, 0.0], var0.eval()) - self.assertAllClose([0.0, 0.0], var1.eval()) + self.assertAllClose([0.0, 0.0], self.evaluate(var0)) + self.assertAllClose([0.0, 0.0], self.evaluate(var1)) # Run GradientDescent for a few steps for _ in range(steps): sgd_update.run() - return var0.eval(), var1.eval() + return self.evaluate(var0), self.evaluate(var1) def testFtrlwithoutRegularization(self): for dtype in self.float_types: @@ -124,8 +124,8 @@ class FtrlOptimizerTest(xla_test.XLATestCase): ftrl_update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([0.0, 0.0], var0.eval()) - self.assertAllClose([0.0, 0.0], var1.eval()) + self.assertAllClose([0.0, 0.0], self.evaluate(var0)) + self.assertAllClose([0.0, 0.0], self.evaluate(var1)) # Run 3 steps FTRL for _ in range(3): @@ -134,12 +134,12 @@ class FtrlOptimizerTest(xla_test.XLATestCase): # Validate updated params self.assertAllCloseAccordingToType( np.array([-2.60260963, -4.29698515]), - var0.eval(), + self.evaluate(var0), float_rtol=1e-4, half_rtol=1e-2) self.assertAllCloseAccordingToType( np.array([-0.28432083, -0.56694895]), - var1.eval(), + self.evaluate(var1), float_rtol=1e-5, half_rtol=1e-2) @@ -158,8 +158,8 @@ class FtrlOptimizerTest(xla_test.XLATestCase): ftrl_update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([4.0, 3.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([4.0, 3.0], self.evaluate(var1)) # Run 3 steps FTRL for _ in range(3): @@ -167,10 +167,14 @@ class FtrlOptimizerTest(xla_test.XLATestCase): # Validate updated params self.assertAllCloseAccordingToType( - np.array([-2.55607247, -3.98729396]), var0.eval(), 1e-5, 1e-5, + np.array([-2.55607247, -3.98729396]), + self.evaluate(var0), + 1e-5, + 1e-5, float_rtol=1e-4) self.assertAllCloseAccordingToType( - np.array([-0.28232238, -0.56096673]), var1.eval(), 1e-5, 1e-5) + np.array([-0.28232238, -0.56096673]), self.evaluate(var1), 1e-5, + 1e-5) def testFtrlWithL1(self): for dtype in self.float_types: @@ -187,8 +191,8 @@ class FtrlOptimizerTest(xla_test.XLATestCase): ftrl_update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([4.0, 3.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([4.0, 3.0], self.evaluate(var1)) # Run 10 steps FTRL for _ in range(10): @@ -197,12 +201,14 @@ class FtrlOptimizerTest(xla_test.XLATestCase): # Validate updated params self.assertAllCloseAccordingToType( np.array([-7.66718769, -10.91273689]), - var0.eval(), + self.evaluate(var0), rtol=1e-4, bfloat16_rtol=1e-1, bfloat16_atol=1e-1) self.assertAllCloseAccordingToType( - np.array([-0.93460727, -1.86147261]), var1.eval(), rtol=1e-4) + np.array([-0.93460727, -1.86147261]), + self.evaluate(var1), + rtol=1e-4) def testFtrlWithL1_L2(self): for dtype in self.float_types: @@ -219,8 +225,8 @@ class FtrlOptimizerTest(xla_test.XLATestCase): ftrl_update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([4.0, 3.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([4.0, 3.0], self.evaluate(var1)) # Run 10 steps FTRL for _ in range(10): @@ -228,9 +234,13 @@ class FtrlOptimizerTest(xla_test.XLATestCase): # Validate updated params self.assertAllCloseAccordingToType( - np.array([-0.24059935, -0.46829352]), var0.eval(), rtol=1e-5) + np.array([-0.24059935, -0.46829352]), + self.evaluate(var0), + rtol=1e-5) self.assertAllCloseAccordingToType( - np.array([-0.02406147, -0.04830509]), var1.eval(), rtol=1e-5) + np.array([-0.02406147, -0.04830509]), + self.evaluate(var1), + rtol=1e-5) def testFtrlWithL1_L2_L2Shrinkage(self): """Test the new FTRL op with support for l2 shrinkage. @@ -254,8 +264,8 @@ class FtrlOptimizerTest(xla_test.XLATestCase): ftrl_update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([4.0, 3.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([4.0, 3.0], self.evaluate(var1)) # Run 10 steps FTRL for _ in range(10): @@ -263,9 +273,13 @@ class FtrlOptimizerTest(xla_test.XLATestCase): # Validate updated params self.assertAllCloseAccordingToType( - np.array([-0.22578996, -0.44345799]), var0.eval(), rtol=1e-4) + np.array([-0.22578996, -0.44345799]), + self.evaluate(var0), + rtol=1e-4) self.assertAllCloseAccordingToType( - np.array([-0.14378493, -0.13229476]), var1.eval(), rtol=1e-4) + np.array([-0.14378493, -0.13229476]), + self.evaluate(var1), + rtol=1e-4) def testFtrlWithL2ShrinkageDoesNotChangeLrSchedule(self): """Verifies that l2 shrinkage in FTRL does not change lr schedule.""" @@ -291,8 +305,8 @@ class FtrlOptimizerTest(xla_test.XLATestCase): update1 = opt1.apply_gradients([(grads1, var1)]) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([1.0, 2.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var1)) # Run 10 steps FTRL for _ in range(10): @@ -301,7 +315,7 @@ class FtrlOptimizerTest(xla_test.XLATestCase): # var0 is experiencing L2 shrinkage so it should be smaller than var1 # in magnitude. - self.assertTrue((var0.eval()**2 < var1.eval()**2).all()) + self.assertTrue((var0.eval()**2 < self.evaluate(var1)**2).all()) accum0 = list(opt0._slots["accum"].values())[0].eval() accum1 = list(opt1._slots["accum"].values())[0].eval() # L2 shrinkage should not change how we update grad accumulator. diff --git a/tensorflow/compiler/tests/function_test.py b/tensorflow/compiler/tests/function_test.py index b1891b918c..a61827c2ae 100644 --- a/tensorflow/compiler/tests/function_test.py +++ b/tensorflow/compiler/tests/function_test.py @@ -40,7 +40,7 @@ class FunctionTest(xla_test.XLATestCase): bval = np.array([5, 6, 7, 8]).reshape([2, 2]).astype(np.float32) expected = APlus2B(aval, bval) - with self.cached_session() as sess: + with self.cached_session(): @function.Defun(dtypes.float32, dtypes.float32) def Foo(a, b): @@ -50,7 +50,7 @@ class FunctionTest(xla_test.XLATestCase): b = constant_op.constant(bval, name="b") with self.test_scope(): call_f = Foo(a, b) - result = sess.run(call_f) + result = self.evaluate(call_f) self.assertAllClose(result, expected, rtol=1e-3) def testNestedFunctions(self): @@ -66,7 +66,7 @@ class FunctionTest(xla_test.XLATestCase): bval = np.array([4, 3, 2, 1]).reshape([2, 2]).astype(np.float32) expected = APlus2B(aval, bval) - with self.cached_session() as sess: + with self.cached_session(): @function.Defun(dtypes.float32, dtypes.float32) def Foo(a, b): @@ -76,7 +76,7 @@ class FunctionTest(xla_test.XLATestCase): b = constant_op.constant(bval, name="b") with self.test_scope(): call_g = Foo(a, b) - result = sess.run(call_g) + result = self.evaluate(call_g) self.assertAllClose(result, expected, rtol=1e-3) def testFunctionMultipleRetvals(self): @@ -90,7 +90,7 @@ class FunctionTest(xla_test.XLATestCase): bval = np.array([5, 6, 7, 8]).reshape([2, 2]).astype(np.float32) expected = Func(aval, bval) - with self.cached_session() as sess: + with self.cached_session(): @function.Defun(dtypes.float32, dtypes.float32) def Foo(a, b): @@ -100,7 +100,7 @@ class FunctionTest(xla_test.XLATestCase): b = constant_op.constant(bval, name="b") with self.test_scope(): call_f = Foo(a, b) - result = sess.run(call_f) + result = self.evaluate(call_f) self.assertAllClose(result, expected, rtol=1e-3) def testCompileTimeConstantsInDefun(self): diff --git a/tensorflow/compiler/tests/jit_test.py b/tensorflow/compiler/tests/jit_test.py index 6f51ae33a1..dbea9849e2 100644 --- a/tensorflow/compiler/tests/jit_test.py +++ b/tensorflow/compiler/tests/jit_test.py @@ -75,7 +75,7 @@ def RunMetadataLabels(run_metadata): def InLabels(labels, substr): """Returns true iff one of the labels contains substr.""" - return any([substr in x for x in labels]) + return any(substr in x for x in labels) def MetadataHasXlaRunOp(run_metadata): diff --git a/tensorflow/compiler/tests/listdiff_op_test.py b/tensorflow/compiler/tests/listdiff_op_test.py index 58622114e4..0210201fa7 100644 --- a/tensorflow/compiler/tests/listdiff_op_test.py +++ b/tensorflow/compiler/tests/listdiff_op_test.py @@ -33,13 +33,13 @@ class ListDiffTest(xla_test.XLATestCase): def _testListDiff(self, x, y, out, idx): for dtype in [dtypes.int32, dtypes.int64]: for index_dtype in [dtypes.int32, dtypes.int64]: - with self.cached_session() as sess: + with self.cached_session(): x_tensor = ops.convert_to_tensor(x, dtype=dtype) y_tensor = ops.convert_to_tensor(y, dtype=dtype) with self.test_scope(): out_tensor, idx_tensor = array_ops.listdiff( x_tensor, y_tensor, out_idx=index_dtype) - tf_out, tf_idx = sess.run([out_tensor, idx_tensor]) + tf_out, tf_idx = self.evaluate([out_tensor, idx_tensor]) self.assertAllEqual(out, tf_out) self.assertAllEqual(idx, tf_idx) self.assertEqual(1, out_tensor.get_shape().ndims) diff --git a/tensorflow/compiler/tests/lrn_ops_test.py b/tensorflow/compiler/tests/lrn_ops_test.py index c6ad67993e..5dddf6ae4e 100644 --- a/tensorflow/compiler/tests/lrn_ops_test.py +++ b/tensorflow/compiler/tests/lrn_ops_test.py @@ -120,8 +120,8 @@ class LRNTest(xla_test.XLATestCase): with self.test_scope(): actual = gen_nn_ops.lrn_grad(out_grads, in_image, out_image, depth_radius, bias, alpha, beta) - expected_val = expected.eval() - actual_val = actual.eval() + expected_val = self.evaluate(expected) + actual_val = self.evaluate(actual) self.assertAllClose(actual_val, expected_val, rtol=1e-3) diff --git a/tensorflow/compiler/tests/lstm_test.py b/tensorflow/compiler/tests/lstm_test.py index 265c0b6d14..776ed899e6 100644 --- a/tensorflow/compiler/tests/lstm_test.py +++ b/tensorflow/compiler/tests/lstm_test.py @@ -88,8 +88,8 @@ class LSTMTest(test.TestCase): (basename, m_prev_scalar, c_prev_scalar, pad_scalar)) # Initialize variables and run the unrolled LSTM step. - sess.run(variables.global_variables_initializer()) - return sess.run([m, c]) + self.evaluate(variables.global_variables_initializer()) + return self.evaluate([m, c]) def testLSTMCell(self): # Run with all-0 weights, no padding. @@ -173,8 +173,8 @@ class LSTMTest(test.TestCase): (basename, m_init_scalar, c_init_scalar, pad_scalar)) # Initialize variables and run the unrolled LSTM layer. - sess.run(variables.global_variables_initializer()) - return sess.run(out_seq) + self.evaluate(variables.global_variables_initializer()) + return self.evaluate(out_seq) def testLSTMLayer(self): # Run with all-0 weights, no padding. diff --git a/tensorflow/compiler/tests/momentum_test.py b/tensorflow/compiler/tests/momentum_test.py index f77521a7c4..3416f7dbd6 100644 --- a/tensorflow/compiler/tests/momentum_test.py +++ b/tensorflow/compiler/tests/momentum_test.py @@ -61,37 +61,43 @@ class MomentumOptimizerTest(xla_test.XLATestCase): self.assertFalse(slot1 in variables.trainable_variables()) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Step 1: the momentum accumulators where 0. So we should see a normal # update: v -= grad * learning_rate mom_update.run() # Check that the momentum accumulators have been updated. - self.assertAllCloseAccordingToType(np.array([0.1, 0.1]), slot0.eval()) - self.assertAllCloseAccordingToType(np.array([0.01, 0.01]), slot1.eval()) + self.assertAllCloseAccordingToType( + np.array([0.1, 0.1]), self.evaluate(slot0)) + self.assertAllCloseAccordingToType( + np.array([0.01, 0.01]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( - np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), var0.eval()) + np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), + self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), var1.eval()) + np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), + self.evaluate(var1)) # Step 2: the momentum accumulators contain the previous update. mom_update.run() # Check that the momentum accumulators have been updated. self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), slot0.eval()) + np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), + self.evaluate(slot0)) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), slot1.eval()) + np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), + self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( np.array([ 1.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0), 2.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ - 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), 3.98 - ( - (0.9 * 0.01 + 0.01) * 2.0) - ]), var1.eval()) + 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), + 3.98 - ((0.9 * 0.01 + 0.01) * 2.0) + ]), self.evaluate(var1)) def testNesterovMomentum(self): for dtype in self.float_types: @@ -115,8 +121,8 @@ class MomentumOptimizerTest(xla_test.XLATestCase): var0_np, accum0_np, var0_np * 0.8, 0.1, 0.9) var1_np, accum1_np = self._update_nesterov_momentum_numpy( var1_np, accum1_np, 0.9, 0.1, 0.9) - self.assertAllCloseAccordingToType(var0_np, var0.eval()) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) def testTensorLearningRateAndMomentum(self): for dtype in self.float_types: @@ -141,37 +147,43 @@ class MomentumOptimizerTest(xla_test.XLATestCase): self.assertFalse(slot1 in variables.trainable_variables()) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Step 1: the momentum accumulators where 0. So we should see a normal # update: v -= grad * learning_rate mom_update.run() # Check that the momentum accumulators have been updated. - self.assertAllCloseAccordingToType(np.array([0.1, 0.1]), slot0.eval()) - self.assertAllCloseAccordingToType(np.array([0.01, 0.01]), slot1.eval()) + self.assertAllCloseAccordingToType( + np.array([0.1, 0.1]), self.evaluate(slot0)) + self.assertAllCloseAccordingToType( + np.array([0.01, 0.01]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( - np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), var0.eval()) + np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), + self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), var1.eval()) + np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), + self.evaluate(var1)) # Step 2: the momentum accumulators contain the previous update. mom_update.run() # Check that the momentum accumulators have been updated. self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), slot0.eval()) + np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), + self.evaluate(slot0)) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), slot1.eval()) + np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), + self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( np.array([ 1.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0), 2.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ - 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), 3.98 - ( - (0.9 * 0.01 + 0.01) * 2.0) - ]), var1.eval()) + 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), + 3.98 - ((0.9 * 0.01 + 0.01) * 2.0) + ]), self.evaluate(var1)) if __name__ == "__main__": diff --git a/tensorflow/compiler/tests/placeholder_test.py b/tensorflow/compiler/tests/placeholder_test.py index 77bb839409..9671ae0ae9 100644 --- a/tensorflow/compiler/tests/placeholder_test.py +++ b/tensorflow/compiler/tests/placeholder_test.py @@ -33,7 +33,7 @@ class PlaceholderTest(xla_test.XLATestCase): ph = array_ops.placeholder_with_default(v, shape=[]) out = ph * 2 sess.run(variables.variables_initializer([v])) - self.assertEqual(8.0, sess.run(out)) + self.assertEqual(8.0, self.evaluate(out)) def test_placeholder_with_default_fed(self): with self.cached_session() as sess, self.test_scope(): diff --git a/tensorflow/compiler/tests/powersign_test.py b/tensorflow/compiler/tests/powersign_test.py index 86536da7fe..5b35c20027 100644 --- a/tensorflow/compiler/tests/powersign_test.py +++ b/tensorflow/compiler/tests/powersign_test.py @@ -91,8 +91,8 @@ class PowerSignTest(xla_test.XLATestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 7 steps of powersign # first 4 steps with positive gradient @@ -125,8 +125,8 @@ class PowerSignTest(xla_test.XLATestCase): ) # Validate updated params - self.assertAllCloseAccordingToType(var0_np, var0.eval()) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) def testDense(self): decay_steps = 10 diff --git a/tensorflow/compiler/tests/proximal_adagrad_test.py b/tensorflow/compiler/tests/proximal_adagrad_test.py index c41b4171e2..63cc51a470 100644 --- a/tensorflow/compiler/tests/proximal_adagrad_test.py +++ b/tensorflow/compiler/tests/proximal_adagrad_test.py @@ -45,15 +45,17 @@ class ProximalAdagradOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([0.0, 0.0], var0.eval()) - self.assertAllClose([0.0, 0.0], var1.eval()) + self.assertAllClose([0.0, 0.0], self.evaluate(var0)) + self.assertAllClose([0.0, 0.0], self.evaluate(var1)) # Run 3 steps Proximal Adagrad. for _ in range(3): update.run() - self.assertAllClose(np.array([-2.60260963, -4.29698515]), var0.eval()) - self.assertAllClose(np.array([-0.28432083, -0.56694895]), var1.eval()) + self.assertAllClose( + np.array([-2.60260963, -4.29698515]), self.evaluate(var0)) + self.assertAllClose( + np.array([-0.28432083, -0.56694895]), self.evaluate(var1)) opt_vars = opt.variables() self.assertStartsWith(opt_vars[0].name, var0._shared_name) self.assertStartsWith(opt_vars[1].name, var1._shared_name) @@ -74,14 +76,14 @@ class ProximalAdagradOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([4.0, 3.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([4.0, 3.0], self.evaluate(var1)) # Run 3 steps Proximal Adagrad. for _ in range(3): update.run() - self.assertAllClose(np.array([-1.60261, -2.296985]), var0.eval()) - self.assertAllClose(np.array([3.715679, 2.433051]), var1.eval()) + self.assertAllClose(np.array([-1.60261, -2.296985]), self.evaluate(var0)) + self.assertAllClose(np.array([3.715679, 2.433051]), self.evaluate(var1)) def testProximalAdagradWithL1(self): with self.cached_session(), self.test_scope(): @@ -98,14 +100,14 @@ class ProximalAdagradOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([4.0, 3.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([4.0, 3.0], self.evaluate(var1)) # Run 10 steps Proximal Adagrad for _ in range(10): update.run() - self.assertAllClose(np.array([-6.663634, -9.190331]), var0.eval()) - self.assertAllClose(np.array([2.959304, 1.029232]), var1.eval()) + self.assertAllClose(np.array([-6.663634, -9.190331]), self.evaluate(var0)) + self.assertAllClose(np.array([2.959304, 1.029232]), self.evaluate(var1)) def testProximalAdagradWithL1_L2(self): with self.cached_session(), self.test_scope(): @@ -122,15 +124,15 @@ class ProximalAdagradOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([4.0, 3.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([4.0, 3.0], self.evaluate(var1)) # Run 10 steps Proximal Adagrad. for _ in range(10): update.run() - self.assertAllClose(np.array([-0.0495, -0.0995]), var0.eval()) - self.assertAllClose(np.array([-0.0045, -0.0095]), var1.eval()) + self.assertAllClose(np.array([-0.0495, -0.0995]), self.evaluate(var0)) + self.assertAllClose(np.array([-0.0045, -0.0095]), self.evaluate(var1)) def applyOptimizer(self, opt, steps=5): var0 = resource_variable_ops.ResourceVariable([1.0, 2.0]) @@ -141,14 +143,14 @@ class ProximalAdagradOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run ProximalAdagrad for a few steps for _ in range(steps): update.run() - return var0.eval(), var1.eval() + return self.evaluate(var0), self.evaluate(var1) def testEquivAdagradwithoutRegularization(self): with self.cached_session(), self.test_scope(): diff --git a/tensorflow/compiler/tests/proximal_gradient_descent_test.py b/tensorflow/compiler/tests/proximal_gradient_descent_test.py index 3d808e6b8a..5aec433be7 100644 --- a/tensorflow/compiler/tests/proximal_gradient_descent_test.py +++ b/tensorflow/compiler/tests/proximal_gradient_descent_test.py @@ -42,15 +42,15 @@ class ProximalGradientDescentOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([0.0, 0.0], var0.eval()) - self.assertAllClose([0.0, 0.0], var1.eval()) + self.assertAllClose([0.0, 0.0], self.evaluate(var0)) + self.assertAllClose([0.0, 0.0], self.evaluate(var1)) # Run 3 steps Proximal Gradient Descent. for _ in range(3): update.run() - self.assertAllClose(np.array([-0.9, -1.8]), var0.eval()) - self.assertAllClose(np.array([-0.09, -0.18]), var1.eval()) + self.assertAllClose(np.array([-0.9, -1.8]), self.evaluate(var0)) + self.assertAllClose(np.array([-0.09, -0.18]), self.evaluate(var1)) def testProximalGradientDescentwithoutRegularization2(self): with self.cached_session(), self.test_scope(): @@ -64,15 +64,15 @@ class ProximalGradientDescentOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([4.0, 3.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([4.0, 3.0], self.evaluate(var1)) # Run 3 steps Proximal Gradient Descent for _ in range(3): update.run() - self.assertAllClose(np.array([0.1, 0.2]), var0.eval()) - self.assertAllClose(np.array([3.91, 2.82]), var1.eval()) + self.assertAllClose(np.array([0.1, 0.2]), self.evaluate(var0)) + self.assertAllClose(np.array([3.91, 2.82]), self.evaluate(var1)) def testProximalGradientDescentWithL1(self): with self.cached_session(), self.test_scope(): @@ -86,15 +86,15 @@ class ProximalGradientDescentOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([4.0, 3.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([4.0, 3.0], self.evaluate(var1)) # Run 10 steps proximal gradient descent. for _ in range(10): update.run() - self.assertAllClose(np.array([-1.988, -3.988001]), var0.eval()) - self.assertAllClose(np.array([3.67, 2.37]), var1.eval()) + self.assertAllClose(np.array([-1.988, -3.988001]), self.evaluate(var0)) + self.assertAllClose(np.array([3.67, 2.37]), self.evaluate(var1)) def testProximalGradientDescentWithL1_L2(self): with self.cached_session(), self.test_scope(): @@ -108,15 +108,15 @@ class ProximalGradientDescentOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([4.0, 3.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([4.0, 3.0], self.evaluate(var1)) # Run 10 steps Proximal Gradient Descent for _ in range(10): update.run() - self.assertAllClose(np.array([-0.0495, -0.0995]), var0.eval()) - self.assertAllClose(np.array([-0.0045, -0.0095]), var1.eval()) + self.assertAllClose(np.array([-0.0495, -0.0995]), self.evaluate(var0)) + self.assertAllClose(np.array([-0.0045, -0.0095]), self.evaluate(var1)) def applyOptimizer(self, opt, steps=5): var0 = resource_variable_ops.ResourceVariable([1.0, 2.0]) @@ -127,14 +127,14 @@ class ProximalGradientDescentOptimizerTest(xla_test.XLATestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run ProximalAdagrad for a few steps for _ in range(steps): update.run() - return var0.eval(), var1.eval() + return self.evaluate(var0), self.evaluate(var1) def testEquivGradientDescentwithoutRegularization(self): with self.cached_session(), self.test_scope(): diff --git a/tensorflow/compiler/tests/qr_op_test.py b/tensorflow/compiler/tests/qr_op_test.py index 236b1b881d..b4d4193e35 100644 --- a/tensorflow/compiler/tests/qr_op_test.py +++ b/tensorflow/compiler/tests/qr_op_test.py @@ -63,7 +63,7 @@ class QrOpTest(xla_test.XLATestCase, parameterized.TestCase): # Tests that x[...,:,:]^H * x[...,:,:] is close to the identity. xx = math_ops.matmul(x, x, adjoint_a=True) identity = array_ops.matrix_band_part(array_ops.ones_like(xx), 0, 0) - precision = self.AdjustedNorm(xx.eval() - identity.eval()) + precision = self.AdjustedNorm(xx.eval() - self.evaluate(identity)) self.assertTrue(np.all(precision < 5.0)) def _test(self, dtype, shape, full_matrices): diff --git a/tensorflow/compiler/tests/random_ops_test.py b/tensorflow/compiler/tests/random_ops_test.py index 36ef6ed5fe..97ffad34c0 100644 --- a/tensorflow/compiler/tests/random_ops_test.py +++ b/tensorflow/compiler/tests/random_ops_test.py @@ -46,9 +46,9 @@ class RandomOpsTest(xla_test.XLATestCase): # The random-number generator, if working correctly, should produce the # same output multiple times with low probability. - y = sess.run(x) - z = sess.run(x) - w = sess.run(x) + y = self.evaluate(x) + z = self.evaluate(x) + w = self.evaluate(x) # We use exact equality here. If the random-number generator is producing # deterministic output, all three outputs will be bitwise identical. @@ -83,7 +83,7 @@ class RandomOpsTest(xla_test.XLATestCase): with self.test_scope(): x = random_ops.random_uniform( shape=[1000], dtype=dtype, minval=-2, maxval=33) - y = sess.run(x) + y = self.evaluate(x) self.assertTrue((y >= -2).sum() == 1000) self.assertTrue((y < 33).sum() == 1000) @@ -102,7 +102,7 @@ class RandomOpsTest(xla_test.XLATestCase): with self.cached_session() as sess: with self.test_scope(): x = random_ops.truncated_normal(shape=[count], dtype=dtype) - y = sess.run(x) + y = self.evaluate(x) def normal_cdf(x): return .5 * math.erfc(-x / math.sqrt(2)) @@ -111,7 +111,7 @@ class RandomOpsTest(xla_test.XLATestCase): return math.exp(-(x**2) / 2.) / math.sqrt(2 * math.pi) def probit(x, sess=sess): - return sess.run(special_math.ndtri(x)) + return self.evaluate(special_math.ndtri(x)) a = -2. b = 2. @@ -148,7 +148,7 @@ class RandomOpsTest(xla_test.XLATestCase): with self.test_scope(): x = math_ops.range(1 << 16) shuffle = random_ops.random_shuffle(x) - result = sess.run(shuffle) + result = self.evaluate(shuffle) expected = range(1 << 16) # Compare sets to avoid randomness behavior changes but make sure still # have all the values. @@ -159,7 +159,7 @@ class RandomOpsTest(xla_test.XLATestCase): with self.test_scope(): x = array_ops.diag(math_ops.range(20)) shuffle = random_ops.random_shuffle(x) - result = sess.run(shuffle) + result = self.evaluate(shuffle) expected = np.diag(range(20)).flatten() # Compare sets to avoid randomness behavior changes but make sure still # have all the values. diff --git a/tensorflow/compiler/tests/randomized_tests.cc b/tensorflow/compiler/tests/randomized_tests.cc index a6b5802012..d23fd12516 100644 --- a/tensorflow/compiler/tests/randomized_tests.cc +++ b/tensorflow/compiler/tests/randomized_tests.cc @@ -3382,10 +3382,10 @@ int main(int argc, char** argv) { } // XLA devices register kernels at construction time; create all known devices // to make sure the kernels are registered. - std::vector devices; + std::vector> devices; TF_CHECK_OK(tensorflow::DeviceFactory::AddDevices( tensorflow::SessionOptions(), "", &devices)); - tensorflow::DeviceMgr device_mgr(devices); + tensorflow::DeviceMgr device_mgr(std::move(devices)); tensorflow::Device* ignored; TF_QCHECK_OK( diff --git a/tensorflow/compiler/tests/reduce_ops_test.py b/tensorflow/compiler/tests/reduce_ops_test.py index 132c59c32c..e8fc81bbb5 100644 --- a/tensorflow/compiler/tests/reduce_ops_test.py +++ b/tensorflow/compiler/tests/reduce_ops_test.py @@ -91,6 +91,7 @@ class ReduceOpsTest(xla_test.XLATestCase, parameterized.TestCase): np.array([], dtype=np.bool).reshape(0, 3), np.array([[False, True, False], [True, True, False]]), ] + ONES = [np.ones([34000, 2])] def testReduceSumF32(self, index_dtype): self._testReduction(math_ops.reduce_sum, np.sum, np.float32, self.REAL_DATA, @@ -149,6 +150,11 @@ class ReduceOpsTest(xla_test.XLATestCase, parameterized.TestCase): self._testReduction(math_ops.reduce_mean, np.mean, np.float32, self.NONEMPTY_REAL_DATA, index_dtype) + def testReduceMeanF16(self, index_dtype): + if np.float16 in self.all_types: + self._testReduction(math_ops.reduce_mean, np.mean, np.float16, self.ONES, + index_dtype) + def testReduceMeanC64(self, index_dtype): self._testReduction(math_ops.reduce_mean, np.mean, np.complex64, self.NONEMPTY_COMPLEX_DATA, index_dtype) diff --git a/tensorflow/compiler/tests/rmsprop_test.py b/tensorflow/compiler/tests/rmsprop_test.py index 8840a1329a..dc3e90b4af 100644 --- a/tensorflow/compiler/tests/rmsprop_test.py +++ b/tensorflow/compiler/tests/rmsprop_test.py @@ -76,7 +76,7 @@ class RmspropTest(xla_test.XLATestCase): rms_opt = rmsprop.RMSPropOptimizer(learning_rate, centered=centered) rms_update = rms_opt.apply_gradients( zip([grads0, grads1], [var0, var1])) - variables.global_variables_initializer().run() + self.evaluate(variables.global_variables_initializer()) mg0 = rms_opt.get_slot(var0, "mg") self.assertEqual(mg0 is not None, centered) @@ -92,12 +92,12 @@ class RmspropTest(xla_test.XLATestCase): self.assertTrue(mom1 is not None) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 3 steps of RMSProp for _ in range(3): - rms_update.run() + self.evaluate(rms_update) var0_np, mg0_np, rms0_np, mom0_np = self._rmsprop_update_numpy( var0_np, @@ -118,14 +118,14 @@ class RmspropTest(xla_test.XLATestCase): # Validate updated params if centered: - self.assertAllCloseAccordingToType(mg0_np, mg0.eval()) - self.assertAllCloseAccordingToType(mg1_np, mg1.eval()) - self.assertAllCloseAccordingToType(rms0_np, rms0.eval()) - self.assertAllCloseAccordingToType(rms1_np, rms1.eval()) - self.assertAllCloseAccordingToType(mom0_np, mom0.eval()) - self.assertAllCloseAccordingToType(mom1_np, mom1.eval()) - self.assertAllCloseAccordingToType(var0_np, var0.eval()) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) + self.assertAllCloseAccordingToType(mg0_np, self.evaluate(mg0)) + self.assertAllCloseAccordingToType(mg1_np, self.evaluate(mg1)) + self.assertAllCloseAccordingToType(rms0_np, self.evaluate(rms0)) + self.assertAllCloseAccordingToType(rms1_np, self.evaluate(rms1)) + self.assertAllCloseAccordingToType(mom0_np, self.evaluate(mom0)) + self.assertAllCloseAccordingToType(mom1_np, self.evaluate(mom1)) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) if __name__ == "__main__": diff --git a/tensorflow/compiler/tests/scan_ops_test.py b/tensorflow/compiler/tests/scan_ops_test.py index 897db384b7..17639bd8a7 100644 --- a/tensorflow/compiler/tests/scan_ops_test.py +++ b/tensorflow/compiler/tests/scan_ops_test.py @@ -71,7 +71,7 @@ def handle_options(func, x, axis, exclusive, reverse): class CumsumTest(xla_test.XLATestCase): - valid_dtypes = [np.float32] + valid_dtypes = [np.float32, np.int32] def axis_dtypes(self): return set(self.int_types).intersection([np.int32, np.int64]) @@ -149,7 +149,7 @@ class CumsumTest(xla_test.XLATestCase): class CumprodTest(xla_test.XLATestCase): - valid_dtypes = [np.float32] + valid_dtypes = [np.float32, np.int32] def axis_dtypes(self): return set(self.int_types).intersection([np.int32, np.int64]) diff --git a/tensorflow/compiler/tests/stateless_random_ops_test.py b/tensorflow/compiler/tests/stateless_random_ops_test.py index 21708aa158..ee7ca7e6f1 100644 --- a/tensorflow/compiler/tests/stateless_random_ops_test.py +++ b/tensorflow/compiler/tests/stateless_random_ops_test.py @@ -156,7 +156,7 @@ class StatelessRandomOpsTest(xla_test.XLATestCase): return math.exp(-(x**2) / 2.) / math.sqrt(2 * math.pi) def probit(x, sess=sess): - return sess.run(special_math.ndtri(x)) + return self.evaluate(special_math.ndtri(x)) a = -2. b = 2. diff --git a/tensorflow/compiler/tests/tensor_array_ops_test.py b/tensorflow/compiler/tests/tensor_array_ops_test.py index 46ca371c8a..d7e26d79c4 100644 --- a/tensorflow/compiler/tests/tensor_array_ops_test.py +++ b/tensorflow/compiler/tests/tensor_array_ops_test.py @@ -79,7 +79,8 @@ class TensorArrayTest(xla_test.XLATestCase): c0 = w2.stack() self.assertAllEqual( - convert([[[4.0, 5.0]], [[6.0, 7.0]], [[8.0, 9.0]]]), c0.eval()) + convert([[[4.0, 5.0]], [[6.0, 7.0]], [[8.0, 9.0]]]), + self.evaluate(c0)) def testTensorArrayWritePack(self): for dtype in self.numeric_tf_types: @@ -97,7 +98,7 @@ class TensorArrayTest(xla_test.XLATestCase): c0 = w2.stack() - self.assertAllEqual([3, 0, 1], c0.eval().shape) + self.assertAllEqual([3, 0, 1], self.evaluate(c0).shape) def _testTensorArrayWriteConcat(self, tf_dtype): with self.cached_session(), self.test_scope(): @@ -113,8 +114,8 @@ class TensorArrayTest(xla_test.XLATestCase): c0 = w2.concat() self.assertAllEqual( - convert([[4.0, 5.0], [104.0, 105.0], [6.0, 7.0], - [106.0, 107.0], [8.0, 9.0], [204.0, 205.0]]), c0.eval()) + convert([[4.0, 5.0], [104.0, 105.0], [6.0, 7.0], [106.0, 107.0], + [8.0, 9.0], [204.0, 205.0]]), self.evaluate(c0)) def testTensorArrayWriteConcat(self): for dtype in self.numeric_tf_types: @@ -341,7 +342,7 @@ class TensorArrayTest(xla_test.XLATestCase): r0_bad = gen_data_flow_ops.tensor_array_read_v3( handle=w0.handle, index=0, dtype=dtype2, flow_in=w0.flow) with self.assertRaisesOpError("TensorArray dtype is "): - r0_bad.eval() + self.evaluate(r0_bad) # Test reading from a different index than the one we wrote to w0.read(1) @@ -422,7 +423,7 @@ class TensorArrayTest(xla_test.XLATestCase): w2 = h2.write(0, 5.0) r2 = w2.read(0) r = r1 + r2 - self.assertAllClose(9.0, r.eval()) + self.assertAllClose(9.0, self.evaluate(r)) def _testTensorArrayGradientWriteReadType(self, dtype): with self.cached_session() as session, self.test_scope(): @@ -504,7 +505,7 @@ class TensorArrayTest(xla_test.XLATestCase): [-0.5, 1.5], # read(0) gradient [20.0, 30.0, 40.0, 50.0], # concat gradient ]) - grad_vals = sess.run(grad_r) # 2 + 2 entries + grad_vals = self.evaluate(grad_r) # 2 + 2 entries self.assertAllClose([2.0 - 0.5 + 20.0, 3.0 + 1.5 + 30.0], grad_vals[0]) self.assertAllEqual([4.0 + 40.0, 5.0 + 50.0], grad_vals[1]) @@ -526,7 +527,7 @@ class TensorArrayTest(xla_test.XLATestCase): with ops.control_dependencies([r0_readtwice]): r1_readtwice = w_readtwice.read(0) - self.assertAllEqual([1.0, -1.0], r1_readtwice.eval()) + self.assertAllEqual([1.0, -1.0], self.evaluate(r1_readtwice)) def _testTensorArrayGradientUnpackRead(self): with self.cached_session() as session, self.test_scope(): @@ -592,7 +593,7 @@ class TensorArrayTest(xla_test.XLATestCase): ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, tensor_array_name="foo", size=3) s = ta.size() - self.assertAllEqual(3, s.eval()) + self.assertAllEqual(3, self.evaluate(s)) def testWriteCloseTensorArray(self): with self.cached_session(), self.test_scope(): @@ -722,7 +723,7 @@ class TensorArrayTest(xla_test.XLATestCase): # r = acc2.stack() # grad = gradients_impl.gradients(r, [x])[0] - # self.assertAllClose(31.0, grad.eval()) + # self.assertAllClose(31.0, self.evaluate(grad)) def testSumOfTwoReadVariablesWithoutRepeatGrad(self): with self.cached_session() as session, self.test_scope(): @@ -912,7 +913,7 @@ class TensorArrayTest(xla_test.XLATestCase): self.assertEqual(0, ta.size().eval()) ta = ta.unstack(array_ops.zeros([0, 3, 5])) packed = ta.stack() - self.assertAllEqual([0, 3, 5], packed.eval().shape) + self.assertAllEqual([0, 3, 5], self.evaluate(packed).shape) # Concatenating zero tensors along their first dimension gives a # first dimension of zero self.assertAllEqual([0, 5], ta.concat().eval().shape) @@ -1041,8 +1042,8 @@ class TensorArrayTest(xla_test.XLATestCase): (read0, read1, size0, size1)) # Tests that the control dependencies was added and executed. - self.assertEqual(1, v0.eval()) - self.assertEqual(1, v1.eval()) + self.assertEqual(1, self.evaluate(v0)) + self.assertEqual(1, self.evaluate(v1)) # Tests correct TensorArray. self.assertEqual(read0_v, 0) diff --git a/tensorflow/compiler/tests/unary_ops_test.py b/tensorflow/compiler/tests/unary_ops_test.py index d612d3b32d..95c9e7ffd4 100644 --- a/tensorflow/compiler/tests/unary_ops_test.py +++ b/tensorflow/compiler/tests/unary_ops_test.py @@ -481,6 +481,72 @@ class UnaryOpsTest(xla_test.XLATestCase): np.array([-1, -0.5, 0, 0.3], dtype=dtype), expected=np.array([-1., -0.5, 0., 0.296875], dtype=dtype)) + def quantize_and_dequantize_v2_round_half_up(x): + return array_ops.quantize_and_dequantize_v2( + x, + -1, + 1.0, + signed_input=True, + num_bits=8, + range_given=True, + round_mode="HALF_UP") + + self._assertOpOutputMatchesExpected( + quantize_and_dequantize_v2_round_half_up, + np.array([-0.8, -0.5, 0, 0.3, 0.8, -2, 33], dtype=dtype), + expected=np.array([ + -102.0 / 127, + -63.0 / 127, + 0, + 38.0 / 127, + 102.0 / 127, + -128.0 / 127, + 1, + ], + dtype=dtype)) + + def quantize_and_dequantize_v2_round_half_to_even(x): + return array_ops.quantize_and_dequantize_v2( + x, + -1.0, + 1.0, + signed_input=True, + num_bits=8, + range_given=True, + round_mode="HALF_TO_EVEN") + + self._assertOpOutputMatchesExpected( + quantize_and_dequantize_v2_round_half_to_even, + np.array( + [ + -0.8, + # The -0.5 should become -63.5 after scaling and with + # rounding this should become -64. But with the test + # unary_ops_test_cpu_ondemand, this fails as the result + # before scaling becomes -63.499996 and gets rounded to -63. + # TODO(sreenik): Some one more familiar with this test needs + # to take a look and resolve this. This works on all other + # variations of the platform like cpu, and gpu. + # -0.5, + 0, + 0.3, + 0.8, + -2, + 33 + ], + dtype=dtype), + expected=np.array( + [ + -102.0 / 127, + # -64.0 / 127, + 0, + 38.0 / 127, + 102.0 / 127, + -128.0 / 127, + 1, + ], + dtype=dtype)) + def quantize_and_dequantize_v3(x): return array_ops.quantize_and_dequantize_v3( x, -127, 127, num_bits=8, signed_input=True, range_given=False) diff --git a/tensorflow/compiler/tests/variable_ops_test.py b/tensorflow/compiler/tests/variable_ops_test.py index 77cdeac816..fcd7ac5ba1 100644 --- a/tensorflow/compiler/tests/variable_ops_test.py +++ b/tensorflow/compiler/tests/variable_ops_test.py @@ -77,7 +77,7 @@ class VariableOpsTest(xla_test.XLATestCase): sess.run(variables.variables_initializer([v])) x = v.sparse_read(2) self.assertAllClose( - np.array([8j, 9, 10, 11]).astype(dtype), sess.run(x)) + np.array([8j, 9, 10, 11]).astype(dtype), self.evaluate(x)) def testSparseRead1DIndices(self): for dtype in self.numeric_types: @@ -89,7 +89,7 @@ class VariableOpsTest(xla_test.XLATestCase): x = v.sparse_read([2, 1]) self.assertAllClose( np.array([[8, 9, 10, 11], [4, 5, 6j, 7]]).astype(dtype), - sess.run(x)) + self.evaluate(x)) def testSparseRead2DIndices(self): for dtype in self.numeric_types: @@ -102,7 +102,7 @@ class VariableOpsTest(xla_test.XLATestCase): self.assertAllClose( np.array([[[8, 9, 10, 11], [4, 5, 6, 7]], [[0, 1, 2j, 3], [8, 9, 10, 11]]]).astype(dtype), - sess.run(x)) + self.evaluate(x)) def testSparseRead2DIndices3DTensor(self): for dtype in self.numeric_types: @@ -115,9 +115,9 @@ class VariableOpsTest(xla_test.XLATestCase): x = v.sparse_read([[2, 1], [3, 0]]) self.assertAllClose( np.array( - [[[[20, 21, 22], [23, 24j, 25]], [[10, 11, 12], [13, 14, 15]] - ], [[[30, 31, 32], [33, 34, 35]], [[0, 1, 2], [3, 4, 5]]] - ],).astype(dtype), sess.run(x)) + [[[[20, 21, 22], [23, 24j, 25]], [[10, 11, 12], [13, 14, 15]]], + [[[30, 31, 32], [33, 34, 35]], [[0, 1, 2], [3, 4, 5]]] + ],).astype(dtype), self.evaluate(x)) def testShape(self): for dtype in self.numeric_types: @@ -229,7 +229,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_add( handle, [0], constant_op.constant([[2]], dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertAllEqual(sess.run(read), [[3], [7]]) + self.assertAllEqual(self.evaluate(read), [[3], [7]]) def testScatterSub(self): with self.test_session() as sess, self.test_scope(): @@ -242,7 +242,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_sub( handle, [1], constant_op.constant([[2]], dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertAllEqual(sess.run(read), [[4], [-1]]) + self.assertAllEqual(self.evaluate(read), [[4], [-1]]) def testScatterMul(self): with self.test_session() as sess, self.test_scope(): @@ -255,7 +255,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_mul( handle, [0], constant_op.constant([[5]], dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[5]]) + self.assertEqual(self.evaluate(read), [[5]]) def testScatterDiv(self): with self.test_session() as sess, self.test_scope(): @@ -268,7 +268,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_div( handle, [0], constant_op.constant([[3]], dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertAllEqual(sess.run(read), [[2]]) + self.assertAllEqual(self.evaluate(read), [[2]]) def testScatterMin(self): with self.test_session() as sess, self.test_scope(): @@ -281,7 +281,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_min( handle, [0], constant_op.constant([[3]], dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[3]]) + self.assertEqual(self.evaluate(read), [[3]]) def testScatterMax(self): with self.test_session() as sess, self.test_scope(): @@ -294,7 +294,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_max( handle, [0], constant_op.constant([[3]], dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[6]]) + self.assertEqual(self.evaluate(read), [[6]]) def testScatterUpdate(self): with self.test_session() as sess, self.test_scope(): @@ -307,7 +307,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_update( handle, [0], constant_op.constant([[3]], dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[3]]) + self.assertEqual(self.evaluate(read), [[3]]) def testScatterAddScalar(self): with self.test_session() as sess, self.test_scope(): @@ -320,7 +320,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_add( handle, [0], constant_op.constant(2, dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[3]]) + self.assertEqual(self.evaluate(read), [[3]]) def testScatterSubScalar(self): with self.test_session() as sess, self.test_scope(): @@ -333,7 +333,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_sub( handle, [0], constant_op.constant(2, dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[-1]]) + self.assertEqual(self.evaluate(read), [[-1]]) def testScatterMulScalar(self): with self.test_session() as sess, self.test_scope(): @@ -346,7 +346,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_mul( handle, [0], constant_op.constant(5, dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[5]]) + self.assertEqual(self.evaluate(read), [[5]]) def testScatterDivScalar(self): with self.test_session() as sess, self.test_scope(): @@ -359,7 +359,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_div( handle, [0], constant_op.constant(3, dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[2]]) + self.assertEqual(self.evaluate(read), [[2]]) def testScatterMinScalar(self): with self.test_session() as sess, self.test_scope(): @@ -372,7 +372,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_min( handle, [0], constant_op.constant(3, dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[3]]) + self.assertEqual(self.evaluate(read), [[3]]) def testScatterMaxScalar(self): with self.test_session() as sess, self.test_scope(): @@ -385,7 +385,7 @@ class VariableOpsTest(xla_test.XLATestCase): resource_variable_ops.resource_scatter_max( handle, [0], constant_op.constant(3, dtype=dtypes.int32))) read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) - self.assertEqual(sess.run(read), [[6]]) + self.assertEqual(self.evaluate(read), [[6]]) def testScatterNdAddOps(self): with self.test_session() as sess, self.test_scope(): @@ -400,7 +400,7 @@ class VariableOpsTest(xla_test.XLATestCase): sess.run(gen_state_ops.resource_scatter_nd_add(handle, indices, updates)) read = resource_variable_ops.read_variable_op( handle, dtype=dtypes.float32) - self.assertAllClose(expected, sess.run(read)) + self.assertAllClose(expected, self.evaluate(read)) def testScatterNdUpdateAddOps(self): with self.test_session() as sess, self.test_scope(): @@ -416,7 +416,7 @@ class VariableOpsTest(xla_test.XLATestCase): gen_state_ops.resource_scatter_nd_update(handle, indices, updates)) read = resource_variable_ops.read_variable_op( handle, dtype=dtypes.float32) - self.assertAllClose(expected, sess.run(read)) + self.assertAllClose(expected, self.evaluate(read)) class StridedSliceAssignChecker(object): diff --git a/tensorflow/compiler/tests/xla_device_test.py b/tensorflow/compiler/tests/xla_device_test.py index 28d61fb07d..ef55292b1b 100644 --- a/tensorflow/compiler/tests/xla_device_test.py +++ b/tensorflow/compiler/tests/xla_device_test.py @@ -81,7 +81,7 @@ class XlaDeviceTest(xla_test.XLATestCase): with self.cached_session() as sess: with self.test_scope(): x = gen_control_flow_ops.control_trigger() - sess.run(x) + self.evaluate(x) if __name__ == "__main__": diff --git a/tensorflow/compiler/tf2xla/BUILD b/tensorflow/compiler/tf2xla/BUILD index e017141549..5a0d9b9af9 100644 --- a/tensorflow/compiler/tf2xla/BUILD +++ b/tensorflow/compiler/tf2xla/BUILD @@ -9,6 +9,7 @@ package_group( "//tensorflow/compiler/jit/...", "//tensorflow/compiler/tests/...", "//tensorflow/compiler/tf2xla/...", + "//tensorflow/contrib/compiler/...", ], ) @@ -195,8 +196,8 @@ cc_library( ":sharding_util", ":side_effect_util", ":tf2xla_util", + "//tensorflow/compiler/jit:flags", "//tensorflow/compiler/jit:xla_cluster_util", - "//tensorflow/compiler/jit/legacy_flags:mark_for_compilation_pass_flags", "//tensorflow/compiler/tf2xla/lib:util", "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:shape_util", @@ -204,13 +205,13 @@ cc_library( "//tensorflow/compiler/xla:statusor", "//tensorflow/compiler/xla:types", "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/compiler/xla/client", "//tensorflow/compiler/xla/client:client_library", "//tensorflow/compiler/xla/client:local_client", "//tensorflow/compiler/xla/client:xla_builder", "//tensorflow/compiler/xla/client:xla_computation", "//tensorflow/compiler/xla/client/lib:arithmetic", "//tensorflow/compiler/xla/client/lib:constants", - "//tensorflow/compiler/xla/client/lib:numeric", "//tensorflow/core:core_cpu", "//tensorflow/core:core_cpu_internal", "//tensorflow/core:framework", @@ -221,6 +222,7 @@ cc_library( "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", + "@com_google_absl//absl/types:optional", "@com_google_absl//absl/types:span", ], alwayslink = 1, @@ -437,21 +439,15 @@ cc_library( name = "dump_graph", srcs = [ "dump_graph.cc", - "dump_graph_flags.cc", - "dump_graph_flags.h", ], hdrs = [ "dump_graph.h", ], deps = [ - "//tensorflow/compiler/xla:parse_flags_from_env", - "//tensorflow/core:core_cpu", - "//tensorflow/core:core_cpu_internal", + "//tensorflow/compiler/jit:flags", "//tensorflow/core:framework", - "//tensorflow/core:framework_internal", - "//tensorflow/core:lib", + "//tensorflow/core:graph", "//tensorflow/core:protos_all_cc", - "@com_google_absl//absl/strings", ], ) diff --git a/tensorflow/compiler/tf2xla/dump_graph.cc b/tensorflow/compiler/tf2xla/dump_graph.cc index 380c6a7e23..64fdbbebc6 100644 --- a/tensorflow/compiler/tf2xla/dump_graph.cc +++ b/tensorflow/compiler/tf2xla/dump_graph.cc @@ -18,87 +18,26 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/dump_graph.h" -#include "absl/strings/str_cat.h" -#include "tensorflow/compiler/tf2xla/dump_graph_flags.h" -#include "tensorflow/core/platform/env.h" -#include "tensorflow/core/platform/mutex.h" +#include "tensorflow/compiler/jit/flags.h" +#include "tensorflow/core/util/dump_graph.h" namespace tensorflow { namespace dump_graph { -namespace { - -struct NameCounts { - mutex counts_mutex; - std::unordered_map counts; -}; - -string MakeUniqueFilename(string name) { - static NameCounts& instance = *new NameCounts; - - // Remove illegal characters from `name`. - for (int i = 0; i < name.size(); ++i) { - char ch = name[i]; - if (ch == '/' || ch == '[' || ch == ']' || ch == '*' || ch == '?') { - name[i] = '_'; - } - } - - int count; - { - mutex_lock lock(instance.counts_mutex); - count = instance.counts[name]++; - } - - string filename = name; - if (count > 0) { - absl::StrAppend(&filename, "_", count); - } - absl::StrAppend(&filename, ".pbtxt"); - return filename; -} - -string WriteTextProtoToUniqueFile( - Env* env, const string& name, const char* proto_type, - const ::tensorflow::protobuf::Message& proto) { - const string& dirname = - legacy_flags::GetDumpGraphFlags()->tf_dump_graph_prefix; - Status status = env->RecursivelyCreateDir(dirname); - if (!status.ok()) { - LOG(WARNING) << "Failed to create " << dirname << " for dumping " - << proto_type << ": " << status; - return "(unavailable)"; - } - string filepath = absl::StrCat(dirname, "/", MakeUniqueFilename(name)); - status = WriteTextProto(Env::Default(), filepath, proto); - if (!status.ok()) { - LOG(WARNING) << "Failed to dump " << proto_type << " to file: " << filepath - << " : " << status; - return "(unavailable)"; - } - LOG(INFO) << "Dumped " << proto_type << " to " << filepath; - return filepath; -} - -} // anonymous namespace - string DumpGraphDefToFile(const string& name, GraphDef const& graph_def) { - return WriteTextProtoToUniqueFile(Env::Default(), name, "GraphDef", - graph_def); + return tensorflow::DumpGraphDefToFile( + name, graph_def, GetDumpGraphFlags()->tf_dump_graph_prefix); } string DumpGraphToFile(const string& name, Graph const& graph, const FunctionLibraryDefinition* flib_def) { - GraphDef graph_def; - graph.ToGraphDef(&graph_def); - if (flib_def) { - *graph_def.mutable_library() = flib_def->ToProto(); - } - return DumpGraphDefToFile(name, graph_def); + return tensorflow::DumpGraphToFile(name, graph, flib_def, + GetDumpGraphFlags()->tf_dump_graph_prefix); } string DumpFunctionDefToFile(const string& name, FunctionDef const& fdef) { - return WriteTextProtoToUniqueFile(Env::Default(), name, "FunctionDef", fdef); + return tensorflow::DumpFunctionDefToFile( + name, fdef, GetDumpGraphFlags()->tf_dump_graph_prefix); } } // namespace dump_graph diff --git a/tensorflow/compiler/tf2xla/dump_graph_flags.cc b/tensorflow/compiler/tf2xla/dump_graph_flags.cc deleted file mode 100644 index 2eb1f8cd84..0000000000 --- a/tensorflow/compiler/tf2xla/dump_graph_flags.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -// Legacy flags for the XLA bridge's dump_graph module. - -#include -#include - -#include "tensorflow/compiler/tf2xla/dump_graph_flags.h" -#include "tensorflow/compiler/xla/parse_flags_from_env.h" -#include "tensorflow/core/platform/types.h" -#include "tensorflow/core/util/command_line_flags.h" - -namespace tensorflow { -namespace legacy_flags { - -// Pointers to the parsed value of the flags and flag descriptors, initialized -// via flags_init. -static DumpGraphFlags* flags; -static std::vector* flag_list; -static std::once_flag flags_init; - -// Allocate *flags. Called via call_once(&flags_init,...). -static void AllocateFlags() { - flags = new DumpGraphFlags; - flags->tf_dump_graph_prefix = "/tmp/"; - flag_list = new std::vector({ - Flag("tf_dump_graph_prefix", &flags->tf_dump_graph_prefix, - "Path prefix to which graphs dumped during debugging should be " - "written."), - }); - xla::ParseFlagsFromEnv(*flag_list); -} - -// Append to *append_to flag definitions associated with the XLA bridge's -// dump_graph module. -void AppendDumpGraphFlags(std::vector* append_to) { - std::call_once(flags_init, &AllocateFlags); - append_to->insert(append_to->end(), flag_list->begin(), flag_list->end()); -} - -// Return a pointer to the DumpGraphFlags struct; -// repeated calls return the same pointer. -// This should be called only after Flags::Parse() has returned. -DumpGraphFlags* GetDumpGraphFlags() { - std::call_once(flags_init, &AllocateFlags); - return flags; -} - -} // namespace legacy_flags -} // namespace tensorflow diff --git a/tensorflow/compiler/tf2xla/dump_graph_flags.h b/tensorflow/compiler/tf2xla/dump_graph_flags.h deleted file mode 100644 index 80a3307d92..0000000000 --- a/tensorflow/compiler/tf2xla/dump_graph_flags.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#ifndef TENSORFLOW_COMPILER_TF2XLA_DUMP_GRAPH_FLAGS_H_ -#define TENSORFLOW_COMPILER_TF2XLA_DUMP_GRAPH_FLAGS_H_ - -// Legacy flags for the XLA bridge's dump_graph module. - -#include - -#include "tensorflow/core/platform/types.h" -#include "tensorflow/core/util/command_line_flags.h" - -namespace tensorflow { -namespace legacy_flags { - -// Append to *flag_list flag definitions associated with the XLA bridge's -// dump_graph module. -void AppendDumpGraphFlags(std::vector* flag_list); - -// The values of flags associated with the XLA bridge's -// dump_graph module. -typedef struct { - string tf_dump_graph_prefix; // Path prefix to which graphs dumped during - // debugging should be written. -} DumpGraphFlags; - -// Return a pointer to the DumpGraphFlags struct; -// repeated calls return the same pointer. -// This should be called only after Flags::Parse() has returned. -DumpGraphFlags* GetDumpGraphFlags(); - -} // namespace legacy_flags -} // namespace tensorflow - -#endif // TENSORFLOW_COMPILER_TF2XLA_DUMP_GRAPH_FLAGS_H_ diff --git a/tensorflow/compiler/tf2xla/functionalize_control_flow.cc b/tensorflow/compiler/tf2xla/functionalize_control_flow.cc index 9ef9f49f42..3dfd3f854c 100644 --- a/tensorflow/compiler/tf2xla/functionalize_control_flow.cc +++ b/tensorflow/compiler/tf2xla/functionalize_control_flow.cc @@ -75,6 +75,25 @@ Status FunctionalizeControlFlow(Graph* graph, return FunctionalizeControlFlow(/*lookup_library=*/nullptr, graph, library); } +Status FunctionalizeControlFlowForGraphDef(GraphDef* graph_def, + FunctionLibraryDefinition* library) { + return FunctionalizeControlFlowForGraphDef(/*lookup_library=*/nullptr, + graph_def, library); +} + +Status FunctionalizeControlFlowForGraphDef( + const FunctionLibraryDefinition* lookup_library, GraphDef* graph_def, + FunctionLibraryDefinition* library) { + FunctionDefLibrary function_lib = graph_def->library(); + Graph graph(OpRegistry::Global()); + + TF_RETURN_IF_ERROR(ConvertGraphDefToGraph({}, *graph_def, &graph)); + TF_RETURN_IF_ERROR(FunctionalizeControlFlow(lookup_library, &graph, library)); + graph.ToGraphDef(graph_def); + std::swap(*graph_def->mutable_library(), function_lib); + return Status::OK(); +} + Status FunctionalizeControlFlowForFunction( const string& func_name, const string& new_func_name, const protobuf::Map& attrs, diff --git a/tensorflow/compiler/tf2xla/functionalize_control_flow.h b/tensorflow/compiler/tf2xla/functionalize_control_flow.h index ba99205640..91d33fa405 100644 --- a/tensorflow/compiler/tf2xla/functionalize_control_flow.h +++ b/tensorflow/compiler/tf2xla/functionalize_control_flow.h @@ -33,6 +33,12 @@ Status FunctionalizeControlFlow(const FunctionLibraryDefinition* lookup_library, Graph* graph, FunctionLibraryDefinition* library); +Status FunctionalizeControlFlowForGraphDef(GraphDef* graph_def, + FunctionLibraryDefinition* library); +Status FunctionalizeControlFlowForGraphDef( + const FunctionLibraryDefinition* lookup_library, GraphDef* graph_def, + FunctionLibraryDefinition* library); + // This pass looks at the graph and all associated FunctionDefs, and turns // traditional control flow structure (Switch/Merge/etc.) into functional // control flow structure (If/While). diff --git a/tensorflow/compiler/tf2xla/functionalize_control_flow_test.cc b/tensorflow/compiler/tf2xla/functionalize_control_flow_test.cc index c3841f996f..9784985af8 100644 --- a/tensorflow/compiler/tf2xla/functionalize_control_flow_test.cc +++ b/tensorflow/compiler/tf2xla/functionalize_control_flow_test.cc @@ -95,77 +95,87 @@ TEST(FunctionalizeControlFlow, Conditional) { } FunctionLibraryDefinition library(OpRegistry::Global(), {}); + GraphDef optimized_graph_def; + graph.ToGraphDef(&optimized_graph_def); + TF_ASSERT_OK( + FunctionalizeControlFlowForGraphDef(&optimized_graph_def, &library)); TF_ASSERT_OK(FunctionalizeControlFlow(&graph, &library)); + GraphDef converted_graph_def; + graph.ToGraphDef(&converted_graph_def); + + for (const GraphDef& graph_def : {optimized_graph_def, converted_graph_def}) { + string op_name; + NameAttrList then_fn; + NameAttrList else_fn; + TF_EXPECT_OK(FindIfThenAndElse(graph_def, &op_name, &then_fn, &else_fn)); + InstantiationResultForTest else_result; + TF_EXPECT_OK( + InstantiateFunctionForTest(else_fn.name(), library, &else_result)); + + // Outer graph + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto y = ops::Placeholder(scope.WithOpName("y"), DT_INT32); + auto x = ops::Placeholder(scope.WithOpName("x"), DT_INT32); + auto less = ops::Less(scope.WithOpName("cond/Less"), y, x); + auto if_op = ops::If(scope.WithOpName(op_name), less, + std::initializer_list{less, y, x}, {DT_INT32}, + then_fn, else_fn); + auto id = ops::Identity(scope.WithOpName("cond/Merge"), if_op.output[0]); + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + TF_EXPECT_GRAPH_EQ(expected, graph_def); + } - GraphDef graph_def; - graph.ToGraphDef(&graph_def); - string op_name; - NameAttrList then_fn; - NameAttrList else_fn; - TF_EXPECT_OK(FindIfThenAndElse(graph_def, &op_name, &then_fn, &else_fn)); - InstantiationResultForTest else_result; - TF_EXPECT_OK( - InstantiateFunctionForTest(else_fn.name(), library, &else_result)); - - // Outer graph - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto y = ops::Placeholder(scope.WithOpName("y"), DT_INT32); - auto x = ops::Placeholder(scope.WithOpName("x"), DT_INT32); - auto less = ops::Less(scope.WithOpName("cond/Less"), y, x); - auto if_op = ops::If(scope.WithOpName(op_name), less, - std::initializer_list{less, y, x}, {DT_INT32}, - then_fn, else_fn); - auto id = ops::Identity(scope.WithOpName("cond/Merge"), if_op.output[0]); - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - TF_EXPECT_GRAPH_EQ(expected, graph_def); - } - - // then body. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg_0 = ops::_Arg(scope.WithOpName("_arg0"), DT_BOOL, 0); - auto arg_1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); - auto arg_2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); - auto identity = ops::Identity(scope.WithOpName("cond/Identity"), arg_0); - auto cond = ops::Const( - scope.WithOpName("cond").WithControlDependencies(identity), 17); - auto mul = ops::Mul(scope.WithOpName("cond/Mul"), arg_1, cond); - auto retval0 = ops::_Retval(scope.WithOpName("_retval0_RetVal"), mul, 0); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - InstantiationResultForTest result; - TF_EXPECT_OK(InstantiateFunctionForTest(then_fn.name(), library, &result)); - - EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); - EXPECT_EQ((DataTypeVector{DT_BOOL, DT_INT32, DT_INT32}), result.arg_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); - } + // then body. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg_0 = ops::_Arg(scope.WithOpName("_arg0"), DT_BOOL, 0); + auto arg_1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); + auto arg_2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); + auto identity = ops::Identity(scope.WithOpName("cond/Identity"), arg_0); + auto cond = ops::Const( + scope.WithOpName("cond").WithControlDependencies(identity), 17); + auto mul = ops::Mul(scope.WithOpName("cond/Mul"), arg_1, cond); + auto retval0 = ops::_Retval(scope.WithOpName("_retval0_RetVal"), mul, 0); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(then_fn.name(), library, &result)); + + EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); + EXPECT_EQ((DataTypeVector{DT_BOOL, DT_INT32, DT_INT32}), + result.arg_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } - // else body. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg_0 = ops::_Arg(scope.WithOpName("_arg0"), DT_BOOL, 0); - auto arg_1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); - auto arg_2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); - auto identity = ops::Identity(scope.WithOpName("cond/Identity_1"), arg_0); - auto cond_1 = ops::Const( - scope.WithOpName("cond_1").WithControlDependencies(identity), 23); - auto add = ops::Add(scope.WithOpName("cond/false/add"), arg_2, cond_1); - auto retval0 = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add, 0); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - InstantiationResultForTest result; - TF_EXPECT_OK(InstantiateFunctionForTest(else_fn.name(), library, &result)); - - EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); - EXPECT_EQ((DataTypeVector{DT_BOOL, DT_INT32, DT_INT32}), result.arg_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); + // else body. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg_0 = ops::_Arg(scope.WithOpName("_arg0"), DT_BOOL, 0); + auto arg_1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); + auto arg_2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); + auto identity = ops::Identity(scope.WithOpName("cond/Identity_1"), arg_0); + auto cond_1 = ops::Const( + scope.WithOpName("cond_1").WithControlDependencies(identity), 23); + auto add = ops::Add(scope.WithOpName("cond/false/add"), arg_2, cond_1); + auto retval0 = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add, 0); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(else_fn.name(), library, &result)); + + EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); + EXPECT_EQ((DataTypeVector{DT_BOOL, DT_INT32, DT_INT32}), + result.arg_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } } } @@ -239,75 +249,77 @@ TEST(FunctionalizeControlFlow, OneLoopVar) { } FunctionLibraryDefinition library(OpRegistry::Global(), {}); + GraphDef optimized_graph_def; + graph.ToGraphDef(&optimized_graph_def); + TF_ASSERT_OK( + FunctionalizeControlFlowForGraphDef(&optimized_graph_def, &library)); TF_ASSERT_OK(FunctionalizeControlFlow(&graph, &library)); + GraphDef converted_graph_def; + graph.ToGraphDef(&converted_graph_def); + + for (const GraphDef& graph_def : {optimized_graph_def, converted_graph_def}) { + NameAttrList cond_fn, body_fn; + TF_EXPECT_OK(FindWhileCondAndBody(graph_def, &cond_fn, &body_fn)); + + // Outer graph + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto source = ops::Placeholder(scope.WithOpName("source"), DT_INT32); + auto while_op = + ops::While(scope.WithOpName("while/LoopCond"), + std::initializer_list{source}, cond_fn, body_fn); + auto sink = ops::Identity(scope.WithOpName("sink"), while_op[0]); + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + TF_EXPECT_GRAPH_EQ(expected, graph_def); + } - GraphDef graph_def; - graph.ToGraphDef(&graph_def); - - NameAttrList cond_fn, body_fn; - TF_EXPECT_OK(FindWhileCondAndBody(graph_def, &cond_fn, &body_fn)); - - // Outer graph - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto source = ops::Placeholder(scope.WithOpName("source"), DT_INT32); - auto while_op = - ops::While(scope.WithOpName("while/LoopCond"), - std::initializer_list{source}, cond_fn, body_fn); - auto sink = ops::Identity(scope.WithOpName("sink"), while_op[0]); - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - TF_EXPECT_GRAPH_EQ(expected, graph_def); - } - - // Condition graph - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto ten = ops::Const( - scope.WithOpName("while/Less/y").WithControlDependencies(arg), 10); - auto less = ops::Less(scope.WithOpName("while/Less"), arg, ten); - auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), less, 0); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - InstantiationResultForTest result; - TF_EXPECT_OK(InstantiateFunctionForTest(cond_fn.name(), library, &result)); - - EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); - EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); - } - - // Body graph. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto identity = ops::Identity(scope.WithOpName("while/Identity"), arg); - auto one = ops::Const( - scope.WithOpName("while/add/y").WithControlDependencies(identity), 1); - auto add = ops::Add(scope.WithOpName("while/add"), identity, one); - auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add, 0); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - InstantiationResultForTest result; - TF_EXPECT_OK(InstantiateFunctionForTest(body_fn.name(), library, &result)); + // Condition graph + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto ten = ops::Const( + scope.WithOpName("while/Less/y").WithControlDependencies(arg), 10); + auto less = ops::Less(scope.WithOpName("while/Less"), arg, ten); + auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), less, 0); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(cond_fn.name(), library, &result)); + + EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); + EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } - EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); - EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); + // Body graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto identity = ops::Identity(scope.WithOpName("while/Identity"), arg); + auto one = ops::Const( + scope.WithOpName("while/add/y").WithControlDependencies(identity), 1); + auto add = ops::Add(scope.WithOpName("while/add"), identity, one); + auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add, 0); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(body_fn.name(), library, &result)); + + EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); + EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } } } -// @function.Defun(noinline=True) -// def increment_fn(x): -// return [x + 1] -// Define the above function, and add it to the given graph. It's used as the -// while loop body in NoinlineLoopBody test. -Status AddNoinlineFunctionToGraph(const string& node_name, Graph* graph) { +FunctionDef GetNoinlineFunctionDef() { FunctionDef fdef = FunctionDefHelper::Create( "increment_fn", {"x:int32"}, {"add:int32"}, {}, { @@ -316,8 +328,17 @@ Status AddNoinlineFunctionToGraph(const string& node_name, Graph* graph) { }, {{"add", "add_0:z:0"}}); (*fdef.mutable_attr())["_noinline"].set_b(true); + return fdef; +} + +// @function.Defun(noinline=True) +// def increment_fn(x): +// return [x + 1] +// Define the above function, and add it to the given graph. It's used as the +// while loop body in NoinlineLoopBody test. +Status AddNoinlineFunctionToGraph(const string& node_name, Graph* graph) { FunctionDefLibrary fdef_lib; - *(fdef_lib.add_function()) = fdef; + *(fdef_lib.add_function()) = GetNoinlineFunctionDef(); TF_RETURN_IF_ERROR(graph->AddFunctionLibrary(fdef_lib)); NodeDef increment_fn; increment_fn.set_name(node_name); @@ -376,55 +397,88 @@ TEST(FunctionalizeControlFlow, NoinlineLoopBody) { FunctionLibraryDefinition lookup_lib(graph.flib_def()); FunctionLibraryDefinition library(OpRegistry::Global(), {}); // Function increment_fn will be copied from lookup_lib to library. - TF_ASSERT_OK(FunctionalizeControlFlow(&lookup_lib, &graph, &library)); + GraphDef optimized_graph_def; + graph.ToGraphDef(&optimized_graph_def); - GraphDef graph_def; - graph.ToGraphDef(&graph_def); + *(optimized_graph_def.mutable_library()->add_function()) = + GetNoinlineFunctionDef(); - NameAttrList cond_fn, body_fn; - TF_ASSERT_OK(FindWhileCondAndBody(graph_def, &cond_fn, &body_fn)); + TF_ASSERT_OK(FunctionalizeControlFlowForGraphDef( + &lookup_lib, &optimized_graph_def, &library)); + TF_ASSERT_OK(FunctionalizeControlFlow(&lookup_lib, &graph, &library)); + GraphDef converted_graph_def; + graph.ToGraphDef(&converted_graph_def); + + for (const GraphDef& graph_def : {optimized_graph_def, converted_graph_def}) { + NameAttrList cond_fn, body_fn; + TF_ASSERT_OK(FindWhileCondAndBody(graph_def, &cond_fn, &body_fn)); + + // Outer graph + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto source = ops::Placeholder(scope.WithOpName("source"), DT_INT32); + auto while_op = + ops::While(scope.WithOpName("while/LoopCond"), + std::initializer_list{source}, cond_fn, body_fn); + GraphDef expected; + TF_ASSERT_OK(scope.ToGraphDef(&expected)); + TF_EXPECT_GRAPH_EQ(expected, graph_def); + } - // Outer graph - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto source = ops::Placeholder(scope.WithOpName("source"), DT_INT32); - auto while_op = - ops::While(scope.WithOpName("while/LoopCond"), - std::initializer_list{source}, cond_fn, body_fn); - GraphDef expected; - TF_ASSERT_OK(scope.ToGraphDef(&expected)); - TF_EXPECT_GRAPH_EQ(expected, graph_def); + // Body graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + TF_ASSERT_OK( + AddNoinlineFunctionToGraph(noinline_node_name, scope.graph())); + auto identity = ops::Identity(scope.WithOpName("while/Identity"), arg); + NodeDef retval; + retval.set_name("_retval0_RetVal"); + retval.set_op(FunctionLibraryDefinition::kRetOp); + *retval.add_input() = noinline_node_name; + (*retval.mutable_attr())["T"].set_type(DT_INT32); + (*retval.mutable_attr())["index"].set_i(0); + Status status; + scope.graph()->AddNode(retval, &status); + TF_ASSERT_OK(status); + + GraphDef expected; + TF_ASSERT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + // Verify that increment_fn has been copied to library. + TF_EXPECT_OK( + InstantiateFunctionForTest(body_fn.name(), library, &result)); + + EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); + EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); + // Ignore the function library when comparing the graphs. + expected.clear_library(); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } } +} - // Body graph. +TEST(FunctionalizeControlFlow, MissingFunctionDefInLibrary) { + const string& noinline_node_name = "while/increment_fn"; + Graph graph(OpRegistry::Global()); { Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto source = ops::Placeholder(scope.WithOpName("source"), DT_INT32); + auto identity = ops::Identity(scope.WithOpName("while/Identity"), source); TF_ASSERT_OK(AddNoinlineFunctionToGraph(noinline_node_name, scope.graph())); - auto identity = ops::Identity(scope.WithOpName("while/Identity"), arg); - NodeDef retval; - retval.set_name("_retval0_RetVal"); - retval.set_op(FunctionLibraryDefinition::kRetOp); - *retval.add_input() = noinline_node_name; - (*retval.mutable_attr())["T"].set_type(DT_INT32); - (*retval.mutable_attr())["index"].set_i(0); - Status status; - scope.graph()->AddNode(retval, &status); - TF_ASSERT_OK(status); - - GraphDef expected; - TF_ASSERT_OK(scope.ToGraphDef(&expected)); + TF_ASSERT_OK(scope.ToGraph(&graph)); + } - InstantiationResultForTest result; - // Verify that increment_fn has been copied to library. - TF_EXPECT_OK(InstantiateFunctionForTest(body_fn.name(), library, &result)); + FunctionLibraryDefinition lookup_lib(graph.flib_def()); + FunctionLibraryDefinition library(OpRegistry::Global(), {}); + GraphDef graph_def; + graph.ToGraphDef(&graph_def); + graph_def.clear_library(); - EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); - EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); - // Ignore the function library when comparing the graphs. - expected.clear_library(); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); - } + Status status = + FunctionalizeControlFlowForGraphDef(&lookup_lib, &graph_def, &library); + EXPECT_EQ(tensorflow::error::NOT_FOUND, status.code()); } // Tests functionalizing OneLoopVar where the loop value is not used post the @@ -467,65 +521,72 @@ TEST(FunctionalizeControlFlow, OneLoopVarWithoutExit) { } FunctionLibraryDefinition library(OpRegistry::Global(), {}); + GraphDef optimized_graph_def; + graph.ToGraphDef(&optimized_graph_def); + TF_ASSERT_OK( + FunctionalizeControlFlowForGraphDef(&optimized_graph_def, &library)); TF_ASSERT_OK(FunctionalizeControlFlow(&graph, &library)); + GraphDef converted_graph_def; + graph.ToGraphDef(&converted_graph_def); + + for (const GraphDef& graph_def : {optimized_graph_def, converted_graph_def}) { + NameAttrList cond_fn, body_fn; + TF_EXPECT_OK(FindWhileCondAndBody(graph_def, &cond_fn, &body_fn)); + + // Outer graph + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto source = ops::Placeholder(scope.WithOpName("source"), DT_INT32); + auto while_op = + ops::While(scope.WithOpName("while/LoopCond"), + std::initializer_list{source}, cond_fn, body_fn); + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + TF_EXPECT_GRAPH_EQ(expected, graph_def); + } - GraphDef graph_def; - graph.ToGraphDef(&graph_def); - - NameAttrList cond_fn, body_fn; - TF_EXPECT_OK(FindWhileCondAndBody(graph_def, &cond_fn, &body_fn)); - - // Outer graph - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto source = ops::Placeholder(scope.WithOpName("source"), DT_INT32); - auto while_op = - ops::While(scope.WithOpName("while/LoopCond"), - std::initializer_list{source}, cond_fn, body_fn); - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - TF_EXPECT_GRAPH_EQ(expected, graph_def); - } - - // Condition graph - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto ten = ops::Const( - scope.WithOpName("while/Less/y").WithControlDependencies(arg), 10); - auto less = ops::Less(scope.WithOpName("while/Less"), arg, ten); - auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), less, 0); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - InstantiationResultForTest result; - TF_EXPECT_OK(InstantiateFunctionForTest(cond_fn.name(), library, &result)); - - EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); - EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); - } - - // Body graph. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto identity = ops::Identity(scope.WithOpName("while/Identity"), arg); - auto one = ops::Const( - scope.WithOpName("while/add/y").WithControlDependencies(identity), 1); - auto add = ops::Add(scope.WithOpName("while/add"), identity, one); - auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add, 0); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - InstantiationResultForTest result; - TF_EXPECT_OK(InstantiateFunctionForTest(body_fn.name(), library, &result)); + // Condition graph + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto ten = ops::Const( + scope.WithOpName("while/Less/y").WithControlDependencies(arg), 10); + auto less = ops::Less(scope.WithOpName("while/Less"), arg, ten); + auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), less, 0); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(cond_fn.name(), library, &result)); + + EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); + EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } - EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); - EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); + // Body graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto identity = ops::Identity(scope.WithOpName("while/Identity"), arg); + auto one = ops::Const( + scope.WithOpName("while/add/y").WithControlDependencies(identity), 1); + auto add = ops::Add(scope.WithOpName("while/add"), identity, one); + auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add, 0); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(body_fn.name(), library, &result)); + + EXPECT_EQ(DataTypeVector{DT_INT32}, result.arg_types); + EXPECT_EQ(DataTypeVector{DT_INT32}, result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } } } @@ -608,86 +669,95 @@ TEST(FunctionalizeControlFlow, TwoLoopVars) { } FunctionLibraryDefinition library(OpRegistry::Global(), {}); + GraphDef optimized_graph_def; + graph.ToGraphDef(&optimized_graph_def); + TF_ASSERT_OK( + FunctionalizeControlFlowForGraphDef(&optimized_graph_def, &library)); TF_ASSERT_OK(FunctionalizeControlFlow(&graph, &library)); + GraphDef converted_graph_def; + graph.ToGraphDef(&converted_graph_def); + + for (const GraphDef& graph_def : {optimized_graph_def, converted_graph_def}) { + NameAttrList cond_fn, body_fn; + TF_EXPECT_OK(FindWhileCondAndBody(graph_def, &cond_fn, &body_fn)); + + // Outer graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto x = ops::Placeholder(scope.WithOpName("Placeholder/x"), DT_INT32); + auto y = ops::Placeholder(scope.WithOpName("Placeholder/y"), DT_INT32); + auto while_op = + ops::While(scope.WithOpName("while/LoopCond"), + std::initializer_list{x, y}, cond_fn, body_fn); + auto sink_x = ops::Identity(scope.WithOpName("sink_x"), while_op[0]); + auto sink_y = ops::Identity(scope.WithOpName("sink_y"), while_op[1]); + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + TF_EXPECT_GRAPH_EQ(expected, graph_def); + } - GraphDef graph_def; - graph.ToGraphDef(&graph_def); - - NameAttrList cond_fn, body_fn; - TF_EXPECT_OK(FindWhileCondAndBody(graph_def, &cond_fn, &body_fn)); - - // Outer graph. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto x = ops::Placeholder(scope.WithOpName("Placeholder/x"), DT_INT32); - auto y = ops::Placeholder(scope.WithOpName("Placeholder/y"), DT_INT32); - auto while_op = - ops::While(scope.WithOpName("while/LoopCond"), - std::initializer_list{x, y}, cond_fn, body_fn); - auto sink_x = ops::Identity(scope.WithOpName("sink_x"), while_op[0]); - auto sink_y = ops::Identity(scope.WithOpName("sink_y"), while_op[1]); - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - TF_EXPECT_GRAPH_EQ(expected, graph_def); - } - - // Condition graph. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); - auto three = ops::Const(scope.WithOpName("while/cond/three") + // Condition graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); + auto three = ops::Const(scope.WithOpName("while/cond/three") + .WithControlDependencies(arg0.output), + 3); + auto cond_add = + ops::Add(scope.WithOpName("while/cond/Add"), arg0.output, three); + auto ten = ops::Const(scope.WithOpName("while/cond/ten") .WithControlDependencies(arg0.output), - 3); - auto cond_add = - ops::Add(scope.WithOpName("while/cond/Add"), arg0.output, three); - auto ten = ops::Const( - scope.WithOpName("while/cond/ten").WithControlDependencies(arg0.output), - 10); - auto less = ops::Less(scope.WithOpName("while/cond/Less"), cond_add, ten); - auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), less, 0); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - InstantiationResultForTest result; - TF_EXPECT_OK(InstantiateFunctionForTest(cond_fn.name(), library, &result)); - - EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32}), result.arg_types); - EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); - } - - // Body graph. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); - - auto identity_x = ops::Identity(scope.WithOpName("while/Identity/x"), arg0); - auto identity_y = ops::Identity(scope.WithOpName("while/Identity/y"), arg1); - - auto one = ops::Const( - scope.WithOpName("while/add/one").WithControlDependencies(identity_x), - 1); - auto two = ops::Const( - scope.WithOpName("while/mul/two").WithControlDependencies(identity_x), - 2); + 10); + auto less = ops::Less(scope.WithOpName("while/cond/Less"), cond_add, ten); + auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), less, 0); - auto add = ops::Add(scope.WithOpName("while/add"), identity_x, one); - auto mul = ops::Add(scope.WithOpName("while/mul"), identity_y, two); - auto retval0 = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add, 0); - auto retval1 = ops::_Retval(scope.WithOpName("_retval1_RetVal"), mul, 1); + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(cond_fn.name(), library, &result)); - InstantiationResultForTest result; - TF_EXPECT_OK(InstantiateFunctionForTest(body_fn.name(), library, &result)); + EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32}), result.arg_types); + EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } - EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32}), result.arg_types); - EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32}), result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); + // Body graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); + + auto identity_x = + ops::Identity(scope.WithOpName("while/Identity/x"), arg0); + auto identity_y = + ops::Identity(scope.WithOpName("while/Identity/y"), arg1); + + auto one = ops::Const( + scope.WithOpName("while/add/one").WithControlDependencies(identity_x), + 1); + auto two = ops::Const( + scope.WithOpName("while/mul/two").WithControlDependencies(identity_x), + 2); + + auto add = ops::Add(scope.WithOpName("while/add"), identity_x, one); + auto mul = ops::Add(scope.WithOpName("while/mul"), identity_y, two); + auto retval0 = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add, 0); + auto retval1 = ops::_Retval(scope.WithOpName("_retval1_RetVal"), mul, 1); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(body_fn.name(), library, &result)); + + EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32}), result.arg_types); + EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32}), result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } } } @@ -841,177 +911,192 @@ TEST(FunctionalizeControlFlow, Complex) { } FunctionLibraryDefinition library(OpRegistry::Global(), {}); + GraphDef optimized_graph_def; + graph.ToGraphDef(&optimized_graph_def); + TF_ASSERT_OK( + FunctionalizeControlFlowForGraphDef(&optimized_graph_def, &library)); TF_ASSERT_OK(FunctionalizeControlFlow(&graph, &library)); + GraphDef converted_graph_def; + graph.ToGraphDef(&converted_graph_def); - GraphDef graph_def; - graph.ToGraphDef(&graph_def); - - NameAttrList outer_cond_fn, outer_body_fn; - TF_EXPECT_OK(FindWhileCondAndBody(graph_def, &outer_cond_fn, &outer_body_fn)); - - // Outer graph. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto x = ops::Placeholder(scope.WithOpName("x"), DT_INT32); - auto three = ops::Const(scope.WithOpName("three"), 3); - auto y = ops::Add(scope.WithOpName("y"), x, three); - - auto var = ops::VarHandleOp(scope.WithOpName("Variable"), DT_INT32, - TensorShape({})); - - auto zero = ops::Const(scope.WithOpName("outer/Const"), 0); - - auto while_op = ops::While(scope.WithOpName("outer/LoopCond"), - std::initializer_list{zero, y, x, var}, - outer_cond_fn, outer_body_fn); - auto sink = ops::Identity(scope.WithOpName("sink"), while_op[0]); - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - TF_EXPECT_GRAPH_EQ(expected, graph_def); - } - - // Outer condition graph. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); - auto arg2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); - auto arg3 = ops::_Arg(scope.WithOpName("_arg3"), DT_RESOURCE, 3); - - auto ten = ops::Const( - scope.WithOpName("outer/Less/y").WithControlDependencies(arg0.output), - 10); - auto less = ops::Less(scope.WithOpName("outer/Less_i"), arg0, ten); - auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), less, 0); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - InstantiationResultForTest result; - TF_EXPECT_OK( - InstantiateFunctionForTest(outer_cond_fn.name(), library, &result)); - - EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32, DT_RESOURCE}), - result.arg_types); - EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); - } - - // Outer body graph. - NameAttrList inner_cond_fn, inner_body_fn; - { - InstantiationResultForTest result; - TF_EXPECT_OK( - InstantiateFunctionForTest(outer_body_fn.name(), library, &result)); - - // Find the inner condition and body names. - TF_EXPECT_OK( - FindWhileCondAndBody(result.gdef, &inner_cond_fn, &inner_body_fn)); - - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); - auto arg2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); - auto arg3 = ops::_Arg(scope.WithOpName("_arg3"), DT_RESOURCE, 3); - - auto identity_i = ops::Identity(scope.WithOpName("outer/Identity"), arg0); - auto one_j = ops::Const( - scope.WithOpName("outer/j").WithControlDependencies(identity_i), 1); - auto while_op = - ops::While(scope.WithOpName("outer/LoopCond_1"), - std::initializer_list{one_j, arg1, arg2, arg3}, - inner_cond_fn, inner_body_fn); - - auto one_outer = ops::Const( - scope.WithOpName("outer/add/y").WithControlDependencies(identity_i), 1); - auto add_i = - ops::Add(scope.WithOpName("outer/add") - .WithControlDependencies(absl::Span{ - while_op[0].op(), while_op[1].op()}), - identity_i, one_outer); - - auto retval0 = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add_i, 0); - auto retval1 = ops::_Retval(scope.WithOpName("_retval1_RetVal"), arg1, 1); - auto retval2 = ops::_Retval(scope.WithOpName("_retval2_RetVal"), arg2, 2); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32, DT_RESOURCE}), - result.arg_types); - EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32}), result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); - } - - // Inner condition graph. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); - auto arg2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); - auto arg3 = ops::_Arg(scope.WithOpName("_arg3"), DT_RESOURCE, 3); - - auto five = ops::Const( - scope.WithOpName("outer/inner/Five").WithControlDependencies(arg0), 5); - auto less_j = ops::Less(scope.WithOpName("outer/inner/Less_j"), arg0, five); - auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), less_j, 0); - - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); - - InstantiationResultForTest result; + for (const GraphDef& graph_def : {optimized_graph_def, converted_graph_def}) { + NameAttrList outer_cond_fn, outer_body_fn; TF_EXPECT_OK( - InstantiateFunctionForTest(inner_cond_fn.name(), library, &result)); - - EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32, DT_RESOURCE}), - result.arg_types); - EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); - } - - // Inner body graph. - { - Scope scope = Scope::NewRootScope().ExitOnError(); - auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); - auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); - auto arg2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); - auto arg3 = ops::_Arg(scope.WithOpName("_arg3"), DT_RESOURCE, 3); - - auto identity_j = - ops::Identity(scope.WithOpName("outer/inner/Identity_j"), arg0); - auto identity_k = - ops::Identity(scope.WithOpName("outer/inner/Identity_k"), arg1); - - auto mul_jk = - ops::Mul(scope.WithOpName("outer/inner/mul"), identity_j, identity_k); - auto add_jkx = ops::Add(scope.WithOpName("outer/inner/add"), mul_jk, arg2); - auto assign = ops::AssignAddVariableOp( - scope.WithOpName("outer/inner/assign_add"), arg3, add_jkx); - - auto one = ops::Const( - scope.WithOpName("outer/inner/One") - .WithControlDependencies( - absl::Span{assign.operation}), - 1); - auto add_j = - ops::Add(scope.WithOpName("outer/inner/add_j"), identity_j, one); + FindWhileCondAndBody(graph_def, &outer_cond_fn, &outer_body_fn)); + + // Outer graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto x = ops::Placeholder(scope.WithOpName("x"), DT_INT32); + auto three = ops::Const(scope.WithOpName("three"), 3); + auto y = ops::Add(scope.WithOpName("y"), x, three); + + auto var = ops::VarHandleOp(scope.WithOpName("Variable"), DT_INT32, + TensorShape({})); + + auto zero = ops::Const(scope.WithOpName("outer/Const"), 0); + + auto while_op = ops::While(scope.WithOpName("outer/LoopCond"), + std::initializer_list{zero, y, x, var}, + outer_cond_fn, outer_body_fn); + auto sink = ops::Identity(scope.WithOpName("sink"), while_op[0]); + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + TF_EXPECT_GRAPH_EQ(expected, graph_def); + } - auto retval0 = ops::_Retval(scope.WithOpName("_retval0_RetVal"), add_j, 0); - auto retval1 = - ops::_Retval(scope.WithOpName("_retval1_RetVal"), identity_k, 1); - auto retval2 = ops::_Retval(scope.WithOpName("_retval2_RetVal"), arg2, 2); + // Outer condition graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); + auto arg2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); + auto arg3 = ops::_Arg(scope.WithOpName("_arg3"), DT_RESOURCE, 3); + + auto ten = ops::Const( + scope.WithOpName("outer/Less/y").WithControlDependencies(arg0.output), + 10); + auto less = ops::Less(scope.WithOpName("outer/Less_i"), arg0, ten); + auto retval = ops::_Retval(scope.WithOpName("_retval0_RetVal"), less, 0); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(outer_cond_fn.name(), library, &result)); + + EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32, DT_RESOURCE}), + result.arg_types); + EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } - GraphDef expected; - TF_EXPECT_OK(scope.ToGraphDef(&expected)); + // Outer body graph. + NameAttrList inner_cond_fn, inner_body_fn; + { + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(outer_body_fn.name(), library, &result)); + + // Find the inner condition and body names. + TF_EXPECT_OK( + FindWhileCondAndBody(result.gdef, &inner_cond_fn, &inner_body_fn)); + + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); + auto arg2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); + auto arg3 = ops::_Arg(scope.WithOpName("_arg3"), DT_RESOURCE, 3); + + auto identity_i = ops::Identity(scope.WithOpName("outer/Identity"), arg0); + auto one_j = ops::Const( + scope.WithOpName("outer/j").WithControlDependencies(identity_i), 1); + auto while_op = + ops::While(scope.WithOpName("outer/LoopCond_1"), + std::initializer_list{one_j, arg1, arg2, arg3}, + inner_cond_fn, inner_body_fn); + + auto one_outer = ops::Const( + scope.WithOpName("outer/add/y").WithControlDependencies(identity_i), + 1); + auto add_i = + ops::Add(scope.WithOpName("outer/add") + .WithControlDependencies(absl::Span{ + while_op[0].op(), while_op[1].op()}), + identity_i, one_outer); + + auto retval0 = + ops::_Retval(scope.WithOpName("_retval0_RetVal"), add_i, 0); + auto retval1 = ops::_Retval(scope.WithOpName("_retval1_RetVal"), arg1, 1); + auto retval2 = ops::_Retval(scope.WithOpName("_retval2_RetVal"), arg2, 2); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32, DT_RESOURCE}), + result.arg_types); + EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32}), + result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } - InstantiationResultForTest result; - TF_EXPECT_OK( - InstantiateFunctionForTest(inner_body_fn.name(), library, &result)); + // Inner condition graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); + auto arg2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); + auto arg3 = ops::_Arg(scope.WithOpName("_arg3"), DT_RESOURCE, 3); + + auto five = ops::Const( + scope.WithOpName("outer/inner/Five").WithControlDependencies(arg0), + 5); + auto less_j = + ops::Less(scope.WithOpName("outer/inner/Less_j"), arg0, five); + auto retval = + ops::_Retval(scope.WithOpName("_retval0_RetVal"), less_j, 0); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(inner_cond_fn.name(), library, &result)); + + EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32, DT_RESOURCE}), + result.arg_types); + EXPECT_EQ(DataTypeVector{DT_BOOL}, result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } - EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32, DT_RESOURCE}), - result.arg_types); - EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32}), result.ret_types); - TF_EXPECT_GRAPH_EQ(expected, result.gdef); + // Inner body graph. + { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto arg0 = ops::_Arg(scope.WithOpName("_arg0"), DT_INT32, 0); + auto arg1 = ops::_Arg(scope.WithOpName("_arg1"), DT_INT32, 1); + auto arg2 = ops::_Arg(scope.WithOpName("_arg2"), DT_INT32, 2); + auto arg3 = ops::_Arg(scope.WithOpName("_arg3"), DT_RESOURCE, 3); + + auto identity_j = + ops::Identity(scope.WithOpName("outer/inner/Identity_j"), arg0); + auto identity_k = + ops::Identity(scope.WithOpName("outer/inner/Identity_k"), arg1); + + auto mul_jk = + ops::Mul(scope.WithOpName("outer/inner/mul"), identity_j, identity_k); + auto add_jkx = + ops::Add(scope.WithOpName("outer/inner/add"), mul_jk, arg2); + auto assign = ops::AssignAddVariableOp( + scope.WithOpName("outer/inner/assign_add"), arg3, add_jkx); + + auto one = ops::Const( + scope.WithOpName("outer/inner/One") + .WithControlDependencies( + absl::Span{assign.operation}), + 1); + auto add_j = + ops::Add(scope.WithOpName("outer/inner/add_j"), identity_j, one); + + auto retval0 = + ops::_Retval(scope.WithOpName("_retval0_RetVal"), add_j, 0); + auto retval1 = + ops::_Retval(scope.WithOpName("_retval1_RetVal"), identity_k, 1); + auto retval2 = ops::_Retval(scope.WithOpName("_retval2_RetVal"), arg2, 2); + + GraphDef expected; + TF_EXPECT_OK(scope.ToGraphDef(&expected)); + + InstantiationResultForTest result; + TF_EXPECT_OK( + InstantiateFunctionForTest(inner_body_fn.name(), library, &result)); + + EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32, DT_RESOURCE}), + result.arg_types); + EXPECT_EQ((DataTypeVector{DT_INT32, DT_INT32, DT_INT32}), + result.ret_types); + TF_EXPECT_GRAPH_EQ(expected, result.gdef); + } } } diff --git a/tensorflow/compiler/tf2xla/kernels/BUILD b/tensorflow/compiler/tf2xla/kernels/BUILD index d85b4f5ae0..fa51a72aea 100644 --- a/tensorflow/compiler/tf2xla/kernels/BUILD +++ b/tensorflow/compiler/tf2xla/kernels/BUILD @@ -121,7 +121,6 @@ tf_kernel_library( ":while_op", "//tensorflow/compiler/tf2xla:common", "//tensorflow/compiler/tf2xla:xla_compiler", - "//tensorflow/compiler/tf2xla/lib:batch_dot", "//tensorflow/compiler/tf2xla/lib:broadcast", "//tensorflow/compiler/tf2xla/lib:cholesky", "//tensorflow/compiler/tf2xla/lib:qr", @@ -144,7 +143,7 @@ tf_kernel_library( "//tensorflow/compiler/xla/client/lib:arithmetic", "//tensorflow/compiler/xla/client/lib:constants", "//tensorflow/compiler/xla/client/lib:math", - "//tensorflow/compiler/xla/client/lib:numeric", + "//tensorflow/compiler/xla/client/lib:matrix", "//tensorflow/compiler/xla/client/lib:pooling", "//tensorflow/compiler/xla/client/lib:prng", "//tensorflow/compiler/xla/client/lib:sorting", @@ -196,7 +195,6 @@ cc_library( "//tensorflow/compiler/xla/client:xla_builder", "//tensorflow/compiler/xla/client/lib:arithmetic", "//tensorflow/compiler/xla/client/lib:constants", - "//tensorflow/compiler/xla/client/lib:numeric", "//tensorflow/core:framework", "//tensorflow/core:lib", "//tensorflow/core:protos_all_cc", @@ -216,7 +214,6 @@ cc_library( "//tensorflow/compiler/xla/client:xla_builder", "//tensorflow/compiler/xla/client/lib:arithmetic", "//tensorflow/compiler/xla/client/lib:constants", - "//tensorflow/compiler/xla/client/lib:numeric", "//tensorflow/core:framework", "//tensorflow/core/kernels:bounds_check", "//tensorflow/core/kernels:conv_ops", diff --git a/tensorflow/compiler/tf2xla/kernels/arg_op.cc b/tensorflow/compiler/tf2xla/kernels/arg_op.cc index 2db2514397..795ea09831 100644 --- a/tensorflow/compiler/tf2xla/kernels/arg_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/arg_op.cc @@ -50,7 +50,7 @@ class XlaArgOp : public XlaOpKernel { return; } - const XlaExpression& arg = XlaContext::Get(ctx).args()[index_]; + const XlaExpression& arg = ctx->xla_context()->args()[index_]; OP_REQUIRES(ctx, arg.kind() != XlaExpression::Kind::kInvalid, errors::InvalidArgument("Invalid/missing argument expression")); ctx->SetOutputExpression(0, arg); diff --git a/tensorflow/compiler/tf2xla/kernels/batch_matmul_op.cc b/tensorflow/compiler/tf2xla/kernels/batch_matmul_op.cc index 4cfe946b2e..1b254e328a 100644 --- a/tensorflow/compiler/tf2xla/kernels/batch_matmul_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/batch_matmul_op.cc @@ -13,9 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "tensorflow/compiler/tf2xla/lib/batch_dot.h" +#include "tensorflow/compiler/tf2xla/lib/util.h" #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" +#include "tensorflow/compiler/xla/client/lib/math.h" +#include "tensorflow/compiler/xla/client/lib/matrix.h" namespace tensorflow { namespace { @@ -28,9 +30,11 @@ class BatchMatMulOp : public XlaOpKernel { } void Compile(XlaOpKernelContext* ctx) override { - auto result = BatchDot(ctx->Input(0), ctx->Input(1), - /*transpose_x=*/adj_x_, /*transpose_y=*/adj_y_, - /*conjugate_x=*/adj_x_, /*conjugate_y=*/adj_y_); + auto result = + xla::BatchDot(MaybeTransposeInMinorDims( + MaybeConjugate(ctx->Input(0), adj_x_), adj_x_), + MaybeTransposeInMinorDims( + MaybeConjugate(ctx->Input(1), adj_y_), adj_y_)); ctx->SetOutput(0, result); } diff --git a/tensorflow/compiler/tf2xla/kernels/batch_norm_op.cc b/tensorflow/compiler/tf2xla/kernels/batch_norm_op.cc index a267c0c72f..0e2f335f33 100644 --- a/tensorflow/compiler/tf2xla/kernels/batch_norm_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/batch_norm_op.cc @@ -115,9 +115,9 @@ class FusedBatchNormGradOp : public XlaOpKernel { // operators. For now, cast everything to the statistics type (which // may be more precise than the input type). auto grad_backprop = - XlaHelpers::ConvertElementType(b, ctx->Input(0), scale_dtype); + XlaHelpers::ConvertElementType(ctx->Input(0), scale_dtype); auto activations = - XlaHelpers::ConvertElementType(b, ctx->Input(1), scale_dtype); + XlaHelpers::ConvertElementType(ctx->Input(1), scale_dtype); auto scale = ctx->Input(2); auto mean = ctx->Input(3); auto var = ctx->Input(4); @@ -151,11 +151,11 @@ class FusedBatchNormGradOp : public XlaOpKernel { const DataType accumulation_type = XlaHelpers::SumAccumulationType(scale_dtype); auto converted = - XlaHelpers::ConvertElementType(b, grad_backprop, accumulation_type); + XlaHelpers::ConvertElementType(grad_backprop, accumulation_type); auto reduce = xla::Reduce(converted, XlaHelpers::Zero(b, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type), reduction_dims); - offset_backprop = XlaHelpers::ConvertElementType(b, reduce, scale_dtype); + offset_backprop = XlaHelpers::ConvertElementType(reduce, scale_dtype); // scratch1 = rsqrt(pop_var + epsilon) auto neg_half = XlaHelpers::FloatLiteral(b, scale_dtype, -0.5); @@ -165,19 +165,18 @@ class FusedBatchNormGradOp : public XlaOpKernel { // scratch2 = sum(y_backprop * (x - mean)) auto mul = xla::Mul(grad_backprop, xla::Sub(activations, mean, {feature_index})); - converted = XlaHelpers::ConvertElementType(b, mul, accumulation_type); + converted = XlaHelpers::ConvertElementType(mul, accumulation_type); reduce = xla::Reduce(converted, XlaHelpers::Zero(b, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type), reduction_dims); - auto scratch2 = XlaHelpers::ConvertElementType(b, reduce, scale_dtype); + auto scratch2 = XlaHelpers::ConvertElementType(reduce, scale_dtype); x_backprop = xla::Mul(grad_backprop, xla::Mul(scratch1, scale), {feature_index}); scale_backprop = xla::Mul(scratch1, scratch2); } - ctx->SetOutput(0, - XlaHelpers::ConvertElementType(b, x_backprop, input_dtype)); + ctx->SetOutput(0, XlaHelpers::ConvertElementType(x_backprop, input_dtype)); ctx->SetOutput(1, scale_backprop); ctx->SetOutput(2, offset_backprop); ctx->SetConstantOutput(3, Tensor()); diff --git a/tensorflow/compiler/tf2xla/kernels/bias_ops.cc b/tensorflow/compiler/tf2xla/kernels/bias_ops.cc index 41f540506b..e7f369b761 100644 --- a/tensorflow/compiler/tf2xla/kernels/bias_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/bias_ops.cc @@ -107,11 +107,11 @@ class BiasAddGradOp : public XlaOpKernel { const DataType accumulation_type = XlaHelpers::SumAccumulationType(input_type(0)); auto converted = - XlaHelpers::ConvertElementType(b, ctx->Input(0), accumulation_type); + XlaHelpers::ConvertElementType(ctx->Input(0), accumulation_type); auto reduce = xla::Reduce(converted, XlaHelpers::Zero(b, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type), reduce_dims); - ctx->SetOutput(0, XlaHelpers::ConvertElementType(b, reduce, input_type(0))); + ctx->SetOutput(0, XlaHelpers::ConvertElementType(reduce, input_type(0))); } private: diff --git a/tensorflow/compiler/tf2xla/kernels/binary_ops.cc b/tensorflow/compiler/tf2xla/kernels/binary_ops.cc index 47e517a657..5e9280c1fe 100644 --- a/tensorflow/compiler/tf2xla/kernels/binary_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/binary_ops.cc @@ -43,6 +43,9 @@ namespace { const std::vector& extend_dimensions) override { \ xla::XlaBuilder* b = ctx->builder(); \ (void)b; \ + (void)lhs_shape; \ + (void)rhs_shape; \ + (void)extend_dimensions; \ return HLO; \ } \ }; \ @@ -103,23 +106,23 @@ static xla::XlaOp FloorDivImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x, XLA_MAKE_BINARY(FloorDiv, FloorDivImpl(b, input_type(0), lhs, rhs, broadcast_helper)); -static xla::XlaOp XlogyImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x, - xla::XlaOp y, const BCast& broadcast_helper) { +xla::XlaOp XlogyImpl(xla::XlaOp x, xla::XlaOp y, + const BCast& broadcast_helper) { std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper); - auto zero = XlaHelpers::Zero(b, dtype); + auto zero = xla::ZerosLike(x); auto is_zero = xla::Eq(x, zero); return xla::Select(is_zero, zero, xla::Mul(x, xla::Log(y))); } -XLA_MAKE_BINARY(Xlogy, XlogyImpl(b, input_type(0), lhs, rhs, broadcast_helper)); +XLA_MAKE_BINARY(Xlogy, XlogyImpl(lhs, rhs, broadcast_helper)); -static xla::XlaOp XdivyImpl(xla::XlaBuilder* b, DataType dtype, xla::XlaOp x, - xla::XlaOp y, const BCast& broadcast_helper) { +xla::XlaOp XdivyImpl(xla::XlaOp x, xla::XlaOp y, + const BCast& broadcast_helper) { std::tie(x, y) = XlaBinaryOp::Broadcast(x, y, broadcast_helper); - auto zero = XlaHelpers::Zero(b, dtype); + auto zero = xla::ZerosLike(x); auto is_zero = xla::Eq(x, zero); return xla::Select(is_zero, zero, xla::Div(x, y)); } -XLA_MAKE_BINARY(Xdivy, XdivyImpl(b, input_type(0), lhs, rhs, broadcast_helper)); +XLA_MAKE_BINARY(Xdivy, XdivyImpl(lhs, rhs, broadcast_helper)); // Implementation of FloorMod. Pseudo-code: // T trunc_mod = std::fmod(x, y); diff --git a/tensorflow/compiler/tf2xla/kernels/categorical_op.cc b/tensorflow/compiler/tf2xla/kernels/categorical_op.cc index ad85940920..7199b9b6fe 100644 --- a/tensorflow/compiler/tf2xla/kernels/categorical_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/categorical_op.cc @@ -21,10 +21,13 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/client/lib/arithmetic.h" +#include "tensorflow/compiler/xla/client/lib/prng.h" #include "tensorflow/compiler/xla/client/xla_builder.h" +#include "tensorflow/compiler/xla/xla_data.pb.h" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/framework/tensor.h" #include "tensorflow/core/framework/tensor_shape.h" +#include "tensorflow/core/framework/types.pb.h" namespace tensorflow { namespace { @@ -57,11 +60,9 @@ class CategoricalOp : public XlaOpKernel { const int64 batch_size = logits_shape.dim_size(0); const int64 num_classes = logits_shape.dim_size(1); - xla::XlaBuilder* builder = ctx->builder(); - xla::Shape uniform_shape; int class_dimension; - if (num_samples > 1) { + if (num_samples != 1) { std::array uniform_shape_array = { {batch_size, num_samples, num_classes}}; xla::PrimitiveType uniform_xla_type; @@ -83,16 +84,16 @@ class CategoricalOp : public XlaOpKernel { xla::ShapeUtil::MakeShape(uniform_xla_type, uniform_shape_array); class_dimension = 1; } - xla::XlaOp uniforms = - xla::RngUniform(XlaHelpers::Zero(builder, input_type(0)), - XlaHelpers::One(builder, input_type(0)), uniform_shape); + xla::PrimitiveType type; + OP_REQUIRES_OK(ctx, DataTypeToPrimitiveType(input_type(0), &type)); + xla::XlaOp log_uniforms = GetLogUniforms(uniform_shape, type, ctx); // Use Gumbel softmax trick to generate categorical samples. // See: // https://hips.seas.harvard.edu/blog/2013/04/06/the-gumbel-max-trick-for-discrete-distributions/ // TODO(b/68769470): Switch to using a cumulative sum approach. auto softmax_entries = - xla::Sub(logits, xla::Log(-xla::Log(uniforms)), + xla::Sub(logits, log_uniforms, /*broadcast_dimensions=*/{0, class_dimension}); xla::PrimitiveType xla_output_type; @@ -107,6 +108,16 @@ class CategoricalOp : public XlaOpKernel { ctx->SetOutput(0, argmax); } + virtual xla::XlaOp GetLogUniforms(xla::Shape uniform_shape, + xla::PrimitiveType type, + XlaOpKernelContext* ctx) { + xla::XlaBuilder* builder = ctx->builder(); + auto uniforms = + xla::RngUniform(XlaHelpers::Zero(builder, input_type(0)), + XlaHelpers::One(builder, input_type(0)), uniform_shape); + return xla::Log(-xla::Log(uniforms)); + } + private: TF_DISALLOW_COPY_AND_ASSIGN(CategoricalOp); }; @@ -115,5 +126,48 @@ class CategoricalOp : public XlaOpKernel { REGISTER_XLA_OP(Name("Multinomial").CompileTimeConstantInput("num_samples"), CategoricalOp); +class StatelessCategoricalOp : public CategoricalOp { + public: + explicit StatelessCategoricalOp(OpKernelConstruction* ctx) + : CategoricalOp(ctx) { + OP_REQUIRES_OK(ctx, ctx->GetAttr("T", &dtype_)); + } + + xla::XlaOp GetLogUniforms(xla::Shape uniform_shape, xla::PrimitiveType type, + XlaOpKernelContext* ctx) override { + xla::XlaOp seed = ctx->Input(2); + auto seed0 = xla::Reshape(xla::Slice(seed, {0}, {1}, {1}), {}); + auto seed1 = xla::Reshape(xla::Slice(seed, {1}, {2}, {1}), {}); + + xla::XlaBuilder* builder = ctx->builder(); + if (uniform_shape.element_type() == xla::BF16) { + uniform_shape.set_element_type(xla::F32); + } + auto uniforms = xla::StatelessRngUniform( + {seed0, seed1}, uniform_shape, XlaHelpers::Zero(builder, DT_FLOAT), + XlaHelpers::One(builder, DT_FLOAT)); + return xla::ConvertElementType(xla::Log(-xla::Log(uniforms)), type); + } + + void Compile(XlaOpKernelContext* ctx) override { + TensorShape seed_shape = ctx->InputShape(2); + OP_REQUIRES(ctx, seed_shape.dims() == 1 && seed_shape.dim_size(0) == 2, + errors::InvalidArgument("seed must have shape [2], not ", + seed_shape.DebugString())); + CategoricalOp::Compile(ctx); + } + + private: + DataType dtype_; + + TF_DISALLOW_COPY_AND_ASSIGN(StatelessCategoricalOp); +}; + +REGISTER_XLA_OP(Name("StatelessMultinomial") + .CompileTimeConstantInput("num_samples") + .TypeConstraint("T", {DT_FLOAT, DT_BFLOAT16}) + .TypeConstraint("Tseed", DT_INT32), + StatelessCategoricalOp); + } // anonymous namespace } // namespace tensorflow diff --git a/tensorflow/compiler/tf2xla/kernels/conv_op_helpers.cc b/tensorflow/compiler/tf2xla/kernels/conv_op_helpers.cc index c9a1be4940..641fefafb3 100644 --- a/tensorflow/compiler/tf2xla/kernels/conv_op_helpers.cc +++ b/tensorflow/compiler/tf2xla/kernels/conv_op_helpers.cc @@ -24,7 +24,6 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/client/lib/arithmetic.h" #include "tensorflow/compiler/xla/client/lib/constants.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal_util.h" #include "tensorflow/core/framework/node_def_util.h" @@ -65,60 +64,63 @@ xla::Shape ExpandedFilterShapeForDepthwiseConvolution(const xla::Shape& shape) { // 0 0 1 1 0 0 0 0 1 1 0 0 // 0 0 0 0 1 1 0 0 0 0 1 1 // -// The first step is to create a one tensor, A, that is [3] -// 0 1 2 +// The first step is to create a iota A with iota_dimension = 2 +// 0 0 0 0 0 0 0 0 0 0 0 0 +// 1 1 1 1 1 1 1 1 1 1 1 1 +// 2 2 2 2 2 2 2 2 2 2 2 2 // -// and another tensor, B, that is [3 * 2] -// 0 1 2 3 4 5 +// 0 0 0 0 0 0 0 0 0 0 0 0 +// 1 1 1 1 1 1 1 1 1 1 1 1 +// 2 2 2 2 2 2 2 2 2 2 2 2 // -// and divide B it by 2 to get -// 0 0 1 1 2 2 +// and another iota B with iota_dimension = 3 +// 0 1 2 3 4 5 0 1 2 3 4 5 +// 0 1 2 3 4 5 0 1 2 3 4 5 +// 0 1 2 3 4 5 0 1 2 3 4 5 // -// then we broadcast the B to [2, 2, 3, 3 * 2] -// 0 0 1 1 2 2 0 0 1 1 2 2 -// 0 0 1 1 2 2 0 0 1 1 2 2 -// 0 0 1 1 2 2 0 0 1 1 2 2 +// 0 1 2 3 4 5 0 1 2 3 4 5 +// 0 1 2 3 4 5 0 1 2 3 4 5 +// 0 1 2 3 4 5 0 1 2 3 4 5 // -// 0 0 1 1 2 2 0 0 1 1 2 2 -// 0 0 1 1 2 2 0 0 1 1 2 2 -// 0 0 1 1 2 2 0 0 1 1 2 2 +// and divide B by 2 to get +// 0 0 1 1 2 2 0 0 1 1 2 2 +// 0 0 1 1 2 2 0 0 1 1 2 2 +// 0 0 1 1 2 2 0 0 1 1 2 2 // -// Finally compare A and broadcasted B in dimension 2 amd return the result at -// the beginning of the comment. +// 0 0 1 1 2 2 0 0 1 1 2 2 +// 0 0 1 1 2 2 0 0 1 1 2 2 +// 0 0 1 1 2 2 0 0 1 1 2 2 +// +// Finally compare A and B and return the result at the beginning of the +// comment. xla::XlaOp CreateExpandedFilterMask(const xla::Shape& filter_shape, xla::XlaBuilder* builder) { xla::Shape expanded_filter_shape = ExpandedFilterShapeForDepthwiseConvolution(filter_shape); int64 depthwise_multiplier = filter_shape.dimensions(filter_shape.dimensions_size() - 1); - int64 input_feature = - filter_shape.dimensions(filter_shape.dimensions_size() - 2); - - // Create a M sized linspace and an M*N sized linspace that will be - // broadcasted into perpendicular dimensions and compared. - xla::XlaOp input_feature_iota = xla::Iota(builder, xla::S32, input_feature); - xla::XlaOp expanded_feature_iota = - xla::Iota(builder, xla::S32, input_feature * depthwise_multiplier); - // Divide the M*N sized linspace by the depthwise_multiplier to create - // [0 0 1 1 2 2] in the example in the function comment. + // Create two iotas with the shape of the expanded filter, one of them with + // the iota dimension chosen as the feature dimension, and the other a iota + // with the iota dimension chosen as the expanded output feature dimension. + std::vector iota_dimensions(expanded_filter_shape.dimensions().begin(), + expanded_filter_shape.dimensions().end()); + xla::Shape iota_shape = xla::ShapeUtil::MakeShape(xla::S32, iota_dimensions); + xla::XlaOp input_feature_iota = xla::Iota( + builder, iota_shape, /*iota_dimension=*/iota_dimensions.size() - 2); + xla::XlaOp expanded_feature_iota = xla::Iota( + builder, iota_shape, /*iota_dimension=*/iota_dimensions.size() - 1); + + // Divide 'expanded_feature_iota' by the depthwise_multiplier to create + // [0 0 1 1 2 2] ... in the example in the function comment. expanded_feature_iota = xla::Div(expanded_feature_iota, XlaHelpers::IntegerLiteral(builder, DataType::DT_INT32, depthwise_multiplier)); - // Broadcast the N*M linspace to [H, W, ..., M, M*N]. - std::vector expanded_feature_broadcast_dims( - expanded_filter_shape.dimensions().begin(), - expanded_filter_shape.dimensions().end()); - expanded_feature_broadcast_dims.pop_back(); - auto broadcasted_expanded_feature_iota = - xla::Broadcast(expanded_feature_iota, expanded_feature_broadcast_dims); - - // Compare the broadcasted linspace to the input feature linspace in the - // input feature dimension to create a diagonal predicate. - return xla::Eq(broadcasted_expanded_feature_iota, input_feature_iota, - {expanded_filter_shape.dimensions_size() - 2}); + // Compare 'input_feature_iota' with 'expanded_feature_iota' to create a + // diagonal predicate. + return xla::Eq(expanded_feature_iota, input_feature_iota); } // Reshapes a filter of shape [H, W, ..., M, N] to [H, W, ..., 1, M*N]. Used to diff --git a/tensorflow/compiler/tf2xla/kernels/conv_ops.cc b/tensorflow/compiler/tf2xla/kernels/conv_ops.cc index d820528a43..eafdba876a 100644 --- a/tensorflow/compiler/tf2xla/kernels/conv_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/conv_ops.cc @@ -22,7 +22,7 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/client/lib/constants.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" +#include "tensorflow/compiler/xla/client/lib/matrix.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal_util.h" #include "tensorflow/core/framework/node_def_util.h" diff --git a/tensorflow/compiler/tf2xla/kernels/diag_op.cc b/tensorflow/compiler/tf2xla/kernels/diag_op.cc index 49c12fc232..ee79cbc70d 100644 --- a/tensorflow/compiler/tf2xla/kernels/diag_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/diag_op.cc @@ -19,7 +19,7 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/client/lib/constants.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" +#include "tensorflow/compiler/xla/client/lib/matrix.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/util.h" #include "tensorflow/core/framework/op_kernel.h" diff --git a/tensorflow/compiler/tf2xla/kernels/dynamic_stitch_op.cc b/tensorflow/compiler/tf2xla/kernels/dynamic_stitch_op.cc index b2f6ef43fa..6e6ba21daf 100644 --- a/tensorflow/compiler/tf2xla/kernels/dynamic_stitch_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/dynamic_stitch_op.cc @@ -113,8 +113,20 @@ class DynamicStitchOp : public XlaOpKernel { } } int number_of_indices = max_index + 1; - OP_REQUIRES(ctx, number_of_indices > 0, - errors::InvalidArgument("no indices supplied")); + int64 result_rank = 1 + data0_shape.dims() - indices0_shape.dims(); + if (number_of_indices == 0) { + std::vector result_shape(result_rank); + for (int d = indices0_shape.dims(); d < data0_shape.dims(); d++) { + result_shape[d - indices0_shape.dims() + 1] = data0_shape.dim_size(d); + } + xla::PrimitiveType element_type = + ctx->input_xla_type(ctx->num_inputs() - 1); + xla::Literal empty_literal = xla::Literal::CreateFromShape( + xla::ShapeUtil::MakeShape(element_type, result_shape)); + ctx->SetOutput(0, xla::ConstantLiteral(ctx->builder(), empty_literal)); + return; + } + // Construct the reverse mapping, for each index, of which slice of which // input it comes from. std::vector src_input_vector(number_of_indices); @@ -157,12 +169,9 @@ class DynamicStitchOp : public XlaOpKernel { // Set up the vectors for slicing: the first dimension will vary // slice by slice, and the rest take the full common extra shape. - std::vector slice_start(1 + data0_shape.dims() - - indices0_shape.dims()); - std::vector slice_limit(1 + data0_shape.dims() - - indices0_shape.dims()); - std::vector stride(1 + data0_shape.dims() - indices0_shape.dims(), - 1); + std::vector slice_start(result_rank); + std::vector slice_limit(result_rank); + std::vector stride(result_rank, 1); for (int d = indices0_shape.dims(); d < data0_shape.dims(); d++) { slice_limit[1 + d - indices0_shape.dims()] = data0_shape.dim_size(d); } diff --git a/tensorflow/compiler/tf2xla/kernels/extract_image_patches_op.cc b/tensorflow/compiler/tf2xla/kernels/extract_image_patches_op.cc index c68b0bfd79..29687c7b82 100644 --- a/tensorflow/compiler/tf2xla/kernels/extract_image_patches_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/extract_image_patches_op.cc @@ -17,7 +17,6 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_helpers.h" #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/core/util/tensor_format.h" diff --git a/tensorflow/compiler/tf2xla/kernels/fake_quantize_ops.cc b/tensorflow/compiler/tf2xla/kernels/fake_quantize_ops.cc index cdba6680de..142be030f7 100644 --- a/tensorflow/compiler/tf2xla/kernels/fake_quantize_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/fake_quantize_ops.cc @@ -260,19 +260,19 @@ class FakeQuantWithMinMaxVarsGradOp : public XlaOpKernel { xla::XlaOp below_min = xla::Lt(input, nudged_input_min); xla::XlaOp select1 = xla::Select(below_min, gradient, zeroes); xla::XlaOp reduce1 = xla::ReduceAll( - XlaHelpers::ConvertElementType(b, select1, accumulation_type), + XlaHelpers::ConvertElementType(select1, accumulation_type), XlaHelpers::Zero(b, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type)); - xla::XlaOp output1 = XlaHelpers::ConvertElementType(b, reduce1, data_type); + xla::XlaOp output1 = XlaHelpers::ConvertElementType(reduce1, data_type); ctx->SetOutput(1, output1); xla::XlaOp above_max = xla::Gt(input, nudged_input_max); xla::XlaOp select2 = xla::Select(above_max, gradient, zeroes); xla::XlaOp reduce2 = xla::ReduceAll( - XlaHelpers::ConvertElementType(b, select2, accumulation_type), + XlaHelpers::ConvertElementType(select2, accumulation_type), XlaHelpers::Zero(b, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type)); - xla::XlaOp output2 = XlaHelpers::ConvertElementType(b, reduce2, data_type); + xla::XlaOp output2 = XlaHelpers::ConvertElementType(reduce2, data_type); ctx->SetOutput(2, output2); } diff --git a/tensorflow/compiler/tf2xla/kernels/fft_ops.cc b/tensorflow/compiler/tf2xla/kernels/fft_ops.cc index 9b06357d9b..6df8b5367d 100644 --- a/tensorflow/compiler/tf2xla/kernels/fft_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/fft_ops.cc @@ -20,6 +20,7 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal_util.h" +#include "tensorflow/compiler/xla/util.h" #include "tensorflow/core/framework/numeric_op.h" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/framework/tensor.h" @@ -50,11 +51,36 @@ class GenericFftOp : public XlaOpKernel { errors::InvalidArgument("input must be at least 1 dimensional")); std::vector fft_length; + xla::XlaOp input = ctx->Input(0); if (fft_type_ == FftType::RFFT || fft_type_ == FftType::IRFFT) { OP_REQUIRES_OK(ctx, ctx->ConstantInputAsIntVector(1, &fft_length)); OP_REQUIRES(ctx, fft_length.size() == fft_rank_, errors::InvalidArgument("fft_length must be length ", fft_rank_, " vector")); + + // Zero pad or truncate the axes we're doing FFT on. + absl::InlinedVector slice_sizes = input_shape.dim_sizes(); + std::vector> padding_sizes(slice_sizes.size()); + std::vector expected_sizes = fft_length; + // IRFFT wants the innermost axis to be n / 2 + 1. + if (fft_type_ == FftType::IRFFT) { + expected_sizes[fft_rank_ - 1] = fft_length[fft_rank_ - 1] / 2 + 1; + } + for (int i = 0; i < fft_rank_; i++) { + int index = input_shape.dims() - fft_rank_ + i; + if (input_shape.dim_size(index) > expected_sizes[i]) { + slice_sizes[index] = expected_sizes[i]; + } else { + padding_sizes[index].second = + expected_sizes[i] - input_shape.dim_size(index); + } + } + + std::vector start_indices(input_shape.dims(), 0); + std::vector strides(input_shape.dims(), 1); + input = xla::Pad(xla::Slice(input, start_indices, slice_sizes, strides), + XlaHelpers::Zero(ctx->builder(), ctx->input_type(0)), + xla::MakeEdgePaddingConfig(padding_sizes)); } else { // Innermost axis provides the FFT length. for (int i = 0; i < fft_rank_; i++) { @@ -63,7 +89,7 @@ class GenericFftOp : public XlaOpKernel { } } - xla::XlaOp fft = xla::Fft(ctx->Input(0), fft_type_, fft_length); + xla::XlaOp fft = xla::Fft(input, fft_type_, fft_length); ctx->SetOutput(0, fft); } diff --git a/tensorflow/compiler/tf2xla/kernels/if_op.cc b/tensorflow/compiler/tf2xla/kernels/if_op.cc index 56da50f140..b5e0839125 100644 --- a/tensorflow/compiler/tf2xla/kernels/if_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/if_op.cc @@ -72,7 +72,7 @@ void XlaIfOp::Compile(XlaOpKernelContext* ctx) { arg.shape = resource->shape(); OP_REQUIRES(ctx, arg.initialized, errors::Unimplemented("Uninitialized arguments: ", arg.name)); - arg.tensor_array_size = resource->tensor_array_size(); + arg.max_array_size = resource->max_array_size(); for (const auto& gradient : resource->tensor_array_gradients()) { arg.tensor_array_gradients.insert(gradient.first); } diff --git a/tensorflow/compiler/tf2xla/kernels/image_ops.cc b/tensorflow/compiler/tf2xla/kernels/image_ops.cc index b49b2516d8..e9bb0a77e9 100644 --- a/tensorflow/compiler/tf2xla/kernels/image_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/image_ops.cc @@ -191,12 +191,11 @@ class AdjustContrastOpV2 : public XlaOpKernel { DataType type = context->input_type(0); const DataType accumulation_type = XlaHelpers::SumAccumulationType(type); - auto converted = - XlaHelpers::ConvertElementType(b, input, accumulation_type); + auto converted = XlaHelpers::ConvertElementType(input, accumulation_type); auto reduce = xla::Reduce(converted, XlaHelpers::Zero(b, accumulation_type), *context->GetOrCreateAdd(accumulation_type), {height_dim, width_dim}); - auto output = XlaHelpers::ConvertElementType(b, reduce, type); + auto output = XlaHelpers::ConvertElementType(reduce, type); output = xla::Div(output, XlaHelpers::FloatLiteral(b, type, height * width)); diff --git a/tensorflow/compiler/tf2xla/kernels/image_resize_ops.cc b/tensorflow/compiler/tf2xla/kernels/image_resize_ops.cc index 0c7ca602bf..5a10c52ba8 100644 --- a/tensorflow/compiler/tf2xla/kernels/image_resize_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/image_resize_ops.cc @@ -19,7 +19,6 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/array4d.h" #include "tensorflow/compiler/xla/client/lib/constants.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/core/framework/kernel_def_builder.h" #include "tensorflow/core/framework/register_types.h" diff --git a/tensorflow/compiler/tf2xla/kernels/index_ops_cpu.cc b/tensorflow/compiler/tf2xla/kernels/index_ops_cpu.cc index e310db2162..e2c05b648b 100644 --- a/tensorflow/compiler/tf2xla/kernels/index_ops_cpu.cc +++ b/tensorflow/compiler/tf2xla/kernels/index_ops_cpu.cc @@ -30,7 +30,9 @@ limitations under the License. namespace tensorflow { namespace { -// The logic below uses a custom-call to implement argmax. +// The logic below uses a custom-call to implement argmax when possible. When +// custom-call is not allowed or input shapes are not supported, this kernel +// falls back to using XLA HLO native ArgMax. // // Also see b/29507024 for first-class XLA support for indexing ops. class ArgMaxCustomCallOp : public XlaOpKernel { @@ -50,27 +52,40 @@ class ArgMaxCustomCallOp : public XlaOpKernel { // overhead, when compiling ahead-of-time. int64 dim; OP_REQUIRES_OK(ctx, ctx->ConstantInputAsIntScalar(1, &dim)); - OP_REQUIRES(ctx, dim >= 0, errors::InvalidArgument("dim must be >= 0")); - OP_REQUIRES( - ctx, dim < input_shape.dims(), - errors::InvalidArgument("dim must be < input rank (", - input_shape.dims(), "), but got: ", dim)); - const int64 dim_size = input_shape.dim_size(dim); - OP_REQUIRES(ctx, dim_size > 0, + + const int input_dims = input_shape.dims(); + const int axis = dim < 0 ? dim + input_dims : dim; + OP_REQUIRES(ctx, axis >= 0 && axis < input_dims, + errors::InvalidArgument("Expected dimension in the range [", + -input_dims, ", ", input_dims, + "), but got ", dim)); + + const int64 axis_size = input_shape.dim_size(axis); + OP_REQUIRES(ctx, axis_size > 0, errors::InvalidArgument( "Reduction axis ", dim, " is empty in shape: ", input_shape.DebugString())); - // The output shape is the input shape contracted along dim. + const DataType dtype = output_type(0); + xla::PrimitiveType output_type; + OP_REQUIRES_OK(ctx, DataTypeToPrimitiveType(dtype, &output_type)); + + // Fall back to XLA ArgMax HLO when CustomCall is not allowed or when input + // shape isn't supported. + if (!ctx->compiler()->options().allow_cpu_custom_calls || + (input_dims != 1 && input_dims != 2)) { + xla::XlaOp output = XlaHelpers::ArgMax(ctx->Input(0), output_type, axis); + ctx->SetOutput(0, output); + return; + } + + xla::XlaOp output; + // The output shape is the input shape contracted along axis. TensorShape output_shape; for (int d = 0; d < input_shape.dims() - 1; ++d) { - output_shape.AddDim(input_shape.dim_size((d < dim) ? d : d + 1)); + output_shape.AddDim(input_shape.dim_size((d < axis) ? d : d + 1)); } - // For now we use a custom-call, only for the 1d and 2d cases. - OP_REQUIRES(ctx, XlaContext::Get(ctx).allow_cpu_custom_calls(), - errors::InvalidArgument( - "ArgMax implementation requires a CustomCall on CPU")); xla::XlaBuilder& b = *ctx->builder(); // XLA passes to the function, so it is not included here. @@ -84,7 +99,7 @@ class ArgMaxCustomCallOp : public XlaOpKernel { args.push_back(xla::ConstantLiteral( &b, xla::LiteralUtil::CreateR1(output_shape.dim_sizes()))); args.push_back( - xla::ConstantLiteral(&b, xla::LiteralUtil::CreateR0(dim))); + xla::ConstantLiteral(&b, xla::LiteralUtil::CreateR0(axis))); } // The argmax function expects row-major layout. @@ -101,24 +116,15 @@ class ArgMaxCustomCallOp : public XlaOpKernel { } // Tell XLA to call the custom code, defined in - // index_ops_kernel_argmax_float_1d.cc. - xla::XlaOp output; - switch (input_shape.dims()) { - case 1: - output = xla::CustomCallWithLayout(&b, "argmax_float_1d_xla_impl", args, - xla_shape, arg_shapes); - break; - case 2: - output = xla::CustomCallWithLayout(&b, "argmax_float_2d_xla_impl", args, - xla_shape, arg_shapes); - break; - default: - OP_REQUIRES(ctx, false, - errors::Unimplemented( - "Argmax is only implemented for 1d and 2d tensors" - ", but got shape: ", - input_shape.DebugString())); + // index_ops_kernel_argmax_float_{1, 2}d.cc. + if (input_dims == 1) { + output = xla::CustomCallWithLayout(&b, "argmax_float_1d_xla_impl", args, + xla_shape, arg_shapes); + } else { + output = xla::CustomCallWithLayout(&b, "argmax_float_2d_xla_impl", args, + xla_shape, arg_shapes); } + output = xla::ConvertElementType(output, output_type); ctx->SetOutput(0, output); } diff --git a/tensorflow/compiler/tf2xla/kernels/l2loss_op.cc b/tensorflow/compiler/tf2xla/kernels/l2loss_op.cc index f028e361bc..93f029731c 100644 --- a/tensorflow/compiler/tf2xla/kernels/l2loss_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/l2loss_op.cc @@ -37,12 +37,11 @@ class L2LossOp : public XlaOpKernel { // output = sum(t ** 2) / 2 const DataType accumulation_type = XlaHelpers::SumAccumulationType(dtype); - auto t = - XlaHelpers::ConvertElementType(b, ctx->Input(0), accumulation_type); + auto t = XlaHelpers::ConvertElementType(ctx->Input(0), accumulation_type); auto square = xla::Mul(t, t); auto reduce = xla::Reduce(square, XlaHelpers::Zero(b, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type), dims); - auto deconverted = XlaHelpers::ConvertElementType(b, reduce, dtype); + auto deconverted = XlaHelpers::ConvertElementType(reduce, dtype); auto two = XlaHelpers::IntegerLiteral(b, dtype, 2); ctx->SetOutput(0, xla::Div(deconverted, two)); } diff --git a/tensorflow/compiler/tf2xla/kernels/lrn_ops.cc b/tensorflow/compiler/tf2xla/kernels/lrn_ops.cc index 87ee2d3aed..987901d82b 100644 --- a/tensorflow/compiler/tf2xla/kernels/lrn_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/lrn_ops.cc @@ -49,16 +49,14 @@ class LRNOp : public XlaOpKernel { // We use a window of depth_radius_ * 2 + 1, to account for the current // element and a depth_radius_ on either side. auto accumulation_type = XlaHelpers::SumAccumulationType(input_type(0)); - auto converted = - XlaHelpers::ConvertElementType(builder, input, accumulation_type); + auto converted = XlaHelpers::ConvertElementType(input, accumulation_type); auto squared = xla::Mul(converted, converted); auto reduce = xla::ReduceWindow( squared, XlaHelpers::Zero(builder, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type), /* window_dimensions = */ {1, 1, 1, depth_radius_ * 2 + 1}, /* window_strides = */ {1, 1, 1, 1}, xla::Padding::kSame); - auto sqr_sum = - XlaHelpers::ConvertElementType(builder, reduce, input_type(0)); + auto sqr_sum = XlaHelpers::ConvertElementType(reduce, input_type(0)); auto scale = xla::Pow( xla::Add(xla::ConstantR0(builder, bias_), @@ -138,15 +136,14 @@ class LRNGradOp : public XlaOpKernel { auto accumulation_type = XlaHelpers::SumAccumulationType(input_type(0)); auto converted = - XlaHelpers::ConvertElementType(builder, in_image, accumulation_type); + XlaHelpers::ConvertElementType(in_image, accumulation_type); auto squared = xla::Mul(converted, converted); auto reduce = xla::ReduceWindow( squared, XlaHelpers::Zero(builder, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type), /* window_dimensions = */ {1, 1, 1, depth_radius_ * 2 + 1}, /* window_strides = */ {1, 1, 1, 1}, xla::Padding::kSame); - auto sqr_sum = - XlaHelpers::ConvertElementType(builder, reduce, input_type(0)); + auto sqr_sum = XlaHelpers::ConvertElementType(reduce, input_type(0)); auto norm = xla::Add(xla::ConstantR0(builder, bias_), @@ -157,15 +154,13 @@ class LRNGradOp : public XlaOpKernel { xla::Div(out_image, norm)), in_grads); - auto converted_dy = - XlaHelpers::ConvertElementType(builder, dy, accumulation_type); + auto converted_dy = XlaHelpers::ConvertElementType(dy, accumulation_type); auto dy_reduce = xla::ReduceWindow( converted_dy, XlaHelpers::Zero(builder, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type), /* window_dimensions = */ {1, 1, 1, depth_radius_ * 2 + 1}, /* window_strides = */ {1, 1, 1, 1}, xla::Padding::kSame); - auto dy_reduced = - XlaHelpers::ConvertElementType(builder, dy_reduce, input_type(0)); + auto dy_reduced = XlaHelpers::ConvertElementType(dy_reduce, input_type(0)); xla::XlaOp gradients = xla::Add( xla::Mul(in_image, dy_reduced), diff --git a/tensorflow/compiler/tf2xla/kernels/matrix_band_part_op.cc b/tensorflow/compiler/tf2xla/kernels/matrix_band_part_op.cc index 8dfd7de591..2dd0a710e4 100644 --- a/tensorflow/compiler/tf2xla/kernels/matrix_band_part_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/matrix_band_part_op.cc @@ -16,8 +16,8 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_helpers.h" #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" +#include "tensorflow/compiler/xla/shape_util.h" #include "tensorflow/core/framework/tensor_shape.h" namespace tensorflow { @@ -61,11 +61,11 @@ class MatrixBandPartOp : public XlaOpKernel { // Compute 'offset', which is how many diagonals we are above/below the // diagonal. - xla::XlaOp iota_m = xla::Iota(builder, index_xla_type, m); - xla::XlaOp iota_n = xla::Iota(builder, index_xla_type, n); + xla::Shape iota_shape = xla::ShapeUtil::MakeShape(index_xla_type, {m, n}); + xla::XlaOp iota_m = xla::Iota(builder, iota_shape, /*iota_dimension=*/0); + xla::XlaOp iota_n = xla::Iota(builder, iota_shape, /*iota_dimension=*/1); - auto offset = xla::Sub(xla::Broadcast(iota_n, {m}), iota_m, - /*broadcast_dimensions=*/{0}); + auto offset = xla::Sub(iota_n, iota_m); // If num_lower or num_upper are negative, include all lower/upper // diagonals. diff --git a/tensorflow/compiler/tf2xla/kernels/matrix_set_diag_op.cc b/tensorflow/compiler/tf2xla/kernels/matrix_set_diag_op.cc index c0ca881ff8..4f980b6d14 100644 --- a/tensorflow/compiler/tf2xla/kernels/matrix_set_diag_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/matrix_set_diag_op.cc @@ -16,7 +16,6 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_helpers.h" #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" namespace tensorflow { diff --git a/tensorflow/compiler/tf2xla/kernels/permute_op.cc b/tensorflow/compiler/tf2xla/kernels/permute_op.cc index 94b51e1a58..71920bf5c1 100644 --- a/tensorflow/compiler/tf2xla/kernels/permute_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/permute_op.cc @@ -75,8 +75,7 @@ class DataFormatVecPermuteOp : public XlaOpKernel { } auto keys = xla::ConstantR1(builder, absl::Span(dst_indices)); if (input_rank == 2) { - keys = xla::BroadcastInDim( - keys, xla::ShapeUtil::MakeShape(xla::S32, {4, 2}), {0}); + keys = xla::BroadcastInDim(keys, {4, 2}, {0}); } auto sorted = xla::Sort(keys, {ctx->Input(0)}, 0); auto output = xla::GetTupleElement(sorted, 1); diff --git a/tensorflow/compiler/tf2xla/kernels/pooling_ops.cc b/tensorflow/compiler/tf2xla/kernels/pooling_ops.cc index a259da6383..06c6cc37ec 100644 --- a/tensorflow/compiler/tf2xla/kernels/pooling_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/pooling_ops.cc @@ -152,7 +152,12 @@ class MaxPoolOp : public PoolingOp { public: MaxPoolOp(OpKernelConstruction* ctx, int num_spatial_dims) : PoolingOp(ctx, /*num_spatial_dims=*/num_spatial_dims, - /*reduction_type=*/ctx->input_type(0)) {} + /*reduction_type=*/ctx->input_type(0)) { + string data_format_str; + OP_REQUIRES_OK(ctx, ctx->GetAttr("data_format", &data_format_str)); + OP_REQUIRES(ctx, FormatFromString(data_format_str, &data_format_), + errors::InvalidArgument("Invalid data format")); + } void Compile(XlaOpKernelContext* ctx) override { auto ksize_or_error = GetKernelSize(ctx); @@ -180,10 +185,6 @@ class MaxPool2DOp : public MaxPoolOp { public: explicit MaxPool2DOp(OpKernelConstruction* ctx) : MaxPoolOp(ctx, /*num_spatial_dims=*/2) { - string data_format_str; - OP_REQUIRES_OK(ctx, ctx->GetAttr("data_format", &data_format_str)); - OP_REQUIRES(ctx, FormatFromString(data_format_str, &data_format_), - errors::InvalidArgument("Invalid data format")); } }; REGISTER_XLA_OP(Name("MaxPool"), MaxPool2DOp); @@ -204,7 +205,12 @@ class AvgPoolOp : public PoolingOp { AvgPoolOp(OpKernelConstruction* ctx, int num_spatial_dims) : PoolingOp(ctx, /*num_spatial_dims=*/num_spatial_dims, /*reduction_type=*/ - XlaHelpers::SumAccumulationType(ctx->input_type(0))) {} + XlaHelpers::SumAccumulationType(ctx->input_type(0))) { + string data_format_str; + OP_REQUIRES_OK(ctx, ctx->GetAttr("data_format", &data_format_str)); + OP_REQUIRES(ctx, FormatFromString(data_format_str, &data_format_), + errors::InvalidArgument("Invalid data format")); + } void Compile(XlaOpKernelContext* ctx) override { auto ksize_or_error = GetKernelSize(ctx); @@ -241,10 +247,6 @@ class AvgPool2DOp : public AvgPoolOp { public: explicit AvgPool2DOp(OpKernelConstruction* ctx) : AvgPoolOp(ctx, /*num_spatial_dims=*/2) { - string data_format_str; - OP_REQUIRES_OK(ctx, ctx->GetAttr("data_format", &data_format_str)); - OP_REQUIRES(ctx, FormatFromString(data_format_str, &data_format_), - errors::InvalidArgument("Invalid data format")); } }; REGISTER_XLA_OP(Name("AvgPool"), AvgPool2DOp); @@ -390,6 +392,11 @@ class AvgPoolGradOp : public XlaOpKernel { OP_REQUIRES(ctx, ksize_[0] == 1 && stride_[0] == 1, errors::Unimplemented( "Pooling is not yet supported on the batch dimension.")); + + string data_format; + OP_REQUIRES_OK(ctx, ctx->GetAttr("data_format", &data_format)); + OP_REQUIRES(ctx, FormatFromString(data_format, &data_format_), + errors::InvalidArgument("Invalid data format")); } int num_dims() const { return num_spatial_dims_ + 2; } @@ -449,10 +456,6 @@ class AvgPool2DGradOp : public AvgPoolGradOp { public: explicit AvgPool2DGradOp(OpKernelConstruction* ctx) : AvgPoolGradOp(ctx, /*num_spatial_dims=*/2) { - string data_format; - OP_REQUIRES_OK(ctx, ctx->GetAttr("data_format", &data_format)); - OP_REQUIRES(ctx, FormatFromString(data_format, &data_format_), - errors::InvalidArgument("Invalid data format")); } }; REGISTER_XLA_OP( diff --git a/tensorflow/compiler/tf2xla/kernels/quantize_and_dequantize_op.cc b/tensorflow/compiler/tf2xla/kernels/quantize_and_dequantize_op.cc index 6f4ed496a1..7fe102428d 100644 --- a/tensorflow/compiler/tf2xla/kernels/quantize_and_dequantize_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/quantize_and_dequantize_op.cc @@ -19,6 +19,7 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/client/lib/arithmetic.h" #include "tensorflow/compiler/xla/client/lib/constants.h" +#include "tensorflow/compiler/xla/client/lib/math.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/client/xla_computation.h" #include "tensorflow/core/platform/macros.h" @@ -26,12 +27,26 @@ limitations under the License. namespace tensorflow { namespace { +enum QuantizerRoundMode { + // Round half up: if the fraction of y is exactly 0.5, then + // round(y) = y + 0.5 + // E.g., -5.5 gets rounded to -5, -5.4 goes to -5, + // 5.4 goes to 5, and 5.5 goes to 6. + ROUND_HALF_UP, + // Round half to even: if the fraction of y is exactly 0.5, then round(y) is + // the nearest even integer to y. + // E.g., 23.5 gets rounded to 24, 24.5 gets rounded to 24, while -23.5 becomes + // -24, and -24.5 gets rounded to 24. + ROUND_HALF_TO_EVEN, +}; + class QuantizeAndDequantizeOp : public XlaOpKernel { public: explicit QuantizeAndDequantizeOp(OpKernelConstruction* ctx) : XlaOpKernel(ctx) { OP_REQUIRES_OK(ctx, ctx->GetAttr("signed_input", &signed_input_)); OP_REQUIRES_OK(ctx, ctx->GetAttr("range_given", &range_given_)); + round_mode_ = ROUND_HALF_TO_EVEN; } void Compile(XlaOpKernelContext* ctx) override { @@ -117,8 +132,17 @@ class QuantizeAndDequantizeOp : public XlaOpKernel { // in that case they were measured from the tensor. input = Clamp(min_range, input, max_range); } - xla::XlaOp result = - Floor((input - min_range) * scale + half) * inverse_scale + min_range; + xla::XlaOp result; + switch (round_mode_) { + case ROUND_HALF_TO_EVEN: { + result = xla::RoundToEven(input * scale) * inverse_scale; + break; + } + case ROUND_HALF_UP: { + result = Floor(input * scale + half) * inverse_scale; + break; + } + } ctx->SetOutput(0, result); } @@ -126,6 +150,7 @@ class QuantizeAndDequantizeOp : public XlaOpKernel { int64 num_bits_ = -1; bool signed_input_; bool range_given_; + QuantizerRoundMode round_mode_; }; class QuantizeAndDequantizeV2Op : public QuantizeAndDequantizeOp { @@ -136,6 +161,20 @@ class QuantizeAndDequantizeV2Op : public QuantizeAndDequantizeOp { OP_REQUIRES(ctx, num_bits_ > 0 && num_bits_ < (signed_input_ ? 62 : 63), errors::InvalidArgument("num_bits is out of range: ", num_bits_, " with signed_input_ ", signed_input_)); + string round_mode_string; + OP_REQUIRES_OK(ctx, ctx->GetAttr("round_mode", &round_mode_string)); + OP_REQUIRES( + ctx, + (round_mode_string == "HALF_UP" || round_mode_string == "HALF_TO_EVEN"), + errors::InvalidArgument("Round mode string must be " + "'HALF_UP' or " + "'HALF_TO_EVEN', is '" + + round_mode_string + "'")); + if (round_mode_string == "HALF_UP") { + round_mode_ = ROUND_HALF_UP; + } else if (round_mode_string == "HALF_TO_EVEN") { + round_mode_ = ROUND_HALF_TO_EVEN; + } } }; diff --git a/tensorflow/compiler/tf2xla/kernels/random_ops.cc b/tensorflow/compiler/tf2xla/kernels/random_ops.cc index 415ce9b77f..8822e29f7e 100644 --- a/tensorflow/compiler/tf2xla/kernels/random_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/random_ops.cc @@ -26,7 +26,6 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/client/lib/arithmetic.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/framework/tensor.h" diff --git a/tensorflow/compiler/tf2xla/kernels/reduction_ops.cc b/tensorflow/compiler/tf2xla/kernels/reduction_ops.cc index 107fa62967..65e158d64f 100644 --- a/tensorflow/compiler/tf2xla/kernels/reduction_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/reduction_ops.cc @@ -113,12 +113,21 @@ class MeanOp : public XlaReductionOp { xla::Add(scalar_lhs, scalar_rhs); } - xla::XlaOp BuildFinalizer(xla::XlaBuilder* builder, - const xla::XlaOp& reduce_output, - int64 num_elements_reduced) override { - auto divisor = XlaHelpers::IntegerLiteral(builder, input_type(0), - num_elements_reduced); - return reduce_output / divisor; + xla::XlaOp BuildFinalizer( + xla::XlaBuilder* /*builder*/, const xla::XlaOp& input, + const xla::XlaOp& reduce_output, + const std::vector& dimensions_to_reduce) override { + if (dimensions_to_reduce.empty()) { + return reduce_output; + } + auto divisor = xla::GetDimensionSize(input, dimensions_to_reduce[0]); + for (int i = 1; i < dimensions_to_reduce.size(); i++) { + auto size = xla::GetDimensionSize(input, dimensions_to_reduce[i]); + divisor = xla::Mul(divisor, size); + } + divisor = xla::ConvertElementType(divisor, xla_reduction_type_); + return XlaHelpers::ConvertElementType(reduce_output / divisor, + input_type(0)); } }; diff --git a/tensorflow/compiler/tf2xla/kernels/reduction_ops.h b/tensorflow/compiler/tf2xla/kernels/reduction_ops.h index 466e79828d..af716eab79 100644 --- a/tensorflow/compiler/tf2xla/kernels/reduction_ops.h +++ b/tensorflow/compiler/tf2xla/kernels/reduction_ops.h @@ -48,13 +48,14 @@ class XlaReductionOp : public XlaOpKernel { const xla::XlaOp& scalar_rhs) = 0; // Applies a transformation to the output of the reduction. The desired - // computation should be added to 'builder'. Argument 'reduce_output' is the - // output of the reduction. 'num_elements_reduced' is the number of elements - // that contributed to the reduction. Returns the transformed reduction - // output, Defaults to returning 'reduce_output' unchanged. - virtual xla::XlaOp BuildFinalizer(xla::XlaBuilder* builder, - const xla::XlaOp& reduce_output, - int64 num_elements_reduced); + // computation should be added to 'builder'. Argument 'input' is the original + // input of the reduction; 'reduce_output' is the output of the reduction. + // Returns the transformed reduction output. Defaults to returning + // 'reduce_output' converted to the input type. + virtual xla::XlaOp BuildFinalizer( + xla::XlaBuilder* builder, const xla::XlaOp& input, + const xla::XlaOp& reduce_output, + const std::vector& dimensions_to_reduce); void Compile(XlaOpKernelContext* ctx) override; diff --git a/tensorflow/compiler/tf2xla/kernels/reduction_ops_common.cc b/tensorflow/compiler/tf2xla/kernels/reduction_ops_common.cc index 118f2798d5..2ca2a85244 100644 --- a/tensorflow/compiler/tf2xla/kernels/reduction_ops_common.cc +++ b/tensorflow/compiler/tf2xla/kernels/reduction_ops_common.cc @@ -35,12 +35,13 @@ XlaReductionOp::XlaReductionOp(OpKernelConstruction* ctx, ctx, DataTypeToPrimitiveType(reduction_type_, &xla_reduction_type_)); } -// Unless BuildFinalizer is overridden the reduction has no -// finalizer. -xla::XlaOp XlaReductionOp::BuildFinalizer(xla::XlaBuilder* builder, - const xla::XlaOp& reduce_output, - int64 num_elements_reduced) { - return reduce_output; +// The default finalizer converts the results back into the input type. This can +// be overridden. +xla::XlaOp XlaReductionOp::BuildFinalizer( + xla::XlaBuilder* /*builder*/, const xla::XlaOp& /*input*/, + const xla::XlaOp& reduce_output, + const std::vector& /*dimensions_to_reduce*/) { + return XlaHelpers::ConvertElementType(reduce_output, input_type(0)); } void XlaReductionOp::Compile(XlaOpKernelContext* ctx) { @@ -71,7 +72,6 @@ void XlaReductionOp::Compile(XlaOpKernelContext* ctx) { absl::InlinedVector bitmap(data_shape.dims(), false); std::vector xla_axes; - int64 num_elements_reduced = 1LL; for (int64 i = 0; i < axes_tensor_shape.num_elements(); ++i) { int64 index = axes[i]; OP_REQUIRES(ctx, @@ -82,7 +82,6 @@ void XlaReductionOp::Compile(XlaOpKernelContext* ctx) { index = (index + data_shape.dims()) % data_shape.dims(); bitmap[index] = true; xla_axes.push_back(index); - num_elements_reduced *= data_shape.dim_size(index); } std::vector final_shape; @@ -118,8 +117,7 @@ void XlaReductionOp::Compile(XlaOpKernelContext* ctx) { xla::XlaComputation reduction_computation = r.Build().ConsumeValueOrDie(); auto reduce = xla::Reduce(data, initial, reduction_computation, xla_axes); - auto deconverted = XlaHelpers::ConvertElementType(b, reduce, input_type(0)); - auto finalized = BuildFinalizer(b, deconverted, num_elements_reduced); + auto finalized = BuildFinalizer(b, data, reduce, xla_axes); auto result = keep_dims_ ? xla::Reshape(finalized, final_shape) : finalized; ctx->SetOutput(0, result); } diff --git a/tensorflow/compiler/tf2xla/kernels/resampler_ops.cc b/tensorflow/compiler/tf2xla/kernels/resampler_ops.cc index 847704608f..54d34a38ab 100644 --- a/tensorflow/compiler/tf2xla/kernels/resampler_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/resampler_ops.cc @@ -24,7 +24,6 @@ limitations under the License. #include "tensorflow/compiler/xla/array4d.h" #include "tensorflow/compiler/xla/client/lib/arithmetic.h" #include "tensorflow/compiler/xla/client/lib/constants.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal.h" #include "tensorflow/compiler/xla/shape_util.h" @@ -44,9 +43,6 @@ namespace { using xla::XlaOp; -// TODO(b/112295522): note that sampling from image boundary is not currently -// being handled properly. - // Calculates the bilinear weight tensor, given basis ratio (px, py) of the // sampling position: // W = [(1-px)*(1-py), px*(1-py), (1-px)*py, px*py] @@ -70,11 +66,8 @@ XlaOp BilinearWeights(XlaOpKernelContext* ctx, XlaOp ratio, std::vector last_two_dims_indices = {(broadcast_dims_size - 2), (broadcast_dims_size - 1)}; - xla::Shape broadcast_shape = - xla::ShapeUtil::MakeShape(xla_type, broadcast_dims); - auto broadcast_first_term = - xla::BroadcastInDim(first_term, broadcast_shape, last_two_dims_indices); + xla::BroadcastInDim(first_term, broadcast_dims, last_two_dims_indices); // Ratio is of the same dimension as warp, which is [batch, dim_0,... dim_n, // 2], we broadcast ratio tensor to 'broadcast_dim' by keeping the @@ -85,7 +78,7 @@ XlaOp BilinearWeights(XlaOpKernelContext* ctx, XlaOp ratio, ratio_broadcast_indices.erase(ratio_broadcast_indices.end() - 2); auto broadcast_ratio = - xla::BroadcastInDim(ratio, broadcast_shape, ratio_broadcast_indices); + xla::BroadcastInDim(ratio, broadcast_dims, ratio_broadcast_indices); auto first_term_subtract_weights = broadcast_first_term - broadcast_ratio; @@ -96,7 +89,7 @@ XlaOp BilinearWeights(XlaOpKernelContext* ctx, XlaOp ratio, sign_change = xla::ConvertElementType(sign_change, xla_type); auto broadcast_sign_change = - xla::BroadcastInDim(sign_change, broadcast_shape, last_two_dims_indices); + xla::BroadcastInDim(sign_change, broadcast_dims, last_two_dims_indices); auto flipped = first_term_subtract_weights * broadcast_sign_change; @@ -232,21 +225,19 @@ XlaOp CalculateGradData(XlaOpKernelContext* ctx, XlaOp grad_output, XlaOp ratio, std::vector weights_with_channels_dims = reshaped_weights_dims; weights_with_channels_dims.push_back(data_channels); - auto weights_with_channels_shape = - xla::ShapeUtil::MakeShape(warp_type, weights_with_channels_dims); std::vector reshaped_weights_indices(reshaped_weights_dims.size()); std::iota(reshaped_weights_indices.begin(), reshaped_weights_indices.end(), 0); // The dimension is [batch, dim_0, ..., dim_n, 2, 2, data_channel]. auto broadcast_reshaped_weights = xla::BroadcastInDim( - reshaped_weights, weights_with_channels_shape, reshaped_weights_indices); + reshaped_weights, weights_with_channels_dims, reshaped_weights_indices); std::vector grad_output_indices(warp_dims_without_last_dims.size()); std::iota(grad_output_indices.begin(), grad_output_indices.end(), 0); grad_output_indices.push_back(weights_with_channels_dims.size() - 1); XlaOp broadcast_grad_output = xla::BroadcastInDim( - grad_output, weights_with_channels_shape, grad_output_indices); + grad_output, weights_with_channels_dims, grad_output_indices); auto grad_output_multiply_weights = broadcast_grad_output * broadcast_reshaped_weights; @@ -294,13 +285,10 @@ XlaOp CalculateGradWarp(XlaOpKernelContext* ctx, XlaOp grad_output, XlaOp ratio, std::vector warp_dims_without_last_dims(warp_dims.begin(), warp_dims.end() - 1); + // With dimension [batch, dim_0, ...dim_n, 4] std::vector neighbor_broadcast_dims = warp_dims_without_last_dims; neighbor_broadcast_dims.push_back(4); - // With dimension [batch, dim_0, ...dim_n, 4] - auto neighbor_broadcast_shape = - xla::ShapeUtil::MakeShape(data_type, neighbor_broadcast_dims); - // The dimension is [batch, dim_0, ... dim_n, 4, data_channels] auto neighbors_data = Gather2by2Neighbors( ctx->builder(), data, gather_indices, data_channels, warp_shape.dims()); @@ -326,7 +314,7 @@ XlaOp CalculateGradWarp(XlaOpKernelContext* ctx, XlaOp grad_output, XlaOp ratio, xla::BroadcastInDim( xla::ConvertElementType( xla::ConstantR1(ctx->builder(), {0, 0, -1, 1}), data_type), - neighbor_broadcast_shape, {last_warp_dim}), + neighbor_broadcast_dims, {last_warp_dim}), neighbors_data, dot_dims, /*precision_config=*/nullptr); // img_cxfy - img_fxfy @@ -334,7 +322,7 @@ XlaOp CalculateGradWarp(XlaOpKernelContext* ctx, XlaOp grad_output, XlaOp ratio, xla::BroadcastInDim( xla::ConvertElementType( xla::ConstantR1(ctx->builder(), {-1, 1, 0, 0}), data_type), - neighbor_broadcast_shape, {last_warp_dim}), + neighbor_broadcast_dims, {last_warp_dim}), neighbors_data, dot_dims, /*precision_config=*/nullptr); // img_cxcy - img_cxfy @@ -342,7 +330,7 @@ XlaOp CalculateGradWarp(XlaOpKernelContext* ctx, XlaOp grad_output, XlaOp ratio, xla::BroadcastInDim( xla::ConvertElementType( xla::ConstantR1(ctx->builder(), {0, -1, 0, 1}), data_type), - neighbor_broadcast_shape, {last_warp_dim}), + neighbor_broadcast_dims, {last_warp_dim}), neighbors_data, dot_dims, /*precision_config=*/nullptr); // img_fxcy - img_fxfy @@ -350,7 +338,7 @@ XlaOp CalculateGradWarp(XlaOpKernelContext* ctx, XlaOp grad_output, XlaOp ratio, xla::BroadcastInDim( xla::ConvertElementType( xla::ConstantR1(ctx->builder(), {-1, 0, 1, 0}), data_type), - neighbor_broadcast_shape, {last_warp_dim}), + neighbor_broadcast_dims, {last_warp_dim}), neighbors_data, dot_dims, /*precision_config=*/nullptr); // Slice out x and y. @@ -421,12 +409,13 @@ class ResamplerOp : public XlaOpKernel { OP_REQUIRES(ctx, warp_shape.dim_size(last_warp_dim) == 2, errors::InvalidArgument( "the last dimension of warp must be exactly size 2.")); + xla::PrimitiveType warp_type = ctx->input_xla_type(1); XlaOp data = ctx->Input("data"); XlaOp warp = ctx->Input("warp"); // Find the coordinates of the top left corner for the 2x2 region to be - // sampled from. The dimensions are (batch, dim_0, ... dim_n, 2) where the + // sampled from. The dimensions are [batch, dim_0, ... dim_n, 2] where the // last dimension of size 2 in turn is [x, y]. XlaOp top_left = xla::ConvertElementType(warp, xla::U32); @@ -457,10 +446,54 @@ class ResamplerOp : public XlaOpKernel { dot_dims.add_lhs_contracting_dimensions(warp_shape.dims() - 1); dot_dims.add_rhs_contracting_dimensions(warp_shape.dims() - 1); + // The dimension is [batch, dim_0, ...dim_n, data_channels]. auto blended_pixels = xla::DotGeneral(weights, neighbors_data, dot_dims, /*precision_config=*/nullptr); - ctx->SetOutput(0, blended_pixels); + // Handle out of boundary cases by constructing a predicate mask array based + // on the in-bound condition, and output 0 for the blended pixel value if + // out-bound. The dimension is the same as top_left: [batch, dim_0, + // ...dim_n, 2] where the last dimension of size 2 is the [x, y] coordinate. + + auto is_ge_zero = xla::Ge(warp, xla::ZerosLike(warp)); + + auto is_lt_image_size = xla::Lt( + warp, + xla::ConvertElementType( + xla::ConstantR1( + ctx->builder(), + {/*width=*/static_cast(data_shape.dim_size(2) - 1), + /*height=*/static_cast(data_shape.dim_size(1) - 1)}), + warp_type), + /*broadcast_dimensions=*/{warp_shape.dims() - 1}); + + auto is_in_bound_x_y = xla::And(is_ge_zero, is_lt_image_size); + // Reduce along last dimension. The resulting dimension is: + // [batch, dim_0, ...dim_n]. + auto is_in_bound = xla::Reduce( + is_in_bound_x_y, xla::ConstantR0(ctx->builder(), true), + xla::CreateScalarAndComputation(xla::PrimitiveType::PRED, + ctx->builder()), + {last_warp_dim}); + + // Broadcast 'is_in_bound' to the same dimension as 'blended_pixels', which + // is the dimension of the result: + // [batch, dim_0, ...dim_n, data_channels]. + auto warp_dims = warp_shape.dim_sizes(); + std::vector result_dims(warp_dims.begin(), warp_dims.end() - 1); + result_dims.push_back(data_channels); + + std::vector broadcasted_dims(warp_dims.size() - 1); + std::iota(broadcasted_dims.begin(), broadcasted_dims.end(), 0); + auto broadcasted_is_in_bound = + xla::BroadcastInDim(is_in_bound, result_dims, broadcasted_dims); + + // Set out of bound samples to zero. + auto zeros = + xla::Broadcast(xla::Zero(ctx->builder(), data_type), result_dims); + auto result = xla::Select(broadcasted_is_in_bound, blended_pixels, zeros); + + ctx->SetOutput(0, result); } }; @@ -473,6 +506,8 @@ class ResamplerGradOp : public XlaOpKernel { OP_REQUIRES_OK(ctx, ctx->GetAttr("T", &output_dtype)); } + // TODO(b/112295522): note that sampling from image boundary is not currently + // being handled properly. void Compile(XlaOpKernelContext* ctx) override { TensorShape data_shape_tf = ctx->InputShape("data"); OP_REQUIRES(ctx, data_shape_tf.dims() == 4, diff --git a/tensorflow/compiler/tf2xla/kernels/retval_op.cc b/tensorflow/compiler/tf2xla/kernels/retval_op.cc index 6970dd0a00..e4046c7955 100644 --- a/tensorflow/compiler/tf2xla/kernels/retval_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/retval_op.cc @@ -47,8 +47,7 @@ class RetvalOp : public XlaOpKernel { // compilation. OP_REQUIRES_OK(ctx, frame->SetRetval(index_, input)); } else { - XlaContext& xla_context = XlaContext::Get(ctx); - xla_context.SetRetval(index_, ctx->InputExpression(0)); + ctx->xla_context()->SetRetval(index_, ctx->InputExpression(0)); } } diff --git a/tensorflow/compiler/tf2xla/kernels/reverse_sequence_op.cc b/tensorflow/compiler/tf2xla/kernels/reverse_sequence_op.cc index 7ff3e91638..d7b38e86cc 100644 --- a/tensorflow/compiler/tf2xla/kernels/reverse_sequence_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/reverse_sequence_op.cc @@ -18,7 +18,6 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/client/lib/constants.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/xla_data.pb.h" #include "tensorflow/core/framework/tensor_shape.h" diff --git a/tensorflow/compiler/tf2xla/kernels/scan_ops.cc b/tensorflow/compiler/tf2xla/kernels/scan_ops.cc index b5fd7850bf..4b9e1a578b 100644 --- a/tensorflow/compiler/tf2xla/kernels/scan_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/scan_ops.cc @@ -39,8 +39,8 @@ namespace { // TODO(phawkins): implement double-sized windowed reductions in XLA and remove // the type constraint. -constexpr std::array kScanOpTypes = { - {DT_HALF, DT_BFLOAT16, DT_FLOAT}}; +constexpr std::array kScanOpTypes = { + {DT_HALF, DT_BFLOAT16, DT_FLOAT, DT_INT32}}; class ScanOp : public XlaOpKernel { public: @@ -103,11 +103,10 @@ class ScanOp : public XlaOpKernel { reducer = ctx->GetOrCreateMul(dtype); } auto output = xla::ReduceWindowWithGeneralPadding( - XlaHelpers::ConvertElementType(builder, ctx->Input(0), dtype), init, - *reducer, window_dims, window_strides, + XlaHelpers::ConvertElementType(ctx->Input(0), dtype), init, *reducer, + window_dims, window_strides, /*base_dilations=*/{}, /*window_dilations=*/{}, padding); - output = - XlaHelpers::ConvertElementType(builder, output, ctx->input_type(0)); + output = XlaHelpers::ConvertElementType(output, ctx->input_type(0)); // In exclusive mode, we have computed an extra element containing the sum // of all the input elements. Slice off this extra "last" element. diff --git a/tensorflow/compiler/tf2xla/kernels/sendrecv_ops.cc b/tensorflow/compiler/tf2xla/kernels/sendrecv_ops.cc index a7f5a8f169..84470b230d 100644 --- a/tensorflow/compiler/tf2xla/kernels/sendrecv_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/sendrecv_ops.cc @@ -42,7 +42,7 @@ SendOp::SendOp(OpKernelConstruction* ctx) : XlaOpKernel(ctx) { } void SendOp::Compile(XlaOpKernelContext* ctx) { - XlaCompiler* compiler = XlaContext::Get(ctx).compiler(); + XlaCompiler* compiler = ctx->compiler(); xla::ChannelHandle channel; OP_REQUIRES_OK(ctx, compiler->GetChannelHandle(tensor_name_, &channel)); xla::Send(ctx->Input(0), channel); @@ -73,7 +73,7 @@ RecvOp::RecvOp(OpKernelConstruction* ctx) : XlaOpKernel(ctx) { } void RecvOp::Compile(XlaOpKernelContext* ctx) { - XlaCompiler* compiler = XlaContext::Get(ctx).compiler(); + XlaCompiler* compiler = ctx->compiler(); xla::ChannelHandle channel; OP_REQUIRES_OK(ctx, compiler->GetChannelHandle(tensor_name_, &channel)); ctx->SetOutput(0, xla::Recv(ctx->builder(), shape_, channel)); diff --git a/tensorflow/compiler/tf2xla/kernels/sequence_ops.cc b/tensorflow/compiler/tf2xla/kernels/sequence_ops.cc index 60b011ba6d..b1fa2915d5 100644 --- a/tensorflow/compiler/tf2xla/kernels/sequence_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/sequence_ops.cc @@ -18,7 +18,7 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_helpers.h" #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" +#include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal.h" #include "tensorflow/compiler/xla/primitive_util.h" #include "tensorflow/core/framework/op_kernel.h" diff --git a/tensorflow/compiler/tf2xla/kernels/softmax_op.cc b/tensorflow/compiler/tf2xla/kernels/softmax_op.cc index d6bd927135..20da803353 100644 --- a/tensorflow/compiler/tf2xla/kernels/softmax_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/softmax_op.cc @@ -71,7 +71,7 @@ class SoftmaxOp : public XlaOpKernel { auto reduce = xla::Reduce(converted, xla::Zero(b, xla_accumulation_type), *ctx->GetOrCreateAdd(accumulation_type), {kClassDim}); - auto sum = XlaHelpers::ConvertElementType(b, reduce, type); + auto sum = XlaHelpers::ConvertElementType(reduce, type); auto softmax = log_ // softmax = shifted_logits - log(sum(exp(shifted_logits))) @@ -111,11 +111,11 @@ std::pair CrossEntropyWithLogits( // sum_{class} (exp(logits - max_logits)) const DataType accumulation_type = XlaHelpers::SumAccumulationType(type); auto converted = - XlaHelpers::ConvertElementType(b, exp_shifted_logits, accumulation_type); + XlaHelpers::ConvertElementType(exp_shifted_logits, accumulation_type); auto reduce = xla::Reduce(converted, XlaHelpers::Zero(b, accumulation_type), *ctx->GetOrCreateAdd(accumulation_type), {kClassDim}); - auto sum_exp = XlaHelpers::ConvertElementType(b, reduce, type); + auto sum_exp = XlaHelpers::ConvertElementType(reduce, type); // log(sum(exp(logits - max_logits))) auto log_sum_exp = xla::Log(sum_exp); @@ -126,11 +126,10 @@ std::pair CrossEntropyWithLogits( // (The subtraction broadcasts along the batch dimension.) auto sub = xla::Sub(shifted_logits, log_sum_exp, {kBatchDim}); auto mul = xla::Mul(xla::Neg(labels), sub); - auto sum = - xla::Reduce(XlaHelpers::ConvertElementType(b, mul, accumulation_type), - XlaHelpers::Zero(b, accumulation_type), - *ctx->GetOrCreateAdd(accumulation_type), {kClassDim}); - auto loss = XlaHelpers::ConvertElementType(b, sum, type); + auto sum = xla::Reduce(XlaHelpers::ConvertElementType(mul, accumulation_type), + XlaHelpers::Zero(b, accumulation_type), + *ctx->GetOrCreateAdd(accumulation_type), {kClassDim}); + auto loss = XlaHelpers::ConvertElementType(sum, type); // backprop: prob - labels, where // prob = exp(logits - max_logits) / sum(exp(logits - max_logits)) diff --git a/tensorflow/compiler/tf2xla/kernels/stack_ops.cc b/tensorflow/compiler/tf2xla/kernels/stack_ops.cc index 7b96b43ad8..8e9e4daf99 100644 --- a/tensorflow/compiler/tf2xla/kernels/stack_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/stack_ops.cc @@ -69,7 +69,7 @@ Status MaybeInitializeStack(xla::XlaBuilder* builder, XlaResource* resource, } TensorShape stack_shape; - stack_shape.AddDim(resource->tensor_array_size()); + stack_shape.AddDim(resource->max_array_size()); stack_shape.AppendShape(elem_shape); if (!resource->initialized()) { @@ -97,10 +97,10 @@ class StackOp : public XlaOpKernel { } void Compile(XlaOpKernelContext* ctx) override { - int64 size; - OP_REQUIRES_OK(ctx, ctx->ConstantInputAsIntScalar(0, &size)); + int64 max_size; + OP_REQUIRES_OK(ctx, ctx->ConstantInputAsIntScalar(0, &max_size)); OP_REQUIRES( - ctx, size >= 0, + ctx, max_size >= 0, errors::InvalidArgument( "XLA compilation requires a fixed stack size upper bound. If " "you are using tf.while_loop, set the maximum_iterations parameter " @@ -108,14 +108,9 @@ class StackOp : public XlaOpKernel { // We defer initializing the Stack resource until we see the first push. // Otherwise we do not know the shape of the stack elements. - xla::XlaOp value; - XlaContext& xc = XlaContext::Get(ctx); - XlaResource* resource; - string name = absl::StrCat("Stack: ", stack_name_); - OP_REQUIRES_OK( - ctx, xc.CreateResource(XlaResource::kStack, -1, std::move(name), dtype_, - TensorShape(), value, /*tensor_array_size=*/size, - /*tensor_array_gradients=*/{}, &resource)); + XlaResource* resource = + ctx->xla_context()->AddResource(XlaResource::CreateStack( + /*name=*/absl::StrCat("Stack: ", stack_name_), dtype_, max_size)); ctx->SetResourceOutput(0, resource); } diff --git a/tensorflow/compiler/tf2xla/kernels/stateless_random_ops.cc b/tensorflow/compiler/tf2xla/kernels/stateless_random_ops.cc index 5db52781be..50653d7b39 100644 --- a/tensorflow/compiler/tf2xla/kernels/stateless_random_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/stateless_random_ops.cc @@ -23,7 +23,6 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_registry.h" #include "tensorflow/compiler/xla/client/lib/constants.h" #include "tensorflow/compiler/xla/client/lib/math.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/lib/prng.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/core/framework/op_kernel.h" diff --git a/tensorflow/compiler/tf2xla/kernels/tensor_array_ops.cc b/tensorflow/compiler/tf2xla/kernels/tensor_array_ops.cc index 252967a746..939d7e1951 100644 --- a/tensorflow/compiler/tf2xla/kernels/tensor_array_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/tensor_array_ops.cc @@ -61,8 +61,8 @@ Status MaybeInitializeTensorArray(xla::XlaBuilder* builder, " but op has dtype ", DataTypeString(dtype), "."); } - TF_RET_CHECK(resource->tensor_array_size() >= 0) - << resource->name() << " size " << resource->tensor_array_size(); + TF_RET_CHECK(resource->max_array_size() >= 0) + << resource->name() << " size " << resource->max_array_size(); if (!resource->initialized()) { TF_RETURN_IF_ERROR(resource->SetTypeAndShape(dtype, elem_shape)); @@ -78,7 +78,7 @@ Status MaybeInitializeTensorArray(xla::XlaBuilder* builder, XLAShapeToTensorShape(shape_or_status.ValueOrDie(), &shape)); TensorShape ta_shape; - ta_shape.AddDim(resource->tensor_array_size()); + ta_shape.AddDim(resource->max_array_size()); ta_shape.AppendShape(elem_shape); if (ta_shape != shape) { return errors::InvalidArgument( @@ -114,7 +114,7 @@ Status CheckTensorArrayIsInitialized(const string& op_name, Status GetTensorArrayShape(const XlaResource* resource, xla::XlaBuilder* builder, TensorShape* shape) { *shape = resource->shape(); - shape->InsertDim(0, resource->tensor_array_size()); + shape->InsertDim(0, resource->max_array_size()); return Status::OK(); } @@ -166,13 +166,10 @@ class TensorArrayOp : public XlaOpKernel { value = xla::Broadcast(zero, ta_shape.dim_sizes()); } - XlaContext& xc = XlaContext::Get(ctx); - XlaResource* var; - string name = absl::StrCat("TensorArray: ", tensor_array_name_); - OP_REQUIRES_OK( - ctx, xc.CreateResource(XlaResource::kTensorArray, -1, std::move(name), - dtype_, shape, value, /*tensor_array_size=*/size, - /*tensor_array_gradients=*/{}, &var)); + XlaResource* var = + ctx->xla_context()->AddResource(XlaResource::CreateTensorArray( + /*name=*/absl::StrCat("TensorArray: ", tensor_array_name_), dtype_, + shape, /*initial_value=*/value, /*max_array_size=*/size)); ctx->SetResourceOutput(0, var); Tensor flow(DT_FLOAT, TensorShape({})); @@ -517,14 +514,13 @@ class TensorArraySplitOp : public XlaOpKernel { xla::XlaOp ta = resource->value(); TensorShape ta_shape; - ta_shape.AddDim(resource->tensor_array_size()); + ta_shape.AddDim(resource->max_array_size()); ta_shape.AppendShape(elem_shape); - OP_REQUIRES( - ctx, lengths.size() == resource->tensor_array_size(), - errors::InvalidArgument( - "TensorArray's size is not equal to the size of lengths (", - lengths.size(), " vs. ", resource->tensor_array_size(), ")")); + OP_REQUIRES(ctx, lengths.size() == resource->max_array_size(), + errors::InvalidArgument( + "TensorArray's size is not equal to the size of lengths (", + lengths.size(), " vs. ", resource->max_array_size(), ")")); const xla::XlaOp value = ctx->Input(1); const xla::XlaOp flow = ctx->Input(3); @@ -562,8 +558,7 @@ class TensorArraySizeOp : public XlaOpKernel { XlaResource* var; OP_REQUIRES_OK(ctx, ctx->GetResourceInput(0, &var)); Tensor size_tensor(DT_INT32, {}); - size_tensor.scalar()() = - static_cast(var->tensor_array_size()); + size_tensor.scalar()() = static_cast(var->max_array_size()); ctx->SetConstantOutput(0, size_tensor); } diff --git a/tensorflow/compiler/tf2xla/kernels/topk_op.cc b/tensorflow/compiler/tf2xla/kernels/topk_op.cc index 8a0c94cfae..ee3bdf3394 100644 --- a/tensorflow/compiler/tf2xla/kernels/topk_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/topk_op.cc @@ -15,7 +15,6 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/tf2xla/xla_op_registry.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/lib/sorting.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal.h" diff --git a/tensorflow/compiler/tf2xla/kernels/training_ops.cc b/tensorflow/compiler/tf2xla/kernels/training_ops.cc index 7077c2e3a5..960c1462ce 100644 --- a/tensorflow/compiler/tf2xla/kernels/training_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/training_ops.cc @@ -320,9 +320,8 @@ class ResourceApplyAdagradDA : public XlaOpKernel { xla::XlaOp lr = ctx->Input(4); xla::XlaOp l1 = ctx->Input(5); xla::XlaOp l2 = ctx->Input(6); - xla::XlaBuilder* const b = ctx->builder(); xla::XlaOp global_step = - XlaHelpers::ConvertElementType(b, ctx->Input(7), dtype_); + XlaHelpers::ConvertElementType(ctx->Input(7), dtype_); accum = accum + grad; squared_accum = squared_accum + xla::Square(grad); diff --git a/tensorflow/compiler/tf2xla/kernels/while_op.cc b/tensorflow/compiler/tf2xla/kernels/while_op.cc index 559414eeaa..ce007fc04a 100644 --- a/tensorflow/compiler/tf2xla/kernels/while_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/while_op.cc @@ -64,7 +64,7 @@ Status MakeXlaCompilerArgumentsFromInputs( if (!arg.initialized) { *has_uninitialized_vars = true; } - arg.tensor_array_size = resource->tensor_array_size(); + arg.max_array_size = resource->max_array_size(); for (const auto& gradient : resource->tensor_array_gradients()) { arg.tensor_array_gradients.insert(gradient.first); } diff --git a/tensorflow/compiler/tf2xla/kernels/xla_broadcast_helper_op.cc b/tensorflow/compiler/tf2xla/kernels/xla_broadcast_helper_op.cc index a9f88a6df2..ad8e707e11 100644 --- a/tensorflow/compiler/tf2xla/kernels/xla_broadcast_helper_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/xla_broadcast_helper_op.cc @@ -89,13 +89,10 @@ class XlaBroadcastHelperOp : public XlaOpKernel { lhs_shape.DebugString(), " and ", rhs_shape.DebugString())); broadcast_shape[dim] = min_rank_shape->dim_size(i); } - xla::PrimitiveType type = context->input_xla_type(0); - xla::Shape broadcast_xla_shape = - xla::ShapeUtil::MakeShape(type, broadcast_shape); if (broadcast_lhs) { - lhs = xla::BroadcastInDim(lhs, broadcast_xla_shape, broadcast_dims); + lhs = xla::BroadcastInDim(lhs, broadcast_shape, broadcast_dims); } else { - rhs = xla::BroadcastInDim(rhs, broadcast_xla_shape, broadcast_dims); + rhs = xla::BroadcastInDim(rhs, broadcast_shape, broadcast_dims); } context->SetOutput(0, lhs); context->SetOutput(1, rhs); diff --git a/tensorflow/compiler/tf2xla/lib/BUILD b/tensorflow/compiler/tf2xla/lib/BUILD index 1ce3930fd1..422781d536 100644 --- a/tensorflow/compiler/tf2xla/lib/BUILD +++ b/tensorflow/compiler/tf2xla/lib/BUILD @@ -17,20 +17,6 @@ filegroup( load("//tensorflow/compiler/xla/tests:build_defs.bzl", "xla_test") -cc_library( - name = "batch_dot", - srcs = ["batch_dot.cc"], - hdrs = ["batch_dot.h"], - deps = [ - "//tensorflow/compiler/xla:shape_util", - "//tensorflow/compiler/xla:status_macros", - "//tensorflow/compiler/xla:statusor", - "//tensorflow/compiler/xla:xla_data_proto", - "//tensorflow/compiler/xla/client:xla_builder", - "//tensorflow/core:lib", - ], -) - cc_library( name = "broadcast", srcs = ["broadcast.cc"], @@ -52,7 +38,6 @@ cc_library( srcs = ["cholesky.cc"], hdrs = ["cholesky.h"], deps = [ - ":batch_dot", ":triangular_solve", ":util", ":while_loop", @@ -63,6 +48,8 @@ cc_library( "//tensorflow/compiler/xla:xla_data_proto", "//tensorflow/compiler/xla/client:xla_builder", "//tensorflow/compiler/xla/client/lib:constants", + "//tensorflow/compiler/xla/client/lib:matrix", + "//tensorflow/compiler/xla/client/lib:slicing", "//tensorflow/core:lib", ], ) @@ -87,7 +74,6 @@ cc_library( srcs = ["qr.cc"], hdrs = ["qr.h"], deps = [ - ":batch_dot", ":util", ":while_loop", "//tensorflow/compiler/xla:literal_util", @@ -99,7 +85,8 @@ cc_library( "//tensorflow/compiler/xla/client/lib:arithmetic", "//tensorflow/compiler/xla/client/lib:constants", "//tensorflow/compiler/xla/client/lib:math", - "//tensorflow/compiler/xla/client/lib:numeric", + "//tensorflow/compiler/xla/client/lib:matrix", + "//tensorflow/compiler/xla/client/lib:slicing", "//tensorflow/core:lib", ], ) @@ -129,7 +116,6 @@ cc_library( srcs = ["triangular_solve.cc"], hdrs = ["triangular_solve.h"], deps = [ - ":batch_dot", ":util", "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:shape_util", @@ -140,7 +126,9 @@ cc_library( "//tensorflow/compiler/xla/client:xla_builder", "//tensorflow/compiler/xla/client:xla_computation", "//tensorflow/compiler/xla/client/lib:constants", - "//tensorflow/compiler/xla/client/lib:numeric", + "//tensorflow/compiler/xla/client/lib:math", + "//tensorflow/compiler/xla/client/lib:matrix", + "//tensorflow/compiler/xla/client/lib:slicing", "//tensorflow/core:lib", ], ) @@ -187,29 +175,6 @@ cc_library( ], ) -xla_test( - name = "util_test", - srcs = ["util_test.cc"], - deps = [ - ":batch_dot", - ":util", - "//tensorflow/compiler/xla:array2d", - "//tensorflow/compiler/xla:literal", - "//tensorflow/compiler/xla:shape_util", - "//tensorflow/compiler/xla:statusor", - "//tensorflow/compiler/xla:test", - "//tensorflow/compiler/xla:types", - "//tensorflow/compiler/xla:xla_data_proto", - "//tensorflow/compiler/xla/client:global_data", - "//tensorflow/compiler/xla/client:local_client", - "//tensorflow/compiler/xla/tests:client_library_test_base", - "//tensorflow/compiler/xla/tests:literal_test_util", - "//tensorflow/compiler/xla/tests:xla_internal_test_main", - "//tensorflow/core:lib", - "//tensorflow/core:test", - ], -) - cc_library( name = "while_loop", srcs = ["while_loop.cc"], diff --git a/tensorflow/compiler/tf2xla/lib/batch_dot.cc b/tensorflow/compiler/tf2xla/lib/batch_dot.cc deleted file mode 100644 index 5400e8834c..0000000000 --- a/tensorflow/compiler/tf2xla/lib/batch_dot.cc +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "tensorflow/compiler/tf2xla/lib/batch_dot.h" - -#include -#include - -#include "tensorflow/compiler/xla/client/xla_builder.h" -#include "tensorflow/compiler/xla/shape_util.h" -#include "tensorflow/compiler/xla/status_macros.h" -#include "tensorflow/compiler/xla/statusor.h" -#include "tensorflow/core/lib/core/errors.h" - -namespace tensorflow { - -xla::XlaOp BatchDot(xla::XlaOp x, xla::XlaOp y, bool transpose_x, - bool transpose_y, bool conjugate_x, bool conjugate_y, - xla::PrecisionConfig::Precision precision) { - xla::XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> xla::StatusOr { - TF_ASSIGN_OR_RETURN(xla::Shape x_shape, builder->GetShape(x)); - TF_ASSIGN_OR_RETURN(xla::Shape y_shape, builder->GetShape(y)); - - // Check that both tensors have the same number of dimensions. There must be - // at least two (the batch dimensions can be empty). - if (xla::ShapeUtil::Rank(x_shape) != xla::ShapeUtil::Rank(y_shape)) { - return errors::InvalidArgument( - "Arguments to BatchedDot have different ranks: ", - xla::ShapeUtil::HumanString(x_shape), " vs. ", - xla::ShapeUtil::HumanString(y_shape)); - } - const int ndims = xla::ShapeUtil::Rank(x_shape); - if (ndims < 2) { - return errors::InvalidArgument( - "Arguments to BatchedDot must have rank >= 2: ", ndims); - } - - // The batch dimensions must be equal and the matrix dimensions must be - // valid. - std::vector batch_dimension_numbers; - for (int i = 0; i < ndims - 2; ++i) { - if (x_shape.dimensions(i) != y_shape.dimensions(i)) { - return errors::InvalidArgument( - "Dimension ", i, " of inputs to BatchedDot must be equal: ", - xla::ShapeUtil::HumanString(x_shape), " vs ", - xla::ShapeUtil::HumanString(y_shape)); - } - batch_dimension_numbers.push_back(i); - } - - int x_inner_dim = transpose_x ? (ndims - 2) : (ndims - 1); - int y_inner_dim = transpose_y ? (ndims - 1) : (ndims - 2); - if (x_shape.dimensions(x_inner_dim) != y_shape.dimensions(y_inner_dim)) { - return errors::InvalidArgument( - "Dimensions ", x_inner_dim, " and ", y_inner_dim, - " of arguments to BatchedDot must be equal: ", - xla::ShapeUtil::HumanString(x_shape), " transpose: ", transpose_x, - " vs. ", xla::ShapeUtil::HumanString(y_shape), - " transpose: ", transpose_y); - } - - // Check for zero lhs/rhs dim size. - if (xla::ShapeUtil::IsZeroElementArray(x_shape) || - xla::ShapeUtil::IsZeroElementArray(y_shape)) { - std::vector dimensions(batch_dimension_numbers.size()); - for (int i = 0; i < batch_dimension_numbers.size(); ++i) { - dimensions[i] = x_shape.dimensions(batch_dimension_numbers[i]); - } - int x_outer_dim = transpose_x ? (ndims - 1) : (ndims - 2); - int y_outer_dim = transpose_y ? (ndims - 2) : (ndims - 1); - dimensions.push_back(x_shape.dimensions(x_outer_dim)); - dimensions.push_back(y_shape.dimensions(y_outer_dim)); - return xla::Broadcast( - xla::ConstantLiteral(builder, - xla::LiteralUtil::Zero(x_shape.element_type())), - dimensions); - } - - if (x_shape.element_type() == xla::C64 && conjugate_x) { - x = xla::Conj(x); - } - if (y_shape.element_type() == xla::C64 && conjugate_y) { - y = xla::Conj(y); - } - - xla::PrecisionConfig precision_proto; - precision_proto.add_operand_precision(precision); - precision_proto.add_operand_precision(precision); - - xla::DotDimensionNumbers dot_dnums; - dot_dnums.add_lhs_contracting_dimensions(x_inner_dim); - dot_dnums.add_rhs_contracting_dimensions(y_inner_dim); - for (auto batch_dimension_number : batch_dimension_numbers) { - dot_dnums.add_lhs_batch_dimensions(batch_dimension_number); - dot_dnums.add_rhs_batch_dimensions(batch_dimension_number); - } - - return xla::DotGeneral(x, y, dot_dnums, &precision_proto); - }); -} - -} // namespace tensorflow diff --git a/tensorflow/compiler/tf2xla/lib/batch_dot.h b/tensorflow/compiler/tf2xla/lib/batch_dot.h deleted file mode 100644 index 6edd63a4d3..0000000000 --- a/tensorflow/compiler/tf2xla/lib/batch_dot.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#ifndef TENSORFLOW_COMPILER_TF2XLA_LIB_BATCH_DOT_H_ -#define TENSORFLOW_COMPILER_TF2XLA_LIB_BATCH_DOT_H_ - -#include "tensorflow/compiler/xla/client/xla_builder.h" -#include "tensorflow/compiler/xla/xla_data.pb.h" - -namespace tensorflow { - -// Multiplies slices of two tensors in batches. - -// Multiplies all slices of `Tensor` `x` and `y` (each slice can be -// viewed as an element of a batch), and arranges the individual results -// in a single output tensor of the same batch size. Each of the -// individual slices can optionally be transposed before multiplication by -// setting the `transpose_x` or `transpose_y` flag to `true`. Similarly, each -// can be elementwise-complex-conjugated by setting the `conjugate_x` or -// `conjugate_y` flag to `true`. To apply a Hermitian adjoint to `x`, set both -// `transpose_x` and `conjugate_x` to `true`, and analogously for `y`. -// -// The input tensors `x` and `y` are 2-D or higher with shape `[..., r_x, c_x]` -// and `[..., r_y, c_y]`. -// -// The output tensor is 2-D or higher with shape `[..., r_o, c_o]`, where: -// -// r_o = c_x if transpose_x else r_x -// c_o = r_y if transpose_y else c_y -// -// It is computed as: -// -// output[..., :, :] = matrix(x[..., :, :]) * matrix(y[..., :, :]) -xla::XlaOp BatchDot( - xla::XlaOp x, xla::XlaOp y, bool transpose_x = false, - bool transpose_y = false, bool conjugate_x = false, - bool conjugate_y = false, - xla::PrecisionConfig::Precision precision = xla::PrecisionConfig::DEFAULT); - -} // namespace tensorflow - -#endif // TENSORFLOW_COMPILER_TF2XLA_LIB_BATCH_DOT_H_ diff --git a/tensorflow/compiler/tf2xla/lib/broadcast.cc b/tensorflow/compiler/tf2xla/lib/broadcast.cc index 3e402ef855..be31f11668 100644 --- a/tensorflow/compiler/tf2xla/lib/broadcast.cc +++ b/tensorflow/compiler/tf2xla/lib/broadcast.cc @@ -80,10 +80,8 @@ xla::StatusOr BroadcastTo(xla::XlaOp input, broadcast_dim = broadcast_shape_size - broadcast_dim - 1; } absl::c_reverse(broadcast_shape); - xla::XlaOp output = xla::BroadcastInDim( - input, - xla::ShapeUtil::MakeShape(input_shape.element_type(), broadcast_shape), - broadcast_dims); + xla::XlaOp output = + xla::BroadcastInDim(input, broadcast_shape, broadcast_dims); if (broadcast_shape != output_dims) { output = xla::Reshape(output, output_dims); } diff --git a/tensorflow/compiler/tf2xla/lib/cholesky.cc b/tensorflow/compiler/tf2xla/lib/cholesky.cc index ab3d0a5668..7ef8659992 100644 --- a/tensorflow/compiler/tf2xla/lib/cholesky.cc +++ b/tensorflow/compiler/tf2xla/lib/cholesky.cc @@ -18,11 +18,12 @@ limitations under the License. #include #include -#include "tensorflow/compiler/tf2xla/lib/batch_dot.h" #include "tensorflow/compiler/tf2xla/lib/triangular_solve.h" #include "tensorflow/compiler/tf2xla/lib/util.h" #include "tensorflow/compiler/tf2xla/lib/while_loop.h" #include "tensorflow/compiler/xla/client/lib/constants.h" +#include "tensorflow/compiler/xla/client/lib/matrix.h" +#include "tensorflow/compiler/xla/client/lib/slicing.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal.h" #include "tensorflow/compiler/xla/shape_util.h" @@ -101,10 +102,7 @@ xla::XlaOp CholeskyUnblocked(xla::XlaOp a, // a[..., i, i] auto a_ii = DynamicSliceInMinorDims(body_a, {i, i}, {1, 1}); // np.dot(row, np.swapaxes(row, -1, -2)) - auto diag_dot = BatchDot(row, row, - /*transpose_x=*/false, - /*transpose_y=*/true, /*conjugate_x=*/false, - /*conjugate_y=*/false, precision); + auto diag_dot = BatchDot(row, TransposeInMinorDims(row), precision); // l[..., i, i] = np.sqrt(a[..., i, i] - np.dot(row, // np.swapaxes(row, -1, -2))) auto l_ii = @@ -122,10 +120,7 @@ xla::XlaOp CholeskyUnblocked(xla::XlaOp a, // The columns in [i, n] are zeroed out in `row`, so we just have to // zero out rows above i+1 after the BatchDot. np.dot(l[..., :, :i], // r.T) - auto dot = BatchDot(body_l, row, - /*transpose_x=*/false, - /*transpose_y=*/true, /*conjugate_x=*/false, - /*conjugate_y=*/false, precision); + auto dot = BatchDot(body_l, TransposeInMinorDims(row), precision); // np.dot(l[..., i+1:, :i], r.T) auto dot_ip1 = xla::Select(xla::Le(mask_range_col, i), mask_zeros_col, dot); @@ -185,9 +180,7 @@ xla::XlaOp Cholesky(xla::XlaOp a, int64 block_size, // a[i:, i:i+k] -= np.dot(l[i:, :i], np.transpose(l[i:i+k, :i])) auto lhs = SliceInMinorDims(l, {i, 0}, {n, i}); auto rhs = SliceInMinorDims(l, {i, 0}, {i + k, i}); - auto delta = BatchDot(lhs, rhs, /*transpose_x=*/false, - /*transpose_y=*/true, /*conjugate_x=*/false, - /*conjugate_y=*/false, precision); + auto delta = BatchDot(lhs, TransposeInMinorDims(rhs), precision); auto before = SliceInMinorDims(a, {i, i}, {n, i + k}); a = UpdateSliceInMinorDims(a, before - delta, {i, i}); } diff --git a/tensorflow/compiler/tf2xla/lib/qr.cc b/tensorflow/compiler/tf2xla/lib/qr.cc index 6b3f2b6e06..d600774860 100644 --- a/tensorflow/compiler/tf2xla/lib/qr.cc +++ b/tensorflow/compiler/tf2xla/lib/qr.cc @@ -18,13 +18,13 @@ limitations under the License. #include #include -#include "tensorflow/compiler/tf2xla/lib/batch_dot.h" #include "tensorflow/compiler/tf2xla/lib/util.h" #include "tensorflow/compiler/tf2xla/lib/while_loop.h" #include "tensorflow/compiler/xla/client/lib/arithmetic.h" #include "tensorflow/compiler/xla/client/lib/constants.h" #include "tensorflow/compiler/xla/client/lib/math.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" +#include "tensorflow/compiler/xla/client/lib/matrix.h" +#include "tensorflow/compiler/xla/client/lib/slicing.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal_util.h" #include "tensorflow/compiler/xla/shape_util.h" @@ -191,12 +191,8 @@ xla::StatusOr QRBlock( auto v_broadcast = xla::Reshape(v, shape); // a[:, :] -= tau * np.dot(v[:, np.newaxis], // np.dot(v[np.newaxis, :], a[:, :])) - auto vva = - BatchDot(v_broadcast, a, /*transpose_x=*/false, /*transpose_y=*/false, - /*conjugate_x=*/false, /*conjugate_y=*/false, precision); - vva = - BatchDot(v_broadcast, vva, /*transpose_x=*/true, /*transpose_y=*/false, - /*conjugate_x=*/false, /*conjugate_y=*/false, precision); + auto vva = BatchDot(v_broadcast, a, precision); + vva = BatchDot(TransposeInMinorDims(v_broadcast), vva, precision); a = a - xla::Mul(tau, vva, /*broadcast_dimensions=*/batch_dim_indices); @@ -278,12 +274,9 @@ xla::StatusOr ComputeWYRepresentation( auto beta = DynamicSliceInMinorDims(taus, {j}, {1}); // yv has shape [..., n, 1] - auto yv = BatchDot(y, v, /*transpose_x=*/true, /*transpose_y=*/false, - /*conjugate_x=*/false, /*conjugate_y=*/false, precision); + auto yv = BatchDot(TransposeInMinorDims(y), v, precision); // wyv has shape [..., m, 1] - auto wyv = - BatchDot(w, yv, /*transpose_x=*/false, /*transpose_y=*/false, - /*conjugate_x=*/false, /*conjugate_y=*/false, precision); + auto wyv = BatchDot(w, yv, precision); auto z = xla::Mul( -beta, v + wyv, @@ -375,23 +368,15 @@ xla::StatusOr QRDecomposition( // a[i:, i+k:] += np.dot(Y, np.dot(W.T, a[i:, i+k:])) auto a_panel = SliceInMinorDims(a, {i, i + k}, {m, n}); - auto a_update = - BatchDot(w, a_panel, /*transpose_x=*/true, /*transpose_y=*/false, - /*conjugate_x=*/false, /*conjugate_y=*/false, precision); - a_update = - BatchDot(y, a_update, /*transpose_x=*/false, /*transpose_y=*/false, - /*conjugate_x=*/false, /*conjugate_y=*/false, precision); + auto a_update = BatchDot(TransposeInMinorDims(w), a_panel, precision); + a_update = BatchDot(y, a_update, precision); a_panel = a_panel + a_update; a = UpdateSliceInMinorDims(a, a_panel, {i, i + k}); // q[:, i:] += np.dot(np.dot(q[:, i:], W), Y.T)) auto q_panel = SliceInMinorDims(q, {0, i}, {m, m}); - auto q_update = - BatchDot(q_panel, w, /*transpose_x=*/false, /*transpose_y=*/false, - /*conjugate_x=*/false, /*conjugate_y=*/false, precision); - q_update = BatchDot(q_update, y, /*transpose_x=*/false, - /*transpose_y=*/true, /*conjugate_x=*/false, - /*conjugate_y=*/false, precision); + auto q_update = BatchDot(q_panel, w, precision); + q_update = BatchDot(q_update, TransposeInMinorDims(y), precision); q_panel = q_panel + q_update; q = UpdateSliceInMinorDims(q, q_panel, {0, i}); } diff --git a/tensorflow/compiler/tf2xla/lib/triangular_solve.cc b/tensorflow/compiler/tf2xla/lib/triangular_solve.cc index 6524c2a9b1..192a61dca2 100644 --- a/tensorflow/compiler/tf2xla/lib/triangular_solve.cc +++ b/tensorflow/compiler/tf2xla/lib/triangular_solve.cc @@ -18,10 +18,11 @@ limitations under the License. #include #include -#include "tensorflow/compiler/tf2xla/lib/batch_dot.h" #include "tensorflow/compiler/tf2xla/lib/util.h" #include "tensorflow/compiler/xla/client/lib/constants.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" +#include "tensorflow/compiler/xla/client/lib/math.h" +#include "tensorflow/compiler/xla/client/lib/matrix.h" +#include "tensorflow/compiler/xla/client/lib/slicing.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/client/xla_computation.h" #include "tensorflow/compiler/xla/literal.h" @@ -311,13 +312,13 @@ xla::XlaOp SolveWithInvertedDiagonalBlocks( auto a_row = MaybeConjugate(SliceInMinorDims(a, start, end), conjugate_a); if (left_side) { - remainder = b_row - BatchDot(a_row, x, transpose_a, false, - /*conjugate_x=*/false, - /*conjugate_y=*/false, precision); + remainder = + b_row - BatchDot(MaybeTransposeInMinorDims(a_row, transpose_a), x, + precision); } else { - remainder = b_row - BatchDot(x, a_row, false, transpose_a, - /*conjugate_x=*/false, - /*conjugate_y=*/false, precision); + remainder = + b_row - BatchDot(x, MaybeTransposeInMinorDims(a_row, transpose_a), + precision); } } @@ -327,13 +328,12 @@ xla::XlaOp SolveWithInvertedDiagonalBlocks( xla::ConstantR0WithType(builder, xla::S32, j * block_size); std::vector update_starts = {start_index, zero}; if (left_side) { - x_update = - BatchDot(inv_block, remainder, transpose_a, false, - /*conjugate_x=*/false, /*conjugate_y=*/false, precision); + x_update = BatchDot(MaybeTransposeInMinorDims(inv_block, transpose_a), + remainder, precision); } else { - x_update = - BatchDot(remainder, inv_block, false, transpose_a, - /*conjugate_x=*/false, /*conjugate_y=*/false, precision); + x_update = BatchDot(remainder, + MaybeTransposeInMinorDims(inv_block, transpose_a), + precision); std::swap(update_starts[0], update_starts[1]); } x = DynamicUpdateSliceInMinorDims(x, x_update, /*starts=*/update_starts); diff --git a/tensorflow/compiler/tf2xla/lib/util.cc b/tensorflow/compiler/tf2xla/lib/util.cc index 804671fbc7..c0bd172d17 100644 --- a/tensorflow/compiler/tf2xla/lib/util.cc +++ b/tensorflow/compiler/tf2xla/lib/util.cc @@ -113,36 +113,6 @@ xla::XlaOp IntegerLiteral(xla::XlaBuilder* builder, xla::PrimitiveType type, return xla::ConstantLiteral(builder, literal); } -xla::XlaOp SliceInMinorDims(xla::XlaOp x, absl::Span start, - absl::Span end) { - xla::XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> xla::StatusOr { - TF_RET_CHECK(start.size() == end.size()); - int64 n_minor_dims = start.size(); - - TF_ASSIGN_OR_RETURN(xla::Shape shape, builder->GetShape(x)); - - const int64 n_dims = xla::ShapeUtil::Rank(shape); - TF_RET_CHECK(n_minor_dims <= n_dims); - auto major_dims = xla::AsInt64Slice(shape.dimensions()) - .subspan( - /*pos=*/0, - /*len=*/n_dims - n_minor_dims); - - // Prepends 0s in the major dim - std::vector padded_start(n_dims, 0); - std::copy(start.begin(), start.end(), - padded_start.begin() + major_dims.size()); - - // Prepends the shape of the major dims. - std::vector padded_end(n_dims); - std::copy(major_dims.begin(), major_dims.end(), padded_end.begin()); - std::copy(end.begin(), end.end(), padded_end.begin() + major_dims.size()); - - std::vector strides(n_dims, 1); - return xla::Slice(x, padded_start, padded_end, strides); - }); -} std::vector ConcatVectors(absl::Span xs, absl::Span ys) { @@ -152,100 +122,4 @@ std::vector ConcatVectors(absl::Span xs, return output; } -xla::XlaOp DynamicSliceInMinorDims(xla::XlaOp x, - absl::Span starts, - absl::Span sizes) { - xla::XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> xla::StatusOr { - TF_ASSIGN_OR_RETURN(xla::Shape shape, builder->GetShape(x)); - const int64 n_dims = xla::ShapeUtil::Rank(shape); - int64 n_minor_dims = starts.size(); - TF_RET_CHECK(n_minor_dims == sizes.size()); - TF_RET_CHECK(n_minor_dims <= n_dims); - auto major_dims = xla::AsInt64Slice(shape.dimensions()) - .subspan( - /*pos=*/0, - /*len=*/n_dims - sizes.size()); - auto padded_starts = PrependZerosInMajorDims(x, starts); - auto padded_sizes = ConcatVectors(major_dims, sizes); - return xla::DynamicSlice(x, padded_starts, padded_sizes); - }); -} - -xla::XlaOp UpdateSlice(xla::XlaOp x, xla::XlaOp update, - absl::Span start) { - xla::XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> xla::StatusOr { - // TODO(phawkins): make int64 work on all backends, remove the int32 cast. - std::vector start_as_int32(start.begin(), start.end()); - auto start_constant = xla::ConstantR1(builder, start_as_int32); - TF_ASSIGN_OR_RETURN(xla::Shape shape, builder->GetShape(x)); - const int64 n_dims = xla::ShapeUtil::Rank(shape); - TF_ASSIGN_OR_RETURN(xla::Shape start_constant_shape, - builder->GetShape(start_constant)); - const int64 start_length = - xla::ShapeUtil::GetDimension(start_constant_shape, -1); - TF_RET_CHECK(start_length == n_dims); - return xla::DynamicUpdateSlice(x, update, start_constant); - }); -} - -xla::XlaOp UpdateSliceInMinorDims(xla::XlaOp x, xla::XlaOp update, - absl::Span start) { - xla::XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> xla::StatusOr { - TF_ASSIGN_OR_RETURN(xla::Shape shape, builder->GetShape(x)); - const int64 n_dims = xla::ShapeUtil::Rank(shape); - const int64 n_minor_dims = start.size(); - TF_RET_CHECK(n_minor_dims <= n_dims); - std::vector padded_start(n_dims, 0); - std::copy(start.begin(), start.end(), - padded_start.begin() + (n_dims - n_minor_dims)); - return UpdateSlice(x, update, padded_start); - }); -} - -xla::XlaOp DynamicUpdateSliceInMinorDims(xla::XlaOp x, xla::XlaOp update, - absl::Span starts) { - auto padded_starts = PrependZerosInMajorDims(x, starts); - return xla::DynamicUpdateSlice(x, update, padded_starts); -} - -xla::XlaOp PrependZerosInMajorDims(xla::XlaOp x, - absl::Span starts) { - xla::XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> xla::StatusOr { - TF_ASSIGN_OR_RETURN(xla::Shape shape, builder->GetShape(x)); - const int64 n_dims = xla::ShapeUtil::Rank(shape); - auto zero = xla::Reshape(xla::ConstantR0(builder, 0), {1}); - std::vector padded_starts(n_dims, zero); - for (int i = 0; i < starts.size(); ++i) { - padded_starts[n_dims - starts.size() + i] = xla::Reshape(starts[i], {1}); - } - return xla::ConcatInDim(builder, padded_starts, 0); - }); -} - -xla::XlaOp TransposeInMinorDims(xla::XlaOp x) { - xla::XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> xla::StatusOr { - TF_ASSIGN_OR_RETURN(xla::Shape shape, builder->GetShape(x)); - const int64 n_dims = xla::ShapeUtil::Rank(shape); - TF_RET_CHECK(n_dims >= 2); - std::vector permutation(n_dims); - std::iota(permutation.begin(), permutation.end(), 0); - std::swap(permutation[n_dims - 1], permutation[n_dims - 2]); - return xla::Transpose(x, permutation); - }); -} - -xla::XlaOp MaybeConjugate(xla::XlaOp x, bool conjugate) { - xla::XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> xla::StatusOr { - TF_ASSIGN_OR_RETURN(xla::Shape shape, builder->GetShape(x)); - auto perform_conj = shape.element_type() == xla::C64 && conjugate; - return perform_conj ? xla::Conj(x) : x; - }); -} - } // namespace tensorflow diff --git a/tensorflow/compiler/tf2xla/lib/util.h b/tensorflow/compiler/tf2xla/lib/util.h index 80e9e5b002..aec8061cb4 100644 --- a/tensorflow/compiler/tf2xla/lib/util.h +++ b/tensorflow/compiler/tf2xla/lib/util.h @@ -38,44 +38,10 @@ xla::XlaOp PrependZerosInMajorDims(xla::XlaOp x, xla::XlaOp IntegerLiteral(xla::XlaBuilder* builder, xla::PrimitiveType type, int64 value); -// Builds a vector of zeros of length rank(x) with the last values being -// those in `starts`. -xla::XlaOp PrependZerosInMajorDims(xla::XlaOp x, - absl::Span starts); - -// Performs a slice in the minor dimensions of a Tensor. -xla::XlaOp SliceInMinorDims(xla::XlaOp x, absl::Span start, - absl::Span end); - // Returns the concatenation of `xs` and `ys`. std::vector ConcatVectors(absl::Span xs, absl::Span ys); -// Performs a dynamic slice in the minor dimensions of a Tensor. -xla::XlaOp DynamicSliceInMinorDims(xla::XlaOp x, - absl::Span starts, - absl::Span sizes); - -// Updates a slice of 'x', i.e., -// x[start[0], ..., start[n]] = update -xla::XlaOp UpdateSlice(xla::XlaOp x, xla::XlaOp update, - absl::Span start); - -// Updates a slice of 'x', where 'start' contains a list of minor dimensions: -// x[..., start[0], ..., start[n]] = update -xla::XlaOp UpdateSliceInMinorDims(xla::XlaOp x, xla::XlaOp update, - absl::Span start); - -xla::XlaOp DynamicUpdateSliceInMinorDims(xla::XlaOp x, xla::XlaOp update, - absl::Span starts); - -// Transposes a stack of matrices `x` by swapping the last two dimensions. -xla::XlaOp TransposeInMinorDims(xla::XlaOp x); - -// Applies a complex conjugation operation if `a` is complex and `conjugate_a` -// is true, otherwise returns its argument. -xla::XlaOp MaybeConjugate(xla::XlaOp x, bool conjugate); - } // namespace tensorflow #endif // TENSORFLOW_COMPILER_TF2XLA_LIB_UTIL_H_ diff --git a/tensorflow/compiler/tf2xla/python/BUILD b/tensorflow/compiler/tf2xla/python/BUILD index c9f486edc8..fef97b98c3 100644 --- a/tensorflow/compiler/tf2xla/python/BUILD +++ b/tensorflow/compiler/tf2xla/python/BUILD @@ -1,11 +1,13 @@ licenses(["notice"]) # Apache 2.0 +package_group( + name = "friends", + includes = ["//tensorflow:internal"], +) + package( default_visibility = [ - "//learning/deepmind/public/wavenet/python:__subpackages__", - "//learning/deepmind/research/alphastar:__subpackages__", - "//learning/tfx:__subpackages__", - "//tensorflow:internal", + ":friends", ], ) diff --git a/tensorflow/compiler/tf2xla/shape_util.h b/tensorflow/compiler/tf2xla/shape_util.h index f7e34a5b40..0b231ea8e7 100644 --- a/tensorflow/compiler/tf2xla/shape_util.h +++ b/tensorflow/compiler/tf2xla/shape_util.h @@ -18,6 +18,7 @@ limitations under the License. #ifndef TENSORFLOW_COMPILER_TF2XLA_SHAPE_UTIL_H_ #define TENSORFLOW_COMPILER_TF2XLA_SHAPE_UTIL_H_ +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/xla_data.pb.h" #include "tensorflow/core/framework/tensor_shape.h" #include "tensorflow/core/framework/types.pb.h" diff --git a/tensorflow/compiler/tf2xla/xla_compiled_cpu_function.h b/tensorflow/compiler/tf2xla/xla_compiled_cpu_function.h index 425e769346..c7341cf8b9 100644 --- a/tensorflow/compiler/tf2xla/xla_compiled_cpu_function.h +++ b/tensorflow/compiler/tf2xla/xla_compiled_cpu_function.h @@ -26,7 +26,7 @@ limitations under the License. // Forward-declare, rather than include, to reduce code size for users that // never use this functionality. namespace xla { -class ProgramShape; +class ProgramShapeProto; class HloProfilePrinterData; } @@ -84,7 +84,7 @@ class XlaCompiledCpuFunction { void set_result_names(const char** result_names) { result_names_ = result_names; } - void set_program_shape(const xla::ProgramShape* program_shape) { + void set_program_shape(const xla::ProgramShapeProto* program_shape) { program_shape_ = program_shape; } const xla::HloProfilePrinterData* hlo_profile_printer_data() const { @@ -122,7 +122,7 @@ class XlaCompiledCpuFunction { const char** result_names_ = nullptr; // [Optional] Arg and result shapes. - const xla::ProgramShape* program_shape_ = nullptr; + const xla::ProgramShapeProto* program_shape_ = nullptr; // [Optional] Profile printer data. Null if profiling is disabled. const xla::HloProfilePrinterData* hlo_profile_printer_data_ = nullptr; @@ -206,8 +206,14 @@ class XlaCompiledCpuFunction { // // Aliasing of argument and result buffers is not allowed, and results in // undefined behavior. - void set_arg_data(size_t index, void* data) { - buffer_table_[arg_index_table_[index]] = data; + void set_arg_data(size_t index, const void* data) { + // The const_cast is safe because the generated code does not write to arg + // buffers. + // + // buffer_table_ contains pointers to buffers that _will_ be written to by + // generated code so it would be misleading to make buffer_table_ a `const + // void**`. + buffer_table_[arg_index_table_[index]] = const_cast(data); } // ------------------------------ @@ -264,7 +270,7 @@ class XlaCompiledCpuFunction { // Returns the shape of the args and results. May return nullptr if the // program shape isn't available. - const xla::ProgramShape* ProgramShape() const { return program_shape_; } + const xla::ProgramShapeProto* ProgramShape() const { return program_shape_; } bool hlo_profiling_enabled() const { return hlo_profile_printer_data_ != nullptr; @@ -287,11 +293,6 @@ class XlaCompiledCpuFunction { // Argument i needs to be placed in buffer_table_[arg_index_to_temp_index_[i]] // for XLA generated code to be able to find it. - // - // For now we need to keep around the args_ array because there is code that - // depends on args() returning a void**. However, in the future we may remove - // args_ in favor of using buffer_table_ as the sole storage for the - // arguments. const int32* const arg_index_table_; // The number of incoming arguments. @@ -310,7 +311,7 @@ class XlaCompiledCpuFunction { // Optional metadata. const char** arg_names_ = nullptr; const char** result_names_ = nullptr; - const xla::ProgramShape* program_shape_ = nullptr; + const xla::ProgramShapeProto* program_shape_ = nullptr; const xla::HloProfilePrinterData* hlo_profile_printer_data_ = nullptr; }; diff --git a/tensorflow/compiler/tf2xla/xla_compiler.cc b/tensorflow/compiler/tf2xla/xla_compiler.cc index a08d030ce7..ee461a3c07 100644 --- a/tensorflow/compiler/tf2xla/xla_compiler.cc +++ b/tensorflow/compiler/tf2xla/xla_compiler.cc @@ -158,7 +158,8 @@ Status BuildComputation( xla::XlaBuilder* builder, xla::XlaComputation* computation, int* num_computation_outputs, int* num_nonconst_outputs, std::vector* outputs, - std::vector* resource_updates) { + std::vector* resource_updates, + xla::Shape* output_shape) { // Attach a common operator name as metadata. This has no semantic effect — it // merely makes the HLO graph more readable when visualized via TensorBoard, // since TensorBoard forms groups out of operators with similar names. @@ -176,6 +177,10 @@ Status BuildComputation( std::vector elems; elems.reserve(retvals.size()); + + // Keeps track of which retvals have layout to update. The first element is + // the output index, second element is the new layout. + std::vector> retval_to_update_layout; for (int i = 0; i < retvals.size(); ++i) { XlaCompiler::OutputDescription& output = (*outputs)[i]; const XlaExpression& retval = retvals[i]; @@ -202,10 +207,12 @@ Status BuildComputation( TF_ASSIGN_OR_RETURN(xla::Shape shape, shape_representation_fn( output.shape, output.type)); value = xla::Reshape(value, xla::AsInt64Slice(shape.dimensions())); + retval_to_update_layout.emplace_back(elems.size(), shape.layout()); } else if (it != retval_cores.end()) { // Apply the sharding to the output, if there is a core assignment. value = identity_op(value); } + elems.push_back(value); break; } @@ -297,6 +304,21 @@ Status BuildComputation( return computation_status.status(); } *computation = computation_status.ConsumeValueOrDie(); + + TF_ASSIGN_OR_RETURN(const auto& program_shape, + computation->GetProgramShape()); + *output_shape = program_shape.result(); + // Update the output layout to the layout of retval. + for (auto& update : retval_to_update_layout) { + if (!always_return_tuple && elems.size() == 1) { + *output_shape->mutable_layout() = update.second; + continue; + } + + xla::Shape* output_sub_shape = + xla::ShapeUtil::GetMutableSubshape(output_shape, {update.first}); + *output_sub_shape->mutable_layout() = update.second; + } return Status::OK(); } @@ -304,10 +326,10 @@ Status BuildComputation( bool XlaCompiler::Argument::operator==( const XlaCompiler::Argument& other) const { - if (std::tie(kind, resource_kind, type, name, initialized, tensor_array_size, + if (std::tie(kind, resource_kind, type, name, initialized, max_array_size, tensor_array_gradients) != std::tie(other.kind, other.resource_kind, other.type, other.name, - other.initialized, other.tensor_array_size, + other.initialized, other.max_array_size, other.tensor_array_gradients)) { return false; } @@ -337,8 +359,8 @@ string XlaCompiler::Argument::HumanString() const { string output = absl::StrCat("kind=resource", common, " resource_kind=", XlaResource::KindToString(resource_kind), " initialized=", initialized); - if (tensor_array_size >= 0) { - absl::StrAppend(&output, " tensor_array_size=", tensor_array_size); + if (max_array_size >= 0) { + absl::StrAppend(&output, " max_array_size=", max_array_size); } if (!tensor_array_gradients.empty()) { absl::StrAppend(&output, " tensor_array_gradients=", @@ -358,7 +380,7 @@ XlaCompiler::XlaCompiler(XlaCompiler::Options options) initialization_status_(Status::OK()), next_step_id_(1), device_(new XlaCompilationDevice(SessionOptions(), options_.device_type)), - device_mgr_({device_}) { + device_mgr_(absl::WrapUnique(device_)) { CHECK(!options_.device_type.type_string().empty()); if (options_.populate_resource_manager) { initialization_status_ = @@ -545,12 +567,12 @@ Status XlaCompiler::XLAShapeForArgument(const XlaCompiler::Argument& arg, return Status::OK(); } case XlaResource::kTensorArray: { - if (arg.tensor_array_size < 0) { + if (arg.max_array_size < 0) { return errors::InvalidArgument( - "Negative tensor_array_size in XLAShapeForArgument"); + "Negative max_array_size in XLAShapeForArgument"); } TensorShape shape; - shape.AddDim(arg.tensor_array_size); + shape.AddDim(arg.max_array_size); shape.AppendShape(arg.shape); TF_RETURN_IF_ERROR(TensorShapeToXLAShape(arg.type, shape, xla_shape)); @@ -562,12 +584,12 @@ Status XlaCompiler::XLAShapeForArgument(const XlaCompiler::Argument& arg, return Status::OK(); } case XlaResource::kStack: { - if (arg.tensor_array_size < 0) { + if (arg.max_array_size < 0) { return errors::InvalidArgument( - "Negative tensor_array_size in XLAShapeForArgument"); + "Negative max_array_size in XLAShapeForArgument"); } TensorShape shape; - shape.AddDim(arg.tensor_array_size); + shape.AddDim(arg.max_array_size); shape.AppendShape(arg.shape); xla::Shape buffer_shape; TF_RETURN_IF_ERROR( @@ -613,21 +635,23 @@ Status XlaCompiler::BuildArguments( const XlaCompiler::Argument& arg = args[i]; XlaExpression& arg_expression = (*arg_expressions)[i]; switch (arg.kind) { - case XlaCompiler::Argument::kResource: + case XlaCompiler::Argument::kResource: { TF_RET_CHECK(arg.resource_kind != XlaResource::kInvalid); // TODO(phawkins): this code assumes that resource arguments do not // alias. - XlaResource* resource; - TF_RETURN_IF_ERROR(context->CreateResource( - arg.resource_kind, i, arg.name, arg.type, arg.shape, xla::XlaOp(), - /*tensor_array_size=*/arg.tensor_array_size, - /*tensor_array_gradients=*/arg.tensor_array_gradients, &resource)); + XlaResource* resource = + context->AddResource(absl::make_unique( + arg.resource_kind, i, arg.name, arg.type, arg.shape, + xla::XlaOp(), + /*max_array_size=*/arg.max_array_size, + /*tensor_array_gradients=*/arg.tensor_array_gradients, + /*tensor_array_multiple_writes_aggregate=*/true)); arg_expression = XlaExpression::Resource(resource); if (arg.initialized) { input_mapping->push_back(i); } - break; + } case XlaCompiler::Argument::kParameter: case XlaCompiler::Argument::kToken: { input_mapping->push_back(i); @@ -901,9 +925,7 @@ Status XlaCompiler::CompileGraph(const XlaCompiler::CompileOptions& options, options_.device_type, name)); xla::XlaBuilder builder(name); - XlaContext* context = - new XlaContext(this, &builder, options_.allow_cpu_custom_calls, - &options_.shape_representation_fn); + XlaContext* context = new XlaContext(this, &builder); core::ScopedUnref context_unref(context); std::vector real_args(args.begin(), args.end()); @@ -988,23 +1010,12 @@ Status XlaCompiler::CompileGraph(const XlaCompiler::CompileOptions& options, options.return_updated_values_for_all_resources, options.always_return_tuple, &builder, result->computation.get(), &num_computation_outputs, &num_nonconst_outputs, &result->outputs, - &result->resource_updates)); + &result->resource_updates, &result->xla_output_shape)); VLOG(2) << "Outputs: total: " << context->retvals().size() << " nonconstant: " << num_nonconst_outputs; - - // Compute the XLA output shape, if there is a computation with non-constant - // outputs. - TF_ASSIGN_OR_RETURN(std::unique_ptr computation_shape, - client()->GetComputationShape(*result->computation)); - - result->xla_output_shape.Swap(computation_shape->mutable_result()); VLOG(2) << "XLA output shape: " - << xla::ShapeUtil::HumanString(result->xla_output_shape); - - // Tensorflow expects a major-to-minor order of results. - xla::LayoutUtil::SetToDefaultLayout(&result->xla_output_shape); - + << xla::ShapeUtil::HumanStringWithLayout(result->xla_output_shape); return Status::OK(); } diff --git a/tensorflow/compiler/tf2xla/xla_compiler.h b/tensorflow/compiler/tf2xla/xla_compiler.h index 6342612468..0d801b73a8 100644 --- a/tensorflow/compiler/tf2xla/xla_compiler.h +++ b/tensorflow/compiler/tf2xla/xla_compiler.h @@ -150,7 +150,7 @@ class XlaCompiler { // For a TensorArray or Stack resource, what is the array's declared size? // (Used for lazy initialization.) - int64 tensor_array_size = -1; + int64 max_array_size = -1; // TensorArray resource parameters are passed as (array, gradient array 0, // ..., gradient array k), where the gradient arrays are in the same order diff --git a/tensorflow/compiler/tf2xla/xla_compiler_test.cc b/tensorflow/compiler/tf2xla/xla_compiler_test.cc index aaee208f63..fe2a5f5b0c 100644 --- a/tensorflow/compiler/tf2xla/xla_compiler_test.cc +++ b/tensorflow/compiler/tf2xla/xla_compiler_test.cc @@ -20,6 +20,7 @@ limitations under the License. #include "tensorflow/cc/ops/function_ops.h" #include "tensorflow/cc/ops/resource_variable_ops.h" #include "tensorflow/cc/ops/standard_ops.h" +#include "tensorflow/compiler/tf2xla/shape_util.h" #include "tensorflow/compiler/tf2xla/side_effect_util.h" #include "tensorflow/compiler/tf2xla/type_util.h" #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" @@ -649,7 +650,7 @@ TEST_F(XlaCompilerTest, CanPassTensorArraysToAndFromComputation) { args[0].initialized = true; args[0].type = DT_INT32; args[0].shape = TensorShape({}); - args[0].tensor_array_size = 2; + args[0].max_array_size = 2; args[0].tensor_array_gradients = {"grad2"}; // Compiles the graph. @@ -708,7 +709,7 @@ TEST_F(XlaCompilerTest, UnwrittenTensorArrayGradientsAreNotComputationOutputs) { args[0].initialized = true; args[0].type = DT_INT32; args[0].shape = TensorShape({}); - args[0].tensor_array_size = 2; + args[0].max_array_size = 2; args[0].tensor_array_gradients = {"grad1"}; // Compiles the graph. @@ -740,7 +741,7 @@ TEST_F(XlaCompilerTest, NewTensorArrayGradientsAreComputationOutputs) { args[0].initialized = true; args[0].type = DT_INT32; args[0].shape = TensorShape({}); - args[0].tensor_array_size = 2; + args[0].max_array_size = 2; args[0].tensor_array_gradients = {"grad1"}; // Compiles the graph. @@ -910,6 +911,82 @@ TEST_F(XlaCompilerTest, Variables) { RunAndCheckVariablesComputation(client_, result); } +TEST_F(XlaCompilerTest, ResultLayoutSingle) { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto a = ops::_Arg(scope.WithOpName("A"), DT_INT32, 0); + auto b = ops::_Retval(scope.WithOpName("RET"), a, 0); + + std::unique_ptr graph(new Graph(OpRegistry::Global())); + TF_ASSERT_OK(scope.ToGraph(graph.get())); + + // Builds a description of the arguments. + std::vector args(1); + args[0].kind = XlaCompiler::Argument::kParameter; + args[0].type = DT_INT32; + args[0].shape = TensorShape({2, 3}); + + auto options = DefaultOptions(); + // Sets the representation function to return a non-default layout. + options.shape_representation_fn = + [](const TensorShape& shape, DataType type) -> xla::StatusOr { + xla::Shape xla_shape; + TF_RETURN_IF_ERROR(TensorShapeToXLAShape(type, shape, &xla_shape)); + *xla_shape.mutable_layout() = xla::LayoutUtil::MakeLayout({0, 1}); + return xla_shape; + }; + + // Compiles the graph. + XlaCompiler compiler(options); + + XlaCompiler::CompilationResult result; + auto compile_options = XlaCompiler::CompileOptions(); + compile_options.always_return_tuple = false; + TF_ASSERT_OK(compiler.CompileGraph(compile_options, "id", std::move(graph), + args, &result)); + EXPECT_TRUE(xla::ShapeUtil::Equal( + result.xla_output_shape, + xla::ShapeUtil::MakeShapeWithLayout(xla::S32, {2, 3}, {0, 1}))); +} + +TEST_F(XlaCompilerTest, ResultLayoutMultiple) { + Scope scope = Scope::NewRootScope().ExitOnError(); + auto a = ops::_Arg(scope.WithOpName("A"), DT_INT32, 0); + auto b = ops::_Retval(scope.WithOpName("RET1"), a, 0); + auto c = ops::_Retval(scope.WithOpName("RET2"), a, 1); + + std::unique_ptr graph(new Graph(OpRegistry::Global())); + TF_ASSERT_OK(scope.ToGraph(graph.get())); + + // Builds a description of the arguments. + std::vector args(1); + args[0].kind = XlaCompiler::Argument::kParameter; + args[0].type = DT_INT32; + args[0].shape = TensorShape({2, 3}); + + auto options = DefaultOptions(); + // Sets the representation function to return a non-default layout. + options.shape_representation_fn = + [](const TensorShape& shape, DataType type) -> xla::StatusOr { + xla::Shape xla_shape; + TF_RETURN_IF_ERROR(TensorShapeToXLAShape(type, shape, &xla_shape)); + *xla_shape.mutable_layout() = xla::LayoutUtil::MakeLayout({0, 1}); + return xla_shape; + }; + + // Compiles the graph. + XlaCompiler compiler(options); + + XlaCompiler::CompilationResult result; + TF_ASSERT_OK(compiler.CompileGraph(XlaCompiler::CompileOptions(), "id", + std::move(graph), args, &result)); + xla::Shape result_shape = + xla::ShapeUtil::MakeShapeWithLayout(xla::S32, {2, 3}, {0, 1}); + + EXPECT_TRUE(xla::ShapeUtil::Equal( + result.xla_output_shape, + xla::ShapeUtil::MakeTupleShape({result_shape, result_shape}))); +} + // Tests a simple graph that reads and writes a variable. TEST_F(XlaCompilerTest, ReturnResourceHandleOnly) { Scope scope = Scope::NewRootScope().ExitOnError(); diff --git a/tensorflow/compiler/tf2xla/xla_context.cc b/tensorflow/compiler/tf2xla/xla_context.cc index 43095fbb47..a69af70503 100644 --- a/tensorflow/compiler/tf2xla/xla_context.cc +++ b/tensorflow/compiler/tf2xla/xla_context.cc @@ -54,25 +54,14 @@ const char XlaContext::kXlaContextResourceName[] = "_xla_context"; return *context; } -/* static */ XlaContext& XlaContext::Get(const XlaOpKernelContext* ctx) { - return Get(ctx->op_kernel_context()); -} - void XlaContext::set_args(std::vector args) { args_ = std::move(args); } -XlaContext::XlaContext( - XlaCompiler* compiler, xla::XlaBuilder* builder, - bool allow_cpu_custom_calls, - const std::function( - const TensorShape&, DataType)>* shape_representation_fn) - : compiler_(compiler), - builder_(builder), - allow_cpu_custom_calls_(allow_cpu_custom_calls), - shape_representation_fn_(shape_representation_fn) {} +XlaContext::XlaContext(XlaCompiler* compiler, xla::XlaBuilder* builder) + : compiler_(compiler), builder_(builder) {} -string XlaContext::DebugString() { return "TLA JIT context"; } +string XlaContext::DebugString() { return "XLA JIT context"; } void XlaContext::SetRetval(int index, const XlaExpression& expression) { if (retvals_.size() <= index) { @@ -81,21 +70,9 @@ void XlaContext::SetRetval(int index, const XlaExpression& expression) { retvals_[index] = expression; } -Status XlaContext::CreateResource( - XlaResource::Kind kind, int arg_num, string name, DataType type, - TensorShape shape, const xla::XlaOp& handle, int64 tensor_array_size, - const std::set& tensor_array_gradients, XlaResource** resource) { - resources_.emplace_back( - new XlaResource(kind, arg_num, std::move(name), type, std::move(shape), - handle, tensor_array_size, tensor_array_gradients, - /*tensor_array_multiple_writes_aggregate=*/false)); - *resource = resources_.back().get(); - return Status::OK(); -} - -xla::StatusOr XlaContext::RepresentationShape( - const TensorShape& shape, DataType type) const { - return (*shape_representation_fn_)(shape, type); +XlaResource* XlaContext::AddResource(std::unique_ptr resource) { + resources_.push_back(std::move(resource)); + return resources_.back().get(); } const xla::XlaComputation* XlaContext::GetOrCreateMax(const DataType type) { diff --git a/tensorflow/compiler/tf2xla/xla_context.h b/tensorflow/compiler/tf2xla/xla_context.h index dbfd344c9b..0767d1faac 100644 --- a/tensorflow/compiler/tf2xla/xla_context.h +++ b/tensorflow/compiler/tf2xla/xla_context.h @@ -41,14 +41,10 @@ class XlaContext : public ResourceBase { public: // Retrieves the XlaContext of the current compilation. static XlaContext& Get(const OpKernelContext* ctx); - static XlaContext& Get(const XlaOpKernelContext* ctx); // Creates a new XlaContext. See the documentation on the class data fields // for descriptions of the arguments. - XlaContext(XlaCompiler* compiler, xla::XlaBuilder* builder, - bool allow_cpu_custom_calls, - const std::function( - const TensorShape&, DataType)>* shape_representation_fn); + XlaContext(XlaCompiler* compiler, xla::XlaBuilder* builder); // Virtual method defined by ResourceBase. string DebugString() override; @@ -58,8 +54,6 @@ class XlaContext : public ResourceBase { // Returns the XlaBuilder that Ops use for compiling new expressions. xla::XlaBuilder* builder() { return builder_; } - bool allow_cpu_custom_calls() const { return allow_cpu_custom_calls_; } - const std::vector& args() const { return args_; } void set_args(std::vector args); @@ -70,25 +64,13 @@ class XlaContext : public ResourceBase { // grows the return values vector to size index+1 if it is smaller. void SetRetval(int index, const XlaExpression& expression); - // Creates a resource with resource `kind` and initial value `handle`. `name` - // is a descriptive name for use in error messages. See the `XlaResource` - // constructor for a description of the remaining arguments. - // Fails if the resource already exists. - Status CreateResource(XlaResource::Kind kind, int arg_num, string name, - DataType type, TensorShape shape, - const xla::XlaOp& handle, int64 tensor_array_size, - const std::set& tensor_array_gradients, - XlaResource** resource); + // Adds 'resource' to the set of resources owned by the context. + XlaResource* AddResource(std::unique_ptr resource); const std::vector>& resources() { return resources_; } - // Returns the XLA shape to be used to represent a variable of TF `shape` - // and `type`, or of an argument or return value of a top-level computation. - xla::StatusOr RepresentationShape(const TensorShape& shape, - DataType type) const; - // Get an XLA lambda to compute Max. This is cached in the // XlaContext since it may be used by multiple Ops. There is a // separate specialization of the computation for each DataType. @@ -118,9 +100,6 @@ class XlaContext : public ResourceBase { // The XlaBuilder used to construct the subgraph's compiled representation. xla::XlaBuilder* builder_; - // Allow ops to emit CustomCall operations for CPU. - const bool allow_cpu_custom_calls_; - // Arguments to the Tensorflow graph, indexed by _Arg index. // Includes both compile-time constant arguments and runtime parameters. std::vector args_; @@ -131,11 +110,6 @@ class XlaContext : public ResourceBase { // Holds ownership of resources. The resources are not ordered. std::vector> resources_; - // Describes the on-host shapes of parameters and return values. Also see: - // XlaDevice::Options::shape_representation_fn. - const std::function(const TensorShape&, DataType)>* - shape_representation_fn_; - // Cache of prebuilt computations indexed by their type. using ComputationMap = std::map; diff --git a/tensorflow/compiler/tf2xla/xla_helpers.cc b/tensorflow/compiler/tf2xla/xla_helpers.cc index 9a34cd8c6a..c2c0751211 100644 --- a/tensorflow/compiler/tf2xla/xla_helpers.cc +++ b/tensorflow/compiler/tf2xla/xla_helpers.cc @@ -26,7 +26,6 @@ limitations under the License. #include "tensorflow/compiler/tf2xla/xla_op_kernel.h" #include "tensorflow/compiler/xla/client/lib/arithmetic.h" #include "tensorflow/compiler/xla/client/lib/constants.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/client/xla_computation.h" #include "tensorflow/compiler/xla/types.h" @@ -216,8 +215,7 @@ DataType XlaHelpers::SumAccumulationType(const DataType& dtype) { return dtype; } -xla::XlaOp XlaHelpers::ConvertElementType(xla::XlaBuilder* const builder, - const xla::XlaOp& operand, +xla::XlaOp XlaHelpers::ConvertElementType(const xla::XlaOp& operand, const DataType new_element_type) { xla::PrimitiveType convert_to; TF_CHECK_OK(DataTypeToPrimitiveType(new_element_type, &convert_to)); diff --git a/tensorflow/compiler/tf2xla/xla_helpers.h b/tensorflow/compiler/tf2xla/xla_helpers.h index 39578144ca..4858dfee55 100644 --- a/tensorflow/compiler/tf2xla/xla_helpers.h +++ b/tensorflow/compiler/tf2xla/xla_helpers.h @@ -80,8 +80,7 @@ class XlaHelpers { // A helper for creating a ConvertElementType xla op given a DataType rather // than the xla::PrimitiveType. - static xla::XlaOp ConvertElementType(xla::XlaBuilder* const builder, - const xla::XlaOp& operand, + static xla::XlaOp ConvertElementType(const xla::XlaOp& operand, const DataType new_element_type); }; diff --git a/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function.cc b/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function.cc index 86a78ee429..fabbcd04fe 100644 --- a/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function.cc +++ b/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function.cc @@ -133,7 +133,8 @@ XlaJitCompiledCpuFunction::Compile( jit->executable_ = std::move(executable); jit->buffer_infos_ = std::move(buffer_infos); jit->arg_index_table_ = std::move(arg_index_table); - jit->program_shape_ = std::move(program_shape); + jit->program_shape_ = + absl::make_unique(program_shape->ToProto()); jit->static_data_.set_raw_function(raw_function); jit->static_data_.set_buffer_infos(jit->buffer_infos_.data()); jit->static_data_.set_num_buffers(jit->buffer_infos_.size()); diff --git a/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function.h b/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function.h index d3c8f22a80..a539205717 100644 --- a/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function.h +++ b/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function.h @@ -80,8 +80,10 @@ class XlaJitCompiledCpuFunction { std::vector arg_names_; std::vector result_names_; - // The backing data for the program shape. - std::unique_ptr program_shape_; + // The backing data for the program shape. The proto form of program shape is + // used because the program shape is serialized and embedded in the object + // file. + std::unique_ptr program_shape_; }; } // namespace tensorflow diff --git a/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function_test.cc b/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function_test.cc index 6d49298a6f..8846088678 100644 --- a/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function_test.cc +++ b/tensorflow/compiler/tf2xla/xla_jit_compiled_cpu_function_test.cc @@ -116,13 +116,13 @@ TEST(XlaJitCompiledCpuFunction, Sum) { // Check program shape. using xla::ShapeUtil; const xla::Shape s32 = ShapeUtil::MakeShape(xla::S32, {}); - const xla::ProgramShape* program_shape = function.ProgramShape(); - ASSERT_TRUE(program_shape != nullptr); - ASSERT_EQ(program_shape->parameters_size(), 2); - EXPECT_TRUE(ShapeUtil::Compatible(program_shape->parameters(0), s32)); - EXPECT_TRUE(ShapeUtil::Compatible(program_shape->parameters(1), s32)); + ASSERT_TRUE(function.ProgramShape() != nullptr); + const xla::ProgramShape program_shape(*function.ProgramShape()); + ASSERT_EQ(program_shape.parameters_size(), 2); + EXPECT_TRUE(ShapeUtil::Compatible(program_shape.parameters(0), s32)); + EXPECT_TRUE(ShapeUtil::Compatible(program_shape.parameters(1), s32)); - const xla::Shape& result = program_shape->result(); + const xla::Shape& result = program_shape.result(); ASSERT_EQ(result.element_type(), xla::TUPLE); ASSERT_EQ(ShapeUtil::TupleElementCount(result), 1); const xla::Shape& result0 = ShapeUtil::GetTupleElementShape(result, 0); diff --git a/tensorflow/compiler/tf2xla/xla_op_kernel.cc b/tensorflow/compiler/tf2xla/xla_op_kernel.cc index 8dd8def054..58808c76de 100644 --- a/tensorflow/compiler/tf2xla/xla_op_kernel.cc +++ b/tensorflow/compiler/tf2xla/xla_op_kernel.cc @@ -36,8 +36,16 @@ bool XlaOpKernelContext::ValidateInputsAreSameShape(OpKernel* op) { return context_->ValidateInputsAreSameShape(op); } +XlaContext* XlaOpKernelContext::xla_context() const { + return &XlaContext::Get(context_); +} + xla::XlaBuilder* XlaOpKernelContext::builder() const { - return XlaContext::Get(this).builder(); + return xla_context()->builder(); +} + +XlaCompiler* XlaOpKernelContext::compiler() const { + return xla_context()->compiler(); } // Retrieves an XlaExpression that was allocated by a previous Op. @@ -338,8 +346,8 @@ Status XlaOpKernelContext::ConstantInputList( namespace { Status ReadVariableInputTensor(const Tensor& tensor, DataType type, - const OpKernelContext* ctx, TensorShape* shape, - xla::XlaOp* value) { + const XlaOpKernelContext* ctx, + TensorShape* shape, xla::XlaOp* value) { const XlaExpression* expression = CastExpressionFromTensor(tensor); XlaResource* variable = expression->resource(); TF_RET_CHECK(variable != nullptr); @@ -357,10 +365,9 @@ Status ReadVariableInputTensor(const Tensor& tensor, DataType type, *shape = variable->shape(); } - XlaContext& xla_context = XlaContext::Get(ctx); - TF_ASSIGN_OR_RETURN( - xla::Shape representation_shape, - xla_context.RepresentationShape(variable->shape(), variable->type())); + TF_ASSIGN_OR_RETURN(xla::Shape representation_shape, + ctx->compiler()->options().shape_representation_fn( + variable->shape(), variable->type())); xla::Shape xla_shape; TF_RETURN_IF_ERROR( TensorShapeToXLAShape(variable->type(), variable->shape(), &xla_shape)); @@ -377,15 +384,15 @@ Status ReadVariableInputTensor(const Tensor& tensor, DataType type, Status XlaOpKernelContext::ReadVariableInput(int index, DataType type, TensorShape* shape, xla::XlaOp* value) { - return ReadVariableInputTensor(context_->input(index), type, context_, shape, + return ReadVariableInputTensor(context_->input(index), type, this, shape, value); } Status XlaOpKernelContext::ReadVariableInput(absl::string_view name, DataType type, TensorShape* shape, xla::XlaOp* value) { - return ReadVariableInputTensor(GetInputTensorByName(name), type, context_, - shape, value); + return ReadVariableInputTensor(GetInputTensorByName(name), type, this, shape, + value); } Status XlaOpKernelContext::GetVariableTypeAndShape(int index, DataType* type, @@ -464,7 +471,7 @@ Status XlaOpKernelContext::GetResourceInput(int index, XlaResource** resource) { namespace { Status AssignVariableTensor(const Tensor& tensor, DataType type, - const OpKernelContext* ctx, xla::XlaOp handle, + const XlaOpKernelContext* ctx, xla::XlaOp handle, xla::XlaBuilder* builder) { const XlaExpression* expression = CastExpressionFromTensor(tensor); XlaResource* variable = expression->resource(); @@ -481,9 +488,9 @@ Status AssignVariableTensor(const Tensor& tensor, DataType type, TF_RETURN_IF_ERROR(variable->SetTypeAndShape(type, shape)); - XlaContext& xla_context = XlaContext::Get(ctx); - TF_ASSIGN_OR_RETURN(xla::Shape representation_shape, - xla_context.RepresentationShape(shape, type)); + TF_ASSIGN_OR_RETURN( + xla::Shape representation_shape, + ctx->compiler()->options().shape_representation_fn(shape, type)); xla::Shape xla_shape; TF_RETURN_IF_ERROR(TensorShapeToXLAShape(type, shape, &xla_shape)); if (!xla::ShapeUtil::Compatible(xla_shape, representation_shape)) { @@ -498,19 +505,15 @@ Status AssignVariableTensor(const Tensor& tensor, DataType type, Status XlaOpKernelContext::AssignVariable(int input_index, DataType type, xla::XlaOp handle) { TF_RET_CHECK(handle.valid()); - return AssignVariableTensor(context_->input(input_index), type, context_, - handle, builder()); + return AssignVariableTensor(context_->input(input_index), type, this, handle, + builder()); } Status XlaOpKernelContext::AssignVariable(absl::string_view name, DataType type, xla::XlaOp handle) { TF_RET_CHECK(handle.valid()); - return AssignVariableTensor(GetInputTensorByName(name), type, context_, - handle, builder()); -} - -XlaCompiler* XlaOpKernelContext::compiler() const { - return XlaContext::Get(context_).compiler(); + return AssignVariableTensor(GetInputTensorByName(name), type, this, handle, + builder()); } void XlaOpKernelContext::CtxFailure(const Status& s) { @@ -530,22 +533,22 @@ void XlaOpKernelContext::CtxFailureWithWarning(const char* file, int line, const xla::XlaComputation* XlaOpKernelContext::GetOrCreateMax( const DataType type) { - return XlaContext::Get(context_).GetOrCreateMax(type); + return xla_context()->GetOrCreateMax(type); } const xla::XlaComputation* XlaOpKernelContext::GetOrCreateMin( const DataType type) { - return XlaContext::Get(context_).GetOrCreateMin(type); + return xla_context()->GetOrCreateMin(type); } const xla::XlaComputation* XlaOpKernelContext::GetOrCreateAdd( const DataType type) { - return XlaContext::Get(context_).GetOrCreateAdd(type); + return xla_context()->GetOrCreateAdd(type); } const xla::XlaComputation* XlaOpKernelContext::GetOrCreateMul( const DataType type) { - return XlaContext::Get(context_).GetOrCreateMul(type); + return xla_context()->GetOrCreateMul(type); } const Tensor& XlaOpKernelContext::GetInputTensorByName(absl::string_view name) { diff --git a/tensorflow/compiler/tf2xla/xla_op_kernel.h b/tensorflow/compiler/tf2xla/xla_op_kernel.h index c06efa2c47..1858844bc0 100644 --- a/tensorflow/compiler/tf2xla/xla_op_kernel.h +++ b/tensorflow/compiler/tf2xla/xla_op_kernel.h @@ -60,6 +60,8 @@ class XlaOpKernelContext { public: explicit XlaOpKernelContext(OpKernelContext* context); + XlaContext* xla_context() const; + // Returns the XLA XlaBuilder containing the output of compilation. xla::XlaBuilder* builder() const; diff --git a/tensorflow/compiler/tf2xla/xla_op_registry.cc b/tensorflow/compiler/tf2xla/xla_op_registry.cc index dcd0e9c5c1..14237df690 100644 --- a/tensorflow/compiler/tf2xla/xla_op_registry.cc +++ b/tensorflow/compiler/tf2xla/xla_op_registry.cc @@ -18,7 +18,7 @@ limitations under the License. #include #include -#include "tensorflow/compiler/jit/legacy_flags/mark_for_compilation_pass_flags.h" +#include "tensorflow/compiler/jit/flags.h" #include "tensorflow/compiler/jit/xla_cluster_util.h" #include "tensorflow/compiler/tf2xla/type_util.h" #include "tensorflow/compiler/tf2xla/xla_context.h" @@ -130,8 +130,7 @@ XlaOpRegistry::~XlaOpRegistry() = default; // Lazily register the CPU and GPU JIT devices the first time // GetCompilationDevice is called. static void* registration_init = [®istry]() { - legacy_flags::MarkForCompilationPassFlags* flags = - legacy_flags::GetMarkForCompilationPassFlags(); + MarkForCompilationPassFlags* flags = GetMarkForCompilationPassFlags(); bool cpu_global_jit = flags->tf_xla_cpu_global_jit; mutex_lock lock(registry.mutex_); diff --git a/tensorflow/compiler/tf2xla/xla_resource.cc b/tensorflow/compiler/tf2xla/xla_resource.cc index a322eb9015..48a3c01272 100644 --- a/tensorflow/compiler/tf2xla/xla_resource.cc +++ b/tensorflow/compiler/tf2xla/xla_resource.cc @@ -18,6 +18,7 @@ limitations under the License. #include #include +#include "absl/memory/memory.h" #include "tensorflow/compiler/tf2xla/shape_util.h" #include "tensorflow/compiler/tf2xla/sharding_util.h" #include "tensorflow/compiler/tf2xla/xla_context.h" @@ -39,9 +40,29 @@ namespace tensorflow { } } +/*static*/ std::unique_ptr XlaResource::CreateStack( + string name, DataType type, int64 max_size) { + return absl::make_unique( + XlaResource::kStack, /*arg_num=*/-1, std::move(name), type, TensorShape(), + /*initial_value=*/xla::XlaOp(), + /*max_array_size=*/max_size, + /*tensor_array_gradients=*/std::set{}, + /*tensor_array_multiple_writes_aggregate=*/false); +} + +/*static*/ std::unique_ptr XlaResource::CreateTensorArray( + string name, DataType type, TensorShape shape, xla::XlaOp initial_value, + int64 max_array_size) { + return absl::make_unique( + XlaResource::kTensorArray, /*arg_num=*/-1, std::move(name), type, shape, + initial_value, max_array_size, + /*tensor_array_gradients=*/std::set{}, + /*tensor_array_multiple_writes_aggregate=*/false); +} + XlaResource::XlaResource(Kind kind, int arg_num, string name, DataType type, TensorShape shape, const xla::XlaOp& initial_value, - int64 tensor_array_size, + int64 max_array_size, const std::set& tensor_array_gradients, bool tensor_array_multiple_writes_aggregate) : kind_(kind), @@ -51,7 +72,7 @@ XlaResource::XlaResource(Kind kind, int arg_num, string name, DataType type, shape_(std::move(shape)), value_(initial_value), initial_value_(initial_value), - tensor_array_size_(tensor_array_size), + max_array_size_(max_array_size), tensor_array_multiple_writes_aggregate_( tensor_array_multiple_writes_aggregate) { CHECK(kind_ != kInvalid); @@ -60,7 +81,7 @@ XlaResource::XlaResource(Kind kind, int arg_num, string name, DataType type, tensor_array_gradients_[gradient].reset(new XlaResource( /*kind=*/kTensorArray, /*arg_num=*/-1, /*name=*/absl::StrCat("TensorArrayGrad: ", name_), type_, shape_, - xla::XlaOp(), tensor_array_size_, /*tensor_array_gradients=*/{}, + xla::XlaOp(), max_array_size_, /*tensor_array_gradients=*/{}, /*tensor_array_multiple_writes_aggregate=*/true)); } } @@ -113,7 +134,7 @@ Status XlaResource::SetZeroValue(xla::XlaBuilder* builder) { } case kTensorArray: { TensorShape ta_shape; - ta_shape.AddDim(tensor_array_size_); + ta_shape.AddDim(max_array_size_); ta_shape.AppendShape(shape_); value_ = xla::Broadcast(XlaHelpers::Zero(builder, type_), ta_shape.dim_sizes()); @@ -121,7 +142,7 @@ Status XlaResource::SetZeroValue(xla::XlaBuilder* builder) { } case kStack: { TensorShape ta_shape; - ta_shape.AddDim(tensor_array_size_); + ta_shape.AddDim(max_array_size_); ta_shape.AppendShape(shape_); value_ = xla::Tuple(builder, {xla::Broadcast(XlaHelpers::Zero(builder, type_), @@ -146,14 +167,14 @@ Status XlaResource::GetOrCreateTensorArrayGradient(const string& source, std::unique_ptr& gradient = tensor_array_gradients_[source]; if (!gradient) { TensorShape ta_shape; - ta_shape.AddDim(tensor_array_size_); + ta_shape.AddDim(max_array_size_); ta_shape.AppendShape(shape_); xla::XlaOp gradient_value = xla::Broadcast(XlaHelpers::Zero(builder, type_), ta_shape.dim_sizes()); gradient.reset( new XlaResource(/*kind=*/kTensorArray, /*arg_num=*/-1, /*name=*/absl::StrCat("TensorArrayGrad: ", name_), - type_, shape_, gradient_value, tensor_array_size_, + type_, shape_, gradient_value, max_array_size_, /*tensor_array_gradients=*/{}, /*tensor_array_multiple_writes_aggregate=*/true)); } diff --git a/tensorflow/compiler/tf2xla/xla_resource.h b/tensorflow/compiler/tf2xla/xla_resource.h index 857b9a928b..736588bb8b 100644 --- a/tensorflow/compiler/tf2xla/xla_resource.h +++ b/tensorflow/compiler/tf2xla/xla_resource.h @@ -38,9 +38,18 @@ class XlaResource { }; static absl::string_view KindToString(Kind kind); + // Creates a new Stack resource. + static std::unique_ptr CreateStack(string name, DataType type, + int64 max_size); + + // Creates a new TensorArray resource. + static std::unique_ptr CreateTensorArray( + string name, DataType type, TensorShape shape, xla::XlaOp initial_value, + int64 max_array_size); + XlaResource(Kind kind, int arg_num, string name, DataType type, TensorShape shape, const xla::XlaOp& initial_value, - int64 tensor_array_size, + int64 max_array_size, const std::set& tensor_array_gradients, bool tensor_array_multiple_writes_aggregate); @@ -119,12 +128,12 @@ class XlaResource { // TODO(phawkins): refactor this code to use subclasses, rather than putting // kind-specific fields in XlaResource. - // 'tensor_array_size' stores the expected size of the TensorArray or Stack. + // 'max_array_size' stores the expected size of the TensorArray or Stack. // We need to store this since sometimes TensorArrays must be initialized // lazily since we do not know the element shape at construction time. // Used by both TensorArrays and Stacks. - int64 tensor_array_size() const { return tensor_array_size_; } - void set_tensor_array_size(int64 size) { tensor_array_size_ = size; } + int64 max_array_size() const { return max_array_size_; } + void set_max_array_size(int64 size) { max_array_size_ = size; } bool tensor_array_multiple_writes_aggregate() const { return tensor_array_multiple_writes_aggregate_; @@ -151,7 +160,7 @@ class XlaResource { xla::XlaOp value_; xla::XlaOp initial_value_; - int64 tensor_array_size_ = -1; + int64 max_array_size_ = -1; bool tensor_array_multiple_writes_aggregate_ = false; std::map> tensor_array_gradients_; diff --git a/tensorflow/compiler/xla/BUILD b/tensorflow/compiler/xla/BUILD index 91096cf1d0..4360e08579 100644 --- a/tensorflow/compiler/xla/BUILD +++ b/tensorflow/compiler/xla/BUILD @@ -226,12 +226,14 @@ cc_library( "index_util.cc", "layout_util.cc", "primitive_util.cc", + "shape.cc", "shape_util.cc", ], hdrs = [ "index_util.h", "layout_util.h", "primitive_util.h", + "shape.h", "shape_util.h", ], visibility = ["//visibility:public"], @@ -254,6 +256,23 @@ cc_library( ], ) +tf_cc_test( + name = "shape_test", + srcs = ["shape_test.cc"], + deps = [ + ":shape_util", + ":status_macros", + ":test", + ":test_helpers", + ":types", + ":util", + ":xla_data_proto", + "//tensorflow/core:lib", + "//tensorflow/core:test_main", + "@com_google_absl//absl/strings", + ], +) + tf_cc_test( name = "shape_util_test", srcs = ["shape_util_test.cc"], @@ -745,6 +764,8 @@ cc_library( "//tensorflow/core:framework_internal", "//tensorflow/core:lib", "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", + "@com_google_absl//absl/types:span", ], ) diff --git a/tensorflow/compiler/xla/array2d.h b/tensorflow/compiler/xla/array2d.h index 782c966b4c..e4aca98f67 100644 --- a/tensorflow/compiler/xla/array2d.h +++ b/tensorflow/compiler/xla/array2d.h @@ -104,7 +104,7 @@ std::unique_ptr> MakeLinspaceArray2D(double from, double to, int64 count = n1 * n2; NativeT step = static_cast((count > 1) ? (to - from) / (count - 1) : 0); - auto set = [&array, n1, n2](int64 index, NativeT value) { + auto set = [&array, n2](int64 index, NativeT value) { (*array)(index / n2, index % n2) = value; }; for (int64 i = 0; i < count - 1; ++i) { diff --git a/tensorflow/compiler/xla/client/BUILD b/tensorflow/compiler/xla/client/BUILD index 42da0ebf49..fe99564d3c 100644 --- a/tensorflow/compiler/xla/client/BUILD +++ b/tensorflow/compiler/xla/client/BUILD @@ -81,6 +81,7 @@ cc_library( "//tensorflow/core:lib", "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", + "@com_google_absl//absl/types:optional", "@com_google_absl//absl/types:span", ], ) @@ -90,11 +91,12 @@ cc_library( srcs = ["executable_build_options.cc"], hdrs = ["executable_build_options.h"], deps = [ + "//tensorflow/compiler/xla:debug_options_flags", "//tensorflow/compiler/xla:shape_util", "//tensorflow/compiler/xla:util", "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/compiler/xla:xla_proto", "//tensorflow/compiler/xla/service:device_memory_allocator", - "//tensorflow/core:lib", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", "@com_google_absl//absl/types:optional", @@ -191,6 +193,7 @@ cc_library( hdrs = ["xla_computation.h"], visibility = ["//visibility:public"], deps = [ + "//tensorflow/compiler/xla:shape_util", "//tensorflow/compiler/xla:status_macros", "//tensorflow/compiler/xla:util", "//tensorflow/compiler/xla:xla_data_proto", diff --git a/tensorflow/compiler/xla/client/client.cc b/tensorflow/compiler/xla/client/client.cc index eef2844e0d..74b76f9299 100644 --- a/tensorflow/compiler/xla/client/client.cc +++ b/tensorflow/compiler/xla/client/client.cc @@ -20,6 +20,7 @@ limitations under the License. #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" +#include "absl/types/optional.h" #include "tensorflow/compiler/xla/client/xla_computation.h" #include "tensorflow/compiler/xla/debug_options_flags.h" #include "tensorflow/compiler/xla/execution_options_util.h" @@ -42,7 +43,7 @@ StatusOr Client::Transfer(const GlobalData& data, TransferToClientRequest request; *request.mutable_data() = data.handle(); if (shape_with_layout != nullptr) { - *request.mutable_shape_with_layout() = *shape_with_layout; + *request.mutable_shape_with_layout() = shape_with_layout->ToProto(); } TransferToClientResponse response; @@ -123,7 +124,7 @@ StatusOr Client::TransferFromOutfeed( } request.set_replica_id(replica_id); if (shape_with_layout != nullptr) { - *request.mutable_shape_with_layout() = *shape_with_layout; + *request.mutable_shape_with_layout() = shape_with_layout->ToProto(); } TransferFromOutfeedResponse response; @@ -170,11 +171,14 @@ StatusOr Client::ExecuteAndTransfer( std::unique_ptr data, Execute(computation, arguments, execution_options, execution_profile)); - const Shape* shape_with_output_layout = nullptr; + absl::optional shape_with_output_layout; if (execution_options && execution_options->has_shape_with_output_layout()) { - shape_with_output_layout = &execution_options->shape_with_output_layout(); + shape_with_output_layout = + Shape(execution_options->shape_with_output_layout()); } - return Transfer(*data, shape_with_output_layout); + return Transfer(*data, shape_with_output_layout.has_value() + ? &(*shape_with_output_layout) + : nullptr); } StatusOr Client::ComputeConstant(const XlaComputation& computation, @@ -229,7 +233,7 @@ StatusOr Client::Compile( // The argument shapes affect how the computation is compiled. for (const auto& arg_shape : argument_shapes) { - *request.add_input_shape_with_layout() = arg_shape; + *request.add_input_shape_with_layout() = arg_shape.ToProto(); } CompileResponse response; @@ -458,7 +462,7 @@ StatusOr Client::GetShape(const GlobalData& data) { return s; } - return response.shape(); + return Shape(response.shape()); } StatusOr Client::ExecutionStatsAsString( diff --git a/tensorflow/compiler/xla/client/executable_build_options.cc b/tensorflow/compiler/xla/client/executable_build_options.cc index 0f1745366b..1f594e551a 100644 --- a/tensorflow/compiler/xla/client/executable_build_options.cc +++ b/tensorflow/compiler/xla/client/executable_build_options.cc @@ -16,6 +16,7 @@ limitations under the License. #include "tensorflow/compiler/xla/client/executable_build_options.h" #include "absl/strings/str_format.h" +#include "tensorflow/compiler/xla/debug_options_flags.h" #include "tensorflow/compiler/xla/shape_util.h" namespace xla { @@ -39,6 +40,13 @@ ExecutableBuildOptions& ExecutableBuildOptions::set_device_ordinal( int ExecutableBuildOptions::device_ordinal() const { return device_ordinal_; } +DebugOptions* ExecutableBuildOptions::mutable_debug_options() { + if (!has_debug_options()) { + debug_options_ = GetDebugOptionsFromFlags(); + } + return &debug_options_.value(); +} + ExecutableBuildOptions& ExecutableBuildOptions::set_result_layout( const Shape& shape_with_layout) { result_layout_set_ = true; @@ -55,68 +63,10 @@ string ExecutableBuildOptions::ToString() const { if (result_layout_set_) { result_layout = ShapeUtil::HumanStringWithLayout(result_layout_); } - string generate_hlo_graph = "nullopt"; - if (generate_hlo_graph_.has_value()) { - generate_hlo_graph = generate_hlo_graph_.value(); - } return absl::StrFormat( "ExecutableBuildOptions{device_ordinal=%d, result_layout=%s, " "generate_hlo_graph=%s}", - device_ordinal_, result_layout, generate_hlo_graph); -} - -ExecutableBuildOptions& ExecutableBuildOptions::set_generate_hlo_graph( - string regex) { - generate_hlo_graph_ = std::move(regex); - return *this; -} - -const absl::optional& ExecutableBuildOptions::generate_hlo_graph() - const { - return generate_hlo_graph_; -} - -ExecutableBuildOptions& ExecutableBuildOptions::set_dump_optimized_hlo_proto_to( - absl::string_view dirpath) { - dump_optimized_hlo_proto_to_ = string(dirpath); - return *this; -} - -const absl::optional& -ExecutableBuildOptions::dump_optimized_hlo_proto_to() const { - return dump_optimized_hlo_proto_to_; -} - -ExecutableBuildOptions& -ExecutableBuildOptions::set_dump_unoptimized_hlo_proto_to( - absl::string_view dirpath) { - dump_unoptimized_hlo_proto_to_ = string(dirpath); - return *this; -} - -const absl::optional& -ExecutableBuildOptions::dump_unoptimized_hlo_proto_to() const { - return dump_unoptimized_hlo_proto_to_; -} - -ExecutableBuildOptions& ExecutableBuildOptions::set_dump_per_pass_hlo_proto_to( - absl::string_view dirpath) { - dump_per_pass_hlo_proto_to_ = string(dirpath); - return *this; -} - -const absl::optional& -ExecutableBuildOptions::dump_per_pass_hlo_proto_to() const { - return dump_per_pass_hlo_proto_to_; -} - -ExecutableBuildOptions& ExecutableBuildOptions::set_hlo_profile(bool enabled) { - hlo_profile_ = enabled; - return *this; -} - -absl::optional ExecutableBuildOptions::hlo_profile() const { - return hlo_profile_; + device_ordinal_, result_layout, debug_options().xla_generate_hlo_graph()); } } // namespace xla diff --git a/tensorflow/compiler/xla/client/executable_build_options.h b/tensorflow/compiler/xla/client/executable_build_options.h index 93334db88b..a58090253b 100644 --- a/tensorflow/compiler/xla/client/executable_build_options.h +++ b/tensorflow/compiler/xla/client/executable_build_options.h @@ -19,7 +19,9 @@ limitations under the License. #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "tensorflow/compiler/xla/service/device_memory_allocator.h" +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/util.h" +#include "tensorflow/compiler/xla/xla.pb.h" #include "tensorflow/compiler/xla/xla_data.pb.h" namespace xla { @@ -44,6 +46,12 @@ class ExecutableBuildOptions { ExecutableBuildOptions& set_result_layout(const Shape& shape_with_layout); const Shape* result_layout() const; + // Expose access to the XLA debug options which will be passed to the + // compilation process. + bool has_debug_options() const { return debug_options_.has_value(); } + const DebugOptions& debug_options() const { return *debug_options_; } + DebugOptions* mutable_debug_options(); + // If set, this specifies an allocator that can be used to allocate temporary // space on the device during compilation. For example, the compiler might // want to run various algorithms on the device and pick the fastest one -- it @@ -55,56 +63,16 @@ class ExecutableBuildOptions { DeviceMemoryAllocator* allocator); DeviceMemoryAllocator* device_allocator() const; - // If set, specifies a regexp of HLO graphs to dump (as in DebugOptions). - ExecutableBuildOptions& set_generate_hlo_graph(string regex); - const absl::optional& generate_hlo_graph() const; - - // If set, specifies a dirpath to dump the end-of-optimization-pipeline HLO - // protobuf to (as in DebugOptions). - ExecutableBuildOptions& set_dump_optimized_hlo_proto_to( - absl::string_view dirpath); - const absl::optional& dump_optimized_hlo_proto_to() const; - - // If set, specifies a dirpath to dump the start-of-optimization-pipeline HLO - // protobuf to (as in DebugOptions). - ExecutableBuildOptions& set_dump_unoptimized_hlo_proto_to( - absl::string_view dirpath); - const absl::optional& dump_unoptimized_hlo_proto_to() const; - - // If set, specifies a dirpath to dump the per-pass-in-pipeline HLO protobufs - // to (as in DebugOptions). - ExecutableBuildOptions& set_dump_per_pass_hlo_proto_to( - absl::string_view dirpath); - const absl::optional& dump_per_pass_hlo_proto_to() const; - - // If true, specifies that we should record an HLO profile during execution - // and log it after execution (as in DebugOptions). If nullopt the default is - // used. - ExecutableBuildOptions& set_hlo_profile(bool enabled); - absl::optional hlo_profile() const; - - void add_disabled_hlo_pass(absl::string_view pass_name) { - disabled_hlo_passes_.push_back(std::string(pass_name)); - } - const absl::Span disabled_hlo_passes() const { - return disabled_hlo_passes_; - } - // Returns a string representation of the build options, suitable for // debugging. string ToString() const; private: - absl::optional hlo_profile_; int device_ordinal_ = -1; Shape result_layout_; bool result_layout_set_ = false; - absl::optional generate_hlo_graph_; - absl::optional dump_optimized_hlo_proto_to_; - absl::optional dump_unoptimized_hlo_proto_to_; - absl::optional dump_per_pass_hlo_proto_to_; + absl::optional debug_options_; DeviceMemoryAllocator* device_allocator_ = nullptr; - std::vector disabled_hlo_passes_; }; } // namespace xla diff --git a/tensorflow/compiler/xla/client/lib/BUILD b/tensorflow/compiler/xla/client/lib/BUILD index f833ddcd32..f0f530d7d7 100644 --- a/tensorflow/compiler/xla/client/lib/BUILD +++ b/tensorflow/compiler/xla/client/lib/BUILD @@ -104,13 +104,17 @@ xla_test( ) cc_library( - name = "numeric", - srcs = ["numeric.cc"], - hdrs = ["numeric.h"], + name = "matrix", + srcs = ["matrix.cc"], + hdrs = ["matrix.h"], deps = [ ":arithmetic", ":constants", + "//tensorflow/compiler/xla:shape_util", + "//tensorflow/compiler/xla:status_macros", + "//tensorflow/compiler/xla:statusor", "//tensorflow/compiler/xla:types", + "//tensorflow/compiler/xla:util", "//tensorflow/compiler/xla:xla_data_proto", "//tensorflow/compiler/xla/client:xla_builder", "@com_google_absl//absl/types:span", @@ -118,11 +122,12 @@ cc_library( ) xla_test( - name = "numeric_test", - srcs = ["numeric_test.cc"], + name = "matrix_test", + srcs = ["matrix_test.cc"], tags = ["enable_for_xla_interpreter"], deps = [ - ":numeric", + ":matrix", + ":slicing", "//tensorflow/compiler/xla:test", "//tensorflow/compiler/xla:types", "//tensorflow/compiler/xla:xla_data_proto", @@ -164,7 +169,6 @@ cc_library( deps = [ ":constants", ":math", - ":numeric", "//tensorflow/compiler/xla:util", "//tensorflow/compiler/xla:xla_data_proto", "//tensorflow/compiler/xla/client:xla_builder", @@ -173,13 +177,46 @@ cc_library( ], ) +cc_library( + name = "slicing", + srcs = ["slicing.cc"], + hdrs = ["slicing.h"], + deps = [ + "//tensorflow/compiler/xla:shape_util", + "//tensorflow/compiler/xla:status_macros", + "//tensorflow/compiler/xla:statusor", + "//tensorflow/compiler/xla:types", + "//tensorflow/compiler/xla:util", + "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/compiler/xla/client:xla_builder", + "@com_google_absl//absl/types:span", + ], +) + +xla_test( + name = "slicing_test", + srcs = ["slicing_test.cc"], + tags = ["enable_for_xla_interpreter"], + deps = [ + ":slicing", + "//tensorflow/compiler/xla:literal_util", + "//tensorflow/compiler/xla:test", + "//tensorflow/compiler/xla:types", + "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/compiler/xla/client:xla_builder", + "//tensorflow/compiler/xla/tests:client_library_test_base", + "//tensorflow/compiler/xla/tests:xla_internal_test_main", + ], +) + cc_library( name = "sorting", srcs = ["sorting.cc"], hdrs = ["sorting.h"], deps = [ - ":numeric", + "//tensorflow/compiler/xla:shape_util", "//tensorflow/compiler/xla:types", + "//tensorflow/compiler/xla:util", "//tensorflow/compiler/xla:xla_data_proto", "//tensorflow/compiler/xla/client:xla_builder", ], @@ -188,10 +225,6 @@ cc_library( xla_test( name = "sorting_test", srcs = ["sorting_test.cc"], - blacklisted_backends = [ - "cpu", - "gpu", - ], tags = ["enable_for_xla_interpreter"], deps = [ ":sorting", diff --git a/tensorflow/compiler/xla/client/lib/math.cc b/tensorflow/compiler/xla/client/lib/math.cc index 08a887a6e4..36fdda39b4 100644 --- a/tensorflow/compiler/xla/client/lib/math.cc +++ b/tensorflow/compiler/xla/client/lib/math.cc @@ -268,17 +268,16 @@ XlaOp Digamma(XlaOp input) { // Implements Banker's rounding: numbers that are equidistant between two // integers are rounded towards even. XlaOp RoundToEven(XlaOp x) { - auto half = xla::ScalarLike(x, 0.5); - auto one = xla::ScalarLike(x, 1.0); - auto two = xla::ScalarLike(x, 2.0); + auto half = ScalarLike(x, 0.5); + auto one = ScalarLike(x, 1.0); + auto two = ScalarLike(x, 2.0); - auto round_val = xla::Floor(x); + auto round_val = Floor(x); auto fraction = x - round_val; - auto nearest_even_int = round_val - two * xla::Floor(half * x); - auto is_odd = xla::Eq(nearest_even_int, one); - return xla::Select(xla::Or(xla::Gt(fraction, half), - xla::And(xla::Eq(fraction, half), is_odd)), - round_val + one, round_val); + auto nearest_even_int = round_val - two * Floor(half * x); + auto is_odd = Eq(nearest_even_int, one); + return Select(Or(Gt(fraction, half), And(Eq(fraction, half), is_odd)), + round_val + one, round_val); } // Trigonometric functions. @@ -320,4 +319,13 @@ XlaOp Cosh(XlaOp x) { return (Exp(x) + Exp(-x)) * ScalarLike(x, 0.5); } XlaOp Sinh(XlaOp x) { return (Exp(x) - Exp(-x)) * ScalarLike(x, 0.5); } +XlaOp MaybeConjugate(XlaOp x, bool conjugate) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); + auto perform_conj = shape.element_type() == C64 && conjugate; + return perform_conj ? Conj(x) : x; + }); +} + } // namespace xla diff --git a/tensorflow/compiler/xla/client/lib/math.h b/tensorflow/compiler/xla/client/lib/math.h index 3f06d04b9a..17612bf9fd 100644 --- a/tensorflow/compiler/xla/client/lib/math.h +++ b/tensorflow/compiler/xla/client/lib/math.h @@ -86,6 +86,10 @@ XlaOp Cosh(XlaOp x); // Computes the hyperbolic sine of 'x'. XlaOp Sinh(XlaOp x); +// Applies a complex conjugation operation if `a` is complex and `conjugate` +// is true, otherwise returns its argument. +xla::XlaOp MaybeConjugate(xla::XlaOp x, bool conjugate); + } // namespace xla #endif // TENSORFLOW_COMPILER_XLA_CLIENT_LIB_MATH_H_ diff --git a/tensorflow/compiler/xla/client/lib/matrix.cc b/tensorflow/compiler/xla/client/lib/matrix.cc new file mode 100644 index 0000000000..ffd744d190 --- /dev/null +++ b/tensorflow/compiler/xla/client/lib/matrix.cc @@ -0,0 +1,185 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/client/lib/matrix.h" + +#include +#include + +#include "absl/types/span.h" +#include "tensorflow/compiler/xla/client/lib/arithmetic.h" +#include "tensorflow/compiler/xla/client/lib/constants.h" +#include "tensorflow/compiler/xla/client/xla_builder.h" +#include "tensorflow/compiler/xla/shape_util.h" +#include "tensorflow/compiler/xla/status_macros.h" +#include "tensorflow/compiler/xla/statusor.h" +#include "tensorflow/compiler/xla/util.h" + +namespace xla { + +XlaOp IdentityMatrix(XlaBuilder* builder, PrimitiveType type, int64 m, + int64 n) { + auto a = Iota(builder, type, m); + auto b = Iota(builder, type, n); + auto indicator = Eq(a, Broadcast(b, {m}), /*broadcast_dimensions=*/{0}); + return ConvertElementType(indicator, type); +} + +XlaOp GetMatrixDiagonal(XlaOp x) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); + const int64 n_dims = ShapeUtil::Rank(shape); + TF_RET_CHECK(n_dims >= 2); + const int64 m = shape.dimensions(n_dims - 2); + const int64 n = shape.dimensions(n_dims - 1); + absl::Span major_dims = + AsInt64Slice(shape.dimensions()).subspan(/*pos=*/0, /*len=*/n_dims - 2); + auto a = Iota(builder, U32, n); + auto b = Iota(builder, U32, m); + auto indicator = Eq(b, Broadcast(a, {m}), /*broadcast_dimensions=*/{0}); + auto mask = Broadcast(indicator, major_dims); + + // TPUs don't support S64 add reduction at the moment. But fortunately + // OR-reductions work just as well for integers. + XlaComputation reducer = + primitive_util::IsIntegralType(shape.element_type()) + ? CreateScalarOrComputation(shape.element_type(), builder) + : CreateScalarAddComputation(shape.element_type(), builder); + + return Reduce(Select(mask, x, Zeros(builder, shape)), ScalarLike(x, 0), + reducer, {m >= n ? n_dims - 2 : n_dims - 1}); + }); +} + +XlaOp Triangle(XlaOp x, bool lower) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); + const int64 n_dims = ShapeUtil::Rank(shape); + TF_RET_CHECK(n_dims >= 2); + const int64 m = shape.dimensions(n_dims - 2); + const int64 n = shape.dimensions(n_dims - 1); + absl::Span major_dims = + AsInt64Slice(shape.dimensions()).subspan(/*pos=*/0, /*len=*/n_dims - 2); + auto a = Iota(builder, U32, n); + auto b = Iota(builder, U32, m); + XlaOp indicator; + if (lower) { + indicator = Ge(b, Broadcast(a, {m}), /*broadcast_dimensions=*/{0}); + } else { + indicator = Le(b, Broadcast(a, {m}), /*broadcast_dimensions=*/{0}); + } + auto mask = Broadcast(indicator, major_dims); + + return Select(mask, x, Zeros(builder, shape)); + }); +} + +XlaOp UpperTriangle(XlaOp x) { return Triangle(x, false); } + +XlaOp LowerTriangle(XlaOp x) { return Triangle(x, true); } + +XlaOp BatchDot(XlaOp x, XlaOp y, PrecisionConfig::Precision precision) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + TF_ASSIGN_OR_RETURN(Shape x_shape, builder->GetShape(x)); + TF_ASSIGN_OR_RETURN(Shape y_shape, builder->GetShape(y)); + + // Check that both tensors have the same number of dimensions. There must be + // at least two (the batch dimensions can be empty). + if (ShapeUtil::Rank(x_shape) != ShapeUtil::Rank(y_shape)) { + return InvalidArgument( + "Arguments to BatchDot have different ranks: %s vs. %s", + ShapeUtil::HumanString(x_shape), ShapeUtil::HumanString(y_shape)); + } + const int ndims = ShapeUtil::Rank(x_shape); + if (ndims < 2) { + return InvalidArgument( + "Arguments to BatchDot must have rank >= 2: got %d", ndims); + } + + // The batch dimensions must be equal and the matrix dimensions must be + // valid. + std::vector batch_dimension_numbers; + for (int i = 0; i < ndims - 2; ++i) { + if (x_shape.dimensions(i) != y_shape.dimensions(i)) { + return InvalidArgument( + "Dimension %d of inputs to BatchDot must be equal: shapes %s vs %s", + i, ShapeUtil::HumanString(x_shape), + ShapeUtil::HumanString(y_shape)); + } + batch_dimension_numbers.push_back(i); + } + + int x_inner_dim = ndims - 1; + int y_inner_dim = ndims - 2; + if (x_shape.dimensions(x_inner_dim) != y_shape.dimensions(y_inner_dim)) { + return InvalidArgument( + "Dimensions %d and %d of arguments to BatchDot must be equal: " + "shapes %s vs %s", + x_inner_dim, y_inner_dim, ShapeUtil::HumanString(x_shape), + ShapeUtil::HumanString(y_shape)); + } + + // Check for zero lhs/rhs dim size. + if (ShapeUtil::IsZeroElementArray(x_shape) || + ShapeUtil::IsZeroElementArray(y_shape)) { + std::vector dimensions(batch_dimension_numbers.size()); + for (int i = 0; i < batch_dimension_numbers.size(); ++i) { + dimensions[i] = x_shape.dimensions(batch_dimension_numbers[i]); + } + int x_outer_dim = ndims - 2; + int y_outer_dim = ndims - 1; + dimensions.push_back(x_shape.dimensions(x_outer_dim)); + dimensions.push_back(y_shape.dimensions(y_outer_dim)); + return Broadcast( + ConstantLiteral(builder, LiteralUtil::Zero(x_shape.element_type())), + dimensions); + } + + PrecisionConfig precision_proto; + precision_proto.add_operand_precision(precision); + precision_proto.add_operand_precision(precision); + + DotDimensionNumbers dot_dnums; + dot_dnums.add_lhs_contracting_dimensions(x_inner_dim); + dot_dnums.add_rhs_contracting_dimensions(y_inner_dim); + for (auto batch_dimension_number : batch_dimension_numbers) { + dot_dnums.add_lhs_batch_dimensions(batch_dimension_number); + dot_dnums.add_rhs_batch_dimensions(batch_dimension_number); + } + + return DotGeneral(x, y, dot_dnums, &precision_proto); + }); +} + +XlaOp TransposeInMinorDims(XlaOp x) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); + const int64 n_dims = ShapeUtil::Rank(shape); + TF_RET_CHECK(n_dims >= 2); + std::vector permutation(n_dims); + std::iota(permutation.begin(), permutation.end(), 0); + std::swap(permutation[n_dims - 1], permutation[n_dims - 2]); + return Transpose(x, permutation); + }); +} + +XlaOp MaybeTransposeInMinorDims(XlaOp x, bool transpose) { + return transpose ? TransposeInMinorDims(x) : x; +} +} // namespace xla diff --git a/tensorflow/compiler/xla/client/lib/numeric.h b/tensorflow/compiler/xla/client/lib/matrix.h similarity index 56% rename from tensorflow/compiler/xla/client/lib/numeric.h rename to tensorflow/compiler/xla/client/lib/matrix.h index efd8cdc257..8856f99c7a 100644 --- a/tensorflow/compiler/xla/client/lib/numeric.h +++ b/tensorflow/compiler/xla/client/lib/matrix.h @@ -13,8 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#ifndef TENSORFLOW_COMPILER_XLA_CLIENT_LIB_NUMERIC_H_ -#define TENSORFLOW_COMPILER_XLA_CLIENT_LIB_NUMERIC_H_ +#ifndef TENSORFLOW_COMPILER_XLA_CLIENT_LIB_MATRIX_H_ +#define TENSORFLOW_COMPILER_XLA_CLIENT_LIB_MATRIX_H_ #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/types.h" @@ -22,9 +22,6 @@ limitations under the License. namespace xla { -// Returns a rank 1 tensor of `type` containing values [0, 1, 2, ...]. -XlaOp Iota(XlaBuilder* builder, PrimitiveType type, int64 size); - // Returns an m x n matrix with 1s on the diagonal elements, zeros everywhere // else. XlaOp IdentityMatrix(XlaBuilder* builder, PrimitiveType type, int64 m, int64 n); @@ -43,6 +40,34 @@ XlaOp UpperTriangle(XlaOp x); // Get the lower triangle part of the last two dimensions XlaOp LowerTriangle(XlaOp x); +// Multiplies slices of two tensors in batches. + +// Multiplies all slices of `Tensor` `x` and `y` (each slice can be +// viewed as an element of a batch), and arranges the individual results +// in a single output tensor of the same batch size. +// +// The input tensors `x` and `y` are 2-D or higher with shape `[..., r_x, c_x]` +// and `[..., r_y, c_y]`. +// +// The output tensor is 2-D or higher with shape `[..., r_o, c_o]`, where: +// +// r_o = c_x if transpose_x else r_x +// c_o = r_y if transpose_y else c_y +// +// It is computed as: +// +// output[..., :, :] = matrix(x[..., :, :]) * matrix(y[..., :, :]) +xla::XlaOp BatchDot( + xla::XlaOp x, xla::XlaOp y, + xla::PrecisionConfig::Precision precision = xla::PrecisionConfig::DEFAULT); + +// Transposes a stack of matrices `x` by swapping the last two dimensions. +xla::XlaOp TransposeInMinorDims(xla::XlaOp x); + +// Transposes `x` in its minor dimensions if `transpose` is true, otherwise +// returns `x` unchanged. +xla::XlaOp MaybeTransposeInMinorDims(xla::XlaOp x, bool transpose); + } // namespace xla -#endif // TENSORFLOW_COMPILER_XLA_CLIENT_LIB_NUMERIC_H_ +#endif // TENSORFLOW_COMPILER_XLA_CLIENT_LIB_MATRIX_H_ diff --git a/tensorflow/compiler/xla/client/lib/numeric_test.cc b/tensorflow/compiler/xla/client/lib/matrix_test.cc similarity index 53% rename from tensorflow/compiler/xla/client/lib/numeric_test.cc rename to tensorflow/compiler/xla/client/lib/matrix_test.cc index 7d6aedd494..0593a7517a 100644 --- a/tensorflow/compiler/xla/client/lib/numeric_test.cc +++ b/tensorflow/compiler/xla/client/lib/matrix_test.cc @@ -13,7 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "tensorflow/compiler/xla/client/lib/numeric.h" +#include "tensorflow/compiler/xla/client/lib/matrix.h" + +#include "tensorflow/compiler/xla/client/lib/slicing.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/test.h" #include "tensorflow/compiler/xla/tests/client_library_test_base.h" @@ -24,13 +26,13 @@ limitations under the License. namespace xla { namespace { -class NumericTest : public ClientLibraryTestBase { +class MatrixTest : public ClientLibraryTestBase { protected: template void TestMatrixDiagonal(); }; -XLA_TEST_F(NumericTest, Triangle) { +XLA_TEST_F(MatrixTest, Triangle) { XlaBuilder builder(TestName()); Array3D input(2, 3, 4); input.FillIota(0); @@ -45,7 +47,7 @@ XLA_TEST_F(NumericTest, Triangle) { } template -void NumericTest::TestMatrixDiagonal() { +void MatrixTest::TestMatrixDiagonal() { XlaBuilder builder("GetMatrixDiagonal"); Array3D input(2, 3, 4); input.FillIota(0); @@ -58,11 +60,46 @@ void NumericTest::TestMatrixDiagonal() { ComputeAndCompareR2(&builder, expected, {a_data.get()}); } -XLA_TEST_F(NumericTest, GetMatrixDiagonal_S32) { TestMatrixDiagonal(); } +XLA_TEST_F(MatrixTest, GetMatrixDiagonal_S32) { TestMatrixDiagonal(); } + +XLA_TEST_F(MatrixTest, GetMatrixDiagonal_S64) { TestMatrixDiagonal(); } + +XLA_TEST_F(MatrixTest, GetMatrixDiagonal_F32) { TestMatrixDiagonal(); } + +Array3D BatchedAValsFull() { + return {{ + {2, 0, 1, 2}, + {3, 6, 0, 1}, + {4, 7, 9, 0}, + {5, 8, 10, 11}, + }, + { + {16, 24, 8, 12}, + {24, 61, 82, 48}, + {8, 82, 456, 106}, + {12, 48, 106, 62}, + }}; +} + +XLA_TEST_F(MatrixTest, RowBatchDot) { + XlaBuilder builder(TestName()); + + int n = 4; -XLA_TEST_F(NumericTest, GetMatrixDiagonal_S64) { TestMatrixDiagonal(); } + XlaOp a, row, index; + auto a_data = + CreateR3Parameter(BatchedAValsFull(), 0, "a", &builder, &a); + auto row_data = CreateR3Parameter({{{9, 1, 0, 0}}, {{2, 4, 0, 0}}}, 1, + "row", &builder, &row); + // Select {{3, 6, 0, 1}, {24, 61, 82, 48}} out of BatchedAValsFull(). + auto index_data = CreateR0Parameter(1, 2, "index", &builder, &index); -XLA_TEST_F(NumericTest, GetMatrixDiagonal_F32) { TestMatrixDiagonal(); } + auto l_index = DynamicSliceInMinorDims( + a, {index, ConstantR0(&builder, 0)}, {1, n}); + BatchDot(l_index, TransposeInMinorDims(row)); + ComputeAndCompareR3(&builder, {{{33}}, {{292}}}, + {a_data.get(), row_data.get(), index_data.get()}); +} } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/client/lib/numeric.cc b/tensorflow/compiler/xla/client/lib/numeric.cc deleted file mode 100644 index 377654220b..0000000000 --- a/tensorflow/compiler/xla/client/lib/numeric.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include -#include - -#include "absl/types/span.h" -#include "tensorflow/compiler/xla/client/lib/arithmetic.h" -#include "tensorflow/compiler/xla/client/lib/constants.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" - -namespace xla { - -XlaOp IdentityMatrix(XlaBuilder* builder, PrimitiveType type, int64 m, - int64 n) { - auto a = Iota(builder, type, m); - auto b = Iota(builder, type, n); - auto indicator = Eq(a, Broadcast(b, {m}), /*broadcast_dimensions=*/{0}); - return ConvertElementType(indicator, type); -} - -XlaOp GetMatrixDiagonal(XlaOp x) { - XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> StatusOr { - TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); - TF_RET_CHECK(n_dims >= 2); - const int64 m = shape.dimensions(n_dims - 2); - const int64 n = shape.dimensions(n_dims - 1); - absl::Span major_dims = - AsInt64Slice(shape.dimensions()).subspan(/*pos=*/0, /*len=*/n_dims - 2); - auto a = Iota(builder, U32, n); - auto b = Iota(builder, U32, m); - auto indicator = Eq(b, Broadcast(a, {m}), /*broadcast_dimensions=*/{0}); - auto mask = Broadcast(indicator, major_dims); - - // TPUs don't support S64 add reduction at the moment. But fortunately - // OR-reductions work just as well for integers. - XlaComputation reducer = - primitive_util::IsIntegralType(shape.element_type()) - ? CreateScalarOrComputation(shape.element_type(), builder) - : CreateScalarAddComputation(shape.element_type(), builder); - - return Reduce(Select(mask, x, Zeros(builder, shape)), ScalarLike(x, 0), - reducer, {m >= n ? n_dims - 2 : n_dims - 1}); - }); -} - -XlaOp Triangle(XlaOp x, bool lower) { - XlaBuilder* builder = x.builder(); - return builder->ReportErrorOrReturn([&]() -> StatusOr { - TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); - TF_RET_CHECK(n_dims >= 2); - const int64 m = shape.dimensions(n_dims - 2); - const int64 n = shape.dimensions(n_dims - 1); - absl::Span major_dims = - AsInt64Slice(shape.dimensions()).subspan(/*pos=*/0, /*len=*/n_dims - 2); - auto a = Iota(builder, U32, n); - auto b = Iota(builder, U32, m); - xla::XlaOp indicator; - if (lower) { - indicator = Ge(b, Broadcast(a, {m}), /*broadcast_dimensions=*/{0}); - } else { - indicator = Le(b, Broadcast(a, {m}), /*broadcast_dimensions=*/{0}); - } - auto mask = Broadcast(indicator, major_dims); - - return Select(mask, x, Zeros(builder, shape)); - }); -} - -XlaOp UpperTriangle(XlaOp x) { return Triangle(x, false); } - -XlaOp LowerTriangle(XlaOp x) { return Triangle(x, true); } - -} // namespace xla diff --git a/tensorflow/compiler/xla/client/lib/prng.cc b/tensorflow/compiler/xla/client/lib/prng.cc index c6f68c8ee2..85b9e1827d 100644 --- a/tensorflow/compiler/xla/client/lib/prng.cc +++ b/tensorflow/compiler/xla/client/lib/prng.cc @@ -18,7 +18,6 @@ limitations under the License. #include "absl/base/casts.h" #include "tensorflow/compiler/xla/client/lib/constants.h" #include "tensorflow/compiler/xla/client/lib/math.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/util.h" diff --git a/tensorflow/compiler/xla/client/lib/slicing.cc b/tensorflow/compiler/xla/client/lib/slicing.cc new file mode 100644 index 0000000000..f8c7df3ff5 --- /dev/null +++ b/tensorflow/compiler/xla/client/lib/slicing.cc @@ -0,0 +1,134 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/client/lib/slicing.h" + +namespace xla { + +XlaOp SliceInMinorDims(XlaOp x, absl::Span start, + absl::Span end) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + TF_RET_CHECK(start.size() == end.size()); + int64 n_minor_dims = start.size(); + + TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); + + const int64 n_dims = ShapeUtil::Rank(shape); + TF_RET_CHECK(n_minor_dims <= n_dims); + auto major_dims = AsInt64Slice(shape.dimensions()) + .subspan( + /*pos=*/0, + /*len=*/n_dims - n_minor_dims); + + // Prepends 0s in the major dim + std::vector padded_start(n_dims, 0); + std::copy(start.begin(), start.end(), + padded_start.begin() + major_dims.size()); + + // Prepends the shape of the major dims. + std::vector padded_end(n_dims); + std::copy(major_dims.begin(), major_dims.end(), padded_end.begin()); + std::copy(end.begin(), end.end(), padded_end.begin() + major_dims.size()); + + std::vector strides(n_dims, 1); + return Slice(x, padded_start, padded_end, strides); + }); +} + +XlaOp UpdateSlice(XlaOp x, XlaOp update, absl::Span start) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + // TODO(phawkins): make int64 work on all backends, remove the int32 cast. + std::vector start_as_int32(start.begin(), start.end()); + auto start_constant = ConstantR1(builder, start_as_int32); + TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); + const int64 n_dims = ShapeUtil::Rank(shape); + TF_ASSIGN_OR_RETURN(Shape start_constant_shape, + builder->GetShape(start_constant)); + const int64 start_length = + ShapeUtil::GetDimension(start_constant_shape, -1); + TF_RET_CHECK(start_length == n_dims); + return DynamicUpdateSlice(x, update, start_constant); + }); +} + +XlaOp UpdateSliceInMinorDims(XlaOp x, XlaOp update, + absl::Span start) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); + const int64 n_dims = ShapeUtil::Rank(shape); + const int64 n_minor_dims = start.size(); + TF_RET_CHECK(n_minor_dims <= n_dims); + std::vector padded_start(n_dims, 0); + std::copy(start.begin(), start.end(), + padded_start.begin() + (n_dims - n_minor_dims)); + return UpdateSlice(x, update, padded_start); + }); +} + +namespace { + +std::vector ConcatVectors(absl::Span xs, + absl::Span ys) { + std::vector output(xs.size() + ys.size()); + std::copy(xs.begin(), xs.end(), output.begin()); + std::copy(ys.begin(), ys.end(), output.begin() + xs.size()); + return output; +} + +XlaOp PrependZerosInMajorDims(XlaOp x, absl::Span starts) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); + const int64 n_dims = ShapeUtil::Rank(shape); + auto zero = Reshape(ConstantR0(builder, 0), {1}); + std::vector padded_starts(n_dims, zero); + for (int i = 0; i < starts.size(); ++i) { + padded_starts[n_dims - starts.size() + i] = Reshape(starts[i], {1}); + } + return ConcatInDim(builder, padded_starts, 0); + }); +} + +} // namespace + +XlaOp DynamicSliceInMinorDims(XlaOp x, absl::Span starts, + absl::Span sizes) { + XlaBuilder* builder = x.builder(); + return builder->ReportErrorOrReturn([&]() -> StatusOr { + TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); + const int64 n_dims = ShapeUtil::Rank(shape); + int64 n_minor_dims = starts.size(); + TF_RET_CHECK(n_minor_dims == sizes.size()); + TF_RET_CHECK(n_minor_dims <= n_dims); + auto major_dims = AsInt64Slice(shape.dimensions()) + .subspan( + /*pos=*/0, + /*len=*/n_dims - sizes.size()); + auto padded_starts = PrependZerosInMajorDims(x, starts); + auto padded_sizes = ConcatVectors(major_dims, sizes); + return DynamicSlice(x, padded_starts, padded_sizes); + }); +} + +XlaOp DynamicUpdateSliceInMinorDims(XlaOp x, XlaOp update, + absl::Span starts) { + auto padded_starts = PrependZerosInMajorDims(x, starts); + return DynamicUpdateSlice(x, update, padded_starts); +} + +} // namespace xla diff --git a/tensorflow/compiler/xla/client/lib/slicing.h b/tensorflow/compiler/xla/client/lib/slicing.h new file mode 100644 index 0000000000..6c482a38b5 --- /dev/null +++ b/tensorflow/compiler/xla/client/lib/slicing.h @@ -0,0 +1,48 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "absl/types/span.h" +#include "tensorflow/compiler/xla/client/xla_builder.h" +#include "tensorflow/compiler/xla/types.h" + +#ifndef TENSORFLOW_COMPILER_XLA_CLIENT_LIB_SLICING_H_ +#define TENSORFLOW_COMPILER_XLA_CLIENT_LIB_SLICING_H_ + +namespace xla { + +// Updates a slice of 'x', i.e., +// x[start[0], ..., start[n]] = update +XlaOp UpdateSlice(XlaOp x, XlaOp update, absl::Span start); + +// Performs a slice in the minor dimensions of a tensor. +// x[..., start[0]:end[0], ..., start[n]:end[n]] +XlaOp SliceInMinorDims(XlaOp x, absl::Span start, + absl::Span end); + +// Updates a slice of 'x', where 'start' contains a list of minor dimensions: +// x[..., start[0]:..., ..., start[n]:...] = update +XlaOp UpdateSliceInMinorDims(XlaOp x, XlaOp update, + absl::Span start); + +// Performs a dynamic slice in the minor dimensions of a tensor. +XlaOp DynamicSliceInMinorDims(XlaOp x, absl::Span starts, + absl::Span sizes); + +XlaOp DynamicUpdateSliceInMinorDims(XlaOp x, XlaOp update, + absl::Span starts); + +} // namespace xla + +#endif // TENSORFLOW_COMPILER_XLA_CLIENT_LIB_SLICING_H_ diff --git a/tensorflow/compiler/tf2xla/lib/util_test.cc b/tensorflow/compiler/xla/client/lib/slicing_test.cc similarity index 67% rename from tensorflow/compiler/tf2xla/lib/util_test.cc rename to tensorflow/compiler/xla/client/lib/slicing_test.cc index 442fe92c34..8d362119e0 100644 --- a/tensorflow/compiler/tf2xla/lib/util_test.cc +++ b/tensorflow/compiler/xla/client/lib/slicing_test.cc @@ -13,28 +13,19 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "tensorflow/compiler/tf2xla/lib/util.h" +#include "tensorflow/compiler/xla/client/lib/slicing.h" -#include -#include -#include - -#include "tensorflow/compiler/tf2xla/lib/batch_dot.h" -#include "tensorflow/compiler/xla/array2d.h" -#include "tensorflow/compiler/xla/literal.h" -#include "tensorflow/compiler/xla/statusor.h" +#include "tensorflow/compiler/xla/client/xla_builder.h" +#include "tensorflow/compiler/xla/literal_util.h" #include "tensorflow/compiler/xla/test.h" #include "tensorflow/compiler/xla/tests/client_library_test_base.h" -#include "tensorflow/compiler/xla/tests/literal_test_util.h" #include "tensorflow/compiler/xla/tests/test_macros.h" #include "tensorflow/compiler/xla/types.h" -#include "tensorflow/core/lib/core/status_test_util.h" -namespace tensorflow { +namespace xla { namespace { -using UtilTest = xla::ClientLibraryTestBase; -using UtilLeftLookingTest = xla::ClientLibraryTestBase; +using SlicingTest = xla::ClientLibraryTestBase; xla::Array2D BValsRight() { return {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}; @@ -63,7 +54,7 @@ xla::Array3D BatchedAValsFull() { }}; } -XLA_TEST_F(UtilTest, Simple2dLookup) { +XLA_TEST_F(SlicingTest, Simple2dLookup) { xla::XlaBuilder builder(TestName()); xla::XlaOp a, x, y; @@ -77,7 +68,7 @@ XLA_TEST_F(UtilTest, Simple2dLookup) { xla::ErrorSpec(1e-2, 1e-2)); } -XLA_TEST_F(UtilTest, Simple3dLookup) { +XLA_TEST_F(SlicingTest, Simple3dLookup) { xla::XlaBuilder builder(TestName()); xla::XlaOp a, index; @@ -92,7 +83,7 @@ XLA_TEST_F(UtilTest, Simple3dLookup) { {a_data.get(), index_data.get()}); } -XLA_TEST_F(UtilTest, SimpleSliceUpdate) { +XLA_TEST_F(SlicingTest, SimpleSliceUpdate) { xla::XlaBuilder builder(TestName()); xla::XlaOp a, b, x, y; @@ -111,26 +102,5 @@ XLA_TEST_F(UtilTest, SimpleSliceUpdate) { {a_data.get(), b_data.get(), x_data.get(), y_data.get()}); } -XLA_TEST_F(UtilTest, RowBatchDot) { - xla::XlaBuilder builder(TestName()); - - int n = 4; - - xla::XlaOp a, row, index; - auto a_data = - CreateR3Parameter(BatchedAValsFull(), 0, "a", &builder, &a); - auto row_data = CreateR3Parameter({{{9, 1, 0, 0}}, {{2, 4, 0, 0}}}, 1, - "row", &builder, &row); - // Select {{3, 6, 0, 1}, {24, 61, 82, 48}} out of BatchedAValsFull(). - auto index_data = CreateR0Parameter(1, 2, "index", &builder, &index); - - auto l_index = DynamicSliceInMinorDims( - a, {index, xla::ConstantR0(&builder, 0)}, {1, n}); - BatchDot(l_index, row, /*transpose_x=*/false, /*transpose_y=*/true); - - ComputeAndCompareR3(&builder, {{{33}}, {{292}}}, - {a_data.get(), row_data.get(), index_data.get()}); -} - } // namespace -} // namespace tensorflow +} // namespace xla diff --git a/tensorflow/compiler/xla/client/lib/sorting.cc b/tensorflow/compiler/xla/client/lib/sorting.cc index 0475fd9c94..e8553a08bb 100644 --- a/tensorflow/compiler/xla/client/lib/sorting.cc +++ b/tensorflow/compiler/xla/client/lib/sorting.cc @@ -14,7 +14,9 @@ limitations under the License. ==============================================================================*/ #include "tensorflow/compiler/xla/client/lib/sorting.h" -#include "tensorflow/compiler/xla/client/lib/numeric.h" +#include "tensorflow/compiler/xla/client/xla_builder.h" +#include "tensorflow/compiler/xla/shape_util.h" +#include "tensorflow/compiler/xla/util.h" namespace xla { @@ -23,13 +25,12 @@ XlaOp TopK(XlaOp input, int64 k) { return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape input_shape, builder->GetShape(input)); int last_dim = input_shape.dimensions_size() - 1; - int last_dim_size = input_shape.dimensions(last_dim); - XlaOp iota_s32 = Iota(builder, S32, last_dim_size); + Shape iota_shape = + ShapeUtil::MakeShape(S32, AsInt64Slice(input_shape.dimensions())); + XlaOp iota_s32 = Iota(builder, iota_shape, last_dim); auto input_dims = input_shape.dimensions(); - std::vector broadcast_dims(input_dims.begin(), input_dims.end() - 1); - XlaOp broadcast_s32 = Broadcast(iota_s32, broadcast_dims); - XlaOp sort_result = Sort(Neg(input), {broadcast_s32}); + XlaOp sort_result = Sort(Neg(input), {iota_s32}); std::vector start_indices(input_shape.dimensions_size(), 0); std::vector limit_indices(input_dims.begin(), input_dims.end()); limit_indices[last_dim] = k; diff --git a/tensorflow/compiler/xla/client/lib/sorting_test.cc b/tensorflow/compiler/xla/client/lib/sorting_test.cc index fef98c9923..27ff36c749 100644 --- a/tensorflow/compiler/xla/client/lib/sorting_test.cc +++ b/tensorflow/compiler/xla/client/lib/sorting_test.cc @@ -14,6 +14,9 @@ limitations under the License. ==============================================================================*/ #include "tensorflow/compiler/xla/client/lib/sorting.h" + +#include + #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/test.h" #include "tensorflow/compiler/xla/tests/client_library_test_base.h" @@ -41,6 +44,28 @@ XLA_TEST_F(SortingTest, TopK3From8Indices) { ComputeAndCompareR1(&builder, {0, 1, 2}, {}); } +// TODO(b/119930279): enable this test. +XLA_TEST_F(SortingTest, DISABLED_TopKFullSortMinInt) { + XlaBuilder builder(TestName()); + auto x_rev = ConstantR1(&builder, {std::numeric_limits::min(), + std::numeric_limits::min() + 1, + std::numeric_limits::max()}); + xla::GetTupleElement(xla::TopK(x_rev, 3), 1); + ComputeAndCompareR1(&builder, {2, 1, 0}, {}); +} + +XLA_TEST_F(SortingTest, NOT_TopKFullSortMinInt) { + XlaBuilder builder(TestName()); + auto x_rev = ConstantR1(&builder, {std::numeric_limits::min(), + std::numeric_limits::min() + 1, + std::numeric_limits::max()}); + xla::GetTupleElement(xla::TopK(x_rev, 3), 1); + // TopK currently negates the keys, which doesn't work correctly for + // std::numeric_limits::min(). Therefore, it will sort this key to the + // front instead of to the back. + ComputeAndCompareR1(&builder, {0, 2, 1}, {}); +} + XLA_TEST_F(SortingTest, TopKFullSort) { XlaBuilder builder(TestName()); const int kSize = 16; @@ -56,5 +81,13 @@ XLA_TEST_F(SortingTest, TopKFullSort) { ComputeAndCompareR1(&builder, inputs, {}); } +XLA_TEST_F(SortingTest, TopKFullSortWithDuplicates) { + XlaBuilder builder(TestName()); + XlaOp a; + auto a_data = CreateR1Parameter({1, 1, 2, 2, 1}, 0, "a", &builder, &a); + xla::GetTupleElement(xla::TopK(a, 5), 1); + ComputeAndCompareR1(&builder, {2, 3, 0, 1, 4}, {a_data.get()}); +} + } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/client/lib/testing.cc b/tensorflow/compiler/xla/client/lib/testing.cc index a44681f586..a95bbf2c8c 100644 --- a/tensorflow/compiler/xla/client/lib/testing.cc +++ b/tensorflow/compiler/xla/client/lib/testing.cc @@ -66,7 +66,7 @@ std::unique_ptr MakeFakeDataViaDeviceOrDie(const Shape& shape, XlaComputation computation = b.Build().ConsumeValueOrDie(); auto execution_options = CreateDefaultExecutionOptions(); - *execution_options.mutable_shape_with_output_layout() = shape; + *execution_options.mutable_shape_with_output_layout() = shape.ToProto(); return client->Execute(computation, /*arguments=*/{}, &execution_options) .ConsumeValueOrDie(); } @@ -98,8 +98,8 @@ std::vector> MakeFakeArgumentsOrDie( auto program_shape = computation.proto().host_program_shape(); std::vector> results; - for (const Shape& shape : program_shape.parameters()) { - results.push_back(MakeFakeDataOrDie(shape, client)); + for (const ShapeProto& shape : program_shape.parameters()) { + results.push_back(MakeFakeDataOrDie(Shape(shape), client)); } return results; } diff --git a/tensorflow/compiler/xla/client/local_client.cc b/tensorflow/compiler/xla/client/local_client.cc index f96b6c9c26..aaa5d6989e 100644 --- a/tensorflow/compiler/xla/client/local_client.cc +++ b/tensorflow/compiler/xla/client/local_client.cc @@ -310,4 +310,28 @@ StatusOr LocalClient::ReplicaNumberToDeviceOrdinal(int replica_number) { return local_service_->ReplicaNumberToDeviceOrdinal(replica_number); } +StatusOr LocalClient::TransferToLocalServer( + const ::xla::BorrowingLiteral& literal, int device_oridinal) { + const ::xla::Shape& shape = literal.shape(); + + TF_ASSIGN_OR_RETURN( + ::xla::ScopedShapedBuffer shaped_buffer, + backend().transfer_manager()->AllocateScopedShapedBuffer( + shape, backend().memory_allocator(), device_oridinal)); + TF_ASSIGN_OR_RETURN(auto stream, + mutable_backend()->BorrowStream(device_oridinal)); + TF_RETURN_IF_ERROR(backend().transfer_manager()->TransferLiteralToDevice( + stream.get(), literal, shaped_buffer)); + std::vector<::xla::ScopedShapedBuffer> replicated_buffer; + replicated_buffer.emplace_back(std::move(shaped_buffer)); + ::xla::TransferToServerResponse result; + TF_ASSIGN_OR_RETURN(*result.mutable_data(), + local_service_->RegisterReplicatedBuffers( + std::move(replicated_buffer), + absl::StrCat("TransferToServer literal of shape ", + ::xla::ShapeUtil::HumanString(shape)))); + + return result; +} + } // namespace xla diff --git a/tensorflow/compiler/xla/client/local_client.h b/tensorflow/compiler/xla/client/local_client.h index e49451ca97..ddb36680e8 100644 --- a/tensorflow/compiler/xla/client/local_client.h +++ b/tensorflow/compiler/xla/client/local_client.h @@ -129,6 +129,10 @@ class LocalClient : public Client { const Literal& literal, int device_ordinal, DeviceMemoryAllocator* allocator = nullptr); + // Transfer the BorrowingLiteral to the device with the given ordinal. + StatusOr TransferToLocalServer( + const ::xla::BorrowingLiteral& literal, int device_oridinal); + // Copy the data from the device contained in the given ShapedBuffer and // return as a Literal. StatusOr ShapedBufferToLiteral(const ShapedBuffer& shaped_buffer); diff --git a/tensorflow/compiler/xla/client/sharding_builder.cc b/tensorflow/compiler/xla/client/sharding_builder.cc index 176802b33e..fb9ea6ec3f 100644 --- a/tensorflow/compiler/xla/client/sharding_builder.cc +++ b/tensorflow/compiler/xla/client/sharding_builder.cc @@ -36,7 +36,7 @@ OpSharding Tile(const Shape& tile_shape, const TileAssignment& tile_assignment) { OpSharding result; result.set_type(OpSharding::Type::OpSharding_Type_OTHER); - *result.mutable_tile_shape() = tile_shape; + *result.mutable_tile_shape() = tile_shape.ToProto(); for (int64 dim : tile_assignment.dimensions()) { result.add_tile_assignment_dimensions(dim); } @@ -52,7 +52,7 @@ OpSharding Tile1D(const Shape& tile_shape, int64 num_tiles) { CHECK_EQ(ShapeUtil::Rank(tile_shape), 1); std::vector dimensions(1, num_tiles); - *result.mutable_tile_shape() = tile_shape; + *result.mutable_tile_shape() = tile_shape.ToProto(); auto& tile_dimension = (*result.mutable_tile_shape()->mutable_dimensions())[0]; tile_dimension = CeilOfRatio(static_cast(tile_dimension), num_tiles); diff --git a/tensorflow/compiler/xla/client/xla_builder.cc b/tensorflow/compiler/xla/client/xla_builder.cc index 0a587725d2..60df2ec395 100644 --- a/tensorflow/compiler/xla/client/xla_builder.cc +++ b/tensorflow/compiler/xla/client/xla_builder.cc @@ -102,7 +102,7 @@ StatusOr XlaBuilder::GetShape(const XlaOp& op) const { TF_RETURN_IF_ERROR(first_error_); TF_ASSIGN_OR_RETURN(auto instr, LookUpInstruction(op)); - return instr->shape(); + return Shape(instr->shape()); } StatusOr> XlaBuilder::GetOperandShapes( @@ -155,7 +155,7 @@ StatusOr XlaBuilder::GetProgramShape(int64 root_id) const { ProgramShape program_shape; - *program_shape.mutable_result() = root_proto->shape(); + *program_shape.mutable_result() = Shape(root_proto->shape()); // Check that the parameter numbers are continuous from 0, and add parameter // shapes and names to the program shape. @@ -172,7 +172,7 @@ StatusOr XlaBuilder::GetProgramShape(int64 root_id) const { const int64 index = instr.parameter_number(); TF_RET_CHECK(index >= 0 && index < param_count) << "invalid parameter number: " << index; - *program_shape.mutable_parameters(index) = instr.shape(); + *program_shape.mutable_parameters(index) = Shape(instr.shape()); *program_shape.mutable_parameter_names(index) = instr.name(); } } @@ -239,6 +239,19 @@ void XlaBuilder::IsConstantVisitor(const int64 op_handle, visited->insert(op_handle); } +Status XlaBuilder::SetDynamicBinding(int64 dynamic_size_param_num, + ShapeIndex dynamic_size_param_index, + int64 target_param_num, + ShapeIndex target_param_index, + int64 target_dim_num) { + TF_RETURN_IF_ERROR(dynamic_parameter_binding_.Bind( + DynamicParameterBinding::DynamicParameter{dynamic_size_param_num, + dynamic_size_param_index}, + DynamicParameterBinding::DynamicDimension{ + target_param_num, target_param_index, target_dim_num})); + return Status::OK(); +} + XlaComputation XlaBuilder::BuildAndNoteError() { DCHECK(parent_builder_ != nullptr); auto build_status = Build(); @@ -275,7 +288,8 @@ StatusOr XlaBuilder::Build(int64 root_id) { HloComputationProto entry; SetProtoIdAndName(&entry, name_, kNameSeparator, GetNextId()); - TF_ASSIGN_OR_RETURN(*entry.mutable_program_shape(), GetProgramShape(root_id)); + TF_ASSIGN_OR_RETURN(ProgramShape program_shape, GetProgramShape(root_id)); + *entry.mutable_program_shape() = program_shape.ToProto(); entry.set_root_id(root_id); for (auto& instruction : instructions_) { @@ -297,6 +311,9 @@ StatusOr XlaBuilder::Build(int64 root_id) { } module->add_computations()->Swap(&entry); + *(module->mutable_dynamic_parameter_binding()) = + dynamic_parameter_binding_.ToProto(); + // Clear data held by this builder. this->instructions_.clear(); this->handle_to_index_.clear(); @@ -312,7 +329,7 @@ StatusOr XlaBuilder::InDimBroadcast( TF_RETURN_IF_ERROR(first_error_); HloInstructionProto instr; - *instr.mutable_shape() = shape; + *instr.mutable_shape() = shape.ToProto(); for (int64 dim : broadcast_dimensions) { instr.add_dimensions(dim); } @@ -363,8 +380,9 @@ XlaOp XlaBuilder::UnaryOp(HloOpcode unop, const XlaOp& operand) { return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferUnaryOpShape(unop, operand_shape)); + *instr.mutable_shape() = shape.ToProto(); return AddInstruction(std::move(instr), unop, {operand}); }); } @@ -375,9 +393,10 @@ XlaOp XlaBuilder::BinaryOp(HloOpcode binop, const XlaOp& lhs, const XlaOp& rhs, HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& lhs_shape, GetShape(lhs)); TF_ASSIGN_OR_RETURN(const Shape& rhs_shape, GetShape(rhs)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferBinaryOpShape( binop, lhs_shape, rhs_shape, broadcast_dimensions)); + *instr.mutable_shape() = shape.ToProto(); const int64 lhs_rank = ShapeUtil::Rank(lhs_shape); const int64 rhs_rank = ShapeUtil::Rank(rhs_shape); @@ -391,7 +410,7 @@ XlaOp XlaBuilder::BinaryOp(HloOpcode binop, const XlaOp& lhs, const XlaOp& rhs, const Shape& from_shape = should_broadcast_lhs ? lhs_shape : rhs_shape; std::vector to_size; - for (int64 size : instr.shape().dimensions()) { + for (int64 size : shape.dimensions()) { to_size.push_back(size); } for (int64 from_dim = 0; from_dim < ShapeUtil::Rank(from_shape); @@ -411,14 +430,14 @@ XlaOp XlaBuilder::BinaryOp(HloOpcode binop, const XlaOp& lhs, const XlaOp& rhs, } TF_ASSIGN_OR_RETURN(Shape updated_lhs_shape, GetShape(updated_lhs)); - if (!ShapeUtil::SameDimensions(instr.shape(), updated_lhs_shape)) { + if (!ShapeUtil::SameDimensions(shape, updated_lhs_shape)) { TF_ASSIGN_OR_RETURN(updated_lhs, - AddBroadcastSequence(instr.shape(), updated_lhs)); + AddBroadcastSequence(shape, updated_lhs)); } TF_ASSIGN_OR_RETURN(Shape updated_rhs_shape, GetShape(updated_rhs)); - if (!ShapeUtil::SameDimensions(instr.shape(), updated_rhs_shape)) { + if (!ShapeUtil::SameDimensions(shape, updated_rhs_shape)) { TF_ASSIGN_OR_RETURN(updated_rhs, - AddBroadcastSequence(instr.shape(), updated_rhs)); + AddBroadcastSequence(shape, updated_rhs)); } return AddInstruction(std::move(instr), binop, {updated_lhs, updated_rhs}); @@ -432,30 +451,28 @@ XlaOp XlaBuilder::TernaryOp(HloOpcode triop, const XlaOp& lhs, const XlaOp& rhs, TF_ASSIGN_OR_RETURN(const Shape& lhs_shape, GetShape(lhs)); TF_ASSIGN_OR_RETURN(const Shape& rhs_shape, GetShape(rhs)); TF_ASSIGN_OR_RETURN(const Shape& ehs_shape, GetShape(ehs)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), - ShapeInference::InferTernaryOpShape( - triop, lhs_shape, rhs_shape, ehs_shape)); + TF_ASSIGN_OR_RETURN( + Shape shape, ShapeInference::InferTernaryOpShape(triop, lhs_shape, + rhs_shape, ehs_shape)); + *instr.mutable_shape() = shape.ToProto(); XlaOp updated_lhs = lhs; XlaOp updated_rhs = rhs; XlaOp updated_ehs = ehs; - if (!ShapeUtil::IsTuple(instr.shape())) { + if (!ShapeUtil::IsTuple(shape)) { if (!ShapeUtil::IsTuple(lhs_shape) && - !ShapeUtil::SameDimensions(instr.shape(), lhs_shape)) { + !ShapeUtil::SameDimensions(shape, lhs_shape)) { // lhs is being implicitly broadcasted. Change to explicit. - TF_ASSIGN_OR_RETURN(updated_lhs, - AddBroadcastSequence(instr.shape(), lhs)); + TF_ASSIGN_OR_RETURN(updated_lhs, AddBroadcastSequence(shape, lhs)); } if (!ShapeUtil::IsTuple(rhs_shape) && - !ShapeUtil::SameDimensions(instr.shape(), rhs_shape)) { + !ShapeUtil::SameDimensions(shape, rhs_shape)) { // rhs is being implicitly broadcasted. Change to explicit. - TF_ASSIGN_OR_RETURN(updated_rhs, - AddBroadcastSequence(instr.shape(), rhs)); + TF_ASSIGN_OR_RETURN(updated_rhs, AddBroadcastSequence(shape, rhs)); } if (!ShapeUtil::IsTuple(ehs_shape) && - !ShapeUtil::SameDimensions(instr.shape(), ehs_shape)) { + !ShapeUtil::SameDimensions(shape, ehs_shape)) { // ehs is being implicitly broadcasted. Change to explicit. - TF_ASSIGN_OR_RETURN(updated_ehs, - AddBroadcastSequence(instr.shape(), ehs)); + TF_ASSIGN_OR_RETURN(updated_ehs, AddBroadcastSequence(shape, ehs)); } } return AddInstruction(std::move(instr), triop, @@ -476,7 +493,7 @@ XlaOp XlaBuilder::Mul(const XlaOp& lhs, const XlaOp& rhs, XlaOp XlaBuilder::ConstantLiteral(const LiteralSlice& literal) { return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; - *instr.mutable_shape() = literal.shape(); + *instr.mutable_shape() = literal.shape().ToProto(); *instr.mutable_literal() = literal.ToProto(); return AddInstruction(std::move(instr), HloOpcode::kConstant); }); @@ -485,7 +502,7 @@ XlaOp XlaBuilder::ConstantLiteral(const LiteralSlice& literal) { XlaOp XlaBuilder::Iota(const Shape& shape, int64 iota_dimension) { return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; - *instr.mutable_shape() = shape; + *instr.mutable_shape() = shape.ToProto(); instr.add_dimensions(iota_dimension); return AddInstruction(std::move(instr), HloOpcode::kIota); }); @@ -505,10 +522,10 @@ XlaOp XlaBuilder::Call(const XlaComputation& computation, [](const Shape& shape) { return &shape; }); TF_ASSIGN_OR_RETURN(const ProgramShape& called_program_shape, computation.GetProgramShape()); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferCallShape(operand_shape_ptrs, - /*to_apply=*/called_program_shape)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferCallShape( + operand_shape_ptrs, + /*to_apply=*/called_program_shape)); + *instr.mutable_shape() = shape.ToProto(); AddCalledComputation(computation, &instr); @@ -526,7 +543,7 @@ XlaOp XlaBuilder::Parameter(int64 parameter_number, const Shape& shape, } instr.set_parameter_number(parameter_number); instr.set_name(name); - *instr.mutable_shape() = shape; + *instr.mutable_shape() = shape.ToProto(); return AddInstruction(std::move(instr), HloOpcode::kParameter); }); } @@ -556,27 +573,35 @@ XlaOp XlaBuilder::Broadcast(const XlaOp& operand, } XlaOp XlaBuilder::BroadcastInDim( - const XlaOp& operand, const Shape& shape, + const XlaOp& operand, const absl::Span out_dim_size, const absl::Span broadcast_dimensions) { return ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_RETURN_IF_ERROR(ShapeInference::InferBroadcastShape(operand_shape, shape, - broadcast_dimensions) + // Output shape, in the case of degenerate broadcast, the out_dim_size is + // not necessarily the same as the dimension sizes of the output shape. + const auto& output_shape = + ShapeUtil::MakeShape(operand_shape.element_type(), out_dim_size); + + TF_RETURN_IF_ERROR(ShapeInference::InferBroadcastShape( + operand_shape, output_shape, broadcast_dimensions) .status()); - std::vector in_dim_size(ShapeUtil::Rank(shape)); - absl::c_copy(shape.dimensions(), in_dim_size.begin()); + std::vector in_dim_size(out_dim_size.begin(), out_dim_size.end()); for (int i = 0; i < broadcast_dimensions.size(); i++) { in_dim_size[broadcast_dimensions[i]] = operand_shape.dimensions(i); } const auto& in_dim_shape = - ShapeUtil::MakeShape(shape.element_type(), in_dim_size); + ShapeUtil::MakeShape(operand_shape.element_type(), in_dim_size); TF_ASSIGN_OR_RETURN( XlaOp in_dim_broadcast, InDimBroadcast(in_dim_shape, operand, broadcast_dimensions)); - if (ShapeUtil::Equal(in_dim_shape, shape)) { + + // If broadcast is not degenerate, return broadcasted result. + if (ShapeUtil::Equal(in_dim_shape, output_shape)) { return in_dim_broadcast; } - return AddBroadcastSequence(shape, in_dim_broadcast); + + // Otherwise handle degenerate broadcast case. + return AddBroadcastSequence(output_shape, in_dim_broadcast); }); } @@ -584,7 +609,7 @@ StatusOr XlaBuilder::Reshape(const Shape& shape, const XlaOp& operand) { TF_RETURN_IF_ERROR(first_error_); HloInstructionProto instr; - *instr.mutable_shape() = shape; + *instr.mutable_shape() = shape.ToProto(); return AddInstruction(std::move(instr), HloOpcode::kReshape, {operand}); } @@ -596,9 +621,9 @@ XlaOp XlaBuilder::Slice(const XlaOp& operand, HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferSliceShape(operand_shape, start_indices, - limit_indices, strides)); + Shape shape, ShapeInference::InferSliceShape( + operand_shape, start_indices, limit_indices, strides)); + *instr.mutable_shape() = shape.ToProto(); for (int i = 0; i < start_indices.size(); i++) { auto* slice_config = instr.add_slice_dimensions(); slice_config->set_start(start_indices[i]); @@ -633,9 +658,10 @@ XlaOp XlaBuilder::DynamicSlice(const XlaOp& operand, const XlaOp& start_indices, TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); TF_ASSIGN_OR_RETURN(const Shape& start_indices_shape, GetShape(start_indices)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferDynamicSliceShape( operand_shape, start_indices_shape, slice_sizes)); + *instr.mutable_shape() = shape.ToProto(); for (int64 size : slice_sizes) { instr.add_dynamic_slice_sizes(size); @@ -655,9 +681,10 @@ XlaOp XlaBuilder::DynamicUpdateSlice(const XlaOp& operand, const XlaOp& update, TF_ASSIGN_OR_RETURN(const Shape& update_shape, GetShape(update)); TF_ASSIGN_OR_RETURN(const Shape& start_indices_shape, GetShape(start_indices)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferDynamicUpdateSliceShape( operand_shape, update_shape, start_indices_shape)); + *instr.mutable_shape() = shape.ToProto(); return AddInstruction(std::move(instr), HloOpcode::kDynamicUpdateSlice, {operand, update, start_indices}); @@ -673,9 +700,9 @@ XlaOp XlaBuilder::ConcatInDim(absl::Span operands, TF_ASSIGN_OR_RETURN(const auto& operand_shapes, GetOperandShapes(operands)); absl::c_transform(operand_shapes, std::back_inserter(operand_shape_ptrs), [](const Shape& shape) { return &shape; }); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferConcatOpShape(operand_shape_ptrs, dimension)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferConcatOpShape( + operand_shape_ptrs, dimension)); + *instr.mutable_shape() = shape.ToProto(); instr.add_dimensions(dimension); @@ -692,10 +719,9 @@ XlaOp XlaBuilder::Pad(const XlaOp& operand, const XlaOp& padding_value, TF_ASSIGN_OR_RETURN(const Shape& padding_value_shape, GetShape(padding_value)); TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferPadShape(operand_shape, padding_value_shape, - padding_config)); - + Shape shape, ShapeInference::InferPadShape( + operand_shape, padding_value_shape, padding_config)); + *instr.mutable_shape() = shape.ToProto(); *instr.mutable_padding_config() = padding_config; return AddInstruction(std::move(instr), HloOpcode::kPad, @@ -708,7 +734,7 @@ XlaOp XlaBuilder::Reshape(const XlaOp& operand, absl::Span new_sizes) { return ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN(const Shape& shape, + TF_ASSIGN_OR_RETURN(const Shape shape, ShapeInference::InferReshapeShape( operand_shape, dimensions, new_sizes)); XlaOp transposed = IsIdentityPermutation(dimensions) @@ -721,7 +747,7 @@ XlaOp XlaBuilder::Reshape(const XlaOp& operand, XlaOp XlaBuilder::Reshape(const XlaOp& operand, absl::Span new_sizes) { return ReportErrorOrReturn([&]() -> StatusOr { - TF_ASSIGN_OR_RETURN(auto shape, GetShape(operand)); + TF_ASSIGN_OR_RETURN(Shape shape, GetShape(operand)); std::vector dimensions(shape.dimensions_size()); std::iota(dimensions.begin(), dimensions.end(), 0); return Reshape(operand, dimensions, new_sizes); @@ -771,7 +797,7 @@ XlaOp XlaBuilder::Collapse(const XlaOp& operand, void XlaBuilder::Trace(const string& tag, const XlaOp& operand) { ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; - *instr.mutable_shape() = ShapeUtil::MakeNil(); + *instr.mutable_shape() = ShapeUtil::MakeNil().ToProto(); *instr.mutable_literal() = LiteralUtil::CreateR1U8(tag).ToProto(); return AddInstruction(std::move(instr), HloOpcode::kTrace, {operand}); }); @@ -797,9 +823,10 @@ XlaOp XlaBuilder::Tuple(absl::Span elements) { TF_ASSIGN_OR_RETURN(const auto& operand_shapes, GetOperandShapes(elements)); absl::c_transform(operand_shapes, std::back_inserter(operand_shape_ptrs), [](const Shape& shape) { return &shape; }); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(const Shape shape, ShapeInference::InferVariadicOpShape( HloOpcode::kTuple, operand_shape_ptrs)); + *instr.mutable_shape() = shape.ToProto(); return AddInstruction(std::move(instr), HloOpcode::kTuple, elements); }); } @@ -814,7 +841,7 @@ XlaOp XlaBuilder::GetTupleElement(const XlaOp& tuple_data, int64 index) { ShapeUtil::HumanString(tuple_shape)); } *instr.mutable_shape() = - ShapeUtil::GetTupleElementShape(tuple_shape, index); + ShapeUtil::GetTupleElementShape(tuple_shape, index).ToProto(); instr.set_tuple_index(index); @@ -873,9 +900,10 @@ XlaOp XlaBuilder::DotGeneral(const XlaOp& lhs, const XlaOp& rhs, HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& lhs_shape, GetShape(lhs)); TF_ASSIGN_OR_RETURN(const Shape& rhs_shape, GetShape(rhs)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferDotOpShape(lhs_shape, rhs_shape, dimension_numbers)); + *instr.mutable_shape() = shape.ToProto(); *instr.mutable_dot_dimension_numbers() = dimension_numbers; if (precision_config != nullptr) { *instr.mutable_precision_config() = *precision_config; @@ -1017,10 +1045,11 @@ XlaOp XlaBuilder::ConvGeneralDilated( MakeWindow(window_dimensions, window_strides, padding, lhs_dilation, rhs_dilation)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferConvolveShape( lhs_shape, rhs_shape, feature_group_count, instr.window(), dimension_numbers)); + *instr.mutable_shape() = shape.ToProto(); *instr.mutable_convolution_dimension_numbers() = dimension_numbers; instr.set_feature_group_count(feature_group_count); @@ -1093,10 +1122,9 @@ XlaOp XlaBuilder::Fft(const XlaOp& operand, const FftType fft_type, return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferFftShape(operand_shape, fft_type, fft_length)); - + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferFftShape( + operand_shape, fft_type, fft_length)); + *instr.mutable_shape() = shape.ToProto(); instr.set_fft_type(fft_type); for (int64 i : fft_length) { instr.add_fft_length(i); @@ -1114,7 +1142,7 @@ XlaOp XlaBuilder::Infeed(const Shape& shape, const string& config) { } const Shape infeed_instruction_shape = ShapeUtil::MakeTupleShape({shape, ShapeUtil::MakeTokenShape()}); - *instr.mutable_shape() = infeed_instruction_shape; + *instr.mutable_shape() = infeed_instruction_shape.ToProto(); instr.set_infeed_config(config); if (ShapeUtil::IsArray(shape) && sharding() && @@ -1135,7 +1163,7 @@ XlaOp XlaBuilder::Infeed(const Shape& shape, const string& config) { XlaOp token; auto make_token = [&]() { HloInstructionProto token_instr; - *token_instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *token_instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); return AddInstruction(std::move(token_instr), HloOpcode::kAfterAll, {}); }; if (sharding()) { @@ -1174,7 +1202,7 @@ XlaOp XlaBuilder::Infeed(const Shape& shape, const string& config) { // TODO(b/80000000): Remove this when clients have been updated to handle // tokens. HloInstructionProto infeed_data; - *infeed_data.mutable_shape() = shape; + *infeed_data.mutable_shape() = shape.ToProto(); infeed_data.set_tuple_index(0); return AddInstruction(std::move(infeed_data), HloOpcode::kGetTupleElement, {infeed}); @@ -1190,7 +1218,7 @@ XlaOp XlaBuilder::InfeedWithToken(const XlaOp& token, const Shape& shape, } const Shape infeed_instruction_shape = ShapeUtil::MakeTupleShape({shape, ShapeUtil::MakeTokenShape()}); - *instr.mutable_shape() = infeed_instruction_shape; + *instr.mutable_shape() = infeed_instruction_shape.ToProto(); instr.set_infeed_config(config); if (ShapeUtil::IsArray(shape) && sharding() && @@ -1215,7 +1243,7 @@ void XlaBuilder::Outfeed(const XlaOp& operand, const Shape& shape_with_layout, ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; - *instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); // Check and set outfeed shape. if (!LayoutUtil::HasLayout(shape_with_layout)) { @@ -1228,14 +1256,14 @@ void XlaBuilder::Outfeed(const XlaOp& operand, const Shape& shape_with_layout, ShapeUtil::HumanStringWithLayout(shape_with_layout), ShapeUtil::HumanStringWithLayout(operand_shape)); } - *instr.mutable_outfeed_shape() = shape_with_layout; + *instr.mutable_outfeed_shape() = shape_with_layout.ToProto(); instr.set_outfeed_config(outfeed_config); // Outfeed takes a token as its second operand. Generate the token to pass // to the outfeed. HloInstructionProto token_instr; - *token_instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *token_instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); TF_ASSIGN_OR_RETURN(XlaOp token, AddInstruction(std::move(token_instr), HloOpcode::kAfterAll, {})); @@ -1249,7 +1277,7 @@ void XlaBuilder::Outfeed(const XlaOp& operand, const Shape& shape_with_layout, // TODO(b/80000000): Remove this when clients have been updated to handle // tokens. HloInstructionProto tuple_instr; - *tuple_instr.mutable_shape() = ShapeUtil::MakeNil(); + *tuple_instr.mutable_shape() = ShapeUtil::MakeNil().ToProto(); // The dummy tuple should have no sharding. { @@ -1268,7 +1296,7 @@ XlaOp XlaBuilder::OutfeedWithToken(const XlaOp& operand, const XlaOp& token, return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; - *instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); // Check and set outfeed shape. if (!LayoutUtil::HasLayout(shape_with_layout)) { @@ -1281,7 +1309,7 @@ XlaOp XlaBuilder::OutfeedWithToken(const XlaOp& operand, const XlaOp& token, ShapeUtil::HumanStringWithLayout(shape_with_layout), ShapeUtil::HumanStringWithLayout(operand_shape)); } - *instr.mutable_outfeed_shape() = shape_with_layout; + *instr.mutable_outfeed_shape() = shape_with_layout.ToProto(); instr.set_outfeed_config(outfeed_config); @@ -1293,7 +1321,7 @@ XlaOp XlaBuilder::OutfeedWithToken(const XlaOp& operand, const XlaOp& token, XlaOp XlaBuilder::CreateToken() { return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; - *instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); return AddInstruction(std::move(instr), HloOpcode::kAfterAll); }); } @@ -1303,8 +1331,17 @@ XlaOp XlaBuilder::AfterAll(absl::Span tokens) { if (tokens.empty()) { return InvalidArgument("AfterAll requires at least one operand"); } + for (int i = 0; i < tokens.size(); ++i) { + const XlaOp& operand = tokens[i]; + TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); + if (!ShapeUtil::IsToken(operand_shape)) { + return InvalidArgument( + "All operands to AfterAll must be tokens; operand %d has shape %s", + i, ShapeUtil::HumanString(operand_shape)); + } + } HloInstructionProto instr; - *instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); return AddInstruction(std::move(instr), HloOpcode::kAfterAll, tokens); }); } @@ -1321,7 +1358,7 @@ XlaOp XlaBuilder::CustomCall( "are reserved for internal use.", call_target_name); } - *instr.mutable_shape() = shape; + *instr.mutable_shape() = shape.ToProto(); instr.set_custom_call_target(call_target_name); instr.set_custom_call_opaque(opaque); if (operand_shapes_with_layout.has_value()) { @@ -1345,7 +1382,7 @@ XlaOp XlaBuilder::CustomCall( "constrained layout.", operand_num); } - *instr.add_operand_shapes_with_layout() = operand_shape; + *instr.add_operand_shapes_with_layout() = operand_shape.ToProto(); ++operand_num; } } @@ -1499,9 +1536,9 @@ XlaOp XlaBuilder::Transpose(const XlaOp& operand, return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferTransposeShape(operand_shape, permutation)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferTransposeShape( + operand_shape, permutation)); + *instr.mutable_shape() = shape.ToProto(); for (int64 dim : permutation) { instr.add_dimensions(dim); } @@ -1514,9 +1551,9 @@ XlaOp XlaBuilder::Rev(const XlaOp& operand, return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferReverseShape(operand_shape, dimensions)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferReverseShape( + operand_shape, dimensions)); + *instr.mutable_shape() = shape.ToProto(); for (int64 dim : dimensions) { instr.add_dimensions(dim); } @@ -1535,9 +1572,9 @@ XlaOp XlaBuilder::Sort(const XlaOp& keys, absl::Span values, GetOperandShapes(values)); absl::c_transform(values_shapes, std::back_inserter(operand_shape_ptrs), [](const Shape& shape) { return &shape; }); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), - ShapeInference::InferVariadicOpShape( - HloOpcode::kSort, operand_shape_ptrs)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferVariadicOpShape( + HloOpcode::kSort, operand_shape_ptrs)); + *instr.mutable_shape() = shape.ToProto(); if (dimension == -1) { TF_ASSIGN_OR_RETURN(const Shape& keys_shape, GetShape(keys)); dimension = ShapeUtil::Rank(keys_shape) - 1; @@ -1559,9 +1596,9 @@ XlaOp XlaBuilder::ConvertElementType(const XlaOp& operand, return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferConvertShape(operand_shape, new_element_type)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferConvertShape( + operand_shape, new_element_type)); + *instr.mutable_shape() = shape.ToProto(); return AddInstruction(std::move(instr), HloOpcode::kConvert, {operand}); }); } @@ -1571,9 +1608,9 @@ XlaOp XlaBuilder::BitcastConvertType(const XlaOp& operand, return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferConvertShape(operand_shape, new_element_type)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferConvertShape( + operand_shape, new_element_type)); + *instr.mutable_shape() = shape.ToProto(); return AddInstruction(std::move(instr), HloOpcode::kBitcastConvert, {operand}); }); @@ -1605,11 +1642,11 @@ XlaOp XlaBuilder::Map(absl::Span operands, TF_ASSIGN_OR_RETURN(const ProgramShape& called_program_shape, computation.GetProgramShape()); TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferMapShape(operand_shape_ptrs, called_program_shape, - dimensions)); + Shape shape, ShapeInference::InferMapShape( + operand_shape_ptrs, called_program_shape, dimensions)); + *instr.mutable_shape() = shape.ToProto(); - const Shape& output_shape = instr.shape(); + Shape output_shape(instr.shape()); const int64 output_rank = ShapeUtil::Rank(output_shape); AddCalledComputation(computation, &instr); std::vector new_operands(operands.begin(), operands.end()); @@ -1652,7 +1689,7 @@ XlaOp XlaBuilder::RngOp(RandomDistribution distribution, } TF_RETURN_IF_ERROR(ShapeUtil::ValidateShapeWithOptionalLayout(shape)); - *instr.mutable_shape() = shape; + *instr.mutable_shape() = shape.ToProto(); instr.set_distribution(distribution); @@ -1680,10 +1717,10 @@ XlaOp XlaBuilder::While(const XlaComputation& condition, TF_ASSIGN_OR_RETURN(const auto& condition_program_shape, condition.GetProgramShape()); TF_ASSIGN_OR_RETURN(const Shape& init_shape, GetShape(init)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferWhileShape(condition_program_shape, - body_program_shape, init_shape)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferWhileShape( + condition_program_shape, + body_program_shape, init_shape)); + *instr.mutable_shape() = shape.ToProto(); // Body comes before condition computation in the vector. AddCalledComputation(body, &instr); AddCalledComputation(condition, &instr); @@ -1700,10 +1737,10 @@ XlaOp XlaBuilder::Gather(const XlaOp& input, const XlaOp& start_indices, TF_ASSIGN_OR_RETURN(const Shape& input_shape, GetShape(input)); TF_ASSIGN_OR_RETURN(const Shape& start_indices_shape, GetShape(start_indices)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferGatherShape(input_shape, start_indices_shape, + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferGatherShape( + input_shape, start_indices_shape, dimension_numbers, slice_sizes)); + *instr.mutable_shape() = shape.ToProto(); *instr.mutable_gather_dimension_numbers() = dimension_numbers; for (int64 bound : slice_sizes) { @@ -1728,10 +1765,11 @@ XlaOp XlaBuilder::Scatter(const XlaOp& input, const XlaOp& scatter_indices, TF_ASSIGN_OR_RETURN(const Shape& updates_shape, GetShape(updates)); TF_ASSIGN_OR_RETURN(const ProgramShape& to_apply_shape, update_computation.GetProgramShape()); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferScatterShape( input_shape, scatter_indices_shape, updates_shape, to_apply_shape, dimension_numbers)); + *instr.mutable_shape() = shape.ToProto(); *instr.mutable_scatter_dimension_numbers() = dimension_numbers; @@ -1758,10 +1796,11 @@ XlaOp XlaBuilder::Conditional(const XlaOp& predicate, const XlaOp& true_operand, TF_ASSIGN_OR_RETURN(const ProgramShape& false_computation_shape, false_computation.GetProgramShape()); TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), + Shape shape, ShapeInference::InferConditionalShape( predicate_shape, true_operand_shape, false_operand_shape, true_computation_shape, false_computation_shape)); + *instr.mutable_shape() = shape.ToProto(); // The index of true_computation must be 0 and that of false computation // must be 1. @@ -1803,9 +1842,10 @@ XlaOp XlaBuilder::Reduce(absl::Span operands, [](const Shape& shape) { return &shape; }); TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), + Shape shape, ShapeInference::InferReduceShape( operand_shape_ptrs, dimensions_to_reduce, called_program_shape)); + *instr.mutable_shape() = shape.ToProto(); for (int64 dim : dimensions_to_reduce) { instr.add_dimensions(dim); @@ -1868,10 +1908,10 @@ XlaOp XlaBuilder::ReduceWindowWithGeneralPadding( MakeWindow(window_dimensions, window_strides, padding, /*lhs_dilation=*/base_dilations, /*rhs_dilation=*/window_dilations)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferReduceWindowShape(operand_shape, init_shape, - instr.window(), to_apply_shape)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferReduceWindowShape( + operand_shape, init_shape, + instr.window(), to_apply_shape)); + *instr.mutable_shape() = shape.ToProto(); AddCalledComputation(computation, &instr); return AddInstruction(std::move(instr), HloOpcode::kReduceWindow, @@ -1889,9 +1929,10 @@ XlaOp XlaBuilder::BatchNormTraining(const XlaOp& operand, const XlaOp& scale, TF_ASSIGN_OR_RETURN(const Shape& scale_shape, GetShape(scale)); TF_ASSIGN_OR_RETURN(const Shape& offset_shape, GetShape(offset)); TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), + Shape shape, ShapeInference::InferBatchNormTrainingShape( operand_shape, scale_shape, offset_shape, feature_index)); + *instr.mutable_shape() = shape.ToProto(); instr.set_epsilon(epsilon); instr.set_feature_index(feature_index); @@ -1913,10 +1954,11 @@ XlaOp XlaBuilder::BatchNormInference(const XlaOp& operand, const XlaOp& scale, TF_ASSIGN_OR_RETURN(const Shape& offset_shape, GetShape(offset)); TF_ASSIGN_OR_RETURN(const Shape& mean_shape, GetShape(mean)); TF_ASSIGN_OR_RETURN(const Shape& variance_shape, GetShape(variance)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), - ShapeInference::InferBatchNormInferenceShape( - operand_shape, scale_shape, offset_shape, - mean_shape, variance_shape, feature_index)); + TF_ASSIGN_OR_RETURN( + Shape shape, ShapeInference::InferBatchNormInferenceShape( + operand_shape, scale_shape, offset_shape, mean_shape, + variance_shape, feature_index)); + *instr.mutable_shape() = shape.ToProto(); instr.set_epsilon(epsilon); instr.set_feature_index(feature_index); @@ -1938,10 +1980,11 @@ XlaOp XlaBuilder::BatchNormGrad(const XlaOp& operand, const XlaOp& scale, TF_ASSIGN_OR_RETURN(const Shape& batch_mean_shape, GetShape(batch_mean)); TF_ASSIGN_OR_RETURN(const Shape& batch_var_shape, GetShape(batch_var)); TF_ASSIGN_OR_RETURN(const Shape& grad_output_shape, GetShape(grad_output)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferBatchNormGradShape( operand_shape, scale_shape, batch_mean_shape, batch_var_shape, grad_output_shape, feature_index)); + *instr.mutable_shape() = shape.ToProto(); instr.set_epsilon(epsilon); instr.set_feature_index(feature_index); @@ -1972,9 +2015,9 @@ XlaOp XlaBuilder::CrossReplicaSum( return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferCrossReplicaSumShape({&operand_shape})); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferCrossReplicaSumShape( + {&operand_shape})); + *instr.mutable_shape() = shape.ToProto(); for (const ReplicaGroup& group : replica_groups) { *instr.add_replica_groups() = group; @@ -2027,8 +2070,8 @@ XlaOp XlaBuilder::AllToAll(const XlaOp& operand, int64 split_dimension, absl::c_transform(slice_shapes, std::back_inserter(slice_shape_ptrs), [](const Shape& shape) { return &shape; }); TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferAllToAllTupleShape(slice_shape_ptrs)); + Shape shape, ShapeInference::InferAllToAllTupleShape(slice_shape_ptrs)); + *instr.mutable_shape() = shape.ToProto(); for (const ReplicaGroup& group : replica_groups) { *instr.add_replica_groups() = group; } @@ -2053,8 +2096,9 @@ XlaOp XlaBuilder::CollectivePermute( TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); HloInstructionProto instr; TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), + Shape shape, ShapeInference::InferCollectivePermuteShape(operand_shape)); + *instr.mutable_shape() = shape.ToProto(); for (const auto& pair : source_target_pairs) { auto* proto_pair = instr.add_source_target_pairs(); @@ -2103,10 +2147,11 @@ XlaOp XlaBuilder::SelectAndScatterWithGeneralPadding( TF_ASSIGN_OR_RETURN(*instr.mutable_window(), MakeWindow(window_dimensions, window_strides, padding, /*lhs_dilation=*/{}, /*rhs_dilation=*/{})); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferSelectAndScatterShape( operand_shape, select_shape, instr.window(), source_shape, init_shape, scatter_shape)); + *instr.mutable_shape() = shape.ToProto(); AddCalledComputation(select, &instr); AddCalledComputation(scatter, &instr); @@ -2121,9 +2166,10 @@ XlaOp XlaBuilder::ReducePrecision(const XlaOp& operand, const int exponent_bits, return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN(*instr.mutable_shape(), + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferReducePrecisionShape( operand_shape, exponent_bits, mantissa_bits)); + *instr.mutable_shape() = shape.ToProto(); instr.set_exponent_bits(exponent_bits); instr.set_mantissa_bits(mantissa_bits); return AddInstruction(std::move(instr), HloOpcode::kReducePrecision, @@ -2138,7 +2184,7 @@ void XlaBuilder::Send(const XlaOp& operand, const ChannelHandle& handle) { // TODO(b/80000000): Remove this when clients have been updated to handle // tokens. HloInstructionProto token_instr; - *token_instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *token_instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); TF_ASSIGN_OR_RETURN(XlaOp token, AddInstruction(std::move(token_instr), HloOpcode::kAfterAll, {})); @@ -2157,15 +2203,17 @@ XlaOp XlaBuilder::SendWithToken(const XlaOp& operand, const XlaOp& token, // token}. HloInstructionProto send_instr; TF_ASSIGN_OR_RETURN(const Shape& shape, GetShape(operand)); - *send_instr.mutable_shape() = ShapeUtil::MakeTupleShape( - {shape, ShapeUtil::MakeShape(U32, {}), ShapeUtil::MakeTokenShape()}); + *send_instr.mutable_shape() = + ShapeUtil::MakeTupleShape( + {shape, ShapeUtil::MakeShape(U32, {}), ShapeUtil::MakeTokenShape()}) + .ToProto(); send_instr.set_channel_id(handle.handle()); TF_ASSIGN_OR_RETURN(XlaOp send, AddInstruction(std::move(send_instr), HloOpcode::kSend, {operand, token})); HloInstructionProto send_done_instr; - *send_done_instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *send_done_instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); send_done_instr.set_channel_id(handle.handle()); return AddInstruction(std::move(send_done_instr), HloOpcode::kSendDone, {send}); @@ -2179,7 +2227,7 @@ XlaOp XlaBuilder::Recv(const Shape& shape, const ChannelHandle& handle) { // TODO(b/80000000): Remove this when clients have been updated to handle // tokens. HloInstructionProto token_instr; - *token_instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *token_instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); TF_ASSIGN_OR_RETURN(XlaOp token, AddInstruction(std::move(token_instr), HloOpcode::kAfterAll, {})); @@ -2190,7 +2238,7 @@ XlaOp XlaBuilder::Recv(const Shape& shape, const ChannelHandle& handle) { // TODO(b/80000000): Remove this when clients have been updated to handle // tokens. HloInstructionProto recv_data; - *recv_data.mutable_shape() = shape; + *recv_data.mutable_shape() = shape.ToProto(); recv_data.set_tuple_index(0); return AddInstruction(std::move(recv_data), HloOpcode::kGetTupleElement, {recv}); @@ -2207,15 +2255,18 @@ XlaOp XlaBuilder::RecvWithToken(const XlaOp& token, const Shape& shape, // Recv instruction produces a tuple of {receive buffer, U32 context, // token}. HloInstructionProto recv_instr; - *recv_instr.mutable_shape() = ShapeUtil::MakeTupleShape( - {shape, ShapeUtil::MakeShape(U32, {}), ShapeUtil::MakeTokenShape()}); + *recv_instr.mutable_shape() = + ShapeUtil::MakeTupleShape( + {shape, ShapeUtil::MakeShape(U32, {}), ShapeUtil::MakeTokenShape()}) + .ToProto(); recv_instr.set_channel_id(handle.handle()); TF_ASSIGN_OR_RETURN(XlaOp recv, AddInstruction(std::move(recv_instr), HloOpcode::kRecv, {token})); HloInstructionProto recv_done_instr; *recv_done_instr.mutable_shape() = - ShapeUtil::MakeTupleShape({shape, ShapeUtil::MakeTokenShape()}); + ShapeUtil::MakeTupleShape({shape, ShapeUtil::MakeTokenShape()}) + .ToProto(); recv_done_instr.set_channel_id(handle.handle()); return AddInstruction(std::move(recv_done_instr), HloOpcode::kRecvDone, {recv}); @@ -2249,9 +2300,11 @@ XlaOp XlaBuilder::SendToHost(const XlaOp& operand, const XlaOp& token, // Send instruction produces a tuple of {aliased operand, U32 context, // token}. HloInstructionProto send_instr; - *send_instr.mutable_shape() = ShapeUtil::MakeTupleShape( - {shape_with_layout, ShapeUtil::MakeShape(U32, {}), - ShapeUtil::MakeTokenShape()}); + *send_instr.mutable_shape() = + ShapeUtil::MakeTupleShape({shape_with_layout, + ShapeUtil::MakeShape(U32, {}), + ShapeUtil::MakeTokenShape()}) + .ToProto(); send_instr.set_channel_id(handle.handle()); send_instr.set_is_host_transfer(true); TF_ASSIGN_OR_RETURN(XlaOp send, @@ -2259,7 +2312,7 @@ XlaOp XlaBuilder::SendToHost(const XlaOp& operand, const XlaOp& token, {operand, token})); HloInstructionProto send_done_instr; - *send_done_instr.mutable_shape() = ShapeUtil::MakeTokenShape(); + *send_done_instr.mutable_shape() = ShapeUtil::MakeTokenShape().ToProto(); send_done_instr.set_channel_id(handle.handle()); send_done_instr.set_is_host_transfer(true); return AddInstruction(std::move(send_done_instr), HloOpcode::kSendDone, @@ -2288,8 +2341,10 @@ XlaOp XlaBuilder::RecvFromHost(const XlaOp& token, const Shape& shape, // Recv instruction produces a tuple of {receive buffer, U32 context, // token}. HloInstructionProto recv_instr; - *recv_instr.mutable_shape() = ShapeUtil::MakeTupleShape( - {shape, ShapeUtil::MakeShape(U32, {}), ShapeUtil::MakeTokenShape()}); + *recv_instr.mutable_shape() = + ShapeUtil::MakeTupleShape( + {shape, ShapeUtil::MakeShape(U32, {}), ShapeUtil::MakeTokenShape()}) + .ToProto(); recv_instr.set_channel_id(handle.handle()); recv_instr.set_is_host_transfer(true); TF_ASSIGN_OR_RETURN(XlaOp recv, AddInstruction(std::move(recv_instr), @@ -2297,7 +2352,8 @@ XlaOp XlaBuilder::RecvFromHost(const XlaOp& token, const Shape& shape, HloInstructionProto recv_done_instr; *recv_done_instr.mutable_shape() = - ShapeUtil::MakeTupleShape({shape, ShapeUtil::MakeTokenShape()}); + ShapeUtil::MakeTupleShape({shape, ShapeUtil::MakeTokenShape()}) + .ToProto(); recv_done_instr.set_channel_id(handle.handle()); recv_done_instr.set_is_host_transfer(true); return AddInstruction(std::move(recv_done_instr), HloOpcode::kRecvDone, @@ -2309,9 +2365,9 @@ XlaOp XlaBuilder::GetDimensionSize(const XlaOp& operand, int64 dimension) { return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const auto& operand_shape, GetShape(operand)); - TF_ASSIGN_OR_RETURN( - *instr.mutable_shape(), - ShapeInference::InferGetDimensionSizeShape(operand_shape, dimension)); + TF_ASSIGN_OR_RETURN(Shape shape, ShapeInference::InferGetDimensionSizeShape( + operand_shape, dimension)); + *instr.mutable_shape() = shape.ToProto(); instr.add_dimensions(dimension); return AddInstruction(std::move(instr), HloOpcode::kGetDimensionSize, {operand}); @@ -2356,7 +2412,7 @@ StatusOr XlaBuilder::BuildConstantSubGraph( SetProtoIdAndName(&entry, StrCat(name_, "_compute_constant"), kNameSeparator, GetNextId()); entry.set_root_id(root->id()); - ProgramShape* program_shape = entry.mutable_program_shape(); + ProgramShapeProto* program_shape = entry.mutable_program_shape(); *program_shape->mutable_result() = root->shape(); // We use std::set to keep the instruction ids in ascending order (which is @@ -2617,9 +2673,10 @@ XlaOp Broadcast(const XlaOp& operand, absl::Span broadcast_sizes) { return operand.builder()->Broadcast(operand, broadcast_sizes); } -XlaOp BroadcastInDim(const XlaOp& operand, const Shape& shape, +XlaOp BroadcastInDim(const XlaOp& operand, + const absl::Span out_dim_size, const absl::Span broadcast_dimensions) { - return operand.builder()->BroadcastInDim(operand, shape, + return operand.builder()->BroadcastInDim(operand, out_dim_size, broadcast_dimensions); } diff --git a/tensorflow/compiler/xla/client/xla_builder.h b/tensorflow/compiler/xla/client/xla_builder.h index 68314a026e..098efb60f9 100644 --- a/tensorflow/compiler/xla/client/xla_builder.h +++ b/tensorflow/compiler/xla/client/xla_builder.h @@ -29,6 +29,7 @@ limitations under the License. #include "tensorflow/compiler/xla/client/xla_computation.h" #include "tensorflow/compiler/xla/literal.h" #include "tensorflow/compiler/xla/literal_util.h" +#include "tensorflow/compiler/xla/service/dynamic_parameter_binding.h" #include "tensorflow/compiler/xla/service/hlo.pb.h" #include "tensorflow/compiler/xla/service/hlo_opcode.h" #include "tensorflow/compiler/xla/shape_util.h" @@ -263,35 +264,30 @@ class XlaBuilder { // evaluating the computation. StatusOr IsConstant(const XlaOp& operand) const; + // Sets up binding which indicates that the `target_dim_num` in the subshape + // `target_param_index` of parameter `target_param_num` is a dynamic dimension + // and its real dynamic size is represented by `dynamic_param_index` in + // parameter `dynamic_param_num`. + // + // TODO(b/119520625): Remove this API once we have more dynamic shape infra + // ready. + Status SetDynamicBinding(int64 dynamic_size_param_num, + ShapeIndex dynamic_size_param_index, + int64 target_param_num, + ShapeIndex target_param_index, int64 target_dim_num); + private: // Build helper which takes the id of the root operation.. StatusOr Build(int64 root_id); - // Enqueues a "retrieve parameter value" instruction for a parameter that was - // passed to the computation. + // Description for the methods below can be found in the corresponding public + // functions section in this file. + XlaOp Parameter(int64 parameter_number, const Shape& shape, const string& name); - // Enqueues a constant with the value of the given literal onto the - // computation. XlaOp ConstantLiteral(const LiteralSlice& literal); - // Enqueues a constant onto the computation. Methods are templated on the - // native host type (NativeT) which corresponds to a specific XLA - // PrimitiveType as given in the following table: - // - // Native Type PrimitiveType - // ----------------------------- - // bool PRED - // int32 S32 - // int64 S64 - // uint32 U32 - // uint64 U64 - // float F32 - // double F64 - // - // Note: not all primitive types defined in xla_data.proto have a - // corresponding native type yet. template XlaOp ConstantR0(NativeT value); template @@ -321,181 +317,79 @@ class XlaBuilder { template XlaOp ConstantR4FromArray4D(const Array4D& values); - // Enqueues a rank one constant (vector) onto the computation. The vector has - // size 'length' and every element has the value 'value'. template XlaOp ConstantR1(int64 length, NativeT value); - // Adds dimensions to an array by duplicating the data in the array. - // - // The new dimensions are inserted on the left, i.e. if - // broadcast_sizes has values {a0, ..., aN} and the operand shape - // has dimensions {b0, ..., bM} then the shape of the output has - // dimensions {a0, ..., aN, b0, ..., bM}. - // - // The new dimensions index into copies of the operand, i.e. - // - // output[i0, ..., iN, j0, ..., jM] = operand[j0, ..., jM] XlaOp Broadcast(const XlaOp& operand, absl::Span broadcast_sizes); - XlaOp BroadcastInDim(const XlaOp& operand, const Shape& shape, + XlaOp BroadcastInDim(const XlaOp& operand, + const absl::Span out_dim_size, const absl::Span broadcast_dimensions); - // Enqueues a pad operation onto the computation that pads the given value on - // the edges as well as between the elements of the input. padding_config - // specifies the padding amount for each dimension. XlaOp Pad(const XlaOp& operand, const XlaOp& padding_value, const PaddingConfig& padding_config); - // Enqueues an operation onto the computation that flattens the operand based - // on the dimension order (major/slowest-varying to minor/fastest-varying) - // given, followed by reshaping it into the shape with the given dimension - // sizes (also major to minor). Conceptually, this is a limited form of - // "shape casting". XlaOp Reshape(const XlaOp& operand, absl::Span dimensions, absl::Span new_sizes); - // Enqueues an operation onto the computation that collapses the operand, from - // first to last dimension (C order), then reshapes it to the given dimension - // sizes. Conceptually, this is a limited form of "shape casting". XlaOp Reshape(const XlaOp& operand, absl::Span new_sizes); - // Wrapper for Reshape. - // Enqueues an operation to collapse the provided dimensions; e.g. an - // operand with dimensions {x=256, y=2, z=2, p=32} can be collapsed to - // {x=1024, y=32} by collapsing dims {0, 1, 2}. Collapsing dimensions must - // be a consecutive, in-order subsequence of the operand dimensions. - // - // Note that collapsing a single dimension does nothing: - // - // {256} collapsing {0} => {256} - // {1} collapsing {0} => {1} - // - // Collapsing multiple dimensions produces a single result dimension: - // - // {256, 2} collapsing {0,1} => {512} - // {256, 2, 3} collapsing {0,1} => {512, 3} - // - // This could potentially cause data to be moved -- it provides a more - // structured form of reshaping than an arbitrary Reshape operation. XlaOp Collapse(const XlaOp& operand, absl::Span dimensions); - // Enqueues a slice operation onto the computation that slices the operand - // from the start indices to the limit indices; e.g. - // - // x - // [ 0 1 2 3 ] - // y [ 4 5 6 7 ] => slice(start={1, 1}, limit={2, 3}) => [ 5 6 ] - // [ 8 9 a b ] - // - // Note that "limit" means up-to-but-not-including; i.e. [start, limit) in 1D - // range notation. - // The strides parameter determines the stride over the slice XlaOp Slice(const XlaOp& operand, absl::Span start_indices, absl::Span limit_indices, absl::Span strides); - // Enqueues a slice operation in a given dimension, taking all other - // dimensions as they are; e.g. if dimno is 1 from start_index 2 to - // limit_index 4 by 1, and the shape is f32[7,8,9], this call is short-hand - // for: - // - // array[:, 2:4:1, :] XlaOp SliceInDim(const XlaOp& operand, int64 start_index, int64 limit_index, int64 stride, int64 dimno); - // Enqueues a slice operation onto the computation that slices the 'operand' - // from dynamic start indices which are passed in 'start_indices'. - // The size of the slice in each dimension is passed in 'slice_sizes', - // which specify the end point of exclusive slice intervals in each - // dimension [start, start + size). - // The shape of 'start_indices' must be rank == 1, with dimension size - // equal to the rank of the 'operand'. - // Slice index calculations are computed modulo input dimension sizes to - // prevent dynamic start indices from generating out-of-bound array accesses. XlaOp DynamicSlice(const XlaOp& operand, const XlaOp& start_indices, absl::Span slice_sizes); - // Enqueues a dynamic update slice operation onto the computation, which - // updates a slice of 'operand' with 'update' at dynamic 'start_indices'. - // The shape of 'update' determines the shape of the slice of 'operand' - // which is updated. - // The indices specified in 'start_indices' specify the offset of the slice - // of 'operand' which is updated. - // - // update = {10, 11} // calculated at runtime. - // [1 2 3] start = {1, 1} // calculated at runtime. [1 2 3 ] - // [4 5 6] => DynamicUpdateslice(data, update, start) => [4 10 11] - // [7 8 9] [7 8 9 ] - // - // The shape of 'start_indices' must be rank == 1, with dimension size - // equal to the rank of the 'operand'. - // Slice index calculations are computed modulo update dimension sizes to - // prevent dynamic start indices from generating out-of-bound array accesses. XlaOp DynamicUpdateSlice(const XlaOp& operand, const XlaOp& update, const XlaOp& start_indices); - // Enqueues a concatenate instruction onto the computation. 'operands' must - // have >= 1 entry. XlaOp ConcatInDim(absl::Span operands, int64 dimension); - // Enqueue a tracing operation onto the computation; the computation will emit - // a logging message with the operand. void Trace(const string& tag, const XlaOp& operand); - // Enqueues a conditional-move-like select operation onto the computation; - // predicated on pred, selects between on_true and on_false. XlaOp Select(const XlaOp& pred, const XlaOp& on_true, const XlaOp& on_false); - // Enqueues a tuple-creation instruction onto the computation. XlaOp Tuple(absl::Span elements); - // Enqueues a tuple-element-get instruction onto the computation. XlaOp GetTupleElement(const XlaOp& tuple_data, int64 index); - // Enqueues an equal-to comparison instruction onto the computation. XlaOp Eq(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a not-equal comparison instruction onto the computation. XlaOp Ne(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a greater-or-equal comparison instruction onto the computation. XlaOp Ge(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a greater-than comparison instruction onto the computation. XlaOp Gt(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a less-than comparison instruction onto the computation. XlaOp Lt(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a less-or-equal comparison instruction onto the computation. XlaOp Le(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a dot instruction onto the computation. XlaOp Dot(const XlaOp& lhs, const XlaOp& rhs, const PrecisionConfig* precision_config = nullptr); - // Enqueues a general dot instruction onto the computation. XlaOp DotGeneral(const XlaOp& lhs, const XlaOp& rhs, const DotDimensionNumbers& dimension_numbers, const PrecisionConfig* precision_config = nullptr); - // Enqueues a convolution instruction onto the computation, which uses the - // default convolution dimension numbers. XlaOp Conv(const XlaOp& lhs, const XlaOp& rhs, absl::Span window_strides, Padding padding, int64 feature_group_count = 1, const PrecisionConfig* precision_config = nullptr); - // Enqueues a convolution instruction onto the computation, with the caller - // provided padding configuration in the format returned by MakePadding(). XlaOp ConvWithGeneralPadding( const XlaOp& lhs, const XlaOp& rhs, absl::Span window_strides, @@ -503,8 +397,6 @@ class XlaBuilder { int64 feature_group_count = 1, const PrecisionConfig* precision_config = nullptr); - // Enqueues a convolution instruction onto the computation, with the caller - // provided dimension numbers configuration. XlaOp ConvWithGeneralDimensions( const XlaOp& lhs, const XlaOp& rhs, absl::Span window_strides, Padding padding, @@ -512,8 +404,6 @@ class XlaBuilder { int64 feature_group_count = 1, const PrecisionConfig* precision_config = nullptr); - // Enqueues a convolution instruction onto the computation, with the caller - // provided padding configuration as well as the dimension numbers. XlaOp ConvGeneral(const XlaOp& lhs, const XlaOp& rhs, absl::Span window_strides, absl::Span> padding, @@ -521,8 +411,6 @@ class XlaBuilder { int64 feature_group_count = 1, const PrecisionConfig* precision_config = nullptr); - // Enqueues a convolution instruction onto the computation, with the caller - // provided padding configuration, dilation factors and dimension numbers. XlaOp ConvGeneralDilated(const XlaOp& lhs, const XlaOp& rhs, absl::Span window_strides, absl::Span> padding, @@ -532,80 +420,53 @@ class XlaBuilder { int64 feature_group_count = 1, const PrecisionConfig* precision_config = nullptr); - // Enqueues an FFT instruction onto the computation, of the given type and - // with the given FFT length. XlaOp Fft(const XlaOp& operand, FftType fft_type, absl::Span fft_length); - // Enqueues an infeed instruction onto the computation, which writes data of - // the given shape to the infeed buffer of the device. XlaOp Infeed(const Shape& shape, const string& config = ""); XlaOp InfeedWithToken(const XlaOp& token, const Shape& shape, const string& config = ""); - // Enqueues an outfeed instruction onto the computation. This instruction - // generates outgoing data transfers for the given data. - // - // shape_with_layout communicates the laid out shape that we want to outfeed - // -- if !ShapeUtil::Compatible(GetShape(operand), shape_with_layout) an error - // will occur. void Outfeed(const XlaOp& operand, const Shape& shape_with_layout, const string& outfeed_config); XlaOp OutfeedWithToken(const XlaOp& operand, const XlaOp& token, const Shape& shape_with_layout, const string& outfeed_config); - // Enqueues a call instruction onto the computation. XlaOp Call(const XlaComputation& computation, absl::Span operands); - // Enqueues a custom call instruction onto the computation. XlaOp CustomCall( const string& call_target_name, absl::Span operands, const Shape& shape_with_layout, const string& opaque, absl::optional> operand_shapes_with_layout); - // The following methods enqueue element-wise binary arithmetic operations - // onto the computation. The shapes of the operands have to match unless one - // of the operands is a scalar, or an explicit broadcast dimension is given - // (see g3doc for more details). - - // Enqueues a complex compose instruction onto the computation. XlaOp Complex(const XlaOp& real, const XlaOp& imag, absl::Span broadcast_dimensions = {}); - // Enqueues a complex conjugate instruction onto the computation. XlaOp Conj(const XlaOp& operand); - // Enqueues an add instruction onto the computation. XlaOp Add(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a subtract instruction onto the computation. XlaOp Sub(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a multiply instruction onto the computation. XlaOp Mul(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a divide instruction onto the computation. XlaOp Div(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a remainder instruction onto the computation. XlaOp Rem(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a max instruction onto the computation. XlaOp Max(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues a min instruction onto the computation. XlaOp Min(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Element-wise logical operators XlaOp And(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); @@ -624,32 +485,23 @@ class XlaBuilder { XlaOp ShiftRightLogical(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Reduces an array among the provided dimensions, given "computation" as a - // reduction operator. XlaOp Reduce(const XlaOp& operand, const XlaOp& init_value, const XlaComputation& computation, absl::Span dimensions_to_reduce); - // Reduces several arrays simultaneously among the provided dimensions, given - // "computation" as a reduction operator. XlaOp Reduce(absl::Span operands, absl::Span init_values, const XlaComputation& computation, absl::Span dimensions_to_reduce); - // Convenience wrapper around the above that reduces all the dimensions in the - // operand shape. XlaOp ReduceAll(const XlaOp& operand, const XlaOp& init_value, const XlaComputation& computation); - // Enqueues a windowed reduce instruction onto the computation. XlaOp ReduceWindow(const XlaOp& operand, const XlaOp& init_value, const XlaComputation& computation, absl::Span window_dimensions, absl::Span window_strides, Padding padding); - // As ReduceWindow(), but the padding is given in the format - // returned by MakePadding(). XlaOp ReduceWindowWithGeneralPadding( const XlaOp& operand, const XlaOp& init_value, const XlaComputation& computation, @@ -659,48 +511,22 @@ class XlaBuilder { absl::Span window_dilations, absl::Span> padding); - // Returns the sum of the operand value within each subgroup of replicas. All - // replicas supply one input to the sum and all replicas receive the resulting - // sum for each subgroup. XlaOp CrossReplicaSum(const XlaOp& operand, absl::Span replica_groups = {}); - // Enqueues an operation that do an AllReduce of the operand cross cores. Here - // AllReduce means doing a reduction on the input operand cross cores and then - // broadcasting the reduction result to those cores. The reduction function is - // defined by `computation`, which should be a commutative computation on - // scalars, e.g., add, min, or max. The way that AllReduce is applied is - // configured by: - // - // - `replica_groups`: each ReplicaGroup contains a list of replica id. If - // empty, all replicas belong to one group. Allreduce will be applied within - // subgroups. For example, we have 4 replicas, then - // replica_groups={{0,2},{1,3}} means, replica 0 and 2 are in subgroup 0, - // replica 1 and 3 are in subgroup 1. - // - // - `channel_id`: for Allreduce nodes from different modules, if they have - // the same channel_id, they will be 'Allreduce'd. If empty, Allreduce will - // not be applied cross modules. - // - // TODO(b/117564385): Rename this to AllReduce when it's ready to use. XlaOp CrossReplicaSum( const XlaOp& operand, const XlaComputation& computation, absl::Span replica_groups = {}, const absl::optional& channel_id = absl::nullopt); - // Enqueues an operation that do an Alltoall of the operand cross cores. XlaOp AllToAll(const XlaOp& operand, int64 split_dimension, int64 concat_dimension, int64 split_count, const std::vector& replica_groups); - // Enqueues an operation that do an CollectivePermute of the operand cross - // cores. XlaOp CollectivePermute( const XlaOp& operand, const std::vector>& source_target_pairs); - // Enqueues an operation that scatters the `source` array to the selected - // indices of each window. XlaOp SelectAndScatter(const XlaOp& operand, const XlaComputation& select, absl::Span window_dimensions, absl::Span window_strides, @@ -708,8 +534,6 @@ class XlaBuilder { const XlaOp& init_value, const XlaComputation& scatter); - // As SelectAndScatter(), but the padding is given in the format - // returned by MakePadding(). XlaOp SelectAndScatterWithGeneralPadding( const XlaOp& operand, const XlaComputation& select, absl::Span window_dimensions, @@ -717,217 +541,119 @@ class XlaBuilder { absl::Span> padding, const XlaOp& source, const XlaOp& init_value, const XlaComputation& scatter); - // Enqueues an abs instruction onto the computation. XlaOp Abs(const XlaOp& operand); - // Enqueues a atan2 instruction onto the computation. XlaOp Atan2(const XlaOp& y, const XlaOp& x, absl::Span broadcast_dimensions = {}); - // Enqueues an exp instruction onto the computation. XlaOp Exp(const XlaOp& operand); - // Enqueues an expm1 instruction onto the computation. XlaOp Expm1(const XlaOp& operand); - // Enqueues a floor instruction onto the computation. XlaOp Floor(const XlaOp& operand); - // Enqueues a ceil instruction onto the computation. XlaOp Ceil(const XlaOp& operand); - // Enqueues a round instruction onto the computation, rounding to nearest even - // with half-way cases rounding away from zero. XlaOp Round(const XlaOp& operand); - // Enqueues an log instruction (natural logarithm) onto the computation. XlaOp Log(const XlaOp& operand); - // Enqueues an log1p instruction (log(x+1)) onto the computation. XlaOp Log1p(const XlaOp& operand); - // Enqueues a sign instruction onto the computation. XlaOp Sign(const XlaOp& operand); - // Enqueues a count leading zeros instruction onto the computation. XlaOp Clz(const XlaOp& operand); - // Enqueues a cosine instruction onto the computation. XlaOp Cos(const XlaOp& operand); - // Enqueues a sine instruction onto the computation. XlaOp Sin(const XlaOp& operand); - // Enqueues a tanh instruction onto the computation. XlaOp Tanh(const XlaOp& operand); - // Enqueues a real-part instruction onto the computation. XlaOp Real(const XlaOp& operand); - // Enqueues an imaginary-part instruction onto the computation. XlaOp Imag(const XlaOp& operand); - // Enqueues a lhs^rhs computation onto the computation. XlaOp Pow(const XlaOp& lhs, const XlaOp& rhs, absl::Span broadcast_dimensions = {}); - // Enqueues an operator that tests if the operand's values are finite, i.e., - // not Inf or NaN. Defined only for floating-point types. Returns an array of - // booleans with the same shape where entries are true iff the corresponding - // entry was NaN. XlaOp IsFinite(const XlaOp& operand); - // Enqueues an iota operation onto the computation. XlaOp Iota(const Shape& shape, int64 iota_dimension); - // Enqueues a rank-1 iota operation onto the computation. XlaOp Iota(PrimitiveType type, int64 size); - // Enqueues a convert instruction onto the computation that changes the - // element type of the operand array to primitive_type. XlaOp ConvertElementType(const XlaOp& operand, PrimitiveType new_element_type); - // Enqueues a no-op instruction onto the computation that changes - // the element type of the operand array to primitive_type. The - // bit-widths of the source and destination element types must be - // identical. XlaOp BitcastConvertType(const XlaOp& operand, PrimitiveType new_element_type); - // Enqueues a negate instruction onto the computation. XlaOp Neg(const XlaOp& operand); - // Enqueues a transpose instruction onto the computation. XlaOp Transpose(const XlaOp& operand, absl::Span permutation); - // Enqueues a reverse instruction onto the computation. The order of the - // elements in the given dimensions is reversed (i.e., the element at index i - // is moved to index dimension_size - 1 - i). XlaOp Rev(const XlaOp& operand, absl::Span dimensions); - // Enqueues a sort (as increasing order) instruction onto the computation. - // If only keys are provided: - // * If the keys are an rank-1 tensor (an array), the result is a sorted array - // of keys, in ascending order. - // * If the keys have higher rank, the keys are sorted along the provided - // dimension. For example, for a rank-2 tensor (a matrix) of keys, a dimension - // value of 0 will indepenently sort every column, and a dimension value of 1 - // will independently sort each row. If no dimension number is provided, then - // the last dimension is chosen by default. - // - // If both keys and values are provided: - // * The keys and all values must be tensors with the same dimensions. The - // element types of the tensors may be different. - // * The result is a tuple that consists of a sorted tensor of keys (along the - // provided dimension, as above) as the first element, and tensors with their - // corresponding values as the other elements. XlaOp Sort(const XlaOp& keys, absl::Span values = {}, int64 dimension = -1); - // Enqueues a clamp instruction onto the computation. XlaOp Clamp(const XlaOp& min, const XlaOp& operand, const XlaOp& max); - // Enqueues a map instruction onto the computation. XlaOp Map(absl::Span operands, const XlaComputation& computation, absl::Span dimensions, absl::Span static_operands = {}); - // Enqueues a N(mu, sigma) random number generation instruction onto the - // computation. XlaOp RngNormal(const XlaOp& mu, const XlaOp& sigma, const Shape& shape); - // Enqueues a U(a, b) random number generation instruction onto the - // computation. Returns values in the semi-open interval [a, b). XlaOp RngUniform(const XlaOp& a, const XlaOp& b, const Shape& shape); - // Enqueues a while node onto the computation. XlaOp While(const XlaComputation& condition, const XlaComputation& body, const XlaOp& init); - // Enqueues a conditional node onto the computation. XlaOp Conditional(const XlaOp& predicate, const XlaOp& true_operand, const XlaComputation& true_computation, const XlaOp& false_operand, const XlaComputation& false_computation); - // Enqueues a ReducePrecision node onto the computation. XlaOp ReducePrecision(const XlaOp& operand, const int exponent_bits, const int mantissa_bits); - // Enqueues a Gather node onto the computation. XlaOp Gather(const XlaOp& input, const XlaOp& start_indices, const GatherDimensionNumbers& dimension_numbers, absl::Span slice_sizes); - // Enqueues a Scatter node onto the computation. XlaOp Scatter(const XlaOp& input, const XlaOp& scatter_indices, const XlaOp& updates, const XlaComputation& update_computation, const ScatterDimensionNumbers& dimension_numbers); - // Enqueues a Send node onto the computation for device-to-device - // communication, to send the given operand to a Recv instruction that shares - // the same channel handle. void Send(const XlaOp& operand, const ChannelHandle& handle); XlaOp SendWithToken(const XlaOp& operand, const XlaOp& token, const ChannelHandle& handle); - // Enqueues a Send node which sends data to the host. XlaOp SendToHost(const XlaOp& operand, const XlaOp& token, const Shape& shape_with_layout, const ChannelHandle& handle); - // Enqueues a Recv node which receives data from the host. XlaOp RecvFromHost(const XlaOp& token, const Shape& shape, const ChannelHandle& handle); - // Enqueues an AfterAll operation with no operands producing a token-shaped - // value. XlaOp CreateToken(); - // Enqueues an AfterAll operation with no operands producing a token-shaped - // value. XlaOp AfterAll(absl::Span tokens); - // Enqueues a Recv node onto the computation. The data comes from a Send - // instruction that shares the same channel handle and its shape must - // be the same as the given shape. XlaOp Recv(const Shape& shape, const ChannelHandle& handle); XlaOp RecvWithToken(const XlaOp& token, const Shape& shape, const ChannelHandle& handle); - // Normalizes operand across spatial and batch dimensions for each feature. - // - // Returns a tuple (normalized, batch_mean, batch_var) where `normalized` - // is the normalized result and batch_mean and batch_var are the mean and - // variance, respectively, across batch for the operand. XlaOp BatchNormTraining(const XlaOp& operand, const XlaOp& scale, const XlaOp& offset, float epsilon, int64 feature_index); - // Normalizes operand across spatial and batch dimensions for each feature. - // - // `BatchNormInference` is equivalent to calling `BatchNormTraining` without - // computing `mean` and `variance` for each batch inside the operation. It - // uses the input `mean` and `variance` instead as estimated values. The - // purpose of this op is to reduce latency in inference, hence the name - // `BatchNormInference`. - // - // The output has the same shape as `operand`, and contains the normalized - // values for each batch. XlaOp BatchNormInference(const XlaOp& operand, const XlaOp& scale, const XlaOp& offset, const XlaOp& mean, const XlaOp& variance, float epsilon, int64 feature_index); - // Calculates the gradients of a batch norm op. - // - // The inputs `batch_mean` and `batch_var` represent the mean and variance - // across the batch. - // - // Returns a tuple of three elements: - // - grad_operand: Gradient with respect to input `operand` - // - grad_offset: Gradient with respect to input `offset` - // - grad_scale: Gradient with respect to input `scale` XlaOp BatchNormGrad(const XlaOp& operand, const XlaOp& scale, const XlaOp& batch_mean, const XlaOp& batch_var, const XlaOp& grad_output, float epsilon, @@ -1019,6 +745,9 @@ class XlaBuilder { // The instructions of this computation. std::vector instructions_; + // Dynamic parameter configuration of this computation. + DynamicParameterBinding dynamic_parameter_binding_; + // A map from XlaOp::Handle to the index in the instructions_ vector where the // instruction is held. absl::flat_hash_map handle_to_index_; @@ -1096,7 +825,7 @@ class XlaBuilder { absl::Span broadcast_sizes); friend XlaOp BroadcastInDim( - const XlaOp& operand, const Shape& shape, + const XlaOp& operand, const absl::Span out_dim_size, const absl::Span broadcast_dimensions); friend XlaOp Pad(const XlaOp& operand, const XlaOp& padding_value, @@ -1393,6 +1122,7 @@ class XlaScopedShardingAssignment { // Free functions for building XlaOps. The intention is that these will // become the public API for building XlaOps rather than calling methods on // XlaBuilder directly. +// // Enqueues a "retrieve parameter value" instruction for a parameter that was // passed to the computation. @@ -1488,7 +1218,8 @@ XlaOp Broadcast(const XlaOp& operand, absl::Span broadcast_sizes); // will generate output // {{1 , 1}, // {2 , 2}} -XlaOp BroadcastInDim(const XlaOp& operand, const Shape& shape, +XlaOp BroadcastInDim(const XlaOp& operand, + const absl::Span out_dim_size, const absl::Span broadcast_dimensions); // Enqueues a pad operation onto the computation that pads the given value on @@ -2138,6 +1869,7 @@ XlaOp BatchNormGrad(const XlaOp& operand, const XlaOp& scale, XlaOp GetDimensionSize(const XlaOp& operand, int64 dimension); // Implementation details below this point. +// template XlaOp XlaBuilder::ConstantR0(NativeT value) { diff --git a/tensorflow/compiler/xla/client/xla_builder_test.cc b/tensorflow/compiler/xla/client/xla_builder_test.cc index 8aa85c3cd6..b3f5be300d 100644 --- a/tensorflow/compiler/xla/client/xla_builder_test.cc +++ b/tensorflow/compiler/xla/client/xla_builder_test.cc @@ -267,7 +267,7 @@ TEST_F(XlaBuilderTest, BinopHasInDimAndDegenerateBroadcast) { TEST_F(XlaBuilderTest, BroadcastInDim) { XlaBuilder b(TestName()); auto x = Parameter(&b, 0, ShapeUtil::MakeShape(F32, {2, 3}), "x"); - BroadcastInDim(x, ShapeUtil::MakeShape(F32, {2, 4, 3}), + BroadcastInDim(x, {2, 4, 3}, /*broadcast_dimensions=*/{0, 2}); TF_ASSERT_OK_AND_ASSIGN(auto module, BuildHloModule(&b)); auto root = module->entry_computation()->root_instruction(); @@ -277,7 +277,7 @@ TEST_F(XlaBuilderTest, BroadcastInDim) { TEST_F(XlaBuilderTest, BroadcastInDimWithDegeneratedDim) { XlaBuilder b(TestName()); auto x = Parameter(&b, 0, ShapeUtil::MakeShape(F32, {2, 1, 4}), "x"); - BroadcastInDim(x, ShapeUtil::MakeShape(F32, {2, 3, 4}), + BroadcastInDim(x, {2, 3, 4}, /*broadcast_dimensions=*/{0, 1, 2}); TF_ASSERT_OK_AND_ASSIGN(auto module, BuildHloModule(&b)); EXPECT_THAT(module->entry_computation()->root_instruction(), @@ -446,5 +446,14 @@ TEST_F(XlaBuilderTest, ProtoMatches) { EXPECT_EQ(c0_string, c1_string); } +TEST_F(XlaBuilderTest, AfterAllWithNonTokenOperands) { + XlaBuilder b(TestName()); + AfterAll(&b, {CreateToken(&b), ConstantR0(&b, 1.0)}); + Status status = b.Build().status(); + ASSERT_IS_NOT_OK(status); + EXPECT_THAT(status.error_message(), + ::testing::HasSubstr("All operands to AfterAll must be tokens")); +} + } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/client/xla_computation.cc b/tensorflow/compiler/xla/client/xla_computation.cc index c9870b65b9..f317892c12 100644 --- a/tensorflow/compiler/xla/client/xla_computation.cc +++ b/tensorflow/compiler/xla/client/xla_computation.cc @@ -25,7 +25,7 @@ namespace xla { StatusOr XlaComputation::GetProgramShape() const { TF_RET_CHECK(proto_.has_host_program_shape()); - return proto_.host_program_shape(); + return ProgramShape(proto_.host_program_shape()); } StatusOr> XlaComputation::Snapshot() const { diff --git a/tensorflow/compiler/xla/client/xla_computation.h b/tensorflow/compiler/xla/client/xla_computation.h index 71598ef8b2..3ccbfb28bd 100644 --- a/tensorflow/compiler/xla/client/xla_computation.h +++ b/tensorflow/compiler/xla/client/xla_computation.h @@ -19,6 +19,7 @@ limitations under the License. #include #include "tensorflow/compiler/xla/service/hlo.pb.h" +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/status_macros.h" #include "tensorflow/compiler/xla/xla_data.pb.h" diff --git a/tensorflow/compiler/xla/debug_options_flags.cc b/tensorflow/compiler/xla/debug_options_flags.cc index 033887d7c1..d7e7b9e621 100644 --- a/tensorflow/compiler/xla/debug_options_flags.cc +++ b/tensorflow/compiler/xla/debug_options_flags.cc @@ -54,7 +54,7 @@ void SetDebugOptionsDefaults(DebugOptions* flags) { // TODO(jlebar): Disable fastmath once doing so is not a performance // regression. flags->set_xla_cpu_enable_fast_math(true); - flags->set_xla_gpu_enable_fast_math(true); + flags->set_xla_gpu_enable_fast_min_max(true); flags->set_xla_force_host_platform_device_count(1); } @@ -160,11 +160,11 @@ void AllocateFlags() { "Enable unsafe fast-math optimizations in the CPU compiler; " "this may produce faster code at the expense of some accuracy."), tensorflow::Flag( - "xla_gpu_enable_fast_math", - bool_setter_for(&DebugOptions::set_xla_cpu_enable_fast_math), - flag_values->xla_cpu_enable_fast_math(), - "Enable unsafe fast-math optimizations in the GPU compiler; " - "this may produce faster code at the expense of some accuracy."), + "xla_gpu_enable_fast_min_max", + bool_setter_for(&DebugOptions::set_xla_gpu_enable_fast_min_max), + flag_values->xla_gpu_enable_fast_min_max(), + "Enable fast floating point min/max lowering that does not propagate " + "NaNs."), tensorflow::Flag( "xla_llvm_enable_alias_scope_metadata", bool_setter_for( @@ -335,7 +335,7 @@ void AllocateFlags() { "behavior to help run tests on the host that run models in parallel " "across multiple devices."), }); - ParseFlagsFromEnv(*flag_objects); + ParseFlagsFromEnvAndDieIfUnknown("XLA_FLAGS", *flag_objects); } } // namespace diff --git a/tensorflow/compiler/xla/experimental/xla_sharding/xla_sharding.py b/tensorflow/compiler/xla/experimental/xla_sharding/xla_sharding.py index fb135f5ced..1fea816a80 100644 --- a/tensorflow/compiler/xla/experimental/xla_sharding/xla_sharding.py +++ b/tensorflow/compiler/xla/experimental/xla_sharding/xla_sharding.py @@ -18,12 +18,9 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import math - import numpy as _np # Avoids becoming a part of public Tensorflow API. from tensorflow.compiler.xla import xla_data_pb2 -from tensorflow.compiler.xla.python_api import xla_shape from tensorflow.core.framework import attr_value_pb2 @@ -64,22 +61,18 @@ class Sharding(object): tile_assignment_devices=[core])) @classmethod - def tile(cls, tile_shape, tile_assignment): + def tile(cls, tile_assignment): """Returns a Tiled sharding attribute. This causes an op to be partially computed on multiple cores in the XLA device. Args: - tile_shape: A xla_shape.Shape describing the tile shape that each core - will compute. - The tile shape does not need to be divisible by the tile assignment. tile_assignment: An np.ndarray describing the topology of the tiling and which device will compute which part of the topology. Raises: - TypeError: tile_assignment was not of np.array type or tile_shape was - not of xla_shape.Shape type. + TypeError: tile_assignment was not of np.array type. TODO(jmolloy): This concept is nefarious and is not something we really want to expose to users (especially as the @@ -87,14 +80,11 @@ class Sharding(object): """ if not isinstance(tile_assignment, _np.ndarray): raise TypeError('Tile assignment must be of type np.ndarray') - if not isinstance(tile_shape, xla_shape.Shape): - raise TypeError('Tile shape must be of type xla_shape.Shape') dims = list(tile_assignment.shape) flattened_devices = tile_assignment.reshape(-1, order='C') return Sharding( proto=xla_data_pb2.OpSharding( type=xla_data_pb2.OpSharding.OTHER, - tile_shape=tile_shape.message, tile_assignment_dimensions=dims, tile_assignment_devices=list(flattened_devices))) @@ -118,14 +108,8 @@ class Sharding(object): shape = tensor.shape.as_list() if shape[split_dimension] < num_devices: raise ValueError('Split dimension was smaller than the required number ' - 'of splits: shape=%r, dimension=%r, num_devices=%r', - shape, split_dimension, num_devices) - - tile_shape = shape - tile_shape[split_dimension] = int( - math.ceil(tile_shape[split_dimension] / num_devices)) - tile_shape_proto = xla_data_pb2.Shape( - element_type=xla_data_pb2.F32, dimensions=tile_shape) + 'of splits: shape=%r, dimension=%r, num_devices=%r' % + (shape, split_dimension, num_devices)) tile_assignment_dims = [1] * len(shape) tile_assignment_dims[split_dimension] = num_devices @@ -133,7 +117,6 @@ class Sharding(object): return Sharding( proto=xla_data_pb2.OpSharding( type=xla_data_pb2.OpSharding.OTHER, - tile_shape=tile_shape_proto, tile_assignment_dimensions=tile_assignment_dims, tile_assignment_devices=range(num_devices))) @@ -149,7 +132,6 @@ class Sharding(object): type=xla_data_pb2.OpSharding.TUPLE, tuple_shardings=tuple_shardings) else: proto = self._proto - attr_value = attr_value_pb2.AttrValue(s=proto.SerializeToString()) # TODO(jmolloy): This need to be seriously revisited before declaring this # API available for public use. @@ -194,8 +176,8 @@ def assign_device(tensor, device): return tensor -def tile(tensor, tile_shape, tile_assignment): - Sharding.tile(tile_shape, tile_assignment).apply_to_tensor(tensor) +def tile(tensor, tile_assignment): + Sharding.tile(tile_assignment).apply_to_tensor(tensor) return tensor diff --git a/tensorflow/compiler/xla/g3doc/_book.yaml b/tensorflow/compiler/xla/g3doc/_book.yaml index bcfbcc3a22..12b7094705 100644 --- a/tensorflow/compiler/xla/g3doc/_book.yaml +++ b/tensorflow/compiler/xla/g3doc/_book.yaml @@ -3,15 +3,15 @@ upper_tabs: - include: /_upper_tabs_left.yaml - include: /api_docs/_upper_tabs_api.yaml # Dropdown menu -- name: Ecosystem - path: /ecosystem +- name: Resources + path: /resources is_default: true menu: - - include: /ecosystem/_menu_toc.yaml + - include: /resources/_menu_toc.yaml lower_tabs: # Subsite tabs other: - - name: Guide + - name: Guide & Tutorials contents: - title: XLA overview path: /xla/overview @@ -27,3 +27,7 @@ upper_tabs: path: /xla/shapes - title: Using AOT compilation path: /xla/tfcompile + - heading: Tutorials + - title: XLA compile API + path: /xla/tutorials/xla_compile + status: experimental diff --git a/tensorflow/compiler/xla/g3doc/_index.yaml b/tensorflow/compiler/xla/g3doc/_index.yaml index 7934cd11ba..858de42711 100644 --- a/tensorflow/compiler/xla/g3doc/_index.yaml +++ b/tensorflow/compiler/xla/g3doc/_index.yaml @@ -17,7 +17,7 @@ landing_page: - classname: devsite-landing-row-cards items: - heading: XLA - TensorFlow, compiled - image_path: /ecosystem/images/tf-logo-card-16x9.png + image_path: /resources/images/tf-logo-card-16x9.png path: https://developers.googleblog.com/2017/03/xla-tensorflow-compiled.html buttons: - label: Read on Google Developers blog @@ -28,7 +28,7 @@ landing_page: - label: Watch the video path: https://www.youtube.com/watch?v=kAOanJczHA0 - heading: XLA on GitHub - image_path: /ecosystem/images/github-card-16x9.png + image_path: /resources/images/github-card-16x9.png path: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/compiler/xla buttons: - label: View on GitHub diff --git a/tensorflow/compiler/xla/g3doc/images/xla_array_layout_figure1.png b/tensorflow/compiler/xla/g3doc/images/xla_array_layout_figure1.png new file mode 100644 index 0000000000000000000000000000000000000000..00cefe4c7806c1c09dd51499375e720bfb0baac6 GIT binary patch literal 20398 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 Jmvv4FO#qulvt$4O literal 0 HcmV?d00001 diff --git a/tensorflow/compiler/xla/g3doc/images/xla_array_layout_figure2.png b/tensorflow/compiler/xla/g3doc/images/xla_array_layout_figure2.png new file mode 100644 index 0000000000000000000000000000000000000000..6439c6e40272ae6b2954e9d7f3de2df470a2b36d GIT binary patch literal 7913 zcmeAS@N?(olHy`uVBq!ia0y~yV6k<$;=|0(|{fY9zC5tRduFQPYyM2OlA;-i;H7&}PaeVHw=XT68 zGF5k3xKhn|PRrxR8l@9u3cZfK`5pUT{rtXbZ2YH&-j| zjek|#*VktyD*Dv)QT+|!g@0yOD(`Pmck?OPVp#wC&hNj;cfR)bb{3wsw={hC)r)<1 zRH@$Nx%2B(({GhdxV(RtE1zEE+HK{3KKn!*S9fiHdg6_1(Y9RcpX(yIZ*I=*kJ#|> zVKw`|IokFS#|x7@w#h_HOg>|;XLm64{}ip2cEZK|jP@0C)=yNNpQjb_`_ih=udz42 zulsRpt62PU=_M&Ibq;=O)#o~FfA4&#+@!czy_~q!-%^)_n?L@4l1;NRanp}=*_!*( zdarIwsDC@_<+@+jS4Vr_`LsURc=3*)L+^4{Z!4;KQQ+RRX3fW=JC=*Y2Q#%HRkW;XB|A}`~S-nExXIb^%duYEaNwCd!uKwAmMrT)tDOod#`yOoRU!eysYcW znF-w1pG4pE{O+$m@}B?3&X@c*c0S7gX?DhEea(jI6;ZQJnRM~ZGZHJ1xc}v?{{H@+ zFH=?2PVFm|?ybuHuNio8-LLf>oga4^es6fY-MnnlnMrSj`>gY)ss~T<){=c=cI+tUCh5xu`3}hRcT8CCW|Ma(`uF?~ z6)|7!bARqO{4Sxfyu5O6(58Z27acyc&j}5x6%u{A>i@fp^1t7Yxa@uuKWVp5nXCJ6 zE!j8cA{n>uPFVjj!I}SM6YK81mC>=B-{PD0f4%`2A4Iuia1c zE9JgcY0JOyb9dV%l#_8Jx^j#5y)XX@53>BrW7)Mo)33gK&-cC2mWki}S5GO>e$W-m zQ}*lsi}z6*q8DHKU47@X`Wp`ELwy^R-*8wTYJ*UH8x%pjz75Jb9M&+ob#oqXeOmnF zwg3H(`H#Pz>Fhss`LX=O^W{&h-|ertcO~eywfUY^dkpzn3OGGCY>4hU9a{HnN7GmJ zH%$`7)7MU19kpfBuCMDRShMj=TdR2IvSikV`jQV*Y`(mx$h`4GYybb-t?V(4XWuV7 zGbwNHZ^>5KbM;4dEWh&edUnCmJN9o3x1JYy!!WJ-S4r@8>(s4T>lB`ty!p4QWZIFV z$EI*)Rh*w|7RFjVx$WzdHwWML{bXJxxNScB3#n_XSNCxX9D2Rp?&brIH|J!3I=IhiLEC8@T{Y+c6^w+p_rkp{%3Tfii(=ngQq!KQ>5!kyT9yvZI^uT--C|hp$pd6 z)NbChEp>Ux&aY*xahEq7wmEX-nCI*=*`7mu&-qWRJ$HK*TLb@(nN6{;v)4^JSpI#| z-stNmS9hmtaVY+n+jKWLx!rTSpSj0oHQqlPZqNC=>CPR+)BlYv2N%)51=G^*N@2~$IZ&DWd0uB_WCU-m&db9ZCiqZK)( zbH3<&5Cy}$gi?r&}Sr6V9LAu`Sdkm8=S*9Z!C)ExUgU3kb6ig z*Y2jT+A5~1k*O6D%Fcf}7IhuqJ2=mFMf}P$eB7*RiS0&mOG`B(b6peLf4bifnSNcP z^zBWv#PZIA?|O5qMM?s^+HNi2|8`$t@u8i1`+sZe4%Z7Omn`DhFZ6{g=gf-8Xx$SD33>%G%fvD!9CT&*WBrD?!S?{4 z^4oeVt_4 zCfQ%1-&ncUoR}4}z~MfZ?=Qp2^9<|eN{g{gIQz1((xFT;CoFp68KL6dsR?`e?=4*C z#?IXl%DsGbkJ^V#JYUw%Y2)2=s+du}q;sC)sVw1ClTDU?rKZnh*z@hU8^V|Njs$q`2BDIpwIDdrIiO|KeXzCQh7l=W`|*67~`vBzFrEjVMjpnnbD z%%|_u_hqn@RXr7)$y?>J;~1ahxm5yoEtARvKJaz@@9ORnOp(ohw@&J*=*|_UBKfgS zY<<42?Y)QjmR4(A-_iPb(W7T;Z)shyGpy~qcr_x$P(!w`R=g_pVBCGT8-itfVtfAW ziR}RwU%!OQT4WR5Z(N)Y<{s+%2j&VwL<4u=OLnjM`|w+R)|(AMw`Ui}O?%_`_etkO{+4I*EN?#S zxwHJZ{in&F=UHgow&$>BPZWPO`NiRn8jd#BqUYBgePOQ>&Gl`*!L$D7mmlqUyEyuN zo!g)3>u>)M&bReBn3w&|=w#N_m^JqDnb(#yR+X)}yaAM&JG(xuI&N``k%8f%#hc%U z-}1{d=pOp^x%KDjC7y??UNPSFj-RncPWz?En-3q}T344%tSZf(YPIalmsh8v`462_ zym2;mn_J^C-Wz|ds+YuET{N}IPv=1M^@_5!n*Z(pScV&AT?^ZAJ-PH=nDRf1_}%(_ zOY`<>JJoqqYVe=*^Ysjy;CMjs#>WXcEc=5uNPfMbAX)YPEtf{wiibD1{*aTq^;YH0 zyO)=J5AxYn$;%1sOFWxoUtyr`cktb^vbCXN>Fu)5cBfD0(@CD&cK3s!@YUcK)!*K} z=X&#@A;V@)RKESUCnjGvWCZ_9R9JSi{mdJRCjt)L`o1upMZof|F?Y*cIlsf_-U;vEueEMqQ_bB_yE{Q#9)!nnO8S=^6tJ@es_73?D2*J=1=eMh~#Fy@m%b$=UK*0cLGkI=$d11 zqdh6Hjmi4U>kHPmcRmcQzt*@fHd0~7l*IN+q3P3hEs3+sUuAfMl`my_eXLdYhTS2F z%f+?dNn6Eyz0ef9gyZV}vrT(9eZ9Qi>+6R-*KCw-o0k6j;C}wgQBlid;mLv9jvYOw z@k3#;;{w*S>giT*E;wIaYJH&n^ZEMJg@!kH_wAluUn+JXH)4HWK(WJ(zta!!HEeF? zUB5A?ZK{{K-d~3>&i@IUPj~$|Ur{*ol*Zj%Usz_!{wmj4C{V%>m)a!D(ERwI5~G+O zsK|SK{pQWTh5Jsd*jQ2IyZP9go3X1lI8X4Oz4^%gxtmvB(8zg^`hK$FZZE%;NjjU4 z9C&J`@!0n;sQ4AVG2!fs+Kfr;(mB&lxgMR-AFysC_jT8!AGS}w+;Ufy&05Eeq2ff| zy!cH~uS|CsEjhq{^?x5@^HlXcrEOo2e6e&p{o~o%TdP_HFK=Le60mDg%V95-Q<^!i zMV;?C9<g(%T{N z=7avi{nZEey^jSq{ldL&$bPO$Eq}=P_~5quyKX=4{W^ay`k?61t{?M@Z_3YXl`hWz zzJG)A{izMwCu5(j`+q62=-%UP`;Uv(pZVLkV#O);-FtpiSQ=GN{Fw0j)5VWLDStQ4 zmzea{Ys2CCQv*owE3>Cil0(Ki!Wd5Cf{3!P8 zep|zf=~eIE{wr5i|EaQf*T*-DQVy?Xy8kaU=*(~VpAI$r_q6wwtzB9jWg7lB|MVKg zWq-fk+3xGFy{=@#VOfFs{#9;&KPsOtF#7N<=l0|8R$m?&eT>?0J9a}j!yMzcRwoXs zuI~MH{HXelSM!5Zucl|cJN?Ojb=cK#qslG69*0Y|U3UClx9-PZF~8%-g=T(s@6Y+@ z^U*YWjYIR>Tc(#|zaHPa?${sZXZ!rl_MBqhJ>`nlz8^m-;@8iRxG&i6Zt82;b=c;E z_5RJr*u!34(b4m(bc;-7*{2qr92PR={fwvYjbF$MOFv#!A5$}D#*FH>^|z#6uf4SK zr0f5d9~B$h)^AVzzigU)jj*s#&yUCDi|l*0xvswv@w9j1oEcA6)q4ePGOYi*z5MIZ zo$Ke$EZleL;JR&J-xcM2+#ED#o?3jrq?-Guuv7n>SwG$U=zqwH@6BDM_;a(h?x${@ zR2*(TvAH#W<(a(y|8k3#xu;vk|2O*i>SkwA#_Q~3e*{0|{aU_c*$SVebv>heV2`&dw53iTK@jPVYxM_cg~G{-hJ7k}HWOWHj2c++1~W24xw>!Vlq?RXlmt-SeDYT5PcX95@tD!luY z9mB3!7(NWN%y%?9+$7ud|H=i%P46Qn7XG)owtLR(e{UxV*Dibh?=-9Nk{w}fO!u~i zN%lJYPJ3JB&Jcdh;_nw7&66iW4rJ#Zytd{4&56l>{#}pUPetyS#`XEjX6xMe@+0krz|F*^*Y4lDczDP5Z~B`qRhj?gkNlT+=C8PS`svoJ(5JmG zBrHGwn0$=sEdQR!&r4Odu3FRITYA-AU+-M#fAhzWV?X}?{(wEDvc~CYbg%8}k1K?Z zmmD}KEH1jZq?p-kKTG`=_PaBxS#Q5_{M7t(y|>oo$GaQ9pXR@IU+(YO--kB`#f8+| zI;D4q!|cnc3l^r4cK?L_-u-aw$MJW*r|$PUgx4lf}u1uq(ceotE)s}x&RGA(cKu2Z-E zTtGM-j+3pjzM@_vhzyJG0!^2N@eaoH7-{<`M z|N9;8SL$m1R!^9|amsc1x(}`A^WAyA&VPRF(DooQU6#DzWc<|NW%Y^otS{|9KR3(1@1W-Yt=-eT`_FCnxZXE6 z_2rtM|Nd$}-@oMB!y5+feh2xUw-q1RDRyh!>C3;_@0YHBb8o}k4cy{y1PVB`?s%{M zzV`MH@tunTYeh>KWcP{t9AIVMy=U!uO?{R<_soCZ?Bv=c|L*>>roH9+Z_70DIxJQ+ ze*5#}rA?*WTjd#8YBts%c(D6vr^5R-jrI1=Y9IA{tb6h5bIz3|3w0vw!uN6>ls_(! zcSH7X0{^?kQ}&2vr@Vj0A6j5_cAjEsERii`Z=zEytxN8^Xz?r$pFdu9KdqSAR1x7gPg#{A%tcx>9Id1u4v%F3l% za<0Y9ResQQ{YHQCh2MtqZ*QjvmOX5WZ9iwe>cFPMc?I7TD)SEV{Qvekx=5z^?p58{ zn)=pn+H9xkCad>;Yu;WOrtO}pTWl8%A1?z7217{|0`~9+S9qu z=HH1M43c~2+J2}jwQ2CZwl(+9=Lz$|oEz2eY|uV&_rZCokH?z*yDlDY{LlTjn4!qv zUrVfIn`{|_!X~*Cs~i1q4xcm;u4~THzVBxkBvK|<$O?XVAG}J% z`dvTIxwuoW8^fG5KFf!gC9q0w;*|X(?A90f!SRDN>+Sv+*d*m1{Q7rKH}#O7nc20#`jks2?!CEb z9Je^1ox%F*=F1Bl>pj>_H}U2?-pYC7p#01$SGvv59p;~K`DV=e=v~uKl^lB8&m+Fz zs;zZOnbe-s@ewM$ugp1i<%{vWF}SZ0UU=>UXNz>=bAvYm3C7QSby@c(Y+BuQ=-sDZ z(>?1BO8?7MPwcLfFpB)GI@ZB`tv}==?Udj1Onl~1fu)cWHxU@OI z{H=Pg)bghK|JCx=n;aNtEOHmWahm(go2J-_y7}h?6z&Usm|3i$ZkiK#iRoA4aS6T~ ziFq4uWzFZ7;XWt&VDouaag9Sf*1we)n&cV#jxv8a^QK$W?*Lz9wEykr=NCry*D3aK zK2;S9nDgQIPR1wS7WT8>t9o&?tKc_#)nV>#$Hw2)Y(H<-JmoB7F=)DLH{s}wdNzeQ zQiq;zntEJ*|L^C20=F?8Igw=|aOiFSzLW*_eVh%`aJO_}nd zIQc>US>60!@n8IXKJ7FG^%X^wrpChSxDRQ+Fnzew}-F@OH_ zJ=yir!q2@%C`NR4~KYX z@11QQ^3V0>`<2NrOTEi0>n@c%U0Ta{IBR9--{TT~|M!SyFY!FAo%+98Ui(D+-5o1G z#r!*@#9II6_{N9nUuHX4B(@j7uBfdpea8^H_!qC&Ud}}61?q1OaacFFFspy4-rZNX zgh_wK8oh`ccQ1Ubs{A?Cb!kF*<=@jG*A{O#&Q4vC%(>m(;n%}|x&MlLdwah!OB`V3 znA;-DkY3-Md1cAMs@(bS8JpkheJy_2B+FEB@bYFaR(T_yJ#G*3W4}-1`j^1Gch3gK zD-2@QW=j)Svv2ZEvG@BS{v>b0oz&HTZ#%Q|1kIG&XJ?(*Rd2sZ`*&d*cUePi;yvqE zrU$rIynfGE^a0$xoXTp=vU~5Il1)8Z5A#X#8|lVoRjn;Pc;4csvGliyZA^1&@Ap&& z%eKy~UC^_2`kGx+T*G8}UO2zJ$(V5>ZQ8k6>y3CFyewpo;u)ASHu|Qd)!%U0hJy8}0jMiVC3VivNyT*yB!9s7jp6x}sZ;Aiy&dDDr ze)WfW@7Mo~M%G_+4L9h|nEK(aJdFKOYGib2s>AL26%MdIa`wTpq~ChKc0b{N@5Q-0Id1)*$B&*b zo+$(BK7GGd|LviIy{77%f6rsSxu-omcIWor{d}L2XC5;3TO09s)&G~`Vkay6mk0ey ze#h_P8ftgr>CxjSrz^(%jlcNu>x@KjH(AQ+z|@5H|9aZ1OE3T5@bvw$JK6u0r~TjV zcyEu~y25V{1*h%5Zu(!|s%#plm;9~2?5KS4ejB@mOD-K;mz~C|>E~}eD^cd&q{TL~ zqgH<5?|pUpqvzsYwq4)y1;wAQ`v10*)9!L{{`dFOr@YbjT%BmM`$yW_s>b(sHABz* zuKzQ$#{5H_<$X2pU7_pWt*SpSC7E<9{(SB1EmB9P@|Eq_`2WY1jj#IUBikl7mT&l= zyZ`#eqvyM>H{G@Gx+li){Qle9r^HV`m-^b@-(P;!Ue)v{xR<;>ZtJY~XCC{nvad^# z@MFJwa!q32D*L=w=1=7RYS{{w|xTxpPzSi`QcY(vv2XliK-7}man~EdE(bDJ*!{s*+G-0q^G2$ z814((e(c4M9rgL$pTrjTC!eynvij9D``^aGjp9CM{+|DN{P@vW58stVua>E7{--;6 zlK)|IMZ1F?|6g|R|C~R~{eDY}@rNTGJ{~1k?JW&Y&ZvKICwhUsh-09LD~-|9zJKz| YV|3EW+_cv-FfcH9y85}Sb4q9e0BqX ![](images/xla_array_layout_figure1.png) + +Figure 1 + +Figure 1 shows how an array F32[3,5] is laid out in memory with 2x2 tiling. A +shape with this layout is written as F32[3,5]{1,0:(2,2)}, where 1,0 relates to +the physical order of dimensions (minor_to_major field in Layout) while (2,2) +after the colon indicates tiling of the physical dimensions by a 2x2 tile. + +Intuitively tiles are laid out to cover the shape and then within each tile, +elements are then laid out without tiling, as in the example above, where the +right part of the example shows the layout in memory, including the white +padding elements that are added in order to have complete 2x2 tiles even though +the original array bounds are not even. + +The extra elements in the padding are not required to contain any particular +value. + +## Linear index formulas for tiling given a shape and a tile + +Without tiling, an element e=(en, en-1, ... , +e1) in an array with array bounds d=(dn, dn-1, +... , d1) (d1 is the most minor dimension) is laid out by major to +minor order at position: + +   linear_index(e, d) \ += linear_index((en, en-1, ... , e1), +(dn, dn-1, ... , d1)) \ += endn-1...d1 + +en-1dn-2...d1 + ... + e1 + +For simplicity of notation in this document we assume a tile has the same number +of dimensions as the array. In XLA's implementation of tiling, this is +generalized to tilings with fewer dimensions by leaving the initial most-major +dimensions unchanged and applying the tiling only to the most minor dimensions, +so that the tiling that is specified mentions a suffix of the physical +dimensions of the shape being tiled. + +When tiling of size (tn, tn-1, ... , t1) is +used, an element in the array with indices (en, en-1, ... +, e1) is mapped to this position in the final layout: + +   linear_index_with_tile(e, d, t) \ += linear_index((⌊e/t⌋, e mod t), (⌈d/t⌉, t))     (arithmetic is +elementwise, (a,b) is concatenation) \ += linear_index((⌊en/tn⌋, ... , +⌊e1/t1⌋, en mod tn, ... , +e1 mod t1), (⌈dn/tn⌉, ... , +⌈d1/t1⌉, tn, tn-1, ... , +t1)) \ += linear_index((⌊en/tn⌋, ... , +⌊e1/t1⌋), (⌈dn/tn⌉, ... , +⌈d1/t1⌉))∙tntn-1...t1 + +linear_index((en mod tn, ... , e1 mod +t1), (tn, tn-1, ... , t1)) + +The layout can be thought of as having two parts: +(⌊en/tn⌋, ... , ⌊e1/t1⌋), which +corresponds to a tile index in an array of tiles of size +(⌈dn/tn⌉, ... , ⌈d1/t1⌉), and +(en mod tn, ... , e1 mod t1), which +corresponds to a within-tile index. The ceil function appears in +⌈di/ti⌉ because if tiles overrun the bounds of the larger +array, padding is inserted as in Figure 1. Both the tiles and elements within +tiles are laid out recursively without tiling. + +For the example in Figure 1, element (2,3) has tile index (1,1), and within-tile +index (0,1), for a combined coordinate vector of (1, 1, 0, 1). The tile indices +have bounds (2, 3) and the tile itself is (2, 2) for a combined vector of (2, 3, +2, 2). The linear index with tile for the element with index (2, 3) in the +logical shape is then + +   linear_index_with_tile((2,3), (3,5), (2,2)) \ += linear_index((1,1,0,1), (2,3,2,2)) \ += linear_index((1,1), (2,3)) ∙ 2 ∙ 2 + linear_index((0,1), (2,2)) \ += (1 ∙ 3 + 1) ∙ 2 ∙ 2 + (0 ∙ 2 + 1) \ += 17. + +# Tiling as pad-reshape-transpose + +Tiling-based layout operates as follows: \ +Consider an array of dimensions (dn, dn-1, ... , d1) (d1 +is the most minor dimension). When it’s laid out with tiling of size +(tn, tn-1, ... , t1) (t1 is the most +minor dimension), that tiling can be described in terms of pad-reshape-transpose +in the following way. + +1. The array is padded to (⌈dn/tn⌉∙tn, ... , + ⌈d1/t1⌉∙t1). +2. Each dimension i is broken into (⌈di/ti⌉, + ti), i.e. the array is reshaped to \ +     (⌈dn/tn⌉, tn, ... , + ⌈d1/t1⌉, t1). \ + There is no physical layout change in this reshape by itself, so this + reshape is a bitcast. If one is not explicitly thinking of a tiling, this + reshape could express any shape with the same number of elements as the + padded shape - the example here is of how to express a tile in this way. +3. A transpose happens by moving tn, ... , t1 to the most + minor dimensions while keeping their relative order, so that the order of + dimensions from most major to most minor becomes \ +     (⌈dn/tn⌉, ... , + ⌈d1/t1⌉, tn, ... , t1). + +The final shape has the prefix \ +    (⌈dn/tn⌉, ... , +⌈d1/t1⌉), which describes the number of tiles in each +dimension. An element in the array (en, ... , e1) is +mapped to this element in the final shape: \ +    (⌊en/tn⌋, ... , +⌊e0/t0⌋, en mod tn, ... , +e1 mod t1). It is easy to see that the linear index of the +element follows the formula above as expected. + +# Repeated tiling + +XLA's tiling becomes even more flexible by applying it repeatedly. + +
![](images/xla_array_layout_figure2.png) + +Figure 2
+ +Figure 2 shows how an array of size 4x8 is tiled by two levels of tiling (first +2x4 then 2x1). We represent this repeated tiling as (2,4)(2,1). Each color +indicates a 2x4 tile and each red border box is a 2x1 tile. The numbers +indicates the linear index in memory of that element in the tiled format. This +format matches the format used for BF16 on TPU, except that the initial tile is +bigger, namely the tiling is (8,128)(2,1), where the purpose of the second +tiling by 2x1 is to collect together two 16 bit values to form one 32 bit value +in a way that aligns with the architecture of a TPU. + +Note that a second or later tile can refer to both the minor within-tile +dimensions, which just rearranges data within the tile, as in this example with +(8,128)(2,1), but can also refer to the major cross-tile dimensions from the +prior tiling. + +# Combining dimensions using tiles + +XLA's tiling also supports combining dimensions. For example, it can combine +dimensions in F32[2,7,8,11,10]{4,3,2,1,0} into F32[112,110]{1,0} first before +tiling it with (2,3). The tile used is (∗,∗,2,∗,3). Here an +asterisk in a tile implies taking that dimension and combining it with the next +more minor dimension. Multiple adjacent dimensions can be subsumed together into +one dimension. A subsumed dimension is represented by a tile value of -1 in that +dimension of the tile, which is not otherwise valid in a tile as a dimension +size. + +More precisely, if dimension i of the shape is eliminated via an asterisk in the +tile, then before the prior definition of tiling is applied, that dimension is +removed from both the shape being tiled and the tile vector, and what was +dimension i-1 of the shape has its array bound increased from di-1 to +didi-1. This step is repeated for each asterisk in the +tile vector. diff --git a/tensorflow/compiler/xla/g3doc/operation_semantics.md b/tensorflow/compiler/xla/g3doc/operation_semantics.md index 73a9db75f6..d888b1f23f 100644 --- a/tensorflow/compiler/xla/g3doc/operation_semantics.md +++ b/tensorflow/compiler/xla/g3doc/operation_semantics.md @@ -13,6 +13,22 @@ arbitrary-dimensional array. For convenience, special cases have more specific and familiar names; for example a *vector* is a 1-dimensional array and a *matrix* is a 2-dimensional array. +## AfterAll + +See also +[`XlaBuilder::AfterAll`](https://www.tensorflow.org/code/tensorflow/compiler/xla/client/xla_builder.h). + +AfterAll takes a variadic number of tokens and produces a single token. Tokens +are primitive types which can be threaded between side-effecting operations to +enforce ordering. `AfterAll` can be used as a join of tokens for ordering a +operation after a set operations. + + `AfterAll(operands)` + +Arguments | Type | Semantics +---------- | ------- | ------------------------- +`operands` | `XlaOp` | variadic number of tokens + ## AllToAll See also @@ -402,6 +418,33 @@ then v12 == f32[8x3] {{10, 11, 12}, ``` +## CollectivePermute + +See also +[`XlaBuilder::CollectivePermute`](https://www.tensorflow.org/code/tensorflow/compiler/xla/client/xla_builder.h). + +CollectivePermute is a collective operation that sends and receives data cross +replicas. + + `CollectivePermute(operand, source_target_pairs)` + +| Arguments | Type | Semantics | +| --------------------- | ----------------------- | -------------------------- | +| `operand` | `XlaOp` | n dimensional input array | +| `source_target_pairs` | `` vector | A list of | +: : : (source_replica_id, : +: : : target_replica_id) pairs. : +: : : For each pair, the operand : +: : : is sent from source : +: : : replica to target replica. : + +Note that there are the following restrictions on the `source_target_pair`: + +- Any two pairs should not have the same target replica id, and they should + not have the same source replica id. +- If a replica id is not a target in any pair, then the output on that replica + is a tensor consists of 0(s) with the same shape as the input. + ## Concatenate See also @@ -1423,10 +1466,11 @@ Builds a constant literal on device rather than a potentially large host transfer. Creates a rank 1 array of values starting at zero and incrementing by one. -Arguments | Type | Semantics ---------- | --------------- | ------------------------------------ -`type` | `PrimitiveType` | type U -`size` | `int64` | The number of elements in the array. +Arguments | Type | Semantics +---------------- | --------------- | ------------------------------------ +`type` | `PrimitiveType` | type U +`size` | `int64` | The number of elements in the array. +`iota_dimension` | `int64` | The dimension to increment along. ## Map @@ -1780,8 +1824,9 @@ XlaBuilder builder(client_, "reduce_window_2x3"); auto shape = ShapeUtil::MakeShape(F32, {4, 6}); auto input = builder.Parameter(0, shape, "input"); builder.ReduceWindow( - input, *max, + input, /*init_val=*/builder.ConstantLiteral(LiteralUtil::MinValue(F32)), + *max, /*window_dimensions=*/{2, 3}, /*window_stride_dimensions=*/{2, 3}, Padding::kValid); diff --git a/tensorflow/compiler/xla/g3doc/tutorials/xla_compile.ipynb b/tensorflow/compiler/xla/g3doc/tutorials/xla_compile.ipynb index a83e3f7859..2a83092805 100644 --- a/tensorflow/compiler/xla/g3doc/tutorials/xla_compile.ipynb +++ b/tensorflow/compiler/xla/g3doc/tutorials/xla_compile.ipynb @@ -1,25 +1,38 @@ { + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "The XLA compile API", + "version": "0.3.2", + "provenance": [], + "collapsed_sections": [], + "toc_visible": true + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + } + }, "cells": [ { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "f4TSNCvpENrW" }, + "cell_type": "markdown", "source": [ "##### Copyright 2018 The TensorFlow Authors." ] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { "cellView": "form", - "colab": {}, "colab_type": "code", - "id": "vamNSA0vEP-m" + "id": "vamNSA0vEP-m", + "colab": {} }, - "outputs": [], + "cell_type": "code", "source": [ "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", @@ -32,139 +45,84 @@ "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License." - ] - }, - { - "cell_type": "code", + ], "execution_count": 0, - "metadata": { - "cellView": "form", - "colab": {}, - "colab_type": "code", - "id": "xD_ydfejEV7H" - }, - "outputs": [], - "source": [ - "#@title MIT License\n", - "#\n", - "# Copyright (c) 2017 François Chollet\n", - "#\n", - "# Permission is hereby granted, free of charge, to any person obtaining a\n", - "# copy of this software and associated documentation files (the \"Software\"),\n", - "# to deal in the Software without restriction, including without limitation\n", - "# the rights to use, copy, modify, merge, publish, distribute, sublicense,\n", - "# and/or sell copies of the Software, and to permit persons to whom the\n", - "# Software is furnished to do so, subject to the following conditions:\n", - "#\n", - "# The above copyright notice and this permission notice shall be included in\n", - "# all copies or substantial portions of the Software.\n", - "#\n", - "# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n", - "# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n", - "# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\n", - "# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n", - "# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n", - "# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n", - "# DEALINGS IN THE SOFTWARE." - ] + "outputs": [] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "e1oSi4lHFt3z" }, + "cell_type": "markdown", "source": [ - "# Welcome to `xla.compile()` tutorial" + "# The XLA compile API" ] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "b7noD9NjFRL-" }, + "cell_type": "markdown", "source": [ - "\u003ctable class=\"tfo-notebook-buttons\" align=\"left\"\u003e\n", - " \u003ctd\u003e\n", - " \u003ca target=\"_blank\" href=\"https://www.tensorflow.org/xla/jit#turning_on_jit_compilation\"\u003e\u003cimg src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" /\u003eView on TensorFlow.org\u003c/a\u003e\n", - " \u003c/td\u003e\n", - " \u003ctd\u003e\n", - " \u003ca target=\"_blank\" href=\"https://colab.sandbox.google.com/github/tensorflow/compiler/xla/g3doc/tutorials/xla_compile.ipynb\"\u003e\u003cimg src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" /\u003eRun in Google Colab\u003c/a\u003e\n", - " \u003c/td\u003e\n", - " \u003ctd\u003e\n", - " \u003ca target=\"_blank\" href=\"https://github.com/tensorflow/compiler/xla/g3doc/tutorials/xla_compile.ipynb\"\u003e\u003cimg src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" /\u003eView source on GitHub\u003c/a\u003e\n", - " \u003c/td\u003e\n", - "\u003c/table\u003e" + "\n", + " \n", + " \n", + " \n", + "
\n", + " View on TensorFlow.org\n", + " \n", + " Run in Google Colab\n", + " \n", + " View source on GitHub\n", + "
" ] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "v9YbsuLZaBXy" }, + "cell_type": "markdown", "source": [ - "xla.compile() is a new experimental API that compiles part or all of a model with [XLA](https://www.tensorflow.org/extend/xla/).\n", "\n", - "Please run all code blocks in order." + "\n", + "Import TensorFlow and the XLA library. XLA contains `xla.compile()`, an experimental API that compiles part or all of a model with [XLA](https://www.tensorflow.org/extend/xla/)." ] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { - "colab": {}, "colab_type": "code", - "id": "45kUPj5ZFrRa" - }, - "outputs": [], - "source": [ - "import tensorflow as tf" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "9NMQFjroSMns" + "id": "45kUPj5ZFrRa", + "colab": {} }, - "source": [ - "Imports XLA library, which includes xla.compile() experimental API." - ] - }, - { "cell_type": "code", - "execution_count": 0, - "metadata": { - "colab": {}, - "colab_type": "code", - "id": "-Uggy03rSGJm" - }, - "outputs": [], "source": [ + "import tensorflow as tf\n", + "\n", "from tensorflow.contrib.compiler import xla" - ] + ], + "execution_count": 0, + "outputs": [] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "GZVNiRmTDV-5" }, + "cell_type": "markdown", "source": [ - "Define some necessary constants and prepare MNIST dataset." + "Define some necessary constants and prepare the MNIST dataset." ] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { - "colab": {}, "colab_type": "code", - "id": "f37TSEGvGX4_" + "id": "f37TSEGvGX4_", + "colab": {} }, - "outputs": [], + "cell_type": "code", "source": [ "# Size of each input image, 28 x 28 pixels\n", "IMAGE_SIZE = 28 * 28\n", @@ -174,17 +132,17 @@ "TRAIN_BATCH_SIZE = 100\n", "# Number of training steps to run\n", "TRAIN_STEPS = 1000" - ] + ], + "execution_count": 0, + "outputs": [] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { - "colab": {}, "colab_type": "code", - "id": "TiVXchblG5hK" + "id": "TiVXchblG5hK", + "colab": {} }, - "outputs": [], + "cell_type": "code", "source": [ "# Loads MNIST dataset.\n", "train, test = tf.keras.datasets.mnist.load_data()\n", @@ -195,16 +153,18 @@ "images, labels = iterator.get_next()\n", "images = tf.reshape(images, [-1, IMAGE_SIZE])\n", "images, labels = tf.cast(images, tf.float32), tf.cast(labels, tf.int64)" - ] + ], + "execution_count": 0, + "outputs": [] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "x_ZehpZP-SfS" }, + "cell_type": "markdown", "source": [ - "## Defines build_mnist_model function to construct model\n", + "# Define the model constructing function\n", "\n", "Following code block contains a function that constructs a simple model with one dense layer, including both forward and backward propagation.\n", "\n", @@ -212,14 +172,12 @@ ] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { - "colab": {}, "colab_type": "code", - "id": "ZbhJl_WvGa3g" + "id": "ZbhJl_WvGa3g", + "colab": {} }, - "outputs": [], + "cell_type": "code", "source": [ "def build_mnist_model(x, y_):\n", " y = tf.keras.layers.Dense(NUM_CLASSES).apply(x)\n", @@ -228,47 +186,41 @@ " train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)\n", "\n", " return y, train_step" - ] + ], + "execution_count": 0, + "outputs": [] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "7Jh3lyQHDfM9" }, - "source": [ - "## Uses xla.compile with build_mnist_model function to enable XLA" - ] - }, - { "cell_type": "markdown", - "metadata": { - "colab_type": "text", - "id": "EtDwez_1gjzv" - }, "source": [ - "Following code block wraps the model with xla.compile(), which allows the target function with provided inputs to be executed by XLA." + "# Enable XLA\n", + "\n", + "Use `xla.compile` with the `build_mnist_model` function to enable XLA. Following code block wraps the model with `xla.compile()`, which allows the target function with provided inputs to be executed by XLA." ] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { - "colab": {}, "colab_type": "code", - "id": "kYpCXCdRHNuN" + "id": "kYpCXCdRHNuN", + "colab": {} }, - "outputs": [], + "cell_type": "code", "source": [ "[y] = xla.compile(build_mnist_model, inputs=[images, labels])" - ] + ], + "execution_count": 0, + "outputs": [] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "4giQh62IrZGF" }, + "cell_type": "markdown", "source": [ "When compiling the graph, XLA replaces all the graph nodes constructed in the target function with a few XLA ops.\n", "\n", @@ -293,62 +245,62 @@ ] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "TPGas4jjFLZl" }, + "cell_type": "markdown", "source": [ "If you were to print the constructed graph now, you will see that it is not much different from a normal Tensorflow graph and you won't be able to find XLA ops mentioned before. This is because the actual compilation happens later when you try to execute the graph with `sess.run()`. At that time, Tensorflow triggers a series of graph rewrite passes that actually generate XLA ops, which compiles and executes computation when all inputs are ready." ] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "EZD1m_n1DxAF" }, + "cell_type": "markdown", "source": [ - "## Trains and tests the model" + "# Train and test the model" ] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { - "colab": {}, "colab_type": "code", - "id": "qe28bAHNHUG2" + "id": "qe28bAHNHUG2", + "colab": {} }, - "outputs": [], + "cell_type": "code", "source": [ "# Creates session and initialize all variables.\n", "# xla.compile() doesn't work with Keras model.fit() API or TF eager mode yet.\n", "sess = tf.Session()\n", "sess.run(tf.global_variables_initializer())" - ] + ], + "execution_count": 0, + "outputs": [] }, { - "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "qgsKmz3n2UiW" }, + "cell_type": "markdown", "source": [ - "Following code block trains model.\n", - "\n", - "Note that evaluating `y` also triggers its control dependency node `train_step`, which updates model variables." + "Following code block trains model. Evaluating `y` also triggers its control dependency node `train_step`, which updates model variables." ] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { - "colab": {}, "colab_type": "code", - "id": "_GxF6jTRHVuA" + "id": "_GxF6jTRHVuA", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + }, + "outputId": "fbf299ca-02d5-4e95-f9fe-8f3c0432d132" }, - "outputs": [], + "cell_type": "code", "source": [ "# Feeds training dataset\n", "sess.run(iterator.make_initializer(train_ds))\n", @@ -356,18 +308,31 @@ "# Runs TRAIN_STEPS steps\n", "for i in range(TRAIN_STEPS):\n", " sess.run(y)\n", + "\n", "print(\"Model trained for %s steps.\" % TRAIN_STEPS)" + ], + "execution_count": 21, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Model trained for 1000 steps.\n" + ], + "name": "stdout" + } ] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { - "colab": {}, "colab_type": "code", - "id": "dHlQlRSRHXD1" + "id": "dHlQlRSRHXD1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + }, + "outputId": "9c3677a2-ec84-406f-9d2c-d722844f3093" }, - "outputs": [], + "cell_type": "code", "source": [ "# Tests trained model\n", "\n", @@ -378,35 +343,31 @@ "correct_prediction = tf.equal(tf.argmax(y, 1), labels)\n", "accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))\n", "print(\"Prediction accuracy after training: %s\" % sess.run(accuracy))" + ], + "execution_count": 22, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Prediction accuracy after training: 0.91\n" + ], + "name": "stdout" + } ] }, { - "cell_type": "code", - "execution_count": 0, "metadata": { - "colab": {}, "colab_type": "code", - "id": "ynJQIuzjHYOb" + "id": "ynJQIuzjHYOb", + "colab": {} }, - "outputs": [], + "cell_type": "code", "source": [ "# Cleans up session\n", "sess.close()" - ] - } - ], - "metadata": { - "colab": { - "collapsed_sections": [], - "name": "xla.compile() Tutorial", - "provenance": [], - "version": "0.3.2" - }, - "kernelspec": { - "display_name": "Python 2", - "name": "python2" + ], + "execution_count": 0, + "outputs": [] } - }, - "nbformat": 4, - "nbformat_minor": 0 -} + ] +} \ No newline at end of file diff --git a/tensorflow/compiler/xla/index_util.h b/tensorflow/compiler/xla/index_util.h index 458bdaf2f8..d76f61eb62 100644 --- a/tensorflow/compiler/xla/index_util.h +++ b/tensorflow/compiler/xla/index_util.h @@ -21,6 +21,7 @@ limitations under the License. #include #include "absl/types/span.h" +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/xla_data.pb.h" #include "tensorflow/core/platform/macros.h" diff --git a/tensorflow/compiler/xla/layout_util.cc b/tensorflow/compiler/xla/layout_util.cc index 2398470dd4..dbb81381ac 100644 --- a/tensorflow/compiler/xla/layout_util.cc +++ b/tensorflow/compiler/xla/layout_util.cc @@ -460,6 +460,13 @@ std::ostream& operator<<(std::ostream& out, const Layout& layout) { } hash_value = Hash64Combine(hash_value, layout.max_sparse_elements()); + for (Tile tile : layout.tiles()) { + for (int64 tile_dim : tile.dimensions()) { + hash_value = Hash64Combine(hash_value, hash()(tile_dim)); + } + } + hash_value = Hash64Combine(hash_value, layout.element_size_in_bits()); + return hash_value; } diff --git a/tensorflow/compiler/xla/layout_util.h b/tensorflow/compiler/xla/layout_util.h index 6e0390763d..6c298e5725 100644 --- a/tensorflow/compiler/xla/layout_util.h +++ b/tensorflow/compiler/xla/layout_util.h @@ -21,6 +21,7 @@ limitations under the License. #include #include "absl/types/span.h" +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/status.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/xla_data.pb.h" diff --git a/tensorflow/compiler/xla/literal.cc b/tensorflow/compiler/xla/literal.cc index cb00a0ab16..8f480c1f10 100644 --- a/tensorflow/compiler/xla/literal.cc +++ b/tensorflow/compiler/xla/literal.cc @@ -27,6 +27,7 @@ limitations under the License. #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" +#include "absl/types/span.h" #include "tensorflow/compiler/xla/index_util.h" #include "tensorflow/compiler/xla/shape_util.h" #include "tensorflow/compiler/xla/status_macros.h" @@ -62,6 +63,14 @@ void ConvertEndianShort(char* bytes, int64 size) { } } +// Since Eigen::half doesn't satisfy the absl::bit_cast contract, we need to be +// able to transparently access the raw 16-bit value contained within. +template +T GetRawValue(T val) { + return val; +} +uint16 GetRawValue(Eigen::half val) { return val.x; } + } // namespace LiteralBase::~LiteralBase() {} @@ -283,16 +292,17 @@ Status MutableLiteralBase::CopyElementFrom(const LiteralSlice& src_literal, if (!proto.has_shape()) { return InvalidArgument("LiteralProto has no shape"); } - if (ShapeUtil::HasPrimitiveType(proto.shape(), OPAQUE)) { + Shape shape(proto.shape()); + if (ShapeUtil::HasPrimitiveType(shape, OPAQUE)) { return InvalidArgument("Literal shape cannot include OPAQUE sub-shape"); } - if (!LayoutUtil::HasLayout(proto.shape())) { + if (!LayoutUtil::HasLayout(shape)) { return InvalidArgument("LiteralProto has no layout"); } - TF_RETURN_IF_ERROR(ShapeUtil::ValidateShapeWithOptionalLayout(proto.shape())); + TF_RETURN_IF_ERROR(ShapeUtil::ValidateShapeWithOptionalLayout(shape)); - Literal literal(proto.shape()); + Literal literal(shape); TF_RETURN_IF_ERROR(literal.root_piece_->ForEachMutableSubpieceWithStatus( [&](const ShapeIndex& index, Piece* piece) { @@ -1012,166 +1022,143 @@ void LiteralBase::Piece::SortSparseElementsInternal() { namespace { -void ToStringHelper(const LiteralBase& literal, const ShapeIndex& shape_index, - bool print_layout, std::vector* pieces) { - const Shape& subshape = ShapeUtil::GetSubshape(literal.shape(), shape_index); - CHECK(LayoutUtil::HasLayout(literal.shape())); - CHECK(LayoutUtil::HasLayout(subshape)); +string ShapeToString(bool print_layout, const Shape& shape) { + return print_layout ? ShapeUtil::HumanStringWithLayout(shape) + : ShapeUtil::HumanString(shape); +} - auto shape_to_string = [print_layout](const Shape& shape) { - if (print_layout) { - return ShapeUtil::HumanStringWithLayout(shape); - } else { - return ShapeUtil::HumanString(shape); - } - }; +void ToStringHelper(const LiteralBase& literal, const ShapeIndex& shape_index, + bool print_layout, std::vector* pieces); - // TODO(b/32894291): refactor this code to reduce code duplication. - if (ShapeUtil::IsTuple(subshape)) { - pieces->push_back(shape_to_string(subshape)); - pieces->push_back(" (\n"); - std::vector tuple_pieces; - for (int i = 0; i < ShapeUtil::TupleElementCount(subshape); ++i) { - ShapeIndex element_index = shape_index; - element_index.push_back(i); - std::vector element_pieces; - ToStringHelper(literal, element_index, print_layout, &element_pieces); - tuple_pieces.push_back(absl::StrJoin(element_pieces, "")); +void TupleToStringHelper(const LiteralBase& literal, + const ShapeIndex& shape_index, bool print_layout, + std::vector* pieces) { + const Shape& subshape = ShapeUtil::GetSubshape(literal.shape(), shape_index); + pieces->push_back(ShapeToString(print_layout, subshape)); + pieces->push_back(" (\n"); + std::vector tuple_pieces; + for (int i = 0; i < ShapeUtil::TupleElementCount(subshape); ++i) { + ShapeIndex element_index = shape_index; + element_index.push_back(i); + std::vector element_pieces; + ToStringHelper(literal, element_index, print_layout, &element_pieces); + tuple_pieces.push_back(absl::StrJoin(element_pieces, "")); + } + pieces->push_back(absl::StrJoin(tuple_pieces, ",\n")); + pieces->push_back("\n)"); +} + +void SparseArrayToStringHelper(const LiteralBase& literal, + const Shape& subshape, bool print_layout, + std::vector* pieces) { + pieces->push_back(ShapeToString(print_layout, subshape)); + pieces->push_back("{"); + int64 rank = ShapeUtil::Rank(subshape); + int64 num_elements = literal.sparse_element_count(); + for (int64 i = 0; i < num_elements; ++i) { + if (i > 0) { + pieces->push_back(", "); } - pieces->push_back(absl::StrJoin(tuple_pieces, ",\n")); - pieces->push_back("\n)"); - return; - } - - if (ShapeUtil::IsToken(subshape)) { - pieces->push_back("token"); - return; - } - - if (LayoutUtil::IsSparseArray(subshape)) { - pieces->push_back(shape_to_string(subshape)); - pieces->push_back("{"); - int64 rank = ShapeUtil::Rank(subshape); - int64 num_elements = literal.sparse_element_count(); - for (int64 i = 0; i < num_elements; ++i) { - if (i > 0) { - pieces->push_back(", "); - } - if (rank == 1) { - pieces->push_back(StrCat(literal.GetSparseIndex(i)[0])); - pieces->push_back(": "); - } else { - pieces->push_back("["); - pieces->push_back(absl::StrJoin(literal.GetSparseIndex(i), ", ")); - pieces->push_back("]: "); - } - pieces->push_back(literal.GetSparseElementAsString(i)); + if (rank == 1) { + pieces->push_back(StrCat(literal.GetSparseIndex(i)[0])); + pieces->push_back(": "); + } else { + pieces->push_back("["); + pieces->push_back(absl::StrJoin(literal.GetSparseIndex(i), ", ")); + pieces->push_back("]: "); } - pieces->push_back("}"); - return; + pieces->push_back(literal.GetSparseElementAsString(i)); } + pieces->push_back("}"); +} - CHECK(LayoutUtil::IsDenseArray(subshape)); - - auto element_to_string = [&](absl::Span indices) -> string { - PrimitiveType element_type = subshape.element_type(); - // We display predicates as 0s and 1s so that the string is more dense. - string elem = element_type == PRED - ? literal.Get(indices, shape_index) ? "1" : "0" - : literal.GetAsString(indices, shape_index); - return ((!indices.empty() && indices.back() > 0) ? ", " : "") + elem; - }; +void DenseArrayToStringHelper(const LiteralBase& literal, + const ShapeIndex& shape_index, bool print_layout, + std::vector* pieces) { + const Shape& subshape = ShapeUtil::GetSubshape(literal.shape(), shape_index); + int64 rank = ShapeUtil::Rank(subshape); + + std::function dimensions, std::vector*)> + to_string_recursive = [&](absl::Span dimensions, + std::vector* accum_indices) { + // dimensions.size() decreases by 1 at each recursive call, + // and accum_indices->size() increases by 1. + // Their sum is equal to the rank of the tensor. + CHECK_EQ(rank, dimensions.size() + accum_indices->size()); + + auto brace_to_string = [&](string brace) -> string { + // Handle 1D tensor + if (rank == 1) { + return brace; + } + // Handle the innermost tensor of a 2D+ tensor. + if (dimensions.size() == 1 && brace == "{") { + return StrCat(" ", brace, dimensions[0] <= 1 ? "" : " "); + } + if (dimensions.size() == 1 && brace == "}") { + return StrCat(dimensions[0] <= 1 ? "" : " ", brace); + } + // Handle the non-innermost tensors of a 2D+ tensor. + if (brace == "{") { + if (rank > 3 && !accum_indices->empty() && + accum_indices->size() < rank) { + int index = accum_indices->size() - 1; + int value = accum_indices->back(); + return StrCat(brace, " /*i", index, "=", value, "*/\n"); + } + return StrCat(brace, "\n"); + } + return StrCat("\n", brace); + }; - if (ShapeUtil::Rank(subshape) == 0) { - pieces->push_back(literal.GetAsString({}, shape_index)); - } else if (ShapeUtil::Rank(subshape) == 1) { - pieces->push_back("{"); - for (int64 i0 = 0; i0 < subshape.dimensions(0); ++i0) { - pieces->push_back(element_to_string({i0})); - } - pieces->push_back("}"); - } else if (ShapeUtil::Rank(subshape) == 2) { - pieces->push_back(shape_to_string(subshape)); - pieces->push_back(" {\n"); - for (int64 i0 = 0; i0 < subshape.dimensions(0); ++i0) { - pieces->push_back(" { "); - for (int64 i1 = 0; i1 < subshape.dimensions(1); ++i1) { - pieces->push_back(element_to_string({i0, i1})); - } - pieces->push_back(" "); - pieces->push_back(i0 == subshape.dimensions(0) - 1 ? "}\n" : "},\n"); - } - pieces->push_back("}"); - } else if (ShapeUtil::Rank(subshape) == 3) { - pieces->push_back(shape_to_string(subshape)); - pieces->push_back(" {\n"); - for (int64 i0 = 0; i0 < subshape.dimensions(0); ++i0) { - pieces->push_back(i0 > 0 ? ",\n{" : "{"); - for (int64 i1 = 0; i1 < subshape.dimensions(1); ++i1) { - pieces->push_back(i1 > 0 ? ",\n { " : " { "); - for (int64 i2 = 0; i2 < subshape.dimensions(2); ++i2) { - pieces->push_back(element_to_string({i0, i1, i2})); - } - pieces->push_back(" }"); - } - pieces->push_back(" }"); - } - pieces->push_back("\n}"); - } else if (ShapeUtil::Rank(subshape) == 4) { - pieces->push_back(shape_to_string(subshape)); - pieces->push_back(" {\n"); - for (int64 i0 = 0; i0 < subshape.dimensions(0); ++i0) { - pieces->push_back(StrFormat(" { /*i0=%d*/\n", i0)); - for (int64 i1 = 0; i1 < subshape.dimensions(1); ++i1) { - pieces->push_back(StrFormat(" { /*i1=%d*/\n", i1)); - for (int64 i2 = 0; i2 < subshape.dimensions(2); ++i2) { - pieces->push_back(" {"); - for (int64 i3 = 0; i3 < subshape.dimensions(3); ++i3) { - pieces->push_back(element_to_string({i0, i1, i2, i3})); + if (dimensions.empty()) { + // Display predicates as 0s and 1s so that the string is more dense. + string elem; + if (subshape.element_type() == PRED && rank > 0) { + elem = literal.Get(*accum_indices, shape_index) ? "1" : "0"; + } else { + elem = literal.GetAsString(*accum_indices, shape_index); } - pieces->push_back(i2 == subshape.dimensions(2) - 1 ? "}\n" : "},\n"); - } - pieces->push_back(i1 == subshape.dimensions(1) - 1 ? " }\n" - : " },\n"); - } - pieces->push_back(i0 == subshape.dimensions(0) - 1 ? " }\n" : " },\n"); - } - pieces->push_back("}"); - } else if (ShapeUtil::Rank(subshape) == 5) { - pieces->push_back(shape_to_string(subshape)); - pieces->push_back(" {\n"); - for (int64 i0 = 0; i0 < subshape.dimensions(0); ++i0) { - pieces->push_back(StrFormat(" { /*i0=%d*/\n", i0)); - for (int64 i1 = 0; i1 < subshape.dimensions(1); ++i1) { - pieces->push_back(StrFormat(" { /*i1=%d*/\n", i1)); - for (int64 i2 = 0; i2 < subshape.dimensions(2); ++i2) { - pieces->push_back(StrFormat(" { /*i2=%d*/\n", i2)); - for (int64 i3 = 0; i3 < subshape.dimensions(3); ++i3) { - pieces->push_back(" {"); - for (int64 i4 = 0; i4 < subshape.dimensions(4); ++i4) { - pieces->push_back(element_to_string({i0, i1, i2, i3, i4})); + pieces->push_back(elem); + } else { + pieces->push_back(brace_to_string("{")); + for (int i = 0; i < dimensions[0]; ++i) { + std::vector cloned_indices(*accum_indices); + cloned_indices.push_back(i); + to_string_recursive(dimensions.subspan(1), &cloned_indices); + if (i < dimensions[0] - 1) { + pieces->push_back(","); + pieces->push_back(dimensions.size() > 1 ? "\n" : " "); } - pieces->push_back(i3 == subshape.dimensions(3) - 1 ? "}\n" - : "},\n"); } - pieces->push_back(i2 == subshape.dimensions(2) - 1 ? " }\n" - : " },\n"); + pieces->push_back(brace_to_string("}")); } - pieces->push_back(i1 == subshape.dimensions(1) - 1 ? " }\n" - : " },\n"); - } - pieces->push_back(i0 == subshape.dimensions(0) - 1 ? " }\n" : " },\n"); - } - pieces->push_back("}"); + }; + + if (rank > 1) { + pieces->push_back(ShapeToString(print_layout, subshape)); + pieces->push_back(" "); + } + std::vector indices = {}; + std::vector dimensions(subshape.dimensions().begin(), + subshape.dimensions().end()); + to_string_recursive(dimensions, &indices); +} + +void ToStringHelper(const LiteralBase& literal, const ShapeIndex& shape_index, + bool print_layout, std::vector* pieces) { + const Shape& subshape = ShapeUtil::GetSubshape(literal.shape(), shape_index); + CHECK(LayoutUtil::HasLayout(literal.shape())); + CHECK(LayoutUtil::HasLayout(subshape)); + if (ShapeUtil::IsTuple(subshape)) { + TupleToStringHelper(literal, shape_index, print_layout, pieces); + } else if (ShapeUtil::IsToken(subshape)) { + pieces->push_back("token"); + } else if (LayoutUtil::IsSparseArray(subshape)) { + SparseArrayToStringHelper(literal, subshape, print_layout, pieces); } else { - pieces->push_back(shape_to_string(subshape)); - pieces->push_back(" {"); - literal.EachCellAsString( - [&](absl::Span indices, const string& value) { - pieces->push_back(" "); - pieces->push_back(value); - }); - pieces->push_back("}"); + CHECK(LayoutUtil::IsDenseArray(subshape)); + DenseArrayToStringHelper(literal, shape_index, print_layout, pieces); } } @@ -1228,16 +1215,32 @@ Literal ConvertBetweenNativeTypes(const LiteralBase& src_literal) { } template -typename std::enable_if<(sizeof(NativeSrcT) == sizeof(NativeDestT)), +typename std::enable_if<(sizeof(NativeSrcT) == sizeof(NativeDestT) && + !std::is_same::value), Literal>::type BitcastBetweenNativeTypes(const LiteralBase& src_literal) { auto converter = [](NativeSrcT src) { - return absl::bit_cast(src); + return absl::bit_cast(GetRawValue(src)); }; return ConvertBetweenNativeTypesWithConverter( src_literal, converter); } +template +typename std::enable_if<(sizeof(NativeSrcT) == sizeof(Eigen::half) && + std::is_same::value), + Literal>::type +BitcastBetweenNativeTypes(const LiteralBase& src_literal) { + // Eigen::half doesn't satisfy the absl::bit_cast contract, so explicitly + // cast to unsigned short and then use raw_uint16_to_half. + auto converter = [](NativeSrcT src) { + return Eigen::half_impl::raw_uint16_to_half( + absl::bit_cast(GetRawValue(src))); + }; + return ConvertBetweenNativeTypesWithConverter( + src_literal, converter); +} + // This template specialization is here to make the compiler happy. bit_cast has // a static check that the types are the same size. This specialization should // never be used because the source and destination types are checked for @@ -1792,7 +1795,7 @@ void CopyToRepeatedField(RepeatedFieldT* dest, } // namespace void LiteralBase::Piece::WriteToProto(LiteralProto* proto) const { - *proto->mutable_shape() = subshape(); + *proto->mutable_shape() = subshape().ToProto(); switch (subshape().element_type()) { case PRED: CopyToRepeatedField(proto->mutable_preds(), data()); @@ -1898,8 +1901,9 @@ Status LiteralBase::Piece::CopyFromProto(const LiteralProto& proto) { // These conditions should have been checked in // MutableLiteralBase::CreateFromProto. TF_RET_CHECK(proto.has_shape()); - TF_RET_CHECK(LayoutUtil::HasLayout(proto.shape())); - TF_RET_CHECK(ShapeUtil::Equal(proto.shape(), subshape())); + Shape shape(proto.shape()); + TF_RET_CHECK(LayoutUtil::HasLayout(shape)); + TF_RET_CHECK(ShapeUtil::Equal(shape, subshape())); if (LayoutUtil::IsSparseArray(subshape())) { // Compute the number of elements (indices) in the sparse shape and reserve diff --git a/tensorflow/compiler/xla/literal.h b/tensorflow/compiler/xla/literal.h index e791048b4d..fa9a71af4c 100644 --- a/tensorflow/compiler/xla/literal.h +++ b/tensorflow/compiler/xla/literal.h @@ -301,7 +301,7 @@ class LiteralBase { // // Note: It's an antipattern to use this method then immediately call // MutableLiteralBase::Populate on the result (since that results in zero - // initialization, then reinitialization. Conside if a call to + // initialization, then reinitialization. Consider if a call to // absl::make_unique(shape), followed by the call to // MutableLiteralBase::Populate can be used instead. static Literal CreateFromShape(const Shape& shape); diff --git a/tensorflow/compiler/xla/literal_test.cc b/tensorflow/compiler/xla/literal_test.cc index 8cec37897a..49363ad802 100644 --- a/tensorflow/compiler/xla/literal_test.cc +++ b/tensorflow/compiler/xla/literal_test.cc @@ -150,12 +150,58 @@ TEST_F(LiteralUtilTest, R3ToString) { const auto literal = LiteralUtil::CreateR3({{{1}, {2}}, {{3}, {4}}, {{5}, {6}}}); const string expected = R"(s32[3,2,1] { -{ { 1 }, - { 2 } }, -{ { 3 }, - { 4 } }, -{ { 5 }, - { 6 } } +{ + {1}, + {2} +}, +{ + {3}, + {4} +}, +{ + {5}, + {6} +} +})"; + EXPECT_EQ(expected, literal.ToString()); +} + +TEST_F(LiteralUtilTest, R6ToString) { + const auto literal = + LiteralUtil::CreateFromDimensions(S32, {2, 2, 1, 1, 1, 2}); + const string expected = R"(s32[2,2,1,1,1,2] { +{ /*i0=0*/ +{ /*i1=0*/ +{ /*i2=0*/ +{ /*i3=0*/ + { 0, 0 } +} +} +}, +{ /*i1=1*/ +{ /*i2=0*/ +{ /*i3=0*/ + { 0, 0 } +} +} +} +}, +{ /*i0=1*/ +{ /*i1=0*/ +{ /*i2=0*/ +{ /*i3=0*/ + { 0, 0 } +} +} +}, +{ /*i1=1*/ +{ /*i2=0*/ +{ /*i3=0*/ + { 0, 0 } +} +} +} +} })"; EXPECT_EQ(expected, literal.ToString()); } @@ -190,12 +236,16 @@ TEST_F(LiteralUtilTest, CreateR3FromArray3d) { EXPECT_THAT(literal.shape().dimensions(), ElementsAre(2, 3, 2)); string result = literal.ToString(); const string expected = R"(f32[2,3,2] { -{ { 1, 2 }, +{ + { 1, 2 }, { 3, 4 }, - { 5, 6 } }, -{ { 7, 8 }, + { 5, 6 } +}, +{ + { 7, 8 }, { 9, 10 }, - { 11, 12 } } + { 11, 12 } +} })"; EXPECT_EQ(expected, result); } @@ -247,18 +297,18 @@ TEST_F(LiteralUtilTest, LiteralR4F32ProjectedStringifies) { EXPECT_THAT(literal.shape().dimensions(), ElementsAre(1, 2, 3, 2)); string result = literal.ToString(); const string expected = R"(f32[1,2,3,2] { - { /*i0=0*/ - { /*i1=0*/ - {1, 2}, - {1001, 1002}, - {2001, 2002} - }, - { /*i1=1*/ - {1, 2}, - {1001, 1002}, - {2001, 2002} - } - } +{ /*i0=0*/ +{ /*i1=0*/ + { 1, 2 }, + { 1001, 1002 }, + { 2001, 2002 } +}, +{ /*i1=1*/ + { 1, 2 }, + { 1001, 1002 }, + { 2001, 2002 } +} +} })"; EXPECT_EQ(expected, result); } @@ -268,30 +318,30 @@ TEST_F(LiteralUtilTest, LiteralR4F32Stringifies) { ElementsAre(2, 2, 3, 3)); string result = literal_r4_2x2x3x3_dim0major_.ToString(); const string expected = R"(f32[2,2,3,3] { - { /*i0=0*/ - { /*i1=0*/ - {1, 2, 3}, - {4, 5, 6}, - {7, 8, 9} - }, - { /*i1=1*/ - {11, 12, 13}, - {14, 15, 16}, - {17, 18, 19} - } - }, - { /*i0=1*/ - { /*i1=0*/ - {101, 102, 103}, - {104, 105, 106}, - {107, 108, 109} - }, - { /*i1=1*/ - {201, 202, 203}, - {204, 205, 206}, - {207, 208, 209} - } - } +{ /*i0=0*/ +{ /*i1=0*/ + { 1, 2, 3 }, + { 4, 5, 6 }, + { 7, 8, 9 } +}, +{ /*i1=1*/ + { 11, 12, 13 }, + { 14, 15, 16 }, + { 17, 18, 19 } +} +}, +{ /*i0=1*/ +{ /*i1=0*/ + { 101, 102, 103 }, + { 104, 105, 106 }, + { 107, 108, 109 } +}, +{ /*i1=1*/ + { 201, 202, 203 }, + { 204, 205, 206 }, + { 207, 208, 209 } +} +} })"; EXPECT_EQ(expected, result); } @@ -1327,13 +1377,26 @@ TEST_F(LiteralUtilTest, BitcastConvertBetweenInvalidTypes) { absl::StrContains(status.error_message(), "bit widths are different")); } +// Sets the layout of the given ShapeProto to the default. +void SetDefaultLayoutOnProto(ShapeProto* shape_proto) { + CHECK(ShapeUtil::IsArrayPrimitiveType(shape_proto->element_type())); + shape_proto->mutable_layout()->set_format(DENSE); + auto* minor_to_major = + shape_proto->mutable_layout()->mutable_minor_to_major(); + minor_to_major->Resize(shape_proto->dimensions_size(), 0); + const int64 size = minor_to_major->size(); + for (int64 i = 0; i < size; ++i) { + minor_to_major->Set(i, size - 1 - i); + } +} + TEST_F(LiteralUtilTest, CopyFromProto_Bool) { LiteralProto p; p.mutable_shape()->set_element_type(PRED); for (int len = 0; len < 25; ++len) { p.mutable_shape()->clear_dimensions(); p.mutable_shape()->add_dimensions(len); - LayoutUtil::SetToDefaultLayout(p.mutable_shape()); + SetDefaultLayoutOnProto(p.mutable_shape()); p.clear_preds(); for (int i = 0; i < len; ++i) { p.add_preds((i % 2) == (len % 2)); @@ -1359,7 +1422,7 @@ TEST_F(LiteralUtilTest, ToProto_f16) { EXPECT_EQ(4, m.data().size()); LiteralProto p = m.ToProto(); - EXPECT_EQ(4, ShapeUtil::ElementsIn(p.shape())); + EXPECT_EQ(4, ShapeUtil::ElementsIn(Shape(p.shape()))); EXPECT_EQ(8, p.f16s().size()); const char* d = p.f16s().data(); EXPECT_EQ(d[0], 0); @@ -1382,7 +1445,7 @@ TEST_F(LiteralUtilTest, CopyFromProto_f16) { p.mutable_shape()->set_element_type(F16); p.mutable_shape()->clear_dimensions(); p.mutable_shape()->add_dimensions(4); - LayoutUtil::SetToDefaultLayout(p.mutable_shape()); + SetDefaultLayoutOnProto(p.mutable_shape()); p.clear_f16s(); p.set_f16s(half_vals, 8); TF_ASSERT_OK_AND_ASSIGN(Literal literal, Literal::CreateFromProto(p)); @@ -1404,7 +1467,7 @@ TEST_F(LiteralUtilTest, CopyFromProto_u16) { p.mutable_shape()->set_element_type(U16); p.mutable_shape()->clear_dimensions(); p.mutable_shape()->add_dimensions(4); - LayoutUtil::SetToDefaultLayout(p.mutable_shape()); + SetDefaultLayoutOnProto(p.mutable_shape()); p.clear_u16s(); p.set_u16s(uint16_vals, 8); TF_ASSERT_OK_AND_ASSIGN(Literal literal, Literal::CreateFromProto(p)); @@ -1537,9 +1600,9 @@ TEST_F(LiteralUtilTest, DecomposeTuple) { Literal nested_tuple = LiteralUtil::MakeTuple( {&tuple_elements[0], &tuple_elements[1], &nil_literal}); - EXPECT_FALSE(ShapeUtil::IsNil(nested_tuple.shape())); + EXPECT_FALSE(ShapeUtil::IsEmptyTuple(nested_tuple.shape())); std::vector elements = nested_tuple.DecomposeTuple(); - EXPECT_TRUE(ShapeUtil::IsNil(nested_tuple.shape())); + EXPECT_TRUE(ShapeUtil::IsEmptyTuple(nested_tuple.shape())); ASSERT_EQ(elements.size(), 3); @@ -1590,7 +1653,7 @@ TEST_F(LiteralUtilTest, MoveIntoTuple) { EXPECT_EQ(literal.Get({1}, /*shape_index=*/{2, 1}), 44.0); for (const Literal& element : elements) { - EXPECT_TRUE(ShapeUtil::IsNil(element.shape())); + EXPECT_TRUE(ShapeUtil::IsEmptyTuple(element.shape())); } } @@ -1706,7 +1769,7 @@ TEST_F(LiteralUtilTest, ProtoRoundTrip) { TEST_F(LiteralUtilTest, InvalidProtoNoValues) { // Proto contains a shape, but no values. LiteralProto proto; - *proto.mutable_shape() = ShapeUtil::MakeShape(F32, {3}); + *proto.mutable_shape() = ShapeUtil::MakeShape(F32, {3}).ToProto(); Status status = Literal::CreateFromProto(proto).status(); ASSERT_FALSE(status.ok()); EXPECT_THAT(status.error_message(), @@ -1727,7 +1790,7 @@ TEST_F(LiteralUtilTest, InvalidProtoNoShape) { TEST_F(LiteralUtilTest, InvalidProtoWrongContainer) { // Proto contains values in wrong container. LiteralProto proto; - *proto.mutable_shape() = ShapeUtil::MakeShape(F32, {3}); + *proto.mutable_shape() = ShapeUtil::MakeShape(F32, {3}).ToProto(); proto.add_preds(false); proto.add_preds(true); proto.add_preds(false); @@ -1740,7 +1803,7 @@ TEST_F(LiteralUtilTest, InvalidProtoWrongContainer) { TEST_F(LiteralUtilTest, InvalidProtoTooFewValues) { // Proto contains too few values. LiteralProto proto; - *proto.mutable_shape() = ShapeUtil::MakeShape(F32, {42, 2}); + *proto.mutable_shape() = ShapeUtil::MakeShape(F32, {42, 2}).ToProto(); proto.add_f32s(1.0); proto.add_f32s(2.0); proto.add_f32s(3.0); @@ -1753,7 +1816,7 @@ TEST_F(LiteralUtilTest, InvalidProtoTooFewValues) { TEST_F(LiteralUtilTest, InvalidProtoTooManyValues) { // Proto contains too many values. LiteralProto proto; - *proto.mutable_shape() = ShapeUtil::MakeShape(S32, {2}); + *proto.mutable_shape() = ShapeUtil::MakeShape(S32, {2}).ToProto(); proto.add_s32s(42); proto.add_s32s(-10); proto.add_s32s(100); @@ -1766,8 +1829,8 @@ TEST_F(LiteralUtilTest, InvalidProtoTooManyValues) { TEST_F(LiteralUtilTest, InvalidProtoMissingLayout) { // Proto shape missing layout. LiteralProto proto; - *proto.mutable_shape() = ShapeUtil::MakeShape(PRED, {2, 2}); - LayoutUtil::ClearLayout(proto.mutable_shape()); + *proto.mutable_shape() = ShapeUtil::MakeShape(PRED, {2, 2}).ToProto(); + proto.mutable_shape()->clear_layout(); proto.add_preds(true); proto.add_preds(false); proto.add_preds(true); @@ -1780,11 +1843,13 @@ TEST_F(LiteralUtilTest, InvalidProtoMissingLayout) { TEST_F(LiteralUtilTest, InvalidProtoTooFewTupleElements) { // Proto has the too few tuple elements. LiteralProto proto; - *proto.mutable_shape() = ShapeUtil::MakeTupleShape( - {ShapeUtil::MakeShape(PRED, {2}), ShapeUtil::MakeShape(F32, {})}); + *proto.mutable_shape() = + ShapeUtil::MakeTupleShape( + {ShapeUtil::MakeShape(PRED, {2}), ShapeUtil::MakeShape(F32, {})}) + .ToProto(); LiteralProto* element0 = proto.add_tuple_literals(); *element0->mutable_shape() = - ShapeUtil::GetTupleElementShape(proto.shape(), 0); + ShapeUtil::GetTupleElementShape(Shape(proto.shape()), 0).ToProto(); element0->add_preds(false); element0->add_preds(true); @@ -1796,19 +1861,21 @@ TEST_F(LiteralUtilTest, InvalidProtoTooFewTupleElements) { TEST_F(LiteralUtilTest, InvalidProtoTooManyTupleElements) { // Proto has the too many tuple elements. LiteralProto proto; - *proto.mutable_shape() = ShapeUtil::MakeTupleShape( - {ShapeUtil::MakeShape(PRED, {2}), ShapeUtil::MakeShape(F32, {})}); + *proto.mutable_shape() = + ShapeUtil::MakeTupleShape( + {ShapeUtil::MakeShape(PRED, {2}), ShapeUtil::MakeShape(F32, {})}) + .ToProto(); LiteralProto* element0 = proto.add_tuple_literals(); *element0->mutable_shape() = - ShapeUtil::GetTupleElementShape(proto.shape(), 0); + ShapeUtil::GetTupleElementShape(Shape(proto.shape()), 0).ToProto(); element0->add_preds(false); element0->add_preds(true); LiteralProto* element1 = proto.add_tuple_literals(); *element1->mutable_shape() = - ShapeUtil::GetTupleElementShape(proto.shape(), 1); + ShapeUtil::GetTupleElementShape(Shape(proto.shape()), 1).ToProto(); element1->add_f32s(42.0); LiteralProto* element2 = proto.add_tuple_literals(); - *element2->mutable_shape() = ShapeUtil::MakeShape(F32, {}); + *element2->mutable_shape() = ShapeUtil::MakeShape(F32, {}).ToProto(); element2->add_f32s(123.0); Status status = Literal::CreateFromProto(proto).status(); diff --git a/tensorflow/compiler/xla/parse_flags_from_env.cc b/tensorflow/compiler/xla/parse_flags_from_env.cc index 40481331b6..5b568888d1 100644 --- a/tensorflow/compiler/xla/parse_flags_from_env.cc +++ b/tensorflow/compiler/xla/parse_flags_from_env.cc @@ -13,15 +13,20 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -// This module exports ParseFlagsFromEnv(), which allows other modules to parse -// flags from an environtment variable, or a file named by the environment -// variable. +// This module exports ParseFlagsFromEnvAndDieIfUnknown(), which allows other +// modules to parse flags from an environtment variable, or a file named by the +// environment variable. #include #include #include +#include +#include #include +#include "absl/strings/str_format.h" +#include "absl/strings/str_join.h" +#include "absl/types/span.h" #include "tensorflow/compiler/xla/parse_flags_from_env.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/core/platform/logging.h" @@ -32,7 +37,6 @@ limitations under the License. namespace xla { -static const char kEnvVar[] = "TF_XLA_FLAGS"; // environment variable queried static const char kWS[] = " \t\r\n"; // whitespace // The following struct represents an argv[]-style array, parsed @@ -42,12 +46,20 @@ static const char kWS[] = " \t\r\n"; // whitespace // constructor/destructor collisions with other "private" types // in the same named namespace. namespace { + +// Functor which deletes objects by calling `free`. Necessary to free strdup'ed +// strings created by AppendToEnvArgv. +struct FreeDeleter { + void operator()(char* ptr) { free(ptr); } +}; + struct EnvArgv { EnvArgv() : initialized(false), argc(0) {} bool initialized; // whether the other fields have been set. int argc; // elements used in argv[] std::vector argv; // flag arguments parsed from environment string. - std::vector argv_save; // saved values from argv[] to avoid leaks + // saved values from argv[] to avoid leaks + std::vector> argv_save; }; } // anonymous namespace @@ -63,7 +75,7 @@ static void AppendToEnvArgv(const char* s0, size_t s0len, const char* s1, string s = string(s0, s0len) + string(s1, s1len); char* str = strdup(s.c_str()); a->argv.push_back(str); - a->argv_save.push_back(str); + a->argv_save.emplace_back(str); a->argc++; } } @@ -127,14 +139,14 @@ static void ParseArgvFromString(const string& flag_str, EnvArgv* a) { } } -// Call ParseArgvFromString(..., a) on a string derived from the setting of an -// environment variable kEnvVar, or a file it points to. -static void SetArgvFromEnv(EnvArgv* a) { +// Call ParseArgvFromString(..., a) on a string derived from the setting of the +// environment variable `envvar`, or a file it points to. +static void SetArgvFromEnv(absl::string_view envvar, EnvArgv* a) { if (!a->initialized) { static const char kDummyArgv[] = ""; AppendToEnvArgv(kDummyArgv, strlen(kDummyArgv), nullptr, 0, a); // dummy argv[0] - const char* env = getenv(kEnvVar); + const char* env = getenv(string(envvar).c_str()); if (env == nullptr || env[0] == '\0') { // nothing } else if (env[strspn(env, kWS)] == '-') { // flags in env var value @@ -157,48 +169,66 @@ static void SetArgvFromEnv(EnvArgv* a) { } } -// The simulated argv[] parsed from the environment. -static EnvArgv* env_argv; +// The simulated argv[] parsed from the environment, one for each different +// environment variable we've seen. +static std::unordered_map& EnvArgvs() { + static auto* env_argvs = new std::unordered_map(); + return *env_argvs; +} -// Used to protect accesses to env_argv. +// Used to protect accesses to env_argvs. static tensorflow::mutex env_argv_mu(tensorflow::LINKER_INITIALIZED); -// Call Flags::Parse(argc, argv, flag_list) against any as yet unrecognized -// flags passed in from the environment. -bool ParseFlagsFromEnv(const std::vector& flag_list) { - env_argv_mu.lock(); - if (env_argv == nullptr) { - env_argv = new EnvArgv; - } - SetArgvFromEnv(env_argv); // a no-op if already initialized +bool ParseFlagsFromEnvAndDieIfUnknown( + absl::string_view envvar, const std::vector& flag_list) { + tensorflow::mutex_lock lock(env_argv_mu); + auto* env_argv = &EnvArgvs()[string(envvar)]; + SetArgvFromEnv(envvar, env_argv); // a no-op if already initialized bool result = tensorflow::Flags::Parse(&env_argv->argc, &env_argv->argv[0], flag_list); - env_argv_mu.unlock(); + + // There's always at least one unparsed argc, namely the fake argv[0]. + if (result && env_argv->argc != 1) { + // Skip the first argv, which is the fake argv[0]. + auto unknown_flags = absl::MakeSpan(env_argv->argv); + unknown_flags.remove_prefix(1); + + // Some flags are set on XLA_FLAGS, others on TF_XLA_FLAGS. If we find an + // unrecognized flag, suggest the alternative. + string alternate_envvar; + if (envvar == "TF_XLA_FLAGS") { + alternate_envvar = "XLA_FLAGS"; + } else if (envvar == "XLA_FLAGS") { + alternate_envvar = "TF_XLA_FLAGS"; + } + string did_you_mean; + if (!alternate_envvar.empty()) { + did_you_mean = absl::StrFormat( + "\nPerhaps you meant to specify these on the %s envvar?", + alternate_envvar); + } + + LOG(FATAL) << "Unknown flag" << (unknown_flags.size() > 1 ? "s" : "") + << " in " << envvar << ": " << absl::StrJoin(unknown_flags, " ") + << did_you_mean; + return false; + } return result; } // Testing only. -// Reset the env_argv struct so that subsequent calls to ParseFlagsFromEnv() -// will parse the environment variable (or the file it points to) anew, and set -// *pargc, and *pargv to point to the internal locations of the argc and argv -// constructed from the environment. -void ResetFlagsFromEnvForTesting(int** pargc, std::vector** pargv) { - env_argv_mu.lock(); - if (env_argv == nullptr) { - env_argv = new EnvArgv; - } - if (!env_argv->argv_save.empty()) { - for (int i = 0; env_argv->argv_save[i] != nullptr; i++) { - free(env_argv->argv_save[i]); - } - } - env_argv->initialized = false; - env_argv->argc = 0; - env_argv->argv.clear(); - env_argv->argv_save.clear(); - env_argv_mu.unlock(); - *pargc = &env_argv->argc; - *pargv = &env_argv->argv; +// +// Resets the env_argv struct so that subsequent calls to +// ParseFlagsFromEnvAndDieIfUnknown() will parse the environment variable (or +// the file it points to) anew, and set *pargc, and *pargv to point to the +// internal locations of the argc and argv constructed from the environment. +void ResetFlagsFromEnvForTesting(absl::string_view envvar, int** pargc, + std::vector** pargv) { + tensorflow::mutex_lock lock(env_argv_mu); + EnvArgvs().erase(string(envvar)); + auto& env_argv = EnvArgvs()[string(envvar)]; + *pargc = &env_argv.argc; + *pargv = &env_argv.argv; } } // namespace xla diff --git a/tensorflow/compiler/xla/parse_flags_from_env.h b/tensorflow/compiler/xla/parse_flags_from_env.h index fe86ee687f..76940a4299 100644 --- a/tensorflow/compiler/xla/parse_flags_from_env.h +++ b/tensorflow/compiler/xla/parse_flags_from_env.h @@ -16,48 +16,58 @@ limitations under the License. #ifndef TENSORFLOW_COMPILER_XLA_PARSE_FLAGS_FROM_ENV_H_ #define TENSORFLOW_COMPILER_XLA_PARSE_FLAGS_FROM_ENV_H_ -// This module exports ParseFlagsFromEnv(), which allows other modules to parse -// flags from the environtment variable TF_XLA_FLAGS, or (if the first +// This module exports ParseFlagsFromEnvAndDieIfUnknown(), which allows other +// modules to parse flags from an environtment variable, or (if the first // non-whitespace in the variable value is not '-'), a file named by that -// environment variable. The accepted syntax is that flags arguments are of -// the form --flag=value or (for boolean flags) --flag, and are whitespace -// separated. The may be one of: -// - -// in which case the effective value is the string itself -// - in which case the effective value is the -// string with the single-quotes removed -// - in which case the effective value if the -// string with the double-quotes removed, and escaped sequences of -// replaced by . +// environment variable. +// +// The accepted syntax is that flags arguments are of the form --flag=value or +// (for boolean flags) --flag, and are whitespace separated. The may be +// one of: +// +// - +// in which case the effective value is the string itself +// - in which case the effective value is the +// string with the single-quotes removed +// - in which case the effective value if the +// string with the double-quotes removed, and escaped sequences of +// replaced by . // // Flags values inconsistent with the type of the flag will be rejected by the // flag parser. // // Examples: -// TF_XLA_FLAGS="--foo=bar --wombat='value with a space'" // -// TF_XLA_FLAGS=/tmp/flagfile +// - TF_XLA_FLAGS="--foo=bar --wombat='value with a space'" +// - TF_XLA_FLAGS=/tmp/flagfile +// // where /tmp/flagfile might contain -// --some_flag="This is a string containing a \" and a '." -// --another_flag=wombats +// +// --some_flag="This is a string containing a \" and a '." +// --another_flag=wombats #include +#include "absl/strings/string_view.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/core/platform/types.h" #include "tensorflow/core/util/command_line_flags.h" namespace xla { -// Call tensorflow::Flags::Parse(argc, argv, flag_list) against any as yet -// unrecognized flags passed in from the environment, and return its -// return value. -bool ParseFlagsFromEnv(const std::vector& flag_list); +// Calls tensorflow::Flags::Parse(argc, argv, flag_list) against any as yet +// unrecognized flags passed in the environment variable `envvar`, and returns +// its return value. +// +// Raises a fatal error if any flags in `envvar` were not recognized. +bool ParseFlagsFromEnvAndDieIfUnknown( + absl::string_view envvar, const std::vector& flag_list); // Used only for testing. Not to be used by clients. -void ResetFlagsFromEnvForTesting(int** pargc, std::vector** pargv); +void ResetFlagsFromEnvForTesting(absl::string_view envvar, int** pargc, + std::vector** pargv); } // namespace xla diff --git a/tensorflow/compiler/xla/parse_flags_from_env_test.cc b/tensorflow/compiler/xla/parse_flags_from_env_test.cc index edd6538402..3465552ebb 100644 --- a/tensorflow/compiler/xla/parse_flags_from_env_test.cc +++ b/tensorflow/compiler/xla/parse_flags_from_env_test.cc @@ -37,20 +37,7 @@ static void TestParseFlagsFromEnv(const char* msg) { // Initialize module under test. int* pargc; std::vector* pargv; - ResetFlagsFromEnvForTesting(&pargc, &pargv); - - // Ensure that environment variable can be parsed when - // no flags are expected. - std::vector empty_flag_list; - bool parsed_ok = ParseFlagsFromEnv(empty_flag_list); - CHECK(parsed_ok) << msg; - const std::vector& argv_first = *pargv; - CHECK_NE(argv_first[0], nullptr) << msg; - int i = 0; - while (argv_first[i] != nullptr) { - i++; - } - CHECK_EQ(i, *pargc) << msg; + ResetFlagsFromEnvForTesting("TF_XLA_FLAGS", &pargc, &pargv); // Check that actual flags can be parsed. bool simple = false; @@ -65,7 +52,7 @@ static void TestParseFlagsFromEnv(const char* msg) { tensorflow::Flag("single_quoted", &single_quoted, ""), tensorflow::Flag("double_quoted", &double_quoted, ""), }; - parsed_ok = ParseFlagsFromEnv(flag_list); + bool parsed_ok = ParseFlagsFromEnvAndDieIfUnknown("TF_XLA_FLAGS", flag_list); CHECK_EQ(*pargc, 1) << msg; const std::vector& argv_second = *pargv; CHECK_NE(argv_second[0], nullptr) << msg; @@ -171,7 +158,8 @@ int main(int argc, char* argv[]) { tensorflow::Flag("int_flag", &int_flag, "An integer flag to test with"), }; xla::string usage = tensorflow::Flags::Usage(argv[0], flag_list); - bool parse_ok = xla::ParseFlagsFromEnv(flag_list); + bool parse_ok = + xla::ParseFlagsFromEnvAndDieIfUnknown("TF_XLA_FLAGS", flag_list); if (!parse_ok) { LOG(QFATAL) << "can't parse from environment\n" << usage; } diff --git a/tensorflow/compiler/xla/protobuf_util.cc b/tensorflow/compiler/xla/protobuf_util.cc index b507a2ef79..ac342bf40f 100644 --- a/tensorflow/compiler/xla/protobuf_util.cc +++ b/tensorflow/compiler/xla/protobuf_util.cc @@ -40,16 +40,6 @@ bool ProtobufEquals(const tensorflow::protobuf::Message& m1, namespace { -string SanitizeFilename(const string& file_name) { - string safe_file_name = file_name; - for (char& c : safe_file_name) { - if (c == '/' || c == '\\') { - c = '_'; - } - } - return safe_file_name; -} - std::pair>*> GetDirectoryExpanders() { static auto* mutex = new tensorflow::mutex; diff --git a/tensorflow/compiler/xla/python/local_computation_builder.cc b/tensorflow/compiler/xla/python/local_computation_builder.cc index 4d2a37cfac..6e2ee86632 100644 --- a/tensorflow/compiler/xla/python/local_computation_builder.cc +++ b/tensorflow/compiler/xla/python/local_computation_builder.cc @@ -148,14 +148,19 @@ static StatusOr ToBuffer(LocalClient* client, /* static */ StatusOr LocalShapedBuffer::FromLiteral( - const Literal& argument, const absl::optional& shape_with_layout) { + const Literal& argument, const absl::optional& shape_with_layout, + int replica_number) { LocalClient* client = GetOrCreateLocalClient(); + TF_ASSIGN_OR_RETURN(int device_ordinal, + client->ReplicaNumberToDeviceOrdinal(replica_number)); + VLOG(1) << "Creating shaped buffer from literal on replica/ordinal: " + << replica_number << "/" << device_ordinal; StatusOr buf = [&] { if (shape_with_layout) { Literal relaid = argument.Relayout(shape_with_layout.value()); - return ToBuffer(client, /*device_ordinal=*/0, relaid); + return ToBuffer(client, device_ordinal, relaid); } - return ToBuffer(client, /*device_ordinal=*/0, argument); + return ToBuffer(client, device_ordinal, argument); }(); TF_RETURN_IF_ERROR(buf.status()); return new LocalShapedBuffer(std::move(buf).ValueOrDie()); @@ -312,67 +317,127 @@ CompiledLocalComputation::CompiledLocalComputation( StatusOr CompiledLocalComputation::Execute( absl::Span argument_handles) { LocalClient* client = GetOrCreateLocalClient(); + StatusOr device_ordinal_status = client->ReplicaNumberToDeviceOrdinal(0); + StatusOr result_buffer_status; + if (!device_ordinal_status.ok()) { + result_buffer_status = device_ordinal_status.status(); + } else { + const int device_ordinal = device_ordinal_status.ValueOrDie(); + VLOG(3) << "Replica 0 mapped to device ordinal for execution: " + << device_ordinal; + + std::vector argument_buffers; + argument_buffers.reserve(argument_handles.size()); + for (auto& handle : argument_handles) { + argument_buffers.push_back(handle->shaped_buffer()); + } + + DeviceAssignment device_assignment = + client->backend() + .computation_placer() + ->AssignDevices(1, /*computation_count=*/1) + .ConsumeValueOrDie(); + + ExecutableRunOptions options; + options.set_device_ordinal(device_ordinal); + options.set_allocator(client->backend().memory_allocator()); + options.set_intra_op_thread_pool( + client->backend().eigen_intra_op_thread_pool_device()); + options.set_device_assignment(&device_assignment); - VLOG(1) << "Execution requested with " << GetReplicaCount() << " replicas."; + result_buffer_status = executable_->Run(argument_buffers, options); + } + + if (!result_buffer_status.ok()) { + return InternalError( + "Failed running replica 0 (other replicas may have failed as well): " + "%s.", + result_buffer_status.status().ToString()); + } + return new LocalShapedBuffer(std::move(result_buffer_status).ValueOrDie()); +} + +StatusOr CompiledLocalComputation::ExecutePerReplica( + absl::Span> argument_handles) { + LocalClient* client = GetOrCreateLocalClient(); + const int num_replicas = GetReplicaCount(); + + if (argument_handles.size() != num_replicas) { + return InvalidArgument( + "Attempted to execute with %d replicas when replica count is %d", + argument_handles.size(), num_replicas); + } + + VLOG(1) << "Executing with " << num_replicas << " replicas."; // Each replica populates a StatusOr result, but only the output value of // replica zero is returned. - std::vector> results(GetReplicaCount()); - { + std::vector> results(num_replicas); + auto execute = [this, client, num_replicas, &argument_handles, + &results](int replica) { + StatusOr device_ordinal_status = + client->ReplicaNumberToDeviceOrdinal(replica); + if (!device_ordinal_status.ok()) { + results[replica] = device_ordinal_status.status(); + return; + } + const int device_ordinal = device_ordinal_status.ValueOrDie(); + VLOG(3) << "Replica " << replica + << " mapped to device ordinal for execution: " << device_ordinal; + + std::vector argument_buffers; + argument_buffers.reserve(argument_handles[replica].size()); + for (auto& handle : argument_handles[replica]) { + argument_buffers.push_back(handle->shaped_buffer()); + } + + DeviceAssignment device_assignment = + client->backend() + .computation_placer() + ->AssignDevices(num_replicas, /*computation_count=*/1) + .ConsumeValueOrDie(); + + ExecutableRunOptions options; + options.set_device_ordinal(device_ordinal); + options.set_allocator(client->backend().memory_allocator()); + options.set_intra_op_thread_pool( + client->backend().eigen_intra_op_thread_pool_device()); + options.set_device_assignment(&device_assignment); + StatusOr result_buffer_status = + executable_->Run(argument_buffers, options); + + results[replica] = std::move(result_buffer_status); + }; + + if (num_replicas == 1) { + // Fast-path if there is only one replica — run the computation on the + // current thread. + execute(0); + } else { + // TODO(phawkins): don't recreate the threadpool for each execution. tensorflow::thread::ThreadPool pool(tensorflow::Env::Default(), "xlarun", - GetReplicaCount()); - - for (int replica = 0; replica < GetReplicaCount(); ++replica) { - pool.Schedule( - [this, client, replica, &argument_handles, &results] { - StatusOr device_ordinal_status = - client->ReplicaNumberToDeviceOrdinal(replica); - if (!device_ordinal_status.ok()) { - results[replica] = device_ordinal_status.status(); - return; - } - const int device_ordinal = device_ordinal_status.ValueOrDie(); - VLOG(3) << "Replica " << replica - << " mapped to device ordinal for execution: " - << device_ordinal; - - std::vector argument_buffers; - argument_buffers.reserve(argument_handles.size()); - for (auto& handle : argument_handles) { - argument_buffers.push_back(handle->shaped_buffer()); - } - - DeviceAssignment device_assignment = - client->backend() - .computation_placer() - ->AssignDevices(GetReplicaCount(), /*computation_count=*/1) - .ConsumeValueOrDie(); - - ExecutableRunOptions options; - options.set_device_ordinal(device_ordinal); - options.set_allocator(client->backend().memory_allocator()); - options.set_intra_op_thread_pool( - client->backend().eigen_intra_op_thread_pool_device()); - options.set_device_assignment(&device_assignment); - StatusOr result_buffer_status = - executable_->Run(argument_buffers, options); - - results[replica] = std::move(result_buffer_status); - }); + num_replicas - 1); + + for (int replica = 0; replica < num_replicas - 1; ++replica) { + pool.Schedule([&execute, replica] { execute(replica); }); } + execute(num_replicas - 1); } - for (int replica = 0; replica < GetReplicaCount(); ++replica) { - const auto& statusor = results[replica]; + std::vector wrapped_results(num_replicas); + for (int replica = 0; replica < num_replicas; ++replica) { + auto& statusor = results[replica]; if (!statusor.ok()) { return InternalError( "Failed running replica %d (other replicas may have failed as well): " "%s.", replica, statusor.status().ToString()); } + wrapped_results[replica] = + new LocalShapedBuffer(std::move(statusor).ValueOrDie()); } - return new LocalShapedBuffer(std::move(results[0]).ValueOrDie()); + return new LocalShapedBufferTuple(std::move(wrapped_results)); } static StatusOr GetReturnValueShape(const XlaComputation& computation) { @@ -487,12 +552,13 @@ StatusOr LocalComputation::CompileForXrt( xrt::XLAComputation c; auto config = c.mutable_config(); - auto shapes = config->mutable_program_shape(); + ProgramShape shapes; for (auto& shape : argument_shapes) { - *shapes->add_parameters() = shape; + *shapes.add_parameters() = shape; } - TF_ASSIGN_OR_RETURN(*shapes->mutable_result(), GetReturnValueShape()); - LayoutUtil::SetToDefaultLayout(shapes); + TF_ASSIGN_OR_RETURN(*shapes.mutable_result(), GetReturnValueShape()); + LayoutUtil::SetToDefaultLayout(&shapes); + *config->mutable_program_shape() = shapes.ToProto(); auto snapshot = computation().Snapshot().ValueOrDie(); *c.mutable_hlo_snapshot() = *snapshot; @@ -584,9 +650,9 @@ LocalOp LocalComputationBuilder::Broadcast( } LocalOp LocalComputationBuilder::BroadcastInDim( - const LocalOp& operand, const Shape& shape, + const LocalOp& operand, absl::Span out_dim_sizes, absl::Span broadcast_dimensions) { - return xla::BroadcastInDim(operand.op(), shape, broadcast_dimensions); + return xla::BroadcastInDim(operand.op(), out_dim_sizes, broadcast_dimensions); } LocalOp LocalComputationBuilder::Pad(const LocalOp& operand, diff --git a/tensorflow/compiler/xla/python/local_computation_builder.h b/tensorflow/compiler/xla/python/local_computation_builder.h index 9e617c48bd..149e44570d 100644 --- a/tensorflow/compiler/xla/python/local_computation_builder.h +++ b/tensorflow/compiler/xla/python/local_computation_builder.h @@ -71,7 +71,8 @@ StatusOr TransferFromOutfeedLocalReplica(const Shape& shape, class LocalShapedBuffer { public: static StatusOr FromLiteral( - const Literal& argument, const absl::optional& shape_with_layout); + const Literal& argument, const absl::optional& shape_with_layout, + int replica_number); LocalShapedBuffer(ScopedShapedBuffer shaped_buffer); StatusOr ToLiteral() const; @@ -175,6 +176,12 @@ class CompiledLocalComputation { StatusOr Execute( absl::Span argument_handles); + // Execute on many replicas. Takes a sequence of argument lists (one argument + // list per replica) and returns a tuple of results (one result per replica). + // The number of argument lists must be equal to the replica count. + StatusOr ExecutePerReplica( + absl::Span > argument_handles); + private: std::unique_ptr executable_; }; @@ -282,7 +289,8 @@ class LocalComputationBuilder { LocalOp Broadcast(const LocalOp& operand, absl::Span broadcast_sizes); - LocalOp BroadcastInDim(const LocalOp& operand, const Shape& shape, + LocalOp BroadcastInDim(const LocalOp& operand, + absl::Span out_dim_sizes, absl::Span broadcast_dimensions); LocalOp Pad(const LocalOp& operand, const LocalOp& padding_value, diff --git a/tensorflow/compiler/xla/python/local_computation_builder.i b/tensorflow/compiler/xla/python/local_computation_builder.i index feabfdb889..d23d693c1e 100644 --- a/tensorflow/compiler/xla/python/local_computation_builder.i +++ b/tensorflow/compiler/xla/python/local_computation_builder.i @@ -363,6 +363,37 @@ tensorflow::ImportNumpy(); $1 = temps; } +%typemap(in) absl::Span > + (std::vector > temps) { + if (!PySequence_Check($input)) { + PyErr_SetString(PyExc_TypeError, "Argument is not a sequence"); + SWIG_fail; + } + const int size = PySequence_Size($input); + temps.reserve(size); + for (int i = 0; i < size; ++i) { + PyObject* o = PySequence_GetItem($input, i); + std::vector vec; + const int vec_size = PySequence_Size(o); + vec.reserve(vec_size); + for (int j = 0; j < vec_size; ++j) { + PyObject* vec_elt = PySequence_GetItem(o, j); + LocalShapedBuffer* lsbp; + if ((SWIG_ConvertPtr(vec_elt, (void**) &lsbp, $descriptor(xla::swig::LocalShapedBuffer*), + SWIG_POINTER_EXCEPTION)) == -1) { + Py_DECREF(vec_elt); + Py_DECREF(o); + SWIG_fail; + } + vec.push_back(lsbp); + Py_DECREF(vec_elt); + } + temps.push_back(vec); + Py_DECREF(o); + } + $1 = temps; +} + %typemap(in) absl::Span (std::vector temps) { if (!PySequence_Check($input)) { @@ -921,22 +952,22 @@ tensorflow::ImportNumpy(); $1 = NULL; } else { if (!HandleStringAttribute($input, "generate_hlo_graph", [&](string s) { - build_options.set_generate_hlo_graph(std::move(s)); + build_options.mutable_debug_options()->set_xla_generate_hlo_graph(std::move(s)); })) { return nullptr; } if (!HandleStringAttribute($input, "dump_optimized_hlo_proto_to", [&](string s) { - build_options.set_dump_optimized_hlo_proto_to(std::move(s)); + build_options.mutable_debug_options()->set_xla_dump_optimized_hlo_proto_to(std::move(s)); })) { return nullptr; } if (!HandleStringAttribute($input, "dump_unoptimized_hlo_proto_to", [&](string s) { - build_options.set_dump_unoptimized_hlo_proto_to(std::move(s)); + build_options.mutable_debug_options()->set_xla_dump_unoptimized_hlo_proto_to(std::move(s)); })) { return nullptr; } if (!HandleStringAttribute($input, "dump_per_pass_hlo_proto_to", [&](string s) { - build_options.set_dump_per_pass_hlo_proto_to(std::move(s)); + build_options.mutable_debug_options()->set_xla_dump_per_pass_hlo_proto_to(std::move(s)); })) { return nullptr; } @@ -950,7 +981,7 @@ tensorflow::ImportNumpy(); PyErr_SetString(PyExc_TypeError, "ExecutableBuildOptions.hlo_profile must be a bool or None."); SWIG_fail; } - build_options.set_hlo_profile(o == Py_True); + build_options.mutable_debug_options()->set_xla_hlo_profile(o == Py_True); } Py_DECREF(o); @@ -992,11 +1023,13 @@ tensorflow::ImportNumpy(); %unignore xla::swig::XrtAllocation; %unignore xla::swig::XrtAllocation::FromLiteral; %unignore xla::swig::XrtAllocation::ToLiteral; +%unignore xla::swig::XrtAllocation::shape; %unignore xla::swig::XrtAllocationTuple; %unignore xla::swig::XrtAllocationTuple::Release; %unignore xla::swig::XrtAllocationTuple::size; %unignore xla::swig::CompiledLocalComputation; %unignore xla::swig::CompiledLocalComputation::Execute; +%unignore xla::swig::CompiledLocalComputation::ExecutePerReplica; %unignore xla::swig::CompiledXrtComputation; %unignore xla::swig::CompiledXrtComputation::Execute; %unignore xla::swig::LocalComputation; diff --git a/tensorflow/compiler/xla/python/xla_client.py b/tensorflow/compiler/xla/python/xla_client.py index 92b0685dbb..c91a2aaf56 100644 --- a/tensorflow/compiler/xla/python/xla_client.py +++ b/tensorflow/compiler/xla/python/xla_client.py @@ -26,6 +26,9 @@ import os import numpy as np +import six +from six.moves import xrange + from tensorflow.compiler.xla import xla_data_pb2 from tensorflow.compiler.xla.python import pywrap_xla as c_api from tensorflow.compiler.xla.service import hlo_pb2 @@ -75,6 +78,13 @@ def CurrentSourceInfoMetadata(op_type=None, op_name=None, skip_frames=1): source_line=lineno) +def _maybe_encode_string(s): + if six.PY3: + return s.encode('utf-8') + else: + return s + + class PaddingType(enum.Enum): VALID = 1 SAME = 2 @@ -212,23 +222,33 @@ class LocalBuffer(object): means the referent is in device memory. """ - def __init__(self, c_buffer, backend): + def __init__(self, c_buffer, backend, replica): self.c_buffer = c_buffer self._backend = backend + self._replica = replica if backend.backend_type == BackendType.XRT: self._delete = c_api.DeleteXrtAllocation else: self._delete = c_api.DeleteLocalShapedBuffer @staticmethod - def from_pyval(pyval, backend=XLA_LOCAL_BACKEND): + def from_pyval(pyval, replica=0, backend=XLA_LOCAL_BACKEND): """Allocate and copy to XLA the given python value.""" pyval = require_numpy_array_layout(pyval) + num_replicas = get_replica_count() + if not 0 <= replica < num_replicas: + raise ValueError( + 'Attempt to place buffer on replica {} when the replica count is {}' + .format(replica, num_replicas)) if backend.backend_type == BackendType.XRT: - cbuf = c_api.XrtAllocation.FromLiteral(pyval, backend.target) + if replica != 0: + raise NotImplementedError( + 'Multi-replica execution is not yet supported via the XRT backend.') + cbuf = c_api.XrtAllocation.FromLiteral( + pyval, _maybe_encode_string(backend.target)) else: - cbuf = c_api.LocalShapedBuffer.FromLiteral(pyval, None) - return LocalBuffer(cbuf, backend) + cbuf = c_api.LocalShapedBuffer.FromLiteral(pyval, None, replica) + return LocalBuffer(cbuf, backend, replica) def to_py(self): return self.c_buffer.ToLiteral() @@ -236,6 +256,9 @@ class LocalBuffer(object): def shape(self): return _wrap_shape(self.c_buffer.shape()) + def replica(self): + return self._replica + def delete(self): if self.c_buffer is not None: self._delete(self.c_buffer) @@ -245,14 +268,15 @@ class LocalBuffer(object): """Assuming a tuple buffer, unpack it into constituent tuple elements.""" assert self.c_buffer is not None if self._backend.backend_type == BackendType.XRT: - result = c_api.DestructureXrtAllocationTuple(self.c_buffer, - self._backend.target) + result = c_api.DestructureXrtAllocationTuple( + self.c_buffer, _maybe_encode_string(self._backend.target)) else: result = c_api.DestructureLocalShapedBufferTuple(self.c_buffer) self.delete() size = result.size() destructured = tuple( - LocalBuffer(result.Release(i), backend=self._backend) + LocalBuffer( + result.Release(i), replica=self._replica, backend=self._backend) for i in xrange(size)) return destructured @@ -322,6 +346,9 @@ class Shape(object): def __ne__(self, other): return not self == other + def __hash__(self): + return hash((self._dtype, self._dimensions, self._minor_to_major)) + def __repr__(self): return ('xla_client.Shape(_dtype={!r}, _dimensions={!r}, ' '_is_tuple={!r}, _minor_to_major={!r})').format( @@ -541,10 +568,13 @@ class LocalComputation(object): ] result_shape = result_shape.map_leaves(layout_fn) + argument_shapes = list(argument_shapes) + compile_options = compile_options or CompileOptions() compile_options.result_shape = result_shape if self._backend.backend_type == BackendType.XRT: - c = self.computation.CompileForXrt(argument_shapes, self._backend.target) + c = self.computation.CompileForXrt( + argument_shapes, _maybe_encode_string(self._backend.target)) else: c = self.computation.Compile(argument_shapes, compile_options) return LocalComputation(c, is_compiled=True, backend=self._backend) @@ -558,23 +588,87 @@ class LocalComputation(object): compile_options=compile_options, layout_fn=layout_fn) - def Execute(self, arguments=()): - """Execute with LocalBuffer arguments and return value.""" + def GetReturnValueShape(self): + return _wrap_shape(self._c_computation.GetReturnValueShape()) + + def Execute(self, arguments=(), check_for_deleted_args=True): + """Execute on one replica with LocalBuffer arguments and return value.""" + if check_for_deleted_args and any(arg.is_deleted() for arg in arguments): + raise ValueError('Executing with deleted local buffer argument') + raw_args = [arg.c_buffer for arg in arguments] + output_buffer = self._c_computation.Execute(raw_args) + return LocalBuffer(output_buffer, backend=self._backend, replica=0) + + def ExecutePerReplica(self, arguments=None): + """Execute on many replicas with LocalBuffer arguments and return value. + + Args: + arguments: A sequence of sequences of LocalBuffers. The i'th inner + sequence comprises the arguments for execution on the i'th replica. + + Returns: + A list of the computation's outputs on each replica, as a LocalBuffer. If + a shallow sequence of arguments was passed in for `arguments`, then the + sole, zero'th replica's output is returned instead, as a LocalBuffer. + """ if not self._is_compiled: raise ValueError('Cannot execute an uncompiled local XLA computation.') - arguments = tuple(arguments) - if any(arg.is_deleted() for arg in arguments): - raise ValueError('Executing with deleted local buffer argument') - return LocalBuffer( - self._c_computation.Execute([arg.c_buffer for arg in arguments]), - backend=self._backend) + if arguments is None: + arguments = ((),) * get_replica_count() + else: + arguments = [list(replica_args) for replica_args in arguments] + + # Check arguments + for replica, replica_args in enumerate(arguments): + for arg in replica_args: + if arg.is_deleted(): + raise ValueError('Executing with deleted local buffer argument') + if arg.replica() != replica: + raise ValueError( + 'Executing on replica {} with argument from replica {}'.format( + replica, arg.replica())) + + # Pull out argument buffer handles + stripped_args = [ + [arg.c_buffer for arg in replica_args] for replica_args in arguments + ] + + # Execute + if self._backend.backend_type == BackendType.XRT: + if len(stripped_args) > 1: + raise NotImplementedError( + 'Multi-replica execution is not yet supported via the XRT backend.') + output_buffers = [self._c_computation.Execute(stripped_args[0])] + else: + output_buffer_tup = self._c_computation.ExecutePerReplica(stripped_args) + size = output_buffer_tup.size() + output_buffers = [output_buffer_tup.Release(i) for i in xrange(size)] + + # Wrap output handles in LocalBuffer instances + return tuple( + LocalBuffer(output_buffer, backend=self._backend, replica=replica) + for replica, output_buffer in enumerate(output_buffers)) def ExecuteWithPythonValues(self, arguments=()): - """Execute with Python values as arguments and return value.""" - arguments = tuple( - LocalBuffer.from_pyval(arg, backend=self._backend) for arg in arguments) + """Execute on one replica with Python values as arguments and output.""" + + def put(arg): + return LocalBuffer.from_pyval(arg, backend=self._backend) + + arguments = [put(arg) for arg in arguments] return self.Execute(arguments).to_py() + def ExecuteWithPythonValuesPerReplica(self, arguments): + """Execute on many replicas with Python values as arguments and output.""" + + def put(arg, replica): + return LocalBuffer.from_pyval(arg, replica, backend=self._backend) + + arguments = [[put(arg, replica) + for arg in replica_args] + for replica, replica_args in enumerate(arguments)] + return [out.to_py() for out in self.ExecutePerReplica(arguments)] + def __del__(self): self._delete(self._c_computation) @@ -761,8 +855,7 @@ class ComputationBuilder(object): Returns: A LocalOp representing the added broadcast-in-dimensions op. """ - xla_shape = Shape.array_shape(self.GetShape(operand).element_type(), shape) - return self._client.BroadcastInDim(operand, xla_shape, broadcast_dimensions) + return self._client.BroadcastInDim(operand, shape, broadcast_dimensions) def Concatenate(self, operands, dimension): """Enqueues a concatenate operation onto the computation. @@ -1380,6 +1473,7 @@ def initialize_platform_name(platform_name): Raises: A runtime exception if the XLA service has already been initialized. """ + platform_name = _maybe_encode_string(platform_name) c_api.InitializePlatformName(platform_name) diff --git a/tensorflow/compiler/xla/python_api/xla_shape.py b/tensorflow/compiler/xla/python_api/xla_shape.py index f158f6b241..95b2bf300e 100644 --- a/tensorflow/compiler/xla/python_api/xla_shape.py +++ b/tensorflow/compiler/xla/python_api/xla_shape.py @@ -25,9 +25,10 @@ from tensorflow.compiler.xla.python_api import types class Shape(object): - """Wraps a xla_data_pb2.Shape message with a convenient Python type. + """Wraps a xla_data_pb2.ShapeProto message with a convenient Python type. - Provides direct access to the underlying xla_data_pb2.Shape message in the + Provides direct access to the underlying xla_data_pb2.ShapeProto message in + the message attribute, along with accessor wrappers to the message's fields. Avoid direct access to .message unless interacting directly with protobuf APIs like CopyFrom. In other words, prefer hauling the shape around in a Shape, and @@ -48,7 +49,7 @@ class Shape(object): Raises: ValueError: if element_type is TUPLE but dimensions are not Shape objects. """ - self.message = xla_data_pb2.Shape() + self.message = xla_data_pb2.ShapeProto() self.message.element_type = element_type if element_type == xla_data_pb2.TUPLE: if not all(isinstance(subshape, Shape) for subshape in dimensions): diff --git a/tensorflow/compiler/xla/rpc/BUILD b/tensorflow/compiler/xla/rpc/BUILD index 3abb3855a4..26affbcceb 100644 --- a/tensorflow/compiler/xla/rpc/BUILD +++ b/tensorflow/compiler/xla/rpc/BUILD @@ -16,7 +16,6 @@ xla_proto_library( use_grpc_plugin = True, visibility = ["//visibility:public"], deps = [ - "//tensorflow/compiler/xla:xla_data_proto", "//tensorflow/compiler/xla:xla_proto", ], ) diff --git a/tensorflow/compiler/xla/rpc/xla_service.proto b/tensorflow/compiler/xla/rpc/xla_service.proto index e4f332cda2..0ff8adc2ac 100644 --- a/tensorflow/compiler/xla/rpc/xla_service.proto +++ b/tensorflow/compiler/xla/rpc/xla_service.proto @@ -43,7 +43,6 @@ limitations under the License. syntax = "proto3"; import "tensorflow/compiler/xla/xla.proto"; -import "tensorflow/compiler/xla/xla_data.proto"; package xla; diff --git a/tensorflow/compiler/xla/service/BUILD b/tensorflow/compiler/xla/service/BUILD index 19b5c1ca25..81e71eee52 100644 --- a/tensorflow/compiler/xla/service/BUILD +++ b/tensorflow/compiler/xla/service/BUILD @@ -281,10 +281,12 @@ tf_cc_test( "//tensorflow/compiler/xla/service:hlo_element_type_converter", "//tensorflow/compiler/xla/tests:hlo_test_base", "//tensorflow/compiler/xla/tests:literal_test_util", + "//tensorflow/compiler/xla/tests:test_utils", "//tensorflow/compiler/xla/tests:xla_internal_test_main", # fixdeps: keep "//tensorflow/core:lib", "//tensorflow/core:test", "@com_google_absl//absl/memory", + "@com_google_absl//absl/strings:str_format", ], ) @@ -292,6 +294,7 @@ cc_library( name = "hlo", srcs = [ "dfs_hlo_visitor.cc", + "dynamic_parameter_binding.cc", "hlo_computation.cc", "hlo_input_output_alias_config.cc", "hlo_instruction.cc", @@ -305,6 +308,7 @@ cc_library( hdrs = [ "dfs_hlo_visitor.h", "dfs_hlo_visitor_with_default.h", + "dynamic_parameter_binding.h", "hlo_clone_context.h", "hlo_computation.h", "hlo_domain_metadata.h", @@ -350,6 +354,25 @@ cc_library( ], ) +tf_cc_test( + name = "dynamic_parameter_binding_test", + srcs = ["dynamic_parameter_binding_test.cc"], + deps = [ + ":hlo", + ":hlo_dce", + ":hlo_memory_scheduler", + ":hlo_ordering", + ":hlo_parser", + "//tensorflow/compiler/xla:shape_util", + "//tensorflow/compiler/xla:types", + "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/compiler/xla/tests:hlo_test_base", + "//tensorflow/compiler/xla/tests:xla_internal_test_main", + "//tensorflow/core:test", + "@com_google_absl//absl/algorithm:container", + ], +) + tf_cc_test( name = "dfs_hlo_visitor_with_default_test", srcs = ["dfs_hlo_visitor_with_default_test.cc"], @@ -387,9 +410,36 @@ tf_cc_test( ":hlo", ":pattern_matcher", "//tensorflow/compiler/xla:shape_util", + "//tensorflow/compiler/xla:test", "//tensorflow/compiler/xla/service:hlo_parser", "//tensorflow/compiler/xla/tests:xla_internal_test_main", "//tensorflow/core:test", + "@com_google_absl//absl/strings", + ], +) + +cc_library( + name = "pattern_matcher_gmock", + testonly = 1, + hdrs = ["pattern_matcher_gmock.h"], + deps = [ + ":pattern_matcher", + "//tensorflow/compiler/xla:test", + "//tensorflow/core:test", + ], +) + +tf_cc_test( + name = "pattern_matcher_gmock_test", + srcs = ["pattern_matcher_gmock_test.cc"], + deps = [ + ":hlo", + ":pattern_matcher", + ":pattern_matcher_gmock", + "//tensorflow/compiler/xla:shape_util", + "//tensorflow/compiler/xla:test", + "//tensorflow/compiler/xla/tests:xla_internal_test_main", + "//tensorflow/core:test", ], ) @@ -403,6 +453,7 @@ cc_library( "//tensorflow/compiler/xla:util", "//tensorflow/core:lib", "//tensorflow/core:lib_internal", + "@com_google_absl//absl/base", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/types:span", ], @@ -1336,6 +1387,7 @@ cc_library( ":hlo", "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:shape_util", + "@com_google_absl//absl/container:flat_hash_set", ], ) @@ -1539,7 +1591,10 @@ tf_cc_test( ":hlo", ":hlo_casting_utils", ":hlo_matchers", + ":hlo_parser", ":hlo_pass", + ":pattern_matcher", + ":pattern_matcher_gmock", "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:shape_util", "//tensorflow/compiler/xla:test", @@ -1707,7 +1762,9 @@ cc_library( ":hlo", ":hlo_pass", ":hlo_query", + ":pattern_matcher", ":while_loop_analysis", + "//tensorflow/compiler/xla:shape_util", "//tensorflow/compiler/xla:statusor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", @@ -1720,9 +1777,14 @@ tf_cc_test( name = "while_loop_simplifier_test", srcs = ["while_loop_simplifier_test.cc"], deps = [ + ":algebraic_simplifier", ":hlo", + ":hlo_cse", ":hlo_dce", ":hlo_matchers", + ":hlo_pass", + ":hlo_pass_pipeline", + ":tuple_simplifier", ":while_loop_simplifier", "//tensorflow/compiler/xla:test", "//tensorflow/compiler/xla/tests:hlo_test_base", @@ -2347,6 +2409,7 @@ cc_library( "//tensorflow/compiler/xla:util", "//tensorflow/compiler/xla:xla_data_proto", "//tensorflow/core:lib", + "@com_google_absl//absl/container:flat_hash_map", ], ) @@ -2600,6 +2663,8 @@ tf_cc_test( ":hlo", ":hlo_matchers", ":layout_assignment", + ":pattern_matcher", + ":pattern_matcher_gmock", "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:shape_layout", "//tensorflow/compiler/xla:shape_util", @@ -2744,6 +2809,8 @@ tf_cc_test( ":hlo_matchers", ":hlo_parser", ":hlo_pass", + ":pattern_matcher", + ":pattern_matcher_gmock", "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:shape_util", "//tensorflow/compiler/xla:test", @@ -2855,6 +2922,46 @@ tf_cc_test( ], ) +cc_library( + name = "hlo_get_dimension_size_rewriter", + srcs = ["hlo_get_dimension_size_rewriter.cc"], + hdrs = ["hlo_get_dimension_size_rewriter.h"], + deps = [ + ":hlo", + ":hlo_pass", + ":shape_inference", + "//tensorflow/compiler/xla:literal", + "//tensorflow/compiler/xla:literal_util", + "//tensorflow/compiler/xla:shape_util", + "//tensorflow/compiler/xla:types", + "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/core:lib", + "@com_google_absl//absl/algorithm:container", + ], +) + +tf_cc_test( + name = "hlo_get_dimension_size_rewriter_test", + srcs = ["hlo_get_dimension_size_rewriter_test.cc"], + deps = [ + ":hlo", + ":hlo_get_dimension_size_rewriter", + ":hlo_matchers", + ":hlo_parser", + "//tensorflow/compiler/xla:literal", + "//tensorflow/compiler/xla:shape_util", + "//tensorflow/compiler/xla:types", + "//tensorflow/compiler/xla:util", + "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/compiler/xla/tests:hlo_test_base", + "//tensorflow/compiler/xla/tests:literal_test_util", + "//tensorflow/compiler/xla/tests:test_utils", + "//tensorflow/compiler/xla/tests:xla_internal_test_main", + "//tensorflow/core:lib", + "//tensorflow/core:test", + ], +) + cc_library( name = "device_memory_allocator", srcs = [ @@ -2913,6 +3020,7 @@ cc_library( "//tensorflow/core:lib", "//tensorflow/core:lib_internal", "@com_google_absl//absl/algorithm:container", + "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/strings", "@llvm//:core", "@llvm//:transform_utils", @@ -3026,6 +3134,7 @@ cc_library( ":hlo_casting_utils", ":hlo_execution_profile", ":hlo_tfgraph_builder", + ":pattern_matcher", "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:shape_util", "//tensorflow/compiler/xla:types", @@ -3318,9 +3427,9 @@ cc_library( ":tuple_util", ":while_loop_analysis", ":while_util", + "//tensorflow/compiler/xla:shape_util", "//tensorflow/compiler/xla:statusor", "//tensorflow/compiler/xla:util", - "//tensorflow/core:lib", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", @@ -3463,6 +3572,8 @@ tf_cc_test( ":hlo_casting_utils", ":hlo_matchers", ":hlo_parser", + ":pattern_matcher", + ":pattern_matcher_gmock", "//tensorflow/compiler/xla:test_helpers", "//tensorflow/compiler/xla:window_util", "//tensorflow/core:lib", @@ -3513,6 +3624,41 @@ cc_library( ], ) +cc_library( + name = "ar_crs_combiner", + srcs = ["ar_crs_combiner.cc"], + hdrs = ["ar_crs_combiner.h"], + deps = [ + ":call_graph", + ":pattern_matcher", + "//tensorflow/compiler/xla:literal", + "//tensorflow/compiler/xla:literal_util", + "//tensorflow/compiler/xla:status_macros", + "//tensorflow/compiler/xla:statusor", + "//tensorflow/compiler/xla:types", + "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/compiler/xla/service:hlo", + "//tensorflow/compiler/xla/service:hlo_pass", + "@com_google_absl//absl/container:flat_hash_map", + "@com_google_absl//absl/strings", + ], +) + +tf_cc_test( + name = "ar_crs_combiner_test", + srcs = ["ar_crs_combiner_test.cc"], + deps = [ + ":ar_crs_combiner", + ":hlo", + ":hlo_matchers", + "//tensorflow/compiler/xla:statusor", + "//tensorflow/compiler/xla/tests:hlo_test_base", + "//tensorflow/compiler/xla/tests:xla_internal_test_main", + "//tensorflow/core:lib", + "//tensorflow/core:test", + ], +) + tf_cc_test( name = "map_inliner_test", srcs = ["map_inliner_test.cc"], diff --git a/tensorflow/compiler/xla/service/algebraic_simplifier.cc b/tensorflow/compiler/xla/service/algebraic_simplifier.cc index 89e62bd2f0..985c5af1c4 100644 --- a/tensorflow/compiler/xla/service/algebraic_simplifier.cc +++ b/tensorflow/compiler/xla/service/algebraic_simplifier.cc @@ -16,6 +16,7 @@ limitations under the License. #include "tensorflow/compiler/xla/service/algebraic_simplifier.h" #include +#include #include #include #include @@ -68,6 +69,45 @@ bool IsAll(const HloInstruction* op, int8 value) { } } +// Checks whether `op` is a floating-point constant or broadcast of a constant +// of the form +/- 2^k for some integer k positive, negative, or zero. Such +// values are interesting because multiplying by a power of 2 just moves the +// exponent. +bool IsAllFpConstantPowerOf2(const HloInstruction* op) { + // Unwrap the broadcast if necessary. + const HloInstruction* c; + if (!Match(op, m::ConstantEffectiveScalar(&c)) && + !Match(op, m::Broadcast(m::Constant(&c).WithShape( + m::Shape().IsEffectiveScalar())))) { + return false; + } + auto val = [&]() -> absl::optional { + switch (c->shape().element_type()) { + case BF16: + return static_cast(c->literal().GetFirstElement()); + case F16: + return static_cast(c->literal().GetFirstElement()); + case F32: + return c->literal().GetFirstElement(); + case F64: + return c->literal().GetFirstElement(); + default: + // Cowardly refuse to consider complex types. + return absl::nullopt; + } + }(); + if (!val) { + return false; + } + + int exp; + double mantissa = std::frexp(*val, &exp); + // frexp returns a value in the range (-1; -0.5] U [0.5, 1). A return value + // of +/-0.5 therefore indicates that the floating point value is a power of + // 2. + return mantissa == 0.5 || mantissa == -0.5; +} + // Returns whether the given transpose produces a result which is bit-wise // identical to its operand and thus may be replaced with a bitcast. bool TransposeIsBitcast(const HloInstruction* transpose) { @@ -84,7 +124,8 @@ bool TransposeIsBitcast(const HloInstruction* transpose) { // reshape may still be a bitcast. For example, a reshape from [28x28] to [784]. bool ReshapeOrCopyIsBitcast( const HloInstruction* instr, - const AlgebraicSimplifier::ValidBitcastCallback& valid_bitcast_callback) { + const AlgebraicSimplifierOptions::ValidBitcastCallback& + valid_bitcast_callback) { CHECK(HloOpcode::kReshape == instr->opcode() || HloOpcode::kCopy == instr->opcode()); @@ -95,6 +136,11 @@ bool ReshapeOrCopyIsBitcast( valid_bitcast_callback(operand->shape(), instr->shape()); } +bool IsUnstridedSlice(const HloInstruction* hlo) { + return absl::c_all_of(hlo->slice_strides(), + [](int64 stride) { return stride == 1; }); +} + // AlgebraicSimplifierVisitor traverses the HLO computation and reduces certain // algebraic expressions to simplified forms. Note: This only supports // simplifications that simply look at the operands of an instruction. For the @@ -180,21 +226,13 @@ class AlgebraicSimplifierVisitor : public DfsHloVisitorWithDefault { const bool changed() const { return changed_; } // Runs the visitor on a computation. - static bool Run( - HloComputation* computation, bool is_layout_sensitive, - AlgebraicSimplifier::ValidBitcastCallback valid_bitcast_callback, - bool enable_dot_strength_reduction, bool enable_conv_simplification); + static bool Run(HloComputation* computation, + const AlgebraicSimplifierOptions& options); private: - explicit AlgebraicSimplifierVisitor( - HloComputation* computation, bool is_layout_sensitive, - AlgebraicSimplifier::ValidBitcastCallback valid_bitcast_callback, - bool enable_dot_strength_reduction, bool enable_conv_simplification) - : computation_(computation), - is_layout_sensitive_(is_layout_sensitive), - valid_bitcast_callback_(std::move(valid_bitcast_callback)), - enable_dot_strength_reduction_(enable_dot_strength_reduction), - enable_conv_simplification_(enable_conv_simplification) {} + explicit AlgebraicSimplifierVisitor(HloComputation* computation, + const AlgebraicSimplifierOptions& options) + : computation_(computation), options_(options) {} // Transforms Dots where at least one input is a vector or has a degenerate // dimension and converts it into a multiply and reduce. This should enable @@ -233,10 +271,10 @@ class AlgebraicSimplifierVisitor : public DfsHloVisitorWithDefault { HloInstruction* new_instruction); // Returns whether the shape of the output of the given instructions are the - // same for the purposes of simplification. If is_layout_sensitive_ is true, - // then this tests shape equality including layout (ShapeUtil::Equal). If - // is_layout_sensitive_ is false, then the tests shape compatibility - // (ShapeUtil::Compatible). + // same for the purposes of simplification. If options_.is_layout_sensitive() + // is true, then this tests shape equality including layout + // (ShapeUtil::Equal). If options_.is_layout_sensitive() is false, then the + // tests shape compatibility (ShapeUtil::Compatible). bool SameShape(const HloInstruction* lhs, const HloInstruction* rhs) const; // Returns whether it was possible to transform `root` to a clamp instruction. @@ -325,22 +363,12 @@ class AlgebraicSimplifierVisitor : public DfsHloVisitorWithDefault { // traversing. HloComputation* computation_; + // The backend-specific options selected for the algebraic simplifier. + const AlgebraicSimplifierOptions& options_; + // Whether algebraic simplification has occurred. bool changed_ = false; - // Whether layout is considered during transformation. - bool is_layout_sensitive_; - - // Callback used to determine if a bitcast is possible. - AlgebraicSimplifier::ValidBitcastCallback valid_bitcast_callback_; - - // Disable dot strength reduction on platforms where it causes a slowdown. - bool enable_dot_strength_reduction_; - - // Disable convolution -> dot simplification on platforms where it causes a - // slowdown. - bool enable_conv_simplification_; - // Cached computation for adding two scalar F32. HloComputation* scalar_add_computation_ = nullptr; }; @@ -348,19 +376,15 @@ class AlgebraicSimplifierVisitor : public DfsHloVisitorWithDefault { } // namespace bool AlgebraicSimplifierVisitor::Run( - HloComputation* computation, bool is_layout_sensitive, - AlgebraicSimplifier::ValidBitcastCallback valid_bitcast_callback, - bool enable_dot_strength_reduction, bool enable_conv_simplification) { - AlgebraicSimplifierVisitor visitor( - computation, is_layout_sensitive, std::move(valid_bitcast_callback), - enable_dot_strength_reduction, enable_conv_simplification); + HloComputation* computation, const AlgebraicSimplifierOptions& options) { + AlgebraicSimplifierVisitor visitor(computation, options); TF_CHECK_OK(computation->Accept(&visitor)); return visitor.changed_; } bool AlgebraicSimplifierVisitor::SameShape(const HloInstruction* lhs, const HloInstruction* rhs) const { - if (is_layout_sensitive_) { + if (options_.is_layout_sensitive()) { return ShapeUtil::Equal(lhs->shape(), rhs->shape()); } else { return ShapeUtil::Compatible(lhs->shape(), rhs->shape()); @@ -431,6 +455,40 @@ Status AlgebraicSimplifierVisitor::HandleAdd(HloInstruction* add) { sum_of_constants)); } + // A*C + B*C => (A+B)*C + // + // - If A, B, and C are integers, do this unconditionally. Proof of + // correctness: https://rise4fun.com/Alive/u9X. + // + // - If A, B, and C are floating point, do this if C is a scalar constant or + // broadcast of scalar constant and is equal to +/- 2^k for some (possibly + // negative) integer k. + // + // Multiplying by a power of 2 just moves the exponent, so our answer is + // exact modulo rounding of intermediate results so long as + // + // - none of the three products has an exponent which underflows (so the + // result is 0 or denormal), and + // - none of the three products overflows to inf. + // + // Proof: See algebraic_simplifier_proof_distributive_property.py. + // + // We deem these differences in rounding, underflow, and overflow + // acceptable in the ML context. + HloInstruction *b, *c; + if (((Match(lhs, m::Multiply(m::Op(&a), m::Op(&c))) && + Match(rhs, m::MultiplyAnyOrder(m::Op().Is(c), m::Op(&b)))) || + (Match(lhs, m::Multiply(m::Op(&c), m::Op(&a))) && + Match(rhs, m::MultiplyAnyOrder(m::Op().Is(c), m::Op(&b))))) && + (ShapeUtil::ElementIsIntegral(add->shape()) || + IsAllFpConstantPowerOf2(c))) { + return ReplaceWithNewInstruction( + add, HloInstruction::CreateBinary( + add->shape(), HloOpcode::kMultiply, + computation_->AddInstruction(HloInstruction::CreateBinary( + add->shape(), HloOpcode::kAdd, a, b)), + c)); + } return Status::OK(); } @@ -504,8 +562,8 @@ Status AlgebraicSimplifierVisitor::HandleCopy(HloInstruction* copy) { return Status::OK(); } - if (is_layout_sensitive_ && - ReshapeOrCopyIsBitcast(copy, valid_bitcast_callback_)) { + if (options_.is_layout_sensitive() && + ReshapeOrCopyIsBitcast(copy, options_.valid_bitcast_callback())) { ReplaceWithBitcast(copy); } @@ -541,7 +599,74 @@ Status AlgebraicSimplifierVisitor::HandleConcatenate( VLOG(10) << "trying to replace " << concatenate->ToString() << " with " << replacement->ToString(); ReplaceInstructionIfSameShape(concatenate, replacement); - } else if (operands.size() == 2) { + return Status::OK(); + } + + // Check if we can merge "adjacent" slice operands which take slices from the + // same other op. For simplicity we only merge unstrided slices. + int64 concatenate_dimension = concatenate->concatenate_dimension(); + for (int64 i = 0; i < operands.size(); ++i) { + if (operands[i]->opcode() != HloOpcode::kSlice || + !IsUnstridedSlice(operands[i])) { + continue; + } + int64 slice_end = operands[i]->slice_limits(concatenate_dimension); + HloInstruction* slice_operand = operands[i]->mutable_operand(0); + int64 j = i + 1; + while (j < operands.size() && operands[j]->opcode() == HloOpcode::kSlice && + IsUnstridedSlice(operands[j]) && + operands[j]->operand(0) == slice_operand && + operands[j]->slice_starts(concatenate_dimension) == slice_end) { + // Check that all the slice_start values are the same in all other + // dimensions. This implies that the slice_limit values are also the same, + // because operands of concatenate need to have the same shape, and we + // already checked that the slices are unstrided. + bool same_other_starts = true; + for (int64 k = 0; k < operands[j]->slice_starts().size(); ++k) { + if (k == concatenate_dimension) { + continue; + } + if (operands[i]->slice_starts(k) != operands[j]->slice_starts(k)) { + same_other_starts = false; + break; + } + } + if (!same_other_starts) { + break; + } + slice_end = operands[j]->slice_limits(concatenate_dimension); + ++j; + } + if (j - i > 1) { + Shape new_slice_shape = operands[i]->shape(); + new_slice_shape.set_dimensions( + concatenate_dimension, + slice_end - operands[i]->slice_starts(concatenate_dimension)); + auto new_limit_indices = operands[i]->slice_limits(); + new_limit_indices[concatenate_dimension] = slice_end; + auto new_slice_op = + computation_->AddInstruction(HloInstruction::CreateSlice( + new_slice_shape, slice_operand, + /*start_indices=*/operands[i]->slice_starts(), + /*limit_indices=*/new_limit_indices, + /*strides=*/operands[i]->slice_strides())); + std::vector new_operands; + for (int64 k = 0; k < i; ++k) { + new_operands.push_back(operands[k]); + } + new_operands.push_back(new_slice_op); + for (int64 k = j; k < operands.size(); ++k) { + new_operands.push_back(operands[k]); + } + auto replacement = + computation_->AddInstruction(concatenate->CloneWithNewOperands( + concatenate->shape(), new_operands)); + ReplaceInstructionIfSameShape(concatenate, replacement); + return Status::OK(); + } + } + + if (operands.size() == 2) { // A binary concat with a broadcasted scalar as an operand can be converted // into a pad which is simpler to fold into other operations. bool is_effective_low_pad = Match( @@ -557,7 +682,7 @@ Status AlgebraicSimplifierVisitor::HandleConcatenate( padding_config_dim->set_edge_padding_high(0); padding_config_dim->set_edge_padding_low(0); padding_config_dim->set_interior_padding(0); - if (dim == concatenate->concatenate_dimension()) { + if (dim == concatenate_dimension) { if (is_effective_low_pad) { padding_config_dim->set_edge_padding_low( operands[0]->shape().dimensions(dim)); @@ -1215,7 +1340,8 @@ Status AlgebraicSimplifierVisitor::HandleDot(HloInstruction* dot) { return ReplaceInstruction(dot, dot_of_gather_optimized); } - if (enable_dot_strength_reduction_ && !is_layout_sensitive_) { + if (options_.enable_dot_strength_reduction() && + !options_.is_layout_sensitive()) { TF_ASSIGN_OR_RETURN(bool did_strength_reduction, HandleDotStrengthReduction(dot)); if (did_strength_reduction) { @@ -1619,6 +1745,27 @@ Status AlgebraicSimplifierVisitor::HandlePad(HloInstruction* pad) { pad, HloInstruction::CreateBroadcast(pad->shape(), pad->mutable_operand(1), {})); } + + // Interior padding on one sized dimensions have no effect. As a result it + // makes other simplifications possible if there is no interior padding. + if (HasInteriorPadding(pad->padding_config())) { + PaddingConfig padding_config = pad->padding_config(); + bool cleared_interior_padding = false; + for (int64 i = 0; i < ShapeUtil::Rank(pad->shape()); ++i) { + if (padding_config.dimensions(i).interior_padding() > 0 && + pad->operand(0)->shape().dimensions(i) == 1) { + cleared_interior_padding = true; + padding_config.mutable_dimensions(i)->set_interior_padding(0); + } + } + if (cleared_interior_padding) { + return ReplaceWithNewInstruction( + pad, + HloInstruction::CreatePad(pad->shape(), pad->mutable_operand(0), + pad->mutable_operand(1), padding_config)); + } + } + // Eliminate nop pads (padding all zero), and replace a pad with negative // padding with a pad with non-negative padding followed by a slice. bool all_zero = true; @@ -1910,8 +2057,8 @@ Status AlgebraicSimplifierVisitor::HandleReshape(HloInstruction* reshape) { } // Make this a bitcast if possible. - if (is_layout_sensitive_ && - ReshapeOrCopyIsBitcast(reshape, valid_bitcast_callback_)) { + if (options_.is_layout_sensitive() && + ReshapeOrCopyIsBitcast(reshape, options_.valid_bitcast_callback())) { ReplaceWithBitcast(reshape); return Status::OK(); } @@ -2030,11 +2177,6 @@ StatusOr AlgebraicSimplifierVisitor::TrySimplifyScalarSlice( return false; } -bool IsUnstridedSlice(const HloInstruction* hlo) { - return absl::c_all_of(hlo->slice_strides(), - [](int64 stride) { return stride == 1; }); -} - StatusOr AlgebraicSimplifierVisitor::TryToReorderSliceAndReshape( HloInstruction* slice) { CHECK_EQ(slice->opcode(), HloOpcode::kSlice); @@ -2501,6 +2643,108 @@ Status AlgebraicSimplifierVisitor::HandleSort(HloInstruction* sort) { return ReplaceWithNewInstruction( sort, HloInstruction::CreateTuple(sort->operands())); } + if (!options_.enable_permutation_sort_replacement()) { + return Status::OK(); + } + // Check if we are sorting a permutation. In that case, we know that the keys + // will be sorted to the identity permutation, and we can represent the + // changes to the 'values' parameter as a scatter. + if (sort->operand_count() == 2 && + operand->opcode() == HloOpcode::kGetTupleElement) { + const HloInstruction* other_sort = operand->operand(0); + // Check whether the 'values' parameter is the result of another sort with + // the same sort dimension. + if (other_sort->opcode() == HloOpcode::kSort && + other_sort->operand_count() >= 2 && + other_sort->dimensions(0) == dimension_to_sort && + other_sort->operand(operand->tuple_index())->opcode() == + HloOpcode::kIota) { + auto* iota = + Cast(other_sort->operand(operand->tuple_index())); + // The sort operand needs to be an integral iota, and the iota dimension + // needs to be the dimension that was sorted. + if (iota->iota_dimension() == dimension_to_sort && + ShapeUtil::ElementIsIntegral(iota->shape())) { + // We use the following construction method for a Scatter that applies + // the permutation from 'keys' to the 'values' parameter. + // - Take the "keys" parameter of the second sort and reshape it to have + // another "1" dimension at the end. + // - Concatenate it with iotas of the same extended shape with all + // different iota_dimensions except the dimension_to_sort in the order + // of iota_dimensions/dimension_to_sort, so e.g. with rank 3 and + // dimension_to_sort = 1, we would have concatenate of (iota with + // iota_dimension=0, keys, iota with iota_dimension = 2) + // - Use this as the indices parameter of scatter, and set updates + // of the scatter to be a reshaped 'values' parameter of sort (adding + // 'rank' many 1 dimensions at the end). + int64 rank = ShapeUtil::Rank(operand->shape()); + Shape extended_shape = operand->shape(); + extended_shape.add_dimensions(1); + extended_shape.mutable_layout()->add_minor_to_major(rank); + auto reshaped_permutation = computation_->AddInstruction( + HloInstruction::CreateReshape(extended_shape, operand)); + std::vector concat_operands; + for (int64 i = 0; i < rank; ++i) { + if (i == dimension_to_sort) { + concat_operands.push_back(reshaped_permutation); + } else { + concat_operands.push_back(computation_->AddInstruction( + HloInstruction::CreateIota(extended_shape, i))); + } + } + Shape concat_shape = operand->shape(); + concat_shape.add_dimensions(rank); + concat_shape.mutable_layout()->add_minor_to_major(rank); + auto scatter_indices = + rank > 1 ? computation_->AddInstruction( + HloInstruction::CreateConcatenate( + concat_shape, concat_operands, rank)) + : reshaped_permutation; + + // We don't care about the operand, it will be completely overridden by + // the updates. + auto scatter_operand = computation_->AddInstruction( + HloInstruction::CreateIota(sort->operand(1)->shape(), 0)); + + // Construct the updates operand of scatter. + Shape update_shape = sort->operand(1)->shape(); + for (int64 i = 0; i < rank; ++i) { + update_shape.add_dimensions(1); + update_shape.mutable_layout()->add_minor_to_major(rank + i); + } + auto scatter_updates = + computation_->AddInstruction(HloInstruction::CreateReshape( + update_shape, sort->mutable_operand(1))); + + // Construct the updates computation, which simply replaces the operand + // values with the update values. + HloComputation::Builder b("update_replace_computation"); + Shape scalar_shape = ShapeUtil::MakeShape(S32, {}); + b.AddInstruction( + HloInstruction::CreateParameter(0, scalar_shape, "scalar_lhs")); + auto scalar_rhs = b.AddInstruction( + HloInstruction::CreateParameter(1, scalar_shape, "scalar_rhs")); + auto update_replace_computation = + computation_->parent()->AddEmbeddedComputation(b.Build(scalar_rhs)); + + ScatterDimensionNumbers dim_numbers; + dim_numbers.set_index_vector_dim(rank); + for (int64 i = 0; i < rank; ++i) { + dim_numbers.add_update_window_dims(rank + i); + dim_numbers.add_scatter_dims_to_operand_dims(i); + } + auto scatter = + computation_->AddInstruction(HloInstruction::CreateScatter( + sort->operand(1)->shape(), scatter_operand, scatter_indices, + scatter_updates, update_replace_computation, dim_numbers)); + return ReplaceWithNewInstruction( + sort, HloInstruction::CreateTuple( + {computation_->AddInstruction(HloInstruction::CreateIota( + operand->shape(), dimension_to_sort)), + scatter})); + } + } + } return Status::OK(); } @@ -2525,7 +2769,7 @@ Status AlgebraicSimplifierVisitor::HandleTranspose(HloInstruction* transpose) { return ReplaceInstruction(transpose, operand); } - if (is_layout_sensitive_ && TransposeIsBitcast(transpose)) { + if (options_.is_layout_sensitive() && TransposeIsBitcast(transpose)) { ReplaceWithBitcast(transpose); return Status::OK(); } @@ -2674,13 +2918,13 @@ StatusOr AlgebraicSimplifierVisitor::SimplifyConvToDot( const ConvolutionDimensionNumbers& dnums = convolution->convolution_dimension_numbers(); - if (!enable_conv_simplification_) { + if (!options_.enable_conv_simplification()) { return false; } // TODO(b/31337498): For now, we cowardly refuse to do this optimization in // layout-insensitive mode, for fear of adding nontrivial reshapes. - if (!is_layout_sensitive_) { + if (!options_.is_layout_sensitive()) { return false; } @@ -2770,9 +3014,9 @@ StatusOr AlgebraicSimplifierVisitor::SimplifyConvToDot( // We cannot insert bitcasts if the layouts will not be compatible. // TODO(b/33178038): Consider inserting a transpose if a bitcast would be // invalid. - if (!valid_bitcast_callback_(input_shape, new_input_shape) || - !valid_bitcast_callback_(filter_shape, new_filter_shape) || - !valid_bitcast_callback_(dot_output_shape, convolution_shape)) { + if (!options_.valid_bitcast_callback()(input_shape, new_input_shape) || + !options_.valid_bitcast_callback()(filter_shape, new_filter_shape) || + !options_.valid_bitcast_callback()(dot_output_shape, convolution_shape)) { return false; } @@ -2878,9 +3122,7 @@ StatusOr AlgebraicSimplifier::Run(HloModule* module) { "AlgebraicSimplifier::Run(), before:\n" + module->ToString()); bool changed = false; for (auto* comp : module->MakeNonfusionComputations()) { - if (AlgebraicSimplifierVisitor::Run( - comp, is_layout_sensitive_, valid_bitcast_callback_, - enable_dot_strength_reduction_, enable_conv_simplification_)) { + if (AlgebraicSimplifierVisitor::Run(comp, options_)) { changed = true; } } diff --git a/tensorflow/compiler/xla/service/algebraic_simplifier.h b/tensorflow/compiler/xla/service/algebraic_simplifier.h index 9f8d0ee88b..d2775b9faf 100644 --- a/tensorflow/compiler/xla/service/algebraic_simplifier.h +++ b/tensorflow/compiler/xla/service/algebraic_simplifier.h @@ -23,8 +23,7 @@ limitations under the License. namespace xla { -// A pass which performs algebraic simplifications. -class AlgebraicSimplifier : public HloModulePass { +class AlgebraicSimplifierOptions { public: // Given shapes 'from_shape' and 'to_shape', determines if it is valid to // bitcast from 'from_shape' to 'to_shape' after considering platform @@ -34,18 +33,63 @@ class AlgebraicSimplifier : public HloModulePass { using ValidBitcastCallback = std::function; + explicit AlgebraicSimplifierOptions( + ValidBitcastCallback valid_bitcast_callback) + : valid_bitcast_callback_(std::move(valid_bitcast_callback)) {} + // If valid_bitcast_callback returns true, then the pass will replace reshapes + // and transposes with bitcasts. + const ValidBitcastCallback& valid_bitcast_callback() const { + return valid_bitcast_callback_; + } + + // If is_layout_sensitive is true, then the simplifier preserves layout during + // transformation. Otherwise, layout is ignored. + void set_is_layout_sensitive(bool is_layout_sensitive) { + is_layout_sensitive_ = is_layout_sensitive; + } + bool is_layout_sensitive() const { return is_layout_sensitive_; } + + // Enable dot simplification on platforms where it is profitable. + void set_enable_dot_strength_reduction(bool enable_dot_strength_reduction) { + enable_dot_strength_reduction_ = enable_dot_strength_reduction; + } + bool enable_dot_strength_reduction() const { + return enable_dot_strength_reduction_; + } + + // Enable convolution simplification on platforms where it is profitable. + void set_enable_conv_simplification(bool enable_conv_simplification) { + enable_conv_simplification_ = enable_conv_simplification; + } + bool enable_conv_simplification() const { + return enable_conv_simplification_; + } + + // If enable_permutation_sort_replacement is true, a sort op that is known to + // sort a permutation will be replaced with a scatter op. + void set_enable_permutation_sort_replacement( + bool enable_permutation_sort_replacement) { + enable_permutation_sort_replacement_ = enable_permutation_sort_replacement; + } + bool enable_permutation_sort_replacement() const { + return enable_permutation_sort_replacement_; + } + + private: + ValidBitcastCallback valid_bitcast_callback_; + bool is_layout_sensitive_{false}; + bool enable_dot_strength_reduction_{true}; + bool enable_conv_simplification_{true}; + bool enable_permutation_sort_replacement_{false}; +}; + +// A pass which performs algebraic simplifications. +class AlgebraicSimplifier : public HloModulePass { + public: // If is_layout_sensitive is true, then the simplifier preserves layout during - // transformation. Otherwise, layout is ignored. If valid_bitcast_callback - // returns true, then the pass will replace reshapes and transposes with - // bitcasts. - AlgebraicSimplifier(bool is_layout_sensitive, - ValidBitcastCallback valid_bitcast_callback, - bool enable_dot_strength_reduction = true, - bool enable_conv_simplification = true) - : is_layout_sensitive_(is_layout_sensitive), - valid_bitcast_callback_(std::move(valid_bitcast_callback)), - enable_dot_strength_reduction_(enable_dot_strength_reduction), - enable_conv_simplification_(enable_conv_simplification) {} + // transformation. Otherwise, layout is ignored. + explicit AlgebraicSimplifier(const AlgebraicSimplifierOptions& options) + : options_(options) {} ~AlgebraicSimplifier() override = default; absl::string_view name() const override { return "algsimp"; } @@ -54,14 +98,7 @@ class AlgebraicSimplifier : public HloModulePass { StatusOr Run(HloModule* module) override; private: - bool is_layout_sensitive_; - ValidBitcastCallback valid_bitcast_callback_; - - // Enable dot simplification on platforms where it is profitable. - bool enable_dot_strength_reduction_; - - // Enable convolution simplification on platforms where it is profitable. - bool enable_conv_simplification_; + AlgebraicSimplifierOptions options_; }; } // namespace xla diff --git a/tensorflow/compiler/xla/service/algebraic_simplifier_proof_distributive_property.py b/tensorflow/compiler/xla/service/algebraic_simplifier_proof_distributive_property.py new file mode 100644 index 0000000000..5da13da041 --- /dev/null +++ b/tensorflow/compiler/xla/service/algebraic_simplifier_proof_distributive_property.py @@ -0,0 +1,82 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Proof that transforming (A*C)+(B*C) <=> (A+B)*C is "safe" if C=2^k. + +Specifically, for all floating-point values A, B, and C, if + + - C is equal to +/- 2^k for some (possibly negative) integer k, and + - A, B, C, A*C, B*C, and A+B are not subnormal, zero, or inf, + +then there exists a rounding mode rm in [RTZ, RNE] such that + + (A*C) + (B*C) == (A+B) * C (computed with rounding mode rm). + +Informally, this means that the equivalence holds for powers of 2 C, modulo +flushing to zero or inf, and modulo rounding of intermediate results. + +Requires z3 python bindings; try `pip install z3-solver`. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +import z3 + +# We do float16 because it lets the solver run much faster. These results +# should generalize to fp32 and fp64, and you can verify this by changing the +# value of FLOAT_TY (and then waiting a while). +FLOAT_TY = z3.Float16 + +a = z3.FP("a", FLOAT_TY()) +b = z3.FP("b", FLOAT_TY()) +c = z3.FP("c", FLOAT_TY()) + +s = z3.Solver() + +# C must be a power of 2, i.e. significand bits must all be 0. +s.add(z3.Extract(FLOAT_TY().sbits() - 1, 0, z3.fpToIEEEBV(c)) == 0) + +for rm in [z3.RTZ(), z3.RNE()]: + z3.set_default_rounding_mode(rm) + before = a * c + b * c + after = (a + b) * c + + # Check that before == after, allowing that 0 == -0. + s.add( + z3.Not( + z3.Or( + before == after, # + z3.And(z3.fpIsZero(before), z3.fpIsZero(after))))) + + for x in [ + (a * c), + (b * c), + (a + b), + ]: + s.add(z3.Not(z3.fpIsSubnormal(x))) + s.add(z3.Not(z3.fpIsZero(x))) + s.add(z3.Not(z3.fpIsInf(x))) + +if s.check() == z3.sat: + m = s.model() + print("Counterexample found!") + print(m) + print("a*c: ", z3.simplify(m[a] * m[c])) + print("b*c: ", z3.simplify(m[b] * m[c])) + print("a+b: ", z3.simplify(m[a] + m[b])) + print("a*c + b*c: ", z3.simplify(m[a] * m[c] + m[b] * m[c])) + print("(a+b) * c: ", z3.simplify((m[a] + m[b]) * m[c])) +else: + print("Proved!") diff --git a/tensorflow/compiler/xla/service/algebraic_simplifier_test.cc b/tensorflow/compiler/xla/service/algebraic_simplifier_test.cc index e4c4da1b0e..14ce519b6a 100644 --- a/tensorflow/compiler/xla/service/algebraic_simplifier_test.cc +++ b/tensorflow/compiler/xla/service/algebraic_simplifier_test.cc @@ -27,9 +27,11 @@ limitations under the License. #include "tensorflow/compiler/xla/service/hlo_computation.h" #include "tensorflow/compiler/xla/service/hlo_instruction.h" #include "tensorflow/compiler/xla/service/hlo_instructions.h" -#include "tensorflow/compiler/xla/service/hlo_matchers.h" #include "tensorflow/compiler/xla/service/hlo_opcode.h" +#include "tensorflow/compiler/xla/service/hlo_parser.h" #include "tensorflow/compiler/xla/service/hlo_pass_fix.h" +#include "tensorflow/compiler/xla/service/pattern_matcher.h" +#include "tensorflow/compiler/xla/service/pattern_matcher_gmock.h" #include "tensorflow/compiler/xla/shape_util.h" #include "tensorflow/compiler/xla/test.h" #include "tensorflow/compiler/xla/tests/hlo_test_base.h" @@ -42,18 +44,20 @@ namespace xla { namespace { using ::testing::ElementsAre; +namespace m = match; -namespace op = xla::testing::opcode_matchers; - -AlgebraicSimplifier::ValidBitcastCallback bitcasting_callback() { +AlgebraicSimplifierOptions::ValidBitcastCallback bitcasting_callback() { return [](const Shape&, const Shape&) { return true; }; } -AlgebraicSimplifier::ValidBitcastCallback non_bitcasting_callback() { +AlgebraicSimplifierOptions::ValidBitcastCallback non_bitcasting_callback() { return [](const Shape&, const Shape&) { return false; }; } -class AlgebraicSimplifierTest : public HloTestBase {}; +class AlgebraicSimplifierTest : public HloTestBase { + protected: + AlgebraicSimplifierOptions default_options_{non_bitcasting_callback()}; +}; // Test that A + 0 is simplified to A TEST_F(AlgebraicSimplifierTest, AddZero) { @@ -70,13 +74,134 @@ TEST_F(AlgebraicSimplifierTest, AddZero) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kAdd); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); } +TEST_F(AlgebraicSimplifierTest, FactorIntegerAddition) { + const char* kModuleStr = R"( + HloModule m + test { + p0 = s32[8] parameter(0) + p1 = s32[8] parameter(1) + p2 = s32[8] parameter(2) + x = s32[8] multiply(p0, p2) + y = s32[8] multiply(p1, p2) + ROOT sum = s32[8] add(x, y) + } + )"; + TF_ASSERT_OK_AND_ASSIGN(auto m, ParseAndReturnVerifiedModule(kModuleStr)); + AlgebraicSimplifier simplifier(default_options_); + ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); + EXPECT_THAT( + m->entry_computation()->root_instruction(), + GmockMatch(m::MultiplyAnyOrder( + m::AddAnyOrder(m::Parameter(0), m::Parameter(1)), m::Parameter(2)))); +} + +// A*C + B*C => (A+B)*C if C is a floating-point power of 2. +TEST_F(AlgebraicSimplifierTest, FactorFpAddition) { + const char* kModuleStr = R"( + HloModule m + test { + p0 = f32[] parameter(0) + p1 = f32[] parameter(1) + c = f32[] constant(0.125) + x = f32[] multiply(p0, c) + y = f32[] multiply(p1, c) + ROOT sum = f32[] add(x, y) + } + )"; + TF_ASSERT_OK_AND_ASSIGN(auto m, ParseAndReturnVerifiedModule(kModuleStr)); + ASSERT_TRUE(AlgebraicSimplifier(default_options_).Run(m.get()).ValueOrDie()); + EXPECT_THAT(m->entry_computation()->root_instruction(), + GmockMatch(m::MultiplyAnyOrder( + m::AddAnyOrder(m::Parameter(0), m::Parameter(1)), + m::ConstantScalar(0.125)))); +} + +// A*C + B*C => (A+B)*C if C is a broadcast of a floating-point power of 2. +TEST_F(AlgebraicSimplifierTest, FactorFpAdditionWithBroadcast) { + const char* kModuleStr = R"( + HloModule m + test { + p0 = f32[4] parameter(0) + p1 = f32[4] parameter(1) + c = f32[] constant(0.125) + b = f32[4] broadcast(c), dimensions={} + x = f32[4] multiply(p0, b) + y = f32[4] multiply(p1, b) + ROOT sum = f32[4] add(x, y) + } + )"; + TF_ASSERT_OK_AND_ASSIGN(auto m, ParseAndReturnVerifiedModule(kModuleStr)); + ASSERT_TRUE(AlgebraicSimplifier(default_options_).Run(m.get()).ValueOrDie()); + EXPECT_THAT(m->entry_computation()->root_instruction(), + GmockMatch(m::MultiplyAnyOrder( + m::AddAnyOrder(m::Parameter(0), m::Parameter(1)), + m::Broadcast(m::ConstantScalar(0.125))))); +} + +// A*C + B*C => (A+B)*C simplification should not happen if C is not a +// floating-point power of 2. +TEST_F(AlgebraicSimplifierTest, FactorFpAdditionNotPowerOf2) { + const char* kModuleStr = R"( + HloModule m + test { + p0 = f32[] parameter(0) + p1 = f32[] parameter(1) + c = f32[] constant(0.3) + x = f32[] multiply(p0, c) + y = f32[] multiply(p1, c) + ROOT sum = f32[] add(x, y) + } + )"; + TF_ASSERT_OK_AND_ASSIGN(auto m, ParseAndReturnVerifiedModule(kModuleStr)); + EXPECT_FALSE(AlgebraicSimplifier(default_options_).Run(m.get()).ValueOrDie()); +} + +// A*C + B*C => (A+B)*C simplification should not happen if A, B, and C are +// complex numbers. +TEST_F(AlgebraicSimplifierTest, FactorFpAdditionComplex) { + const char* kModuleStr = R"( + HloModule m + test { + p0 = c64[8] parameter(0) + p1 = c64[8] parameter(1) + p2 = c64[8] parameter(2) + x = c64[8] multiply(p0, p2) + y = c64[8] multiply(p1, p2) + ROOT sum = c64[8] add(x, y) + } + )"; + TF_ASSERT_OK_AND_ASSIGN(auto m, ParseAndReturnVerifiedModule(kModuleStr)); + EXPECT_FALSE(AlgebraicSimplifier(default_options_).Run(m.get()).ValueOrDie()); +} + +// A*C + B*C => (A+B)*C simplification is OK if A, B, and C are complex. +TEST_F(AlgebraicSimplifierTest, FactorFpAdditionBfloat16) { + const char* kModuleStr = R"( + HloModule m + test { + p0 = bf16[4] parameter(0) + p1 = bf16[4] parameter(1) + c = bf16[] constant(0.125) + b = bf16[4] broadcast(c), dimensions={} + x = bf16[4] multiply(p0, b) + y = bf16[4] multiply(p1, b) + ROOT sum = bf16[4] add(x, y) + } + )"; + TF_ASSERT_OK_AND_ASSIGN(auto m, ParseAndReturnVerifiedModule(kModuleStr)); + ASSERT_TRUE(AlgebraicSimplifier(default_options_).Run(m.get()).ValueOrDie()); + EXPECT_THAT(m->entry_computation()->root_instruction(), + GmockMatch(m::MultiplyAnyOrder( + m::AddAnyOrder(m::Parameter(0), m::Parameter(1)), + m::Broadcast(m::ConstantScalar(0.125))))); +} + // Test that A * 0 is simplified to 0 TEST_F(AlgebraicSimplifierTest, MulZero) { auto m = CreateNewVerifiedModule(); @@ -92,8 +217,7 @@ TEST_F(AlgebraicSimplifierTest, MulZero) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kMultiply); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_EQ(computation->root_instruction(), zero); } @@ -115,8 +239,7 @@ TEST_F(AlgebraicSimplifierTest, SelectTrue) { auto computation = module->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kSelect); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); EXPECT_EQ(computation->root_instruction(), param0); } @@ -138,8 +261,7 @@ TEST_F(AlgebraicSimplifierTest, SelectFalse) { auto computation = module->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kSelect); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); EXPECT_EQ(computation->root_instruction(), param1); } @@ -159,8 +281,7 @@ TEST_F(AlgebraicSimplifierTest, SelectIdentical) { auto computation = module->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kSelect); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); EXPECT_EQ(computation->root_instruction(), param1); } @@ -196,11 +317,10 @@ TEST_F(AlgebraicSimplifierTest, TwoReducesToOne) { builder.AddInstruction(HloInstruction::CreateReduce(r1f32, reduce0, zero, dims1, add_computation)); m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); HloInstruction* root = m->entry_computation()->root_instruction(); - EXPECT_THAT(root, op::Reduce(param, zero)); + EXPECT_THAT(root, GmockMatch(m::Reduce(m::Parameter(0), m::Op().Is(zero)))); EXPECT_EQ(root->dimensions(), std::vector({0, 2, 3})); } @@ -219,11 +339,10 @@ TEST_F(AlgebraicSimplifierTest, AddConstOnLHS) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kAdd); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Add(param0, op::Constant())); + EXPECT_THAT(root, GmockMatch(m::Add(m::Parameter(0), m::Constant()))); } // Test that [(A + C1) + C2] => [A + (C1 + C2)] for constants C1 and C2. @@ -246,11 +365,12 @@ TEST_F(AlgebraicSimplifierTest, AddReassociateMergeConstants) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kAdd); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Add(param0, op::Add(constant1, constant2))); + EXPECT_THAT(root, GmockMatch(m::Add( + m::Op().Is(param0), + m::Add(m::Op().Is(constant1), m::Op().Is(constant2))))); } TEST_F(AlgebraicSimplifierTest, AddBroadcastZeroR0Operand) { @@ -269,8 +389,7 @@ TEST_F(AlgebraicSimplifierTest, AddBroadcastZeroR0Operand) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kAdd); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -306,11 +425,11 @@ TEST_F(AlgebraicSimplifierTest, InlineTrivialMap) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kMap); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Add(param0, op::Broadcast(zero))); + EXPECT_THAT(root, GmockMatch(m::Add(m::Parameter(0), + m::Broadcast(m::Op().Is(zero))))); } TEST_F(AlgebraicSimplifierTest, AddBroadcastZeroR1Operand) { @@ -329,8 +448,7 @@ TEST_F(AlgebraicSimplifierTest, AddBroadcastZeroR1Operand) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kAdd); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -344,12 +462,11 @@ TEST_F(AlgebraicSimplifierTest, ConstantToBroadcast) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); - EXPECT_THAT(root, op::Constant()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + EXPECT_THAT(root, GmockMatch(m::Constant())); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Broadcast(op::Constant())); + EXPECT_THAT(root, GmockMatch(m::Broadcast(m::Constant()))); EXPECT_EQ(3.14f, root->operand(0)->literal().GetFirstElement()); } @@ -361,12 +478,11 @@ TEST_F(AlgebraicSimplifierTest, ConstantNotToBroadcast) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); - EXPECT_THAT(root, op::Constant()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + EXPECT_THAT(root, GmockMatch(m::Constant())); + AlgebraicSimplifier simplifier(default_options_); ASSERT_FALSE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Constant()); + EXPECT_THAT(root, GmockMatch(m::Constant())); } TEST_F(AlgebraicSimplifierTest, IotaToBroadcast) { @@ -377,12 +493,11 @@ TEST_F(AlgebraicSimplifierTest, IotaToBroadcast) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); - EXPECT_THAT(root, op::Constant()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + EXPECT_THAT(root, GmockMatch(m::Constant())); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Iota()); + EXPECT_THAT(root, GmockMatch(m::Iota())); } // Test that A - 0 is simplified to A @@ -400,8 +515,7 @@ TEST_F(AlgebraicSimplifierTest, SubZero) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kSubtract); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -422,11 +536,11 @@ TEST_F(AlgebraicSimplifierTest, SubConstCanonicalization) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kSubtract); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Add(param0, op::Negate(constant))); + EXPECT_THAT(root, GmockMatch(m::Add(m::Parameter(0), + m::Negate(m::Op().Is(constant))))); } // Test that (A/B)/C is simplified to A/(B*C). @@ -448,14 +562,16 @@ TEST_F(AlgebraicSimplifierTest, LhsDivOfDiv) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Divide(op::Divide(param0, param1), param2)); + GmockMatch(m::Divide(m::Divide(m::Parameter(0), m::Parameter(1)), + m::Parameter(2)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), - op::Divide(param0, op::Multiply(param1, param2))); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Divide(m::Parameter(0), + m::Multiply(m::Parameter(1), m::Parameter(2))))); } // Test that A/(B/C) is simplified to (A*C)/B. @@ -476,15 +592,18 @@ TEST_F(AlgebraicSimplifierTest, RhsDivOfDiv) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), - op::Divide(param0, op::Divide(param1, param2))); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Divide(m::Parameter(0), + m::Divide(m::Parameter(1), m::Parameter(2))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), - op::Divide(op::Multiply(param0, param2), param1)); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Divide(m::Multiply(m::Parameter(0), m::Parameter(2)), + m::Parameter(1)))); } // Test that (A/B)/(C/D) is simplified to (A*D)/(B*C). @@ -511,15 +630,16 @@ TEST_F(AlgebraicSimplifierTest, DivOfDivAndDiv) { EXPECT_THAT( computation->root_instruction(), - op::Divide(op::Divide(param0, param1), op::Divide(param2, param3))); + GmockMatch(m::Divide(m::Divide(m::Parameter(0), m::Parameter(1)), + m::Divide(m::Parameter(2), m::Parameter(3))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT( computation->root_instruction(), - op::Divide(op::Multiply(param0, param3), op::Multiply(param1, param2))); + GmockMatch(m::Divide(m::Multiply(m::Parameter(0), m::Parameter(3)), + m::Multiply(m::Parameter(1), m::Parameter(2))))); } // Test that A/exp(B) is simplified to A*exp(-B). @@ -539,14 +659,14 @@ TEST_F(AlgebraicSimplifierTest, DivOfExp) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Divide(param0, op::Exp(param1))); + GmockMatch(m::Divide(m::Parameter(0), m::Exp(m::Parameter(1))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::Multiply(param0, op::Exp(op::Negate(param1)))); + GmockMatch(m::Multiply(m::Parameter(0), + m::Exp(m::Negate(m::Parameter(1)))))); } // Test that A/pow(B,C) is simplified to A*pow(B,-C). @@ -567,15 +687,18 @@ TEST_F(AlgebraicSimplifierTest, DivOfPower) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), - op::Divide(param0, op::Power(param1, param2))); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Divide(m::Parameter(0), + m::Power(m::Parameter(1), m::Parameter(2))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::Multiply(param0, op::Power(param1, op::Negate(param2)))); + GmockMatch(m::Multiply( + m::Parameter(0), + m::Power(m::Parameter(1), m::Negate(m::Parameter(2)))))); } // Test that broadcasting is done on the right step when simplifying A/pow(B,C) @@ -597,15 +720,18 @@ TEST_F(AlgebraicSimplifierTest, DivOfBroadcastingPower) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), - op::Divide(param0, op::Power(param1, param2))); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Divide(m::Parameter(0), + m::Power(m::Parameter(1), m::Parameter(2))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); ASSERT_THAT(computation->root_instruction(), - op::Multiply(param0, op::Power(param1, op::Negate(param2)))); + GmockMatch(m::Multiply( + m::Parameter(0), + m::Power(m::Parameter(1), m::Negate(m::Parameter(2)))))); } // A / Const => A * InvertedConst @@ -623,12 +749,11 @@ TEST_F(AlgebraicSimplifierTest, DivideByConstant) { auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::Multiply(param0, op::Constant())); + GmockMatch(m::Multiply(m::Parameter(0), m::Constant()))); } // pow(pow(A, X), Y) => pow(A, X*Y) @@ -648,11 +773,12 @@ TEST_F(AlgebraicSimplifierTest, PowerOfPower) { inner_power, exp2)); auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), - op::Power(base, op::Multiply(exp1, exp2))); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Power(m::Op().Is(base), + m::Multiply(m::Op().Is(exp1), m::Op().Is(exp2))))); } // Don't simplify pow(pow(A, X), Y) => pow(A, X*Y) if X and Y are complex @@ -673,8 +799,7 @@ TEST_F(AlgebraicSimplifierTest, PowerOfPowerComplex) { inner_power, exp2)); m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_FALSE(simplifier.Run(m.get()).ValueOrDie()); } @@ -693,8 +818,7 @@ TEST_F(AlgebraicSimplifierTest, DivOneScalar) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root, div); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -715,8 +839,7 @@ TEST_F(AlgebraicSimplifierTest, DivOneArray) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root, div); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -740,8 +863,7 @@ TEST_F(AlgebraicSimplifierTest, ComplexOfRealImagC) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root, cplx); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -765,8 +887,7 @@ TEST_F(AlgebraicSimplifierTest, RealOfComplex) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root, real); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -790,8 +911,7 @@ TEST_F(AlgebraicSimplifierTest, ImagOfComplex) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root, imag); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param1); @@ -818,11 +938,10 @@ TEST_F(AlgebraicSimplifierTest, SelectMakeTuple) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root, add); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Add(param1, param2)); + EXPECT_THAT(root, GmockMatch(m::Add(m::Parameter(1), m::Parameter(2)))); } // Test that exp(A)/exp(B) is simplified to exp(A-B) @@ -843,15 +962,16 @@ TEST_F(AlgebraicSimplifierTest, ExpDiv) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), - op::Divide(op::Exp(param0), op::Exp(param1))); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Divide(m::Exp(m::Parameter(0)), m::Exp(m::Parameter(1))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), - op::Exp(op::Subtract(param0, param1))); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Exp(m::Subtract(m::Parameter(0), m::Parameter(1))))); } // Test that exp(A)*exp(B) is simplified to exp(A+B) @@ -873,14 +993,14 @@ TEST_F(AlgebraicSimplifierTest, ExpMul) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Multiply(op::Exp(param0), op::Exp(param1))); + GmockMatch(m::Multiply(m::Exp(m::Parameter(0)), + m::Exp(m::Parameter(1))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::Exp(op::Add(param0, param1))); + GmockMatch(m::Exp(m::Add(m::Parameter(0), m::Parameter(1))))); } // Test that pow(exp(A), B) is simplified to exp(A*B) @@ -900,14 +1020,14 @@ TEST_F(AlgebraicSimplifierTest, PowExp) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Power(op::Exp(param0), param1)); + GmockMatch(m::Power(m::Exp(m::Parameter(0)), m::Parameter(1)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), - op::Exp(op::Multiply(param0, param1))); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Exp(m::Multiply(m::Parameter(0), m::Parameter(1))))); } // Test that ln(pow(A, B)) is simplified to ln(A)*B @@ -927,14 +1047,14 @@ TEST_F(AlgebraicSimplifierTest, LnPow) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Log(op::Power(param0, param1))); + GmockMatch(m::Log(m::Power(m::Parameter(0), m::Parameter(1))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), - op::Multiply(op::Log(param0), param1)); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Multiply(m::Log(m::Parameter(0)), m::Parameter(1)))); } // Test that ln(exp(A)) is simplified to A @@ -951,10 +1071,10 @@ TEST_F(AlgebraicSimplifierTest, LnExp) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Log(op::Exp(param0))); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Log(m::Exp(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_EQ(computation->root_instruction(), param0); @@ -981,13 +1101,14 @@ TEST_F(AlgebraicSimplifierTest, LnExpDiv) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Log(op::Divide(op::Exp(param0), op::Exp(param1)))); + GmockMatch(m::Log(m::Divide(m::Exp(m::Parameter(0)), + m::Exp(m::Parameter(1)))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Subtract(param0, param1)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Subtract(m::Parameter(0), m::Parameter(1)))); } // Test that pow(A, 0) where A is a scalar is simplified to the scalar @@ -1005,14 +1126,14 @@ TEST_F(AlgebraicSimplifierTest, Pow0Scalar) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Power(param0, zero)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Power(m::Parameter(0), m::Op().Is(zero)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); HloInstruction* root = computation->root_instruction(); - EXPECT_THAT(root, op::Constant()); + EXPECT_THAT(root, GmockMatch(m::Constant())); EXPECT_EQ(root->literal().GetFirstElement(), 1); } @@ -1030,14 +1151,14 @@ TEST_F(AlgebraicSimplifierTest, Pow0Vector) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Power(param0, zero)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Power(m::Parameter(0), m::Op().Is(zero)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); HloInstruction* root = computation->root_instruction(); - EXPECT_THAT(root, op::Broadcast()); + EXPECT_THAT(root, GmockMatch(m::Broadcast())); EXPECT_TRUE(ShapeUtil::Equal(root->shape(), r1f32)) << ShapeUtil::HumanString(root->shape()); EXPECT_EQ(root->dimensions().size(), 0); @@ -1059,10 +1180,10 @@ TEST_F(AlgebraicSimplifierTest, Pow1) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Power(param0, one)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Power(m::Parameter(0), m::Op().Is(one)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_EQ(computation->root_instruction(), param0); @@ -1082,13 +1203,14 @@ TEST_F(AlgebraicSimplifierTest, Pow2) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Power(param0, two)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Power(m::Parameter(0), m::Op().Is(two)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Multiply(param0, param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Multiply(m::Parameter(0), m::Parameter(0)))); } // Test that pow(A, -1) is simplified to 1/A. @@ -1105,14 +1227,14 @@ TEST_F(AlgebraicSimplifierTest, PowNegative1) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Power(param0, negative_one)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Power(m::Parameter(0), m::Op().Is(negative_one)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); HloInstruction* root = computation->root_instruction(); - EXPECT_THAT(root, op::Divide(op::Broadcast(), param0)); + EXPECT_THAT(root, GmockMatch(m::Divide(m::Broadcast(), m::Parameter(0)))); EXPECT_EQ(root->operand(0)->opcode(), HloOpcode::kBroadcast); EXPECT_EQ(root->operand(0)->operand(0)->literal().GetFirstElement(), 1); @@ -1153,13 +1275,12 @@ TEST_F(AlgebraicSimplifierTest, ZeroSizedConvolution) { ShapeUtil::MakeShape(F32, {3, 3, 3}), lhs, rhs, /*feature_group_count=*/1, window, dnums, DefaultPrecisionConfig(2))); m->AddEntryComputation(builder.Build()); - HloPassFix simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + HloPassFix simplifier(default_options_); EXPECT_THAT(m->entry_computation()->root_instruction(), - op::Convolution(lhs, rhs)); + GmockMatch(m::Convolution(m::Op().Is(lhs), m::Op().Is(rhs)))); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(m->entry_computation()->root_instruction(), - op::Broadcast(op::Constant())); + GmockMatch(m::Broadcast(m::Constant()))); } TEST_F(AlgebraicSimplifierTest, ZeroSizedReduceWindow) { @@ -1196,13 +1317,12 @@ TEST_F(AlgebraicSimplifierTest, ZeroSizedReduceWindow) { HloInstruction::CreateConstant(LiteralUtil::CreateR0(0.0f))), window, add_computation)); m->AddEntryComputation(builder.Build()); - HloPassFix simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + HloPassFix simplifier(default_options_); EXPECT_THAT(m->entry_computation()->root_instruction(), - op::ReduceWindow(param, op::Constant())); + GmockMatch(m::ReduceWindow(m::Parameter(0), m::Constant()))); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(m->entry_computation()->root_instruction(), - op::Broadcast(op::Constant())); + GmockMatch(m::Broadcast(m::Constant()))); } TEST_F(AlgebraicSimplifierTest, ZeroSizedPad) { @@ -1225,12 +1345,11 @@ TEST_F(AlgebraicSimplifierTest, ZeroSizedPad) { padding)); m->AddEntryComputation(builder.Build()); EXPECT_THAT(m->entry_computation()->root_instruction(), - op::Pad(param, op::Constant())); - HloPassFix simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + GmockMatch(m::Pad(m::Parameter(0), m::Constant()))); + HloPassFix simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(m->entry_computation()->root_instruction(), - op::Broadcast(op::Constant())); + GmockMatch(m::Broadcast(m::Constant()))); } TEST_F(AlgebraicSimplifierTest, ReshapeBroadcast) { @@ -1251,10 +1370,9 @@ TEST_F(AlgebraicSimplifierTest, ReshapeBroadcast) { m->AddEntryComputation(std::move(computation)); EXPECT_THAT(m->entry_computation()->root_instruction(), - op::Reshape(op::Broadcast(op::Reshape(op)))); + GmockMatch(m::Reshape(m::Broadcast(m::Reshape(m::Op().Is(op)))))); - HloPassFix simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + HloPassFix simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(m->entry_computation()->root_instruction(), op); @@ -1271,10 +1389,10 @@ TEST_F(AlgebraicSimplifierTest, ConvertBetweenSameType) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Convert(input)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Convert(m::Op().Is(input)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), input); @@ -1292,10 +1410,10 @@ TEST_F(AlgebraicSimplifierTest, RemoveCopy) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Copy(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Copy(m::Parameter(0)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), param0); @@ -1314,19 +1432,24 @@ TEST_F(AlgebraicSimplifierTest, CopyEqualsBitcast) { *copy->mutable_shape()->mutable_layout() = LayoutUtil::MakeLayout({1, 2, 0, 3}); auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Copy(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Copy(m::Parameter(0)))); - AlgebraicSimplifier simplifier1(/*is_layout_sensitive=*/true, - non_bitcasting_callback()); + AlgebraicSimplifierOptions options(non_bitcasting_callback()); + options.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier1(options); ASSERT_FALSE(simplifier1.Run(m.get()).ValueOrDie()); // Verify that the copy is not replaced. - EXPECT_THAT(computation->root_instruction(), op::Copy(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Copy(m::Parameter(0)))); - AlgebraicSimplifier simplifier2(/*is_layout_sensitive=*/true, - bitcasting_callback()); + AlgebraicSimplifierOptions options2(bitcasting_callback()); + options2.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier2(options2); ASSERT_TRUE(simplifier2.Run(m.get()).ValueOrDie()); // Verify that the copy is replaced. - EXPECT_THAT(computation->root_instruction(), op::Bitcast(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Bitcast(m::Parameter(0)))); } // Test that unary concatenates are removed. @@ -1341,10 +1464,10 @@ TEST_F(AlgebraicSimplifierTest, RemoveUnaryConcatenate) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Concatenate(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Concatenate(m::Parameter(0)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), param0); @@ -1371,16 +1494,17 @@ TEST_F(AlgebraicSimplifierTest, RemoveEmptyConcatenateOperands) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT( - computation->root_instruction(), - op::Concatenate(empty_literal, param0, param0, empty_slice, param1)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Concatenate( + m::Op().Is(empty_literal), m::Parameter(0), m::Parameter(0), + m::Op().Is(empty_slice), m::Parameter(1)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::Concatenate(param0, param0, param1)); + GmockMatch(m::Concatenate(m::Parameter(0), m::Parameter(0), + m::Parameter(1)))); } // Test that reduce of concat is simplified. @@ -1423,14 +1547,14 @@ TEST_F(AlgebraicSimplifierTest, SimplifyReduceOfConcat) { auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT( computation->root_instruction(), - op::Map(op::Map(op::Reduce(param0, zero), op::Reduce(param1, zero)), - op::Reduce(param2, zero))); + GmockMatch(m::Map(m::Map(m::Reduce(m::Parameter(0), m::Op().Is(zero)), + m::Reduce(m::Parameter(1), m::Op().Is(zero))), + m::Reduce(m::Parameter(2), m::Op().Is(zero))))); } // Test a concatenate with only empty operands is removed. @@ -1453,10 +1577,10 @@ TEST_F(AlgebraicSimplifierTest, OnlyEmptyConcatenateOperands) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Concatenate(empty_literal, empty_slice)); + GmockMatch(m::Concatenate(m::Op().Is(empty_literal), + m::Op().Is(empty_slice)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_EQ(computation->root_instruction(), empty_literal); @@ -1479,10 +1603,80 @@ TEST_F(AlgebraicSimplifierTest, ConcatenateOfBroadcastBecomesPad) { auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Pad(param0, param1)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Pad(m::Parameter(0), m::Parameter(1)))); +} + +TEST_F(AlgebraicSimplifierTest, SimplifyConcatenateOfSlices) { + auto m = CreateNewVerifiedModule(); + Shape r2f32 = ShapeUtil::MakeShape(F32, {100, 99}); + Shape concat_shape = ShapeUtil::MakeShape(F32, {50, 80}); + HloComputation::Builder builder(TestName()); + HloInstruction* param0 = builder.AddInstruction( + HloInstruction::CreateParameter(0, r2f32, "param0")); + HloInstruction* param1 = builder.AddInstruction( + HloInstruction::CreateParameter(1, r2f32, "param1")); + + HloInstruction* slice0 = builder.AddInstruction(HloInstruction::CreateSlice( + ShapeUtil::MakeShape(F32, {50, 10}), param0, /*start_indices=*/{0, 0}, + /*limit_indices=*/{50, 10}, /*strides=*/{1, 1})); + + // Cannot merge 'slice0' and 'slice1' because of different start indices in + // dimension 0. + HloInstruction* slice1 = builder.AddInstruction(HloInstruction::CreateSlice( + ShapeUtil::MakeShape(F32, {50, 10}), param0, /*start_indices=*/{50, 10}, + /*limit_indices=*/{100, 20}, /*strides=*/{1, 1})); + + // Cannot merge 'slice1' and 'slice2' because of stride in dimension 2. + HloInstruction* slice2 = builder.AddInstruction(HloInstruction::CreateSlice( + ShapeUtil::MakeShape(F32, {50, 10}), param0, /*start_indices=*/{50, 20}, + /*limit_indices=*/{100, 40}, /*strides=*/{1, 2})); + + // Cannot merge 'slice2' and 'slice3' because of stride in dimension 2. + HloInstruction* slice3 = builder.AddInstruction(HloInstruction::CreateSlice( + ShapeUtil::MakeShape(F32, {50, 10}), param0, /*start_indices=*/{50, 40}, + /*limit_indices=*/{100, 50}, /*strides=*/{1, 1})); + + // Can merge 'slice3' and 'slice4'. + HloInstruction* slice4 = builder.AddInstruction(HloInstruction::CreateSlice( + ShapeUtil::MakeShape(F32, {50, 10}), param0, /*start_indices=*/{50, 50}, + /*limit_indices=*/{100, 60}, /*strides=*/{1, 1})); + + // Can merge 'slice4' and 'slice5'. + HloInstruction* slice5 = builder.AddInstruction(HloInstruction::CreateSlice( + ShapeUtil::MakeShape(F32, {50, 10}), param0, /*start_indices=*/{50, 60}, + /*limit_indices=*/{100, 70}, /*strides=*/{1, 1})); + + // Cannot merge 'slice5' and 'slice6' because of overlap. + HloInstruction* slice6 = builder.AddInstruction(HloInstruction::CreateSlice( + ShapeUtil::MakeShape(F32, {50, 10}), param0, /*start_indices=*/{50, 69}, + /*limit_indices=*/{100, 79}, /*strides=*/{1, 1})); + + // Cannot merge 'slice6' and 'slice7' because of slicing from a different + // parameter. + HloInstruction* slice7 = builder.AddInstruction(HloInstruction::CreateSlice( + ShapeUtil::MakeShape(F32, {50, 10}), param1, /*start_indices=*/{50, 79}, + /*limit_indices=*/{100, 89}, /*strides=*/{1, 1})); + + builder.AddInstruction(HloInstruction::CreateConcatenate( + concat_shape, + {slice0, slice1, slice2, slice3, slice4, slice5, slice6, slice7}, 1)); + auto computation = m->AddEntryComputation(builder.Build()); + + AlgebraicSimplifier simplifier(default_options_); + ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); + auto s = m::Slice(m::Parameter(0)); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Concatenate(s, s, s, s, s, m::Slice(m::Parameter(1))))); + // The operand 3 should be a merge of 'slice3', 'slice4' and 'slice5', so its + // shape should have dimensions {50, 30}. + EXPECT_TRUE( + ShapeUtil::Equal(computation->root_instruction()->operand(3)->shape(), + ShapeUtil::MakeShape(F32, {50, 30}))); + EXPECT_EQ(computation->root_instruction()->operand(3)->slice_starts(1), 40); } // Test that a simplification which changes layouts is not performed if layout @@ -1502,14 +1696,17 @@ TEST_F(AlgebraicSimplifierTest, CopyWithDifferentLayout) { *param0->mutable_shape()->mutable_layout() = LayoutUtil::MakeLayout({0, 1}); *copy->mutable_shape()->mutable_layout() = LayoutUtil::MakeLayout({1, 0}); - EXPECT_THAT(computation->root_instruction(), op::Copy(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Copy(m::Parameter(0)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/true, - non_bitcasting_callback()); + AlgebraicSimplifierOptions options(non_bitcasting_callback()); + options.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier(options); EXPECT_FALSE(simplifier.Run(m.get()).ValueOrDie()); // Copy has not been removed. - EXPECT_THAT(computation->root_instruction(), op::Copy(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Copy(m::Parameter(0)))); } // Test that a simplification which preserves layouts is performed if layout @@ -1529,10 +1726,12 @@ TEST_F(AlgebraicSimplifierTest, CopyWithSameLayout) { *param0->mutable_shape()->mutable_layout() = LayoutUtil::MakeLayout({0, 1}); *copy->mutable_shape()->mutable_layout() = LayoutUtil::MakeLayout({0, 1}); - EXPECT_THAT(computation->root_instruction(), op::Copy(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Copy(m::Parameter(0)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/true, - non_bitcasting_callback()); + AlgebraicSimplifierOptions options(non_bitcasting_callback()); + options.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier(options); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); // Copy has been removed. @@ -1557,14 +1756,17 @@ TEST_F(AlgebraicSimplifierTest, NoBitcastAdded) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Parameter(0)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/true, - non_bitcasting_callback()); + AlgebraicSimplifierOptions options(non_bitcasting_callback()); + options.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier(options); EXPECT_FALSE(simplifier.Run(m.get()).ValueOrDie()); // Reshape is not replaced with a bitcast. - EXPECT_THAT(computation->root_instruction(), op::Reshape(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Parameter(0)))); } // Test transforming reshapes and transposes of rng. @@ -1588,13 +1790,13 @@ TEST_F(AlgebraicSimplifierTest, ReshapeOfTransposeOfRngToRng) { auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifier simplifier( + (AlgebraicSimplifierOptions(bitcasting_callback()))); EXPECT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - // Verify that that reshape(transpose(rng)) is replace by a single rng of the + // Verify that reshape(transpose(rng)) is replace by a single rng of the // same shape as the reshape. - EXPECT_THAT(computation->root_instruction(), op::Rng()); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Rng())); EXPECT_TRUE(ShapeUtil::Equal(computation->root_instruction()->shape(), reshape_shape)); } @@ -1636,17 +1838,20 @@ TEST_F(AlgebraicSimplifierTest, ReshapeReplacedWithBitcast) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Tuple(transformable_reshape, dimensions_wrong_reshape, - layout_wrong_reshape)); + GmockMatch(m::Tuple(m::Op().Is(transformable_reshape), + m::Op().Is(dimensions_wrong_reshape), + m::Op().Is(layout_wrong_reshape)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/true, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + options.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier(options); simplifier.Run(m.get()).ValueOrDie(); // Verify that only the first reshape is replaced. EXPECT_THAT( computation->root_instruction(), - op::Tuple(op::Bitcast(), dimensions_wrong_reshape, layout_wrong_reshape)); + GmockMatch(m::Tuple(m::Bitcast(), m::Op().Is(dimensions_wrong_reshape), + m::Op().Is(layout_wrong_reshape)))); } // Regression test for a bug where if we failed to sink a reshape, we'd set the @@ -1667,8 +1872,8 @@ TEST_F(AlgebraicSimplifierTest, FailureToSinkReshapeDoesntAffectChangedBit) { builder.AddInstruction( HloInstruction::CreateReshape(ShapeUtil::MakeShape(F32, {4}), add)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifier simplifier( + (AlgebraicSimplifierOptions(bitcasting_callback()))); m->AddEntryComputation(builder.Build()); EXPECT_TRUE(simplifier.Run(m.get()).ValueOrDie()); } @@ -1692,8 +1897,8 @@ TEST_F(AlgebraicSimplifierTest, FailureToSinkBroadcastDoesntAffectChangedBit) { HloInstruction::CreateBroadcast(ShapeUtil::MakeShape(F32, {2, 2, 2}), add, /*broadcast_dimensions=*/{0, 1})); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifier simplifier( + (AlgebraicSimplifierOptions(bitcasting_callback()))); m->AddEntryComputation(builder.Build()); EXPECT_TRUE(simplifier.Run(m.get()).ValueOrDie()); } @@ -1715,14 +1920,17 @@ TEST_F(AlgebraicSimplifierTest, TransposeEqualsBitcast1) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Transpose(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Transpose(m::Parameter(0)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/true, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + options.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier(options); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); // Verify that the reshape is replaced. - EXPECT_THAT(computation->root_instruction(), op::Bitcast(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Bitcast(m::Parameter(0)))); } TEST_F(AlgebraicSimplifierTest, TransposeEqualsBitcast2) { @@ -1742,14 +1950,17 @@ TEST_F(AlgebraicSimplifierTest, TransposeEqualsBitcast2) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Transpose(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Transpose(m::Parameter(0)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/true, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + options.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier(options); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); // Verify that the reshape is replaced. - EXPECT_THAT(computation->root_instruction(), op::Bitcast(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Bitcast(m::Parameter(0)))); } TEST_F(AlgebraicSimplifierTest, ReshapesMerged) { @@ -1769,13 +1980,13 @@ TEST_F(AlgebraicSimplifierTest, ReshapesMerged) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Reshape(op::Reshape(param0))); + GmockMatch(m::Reshape(m::Reshape(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Parameter(0)))); } TEST_F(AlgebraicSimplifierTest, CopiesMerged) { @@ -1796,13 +2007,16 @@ TEST_F(AlgebraicSimplifierTest, CopiesMerged) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Copy(op::Copy(param0))); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Copy(m::Copy(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/true, - non_bitcasting_callback()); + AlgebraicSimplifierOptions options(non_bitcasting_callback()); + options.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier(options); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Copy(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Copy(m::Parameter(0)))); } TEST_F(AlgebraicSimplifierTest, TransposesMerged) { @@ -1821,13 +2035,14 @@ TEST_F(AlgebraicSimplifierTest, TransposesMerged) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Transpose(transpose1)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Transpose(m::Op().Is(transpose1)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Transpose(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Transpose(m::Parameter(0)))); EXPECT_EQ(std::vector({2, 1, 0}), computation->root_instruction()->dimensions()); } @@ -1846,13 +2061,13 @@ TEST_F(AlgebraicSimplifierTest, ReshapeAndBroadcastMerged) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Broadcast(op::Reshape(param0))); + GmockMatch(m::Broadcast(m::Reshape(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Broadcast(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Broadcast(m::Parameter(0)))); } // Test merging broadcast and reshape. @@ -1869,13 +2084,13 @@ TEST_F(AlgebraicSimplifierTest, BroadcastAndReshapeMerged) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Reshape(op::Broadcast(param0))); + GmockMatch(m::Reshape(m::Broadcast(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Broadcast(param0)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Broadcast(m::Parameter(0)))); } TEST_F(AlgebraicSimplifierTest, BroadcastAndReshape_1_3x1_3) { @@ -1891,14 +2106,13 @@ TEST_F(AlgebraicSimplifierTest, BroadcastAndReshape_1_3x1_3) { auto computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Reshape(op::Broadcast(param))); + GmockMatch(m::Reshape(m::Broadcast(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); EXPECT_FALSE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::Reshape(op::Broadcast(param))); + GmockMatch(m::Reshape(m::Broadcast(m::Parameter(0))))); } TEST_F(AlgebraicSimplifierTest, BroadcastAndReshape_4_3x2x4_6x1x1x4) { @@ -1914,13 +2128,13 @@ TEST_F(AlgebraicSimplifierTest, BroadcastAndReshape_4_3x2x4_6x1x1x4) { HloComputation* computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Reshape(op::Broadcast(param))); + GmockMatch(m::Reshape(m::Broadcast(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Broadcast(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Broadcast(m::Parameter(0)))); EXPECT_THAT(computation->root_instruction()->dimensions(), ::testing::ElementsAre(3)); } @@ -1938,13 +2152,13 @@ TEST_F(AlgebraicSimplifierTest, BroadcastAndReshape_1_3x2x1_6x1x1x1) { HloComputation* computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Reshape(op::Broadcast(param))); + GmockMatch(m::Reshape(m::Broadcast(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Broadcast(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Broadcast(m::Parameter(0)))); const std::vector broadcast_dims = computation->root_instruction()->dimensions(); EXPECT_EQ(1, broadcast_dims.size()); @@ -1964,14 +2178,13 @@ TEST_F(AlgebraicSimplifierTest, BroadcastAndReshape_4_3x2x4x2_6x8) { HloComputation* computation = m->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->root_instruction(), - op::Reshape(op::Broadcast(param))); + GmockMatch(m::Reshape(m::Broadcast(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); EXPECT_FALSE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::Reshape(op::Broadcast(param))); + GmockMatch(m::Reshape(m::Broadcast(m::Parameter(0))))); } TEST_F(AlgebraicSimplifierTest, IotaAndReshapeMerged) { @@ -1984,13 +2197,13 @@ TEST_F(AlgebraicSimplifierTest, IotaAndReshapeMerged) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(op::Iota())); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Iota()))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Iota()); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Iota())); EXPECT_TRUE( ShapeUtil::Equal(computation->root_instruction()->shape(), result_shape)); } @@ -2004,14 +2217,13 @@ TEST_F(AlgebraicSimplifierTest, IotaEffectiveScalar) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Iota()); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Iota())); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); auto root = computation->root_instruction(); - EXPECT_THAT(root, op::Broadcast(op::Constant())); + EXPECT_THAT(root, GmockMatch(m::Broadcast(m::Constant()))); EXPECT_EQ(0.0f, root->operand(0)->literal().GetFirstElement()); EXPECT_TRUE( ShapeUtil::Equal(computation->root_instruction()->shape(), result_shape)); @@ -2027,13 +2239,14 @@ TEST_F(AlgebraicSimplifierTest, IotaAndReshape_1_3x2_6) { auto computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(op::Iota())); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Iota()))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); EXPECT_FALSE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(op::Iota())); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Iota()))); } TEST_F(AlgebraicSimplifierTest, IotaAndReshape_4_3x2x4_6x1x1x4) { @@ -2046,13 +2259,13 @@ TEST_F(AlgebraicSimplifierTest, IotaAndReshape_4_3x2x4_6x1x1x4) { HloComputation* computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(op::Iota())); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Iota()))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Iota()); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Iota())); EXPECT_EQ(Cast(computation->root_instruction()) ->iota_dimension(), 3); @@ -2068,13 +2281,13 @@ TEST_F(AlgebraicSimplifierTest, IotaAndReshape_1_3x2x2_6x1x1x2) { HloComputation* computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(op::Iota())); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Iota()))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Iota()); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Iota())); const int64 iota_dim = Cast(computation->root_instruction()) ->iota_dimension(); @@ -2091,13 +2304,14 @@ TEST_F(AlgebraicSimplifierTest, IotaAndReshape_4_3x2x4x2_6x8) { HloComputation* computation = m->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(op::Iota())); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Iota()))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); EXPECT_FALSE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(op::Iota())); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Iota()))); } TEST_F(AlgebraicSimplifierTest, RemoveNoopPad) { @@ -2120,10 +2334,10 @@ TEST_F(AlgebraicSimplifierTest, RemoveNoopPad) { auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Pad(param, zero)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Pad(m::Parameter(0), m::Op().Is(zero)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), param); @@ -2153,8 +2367,7 @@ TEST_F(AlgebraicSimplifierTest, NegativePadding) { auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); auto has_negative_padding = [](const HloInstruction* pad) { for (auto& padding_dimension : pad->padding_config().dimensions()) { @@ -2166,16 +2379,54 @@ TEST_F(AlgebraicSimplifierTest, NegativePadding) { return false; }; - EXPECT_THAT(computation->root_instruction(), op::Pad(param, zero)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Pad(m::Parameter(0), m::Op().Is(zero)))); EXPECT_TRUE(has_negative_padding(pad)); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Slice(op::Pad(param, zero))); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Slice(m::Pad(m::Parameter(0), m::Op().Is(zero))))); EXPECT_FALSE( has_negative_padding(computation->root_instruction()->operand(0))); } +TEST_F(AlgebraicSimplifierTest, TrivialInteriorPadding) { + // Verify that a pad instruction with interior padding on one-sized + // dimensions, removes the interior padding. + HloComputation::Builder builder(TestName()); + HloInstruction* param = + builder.AddInstruction(HloInstruction::CreateParameter( + 0, ShapeUtil::MakeShape(F32, {2, 1}), "param")); + HloInstruction* zero = builder.AddInstruction( + HloInstruction::CreateConstant(LiteralUtil::CreateR0(0.0f))); + PaddingConfig padding; + for (int i = 0; i < 2; ++i) { + auto dimension = padding.add_dimensions(); + dimension->set_edge_padding_low(3); + dimension->set_edge_padding_high(3); + dimension->set_interior_padding(i * 3); + } + HloInstruction* pad = builder.AddInstruction(HloInstruction::CreatePad( + ShapeUtil::MakeShape(F32, {8, 7}), param, zero, padding)); + + auto module = CreateNewVerifiedModule(); + HloComputation* computation = module->AddEntryComputation(builder.Build()); + + AlgebraicSimplifier simplifier(default_options_); + + ASSERT_THAT(computation->root_instruction(), + GmockMatch(m::Pad(m::Parameter(0), m::Op().Is(zero)))); + ASSERT_TRUE(HasInteriorPadding(pad->padding_config())); + + EXPECT_TRUE(simplifier.Run(module.get()).ValueOrDie()); + + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Pad(m::Parameter(0), m::Op().Is(zero)))); + EXPECT_FALSE( + HasInteriorPadding(computation->root_instruction()->padding_config())); +} + TEST_F(AlgebraicSimplifierTest, RemoveNoopReshape) { HloComputation::Builder builder(TestName()); HloInstruction* param = @@ -2187,10 +2438,10 @@ TEST_F(AlgebraicSimplifierTest, RemoveNoopReshape) { auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Parameter(0)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), param); @@ -2210,10 +2461,10 @@ TEST_F(AlgebraicSimplifierTest, RemoveNoopSlice) { auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Slice(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Slice(m::Parameter(0)))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), param); @@ -2239,13 +2490,14 @@ TEST_F(AlgebraicSimplifierTest, SliceOfSliceToSlice) { auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Slice(op::Slice(param))); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Slice(m::Slice(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Slice(param)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Slice(m::Parameter(0)))); EXPECT_EQ(computation->root_instruction()->slice_starts(0), 3); EXPECT_EQ(computation->root_instruction()->slice_starts(1), 5); EXPECT_EQ(computation->root_instruction()->slice_limits(0), dim0 - 2); @@ -2271,13 +2523,14 @@ TEST_F(AlgebraicSimplifierTest, SliceOfReshapeToReshapeOfSlice) { auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Slice(op::Reshape(param))); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Slice(m::Reshape(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Reshape(op::Slice(param))); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Reshape(m::Slice(m::Parameter(0))))); } TEST_F(AlgebraicSimplifierTest, SliceOfReshapeUnchanged) { @@ -2296,10 +2549,10 @@ TEST_F(AlgebraicSimplifierTest, SliceOfReshapeUnchanged) { auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Slice(op::Reshape(param))); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Slice(m::Reshape(m::Parameter(0))))); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_FALSE(simplifier.Run(module.get()).ValueOrDie()); } @@ -2312,12 +2565,84 @@ TEST_F(AlgebraicSimplifierTest, RemoveNoopSort) { builder.AddInstruction(HloInstruction::CreateSort(keys_shape, 0, keys)); auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), keys); } +TEST_F(AlgebraicSimplifierTest, ReplacePermutationSortWithScatter) { + const char* hlo_string = R"( + HloModule permutation_sort + + ENTRY sort_computation { + keys = f32[64,8732]{1,0} parameter(0) + values = s32[64,8732]{1,0} iota(), iota_dimension=1 + sort = (f32[64,8732]{1,0}, s32[64,8732]{1,0}) sort(keys, values), dimensions={1} + gte = s32[64,8732]{1,0} get-tuple-element(sort), index=1 + ROOT sort2 = (s32[64,8732]{1,0}, s32[64,8732]{1,0}) sort(gte, values), dimensions={1} + } + )"; + TF_ASSERT_OK_AND_ASSIGN(auto module, + ParseAndReturnVerifiedModule(hlo_string)); + + AlgebraicSimplifierOptions options(non_bitcasting_callback()); + options.set_enable_permutation_sort_replacement(true); + AlgebraicSimplifier simplifier(options); + EXPECT_TRUE(simplifier.Run(module.get()).ValueOrDie()); + auto root = module->entry_computation()->root_instruction(); + EXPECT_THAT(root, + GmockMatch(m::Tuple( + m::Iota(), + m::Scatter(m::Iota(), m::Concatenate(m::Iota(), m::Reshape()), + m::Reshape())))); +} + +TEST_F(AlgebraicSimplifierTest, DontReplacePermutationSortIfNonIntegral) { + // Same as ReplacePermutationSortWithScatter except that the iota has F32 + // type. + const char* hlo_string = R"( + HloModule permutation_sort + + ENTRY sort_computation { + keys = f32[64,8732]{1,0} parameter(0) + values = f32[64,8732]{1,0} iota(), iota_dimension=1 + sort = (f32[64,8732]{1,0}, f32[64,8732]{1,0}) sort(keys, values), dimensions={1} + gte = f32[64,8732]{1,0} get-tuple-element(sort), index=1 + ROOT sort2 = (f32[64,8732]{1,0}, f32[64,8732]{1,0}) sort(gte, values), dimensions={1} + } + )"; + TF_ASSERT_OK_AND_ASSIGN(auto module, + ParseAndReturnVerifiedModule(hlo_string)); + + AlgebraicSimplifierOptions options(non_bitcasting_callback()); + options.set_enable_permutation_sort_replacement(true); + AlgebraicSimplifier simplifier(options); + EXPECT_FALSE(simplifier.Run(module.get()).ValueOrDie()); +} + +TEST_F(AlgebraicSimplifierTest, DontReplacePermutationSortWrongDimensions) { + // Same as ReplacePermutationSortWithScatter except that the sort dimensions + // don't match. + const char* hlo_string = R"( + HloModule permutation_sort + + ENTRY sort_computation { + keys = f32[64,8732]{1,0} parameter(0) + values = s32[64,8732]{1,0} iota(), iota_dimension=1 + sort = (f32[64,8732]{1,0}, s32[64,8732]{1,0}) sort(keys, values), dimensions={1} + gte = s32[64,8732]{1,0} get-tuple-element(sort), index=1 + ROOT sort2 = (s32[64,8732]{1,0}, s32[64,8732]{1,0}) sort(gte, values), dimensions={0} + } + )"; + TF_ASSERT_OK_AND_ASSIGN(auto module, + ParseAndReturnVerifiedModule(hlo_string)); + + AlgebraicSimplifierOptions options(non_bitcasting_callback()); + options.set_enable_permutation_sort_replacement(true); + AlgebraicSimplifier simplifier(options); + EXPECT_FALSE(simplifier.Run(module.get()).ValueOrDie()); +} + TEST_F(AlgebraicSimplifierTest, ReplaceEffectiveScalarKeyValueSortWithTuple) { auto builder = HloComputation::Builder(TestName()); @@ -2334,11 +2659,11 @@ TEST_F(AlgebraicSimplifierTest, ReplaceEffectiveScalarKeyValueSortWithTuple) { keys, {values0, values1})); auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::Tuple(keys, values0, values1)); + GmockMatch(m::Tuple(m::Op().Is(keys), m::Op().Is(values0), + m::Op().Is(values1)))); } // Test that A && True is simplified to A @@ -2356,8 +2681,7 @@ TEST_F(AlgebraicSimplifierTest, AndTrue) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kAnd); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -2378,8 +2702,7 @@ TEST_F(AlgebraicSimplifierTest, AndTrue2) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kAnd); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -2400,8 +2723,7 @@ TEST_F(AlgebraicSimplifierTest, AndFalse) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kAnd); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, const_false); @@ -2422,8 +2744,7 @@ TEST_F(AlgebraicSimplifierTest, AndFalse2) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kAnd); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, const_false); @@ -2444,8 +2765,7 @@ TEST_F(AlgebraicSimplifierTest, OrTrue) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kOr); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, const_true); @@ -2466,8 +2786,7 @@ TEST_F(AlgebraicSimplifierTest, OrTrue2) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kOr); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, const_true); @@ -2488,8 +2807,7 @@ TEST_F(AlgebraicSimplifierTest, OrFalse) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kOr); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -2510,8 +2828,7 @@ TEST_F(AlgebraicSimplifierTest, OrFalse2) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kOr); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); EXPECT_EQ(root, param0); @@ -2641,15 +2958,15 @@ TEST_P(ConvInputPaddingTest, DoTest) { auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); if (testcase.expected_conv_window.empty()) { ASSERT_FALSE(simplifier.Run(module.get()).ValueOrDie()); } else { ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); auto* conv = module->entry_computation()->root_instruction(); SCOPED_TRACE(module->ToString()); - ASSERT_THAT(conv, op::Convolution(op::Parameter(), op::Parameter())); + ASSERT_THAT(conv, + GmockMatch(m::Convolution(m::Parameter(), m::Parameter()))); EXPECT_EQ(window_util::ToString(conv->window()), absl::StrCat("size=3x3 ", testcase.expected_conv_window)); } @@ -2759,15 +3076,15 @@ TEST_P(ConvFilterPaddingTest, DoIt) { auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); if (testcase.expected_conv_window.empty()) { ASSERT_FALSE(simplifier.Run(module.get()).ValueOrDie()); } else { ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); auto* conv = module->entry_computation()->root_instruction(); SCOPED_TRACE(module->ToString()); - ASSERT_THAT(conv, op::Convolution(op::Parameter(), op::Parameter())); + ASSERT_THAT(conv, + GmockMatch(m::Convolution(m::Parameter(), m::Parameter()))); EXPECT_EQ(window_util::ToString(conv->window()), absl::StrFormat("size=%dx%d %s", conv->operand(1)->shape().dimensions(2), @@ -2908,8 +3225,9 @@ TEST_F(AlgebraicSimplifierTest, ConvertConvToMatmul) { auto module = CreateNewUnverifiedModule(); auto* computation = module->AddEntryComputation(b.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/true, - bitcasting_callback()); + AlgebraicSimplifierOptions simplifier_options(bitcasting_callback()); + simplifier_options.set_is_layout_sensitive(true); + AlgebraicSimplifier simplifier(simplifier_options); if (!simplifier.Run(module.get()).ValueOrDie()) { return "NO_CHANGE"; } @@ -3032,17 +3350,15 @@ TEST_F(AlgebraicSimplifierTest, ScalarBroadcastToSlice) { EXPECT_EQ(root, slice); EXPECT_TRUE(ShapeUtil::Equal(root->shape(), slice_shape)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); // Running simplification again should not result in any further changes. ASSERT_FALSE(simplifier.Run(module.get()).ValueOrDie()); - - root = computation->root_instruction(); - EXPECT_THAT(root, op::Broadcast(scalar_param)); - EXPECT_TRUE(ShapeUtil::Equal(root->shape(), slice_shape)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Broadcast(m::Op().Is(scalar_param)) + .WithShapeEqualTo(&slice_shape))); } // Test that reshape(transpose(broadcast(/*scalar value*/))) simplifies to a @@ -3071,13 +3387,11 @@ TEST_F(AlgebraicSimplifierTest, ScalarBroadcastToTransposeReshape) { EXPECT_EQ(root, reshape); EXPECT_TRUE(ShapeUtil::Equal(root->shape(), reshape_shape)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); - - root = computation->root_instruction(); - EXPECT_THAT(root, op::Broadcast(forty_two)); - EXPECT_TRUE(ShapeUtil::Equal(root->shape(), reshape_shape)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Broadcast(m::Op().Is(forty_two)) + .WithShapeEqualTo(&reshape_shape))); } // Test that ReduceWindow(Pad(op, x), y) can simplify to ReduceWindow(op, x). @@ -3138,8 +3452,7 @@ TEST_F(AlgebraicSimplifierTest, FoldPadIntoReduceWindow) { auto computation = module->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root, reduce_window); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); // Running simplification again should not result in any further changes. @@ -3147,7 +3460,8 @@ TEST_F(AlgebraicSimplifierTest, FoldPadIntoReduceWindow) { // Verify the result root = computation->root_instruction(); - EXPECT_THAT(root, op::ReduceWindow(operand, op::Constant())); + EXPECT_THAT(root, + GmockMatch(m::ReduceWindow(m::Op().Is(operand), m::Constant()))); EXPECT_TRUE(ShapeUtil::Equal(root->shape(), reduce_window_shape)) << ShapeUtil::HumanString(root->shape()) << " vs " << ShapeUtil::HumanString(reduce_window_shape); @@ -3224,8 +3538,7 @@ TEST_F(AlgebraicSimplifierTest, FoldConvertedPadIntoReduceWindow) { auto computation = module->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root, reduce_window); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); // Running simplification again should not result in any further changes. @@ -3233,7 +3546,8 @@ TEST_F(AlgebraicSimplifierTest, FoldConvertedPadIntoReduceWindow) { // Verify the result root = computation->root_instruction(); - EXPECT_THAT(root, op::ReduceWindow(op::Convert(parameter), op::Constant())); + EXPECT_THAT(root, GmockMatch(m::ReduceWindow(m::Convert(m::Parameter(0)), + m::Constant()))); EXPECT_TRUE(ShapeUtil::Equal(root->shape(), reduce_window_shape)) << ShapeUtil::HumanString(root->shape()) << " vs " << ShapeUtil::HumanString(reduce_window_shape); @@ -3258,8 +3572,7 @@ TEST_F(AlgebraicSimplifierTest, ReversalOfTrivialDimensionsToBitcast) { auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(module.get()).ValueOrDie()); HloInstruction* root = computation->root_instruction(); @@ -3295,8 +3608,7 @@ TEST_F(AlgebraicSimplifierTest, IteratorInvalidation) { m->AddEmbeddedComputation(std::move(dot_computation)); m->AddEntryComputation(call_builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); } @@ -3313,11 +3625,10 @@ TEST_F(AlgebraicSimplifierTest, ConstantTupleBecomesTupleOfConstants) { auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::Tuple(op::Constant(), op::Constant())); + GmockMatch(m::Tuple(m::Constant(), m::Constant()))); } // A dynamic-slice is trivial if its start indices are all zeroes and the size @@ -3337,10 +3648,9 @@ TEST_F(AlgebraicSimplifierTest, TrivialDynamicSlice) { /*slice_sizes=*/{10, 100, 1000})); auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); - EXPECT_THAT(computation->root_instruction(), op::Parameter()); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Parameter())); } // A dynamic-update-slice is trivial if its start indices are all zeroes and the @@ -3371,11 +3681,10 @@ TEST_F(AlgebraicSimplifierTest, TrivialDynamicUpdateSlice) { 3, ShapeUtil::MakeShape(U32, {3}), "update_indices")))); auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), - op::DynamicSlice(op::Parameter(), op::Parameter())); + GmockMatch(m::DynamicSlice(m::Parameter(), m::Parameter()))); } // Test that two consecutive broadcasts can be merged to one. @@ -3394,11 +3703,10 @@ TEST_F(AlgebraicSimplifierTest, MergeBroadcasts) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kBroadcast); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Broadcast(op::Constant())); + EXPECT_THAT(root, GmockMatch(m::Broadcast(m::Constant()))); EXPECT_THAT(root->dimensions(), ElementsAre(2)); } @@ -3421,11 +3729,10 @@ TEST_F(AlgebraicSimplifierTest, MergeBroadcasts2) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kBroadcast); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Broadcast(op::Parameter(0))); + EXPECT_THAT(root, GmockMatch(m::Broadcast(m::Parameter(0)))); EXPECT_THAT(root->dimensions(), ElementsAre(1, 3)); } @@ -3442,11 +3749,10 @@ TEST_F(AlgebraicSimplifierTest, MergeBroadcastAndIota) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kBroadcast); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Iota()); + EXPECT_THAT(root, GmockMatch(m::Iota())); EXPECT_EQ(Cast(root)->iota_dimension(), 2); } @@ -3464,11 +3770,10 @@ TEST_F(AlgebraicSimplifierTest, MergeBroadcastAndIota2) { auto computation = m->AddEntryComputation(builder.Build()); HloInstruction* root = computation->root_instruction(); EXPECT_EQ(root->opcode(), HloOpcode::kBroadcast); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); root = computation->root_instruction(); - EXPECT_THAT(root, op::Iota()); + EXPECT_THAT(root, GmockMatch(m::Iota())); EXPECT_EQ(Cast(root)->iota_dimension(), 2); } @@ -3486,11 +3791,11 @@ TEST_F(AlgebraicSimplifierTest, SliceOfPadLow) { TF_ASSERT_OK_AND_ASSIGN(auto module, ParseAndReturnVerifiedModule(hlo_string)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + AlgebraicSimplifier simplifier(options); EXPECT_TRUE(simplifier.Run(module.get()).ValueOrDie()); auto root = module->entry_computation()->root_instruction(); - EXPECT_THAT(root, op::Reshape(op::Constant())); + EXPECT_THAT(root, GmockMatch(m::Reshape(m::Constant()))); } TEST_F(AlgebraicSimplifierTest, SliceOfPadHigh) { @@ -3507,11 +3812,11 @@ TEST_F(AlgebraicSimplifierTest, SliceOfPadHigh) { TF_ASSERT_OK_AND_ASSIGN(auto module, ParseAndReturnVerifiedModule(hlo_string)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + AlgebraicSimplifier simplifier(options); EXPECT_TRUE(simplifier.Run(module.get()).ValueOrDie()); auto root = module->entry_computation()->root_instruction(); - EXPECT_THAT(root, op::Reshape(op::Constant())); + EXPECT_THAT(root, GmockMatch(m::Reshape(m::Constant()))); } TEST_F(AlgebraicSimplifierTest, SliceOfPadMidNonScalar) { @@ -3528,8 +3833,8 @@ TEST_F(AlgebraicSimplifierTest, SliceOfPadMidNonScalar) { TF_ASSERT_OK_AND_ASSIGN(auto module, ParseAndReturnVerifiedModule(hlo_string)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + AlgebraicSimplifier simplifier(options); EXPECT_FALSE(simplifier.Run(module.get()).ValueOrDie()); } @@ -3547,11 +3852,11 @@ TEST_F(AlgebraicSimplifierTest, SliceOfPadMidScalar) { TF_ASSERT_OK_AND_ASSIGN(auto module, ParseAndReturnVerifiedModule(hlo_string)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + AlgebraicSimplifier simplifier(options); EXPECT_TRUE(simplifier.Run(module.get()).ValueOrDie()); auto root = module->entry_computation()->root_instruction(); - EXPECT_THAT(root, op::Parameter()); + EXPECT_THAT(root, GmockMatch(m::Parameter())); } TEST_F(AlgebraicSimplifierTest, SliceOfConcatScalarInput) { @@ -3569,11 +3874,11 @@ TEST_F(AlgebraicSimplifierTest, SliceOfConcatScalarInput) { TF_ASSERT_OK_AND_ASSIGN(auto module, ParseAndReturnVerifiedModule(hlo_string)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + AlgebraicSimplifier simplifier(options); EXPECT_TRUE(simplifier.Run(module.get()).ValueOrDie()); auto root = module->entry_computation()->root_instruction(); - EXPECT_THAT(root, op::Parameter(1)); + EXPECT_THAT(root, GmockMatch(m::Parameter(1))); } TEST_F(AlgebraicSimplifierTest, SliceOfConcatNonScalarInput) { @@ -3591,11 +3896,11 @@ TEST_F(AlgebraicSimplifierTest, SliceOfConcatNonScalarInput) { TF_ASSERT_OK_AND_ASSIGN(auto module, ParseAndReturnVerifiedModule(hlo_string)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + AlgebraicSimplifier simplifier(options); EXPECT_TRUE(simplifier.Run(module.get()).ValueOrDie()); auto root = module->entry_computation()->root_instruction(); - EXPECT_THAT(root, op::Slice(op::Parameter(2))); + EXPECT_THAT(root, GmockMatch(m::Slice(m::Parameter(2)))); EXPECT_EQ(root->slice_starts(0), 1); EXPECT_EQ(root->slice_limits(0), 2); } @@ -3613,11 +3918,11 @@ TEST_F(AlgebraicSimplifierTest, NegateNegate) { TF_ASSERT_OK_AND_ASSIGN(auto module, ParseAndReturnVerifiedModule(hlo_string)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + AlgebraicSimplifier simplifier(options); EXPECT_TRUE(simplifier.Run(module.get()).ValueOrDie()); auto root = module->entry_computation()->root_instruction(); - EXPECT_THAT(root, op::Parameter(0)); + EXPECT_THAT(root, GmockMatch(m::Parameter(0))); } TEST_F(AlgebraicSimplifierTest, NotNot) { @@ -3633,11 +3938,11 @@ TEST_F(AlgebraicSimplifierTest, NotNot) { TF_ASSERT_OK_AND_ASSIGN(auto module, ParseAndReturnVerifiedModule(hlo_string)); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - bitcasting_callback()); + AlgebraicSimplifierOptions options(bitcasting_callback()); + AlgebraicSimplifier simplifier(options); EXPECT_TRUE(simplifier.Run(module.get()).ValueOrDie()); auto root = module->entry_computation()->root_instruction(); - EXPECT_THAT(root, op::Parameter(0)); + EXPECT_THAT(root, GmockMatch(m::Parameter(0))); } struct PadReduceWindowEffectiveBroadcastCase { @@ -3733,8 +4038,7 @@ TEST_P(PadReduceWindowEffectiveBroadcastTest, DoIt) { output_shape, pad, zero, window, add_computation)); auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); TF_ASSERT_OK_AND_ASSIGN(bool run_successful, simplifier.Run(m.get())); ASSERT_TRUE(run_successful); @@ -3742,10 +4046,10 @@ TEST_P(PadReduceWindowEffectiveBroadcastTest, DoIt) { ShapeUtil::Equal(computation->root_instruction()->shape(), output_shape)); if (param.should_become_broadcast) { - EXPECT_THAT(computation->root_instruction(), op::Broadcast(::testing::_)); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Broadcast())); } else { EXPECT_THAT(computation->root_instruction(), - op::ReduceWindow(::testing::_, zero)); + GmockMatch(m::ReduceWindow(m::Op(), m::Op().Is(zero)))); } } @@ -3815,8 +4119,7 @@ TEST_P(DotStrengthReductionTest, DotStrengthReduction) { builder.AddInstruction(HloInstruction::CreateDot( dot_shape, lhs, rhs, dot_dnums, DefaultPrecisionConfig(2))); auto computation = module->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); TF_ASSERT_OK_AND_ASSIGN(bool changed, simplifier.Run(module.get())); const bool dot_should_be_transformed = m == 1 || k == 1 || n == 1; const bool computation_should_be_modified = @@ -3845,7 +4148,7 @@ struct DotOfConcatTestSpec { }; class DotOfConcatSimplificationTest - : public HloTestBase, + : public AlgebraicSimplifierTest, public ::testing::WithParamInterface {}; // Test that we transform @@ -3893,19 +4196,19 @@ TEST_P(DotOfConcatSimplificationTest, ConstantLHS) { dot_shape, lhs, rhs, dot_dnums, DefaultPrecisionConfig(2))); auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); TF_ASSERT_OK_AND_ASSIGN(bool run_successful, simplifier.Run(m.get())); ASSERT_TRUE(run_successful); EXPECT_TRUE( ShapeUtil::Equal(computation->root_instruction()->shape(), dot_shape)); - auto match_dot_0 = op::Dot(op::Slice(op::Constant()), op::Parameter(0)); - auto match_dot_1 = op::Dot(op::Slice(op::Constant()), op::Parameter(1)); - auto match_dot_2 = op::Dot(op::Slice(op::Constant()), op::Parameter(2)); - EXPECT_THAT(computation->root_instruction(), - op::Add(op::Add(match_dot_0, match_dot_1), match_dot_2)); + auto match_dot_0 = m::Dot(m::Slice(m::Constant()), m::Parameter(0)); + auto match_dot_1 = m::Dot(m::Slice(m::Constant()), m::Parameter(1)); + auto match_dot_2 = m::Dot(m::Slice(m::Constant()), m::Parameter(2)); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Add(m::Add(match_dot_0, match_dot_1), match_dot_2))); } // Test that we transform @@ -3958,20 +4261,20 @@ TEST_P(DotOfConcatSimplificationTest, ConstantRHS) { dot_shape, lhs, rhs, dot_dnums, DefaultPrecisionConfig(2))); auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); TF_ASSERT_OK_AND_ASSIGN(bool run_successful, simplifier.Run(m.get())); ASSERT_TRUE(run_successful); EXPECT_TRUE( ShapeUtil::Equal(computation->root_instruction()->shape(), dot_shape)); - auto match_dot_0 = op::Dot(op::Parameter(0), op::Slice(op::Constant())); - auto match_dot_1 = op::Dot(op::Parameter(1), op::Slice(op::Constant())); - auto match_dot_2 = op::Dot(op::Parameter(2), op::Slice(op::Constant())); - auto match_dot_3 = op::Dot(op::Parameter(3), op::Slice(op::Constant())); - EXPECT_THAT(computation->root_instruction(), - op::Add(op::Add(op::Add(match_dot_0, match_dot_1), match_dot_2), - match_dot_3)); + auto match_dot_0 = m::Dot(m::Parameter(0), m::Slice(m::Constant())); + auto match_dot_1 = m::Dot(m::Parameter(1), m::Slice(m::Constant())); + auto match_dot_2 = m::Dot(m::Parameter(2), m::Slice(m::Constant())); + auto match_dot_3 = m::Dot(m::Parameter(3), m::Slice(m::Constant())); + EXPECT_THAT( + computation->root_instruction(), + GmockMatch(m::Add(m::Add(m::Add(match_dot_0, match_dot_1), match_dot_2), + match_dot_3))); } DotOfConcatTestSpec kDotOfConcatTestSpecs[] = { @@ -4000,8 +4303,7 @@ TEST_F(AlgebraicSimplifierTest, DynamicUpdateSliceZeroUpdate) { const HloComputation* const computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); ASSERT_TRUE(simplifier.Run(m.get()).ValueOrDie()); EXPECT_THAT(computation->root_instruction(), operand); } @@ -4021,7 +4323,7 @@ struct DotOfGatherTestSpec { }; class DotOfGatherSimplificationTest - : public HloTestBase, + : public AlgebraicSimplifierTest, public ::testing::WithParamInterface {}; // input: dot(DS(ctA), ctB)) @@ -4078,8 +4380,7 @@ TEST_P(DotOfGatherSimplificationTest, ConstantRHS) { dot_shape, ds, rhs, dot_dnums, DefaultPrecisionConfig(2))); auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); TF_ASSERT_OK_AND_ASSIGN(bool run_successful, simplifier.Run(m.get())); ASSERT_TRUE(run_successful); EXPECT_TRUE( @@ -4090,8 +4391,8 @@ TEST_P(DotOfGatherSimplificationTest, ConstantRHS) { HloOpcode::kDynamicSlice); } else { EXPECT_THAT(computation->root_instruction(), - op::DynamicSlice(op::Dot(op::Constant(), op::Constant()), - op::Concatenate())); + GmockMatch(m::DynamicSlice(m::Dot(m::Constant(), m::Constant()), + m::Concatenate()))); } } @@ -4149,8 +4450,7 @@ TEST_P(DotOfGatherSimplificationTest, ConstantLHS) { dot_shape, lhs, ds, dot_dnums, DefaultPrecisionConfig(2))); auto computation = m->AddEntryComputation(builder.Build()); - AlgebraicSimplifier simplifier(/*is_layout_sensitive=*/false, - non_bitcasting_callback()); + AlgebraicSimplifier simplifier(default_options_); TF_ASSERT_OK_AND_ASSIGN(bool run_successful, simplifier.Run(m.get())); ASSERT_TRUE(run_successful); EXPECT_TRUE( @@ -4161,8 +4461,8 @@ TEST_P(DotOfGatherSimplificationTest, ConstantLHS) { HloOpcode::kDynamicSlice); } else { EXPECT_THAT(computation->root_instruction(), - op::DynamicSlice(op::Dot(op::Constant(), op::Constant()), - op::Concatenate())); + GmockMatch(m::DynamicSlice(m::Dot(m::Constant(), m::Constant()), + m::Concatenate()))); } } diff --git a/tensorflow/compiler/xla/service/ar_crs_combiner.cc b/tensorflow/compiler/xla/service/ar_crs_combiner.cc new file mode 100644 index 0000000000..c11452a6fb --- /dev/null +++ b/tensorflow/compiler/xla/service/ar_crs_combiner.cc @@ -0,0 +1,286 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/service/ar_crs_combiner.h" + +#include +#include +#include + +#include "tensorflow/compiler/xla/literal.h" +#include "tensorflow/compiler/xla/literal_util.h" +#include "tensorflow/compiler/xla/service/call_graph.h" +#include "tensorflow/compiler/xla/service/hlo_computation.h" +#include "tensorflow/compiler/xla/service/hlo_instruction.h" +#include "tensorflow/compiler/xla/service/hlo_opcode.h" +#include "tensorflow/compiler/xla/service/pattern_matcher.h" +#include "tensorflow/compiler/xla/status_macros.h" +#include "tensorflow/compiler/xla/types.h" +#include "tensorflow/compiler/xla/xla_data.pb.h" + +namespace xla { + +namespace { + +namespace m = match; + +// If the argument instruction is a CRS in the sequence +// AR -> Convert -> Add -> CRS +// then return the AR in the sequence. +// TODO(b/117554291): Rewrite this to recognize more general patterns, +// not just the specific one of AR -> Add -> Convert -> CRS. +absl::optional MatchesArCrsPattern( + HloInstruction* instruction) { + HloInstruction *ar, *convert, *add, *crs; + if (Match(instruction, + m::CrossReplicaSum( + &crs, m::Add(&add, m::Op(), + m::Convert(&convert, + m::CrossReplicaSum(&ar, m::Op()))))) && + ar->users().size() == 1 && ar->shape().element_type() == BF16 && + convert->shape().element_type() == F32 && !crs->all_reduce_id()) { + return ar; + } + return absl::optional(); +} + +} // namespace + +absl::optional ArCrsCombiner::WhileFromBodyParameter( + HloInstruction* instruction) { + CHECK(HloOpcode::kParameter == instruction->opcode()); + HloComputation* computation = instruction->parent(); + auto caller_instructions = call_graph_->GetComputationCallers(computation); + if (caller_instructions.size() == 1) { + auto caller_instruction = caller_instructions[0]; + if (caller_instruction->opcode() == HloOpcode::kWhile) { + return caller_instruction; + } + } + return absl::optional(); +} + +std::vector ArCrsCombiner::GetAllTuples( + HloInstruction* instruction) { + if (instruction->opcode() == HloOpcode::kTuple) { + return {instruction}; + } + if (instruction->opcode() == HloOpcode::kDomain) { + return GetAllTuples(instruction->operands()[0]); + } + if (instruction->opcode() == HloOpcode::kParameter) { + auto maybe_while = WhileFromBodyParameter(instruction); + if (!maybe_while) { + return {}; + } + auto while_instr = *maybe_while; + auto init_tuples = GetAllTuples(while_instr->while_init()); + auto body_tuples = + GetAllTuples(while_instr->while_body()->root_instruction()); + if (init_tuples.empty() || body_tuples.empty()) { + return {}; + } + init_tuples.insert(init_tuples.end(), body_tuples.begin(), + body_tuples.end()); + return init_tuples; + } + if (instruction->opcode() == HloOpcode::kGetTupleElement) { + std::vector result_tuples; + for (auto tuple : GetAllTuples(instruction->operands()[0])) { + auto tmp_tuples = + GetAllTuples(tuple->mutable_operand(instruction->tuple_index())); + if (tmp_tuples.empty()) { + return {}; + } + result_tuples.insert(result_tuples.end(), tmp_tuples.begin(), + tmp_tuples.end()); + } + return result_tuples; + } + return {}; +} + +bool ArCrsCombiner::TupleElementsComputeSameValue( + HloInstruction* tuple_shaped_instruction, int64 i1, int64 i2, + absl::flat_hash_map* visited_pairs) { + auto tuples = GetAllTuples(tuple_shaped_instruction); + if (tuples.empty()) { + return false; + } + for (auto tuple : tuples) { + CHECK(tuple->opcode() == HloOpcode::kTuple); + if (!InstructionsComputeSameValue(tuple->mutable_operand(i1), + tuple->mutable_operand(i2), + visited_pairs)) { + return false; + } + } + return true; +} + +/* static */ +bool ArCrsCombiner::TestInstructionsComputeSameValue(HloInstruction* i1, + HloInstruction* i2) { + ArCrsCombiner combiner(/*num_spatial_partitions=*/2); + auto module = i1->parent()->parent(); + CHECK_EQ(module, i2->parent()->parent()); + combiner.call_graph_ = CallGraph::Build(module); + absl::flat_hash_map visited_pairs; + return combiner.InstructionsComputeSameValue(i1, i2, &visited_pairs); +} + +bool ArCrsCombiner::InstructionsComputeSameValue( + HloInstruction* i1, HloInstruction* i2, + absl::flat_hash_map* visited_pairs) { + if (i1 == i2) { + return true; + } + auto uid1 = i1->unique_id(); + auto uid2 = i2->unique_id(); + auto min_uid = std::min(uid1, uid2); + auto max_uid = std::max(uid1, uid2); + auto it = visited_pairs->find(min_uid); + if (it != visited_pairs->end() && max_uid == it->second) { + return true; + } + auto opcode1 = i1->opcode(); + auto operands1 = i1->operands(); + if (opcode1 != i2->opcode() || operands1.size() != i2->operands().size()) { + return false; + } + if (opcode1 == HloOpcode::kConstant || i1->IsCrossModuleAllReduce()) { + return i1->Identical( + *i2, + /*eq_operands=*/std::equal_to(), + /*eq_computations=*/std::equal_to(), + /*layout_sensitive=*/false); + } + visited_pairs->emplace(min_uid, max_uid); + for (int i = 0; i < operands1.size(); ++i) { + auto operand1 = operands1[i]; + auto operand2 = i2->operands()[i]; + if (!InstructionsComputeSameValue(operand1, operand2, visited_pairs)) { + return false; + } + } + if (opcode1 == HloOpcode::kGetTupleElement) { + if (i1->tuple_index() == i2->tuple_index()) { + return true; + } + return TupleElementsComputeSameValue(operands1[0], i1->tuple_index(), + i2->tuple_index(), visited_pairs); + } + return true; +} + +void ArCrsCombiner::GroupAllReducesById(HloModule* module) { + for (HloComputation* computation : module->MakeNonfusionComputations()) { + for (HloInstruction* instruction : computation->instructions()) { + auto ar = MatchesArCrsPattern(instruction); + if (ar) { + all_reduce_map_[*((*ar)->all_reduce_id())].push_back(*ar); + } + } + } +} + +void ArCrsCombiner::KeepProvablyEqualInstructionGroups() { + for (auto it : all_reduce_map_) { + auto instruction_vec = it.second; + CHECK_EQ(instruction_vec.size(), num_spatial_partitions_); + + auto instr_0 = instruction_vec[0]; + auto add_0 = instr_0->users()[0]->users()[0]; + CHECK(HloOpcode::kAdd == add_0->opcode()); + + for (int i = 1; i < instruction_vec.size(); ++i) { + auto instr_i = instruction_vec[i]; + auto add_i = instr_i->users()[0]->users()[0]; + CHECK(HloOpcode::kAdd == add_i->opcode()); + absl::flat_hash_map visited_pairs; + if (!InstructionsComputeSameValue(add_0, add_i, &visited_pairs)) { + all_reduce_map_.erase(it.first); + } + } + } +} + +StatusOr ArCrsCombiner::RewriteGraph() { + if (all_reduce_map_.empty()) { + return false; + } + + auto computation_is_addition = [](HloComputation* c) { + return c->instruction_count() == 3 && + Match(c->root_instruction(), m::Add(m::Parameter(), m::Parameter())); + }; + + for (auto it : all_reduce_map_) { + auto instruction_vec = it.second; + for (auto all_reduce : instruction_vec) { + auto parent_computation = all_reduce->parent(); + auto convert = all_reduce->users()[0]; + auto add = convert->users()[0]; + auto crs = add->users()[0]; + + if (!computation_is_addition(all_reduce->called_computations()[0]) || + !computation_is_addition(crs->called_computations()[0])) { + continue; + } + HloInstruction* other_summand = (add->operands()[0] == convert) + ? add->operands()[1] + : add->operands()[0]; + // Remove the AllReduce and replace the CRS with: + // AllReduce - (other_summand * (num_spatial_partitions_ - 1)) + TF_CHECK_OK( + all_reduce->ReplaceAllUsesWith(all_reduce->mutable_operand(0))); + crs->set_all_reduce_id(all_reduce->all_reduce_id()); + auto new_shape = crs->shape(); + HloInstruction* to_subtract; + if (num_spatial_partitions_ == 2) { + to_subtract = other_summand; + } else { + Literal partitions_minus_1_lit = Literal(new_shape); + partitions_minus_1_lit.PopulateWithValue( + num_spatial_partitions_ - 1); + auto partitions_minus_1_const = parent_computation->AddInstruction( + HloInstruction::CreateConstant(partitions_minus_1_lit.Clone())); + to_subtract = + parent_computation->AddInstruction(HloInstruction::CreateBinary( + new_shape, HloOpcode::kMultiply, other_summand, + partitions_minus_1_const)); + } + auto sub = + parent_computation->AddInstruction(HloInstruction::CreateBinary( + new_shape, HloOpcode::kSubtract, crs, to_subtract)); + TF_CHECK_OK(crs->ReplaceAllUsesWith(sub)); + TF_CHECK_OK(parent_computation->RemoveInstruction(all_reduce)); + } + } + + return true; +} + +StatusOr ArCrsCombiner::Run(HloModule* module) { + call_graph_ = CallGraph::Build(module); + + GroupAllReducesById(module); + + KeepProvablyEqualInstructionGroups(); + + return RewriteGraph(); +} + +} // namespace xla diff --git a/tensorflow/compiler/xla/service/ar_crs_combiner.h b/tensorflow/compiler/xla/service/ar_crs_combiner.h new file mode 100644 index 0000000000..f6a7ef76ec --- /dev/null +++ b/tensorflow/compiler/xla/service/ar_crs_combiner.h @@ -0,0 +1,88 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_COMPILER_XLA_SERVICE_AR_CRS_COMBINER_H_ +#define TENSORFLOW_COMPILER_XLA_SERVICE_AR_CRS_COMBINER_H_ + +#include "absl/container/flat_hash_map.h" +#include "absl/strings/string_view.h" +#include "tensorflow/compiler/xla/service/call_graph.h" +#include "tensorflow/compiler/xla/service/hlo_module.h" +#include "tensorflow/compiler/xla/service/hlo_pass_interface.h" +#include "tensorflow/compiler/xla/statusor.h" + +namespace xla { + +// Combine an AllReduce and a CrossReplicaSum when they are close to each other +// in the graph, to use an efficient CrossReplicaSum implementation that +// fully utilizes the interconnect bandwidth. +class ArCrsCombiner : public HloModulePass { + public: + ArCrsCombiner(int num_spatial_partitions) + : num_spatial_partitions_(num_spatial_partitions) {} + absl::string_view name() const override { return "ar-crs-combiner"; } + StatusOr Run(HloModule* module) override; + + // Helper method to allow testing of InstructionsComputeSameValue. + static bool TestInstructionsComputeSameValue(HloInstruction* i1, + HloInstruction* i2); + + private: + // If the passed instruction is a while parameter, and the while body is only + // called by a single while instruction, return the while instruction. + absl::optional WhileFromBodyParameter( + HloInstruction* instruction); + + // Returns a vector of tuple instructions. + // If all instructions that flow to "instruction" are tuples, return them. + // Otherwise, return an empty vector. + std::vector GetAllTuples(HloInstruction* instruction); + + // Checks whether two different elements in the same tuple compute the same + // value. + bool TupleElementsComputeSameValue( + HloInstruction* tuple_shaped_instruction, int64 i1, int64 i2, + absl::flat_hash_map* visited_pairs); + + // Returns whether the instructions i1 and i2 can be shown to evaluate to the + // same value. Handling WHILE requires recursion, which may cause us to visit + // the same instruction again. To avoid infinite loops, we pass a cache of + // visited instruction pairs. + bool InstructionsComputeSameValue( + HloInstruction* i1, HloInstruction* i2, + absl::flat_hash_map* visited_pairs); + + // Populates all_reduce_map_. + void GroupAllReducesById(HloModule* module); + + // Looks at each AllReduce group in all_reduce_map_, and keeps only the + // groups for which it's safe to move the AllReduce later in the HLO graph. + void KeepProvablyEqualInstructionGroups(); + + // Performs the graph rewrite that eliminates the early AllReduce and turns + // the later CRS into an AllReduce. + StatusOr RewriteGraph(); + + int num_spatial_partitions_; + + // Map from all-reduce ids to the all reduce instructions. + absl::flat_hash_map> all_reduce_map_; + + std::unique_ptr call_graph_; +}; + +} // namespace xla + +#endif // TENSORFLOW_COMPILER_XLA_SERVICE_AR_CRS_COMBINER_H_ diff --git a/tensorflow/compiler/xla/service/ar_crs_combiner_test.cc b/tensorflow/compiler/xla/service/ar_crs_combiner_test.cc new file mode 100644 index 0000000000..9d5eaf63cc --- /dev/null +++ b/tensorflow/compiler/xla/service/ar_crs_combiner_test.cc @@ -0,0 +1,415 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/service/ar_crs_combiner.h" +#include "tensorflow/compiler/xla/service/hlo_matchers.h" +#include "tensorflow/compiler/xla/statusor.h" +#include "tensorflow/compiler/xla/tests/hlo_test_base.h" +#include "tensorflow/core/lib/core/status_test_util.h" + +namespace xla { +namespace { + +namespace op = xla::testing::opcode_matchers; + +class ArCrsCombinerTest : public HloTestBase {}; + +TEST_F(ArCrsCombinerTest, SameValueTestBasecase) { + const char* module_str = R"( +HloModule foobar + +ENTRY %entrycomp (p: f32[2,2]) -> (f32[2,2], f32[2,2]) { + %p = f32[2,2] parameter(0) + %constant.f32.1 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + %constant.f32.2 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + ROOT %tuple = (f32[2,2], f32[2,2]) tuple(%constant.f32.1, %constant.f32.2) +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + auto root_tuple = module->entry_computation()->root_instruction(); + auto i1 = root_tuple->operands()[0]; + auto i2 = root_tuple->operands()[1]; + EXPECT_FALSE(ArCrsCombiner::TestInstructionsComputeSameValue( + i1, module->entry_computation()->parameter_instruction(0))); + EXPECT_TRUE(ArCrsCombiner::TestInstructionsComputeSameValue(i1, i2)); +} + +TEST_F(ArCrsCombinerTest, SameValueTestNumOperands) { + const char* module_str = R"( +HloModule foobar + +ENTRY %entrycomp (p: f32[2,2]) -> ((f32[2,2]), (f32[2,2], f32[2,2])) { + %p = f32[2,2] parameter(0) + %constant.f32 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + %tuple1 = (f32[2,2]) tuple(%constant.f32) + %tuple2 = (f32[2,2], f32[2,2]) tuple(%constant.f32, %constant.f32) + ROOT %tuple = ((f32[2,2]), (f32[2,2], f32[2,2])) tuple(%tuple1, %tuple2) +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + auto root_tuple = module->entry_computation()->root_instruction(); + auto i1 = root_tuple->operands()[0]; + auto i2 = root_tuple->operands()[1]; + EXPECT_FALSE(ArCrsCombiner::TestInstructionsComputeSameValue(i1, i2)); +} + +TEST_F(ArCrsCombinerTest, SameValueTestTupleElementSameIndex) { + const char* module_str = R"( +HloModule foobar + +ENTRY %entrycomp (p: f32[2,2]) -> (f32[2,2], f32[2,2]) { + %p = f32[2,2] parameter(0) + %constant.f32 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + %tuple.1 = (f32[2,2], f32[2,2]) tuple(%constant.f32, %constant.f32) + %get-tuple-element.1 = f32[2,2] get-tuple-element(%tuple.1), index=0 + %get-tuple-element.2 = f32[2,2] get-tuple-element(%tuple.1), index=0 + ROOT %tuple = (f32[2,2], f32[2,2]) tuple(%get-tuple-element.1, %get-tuple-element.2) +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + auto root_tuple = module->entry_computation()->root_instruction(); + auto i1 = root_tuple->operands()[0]; + auto i2 = root_tuple->operands()[1]; + EXPECT_TRUE(ArCrsCombiner::TestInstructionsComputeSameValue(i1, i2)); +} + +TEST_F(ArCrsCombinerTest, SameValueTestTupleElementDifferentIndex1) { + const char* module_str = R"( +HloModule foobar + +ENTRY %entrycomp (p: f32[2,2]) -> (f32[2,2], f32[2,2]) { + %p = f32[2,2] parameter(0) + %constant.f32 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + %tuple.1 = (f32[2,2], f32[2,2]) tuple(%constant.f32, %constant.f32) + %get-tuple-element.1 = f32[2,2] get-tuple-element(%tuple.1), index=0 + %get-tuple-element.2 = f32[2,2] get-tuple-element(%tuple.1), index=1 + ROOT %tuple = (f32[2,2], f32[2,2]) tuple(%get-tuple-element.1, %get-tuple-element.2) +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + auto root_tuple = module->entry_computation()->root_instruction(); + auto i1 = root_tuple->operands()[0]; + auto i2 = root_tuple->operands()[1]; + EXPECT_TRUE(ArCrsCombiner::TestInstructionsComputeSameValue(i1, i2)); +} + +TEST_F(ArCrsCombinerTest, SameValueTestTupleElementDifferentIndex2) { + const char* module_str = R"( +HloModule foobar + +ENTRY %entrycomp (p: f32[2,2]) -> (f32[2,2], f32[2,2]) { + %p = f32[2,2] parameter(0) + %constant.f32.1 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + %constant.f32.2 = f32[2,2] constant(f32[2,2] {{2, 3}, {4, 5}}) + %tuple.1 = (f32[2,2], f32[2,2]) tuple(%constant.f32.1, %constant.f32.2) + %get-tuple-element.1 = f32[2,2] get-tuple-element(%tuple.1), index=0 + %get-tuple-element.2 = f32[2,2] get-tuple-element(%tuple.1), index=1 + ROOT %tuple = (f32[2,2], f32[2,2]) tuple(%get-tuple-element.1, %get-tuple-element.2) +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + auto root_tuple = module->entry_computation()->root_instruction(); + auto i1 = root_tuple->operands()[0]; + auto i2 = root_tuple->operands()[1]; + EXPECT_FALSE(ArCrsCombiner::TestInstructionsComputeSameValue(i1, i2)); +} + +TEST_F(ArCrsCombinerTest, SameValueTestWhile1) { + const char* module_str = R"( +HloModule foobar + +%condition (x: (f32[2,2], f32[2,2])) -> pred[] { + %x = (f32[2,2], f32[2,2]) parameter(0) + %constant.0 = s32[] constant(0) + %constant.1 = s32[] constant(1) + ROOT %greater-than = pred[] greater-than(s32[] %constant.1, s32[] %constant.0) +} + +%body (x: (f32[2,2], f32[2,2])) -> (f32[2,2], f32[2,2]) { + %x = (f32[2,2], f32[2,2]) parameter(0) + %constant.f32 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + %get-tuple-element.1 = f32[2,2] get-tuple-element(%x), index=0 + %get-tuple-element.2 = f32[2,2] get-tuple-element(%x), index=1 + %add.1 = f32[2,2] add(%get-tuple-element.1, %constant.f32) + %add.2 = f32[2,2] add(%get-tuple-element.2, %constant.f32) + ROOT %tuple = (f32[2,2], f32[2,2]) tuple(%add.1, %add.2) +} + +ENTRY %WhileLoop () -> (f32[2,2], f32[2,2]) { + %constant.f32 = f32[2,2] constant(f32[2,2] {{3, 4}, {5, 6}}) + %init.tuple = (f32[2,2], f32[2,2]) tuple(%constant.f32, %constant.f32) + ROOT %while = (f32[2,2], f32[2,2]) while(%init.tuple), condition=%condition, body=%body +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + auto root_while = module->entry_computation()->root_instruction(); + auto body_tuple = root_while->while_body()->root_instruction(); + auto i1 = body_tuple->operands()[0]; + auto i2 = body_tuple->operands()[1]; + EXPECT_TRUE(ArCrsCombiner::TestInstructionsComputeSameValue(i1, i2)); +} + +TEST_F(ArCrsCombinerTest, SameValueTestWhile2) { + const char* module_str = R"( +HloModule foobar + +%condition (x: (f32[2,2], f32[2,2])) -> pred[] { + %x = (f32[2,2], f32[2,2]) parameter(0) + %constant.0 = s32[] constant(0) + %constant.1 = s32[] constant(1) + ROOT %greater-than = pred[] greater-than(s32[] %constant.1, s32[] %constant.0) +} + +%body (x: (f32[2,2], f32[2,2])) -> (f32[2,2], f32[2,2]) { + %x = (f32[2,2], f32[2,2]) parameter(0) + %constant.f32 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + %get-tuple-element.1 = f32[2,2] get-tuple-element(%x), index=0 + %get-tuple-element.2 = f32[2,2] get-tuple-element(%x), index=1 + %add.1 = f32[2,2] add(%get-tuple-element.1, %constant.f32) + %add.2 = f32[2,2] add(%get-tuple-element.2, %constant.f32) + ROOT %tuple = (f32[2,2], f32[2,2]) tuple(%add.1, %add.2) +} + +ENTRY %WhileLoop () -> (f32[2,2], f32[2,2]) { + %constant.f32.1 = f32[2,2] constant(f32[2,2] {{3, 4}, {5, 6}}) + %constant.f32.2 = f32[2,2] constant(f32[2,2] {{3, 4}, {7, 8}}) + %init.tuple = (f32[2,2], f32[2,2]) tuple(%constant.f32.1, %constant.f32.2) + ROOT %while = (f32[2,2], f32[2,2]) while(%init.tuple), condition=%condition, body=%body +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + auto root_while = module->entry_computation()->root_instruction(); + auto body_tuple = root_while->while_body()->root_instruction(); + auto i1 = body_tuple->operands()[0]; + auto i2 = body_tuple->operands()[1]; + EXPECT_FALSE(ArCrsCombiner::TestInstructionsComputeSameValue(i1, i2)); +} + +TEST_F(ArCrsCombinerTest, SameValueTestWhile3) { + const char* module_str = R"( +HloModule foobar + +%condition (x: (f32[2,2], f32[2,2])) -> pred[] { + %x = (f32[2,2], f32[2,2]) parameter(0) + %constant.0 = s32[] constant(0) + %constant.1 = s32[] constant(1) + ROOT %greater-than = pred[] greater-than(s32[] %constant.1, s32[] %constant.0) +} + +%body (x: (f32[2,2], f32[2,2])) -> (f32[2,2], f32[2,2]) { + %x = (f32[2,2], f32[2,2]) parameter(0) + %constant.f32.1 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + %constant.f32.2 = f32[2,2] constant(f32[2,2] {{3, 4}, {1, 2}}) + %get-tuple-element.1 = f32[2,2] get-tuple-element(%x), index=0 + %get-tuple-element.2 = f32[2,2] get-tuple-element(%x), index=1 + %add.1 = f32[2,2] add(%get-tuple-element.1, %constant.f32.1) + %add.2 = f32[2,2] add(%get-tuple-element.2, %constant.f32.2) + ROOT %tuple = (f32[2,2], f32[2,2]) tuple(%add.1, %add.2) +} + +ENTRY %WhileLoop () -> (f32[2,2], f32[2,2]) { + %constant.f32 = f32[2,2] constant(f32[2,2] {{3, 4}, {5, 6}}) + %init.tuple = (f32[2,2], f32[2,2]) tuple(%constant.f32, %constant.f32) + ROOT %while = (f32[2,2], f32[2,2]) while(%init.tuple), condition=%condition, body=%body +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + auto root_while = module->entry_computation()->root_instruction(); + auto body_tuple = root_while->while_body()->root_instruction(); + auto i1 = body_tuple->operands()[0]->operands()[0]; // %get-tuple-element.1 + auto i2 = body_tuple->operands()[1]->operands()[0]; // %get-tuple-element.2 + EXPECT_FALSE(ArCrsCombiner::TestInstructionsComputeSameValue(i1, i2)); +} + +TEST_F(ArCrsCombinerTest, RewritePatternArConvertAddCrs) { + const char* module_str = R"( +HloModule foobar + +%binary_add (a: bf16[], b: bf16[]) -> bf16[] { + %a = bf16[] parameter(0) + %b = bf16[] parameter(1) + ROOT %add = bf16[] add(%a, %b) +} + +%sum.f32 (x: f32[], y: f32[]) -> f32[] { + %x = f32[] parameter(0) + %y = f32[] parameter(1) + ROOT %add = f32[] add(%x, %y) +} + +ENTRY %entrycomp (p: f32[2,2]) -> (f32[2,2], f32[2,2]) { + %p = f32[2,2] parameter(0) + %constant.bf16 = bf16[2,2] constant(bf16[2,2] {{1, 2}, {3, 4}}) + %constant.f32 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + + %cross-replica-sum.ar.1 = bf16[2,2] + cross-replica-sum(%constant.bf16), + replica_groups={{0},{1}}, + all_reduce_id=1, + to_apply=%binary_add, + sharding={maximal device=0} + %convert.1 = f32[2,2] + convert(%cross-replica-sum.ar.1), + sharding={maximal device=0} + %add.1 = f32[2,2] + add(%constant.f32, %convert.1), + sharding={maximal device=0} + %cross-replica-sum.1 = f32[2,2] + cross-replica-sum(%add.1), + replica_groups={{0,1}}, + to_apply=%sum.f32, + sharding={maximal device=0} + + %cross-replica-sum.ar.2 = bf16[2,2] + cross-replica-sum(%constant.bf16), + replica_groups={{0},{1}}, + all_reduce_id=1, + to_apply=%binary_add, + sharding={maximal device=1} + %convert.2 = f32[2,2] + convert(%cross-replica-sum.ar.2), + sharding={maximal device=1} + %add.2 = f32[2,2] + add(%constant.f32, %convert.2), + sharding={maximal device=1} + %cross-replica-sum.2 = f32[2,2] + cross-replica-sum(%add.2), + replica_groups={{0,1}}, + to_apply=%sum.f32, + sharding={maximal device=1} + + ROOT %tuple = (f32[2,2], f32[2,2]) + tuple(%cross-replica-sum.1, %cross-replica-sum.2), + sharding={{maximal device=0}, {maximal device=1}} +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + auto crs_before = + module->entry_computation()->root_instruction()->operands()[0]; + auto replica_groups_before = crs_before->replica_groups(); + ArCrsCombiner combiner(2); + auto changed = combiner.Run(module.get()).ValueOrDie(); + EXPECT_TRUE(changed); + EXPECT_THAT(module->entry_computation()->root_instruction(), + op::Tuple(op::Subtract(op::CrossReplicaSum(), op::Constant()), + op::Subtract(op::CrossReplicaSum(), op::Constant()))); + auto sub = module->entry_computation()->root_instruction()->operands()[0]; + auto crs_after = sub->operands()[0]; + auto replica_groups_after = crs_after->replica_groups(); + ASSERT_EQ(replica_groups_before.size(), replica_groups_after.size()); + for (int i = 0; i < replica_groups_before.size(); ++i) { + // Somewhat verbose way to compare the replica_ids, because EqualsProto + // is not available in the open-source build. + auto group_before = replica_groups_before[i]; + std::vector ids_before(group_before.replica_ids().begin(), + group_before.replica_ids().end()); + auto group_after = replica_groups_after[i]; + std::vector ids_after(group_after.replica_ids().begin(), + group_after.replica_ids().end()); + EXPECT_EQ(ids_before, ids_after); + } +} + +TEST_F(ArCrsCombinerTest, OtherSummandNotTheSameDontRewrite) { + const char* module_str = R"( +HloModule foobar + +%binary_add (a: bf16[], b: bf16[]) -> bf16[] { + %a = bf16[] parameter(0) + %b = bf16[] parameter(1) + ROOT %add = bf16[] add(%a, %b) +} + +%sum.f32 (x: f32[], y: f32[]) -> f32[] { + %x = f32[] parameter(0) + %y = f32[] parameter(1) + ROOT %add = f32[] add(%x, %y) +} + +ENTRY %entrycomp (p: f32[2,2]) -> (f32[2,2], f32[2,2]) { + %p = f32[2,2] parameter(0) + %constant.bf16 = bf16[2,2] constant(bf16[2,2] {{1, 2}, {3, 4}}) + %constant.f32.1 = f32[2,2] constant(f32[2,2] {{1, 2}, {3, 4}}) + %constant.f32.2 = f32[2,2] constant(f32[2,2] {{3, 4}, {5, 6}}) + + %cross-replica-sum.ar.1 = bf16[2,2] + cross-replica-sum(%constant.bf16), + replica_groups={{0},{1}}, + all_reduce_id=1, + to_apply=%binary_add, + sharding={maximal device=0} + %convert.1 = f32[2,2] + convert(%cross-replica-sum.ar.1), + sharding={maximal device=0} + %add.1 = f32[2,2] + add(%constant.f32.1, %convert.1), + sharding={maximal device=0} + %cross-replica-sum.1 = f32[2,2] + cross-replica-sum(%add.1), + replica_groups={{0,1}}, + to_apply=%sum.f32, + sharding={maximal device=0} + + %cross-replica-sum.ar.2 = bf16[2,2] + cross-replica-sum(%constant.bf16), + replica_groups={{0},{1}}, + all_reduce_id=1, + to_apply=%binary_add, + sharding={maximal device=1} + %convert.2 = f32[2,2] + convert(%cross-replica-sum.ar.2), + sharding={maximal device=1} + %add.2 = f32[2,2] + add(%constant.f32.2, %convert.2), + sharding={maximal device=1} + %cross-replica-sum.2 = f32[2,2] + cross-replica-sum(%add.2), + replica_groups={{0,1}}, + to_apply=%sum.f32, + sharding={maximal device=1} + + ROOT %tuple = (f32[2,2], f32[2,2]) + tuple(%cross-replica-sum.1, %cross-replica-sum.2), + sharding={{maximal device=0}, {maximal device=1}} +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_str)); + ArCrsCombiner combiner(2); + auto changed = combiner.Run(module.get()).ValueOrDie(); + EXPECT_FALSE(changed); +} + +} // namespace +} // namespace xla diff --git a/tensorflow/compiler/xla/service/batchnorm_expander.cc b/tensorflow/compiler/xla/service/batchnorm_expander.cc index f70f6ddfec..0e6ca1871b 100644 --- a/tensorflow/compiler/xla/service/batchnorm_expander.cc +++ b/tensorflow/compiler/xla/service/batchnorm_expander.cc @@ -107,19 +107,37 @@ class BatchNormExpanderVisitor : public DfsHloVisitorWithDefault { } std::unique_ptr Mean( - int64 element_count, HloInstruction* operand, + HloInstruction* element_count, HloInstruction* operand, const std::function)>& add_instruction) { - HloInstruction* elem_count_recip = - add_instruction(HloInstruction::CreateBroadcast( - operand->shape(), - add_instruction(HloInstruction::CreateConvert( - ShapeUtil::MakeShape(operand->shape().element_type(), {}), - add_instruction(HloInstruction::CreateConstant( - LiteralUtil::CreateR0(1.0 / element_count))))), - {})); - return HloInstruction::CreateBinary(operand->shape(), HloOpcode::kMultiply, - operand, elem_count_recip); + auto broadcast = add_instruction( + HloInstruction::CreateBroadcast(operand->shape(), element_count, {})); + return HloInstruction::CreateBinary(operand->shape(), HloOpcode::kDivide, + operand, broadcast); + } + + std::unique_ptr DynamicElementCountPerFeature( + HloInstruction* operand, int64 feature_index, + const std::function)>& + add_instruction) { + auto elements_per_feature_u32 = add_instruction( + HloInstruction::CreateConstant(LiteralUtil::CreateR0(1))); + + for (int64 i = 0; i < ShapeUtil::Rank(operand->shape()); ++i) { + if (i == feature_index) { + continue; + } + auto dynamic_dimension_size = + add_instruction(HloInstruction::CreateGetDimensionSize( + ShapeUtil::MakeShape(U32, {}), operand, i)); + elements_per_feature_u32 = add_instruction(HloInstruction::CreateBinary( + ShapeUtil::MakeShape(U32, {}), HloOpcode::kMultiply, + dynamic_dimension_size, elements_per_feature_u32)); + } + + return HloInstruction::CreateConvert( + ShapeUtil::MakeShape(operand->shape().element_type(), {}), + elements_per_feature_u32); } // Replaces the existing HLO instruction old_instruction, with @@ -195,9 +213,6 @@ Status BatchNormExpanderVisitor::HandleBatchNormTraining( const Shape operand_shape = operand->shape(); PrimitiveType ptype = operand_shape.element_type(); int64 feature_index = batch_norm->feature_index(); - const int64 feature_count = operand_shape.dimensions(feature_index); - const int64 size_in_elements = ShapeUtil::ElementsIn(operand_shape); - int64 elements_per_feature_int64 = size_in_elements / feature_count; HloInstruction* scale = batch_norm->mutable_operand(1); HloInstruction* offset = batch_norm->mutable_operand(2); @@ -220,6 +235,9 @@ Status BatchNormExpanderVisitor::HandleBatchNormTraining( } } + auto elements_per_feature = + add(DynamicElementCountPerFeature(operand, feature_index, add)); + auto scale_broadcasted = add( HloInstruction::CreateBroadcast(operand_shape, scale, {feature_index})); @@ -243,13 +261,13 @@ Status BatchNormExpanderVisitor::HandleBatchNormTraining( add_reduce_computation)); // E[X]. - auto mean = add(Mean(elements_per_feature_int64, sum, add)); + auto mean = add(Mean(elements_per_feature, sum, add)); auto mean_broadcasted = add( HloInstruction::CreateBroadcast(operand_shape, mean, {feature_index})); // E[X^2]. - auto square_mean = add(Mean(elements_per_feature_int64, squared_sum, add)); + auto square_mean = add(Mean(elements_per_feature, squared_sum, add)); // E^2[X]. auto mean_square = @@ -458,9 +476,8 @@ Status BatchNormExpanderVisitor::HandleBatchNormGrad( int64 feature_index = batch_norm->feature_index(); - const int64 size_in_elements = ShapeUtil::ElementsIn(activation_shape); - const int64 feature_count = activation_shape.dimensions(feature_index); - const int64 elements_per_feature_int64 = size_in_elements / feature_count; + auto elements_per_feature = + add(DynamicElementCountPerFeature(activation, feature_index, add)); auto zero_literal = LiteralUtil::CreateR0(0.0f); TF_ASSIGN_OR_RETURN(zero_literal, zero_literal.Convert(ptype)); @@ -553,15 +570,9 @@ Status BatchNormExpanderVisitor::HandleBatchNormGrad( add_binary(activation_shape, HloOpcode::kMultiply, scale_broadcasted, rsqrt_var_add_epsilon_broadcasted); - scale_times_rsqrt_var_add_epsilon = add( - Mean(elements_per_feature_int64, scale_times_rsqrt_var_add_epsilon, add)); + scale_times_rsqrt_var_add_epsilon = + add(Mean(elements_per_feature, scale_times_rsqrt_var_add_epsilon, add)); - auto elements_per_feature_literal = - LiteralUtil::CreateR0(elements_per_feature_int64); - TF_ASSIGN_OR_RETURN(elements_per_feature_literal, - elements_per_feature_literal.Convert(ptype)); - auto elements_per_feature = add( - HloInstruction::CreateConstant(std::move(elements_per_feature_literal))); auto i1 = add_binary(activation_shape, HloOpcode::kMultiply, grad_output, add(HloInstruction::CreateBroadcast( activation_shape, elements_per_feature, {}))); diff --git a/tensorflow/compiler/xla/service/batchnorm_expander_test.cc b/tensorflow/compiler/xla/service/batchnorm_expander_test.cc index 08cf802617..8e8fbbd935 100644 --- a/tensorflow/compiler/xla/service/batchnorm_expander_test.cc +++ b/tensorflow/compiler/xla/service/batchnorm_expander_test.cc @@ -36,7 +36,21 @@ limitations under the License. namespace xla { namespace { -using BatchNormExpanderTest = HloTestBase; +class BatchNormExpanderTest : public HloTestBase { + protected: + // BatchNorm should have a dynamic sized dividor for mean operations. + int64 CountGetDimensionSize(const HloModule& module) { + int64 count = 0; + for (HloComputation* comp : module.computations()) { + for (HloInstruction* inst : comp->instructions()) { + if (inst->opcode() == HloOpcode::kGetDimensionSize) { + count++; + } + } + } + return count; + } +}; // Test that we expand BatchNormTraining. TEST_F(BatchNormExpanderTest, BatchNormTraining) { @@ -68,6 +82,7 @@ TEST_F(BatchNormExpanderTest, BatchNormTraining) { /*rewrite_grad_op=*/true); ASSERT_TRUE(rewriter.Run(module.get()).ValueOrDie()); root = computation->root_instruction(); + EXPECT_EQ(CountGetDimensionSize(*module), 3); // Make sure this operation is expanded. EXPECT_EQ(root->opcode(), HloOpcode::kTuple); } @@ -110,6 +125,7 @@ TEST_F(BatchNormExpanderTest, BatchNormGrad) { /*rewrite_grad_op=*/true); ASSERT_TRUE(rewriter.Run(module.get()).ValueOrDie()); root = computation->root_instruction(); + EXPECT_EQ(CountGetDimensionSize(*module), 3); // Make sure this operation is expanded. EXPECT_EQ(root->opcode(), HloOpcode::kTuple); } diff --git a/tensorflow/compiler/xla/service/buffer_assignment.cc b/tensorflow/compiler/xla/service/buffer_assignment.cc index 40c012a5e4..8d7c624478 100644 --- a/tensorflow/compiler/xla/service/buffer_assignment.cc +++ b/tensorflow/compiler/xla/service/buffer_assignment.cc @@ -746,8 +746,7 @@ StatusOr> BufferAssigner::Run( LogicalBuffer::AlignmentFunction color_alignment, bool allow_input_output_aliasing, bool allocate_buffers_for_constants, BufferLiveness::Colorer colorer, ReuseAllocationFunction reuse_checker) { - BufferAssigner assigner(allow_input_output_aliasing, - allocate_buffers_for_constants, std::move(colorer), + BufferAssigner assigner(allocate_buffers_for_constants, std::move(colorer), std::move(reuse_checker)); return assigner.CreateAssignment(module, std::move(hlo_ordering), std::move(buffer_size), @@ -1434,33 +1433,40 @@ BufferAssigner::MergeColocatedBufferSets( computation == module->entry_computation(); }; + std::vector set_can_be_merged(colocated_buffer_sets.size(), true); + + // Do not merge if one of the sets includes live outs, entry parameters or + // constants. + // + // Buffer liveness does not report the correct live range for entry + // parameter and live out buffers so we have to special case them here. On + // backends that support constant buffer allocations, constant buffers are + // assigned globals in readonly storage so we can't merge colocated buffer + // sets containing constants with colocated buffer sets containing writing + // instructions or other constants. + // + // Moreover (on the CPU/GPU backends) the entry parameter buffers belong to + // the caller of the executable so we can't write to entry parameters + // either, and the argument for not merging constants also applies to entry + // parameters. + for (int64 i = 0; i < colocated_buffer_sets.size(); ++i) { + for (auto& buffer : colocated_buffer_sets[i]) { + if (buffer_liveness.MaybeLiveOut(*buffer) || + is_entry_parameter(*buffer) || + buffer->instruction()->opcode() == HloOpcode::kConstant) { + set_can_be_merged[i] = false; + break; + } + } + } + // Returns true if the two colocated buffer sets (specified by their indices // into the colocated_buffer_sets) can be merged into a single set. auto cannot_merge_buffer_sets = [&colocated_buffer_sets, &buffer_liveness, &buffer_size, - &is_entry_parameter](int64 i, int64 j) { - // Do not merge if one of the sets includes live outs, entry parameters or - // constants. - // - // Buffer liveness does not report the correct live range for entry - // parameter and live out buffers so we have to special case them here. On - // backends that support constant buffer allocations, constant buffers are - // assigned globals in readonly storage so we can't merge colocated buffer - // sets containing constants with colocated buffer sets containing writing - // instructions or other constants. - // - // Moreover (on the CPU/GPU backends) the entry parameter buffers belong to - // the caller of the executable so we can't write to entry parameters - // either, and the argument for not merging constants also applies to entry - // parameters. - for (int64 key : {i, j}) { - for (auto& buffer : colocated_buffer_sets[key]) { - if (buffer_liveness.MaybeLiveOut(*buffer) || - is_entry_parameter(*buffer) || - buffer->instruction()->opcode() == HloOpcode::kConstant) { - return true; - } - } + &set_can_be_merged](int64 i, int64 j) { + if (!set_can_be_merged[i] || !set_can_be_merged[j]) { + return true; } // Colocated sets satisfy the invariant that all buffers within a set have diff --git a/tensorflow/compiler/xla/service/buffer_assignment.h b/tensorflow/compiler/xla/service/buffer_assignment.h index d8e1612b89..0a9fdede80 100644 --- a/tensorflow/compiler/xla/service/buffer_assignment.h +++ b/tensorflow/compiler/xla/service/buffer_assignment.h @@ -545,12 +545,10 @@ class BufferAssigner { ReuseAllocationFunction reuse_checker = nullptr); private: - BufferAssigner(bool allow_input_output_aliasing, - bool allocate_buffers_for_constants, + BufferAssigner(bool allocate_buffers_for_constants, BufferLiveness::Colorer colorer, ReuseAllocationFunction reuse_checker) - : allow_input_output_aliasing_(allow_input_output_aliasing), - allocate_buffers_for_constants_(allocate_buffers_for_constants), + : allocate_buffers_for_constants_(allocate_buffers_for_constants), colorer_(colorer), reuse_checker_(reuse_checker) {} virtual ~BufferAssigner() = default; @@ -640,10 +638,6 @@ class BufferAssigner { LogicalBuffer::Color::Hasher> SplitBuffersByColor(const absl::flat_hash_set& buffers); - // If true, buffer assignments assumes that input parameter buffers and output - // buffers can be shared if their sizes match. - bool allow_input_output_aliasing_; - // If true, allocate buffers for constant instructions. bool allocate_buffers_for_constants_; diff --git a/tensorflow/compiler/xla/service/buffer_assignment_test.cc b/tensorflow/compiler/xla/service/buffer_assignment_test.cc index b1fc50cb18..8f482e6ba8 100644 --- a/tensorflow/compiler/xla/service/buffer_assignment_test.cc +++ b/tensorflow/compiler/xla/service/buffer_assignment_test.cc @@ -137,8 +137,7 @@ class BufferAssignmentTest : public HloTestBase { } std::unique_ptr RunBufferAssignmentWithInstructionSequence( - HloModule* module, - absl::Span instruction_sequence, + HloModule* module, absl::Span instruction_sequence, int64 alignment = 1) { HloSchedule schedule(module); schedule.set_sequence(module->entry_computation(), instruction_sequence); @@ -1853,7 +1852,7 @@ class WhileBufferAssignmentTest : public HloTestBase { std::unique_ptr RunBufferAssignment(HloModule* module, int64 alignment = 1) { HloSchedule schedule = - ScheduleModule(*module, ByteSizeOf).ConsumeValueOrDie(); + ScheduleModule(module, ByteSizeOf).ConsumeValueOrDie(); return BufferAssigner::Run( module, absl::make_unique(schedule), ByteSizeOf, @@ -2162,7 +2161,7 @@ TEST_F(WhileBufferAssignmentTest, ColocatedBuffers) { // nodes are traversed during BufferAssignment. TF_ASSERT_OK_AND_ASSIGN( HloSchedule schedule, - ScheduleModule(*module, [](const BufferValue& buffer) { + ScheduleModule(module.get(), [](const BufferValue& buffer) { return ShapeUtil::ByteSizeOf(buffer.shape(), /*pointer_size=*/sizeof(void*)); })); @@ -2391,15 +2390,16 @@ TEST_F(WhileBufferAssignmentTest, WhileLoopsInterferingResultRange) { RunCopyInsertion(module.get()); HloSchedule schedule = - ScheduleModule(*module, ByteSizeOf).ConsumeValueOrDie(); + ScheduleModule(module.get(), ByteSizeOf).ConsumeValueOrDie(); // To trigger b/38494731, we want a specific Hlo schedule for the // root computation, so we overwrite that entry with a manually // crafted sequence. - schedule.set_sequence(module->entry_computation(), - {input1, weights1, one, output1, while1->operand(0), - while1, input0, weights0, zero, output0, - while0->operand(0), while0, gte0, gte1, root_add}); + schedule.set_sequence( + module->entry_computation(), + {input1, weights1, one, output1, while1->mutable_operand(0), while1, + input0, weights0, zero, output0, while0->mutable_operand(0), while0, + gte0, gte1, root_add}); // If this ASSERT fails, we constructed a bogus sequence above and this test // itself is buggy. diff --git a/tensorflow/compiler/xla/service/buffer_liveness_test.cc b/tensorflow/compiler/xla/service/buffer_liveness_test.cc index aeee543e84..40825a7871 100644 --- a/tensorflow/compiler/xla/service/buffer_liveness_test.cc +++ b/tensorflow/compiler/xla/service/buffer_liveness_test.cc @@ -117,7 +117,7 @@ TEST_F(BufferLivenessTest, ElementwiseChain) { auto log = builder.AddInstruction( HloInstruction::CreateUnary(vec_, HloOpcode::kLog, exp)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); auto liveness = @@ -164,7 +164,7 @@ TEST_F(BufferLivenessTest, MultipleEntryParameters_Sequential) { auto add = builder.AddInstruction( HloInstruction::CreateBinary(vec_, HloOpcode::kAdd, negate, exp)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* entry = module->AddEntryComputation(builder.Build()); HloSchedule schedule(module.get()); @@ -213,7 +213,7 @@ TEST_F(BufferLivenessTest, NonElementwiseOperand) { auto reverse = builder.AddInstruction(HloInstruction::CreateReverse(vec_, negate, {0})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); auto liveness = @@ -247,7 +247,7 @@ TEST_F(BufferLivenessTest, OverlappedBuffers) { auto add = builder.AddInstruction( HloInstruction::CreateBinary(vec_, HloOpcode::kAdd, negate, exp)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); auto liveness = @@ -289,7 +289,7 @@ TEST_F(BufferLivenessTest, OverlappedBuffersSequentialOrder) { auto add = builder.AddInstruction( HloInstruction::CreateBinary(vec_, HloOpcode::kAdd, negate, exp)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); HloSchedule schedule(module.get()); @@ -336,7 +336,7 @@ TEST_F(BufferLivenessTest, RootInstructionIsNotLastInSequentialOrder) { HloInstruction::CreateSend(recv_done, token, /*channel_id=*/1)); auto send_done = builder.AddInstruction(HloInstruction::CreateSendDone(send)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build(add)); HloSchedule schedule(module.get()); @@ -373,7 +373,7 @@ TEST_F(BufferLivenessTest, TupleLiveOut) { auto outer_tuple = builder.AddInstruction(HloInstruction::CreateTuple({inner_tuple, exp})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); auto liveness = @@ -393,7 +393,7 @@ TEST_F(BufferLivenessTest, TupleLiveOut) { TEST_F(BufferLivenessTest, EmbeddedComputation) { // Test MaybeLiveOut and MayInterfere for embedded computation. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto embedded_builder = HloComputation::Builder(TestName() + "_embedded"); auto embedded_param = embedded_builder.AddInstruction( @@ -450,7 +450,7 @@ TEST_F(BufferLivenessTest, TupleConstantLiveOut) { builder.AddInstruction(HloInstruction::CreateGetTupleElement( inner_tuple0.shape(), tuple_constant, 0)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); auto liveness = @@ -576,7 +576,7 @@ TEST_F(BufferLivenessTest, DependentTupleElements) { auto tuple_root = builder.AddInstruction(HloInstruction::CreateTuple({add0, add1})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(BuildDummyComputation()); module->AddEmbeddedComputation(builder.Build()); @@ -611,8 +611,8 @@ TEST_F(BufferLivenessTest, DependentTupleElements) { class FusedDynamicUpdateSliceLivenessTest : public BufferLivenessTest { protected: // Builds and runs a computation (see test case computation graphs below). - std::unique_ptr BuildModule(const bool update_uses_tuple_element1, - const bool fuse_gte0) { + std::unique_ptr BuildModule( + const bool update_uses_tuple_element1, const bool fuse_gte0) { auto builder = HloComputation::Builder(TestName()); // Create param0 Tuple. Shape data_shape = ShapeUtil::MakeShape(F32, {8}); @@ -646,7 +646,7 @@ class FusedDynamicUpdateSliceLivenessTest : public BufferLivenessTest { builder.AddInstruction( HloInstruction::CreateTuple({gte0, dynamic_update_slice})); // Build module and get reference to entry computation. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); auto* computation = module->entry_computation(); // Create fusion instruction based on number of tuple element 1 users. @@ -802,7 +802,7 @@ class DynamicUpdateSliceLivenessTest : public BufferLivenessTest { auto tuple_root = builder.AddInstruction( HloInstruction::CreateTuple({gte0, dynamic_update_slice})); // Build module and get reference to entry computation. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(BuildDummyComputation()); module->AddEmbeddedComputation(builder.Build()); // Run BufferLiveness on 'module'. diff --git a/tensorflow/compiler/xla/service/call_graph.cc b/tensorflow/compiler/xla/service/call_graph.cc index bdd5069632..7987343bfa 100644 --- a/tensorflow/compiler/xla/service/call_graph.cc +++ b/tensorflow/compiler/xla/service/call_graph.cc @@ -325,6 +325,15 @@ bool CallGraph::IsFlattened() const { return true; } +std::vector CallGraph::GetComputationCallers( + HloComputation* c) { + std::vector callers; + for (auto callsite : GetNode(c).caller_callsites()) { + callers.push_back(callsite.instruction()); + } + return callers; +} + std::pair CallGraph::NearestAncestorsInSameComputation(HloInstruction* a, HloInstruction* b) const { diff --git a/tensorflow/compiler/xla/service/call_graph.h b/tensorflow/compiler/xla/service/call_graph.h index cb56f4789d..05c7c99873 100644 --- a/tensorflow/compiler/xla/service/call_graph.h +++ b/tensorflow/compiler/xla/service/call_graph.h @@ -236,6 +236,10 @@ class CallGraph { // FlattenCallGraph. bool IsFlattened() const; + // Returns a vector of instructions calling the passed computation. + // (Often a vector of size 1.) + std::vector GetComputationCallers(HloComputation* c); + string ToString() const; private: diff --git a/tensorflow/compiler/xla/service/compile_only_service.cc b/tensorflow/compiler/xla/service/compile_only_service.cc index 67132274c0..1965925fa7 100644 --- a/tensorflow/compiler/xla/service/compile_only_service.cc +++ b/tensorflow/compiler/xla/service/compile_only_service.cc @@ -86,15 +86,15 @@ CompileOnlyService::CompileAheadOfTime( Executable::DumpToDirectory(per_host_path, filename, hlo_snapshot)); } - const auto& program_shape = instance.computation.host_program_shape(); ExecutionOptions execution_options; *execution_options.mutable_debug_options() = debug_options; *execution_options.mutable_shape_with_output_layout() = - *instance.result_layout; + instance.result_layout->ToProto(); TF_ASSIGN_OR_RETURN( std::unique_ptr module_config, - CreateModuleConfig(program_shape, instance.argument_layouts, - &execution_options)); + CreateModuleConfig( + ProgramShape(instance.computation.host_program_shape()), + instance.argument_layouts, &execution_options)); TF_ASSIGN_OR_RETURN( std::unique_ptr hlo_module, diff --git a/tensorflow/compiler/xla/service/computation_placer.h b/tensorflow/compiler/xla/service/computation_placer.h index c899ffb9dc..844b42a38d 100644 --- a/tensorflow/compiler/xla/service/computation_placer.h +++ b/tensorflow/compiler/xla/service/computation_placer.h @@ -105,8 +105,6 @@ class ComputationPlacer { // Map from platform kind to computation placer singleton. static std::map* GetPlatformComputationPlacers(); - se::Platform::Id platform_id_; - TF_DISALLOW_COPY_AND_ASSIGN(ComputationPlacer); }; diff --git a/tensorflow/compiler/xla/service/convolution_feature_group_converter.cc b/tensorflow/compiler/xla/service/convolution_feature_group_converter.cc index 7f7f1503a0..95c7724c3c 100644 --- a/tensorflow/compiler/xla/service/convolution_feature_group_converter.cc +++ b/tensorflow/compiler/xla/service/convolution_feature_group_converter.cc @@ -142,16 +142,16 @@ std::vector GetMaskIds(int64 group_size, int64 group_count) { // Finally we use the Eq op of these two broadcasted constants and get the // desired mask. HloInstruction* GetExpandedFilterMask( - const Shape& filter_shape, int64 input_feature_dim, - int64 output_feature_dim, int64 group_count, + const Shape& filter_shape, int64 kernel_input_feature_dim, + int64 kernel_output_feature_dim, int64 group_count, const std::function)>& add_instruction) { Shape expanded_filter_shape = - ExpandedFilterShape(filter_shape, group_count, input_feature_dim); + ExpandedFilterShape(filter_shape, group_count, kernel_input_feature_dim); Shape mask_shape = ShapeUtil::MakeShape( S32, AsInt64Slice(expanded_filter_shape.dimensions())); - int64 output_feature = filter_shape.dimensions(output_feature_dim); - int64 group_size = filter_shape.dimensions(input_feature_dim); + int64 output_feature = filter_shape.dimensions(kernel_output_feature_dim); + int64 group_size = filter_shape.dimensions(kernel_input_feature_dim); // Create a 'input_feature' sized linspace and 'output_feature' sized linspace // that will be broadcasted into perpendicular dimensions and compared. @@ -159,15 +159,14 @@ HloInstruction* GetExpandedFilterMask( GetMaskIds(group_size, group_count); const std::vector output_feature_filter_mask = GetMaskIds(output_feature / group_count, group_count); - auto mask1 = add_instruction(HloInstruction::CreateConstant( LiteralUtil::CreateR1(input_feature_filter_mask))); - auto broadcasted_mask1 = add_instruction( - HloInstruction::CreateBroadcast(mask_shape, mask1, {input_feature_dim})); + auto broadcasted_mask1 = add_instruction(HloInstruction::CreateBroadcast( + mask_shape, mask1, {kernel_input_feature_dim})); auto mask2 = add_instruction(HloInstruction::CreateConstant( LiteralUtil::CreateR1(output_feature_filter_mask))); - auto broadcasted_mask2 = add_instruction( - HloInstruction::CreateBroadcast(mask_shape, mask2, {output_feature_dim})); + auto broadcasted_mask2 = add_instruction(HloInstruction::CreateBroadcast( + mask_shape, mask2, {kernel_output_feature_dim})); // Compare the broadcasted output feature linspace to the input feature // linspace to create a diagonal predicate. @@ -189,91 +188,203 @@ Status ConvolutionVisitor::HandleConvolution(HloInstruction* convolution) { }; auto dim_numbers = convolution->convolution_dimension_numbers(); - int64 input_feature_dim = dim_numbers.kernel_input_feature_dimension(); - int64 group_size = filter->shape().dimensions(input_feature_dim); - int64 output_feature_dim = dim_numbers.kernel_output_feature_dimension(); - auto expanded_filter_shape = - ExpandedFilterShape(filter->shape(), group_count, input_feature_dim); - HloInstruction* filter_mask = GetExpandedFilterMask( - filter->shape(), input_feature_dim, output_feature_dim, group_count, add); + int64 kernel_input_feature_dim = dim_numbers.kernel_input_feature_dimension(); + int64 group_size = filter->shape().dimensions(kernel_input_feature_dim); + int64 kernel_output_feature_dim = + dim_numbers.kernel_output_feature_dimension(); + auto expanded_filter_shape = ExpandedFilterShape(filter->shape(), group_count, + kernel_input_feature_dim); + HloInstruction* filter_mask = + GetExpandedFilterMask(filter->shape(), kernel_input_feature_dim, + kernel_output_feature_dim, group_count, add); HloInstruction* expanded_filter; if (group_size == 1) { bool depthwise_separable = - (group_count == filter->shape().dimensions(output_feature_dim)); + (group_count == filter->shape().dimensions(kernel_output_feature_dim)); // If the code generator handles depthwise separable convolutions // inherently, then no filter expansion is needed. if (!filter_expansion_ && depthwise_separable) { - const int64 old_kernel_input_feature_dimension = - dim_numbers.kernel_input_feature_dimension(); - const int64 old_kernel_output_feature_dimension = - dim_numbers.kernel_output_feature_dimension(); - - // For depthwise convolutions, we want the kernel input feature dimension - // to be smaller than the output feature dimension. If that's not the - // case, we swap the dimensions. - if (old_kernel_input_feature_dimension > - old_kernel_output_feature_dimension) { - Shape reshaped_filter_shape = filter->shape(); - auto& dimensions = *reshaped_filter_shape.mutable_dimensions(); - std::swap(dimensions[old_kernel_input_feature_dimension], - dimensions[old_kernel_output_feature_dimension]); - - auto reshaped_filter = - add(HloInstruction::CreateReshape(reshaped_filter_shape, filter)); - - dim_numbers.set_kernel_input_feature_dimension( - old_kernel_output_feature_dimension); - - dim_numbers.set_kernel_output_feature_dimension( - old_kernel_input_feature_dimension); - - auto new_convolution = HloInstruction::CreateConvolve( - convolution->shape(), convolution->mutable_operand(0), - reshaped_filter, group_count, convolution->window(), dim_numbers, - convolution->precision_config()); - - TF_RETURN_IF_ERROR(computation_->ReplaceWithNewInstruction( - convolution, std::move(new_convolution))); - } return Status::OK(); } // We want to repeat 'filter' in the 'input_feature_dim' dimension // 'group_count' times. Shape reshaped_filter_shape = - ShapeUtil::DeleteDimension(input_feature_dim, filter->shape()); + ShapeUtil::DeleteDimension(kernel_input_feature_dim, filter->shape()); auto reshaped_filter = add(HloInstruction::CreateReshape(reshaped_filter_shape, filter)); std::vector broadcast_dims; for (int64 i = 0; i < filter->shape().dimensions_size(); ++i) { - if (i == input_feature_dim) { + if (i == kernel_input_feature_dim) { continue; } broadcast_dims.push_back(i); } expanded_filter = add(HloInstruction::CreateBroadcast( expanded_filter_shape, reshaped_filter, broadcast_dims)); + + auto zero = add(HloInstruction::CreateConstant( + LiteralUtil::Zero(expanded_filter_shape.element_type()))); + auto zero_filter = + add(HloInstruction::CreateBroadcast(expanded_filter_shape, zero, {})); + auto new_filter = add(HloInstruction::CreateTernary( + expanded_filter_shape, HloOpcode::kSelect, filter_mask, expanded_filter, + zero_filter)); + + auto new_convolution = HloInstruction::CreateConvolve( + convolution->shape(), convolution->mutable_operand(0), new_filter, + /*feature_group_count=*/1, convolution->window(), dim_numbers, + convolution->precision_config()); + TF_RETURN_IF_ERROR(computation_->ReplaceWithNewInstruction( + convolution, std::move(new_convolution))); } else { - // We could possibly also use reshape, broadcast, reshape instead of concat - // here, but it would require more complex code, and for depthwise - // convolution we would never end up in this branch. - std::vector concat_operands(group_count, filter); - expanded_filter = add(HloInstruction::CreateConcatenate( - expanded_filter_shape, concat_operands, input_feature_dim)); + int64 activation_input_feature_dim = dim_numbers.input_feature_dimension(); + + int64 output_feature = + filter->shape().dimensions(kernel_output_feature_dim); + + // If group_count == output_feature, then we map those grouped convolutions + // onto depthwise convolution. This is done by adding an additional spatial + // dimension to the activations, kernel, and the output. + // E.g., we would turn + // [2, 12]{B, IF} conv [3, 4]{IF, OF} into + // [3, 2, 4]{S, B, IF} depth conv [3, 1, 4]{S, IF, OF}, where S is the + // additional spatial dimension. The generated convolution output will be + // [1, 2, 4]{S, B, OF} and then reshape the output back to [2, 4] {B, OF}. + + if (group_count == output_feature && !filter_expansion_) { + auto filter = convolution->mutable_operand(1); + auto activation = convolution->mutable_operand(0); + + // Add spatial dimension to the activation, and reshape. + Shape reshaped_activation_shape = activation->shape(); + ShapeUtil::AppendMajorDimension(group_size, &reshaped_activation_shape); + + int64 new_spatial_dim = reshaped_activation_shape.dimensions().size() - 1; + + reshaped_activation_shape.set_dimensions(activation_input_feature_dim, + group_count); + activation = add( + HloInstruction::CreateReshape(reshaped_activation_shape, activation)); + + // Add spatial dimension to the filter, and reshape. + Shape reshaped_filter_shape = filter->shape(); + ShapeUtil::AppendMajorDimension(1, &reshaped_filter_shape); + + filter = + add(HloInstruction::CreateReshape(reshaped_filter_shape, filter)); + + Shape new_output_shape = convolution->shape(); + ShapeUtil::AppendMajorDimension(1, &new_output_shape); + + // Edit convolution dimension numbers. Note that kernel_input_feature_dim + // now becomes a spatial dimension, and the newly added dimension of size + // 1 is the new kernel_input_feature_dim. + dim_numbers.add_input_spatial_dimensions(new_spatial_dim); + dim_numbers.add_kernel_spatial_dimensions(kernel_input_feature_dim); + dim_numbers.set_kernel_input_feature_dimension(new_spatial_dim); + dim_numbers.add_output_spatial_dimensions(new_spatial_dim); + + // Add window for the new spatial dimension. + Window new_window = convolution->window(); + auto* dim = new_window.add_dimensions(); + dim->set_window_dilation(1); + dim->set_base_dilation(1); + dim->set_stride(1); + dim->set_size(group_size); + + auto new_convolution = add(HloInstruction::CreateConvolve( + new_output_shape, activation, filter, group_count, new_window, + dim_numbers, convolution->precision_config())); + + // Delete the extra spatial dimension, and reshape. + Shape reshaped_convolution_shape = + ShapeUtil::DeleteDimension(new_spatial_dim, new_convolution->shape()); + auto reshaped_convolution = HloInstruction::CreateReshape( + reshaped_convolution_shape, new_convolution); + + TF_RETURN_IF_ERROR(computation_->ReplaceWithNewInstruction( + convolution, std::move(reshaped_convolution))); + + } else { + // The filter expansion mechanism adds zeroes in the kernel. + // For an OF = 12, IF = 6, and kernel IF = 2, the expanded filter mask + // would look like (IF on the Y-axis, OF on the X-axis) + // 1 1 1 1 0 0 0 0 0 0 0 0 + // 1 1 1 1 0 0 0 0 0 0 0 0 + // 0 0 0 0 1 1 1 1 0 0 0 0 + // 0 0 0 0 1 1 1 1 0 0 0 0 + // 0 0 0 0 0 0 0 0 1 1 1 1 + // 0 0 0 0 0 0 0 0 1 1 1 1 + // + // Instead of convolving the above with the input, we instead slice the + // kernel into three kernels, each containing islands of 1s from the + // filter above. We also slice the activations in the IF dimension with + // each slice of size = group_size. For each slice, we perform + // convolutions, and concatenate the generated outputs in the output OF + // dimension. + + std::vector sliced_convolutions; + auto activation = convolution->mutable_operand(0); + std::vector slice_strides(filter->shape().dimensions_size(), 1); + std::vector filter_slice_starts(filter->shape().dimensions_size(), + 0); + std::vector filter_slice_limits( + filter->shape().dimensions().begin(), + filter->shape().dimensions().end()); + std::vector activation_slice_starts( + activation->shape().dimensions_size(), 0); + std::vector activation_slice_limits( + activation->shape().dimensions().begin(), + activation->shape().dimensions().end()); + + int64 output_feature = + filter->shape().dimensions(kernel_output_feature_dim); + auto output_feature_dim = dim_numbers.output_feature_dimension(); + int64 filter_slice_width = output_feature / group_count; + + int64 activation_input_feature_dim = + dim_numbers.input_feature_dimension(); + + for (int64 i = 0; i < group_count; i++) { + filter_slice_starts[kernel_output_feature_dim] = i * filter_slice_width; + filter_slice_limits[kernel_output_feature_dim] = + (i + 1) * filter_slice_width; + auto filter_sliced_shape = filter->shape(); + filter_sliced_shape.set_dimensions(kernel_output_feature_dim, + filter_slice_width); + auto filter_slice = add(HloInstruction::CreateSlice( + filter_sliced_shape, filter, filter_slice_starts, + filter_slice_limits, slice_strides)); + + activation_slice_starts[activation_input_feature_dim] = i * group_size; + activation_slice_limits[activation_input_feature_dim] = + (i + 1) * group_size; + auto activation_sliced_shape = activation->shape(); + activation_sliced_shape.set_dimensions(activation_input_feature_dim, + group_size); + auto activation_slice = add(HloInstruction::CreateSlice( + activation_sliced_shape, activation, activation_slice_starts, + activation_slice_limits, slice_strides)); + + auto conv_slice_shape = convolution->shape(); + conv_slice_shape.set_dimensions(output_feature_dim, filter_slice_width); + + auto new_convolution = add(HloInstruction::CreateConvolve( + conv_slice_shape, activation_slice, filter_slice, + /*feature_group_count=*/1, convolution->window(), dim_numbers, + convolution->precision_config())); + + sliced_convolutions.push_back(new_convolution); + } + + auto new_conv = HloInstruction::CreateConcatenate( + convolution->shape(), sliced_convolutions, output_feature_dim); + TF_RETURN_IF_ERROR(computation_->ReplaceWithNewInstruction( + convolution, std::move(new_conv))); + } } - auto zero = add(HloInstruction::CreateConstant( - LiteralUtil::Zero(expanded_filter_shape.element_type()))); - auto zero_filter = - add(HloInstruction::CreateBroadcast(expanded_filter_shape, zero, {})); - auto new_filter = add( - HloInstruction::CreateTernary(expanded_filter_shape, HloOpcode::kSelect, - filter_mask, expanded_filter, zero_filter)); - auto new_convolution = HloInstruction::CreateConvolve( - convolution->shape(), convolution->mutable_operand(0), new_filter, - /*feature_group_count=*/1, convolution->window(), dim_numbers, - convolution->precision_config()); - TF_RETURN_IF_ERROR(computation_->ReplaceWithNewInstruction( - convolution, std::move(new_convolution))); + return Status::OK(); } diff --git a/tensorflow/compiler/xla/service/convolution_feature_group_converter_test.cc b/tensorflow/compiler/xla/service/convolution_feature_group_converter_test.cc index 28373ebf63..e6bf2143a2 100644 --- a/tensorflow/compiler/xla/service/convolution_feature_group_converter_test.cc +++ b/tensorflow/compiler/xla/service/convolution_feature_group_converter_test.cc @@ -82,18 +82,14 @@ ENTRY %Convolve1D1Window_0.v3 (input: f32[1,2,4], filter: f32[1,2,2]) -> f32[1,2 ConvolutionFeatureGroupConverter converter; ASSERT_TRUE(converter.Run(module.get()).ValueOrDie()); root = computation->root_instruction(); - // Make sure the convolution is converted to one with feature_group_count = 1. - EXPECT_EQ(root->opcode(), HloOpcode::kConvolution); - EXPECT_EQ(root->feature_group_count(), 1); - // Verify that the filter operand has been replaced. - EXPECT_THAT(root->operand(1), - op::Select(op::Eq(op::Broadcast(op::Constant()), - op::Broadcast(op::Constant())), - // We expect to see Concatenate here instead of - // Broadcast, because feature_group_count < input - // feature dimension. - op::Concatenate(op::Parameter(), op::Parameter()), - op::Broadcast(op::Constant()))); + // Make sure the convolution is replaced with a concatenate. + EXPECT_EQ(root->opcode(), HloOpcode::kConcatenate); + // And the operands of the concatenate are convolutions, each with a feature + // group count = 1. + EXPECT_EQ(root->operand(0)->opcode(), HloOpcode::kConvolution); + EXPECT_EQ(root->operand(1)->opcode(), HloOpcode::kConvolution); + EXPECT_EQ(root->operand(0)->feature_group_count(), 1); + EXPECT_EQ(root->operand(1)->feature_group_count(), 1); } } // namespace diff --git a/tensorflow/compiler/xla/service/copy_insertion.cc b/tensorflow/compiler/xla/service/copy_insertion.cc index 4e547d925f..df60596638 100644 --- a/tensorflow/compiler/xla/service/copy_insertion.cc +++ b/tensorflow/compiler/xla/service/copy_insertion.cc @@ -442,7 +442,6 @@ class CopyRemover { const HloOrdering& ordering, HloModule* module) : module_(module), alias_analysis_(alias_analysis), - ordering_(ordering), buffer_value_tracker_(*module, alias_analysis, ordering) {} // Try to elide the given copy. The copy is elided if the instruction is not @@ -1003,7 +1002,6 @@ class CopyRemover { HloModule* module_; const HloAliasAnalysis& alias_analysis_; - const HloOrdering& ordering_; // Object tracking the HLO values contained in each HLO buffer. BufferValueTracker buffer_value_tracker_; diff --git a/tensorflow/compiler/xla/service/copy_insertion_test.cc b/tensorflow/compiler/xla/service/copy_insertion_test.cc index 7446bc7cc1..e4e9d7ba05 100644 --- a/tensorflow/compiler/xla/service/copy_insertion_test.cc +++ b/tensorflow/compiler/xla/service/copy_insertion_test.cc @@ -94,7 +94,7 @@ TEST_F(CopyInsertionTest, SingleParameter) { EXPECT_THAT(x->users(), UnorderedElementsAre(tuple)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); InsertCopies(module.get()); @@ -114,7 +114,7 @@ TEST_F(CopyInsertionTest, SingleConstant) { EXPECT_THAT(constant->users(), UnorderedElementsAre(tuple)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); InsertCopies(module.get()); @@ -127,7 +127,7 @@ TEST_F(CopyInsertionTest, SingleConstant) { TEST_F(CopyInsertionTest, ExistingCopiesNotRemoved) { // Verify that kCopy instructions which change layout and exist before // copy-insertion remain in the graph after copy-insertion. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto builder = HloComputation::Builder(TestName()); HloInstruction* constant = @@ -181,7 +181,7 @@ TEST_F(CopyInsertionTest, MultipleConstantsAndParameters) { builder.AddInstruction(HloInstruction::CreateTuple({constant2, x, add})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); InsertCopies(module.get()); @@ -217,7 +217,7 @@ TEST_F(CopyInsertionTest, AmbiguousPointsToSet) { EXPECT_THAT(constant2->users(), UnorderedElementsAre(tuple1, tuple2)); EXPECT_THAT(constant3->users(), UnorderedElementsAre(tuple2)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); HloInstruction* old_root = module->entry_computation()->root_instruction(); @@ -238,7 +238,7 @@ TEST_F(CopyInsertionTest, BitcastParameter) { HloInstruction* bitcast = builder.AddInstruction(HloInstruction::CreateUnary( ShapeUtil::MakeShape(F32, {2, 2}), HloOpcode::kBitcast, x)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); EXPECT_THAT(x->users(), UnorderedElementsAre(bitcast)); @@ -261,7 +261,7 @@ TEST_F(CopyInsertionTest, BitcastConstant) { HloInstruction* bitcast = builder.AddInstruction(HloInstruction::CreateUnary( ShapeUtil::MakeShape(F32, {2, 2}), HloOpcode::kBitcast, constant)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); EXPECT_THAT(constant->users(), UnorderedElementsAre(bitcast)); @@ -283,7 +283,7 @@ TEST_F(CopyInsertionTest, BitcastTupleElementParameter) { ShapeUtil::MakeShape(F32, {2, 2}), HloOpcode::kBitcast, x)); builder.AddInstruction(HloInstruction::CreateTuple({bitcast})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); EXPECT_THAT(x->users(), UnorderedElementsAre(bitcast)); @@ -310,7 +310,7 @@ TEST_F(CopyInsertionTest, NestedTupleParameter) { ShapeUtil::MakeShape(F32, {42})}), "param0")); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); EXPECT_EQ(HloOpcode::kParameter, @@ -351,7 +351,7 @@ TEST_F(CopyInsertionTest, ElementOfNestedTupleParameter) { auto gte = builder.AddInstruction(HloInstruction::CreateGetTupleElement( ShapeUtil::GetSubshape(param->shape(), {0}), param, 0)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); EXPECT_EQ(gte, module->entry_computation()->root_instruction()); @@ -388,7 +388,7 @@ TEST_F(CopyInsertionTest, AmbiguousTopLevelRoot) { builder.AddInstruction(HloInstruction::CreateGetTupleElement( ShapeUtil::GetSubshape(select->shape(), {0}), select, 0)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); EXPECT_EQ(gte, module->entry_computation()->root_instruction()); @@ -1295,7 +1295,7 @@ TEST_F(WhileCopyInsertionTest, InitPointsToNonDistinctUsedByTwoWhileLoops) { TEST_F(CopyInsertionTest, SwizzlingWhile) { // Test a while instruction with a body which permutes its tuple parameter // elements. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape loop_state_shape = ShapeUtil::MakeTupleShape({scalar_shape_, scalar_shape_}); @@ -1362,7 +1362,7 @@ TEST_F(CopyInsertionTest, CrossingParameters) { // | / \ | // | / \| // (p1 , p0) - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape tuple_shape = ShapeUtil::MakeTupleShape({scalar_shape_, scalar_shape_}); @@ -1395,7 +1395,7 @@ TEST_F(CopyInsertionTest, ParametersAliasing) { // | | // | | // (p0 , p1) - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape tuple_shape = ShapeUtil::MakeTupleShape({scalar_shape_, scalar_shape_}); @@ -1428,7 +1428,7 @@ TEST_F(CopyInsertionTest, ParameterWithNoAliasing) { // | | // | | // (p0 , p1) - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape tuple_shape = ShapeUtil::MakeTupleShape({scalar_shape_, scalar_shape_}); @@ -1461,7 +1461,7 @@ TEST_F(CopyInsertionTest, ParameterWithPartialAliasing) { // | | // | | // (p0 , p1) - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape tuple_shape = ShapeUtil::MakeTupleShape({scalar_shape_, scalar_shape_}); @@ -1496,7 +1496,7 @@ TEST_F(CopyInsertionTest, ParameterAndParallelOpsWithPartialAliasing) { // | | | // | | | // +-- (p0 , p1) - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape tuple_shape = ShapeUtil::MakeTupleShape({scalar_shape_, scalar_shape_}); @@ -1534,7 +1534,7 @@ TEST_F(CopyInsertionTest, ParameterAndOpsWithPartialAliasing) { // | Add----+ // | | | // +-- (p0 , p1) - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape tuple_shape = ShapeUtil::MakeTupleShape({scalar_shape_, scalar_shape_}); @@ -1569,7 +1569,7 @@ TEST_F(CopyInsertionTest, SwizzlingWhileWithOneOp) { // the operation (instruction) on the element makes the live range of the // respective input and output elements different than if the instruction were // not there (as in the SwizzlingWhile test above). - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape loop_state_shape = ShapeUtil::MakeTupleShape({scalar_shape_, scalar_shape_}); @@ -1632,7 +1632,7 @@ TEST_F(CopyInsertionTest, SwizzlingWhileSharedInput) { // the while body is a single constant (both loop state elements are the same // constant). This means no copies are necessary because both loop state // elements are the same so interchanging them is a no-op. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape loop_state_shape = ShapeUtil::MakeTupleShape({scalar_shape_, scalar_shape_}); @@ -1693,7 +1693,7 @@ TEST_F(CopyInsertionTest, SequentialWhiles) { const Shape loop_state_shape = ShapeUtil::MakeTupleShape( {element_shape, element_shape, element_shape, element_shape}); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto builder = HloComputation::Builder(TestName()); auto param_0 = builder.AddInstruction( HloInstruction::CreateParameter(0, element_shape, "param_0")); @@ -1783,7 +1783,7 @@ TEST_F(CopyInsertionTest, SequentialWhiles) { TEST_F(CopyInsertionTest, WhileBodyWithConstantRoot) { // Test a while body and condition which are each simply a constant (root of // computation is a constant). The body constant should be copied. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto builder = HloComputation::Builder(TestName()); auto param_0 = builder.AddInstruction( HloInstruction::CreateParameter(0, scalar_shape_, "param_0")); diff --git a/tensorflow/compiler/xla/service/cpu/BUILD b/tensorflow/compiler/xla/service/cpu/BUILD index 2763d18121..ce4c2a9cc6 100644 --- a/tensorflow/compiler/xla/service/cpu/BUILD +++ b/tensorflow/compiler/xla/service/cpu/BUILD @@ -96,6 +96,7 @@ cc_library( "@com_google_absl//absl/types:span", "//tensorflow/compiler/tf2xla:cpu_function_runtime", "//tensorflow/compiler/xla/service:map_inliner", + "//tensorflow/compiler/xla/service:hlo_get_dimension_size_rewriter", "//tensorflow/compiler/xla/service:scatter_expander", "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:protobuf_util", diff --git a/tensorflow/compiler/xla/service/cpu/compiler_functor.cc b/tensorflow/compiler/xla/service/cpu/compiler_functor.cc index 73b03440cb..796a7cf94d 100644 --- a/tensorflow/compiler/xla/service/cpu/compiler_functor.cc +++ b/tensorflow/compiler/xla/service/cpu/compiler_functor.cc @@ -61,19 +61,6 @@ Disabling these as a starting point. // TODO(b/64227304) Creating a custom pass pipeline will replace this. namespace { -class FilteredFunctionPassManager : public llvm::legacy::FunctionPassManager { - public: - FilteredFunctionPassManager(llvm::Module* m, bool disable_expensive_passes) - : llvm::legacy::FunctionPassManager(m), - disable_expensive_passes_(disable_expensive_passes) {} - void add(llvm::Pass* p) override { - llvm::legacy::FunctionPassManager::add(p); - } - - private: - bool disable_expensive_passes_; -}; - class FilteredPassManager : public llvm::legacy::PassManager { public: explicit FilteredPassManager(bool disable_expensive_passes) @@ -96,8 +83,7 @@ class FilteredPassManager : public llvm::legacy::PassManager { std::unique_ptr CompilerFunctor::operator()( llvm::Module& module) const { FilteredPassManager module_passes(disable_expensive_passes_); - FilteredFunctionPassManager function_passes(&module, - disable_expensive_passes_); + llvm::legacy::FunctionPassManager function_passes(&module); VLOG(2) << "IR before optimizations"; XLA_VLOG_LINES(2, llvm_ir::DumpModuleToString(module)); diff --git a/tensorflow/compiler/xla/service/cpu/cpu_compiler.cc b/tensorflow/compiler/xla/service/cpu/cpu_compiler.cc index 4ce5a8a292..6374822c81 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_compiler.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_compiler.cc @@ -76,6 +76,7 @@ limitations under the License. #include "tensorflow/compiler/xla/service/hlo_cse.h" #include "tensorflow/compiler/xla/service/hlo_dce.h" #include "tensorflow/compiler/xla/service/hlo_element_type_converter.h" +#include "tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.h" #include "tensorflow/compiler/xla/service/hlo_instruction.h" #include "tensorflow/compiler/xla/service/hlo_memory_scheduler.h" #include "tensorflow/compiler/xla/service/hlo_opcode.h" @@ -268,10 +269,11 @@ Status CpuCompiler::RunHloPassesThroughLayoutAssn( /*rewrite_training_op=*/true, /*rewrite_inference_op=*/true, /*rewrite_grad_op=*/true); - pass.AddPass( - /*is_layout_sensitive=*/false, - [](const Shape&, const Shape&) { return false; }, - /*enable_dot_strength_reduction=*/false); + pipeline.AddPass(); + AlgebraicSimplifierOptions options( + [](const Shape&, const Shape&) { return false; }); + options.set_enable_dot_strength_reduction(false); + pass.AddPass(options); pass.AddPass(); // BatchNormExpander can create zero-sized ops, so zero-sized HLO @@ -334,10 +336,11 @@ Status CpuCompiler::RunHloPassesAfterLayoutAssn( pass.AddInvariantChecker( /*layout_sensitive=*/true, /*allow_mixed_precision=*/false); - pass.AddPass>( - /*is_layout_sensitive=*/true, - [](const Shape&, const Shape&) { return true; }, - /*enable_dot_strength_reduction=*/false); + AlgebraicSimplifierOptions options( + [](const Shape&, const Shape&) { return true; }); + options.set_is_layout_sensitive(true); + options.set_enable_dot_strength_reduction(false); + pass.AddPass>(options); pass.AddPass(); pass.AddPass(/*is_layout_sensitive=*/true); } @@ -587,9 +590,9 @@ StatusOr> CpuCompiler::RunBackend( // Select an order for emitting the HLO instructions for each // computation. Using this sequence enables tighter buffer liveness analysis // and reduced memory usage (as compared to using DependencyHloOrdering). - TF_ASSIGN_OR_RETURN( - HloSchedule schedule, - ScheduleModule(*module, BufferSizeBytesFunction(), DFSMemoryScheduler)); + TF_ASSIGN_OR_RETURN(HloSchedule schedule, + ScheduleModule(module.get(), BufferSizeBytesFunction(), + DFSMemoryScheduler)); // Run buffer allocation on the HLO graph. TF_ASSIGN_OR_RETURN( @@ -779,7 +782,7 @@ CpuCompiler::CompileAheadOfTime(std::unique_ptr module_group, XLA_VLOG_LINES(2, module->ToString()); TF_ASSIGN_OR_RETURN(HloSchedule schedule, - ScheduleModule(*module, BufferSizeBytesFunction())); + ScheduleModule(module, BufferSizeBytesFunction())); // Run buffer analysis on the HLO graph. This analysis figures out which // temporary buffers are required to run the computation. diff --git a/tensorflow/compiler/xla/service/cpu/cpu_executable.cc b/tensorflow/compiler/xla/service/cpu/cpu_executable.cc index 29abf38e43..818b2b0d0d 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_executable.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_executable.cc @@ -51,8 +51,7 @@ namespace cpu { CpuExecutable::CpuExecutable( std::unique_ptr jit, std::unique_ptr assignment, - std::unique_ptr hlo_module, - const string& entry_function_name, + std::unique_ptr hlo_module, const string& entry_function_name, std::unique_ptr hlo_profile_printer_data, std::unique_ptr hlo_profile_index_map) : Executable(std::move(hlo_module), std::move(hlo_profile_printer_data), diff --git a/tensorflow/compiler/xla/service/cpu/cpu_executable.h b/tensorflow/compiler/xla/service/cpu/cpu_executable.h index 3c3c047bfe..3b91b15ba9 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_executable.h +++ b/tensorflow/compiler/xla/service/cpu/cpu_executable.h @@ -49,7 +49,7 @@ class CpuExecutable : public Executable { public: CpuExecutable(std::unique_ptr jit, std::unique_ptr assignment, - std::unique_ptr hlo_module, + std::unique_ptr hlo_module, const string& entry_function_name, std::unique_ptr hlo_profile_printer_data, std::unique_ptr hlo_profile_index_map); diff --git a/tensorflow/compiler/xla/service/cpu/cpu_instruction_fusion.cc b/tensorflow/compiler/xla/service/cpu/cpu_instruction_fusion.cc index f9cd61bea3..6f79ad7c14 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_instruction_fusion.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_instruction_fusion.cc @@ -48,10 +48,15 @@ bool IsMatrixVectorDot(const HloInstruction* hlo) { (hlo_shape.dimensions(0) == 1 || hlo_shape.dimensions(1) == 1); } +bool HasExactlyOneUse(const HloInstruction& hlo_instr) { + return hlo_instr.user_count() == 1 && + absl::c_count(hlo_instr.users().front()->operands(), &hlo_instr) == 1; +} + bool CanBeOutputFused(const HloInstruction* producer, const HloInstruction* consumer) { return consumer->opcode() == HloOpcode::kAdd && IsMatrixVectorDot(producer) && - producer->user_count() == 1; + HasExactlyOneUse(*producer) == 1; } bool CanBeOutputFusedIntoSomeOperand(const HloInstruction* consumer) { diff --git a/tensorflow/compiler/xla/service/cpu/cpu_instruction_fusion_test.cc b/tensorflow/compiler/xla/service/cpu/cpu_instruction_fusion_test.cc index c95a514ca0..527df0bd1c 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_instruction_fusion_test.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_instruction_fusion_test.cc @@ -321,7 +321,7 @@ TEST_F(OpcodeFusionTest, Exponential_Reshape_Negate) { builder.AddInstruction( HloInstruction::CreateUnary(result_shape, HloOpcode::kNegate, reshape2)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); RunFusionAndCheckOpcodesWereFused( @@ -370,7 +370,7 @@ TEST_F(OpcodeFusionTest, Broadcast_Negate) { builder.AddInstruction(HloInstruction::CreateUnary( result_shape, HloOpcode::kNegate, broadcast1)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); RunFusionAndCheckOpcodesWereFused( @@ -410,7 +410,7 @@ TEST_F(OpcodeFusionTest, Exponential_Negate) { builder.AddInstruction( HloInstruction::CreateUnary(param_shape, HloOpcode::kNegate, exp1)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); RunFusionAndCheckOpcodesWereFused( @@ -429,7 +429,7 @@ TEST_F(OpcodeFusionTest, Reshape_Negate) { builder.AddInstruction( HloInstruction::CreateUnary(result_shape, HloOpcode::kNegate, reshape1)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); RunFusionAndCheckOpcodesWereFused( @@ -447,7 +447,7 @@ TEST_F(OpcodeFusionTest, Reverse_Negate) { builder.AddInstruction( HloInstruction::CreateUnary(param_shape, HloOpcode::kNegate, reverse1)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); RunFusionAndCheckOpcodesWereFused( @@ -489,7 +489,7 @@ TEST_F(OpcodeFusionTest, Exponential_Transpose_Negate) { builder.AddInstruction(HloInstruction::CreateUnary( result_shape, HloOpcode::kNegate, transpose2)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); RunFusionAndCheckOpcodesWereFused( @@ -498,7 +498,7 @@ TEST_F(OpcodeFusionTest, Exponential_Transpose_Negate) { } TEST_F(OpcodeFusionTest, UnaryMapOfExp) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation::Builder builder(TestName()); Shape shape = ShapeUtil::MakeShape(F32, {3, 4}); @@ -517,7 +517,7 @@ TEST_F(OpcodeFusionTest, UnaryMapOfExp) { } TEST_F(OpcodeFusionTest, BinaryMapOfExps) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation::Builder builder(TestName()); Shape shape = ShapeUtil::MakeShape(F32, {3, 4}); @@ -542,7 +542,7 @@ TEST_F(OpcodeFusionTest, BinaryMapOfExps) { } TEST_F(OpcodeFusionTest, DynamicSliceWithDynamicUpdateSlice) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation::Builder builder(TestName()); Shape full_shape = ShapeUtil::MakeShape(F32, {10, 100, 1000}); @@ -573,7 +573,7 @@ TEST_F(OpcodeFusionTest, DynamicSliceWithDynamicUpdateSlice) { } TEST_F(OpcodeFusionTest, MessOfFusibleNodes) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation::Builder builder(TestName()); Shape full_shape = ShapeUtil::MakeShape(F32, {4, 100, 10, 100, 50}); @@ -712,7 +712,7 @@ void CreateComputationForDotAddOutputFusionTest(const string& test_name, } TEST_F(OpcodeFusionTest, DotAddOutputFusion_1x50x19) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); CreateComputationForDotAddOutputFusionTest(TestName(), module.get(), /*m=*/1, /*k=*/50, /*n=*/19, /*add_extra_use_for_dot=*/false); @@ -725,7 +725,7 @@ TEST_F(OpcodeFusionTest, DotAddOutputFusion_1x50x19) { } TEST_F(OpcodeFusionTest, DotAddOutputFusion_19x50x1) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); CreateComputationForDotAddOutputFusionTest(TestName(), module.get(), /*m=*/19, /*k=*/50, /*n=*/1, /*add_extra_use_for_dot=*/false); @@ -738,7 +738,7 @@ TEST_F(OpcodeFusionTest, DotAddOutputFusion_19x50x1) { } TEST_F(OpcodeFusionTest, DotAddOutputFusion_19x50x19) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); CreateComputationForDotAddOutputFusionTest(TestName(), module.get(), /*m=*/19, /*k=*/50, /*n=*/19, /*add_extra_use_for_dot=*/false); @@ -751,7 +751,7 @@ TEST_F(OpcodeFusionTest, DotAddOutputFusion_19x50x19) { } TEST_F(OpcodeFusionTest, DotAddOutputFusion_19x50x1_multi_use) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); CreateComputationForDotAddOutputFusionTest(TestName(), module.get(), /*m=*/19, /*k=*/50, /*n=*/1, /*add_extra_use_for_dot=*/true); @@ -763,6 +763,28 @@ TEST_F(OpcodeFusionTest, DotAddOutputFusion_19x50x1_multi_use) { Not(op::Fusion())); } +TEST_F(InstructionFusionTest, + DotOperationFusion_DontOutputFuseDuplicateOperands) { + absl::string_view module_string = R"( +HloModule module + +ENTRY main { + a = f32[50,60]{1,0} parameter(0) + b = f32[60,1]{1,0} parameter(1) + c = f32[50,1]{1,0} dot(a, b), lhs_contracting_dims={1}, rhs_contracting_dims={0} + ROOT d = f32[50,1]{1,0} add(c, c) +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_string)); + TF_ASSERT_OK_AND_ASSIGN(bool fused_something, + CpuInstructionFusion().Run(module.get())); + EXPECT_FALSE(fused_something); + EXPECT_THAT(module->entry_computation()->root_instruction(), + Not(op::Fusion())); +} + struct GatherLoopFusionTestSpec { string test_name; string hlo_computation_text; diff --git a/tensorflow/compiler/xla/service/cpu/cpu_layout_assignment_test.cc b/tensorflow/compiler/xla/service/cpu/cpu_layout_assignment_test.cc index 2cd52e4a18..6c61b64758 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_layout_assignment_test.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_layout_assignment_test.cc @@ -73,7 +73,7 @@ TEST_F(CpuLayoutAssignmentTest, DotWithConstantRhsTensor) { auto result = builder.AddInstruction( CreateCanonicalDot(result_shape, dot_lhs, dot_rhs)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); ComputationLayout computation_layout(computation->ComputeProgramShape()); @@ -114,7 +114,7 @@ TEST_F(CpuLayoutAssignmentTest, MultipleDotsWithSameConstantRhsTensor0) { builder.AddInstruction(HloInstruction::CreateBinary( result_shape, HloOpcode::kAdd, dot_a_result, dot_b_result)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); ComputationLayout computation_layout(computation->ComputeProgramShape()); @@ -158,7 +158,7 @@ TEST_F(CpuLayoutAssignmentTest, MultipleDotsWithSameConstantRhsTensor1) { auto tuple_result = builder.AddInstruction( HloInstruction::CreateTuple({dot_a_result, dot_b_result})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); ComputationLayout computation_layout(computation->ComputeProgramShape()); @@ -192,7 +192,7 @@ TEST_F(CpuLayoutAssignmentTest, DotWithConstantLhsTensor) { auto dot_result = builder.AddInstruction( CreateCanonicalDot(result_shape, dot_lhs, dot_rhs)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); ComputationLayout computation_layout(computation->ComputeProgramShape()); @@ -232,7 +232,7 @@ TEST_F(CpuLayoutAssignmentTest, DotWithConstantRhsTensorThroughGTE) { auto dot_result = builder.AddInstruction( CreateCanonicalDot(result_shape, dot_lhs, dot_rhs)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); ComputationLayout computation_layout(computation->ComputeProgramShape()); @@ -353,7 +353,7 @@ static void AssertCorrectLayoutForDotOutputFusion( } TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_1x50x19_dot_idx_0) { - std::unique_ptr module = CreateNewUnverifiedModule(); + std::unique_ptr module = CreateNewVerifiedModule(); TF_ASSERT_OK_AND_ASSIGN( DotOutputFusionLayoutAssignmentResult layout_assignment_result, RunDotOutputFusion(module.get(), TestName(), /*m=*/1, /*k=*/50, /*n=*/19, @@ -365,7 +365,7 @@ TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_1x50x19_dot_idx_0) { } TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_1x50x19_dot_idx_1) { - std::unique_ptr module = CreateNewUnverifiedModule(); + std::unique_ptr module = CreateNewVerifiedModule(); TF_ASSERT_OK_AND_ASSIGN( DotOutputFusionLayoutAssignmentResult layout_assignment_result, RunDotOutputFusion(module.get(), TestName(), /*m=*/1, /*k=*/50, /*n=*/19, @@ -377,7 +377,7 @@ TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_1x50x19_dot_idx_1) { } TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_19x50x1_dot_idx_0) { - std::unique_ptr module = CreateNewUnverifiedModule(); + std::unique_ptr module = CreateNewVerifiedModule(); TF_ASSERT_OK_AND_ASSIGN( DotOutputFusionLayoutAssignmentResult layout_assignment_result, RunDotOutputFusion(module.get(), TestName(), /*m=*/19, /*k=*/50, /*n=*/1, @@ -389,7 +389,7 @@ TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_19x50x1_dot_idx_0) { } TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_19x50x1_dot_idx_1) { - std::unique_ptr module = CreateNewUnverifiedModule(); + std::unique_ptr module = CreateNewVerifiedModule(); TF_ASSERT_OK_AND_ASSIGN( DotOutputFusionLayoutAssignmentResult layout_assignment_result, RunDotOutputFusion(module.get(), TestName(), /*m=*/19, /*k=*/50, /*n=*/1, @@ -401,7 +401,7 @@ TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_19x50x1_dot_idx_1) { } TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_19x50x19_dot_idx_0) { - std::unique_ptr module = CreateNewUnverifiedModule(); + std::unique_ptr module = CreateNewVerifiedModule(); TF_ASSERT_OK_AND_ASSIGN( DotOutputFusionLayoutAssignmentResult layout_assignment_result, RunDotOutputFusion(module.get(), TestName(), /*m=*/19, /*k=*/50, /*n=*/19, @@ -413,7 +413,7 @@ TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_19x50x19_dot_idx_0) { } TEST_F(CpuLayoutAssignmentTest, DotOutputFusion_19x50x19_dot_idx_1) { - std::unique_ptr module = CreateNewUnverifiedModule(); + std::unique_ptr module = CreateNewVerifiedModule(); TF_ASSERT_OK_AND_ASSIGN( DotOutputFusionLayoutAssignmentResult layout_assignment_result, RunDotOutputFusion(module.get(), TestName(), /*m=*/19, /*k=*/50, /*n=*/19, diff --git a/tensorflow/compiler/xla/service/cpu/cpu_options.cc b/tensorflow/compiler/xla/service/cpu/cpu_options.cc index b8ace57026..92debb83e3 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_options.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_options.cc @@ -22,7 +22,6 @@ limitations under the License. namespace { const char* const kXlaOptimizeForSizeCpuOption = "xla_cpu_optimize_for_size"; -const char* const kXlaDisableVectorizedReduce = "xla_disable_vectorized_reduce"; const char* const kLlvmIrDotTilingFactor = "xla_llvm_dot_tiling_factor"; const char* const kXlaEnableExperimentalLlvmIrGemm = "xla_enable_experimental_llvm_ir_gemm"; diff --git a/tensorflow/compiler/xla/service/cpu/ir_emitter.cc b/tensorflow/compiler/xla/service/cpu/ir_emitter.cc index 620c45fa39..4032c2da2f 100644 --- a/tensorflow/compiler/xla/service/cpu/ir_emitter.cc +++ b/tensorflow/compiler/xla/service/cpu/ir_emitter.cc @@ -111,7 +111,7 @@ IrEmitter::IrEmitter( StatusOr IrEmitter::EmitComputation( HloComputation* computation, const string& function_name_prefix, bool is_top_level_computation, - const std::vector* instruction_order) { + const std::vector* instruction_order) { string function_name = name_uniquer_.GetUniqueName(function_name_prefix); VLOG(2) << "Emitting IR for CPU function [" << function_name_prefix << "]; ordered? " << (instruction_order != nullptr); @@ -140,7 +140,7 @@ StatusOr IrEmitter::EmitComputation( // readcyclecounter if it is unavailable. bool use_rdtscp = arch_type_ == llvm::Triple::ArchType::x86 || arch_type_ == llvm::Triple::ArchType::x86_64; - profiling_state_ = ProfilingState(use_rdtscp, GetProfileCountersArgument()); + profiling_state_ = ProfilingState(use_rdtscp); if (instruction_order == nullptr) { TF_RETURN_IF_ERROR(computation->Accept(this)); } else { @@ -1379,33 +1379,6 @@ Status IrEmitter::HandleCrossReplicaSum(HloInstruction* crs) { return Status::OK(); } -// Fills up the free variables in 'index_with_free_var' with values from -// 'filler_index'. The size of free variables must be the same as the -// size of 'filler_index'. -// -// This is often used after dimension reduction, where -// 'index_with_free_var' has one or more dimensions reduced, which serves as -// free variables (represented as nullptr). For example, if we have a 4 -// dimensional input and index for the dimension being reduced is -// 2 (third dimension), we will have an index like [i, j, NULL, k] -// after reduced dimension. -// -// Here we fill up that free variable by 'filler_index', which contains -// the value in the reduced dimension. -static llvm_ir::IrArray::Index FillReducedDimensionIndex( - llvm_ir::IrArray::Index index_with_free_var, - llvm_ir::IrArray::Index filler_index) { - llvm_ir::IrArray::Index::const_iterator it = filler_index.begin(); - - for (size_t i = 0; i < index_with_free_var.size(); ++i) { - if (index_with_free_var[i] == nullptr) { - index_with_free_var[i] = *it++; - } - } - CHECK(filler_index.end() == it); - return index_with_free_var; -} - Status IrEmitter::HandleParameter(HloInstruction* parameter) { VLOG(2) << "HandleParameter: " << parameter->ToString(); return EmitTargetAddressForOp(parameter); @@ -2194,14 +2167,6 @@ Status IrEmitter::HandlePad(HloInstruction* pad) { return Status::OK(); } -// If `hlo` is a Transpose, returns its operand; otherwise returns `hlo` itself. -static const HloInstruction* StripTranspose(const HloInstruction& hlo) { - if (hlo.IsRank2Transpose()) { - return hlo.operand(0); - } - return &hlo; -} - Status IrEmitter::HandleFusion(HloInstruction* fusion) { auto* root = fusion->fused_expression_root(); if (llvm_ir::CanEmitFusedDynamicUpdateSliceInPlace(fusion, assignment_)) { @@ -2600,10 +2565,17 @@ Status IrEmitter::HandleConditional(HloInstruction* conditional) { return Status::OK(); } -Status IrEmitter::HandleAfterAll(HloInstruction* gen_token) { - TF_RET_CHECK(ByteSizeOf(gen_token->shape()) == 0); +Status IrEmitter::HandleAfterAll(HloInstruction* after_all) { + TF_RET_CHECK(ByteSizeOf(after_all->shape()) == 0); // No code to generate, but we need to emit an address for book-keeping. - TF_RETURN_IF_ERROR(EmitTargetAddressForOp(gen_token)); + TF_RETURN_IF_ERROR(EmitTargetAddressForOp(after_all)); + return Status::OK(); +} + +Status IrEmitter::HandleAddDependency(HloInstruction* add_dependency) { + // AddDedendency just forwards its zero-th operand. + emitted_value_[add_dependency] = + GetEmittedValueFor(add_dependency->operand(0)); return Status::OK(); } diff --git a/tensorflow/compiler/xla/service/cpu/ir_emitter.h b/tensorflow/compiler/xla/service/cpu/ir_emitter.h index 136b88ff75..559a8162a2 100644 --- a/tensorflow/compiler/xla/service/cpu/ir_emitter.h +++ b/tensorflow/compiler/xla/service/cpu/ir_emitter.h @@ -101,7 +101,7 @@ class IrEmitter : public DfsHloVisitorWithDefault, StatusOr EmitComputation( HloComputation* computation, const string& function_name_prefix, bool is_top_level_computation, - const std::vector* instruction_order); + const std::vector* instruction_order); llvm::IRBuilder<>* b() { return &b_; } @@ -159,7 +159,8 @@ class IrEmitter : public DfsHloVisitorWithDefault, Status HandleConcatenate(HloInstruction* concatenate) override; Status HandleConditional(HloInstruction* conditional) override; Status HandleScatter(HloInstruction* scatter) override; - Status HandleAfterAll(HloInstruction* gen_token) override; + Status HandleAfterAll(HloInstruction* after_all) override; + Status HandleAddDependency(HloInstruction* add_dependency) override; Status HandleRng(HloInstruction* rng) override; Status FinishVisit(HloInstruction* root) override; @@ -467,9 +468,8 @@ class IrEmitter : public DfsHloVisitorWithDefault, // profiling a computation. class ProfilingState { public: - ProfilingState() : use_rdtscp_(false), prof_counters_(nullptr) {} - ProfilingState(bool use_rdtscp, llvm::Value* prof_counters) - : use_rdtscp_(use_rdtscp), prof_counters_(prof_counters) {} + ProfilingState() : use_rdtscp_(false) {} + explicit ProfilingState(bool use_rdtscp) : use_rdtscp_(use_rdtscp) {} // Record the cycle counter before an HLO executes. void RecordCycleStart(llvm::IRBuilder<>* b, HloInstruction* hlo); @@ -494,9 +494,6 @@ class IrEmitter : public DfsHloVisitorWithDefault, // intrinsic? bool use_rdtscp_; - // The argument which corresponds to the profile counter buffer. - llvm::Value* prof_counters_; - // The first read cycle counter in the program. llvm::Value* first_read_cycle_start_ = nullptr; diff --git a/tensorflow/compiler/xla/service/cpu/runtime_key_value_sort.cc b/tensorflow/compiler/xla/service/cpu/runtime_key_value_sort.cc index 669eeb95f3..722aa3120e 100644 --- a/tensorflow/compiler/xla/service/cpu/runtime_key_value_sort.cc +++ b/tensorflow/compiler/xla/service/cpu/runtime_key_value_sort.cc @@ -17,6 +17,7 @@ limitations under the License. #include #include #include +#include #include #include #include @@ -41,61 +42,60 @@ void KeyValueSort(std::pair* row_to_sort, int64 num_elements) { std::sort(row_to_sort, row_to_sort + num_elements); } -// For floating point numbers, we want a total order comparator. -NaN and NaN -// should appear at the beginning and end of the ordering, and -0.0 should -// appear before 0.0. Also we want to have a stable sort, so if the keys are the -// same, we compare the index values. -template -bool LessThan(KeyType lhs, int64 lhs_index, KeyType rhs, int64 rhs_index) { - bool lhs_is_negative = std::signbit(lhs); - bool rhs_is_negative = std::signbit(rhs); - // If the signs are different, we can just compare the signs. - if (lhs_is_negative != rhs_is_negative) { - return lhs_is_negative && !rhs_is_negative; - } - bool lhs_nan = std::isnan(lhs); - bool rhs_nan = std::isnan(rhs); - // Exactly one number is nan? - if (lhs_nan != rhs_nan) { - if (lhs_nan) { - return lhs_is_negative; - } - return !rhs_is_negative; +// We would like a total order of floating point numbers so that the +// sort has a predictable behavior in the presence of NaNs. Rather +// than using floating point comparison, we use the following trick: +// If f is a float, and +// x = bit_cast(f); +// y = x < 0 ? 0x7FFFFFFF - x : x; +// then y is ordered as an int32 such that finite values have the +// obvious order, -0 is ordered before 0, and -NaN and NaN appear at +// the beginning and end of the ordering. +template +CastType Convert(KeyType value) { + CastType casted_value; + memcpy(&casted_value, &value, sizeof(CastType)); + if (casted_value < 0) { + return static_cast(std::numeric_limits::max()) - + casted_value; } - if (lhs != rhs) { - return lhs < rhs; - } - return lhs_index < rhs_index; + return casted_value; +} + +template +bool LessThan(KeyType lhs, KeyType rhs) { + return Convert(lhs) < + Convert(rhs); } template <> void KeyValueSort(std::pair* row_to_sort, int64 num_elements) { - std::sort(row_to_sort, row_to_sort + num_elements, - [](const std::pair& lhs, - const std::pair& rhs) -> bool { - return LessThan(lhs.first, lhs.second, rhs.first, rhs.second); - }); + std::stable_sort(row_to_sort, row_to_sort + num_elements, + [](const std::pair& lhs, + const std::pair& rhs) -> bool { + return LessThan(lhs.first, rhs.first); + }); } template <> void KeyValueSort(std::pair* row_to_sort, int64 num_elements) { - std::sort(row_to_sort, row_to_sort + num_elements, - [](const std::pair& lhs, - const std::pair& rhs) -> bool { - return LessThan(lhs.first, lhs.second, rhs.first, rhs.second); - }); + std::stable_sort(row_to_sort, row_to_sort + num_elements, + [](const std::pair& lhs, + const std::pair& rhs) -> bool { + return LessThan(lhs.first, rhs.first); + }); } template <> void KeyValueSort(std::pair* row_to_sort, int64 num_elements) { - std::sort(row_to_sort, row_to_sort + num_elements, - [](const std::pair& lhs, - const std::pair& rhs) -> bool { - return LessThan( - Eigen::half_impl::half_to_float(lhs.first), lhs.second, - Eigen::half_impl::half_to_float(rhs.first), rhs.second); - }); + std::stable_sort(row_to_sort, row_to_sort + num_elements, + [](const std::pair& lhs, + const std::pair& rhs) -> bool { + return LessThan( + Eigen::half_impl::half_to_float(lhs.first), + Eigen::half_impl::half_to_float(rhs.first)); + }); } template diff --git a/tensorflow/compiler/xla/service/cpu/simple_orc_jit.cc b/tensorflow/compiler/xla/service/cpu/simple_orc_jit.cc index f77641eb7d..efccadedf2 100644 --- a/tensorflow/compiler/xla/service/cpu/simple_orc_jit.cc +++ b/tensorflow/compiler/xla/service/cpu/simple_orc_jit.cc @@ -128,8 +128,18 @@ SimpleOrcJIT::SimpleOrcJIT(const llvm::TargetOptions& target_options, } llvm::JITSymbol SimpleOrcJIT::ResolveRuntimeSymbol(const std::string& name) { - void* func_addr = CustomCallTargetRegistry::Global()->Lookup(name); + void* func_addr = nullptr; + if (name.size() > 1 && name.front() == data_layout_.getGlobalPrefix()) { + // On Mac OS X, 'name' may have a leading underscore prefix, even though the + // registered name may not. + std::string stripped_name(name.begin() + 1, name.end()); + func_addr = CustomCallTargetRegistry::Global()->Lookup(stripped_name); + } else { + func_addr = CustomCallTargetRegistry::Global()->Lookup(name); + } + if (func_addr == nullptr) { + VLOG(2) << "Unable to resolve runtime symbol: " << name; return nullptr; } llvm::JITEvaluatedSymbol symbol_info(reinterpret_cast(func_addr), diff --git a/tensorflow/compiler/xla/service/cpu/tests/cpu_eigen_dot_operation_test.cc b/tensorflow/compiler/xla/service/cpu/tests/cpu_eigen_dot_operation_test.cc index 691b3c7bee..f8f5f392da 100644 --- a/tensorflow/compiler/xla/service/cpu/tests/cpu_eigen_dot_operation_test.cc +++ b/tensorflow/compiler/xla/service/cpu/tests/cpu_eigen_dot_operation_test.cc @@ -50,7 +50,7 @@ class CpuEigenDotOperationTest /*entry_point_name=*/"entry", /*relocation_model=*/CpuAotCompilationOptions::RelocationModel::Static}; - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); hlo_module->AddEntryComputation(std::move(entry_computation)); CompileAheadOfTimeAndVerifyIr(std::move(hlo_module), options, diff --git a/tensorflow/compiler/xla/service/cpu/tests/cpu_external_constants_test.cc b/tensorflow/compiler/xla/service/cpu/tests/cpu_external_constants_test.cc index d201a151d7..e30f95311f 100644 --- a/tensorflow/compiler/xla/service/cpu/tests/cpu_external_constants_test.cc +++ b/tensorflow/compiler/xla/service/cpu/tests/cpu_external_constants_test.cc @@ -46,7 +46,7 @@ class CpuExternalConstantsTest : public CpuCodegenTest { builder.AddInstruction( HloInstruction::CreateBinary(shape, HloOpcode::kAdd, param, constant)); - std::unique_ptr module = CreateNewUnverifiedModule(); + std::unique_ptr module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); CompileAndVerifyIr(std::move(module), filecheck_pattern, diff --git a/tensorflow/compiler/xla/service/cpu/tests/cpu_intrinsic_test.cc b/tensorflow/compiler/xla/service/cpu/tests/cpu_intrinsic_test.cc index 773336c7a9..9b10c49f4f 100644 --- a/tensorflow/compiler/xla/service/cpu/tests/cpu_intrinsic_test.cc +++ b/tensorflow/compiler/xla/service/cpu/tests/cpu_intrinsic_test.cc @@ -91,7 +91,7 @@ TEST_P(CpuUnaryIntrinsicTest, DoIt) { /*entry_point_name=*/"entry", /*relocation_model=*/CpuAotCompilationOptions::RelocationModel::Static}; - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); hlo_module->AddEntryComputation(std::move(computation)); string check_lines{spec.check_lines.data(), spec.check_lines.size()}; diff --git a/tensorflow/compiler/xla/service/cpu/tests/cpu_literal_caching_test.cc b/tensorflow/compiler/xla/service/cpu/tests/cpu_literal_caching_test.cc index 3b87683fff..fa0e09ff6b 100644 --- a/tensorflow/compiler/xla/service/cpu/tests/cpu_literal_caching_test.cc +++ b/tensorflow/compiler/xla/service/cpu/tests/cpu_literal_caching_test.cc @@ -63,7 +63,7 @@ CHECK-NOT: private constant [48 x i8] )"; TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, - ParseHloString(hlo_text)); + ParseAndReturnVerifiedModule(hlo_text)); CpuAotCompilationOptions options{ /*triple=*/"x86_64-pc-linux", /*cpu_name=*/"", /*features=*/"", @@ -104,14 +104,14 @@ ENTRY main { )"; string filecheck_pattern = R"( -CHECK: private constant [4 x i8] -CHECK: private constant [8 x i8] +CHECK-DAG: private constant [4 x i8] +CHECK-DAG: private constant [8 x i8] CHECK-NOT: private constant [4 x i8] CHECK-NOT: private constant [8 x i8] )"; TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, - ParseHloString(hlo_text)); + ParseAndReturnVerifiedModule(hlo_text)); CpuAotCompilationOptions options{ /*triple=*/"x86_64-pc-linux", /*cpu_name=*/"", /*features=*/"", diff --git a/tensorflow/compiler/xla/service/cpu/tests/cpu_noalias_test.cc b/tensorflow/compiler/xla/service/cpu/tests/cpu_noalias_test.cc index f5419b7063..a7702c2aee 100644 --- a/tensorflow/compiler/xla/service/cpu/tests/cpu_noalias_test.cc +++ b/tensorflow/compiler/xla/service/cpu/tests/cpu_noalias_test.cc @@ -56,7 +56,7 @@ TEST_F(CpuNoAliasTest, Concat) { std::unique_ptr computation = builder.Build(); - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); hlo_module->AddEntryComputation(std::move(computation)); // Now that we have an HLO module, build an llvm_ir::AliasAnalysis for it. diff --git a/tensorflow/compiler/xla/service/cpu/xfeed_manager.h b/tensorflow/compiler/xla/service/cpu/xfeed_manager.h index 990ff94ba2..70008947f3 100644 --- a/tensorflow/compiler/xla/service/cpu/xfeed_manager.h +++ b/tensorflow/compiler/xla/service/cpu/xfeed_manager.h @@ -23,6 +23,7 @@ limitations under the License. #include #include "absl/types/span.h" +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/statusor.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/xla_data.pb.h" diff --git a/tensorflow/compiler/xla/service/dfs_hlo_visitor.h b/tensorflow/compiler/xla/service/dfs_hlo_visitor.h index d637128322..e84bf00153 100644 --- a/tensorflow/compiler/xla/service/dfs_hlo_visitor.h +++ b/tensorflow/compiler/xla/service/dfs_hlo_visitor.h @@ -251,6 +251,7 @@ class DfsHloVisitorBase { virtual Status HandleBatchNormGrad(HloInstructionPtr hlo) = 0; + virtual Status HandleAddDependency(HloInstructionPtr add_dependency) = 0; virtual Status HandleAfterAll(HloInstructionPtr token) = 0; // Invoked to inform the visitor that the traversal has completed, and that diff --git a/tensorflow/compiler/xla/service/dfs_hlo_visitor_with_default.h b/tensorflow/compiler/xla/service/dfs_hlo_visitor_with_default.h index e57184f639..80ea5be298 100644 --- a/tensorflow/compiler/xla/service/dfs_hlo_visitor_with_default.h +++ b/tensorflow/compiler/xla/service/dfs_hlo_visitor_with_default.h @@ -206,6 +206,9 @@ class DfsHloVisitorWithDefaultBase Status HandleGetDimensionSize(HloInstructionPtr get_size) override { return DefaultAction(get_size); } + Status HandleAddDependency(HloInstructionPtr add_dependency) override { + return DefaultAction(add_dependency); + } // Invoked to inform the visitor that the traversal has completed, and that // the root was "root". diff --git a/tensorflow/compiler/xla/service/dynamic_parameter_binding.cc b/tensorflow/compiler/xla/service/dynamic_parameter_binding.cc new file mode 100644 index 0000000000..c8bfc89050 --- /dev/null +++ b/tensorflow/compiler/xla/service/dynamic_parameter_binding.cc @@ -0,0 +1,138 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/service/dynamic_parameter_binding.h" +#include "tensorflow/compiler/xla/service/hlo_computation.h" +#include "tensorflow/compiler/xla/service/hlo_instruction.h" +#include "tensorflow/compiler/xla/service/hlo_module.h" + +namespace xla { + +Status DynamicParameterBinding::Bind( + const DynamicParameter& dynamic_parameter, + const DynamicDimension& dynamic_dimension) { + auto result = bindings_.emplace(dynamic_dimension, dynamic_parameter); + TF_RET_CHECK(result.second); + return Status::OK(); +} + +absl::optional +DynamicParameterBinding::GetBinding(const DynamicDimension& dynamic_dimension) { + auto param_iter = bindings_.find(dynamic_dimension); + if (param_iter == bindings_.end()) { + return absl::nullopt; + } + return param_iter->second; +} + +DynamicParameterBindingProto DynamicParameterBinding::ToProto() const { + DynamicParameterBindingProto result; + for (const auto& binding : bindings_) { + const DynamicDimension& dynamic_dimension = binding.first; + const DynamicParameter& dynamic_param = binding.second; + DynamicParameterBindingProto::Binding binding_proto; + binding_proto.set_dynamic_param_num(dynamic_param.parameter_num); + for (int64 i : dynamic_param.parameter_index) { + binding_proto.add_dynamic_param_index(i); + } + + binding_proto.set_target_param_num(dynamic_dimension.parameter_num); + + for (int64 i : dynamic_dimension.parameter_index) { + binding_proto.add_target_param_index(i); + } + + binding_proto.set_target_param_dim_num(dynamic_dimension.dimension); + result.add_entries()->Swap(&binding_proto); + } + return result; +} + +StatusOr DynamicParameterBinding::CreateFromProto( + const DynamicParameterBindingProto& proto) { + DynamicParameterBinding result; + for (const DynamicParameterBindingProto::Binding& binding : proto.entries()) { + int64 dynamic_param_num = binding.dynamic_param_num(); + ShapeIndex dynamic_param_index(binding.dynamic_param_index().begin(), + binding.dynamic_param_index().end()); + int64 target_param_num = binding.target_param_num(); + ShapeIndex target_param_index(binding.target_param_index().begin(), + binding.target_param_index().end()); + int64 target_dim_num = binding.target_param_num(); + + TF_RETURN_IF_ERROR( + result.Bind(DynamicParameter{dynamic_param_num, dynamic_param_index}, + DynamicDimension{target_param_num, target_param_index, + target_dim_num})); + } + + return result; +} + +string DynamicParameterBinding::ToString() const { + std::vector pieces; + pieces.push_back("DynamicParameterBinding: "); + for (const auto& binding : bindings_) { + const DynamicDimension& dynamic_dimension = binding.first; + const DynamicParameter& dynamic_param = binding.second; + pieces.push_back(absl::StrFormat( + " -- Input param number %lld at %s has dim %lld as dynamic" + " dimension, which is represented by param number %lld at " + "%s", + dynamic_dimension.parameter_num, + dynamic_dimension.parameter_index.ToString(), + dynamic_dimension.dimension, dynamic_param.parameter_num, + dynamic_param.parameter_index.ToString())); + } + return absl::StrJoin(pieces, "\n"); +} + +Status DynamicParameterBinding::ForEachBinding(BindingFn fn) const { + for (const auto& binding : bindings_) { + TF_RETURN_IF_ERROR(fn(binding.second, binding.first)); + } + return Status::OK(); +} + +Status DynamicParameterBinding::Verify(const HloModule& module) const { + const HloComputation* entry = module.entry_computation(); + return ForEachBinding([&](const DynamicParameter& dynamic_parameter, + const DynamicDimension& dynamic_dimension) + -> Status { + TF_RET_CHECK(dynamic_parameter.parameter_num < entry->num_parameters()); + TF_RET_CHECK(dynamic_dimension.parameter_num < entry->num_parameters()); + TF_RET_CHECK(ShapeUtil::IndexIsValid( + entry->parameter_instruction(dynamic_parameter.parameter_num)->shape(), + dynamic_parameter.parameter_index)); + TF_RET_CHECK(ShapeUtil::IndexIsValid( + entry->parameter_instruction(dynamic_dimension.parameter_num)->shape(), + dynamic_dimension.parameter_index)); + TF_RET_CHECK( + dynamic_dimension.dimension < + ShapeUtil::Rank(ShapeUtil::GetSubshape( + entry->parameter_instruction(dynamic_dimension.parameter_num) + ->shape(), + dynamic_dimension.parameter_index))); + return Status::OK(); + }); +} + +std::ostream& operator<<(std::ostream& out, + const DynamicParameterBinding& binding) { + out << binding.ToString(); + return out; +} + +} // namespace xla diff --git a/tensorflow/compiler/xla/service/dynamic_parameter_binding.h b/tensorflow/compiler/xla/service/dynamic_parameter_binding.h new file mode 100644 index 0000000000..dd474d8eed --- /dev/null +++ b/tensorflow/compiler/xla/service/dynamic_parameter_binding.h @@ -0,0 +1,125 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_COMPILER_XLA_SERVICE_DYNAMIC_PARAMETER_BINDING_H_ +#define TENSORFLOW_COMPILER_XLA_SERVICE_DYNAMIC_PARAMETER_BINDING_H_ + +#include + +#include "absl/container/flat_hash_map.h" +#include "absl/types/optional.h" +#include "tensorflow/compiler/xla/service/hlo.pb.h" +#include "tensorflow/compiler/xla/shape_tree.h" +#include "tensorflow/compiler/xla/shape_util.h" + +namespace xla { + +class HloModule; +// We currently use an explicit API that takes an extra parameter to indicate +// the runtime size of a dynamic dimension. DynamicParameterBinding indicates +// the relationship between parameter: We can have a dynamic parameter that +// points to another target parameter to indicate that the target parameter is +// dynamic. +// +// +// TODO(b/119520625): Remove this API once we have more dynamic shape infra +// ready. +class DynamicParameterBinding { + public: + // DynamicParameter represents a special parameter that is used to represent + // the runtime size of a dimension of another parameter. A dynamic parameter + // has to be a scalar value. + struct DynamicParameter { + // The parameter number of dynamic parameter. + int64 parameter_num; + // The index of the parameter. + ShapeIndex parameter_index; + }; + + // DynamicDimension represents a dimension whose size is determined at + // runtime. A DynamicDimension's runtime size is determined by the binded + // DynamicParameter using `DynamicParameterBinding::Bind` method. + struct DynamicDimension { + // The parameter number of dynamic dimension. + int64 parameter_num; + // The subshape index of the parameter. + ShapeIndex parameter_index; + // The dimension number in the subshape. + int64 dimension; + + // "friend" keyword are added so these functions can be found by ADL. + template + friend H AbslHashValue(H h, const DynamicDimension& m) { + return H::combine(std::move(h), m.parameter_num, m.parameter_index, + m.dimension); + } + + friend bool operator==(const DynamicDimension& lhs, + const DynamicDimension& rhs) { + return lhs.parameter_num == rhs.parameter_num && + lhs.parameter_index == rhs.parameter_index && + lhs.dimension == rhs.dimension; + } + }; + + DynamicParameterBinding() = default; + + virtual ~DynamicParameterBinding() = default; + + // Adds binding which indicates that the dimension indicated by + // `dynamic_dimension` is dynamic, and its runtime size is represented by + // `dynamic_parameter`. + Status Bind(const DynamicParameter& dynamic_parameter, + const DynamicDimension& dynamic_dimension); + + // Returns the parameter and the index representing the runtime size of + // dimension `dim_num` of parameter `param_num` at `param_index`. + // + // Returns nullopt if the binding is not set. + absl::optional GetBinding( + const DynamicDimension& dynamic_dimension); + + using BindingFn = + std::function; + + // Iterate through each binding. + Status ForEachBinding(BindingFn fn) const; + + DynamicParameterBindingProto ToProto() const; + + static StatusOr CreateFromProto( + const DynamicParameterBindingProto& proto); + + string ToString() const; + + // Verifies that the given binding is valid for the given module. + // Specifically, the binding's parameter and parameter size should be valid. + Status Verify(const HloModule& module) const; + + private: + // Keeps track of mappings from DynamicDimension to DynamicParameter. The + // direction of is chosen so that we can easily query if a dimension is + // dynamic and which dynamic parameter represents the real size of that + // dimension. + absl::flat_hash_map bindings_; +}; + +std::ostream& operator<<(std::ostream& out, + const DynamicParameterBinding& binding); + +} // namespace xla + +#endif // TENSORFLOW_COMPILER_XLA_SERVICE_DYNAMIC_PARAMETER_BINDING_H_ diff --git a/tensorflow/compiler/xla/service/dynamic_parameter_binding_test.cc b/tensorflow/compiler/xla/service/dynamic_parameter_binding_test.cc new file mode 100644 index 0000000000..83a6d83dff --- /dev/null +++ b/tensorflow/compiler/xla/service/dynamic_parameter_binding_test.cc @@ -0,0 +1,153 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/service/dynamic_parameter_binding.h" + +#include +#include + +#include "absl/algorithm/container.h" +#include "tensorflow/compiler/xla/service/hlo_computation.h" +#include "tensorflow/compiler/xla/service/hlo_dce.h" +#include "tensorflow/compiler/xla/service/hlo_instruction.h" +#include "tensorflow/compiler/xla/service/hlo_memory_scheduler.h" +#include "tensorflow/compiler/xla/service/hlo_opcode.h" +#include "tensorflow/compiler/xla/service/hlo_ordering.h" +#include "tensorflow/compiler/xla/service/hlo_parser.h" +#include "tensorflow/compiler/xla/shape_util.h" +#include "tensorflow/compiler/xla/tests/hlo_test_base.h" +#include "tensorflow/compiler/xla/types.h" +#include "tensorflow/core/lib/core/status_test_util.h" + +namespace xla { +namespace { +class DynamicParameterBindingTest : public HloTestBase {}; + +TEST_F(DynamicParameterBindingTest, SimpleBinding) { + // 'b' is a dynamic shape; 'a' represents the real size of b's first + // dimension. + const string module_str = R"( +HloModule TEST + +ENTRY main { + a = f32[] parameter(0) + b = f32[10] parameter(1) + ROOT root = (f32[], f32[10]) tuple(%a, %b) +} +)"; + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseHloString(module_str)); + + DynamicParameterBinding binding; + + TF_EXPECT_OK( + binding.Bind(DynamicParameterBinding::DynamicParameter{0, {}}, + DynamicParameterBinding::DynamicDimension{1, {}, 0})); + + absl::optional param = + binding.GetBinding( + DynamicParameterBinding::DynamicDimension{/*parameter_num=*/1, + /*parameter_index=*/{}, + /*dimension=*/0}); + EXPECT_TRUE(param); + EXPECT_EQ(param->parameter_num, 0); + EXPECT_EQ(param->parameter_index, ShapeIndex({})); + TF_EXPECT_OK(binding.Verify(*module)); +} + +TEST_F(DynamicParameterBindingTest, TupleBinding) { + // 'gte2' is a dynamic shape; 'gte1' represents the real size of gte2's first + // dimension. + const string module_str = R"( +HloModule TEST + +ENTRY main { + param = (f32[], f32[10]) parameter(0) + gte1 = f32[] get-tuple-element(%param), index=0 + gte2 = f32[10] get-tuple-element(%param), index=1 + ROOT root = (f32[], f32[10]) tuple(%gte1, %gte2) +} +)"; + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseHloString(module_str)); + + DynamicParameterBinding binding; + + TF_EXPECT_OK( + binding.Bind(DynamicParameterBinding::DynamicParameter{0, {0}}, + DynamicParameterBinding::DynamicDimension{0, {1}, 0})); + + absl::optional param = + binding.GetBinding( + DynamicParameterBinding::DynamicDimension{/*parameter_num=*/0, + /*parameter_index=*/{1}, + /*dimension=*/0}); + + EXPECT_TRUE(param); + EXPECT_EQ(param->parameter_num, 0); + EXPECT_EQ(param->parameter_index, ShapeIndex({0})); + TF_EXPECT_OK(binding.Verify(*module)); +} + +TEST_F(DynamicParameterBindingTest, TupleBindingWithMultiDimension) { + // 'gte2' is a dynamic shape; 'gte1' represents the real size of gte2's both + // dimensions. + const string module_str = R"( +HloModule TEST + +ENTRY main { + param = (f32[], f32[10, 10]) parameter(0) + gte1 = f32[] get-tuple-element(%param), index=0 + gte2 = f32[10, 10] get-tuple-element(%param), index=1 + ROOT root = (f32[], f32[10, 10]) tuple(%gte1, %gte2) +} +)"; + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseHloString(module_str)); + + DynamicParameterBinding binding; + + TF_EXPECT_OK( + binding.Bind(DynamicParameterBinding::DynamicParameter{0, {0}}, + DynamicParameterBinding::DynamicDimension{0, {1}, 0})); + + TF_EXPECT_OK( + binding.Bind(DynamicParameterBinding::DynamicParameter{0, {0}}, + DynamicParameterBinding::DynamicDimension{0, {1}, 1})); + + absl::optional param = + binding.GetBinding( + DynamicParameterBinding::DynamicDimension{/*parameter_num=*/0, + /*parameter_index=*/{1}, + /*dimension=*/0}); + + EXPECT_TRUE(param); + EXPECT_EQ(param->parameter_num, 0); + EXPECT_EQ(param->parameter_index, ShapeIndex({0})); + + absl::optional param2 = + binding.GetBinding( + DynamicParameterBinding::DynamicDimension{/*parameter_num=*/0, + /*parameter_index=*/{1}, + /*dimension=*/0}); + EXPECT_TRUE(param2); + EXPECT_EQ(param2->parameter_num, 0); + EXPECT_EQ(param2->parameter_index, ShapeIndex({0})); + + TF_EXPECT_OK(binding.Verify(*module)); +} + +} // namespace +} // namespace xla diff --git a/tensorflow/compiler/xla/service/elemental_ir_emitter.cc b/tensorflow/compiler/xla/service/elemental_ir_emitter.cc index f98c943669..6f1f95f2e9 100644 --- a/tensorflow/compiler/xla/service/elemental_ir_emitter.cc +++ b/tensorflow/compiler/xla/service/elemental_ir_emitter.cc @@ -22,6 +22,7 @@ limitations under the License. // IWYU pragma: no_include "llvm/IR/Intrinsics.gen.inc" #include "absl/algorithm/container.h" +#include "absl/container/flat_hash_map.h" #include "absl/strings/str_cat.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Instructions.h" @@ -1671,26 +1672,66 @@ StatusOr ElementalIrEmitter::EmitElementalConcatenate( b_->SetInsertPoint(init_block); + // Assign a unique id for each *different* operand, and count how often each + // operand is used. If all operands are different, the usage count will be 1 + // for each operand. + absl::flat_hash_map to_unique_operand_id; + std::vector operand_usage_count; + for (const auto* operand : hlo->operands()) { + if (to_unique_operand_id.contains(operand)) { + ++operand_usage_count[to_unique_operand_id[operand]]; + } else { + int64 unique_operand_id = to_unique_operand_id.size(); + to_unique_operand_id[operand] = unique_operand_id; + operand_usage_count.push_back(1); + } + } + + // To avoid that we emit the same operand more than once, we create one basic + // block for each *different* operand with a PHI node for the different source + // index inputs. + std::vector emit_operand_blocks( + to_unique_operand_id.size(), nullptr); + std::vector source_index_phis(to_unique_operand_id.size(), + nullptr); + for (const auto* operand : hlo->operands()) { + int64 operand_id = to_unique_operand_id[operand]; + if (emit_operand_blocks[operand_id] != nullptr) { + continue; + } + + emit_operand_blocks[operand_id] = llvm_ir::CreateBasicBlock( + exit_block, StrCat("concat_index_from_operand_id", operand_id), b_); + auto saved_insert_point = b_->GetInsertPoint(); + llvm_ir::SetToFirstInsertPoint(emit_operand_blocks[operand_id], b_); + source_index_phis[operand_id] = + PHI(source_index.GetType(), operand_usage_count[operand_id]); + auto operand_index = source_index; + operand_index[concat_dim] = source_index_phis[operand_id]; + + // Create the terminator of the block before calling operand generators, + // because they require non-degenerate basic blocks. + b_->SetInsertPoint(llvm::BranchInst::Create( + exit_block, /*InsertAtEnd=*/emit_operand_blocks[operand_id])); + TF_ASSIGN_OR_RETURN(llvm::Value * value, + operand_to_generator.at(operand)(operand_index)); + output->addIncoming(value, b_->GetInsertBlock()); + b_->SetInsertPoint(init_block, saved_insert_point); + } + for (int64 operand_idx = 0; operand_idx < hlo->operand_count(); ++operand_idx) { const HloInstruction* operand = hlo->operand(operand_idx); - auto true_block = llvm_ir::CreateBasicBlock( - exit_block, StrCat("concat_index_from_operand", operand_idx), b_); auto false_block = llvm_ir::CreateBasicBlock( exit_block, StrCat("concat_index_not_from_operand", operand_idx), b_); auto concat_dim_size = llvm::ConstantInt::get(source_index[concat_dim]->getType(), operand->shape().dimensions(concat_dim)); - CondBr(ICmpULT(source_index[concat_dim], concat_dim_size), true_block, - false_block); - - // Create the terminator of the true block before calling operand - // generators, because they require non-degenerate basic blocks. - b_->SetInsertPoint( - llvm::BranchInst::Create(exit_block, /*InsertAtEnd=*/true_block)); - TF_ASSIGN_OR_RETURN(llvm::Value * value, - operand_to_generator.at(operand)(source_index)); - output->addIncoming(value, b_->GetInsertBlock()); + int64 operand_id = to_unique_operand_id[operand]; + source_index_phis[operand_id]->addIncoming(source_index[concat_dim], + b_->GetInsertBlock()); + CondBr(ICmpULT(source_index[concat_dim], concat_dim_size), + emit_operand_blocks[operand_id], false_block); // Subtract the size of the concat dimension of the current operand // from the source index. @@ -2204,13 +2245,15 @@ llvm_ir::ElementGenerator ElementalIrEmitter::MakeElementGenerator( : iota->shape(); PrimitiveType component_element_type = component_shape.element_type(); llvm::Value* iota_result; - if (ShapeUtil::ElementIsIntegral(component_shape)) { + if (primitive_util::IsIntegralType(component_element_type) || + component_element_type == PRED) { iota_result = b_->CreateIntCast( elem_index_linear, llvm_ir::PrimitiveTypeToIrType(component_element_type, module_), /*isSigned=*/false); } else { - TF_RET_CHECK(ShapeUtil::ElementIsFloating(component_shape)) + TF_RET_CHECK( + primitive_util::IsFloatingPointType(component_element_type)) << component_element_type; llvm::Type* float_ir_type; if (component_element_type == BF16) { diff --git a/tensorflow/compiler/xla/service/executable.h b/tensorflow/compiler/xla/service/executable.h index 45f620f3f3..b34bca55a4 100644 --- a/tensorflow/compiler/xla/service/executable.h +++ b/tensorflow/compiler/xla/service/executable.h @@ -61,7 +61,7 @@ struct ExecutionOutput { class Executable { public: explicit Executable( - std::unique_ptr hlo_module, + std::unique_ptr hlo_module, std::unique_ptr hlo_profile_printer_data, std::unique_ptr hlo_profile_index_map) : hlo_module_(std::move(hlo_module)), @@ -162,7 +162,7 @@ class Executable { return hlo_profile_printer_data_ != nullptr; } - const HloModule& module() const { return *hlo_module_; } + HloModule& module() const { return *hlo_module_; } const bool has_module() const { return hlo_module_ != nullptr; } @@ -199,7 +199,7 @@ class Executable { // HloModule this was compiled from. BufferAssignment keeps pointers to // HloInstructions owned by the HloModule so we need to keep the HloModule // around. - const std::unique_ptr hlo_module_; + const std::unique_ptr hlo_module_; // HloSnapshot this was compiled from. Null if not dumping executions. std::unique_ptr hlo_snapshot_; diff --git a/tensorflow/compiler/xla/service/gpu/BUILD b/tensorflow/compiler/xla/service/gpu/BUILD index b1629616ac..bfd1b6cb14 100644 --- a/tensorflow/compiler/xla/service/gpu/BUILD +++ b/tensorflow/compiler/xla/service/gpu/BUILD @@ -701,6 +701,7 @@ cc_library( "//tensorflow/compiler/xla/service:hlo_cse", "//tensorflow/compiler/xla/service:hlo_dce", "//tensorflow/compiler/xla/service:hlo_element_type_converter", + "//tensorflow/compiler/xla/service:hlo_get_dimension_size_rewriter", "//tensorflow/compiler/xla/service:hlo_pass", "//tensorflow/compiler/xla/service:hlo_pass_pipeline", "//tensorflow/compiler/xla/service:hlo_proto", diff --git a/tensorflow/compiler/xla/service/gpu/cudnn_conv_rewriter.cc b/tensorflow/compiler/xla/service/gpu/cudnn_conv_rewriter.cc index 4ce877f62a..e81850db69 100644 --- a/tensorflow/compiler/xla/service/gpu/cudnn_conv_rewriter.cc +++ b/tensorflow/compiler/xla/service/gpu/cudnn_conv_rewriter.cc @@ -77,7 +77,11 @@ bool CanImplementAsCudnnForwardConv(HloInstruction* conv) { return false; } - if (window_util::HasWindowReversal(conv->window())) { + // CuDNN can perform either cross correlation (no reversal), + // or convolution (all dimensions reversed). + if (dnums.input_spatial_dimensions_size() == 2 + ? !window_util::AllOrNoneReversed(conv->window()) + : window_util::HasWindowReversal(conv->window())) { return false; } return true; diff --git a/tensorflow/compiler/xla/service/gpu/cudnn_conv_runner.cc b/tensorflow/compiler/xla/service/gpu/cudnn_conv_runner.cc index 492d290bf4..3425e1b494 100644 --- a/tensorflow/compiler/xla/service/gpu/cudnn_conv_runner.cc +++ b/tensorflow/compiler/xla/service/gpu/cudnn_conv_runner.cc @@ -138,6 +138,7 @@ Status RunCudnnConvImpl(CudnnConvParams params, const int num_dimensions = window.dimensions_size(); CHECK_LE(num_dimensions, 3); + CHECK_GE(num_dimensions, 1); // cuDNN does not support 1D convolutions. We therefore express 1D // convolutions as 2D convolutions where the first spatial dimension is 1. // This matches the behavior of TF (see definition of conv1d in @@ -148,10 +149,15 @@ Status RunCudnnConvImpl(CudnnConvParams params, output_shape.element_type()) << ShapeUtil::HumanString(output_shape); + // If one dimension is reversed, we need to have all dimensions reversed (so + // we're doing convolution not cross correlation). + const bool dims_reversed = window.dimensions()[0].window_reversal(); + CHECK_EQ(num_dimensions, dnums.input_spatial_dimensions_size()); CHECK_EQ(num_dimensions, dnums.kernel_spatial_dimensions_size()); CHECK_EQ(num_dimensions, dnums.output_spatial_dimensions_size()); for (const WindowDimension& dim : window.dimensions()) { + CHECK_EQ(dims_reversed, dim.window_reversal()); CHECK_EQ(dim.padding_low(), dim.padding_high()); CHECK_EQ(dim.base_dilation(), 1) << "cudnn does not support base dilation; it " @@ -198,6 +204,7 @@ Status RunCudnnConvImpl(CudnnConvParams params, ConvolutionDescriptor convolution_descriptor(effective_num_dimensions); convolution_descriptor.set_group_count(feature_group_count); + convolution_descriptor.set_convolution_not_crosscorr(dims_reversed); for (int dim = 0; dim < num_dimensions; ++dim) { convolution_descriptor .set_zero_padding( @@ -363,14 +370,12 @@ StatusOr GetCudnnConvParams( params.output_shape = &conv_result_shape; params.fusion.emplace(); auto& fusion = *params.fusion; - if (backend_config.activation_mode() < - static_cast(se::dnn::ActivationMode::kNumActivationModes)) { - fusion.mode = static_cast( - backend_config.activation_mode()); - } else { + if (!se::dnn::ActivationMode_IsValid(backend_config.activation_mode())) { return InternalError("Bad activation mode: %s", backend_config.ShortDebugString()); } + fusion.mode = static_cast( + backend_config.activation_mode()); fusion.side_input_scale = backend_config.side_input_scale(); params.input_buf = operand_buffers[0]; params.filter_buf = operand_buffers[1]; diff --git a/tensorflow/compiler/xla/service/gpu/elemental_ir_emitter.cc b/tensorflow/compiler/xla/service/gpu/elemental_ir_emitter.cc index 6dcdaf1cfe..2ab754a471 100644 --- a/tensorflow/compiler/xla/service/gpu/elemental_ir_emitter.cc +++ b/tensorflow/compiler/xla/service/gpu/elemental_ir_emitter.cc @@ -161,6 +161,16 @@ StatusOr GpuElementalIrEmitter::EmitFloatBinaryOp( PrimitiveType lhs_input_type = op->operand(0)->shape().element_type(); PrimitiveType rhs_input_type = op->operand(1)->shape().element_type(); PrimitiveType output_type = op->shape().element_type(); + HloOpcode opcode = op->opcode(); + + if (hlo_module_config_.debug_options().xla_gpu_enable_fast_min_max() && + (opcode == HloOpcode::kMaximum || opcode == HloOpcode::kMinimum)) { + return llvm_ir::EmitCallToIntrinsic( + opcode == HloOpcode::kMaximum ? llvm::Intrinsic::maxnum + : llvm::Intrinsic::minnum, + {lhs_value, rhs_value}, {lhs_value->getType()}, b_); + } + switch (op->opcode()) { case HloOpcode::kRemainder: { return EmitLibdeviceMathCall("__nv_fmod", {lhs_value, rhs_value}, diff --git a/tensorflow/compiler/xla/service/gpu/fusion_merger.cc b/tensorflow/compiler/xla/service/gpu/fusion_merger.cc index 30c1f90889..470457935a 100644 --- a/tensorflow/compiler/xla/service/gpu/fusion_merger.cc +++ b/tensorflow/compiler/xla/service/gpu/fusion_merger.cc @@ -229,7 +229,7 @@ Status FusionInstructionMerger::HandleFusion(HloInstruction* fusion) { if (!absl::c_all_of(fusion->users(), [&](const HloInstruction* user) { return user->opcode() == HloOpcode::kFusion && (user->fusion_kind() == HloInstruction::FusionKind::kLoop || - (user->fusion_kind() == HloInstruction::FusionKind::kInput && + (IsReduceInputFusion(*user) && LayoutsAreReduceInputFusionFriendly(*fusion, *user))); })) { VLOG(3) << "Not merging " << fusion->name() diff --git a/tensorflow/compiler/xla/service/gpu/gpu_executable.cc b/tensorflow/compiler/xla/service/gpu/gpu_executable.cc index 5742632782..ae2e718db2 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_executable.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_executable.cc @@ -51,7 +51,7 @@ GpuExecutable::GpuExecutable( const string& ptx, const std::vector& cubin, std::pair compute_capability, std::unique_ptr thunk_schedule, - std::unique_ptr hlo_module, + std::unique_ptr hlo_module, std::unique_ptr assignment, std::unique_ptr hlo_profile_printer_data, std::unique_ptr hlo_profile_index_map) diff --git a/tensorflow/compiler/xla/service/gpu/gpu_executable.h b/tensorflow/compiler/xla/service/gpu/gpu_executable.h index 0e276282e4..2b3c77f5b8 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_executable.h +++ b/tensorflow/compiler/xla/service/gpu/gpu_executable.h @@ -54,7 +54,7 @@ class GpuExecutable : public Executable { GpuExecutable(const string& ptx, const std::vector& cubin, std::pair compute_capability, std::unique_ptr thunk_schedule, - std::unique_ptr hlo_module, + std::unique_ptr hlo_module, std::unique_ptr assignment, std::unique_ptr hlo_profile_printer_data, std::unique_ptr hlo_profile_index_map); diff --git a/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc b/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc index 2d31fd5570..452e763a8e 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc @@ -55,7 +55,7 @@ bool LayoutsAreReduceInputFusionFriendly(const HloInstruction& producer, }); } -bool IsInputFusibleReduction(const HloInstruction& instr) { +bool IsReduceInputFusion(const HloInstruction& instr) { if (instr.IsMultiOutputFusion()) { for (const HloInstruction* operand : instr.fused_expression_root()->operands()) { @@ -67,17 +67,70 @@ bool IsInputFusibleReduction(const HloInstruction& instr) { return true; } } - return false; - } else if (instr.opcode() == HloOpcode::kFusion) { - if (IsReductionToVector(*instr.fused_expression_root())) { - CHECK(instr.fusion_kind() == HloInstruction::FusionKind::kInput) - << " Fusion rooted at reduction-to-vector op must be of kind kInput: " - << instr.ToString(); - return true; + } else if (instr.opcode() == HloOpcode::kFusion && + IsReductionToVector(*instr.fused_expression_root())) { + CHECK(instr.fusion_kind() == HloInstruction::FusionKind::kInput) + << " Fusion rooted at reduction-to-vector op must be of kind kInput: " + << instr.ToString(); + return true; + } + return false; +} + +bool IsInputFusibleReduction(const HloInstruction& instr) { + return IsReduceInputFusion(instr) || IsReductionToVector(instr); +} + +bool ShapesCompatibleForMultiOutputFusion(const HloInstruction& instr1, + const HloInstruction& instr2) { + // Returns the instructions that determines the emitter used for lowering, + // sometimes referred to as "the real hero". + auto get_real_hero = + [&](const HloInstruction* instr) -> const HloInstruction* { + if (instr->opcode() == HloOpcode::kFusion) { + auto fused_expression_root = instr->fused_expression_root(); + if (instr->IsMultiOutputFusion()) { + // If possible, we want to pick a reduction-to-vector operand of the + // fusion root, because it has the most constraints. + for (const auto* inst : fused_expression_root->operands()) { + if (IsReductionToVector(*inst)) { + return inst; + } + } + return fused_expression_root->operands()[0]; + } + return fused_expression_root; } + return instr; + }; + + // Multi-output fusion kernels share a common parallel loop. The loop + // dimenstions are determined by instruction shapes. + auto get_loop_shape = [&](const HloInstruction* element_instr) { + // Special-case reduction-to-vector ops: The loop dimensions are determined + // by the shape of the first operand. + if (IsReductionToVector(*element_instr)) { + return element_instr->operand(0)->shape(); + } + return element_instr->shape(); + }; + + // All shapes of the root tuple of multi-output fusions should agree, i.e. all + // root ops should have equal output shapes. An exception are + // reduction-to-vector ops. Here the input shapes of the reduction (first + // operand shape) and the reduction dimensions need to match. + auto* instr_1 = get_real_hero(&instr1); + auto* instr_2 = get_real_hero(&instr2); + // TODO(tjoerg): Relax the shape constraint. The datatype does not matter. + if (IsReductionToVector(*instr_1) && IsReductionToVector(*instr_2) && + (!ShapeUtil::Equal(instr_1->shape(), instr_2->shape()) || + instr_1->dimensions() != instr_2->dimensions())) { return false; } - return IsReductionToVector(instr); + // The elementwise output shapes must be the same (including layout). + // TODO(tjoerg): Further relax the constraint. The datatype does not matter. + return ShapeUtil::EqualIgnoringFpPrecision(get_loop_shape(instr_1), + get_loop_shape(instr_2)); } } // namespace gpu diff --git a/tensorflow/compiler/xla/service/gpu/gpu_fusible.h b/tensorflow/compiler/xla/service/gpu/gpu_fusible.h index f7c24a0d5b..e9d7ba1c4c 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_fusible.h +++ b/tensorflow/compiler/xla/service/gpu/gpu_fusible.h @@ -33,16 +33,29 @@ namespace gpu { bool LayoutsAreReduceInputFusionFriendly(const HloInstruction& producer, const HloInstruction& reduce); -// Whether `instr` is fusible as root of a reduce input fusions, i.e. `instr` -// is either an unfused reduction-to-vector op, an input fusion rooted at a -// reduction-to-vector op, or a multi-output input fusion with at least one -// reduction-to-vector op root. // Note that reduction ops are lowered in different ways. Reduce input fusions // are lowered by IrEmitterUnnested::EmitReductionToVector and must be rooted at // reduction-to-vector ops. Other reduction ops are lowered by // GpuElementalIrEmitter and fused like elementwise ops. + +// Whether `instr` is an input fusion rooted at a reduction-to-vector op or a +// multi-output input fusion with at least one reduction-to-vector op root. +bool IsReduceInputFusion(const HloInstruction& instr); + +// Whether `instr` is fusible as root of a reduce input fusions, i.e. `instr` +// is either an unfused reduction-to-vector op or a reduce input fusion. bool IsInputFusibleReduction(const HloInstruction& instr); +// Whether instruction shapes are compatible for multi-output fusion, i.e. +// whether the emitters support lowering the resulting fusion. +// This function works for both, sibling and producer-conumser multi-output +// fusion. +// So far, multi-output fusion is supported for loop fusions and reduce +// input fusions only. It is up to the caller to ensure the instructions +// themselves are fusible! +bool ShapesCompatibleForMultiOutputFusion(const HloInstruction& instr1, + const HloInstruction& instr2); + } // namespace gpu } // namespace xla diff --git a/tensorflow/compiler/xla/service/gpu/gpu_fusible_test.cc b/tensorflow/compiler/xla/service/gpu/gpu_fusible_test.cc index d91b7bc61f..15d4ee206c 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_fusible_test.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_fusible_test.cc @@ -178,7 +178,7 @@ TEST_F(GpuFusibleTest, EXPECT_TRUE(LayoutsAreReduceInputFusionFriendly(*loop_fusion, *reduce)); } -TEST_F(GpuFusibleTest, IsInputFusibleReduction_ReductionToVector) { +TEST_F(GpuFusibleTest, IsReduceInputFusion_ReductionToVector) { auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( ENTRY entry { c0 = f32[] parameter(0) @@ -191,10 +191,11 @@ TEST_F(GpuFusibleTest, IsInputFusibleReduction_ReductionToVector) { const HloInstruction* reduce = module->entry_computation()->root_instruction(); ASSERT_EQ(reduce->opcode(), HloOpcode::kReduce); + EXPECT_FALSE(IsReduceInputFusion(*reduce)); EXPECT_TRUE(IsInputFusibleReduction(*reduce)); } -TEST_F(GpuFusibleTest, IsInputFusibleReduction_ElementalReduction) { +TEST_F(GpuFusibleTest, IsReduceInputFusion_ElementalReduction) { auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( ENTRY entry { c0 = f32[] parameter(0) @@ -207,10 +208,11 @@ TEST_F(GpuFusibleTest, IsInputFusibleReduction_ElementalReduction) { const HloInstruction* reduce = module->entry_computation()->root_instruction(); ASSERT_EQ(reduce->opcode(), HloOpcode::kReduce); + EXPECT_FALSE(IsReduceInputFusion(*reduce)); EXPECT_FALSE(IsInputFusibleReduction(*reduce)); } -TEST_F(GpuFusibleTest, IsInputFusibleReduction_SingleOutputInputReduceFusion) { +TEST_F(GpuFusibleTest, IsReduceInputFusion_SingleOutputInputReduceFusion) { auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( fused_reduction { c0 = f32[] parameter(0) @@ -225,10 +227,11 @@ TEST_F(GpuFusibleTest, IsInputFusibleReduction_SingleOutputInputReduceFusion) { const HloInstruction* reduce = module->entry_computation()->root_instruction(); ASSERT_EQ(reduce->opcode(), HloOpcode::kFusion); + EXPECT_TRUE(IsReduceInputFusion(*reduce)); EXPECT_TRUE(IsInputFusibleReduction(*reduce)); } -TEST_F(GpuFusibleTest, IsInputFusibleReduction_SingleOutputLoopReduceFusion) { +TEST_F(GpuFusibleTest, IsReduceInputFusion_SingleOutputLoopReduceFusion) { auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( fused_reduction { c0 = f32[] parameter(0) @@ -243,10 +246,11 @@ TEST_F(GpuFusibleTest, IsInputFusibleReduction_SingleOutputLoopReduceFusion) { const HloInstruction* reduce = module->entry_computation()->root_instruction(); ASSERT_EQ(reduce->opcode(), HloOpcode::kFusion); + EXPECT_FALSE(IsReduceInputFusion(*reduce)); EXPECT_FALSE(IsInputFusibleReduction(*reduce)); } -TEST_F(GpuFusibleTest, IsInputFusibleReduction_MultiOutputInputReduceFusion) { +TEST_F(GpuFusibleTest, IsReduceInputFusion_MultiOutputInputReduceFusion) { auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( fused_reduction { c0 = f32[] parameter(0) @@ -263,11 +267,12 @@ TEST_F(GpuFusibleTest, IsInputFusibleReduction_MultiOutputInputReduceFusion) { const HloInstruction* reduce = module->entry_computation()->root_instruction(); ASSERT_EQ(reduce->opcode(), HloOpcode::kFusion); + EXPECT_TRUE(IsReduceInputFusion(*reduce)); EXPECT_TRUE(IsInputFusibleReduction(*reduce)); } TEST_F(GpuFusibleTest, - IsInputFusibleReduction_MultiOutputInputReduceFusionWithExtraOutputs) { + IsReduceInputFusion_MultiOutputInputReduceFusionWithExtraOutputs) { auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( fused_reduction { c0 = f32[] parameter(0) @@ -284,10 +289,11 @@ TEST_F(GpuFusibleTest, const HloInstruction* reduce = module->entry_computation()->root_instruction(); ASSERT_EQ(reduce->opcode(), HloOpcode::kFusion); + EXPECT_TRUE(IsReduceInputFusion(*reduce)); EXPECT_TRUE(IsInputFusibleReduction(*reduce)); } -TEST_F(GpuFusibleTest, IsInputFusibleReduction_MultiOutputLoopReduceFusion) { +TEST_F(GpuFusibleTest, IsReduceInputFusion_MultiOutputLoopReduceFusion) { auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( fused_reduction { c0 = f32[] parameter(0) @@ -304,11 +310,12 @@ TEST_F(GpuFusibleTest, IsInputFusibleReduction_MultiOutputLoopReduceFusion) { const HloInstruction* reduce = module->entry_computation()->root_instruction(); ASSERT_EQ(reduce->opcode(), HloOpcode::kFusion); + EXPECT_FALSE(IsReduceInputFusion(*reduce)); EXPECT_FALSE(IsInputFusibleReduction(*reduce)); } TEST_F(GpuFusibleTest, - IsInputFusibleReduction_MultiOutputLoopFusionReduceAndElementwiseOp) { + IsReduceInputFusion_MultiOutputLoopFusionReduceAndElementwiseOp) { auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( fused_reduction { c0 = f32[] parameter(0) @@ -325,8 +332,304 @@ TEST_F(GpuFusibleTest, const HloInstruction* reduce = module->entry_computation()->root_instruction(); ASSERT_EQ(reduce->opcode(), HloOpcode::kFusion); + EXPECT_FALSE(IsReduceInputFusion(*reduce)); EXPECT_FALSE(IsInputFusibleReduction(*reduce)); } +TEST_F(GpuFusibleTest, ShapesCompatibleForMultiOutputFusion_LoopFusions) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + fused_computation_1 { + p0.1 = f32[6400]{0} parameter(0) + ROOT mul = f32[6400]{0} multiply(p0.1, p0.1) + } + + fused_computation_2 { + p0.2 = f32[6400]{0} parameter(0) + const.2 = f32[] constant(1) + ROOT div = f32[6400]{0} divide(p0.2, const.2) + } + + ENTRY entry { + p0 = f32[6400]{0} parameter(0) + fusion.1 = f32[6400]{0} fusion(p0), kind=kLoop, calls=fused_computation_1 + fusion.2 = f32[6400]{0} fusion(p0), kind=kLoop, calls=fused_computation_2 + ROOT root = (f32[6400]{0}, f32[6400]{0}) tuple(fusion.1, fusion.2) + })")) + .ValueOrDie(); + const HloInstruction* fusion_1 = + module->entry_computation()->root_instruction()->operand(0); + const HloInstruction* fusion_2 = + module->entry_computation()->root_instruction()->operand(1); + EXPECT_TRUE(ShapesCompatibleForMultiOutputFusion(*fusion_1, *fusion_2)); +} + +TEST_F(GpuFusibleTest, ShapesCompatibleForMultiOutputFusion_IgnoreFpPrecision) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + fused_computation_1 { + p0.1 = f32[6400]{0} parameter(0) + ROOT mul = f32[6400]{0} multiply(p0.1, p0.1) + } + + fused_computation_2 { + p0.2 = f32[6400]{0} parameter(0) + ROOT convert = f16[6400]{0} convert(p0.2) + } + + ENTRY entry { + p0 = f32[6400]{0} parameter(0) + fusion.1 = f32[6400]{0} fusion(p0), kind=kLoop, calls=fused_computation_1 + fusion.2 = f32[6400]{0} fusion(p0), kind=kLoop, calls=fused_computation_2 + ROOT root = (f32[6400]{0}, f32[6400]{0}) tuple(fusion.1, fusion.2) + })")) + .ValueOrDie(); + const HloInstruction* fusion_1 = + module->entry_computation()->root_instruction()->operand(0); + const HloInstruction* fusion_2 = + module->entry_computation()->root_instruction()->operand(1); + EXPECT_TRUE(ShapesCompatibleForMultiOutputFusion(*fusion_1, *fusion_2)); +} + +TEST_F(GpuFusibleTest, ShapesCompatibleForMultiOutputFusion_Reduce) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + fused_computation_1 { + p0.1 = f32[6400]{0} parameter(0) + ROOT mul = f32[6400]{0} multiply(p0.1, p0.1) + } + + ENTRY entry { + p0 = f32[6400]{0} parameter(0) + fusion.1 = f32[6400]{0} fusion(p0), kind=kLoop, calls=fused_computation_1 + const.2 = f32[] constant(0) + reduce = f32[] reduce(p0, const.2), dimensions={0}, to_apply=scalar_add + ROOT root = (f32[6400]{0}, f32[]) tuple(fusion.1, reduce) + })")) + .ValueOrDie(); + const HloInstruction* fusion = + module->entry_computation()->root_instruction()->operand(0); + const HloInstruction* reduce = + module->entry_computation()->root_instruction()->operand(1); + EXPECT_TRUE(ShapesCompatibleForMultiOutputFusion(*fusion, *reduce)); +} + +TEST_F(GpuFusibleTest, ShapesCompatibleForMultiOutputFusion_Elementwise) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + fused_computation_1 { + p0.1 = f32[6400]{0} parameter(0) + ROOT mul = f32[6400]{0} multiply(p0.1, p0.1) + } + + ENTRY entry { + p0 = f32[6400]{0} parameter(0) + fusion.1 = f32[6400]{0} fusion(p0), kind=kLoop, calls=fused_computation_1 + const.2 = f32[] constant(1) + div = f32[6400]{0} divide(p0, const.2) + ROOT root = (f32[6400]{0}, f32[6400]{0}) tuple(fusion.1, div) + })")) + .ValueOrDie(); + const HloInstruction* fusion = + module->entry_computation()->root_instruction()->operand(0); + const HloInstruction* div = + module->entry_computation()->root_instruction()->operand(1); + EXPECT_TRUE(ShapesCompatibleForMultiOutputFusion(*fusion, *div)); +} + +TEST_F(GpuFusibleTest, + ShapesCompatibleForMultiOutputFusion_MultiOutputLoopFusion) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + fused_computation_1 { + p0.1 = f32[8,1,5,16,1,1]{5,4,3,2,1,0} parameter(0) + mul = f32[8,1,5,16,1,1]{5,4,3,2,1,0} multiply(p0.1, p0.1) + exp = f32[8,1,5,16,1,1]{5,4,3,2,1,0} exponential(p0.1) + ROOT tuple = (f32[8,1,5,16,1,1]{5,4,3,2,1,0}, f32[8,1,5,16,1,1]{5,4,3,2,1,0}) tuple(mul, exp) + } + + fused_computation_2 { + p0.2 = f32[8,1,5,16,1,1]{5,4,3,2,1,0} parameter(0) + const.2 = f32[] constant(0) + ROOT add = f32[8,1,5,16,1,1]{5,4,3,2,1,0} add(p0.2, const.2) + } + + ENTRY entry { + p0 = f32[8,1,5,16,1,1]{5,4,3,2,1,0} parameter(0) + fusion.1 = (f32[8,1,5,16,1,1]{5,4,3,2,1,0}, f32[8,1,5,16,1,1]{5,4,3,2,1,0}) fusion(p0), kind=kLoop, calls=fused_computation_1 + fusion.2 = f32[8,1,5,16,1,1]{5,4,3,2,1,0} fusion(p0), kind=kLoop, calls=fused_computation_2 + gte0 = f32[8,1,5,16,1,1]{5,4,3,2,1,0} get-tuple-element(fusion.1), index=0 + gte1 = f32[8,1,5,16,1,1]{5,4,3,2,1,0} get-tuple-element(fusion.1), index=1 + ROOT root = (f32[8,1,5,16,1,1]{5,4,3,2,1,0}, f32[8,1,5,16,1,1]{5,4,3,2,1,0}, f32[8,1,5,16,1,1]{5,4,3,2,1,0}) tuple(gte0, gte1, fusion.2) + })")) + .ValueOrDie(); + const HloInstruction* fusion_1 = + module->entry_computation()->root_instruction()->operand(0)->operand(0); + const HloInstruction* fusion_2 = + module->entry_computation()->root_instruction()->operand(1)->operand(0); + EXPECT_TRUE(ShapesCompatibleForMultiOutputFusion(*fusion_1, *fusion_2)); +} + +TEST_F(GpuFusibleTest, ShapesCompatibleForMultiOutputFusion_UnfusedOps) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + ENTRY reduce { + p0 = f32[2,2,2]{2,1,0} parameter(0) + c0 = f32[] constant(0) + exp = f32[2,2,2]{2,1,0} exponential(p0) + reduce = f32[2,2]{1,0} reduce(exp, c0), dimensions={2}, to_apply=scalar_add + ROOT root = (f32[2,2]{1,0}, f32[2,2,2]{2,1,0}) tuple(reduce, exp) + })")) + .ValueOrDie(); + const HloInstruction* reduce = + module->entry_computation()->root_instruction()->operand(0); + const HloInstruction* exp = + module->entry_computation()->root_instruction()->operand(1); + EXPECT_TRUE(ShapesCompatibleForMultiOutputFusion(*reduce, *exp)); +} + +TEST_F(GpuFusibleTest, ShapesCompatibleForMultiOutputFusion_DifferentLayouts) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + ENTRY reduce { + p0 = f32[2,2,2]{2,1,0} parameter(0) + p1 = f32[2,2,2]{0,1,2} parameter(1) + c0 = f32[] constant(0) + exp = f32[2,2,2]{2,1,0} exponential(p0) + reduce = f32[2,2]{0,1} reduce(p1, c0), dimensions={2}, to_apply=scalar_add + ROOT root = (f32[2,2]{0,1}, f32[2,2,2]{2,1,0}) tuple(reduce, exp) + })")) + .ValueOrDie(); + const HloInstruction* reduce = + module->entry_computation()->root_instruction()->operand(0); + const HloInstruction* exp = + module->entry_computation()->root_instruction()->operand(1); + EXPECT_FALSE(ShapesCompatibleForMultiOutputFusion(*reduce, *exp)); +} + +TEST_F(GpuFusibleTest, + ShapesCompatibleForMultiOutputFusion_MultiOutputReduceFusion) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + fused_select { + p1.1 = f32[2,2,2]{2,1,0} parameter(1) + c0 = f32[] constant(0) + broadcast = f32[2,2,2]{2,1,0} broadcast(f32[] c0), dimensions={} + greater-than = pred[2,2,2]{2,1,0} greater-than(f32[2,2,2]{2,1,0} p1.1, f32[2,2,2]{2,1,0} broadcast) + p0.1 = f32[2,2,2]{2,1,0} parameter(0) + ROOT select = f32[2,2,2]{2,1,0} select(pred[2,2,2]{2,1,0} greater-than, f32[2,2,2]{2,1,0} p0.1, f32[2,2,2]{2,1,0} broadcast) + } + + fused_reduce { + p0.2 = f32[2,2,2]{2,1,0} parameter(0) + c1 = f32[] constant(0) + r1 = f32[2,2]{1,0} reduce(p0.2, c1), dimensions={2}, to_apply=scalar_add + mul = f32[2,2,2]{2,1,0} multiply(p0.2, p0.2) + r2 = f32[2,2]{1,0} reduce(mul, c1), dimensions={2}, to_apply=scalar_add + ROOT tuple = (f32[2,2]{1,0}, f32[2,2]{1,0}) tuple(r1, r2) + } + + ENTRY reduce { + p0 = f32[2,2,2]{2,1,0} parameter(0) + p1 = f32[2,2,2]{2,1,0} parameter(1) + select = f32[2,2,2]{2,1,0} fusion(p0, p1), kind=kLoop, calls=fused_select + fusion = (f32[2,2]{1,0}, f32[2,2]{1,0}) fusion(select), kind=kInput, calls=fused_reduce + gte0 = f32[2,2]{1,0} get-tuple-element(fusion), index=0 + gte1 = f32[2,2]{1,0} get-tuple-element(fusion), index=1 + ROOT root = (f32[2,2]{1,0}, f32[2,2]{1,0}, f32[2,2,2]{2,1,0}) tuple(gte1, gte1, select) + })")) + .ValueOrDie(); + const HloInstruction* fusion_1 = + module->entry_computation()->root_instruction()->operand(0)->operand(0); + const HloInstruction* fusion_2 = + module->entry_computation()->root_instruction()->operand(1)->operand(0); + EXPECT_TRUE(ShapesCompatibleForMultiOutputFusion(*fusion_1, *fusion_2)); +} + +TEST_F(GpuFusibleTest, ShapesCompatibleForMultiOutputFusion_ReduceFusions) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + fused_reduce_1 { + p0.1 = f32[2,2,2]{2,1,0} parameter(0) + c0 = f32[] constant(0) + ROOT reduce = f32[2,2]{1,0} reduce(f32[2,2,2]{2,1,0} p0.1, f32[] c0), dimensions={0}, to_apply=scalar_add + } + + fused_reduce_2 { + p0.2 = f32[2,2,2]{2,1,0} parameter(0) + mul = f32[2,2,2]{2,1,0} multiply(f32[2,2,2]{2,1,0} p0.2, f32[2,2,2]{2,1,0} p0.2) + c1 = f32[] constant(0) + ROOT reduce = f32[2,2]{1,0} reduce(f32[2,2,2]{2,1,0} mul, f32[] c1), dimensions={0}, to_apply=scalar_add + } + + ENTRY reduce { + p0 = f32[2,2,2]{2,1,0} parameter(0) + p1 = f32[2,2,2]{2,1,0} parameter(1) + reduce_1 = f32[2,2]{1,0} fusion(p0), kind=kLoop, calls=fused_reduce_1 + reduce_2 = f32[2,2]{1,0} fusion(p1), kind=kLoop, calls=fused_reduce_2 + ROOT root = (f32[2,2]{1,0}, f32[2,2,2]{2,1,0}) tuple(reduce_1, reduce_2) + })")) + .ValueOrDie(); + const HloInstruction* fusion_1 = + module->entry_computation()->root_instruction()->operand(0); + const HloInstruction* fusion_2 = + module->entry_computation()->root_instruction()->operand(1); + EXPECT_TRUE(ShapesCompatibleForMultiOutputFusion(*fusion_1, *fusion_2)); +} + +TEST_F(GpuFusibleTest, + ShapesCompatibleForMultiOutputFusion_DifferentReduceDimensions) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + fused_reduce_1 { + p0.1 = f32[2,2,2]{2,1,0} parameter(0) + c0 = f32[] constant(0) + ROOT reduce = f32[2,2]{1,0} reduce(f32[2,2,2]{2,1,0} p0.1, f32[] c0), dimensions={0}, to_apply=scalar_add + } + + fused_reduce_2 { + p0.2 = f32[2,2,2]{2,1,0} parameter(0) + mul = f32[2,2,2]{2,1,0} multiply(f32[2,2,2]{2,1,0} p0.2, f32[2,2,2]{2,1,0} p0.2) + c1 = f32[] constant(0) + ROOT reduce = f32[2,2]{1,0} reduce(f32[2,2,2]{2,1,0} mul, f32[] c1), dimensions={2}, to_apply=scalar_add + } + + ENTRY reduce { + p0 = f32[2,2,2]{2,1,0} parameter(0) + p1 = f32[2,2,2]{2,1,0} parameter(1) + reduce_1 = f32[2,2]{1,0} fusion(p0), kind=kLoop, calls=fused_reduce_1 + reduce_2 = f32[2,2]{1,0} fusion(p1), kind=kLoop, calls=fused_reduce_2 + ROOT root = (f32[2,2]{1,0}, f32[2,2,2]{2,1,0}) tuple(reduce_1, reduce_2) + })")) + .ValueOrDie(); + const HloInstruction* fusion_1 = + module->entry_computation()->root_instruction()->operand(0); + const HloInstruction* fusion_2 = + module->entry_computation()->root_instruction()->operand(1); + EXPECT_FALSE(ShapesCompatibleForMultiOutputFusion(*fusion_1, *fusion_2)); +} + +TEST_F(GpuFusibleTest, + ShapesCompatibleForMultiOutputFusion_NoReductionToVector) { + auto module = ParseHloString(absl::StrCat(kModulePrefix, R"( + fused_element_wise { + p0.1 = f32[2,2,2]{2,1,0} parameter(0) + p1.1 = f32[2,2,2]{2,1,0} parameter(1) + ROOT add = f32[2,2,2]{2,1,0} add(p0.1, p1.1) + } + + fused_reduce { + p0.2 = f32[2,2,2]{2,1,0} parameter(0) + mul = f32[2,2,2]{2,1,0} multiply(f32[2,2,2]{2,1,0} p0.2, f32[2,2,2]{2,1,0} p0.2) + c1 = f32[] constant(0) + // Note that reduce is not a reduction-to-vector. + ROOT reduce = f32[2,2]{1,0} reduce(f32[2,2,2]{2,1,0} mul, f32[] c1), dimensions={1}, to_apply=scalar_add + } + + ENTRY reduce { + p0 = f32[2,2,2]{2,1,0} parameter(0) + p1 = f32[2,2,2]{2,1,0} parameter(1) + element_wise = f32[2,2,2]{2,1,0} fusion(p0, p1), kind=kLoop, calls=fused_element_wise + fusion = (f32[2,2]{1,0}, f32[2,2]{1,0}) fusion(element_wise), kind=kLoop, calls=fused_reduce + ROOT root = (f32[2,2]{1,0}, f32[2,2,2]{2,1,0}) tuple(fusion, element_wise) + })")) + .ValueOrDie(); + const HloInstruction* fusion_1 = + module->entry_computation()->root_instruction()->operand(0); + const HloInstruction* fusion_2 = + module->entry_computation()->root_instruction()->operand(1); + EXPECT_FALSE(ShapesCompatibleForMultiOutputFusion(*fusion_1, *fusion_2)); +} + } // namespace gpu } // namespace xla diff --git a/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule.cc b/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule.cc index 91609c730b..1126943624 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule.cc @@ -37,7 +37,7 @@ class GpuHloOrdering : public PredecessorHloOrdering { public: GpuHloOrdering(const HloModule* module, const StreamAssignment& stream_assignment, - const std::vector& thunk_launch_order); + const std::vector& thunk_launch_order); ~GpuHloOrdering() override = default; // Only the entry computation can possibly be sequentially ordered, and only @@ -56,7 +56,7 @@ class GpuHloOrdering : public PredecessorHloOrdering { GpuHloOrdering::GpuHloOrdering( const HloModule* module, const StreamAssignment& stream_assignment, - const std::vector& thunk_launch_order) + const std::vector& thunk_launch_order) : PredecessorHloOrdering(module) { // The entry computation has a total order when there's only one stream. if (stream_assignment.StreamCount() == 1) { @@ -150,7 +150,7 @@ GpuHloOrdering::GpuHloOrdering( // However, if the total order is A,B,D,C,E, then C and E can run // concurrently. void BFSLaunchOrder(const HloComputation* computation, - std::vector* launch_order) { + std::vector* launch_order) { // This topological sort uses two data structures: // 1. `incoming_edge_count` which keeps track of the number of incoming // edges to each HLO; @@ -158,9 +158,9 @@ void BFSLaunchOrder(const HloComputation* computation, // // The sorting algorithm repeatedly pops the top from the queue and deletes // that HLO from the graph, making more HLOs incoming-edge free. - std::deque queue; + std::deque queue; std::unordered_map incoming_edge_count; - for (const auto& hlo : computation->instructions()) { + for (auto* hlo : computation->instructions()) { if (hlo->operand_count() == 0) { queue.push_back(hlo); } else { @@ -172,10 +172,10 @@ void BFSLaunchOrder(const HloComputation* computation, } while (!queue.empty()) { - const HloInstruction* x = queue.front(); + HloInstruction* x = queue.front(); queue.pop_front(); launch_order->push_back(x); - for (const HloInstruction* y : x->users()) { + for (HloInstruction* y : x->users()) { --incoming_edge_count[y]; if (incoming_edge_count[y] == 0) { queue.push_back(y); @@ -195,14 +195,14 @@ StatusOr> GpuHloSchedule::Build( std::unique_ptr schedule(new GpuHloSchedule); // Initialize thunk_launch_order_, the total order of thunk launches. - const HloComputation* entry_computation = module.entry_computation(); + HloComputation* entry_computation = module.entry_computation(); if (stream_assignment.StreamCount() == 1) { // All kernels are launched on a single stream, so there's no loss of // concurrency by optimizing for minimal memory usage. TF_ASSIGN_OR_RETURN( HloInstructionSequence sequence, ScheduleComputation( - *entry_computation, [pointer_size](const BufferValue& buffer) { + entry_computation, [pointer_size](const BufferValue& buffer) { return ShapeUtil::ByteSizeOf(buffer.shape(), pointer_size); })); schedule->thunk_launch_order_ = sequence.instructions(); diff --git a/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule.h b/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule.h index 07a7fc67aa..7f224ffe4f 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule.h +++ b/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule.h @@ -46,7 +46,7 @@ class GpuHloSchedule { // Returns the total order of thunk launches, represented in terms of HLO // instructions. - const std::vector& ThunkLaunchOrder() const { + const std::vector& ThunkLaunchOrder() const { return thunk_launch_order_; } @@ -60,7 +60,7 @@ class GpuHloSchedule { private: GpuHloSchedule(); - std::vector thunk_launch_order_; + std::vector thunk_launch_order_; std::unique_ptr hlo_ordering_; }; diff --git a/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule_test.cc b/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule_test.cc index 6d3aed15eb..91db7151f2 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule_test.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_hlo_schedule_test.cc @@ -33,7 +33,7 @@ namespace gpu { class GpuHloScheduleTest : public HloTestBase { protected: - using HloVec = std::vector; + using HloVec = std::vector; // Pre-canned shapes. Shape f32_2x2_ = ShapeUtil::MakeShape(F32, {2, 2}); @@ -44,7 +44,7 @@ class GpuHloScheduleTest : public HloTestBase { .ConsumeValueOrDie(); } - std::unique_ptr CreateNewUnverifiedModule() { + std::unique_ptr CreateNewVerifiedModule() { HloModuleConfig config; auto debug_options = GetDebugOptionsForTest(); debug_options.set_xla_gpu_disable_multi_streaming(false); @@ -79,7 +79,7 @@ TEST_F(GpuHloScheduleTest, SequentialMatMul) { HloInstruction* dot2 = builder.AddInstruction(CreateCanonicalDot(f32_2x2_, dot1, z)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build(dot2)); std::unique_ptr streams = AssignStreams(*module); @@ -139,7 +139,7 @@ TEST_F(GpuHloScheduleTest, SequentialAdd) { HloInstruction* add3 = builder.AddInstruction( HloInstruction::CreateBinary(f32_2x2_, HloOpcode::kAdd, add1, add2)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build(add3)); std::unique_ptr streams = AssignStreams(*module); @@ -209,7 +209,7 @@ TEST_F(GpuHloScheduleTest, ConcurrentMatMul) { HloInstruction* add = builder.AddInstruction(CreateCanonicalDot(f32_2x2_, dot1, dot2)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build(add)); std::unique_ptr streams = AssignStreams(*module); @@ -288,7 +288,7 @@ TEST_F(GpuHloScheduleTest, LatticeMatMul) { HloInstruction* d40 = builder.AddInstruction(CreateCanonicalDot(f32_2x2_, d30, d31)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build(d40)); std::unique_ptr streams = AssignStreams(*module); diff --git a/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc b/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc index 1c0a23fa3e..f59da2caa1 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc @@ -65,8 +65,8 @@ HeuristicLayoutAssignment(const HloInstruction* instr, VLOG(2) << "Using heuristic to figure out layouts for " << instr->ToString(); - // Empirically we've found with Volta and cudnn 7 that backward-input convs - // with stride are significantly faster with NCHW layouts. + // Empirically we've found with Volta and cudnn <= 7.3 that backward-input + // convs with stride are significantly faster with NCHW layouts. // // We could have used a mixed layout combination, e.g. (NHWC, NCHW, NCHW), // which on paper gives good performance. However, there are two observations: @@ -75,11 +75,17 @@ HeuristicLayoutAssignment(const HloInstruction* instr, // * we've also observed that for mixed layouts, cuDNN transposes data back // and forth from a different layout combination. If we end up with // transposes anyway, we prefer to have them in XLA, as they can be fused. - // TODO(timshen): Figure out the exact condition. This may be achieved by - // auto-tuning layouts offline. - if (instr->custom_call_target() == kCudnnConvBackwardInputCallTarget && - window_util::HasStride(instr->window())) { - return kAllNCHW; + if (auto* dnn = stream_executor->AsDnn()) { + auto version_status = dnn->GetVersion(); + if (version_status.ok()) { + auto version = version_status.ConsumeValueOrDie(); + if (std::make_tuple(version.major_version(), version.minor_version()) <= + std::make_tuple(7, 3) && + instr->custom_call_target() == kCudnnConvBackwardInputCallTarget && + window_util::HasStride(instr->window())) { + return kAllNCHW; + } + } } // For other Volta f16 convolutions, use NHWC. diff --git a/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment_test.cc b/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment_test.cc index 8cc76c872c..2ffc8bfb49 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment_test.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment_test.cc @@ -61,7 +61,7 @@ TEST_F(LayoutAssignmentTest, Elementwise) { HloInstruction::CreateParameter(1, ashape, "y")); auto add = builder.AddInstruction( HloInstruction::CreateBinary(ashape, HloOpcode::kAdd, x, y)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build(add)); @@ -148,7 +148,7 @@ TEST_F(LayoutAssignmentTest, BatchNormInference) { {operand, scale, offset, mean, variance, epsilon, feature_index}, kCudnnBatchNormForwardInferenceCallTarget)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build(batchnorm)); @@ -217,7 +217,7 @@ TEST_F(LayoutAssignmentTest, BatchNormTraining) { batchnorm_shape, {operand, scale, offset, epsilon, feature_index}, kCudnnBatchNormForwardTrainingCallTarget)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build(batchnorm)); @@ -298,7 +298,7 @@ TEST_F(LayoutAssignmentTest, BatchNormGrad) { feature_index}, kCudnnBatchNormBackwardCallTarget)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build(batchnorm)); diff --git a/tensorflow/compiler/xla/service/gpu/instruction_fusion.cc b/tensorflow/compiler/xla/service/gpu/instruction_fusion.cc index 43f43b50e4..6151dd8ff4 100644 --- a/tensorflow/compiler/xla/service/gpu/instruction_fusion.cc +++ b/tensorflow/compiler/xla/service/gpu/instruction_fusion.cc @@ -80,7 +80,7 @@ bool IsIEEEFloatingPointScalarConstant(const HloInstruction* constant) { // This function limits the maximum number of operands to a fusion. // // There's a cap on how many parameters we can pass to a CUDA kernel, but -// exactly what that limit is is hazy, as it depends on (among other things) how +// exactly what that limit is hazy, as it depends on (among other things) how // much GPU constant memory is in use for other purposes. // // Moreover, we don't even know at the point that we're running fusion how many @@ -181,7 +181,8 @@ bool GpuInstructionFusion::ShouldFuse(HloInstruction* consumer, return true; } } else if (consumer->operand_count() == 2 && - consumer->opcode() == HloOpcode::kAdd) { + consumer->opcode() == HloOpcode::kAdd && + consumer->operand(other_operand_index) != producer) { // Fuse a bias add into the output of the dot. return true; } diff --git a/tensorflow/compiler/xla/service/gpu/instruction_fusion_test.cc b/tensorflow/compiler/xla/service/gpu/instruction_fusion_test.cc index fb77bc4b8e..688604cd36 100644 --- a/tensorflow/compiler/xla/service/gpu/instruction_fusion_test.cc +++ b/tensorflow/compiler/xla/service/gpu/instruction_fusion_test.cc @@ -117,7 +117,7 @@ TEST_F(InstructionFusionTest, PotentialBitcastReshapeOfDotUnfused) { auto reshape2 = builder.AddInstruction(HloInstruction::CreateReshape( ShapeUtil::MakeShape(S32, {1, 1, 1}), dot1)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_EQ(reshape2, computation->root_instruction()); EXPECT_FALSE(GpuInstructionFusion(/*may_duplicate=*/true) @@ -134,7 +134,7 @@ TEST_F(InstructionFusionTest, PotentialBitcastTransposeOfDotUnfused) { auto transpose2 = builder.AddInstruction(HloInstruction::CreateTranspose( ShapeUtil::MakeShape(S32, {1, 1}), dot1, {0, 1})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_EQ(transpose2, computation->root_instruction()); EXPECT_FALSE(GpuInstructionFusion(/*may_duplicate=*/true) @@ -358,6 +358,29 @@ TEST_F(InstructionFusionTest, DotOutputFusionBiasAdd) { op::Parameter())); } +TEST_F(InstructionFusionTest, + DotOperationFusion_DontOutputFuseDuplicateOperands) { + absl::string_view module_string = R"( +HloModule module + +ENTRY main { + a = f32[50,60]{1,0} parameter(0) + b = f32[60,1]{1,0} parameter(1) + c = f32[50,1]{1,0} dot(a, b), lhs_contracting_dims={1}, rhs_contracting_dims={0} + ROOT d = f32[50,1]{1,0} add(c, c) +} +)"; + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseAndReturnVerifiedModule(module_string)); + TF_ASSERT_OK_AND_ASSIGN( + bool fused_something, + GpuInstructionFusion(/*may_duplicate=*/false).Run(module.get())); + EXPECT_FALSE(fused_something); + EXPECT_THAT(module->entry_computation()->root_instruction(), + Not(op::Fusion())); +} + // Compute sum(1/p0), where p0 has type f32, twice. Check that the division is // duplicated and fused into both reduces. TEST_F(InstructionFusionTest, FloatingPointDivIsCheap) { @@ -723,7 +746,7 @@ TEST_F(InstructionFusionTest, AvoidsLargeFusion) { sum = b.AddInstruction( HloInstruction::CreateBinary(shape, HloOpcode::kAdd, sum, param)); } - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(b.Build()); EXPECT_TRUE(GpuInstructionFusion(/*may_duplicate=*/true) .Run(module.get()) diff --git a/tensorflow/compiler/xla/service/gpu/ir_emitter.cc b/tensorflow/compiler/xla/service/gpu/ir_emitter.cc index 7fcdd805ed..6693f66d62 100644 --- a/tensorflow/compiler/xla/service/gpu/ir_emitter.cc +++ b/tensorflow/compiler/xla/service/gpu/ir_emitter.cc @@ -63,9 +63,6 @@ IrEmitter::IrEmitter(const HloModuleConfig& hlo_module_config, &ir_emitter_context->buffer_assignment(), &b_, module_, is_nested), hlo_module_config_(hlo_module_config) { - b_.setFastMathFlags(llvm_ir::GetFastMathFlags( - /*fast_math_enabled=*/hlo_module_config.debug_options() - .xla_gpu_enable_fast_math())); } Status IrEmitter::DefaultAction(HloInstruction* hlo) { @@ -97,6 +94,18 @@ Status IrEmitter::HandleBitcast(HloInstruction* bitcast) { return Status::OK(); } +Status IrEmitter::HandleAddDependency(HloInstruction* add_dependency) { + VLOG(2) << "HandleAddDependency: " << add_dependency->ToString(); + const HloInstruction* operand = add_dependency->operand(0); + // Add_Dependency is a no-op, but we still want to bind it to an llvm::Value + // sometimes, e.g., when it's operand is a constant or a bitcast of a + // constant. + if (bindings_.BoundToIrValue(*operand)) { + bindings_.BindHloToIrValue(*add_dependency, GetBasePointer(*operand)); + } + return Status::OK(); +} + Status IrEmitter::HandleGetTupleElement(HloInstruction* get_tuple_element) { auto operand = get_tuple_element->operand(0); CHECK(bindings_.BoundToIrValue(*operand)); diff --git a/tensorflow/compiler/xla/service/gpu/ir_emitter.h b/tensorflow/compiler/xla/service/gpu/ir_emitter.h index 56c3f45200..2da46c0169 100644 --- a/tensorflow/compiler/xla/service/gpu/ir_emitter.h +++ b/tensorflow/compiler/xla/service/gpu/ir_emitter.h @@ -100,6 +100,7 @@ class IrEmitter : public DfsHloVisitorWithDefault, Status HandleBatchNormInference(HloInstruction* batch_norm) override; Status HandleBatchNormTraining(HloInstruction* batch_norm) override; Status HandleBatchNormGrad(HloInstruction* batch_norm) override; + Status HandleAddDependency(HloInstruction* add_dependency) override; Status FinishVisit(HloInstruction* root) override { return Status::OK(); } diff --git a/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc b/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc index 87b6cd640a..bbe1583c01 100644 --- a/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc +++ b/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc @@ -22,7 +22,6 @@ limitations under the License. #include "tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.h" #include "absl/algorithm/container.h" -#include "absl/container/inlined_vector.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/types/optional.h" @@ -65,11 +64,11 @@ limitations under the License. #include "tensorflow/compiler/xla/service/hlo_casting_utils.h" #include "tensorflow/compiler/xla/service/hlo_computation.h" #include "tensorflow/compiler/xla/service/hlo_instruction.h" +#include "tensorflow/compiler/xla/service/hlo_instructions.h" #include "tensorflow/compiler/xla/service/hlo_opcode.h" #include "tensorflow/compiler/xla/service/llvm_ir/buffer_assignment_util.h" #include "tensorflow/compiler/xla/service/llvm_ir/dynamic_update_slice_util.h" #include "tensorflow/compiler/xla/service/llvm_ir/fused_ir_emitter.h" -#include "tensorflow/compiler/xla/service/llvm_ir/kernel_support_library.h" #include "tensorflow/compiler/xla/service/llvm_ir/llvm_util.h" #include "tensorflow/compiler/xla/service/llvm_ir/sort_util.h" #include "tensorflow/compiler/xla/service/llvm_ir/tuple_ops.h" @@ -88,6 +87,8 @@ limitations under the License. namespace xla { namespace gpu { +using llvm_ir::KernelMappingScheme; + namespace { using absl::InlinedVector; @@ -546,91 +547,7 @@ Status IrEmitterUnnested::HandleFusion(HloInstruction* fusion) { // TODO(b/112040122): Support variadic reduce. return Unimplemented("Variadic reduce is not supported on GPU"); } - VLOG(3) << "Emitting fused reduction to vector: " << fusion->ToString(); - std::vector> thunks; - absl::Span output_instructions = - root->opcode() == HloOpcode::kTuple - ? root->operands() - : absl::Span(&root, 1); - - // For multi-output fusion emit an initializer for each tuple element. - // Otherwise it's sufficient to just initialize the single output. - HloInstruction* first_reduce = nullptr; - for (int i = 0, e = output_instructions.size(); i != e; ++i) { - if (output_instructions[i]->opcode() == HloOpcode::kReduce) { - TF_ASSIGN_OR_RETURN( - std::unique_ptr initializer_thunk, - BuildInitializerThunk(fusion, output_instructions[i] == root - ? ShapeIndex() - : ShapeIndex({i}))); - thunks.push_back(std::move(initializer_thunk)); - first_reduce = - first_reduce == nullptr ? output_instructions[i] : first_reduce; - } - } - CHECK(first_reduce != nullptr); - std::unique_ptr kernel_thunk = - BuildKernelThunk(fusion, /*implements_whole_instruction=*/false); - GpuElementalIrEmitter elemental_emitter( - hlo_module_config_, ir_emitter_context_->llvm_module(), &b_, - GetNestedComputer()); - FusedIrEmitter fused_emitter(GetGeneratorForOperandIrArrays(fusion), - &elemental_emitter); - TF_RETURN_IF_ERROR(root->Accept(&fused_emitter)); - - // For multi-output fusion CHECK the constraints and feed all the - // reduces into a single loop code generator. Single-output reduce - // fusion is a special case of that. - InlinedVector input_gens; - InlinedVector init_value_gens; - std::vector> - extra_output_gens; - InlinedVector reducers; - InlinedVector reduce_output_shapes; - for (int i = 0, e = output_instructions.size(); i != e; ++i) { - const HloInstruction* inst = output_instructions[i]; - ShapeIndex output_shape_index; - if (root->opcode() == HloOpcode::kTuple) { - output_shape_index = {i}; - } - if (inst->opcode() == HloOpcode::kReduce) { - CHECK(IsReductionToVector(*inst)) - << "Only reductions to vector are supported"; - // Shapes, layouts and dimensions must be the same for all reduces - // inside of this fusion. - CHECK(ShapeUtil::Equal(first_reduce->shape(), inst->shape())); - CHECK(ShapeUtil::Equal(first_reduce->operand(0)->shape(), - inst->operand(0)->shape())); - CHECK(ShapeUtil::Equal(first_reduce->operand(1)->shape(), - inst->operand(1)->shape())); - CHECK(first_reduce->dimensions() == inst->dimensions()); - input_gens.push_back(fused_emitter.GetGenerator(inst->operand(0))); - init_value_gens.push_back( - fused_emitter.GetGenerator(inst->operand(1))); - reducers.push_back(inst->to_apply()); - reduce_output_shapes.push_back(std::move(output_shape_index)); - } else { - // For extra outputs we can relax shape equality to allow different - // types (with the same number of elements). Layouts still have to - // match. - CHECK(ShapeUtil::CompatibleIgnoringElementType( - first_reduce->operand(0)->shape(), inst->shape())); - CHECK(LayoutUtil::Equal(first_reduce->operand(0)->shape().layout(), - inst->shape().layout())); - extra_output_gens.emplace_back(fused_emitter.GetGenerator(inst), - std::move(output_shape_index)); - } - } - const Shape& input_shape = first_reduce->operand(0)->shape(); - TF_CHECK_OK(EmitReductionToVector( - kernel_thunk.get(), first_reduce, input_shape, input_gens, - init_value_gens, first_reduce->dimensions(), reducers, - reduce_output_shapes, extra_output_gens)); - thunks.push_back(std::move(kernel_thunk)); - std::unique_ptr sequential_thunk = - absl::make_unique(std::move(thunks), fusion); - AddThunkToThunkSequence(std::move(sequential_thunk)); - return Status::OK(); + return EmitReductionToVector(fusion); } default: LOG(FATAL) << "Bad opcode for input fusion: " @@ -700,13 +617,12 @@ Status IrEmitterUnnested::HandleCopy(HloInstruction* copy) { } Status IrEmitterUnnested::EmitExtraOutputsForReduce( - const HloInstruction* reduce, const IrArray::Index& index, + const HloInstruction* unnested_hlo, const IrArray::Index& index, absl::Span> extra_output_gens) { for (int i = 0; i != extra_output_gens.size(); ++i) { - const HloInstruction* output = reduce->parent()->FusionInstruction(); llvm::Value* extra_output_address = - GetIrArray(*output, *output, extra_output_gens[i].second) + GetIrArray(*unnested_hlo, *unnested_hlo, extra_output_gens[i].second) .EmitArrayElementAddress(index, &b_, "extra_output_element_address"); TF_ASSIGN_OR_RETURN(llvm::Value* const extra_output_ir_value, @@ -716,984 +632,13 @@ Status IrEmitterUnnested::EmitExtraOutputsForReduce( return Status::OK(); } -Status IrEmitterUnnested::EmitReductionToScalar( - KernelThunk* kernel_thunk, HloInstruction* reduce, const Shape& input_shape, - absl::Span input_gens, - absl::Span init_value_gens, - absl::Span reducers, - absl::Span reduce_output_shapes, - absl::Span> - extra_output_gens) { - // Number of elements processed by a single thread. - constexpr int64 kTileSize = 16; - int64 num_elems = ShapeUtil::ElementsIn(input_shape); - - // Round up the number of tiles to a multiple of the warp size. This is - // necessary for correctness. We launch one thread per tile, and if the - // number of threads isn't a multiple of the number of the warp size, our - // shuffles will read from inactive threads, producing undefined values. - int64 num_tiles = - RoundUpToNearest(CeilOfRatio(num_elems, kTileSize), kWarpSize); - - Shape tiled_input_shape = ShapeUtil::MakeShapeWithLayout( - reduce->shape().element_type(), {num_tiles}, {0}); - LaunchDimensions launch_dimensions = CalculateLaunchDimensions( - tiled_input_shape, ir_emitter_context_->device_description()); - - llvm::Type* index_ty = - GetIndexTypeForKernel(reduce, launch_dimensions.launch_bound(), &b_); - - auto index_typed_constant = [&](uint64 c) -> llvm::Constant* { - return llvm::ConstantInt::get(index_ty, c); - }; - - // Check whether every thread will process a full tile's worth of elements - // without reading outside the bounds of the input. If this is true, we can - // skip some bounds checks in the final algorithm. - bool all_threads_in_bounds = num_tiles * kTileSize == num_elems; - - // __global__ void full_reduce_kernel() { - // x_in_tiles = threadIdx.x + blockIdx.x * blockDim.x; - // x = x_in_tiles * kTileSize; - // - // partial_result = init_value; - // if (all_threads_in_bounds || x + kTileSize <= num_elems) { - // for (i = 0; i < kTileSize; ++i) { - // partial_result = Reducer(partial_result, input[x + i]); - // } - // } else { - // for (i = 0; i < kTileSize; ++i) { - // if (x + i < num_elems) { - // partial_result = Reducer(partial_result, input[x + i]); - // } - // } - // } - // for (i = warpSize / 2; i > 0; i /= 2) { - // partial_result = Reducer(partial_result, - // __shfl_down(partial_result, i)); - // } - // if (lane_id == 0) { - // AtomicReducer(&output[y], partial_result); - // } - // } - // - // // Choose num_blocks and threads_per_block such that: - // // - // // num_blocks * threads_per_block = - // // RoundUpToNextMultipleOf(Ceil(num_elems / kTileSize), warpSize), - // // - // // and threads_per_block is a multiple of warpSize. - // reduce_kernel // - auto loop_body_emitter = [=](const IrArray::Index& tile_index) -> Status { - const int num_reduces = reducers.size(); - llvm::Type* element_ir_type = - llvm_ir::PrimitiveTypeToIrType(input_shape.element_type(), module_); - std::vector partial_reduction_result_addresses; - for (int i = 0; i != num_reduces; ++i) { - llvm::Value* partial_reduction_result_address = - Alloca(element_ir_type, /*ArraySize=*/nullptr, - "partial_reduction_result." + llvm::Twine(i)); - TF_ASSIGN_OR_RETURN(llvm::Value* const init_ir_value, - init_value_gens[i](IrArray::Index(index_ty))); - Store(init_ir_value, partial_reduction_result_address); - partial_reduction_result_addresses.push_back( - partial_reduction_result_address); - } - - llvm::Value* x_in_tiles = tile_index[0]; - x_in_tiles = ZExtOrTrunc(x_in_tiles, index_ty); - - // Emit an inner for-loop that reduces the elements in the tile. - auto emit_tile_element_loop = [=](bool tile_in_bounds) -> Status { - std::unique_ptr tile_element_loop = - llvm_ir::ForLoop::EmitForLoop( - "element_id_in_tile", index_typed_constant(0), - index_typed_constant(kTileSize), index_typed_constant(1), &b_); - - // Emit the body of the partial reduction loop. - llvm_ir::SetToFirstInsertPoint(tile_element_loop->GetBodyBasicBlock(), - &b_); - llvm::Value* x = - NSWAdd(NSWMul(x_in_tiles, index_typed_constant(kTileSize)), - tile_element_loop->GetIndVarValue()); - // Unless we know the tile is entirely in bounds, we have to emit a - // x-in-bounds check before reading from the input. - if (!tile_in_bounds) { - llvm_ir::LlvmIfData if_data = llvm_ir::EmitIfThenElse( - ICmpULT(x, index_typed_constant(num_elems)), "x_in_bounds", &b_); - - // Emit code that reads the input element and accumulates it to - // the partial reduction result. - llvm_ir::SetToFirstInsertPoint(if_data.true_block, &b_); - } - - IrArray::Index input_index( - /*linear=*/x, input_shape, &b_); - llvm::Value* input_address = Alloca(element_ir_type); - for (int i = 0; i != num_reduces; ++i) { - TF_ASSIGN_OR_RETURN(llvm::Value* const input_ir_value, - input_gens[i](input_index)); - Store(input_ir_value, input_address); - TF_RETURN_IF_ERROR(EmitCallToNestedComputation( - *reducers[i], - {partial_reduction_result_addresses[i], input_address}, - partial_reduction_result_addresses[i])); - } - return EmitExtraOutputsForReduce(reduce, input_index, extra_output_gens); - }; - - // x_end = kTileSize + x_in_tiles * kTileSize, i.e., the location that's - // immediately beyond the tile. - llvm::Value* x_end = - NSWAdd(index_typed_constant(kTileSize), - NSWMul(x_in_tiles, index_typed_constant(kTileSize))); - // The tile is entirely in bound if all_threads_in_bounds or - // x_end <= num_elems. - llvm::Value* tile_in_bounds = - Or(ICmpULE(x_end, index_typed_constant(num_elems)), - b_.getInt1(all_threads_in_bounds)); - llvm_ir::LlvmIfData if_tile_in_bounds_data = - llvm_ir::EmitIfThenElse(tile_in_bounds, "tile_in_bounds", &b_); - llvm_ir::SetToFirstInsertPoint(if_tile_in_bounds_data.true_block, &b_); - TF_RETURN_IF_ERROR(emit_tile_element_loop(/*tile_in_bounds=*/true)); - llvm_ir::SetToFirstInsertPoint(if_tile_in_bounds_data.false_block, &b_); - TF_RETURN_IF_ERROR(emit_tile_element_loop(/*tile_in_bounds=*/false)); - - // After the if-then-else statement on tile_in_bounds, emit calls to - // shfl_down that accumulate the partial reduction results of all threads - // from the warp. - llvm_ir::SetToFirstInsertPoint(if_tile_in_bounds_data.after_block, &b_); - int bit_width = llvm_ir::GetSizeInBits(element_ir_type); - // bitcast cannot be applied to aggregate types (even packed ones), so we - // instead bitcast addresses of load/store to intN* of the same bit-width. - llvm::Type* shuffle_ir_type = element_ir_type->isStructTy() - ? b_.getIntNTy(bit_width) - : element_ir_type; - for (int shuffle_distance = kWarpSize / 2; shuffle_distance >= 1; - shuffle_distance /= 2) { - llvm::Value* result_from_other_lane = - Alloca(element_ir_type, nullptr, "result_from_other_lane"); - for (int i = 0; i != num_reduces; ++i) { - llvm::Value* partial_reduction_result = - Load(BitCast(partial_reduction_result_addresses[i], - shuffle_ir_type->getPointerTo()), - "partial_reduction_result"); - CHECK_EQ(launch_dimensions.threads_per_block() % kWarpSize, 0) - << "Requires block size a multiple of the warp size, otherwise we " - "will read undefined elements."; - Store(EmitFullWarpShuffleDown(partial_reduction_result, - b_.getInt32(shuffle_distance), &b_), - BitCast(result_from_other_lane, shuffle_ir_type->getPointerTo())); - TF_RETURN_IF_ERROR(EmitCallToNestedComputation( - *reducers[i], - {partial_reduction_result_addresses[i], result_from_other_lane}, - partial_reduction_result_addresses[i])); - } - } - - const HloInstruction* output = - reduce->IsFused() ? reduce->parent()->FusionInstruction() : reduce; - - // Emit an atomic operation that accumulates the partial reduction result of - // lane 0 (which holds the partially accumulated result for its warp) to the - // output element. - llvm::Value* lane_id = - URem(x_in_tiles, index_typed_constant(kWarpSize), "lane_id"); - llvm_ir::LlvmIfData if_lane_id_is_zero_data = llvm_ir::EmitIfThenElse( - ICmpEQ(lane_id, index_typed_constant(0)), "lane_id_is_zero", &b_); - llvm_ir::SetToFirstInsertPoint(if_lane_id_is_zero_data.true_block, &b_); - - for (int i = 0; i != num_reduces; ++i) { - llvm::Value* output_address = - GetIrArray(*output, *output, reduce_output_shapes[i]) - .EmitArrayElementAddress( - IrArray::Index( - /*linear=*/b_.getInt64(0), - ShapeUtil::GetSubshape(output->shape(), - reduce_output_shapes[i]), - &b_), - &b_, "output_element_address"); - TF_RETURN_IF_ERROR(EmitAtomicOperationForNestedComputation( - *reducers[i], output_address, partial_reduction_result_addresses[i])); - } - return Status::OK(); - }; - - // Emit a parallel loop that iterates through all input tiles, one per thread. - UpdateLaunchDimensions(launch_dimensions, kernel_thunk, - ir_emitter_context_->llvm_module()); - return ParallelLoopEmitter(loop_body_emitter, tiled_input_shape, - launch_dimensions, &b_) - .EmitLoop(IrName(reduce), index_ty); -} - -Status IrEmitterUnnested::EmitColumnReduction( - KernelThunk* kernel_thunk, int64 height, int64 width, - HloInstruction* reduce, const Shape& input_shape, - absl::Span input_gens, - absl::Span init_value_gens, - absl::Span reducers, - absl::Span reduce_output_shapes, - absl::Span> - extra_output_gens) { - // Divide the input matrix into tiles of size KxL. For example, when the - // input matrix is 4x4, K=2, and L=1 the tiled matrix looks like - // - // 0123 - // 0123 - // 4567 - // 4567 // Numbers indicate tile IDs. - // - // Each tile is first partially reduced to a scalar by a thread, and then the - // scalar is accumulated to the output vector using atomic operations. - // - // We choose 128 as the tile size based on empirical evidence. It's big enough - // to reduce the amount of atomic adds in the end, maximizing the memory - // bandwidth. A tile width of 2 allows for high memory bandwidth utilization - // on 16b input data. - constexpr int64 kTileHeight = 128; - constexpr int64 kTileWidth = 2; - - // If the height is not a multiple of kTileHeight, we pad the bottom of the - // input matrix. - const int64 height_in_tiles = CeilOfRatio(height, kTileHeight); - // If width is not a multiple of kTileWidth the rightmost thread will process - // fewer input elements. - const int64 width_in_tiles = CeilOfRatio(width, kTileWidth); - Shape tiled_input_shape = - ShapeUtil::MakeShapeWithLayout(reduce->shape().element_type(), - {height_in_tiles, width_in_tiles}, {1, 0}); - LaunchDimensions launch_dimensions = CalculateLaunchDimensions( - tiled_input_shape, ir_emitter_context_->device_description()); - - // TODO(b/110211620): Convert to use i32 index_type when it is possible. - llvm::Type* index_ty = b_.getInt64Ty(); - - auto index_typed_constant = [&](uint64 c) -> llvm::Constant* { - return llvm::ConstantInt::get(index_ty, c); - }; - - // for (linear_index = threadIdx.x + blockIdx.x * blockDim.x; - // linear_index < height_in_tiles * width_in_tiles; - // linear_index += blockDim.x * gridDim.x) { - // y_in_tiles = linear_index / width_in_tiles; - // x_in_tiles = linear_index % width_in_tiles; - // - // partial_results[kTileWidth] = init_values; - // tile_in_y_bounds = height % kTileHeight == 0 || - // y_in_tiles * kTileHeight + kTileHeight <= height; - // tile_in_x_bounds = width % kTileWidth == 0 || - // x_in_tiles * kTileWidth + kTileWidth <= width; - // // The implementation handles y and x bound checks separately. - // if (tile_in_y_bounds && tile_in_x_bounds) { - // for (y_offset : range(kTileHeight)) { - // y = y_in_tiles * kTileHeight + y_offset; - // for (x_offset : range(kTileWidth)) { - // x = x_in_tiles * kTileWidth + x_offset; - // partial_result = Reducer(partial_result[x_offset], input[y][x]); - // } - // } - // } else { - // for (y_offset : range(kTileHeight)) { - // y = y_in_tiles * kTileHeight + y_offset; - // for (y_offset : range(kTileHeight)) { - // x = x_in_tiles * kTileWidth + x_offset; - // if (y < height && x < width) { - // partial_result = Reducer(partial_result, input[y][x]); - // } - // } - // } - // } - // for (x_offset : range(kTileWidth)) { - // AtomicReducer(&output[x + x_offset], partial_result[x_offset]); - // } - // } - auto loop_body_emitter = [=](const IrArray::Index& tile_index) -> Status { - const int num_reduces = reducers.size(); - // Emit the loop body that reduces one tile. - llvm::Type* element_ir_type = - llvm_ir::PrimitiveTypeToIrType(input_shape.element_type(), module_); - std::vector partial_reduction_result_addresses; - for (int i = 0; i != num_reduces; ++i) { - for (int x_offset = 0; x_offset < kTileWidth; ++x_offset) { - llvm::Value* partial_reduction_result_address = - Alloca(element_ir_type, /*ArraySize=*/nullptr, - "partial_reduction_result." + - llvm::Twine(i * kTileWidth + x_offset)); - TF_ASSIGN_OR_RETURN(llvm::Value* const init_ir_value, - init_value_gens[i](IrArray::Index(index_ty))); - Store(init_ir_value, partial_reduction_result_address); - partial_reduction_result_addresses.push_back( - partial_reduction_result_address); - } - } - - // Emit an inner for-loop that partially reduces the elements in the given - // tile. - llvm::Value* y_in_tiles = tile_index[0]; - llvm::Value* x_in_tiles = tile_index[1]; - - y_in_tiles = ZExtOrTrunc(y_in_tiles, index_ty); - x_in_tiles = ZExtOrTrunc(x_in_tiles, index_ty); - - auto emit_tile_element_loop = [=](bool tile_in_y_bounds, - bool tile_in_x_bounds) -> Status { - std::unique_ptr tile_element_loop = - llvm_ir::ForLoop::EmitForLoop( - "element_id_in_tile", index_typed_constant(0), - index_typed_constant(kTileHeight), index_typed_constant(1), &b_); - - // Emit the body of the partial reduction loop. - llvm_ir::SetToFirstInsertPoint(tile_element_loop->GetBodyBasicBlock(), - &b_); - llvm::Value* y = - NSWAdd(NSWMul(y_in_tiles, index_typed_constant(kTileHeight)), - tile_element_loop->GetIndVarValue()); - - // Unless we know that y is in bounds, we have to emit a check before - // reading from the input. - if (!tile_in_y_bounds) { - llvm_ir::LlvmIfData if_data = llvm_ir::EmitIfThenElse( - ICmpULT(y, index_typed_constant(height)), "y_in_bounds", &b_); - - // Emit code that reads the input element and accumulates it to - // the partial reduction result. - llvm_ir::SetToFirstInsertPoint(if_data.true_block, &b_); - } - for (int x_offset = 0; x_offset < kTileWidth; ++x_offset) { - llvm::Value* x = - NSWAdd(NSWMul(x_in_tiles, index_typed_constant(kTileWidth)), - index_typed_constant(x_offset)); - // Unless we know that x is in bounds, we have to emit a check before - // reading from the input. - if (!tile_in_x_bounds) { - llvm_ir::LlvmIfData if_data = llvm_ir::EmitIfThenElse( - ICmpULT(x, index_typed_constant(width)), "x_in_bounds", &b_); - llvm_ir::SetToFirstInsertPoint(if_data.true_block, &b_); - } - llvm::Value* input_address = Alloca(element_ir_type); - // {y,x} is an index to input_matrix_shape [height,width]. We need to - // convert that to an index to input_shape (the shape of the operand of - // "reduce"). This conversion is composed of a transposition from - // input_shape to normalized_input_shape and a reshape from - // normalized_input_shape to input_matrix_shape. - const Shape normalized_input_shape = - ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout( - input_shape); - auto input_shape_min2maj = LayoutUtil::MinorToMajor(input_shape); - const std::vector transpose_dimension_mapping( - input_shape_min2maj.rbegin(), input_shape_min2maj.rend()); - - const Shape input_matrix_shape = - ShapeUtil::MakeShapeWithDescendingLayout(input_shape.element_type(), - {height, width}); - const IrArray::Index input_matrix_index({y, x}, input_matrix_shape, - &b_); - const IrArray::Index input_index = - input_matrix_index - .SourceIndexOfReshape(input_matrix_shape, - normalized_input_shape, &b_) - .SourceIndexOfTranspose(normalized_input_shape, input_shape, - transpose_dimension_mapping, &b_); - for (int i = 0; i != num_reduces; ++i) { - TF_ASSIGN_OR_RETURN(llvm::Value* const input_ir_value, - input_gens[i](input_index)); - Store(input_ir_value, input_address); - TF_RETURN_IF_ERROR(EmitCallToNestedComputation( - *reducers[i], - {partial_reduction_result_addresses[i * kTileWidth + x_offset], - input_address}, - partial_reduction_result_addresses[i * kTileWidth + x_offset])); - TF_RETURN_IF_ERROR(EmitExtraOutputsForReduce(reduce, input_index, - extra_output_gens)); - } - } - return Status::OK(); - }; - - // y_end = kTileHeight + y_in_tiles * kTileHeight, i.e., the y location - // that's immediately beyond the tile. - llvm::Value* y_end = - NSWAdd(index_typed_constant(kTileHeight), - NSWMul(y_in_tiles, index_typed_constant(kTileHeight))); - // x_end = kTileWidth + x_in_tiles * kTileWidth, i.e., the x location - // that's immediately beyond the tile. - llvm::Value* x_end = - NSWAdd(index_typed_constant(kTileWidth), - NSWMul(x_in_tiles, index_typed_constant(kTileWidth))); - llvm::Value* tile_in_y_bounds = - Or(ICmpULE(y_end, index_typed_constant(height)), - b_.getInt1(height % kTileHeight == 0)); - llvm::Value* tile_in_x_bounds = - Or(ICmpULE(x_end, index_typed_constant(width)), - b_.getInt1(width % kTileWidth == 0)); - // The tile is in y bounds if "height" is a multiple of kTileHeight or - // y_end <= height. - llvm_ir::LlvmIfData if_tile_in_y_bounds_data = - llvm_ir::EmitIfThenElse(tile_in_y_bounds, "tile_in_y_bounds", &b_); - llvm_ir::SetToFirstInsertPoint(if_tile_in_y_bounds_data.true_block, &b_); - // The tile is in x bounds if "width" is a multiple of kTileWidth or - // x_end <= width. - llvm_ir::LlvmIfData if_tile_in_x_bounds_data = - llvm_ir::EmitIfThenElse(tile_in_x_bounds, "tile_in_x_bounds", &b_); - llvm_ir::SetToFirstInsertPoint(if_tile_in_x_bounds_data.true_block, &b_); - TF_RETURN_IF_ERROR(emit_tile_element_loop(/*tile_in_y_bounds=*/true, - /*tile_in_x_bounds=*/true)); - llvm_ir::SetToFirstInsertPoint(if_tile_in_x_bounds_data.false_block, &b_); - TF_RETURN_IF_ERROR(emit_tile_element_loop(/*tile_in_y_bounds=*/true, - /*tile_in_x_bounds=*/false)); - llvm_ir::SetToFirstInsertPoint(if_tile_in_y_bounds_data.false_block, &b_); - if_tile_in_x_bounds_data = - llvm_ir::EmitIfThenElse(tile_in_x_bounds, "tile_in_x_bounds", &b_); - llvm_ir::SetToFirstInsertPoint(if_tile_in_x_bounds_data.true_block, &b_); - TF_RETURN_IF_ERROR(emit_tile_element_loop(/*tile_in_y_bounds=*/false, - /*tile_in_x_bounds=*/true)); - llvm_ir::SetToFirstInsertPoint(if_tile_in_x_bounds_data.false_block, &b_); - TF_RETURN_IF_ERROR(emit_tile_element_loop(/*tile_in_y_bounds=*/false, - /*tile_in_x_bounds=*/false)); - - // After the nested if-then-else statement on tile_in_y_bounds and - // tile_in_x_bounds, emit atomic operations to accumulate the partial - // reduction result to the output element. - llvm_ir::SetToFirstInsertPoint(if_tile_in_y_bounds_data.after_block, &b_); - const HloInstruction* output = - reduce->IsFused() ? reduce->parent()->FusionInstruction() : reduce; - for (int i = 0; i != num_reduces; ++i) { - for (int x_offset = 0; x_offset < kTileWidth; ++x_offset) { - llvm::Value* x = - NSWAdd(NSWMul(x_in_tiles, index_typed_constant(kTileWidth)), - index_typed_constant(x_offset)); - llvm::Value* output_address = - GetIrArray(*output, *output, reduce_output_shapes[i]) - .EmitArrayElementAddress( - IrArray::Index( - x, - ShapeUtil::GetSubshape(output->shape(), - reduce_output_shapes[i]), - &b_), - &b_, "output_element_address"); - TF_RETURN_IF_ERROR(EmitAtomicOperationForNestedComputation( - *reducers[i], output_address, - partial_reduction_result_addresses[i * kTileWidth + x_offset])); - } - } - return Status::OK(); - }; - - // Emit a parallel loop that iterate through all input tiles. - UpdateLaunchDimensions(launch_dimensions, kernel_thunk, - ir_emitter_context_->llvm_module()); - return ParallelLoopEmitter(loop_body_emitter, tiled_input_shape, - launch_dimensions, &b_) - .EmitLoop(IrName(reduce), index_ty); -} - -static std::pair ComputeTilingSchemeForReduction( - int64 depth, int64 width, int64 kWarpSize) { - constexpr int64 kTargetNumElementsPerThread = 64; - int64 x_tile_size = kTargetNumElementsPerThread; - int64 z_tile_size = 1; - - // Only tile along the x dimension with tile size kTargetNumElementsPerThread - // if doing so doesn't require a slow version of loop with bound check on each - // dimension. A more sophisticated heuristics is to enable tile along the - // x dimension with tile size kTargetNumElementsPerThread when either width is - // a factor of (kWarpSize * kTargetNumElementsPerThread) or width is big - // enough so that only a small fraction of the threads execute the slow - // version of loop with bound check. - if (width % (kWarpSize * kTargetNumElementsPerThread) != 0) { - x_tile_size = 8; - z_tile_size = 8; - while (depth % z_tile_size != 0) { - z_tile_size -= 1; - } - } - - return std::pair(x_tile_size, z_tile_size); -} - -Status IrEmitterUnnested::EmitRowReduction( - KernelThunk* kernel_thunk, int64 depth, int64 height, int64 width, - HloInstruction* reduce, const Shape& input_shape, - absl::Span input_gens, - absl::Span init_value_gens, - absl::Span reducers, - absl::Span reduce_output_shapes, - absl::Span> - extra_output_gens) { - // A naive algorithm is: - // 1. Divide the x dimension of the input tensor into tiles of size 1x1xX. - // 2. Partially reduces each tile to a scalar using one thread. - // 3. Accumulates that scalar to the output vector using atomic operations. - // - // for (linear_index = threadIdx.x + blockIdx.x * blockDim.x; - // linear_index < depth * height * width_in_tiles; - // linear_index += blockDim.x * gridDim.x) { - // int x_in_tiles = linear_index % width_in_tiles; - // int y = linear_index / width_in_tiles % height; - // int z = linear_index / (height * width_in_tiles); - // float partial_result = 0; - // for (element_id_in_tile : range(x_tile_size)) { - // int x = x_in_tiles * x_tile_size + element_id_in_tile; - // if (x < width) - // partial_result = reducer(partial_result, input[z][y][x]); - // } - // AtomicReducer(&output[y], partial_result); - // } - // - // Four optimizations are performed. - // - // 1. To coalesce global memory accesses, dilate the tile with a factor of 32 - // (i.e. the warp size). For example, suppose the width is 8x32=256. Instead - // of making each tile consecutive, we let make tile 0 column - // [0,32,64,...,224], tile 1 column [1,33,65,...,225], and so on. This ensures - // that threads in a warp access consecutive memory in one iteration (i.e. - // coalesced). In the above example, the warp that contains thread 0-31 - // accesses column 0-31 in the first iteration, and 32-63 in the second - // iteration, and so on. - // - // 2. Partially accumulate partial reduced results computed by threads in the - // same warp using shfl_down. Using shfl_down is faster than directly using - // atomic operations because shfl_down transfers the data between threads - // using shared memory and threads in the same warp run in lock step (thus no - // extra synchronization needed). See - // https://devblogs.nvidia.com/parallelforall/faster-parallel-reductions-kepler/ - // for details. The downside is, to produce correct results when using - // shfl_down, we need to guarantee threads in the same warp work on input - // elements with the same y, so the number of tiles in each row must be a - // multiple of 32. - // - // 3. Specialize the case that the entire tile is in bounds. When that is - // true, we don't need to emit "if(x 0; shuffle_distance /= 2) - // partial_result = Reducer( - // partial_result, - // __shfl_down_sync(CUDA_WARP_ALL, partial_result, shuffle_distance)); - // if (lane_id == 0) - // AtomicReducer(&output[y], partial_result); - // } - // - - int64 x_tile_size; - int64 z_tile_size; - std::tie(x_tile_size, z_tile_size) = - ComputeTilingSchemeForReduction(depth, width, kWarpSize); - - // Round the width in tiles up to the nearest multiple of kWarpSize, so that - // the use of shfl_down is valid. - const int64 width_in_tiles = - RoundUpToNearest(CeilOfRatio(width, x_tile_size), kWarpSize); - Shape tiled_input_shape = ShapeUtil::MakeShapeWithLayout( - reduce->shape().element_type(), - {depth / z_tile_size, height, width_in_tiles}, {2, 1, 0}); - LaunchDimensions launch_dimensions = CalculateLaunchDimensions( - tiled_input_shape, ir_emitter_context_->device_description()); - llvm::Type* index_ty = - GetIndexTypeForKernel(reduce, launch_dimensions.launch_bound(), &b_); - - auto index_typed_constant = [&](uint64 c) -> llvm::Constant* { - return llvm::ConstantInt::get(index_ty, c); - }; - - auto loop_body_emitter = [=](const IrArray::Index& tile_index) { - const int num_reduces = reducers.size(); - llvm::Type* element_ir_type = llvm_ir::PrimitiveTypeToIrType( - input_shape.element_type(), ir_emitter_context_->llvm_module()); - std::vector partial_reduction_result_addresses; - for (int i = 0; i != num_reduces; ++i) { - llvm::Value* partial_reduction_result_address = - Alloca(element_ir_type, /*ArraySize=*/nullptr, - "partial_reduction_result." + llvm::Twine(i)); - TF_ASSIGN_OR_RETURN(llvm::Value* const init_ir_value, - init_value_gens[i](IrArray::Index(index_ty))); - Store(init_ir_value, partial_reduction_result_address); - partial_reduction_result_addresses.push_back( - partial_reduction_result_address); - } - - llvm::Value* z_tile = tile_index[0]; - llvm::Value* y = tile_index[1]; - llvm::Value* x_tile = tile_index[2]; - - x_tile = ZExtOrTrunc(x_tile, index_ty); - - llvm::Value* warp_id = - UDiv(x_tile, index_typed_constant(kWarpSize), "warp_id"); - llvm::Value* lane_id = - URem(x_tile, index_typed_constant(kWarpSize), "lane_id"); - - // The x-location of the last element in this z-x-tile. - // last_x = lane_id + warpSize * (x_tile_size - 1 + warp_id * x_tile_size); - llvm::Value* last_x = NSWAdd( - lane_id, - NSWMul(index_typed_constant(kWarpSize), - NSWAdd(index_typed_constant(x_tile_size - 1), - NSWMul(warp_id, index_typed_constant(x_tile_size))))); - - KernelSupportLibrary ksl( - &b_, - /*unroll_mode=*/xla::llvm_ir::UnrollMode::kFullyUnroll, - /*prevent_vectorization=*/false); - - // Emit a for-loop that partially reduces the elements in the given - // z-x-tile. - auto emit_z_x_tile_element_loop = [&](bool x_tile_in_bounds, - int64 x_tile_loop_bound) -> Status { - auto emit_z_tile_element_loop = [&](llvm::Value* z_indvar) -> Status { - llvm::Value* z = - NSWAdd(z_indvar, NSWMul(index_typed_constant(z_tile_size), z_tile)); - TF_RETURN_IF_ERROR(ksl.For( - "x_tile", - /*start=*/index_typed_constant(0), - /*end=*/index_typed_constant(x_tile_loop_bound), - /*step=*/1, [&](llvm::Value* x_indvar) -> Status { - // x = lane_id + - // warpSize * (element_id_in_x_tile + warp_id * x_tile_size); - llvm::Value* x = NSWAdd( - lane_id, - NSWMul(index_typed_constant(kWarpSize), - NSWAdd(x_indvar, - NSWMul(warp_id, llvm::ConstantInt::get( - index_ty, x_tile_size))))); - - // Unless we know the x-tile is entirely in bounds, we have to - // emit a x-in-bounds check before reading from the input. - if (!x_tile_in_bounds) { - llvm_ir::LlvmIfData if_x_in_bounds_data = - llvm_ir::EmitIfThenElse( - ICmpULT(x, index_typed_constant(width)), "x_in_bounds", - &b_); - // Points b_ to the then-block. - llvm_ir::SetToFirstInsertPoint(if_x_in_bounds_data.true_block, - &b_); - } - - // Emit code that reads the input element and accumulates it - // to the partial reduction result. - llvm::Value* input_address = Alloca(element_ir_type); - { - // {z,y,x} is an index to input_3d_tensor_shape - // [depth,height,width]. We need to convert that to an index - // to input_shape (the shape of the operand of "reduce"). - // This conversion is composed of a transposition from - // input_shape to normalized_input_shape and a reshape from - // normalized_input_shape to input_3d_tensor_shape. - const Shape normalized_input_shape = ShapeUtil:: - MakeShapeWithDescendingLayoutAndSamePhysicalLayout( - input_shape); - auto input_shape_min2maj = - LayoutUtil::MinorToMajor(input_shape); - const std::vector transpose_dimension_mapping( - input_shape_min2maj.rbegin(), input_shape_min2maj.rend()); - const Shape input_3d_tensor_shape = - ShapeUtil::MakeShapeWithDescendingLayout( - input_shape.element_type(), {depth, height, width}); - const IrArray::Index input_3d_tensor_index( - {z, y, x}, input_3d_tensor_shape, &b_); - const IrArray::Index input_index = - input_3d_tensor_index - .SourceIndexOfReshape(input_3d_tensor_shape, - normalized_input_shape, &b_) - .SourceIndexOfTranspose( - normalized_input_shape, input_shape, - transpose_dimension_mapping, &b_); - - for (int i = 0; i != num_reduces; ++i) { - TF_ASSIGN_OR_RETURN(llvm::Value* const input_ir_value, - input_gens[i](input_index)); - Store(input_ir_value, input_address); - TF_RETURN_IF_ERROR(EmitCallToNestedComputation( - *reducers[i], - {partial_reduction_result_addresses[i], input_address}, - partial_reduction_result_addresses[i])); - } - return EmitExtraOutputsForReduce(reduce, input_index, - extra_output_gens); - } - })); - return Status::OK(); - }; - - return ksl.For("z_tile", - /*start=*/index_typed_constant(0), - /*end=*/index_typed_constant(z_tile_size), - /*step=*/1, emit_z_tile_element_loop); - }; - - llvm::Value* tile_in_bounds = - Or(b_.getInt1(width % (x_tile_size * kWarpSize) == 0), - ICmpULT(last_x, index_typed_constant(width))); - - TF_RETURN_IF_ERROR( - ksl.If(tile_in_bounds, - /*true_block_generator=*/ - [&]() -> Status { - return emit_z_x_tile_element_loop(/*x_tile_in_bounds=*/true, - x_tile_size); - }, - /*false_block_generator=*/ - [&]() -> Status { - return emit_z_x_tile_element_loop( - /*x_tile_in_bounds=*/false, - CeilOfRatio(width % (x_tile_size * kWarpSize), kWarpSize)); - })); - - // After accumulating the elements of the z_x_tile, emit calls to - // shfl_down that accumulate the partial reduction results of all - // threads in a warp. - int bit_width = llvm_ir::GetSizeInBits(element_ir_type); - // bitcast cannot be applied to aggregate types (even packed ones), so we - // instead bitcast addresses of load/store to intN* of the same bit-width. - llvm::Type* shuffle_ir_type = element_ir_type->isStructTy() - ? b_.getIntNTy(bit_width) - : element_ir_type; - for (int shuffle_distance = 16; shuffle_distance >= 1; - shuffle_distance /= 2) { - llvm::Value* result_from_other_lane = - Alloca(element_ir_type, nullptr, "result_from_other_lane"); - for (int i = 0; i != num_reduces; ++i) { - llvm::Value* partial_reduction_result = - Load(BitCast(partial_reduction_result_addresses[i], - shuffle_ir_type->getPointerTo()), - "partial_reduction_result"); - CHECK_EQ(launch_dimensions.threads_per_block() % kWarpSize, 0) - << "Requires block size a multiple of the warp size, otherwise we " - "will read undefined elements."; - Store(EmitFullWarpShuffleDown(partial_reduction_result, - b_.getInt32(shuffle_distance), &b_), - BitCast(result_from_other_lane, shuffle_ir_type->getPointerTo())); - TF_RETURN_IF_ERROR(EmitCallToNestedComputation( - *reducers[i], - {partial_reduction_result_addresses[i], result_from_other_lane}, - partial_reduction_result_addresses[i])); - } - } - - const HloInstruction* output = - reduce->IsFused() ? reduce->parent()->FusionInstruction() : reduce; - - // Emit an atomic operation that accumulates the partial reduction result of - // lane 0 (which holds the partially accumulated result for its warp) to the - // output element. - llvm_ir::LlvmIfData if_lane_id_is_zero_data = llvm_ir::EmitIfThenElse( - ICmpEQ(lane_id, index_typed_constant(0)), "lane_id_is_zero", &b_); - llvm_ir::SetToFirstInsertPoint(if_lane_id_is_zero_data.true_block, &b_); - for (int i = 0; i != num_reduces; ++i) { - llvm::Value* output_address = - GetIrArray(*output, *output, reduce_output_shapes[i]) - .EmitArrayElementAddress( - IrArray::Index(y, - ShapeUtil::GetSubshape( - output->shape(), reduce_output_shapes[i]), - &b_), - &b_, "output_element_address"); - // We don't need to emit atomic operations if there is only one tile of - // results. 'depth' is the z dimension, 'width' is the x dimension. - if (z_tile_size >= depth && x_tile_size >= width) { - TF_RETURN_IF_ERROR(EmitCallToNestedComputation( - *reducers[i], - {output_address, partial_reduction_result_addresses[i]}, - output_address)); - } else { - TF_RETURN_IF_ERROR(EmitAtomicOperationForNestedComputation( - *reducers[i], output_address, - partial_reduction_result_addresses[i])); - } - } - return Status::OK(); - }; - - // Emit a parallel loop that iterates through every input tiles. - UpdateLaunchDimensions(launch_dimensions, kernel_thunk, - ir_emitter_context_->llvm_module()); - return ParallelLoopEmitter(loop_body_emitter, tiled_input_shape, - launch_dimensions, &b_) - .EmitLoop(IrName(reduce), index_ty); -} - -// Figures out whether `reduce` is a row or column reduction, and which -// dimensions to reduce, and calls either `EmitRowReduction` or -// `EmitColumnReduction` as appropriate. -// Prerequisite: all the dimensions to keep are contiguous in the input layout -// and, if `reduce` is fused, the fused subgraph is pure -// elementwise. -Status IrEmitterUnnested::EmitReductionToVector( - KernelThunk* kernel_thunk, HloInstruction* reduce, const Shape& input_shape, - absl::Span input_gens, - absl::Span init_value_gens, - absl::Span dimensions_to_reduce, - absl::Span reducers, - absl::Span reduce_output_shapes, - absl::Span> - extra_output_gens) { - // This emission requires "reduce" to have an input layout. It is either set - // by LayoutAssignment (for a top-level kReduce) or by InstructionFusion (for - // a fused kReduce). - CHECK(input_shape.has_layout()) << "LayoutAssignment or InstructionFusion " - "doesn't set the input layout of " - << reduce->ToString(); - - // Specialize multi-dimensional-array-to-vector reduction. - std::vector input_dims_to_keep; - for (int64 input_dim = 0; input_dim < ShapeUtil::Rank(input_shape); - ++input_dim) { - if (std::find(dimensions_to_reduce.begin(), dimensions_to_reduce.end(), - input_dim) == dimensions_to_reduce.end()) { - input_dims_to_keep.push_back(input_dim); - } - } - - // Sort the dimensions to keep from minor to major, to facilitate checking - // whether another dimension is major or minor of them. - std::sort(input_dims_to_keep.begin(), input_dims_to_keep.end(), - [&input_shape](int64 dim_a, int64 dim_b) { - return PositionInContainer(LayoutUtil::MinorToMajor(input_shape), - dim_a) < - PositionInContainer(LayoutUtil::MinorToMajor(input_shape), - dim_b); - }); - // Now, if output rank is at least 1, `input_dims_to_keep.front()` is - // minormost and `input_dims_to_keep.back()` is majormost. - - // If the dimensions to keep are minormost, emit a column reduction. As all - // the dimensions to keep are contiguous, by prerequisite of - // `EmitReductionToVector`, we only need to check whether the minormost - // dimension of the input is to keep. - if (ShapeUtil::IsEffectiveScalar(reduce->shape())) { - return EmitReductionToScalar(kernel_thunk, reduce, input_shape, input_gens, - init_value_gens, reducers, - reduce_output_shapes, extra_output_gens); - } else if (input_dims_to_keep.front() == - LayoutUtil::Minor(input_shape.layout(), 0)) { - // Column reduction. Treat the result of "input" as a matrix whose width - // is the most minor dimension and height the product of other dimensions, - // and treat "reduce" as a column reduction of the input matrix. - const int64 width = ShapeUtil::ElementsIn(reduce->shape()); - // "width" can be zero, so don't do - // height = ShapeUtil::ElementsIn(input_shape) / width; - int64 height = 1; - for (int64 input_dim = 0; input_dim < ShapeUtil::Rank(input_shape); - ++input_dim) { - if (!std::count(input_dims_to_keep.begin(), input_dims_to_keep.end(), - input_dim)) { - height *= input_shape.dimensions(input_dim); - } - } - return EmitColumnReduction(kernel_thunk, height, width, reduce, input_shape, - input_gens, init_value_gens, reducers, - reduce_output_shapes, extra_output_gens); - } else { - // Reduce the row dimension of a matrix or reduce dimension 0 and 2 in a - // 3D tensor. The size of dimension 1 (the height) is the size of the - // dimension to keep, the size of dimension 0 (the depth) is the product - // of dimensions that are more major than the dimension to keep, and the - // size of dimension 2 (the width) is the product of more minor - // dimensions. - int64 depth = 1; - int64 width = 1; - for (int64 input_dim = 0; input_dim < ShapeUtil::Rank(input_shape); - ++input_dim) { - if (PositionInContainer(LayoutUtil::MinorToMajor(input_shape), - input_dim) > - PositionInContainer(LayoutUtil::MinorToMajor(input_shape), - input_dims_to_keep.back())) { - depth *= input_shape.dimensions(input_dim); - } else if (PositionInContainer(LayoutUtil::MinorToMajor(input_shape), - input_dim) < - PositionInContainer(LayoutUtil::MinorToMajor(input_shape), - input_dims_to_keep.front())) { - width *= input_shape.dimensions(input_dim); - } - } - const int64 height = ShapeUtil::ElementsIn(reduce->shape()); - return EmitRowReduction(kernel_thunk, depth, height, width, reduce, - input_shape, input_gens, init_value_gens, reducers, - reduce_output_shapes, extra_output_gens); - } -} - Status IrEmitterUnnested::HandleReduce(HloInstruction* reduce) { // TODO(b/112040122): Support multi-output reduce. if (!ShapeUtil::IsArray(reduce->shape())) { return Unimplemented("Multi-output reduce is not supported on GPU"); } - auto input = reduce->operand(0); - auto init_value = reduce->operand(1); - absl::Span dimensions_to_reduce(reduce->dimensions()); - HloComputation* reducer = reduce->to_apply(); - // HandleReduce specializes reduction from a multi-dimensional array to a 1D - // array. The specialized version requires an initializer thunk that - // initializes the output array to the initial value of the reduce. if (IsReductionToVector(*reduce)) { - TF_ASSIGN_OR_RETURN(std::unique_ptr initializer_thunk, - BuildInitializerThunk(reduce)); - std::vector> thunks; - thunks.push_back(std::move(initializer_thunk)); - std::unique_ptr kernel_thunk = - BuildKernelThunk(reduce, /*implements_whole_instruction=*/false); - - TF_CHECK_OK(EmitReductionToVector( - kernel_thunk.get(), reduce, input->shape(), - {[&](const IrArray::Index& index) { - return GetIrArray(*input, *reduce).EmitReadArrayElement(index, &b_); - }}, - {[&](const IrArray::Index& index) { - return GetIrArray(*init_value, *reduce) - .EmitReadArrayElement(index, &b_); - }}, - dimensions_to_reduce, {reducer}, {{}}, {})); - - thunks.push_back(std::move(kernel_thunk)); - - std::unique_ptr sequential_thunk = - absl::make_unique(std::move(thunks), reduce); - AddThunkToThunkSequence(std::move(sequential_thunk)); - return Status::OK(); + return EmitReductionToVector(reduce); } return IrEmitter::HandleReduce(reduce); @@ -1818,7 +763,7 @@ Status IrEmitterUnnested::HandleSelectAndScatter( // Create the inner loop to iterate over the window. llvm_ir::ForLoopNest window_loops(IrName(select_and_scatter, "inner"), &b_, index_type); - std::vector window_size; + DimensionVector window_size; for (const auto& dim : window.dimensions()) { window_size.push_back(dim.size()); CHECK_GT(dim.size(), 0); @@ -2171,7 +1116,18 @@ Status IrEmitterUnnested::HandleSelect(HloInstruction* select) { Status IrEmitterUnnested::HandleSort(HloInstruction* sort) { std::vector> thunks; Shape keys_shape = sort->operand(0)->shape(); + int64 dimension_to_sort = sort->dimensions(0); + // In case there is a 'values' parameter that is a iota, we take note and use + // it later to ensure a stable sort. Otherwise, we don't guarantee a stable + // sort. + int64 iota_values_parameter_index = -1; for (int64 i = 0; i < sort->operand_count(); ++i) { + if (i > 0 && sort->operand(i)->opcode() == HloOpcode::kIota && + ShapeUtil::ElementIsIntegral(sort->operand(i)->shape()) && + Cast(sort->operand(i))->iota_dimension() == + dimension_to_sort) { + iota_values_parameter_index = i; + } ShapeIndex shape_index = sort->operand_count() > 1 ? ShapeIndex({i}) : ShapeIndex({}); // We assume that the layout of all involved operands and outputs is the @@ -2196,7 +1152,6 @@ Status IrEmitterUnnested::HandleSort(HloInstruction* sort) { } } - int64 dimension_to_sort = sort->dimensions(0); uint64 dimension_to_sort_bound = keys_shape.dimensions(dimension_to_sort); int64 num_stages = tensorflow::Log2Ceiling(dimension_to_sort_bound); CHECK_GE(1ULL << num_stages, dimension_to_sort_bound); @@ -2298,8 +1253,9 @@ Status IrEmitterUnnested::HandleSort(HloInstruction* sort) { } } return llvm_ir::EmitSortInPlace( - dimension_to_sort, keys_array, values_arrays, IrName(sort), xor_masks, - &b_, launch_dimensions, + dimension_to_sort, keys_array, values_arrays, + iota_values_parameter_index, IrName(sort), xor_masks, &b_, + launch_dimensions, xor_masks.size() > 1 ? num_iterations_in_sort_dim : standard_num_iterations_in_sort_dim, kTileSize); @@ -2385,7 +1341,7 @@ Status IrEmitterUnnested::HandleCrossReplicaSum(HloInstruction* crs) { return Status::OK(); } -Status IrEmitterUnnested::HandleAfterAll(HloInstruction* gen_token) { +Status IrEmitterUnnested::HandleAfterAll(HloInstruction* after_all) { return Status::OK(); } @@ -3146,31 +2102,6 @@ std::vector IrEmitterUnnested::ConstructIrArrayForInputs( return param_arrays; } -int IrEmitterUnnested::ConstructOutputReducedShapeAndCastOutputIrArrayToShape( - const HloInstruction& hlo, const std::vector& output_arrays, - absl::Span reduced_output_dims, - std::vector* output_reduced_shapes, - std::vector* output_in_reduced_shape_arrays) { - int64 num_outputs = 1; - if (hlo.IsMultiOutputFusion()) { - num_outputs = ShapeUtil::TupleElementCount(hlo.shape()); - output_in_reduced_shape_arrays->reserve(num_outputs); - output_reduced_shapes->reserve(num_outputs); - for (int64 i = 0; i < num_outputs; ++i) { - output_reduced_shapes->push_back(ShapeUtil::MakeShapeWithDescendingLayout( - ShapeUtil::GetSubshape(hlo.shape(), {i}).element_type(), - reduced_output_dims)); - output_in_reduced_shape_arrays->push_back( - output_arrays[i].CastToShape((*output_reduced_shapes)[i], &b_)); - } - } else { - output_reduced_shapes->push_back(ShapeUtil::MakeShapeWithDescendingLayout( - hlo.shape().element_type(), reduced_output_dims)); - output_in_reduced_shape_arrays->push_back( - output_arrays[0].CastToShape((*output_reduced_shapes)[0], &b_)); - } - return num_outputs; -} int IrEmitterUnnested::ConstructInputReducedShapeAndCastInputIrArrayToShape( const HloInstruction& hlo, const std::vector& param_arrays, @@ -3230,304 +2161,894 @@ llvm::Value* GetBlockIdx(llvm::IRBuilder<>* builder, llvm::Type* index_ty, "block.id.x"); } -// Emits code to process up to (tile_size/num_rows) elements in a tile, given -// `emit_elem_function` is the function to emit code to process one element, `y` -// and `x` are the coordinates for the first element to process, and `index` is -// the index for the origin of the tile. Emits bounds check to ensure that each -// processed element is within the boundary defined by `tile_width` and -// `tile_height`. +void EmitFullTile(const KernelMappingScheme* mapping_scheme, + const IrArray::Index& tile_origin_index, + llvm::IRBuilder<>* builder, llvm::Value* y, llvm::Value* x, + llvm::Type* index_ty, + const std::function& emit_elem_function) { + int64 num_threads_x = mapping_scheme->GetNumberOfThreadsForDimensionX(); + int64 num_threads_y = mapping_scheme->GetNumberOfThreadsForDimensionY(); + int64 tile_size_x = mapping_scheme->GetTileSizeForDimensionX(); + int64 tile_size_y = mapping_scheme->GetTileSizeForDimensionY(); + for (int64 i = 0; i < tile_size_y; i += num_threads_y) { + IrArray::Index source_idx_y = + tile_origin_index.AddOffsetToDim(llvm::ConstantInt::get(index_ty, i), + KernelMappingScheme::DimY, builder); + llvm::Value* y_loc = + builder->CreateAdd(llvm::ConstantInt::get(index_ty, i), y); + for (int64 j = 0; j < tile_size_x; j += num_threads_x) { + IrArray::Index source_idx = + source_idx_y.AddOffsetToDim(llvm::ConstantInt::get(index_ty, j), + KernelMappingScheme::DimX, builder); + llvm::Value* x_loc = + builder->CreateAdd(llvm::ConstantInt::get(index_ty, j), x); + emit_elem_function(source_idx, y_loc, x_loc); + } + } +} + +void EmitPartialTile( + const KernelMappingScheme* mapping_scheme, + const IrArray::Index& tile_origin_index, const string& loop_name, + KernelSupportLibrary* ksl, llvm::IRBuilder<>* builder, llvm::Value* y, + llvm::Value* x, llvm::Value* tile_height, llvm::Value* tile_width, + llvm::Type* index_ty, + const std::function& emit_elem_function) { + int64 num_threads_x = mapping_scheme->GetNumberOfThreadsForDimensionX(); + int64 num_threads_y = mapping_scheme->GetNumberOfThreadsForDimensionY(); + int64 tile_size_x = mapping_scheme->GetTileSizeForDimensionX(); + + for (int64 j = 0; j < tile_size_x; j += num_threads_x) { + IrArray::Index source_idx = + tile_origin_index.AddOffsetToDim(llvm::ConstantInt::get(index_ty, j), + KernelMappingScheme::DimX, builder); + llvm::Value* x_loc = + builder->CreateAdd(llvm::ConstantInt::get(index_ty, j), x); + + ksl->IfReturnVoid( + loop_name + "_x_in_tile", builder->CreateICmpULT(x_loc, tile_width), + [&] { + // tile_height_bound = + // ceil(tile_height / num_threads_y) * num_threads_y + llvm::Value* ceiling_of_ratio = builder->CreateUDiv( + builder->CreateAdd(tile_height, llvm::ConstantInt::get( + index_ty, num_threads_y - 1)), + llvm::ConstantInt::get(index_ty, num_threads_y)); + llvm::Value* tile_height_bound = builder->CreateMul( + ceiling_of_ratio, + llvm::ConstantInt::get(index_ty, num_threads_y)); + ksl->ForReturnVoid( + loop_name, /*start=*/llvm::ConstantInt::get(index_ty, 0), + /*end=*/tile_height_bound, + /*step=*/llvm::ConstantInt::get(index_ty, num_threads_y), + [&](llvm::Value* y_indvar) { + llvm::Value* y_loc = builder->CreateAdd(y_indvar, y); + ksl->IfReturnVoid( + loop_name + "_y_in_tile", + builder->CreateICmpULT(y_loc, tile_height), [&] { + emit_elem_function( + source_idx.AddOffsetToDim( + y_indvar, KernelMappingScheme::DimY, builder), + y_loc, x_loc); + }); + }); + }); + } +} + +// Emits code to process up to +// (tile_size_x/num_threads_x * tile_size_y/num_threads_y) elements in a tile, +// given `emit_elem_function` is the function to emit code to process one +// element, `y` and `x` are the intra-tile coordinates for the first element +// to process, and `index` is the index for the origin of the tile. Information +// about tile_size_x/y and num_threads_x/y are stored in `mapping_scheme`. Emits +// bounds check to ensure that each processed element is within the boundary +// defined by `tile_width` and `tile_height`. void EmitTiledElementalCodeWithBoundsCheck( - int64 tile_size, int64 num_rows, const IrArray::Index& index, - const string& loop_name, KernelSupportLibrary* ksl, - llvm::IRBuilder<>* builder, llvm::Value* y, llvm::Value* x, - llvm::Value* tile_width, llvm::Value* tile_height, - const std::function& - emit_elem_function) { + const KernelMappingScheme* mapping_scheme, + const IrArray::Index& tile_origin_index, const string& loop_name, + KernelSupportLibrary* ksl, llvm::IRBuilder<>* builder, llvm::Value* y, + llvm::Value* x, llvm::Value* tile_height, llvm::Value* tile_width, + const std::function& emit_elem_function) { + int64 tile_size_x = mapping_scheme->GetTileSizeForDimensionX(); + int64 tile_size_y = mapping_scheme->GetTileSizeForDimensionY(); llvm::Type* index_ty = tile_width->getType(); - // Emits a constant value with index type. + + ksl->IfReturnVoid( + loop_name + "_full_tile", + builder->CreateAnd( + builder->CreateICmpEQ(llvm::ConstantInt::get(index_ty, tile_size_x), + tile_width), + builder->CreateICmpEQ(llvm::ConstantInt::get(index_ty, tile_size_y), + tile_height)), + [&] { + EmitFullTile(mapping_scheme, tile_origin_index, builder, y, x, index_ty, + emit_elem_function); + }, + [&] { + EmitPartialTile(mapping_scheme, tile_origin_index, loop_name, ksl, + builder, y, x, tile_height, tile_width, index_ty, + emit_elem_function); + }); +} +} // namespace + +// Emits code to process a tensor element in a tile for the given kCopy HLO that +// performs a 0-2-1 transpose. +// +// index: The index for the first output element in the normalized tensor. The +// normalized tensor is the resulting tensor after collapsing contiguous +// dimensions that play the same role in the transpose. +// y_loc: The y coordinate within a tile. +// x_loc: The x coordinate within a tile. +// kernel_info: Other information to support the kernel code generation. +void IrEmitterUnnested::EmitTileElementForCopy( + HloInstruction* hlo, const llvm_ir::IrArray::Index& index, + const KernelCodegenInfo* kernel_info, llvm::Value* y_loc, + llvm::Value* x_loc) { + llvm_ir::TiledParameterInfo* tiled_param_info = + kernel_info->GetTiledParameterInfo(); + // TODO(jlebar): Add AA metadata to this load. + llvm::Instruction* load_from_shmem_buffer = + Load(GEP(tiled_param_info->GetBufferForParameter(0), + {b_.getInt64(0), x_loc, y_loc}), + "output_element"); + llvm_ir::IrArray output_array = GetIrArray(*hlo, *hlo); + Shape output_reduced_shape = ShapeUtil::MakeShapeWithDescendingLayout( + hlo->shape().element_type(), + kernel_info->GetKernelMappingScheme()->GetDimensionsInElements()); + // When the output_reduced_shape is a 0-2-1 transpose of the input shape, + // the 0-2-1 transpose is achieved through EmitWriteArrayElement. + output_array.CastToShape(output_reduced_shape, &b_) + .EmitWriteArrayElement(index, load_from_shmem_buffer, &b_); +} + +// Emits code to process a tensor element in a tile for the given kLoop fusion +// HLO containing parameters that are 0-2-1 transpose of its outputs. +// +// index: The index for the first output element in the normalized tensor, that +// is the resulting tensor after collapsing contiguous dimensions that play +// the same role in the transpose. +// kernel_info: Other information to support the kernel code generation. +// y_loc: The y coordinate within a tile. +// x_loc: The x coordinate within a tile. +void IrEmitterUnnested::EmitTileElementForFusion( + HloInstruction* hlo, const llvm_ir::IrArray::Index& index, + const KernelCodegenInfo* kernel_info, llvm::Value* y_loc, + llvm::Value* x_loc) { + llvm_ir::TiledParameterInfo* tiled_param_info = + kernel_info->GetTiledParameterInfo(); + std::vector output_arrays = ConstructIrArrayForOutputs(*hlo); + GpuElementalIrEmitter elem_emitter(hlo_module_config_, module_, &b_, + GetNestedComputer()); + FusedIrEmitter fused_emitter(GetGeneratorForOperandIrArrays(hlo), + &elem_emitter); + tiled_param_info->set_y(y_loc); + tiled_param_info->set_x(x_loc); + fused_emitter.SetTiledParameterInfo(tiled_param_info); + TF_CHECK_OK(hlo->fused_expression_root()->Accept(&fused_emitter)); + IrArray::Index untiled_index = + kernel_info->GetKernelMappingScheme()->GetUnnormalizedIndex( + index, output_arrays[0].GetShape()); + const llvm_ir::ElementGenerator& output_generator = + fused_emitter.GetRootGenerator(); + llvm::Value* output_value = output_generator(untiled_index).ValueOrDie(); + if (hlo->IsMultiOutputFusion()) { + DCHECK(output_value->getType()->isStructTy()); + DCHECK_EQ(output_value->getType()->getStructNumElements(), + output_arrays.size()); + for (int64 i = 0; i < output_arrays.size(); ++i) { + output_arrays[i].EmitWriteArrayElement( + untiled_index, ExtractValue(output_value, i), &b_); + } + } else { + output_arrays[0].EmitWriteArrayElement(untiled_index, output_value, &b_); + } +} + +// Information to support the code generation for a tiled reduction kernel. +using AddressVector = InlinedVector; +class ReductionCodegenInfo : public IrEmitterUnnested::KernelCodegenInfo { + public: + explicit ReductionCodegenInfo(llvm_ir::KernelMappingScheme* mapping_scheme, + bool is_row_reduction) + : KernelCodegenInfo(mapping_scheme), + current_output_linear_index_address_(nullptr), + current_output_inbound_address_(nullptr), + is_row_reduction_(is_row_reduction) {} + + void SetCurrentOutputLinearIndexAddress(llvm::AllocaInst* a) { + current_output_linear_index_address_ = a; + } + // Returns the address of the memory that stores the linear index of the + // current output. Since we are processing reduction to contiguous physical + // dimensions, this linear index is the linear index of the 1D output array. + llvm::AllocaInst* GetCurrentOutputLinearIndexAddress() const { + return current_output_linear_index_address_; + } + + void SetCurrentOutputInboundAddress(llvm::AllocaInst* a) { + current_output_inbound_address_ = a; + } + + llvm::AllocaInst* GetCurrentOutputInboundAddress() const { + return current_output_inbound_address_; + } + + AddressVector* GetMutablePartialResultAddresses() { + return &partial_result_addresses_; + } + const AddressVector& GetPartialResultAddresses() const { + return partial_result_addresses_; + } + + AddressVector* GetMutableReductionInputAddresses() { + return &reduction_input_addresses_; + } + const AddressVector& GetReductionInputAddresses() const { + return reduction_input_addresses_; + } + + InlinedVector* GetMutableReducers() { return &reducers_; } + const InlinedVector& GetReducers() const { + return reducers_; + } + int GetNumberOfReduces() const { return reducers_.size(); } + + InlinedVector* GetMutableReductionOutputShapeIndices() { + return &reduction_output_shape_indices_; + } + const InlinedVector& GetReductionOutputShapeIndices() const { + return reduction_output_shape_indices_; + } + + bool IsRowReduction() const { return is_row_reduction_; } + + // Return the dimension that is being reduced between DimX and DimY. + int GetReducedDimensionEnum() const { + return IsRowReduction() ? llvm_ir::KernelMappingScheme::DimX + : llvm_ir::KernelMappingScheme::DimY; + } + + // Return the dimension that is being ketp between DimX and DimY. + int GetKeptDimensionEnum() const { + return IsRowReduction() ? llvm_ir::KernelMappingScheme::DimY + : llvm_ir::KernelMappingScheme::DimX; + } + + private: + AddressVector partial_result_addresses_; + AddressVector reduction_input_addresses_; + InlinedVector reducers_; + InlinedVector reduction_output_shape_indices_; + llvm::AllocaInst* current_output_linear_index_address_; + llvm::AllocaInst* current_output_inbound_address_; + bool is_row_reduction_; +}; + +namespace { +// Returns a group of instructions that generate the output for the kernel +// containing the given HLO instruction. The result may be an unnested kReduce +// HLO, a nested kReduce HLO of a kInput fusion, or the operands of the tuple +// for a multiple output fusion. +absl::Span GetOutputInstructions( + HloInstruction* const* reduce_or_tuple_pointer) { + HloOpcode opcode = (*reduce_or_tuple_pointer)->opcode(); + CHECK(opcode == HloOpcode::kReduce || opcode == HloOpcode::kTuple); + return opcode == HloOpcode::kTuple + ? (*reduce_or_tuple_pointer)->operands() + : absl::Span(reduce_or_tuple_pointer, 1); +} + +const HloInstruction* GetFirstReduceInstruction( + absl::Span instructions) { + auto first_reduce_iter = + absl::c_find_if(instructions, [](const HloInstruction* inst) { + return inst->opcode() == HloOpcode::kReduce; + }); + CHECK_NE(first_reduce_iter, instructions.end()); + return *first_reduce_iter; +} + +}; // namespace + +void IrEmitterUnnested::EmitPrologueForOneReduction( + HloInstruction* unnested_hlo, HloInstruction* reduce_inst, int reduce_idx, + KernelCodegenInfo* kernel_info, GpuElementalIrEmitter* elemental_emitter, + ShapeIndex output_shape_index) { + ReductionCodegenInfo* reduction_info = + static_cast(kernel_info); + + InlinedVector* reducers = + reduction_info->GetMutableReducers(); + CHECK(IsReductionToVector(*reduce_inst)); + reducers->push_back(reduce_inst->to_apply()); + + InlinedVector* reduction_output_shape_indices = + reduction_info->GetMutableReductionOutputShapeIndices(); + reduction_output_shape_indices->push_back(std::move(output_shape_index)); + + AddressVector* reduction_input_addresses = + reduction_info->GetMutableReductionInputAddresses(); + llvm::Type* element_type = llvm_ir::PrimitiveTypeToIrType( + reduce_inst->shape().element_type(), ir_emitter_context_->llvm_module()); + llvm::AllocaInst* reduction_input_address = Alloca(element_type); + reduction_input_addresses->push_back(reduction_input_address); + + AddressVector* partial_result_addresses = + reduction_info->GetMutablePartialResultAddresses(); + llvm::AllocaInst* partial_result_address = + Alloca(element_type, /*ArraySize=*/nullptr, + "partial_reduction_result." + llvm::Twine(reduce_idx)); + partial_result_addresses->push_back(partial_result_address); + + // Initialize the partial result with the initial value of the reduction. + llvm::Value* init_ir_value; + if (unnested_hlo->opcode() == HloOpcode::kFusion) { + HloInstruction* init_value_operand = reduce_inst->mutable_operand(1); + FusedIrEmitter fused_emitter(GetGeneratorForOperandIrArrays(unnested_hlo), + elemental_emitter); + + TF_CHECK_OK(init_value_operand->Accept(&fused_emitter)); + init_ir_value = + fused_emitter + .GetGenerator(init_value_operand)(IrArray::Index(b_.getInt32Ty())) + .ValueOrDie(); + } else { + const HloInstruction* init_value = unnested_hlo->operand(1); + init_ir_value = + GetIrArray(*init_value, *unnested_hlo) + .EmitReadArrayElement(IrArray::Index(b_.getInt32Ty()), &b_); + } + + Store(init_ir_value, partial_result_address); +} + +void IrEmitterUnnested::EmitPrologueForReduction( + HloInstruction* unnested_hlo, KernelCodegenInfo* kernel_info) { + VLOG(10) << "Emit prologue for reduction " << unnested_hlo->ToString(); + // Find the unnested kReduce or the tuple that contains a list of kReduce. + HloInstruction* reduce_or_tuple = unnested_hlo->opcode() == HloOpcode::kFusion + ? unnested_hlo->fused_expression_root() + : unnested_hlo; + absl::Span output_instructions = + GetOutputInstructions(&reduce_or_tuple); + ReductionCodegenInfo* reduction_info = + static_cast(kernel_info); + GpuElementalIrEmitter elemental_emitter(hlo_module_config_, + ir_emitter_context_->llvm_module(), + &b_, GetNestedComputer()); + const HloInstruction* first_reduce = nullptr; + for (int i = 0, e = output_instructions.size(); i != e; ++i) { + if (output_instructions[i]->opcode() != HloOpcode::kReduce) { + continue; + } + HloInstruction* reduce_inst = output_instructions[i]; + if (first_reduce == nullptr) { + first_reduce = reduce_inst; + } else { + CHECK(first_reduce->dimensions() == reduce_inst->dimensions()); + } + ShapeIndex output_shape_index; + if (reduce_or_tuple->opcode() == HloOpcode::kTuple) { + output_shape_index = {i}; + } + + EmitPrologueForOneReduction(unnested_hlo, reduce_inst, i, kernel_info, + &elemental_emitter, + std::move(output_shape_index)); + } + + // Allocate stack storage to store the current output linear index and record + // the address of the storage. + reduction_info->SetCurrentOutputLinearIndexAddress( + Alloca(reduction_info->GetIndexType())); + + if (!reduction_info->IsRowReduction()) { + llvm::Type* bool_ty = b_.getInt1Ty(); + llvm::AllocaInst* output_inbound_addr = Alloca(bool_ty); + Store(llvm::ConstantInt::get(bool_ty, 0), output_inbound_addr); + reduction_info->SetCurrentOutputInboundAddress(output_inbound_addr); + } +} + +void IrEmitterUnnested::EmitFullWarpShuffleDownLoopForAllReduces( + const InlinedVector& reducers, + const AddressVector& partial_result_addresses) { + for (int distance = 16; distance >= 1; distance /= 2) { + for (int i = 0; i != reducers.size(); ++i) { + llvm::Type* element_type = + partial_result_addresses[i]->getType()->getElementType(); + int bit_width = llvm_ir::GetSizeInBits(element_type); + llvm::Value* result_from_other_lane = Alloca( + element_type, nullptr, "result_from_other_lane" + llvm::Twine(i)); + // Bitcast cannot be applied to aggregate types (even packed ones), so + // we bitcast addresses of load/store to intN* of the same bit-width. + llvm::Type* shuffled_value_type = + element_type->isStructTy() ? b_.getIntNTy(bit_width) : element_type; + auto convert_pointer_for_shuffle = [&](llvm::Value* ptr) { + return BitCast(ptr, shuffled_value_type->getPointerTo()); + }; + llvm::Value* partial_result = + Load(convert_pointer_for_shuffle(partial_result_addresses[i]), + "partial_reduction_result"); + Store(EmitFullWarpShuffleDown(partial_result, b_.getInt32(distance), &b_), + convert_pointer_for_shuffle(result_from_other_lane)); + TF_CHECK_OK(EmitCallToNestedComputation( + *reducers[i], {partial_result_addresses[i], result_from_other_lane}, + partial_result_addresses[i])); + } + } +} + +void IrEmitterUnnested::EmitEpilogueForReduction( + HloInstruction* unnested_hlo, KernelCodegenInfo* kernel_info) { + ReductionCodegenInfo* reduction_info = + static_cast(kernel_info); + int num_reduces = reduction_info->GetNumberOfReduces(); + const AddressVector& partial_result_addresses = + reduction_info->GetPartialResultAddresses(); + const InlinedVector& reducers = + reduction_info->GetReducers(); + const InlinedVector& reduction_output_shape_indices = + reduction_info->GetReductionOutputShapeIndices(); + + if (reduction_info->IsRowReduction()) { + EmitFullWarpShuffleDownLoopForAllReduces(reducers, + partial_result_addresses); + llvm::Value* lane_id = reduction_info->GetLaneId(); + llvm_ir::LlvmIfData if_lane_id_is_zero_data = llvm_ir::EmitIfThenElse( + ICmpEQ(lane_id, llvm::ConstantInt::get(lane_id->getType(), 0)), + "lane_id_is_zero", &b_); + llvm_ir::SetToFirstInsertPoint(if_lane_id_is_zero_data.true_block, &b_); + } else { + llvm::Value* output_inbound_addr = + reduction_info->GetCurrentOutputInboundAddress(); + llvm::Value* output_inbound = Load(output_inbound_addr); + llvm_ir::LlvmIfData if_output_inbound_data = llvm_ir::EmitIfThenElse( + ICmpEQ(output_inbound, + llvm::ConstantInt::get(output_inbound->getType(), 1)), + "output_inbound", &b_); + llvm_ir::SetToFirstInsertPoint(if_output_inbound_data.true_block, &b_); + } + + // Emit an atomic operation that accumulates the partial reduction to the + // output element. For row reduction, this is only for lane 0 due to the + // if-statement emitted above. + for (int i = 0; i != num_reduces; ++i) { + IrArray::Index element_index( + /*linear=*/Load(reduction_info->GetCurrentOutputLinearIndexAddress(), + "output_linear_addr"), + ShapeUtil::GetSubshape(unnested_hlo->shape(), + reduction_output_shape_indices[i]), + &b_); + llvm::Value* output_address = + GetIrArray(*unnested_hlo, *unnested_hlo, + reduction_output_shape_indices[i]) + .EmitArrayElementAddress(element_index, &b_, + "output_element_address"); + // Do not emit atomic operations if each element in the reduction result is + // computed by one block, that is the dimension being reduced has only one + // block. + const llvm_ir::KernelMappingScheme* mapping_scheme = + reduction_info->GetKernelMappingScheme(); + if (mapping_scheme->GetTileBlockSizeForDimension( + llvm_ir::KernelMappingScheme::DimZ) == 1 && + mapping_scheme->GetTileBlockSizeForDimension( + reduction_info->GetReducedDimensionEnum()) == 1) { + TF_CHECK_OK(EmitCallToNestedComputation( + *reducers[i], {output_address, partial_result_addresses[i]}, + output_address)); + } else { + TF_CHECK_OK(EmitAtomicOperationForNestedComputation( + *reducers[i], output_address, partial_result_addresses[i])); + } + } +} + +void IrEmitterUnnested::EmitTileElementForReduction( + HloInstruction* unnested_hlo, const llvm_ir::IrArray::Index& index, + const KernelCodegenInfo* kernel_info, llvm::Value* y_loc, + llvm::Value* x_loc) { + VLOG(10) << "Emit tile element for reduce " << unnested_hlo->ToString(); + HloInstruction* reduce_or_tuple = unnested_hlo->opcode() == HloOpcode::kFusion + ? unnested_hlo->fused_expression_root() + : unnested_hlo; + llvm_ir::TiledParameterInfo* tiled_param_info = + kernel_info->GetTiledParameterInfo(); + tiled_param_info->set_y(y_loc); + tiled_param_info->set_x(x_loc); + + // Record the linear address for the current reduction. + const ReductionCodegenInfo* reduction_info = + dynamic_cast(kernel_info); + Store(index[reduction_info->GetKeptDimensionEnum()], + reduction_info->GetCurrentOutputLinearIndexAddress()); + if (!reduction_info->IsRowReduction()) { + llvm::Type* bool_ty = b_.getInt1Ty(); + llvm::AllocaInst* output_inbound_addr = + reduction_info->GetCurrentOutputInboundAddress(); + Store(llvm::ConstantInt::get(bool_ty, 1), output_inbound_addr); + } + + InlinedVector input_gens; + std::vector> + extra_output_gens; + GpuElementalIrEmitter elem_emitter(hlo_module_config_, module_, &b_, + GetNestedComputer()); + FusedIrEmitter fused_emitter(GetGeneratorForOperandIrArrays(unnested_hlo), + &elem_emitter); + absl::Span output_instructions = + GetOutputInstructions(&reduce_or_tuple); + // Construct the ElementGenerator for each reduction and extra output in the + // the group of output instructions. + if (unnested_hlo->opcode() == HloOpcode::kFusion) { + fused_emitter.SetTiledParameterInfo(tiled_param_info); + TF_CHECK_OK(unnested_hlo->fused_expression_root()->Accept(&fused_emitter)); + + for (int i = 0, e = output_instructions.size(); i != e; ++i) { + const HloInstruction* inst = output_instructions[i]; + ShapeIndex output_shape_index; + if (reduce_or_tuple->opcode() == HloOpcode::kTuple) { + output_shape_index = {i}; + } + if (inst->opcode() == HloOpcode::kReduce) { + input_gens.push_back(fused_emitter.GetGenerator(inst->operand(0))); + } else { + extra_output_gens.emplace_back(fused_emitter.GetGenerator(inst), + std::move(output_shape_index)); + } + } + } else { + input_gens.push_back([&](const IrArray::Index& index) { + return GetIrArray(*unnested_hlo->operand(0), *unnested_hlo) + .EmitReadArrayElement(index, &b_); + }); + } + + IrArray::Index input_index = + reduction_info->GetKernelMappingScheme()->GetUnnormalizedIndex( + index, + GetFirstReduceInstruction(output_instructions)->operand(0)->shape()); + const AddressVector& partial_reduction_result_addresses = + reduction_info->GetPartialResultAddresses(); + const AddressVector& reduction_input_addresses = + reduction_info->GetReductionInputAddresses(); + const InlinedVector& reducers = + reduction_info->GetReducers(); + + // Emit code to generate the input and perform the reduction computation for + // each reduction instruction. + for (int i = 0; i != reducers.size(); ++i) { + llvm::Value* const input_ir_value = input_gens[i](input_index).ValueOrDie(); + Store(input_ir_value, reduction_input_addresses[i]); + TF_CHECK_OK(EmitCallToNestedComputation( + *reducers[i], + {partial_reduction_result_addresses[i], reduction_input_addresses[i]}, + partial_reduction_result_addresses[i])); + } + + // Emit code to generate the output for the non-reduction instructions in the + // fusion, if any. + TF_CHECK_OK( + EmitExtraOutputsForReduce(unnested_hlo, input_index, extra_output_gens)); +} + +// Emits a kernel for the hlo instruction using the given tiling scheme. +void IrEmitterUnnested::EmitBlock(const TileGenerator& emit_one_tile, + const KernelCodegenInfo* kernel_info, + KernelSupportLibrary& ksl, + llvm::Type* index_ty) { + KernelMappingScheme* mapping_scheme = kernel_info->GetKernelMappingScheme(); + absl::Span dims_in_tile = mapping_scheme->GetDimensionsInTiles(); + absl::Span dims_in_block = + mapping_scheme->GetDimensionsInBlocks(); + absl::Span block_sizes = mapping_scheme->GetBlockSizes(); auto index_typed_constant = [&](uint64 c) -> llvm::Constant* { return llvm::ConstantInt::get(index_ty, c); }; - // Adds `addend` to the given `dim` of `index`. - auto offset_dim = [&](IrArray::Index index, llvm::Value* addend, int64 dim) { - index[dim] = builder->CreateAdd(index[dim], addend); - return index; - }; - auto emit_full_tile = [&] { - for (int64 i = 0; i < tile_size; i += num_rows) { - auto source_idx = offset_dim(index, index_typed_constant(i), /*dim=*/1); - auto y_loc = builder->CreateAdd(index_typed_constant(i), y); - emit_elem_function(source_idx, y_loc); + // Emit all the tiles for a given dimension in a tile block. + auto emit_tiles_for_block_dim = + [&](const string& loop_name, const IrArray::Index& starting_tile, + int dim_id, + const std::function + emit_next_block_dim) { + if (block_sizes[dim_id] == 1) { + emit_next_block_dim(starting_tile); + } else { + llvm::Value* starting_tile_index_for_dim = starting_tile[dim_id]; + llvm::Value* block_size_for_dim = + index_typed_constant(block_sizes[dim_id]); + llvm::Value* block_id_for_dim = + b_.CreateUDiv(starting_tile_index_for_dim, block_size_for_dim); + llvm::Value* last_block_for_dim = + index_typed_constant(dims_in_block[dim_id] - 1); + llvm::Value* last_block_size_for_dim = index_typed_constant( + dims_in_tile[dim_id] - + (dims_in_block[dim_id] - 1) * block_sizes[dim_id]); + llvm::Value* num_tiles_in_block = + Select(ICmpEQ(last_block_for_dim, block_id_for_dim), + last_block_size_for_dim, block_size_for_dim); + + ksl.ForReturnVoid( + loop_name, + /*start=*/index_typed_constant(0), + /*end=*/num_tiles_in_block, + /*step=*/1, [&](llvm::Value* block_dim_induction_var) { + IrArray::Index tile_index = starting_tile.AddOffsetToDim( + block_dim_induction_var, dim_id, &b_); + emit_next_block_dim(tile_index); + }); + } + }; + + absl::Span reduced_dims = + mapping_scheme->GetDimensionsInElements(); + const bool block_contains_multi_tiles = + mapping_scheme->GetNumberOfTilesInOneBlock() > 1; + + // Emit the tile with a given tile_index, by calculating the tight bounds for + // each dimension of the tile and then calling emit_one_tile. + auto emit_one_tile_for_tile_index = [&](const IrArray::Index& tile_index) { + std::vector output_tile_bounds(3); + for (int i = KernelMappingScheme::DimY; i < KernelMappingScheme::DimTot; + ++i) { + int64 tile_size_for_dim = mapping_scheme->GetTileSizeForDimension(i); + // Only last row or column may not have full size. + llvm::Value* is_last_row = + ICmpEQ(tile_index[i], index_typed_constant(dims_in_tile[i] - 1)); + int64 partial_row_size = + reduced_dims[i] - (dims_in_tile[i] - 1) * tile_size_for_dim; + output_tile_bounds[i] = + Select(is_last_row, index_typed_constant(partial_row_size), + index_typed_constant(tile_size_for_dim), "tile_bound"); } - }; - auto emit_last_row = [&] { - ksl->IfReturnVoid("x_in_tile", builder->CreateICmpULT(x, tile_width), [&] { - // tile_height_upper_bound = - // ceil(tile_height / num_rows) * num_rows - auto tile_height_upper_bound = builder->CreateMul( - builder->CreateUDiv( - builder->CreateAdd(tile_height, - index_typed_constant(num_rows - 1)), - index_typed_constant(num_rows)), - index_typed_constant(num_rows)); - ksl->ForReturnVoid( - loop_name, /*start=*/index_typed_constant(0), - /*end=*/tile_height_upper_bound, - /*step=*/index_typed_constant(num_rows), [&](llvm::Value* y_indvar) { - auto y_loc = builder->CreateAdd(y_indvar, y); - ksl->IfReturnVoid( - "y_in_tile", builder->CreateICmpULT(y_loc, tile_height), [&] { - emit_elem_function(offset_dim(index, y_indvar, /*dim=*/1), - y_loc); - }); - }); - }); + IrArray::Index tile_origin = + mapping_scheme->GetElementIndexForTileOrigin(tile_index); + emit_one_tile(tile_origin, output_tile_bounds, block_contains_multi_tiles); }; - ksl->IfReturnVoid( - "full_tile", - builder->CreateAnd( - builder->CreateICmpEQ(index_typed_constant(tile_size), tile_width), - builder->CreateICmpEQ(index_typed_constant(tile_size), tile_height)), - emit_full_tile, emit_last_row); + + const IrArray::Index starting_block = + mapping_scheme->EmitBlockIndex(index_ty); + const IrArray::Index starting_tile_for_dim_z = + mapping_scheme->GetTileIndexForBlockOrigin(starting_block); + + // Emit the three dimensional block of tiles. + emit_tiles_for_block_dim( + "block_dim_z", starting_tile_for_dim_z, KernelMappingScheme::DimZ, + [&](const IrArray::Index& starting_tile_for_dim_y) { + emit_tiles_for_block_dim( + "block_dim_y", starting_tile_for_dim_y, KernelMappingScheme::DimY, + [&](const IrArray::Index& starting_tile_for_dim_x) { + emit_tiles_for_block_dim("block_dim_x", starting_tile_for_dim_x, + KernelMappingScheme::DimX, + emit_one_tile_for_tile_index); + }); + }); } -} // namespace -// Emits a kernel for the given hlo instruction using a tiled 0-2-1 transpose -// algorithm to improve the memory access patterns for the input parameters -// which have a shape that is a 0-2-1 transpose of the output tensors. -// -// For the purpose of tiling, the output tensors have a logical shape of three -// components 0-2-1 while the relevant input parameters have a logical shape of -// three components 0-1-2 in the order major to minor. The x- and y- dimensions -// of the tensors are tiled in square tiles of edge length `kTileSize`. Each -// thread block of `kTileSize` x `kNumRows` threads transposes one tile: each -// thread copies kTileSize/kNumRows elements from the input to a shared memory -// tile, then the otherwise "regular hlo kernel" reads from the shared memory -// instead of the original input. -// -// This is similar to the following CUDA algorithm in TensorFlow: -// https://goo.gl/MStRV6. -// -// `kTileSize` should usually be same as warp size. We currently choose 32 for -// `kTileSize` and 4 for `kNumRows`. The CUDA algorithm uses 8 for `kNumRows`. +// Emits a kernel for the hlo instruction using the given kernel mapping scheme. // -// TODO(b/33320379): Here each block transposes 1 tile. It may be more efficient -// to launch fewer blocks so each transposes many tiles. -LaunchDimensions IrEmitterUnnested::EmitHlo021Tile( - HloInstruction* hlo, absl::Span reduced_output_dims, - absl::Span tiled_param_ids) { - // Parameters for the tiling algorithm. - constexpr int64 kTileSize = 32; - constexpr int64 kNumRows = 4; - constexpr int64 kThreadsPerTile = kTileSize * kNumRows; - - // Construct IrArrays for the inputs and outputs. - std::vector output_arrays = ConstructIrArrayForOutputs(*hlo); - int64 num_outputs = output_arrays.size(); - std::vector param_arrays = ConstructIrArrayForInputs(*hlo); +// unnested_hlo: The unnested hlo instruction for which the kernel is generated. +// Currently, these hlo instructions are supported: kLoop fusion, kCopy. +// tiled_param_ids: The IDs for the parameters that are 0-2-1 transpose of +// other tensors with the same dimensions and need to be tiled and tranposed. +// mapping_scheme: The tiling scheme to use. +// kernel_generator: Contains function objects for code generation, such as +// element generator, block prologue and epilogue generators. +// kernel_info: Represent other information to support the code generation +// of the tiled kernel for the hlo. +LaunchDimensions IrEmitterUnnested::EmitKernel( + HloInstruction* unnested_hlo, absl::Span tiled_param_ids, + const KernelCodeGenerator& kernel_generator, + KernelCodegenInfo* kernel_info) { + KernelMappingScheme* mapping_scheme = kernel_info->GetKernelMappingScheme(); + + std::vector param_arrays = ConstructIrArrayForInputs(*unnested_hlo); int64 num_params = param_arrays.size(); - // Allocate shared memory buffers to store the tiled inputs. std::vector param_shmem_buffers(num_params, nullptr); for (int64 id : tiled_param_ids) { - const HloInstruction* param = hlo->operand(id); - // Add 1 to the minor dimension to reduce shared memory bank conflicts. - llvm::Type* tile_type = llvm::ArrayType::get( - llvm::ArrayType::get(llvm_ir::PrimitiveTypeToIrType( - param->shape().element_type(), module_), - kTileSize + 1), - kTileSize); - auto* tile_base_ptr = llvm_ir::AllocateSharedMemoryTile( - b_.GetInsertBlock()->getParent()->getParent(), tile_type, - IrName(hlo, StrCat("tile", id))); - param_shmem_buffers[id] = tile_base_ptr; + const HloInstruction* param = unnested_hlo->operand(id); + param_shmem_buffers[id] = + mapping_scheme->GetSharedMemoryBufferForElementType( + llvm_ir::PrimitiveTypeToIrType(param->shape().element_type(), + module_), + IrName(unnested_hlo, StrCat("tile", id))); VLOG(3) << "Added shmem buffer for parameter " << id << ": " - << llvm_ir::DumpToString(*tile_base_ptr); - } - - // The 0-2-1 shape of the tiling scheme is the reduced shape of the HLO result - // for the purpose of tiling. Calculate the logical output dimensions in the - // tile from the reduced output dimensions. - std::vector output_dims_in_tiles = std::vector( - reduced_output_dims.begin(), reduced_output_dims.end()); - CHECK_EQ(output_dims_in_tiles.size(), 3); - for (int i = 1; i < 3; ++i) { - output_dims_in_tiles[i] = - CeilOfRatio(output_dims_in_tiles[i], kTileSize); + << llvm_ir::DumpToString(*param_shmem_buffers[id]); } - const int64 num_tiles = - absl::c_accumulate(output_dims_in_tiles, 1, std::multiplies()); - LaunchDimensions launch_dimensions(num_tiles, kThreadsPerTile); - llvm::Type* index_ty = - GetIndexTypeForKernel(hlo, launch_dimensions.launch_bound(), &b_); + LaunchDimensions launch_dimensions = LaunchDimensions( + mapping_scheme->GetNumberOfBlocks(), mapping_scheme->GetThreadsPerTile()); + llvm::Type* index_ty = GetIndexTypeForKernel( + unnested_hlo, launch_dimensions.launch_bound(), &b_); auto index_typed_constant = [&](uint64 c) -> llvm::Constant* { return llvm::ConstantInt::get(index_ty, c); }; - // Cast each output IrArray to its corresponding reduced shape and keep the - // reduced shape live during IR emission. - std::vector output_in_reduced_shape_arrays; - std::vector output_reduced_shapes; - CHECK_EQ(ConstructOutputReducedShapeAndCastOutputIrArrayToShape( - *hlo, output_arrays, reduced_output_dims, &output_reduced_shapes, - &output_in_reduced_shape_arrays), - num_outputs); - // For each tiled parameter, cast its input IrArray to the corresponding // reduced shape and keep the reduced shape live during IR emission. std::vector param_in_reduced_shape_arrays; std::vector param_reduced_shapes; - CHECK_EQ(ConstructInputReducedShapeAndCastInputIrArrayToShape( - *hlo, param_arrays, param_shmem_buffers, reduced_output_dims, - ¶m_reduced_shapes, ¶m_in_reduced_shape_arrays), - num_params); + absl::Span reduced_dims = + mapping_scheme->GetDimensionsInElements(); + int num_shapes = ConstructInputReducedShapeAndCastInputIrArrayToShape( + *unnested_hlo, param_arrays, param_shmem_buffers, reduced_dims, + ¶m_reduced_shapes, ¶m_in_reduced_shape_arrays); + DCHECK_EQ(num_shapes, num_params); // Calculate the starting element coordinate within a tile for the current // thread, (y, x) from thread_id. llvm::Value* x; llvm::Value* y; - std::tie(y, x) = CalculateYXCoordinateWithinTile( - &b_, index_typed_constant(kTileSize), kThreadsPerTile); - - // Calculate the index for the current output tile from block_id. - const IrArray::Index output_tile_index( - GetBlockIdx(&b_, index_ty, num_tiles), - ShapeUtil::MakeShapeWithDescendingLayout(PRED /*arbitrary*/, - output_dims_in_tiles), - &b_); - - // Output tile origin is the index for the first element of the current output - // tile. - const IrArray::Index output_tile_origin = [&] { - IrArray::Index index = output_tile_index; - for (int i = 1; i < 3; ++i) { - index[i] = Mul(output_tile_index[i], index_typed_constant(kTileSize), - "tile_origin." + std::to_string(i)); - } - return index; - }(); - - // Calculate the input tile origin from the output tile origin. - const IrArray::Index input_tile_origin( - Permute({0, 2, 1}, output_tile_origin.multidim())); + std::tie(y, x) = mapping_scheme->EmitThreadYXCoordinate(index_ty); - // Calculate the current output tile bounds in each of the logical dimensions. - std::vector output_tile_bounds(3); - for (int i = 1; i < 3; ++i) { - // Only last row or column may not have full size. - output_tile_bounds[i] = - Select(ICmpEQ(output_tile_index[i], - index_typed_constant(output_dims_in_tiles[i] - 1)), - index_typed_constant(reduced_output_dims[i] - - (output_dims_in_tiles[i] - 1) * kTileSize), - index_typed_constant(kTileSize), "kTileSize"); - } + kernel_info->SetLaneId( + mapping_scheme->GetNumberOfThreadsForDimensionX() == kWarpSize ? x + : nullptr); + kernel_info->SetIndexType(index_ty); KernelSupportLibrary ksl(&b_, llvm_ir::UnrollMode::kDefaultUnroll); - // Curry a few parameters to EmitTiledElementalCodeWithBoundsCheck. auto emit_tiled_elemental_code_with_bounds_check = [&](const IrArray::Index& index, const string& loop_name, - llvm::Value* tile_width, llvm::Value* tile_height, - const std::function& - emit_elem_function) { - EmitTiledElementalCodeWithBoundsCheck( - kTileSize, kNumRows, index, loop_name, &ksl, &b_, y, x, tile_width, - tile_height, emit_elem_function); + llvm::Value* tile_height, llvm::Value* tile_width, + const std::function& emit_elem_function) { + EmitTiledElementalCodeWithBoundsCheck(mapping_scheme, index, loop_name, + &ksl, &b_, y, x, tile_height, + tile_width, emit_elem_function); }; - // Adds `addend` to the given `dim` of `index`. - auto offset_dim = [&](IrArray::Index index, llvm::Value* addend, int64 dim) { - index[dim] = Add(index[dim], addend); - return index; - }; - const IrArray::Index input_index = - offset_dim(offset_dim(input_tile_origin, x, /*dim=*/2), y, /*dim=*/1); - - // Copy input parameter values to shared memory buffers: - // tile[y, x] = input[index] - emit_tiled_elemental_code_with_bounds_check( - input_index, "input", output_tile_bounds[1], output_tile_bounds[2], - [&](const IrArray::Index& index, llvm::Value* y_loc) { - for (int64 id : tiled_param_ids) { - IrArray& input_in_logical_shape = param_in_reduced_shape_arrays[id]; - llvm::Value* shmem_buffer = param_shmem_buffers[id]; - // TODO(jlebar): Add AA metadata to this store. Tile buffers are - // global variables, so LLVM can't infer much about it. - Store(input_in_logical_shape.EmitReadArrayElement(index, &b_, - "input_element"), - GEP(shmem_buffer, {index_typed_constant(0), y_loc, x})); - } - }); + auto emit_one_tile = [&](const IrArray::Index& output_tile_origin, + absl::Span output_tile_bounds, + bool block_contains_multi_tiles) { + // Calculate the input tile origin from the output tile origin. + const IrArray::Index input_tile_origin( + Permute({0, 2, 1}, output_tile_origin.multidim())); + + const IrArray::Index input_index = + input_tile_origin.AddOffsetToDim(x, KernelMappingScheme::DimX, &b_) + .AddOffsetToDim(y, KernelMappingScheme::DimY, &b_); + + // If shared memory transpose is needed, wait for all threads to reach this + // point, lest we copy a value from tile to output before the other thread + // copies it from input to tile. This is `__syncthreads` in CUDA. + if (!tiled_param_ids.empty()) { + // Copy input parameter values to shared memory buffers: + // tile[y, x] = input[index] + // Note that tile_width and tile_height are flipped here because we are + // reading a transposed tile. + emit_tiled_elemental_code_with_bounds_check( + input_index, "input", output_tile_bounds[2], output_tile_bounds[1], + [&](const IrArray::Index& index, llvm::Value* y_loc, + llvm::Value* x_loc) { + for (int64 id : tiled_param_ids) { + IrArray& input_in_logical_shape = + param_in_reduced_shape_arrays[id]; + llvm::Value* shmem_buffer = param_shmem_buffers[id]; + // TODO(jlebar): Add AA metadata to this store. Tile buffers are + // global variables, so LLVM can't infer much about it. + Store(input_in_logical_shape.EmitReadArrayElement( + index, &b_, "input_element"), + GEP(shmem_buffer, {index_typed_constant(0), y_loc, x_loc})); + } + }); - // Wait for all threads to reach this point, lest we copy a value from tile to - // output before the other thread copies it from input to tile. - // This is `__syncthreads` in CUDA. - llvm_ir::EmitCallToIntrinsic(llvm::Intrinsic::nvvm_barrier0, {}, {}, &b_); + // Wait for all threads to reach this point using `__syncthreads` in CUDA. + llvm_ir::EmitCallToIntrinsic(llvm::Intrinsic::nvvm_barrier0, {}, {}, &b_); + } - llvm_ir::TiledParameterInfo tiled_param_info(param_shmem_buffers, y, x); + llvm_ir::TiledParameterInfo tiled_param_info(param_shmem_buffers, y, x); + kernel_info->SetTiledParamInfo(&tiled_param_info); - const IrArray::Index output_index = - offset_dim(offset_dim(output_tile_origin, x, /*dim=*/2), y, /*dim=*/1); + const IrArray::Index output_index = + output_tile_origin.AddOffsetToDim(x, KernelMappingScheme::DimX, &b_) + .AddOffsetToDim(y, KernelMappingScheme::DimY, &b_); - // Write to output[index] by emitting code like normal, except that values for - // the tiled parameters are read from the shmem buffers. - if (hlo->opcode() == HloOpcode::kCopy) { + // Write to output[index] by emitting code like normal, except that values + // for the tiled parameters are read from the shmem buffers. emit_tiled_elemental_code_with_bounds_check( - output_index, "output", output_tile_bounds[2], output_tile_bounds[1], - [&](const IrArray::Index& index, llvm::Value* y_loc) { - // TODO(jlebar): Add AA metadata to this load. - llvm::Instruction* load_from_shmem_buffer = - Load(GEP(param_shmem_buffers[0], {b_.getInt64(0), x, y_loc}), - "output_element"); - output_in_reduced_shape_arrays[0].EmitWriteArrayElement( - index, load_from_shmem_buffer, &b_); - }); - } else { - CHECK_EQ(hlo->opcode(), HloOpcode::kFusion); - emit_tiled_elemental_code_with_bounds_check( - output_index, "output", output_tile_bounds[2], output_tile_bounds[1], - [&](const IrArray::Index& index, llvm::Value* y_loc) { - GpuElementalIrEmitter elem_emitter(hlo_module_config_, module_, &b_, - GetNestedComputer()); - FusedIrEmitter fused_emitter(GetGeneratorForOperandIrArrays(hlo), - &elem_emitter); - tiled_param_info.set_y(y_loc); - fused_emitter.SetTiledParameterInfo(&tiled_param_info); - TF_CHECK_OK(hlo->fused_expression_root()->Accept(&fused_emitter)); - IrArray::Index untiled_index = llvm_ir::GetUnreducedOutputIndex( - index, output_reduced_shapes[0], output_arrays[0].GetShape(), - &b_); - const llvm_ir::ElementGenerator& output_generator = - fused_emitter.GetRootGenerator(); - llvm::Value* output_value = - output_generator(untiled_index).ValueOrDie(); - if (hlo->IsMultiOutputFusion()) { - CHECK(output_value->getType()->isStructTy()); - CHECK_EQ(output_value->getType()->getStructNumElements(), - output_in_reduced_shape_arrays.size()); - for (int64 i = 0; i < output_in_reduced_shape_arrays.size(); ++i) { - output_in_reduced_shape_arrays[i].EmitWriteArrayElement( - index, ExtractValue(output_value, i), &b_); - } - } else { - output_in_reduced_shape_arrays[0].EmitWriteArrayElement( - index, output_value, &b_); - } + output_index, "output", output_tile_bounds[1], output_tile_bounds[2], + [&](const IrArray::Index& index, llvm::Value* y_loc, + llvm::Value* x_loc) { + kernel_generator.GetTileElementGenerator()(unnested_hlo, index, + kernel_info, y_loc, x_loc); }); + + // If a tile block contains multiple tiles and shared memory buffers are + // used, we need to wait for all threads to finish using the shared memory + // buffer for the current tile before we move on to process the next tile + // and overwrite the shared memory buffers. + if (block_contains_multi_tiles && !tiled_param_ids.empty()) { + llvm_ir::EmitCallToIntrinsic(llvm::Intrinsic::nvvm_barrier0, {}, {}, &b_); + } + }; + + const BlockPrologueGenerator& block_prologue_generator = + kernel_generator.GetBlockPrologueGenerator(); + if (block_prologue_generator) { + block_prologue_generator(unnested_hlo, kernel_info); } - // For multioutput fusion, emit a tuple with all the individual outputs. - if (hlo->IsMultiOutputFusion()) { - llvm_ir::EmitTuple(GetIrArray(*hlo, *hlo), output_arrays, &b_, module_); + EmitBlock(std::move(emit_one_tile), kernel_info, ksl, index_ty); + + const BlockEpilogueGenerator& block_epilogue_generator = + kernel_generator.GetBlockEpilogueGenerator(); + if (block_epilogue_generator) { + block_epilogue_generator(unnested_hlo, kernel_info); + } + + // For multioutput fusion, emit a tuple with pointers to all the individual + // outputs. + if (unnested_hlo->IsMultiOutputFusion()) { + std::vector output_arrays = + ConstructIrArrayForOutputs(*unnested_hlo); + llvm_ir::EmitTuple(GetIrArray(*unnested_hlo, *unnested_hlo), output_arrays, + &b_, module_); } return launch_dimensions; } +// Emits a kernel for the given hlo instruction using a tiled 0-2-1 transpose +// algorithm to improve the memory access patterns for the input parameters +// with a shape that is a 0-2-1 transpose of the output tensor shape. +// +// For the purpose of tiling, the output tensors have a logical shape of three +// components 0-2-1 while the relevant input parameters have a logical shape +// of three components 0-1-2 in the order major to minor. The x- and y- +// dimensions of the tensors are tiled in square tiles with an edge length +// `kTileSize`. Each thread block of `kTileSize` x `kNumRows` threads +// transposes one tile: each thread copies kTileSize/kNumRows elements from +// the input to a shared memory tile, then the otherwise "regular HLO kernel" +// reads from the shared memory instead of the original input. +// +// This is similar to the following CUDA algorithm in TensorFlow: +// https://goo.gl/MStRV6. +// +// `kTileSize` should usually be same as warp size. We currently choose 32 for +// `kTileSize` and 4 for `kNumRows`. The CUDA algorithm uses 8 for `kNumRows`. +// +// TODO(b/33320379): Here each block transposes 1 tile. It may be more +// efficient to launch fewer blocks so each transposes many tiles. +LaunchDimensions IrEmitterUnnested::EmitHlo021Tile( + HloInstruction* hlo, absl::Span reduced_output_dims, + absl::Span tiled_param_ids) { + constexpr int kNumRows = 4; + KernelMappingScheme mapping_scheme( + reduced_output_dims, /*tile_size_y=*/kWarpSize, + /*tile_size_x=*/kWarpSize, /*req_block_sizes=*/{1, 1, 1}, + /*num_threads_y=*/kNumRows, + /*num_threads_x=*/kWarpSize, &b_); + TileElementGenerator element_generator; + if (hlo->opcode() == HloOpcode::kCopy) { + element_generator = [&](HloInstruction* hlo, + const llvm_ir::IrArray::Index& index, + const KernelCodegenInfo* kernel_info, + llvm::Value* y_loc, llvm::Value* x_loc) { + EmitTileElementForCopy(hlo, index, kernel_info, y_loc, x_loc); + }; + } else { + DCHECK_EQ(hlo->opcode(), HloOpcode::kFusion); + element_generator = [&](HloInstruction* hlo, + const llvm_ir::IrArray::Index& index, + const KernelCodegenInfo* kernel_info, + llvm::Value* y_loc, llvm::Value* x_loc) { + EmitTileElementForFusion(hlo, index, kernel_info, y_loc, x_loc); + }; + } + KernelCodegenInfo kernel_info(&mapping_scheme); + KernelCodeGenerator kernel_generator(std::move(element_generator)); + return EmitKernel(hlo, tiled_param_ids, kernel_generator, &kernel_info); +} + namespace { // Returns true to indicate it is safe to use the tile based shared memory // transpose implementation to implement the kernel for the instruction. @@ -3562,8 +3083,8 @@ bool IrEmitterUnnested::CheckAndEmitHloWithTile021(HloInstruction* hlo) { ? ShapeUtil::GetSubshape(hlo->shape(), {0}) : hlo->shape(); - // If the output_shape is reduced to 021 shape, find all the parameters of the - // hlo that are in the corresponding 012 shape. + // If the output_shape is reduced to 021 shape, find all the parameters of + // the HLO that are in the corresponding 012 shape. std::vector params_012; optional> reduced_dims_021; for (int64 operand_idx = 0; operand_idx < hlo->operand_count(); @@ -3600,9 +3121,9 @@ bool IrEmitterUnnested::CheckAndEmitHloWithTile021(HloInstruction* hlo) { } // Each of our shared memory tiles has 32*33 elements (so ~4kb, if the - // elements are of size 4 bytes), and CUDA has an architectural limit of 48kb - // shared memory per SM. (This is increased to 96kb in Volta, but we don't - // use this, in part because it eats into our L1 cache space.) + // elements are of size 4 bytes), and CUDA has an architectural limit of + // 48kb shared memory per SM. (This is increased to 96kb in Volta, but we + // don't use this, in part because it eats into our L1 cache space.) // // For correctness we need to ensure that we don't make more than 48kb worth // of shmem tiles per block. And for performance, we'd probably like to use @@ -3610,9 +3131,9 @@ bool IrEmitterUnnested::CheckAndEmitHloWithTile021(HloInstruction* hlo) { // gpu core. // // We say without benchmarks that we want at least 3 threads/block, - // corresponding to 3 shmem tiles if the elements are 32 bits wide. We choose - // which params get the shmem transpose treatment arbitrarily; it's not clear - // if there's a Right Choice. + // corresponding to 3 shmem tiles if the elements are 32 bits wide. We + // choose which params get the shmem transpose treatment arbitrarily; it's + // not clear if there's a Right Choice. // // This is only sound if tiled transposes are the only place where we use // shared memory in fusions. If in the future other fusible ops use shared @@ -3645,6 +3166,246 @@ bool IrEmitterUnnested::CheckAndEmitHloWithTile021(HloInstruction* hlo) { return true; } +namespace { +// Checks that the outputs of a fusion with reduction are consistent. +Status AreFusedReductionOutputsConsistent( + absl::Span output_instructions, + const HloInstruction* first_reduce) { + for (const HloInstruction* inst : output_instructions) { + if (inst->opcode() == HloOpcode::kReduce) { + // Shapes, layouts and dimensions must be the same for all reduces + // inside of this fusion. + TF_RET_CHECK(ShapeUtil::Equal(first_reduce->shape(), inst->shape())); + TF_RET_CHECK(ShapeUtil::Equal(first_reduce->operand(0)->shape(), + inst->operand(0)->shape())); + TF_RET_CHECK(ShapeUtil::Equal(first_reduce->operand(1)->shape(), + inst->operand(1)->shape())); + TF_RET_CHECK(first_reduce->dimensions() == inst->dimensions()); + } else { + // For extra outputs we can relax shape equality to allow different + // types (with the same number of elements). Layouts still have to + // match. + TF_RET_CHECK(ShapeUtil::CompatibleIgnoringElementType( + first_reduce->operand(0)->shape(), inst->shape())); + TF_RET_CHECK(LayoutUtil::Equal(first_reduce->operand(0)->shape().layout(), + inst->shape().layout())); + } + } + return Status::OK(); +} + +// Finds the dimensions to keep for the reduction, sorts and returns the +// dimensions from minor to major. +DimensionVector GetDimensionsToKeepMinorToMajor( + const Shape& input_shape, absl::Span dims_to_reduce) { + DimensionVector input_dims(ShapeUtil::Rank(input_shape), 0); + absl::c_iota(input_dims, 0); + DimensionVector input_dims_to_keep; + for (int input_dim : input_dims) { + auto it = absl::c_find_if(dims_to_reduce, [&](int64 dim_to_reduce) { + return dim_to_reduce == input_dim; + }); + if (it == dims_to_reduce.end()) { + input_dims_to_keep.push_back(input_dim); + } + } + + // Sort the dimensions to keep from minor to major. + absl::c_sort(input_dims_to_keep, [&input_shape](int64 dim_a, int64 dim_b) { + return PositionInContainer(LayoutUtil::MinorToMajor(input_shape), dim_a) < + PositionInContainer(LayoutUtil::MinorToMajor(input_shape), dim_b); + }); + + VLOG(10) << "dims to keep minor to major" + << absl::StrJoin(input_dims_to_keep, ","); + return input_dims_to_keep; +} + +// Given the input shape and dimensions to reduce for the reduction to vector, +// returns : +// num_kept: the number of elements in the contiguous dimensions to keep. +// num_reduced_major: the number of elements in the dimensions to reduce that +// are more major than the dimensions to keep. +// num_reduced_minor: the number of elements in the dimensions to reduce that +// are more minor than the dimensions to kept. +std::tuple GetReductionToVectorDimensions( + const Shape& input_shape, absl::Span dims_to_reduce) { + DimensionVector input_dims_to_keep_minor_to_major = + GetDimensionsToKeepMinorToMajor(input_shape, dims_to_reduce); + CHECK(LayoutUtil::AreDimensionsConsecutive( + input_shape.layout(), input_dims_to_keep_minor_to_major)); + int num_reduced_major = 1, num_kept = 1, num_reduced_minor = 1; + if (input_dims_to_keep_minor_to_major.empty()) { + return std::make_tuple(num_reduced_major, num_kept, num_reduced_minor); + } + DimensionVector input_dims(ShapeUtil::Rank(input_shape), 0); + absl::c_iota(input_dims, 0); + absl::Span minor_to_major = + LayoutUtil::MinorToMajor(input_shape); + for (int input_dim : input_dims) { + int64 curr_dim_size = input_shape.dimensions(input_dim); + if (PositionInContainer(minor_to_major, input_dim) > + PositionInContainer(minor_to_major, + input_dims_to_keep_minor_to_major.back())) { + num_reduced_major *= curr_dim_size; + } else if (PositionInContainer(minor_to_major, input_dim) < + PositionInContainer(minor_to_major, + input_dims_to_keep_minor_to_major.front())) { + num_reduced_minor *= curr_dim_size; + } else { + num_kept *= curr_dim_size; + } + } + + return std::make_tuple(num_reduced_major, num_kept, num_reduced_minor); +} + +std::tuple ComputeMappingSchemeAndReductionKind( + const HloInstruction* first_reduce, llvm::IRBuilder<>* b) { + int64 depth = 1; + int64 height = 1; + int64 width = 1; + bool is_row_reduction = true; + int64 tile_size_x = 1; + int64 tile_size_y = 1; + int64 block_size_y = 1; + int64 block_size_z = 1; + int64 num_threads_x = 1; + int64 num_threads_y = 1; + const Shape& input_shape = first_reduce->operand(0)->shape(); + int64 num_input_elems = ShapeUtil::ElementsIn(input_shape); + int64 num_output_elems = ShapeUtil::ElementsIn(first_reduce->shape()); + int64 num_reduced_major, num_kept, num_reduced_minor; + std::tie(num_reduced_major, num_kept, num_reduced_minor) = + GetReductionToVectorDimensions(input_shape, first_reduce->dimensions()); + CHECK_EQ(num_output_elems, num_kept); + + if (num_kept == 1) { + // Scalar reduction is a special row reduction with depth = height = 1. + width = num_input_elems; + tile_size_x = kWarpSize * 16; + num_threads_x = kWarpSize; + } else if (num_reduced_minor == 1) { + // Column reduction reduces inputs with dimension [height, width], where + // width is the minor dimension, to dimension [width]. + height = num_reduced_major; + width = num_kept; + is_row_reduction = false; + tile_size_x = std::min(kWarpSize, num_kept); + // The old Column reduction algorithm uses kTileHeight = 128. We choose + // tile_size_y * block_size_y = 128 to match the value of kTileHeight. Using + // a non-trivial block_size_y here is a way to avoid unrolling all the 128 + // iterations. + tile_size_y = 32; + block_size_y = 4; + num_threads_x = tile_size_x; + } else { + // Row reduction reduces inputs with dimension [depth, height, width], + // where width is the most minor dimension, to dimension [height] . + depth = num_reduced_major; + height = num_kept; + width = num_reduced_minor; + num_threads_x = kWarpSize; + if (width % (kWarpSize * 64) == 0) { + tile_size_x = kWarpSize * 64; + } else { + tile_size_x = kWarpSize * 8; + block_size_z = 8; + while (depth % block_size_z != 0) { + block_size_z -= 1; + } + } + } + DCHECK_EQ(depth * height * width, num_input_elems); + VLOG(10) << "is_row_reduction " << is_row_reduction << depth << " " << height + << " " << width; + + DimensionVector dims_in_elem{depth, height, width}; + DimensionVector req_block_sizes{block_size_z, block_size_y, 1}; + llvm_ir::KernelMappingScheme mapping_scheme(dims_in_elem, tile_size_y, + tile_size_x, req_block_sizes, + num_threads_y, num_threads_x, b); + return std::make_tuple(mapping_scheme, is_row_reduction); +} + +} // namespace + +Status IrEmitterUnnested::EmitReductionToVector(HloInstruction* unnested_hlo) { + VLOG(10) << "Emitting reduction to vector " << unnested_hlo->ToString(); + + HloInstruction* reduce_or_tuple = unnested_hlo->opcode() == HloOpcode::kFusion + ? unnested_hlo->fused_expression_root() + : unnested_hlo; + absl::Span output_instructions = + GetOutputInstructions(&reduce_or_tuple); + const HloInstruction* first_reduce = + GetFirstReduceInstruction(output_instructions); + + if (output_instructions.size() > 1) { + TF_RETURN_IF_ERROR( + AreFusedReductionOutputsConsistent(output_instructions, first_reduce)); + } + + // Build an initializer thunk to initialize each reduction output. + std::vector> thunks; + for (int i = 0, e = output_instructions.size(); i != e; ++i) { + if (output_instructions[i]->opcode() != HloOpcode::kReduce) { + continue; + } + TF_ASSIGN_OR_RETURN( + std::unique_ptr initializer_thunk, + BuildInitializerThunk(unnested_hlo, + (output_instructions[i] == reduce_or_tuple) + ? ShapeIndex() + : ShapeIndex({i}))); + thunks.push_back(std::move(initializer_thunk)); + } + + // Build a kernel thunk to compute all the outputs. + std::unique_ptr kernel_thunk = + BuildKernelThunk(unnested_hlo, /*implements_whole_instruction=*/false); + + const Shape& input_shape = first_reduce->operand(0)->shape(); + // The layout of a reduction input is either set by LayoutAssignment for + // unnested kReduce or by InstructionFusion for fused kReduce. + CHECK(input_shape.has_layout()) << "LayoutAssignment or InstructionFusion " + "doesn't set the input layout of " + << first_reduce->ToString(); + + bool is_row_reduction; + llvm_ir::KernelMappingScheme mapping_scheme; + std::tie(mapping_scheme, is_row_reduction) = + ComputeMappingSchemeAndReductionKind(first_reduce, &b_); + ReductionCodegenInfo reduction_info(&mapping_scheme, is_row_reduction); + KernelCodeGenerator kernel_generator( + /*tile_element_generator=*/ + [&](HloInstruction* hlo, const llvm_ir::IrArray::Index& index, + const KernelCodegenInfo* kernel_info, llvm::Value* y_loc, + llvm::Value* x_loc) { + EmitTileElementForReduction(hlo, index, kernel_info, y_loc, x_loc); + }, + /*block_prologue_generator=*/ + [&](HloInstruction* hlo, KernelCodegenInfo* kernel_info) { + EmitPrologueForReduction(hlo, kernel_info); + }, + /*block_epilogue_generator*/ + [&](HloInstruction* hlo, KernelCodegenInfo* kernel_info) { + EmitEpilogueForReduction(hlo, kernel_info); + }); + + LaunchDimensions launch_dimensions = + EmitKernel(unnested_hlo, {}, kernel_generator, &reduction_info); + UpdateLaunchDimensions(launch_dimensions, kernel_thunk.get(), + ir_emitter_context_->llvm_module()); + + thunks.push_back(std::move(kernel_thunk)); + std::unique_ptr sequential_thunk = + absl::make_unique(std::move(thunks), unnested_hlo); + AddThunkToThunkSequence(std::move(sequential_thunk)); + + return Status::OK(); +} + Status IrEmitterUnnested::EmitConstantGlobals() { for (const BufferAllocation& allocation : ir_emitter_context_->buffer_assignment().Allocations()) { @@ -3666,10 +3427,10 @@ Status IrEmitterUnnested::EmitConstantGlobals() { } // These globals will be looked up by name by GpuExecutable so we need to - // give them an external linkage. Not all of their uses are visible in the - // LLVM IR (e.g. TupleThunk) so we can't give then a linkage that merely - // preserves their names (like available_externally), we also need to ensure - // that they stick around even if they're "unused". + // give them an external linkage. Not all of their uses are visible in + // the LLVM IR (e.g. TupleThunk) so we can't give then a linkage that + // merely preserves their names (like available_externally), we also need + // to ensure that they stick around even if they're "unused". // // We may have to be more more clever here in the future if we notice that // we're keeping around too many globals because of their linkage. diff --git a/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.h b/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.h index 334c0b3c20..85a0e5328c 100644 --- a/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.h +++ b/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.h @@ -16,9 +16,11 @@ limitations under the License. #ifndef TENSORFLOW_COMPILER_XLA_SERVICE_GPU_IR_EMITTER_UNNESTED_H_ #define TENSORFLOW_COMPILER_XLA_SERVICE_GPU_IR_EMITTER_UNNESTED_H_ +#include "absl/container/inlined_vector.h" #include "tensorflow/compiler/xla/service/gpu/ir_emitter.h" #include "tensorflow/compiler/xla/service/gpu/sequential_thunk.h" #include "tensorflow/compiler/xla/service/gpu/thunk.h" +#include "tensorflow/compiler/xla/service/llvm_ir/kernel_support_library.h" #include "tensorflow/compiler/xla/service/llvm_ir/kernel_tiling.h" namespace xla { @@ -47,6 +49,99 @@ namespace gpu { // class IrEmitterUnnested : public IrEmitter { public: + // Parameter block_contains_multi_tiles indicates whether a tile block + // consists of multiple tiles or not. If the tile block contains only one + // tile, there is no need to use atomic operation to accumulate a local result + // to a global result to implement reduction. + using TileGenerator = + std::function output_tile_bounds, + bool block_contains_multi_tiles)>; + // KernelCodegenInfo records the common information to support the code + // generation for a kernel to process tensor elements by blocks. A block of + // tensor elements may contain one or multiple tiles. The code generators that + // generate code for tile elements or block prologue/epilogue refer to this + // class in their prototypes. If the implementations of such code generators + // require other information that are specific to the HLO instructions, the + // implementations need to define and use derived classes of this class. + class KernelCodegenInfo { + public: + explicit KernelCodegenInfo(llvm_ir::KernelMappingScheme* mapping_scheme) + : mapping_scheme_(mapping_scheme), + tiled_param_info_(nullptr), + lane_id_(nullptr), + index_ty_(nullptr) {} + virtual ~KernelCodegenInfo() {} + + void SetLaneId(llvm::Value* v) { lane_id_ = v; } + void SetIndexType(llvm::Type* t) { index_ty_ = t; } + void SetTiledParamInfo(llvm_ir::TiledParameterInfo* tiled_param_info) { + CHECK_EQ(tiled_param_info_, nullptr); + tiled_param_info_ = tiled_param_info; + } + + llvm::Value* GetLaneId() const { return lane_id_; } + llvm_ir::KernelMappingScheme* GetKernelMappingScheme() const { + return mapping_scheme_; + } + llvm_ir::TiledParameterInfo* GetTiledParameterInfo() const { + return tiled_param_info_; + } + llvm::Type* GetIndexType() const { return index_ty_; } + + private: + llvm_ir::KernelMappingScheme* mapping_scheme_; + llvm_ir::TiledParameterInfo* tiled_param_info_; + llvm::Value* lane_id_; + llvm::Type* index_ty_; + }; + + // A function object to prepare for the code generation for a tile block. + using BlockPrologueGenerator = + std::function; + // A function object to finalize the code generation for a tile block. + using BlockEpilogueGenerator = + std::function; + // A function object to generate code to process one element in a tile. + // + // hlo: the instruction for which the code is generated for. + // index: the index for the first output element of the current thread. + // y_loc: The y coordinate within a tile. + // x_loc: The x coordinate within a tile. + // kernel_info: Other information to support the kernel code generation. + using TileElementGenerator = std::function; + + // KernelCodeGenerator records the code generator objects that generate code + // for tile elements or tile block prologue/epilogue. + class KernelCodeGenerator { + public: + explicit KernelCodeGenerator( + TileElementGenerator tile_element_generator, + BlockPrologueGenerator block_prologue_generator = {}, + BlockEpilogueGenerator block_epilogue_generator = {}) + : tile_element_generator_(std::move(tile_element_generator)), + block_prologue_generator_(std::move(block_prologue_generator)), + block_epilogue_generator_(std::move(block_epilogue_generator)) {} + + const TileElementGenerator& GetTileElementGenerator() const { + return tile_element_generator_; + } + const BlockPrologueGenerator& GetBlockPrologueGenerator() const { + return block_prologue_generator_; + } + const BlockEpilogueGenerator& GetBlockEpilogueGenerator() const { + return block_epilogue_generator_; + } + + private: + TileElementGenerator tile_element_generator_; + BlockPrologueGenerator block_prologue_generator_; + BlockEpilogueGenerator block_epilogue_generator_; + }; + IrEmitterUnnested(const HloModuleConfig& hlo_module_config, const HloComputation* hlo_computation, IrEmitterContext* ir_emitter_context); @@ -82,7 +177,7 @@ class IrEmitterUnnested : public IrEmitter { Status HandleSort(HloInstruction* sort) override; Status HandleTupleSelect(HloInstruction* tuple_select) override; Status HandleCrossReplicaSum(HloInstruction* crs) override; - Status HandleAfterAll(HloInstruction* gen_token) override; + Status HandleAfterAll(HloInstruction* after_all) override; Status EmitTargetElementLoop( const HloInstruction& hlo, @@ -111,82 +206,14 @@ class IrEmitterUnnested : public IrEmitter { // Helper for writing extra outputs from inside a reduce kernel. Status EmitExtraOutputsForReduce( - const HloInstruction* reduce, const llvm_ir::IrArray::Index& index, - absl::Span> - extra_output_gens); - - // EmitColumnReduction and EmitRowReduction emit code for column and row - // reduction of a matrix and/or 3D tensor. Row and column reduction have - // different memory access pattern, so for performance their implementations - // are significantly different. - // - // Emits code that reduces a matrix of shape [height x width] to a vector of - // [width]. Other parameters have the same meaning as those of - // `EmitReductionToVector`. Note that input shape might not be - // [height x width], but can be bitcast to [height x width] with "height" - // being the major dimension. - Status EmitColumnReduction( - KernelThunk* kernel_thunk, int64 height, int64 width, - HloInstruction* reduce, const Shape& input_shape, - absl::Span input_gens, - absl::Span init_value_gens, - absl::Span reducers, - absl::Span reduce_output_shapes, - absl::Span> - extra_output_gens); - - // Emits code that reduces a 3D tensor of shape [depth x height x width] to a - // vector of shape [height]. Other parameters have the same meaning as those - // of `EmitReductionToVector`. Note that input shape might not be - // [depth x height x width], but can be bitcast to [depth x height x width] - // with "depth" being the most major dimension. - Status EmitRowReduction( - KernelThunk* kernel_thunk, int64 depth, int64 height, int64 width, - HloInstruction* reduce, const Shape& input_shape, - absl::Span input_gens, - absl::Span init_value_gens, - absl::Span reducers, - absl::Span reduce_output_shapes, + const HloInstruction* unnested_hlo, const llvm_ir::IrArray::Index& index, absl::Span> extra_output_gens); - // Emits code that reduces a tensor of arbitrary rank to a scalar. - Status EmitReductionToScalar( - KernelThunk* kernel_thunk, HloInstruction* reduce, - const Shape& input_shape, - absl::Span input_gens, - absl::Span init_value_gens, - absl::Span reducers, - absl::Span reduce_output_shapes, - absl::Span> - extra_output_gens); - - // Figures out whether `reduce` is a row or column reduction, and which - // dimensions to reduce, and calls either `EmitRowReduction` or - // `EmitColumnReduction` as appropriate. `input_shape` is the shape of the - // input array, which is the operand of the Reduce instruction if unfused or - // of the Fusion instruction if fused. `input_gen` and `init_value_gen` - // generate elements of the input and the initial value. Other parameters mean - // the same as for `HandleReduce`. - // - // Multiple reduces can be emitted in the same loop, assuming they have the - // same input and output shapes, and the same reduce dimensions. - // - // extra_output_gens can contain extra generators for intermediate outputs. - // These must have the same shape as the reduce input as they are computed - // when the reduce inputs are being read. + // Generates code for reduction to contiguous dimensions. // - // Prerequisite: `IsReductionToVector(*reduce)` - Status EmitReductionToVector( - KernelThunk* kernel_thunk, HloInstruction* reduce, - const Shape& input_shape, - absl::Span input_gens, - absl::Span init_value_gens, - absl::Span dimensions_to_reduce, - absl::Span reducers, - absl::Span reduce_output_shapes, - absl::Span> - extra_output_gens); + // Prerequisite: `IsReductionToVector(*unnested_hlo)` + Status EmitReductionToVector(HloInstruction* unnested_hlo); // Emits code for an in-place scatter, modifying `thunk`s launch dimensions in // the process. `scatter` may be fused, scatter indices are taken from @@ -205,22 +232,55 @@ class IrEmitterUnnested : public IrEmitter { LaunchDimensions EmitHlo021Tile(HloInstruction* hlo, absl::Span reduced_output_dims, absl::Span tiled_param_ids); + // Emits a kernel for an unnested HLO instruction. + LaunchDimensions EmitKernel(HloInstruction* unnested_hlo, + absl::Span param_ids, + const KernelCodeGenerator& kernel_generator, + KernelCodegenInfo* kernel_info); + void EmitBlock(const TileGenerator& emit_one_tile, + const KernelCodegenInfo* kernel_info, + KernelSupportLibrary& ksl, llvm::Type* index_ty); + // Emits code to process a tensor element in a tile for the given kCopy HLO + // that performs a 0-2-1 transpose. + void EmitTileElementForCopy(HloInstruction* hlo, + const llvm_ir::IrArray::Index& index, + const KernelCodegenInfo* kernel_info, + llvm::Value* y_loc, llvm::Value* x_loc); + // Emits code to process a tensor element in a tile for the given kLoop fusion + // HLO containing parameters that are 0-2-1 transpose of its outputs. + void EmitTileElementForFusion(HloInstruction* hlo, + const llvm_ir::IrArray::Index& index, + const KernelCodegenInfo* kernel_info, + llvm::Value* y_loc, llvm::Value* x_loc); + // Emits code to process a tensor element in a tile for the given input hlo + // that is either a unnested kReduce or a kInput fusion. + void EmitTileElementForReduction(HloInstruction* unnested_hlo, + const llvm_ir::IrArray::Index& index, + const KernelCodegenInfo* kernel_info, + llvm::Value* y_loc, llvm::Value* x_loc); + // Prepares for the code generation for a tile block of a reduction kernel. + void EmitPrologueForReduction(HloInstruction* unnested_hlo, + KernelCodegenInfo* kernel_info); + void EmitPrologueForOneReduction(HloInstruction* unnested_hlo, + HloInstruction* reduce_inst, int reduce_idx, + KernelCodegenInfo* kernel_info, + GpuElementalIrEmitter* elemental_emitter, + ShapeIndex output_shape_index); + // Wraps up the code generation for a tile block of a reduction kernel. + void EmitEpilogueForReduction(HloInstruction* unnested_hlo, + KernelCodegenInfo* kernel_info); + // For each reducer, emits the shuffle-down loop to accumulate the partial + // result to the global result. + void EmitFullWarpShuffleDownLoopForAllReduces( + const absl::InlinedVector& reducers, + const absl::InlinedVector& + partial_result_addresses); // Generates the IrArray for each input of an hlo and returns a vector that // constains such IrArrays. std::vector ConstructIrArrayForInputs( const HloInstruction& hlo); - // For each output of the `hlo` instruction, constructs the reduced shape for - // the output with the given `reduced_output_dims` and cast the original - // output IrArray element in `output_arrays` to the reduced shape. Returns - // the number of outputs. - int ConstructOutputReducedShapeAndCastOutputIrArrayToShape( - const HloInstruction& hlo, - const std::vector& output_arrays, - absl::Span reduced_output_dims, - std::vector* output_reduced_shapes, - std::vector* output_in_reduced_shape_arrays); // For each input of the `hlo` instruction, checks its value in // `param_buffers` to find out whether the input has a reduced shape. If the // input has a reduced shape, constructs the reduced shape for the input and diff --git a/tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/nvptx_backend_lib.cc b/tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/nvptx_backend_lib.cc index 8751e3a9c2..24f07e6897 100644 --- a/tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/nvptx_backend_lib.cc +++ b/tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/nvptx_backend_lib.cc @@ -177,13 +177,6 @@ std::unique_ptr GetTargetMachine( } TargetOptions target_options = InitTargetOptionsFromCodeGenFlags(); - llvm_ir::SetTargetOptions( - /*fast_math_enabled=*/hlo_module_config.debug_options() - .xla_gpu_enable_fast_math(), - &target_options); - - // Enable FMA synthesis. - target_options.AllowFPOpFusion = FPOpFusion::Fast; // Set the verbose assembly options. target_options.MCOptions.AsmVerbose = false; @@ -453,18 +446,21 @@ void GPUBackendInit(const HloModuleConfig& hlo_module_config) { // * 3-6 gives similar results as 2; // * >6 start hurting the performance of at least dot product kernels. // - // TODO(jingyue): The current threshold only considers the numbr of IR + // TODO(jingyue): The current threshold only considers the number of IR // instructions which do not accurately reflect the true cost. We need a // better cost model. FeedLLVMWithFlags({"-bonus-inst-threshold=2"}); - // TODO(b/22073864): Increase limit when scan memory dependency. - // This helps to reduce more redundant load instructions. + // Increase limit when scanning memory dependencies. This helps to reduce + // more redundant load instructions. // // The specific value is currently large enough for s3d in shoc benchmark, // which contains a lot of load instructions and many arithmetic instructions // between those loads. FeedLLVMWithFlags({"-memdep-block-scan-limit=500"}); + // Use div.approx -- it matters for some float-division heavy benchmarks. + FeedLLVMWithFlags({"-nvptx-prec-divf32=0"}); + llvm_ir::InitializeLLVMCommandLineOptions(hlo_module_config); // Initialize the NVPTX target; it's the only target we link with, so call its diff --git a/tensorflow/compiler/xla/service/gpu/multi_output_fusion.cc b/tensorflow/compiler/xla/service/gpu/multi_output_fusion.cc index d9b06828e2..01fddcede6 100644 --- a/tensorflow/compiler/xla/service/gpu/multi_output_fusion.cc +++ b/tensorflow/compiler/xla/service/gpu/multi_output_fusion.cc @@ -41,50 +41,7 @@ GpuMultiOutputFusion::GpuMultiOutputFusion() : MultiOutputFusion(INT64_MAX) {} bool GpuMultiOutputFusion::ShapesCompatibleForFusion(HloInstruction* instr1, HloInstruction* instr2) { - auto get_element_instr = - [&](const HloInstruction* instr) -> const HloInstruction* { - const HloInstruction* element_instr = instr; - if (instr->opcode() == HloOpcode::kFusion) { - auto fused_expression_root = instr->fused_expression_root(); - if (instr->IsMultiOutputFusion()) { - // If possible, we want to pick a reduce operand of the fusion root, - // because it has the most constraints. - for (const auto* inst : fused_expression_root->operands()) { - if (IsReductionToVector(*inst)) { - return inst; - } - } - return fused_expression_root->operands()[0]; - } else { - element_instr = fused_expression_root; - } - } - return element_instr; - }; - - auto get_element_shape = [&](const HloInstruction* element_instr) { - // Special handling of kReduce instructions -- the fusion - // applies to the first operand. - if (IsReductionToVector(*element_instr)) { - return element_instr->operand(0)->shape(); - } - return element_instr->shape(); - }; - - // The shapes in all tuple operands should agree, unless it is a reduce. - // In that case, the operand of the reduce needs to have the same shape - // as the other tuple operands, but also we need to compare the output - // shapes of the reduces. - auto* element_instr_1 = get_element_instr(instr1); - auto* element_instr_2 = get_element_instr(instr2); - if (element_instr_1->opcode() == HloOpcode::kReduce && - element_instr_2->opcode() == HloOpcode::kReduce && - !ShapeUtil::Equal(element_instr_1->shape(), element_instr_2->shape())) { - return false; - } - // The elementwise output shapes must be the same (including layout). - return ShapeUtil::EqualIgnoringFpPrecision( - get_element_shape(element_instr_1), get_element_shape(element_instr_2)); + return ShapesCompatibleForMultiOutputFusion(*instr1, *instr2); } bool GpuMultiOutputFusion::IsFusible(HloInstruction* instr) { @@ -205,7 +162,7 @@ bool GpuMultiOutputFusion::DoProducerConsumerMultiOutputFusion() { VLOG(3) << producer->name() << " is not a loop fusion."; continue; } - if (!ShapesCompatibleForFusion(producer, consumer)) { + if (!ShapesCompatibleForMultiOutputFusion(*producer, *consumer)) { VLOG(3) << producer->name() << " has an incompatible shape."; continue; } diff --git a/tensorflow/compiler/xla/service/gpu/multi_output_fusion_test.cc b/tensorflow/compiler/xla/service/gpu/multi_output_fusion_test.cc index dc221f22a7..d16c87ba5c 100644 --- a/tensorflow/compiler/xla/service/gpu/multi_output_fusion_test.cc +++ b/tensorflow/compiler/xla/service/gpu/multi_output_fusion_test.cc @@ -580,7 +580,7 @@ TEST_F(MultiOutputFusionTest, AvoidsLargeFusion) { // ... // where each of the (pi * pj)'s is represented as a fusion node so that // multi-output fusion will pay attention to it. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation::Builder b(TestName()); Shape shape = ShapeUtil::MakeShape(F32, {10, 100}); diff --git a/tensorflow/compiler/xla/service/gpu/nvptx_compiler.cc b/tensorflow/compiler/xla/service/gpu/nvptx_compiler.cc index de04ed85c3..e934cbda17 100644 --- a/tensorflow/compiler/xla/service/gpu/nvptx_compiler.cc +++ b/tensorflow/compiler/xla/service/gpu/nvptx_compiler.cc @@ -67,6 +67,7 @@ limitations under the License. #include "tensorflow/compiler/xla/service/hlo_cse.h" #include "tensorflow/compiler/xla/service/hlo_dce.h" #include "tensorflow/compiler/xla/service/hlo_element_type_converter.h" +#include "tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.h" #include "tensorflow/compiler/xla/service/hlo_instruction.h" #include "tensorflow/compiler/xla/service/hlo_pass_fix.h" #include "tensorflow/compiler/xla/service/hlo_pass_pipeline.h" @@ -173,13 +174,16 @@ Status OptimizeHloModule(HloModule* hlo_module, se::StreamExecutor* stream_exec, /*rewrite_inference_op=*/true, /*rewrite_grad_op=*/true); + pipeline.AddPass(); + // BatchNormExpander can create zero-sized ops, so zero-sized HLO // elimination has to come after that pass. pipeline.AddPass(); - pass.AddPass( - /*is_layout_sensitive=*/false, + AlgebraicSimplifierOptions options( [](const Shape&, const Shape&) { return false; }); + options.set_enable_permutation_sort_replacement(true); + pass.AddPass(options); pass.AddPass(); pass.AddPass(); pass.AddPass(); @@ -248,11 +252,13 @@ Status OptimizeHloModule(HloModule* hlo_module, se::StreamExecutor* stream_exec, // The LayoutAssignment pass may leave behind kCopy instructions which are // duplicate or NOPs, so remove them with algebraic simplification and CSE. - pipeline.AddPass>( - /*is_layout_sensitive=*/true, + AlgebraicSimplifierOptions options( /*valid_bitcast_callback=*/[](const Shape&, const Shape&) { return true; }); + options.set_is_layout_sensitive(true); + options.set_enable_permutation_sort_replacement(true); + pipeline.AddPass>(options); // Choose the fastest algorithm for each conv. // @@ -810,7 +816,7 @@ std::vector NVPTXCompiler::CompilePtxOrGetCachedResult(const string& ptx, // binaries are not available. We don't want to spam logs with // identical warnings in this case. - // TODO(zhengxq): we should implement a LOG_FIRST_N and LOG_EVERY_N + // TODO(jlebar): we should implement a LOG_FIRST_N and LOG_EVERY_N // for more general usage. static std::atomic warning_done(false); log_warning = !warning_done.exchange(true); diff --git a/tensorflow/compiler/xla/service/gpu/stream_assignment_test.cc b/tensorflow/compiler/xla/service/gpu/stream_assignment_test.cc index f2ef11e1e6..31a5d7a8c0 100644 --- a/tensorflow/compiler/xla/service/gpu/stream_assignment_test.cc +++ b/tensorflow/compiler/xla/service/gpu/stream_assignment_test.cc @@ -30,7 +30,7 @@ namespace gpu { class StreamAssignmentTest : public HloTestBase { protected: - std::unique_ptr CreateNewUnverifiedModule() { + std::unique_ptr CreateNewVerifiedModule() { HloModuleConfig config; auto debug_options = GetDebugOptionsForTest(); debug_options.set_xla_gpu_disable_multi_streaming(false); @@ -55,7 +55,7 @@ TEST_F(StreamAssignmentTest, SequentialMatMul) { HloInstruction* dot2 = builder.AddInstruction(CreateCanonicalDot(f32_2x2_, dot1, z)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build(dot2)); std::unique_ptr assignment = AssignStreams(*module); @@ -76,7 +76,7 @@ TEST_F(StreamAssignmentTest, ConcurrentMatMul) { HloInstruction* add = builder.AddInstruction( HloInstruction::CreateBinary(f32_2x2_, HloOpcode::kAdd, dot1, dot2)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build(add)); std::unique_ptr assignment = AssignStreams(*module); @@ -120,7 +120,7 @@ TEST_F(StreamAssignmentTest, LatticeMatMul) { HloInstruction* d40 = builder.AddInstruction(CreateCanonicalDot(f32_2x2_, d30, d31)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build(d40)); std::unique_ptr assignment = AssignStreams(*module); diff --git a/tensorflow/compiler/xla/service/gpu/tests/gpu_codegen_test.h b/tensorflow/compiler/xla/service/gpu/tests/gpu_codegen_test.h index d2f30ae7bc..d917320e36 100644 --- a/tensorflow/compiler/xla/service/gpu/tests/gpu_codegen_test.h +++ b/tensorflow/compiler/xla/service/gpu/tests/gpu_codegen_test.h @@ -26,7 +26,7 @@ namespace gpu { // Tests that verify IR or PTX emitted by the GPU backend is as expected. class GpuCodegenTest : public LlvmIrGenTestBase { protected: - // Like HloTestBase::CreateNewUnverifiedModule(), with a flag for configuring + // Like HloTestBase::CreateNewVerifiedModule(), with a flag for configuring // the ftz option. std::unique_ptr CreateNewUnverifiedModuleWithFTZ(bool ftz); diff --git a/tensorflow/compiler/xla/service/gpu/tests/gpu_copy_test.cc b/tensorflow/compiler/xla/service/gpu/tests/gpu_copy_test.cc index 268b48a1ca..a1ed849904 100644 --- a/tensorflow/compiler/xla/service/gpu/tests/gpu_copy_test.cc +++ b/tensorflow/compiler/xla/service/gpu/tests/gpu_copy_test.cc @@ -46,7 +46,7 @@ TEST_F(GpuCopyTest, UseMemcpy) { std::unique_ptr computation = builder.Build(); - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); hlo_module->AddEntryComputation(std::move(computation)); // There should not be any kernel prefixed "copy". diff --git a/tensorflow/compiler/xla/service/gpu/tests/gpu_ftz_test.cc b/tensorflow/compiler/xla/service/gpu/tests/gpu_ftz_test.cc index d0ccd8619b..5e524faab1 100644 --- a/tensorflow/compiler/xla/service/gpu/tests/gpu_ftz_test.cc +++ b/tensorflow/compiler/xla/service/gpu/tests/gpu_ftz_test.cc @@ -75,16 +75,16 @@ class GpuFtzDisabledTest : public GpuFtzTest { // Check that we emit mul.ftz.f32 when in ftz mode, and plain mul.f32 otherwise. TEST_F(GpuFtzEnabledTest, MultiplyFtz) { CompileAndVerifyPtx(CreateBinaryOpModule(HloOpcode::kMultiply), R"( - CHECK-NOT: mul.f32 - CHECK: mul.ftz.f32 - CHECK-NOT: mul.f32 + CHECK-NOT: mul.rn.f32 + CHECK: mul.rn.ftz.f32 + CHECK-NOT: mul.rn.f32 )"); } TEST_F(GpuFtzDisabledTest, MultiplyFtz) { CompileAndVerifyPtx(CreateBinaryOpModule(HloOpcode::kMultiply), R"( - CHECK-NOT: mul.ftz.f32 - CHECK: mul.f32 - CHECK-NOT: mul.ftz.f32 + CHECK-NOT: mul.rn.ftz.f32 + CHECK: mul.rn.f32 + CHECK-NOT: mul.rn.ftz.f32 )"); } diff --git a/tensorflow/compiler/xla/service/gpu/tests/gpu_index_test.cc b/tensorflow/compiler/xla/service/gpu/tests/gpu_index_test.cc index da8e513a2c..6814be779e 100644 --- a/tensorflow/compiler/xla/service/gpu/tests/gpu_index_test.cc +++ b/tensorflow/compiler/xla/service/gpu/tests/gpu_index_test.cc @@ -51,7 +51,7 @@ TEST_F(GpuIndexTest, CompatibleUseLinearIndex) { builder.AddInstruction(HloInstruction::CreateBinary( ShapeUtil::MakeShape(PRED, {5, 7, 2}), HloOpcode::kGe, param_x, param_y)); - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); hlo_module->AddEntryComputation(builder.Build()); // Check the optimized IR as the unoptimized IR contains dead udiv and urem. diff --git a/tensorflow/compiler/xla/service/gpu/tests/gpu_ldg_test.cc b/tensorflow/compiler/xla/service/gpu/tests/gpu_ldg_test.cc index ea1fee040d..3019215c01 100644 --- a/tensorflow/compiler/xla/service/gpu/tests/gpu_ldg_test.cc +++ b/tensorflow/compiler/xla/service/gpu/tests/gpu_ldg_test.cc @@ -48,7 +48,7 @@ TEST_F(GpuLdgTest, LdgForParamRead) { HloInstruction::CreateBinary(shape, HloOpcode::kAdd, param, param)); std::unique_ptr computation = builder.Build(); - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); hlo_module->AddEntryComputation(std::move(computation)); CompileAndVerifyPtx(std::move(hlo_module), R"( @@ -73,7 +73,7 @@ TEST_F(GpuLdgTest, LdgForNonParamRead) { builder.AddInstruction(HloInstruction::CreateTuple({add, square})); std::unique_ptr computation = builder.Build(); - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); hlo_module->AddEntryComputation(std::move(computation)); CompileAndVerifyPtx(std::move(hlo_module), R"( @@ -95,7 +95,7 @@ TEST_F(GpuLdgTest, LdgForNonParamRead) { // reduce in the foreseeable future. But if that turns out to be wrong, I give // you, future reader, permission to delete this test. TEST_F(GpuLdgTest, NoLdgWhenSharingBuffer) { - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); HloComputation::Builder builder(TestName()); HloComputation* reduce_computation; diff --git a/tensorflow/compiler/xla/service/gpu/tests/gpu_noalias_test.cc b/tensorflow/compiler/xla/service/gpu/tests/gpu_noalias_test.cc index 14285459b5..ca0a78034d 100644 --- a/tensorflow/compiler/xla/service/gpu/tests/gpu_noalias_test.cc +++ b/tensorflow/compiler/xla/service/gpu/tests/gpu_noalias_test.cc @@ -47,7 +47,7 @@ TEST_F(GpuNoAliasTest, Concat) { std::unique_ptr computation = builder.Build(); - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); hlo_module->AddEntryComputation(std::move(computation)); CompileAndVerifyIr(std::move(hlo_module), diff --git a/tensorflow/compiler/xla/service/gpu/thunk_schedule.cc b/tensorflow/compiler/xla/service/gpu/thunk_schedule.cc index 141f321938..6b2d76764a 100644 --- a/tensorflow/compiler/xla/service/gpu/thunk_schedule.cc +++ b/tensorflow/compiler/xla/service/gpu/thunk_schedule.cc @@ -45,7 +45,7 @@ void ThunkSchedule::AddDependenciesOnTransitiveOperands( ThunkSchedule::ThunkSchedule( std::unique_ptr thunks, std::unique_ptr stream_assignment, - const std::vector& hlo_total_order) + const std::vector& hlo_total_order) : thunks_(std::move(thunks)), stream_assignment_(std::move(stream_assignment)) { std::unordered_map hlo_to_thunk; @@ -53,7 +53,7 @@ ThunkSchedule::ThunkSchedule( InsertOrDie(&hlo_to_thunk, thunk->hlo_instruction(), thunk.get()); } - for (const HloInstruction* hlo : hlo_total_order) { + for (HloInstruction* hlo : hlo_total_order) { if (hlo_to_thunk.count(hlo)) { thunk_total_order_.push_back(FindOrDie(hlo_to_thunk, hlo)); } diff --git a/tensorflow/compiler/xla/service/gpu/thunk_schedule.h b/tensorflow/compiler/xla/service/gpu/thunk_schedule.h index d3352994f8..43b628a1ba 100644 --- a/tensorflow/compiler/xla/service/gpu/thunk_schedule.h +++ b/tensorflow/compiler/xla/service/gpu/thunk_schedule.h @@ -46,7 +46,7 @@ class ThunkSchedule { public: ThunkSchedule(std::unique_ptr thunks, std::unique_ptr stream_assignment, - const std::vector& hlo_total_order); + const std::vector& hlo_total_order); // Returns the total order of executing all the thunks. const std::vector& TotalOrder() const { return thunk_total_order_; } diff --git a/tensorflow/compiler/xla/service/gpu/while_transformer_test.cc b/tensorflow/compiler/xla/service/gpu/while_transformer_test.cc index c7f5112764..2dce7749bb 100644 --- a/tensorflow/compiler/xla/service/gpu/while_transformer_test.cc +++ b/tensorflow/compiler/xla/service/gpu/while_transformer_test.cc @@ -29,7 +29,7 @@ namespace { class WhileTransformerTest : public HloTestBase { protected: WhileTransformerTest() - : module_(CreateNewUnverifiedModule()), + : module_(CreateNewVerifiedModule()), induction_variable_shape_(ShapeUtil::MakeShape(S32, {})), data_shape_(ShapeUtil::MakeShape(F32, {8})), condition_result_shape_(ShapeUtil::MakeShape(PRED, {})) {} diff --git a/tensorflow/compiler/xla/service/heap_simulator_test.cc b/tensorflow/compiler/xla/service/heap_simulator_test.cc index fad3215fc8..dc40b9446a 100644 --- a/tensorflow/compiler/xla/service/heap_simulator_test.cc +++ b/tensorflow/compiler/xla/service/heap_simulator_test.cc @@ -258,7 +258,7 @@ class HeapSimulatorTracker { // Constructor for testing a single entry computation. HeapSimulatorTracker( const string& name, std::unique_ptr computation, - const std::vector& instruction_sequence) { + const std::vector& instruction_sequence) { HloModuleConfig config; module_ = absl::make_unique(name, config); module_->AddEntryComputation(std::move(computation)); @@ -286,7 +286,7 @@ class HeapSimulatorTracker { // Similar to the single entry computation constructor above, but runs the // simulation over the entire module. void RunWholeModule( - const std::vector& full_module_sequence) { + const std::vector& full_module_sequence) { points_to_analysis_ = TuplePointsToAnalysis::Run(module_.get()).ConsumeValueOrDie(); @@ -294,7 +294,7 @@ class HeapSimulatorTracker { HloSchedule schedule(module_.get()); absl::flat_hash_map reverse_position; for (int i = 0; i < full_module_sequence.size(); ++i) { - const HloInstruction* instruction = full_module_sequence[i]; + HloInstruction* instruction = full_module_sequence[i]; schedule.GetOrCreateSequence(instruction->parent()) .push_back(instruction); reverse_position[instruction] = full_module_sequence.size() - i; diff --git a/tensorflow/compiler/xla/service/hlo.proto b/tensorflow/compiler/xla/service/hlo.proto index dbab62f847..414c632712 100644 --- a/tensorflow/compiler/xla/service/hlo.proto +++ b/tensorflow/compiler/xla/service/hlo.proto @@ -51,7 +51,7 @@ message HloInstructionProto { string name = 1; string opcode = 2; - xla.Shape shape = 3; + xla.ShapeProto shape = 3; xla.OpMetadata metadata = 7; @@ -132,7 +132,7 @@ message HloInstructionProto { string custom_call_opaque = 53; // Shape of outfeed request. - xla.Shape outfeed_shape = 29; + xla.ShapeProto outfeed_shape = 29; // Describes the dimension numbers used for a dot operation xla.DotDimensionNumbers dot_dimension_numbers = 30; @@ -190,7 +190,7 @@ message HloInstructionProto { // 'operand_shapes_with_layout' must contain a shape with layout for each // operand. bool constrain_layout = 56; - repeated Shape operand_shapes_with_layout = 57; + repeated xla.ShapeProto operand_shapes_with_layout = 57; } // Serialization of HloComputation. @@ -205,7 +205,8 @@ message HloComputationProto { repeated HloInstructionProto instructions = 2; // The program shape (with layout) of this computation. - xla.ProgramShape program_shape = 4; + + xla.ProgramShapeProto program_shape = 4; // The id of this computation. int64 id = 5; @@ -251,6 +252,41 @@ message HloInputOutputAliasProto { repeated AliasEntryProto entries = 1; } +message DynamicParameterBindingProto { + // A list of bindings which indicates that the `target_dim_num` in + // the subshape `target_param_index` of parameter `target_param_num` + // is a dynamic dimension and its real dynamic size is represented + // by `dynamic_param_index` in parameter `dynamic_param_num`. + // + // As an example, imagine we have a program: + // + // ENTRY main { + // a = f32[] parameter(0) + // b = f32[10] parameter(1) + // ROOT root = (f32[], f32[10]) tuple(%a, %b) + // } + // + // Let's say 'b' (param index 1) is a dynamic shape whose input has + // an upperbound of 10 and real size is determined at runtime.'a' + // represents the real size of b's first dimension. + // + // In this case, the fields are set in the following way: + // dynamic_param_num = 1 + // dynamic_param_index = {} + // target_param_num = 0 + // target_param_index = {} + // target_param_dim = 0 + message Binding { + int64 dynamic_param_num = 1; + repeated int64 dynamic_param_index = 2; + int64 target_param_num = 3; + repeated int64 target_param_index = 4; + int64 target_param_dim_num = 5; + } + + repeated Binding entries = 1; +} + // Serialization of HloModule. message HloModuleProto { string name = 1; @@ -262,7 +298,7 @@ message HloModuleProto { repeated HloComputationProto computations = 3; // The host program shape (with layout) of the entry computation. - xla.ProgramShape host_program_shape = 4; + xla.ProgramShapeProto host_program_shape = 4; // The id of this module. int64 id = 5; @@ -272,6 +308,8 @@ message HloModuleProto { // Describes alias information between inputs and outputs. HloInputOutputAliasProto input_output_alias = 8; + + DynamicParameterBindingProto dynamic_parameter_binding = 9; } // Serialization of LogicalBuffer. diff --git a/tensorflow/compiler/xla/service/hlo_computation.cc b/tensorflow/compiler/xla/service/hlo_computation.cc index 0c20d207dd..ff122b529b 100644 --- a/tensorflow/compiler/xla/service/hlo_computation.cc +++ b/tensorflow/compiler/xla/service/hlo_computation.cc @@ -499,7 +499,7 @@ HloComputationProto HloComputation::ToProto() const { proto.add_instructions()->Swap(&instruction_proto); } proto.set_root_id(root_instruction()->unique_id()); - *proto.mutable_program_shape() = ComputeProgramShape(); + *proto.mutable_program_shape() = ComputeProgramShape().ToProto(); return proto; } @@ -711,6 +711,8 @@ bool HloComputation::operator==(const HloComputation& other) const { return eq(root_instruction(), other.root_instruction()); } +uint64 HloComputation::Hash() const { return root_instruction()->Hash(); } + Status HloComputation::ReplaceWithNewInstruction( HloInstruction* old_instruction, std::unique_ptr new_instruction) { @@ -795,7 +797,7 @@ Status HloComputation::AcceptWithOperandOrder( template Status HloComputation::AcceptOrdered( DfsHloVisitorBase* visitor, - const std::vector& order) const { + const std::vector& order) const { VLOG(3) << "Accepting visitor with order."; for (HloInstruction* root : CollectUnreachableRoots()) { TF_RET_CHECK(std::find(order.begin(), order.end(), root) != order.end()) @@ -825,9 +827,9 @@ Status HloComputation::AcceptOrdered( // Explicit instantiations. template Status HloComputation::AcceptOrdered( - DfsHloVisitor*, const std::vector&) const; + DfsHloVisitor*, const std::vector&) const; template Status HloComputation::AcceptOrdered( - ConstDfsHloVisitor*, const std::vector&) const; + ConstDfsHloVisitor*, const std::vector&) const; Status HloComputation::Accept( const std::function& visitor_func) { diff --git a/tensorflow/compiler/xla/service/hlo_computation.h b/tensorflow/compiler/xla/service/hlo_computation.h index fc7d2035e5..c584e4c7ca 100644 --- a/tensorflow/compiler/xla/service/hlo_computation.h +++ b/tensorflow/compiler/xla/service/hlo_computation.h @@ -264,6 +264,12 @@ class HloComputation { // Return whether `*this` and `other` are functionally equivalent. bool operator==(const HloComputation& other) const; + // Generates a hash value of an HLO computation. Hash considers + // information on opcode, shape, operands, and typically a root instruction. + // This function returns the same hash value for equivalent HLO computations, + // with respect to HloInstruction::Identical() method. + uint64 Hash() const; + // Replaces old instruction with newly created instruction. Removes old // instruction from computation. Updates uses and root instruction. Status ReplaceWithNewInstruction( @@ -301,7 +307,7 @@ class HloComputation { // be a topological sort of all instructions in the computation. template Status AcceptOrdered(DfsHloVisitorBase* visitor, - const std::vector& order) const; + const std::vector& order) const; // Same as Accept() above, but the visitor is given as a function. Status Accept(const std::function& visitor_func); diff --git a/tensorflow/compiler/xla/service/hlo_computation_test.cc b/tensorflow/compiler/xla/service/hlo_computation_test.cc index 1e7a6e197f..8b50cfa9ae 100644 --- a/tensorflow/compiler/xla/service/hlo_computation_test.cc +++ b/tensorflow/compiler/xla/service/hlo_computation_test.cc @@ -65,7 +65,7 @@ class HloComputationTest : public HloTestBase { }; TEST_F(HloComputationTest, GetEmbeddedComputationsEmpty) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto negate_computation = module->AddEntryComputation(CreateNegateComputation()); EXPECT_TRUE(negate_computation->MakeEmbeddedComputationsList().empty()); @@ -73,7 +73,7 @@ TEST_F(HloComputationTest, GetEmbeddedComputationsEmpty) { TEST_F(HloComputationTest, GetEmbeddedComputationsOneComputation) { // Create computation which calls one other computation. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto negate_computation = module->AddEmbeddedComputation(CreateNegateComputation()); auto map_computation = @@ -85,7 +85,7 @@ TEST_F(HloComputationTest, GetEmbeddedComputationsOneComputation) { TEST_F(HloComputationTest, GetEmbeddedComputationsDiamond) { // Create computations with a diamond-shaped callgraph. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto negate_computation = module->AddEmbeddedComputation(CreateNegateComputation()); auto map1_computation = @@ -119,7 +119,7 @@ TEST_F(HloComputationTest, PostOrderSingleton) { auto builder = HloComputation::Builder(TestName()); auto constant = builder.AddInstruction( HloInstruction::CreateConstant(LiteralUtil::CreateR0(42.0f))); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->MakeInstructionPostOrder(), ElementsAre(constant)); } @@ -134,7 +134,7 @@ TEST_F(HloComputationTest, PostOrderSimple) { HloInstruction::CreateUnary(r0f32_, HloOpcode::kNegate, constant)); auto negate2 = builder.AddInstruction( HloInstruction::CreateUnary(r0f32_, HloOpcode::kNegate, negate1)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->MakeInstructionPostOrder(), ElementsAre(constant, negate1, negate2)); @@ -170,7 +170,7 @@ TEST_F(HloComputationTest, PostOrderDisconnectedInstructions) { HloInstruction::CreateConstant(LiteralUtil::CreateR0(42.0f))); auto constant4 = builder.AddInstruction( HloInstruction::CreateConstant(LiteralUtil::CreateR0(42.0f))); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_THAT(computation->MakeInstructionPostOrder(), UnorderedElementsAre(constant1, constant2, constant3, constant4)); @@ -192,7 +192,7 @@ TEST_F(HloComputationTest, PostOrderWithMultipleRoots) { r0f32_, HloOpcode::kAdd, constant2, constant3)); auto add3 = builder.AddInstruction(HloInstruction::CreateBinary( r0f32_, HloOpcode::kAdd, constant1, constant3)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); auto post_order = computation->MakeInstructionPostOrder(); EXPECT_EQ(6, post_order.size()); @@ -217,7 +217,7 @@ TEST_F(HloComputationTest, VisitWithMultipleRoots) { constant2, constant3)); builder.AddInstruction(HloInstruction::CreateBinary(r0f32_, HloOpcode::kAdd, constant1, constant3)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Visitor which keeps track of which instructions have been visited. class TestVisitor : public DfsHloVisitorWithDefault { @@ -257,7 +257,7 @@ TEST_F(HloComputationTest, DeepCopyArray) { auto builder = HloComputation::Builder(TestName()); auto constant = builder.AddInstruction(HloInstruction::CreateConstant( LiteralUtil::CreateR1({1.0, 2.0, 3.0}))); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); auto copy = computation->DeepCopyInstruction(constant).ValueOrDie(); @@ -274,7 +274,7 @@ TEST_F(HloComputationTest, DeepCopyTuple) { auto tuple = builder.AddInstruction( HloInstruction::CreateTuple({constant1, constant2})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); auto tuple_copy = computation->DeepCopyInstruction(tuple).ValueOrDie(); @@ -376,7 +376,7 @@ TEST_F(HloComputationTest, DeepCopyToken) { // copied. auto builder = HloComputation::Builder(TestName()); auto token = builder.AddInstruction(HloInstruction::CreateToken()); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); auto copy = computation->DeepCopyInstruction(token).ValueOrDie(); @@ -393,7 +393,7 @@ TEST_F(HloComputationTest, DeepCopyTokenTuple) { HloInstruction::CreateConstant(LiteralUtil::CreateR0(42.0))); auto tuple = builder.AddInstruction(HloInstruction::CreateTuple({token, constant})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); auto copy = computation->DeepCopyInstruction(tuple).ValueOrDie(); @@ -440,7 +440,7 @@ TEST_F(HloComputationTest, RemoveInstructionWithDuplicateOperand) { r0f32_, HloOpcode::kAdd, dead_negate, dead_negate)); auto negate = builder.AddInstruction( HloInstruction::CreateUnary(r0f32_, HloOpcode::kNegate, constant)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_EQ(4, computation->instruction_count()); EXPECT_THAT(computation->root_instruction(), op::Negate(constant)); @@ -466,7 +466,7 @@ TEST_F(HloComputationTest, CloneWithControlDependency) { HloInstruction::CreateParameter(0, r0f32_, "param0")); auto negate = builder.AddInstruction( HloInstruction::CreateUnary(r0f32_, HloOpcode::kNegate, param)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build(/*root_instruction=*/add)); @@ -505,7 +505,7 @@ TEST_F(HloComputationTest, Stringification) { 2, PrecisionConfig::DEFAULT); builder.AddInstruction( HloInstruction::CreateDot(sout, x, reshape, dot_dnums, precision_config)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto* computation = module->AddEntryComputation(builder.Build()); auto options = HloPrintOptions().set_print_metadata(false); @@ -540,7 +540,7 @@ TEST_F(HloComputationTest, StringificationIndent) { 2, PrecisionConfig::DEFAULT); builder.AddInstruction( HloInstruction::CreateDot(sout, x, reshape, dot_dnums, precision_config)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto* computation = module->AddEntryComputation(builder.Build()); auto options = @@ -576,7 +576,7 @@ TEST_F(HloComputationTest, StringificationCanonical) { 2, PrecisionConfig::DEFAULT); builder.AddInstruction( HloInstruction::CreateDot(sout, x, reshape, dot_dnums, precision_config)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto* computation = module->AddEntryComputation(builder.Build()); auto options = HloPrintOptions().set_print_metadata(false); diff --git a/tensorflow/compiler/xla/service/hlo_constant_folding_test.cc b/tensorflow/compiler/xla/service/hlo_constant_folding_test.cc index d12f920722..4f81dc94e5 100644 --- a/tensorflow/compiler/xla/service/hlo_constant_folding_test.cc +++ b/tensorflow/compiler/xla/service/hlo_constant_folding_test.cc @@ -22,21 +22,22 @@ limitations under the License. #include "tensorflow/compiler/xla/literal.h" #include "tensorflow/compiler/xla/service/hlo_computation.h" #include "tensorflow/compiler/xla/service/hlo_instruction.h" -#include "tensorflow/compiler/xla/service/hlo_matchers.h" #include "tensorflow/compiler/xla/service/hlo_opcode.h" #include "tensorflow/compiler/xla/service/hlo_parser.h" #include "tensorflow/compiler/xla/service/hlo_pass_fix.h" +#include "tensorflow/compiler/xla/service/pattern_matcher.h" +#include "tensorflow/compiler/xla/service/pattern_matcher_gmock.h" #include "tensorflow/compiler/xla/shape_util.h" #include "tensorflow/compiler/xla/test.h" #include "tensorflow/compiler/xla/tests/hlo_test_base.h" #include "tensorflow/compiler/xla/tests/literal_test_util.h" #include "tensorflow/compiler/xla/types.h" -namespace op = xla::testing::opcode_matchers; - namespace xla { namespace { +namespace m = xla::match; + using HloConstantFoldingTest = HloTestBase; TEST_F(HloConstantFoldingTest, ConvertF32ToS64) { @@ -49,13 +50,14 @@ TEST_F(HloConstantFoldingTest, ConvertF32ToS64) { auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Convert(input)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Convert().WithOperand(0, m::Op().Is(input)))); HloConstantFolding const_folder; TF_ASSERT_OK_AND_ASSIGN(bool result, const_folder.Run(module.get())); EXPECT_TRUE(result); - EXPECT_THAT(computation->root_instruction(), op::Constant()); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Constant())); EXPECT_EQ(computation->root_instruction()->literal().GetFirstElement(), 42); } @@ -70,13 +72,14 @@ TEST_F(HloConstantFoldingTest, ConvertS64ToF32) { auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Convert(input)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Convert().WithOperand(0, m::Op().Is(input)))); HloConstantFolding const_folder; TF_ASSERT_OK_AND_ASSIGN(bool result, const_folder.Run(module.get())); EXPECT_TRUE(result); - EXPECT_THAT(computation->root_instruction(), op::Constant()); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Constant())); EXPECT_EQ(computation->root_instruction()->literal().GetFirstElement(), 42.0f); } @@ -91,13 +94,14 @@ TEST_F(HloConstantFoldingTest, ConvertF32ArrayToS64Array) { auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); - EXPECT_THAT(computation->root_instruction(), op::Convert(input)); + EXPECT_THAT(computation->root_instruction(), + GmockMatch(m::Convert().WithOperand(0, m::Op().Is(input)))); HloConstantFolding const_folder; TF_ASSERT_OK_AND_ASSIGN(bool result, const_folder.Run(module.get())); EXPECT_TRUE(result); - EXPECT_THAT(computation->root_instruction(), op::Constant()); + EXPECT_THAT(computation->root_instruction(), GmockMatch(m::Constant())); EXPECT_EQ(computation->root_instruction()->literal().Get({0}), 42); EXPECT_EQ(computation->root_instruction()->literal().Get({1}), 19); } @@ -138,7 +142,7 @@ TEST_F(HloConstantFoldingTest, Concatenate) { EXPECT_TRUE(result); HloInstruction* root = computation->root_instruction(); - EXPECT_THAT(root, op::Constant()); + EXPECT_THAT(root, GmockMatch(m::Constant())); EXPECT_TRUE(ShapeUtil::Equal(root->shape(), shape)); } } @@ -165,7 +169,7 @@ TEST_F(HloConstantFoldingTest, Slice) { EXPECT_TRUE(result); HloInstruction* root = computation->root_instruction(); - EXPECT_THAT(root, op::Constant()); + EXPECT_THAT(root, GmockMatch(m::Constant())); EXPECT_TRUE(ShapeUtil::Equal(root->shape(), shape)); } @@ -190,7 +194,7 @@ TEST_F(HloConstantFoldingTest, TransposeConstantFold) { EXPECT_TRUE(result); HloInstruction* root = computation->root_instruction(); - EXPECT_THAT(root, op::Constant()); + EXPECT_THAT(root, GmockMatch(m::Constant())); EXPECT_TRUE(ShapeUtil::Compatible(root->shape(), shape)); using NativeT = typename primitive_util::PrimitiveTypeToNative::type; @@ -240,7 +244,8 @@ TEST_F(HloConstantFoldingTest, ConstantFoldReduceNoLayout) { TF_ASSERT_OK_AND_ASSIGN(bool result, const_folder.Run(m.get())); EXPECT_FALSE(result); - EXPECT_THAT(m->entry_computation()->root_instruction(), op::Reduce()); + EXPECT_THAT(m->entry_computation()->root_instruction(), + GmockMatch(m::Reduce())); } const char* const kConstantFoldLargePad = R"( @@ -260,7 +265,7 @@ TEST_F(HloConstantFoldingTest, DoesNotFoldLargePad) { EXPECT_FALSE(result); EXPECT_THAT(module->entry_computation()->root_instruction(), - op::Pad(op::Constant(), op::Constant())); + GmockMatch(m::Pad(m::Constant(), m::Constant()))); } } // namespace diff --git a/tensorflow/compiler/xla/service/hlo_cost_analysis.cc b/tensorflow/compiler/xla/service/hlo_cost_analysis.cc index fdfb38b858..df7d3826db 100644 --- a/tensorflow/compiler/xla/service/hlo_cost_analysis.cc +++ b/tensorflow/compiler/xla/service/hlo_cost_analysis.cc @@ -419,6 +419,21 @@ Status HloCostAnalysis::HandleTranspose(const HloInstruction*) { } Status HloCostAnalysis::HandleAfterAll(const HloInstruction*) { + // This instruction is used to enforce ordering at compile time. No code is + // emitted. + current_should_compute_bottleneck_time_ = false; + current_properties_[kBytesAccessedKey] = 0; + current_properties_[kOptimalSecondsKey] = 0; + return Status::OK(); +} + +Status HloCostAnalysis::HandleAddDependency( + const HloInstruction* add_dependency) { + // This instruction is used to enforce ordering at compile time. No code is + // emitted. + current_should_compute_bottleneck_time_ = false; + current_properties_[kBytesAccessedKey] = 0; + current_properties_[kOptimalSecondsKey] = 0; return Status::OK(); } diff --git a/tensorflow/compiler/xla/service/hlo_cost_analysis.h b/tensorflow/compiler/xla/service/hlo_cost_analysis.h index 8ced9d776e..33983119c9 100644 --- a/tensorflow/compiler/xla/service/hlo_cost_analysis.h +++ b/tensorflow/compiler/xla/service/hlo_cost_analysis.h @@ -101,6 +101,7 @@ class HloCostAnalysis : public ConstDfsHloVisitor { Status HandleBroadcast(const HloInstruction* broadcast) override; Status HandlePad(const HloInstruction* pad) override; Status HandleReshape(const HloInstruction* reshape) override; + Status HandleAddDependency(const HloInstruction* add_dependency) override; Status HandleAfterAll(const HloInstruction* token) override; Status HandleTranspose(const HloInstruction* transpose) override; Status HandleWhile(const HloInstruction* xla_while) override; diff --git a/tensorflow/compiler/xla/service/hlo_cost_analysis_test.cc b/tensorflow/compiler/xla/service/hlo_cost_analysis_test.cc index 6a15b3440c..ff32faf298 100644 --- a/tensorflow/compiler/xla/service/hlo_cost_analysis_test.cc +++ b/tensorflow/compiler/xla/service/hlo_cost_analysis_test.cc @@ -387,7 +387,7 @@ TEST_F(FusionCostAnalysis, LoopFusion) { HloInstruction::CreateBinary(r2f32, HloOpcode::kSubtract, mul, clamp)); auto tuple = HloInstruction::CreateTuple({sub, sub, mul, c1}); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto* computation = module->AddEntryComputation(builder.Build()); auto* fusion = computation->CreateFusionInstruction( {sub, mul, exp, clamp, add}, HloInstruction::FusionKind::kLoop); @@ -429,7 +429,7 @@ TEST_F(FusionCostAnalysis, NoLayout) { auto add = builder.AddInstruction(HloInstruction::CreateBinary( shape_with_layout, HloOpcode::kAdd, c1, broadcast)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto* computation = module->AddEntryComputation(builder.Build()); auto* fusion = computation->CreateFusionInstruction( {add, broadcast}, HloInstruction::FusionKind::kLoop); @@ -472,7 +472,7 @@ TEST_F(DomainCostAnalysis, DomainCost) { auto domain = builder.AddInstruction( HloInstruction::CreateDomain(tuple->shape(), tuple, nullptr, nullptr)); - auto hlo_module = CreateNewUnverifiedModule(); + auto hlo_module = CreateNewVerifiedModule(); hlo_module->AddEntryComputation(builder.Build()); EXPECT_EQ(hlo_module->entry_computation()->root_instruction(), domain); diff --git a/tensorflow/compiler/xla/service/hlo_dataflow_analysis.cc b/tensorflow/compiler/xla/service/hlo_dataflow_analysis.cc index 5dcf6bc985..3ed3d3c11c 100644 --- a/tensorflow/compiler/xla/service/hlo_dataflow_analysis.cc +++ b/tensorflow/compiler/xla/service/hlo_dataflow_analysis.cc @@ -466,6 +466,21 @@ bool HloDataflowAnalysis::UpdateDomainValueSet(HloInstruction* domain) { return changed; } +bool HloDataflowAnalysis::UpdateAddDependencyValueSet( + HloInstruction* add_dependency) { + // AddDependency just forwards the value of its zero-th operand. + CHECK_EQ(add_dependency->opcode(), HloOpcode::kAddDependency); + const InstructionValueSet& operand_set = + GetInstructionValueSet(add_dependency->operand(0)); + InstructionValueSet& add_dependency_set = + GetInstructionValueSet(add_dependency); + if (operand_set != add_dependency_set) { + add_dependency_set = operand_set; + return true; + } + return false; +} + bool HloDataflowAnalysis::UpdateGetTupleElementValueSet(HloInstruction* gte) { CHECK_EQ(gte->opcode(), HloOpcode::kGetTupleElement); bool changed = false; @@ -622,6 +637,8 @@ bool HloDataflowAnalysis::UpdateInstructionValueSet( HloInstruction* instruction) { // Recompute from operands. switch (instruction->opcode()) { + case HloOpcode::kAddDependency: + return UpdateAddDependencyValueSet(instruction); case HloOpcode::kBitcast: return UpdateBitcastValueSet(instruction); case HloOpcode::kDomain: @@ -795,6 +812,7 @@ Status HloDataflowAnalysis::InitializeInstructionValueSets() { define_all_values(); } break; + case HloOpcode::kAddDependency: case HloOpcode::kWhile: case HloOpcode::kCall: case HloOpcode::kConditional: diff --git a/tensorflow/compiler/xla/service/hlo_dataflow_analysis.h b/tensorflow/compiler/xla/service/hlo_dataflow_analysis.h index abac398c04..ece17fc4c3 100644 --- a/tensorflow/compiler/xla/service/hlo_dataflow_analysis.h +++ b/tensorflow/compiler/xla/service/hlo_dataflow_analysis.h @@ -193,6 +193,7 @@ class HloDataflowAnalysis { bool UpdateSendValueSet(HloInstruction* send); bool UpdateTupleValueSet(HloInstruction* tuple); bool UpdateWhileValueSet(HloInstruction* xla_while); + bool UpdateAddDependencyValueSet(HloInstruction* add_dependency); // Propagate the dataflow through the module. void Propagate(); diff --git a/tensorflow/compiler/xla/service/hlo_dataflow_analysis_test.cc b/tensorflow/compiler/xla/service/hlo_dataflow_analysis_test.cc index 6422346c10..f7a1f19a6f 100644 --- a/tensorflow/compiler/xla/service/hlo_dataflow_analysis_test.cc +++ b/tensorflow/compiler/xla/service/hlo_dataflow_analysis_test.cc @@ -43,7 +43,7 @@ using ::testing::UnorderedElementsAre; class HloDataflowAnalysisTest : public HloTestBase, public ::testing::WithParamInterface { protected: - HloDataflowAnalysisTest() : module_(CreateNewUnverifiedModule()) {} + HloDataflowAnalysisTest() : module_(CreateNewVerifiedModule()) {} // Run dataflow analysis on the member module. For convenience returns a // reference to the generated analysis stored in analysis_. @@ -1877,6 +1877,30 @@ TEST_P(HloDataflowAnalysisTest, NestedConditionals) { } } +TEST_P(HloDataflowAnalysisTest, AddDependency) { + string module_string = R"( +HloModule AddDependency +ENTRY %AddDependency (p: f32[3]) -> f32[3] { + %p = f32[3] parameter(0) + %token = token[] after-all() + ROOT %add_dep = f32[3] add-dependency(f32[3] %p, token[] %token) +} +)"; + TF_ASSERT_OK_AND_ASSIGN( + std::unique_ptr module, + ParseHloString(module_string, GetModuleConfigForTest())); + + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr analysis, + HloDataflowAnalysis::Run(*module)); + const HloInstruction* root = module->entry_computation()->root_instruction(); + EXPECT_EQ(root->opcode(), HloOpcode::kAddDependency); + + // The after-all and parameter should define a value. Add-dependency should + // not. + EXPECT_EQ(analysis->values().size(), 2); + EXPECT_FALSE(analysis->ValueIsDefinedAt(root)); +} + INSTANTIATE_TEST_CASE_P(HloDataflowAnalysisInstantiation, HloDataflowAnalysisTest, ::testing::Values(false, true)); diff --git a/tensorflow/compiler/xla/service/hlo_dce_test.cc b/tensorflow/compiler/xla/service/hlo_dce_test.cc index 6c8095d397..1fa4259a3e 100644 --- a/tensorflow/compiler/xla/service/hlo_dce_test.cc +++ b/tensorflow/compiler/xla/service/hlo_dce_test.cc @@ -59,7 +59,7 @@ TEST_F(HloDceTest, NoDeadCode) { builder.AddInstruction(HloInstruction::CreateBinary( constant1->shape(), HloOpcode::kAdd, constant1, constant2)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_EQ(3, computation->instruction_count()); @@ -110,7 +110,7 @@ TEST_F(HloDceTest, DeadParameters) { builder.AddInstruction(HloInstruction::CreateUnary( live_param->shape(), HloOpcode::kNegate, live_param)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_EQ(5, computation->instruction_count()); @@ -150,7 +150,7 @@ TEST_F(HloDceTest, ControlDependencies) { builder.AddInstruction(HloInstruction::CreateBinary( constant1->shape(), HloOpcode::kAdd, constant1, constant2)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Add a control dependency between two instructions. @@ -175,7 +175,7 @@ TEST_F(HloDceTest, ControlDependencies) { // Tests that a dead call instruction is removed. TEST_F(HloDceTest, DeadInstructionWithCalledComputation) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); Shape shape = ShapeUtil::MakeShape(F32, {}); // Called computation for the call instruction. @@ -323,7 +323,7 @@ TEST_F(HloDceTest, CalledComputationWithNestedSideEffect) { } TEST_F(HloDceTest, RemoveDeadSubcomputation) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); HloComputation::Builder builder(TestName()); HloComputation::Builder subcomp_builder("reduction_subcomp"); diff --git a/tensorflow/compiler/xla/service/hlo_evaluator.cc b/tensorflow/compiler/xla/service/hlo_evaluator.cc index 7fcafafc09..3a7652a8dc 100644 --- a/tensorflow/compiler/xla/service/hlo_evaluator.cc +++ b/tensorflow/compiler/xla/service/hlo_evaluator.cc @@ -39,6 +39,7 @@ limitations under the License. #include "tensorflow/compiler/xla/service/hlo_query.h" #include "tensorflow/compiler/xla/service/shape_inference.h" #include "tensorflow/compiler/xla/shape_util.h" +#include "tensorflow/compiler/xla/statusor.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/util.h" #include "tensorflow/compiler/xla/window_util.h" @@ -396,6 +397,16 @@ StatusOr HloEvaluator::EvaluateDotOp( return Evaluate(cloned_instruction.get()); } +Status HloEvaluator::HandleBitcast(HloInstruction* bitcast) { + const Literal& operand_literal = GetEvaluatedLiteralFor(bitcast->operand(0)); + Literal result(bitcast->shape()); + TF_RET_CHECK(operand_literal.size_bytes() == result.size_bytes()); + memcpy(result.untyped_data(), operand_literal.untyped_data(), + operand_literal.size_bytes()); + evaluated_[bitcast] = std::move(result); + return Status::OK(); +} + Status HloEvaluator::HandleParameter(HloInstruction* parameter) { CHECK_LT(parameter->parameter_number(), arg_literals_.size()); const Literal* input_literal = arg_literals_[parameter->parameter_number()]; @@ -1046,8 +1057,15 @@ Status HloEvaluator::HandleBroadcast(HloInstruction* broadcast) { return Status::OK(); } -Status HloEvaluator::HandleAfterAll(HloInstruction* token) { - evaluated_[token] = LiteralUtil::CreateToken(); +Status HloEvaluator::HandleAfterAll(HloInstruction* after_all) { + evaluated_[after_all] = LiteralUtil::CreateToken(); + return Status::OK(); +} + +Status HloEvaluator::HandleAddDependency(HloInstruction* add_dependency) { + // AddDedendency just forwards its zero-th operand. + evaluated_[add_dependency] = + GetEvaluatedLiteralFor(add_dependency->operand(0)).Clone(); return Status::OK(); } @@ -1279,10 +1297,10 @@ StatusOr EvaluateSortInternal(HloInstruction* sort, key_value_vector.push_back( std::make_pair(keys_data[i], values_data[i])); } - std::sort(key_value_vector.begin(), key_value_vector.end(), - [](const kv_pair& a, const kv_pair& b) { - return SafeLess(a.first, b.first); - }); + std::stable_sort(key_value_vector.begin(), key_value_vector.end(), + [](const kv_pair& a, const kv_pair& b) { + return SafeLess(a.first, b.first); + }); std::vector result_keys; // We use a InlinedVector here because we need to convert it to an // absl::Span later, and this would not work with std::vector. diff --git a/tensorflow/compiler/xla/service/hlo_evaluator.h b/tensorflow/compiler/xla/service/hlo_evaluator.h index 07f8d0aad4..45ed8131dc 100644 --- a/tensorflow/compiler/xla/service/hlo_evaluator.h +++ b/tensorflow/compiler/xla/service/hlo_evaluator.h @@ -144,6 +144,8 @@ class HloEvaluator : public DfsHloVisitorWithDefault { // Operations that are type-agnostic or always return a specific type, such as // HandleIsFinite where boolean is always returned. // + Status HandleBitcast(HloInstruction* bitcast) override; + Status HandleParameter(HloInstruction* parameter) override; Status HandleConstant(HloInstruction* constant) override; @@ -180,7 +182,9 @@ class HloEvaluator : public DfsHloVisitorWithDefault { Status HandleBroadcast(HloInstruction* broadcast) override; - Status HandleAfterAll(HloInstruction* token) override; + Status HandleAfterAll(HloInstruction* after_all) override; + + Status HandleAddDependency(HloInstruction* add_dependency) override; Status HandleSort(HloInstruction* sort) override; @@ -221,16 +225,7 @@ class HloEvaluator : public DfsHloVisitorWithDefault { const Literal& operand_literal) { const auto shape = instruction->shape(); const auto* operand = instruction->operand(0); - - // TODO(b/35950897, b/27796129): add DCHECK back once implicit broadcast is - // removed. - if (!ShapeUtil::SameDimensions(shape, operand->shape())) { - return Unimplemented( - "Implicit broadcasting is currently unsupported in HLO evaluator " - "Shape Mismatch: %s vs %s", - ShapeUtil::HumanString(shape), - ShapeUtil::HumanString(operand->shape())); - } + TF_RET_CHECK(ShapeUtil::SameDimensions(shape, operand->shape())); Literal result(shape); TF_RETURN_IF_ERROR( diff --git a/tensorflow/compiler/xla/service/hlo_evaluator_test.cc b/tensorflow/compiler/xla/service/hlo_evaluator_test.cc index d95b6ad04f..4eaaab20ea 100644 --- a/tensorflow/compiler/xla/service/hlo_evaluator_test.cc +++ b/tensorflow/compiler/xla/service/hlo_evaluator_test.cc @@ -22,6 +22,7 @@ limitations under the License. #include #include "absl/memory/memory.h" +#include "absl/strings/str_format.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal.h" #include "tensorflow/compiler/xla/reference_util.h" @@ -35,6 +36,7 @@ limitations under the License. #include "tensorflow/compiler/xla/test.h" #include "tensorflow/compiler/xla/tests/hlo_test_base.h" #include "tensorflow/compiler/xla/tests/literal_test_util.h" +#include "tensorflow/compiler/xla/tests/test_utils.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/util.h" #include "tensorflow/compiler/xla/xla_data.pb.h" @@ -2765,6 +2767,33 @@ ENTRY main { EXPECT_TRUE(LiteralTestUtil::Equal(arg, actual)); } +TEST_P(HloEvaluatorTest, Bitcast) { + // Regression test for b/114735354. + constexpr absl::string_view hlo_text_base = R"( +HloModule Bitcast + +ENTRY main { + param = %s[32,121]{1,0} parameter(0) + ROOT bitcast = %s[121,32,1]{0,1,2} bitcast(%s[32,121]{1,0} param) +} +)"; + string hlo_text; + if (use_bfloat16_) { + hlo_text = absl::StrFormat(hlo_text_base, "bf16", "bf16", "bf16"); + } else { + hlo_text = absl::StrFormat(hlo_text_base, "f32", "f32", "f32"); + } + TF_ASSERT_OK_AND_ASSIGN(m_, ParseAndReturnVerifiedModule(hlo_text)); + auto args = MakeFakeArguments(m_.get()).ConsumeValueOrDie(); + Literal actual = Evaluate({&args[0]}); + if (use_bfloat16_) { + EXPECT_TRUE( + absl::c_equal(args[0].data(), actual.data())); + } else { + EXPECT_TRUE(absl::c_equal(args[0].data(), actual.data())); + } +} + INSTANTIATE_TEST_CASE_P(HloEvaluatorTest_Instantiation, HloEvaluatorTest, ::testing::ValuesIn(use_bf16_params)); diff --git a/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h b/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h index ebed875eb4..b87fc3e340 100644 --- a/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h +++ b/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h @@ -161,9 +161,6 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { HloOpcodeString(hlo_instruction->opcode())); } - // TODO(b/35950897): many of the stl functions used in the handlers are not - // overloaded for every XLA primitive type. - template ::value>::type* = nullptr> @@ -596,7 +593,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { return Status::OK(); } - Status HandleDivide(HloInstruction* divide) { + Status HandleDivide(HloInstruction* divide) override { return HandleDivide(divide); } @@ -1556,10 +1553,10 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const auto& row_data = row_to_sort.data(); std::vector result_data(row_data.begin(), row_data.end()); - std::sort(result_data.begin(), result_data.end(), - [](const NativeT& a, const NativeT& b) { - return SafeLess(a, b); - }); + std::stable_sort(result_data.begin(), result_data.end(), + [](const NativeT& a, const NativeT& b) { + return SafeLess(a, b); + }); Literal sorted_row(ShapeUtil::MakeShape(keys->shape().element_type(), {sort_dim_elements})); sorted_row.PopulateR1(absl::Span(result_data)); @@ -2546,12 +2543,14 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { template ::value || - std::is_same::value || - std::is_same::value>::type* = nullptr> + std::is_integral::value || + std::is_floating_point::value>::type* = nullptr> Status HandleIota(HloInstruction* instruction) { auto* iota = Cast(instruction); - std::vector data(iota->shape().dimensions(iota->iota_dimension())); + // Avoid using std::vector since std::vector does not convert to + // absl::Span. + absl::InlinedVector data( + iota->shape().dimensions(iota->iota_dimension())); std::iota(data.begin(), data.end(), 0); auto result = LiteralUtil::CreateR1(data); @@ -2568,9 +2567,8 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { } template ::value || - std::is_same::value || - std::is_same::value)>::type* = nullptr> + !(std::is_integral::value || + std::is_floating_point::value)>::type* = nullptr> Status HandleIota(HloInstruction* iota) { return InvalidArgument("Unsupported type for iota"); } @@ -2722,17 +2720,8 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const auto shape = instruction->shape(); const auto* lhs = instruction->operand(0); const auto* rhs = instruction->operand(1); - - // TODO(b/35950897, b/27796129): add DCHECK back once implicit broadcast - // is removed. - if (!(ShapeUtil::SameDimensions(shape, rhs->shape()) && - ShapeUtil::SameDimensions(lhs->shape(), rhs->shape()))) { - return Unimplemented( - "Implicit broadcasting is currently unsupported in HLO evaluator " - "Shape Mismatch: %s vs %s vs %s: ", - ShapeUtil::HumanString(shape), ShapeUtil::HumanString(lhs->shape()), - ShapeUtil::HumanString(rhs->shape())); - } + TF_RET_CHECK(ShapeUtil::SameDimensions(shape, rhs->shape())); + TF_RET_CHECK(ShapeUtil::SameDimensions(lhs->shape(), rhs->shape())); const Literal& lhs_literal = parent_->GetEvaluatedLiteralFor(lhs); const Literal& rhs_literal = parent_->GetEvaluatedLiteralFor(rhs); @@ -2756,19 +2745,9 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const auto* lhs = instruction->operand(0); const auto* rhs = instruction->operand(1); const auto* ehs = instruction->operand(2); - - // TODO(b/35950897, b/27796129): add DCHECK back once implicit - // broadcast is removed. - if (!(ShapeUtil::SameDimensions(shape, lhs->shape()) && - ShapeUtil::SameDimensions(lhs->shape(), rhs->shape()) && - ShapeUtil::SameDimensions(rhs->shape(), ehs->shape()))) { - return Unimplemented( - "Implicit broadcasting is currently unsupported in HLO evaluator " - "Shape Mismatch: %s vs %s vs %s vs %s: ", - ShapeUtil::HumanString(shape), ShapeUtil::HumanString(lhs->shape()), - ShapeUtil::HumanString(rhs->shape()), - ShapeUtil::HumanString(ehs->shape())); - } + TF_RET_CHECK(ShapeUtil::SameDimensions(shape, lhs->shape())); + TF_RET_CHECK(ShapeUtil::SameDimensions(lhs->shape(), rhs->shape())); + TF_RET_CHECK(ShapeUtil::SameDimensions(rhs->shape(), ehs->shape())); const Literal& lhs_literal = parent_->GetEvaluatedLiteralFor(lhs); const Literal& rhs_literal = parent_->GetEvaluatedLiteralFor(rhs); diff --git a/tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.cc b/tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.cc new file mode 100644 index 0000000000..c919dbd82d --- /dev/null +++ b/tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.cc @@ -0,0 +1,61 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.h" + +#include "absl/algorithm/container.h" +#include "tensorflow/compiler/xla/literal_util.h" +#include "tensorflow/compiler/xla/service/hlo_instruction.h" +#include "tensorflow/compiler/xla/service/hlo_opcode.h" +#include "tensorflow/compiler/xla/service/shape_inference.h" + +namespace xla { + +namespace { + +StatusOr ReplaceGetSize(HloInstruction* instr) { + if (instr->opcode() != HloOpcode::kGetDimensionSize) { + return false; + } + HloComputation* computation = instr->parent(); + + TF_ASSIGN_OR_RETURN(auto legal_shape, + ShapeInference::InferGetDimensionSizeShape( + instr->operand(0)->shape(), instr->dimension())); + TF_RET_CHECK(ShapeUtil::Equal(instr->shape(), legal_shape)); + TF_RET_CHECK(ShapeUtil::HasPrimitiveType(instr->shape(), U32)); + uint32 size = instr->operand(0)->shape().dimensions(instr->dimension()); + HloInstruction* new_instr = computation->AddInstruction( + HloInstruction::CreateConstant(LiteralUtil::CreateR0(size))); + TF_RETURN_IF_ERROR(instr->ReplaceAllUsesWith(new_instr)); + return true; +} + +} // namespace + +StatusOr HloGetDimensionSizeRewriter::Run(HloModule* module) { + bool changed = false; + HloProto proto; + *proto.mutable_hlo_module() = module->ToProto(); + for (auto* computation : module->computations()) { + for (auto instruction : computation->instructions()) { + TF_ASSIGN_OR_RETURN(bool replaced, ReplaceGetSize(instruction)); + changed = changed || replaced; + } + } + return changed; +} + +} // namespace xla diff --git a/tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.h b/tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.h new file mode 100644 index 0000000000..30f44c23a8 --- /dev/null +++ b/tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.h @@ -0,0 +1,36 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_COMPILER_XLA_SERVICE_HLO_GET_DIMENSION_SIZE_REWRITER_H_ +#define TENSORFLOW_COMPILER_XLA_SERVICE_HLO_GET_DIMENSION_SIZE_REWRITER_H_ + +#include "tensorflow/compiler/xla/service/hlo_module.h" +#include "tensorflow/compiler/xla/service/hlo_pass_interface.h" + +namespace xla { + +// Pass to replace a kGetDimensionSize instruction with a constant instruction. +class HloGetDimensionSizeRewriter : public HloModulePass { + public: + absl::string_view name() const override { + return "hlo-get-dimension-size-rewriter"; + } + + StatusOr Run(HloModule* module) override; +}; + +} // namespace xla + +#endif // TENSORFLOW_COMPILER_XLA_SERVICE_HLO_GET_DIMENSION_SIZE_REWRITER_H_ diff --git a/tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter_test.cc b/tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter_test.cc new file mode 100644 index 0000000000..a86aebdd5b --- /dev/null +++ b/tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter_test.cc @@ -0,0 +1,83 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/service/hlo_get_dimension_size_rewriter.h" + +#include "tensorflow/compiler/xla/service/hlo_computation.h" +#include "tensorflow/compiler/xla/service/hlo_instruction.h" +#include "tensorflow/compiler/xla/service/hlo_matchers.h" +#include "tensorflow/compiler/xla/service/hlo_module.h" +#include "tensorflow/compiler/xla/service/hlo_opcode.h" +#include "tensorflow/compiler/xla/service/hlo_parser.h" +#include "tensorflow/compiler/xla/shape_util.h" +#include "tensorflow/compiler/xla/tests/hlo_test_base.h" +#include "tensorflow/compiler/xla/tests/literal_test_util.h" +#include "tensorflow/compiler/xla/tests/test_utils.h" +#include "tensorflow/compiler/xla/types.h" +#include "tensorflow/core/lib/core/status_test_util.h" +#include "tensorflow/core/platform/types.h" + +namespace xla { +namespace { + +namespace op = xla::testing::opcode_matchers; + +class HloGetDimensionSizeRewriterTest : public HloTestBase { + protected: + HloGetDimensionSizeRewriterTest() {} +}; + +TEST_F(HloGetDimensionSizeRewriterTest, Ok) { + auto module = ParseHloString(R"( +HloModule _ +ENTRY gds { + p = s32[3,4] parameter(0) + size0 = u32[] get-dimension-size(p), dimensions={0} + size1 = u32[] get-dimension-size(p), dimensions={1} + ROOT mul = u32[] multiply(size0, size1) +})") + .ValueOrDie(); + HloGetDimensionSizeRewriter pass; + EXPECT_TRUE(pass.Run(module.get()).ValueOrDie()); + EXPECT_THAT(module->entry_computation()->root_instruction(), + op::Multiply(op::Constant(), op::Constant())); +} + +TEST_F(HloGetDimensionSizeRewriterTest, IllegalType) { + auto module = ParseHloString(R"( +HloModule _ +ENTRY gds { + p = s32[3]{0} parameter(0) + ROOT gds = s64[] get-dimension-size(p), dimensions={0} +})") + .ValueOrDie(); + HloGetDimensionSizeRewriter pass; + EXPECT_FALSE(pass.Run(module.get()).ok()); +} + +TEST_F(HloGetDimensionSizeRewriterTest, IllegalDimension) { + auto module = ParseHloString(R"( +HloModule _ +ENTRY gds { + p = f32[2,5] parameter(0) + ROOT gds = u32[] get-dimension-size(p), dimensions={2} +})") + .ValueOrDie(); + HloGetDimensionSizeRewriter pass; + EXPECT_FALSE(pass.Run(module.get()).ok()); +} + +} // namespace +} // namespace xla diff --git a/tensorflow/compiler/xla/service/hlo_graph_dumper.cc b/tensorflow/compiler/xla/service/hlo_graph_dumper.cc index 05cc1593e4..302eca656b 100644 --- a/tensorflow/compiler/xla/service/hlo_graph_dumper.cc +++ b/tensorflow/compiler/xla/service/hlo_graph_dumper.cc @@ -21,6 +21,7 @@ limitations under the License. #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ limitations under the License. #include "tensorflow/compiler/xla/service/hlo_instructions.h" #include "tensorflow/compiler/xla/service/hlo_module.h" #include "tensorflow/compiler/xla/service/hlo_tfgraph_builder.h" +#include "tensorflow/compiler/xla/service/pattern_matcher.h" #include "tensorflow/compiler/xla/shape_util.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/window_util.h" @@ -111,11 +113,6 @@ class NodeFilter { result == kSomeUsersOmitted; } - bool ShowFusionSubcomputation(const HloInstruction* instr) const { - CHECK_EQ(instr->opcode(), HloOpcode::kFusion); - return Show(instr) && !SomeOrAllOperandsOmitted(instr); - } - private: std::function filter_; }; @@ -240,34 +237,28 @@ string HtmlLikeStringSanitize(absl::string_view s) { // it to a short string lets us tell the user what the subcomputation is without // drawing it as a graph. optional MatchTrivialComputation(const HloComputation* computation) { + namespace m = match; + if (computation->instruction_count() != 3) { return nullopt; } - HloInstruction* root = computation->root_instruction(); - if (root->operand_count() != 2) { - return nullopt; - } - - // Check that both of the operands to the root are parameters. - const HloInstruction* operand0 = root->operand(0); - const HloInstruction* operand1 = root->operand(1); - if (operand0->opcode() != HloOpcode::kParameter || - operand1->opcode() != HloOpcode::kParameter) { - return nullopt; - } - - // Check that the two operands of root are param0 and param1. All of the - // opcodes we recognize are commutative, so we're OK with either order. - auto n0 = operand0->parameter_number(); - auto n1 = operand1->parameter_number(); - if (!(n0 == 0 && n1 == 1) && !(n1 == 0 && n0 == 1)) { + const HloInstruction *param0, *param1; + if (!Match(root, m::Op() + .WithNumOperands(2) + .WithShape(m::Shape().IsEffectiveScalar()) + .WithBinaryOperandsAnyOrder( + m::Parameter(¶m0, 0) + .WithShape(m::Shape().IsEffectiveScalar()), + m::Parameter(¶m1, 1) + .WithShape(m::Shape().IsEffectiveScalar())))) { return nullopt; } - // If the params are reversed, check that the operation being performed is - // commutative. - if (n0 == 1) { + // If the params are reversed (i.e. operand0 is param1 and operand1 is + // param0), check that the operation being performed is commutative. + if (root->operand(0) == param1) { + CHECK_EQ(root->operand(1), param0); switch (root->opcode()) { case HloOpcode::kLe: case HloOpcode::kGe: @@ -279,13 +270,6 @@ optional MatchTrivialComputation(const HloComputation* computation) { } } - // Check that the root and params are all effective scalars. - if (!ShapeUtil::IsEffectiveScalar(root->shape()) || - !ShapeUtil::IsEffectiveScalar(operand0->shape()) || - !ShapeUtil::IsEffectiveScalar(operand1->shape())) { - return nullopt; - } - // If we recognize the root's opcode, we've successfully pattern-matched! switch (root->opcode()) { case HloOpcode::kAdd: @@ -578,7 +562,7 @@ bool HloDotDumper::ShouldShowSubcomputation(const HloComputation* subcomp) { // Show the subcomputation if we're showing any of its members. return std::any_of( - computation_->instructions().begin(), computation_->instructions().end(), + subcomp->instructions().begin(), subcomp->instructions().end(), [&](const HloInstruction* instr) { return filter_.Show(instr); }); } @@ -987,6 +971,7 @@ ColorScheme HloDotDumper::GetInstructionColor(const HloInstruction* instr) { case HloOpcode::kGetTupleElement: case HloOpcode::kTrace: case HloOpcode::kAfterAll: + case HloOpcode::kAddDependency: case HloOpcode::kTuple: return kWhite; case HloOpcode::kBroadcast: @@ -1267,12 +1252,12 @@ const HloInstruction* HloDotDumper::GetNodeForEdge( class GraphRendererRegistry { public: - void AddRenderer(GraphRendererInterface* graph_renderer) { + void SetRenderer(std::shared_ptr graph_renderer) { tensorflow::mutex_lock lock(mu_); graph_renderer_ = graph_renderer; } - GraphRendererInterface* GetDefaultRenderer() { + std::shared_ptr GetDefaultRenderer() { tensorflow::mutex_lock lock(mu_); return graph_renderer_; } @@ -1284,20 +1269,21 @@ class GraphRendererRegistry { private: tensorflow::mutex mu_; - GraphRendererInterface* graph_renderer_ = nullptr; + std::shared_ptr graph_renderer_ GUARDED_BY(mu_); }; } // namespace -Registrar::Registrar(GraphRendererInterface* dumper) { - GraphRendererRegistry::Default()->AddRenderer(dumper); +Registrar::Registrar(std::shared_ptr dumper) { + GraphRendererRegistry::Default()->SetRenderer(dumper); } namespace { // Gets a NodeFilter that includes roughly all instructions whose distance from // root is <= radius. -NodeFilter MakeNodeFilter(const HloInstruction* root, int64 radius) { +NodeFilter MakeNodeRadiusAroundFilter(const HloInstruction* root, + int64 radius) { // First, find the neighborhood of nodes with distance from root <= radius. // These nodes are our initial set of "normal" nodes. std::unordered_map nodes; @@ -1404,6 +1390,56 @@ NodeFilter MakeNodeFilter(const HloInstruction* root, int64 radius) { }); } +// Gets a node filter that includes nodes on all paths from `from` to `to`. If +// the all-paths set contains more than max_nodes elements, includes the nodes +// on the shortest paths and sets hit_limit to true. +NodeFilter MakeNodeFromToFilter(const HloInstruction* from, + const HloInstruction* to, int64 max_nodes, + bool* hit_limit) { + *hit_limit = false; + + // Elements in the queue are paths through the graph. + std::deque> queue; + queue.push_front({from}); + + // Compute the set of nodes we want to show using a slightly-modified + // Djikstra's algorithm. The only real difference is, rather than stopping + // when we find a (shortest) path, we continue until we've found max_nodes + // nodes on some path. + std::unordered_set visited; + std::unordered_set to_display = {from, to}; + while (!queue.empty() && to_display.size() < max_nodes) { + std::vector path = std::move(queue.front()); + queue.pop_front(); + if (!visited.insert(path.back()).second) { + continue; + } + + for (const auto* user : path.back()->users()) { + if (user == to) { + auto it = path.begin(); + for (; it != path.end() && to_display.size() < max_nodes; ++it) { + to_display.insert(*it); + } + if (it != path.end()) { + *hit_limit = true; + } + } else if (!visited.count(user)) { + auto new_path = path; + new_path.push_back(user); + queue.push_back(std::move(new_path)); + } + } + } + + return NodeFilter([=](const HloInstruction* instr) { + if (instr == from || instr == to) { + return kHighlightNode; + } + return to_display.count(instr) ? kNormalNode : kHideNode; + }); +} + string SaveGraph(const string& graph, GraphRendererInterface::GraphKind graph_kind, const string& dest_path) { @@ -1483,7 +1519,7 @@ string DumpNeighborhoodAround(const HloInstruction& node, int radius, auto debug_options = node.GetModule()->config().debug_options(); string label = StrCat("Neighborhood of ", radius, " nodes around ", node.name()); - NodeFilter filter = MakeNodeFilter(&node, radius); + NodeFilter filter = MakeNodeRadiusAroundFilter(&node, radius); string graph = HloDotDumper(node.parent(), label, debug_options, show_backend_config, /*profile=*/nullptr, filter) @@ -1491,6 +1527,29 @@ string DumpNeighborhoodAround(const HloInstruction& node, int radius, return ExportGraph(graph, GraphRendererInterface::DOT_GRAPH, debug_options); } +string DumpAllPathsFromTo(const HloInstruction& from, const HloInstruction& to, + int64 max_nodes, bool show_backend_config) { + CHECK_EQ(from.parent(), to.parent()) << "Nodes must be in same computation!"; + auto debug_options = from.GetModule()->config().debug_options(); + + bool hit_limit = false; + NodeFilter filter = MakeNodeFromToFilter(&from, &to, max_nodes, &hit_limit); + string label; + if (!hit_limit) { + label = StrCat("All paths from ", from.name(), " to ", to.name()); + } else { + label = StrCat(max_nodes, " nodes on the shortest paths from ", from.name(), + " to ", to.name(), + "

***SHOWING ONLY A SUBSET OF ALL PATHS BETWEEN " + "NODES***

"); + } + string graph = + HloDotDumper(from.parent(), label, debug_options, show_backend_config, + /*profile=*/nullptr, filter) + .Dump(); + return ExportGraph(graph, GraphRendererInterface::DOT_GRAPH, debug_options); +} + void DumpText(const HloModule& module, const string& label, const string& directory_path, bool do_prefix) { Env* env = Env::Default(); diff --git a/tensorflow/compiler/xla/service/hlo_graph_dumper.h b/tensorflow/compiler/xla/service/hlo_graph_dumper.h index 0b11f34abb..de1eefab77 100644 --- a/tensorflow/compiler/xla/service/hlo_graph_dumper.h +++ b/tensorflow/compiler/xla/service/hlo_graph_dumper.h @@ -66,6 +66,12 @@ string DumpGraph(const HloComputation& computation, const string& label, string DumpNeighborhoodAround(const HloInstruction& node, int radius, bool show_backend_config = false); +// Dumps nodes on any of the paths from `from` to `to`. If there are more than +// max_nodes on all paths, restricts to the max_nodes nodes on the shortest +// paths. +string DumpAllPathsFromTo(const HloInstruction& from, const HloInstruction& to, + int64 max_nodes, bool show_backend_config = false); + // Dumps the HloModule::ToString() as a file into the provided directory path // suffixed with the provided label. // @@ -87,13 +93,13 @@ void DumpText(const HloModule& module, const string& label, // Class that registers a graph renderer. class Registrar { public: - Registrar(GraphRendererInterface* dumper); + Registrar(std::shared_ptr dumper); }; -#define XLA_INTERNAL_REGISTER_GRAPH_RENDERER(factory, ctr, ...) \ - static ::xla::hlo_graph_dumper::Registrar \ - XLA_INTERNAL_REGISTER_GRAPH_RENDERER_NAME(ctr)(new factory, \ - ##__VA_ARGS__) +#define XLA_INTERNAL_REGISTER_GRAPH_RENDERER(factory, ctr, ...) \ + static ::xla::hlo_graph_dumper::Registrar \ + XLA_INTERNAL_REGISTER_GRAPH_RENDERER_NAME(ctr)( \ + std::make_shared(), ##__VA_ARGS__) // __COUNTER__ must go through another macro to be properly expanded #define XLA_INTERNAL_REGISTER_GRAPH_RENDERER_NAME(ctr) ___##ctr##__object_ diff --git a/tensorflow/compiler/xla/service/hlo_instruction.cc b/tensorflow/compiler/xla/service/hlo_instruction.cc index 26786ee950..21b1dbc167 100644 --- a/tensorflow/compiler/xla/service/hlo_instruction.cc +++ b/tensorflow/compiler/xla/service/hlo_instruction.cc @@ -93,7 +93,8 @@ StatusOr> HloInstruction::CreateFromProto( [&computation_map](int64 id) { return computation_map.contains(id); })) << proto.name() << " instruction references invalid computation id(s)"; - TF_RETURN_IF_ERROR(ShapeUtil::ValidateShapeWithOptionalLayout(proto.shape())); + Shape shape(proto.shape()); + TF_RETURN_IF_ERROR(ShapeUtil::ValidateShapeWithOptionalLayout(shape)); switch (opcode) { // Ops migrated to subclasses. @@ -101,23 +102,23 @@ StatusOr> HloInstruction::CreateFromProto( TF_RET_CHECK(proto.operand_ids_size() == 3) << "BatchNormTraining instruction should have 3 operands but sees " << proto.operand_ids_size(); - instruction = CreateBatchNormTraining( - proto.shape(), operands(0), operands(1), operands(2), proto.epsilon(), - proto.feature_index()); + instruction = + CreateBatchNormTraining(shape, operands(0), operands(1), operands(2), + proto.epsilon(), proto.feature_index()); break; case HloOpcode::kBatchNormInference: TF_RET_CHECK(proto.operand_ids_size() == 5) << "BatchNormInference instruction should have 5 operands but sees " << proto.operand_ids_size(); instruction = CreateBatchNormInference( - proto.shape(), operands(0), operands(1), operands(2), operands(3), + shape, operands(0), operands(1), operands(2), operands(3), operands(4), proto.epsilon(), proto.feature_index()); break; case HloOpcode::kBatchNormGrad: TF_RET_CHECK(proto.operand_ids_size() == 5) << "BatchNormGrad instruction should have 5 operands but sees " << proto.operand_ids_size(); - instruction = CreateBatchNormGrad(proto.shape(), operands(0), operands(1), + instruction = CreateBatchNormGrad(shape, operands(0), operands(1), operands(2), operands(3), operands(4), proto.epsilon(), proto.feature_index()); break; @@ -127,7 +128,7 @@ StatusOr> HloInstruction::CreateFromProto( << proto.operand_ids_size(); std::vector fft_length(proto.fft_length().begin(), proto.fft_length().end()); - instruction = CreateFft(proto.shape(), operands(0), proto.fft_type(), + instruction = CreateFft(shape, operands(0), proto.fft_type(), absl::Span(fft_length)); break; } @@ -148,7 +149,7 @@ StatusOr> HloInstruction::CreateFromProto( TF_RET_CHECK(proto.operand_ids_size() == 1) << "Recv instruction should have 1 operand but sees " << proto.operand_ids_size(); - instruction = CreateRecv(proto.shape().tuple_shapes(0), operands(0), + instruction = CreateRecv(shape.tuple_shapes(0), operands(0), proto.channel_id(), proto.is_host_transfer()); break; case HloOpcode::kRecvDone: @@ -161,7 +162,7 @@ StatusOr> HloInstruction::CreateFromProto( TF_RET_CHECK(proto.operand_ids_size() == 1) << "Reverse instruction should have 1 operand but sees " << proto.operand_ids_size(); - instruction = CreateReverse(proto.shape(), operands(0), + instruction = CreateReverse(shape, operands(0), std::vector(proto.dimensions().begin(), proto.dimensions().end())); break; @@ -170,7 +171,7 @@ StatusOr> HloInstruction::CreateFromProto( << "Concatenate instruction should have 1 dimension but sees " << proto.dimensions_size(); instruction = - CreateConcatenate(proto.shape(), all_operands(), proto.dimensions(0)); + CreateConcatenate(shape, all_operands(), proto.dimensions(0)); break; case HloOpcode::kReduce: TF_RET_CHECK(proto.operand_ids_size() % 2 == 0) @@ -188,7 +189,7 @@ StatusOr> HloInstruction::CreateFromProto( absl::MakeSpan(reduce_operands) .subspan(reduce_operands.size() / 2, reduce_operands.size()); instruction = - CreateReduce(proto.shape(), inputs, init_values, + CreateReduce(shape, inputs, init_values, std::vector(proto.dimensions().begin(), proto.dimensions().end()), computations(0)); @@ -203,7 +204,7 @@ StatusOr> HloInstruction::CreateFromProto( auto sort_operands = all_operands(); HloInstruction* keys = sort_operands[0]; instruction = CreateSort( - proto.shape(), proto.dimensions(0), keys, + shape, proto.dimensions(0), keys, absl::Span(sort_operands).subspan(1)); break; } @@ -212,7 +213,7 @@ StatusOr> HloInstruction::CreateFromProto( << "Transpose instruction should have 1 operand but sees " << proto.operand_ids_size(); instruction = - CreateTranspose(proto.shape(), operands(0), + CreateTranspose(shape, operands(0), std::vector(proto.dimensions().begin(), proto.dimensions().end())); break; @@ -221,7 +222,7 @@ StatusOr> HloInstruction::CreateFromProto( << "Broadcast instruction should have 1 operand but sees " << proto.operand_ids_size(); instruction = - CreateBroadcast(proto.shape(), operands(0), + CreateBroadcast(shape, operands(0), std::vector(proto.dimensions().begin(), proto.dimensions().end())); break; @@ -229,7 +230,7 @@ StatusOr> HloInstruction::CreateFromProto( TF_RET_CHECK(proto.called_computation_ids_size() == 1) << "Map instruction should have 1 called computation but sees " << proto.called_computation_ids_size(); - instruction = CreateMap(proto.shape(), all_operands(), computations(0)); + instruction = CreateMap(shape, all_operands(), computations(0)); break; case HloOpcode::kSlice: { TF_RET_CHECK(proto.operand_ids_size() == 1) @@ -242,8 +243,8 @@ StatusOr> HloInstruction::CreateFromProto( slice_limits.push_back(slice_dimensions.limit()); slice_strides.push_back(slice_dimensions.stride()); } - instruction = CreateSlice(proto.shape(), operands(0), slice_starts, - slice_limits, slice_strides); + instruction = CreateSlice(shape, operands(0), slice_starts, slice_limits, + slice_strides); break; } case HloOpcode::kConstant: { @@ -253,7 +254,7 @@ StatusOr> HloInstruction::CreateFromProto( Literal::CreateFromProto(proto.literal())); instruction = CreateConstant(std::move(literal)); } else { - instruction = absl::make_unique(proto.shape()); + instruction = absl::make_unique(shape); } break; } @@ -284,55 +285,54 @@ StatusOr> HloInstruction::CreateFromProto( tensorflow::gtl::FindPtrOrNull(computation_map, fusion_id); TF_RET_CHECK(fused_computation != nullptr) << "No fusion computation with id " << fusion_id; - instruction = CreateFusion(proto.shape(), fusion_kind, all_operands(), - fused_computation); + instruction = + CreateFusion(shape, fusion_kind, all_operands(), fused_computation); break; } case HloOpcode::kRng: - instruction = - CreateRng(proto.shape(), proto.distribution(), all_operands()); + instruction = CreateRng(shape, proto.distribution(), all_operands()); break; case HloOpcode::kParameter: - instruction = CreateParameter(proto.parameter_number(), proto.shape(), - proto.name()); + instruction = + CreateParameter(proto.parameter_number(), shape, proto.name()); break; case HloOpcode::kGetTupleElement: TF_RET_CHECK(proto.operand_ids_size() == 1) << "GetTupleElement instruction should have 1 operand but sees " << proto.operand_ids_size(); - instruction = CreateGetTupleElement(proto.shape(), operands(0), - proto.tuple_index()); + instruction = + CreateGetTupleElement(shape, operands(0), proto.tuple_index()); break; case HloOpcode::kReducePrecision: TF_RET_CHECK(proto.operand_ids_size() == 1) << "ReducePrecision instruction should have 1 operand but sees " << proto.operand_ids_size(); - instruction = - CreateReducePrecision(proto.shape(), operands(0), - proto.exponent_bits(), proto.mantissa_bits()); + instruction = CreateReducePrecision( + shape, operands(0), proto.exponent_bits(), proto.mantissa_bits()); break; case HloOpcode::kInfeed: { - TF_RET_CHECK(ShapeUtil::IsTuple(proto.shape()) && - (ShapeUtil::TupleElementCount(proto.shape()) == 2)) + TF_RET_CHECK(ShapeUtil::IsTuple(shape) && + (ShapeUtil::TupleElementCount(shape) == 2)) << "Infeed should have a tuple shape with 2 operands, but has: " - << proto.shape(); - const Shape& data_shape = - ShapeUtil::GetTupleElementShape(proto.shape(), 0); + << shape; + const Shape& data_shape = ShapeUtil::GetTupleElementShape(shape, 0); TF_RET_CHECK(proto.operand_ids_size() == 1) << "Infeed instruction should have 1 operand but sees " << proto.operand_ids_size(); instruction = CreateInfeed(data_shape, operands(0), proto.infeed_config()); } break; - case HloOpcode::kOutfeed: + case HloOpcode::kOutfeed: { TF_RET_CHECK(proto.operand_ids_size() == 2) << "Outfeed instruction should have 2 operands but sees " << proto.operand_ids_size(); + Shape outfeed_shape(proto.outfeed_shape()); TF_RETURN_IF_ERROR( - ShapeUtil::ValidateShapeWithOptionalLayout(proto.outfeed_shape())); - instruction = CreateOutfeed(proto.outfeed_shape(), operands(0), - operands(1), proto.outfeed_config()); + ShapeUtil::ValidateShapeWithOptionalLayout(outfeed_shape)); + instruction = CreateOutfeed(outfeed_shape, operands(0), operands(1), + proto.outfeed_config()); break; + } case HloOpcode::kCrossReplicaSum: { TF_RET_CHECK(proto.called_computation_ids_size() == 1) << "CrossReplicaSum should have 1 called computation but sees " @@ -342,7 +342,7 @@ StatusOr> HloInstruction::CreateFromProto( all_reduce_id = proto.all_reduce_id(); } instruction = CreateCrossReplicaSum( - proto.shape(), all_operands(), computations(0), + shape, all_operands(), computations(0), /*replica_groups=*/ std::vector(proto.replica_groups().begin(), proto.replica_groups().end()), @@ -352,7 +352,7 @@ StatusOr> HloInstruction::CreateFromProto( } case HloOpcode::kAllToAll: { instruction = CreateAllToAll( - proto.shape(), all_operands(), + shape, all_operands(), /*replica_groups=*/ std::vector(proto.replica_groups().begin(), proto.replica_groups().end())); @@ -368,8 +368,8 @@ StatusOr> HloInstruction::CreateFromProto( source_target_pairs[i].first = proto.source_target_pairs(i).source(); source_target_pairs[i].second = proto.source_target_pairs(i).target(); } - instruction = CreateCollectivePermute(proto.shape(), operands(0), - source_target_pairs); + instruction = + CreateCollectivePermute(shape, operands(0), source_target_pairs); break; } case HloOpcode::kConvolution: { @@ -382,7 +382,7 @@ StatusOr> HloInstruction::CreateFromProto( precision_config.mutable_operand_precision()->Resize( proto.operand_ids_size(), PrecisionConfig::DEFAULT); instruction = CreateConvolve( - proto.shape(), operands(0), operands(1), + shape, operands(0), operands(1), std::max(proto.feature_group_count(), 1), proto.window(), proto.convolution_dimension_numbers(), precision_config); break; @@ -394,7 +394,7 @@ StatusOr> HloInstruction::CreateFromProto( TF_RET_CHECK(proto.called_computation_ids_size() == 1) << "ReduceWindow should have 1 called computation but sees " << proto.called_computation_ids_size(); - instruction = CreateReduceWindow(proto.shape(), operands(0), operands(1), + instruction = CreateReduceWindow(shape, operands(0), operands(1), proto.window(), computations(0)); break; case HloOpcode::kSelectAndScatter: @@ -404,9 +404,9 @@ StatusOr> HloInstruction::CreateFromProto( TF_RET_CHECK(proto.called_computation_ids_size() == 2) << "SelectAndScatter should have 2 called computations but sees " << proto.called_computation_ids_size(); - instruction = CreateSelectAndScatter( - proto.shape(), operands(0), computations(0), proto.window(), - operands(1), operands(2), computations(1)); + instruction = CreateSelectAndScatter(shape, operands(0), computations(0), + proto.window(), operands(1), + operands(2), computations(1)); break; case HloOpcode::kCustomCall: if (proto.constrain_layout()) { @@ -414,16 +414,17 @@ StatusOr> HloInstruction::CreateFromProto( // vector of pointers essentially) so create a vector of shapes to pass // in. std::vector operand_shapes; - for (const Shape& shape : proto.operand_shapes_with_layout()) { - operand_shapes.push_back(shape); + for (const ShapeProto& shape_proto : + proto.operand_shapes_with_layout()) { + operand_shapes.emplace_back(shape_proto); } - instruction = CreateCustomCall( - proto.shape(), all_operands(), proto.custom_call_target(), - operand_shapes, proto.custom_call_opaque()); + instruction = + CreateCustomCall(shape, all_operands(), proto.custom_call_target(), + operand_shapes, proto.custom_call_opaque()); } else { - instruction = CreateCustomCall(proto.shape(), all_operands(), - proto.custom_call_target(), - proto.custom_call_opaque()); + instruction = + CreateCustomCall(shape, all_operands(), proto.custom_call_target(), + proto.custom_call_opaque()); } if (proto.has_window()) { static_cast(instruction.get()) @@ -443,8 +444,8 @@ StatusOr> HloInstruction::CreateFromProto( << "Pad instruction should have 2 operands but sees " << proto.operand_ids_size(); TF_RET_CHECK(proto.has_padding_config()); - instruction = CreatePad(proto.shape(), operands(0), operands(1), - proto.padding_config()); + instruction = + CreatePad(shape, operands(0), operands(1), proto.padding_config()); break; case HloOpcode::kDynamicSlice: { TF_RET_CHECK(proto.operand_ids_size() == 2) @@ -452,8 +453,8 @@ StatusOr> HloInstruction::CreateFromProto( << proto.operand_ids_size(); std::vector slice_sizes(proto.dynamic_slice_sizes_size()); absl::c_copy(proto.dynamic_slice_sizes(), slice_sizes.begin()); - instruction = CreateDynamicSlice(proto.shape(), operands(0), operands(1), - slice_sizes); + instruction = + CreateDynamicSlice(shape, operands(0), operands(1), slice_sizes); break; } case HloOpcode::kGather: { @@ -469,7 +470,7 @@ StatusOr> HloInstruction::CreateFromProto( for (int64 bound : proto.gather_slice_sizes()) { gather_slice_sizes.push_back(bound); } - instruction = CreateGather(proto.shape(), operands(0), operands(1), + instruction = CreateGather(shape, operands(0), operands(1), *gather_dimension_numbers, gather_slice_sizes); break; } @@ -485,16 +486,15 @@ StatusOr> HloInstruction::CreateFromProto( auto scatter_dimension_numbers = absl::make_unique( proto.scatter_dimension_numbers()); - instruction = - CreateScatter(proto.shape(), operands(0), operands(1), operands(2), - computations(0), *scatter_dimension_numbers); + instruction = CreateScatter(shape, operands(0), operands(1), operands(2), + computations(0), *scatter_dimension_numbers); break; } case HloOpcode::kIota: TF_RET_CHECK(proto.dimensions_size() == 1) << "Iota instruction should have 1 dimension but sees " << proto.dimensions_size(); - instruction = CreateIota(proto.shape(), proto.dimensions(0)); + instruction = CreateIota(shape, proto.dimensions(0)); break; case HloOpcode::kDot: { TF_RET_CHECK(proto.has_dot_dimension_numbers()) @@ -506,8 +506,8 @@ StatusOr> HloInstruction::CreateFromProto( precision_config.mutable_operand_precision()->Resize( proto.operand_ids_size(), PrecisionConfig::DEFAULT); instruction = absl::make_unique( - proto.shape(), operands(0), operands(1), - proto.dot_dimension_numbers(), precision_config); + shape, operands(0), operands(1), proto.dot_dimension_numbers(), + precision_config); break; } case HloOpcode::kDomain: { @@ -529,7 +529,7 @@ StatusOr> HloInstruction::CreateFromProto( exit_hlo_sharding = std::make_shared(sharding); } instruction = absl::make_unique( - proto.shape(), operands(0), + shape, operands(0), absl::make_unique(entry_hlo_sharding), absl::make_unique(exit_hlo_sharding)); break; @@ -537,11 +537,11 @@ StatusOr> HloInstruction::CreateFromProto( case HloOpcode::kGetDimensionSize: TF_RET_CHECK(proto.operand_ids_size() == 1); TF_RET_CHECK(proto.dimensions_size() == 1); - instruction = CreateGetDimensionSize(proto.shape(), operands(0), - proto.dimensions(0)); + instruction = + CreateGetDimensionSize(shape, operands(0), proto.dimensions(0)); break; default: { - instruction = absl::WrapUnique(new HloInstruction(opcode, proto.shape())); + instruction = absl::WrapUnique(new HloInstruction(opcode, shape)); for (const int64 operand_id : proto.operand_ids()) { instruction->AppendOperand(instruction_map.at(operand_id)); } @@ -855,6 +855,16 @@ HloInstruction::CreateCollectivePermute( new HloInstruction(HloOpcode::kAfterAll, ShapeUtil::MakeTokenShape())); } +/* static */ std::unique_ptr +HloInstruction::CreateAddDependency(HloInstruction* data_operand, + HloInstruction* token_operand) { + auto instruction = absl::WrapUnique( + new HloInstruction(HloOpcode::kAddDependency, data_operand->shape())); + instruction->AppendOperand(data_operand); + instruction->AppendOperand(token_operand); + return instruction; +} + /* static */ std::unique_ptr HloInstruction::CreateWhile( const Shape& shape, HloComputation* condition, HloComputation* body, HloInstruction* init) { @@ -1394,6 +1404,10 @@ std::unique_ptr HloInstruction::CloneWithNewOperands( clone = CreateAfterAll(new_operands); } break; + case HloOpcode::kAddDependency: + CHECK_EQ(new_operands.size(), 2); + clone = CreateAddDependency(new_operands[0], new_operands[1]); + break; } // SetupDerivedInstruction will setup the precision_config_ field. SetupDerivedInstruction(clone.get()); @@ -1680,6 +1694,7 @@ bool HloInstruction::IdenticalSlowPath( // This opcode has complex or special behavior so just return false. case HloOpcode::kAfterAll: + case HloOpcode::kAddDependency: return false; // Remaining instructions with special values. @@ -1745,6 +1760,26 @@ bool HloInstruction::IdenticalSlowPath( return false; } +uint64 HloInstruction::Hash() const { + using tensorflow::Hash64Combine; + + uint64 hash_value = Hash64Combine(0, static_cast(opcode())); + hash_value = Hash64Combine(hash_value, ShapeUtil::Hash(shape())); + + if (!IsCrossModuleAllReduce()) { + if (!operands().empty()) { + for (size_t i = 0; i < operands().size(); ++i) { + hash_value = Hash64Combine(hash_value, operand(i)->Hash()); + } + } + } + + hash_value = Hash64Combine(hash_value, InnerHash()); + return hash_value; +} + +uint64 HloInstruction::InnerHash() const { return 13; } + void HloInstruction::RemoveUser(HloInstruction* user) { auto set_it = user_set_.find(user); CHECK(set_it != user_set_.end()); @@ -1900,6 +1935,11 @@ void HloInstruction::set_while_body(HloComputation* computation) { called_computations_[kBodyComputationIndex] = computation; } +HloInstruction* HloInstruction::while_init() const { + CHECK_EQ(HloOpcode::kWhile, opcode_); + return operands_[0]; +} + HloComputation* HloInstruction::true_computation() const { CHECK_EQ(HloOpcode::kConditional, opcode_); return called_computations_[kTrueComputationIndex]; @@ -2214,7 +2254,7 @@ HloInstructionProto HloInstruction::ToProto() const { proto.set_id(unique_id_); proto.set_name(name_); proto.set_opcode(HloOpcodeString(opcode_)); - *proto.mutable_shape() = shape_; + *proto.mutable_shape() = shape_.ToProto(); for (const HloInstruction* operand : operands_) { proto.add_operand_ids(operand->unique_id()); } @@ -2462,6 +2502,8 @@ Status HloInstruction::Visit(DfsHloVisitorBase* visitor) { return visitor->HandleDomain(this); case HloOpcode::kAfterAll: return visitor->HandleAfterAll(this); + case HloOpcode::kAddDependency: + return visitor->HandleAddDependency(this); case HloOpcode::kIota: return visitor->HandleIota(this); case HloOpcode::kGetDimensionSize: @@ -2623,36 +2665,6 @@ Status HloInstruction::AcceptWithOperandOrder( return Status::OK(); } -namespace { - -// Returns true if the given order is a topological sort of the instructions -// it contains. -bool OrderIsTopologicalSort(const std::vector& order) { - // Create a map from instruction to its position in 'order'. - std::unordered_map order_position; - for (int i = 0; i < order.size(); i++) { - if (!order_position.insert({order[i], i}).second) { - // Instruction order[i] is duplicated in the order. - return false; - } - } - // Verify that the operand of each instruction in the order is also in the - // order *and* the operand's position is earlier (defs are before uses for - // all ops). - for (auto* instruction : order) { - for (auto* operand : instruction->operands()) { - if (!ContainsKey(order_position, operand) || - order_position.at(operand) >= order_position.at(instruction)) { - return false; - } - } - } - - return true; -} - -} // namespace - Status HloInstruction::Accept( const std::function& visitor_func) { FunctionVisitor visitor(visitor_func); @@ -3022,6 +3034,16 @@ const PrecisionConfig& HloInstruction::precision_config() const { LOG(FATAL) << "Unimplemented method."; } +PrecisionConfig* HloInstruction::mutable_precision_config() { + if (auto* convolution = DynCast(this)) { + return convolution->mutable_precision_config(); + } + if (auto* dot = DynCast(this)) { + return dot->mutable_precision_config(); + } + LOG(FATAL) << "Unimplemented method."; +} + HloModule* HloInstruction::GetModule() const { if (parent_) { return parent_->parent(); @@ -3064,6 +3086,10 @@ int64 HloInstruction::concatenate_dimension() const { return Cast(this)->concatenate_dimension(); } +int64 HloInstruction::dimension() const { + return Cast(this)->dimension(); +} + bool HloInstruction::IsRank2Transpose() const { auto transpose = DynCast(this); return transpose != nullptr && transpose->IsRank2Transpose(); @@ -3243,6 +3269,11 @@ absl::optional HloInstruction::all_reduce_id() const { return Cast(this)->all_reduce_id(); } +void HloInstruction::set_all_reduce_id( + const absl::optional& all_reduce_id) { + return Cast(this)->set_all_reduce_id(all_reduce_id); +} + const ConvolutionDimensionNumbers& HloInstruction::convolution_dimension_numbers() const { if (auto convolution = DynCast(this)) { diff --git a/tensorflow/compiler/xla/service/hlo_instruction.h b/tensorflow/compiler/xla/service/hlo_instruction.h index 818d4ede0f..a54716217d 100644 --- a/tensorflow/compiler/xla/service/hlo_instruction.h +++ b/tensorflow/compiler/xla/service/hlo_instruction.h @@ -770,6 +770,9 @@ class HloInstruction { static std::unique_ptr CreateGetDimensionSize( const Shape& shape, HloInstruction* operand, int64 dimension); + static std::unique_ptr CreateAddDependency( + HloInstruction* data_operand, HloInstruction* token_operand); + // Returns the opcode for this instruction. HloOpcode opcode() const { return opcode_; } @@ -883,11 +886,15 @@ class HloInstruction { return false; } - // Use an explicit loop rather than ContainerEquals, because copying around - // std::functions may be too expensive in some cases. - for (size_t i = 0; i < operands().size(); ++i) { - if (!eq_operands(operand(i), other.operand(i))) { - return false; + // Two AllReduces are Identical if they have the same all_reduce_id. + // Their operands don't have to be Identical. + if (!IsCrossModuleAllReduce()) { + // Use an explicit loop rather than ContainerEquals, because copying + // around std::functions may be too expensive in some cases. + for (size_t i = 0; i < operands().size(); ++i) { + if (!eq_operands(operand(i), other.operand(i))) { + return false; + } } } @@ -898,6 +905,12 @@ class HloInstruction { return IdenticalSlowPath(other, eq_computations); } + // Generates a hash value of an HLO instruction. Hash considers + // information on opcode, shape, operands, and typically a root instruction. + // This function returns the same hash value for equivalent HLO instructions, + // with respect to HloInstruction::Identical() method. + uint64 Hash() const; + // Returns whether the instruction has a constant operand. bool HasConstantOperand() const; @@ -997,6 +1010,8 @@ class HloInstruction { void set_while_condition(HloComputation* while_condition); void set_while_body(HloComputation* while_body); + HloInstruction* while_init() const; + // Gets/sets the true and false HloComputation for Conditional. The setters // should only be called by HloModule or HloComputation methods. // @@ -1257,6 +1272,7 @@ class HloInstruction { // superior. // Precondition: opcode must be kConvolution or kDot. const PrecisionConfig& precision_config() const; + PrecisionConfig* mutable_precision_config(); // Sets the debug metadata for this instruction. void set_metadata(const OpMetadata& metadata) { metadata_ = metadata; } @@ -1317,6 +1333,9 @@ class HloInstruction { // Delegates to HloConcatenateInstruction::concatenate_dimension. int64 concatenate_dimension() const; + // Delegates to HloGetDimensionSizeInstruction::dimension. + int64 dimension() const; + // Returns whether this instruction does a rank-2 transposition. bool IsRank2Transpose() const; @@ -1435,6 +1454,7 @@ class HloInstruction { // Delegates to HloAllReduceInstruction::all_reduce_id. absl::optional all_reduce_id() const; + void set_all_reduce_id(const absl::optional& all_reduce_id); // Returns data on the window in a windowed operation such as // convolution. @@ -1599,6 +1619,10 @@ class HloInstruction { const std::function& eq_computations) const; + // Generates a hash value specific to a particular type of an instruction. + // This function typically considers the inner root instruction. + virtual uint64 InnerHash() const; + // Creates an n-ary elementwise operation. static std::unique_ptr CreateNary( const Shape& shape, HloOpcode opcode, diff --git a/tensorflow/compiler/xla/service/hlo_instructions.cc b/tensorflow/compiler/xla/service/hlo_instructions.cc index 4c765aa375..1ea02cf9c0 100644 --- a/tensorflow/compiler/xla/service/hlo_instructions.cc +++ b/tensorflow/compiler/xla/service/hlo_instructions.cc @@ -370,6 +370,11 @@ HloAllReduceInstruction::HloAllReduceInstruction( AppendComputation(reduce_computation); } +void HloAllReduceInstruction::set_all_reduce_id( + const absl::optional& all_reduce_id) { + all_reduce_id_ = all_reduce_id; +} + HloInstructionProto HloAllReduceInstruction::ToProto() const { HloInstructionProto proto = HloCollectiveInstruction::ToProto(); // Proto3 is so sad. @@ -1367,6 +1372,10 @@ bool HloFusionInstruction::IdenticalSlowPath( other.fused_instructions_computation()); } +uint64 HloFusionInstruction::InnerHash() const { + return fused_instructions_computation()->Hash(); +} + std::unique_ptr HloFusionInstruction::CloneWithNewOperandsImpl( const Shape& shape, absl::Span new_operands, HloCloneContext* context) const { @@ -1610,7 +1619,7 @@ HloOutfeedInstruction::HloOutfeedInstruction(const Shape& outfeed_shape, HloInstructionProto HloOutfeedInstruction::ToProto() const { HloInstructionProto proto = HloInstruction::ToProto(); proto.set_outfeed_config(outfeed_config()); - *proto.mutable_outfeed_shape() = outfeed_shape(); + *proto.mutable_outfeed_shape() = outfeed_shape().ToProto(); return proto; } @@ -1862,7 +1871,7 @@ HloInstructionProto HloCustomCallInstruction::ToProto() const { if (layout_constrained()) { proto.set_constrain_layout(true); for (const Shape& shape : operand_shapes_with_layout_) { - *proto.add_operand_shapes_with_layout() = shape; + *proto.add_operand_shapes_with_layout() = shape.ToProto(); } } return proto; diff --git a/tensorflow/compiler/xla/service/hlo_instructions.h b/tensorflow/compiler/xla/service/hlo_instructions.h index d43a8973cc..b5c28137a1 100644 --- a/tensorflow/compiler/xla/service/hlo_instructions.h +++ b/tensorflow/compiler/xla/service/hlo_instructions.h @@ -252,6 +252,7 @@ class HloAllReduceInstruction : public HloCollectiveInstruction { } absl::optional all_reduce_id() const { return all_reduce_id_; } + void set_all_reduce_id(const absl::optional& all_reduce_id); // Returns a serialized representation of this instruction. HloInstructionProto ToProto() const override; @@ -742,6 +743,8 @@ class HloFusionInstruction : public HloInstruction { const HloInstruction& other, const std::function& eq_computations) const override; + uint64 InnerHash() const override; + // Implementation for non-common logic of CloneWithNewOperands. std::unique_ptr CloneWithNewOperandsImpl( const Shape& shape, absl::Span new_operands, @@ -954,6 +957,7 @@ class HloConvolutionInstruction : public HloInstruction { // information but it is presumed that the alternate lowering is strictly // superior. const PrecisionConfig& precision_config() const { return precision_config_; } + PrecisionConfig* mutable_precision_config() { return &precision_config_; } string ToCategory() const override; // Returns a serialized representation of this instruction. @@ -1325,6 +1329,7 @@ class HloDotInstruction : public HloInstruction { // information but it is presumed that the alternate lowering is strictly // superior. const PrecisionConfig& precision_config() const { return precision_config_; } + PrecisionConfig* mutable_precision_config() { return &precision_config_; } // Returns a serialized representation of this instruction. HloInstructionProto ToProto() const override; diff --git a/tensorflow/compiler/xla/service/hlo_lexer.h b/tensorflow/compiler/xla/service/hlo_lexer.h index 3e2f8bcd52..d6a2b292a3 100644 --- a/tensorflow/compiler/xla/service/hlo_lexer.h +++ b/tensorflow/compiler/xla/service/hlo_lexer.h @@ -20,6 +20,7 @@ limitations under the License. #include "absl/strings/string_view.h" #include "tensorflow/compiler/xla/service/hlo_token.h" +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/xla_data.pb.h" #include "tensorflow/core/platform/logging.h" diff --git a/tensorflow/compiler/xla/service/hlo_matchers.cc b/tensorflow/compiler/xla/service/hlo_matchers.cc index 5269cad94d..d28e79d41a 100644 --- a/tensorflow/compiler/xla/service/hlo_matchers.cc +++ b/tensorflow/compiler/xla/service/hlo_matchers.cc @@ -237,8 +237,4 @@ void PrintTo(const HloInstruction* inst, ::std::ostream* os) { *os << (inst ? inst->ToString() : "nullptr"); } -void PrintTo(HloInstruction* inst, ::std::ostream* os) { - PrintTo(const_cast(inst), os); -} - } // namespace xla diff --git a/tensorflow/compiler/xla/service/hlo_matchers.h b/tensorflow/compiler/xla/service/hlo_matchers.h index 170ec93a33..235efb19ce 100644 --- a/tensorflow/compiler/xla/service/hlo_matchers.h +++ b/tensorflow/compiler/xla/service/hlo_matchers.h @@ -385,7 +385,6 @@ std::vector Pointers(const Container& container) { // Tell GMock to print HloInstruction* by value, so error messages are nice. // Has to be in the same namespace as 'HloInstruction'. void PrintTo(const HloInstruction* inst, ::std::ostream* os); -void PrintTo(HloInstruction* inst, ::std::ostream* os); } // namespace xla diff --git a/tensorflow/compiler/xla/service/hlo_memory_scheduler.cc b/tensorflow/compiler/xla/service/hlo_memory_scheduler.cc index 234fcd266a..d2740bcce2 100644 --- a/tensorflow/compiler/xla/service/hlo_memory_scheduler.cc +++ b/tensorflow/compiler/xla/service/hlo_memory_scheduler.cc @@ -73,7 +73,7 @@ class ListScheduler { // Construct and return a memory-minimizing sequence of HLO instructions // containing the given HLO computation. static StatusOr Run( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& @@ -98,7 +98,7 @@ class ListScheduler { // comparison operators. using Priority = std::pair; - ListScheduler(const HloComputation& computation, + ListScheduler(HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& @@ -111,7 +111,7 @@ class ListScheduler { // instruction. An HLO instruction "uses" a LogicalBuffer if the // LogicalBuffer is in an operand of the instruction as indicated by // points-to analysis. - for (auto* instruction : computation.instructions()) { + for (auto* instruction : computation->instructions()) { absl::flat_hash_set instr_uses; for (auto* operand : instruction->operands()) { points_to_analysis.GetPointsToSet(operand).ForEachElement( @@ -126,13 +126,13 @@ class ListScheduler { // Create map containing the number of unscheduled uses (hlo instructions) // of each logical buffer. - for (auto* instruction : computation.instructions()) { + for (auto* instruction : computation->instructions()) { for (auto* buffer : points_to_analysis.GetBuffersDefinedByInstruction(instruction)) { unscheduled_use_count_[buffer] = 0; } } - for (auto* instruction : computation.instructions()) { + for (auto* instruction : computation->instructions()) { for (const LogicalBuffer* buffer : buffer_uses_.at(instruction)) { ++unscheduled_use_count_[buffer]; } @@ -141,7 +141,7 @@ class ListScheduler { // Buffers live out of the computation have an implicit use at the end of // the computation. for (const LogicalBuffer* live_out_buffer : - points_to_analysis.GetPointsToSet(computation.root_instruction()) + points_to_analysis.GetPointsToSet(computation->root_instruction()) .CreateFlattenedSet()) { ++unscheduled_use_count_[live_out_buffer]; } @@ -157,7 +157,7 @@ class ListScheduler { // HloInstruction, plus some cached metadata, saved for the purposes of making // BytesFreedIfScheduled fast. struct ReadyListEntry { - const HloInstruction* instruction; + HloInstruction* instruction; // The total size of all buffers defined by this instruction. int64 bytes_defined; @@ -171,7 +171,7 @@ class ListScheduler { }; // Creates a ReadyListEntry for the given instruction. - ReadyListEntry MakeReadyListEntry(const HloInstruction* instruction) { + ReadyListEntry MakeReadyListEntry(HloInstruction* instruction) { ReadyListEntry entry; entry.instruction = instruction; @@ -250,13 +250,13 @@ class ListScheduler { // Populate the ready list with instructions which have no operands or // control predecessors. absl::flat_hash_map unscheduled_pred_count; - for (auto* instruction : computation_.instructions()) { + for (auto* instruction : computation_->instructions()) { // TODO(b/34466113): Replace this and above with successors() or // predecessors() when these methods are added to HloInstruction. - for (const HloInstruction* user : instruction->users()) { + for (HloInstruction* user : instruction->users()) { unscheduled_pred_count[user]++; } - for (const HloInstruction* succ : instruction->control_successors()) { + for (HloInstruction* succ : instruction->control_successors()) { unscheduled_pred_count[succ]++; } } @@ -275,7 +275,7 @@ class ListScheduler { ready_instructions[inst] = it; }; - for (auto* instruction : computation_.instructions()) { + for (auto* instruction : computation_->instructions()) { if (instruction->operands().empty() && instruction->control_predecessors().empty()) { add_to_ready_queue(instruction); @@ -287,7 +287,7 @@ class ListScheduler { // schedule. auto best_it = ready_queue.end(); --best_it; - const HloInstruction* best = best_it->second.instruction; + HloInstruction* best = best_it->second.instruction; VLOG(2) << "Schedule instruction: " << best->ToShortString() << " Bytes freed: " << best_it->first.first; ready_queue.erase(best_it); @@ -348,13 +348,13 @@ class ListScheduler { } } } - CHECK_EQ(schedule.size(), computation_.instruction_count()); - CHECK_EQ(scheduled_instructions_.size(), computation_.instruction_count()); + CHECK_EQ(schedule.size(), computation_->instruction_count()); + CHECK_EQ(scheduled_instructions_.size(), computation_->instruction_count()); return schedule; } - const HloComputation& computation_; + HloComputation* computation_; const TuplePointsToAnalysis& points_to_analysis_; const LogicalBuffer::SizeFunction& size_function_; // Computations are analyzed in post-order. When scheduling an instruction @@ -386,13 +386,13 @@ int64 SumLogicalBufferSizes( } StatusOr ScheduleComputationHelper( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const MemorySchedulerAlgorithm& algorithm, const absl::flat_hash_map& memory_by_computation) { - VLOG(2) << "Computation: " << computation.name(); + VLOG(2) << "Computation: " << computation->name(); if (algorithm) { return algorithm(computation, points_to_analysis, size_function, memory_by_computation); @@ -404,17 +404,17 @@ StatusOr ScheduleComputationHelper( } // namespace StatusOr DFSMemoryScheduler( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& memory_by_computation) { // These variables are a hack to prevent overflows. int64 cumulative_total_size = 0; - int64 total_hlos = computation.parent()->instruction_count(); + int64 total_hlos = computation->parent()->instruction_count(); absl::flat_hash_map extra_users; absl::flat_hash_map total_sizes; - for (const HloInstruction* hlo : computation.MakeInstructionPostOrder()) { + for (const HloInstruction* hlo : computation->MakeInstructionPostOrder()) { if (ListScheduler::IgnoreInstruction(*hlo)) { extra_users[hlo] = 0; total_sizes[hlo] = 0; @@ -448,8 +448,8 @@ StatusOr DFSMemoryScheduler( total_sizes[hlo] = std::min(total_sizes[hlo], cumulative_total_size); extra_users[hlo] = std::min(extra_users[hlo], total_hlos); } - CHECK_EQ(extra_users.size(), computation.instruction_count()); - CHECK_EQ(total_sizes.size(), computation.instruction_count()); + CHECK_EQ(extra_users.size(), computation->instruction_count()); + CHECK_EQ(total_sizes.size(), computation->instruction_count()); // Construct a total order based on DFS post-order, visiting operands in // decreasing cumulative extra user order, and next by cumulative size, with a @@ -459,7 +459,7 @@ StatusOr DFSMemoryScheduler( sequence.push_back(hlo); return Status::OK(); }); - TF_RETURN_IF_ERROR(computation.AcceptWithOperandOrder( + TF_RETURN_IF_ERROR(computation->AcceptWithOperandOrder( &visitor, [&extra_users, &total_sizes](const HloInstruction* a, const HloInstruction* b) { if (extra_users[a] != extra_users[b]) { @@ -470,12 +470,12 @@ StatusOr DFSMemoryScheduler( } return a->name() < b->name(); })); - CHECK_EQ(sequence.size(), computation.instruction_count()); + CHECK_EQ(sequence.size(), computation->instruction_count()); return sequence; } // namespace xla StatusOr ListMemoryScheduler( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& @@ -485,16 +485,16 @@ StatusOr ListMemoryScheduler( } StatusOr PostOrderMemoryScheduler( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& memory_by_computation) { - return HloInstructionSequence(computation.MakeInstructionPostOrder()); + return HloInstructionSequence(computation->MakeInstructionPostOrder()); } StatusOr DefaultMemoryScheduler( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& @@ -513,7 +513,7 @@ StatusOr DefaultMemoryScheduler( memory_by_computation)); TF_ASSIGN_OR_RETURN(const int64 list_memory, HeapSimulator::MinimumMemoryForComputation( - computation, list_sequence, points_to_analysis, + *computation, list_sequence, points_to_analysis, size_function, &memory_by_computation)); VLOG(2) << "Min-memory list sequence: " << HumanReadableNumBytes(list_memory); @@ -522,7 +522,7 @@ StatusOr DefaultMemoryScheduler( size_function, memory_by_computation)); TF_ASSIGN_OR_RETURN(const int64 dfs_memory, HeapSimulator::MinimumMemoryForComputation( - computation, dfs_sequence, points_to_analysis, + *computation, dfs_sequence, points_to_analysis, size_function, &memory_by_computation)); VLOG(2) << "Min-memory dfs sequence: " << HumanReadableNumBytes(dfs_memory); @@ -532,7 +532,7 @@ StatusOr DefaultMemoryScheduler( memory_by_computation)); TF_ASSIGN_OR_RETURN(const int64 post_order_memory, HeapSimulator::MinimumMemoryForComputation( - computation, post_order_sequence, points_to_analysis, + *computation, post_order_sequence, points_to_analysis, size_function, &memory_by_computation)); VLOG(2) << "Min-memory post order sequence: " << HumanReadableNumBytes(post_order_memory); @@ -555,17 +555,17 @@ StatusOr DefaultMemoryScheduler( } StatusOr ScheduleModule( - const HloModule& module, const LogicalBuffer::SizeFunction& size_function, + HloModule* module, const LogicalBuffer::SizeFunction& size_function, const MemorySchedulerAlgorithm& algorithm) { - HloSchedule schedule(&module); + HloSchedule schedule(module); TF_ASSIGN_OR_RETURN(std::unique_ptr points_to_analysis, - TuplePointsToAnalysis::Run(&module)); + TuplePointsToAnalysis::Run(module)); absl::flat_hash_map memory_by_computation; - for (const auto* computation : module.MakeComputationPostOrder()) { + for (auto* computation : module->MakeComputationPostOrder()) { if (!computation->IsFusionComputation()) { TF_ASSIGN_OR_RETURN(HloInstructionSequence computation_sequence, ScheduleComputationHelper( - *computation, *points_to_analysis, size_function, + computation, *points_to_analysis, size_function, algorithm, memory_by_computation)); memory_by_computation[computation] = HeapSimulator::MinimumMemoryForComputation( @@ -583,11 +583,11 @@ StatusOr ScheduleModule( } StatusOr ScheduleComputation( - const HloComputation& computation, + HloComputation* computation, const LogicalBuffer::SizeFunction& size_function) { - CHECK(!computation.IsFusionComputation()); + CHECK(!computation->IsFusionComputation()); TF_ASSIGN_OR_RETURN(std::unique_ptr points_to_analysis, - TuplePointsToAnalysis::Run(computation.parent())); + TuplePointsToAnalysis::Run(computation->parent())); absl::flat_hash_map empty_map; return ScheduleComputationHelper(computation, *points_to_analysis, size_function, nullptr, empty_map); @@ -600,7 +600,7 @@ HloMemoryScheduler::HloMemoryScheduler( StatusOr HloMemoryScheduler::Run(HloModule* module) { TF_ASSIGN_OR_RETURN(HloSchedule schedule, - ScheduleModule(*module, size_function_, algorithm_)); + ScheduleModule(module, size_function_, algorithm_)); TF_RETURN_IF_ERROR(module->set_schedule(std::move(schedule))); return true; } diff --git a/tensorflow/compiler/xla/service/hlo_memory_scheduler.h b/tensorflow/compiler/xla/service/hlo_memory_scheduler.h index cca5dc4939..7227bfb27c 100644 --- a/tensorflow/compiler/xla/service/hlo_memory_scheduler.h +++ b/tensorflow/compiler/xla/service/hlo_memory_scheduler.h @@ -36,14 +36,14 @@ namespace xla { // that describes buffer aliasing, together with a target-specific size function // that maps a tensor's logical size to its padded size. typedef std::function( - const HloComputation&, const TuplePointsToAnalysis&, + HloComputation*, const TuplePointsToAnalysis&, const LogicalBuffer::SizeFunction&, const absl::flat_hash_map&)> MemorySchedulerAlgorithm; // List scheduler StatusOr ListMemoryScheduler( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& @@ -51,7 +51,7 @@ StatusOr ListMemoryScheduler( // DFS-order scheduler StatusOr DFSMemoryScheduler( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& @@ -59,7 +59,7 @@ StatusOr DFSMemoryScheduler( // Naive Post Order scheduler StatusOr PostOrderMemoryScheduler( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& @@ -69,7 +69,7 @@ StatusOr PostOrderMemoryScheduler( // and the DFS scheduler, and chooses whichever returns a lower min-memory, // not accounting for fragmentation. StatusOr DefaultMemoryScheduler( - const HloComputation& computation, + HloComputation* computation, const TuplePointsToAnalysis& points_to_analysis, const LogicalBuffer::SizeFunction& size_function, const absl::flat_hash_map& @@ -79,13 +79,13 @@ StatusOr DefaultMemoryScheduler( // the computation. size_function is the function returning the number of bytes // required for a LogicalBuffer. StatusOr ScheduleModule( - const HloModule& module, const LogicalBuffer::SizeFunction& size_function, + HloModule* module, const LogicalBuffer::SizeFunction& size_function, const MemorySchedulerAlgorithm& algorithm = {}); // Computes the schedule for a single computation. // Currently only used by the GPU backend. StatusOr ScheduleComputation( - const HloComputation& computation, + HloComputation* computation, const LogicalBuffer::SizeFunction& size_function); // A pass which schedules the HLO instructions in a module. The HloModule's diff --git a/tensorflow/compiler/xla/service/hlo_memory_scheduler_test.cc b/tensorflow/compiler/xla/service/hlo_memory_scheduler_test.cc index 984a6266ab..bc0d7e2bc0 100644 --- a/tensorflow/compiler/xla/service/hlo_memory_scheduler_test.cc +++ b/tensorflow/compiler/xla/service/hlo_memory_scheduler_test.cc @@ -65,7 +65,7 @@ TEST_F(HloSchedulingTest, LastUseScheduledFirst) { auto sub = builder.AddInstruction( HloInstruction::CreateBinary(vec, HloOpcode::kSubtract, add, negate)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); HloMemoryScheduler scheduler([](const BufferValue& buffer) { @@ -78,7 +78,7 @@ TEST_F(HloSchedulingTest, LastUseScheduledFirst) { TF_ASSERT_OK(module->schedule().Verify()); // Verify that all instructions are in the sequence. - const std::vector& sequence = + const std::vector& sequence = module->schedule().sequence(module->entry_computation()).instructions(); EXPECT_EQ(module->entry_computation()->instruction_count(), sequence.size()); @@ -124,9 +124,9 @@ ENTRY root { }; TF_ASSERT_OK_AND_ASSIGN( HloSchedule schedule, - ScheduleModule(*module, size_fn, ListMemoryScheduler)); + ScheduleModule(module.get(), size_fn, ListMemoryScheduler)); // Verify that all instructions are in the sequence. - const std::vector& sequence = + const std::vector& sequence = schedule.sequence(module->entry_computation()).instructions(); EXPECT_EQ(module->entry_computation()->instruction_count(), sequence.size()); @@ -172,15 +172,16 @@ TEST_F(HloSchedulingTest, TuplesAreAccountedCorrectly) { builder.AddInstruction(HloInstruction::CreateBinary(r1f32, HloOpcode::kAdd, tuple_elm, abs_abs2)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); TF_ASSERT_OK_AND_ASSIGN(HloSchedule schedule, - ScheduleModule(*module, - [](const BufferValue& buffer) { - return ShapeUtil::ByteSizeOf( - buffer.shape(), TUPLE_SIZE); - }, - ListMemoryScheduler)); + ScheduleModule( + module.get(), + [](const BufferValue& buffer) { + return ShapeUtil::ByteSizeOf(buffer.shape(), + TUPLE_SIZE); + }, + ListMemoryScheduler)); // Verify that all instructions are in the sequence. EXPECT_EQ(module->entry_computation()->instruction_count(), @@ -218,19 +219,19 @@ TEST_F(HloSchedulingTest, MultiOutputFusionAccountedCorrectly) { builder.AddInstruction( HloInstruction::CreateBinary(r1f32, HloOpcode::kAdd, tuple_elm, exp)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto* computation = module->AddEntryComputation(builder.Build()); auto fusion = computation->CreateFusionInstruction( {tuple, mul, add}, HloInstruction::FusionKind::kLoop); TF_ASSERT_OK_AND_ASSIGN(HloSchedule schedule, - ScheduleModule(*module, - [](const BufferValue& buffer) { - return ShapeUtil::ByteSizeOf( - buffer.shape(), 2); - }, - ListMemoryScheduler)); + ScheduleModule( + module.get(), + [](const BufferValue& buffer) { + return ShapeUtil::ByteSizeOf(buffer.shape(), 2); + }, + ListMemoryScheduler)); // Verify that all instructions are in the sequence. EXPECT_EQ(module->entry_computation()->instruction_count(), @@ -252,7 +253,7 @@ TEST_F(HloSchedulingTest, HeapSimulatorAccountsForSubcomputations) { HloInstruction::CreateParameter(0, r1f32, "cond_param")); HloInstruction* zero_vector = cond_builder.AddInstruction(HloInstruction::CreateConstant( - LiteralUtil::CreateR2({{0, 0, 0, 0}}))); + LiteralUtil::CreateR1({0, 0, 0, 0}))); cond_builder.AddInstruction(HloInstruction::CreateBinary( ShapeUtil::MakeShape(PRED, {}), HloOpcode::kNe, cond_param, zero_vector)); auto cond_computation = module->AddEmbeddedComputation(cond_builder.Build()); @@ -284,7 +285,7 @@ TEST_F(HloSchedulingTest, HeapSimulatorAccountsForSubcomputations) { }; TF_ASSERT_OK_AND_ASSIGN( HloSchedule schedule, - ScheduleModule(*module, size_fn, ListMemoryScheduler)); + ScheduleModule(module.get(), size_fn, ListMemoryScheduler)); // Verify that all instructions are in the sequence. auto entry_computation = module->entry_computation(); EXPECT_EQ(module->entry_computation()->instruction_count(), diff --git a/tensorflow/compiler/xla/service/hlo_module.cc b/tensorflow/compiler/xla/service/hlo_module.cc index 14bf17f4be..fe8371384c 100644 --- a/tensorflow/compiler/xla/service/hlo_module.cc +++ b/tensorflow/compiler/xla/service/hlo_module.cc @@ -240,8 +240,10 @@ HloModuleProto HloModule::ToProto() const { *proto.mutable_schedule() = schedule().ToProto().ValueOrDie(); } *proto.mutable_host_program_shape() = - entry_computation_layout().ComputeProgramShape(); + entry_computation_layout().ComputeProgramShape().ToProto(); *proto.mutable_input_output_alias() = input_output_alias_config().ToProto(); + *proto.mutable_dynamic_parameter_binding() = + dynamic_parameter_binding().ToProto(); return proto; } @@ -255,7 +257,7 @@ StatusOr> HloModule::CreateFromProto( // the entry parameters and root. TF_RET_CHECK(proto.has_host_program_shape()) << "No program shape found in the proto"; - const auto& expected_program_shape = proto.host_program_shape(); + ProgramShape expected_program_shape(proto.host_program_shape()); TF_RET_CHECK(expected_program_shape.parameters_size() == module_config.entry_computation_layout().parameter_count()); for (int i = 0; i < expected_program_shape.parameters_size(); ++i) { @@ -325,6 +327,10 @@ StatusOr> HloModule::CreateFromProto( // Because we didn't uniquify the names or the ids, double-check that the // instruction and computation names and ids are unique from the proto. + TF_ASSIGN_OR_RETURN(module->dynamic_parameter_binding_, + DynamicParameterBinding::CreateFromProto( + proto.dynamic_parameter_binding())); + absl::flat_hash_set computation_names; absl::flat_hash_set instruction_names; absl::flat_hash_set computation_ids; @@ -363,9 +369,9 @@ StatusOr HloModule::CreateModuleConfigFromProto( const HloModuleProto& module, const DebugOptions& debug_options) { TF_RET_CHECK(module.has_host_program_shape()) << "No program shape found in the proto"; - const auto& program_shape = module.host_program_shape(); + ProgramShape program_shape(module.host_program_shape()); - HloModuleConfig module_config(program_shape); + HloModuleConfig module_config(ProgramShape{program_shape}); module_config.set_debug_options(debug_options); // The module config is constructed with default layouts regardless of what is diff --git a/tensorflow/compiler/xla/service/hlo_module.h b/tensorflow/compiler/xla/service/hlo_module.h index 8a1f999e3a..7b9cbf9a53 100644 --- a/tensorflow/compiler/xla/service/hlo_module.h +++ b/tensorflow/compiler/xla/service/hlo_module.h @@ -28,6 +28,7 @@ limitations under the License. #include "absl/types/optional.h" #include "absl/types/span.h" #include "tensorflow/compiler/xla/iterator_util.h" +#include "tensorflow/compiler/xla/service/dynamic_parameter_binding.h" #include "tensorflow/compiler/xla/service/hlo.pb.h" #include "tensorflow/compiler/xla/service/hlo_clone_context.h" #include "tensorflow/compiler/xla/service/hlo_computation.h" @@ -103,11 +104,7 @@ class HloModule { HloCloneContext* context = nullptr); // Return a pointer to the entry computation of the module. - const HloComputation* entry_computation() const { - CHECK_NE(nullptr, entry_computation_); - return entry_computation_; - } - HloComputation* entry_computation() { + HloComputation* entry_computation() const { CHECK_NE(nullptr, entry_computation_); return entry_computation_; } @@ -135,6 +132,12 @@ class HloModule { return config_.entry_computation_layout(); } + // Generates a hash value of an HLO module. Hash considers + // information on opcode, shape, operands, and typically a root instruction. + // This function returns the same hash value for equivalent HLO modules, + // with respect to HloInstruction::Identical() method. + uint64 Hash() const { return entry_computation()->Hash(); } + // Gets the computations in this module. // // Returns a view of HloComputation*s, so you can iterate over this in the @@ -232,6 +235,16 @@ class HloModule { return input_output_alias_config_; } + // DynamicParameterBinding holds the list of bindings that indicates which + // parameter dimensions are dynamic and which parameters represent their + // runtime value. + DynamicParameterBinding& dynamic_parameter_binding() { + return dynamic_parameter_binding_; + } + const DynamicParameterBinding& dynamic_parameter_binding() const { + return dynamic_parameter_binding_; + } + // Returns an id that is unique to this module across all modules created over // the lifetime of this process. int unique_id() const { return unique_id_; } @@ -285,6 +298,9 @@ class HloModule { // alias_config indicates the alias information of input/output buffers that // are expected from the module. HloInputOutputAliasConfig input_output_alias_config_; + + // Bindings for dynamic parameter mapping. + DynamicParameterBinding dynamic_parameter_binding_; }; } // namespace xla diff --git a/tensorflow/compiler/xla/service/hlo_module_test.cc b/tensorflow/compiler/xla/service/hlo_module_test.cc index 3ae67e4e5e..620cb7e01a 100644 --- a/tensorflow/compiler/xla/service/hlo_module_test.cc +++ b/tensorflow/compiler/xla/service/hlo_module_test.cc @@ -63,7 +63,7 @@ class HloModuleTest : public HloTestBase { TEST_F(HloModuleTest, OneComputationPostOrder) { // Create a module with a single computation. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(CreateConstantComputation()); EXPECT_THAT(module->MakeComputationPostOrder(), @@ -72,7 +72,7 @@ TEST_F(HloModuleTest, OneComputationPostOrder) { TEST_F(HloModuleTest, TwoComputationsPostOrder) { // Create a module with two unconnected computations. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation1 = module->AddEntryComputation(CreateConstantComputation()); auto computation2 = module->AddEmbeddedComputation(CreateConstantComputation()); @@ -88,7 +88,7 @@ TEST_F(HloModuleTest, TwoComputationsPostOrder) { TEST_F(HloModuleTest, CloneTest) { // Create and copy a module with a diamond call graph of computations. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation1 = module->AddEmbeddedComputation(CreateConstantComputation()); auto computation2 = @@ -111,7 +111,7 @@ TEST_F(HloModuleTest, CloneTest) { } TEST_F(HloModuleTest, CloneHasFusion) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); // Create the fused computation. HloComputation* fused_computation; @@ -154,7 +154,7 @@ TEST_F(HloModuleTest, CloneHasFusion) { TEST_F(HloModuleTest, DiamondComputationsPostOrder) { // Create a module with a diamond call graph of computations. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation1 = module->AddEmbeddedComputation(CreateConstantComputation()); auto computation2 = @@ -174,7 +174,7 @@ TEST_F(HloModuleTest, DiamondComputationsPostOrder) { TEST_F(HloModuleTest, LargeConstantToString) { // Create a module with a single computation. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto builder = HloComputation::Builder("Constant"); std::vector values(16, 42.0); builder.AddInstruction( @@ -194,8 +194,8 @@ TEST_F(HloModuleTest, LargeConstantToString) { } TEST_F(HloModuleTest, UniqueModuleId) { - auto module_a = CreateNewUnverifiedModule(); - auto module_b = CreateNewUnverifiedModule(); + auto module_a = CreateNewVerifiedModule(); + auto module_b = CreateNewVerifiedModule(); EXPECT_NE(module_a->unique_id(), module_b->unique_id()); } diff --git a/tensorflow/compiler/xla/service/hlo_opcode.h b/tensorflow/compiler/xla/service/hlo_opcode.h index 70c7d70b41..127cfd165a 100644 --- a/tensorflow/compiler/xla/service/hlo_opcode.h +++ b/tensorflow/compiler/xla/service/hlo_opcode.h @@ -47,6 +47,8 @@ namespace xla { #define HLO_OPCODE_LIST(V) \ V(kAbs, "abs") \ V(kAdd, "add") \ + V(kAddDependency, "add-dependency") \ + V(kAfterAll, "after-all", kHloOpcodeIsVariadic) \ V(kAllToAll, "all-to-all") \ V(kAtan2, "atan2") \ V(kBatchNormGrad, "batch-norm-grad") \ @@ -84,7 +86,6 @@ namespace xla { V(kGather, "gather") \ V(kGe, "greater-than-or-equal-to", kHloOpcodeIsComparison) \ V(kGetDimensionSize, "get-dimension-size") \ - V(kAfterAll, "after-all", kHloOpcodeIsVariadic) \ V(kGetTupleElement, "get-tuple-element") \ V(kGt, "greater-than", kHloOpcodeIsComparison) \ V(kImag, "imag") \ diff --git a/tensorflow/compiler/xla/service/hlo_ordering.cc b/tensorflow/compiler/xla/service/hlo_ordering.cc index f5f99bece1..ca6a154809 100644 --- a/tensorflow/compiler/xla/service/hlo_ordering.cc +++ b/tensorflow/compiler/xla/service/hlo_ordering.cc @@ -356,8 +356,7 @@ void SequentialHloOrdering::Initialize() { // Create a map from instruction to its order position. TF_DCHECK_OK(schedule_.Verify()); for (const auto& computation_sequence : schedule_.sequences()) { - const std::vector& order = - computation_sequence.second.instructions(); + const auto& order = computation_sequence.second.instructions(); for (int i = 0; i < order.size(); ++i) { InsertOrDie(&order_position_, order[i], i); } diff --git a/tensorflow/compiler/xla/service/hlo_ordering_test.cc b/tensorflow/compiler/xla/service/hlo_ordering_test.cc index 2ab8aa57f6..3ca77e60cd 100644 --- a/tensorflow/compiler/xla/service/hlo_ordering_test.cc +++ b/tensorflow/compiler/xla/service/hlo_ordering_test.cc @@ -53,7 +53,7 @@ TEST_F(HloOrderingTest, InstructionsInDifferentComputations) { // %c = Constant(42.0f) // // This results in a diamond-shaped callgraph. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape scalar_shape = ShapeUtil::MakeShape(xla::F32, {}); auto builder_c = HloComputation::Builder("C"); @@ -126,7 +126,7 @@ TEST_F(HloOrderingTest, InstructionsInWhileComputations) { // %constant = Constant(1.0) // return While(%constant, body, condition) // - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape scalar_shape = ShapeUtil::MakeShape(xla::F32, {}); auto body_builder = HloComputation::Builder("body"); @@ -176,7 +176,7 @@ TEST_F(HloOrderingTest, InstructionsInWhileComputations) { TEST_F(HloOrderingTest, ParametersDefinedBeforeOthers) { // Entry parameter should always be defined before other instruction. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape scalar_shape = ShapeUtil::MakeShape(xla::F32, {}); auto builder = HloComputation::Builder(TestName()); auto constant = builder.AddInstruction( @@ -209,7 +209,7 @@ TEST_F(HloOrderingTest, ValuesInWhileComputations) { // %while = While(%constant, body, condition) // %add = Add(%constant, %while) // - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape scalar_shape = ShapeUtil::MakeShape(xla::F32, {}); auto body_builder = HloComputation::Builder("body"); @@ -407,7 +407,7 @@ TEST_F(HloOrderingTest, // %dead = Constant(123.0) // // %root should interfere with %dead. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape scalar_shape = ShapeUtil::MakeShape(xla::F32, {}); auto builder = HloComputation::Builder(TestName()); @@ -455,7 +455,7 @@ TEST_F(HloOrderingTest, // ROOT %call = call({%c}), subcomputation // // %root should interfere with %dead. - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); const Shape scalar_shape = ShapeUtil::MakeShape(xla::F32, {}); auto subbuilder = HloComputation::Builder(TestName() + ".sub"); diff --git a/tensorflow/compiler/xla/service/hlo_parser.cc b/tensorflow/compiler/xla/service/hlo_parser.cc index 4390145c6b..9b5bb5d0bd 100644 --- a/tensorflow/compiler/xla/service/hlo_parser.cc +++ b/tensorflow/compiler/xla/service/hlo_parser.cc @@ -47,11 +47,11 @@ const double kF16max = 65504; // Creates and returns a schedule created using the order of the instructions in // the HloComputation::instructions() vectors in the module. -HloSchedule ScheduleFromInstructionOrder(const HloModule* module) { +HloSchedule ScheduleFromInstructionOrder(HloModule* module) { HloSchedule schedule(module); - for (const HloComputation* computation : module->computations()) { + for (HloComputation* computation : module->computations()) { if (!computation->IsFusionComputation()) { - for (const HloInstruction* instruction : computation->instructions()) { + for (HloInstruction* instruction : computation->instructions()) { schedule.GetOrCreateSequence(computation).push_back(instruction); } } @@ -850,6 +850,15 @@ bool HloParser::ParseInstructionRhs(HloComputation::Builder* builder, } break; } + case HloOpcode::kAddDependency: { + if (!ParseOperands(&operands, /*expected_size=*/2) || + !ParseAttributes(attrs)) { + return false; + } + instruction = builder->AddInstruction( + HloInstruction::CreateAddDependency(operands[0], operands[1])); + break; + } case HloOpcode::kSort: { optional> dimensions; attrs["dimensions"] = {/*required=*/true, AttrTy::kBracedInt64List, diff --git a/tensorflow/compiler/xla/service/hlo_parser_test.cc b/tensorflow/compiler/xla/service/hlo_parser_test.cc index c59bdc0a0b..ab71f011ac 100644 --- a/tensorflow/compiler/xla/service/hlo_parser_test.cc +++ b/tensorflow/compiler/xla/service/hlo_parser_test.cc @@ -21,7 +21,8 @@ limitations under the License. #include "absl/strings/string_view.h" #include "tensorflow/compiler/xla/service/hlo_casting_utils.h" #include "tensorflow/compiler/xla/service/hlo_instructions.h" -#include "tensorflow/compiler/xla/service/hlo_matchers.h" +#include "tensorflow/compiler/xla/service/pattern_matcher.h" +#include "tensorflow/compiler/xla/service/pattern_matcher_gmock.h" #include "tensorflow/compiler/xla/window_util.h" #include "tensorflow/core/lib/core/status_test_util.h" #include "tensorflow/core/platform/test.h" @@ -29,7 +30,7 @@ limitations under the License. namespace xla { namespace { -namespace op = ::xla::testing::opcode_matchers; +namespace m = ::xla::match; using absl::string_view; struct TestData { @@ -195,7 +196,7 @@ ENTRY %add_constants () -> f32[] { R"(HloModule TupleConstant_module ENTRY %TupleConstant.v1 () -> (f32[2,1], f32[2]) { - ROOT %constant = (f32[2,1]{1,0}, f32[2]{0}) constant((f32[2,1], f32[2]) ( f32[2,1] { { 1 }, { 2 } }, {2, 42} )) + ROOT %constant = (f32[2,1]{1,0}, f32[2]{0}) constant((f32[2,1], f32[2]) ( f32[2,1] { {1}, {2} }, {2, 42} )) } )" @@ -587,7 +588,7 @@ ENTRY %DynamicUpdateSlice.v4 (input: s32[1,1,25,1], update: s32[1,1,2,1], start_ R"(HloModule BasicTraining_module ENTRY %BasicTraining.v4 () -> (f32[2,2,1,2], f32[2], f32[2]) { - %constant = f32[2,2,1,2]{3,2,1,0} constant(f32[2,2,1,2] { { /*i0=0*/ { /*i1=0*/ {1, 2} }, { /*i1=1*/ {3, 4} } }, { /*i0=1*/ { /*i1=0*/ {5, 6} }, { /*i1=1*/ {7, 8} } } }) + %constant = f32[2,2,1,2]{3,2,1,0} constant(f32[2,2,1,2] { { /*i0=0*/ { /*i1=0*/ { 1, 2 } }, { /*i1=1*/ { 3, 4 } } }, { /*i0=1*/ { /*i1=0*/ { 5, 6 } }, { /*i1=1*/ { 7, 8 } } } }) %constant.1 = f32[2]{0} constant({2, 3}) %constant.2 = f32[2]{0} constant({1, 2}) ROOT %batch-norm-training = (f32[2,2,1,2]{3,2,1,0}, f32[2]{0}, f32[2]{0}) batch-norm-training(f32[2,2,1,2]{3,2,1,0} %constant, f32[2]{0} %constant.1, f32[2]{0} %constant.2), epsilon=0.001, feature_index=3 @@ -1241,7 +1242,38 @@ ENTRY Sort { } )" + }, +// AfterAll with multiple operands +{ +"AfterAllWithMultipleOperands", +R"(HloModule AfterAllWithMultipleOperands + +ENTRY AfterAllWithMultipleOperands { + p0 = f32[] parameter(0) + token0 = token[] after-all() + token1 = token[] after-all() + ROOT after-all = token[] after-all(p0, token0, token1) } + +)" +}, +// AddDependency +// A dependency chain is created from 'neg' to 'exp' using tokens. +{ +"AddDependency", +R"(HloModule AddDependency + +ENTRY AddDependency { + p = f32[] parameter(0) + neg = f32[] negate(p) + token = token[] after-all(neg) + p_after_token = f32[] add-dependency(p, token) + exp = f32[] exponential(p_after_token) + ROOT sum = f32[] add(neg, exp) +} + +)" +}, }); // clang-format on } @@ -1862,7 +1894,8 @@ ENTRY ReduceR3ToR2 { )"; TF_ASSERT_OK_AND_ASSIGN(auto module, ParseHloString(original)); ASSERT_NE(module->entry_computation(), nullptr); - EXPECT_THAT(module->entry_computation()->root_instruction(), op::Reduce()); + EXPECT_THAT(module->entry_computation()->root_instruction(), + GmockMatch(m::Reduce())); } TEST_F(HloParserTest, ParseSharding) { @@ -1922,7 +1955,7 @@ TEST(HloParserSingleOpTest, SingleOp) { const HloComputation* computation = module->entry_computation(); ASSERT_NE(computation, nullptr); EXPECT_THAT(computation->root_instruction(), - op::Multiply(op::Parameter(0), op::Parameter(1))); + GmockMatch(m::Multiply(m::Parameter(0), m::Parameter(1)))); } TEST(HloParserSingleOpTest, SingleOpNoShapeProducesError) { @@ -1950,7 +1983,7 @@ TEST(HloParserSingleOpTest, SingleOpNoNames) { const HloComputation* computation = module->entry_computation(); ASSERT_NE(computation, nullptr); EXPECT_THAT(computation->root_instruction(), - op::Multiply(op::Parameter(0), op::Parameter(1))); + GmockMatch(m::Multiply(m::Parameter(0), m::Parameter(1)))); } TEST(HloParserSingleOpTest, CanonicalOp) { @@ -1959,7 +1992,7 @@ TEST(HloParserSingleOpTest, CanonicalOp) { const HloComputation* computation = module->entry_computation(); ASSERT_NE(computation, nullptr); EXPECT_THAT(computation->root_instruction(), - op::Multiply(op::Parameter(0), op::Parameter(1))); + GmockMatch(m::Multiply(m::Parameter(0), m::Parameter(1)))); EXPECT_EQ( computation->root_instruction()->ToString(HloPrintOptions::Canonical()), text); @@ -2013,7 +2046,11 @@ TEST(HloParserSingleOpTest, SingleOpWithNested) { const HloComputation* computation = module->entry_computation(); ASSERT_NE(computation, nullptr); EXPECT_THAT(computation->root_instruction(), - op::Fusion(op::Parameter(0), op::Parameter(1))); + GmockMatch(m::Op() + .WithOpcode(HloOpcode::kFusion) + .WithNumOperands(2) + .WithOperand(0, m::Parameter(0)) + .WithOperand(1, m::Parameter(1)))); } TEST(HloParserSingleOpTest, SingleOpWithNested_DoesNotExist) { @@ -2057,7 +2094,7 @@ TEST(HloParserSingleOpTest, ConvolutionTrivialFeatureGroupCount) { const HloComputation* computation = module->entry_computation(); ASSERT_NE(computation, nullptr); EXPECT_THAT(computation->root_instruction(), - op::Convolution(op::Parameter(0), op::Parameter(1))); + GmockMatch(m::Convolution(m::Parameter(0), m::Parameter(1)))); auto* convolution = Cast(computation->root_instruction()); EXPECT_EQ(convolution->feature_group_count(), 1); @@ -2121,8 +2158,10 @@ ENTRY %axpy.v5 (alpha: f32[], x: f32[2,4], y: f32[2,4]) -> f32[2,4] { module->schedule().is_computation_scheduled(module->entry_computation())); EXPECT_THAT( module->schedule().sequence(module->entry_computation()).instructions(), - ::testing::ElementsAre(op::Parameter(), op::Broadcast(), op::Parameter(), - op::Multiply(), op::Parameter(), op::Add())); + ::testing::ElementsAre( + GmockMatch(m::Parameter()), GmockMatch(m::Broadcast()), + GmockMatch(m::Parameter()), GmockMatch(m::Multiply()), + GmockMatch(m::Parameter()), GmockMatch(m::Add()))); } TEST_F(HloParserTest, IsScheduledIsTrueDifferentOrder) { @@ -2148,8 +2187,10 @@ ENTRY %axpy.v5 (alpha: f32[], x: f32[2,4], y: f32[2,4]) -> f32[2,4] { module->schedule().is_computation_scheduled(module->entry_computation())); EXPECT_THAT( module->schedule().sequence(module->entry_computation()).instructions(), - ::testing::ElementsAre(op::Parameter(), op::Parameter(), op::Parameter(), - op::Broadcast(), op::Multiply(), op::Add())); + ::testing::ElementsAre( + GmockMatch(m::Parameter()), GmockMatch(m::Parameter()), + GmockMatch(m::Parameter()), GmockMatch(m::Broadcast()), + GmockMatch(m::Multiply()), GmockMatch(m::Add()))); } TEST_F(HloParserTest, CustomCallWrongNumberofOperandConstraints) { diff --git a/tensorflow/compiler/xla/service/hlo_proto_util.cc b/tensorflow/compiler/xla/service/hlo_proto_util.cc index cf33668f5b..981d06ce10 100644 --- a/tensorflow/compiler/xla/service/hlo_proto_util.cc +++ b/tensorflow/compiler/xla/service/hlo_proto_util.cc @@ -48,7 +48,7 @@ StatusOr> CreateModuleFromProto( return std::move(module); } -StatusOr> EntryComputationParameterShapes( +StatusOr> EntryComputationParameterShapes( const HloProto& hlo_proto) { if (!hlo_proto.has_hlo_module()) { return NotFound("HloProto missing HloModuleProto."); @@ -57,15 +57,16 @@ StatusOr> EntryComputationParameterShapes( return NotFound("HloProto missing program shape."); } - std::vector parameter_shapes; + std::vector parameter_shapes; const auto& program_shape = hlo_proto.hlo_module().host_program_shape(); - for (const Shape& shape : program_shape.parameters()) { + for (const ShapeProto& shape : program_shape.parameters()) { parameter_shapes.push_back(&shape); } return parameter_shapes; } -StatusOr EntryComputationOutputShape(const HloProto& hlo_proto) { +StatusOr EntryComputationOutputShape( + const HloProto& hlo_proto) { if (!hlo_proto.has_hlo_module()) { return NotFound("HloProto missing HloModuleProto."); } diff --git a/tensorflow/compiler/xla/service/hlo_proto_util.h b/tensorflow/compiler/xla/service/hlo_proto_util.h index 1db82dd6fc..31ea2aaffd 100644 --- a/tensorflow/compiler/xla/service/hlo_proto_util.h +++ b/tensorflow/compiler/xla/service/hlo_proto_util.h @@ -43,12 +43,13 @@ StatusOr> CreateModuleFromProto( // Returns the shapes of the parameters of the entry computation. Shape pointers // refer to shapes inside of the given HloProto. -StatusOr> EntryComputationParameterShapes( +StatusOr> EntryComputationParameterShapes( const HloProto& hlo_proto); // Returns the shape of the output of the entry computation. The shape pointer // refers to the output shape inside of the given HloProto. -StatusOr EntryComputationOutputShape(const HloProto& hlo_proto); +StatusOr EntryComputationOutputShape( + const HloProto& hlo_proto); } // namespace xla diff --git a/tensorflow/compiler/xla/service/hlo_rematerialization.cc b/tensorflow/compiler/xla/service/hlo_rematerialization.cc index 49e46ecd00..48add75523 100644 --- a/tensorflow/compiler/xla/service/hlo_rematerialization.cc +++ b/tensorflow/compiler/xla/service/hlo_rematerialization.cc @@ -130,10 +130,10 @@ using ItemList = absl::InlinedVector; // before arbitrary elements. class InstructionList { public: - explicit InstructionList(const std::vector& order) { + explicit InstructionList(const HloInstructionSequence& order) { int64 position = 0; Item* last = nullptr; - for (const HloInstruction* inst : order) { + for (HloInstruction* inst : order.instructions()) { // Add a new item to the linked list. Item* item = new Item; item->next = nullptr; @@ -151,7 +151,7 @@ class InstructionList { // to be monotonically increasing through the list, and so is still useful // for quickly(-ish) determining the order of arbitrary instructions in // the list. - item->instruction = const_cast(inst); + item->instruction = inst; item->position = position; position++; @@ -927,7 +927,7 @@ Item* PickRematerializationCandidate( StatusOr HloRematerialization::ComputePeakMemory( const HloComputation* computation, - const std::vector& order) const { + const HloInstructionSequence& order) const { InstructionList instruction_list(order); MemoryUsageTracker tracker(computation, size_function_, *points_to_analysis_, instruction_list); @@ -971,8 +971,7 @@ StatusOr HloRematerialization::RematerializeComputation( << HumanReadableNumBytes(computation_peak_memory_.at(computation)); CHECK(!ContainsKey(rematerialized_computations_, computation)); - InstructionList instruction_list( - schedule->sequence(computation).instructions()); + InstructionList instruction_list(schedule->sequence(computation)); MemoryUsageTracker memory_tracker(computation, size_function_, *points_to_analysis_, instruction_list); bool changed = false; @@ -1184,7 +1183,7 @@ StatusOr HloRematerialization::RematerializeComputation( sequence.clear(); for (auto* item = instruction_list.first(); item != nullptr; item = instruction_list.next(item)) { - const HloInstruction* instruction = item->instruction; + HloInstruction* instruction = item->instruction; sequence.push_back(instruction); } rematerialized_computations_.insert(computation); @@ -1235,10 +1234,8 @@ StatusOr HloRematerialization::Run(HloModule* module) { if (node.context() == CallContext::kSequential) { TF_ASSIGN_OR_RETURN( computation_peak_memory_[node.computation()], - ComputePeakMemory(node.computation(), - module->schedule() - .sequence(node.computation()) - .instructions())); + ComputePeakMemory(node.computation(), module->schedule().sequence( + node.computation()))); } return Status::OK(); }, diff --git a/tensorflow/compiler/xla/service/hlo_rematerialization.h b/tensorflow/compiler/xla/service/hlo_rematerialization.h index 70d83c04f0..a07d348041 100644 --- a/tensorflow/compiler/xla/service/hlo_rematerialization.h +++ b/tensorflow/compiler/xla/service/hlo_rematerialization.h @@ -87,9 +87,8 @@ class HloRematerialization : public HloModulePass { // peak memory is the maximum total size of all live HLO instruction values at // any program point. 'order' is the order in which the HLO instructions will // be emitted which is used to determine lifespans of HLO values. - StatusOr ComputePeakMemory( - const HloComputation* computation, - const std::vector& order) const; + StatusOr ComputePeakMemory(const HloComputation* computation, + const HloInstructionSequence& order) const; // Returns the peak memory usage of the called computations for the given // instruction. Zero is returned if the instruction calls no computations. diff --git a/tensorflow/compiler/xla/service/hlo_runner.cc b/tensorflow/compiler/xla/service/hlo_runner.cc index 3f0ca342b4..5a9b820a9d 100644 --- a/tensorflow/compiler/xla/service/hlo_runner.cc +++ b/tensorflow/compiler/xla/service/hlo_runner.cc @@ -205,6 +205,40 @@ StatusOr HloRunner::ExecuteWithDeviceBuffers( /*profile=*/profile); } +StatusOr HloRunner::ExecuteWithDeviceBuffers( + std::unique_ptr executable, + const absl::Span arguments, + ExecutionProfile* profile) { + // Get service run options. + se::Stream stream(backend().default_stream_executor()); + stream.Init(); + ServiceExecutableRunOptions service_run_options = + GetServiceRunOptionsForDevice(backend().default_device_ordinal(), &stream, + nullptr); + + TF_ASSIGN_OR_RETURN( + ScopedShapedBuffer retval, + executable->ExecuteOnStreamWrapper(&service_run_options, + /*profile=*/profile, arguments)); + TF_RETURN_IF_ERROR(stream.BlockHostUntilDone()); + return std::move(retval); +} + +StatusOr HloRunner::ExecuteWithDeviceBuffers( + std::unique_ptr executable, + const absl::Span arguments, + ExecutionProfile* profile) { + std::vector argument_pointers; + argument_pointers.reserve(arguments.size()); + for (const auto& argument : arguments) { + argument_pointers.push_back(&argument); + } + return ExecuteWithDeviceBuffers( + /*executable=*/std::move(executable), + /*arguments=*/argument_pointers, + /*profile=*/profile); +} + StatusOr> HloRunner::ExecuteReplicated( std::unique_ptr module, const ReplicatedExecuteOptions& options) { diff --git a/tensorflow/compiler/xla/service/hlo_runner.h b/tensorflow/compiler/xla/service/hlo_runner.h index 2e934bf66a..bb792cf8c9 100644 --- a/tensorflow/compiler/xla/service/hlo_runner.h +++ b/tensorflow/compiler/xla/service/hlo_runner.h @@ -136,6 +136,21 @@ class HloRunner { const absl::Span arguments, bool run_hlo_passes = true, ExecutionProfile* profile = nullptr); + StatusOr ExecuteWithDeviceBuffers( + std::unique_ptr executable, + const absl::Span arguments, + ExecutionProfile* profile = nullptr); + + StatusOr ExecuteWithDeviceBuffers( + std::unique_ptr executable, + const absl::Span arguments, + ExecutionProfile* profile = nullptr); + + // Creates an executable object given an HLO module. If run_hlo_passes is + // true, the HLO passes will be run as part of compilation. + StatusOr> CreateExecutable( + std::unique_ptr module, bool run_hlo_passes); + // Executes a given HLO module into a set of replicas, and returns a map // with the replica number as key, and the corresponding returned literal as // value. @@ -152,11 +167,6 @@ class HloRunner { const Backend& backend() const; private: - // Creates an executable object given an HLO module. If run_hlo_passes is - // true, the HLO passes will be run before. - StatusOr> CreateExecutable( - std::unique_ptr module, bool run_hlo_passes); - // Creates a ServiceExecutableRunOptions object to configure a run on device, // using the provided stream object. If device_assignment is not nullptr, it // will be used to configure the replication parameters. Replicated executions diff --git a/tensorflow/compiler/xla/service/hlo_schedule.cc b/tensorflow/compiler/xla/service/hlo_schedule.cc index a5780b7551..8f6eb974c5 100644 --- a/tensorflow/compiler/xla/service/hlo_schedule.cc +++ b/tensorflow/compiler/xla/service/hlo_schedule.cc @@ -46,8 +46,8 @@ namespace xla { << "No computation exists in HLO module with id " << computation_id; const HloComputation* computation = comp_it->second; - absl::flat_hash_map id_to_instruction; - for (const HloInstruction* instruction : computation->instructions()) { + absl::flat_hash_map id_to_instruction; + for (HloInstruction* instruction : computation->instructions()) { id_to_instruction[instruction->unique_id()] = instruction; } @@ -81,9 +81,8 @@ StatusOr HloSchedule::ToProto() const { return std::move(proto); } -void HloSchedule::set_sequence( - const HloComputation* computation, - absl::Span sequence) { +void HloSchedule::set_sequence(const HloComputation* computation, + absl::Span sequence) { set_sequence(computation, HloInstructionSequence(sequence)); } @@ -114,8 +113,8 @@ Status HloSchedule::UpdateComputationSchedule( const HloComputation* computation) { // Map from unique ID to HloInstruction pointer for instructions in the // computation. - absl::flat_hash_map id_to_instruction; - for (const HloInstruction* instruction : computation->instructions()) { + absl::flat_hash_map id_to_instruction; + for (HloInstruction* instruction : computation->instructions()) { InsertOrDie(&id_to_instruction, instruction->unique_id(), instruction); } @@ -128,7 +127,7 @@ Status HloSchedule::UpdateComputationSchedule( // Map from HloInstruction X to newly added instructions (instruction is in // computation, but not in schedule) which use X. If an instruction is not in // the map, then it has no users which are newly added instructions. - absl::flat_hash_map> + absl::flat_hash_map> new_instruction_uses; // For each newly added instruction, this is the count of the instruction's @@ -138,9 +137,9 @@ Status HloSchedule::UpdateComputationSchedule( // Create a worklist of newly added instructions which are ready to be added // to the schedule. Initialize worklist with those that have zero operands. - std::queue worklist; + std::queue worklist; - for (const HloInstruction* instruction : computation->instructions()) { + for (HloInstruction* instruction : computation->instructions()) { if (ids_in_schedule.count(instruction->unique_id()) == 0) { // This is a newly added instruction which is not in the schedule. if (instruction->operands().empty()) { @@ -161,17 +160,17 @@ Status HloSchedule::UpdateComputationSchedule( // Lambda which schedules all instructions on the worklist. auto schedule_worklist = [&]() { while (!worklist.empty()) { - const HloInstruction* instruction = worklist.front(); + HloInstruction* instruction = worklist.front(); worklist.pop(); new_sequence.push_back(instruction); - std::vector* new_users = + std::vector* new_users = tensorflow::gtl::FindOrNull(new_instruction_uses, instruction); if (new_users != nullptr) { // This just-scheduled instruction has users which are newly added to // the module. Update the number of unscheduled operands and push the // newly added instruction to the worklist if it is ready to // schedule. - for (const HloInstruction* new_user : *new_users) { + for (HloInstruction* new_user : *new_users) { unscheduled_operand_count.at(new_user)--; CHECK_GE(unscheduled_operand_count.at(new_user), 0); if (unscheduled_operand_count.at(new_user) == 0) { diff --git a/tensorflow/compiler/xla/service/hlo_schedule.h b/tensorflow/compiler/xla/service/hlo_schedule.h index 0a714101ee..486ddbf499 100644 --- a/tensorflow/compiler/xla/service/hlo_schedule.h +++ b/tensorflow/compiler/xla/service/hlo_schedule.h @@ -35,14 +35,14 @@ class HloInstructionSequence { public: HloInstructionSequence() = default; explicit HloInstructionSequence( - absl::Span instructions) { - for (const HloInstruction* instruction : instructions) { + absl::Span instructions) { + for (HloInstruction* instruction : instructions) { push_back(instruction); } } // Adds the instruction to the end of the sequence. - void push_back(const HloInstruction* instruction) { + void push_back(HloInstruction* instruction) { instruction_sequence_.push_back(instruction); id_sequence_.push_back(instruction->unique_id()); } @@ -56,7 +56,7 @@ class HloInstructionSequence { int64 size() const { return instruction_sequence_.size(); } // Returns the sequence of HLO instructions. - const std::vector& instructions() const { + const std::vector& instructions() const { return instruction_sequence_; } @@ -65,7 +65,7 @@ class HloInstructionSequence { private: // The sequence as HloInstructions. - std::vector instruction_sequence_; + std::vector instruction_sequence_; // The sequence of HLO instructions, represented by their unique IDs. The // sequence is stored as both HloInstructions and unique IDs because the @@ -98,7 +98,7 @@ class HloSchedule { // Sets the sequence for the given computation to the given sequence. void set_sequence(const HloComputation* computation, - absl::Span sequence); + absl::Span sequence); void set_sequence(const HloComputation* computation, HloInstructionSequence sequence); diff --git a/tensorflow/compiler/xla/service/hlo_schedule_test.cc b/tensorflow/compiler/xla/service/hlo_schedule_test.cc index 1424569ac1..0e56e6f760 100644 --- a/tensorflow/compiler/xla/service/hlo_schedule_test.cc +++ b/tensorflow/compiler/xla/service/hlo_schedule_test.cc @@ -56,10 +56,10 @@ ENTRY main { ParseHloString(module_str)); TF_ASSERT_OK_AND_ASSIGN( HloSchedule schedule, - ScheduleModule(*module, [](const BufferValue& buffer) { + ScheduleModule(module.get(), [](const BufferValue& buffer) { return ShapeUtil::ByteSizeOf(buffer.shape()); })); - const std::vector& entry_schedule = + const auto& entry_schedule = schedule.sequence(module->entry_computation()).instructions(); EXPECT_EQ(entry_schedule.size(), 6); @@ -90,7 +90,7 @@ ENTRY main { ParseHloString(module_str)); TF_ASSERT_OK_AND_ASSIGN( HloSchedule schedule, - ScheduleModule(*module, [](const BufferValue& buffer) { + ScheduleModule(module.get(), [](const BufferValue& buffer) { return ShapeUtil::ByteSizeOf(buffer.shape()); })); @@ -139,7 +139,7 @@ ENTRY main { ParseHloString(module_str)); TF_ASSERT_OK_AND_ASSIGN( HloSchedule schedule, - ScheduleModule(*module, [](const BufferValue& buffer) { + ScheduleModule(module.get(), [](const BufferValue& buffer) { return ShapeUtil::ByteSizeOf(buffer.shape()); })); @@ -183,7 +183,7 @@ ENTRY main { ParseHloString(module_str)); TF_ASSERT_OK_AND_ASSIGN( HloSchedule schedule, - ScheduleModule(*module, [](const BufferValue& buffer) { + ScheduleModule(module.get(), [](const BufferValue& buffer) { return ShapeUtil::ByteSizeOf(buffer.shape()); })); @@ -244,7 +244,7 @@ ENTRY %WhileLoop () -> s32[] { ParseHloString(module_str)); TF_ASSERT_OK_AND_ASSIGN( HloSchedule schedule, - ScheduleModule(*module, [](const BufferValue& buffer) { + ScheduleModule(module.get(), [](const BufferValue& buffer) { return ShapeUtil::ByteSizeOf(buffer.shape(), /*pointer_size=*/sizeof(void*)); })); @@ -313,7 +313,7 @@ ENTRY %WhileLoop () -> s32[] { ParseHloString(module_str)); TF_ASSERT_OK_AND_ASSIGN( HloSchedule schedule, - ScheduleModule(*module, [](const BufferValue& buffer) { + ScheduleModule(module.get(), [](const BufferValue& buffer) { return ShapeUtil::ByteSizeOf(buffer.shape(), /*pointer_size=*/sizeof(void*)); })); diff --git a/tensorflow/compiler/xla/service/hlo_sharding_metadata.cc b/tensorflow/compiler/xla/service/hlo_sharding_metadata.cc index 88329c8997..f506130445 100644 --- a/tensorflow/compiler/xla/service/hlo_sharding_metadata.cc +++ b/tensorflow/compiler/xla/service/hlo_sharding_metadata.cc @@ -253,7 +253,7 @@ StatusOr ApplyShardingFromUsers(HloInstruction* instruction, instruction->shape(), HloSharding::AssignDevice(kUnassignedDevice)); for (HloInstruction* user : instruction->users()) { if (user->opcode() == HloOpcode::kDomain && - domain.exit_domains.count(const_cast(user)) > 0) { + domain.exit_domains.count(user) > 0) { // If a user is a domain and it is registered in the domain exits, then // the instruction sharding is taken directly from the domain, and no // further users need to be visited. diff --git a/tensorflow/compiler/xla/service/hlo_subcomputation_unification_test.cc b/tensorflow/compiler/xla/service/hlo_subcomputation_unification_test.cc index 11994d99c9..c1073911ea 100644 --- a/tensorflow/compiler/xla/service/hlo_subcomputation_unification_test.cc +++ b/tensorflow/compiler/xla/service/hlo_subcomputation_unification_test.cc @@ -66,7 +66,7 @@ class HloSubcomputationUnificationTest : public HloTestBase { }; TEST_F(HloSubcomputationUnificationTest, UnifyIdentities) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto builder = HloComputation::Builder(TestName()); auto callee1 = @@ -103,7 +103,7 @@ TEST_F(HloSubcomputationUnificationTest, UnifyIdentities) { } TEST_F(HloSubcomputationUnificationTest, UnifyAdditions) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto builder = HloComputation::Builder(TestName()); auto callee1 = @@ -184,7 +184,7 @@ TEST_F(HloSubcomputationUnificationTest, DifferentParameterShapes) { // Regression test for b/31466798. Checks that entry_computation is still valid // after unification. TEST_F(HloSubcomputationUnificationTest, TwoIdenticalComputations) { - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); for (int i = 0; i < 2; ++i) { HloComputation::Builder builder("pow"); auto x = diff --git a/tensorflow/compiler/xla/service/hlo_value.h b/tensorflow/compiler/xla/service/hlo_value.h index b6670d409b..1f01b0bb36 100644 --- a/tensorflow/compiler/xla/service/hlo_value.h +++ b/tensorflow/compiler/xla/service/hlo_value.h @@ -166,9 +166,6 @@ class HloValue : public BufferValue { // Whether this value is live out of the HLO module. bool live_out_of_module_ = false; - - // Whether this value is live out of its computation. - bool live_out_of_computation_ = false; }; std::ostream& operator<<(std::ostream& out, const HloValue& hlo_value); diff --git a/tensorflow/compiler/xla/service/hlo_verifier.cc b/tensorflow/compiler/xla/service/hlo_verifier.cc index 27fd685a69..77db7b098a 100644 --- a/tensorflow/compiler/xla/service/hlo_verifier.cc +++ b/tensorflow/compiler/xla/service/hlo_verifier.cc @@ -753,13 +753,19 @@ Status ShapeVerifier::HandleAfterAll(HloInstruction* token) { for (const HloInstruction* operand : token->operands()) { operand_shapes.push_back(&operand->shape()); } - return CheckShape(token, ShapeInference::InferAfterAllShape(operand_shapes)); + return CheckShape(token, ShapeUtil::MakeTokenShape()); +} + +Status ShapeVerifier::HandleAddDependency(HloInstruction* add_dependency) { + TF_RETURN_IF_ERROR(CheckOperandCount(add_dependency, 2)); + TF_RETURN_IF_ERROR(CheckIsTokenOperand(add_dependency, 1)); + return CheckShape(add_dependency, add_dependency->operand(0)->shape()); } Status ShapeVerifier::HandleGetDimensionSize(HloInstruction* get_size) { - return CheckShape( - get_size, ShapeInference::InferGetDimensionSizeShape( - get_size->operand(0)->shape(), get_size->dimensions(0))); + return CheckShape(get_size, + ShapeInference::InferGetDimensionSizeShape( + get_size->operand(0)->shape(), get_size->dimension())); } Status ShapeVerifier::CheckShape(const HloInstruction* instruction, @@ -1373,9 +1379,8 @@ class InstructionVerifier : public DfsHloVisitorWithDefault { const Layout& operand_layout = operand_shape.layout(); TF_RET_CHECK(LayoutUtil::Equal(result_layout, operand_layout)) << "Instruction shouldn't change layouts " - << instruction->ToString() << " From " - << ShapeUtil::HumanString(result_shape) << " To " - << ShapeUtil::HumanString(operand_shape); + << instruction->ToString() << " From " << result_shape << " To " + << operand_shape; } } } @@ -1426,6 +1431,8 @@ StatusOr HloVerifier::Run(HloModule* module) { return target_metadata_->ShapeSize(shape); })); + TF_RETURN_IF_ERROR(module->dynamic_parameter_binding().Verify(*module)); + return false; } diff --git a/tensorflow/compiler/xla/service/hlo_verifier.h b/tensorflow/compiler/xla/service/hlo_verifier.h index 9fbfd6a21c..e4d0c3d695 100644 --- a/tensorflow/compiler/xla/service/hlo_verifier.h +++ b/tensorflow/compiler/xla/service/hlo_verifier.h @@ -95,6 +95,7 @@ class ShapeVerifier : public DfsHloVisitor { Status HandleScatter(HloInstruction* scatter) override; Status HandleAfterAll(HloInstruction* token) override; Status HandleGetDimensionSize(HloInstruction* get_size) override; + Status HandleAddDependency(HloInstruction* add_dependency) override; Status FinishVisit(HloInstruction*) override { return Status::OK(); } diff --git a/tensorflow/compiler/xla/service/hlo_verifier_test.cc b/tensorflow/compiler/xla/service/hlo_verifier_test.cc index 5ddfe0a944..4bc557e4e6 100644 --- a/tensorflow/compiler/xla/service/hlo_verifier_test.cc +++ b/tensorflow/compiler/xla/service/hlo_verifier_test.cc @@ -35,6 +35,10 @@ namespace { using ::testing::HasSubstr; +std::unique_ptr CreateUnverifiedModule() { + return absl::make_unique("module", HloModuleConfig()); +} + // This class cannot be converted to use HloTestBase. It explicitly // uses HloTestBase to create and test malformed HLOs. class HloVerifierTest : public HloTestBase { @@ -66,7 +70,7 @@ TEST_F(HloVerifierTest, NullInstructionParent) { HloInstruction::CreateParameter(0, scalar_shape, "param")); HloInstruction* negate = builder.AddInstruction( HloInstruction::CreateUnary(scalar_shape, HloOpcode::kNegate, param)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateUnverifiedModule(); module->AddEntryComputation(builder.Build()); TF_ASSERT_OK(verifier().Run(module.get()).status()); @@ -85,7 +89,7 @@ TEST_F(HloVerifierTest, NullComputationParent) { HloInstruction::CreateParameter(0, scalar_shape, "param")); builder.AddInstruction( HloInstruction::CreateUnary(scalar_shape, HloOpcode::kNegate, param)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateUnverifiedModule(); HloComputation* computation = module->AddEntryComputation(builder.Build()); TF_ASSERT_OK(verifier().Run(module.get()).status()); @@ -104,7 +108,7 @@ TEST_F(HloVerifierTest, DifferentOperandParents) { HloInstruction::CreateParameter(0, scalar_shape, "param")); HloInstruction* negate = builder.AddInstruction( HloInstruction::CreateUnary(scalar_shape, HloOpcode::kNegate, param)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateUnverifiedModule(); module->AddEntryComputation(builder.Build()); HloComputation::Builder emb_builder(TestName()); @@ -138,7 +142,7 @@ TEST_F(HloVerifierTest, ResetsShapeVerifierState) { builder.AddInstruction( HloInstruction::CreateBinary(s2, HloOpcode::kMultiply, add, add)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateUnverifiedModule(); module->AddEntryComputation(builder.Build()); // Run the verifier twice. It should fail both times, because it shouldn't @@ -303,7 +307,7 @@ TEST_F(HloVerifierTest, NegativeInteriorPaddingNotAllowed) { HloInstruction::CreateConstant(LiteralUtil::Zero(F32))), padding_config)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateUnverifiedModule(); module->AddEntryComputation(builder.Build()); auto status = verifier().Run(module.get()).status(); @@ -327,7 +331,7 @@ TEST_F(HloVerifierTest, PadNegativeInteriorDilationNotAllowed) { HloInstruction::CreateConstant(LiteralUtil::Zero(F32).Clone())), padding_config)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateUnverifiedModule(); module->AddEntryComputation(builder.Build()); EXPECT_THAT(verifier().Run(module.get()).status().error_message(), diff --git a/tensorflow/compiler/xla/service/indexed_array_analysis_test.cc b/tensorflow/compiler/xla/service/indexed_array_analysis_test.cc index 20cc18f981..98246d5403 100644 --- a/tensorflow/compiler/xla/service/indexed_array_analysis_test.cc +++ b/tensorflow/compiler/xla/service/indexed_array_analysis_test.cc @@ -481,8 +481,8 @@ ENTRY main { const char* expected_root_expression = R"( (scalar-indexed-const (constant s32[2,1,1,1,6] s32[2,1,1,1,6] { - { /*i0=0*/ { /*i1=0*/ { /*i2=0*/ {1, 2, 3, 4, 5, 6} } } }, - { /*i0=1*/ { /*i1=0*/ { /*i2=0*/ {1, 2, 3, 4, 5, 6} } } } }) + { /*i0=0*/ { /*i1=0*/ { /*i2=0*/ { 1, 2, 3, 4, 5, 6 } } } }, + { /*i0=1*/ { /*i1=0*/ { /*i2=0*/ { 1, 2, 3, 4, 5, 6 } } } } }) (reshape %indices to s32[]) 0->[]) )"; @@ -512,8 +512,8 @@ ENTRY main { const char* expected_root_expression = R"( (scalar-indexed-const (constant s32[2,1,1,6] s32[2,1,1,6] { - { /*i0=0*/ { /*i1=0*/ {1, 2, 3, 4, 5, 6} } }, - { /*i0=1*/ { /*i1=0*/ {1, 2, 3, 4, 5, 6} } } }) + { /*i0=0*/ { /*i1=0*/ { 1, 2, 3, 4, 5, 6 } } }, + { /*i0=1*/ { /*i1=0*/ { 1, 2, 3, 4, 5, 6 } } } }) (reshape %indices to s32[5]) 0->[2]) )"; diff --git a/tensorflow/compiler/xla/service/instruction_fusion.cc b/tensorflow/compiler/xla/service/instruction_fusion.cc index 7f2d7e7cff..7559ed1bab 100644 --- a/tensorflow/compiler/xla/service/instruction_fusion.cc +++ b/tensorflow/compiler/xla/service/instruction_fusion.cc @@ -103,7 +103,6 @@ bool IsAlwaysDuplicable(const HloInstruction& instruction) { case HloOpcode::kShiftRightLogical: case HloOpcode::kSlice: case HloOpcode::kSubtract: - case HloOpcode::kAfterAll: case HloOpcode::kTranspose: case HloOpcode::kTuple: case HloOpcode::kTupleSelect: @@ -116,7 +115,10 @@ bool IsAlwaysDuplicable(const HloInstruction& instruction) { case HloOpcode::kSin: return ShapeUtil::ElementIsComplex(instruction.shape()); - // Expensive instructions. + // Expensive instructions or unusual instructions for which fusion is + // nonsensical. + case HloOpcode::kAddDependency: + case HloOpcode::kAfterAll: case HloOpcode::kAtan2: case HloOpcode::kBatchNormGrad: case HloOpcode::kBatchNormInference: @@ -455,8 +457,13 @@ StatusOr InstructionFusion::Run(HloModule* module) { computation_ = computation; reachability_ = HloReachabilityMap::Build(computation_); - HloInstructionSet do_not_duplicate = - ComputeGloballyUnfusible(computation_->MakeInstructionPostOrder()); + HloInstructionSet do_not_duplicate; + // If we allow duplications, we need to compute which instructions we do not + // want to duplicate based on a global analysis of the graph. + if (may_duplicate_) { + do_not_duplicate = + ComputeGloballyUnfusible(computation_->MakeInstructionPostOrder()); + } auto fusion_queue = GetFusionQueue(computation_); // Instruction fusion effectively fuses edges in the computation graph @@ -564,8 +571,8 @@ HloInstruction* InstructionFusion::FuseIntoMultiOutput( bool InstructionFusion::MultiOutputFusionCreatesCycle( HloInstruction* producer, HloInstruction* consumer) { auto is_reachable = [&](const HloInstruction* a, const HloInstruction* b) { - // A consumer operand may have been multii-output fused into a parallel - // consumer and thus be missing from the oridinal reachability map. + // A consumer operand may have been multi-output fused into a parallel + // consumer and thus be missing from the original reachability map. if (!reachability_->IsPresent(a) || !reachability_->IsPresent(b)) { reachability_ = HloReachabilityMap::Build(consumer->parent()); } diff --git a/tensorflow/compiler/xla/service/instruction_fusion_test.cc b/tensorflow/compiler/xla/service/instruction_fusion_test.cc index 39904bd54b..58b7135cea 100644 --- a/tensorflow/compiler/xla/service/instruction_fusion_test.cc +++ b/tensorflow/compiler/xla/service/instruction_fusion_test.cc @@ -117,7 +117,7 @@ TEST_F(InstructionFusionTest, PotentialBitcastReshapeOfParameterUnfused) { auto reshape1 = builder.AddInstruction( HloInstruction::CreateReshape(ShapeUtil::MakeShape(S32, {1, 1}), param0)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_EQ(reshape1, computation->root_instruction()); EXPECT_FALSE( @@ -133,7 +133,7 @@ TEST_F(InstructionFusionTest, PotentialBitcastSimpleReshapeOfParameterUnfused) { auto reshape1 = builder.AddInstruction( HloInstruction::CreateReshape(ShapeUtil::MakeShape(S32, {1, 1}), param0)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_EQ(reshape1, computation->root_instruction()); EXPECT_FALSE( @@ -149,7 +149,7 @@ TEST_F(InstructionFusionTest, PotentialBitcastTransposeOfParameterUnfused) { auto transpose1 = builder.AddInstruction(HloInstruction::CreateTranspose( ShapeUtil::MakeShape(S32, {}), param0, {})); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); EXPECT_EQ(transpose1, computation->root_instruction()); EXPECT_FALSE( @@ -394,6 +394,56 @@ TEST_F(InstructionFusionTest, AllowEffectiveUnaryDuplication) { .ValueOrDie()); } +TEST_F(InstructionFusionTest, FuseDiamondGraphsNoDuplication) { + auto module = ParseHloString(R"( + HloModule test_module + ENTRY Test { + p0 = f32[100] parameter(0) + p1 = f32[100] parameter(1) + add = f32[100] add(p0, p1) + slice1 = f32[99] slice(add), slice={[0:99:1]} + slice2 = f32[99] slice(add), slice={[1:100:1]} + ROOT add2 = f32[99] add(slice1, slice2) + })") + .ValueOrDie(); + EXPECT_TRUE( + InstructionFusion(InstructionFusion::IsExpensive, /*may_duplicate=*/false) + .Run(module.get()) + .ValueOrDie()) + << module->ToString(); + + HloInstruction* root = module->entry_computation()->root_instruction(); + // 'add' would originally need to be duplicated if fused. However after its + // two users 'slice1' and 'slice2' are fused into 'add2', 'add' has only one + // user and can now be also fused. + EXPECT_THAT(root, op::Fusion(op::Parameter(), op::Parameter())); +} + +TEST_F(InstructionFusionTest, FuseDiamondGraphsAllowDuplication) { + auto module = ParseHloString(R"( + HloModule test_module + ENTRY Test { + p0 = f32[100] parameter(0) + p1 = f32[100] parameter(1) + add = f32[100] add(p0, p1) + slice1 = f32[99] slice(add), slice={[0:99:1]} + slice2 = f32[99] slice(add), slice={[1:100:1]} + ROOT add2 = f32[99] add(slice1, slice2) + })") + .ValueOrDie(); + EXPECT_TRUE( + InstructionFusion(InstructionFusion::IsExpensive, /*may_duplicate=*/true) + .Run(module.get()) + .ValueOrDie()) + << module->ToString(); + + HloInstruction* root = module->entry_computation()->root_instruction(); + // 'add' would originally need to be duplicated if fused. However after its + // two users 'slice1' and 'slice2' are fused into 'add2', 'add' has only one + // user and can now be also fused. + EXPECT_THAT(root, op::Fusion(op::Parameter(), op::Parameter())); +} + TEST_F(InstructionFusionTest, WideningConvertsAreAlwaysDuplicableIntoConsumers) { auto module = ParseHloString(R"( diff --git a/tensorflow/compiler/xla/service/interpreter/executable.cc b/tensorflow/compiler/xla/service/interpreter/executable.cc index a06d6113e8..7635fbfed6 100644 --- a/tensorflow/compiler/xla/service/interpreter/executable.cc +++ b/tensorflow/compiler/xla/service/interpreter/executable.cc @@ -37,7 +37,7 @@ namespace xla { namespace interpreter { InterpreterExecutable::InterpreterExecutable( - std::unique_ptr hlo_module, + std::unique_ptr hlo_module, std::unique_ptr evaluator) : Executable(std::move(hlo_module), /*hlo_profile_printer=*/nullptr, /*hlo_profile_index_map=*/nullptr), diff --git a/tensorflow/compiler/xla/service/interpreter/executable.h b/tensorflow/compiler/xla/service/interpreter/executable.h index 3b1ebce0c7..bda13d3763 100644 --- a/tensorflow/compiler/xla/service/interpreter/executable.h +++ b/tensorflow/compiler/xla/service/interpreter/executable.h @@ -42,7 +42,7 @@ namespace interpreter { // buffer allocation. Refer to interpreter/README.md for more. class InterpreterExecutable : public Executable { public: - InterpreterExecutable(std::unique_ptr hlo_module, + InterpreterExecutable(std::unique_ptr hlo_module, std::unique_ptr evaluator); ~InterpreterExecutable() override; diff --git a/tensorflow/compiler/xla/service/interpreter/executor.cc b/tensorflow/compiler/xla/service/interpreter/executor.cc index 4fb67bd0b7..e3e5fa7154 100644 --- a/tensorflow/compiler/xla/service/interpreter/executor.cc +++ b/tensorflow/compiler/xla/service/interpreter/executor.cc @@ -78,9 +78,14 @@ port::Status XlaInterpreterExecutor::SynchronousMemcpy( return port::Status::OK(); } -bool XlaInterpreterExecutor::HostCallback(Stream *stream, - std::function callback) { - AsExecutorStream(stream)->EnqueueTask(callback); +bool XlaInterpreterExecutor::HostCallback( + Stream *stream, std::function callback) { + AsExecutorStream(stream)->EnqueueTask([callback]() { + port::Status s = callback(); + if (!s.ok()) { + LOG(WARNING) << "Host callback failed: " << s; + } + }); return true; } diff --git a/tensorflow/compiler/xla/service/interpreter/executor.h b/tensorflow/compiler/xla/service/interpreter/executor.h index fbb9945784..400c305154 100644 --- a/tensorflow/compiler/xla/service/interpreter/executor.h +++ b/tensorflow/compiler/xla/service/interpreter/executor.h @@ -125,7 +125,8 @@ class XlaInterpreterExecutor : public internal::StreamExecutorInterface { return port::Status{port::error::UNIMPLEMENTED, ""}; } - bool HostCallback(Stream *stream, std::function callback) override; + bool HostCallback(Stream *stream, + std::function callback) override; port::Status AllocateEvent(Event *event) override { return port::Status{port::error::UNIMPLEMENTED, ""}; diff --git a/tensorflow/compiler/xla/service/layout_assignment.cc b/tensorflow/compiler/xla/service/layout_assignment.cc index a904119222..eddef850cf 100644 --- a/tensorflow/compiler/xla/service/layout_assignment.cc +++ b/tensorflow/compiler/xla/service/layout_assignment.cc @@ -2000,6 +2000,7 @@ bool LayoutAssignment::InstructionCanChangeLayout( switch (instruction->opcode()) { case HloOpcode::kAbs: case HloOpcode::kAdd: + case HloOpcode::kAddDependency: case HloOpcode::kAnd: case HloOpcode::kAtan2: case HloOpcode::kBitcastConvert: diff --git a/tensorflow/compiler/xla/service/layout_assignment_test.cc b/tensorflow/compiler/xla/service/layout_assignment_test.cc index 2400b7bb7c..311bd78905 100644 --- a/tensorflow/compiler/xla/service/layout_assignment_test.cc +++ b/tensorflow/compiler/xla/service/layout_assignment_test.cc @@ -31,6 +31,8 @@ limitations under the License. #include "tensorflow/compiler/xla/service/hlo_module.h" #include "tensorflow/compiler/xla/service/hlo_opcode.h" #include "tensorflow/compiler/xla/service/hlo_parser.h" +#include "tensorflow/compiler/xla/service/pattern_matcher.h" +#include "tensorflow/compiler/xla/service/pattern_matcher_gmock.h" #include "tensorflow/compiler/xla/shape_layout.h" #include "tensorflow/compiler/xla/shape_util.h" #include "tensorflow/compiler/xla/test.h" @@ -42,11 +44,10 @@ limitations under the License. #include "tensorflow/core/lib/core/status.h" #include "tensorflow/core/lib/core/status_test_util.h" -namespace op = xla::testing::opcode_matchers; - namespace xla { namespace { +namespace m = xla::match; using ::testing::ElementsAre; class LayoutAssignmentTest : public HloTestBase { @@ -328,11 +329,10 @@ TEST_F(LayoutAssignmentTest, ConflictingLayoutTuple) { // %tuple.1 = Tuple(%copy) layout=({0,1}) // %tuple.2 = Tuple(%tuple.0, %tuple.1) layout=(({1,0}), ({0,1})) // - EXPECT_TRUE( - AlgebraicSimplifier(/*is_layout_sensitive=*/true, - [](const Shape&, const Shape&) { return false; }) - .Run(m.get()) - .ValueOrDie()); + AlgebraicSimplifierOptions options( + [](const Shape&, const Shape&) { return false; }); + options.set_is_layout_sensitive(true); + EXPECT_TRUE(AlgebraicSimplifier(options).Run(m.get()).ValueOrDie()); HloInstruction* root = m->entry_computation()->root_instruction(); // Verify layout of the root and the root's operands. EXPECT_TRUE(ShapeUtil::Equal(result_shape, root->shape())); @@ -343,7 +343,8 @@ TEST_F(LayoutAssignmentTest, ConflictingLayoutTuple) { // Verify the structure of the HLO graph. EXPECT_THAT(root, - op::Tuple(op::Tuple(constant), op::Tuple(op::Copy(constant)))); + GmockMatch(m::Tuple(m::Tuple(m::Op().Is(constant)), + m::Tuple(m::Copy(m::Op().Is(constant)))))); } TEST_F(LayoutAssignmentTest, ElementwiseAndReshape) { @@ -947,9 +948,11 @@ TEST_F(LayoutAssignmentTest, CopySliceOperandToAvoidImplicitLayoutChange) { HloInstruction* root = compiled_module->entry_computation()->root_instruction(); Shape shape_copy = ShapeUtil::MakeShapeWithLayout(F32, {4, 5}, {1, 0}); - EXPECT_THAT(root, op::Add(op::Parameter(), - op::Slice(AllOf(op::Copy(op::Parameter(1)), - op::ShapeWithLayout(shape_copy))))); + EXPECT_THAT( + root, + GmockMatch(m::Add( + m::Parameter(), + m::Slice(m::Copy(m::Parameter(1)).WithShapeEqualTo(&shape_copy))))); } TEST_F(LayoutAssignmentTest, CopyDSliceOperandToAvoidImplicitLayoutChange) { @@ -977,10 +980,11 @@ TEST_F(LayoutAssignmentTest, CopyDSliceOperandToAvoidImplicitLayoutChange) { compiled_module->entry_computation()->root_instruction(); Shape shape_copy = ShapeUtil::MakeShapeWithLayout(F32, {4, 5}, {1, 0}); EXPECT_THAT(root, - op::Add(op::Parameter(), - op::DynamicSlice(AllOf(op::Copy(op::Parameter(1)), - op::ShapeWithLayout(shape_copy)), - op::Parameter(2)))); + GmockMatch(m::Add( + m::Parameter(), + m::DynamicSlice( + m::Copy(m::Parameter(1)).WithShapeEqualTo(&shape_copy), + m::Parameter(2))))); } TEST_F(LayoutAssignmentTest, CopyConcatOperandToAvoidImplicitLayoutChange) { @@ -1008,11 +1012,12 @@ TEST_F(LayoutAssignmentTest, CopyConcatOperandToAvoidImplicitLayoutChange) { HloInstruction* root = compiled_module->entry_computation()->root_instruction(); Shape shape_copy = ShapeUtil::MakeShapeWithLayout(F32, {3, 5}, {1, 0}); - EXPECT_THAT(root, - op::Add(op::Parameter(), - op::Concatenate(AllOf(op::Copy(op::Parameter(1)), - op::ShapeWithLayout(shape_copy)), - op::Parameter(2)))); + EXPECT_THAT( + root, + GmockMatch(m::Add( + m::Parameter(), + m::Concatenate(m::Copy(m::Parameter(1)).WithShapeEqualTo(&shape_copy), + m::Parameter(2))))); } TEST_F(LayoutAssignmentTest, @@ -1039,7 +1044,8 @@ TEST_F(LayoutAssignmentTest, .ConsumeValueOrDie(); HloInstruction* root = compiled_module->entry_computation()->root_instruction(); - EXPECT_THAT(root, op::Convolution(op::Parameter(0), op::Parameter(1))); + EXPECT_THAT(root, + GmockMatch(m::Convolution(m::Parameter(0), m::Parameter(1)))); } TEST_F(LayoutAssignmentTest, PropagatingLayoutFromResultToOperand) { @@ -1063,8 +1069,9 @@ TEST_F(LayoutAssignmentTest, PropagatingLayoutFromResultToOperand) { HloInstruction* root = compiled_module->entry_computation()->root_instruction(); Shape shape_copy = ShapeUtil::MakeShapeWithLayout(F32, {4, 5}, {0, 1}); - EXPECT_THAT(root, op::Slice(AllOf(op::Copy(op::Parameter(0)), - op::ShapeWithLayout(shape_copy)))); + EXPECT_THAT(root, + GmockMatch(m::Slice( + m::Copy(m::Parameter(0)).WithShapeEqualTo(&shape_copy)))); } TEST_F(LayoutAssignmentTest, TupleCopyOnLayoutMismatch) { @@ -1150,7 +1157,7 @@ ENTRY %CustomCallWithNotLayoutConstrained (p: f32[42,2,3]) -> f32[1,2,3,4] { AssignLayouts(m.get(), &computation_layout); HloInstruction* root = m->entry_computation()->root_instruction(); - ASSERT_THAT(root, op::CustomCall(op::Parameter())); + ASSERT_THAT(root, GmockMatch(m::CustomCall(m::Parameter()))); ExpectLayoutIs(root->shape(), {3, 2, 0, 1}); ExpectLayoutIs(root->operand(0)->shape(), {0, 2, 1}); } @@ -1166,7 +1173,7 @@ ENTRY %CustomCallWithNotLayoutConstrained (p: f32[42,2,3]) -> f32[1,2,3,4] { AssignLayouts(m.get(), &computation_layout); HloInstruction* root = m->entry_computation()->root_instruction(); - ASSERT_THAT(root, op::CustomCall(op::Parameter())); + ASSERT_THAT(root, GmockMatch(m::CustomCall(m::Parameter()))); ExpectLayoutIs(root->shape(), {0, 2, 3, 1}); ExpectLayoutIs(root->operand(0)->shape(), {0, 1, 2}); } @@ -1197,7 +1204,7 @@ ENTRY %CustomCallWithLayoutConstraints (p0: f32[4,4], p1: f32[2,3]) -> f32[1,2,3 // The custom call should be partially encapsulated in kCopy instructions // because of the layout mismatches. ASSERT_THAT(m->entry_computation()->root_instruction(), - op::Copy(op::CustomCall(op::Copy(), op::Parameter()))); + GmockMatch(m::Copy(m::CustomCall(m::Copy(), m::Parameter())))); const HloInstruction* custom_call = m->entry_computation()->root_instruction()->operand(0); @@ -1223,7 +1230,7 @@ ENTRY %CustomCallLayoutConstrainedZeroOperands () -> f32[1,2,3,4] { AssignLayouts(m.get(), &computation_layout); ASSERT_THAT(m->entry_computation()->root_instruction(), - op::Copy(op::CustomCall())); + GmockMatch(m::Copy(m::CustomCall()))); const HloInstruction* custom_call = m->entry_computation()->root_instruction()->operand(0); @@ -1257,7 +1264,7 @@ ENTRY %CustomCallLayoutConstrainedTupleOperand (p0: f32[4,4], p1: f32[2,3]) -> f ExpectLayoutIs(root->shape(), {2, 1, 0, 3}); ASSERT_THAT(m->entry_computation()->root_instruction(), - op::Copy(op::CustomCall(op::Tuple()))); + GmockMatch(m::Copy(m::CustomCall(m::Tuple())))); const HloInstruction* custom_call = m->entry_computation()->root_instruction()->operand(0); diff --git a/tensorflow/compiler/xla/service/llvm_ir/ir_array.h b/tensorflow/compiler/xla/service/llvm_ir/ir_array.h index f4b05f29c3..d6d84994ee 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/ir_array.h +++ b/tensorflow/compiler/xla/service/llvm_ir/ir_array.h @@ -25,6 +25,7 @@ limitations under the License. #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Value.h" #include "tensorflow/compiler/xla/map_util.h" +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/xla_data.pb.h" #include "tensorflow/core/platform/logging.h" @@ -108,6 +109,14 @@ class IrArray { Index(absl::Span multidim, llvm::Value* linear, const Shape& shape); + // Returns an index that adds `addend` to the given `dim` of the object. + Index AddOffsetToDim(llvm::Value* addend, int64 dim, + llvm::IRBuilder<>* b) const { + IrArray::Index index = *this; + index[dim] = b->CreateAdd(index[dim], addend); + return index; + } + const std::vector& multidim() const { return multidim_; } llvm::Value* linear() const { return linear_; } diff --git a/tensorflow/compiler/xla/service/llvm_ir/kernel_tiling.cc b/tensorflow/compiler/xla/service/llvm_ir/kernel_tiling.cc index e5fbdbd51b..1aa85eb8d2 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/kernel_tiling.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/kernel_tiling.cc @@ -52,6 +52,29 @@ Shape MergeDimensions(absl::Span segs, const Shape& shape) { return ShapeUtil::MakeShapeWithDescendingLayout(shape.element_type(), dimensions); } + +// Given an index for a shape, return the equivalent new index if the shape is +// reshaped to another shape. +IrArray::Index GetReshapedIndex(const IrArray::Index& index, const Shape& shape, + const Shape& reshaped_shape, + llvm::IRBuilder<>* b) { + auto bounds = shape.dimensions(); + auto minor_to_major = shape.layout().minor_to_major(); + llvm::Value* linear_index = index.GetConstantWithIndexType(0); + int64 multiplier = 1; + for (int i = 0; i < index.size(); ++i) { + int64 dim = minor_to_major[i]; + llvm::Value* addend = b->CreateMul( + index[dim], index.GetConstantWithIndexType(multiplier), "linearizing", + /*HasNUW=*/true, /*HasNSW=*/true); + linear_index = b->CreateAdd(linear_index, addend, "", + /*HasNUW=*/true, /*HasNSW=*/true); + multiplier *= bounds[dim]; + } + + return IrArray::Index(linear_index, reshaped_shape, b); +} + } // namespace absl::optional > FindTranspose021(const Shape& a, @@ -60,28 +83,30 @@ absl::optional > FindTranspose021(const Shape& a, return absl::nullopt; } - std::vector perm(a.dimensions().size()); - { - auto layout_a_orig = LayoutUtil::MinorToMajor(a); - std::vector layout_a(layout_a_orig.rbegin(), layout_a_orig.rend()); - auto layout_b_orig = LayoutUtil::MinorToMajor(b); - std::vector layout_b(layout_b_orig.rbegin(), layout_b_orig.rend()); - for (size_t i = 0; i < perm.size(); ++i) { - perm[i] = PositionInContainer(layout_b, layout_a[i]); - } + std::vector permutation(a.dimensions().size()); + absl::Span minor_to_major_a = LayoutUtil::MinorToMajor(a); + std::vector major_to_minor_a(minor_to_major_a.rbegin(), + minor_to_major_a.rend()); + absl::Span minor_to_major_b = LayoutUtil::MinorToMajor(b); + std::vector major_to_minor_b(minor_to_major_b.rbegin(), + minor_to_major_b.rend()); + for (size_t i = 0; i < permutation.size(); ++i) { + permutation[i] = PositionInContainer(major_to_minor_b, major_to_minor_a[i]); } - auto segs = ConsecutiveSegments(perm); - if ((3 == segs.size() && 0 == perm[0]) || 2 == segs.size()) { - Shape norm_a = + + std::vector segments = ConsecutiveSegments(permutation); + if ((3 == segments.size() && 0 == permutation[0]) || 2 == segments.size()) { + Shape descending_layout_shape = ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout(a); - Shape reduced_a = MergeDimensions(segs, norm_a); - auto reduced_a_dims = reduced_a.dimensions(); + Shape normalized_shape = MergeDimensions(segments, descending_layout_shape); + absl::Span normalized_dims = + AsInt64Slice(normalized_shape.dimensions()); std::vector dims_021; - if (2 == segs.size()) { + if (2 == segments.size()) { // The logical component-0 is of size one. - dims_021 = {1, reduced_a_dims[1], reduced_a_dims[0]}; + dims_021 = {1, normalized_dims[1], normalized_dims[0]}; } else { - dims_021 = {reduced_a_dims[0], reduced_a_dims[2], reduced_a_dims[1]}; + dims_021 = {normalized_dims[0], normalized_dims[2], normalized_dims[1]}; } return dims_021; @@ -90,27 +115,117 @@ absl::optional > FindTranspose021(const Shape& a, return absl::nullopt; } -IrArray::Index GetUnreducedOutputIndex( - const IrArray::Index& reduced_output_index, - const Shape& reduced_output_shape, const Shape& unreduced_output_shape, - llvm::IRBuilder<>* b) { - auto bounds = reduced_output_shape.dimensions(); - auto minor_to_major = reduced_output_shape.layout().minor_to_major(); - llvm::Value* linear_index = reduced_output_index.GetConstantWithIndexType(0); - int64 multiplier = 1; - for (int i = 0; i < reduced_output_index.size(); ++i) { - int64 dim = minor_to_major[i]; - llvm::Value* addend = - b->CreateMul(reduced_output_index[dim], - reduced_output_index.GetConstantWithIndexType(multiplier), - "linearizing", - /*HasNUW=*/true, /*HasNSW=*/true); - linear_index = b->CreateAdd(linear_index, addend, "", - /*HasNUW=*/true, /*HasNSW=*/true); - multiplier *= bounds[dim]; +KernelMappingScheme::KernelMappingScheme( + absl::Span dims_in_elems, int64 tile_size_y, int64 tile_size_x, + absl::Span req_block_sizes, int64 num_threads_y, + int64 num_threads_x, llvm::IRBuilder<>* b) + : b_(b), + dims_in_elems_(dims_in_elems.begin(), dims_in_elems.end()), + tile_sizes_{1, tile_size_y, tile_size_x}, + num_threads_x_(num_threads_x), + num_threads_y_(num_threads_y) { + DCHECK_EQ(dims_in_elems_.size(), 3); + DCHECK_EQ(req_block_sizes.size(), 3); + + DCHECK_EQ(tile_size_y % num_threads_y_, 0); + DCHECK_EQ(tile_size_x % num_threads_x_, 0); + + dims_in_tiles_ = ElementWiseCeilOfRatio(dims_in_elems_, tile_sizes_); + block_sizes_.reserve(req_block_sizes.size()); + absl::c_transform(req_block_sizes, dims_in_tiles_, + std::back_inserter(block_sizes_), + [](const int64 requested_size, const int64 max_size) { + return std::min(requested_size, max_size); + }); + dims_in_blocks_ = ElementWiseCeilOfRatio(dims_in_tiles_, block_sizes_); + + VLOG(10) << "dims_in_elems_ = [" << absl::StrJoin(dims_in_elems_, ",") << "]"; + VLOG(10) << "dims_in_tiles_ = [" << absl::StrJoin(dims_in_tiles_, ",") << "]"; + VLOG(10) << "dims_in_blocks_ = [" << absl::StrJoin(dims_in_blocks_, ",") + << "]"; +} + +IrArray::Index KernelMappingScheme::GetUnnormalizedIndex( + const IrArray::Index& normalized_shape_index, + const Shape& unnormalized_shape) { + DCHECK_EQ(normalized_shape_index.size(), dims_in_elems_.size()); + Shape output_shape = ShapeUtil::MakeShapeWithDescendingLayout( + unnormalized_shape.element_type(), GetDimensionsInElements()); + return GetReshapedIndex(normalized_shape_index, output_shape, + unnormalized_shape, b_); +} + +IrArray::Index KernelMappingScheme::EmitBlockIndex(llvm::Type* index_ty) { + llvm::Value* block_id = llvm_ir::EmitCallToIntrinsic( + llvm::Intrinsic::nvvm_read_ptx_sreg_ctaid_x, {}, {}, b_); + llvm_ir::AddRangeMetadata(0, GetNumberOfBlocks(), + llvm::cast(block_id)); + llvm::Value* linear_block_id = + b_->CreateIntCast(block_id, index_ty, /*isSigned=*/true, "block.id.x"); + return IrArray::Index(linear_block_id, + ShapeUtil::MakeShapeWithDescendingLayout( + PRED /*arbitrary*/, dims_in_blocks_), + b_); +} + +IrArray::Index KernelMappingScheme::GetTileIndexForBlockOrigin( + const IrArray::Index& block_index) { + IrArray::Index tile_index = block_index; + for (int i = 0; i < block_sizes_.size(); ++i) { + tile_index[i] = b_->CreateMul( + block_index[i], + llvm::ConstantInt::get(block_index[i]->getType(), block_sizes_[i]), + "block_origin." + std::to_string(i)); + } + return tile_index; +} + +IrArray::Index KernelMappingScheme::GetElementIndexForTileOrigin( + const IrArray::Index& tile_index) { + IrArray::Index elem_index = tile_index; + for (int i = DimY; i < DimTot; ++i) { + elem_index[i] = + b_->CreateMul(tile_index[i], + llvm::ConstantInt::get(tile_index[i]->getType(), + GetTileSizeForDimension(i)), + "tile_origin." + std::to_string(i)); } + return elem_index; +} + +llvm::GlobalVariable* KernelMappingScheme::GetSharedMemoryBufferForElementType( + llvm::Type* elem_ty, absl::string_view buffer_name) { + // If shared memory tranpose is needed, we use square tiles. + CHECK_EQ(GetTileSizeForDimensionX(), GetTileSizeForDimensionY()); + + // For Nvidia GPUs, the warp size is 32 threads and the shared memory bank is + // organized into 32-way. We usually use the warp size or a multiplier or a + // the warp size as the size for tiling. This may cause all elements in the + // same column of a tile use the same memory bank and therefore shared memory + // bank conflicts. Adding 1 to the minor dimension of the shared memory buffer + // can reduce such shared memory bank conflicts. + llvm::Type* buffer_type = llvm::ArrayType::get( + llvm::ArrayType::get(elem_ty, GetTileSizeForDimension(DimX) + 1), + GetTileSizeForDimension(DimY)); + return llvm_ir::AllocateSharedMemoryTile(b_->GetInsertBlock()->getModule(), + buffer_type, buffer_name); +} - return IrArray::Index(linear_index, unreduced_output_shape, b); +std::tuple +KernelMappingScheme::EmitThreadYXCoordinate(llvm::Type* index_ty) { + // Calculate (y, x) coordinate of the thread in the 2D view of thread block + // defined by (num_thread_y, num_thread_x) from thread_id. + llvm::CallInst* thread_id_raw = llvm_ir::EmitCallToIntrinsic( + llvm::Intrinsic::nvvm_read_ptx_sreg_tid_x, {}, {}, b_); + llvm_ir::AddRangeMetadata(0, GetThreadsPerTile(), thread_id_raw); + llvm::Value* thread_id_int = + b_->CreateIntCast(thread_id_raw, index_ty, + /*isSigned=*/true, "thread.id.x"); + llvm::Value* num_thread_x = + llvm::ConstantInt::get(index_ty, GetNumberOfThreadsForDimensionX()); + llvm::Value* x = b_->CreateURem(thread_id_int, num_thread_x); + llvm::Value* y = b_->CreateUDiv(thread_id_int, num_thread_x); + return std::make_tuple(y, x); } } // namespace llvm_ir diff --git a/tensorflow/compiler/xla/service/llvm_ir/kernel_tiling.h b/tensorflow/compiler/xla/service/llvm_ir/kernel_tiling.h index 5ea05b3188..7277aeac8a 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/kernel_tiling.h +++ b/tensorflow/compiler/xla/service/llvm_ir/kernel_tiling.h @@ -28,23 +28,165 @@ namespace llvm_ir { // If a shape can be viewed as three logical components 0-1-2 in the order of // major to minor, a 0-2-1-transpose changes the order of such logical // components to 0-2-1. We call the shape being transposed the input shape and -// the transposed shape the output shape. The logical view of the input and -// output shapes for the transpose are called the 0-1-2 shape or reduced input -// shape and the 0-2-1 shape or the reduced output shape respectively. The -// original input and output shapes are called the unreduced input and output -// shapes. - +// the transposed shape the output shape. The logical view of the input/output +// shapes for the transpose are called the 0-1-2/0-2-1 shapes or the normalized +// shapes. The original input/output shapes are called unnormalized shapes. +// // If `b` is a 0-2-1 transpose of `a` in 0-1-2, return the dimensions for the -// reduced shape of `b` or the 0-2-1 shape. +// normalized shape of `b` or the 0-2-1 shape. absl::optional > FindTranspose021(const Shape& a, const Shape& b); -// Return the unreduced output index corresponding to the given reduced output -// index. -IrArray::Index GetUnreducedOutputIndex( - const IrArray::Index& reduced_output_index, - const Shape& reduced_output_shape, const Shape& unreduced_output_shape, - llvm::IRBuilder<>* b); +// A tile is a spatial subdivision of a tensor. We group tensor elements into +// tiles so that we can launch kernels to process the tensor elements in blocks +// of tiles. +// +// A kernel mapping scheme describes a method to partition the tensors accessed +// by an unnested HLO instruction into tiles and blocks of tiles, and the +// associated information to use hardware threads to process the tensor elements +// in blocks of tiles. +// +// Currently, there are two main use cases for a tiling scheme. First, we +// implement kernels with 0-2-1 memory transpose using shared memory to improve +// memory access pattern. Second, we implement reduction to contiguous +// dimensions in layout, with or without memory tranpsose, to achieve better +// memory access pattern as well as to reduce the need numbers of executed +// expensive instructions, such as thread synchronization related instructions +// and atomic operations. For both use cases, we can apply a normalization to +// the original tensors, to collapse contiguous dimensions for the same purpose +// and produce normlized three dimensional tensors. For this reason, the tiling +// scheme class only needs to handle normalized three dimensional tensors and +// two dimensional tiles. +// +// The current implementation of the class is somewhat NVIDIA GPU oriented. This +// situation can be improved when there is a need though. The idea of 0-2-1 +// transpose using shared memory can be found in the following CUDA algorithm in +// TensorFlow: https://goo.gl/MStRV6. +// +// We use a thread block to process a tile because we want to use the HW thread +// block synchronization primitives to synchronize the processing of all the +// elements in the same tile. A thread block can be viewed as a two dimensional +// array of threads, described by the number of threads for the Y and X +// dimensions. A thread block (num_threads_y, num_threads_x) processes a tile of +// (tile_size_y, tile_size_x) as follows: each thread in the thread block +// processes one element in the tile so that all the threads in the thread block +// together process a subdivision of the tile that has the same dimension as the +// thread block array. Then the thread block moves on to process the next +// subdivision of the tile until the whole tile is processed. Therefore, each +// thread in the thread block processes +// tile_size_x/num_threads_x * tile_size_y/num_threads_y elements in a tile. +// +// There are situations where we want a thread block to process multiple +// tiles. We can't group those tiles into a bigger tiles because we limit a tile +// to a two dimensional spatial subdivision of a tensor. For example, when we +// use tiling to implement reduction with tranpose, we want the partial sum +// produced by each thread to accumulate values for more elements before using +// shlf_down and atomic_add instructions for further reduction, to amortize the +// cost of such expensive instructions. The concept of tile block is introduced +// for this purpose. A tile block is a three dimensional array of tiles, of +// which some dimensions may be degenerated to only one tile. +class KernelMappingScheme { + public: + enum { DimZ = 0, DimY, DimX, DimTot }; + + public: + KernelMappingScheme() {} + // dims_in_elems: the normalized tensor dimensions. + // req_block_sizes: the requested block size in number of tiles for each + // dimension. The actual block size is set to min(req_block_size, + // dims_in_number_of_blocks). + KernelMappingScheme(absl::Span dims_in_elems, int64 tile_size_y, + int64 tile_size_x, + absl::Span req_block_sizes, + int64 num_threads_y, int64 num_threads_x, + llvm::IRBuilder<>* b); + + absl::Span GetDimensionsInElements() const { + return dims_in_elems_; + } + absl::Span GetDimensionsInTiles() const { + return dims_in_tiles_; + } + absl::Span GetDimensionsInBlocks() const { + return dims_in_blocks_; + } + + int64 GetNumberOfTilesInTotal() const { + return absl::c_accumulate(dims_in_tiles_, 1LL, std::multiplies()); + } + int64 GetNumberOfTilesInOneBlock() const { + return absl::c_accumulate(block_sizes_, 1, std::multiplies()); + } + + int64 GetNumberOfBlocks() const { + return absl::c_accumulate(dims_in_blocks_, 1, std::multiplies()); + } + + int64 GetTileSizeForDimension(int d) const { + DCHECK(d >= DimZ && d <= DimX); + return tile_sizes_[d]; + } + int64 GetTileSizeForDimensionX() const { + return GetTileSizeForDimension(DimX); + } + int64 GetTileSizeForDimensionY() const { + return GetTileSizeForDimension(DimY); + } + + absl::Span GetBlockSizes() const { return block_sizes_; } + int64 GetTileBlockSizeForDimension(int d) const { + DCHECK(d >= DimZ && d <= DimX); + return dims_in_blocks_[d]; + } + + int64 GetNumberOfThreadsForDimensionX() const { return num_threads_x_; } + int64 GetNumberOfThreadsForDimensionY() const { return num_threads_y_; } + + int64 GetThreadsPerTile() const { + return GetNumberOfThreadsForDimensionX() * + GetNumberOfThreadsForDimensionY(); + } + + IrArray::Index EmitBlockIndex(llvm::Type* index_ty); + // Returns the index for the first tile in the block with the given block + // index. + IrArray::Index GetTileIndexForBlockOrigin(const IrArray::Index& block_index); + // Returns the index for the first element in the tile with the given tile + // index. + IrArray::Index GetElementIndexForTileOrigin(const IrArray::Index& tile_index); + + std::tuple EmitThreadYXCoordinate( + llvm::Type* index_ty); + + IrArray::Index GetUnnormalizedIndex( + const IrArray::Index& normalized_shape_index, + const Shape& unnormalized_shape); + + llvm::GlobalVariable* GetSharedMemoryBufferForElementType( + llvm::Type* elem_ty, absl::string_view buffer_name); + + private: + llvm::IRBuilder<>* b_; + // The number of elements in each dimension. + std::vector dims_in_elems_; + + // The number of elements for each dimension of a tile. + std::vector tile_sizes_; + // The number of tiles in each dimension. It is computed from dims_in_elem_ + // and tile_sizes_. + std::vector dims_in_tiles_; + + // The number of tiles for each dimension of a tile block. + std::vector block_sizes_; + // The number of blocks in each dimension of a tile block. It is computed from + // dims_in_tile_ and block_sizes_. + std::vector dims_in_blocks_; + + // Number of threads used to process elements in the X direction of a tile. + int64 num_threads_x_; + // Number of threads used to process elements in the Y direction of a tile. + int64 num_threads_y_; +}; // A class to represent information for tiled parameters to support IR emission // for 021 transpose. diff --git a/tensorflow/compiler/xla/service/llvm_ir/llvm_util.cc b/tensorflow/compiler/xla/service/llvm_ir/llvm_util.cc index df78726166..ceea24685a 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/llvm_util.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/llvm_util.cc @@ -244,10 +244,11 @@ StatusOr EncodeSelfDescribingShapeConstant(const Shape& shape, StatusOr DecodeSelfDescribingShapeConstant(const void* shape_ptr, int32 size_bytes) { - Shape shape; - TF_RET_CHECK(shape.ParseFromArray(shape_ptr, size_bytes)); + ShapeProto shape_proto; + TF_RET_CHECK(shape_proto.ParseFromArray(shape_ptr, size_bytes)); + Shape shape(shape_proto); TF_RETURN_IF_ERROR(ShapeUtil::ValidateShape(shape)); - return shape; + return std::move(shape); } llvm::Constant* ConvertLiteralToIrConstant(const Literal& literal, diff --git a/tensorflow/compiler/xla/service/llvm_ir/sort_util.cc b/tensorflow/compiler/xla/service/llvm_ir/sort_util.cc index fd16af67fe..e22c2173c2 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/sort_util.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/sort_util.cc @@ -47,7 +47,8 @@ namespace { // Adds the inner comparison loop body where we compare elements. void EmitCompareLoopBody( int64 iteration_bound, PrimitiveType key_type, int64 num_values, - llvm::Value* element_pair_index, int64 xor_mask, llvm::Type* index_type, + int64 iota_values_parameter_index, llvm::Value* element_pair_index, + int64 xor_mask, llvm::Type* index_type, std::function read_element, std::function write_element, @@ -139,34 +140,42 @@ void EmitCompareLoopBody( is_signed_comparison = false; } // If key2 < key1 - ksl.IfReturnVoid( - "is_smaller_than", + auto is_smaller_than = b->CreateICmp(is_signed_comparison ? llvm::ICmpInst::ICMP_SLT : llvm::ICmpInst::ICMP_ULT, - compare_key2, compare_key1), - [&]() { - // Swap key1 with key2. - write_element(0, current_keys_index, key2); - write_element(0, compare_keys_index, key1); - for (int64 i = 1; i <= num_values; ++i) { - // Also swap the values. - auto value1 = read_element(i, current_keys_index); - auto value2 = read_element(i, compare_keys_index); - write_element(i, current_keys_index, value2); - write_element(i, compare_keys_index, value1); - } - }); + compare_key2, compare_key1); + if (iota_values_parameter_index >= 0) { + auto keys_equal = b->CreateICmpEQ(compare_key1, compare_key2); + auto key_index1 = + read_element(iota_values_parameter_index, current_keys_index); + auto key_index2 = + read_element(iota_values_parameter_index, compare_keys_index); + auto index_is_smaller_than = + b->CreateICmp(llvm::ICmpInst::ICMP_ULT, key_index2, key_index1); + is_smaller_than = b->CreateOr( + is_smaller_than, b->CreateAnd(keys_equal, index_is_smaller_than)); + } + ksl.IfReturnVoid("is_smaller_than", is_smaller_than, [&]() { + // Swap key1 with key2. + write_element(0, current_keys_index, key2); + write_element(0, compare_keys_index, key1); + for (int64 i = 1; i <= num_values; ++i) { + // Also swap the values. + auto value1 = read_element(i, current_keys_index); + auto value2 = read_element(i, compare_keys_index); + write_element(i, current_keys_index, value2); + write_element(i, compare_keys_index, value1); + } + }); }); } -void EmitTiledCompareLoop(const IrArray::Index& tiled_keys_index, - int64 dimension_to_sort, - int64 dimension_to_sort_bound, - PrimitiveType keys_type, - absl::Span xor_masks, - const std::vector& params, - const std::vector& param_shmem_buffers, - int64 tile_size, llvm::IRBuilder<>* b) { +void EmitTiledCompareLoop( + const IrArray::Index& tiled_keys_index, int64 dimension_to_sort, + int64 dimension_to_sort_bound, PrimitiveType keys_type, + absl::Span xor_masks, const std::vector& params, + const std::vector& param_shmem_buffers, + int64 iota_values_parameter_index, int64 tile_size, llvm::IRBuilder<>* b) { KernelSupportLibrary ksl(b); llvm::Value* thread_id = llvm_ir::EmitCallToIntrinsic( llvm::Intrinsic::nvvm_read_ptx_sreg_tid_x, {}, {}, b); @@ -253,20 +262,22 @@ void EmitTiledCompareLoop(const IrArray::Index& tiled_keys_index, RoundDownToNearest(dimension_to_sort_bound, tile_size))), [&]() { EmitCompareLoopBody(dimension_to_sort_bound % tile_size, keys_type, - params.size() - 1, element_pair_index, xor_mask, + params.size() - 1, iota_values_parameter_index, + element_pair_index, xor_mask, tiled_keys_index.GetType(), read_element, write_element, b); }, [&]() { - EmitCompareLoopBody( - tile_size, keys_type, params.size() - 1, element_pair_index, - xor_mask, tiled_keys_index.GetType(), read_element, - write_element, b, /*needs_bounds_checks=*/false); + EmitCompareLoopBody(tile_size, keys_type, params.size() - 1, + iota_values_parameter_index, element_pair_index, + xor_mask, tiled_keys_index.GetType(), + read_element, write_element, b, + /*needs_bounds_checks=*/false); }); } else { EmitCompareLoopBody(tile_size, keys_type, params.size() - 1, - element_pair_index, xor_mask, - tiled_keys_index.GetType(), read_element, + iota_values_parameter_index, element_pair_index, + xor_mask, tiled_keys_index.GetType(), read_element, write_element, b, /*needs_bounds_checks=*/false); } // Wait until all comparisons have happened. @@ -296,6 +307,7 @@ void EmitTiledCompareLoop(const IrArray::Index& tiled_keys_index, Status EmitSortInPlace(int64 dimension_to_sort, const IrArray& keys_array, const std::vector& values_arrays, + int64 iota_values_parameter_index, absl::string_view name, absl::Span xor_masks, llvm::IRBuilder<>* b, const gpu::LaunchDimensions& launch_dimensions, @@ -367,8 +379,8 @@ Status EmitSortInPlace(int64 dimension_to_sort, const IrArray& keys_array, if (xor_masks.size() > 1) { EmitTiledCompareLoop(keys_index, dimension_to_sort, dimension_to_sort_bound, keys_shape.element_type(), - xor_masks, params, param_shmem_buffers, tile_size, - b); + xor_masks, params, param_shmem_buffers, + iota_values_parameter_index, tile_size, b); } else { auto read_element = [&](int64 operand, llvm::Value* index) { keys_index[dimension_to_sort] = index; @@ -380,9 +392,10 @@ Status EmitSortInPlace(int64 dimension_to_sort, const IrArray& keys_array, params[operand].EmitWriteArrayElement(keys_index, value, b); }; EmitCompareLoopBody(dimension_to_sort_bound, keys_shape.element_type(), - values_arrays.size(), tiles_index[rank - 1], - xor_masks[0], tiles_index.GetType(), read_element, - write_element, b); + values_arrays.size(), iota_values_parameter_index, + tiles_index[rank - 1], xor_masks[0], + tiles_index.GetType(), read_element, write_element, + b); } return Status::OK(); }; diff --git a/tensorflow/compiler/xla/service/llvm_ir/sort_util.h b/tensorflow/compiler/xla/service/llvm_ir/sort_util.h index 556a217322..685f9383ac 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/sort_util.h +++ b/tensorflow/compiler/xla/service/llvm_ir/sort_util.h @@ -31,9 +31,12 @@ namespace llvm_ir { // Emits llvm IR to do pairwise comparisons/swaps in the 'dimension_to_sort' // dimension of 'keys_array'. All other dimensions are kept as-is. This // implements the inner loop of BitonicSort. It is assumed that 'xor_masks' -// contains only powers of 2, or values 2^k - 1 (k > 0). +// contains only powers of 2, or values 2^k - 1 (k > 0). If +// 'iota_values_parameter_index' is >= 0, it points at a 'values_arrays' operand +// that is a iota and can be used to make the sorting stable. Status EmitSortInPlace(int64 dimension_to_sort, const IrArray& keys_array, const std::vector& values_arrays, + int64 iota_values_parameter_index, absl::string_view name, absl::Span xor_masks, llvm::IRBuilder<>* b, const gpu::LaunchDimensions& launch_dimensions, diff --git a/tensorflow/compiler/xla/service/local_service.cc b/tensorflow/compiler/xla/service/local_service.cc index cca3755617..6c89700983 100644 --- a/tensorflow/compiler/xla/service/local_service.cc +++ b/tensorflow/compiler/xla/service/local_service.cc @@ -96,44 +96,18 @@ ExecutionOptions CreateExecutionOptions( const ExecutableBuildOptions& build_options, const ProgramShape* program_shape) { ExecutionOptions execution_options = CreateDefaultExecutionOptions(); - if (build_options.hlo_profile().has_value()) { - execution_options.mutable_debug_options()->set_xla_hlo_profile( - *build_options.hlo_profile()); - } - if (build_options.generate_hlo_graph().has_value()) { - execution_options.mutable_debug_options()->set_xla_generate_hlo_graph( - build_options.generate_hlo_graph().value()); - } - if (build_options.dump_optimized_hlo_proto_to().has_value()) { - execution_options.mutable_debug_options() - ->set_xla_dump_optimized_hlo_proto_to( - build_options.dump_optimized_hlo_proto_to().value()); - } - if (build_options.dump_unoptimized_hlo_proto_to().has_value()) { - execution_options.mutable_debug_options() - ->set_xla_dump_unoptimized_hlo_proto_to( - build_options.dump_unoptimized_hlo_proto_to().value()); - } - if (build_options.dump_per_pass_hlo_proto_to().has_value()) { - execution_options.mutable_debug_options() - ->set_xla_dump_per_pass_hlo_proto_to( - build_options.dump_per_pass_hlo_proto_to().value()); + if (build_options.has_debug_options()) { + *execution_options.mutable_debug_options() = build_options.debug_options(); } if (build_options.result_layout() != nullptr) { *execution_options.mutable_shape_with_output_layout() = - *build_options.result_layout(); + build_options.result_layout()->ToProto(); } else { + Shape result_shape(program_shape->result()); + LayoutUtil::SetToDefaultLayout(&result_shape); *execution_options.mutable_shape_with_output_layout() = - program_shape->result(); - LayoutUtil::SetToDefaultLayout( - execution_options.mutable_shape_with_output_layout()); + result_shape.ToProto(); } - - for (const std::string& disabled_pass : build_options.disabled_hlo_passes()) { - execution_options.mutable_debug_options()->add_xla_disable_hlo_passes( - disabled_pass); - } - return execution_options; } @@ -145,7 +119,7 @@ StatusOr> LocalService::CompileExecutable( const ExecutableBuildOptions& build_options) { const HloModuleProto& proto = computation.proto(); TF_RET_CHECK(proto.has_host_program_shape()); - const ProgramShape& program_shape = proto.host_program_shape(); + ProgramShape program_shape(proto.host_program_shape()); // Validate incoming layouts. if (argument_layouts.size() != program_shape.parameters_size()) { @@ -220,4 +194,10 @@ StatusOr LocalService::GlobalDataToShapedBuffer( return buffers[replica_number]; } +StatusOr LocalService::RegisterReplicatedBuffers( + std::vector replicated_buffers, const string& tag) { + return allocation_tracker_.RegisterReplicatedBuffers( + std::move(replicated_buffers), tag); +} + } // namespace xla diff --git a/tensorflow/compiler/xla/service/local_service.h b/tensorflow/compiler/xla/service/local_service.h index 3b4f0b5083..f56ba32b04 100644 --- a/tensorflow/compiler/xla/service/local_service.h +++ b/tensorflow/compiler/xla/service/local_service.h @@ -63,6 +63,11 @@ class LocalService : public Service { StatusOr GlobalDataToShapedBuffer( const GlobalDataHandle& data, int replica_number); + // Registers a vector of shaped buffers of device memory, one per replica, and + // returns a corresponding handle that can be used for talking to XLA clients. + StatusOr RegisterReplicatedBuffers( + std::vector replicated_buffers, const string& tag); + private: explicit LocalService(const ServiceOptions& options, std::unique_ptr backend); diff --git a/tensorflow/compiler/xla/service/logical_buffer_analysis.cc b/tensorflow/compiler/xla/service/logical_buffer_analysis.cc index ec52a24d78..972a5b9ced 100644 --- a/tensorflow/compiler/xla/service/logical_buffer_analysis.cc +++ b/tensorflow/compiler/xla/service/logical_buffer_analysis.cc @@ -113,6 +113,13 @@ Status LogicalBufferAnalysis::HandleGetTupleElement(HloInstruction*) { return Status::OK(); } +Status LogicalBufferAnalysis::HandleAddDependency( + HloInstruction* add_dependency) { + // AddDependency just forwards the value of its zero-th operand and does not + // create buffers. + return Status::OK(); +} + Status LogicalBufferAnalysis::HandleCopy(HloInstruction* copy) { // The top-level buffer (index={}) for kCopy is newly created, but all other // buffers (in the case of a tuple shape) come from the operand diff --git a/tensorflow/compiler/xla/service/logical_buffer_analysis.h b/tensorflow/compiler/xla/service/logical_buffer_analysis.h index 81f524d84a..7ffca943d0 100644 --- a/tensorflow/compiler/xla/service/logical_buffer_analysis.h +++ b/tensorflow/compiler/xla/service/logical_buffer_analysis.h @@ -64,6 +64,7 @@ class LogicalBufferAnalysis : public DfsHloVisitorWithDefault { Status HandleRecvDone(HloInstruction* recv_done) override; Status HandleSend(HloInstruction* send) override; Status HandleTupleSelect(HloInstruction* tuple_select) override; + Status HandleAddDependency(HloInstruction* add_dependency) override; // A map from the buffer ID to the logical buffer std::vector> logical_buffers_; diff --git a/tensorflow/compiler/xla/service/pattern_matcher.h b/tensorflow/compiler/xla/service/pattern_matcher.h index 6152cdc609..432aa1ea0b 100644 --- a/tensorflow/compiler/xla/service/pattern_matcher.h +++ b/tensorflow/compiler/xla/service/pattern_matcher.h @@ -16,6 +16,7 @@ limitations under the License. #ifndef TENSORFLOW_COMPILER_XLA_SERVICE_PATTERN_MATCHER_H_ #define TENSORFLOW_COMPILER_XLA_SERVICE_PATTERN_MATCHER_H_ +#include "absl/strings/str_replace.h" #include "absl/strings/string_view.h" #include "absl/utility/utility.h" #include "tensorflow/compiler/xla/layout_util.h" @@ -44,32 +45,48 @@ namespace xla { // // This pattern will match Add instructions whose first operand is a constant. // -// Each pattern type has the following modifiers: +// Each pattern type has the following modifiers, which are described where +// nontrivial. // // Op(): -// - WithName: match operations with the given name -// - WithOpcode: match operations with the given opcode -// - WithShape: match operations whose shape matches the given pattern -// - WithOperand: match operations whose operand matches the given pattern +// - Is: is the given HloInstruction* (i.e. pointer equality) +// - WithName +// - WithOpcode +// - WithoutOpcode: anything other than the given opcode +// - WithShape: instr's shape matches the given pattern +// - WithShapeEqualTo: instr's shape is equal to the given Shape +// - WithShapeCompatibleTo: instr's shape is compatible with the given Shape +// - WithNumOperands +// - WithOperand: operand at the given index matches the given pattern +// - IsConstant +// - IsNonConstant +// - IsConstantScalar/IsEffectiveConstantScalar: Optionally accepts a value, +// e.g. IsConstantScalar() or IsConstantScalar(42). +// - WithFusionKind +// - WithTupleIndex: get-tuple-element operations with the given tuple index +// - WithOneUse: Instruction is used as an operand exactly once. +// - WithOneUser: Instruction is used by exactly one other instruction, but +// is possibly used more than once as an operand (e.g. multiply(x,x)). // // Shape(): -// - EqualTo: matches shapes that are equal to the argument -// - CompatibleTo: matches shapes that are compatible to the argument -// - IsScalar/IsArray/IsTuple: matches scalar/array/tuple shapes -// - IsDenseArray/IsSparseArray: matches arrays with dense/sparse format -// - WithLayout: match shapes whose layout matches the given pattern -// - WithLayoutEqualTo: matches shapes whose layouts equal the argument -// - WithSubshape: matches tuple shapes whose subshape matches the given -// pattern -// - WithSubshapeEqualTo: matches shapes with a subshape equal the argument -// - WithElementType: matches array/scalar shapes with the given element -// type -// - WithRank: matches array/scalar types with the given rank +// - EqualTo +// - CompatibleTo +// - IsScalar/IsEffectiveScalar/IsArray/IsTuple +// - IsDenseArray/IsSparseArray +// - WithLayout: layout shape's layout matches the given pattern (e.g. +// Layout().WithDenseFormat()) +// - WithLayoutEqualTo: shape's layout equals the argument (i.e. another +// Layout, but not the result of Layout().foo()) +// - WithSubshape: shape is a tuple whose subshape matches the given pattern +// (e.g. Shape().IsScalar()). +// - WithSubshapeEqualTo: shape is a tuple with a subshape equal to the arg +// (i.e. another Shape, but not the result of Shape().foo()) +// - WithElementType: shape is an array/scalar with the given elem type +// - WithRank: shape is an array/scalar with the given rank // // Layout(): -// - EqualTo: matches layouts that are equal to the argument -// - WithDenseFormat/WithSparseFormat: matches layouts with dense/sparse -// format +// - EqualTo +// - WithDenseFormat/WithSparseFormat // // Op(), Shape(), and Layout() may be passed an argument of type // HloInstruction**, Shape**, or Layout**, respectively, or const versions of @@ -82,53 +99,55 @@ namespace xla { // CHECK(Match(foo, // match::Op().WithOperand(0, match::Op(&matched_operand)))); // -// Helpers are provided for common nullary, unary, binary, and ternary -// instructions. These helpers can be called with no arguments, in which case -// they will match any instruction matching the opcode. They may also be called -// with matches for the operands and with an optional capture. (The capture must -// be the first argument.) Some examples of these helpers and their equivalents -// are provided below. -// +// Helpers are provided for most HLO instructions. These helpers can be called +// with no arguments, in which case they will match any instruction matching the +// opcode. They may also be called with matches for the operands and with an +// optional capture. (The capture must be the first argument.) Some examples of +// these helpers and their equivalents are provided below. + // Example nullary instruction: -// Param() == Op().WithOpcode(HloOpcode::kParam) -// Param(&a) == Op(&a).WithOpcode(HloOpcode::kParam) +// Parameter() == Op().WithOpcode(HloOpcode::kParameter) +// Parameter(&a) == Op(&a).WithOpcode(HloOpcode::kParameter) // // Example unary instruction: -// Abs() == Op().WithOpcode(HloOpcode::kAbs) -// Abs(Op(&a)) == Op().WithOpcode(HloOpcode::kAbs) -// .WithOperand(0, Op(&a))) -// Abs(&a, Op(&b)) == Op(&a).WithOpcode(HloOpcode::kAbs) -// .WithOperand(0, Op(&b)) +// Abs() == Op().WithOpcode(HloOpcode::kAbs) +// Abs(Op(&a)) == Op().WithOpcode(HloOpcode::kAbs) +// .WithOperand(0, Op(&a))) +// Abs(&a, Op(&b)) == Op(&a).WithOpcode(HloOpcode::kAbs) +// .WithOperand(0, Op(&b)) +// +// Commutative binary instructions have a special form that accepts either order +// of args, e.g.: +// +// AddAnyOrder(Parameter(1), Abs()) == +// Op().WithOpcode(HloOpcode::kAdd) +// .WithBinaryOperandsAnyOrder(Op().WithParameterNum(1), Abs()); // -// Example binary instruction: -// Add() == Op().WithOpcode(HloOpcode::kAdd) -// Add(Op(&a), Op(&b)) == Op().WithOpcode(HloOpcode::kAdd) -// .WithOperand(0, Op(&a)) -// .WithOperand(1, Op(&b)) -// Add(&a, Op(&b), Op(&c)) == Op(&a).WithOpcode(HloOpcode::kAdd) -// .WithOperand(0, Op(&b)) -// .WithOperand(1, Op(&c)) +// MultiplyAnyOrder(&a, Parameter(), Abs()) // Captures the mul in `a`. // -// Example ternary instruction: -// Clamp() == Op().WithOpcode(HloOpcode::kClamp) -// Clamp(Op(&a), Op(&b), Op(&c)) == Op().WithOpcode(HloOpcode::kClamp) -// .WithOperand(0, Op(&a)) -// .WithOperand(1, Op(&b)) -// .WithOperand(2, Op(&c)) -// Clamp(&a, Op(&b), Op(&c), Op(&d)) == Op(&a).WithOpcode(HloOpcode::kClamp) -// .WithOperand(0, Op(&b)) -// .WithOperand(1, Op(&c)) -// .WithOperand(2, Op(&d)) +// The following additional helpers are provided. In all cases, `&a` is +// optional. // +// ConstantScalar(&a) == Op(&a).IsConstantScalar(); +// ConstantScalar(&a, v) == Op(&a).IsConstantScalar(v); +// ConstantEffectiveScalar(&a) == Op(&a).IsConstantEffectiveScalar(); +// ConstantEffectiveScalar(&a, v) == Op(&a).IsConstantEffectiveScalar(&a, v) +// NonConstant(&a) == Op(&a).IsNonConstant() +// GetTupleElement(&a, b, index) == Op(&a).WithTupleIndex(index) +// .WithOperand(0, b); +// Parameter(&a, n) == Op(&a).WithParameterNum(n); struct MatchOption { // If true, actually capture matched item into the user pointer. bool capture; + + // An explanation for why we failed to match is streamed here, if not-null. + std::ostream* explain_os; }; template bool Match(Value* value, const Pattern& pattern, - MatchOption option = {/*.capture=*/true}) { + MatchOption option = {/*.capture=*/true, /*.explain_os=*/nullptr}) { if (option.capture) { auto new_option = option; new_option.capture = false; @@ -143,6 +162,77 @@ namespace match { namespace detail { +// Macro for streaming to option.explain_os if it's not null. +// +// EXPLAIN << "value of foo(): " << foo() +// +#pragma push_macro("EXPLAIN") +#define EXPLAIN \ + if (option.explain_os) *option.explain_os + +// kIndentInc is the additional number of spaces that we indent by when we +// increase the indent "by one". +enum { + kIndentInc = 2, +}; + +// Writes a newline and then `indent` spaces. +// +// We follow an unintuitive convention in this file's pretty-printers: Indents +// are performed by the caller, not the callee. For example, if you want to +// print +// +// foo: +// - bar +// +// you'd do: +// +// Foo::DescribeTo(std::ostream* os, int64 indent) { +// *os << "foo:"; +// Indent(os, indent) // Create a newline at the *current* indent level. +// *os << " - "; +// bar.DescribeTo(os, indent + 3); // + 3 because strlen(" * ") == 3. +// } +// +// Bar::DescribeTo(std::ostream* os, int64 indent) { *os << "bar"; } +// +// Notice that Bar::DescribeTo() does not call Indent; the indenting is +// performed by Foo. This convention allows the caller to decide whether a +// matcher is preceded by a newline, which is important e.g. for the AllOf +// matcher. +// +// (Incidentally, indenting in Match's explanations is handled differently. +// Indents are a common case in DescribeTo [we're printing a whole tree], but +// they're a special case in Match [we're printing only a path through the tree +// that encounters a failing node]. Indents in Match only appear when we +// encounter a failing disjunction, so we just handle them as a special case +// there.) +inline void Indent(std::ostream* os, int64 indent) { + *os << "\n"; + for (int64 i = 0; i < indent; ++i) { + *os << " "; + } +} + +// SFINAE template that determines whether T declares a static member +// kIsTrivialMatcher. +// +// Trivial matchers get special treatment. For example, when printing +// a conjunction of matchers, we don't print "and" after a trivial matcher. This +// yields e.g. +// "a shape compatible with f32[1,2]" +// rather than +// "a shape AND compatible with f32[1,2]" +template +struct IsTrivialMatcher { + static constexpr bool value = false; +}; +template +struct IsTrivialMatcher::type> { + static constexpr bool value = true; +}; + template class AllOfPattern { public: @@ -162,10 +252,19 @@ class AllOfPattern { return matched; } + void DescribeTo(std::ostream* os, int64 indent = 0) const { + DescribeToImpl(os, std::integral_constant(), indent); + } + + // Accessor for patterns_. Please don't use this outside of this file. + const std::tuple& patterns() const { return patterns_; } + private: template bool MatchImpl(ItemType* item, MatchOption option, std::integral_constant) const { + // We don't need to do any EXPLAINing here; it's all correctly handled by + // our sub-matchers (if any fail). return std::get(patterns_).Match(item, option) && MatchImpl(item, option, std::integral_constant()); } @@ -176,6 +275,73 @@ class AllOfPattern { return true; } + // Pretty-printing a conjunction has some special cases to make it easy to + // read in the simple (common) case. + // + // If sizeof...(Patterns) == 1, prints as e.g. + // + // a shape + // + // If sizeof...(Patterns) == 2 and patterns_[0] is a trivial matcher (e.g. "a + // shape") prints as + // + // a shape compatible with f32[1,2] + // + // If sizeof...(Patterns) > 2 and patterns_[0] is a trivial matcher, prints as + // + // a shape: + // * compatible with f32[1,2] AND + // * that represents a scalar + // + // Otherwise prints as: + // + // all of: + // * foo AND + // * bar + // + template + void DescribeToImpl(std::ostream* os, std::integral_constant, + int64 indent) const { + constexpr bool first_is_trivial = + IsTrivialMatcher(patterns_))>::type>::value; + constexpr bool is_last = index == sizeof...(Patterns) - 1; + const auto& submatcher = std::get(patterns_); + + auto print_bulleted_item = [&] { + *os << " * "; + submatcher.DescribeTo(os, indent + 3); + if (!is_last) { + *os << " AND"; + Indent(os, indent); + } + }; + + if (index == 0) { + if (first_is_trivial || is_last) { + submatcher.DescribeTo(os, indent + kIndentInc); + if (sizeof...(Patterns) > 2) { + *os << ":"; + Indent(os, indent); + } + } else { + *os << "all of:"; + Indent(os, indent); + print_bulleted_item(); + } + } else if (first_is_trivial && index == 1 && sizeof...(Patterns) == 2) { + *os << " "; + submatcher.DescribeTo(os, indent); + } else { + print_bulleted_item(); + } + DescribeToImpl(os, std::integral_constant(), indent); + } + + void DescribeToImpl(std::ostream* os, + std::integral_constant, + int64 indent) const {} + std::tuple patterns_; }; @@ -183,10 +349,6 @@ class AllOfPattern { // Returns a pattern that represents the conjunction of all input patterns. All // patterns need to match in order to have the AllOf pattern match. -// -// TODO(timshen): Currently AllOf is still nested, e.g. AllOf, B> is -// not AllOf. We might want to flatten the AllOf type structure if the -// C++ compile error message gets annoying. template detail::AllOfPattern::type, Patterns...> AllOf( const Patterns&... patterns) { @@ -194,6 +356,25 @@ detail::AllOfPattern::type, Patterns...> AllOf( Patterns...>(patterns...); } +// AllOf, X, Y, ...> => AllOf. +// +// This transformation is necessary for good pretty-printing. +template +detail::AllOfPattern::type, InnerPs..., + OuterPs...> +AllOf(const detail::AllOfPattern& inner_p, + const OuterPs&... outer_ps) { + // Invoke constructor of AllOfPattern. + auto make_all_of = [](const InnerPs&... inner_ps, + const OuterPs&... outer_ps) { + return detail::AllOfPattern::type, + InnerPs..., OuterPs...>(inner_ps..., + outer_ps...); + }; + return absl::apply(make_all_of, std::tuple_cat(inner_p.patterns(), + std::make_tuple(outer_ps...))); +} + namespace detail { template @@ -204,8 +385,18 @@ class LayoutPattern; class LayoutPatternBaseImpl { public: bool Match(const ::xla::Layout* layout, MatchOption option) const { - return layout != nullptr; + if (layout == nullptr) { + EXPLAIN << "Layout is null"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "a layout"; } + + static constexpr bool kIsTrivialMatcher = true; }; // A LayoutPattern implementation that matches only if the layout equals a @@ -216,7 +407,17 @@ class LayoutPatternEqualImpl { : layout_(layout) {} bool Match(const ::xla::Layout* layout, MatchOption option) const { - return LayoutUtil::Equal(*layout_, *layout); + if (!LayoutUtil::Equal(*layout_, *layout)) { + EXPLAIN << "Layout " << LayoutUtil::HumanString(*layout) + << " is not equal to expected " + << LayoutUtil::HumanString(*layout_); + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "equal to " << LayoutUtil::HumanString(*layout_); } private: @@ -230,7 +431,16 @@ class LayoutPatternFormatImpl { explicit constexpr LayoutPatternFormatImpl(Format format) : format_(format) {} bool Match(const ::xla::Layout* layout, MatchOption option) const { - return layout->format() == format_; + if (layout->format() != format_) { + EXPLAIN << "Layout has format " << Format_Name(layout->format()) + << " but expected " << Format_Name(format_); + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "with format " << Format_Name(format_); } private: @@ -242,11 +452,13 @@ template class LayoutPattern { private: template - LayoutPattern> - AppendImpl(NewImpl new_impl) const { - return LayoutPattern>( - AllOf(impl_, std::move(new_impl)), matched_layout_); + auto AppendImpl(NewImpl new_impl) const + -> LayoutPattern(std::declval(), + std::move(new_impl)))> { + auto new_allof = AllOf(impl_, std::move(new_impl)); + return LayoutPattern(std::move(new_allof), + matched_layout_); } public: @@ -276,6 +488,10 @@ class LayoutPattern { return false; } + void DescribeTo(std::ostream* os, int64 indent = 0) const { + impl_.DescribeTo(os, indent); + } + // Modifies the pattern to match only if the layout equals the given proto. // The layout must outlive the returned pattern. constexpr auto EqualTo(const ::xla::Layout* layout) const @@ -306,19 +522,48 @@ class AnyOfPattern { explicit AnyOfPattern(const Patterns&... patterns) : patterns_(patterns...) {} bool Match(const Item* item, MatchOption option) const { - return MatchImpl(item, option, std::integral_constant()); + return MatchImpl(item, option); } bool Match(Item* item, MatchOption option) const { - return MatchImpl(item, option, std::integral_constant()); + return MatchImpl(item, option); + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "any of:"; + Indent(os, indent); + DescribeToImpl(os, std::integral_constant(), indent); } private: + template + bool MatchImpl(ItemType* item, MatchOption option) const { + // If we're generating an explanation, buffer it until we know we failed. + absl::optional explanation; + MatchOption new_option = option; + if (option.explain_os) { + new_option.explain_os = &explanation.emplace(); + } + bool rv = MatchRecursiveImpl(item, new_option, + std::integral_constant()); + if (!rv && option.explain_os) { + EXPLAIN << "None of the following matchers succeeded:"; + EXPLAIN << explanation->str(); + } + return rv; + } + template - bool MatchImpl(ItemType* item, MatchOption option, - std::integral_constant) const { + bool MatchRecursiveImpl(ItemType* item, MatchOption option, + std::integral_constant) const { auto new_option = option; new_option.capture = false; + + absl::optional explanation; + if (option.explain_os) { + new_option.explain_os = &explanation.emplace(); + } + // Try to match the sub-pattern without capturing behavior. if (std::get(patterns_).Match(item, new_option)) { // Capture the branch. @@ -337,20 +582,46 @@ class AnyOfPattern { // AnyOf will be a runtime number indicate which sub-pattern is matched. // Then we run another pass to do captures only with the help of the // trace. - bool ret = std::get(patterns_).Match(item, option); - DCHECK(ret); + bool matched = std::get(patterns_).Match(item, option); + DCHECK(matched); } return true; } - return MatchImpl(item, option, std::integral_constant()); + if (option.explain_os) { + EXPLAIN << "\nMatcher #" << index + 1; + EXPLAIN << "\n - "; + std::get(patterns_).DescribeTo(option.explain_os, /*indent=*/3); + EXPLAIN << "\nfailed with"; + EXPLAIN << "\n - "; + EXPLAIN << absl::StrReplaceAll(explanation->str(), {{"\n", "\n "}}); + } + return MatchRecursiveImpl(item, option, + std::integral_constant()); } template - bool MatchImpl(ItemType* item, MatchOption option, - std::integral_constant) const { + bool MatchRecursiveImpl( + ItemType* item, MatchOption option, + std::integral_constant) const { return false; } + template + void DescribeToImpl(std::ostream* os, std::integral_constant, + int64 indent) const { + *os << " - "; + std::get(patterns_).DescribeTo(os, indent + 3); + if (index != sizeof...(Patterns) - 1) { + *os << " OR"; + Indent(os, indent); + } + DescribeToImpl(os, std::integral_constant(), indent); + } + + void DescribeToImpl(std::ostream* os, + std::integral_constant, + int64 indent) const {} + std::tuple patterns_; }; @@ -395,8 +666,17 @@ class ShapePattern; class ShapePatternBaseImpl { public: bool Match(const ::xla::Shape* shape, MatchOption option) const { + if (shape == nullptr) { + EXPLAIN << "Shape is null"; + } return shape != nullptr; } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "a shape"; + } + + static constexpr bool kIsTrivialMatcher = true; }; // A ShapePattern implementation that matches only if the shape equals a Shape @@ -407,7 +687,16 @@ class ShapePatternEqualImpl { : shape_(shape) {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - return ShapeUtil::Equal(*shape_, *shape); + if (!ShapeUtil::Equal(*shape_, *shape)) { + EXPLAIN << "Shape not equal to " + << ShapeUtil::HumanStringWithLayout(*shape_); + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "equal to " << ShapeUtil::HumanStringWithLayout(*shape_); } private: @@ -422,7 +711,16 @@ class ShapePatternCompatibleImpl { : shape_(shape) {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - return ShapeUtil::Compatible(*shape_, *shape); + if (!ShapeUtil::Compatible(*shape_, *shape)) { + EXPLAIN << "Shape not compatible with " + << ShapeUtil::HumanString(*shape_); + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "compatible with " << ShapeUtil::HumanString(*shape_); } private: @@ -437,7 +735,16 @@ class ShapePatternElementTypeImpl { : element_type_(element_type) {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - return shape->element_type() == element_type_; + if (shape->element_type() != element_type_) { + EXPLAIN << "Shape does not have element type " + << PrimitiveType_Name(element_type_); + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "with element type " << PrimitiveType_Name(element_type_); } private: @@ -450,7 +757,15 @@ class ShapePatternIsScalarImpl { explicit constexpr ShapePatternIsScalarImpl() {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - return ShapeUtil::IsScalar(*shape); + if (!ShapeUtil::IsScalar(*shape)) { + EXPLAIN << "Shape is not a scalar"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "that represents a scalar"; } }; @@ -460,7 +775,15 @@ class ShapePatternIsArrayImpl { explicit constexpr ShapePatternIsArrayImpl() {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - return ShapeUtil::IsArray(*shape); + if (!ShapeUtil::IsArray(*shape)) { + EXPLAIN << "Shape is not an array"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "that represents an array"; } }; @@ -470,7 +793,34 @@ class ShapePatternIsTupleImpl { explicit constexpr ShapePatternIsTupleImpl() {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - return ShapeUtil::IsTuple(*shape); + if (!ShapeUtil::IsTuple(*shape)) { + EXPLAIN << "Shape is not a tuple"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "that represents a tuple"; + } +}; + +// A ShapePattern implementation that matches only if the shape is an effective +// scalar. +class ShapePatternEffectiveScalarImpl { + public: + explicit constexpr ShapePatternEffectiveScalarImpl() {} + + bool Match(const ::xla::Shape* shape, MatchOption option) const { + if (!ShapeUtil::IsEffectiveScalar(*shape)) { + EXPLAIN << "Shape is not an effective scalar"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "that is an effective scalar"; } }; @@ -481,7 +831,23 @@ class ShapePatternRankImpl { explicit constexpr ShapePatternRankImpl(int64 rank) : rank_(rank) {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - return ShapeUtil::Rank(*shape) == rank_; + if (ShapeUtil::Rank(*shape) != rank_) { + if (rank_ == 0) { + EXPLAIN << "Shape is not a scalar"; + } else { + EXPLAIN << "Shape does not have rank " << rank_; + } + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + if (rank_ == 0) { + *os << "that is a scalar"; + } else { + *os << "that has " << rank_ << " dimension" << (rank_ != 1 ? "s" : ""); + } } private: @@ -503,8 +869,21 @@ class ShapePatternLayoutImpl { } bool Match(Shape* shape, MatchOption option) const { - return LayoutUtil::HasLayout(*shape) && - layout_.Match(shape->mutable_layout(), option); + if (!LayoutUtil::HasLayout(*shape)) { + EXPLAIN << "Shape does not have a layout"; + return false; + } + if (!layout_.Match(shape->mutable_layout(), option)) { + EXPLAIN << "\nin layout"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "with"; + Indent(os, indent + kIndentInc); + layout_.DescribeTo(os, indent + kIndentInc); } private: @@ -522,17 +901,40 @@ class ShapePatternSubshapeImpl { : index_(index), subshape_(subshape) {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - return ShapeUtil::IndexIsValid(*shape, index_) && - subshape_.Match(&ShapeUtil::GetSubshape(*shape, index_), option); + return MatchImpl(shape, option); } bool Match(::xla::Shape* shape, MatchOption option) const { - return ShapeUtil::IndexIsValid(*shape, index_) && - subshape_.Match(ShapeUtil::GetMutableSubshape(shape, index_), - option); + return MatchImpl(shape, option); + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "with subshape at index " << index_.ToString() << " which is"; + Indent(os, indent + kIndentInc); + subshape_.DescribeTo(os, indent + kIndentInc); } private: + Shape* GetSubshape(Shape* shape) const { + return ShapeUtil::GetMutableSubshape(shape, index_); + } + const Shape* GetSubshape(const Shape* shape) const { + return &ShapeUtil::GetSubshape(*shape, index_); + } + + template + bool MatchImpl(ShapeType* shape, MatchOption option) const { + if (!ShapeUtil::IndexIsValid(*shape, index_)) { + EXPLAIN << "No subshape at " << index_.ToString(); + return false; + } + if (!subshape_.Match(GetSubshape(shape), option)) { + EXPLAIN << "\nin subshape at " << index_.ToString(); + return false; + } + return true; + } + ShapeIndexView index_; ShapePattern subshape_; }; @@ -542,10 +944,12 @@ template class ShapePattern { private: template - ShapePattern> AppendImpl( - NewImpl new_impl) const { - return ShapePattern>( - AllOf(impl_, std::move(new_impl)), matched_shape_); + auto AppendImpl(NewImpl new_impl) const + -> ShapePattern(std::declval(), + std::move(new_impl)))> { + auto new_all_of = AllOf(impl_, std::move(new_impl)); + return ShapePattern(std::move(new_all_of), + matched_shape_); } public: @@ -560,6 +964,11 @@ class ShapePattern { } return true; } + if (shape) { + EXPLAIN << "\nin " + << (shape->has_layout() ? ShapeUtil::HumanStringWithLayout(*shape) + : ShapeUtil::HumanString(*shape)); + } return false; } @@ -571,9 +980,16 @@ class ShapePattern { } return true; } + EXPLAIN << "\nin " + << (shape->has_layout() ? ShapeUtil::HumanStringWithLayout(*shape) + : ShapeUtil::HumanString(*shape)); return false; } + void DescribeTo(std::ostream* os, int64 indent = 0) const { + return impl_.DescribeTo(os, indent); + } + // Modifies the pattern to match only if the shape equals the given proto. // The layout must outlive the returned pattern. constexpr auto EqualTo(const ::xla::Shape* shape) const @@ -612,6 +1028,11 @@ class ShapePattern { return AppendImpl(ShapePatternIsTupleImpl()); } + constexpr auto IsEffectiveScalar() const + -> decltype(this->AppendImpl(ShapePatternEffectiveScalarImpl())) { + return AppendImpl(ShapePatternEffectiveScalarImpl()); + } + // Modifies the pattern to match only if the shape has the given rank. constexpr auto WithRank(int64 rank) const -> decltype(this->AppendImpl(ShapePatternRankImpl(rank))) { @@ -706,6 +1127,22 @@ Shape(::xla::Shape** matched_shape) { namespace detail { +// Overloads to get a const or non-const operand out of an instruction. +inline HloInstruction* HloOperand(HloInstruction* instr, int64 idx) { + return instr->mutable_operand(idx); +} +inline const HloInstruction* HloOperand(const HloInstruction* instr, + int64 idx) { + return instr->operand(idx); +} + +// Pretty-printer for HloInstruction. Sort of like ToShortString, but with +// fewer %s and more shapes. +inline string InstToString(const HloInstruction* inst) { + return inst->ToString( + HloPrintOptions().set_print_metadata(false).set_print_percent(false)); +} + template class HloInstructionPattern; @@ -714,8 +1151,18 @@ class HloInstructionPattern; class HloInstructionPatternBaseImpl { public: bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { - return inst != nullptr; + if (inst == nullptr) { + EXPLAIN << "HloInstruction* is null"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "an HloInstruction"; } + + static constexpr bool kIsTrivialMatcher = true; }; // An HloInstructionPattern implementation that matches only if the instruction @@ -726,13 +1173,44 @@ class HloInstructionPatternNameImpl { : name_(name) {} bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { - return inst->name() == name_; + if (inst->name() != name_) { + EXPLAIN << "HloInstruction not named \"" << name_ << "\""; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "named \"" << name_ << "\""; } private: absl::string_view name_; }; +// An HloInstructionPattern implementation that matches only if the instruction +// equals a particular pointer. +class HloInstructionIsImpl { + public: + explicit HloInstructionIsImpl(const HloInstruction* inst) : inst_(inst) {} + + bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { + if (inst != inst_) { + EXPLAIN << "HloInstruction " << inst << " is not " << inst_ << " (" + << InstToString(inst_) << ")"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "which is " << inst_ << " (" << InstToString(inst_) << ")"; + } + + private: + const HloInstruction* inst_; +}; + // An HloInstructionPattern implementation that matches only if the instruction // has a given opcode. class HloInstructionPatternOpcodeImpl { @@ -742,7 +1220,25 @@ class HloInstructionPatternOpcodeImpl { : opcode_(opcode), invert_(invert) {} bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { - return (invert_ ^ (inst->opcode() == opcode_)); + if (invert_ && inst->opcode() == opcode_) { + EXPLAIN << "HloInstruction has opcode " << HloOpcodeString(opcode_) + << ", expected anything else"; + return false; + } + if (!invert_ && inst->opcode() != opcode_) { + EXPLAIN << "HloInstruction doesn't have opcode " + << HloOpcodeString(opcode_); + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + if (!invert_) { + *os << "with opcode " << HloOpcodeString(opcode_); + } else { + *os << "with any opcode other than " << HloOpcodeString(opcode_); + } } private: @@ -757,8 +1253,17 @@ class HloInstructionPatternNumOperandsImpl { explicit constexpr HloInstructionPatternNumOperandsImpl(int64 num_operands) : num_operands_(num_operands) {} - bool Match(const ::xla::HloInstruction* inst, MatchOption /*option*/) const { - return inst->operand_count() == num_operands_; + bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { + if (inst->operand_count() != num_operands_) { + EXPLAIN << "HloInstruction doesn't have " << num_operands_ << " operands"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "with " << num_operands_ << " operand" + << (num_operands_ != 1 ? "s" : ""); } private: @@ -775,11 +1280,25 @@ class HloInstructionPatternShapeImpl { : shape_(shape) {} bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { - return shape_.Match(&inst->shape(), option); + if (!shape_.Match(&inst->shape(), option)) { + EXPLAIN << "\nin output shape"; + return false; + } + return true; } bool Match(::xla::HloInstruction* inst, MatchOption option) const { - return shape_.Match(inst->mutable_shape(), option); + if (!shape_.Match(inst->mutable_shape(), option)) { + EXPLAIN << "\nin output shape"; + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "outputting"; + Indent(os, indent + kIndentInc); + shape_.DescribeTo(os, indent + kIndentInc); } private: @@ -797,20 +1316,197 @@ class HloInstructionPatternOperandImpl { : operand_index_(operand_index), operand_(operand) {} bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { - return operand_index_ < inst->operand_count() && - operand_.Match(inst->operand(operand_index_), option); + return MatchImpl(inst, option); } bool Match(::xla::HloInstruction* inst, MatchOption option) const { - return operand_index_ < inst->operand_count() && - operand_.Match(inst->mutable_operand(operand_index_), option); + return MatchImpl(inst, option); + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "with operand " << operand_index_ << " which is:"; + Indent(os, indent + kIndentInc); + operand_.DescribeTo(os, indent + kIndentInc); } private: + template + bool MatchImpl(HloInstructionType* inst, MatchOption option) const { + if (operand_index_ >= inst->operand_count()) { + EXPLAIN << "desired operand index " << operand_index_ + << " is out of bounds"; + return false; + } + if (!operand_.Match(HloOperand(inst, operand_index_), option)) { + EXPLAIN << "\nin operand " << operand_index_; + return false; + } + return true; + } + int64 operand_index_; HloInstructionPattern operand_; }; +// Matches a binary instruction whose operands come in any order. +template +class HloInstructionPatternBinaryOperandsAnyOrderImpl { + public: + explicit constexpr HloInstructionPatternBinaryOperandsAnyOrderImpl( + const HloInstructionPattern& op1, + const HloInstructionPattern& op2) + : op1_(op1), op2_(op2) {} + + bool Match(HloInstruction* inst, MatchOption option) const { + return MatchImpl(inst, option); + } + + bool Match(const HloInstruction* inst, MatchOption option) const { + return MatchImpl(inst, option); + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "with two operands in either order:"; + Indent(os, indent); + *os << " - "; + op1_.DescribeTo(os, indent + 3); + Indent(os, indent); + *os << " - "; + op2_.DescribeTo(os, indent + 3); + } + + private: + HloInstruction* operand(HloInstruction* inst, int64 idx) const { + return inst->mutable_operand(idx); + } + const HloInstruction* operand(const HloInstruction* inst, int64 idx) const { + return inst->operand(idx); + } + + template + bool MatchImpl(HloInstructionType* inst, MatchOption option) const { + // We could implement this using AnyOf and AllOf matchers, but the templates + // get pretty difficult to debug, since any compile error herein becomes + // not-an-error via SFINAE. Also this way lets us give better messages on + // failure. + if (inst->operand_count() != 2) { + EXPLAIN << "HloInstruction did not have two operands"; + return false; + } + + // If we're not generating explanations, this is pretty simple. + if (!option.explain_os) { + auto try_match = [&](int64 idx1, int64 idx2) { + MatchOption new_option = option; + new_option.capture = false; + if (op1_.Match(operand(inst, idx1), new_option) && + op2_.Match(operand(inst, idx2), new_option)) { + if (option.capture) { + bool matched = op1_.Match(operand(inst, idx1), option) && + op2_.Match(operand(inst, idx2), option); + DCHECK(matched); + } + return true; + } + return false; + }; + return try_match(0, 1) || try_match(1, 0); + } + + // If we are generating explanations, we have some work to do in order to + // generate a helpful error. + // + // First, try all four operand/matcher combinations, recording the + // failure explanations separately from option.explain_os. matches[i][j] + // tells us if matcher_i matches operand j. + bool matches[/*matcher*/ 2][/*operand*/ 2]; + std::stringstream explanations[/*matcher*/ 2][/*operand*/ 2]; + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + MatchOption new_option = option; + new_option.capture = false; + new_option.explain_os = &explanations[i][j]; + matches[i][j] = i == 0 ? op1_.Match(operand(inst, j), new_option) + : op2_.Match(operand(inst, j), new_option); + } + } + + // Check if the match succeeded. + for (int i = 0; i < 2; ++i) { + if (matches[0][i] && matches[1][(i + 1) % 2]) { + // Rerun the matches with capture enabled if necessary. + if (option.capture) { + auto* operand1 = operand(inst, i); + auto* operand2 = operand(inst, (i + 1) % 2); + bool matched = + op1_.Match(operand1, option) && op2_.Match(operand2, option); + DCHECK(matched); + } + return true; + } + } + + auto describe_matcher = [&](int matcher_idx) { + EXPLAIN << "\n - "; + if (matcher_idx == 0) { + op1_.DescribeTo(option.explain_os, /*indent=*/3); + } else { + CHECK_EQ(matcher_idx, 1); + op2_.DescribeTo(option.explain_os, /*indent=*/3); + } + for (int i = 0; i < 2; ++i) { + if (matches[matcher_idx][/*operand*/ i]) { + continue; + } + EXPLAIN << "\ndoes not match " << (i == 0 ? "LHS" : "RHS") << ":\n"; + EXPLAIN << " - "; + EXPLAIN << absl::StrReplaceAll( + explanations[matcher_idx][/*operand*/ i].str(), {{"\n", "\n "}}); + } + }; + + // If we failed to match, one of the following is true: + // 1. op1 (op2) matches neither LHS nor RHS, or + // 2. op1 and op2 both match LHS (RHS), but neither matches RHS (LHS). + // We print different explanations depending on which case we're in. + + // Case 1. + bool wrote_explanation = false; + for (int i = 0; !wrote_explanation && i < 2; ++i) { + if (!matches[i][0] && !matches[i][1]) { + EXPLAIN << "HloInstruction's operands (ignoring order) did not match " + << (i == 0 ? "first" : "second") << " matcher. Specifically,"; + describe_matcher(i); + wrote_explanation = true; + } + } + + // Case 2. + for (int i = 0; !wrote_explanation && i < 2; ++i) { + if (matches[/*matcher*/ 0][/*operand*/ i] && + matches[/*matcher*/ 1][/*operand*/ i]) { + CHECK(!matches[0][(i + 1) % 2]); + CHECK(!matches[1][(i + 1) % 2]); + CHECK(!wrote_explanation); + EXPLAIN << "HloInstruction's " << (i == 1 ? "LHS" : "RHS") + << " operand did not match either of the two matchers. " + "Specifically,"; + describe_matcher(0); + EXPLAIN << "\nand"; + describe_matcher(1); + wrote_explanation = true; + } + } + + CHECK(wrote_explanation); + return false; + } + + HloInstructionPattern op1_; + HloInstructionPattern op2_; +}; + // An HloInstructionPattern implementation that matches only if the instruction // is a fusion node with a particular kind. class HloInstructionPatternFusionKindImpl { @@ -820,14 +1516,32 @@ class HloInstructionPatternFusionKindImpl { : kind_(kind) {} bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { - return inst->opcode() == HloOpcode::kFusion && inst->fusion_kind() == kind_; + return MatchImpl(inst, option); } bool Match(::xla::HloInstruction* inst, MatchOption option) const { - return inst->opcode() == HloOpcode::kFusion && inst->fusion_kind() == kind_; + return MatchImpl(inst, option); + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "with fusion kind " << ToString(kind_); } private: + template + bool MatchImpl(HloInstructionType* inst, MatchOption option) const { + if (inst->opcode() != HloOpcode::kFusion) { + EXPLAIN << "HloInstruction does not have fusion kind " << ToString(kind_) + << "; it's not a fusion"; + return false; + } + if (inst->fusion_kind() != kind_) { + EXPLAIN << "HloInstruction does not have fusion kind " << ToString(kind_); + return false; + } + return true; + } + ::xla::HloInstruction::FusionKind kind_; }; @@ -839,47 +1553,211 @@ class HloInstructionPatternTupleIndexImpl { : tuple_index_(tuple_index) {} bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { - return inst->opcode() == HloOpcode::kGetTupleElement && - inst->tuple_index() == tuple_index_; + return MatchImpl(inst, option); } bool Match(::xla::HloInstruction* inst, MatchOption option) const { - return inst->opcode() == HloOpcode::kGetTupleElement && - inst->tuple_index() == tuple_index_; + return MatchImpl(inst, option); + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "which is a GTE with index " << tuple_index_; } private: + template + bool MatchImpl(HloInstructionType* inst, MatchOption option) const { + if (inst->opcode() != HloOpcode::kGetTupleElement) { + EXPLAIN << "HloInstruction is not a GTE with index " << tuple_index_ + << "; it's not a GTE at all"; + return false; + } + if (inst->tuple_index() != tuple_index_) { + EXPLAIN << "HloInstruction is not a GTE with index " << tuple_index_; + return false; + } + return true; + } + int64 tuple_index_; }; -template -class HloPredicatePatternImpl { +class HloInstructionPatternParameterNumImpl { public: - explicit HloPredicatePatternImpl(Predicate pred) : pred_(std::move(pred)) {} + explicit constexpr HloInstructionPatternParameterNumImpl(int64 parameter_num) + : parameter_num_(parameter_num) {} + + bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { + return MatchImpl(inst, option); + } - bool Match(const ItemType* item, MatchOption option) const { - return pred_(item); + bool Match(::xla::HloInstruction* inst, MatchOption option) const { + return MatchImpl(inst, option); } - bool Match(ItemType* item, MatchOption option) const { return pred_(item); } + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "which is parameter " << parameter_num_; + } private: - Predicate pred_; + template + bool MatchImpl(HloInstructionType* inst, MatchOption option) const { + if (inst->opcode() != HloOpcode::kParameter || + inst->parameter_number() != parameter_num_) { + EXPLAIN << "HloInstruction is not parameter " << parameter_num_; + return false; + } + return true; + } + + int64 parameter_num_; }; -struct PatternFriend; +// Superclass that contains common code used by Op::WithOneUse() and +// Op::WithOneUser(). +class HloInstructionPatternOneUseOrUserImpl { + protected: + bool MatchOneUser(const HloInstruction* inst, MatchOption option) const { + if (inst->user_count() != 1) { + EXPLAIN << "HloInstruction has " << inst->user_count() + << " users, but expected exactly one."; + if (inst->user_count() > 1) { + EXPLAIN << "\nAll users:"; + for (const HloInstruction* user : inst->users()) { + EXPLAIN << "\n - " << InstToString(user); + } + } + return false; + } + return true; + } +}; + +class HloInstructionPatternOneUseImpl + : public HloInstructionPatternOneUseOrUserImpl { + public: + bool Match(const HloInstruction* inst, MatchOption option) const { + if (!MatchOneUser(inst, option)) { + return false; + } + + int64 use_count = absl::c_count_if( + inst->users()[0]->operands(), + [&](const HloInstruction* operand) { return operand == inst; }); + if (use_count != 1) { + EXPLAIN << "HloInstruction is used " << use_count + << " times by its user, but is expected to be used just once: " + << InstToString(inst->users()[0]); + return false; + } + return true; + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "which has exactly one use"; + } +}; + +class HloInstructionPatternOneUserImpl + : public HloInstructionPatternOneUseOrUserImpl { + public: + bool Match(const HloInstruction* inst, MatchOption option) const { + return MatchOneUser(inst, option); + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "which has exactly one user (but possibly is used multiple times by " + "that instruction)"; + } +}; + +// Matches a constant scalar or effective scalar, optionally with a given value. +template +class HloConstantScalarImpl { + public: + explicit constexpr HloConstantScalarImpl(bool match_effective_scalar) + : val_(absl::nullopt), match_effective_scalar_(match_effective_scalar) {} + + constexpr HloConstantScalarImpl(ScalarTy val, bool match_effective_scalar) + : val_(val), match_effective_scalar_(match_effective_scalar) {} + + bool Match(const ::xla::HloInstruction* inst, MatchOption option) const { + return MatchImpl(inst, option); + } + + bool Match(::xla::HloInstruction* inst, MatchOption option) const { + return MatchImpl(inst, option); + } + + void DescribeTo(std::ostream* os, int64 indent = 0) const { + *os << "which is a constant " + << (match_effective_scalar_ ? "effective " : "") << "scalar"; + if (val_.has_value()) { + *os << " with value " << *val_; + } + } + + private: + template + bool MatchImpl(InstTy* inst, MatchOption option) const { + const auto* const_inst = DynCast(inst); + if (!const_inst) { + EXPLAIN << "HloInstruction is not a constant"; + return false; + } + if (match_effective_scalar_ && + !ShapeUtil::IsEffectiveScalar(inst->shape())) { + EXPLAIN << "HloInstruction is not an effective scalar"; + return false; + } + if (!match_effective_scalar_ && !ShapeUtil::IsScalar(inst->shape())) { + EXPLAIN << "HloInstruction is not a scalar"; + return false; + } + if (!val_.has_value()) { + return true; + } + + // Check that literal == static_cast(val) and + // val == static_cast(literal). This is sufficient to ensure that + // the two constant scalars are actually "equal". + auto val_literal = LiteralUtil::CreateR0(*val_); + auto literal_r0_or = const_inst->literal().Reshape({}); + auto val_as_literal_ty_or = + val_literal.Convert(const_inst->shape().element_type()); + if (!literal_r0_or.ok() || !val_as_literal_ty_or.ok()) { + EXPLAIN << "could not construct relevant Literals (how did this happen?)"; + return false; + } + auto literal_r0 = std::move(literal_r0_or).ValueOrDie(); + auto val_as_literal_ty = std::move(val_as_literal_ty_or).ValueOrDie(); + auto literal_r0_as_val_ty_or = + literal_r0.Convert(val_literal.shape().element_type()); + bool rv = literal_r0_as_val_ty_or.ok() && // + literal_r0_as_val_ty_or.ValueOrDie() == val_literal && + literal_r0 == val_as_literal_ty; + if (!rv) { + EXPLAIN << "HloInstruction's constant value " << literal_r0.ToString() + << " did not match expected value " << *val_; + } + return rv; + } + + absl::optional val_; + bool match_effective_scalar_; +}; // A pattern that matches HloInstructions. template class HloInstructionPattern { private: template - HloInstructionPattern> - AppendImpl(NewImpl new_impl) const { - return HloInstructionPattern< - HloInstructionType, AllOfPattern<::xla::HloInstruction, Impl, NewImpl>>( - AllOf(impl_, std::move(new_impl)), matched_inst_); + auto AppendImpl(NewImpl new_impl) const -> HloInstructionPattern< + HloInstructionType, decltype(AllOf( + std::declval(), std::move(new_impl)))> { + auto new_allof = AllOf(impl_, std::move(new_impl)); + return HloInstructionPattern( + std::move(new_allof), matched_inst_); } public: @@ -895,6 +1773,9 @@ class HloInstructionPattern { } return true; } + if (inst != nullptr) { + EXPLAIN << "\nin " << InstToString(inst); + } return false; } @@ -906,6 +1787,7 @@ class HloInstructionPattern { } return true; } + EXPLAIN << "\nin " << InstToString(inst); return false; } @@ -935,12 +1817,47 @@ class HloInstructionPattern { return AppendImpl(HloInstructionPatternOpcodeImpl(opcode, true)); } + constexpr auto Is(const HloInstruction* instr) const + -> decltype(this->AppendImpl(HloInstructionIsImpl(instr))) { + return AppendImpl(HloInstructionIsImpl(instr)); + } + // Modifies the pattern to match only if the instruction is a constant. constexpr auto IsConstant() const -> decltype(this->WithOpcode(HloOpcode::kConstant)) { return WithOpcode(HloOpcode::kConstant); } + constexpr auto IsConstantScalar() const -> decltype(this->AppendImpl( + HloConstantScalarImpl(/*match_effective_scalar=*/false))) { + return AppendImpl( + HloConstantScalarImpl(/*match_effective_scalar=*/false)); + } + + // This does not check that T has the same type as the instruction, so e.g. + // IsConstantScalar(1.0) may match a constant of shape int32[]. + template + constexpr auto IsConstantScalar(const ScalarTy& val) const + -> decltype(this->AppendImpl(HloConstantScalarImpl( + val, /*match_effective_scalar=*/false))) { + return AppendImpl( + HloConstantScalarImpl(val, /*match_effective_scalar=*/false)); + } + + constexpr auto IsConstantEffectiveScalar() const -> decltype(this->AppendImpl( + HloConstantScalarImpl(/*match_effective_scalar=*/true))) { + return AppendImpl( + HloConstantScalarImpl(/*match_effective_scalar=*/true)); + } + + template + constexpr auto IsConstantEffectiveScalar(const ScalarTy& val) const + -> decltype(this->AppendImpl(HloConstantScalarImpl( + val, /*match_effective_scalar=*/true))) { + return AppendImpl( + HloConstantScalarImpl(val, /*match_effective_scalar=*/true)); + } + // Modifies the pattern to match only if the instruction is not a constant. constexpr auto IsNonConstant() const -> decltype(this->WithoutOpcode(HloOpcode::kConstant)) { @@ -957,6 +1874,22 @@ class HloInstructionPattern { HloInstructionPatternShapeImpl(shape)); } + // Make this a templated function to work around gcc 4.9.4 template infinite + // recursion bug. + template + constexpr auto WithShapeEqualTo(const ::xla::Shape* shape) + -> decltype(this->WithShape(Shape().EqualTo(shape))) { + return WithShape(Shape().EqualTo(shape)); + } + + // Make this a templated function to work around gcc 4.9.4 template infinite + // recursion bug. + template + constexpr auto WithShapeCompatibleTo(const ::xla::Shape* shape) + -> decltype(this->WithShape(Shape().CompatibleTo(shape))) { + return WithShape(Shape().CompatibleTo(shape)); + } + // Modifies the pattern to match only if the instruction has an operand that // matches the given pattern. template @@ -971,6 +1904,20 @@ class HloInstructionPattern { operand_index, operand)); } + template + constexpr auto WithBinaryOperandsAnyOrder( + const HloInstructionPattern& op1, + const HloInstructionPattern& op2) const + -> decltype(this->AppendImpl( + HloInstructionPatternBinaryOperandsAnyOrderImpl< + OperandType1, OperandImpl1, OperandType2, OperandImpl2>(op1, + op2))) { + return AppendImpl( + HloInstructionPatternBinaryOperandsAnyOrderImpl< + OperandType1, OperandImpl1, OperandType2, OperandImpl2>(op1, op2)); + } + // Modifies the pattern to match only if the instruction is a fusion node with // the given kind. constexpr auto WithFusionKind(HloInstruction::FusionKind kind) const @@ -985,17 +1932,34 @@ class HloInstructionPattern { return AppendImpl(HloInstructionPatternTupleIndexImpl(tuple_index)); } - private: - template - constexpr auto WithPredicate(Predicate pred) const -> decltype( - this->AppendImpl(HloPredicatePatternImpl( - std::move(pred)))) { - return AppendImpl( - HloPredicatePatternImpl(std::move(pred))); + // Modifies the pattern to match only if the instruction is a parameter + // with the given parameter number. + constexpr auto WithParameterNum(int64 parameter_num) const -> decltype( + this->AppendImpl(HloInstructionPatternParameterNumImpl(parameter_num))) { + return AppendImpl(HloInstructionPatternParameterNumImpl(parameter_num)); } - friend struct PatternFriend; + // Modifies the pattern to match if the instruction is used exactly once. + // Does not match if the instruction is used twice by the same user (e.g. + // multiply(x,x)). + constexpr auto WithOneUse() const + -> decltype(this->AppendImpl(HloInstructionPatternOneUseImpl())) { + return AppendImpl(HloInstructionPatternOneUseImpl()); + } + + // Modifies the pattern to match if the instruction is used by exactly one + // other instruction. Will match if the instruction is used twice, so long as + // it's by the same user (e.g. multiply(x,x)). + constexpr auto WithOneUser() const + -> decltype(this->AppendImpl(HloInstructionPatternOneUserImpl())) { + return AppendImpl(HloInstructionPatternOneUserImpl()); + } + void DescribeTo(std::ostream* os, int64 indent = 0) const { + impl_.DescribeTo(os, indent); + } + + private: Impl impl_; HloInstructionType** matched_inst_; }; @@ -1036,6 +2000,7 @@ Op(::xla::HloInstruction** matched_inst) { XLA_NULLOP_PATTERN(Constant) XLA_NULLOP_PATTERN(Parameter) XLA_NULLOP_PATTERN(Iota) +XLA_NULLOP_PATTERN(Rng) #undef XLA_NULLOP_PATTERN // Helpers for unary instructions. @@ -1067,8 +2032,10 @@ XLA_UNOP_PATTERN(RoundNearestAfz) XLA_UNOP_PATTERN(Bitcast) XLA_UNOP_PATTERN(Broadcast) XLA_UNOP_PATTERN(Ceil) +XLA_UNOP_PATTERN(Convert) XLA_UNOP_PATTERN(Copy) XLA_UNOP_PATTERN(Cos) +XLA_UNOP_PATTERN(CrossReplicaSum) XLA_UNOP_PATTERN(Exp) XLA_UNOP_PATTERN(Fft) XLA_UNOP_PATTERN(Floor) @@ -1088,6 +2055,7 @@ XLA_UNOP_PATTERN(Reverse) XLA_UNOP_PATTERN(SendDone) XLA_UNOP_PATTERN(Sign) XLA_UNOP_PATTERN(Sin) +XLA_UNOP_PATTERN(Slice) XLA_UNOP_PATTERN(Sort) XLA_UNOP_PATTERN(Tanh) XLA_UNOP_PATTERN(Transpose) @@ -1125,25 +2093,32 @@ XLA_UNOP_PATTERN(Transpose) #define XLA_COMMUTATIVE_BINOP_PATTERN(NAME) \ XLA_BINOP_PATTERN(NAME) \ \ - template \ - inline auto NAME##AnyOrder(Lhs&& lhs, Rhs&& rhs) \ - ->decltype(AnyOf(NAME(lhs, rhs), NAME(rhs, lhs))) { \ - return AnyOf(NAME(lhs, rhs), NAME(rhs, lhs)); \ - } \ - \ template \ inline auto NAME##AnyOrder(HloInstructionType** matched_inst, Lhs&& lhs, \ Rhs&& rhs) \ - ->decltype(AnyOf(NAME(matched_inst, lhs, rhs), \ - NAME(matched_inst, rhs, lhs))) { \ - return AnyOf(NAME(matched_inst, lhs, rhs), \ - NAME(matched_inst, rhs, lhs)); \ + ->decltype(Op(matched_inst) \ + .WithOpcode(HloOpcode::k##NAME) \ + .WithBinaryOperandsAnyOrder(std::forward(lhs), \ + std::forward(rhs))) { \ + return Op(matched_inst) \ + .WithOpcode(HloOpcode::k##NAME) \ + .WithBinaryOperandsAnyOrder(std::forward(lhs), \ + std::forward(rhs)); \ + } \ + template \ + inline auto NAME##AnyOrder(Lhs&& lhs, Rhs&& rhs) \ + ->decltype(NAME##AnyOrder( \ + nullptr, std::forward(lhs), std::forward(rhs))) { \ + return NAME##AnyOrder( \ + nullptr, std::forward(lhs), std::forward(rhs)); \ } XLA_COMMUTATIVE_BINOP_PATTERN(Add) XLA_BINOP_PATTERN(Atan2) XLA_BINOP_PATTERN(Divide) XLA_BINOP_PATTERN(Complex) +XLA_BINOP_PATTERN(Convolution) XLA_BINOP_PATTERN(Dot) +XLA_BINOP_PATTERN(DynamicSlice) XLA_COMMUTATIVE_BINOP_PATTERN(Eq) XLA_BINOP_PATTERN(Gather) XLA_BINOP_PATTERN(Ge) @@ -1155,7 +2130,9 @@ XLA_COMMUTATIVE_BINOP_PATTERN(Minimum) XLA_COMMUTATIVE_BINOP_PATTERN(Multiply) XLA_COMMUTATIVE_BINOP_PATTERN(Ne) XLA_BINOP_PATTERN(Outfeed) +XLA_BINOP_PATTERN(Pad) XLA_BINOP_PATTERN(Power) +XLA_BINOP_PATTERN(ReduceWindow) XLA_BINOP_PATTERN(Remainder) XLA_BINOP_PATTERN(Send) XLA_BINOP_PATTERN(Subtract) @@ -1202,6 +2179,7 @@ XLA_BINOP_PATTERN(ShiftRightLogical) .WithOperand(2, std::forward(arg2)); \ } XLA_TERNOP_PATTERN(Clamp); +XLA_TERNOP_PATTERN(Scatter); XLA_TERNOP_PATTERN(Select); #undef XLA_TERNOP_PATTERN @@ -1255,31 +2233,10 @@ inline auto WithOperands(Matcher&& m, int64 operand_num, FirstArg&& first_arg, // We could implement all ops as "variadic" ops, but it would make the // already-bad compile errors even worse. XLA_VARIADIC_OP_PATTERN(Concatenate); +XLA_VARIADIC_OP_PATTERN(CustomCall); +XLA_VARIADIC_OP_PATTERN(Map) XLA_VARIADIC_OP_PATTERN(Reduce); - -namespace detail { -struct PatternFriend { - template - static auto ConstantScalar(T constant) -> decltype( - Constant() - .WithShape(match::Shape().IsScalar()) - .WithPredicate( - std::declval>())) { - std::function pred = - [constant](const HloInstruction* instr) { - const auto& literal = Cast(instr)->literal(); - auto status_or_const = LiteralUtil::CreateR0(constant).Convert( - literal.shape().element_type()); - return status_or_const.ok() && - literal == status_or_const.ConsumeValueOrDie(); - }; - - return Constant() - .WithShape(match::Shape().IsScalar()) - .WithPredicate(std::move(pred)); - } -}; -} // namespace detail +XLA_VARIADIC_OP_PATTERN(Tuple); // Helpers for matching non-constant instructions. inline auto NonConstant() -> decltype(Op().IsNonConstant()) { @@ -1318,14 +2275,71 @@ inline auto GetTupleElement(HloInstructionType** matched_inst, Arg&& arg, .WithTupleIndex(tuple_index); } -template -inline auto ConstantScalar(T constant) - -> decltype(detail::PatternFriend::ConstantScalar(constant)) { - return detail::PatternFriend::ConstantScalar(constant); +// Add overloads for Parameter which take an int64 specifying the parameter +// number. +inline auto Parameter(int64 parameter_num) -> decltype( + Op().WithOpcode(HloOpcode::kParameter).WithParameterNum(parameter_num)) { + return Op().WithOpcode(HloOpcode::kParameter).WithParameterNum(parameter_num); +} +template +inline auto Parameter(HloInstructionType** matched_inst, int64 parameter_num) + -> decltype(Op(matched_inst) + .WithOpcode(HloOpcode::kParameter) + .WithParameterNum(parameter_num)) { + return Op(matched_inst) + .WithOpcode(HloOpcode::kParameter) + .WithParameterNum(parameter_num); +} + +inline auto ConstantScalar() -> decltype(Op().IsConstantScalar()) { + return Op().IsConstantScalar(); +} + +template +inline auto ConstantScalar(HloInstructionType** matched_inst) + -> decltype(Op(matched_inst).IsConstantScalar()) { + return Op(matched_inst).IsConstantScalar(); +} + +template +inline auto ConstantScalar(ScalarTy val) + -> decltype(Op().IsConstantScalar(val)) { + return Op().IsConstantScalar(val); +} + +template +inline auto ConstantScalar(HloInstructionType** matched_inst, ScalarTy val) + -> decltype(Op(matched_inst).IsConstantScalar(val)) { + return Op(matched_inst).IsConstantScalar(val); +} + +inline auto ConstantEffectiveScalar() -> decltype(Op().IsConstantScalar()) { + return Op().IsConstantEffectiveScalar(); +} + +template +inline auto ConstantEffectiveScalar(HloInstructionType** matched_inst) + -> decltype(Op(matched_inst).IsConstantScalar()) { + return Op(matched_inst).IsConstantEffectiveScalar(); +} + +template +inline auto ConstantEffectiveScalar(ScalarTy val) + -> decltype(Op().IsConstantEffectiveScalar(val)) { + return Op().IsConstantEffectiveScalar(val); +} + +template +inline auto ConstantEffectiveScalar(HloInstructionType** matched_inst, + ScalarTy val) + -> decltype(Op(matched_inst).IsConstantEffectiveScalar(val)) { + return Op(matched_inst).IsConstantEffectiveScalar(val); } } // namespace match } // namespace xla +#undef EXPLAIN +#pragma pop_macro("EXPLAIN") #endif // TENSORFLOW_COMPILER_XLA_SERVICE_PATTERN_MATCHER_H_ diff --git a/tensorflow/compiler/xla/service/pattern_matcher_gmock.h b/tensorflow/compiler/xla/service/pattern_matcher_gmock.h new file mode 100644 index 0000000000..8fe2d10a11 --- /dev/null +++ b/tensorflow/compiler/xla/service/pattern_matcher_gmock.h @@ -0,0 +1,92 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_COMPILER_XLA_SERVICE_PATTERN_MATCHER_GMOCK_H_ +#define TENSORFLOW_COMPILER_XLA_SERVICE_PATTERN_MATCHER_GMOCK_H_ + +#include +#include "tensorflow/compiler/xla/service/pattern_matcher.h" +#include "tensorflow/compiler/xla/test.h" +#include "tensorflow/core/platform/test.h" + +namespace xla { + +namespace pattern_matcher_gmock_detail { +template +class GmockMatcher { + public: + explicit GmockMatcher(Pattern p) : pattern_(std::move(p)) {} + + // In service of better error messages, list out the overloads explicitly + // rather than just using a template. gMock's polymorphism plus + // pattern_matcher yields some pretty gnarly stuff. + bool MatchAndExplain(const Layout& l, + ::testing::MatchResultListener* listener) const { + return MatchAndExplainImpl(&l, listener); + } + bool MatchAndExplain(const Layout* l, + ::testing::MatchResultListener* listener) const { + return MatchAndExplainImpl(l, listener); + } + + bool MatchAndExplain(const Shape& s, + ::testing::MatchResultListener* listener) const { + return MatchAndExplainImpl(&s, listener); + } + bool MatchAndExplain(const Shape* s, + ::testing::MatchResultListener* listener) const { + return MatchAndExplainImpl(s, listener); + } + + bool MatchAndExplain(const HloInstruction& instr, + ::testing::MatchResultListener* listener) const { + return MatchAndExplainImpl(&instr, listener); + } + bool MatchAndExplain(const HloInstruction* instr, + ::testing::MatchResultListener* listener) const { + return MatchAndExplainImpl(instr, listener); + } + + void DescribeTo(std::ostream* os) const { pattern_.DescribeTo(os); } + + void DescribeNegationTo(std::ostream* os) const { + *os << "is NOT: "; + DescribeTo(os); + } + + private: + template + bool MatchAndExplainImpl(const T* t, + ::testing::MatchResultListener* listener) const { + MatchOption options{/*.capture=*/true, /*.explain_os=*/listener->stream()}; + return Match(t, pattern_, options); + } + + Pattern pattern_; +}; +} // namespace pattern_matcher_gmock_detail + +template +::testing::PolymorphicMatcher< + pattern_matcher_gmock_detail::GmockMatcher> +GmockMatch(Pattern&& p) { + return ::testing::MakePolymorphicMatcher( + pattern_matcher_gmock_detail::GmockMatcher( + std::forward(p))); +} + +} // namespace xla + +#endif // TENSORFLOW_COMPILER_XLA_SERVICE_PATTERN_MATCHER_GMOCK_H_ diff --git a/tensorflow/compiler/xla/service/pattern_matcher_gmock_test.cc b/tensorflow/compiler/xla/service/pattern_matcher_gmock_test.cc new file mode 100644 index 0000000000..9ca2fb05c1 --- /dev/null +++ b/tensorflow/compiler/xla/service/pattern_matcher_gmock_test.cc @@ -0,0 +1,76 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/service/pattern_matcher_gmock.h" +#include "tensorflow/compiler/xla/service/pattern_matcher.h" +#include "tensorflow/compiler/xla/shape_util.h" +#include "tensorflow/compiler/xla/test.h" +#include "tensorflow/core/platform/test.h" + +namespace xla { +namespace { + +namespace m = ::xla::match; +using ::testing::Eq; +using ::testing::Not; + +template +string Describe(const ::testing::Matcher& m) { + std::stringstream ss; + m.DescribeTo(&ss); + return ss.str(); +} + +template +string Explain( + const MatchedTy& val, + const ::testing::Matcher::type>& m) { + ::testing::StringMatchResultListener listener; + EXPECT_THAT(val, ::testing::Not(m)); // For the error message. + EXPECT_FALSE(m.MatchAndExplain(val, &listener)); + return listener.str(); +} + +// This file tests the GmockMatch function. The actual explanation and +// description returned by matchers is tested in pattern_matchers_test. +TEST(PatternMatcherGmock, MatchShape) { + Shape s = ShapeUtil::MakeShape(F32, {10, 100}); + // You can pass const Shape& or a const Shape*. + EXPECT_THAT(s, GmockMatch(m::Shape())); + EXPECT_THAT(&s, Not(GmockMatch(m::Shape().WithElementType(F16)))); + EXPECT_THAT(Describe(GmockMatch(m::Shape().IsArray())), + "a shape that represents an array"); +} + +TEST(PatternMatcherGmock, MatchLayout) { + Layout l = LayoutUtil::MakeLayout({0, 1}); + EXPECT_THAT(l, GmockMatch(m::Layout())); + EXPECT_THAT(&l, Not(GmockMatch(m::Layout().WithSparseFormat()))); + EXPECT_THAT(Describe(GmockMatch(m::Layout().WithSparseFormat())), + "a layout with format SPARSE"); +} + +TEST(PatternMatchGmock, MatchInstruction) { + auto instr = + HloInstruction::CreateParameter(0, ShapeUtil::MakeShape(F32, {42}), "p"); + EXPECT_THAT(instr.get(), GmockMatch(m::Parameter())); + EXPECT_THAT(*instr, GmockMatch(m::Parameter(0))); + EXPECT_THAT(*instr, Not(GmockMatch(m::Parameter(1)))); + EXPECT_THAT(Describe(GmockMatch(m::Parameter())), + "an HloInstruction with opcode parameter"); +} + +} // anonymous namespace +} // namespace xla diff --git a/tensorflow/compiler/xla/service/pattern_matcher_test.cc b/tensorflow/compiler/xla/service/pattern_matcher_test.cc index 3f74273517..186ef0c791 100644 --- a/tensorflow/compiler/xla/service/pattern_matcher_test.cc +++ b/tensorflow/compiler/xla/service/pattern_matcher_test.cc @@ -14,14 +14,18 @@ limitations under the License. ==============================================================================*/ #include "tensorflow/compiler/xla/service/pattern_matcher.h" +#include "absl/strings/str_cat.h" #include "tensorflow/compiler/xla/service/hlo_instruction.h" #include "tensorflow/compiler/xla/service/hlo_opcode.h" #include "tensorflow/compiler/xla/service/hlo_parser.h" +#include "tensorflow/compiler/xla/test.h" #include "tensorflow/core/platform/test.h" namespace xla { namespace { +namespace m = match; + TEST(PatternMatcherTest, AddOp) { constexpr char kModuleStr[] = R"(HloModule two_plus_two_module ENTRY %two_plus_two_computation () -> f32[] { @@ -229,23 +233,74 @@ TEST(PatternMatcherTest, AnyOf) { } TEST(PatternMatcherTest, ConstantScalar) { - constexpr char kModuleStr[] = R"( - HloModule test_module ENTRY test { ROOT constant = f16[] constant(42) })"; - TF_ASSERT_OK_AND_ASSIGN(auto hlo_module, ParseHloString(kModuleStr)); - auto* root = hlo_module->entry_computation()->root_instruction(); - - EXPECT_TRUE(Match(root, match::ConstantScalar(42))); - EXPECT_FALSE(Match(root, match::ConstantScalar(41))); - EXPECT_FALSE(Match(root, match::ConstantScalar(0))); -} + using match::ConstantEffectiveScalar; + using match::ConstantScalar; + using match::Op; + using match::Tuple; -TEST(PatternMatcherTest, NoMatchConstantScalar) { constexpr char kModuleStr[] = R"( - HloModule test_module ENTRY test { ROOT v = f16[] parameter(0) })"; + HloModule test_module + ENTRY test { + a = s32[] constant(1) + b = s32[1,1] constant(s32[1,1]{{2}}) + c = s32[1,2] constant(s32[1,2]{{2,2}}) + d = f32[] constant(1) + e = f32[] constant(1.25) + ROOT tuple = (s32[], s32[1,1], s32[1,2], f32[], f32[]) tuple(a,b,c,d,e) + })"; TF_ASSERT_OK_AND_ASSIGN(auto hlo_module, ParseHloString(kModuleStr)); auto* root = hlo_module->entry_computation()->root_instruction(); - EXPECT_FALSE(Match(root, match::ConstantScalar(42))); + const HloInstruction* a = root->operand(0); + const HloInstruction* b = root->operand(1); + const HloInstruction* c = root->operand(2); + const HloInstruction* d = root->operand(3); + const HloInstruction* e = root->operand(4); + EXPECT_TRUE(Match(a, ConstantScalar())); + EXPECT_TRUE(Match(a, ConstantScalar(1))); + EXPECT_TRUE(Match(a, ConstantEffectiveScalar())); + EXPECT_TRUE(Match(a, ConstantEffectiveScalar(1))); + EXPECT_FALSE(Match(a, ConstantScalar(2))); + EXPECT_FALSE(Match(a, ConstantScalar(2.01))); + EXPECT_FALSE(Match(a, ConstantEffectiveScalar(2))); + EXPECT_FALSE(Match(a, ConstantEffectiveScalar(1.01))); + + EXPECT_FALSE(Match(b, ConstantScalar())); + EXPECT_FALSE(Match(b, ConstantScalar(2))); + EXPECT_TRUE(Match(b, ConstantEffectiveScalar())); + EXPECT_TRUE(Match(b, ConstantEffectiveScalar(2))); + + EXPECT_FALSE(Match(c, ConstantScalar())); + EXPECT_FALSE(Match(c, ConstantScalar(2))); + EXPECT_FALSE(Match(c, ConstantEffectiveScalar())); + EXPECT_FALSE(Match(c, ConstantEffectiveScalar(2))); + + EXPECT_TRUE(Match(d, ConstantScalar(1))); + EXPECT_TRUE(Match(d, ConstantEffectiveScalar(1))); + EXPECT_TRUE(Match(d, ConstantScalar(1.0))); + EXPECT_TRUE(Match(d, ConstantEffectiveScalar(1.0))); + + EXPECT_TRUE(Match(e, ConstantScalar(1.25f))); + EXPECT_TRUE(Match(e, ConstantScalar(1.25))); + EXPECT_TRUE(Match(e, ConstantEffectiveScalar(1.25))); + EXPECT_FALSE(Match(e, ConstantScalar(1))); + EXPECT_FALSE(Match(e, ConstantEffectiveScalar(1))); + + const HloInstruction* instr = nullptr; + EXPECT_TRUE(Match(a, ConstantScalar(&instr))); + EXPECT_EQ(instr, a); + + instr = nullptr; + EXPECT_TRUE(Match(a, ConstantScalar(&instr, 1))); + EXPECT_EQ(instr, a); + + instr = nullptr; + EXPECT_TRUE(Match(a, ConstantEffectiveScalar(&instr))); + EXPECT_EQ(instr, a); + + instr = nullptr; + EXPECT_TRUE(Match(a, ConstantEffectiveScalar(&instr, 1))); + EXPECT_EQ(instr, a); } TEST(PatternMatcherTest, MultiplyAnyOrder) { @@ -267,6 +322,15 @@ TEST(PatternMatcherTest, MultiplyAnyOrder) { root, MultiplyAnyOrder(&instr, ConstantScalar(42), ConstantScalar(52)))); EXPECT_TRUE(Match( root, MultiplyAnyOrder(&instr, ConstantScalar(52), ConstantScalar(42)))); + + // Check that MultiplyAnyOrder exposes the same API as Op(), so we can call + // e.g. IsNonConstant() on it. + EXPECT_TRUE(Match( + root, MultiplyAnyOrder(&instr, ConstantScalar(42), ConstantScalar(52)) + .IsNonConstant())); + EXPECT_TRUE( + Match(root, MultiplyAnyOrder(ConstantScalar(42), ConstantScalar(52)) + .IsNonConstant())); } TEST(PatternMatcherTest, AnyOfShortCircuit) { @@ -315,14 +379,22 @@ TEST(PatternMatcherTest, AllOf) { TF_ASSERT_OK_AND_ASSIGN(auto hlo_module, ParseHloString(kModuleStr)); auto* root = hlo_module->entry_computation()->root_instruction(); + auto f16_scalar = ShapeUtil::MakeShape(F16, {}); + auto f16_pattern = Constant().WithShapeEqualTo(&f16_scalar); + auto f16_compatible_pattern = Constant().WithShapeCompatibleTo(&f16_scalar); auto scalar_pattern = Constant().WithShape(match::Shape().IsScalar()); - auto f16_pattern = Constant().WithShape(match::Shape().WithElementType(F16)); ASSERT_TRUE(Match(root, scalar_pattern)); ASSERT_TRUE(Match(root, f16_pattern)); - EXPECT_TRUE(Match(root, AllOf(scalar_pattern, f16_pattern))); - EXPECT_TRUE(Match(root, AllOf(f16_pattern, scalar_pattern))); + ASSERT_TRUE(Match(root, f16_compatible_pattern)); + EXPECT_TRUE(Match(root, AllOf(scalar_pattern, f16_pattern, + f16_compatible_pattern))); + EXPECT_TRUE( + Match(root, AllOf(f16_pattern, f16_compatible_pattern, + scalar_pattern))); EXPECT_FALSE( Match(root, AllOf(Broadcast(Op()), f16_pattern))); + EXPECT_FALSE(Match( + root, AllOf(Broadcast(Op()), f16_compatible_pattern))); EXPECT_FALSE( Match(root, AllOf(Broadcast(Op()), scalar_pattern))); } @@ -431,5 +503,433 @@ TEST(PatternMatcherTest, TestConcat) { Reshape(ConstantScalar(4))))); } +template +string Description(const Pattern& pattern) { + std::stringstream ss; + pattern.DescribeTo(&ss); + return ss.str(); +} + +template +string Explanation(Elem* elem, const Pattern& pattern) { + std::stringstream ss; + MatchOption options{/*.capture=*/true, /*.explain_os=*/&ss}; + Match(elem, pattern, options); + return ss.str(); +} +template +string Explanation(const std::unique_ptr& elem, const Pattern& pattern) { + return Explanation(elem.get(), pattern); +} +template +string Explanation(const Elem& elem, const Pattern& pattern) { + return Explanation(&elem, pattern); +} + +// Helper macro for checking a pattern's description and the explanation printed +// when attempting to match (and presumably failing) on a given object. +// +// We use a macro rather than a function because we want good line numbers in +// errors. We use this rather than writing a helper that returns a pair of +// (description, explanation) and doing something like +// +// EXPECT_THAT(DescAndExplanation(...), ::testing::Pair(..., ...)); +// +// because EXPECT_EQ prints a unified diff if multiline string comparison fails, +// while EXPECT_THAT does not. This unified diff makes the errors much easier +// to read. +#define EXPECT_DESC_AND_EXPLANATION(elem, pattern, expected_desc, \ + expected_explanation) \ + do { \ + EXPECT_EQ(Description(pattern), (expected_desc)); \ + EXPECT_EQ(Explanation((elem), (pattern)), expected_explanation); \ + } while (0) + +TEST(PatternMatcherTest, LayoutDescribeToAndExplain) { + auto layout = LayoutUtil::MakeLayout({1, 2}); + auto layout2 = LayoutUtil::MakeLayout({2, 2}); + + EXPECT_DESC_AND_EXPLANATION(static_cast(nullptr), m::Layout(), + "a layout", "Layout is null"); + EXPECT_DESC_AND_EXPLANATION(layout2, m::Layout().EqualTo(&layout), + "a layout equal to {1,2}", + "Layout {2,2} is not equal to expected {1,2}"); + EXPECT_DESC_AND_EXPLANATION(layout2, m::Layout().WithSparseFormat(), + "a layout with format SPARSE", + "Layout has format DENSE but expected SPARSE"); + EXPECT_DESC_AND_EXPLANATION(layout, + m::Layout().EqualTo(&layout).WithSparseFormat(), + "a layout:\n" + " * equal to {1,2} AND\n" + " * with format SPARSE", + "Layout has format DENSE but expected SPARSE"); +} + +TEST(PatternMatcherTest, ShapeDescribeToAndExplain) { + auto shape = ShapeUtil::MakeShapeWithLayout(F32, {1, 2}, {0, 1}); + auto layout = shape.layout(); + + EXPECT_DESC_AND_EXPLANATION(static_cast(nullptr), m::Shape(), + "a shape", "Shape is null"); + EXPECT_DESC_AND_EXPLANATION( + ShapeUtil::MakeShapeWithLayout(F32, {1, 2}, {1, 0}), + m::Shape().EqualTo(&shape), "a shape equal to f32[1,2]{0,1}", + "Shape not equal to f32[1,2]{0,1}\n" + "in f32[1,2]{1,0}"); + EXPECT_DESC_AND_EXPLANATION(ShapeUtil::MakeShape(F32, {2, 2}), + m::Shape().CompatibleTo(&shape), + "a shape compatible with f32[1,2]", + "Shape not compatible with f32[1,2]\n" + "in f32[2,2]{1,0}"); + EXPECT_DESC_AND_EXPLANATION(shape, m::Shape().WithElementType(F16), + "a shape with element type F16", + "Shape does not have element type F16\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION(shape, m::Shape().IsScalar(), + "a shape that represents a scalar", + "Shape is not a scalar\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION(ShapeUtil::MakeNil(), m::Shape().IsArray(), + "a shape that represents an array", + "Shape is not an array\n" + "in ()"); + EXPECT_DESC_AND_EXPLANATION(shape, m::Shape().IsTuple(), + "a shape that represents a tuple", + "Shape is not a tuple\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION(shape, m::Shape().IsEffectiveScalar(), + "a shape that is an effective scalar", + "Shape is not an effective scalar\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION(shape, m::Shape().WithRank(42), + "a shape that has 42 dimensions", + "Shape does not have rank 42\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION(shape, m::Shape().WithRank(0), + "a shape that is a scalar", + "Shape is not a scalar\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION(shape, m::Shape().WithRank(1).IsArray(), + "a shape:\n" + " * that has 1 dimension AND\n" + " * that represents an array", + "Shape does not have rank 1\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION(ShapeUtil::MakeNil(), + m::Shape().IsArray().WithRank(1), + "a shape:\n" + " * that represents an array AND\n" + " * that has 1 dimension", + "Shape is not an array\n" + "in ()"); + EXPECT_DESC_AND_EXPLANATION( + ShapeUtil::MakeShapeWithLayout(F32, {1, 2}, {1, 0}), + m::Shape().WithLayoutEqualTo(&layout), + "a shape with\n a layout equal to {0,1}", + "Layout {1,0} is not equal to expected {0,1}\n" + "in f32[1,2]{1,0}"); + EXPECT_DESC_AND_EXPLANATION( + shape, m::Shape().WithLayout(m::Layout().WithSparseFormat()), + "a shape with\n a layout with format SPARSE", + "Layout has format DENSE but expected SPARSE\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION(shape, + m::Shape().WithSubshapeEqualTo({10}, &shape), + "a shape with subshape at index {10} which is\n" + " a shape equal to f32[1,2]{0,1}", + "No subshape at {10}\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION( + ShapeUtil::MakeTupleShape({ShapeUtil::MakeShape(F32, {2, 2})}), + m::Shape().WithSubshapeEqualTo({0}, &shape), + "a shape with subshape at index {0} which is\n" + " a shape equal to f32[1,2]{0,1}", + "Shape not equal to f32[1,2]{0,1}\n" + "in f32[2,2]{1,0}\n" + "in subshape at {0}\n" + "in (f32[2,2])"); + EXPECT_DESC_AND_EXPLANATION(shape, + m::Shape().WithSubshapeCompatibleTo({10}, &shape), + "a shape with subshape at index {10} which is\n" + " a shape compatible with f32[1,2]", + "No subshape at {10}\n" + "in f32[1,2]{0,1}"); + EXPECT_DESC_AND_EXPLANATION( + ShapeUtil::MakeTupleShape({ShapeUtil::MakeShape(F32, {2, 2})}), + m::Shape().WithSubshapeCompatibleTo({0}, &shape), + "a shape with subshape at index {0} which is\n" + " a shape compatible with f32[1,2]", + "Shape not compatible with f32[1,2]\n" + "in f32[2,2]{1,0}\n" + "in subshape at {0}\n" + "in (f32[2,2])"); + EXPECT_DESC_AND_EXPLANATION( + ShapeUtil::MakeTupleShape({ShapeUtil::MakeTupleShape({shape})}), + m::Shape().WithSubshape({0, 0}, m::Shape().IsScalar()), + "a shape with subshape at index {0,0} which is\n" + " a shape that represents a scalar", + "Shape is not a scalar\n" + "in f32[1,2]{0,1}\n" + "in subshape at {0,0}\n" + "in ((f32[1,2]))"); +} + +std::unique_ptr SetName(absl::string_view name, + std::unique_ptr instr) { + instr->SetAndSanitizeName(string(name)); + return instr; +} + +TEST(PatternMatcherTest, HloInstructionDescribeToAndExplain) { + std::unique_ptr iota = + SetName("i", HloInstruction::CreateIota(ShapeUtil::MakeShape(S32, {42}), + /*iota_dimension=*/0)); + std::unique_ptr constant = + SetName("c", HloInstruction::CreateConstant(LiteralUtil::CreateR0(0))); + + EXPECT_DESC_AND_EXPLANATION(static_cast(nullptr), + m::Op(), "an HloInstruction", + "HloInstruction* is null"); + EXPECT_DESC_AND_EXPLANATION(iota, m::Op().WithName("foo"), + "an HloInstruction named \"foo\"", + "HloInstruction not named \"foo\"\n" + "in i = s32[42]{0} iota(), iota_dimension=0"); + EXPECT_DESC_AND_EXPLANATION(iota, m::Op().WithOpcode(HloOpcode::kAdd), + "an HloInstruction with opcode add", + "HloInstruction doesn't have opcode add\n" + "in i = s32[42]{0} iota(), iota_dimension=0"); + EXPECT_DESC_AND_EXPLANATION( + constant, m::Op().IsNonConstant(), + "an HloInstruction with any opcode other than constant", + "HloInstruction has opcode constant, expected anything else\n" + "in c = s32[] constant(0)"); + EXPECT_DESC_AND_EXPLANATION(iota, m::Op().WithNumOperands(42), + "an HloInstruction with 42 operands", + "HloInstruction doesn't have 42 operands\n" + "in i = s32[42]{0} iota(), iota_dimension=0"); + EXPECT_DESC_AND_EXPLANATION(iota, m::Op().WithShape(m::Shape().IsTuple()), + "an HloInstruction outputting\n" + " a shape that represents a tuple", + "Shape is not a tuple\n" + "in s32[42]{0}\n" + "in output shape\n" + "in i = s32[42]{0} iota(), iota_dimension=0"); + EXPECT_DESC_AND_EXPLANATION( + iota, m::Op().WithOperand(2, m::Op().WithOpcode(HloOpcode::kAdd)), + "an HloInstruction with operand 2 which is:\n" + " an HloInstruction with opcode add", + "desired operand index 2 is out of bounds\n" + "in i = s32[42]{0} iota(), iota_dimension=0"); + + EXPECT_DESC_AND_EXPLANATION( + SetName("a", HloInstruction::CreateBinary(ShapeUtil::MakeShape(S32, {}), + HloOpcode::kAdd, constant.get(), + constant.get())), + m::Op().WithOperand(1, m::Op().IsNonConstant()), + "an HloInstruction with operand 1 which is:\n" + " an HloInstruction with any opcode other than constant", + "HloInstruction has opcode constant, expected anything else\n" + "in c = s32[] constant(0)\n" + "in operand 1\n" + "in a = s32[] add(s32[] c, s32[] c)"); + EXPECT_DESC_AND_EXPLANATION( + iota, m::Op().WithFusionKind(HloInstruction::FusionKind::kLoop), + "an HloInstruction with fusion kind kLoop", + "HloInstruction does not have fusion kind kLoop; it's not a fusion\n" + "in i = s32[42]{0} iota(), iota_dimension=0"); + EXPECT_DESC_AND_EXPLANATION( + iota, m::Op().WithTupleIndex(42), + "an HloInstruction which is a GTE with index 42", + "HloInstruction is not a GTE with index 42; it's not a GTE at all\n" + "in i = s32[42]{0} iota(), iota_dimension=0"); + EXPECT_DESC_AND_EXPLANATION(iota, m::Op().IsConstantScalar(), + "an HloInstruction which is a constant scalar", + "HloInstruction is not a constant\n" + "in i = s32[42]{0} iota(), iota_dimension=0"); + EXPECT_DESC_AND_EXPLANATION( + SetName("c", HloInstruction::CreateConstant( + LiteralUtil::CreateR1({1, 2}))), + m::Op().IsConstantEffectiveScalar(), + "an HloInstruction which is a constant effective scalar", + "HloInstruction is not an effective scalar\n" + "in c = s32[2]{0} constant({1, 2})"); + EXPECT_DESC_AND_EXPLANATION( + SetName("c", HloInstruction::CreateConstant(LiteralUtil::CreateR0(10))), + m::Op().IsConstantScalar(42), + "an HloInstruction which is a constant scalar with value 42", + "HloInstruction's constant value 10 did not match expected value 42\n" + "in c = s32[] constant(10)"); + EXPECT_DESC_AND_EXPLANATION( + SetName("c", HloInstruction::CreateConstant(LiteralUtil::CreateR0(2.25))), + m::Op().IsConstantEffectiveScalar(1.25), + "an HloInstruction which is a constant effective scalar with value 1.25", + "HloInstruction's constant value 2.25 did not match expected value 1.25\n" + "in c = f64[] constant(2.25)"); + EXPECT_DESC_AND_EXPLANATION( + constant, m::Op().Is(iota.get()), + absl::StrCat("an HloInstruction which is 0x", absl::Hex(iota.get()), + " (i = s32[42]{0} iota(), iota_dimension=0)"), + absl::StrCat("HloInstruction 0x", absl::Hex(constant.get()), " is not 0x", + absl::Hex(iota.get()), + " (i = s32[42]{0} iota(), iota_dimension=0)\n" + "in c = s32[] constant(0)")); +} + +TEST(PatternMatcherTest, HloInstructionMatcherAnyOrderDescribeTo) { + auto scalar_s32 = ShapeUtil::MakeShape(S32, {}); + EXPECT_DESC_AND_EXPLANATION( + SetName("a", HloInstruction::CreateBinary( + scalar_s32, HloOpcode::kAdd, + SetName("b", HloInstruction::CreateConstant( + LiteralUtil::CreateR0(0))) + .get(), + SetName("c", HloInstruction::CreateConstant( + LiteralUtil::CreateR0(0))) + .get())), + m::AddAnyOrder(m::Op().WithName("b"), m::Op().WithName("bar")), + "an HloInstruction:\n" + " * with opcode add AND\n" + " * with two operands in either order:\n" + " - an HloInstruction named \"b\"\n" + " - an HloInstruction named \"bar\"", + "HloInstruction's operands (ignoring order) did not match second " + "matcher. Specifically,\n" + " - an HloInstruction named \"bar\"\n" + "does not match LHS:\n" + " - HloInstruction not named \"bar\"\n" + " in b = s32[] constant(0)\n" + "does not match RHS:\n" + " - HloInstruction not named \"bar\"\n" + " in c = s32[] constant(0)\n" + "in a = s32[] add(s32[] b, s32[] c)"); + + EXPECT_DESC_AND_EXPLANATION( + SetName("a", + HloInstruction::CreateBinary( + scalar_s32, HloOpcode::kAdd, + HloInstruction::CreateParameter(0, scalar_s32, "p").get(), + SetName("c", HloInstruction::CreateConstant( + LiteralUtil::CreateR0(0))) + .get())), + m::AddAnyOrder(m::Op().IsConstantScalar(), m::Op().IsConstant()), + "an HloInstruction:\n" + " * with opcode add AND\n" + " * with two operands in either order:\n" + " - an HloInstruction which is a constant scalar\n" + " - an HloInstruction with opcode constant", + "HloInstruction's LHS operand did not match either of the two matchers. " + "Specifically,\n" + " - an HloInstruction which is a constant scalar\n" + "does not match LHS:\n" + " - HloInstruction is not a constant\n" + " in p = s32[] parameter(0)\n" + "and\n" + " - an HloInstruction with opcode constant\n" + "does not match LHS:\n" + " - HloInstruction doesn't have opcode constant\n" + " in p = s32[] parameter(0)\n" + "in a = s32[] add(s32[] p, s32[] c)"); +} + +TEST(PatternMatcherTest, AnyOfMatcherDescribeToAndExplain) { + EXPECT_DESC_AND_EXPLANATION( + SetName("c", HloInstruction::CreateConstant(LiteralUtil::CreateR0(0))), + m::AnyOf(m::Op().WithName("foo"), + m::Op().WithName("bar")), + "any of:\n" + " - an HloInstruction named \"foo\" OR\n" + " - an HloInstruction named \"bar\"", + "None of the following matchers succeeded:\n" + "Matcher #1\n" + " - an HloInstruction named \"foo\"\n" + "failed with\n" + " - HloInstruction not named \"foo\"\n" + " in c = s32[] constant(0)\n" + "Matcher #2\n" + " - an HloInstruction named \"bar\"\n" + "failed with\n" + " - HloInstruction not named \"bar\"\n" + " in c = s32[] constant(0)"); +} + +TEST(PatternMatcherTest, Parameter) { + auto param = + HloInstruction::CreateParameter(1, ShapeUtil::MakeShape(F32, {}), "p1"); + auto non_param = + SetName("c", HloInstruction::CreateConstant(LiteralUtil::CreateR0(0))); + EXPECT_FALSE(Match(param.get(), m::Parameter(0))); + EXPECT_TRUE(Match(param.get(), m::Parameter())); + EXPECT_TRUE(Match(param.get(), m::Parameter(1))); + EXPECT_FALSE(Match(non_param.get(), m::Parameter())); + EXPECT_FALSE(Match(non_param.get(), m::Parameter(1))); + + EXPECT_DESC_AND_EXPLANATION(non_param, m::Parameter(1), + "an HloInstruction:\n" + " * with opcode parameter AND\n" + " * which is parameter 1", + "HloInstruction doesn't have opcode parameter\n" + "in c = s32[] constant(0)"); + EXPECT_EQ(Explanation(HloInstruction::CreateParameter( + 0, ShapeUtil::MakeShape(F32, {}), "p0"), + m::Parameter(1)), + "HloInstruction is not parameter 1\n" + "in p0 = f32[] parameter(0)"); +} + +TEST(PatternMatcherTest, OneUseAndOneUser) { + auto param = + HloInstruction::CreateParameter(0, ShapeUtil::MakeShape(F32, {}), "p0"); + + EXPECT_FALSE(Match(param.get(), m::Op().WithOneUse())); + EXPECT_DESC_AND_EXPLANATION( + param, m::Op().WithOneUse(), + "an HloInstruction which has exactly one use", + "HloInstruction has 0 users, but expected exactly one.\n" + "in p0 = f32[] parameter(0)"); + + EXPECT_FALSE(Match(param.get(), m::Op().WithOneUser())); + EXPECT_DESC_AND_EXPLANATION( + param, m::Op().WithOneUser(), + "an HloInstruction which has exactly one user (but possibly is used " + "multiple times by that instruction)", + "HloInstruction has 0 users, but expected exactly one.\n" + "in p0 = f32[] parameter(0)"); + + { + auto reshape = + SetName("r", HloInstruction::CreateReshape( + ShapeUtil::MakeShape(F32, {1}), param.get())); + EXPECT_TRUE(Match(param.get(), m::Op().WithOneUse())); + EXPECT_TRUE(Match(param.get(), m::Op().WithOneUser())); + + auto reshape1 = + SetName("r1", HloInstruction::CreateReshape( + ShapeUtil::MakeShape(F32, {1}), param.get())); + EXPECT_FALSE(Match(param.get(), m::Op().WithOneUse())); + EXPECT_FALSE(Match(param.get(), m::Op().WithOneUser())); + + const char* kMultipleUserExplanation = + "HloInstruction has 2 users, but expected exactly one.\n" + "All users:\n" + " - r = f32[1]{0} reshape(f32[] p0)\n" + " - r1 = f32[1]{0} reshape(f32[] p0)\n" + "in p0 = f32[] parameter(0)"; + EXPECT_EQ(Explanation(param.get(), m::Op().WithOneUse()), + kMultipleUserExplanation); + EXPECT_EQ(Explanation(param.get(), m::Op().WithOneUser()), + kMultipleUserExplanation); + } + + auto add = SetName("add", HloInstruction::CreateBinary( + ShapeUtil::MakeShape(F32, {}), HloOpcode::kAdd, + param.get(), param.get())); + EXPECT_TRUE(Match(param.get(), m::Op().WithOneUser())); + EXPECT_FALSE(Match(param.get(), m::Op().WithOneUse())); + EXPECT_EQ(Explanation(param.get(), m::Op().WithOneUse()), + "HloInstruction is used 2 times by its user, but is expected to be " + "used just once: add = f32[] add(f32[] p0, f32[] p0)\n" + "in p0 = f32[] parameter(0)"); +} + } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/service/reduce_precision_insertion_test.cc b/tensorflow/compiler/xla/service/reduce_precision_insertion_test.cc index 16fa80d53e..efeec96571 100644 --- a/tensorflow/compiler/xla/service/reduce_precision_insertion_test.cc +++ b/tensorflow/compiler/xla/service/reduce_precision_insertion_test.cc @@ -54,7 +54,7 @@ TEST_F(ReducePrecisionInsertionTest, BeforeUnaryInstruction) { HloInstruction* b = builder.AddInstruction( HloInstruction::CreateUnary(shape, HloOpcode::kCos, a)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected state before adding ops. @@ -81,7 +81,7 @@ TEST_F(ReducePrecisionInsertionTest, BeforeUnaryScalarInstruction) { HloInstruction* b = builder.AddInstruction( HloInstruction::CreateUnary(shape, HloOpcode::kCos, a)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected state before adding ops. @@ -111,7 +111,7 @@ TEST_F(ReducePrecisionInsertionTest, BeforeBinaryInstruction) { HloInstruction* c = builder.AddInstruction( HloInstruction::CreateBinary(shape, HloOpcode::kAdd, a, b)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected state before adding ops. @@ -140,7 +140,7 @@ TEST_F(ReducePrecisionInsertionTest, BeforeZeroInputInstruction) { HloInstruction* b = builder.AddInstruction( HloInstruction::CreateUnary(shape, HloOpcode::kCos, a)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected state before adding ops. @@ -173,7 +173,7 @@ TEST_F(ReducePrecisionInsertionTest, AvoidAddingDuplicateInstructions) { HloInstruction* d = builder.AddInstruction( HloInstruction::CreateBinary(shape, HloOpcode::kAdd, b, c)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected state before adding ops. @@ -205,7 +205,7 @@ TEST_F(ReducePrecisionInsertionTest, AfterRootInstruction) { HloInstruction* b = builder.AddInstruction( HloInstruction::CreateUnary(shape, HloOpcode::kCos, a)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected state before adding ops. @@ -242,7 +242,7 @@ TEST_F(ReducePrecisionInsertionTest, AfterNonRootInstruction) { HloInstruction* c = builder.AddInstruction( HloInstruction::CreateBinary(shape, HloOpcode::kAdd, a_cos, b_cos)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); module->AddEntryComputation(builder.Build()); // Confirm expected graph before adding ops. @@ -295,7 +295,7 @@ TEST_F(ReducePrecisionInsertionTest, ShouldReduceOutputPrecisionIsFalse) { HloInstruction* y = builder.AddInstruction( HloInstruction::CreateUnary(shape, HloOpcode::kCos, x)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected graph before adding ops. @@ -321,7 +321,7 @@ TEST_F(ReducePrecisionInsertionTest, InsertionIsNotRecursive) { HloInstruction* b = builder.AddInstruction( HloInstruction::CreateReducePrecision(shape, a, 8, 23)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected state before adding ops. @@ -348,7 +348,7 @@ TEST_F(ReducePrecisionInsertionTest, SkipRedundantReducePrecisionAfter) { HloInstruction* y = builder.AddInstruction( HloInstruction::CreateReducePrecision(shape, x, 5, 10)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected graph before adding ops. @@ -376,7 +376,7 @@ TEST_F(ReducePrecisionInsertionTest, AddNonRedundantReducePrecision) { HloInstruction* y = builder.AddInstruction( HloInstruction::CreateReducePrecision(shape, x, 8, 23)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Confirm expected graph before adding ops. @@ -402,7 +402,7 @@ TEST_F(ReducePrecisionInsertionTest, IgnoreOpsInsideFusionNode) { builder.AddInstruction(HloInstruction::CreateParameter(0, shape, "x")); HloInstruction* y = builder.AddInstruction( HloInstruction::CreateUnary(shape, HloOpcode::kCos, x)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Manually fuse the kCos operation into a fusion operation. @@ -438,7 +438,7 @@ TEST_F(ReducePrecisionInsertionTest, OpGetsInsertedInHeadOfFusionNode) { builder.AddInstruction(HloInstruction::CreateParameter(0, shape, "x")); HloInstruction* y = builder.AddInstruction( HloInstruction::CreateUnary(shape, HloOpcode::kCos, x)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Manually fuse the kCos operation into a fusion operation. @@ -485,7 +485,7 @@ TEST_F(ReducePrecisionInsertionTest, OpGetsInsertedInTailOfFusionNode) { builder.AddInstruction(HloInstruction::CreateParameter(0, shape, "x")); HloInstruction* y = builder.AddInstruction( HloInstruction::CreateUnary(shape, HloOpcode::kCos, x)); - auto module = CreateNewUnverifiedModule(); + auto module = CreateNewVerifiedModule(); auto computation = module->AddEntryComputation(builder.Build()); // Manually fuse the kCos operation into a fusion operation. diff --git a/tensorflow/compiler/xla/service/service.cc b/tensorflow/compiler/xla/service/service.cc index 75f7413b3c..5ec7fe2ade 100644 --- a/tensorflow/compiler/xla/service/service.cc +++ b/tensorflow/compiler/xla/service/service.cc @@ -41,6 +41,7 @@ limitations under the License. #include "tensorflow/compiler/xla/service/source_map_util.h" #include "tensorflow/compiler/xla/service/stream_pool.h" #include "tensorflow/compiler/xla/service/transfer_manager.h" +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/shape_layout.h" #include "tensorflow/compiler/xla/shape_util.h" #include "tensorflow/compiler/xla/status_macros.h" @@ -275,8 +276,8 @@ StatusOr> Service::CreateModuleConfig( } if (execution_options != nullptr && execution_options->has_shape_with_output_layout()) { - const auto& shape_with_output_layout = - execution_options->shape_with_output_layout(); + const Shape shape_with_output_layout( + execution_options->shape_with_output_layout()); TF_RETURN_IF_ERROR( ValidateResultShape(shape_with_output_layout, program_shape.result())); TF_RETURN_IF_ERROR( @@ -658,9 +659,9 @@ Status Service::ExecuteGraphParallel(const ExecuteGraphParallelRequest* arg, // replica 0. TF_ASSIGN_OR_RETURN( std::unique_ptr module_config, - CreateModuleConfig(request.computation().host_program_shape(), - replicated_arguments.front(), - request.execution_options())); + CreateModuleConfig( + ProgramShape{request.computation().host_program_shape()}, + replicated_arguments.front(), request.execution_options())); VLOG(3) << "ExecuteGraphParallel created HloModuleConfig computation layout: " << module_config->entry_computation_layout().ToString(); @@ -745,9 +746,9 @@ Status Service::GetDeviceHandles(const GetDeviceHandlesRequest* arg, } if (available_device_count < arg->device_count() * replica_count) { return ResourceExhausted( - "Requested device count (%d) exceeds the number of available devices " - "on the target (%d)", - arg->device_count(), available_device_count); + "Requested logical device count (%d) with replica count (%d) exceeds " + "the number of available physical devices on the target (%d)", + arg->device_count(), replica_count, available_device_count); } for (int64 i = 0; i < arg->device_count(); ++i) { @@ -818,14 +819,17 @@ Status Service::Compile(const CompileRequest* arg, CompileResponse* result) { "The compile request does not support multiple device handles."); } - std::vector argument_shapes; - absl::c_transform(arg->input_shape_with_layout(), - std::back_inserter(argument_shapes), - [](const Shape& shape) { return &shape; }); + std::vector argument_shapes; + argument_shapes.reserve(arg->input_shape_with_layout_size()); + std::vector argument_shape_ptrs; + for (const ShapeProto& shape_proto : arg->input_shape_with_layout()) { + argument_shapes.push_back(Shape(shape_proto)); + argument_shape_ptrs.push_back(&argument_shapes.back()); + } TF_ASSIGN_OR_RETURN( std::unique_ptr module_config, - CreateModuleConfig(arg->computation().host_program_shape(), - argument_shapes, &arg->execution_options())); + CreateModuleConfig(ProgramShape{arg->computation().host_program_shape()}, + argument_shape_ptrs, &arg->execution_options())); VLOG(3) << "Compile created HloModuleConfig computation layout: " << module_config->entry_computation_layout().ToString(); @@ -930,14 +934,14 @@ Status Service::TransferToClient(const TransferToClientRequest* arg, TF_ASSIGN_OR_RETURN(const ShapedBuffer* shaped_buffer, allocation_tracker_.ResolveForReplica(arg->data(), 0)); - const Shape* return_shape; + Shape return_shape; if (arg->has_shape_with_layout()) { - if (!LayoutUtil::HasLayout(arg->shape_with_layout())) { + return_shape = Shape(arg->shape_with_layout()); + if (!LayoutUtil::HasLayout(return_shape)) { return InvalidArgument("shape_with_layout must have layout if present."); } - return_shape = &arg->shape_with_layout(); } else { - return_shape = &shaped_buffer->on_host_shape(); + return_shape = Shape(shaped_buffer->on_host_shape()); } TF_ASSIGN_OR_RETURN(auto stream, execute_backend_->BorrowStream( @@ -948,30 +952,15 @@ Status Service::TransferToClient(const TransferToClientRequest* arg, execute_backend_->transfer_manager()->TransferLiteralFromDevice( stream.get(), *shaped_buffer)); - if (LayoutUtil::LayoutsInShapesEqual(*return_shape, result_literal.shape())) { + if (LayoutUtil::LayoutsInShapesEqual(return_shape, result_literal.shape())) { *result->mutable_literal() = result_literal.ToProto(); } else { *result->mutable_literal() = - result_literal.Relayout(*return_shape).ToProto(); + result_literal.Relayout(return_shape).ToProto(); } return Status::OK(); } -namespace { - -// Creates a clone of the given shaped buffer with the given device ordinal. The -// shape and DeviceMemoryBase values of the clone are identical to the original. -std::unique_ptr CloneShapedBufferOnDevice( - const ShapedBuffer& shaped_buffer, int device_ordinal) { - auto clone = absl::make_unique( - shaped_buffer.on_host_shape(), shaped_buffer.on_device_shape(), - shaped_buffer.platform(), device_ordinal); - clone->buffers() = shaped_buffer.buffers(); - return clone; -} - -} // namespace - Status Service::TransferToServer(const TransferToServerRequest* arg, TransferToServerResponse* result) { TF_ASSIGN_OR_RETURN(Literal literal, @@ -1060,11 +1049,11 @@ Status Service::TransferFromOutfeed(const TransferFromOutfeedRequest* arg, executor = replicas[arg->replica_id()]; } - auto literal = Literal::CreateFromShape(arg->shape_with_layout()); + auto literal = Literal::CreateFromShape(Shape(arg->shape_with_layout())); TF_RETURN_IF_ERROR( execute_backend_->transfer_manager()->TransferLiteralFromOutfeed( - executor, arg->shape_with_layout(), literal)); + executor, Shape(arg->shape_with_layout()), literal)); *result->mutable_literal() = literal.ToProto(); return Status::OK(); } @@ -1087,7 +1076,7 @@ Status Service::ComputeConstantGraph(const ComputeConstantGraphRequest* arg, "constant computation may not depend on any parameters."); } - ProgramShape program_shape = arg->computation().host_program_shape(); + ProgramShape program_shape(arg->computation().host_program_shape()); TF_DCHECK_OK(ShapeUtil::ValidateShape(program_shape.result())); if (arg->has_output_layout()) { TF_RETURN_IF_ERROR(LayoutUtil::ValidateLayoutForShape( @@ -1118,7 +1107,7 @@ Status Service::ComputeConstantGraph(const ComputeConstantGraphRequest* arg, Status Service::GetShape(const GetShapeRequest* arg, GetShapeResponse* result) { TF_ASSIGN_OR_RETURN(const ShapedBuffer* buffer, allocation_tracker_.ResolveForReplica(arg->data(), 0)); - *result->mutable_shape() = buffer->on_host_shape(); + *result->mutable_shape() = buffer->on_host_shape().ToProto(); return Status::OK(); } @@ -1131,7 +1120,7 @@ Status Service::GetComputationGraphStats( return InvalidArgument("Program shape may not be empty."); } - HloModuleConfig config(arg->computation().host_program_shape()); + HloModuleConfig config(ProgramShape{arg->computation().host_program_shape()}); config.set_debug_options(arg->debug_options()); TF_ASSIGN_OR_RETURN(std::unique_ptr module, CreateModuleFromProto(arg->computation(), config)); diff --git a/tensorflow/compiler/xla/service/shape_inference.cc b/tensorflow/compiler/xla/service/shape_inference.cc index 61a60ef9ef..7e7282a737 100644 --- a/tensorflow/compiler/xla/service/shape_inference.cc +++ b/tensorflow/compiler/xla/service/shape_inference.cc @@ -391,17 +391,6 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, return ShapeUtil::MakeShape(element_type, new_dimensions); } -/* static */ StatusOr ShapeInference::InferAfterAllShape( - absl::Span arg_shapes) { - for (const Shape* arg_shape : arg_shapes) { - if (arg_shape->element_type() != TOKEN) { - return InvalidArgument( - "Operands of token instructions must be TOKEN types."); - } - } - return ShapeUtil::MakeTokenShape(); -} - /* static */ StatusOr ShapeInference::InferConvertShape( const Shape& operand_shape, PrimitiveType new_element_type) { auto old_element_type = operand_shape.element_type(); @@ -1029,7 +1018,7 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, switch (opcode) { case HloOpcode::kTuple: { Shape result = ShapeUtil::MakeTupleShape({}); - result.mutable_tuple_shapes()->Reserve(operand_shapes.size()); + result.mutable_tuple_shapes()->reserve(operand_shapes.size()); for (const Shape* shape : operand_shapes) { ShapeUtil::AppendShapeToTuple(*shape, &result); } @@ -2038,7 +2027,16 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, dimension); } - return ShapeUtil::MakeShape(S64, {}); + // TODO(b/119580730): Remove this restriction when very large dimension size + // is needed. + if (shape.dimensions(dimension) > std::numeric_limits::max()) { + return InvalidArgument( + "GetDimensionSize's input shape is %s, the %dth dimension exceeds the " + "UINT_MAX limit.", + ShapeUtil::HumanString(shape), dimension); + } + + return ShapeUtil::MakeShape(U32, {}); } /* static */ StatusOr ShapeInference::InferSliceShape( diff --git a/tensorflow/compiler/xla/service/shape_inference.h b/tensorflow/compiler/xla/service/shape_inference.h index 31ef4b2e41..d94385a04d 100644 --- a/tensorflow/compiler/xla/service/shape_inference.h +++ b/tensorflow/compiler/xla/service/shape_inference.h @@ -232,13 +232,6 @@ class ShapeInference { static StatusOr InferConcatOpShape( absl::Span arg_shapes, int64 dimension); - // Infers the shape produced by a kAfterAll. Trivially this shape is always a - // TOKEN shape. However, ShapeInference serves two purposes: inferring shapes - // and checking operand shapes. This method verifies that the operand shapes - // are all TOKENs. - static StatusOr InferAfterAllShape( - absl::Span arg_shapes); - // Helper that validates the given operand shape can be converted to the // target output_shape via a convert instruction -- the requirement is that // the shape is identical except for the element type. diff --git a/tensorflow/compiler/xla/service/transpose_folding_test.cc b/tensorflow/compiler/xla/service/transpose_folding_test.cc index 7a565bf076..17cdaa74fc 100644 --- a/tensorflow/compiler/xla/service/transpose_folding_test.cc +++ b/tensorflow/compiler/xla/service/transpose_folding_test.cc @@ -172,7 +172,7 @@ TEST_F(TransposeFoldingTest, FuseDotWithConstantOperands) { HloInstruction* mul = builder.AddInstruction(HloInstruction::CreateBinary( add->shape(), HloOpcode::kMultiply, add, sub)); - auto module = CreateNewUnverifiedModule("fuse_with_constant_operands"); + auto module = CreateNewVerifiedModule("fuse_with_constant_operands"); HloComputation* entry_computation = module->AddEntryComputation(builder.Build(mul)); HloInstruction* call = module->OutlineExpressionFromComputation( @@ -247,7 +247,7 @@ TEST_F(TransposeFoldingTest, FoldConvDimSwapTransposeRhs) { conv_shape.ValueOrDie(), x, transpose_y, /*feature_group_count=*/1, window, dnums, DefaultPrecisionConfig(2))); - auto module = CreateNewUnverifiedModule("test_module"); + auto module = CreateNewVerifiedModule("test_module"); HloComputation* entry_computation = module->AddEntryComputation(builder.Build(conv)); FoldTranspose(module.get()); @@ -302,7 +302,7 @@ TEST_F(TransposeFoldingTest, FoldConvComplexTransposeRhs) { conv_shape.ValueOrDie(), x, transpose_y, /*feature_group_count=*/1, window, dnums, DefaultPrecisionConfig(2))); - auto module = CreateNewUnverifiedModule("test_module"); + auto module = CreateNewVerifiedModule("test_module"); HloComputation* entry_computation = module->AddEntryComputation(builder.Build(conv)); FoldTranspose(module.get()); @@ -362,7 +362,7 @@ TEST_F(TransposeFoldingTest, FoldConvTransposeLhs) { conv_shape.ValueOrDie(), transpose_x, y, /*feature_group_count=*/1, window, dnums, DefaultPrecisionConfig(2))); - auto module = CreateNewUnverifiedModule("test_module"); + auto module = CreateNewVerifiedModule("test_module"); HloComputation* entry_computation = module->AddEntryComputation(builder.Build(conv)); FoldTranspose(module.get()); @@ -428,7 +428,7 @@ TEST_F(TransposeFoldingTest, FoldConvComplexTransposeLhs) { conv_shape.ValueOrDie(), transpose_x, y, /*feature_group_count=*/1, window, dnums, DefaultPrecisionConfig(2))); - auto module = CreateNewUnverifiedModule("test_module"); + auto module = CreateNewVerifiedModule("test_module"); HloComputation* entry_computation = module->AddEntryComputation(builder.Build(conv)); FoldTranspose(module.get()); diff --git a/tensorflow/compiler/xla/service/tuple_points_to_analysis.cc b/tensorflow/compiler/xla/service/tuple_points_to_analysis.cc index 96f3055c98..50d51eaeb7 100644 --- a/tensorflow/compiler/xla/service/tuple_points_to_analysis.cc +++ b/tensorflow/compiler/xla/service/tuple_points_to_analysis.cc @@ -280,6 +280,13 @@ Status TuplePointsToAnalysis::HandleDomain(HloInstruction* domain) { return Status::OK(); } +Status TuplePointsToAnalysis::HandleAddDependency( + HloInstruction* add_dependency) { + // AddDependency just forwards the value of its zero-th operand. + CreateCopiedPointsToSet(add_dependency, add_dependency->operand(0)); + return Status::OK(); +} + Status TuplePointsToAnalysis::HandleRecvDone(HloInstruction* recv_done) { // RecvDone aliases its input (Recv) tuple element {0} to element {0} of its // output. The other indices ({} and {1}) define their own buffers. diff --git a/tensorflow/compiler/xla/service/tuple_points_to_analysis.h b/tensorflow/compiler/xla/service/tuple_points_to_analysis.h index bcfcb388f9..0a1d5649d6 100644 --- a/tensorflow/compiler/xla/service/tuple_points_to_analysis.h +++ b/tensorflow/compiler/xla/service/tuple_points_to_analysis.h @@ -252,6 +252,7 @@ class TuplePointsToAnalysis : public DfsHloVisitorWithDefault { Status HandleRecvDone(HloInstruction* recv_done) override; Status HandleSend(HloInstruction* send) override; Status HandleTupleSelect(HloInstruction* tuple_select) override; + Status HandleAddDependency(HloInstruction* add_dependency) override; string ToString() const; diff --git a/tensorflow/compiler/xla/service/tuple_points_to_analysis_test.cc b/tensorflow/compiler/xla/service/tuple_points_to_analysis_test.cc index 10ef2d38fa..561762b5d4 100644 --- a/tensorflow/compiler/xla/service/tuple_points_to_analysis_test.cc +++ b/tensorflow/compiler/xla/service/tuple_points_to_analysis_test.cc @@ -264,6 +264,22 @@ TEST_F(TuplePointsToAnalysisTest, GetTupleElement) { UnorderedElementsAre(inner_tuple)); } +TEST_F(TuplePointsToAnalysisTest, AddDependency) { + auto builder = HloComputation::Builder(TestName()); + auto constant = builder.AddInstruction( + HloInstruction::CreateConstant(LiteralUtil::CreateR0(1.0))); + auto token = builder.AddInstruction(HloInstruction::CreateToken()); + auto add_dependency = builder.AddInstruction( + HloInstruction::CreateAddDependency(constant, token)); + BuildModuleAndRunAnalysis(builder.Build()); + + auto& points_to_set = points_to_analysis_->GetPointsToSet(add_dependency); + EXPECT_EQ(1, points_to_set.size()); + EXPECT_FALSE(points_to_set.IsAmbiguous()); + EXPECT_TRUE(points_to_set.IsDistinct()); + ExpectHasTopLevelBuffers(points_to_set.CreateFlattenedSet(), {constant}); +} + TEST_F(TuplePointsToAnalysisTest, DuplicatedElement) { // Create a tuple which contains duplicate elements. auto builder = HloComputation::Builder(TestName()); diff --git a/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.cc b/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.cc index b7c28bfac7..41011176ff 100644 --- a/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.cc +++ b/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.cc @@ -21,6 +21,7 @@ limitations under the License. #include "tensorflow/compiler/xla/service/tuple_util.h" #include "tensorflow/compiler/xla/service/while_loop_analysis.h" #include "tensorflow/compiler/xla/service/while_util.h" +#include "tensorflow/compiler/xla/shape_util.h" #include "tensorflow/compiler/xla/util.h" namespace xla { @@ -207,6 +208,37 @@ WhileLoopInvariantCodeMotion::TryHoistingInvariantInstructionsFromWhileBody( continue; } + if (!hoist_size_inflating_ops_) { + // Check that hoisting the instruction doesn't cause a significant memory + // blow-up. LICM extends the live-range of the output of the hoisted + // instruction to be the entire while loop, which may be problematic on + // platforms where memory is limited. This can be especially harmful if + // the instruction has a significantly larger output than its input, e.g. + // kIota, kBroadcast or kConstant. + int64 input_size = 0, output_size = 0; + + for (auto* operand : instruction->operands()) { + ShapeUtil::ForEachSubshape( + operand->shape(), + [&input_size](const Shape& subshape, const ShapeIndex& /*index*/) { + if (ShapeUtil::IsArray(subshape)) { + input_size += ShapeUtil::ByteSizeOfElements(subshape); + } + }); + } + ShapeUtil::ForEachSubshape( + instruction->shape(), + [&output_size](const Shape& subshape, const ShapeIndex& /*index*/) { + if (ShapeUtil::IsArray(subshape)) { + output_size += ShapeUtil::ByteSizeOfElements(subshape); + } + }); + + if (output_size > input_size) { + continue; + } + } + auto is_invariant = [&](HloInstruction* op) { return hoisted_instructions.find(op) != hoisted_instructions.end() || unhoisted_invariant_instructions.count(op) || diff --git a/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.h b/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.h index 3031899f71..bd6232dc0a 100644 --- a/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.h +++ b/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.h @@ -34,8 +34,14 @@ class WhileLoopInvariantCodeMotion : public HloModulePass { // Setting `hoist_constants` to false can be help if LICM is run in the mid // level HLO pipeline because hoisting constants out of while loop bodies can // break optimizations like constant folding. - explicit WhileLoopInvariantCodeMotion(bool hoist_constants = false) - : hoist_constants_(hoist_constants) {} + // Setting `hoist_size_inflating_ops` to false will forbid hoisting + // instructions where the size of the output(s) is larger than the size of the + // input(s). This is useful on platforms on which it's important to prevent + // blow-ups in memory size. + explicit WhileLoopInvariantCodeMotion(bool hoist_constants = false, + bool hoist_size_inflating_ops = true) + : hoist_constants_(hoist_constants), + hoist_size_inflating_ops_(hoist_size_inflating_ops) {} ~WhileLoopInvariantCodeMotion() override = default; absl::string_view name() const override { @@ -49,6 +55,7 @@ class WhileLoopInvariantCodeMotion : public HloModulePass { HloInstruction* while_instr); bool hoist_constants_; + bool hoist_size_inflating_ops_; }; } // namespace xla diff --git a/tensorflow/compiler/xla/service/while_loop_invariant_code_motion_test.cc b/tensorflow/compiler/xla/service/while_loop_invariant_code_motion_test.cc index 046ccb2d3f..8e7c4bc882 100644 --- a/tensorflow/compiler/xla/service/while_loop_invariant_code_motion_test.cc +++ b/tensorflow/compiler/xla/service/while_loop_invariant_code_motion_test.cc @@ -570,5 +570,59 @@ TEST_F(WhileLoopInvariantCodeMotionTest, DoNotHoistOutOfSingleIteration) { EXPECT_FALSE(simplified_loop); } +const char* const kInflatingTestCase = R"( +HloModule ModuleWithWhile + +mul { + lhs = f32[] parameter(0) + rhs = f32[] parameter(1) + ROOT mul = f32[] multiply(lhs, rhs) +} + +body { + p_body = (f32[]) parameter(0) + iota = f32[1024, 1024] iota(), iota_dimension=0 + add = f32[1024, 1024] add(iota, iota) + constant = f32[] constant(1.0) + reduce = f32[] reduce(f32[1024, 1024] add, f32[] constant), dimensions={0,1}, to_apply=mul + ROOT root = (f32[]) tuple(reduce) +} + +condition { + p_cond = (f32[]) parameter(0) + ROOT result = pred[] constant(true) +} + +ENTRY entry { + param = f32[] parameter(0) + while_init = (f32[]) tuple(param) + ROOT while = (f32[]) while(while_init), condition=condition, body=body +} +)"; + +TEST_F(WhileLoopInvariantCodeMotionTest, HoistsInflatingByDefault) { + auto m = ParseAndReturnVerifiedModule(kInflatingTestCase).ValueOrDie(); + + TF_ASSERT_OK_AND_ASSIGN( + bool simplified_loop, + WhileLoopInvariantCodeMotion(/*hoist_constants=*/true).Run(m.get())); + EXPECT_TRUE(simplified_loop); + + HloComputation* while_body = m->GetComputationWithName("wide.body"); + ASSERT_NE(while_body, nullptr); + EXPECT_THAT(while_body->instructions(), Not(Contains(op::Iota()))); +} + +TEST_F(WhileLoopInvariantCodeMotionTest, NoHoistInflating) { + auto m = ParseAndReturnVerifiedModule(kInflatingTestCase).ValueOrDie(); + + TF_ASSERT_OK_AND_ASSIGN( + bool simplified_loop, + WhileLoopInvariantCodeMotion(/*hoist_constants=*/true, + /*hoist_size_inflating_ops=*/false) + .Run(m.get())); + EXPECT_FALSE(simplified_loop); +} + } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/service/while_loop_simplifier.cc b/tensorflow/compiler/xla/service/while_loop_simplifier.cc index 6f924a29d8..d30f67dd81 100644 --- a/tensorflow/compiler/xla/service/while_loop_simplifier.cc +++ b/tensorflow/compiler/xla/service/while_loop_simplifier.cc @@ -19,13 +19,17 @@ limitations under the License. #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" #include "absl/types/optional.h" +#include "tensorflow/compiler/xla/primitive_util.h" #include "tensorflow/compiler/xla/service/call_inliner.h" #include "tensorflow/compiler/xla/service/hlo_instruction.h" +#include "tensorflow/compiler/xla/service/hlo_instructions.h" #include "tensorflow/compiler/xla/service/hlo_query.h" +#include "tensorflow/compiler/xla/service/pattern_matcher.h" #include "tensorflow/compiler/xla/service/while_loop_analysis.h" namespace xla { +namespace m = match; using absl::optional; using hlo_query::ContainsInstrWithOpcode; @@ -302,6 +306,147 @@ static StatusOr TryRemoveDeadWhileParams(HloInstruction* while_op) { return true; } +// Removes each loop parameter (i.e. member of the while loop tuple) that is a +// constant and is the same in the while loop body and the while loop init. +static StatusOr TryRemoveConstantParams(HloInstruction* while_op) { + HloModule* module = while_op->GetModule(); + HloComputation* computation = while_op->parent(); + auto* while_init = while_op->mutable_operand(0); + auto* while_body = while_op->while_body(); + auto* while_cond = while_op->while_condition(); + auto* while_body_root = while_body->root_instruction(); + if (while_init->opcode() != HloOpcode::kTuple || + while_body_root->opcode() != HloOpcode::kTuple) { + return false; + } + + TF_RET_CHECK(while_cond->num_parameters() == 1); + TF_RET_CHECK(while_body->num_parameters() == 1); + TF_RET_CHECK( + ShapeUtil::Compatible(while_init->shape(), while_body_root->shape())); + + absl::flat_hash_set constant_tuple_indices; + const auto& while_shape = while_init->shape(); + for (int64 i = 0; i < while_shape.tuple_shapes_size(); ++i) { + auto* init_elem = while_init->operand(i); + auto* body_elem = while_body_root->operand(i); + if (init_elem->opcode() == HloOpcode::kConstant && + body_elem->opcode() == HloOpcode::kConstant && + init_elem->literal() == body_elem->literal()) { + constant_tuple_indices.insert(i); + } + } + + if (constant_tuple_indices.empty()) { + return false; + } + + // OK, we found some constant elements of the while parameter! Eliminate + // them. + std::vector new_while_shape_elems; + for (int64 i = 0; i < while_shape.tuple_shapes_size(); ++i) { + if (!constant_tuple_indices.count(i)) { + new_while_shape_elems.push_back(while_shape.tuple_shapes(i)); + } + } + Shape new_while_shape = ShapeUtil::MakeTupleShape(new_while_shape_elems); + + // `new_instrs` holds instructions created outside of a computation for + // cloning. Elements added here just need to live until the end of the + // relevant CloneWithReplacement call. + std::vector> new_instrs; + auto add_new_instr = [&](std::unique_ptr instr) { + new_instrs.push_back(std::move(instr)); + return new_instrs.back().get(); + }; + + // Returns a new tuple without the elements of constant_tuple_indices. + auto remove_constant_elems = [&](HloInstruction* instr) { + CHECK(ShapeUtil::Compatible(instr->shape(), while_shape)); + + std::vector tuple_elems; + for (int64 i = 0; i < while_shape.tuple_shapes_size(); ++i) { + if (!constant_tuple_indices.count(i)) { + tuple_elems.push_back( + add_new_instr(HloInstruction::CreateGetTupleElement( + while_shape.tuple_shapes(i), instr, i))); + } + } + return HloInstruction::CreateTuple(tuple_elems); + }; + + auto add_constant_elems = [&](HloInstruction* instr) { + CHECK(ShapeUtil::Compatible(instr->shape(), new_while_shape)); + + std::vector tuple_elems; + int64 j = 0; + for (int64 i = 0; i < while_shape.tuple_shapes_size(); ++i) { + if (constant_tuple_indices.count(i)) { + tuple_elems.push_back(while_init->mutable_operand(i)); + } else { + tuple_elems.push_back( + add_new_instr(HloInstruction::CreateGetTupleElement( + while_shape.tuple_shapes(i), instr, j))); + ++j; + } + } + return HloInstruction::CreateTuple(tuple_elems); + }; + + // Special case: constant_tuple_indices covers the whole while parameter, so + // the new while shape is the empty tuple. In this case, the value of the + // while loop is simply equal to the value of `init`. + // + // It's unfortunate to special-case this, but it's simpler than the + // alternative. The problem is that if our while parameter has no + // non-constant elems, the tuple returned by `add_constant_elems` won't depend + // on instr (the loop body/cond parameter), and therefore + // CloneWithReplacementPairs will *leave the parameter out entirely*, creating + // invalid HLO. + if (ShapeUtil::IsEmptyTuple(new_while_shape)) { + TF_RETURN_IF_ERROR(computation->ReplaceInstruction(while_op, while_init)); + return true; + } + + std::unique_ptr new_while_cond = + while_cond->CloneWithReplacementPairs({ + while_cond->parameter_instruction(0), + add_constant_elems(add_new_instr(HloInstruction::CreateParameter( + 0, new_while_shape, + while_cond->parameter_instruction(0)->name()))), + }); + + std::unique_ptr new_while_body = + while_body->CloneWithReplacementPairs( + { + while_body->parameter_instruction(0), + add_constant_elems(add_new_instr(HloInstruction::CreateParameter( + 0, new_while_shape, + while_cond->parameter_instruction(0)->name()))), + }, + { + while_body->root_instruction(), + remove_constant_elems( + add_new_instr(while_body->root_instruction()->Clone())), + }); + + // Create the final while loop, and add any new instructions created to + // `computation`. + new_instrs.clear(); + TF_RETURN_IF_ERROR(computation->ReplaceWithNewInstruction( + while_op, + add_constant_elems( + computation->AddInstruction(HloInstruction::CreateWhile( + new_while_shape, + module->AddEmbeddedComputation(std::move(new_while_cond)), + module->AddEmbeddedComputation(std::move(new_while_body)), + add_new_instr(remove_constant_elems(while_init))))))); + for (auto& instr : new_instrs) { + computation->AddInstruction(std::move(instr)); + } + return true; +} + // Tries to remove a while loop from the graph. // // - Loops with trip count of 0 can be replaced by the loop's "init" value. @@ -381,16 +526,14 @@ static StatusOr TryPropagateConstant(HloInstruction* while_op) { // performance by forcing us to copy constants. absl::flat_hash_map index_to_constant; for (int i = 0; i < root_operands.size(); i++) { - HloInstruction* instr = root_operands[i]; - if (instr->opcode() == HloOpcode::kGetTupleElement && - instr->tuple_index() == i && instr->operand(0) == while_body_param && - ShapeUtil::IsScalar(instr->shape())) { - auto tuple_element = while_init->operand(i); - if (tuple_element->IsConstant()) { - VLOG(3) << "Found loop invariant tuple element " << i << " " - << tuple_element->ToString(); - index_to_constant[i] = tuple_element; - } + const HloInstruction* init_tuple_elem = nullptr; + if (Match(root_operands[i], + m::GetTupleElement(m::Op().Is(while_body_param), i) + .WithShape(m::Shape().IsScalar())) && + Match(while_init->operand(i), m::Constant(&init_tuple_elem))) { + VLOG(3) << "Found loop invariant tuple element " << i << " " + << init_tuple_elem->ToString(); + index_to_constant[i] = init_tuple_elem; } } @@ -519,14 +662,6 @@ static StatusOr TryFlattenNestedTuples(HloInstruction* while_op) { return false; } - // Cowardly refuse to perform this optimization in the presence of kDomain - // instructions, which may reference other instructions in the loop and - // therefore make this complicated. - if (ContainsInstrWithOpcode(while_body, {HloOpcode::kDomain}) || - ContainsInstrWithOpcode(while_cond, {HloOpcode::kDomain})) { - return false; - } - std::vector flattened_shape_elems; ShapeUtil::ForEachSubshape(while_shape, [&](const Shape& s, const ShapeIndex& /*index*/) { @@ -605,6 +740,243 @@ static StatusOr TryFlattenNestedTuples(HloInstruction* while_op) { return true; } +// Tries to merge loop induction variables of a given type. +// +// In this pass we're only concerned with elements of the loop's tuple that +// are effective-scalars of type `elem_ty`. Some terminology: +// +// - The trip counter is the first element of the loop's tuple that starts at +// 0 and does x++ on each iteration. +// +// - An induction variable is an element of the loop's tuple that is not the +// trip counter and does `x += ` on each iteration of the loop. +// Negative constants are OK. +// +// This pass adds a trip counter if one isn't already present, then replaces +// each induction variable with +// +// + * . +// +// This reduces the number of scalar operations in the loop, which is important +// e.g. on GPUs, where each scalar operation is nontrivially expensive because +// it's a separate kernel launch. +// +// Returns the new loop if a change was made, or null if no change was made. +// Note that the new loop is not a valid replacement for the old loop; it may +// need to be wrapped in a tuple that changes its shape. We return the loop +// itself so that you can call TryMergeInductionVariables in a loop, once for +// each integral type elem_ty. +static StatusOr TryMergeInductionVariables( + HloInstruction* while_op, PrimitiveType elem_ty) { + CHECK(primitive_util::IsIntegralType(elem_ty)) << PrimitiveType_Name(elem_ty); + HloModule* module = while_op->GetModule(); + HloComputation* computation = while_op->parent(); + auto* while_init = while_op->mutable_operand(0); + auto* while_body = while_op->while_body(); + auto* while_cond = while_op->while_condition(); + auto* while_body_root = while_body->root_instruction(); + if (while_init->opcode() != HloOpcode::kTuple || + while_body_root->opcode() != HloOpcode::kTuple) { + return nullptr; + } + + TF_RET_CHECK(while_cond->num_parameters() == 1); + TF_RET_CHECK(while_body->num_parameters() == 1); + TF_RET_CHECK( + ShapeUtil::Compatible(while_init->shape(), while_body_root->shape())); + Shape while_shape = while_init->shape(); + + // The tuple index of the trip counter, if one is present. + absl::optional trip_counter; + // Maps the tuple index of each induction variable to its constant increment. + absl::flat_hash_map induction_vars; + for (int64 i = 0; i < while_body_root->operand_count(); ++i) { + HloInstruction* constant; + if (!Match(while_body_root->mutable_operand(i), + m::AddAnyOrder(m::GetTupleElement(m::Parameter(), i), + m::ConstantScalar(&constant)) + .WithShape(m::Shape().WithElementType(elem_ty)))) { + continue; + } + if (!trip_counter && constant->literal().IsAll(1) && + while_init->operand(i)->IsConstant() && + while_init->operand(i)->literal().IsAll(0)) { + VLOG(10) << "Found existing trip counter at index " << i; + trip_counter = i; + } else { + VLOG(10) << "Found induction variable at index " << i; + induction_vars.emplace(i, Cast(constant)); + } + } + + // There's only something to simplify if we can either: + // + // - combine one or more induction vars with an existing trip counter, or + // - replace two or more induction variables with a new trip counter. + // + // Put another way, there's only something to simplify if the number of + // induction vars plus the number of existing trip counters (0 or 1) is >= 2. + if (induction_vars.size() + (trip_counter.has_value() ? 1 : 0) < 2) { + return nullptr; + } + + // OK, we're going to do the transformation! Set up some helpers. + + // `new_instrs` holds instructions created outside of a computation for + // cloning. Elements added here just need to live until the end of the + // relevant CloneWithReplacement call. + std::vector> new_instrs; + auto add_new_instr = [&](std::unique_ptr instr) { + new_instrs.push_back(std::move(instr)); + return new_instrs.back().get(); + }; + + auto add_binary_op = [&](const Shape& shape, HloOpcode opcode, + HloInstruction* lhs, HloInstruction* rhs) { + // Reshape lhs/rhs to the output shape if necessary. This deals with the + // fact that induction variables need only be effective scalars, not true + // scalars. + if (!ShapeUtil::Compatible(shape, lhs->shape())) { + lhs = add_new_instr(HloInstruction::CreateReshape(shape, lhs)); + } + if (!ShapeUtil::Compatible(shape, rhs->shape())) { + rhs = add_new_instr(HloInstruction::CreateReshape(shape, rhs)); + } + return add_new_instr(HloInstruction::CreateBinary(shape, opcode, lhs, rhs)); + }; + + auto add_gte = [&](HloInstruction* src, int64 idx) { + return add_new_instr(HloInstruction::CreateGetTupleElement( + src->shape().tuple_shapes(idx), src, idx)); + }; + + // Our new while loop will have the same shape as the old while loop, except + // we'll add a trip counter to the end if it wasn't originally present. + Shape new_while_shape = while_shape; + bool added_trip_counter = false; + if (!trip_counter) { + VLOG(10) << "Adding new trip counter to end of loop's tuple."; + trip_counter = new_while_shape.tuple_shapes_size(); + *new_while_shape.add_tuple_shapes() = + ShapeUtil::MakeShape(elem_ty, /*dimensions=*/{}); + added_trip_counter = true; + } + + // Converts `instr` into a tuple of the "old" form -- that is, to a tuple with + // shape `while_body->shape()` and where the induction variables are "reified" + // (i.e. they have value + * ). + auto convert_to_old_form = [&](HloInstruction* instr) { + CHECK(ShapeUtil::Compatible(instr->shape(), new_while_shape)); + std::vector tuple_elems; + for (int64 i = 0; i < while_shape.tuple_shapes_size(); ++i) { + const auto& elem_shape = while_shape.tuple_shapes(i); + if (!induction_vars.count(i)) { + tuple_elems.push_back(add_gte(instr, i)); + continue; + } + tuple_elems.push_back(add_binary_op( + elem_shape, HloOpcode::kAdd, add_gte(instr, i), + add_binary_op(elem_shape, HloOpcode::kMultiply, + add_gte(instr, *trip_counter), + add_new_instr(induction_vars.at(i)->Clone())))); + } + return HloInstruction::CreateTuple(tuple_elems); + }; + + // Converts `root` into a tuple of the "new" form -- that is, to a tuple with + // shape `new_while_shape` and where the induction variables (but not trip + // counters) are replaced with their unchanging values. + auto convert_to_new_form = [&](HloInstruction* old_root, + HloParameterInstruction* loop_body_param) { + CHECK(ShapeUtil::Compatible(old_root->shape(), while_shape)); + std::vector tuple_elems; + + // In the new form, induction variables come from `init`, everything else + // (including the trip counter if it's not one we created ourselves) comes + // from the `root` tuple unmodified. + for (int64 i = 0; i < while_shape.tuple_shapes_size(); ++i) { + tuple_elems.push_back( + add_gte((induction_vars.count(i) ? loop_body_param : old_root), i)); + } + // If we created a trip counter ourselves, add 1 to it in the next + // iteration. + if (added_trip_counter) { + tuple_elems.push_back(add_binary_op( + new_while_shape.tuple_shapes(*trip_counter), HloOpcode::kAdd, + add_gte(loop_body_param, *trip_counter), + add_new_instr( + HloInstruction::CreateConstant(LiteralUtil::One(elem_ty))))); + } + + return HloInstruction::CreateTuple(tuple_elems); + }; + + // Creates a new init tuple, which is the same as the old init tuple except if + // we added a trip counter, it's set to 0. + auto get_new_while_init = [&](HloInstruction* init) { + CHECK(ShapeUtil::Compatible(init->shape(), while_shape)); + if (!added_trip_counter) { + return init; + } + std::vector tuple_elems; + for (int64 i = 0; i < while_shape.tuple_shapes_size(); ++i) { + tuple_elems.push_back(add_gte(init, i)); + } + tuple_elems.push_back(add_new_instr( + HloInstruction::CreateConstant(LiteralUtil::Zero(elem_ty)))); + return add_new_instr(HloInstruction::CreateTuple(tuple_elems)); + }; + + std::unique_ptr new_while_cond = + while_cond->CloneWithReplacementPairs({ + while_cond->parameter_instruction(0), + convert_to_old_form(add_new_instr(HloInstruction::CreateParameter( + 0, new_while_shape, + while_cond->parameter_instruction(0)->name()))), + }); + + // Creating the new while body proceeds in two steps. First we convert the + // users of the parameter to the old form. Then as a second + // CloneWithReplacement operation we convert the root to the new form. We + // have to do this in two steps because the new root needs to use the new + // param0, and during the first clone operation, only the *old-form* param0 is + // accessible. + // + // We have to add temp_new_while_body to the module because cloning a + // computation touches the module (to get its NameUniquer). + HloComputation* temp_new_while_body = + module->AddEmbeddedComputation(while_body->CloneWithReplacementPairs({ + while_body->parameter_instruction(0), + convert_to_old_form(add_new_instr(HloInstruction::CreateParameter( + 0, new_while_shape, + while_body->parameter_instruction(0)->name()))), + })); + std::unique_ptr new_while_body = + temp_new_while_body->CloneWithReplacementPairs({ + temp_new_while_body->root_instruction(), + convert_to_new_form( + add_new_instr(temp_new_while_body->root_instruction()->Clone()), + Cast( + temp_new_while_body->parameter_instruction(0))), + }); + TF_RETURN_IF_ERROR(module->RemoveEmbeddedComputation(temp_new_while_body)); + + // Create the final while loop, and add any new instructions created to + // `computation`. + new_instrs.clear(); + auto* new_while = computation->AddInstruction(HloInstruction::CreateWhile( + new_while_shape, + module->AddEmbeddedComputation(std::move(new_while_cond)), + module->AddEmbeddedComputation(std::move(new_while_body)), + get_new_while_init(while_init))); + TF_RETURN_IF_ERROR(computation->ReplaceWithNewInstruction( + while_op, convert_to_old_form(new_while))); + for (auto& instr : new_instrs) { + computation->AddInstruction(std::move(instr)); + } + return new_while; +} + StatusOr WhileLoopSimplifier::Run(HloModule* module) { XLA_VLOG_LINES(3, "WhileLoopSimplifier::Run(), before:\n" + module->ToString()); @@ -650,19 +1022,50 @@ StatusOr WhileLoopSimplifier::Run(HloModule* module) { continue; } + // TODO(b/119281462): Cowardly refuse to perform any of the following + // optimizations in the presence of kDomain instructions. It seems that + // modifying a while loop's tuple doesn't work when kDomain is present. + if (ContainsInstrWithOpcode(while_op->while_body(), {HloOpcode::kDomain}) || + ContainsInstrWithOpcode(while_op->while_condition(), + {HloOpcode::kDomain})) { + continue; + } + + // Each of the optimizations below modifies the while loop itself if it's + // successful, meaning that `while_op` is no longer valid after one of these + // transformations returns true. + TF_ASSIGN_OR_RETURN(result, TryFlattenNestedTuples(while_op)); changed |= result; if (result) { - // Successfully flattening nested tuples results in us cloning and - // replacing the while loop, meaning that `while_op` is no longer valid. continue; } TF_ASSIGN_OR_RETURN(result, TryRemoveDeadWhileParams(while_op)); changed |= result; if (result) { - // Successfully removing dead while params results in us cloning and - // replacing the while loop, meaning that `while_op` is no longer valid. + continue; + } + + TF_ASSIGN_OR_RETURN(result, TryRemoveConstantParams(while_op)); + changed |= result; + if (result) { + continue; + } + + bool merged_induction_vars = false; + // Notably missing from this list are S16 and U16. These don't currently + // work because S/U16 literals are not implemented. + for (auto elem_ty : {S8, U8, S32, U32, S64, U64}) { + TF_ASSIGN_OR_RETURN(auto* new_while_op, + TryMergeInductionVariables(while_op, elem_ty)); + if (new_while_op) { + while_op = new_while_op; + changed = true; + merged_induction_vars = true; + } + } + if (merged_induction_vars) { continue; } } diff --git a/tensorflow/compiler/xla/service/while_loop_simplifier_test.cc b/tensorflow/compiler/xla/service/while_loop_simplifier_test.cc index 05005e0b26..4950e8269e 100644 --- a/tensorflow/compiler/xla/service/while_loop_simplifier_test.cc +++ b/tensorflow/compiler/xla/service/while_loop_simplifier_test.cc @@ -17,9 +17,12 @@ limitations under the License. #include "absl/strings/str_cat.h" #include "absl/strings/str_replace.h" +#include "tensorflow/compiler/xla/service/algebraic_simplifier.h" +#include "tensorflow/compiler/xla/service/hlo_cse.h" #include "tensorflow/compiler/xla/service/hlo_dce.h" #include "tensorflow/compiler/xla/service/hlo_instruction.h" #include "tensorflow/compiler/xla/service/hlo_matchers.h" +#include "tensorflow/compiler/xla/service/tuple_simplifier.h" #include "tensorflow/compiler/xla/test.h" #include "tensorflow/compiler/xla/tests/hlo_test_base.h" #include "tensorflow/core/lib/core/status_test_util.h" @@ -27,8 +30,17 @@ limitations under the License. namespace xla { namespace { +using ::testing::_; namespace op = xla::testing::opcode_matchers; +// Returns the first kWhile instruction within m's entry computation. +HloInstruction* FindFirstWhile(HloModule* m) { + const auto& instrs = m->entry_computation()->instructions(); + return *absl::c_find_if(instrs, [](const HloInstruction* instr) { + return instr->opcode() == HloOpcode::kWhile; + }); +} + class WhileLoopSimplifierTest : public HloTestBase { protected: // Makes an HloModule that contains a loop with `num_iters` iteration. @@ -540,11 +552,7 @@ TEST_F(WhileLoopSimplifierTest, FlattenNestedTuple) { // it easy to find. EXPECT_TRUE(HloDCE().Run(m.get()).ok()); - const auto& instrs = m->entry_computation()->instructions(); - HloInstruction* new_while = - *absl::c_find_if(instrs, [](const HloInstruction* instr) { - return instr->opcode() == HloOpcode::kWhile; - }); + HloInstruction* new_while = FindFirstWhile(m.get()); Shape flat_tuple = ShapeUtil::ParseShapeString("(s32[1], s32[2], s32[3], s32[4])") .ValueOrDie(); @@ -563,5 +571,177 @@ TEST_F(WhileLoopSimplifierTest, FlattenNestedTuple) { .ValueOrDie())); } +// Edge-case: All elements of the loop carry are constants which can be removed, +// leaving us with a nullary loop. This is a special case, we just replace the +// loop with its init. +TEST_F(WhileLoopSimplifierTest, OnlyConstantsInLoopCarry) { + const string hlo_string = R"( + HloModule Test + Body { + param = (s32[1]) parameter(0) + a = s32[1] constant({0}) + ROOT tuple = (s32[1]) tuple(a) + } + Cond { + param = (s32[1]) parameter(0) + ROOT cond = pred[] constant(true) + } + ENTRY Loop { + a = s32[1] constant({0}) + init = (s32[1]) tuple(a) + ROOT while = (s32[1]) while(init), condition=Cond, body=Body + })"; + + auto m = ParseAndReturnVerifiedModule(hlo_string).ValueOrDie(); + EXPECT_TRUE(WhileLoopSimplifier().Run(m.get()).ValueOrDie()); + EXPECT_TRUE(HloDCE().Run(m.get()).ok()); + EXPECT_TRUE(TupleSimplifier().Run(m.get()).ok()); + EXPECT_THAT(m->entry_computation()->root_instruction(), + op::Tuple(op::Constant())); +} + +TEST_F(WhileLoopSimplifierTest, RemoveConstantFromLoopCarry) { + const string hlo_string = R"( + HloModule Test + Body { + param = (s32[1], s32[2], s32[3]) parameter(0) + a = s32[1] get-tuple-element(param), index=0 + a.1 = s32[1] add(a, a) + b = s32[2] constant({1,1}) + c = s32[3] constant({10,10,10}) + ROOT tuple = (s32[1], s32[2], s32[3]) tuple(a.1, b, c) + } + Cond { + param = (s32[1], s32[2], s32[3]) parameter(0) + /* Use each tuple element. The verifier will then ensure that if any of + * these get modified, they're replaced with values of the correct shape. */ + a = s32[1] get-tuple-element(param), index=0 + b = s32[2] get-tuple-element(param), index=1 + c = s32[3] get-tuple-element(param), index=2 + ROOT cond = pred[] constant(true) + } + ENTRY Loop { + /* Only `b` should be simplified away. `a` is not a constant within the + * loop, and `c`'s value changes depending on whether we run 0 or 1 + * iterations of the loop. */ + a = s32[1] constant({0}) + b = s32[2] constant({1,1}) + c = s32[3] constant({2,2,2}) + init = (s32[1], s32[2], s32[3]) tuple(a,b,c) + ROOT while = (s32[1], s32[2], s32[3]) while(init), + condition=Cond, body=Body + })"; + + auto m = ParseAndReturnVerifiedModule(hlo_string).ValueOrDie(); + EXPECT_TRUE(WhileLoopSimplifier().Run(m.get()).ValueOrDie()); + // DCE away the old loop so there's just one while loop in the module, making + // it easy to find. + EXPECT_TRUE(HloDCE().Run(m.get()).ok()); + // Run the tuple simplifier to make the resulting HLO a bit easier to check. + EXPECT_TRUE(TupleSimplifier().Run(m.get()).ok()); + + HloInstruction* new_while = FindFirstWhile(m.get()); + Shape new_while_shape = + ShapeUtil::ParseShapeString("(s32[1], s32[3])").ValueOrDie(); + EXPECT_TRUE(ShapeUtil::Equal(new_while->shape(), new_while_shape)); + EXPECT_TRUE(ShapeUtil::Equal( + new_while->while_body()->root_instruction()->shape(), new_while_shape)); + EXPECT_TRUE(ShapeUtil::Equal( + new_while->while_body()->parameter_instruction(0)->shape(), + new_while_shape)); + EXPECT_TRUE(ShapeUtil::Equal( + new_while->while_condition()->parameter_instruction(0)->shape(), + new_while_shape)); + EXPECT_TRUE(ShapeUtil::Equal( + m->entry_computation()->root_instruction()->shape(), + ShapeUtil::ParseShapeString("(s32[1], s32[2], s32[3])").ValueOrDie())); + EXPECT_THAT(m->entry_computation()->root_instruction(), + op::Tuple(_, op::Constant(), _)); +} + +const char* const kSimpleMergeInductionVariablesModule = R"( + HloModule Test + Body { + param = (TYPE[], TYPE[], TYPE[]) parameter(0) + + a = TYPE[] get-tuple-element(param), index=0 + one = TYPE[] constant(1) + a1 = TYPE[] add(a, one) + + b = TYPE[] get-tuple-element(param), index=1 + negone = TYPE[] constant(-1) + b1 = TYPE[] add(b, negone) + + c = TYPE[] add(a, b) + + ROOT tuple = (TYPE[], TYPE[], TYPE[]) tuple(a1,b1,c) + } + Cond { + param = (TYPE[], TYPE[], TYPE[]) parameter(0) + a = TYPE[] get-tuple-element(param), index=0 + b = TYPE[] get-tuple-element(param), index=1 + sum = TYPE[] power(a, b) + ten = TYPE[] constant(10) + ROOT cond = pred[] less-than(sum, ten) + } + ENTRY Loop { + a = TYPE[] constant(10) + b = TYPE[] constant(100) + c = TYPE[] constant(0) + init = (TYPE[], TYPE[], TYPE[]) tuple(a,b,c) + while = (TYPE[], TYPE[], TYPE[]) while(init), condition=Cond, body=Body + + a1 = TYPE[] get-tuple-element(while), index=0 + b1 = TYPE[] get-tuple-element(while), index=1 + ROOT sum = TYPE[] add(a1, b1) + })"; + +TEST_F(WhileLoopSimplifierTest, MergeInductionVariables_Simple) { + string hlo_string = absl::StrReplaceAll(kSimpleMergeInductionVariablesModule, + {{"TYPE", "s32"}}); + + auto m = ParseAndReturnVerifiedModule(hlo_string).ValueOrDie(); + EXPECT_TRUE(WhileLoopSimplifier().Run(m.get()).ValueOrDie()); + // DCE away the old loop so there's just one while loop in the module, making + // it easy to find, and run the tuple simplifier to make the resulting HLO + // easier to check. + EXPECT_TRUE(HloDCE().Run(m.get()).ok()); + EXPECT_TRUE(TupleSimplifier().Run(m.get()).ok()); + + HloInstruction* new_while = FindFirstWhile(m.get()); + // We should have added a new loop counter for s32[] to the end of the tuple. + SCOPED_TRACE(m->ToString()); + Shape new_while_shape = + ShapeUtil::ParseShapeString("(s32[], s32[], s32[], s32[])").ValueOrDie(); + EXPECT_TRUE(ShapeUtil::Equal(new_while->shape(), new_while_shape)); + EXPECT_TRUE(ShapeUtil::Equal( + new_while->while_body()->root_instruction()->shape(), new_while_shape)); + EXPECT_TRUE(ShapeUtil::Equal( + new_while->while_body()->parameter_instruction(0)->shape(), + new_while_shape)); + EXPECT_TRUE(ShapeUtil::Equal( + new_while->while_condition()->parameter_instruction(0)->shape(), + new_while_shape)); + + EXPECT_THAT(new_while->while_body()->root_instruction(), + op::Tuple(op::GetTupleElement(op::Parameter(), 0), + op::GetTupleElement(op::Parameter(), 1), op::Add(), + op::Add(op::GetTupleElement(op::Parameter(), 3), + op::Constant()))); + EXPECT_THAT(new_while->while_condition()->root_instruction(), + op::Lt(op::Power(op::Add(), op::Add()), op::Constant())); +} + +// We shouldn't merge S16 induction variables; we can't create constants of this +// type because S16 literals are not implemented. +TEST_F(WhileLoopSimplifierTest, MergeInductionVariables_SkipS16) { + string hlo_string = absl::StrReplaceAll(kSimpleMergeInductionVariablesModule, + {{"TYPE", "s16"}}); + EXPECT_FALSE( + WhileLoopSimplifier() + .Run(ParseAndReturnVerifiedModule(hlo_string).ValueOrDie().get()) + .ValueOrDie()); +} + } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/shape.cc b/tensorflow/compiler/xla/shape.cc new file mode 100644 index 0000000000..746ab9e997 --- /dev/null +++ b/tensorflow/compiler/xla/shape.cc @@ -0,0 +1,107 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/shape.h" + +#include "absl/strings/str_cat.h" +#include "absl/strings/str_join.h" +#include "tensorflow/compiler/xla/shape_util.h" + +namespace xla { + +Shape::Shape(const ShapeProto& shape_proto) { + set_element_type(shape_proto.element_type()); + dimensions_.reserve(shape_proto.dimensions_size()); + for (const int64 dimension : shape_proto.dimensions()) { + add_dimensions(dimension); + } + tuple_shapes_.reserve(shape_proto.tuple_shapes_size()); + for (const ShapeProto& element_shape : shape_proto.tuple_shapes()) { + *add_tuple_shapes() = Shape(element_shape); + } + if (shape_proto.has_layout()) { + *mutable_layout() = shape_proto.layout(); + } +} + +ShapeProto Shape::ToProto() const { + ShapeProto proto; + proto.set_element_type(element_type_); + proto.mutable_dimensions()->Reserve(dimensions_size()); + for (const int64 dimension : dimensions()) { + proto.add_dimensions(dimension); + } + proto.mutable_tuple_shapes()->Reserve(tuple_shapes_size()); + for (const Shape& shape : tuple_shapes()) { + *proto.add_tuple_shapes() = shape.ToProto(); + } + if (has_layout()) { + *proto.mutable_layout() = layout(); + } + return proto; +} + +string Shape::ToString(bool print_layout) const { + if (print_layout) { + return ShapeUtil::HumanStringWithLayout(*this); + } else { + return ShapeUtil::HumanString(*this); + } +} + +std::ostream& operator<<(std::ostream& out, const Shape& shape) { + out << shape.ToString(/*print_layout=*/true); + return out; +} + +ProgramShape::ProgramShape(const ProgramShapeProto& program_shape_proto) { + for (const ShapeProto& shape_proto : program_shape_proto.parameters()) { + *add_parameters() = Shape(shape_proto); + } + *mutable_result() = Shape(program_shape_proto.result()); + for (const string& name : program_shape_proto.parameter_names()) { + add_parameter_names(name); + } +} + +ProgramShapeProto ProgramShape::ToProto() const { + ProgramShapeProto proto; + for (const Shape& shape : parameters()) { + *proto.add_parameters() = shape.ToProto(); + } + *proto.mutable_result() = result().ToProto(); + for (const string& name : parameter_names()) { + proto.add_parameter_names(name); + } + return proto; +} + +string ProgramShape::ToString() const { + std::vector parameter_strings(parameters_size()); + for (int i = 0; i < parameters_size(); ++i) { + parameter_strings[i] = absl::StrCat( + i < parameter_names_size() ? parameter_names(i) : "(unknown)", ": ", + ShapeUtil::HumanString(parameters(i))); + } + return absl::StrCat("(", absl::StrJoin(parameter_strings, ", "), ") -> ", + ShapeUtil::HumanString(result())); +} + +std::ostream& operator<<(std::ostream& out, const ProgramShape& program_shape) { + out << program_shape.ToString() << "\n"; + return out; +} + +} // namespace xla diff --git a/tensorflow/compiler/xla/shape.h b/tensorflow/compiler/xla/shape.h new file mode 100644 index 0000000000..7f6b14ab42 --- /dev/null +++ b/tensorflow/compiler/xla/shape.h @@ -0,0 +1,204 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_COMPILER_XLA_SHAPE_H_ +#define TENSORFLOW_COMPILER_XLA_SHAPE_H_ + +#include +#include + +#include "absl/types/optional.h" +#include "tensorflow/compiler/xla/types.h" +#include "tensorflow/compiler/xla/xla_data.pb.h" +#include "tensorflow/core/platform/types.h" + +namespace xla { + +// A shape describes the number of dimensions in a array, the bounds of each +// dimension, and the primitive component type. For tuples, shape describes the +// structure (number of elements and nesting). +class Shape { + public: + Shape() = default; + + // Construct a shape from a ShapeProto. + explicit Shape(const ShapeProto& shape_proto); + + // Returns a ShapeProto representation of the Shape. + ShapeProto ToProto() const; + + // Returns a human-readable string that represents the given shape, with or + // without layout. e.g. "F32[42,12] {0, 1}" or "F32[64]". + string ToString(bool print_layout = false) const; + + // The following methods mirror the protobuf generated code interface for the + // message ShapeProto. This enabled easy migration of this data structure + // from a proto to a proper C++ class. + // TODO(b/29771030): Replace or augment these methods with a more ergonomic + // interface. + + // Methods for accessing the primitive type. + PrimitiveType element_type() const { return element_type_; } + void set_element_type(PrimitiveType value) { element_type_ = value; } + + // Methods for accessing the dimensions array. + int dimensions_size() const { return dimensions_.size(); } + int64 dimensions(int index) const { return dimensions_.at(index); } + void set_dimensions(int index, int64 value) { dimensions_.at(index) = value; } + void add_dimensions(int64 value) { dimensions_.push_back(value); } + void clear_dimensions() { dimensions_.clear(); } + const std::vector& dimensions() const { return dimensions_; } + std::vector* mutable_dimensions() { return &dimensions_; } + + // Methods for accessing the tuple subshapes. This field only non-empty for + // tuple shapes. + int tuple_shapes_size() const { return tuple_shapes_.size(); } + const Shape& tuple_shapes(int index) const { return tuple_shapes_.at(index); } + Shape* mutable_tuple_shapes(int index) { return &tuple_shapes_.at(index); } + Shape* add_tuple_shapes() { + tuple_shapes_.push_back(Shape()); + return &tuple_shapes_.back(); + } + void clear_tuple_shapes() { tuple_shapes_.clear(); } + const std::vector& tuple_shapes() const { return tuple_shapes_; } + std::vector* mutable_tuple_shapes() { return &tuple_shapes_; } + + // Methods for accessing the layout field. + bool has_layout() const { return layout_.has_value(); } + const Layout& layout() const { + if (layout_.has_value()) { + return *layout_; + } else { + return Layout::default_instance(); + } + } + Layout* mutable_layout() { + if (!layout_.has_value()) { + layout_ = Layout(); + } + return &layout_.value(); + } + void clear_layout() { layout_.reset(); } + + void Swap(Shape* other) { + using std::swap; + swap(*this, *other); + } + + void Clear() { + element_type_ = PRIMITIVE_TYPE_INVALID; + dimensions_.clear(); + tuple_shapes_.clear(); + layout_.reset(); + } + + string SerializeAsString() const { return ToProto().SerializeAsString(); } + string ShortDebugString() const { return ToProto().ShortDebugString(); } + string DebugString() const { return ToProto().DebugString(); } + + public: + // The element type of this shape (tuple, array, etc). + PrimitiveType element_type_ = PRIMITIVE_TYPE_INVALID; + + // The array bounds of the dimensions. This is nonempty only for array shapes. + std::vector dimensions_; + + // The tuple element subshapes. This is nonempty only for tuple shapes. + std::vector tuple_shapes_; + + // The array layout of the shape. This is present only for array shapes. + absl::optional layout_; +}; + +// Shape of the parameters and output of an XLA computation. This is analogous +// to a traditional function signature. +class ProgramShape { + public: + ProgramShape() = default; + + // Creates a ProgramShape from a ProgramShapeProto protobuf. + explicit ProgramShape(const ProgramShapeProto& program_shape_proto); + + // Returns a proto representation of the object. + ProgramShapeProto ToProto() const; + + string ToString() const; + + // The following methods mirror the protobuf generated code interface for the + // message ProgramShapeProto. This enabled easy migration of this data + // structure from a proto to a proper C++ class. + // TODO(b/29771030): Replace or augment these methods with a more ergonomic + // interface. + + // Methods for accessing and manipulating the Shape of the parameters. + int parameters_size() const { return parameters_.size(); } + const Shape& parameters(int index) const { return parameters_.at(index); } + Shape* mutable_parameters(int index) { return ¶meters_.at(index); } + Shape* add_parameters() { + parameters_.emplace_back(); + return ¶meters_.back(); + } + void clear_parameters() { parameters_.clear(); } + const std::vector& parameters() const { return parameters_; } + std::vector* mutable_parameters() { return ¶meters_; } + + // Methods for accessing and manipulating the Shape of the result. + const Shape& result() const { return result_; } + Shape* mutable_result() { return &result_; } + + // Methods for accessing and manipulating the names of the parameters. + int parameter_names_size() const { return parameter_names_.size(); } + const string& parameter_names(int index) const { + return parameter_names_.at(index); + } + void set_parameter_names(int index, const string& value) { + parameter_names_.at(index) = value; + } + string* mutable_parameter_names(int index) { + return ¶meter_names_.at(index); + } + void add_parameter_names(const string& value) { + parameter_names_.push_back(value); + } + string* add_parameter_names() { + parameter_names_.push_back(""); + return ¶meter_names_.back(); + } + void clear_parameter_names() { parameter_names_.clear(); } + const std::vector& parameter_names() const { + return parameter_names_; + } + std::vector* mutable_parameter_names() { return ¶meter_names_; } + + string ShortDebugString() const { return ToProto().ShortDebugString(); } + string DebugString() const { return ToProto().DebugString(); } + + private: + // The shapes of the parameters of the computation represented by this object. + std::vector parameters_; + + // The names of the parameters of the computation represented by this object. + std::vector parameter_names_; + + // The shape of the result of the computation represented by this object. + Shape result_; +}; + +std::ostream& operator<<(std::ostream& out, const Shape& shape); +std::ostream& operator<<(std::ostream& out, const ProgramShape& program_shape); + +} // namespace xla + +#endif // TENSORFLOW_COMPILER_XLA_SHAPE_H_ diff --git a/tensorflow/compiler/xla/shape_test.cc b/tensorflow/compiler/xla/shape_test.cc new file mode 100644 index 0000000000..e396897eee --- /dev/null +++ b/tensorflow/compiler/xla/shape_test.cc @@ -0,0 +1,149 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xla/shape.h" + +#include +#include "absl/strings/str_cat.h" +#include "absl/strings/str_join.h" +#include "tensorflow/compiler/xla/layout_util.h" +#include "tensorflow/compiler/xla/shape_util.h" +#include "tensorflow/compiler/xla/status_macros.h" +#include "tensorflow/compiler/xla/test.h" +#include "tensorflow/compiler/xla/test_helpers.h" +#include "tensorflow/compiler/xla/types.h" +#include "tensorflow/compiler/xla/util.h" +#include "tensorflow/compiler/xla/xla_data.pb.h" + +namespace xla { +namespace { + +class ShapeTest : public ::testing::Test { + protected: + const Shape opaque_ = ShapeUtil::MakeOpaqueShape(); + const Shape token_ = ShapeUtil::MakeTokenShape(); + const Shape scalar_ = ShapeUtil::MakeShape(F32, {}); + const Shape matrix_ = ShapeUtil::MakeShape(U32, {1, 2}); + const Shape matrix2_ = ShapeUtil::MakeShapeWithLayout(S32, {3, 4}, {0, 1}); + const Shape tuple_ = + ShapeUtil::MakeTupleShape({opaque_, scalar_, matrix_, matrix2_}); + const Shape nested_tuple_ = + ShapeUtil::MakeTupleShape({tuple_, matrix_, token_}); +}; + +TEST_F(ShapeTest, ShapeToFromProto) { + for (const Shape& shape : + {opaque_, token_, scalar_, matrix_, matrix2_, tuple_, nested_tuple_}) { + Shape shape_copy(shape.ToProto()); + EXPECT_TRUE(ShapeUtil::Equal(shape, shape_copy)) + << shape << " != " << shape_copy; + } +} + +TEST_F(ShapeTest, ShapeToString) { + EXPECT_EQ("opaque[]", opaque_.ToString()); + EXPECT_EQ("token[]", token_.ToString()); + EXPECT_EQ("f32[]", scalar_.ToString()); + EXPECT_EQ("u32[1,2]", matrix_.ToString()); + EXPECT_EQ("s32[3,4]", matrix2_.ToString()); + EXPECT_EQ("(opaque[], f32[], u32[1,2], s32[3,4])", tuple_.ToString()); + EXPECT_EQ("((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], token[])", + nested_tuple_.ToString()); + + EXPECT_EQ("opaque[]", opaque_.ToString(/*print_layout=*/true)); + EXPECT_EQ("f32[]", scalar_.ToString(/*print_layout=*/true)); + EXPECT_EQ("u32[1,2]{1,0}", matrix_.ToString(/*print_layout=*/true)); + EXPECT_EQ("s32[3,4]{0,1}", matrix2_.ToString(/*print_layout=*/true)); + EXPECT_EQ("(opaque[], f32[], u32[1,2]{1,0}, s32[3,4]{0,1})", + tuple_.ToString(/*print_layout=*/true)); + EXPECT_EQ( + "((opaque[], f32[], u32[1,2]{1,0}, s32[3,4]{0,1}), u32[1,2]{1,0}, " + "token[])", + nested_tuple_.ToString(/*print_layout=*/true)); +} + +TEST_F(ShapeTest, ProgramShapeToFromProto) { + ProgramShape program_shape; + *program_shape.add_parameters() = ShapeUtil::MakeShape(F32, {1, 2, 3}); + *program_shape.add_parameters() = ShapeUtil::MakeTokenShape(); + *program_shape.add_parameters() = ShapeUtil::MakeShape(S64, {}); + *program_shape.add_parameters() = ShapeUtil::MakeTupleShape( + {ShapeUtil::MakeShape(S32, {}), + ShapeUtil::MakeTupleShape({ShapeUtil::MakeTokenShape()}), + ShapeUtil::MakeShape(F32, {42, 42})}); + + *program_shape.mutable_result() = ShapeUtil::MakeShape(F32, {7}); + + program_shape.add_parameter_names("foo"); + program_shape.add_parameter_names("bar"); + program_shape.add_parameter_names("baz"); + program_shape.add_parameter_names("qux qux"); + + // Create a copy of the program shape by round-tripping through a proto. + ProgramShape program_shape_copy(program_shape.ToProto()); + ASSERT_EQ(program_shape.parameters_size(), + program_shape_copy.parameters_size()); + for (int i = 0; i < program_shape.parameters_size(); ++i) { + EXPECT_TRUE(ShapeUtil::Equal(program_shape.parameters(i), + program_shape_copy.parameters(i))); + } + + EXPECT_TRUE( + ShapeUtil::Equal(program_shape.result(), program_shape_copy.result())); + + ASSERT_EQ(program_shape.parameter_names_size(), + program_shape_copy.parameter_names_size()); + for (int i = 0; i < program_shape.parameter_names_size(); ++i) { + EXPECT_EQ(program_shape.parameter_names(i), + program_shape_copy.parameter_names(i)); + } +} + +TEST_F(ShapeTest, ProgramShapeToString) { + ProgramShape prog = ShapeUtil::MakeProgramShape( + {opaque_, scalar_, matrix_, matrix2_, tuple_, nested_tuple_}, + nested_tuple_); + EXPECT_EQ( + "((unknown): opaque[], " + "(unknown): f32[], " + "(unknown): u32[1,2], " + "(unknown): s32[3,4], " + "(unknown): (opaque[], f32[], u32[1,2], s32[3,4]), " + "(unknown): ((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], token[])) " + "-> " + "((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], token[])", + prog.ToString()); + + prog.add_parameter_names("arg0"); + prog.add_parameter_names("scalar"); + prog.add_parameter_names("matrix"); + prog.add_parameter_names("matrix2"); + prog.add_parameter_names("tuple"); + prog.add_parameter_names("nested_tuple"); + EXPECT_EQ( + "(arg0: opaque[], " + "scalar: f32[], " + "matrix: u32[1,2], " + "matrix2: s32[3,4], " + "tuple: (opaque[], f32[], u32[1,2], s32[3,4]), " + "nested_tuple: ((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], " + "token[])) " + "-> " + "((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], token[])", + prog.ToString()); +} + +} // namespace +} // namespace xla diff --git a/tensorflow/compiler/xla/shape_tree.h b/tensorflow/compiler/xla/shape_tree.h index df610102b4..7bf9772916 100644 --- a/tensorflow/compiler/xla/shape_tree.h +++ b/tensorflow/compiler/xla/shape_tree.h @@ -667,12 +667,11 @@ void ShapeTree::CopySubtreeFrom(const ShapeTree& other, template bool ShapeTree::operator==(const ShapeTree& other) const { bool equal = true; - ForEachElement( - [this, &other, &equal](const ShapeIndex& index, const T& data) { - if (data != other.element(index)) { - equal = false; - } - }); + ForEachElement([&other, &equal](const ShapeIndex& index, const T& data) { + if (data != other.element(index)) { + equal = false; + } + }); return equal; } diff --git a/tensorflow/compiler/xla/shape_tree_test.cc b/tensorflow/compiler/xla/shape_tree_test.cc index c8ff55e784..2b6c484bc4 100644 --- a/tensorflow/compiler/xla/shape_tree_test.cc +++ b/tensorflow/compiler/xla/shape_tree_test.cc @@ -52,10 +52,10 @@ class ShapeTreeTest : public ::testing::Test { TEST_F(ShapeTreeTest, DefaultConstructor) { ShapeTree int_tree; - EXPECT_TRUE(ShapeUtil::IsNil(int_tree.shape())); + EXPECT_TRUE(ShapeUtil::IsEmptyTuple(int_tree.shape())); ShapeTree bool_tree; - EXPECT_TRUE(ShapeUtil::IsNil(bool_tree.shape())); + EXPECT_TRUE(ShapeUtil::IsEmptyTuple(bool_tree.shape())); } void ShapeTreeTest::TestShapeConstructor(const Shape& shape, diff --git a/tensorflow/compiler/xla/shape_util.cc b/tensorflow/compiler/xla/shape_util.cc index d0c35d8dee..f3cc51ca91 100644 --- a/tensorflow/compiler/xla/shape_util.cc +++ b/tensorflow/compiler/xla/shape_util.cc @@ -79,14 +79,14 @@ bool ShapeIndexView::StartsWith(ShapeIndexView prefix) const { indices_.subspan(0, prefix.size()) == prefix.indices_; } -namespace { - -// Returns whether the given primitive type corresponds to an array shape. -bool IsArrayPrimitiveType(PrimitiveType primitive_type) { +/* static */ bool ShapeUtil::IsArrayPrimitiveType( + PrimitiveType primitive_type) { return primitive_type != PRIMITIVE_TYPE_INVALID && primitive_type != TUPLE && primitive_type != OPAQUE && primitive_type != TOKEN; } +namespace { + // Recursive helper for comparing the equality of two shapes. Returns true if // the shapes are the same. If compare_layouts is true, then layouts must also // match. @@ -121,6 +121,23 @@ bool CompareShapes(const Shape& lhs, const Shape& rhs, bool compare_layouts, VLOG(3) << "CompareShapes: lhs layout != rhs layout"; return false; } + + const auto& lhs_tiles = lhs.layout().tiles(); + const auto& rhs_tiles = rhs.layout().tiles(); + if (lhs_tiles.size() != rhs_tiles.size()) { + return false; + } + for (int64 i = 0; i < lhs_tiles.size(); i++) { + if (!absl::c_equal(lhs_tiles[i].dimensions(), + rhs_tiles[i].dimensions())) { + return false; + } + } + + if (lhs.layout().element_size_in_bits() != + rhs.layout().element_size_in_bits()) { + return false; + } } } @@ -203,7 +220,7 @@ StatusOr MakeShapeWithLayoutInternal( /* static */ ProgramShape ShapeUtil::MakeProgramShape( std::initializer_list parameters, Shape result) { ProgramShape program_shape; - for (const auto& shape : parameters) { + for (const Shape& shape : parameters) { *program_shape.add_parameters() = shape; } *program_shape.mutable_result() = std::move(result); @@ -272,7 +289,7 @@ ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout( /* static */ Shape ShapeUtil::MakeTupleShape(absl::Span shapes) { Shape result; result.set_element_type(TUPLE); - result.mutable_tuple_shapes()->Reserve(shapes.size()); + result.mutable_tuple_shapes()->reserve(shapes.size()); for (const auto& shape : shapes) { AppendShapeToTuple(shape, &result); } @@ -372,10 +389,6 @@ ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout( return IsTuple(shape) && TupleElementCount(shape) == 0; } -/* static */ bool ShapeUtil::IsNil(const Shape& shape) { - return IsEmptyTuple(shape); -} - /* static */ int64 ShapeUtil::TupleElementCount(const Shape& shape) { CHECK(IsTuple(shape)) << HumanString(shape); return shape.tuple_shapes_size(); @@ -1155,7 +1168,7 @@ Status ForEachMutableSubshapeHelper( // Let the argument `permutation` be P. This is a permutation over `shape`'s // dimensions, so our return value will be a shape with dims P.I = P. Our // goal is to construct a layout permutation L* that we can apply to P such - // that that the physical dimension ordering of the returned shape is the same + // that the physical dimension ordering of the returned shape is the same // as that of the original shape, namely L'. // // Our returned shape has dims P and layout L*, so its in-memory layout is @@ -1600,7 +1613,8 @@ ShapeUtil::DimensionsUnmodifiedByReshape(const Shape& input_shape, /* static */ Shape ShapeUtil::DeleteDimension(int64 dim_to_delete, Shape shape) { CHECK(IsArray(shape)); - shape.mutable_dimensions()->erase(shape.dimensions().begin() + dim_to_delete); + shape.mutable_dimensions()->erase(shape.mutable_dimensions()->begin() + + dim_to_delete); if (LayoutUtil::HasLayout(shape)) { Layout* layout = shape.mutable_layout(); layout->set_format(DENSE); @@ -1634,11 +1648,6 @@ ShapeUtil::DimensionsUnmodifiedByReshape(const Shape& input_shape, return shape; } -std::ostream& operator<<(std::ostream& out, const Shape& shape) { - out << ShapeUtil::HumanStringWithLayout(shape); - return out; -} - /*static*/ size_t ShapeUtil::Hash(const Shape& shape) { using tensorflow::hash; using tensorflow::Hash64Combine; diff --git a/tensorflow/compiler/xla/shape_util.h b/tensorflow/compiler/xla/shape_util.h index a7a3026cf3..84a27f662a 100644 --- a/tensorflow/compiler/xla/shape_util.h +++ b/tensorflow/compiler/xla/shape_util.h @@ -28,6 +28,7 @@ limitations under the License. #include "absl/types/span.h" #include "tensorflow/compiler/xla/layout_util.h" #include "tensorflow/compiler/xla/primitive_util.h" +#include "tensorflow/compiler/xla/shape.h" #include "tensorflow/compiler/xla/status_macros.h" #include "tensorflow/compiler/xla/statusor.h" #include "tensorflow/compiler/xla/types.h" @@ -37,6 +38,7 @@ limitations under the License. #include "tensorflow/core/platform/cpu_info.h" #include "tensorflow/core/platform/env.h" #include "tensorflow/core/platform/macros.h" +#include "tensorflow/core/platform/mutex.h" #include "tensorflow/core/platform/types.h" namespace xla { @@ -100,6 +102,11 @@ class ShapeIndex { string ToString() const; + template + friend H AbslHashValue(H h, const ShapeIndex& index) { + return H::combine(std::move(h), index.indices_); + } + private: container_type indices_; }; @@ -461,6 +468,9 @@ class ShapeUtil { // arrays. static bool IsArray(const Shape& shape); + // Returns whether the given primitive type corresponds to an array shape. + static bool IsArrayPrimitiveType(PrimitiveType primitive_type); + // Returns whether the shape is a tuple with at least one element which is // also a tuple. static bool IsNestedTuple(const Shape& shape); @@ -468,9 +478,6 @@ class ShapeUtil { // Returns true if shape is an empty tuple. static bool IsEmptyTuple(const Shape& shape); - // Returns true if shape is the nil shape (an empty tuple). - static bool IsNil(const Shape& shape); - // Returns the number of elements in the given tuple shape. // Precondition: IsTuple(shape) static int64 TupleElementCount(const Shape& shape); @@ -754,10 +761,18 @@ class ShapeUtil { pool.emplace(tensorflow::Env::Default(), "foreach", kNumThreads); } + tensorflow::mutex mu; + Status status; // Guarded by mu + while (n < rank) { if (pool != absl::nullopt) { - pool->Schedule( - [indexes, &visitor_function] { visitor_function(indexes); }); + pool->Schedule([indexes, &visitor_function, &mu, &status] { + StatusOr result = visitor_function(indexes); + if (!result.ok()) { + tensorflow::mutex_lock lock(mu); + status = status.ok() ? result.status() : status; + } + }); } else { TF_ASSIGN_OR_RETURN(bool should_continue, visitor_function(indexes)); if (!should_continue) { @@ -775,14 +790,14 @@ class ShapeUtil { } } - return Status::OK(); + // Waits for the scheduled work to complete. + pool.reset(); + return status; } TF_DISALLOW_COPY_AND_ASSIGN(ShapeUtil); }; -std::ostream& operator<<(std::ostream& out, const Shape& shape); - } // namespace xla #endif // TENSORFLOW_COMPILER_XLA_SHAPE_UTIL_H_ diff --git a/tensorflow/compiler/xla/shape_util_test.cc b/tensorflow/compiler/xla/shape_util_test.cc index 0c647369a3..60bdbe3020 100644 --- a/tensorflow/compiler/xla/shape_util_test.cc +++ b/tensorflow/compiler/xla/shape_util_test.cc @@ -376,12 +376,12 @@ TEST(ShapeUtilTest, ByteSizeOfWithoutPadding) { } TEST(ShapeUtilTest, NilShape) { - EXPECT_TRUE(ShapeUtil::IsNil(ShapeUtil::MakeNil())); - EXPECT_FALSE(ShapeUtil::IsNil(ShapeUtil::MakeShape(F32, {1, 2, 3}))); - EXPECT_FALSE(ShapeUtil::IsNil(ShapeUtil::MakeShape(F32, {0, 1}))); - EXPECT_FALSE(ShapeUtil::IsNil( + EXPECT_TRUE(ShapeUtil::IsEmptyTuple(ShapeUtil::MakeNil())); + EXPECT_FALSE(ShapeUtil::IsEmptyTuple(ShapeUtil::MakeShape(F32, {1, 2, 3}))); + EXPECT_FALSE(ShapeUtil::IsEmptyTuple(ShapeUtil::MakeShape(F32, {0, 1}))); + EXPECT_FALSE(ShapeUtil::IsEmptyTuple( ShapeUtil::MakeTupleShape({ShapeUtil::MakeShape(S32, {})}))); - EXPECT_FALSE(ShapeUtil::IsNil( + EXPECT_FALSE(ShapeUtil::IsEmptyTuple( ShapeUtil::MakeTupleShape({ShapeUtil::MakeShape(F32, {0})}))); } @@ -546,68 +546,6 @@ TEST(ShapeUtilTest, IsLeafIndex) { EXPECT_TRUE(ShapeUtil::IsLeafIndex(nested_tuple_shape, {1, 1})); } -TEST(ShapeUtilTest, HumanString) { - Shape opaque = ShapeUtil::MakeOpaqueShape(); - Shape token = ShapeUtil::MakeTokenShape(); - Shape scalar = ShapeUtil::MakeShape(F32, {}); - Shape matrix = ShapeUtil::MakeShape(U32, {1, 2}); - Shape matrix2 = ShapeUtil::MakeShapeWithLayout(S32, {3, 4}, {0, 1}); - Shape tuple = ShapeUtil::MakeTupleShape({opaque, scalar, matrix, matrix2}); - Shape nested_tuple = ShapeUtil::MakeTupleShape({tuple, matrix, token}); - - EXPECT_EQ("opaque[]", ShapeUtil::HumanString(opaque)); - EXPECT_EQ("token[]", ShapeUtil::HumanString(token)); - EXPECT_EQ("f32[]", ShapeUtil::HumanString(scalar)); - EXPECT_EQ("u32[1,2]", ShapeUtil::HumanString(matrix)); - EXPECT_EQ("s32[3,4]", ShapeUtil::HumanString(matrix2)); - EXPECT_EQ("(opaque[], f32[], u32[1,2], s32[3,4])", - ShapeUtil::HumanString(tuple)); - EXPECT_EQ("((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], token[])", - ShapeUtil::HumanString(nested_tuple)); - - EXPECT_EQ("opaque[]", ShapeUtil::HumanStringWithLayout(opaque)); - EXPECT_EQ("f32[]", ShapeUtil::HumanStringWithLayout(scalar)); - EXPECT_EQ("u32[1,2]{1,0}", ShapeUtil::HumanStringWithLayout(matrix)); - EXPECT_EQ("s32[3,4]{0,1}", ShapeUtil::HumanStringWithLayout(matrix2)); - EXPECT_EQ("(opaque[], f32[], u32[1,2]{1,0}, s32[3,4]{0,1})", - ShapeUtil::HumanStringWithLayout(tuple)); - EXPECT_EQ( - "((opaque[], f32[], u32[1,2]{1,0}, s32[3,4]{0,1}), u32[1,2]{1,0}, " - "token[])", - ShapeUtil::HumanStringWithLayout(nested_tuple)); - - ProgramShape prog = ShapeUtil::MakeProgramShape( - {opaque, scalar, matrix, matrix2, tuple, nested_tuple}, nested_tuple); - EXPECT_EQ( - "((unknown): opaque[], " - "(unknown): f32[], " - "(unknown): u32[1,2], " - "(unknown): s32[3,4], " - "(unknown): (opaque[], f32[], u32[1,2], s32[3,4]), " - "(unknown): ((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], token[])) " - "-> " - "((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], token[])", - ShapeUtil::HumanString(prog)); - - prog.add_parameter_names("arg0"); - prog.add_parameter_names("scalar"); - prog.add_parameter_names("matrix"); - prog.add_parameter_names("matrix2"); - prog.add_parameter_names("tuple"); - prog.add_parameter_names("nested_tuple"); - EXPECT_EQ( - "(arg0: opaque[], " - "scalar: f32[], " - "matrix: u32[1,2], " - "matrix2: s32[3,4], " - "tuple: (opaque[], f32[], u32[1,2], s32[3,4]), " - "nested_tuple: ((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], " - "token[])) " - "-> " - "((opaque[], f32[], u32[1,2], s32[3,4]), u32[1,2], token[])", - ShapeUtil::HumanString(prog)); -} - TEST(ShapeUtilTest, ForEachSubshapeArray) { const Shape shape = ShapeUtil::MakeShape(F32, {2, 3}); int calls = 0; diff --git a/tensorflow/compiler/xla/tests/BUILD b/tensorflow/compiler/xla/tests/BUILD index db34d34f96..f7f090fe4a 100644 --- a/tensorflow/compiler/xla/tests/BUILD +++ b/tensorflow/compiler/xla/tests/BUILD @@ -79,6 +79,7 @@ cc_library( "//tensorflow/compiler/xla/service:hlo_verifier", "//tensorflow/compiler/xla/service:transfer_manager", "//tensorflow/core:lib", + "@com_google_absl//absl/base", "@com_google_absl//absl/memory", "@com_google_absl//absl/types:span", ], @@ -135,6 +136,7 @@ cc_library( "//tensorflow/core:stream_executor_no_cuda", "//tensorflow/core:test", "@com_google_absl//absl/algorithm:container", + "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/memory", "@com_google_absl//absl/types:optional", "@com_google_absl//absl/types:span", @@ -297,6 +299,56 @@ xla_test( ], ) +xla_test( + name = "conv_depthwise_test", + timeout = "long", + srcs = ["conv_depthwise_test.cc"], + blacklisted_backends = [ + # disabled because of a break b/119590850. + "gpu", + ], + shard_count = 50, + deps = [ + "//tensorflow/compiler/xla:execution_options_util", + "//tensorflow/compiler/xla:status_macros", + "//tensorflow/compiler/xla:test", + "//tensorflow/compiler/xla/client:xla_computation", + "//tensorflow/compiler/xla/service:bfloat16_normalization", + "//tensorflow/compiler/xla/service:despecializer", + "//tensorflow/compiler/xla/service:hlo_parser", + "//tensorflow/compiler/xla/tests:client_library_test_base", + "//tensorflow/compiler/xla/tests:hlo_test_base", + "//tensorflow/compiler/xla/tests:xla_internal_test_main", + "@com_google_absl//absl/types:optional", + ], +) + +xla_test( + name = "grouped_convolution_test", + timeout = "long", + srcs = ["grouped_convolution_test.cc"], + blacklisted_backends = [ + # disabled because of a break b/119590850. + "gpu", + # disabled because it times out. + "cpu", + ], + shard_count = 50, + deps = [ + "//tensorflow/compiler/xla:execution_options_util", + "//tensorflow/compiler/xla:status_macros", + "//tensorflow/compiler/xla:test", + "//tensorflow/compiler/xla/client:xla_computation", + "//tensorflow/compiler/xla/service:bfloat16_normalization", + "//tensorflow/compiler/xla/service:despecializer", + "//tensorflow/compiler/xla/service:hlo_parser", + "//tensorflow/compiler/xla/tests:client_library_test_base", + "//tensorflow/compiler/xla/tests:hlo_test_base", + "//tensorflow/compiler/xla/tests:xla_internal_test_main", + "@com_google_absl//absl/types:optional", + ], +) + xla_test( name = "check_execution_arity_test", srcs = ["check_execution_arity_test.cc"], @@ -1265,6 +1317,7 @@ xla_test( "enable_for_xla_interpreter", ], deps = [ + "//tensorflow/compiler/xla/service:hlo_parser", "//tensorflow/compiler/xla/service:hlo_verifier", "//tensorflow/compiler/xla/tests:hlo_test_base", "//tensorflow/compiler/xla/tests:xla_internal_test_main", @@ -1865,6 +1918,7 @@ xla_test( xla_test( name = "multioutput_fusion_test", srcs = ["multioutput_fusion_test.cc"], + backends = ["gpu"], deps = [ "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:shape_util", diff --git a/tensorflow/compiler/xla/tests/array_elementwise_ops_test.cc b/tensorflow/compiler/xla/tests/array_elementwise_ops_test.cc index 2180b22cb3..f6be27bee2 100644 --- a/tensorflow/compiler/xla/tests/array_elementwise_ops_test.cc +++ b/tensorflow/compiler/xla/tests/array_elementwise_ops_test.cc @@ -350,6 +350,44 @@ TEST_P(ArrayElementwiseOpTestParamCount, AddManyValues) { error_spec_); } +// TODO(b/119692968): This test runs OOM on the GPU and CPU backend. +XLA_TEST_F(ArrayElementwiseOpTest, + DISABLED_ON_GPU(DISABLED_ON_CPU(DeeplyNestedAddWithSlices))) { + XlaBuilder builder(TestName()); + std::vector values(30, 0.0); + auto a_literal = LiteralUtil::CreateR1(values); + auto a = Parameter(&builder, 0, a_literal.shape(), "x"); + auto b_literal = LiteralUtil::CreateR1(values); + auto b = Parameter(&builder, 1, b_literal.shape(), "x"); + + // Construct a sequence of diamond-shaped gadgets like this: + // + // add + // / \ + // slice slice + // \ / + // add + // + // Each 'left' slice removes the last element, each 'right' slice removes the + // first element. In this way, we index into the add with different + // multi-dimensional index arrays, which defeats the caching we use to avoid + // exponential compile time. + std::function generate_recursive = + [&](int64 slice_size) -> XlaOp { + if (slice_size == values.size()) { + return Add(a, b); + } + XlaOp param = generate_recursive(slice_size + 1); + auto slice1 = Slice(param, {0}, {slice_size}, {1}); + auto slice2 = Slice(param, {1}, {slice_size + 1}, {1}); + return Add(slice1, slice2); + }; + generate_recursive(1); + auto a_data = client_->TransferToServer(a_literal).ConsumeValueOrDie(); + auto b_data = client_->TransferToServer(b_literal).ConsumeValueOrDie(); + ComputeAndCompareR1(&builder, {0.0}, {a_data.get(), b_data.get()}); +} + XLA_TEST_F(ArrayElementwiseOpTest, SubTwoConstantF32s) { XlaBuilder builder(TestName()); auto a = ConstantR1(&builder, {-2.5f, 3.14f, 2.25f, -10.0f, 6.0f}); @@ -2744,12 +2782,16 @@ XLA_TEST_F(ArrayElementwiseOpTest, CompareGtR3F32sWithDegenerateDim2) { Array3D expected_3d( {{{0, 1}, {0, 0}, {0, 0}}, {{0, 1}, {1, 0}, {0, 1}}}); const string expected = R"(pred[2,3,2] { -{ { 0, 1 }, +{ + { 0, 1 }, { 0, 0 }, - { 0, 0 } }, -{ { 0, 1 }, + { 0, 0 } +}, +{ + { 0, 1 }, { 1, 0 }, - { 0, 1 } } + { 0, 1 } +} })"; EXPECT_EQ(expected, ExecuteToString(&builder, {})); } diff --git a/tensorflow/compiler/xla/tests/broadcast_simple_test.cc b/tensorflow/compiler/xla/tests/broadcast_simple_test.cc index dde19fb65d..702fb32adf 100644 --- a/tensorflow/compiler/xla/tests/broadcast_simple_test.cc +++ b/tensorflow/compiler/xla/tests/broadcast_simple_test.cc @@ -161,8 +161,7 @@ XLA_TEST_F(BroadcastSimpleTest, 1DTo2D) { XLA_TEST_F(BroadcastSimpleTest, 1DTo2D_WithDimsUsual) { XlaBuilder b(TestName()); - BroadcastInDim(ConstantR1(&b, {1, 2}), - ShapeUtil::MakeShape(F32, {2, 2}), {1}); + BroadcastInDim(ConstantR1(&b, {1, 2}), {2, 2}, {1}); Array2D expected(2, 2); expected(0, 0) = 1; @@ -175,8 +174,7 @@ XLA_TEST_F(BroadcastSimpleTest, 1DTo2D_WithDimsUsual) { XLA_TEST_F(BroadcastSimpleTest, 1DTo2D_WithDimsTranspose) { XlaBuilder b(TestName()); - BroadcastInDim(ConstantR1(&b, {1, 2}), - ShapeUtil::MakeShape(F32, {2, 2}), {0}); + BroadcastInDim(ConstantR1(&b, {1, 2}), {2, 2}, {0}); Array2D expected(2, 2); expected(0, 0) = 1; @@ -189,8 +187,8 @@ XLA_TEST_F(BroadcastSimpleTest, 1DTo2D_WithDimsTranspose) { XLA_TEST_F(BroadcastSimpleTest, 2DTo3D_WithDims) { XlaBuilder b(TestName()); - BroadcastInDim(ConstantR2(&b, {{1.0, 5.0}, {2.0, 6.0}}), - ShapeUtil::MakeShape(F32, {2, 2, 2}), {0, 1}); + BroadcastInDim(ConstantR2(&b, {{1.0, 5.0}, {2.0, 6.0}}), {2, 2, 2}, + {0, 1}); Array3D expected(2, 2, 2); expected(0, 0, 0) = 1.0; @@ -207,8 +205,8 @@ XLA_TEST_F(BroadcastSimpleTest, 2DTo3D_WithDims) { XLA_TEST_F(BroadcastSimpleTest, 2DTo3D_WithDimsNotPossibleWithBroadCast) { XlaBuilder b(TestName()); - BroadcastInDim(ConstantR2(&b, {{1.0, 5.0}, {2.0, 6.0}}), - ShapeUtil::MakeShape(F32, {2, 2, 2}), {0, 2}); + BroadcastInDim(ConstantR2(&b, {{1.0, 5.0}, {2.0, 6.0}}), {2, 2, 2}, + {0, 2}); Array3D expected(2, 2, 2); expected(0, 0, 0) = 1.0; @@ -225,8 +223,7 @@ XLA_TEST_F(BroadcastSimpleTest, 2DTo3D_WithDimsNotPossibleWithBroadCast) { XLA_TEST_F(BroadcastSimpleTest, 1DTo2D_WithDimsNotPossibleWithBroadCast) { XlaBuilder b(TestName()); - BroadcastInDim(ConstantR1(&b, {1, 2}), - ShapeUtil::MakeShape(F32, {3, 2}), {1}); + BroadcastInDim(ConstantR1(&b, {1, 2}), {3, 2}, {1}); Array2D expected(3, 2); expected(0, 0) = 1; diff --git a/tensorflow/compiler/xla/tests/client_library_test_base.cc b/tensorflow/compiler/xla/tests/client_library_test_base.cc index b98572e24c..12c0299833 100644 --- a/tensorflow/compiler/xla/tests/client_library_test_base.cc +++ b/tensorflow/compiler/xla/tests/client_library_test_base.cc @@ -107,7 +107,7 @@ StatusOr ClientLibraryTestBase::ExecuteAndTransfer( ExecutionOptions execution_options = execution_options_; if (shape_with_output_layout != nullptr) { *execution_options.mutable_shape_with_output_layout() = - *shape_with_output_layout; + shape_with_output_layout->ToProto(); } return client_->ExecuteAndTransfer(computation, arguments, &execution_options); @@ -127,7 +127,7 @@ StatusOr ClientLibraryTestBase::ExecuteAndTransferReference( ExecutionOptions execution_options = execution_options_; if (shape_with_output_layout != nullptr) { *execution_options.mutable_shape_with_output_layout() = - *shape_with_output_layout; + shape_with_output_layout->ToProto(); } execution_options.clear_device_handles(); return ref_client_->ExecuteAndTransfer(computation, arguments, diff --git a/tensorflow/compiler/xla/tests/client_library_test_base.h b/tensorflow/compiler/xla/tests/client_library_test_base.h index 34148e5886..65a23dd883 100644 --- a/tensorflow/compiler/xla/tests/client_library_test_base.h +++ b/tensorflow/compiler/xla/tests/client_library_test_base.h @@ -76,7 +76,7 @@ class ClientLibraryTestBase : public ::testing::Test { void SetFastMathDisabled(bool disabled) { auto* opts = execution_options_.mutable_debug_options(); opts->set_xla_cpu_enable_fast_math(!disabled); - opts->set_xla_gpu_enable_fast_math(!disabled); + opts->set_xla_gpu_enable_fast_min_max(!disabled); } void SetSeed(uint64 seed) { execution_options_.set_seed(seed); } diff --git a/tensorflow/compiler/xla/tests/client_test.cc b/tensorflow/compiler/xla/tests/client_test.cc index 6f2ca84bb6..363dee74b2 100644 --- a/tensorflow/compiler/xla/tests/client_test.cc +++ b/tensorflow/compiler/xla/tests/client_test.cc @@ -50,7 +50,8 @@ XLA_TEST_F(ClientTest, ExecuteWithLayout) { ExecutionOptions execution_options = execution_options_; *execution_options.mutable_shape_with_output_layout() = ShapeUtil::MakeShapeWithLayout(S32, /*dimensions=*/{2, 2}, - execute_layout); + execute_layout) + .ToProto(); TF_ASSERT_OK_AND_ASSIGN( std::unique_ptr data, client_->Execute(computation, {}, &execution_options)); @@ -84,7 +85,8 @@ XLA_TEST_F(ClientTest, ExecuteWithTupleLayout) { {ShapeUtil::MakeShapeWithLayout(S32, /*dimensions=*/{2, 2}, /*minor_to_major=*/{0, 1}), ShapeUtil::MakeShapeWithLayout(S32, /*dimensions=*/{2, 2}, - /*minor_to_major=*/{1, 0})}); + /*minor_to_major=*/{1, 0})}) + .ToProto(); TF_ASSERT_OK_AND_ASSIGN( auto result, diff --git a/tensorflow/compiler/xla/tests/concat_test.cc b/tensorflow/compiler/xla/tests/concat_test.cc index 9811a015e9..4f5b525a34 100644 --- a/tensorflow/compiler/xla/tests/concat_test.cc +++ b/tensorflow/compiler/xla/tests/concat_test.cc @@ -492,6 +492,32 @@ XLA_TEST_F(ConcatTest, ConcatR3WeirdDims) { ComputeAndCompareR3(&builder, expected, {p0.get(), p1.get()}); } +XLA_TEST_F(ConcatTest, ConcatDeeplyNested) { + XlaBuilder builder(TestName()); + auto a_literal = LiteralUtil::CreateR1({256.0}); + auto a = Parameter(&builder, 0, a_literal.shape(), "x"); + auto b = ConcatInDim(&builder, {a, a}, 0); + auto c = ConcatInDim(&builder, {b, b}, 0); + auto d = ConcatInDim(&builder, {c, c}, 0); + auto e = ConcatInDim(&builder, {d, d}, 0); + auto f = ConcatInDim(&builder, {e, e}, 0); + auto g = ConcatInDim(&builder, {f, f}, 0); + auto h = ConcatInDim(&builder, {g, g}, 0); + auto i = ConcatInDim(&builder, {h, h}, 0); + auto j = ConcatInDim(&builder, {i, i}, 0); + auto k = ConcatInDim(&builder, {j, j}, 0); + auto l = ConcatInDim(&builder, {k, k}, 0); + auto m = ConcatInDim(&builder, {l, l}, 0); + auto n = ConcatInDim(&builder, {m, m}, 0); + auto o = ConcatInDim(&builder, {n, n}, 0); + auto p = ConcatInDim(&builder, {o, o}, 0); + auto q = ConcatInDim(&builder, {p, p}, 0); + ConcatInDim(&builder, {q, q}, 0); + std::vector expected(131072, 256.0); + auto a_data = client_->TransferToServer(a_literal).ConsumeValueOrDie(); + ComputeAndCompareR1(&builder, expected, {a_data.get()}); +} + // Describes a binary rank-2 concatenation test. struct R2BinarySpec { int64 lhs_dim0; diff --git a/tensorflow/compiler/xla/tests/conv_depthwise_test.cc b/tensorflow/compiler/xla/tests/conv_depthwise_test.cc new file mode 100644 index 0000000000..bc9bd8a269 --- /dev/null +++ b/tensorflow/compiler/xla/tests/conv_depthwise_test.cc @@ -0,0 +1,234 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "absl/types/optional.h" +#include "tensorflow/compiler/xla/client/xla_computation.h" +#include "tensorflow/compiler/xla/execution_options_util.h" +#include "tensorflow/compiler/xla/service/bfloat16_normalization.h" +#include "tensorflow/compiler/xla/service/despecializer.h" +#include "tensorflow/compiler/xla/service/hlo_parser.h" +#include "tensorflow/compiler/xla/status_macros.h" +#include "tensorflow/compiler/xla/test.h" +#include "tensorflow/compiler/xla/tests/client_library_test_base.h" +#include "tensorflow/compiler/xla/tests/hlo_test_base.h" +#include "tensorflow/compiler/xla/tests/test_macros.h" + +namespace xla { +namespace { + +string GetFloatDataType(bool use_bfloat16) { + return use_bfloat16 ? "bf16" : "f32"; +} + +struct DepthwiseConvolution2DSpec { + int64 output_feature, window, stride, pad, lhs_dilate; + std::vector activation_dims; + std::vector activation_layout; + std::vector kernel_dims; + std::vector kernel_layout; + std::vector output_dims; + std::vector output_layout; +}; + +class DepthwiseConvolution2DTest + : public HloTestBase, + public ::testing::WithParamInterface< + ::testing::tuple> {}; + +static std::vector GetConv2DTestCases() { + std::vector config_set; + std::vector> config_options = { + {128, 6, 3, 64}, {256, 5, 3, 256}, {256, 5, 2, 144}, {144, 5, 3, 64}, + {144, 5, 2, 256}, {8, 48, 17, 8}, {128, 20, 6, 64}, {128, 1, 2, 144}, + {256, 1, 2, 64}, {64, 14, 12, 172}, {16, 9, 4, 16}}; + + for (auto option : config_options) { + int64 feature = option[0]; + int64 activation_size = option[1]; + int64 kernel_size = option[2]; + int64 batch = option[3]; + + std::vector kernel_layout = {3, 2, 1, 0}; + DepthwiseConvolution2DSpec config; + config.output_feature = feature; + config.window = kernel_size; + + config.activation_dims = {batch, activation_size, activation_size, feature}; + config.activation_layout = {3, 0, 2, 1}; + + config.kernel_dims = {kernel_size, kernel_size, 1, feature}; + config.kernel_layout = {3, 2, 1, 0}; + + if (activation_size == 1 && kernel_size == 2) { + // Test for outer dim. + config.output_dims = {batch, activation_size + kernel_size - 1, + activation_size + kernel_size, feature}; + } else if (feature == 256) { + // Restrict dilation-based tests only to one feature configuration. + config.stride = activation_size - 1; + config.pad = 0; + config.lhs_dilate = feature / 32; + config.output_dims = {batch, feature / 32, + activation_size - kernel_size + 1, feature}; + } else { + config.stride = config.pad = config.lhs_dilate = -1; + config.output_dims = {batch, activation_size - kernel_size + 1, + activation_size - kernel_size + 1, feature}; + } + + // Try this layout for all kernel shapes. + config.output_layout = {3, 0, 2, 1}; + config_set.push_back(config); + + // Try other layouts only for certain kernel shapes. + if (kernel_size % 2 == 0) { + config.activation_layout = {0, 3, 2, 1}; + config_set.push_back(config); + + config.output_layout = {0, 3, 2, 1}; + config_set.push_back(config); + + config.activation_layout = {3, 0, 2, 1}; + config_set.push_back(config); + } + } + + return config_set; +} + +string DepthwiseConvolution2DTestDataToString( + const ::testing::TestParamInfo< + ::testing::tuple>& data) { + const auto& spec = ::testing::get<0>(data.param); + const string data_type = GetFloatDataType(::testing::get<1>(data.param)); + string str = absl::StrCat( + "activation_dims_", absl::StrJoin(spec.activation_dims, "x"), + "_activation_layout_", absl::StrJoin(spec.activation_layout, "_"), + "_kernel_dims_", absl::StrJoin(spec.kernel_dims, "x"), "_kernel_layout_", + absl::StrJoin(spec.kernel_layout, "_"), "_output_dims_", + absl::StrJoin(spec.output_dims, "x"), "_output_layout_", + absl::StrJoin(spec.output_layout, "_"), data_type); + // -1 indicates non-existence. + if (spec.stride != -1) { + absl::StrAppend(&str, "_lhs_dilation_", spec.lhs_dilate, "x1"); + } + + // Test names are not allowed to contain the '-' character. + absl::c_replace(str, '-', 'n'); + return str; +} + +string BuildHloTextDepthwiseConvolution2D( + const DepthwiseConvolution2DSpec& spec, bool use_bfloat16) { + const string data_type = GetFloatDataType(use_bfloat16); + if (spec.activation_dims[1] == 1 && spec.kernel_dims[1] == 2) { + return absl::StrFormat( + R"( + HloModule TensorFlowDepthwiseConv + + ENTRY main { + activation = %s[%s]{%s} parameter(0) + kernel = %s[%s]{%s} parameter(1) + ROOT conv = %s[%s]{%s} convolution(%s[%s]{%s} activation, %s[%s]{%s} kernel), + window={size=%dx%d pad=1_1x%d_%d rhs_dilate=1x%d}, dim_labels=b01f_01io->b01f, + feature_group_count=%d + } + )", + data_type, absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), data_type, + absl::StrJoin(spec.output_dims, ","), + absl::StrJoin(spec.output_layout, ","), data_type, + absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), spec.window, spec.window, + spec.window, spec.window, spec.window, spec.output_feature); + + } else if (spec.stride == -1) { + return absl::StrFormat( + R"( + HloModule TensorFlowDepthwiseConv + + ENTRY main { + activation = %s[%s]{%s} parameter(0) + kernel = %s[%s]{%s} parameter(1) + ROOT conv = %s[%s]{%s} convolution(%s[%s]{%s} activation, %s[%s]{%s} kernel), + window={size=%dx%d}, dim_labels=b01f_01io->b01f, + feature_group_count=%d + } + )", + data_type, absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), data_type, + absl::StrJoin(spec.output_dims, ","), + absl::StrJoin(spec.output_layout, ","), data_type, + absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), spec.window, spec.window, + spec.output_feature); + } else { + return absl::StrFormat( + R"( + HloModule TensorFlowDepthwiseConv + + ENTRY main { + activation = %s[%s]{%s} parameter(0) + kernel = %s[%s]{%s} parameter(1) + ROOT conv = %s[%s]{%s} convolution(%s[%s]{%s} activation, %s[%s]{%s} kernel), + window={size=%dx%d stride=%dx1 pad=%d_%dx0_0 lhs_dilate=%dx1}, + dim_labels=b01f_01io->b01f, feature_group_count=%d + } + )", + data_type, absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), data_type, + absl::StrJoin(spec.output_dims, ","), + absl::StrJoin(spec.output_layout, ","), data_type, + absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), spec.window, spec.window, + spec.stride, 0, 0, spec.lhs_dilate, spec.output_feature); + } +} + +XLA_TEST_P(DepthwiseConvolution2DTest, DoIt) { + const DepthwiseConvolution2DSpec& spec = ::testing::get<0>(GetParam()); + bool use_bfloat16 = ::testing::get<1>(GetParam()); + const string hlo_text = + BuildHloTextDepthwiseConvolution2D(spec, use_bfloat16); + + EXPECT_TRUE(RunAndCompare(hlo_text, ErrorSpec{0.01, 0.01}, + [](HloModule* module) -> Status { + BFloat16MixedPrecisionRemoval remover; + TF_RETURN_IF_ERROR(remover.Run(module).status()); + Despecializer despecializer; + return despecializer.Run(module).status(); + })); +} + +INSTANTIATE_TEST_CASE_P( + DepthwiseConvolution2DTestWithRandomIndices, DepthwiseConvolution2DTest, + ::testing::Combine(::testing::ValuesIn(GetConv2DTestCases()), + ::testing::Bool()), + DepthwiseConvolution2DTestDataToString); + +} // namespace +} // namespace xla diff --git a/tensorflow/compiler/xla/tests/convolution_test.cc b/tensorflow/compiler/xla/tests/convolution_test.cc index 211d004ec8..459add9681 100644 --- a/tensorflow/compiler/xla/tests/convolution_test.cc +++ b/tensorflow/compiler/xla/tests/convolution_test.cc @@ -721,23 +721,573 @@ class Convolve2D_1x4x4x512_3x3x1x512_Depthwise_Valid : public ConvolutionTest { ComputeAndCompareLiteral(&builder, expected_r4, {input_literal.get(), filter_literal.get()}, error_spec_); + } +}; + +TYPED_TEST_CASE(Convolve2D_1x4x4x512_3x3x1x512_Depthwise_Valid, TestTypes); +TYPED_TEST(Convolve2D_1x4x4x512_3x3x1x512_Depthwise_Valid, Types) { + this->RunTest(); +} + +template +class Convolve2D_1x4x4x512_3x3x1x512_Depthwise_Valid_Output_Batch_In_Lanes + : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {1, 4, 4, 512}; + std::vector filter_dims = {3, 3, 1, 512}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/512); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape), + static_cast(1)); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape), + static_cast(2)); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + std::vector output_elems(2048, static_cast(18)); + + auto expected_r1 = LiteralUtil::CreateR1(output_elems); + auto expected_r4 = expected_r1.Reshape({1, 2, 2, 512}).ConsumeValueOrDie(); + auto expected_r4_relaid = + expected_r4.Relayout(LayoutUtil::MakeLayout({0, 3, 2, 1})); + + auto input_literal = + client_->TransferToServer(input_r4).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4_relaid, + {input_literal.get(), filter_literal.get()}, + error_spec_, &expected_r4_relaid.shape()); + } +}; + +TYPED_TEST_CASE( + Convolve2D_1x4x4x512_3x3x1x512_Depthwise_Valid_Output_Batch_In_Lanes, + TestTypes); +TYPED_TEST(Convolve2D_1x4x4x512_3x3x1x512_Depthwise_Valid_Output_Batch_In_Lanes, + Types) { + this->RunTest(); +} + +template +class Convolve2D_256x4x4x512_3x3x1x512_Depthwise_Input_Batch_in_Lanes + : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {256, 4, 4, 512}; + std::vector filter_dims = {3, 3, 1, 512}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/512); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape), + static_cast(1)); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + auto input_r4_relaid = + input_r4.Relayout(LayoutUtil::MakeLayout({0, 3, 2, 1})); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape), + static_cast(2)); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + std::vector output_elems(2048 * 256, static_cast(18)); + + auto expected_r1 = LiteralUtil::CreateR1(output_elems); + auto expected_r4 = + expected_r1.Reshape({256, 2, 2, 512}).ConsumeValueOrDie(); + + auto input_literal = + client_->TransferToServer(input_r4_relaid).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4, + {input_literal.get(), filter_literal.get()}, + error_spec_); + } +}; + +TYPED_TEST_CASE(Convolve2D_256x4x4x512_3x3x1x512_Depthwise_Input_Batch_in_Lanes, + TestTypes); +TYPED_TEST(Convolve2D_256x4x4x512_3x3x1x512_Depthwise_Input_Batch_in_Lanes, + Types) { + this->RunTest(); +} + +template +class Convolve2D_256x4x4x512_3x3x1x512_Depthwise_Both_Batch_in_Lanes + : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {256, 4, 4, 512}; + std::vector filter_dims = {3, 3, 1, 512}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/512); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape), + static_cast(1)); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + auto input_r4_relaid = + input_r4.Relayout(LayoutUtil::MakeLayout({0, 3, 2, 1})); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape), + static_cast(2)); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + std::vector output_elems(2048 * 256, static_cast(18)); + + auto expected_r1 = LiteralUtil::CreateR1(output_elems); + auto expected_r4 = + expected_r1.Reshape({256, 2, 2, 512}).ConsumeValueOrDie(); + auto expected_r4_relaid = + expected_r4.Relayout(LayoutUtil::MakeLayout({0, 3, 2, 1})); + + auto input_literal = + client_->TransferToServer(input_r4_relaid).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4_relaid, + {input_literal.get(), filter_literal.get()}, + error_spec_, &expected_r4_relaid.shape()); + } +}; + +TYPED_TEST_CASE(Convolve2D_256x4x4x512_3x3x1x512_Depthwise_Both_Batch_in_Lanes, + TestTypes); +TYPED_TEST(Convolve2D_256x4x4x512_3x3x1x512_Depthwise_Both_Batch_in_Lanes, + Types) { + this->RunTest(); +} + +template +class Convolve2D_1x4x4x5_3x3x1x5_Depthwise_Valid_Output_Batch_In_Lanes + : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {1, 4, 4, 5}; + std::vector filter_dims = {3, 3, 1, 5}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/5); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape)); + iota_int_init_value(input_elems, 1); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + auto input_r4_relaid = + input_r4.Relayout(LayoutUtil::MakeLayout({0, 3, 2, 1})); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape)); + iota_int_init_value(filter_elems, 1); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + auto expected_r1 = LiteralUtil::CreateR1( + {static_cast(6864), static_cast(7296), static_cast(7746), + static_cast(8214), static_cast(8700), static_cast(7809), + static_cast(8286), static_cast(8781), static_cast(9294), + static_cast(9825), static_cast(10644), static_cast(11256), + static_cast(11886), static_cast(12534), static_cast(13200), + static_cast(11589), static_cast(12246), static_cast(12921), + static_cast(13614), static_cast(14325)}); + auto expected_r4 = expected_r1.Reshape({1, 2, 2, 5}).ConsumeValueOrDie(); + auto expected_r4_relaid = + expected_r4.Relayout(LayoutUtil::MakeLayout({0, 3, 2, 1})); + + auto input_literal = + client_->TransferToServer(input_r4_relaid).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4_relaid, + {input_literal.get(), filter_literal.get()}, + error_spec_, &expected_r4_relaid.shape()); + } +}; + +TYPED_TEST_CASE( + Convolve2D_1x4x4x5_3x3x1x5_Depthwise_Valid_Output_Batch_In_Lanes, + TestTypes); +TYPED_TEST(Convolve2D_1x4x4x5_3x3x1x5_Depthwise_Valid_Output_Batch_In_Lanes, + Types) { + this->RunTest(); +} + +template +class Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Valid : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {1, 4, 4, 160}; + std::vector filter_dims = {3, 3, 1, 160}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/160); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape), + static_cast(1)); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape), + static_cast(2)); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + std::vector output_elems(640, static_cast(18)); + + auto expected_r1 = LiteralUtil::CreateR1(output_elems); + auto expected_r4 = expected_r1.Reshape({1, 2, 2, 160}).ConsumeValueOrDie(); + + auto input_literal = + client_->TransferToServer(input_r4).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4, + {input_literal.get(), filter_literal.get()}, + error_spec_); + } +}; + +TYPED_TEST_CASE(Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Valid, TestTypes); +TYPED_TEST(Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Valid, Types) { + this->RunTest(); +} + +template +class Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Input_Batch_In_Lanes + : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {1, 4, 4, 160}; + std::vector filter_dims = {3, 3, 1, 160}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/160); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape), + static_cast(1)); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + auto input_r4_relaid = + input_r4.Relayout(LayoutUtil::MakeLayout({0, 3, 2, 1})); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape), + static_cast(2)); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + std::vector output_elems(640, static_cast(18)); + + auto expected_r1 = LiteralUtil::CreateR1(output_elems); + auto expected_r4 = expected_r1.Reshape({1, 2, 2, 160}).ConsumeValueOrDie(); + auto expected_r4_relaid = + expected_r4.Relayout(LayoutUtil::MakeLayout({3, 0, 2, 1})); + + auto input_literal = + client_->TransferToServer(input_r4_relaid).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4_relaid, + {input_literal.get(), filter_literal.get()}, + error_spec_, &expected_r4_relaid.shape()); + } +}; + +TYPED_TEST_CASE(Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Input_Batch_In_Lanes, + TestTypes); +TYPED_TEST(Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Input_Batch_In_Lanes, + Types) { + this->RunTest(); +} + +template +class Convolve2D_1x4x4x160_3x3x1x160_Dephtwise_Both_Batch_In_Lanes + : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {1, 4, 4, 160}; + std::vector filter_dims = {3, 3, 1, 160}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/160); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape), + static_cast(1)); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + auto input_r4_relaid = + input_r4.Relayout(LayoutUtil::MakeLayout({0, 3, 2, 1})); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape), + static_cast(2)); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + std::vector output_elems(640, static_cast(18)); + + auto expected_r1 = LiteralUtil::CreateR1(output_elems); + auto expected_r4 = expected_r1.Reshape({1, 2, 2, 160}).ConsumeValueOrDie(); + auto expected_r4_relaid = + expected_r4.Relayout(LayoutUtil::MakeLayout({0, 3, 2, 1})); + + auto input_literal = + client_->TransferToServer(input_r4_relaid).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4_relaid, + {input_literal.get(), filter_literal.get()}, + error_spec_, &expected_r4_relaid.shape()); + } +}; + +TYPED_TEST_CASE(Convolve2D_1x4x4x160_3x3x1x160_Dephtwise_Both_Batch_In_Lanes, + TestTypes); +TYPED_TEST(Convolve2D_1x4x4x160_3x3x1x160_Dephtwise_Both_Batch_In_Lanes, + Types) { + this->RunTest(); +} + +template +class Convolve2D_1x4x4x1024_3x3x1x1024_Depthwise_Valid + : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {1, 4, 4, 1024}; + std::vector filter_dims = {3, 3, 1, 1024}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); - auto filter_r = filter_r1.Reshape(filter_dims); + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/1024); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape), + static_cast(1)); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape), + static_cast(2)); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + std::vector output_elems(4096, static_cast(18)); + + auto expected_r1 = LiteralUtil::CreateR1(output_elems); + auto expected_r4 = expected_r1.Reshape({1, 2, 2, 1024}).ConsumeValueOrDie(); + + auto input_literal = + client_->TransferToServer(input_r4).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4, + {input_literal.get(), filter_literal.get()}, + error_spec_); } }; -TYPED_TEST_CASE(Convolve2D_1x4x4x512_3x3x1x512_Depthwise_Valid, TestTypes); -TYPED_TEST(Convolve2D_1x4x4x512_3x3x1x512_Depthwise_Valid, Types) { +TYPED_TEST_CASE(Convolve2D_1x4x4x1024_3x3x1x1024_Depthwise_Valid, TestTypes); +TYPED_TEST(Convolve2D_1x4x4x1024_3x3x1x1024_Depthwise_Valid, Types) { this->RunTest(); } template -class Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Valid : public ConvolutionTest { +class Convolve2D_1x2x2x6_2x2x2x12_Grouped_Valid : public ConvolutionTest { public: void RunTest() { XlaBuilder builder(TestName()); - std::vector input_dims = {1, 4, 4, 160}; - std::vector filter_dims = {3, 3, 1, 160}; + std::vector input_dims = {1, 2, 2, 6}; + std::vector filter_dims = {2, 2, 2, 12}; Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); { @@ -760,23 +1310,89 @@ class Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Valid : public ConvolutionTest { dnums.set_kernel_output_feature_dimension(3); ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, - /*feature_group_count=*/160); + /*feature_group_count=*/3); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape)); + iota_int_init_value(input_elems, 1); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape)); + iota_int_init_value(filter_elems, 1); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + auto expected_r1 = LiteralUtil::CreateR1( + {static_cast(5076), static_cast(5160), static_cast(5244), + static_cast(5328), static_cast(6164), static_cast(6264), + static_cast(6364), static_cast(6464), static_cast(7380), + static_cast(7496), static_cast(7612), static_cast(7728)}); + auto expected_r4 = expected_r1.Reshape({1, 1, 1, 12}).ConsumeValueOrDie(); + + auto input_literal = + client_->TransferToServer(input_r4).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4, + {input_literal.get(), filter_literal.get()}, + error_spec_); + } +}; + +TYPED_TEST_CASE(Convolve2D_1x2x2x6_2x2x2x12_Grouped_Valid, TestTypes); +TYPED_TEST(Convolve2D_1x2x2x6_2x2x2x12_Grouped_Valid, Types) { + this->RunTest(); +} + +template +class Convolve2D_1x2x2x1024_2x2x128x512_Grouped_Valid : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {1, 2, 2, 1024}; + std::vector filter_dims = {2, 2, 128, 512}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/8); } std::vector input_elems(ShapeUtil::ElementsIn(input_shape), static_cast(1)); + auto input_r1 = LiteralUtil::CreateR1(input_elems); auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape), static_cast(2)); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); - std::vector output_elems(640, static_cast(18)); - + std::vector output_elems(512, static_cast(1024)); auto expected_r1 = LiteralUtil::CreateR1(output_elems); - auto expected_r4 = expected_r1.Reshape({1, 2, 2, 160}).ConsumeValueOrDie(); + auto expected_r4 = expected_r1.Reshape({1, 1, 1, 512}).ConsumeValueOrDie(); auto input_literal = client_->TransferToServer(input_r4).ConsumeValueOrDie(); @@ -786,24 +1402,21 @@ class Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Valid : public ConvolutionTest { ComputeAndCompareLiteral(&builder, expected_r4, {input_literal.get(), filter_literal.get()}, error_spec_); - - auto filter_r = filter_r1.Reshape(filter_dims); } }; -TYPED_TEST_CASE(Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Valid, TestTypes); -TYPED_TEST(Convolve2D_1x4x4x160_3x3x1x160_Depthwise_Valid, Types) { +TYPED_TEST_CASE(Convolve2D_1x2x2x1024_2x2x128x512_Grouped_Valid, TestTypes); +TYPED_TEST(Convolve2D_1x2x2x1024_2x2x128x512_Grouped_Valid, Types) { this->RunTest(); } template -class Convolve2D_1x4x4x1024_3x3x1x1024_Depthwise_Valid - : public ConvolutionTest { +class Convolve2D_1x2x2x1024_2x2x128x8_Grouped_Valid : public ConvolutionTest { public: void RunTest() { XlaBuilder builder(TestName()); - std::vector input_dims = {1, 4, 4, 1024}; - std::vector filter_dims = {3, 3, 1, 1024}; + std::vector input_dims = {1, 2, 2, 1024}; + std::vector filter_dims = {2, 2, 128, 8}; Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); { @@ -826,23 +1439,24 @@ class Convolve2D_1x4x4x1024_3x3x1x1024_Depthwise_Valid dnums.set_kernel_output_feature_dimension(3); ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, - /*feature_group_count=*/1024); + /*feature_group_count=*/8); } std::vector input_elems(ShapeUtil::ElementsIn(input_shape), static_cast(1)); + auto input_r1 = LiteralUtil::CreateR1(input_elems); auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape), static_cast(2)); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); - std::vector output_elems(4096, static_cast(18)); - + std::vector output_elems(8, static_cast(1024)); auto expected_r1 = LiteralUtil::CreateR1(output_elems); - auto expected_r4 = expected_r1.Reshape({1, 2, 2, 1024}).ConsumeValueOrDie(); + auto expected_r4 = expected_r1.Reshape({1, 1, 1, 8}).ConsumeValueOrDie(); auto input_literal = client_->TransferToServer(input_r4).ConsumeValueOrDie(); @@ -852,23 +1466,21 @@ class Convolve2D_1x4x4x1024_3x3x1x1024_Depthwise_Valid ComputeAndCompareLiteral(&builder, expected_r4, {input_literal.get(), filter_literal.get()}, error_spec_); - - auto filter_r = filter_r1.Reshape(filter_dims); } }; -TYPED_TEST_CASE(Convolve2D_1x4x4x1024_3x3x1x1024_Depthwise_Valid, TestTypes); -TYPED_TEST(Convolve2D_1x4x4x1024_3x3x1x1024_Depthwise_Valid, Types) { +TYPED_TEST_CASE(Convolve2D_1x2x2x1024_2x2x128x8_Grouped_Valid, TestTypes); +TYPED_TEST(Convolve2D_1x2x2x1024_2x2x128x8_Grouped_Valid, Types) { this->RunTest(); } template -class Convolve2D_1x2x2x6_2x2x1x12_Grouped_Valid : public ConvolutionTest { +class Convolve2D_1x2x2x12_2x2x3x4_Grouped_Valid : public ConvolutionTest { public: void RunTest() { XlaBuilder builder(TestName()); - std::vector input_dims = {1, 2, 2, 6}; - std::vector filter_dims = {2, 2, 2, 12}; + std::vector input_dims = {1, 2, 2, 12}; + std::vector filter_dims = {2, 2, 3, 4}; Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); { @@ -891,7 +1503,7 @@ class Convolve2D_1x2x2x6_2x2x1x12_Grouped_Valid : public ConvolutionTest { dnums.set_kernel_output_feature_dimension(3); ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, - /*feature_group_count=*/3); + /*feature_group_count=*/4); } std::vector input_elems(ShapeUtil::ElementsIn(input_shape)); @@ -904,12 +1516,140 @@ class Convolve2D_1x2x2x6_2x2x1x12_Grouped_Valid : public ConvolutionTest { auto filter_r1 = LiteralUtil::CreateR1(filter_elems); auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + auto expected_r1 = + LiteralUtil::CreateR1({static_cast(7712), static_cast(8816), + static_cast(9992), static_cast(11240)}); + auto expected_r4 = expected_r1.Reshape({1, 1, 1, 4}).ConsumeValueOrDie(); + + auto input_literal = + client_->TransferToServer(input_r4).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4, + {input_literal.get(), filter_literal.get()}, + error_spec_); + } +}; + +TYPED_TEST_CASE(Convolve2D_1x2x2x12_2x2x3x4_Grouped_Valid, TestTypes); +TYPED_TEST(Convolve2D_1x2x2x12_2x2x3x4_Grouped_Valid, Types) { + this->RunTest(); +} + +template +class Convolve2D_1x2x2x12_2x2x3x4_Grouped_Valid_Filter_OF_In_Sublanes + : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {1, 2, 2, 12}; + std::vector filter_dims = {2, 2, 4, 3}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(3); + dnums.set_kernel_output_feature_dimension(2); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/4); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape)); + iota_int_init_value(input_elems, 1); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape)); + iota_int_init_value(filter_elems, 1); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + auto filter_r4_relaid = + filter_r4.Relayout(LayoutUtil::MakeLayout({3, 2, 1, 0})); auto expected_r1 = LiteralUtil::CreateR1( - {static_cast(5076), static_cast(5160), static_cast(5244), - static_cast(5328), static_cast(6164), static_cast(6264), - static_cast(6364), static_cast(6464), static_cast(7380), - static_cast(7496), static_cast(7612), static_cast(7728)}); - auto expected_r4 = expected_r1.Reshape({1, 1, 1, 12}).ConsumeValueOrDie(); + {static_cast(6968), static_cast(8516), static_cast(10280), + static_cast(12260)}); + auto expected_r4 = expected_r1.Reshape({1, 1, 1, 4}).ConsumeValueOrDie(); + + auto input_literal = + client_->TransferToServer(input_r4).ConsumeValueOrDie(); + auto filter_literal = + client_->TransferToServer(filter_r4_relaid).ConsumeValueOrDie(); + + ComputeAndCompareLiteral(&builder, expected_r4, + {input_literal.get(), filter_literal.get()}, + error_spec_); + } +}; + +TYPED_TEST_CASE(Convolve2D_1x2x2x12_2x2x3x4_Grouped_Valid_Filter_OF_In_Sublanes, + TestTypes); +TYPED_TEST(Convolve2D_1x2x2x12_2x2x3x4_Grouped_Valid_Filter_OF_In_Sublanes, + Types) { + this->RunTest(); +} + +template +class Convolve2D_1x1x1x12_1x1x3x4_Grouped_Valid : public ConvolutionTest { + public: + void RunTest() { + XlaBuilder builder(TestName()); + std::vector input_dims = {1, 1, 1, 12}; + std::vector filter_dims = {1, 1, 3, 4}; + Shape input_shape = ShapeUtil::MakeShapeWithType(input_dims); + Shape filter_shape = ShapeUtil::MakeShapeWithType(filter_dims); + { + auto input = Parameter(&builder, 0, input_shape, "input"); + auto filter = Parameter(&builder, 1, filter_shape, "filter"); + + // Tensorflow dimension numbers for 2D convolution. + ConvolutionDimensionNumbers dnums; + dnums.set_input_batch_dimension(0); + dnums.set_output_batch_dimension(0); + dnums.add_input_spatial_dimensions(1); + dnums.add_output_spatial_dimensions(1); + dnums.add_input_spatial_dimensions(2); + dnums.add_output_spatial_dimensions(2); + dnums.set_input_feature_dimension(3); + dnums.set_output_feature_dimension(3); + dnums.add_kernel_spatial_dimensions(0); + dnums.add_kernel_spatial_dimensions(1); + dnums.set_kernel_input_feature_dimension(2); + dnums.set_kernel_output_feature_dimension(3); + + ConvWithGeneralDimensions(input, filter, {1, 1}, Padding::kValid, dnums, + /*feature_group_count=*/4); + } + + std::vector input_elems(ShapeUtil::ElementsIn(input_shape)); + iota_int_init_value(input_elems, 1); + auto input_r1 = LiteralUtil::CreateR1(input_elems); + auto input_r4 = input_r1.Reshape(input_dims).ConsumeValueOrDie(); + + std::vector filter_elems(ShapeUtil::ElementsIn(filter_shape)); + iota_int_init_value(filter_elems, 1); + auto filter_r1 = LiteralUtil::CreateR1(filter_elems); + auto filter_r4 = filter_r1.Reshape(filter_dims).ConsumeValueOrDie(); + + auto expected_r1 = + LiteralUtil::CreateR1({static_cast(38), static_cast(98), + static_cast(176), static_cast(272)}); + auto expected_r4 = expected_r1.Reshape({1, 1, 1, 4}).ConsumeValueOrDie(); auto input_literal = client_->TransferToServer(input_r4).ConsumeValueOrDie(); @@ -922,8 +1662,8 @@ class Convolve2D_1x2x2x6_2x2x1x12_Grouped_Valid : public ConvolutionTest { } }; -TYPED_TEST_CASE(Convolve2D_1x2x2x6_2x2x1x12_Grouped_Valid, TestTypes); -TYPED_TEST(Convolve2D_1x2x2x6_2x2x1x12_Grouped_Valid, Types) { +TYPED_TEST_CASE(Convolve2D_1x1x1x12_1x1x3x4_Grouped_Valid, TestTypes); +TYPED_TEST(Convolve2D_1x1x1x12_1x1x3x4_Grouped_Valid, Types) { this->RunTest(); } @@ -1217,6 +1957,18 @@ ENTRY Test { EXPECT_TRUE(RunAndCompare(kHlo, ErrorSpec{0.001})); } +XLA_TEST_F(ConvolutionHloTest, DISABLED_ON_CPU(ConvolveF64ForwardReversed)) { + constexpr char kHlo[] = R"( +HloModule TestModule + +ENTRY Test { + %arg0 = f64[3,56,56,16] parameter(0) + %arg1 = f64[3,3,3,64] parameter(1) + ROOT %conv = f64[54,54,16,64] convolution(%arg0, %arg1), window={size=3x3 rhs_reversal=1x1}, dim_labels=f01b_i01o->01bf +})"; + EXPECT_TRUE(RunAndCompare(kHlo, ErrorSpec{0.001})); +} + XLA_TEST_F(ConvolutionHloTest, DISABLED_ON_CPU(ConvolveF64BackwardFilter)) { constexpr char kHlo[] = R"( HloModule TestModule diff --git a/tensorflow/compiler/xla/tests/dot_operation_test.cc b/tensorflow/compiler/xla/tests/dot_operation_test.cc index 6c0847a875..25091b8d5d 100644 --- a/tensorflow/compiler/xla/tests/dot_operation_test.cc +++ b/tensorflow/compiler/xla/tests/dot_operation_test.cc @@ -637,6 +637,76 @@ XLA_TYPED_TEST(DotOperationTest_F16F32F64CF64, GeneralMatMul) { {x_data.get(), y_data.get()}, this->error_spec_); } +#ifndef XLA_TEST_BACKEND_CPU +// TODO(b/74459949): failed on CPU on 2018-10-29. +XLA_TYPED_TEST(DotOperationTest_F16F32F64CF64, GeneralMatMulR3LhsR2Rhs) { + using T = TypeParam; + + XlaBuilder builder(this->TestName()); + auto x = + Parameter(&builder, 0, ShapeUtil::MakeShapeWithType({2, 2, 2}), "x"); + auto y = Parameter(&builder, 1, ShapeUtil::MakeShapeWithType({2, 2}), "y"); + + DotDimensionNumbers dnums; + dnums.add_lhs_contracting_dimensions(1); + dnums.add_rhs_contracting_dimensions(1); + dnums.add_lhs_batch_dimensions(0); + dnums.add_rhs_batch_dimensions(0); + + DotGeneral(x, y, dnums); + + auto x_data = + this->client_ + ->TransferToServer(LiteralUtil::CreateR3FromArray3D( + {{{1.0f, 2.0f}, {3.0f, 4.0f}}, {{5.0f, 6.0f}, {7.0f, 8.0f}}})) + .ConsumeValueOrDie(); + + auto y_data = this->client_ + ->TransferToServer(LiteralUtil::CreateR2FromArray2D( + {{1.0f, 0.0f}, {0.0f, 1.0f}})) + .ConsumeValueOrDie(); + + this->template ComputeAndCompareR2( + &builder, + /*expected=*/{{1.0f, 2.0f}, {7.0f, 8.0f}}, {x_data.get(), y_data.get()}, + this->error_spec_); +} + +// TODO(b/74459949): failed on CPU on 2018-10-29. +XLA_TYPED_TEST(DotOperationTest_F16F32F64CF64, GeneralMatMulR2LhsR3Rhs) { + using T = TypeParam; + + XlaBuilder builder(this->TestName()); + auto x = Parameter(&builder, 0, ShapeUtil::MakeShapeWithType({2, 2}), "x"); + auto y = + Parameter(&builder, 1, ShapeUtil::MakeShapeWithType({2, 2, 2}), "y"); + + DotDimensionNumbers dnums; + dnums.add_lhs_contracting_dimensions(1); + dnums.add_rhs_contracting_dimensions(1); + dnums.add_lhs_batch_dimensions(0); + dnums.add_rhs_batch_dimensions(0); + + DotGeneral(x, y, dnums); + + auto x_data = this->client_ + ->TransferToServer(LiteralUtil::CreateR2FromArray2D( + {{1.0f, 0.0f}, {0.0f, 1.0f}})) + .ConsumeValueOrDie(); + + auto y_data = + this->client_ + ->TransferToServer(LiteralUtil::CreateR3FromArray3D( + {{{1.0f, 2.0f}, {3.0f, 4.0f}}, {{5.0f, 6.0f}, {7.0f, 8.0f}}})) + .ConsumeValueOrDie(); + + this->template ComputeAndCompareR2( + &builder, + /*expected=*/{{1.0f, 2.0f}, {7.0f, 8.0f}}, {x_data.get(), y_data.get()}, + this->error_spec_); +} +#endif // XLA_TEST_BACKEND_CPU + XLA_TYPED_TEST(DotOperationTest_F16F32F64CF64, GeneralMatMulMultipleBatch) { using T = TypeParam; diff --git a/tensorflow/compiler/xla/tests/grouped_convolution_test.cc b/tensorflow/compiler/xla/tests/grouped_convolution_test.cc new file mode 100644 index 0000000000..8f7049910e --- /dev/null +++ b/tensorflow/compiler/xla/tests/grouped_convolution_test.cc @@ -0,0 +1,245 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "absl/types/optional.h" +#include "tensorflow/compiler/xla/client/xla_computation.h" +#include "tensorflow/compiler/xla/execution_options_util.h" +#include "tensorflow/compiler/xla/service/bfloat16_normalization.h" +#include "tensorflow/compiler/xla/service/despecializer.h" +#include "tensorflow/compiler/xla/service/hlo_parser.h" +#include "tensorflow/compiler/xla/status_macros.h" +#include "tensorflow/compiler/xla/test.h" +#include "tensorflow/compiler/xla/tests/client_library_test_base.h" +#include "tensorflow/compiler/xla/tests/hlo_test_base.h" +#include "tensorflow/compiler/xla/tests/test_macros.h" + +namespace xla { +namespace { + +string GetFloatDataType(bool use_bfloat16) { + return use_bfloat16 ? "bf16" : "f32"; +} + +struct GroupedConvolution2DSpec { + int64 input_feature, output_feature, window, stride, pad, lhs_dilate; + int64 group_size, group_count; + std::vector activation_dims; + std::vector activation_layout; + std::vector kernel_dims; + std::vector kernel_layout; + std::vector output_dims; + std::vector output_layout; +}; + +class GroupedConvolution2DTest + : public HloTestBase, + public ::testing::WithParamInterface< + ::testing::tuple> {}; + +static std::vector GetConv2DTestCases() { + std::vector config_set; + // Add to this set if you want a new test configuration. + // Rule : the penultimate number must be divisible by the last number. + std::vector> config_options = {{8, 2, 2, 1, 1024, 128}, + {512, 3, 3, 144, 1024, 16}, + {256, 3, 3, 129, 512, 64}, + {64, 1, 2, 127, 32, 8}, + {256, 3, 3, 256, 1024, 4}}; + + for (auto option : config_options) { + int64 output_feature = option[0]; + int64 activation_size = option[1]; + int64 kernel_size = option[2]; + int64 batch = option[3]; + int64 input_feature = option[4]; + int64 group_size = option[5]; + + std::vector kernel_layout = {3, 2, 1, 0}; + GroupedConvolution2DSpec config; + config.group_size = group_size; + config.group_count = input_feature / group_size; + config.output_feature = output_feature; + config.window = kernel_size; + + config.activation_dims = {batch, activation_size, activation_size, + input_feature}; + config.activation_layout = {3, 0, 2, 1}; + + config.kernel_dims = {kernel_size, kernel_size, group_size, output_feature}; + config.kernel_layout = {3, 2, 1, 0}; + + if (activation_size == 1 && kernel_size == 2) { + // Test for outer dim. + config.output_dims = {batch, activation_size + kernel_size - 1, + activation_size + kernel_size, output_feature}; + } else if (output_feature == 256) { + // Restrict dilation-based tests only to one feature configuration. + config.stride = activation_size - 1; + config.pad = 0; + config.lhs_dilate = output_feature / 32; + config.output_dims = {batch, output_feature / 32, + activation_size - kernel_size + 1, output_feature}; + } else { + config.stride = config.pad = config.lhs_dilate = -1; + config.output_dims = {batch, activation_size - kernel_size + 1, + activation_size - kernel_size + 1, output_feature}; + } + + // Try this layout for all kernel shapes. + config.output_layout = {3, 0, 2, 1}; + config_set.push_back(config); + + // Try other layouts only for certain kernel shapes. + if (kernel_size % 2 == 0) { + config.activation_layout = {0, 3, 2, 1}; + config_set.push_back(config); + + config.output_layout = {0, 3, 2, 1}; + config_set.push_back(config); + + config.activation_layout = {3, 0, 2, 1}; + config_set.push_back(config); + } + } + + return config_set; +} + +string GroupedConvolution2DTestDataToString( + const ::testing::TestParamInfo< + ::testing::tuple>& data) { + const auto& spec = ::testing::get<0>(data.param); + const string data_type = GetFloatDataType(::testing::get<1>(data.param)); + string str = absl::StrCat( + "activation_dims_", absl::StrJoin(spec.activation_dims, "x"), + "_activation_layout_", absl::StrJoin(spec.activation_layout, "_"), + "_kernel_dims_", absl::StrJoin(spec.kernel_dims, "x"), "_kernel_layout_", + absl::StrJoin(spec.kernel_layout, "_"), "_output_dims_", + absl::StrJoin(spec.output_dims, "x"), "_output_layout_", + absl::StrJoin(spec.output_layout, "_"), data_type); + // -1 indicates non-existence. + if (spec.stride != -1) { + absl::StrAppend(&str, "_lhs_dilation_", spec.lhs_dilate, "x1"); + } + + // Test names are not allowed to contain the '-' character. + absl::c_replace(str, '-', 'n'); + return str; +} + +string BuildHloTextGroupedConvolution2D(const GroupedConvolution2DSpec& spec, + bool use_bfloat16) { + const string data_type = GetFloatDataType(use_bfloat16); + if (spec.activation_dims[1] == 1 && spec.kernel_dims[1] == 2) { + // Check for outer dim. + return absl::StrFormat( + R"( + HloModule TensorFlowDepthwiseConv + + ENTRY main { + activation = %s[%s]{%s} parameter(0) + kernel = %s[%s]{%s} parameter(1) + ROOT conv = %s[%s]{%s} convolution(%s[%s]{%s} activation, %s[%s]{%s} kernel), + window={size=%dx%d pad=1_1x%d_%d rhs_dilate=1x%d}, dim_labels=b01f_01io->b01f, + feature_group_count=%d + } + )", + data_type, absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), data_type, + absl::StrJoin(spec.output_dims, ","), + absl::StrJoin(spec.output_layout, ","), data_type, + absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), spec.window, spec.window, + spec.window, spec.window, spec.window, spec.group_count); + + } else if (spec.stride == -1) { + // Check for basic, non-dilated cases. + return absl::StrFormat( + R"( + HloModule TensorFlowDepthwiseConv + + ENTRY main { + activation = %s[%s]{%s} parameter(0) + kernel = %s[%s]{%s} parameter(1) + ROOT conv = %s[%s]{%s} convolution(%s[%s]{%s} activation, %s[%s]{%s} kernel), + window={size=%dx%d}, dim_labels=b01f_01io->b01f, + feature_group_count=%d + } + )", + data_type, absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), data_type, + absl::StrJoin(spec.output_dims, ","), + absl::StrJoin(spec.output_layout, ","), data_type, + absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), spec.window, spec.window, + spec.group_count); + } else { + // Check for base dilations. + return absl::StrFormat( + R"( + HloModule TensorFlowDepthwiseConv + + ENTRY main { + activation = %s[%s]{%s} parameter(0) + kernel = %s[%s]{%s} parameter(1) + ROOT conv = %s[%s]{%s} convolution(%s[%s]{%s} activation, %s[%s]{%s} kernel), + window={size=%dx%d stride=%dx1 pad=%d_%dx0_0 lhs_dilate=%dx1}, + dim_labels=b01f_01io->b01f, feature_group_count=%d + } + )", + data_type, absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), data_type, + absl::StrJoin(spec.output_dims, ","), + absl::StrJoin(spec.output_layout, ","), data_type, + absl::StrJoin(spec.activation_dims, ","), + absl::StrJoin(spec.activation_layout, ","), data_type, + absl::StrJoin(spec.kernel_dims, ","), + absl::StrJoin(spec.kernel_layout, ","), spec.window, spec.window, + spec.stride, 0, 0, spec.lhs_dilate, spec.group_count); + } +} + +XLA_TEST_P(GroupedConvolution2DTest, DoIt) { + const GroupedConvolution2DSpec& spec = ::testing::get<0>(GetParam()); + bool use_bfloat16 = ::testing::get<1>(GetParam()); + const string hlo_text = BuildHloTextGroupedConvolution2D(spec, use_bfloat16); + + EXPECT_TRUE(RunAndCompare(hlo_text, ErrorSpec{0.01, 0.01}, + [](HloModule* module) -> Status { + BFloat16MixedPrecisionRemoval remover; + TF_RETURN_IF_ERROR(remover.Run(module).status()); + Despecializer despecializer; + return despecializer.Run(module).status(); + })); +} + +INSTANTIATE_TEST_CASE_P( + GroupedConvolution2DTestWithRandomIndices, GroupedConvolution2DTest, + ::testing::Combine(::testing::ValuesIn(GetConv2DTestCases()), + ::testing::Bool()), + GroupedConvolution2DTestDataToString); + +} // namespace +} // namespace xla diff --git a/tensorflow/compiler/xla/tests/hlo_test_base.cc b/tensorflow/compiler/xla/tests/hlo_test_base.cc index d8fa00272f..989a7c705a 100644 --- a/tensorflow/compiler/xla/tests/hlo_test_base.cc +++ b/tensorflow/compiler/xla/tests/hlo_test_base.cc @@ -99,6 +99,8 @@ void VerifiedHloModule::VerifyOrAddFailure(const string& message) { ADD_FAILURE() << "HloVerifier failed on module " << name() << (message.empty() ? "" : absl::StrCat(" (", message, ")")) << ": " << status; + LOG(ERROR) << "Contents of bad module:"; + XLA_LOG_LINES(tensorflow::ERROR, ToString()); } } @@ -140,14 +142,6 @@ std::unique_ptr HloTestBase::CreateNewVerifiedModule( allow_mixed_precision_in_hlo_verifier_); } -StatusOr> -HloTestBase::ParseAndReturnUnverifiedModule(absl::string_view hlo_text, - const HloModuleConfig& config) { - auto module = absl::make_unique(TestName(), config); - TF_RETURN_IF_ERROR(ParseHloString(hlo_text, module.get())); - return std::move(module); -} - StatusOr> HloTestBase::ParseAndReturnVerifiedModule(absl::string_view hlo_text, const HloModuleConfig& config) { diff --git a/tensorflow/compiler/xla/tests/hlo_test_base.h b/tensorflow/compiler/xla/tests/hlo_test_base.h index 366726d90b..1d1e7f4372 100644 --- a/tensorflow/compiler/xla/tests/hlo_test_base.h +++ b/tensorflow/compiler/xla/tests/hlo_test_base.h @@ -20,6 +20,7 @@ limitations under the License. #include #include +#include "absl/base/macros.h" #include "absl/types/optional.h" #include "absl/types/span.h" #include "tensorflow/compiler/xla/service/backend.h" @@ -100,6 +101,7 @@ class HloTestBase : public ::testing::Test { // // This returns a vanilla HloModule that doesn't run the HLO verifier on // destruction. + ABSL_DEPRECATED("Use CreateNewVerifiedModule instead.") std::unique_ptr CreateNewUnverifiedModule( const string& name = TestName()); @@ -108,12 +110,6 @@ class HloTestBase : public ::testing::Test { std::unique_ptr CreateNewVerifiedModule( const string& name = TestName()); - // Parses the given string and returns module as a vanilla, unverified - // HloModule. - StatusOr> ParseAndReturnUnverifiedModule( - absl::string_view hlo_text, - const HloModuleConfig& config = HloModuleConfig()); - // Parses the given string and returns module as a VerifiedHloModule. StatusOr> ParseAndReturnVerifiedModule( absl::string_view hlo_text, diff --git a/tensorflow/compiler/xla/tests/iota_test.cc b/tensorflow/compiler/xla/tests/iota_test.cc index 310f349592..65205f53dd 100644 --- a/tensorflow/compiler/xla/tests/iota_test.cc +++ b/tensorflow/compiler/xla/tests/iota_test.cc @@ -113,5 +113,26 @@ INSTANTIATE_TEST_CASE_P(IotaR3TestInstantiation, IotaR3Test, /*step=*/10), ::testing::Values(0, 1, 2))); +class IotaR3PredTest : public ClientLibraryTestBase, + public ::testing::WithParamInterface {}; + +TEST_P(IotaR3PredTest, DoIt) { + const auto element_type = PRED; + const int64 num_elements = 2; + const int64 iota_dim = GetParam(); + XlaBuilder builder(TestName() + "_" + PrimitiveType_Name(element_type)); + std::vector dimensions = {42, 19}; + dimensions.insert(dimensions.begin() + iota_dim, num_elements); + Iota(&builder, ShapeUtil::MakeShape(element_type, dimensions), iota_dim); + if (primitive_util::IsFloatingPointType(element_type)) { + ComputeAndCompare(&builder, {}, ErrorSpec{0.0001}); + } else { + ComputeAndCompare(&builder, {}); + } +} + +INSTANTIATE_TEST_CASE_P(IotaR3PredTestInstantiation, IotaR3PredTest, + ::testing::Values(0, 1, 2)); + } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/tests/replay_test.cc b/tensorflow/compiler/xla/tests/replay_test.cc index 5cf87e565b..34c7dc7c46 100644 --- a/tensorflow/compiler/xla/tests/replay_test.cc +++ b/tensorflow/compiler/xla/tests/replay_test.cc @@ -55,7 +55,8 @@ TEST_F(ReplayTest, TwoPlusTwoReplay) { client_->GetComputationShape(computation).ConsumeValueOrDie(); std::unique_ptr replayed_shape = client_->GetComputationShape(replayed).ConsumeValueOrDie(); - ASSERT_TRUE(protobuf_util::ProtobufEquals(*original_shape, *replayed_shape)); + ASSERT_TRUE(protobuf_util::ProtobufEquals(original_shape->ToProto(), + replayed_shape->ToProto())); // Run it. Literal literal = @@ -87,7 +88,8 @@ XLA_TEST_F(ReplayTest, XPlusYReplayWithParameters) { client_->GetComputationShape(computation).ConsumeValueOrDie(); std::unique_ptr replayed_shape = client_->GetComputationShape(replayed).ConsumeValueOrDie(); - ASSERT_TRUE(protobuf_util::ProtobufEquals(*original_shape, *replayed_shape)); + ASSERT_TRUE(protobuf_util::ProtobufEquals(original_shape->ToProto(), + replayed_shape->ToProto())); // Run it. std::unique_ptr x_data = @@ -133,7 +135,8 @@ TEST_F(ReplayTest, MapPlusTwoOverR1) { client_->GetComputationShape(computation).ConsumeValueOrDie(); std::unique_ptr replayed_shape = client_->GetComputationShape(replayed).ConsumeValueOrDie(); - ASSERT_TRUE(protobuf_util::ProtobufEquals(*original_shape, *replayed_shape)); + ASSERT_TRUE(protobuf_util::ProtobufEquals(original_shape->ToProto(), + replayed_shape->ToProto())); // Run it. Literal literal = diff --git a/tensorflow/compiler/xla/tests/reshape_test.cc b/tensorflow/compiler/xla/tests/reshape_test.cc index dedc95b5ae..298136002e 100644 --- a/tensorflow/compiler/xla/tests/reshape_test.cc +++ b/tensorflow/compiler/xla/tests/reshape_test.cc @@ -618,7 +618,8 @@ XLA_TEST_P(ReshapeTest, R4Dim0MinorLayoutToR2Dim0MajorLayout) { ExecutionOptions execution_options = execution_options_; *execution_options.mutable_shape_with_output_layout() = ShapeUtil::MakeShapeWithLayout(use_bfloat16() ? BF16 : F32, {2, 8}, - {1, 0}); + {1, 0}) + .ToProto(); Literal actual = client_ ->ExecuteAndTransfer(computation, {input.get()}, &execution_options) @@ -767,7 +768,8 @@ XLA_TEST_P(ReshapeTest, NoopReshape) { ExecutionOptions execution_options = execution_options_; *execution_options.mutable_shape_with_output_layout() = ShapeUtil::MakeShapeWithLayout(use_bfloat16() ? BF16 : F32, {7, 2, 3, 5}, - {2, 3, 0, 1}); + {2, 3, 0, 1}) + .ToProto(); Literal output_literal = client_ ->ExecuteAndTransfer(computation, {input_data.get()}, diff --git a/tensorflow/compiler/xla/tests/scatter_test.cc b/tensorflow/compiler/xla/tests/scatter_test.cc index 7e1f4aa0eb..32de0fdf78 100644 --- a/tensorflow/compiler/xla/tests/scatter_test.cc +++ b/tensorflow/compiler/xla/tests/scatter_test.cc @@ -129,6 +129,42 @@ ENTRY main { RunTest(hlo_text, &operand, &scatter_indices, &updates); } +XLA_TEST_F(ScatterTest, TensorFlowScatterV2_InversePermutation) { + const char* hlo_text = R"( +HloModule TensorFlowScatterV2 + +update_s32 (lhs: s32[], rhs: s32[]) -> s32[] { + lhs = s32[] parameter(0) + ROOT rhs = s32[] parameter(1) +} + +ENTRY main { + permutation = s32[3,4] parameter(0) + reshape = s32[3,4,1] reshape(permutation) + operand = s32[3,4] iota(), iota_dimension=1 + updates = s32[3,4,1,1] iota(), iota_dimension=1 + iota = s32[3,4,1] iota(), iota_dimension=0 + indices = s32[3,4,2] concatenate(iota, reshape), dimensions={2} + ROOT scatter = s32[3,4] scatter(operand, indices, updates), + to_apply=update_s32, + update_window_dims={2,3}, + inserted_window_dims={}, + scatter_dims_to_operand_dims={0,1}, + index_vector_dim=2 +} +)"; + Literal permutation = + LiteralUtil::CreateR2({{1, 3, 2, 0}, {3, 0, 2, 1}, {2, 3, 1, 0}}); + HloModuleConfig config; + config.set_debug_options(GetDebugOptionsForTest()); + TF_ASSERT_OK_AND_ASSIGN(std::unique_ptr module, + ParseHloString(hlo_text, config)); + auto actual = ExecuteAndTransfer(std::move(module), {&permutation}); + Literal expected = + LiteralUtil::CreateR2({{3, 0, 2, 1}, {1, 3, 2, 0}, {3, 2, 0, 1}}); + EXPECT_TRUE(LiteralTestUtil::Equal(expected, actual)); +} + XLA_TEST_F(ScatterTest, SimpleR4) { const char* hlo_text = R"( HloModule SimpleR4 diff --git a/tensorflow/compiler/xla/tests/test_utils.cc b/tensorflow/compiler/xla/tests/test_utils.cc index 2f18036ff4..eafa48ed7b 100644 --- a/tensorflow/compiler/xla/tests/test_utils.cc +++ b/tensorflow/compiler/xla/tests/test_utils.cc @@ -15,6 +15,7 @@ limitations under the License. #include +#include "absl/base/casts.h" #include "absl/memory/memory.h" #include "tensorflow/compiler/xla/literal_util.h" #include "tensorflow/compiler/xla/primitive_util.h" @@ -28,65 +29,113 @@ namespace xla { namespace { template -void PopulateWithRandomFloatingPointDataImpl(Literal* literal, - std::minstd_rand0* engine, - bool no_duplicates) { +void PopulateWithRandomFloatingPointData(Literal* literal, + std::minstd_rand0* engine) { + std::uniform_real_distribution generator(-0.1f, 0.2f); + for (FloatT& value : literal->data()) { + value = static_cast(generator(*engine)); + } +} + +template +void PopulateWithIntNext(Literal* literal); + +template <> +void PopulateWithIntNext(Literal* literal) { + // Duplicates may be generated if we don't have enough bits. + uint16 next_value = 0; + for (half& value : literal->data()) { + // Zero-out the MSB of the exponent to avoid Infs and NaNs, and put it into + // the sign bit. We could be less wasteful, but this is best-effort anyway. + uint16 exponent_msb = next_value & 0x4000; + value.x = (next_value & 0xBFFF) | (exponent_msb << 1); + next_value++; + } +} + +template <> +void PopulateWithIntNext(Literal* literal) { + // Duplicates may be generated if we don't have enough bits. + // Start at 0x80 rather than 0 to avoid denormals. + uint16 next_value = 0x80; + for (bfloat16& value : literal->data()) { + // Zero-out the MSB of the exponent to avoid Infs and NaNs, and put it into + // the sign bit. We could be less wasteful, but this is best-effort anyway. + uint16 exponent_msb = next_value & 0x4000; + value.value = (next_value & 0xBFFF) | (exponent_msb << 1); + next_value++; + } +} + +template +void PopulateWithNextAfter(Literal* literal) { + // Duplicates may be generated if the number of elements in the literal + // exceeds the number of positive values supported by the type. + float next_value = std::numeric_limits::min(); + for (float& value : literal->data()) { + value = next_value; + next_value = std::nextafter(next_value, std::numeric_limits::max()); + } +} + +template ::value || + std::is_same::value, + int>::type = 0> +void PopulateWithNoDuplicateData(Literal* literal, std::minstd_rand0* engine) { + PopulateWithIntNext(literal); + std::shuffle(literal->data().begin(), literal->data().end(), + *engine); +} + +template ::value && + !std::is_same::value, + int>::type = 0> +void PopulateWithNoDuplicateData(Literal* literal, std::minstd_rand0* engine) { + PopulateWithNextAfter(literal); + std::shuffle(literal->data().begin(), literal->data().end(), + *engine); +} + +template +void PopulateWithFloatingPointData(Literal* literal, std::minstd_rand0* engine, + bool no_duplicates) { CHECK(engine != nullptr); CHECK_EQ(literal->shape().element_type(), primitive_util::NativeToPrimitiveType()); if (no_duplicates) { - // Duplicates may be generated if the number of elements in the literal - // exceeds the number of positive values supported by the type. - FloatT next_value = std::numeric_limits::min(); - for (FloatT& value : literal->data()) { - value = next_value; - next_value = - std::nextafter(next_value, std::numeric_limits::max()); - } - std::shuffle(literal->data().begin(), literal->data().end(), - *engine); + PopulateWithNoDuplicateData(literal, engine); } else { - std::uniform_real_distribution generator(-0.1f, 0.2f); - for (FloatT& value : literal->data()) { - value = static_cast(generator(*engine)); - } + PopulateWithRandomFloatingPointData(literal, engine); } } -template -void PopulateWithRandomFloatingPointData(Literal* literal, +template <> +void PopulateWithFloatingPointData(Literal* literal, std::minstd_rand0* engine, bool no_duplicates) { CHECK(engine != nullptr); - PopulateWithRandomFloatingPointDataImpl(literal, engine, - no_duplicates); -} - -template <> -void PopulateWithRandomFloatingPointData(Literal* literal, - std::minstd_rand0* engine, - bool no_duplicates) { - // no_duplicates is ignored for half types. Unique values can only be - // generated for arrays with fewer than ~2**16 elements and no_duplicates is - // best-effort anyway. - CHECK(engine != nullptr); - std::uniform_real_distribution generator(-0.1f, 0.2f); - for (half& value : literal->data()) { - value = static_cast(generator(*engine)); + CHECK_EQ(literal->shape().element_type(), + primitive_util::NativeToPrimitiveType()); + if (no_duplicates) { + PopulateWithNoDuplicateData(literal, engine); + } else { + PopulateWithRandomFloatingPointData(literal, engine); } } template <> -void PopulateWithRandomFloatingPointData(Literal* literal, - std::minstd_rand0* engine, - bool no_duplicates) { - // no_duplicates is ignored for bfloat types. Unique values can only be - // generated for arrays with fewer than ~2**16 elements and no_duplicates is - // best-effort anyway. +void PopulateWithFloatingPointData(Literal* literal, + std::minstd_rand0* engine, + bool no_duplicates) { CHECK(engine != nullptr); - std::uniform_real_distribution generator(-0.1f, 0.2f); - for (bfloat16& value : literal->data()) { - value = static_cast(generator(*engine)); + CHECK_EQ(literal->shape().element_type(), + primitive_util::NativeToPrimitiveType()); + if (no_duplicates) { + PopulateWithNoDuplicateData(literal, engine); + } else { + PopulateWithRandomFloatingPointData(literal, engine); } } @@ -135,20 +184,16 @@ StatusOr MakeFakeLiteralInternal(const Shape& shape, Literal literal(shape); switch (shape.element_type()) { case BF16: - PopulateWithRandomFloatingPointData(&literal, engine, - no_duplicates); + PopulateWithFloatingPointData(&literal, engine, no_duplicates); break; case F16: - PopulateWithRandomFloatingPointData(&literal, engine, - no_duplicates); + PopulateWithFloatingPointData(&literal, engine, no_duplicates); break; case F32: - PopulateWithRandomFloatingPointData(&literal, engine, - no_duplicates); + PopulateWithFloatingPointData(&literal, engine, no_duplicates); break; case F64: - PopulateWithRandomFloatingPointData(&literal, engine, - no_duplicates); + PopulateWithFloatingPointData(&literal, engine, no_duplicates); break; case S8: PopulateWithRandomIntegralData(&literal, engine, no_duplicates); diff --git a/tensorflow/compiler/xla/tests/test_utils_test.cc b/tensorflow/compiler/xla/tests/test_utils_test.cc index e066b3f4f2..e8f5d7a9a7 100644 --- a/tensorflow/compiler/xla/tests/test_utils_test.cc +++ b/tensorflow/compiler/xla/tests/test_utils_test.cc @@ -175,5 +175,28 @@ ENTRY %sort.148.1589 (parameter.0: s32[1048576], parameter.1: s32[1048576]) -> ( } } +XLA_TEST_F(TestUtilsTest, NoDuplicatesBfloat16) { + // Inputs which are sort keys in key/value sorts should have no duplicates. + auto module = ParseHloString(R"( +HloModule sort, is_scheduled=true + +ENTRY %sort. (parameter.0: bf16[2,1452], parameter.1: s32[2,1452]) -> (bf16[2,1452], s32[2,1452]) { + %parameter.0 = bf16[2,1452]{1,0} parameter(0) + %parameter.1 = s32[2,1452]{1,0} parameter(1) + ROOT %sort = (bf16[2,1452]{1,0}, s32[2,1452]{1,0}) sort(bf16[2,1452]{1,0} %parameter.0, s32[2,1452]{1,0} %parameter.1), dimensions={1} +} +)") + .ValueOrDie(); + TF_ASSERT_OK_AND_ASSIGN(std::vector args, + MakeFakeArguments(module.get())); + ASSERT_EQ(args.size(), 2); + const Literal& key_arg = args[0]; + + absl::flat_hash_set key_set; + for (const bfloat16& value : key_arg.data()) { + EXPECT_TRUE(key_set.insert(absl::bit_cast(value)).second); + } +} + } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/tests/token_hlo_test.cc b/tensorflow/compiler/xla/tests/token_hlo_test.cc index a2b7c26331..601c6b0693 100644 --- a/tensorflow/compiler/xla/tests/token_hlo_test.cc +++ b/tensorflow/compiler/xla/tests/token_hlo_test.cc @@ -16,6 +16,7 @@ limitations under the License. #include #include "absl/strings/str_cat.h" +#include "tensorflow/compiler/xla/service/hlo_parser.h" #include "tensorflow/compiler/xla/service/hlo_verifier.h" #include "tensorflow/compiler/xla/tests/hlo_test_base.h" #include "tensorflow/compiler/xla/tests/test_macros.h" @@ -108,26 +109,6 @@ XLA_TEST_F(TokenHloTest, InvalidTupleTokenShapedEntryParameter) { ::testing::HasSubstr("Entry parameter 0 is or contains a token shape")); } -XLA_TEST_F(TokenHloTest, InvalidOperandToTokenInstruction) { - std::unique_ptr module = CreateNewUnverifiedModule(); - auto builder = HloComputation::Builder(TestName()); - auto param = builder.AddInstruction( - HloInstruction::CreateParameter(0, ShapeUtil::MakeShape(F32, {}), "p0")); - builder.AddInstruction(HloInstruction::CreateAfterAll({param})); - builder.AddInstruction( - HloInstruction::CreateConstant(LiteralUtil::CreateR0(123))); - module->AddEntryComputation(builder.Build()); - - Status status = - HloVerifier(/*layout_sensitive=*/false, /*allow_mixed_precision=*/false) - .Run(module.get()) - .status(); - ASSERT_IS_NOT_OK(status); - EXPECT_THAT(status.error_message(), - ::testing::HasSubstr( - "Operands of token instructions must be TOKEN types")); -} - XLA_TEST_F(TokenHloTest, TokenInWhileLoop) { // Thread a token around a while loop. Token is created and consumed by a // AfterAll instruction in the while body. @@ -220,5 +201,95 @@ ENTRY %TokenInConditional (param.3: pred[]) -> s32[] { } } +XLA_TEST_F(TokenHloTest, AddDependency) { + string module_string = R"( +HloModule AddDependency, is_scheduled=true + +// Computes (p0 + 42) * (-p1) +// where there is a dependency from the add to the negation using a token +// with after-all and add-dependency instructions. +ENTRY %AddDependency (p0: f32[], p1: f32[]) -> f32[] { + %p0 = f32[] parameter(0) + %p1 = f32[] parameter(1) + + %forty_two = f32[] constant(42.0) + %add = f32[] add(f32[] %p0, f32[] %forty_two) + %token = token[] after-all(f32[] %add) + %p1_after_token = f32[] add-dependency(f32[] %p1, token[] %token) + %neg = f32[] negate(f32[] %p1_after_token) + ROOT %product = f32[] multiply(f32[] %add, f32[] %neg) +} +)"; + TF_ASSERT_OK_AND_ASSIGN( + std::unique_ptr module, + ParseHloString(module_string, GetModuleConfigForTest())); + auto p0 = LiteralUtil::CreateR0(10.0); + auto p1 = LiteralUtil::CreateR0(3.0); + auto expected = LiteralUtil::CreateR0(-156.0); + EXPECT_EQ(expected, ExecuteNoHloPasses(std::move(module), {&p0, &p1})); +} + +XLA_TEST_F(TokenHloTest, AddDependencyOfConstant) { + string module_string = R"( +HloModule AddDependencyOfConstant, is_scheduled=true + +ENTRY %AddDependency (p0: f32[]) -> f32[] { + %p0 = f32[] parameter(0) + %forty_two = f32[] constant(42.0) + %token = token[] after-all(f32[] %p0) + %forty_two_after_token = f32[] add-dependency(f32[] %forty_two, token[] %token) + ROOT %product = f32[] multiply(f32[] %p0, f32[] %forty_two_after_token) +} +)"; + TF_ASSERT_OK_AND_ASSIGN( + std::unique_ptr module, + ParseHloString(module_string, GetModuleConfigForTest())); + auto p0 = LiteralUtil::CreateR0(10.0); + auto expected = LiteralUtil::CreateR0(420.0); + EXPECT_EQ(expected, ExecuteNoHloPasses(std::move(module), {&p0})); +} + +XLA_TEST_F(TokenHloTest, AddDependencyAsRoot) { + string module_string = R"( +HloModule AddDependencyAsRoot, is_scheduled=true +ENTRY %AddDependency (p: f32[3]) -> f32[3] { + %p = f32[3] parameter(0) + %neg = f32[3] negate(f32[3] %p) + %token = token[] after-all() + ROOT %add_dep = f32[3] add-dependency(f32[3] %neg, token[] %token) +} +)"; + TF_ASSERT_OK_AND_ASSIGN( + std::unique_ptr module, + ParseHloString(module_string, GetModuleConfigForTest())); + auto input = LiteralUtil::CreateR1({1.0, 3.0, 7.0}); + auto expected = LiteralUtil::CreateR1({-1.0, -3.0, -7.0}); + EXPECT_EQ(expected, ExecuteNoHloPasses(std::move(module), {&input})); +} + +XLA_TEST_F(TokenHloTest, TupleShapedAddDependency) { + string module_string = R"( +HloModule TupleShapedAddDependency, is_scheduled=true +ENTRY %TupleShapedAddDependency (p0: f32[3], p1: f32[3]) -> f32[3] { + %p0 = f32[3] parameter(0) + %p1 = f32[3] parameter(1) + %forty_two = f32[] constant(42.0) + %token = token[] after-all() + %tuple = (f32[3], token[], f32[3], f32[]) tuple(f32[3] %p0, token[] %token, f32[3] %p1, f32[] %forty_two) + %add_dep = (f32[3], token[], f32[3], f32[]) add-dependency((f32[3], token[], f32[3], f32[]) %tuple, token[] %token) + %elem0 = f32[3] get-tuple-element((f32[3], token[], f32[3], f32[]) %add_dep), index=0 + %elem2 = f32[3] get-tuple-element((f32[3], token[], f32[3], f32[]) %add_dep), index=2 + ROOT %diff = f32[3] subtract(f32[3] %elem0, f32[3] %elem2) +} +)"; + TF_ASSERT_OK_AND_ASSIGN( + std::unique_ptr module, + ParseHloString(module_string, GetModuleConfigForTest())); + auto p0 = LiteralUtil::CreateR1({3.0, 3.0, 47.0}); + auto p1 = LiteralUtil::CreateR1({1.0, -2.0, 2.0}); + auto expected = LiteralUtil::CreateR1({2.0, 5.0, 45.0}); + EXPECT_EQ(expected, ExecuteNoHloPasses(std::move(module), {&p0, &p1})); +} + } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc b/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc index ca036f1ae0..e57d072a06 100644 --- a/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc +++ b/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc @@ -157,10 +157,12 @@ void ExecuteAndFetchProfile(string* profile_output, LocalClient* client, TF_ASSERT_OK(transfer_manager->TransferLiteralToDevice( stream_ptr.get(), Literal::CreateFromShape(rhs_arg_shape), rhs_arg)); + ExecutableBuildOptions build_options; + build_options.mutable_debug_options()->set_xla_hlo_profile(true); TF_ASSERT_OK_AND_ASSIGN( std::unique_ptr local_executable, client->Compile(computation, {&lhs_arg_shape, &rhs_arg_shape}, - ExecutableBuildOptions().set_hlo_profile(true))); + build_options)); Executable* executable = local_executable->executable(); HloExecutionProfile hlo_execution_profile( @@ -208,7 +210,7 @@ XLA_TEST_F(HloProfileTest, ProfileSingleComputation) { string profile_output; ExecuteAndFetchProfile(&profile_output, client, computation, lhs_shape, rhs_shape); - + VLOG(4) << "Profile Output:\n" << profile_output; std::vector profile_output_lines = absl::StrSplit(profile_output, '\n'); diff --git a/tensorflow/compiler/xla/tools/replay_computation.cc b/tensorflow/compiler/xla/tools/replay_computation.cc index 47be9f5adf..ff2c339992 100644 --- a/tensorflow/compiler/xla/tools/replay_computation.cc +++ b/tensorflow/compiler/xla/tools/replay_computation.cc @@ -82,13 +82,17 @@ struct Options { std::unique_ptr CompileExecutable(const HloSnapshot& module, LocalClient* client) { XlaComputation computation(module.hlo().hlo_module()); - std::vector argument_layouts; - for (const auto& param : + std::vector argument_layouts; + argument_layouts.reserve( + computation.proto().host_program_shape().parameters_size()); + std::vector argument_layout_ptrs; + for (const ShapeProto& param : computation.proto().host_program_shape().parameters()) { - argument_layouts.push_back(¶m); + argument_layouts.push_back(Shape(param)); + argument_layout_ptrs.push_back(&argument_layouts.back()); } return client - ->Compile(computation, argument_layouts, ExecutableBuildOptions()) + ->Compile(computation, argument_layout_ptrs, ExecutableBuildOptions()) .ValueOrDie(); } @@ -149,7 +153,7 @@ StatusOr ReplayComputation(const HloSnapshot& module, << "--generate_fake_infeed only works if the model has 0 or 1 " "infeed ops, but this one has >= 2."; provide_infeed = true; - infeed_shape = instruction.shape(); + infeed_shape = Shape(instruction.shape()); LOG(INFO) << "Generating fake infeed shape for inferred shape: " << ShapeUtil::HumanString(infeed_shape); } @@ -315,9 +319,10 @@ int RealMain(absl::Span args, const Options& opts) { if (snapshot.has_result()) { Literal literal = Literal::CreateFromProto(snapshot.result()).ConsumeValueOrDie(); - fprintf(stdout, "was %s:%s\n", - ShapeUtil::HumanString(snapshot.result().shape()).c_str(), - literal.ToString().c_str()); + fprintf( + stdout, "was %s:%s\n", + ShapeUtil::HumanString(Shape(snapshot.result().shape())).c_str(), + literal.ToString().c_str()); } } } diff --git a/tensorflow/compiler/xla/util.h b/tensorflow/compiler/xla/util.h index 8ce7416474..6722641e9d 100644 --- a/tensorflow/compiler/xla/util.h +++ b/tensorflow/compiler/xla/util.h @@ -152,6 +152,13 @@ static inline absl::Span AsInt64Slice( slice.size()); } +// TODO(b/29771030): This nop overload was added to simplify the migration of +// Shape from a proto to a C++ class. Remove after class has been migrated. +static inline absl::Span AsInt64Slice( + absl::Span slice) { + return slice; +} + // As above, but for uint64 types. static inline absl::Span AsUInt64Slice( const tensorflow::protobuf::RepeatedField& v) { @@ -387,6 +394,19 @@ T CeilOfRatio(T dividend, T divisor) { return tensorflow::MathUtil::CeilOfRatio(dividend, divisor); } +template +std::vector ElementWiseCeilOfRatio(absl::Span dividends, + absl::Span divisors) { + std::vector ceil_of_ratios; + CHECK_EQ(dividends.size(), divisors.size()); + ceil_of_ratios.reserve(dividends.size()); + absl::c_transform(dividends, divisors, std::back_inserter(ceil_of_ratios), + [](const T dividend, const T divisor) { + return CeilOfRatio(dividend, divisor); + }); + return ceil_of_ratios; +} + // Rounds the value up to a multiple of the divisor by first calling CeilOfRatio // then multiplying by the divisor. For example: RoundUpToNearest(13, 8) => 16 template diff --git a/tensorflow/compiler/xla/window_util.cc b/tensorflow/compiler/xla/window_util.cc index 8ea8dbab25..f113a705b4 100644 --- a/tensorflow/compiler/xla/window_util.cc +++ b/tensorflow/compiler/xla/window_util.cc @@ -185,6 +185,17 @@ bool HasWindowReversal(const Window& window) { return false; } +bool AllOrNoneReversed(const Window& window) { + if (window.dimensions().size() == 0) { + return true; + } + bool reversed = window.dimensions()[0].window_reversal(); + return std::all_of(window.dimensions().begin(), window.dimensions().end(), + [&](const WindowDimension& dim) { + return dim.window_reversal() == reversed; + }); +} + bool HasDilation(const Window& window) { return HasBaseDilation(window) || HasWindowDilation(window); } diff --git a/tensorflow/compiler/xla/window_util.h b/tensorflow/compiler/xla/window_util.h index 1fb9e855fc..099d7ecdd5 100644 --- a/tensorflow/compiler/xla/window_util.h +++ b/tensorflow/compiler/xla/window_util.h @@ -56,6 +56,7 @@ bool HasWindowDilation(const Window& window); bool HasDilation(const Window& window); bool HasWindowReversal(const Window& window); +bool AllOrNoneReversed(const Window& window); // Returns true if the given logical dimension is inactive in the sense that it // has window bound 1, no striding and no padding. diff --git a/tensorflow/compiler/xla/xla.proto b/tensorflow/compiler/xla/xla.proto index 28df3b03f3..bdeb1728fa 100644 --- a/tensorflow/compiler/xla/xla.proto +++ b/tensorflow/compiler/xla/xla.proto @@ -193,7 +193,11 @@ message DebugOptions { // - Assuming that operations never produce or consume NaN or +/- Inf. // - Assuming that +0 and -0 are indistinguishable. bool xla_cpu_enable_fast_math = 99; - bool xla_gpu_enable_fast_math = 100; + + // When true we lower the Minimum and Maximum hlos in the GPU backend such + // that Min(NotNaN, NaN) = Min(NaN, NotNaN) = NotNaN. In other words, if flag + // this is true we don't propagate NaNs through Min and Max. + bool xla_gpu_enable_fast_min_max = 100; // Crashes the program when any kind of verification fails, instead of just // logging the failures. One example is cross checking of convolution results @@ -224,7 +228,7 @@ message ExecutionOptions { // may be faster when using this layout. // // We use a Shape here to accommodate computations that return a tuple. - Shape shape_with_output_layout = 2; + ShapeProto shape_with_output_layout = 2; // Used to seed random-number generators used in this computation. If this is // 0, we generate a seed ourselves. @@ -253,7 +257,7 @@ message TransferToClientRequest { // This optional field directs the service to return the literal in this // layout. A shape is used to hold the layout to accommodate tuples. - Shape shape_with_layout = 2; + ShapeProto shape_with_layout = 2; } message TransferToClientResponse { @@ -281,7 +285,7 @@ message TransferToInfeedResponse { message TransferFromOutfeedRequest { // This optional field directs the service to return the literal in this // layout. A shape is used to hold the layout to accommodate tuples. - Shape shape_with_layout = 1; + ShapeProto shape_with_layout = 1; int64 replica_id = 2; DeviceHandle device_handle = 3; @@ -332,7 +336,7 @@ message CompileRequest { // The layouts of the input arguments. If not set, the default layout will be // used. Although the real arguments are not needed in compilation, the // layouts of the arguments can affect the compilation. - repeated Shape input_shape_with_layout = 3; + repeated ShapeProto input_shape_with_layout = 3; } message CompileResponse { @@ -406,7 +410,7 @@ message LoadDataRequest { string columnio_field = 2; // Individual element shape, excluding rows. - Shape element_shape = 3; + ShapeProto element_shape = 3; // Warning: ColumnIO does not support random-access, so use offset with // caution in performance-critical scenarios. @@ -422,7 +426,7 @@ message LoadDataRequest { message LoadDataResponse { GlobalDataHandle data = 1; - Shape data_shape = 2; + ShapeProto data_shape = 2; int64 available_rows = 3; int64 rows_loaded = 4; int64 nanoseconds = 5; @@ -433,7 +437,7 @@ message GetShapeRequest { } message GetShapeResponse { - Shape shape = 1; + ShapeProto shape = 1; } message UnpackRequest { diff --git a/tensorflow/compiler/xla/xla_data.proto b/tensorflow/compiler/xla/xla_data.proto index 683ccc40f1..85ec83437a 100644 --- a/tensorflow/compiler/xla/xla_data.proto +++ b/tensorflow/compiler/xla/xla_data.proto @@ -108,6 +108,16 @@ enum Format { SPARSE = 2; } +// Describes a tile used in tiling-based layout. Refer to +// g3doc/layout_with_tiling.md for details about tiling-based layout. +message Tile { + // Number of elements in each dimension of the tile. It's ordered from the + // most major dimension of the tile to the most minor dimension of the tile. + // The dimensions correspond to a suffix of the dimensions of the shape being + // tiled. + repeated int64 dimensions = 1; +} + // A layout describes how the array is placed in (1D) memory space. This // includes the minor-to-major ordering of dimensions within a shape. // @@ -138,6 +148,20 @@ message Layout { // memory. This field must be unset unless the format is SPARSE. int64 max_sparse_elements = 5; + // A sequence of tiles, starting from the tile that's applied first to the + // Shape. + // + // TODO(b/119839262): implement tiling in each backend or add Unimplemented + // error. + repeated Tile tiles = 6; + + // Bit size of each element. If the size is bigger than what the element + // type requires, the value is stored in the least significant + // bits and the additional most significant bits are filled with 0's. + // + // TODO(b/119839262): implement in each backend or add Unimplemented error. + int64 element_size_in_bits = 7; + // Important: if any field is added, be sure to modify ShapeUtil::Equal() and // LayoutUtil::Hash appropriately to account for the new field. } @@ -154,7 +178,7 @@ message Layout { // See the XLA documentation for more information on shapes and layouts. // // LINT.IfChange -message Shape { +message ShapeProto { reserved 1; reserved "rank"; @@ -169,7 +193,7 @@ message Shape { repeated int64 dimensions = 3; // For tuples only, the shapes of constitutent shapes in the tuple sequence. - repeated Shape tuple_shapes = 4; + repeated ShapeProto tuple_shapes = 4; // The layout used to back this shape. Layout layout = 5; @@ -183,9 +207,9 @@ message Shape { // Shape of the parameters and output of a computation (like a traditional // function signature). -message ProgramShape { - repeated Shape parameters = 1; - Shape result = 2; +message ProgramShapeProto { + repeated ShapeProto parameters = 1; + ShapeProto result = 2; repeated string parameter_names = 3; } @@ -320,7 +344,7 @@ message DeviceAssignmentProto { // Transfers to/from the client are encoded in literal form, and the structure // of the repeated fields is implied by the shape. message LiteralProto { - Shape shape = 1; + ShapeProto shape = 1; repeated bool preds = 2; bytes s8s = 15; bytes u8s = 3; @@ -521,7 +545,7 @@ message OpSharding { } Type type = 1; // The shape of the sharded tile. - Shape tile_shape = 2; + ShapeProto tile_shape = 2; // The shape of the tile assignment tensor - this must be the same rank as // tile_shape and the product of its dimensions must equal // tile_assignment_devices.size(). diff --git a/tensorflow/compiler/xrt/BUILD b/tensorflow/compiler/xrt/BUILD index 2ff97914f8..2dae746d03 100644 --- a/tensorflow/compiler/xrt/BUILD +++ b/tensorflow/compiler/xrt/BUILD @@ -22,6 +22,7 @@ xla_proto_library( deps = [ "//tensorflow/compiler/tf2xla:host_compute_metadata_proto", "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/compiler/xla:xla_proto", "//tensorflow/compiler/xla/service:hlo_proto", ], ) @@ -32,20 +33,25 @@ cc_library( "xrt_compilation_cache.cc", "xrt_device.cc", "xrt_state.cc", + "xrt_util.cc", ], hdrs = [ "xrt_compilation_cache.h", "xrt_device.h", "xrt_state.h", + "xrt_util.h", ], deps = [ "//tensorflow/compiler/jit:xla_device", "//tensorflow/compiler/tf2xla:xla_compiler", + "//tensorflow/compiler/xla:debug_options_flags", "//tensorflow/compiler/xla:literal", "//tensorflow/compiler/xla:shape_util", "//tensorflow/compiler/xla:status_macros", "//tensorflow/compiler/xla:statusor", + "//tensorflow/compiler/xla:types", "//tensorflow/compiler/xla:xla_data_proto", + "//tensorflow/compiler/xla:xla_proto", "//tensorflow/compiler/xla/client:local_client", "//tensorflow/compiler/xla/service:backend", "//tensorflow/compiler/xla/service:device_memory_allocator", diff --git a/tensorflow/compiler/xrt/kernels/xrt_compile_ops.cc b/tensorflow/compiler/xrt/kernels/xrt_compile_ops.cc index dc62cf7a6b..2ccdf0f02d 100644 --- a/tensorflow/compiler/xrt/kernels/xrt_compile_ops.cc +++ b/tensorflow/compiler/xrt/kernels/xrt_compile_ops.cc @@ -33,6 +33,7 @@ limitations under the License. #include "tensorflow/compiler/xrt/xrt.pb.h" #include "tensorflow/compiler/xrt/xrt_compilation_cache.h" #include "tensorflow/compiler/xrt/xrt_device.h" +#include "tensorflow/compiler/xrt/xrt_util.h" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/framework/resource_mgr.h" #include "tensorflow/core/framework/tensor.h" @@ -108,19 +109,26 @@ Status XRTCompileOp::Compile(OpKernelContext* ctx, TF_ASSIGN_OR_RETURN(xla::XlaComputation computation, client->LoadSnapshot(computation_proto.hlo_snapshot())); - std::vector argument_layouts( + std::vector argument_layouts( + config.program_shape().parameters_size()); + std::vector argument_layout_ptrs( config.program_shape().parameters_size()); for (int i = 0; i < config.program_shape().parameters_size(); ++i) { - argument_layouts[i] = &config.program_shape().parameters(i); + argument_layouts[i] = xla::Shape(config.program_shape().parameters(i)); + argument_layout_ptrs[i] = &argument_layouts[i]; } xla::ExecutableBuildOptions build_options; build_options.set_device_ordinal(client->default_device_ordinal()); - build_options.set_result_layout(config.program_shape().result()); + build_options.set_result_layout(xla::Shape(config.program_shape().result())); build_options.set_device_allocator(device_ref.backend()->memory_allocator()); + if (config.has_debug_options()) { + *build_options.mutable_debug_options() = + BuildXlaDebugOptions(config.debug_options()); + } VLOG(1) << "Building executable"; auto compile_result = - client->Compile(computation, argument_layouts, build_options); + client->Compile(computation, argument_layout_ptrs, build_options); if (!compile_result.ok()) { return compile_result.status(); } @@ -174,11 +182,12 @@ void XRTCompileOp::Compute(OpKernelContext* ctx) { ctx->set_output(0, handle_output); xla::LocalExecutable* executable = entry->get().get_executable(); - xla::ProgramShape program_shape = executable->executable() - ->module() - .config() - .entry_computation_layout() - .ComputeProgramShape(); + xla::ProgramShapeProto program_shape = executable->executable() + ->module() + .config() + .entry_computation_layout() + .ComputeProgramShape() + .ToProto(); Tensor program_shape_output(DT_STRING, TensorShape({1})); program_shape_output.vec()(0) = program_shape.SerializeAsString(); ctx->set_output(1, program_shape_output); diff --git a/tensorflow/compiler/xrt/kernels/xrt_execute_op.cc b/tensorflow/compiler/xrt/kernels/xrt_execute_op.cc index 8c6191ddc0..751329eefc 100644 --- a/tensorflow/compiler/xrt/kernels/xrt_execute_op.cc +++ b/tensorflow/compiler/xrt/kernels/xrt_execute_op.cc @@ -228,14 +228,35 @@ Status XRTExecuteOp::DoWork(OpKernelContext* context) { TF_RETURN_IF_ERROR(XRTTupleAllocation::CreateFromBuffer( shaped_buffer, device_ref.backend(), device_ref.device_ordinal(), &output_tuple)); - - Tensor* output_tensor; - TF_RETURN_IF_ERROR( - context->allocate_output(0, TensorShape({}), &output_tensor)); - int64 key; - TF_RETURN_IF_ERROR(output_tuple->Intern(rm, &key)); - output_tensor->scalar()() = key; - + if (config_proto.return_exploded_tuple() && + xla::ShapeUtil::IsTuple(output_tuple->on_device_shape())) { + int64 tuple_element_count = + xla::ShapeUtil::TupleElementCount(output_tuple->on_device_shape()); + Tensor* output_tensor; + TF_RETURN_IF_ERROR(context->allocate_output( + 0, TensorShape({tuple_element_count}), &output_tensor)); + + for (int64 i = 0; i < tuple_element_count; ++i) { + xla::ShapeIndex shape_index; + shape_index.push_back(i); + + XRTTupleAllocation* suballocation; + TF_RETURN_IF_ERROR(XRTTupleAllocation::MakeSubBuffer( + output_tuple, shape_index, &suballocation, + /*alias_parent_allocation=*/false)); + int64 key; + TF_RETURN_IF_ERROR(suballocation->Intern(rm, &key)); + output_tensor->vec()(i) = key; + } + output_tuple->Unref(); + } else { + Tensor* output_tensor; + TF_RETURN_IF_ERROR( + context->allocate_output(0, TensorShape({}), &output_tensor)); + int64 key; + TF_RETURN_IF_ERROR(output_tuple->Intern(rm, &key)); + output_tensor->scalar()() = key; + } return Status::OK(); } diff --git a/tensorflow/compiler/xrt/kernels/xrt_state_ops.cc b/tensorflow/compiler/xrt/kernels/xrt_state_ops.cc index ffea592491..3258286c10 100644 --- a/tensorflow/compiler/xrt/kernels/xrt_state_ops.cc +++ b/tensorflow/compiler/xrt/kernels/xrt_state_ops.cc @@ -87,6 +87,19 @@ REGISTER_KERNEL_BUILDER(Name("XRTReadLiteral") .HostMemory("literal"), XRTReadLiteralOp); +REGISTER_KERNEL_BUILDER(Name("XRTWriteLiteral") + .Device(DEVICE_XLA_GPU) + .HostMemory("handle") + .HostMemory("literal") + .HostMemory("output_handle"), + XRTWriteLiteralOp); +REGISTER_KERNEL_BUILDER(Name("XRTWriteLiteral") + .Device(DEVICE_XLA_CPU) + .HostMemory("handle") + .HostMemory("literal") + .HostMemory("output_handle"), + XRTWriteLiteralOp); + REGISTER_KERNEL_BUILDER(Name("XRTReadLiteralAndRelease") .Device(DEVICE_XLA_GPU) .HostMemory("handle") diff --git a/tensorflow/compiler/xrt/kernels/xrt_state_ops.h b/tensorflow/compiler/xrt/kernels/xrt_state_ops.h index 54b06558ad..26a58fa42d 100644 --- a/tensorflow/compiler/xrt/kernels/xrt_state_ops.h +++ b/tensorflow/compiler/xrt/kernels/xrt_state_ops.h @@ -393,6 +393,56 @@ class XRTReadLiteralOp : public OpKernel { } }; +// Op that writes a new literal value into device-resident memory. +template +class XRTWriteLiteralOp : public OpKernel { + public: + explicit XRTWriteLiteralOp(OpKernelConstruction* ctx) : OpKernel(ctx) {} + ~XRTWriteLiteralOp() override = default; + XRTWriteLiteralOp(const XRTWriteLiteralOp&) = delete; + XRTWriteLiteralOp& operator=(const XRTWriteLiteralOp&) = delete; + + void Compute(OpKernelContext* ctx) override { + VLOG(1) << "XRTWriteLiteralOp::Compute"; + + const Tensor& handle_tensor = ctx->input(0); + OP_REQUIRES( + ctx, TensorShapeUtils::IsScalar(handle_tensor.shape()), + errors::Internal("computation input should be an int64 scalar")); + int64 allocation_handle = handle_tensor.scalar()(); + + const Tensor& literal_info = ctx->input(1); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(literal_info.shape()), + errors::Internal("literal input should be a string scalar")); + xla::LiteralProto literal_proto; + OP_REQUIRES(ctx, + literal_proto.ParseFromString(literal_info.scalar()()), + errors::InvalidArgument( + "Unable to parse allocation input to LiteralProto")); + xla::Literal literal; + OP_REQUIRES_OK(ctx, XRTStateHelpers::MakeLiteral(literal_proto, &literal)); + + ResourceMgr* rm; + OP_REQUIRES_OK(ctx, DeviceAccessor::GetResourceManager(ctx, &rm)); + + XRTTupleAllocation* allocation; + OP_REQUIRES_OK( + ctx, XRTTupleAllocation::Lookup(rm, allocation_handle, &allocation)); + core::ScopedUnref allocation_unref(allocation); + // We are guaranteed that the underlying device object won't be deleted out + // from under us, while the ScopedRef is live. + typename DeviceAccessor::ScopedRef device_ref; + OP_REQUIRES_OK(ctx, DeviceAccessor::InitScopedRef( + ctx, allocation->device_ordinal(), &device_ref)); + OP_REQUIRES_OK(ctx, + allocation->WriteLiteral(device_ref.backend(), literal)); + + Tensor output(DT_INT64, TensorShape({})); + output.scalar()() = allocation_handle; + ctx->set_output(0, output); + } +}; + // Op that discards a handle to device memory. template class XRTReleaseAllocationOp : public OpKernel { diff --git a/tensorflow/compiler/xrt/ops/xrt_state_ops.cc b/tensorflow/compiler/xrt/ops/xrt_state_ops.cc index 07d025ce34..a3d63106fa 100644 --- a/tensorflow/compiler/xrt/ops/xrt_state_ops.cc +++ b/tensorflow/compiler/xrt/ops/xrt_state_ops.cc @@ -95,6 +95,20 @@ Copies an allocated tuple from device memory and returns it as a literal. 'literal' is a serialized xla::LiteralProto proto. )"); +REGISTER_OP("XRTWriteLiteral") + .Input("handle: int64") + .Input("literal: string") + .Output("output_handle: int64") + .SetShapeFn(tensorflow::shape_inference::ScalarShape) + .Doc( + R"( +Copies the input literal into the device memory pointed to by handle. +Returns the handle itself. + +'handle' is the id returned from the Op that produced the on-device allocation. +'literal' is a serialized xla::LiteralProto proto to be written to device memory. +)"); + REGISTER_OP("XRTReadLiteralAndRelease") .Input("handle: int64") .Output("literal: string") diff --git a/tensorflow/compiler/xrt/tests/raw_api_test.cc b/tensorflow/compiler/xrt/tests/raw_api_test.cc index 25464b5554..abaa17e50e 100644 --- a/tensorflow/compiler/xrt/tests/raw_api_test.cc +++ b/tensorflow/compiler/xrt/tests/raw_api_test.cc @@ -102,7 +102,7 @@ bool CompareLiteralProtos(const xla::LiteralProto& a, auto l_b = xla::Literal::CreateFromProto(b).ValueOrDie(); bool equal = l_a == l_b; if (!equal) { - LOG(INFO) << "LiteralProtos don't match " << a.DebugString() + LOG(INFO) << "LiteralProtos don't match: " << a.DebugString() << " != " << b.DebugString(); } return equal; @@ -175,6 +175,18 @@ xla::XlaComputation AddAndTuple() { return builder.Build().ValueOrDie(); } +xla::XlaComputation AddAndSubTuple() { + xla::XlaBuilder builder("AddAndSubTuple"); + auto p0 = xla::Parameter(&builder, 0, xla::ShapeUtil::MakeShape(xla::F32, {}), + "P0"); + auto p1 = xla::Parameter(&builder, 1, xla::ShapeUtil::MakeShape(xla::F32, {}), + "P1"); + auto sum = xla::Add(p0, p1); + auto sub = xla::Sub(p0, p1); + xla::Tuple(&builder, {sum, sub}); + return builder.Build().ValueOrDie(); +} + void StoreComputationSnapshot(const xla::XlaComputation& computation, xla::HloSnapshot* dst) { auto snapshot = computation.Snapshot().ValueOrDie(); @@ -203,6 +215,56 @@ xla::ProgramShape XlaCompiledProgramShape( ->ComputeProgramShape(); } +TEST(RawApiTest, AllocAndRewrite) { + xrt::XLAAllocation alloc; + alloc.set_device_ordinal(0); + *alloc.mutable_value() = + xla::LiteralUtil::CreateR2({{4, 5}, {6, 7}}).ToProto(); + + Scope root = Scope::NewRootScope().WithDevice(DeviceFromFlag()); + auto value = + ops::Const(root.WithDevice("/device:CPU:0"), alloc.SerializeAsString()); + auto handle = ops::XRTAllocate(root, value); + auto read_back = ops::XRTReadLiteral(root, handle); + TF_ASSERT_OK(root.status()); + + tensorflow::ClientSession session(root); + std::vector outputs; + TF_EXPECT_OK(session.Run({read_back, handle}, &outputs)); + EXPECT_EQ(outputs.size(), 2); + + int64 allocation_handle = outputs[1].scalar()(); + xla::LiteralProto response; + EXPECT_TRUE(response.ParseFromString(outputs[0].scalar()())); + EXPECT_TRUE(CompareLiteralProtos(alloc.value(), response)); + outputs.clear(); + + xla::LiteralProto new_literal = + xla::LiteralUtil::CreateR2({{9, 2}, {4, 1}}).ToProto(); + auto new_value = ops::Const(root.WithDevice("/device:CPU:0"), + new_literal.SerializeAsString()); + auto write_op = + ops::XRTWriteLiteral(root, Input(allocation_handle), new_value); + TF_ASSERT_OK(root.status()); + TF_EXPECT_OK(session.Run({write_op}, &outputs)); + EXPECT_EQ(outputs.size(), 1); + EXPECT_EQ(allocation_handle, outputs[0].scalar()()); + outputs.clear(); + + auto read_after_write = ops::XRTReadLiteral(root, Input(allocation_handle)); + TF_EXPECT_OK(session.Run({read_after_write}, &outputs)); + EXPECT_EQ(outputs.size(), 1); + + xla::LiteralProto new_response; + EXPECT_TRUE(new_response.ParseFromString(outputs[0].scalar()())); + EXPECT_TRUE(CompareLiteralProtos(new_literal, new_response)); + + auto release = + ops::XRTReleaseAllocationHandle(root, Input(allocation_handle)); + TF_EXPECT_OK(session.Run(tensorflow::ClientSession::FeedType(), {}, {release}, + &outputs)); +} + TEST(RawApiTest, ReadAndWriteState) { xrt::XLAAllocation alloc; alloc.set_device_ordinal(0); @@ -375,9 +437,12 @@ TEST(RawApiTest, CompileAndExecute) { xrt::XLAComputation c; auto config = c.mutable_config(); auto shapes = config->mutable_program_shape(); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {2}); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {2}); - *shapes->mutable_result() = xla::ShapeUtil::MakeShape(xla::F32, {2}); + *shapes->add_parameters() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); + *shapes->add_parameters() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); + *shapes->mutable_result() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); StoreComputationSnapshot(AddAndScale(), c.mutable_hlo_snapshot()); xrt::XRTExecutionConfig e; @@ -411,7 +476,7 @@ TEST(RawApiTest, CompileAndExecute) { auto expected = xla::LiteralUtil::CreateR1({27.0f, 21.0f}); EXPECT_TRUE(CompareLiteralToLiteralProto(expected, response)); - xla::ProgramShape program_shape; + xla::ProgramShapeProto program_shape; EXPECT_TRUE(program_shape.ParseFromString(outputs[1].vec()(0))); EXPECT_EQ(program_shape.parameters_size(), 2); } @@ -427,9 +492,12 @@ TEST(RawApiTest, CompileAndExecuteWithArgumentVector) { xrt::XLAComputation c; auto config = c.mutable_config(); auto shapes = config->mutable_program_shape(); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {2}); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {2}); - *shapes->mutable_result() = xla::ShapeUtil::MakeShape(xla::F32, {2}); + *shapes->add_parameters() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); + *shapes->add_parameters() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); + *shapes->mutable_result() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); StoreComputationSnapshot(AddAndScale(), c.mutable_hlo_snapshot()); xrt::XRTExecutionConfig e; @@ -465,7 +533,7 @@ TEST(RawApiTest, CompileAndExecuteWithArgumentVector) { auto expected = xla::LiteralUtil::CreateR1({27.0f, 21.0f}); EXPECT_TRUE(CompareLiteralToLiteralProto(expected, response)); - xla::ProgramShape program_shape; + xla::ProgramShapeProto program_shape; EXPECT_TRUE(program_shape.ParseFromString(outputs[1].vec()(0))); EXPECT_EQ(program_shape.parameters_size(), 2); } @@ -494,8 +562,8 @@ TEST(RawApiTest, CompileWithXlaReturnShapes) { xrt::XLAComputation c; auto config = c.mutable_config(); auto shapes = config->mutable_program_shape(); - *shapes->add_parameters() = param_shape; - *shapes->mutable_result() = result_shape; + *shapes->add_parameters() = param_shape.ToProto(); + *shapes->mutable_result() = result_shape.ToProto(); StoreComputationSnapshot(xla_computation, c.mutable_hlo_snapshot()); Scope root = Scope::NewRootScope().WithDevice(DeviceFromFlag()); @@ -510,8 +578,9 @@ TEST(RawApiTest, CompileWithXlaReturnShapes) { TF_EXPECT_OK(session.Run(tensorflow::ClientSession::FeedType(), {c_handle.program_shape}, {release}, &outputs)); - xla::ProgramShape program_shape; - EXPECT_TRUE(program_shape.ParseFromString(outputs[0].vec()(0))); + xla::ProgramShapeProto program_shape_proto; + EXPECT_TRUE(program_shape_proto.ParseFromString(outputs[0].vec()(0))); + xla::ProgramShape program_shape(program_shape_proto); EXPECT_EQ(program_shape.parameters_size(), 1); VLOG(2) << "Param: " @@ -520,7 +589,7 @@ TEST(RawApiTest, CompileWithXlaReturnShapes) { << xla::ShapeUtil::HumanStringWithLayout(program_shape.result()); xla::ProgramShape xla_program_shape = - XlaCompiledProgramShape(xla_computation, *shapes); + XlaCompiledProgramShape(xla_computation, xla::ProgramShape(*shapes)); EXPECT_TRUE(xla::LayoutUtil::Equal( xla::ShapeUtil::GetSubshape(program_shape.parameters(0), {0}).layout(), xla::ShapeUtil::GetSubshape(xla_program_shape.parameters(0), {0}) @@ -547,11 +616,11 @@ TEST(RawApiTest, DotGeneralWithLayoutTest) { auto config = c.mutable_config(); auto shapes = config->mutable_program_shape(); *shapes->add_parameters() = - xla::ShapeUtil::MakeShapeWithLayout(xla::F32, {2, 2}, {0, 1}); + xla::ShapeUtil::MakeShapeWithLayout(xla::F32, {2, 2}, {0, 1}).ToProto(); *shapes->add_parameters() = - xla::ShapeUtil::MakeShapeWithLayout(xla::F32, {2, 1}, {0, 1}); + xla::ShapeUtil::MakeShapeWithLayout(xla::F32, {2, 1}, {0, 1}).ToProto(); *shapes->mutable_result() = - xla::ShapeUtil::MakeShapeWithLayout(xla::F32, {2, 1}, {0, 1}); + xla::ShapeUtil::MakeShapeWithLayout(xla::F32, {2, 1}, {0, 1}).ToProto(); StoreComputationSnapshot(Dot(), c.mutable_hlo_snapshot()); xrt::XRTExecutionConfig e; @@ -592,7 +661,7 @@ TEST(RawApiTest, CompileAndExecuteZeroArg) { xrt::XLAComputation c; auto config = c.mutable_config(); auto shapes = config->mutable_program_shape(); - *shapes->mutable_result() = xla::ShapeUtil::MakeShape(xla::F32, {}); + *shapes->mutable_result() = xla::ShapeUtil::MakeShape(xla::F32, {}).ToProto(); xrt::XRTExecutionConfig e; e.set_release_input_handles(true); @@ -632,10 +701,13 @@ TEST(RawApiTest, CompileAndExecuteReturnTuple) { xrt::XLAComputation c; auto config = c.mutable_config(); auto shapes = config->mutable_program_shape(); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {2}); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {2}); - *shapes->mutable_result() = xla::ShapeUtil::MakeTupleShape( - {xla::ShapeUtil::MakeShape(xla::F32, {2})}); + *shapes->add_parameters() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); + *shapes->add_parameters() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); + *shapes->mutable_result() = + xla::ShapeUtil::MakeTupleShape({xla::ShapeUtil::MakeShape(xla::F32, {2})}) + .ToProto(); StoreComputationSnapshot(AddAndTuple(), c.mutable_hlo_snapshot()); xrt::XRTExecutionConfig e; @@ -671,14 +743,81 @@ TEST(RawApiTest, CompileAndExecuteReturnTuple) { EXPECT_TRUE(CompareLiteralToLiteralProto(expected, response)); } +TEST(RawApiTest, CompileAndExecuteReturnExplodedTuple) { + xrt::XLAAllocation p0; + p0.set_device_ordinal(0); + *p0.mutable_value() = xla::LiteralUtil::CreateR0(12.0f).ToProto(); + + xrt::XLAAllocation p1; + p1.set_device_ordinal(0); + *p1.mutable_value() = xla::LiteralUtil::CreateR0(3.0f).ToProto(); + + xrt::XLAComputation c; + auto config = c.mutable_config(); + auto shapes = config->mutable_program_shape(); + *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {}).ToProto(); + *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {}).ToProto(); + *shapes->mutable_result() = + xla::ShapeUtil::MakeTupleShape({xla::ShapeUtil::MakeShape(xla::F32, {}), + xla::ShapeUtil::MakeShape(xla::F32, {})}) + .ToProto(); + StoreComputationSnapshot(AddAndSubTuple(), c.mutable_hlo_snapshot()); + + xrt::XRTExecutionConfig e; + e.set_release_input_handles(true); + e.set_release_compilation_handle(true); + e.set_return_exploded_tuple(true); + + Scope root = Scope::NewRootScope().WithDevice(DeviceFromFlag()); + auto e_config = + ops::Const(root.WithDevice("/device:CPU:0"), e.SerializeAsString()); + auto computation = + ops::Const(root.WithDevice("/device:CPU:0"), c.SerializeAsString()); + auto c_handle = ops::XRTCompile(root, computation); + auto p0_value = + ops::Const(root.WithDevice("/device:CPU:0"), p0.SerializeAsString()); + auto p0_handle = ops::XRTAllocate(root, p0_value); + auto p1_value = + ops::Const(root.WithDevice("/device:CPU:0"), p1.SerializeAsString()); + auto p1_handle = ops::XRTAllocate(root, p1_value); + auto result = ops::XRTExecute(root, c_handle.handle, e_config, + {Output(p0_handle), Output(p1_handle)}); + TF_ASSERT_OK(root.status()); + + ClientSession session(root); + std::vector outputs; + TF_EXPECT_OK(session.Run({result}, &outputs)); + EXPECT_EQ(outputs.size(), 1); + + auto handles_vec = outputs.front().vec(); + EXPECT_EQ(handles_vec.size(), 2); + + const float kResults[2] = {15.0f, 9.0f}; + for (int64 i = 0; i < handles_vec.size(); ++i) { + auto read_back = ops::XRTReadLiteralAndRelease(root, Input(handles_vec(i))); + std::vector voutputs; + TF_EXPECT_OK(session.Run({read_back}, &voutputs)); + EXPECT_EQ(voutputs.size(), 1); + + xla::LiteralProto response; + EXPECT_TRUE(response.ParseFromString(voutputs[0].scalar()())); + + auto expected = xla::LiteralUtil::CreateR0(kResults[i]); + EXPECT_TRUE(CompareLiteralToLiteralProto(expected, response)); + } +} + TEST(RawApiTest, LeakCompilationReference) { xrt::XLAComputation c; auto config = c.mutable_config(); auto shapes = config->mutable_program_shape(); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {2}); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::F32, {2}); - *shapes->mutable_result() = xla::ShapeUtil::MakeTupleShape( - {xla::ShapeUtil::MakeShape(xla::F32, {2})}); + *shapes->add_parameters() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); + *shapes->add_parameters() = + xla::ShapeUtil::MakeShape(xla::F32, {2}).ToProto(); + *shapes->mutable_result() = + xla::ShapeUtil::MakeTupleShape({xla::ShapeUtil::MakeShape(xla::F32, {2})}) + .ToProto(); StoreComputationSnapshot(AddAndTuple(), c.mutable_hlo_snapshot()); Scope root = Scope::NewRootScope().WithDevice(DeviceFromFlag()); @@ -703,9 +842,9 @@ TEST(RawApiTest, CompileAndExecuteWithS64Argument) { xrt::XLAComputation c; auto config = c.mutable_config(); auto shapes = config->mutable_program_shape(); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::S64, {}); - *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::S64, {}); - *shapes->mutable_result() = xla::ShapeUtil::MakeShape(xla::S64, {}); + *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::S64, {}).ToProto(); + *shapes->add_parameters() = xla::ShapeUtil::MakeShape(xla::S64, {}).ToProto(); + *shapes->mutable_result() = xla::ShapeUtil::MakeShape(xla::S64, {}).ToProto(); StoreComputationSnapshot(AddS64(), c.mutable_hlo_snapshot()); xrt::XRTExecutionConfig e; @@ -739,11 +878,11 @@ TEST(RawApiTest, CompileAndExecuteWithS64Argument) { auto expected = xla::LiteralUtil::CreateR0(15123899); EXPECT_TRUE(CompareLiteralToLiteralProto(expected, response)); - xla::ProgramShape program_shape; + xla::ProgramShapeProto program_shape; EXPECT_TRUE(program_shape.ParseFromString(outputs[1].vec()(0))); EXPECT_EQ(program_shape.parameters_size(), 2); - EXPECT_TRUE( - xla::ShapeUtil::HasPrimitiveType(program_shape.result(), xla::S64)); + EXPECT_TRUE(xla::ShapeUtil::HasPrimitiveType( + xla::Shape(program_shape.result()), xla::S64)); } } // namespace diff --git a/tensorflow/compiler/xrt/xrt.proto b/tensorflow/compiler/xrt/xrt.proto index 6ab77fbaaf..378bb9246f 100644 --- a/tensorflow/compiler/xrt/xrt.proto +++ b/tensorflow/compiler/xrt/xrt.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package xrt; import "tensorflow/compiler/tf2xla/host_compute_metadata.proto"; +import "tensorflow/compiler/xla/xla.proto"; import "tensorflow/compiler/xla/xla_data.proto"; import "tensorflow/compiler/xla/service/hlo.proto"; @@ -36,16 +37,18 @@ message XLAComputationConfig { tensorflow.tf2xla.HostComputeMetadata host_compute_metadata = 3; // The arg/result shapes for the whole computation. - xla.ProgramShape program_shape = 4; + xla.ProgramShapeProto program_shape = 4; // The arg/result shapes for each core of a model-parallel // computation. per_core_args_and_result_shapes is optional for a // single-core computation. - repeated xla.ProgramShape per_core_program_shape = 5; + repeated xla.ProgramShapeProto per_core_program_shape = 5; // Describes how replicated computation instances should be assigned to // devices. There are num_cores_per_replica computations, and each one will be // sent and executed to the set of replica device numbers described in the // DeviceAssignment proto. DeviceAssignment device_assignment = 6; + // The debugging options to be passed to the XLA compilation process. + xla.DebugOptions debug_options = 7; } // Options and XLA computation for a compilation. @@ -98,4 +101,8 @@ message XRTExecutionConfig { bool release_input_handles = 5; // If true, release the handle to the computation after running. bool release_compilation_handle = 6; + // If set to true, and the result shape is a tuple, then instead of returning + // a single tuple allocation the execution will return a vector of + // allocations, one for each of the first-level elements of the result tuple. + bool return_exploded_tuple = 7; } diff --git a/tensorflow/compiler/xrt/xrt_state.cc b/tensorflow/compiler/xrt/xrt_state.cc index 3a99820d7a..5c7c537c34 100644 --- a/tensorflow/compiler/xrt/xrt_state.cc +++ b/tensorflow/compiler/xrt/xrt_state.cc @@ -183,6 +183,20 @@ Status XRTTupleAllocation::ToLiteral(xla::Backend* backend, int device_ordinal, return Status::OK(); } +Status XRTTupleAllocation::WriteLiteral(xla::Backend* backend, + const xla::Literal& literal) { + if (!xla::ShapeUtil::Equal(literal.shape(), on_host_shape())) { + return errors::InvalidArgument( + "New literal shape not matching the existing one: literal=", + xla::ShapeUtil::HumanStringWithLayout(literal.shape()), + " device=", xla::ShapeUtil::HumanStringWithLayout(on_host_shape())); + } + auto transfer_manager = backend->transfer_manager(); + TF_ASSIGN_OR_RETURN(auto stream, backend->BorrowStream(device_ordinal())); + return transfer_manager->TransferLiteralToDevice(stream.get(), literal, + ToShapedBuffer()); +} + void XRTTupleAllocation::DiscardAllocation( const xla::ShapeIndex& buffer_index) { buffers_.element(buffer_index)->DiscardAllocation(); diff --git a/tensorflow/compiler/xrt/xrt_state.h b/tensorflow/compiler/xrt/xrt_state.h index 73b5584e38..3664c0cd4e 100644 --- a/tensorflow/compiler/xrt/xrt_state.h +++ b/tensorflow/compiler/xrt/xrt_state.h @@ -137,6 +137,9 @@ class XRTTupleAllocation : public ResourceBase { Status ToLiteral(xla::Backend* backend, int device_ordinal, xla::Literal* literal); + // Write a new literal value to the allocation. + Status WriteLiteral(xla::Backend* backend, const xla::Literal& literal); + // True if none of the buffers in the allocation are aliased by any other live // handle. bool IsExclusiveOwner(); diff --git a/tensorflow/compiler/xrt/xrt_util.cc b/tensorflow/compiler/xrt/xrt_util.cc new file mode 100644 index 0000000000..3ef8bedc73 --- /dev/null +++ b/tensorflow/compiler/xrt/xrt_util.cc @@ -0,0 +1,76 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/compiler/xrt/xrt_util.h" + +#include +#include + +#include "tensorflow/compiler/xla/debug_options_flags.h" +#include "tensorflow/compiler/xla/types.h" +#include "tensorflow/core/platform/logging.h" + +namespace tensorflow { +namespace { + +bool DebugOptionsPassThroughEnabled() { + const char* env = getenv("TF_XLA_DEBUG_OPTIONS_PASSTHROUGH"); + bool enabled = + env != nullptr && (strcmp(env, "1") == 0 || strcmp(env, "true") == 0); + if (enabled) { + LOG(WARNING) << "Passing through XLA debug options!"; + } else { + LOG(WARNING) << "TF_XLA_DEBUG_OPTIONS_PASSTHROUGH not set, not all options " + "will be retained"; + } + return enabled; +} + +string SafeDebugPath(const string& path) { + if (path.empty() || path.compare(0, 5, "gs://") == 0 || + path.compare(0, 11, "bigstore://") == 0) { + return path; + } + LOG(WARNING) << "Invalid config path (will be dropped): " << path; + return string(); +} + +} // namespace + +xla::DebugOptions BuildXlaDebugOptions(const xla::DebugOptions& ref_options) { + static const bool options_passthrough = DebugOptionsPassThroughEnabled(); + if (options_passthrough) { + return ref_options; + } + xla::DebugOptions options = xla::GetDebugOptionsFromFlags(); + options.set_xla_generate_hlo_text_to( + SafeDebugPath(ref_options.xla_generate_hlo_text_to())); + options.set_xla_dump_optimized_hlo_proto_to( + SafeDebugPath(ref_options.xla_dump_optimized_hlo_proto_to())); + options.set_xla_dump_computations_to( + SafeDebugPath(ref_options.xla_dump_computations_to())); + options.set_xla_dump_executions_to( + SafeDebugPath(ref_options.xla_dump_executions_to())); + for (auto& pass : ref_options.xla_disable_hlo_passes()) { + options.add_xla_disable_hlo_passes(pass); + } + options.set_xla_dump_unoptimized_hlo_proto_to( + SafeDebugPath(ref_options.xla_dump_unoptimized_hlo_proto_to())); + options.set_xla_dump_per_pass_hlo_proto_to( + SafeDebugPath(ref_options.xla_dump_per_pass_hlo_proto_to())); + return options; +} + +} // namespace tensorflow diff --git a/tensorflow/compiler/xrt/xrt_util.h b/tensorflow/compiler/xrt/xrt_util.h new file mode 100644 index 0000000000..d9c05a7f34 --- /dev/null +++ b/tensorflow/compiler/xrt/xrt_util.h @@ -0,0 +1,34 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Utility functions in support of the XRT API. + +#ifndef TENSORFLOW_COMPILER_XRT_XRT_UTIL_H_ +#define TENSORFLOW_COMPILER_XRT_XRT_UTIL_H_ + +#include "tensorflow/compiler/xla/xla.pb.h" + +namespace tensorflow { + +// Filters the debug options provided as argument according to the value of the +// TF_XLA_DEBUG_OPTIONS_PASSTHROUGH environment variable. If such variable is +// set to "1" or "true", the debug options will be returned as is. Otherwise +// only a subset of them will be set in the returned ones, and all the paths +// contained in it, will be limited to gs:// and bigstore:// ones. +xla::DebugOptions BuildXlaDebugOptions(const xla::DebugOptions& ref_options); + +} // namespace tensorflow + +#endif // TENSORFLOW_COMPILER_XRT_XRT_UTIL_H_ diff --git a/tensorflow/contrib/all_reduce/BUILD b/tensorflow/contrib/all_reduce/BUILD index a513aa1e7c..f6c6560c1c 100644 --- a/tensorflow/contrib/all_reduce/BUILD +++ b/tensorflow/contrib/all_reduce/BUILD @@ -9,8 +9,6 @@ licenses(["notice"]) # Apache 2.0 exports_files(["LICENSE"]) -load("//tensorflow:tensorflow.bzl", "tf_py_test") - py_library( name = "all_reduce_py", srcs = ["__init__.py"], @@ -29,29 +27,6 @@ py_library( srcs_version = "PY2AND3", visibility = ["//visibility:public"], deps = [ - "//tensorflow/python:array_ops", - "//tensorflow/python:framework_ops", - "//tensorflow/python:math_ops", - "//tensorflow/python:nccl_ops", - ], -) - -tf_py_test( - name = "all_reduce_test", - srcs = ["python/all_reduce_test.py"], - additional_deps = [ - ":all_reduce", - "//third_party/py/numpy", - "//tensorflow/core:protos_all_py", - "//tensorflow/python:array_ops", - "//tensorflow/python:client", - "//tensorflow/python:framework_ops", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:math_ops", - "//tensorflow/python:constant_op", - "//tensorflow/python:client_testlib", - "//tensorflow/python:platform", - "//tensorflow/python:platform_test", - "//tensorflow/python:state_ops", + "//tensorflow/python/distribute:all_reduce", ], ) diff --git a/tensorflow/contrib/all_reduce/python/all_reduce.py b/tensorflow/contrib/all_reduce/python/all_reduce.py index 25f4b4b8d3..238cdaf8a7 100644 --- a/tensorflow/contrib/all_reduce/python/all_reduce.py +++ b/tensorflow/contrib/all_reduce/python/all_reduce.py @@ -18,842 +18,5 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import collections -import math - -from tensorflow.python.framework import device as device_lib -from tensorflow.python.framework import ops -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import nccl_ops - - -def _flatten_tensors(tensors): - """Check tensors for isomorphism and flatten. - - Args: - tensors: list of T `tf.Tensor` which must all have the same shape. - - Returns: - tensors: a list of T `tf.Tensor` which are flattened (1D) views of tensors - shape: the original shape of each element of input tensors - - Raises: - ValueError: tensors are empty or non-isomorphic or have unknown shape. - """ - if not tensors: - raise ValueError("tensors cannot be empty") - shape = tensors[0].shape - for tensor in tensors: - shape = shape.merge_with(tensor.shape) - if not shape.is_fully_defined(): - raise ValueError("Tensors must have statically known shape.") - if len(shape) != 1: - reshaped = [] - for t in tensors: - with ops.colocate_with(t): - reshaped.append(array_ops.reshape(t, [-1])) - tensors = reshaped - return tensors, shape - - -def _reshape_tensors(tensors, shape): - """Reshape tensors flattened by _flatten_tensors. - - Args: - tensors: list of T `tf.Tensor` of identical length 1D tensors. - shape: list of integers describing the desired shape. Product of - the elements must equal the length of each tensor. - - Returns: - list of T `tf.Tensor` which are the reshaped inputs. - """ - reshaped = [] - for t in tensors: - with ops.colocate_with(t): - reshaped.append(array_ops.reshape(t, shape)) - return reshaped - - -def _padded_split(tensor, pieces): - """Like split for 1D tensors but pads-out case where len % pieces != 0. - - Args: - tensor: T `tf.Tensor` that must be 1D. - pieces: a positive integer specifying the number of pieces into which - tensor should be split. - - Returns: - list of T `tf.Tensor` of length pieces, which hold the values of - thin input tensor, in order. The final tensor may - be zero-padded on the end to make its size equal to those of all - of the other tensors. - - Raises: - ValueError: The input tensor is not 1D. - """ - shape = tensor.shape - if 1 != len(shape): - raise ValueError("input tensor must be 1D") - tensor_len = shape.dims[0].value - with ops.colocate_with(tensor): - if tensor_len % pieces != 0: - # pad to an even length - chunk_size = 1 + tensor_len // pieces - if pieces > tensor_len: - # This is an edge case that should not come up in practice, - # i.e. a different reduction algorithm would be better, - # but we'll make it work just for completeness. - pad_len = pieces - tensor_len - extended_whole = array_ops.concat( - [tensor, array_ops.zeros([pad_len], dtype=tensor.dtype)], 0) - parts = array_ops.split(extended_whole, pieces) - return parts, pad_len - elif (pieces - 1) * chunk_size >= tensor_len: - # Another edge case of limited real interest. - pad_len = (pieces * chunk_size) % tensor_len - extended_whole = array_ops.concat( - [tensor, array_ops.zeros([pad_len], dtype=tensor.dtype)], 0) - parts = array_ops.split(extended_whole, pieces) - return parts, pad_len - else: - last_chunk_size = tensor_len - (pieces - 1) * chunk_size - pad_len = chunk_size - last_chunk_size - piece_lens = [chunk_size for _ in range(pieces - 1)] + [last_chunk_size] - parts = array_ops.split(tensor, piece_lens) - parts[-1] = array_ops.concat( - [parts[-1], array_ops.zeros([pad_len], dtype=tensor.dtype)], 0) - return parts, pad_len - else: - return array_ops.split(tensor, pieces), 0 - - -def _strip_padding(tensors, pad_len): - """Strip the suffix padding added by _padded_split. - - Args: - tensors: list of T `tf.Tensor` of identical length 1D tensors. - pad_len: number of elements to be stripped from the end of each tensor. - - Returns: - list of T `tf.Tensor` which are the stripped inputs. - - Raises: - ValueError: tensors must be a non-empty list of 1D tensors, and - each must be longer than pad_len. - """ - if not tensors: - raise ValueError("tensors cannot be empty") - shape = tensors[0].shape - if len(shape) > 1: - raise ValueError("tensors must be 1D") - prefix_len = int(shape[0] - pad_len) - if prefix_len < 0: - raise ValueError("pad_len longer than tensor") - stripped = [] - for t in tensors: - with ops.colocate_with(t): - stripped.append(array_ops.slice(t, [0], [prefix_len])) - return stripped - - -def _ragged_split(tensor, pieces): - """Like split for 1D tensors but allows case where len % pieces != 0. - - Args: - tensor: T `tf.Tensor` that must be 1D. - pieces: a positive integer specifying the number of pieces into which - tensor should be split. - - Returns: - list of T `tf.Tensor` of length pieces, which hold the values of - the input tensor, in order. The final tensor may be shorter - than the others, which will all be of equal length. - - Raises: - ValueError: input tensor must be 1D. - """ - shape = tensor.shape - if 1 != len(shape): - raise ValueError("input tensor must be 1D") - tensor_len = shape.dims[0].value - chunk_size = tensor_len // pieces - with ops.colocate_with(tensor): - if tensor_len != (pieces * chunk_size): - # last piece will be short - assert pieces > 1 - last_chunk_size = tensor_len - ((pieces - 1) * chunk_size) - assert last_chunk_size > 0 - piece_lens = [chunk_size for _ in range(pieces - 1)] + [last_chunk_size] - return array_ops.split(tensor, piece_lens) - else: - return array_ops.split(tensor, pieces) - - -def _ring_permutations(num_workers, num_subchunks, gpu_perm): - """"Generate an array of device index arrays, one for each subchunk. - - In the basic ring reduction algorithm there are size(T)/num_devices - data chunks and each device process one chunk per tick, i.e. sending - one chunk and receiving one chunk. The idea of subchunking is that - each device processes num_subchunks smaller data regions per tick, - and the ring rank permutation is different for each subchunk index - so that a device is potentially sending to and receiving from - num_subchunks different other devices at each tick. Where multiple - independent data channels exist between devices, this strategy - supplies a method of using them in parallel. - - Args: - num_workers: number of worker tasks - num_subchunks: number of subchunks into which to divide each per-GPU chunk. - gpu_perm: an array of integers in [0, num_gpus-1] giving the default - ring order of GPUs at each worker. Other permutations will be generated - by rotating this array and splicing together per-worker instances. - - Raises: - ValueError: the number of subchunks may not exceed the number of GPUs. - - Returns: - pred_by_s_d: list of lists that maps (by index) from (subchunk, dev) to - preceding device in the permutation for that subchunk. The - device index of GPU i at worker j is i + (j * num_gpus). - rank_by_s_d: list of lists that maps (by index) from (subchunk, dev) to - local rank of device d in the permutation for that subchunk. - """ - num_gpus = len(gpu_perm) - devices = num_workers * num_gpus - if devices == 0: - return [], [] - if num_subchunks > num_gpus: - raise ValueError( - "num_subchunks %d must be <= num_gpus %d" % (num_subchunks, num_gpus)) - rotation_interval = max(1, int(num_gpus / num_subchunks)) - perms_by_s = [] - for s in range(0, num_subchunks): - full_order = [] - offset = s * rotation_interval - for w in range(0, num_workers): - default_order = [(w * num_gpus) + i for i in gpu_perm] - dev_order = default_order[offset:] + default_order[:offset] - full_order += dev_order - perms_by_s.append(full_order) - pred_by_s_d = [[-1 for d in range(0, devices)] - for s in range(0, num_subchunks)] - rank_by_s_d = [[-1 for d in range(0, devices)] - for s in range(0, num_subchunks)] - for s in range(0, num_subchunks): - for d in range(0, devices): - for t in range(0, devices): - if d == perms_by_s[s][t]: - rank_by_s_d[s][d] = t - pred_by_s_d[s][d] = perms_by_s[s][(t + devices - 1) % devices] - break - return (pred_by_s_d, rank_by_s_d) - - -def build_ring_all_reduce(input_tensors, num_workers, num_subchunks, - gpu_perm, red_op, un_op=None): - """Construct a subgraph performing a ring-style all-reduce of input_tensors. - - Args: - input_tensors: a list of T `tf.Tensor` objects, which must all - have the same shape and type. - num_workers: number of worker tasks spanned by input_tensors. - num_subchunks: number of subchunks each device should process in one tick. - gpu_perm: a list of ints giving a ring-wise rank ordering of GPUs at - each worker. All workers must have the same number of - GPUs with the same rank ordering. If NVLINK is available, this should - be a ring order supported by NVLINK edges. - red_op: a binary operator for elementwise reduction. - un_op: an optional unary operator to apply to fully reduced values. - - Raises: - ValueError: empty input_tensors or they don't all have same - size. - - Returns: - a list of T `tf.Tensor` identical sum-reductions of input_tensors. - """ - if len(input_tensors) < 2: - raise ValueError("input_tensors must be length 2 or longer") - input_tensors, shape = _flatten_tensors(input_tensors) - devices = [t.device for t in input_tensors] - (pred_by_s_d, rank_by_s_d) = _ring_permutations( - num_workers, num_subchunks, gpu_perm) - chunks_by_dev, pad_len = _build_ring_gather( - input_tensors, devices, - num_subchunks, pred_by_s_d, rank_by_s_d, red_op) - if un_op: - chunks_by_dev = _apply_unary_to_chunks(un_op, chunks_by_dev) - output_tensors = _build_ring_scatter(pred_by_s_d, rank_by_s_d, - chunks_by_dev) - if pad_len > 0: - output_tensors = _strip_padding(output_tensors, pad_len) - if len(shape) != 1: - output_tensors = _reshape_tensors(output_tensors, shape) - return output_tensors - - -def _build_ring_gather(input_tensors, devices, num_subchunks, - pred_by_s_d, rank_by_s_d, red_op): - """Construct a subgraph for the first (reduction) pass of ring all-reduce. - - Args: - input_tensors: a list of T `tf.Tensor` 1D input tensors of same - shape and type. - devices: array of device name strings - num_subchunks: number of subchunks each device should process in one tick. - pred_by_s_d: as produced by _ring_permutations - rank_by_s_d: as produced by _ring_permutations - red_op: a binary operator for elementwise reduction - - Raises: - ValueError: tensors must all be one dimensional. - - Returns: - list of list of T `tf.Tensor` of (partially) reduced values where - exactly num_subchunks chunks at each device are fully reduced. - """ - num_devices = len(input_tensors) - if num_devices == 0: - return [] - if num_devices == 1: - return input_tensors - shape = input_tensors[0].shape - if 1 != len(shape): - raise ValueError("input tensors must be 1D") - num_chunks = num_devices * num_subchunks - num_ticks = num_devices - 1 - # Initialize chunks_by_dev with splits of the input tensors. - chunks_by_dev = [] - split_pad_len = 0 - for d in range(0, num_devices): - with ops.device(devices[d]): - splits, split_pad_len = _padded_split(input_tensors[d], num_chunks) - chunks_by_dev.append(splits) - # Reduction phase - for tick in range(0, num_ticks): - # One new partial reduction for every chunk - new_partial_reductions = [None for _ in range(0, num_chunks)] - # Compute reductions with respect to last tick's values - for d in range(0, num_devices): - with ops.device(devices[d]): - for s in range(0, num_subchunks): - rank = rank_by_s_d[s][d] - seg_index = (rank + num_devices - (2 + tick)) % num_devices - pred_dev = pred_by_s_d[s][d] - chunk_index = (seg_index * num_subchunks) + s - new_partial_reductions[chunk_index] = red_op( - chunks_by_dev[pred_dev][chunk_index], - chunks_by_dev[d][chunk_index]) - # Update chunks_by_dev with the new values at the end of the tick. - for d in range(0, num_devices): - for s in range(0, num_subchunks): - rank = rank_by_s_d[s][d] - seg_index = (rank + num_devices - (2 + tick)) % num_devices - chunk_index = (seg_index * num_subchunks) + s - chunks_by_dev[d][chunk_index] = new_partial_reductions[chunk_index] - return chunks_by_dev, split_pad_len - - -def _apply_unary_to_chunks(f, chunks_by_dev): - """Apply a unary op to each tensor in chunks_by_dev, on same device. - - Args: - f: a unary function over T `tf.Tensor`. - chunks_by_dev: list of lists of T `tf.Tensor`. - - Returns: - new list of lists of T `tf.Tensor` with the same structure as - chunks_by_dev containing the derived tensors. - """ - output = [] - for x in chunks_by_dev: - with ops.colocate_with(x[0]): - output.append([f(t) for t in x]) - return output - - -def _build_ring_scatter(pred_by_s_d, rank_by_s_d, - chunks_by_dev): - """Construct subgraph for second (scatter) pass of ring all-reduce. - - Args: - pred_by_s_d: as produced by _ring_permutations - rank_by_s_d: as produced by _ring_permutations - chunks_by_dev: list of list of T `tf.Tensor` indexed by ints - (device, chunk) - - Raises: - ValueError: chunks_by_dev is not well-formed - - Returns: - list of T `tf.Tensor` which are the fully reduced tensors, one - at each device corresponding to the outer dimension of chunks_by_dev. - """ - num_devices = len(chunks_by_dev) - num_chunks = len(chunks_by_dev[0]) - if 0 != num_chunks % num_devices: - raise ValueError( - "Expect number of chunks per device to be divisible by num_devices") - num_subchunks = int(num_chunks / num_devices) - num_ticks = num_devices - 1 - for tick in range(0, num_ticks): - passed_values = [None for _ in range(0, num_chunks)] - for d in range(0, num_devices): - with ops.colocate_with(chunks_by_dev[d][0]): - for s in range(0, num_subchunks): - rank = rank_by_s_d[s][d] - seg_index = (rank + num_devices - (1 + tick)) % num_devices - pred_dev = pred_by_s_d[s][d] - chunk_index = (seg_index * num_subchunks) + s - passed_values[chunk_index] = array_ops.identity( - chunks_by_dev[pred_dev][chunk_index]) - for d in range(0, num_devices): - for s in range(0, num_subchunks): - rank = rank_by_s_d[s][d] - seg_index = (rank + num_devices - (1 + tick)) % num_devices - chunk_index = (seg_index * num_subchunks) + s - chunks_by_dev[d][chunk_index] = passed_values[chunk_index] - # Join chunks at each device. - output = [] - for x in chunks_by_dev: - with ops.colocate_with(x[0]): - output.append(array_ops.concat(x, 0)) - return output - - -def build_recursive_hd_all_reduce(input_tensors, red_op, un_op=None): - """Construct a subgraph for recursive halving-doubling all-reduce. - - The recursive halving-doubling algorithm is described in - http://www.mcs.anl.gov/~thakur/papers/ijhpca-coll.pdf - - The concept is to arrange the participating n devices in - a linear sequence where devices exchange data pairwise - with one other device in each round. During the gather - phase there are lg(n) rounds where devices exchange - increasingly smaller sub-tensors with another device - at increasingly greater distances, until at the top - each device has 1/n of the fully reduced values. During the - scatter phase each device exchanges its fully reduced - sub-tensor (which doubles in length at each round) - with one other device at increasingly smaller distances - until each device has all of the fully reduced values. - - Note: this preliminary version requires that len(input_tensors) be a - power of 2. TODO(tucker): relax this restriction. Also, the - number of elements in each tensor must be divisible by 2^h where h - is the number of hops in each phase. This will also be relaxed in - the future with edge-case specific logic. - - Args: - input_tensors: list of T `tf.Tensor` to be elementwise reduced. - red_op: a binary elementwise reduction Op. - un_op: an optional unary elementwise Op to apply to reduced values. - - Returns: - list of T `tf.Tensor` which are the fully reduced tensors, one - at each device of input_tensors. - - Raises: - ValueError: num_devices not a power of 2, or tensor len not divisible - by 2 the proper number of times. - """ - devices = [t.device for t in input_tensors] - input_tensors, shape = _flatten_tensors(input_tensors) - reduced_shards = _build_recursive_hd_gather(input_tensors, devices, red_op) - if un_op: - reduced_shards = [un_op(t) for t in reduced_shards] - output_tensors = _build_recursive_hd_scatter(reduced_shards, devices) - if len(shape) != 1: - output_tensors = _reshape_tensors(output_tensors, shape) - return output_tensors - - -def _build_recursive_hd_gather(input_tensors, devices, red_op): - """Construct the gather phase of recursive halving-doubling all-reduce. - - Args: - input_tensors: list of T `tf.Tensor` to be elementwise reduced. - devices: a list of strings naming the devices hosting input_tensors, - which will also be used to host the (partial) reduction values. - red_op: a binary elementwise reduction Op. - - Returns: - list of T `tf.Tensor` which are the fully reduced tensor shards. - - Raises: - ValueError: num_devices not a power of 2, or tensor len not divisible - by 2 the proper number of times. - """ - num_devices = len(devices) - num_hops = int(math.log(num_devices, 2)) - if num_devices != (2 ** num_hops): - raise ValueError("num_devices must be a power of 2") - chunks = input_tensors - for h in range(0, num_hops): - span = 2 ** h - group_size = span * 2 - new_chunks = [[] for _ in devices] - for d in range(0, num_devices): - if (d % group_size) >= (group_size / 2): - # skip right half of a pair - continue - left_dev = devices[d] - right_dev = devices[d + span] - left_split = array_ops.split(chunks[d], 2) - right_split = array_ops.split(chunks[d+span], 2) - with ops.device(left_dev): - new_chunks[d] = red_op(left_split[0], right_split[0]) - with ops.device(right_dev): - new_chunks[d + span] = red_op(left_split[1], right_split[1]) - chunks = new_chunks - return chunks - - -def _build_recursive_hd_scatter(input_tensors, devices): - """Construct the scatter phase of recursive halving-doublng all-reduce. - - Args: - input_tensors: list of T `tf.Tensor` that are fully-reduced shards. - devices: a list of strings naming the devices on which the reconstituted - full tensors should be placed. - - Returns: - list of T `tf.Tensor` which are the fully reduced tensors. - """ - num_devices = len(devices) - num_hops = int(math.log(num_devices, 2)) - assert num_devices == (2 ** num_hops), "num_devices must be a power of 2" - chunks = input_tensors - for h in reversed(range(0, num_hops)): - span = 2 ** h - group_size = span * 2 - new_chunks = [[] for _ in devices] - for d in range(0, num_devices): - if (d % group_size) >= (group_size / 2): - # skip right half of a pair - continue - left_idx = d - right_idx = d + span - left_dev = devices[left_idx] - right_dev = devices[right_idx] - with ops.device(left_dev): - new_chunks[left_idx] = array_ops.concat([chunks[left_idx], - chunks[right_idx]], 0) - with ops.device(right_dev): - new_chunks[right_idx] = array_ops.concat([chunks[left_idx], - chunks[right_idx]], 0) - chunks = new_chunks - return chunks - - -def build_shuffle_all_reduce(input_tensors, gather_devices, red_op, un_op=None): - """Construct a subgraph for shuffle all-reduce. - - Shuffle reduce is essentially the algorithm implemented when using - parameter servers. Suppose tensor length is n, there are d devices - and g gather shards. Each device sends a n/g length sub-tensor to - each gather shard. The gather shards perform a reduction across d - fragments, then broadcast the result back to each device. The - devices then join the g fully reduced fragments they receive from - the shards. The gather shards could perform d-1 pairwise - reductions, or one d-way reduction. The first is better where - reduction Op time is low compared to transmission time, the second - better in the other case. - - Args: - input_tensors: list of T @(tf.Tensor} values to be reduced. - gather_devices: list of names of devices on which reduction shards - should be placed. - red_op: an n-array elementwise reduction Op - un_op: optional elementwise unary Op to be applied to fully-reduced values. - - Returns: - list of T `tf.Tensor` which are the fully reduced tensors. - """ - input_tensors, shape = _flatten_tensors(input_tensors) - dst_devices = [t.device for t in input_tensors] - reduced_shards = _build_shuffle_gather(input_tensors, gather_devices, - red_op, un_op) - output_tensors = _build_shuffle_scatter(reduced_shards, dst_devices) - if len(shape) != 1: - output_tensors = _reshape_tensors(output_tensors, shape) - return output_tensors - - -def _build_shuffle_gather(input_tensors, gather_devices, red_op, un_op=None): - """Construct the gather (concentrate and reduce) phase of shuffle all-reduce. - - Args: - input_tensors: list of T @(tf.Tensor} values to be reduced. - gather_devices: list of names of devices on which reduction shards - should be placed. - red_op: the binary reduction Op - un_op: optional elementwise unary Op to be applied to fully-reduced values. - - Returns: - list of T `tf.Tensor` which are the fully reduced shards. - - Raises: - ValueError: inputs not well-formed. - """ - num_source_devices = len(input_tensors) - num_gather_devices = len(gather_devices) - shape = input_tensors[0].shape - if len(shape) != 1: - raise ValueError("input_tensors must be 1D") - shards_by_source = [] - for d in range(0, num_source_devices): - with ops.colocate_with(input_tensors[d]): - shards_by_source.append( - _ragged_split(input_tensors[d], num_gather_devices)) - reduced_shards = [] - for d in range(0, num_gather_devices): - with ops.device(gather_devices[d]): - values = [s[d] for s in shards_by_source] - red_shard = red_op(values) - if un_op: - red_shard = un_op(red_shard) - reduced_shards.append(red_shard) - return reduced_shards - - -def _build_shuffle_scatter(reduced_shards, dst_devices): - """Build the scatter phase of shuffle all-reduce. - - Args: - reduced_shards: list of T @(tf.Tensor} fully reduced shards - dst_devices: list of names of devices at which the fully-reduced value - should be reconstituted. - - Returns: - list of T `tf.Tensor` scattered tensors. - """ - num_devices = len(dst_devices) - out_tensors = [] - for d in range(0, num_devices): - with ops.device(dst_devices[d]): - out_tensors.append(array_ops.concat(reduced_shards, 0)) - return out_tensors - - -def _split_by_task(devices, values): - """Partition devices and values by common task. - - Args: - devices: list of device name strings - values: list of T `tf.tensor` of same length as devices. - - Returns: - (per_task_devices, per_task_values) where both values are - lists of lists with isomorphic structure: the outer list is - indexed by task, and the inner list has length of the number - of values belonging to that task. per_task_devices contains - the specific devices to which the values are local, and - per_task_values contains the corresponding values. - - Raises: - ValueError: devices must be same length as values. - """ - num_devices = len(devices) - if num_devices != len(values): - raise ValueError("len(devices) must equal len(values)") - per_task_devices = collections.OrderedDict() - per_task_values = collections.OrderedDict() - for d in range(num_devices): - d_spec = device_lib.DeviceSpec.from_string(devices[d]) - if not hasattr(d_spec, "task") or d_spec.task is None: - assert False, "failed to parse device %s" % devices[d] - index = (d_spec.job or "localhost", d_spec.replica or 0, d_spec.task) - if index not in per_task_devices: - per_task_devices[index] = [] - per_task_values[index] = [] - per_task_devices[index].append(devices[d]) - per_task_values[index].append(values[d]) - - return (list(per_task_devices.values()), list(per_task_values.values())) - - -def build_nccl_all_reduce(input_tensors, red_op, un_op=None): - """Build a subgraph that does one full all-reduce, using NCCL. - - Args: - input_tensors: list of T `tf.Tensor` of same-shape and type values to - be reduced. - red_op: binary elementwise reduction operator. Must be one of - {tf.add} - un_op: optional unary elementwise Op to apply to fully-reduce values. - - Returns: - list of T `tf.Tensor` of reduced values. - - Raises: - ValueError: red_op not supported. - """ - if red_op == math_ops.add: - output_tensors = nccl_ops.all_sum(input_tensors) - else: - raise ValueError("red_op not supported by NCCL all-reduce: ", red_op) - if un_op: - un_op_wrapped = [] - for t in output_tensors: - with ops.colocate_with(t): - un_op_wrapped.append(un_op(t)) - output_tensors = un_op_wrapped - return output_tensors - - -def _build_nccl_hybrid(input_tensors, red_op, upper_level_f): - """Construct a subgraph for NCCL hybrid all-reduce. - - Args: - input_tensors: list of T `tf.Tensor` of same-shape and type values to - be reduced. - red_op: binary elementwise reduction operator. - upper_level_f: function for reducing one value per worker, across - workers. - - Returns: - list of T `tf.Tensor` of reduced values. - - Raises: - ValueError: inputs not well-formed. - """ - input_tensors, shape = _flatten_tensors(input_tensors) - devices = [t.device for t in input_tensors] - per_worker_devices, per_worker_values = _split_by_task(devices, input_tensors) - num_workers = len(per_worker_devices) - up_values = [None for w in range(0, num_workers)] - up_devices = up_values[:] - down_values = up_values[:] - # First stage: reduce within each worker using NCCL - for w in range(0, num_workers): - worker_values = build_nccl_all_reduce(per_worker_values[w], red_op) - # NOTE: these reductions will not run to completion unless - # every output value is used. Since we only need one, we - # need to put control dependencies on the rest. - with ops.control_dependencies(worker_values): - with ops.device(worker_values[0].device): - up_values[w] = array_ops.identity(worker_values[0]) - up_devices[w] = per_worker_devices[w][0] - # Second stage: Apply upper_level_f to reduce across first device at - # each worker - level_2_output = upper_level_f(up_values) - # Third stage: propagate within each worker using NCCL Broadcast - for w in range(0, num_workers): - dst_tensors = [] - with ops.device(per_worker_devices[w][0]): - broadcast_src = nccl_ops.broadcast(array_ops.identity(level_2_output[w])) - for d in per_worker_devices[w]: - with ops.device(d): - dst_tensors.append(array_ops.identity(broadcast_src)) - down_values[w] = dst_tensors - output_tensors = [v for sublist in down_values for v in sublist] - if len(shape) != 1: - output_tensors = _reshape_tensors(output_tensors, shape) - return output_tensors - - -def _reduce_non_singleton(input_tensors, red_f, un_op): - """If input_tensors has more than one element apply red_f, else apply un_op.""" - if len(input_tensors) > 1: - return red_f(input_tensors) - else: - if not un_op: - return input_tensors - output_tensors = [] - for t in input_tensors: - with ops.colocate_with(t): - output_tensors.append(un_op(t)) - return output_tensors - - -def build_nccl_then_ring(input_tensors, subdiv, red_op, un_op=None): - """Construct hybrid of NCCL within workers, Ring across workers.""" - def upper_builder(y): - return build_ring_all_reduce(y, len(y), subdiv, [0], red_op, un_op) - def upper_level_f(x): - return _reduce_non_singleton(x, upper_builder, un_op) - return _build_nccl_hybrid(input_tensors, red_op, upper_level_f) - - -def build_nccl_then_recursive_hd(input_tensors, red_op, un_op=None): - """Construct hybrid of NCCL within workers, Recursive-HD across workers.""" - upper_level_f = lambda x: build_recursive_hd_all_reduce(x, red_op, un_op) - return _build_nccl_hybrid(input_tensors, red_op, upper_level_f) - - -def build_nccl_then_shuffle(input_tensors, gather_devices, nccl_red_op, - shuffle_red_op, un_op=None): - """Construct hybrid of NCCL within workers, Shuffle across workers.""" - upper_level_f = lambda x: build_shuffle_all_reduce(x, gather_devices, - shuffle_red_op, un_op) - return _build_nccl_hybrid(input_tensors, nccl_red_op, upper_level_f) - - -def _build_shuffle_hybrid(input_tensors, gather_devices, red_op, upper_level_f): - """Construct a subgraph for Shuffle hybrid all-reduce. - - Args: - input_tensors: list of T `tf.Tensor` of same-shape and type values to - be reduced. - gather_devices: list of device names on which to host gather shards. - red_op: binary elementwise reduction operator. - upper_level_f: function for reducing one value per worker, across - workers. - - Returns: - list of T `tf.Tensor` of reduced values. - - Raises: - ValueError: inputs not well-formed. - """ - input_tensors, shape = _flatten_tensors(input_tensors) - # First stage, reduce across each worker using gather_devices. - devices = [t.device for t in input_tensors] - per_worker_devices, per_worker_values = _split_by_task(devices, input_tensors) - num_workers = len(per_worker_devices) - up_values = [] - if len(gather_devices) != num_workers: - raise ValueError("For shuffle hybrid, gather_devices must contain one " - "device per worker. ") - for w in range(0, num_workers): - reduced_shards = _build_shuffle_gather( - per_worker_values[w], [gather_devices[w]], red_op) - up_values.append(reduced_shards[0]) - # Second stage, apply upper_level_f. - level_2_output = upper_level_f(up_values) - # Third stage, apply shuffle scatter at each worker. - output_tensors = [] - for w in range(0, num_workers): - output_tensors += _build_shuffle_scatter( - [level_2_output[w]], per_worker_devices[w]) - if len(shape) != 1: - output_tensors = _reshape_tensors(output_tensors, shape) - return output_tensors - - -def build_shuffle_then_ring(input_tensors, gather_devices, subdiv, - red_n_op, red_op, un_op=None): - """Construct hybrid of Shuffle within workers, Ring across workers.""" - def upper_builder(tensors): - return build_ring_all_reduce(tensors, len(tensors), subdiv, [0], - red_op, un_op) - def upper_level_f(tensors): - return _reduce_non_singleton(tensors, upper_builder, un_op) - return _build_shuffle_hybrid( - input_tensors, gather_devices, red_n_op, upper_level_f) - - -def build_shuffle_then_shuffle(input_tensors, first_gather_devices, - second_gather_devices, red_op, un_op=None): - """Construct hybrid of Shuffle within workers, Shuffle across workers.""" - def upper_builder(tensors): - return build_shuffle_all_reduce(tensors, second_gather_devices, - red_op, un_op) - def upper_level_f(tensors): - return _reduce_non_singleton(tensors, upper_builder, un_op) - return _build_shuffle_hybrid( - input_tensors, first_gather_devices, red_op, upper_level_f) +# pylint: disable=unused-import,wildcard-import +from tensorflow.python.distribute.all_reduce import * diff --git a/tensorflow/contrib/autograph/examples/benchmarks/BUILD b/tensorflow/contrib/autograph/examples/benchmarks/BUILD new file mode 100644 index 0000000000..6d2d70c99b --- /dev/null +++ b/tensorflow/contrib/autograph/examples/benchmarks/BUILD @@ -0,0 +1,36 @@ +licenses(["notice"]) # Apache 2.0 + +load("//tensorflow:tensorflow.bzl", "py_test") +load("//tensorflow/tools/test:performance.bzl", "tf_py_logged_benchmark") + +py_library( + name = "benchmark_base", + srcs = [ + "benchmark_base.py", + ], + deps = [ + "//tensorflow:tensorflow_py", + ], +) + +py_test( + name = "cartpole_benchmark", + size = "enormous", + srcs = ["cartpole_benchmark.py"], + tags = [ + "local", + "manual", + "no_oss", + "notap", + "nozapfhahn", + ], + deps = [ + ":benchmark_base", + # Note: required gym dependency may need to be added here. + ], +) + +tf_py_logged_benchmark( + name = "cartpole_logged_benchmark", + target = "//tensorflow/contrib/autograph/examples/benchmarks:cartpole_benchmark", +) diff --git a/tensorflow/contrib/autograph/examples/benchmarks/benchmark_base.py b/tensorflow/contrib/autograph/examples/benchmarks/benchmark_base.py new file mode 100644 index 0000000000..93c694849c --- /dev/null +++ b/tensorflow/contrib/autograph/examples/benchmarks/benchmark_base.py @@ -0,0 +1,62 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Common benchmarking code. + +See https://www.tensorflow.org/community/benchmarks for usage. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +import numpy as np + +import tensorflow as tf + + +class ReportingBenchmark(tf.test.Benchmark): + """Base class for a benchmark that reports general performance metrics. + + Subclasses only need to call one of the _profile methods, and optionally + report_results. + """ + + def time_execution(self, name, target, iters, warm_up_iters=5): + for _ in range(warm_up_iters): + target() + + all_times = [] + for _ in range(iters): + iter_time = time.time() + target() + all_times.append(time.time() - iter_time) + + avg_time = np.average(all_times) + + extras = dict() + extras['all_times'] = all_times + + if isinstance(name, tuple): + extras['name'] = name + name = '_'.join(str(piece) for piece in name) + + self.report_benchmark( + iters=iters, wall_time=avg_time, name=name, extras=extras) + + +if __name__ == '__main__': + tf.test.main() diff --git a/tensorflow/contrib/autograph/examples/benchmarks/cartpole_benchmark.py b/tensorflow/contrib/autograph/examples/benchmarks/cartpole_benchmark.py new file mode 100644 index 0000000000..4f553be58e --- /dev/null +++ b/tensorflow/contrib/autograph/examples/benchmarks/cartpole_benchmark.py @@ -0,0 +1,492 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""A basic RL cartpole benchmark. + +The RL model uses the OpenAI Gym environment to train a simple network using +the policy gradients method. The training scales the gradients for each step +by the episode's cumulative discounted reward and averages these gradients over +a fixed number of games before applying the optimization step. + +For benchmarking purposes, we replace the OpenAI Gym environment to a fake +that returns random actions and rewards and never ends the episode. This way +the benchmarks compare the same amount of computation at each step. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import gym +import numpy as np +import tensorflow as tf + +from tensorflow.contrib import eager +from tensorflow.contrib.autograph.examples.benchmarks import benchmark_base +from tensorflow.python import autograph as ag +from tensorflow.python.eager import context + +# +# AutoGraph implementation +# + + +@ag.convert() +def graph_append_discounted_rewards(destination, rewards, discount_rate): + """Discounts episode rewards and appends them to destination.""" + ag.set_element_type(rewards, tf.float32) + + cdr = 0.0 + reverse_discounted = [] + ag.set_element_type(reverse_discounted, tf.float32) + + for i in range(len(rewards) - 1, -1, -1): + cdr = cdr * discount_rate + rewards[i] + cdr.set_shape(()) + reverse_discounted.append(cdr) + + retval = destination + # Note: AutoGraph doesn't yet support reversed() so we use a loop instead. + for i in range(len(reverse_discounted) - 1, -1, -1): + retval.append(reverse_discounted[i]) + + return retval + + +class GraphPolicyNetwork(tf.keras.Model): + """Policy network for the cart-pole reinforcement learning problem. + + The forward path of the network takes an observation from the cart-pole + environment (length-4 vector) and outputs an action. + """ + + def __init__(self, hidden_size): + super(GraphPolicyNetwork, self).__init__() + self._hidden_layer = tf.keras.layers.Dense( + hidden_size, activation=tf.nn.elu) + self._output_layer = tf.keras.layers.Dense(1) + + def call(self, inputs): + """Calculates logits and action. + + Args: + inputs: Observations from a step in the cart-pole environment, of shape + `(batch_size, input_size)` + + Returns: + logits: the logits output by the output layer. This can be viewed as the + likelihood vales of choosing the left (0) action. Shape: + `(batch_size, 1)`. + actions: randomly selected actions ({0, 1}) based on the logits. Shape: + `(batch_size, 1)`. + """ + hidden = self._hidden_layer(inputs) + logits = self._output_layer(hidden) + + left_prob = tf.nn.sigmoid(logits) + action_probs = tf.concat([left_prob, 1.0 - left_prob], 1) + + actions = tf.multinomial(tf.log(action_probs), 1) + return logits, actions + + # TODO(mdan): Move this method out of the class. + @ag.convert() + def train(self, cart_pole_env, optimizer, discount_rate, num_games, + max_steps_per_game): + var_list = tf.trainable_variables() + grad_list = [ + tf.TensorArray(tf.float32, 0, dynamic_size=True) for _ in var_list + ] + + step_counts = [] + discounted_rewards = [] + ag.set_element_type(discounted_rewards, tf.float32) + ag.set_element_type(step_counts, tf.int32) + + # Note: we use a shared object, cart_pole_env here. Because calls to the + # object's method are made through py_func, TensorFlow cannot detect its + # data dependencies. Hence we must manually synchronize access to it + # and ensure the control dependencies are set in such a way that + # calls to reset(), take_one_step, etc. are made in the correct order. + sync_counter = tf.constant(0) + + for _ in tf.range(num_games): + with tf.control_dependencies([sync_counter]): + obs = cart_pole_env.reset() + with tf.control_dependencies([obs]): + sync_counter += 1 + + game_rewards = [] + ag.set_element_type(game_rewards, tf.float32) + + for step in tf.range(max_steps_per_game): + logits, actions = self(obs) # pylint:disable=not-callable + logits = tf.reshape(logits, ()) + actions = tf.reshape(actions, ()) + + labels = 1.0 - tf.cast(actions, tf.float32) + loss = tf.nn.sigmoid_cross_entropy_with_logits( + labels=labels, logits=logits) + grads = tf.gradients(loss, var_list) + + for i in range(len(grads)): + grad_list[i].append(grads[i]) + + with tf.control_dependencies([sync_counter]): + obs, reward, done = cart_pole_env.step(actions) + with tf.control_dependencies([obs]): + sync_counter += 1 + obs = tf.reshape(obs, (1, 4)) + + game_rewards.append(reward) + if reward < 0.1 or done: + step_counts.append(step + 1) + break + + discounted_rewards = graph_append_discounted_rewards( + discounted_rewards, game_rewards, discount_rate) + + discounted_rewards = ag.stack(discounted_rewards) + discounted_rewards.set_shape((None,)) + mean, variance = tf.nn.moments(discounted_rewards, [0]) + normalized_rewards = (discounted_rewards - mean) / tf.sqrt(variance) + + for i in range(len(grad_list)): + g = ag.stack(grad_list[i]) + + # This block just adjusts the shapes to match for multiplication. + r = normalized_rewards + if r.shape.ndims < g.shape.ndims: + r = tf.expand_dims(r, -1) + if r.shape.ndims < g.shape.ndims: + r = tf.expand_dims(r, -1) + + grad_list[i] = tf.reduce_mean(g * r, axis=0) + + optimizer.apply_gradients( + zip(grad_list, var_list), global_step=tf.train.get_global_step()) + + return ag.stack(step_counts) + + +@ag.convert() +def graph_train_model(policy_network, cart_pole_env, optimizer, iterations): + """Trains the policy network for a given number of iterations.""" + i = tf.constant(0) + mean_steps_per_iteration = [] + ag.set_element_type(mean_steps_per_iteration, tf.int32) + + while i < iterations: + steps_per_game = policy_network.train( + cart_pole_env, + optimizer, + discount_rate=0.95, + num_games=20, + max_steps_per_game=200) + mean_steps_per_iteration.append(tf.reduce_mean(steps_per_game)) + i += 1 + + return ag.stack(mean_steps_per_iteration) + + +class GraphGymCartpoleEnv(object): + """An env backed by OpenAI Gym's CartPole environment. + + Used to confirm a functional model only. + """ + + def __init__(self): + cart_pole_env = gym.make('CartPole-v1') + cart_pole_env.seed(0) + cart_pole_env.reset() + self.env = cart_pole_env + + def reset(self): + obs = ag.utils.wrap_py_func(self.env.reset, tf.float64, ()) + obs = tf.reshape(obs, (1, 4)) + obs = tf.cast(obs, tf.float32) + return obs + + def step(self, actions): + + def take_one_step(actions): + obs, reward, done, _ = self.env.step(actions) + obs = obs.astype(np.float32) + reward = np.float32(reward) + return obs, reward, done + + return ag.utils.wrap_py_func(take_one_step, + (tf.float32, tf.float32, tf.bool), (actions,)) + + +class GraphRandomCartpoleEnv(object): + """An environment that returns random actions and never finishes. + + Used during benchmarking, it will cause training to run a constant number of + steps. + """ + + def reset(self): + return tf.random.normal((1, 4)) + + def step(self, actions): + with tf.control_dependencies([actions]): + random_obs = tf.random.normal((1, 4)) + fixed_reward = tf.constant(0.001) + done = tf.constant(False) + return random_obs, fixed_reward, done + + +# +# Eager implementation +# + + +def eager_append_discounted_rewards(discounted_rewards, rewards, discount_rate): + cdr = 0.0 + reverse_discounted = [] + + for i in range(len(rewards) - 1, -1, -1): + cdr = cdr * discount_rate + rewards[i] + reverse_discounted.append(cdr) + + discounted_rewards.extend(reversed(reverse_discounted)) + return discounted_rewards + + +class EagerPolicyNetwork(tf.keras.Model): + """Policy network for the cart-pole reinforcement learning problem. + + The forward path of the network takes an observation from the cart-pole + environment (length-4 vector) and outputs an action. + """ + + def __init__(self, hidden_size): + super(EagerPolicyNetwork, self).__init__() + self._hidden_layer = tf.keras.layers.Dense( + hidden_size, activation=tf.nn.elu) + self._output_layer = tf.keras.layers.Dense(1) + + def call(self, inputs): + """Calculates logits and action. + + Args: + inputs: Observations from a step in the cart-pole environment, of shape + `(batch_size, input_size)` + + Returns: + logits: the logits output by the output layer. This can be viewed as the + likelihood vales of choosing the left (0) action. Shape: + `(batch_size, 1)`. + actions: randomly selected actions ({0, 1}) based on the logits. Shape: + `(batch_size, 1)`. + """ + hidden = self._hidden_layer(inputs) + logits = self._output_layer(hidden) + + left_prob = tf.nn.sigmoid(logits) + action_probs = tf.concat([left_prob, 1.0 - left_prob], 1) + + self._grad_fn = eager.implicit_gradients( + self._get_cross_entropy_and_save_actions) + + actions = tf.multinomial(tf.log(action_probs), 1) + return logits, actions + + def _get_cross_entropy_and_save_actions(self, inputs): + logits, actions = self(inputs) # pylint:disable=not-callable + self._current_actions = actions + labels = 1.0 - tf.cast(actions, tf.float32) + return tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=logits) + + def train(self, cart_pole_env, optimizer, discount_rate, num_games, + max_steps_per_game): + grad_list = None + + step_counts = [] + discounted_rewards = [] + + for _ in range(num_games): + obs = cart_pole_env.reset() + + game_rewards = [] + + for step in range(max_steps_per_game): + grads_and_vars = self._grad_fn(tf.constant([obs], dtype=tf.float32)) + grads, var_list = zip(*grads_and_vars) + actions = self._current_actions.numpy()[0][0] + + if grad_list is None: + grad_list = [[g] for g in grads] + else: + for i in range(len(grads)): + grad_list[i].append(grads[i]) + + obs, reward, done = cart_pole_env.step(actions) + + game_rewards.append(reward) + if reward < 0.1 or done: + step_counts.append(step + 1) + break + + discounted_rewards = eager_append_discounted_rewards( + discounted_rewards, game_rewards, discount_rate) + + discounted_rewards = tf.stack(discounted_rewards) + mean, variance = tf.nn.moments(discounted_rewards, [0]) + normalized_rewards = (discounted_rewards - mean) / tf.sqrt(variance) + + for i in range(len(grad_list)): + g = tf.stack(grad_list[i]) + + r = normalized_rewards + while r.shape.ndims < g.shape.ndims: + r = tf.expand_dims(r, -1) + + grad_list[i] = tf.reduce_mean(g * r, axis=0) + + optimizer.apply_gradients( + zip(grad_list, var_list), global_step=tf.train.get_global_step()) + + return tf.stack(step_counts) + + +def eager_train_model(policy_network, cart_pole_env, optimizer, iterations): + """Trains the policy network for a given number of iterations.""" + mean_steps_per_iteration = [] + + for _ in range(iterations): + steps_per_game = policy_network.train( + cart_pole_env, + optimizer, + discount_rate=0.95, + num_games=20, + max_steps_per_game=200) + mean_steps_per_iteration.append(tf.reduce_mean(steps_per_game)) + + return mean_steps_per_iteration + + +class EagerGymCartpoleEnv(object): + """An env backed by OpenAI Gym's CartPole environment. + + Used to confirm a functional model only. + """ + + def __init__(self): + cart_pole_env = gym.make('CartPole-v1') + cart_pole_env.seed(0) + cart_pole_env.reset() + self.env = cart_pole_env + + def reset(self): + return self.env.reset() + + def step(self, actions): + obs, reward, done, _ = self.env.step(actions) + return obs, reward, done + + +class EagerRandomCartpoleEnv(object): + """An environment that returns random actions and never finishes. + + Used during benchmarking, it will cause training to run a constant number of + steps. + """ + + def reset(self): + return np.random.normal(size=(4,)) + + def step(self, actions): + with tf.control_dependencies([actions]): + random_obs = np.random.normal(size=(4,)) + fixed_reward = 0.001 + done = False + return random_obs, fixed_reward, done + + +def graph_demo_training(): + """Not used in the benchmark. Used to confirm a functional model.""" + with tf.Graph().as_default(): + tf.set_random_seed(0) + + network = GraphPolicyNetwork(hidden_size=5) + network.build((1, 4)) + env = GraphGymCartpoleEnv() + opt = tf.train.AdamOptimizer(0.05) + + train_ops = graph_train_model(network, env, opt, iterations=5) + + with tf.Session() as sess: + sess.run(tf.global_variables_initializer()) + sess.run(tf.local_variables_initializer()) + steps_per_iteration = sess.run(train_ops) + for i, steps in enumerate(steps_per_iteration): + print('Step {} iterations: {}'.format(i, steps)) + + +def eager_demo_training(): + with context.eager_mode(): + network = EagerPolicyNetwork(hidden_size=5) + network.build((1, 4)) + env = EagerGymCartpoleEnv() + opt = tf.train.AdamOptimizer(0.05) + + steps_per_iteration = eager_train_model(network, env, opt, iterations=5) + for i, steps in enumerate(steps_per_iteration): + print('Step {} iterations: {}'.format(i, steps)) + + +class RLCartPoleBenchmark(benchmark_base.ReportingBenchmark): + """Actual benchmark. + + Trains the RL agent a fixed number of times, on random environments that + result in constant number of steps. + """ + + def benchmark_cartpole(self): + + def train_session(sess, ops): + return lambda: sess.run(ops) + + def train_eager(network, env, opt): + return lambda: eager_train_model(network, env, opt, iterations=10) + + for model_size in (10, 100, 1000): + with tf.Graph().as_default(): + network = GraphPolicyNetwork(hidden_size=model_size) + network.build((1, 4)) + env = GraphRandomCartpoleEnv() + opt = tf.train.AdamOptimizer(0.05) + train_ops = graph_train_model(network, env, opt, iterations=10) + + with tf.Session() as sess: + sess.run(tf.global_variables_initializer()) + sess.run(tf.local_variables_initializer()) + + self.time_execution(('cartpole', 'autograph', model_size), + train_session(sess, train_ops), 20) + + with context.eager_mode(): + network = EagerPolicyNetwork(hidden_size=model_size) + network.build((1, 4)) + env = EagerRandomCartpoleEnv() + opt = tf.train.AdamOptimizer(0.05) + + self.time_execution(('cartpole', 'eager', model_size), + train_eager(network, env, opt), 20) + + +if __name__ == '__main__': + tf.test.main() diff --git a/tensorflow/contrib/batching/python/ops/batch_ops.py b/tensorflow/contrib/batching/python/ops/batch_ops.py index 55faad983f..3e4d0dc1ce 100644 --- a/tensorflow/contrib/batching/python/ops/batch_ops.py +++ b/tensorflow/contrib/batching/python/ops/batch_ops.py @@ -18,8 +18,9 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.python.framework import function +from tensorflow.python.eager import function from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_spec from tensorflow.python.ops import gen_batch_ops # go/tf-wildcard-import # pylint: disable=wildcard-import @@ -101,12 +102,15 @@ def batch_function(num_batch_threads, def decorator(fn): # pylint: disable=missing-docstring def decorated(*args): # pylint: disable=missing-docstring - types = [arg.dtype for arg in args] - @function.Defun(*types) + @function.defun() def computation(*computation_args): return fn(*computation_args) + computation = computation.get_concrete_function( + *[tensor_spec.TensorSpec(dtype=x.dtype, shape=x.shape, name=str(i)) + for i, x in enumerate(args)]) + with ops.name_scope("batch") as name: for a in args: if not isinstance(a, ops.Tensor): @@ -123,7 +127,7 @@ def batch_function(num_batch_threads, f=computation, in_tensors=list(args), captured_tensors=computation.captured_inputs, - Tout=[o.type for o in computation.definition.signature.output_arg]) + Tout=[o.dtype for o in computation.outputs]) return decorated diff --git a/tensorflow/contrib/batching/python/ops/batch_ops_test.py b/tensorflow/contrib/batching/python/ops/batch_ops_test.py index 01ee8703a9..9109b9c1c9 100644 --- a/tensorflow/contrib/batching/python/ops/batch_ops_test.py +++ b/tensorflow/contrib/batching/python/ops/batch_ops_test.py @@ -219,6 +219,7 @@ class BatchOpsTest(test.TestCase): @batch_ops.batch_function(1, 10, 100000) def computation(in_t): + self.assertTrue(in_t.shape is not None) return in_t + 1 inp = array_ops.placeholder(dtype=dtypes.int32, shape=[1]) diff --git a/tensorflow/contrib/bayesflow/python/kernel_tests/monte_carlo_test.py b/tensorflow/contrib/bayesflow/python/kernel_tests/monte_carlo_test.py index 13215ffabf..8b6ed9f041 100644 --- a/tensorflow/contrib/bayesflow/python/kernel_tests/monte_carlo_test.py +++ b/tensorflow/contrib/bayesflow/python/kernel_tests/monte_carlo_test.py @@ -81,7 +81,7 @@ class ExpectationImportanceSampleTest(test.TestCase): # Compute E_p[X_1 * X_2 > 0], with X_i the ith component of X ~ p(x). # Should equal 1/2 because p is a spherical Gaussian centered at (0, 0). def indicator(x): - x1_times_x2 = math_ops.reduce_prod(x, reduction_indices=[-1]) + x1_times_x2 = math_ops.reduce_prod(x, axis=[-1]) return 0.5 * (math_ops.sign(x1_times_x2) + 1.0) prob = mc.expectation_importance_sampler( diff --git a/tensorflow/contrib/bayesflow/python/ops/monte_carlo_impl.py b/tensorflow/contrib/bayesflow/python/ops/monte_carlo_impl.py index 18d40fc1df..e83a548511 100644 --- a/tensorflow/contrib/bayesflow/python/ops/monte_carlo_impl.py +++ b/tensorflow/contrib/bayesflow/python/ops/monte_carlo_impl.py @@ -353,12 +353,12 @@ def expectation(f, samples, log_prob=None, use_reparametrization=True, def _sample_mean(values): """Mean over sample indices. In this module this is always [0].""" - return math_ops.reduce_mean(values, reduction_indices=[0]) + return math_ops.reduce_mean(values, axis=[0]) def _sample_max(values): """Max over sample indices. In this module this is always [0].""" - return math_ops.reduce_max(values, reduction_indices=[0]) + return math_ops.reduce_max(values, axis=[0]) def _get_samples(dist, z, n, seed): diff --git a/tensorflow/contrib/bigtable/README.md b/tensorflow/contrib/bigtable/README.md index 2c44abed5e..79052bee35 100644 --- a/tensorflow/contrib/bigtable/README.md +++ b/tensorflow/contrib/bigtable/README.md @@ -51,25 +51,18 @@ BIGTABLE_TABLE_NAME = '' PREFIX = 'train-' def main(): + tf.enable_eager_execution() + client = tf.contrib.cloud.BigtableClient(GCP_PROJECT_ID, BIGTABLE_INSTANCE_ID) table = client.table(BIGTABLE_TABLE_NAME) dataset = table.keys_by_prefix_dataset(PREFIX) - iterator = dataset.make_initializable_iterator() - get_next_op = iterator.get_next() - with tf.Session() as sess: - print('Initializing the iterator.') - sess.run(iterator.initializer) - print('Retrieving rows:') - row_index = 0 - while True: - try: - row_key = sess.run(get_next_op) - print('Row key %d: %s' % (row_index, row_key)) - row_index += 1 - except tf.errors.OutOfRangeError: - print('Finished reading data!') - break + print('Retrieving rows:') + row_index = 0 + for row_key in dataset: + print('Row key %d: %s' % (row_index, row_key)) + row_index += 1 + print('Finished reading data!') if __name__ == '__main__': main() diff --git a/tensorflow/contrib/bigtable/kernels/test_kernels/bigtable_test_client.cc b/tensorflow/contrib/bigtable/kernels/test_kernels/bigtable_test_client.cc index f083ce6f44..e95dc57718 100644 --- a/tensorflow/contrib/bigtable/kernels/test_kernels/bigtable_test_client.cc +++ b/tensorflow/contrib/bigtable/kernels/test_kernels/bigtable_test_client.cc @@ -366,6 +366,39 @@ BigtableTestClient::MutateRows( return MakeUnique(request.entries_size()); } +std::unique_ptr> +BigtableTestClient::AsyncMutateRow( + grpc::ClientContext* context, + google::bigtable::v2::MutateRowRequest const& request, + grpc::CompletionQueue* cq) { + LOG(WARNING) << "Call to InMemoryDataClient::" << __func__ + << "(); this will likely cause a crash!"; + return nullptr; +} + +std::unique_ptr<::grpc::ClientAsyncReaderInterface< + ::google::bigtable::v2::SampleRowKeysResponse>> +BigtableTestClient::AsyncSampleRowKeys( + ::grpc::ClientContext* context, + const ::google::bigtable::v2::SampleRowKeysRequest& request, + ::grpc::CompletionQueue* cq, void* tag) { + LOG(WARNING) << "Call to InMemoryDataClient::" << __func__ + << "(); this will likely cause a crash!"; + return nullptr; +} + +std::unique_ptr<::grpc::ClientAsyncReaderInterface< + ::google::bigtable::v2::MutateRowsResponse>> +BigtableTestClient::AsyncMutateRows( + ::grpc::ClientContext* context, + const ::google::bigtable::v2::MutateRowsRequest& request, + ::grpc::CompletionQueue* cq, void* tag) { + LOG(WARNING) << "Call to InMemoryDataClient::" << __func__ + << "(); this will likely cause a crash!"; + return nullptr; +} + std::shared_ptr BigtableTestClient::Channel() { LOG(WARNING) << "Call to InMemoryDataClient::Channel(); this will likely " "cause a crash!"; diff --git a/tensorflow/contrib/bigtable/kernels/test_kernels/bigtable_test_client.h b/tensorflow/contrib/bigtable/kernels/test_kernels/bigtable_test_client.h index dac2b16a21..c4a1f06bc5 100644 --- a/tensorflow/contrib/bigtable/kernels/test_kernels/bigtable_test_client.h +++ b/tensorflow/contrib/bigtable/kernels/test_kernels/bigtable_test_client.h @@ -61,6 +61,25 @@ class BigtableTestClient : public ::google::cloud::bigtable::DataClient { MutateRows(grpc::ClientContext* context, google::bigtable::v2::MutateRowsRequest const& request) override; + std::unique_ptr> + AsyncMutateRow(grpc::ClientContext* context, + google::bigtable::v2::MutateRowRequest const& request, + grpc::CompletionQueue* cq) override; + + std::unique_ptr<::grpc::ClientAsyncReaderInterface< + ::google::bigtable::v2::SampleRowKeysResponse>> + AsyncSampleRowKeys( + ::grpc::ClientContext* context, + const ::google::bigtable::v2::SampleRowKeysRequest& request, + ::grpc::CompletionQueue* cq, void* tag) override; + + std::unique_ptr<::grpc::ClientAsyncReaderInterface< + ::google::bigtable::v2::MutateRowsResponse>> + AsyncMutateRows(::grpc::ClientContext* context, + const ::google::bigtable::v2::MutateRowsRequest& request, + ::grpc::CompletionQueue* cq, void* tag) override; + std::shared_ptr Channel() override; private: diff --git a/tensorflow/contrib/bigtable/python/kernel_tests/bigtable_ops_test.py b/tensorflow/contrib/bigtable/python/kernel_tests/bigtable_ops_test.py index 316da9ebe1..197f5578eb 100644 --- a/tensorflow/contrib/bigtable/python/kernel_tests/bigtable_ops_test.py +++ b/tensorflow/contrib/bigtable/python/kernel_tests/bigtable_ops_test.py @@ -57,7 +57,7 @@ class BigtableOpsTest(test.TestCase): sess.run(write_op) def runReadKeyTest(self, read_ds): - itr = read_ds.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(read_ds) n = itr.get_next() expected = list(self.COMMON_ROW_KEYS) expected.reverse() @@ -78,7 +78,7 @@ class BigtableOpsTest(test.TestCase): self.runReadKeyTest(self._table.keys_by_range_dataset("r1", "r4")) def runScanTest(self, read_ds): - itr = read_ds.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(read_ds) n = itr.get_next() expected_keys = list(self.COMMON_ROW_KEYS) expected_keys.reverse() @@ -120,7 +120,7 @@ class BigtableOpsTest(test.TestCase): def testLookup(self): ds = self._table.keys_by_prefix_dataset("r") ds = ds.apply(self._table.lookup_columns(cf1="c1")) - itr = ds.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(ds) n = itr.get_next() expected_keys = list(self.COMMON_ROW_KEYS) expected_values = list(self.COMMON_VALUES) @@ -141,7 +141,7 @@ class BigtableOpsTest(test.TestCase): def testSampleKeys(self): ds = self._table.sample_keys() - itr = ds.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(ds) n = itr.get_next() expected_key = self.COMMON_ROW_KEYS[0] with self.cached_session() as sess: @@ -161,7 +161,7 @@ class BigtableOpsTest(test.TestCase): sess.run(n) def runSampleKeyPairsTest(self, ds, expected_key_pairs): - itr = ds.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(ds) n = itr.get_next() with self.cached_session() as sess: self._writeCommonValues(sess) @@ -218,7 +218,7 @@ class BigtableOpsTest(test.TestCase): def testSampleKeyPairsPrefixAndStartKey(self): ds = bigtable_api._BigtableSampleKeyPairsDataset( self._table, prefix="r", start="r1", end="") - itr = ds.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(ds) with self.cached_session() as sess: with self.assertRaises(errors.InvalidArgumentError): sess.run(itr.initializer) @@ -226,14 +226,14 @@ class BigtableOpsTest(test.TestCase): def testSampleKeyPairsPrefixAndEndKey(self): ds = bigtable_api._BigtableSampleKeyPairsDataset( self._table, prefix="r", start="", end="r3") - itr = ds.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(ds) with self.cached_session() as sess: with self.assertRaises(errors.InvalidArgumentError): sess.run(itr.initializer) def testParallelScanPrefix(self): ds = self._table.parallel_scan_prefix(prefix="r", cf1="c1") - itr = ds.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(ds) n = itr.get_next() with self.cached_session() as sess: self._writeCommonValues(sess) @@ -251,7 +251,7 @@ class BigtableOpsTest(test.TestCase): def testParallelScanRange(self): ds = self._table.parallel_scan_range(start="r1", end="r4", cf1="c1") - itr = ds.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(ds) n = itr.get_next() with self.cached_session() as sess: self._writeCommonValues(sess) diff --git a/tensorflow/contrib/bigtable/python/ops/bigtable_api.py b/tensorflow/contrib/bigtable/python/ops/bigtable_api.py index 7c87b0daeb..9f97934193 100644 --- a/tensorflow/contrib/bigtable/python/ops/bigtable_api.py +++ b/tensorflow/contrib/bigtable/python/ops/bigtable_api.py @@ -222,7 +222,7 @@ class BigtableTable(object): A `tf.data.Dataset`. containing `tf.string` Tensors corresponding to all of the row keys matching that prefix. """ - return _BigtablePrefixKeyDataset(self, prefix) + return dataset_ops.DatasetV1Adapter(_BigtablePrefixKeyDataset(self, prefix)) def sample_keys(self): """Retrieves a sampling of row keys from the Bigtable table. @@ -234,7 +234,7 @@ class BigtableTable(object): Returns: A `tf.data.Dataset` returning string row keys. """ - return _BigtableSampleKeysDataset(self) + return dataset_ops.DatasetV1Adapter(_BigtableSampleKeysDataset(self)) def scan_prefix(self, prefix, probability=None, columns=None, **kwargs): """Retrieves row (including values) from the Bigtable service. @@ -279,7 +279,8 @@ class BigtableTable(object): """ probability = _normalize_probability(probability) normalized = _normalize_columns(columns, kwargs) - return _BigtableScanDataset(self, prefix, "", "", normalized, probability) + return dataset_ops.DatasetV1Adapter( + _BigtableScanDataset(self, prefix, "", "", normalized, probability)) def scan_range(self, start, end, probability=None, columns=None, **kwargs): """Retrieves rows (including values) from the Bigtable service. @@ -324,7 +325,8 @@ class BigtableTable(object): """ probability = _normalize_probability(probability) normalized = _normalize_columns(columns, kwargs) - return _BigtableScanDataset(self, "", start, end, normalized, probability) + return dataset_ops.DatasetV1Adapter( + _BigtableScanDataset(self, "", start, end, normalized, probability)) def parallel_scan_prefix(self, prefix, @@ -380,7 +382,8 @@ class BigtableTable(object): """ probability = _normalize_probability(probability) normalized = _normalize_columns(columns, kwargs) - ds = _BigtableSampleKeyPairsDataset(self, prefix, "", "") + ds = dataset_ops.DatasetV1Adapter( + _BigtableSampleKeyPairsDataset(self, prefix, "", "")) return self._make_parallel_scan_dataset(ds, num_parallel_scans, probability, normalized) @@ -442,7 +445,8 @@ class BigtableTable(object): """ probability = _normalize_probability(probability) normalized = _normalize_columns(columns, kwargs) - ds = _BigtableSampleKeyPairsDataset(self, "", start, end) + ds = dataset_ops.DatasetV1Adapter( + _BigtableSampleKeyPairsDataset(self, "", start, end)) return self._make_parallel_scan_dataset(ds, num_parallel_scans, probability, normalized) diff --git a/tensorflow/contrib/boosted_trees/estimator_batch/BUILD b/tensorflow/contrib/boosted_trees/estimator_batch/BUILD index 14b6fc4ac2..d3b23d949e 100644 --- a/tensorflow/contrib/boosted_trees/estimator_batch/BUILD +++ b/tensorflow/contrib/boosted_trees/estimator_batch/BUILD @@ -132,6 +132,7 @@ py_library( srcs = ["estimator.py"], srcs_version = "PY2AND3", deps = [ + ":custom_loss_head", ":estimator_utils", ":model", "//tensorflow/contrib/boosted_trees:losses", diff --git a/tensorflow/contrib/boosted_trees/estimator_batch/custom_export_strategy.py b/tensorflow/contrib/boosted_trees/estimator_batch/custom_export_strategy.py index a3df272e69..b314b4d74d 100644 --- a/tensorflow/contrib/boosted_trees/estimator_batch/custom_export_strategy.py +++ b/tensorflow/contrib/boosted_trees/estimator_batch/custom_export_strategy.py @@ -41,7 +41,8 @@ def make_custom_export_strategy(name, convert_fn, feature_columns, export_input_fn, - use_core_columns=False): + use_core_columns=False, + feature_engineering_fn=None): """Makes custom exporter of GTFlow tree format. Args: @@ -52,6 +53,7 @@ def make_custom_export_strategy(name, export_input_fn: A function that takes no arguments and returns an `InputFnOps`. use_core_columns: A boolean, whether core feature columns were used. + feature_engineering_fn: Feature eng function to be called on the input. Returns: An `ExportStrategy`. @@ -59,9 +61,12 @@ def make_custom_export_strategy(name, base_strategy = saved_model_export_utils.make_export_strategy( serving_input_fn=export_input_fn, strip_default_attrs=True) input_fn = export_input_fn() + features = input_fn.features + if feature_engineering_fn is not None: + features, _ = feature_engineering_fn(features, labels=None) (sorted_feature_names, dense_floats, sparse_float_indices, _, _, sparse_int_indices, _, _) = gbdt_batch.extract_features( - input_fn.features, feature_columns, use_core_columns) + features, feature_columns, use_core_columns) def export_fn(estimator, export_dir, checkpoint_path=None, eval_result=None): """A wrapper to export to SavedModel, and convert it to other formats.""" diff --git a/tensorflow/contrib/boosted_trees/estimator_batch/dnn_tree_combined_estimator.py b/tensorflow/contrib/boosted_trees/estimator_batch/dnn_tree_combined_estimator.py index ca73e4af2f..358404cd94 100644 --- a/tensorflow/contrib/boosted_trees/estimator_batch/dnn_tree_combined_estimator.py +++ b/tensorflow/contrib/boosted_trees/estimator_batch/dnn_tree_combined_estimator.py @@ -36,7 +36,7 @@ from tensorflow.contrib.learn.python.learn.estimators import estimator from tensorflow.contrib.learn.python.learn.estimators import head as head_lib from tensorflow.python.estimator import estimator as core_estimator from tensorflow.contrib.learn.python.learn.estimators import model_fn -from tensorflow.python.feature_column import feature_column as feature_column_lib +from tensorflow.python.feature_column import feature_column_lib from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops diff --git a/tensorflow/contrib/boosted_trees/estimator_batch/estimator.py b/tensorflow/contrib/boosted_trees/estimator_batch/estimator.py index 38d19976ef..a178820841 100644 --- a/tensorflow/contrib/boosted_trees/estimator_batch/estimator.py +++ b/tensorflow/contrib/boosted_trees/estimator_batch/estimator.py @@ -18,6 +18,8 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import functools + from tensorflow.contrib.boosted_trees.estimator_batch import model from tensorflow.contrib.boosted_trees.python.utils import losses from tensorflow.contrib.learn.python.learn.estimators import estimator @@ -26,7 +28,8 @@ from tensorflow.python.estimator.canned import head as core_head_lib from tensorflow.python.estimator import estimator as core_estimator from tensorflow.python.ops import math_ops from tensorflow.python.ops.losses import losses as core_losses - +from tensorflow.contrib.boosted_trees.estimator_batch import custom_loss_head +from tensorflow.python.ops import array_ops # ================== Old estimator interface=================================== # The estimators below were designed for old feature columns and old estimator @@ -414,6 +417,108 @@ class GradientBoostedDecisionTreeRanker(estimator.Estimator): config=config, feature_engineering_fn=feature_engineering_fn) +# When using this estimator, make sure to regularize the hessian (at least l2, +# min_node_weight)! +# TODO(nponomareva): extend to take multiple quantiles in one go. +class GradientBoostedDecisionTreeQuantileRegressor(estimator.Estimator): + """An estimator that does quantile regression and returns quantile estimates. + """ + + def __init__(self, + learner_config, + examples_per_layer, + quantiles, + label_dimension=1, + num_trees=None, + feature_columns=None, + weight_column_name=None, + model_dir=None, + config=None, + feature_engineering_fn=None, + logits_modifier_function=None, + center_bias=True, + use_core_libs=False, + output_leaf_index=False, + override_global_step_value=None, + num_quantiles=100): + """Initializes a GradientBoostedDecisionTreeQuantileRegressor instance. + + Args: + learner_config: A config for the learner. + examples_per_layer: Number of examples to accumulate before growing a + layer. It can also be a function that computes the number of examples + based on the depth of the layer that's being built. + quantiles: a list of quantiles for the loss, each between 0 and 1. + label_dimension: Dimension of regression label. This is the size + of the last dimension of the labels `Tensor` (typically, this has shape + `[batch_size, label_dimension]`). When label_dimension>1, it is + recommended to use multiclass strategy diagonal hessian or full hessian. + num_trees: An int, number of trees to build. + feature_columns: A list of feature columns. + weight_column_name: Name of the column for weights, or None if not + weighted. + model_dir: Directory for model exports, etc. + config: `RunConfig` object to configure the runtime settings. + feature_engineering_fn: Feature engineering function. Takes features and + labels which are the output of `input_fn` and returns features and + labels which will be fed into the model. + logits_modifier_function: A modifier function for the logits. + center_bias: Whether a separate tree should be created for first fitting + the bias. + use_core_libs: Whether feature columns and loss are from the core (as + opposed to contrib) version of tensorflow. + output_leaf_index: whether to output leaf indices along with predictions + during inference. The leaf node indexes are available in predictions + dict by the key 'leaf_index'. For example, + result_dict = classifier.predict(...) + for example_prediction_result in result_dict: + # access leaf index list by example_prediction_result["leaf_index"] + # which contains one leaf index per tree + override_global_step_value: If after the training is done, global step + value must be reset to this value. This should be used to reset global + step to a number > number of steps used to train the current ensemble. + For example, the usual way is to train a number of trees and set a very + large number of training steps. When the training is done (number of + trees were trained), this parameter can be used to set the global step + to a large value, making it look like that number of training steps ran. + If None, no override of global step will happen. + num_quantiles: Number of quantiles to build for numeric feature values. + """ + + if len(quantiles) > 1: + raise ValueError('For now, just one quantile per estimator is supported') + + def _quantile_regression_head(quantile): + # Use quantile regression. + head = custom_loss_head.CustomLossHead( + loss_fn=functools.partial( + losses.per_example_quantile_regression_loss, quantile=quantile), + link_fn=array_ops.identity, + logit_dimension=label_dimension) + return head + + learner_config.num_classes = max(2, label_dimension) + + super(GradientBoostedDecisionTreeQuantileRegressor, self).__init__( + model_fn=model.model_builder, + params={ + 'head': _quantile_regression_head(quantiles[0]), + 'feature_columns': feature_columns, + 'learner_config': learner_config, + 'num_trees': num_trees, + 'weight_column_name': weight_column_name, + 'examples_per_layer': examples_per_layer, + 'logits_modifier_function': logits_modifier_function, + 'center_bias': center_bias, + 'use_core_libs': use_core_libs, + 'output_leaf_index': False, + 'override_global_step_value': override_global_step_value, + 'num_quantiles': num_quantiles, + }, + model_dir=model_dir, + config=config, + feature_engineering_fn=feature_engineering_fn) + # ================== New Estimator interface=================================== # The estimators below use new core Estimator interface and must be used with # new feature columns and heads. @@ -437,12 +542,42 @@ def core_multiclass_head( # pylint:disable=protected-access head_fn = core_head_lib._multi_class_head_with_softmax_cross_entropy_loss( - n_classes=n_classes, loss_fn=loss_fn, loss_reduction=loss_reduction) + n_classes=n_classes, + loss_fn=loss_fn, + loss_reduction=loss_reduction, + weight_column=weight_column) # pylint:enable=protected-access return head_fn +# For quantile regression, use this head with Core..Estimator, or use +# Core..QuantileRegressor directly, +def core_quantile_regression_head( + quantiles, + label_dimension=1, + weight_column=None, + loss_reduction=core_losses.Reduction.SUM_OVER_NONZERO_WEIGHTS): + """Core head for quantile regression problems.""" + + def loss_fn(labels, logits): + result = losses.per_example_quantile_regression_loss( + labels=labels, + predictions=logits, + weights=weight_column, + quantile=quantiles) + return result[0] + + # pylint:disable=protected-access + head_fn = core_head_lib._regression_head( + label_dimension=label_dimension, + loss_fn=loss_fn, + loss_reduction=loss_reduction, + weight_column=weight_column) + # pylint:enable=protected-access + return head_fn + + class CoreGradientBoostedDecisionTreeEstimator(core_estimator.Estimator): """An estimator using gradient boosted decision trees. @@ -606,3 +741,104 @@ class CoreGradientBoostedDecisionTreeRanker(core_estimator.Estimator): super(CoreGradientBoostedDecisionTreeRanker, self).__init__( model_fn=_model_fn, model_dir=model_dir, config=config) + + +# When using this estimator, make sure to regularize the hessian (at least l2, +# min_node_weight)! +# TODO(nponomareva): extend to take multiple quantiles in one go. +class CoreGradientBoostedDecisionTreeQuantileRegressor( + core_estimator.Estimator): + """An estimator that does quantile regression and returns quantile estimates. + """ + + def __init__(self, + learner_config, + examples_per_layer, + quantiles, + label_dimension=1, + num_trees=None, + feature_columns=None, + weight_column_name=None, + model_dir=None, + config=None, + label_keys=None, + feature_engineering_fn=None, + logits_modifier_function=None, + center_bias=True, + output_leaf_index=False, + num_quantiles=100): + """Initializes a core version of GradientBoostedDecisionTreeEstimator. + + Args: + learner_config: A config for the learner. + examples_per_layer: Number of examples to accumulate before growing a + layer. It can also be a function that computes the number of examples + based on the depth of the layer that's being built. + quantiles: a list of quantiles for the loss, each between 0 and 1. + label_dimension: Dimension of regression label. This is the size + of the last dimension of the labels `Tensor` (typically, this has shape + `[batch_size, label_dimension]`). When label_dimension>1, it is + recommended to use multiclass strategy diagonal hessian or full hessian. + num_trees: An int, number of trees to build. + feature_columns: A list of feature columns. + weight_column_name: Name of the column for weights, or None if not + weighted. + model_dir: Directory for model exports, etc. + config: `RunConfig` object to configure the runtime settings. + label_keys: Optional list of strings with size `[n_classes]` defining the + label vocabulary. Only supported for `n_classes` > 2. + feature_engineering_fn: Feature engineering function. Takes features and + labels which are the output of `input_fn` and returns features and + labels which will be fed into the model. + logits_modifier_function: A modifier function for the logits. + center_bias: Whether a separate tree should be created for first fitting + the bias. + output_leaf_index: whether to output leaf indices along with predictions + during inference. The leaf node indexes are available in predictions + dict by the key 'leaf_index'. For example, + result_dict = classifier.predict(...) + for example_prediction_result in result_dict: + # access leaf index list by example_prediction_result["leaf_index"] + # which contains one leaf index per tree + num_quantiles: Number of quantiles to build for numeric feature values. + """ + if len(quantiles) > 1: + raise ValueError('For now, just one quantile per estimator is supported') + + def _model_fn(features, labels, mode, config): + return model.model_builder( + features=features, + labels=labels, + mode=mode, + config=config, + params={ + 'head': + core_quantile_regression_head( + quantiles[0], label_dimension=label_dimension), + 'feature_columns': + feature_columns, + 'learner_config': + learner_config, + 'num_trees': + num_trees, + 'weight_column_name': + weight_column_name, + 'examples_per_layer': + examples_per_layer, + 'center_bias': + center_bias, + 'logits_modifier_function': + logits_modifier_function, + 'use_core_libs': + True, + 'output_leaf_index': + output_leaf_index, + 'override_global_step_value': + None, + 'num_quantiles': + num_quantiles, + }, + output_type=model.ModelBuilderOutputType.ESTIMATOR_SPEC) + + super(CoreGradientBoostedDecisionTreeQuantileRegressor, self).__init__( + model_fn=_model_fn, model_dir=model_dir, config=config) diff --git a/tensorflow/contrib/boosted_trees/estimator_batch/estimator_test.py b/tensorflow/contrib/boosted_trees/estimator_batch/estimator_test.py index c155128c0e..ee052ac603 100644 --- a/tensorflow/contrib/boosted_trees/estimator_batch/estimator_test.py +++ b/tensorflow/contrib/boosted_trees/estimator_batch/estimator_test.py @@ -25,6 +25,7 @@ from tensorflow.contrib.boosted_trees.proto import learner_pb2 from tensorflow.contrib.layers.python.layers import feature_column as contrib_feature_column from tensorflow.contrib.learn.python.learn.estimators import run_config from tensorflow.python.estimator.canned import head as head_lib +from tensorflow.python.estimator.inputs import numpy_io from tensorflow.python.feature_column import feature_column_lib as core_feature_column from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes @@ -47,8 +48,8 @@ def _multiclass_train_input_fn(): features = { "x": constant_op.constant([[2.], [1.], [1.], [5.], [3.5], [4.6], [3.5]]) } - label = constant_op.constant( - [[1], [0], [0], [2], [2], [0], [1]], dtype=dtypes.int32) + label = constant_op.constant([[1], [0], [0], [2], [2], [0], [1]], + dtype=dtypes.int32) return features, label @@ -77,6 +78,59 @@ def _infer_ranking_train_input_fn(): return features, None +_QUANTILE_REGRESSION_SIZE = 1000 + + +def _quantile_regression_input_fns(two_dimension=False): + # The data generation is taken from + # http://scikit-learn.org/stable/auto_examples/ensemble/plot_gradient_boosting_quantile.html + np.random.seed(1) + + def f(x): + """The function to predict.""" + return x * np.sin(x) + + def g(x): + """The function to predict.""" + return x * np.cos(x) + + # Training data. + x = np.atleast_2d(np.random.uniform(0, 10.0, + size=_QUANTILE_REGRESSION_SIZE)).T + x = x.astype(np.float32) + + # Labels. + if not two_dimension: + y = f(x).ravel() + else: + y = np.column_stack((f(x).ravel(), g(x).ravel())) + + # Add random noise. + dy = 1.5 + 1.0 * np.random.random(y.shape) + noise = np.random.normal(0, dy) + y += noise + y_original = y.astype(np.float32) + if not two_dimension: + y = y.reshape(_QUANTILE_REGRESSION_SIZE, 1) + + train_input_fn = numpy_io.numpy_input_fn( + x=x, + y=y, + batch_size=_QUANTILE_REGRESSION_SIZE, + num_epochs=None, + shuffle=True) + + # Test on the training data to make sure the predictions are calibrated. + test_input_fn = numpy_io.numpy_input_fn( + x=x, + y=y, + batch_size=_QUANTILE_REGRESSION_SIZE, + num_epochs=1, + shuffle=False) + + return train_input_fn, test_input_fn, y_original + + class BoostedTreeEstimatorTest(test_util.TensorFlowTestCase): def setUp(self): @@ -341,6 +395,130 @@ class BoostedTreeEstimatorTest(test_util.TensorFlowTestCase): for prediction_dict in result_iter: self.assertTrue("classes" in prediction_dict) + # One dimensional quantile regression. + def testQuantileRegression(self): + learner_config = learner_pb2.LearnerConfig() + learner_config.num_classes = 2 + learner_config.constraints.max_tree_depth = 3 + learner_config.growing_mode = learner_pb2.LearnerConfig.WHOLE_TREE + learner_config.constraints.min_node_weight = 1 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.l2 = 1.0 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.l1 = 1.0 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.tree_complexity = ( + 1.0 / _QUANTILE_REGRESSION_SIZE) + + train_input_fn, test_input_fn, y = _quantile_regression_input_fns() + + # 95% percentile. + model_upper = estimator.GradientBoostedDecisionTreeQuantileRegressor( + quantiles=[0.95], + learner_config=learner_config, + num_trees=100, + examples_per_layer=_QUANTILE_REGRESSION_SIZE, + center_bias=False) + + model_upper.fit(input_fn=train_input_fn, steps=1000) + result_iter = model_upper.predict(input_fn=test_input_fn) + upper = [] + for prediction_dict in result_iter: + upper.append(prediction_dict["scores"]) + + frac_below_upper = round(1. * np.count_nonzero(upper > y) / len(y), 3) + # +/- 3% + self.assertTrue(frac_below_upper >= 0.92) + self.assertTrue(frac_below_upper <= 0.98) + + train_input_fn, test_input_fn, _ = _quantile_regression_input_fns() + model_lower = estimator.GradientBoostedDecisionTreeQuantileRegressor( + quantiles=[0.05], + learner_config=learner_config, + num_trees=100, + examples_per_layer=_QUANTILE_REGRESSION_SIZE, + center_bias=False) + + model_lower.fit(input_fn=train_input_fn, steps=1000) + result_iter = model_lower.predict(input_fn=test_input_fn) + lower = [] + for prediction_dict in result_iter: + lower.append(prediction_dict["scores"]) + + frac_above_lower = round(1. * np.count_nonzero(lower < y) / len(y), 3) + # +/- 3% + self.assertTrue(frac_above_lower >= 0.92) + self.assertTrue(frac_above_lower <= 0.98) + + # Multi-dimensional quantile regression. + def testQuantileRegressionMultiDimLabel(self): + learner_config = learner_pb2.LearnerConfig() + learner_config.num_classes = 2 + learner_config.constraints.max_tree_depth = 3 + learner_config.growing_mode = learner_pb2.LearnerConfig.WHOLE_TREE + learner_config.constraints.min_node_weight = 1 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.l2 = 1.0 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.l1 = 1.0 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.tree_complexity = ( + 1.0 / _QUANTILE_REGRESSION_SIZE) + + train_input_fn, test_input_fn, y = _quantile_regression_input_fns( + two_dimension=True) + + # 95% percentile. + model_upper = estimator.GradientBoostedDecisionTreeQuantileRegressor( + quantiles=[0.95], + learner_config=learner_config, + label_dimension=2, + num_trees=100, + examples_per_layer=_QUANTILE_REGRESSION_SIZE, + center_bias=False) + + model_upper.fit(input_fn=train_input_fn, steps=1000) + result_iter = model_upper.predict(input_fn=test_input_fn) + upper = [] + for prediction_dict in result_iter: + upper.append(prediction_dict["scores"]) + + count_below_upper = np.count_nonzero(upper > y, axis=0) + count_both_below_upper = np.count_nonzero(np.prod(upper > y, axis=1)) + frac_below_upper_0 = round(1. * count_below_upper[0] / len(y), 3) + frac_below_upper_1 = round(1. * count_below_upper[1] / len(y), 3) + frac_both_below_upper = round(1. * count_both_below_upper / len(y), 3) + # +/- 3% + self.assertTrue(frac_below_upper_0 >= 0.92) + self.assertTrue(frac_below_upper_0 <= 0.98) + self.assertTrue(frac_below_upper_1 >= 0.92) + self.assertTrue(frac_below_upper_1 <= 0.98) + self.assertTrue(frac_both_below_upper >= 0.92) + self.assertTrue(frac_both_below_upper <= 0.98) + + train_input_fn, test_input_fn, _ = _quantile_regression_input_fns( + two_dimension=True) + model_lower = estimator.GradientBoostedDecisionTreeQuantileRegressor( + quantiles=[0.05], + learner_config=learner_config, + label_dimension=2, + num_trees=100, + examples_per_layer=_QUANTILE_REGRESSION_SIZE, + center_bias=False) + + model_lower.fit(input_fn=train_input_fn, steps=1000) + result_iter = model_lower.predict(input_fn=test_input_fn) + lower = [] + for prediction_dict in result_iter: + lower.append(prediction_dict["scores"]) + + count_above_lower = np.count_nonzero(lower < y, axis=0) + count_both_aboce_lower = np.count_nonzero(np.prod(lower < y, axis=1)) + frac_above_lower_0 = round(1. * count_above_lower[0] / len(y), 3) + frac_above_lower_1 = round(1. * count_above_lower[1] / len(y), 3) + frac_both_above_lower = round(1. * count_both_aboce_lower / len(y), 3) + # +/- 3% + self.assertTrue(frac_above_lower_0 >= 0.92) + self.assertTrue(frac_above_lower_0 <= 0.98) + self.assertTrue(frac_above_lower_1 >= 0.92) + self.assertTrue(frac_above_lower_1 <= 0.98) + self.assertTrue(frac_both_above_lower >= 0.92) + self.assertTrue(frac_both_above_lower <= 0.98) + class CoreGradientBoostedDecisionTreeEstimators(test_util.TensorFlowTestCase): @@ -489,8 +667,8 @@ class CoreGradientBoostedDecisionTreeEstimators(test_util.TensorFlowTestCase): feature_columns = [ core_feature_column.weighted_categorical_column( - categorical_column=core_feature_column. - categorical_column_with_vocabulary_list( + categorical_column=core_feature_column + .categorical_column_with_vocabulary_list( key="word", vocabulary_list=["the", "cat", "dog"]), weight_feature_key="weight") ] @@ -509,8 +687,8 @@ class CoreGradientBoostedDecisionTreeEstimators(test_util.TensorFlowTestCase): # Weights for the words are 5 - cat, 6- dog and 1 -the. features_dict["word"] = sparse_tensor.SparseTensor( indices=[[0, 0], [0, 1], [1, 0], [3, 0]], - values=constant_op.constant( - ["the", "cat", "dog", "the"], dtype=dtypes.string), + values=constant_op.constant(["the", "cat", "dog", "the"], + dtype=dtypes.string), dense_shape=[4, 3]) features_dict["weight"] = sparse_tensor.SparseTensor( indices=[[0, 0], [0, 1], [1, 0], [3, 0]], @@ -534,6 +712,132 @@ class CoreGradientBoostedDecisionTreeEstimators(test_util.TensorFlowTestCase): est.evaluate(input_fn=input_fn, steps=1) est.predict(input_fn=input_fn) + # One dimensional quantile regression. + def testQuantileRegression(self): + learner_config = learner_pb2.LearnerConfig() + learner_config.num_classes = 2 + learner_config.constraints.max_tree_depth = 3 + learner_config.growing_mode = learner_pb2.LearnerConfig.WHOLE_TREE + learner_config.constraints.min_node_weight = 1 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.l2 = 1.0 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.l1 = 1.0 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.tree_complexity = ( + 1.0 / _QUANTILE_REGRESSION_SIZE) + + train_input_fn, test_input_fn, y = _quantile_regression_input_fns() + y = y.reshape(_QUANTILE_REGRESSION_SIZE, 1) + + # 95% percentile. + model_upper = estimator.CoreGradientBoostedDecisionTreeQuantileRegressor( + quantiles=[0.95], + learner_config=learner_config, + num_trees=100, + examples_per_layer=_QUANTILE_REGRESSION_SIZE, + center_bias=False) + + model_upper.train(input_fn=train_input_fn, steps=1000) + result_iter = model_upper.predict(input_fn=test_input_fn) + upper = [] + for prediction_dict in result_iter: + upper.append(prediction_dict["predictions"]) + + frac_below_upper = round(1. * np.count_nonzero(upper > y) / len(y), 3) + # +/- 3% + self.assertTrue(frac_below_upper >= 0.92) + self.assertTrue(frac_below_upper <= 0.98) + + train_input_fn, test_input_fn, _ = _quantile_regression_input_fns() + model_lower = estimator.CoreGradientBoostedDecisionTreeQuantileRegressor( + quantiles=[0.05], + learner_config=learner_config, + num_trees=100, + examples_per_layer=_QUANTILE_REGRESSION_SIZE, + center_bias=False) + + model_lower.train(input_fn=train_input_fn, steps=1000) + result_iter = model_lower.predict(input_fn=test_input_fn) + lower = [] + for prediction_dict in result_iter: + lower.append(prediction_dict["predictions"]) + + frac_above_lower = round(1. * np.count_nonzero(lower < y) / len(y), 3) + # +/- 3% + self.assertTrue(frac_above_lower >= 0.92) + self.assertTrue(frac_above_lower <= 0.98) + + # Multi-dimensional quantile regression. + def testQuantileRegressionMultiDimLabel(self): + learner_config = learner_pb2.LearnerConfig() + learner_config.num_classes = 2 + learner_config.constraints.max_tree_depth = 3 + learner_config.growing_mode = learner_pb2.LearnerConfig.WHOLE_TREE + learner_config.constraints.min_node_weight = 1 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.l2 = 1.0 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.l1 = 1.0 / _QUANTILE_REGRESSION_SIZE + learner_config.regularization.tree_complexity = ( + 1.0 / _QUANTILE_REGRESSION_SIZE) + + train_input_fn, test_input_fn, y = _quantile_regression_input_fns( + two_dimension=True) + y = y.reshape(_QUANTILE_REGRESSION_SIZE, 2) + + # 95% percentile. + model_upper = estimator.CoreGradientBoostedDecisionTreeQuantileRegressor( + quantiles=[0.95], + learner_config=learner_config, + num_trees=100, + label_dimension=2, + examples_per_layer=_QUANTILE_REGRESSION_SIZE, + center_bias=False) + + model_upper.train(input_fn=train_input_fn, steps=1000) + result_iter = model_upper.predict(input_fn=test_input_fn) + upper = [] + for prediction_dict in result_iter: + upper.append(prediction_dict["predictions"]) + + count_below_upper = np.count_nonzero(upper > y, axis=0) + count_both_below_upper = np.count_nonzero(np.prod(upper > y, axis=1)) + frac_below_upper_0 = round(1. * count_below_upper[0] / len(y), 3) + frac_below_upper_1 = round(1. * count_below_upper[1] / len(y), 3) + frac_both_below_upper = round(1. * count_both_below_upper / len(y), 3) + # +/- 3% + self.assertTrue(frac_below_upper_0 >= 0.92) + self.assertTrue(frac_below_upper_0 <= 0.98) + self.assertTrue(frac_below_upper_1 >= 0.92) + self.assertTrue(frac_below_upper_1 <= 0.98) + self.assertTrue(frac_both_below_upper >= 0.92) + self.assertTrue(frac_both_below_upper <= 0.98) + + train_input_fn, test_input_fn, _ = _quantile_regression_input_fns( + two_dimension=True) + model_lower = estimator.CoreGradientBoostedDecisionTreeQuantileRegressor( + quantiles=[0.05], + learner_config=learner_config, + num_trees=100, + label_dimension=2, + examples_per_layer=_QUANTILE_REGRESSION_SIZE, + center_bias=False) + + model_lower.train(input_fn=train_input_fn, steps=1000) + result_iter = model_lower.predict(input_fn=test_input_fn) + lower = [] + for prediction_dict in result_iter: + lower.append(prediction_dict["predictions"]) + + count_above_lower = np.count_nonzero(lower < y, axis=0) + count_both_aboce_lower = np.count_nonzero(np.prod(lower < y, axis=1)) + frac_above_lower_0 = round(1. * count_above_lower[0] / len(y), 3) + frac_above_lower_1 = round(1. * count_above_lower[1] / len(y), 3) + frac_both_above_lower = round(1. * count_both_aboce_lower / len(y), 3) + # +/- 3% + self.assertTrue(frac_above_lower_0 >= 0.92) + self.assertTrue(frac_above_lower_0 <= 0.98) + self.assertTrue(frac_above_lower_1 >= 0.92) + self.assertTrue(frac_above_lower_1 <= 0.98) + self.assertTrue(frac_both_above_lower >= 0.92) + self.assertTrue(frac_both_above_lower <= 0.98) + if __name__ == "__main__": googletest.main() diff --git a/tensorflow/contrib/boosted_trees/examples/boston.py b/tensorflow/contrib/boosted_trees/examples/boston.py index 54c4ff059e..09b240a700 100644 --- a/tensorflow/contrib/boosted_trees/examples/boston.py +++ b/tensorflow/contrib/boosted_trees/examples/boston.py @@ -90,13 +90,13 @@ def _make_experiment_fn(output_dir): (x_train, y_train), (x_test, y_test) = tf.keras.datasets.boston_housing.load_data() - train_input_fn = tf.estimator.inputs.numpy_input_fn( + train_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( x={"x": x_train}, y=y_train, batch_size=FLAGS.batch_size, num_epochs=None, shuffle=True) - eval_input_fn = tf.estimator.inputs.numpy_input_fn( + eval_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( x={"x": x_test}, y=y_test, num_epochs=1, shuffle=False) feature_columns = [ diff --git a/tensorflow/contrib/boosted_trees/examples/boston_combined.py b/tensorflow/contrib/boosted_trees/examples/boston_combined.py index e04b56afbf..d640af354f 100644 --- a/tensorflow/contrib/boosted_trees/examples/boston_combined.py +++ b/tensorflow/contrib/boosted_trees/examples/boston_combined.py @@ -80,13 +80,13 @@ def _make_experiment_fn(output_dir): (x_train, y_train), (x_test, y_test) = tf.keras.datasets.boston_housing.load_data() - train_input_fn = tf.estimator.inputs.numpy_input_fn( + train_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( x={"x": x_train}, y=y_train, batch_size=FLAGS.batch_size, num_epochs=None, shuffle=True) - eval_input_fn = tf.estimator.inputs.numpy_input_fn( + eval_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( x={"x": x_test}, y=y_test, num_epochs=1, shuffle=False) feature_columns = [ diff --git a/tensorflow/contrib/boosted_trees/kernels/split_handler_ops.cc b/tensorflow/contrib/boosted_trees/kernels/split_handler_ops.cc index 8edb5d6c64..6d78e27e8f 100644 --- a/tensorflow/contrib/boosted_trees/kernels/split_handler_ops.cc +++ b/tensorflow/contrib/boosted_trees/kernels/split_handler_ops.cc @@ -834,8 +834,13 @@ class BuildCategoricalEqualitySplitsOp : public OpKernel { root_gradient_stats *= normalizer_ratio; NodeStats root_stats = state->ComputeNodeStats(root_gradient_stats); int32 best_feature_idx = 0; + bool best_feature_updated = false; NodeStats best_right_node_stats(0); NodeStats best_left_node_stats(0); + CHECK(end_index - start_index >= 2) + << "Partition should have a non bias feature. Start index " + << start_index << " and end index " << end_index; + for (int64 feature_idx = start_index + 1; feature_idx < end_index; ++feature_idx) { GradientStats left_gradient_stats(*gradients_t, *hessians_t, @@ -845,11 +850,13 @@ class BuildCategoricalEqualitySplitsOp : public OpKernel { root_gradient_stats - left_gradient_stats; NodeStats left_stats = state->ComputeNodeStats(left_gradient_stats); NodeStats right_stats = state->ComputeNodeStats(right_gradient_stats); - if (left_stats.gain + right_stats.gain > best_gain) { + if (!best_feature_updated || + left_stats.gain + right_stats.gain > best_gain) { best_gain = left_stats.gain + right_stats.gain; best_left_node_stats = left_stats; best_right_node_stats = right_stats; best_feature_idx = feature_idx; + best_feature_updated = true; } } SplitInfo split_info; @@ -864,7 +871,7 @@ class BuildCategoricalEqualitySplitsOp : public OpKernel { << feature_ids(best_feature_idx, 0) << ", " << feature_ids(best_feature_idx, 1) << "\nPartition IDS: " << partition_ids(start_index) << " " - << partition_ids(best_feature_idx); + << partition_ids(best_feature_idx) << " and best gain " << best_gain; equality_split->set_feature_id(feature_ids(best_feature_idx, 0)); auto* left_child = split_info.mutable_left_child(); auto* right_child = split_info.mutable_right_child(); diff --git a/tensorflow/contrib/boosted_trees/lib/learner/batch/categorical_split_handler.py b/tensorflow/contrib/boosted_trees/lib/learner/batch/categorical_split_handler.py index 4da25298cb..d26af58419 100644 --- a/tensorflow/contrib/boosted_trees/lib/learner/batch/categorical_split_handler.py +++ b/tensorflow/contrib/boosted_trees/lib/learner/batch/categorical_split_handler.py @@ -119,7 +119,7 @@ class EqualitySplitHandler(base_split_handler.BaseSplitHandler): def not_active_inputs(): return (constant_op.constant([], dtype=dtypes.int32), - constant_op.constant([], dtype=dtypes.int64, shape=[1, 2]), + constant_op.constant_v1([], dtype=dtypes.int64, shape=[1, 2]), empty_gradients, empty_hessians) def active_inputs(): diff --git a/tensorflow/contrib/boosted_trees/lib/learner/batch/categorical_split_handler_test.py b/tensorflow/contrib/boosted_trees/lib/learner/batch/categorical_split_handler_test.py index a2f708081a..386dc19fc7 100644 --- a/tensorflow/contrib/boosted_trees/lib/learner/batch/categorical_split_handler_test.py +++ b/tensorflow/contrib/boosted_trees/lib/learner/batch/categorical_split_handler_test.py @@ -36,9 +36,9 @@ def get_empty_tensors(gradient_shape, hessian_shape): empty_hess_shape = [1] + hessian_shape.as_list() empty_grad_shape = [1] + gradient_shape.as_list() - empty_gradients = constant_op.constant( + empty_gradients = constant_op.constant_v1( [], dtype=dtypes.float32, shape=empty_grad_shape) - empty_hessians = constant_op.constant( + empty_hessians = constant_op.constant_v1( [], dtype=dtypes.float32, shape=empty_hess_shape) return empty_gradients, empty_hessians @@ -486,8 +486,8 @@ class EqualitySplitHandlerTest(test_util.TensorFlowTestCase): gradients = array_ops.constant([0.2, -0.5, 1.2, 4.0]) hessians = array_ops.constant([0.12, 0.07, 0.2, 0.13]) partition_ids = [0, 0, 0, 1] - indices = array_ops.constant([], dtype=dtypes.int64, shape=[0, 2]) - values = array_ops.constant([], dtype=dtypes.int64) + indices = constant_op.constant_v1([], dtype=dtypes.int64, shape=[0, 2]) + values = constant_op.constant_v1([], dtype=dtypes.int64) gradient_shape = tensor_shape.scalar() hessian_shape = tensor_shape.scalar() diff --git a/tensorflow/contrib/boosted_trees/lib/learner/batch/ordinal_split_handler.py b/tensorflow/contrib/boosted_trees/lib/learner/batch/ordinal_split_handler.py index 1fffbb5f66..0476bed2cd 100644 --- a/tensorflow/contrib/boosted_trees/lib/learner/batch/ordinal_split_handler.py +++ b/tensorflow/contrib/boosted_trees/lib/learner/batch/ordinal_split_handler.py @@ -605,7 +605,7 @@ def dense_make_stats_update(is_active, are_buckets_ready, float_column, quantile_buckets, example_partition_ids, gradients, hessians, weights, empty_gradients, empty_hessians): """Updates the state for dense split handler.""" - empty_float = constant_op.constant([], dtype=dtypes.float32) + empty_float = constant_op.constant_v1([], dtype=dtypes.float32) quantile_values, quantile_weights = control_flow_ops.cond( is_active[1], # For the next layer, this handler is inactive. @@ -621,8 +621,8 @@ def dense_make_stats_update(is_active, are_buckets_ready, float_column, return (example_partition_ids, quantized_feature, gradients, hessians) def not_ready_inputs_fn(): - return (constant_op.constant([], dtype=dtypes.int32), - constant_op.constant([[]], dtype=dtypes.int64, shape=[1, 2]), + return (constant_op.constant_v1([], dtype=dtypes.int32), + constant_op.constant_v1([[]], dtype=dtypes.int64, shape=[1, 2]), empty_gradients, empty_hessians) example_partition_ids, feature_ids, gradients, hessians = ( @@ -708,11 +708,11 @@ def sparse_make_stats_update( def quantiles_not_ready(): """The subgraph for when the quantiles are not ready.""" - return (constant_op.constant([], dtype=dtypes.int32), - constant_op.constant([], dtype=dtypes.int64, shape=[1, 2]), + return (constant_op.constant_v1([], dtype=dtypes.int32), + constant_op.constant_v1([], dtype=dtypes.int64, shape=[1, 2]), empty_gradients, empty_hessians) - empty_float = constant_op.constant([], dtype=dtypes.float32) + empty_float = constant_op.constant_v1([], dtype=dtypes.float32) handler_not_active = (constant_op.constant( [], dtype=dtypes.int64, shape=[0, 2]), empty_float, constant_op.constant([0, 1], dtype=dtypes.int64), diff --git a/tensorflow/contrib/boosted_trees/lib/learner/batch/ordinal_split_handler_test.py b/tensorflow/contrib/boosted_trees/lib/learner/batch/ordinal_split_handler_test.py index 74b0ea6989..4a1b528646 100644 --- a/tensorflow/contrib/boosted_trees/lib/learner/batch/ordinal_split_handler_test.py +++ b/tensorflow/contrib/boosted_trees/lib/learner/batch/ordinal_split_handler_test.py @@ -39,9 +39,9 @@ def get_empty_tensors(gradient_shape, hessian_shape): empty_hess_shape = [1] + hessian_shape.as_list() empty_grad_shape = [1] + gradient_shape.as_list() - empty_gradients = constant_op.constant( + empty_gradients = constant_op.constant_v1( [], dtype=dtypes.float32, shape=empty_grad_shape) - empty_hessians = constant_op.constant( + empty_hessians = constant_op.constant_v1( [], dtype=dtypes.float32, shape=empty_hess_shape) return empty_gradients, empty_hessians @@ -1476,9 +1476,9 @@ class SparseSplitHandlerTest(test_util.TensorFlowTestCase): def testEmpty(self): with self.cached_session() as sess: - indices = array_ops.constant([], dtype=dtypes.int64, shape=[0, 2]) + indices = constant_op.constant_v1([], dtype=dtypes.int64, shape=[0, 2]) # No values in this feature column in this mini-batch. - values = array_ops.constant([], dtype=dtypes.float32) + values = constant_op.constant_v1([], dtype=dtypes.float32) sparse_column = sparse_tensor.SparseTensor(indices, values, [4, 1]) gradient_shape = tensor_shape.scalar() @@ -1549,8 +1549,9 @@ class SparseSplitHandlerTest(test_util.TensorFlowTestCase): sparse_column = array_ops.sparse_placeholder(dtypes.float32) # We have two batches - at first, a sparse feature is empty. - empty_indices = array_ops.constant([], dtype=dtypes.int64, shape=[0, 2]) - empty_values = array_ops.constant([], dtype=dtypes.float32) + empty_indices = constant_op.constant_v1([], dtype=dtypes.int64, + shape=[0, 2]) + empty_values = constant_op.constant_v1([], dtype=dtypes.float32) empty_sparse_column = sparse_tensor.SparseTensor(empty_indices, empty_values, [4, 2]) empty_sparse_column = empty_sparse_column.eval(session=sess) diff --git a/tensorflow/contrib/boosted_trees/python/training/functions/gbdt_batch.py b/tensorflow/contrib/boosted_trees/python/training/functions/gbdt_batch.py index ab5713fbe2..9fdc2fc0c2 100644 --- a/tensorflow/contrib/boosted_trees/python/training/functions/gbdt_batch.py +++ b/tensorflow/contrib/boosted_trees/python/training/functions/gbdt_batch.py @@ -897,9 +897,9 @@ class GradientBoostedDecisionTreeModel(object): empty_hess_shape = [1] + self._hessian_shape.as_list() empty_grad_shape = [1] + self._gradient_shape.as_list() - empty_gradients = constant_op.constant( + empty_gradients = constant_op.constant_v1( [], dtype=dtypes.float32, shape=empty_grad_shape) - empty_hessians = constant_op.constant( + empty_hessians = constant_op.constant_v1( [], dtype=dtypes.float32, shape=empty_hess_shape) active_handlers = array_ops.unstack(active_handlers, axis=0) @@ -1257,13 +1257,12 @@ class GradientBoostedDecisionTreeModel(object): def _get_replica_device_setter(self, worker_device): """Creates a replica device setter.""" ps_tasks = self._num_ps_replicas - ps_ops = [ - "Variable", - "VariableV2", + ps_ops = list(device_setter.STANDARD_PS_OPS) + ps_ops.extend([ "DecisionTreeEnsembleResourceHandleOp", "StatsAccumulatorScalarResourceHandleOp", "StatsAccumulatorTensorResourceHandleOp", - ] + ]) ps_strategy = _OpRoundRobinStrategy(ps_ops, ps_tasks) return device_setter.replica_device_setter( worker_device=worker_device, diff --git a/tensorflow/contrib/boosted_trees/python/utils/losses.py b/tensorflow/contrib/boosted_trees/python/utils/losses.py index b5ebaf1999..220e981618 100644 --- a/tensorflow/contrib/boosted_trees/python/utils/losses.py +++ b/tensorflow/contrib/boosted_trees/python/utils/losses.py @@ -48,6 +48,47 @@ def per_example_logistic_loss(labels, weights, predictions): labels=labels, logits=predictions) return unweighted_loss * weights, control_flow_ops.no_op() +# MUST USE WITH HESSIAN REGULARIZATION, +# This loss can have zero hessian, so it must be used with l2 or min_node_weight +# regularization. +# An example config is +# learner_config.constraints.min_node_weight = 1 / num_examples_per_layer +# learner_config.regularization.l2 = 1.0 / num_examples_per_layer +# TODO(nponomareva): make it multidimensional so we can estimate several +# quantiles at once. +def per_example_quantile_regression_loss(labels, weights, predictions, + quantile): + """Smoothed loss for quantile regression. + + The standard quantile regression loss is quantile*(y-y') when y>y' and + (quantile-1)*(y-y') otherwise, y' is a prediction, y is a label. The impl + below is this loss but squared in the region where the loss value < 1. + + Args: + labels: Rank 2 (N, D) tensor of per-example labels. + weights: Rank 2 (N, 1) tensor of per-example weights. + predictions: Rank 2 (N, D) tensor of per-example predictions. + quantile: The quantile to use. + + Returns: + loss: A Rank 2 (N, 1) tensor of per-example quantile loss. + update_op: An update operation to update the loss's internal state. + """ + labels = math_ops.to_float(labels) + error = labels - predictions + square_loss_right = array_ops.where(error * quantile < 1.0, + math_ops.square(quantile * error), + quantile * error) + square_loss_left = array_ops.where(error * (quantile - 1) < 1, + math_ops.square((quantile - 1) * error), + (quantile - 1) * error) + + unweighted_loss = array_ops.where(error > 0, square_loss_right, + square_loss_left) + if weights is None: + return unweighted_loss, control_flow_ops.no_op() + else: + return unweighted_loss * weights, control_flow_ops.no_op() # This is classical form of Maximum entropy loss, that is twice differentiable # (sparse_softmax_cross_entropy which is what we go for is not twice @@ -78,8 +119,7 @@ def per_example_maxent_loss(labels, weights, logits, num_classes, eps=1e-15): labels = array_ops.expand_dims(labels, 1) # Labels are indices of classes, convert them to one hot encodings. target_one_hot = array_ops.one_hot(indices=labels, depth=num_classes) - labels = math_ops.reduce_sum( - input_tensor=target_one_hot, reduction_indices=[1]) + labels = math_ops.reduce_sum(input_tensor=target_one_hot, axis=[1]) labels = math_ops.to_float(labels) # Calculate softmax probabilities for each class. diff --git a/tensorflow/contrib/checkpoint/python/containers.py b/tensorflow/contrib/checkpoint/python/containers.py index 242c1e8ba4..5418e2605b 100644 --- a/tensorflow/contrib/checkpoint/python/containers.py +++ b/tensorflow/contrib/checkpoint/python/containers.py @@ -46,6 +46,10 @@ class UniqueNameTracker(data_structures.CheckpointableDataStructure): self._maybe_initialize_checkpointable() self._name_counts = {} + @property + def _values(self): + return [dep.ref for dep in self._checkpoint_dependencies] + def track(self, checkpointable, base_name): """Add a dependency on `checkpointable`. diff --git a/tensorflow/contrib/cluster_resolver/BUILD b/tensorflow/contrib/cluster_resolver/BUILD index 9e1867ea9d..f944b7f884 100644 --- a/tensorflow/contrib/cluster_resolver/BUILD +++ b/tensorflow/contrib/cluster_resolver/BUILD @@ -21,173 +21,25 @@ py_library( py_library( name = "cluster_resolver_py", - srcs = [ + srcs = glob([ "__init__.py", - "python/training/__init__.py", - ], + "python/training/*.py", + ]), srcs_version = "PY2AND3", visibility = ["//visibility:public"], - deps = [ - ":base_cluster_resolver_py", - ":gce_cluster_resolver_py", - ":kubernetes_cluster_resolver_py", - ":slurm_cluster_resolver_py", - ":tfconfig_cluster_resolver_py", - ":tpu_cluster_resolver_py", - "//tensorflow/python:util", - ], -) - -py_library( - name = "base_cluster_resolver_py", - srcs = ["python/training/cluster_resolver.py"], - srcs_version = "PY2AND3", - deps = [ - "//tensorflow/python:training", - ], -) - -py_library( - name = "gce_cluster_resolver_py", - srcs = ["python/training/gce_cluster_resolver.py"], - srcs_version = "PY2AND3", - deps = [ - ":base_cluster_resolver_py", - "//tensorflow/python:training", - ], -) - -py_library( - name = "tfconfig_cluster_resolver_py", - srcs = ["python/training/tfconfig_cluster_resolver.py"], - srcs_version = "PY2AND3", - deps = [ - ":base_cluster_resolver_py", - "//tensorflow/python:training", - ], -) - -py_library( - name = "tpu_cluster_resolver_py", - srcs = ["python/training/tpu_cluster_resolver.py"], - srcs_version = "PY2AND3", - deps = [ - ":base_cluster_resolver_py", - "//tensorflow/python:training", - ], -) - -py_library( - name = "slurm_cluster_resolver_py", - srcs = ["python/training/slurm_cluster_resolver.py"], - srcs_version = "PY2AND3", - deps = [ - ":base_cluster_resolver_py", - "//tensorflow/python:training", - ], -) - -py_library( - name = "kubernetes_cluster_resolver_py", - srcs = ["python/training/kubernetes_cluster_resolver.py"], - srcs_version = "PY2AND3", - deps = [ - ":base_cluster_resolver_py", - "//tensorflow/python:training", - ], -) - -tf_py_test( - name = "base_cluster_resolver_py_test", - srcs = ["python/training/cluster_resolver_test.py"], - additional_deps = [ - ":cluster_resolver_py", - "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_for_generated_wrappers", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:platform_test", - "//tensorflow/python:training", - ], - main = "python/training/cluster_resolver_test.py", -) - -tf_py_test( - name = "gce_cluster_resolver_py_test", - size = "small", - srcs = ["python/training/gce_cluster_resolver_test.py"], - additional_deps = [ - ":cluster_resolver_py", - ":gce_cluster_resolver_py", - "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_for_generated_wrappers", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:platform_test", - "//tensorflow/python:training", - ], - main = "python/training/gce_cluster_resolver_test.py", -) - -tf_py_test( - name = "tfconfig_cluster_resolver_py_test", - size = "small", - srcs = ["python/training/tfconfig_cluster_resolver_test.py"], - additional_deps = [ - ":tfconfig_cluster_resolver_py", - "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_for_generated_wrappers", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:platform_test", - "//tensorflow/python:training", - ], - grpc_enabled = True, - main = "python/training/tfconfig_cluster_resolver_test.py", -) - -tf_py_test( - name = "tpu_cluster_resolver_py_test", - size = "small", - srcs = ["python/training/tpu_cluster_resolver_test.py"], - additional_deps = [ - ":tpu_cluster_resolver_py", - "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_for_generated_wrappers", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:platform_test", - "//tensorflow/python:training", - ], - grpc_enabled = True, - main = "python/training/tpu_cluster_resolver_test.py", -) - -tf_py_test( - name = "slurm_cluster_resolver_py_test", - size = "small", - srcs = ["python/training/slurm_cluster_resolver_test.py"], - additional_deps = [ - ":cluster_resolver_py", - ":slurm_cluster_resolver_py", - "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_for_generated_wrappers", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:platform_test", - "//tensorflow/python:training", - ], - main = "python/training/slurm_cluster_resolver_test.py", - tags = [], + deps = ["//tensorflow/python/distribute/cluster_resolver:cluster_resolver_lib"], ) tf_py_test( - name = "kubernetes_cluster_resolver_py_test", - size = "small", - srcs = ["python/training/kubernetes_cluster_resolver_test.py"], + name = "cluster_resolver_initialization_test", + srcs = ["cluster_resolver_initialization_test.py"], additional_deps = [ ":cluster_resolver_py", - ":kubernetes_cluster_resolver_py", "//tensorflow/python:client_testlib", "//tensorflow/python:framework_for_generated_wrappers", "//tensorflow/python:framework_test_lib", "//tensorflow/python:platform_test", "//tensorflow/python:training", ], - main = "python/training/kubernetes_cluster_resolver_test.py", + main = "cluster_resolver_initialization_test.py", ) diff --git a/tensorflow/contrib/cluster_resolver/__init__.py b/tensorflow/contrib/cluster_resolver/__init__.py index fd1263fe81..390b3e7550 100644 --- a/tensorflow/contrib/cluster_resolver/__init__.py +++ b/tensorflow/contrib/cluster_resolver/__init__.py @@ -20,12 +20,14 @@ from __future__ import division from __future__ import print_function # pylint: disable=wildcard-import,unused-import -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import ClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import SimpleClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import UnionClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.gce_cluster_resolver import GceClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.slurm_cluster_resolver import SlurmClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.tpu_cluster_resolver import TPUClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import ClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import SimpleClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import UnionClusterResolver +from tensorflow.python.distribute.cluster_resolver.gce_cluster_resolver import GceClusterResolver +from tensorflow.python.distribute.cluster_resolver.kubernetes_cluster_resolver import KubernetesClusterResolver +from tensorflow.python.distribute.cluster_resolver.slurm_cluster_resolver import SlurmClusterResolver +from tensorflow.python.distribute.cluster_resolver.tfconfig_cluster_resolver import TFConfigClusterResolver +from tensorflow.python.distribute.cluster_resolver.tpu_cluster_resolver import TPUClusterResolver # pylint: enable=wildcard-import,unused-import from tensorflow.python.util.all_util import remove_undocumented @@ -35,6 +37,8 @@ _allowed_symbols = [ 'SimpleClusterResolver', 'UnionClusterResolver', 'GceClusterResolver', + 'KubernetesClusterResolver', + 'TFConfigClusterResolver', 'TPUClusterResolver', 'SlurmClusterResolver', ] diff --git a/tensorflow/contrib/cluster_resolver/cluster_resolver_initialization_test.py b/tensorflow/contrib/cluster_resolver/cluster_resolver_initialization_test.py new file mode 100644 index 0000000000..01ff1478c6 --- /dev/null +++ b/tensorflow/contrib/cluster_resolver/cluster_resolver_initialization_test.py @@ -0,0 +1,53 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests to ensure ClusterResolvers are usable via the old contrib path.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.contrib.cluster_resolver import SimpleClusterResolver +from tensorflow.contrib.cluster_resolver.python.training import cluster_resolver +from tensorflow.contrib.cluster_resolver.python.training import UnionClusterResolver +from tensorflow.python.platform import test +from tensorflow.python.training import server_lib + + +class ClusterResolverInitializationTest(test.TestCase): + + def testCreateSimpleClusterResolverFromLib(self): + base_cluster_spec = server_lib.ClusterSpec({ + "ps": ["ps0:2222", "ps1:2222"], + "worker": ["worker0:2222", "worker1:2222", "worker2:2222"] + }) + cluster_resolver.SimpleClusterResolver(base_cluster_spec) + + def testCreateSimpleClusterResolver(self): + base_cluster_spec = server_lib.ClusterSpec({ + "ps": ["ps0:2222", "ps1:2222"], + "worker": ["worker0:2222", "worker1:2222", "worker2:2222"] + }) + SimpleClusterResolver(base_cluster_spec) + + def testCreateUnionClusterResolver(self): + base_cluster_spec = server_lib.ClusterSpec({ + "ps": ["ps0:2222", "ps1:2222"], + "worker": ["worker0:2222", "worker1:2222", "worker2:2222"] + }) + simple_cr = SimpleClusterResolver(base_cluster_spec) + UnionClusterResolver(simple_cr) + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/contrib/cluster_resolver/python/training/__init__.py b/tensorflow/contrib/cluster_resolver/python/training/__init__.py index 6d9120a3b9..10d93549eb 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/__init__.py +++ b/tensorflow/contrib/cluster_resolver/python/training/__init__.py @@ -18,11 +18,36 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import ClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import SimpleClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import UnionClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.gce_cluster_resolver import GceClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.kubernetes_cluster_resolver import KubernetesClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.slurm_cluster_resolver import SlurmClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.tfconfig_cluster_resolver import TFConfigClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.tpu_cluster_resolver import TPUClusterResolver +# This file (and all files in this directory in general) is a backwards +# compatibility shim that exists to re-export ClusterResolvers such that +# existing OSS code will not be broken. + +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import ClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import SimpleClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import UnionClusterResolver +from tensorflow.python.distribute.cluster_resolver.gce_cluster_resolver import GceClusterResolver +from tensorflow.python.distribute.cluster_resolver.kubernetes_cluster_resolver import KubernetesClusterResolver +from tensorflow.python.distribute.cluster_resolver.slurm_cluster_resolver import SlurmClusterResolver +from tensorflow.python.distribute.cluster_resolver.tfconfig_cluster_resolver import TFConfigClusterResolver +from tensorflow.python.distribute.cluster_resolver.tpu_cluster_resolver import TPUClusterResolver + +from tensorflow.python.util.all_util import remove_undocumented + +_allowed_symbols = [ + 'cluster_resolver', + 'gce_cluster_resolver', + 'kubernetes_cluster_resolver', + 'slurm_cluster_resolver', + 'tfconfig_cluster_resolver', + 'tpu_cluster_resolver', + 'ClusterResolver', + 'SimpleClusterResolver', + 'UnionClusterResolver', + 'GceClusterResolver', + 'KubernetesClusterResolver', + 'TFConfigClusterResolver', + 'TPUClusterResolver', + 'SlurmClusterResolver', +] + +remove_undocumented(__name__, _allowed_symbols) diff --git a/tensorflow/contrib/cluster_resolver/python/training/cluster_resolver.py b/tensorflow/contrib/cluster_resolver/python/training/cluster_resolver.py index 40b1e667ee..99840fb516 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/cluster_resolver.py +++ b/tensorflow/contrib/cluster_resolver/python/training/cluster_resolver.py @@ -1,4 +1,4 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,333 +12,29 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Cluster Resolvers are used for dynamic cluster IP/hostname resolution.""" +"""Stub file for ClusterResolver to maintain backwards compatibility.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import abc +# This file (and all files in this directory in general) is a backwards +# compatibility shim that exists to re-export ClusterResolvers such that +# existing OSS code will not be broken. -import six +# pylint: disable=unused-import +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import ClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import SimpleClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import UnionClusterResolver +# pylint: enable=unused-import -from tensorflow.python.training.server_lib import ClusterSpec +from tensorflow.python.util.all_util import remove_undocumented +_allowed_symbols = [ + 'ClusterResolver', + 'SimpleClusterResolver', + 'UnionClusterResolver', +] -def _format_master_url(master, rpc_layer=None): - if rpc_layer: - return '%s://%s' % (rpc_layer, master) - else: - return master +remove_undocumented(__name__, _allowed_symbols) - -@six.add_metaclass(abc.ABCMeta) -class ClusterResolver(object): - """Abstract class for all implementations of ClusterResolvers. - - This defines the skeleton for all implementations of ClusterResolvers. - ClusterResolvers are a way for TensorFlow to communicate with various cluster - management systems (e.g. GCE, AWS, etc...). - - By letting TensorFlow communicate with these systems, we will be able to - automatically discover and resolve IP addresses for various TensorFlow - workers. This will eventually allow us to automatically recover from - underlying machine failures and scale TensorFlow worker clusters up and down. - """ - - @abc.abstractmethod - def cluster_spec(self): - """Retrieve the current state of the cluster and returns a ClusterSpec. - - Returns: - A ClusterSpec representing the state of the cluster at the moment this - function is called. - - Implementors of this function must take care in ensuring that the - ClusterSpec returned is up-to-date at the time of calling this function. - This usually means retrieving the information from the underlying cluster - management system every time this function is invoked and reconstructing - a cluster_spec, rather than attempting to cache anything. - """ - raise NotImplementedError( - 'cluster_spec is not implemented for {}.'.format(self)) - - @abc.abstractmethod - def master(self, task_type=None, task_index=None, rpc_layer=None): - """Retrieves the name or URL of the session master. - - Args: - task_type: (Optional) The type of the TensorFlow task of the master. - task_index: (Optional) The index of the TensorFlow task of the master. - rpc_layer: (Optional) The RPC protocol for the given cluster. - - Returns: - The name or URL of the session master. - - Implementors of this function must take care in ensuring that the master - returned is up-to-date at the time to calling this function. This usually - means retrieving the master every time this function is invoked. - """ - raise NotImplementedError('master is not implemented for {}.'.format(self)) - - -class SimpleClusterResolver(ClusterResolver): - """Simple implementation of ClusterResolver that accepts a ClusterSpec.""" - - def __init__(self, cluster_spec, master='', task_type=None, task_index=None, - environment='', num_accelerators_per_worker=0, - rpc_layer=None): - """Creates a SimpleClusterResolver from a ClusterSpec.""" - super(SimpleClusterResolver, self).__init__() - - self._task_type = task_type - self._task_index = task_index - self._environment = environment - self._num_accelerators_per_worker = num_accelerators_per_worker - self._rpc_layer = rpc_layer - - if not isinstance(cluster_spec, ClusterSpec): - raise TypeError('cluster_spec must be a ClusterSpec.') - self._cluster_spec = cluster_spec - - if not isinstance(master, str): - raise TypeError('master must be a string.') - self._master = master - - def cluster_spec(self): - """Returns the ClusterSpec passed into the constructor.""" - return self._cluster_spec - - def master(self, task_type=None, task_index=None, rpc_layer=None): - """Returns the master address to use when creating a session. - - Args: - task_type: (Optional) The type of the TensorFlow task of the master. - task_index: (Optional) The index of the TensorFlow task of the master. - rpc_layer: (Optional) The RPC used by distributed TensorFlow. - - Returns: - The name or URL of the session master. - - If a task_type and task_index is given, this will override the `master` - string passed into the initialization function. - """ - if task_type is not None and task_index is not None: - master = self.cluster_spec().task_address(task_type, task_index) - else: - master = self._master - - return _format_master_url(master, rpc_layer or self._rpc_layer) - - @property - def task_type(self): - return self._task_type - - @property - def task_index(self): - return self._task_index - - @task_type.setter - def task_type(self, task_type): - self._task_type = task_type - - @task_index.setter - def task_index(self, task_index): - self._task_index = task_index - - @property - def environment(self): - return self._environment - - def num_accelerators_per_worker(self, session_config=None): - """Returns the number of accelerator cores per worker. - - Args: - session_config: Unused. The SimpleClusterResolver does not do automatic - detection of accelerators, so a TensorFlow session will never be - created, and thus a `session_config` is never necessary here, and will - be ignored. - """ - del session_config - return self._num_accelerators_per_worker - - @property - def rpc_layer(self): - return self._rpc_layer - - @rpc_layer.setter - def rpc_layer(self, rpc_layer): - self._rpc_layer = rpc_layer - - -class UnionClusterResolver(ClusterResolver): - """Performs a union on underlying ClusterResolvers. - - This class performs a union given two or more existing ClusterResolvers. It - merges the underlying ClusterResolvers, and returns one unified ClusterSpec - when cluster_spec is called. The details of the merge function is - documented in the cluster_spec function. - - For additional Cluster Resolver properties such as task type, task index, - rpc layer, environment, etc..., we will return the value from the first - ClusterResolver in the union. - """ - - def __init__(self, *args, **kwargs): - """Initializes a UnionClusterResolver with other ClusterResolvers. - - Args: - *args: `ClusterResolver` objects to be unionized. - **kwargs: - rpc_layer - (Optional) Override value for the RPC layer used by - TensorFlow. - task_type - (Optional) Override value for the current task type. - task_index - (Optional) Override value for the current task index. - - Raises: - TypeError: If any argument is not a subclass of `ClusterResolvers`. - ValueError: If there are no arguments passed. - """ - super(UnionClusterResolver, self).__init__() - - self._rpc_layer = kwargs.pop('rpc_layer', None) - self._task_type = kwargs.pop('task_type', None) - self._task_index = kwargs.pop('task_index', None) - - if kwargs: - raise ValueError('Unexpected kwargs provided {!r}'.format(kwargs)) - - if not args: - raise ValueError('At least one ClusterResolver is required.') - - for cluster_resolver in args: - if not isinstance(cluster_resolver, ClusterResolver): - raise TypeError('All arguments must be a sub-class of ' - '`ClusterResolver.`') - self._cluster_resolvers = args - - def cluster_spec(self): - """Returns a union of all the ClusterSpecs from the ClusterResolvers. - - Returns: - A ClusterSpec containing host information merged from all the underlying - ClusterResolvers. - - Raises: - KeyError: If there are conflicting keys detected when merging two or - more dictionaries, this exception is raised. - - Note: If there are multiple ClusterResolvers exposing ClusterSpecs with the - same job name, we will merge the list/dict of workers. - - If *all* underlying ClusterSpecs expose the set of workers as lists, we will - concatenate the lists of workers, starting with the list of workers from - the first ClusterResolver passed into the constructor. - - If *any* of the ClusterSpecs expose the set of workers as a dict, we will - treat all the sets of workers as dicts (even if they are returned as lists) - and will only merge them into a dict if there is no conflicting keys. If - there is a conflicting key, we will raise a `KeyError`. - """ - - merged_cluster = {} - - # We figure out whether it is all lists for a particular job, or whether - # there are dicts inside. - for cluster_resolver in self._cluster_resolvers: - cluster_spec = cluster_resolver.cluster_spec() - cluster_dict = cluster_spec.as_dict() - - for job_name, tasks in cluster_dict.items(): - if job_name in merged_cluster: - # If we see a dict, then we write a dict out regardless. - if isinstance(tasks, dict): - merged_cluster[job_name] = {} - else: - # We take whichever type is present. - if isinstance(tasks, list): - merged_cluster[job_name] = [] - else: - merged_cluster[job_name] = {} - - # We then do the merge as appropriate in merged_cluster[job]. - for cluster_resolver in self._cluster_resolvers: - cluster_spec = cluster_resolver.cluster_spec() - cluster_dict = cluster_spec.as_dict() - - for job_name, tasks in cluster_dict.items(): - if isinstance(merged_cluster[job_name], list): - # We all have lists, we can just concatenate and be done. - merged_cluster[job_name].extend(tasks) - else: - if isinstance(tasks, list): - # We convert to a dictionary if the type is a list. - task_dict = dict(zip(range(0, len(tasks)), tasks)) - else: - # We can simply make a copy (for update) and be done. - task_dict = tasks.copy() - - # We detect if there are duplicates, and raise an error if so. - task_keys = set(task_dict) - merged_keys = set(merged_cluster[job_name].keys()) - intersected_keys = task_keys.intersection(merged_keys) - if intersected_keys: - raise KeyError('Duplicate keys detected when merging two ' - 'ClusterSpecs: %s' % repr(intersected_keys)) - - # We do the merge after all the processing. - merged_cluster[job_name].update(task_dict) - - return ClusterSpec(merged_cluster) - - def master(self, task_type=None, task_index=None, rpc_layer=None): - """Returns the master address to use when creating a session. - - This usually returns the master from the first ClusterResolver passed in, - but you can override this by specifying the task_type and task_index. - - Args: - task_type: (Optional) The type of the TensorFlow task of the master. - task_index: (Optional) The index of the TensorFlow task of the master. - rpc_layer: (Optional) The RPC protocol for the given cluster. - - Returns: - The name or URL of the session master. - """ - if task_type is not None and task_index is not None: - master = self.cluster_spec().task_address(task_type, task_index) - return _format_master_url(master, rpc_layer or self._rpc_layer) - - return self._cluster_resolvers[0].master(rpc_layer=rpc_layer) - - @property - def task_type(self): - return self._task_type or self._cluster_resolvers[0].task_type - - @property - def task_index(self): - return self._task_index or self._cluster_resolvers[0].task_index - - @task_type.setter - def task_type(self, task_type): - self._task_type = task_type - - @task_index.setter - def task_index(self, task_index): - self._task_index = task_index - - @property - def environment(self): - return self._cluster_resolvers[0].environment - - def num_accelerators_per_worker(self, session_config=None): - return self._cluster_resolvers[0].num_accelerators_per_worker( - session_config) - - @property - def rpc_layer(self): - return self._rpc_layer or self._cluster_resolvers[0].rpc_layer - - @rpc_layer.setter - def rpc_layer(self, rpc_layer): - self._rpc_layer = rpc_layer diff --git a/tensorflow/contrib/cluster_resolver/python/training/gce_cluster_resolver.py b/tensorflow/contrib/cluster_resolver/python/training/gce_cluster_resolver.py index 195b68959b..55e61155c6 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/gce_cluster_resolver.py +++ b/tensorflow/contrib/cluster_resolver/python/training/gce_cluster_resolver.py @@ -1,4 +1,4 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,197 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Implementation of Cluster Resolvers for GCE Instance Groups.""" +"""Stub file for GceClusterResolver to maintain backwards compatibility.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function +# This file (and all files in this directory in general) is a backwards +# compatibility shim that exists to re-export ClusterResolvers such that +# existing OSS code will not be broken. -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import ClusterResolver -from tensorflow.python.training.server_lib import ClusterSpec +# pylint: disable=unused-import +from tensorflow.python.distribute.cluster_resolver.gce_cluster_resolver import GceClusterResolver +# pylint: enable=unused-import -_GOOGLE_API_CLIENT_INSTALLED = True -try: - from googleapiclient import discovery # pylint: disable=g-import-not-at-top - from oauth2client.client import GoogleCredentials # pylint: disable=g-import-not-at-top -except ImportError: - _GOOGLE_API_CLIENT_INSTALLED = False +from tensorflow.python.util.all_util import remove_undocumented +_allowed_symbols = [ + 'GceClusterResolver', +] -def _format_master_url(master, rpc_layer=None): - return '%s://%s' % (rpc_layer, master) if rpc_layer else master - - -class GceClusterResolver(ClusterResolver): - """Cluster Resolver for Google Compute Engine. - - This is an implementation of cluster resolvers for the Google Compute Engine - instance group platform. By specifying a project, zone, and instance group, - this will retrieve the IP address of all the instances within the instance - group and return a Cluster Resolver object suitable for use for distributed - TensorFlow. - """ - - def __init__(self, - project, - zone, - instance_group, - port, - task_type='worker', - task_index=0, - rpc_layer='grpc', - num_accelerators_per_worker=0, - credentials='default', - service=None): - """Creates a new GceClusterResolver object. - - This takes in a few parameters and creates a GceClusterResolver project. It - will then use these parameters to query the GCE API for the IP addresses of - each instance in the instance group. - - Args: - project: Name of the GCE project. - zone: Zone of the GCE instance group. - instance_group: Name of the GCE instance group. - port: Port of the listening TensorFlow server (default: 8470) - task_type: Name of the TensorFlow job this GCE instance group of VM - instances belong to. - task_index: The task index for this particular VM, within the GCE - instance group. In particular, every single instance should be assigned - a unique ordinal index within an instance group manually so that they - can be distinguished from each other. - rpc_layer: The RPC layer TensorFlow should use to communicate across - instances. - num_accelerators_per_worker: Number of accelerators (GPUs) present per - instance. - credentials: GCE Credentials. If nothing is specified, this defaults to - GoogleCredentials.get_application_default(). - service: The GCE API object returned by the googleapiclient.discovery - function. (Default: discovery.build('compute', 'v1')). If you specify a - custom service object, then the credentials parameter will be ignored. - - Raises: - ImportError: If the googleapiclient is not installed. - """ - self._project = project - self._zone = zone - self._instance_group = instance_group - self._task_type = task_type - self._task_index = task_index - self._rpc_layer = rpc_layer - self._port = port - self._credentials = credentials - - if credentials == 'default': - if _GOOGLE_API_CLIENT_INSTALLED: - self._credentials = GoogleCredentials.get_application_default() - - if service is None: - if not _GOOGLE_API_CLIENT_INSTALLED: - raise ImportError('googleapiclient must be installed before using the ' - 'GCE cluster resolver') - self._service = discovery.build( - 'compute', 'v1', - credentials=self._credentials) - else: - self._service = service - - def cluster_spec(self): - """Returns a ClusterSpec object based on the latest instance group info. - - This returns a ClusterSpec object for use based on information from the - specified instance group. We will retrieve the information from the GCE APIs - every time this method is called. - - Returns: - A ClusterSpec containing host information retrieved from GCE. - """ - request_body = {'instanceState': 'RUNNING'} - request = self._service.instanceGroups().listInstances( - project=self._project, - zone=self._zone, - instanceGroups=self._instance_group, - body=request_body, - orderBy='name') - - worker_list = [] - - while request is not None: - response = request.execute() - - items = response['items'] - for instance in items: - instance_name = instance['instance'].split('/')[-1] - - instance_request = self._service.instances().get( - project=self._project, - zone=self._zone, - instance=instance_name) - - if instance_request is not None: - instance_details = instance_request.execute() - ip_address = instance_details['networkInterfaces'][0]['networkIP'] - instance_url = '%s:%s' % (ip_address, self._port) - worker_list.append(instance_url) - - request = self._service.instanceGroups().listInstances_next( - previous_request=request, - previous_response=response) - - worker_list.sort() - return ClusterSpec({self._task_type: worker_list}) - - def master(self, task_type=None, task_index=None, rpc_layer=None): - task_type = task_type if task_type is not None else self._task_type - task_index = task_index if task_index is not None else self._task_index - - if task_type is not None and task_index is not None: - master = self.cluster_spec().task_address(task_type, task_index) - if rpc_layer or self._rpc_layer: - return '%s://%s' % (rpc_layer or self._rpc_layer, master) - else: - return master - - return '' - - @property - def task_type(self): - return self._task_type - - @property - def task_index(self): - return self._task_index - - @task_type.setter - def task_type(self, task_type): - raise RuntimeError( - 'You cannot reset the task_type of the GceClusterResolver after it has ' - 'been created.') - - @task_index.setter - def task_index(self, task_index): - self._task_index = task_index - - @property - def environment(self): - """Returns the current environment which TensorFlow is running in. - - For users in the GCE environment, the environment property is always an - empty string, and Google users will not use this ClusterResolver for running - on internal systems. - """ - return '' - - @property - def rpc_layer(self): - return self._rpc_layer - - @rpc_layer.setter - def rpc_layer(self, rpc_layer): - self._rpc_layer = rpc_layer - - def num_accelerators_per_worker(self, session_config=None): - del session_config # Unused, since this is set manually in __init__. - return self._num_accelerators_per_worker - +remove_undocumented(__name__, _allowed_symbols) diff --git a/tensorflow/contrib/cluster_resolver/python/training/kubernetes_cluster_resolver.py b/tensorflow/contrib/cluster_resolver/python/training/kubernetes_cluster_resolver.py index ddae64839f..a8eaf33629 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/kubernetes_cluster_resolver.py +++ b/tensorflow/contrib/cluster_resolver/python/training/kubernetes_cluster_resolver.py @@ -12,121 +12,25 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Implementation of Cluster Resolvers for Kubernetes.""" +"""Stub file for KubernetesClusterResolver for backwards compatibility.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import ClusterResolver -from tensorflow.python.training import server_lib +# This file (and all files in this directory in general) is a backwards +# compatibility shim that exists to re-export ClusterResolvers such that +# existing OSS code will not be broken. -_KUBERNETES_API_CLIENT_INSTALLED = True -try: - from kubernetes import client as k8sclient # pylint: disable=g-import-not-at-top - from kubernetes import config as k8sconfig # pylint: disable=g-import-not-at-top -except ImportError: - _KUBERNETES_API_CLIENT_INSTALLED = False +# pylint: disable=unused-import +from tensorflow.python.distribute.cluster_resolver.kubernetes_cluster_resolver import KubernetesClusterResolver +# pylint: enable=unused-import +from tensorflow.python.util.all_util import remove_undocumented -class KubernetesClusterResolver(ClusterResolver): - """Cluster Resolver for Kubernetes. +_allowed_symbols = [ + 'KubernetesClusterResolver', +] - This is an implementation of cluster resolvers for Kubernetes. When given the - the Kubernetes namespace and label selector for pods, we will retrieve the - pod IP addresses of all running pods matching the selector, and return a - ClusterSpec based on that information. - """ +remove_undocumented(__name__, _allowed_symbols) - def __init__(self, - job_to_label_mapping=None, - tf_server_port=8470, - override_client=None): - """Initializes a new KubernetesClusterResolver. - - This initializes a new Kubernetes Cluster Resolver. The Cluster Resolver - will attempt to talk to the Kubernetes master to retrieve all the instances - of pods matching a label selector. - - Args: - job_to_label_mapping: A mapping of TensorFlow jobs to label selectors. - This allows users to specify many TensorFlow jobs in one Cluster - Resolver, and each job can have pods belong with different label - selectors. For example, a sample mapping might be - ``` - {'worker': ['job-name=worker-cluster-a', 'job-name=worker-cluster-b'], - 'ps': ['job-name=ps-1', 'job-name=ps-2']} - ``` - tf_server_port: The port the TensorFlow server is listening on. - override_client: The Kubernetes client (usually automatically retrieved - using `from kubernetes import client as k8sclient`). If you pass this - in, you are responsible for setting Kubernetes credentials manually. - - Raises: - ImportError: If the Kubernetes Python client is not installed and no - `override_client` is passed in. - """ - if _KUBERNETES_API_CLIENT_INSTALLED: - k8sconfig.load_kube_config() - - if not job_to_label_mapping: - job_to_label_mapping = {'worker': ['job-name=tensorflow']} - - if not override_client and not _KUBERNETES_API_CLIENT_INSTALLED: - raise ImportError('The Kubernetes Python client must be installed before' - 'using the Kubernetes Cluster Resolver. To install the' - 'Kubernetes Python client, run `pip install ' - 'kubernetes` on your command line.') - - self._job_to_label_mapping = job_to_label_mapping - self._tf_server_port = tf_server_port - self._override_client = override_client - - def master(self): - # TODO(frankchn): Figure out a standard way to pass in the current task type - # and task id via Kubernetes. - pass - - def get_master(self): - return self.master() - - def get_job_name(self): - return self._job_name - - def cluster_spec(self): - """Returns a ClusterSpec object based on the latest info from Kubernetes. - - We retrieve the information from the Kubernetes master every time this - method is called. - - Returns: - A ClusterSpec containing host information returned from Kubernetes. - - Raises: - RuntimeError: If any of the pods returned by the master is not in the - `Running` phase. - """ - if not self._override_client: - k8sconfig.load_kube_config() - - client = self._override_client or k8sclient.CoreV1Api() - cluster_map = {} - - for tf_job in self._job_to_label_mapping: - all_pods = [] - for selector in self._job_to_label_mapping[tf_job]: - ret = client.list_pod_for_all_namespaces(label_selector=selector) - selected_pods = [] - - # Sort the list by the name to make sure it doesn't change call to call. - for pod in sorted(ret.items, key=lambda x: x.metadata.name): - if pod.status.phase == 'Running': - selected_pods.append( - '%s:%s' % (pod.status.host_ip, self._tf_server_port)) - else: - raise RuntimeError('Pod "%s" is not running; phase: "%s"' % - (pod.metadata.name, pod.status.phase)) - all_pods.extend(selected_pods) - cluster_map[tf_job] = all_pods - - return server_lib.ClusterSpec(cluster_map) diff --git a/tensorflow/contrib/cluster_resolver/python/training/slurm_cluster_resolver.py b/tensorflow/contrib/cluster_resolver/python/training/slurm_cluster_resolver.py index dabe2fe1d3..fcd2a846ee 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/slurm_cluster_resolver.py +++ b/tensorflow/contrib/cluster_resolver/python/training/slurm_cluster_resolver.py @@ -12,185 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Implementation of Cluster Resolvers for Slurm workload manager.""" +"""Stub file for SlurmClusterResolver to maintain backwards compatibility.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import collections -import os -import subprocess +# This file (and all files in this directory in general) is a backwards +# compatibility shim that exists to re-export ClusterResolvers such that +# existing OSS code will not be broken. -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import ClusterResolver -from tensorflow.python.training.server_lib import ClusterSpec +# pylint: disable=unused-import +from tensorflow.python.distribute.cluster_resolver.slurm_cluster_resolver import SlurmClusterResolver +# pylint: enable=unused-import +from tensorflow.python.util.all_util import remove_undocumented -class SlurmClusterResolver(ClusterResolver): - """Cluster Resolver for system with Slurm workload manager. +_allowed_symbols = [ + 'SlurmClusterResolver', +] - This is an implementation of cluster resolvers for Slurm clusters. This allows - the specification of jobs and task counts, number of tasks per node, number of - GPUs on each node and number of GPUs for each task, It retrieves system - attributes by Slurm environment variables, resolves allocated computing node - names, construct a cluster and return a Cluster Resolver object which an be - use for distributed TensorFlow. - """ - - def _resolve_hostnames(self): - """Resolve host names of nodes allocated in current jobs. - - Returns: - A list of node names as strings. - """ - hostlist = (subprocess.check_output(['scontrol', 'show', 'hostname']). - decode('utf-8').strip().split('\n')) - return hostlist - - def __init__(self, - jobs, - port_base=8888, - gpus_per_node=1, - gpus_per_task=1, - tasks_per_node=None, - auto_set_gpu=True): - """Creates a new SlurmClusterResolver object. - - This takes in parameters and creates a SlurmClusterResolver object. It uses - those parameters to check which nodes will processes reside and resolves - their hostnames. With the number of the GPUs on each node and number of GPUs - for each task it offsets the port number for each processes and allocate - GPUs to tasks by setting environment variables. The resolver currently - supports homogeneous tasks and default Slurm process allocation. - - Args: - jobs: Dictionary with job names as key and number of tasks in the job as - value - port_base: The first port number to start with for processes on a node. - gpus_per_node: Number of GPUs available on each node. - gpus_per_task: Number of GPUs to be used for each task. - tasks_per_node: Number of tasks to run on each node, if not set defaults - to Slurm's output environment variable SLURM_NTASKS_PER_NODE. - auto_set_gpu: Set the visible CUDA devices automatically while resolving - the cluster by setting CUDA_VISIBLE_DEVICES environment variable. - Defaults to True. - - Returns: - A ClusterResolver object which can be used with distributed TensorFlow. - - Raises: - RuntimeError: If requested more GPUs per node then available or requested - more tasks then assigned tasks. - """ - - # check if launched by mpirun - if 'OMPI_COMM_WORLD_RANK' in os.environ: - self._rank = int(os.environ['OMPI_COMM_WORLD_RANK']) - num_tasks = int(os.environ['OMPI_COMM_WORLD_SIZE']) - else: - self._rank = int(os.environ['SLURM_PROCID']) - num_tasks = int(os.environ['SLURM_NTASKS']) - - self._jobs = collections.OrderedDict(sorted(jobs.items())) - self._port_base = port_base - - # user specification overrides SLURM specification - if tasks_per_node is not None: - self._tasks_per_node = tasks_per_node - elif tasks_per_node is None and 'SLURM_NTASKS_PER_NODE' in os.environ: - self._tasks_per_node = int(os.environ['SLURM_NTASKS_PER_NODE']) - else: - raise RuntimeError('Neither `tasks_per_node` or ' - 'SLURM_NTASKS_PER_NODE is set.') - - self._gpus_per_node = gpus_per_node - self._gpus_per_task = gpus_per_task - - self._auto_set_gpu = auto_set_gpu - self._job_name = None - self._task_index = None - - self._gpu_allocation = [] - self._cluster_allocation = {} - - if self._tasks_per_node * self._gpus_per_task > self._gpus_per_node: - raise RuntimeError('Requested more GPUs per node then available.') - - if sum(self._jobs.values()) != num_tasks: - raise RuntimeError('Requested more tasks then assigned tasks.') - - def cluster_spec(self): - """Returns a ClusterSpec object based on the latest instance group info. - - This returns a ClusterSpec object for use based on information from the - specified initialization parameters and Slurm environment variables. The - cluster specification is resolved each time this function is called. The - resolver extract hostnames of nodes by scontrol and pack tasks in that - order until a node a has number of tasks that is equal to specification. - GPUs on nodes are allocated to tasks by specification through setting - CUDA_VISIBLE_DEVICES environment variable. - - Returns: - A ClusterSpec containing host information retrieved from Slurm's - environment variables. - """ - hostlist = self._resolve_hostnames() - - task_list = [] - self._gpu_allocation = [] - self._cluster_allocation = {} - - for host in hostlist: - for port_offset, gpu_offset in zip( - range(self._tasks_per_node), - range(0, self._gpus_per_node, self._gpus_per_task)): - - host_addr = '%s:%d' % (host, self._port_base + port_offset) - task_list.append(host_addr) - gpu_id_list = [] - - for gpu_id in range(gpu_offset, gpu_offset + self._gpus_per_task): - gpu_id_list.append(str(gpu_id)) - - self._gpu_allocation.append(','.join(gpu_id_list)) - - cluster_rank_offset_start = 0 - cluster_rank_offset_end = 0 - - for job_name, num_tasks in self._jobs.items(): - cluster_rank_offset_end = cluster_rank_offset_start + num_tasks - - self._cluster_allocation[job_name] = \ - task_list[cluster_rank_offset_start:cluster_rank_offset_end] - - if self._rank >= cluster_rank_offset_start and \ - self._rank < cluster_rank_offset_end: - - self._job_name = job_name - self._task_index = self._rank - cluster_rank_offset_start - - cluster_rank_offset_start = cluster_rank_offset_end - - if self._auto_set_gpu is True: - os.environ['CUDA_VISIBLE_DEVICES'] = self._gpu_allocation[self._rank] - - return ClusterSpec(self._cluster_allocation) - - def get_task_info(self): - """Returns job name and task_index for the process which calls this. - - This returns the job name and task index for the process which calls this - function according to its rank and cluster specification. The job name and - task index are set after a cluster is constructed by cluster_spec otherwise - defaults to None. - - Returns: - A string specifying job name the process belongs to and an integner - specifying the task index the process belongs to in that job. - """ - return self._job_name, self._task_index - - def master(self, task_type=None, task_index=None): - if task_type and task_index: - return self.cluster_spec().task_address(task_type, task_index) - return self._cluster_allocation[str(self._job_name)][self._task_index] +remove_undocumented(__name__, _allowed_symbols) diff --git a/tensorflow/contrib/cluster_resolver/python/training/tfconfig_cluster_resolver.py b/tensorflow/contrib/cluster_resolver/python/training/tfconfig_cluster_resolver.py index 7bbd189d03..9db7f47dcb 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/tfconfig_cluster_resolver.py +++ b/tensorflow/contrib/cluster_resolver/python/training/tfconfig_cluster_resolver.py @@ -12,81 +12,25 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Implementation of Cluster Resolvers for TF_CONFIG Environment Variables.""" - +"""Stub file for TFConfigClusterResolver to maintain backwards compatibility.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import json -import os - -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import ClusterResolver -from tensorflow.python.training.server_lib import ClusterSpec - -_TF_CONFIG_ENV = 'TF_CONFIG' -_SESSION_MASTER_KEY = 'session_master' - - -class TFConfigClusterResolver(ClusterResolver): - """Implementation of a ClusterResolver which reads the TF_CONFIG EnvVar.""" - - def _load_tf_config(self): - return json.loads(os.environ.get(_TF_CONFIG_ENV, '{}')) - - def cluster_spec(self): - """Returns a ClusterSpec based on the TF_CONFIG environment variable. - - Returns: - A ClusterSpec with information from the TF_CONFIG environment variable. - """ - tf_config = self._load_tf_config() - if 'cluster' not in tf_config: - return ClusterSpec({}) - return ClusterSpec(tf_config['cluster']) - - def master(self, task_type=None, task_index=0): - """Returns the master address to use when creating a TensorFlow session. - - Args: - task_type: (String, optional) Overrides and sets the task_type of the - master. - task_index: (Integer, optional) Overrides and sets the task id of the - master. - - Returns: - The address of the master. - - Raises: - RuntimeError: If the task_type or task_id is not specified and the - `TF_CONFIG` environment variable does not contain a task section. - """ +# This file (and all files in this directory in general) is a backwards +# compatibility shim that exists to re-export ClusterResolvers such that +# existing OSS code will not be broken. - # If `session_master` is set, just use that. - tf_config = self._load_tf_config() - if _SESSION_MASTER_KEY in tf_config: - return tf_config[_SESSION_MASTER_KEY] +# pylint: disable=unused-import +from tensorflow.python.distribute.cluster_resolver.tfconfig_cluster_resolver import TFConfigClusterResolver +# pylint: enable=unused-import - if 'rpc_layer' in tf_config: - rpclayer = '%s://' % tf_config['rpc_layer'] - else: - rpclayer = '' +from tensorflow.python.util.all_util import remove_undocumented - # Return an empty string if we are the only job in the ClusterSpec. - cluster_spec = self.cluster_spec() - if (not cluster_spec.jobs or - (len(cluster_spec.jobs) == 1 and - len(cluster_spec.job_tasks(cluster_spec.jobs[0])) == 1)): - return '' +_allowed_symbols = [ + 'TFConfigClusterResolver', +] - # We try to auto-detect the task type and id, but uses the user-supplied one - # where available - if not task_type: - if 'task' not in tf_config: - raise RuntimeError('You must either specify a `task_type`, or your ' - 'TF_CONFIG must contain a `task` section.') - task_type = tf_config['task']['type'] - task_index = tf_config['task']['index'] +remove_undocumented(__name__, _allowed_symbols) - return rpclayer + cluster_spec.task_address(task_type, task_index) diff --git a/tensorflow/contrib/cluster_resolver/python/training/tpu_cluster_resolver.py b/tensorflow/contrib/cluster_resolver/python/training/tpu_cluster_resolver.py index 1f6803a9ff..3a1eaccd06 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/tpu_cluster_resolver.py +++ b/tensorflow/contrib/cluster_resolver/python/training/tpu_cluster_resolver.py @@ -1,4 +1,4 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,341 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Implementation of Cluster Resolvers for Cloud TPUs.""" +"""Stub file for TPUClusterResolver to maintain backwards compatibility.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import os +# This file (and all files in this directory in general) is a backwards +# compatibility shim that exists to re-export ClusterResolvers such that +# existing OSS code will not be broken. -from six.moves.urllib.request import Request -from six.moves.urllib.request import urlopen +# pylint: disable=unused-import +from tensorflow.python.distribute.cluster_resolver.tpu_cluster_resolver import TPUClusterResolver +# pylint: enable=unused-import -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import ClusterResolver -from tensorflow.python.training import server_lib -from tensorflow.python.util import compat +from tensorflow.python.util.all_util import remove_undocumented -_GOOGLE_API_CLIENT_INSTALLED = True -try: - from googleapiclient import discovery # pylint: disable=g-import-not-at-top - from oauth2client.client import GoogleCredentials # pylint: disable=g-import-not-at-top -except ImportError: - _GOOGLE_API_CLIENT_INSTALLED = False +_allowed_symbols = [ + 'TPUClusterResolver', +] - -_GKE_ENV_VARIABLE = 'KUBE_GOOGLE_CLOUD_TPU_ENDPOINTS' -_ENDPOINTS_SEPARATOR = ',' -_DEFAULT_ENV_VARIABLE = 'TPU_NAME' -_DISCOVERY_SERVICE_URL_ENV_VARIABLE = 'TPU_API_DISCOVERY_URL' - - -class TPUClusterResolver(ClusterResolver): - """Cluster Resolver for Google Cloud TPUs. - - This is an implementation of cluster resolvers for the Google Cloud TPU - service. As Cloud TPUs are in alpha, you will need to specify a API definition - file for this to consume, in addition to a list of Cloud TPUs in your Google - Cloud Platform project. - """ - - def _tpuService(self): - """Creates a new Cloud TPU API object. - - This works around an issue where the underlying HTTP connection sometimes - times out when the script has been running for too long. Other methods in - this object calls this method to get a new API object whenever they need - to communicate with the Cloud API. - - Returns: - A Google Cloud TPU API object. - """ - if self._service: - return self._service - - credentials = self._credentials - if credentials is None or credentials == 'default': - credentials = GoogleCredentials.get_application_default() - - if self._discovery_url: - return discovery.build( - 'tpu', 'v1alpha1', - credentials=credentials, - discoveryServiceUrl=self._discovery_url) - else: - return discovery.build( - 'tpu', 'v1alpha1', - credentials=credentials) - - def _requestComputeMetadata(self, path): - req = Request('http://metadata/computeMetadata/v1/%s' % path, - headers={'Metadata-Flavor': 'Google'}) - resp = urlopen(req) - return compat.as_bytes(resp.read()) - - def _shouldResolve(self): - if (self._tpu == compat.as_bytes('') or - self._tpu == compat.as_bytes('local') or - self._tpu.startswith(compat.as_bytes('/bns')) or - self._tpu.startswith(compat.as_bytes('localhost:')) or - self._tpu.startswith(compat.as_bytes('grpc://'))): - return False - return True - - @staticmethod - def _inGke(): - """When running in GKE, the environment variable will be set.""" - return _GKE_ENV_VARIABLE in os.environ - - @staticmethod - def _gkeEndpoints(): - return os.environ[_GKE_ENV_VARIABLE] - - @staticmethod - def _envVarFallback(): - if _DEFAULT_ENV_VARIABLE in os.environ: - return os.environ[_DEFAULT_ENV_VARIABLE] - return None - - @staticmethod - def _environmentDiscoveryUrl(): - return os.environ.get(_DISCOVERY_SERVICE_URL_ENV_VARIABLE) - - def __init__(self, - tpu=None, - zone=None, - project=None, - job_name='worker', - coordinator_name=None, - coordinator_address=None, - credentials='default', - service=None, - discovery_url=None): - """Creates a new TPUClusterResolver object. - - The ClusterResolver will then use the parameters to query the Cloud TPU APIs - for the IP addresses and ports of each Cloud TPU listed. - - Args: - tpu: Either a string, or a list of strings corresponding to the TPUs to - use. If the single string is the empty string, the string 'local', or a - string that begins with 'grpc://' or '/bns', then it is assumed to not - correspond with a Cloud TPU and will instead be passed as the session - master and no ClusterSpec propagation will be done. - zone: Zone where the TPUs are located. If omitted or empty, we will assume - that the zone of the TPU is the same as the zone of the GCE VM, which we - will try to discover from the GCE metadata service. - project: Name of the GCP project containing Cloud TPUs. If omitted or - empty, we will try to discover the project name of the GCE VM from the - GCE metadata service. - job_name: Name of the TensorFlow job the TPUs belong to. - coordinator_name: The name to use for the coordinator. Set to None if the - coordinator should not be included in the computed ClusterSpec. - coordinator_address: The address of the coordinator (typically an ip:port - pair). If set to None, a TF server will be started. If coordinator_name - is None, a TF server will not be started even if coordinator_address is - None. - credentials: GCE Credentials. If None, then we use default credentials - from the oauth2client - service: The GCE API object returned by the googleapiclient.discovery - function. If you specify a custom service object, then the credentials - parameter will be ignored. - discovery_url: A URL template that points to the location of - the discovery service. It should have two parameters {api} and - {apiVersion} that when filled in produce an absolute URL to the - discovery document for that service. The environment variable - 'TPU_API_DISCOVERY_URL' will override this. - - Raises: - ImportError: If the googleapiclient is not installed. - ValueError: If no TPUs are specified. - """ - if isinstance(tpu, list): - if not tpu: - raise ValueError('At least one TPU must be specified.') - if len(tpu) != 1: - raise NotImplementedError( - 'Using multiple TPUs in a single session is not yet implemented') - tpu = tpu[0] - - in_gke = self._inGke() - # When using GKE with Cloud TPUs, the env variable will be set. - if tpu is None: - if in_gke: - tpu = self._gkeEndpoints() - else: - tpu = self._envVarFallback() - - if tpu is None: - raise ValueError('Please provide a TPU Name to connect to.') - - self._tpu = compat.as_bytes(tpu) # self._tpu is always bytes - self._job_name = job_name - - # Whether we should actually attempt to contact Cloud APIs - should_resolve = self._shouldResolve() - - # We error out if we are in a non-Cloud environment which cannot talk to the - # Cloud APIs using the standard class and a special object is not passed in. - self._service = service - if (self._service is None and should_resolve and - not _GOOGLE_API_CLIENT_INSTALLED): - raise ImportError('googleapiclient and oauth2client must be installed ' - 'before using the TPU cluster resolver. Execute: ' - '`pip install --upgrade google-api-python-client` ' - 'and `pip install --upgrade oauth2client` to ' - 'install with pip.') - - # We save user-passed credentials, unless the user didn't pass in anything. - self._credentials = credentials - if (credentials == 'default' and should_resolve and - _GOOGLE_API_CLIENT_INSTALLED): - self._credentials = None - - # Automatically detect project and zone if unspecified. - if not project and should_resolve: - project = compat.as_str( - self._requestComputeMetadata('project/project-id')) - if not zone and should_resolve: - zone_path = compat.as_str(self._requestComputeMetadata('instance/zone')) - zone = zone_path.split('/')[-1] - self._project = project - self._zone = zone - - self._discovery_url = self._environmentDiscoveryUrl() or discovery_url - - self._coordinator_name = coordinator_name - if (coordinator_name and not coordinator_address and - (should_resolve or in_gke)): - self._start_local_server() - else: - self._coordinator_address = coordinator_address - - def master(self, task_type=None, task_index=None): - """Get the Master string to be used for the session. - - In the normal case, this returns the grpc path (grpc://1.2.3.4:8470) of - first instance in the ClusterSpec returned by the cluster_spec function. - - If a non-TPU name is used when constructing a TPUClusterResolver, that will - be returned instead (e.g. If the tpus argument's value when constructing - this TPUClusterResolver was 'grpc://10.240.1.2:8470', - 'grpc://10.240.1.2:8470' will be returned). - - Args: - task_type: (Optional) The type of the TensorFlow task of the master. - task_index: (Optional) The index of the TensorFlow task of the master. - - Returns: - string, the connection string to use when creating a session. - - Raises: - ValueError: If none of the TPUs specified exists. - """ - if not self._shouldResolve(): - return self._tpu.split(compat.as_bytes(_ENDPOINTS_SEPARATOR))[0] - - cluster_spec = self.cluster_spec() - if task_type and task_index: - return cluster_spec.task_address(task_type, task_index) - - job_tasks = cluster_spec.job_tasks(self._job_name) - if not job_tasks: - raise ValueError('No TPUs exists with the specified names exist.') - - return 'grpc://' + job_tasks[0] - - def get_master(self): - return self.master() - - def get_job_name(self): - if self._shouldResolve(): - return self._job_name - - def cluster_spec(self): - """Returns a ClusterSpec object based on the latest TPU information. - - We retrieve the information from the GCE APIs every time this method is - called. - - Returns: - A ClusterSpec containing host information returned from Cloud TPUs. - - Raises: - RuntimeError: If the provided TPU is not healthy. - """ - ############################################################################ - # There are 5 potential cases this code must handle: - # 1. [Normal case.] We should resolve the TPU name to a set of tasks, and - # a. Create a ClusterSpec that includes the coordinator job - # b. Create a ClusterSpec without the coordinator job. - # 2. [GKE / No API Access.] We should not resolve the TPU name to a set of - # tasks and - # a. Create a ClusterSpec with the coordinator - # b. Create a ClusterSpec without the coordinator - # 3. [Other (legacy non-gRPC).] We should return an empty ClusterSpec. - ############################################################################ - - if self._shouldResolve(): - # Case 1. - full_name = 'projects/%s/locations/%s/nodes/%s' % ( - self._project, self._zone, compat.as_text(self._tpu)) - service = self._tpuService() - request = service.projects().locations().nodes().get(name=full_name) - response = request.execute() - - if 'state' in response and response['state'] != 'READY': - raise RuntimeError('TPU "%s" is not yet ready; state: "%s"' % - (compat.as_text(self._tpu), response['state'])) - - if 'health' in response and response['health'] != 'HEALTHY': - raise RuntimeError('TPU "%s" is unhealthy: "%s"' % - (compat.as_text(self._tpu), response['health'])) - - if 'networkEndpoints' in response: - worker_list = [ - '%s:%s' % (endpoint['ipAddress'], endpoint['port']) - for endpoint in response['networkEndpoints'] - ] - else: - # Fall back to the deprecated response format - instance_url = '%s:%s' % (response['ipAddress'], response['port']) - worker_list = [instance_url] - - cluster_spec = {self._job_name: worker_list} - else: - if not self._tpu.startswith(compat.as_bytes('grpc://')): - # Case 3. - return None - # Case 2. - cluster_spec = { - self._job_name: [ - x[len(compat.as_bytes('grpc://')):] - for x in self._tpu.split(compat.as_bytes(_ENDPOINTS_SEPARATOR)) - ] - } - - if self._coordinator_address: - # {1, 2}.a - cluster_spec[self._coordinator_name] = [self._coordinator_address] - - return server_lib.ClusterSpec(cluster_spec) - - def _start_local_server(self): - address = self._requestComputeMetadata('instance/network-interfaces/0/ip') - self._server = server_lib.Server( - { - 'local': ['0.0.0.0:0'] - }, protocol='grpc', config=None, start=True) - # self._server.target is of the form: grpc://ipaddress:port - target = compat.as_bytes(self._server.target) - splits = target.split(compat.as_bytes(':')) - assert len(splits) == 3, self._server.target - assert splits[0] == compat.as_bytes('grpc'), self._server.target - self._coordinator_port = compat.as_text(splits[2]) - self._coordinator_address = '%s:%s' % ( - address, compat.as_text(self._coordinator_port)) - - def __deepcopy__(self, memo): - # TODO(b/73668574): Remove this once RunConfig avoids performing deepcopy. - return self +remove_undocumented(__name__, _allowed_symbols) diff --git a/tensorflow/contrib/cmake/CMakeLists.txt b/tensorflow/contrib/cmake/CMakeLists.txt index a63366e136..124d6cfd47 100644 --- a/tensorflow/contrib/cmake/CMakeLists.txt +++ b/tensorflow/contrib/cmake/CMakeLists.txt @@ -12,7 +12,7 @@ if(WIN32) endif() # Project -project(tensorflow C CXX) +project(tensorflow VERSION 1.12.0 LANGUAGES C CXX) # Set C++14 as standard for the whole project set(CMAKE_CXX_STANDARD 14) @@ -193,6 +193,7 @@ if(WIN32) set(CMAKE_SUPPRESS_REGENERATION ON) endif() + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -std=c++11") endif() @@ -281,6 +282,14 @@ else (systemlib_ZLIB) ${zlib_STATIC_LIBRARIES}) endif (systemlib_ZLIB) +if (systemlib_ABSEIL_CPP) + set(tensorflow_EXTERNAL_LIBRARIES ${tensorflow_EXTERNAL_LIBRARIES} + ${abseil_cpp_LIBRARIES}) +else (systemlib_ABSEIL_CPP) + set(tensorflow_EXTERNAL_LIBRARIES ${tensorflow_EXTERNAL_LIBRARIES} + ${abseil_cpp_STATIC_LIBRARIES}) +endif (systemlib_ABSEIL_CPP) + set(tensorflow_EXTERNAL_DEPENDENCIES zlib_copy_headers_to_destination gif_copy_headers_to_destination @@ -394,6 +403,7 @@ if (tensorflow_ENABLE_GPU) set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};--include-path ${PROJECT_BINARY_DIR}/$\{build_configuration\};--expt-relaxed-constexpr) set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};-ftz=true) # Flush denormals to zero set(CUDA_INCLUDE ${CUDA_TOOLKIT_TARGET_DIR} ${CUDA_TOOLKIT_TARGET_DIR}/extras/CUPTI/include) + include_directories(${CUDA_INCLUDE}) if (WIN32) add_definitions(-DGOOGLE_CUDA=1 -DTF_EXTRA_CUDA_CAPABILITIES=3.7,5.2,6.0,6.1,7.0) @@ -546,14 +556,20 @@ if (tensorflow_ENABLE_GPU) cudnn_version_number=${tensorflow_CUDNN_VERSION}) endif(WIN32) else(tensorflow_ENABLE_GPU) - set(tensorflow_BUILD_INFO_FLAGS --build_config cpu --key_value - msvcp_dll_name=msvcp140.dll) + if(WIN32) + set(tensorflow_BUILD_INFO_FLAGS --build_config cpu --key_value + msvcp_dll_name=msvcp140.dll) + else() + set(tensorflow_BUILD_INFO_FLAGS --build_config cpu) + endif() endif(tensorflow_ENABLE_GPU) -# Find python executable -include(FindPythonInterp) -if(NOT ${PYTHONINTERP_FOUND}) - message(FATAL_ERROR "CMake was unable to find a python interpreter.") +if(tensorflow_BUILD_PYTHON_BINDINGS) + # Find python executable + include(FindPythonInterp) + if(NOT ${PYTHONINTERP_FOUND}) + message(FATAL_ERROR "CMake was unable to find a python interpreter.") + endif() endif() # Let's get to work! @@ -574,6 +590,7 @@ include(tf_cc_ops.cmake) include(tf_c.cmake) include(tf_grappler.cmake) include(tf_core_profiler.cmake) +include(tf_core_eager_runtime.cmake) if(tensorflow_BUILD_CC_EXAMPLE) include(tf_tutorials.cmake) include(tf_label_image_example.cmake) @@ -587,4 +604,4 @@ if(tensorflow_BUILD_SHARED_LIB) endif() if(tensorflow_BUILD_CC_TESTS OR tensorflow_BUILD_PYTHON_TESTS) include(tf_tests.cmake) -endif() +endif() \ No newline at end of file diff --git a/tensorflow/contrib/cmake/README.md b/tensorflow/contrib/cmake/README.md index 84c679162c..df5ff6cd53 100644 --- a/tensorflow/contrib/cmake/README.md +++ b/tensorflow/contrib/cmake/README.md @@ -6,9 +6,9 @@ platforms. For details, see the [TensorFlow install guide](https://www.tensorflow.org/install/). This directory contains CMake files for building TensorFlow on Microsoft -Windows. [CMake](https://cmake.org) is a cross-platform tool that can +Windows and Linux. [CMake](https://cmake.org) is a cross-platform tool that can generate build scripts for multiple build systems, including Microsoft -Visual Studio. +Visual Studio and GCC. "The method has not been tested on Mac OS X. **N.B.** We provide Linux build instructions primarily for the purpose of testing the build. We recommend using the standard Bazel-based build on @@ -23,6 +23,7 @@ for instructions on how to install a pre-built TensorFlow package on Windows. ### Current known limitations * It is not possible to load a custom Op library. * GCS file system is not supported. +* Debug build is not available since Python for Windows is no longer distributed with a debug library. ## Building with CMake @@ -53,12 +54,12 @@ bindings. ### Known-good configurations * Microsoft Windows 10 - - Microsoft Visual Studio Enterprise 2015 with Visual C++ 2015 + - Microsoft Visual Studio Enterprise/ Community 2015 with Visual C++ 2015 - [Anaconda 4.1.1 (Python 3.5 64-bit)](https://www.anaconda.com/download/) - [Git for Windows version 2.9.2.windows.1](https://git-scm.com/download/win) - [swigwin-3.0.10](http://www.swig.org/download.html) - - [NVidia CUDA Toolkit 8.0](https://developer.nvidia.com/cuda-downloads) - - [NVidia CUDNN 5.1](https://developer.nvidia.com/cudnn) + - [NVidia CUDA Toolkit 9.0](https://developer.nvidia.com/cuda-downloads) + - [NVidia CUDNN 7](https://developer.nvidia.com/cudnn) - [CMake 3.6](https://cmake.org/files/v3.6/cmake-3.6.3-win64-x64.msi) * Ubuntu 14.04 @@ -66,8 +67,8 @@ bindings. - Docker 1.9.1 (for automated testing) ### Current known limitations - - The Python package supports **Python 3.5 only**, because that is the only - version for which standard Python binaries exist and those binaries are + - The Python package supports **Python 3.5/3.6 only**, because these are the only + versions for which standard Python binaries exist and those binaries are compatible with the TensorFlow runtime. (On Windows, the standard Python binaries for versions earlier than 3.5 were compiled with older compilers that do not have all of the features (e.g. C++11 support) needed to compile @@ -104,8 +105,151 @@ We are actively working on improving CMake and Windows support, and addressing these limitations. We would appreciate pull requests that implement missing ops or APIs. +CMake GUI build (all platforms) +================================== +Install from CMake GUI would be a convenient way to generate C++ build projects. The software supports Windows, MacOS and Linux, while the posix platform provides an extra ccmake binary to run command line GUI. Both working principal of cmake, ccmake and cmake-gui are the same, the only difference is by providing suitable interface for project configuration and dependency setting. + +0. Pre-buid checklist: + The following binary/libraries should be setted in system path, otherwise you need to set manualy via cmake. + * Compiler (GCC for Linux, MSVC for Windows) + * Make sure compiler directory has been set to system path + * CUDA 9.0 (GPU build) + * CUDNN (GPU build) + * NCCL (GPU build on Linux) + * SWIG (python binding) + * Perl (required if you need ssl support, optional) + * Go (required if you need ssl support, optional) + * NASM/YASM (required by grpc for ssl support, optional) +1. Start CMake GUI +2. Click on `Browse Source` and direct to the the folder `/tensorflow/contrib/cmake` +3. Click on `Browse Build` and spectify a location that you want tensorflow to be build +4. Click on `Configure`, a new window will be prompted out, specify the generator mode for the project generation. For Windows, choose `Visual Studio Win64`, for Linux, choose `Unix Makefiles`, then press `Finish`. Wait for a moment, the default project dependecy would automatically generate. +5. There are a few options that you can customize your own build. **The setting here is crucial for a sucessful build, please check all items carefully.** + * `tensorflow_BUILD_ALL_KERNELS` should alway be `on` + * `tensorflow_BUILD_CC_EXAMPLE` is default to be `on`. This can help you to test build (optional) + * `tensorflow_BUILD_CONTRIB_KERNELS` is default to be `on`, but it won't affect tensorflow function, turn it to `off` if you want a slim build. (optional) + * `tensorflow_BUILD_PYTHON_BINDING` is default to be `on`. Set to `off` if you don't need python interaface. If SWIG is not in system path, you need set it manually. (optional) + * `tensorflow_BUILD_SHARED_LIB` is default to be `off`. Set to `on` if you want the c++ interface. (optional) + * `tensorflow_ENABLE_GPU` is default to be `off`. Set to `on` if you want GPU support. It will search CUDA and CUDNN dependecies if you have set them to system path, otherwise CMake would prompt error and request you to set it manually. (optional) + * `tensorflow_ENABLE_GRPC_SUPPORT` is default to be `on`. For Linux build, this option must always be `on`. This need to be `on` for a gpu build. Reminded that Perl, Go and NASM/YASM are required for this option if you want to build grpc with offical SSL support. + * `tensorflow_ENABLE_POSITION_INDEPENDENT_CODE` should always be `on` + * `tensorflow_ENABLE_SNAPPY_SUPPORT` should always be `on` + * `tensorflow_OPTIMIZE_FOR_NATIVE_ARCH` should always be `on` + * `CMAKE_INSTALL_PREFIX` is the location where the final package will be installed. You may change it to your own preferred path (optional) + +6. After changing the configuration in step 5, press `Configure` again +7. If not error is found, press `Generate` + +#### Windows + +1. Open `tensorflow.sln` in the build folder (Windows). Change build type from `Debug` to `Release`. Choose `Build`->`Build Solution`. This may take more than hours of compilation. If everything is alright, the output window would show no error. + + ##### Python + + In solution explorer, right click on `tf_python_build_pip_package` -> `build`. It will generate the wheel file in `/tf_python/dist`. Install with following command: + + ```pip install --upgrade tensorflow-.whl``` + + ***The wheel name varies depends on you config. Change to your own wheel filename.*** + + Reminded that some pip installation requires administrator right command prompt. + + ##### C++ + + You can directly use the build folder tree for C++ interface with cmake. If you want to do installation for api releasing, right click on `Install` -> `build`. The headers and library will be installed in the directory specify by `CMAKE_INSTALL_PREFIX` during configuration. + +2. For smaller RAM computer, it is noticed that out of heap space error appears. Change to command prompt build is an alternative to do step 1. + + Open `VS2015 x64 Native Tools Command Prompt`. You can open it by press `Start`, then type the binary name. Use `VS2017 x64 Native Tools Command Prompt` if you are using MSVC 2017. + + ##### Python + + Directly build python wheel package by following command: + + ```MSBuild /p:Configuration=Release ``` + + Remember to change `` to the actual path of the file, it can be found at the root of build directory + + Install the wheel file generated as instructed by step 1. + + ##### C++ interface + Build from VS native toolchain with following command: + ```MSBuild /p:Configuration=Release ``` + + Headers are discretely located in the build folders. Tensorflow library can be found at `/Release`, namely `tensorflow.dll` and `tensorflow.lib`. + + * Build to install for api release (optional): + ```MSBuild /p:Configuration=Release ``` + + Remember to change `` and `` to the actual path of the file, it can be found at the root of build directory. + +#### Linux/MacOS (command line GNU build) + +1. Open the terminal, change working directory to the one specified in step 3. + +2. Type the following command: + + ```make -sj all``` + + ##### Python + + **Important Note** CMake generated python wheel for Linux/MacOs is currently under development. Please use bazel build. + + Follow code is an expected Linux/MacOS python package build after development work is completed. + + ``` + make -sj tf_python_build_pip_package + cd tf_python + pip install --upgrade tensorflow-.whl + ``` + + ##### C++ interface + + ```make -sj install``` + + Where `` is the threads used for the compilation, change to any integer less or equal to your computer's maxiumum thread number. + + Headers are discretely located in the build folders. Tensorflow library can be found at ``, namely `tensorflow.so` (Linux) or `tensorflow.dylib` (MacOS). + +#### Start a Tensorflow C++ project with CMake +Here we assume that you have basic knowledge on gathering dependency with `CMakeLists.txt`. Here we introduce how the C++ api works with [official hello world tutorial](https://www.tensorflow.org/api_guides/cc/guide). + +1. Create a new working directory and create a new text file named `CMakeLists.txt` and the c++ file `main.cxx` +2. Fill in the `main.cxx` with the code provided in [official c++ api basic](https://www.tensorflow.org/api_guides/cc/guide). +3. Fill in the `CMakeLists.txt` with following code: + ``` cmake + cmake_minimum_required (VERSION 2.6) + project (tf_hello) + + # Tensorflow + find_package(Tensorflow REQUIRED) + include_directories(${TENSORFLOW_INCLUDE_DIRS}) + + # compiler setting required by tensorflow, to be tested on all compilers + # currently only tested on MSVC and GCC + if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC) + add_definitions(-DCOMPILER_MSVC) + elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL GNU) + if (${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS "3") + add_definitions(-DCOMPILER_GCC3) + else() + add_definitions(-D__GNUC__) + endif() + else() + message(ERROR " compiler ${CMAKE_CXX_COMPILER_ID} not supported by this CMakeList.txt, under development") + endif() + + add_executable(tf_hello main.cxx) + target_link_libraries(tf_hello ${TENSORFLOW_LIBRARIES}) + ``` +4. Configure the folder with cmake-gui, an error should be prompted out, requesting you to locate the folder containing `TensorflowConfig.cmake`. This file can be found at `` or `` (for those have build install in previous steps). + +5. Configure again, generate the project. +6. Compile the project with `Release` config (Windows). For Linux users, just compile the project. +7. Copy the `tensorflow.dll`(Windows)/`tensorflow.so`(Linux) from build directory to the build folder containing `tf_hello` binary. +8. Run `tf_hello` binary -Step-by-step Windows build +Step-by-step Windows build (command prompt) ========================== 1. Install the prerequisites detailed above, and set up your environment. @@ -292,4 +436,4 @@ $ cd tensorflow $ tensorflow/tools/ci_build/ci_build.sh CMAKE tensorflow/tools/ci_build/builds/cmake.sh ``` -That's it. Dependencies included. +That's it. Dependencies included. \ No newline at end of file diff --git a/tensorflow/contrib/cmake/TensorflowConfig.cmake.in b/tensorflow/contrib/cmake/TensorflowConfig.cmake.in new file mode 100644 index 0000000000..cc04db6e95 --- /dev/null +++ b/tensorflow/contrib/cmake/TensorflowConfig.cmake.in @@ -0,0 +1,16 @@ +# - Config file for the Tensorflow package +# It defines the following variables +# TENSORFLOW_INCLUDE_DIRS - include directories for FooBar +# TENSORFLOW_LIBRARIES - libraries to link against + +# Compute paths +get_filename_component(TENSORFLOW_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +set(TENSORFLOW_INCLUDE_DIRS "@CONF_INCLUDE_DIRS@") + +# Our library dependencies (contains definitions for IMPORTED targets) +if(NOT TENSORFLOW_BINARY_DIR) + include("${TENSORFLOW_CMAKE_DIR}/TensorflowTargets.cmake") +endif() + +# These are IMPORTED targets created by TensorflowTargets.cmake +set(TENSORFLOW_LIBRARIES tensorflow) \ No newline at end of file diff --git a/tensorflow/contrib/cmake/TensorflowConfigVersion.cmake.in b/tensorflow/contrib/cmake/TensorflowConfigVersion.cmake.in new file mode 100644 index 0000000000..2a9609ddb9 --- /dev/null +++ b/tensorflow/contrib/cmake/TensorflowConfigVersion.cmake.in @@ -0,0 +1,11 @@ +set(PACKAGE_VERSION "@TENSORFLOW_VERSION@") + +# Check whether the requested PACKAGE_FIND_VERSION is compatible +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() \ No newline at end of file diff --git a/tensorflow/contrib/cmake/external/abseil_cpp.cmake b/tensorflow/contrib/cmake/external/abseil_cpp.cmake index 4546dbdecc..46a193971c 100644 --- a/tensorflow/contrib/cmake/external/abseil_cpp.cmake +++ b/tensorflow/contrib/cmake/external/abseil_cpp.cmake @@ -31,27 +31,24 @@ if (systemlib_ABSEIL_CPP) message(STATUS " abseil_cpp includes: ${ABSEIL_CPP_INCLUDE_DIR}") message(STATUS " abseil_cpp libraries: ${ABSEIL_CPP_LIBRARIES}") - add_custom_target(abseil_cpp_build) - list(APPEND tensorflow_EXTERNAL_DEPENDENCIES abseil_cpp_build) + add_custom_target(abseil_cpp) + list(APPEND tensorflow_EXTERNAL_DEPENDENCIES abseil_cpp) else (systemlib_ABSEIL_CPP) include (ExternalProject) - set(abseil_cpp_INCLUDE_DIR ${CMAKE_BINARY_DIR}/abseil_cpp/src/abseil_cpp_build) + set(abseil_cpp_INCLUDE_DIR ${CMAKE_BINARY_DIR}/abseil_cpp/src/abseil_cpp) set(abseil_cpp_URL https://github.com/abseil/abseil-cpp/archive/e01d95528ea2137a4a27a88d1f57c6cb260aafed.tar.gz) set(abseil_cpp_HASH SHA256=84043ed402d2a2a6ba4cdddb7e85118b1158fd81fe4ac3a14adc343d054c1e2e) - set(abseil_cpp_BUILD ${CMAKE_BINARY_DIR}/abseil_cpp/src/abseil_cpp_build) + set(abseil_cpp_BUILD ${CMAKE_BINARY_DIR}/abseil_cpp/src/abseil_cpp-build) if(WIN32) if(${CMAKE_GENERATOR} MATCHES "Visual Studio.*") set(abseil_cpp_STATIC_LIBRARIES ${abseil_cpp_BUILD}/absl/base/Release/absl_base.lib - ${abseil_cpp_BUILD}/absl/base/Release/absl_spinlock_wait.lib ${abseil_cpp_BUILD}/absl/base/Release/absl_dynamic_annotations.lib - ${abseil_cpp_BUILD}/absl/base/Release/absl_malloc_internal.lib - ${abseil_cpp_BUILD}/absl/base/Release/absl_throw_delegate.lib - ${abseil_cpp_BUILD}/absl/numeric/Release/absl_int128.lib + ${abseil_cpp_BUILD}/absl/base/Release/absl_internal_malloc_internal.lib ${abseil_cpp_BUILD}/absl/strings/Release/absl_strings.lib ${abseil_cpp_BUILD}/absl/strings/Release/str_format_internal.lib ${abseil_cpp_BUILD}/absl/types/Release/absl_bad_optional_access.lib) @@ -80,15 +77,12 @@ else (systemlib_ABSEIL_CPP) ${abseil_cpp_BUILD}/absl/types/libabsl_bad_optional_access.a) endif() - ExternalProject_Add(abseil_cpp_build + ExternalProject_Add(abseil_cpp PREFIX abseil_cpp URL ${abseil_cpp_URL} URL_HASH ${abseil_cpp_HASH} DOWNLOAD_DIR "${DOWNLOAD_LOCATION}" - BUILD_IN_SOURCE 1 BUILD_BYPRODUCTS ${abseil_cpp_STATIC_LIBRARIES} - BUILD_COMMAND ${CMAKE_COMMAND} --build . --config Release - COMMAND ${CMAKE_COMMAND} --build . --config Release INSTALL_COMMAND "" CMAKE_CACHE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=${tensorflow_ENABLE_POSITION_INDEPENDENT_CODE} @@ -99,6 +93,6 @@ else (systemlib_ABSEIL_CPP) include_directories(${abseil_cpp_INCLUDE_DIR}) list(APPEND tensorflow_EXTERNAL_LIBRARIES ${abseil_cpp_STATIC_LIBRARIES}) - list(APPEND tensorflow_EXTERNAL_DEPENDENCIES abseil_cpp_build) + list(APPEND tensorflow_EXTERNAL_DEPENDENCIES abseil_cpp) -endif (systemlib_ABSEIL_CPP) +endif (systemlib_ABSEIL_CPP) \ No newline at end of file diff --git a/tensorflow/contrib/cmake/external/png.cmake b/tensorflow/contrib/cmake/external/png.cmake index 1a147e9c8e..32e6d78e50 100644 --- a/tensorflow/contrib/cmake/external/png.cmake +++ b/tensorflow/contrib/cmake/external/png.cmake @@ -59,6 +59,7 @@ ExternalProject_Add(png -DCMAKE_VERBOSE_MAKEFILE:BOOL=OFF -DCMAKE_INSTALL_PREFIX:STRING=${png_INSTALL} -DZLIB_ROOT:STRING=${ZLIB_INSTALL} + -DPNG_TESTS:BOOL=OFF ) ## put png includes in the directory where they are expected diff --git a/tensorflow/contrib/cmake/modules/FindAbseilCpp.cmake b/tensorflow/contrib/cmake/modules/FindAbseilCpp.cmake index d4f8bb1bec..944ae3997a 100644 --- a/tensorflow/contrib/cmake/modules/FindAbseilCpp.cmake +++ b/tensorflow/contrib/cmake/modules/FindAbseilCpp.cmake @@ -24,10 +24,10 @@ if(EXISTS "${ABSEIL_CPP_INCLUDE_DIR}" AND NOT "${ABSEIL_CPP_INCLUDE_DIR}" STREQU # search all libraries if no COMPONENTS was requested set(AbseilCpp_FIND_COMPONENTS "absl_algorithm;absl_any;absl_bad_any_cast" - "absl_bad_optional_access;absl_base absl_container;absl_debugging" + "absl_bad_optional_access;absl_base;absl_container;absl_debugging" "absl_dynamic_annotations;absl_examine_stack;absl_failure_signal_handler" - "absl_int128;absl_leak_check;absl_malloc_internal;absl_memory;absl_meta" - "absl_numeric;absl_optional;absl_span;absl_spinlock_wait;absl_stack_consumption" + "absl_int128;absl_leak_check;absl_internal_malloc_internal;absl_memory;absl_meta" + "absl_numeric;absl_optional;absl_span;absl_internal_spinlock_wait;absl_stack_consumption" "absl_stacktrace;absl_str_format;absl_strings;absl_symbolize;absl_synchronization" "absl_throw_delegate;absl_time;absl_utility;str_format_extension_internal" "str_format_internal;test_instance_tracker_lib") diff --git a/tensorflow/contrib/cmake/tf_c.cmake b/tensorflow/contrib/cmake/tf_c.cmake index 7a30eb94f5..a04142bd24 100644 --- a/tensorflow/contrib/cmake/tf_c.cmake +++ b/tensorflow/contrib/cmake/tf_c.cmake @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== + ######################################################## # tf_c_framework library ######################################################## diff --git a/tensorflow/contrib/cmake/tf_core_cpu.cmake b/tensorflow/contrib/cmake/tf_core_cpu.cmake index a54cbff33b..d8884d464f 100644 --- a/tensorflow/contrib/cmake/tf_core_cpu.cmake +++ b/tensorflow/contrib/cmake/tf_core_cpu.cmake @@ -39,6 +39,8 @@ file(GLOB_RECURSE tf_core_cpu_exclude_srcs "${tensorflow_source_dir}/tensorflow/core/*test*.h" "${tensorflow_source_dir}/tensorflow/core/*test*.cc" "${tensorflow_source_dir}/tensorflow/core/*main.cc" + "${tensorflow_source_dir}/tensorflow/core/common_runtime/eager/*.cc" + "${tensorflow_source_dir}/tensorflow/core/common_runtime/eager/*.h" "${tensorflow_source_dir}/tensorflow/core/common_runtime/gpu/*.cc" "${tensorflow_source_dir}/tensorflow/core/common_runtime/gpu_device_factory.cc" "${tensorflow_source_dir}/tensorflow/core/common_runtime/direct_session.cc" diff --git a/tensorflow/contrib/cmake/tf_core_eager_runtime.cmake b/tensorflow/contrib/cmake/tf_core_eager_runtime.cmake new file mode 100644 index 0000000000..78e4c0d303 --- /dev/null +++ b/tensorflow/contrib/cmake/tf_core_eager_runtime.cmake @@ -0,0 +1,57 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +######################################################## +# tf_core_eager_runtime library +######################################################## +file(GLOB_RECURSE tf_core_eager_runtime_srcs + "${tensorflow_source_dir}/tensorflow/core/common_runtime/eager/*.cc" + "${tensorflow_source_dir}/tensorflow/core/common_runtime/eager/*.h" +) + +file(GLOB_RECURSE tf_core_eager_runtime_exclude_srcs + "${tensorflow_source_dir}/tensorflow/core/common_runtime/eager/*test*.h" + "${tensorflow_source_dir}/tensorflow/core/common_runtime/eager/*test*.cc" +) + +list(REMOVE_ITEM tf_core_eager_runtime_srcs ${tf_core_eager_runtime_exclude_srcs}) + +add_library(tf_core_eager_runtime OBJECT ${tf_core_eager_runtime_srcs}) +add_dependencies( + tf_core_eager_runtime + tf_c + tf_core_lib) + + +file(GLOB_RECURSE tf_c_eager_srcs + "${tensorflow_source_dir}/tensorflow/c/eager/*.cc" + "${tensorflow_source_dir}/tensorflow/c/eager/*.h" +) + +file(GLOB_RECURSE tf_c_eager_exlclude_srcs + "${tensorflow_source_dir}/tensorflow/c/eager/*test*.h" + "${tensorflow_source_dir}/tensorflow/c/eager/*test*.cc" +) + +list(REMOVE_ITEM tf_c_eager_srcs ${tf_c_eager_exlclude_srcs}) + +add_library(tf_c_eager OBJECT ${tf_c_eager_srcs}) +add_dependencies( + tf_c_eager + tf_core_eager_runtime + tf_c + tf_cc_framework + tf_cc_while_loop + tf_core_lib + tf_protos_cc) \ No newline at end of file diff --git a/tensorflow/contrib/cmake/tf_core_framework.cmake b/tensorflow/contrib/cmake/tf_core_framework.cmake index 7e806685b8..d7b2a1339e 100644 --- a/tensorflow/contrib/cmake/tf_core_framework.cmake +++ b/tensorflow/contrib/cmake/tf_core_framework.cmake @@ -140,16 +140,19 @@ set(tf_proto_text_srcs "tensorflow/core/example/example.proto" "tensorflow/core/example/feature.proto" "tensorflow/core/framework/allocation_description.proto" + "tensorflow/core/framework/api_def.proto" "tensorflow/core/framework/attr_value.proto" "tensorflow/core/framework/cost_graph.proto" "tensorflow/core/framework/device_attributes.proto" "tensorflow/core/framework/function.proto" "tensorflow/core/framework/graph.proto" "tensorflow/core/framework/graph_transfer_info.proto" + "tensorflow/core/framework/iterator.proto" "tensorflow/core/framework/kernel_def.proto" "tensorflow/core/framework/log_memory.proto" "tensorflow/core/framework/node_def.proto" "tensorflow/core/framework/op_def.proto" + "tensorflow/core/framework/reader_base.proto" "tensorflow/core/framework/remote_fused_graph_execute_info.proto" "tensorflow/core/framework/resource_handle.proto" "tensorflow/core/framework/step_stats.proto" @@ -159,6 +162,7 @@ set(tf_proto_text_srcs "tensorflow/core/framework/tensor_shape.proto" "tensorflow/core/framework/tensor_slice.proto" "tensorflow/core/framework/types.proto" + "tensorflow/core/framework/variable.proto" "tensorflow/core/framework/versions.proto" "tensorflow/core/lib/core/error_codes.proto" "tensorflow/core/protobuf/cluster.proto" @@ -204,10 +208,10 @@ file(GLOB tf_core_platform_srcs "${tensorflow_source_dir}/tensorflow/core/framework/resource_handle.h" "${tensorflow_source_dir}/tensorflow/core/framework/resource_handle.cc") if (NOT tensorflow_ENABLE_GPU) - file(GLOB tf_core_platform_gpu_srcs + file(GLOB tf_core_platform_gpu_srcs_exclude "${tensorflow_source_dir}/tensorflow/core/platform/cuda_libdevice_path.*" "${tensorflow_source_dir}/tensorflow/core/platform/default/cuda_libdevice_path.*") - list(REMOVE_ITEM tf_core_platform_srcs ${tf_core_platform_gpu_srcs}) + list(REMOVE_ITEM tf_core_platform_srcs ${tf_core_platform_gpu_srcs_exclude}) else() file(GLOB tf_core_platform_srcs_exclude "${tensorflow_source_dir}/tensorflow/core/platform/default/device_tracer.cc") diff --git a/tensorflow/contrib/cmake/tf_core_ops.cmake b/tensorflow/contrib/cmake/tf_core_ops.cmake index 9cfa8b9074..6e75963313 100644 --- a/tensorflow/contrib/cmake/tf_core_ops.cmake +++ b/tensorflow/contrib/cmake/tf_core_ops.cmake @@ -13,13 +13,14 @@ # limitations under the License. # ============================================================================== set(tf_op_lib_names - "audio_ops" "array_ops" + "audio_ops" "batch_ops" "bitwise_ops" "boosted_trees_ops" "candidate_sampling_ops" "checkpoint_ops" + "collective_ops" "control_flow_ops" "ctc_ops" "cudnn_rnn_ops" @@ -32,8 +33,8 @@ set(tf_op_lib_names "io_ops" "linalg_ops" "list_ops" - "lookup_ops" "logging_ops" + "lookup_ops" "manip_ops" "math_ops" "nn_ops" @@ -43,10 +44,11 @@ set(tf_op_lib_names "remote_fused_graph_ops" "resource_variable_ops" "rpc_ops" + "scoped_allocator_ops" "script_ops" "sdca_ops" - "set_ops" "sendrecv_ops" + "set_ops" "sparse_ops" "spectral_ops" "state_ops" @@ -54,6 +56,7 @@ set(tf_op_lib_names "string_ops" "summary_ops" "training_ops" + "word2vec_ops" ) foreach(tf_op_lib_name ${tf_op_lib_names}) diff --git a/tensorflow/contrib/cmake/tf_python.cmake b/tensorflow/contrib/cmake/tf_python.cmake index df7b854afc..5028498598 100755 --- a/tensorflow/contrib/cmake/tf_python.cmake +++ b/tensorflow/contrib/cmake/tf_python.cmake @@ -313,15 +313,14 @@ function(GENERATE_PYTHON_OP_LIB tf_python_op_lib_name) ${GENERATE_PYTHON_OP_LIB_DESTINATION} PARENT_SCOPE) endfunction() -GENERATE_PYTHON_OP_LIB("audio_ops") GENERATE_PYTHON_OP_LIB("array_ops") +GENERATE_PYTHON_OP_LIB("audio_ops") GENERATE_PYTHON_OP_LIB("batch_ops") GENERATE_PYTHON_OP_LIB("bitwise_ops") GENERATE_PYTHON_OP_LIB("boosted_trees_ops") -GENERATE_PYTHON_OP_LIB("math_ops") -GENERATE_PYTHON_OP_LIB("functional_ops") GENERATE_PYTHON_OP_LIB("candidate_sampling_ops") GENERATE_PYTHON_OP_LIB("checkpoint_ops") +GENERATE_PYTHON_OP_LIB("collective_ops") GENERATE_PYTHON_OP_LIB("control_flow_ops" ADDITIONAL_LIBRARIES $) GENERATE_PYTHON_OP_LIB("ctc_ops") @@ -332,14 +331,18 @@ GENERATE_PYTHON_OP_LIB("decode_proto_ops" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/proto/python/ops/gen_decode_proto_op.py) GENERATE_PYTHON_OP_LIB("encode_proto_ops" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/proto/python/ops/gen_encode_proto_op.py) +GENERATE_PYTHON_OP_LIB("function_ops") +GENERATE_PYTHON_OP_LIB("functional_ops") GENERATE_PYTHON_OP_LIB("image_ops") GENERATE_PYTHON_OP_LIB("io_ops") GENERATE_PYTHON_OP_LIB("linalg_ops") GENERATE_PYTHON_OP_LIB("list_ops") GENERATE_PYTHON_OP_LIB("logging_ops") GENERATE_PYTHON_OP_LIB("lookup_ops") -GENERATE_PYTHON_OP_LIB("nn_ops") GENERATE_PYTHON_OP_LIB("manip_ops") +GENERATE_PYTHON_OP_LIB("math_ops") +GENERATE_PYTHON_OP_LIB("nn_ops") +GENERATE_PYTHON_OP_LIB("no_op") GENERATE_PYTHON_OP_LIB("parsing_ops") GENERATE_PYTHON_OP_LIB("random_ops") GENERATE_PYTHON_OP_LIB("remote_fused_graph_ops" @@ -347,17 +350,21 @@ GENERATE_PYTHON_OP_LIB("remote_fused_graph_ops" GENERATE_PYTHON_OP_LIB("resource_variable_ops") GENERATE_PYTHON_OP_LIB("rpc_ops" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/rpc/python/ops/gen_rpc_op.py) +GENERATE_PYTHON_OP_LIB("scoped_allocator_ops") GENERATE_PYTHON_OP_LIB("script_ops") GENERATE_PYTHON_OP_LIB("sdca_ops") +GENERATE_PYTHON_OP_LIB("sendrecv_ops") GENERATE_PYTHON_OP_LIB("set_ops") -GENERATE_PYTHON_OP_LIB("state_ops") GENERATE_PYTHON_OP_LIB("sparse_ops") GENERATE_PYTHON_OP_LIB("spectral_ops") +GENERATE_PYTHON_OP_LIB("state_ops") +GENERATE_PYTHON_OP_LIB("stateless_random_ops") GENERATE_PYTHON_OP_LIB("string_ops") GENERATE_PYTHON_OP_LIB("summary_ops") GENERATE_PYTHON_OP_LIB("user_ops") GENERATE_PYTHON_OP_LIB("training_ops" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/python/training/gen_training_ops.py) +GENERATE_PYTHON_OP_LIB("word2vec_ops") GENERATE_PYTHON_OP_LIB("contrib_boosted_trees_model_ops" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/boosted_trees/python/ops/gen_model_ops.py) @@ -391,11 +398,8 @@ GENERATE_PYTHON_OP_LIB("contrib_layers_sparse_feature_cross_ops" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/layers/ops/gen_sparse_feature_cross_op.py) GENERATE_PYTHON_OP_LIB("contrib_memory_stats_ops" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/memory_stats/ops/gen_memory_stats_ops.py) -GENERATE_PYTHON_OP_LIB("contrib_nccl_ops" - DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/nccl/ops/gen_nccl_ops.py) GENERATE_PYTHON_OP_LIB("contrib_periodic_resample_ops" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/periodic_resample/python/ops/gen_periodic_resample_op.py) - GENERATE_PYTHON_OP_LIB("contrib_nearest_neighbor_ops" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/contrib/nearest_neighbor/ops/gen_nearest_neighbor_ops.py) GENERATE_PYTHON_OP_LIB("contrib_resampler_ops" @@ -524,11 +528,13 @@ if(WIN32) add_library(pywrap_tensorflow_internal_static STATIC ${pywrap_tensorflow_internal_src} $ + $ $ $ $ $ $ + $ $ $ $ @@ -581,11 +587,13 @@ endif(WIN32) add_library(pywrap_tensorflow_internal SHARED ${pywrap_tensorflow_internal_src} $ + $ $ $ $ $ $ + $ $ $ $ @@ -615,13 +623,28 @@ target_include_directories(pywrap_tensorflow_internal PUBLIC ${NUMPY_INCLUDE_DIR} ) -target_link_libraries(pywrap_tensorflow_internal PRIVATE +if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0) + # There is a bug in GCC 5 resulting in undefined reference to a __cpu_model function when + # linking to the tensorflow library. Adding the following libraries fixes it. + # See issue on github: https://github.com/tensorflow/tensorflow/issues/9593 + target_link_libraries(pywrap_tensorflow_internal PRIVATE + ${tf_core_gpu_kernels_lib} + ${tensorflow_EXTERNAL_LIBRARIES} + tf_protos_cc + tf_python_protos_cc + ${PYTHON_LIBRARIES} + gcc_s + gcc +) +else() + target_link_libraries(pywrap_tensorflow_internal PRIVATE ${tf_core_gpu_kernels_lib} ${tensorflow_EXTERNAL_LIBRARIES} tf_protos_cc tf_python_protos_cc ${PYTHON_LIBRARIES} ) +endif() if(WIN32) diff --git a/tensorflow/contrib/cmake/tf_shared_lib.cmake b/tensorflow/contrib/cmake/tf_shared_lib.cmake index fdf522f1fd..62005dd113 100644 --- a/tensorflow/contrib/cmake/tf_shared_lib.cmake +++ b/tensorflow/contrib/cmake/tf_shared_lib.cmake @@ -23,6 +23,8 @@ if(WIN32) # we need. # add_library(tensorflow_static STATIC + $ + $ $ $ $ @@ -65,6 +67,8 @@ endif(WIN32) # tensorflow is a shared library containing all of the # TensorFlow runtime and the standard ops and kernels. add_library(tensorflow SHARED + $ + $ $ $ $ @@ -96,6 +100,27 @@ if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0) target_link_libraries(tensorflow PRIVATE gcc_s gcc) endif() +# Offer the user the choice of overriding the installation directories +set(INSTALL_LIB_DIR lib CACHE PATH "Installation directory for libraries") +set(INSTALL_BIN_DIR bin CACHE PATH "Installation directory for executables") +set(INSTALL_INCLUDE_DIR include CACHE PATH + "Installation directory for header files") +if(WIN32 AND NOT CYGWIN) + set(DEF_INSTALL_CMAKE_DIR cmake) +else() + set(DEF_INSTALL_CMAKE_DIR lib/cmake) +endif() +set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH + "Installation directory for CMake files") + +# Make relative paths absolute (needed later on) +foreach(p LIB BIN INCLUDE CMAKE) + set(var INSTALL_${p}_DIR) + if(NOT IS_ABSOLUTE "${${var}}") + set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") + endif() +endforeach() + if(WIN32) add_dependencies(tensorflow tensorflow_static) endif(WIN32) @@ -103,14 +128,57 @@ endif(WIN32) target_include_directories(tensorflow PUBLIC $) -install(TARGETS tensorflow EXPORT tensorflow_export - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib) +# Add all targets to build-tree export set +export(TARGETS tensorflow + FILE ${PROJECT_BINARY_DIR}/TensorflowTargets.cmake) + +# Export the package for use from the build-tree +export(PACKAGE Tensorflow) + +# Create the TensorflowConfig.cmake and TensorflowConfigVersion files +file(RELATIVE_PATH REL_INCLUDE_DIR "${INSTALL_CMAKE_DIR}" + "${INSTALL_INCLUDE_DIR}") +# for the build tree +set(CONF_INCLUDE_DIRS "${tensorflow_source_dir}" + "${PROJECT_BINARY_DIR}" + "${CMAKE_CURRENT_BINARY_DIR}/protobuf/src/protobuf/src" + "${CMAKE_CURRENT_BINARY_DIR}/nsync/install/include" # Please if there is a better directory + "${CMAKE_CURRENT_BINARY_DIR}/eigen/src/eigen/Eigen/" + "${CMAKE_CURRENT_BINARY_DIR}/external/eigen_archive/" + "${tensorflow_source_dir}/third_party/eigen3/" + "${CMAKE_CURRENT_BINARY_DIR}/eigen/src/eigen/unsupported/Eigen/") +configure_file(TensorflowConfig.cmake.in + "${PROJECT_BINARY_DIR}/TensorflowConfig.cmake" @ONLY) +# for the install tree, yet to be complete +set(CONF_INCLUDE_DIRS "\${TENSORFLOW_CMAKE_DIR}/${REL_INCLUDE_DIR}") +configure_file(TensorflowConfig.cmake.in + "${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/TensorflowConfig.cmake" @ONLY) +# for both +configure_file(TensorflowConfigVersion.cmake.in + "${PROJECT_BINARY_DIR}/TensorflowConfigVersion.cmake" @ONLY) + +# install(TARGETS tensorflow EXPORT tensorflow_export +# RUNTIME DESTINATION ${INSTALL_BIN_DIR} +# LIBRARY DESTINATION ${INSTALL_LIB_DIR} +# ARCHIVE DESTINATION ${INSTALL_LIB_DIR}) + +# install(EXPORT tensorflow_export +# FILE TensorflowConfig.cmake +# DESTINATION ${INSTALL_CMAKE_DIR}) -install(EXPORT tensorflow_export - FILE TensorflowConfig.cmake - DESTINATION lib/cmake) +install(FILES + "${PROJECT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/TensorflowConfig.cmake" + "${PROJECT_BINARY_DIR}/TensorflowConfigVersion.cmake" + DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev) + +# install the export set for use with the install-tree +install(EXPORT TensorflowTargets + DESTINATION ${INSTALL_CMAKE_DIR}) + +install(TARGETS tensorflow EXPORT TensorflowTargets + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR}) # install necessary headers # tensorflow headers @@ -145,6 +213,10 @@ install(DIRECTORY ${tensorflow_source_dir}/third_party/eigen3/ # unsupported Eigen directory install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/eigen/src/eigen/unsupported/Eigen/ DESTINATION include/unsupported/Eigen) +# absl directory +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/abseil_cpp/src/abseil_cpp/absl/ + DESTINATION include/absl + FILES_MATCHING PATTERN "*.h") # mkl if (tensorflow_ENABLE_MKL_SUPPORT) install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/mkl/src/mkl/include/ diff --git a/tensorflow/contrib/compiler/BUILD b/tensorflow/contrib/compiler/BUILD index 1630f010ab..e4566437c6 100644 --- a/tensorflow/contrib/compiler/BUILD +++ b/tensorflow/contrib/compiler/BUILD @@ -58,6 +58,7 @@ py_library( srcs_version = "PY2AND3", deps = [ "//tensorflow/compiler/jit:xla_ops_py", + "//tensorflow/compiler/jit/ops:xla_ops_grad", "//tensorflow/python:array_ops", "//tensorflow/python:control_flow_ops", "//tensorflow/python:framework_ops", diff --git a/tensorflow/contrib/compiler/xla.py b/tensorflow/contrib/compiler/xla.py index 335ac79464..f867cd15b6 100644 --- a/tensorflow/contrib/compiler/xla.py +++ b/tensorflow/contrib/compiler/xla.py @@ -23,6 +23,7 @@ import contextlib from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.compiler.jit.ops import xla_ops +from tensorflow.compiler.jit.ops import xla_ops_grad # pylint: disable=unused-import from tensorflow.core.framework import attr_value_pb2 from tensorflow.python.estimator import model_fn as model_fn_lib from tensorflow.python.framework import ops diff --git a/tensorflow/contrib/constrained_optimization/python/constrained_minimization_problem.py b/tensorflow/contrib/constrained_optimization/python/constrained_minimization_problem.py index 41258edd90..6926c0d03f 100644 --- a/tensorflow/contrib/constrained_optimization/python/constrained_minimization_problem.py +++ b/tensorflow/contrib/constrained_optimization/python/constrained_minimization_problem.py @@ -74,8 +74,8 @@ class ConstrainedMinimizationProblem(object): if (constraints_shape.ndims is None or proxy_constraints_shape.ndims is None or - any([ii is None for ii in constraints_shape.as_list()]) or - any([ii is None for ii in proxy_constraints_shape.as_list()])): + any(ii is None for ii in constraints_shape.as_list()) or + any(ii is None for ii in proxy_constraints_shape.as_list())): raise ValueError( "constraints and proxy_constraints must have fully-known shapes") if constraints_shape != proxy_constraints_shape: diff --git a/tensorflow/contrib/crf/python/ops/crf.py b/tensorflow/contrib/crf/python/ops/crf.py index 656633f0bf..40e159b8fc 100644 --- a/tensorflow/contrib/crf/python/ops/crf.py +++ b/tensorflow/contrib/crf/python/ops/crf.py @@ -38,12 +38,12 @@ tf_unary_scores, tf_sequence_lengths, tf_transition_params, _ = session.run( [unary_scores, sequence_lengths, transition_params, train_op]) for tf_unary_scores_, tf_sequence_length_ in zip(tf_unary_scores, tf_sequence_lengths): -# Remove padding. -tf_unary_scores_ = tf_unary_scores_[:tf_sequence_length_] + # Remove padding. + tf_unary_scores_ = tf_unary_scores_[:tf_sequence_length_] -# Compute the highest score and its tag sequence. -tf_viterbi_sequence, tf_viterbi_score = tf.contrib.crf.viterbi_decode( - tf_unary_scores_, tf_transition_params) + # Compute the highest score and its tag sequence. + tf_viterbi_sequence, tf_viterbi_score = tf.contrib.crf.viterbi_decode( + tf_unary_scores_, tf_transition_params) """ from __future__ import absolute_import diff --git a/tensorflow/contrib/cudnn_rnn/BUILD b/tensorflow/contrib/cudnn_rnn/BUILD index 670b549432..8d35622e39 100644 --- a/tensorflow/contrib/cudnn_rnn/BUILD +++ b/tensorflow/contrib/cudnn_rnn/BUILD @@ -42,10 +42,11 @@ tf_custom_op_py_library( cuda_py_test( name = "cudnn_rnn_ops_test", - size = "large", + size = "medium", srcs = ["python/kernel_tests/cudnn_rnn_ops_test.py"], additional_deps = [ ":cudnn_rnn_py", + "@absl_py//absl/testing:parameterized", "//tensorflow/core:protos_all_py", "//tensorflow/contrib/rnn:rnn_py", "//tensorflow/python/ops/losses:losses", @@ -61,7 +62,7 @@ cuda_py_test( "//tensorflow/python:training", "//tensorflow/python:variables", ], - shard_count = 6, + shard_count = 2, tags = [ "noasan", # http://b/62067814 "requires-gpu-sm35", diff --git a/tensorflow/contrib/cudnn_rnn/python/kernel_tests/cudnn_rnn_ops_test.py b/tensorflow/contrib/cudnn_rnn/python/kernel_tests/cudnn_rnn_ops_test.py index ae839108eb..a268415f0e 100644 --- a/tensorflow/contrib/cudnn_rnn/python/kernel_tests/cudnn_rnn_ops_test.py +++ b/tensorflow/contrib/cudnn_rnn/python/kernel_tests/cudnn_rnn_ops_test.py @@ -18,24 +18,30 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import collections import itertools import os import unittest +from absl.testing import parameterized import numpy as np from tensorflow.contrib.cudnn_rnn.python.ops import cudnn_rnn_ops from tensorflow.core.protobuf import saver_pb2 +from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import random_seed from tensorflow.python.framework.test_util import TensorFlowTestCase from tensorflow.python.ops import array_ops -from tensorflow.python.ops import gradient_checker -from tensorflow.python.ops import math_ops +from tensorflow.python.ops import gradients_impl +from tensorflow.python.ops import init_ops from tensorflow.python.ops import random_ops +from tensorflow.python.ops import rnn +from tensorflow.python.ops import rnn_cell_impl from tensorflow.python.ops import state_ops +from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables from tensorflow.python.platform import googletest from tensorflow.python.platform import test @@ -56,714 +62,989 @@ CUDNN_RNN_TANH_PARAMS_PER_LAYER = cudnn_rnn_ops.CUDNN_RNN_TANH_PARAMS_PER_LAYER CUDNN_RNN_RELU_PARAMS_PER_LAYER = cudnn_rnn_ops.CUDNN_RNN_RELU_PARAMS_PER_LAYER -def _CreateModel(rnn_mode, - num_layers, - num_units, - input_size, - input_mode="linear_input", - direction=cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION, - dtype=dtypes.float32, - dropout=0.): - del input_mode - if rnn_mode == cudnn_rnn_ops.CUDNN_LSTM: - model_fn = cudnn_rnn_ops.CudnnLSTM - elif rnn_mode == cudnn_rnn_ops.CUDNN_GRU: - model_fn = cudnn_rnn_ops.CudnnGRU - elif rnn_mode == cudnn_rnn_ops.CUDNN_RNN_TANH: - model_fn = cudnn_rnn_ops.CudnnRNNTanh - elif rnn_mode == cudnn_rnn_ops.CUDNN_RNN_RELU: - model_fn = cudnn_rnn_ops.CudnnRNNRelu +def RunLSTM(sess, + num_units, + input_size, + batch_size, + time, + num_layers=1, + is_training=True, + dropout=0., + num_dirs=True, + dtype=dtypes.float32): + # TODO(jamesqin): add multi-layer tests. + # TODO(jamesqin): add multi-dir tests + assert num_layers == 1 + assert num_dirs == 1 + if is_training and not np.isclose(dropout, 0): + raise ValueError("dropout can not be 0. when test training.") + + # set graph level random seed and numpy random seed. + random_seed.set_random_seed(0) + np.random.seed(0) + + inputs = variable_scope.get_variable( + "inputs", + initializer=np.random.rand(time, batch_size, + input_size).astype(dtype.as_numpy_dtype), + dtype=dtype) + initial_h_op = variable_scope.get_variable( + "initial_h_op", + initializer=np.random.rand(batch_size, + num_units).astype(dtype.as_numpy_dtype), + dtype=dtype) + initial_c_op = variable_scope.get_variable( + "initial_c_op", + initializer=np.random.rand(batch_size, + num_units).astype(dtype.as_numpy_dtype), + dtype=dtype) + + initializer = init_ops.random_uniform_initializer( + -0.01, 0.01, dtype=dtype, seed=19980904) + + with variable_scope.variable_scope("test", initializer=initializer): + w = variable_scope.get_variable( + "rnn/lstm_cell/kernel", + shape=[input_size + num_units, num_units * 4], + dtype=dtype) + b = variable_scope.get_variable( + "rnn/lstm_cell/bias", shape=[num_units * 4], dtype=dtype) + + # canonical lstm. must set forget_bias to 0. to align with cudnn lstm. + cell = rnn_cell_impl.LSTMCell(num_units, forget_bias=0., reuse=True) + outputs_op, state_tuple_op = rnn.dynamic_rnn( + cell, + inputs, + initial_state=rnn_cell_impl.LSTMStateTuple( + h=initial_h_op, c=initial_c_op), + dtype=dtype, + time_major=True, + scope=None) + + # Convert to cudnn opaque param. + format_converter = cudnn_rnn_ops.CudnnParamsFormatConverterLSTM( + num_layers, num_units, input_size) + opaque_params = format_converter.tf_canonical_to_opaque([w, b]) + + cu_initial_h_op = array_ops.expand_dims(initial_h_op, axis=0) + cu_initial_c_op = array_ops.expand_dims(initial_c_op, axis=0) + cu_outputs_op, cu_h_op, cu_c_op = cudnn_rnn_ops._cudnn_rnn( + inputs, + cu_initial_h_op, + cu_initial_c_op, + opaque_params, + dropout=dropout, + is_training=is_training, + rnn_mode=cudnn_rnn_ops.CUDNN_LSTM) + # Remove the trivial 1st dimension. + cu_state_tuple_op = rnn_cell_impl.LSTMStateTuple( + c=array_ops.squeeze(cu_c_op, axis=0), + h=array_ops.squeeze(cu_h_op, axis=0)) + + if is_training: + (inp_grad_op, hgrad_op, + cgrad_op, wgrad_op, bgrad_op) = gradients_impl.gradients( + outputs_op, [inputs, initial_h_op, initial_c_op, w, b]) + + (cu_inp_grad_op, cu_hgrad_op, + cu_cgrad_op, opaque_grad_op) = gradients_impl.gradients( + cu_outputs_op, + [inputs, cu_initial_h_op, cu_initial_c_op, opaque_params]) + # Remove the trivial 1st dimension + cu_hgrad_op = array_ops.squeeze(cu_hgrad_op, axis=0) + # Remove the trivial 1st dimension + cu_cgrad_op = array_ops.squeeze(cu_cgrad_op, axis=0) + + cu_wgrad_op, cu_bgrad_op = format_converter.opaque_to_tf_canonical( + opaque_grad_op) + cu_wgrad_op = cu_wgrad_op[0] + cu_bgrad_op = cu_bgrad_op[0] + # cudnn lstm has 2 biases each gate. When converting to tf canonical format, + # the two biases are summed into one. Thus here bias gradient should be + # halved when comparing with tf lstm. + cu_bgrad_op *= 0.5 + + init_op = variables.global_variables_initializer() + sess.run(init_op) + + if is_training: + outputs, state_tuple, inp_grad, state_grad, wgrad, bgrad = sess.run([ + outputs_op, state_tuple_op, inp_grad_op, + (hgrad_op, cgrad_op), wgrad_op, bgrad_op + ]) + (cu_outputs, cu_state_tuple, cu_inp_grad, cu_state_grad, cu_wgrad, + cu_bgrad) = sess.run([ + cu_outputs_op, cu_state_tuple_op, cu_inp_grad_op, + (cu_hgrad_op, cu_cgrad_op), cu_wgrad_op, cu_bgrad_op + ]) + + logging.vlog(1, "outputs: %s" % outputs) + logging.vlog(1, "cu_outputs: %s" % cu_outputs) + logging.vlog(1, "state_tuple: %s" % str(state_tuple)) + logging.vlog(1, "cu_state_tuple: %s" % str(cu_state_tuple)) + logging.vlog(1, "inp_grad: %s" % inp_grad) + logging.vlog(1, "cu_inp_grad: %s" % cu_inp_grad) + logging.vlog(1, "state_grad: %s" % str(state_grad)) + logging.vlog(1, "cu_state_grad: %s" % str(cu_state_grad)) + logging.vlog(1, "wgrad: %s" % str(wgrad)) + logging.vlog(1, "bgrad: %s" % str(bgrad)) + logging.vlog(1, "cu_wgrad: %s" % str(cu_wgrad)) + logging.vlog(1, "cu_bgrad: %s" % str(cu_bgrad)) + return (outputs, cu_outputs, state_tuple, cu_state_tuple, inp_grad, + cu_inp_grad, state_grad, cu_state_grad, wgrad, bgrad, cu_wgrad, + cu_bgrad) else: - raise ValueError("Invalid rnn_mode: %s" % rnn_mode) - return model_fn( - num_layers, - num_units, - input_size, - direction=direction, - dtype=dtype, - dropout=dropout) - - -def _CreateParamsSavable(params, - model, - base_variable_scope=None, - name="params_canonical"): - """Create a RNNParamsSaveable for the weight and bias parameters. + outputs, state_tuple = sess.run([outputs_op, state_tuple_op]) + cu_outputs, cu_state_tuple = sess.run([cu_outputs_op, cu_state_tuple_op]) + + logging.vlog(1, "outputs: %s" % outputs) + logging.vlog(1, "cu_outputs: %s" % cu_outputs) + logging.vlog(1, "state_tuple: %s" % str(state_tuple)) + logging.vlog(1, "cu_state_tuple: %s" % str(cu_state_tuple)) + return outputs, cu_outputs, state_tuple, cu_state_tuple + + +# Basic set of RNN configs to test. They can be further extended in relevant +# test (e.g. adding num_dirs). +NAMED_RNN_TESTCASES = ({ + "testcase_name": "xsmall", + "num_units": 1, + "input_size": 1, + "batch_size": 1, + "time": 1, + "num_layers": 1, +}, { + "testcase_name": "small", + "num_units": 4, + "input_size": 4, + "batch_size": 4, + "time": 4, + "num_layers": 1, +}, { + "testcase_name": "medium", + "num_units": 128, + "input_size": 64, + "batch_size": 8, + "time": 16, + "num_layers": 1, +}, { + "testcase_name": "large", + "num_units": 128, + "input_size": 128, + "batch_size": 16, + "time": 32, + "num_layers": 1, +}) + + +def ExpandNamedTestCases(inputs, *remove_keys, **extra_configs): + """Expands testcase with new config dimensions. + + Example: + inputs = ( + {'testcase_name': 'test1', 'gender': 'male'} + {'testcase_name': 'test2', 'gender': 'female'} + ) + remove_keys: empty + extra_configs = { + 'age': [40, 80] + 'height': [5, 6] + } + + Returns: + ( + {'testcase_name': 'test1_age_40_height_5','gender': 'male', 'age': + 40,'height': 5} + {'testcase_name': 'test1_age_40_height_6', 'gender': 'male', 'age': 40, + 'height': 6} + {'testcase_name': 'test1_age_80_height_5', 'gender': 'male', 'age': 80, + 'height': 5} + {'testcase_name': 'test1_age_80_height_6', 'gender': 'male', 'age': 80, + 'height': 6} + + {'testcase_name': 'test2_age_40_height_5', 'gender': 'female', 'age': + 40, + 'height': 5} + {'testcase_name': 'test2_age_40_height_6', 'gender': 'female', 'age': + 40, + 'height': 6} + {'testcase_name': 'test2_age_80_height_5', 'gender': 'female', 'age': + 80, + 'height': 5} + {'testcase_name': 'test2_age_80_height_6', 'gender': 'female', 'age': + 80, + 'height': 6} + ) Args: - params: a Variable for weight and bias parameters. - model: a CudnnRNN model. - base_variable_scope: a string, prefix of names of saved variables. - name: a string, name of the RNNParamsSaveable object. + inputs: A list of dictionary, each being a testcase. + *remove_keys: A list of keys into testcase which are not needed in new + testcases. + **extra_configs: A dict of new test dimension and applicable values in that + dimension. + Returns: - a RNNParamsSaveable object. + A list of dictionary with expanded test cases. """ - if model._rnn_mode == CUDNN_LSTM: - fn = cudnn_rnn_ops.CudnnLSTMSaveable - elif model._rnn_mode == CUDNN_GRU: - fn = cudnn_rnn_ops.CudnnGRUSaveable - elif model._rnn_mode == CUDNN_RNN_TANH: - fn = cudnn_rnn_ops.CudnnRNNTanhSaveable - elif model._rnn_mode == CUDNN_RNN_RELU: - fn = cudnn_rnn_ops.CudnnRNNReluSaveable - params_saveable = fn( - params, - model.num_layers, - model.num_units, - model.input_size, - model.input_mode, - model.direction, - scope=base_variable_scope, - name=name) - ops.add_to_collection(ops.GraphKeys.SAVEABLE_OBJECTS, params_saveable) - return params_saveable - - -def _MinLSTMParamSize(num_layers, - num_units, - input_size, - direction=cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION): - if direction == cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION: - first_layer_weights = 4 * num_units * (num_units + input_size) - higher_layer_weights = 8 * (num_layers - 1) * num_units * num_units - all_biases = 8 * num_layers * num_units - return first_layer_weights + higher_layer_weights + all_biases - elif direction == cudnn_rnn_ops.CUDNN_RNN_BIDIRECTION: - first_layer_weights = 4 * num_units * (num_units + input_size) - higher_layer_weights = (num_layers - 1) * ( - 4 * 2 * num_units * num_units + 4 * num_units**2) - all_biases = 8 * num_layers * num_units - return 2 * (first_layer_weights + higher_layer_weights + all_biases) - else: - raise ValueError("%s direction is not supported.") + res = [] + ordered_extra_configs = collections.OrderedDict(extra_configs) + keys = ordered_extra_configs.keys() + # A list of list of configs. + # The outer loop is iterating keys, the innner is values of one key. + combined_kv = [[(k, v) for v in ordered_extra_configs[k]] for k in keys] + logging.info("combined_kv: %s", combined_kv) + for inp in inputs: + # Each inp is a dict + for config in itertools.product(*combined_kv): + new_inp = dict(inp) + # config is a list in the form of [(k_i, v_j), (k_p, v_q), ...] + suffix = ["%s_%s" % (p[0], str(p[1])) for p in config] + suffix = "_".join(suffix) + new_inp["testcase_name"] += "_" + suffix + for k, v in config: + new_inp[k] = v + # Remove not used keys from the new test case. + if remove_keys: + if not isinstance(remove_keys, (list, tuple)): + remove_keys = [remove_keys] + for k in remove_keys: + new_inp.pop(k, None) + logging.info("new_inp: %s", new_inp) + res.append(new_inp) + # Dedup, necessary if `remove_keys` is set. + return [dict(t) for t in {tuple(d.items()) for d in res}] -class CudnnRNNTestSaveRestore(TensorFlowTestCase): - def _CompareWeights(self, lhs, rhs): - self.assertEqual(len(lhs), len(rhs)) - for lw, rw in zip(lhs, rhs): - self.assertAllEqual(lw, rw) +class CudnnLSTMTest(TensorFlowTestCase, parameterized.TestCase): - def _CompareBiases(self, lhs, rhs, rnn_mode, num_layers, direction): - self.assertEqual(len(lhs), len(rhs)) - if rnn_mode == CUDNN_LSTM: - num_params_per_layer = CUDNN_LSTM_PARAMS_PER_LAYER - elif rnn_mode == CUDNN_GRU: - num_params_per_layer = CUDNN_GRU_PARAMS_PER_LAYER - elif rnn_mode == CUDNN_RNN_TANH: - num_params_per_layer = CUDNN_RNN_TANH_PARAMS_PER_LAYER - else: - num_params_per_layer = CUDNN_RNN_RELU_PARAMS_PER_LAYER - num_dirs = 1 if direction == CUDNN_RNN_UNIDIRECTION else 2 - num_params_per_layer *= num_dirs - self.assertEqual(num_params_per_layer * num_layers, len(lhs)) - - for i in range(num_layers): - layer_lhs = lhs[i * num_params_per_layer: (i+1) * num_params_per_layer] - layer_rhs = rhs[i * num_params_per_layer: (i+1) * num_params_per_layer] - if direction == CUDNN_RNN_UNIDIRECTION: - self._CompareSingleLayerBiases(layer_lhs, layer_rhs) - else: - size = len(layer_lhs) - fw_lhs, bw_lhs = layer_lhs[:size//2], layer_lhs[size//2:] - fw_rhs, bw_rhs = layer_rhs[:size//2], layer_rhs[size//2:] - self._CompareSingleLayerBiases(fw_lhs, fw_rhs) - self._CompareSingleLayerBiases(bw_lhs, bw_rhs) - - def _CompareSingleLayerBiases(self, lhs, rhs): - self.assertEqual(len(lhs), len(rhs)) - - lf_lhs, rt_lhs = lhs[:len(lhs)//2], lhs[len(lhs)//2:] - lf_rhs, rt_rhs = rhs[:len(rhs)//2], rhs[len(rhs)//2:] - self.assertEqual(len(lf_lhs), len(rt_lhs)) - self.assertEqual(len(lf_rhs), len(rt_rhs)) - - sum_lhs, sum_rhs = [], [] - for lf, rt in zip(lf_lhs, rt_lhs): - sum_lhs.append(lf + rt) - for lf, rt in zip(lf_rhs, rt_rhs): - sum_rhs.append(lf + rt) - self.assertEqual(len(sum_lhs), len(sum_rhs)) - for lf, rt in zip(sum_lhs, sum_rhs): - self.assertAllEqual(lf, rt) + def _test_training_helper(self, + num_units, + input_size, + batch_size, + time, + num_layers, + dtype, + rtol=2e-6, + atol=2e-6): + with self.session(use_gpu=True) as sess: + (outputs, cu_outputs, state_tuple, cu_state_tuple, inp_grad, cu_inp_grad, + state_grad, cu_state_grad, wgrad, bgrad, cu_wgrad, cu_bgrad) = RunLSTM( + sess, num_units, input_size, batch_size, time, num_layers) - def _testSaveRestoreVariable(self, rnn_mode, direction, dtype): - num_layers = 2 - num_units = 7 - input_size = 3 - with ops.Graph().as_default(): - model = _CreateModel( - rnn_mode, - num_layers=num_layers, - num_units=num_units, - input_size=input_size, - direction=direction, - dtype=dtype) - random_seed.set_random_seed(1234) - params_size_t = model.params_size() - params = variables.VariableV1( - random_ops.random_uniform([params_size_t], dtype=dtype), - dtype=dtype, - validate_shape=False) - saveable = _CreateParamsSavable(params, model) - weights, biases = saveable.format_converter._opaque_to_cu_canonical( - saveable._variables) - reset_params = state_ops.assign( - params, - array_ops.zeros([params_size_t], dtype=dtype), - validate_shape=False) - save_path = os.path.join(self.get_temp_dir(), - "save-restore-variable-test") - saver = saver_lib.Saver(write_version=saver_pb2.SaverDef.V2) - # Passing graph explicitly, otherwise an old sess would be reused. - with self.test_session( - use_gpu=True, graph=ops.get_default_graph()) as sess: - sess.run(variables.global_variables_initializer()) - val = saver.save(sess, save_path) - self.assertEqual(save_path, val) + self.assertAllClose(outputs, cu_outputs, rtol=rtol, atol=atol) + for s, cu_s in zip(state_tuple, cu_state_tuple): + self.assertAllClose(s, cu_s, rtol=rtol, atol=atol) + for sg, cu_sg in zip(state_grad, cu_state_grad): + self.assertAllClose(sg, cu_sg, rtol=rtol, atol=atol) + self.assertAllClose(inp_grad, cu_inp_grad, rtol=rtol, atol=atol) + self.assertAllClose(bgrad, cu_bgrad, rtol=rtol, atol=atol) + self.assertAllClose(wgrad, cu_wgrad, rtol=rtol, atol=atol) - weights_v, biases_v = sess.run([weights, biases]) + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_training(self, num_units, input_size, batch_size, time, num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + self._test_training_helper(num_units, input_size, batch_size, time, + num_layers, dtypes.float32) - sess.run(reset_params) - saver.restore(sess, save_path) - weights_v_restored, biases_v_restored = sess.run([weights, biases]) - - self._CompareWeights(weights_v, weights_v_restored) - self._CompareBiases(biases_v, biases_v_restored, rnn_mode, num_layers, - direction) - - def _testSaveRestoreTwoVariables(self, rnn_mode, direction, dtype): - num_layers = 2 - num_units = 7 - input_size = 3 - with ops.Graph().as_default(): - model = _CreateModel( - rnn_mode, - num_layers=num_layers, - num_units=num_units, - input_size=input_size, - direction=direction, - dtype=dtype) - random_seed.set_random_seed(1234) - params_size_t = model.params_size() - names = ["rnn_1", "rnn_2"] - param_vars = [ - variables.VariableV1( - random_ops.random_uniform([params_size_t], dtype=dtype), - dtype=dtype, - validate_shape=False) for name in names - ] - saveables = [] - for name, params in zip(names, param_vars): - saveables.append(_CreateParamsSavable(params, model, name, name)) - weights1, biases1 = saveables[0].format_converter._opaque_to_cu_canonical( - saveables[0]._variables) - weights2, biases2 = saveables[1].format_converter._opaque_to_cu_canonical( - saveables[1]._variables) - reset_params = [ - state_ops.assign( - params, - array_ops.zeros([params_size_t], dtype=dtype), - validate_shape=False) for params in param_vars - ] - save_path = os.path.join(self.get_temp_dir(), - "save-restore-variable-test") - saver = saver_lib.Saver(write_version=saver_pb2.SaverDef.V2) - # Passing graph explicitly, otherwise an old sess would be reused. - with self.test_session(use_gpu=True, - graph=ops.get_default_graph()) as sess: - sess.run(variables.global_variables_initializer()) - val = saver.save(sess, save_path) - self.assertEqual(save_path, val) - weights1_v, biases1_v = sess.run([weights1, biases1]) - weights2_v, biases2_v = sess.run([weights2, biases2]) - - sess.run(reset_params) - saver.restore(sess, save_path) - weights1_v_restored, biases1_v_restored = sess.run([weights1, biases1]) - weights2_v_restored, biases2_v_restored = sess.run([weights2, biases2]) - - self._CompareWeights(weights1_v, weights1_v_restored) - self._CompareWeights(weights2_v, weights2_v_restored) - self._CompareBiases(biases1_v, biases1_v_restored, rnn_mode, num_layers, - direction) - self._CompareBiases(biases2_v, biases2_v_restored, rnn_mode, num_layers, - direction) - - def _testSaveRestoreOutput(self, rnn_mode, direction, dtype): - with ops.Graph().as_default(): - num_layers = 2 - num_units = 7 - input_size = 7 - seq_length = 10 - batch_size = 5 - dir_count = 1 if direction == cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION else 2 - model = _CreateModel( - rnn_mode, + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_training_fp16(self, num_units, input_size, batch_size, time, + num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + self._test_training_helper( + num_units, + input_size, + batch_size, + time, + num_layers, + dtypes.float16, + rtol=5e-3, + atol=5e-4) + + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_inference(self, num_units, input_size, batch_size, time, num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + with self.session(use_gpu=True) as sess: + (outputs, cu_outputs, state_tuple, cu_state_tuple) = RunLSTM( + sess, + num_units, + input_size, + batch_size, + time, num_layers, + is_training=False) + + self.assertAllClose(outputs, cu_outputs) + # h + self.assertAllClose(state_tuple.h, cu_state_tuple.h) + # c + self.assertAllClose(state_tuple.c, cu_state_tuple.c) + + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_inference_fp16(self, num_units, input_size, batch_size, time, + num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + with self.session(use_gpu=True) as sess: + (outputs, cu_outputs, state_tuple, cu_state_tuple) = RunLSTM( + sess, num_units, input_size, - direction=direction, - dtype=dtype) - params_size_t = model.params_size() - params = variables.VariableV1( - array_ops.ones([params_size_t], dtype=dtype), - validate_shape=False, - dtype=dtype) - _CreateParamsSavable(params, model) - save_path = os.path.join(self.get_temp_dir(), "save-restore-output-test") - saver = saver_lib.Saver(write_version=saver_pb2.SaverDef.V2) + batch_size, + time, + num_layers, + is_training=False, + dtype=dtypes.float16) - np.random.seed(1234) - has_input_c = (rnn_mode == cudnn_rnn_ops.CUDNN_LSTM) - input_data = constant_op.constant( - np.random.randn(seq_length, batch_size, input_size), dtype=dtype) - input_h = constant_op.constant( - np.random.randn(num_layers * dir_count, batch_size, num_units), - dtype=dtype) - if has_input_c: - input_c = constant_op.constant( - np.random.randn(num_layers * dir_count, batch_size, num_units), - dtype=dtype) - outputs = model( - input_data=input_data, - input_h=input_h, - input_c=input_c, - params=params, - is_training=False) - else: - outputs = model( - input_data=input_data, - input_h=input_h, - params=params, - is_training=False) - total_sum = sum(map(math_ops.reduce_sum, outputs)) - # Passing graph explicitly, otherwise an old sess would be reused. - with self.test_session( - use_gpu=True, graph=ops.get_default_graph()) as sess: - sess.run(variables.global_variables_initializer()) - total_sum_v = sess.run(total_sum) - val = saver.save(sess, save_path) - self.assertEqual(save_path, val) - # Passing graph explicitly, otherwise an old sess would be reused. - with self.test_session( - use_gpu=True, graph=ops.get_default_graph()) as sess: - reset_params = state_ops.assign( - params, - array_ops.zeros([params_size_t], dtype=dtype), - validate_shape=False) - sess.run(reset_params) - saver.restore(sess, save_path) - total_sum_v_restored = sess.run(total_sum) - self.assertAllClose(total_sum_v, total_sum_v_restored, atol=1e-5) + rtol, atol = 5e-3, 5e-4 + self.assertAllClose(outputs, cu_outputs, rtol=rtol, atol=atol) + # h + self.assertAllClose( + state_tuple.h, cu_state_tuple.h, rtol=rtol, atol=atol) + # c + self.assertAllClose( + state_tuple.c, cu_state_tuple.c, rtol=rtol, atol=atol) + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) @unittest.skipUnless(test.is_built_with_cuda(), "Test only applicable when running on GPUs") - def testSaveRestore(self): - rnn_modes = [ - cudnn_rnn_ops.CUDNN_LSTM, cudnn_rnn_ops.CUDNN_GRU, - cudnn_rnn_ops.CUDNN_RNN_TANH, cudnn_rnn_ops.CUDNN_RNN_RELU - ] - directions = [ - cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION, - cudnn_rnn_ops.CUDNN_RNN_BIDIRECTION - ] - dtype_list = [dtypes.float32, dtypes.float64] - for rnn_mode, direction, dtype in itertools.product(rnn_modes, directions, - dtype_list): - self._testSaveRestoreVariable(rnn_mode, direction, dtype) - self._testSaveRestoreTwoVariables(rnn_mode, direction, dtype) - self._testSaveRestoreOutput(rnn_mode, direction, dtype) - - -class CudnnRNNTestParamsSize(TensorFlowTestCase): - - def _testOneLSTMParamsSize(self, num_layers, num_units, input_size, - direction): - logging.info("Testing one lstm param size with config: %s", locals()) - min_params_size = _MinLSTMParamSize(num_layers, num_units, input_size, - direction) - model = _CreateModel( - cudnn_rnn_ops.CUDNN_LSTM, - num_layers, + def test_inference_with_dropout(self, num_units, input_size, batch_size, time, + num_layers): + """Validates that dropout does not affect Cudnn Rnn inference.""" + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + # Hand-picked dropouts are used below (0. and 1.) + with ops.Graph().as_default() as g: + with self.session(use_gpu=True, graph=g) as sess: + # 1st time w/o dropout. + (_, cu_outputs, _, cu_state_tuple) = RunLSTM( + sess, + num_units, + input_size, + batch_size, + time, + num_layers, + is_training=False, + dropout=0.) + + with ops.Graph().as_default() as g: + with self.session(use_gpu=True, graph=g) as sess: + (_, cu_outputs2, _, cu_state_tuple2) = RunLSTM( + sess, + num_units, + input_size, + batch_size, + time, + num_layers, + is_training=False, + dropout=1.) + + self.assertAllClose(cu_outputs, cu_outputs2) + # h + self.assertAllClose(cu_state_tuple.h, cu_state_tuple2.h) + # c + self.assertAllClose(cu_state_tuple.c, cu_state_tuple2.c) + + +def RunGRU(sess, + num_units, + input_size, + batch_size, + time, + num_layers=1, + is_training=True, + dropout=0., + num_dirs=True, + dtype=dtypes.float32): + # TODO(jamesqin): add multi-layer tests. + # TODO(jamesqin): add multi-dir tests + assert num_layers == 1 + assert num_dirs == 1 + if is_training and not np.isclose(dropout, 0): + raise ValueError("dropout can not be 0. when test training.") + + # set graph level random seed and numpy random seed. + random_seed.set_random_seed(0) + np.random.seed(0) + + inputs = variable_scope.get_variable( + "inputs", + initializer=np.random.rand(time, batch_size, + input_size).astype(dtype.as_numpy_dtype), + dtype=dtype) + initial_h_op = variable_scope.get_variable( + "initial_h_op", + initializer=np.random.rand(batch_size, + num_units).astype(dtype.as_numpy_dtype), + dtype=dtype) + + initializer = init_ops.random_uniform_initializer( + -0.01, 0.01, dtype=dtype, seed=19980904) + with variable_scope.variable_scope("test", initializer=initializer): + gate_kernel = variable_scope.get_variable( + "rnn/cudnn_compatible_gru_cell/gates/kernel", + shape=[input_size + num_units, num_units * 2], + dtype=dtype) + gate_bias = variable_scope.get_variable( + "rnn/cudnn_compatible_gru_cell/gates/bias", + shape=[num_units * 2], + dtype=dtype) + candidate_inp_kernel = variable_scope.get_variable( + "rnn/cudnn_compatible_gru_cell/candidate/input_projection/kernel", + shape=[input_size, num_units], + dtype=dtype) + candidate_inp_bias = variable_scope.get_variable( + "rnn/cudnn_compatible_gru_cell/candidate/input_projection/bias", + shape=[num_units], + dtype=dtype) + candidate_hid_kernel = variable_scope.get_variable( + "rnn/cudnn_compatible_gru_cell/candidate/hidden_projection/kernel", + shape=[num_units, num_units], + dtype=dtype) + candidate_hid_bias = variable_scope.get_variable( + "rnn/cudnn_compatible_gru_cell/candidate/hidden_projection/bias", + shape=[num_units], + dtype=dtype) + + cell = cudnn_rnn_ops.CudnnCompatibleGRUCell(num_units, reuse=True) + outputs_op, h_op = rnn.dynamic_rnn( + cell, + inputs, + initial_state=initial_h_op, + dtype=dtype, + time_major=True, + scope=None) + + ws = [gate_kernel, candidate_inp_kernel, candidate_hid_kernel] + bs = [gate_bias, candidate_inp_bias, candidate_hid_bias] + # Convert to cudnn opaque param. + format_converter = cudnn_rnn_ops.CudnnParamsFormatConverterGRU( + num_layers, num_units, input_size) + opaque_params = format_converter.tf_canonical_to_opaque(ws + bs) + + cu_initial_h_op = array_ops.expand_dims(initial_h_op, axis=0) + cu_outputs_op, cu_h_op, _ = cudnn_rnn_ops._cudnn_rnn( + inputs, + cu_initial_h_op, + array_ops.zeros_like(cu_initial_h_op), # not used + opaque_params, + dropout=dropout, + is_training=is_training, + rnn_mode=cudnn_rnn_ops.CUDNN_GRU) + + if is_training: + (inp_grad_op, hgrad_op, gk_grad_op, cik_grad_op, chk_grad_op, gb_grad_op, + cib_grad_op, chb_grad_op) = gradients_impl.gradients( + outputs_op, [inputs, initial_h_op] + ws + bs) + + (cu_inp_grad_op, cu_hgrad_op, opaque_grad_op) = gradients_impl.gradients( + cu_outputs_op, [inputs, cu_initial_h_op, opaque_params]) + # Remove the trivial 1st dimension + cu_hgrad_op = array_ops.squeeze(cu_hgrad_op, axis=0) + + cu_wgrad_op, cu_bgrad_op = format_converter.opaque_to_tf_canonical( + opaque_grad_op) + (cu_gk_grad_op, cu_cik_grad_op, cu_chk_grad_op) = cu_wgrad_op + (cu_gb_grad_op, cu_cib_grad_op, cu_chb_grad_op) = cu_bgrad_op + # cudnn gru has 2 biases for reset and update gates. When converting to tf + # canonical format, the two biases are summed into one. Thus here relevant + # bias gradient should be halved before comparing with tf gru. + cu_gb_grad_op *= 0.5 + + init_op = variables.global_variables_initializer() + sess.run(init_op) + + if is_training: + outputs, h, inp_grad, hgrad, wgrad, bgrad = sess.run([ + outputs_op, h_op, inp_grad_op, hgrad_op, + (gk_grad_op, cik_grad_op, chk_grad_op), + (gb_grad_op, cib_grad_op, chb_grad_op) + ]) + (cu_outputs, cu_h, cu_inp_grad, cu_hgrad, cu_wgrad, cu_bgrad) = sess.run([ + cu_outputs_op, cu_h_op, cu_inp_grad_op, cu_hgrad_op, + (cu_gk_grad_op, cu_cik_grad_op, cu_chk_grad_op), + (cu_gb_grad_op, cu_cib_grad_op, cu_chb_grad_op) + ]) + # Remove the trivial 1st dimension + cu_h = np.squeeze(cu_h, axis=0) + + logging.vlog(1, "outputs: %s" % outputs) + logging.vlog(1, "cu_outputs: %s" % cu_outputs) + logging.vlog(1, "h: %s" % h) + logging.vlog(1, "cu_h: %s" % h) + logging.vlog(1, "inp_grad: %s" % inp_grad) + logging.vlog(1, "cu_inp_grad: %s" % cu_inp_grad) + logging.vlog(1, "hgrad: %s" % hgrad) + logging.vlog(1, "cu_hgrad: %s" % cu_hgrad) + logging.vlog(1, "wgrad: %s" % str(wgrad)) + logging.vlog(1, "bgrad: %s" % str(bgrad)) + logging.vlog(1, "cu_wgrad: %s" % str(cu_wgrad)) + logging.vlog(1, "cu_bgrad: %s" % str(cu_bgrad)) + return (outputs, cu_outputs, h, cu_h, inp_grad, cu_inp_grad, hgrad, + cu_hgrad, wgrad, bgrad, cu_wgrad, cu_bgrad) + else: + outputs, h = sess.run([outputs_op, h_op]) + cu_outputs, cu_h = sess.run([cu_outputs_op, cu_h_op]) + # Remove the trivial 1st dimension. + cu_h = np.squeeze(cu_h, axis=0) + + logging.vlog(1, "outputs: %s" % outputs) + logging.vlog(1, "cu_outputs: %s" % cu_outputs) + logging.vlog(1, "h: %s" % h) + logging.vlog(1, "cu_h: %s" % h) + return outputs, cu_outputs, h, cu_h + + +class CudnnGRUTest(TensorFlowTestCase, parameterized.TestCase): + + def _test_training_helper(self, + num_units, + input_size, + batch_size, + time, + num_layers, + dtype, + rtol=2e-6, + atol=2e-6): + with self.session(use_gpu=True) as sess: + (outputs, cu_outputs, h, cu_h, inp_grad, cu_inp_grad, hgrad, + cu_hgrad, wgrad, bgrad, cu_wgrad, cu_bgrad) = RunGRU( + sess, num_units, input_size, batch_size, time, num_layers) + + self.assertAllClose(outputs, cu_outputs, rtol=rtol, atol=atol) + self.assertAllClose(h, cu_h, rtol=rtol, atol=atol) + self.assertAllClose(hgrad, cu_hgrad, rtol=rtol, atol=atol) + self.assertAllClose(inp_grad, cu_inp_grad, rtol=rtol, atol=atol) + for bg, cu_bg in zip(bgrad, cu_bgrad): + self.assertAllClose(bg, cu_bg, rtol=rtol, atol=atol) + for wg, cu_wg in zip(wgrad, cu_wgrad): + self.assertAllClose(wg, cu_wg, rtol=rtol, atol=atol) + + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_training(self, num_units, input_size, batch_size, time, num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + self._test_training_helper(num_units, input_size, batch_size, time, + num_layers, dtypes.float32) + + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_training_fp16(self, num_units, input_size, batch_size, time, + num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + self._test_training_helper( num_units, input_size, - direction=direction) - params_size = model.params_size() - with self.test_session(use_gpu=True, graph=ops.get_default_graph()) as sess: - params_size_v = sess.run(params_size) - self.assertLessEqual(min_params_size, params_size_v) + batch_size, + time, + num_layers, + dtypes.float16, + rtol=5e-3, + atol=5e-4) + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) @unittest.skipUnless(test.is_built_with_cuda(), "Test only applicable when running on GPUs") - def testLSTMParamsSize(self): - test_configs = [ - [4, 200, 200], - [4, 200, 300], - [4, 200, 100], - [1, 100, 200], - [2, 200, 100], - [3, 200, 400], - ] - directions = [ - cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION, - cudnn_rnn_ops.CUDNN_RNN_BIDIRECTION - ] - for (config, direction) in itertools.product(test_configs, directions): - num_layers, num_units, input_size = config - with ops.Graph().as_default(): - self._testOneLSTMParamsSize(num_layers, num_units, input_size, - direction) + def test_inference(self, num_units, input_size, batch_size, time, num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + with self.session(use_gpu=True) as sess: + (outputs, cu_outputs, h, cu_h) = RunGRU( + sess, + num_units, + input_size, + batch_size, + time, + num_layers, + is_training=False) + self.assertAllClose(outputs, cu_outputs) + self.assertAllClose(h, cu_h) + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) @unittest.skipUnless(test.is_built_with_cuda(), "Test only applicable when running on GPUs") - def testLSTMParamsSizeShape(self): - with self.assertRaisesRegexp( - ValueError, "Shape must be rank 0 but is rank 1"): - model = _CreateModel( - cudnn_rnn_ops.CUDNN_LSTM, - constant_op.constant([4]), 200, 200, - direction=cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION) - _ = model.params_size() - with self.assertRaisesRegexp( - ValueError, "Shape must be rank 0 but is rank 1"): - model = _CreateModel( - cudnn_rnn_ops.CUDNN_LSTM, - 4, constant_op.constant([200]), 200, - direction=cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION) - _ = model.params_size() - with self.assertRaisesRegexp( - ValueError, "Shape must be rank 0 but is rank 1"): - model = _CreateModel( + def test_inference_fp16(self, num_units, input_size, batch_size, time, + num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + with self.session(use_gpu=True) as sess: + (outputs, cu_outputs, h, cu_h) = RunGRU( + sess, + num_units, + input_size, + batch_size, + time, + num_layers, + is_training=False, + dtype=dtypes.float16) + + rtol, atol = 5e-3, 5e-4 + self.assertAllClose(outputs, cu_outputs, rtol=rtol, atol=atol) + self.assertAllClose(h, cu_h, rtol=rtol, atol=atol) + + @parameterized.named_parameters(*NAMED_RNN_TESTCASES) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_inference_with_dropout(self, num_units, input_size, batch_size, time, + num_layers): + """Validates that dropout does not affect Cudnn Rnn inference.""" + # Hand-picked dropouts are used below (0. and 1.) + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + with ops.Graph().as_default() as g: + with self.session(use_gpu=True, graph=g) as sess: + # 1st time w/o dropout. + (_, cu_outputs, _, cu_h) = RunGRU( + sess, + num_units, + input_size, + batch_size, + time, + num_layers, + is_training=False, + dropout=0.) + + with ops.Graph().as_default() as g: + with self.session(use_gpu=True, graph=g) as sess: + (_, cu_outputs2, _, cu_h2) = RunGRU( + sess, + num_units, + input_size, + batch_size, + time, + num_layers, + is_training=False, + dropout=1.) + + self.assertAllClose(cu_outputs, cu_outputs2) + self.assertAllClose(cu_h[0], cu_h2[0]) + + +class CudnnParamsFormatConverterTest(TensorFlowTestCase, + parameterized.TestCase): + """Class for testing various format converters.""" + + def _test_lstm_helper(self, num_units, input_size, num_layers, direction): + with self.session(use_gpu=True) as sess: + random_seed.set_random_seed(0) + np.random.seed(0) + + num_dirs = 1 if direction == cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION else 2 + format_converter = cudnn_rnn_ops.CudnnParamsFormatConverterLSTM( + num_layers, num_units, input_size, direction=direction) + + ws, bs = [], [] + for _ in range(num_layers * num_dirs): + w = constant_op.constant( + np.random.rand(input_size + num_units, 4 * num_units), + dtype=dtypes.float32) + b = constant_op.constant( + np.random.rand(4 * num_units), dtype=dtypes.float32) + ws.append(w) + bs.append(b) + + opaque_params = format_converter.tf_canonical_to_opaque(ws + bs) + opaque_params_size = cudnn_rnn_ops.cudnn_rnn_opaque_params_size( cudnn_rnn_ops.CUDNN_LSTM, - 4, 200, constant_op.constant([200]), - direction=cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION) - _ = model.params_size() + num_layers, + num_units, + input_size, + direction=direction) + ws_r, bs_r = format_converter.opaque_to_tf_canonical(opaque_params) -class CudnnRNNTestInference(TensorFlowTestCase): + # Test tf_canonical_to_opaque() followed by opaque_to_tf_canonical() + # returns the original input. + ws, ws_r, bs, bs_r = sess.run([ws, ws_r, bs, bs_r]) + for w, w_r in zip(ws, ws_r): + self.assertAllClose(w, w_r) + for b, b_r in zip(bs, bs_r): + self.assertAllClose(b, b_r) - def _testOneSimpleInference(self, rnn_mode, num_layers, num_units, input_size, - batch_size, seq_length, dir_count, dropout, - expected, tolerance): - random_seed.set_random_seed(5678) - model = _CreateModel( - rnn_mode, - num_layers, - num_units, - input_size, - input_mode="auto_select", - direction=(cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION if dir_count == 1 - else cudnn_rnn_ops.CUDNN_RNN_BIDIRECTION), - dropout=dropout) - has_input_c = (rnn_mode == cudnn_rnn_ops.CUDNN_LSTM) - params_size_t = model.params_size() - input_data = array_ops.ones([seq_length, batch_size, input_size]) - input_h = array_ops.ones([num_layers * dir_count, batch_size, num_units]) - params = variables.VariableV1( - array_ops.ones([params_size_t]), validate_shape=False) - if has_input_c: - input_c = array_ops.ones([num_layers * dir_count, batch_size, num_units]) - output, output_h, output_c = model( - input_data=input_data, - input_h=input_h, - input_c=input_c, - params=params, - is_training=False) - else: - output, output_h = model( - input_data=input_data, - input_h=input_h, - params=params, - is_training=False) - output_sum = math_ops.reduce_sum(output) - output_h_sum = math_ops.reduce_sum(output_h) - total_sum = output_sum + output_h_sum - if has_input_c: - output_c_sum = math_ops.reduce_sum(output_c) - total_sum += output_c_sum - with self.test_session(use_gpu=True, graph=ops.get_default_graph()) as sess: - sess.run(variables.global_variables_initializer()) - total_sum_v = sess.run([total_sum]) + # Test opaque_params size lower bound + opaque_params_size_v = sess.run(opaque_params_size) + min_params_size = sum(x.size for x in ws) + np.sum(x.size for x in bs) + logging.info("min_parm_size: %d vs actual_opaque_param_size: %d", + min_params_size, opaque_params_size_v) + self.assertLessEqual(min_params_size, opaque_params_size_v) - self.assertAllClose( - total_sum_v[0], expected, atol=tolerance, rtol=tolerance) + @parameterized.named_parameters((c["testcase_name"], c["num_units"], + c["input_size"], c["num_layers"]) + for c in NAMED_RNN_TESTCASES) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_lstm(self, num_units, input_size, num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + self._test_lstm_helper(num_units, input_size, num_layers, + cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION) + @parameterized.named_parameters((c["testcase_name"], c["num_units"], + c["input_size"], c["num_layers"]) + for c in NAMED_RNN_TESTCASES) @unittest.skipUnless(test.is_built_with_cuda(), "Test only applicable when running on GPUs") - def testSimpleInference(self): - test_configs = [ - { - "rnn_mode": cudnn_rnn_ops.CUDNN_LSTM, - "expected": 231833.22, - "tolerance": 1e-2, - "shape": { - "num_layers": 4, - "num_units": 200, - "input_size": 200, - "batch_size": 20, - "seq_length": 10, - "dir_count": 1, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_GRU, - "expected": 56000, - "tolerance": 1e-2, - "shape": { - "num_layers": 4, - "num_units": 200, - "input_size": 200, - "batch_size": 20, - "seq_length": 10, - "dir_count": 1, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_RNN_TANH, - "expected": 56000, - "tolerance": 1e-2, - "shape": { - "num_layers": 4, - "num_units": 200, - "input_size": 200, - "batch_size": 20, - "seq_length": 10, - "dir_count": 1, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_RNN_RELU, - "expected": 130688, - "tolerance": 1e-2, - "shape": { - "num_layers": 2, - "num_units": 8, - "input_size": 4, - "batch_size": 4, - "seq_length": 2, - "dir_count": 1, - }, - }, - ] - # Cudnn scales result for dropout during training, therefore dropout has no - # impact for inference results. - # (lstm, gru, rnn_tanh are saturated in the test. rnn_relu case is most - # demonstrative of the dropout-invariant nature of CudnnRnn.) - dropouts = [0., 0.5, 1.] - for (config, dropout) in itertools.product(test_configs, dropouts): - rnn_mode = config["rnn_mode"] - expected = config["expected"] - tolerance = config["tolerance"] - shape = config["shape"] - with ops.Graph().as_default(): - self._testOneSimpleInference( - rnn_mode, shape["num_layers"], shape["num_units"], - shape["input_size"], shape["batch_size"], shape["seq_length"], - shape["dir_count"], dropout, expected, tolerance) - - -class CudnnRNNTestTraining(TensorFlowTestCase): - - def _testOneSimpleTraining(self, rnn_mode, num_layers, num_units, input_size, - batch_size, seq_length, dir_count, dropout, dtype, - delta, tolerance): - # Gradient checking runs two forward ops with almost the same input. Need to - # make sure the drop patterns across the two runs are the same. - logging.info("Training test with config: %s", locals()) - old_env_state = os.environ.get("TF_CUDNN_RESET_RND_GEN_STATE", str(False)) - os.environ["TF_CUDNN_RESET_RND_GEN_STATE"] = str(True) - has_input_c = (rnn_mode == cudnn_rnn_ops.CUDNN_LSTM) - random_seed.set_random_seed(5678) - direction = (cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION if dir_count == 1 - else cudnn_rnn_ops.CUDNN_RNN_BIDIRECTION) - model = _CreateModel( - rnn_mode, - num_layers, - num_units, - input_size, - direction=direction, - dtype=dtype, - dropout=dropout) - params_size_t = model.params_size() - input_data = variables.VariableV1( - random_ops.random_uniform( - [seq_length, batch_size, input_size], dtype=dtype), - dtype=dtype) - input_h = variables.VariableV1( - random_ops.random_uniform( - [num_layers * dir_count, batch_size, num_units], dtype=dtype), - dtype=dtype) - params = variables.VariableV1( - random_ops.random_uniform([params_size_t], dtype=dtype), - validate_shape=False, - dtype=dtype) - if has_input_c: - input_c = variables.VariableV1( - random_ops.random_uniform( - [num_layers * dir_count, batch_size, num_units], dtype=dtype), - dtype=dtype) - - output, output_h, output_c = model( - input_data=input_data, - input_h=input_h, - input_c=input_c, - params=params) - else: - output, output_h = model( - input_data=input_data, input_h=input_h, params=params) - output_sum = math_ops.reduce_sum(output) - output_h_sum = math_ops.reduce_sum(output_h) - total_sum = output_sum + output_h_sum - if has_input_c: - output_c_sum = math_ops.reduce_sum(output_c) - total_sum += output_c_sum - - with self.test_session(use_gpu=True, graph=ops.get_default_graph()) as sess: - params_size_v = sess.run(params_size_t) - inputs_and_shapes = [ - (input_data, [seq_length, batch_size, input_size]), - (input_h, [num_layers * dir_count, batch_size, num_units]), - (params, [params_size_v]), - ] - if has_input_c: - inputs_and_shapes.append( - (input_c, [num_layers * dir_count, batch_size, num_units]),) - sess.run(variables.global_variables_initializer()) - all_inputs = [entry[0] for entry in inputs_and_shapes] - all_shapes = [entry[1] for entry in inputs_and_shapes] - - err = gradient_checker.compute_gradient_error( - all_inputs, all_shapes, total_sum, [1], delta=delta) - - self.assertLess(err, tolerance) - os.environ["TF_CUDNN_RESET_RND_GEN_STATE"] = old_env_state + def test_lstm_bidi(self, num_units, input_size, num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + self._test_lstm_helper(num_units, input_size, num_layers, + cudnn_rnn_ops.CUDNN_RNN_BIDIRECTION) + + def _test_gru_helper(self, num_units, input_size, num_layers, direction): + with self.session(use_gpu=True) as sess: + random_seed.set_random_seed(0) + np.random.seed(0) + + num_dirs = 1 if direction == cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION else 2 + format_converter = cudnn_rnn_ops.CudnnParamsFormatConverterGRU( + num_layers, num_units, input_size, direction=direction) + + ws, bs = [], [] + for _ in range(num_layers * num_dirs): + gate_kernel = constant_op.constant( + np.random.rand(input_size + num_units, num_units * 2), + dtype=dtypes.float32) + gate_bias = constant_op.constant( + np.random.rand(num_units * 2), dtype=dtypes.float32) + candidate_inp_kernel = constant_op.constant( + np.random.rand(input_size, num_units), dtype=dtypes.float32) + candidate_inp_bias = constant_op.constant( + np.random.rand(num_units), dtype=dtypes.float32) + candidate_hid_kernel = constant_op.constant( + np.random.rand(num_units, num_units), dtype=dtypes.float32) + candidate_hid_bias = constant_op.constant( + np.random.rand(num_units), dtype=dtypes.float32) + ws.extend([gate_kernel, candidate_inp_kernel, candidate_hid_kernel]) + bs.extend([gate_bias, candidate_inp_bias, candidate_hid_bias]) + opaque_params = format_converter.tf_canonical_to_opaque(ws + bs) + opaque_params_size = cudnn_rnn_ops.cudnn_rnn_opaque_params_size( + cudnn_rnn_ops.CUDNN_GRU, + num_layers, + num_units, + input_size, + direction=direction) + + ws_r, bs_r = format_converter.opaque_to_tf_canonical(opaque_params) + + # Test tf_canonical_to_opaque() followed by opaque_to_tf_canonical() + # returns the original input. + ws, ws_r, bs, bs_r = sess.run([ws, ws_r, bs, bs_r]) + for w, w_r in zip(ws, ws_r): + self.assertAllClose(w, w_r) + for b, b_r in zip(bs, bs_r): + self.assertAllClose(b, b_r) + + # Test opaque_params size lower bound + opaque_params_size_v = sess.run(opaque_params_size) + min_params_size = sum(x.size for x in ws) + sum(x.size for x in bs) + logging.info("min_parm_size: %d vs actual_opaque_param_size: %d", + min_params_size, opaque_params_size_v) + self.assertLessEqual(min_params_size, opaque_params_size_v) + + @parameterized.named_parameters((c["testcase_name"], c["num_units"], + c["input_size"], c["num_layers"]) + for c in NAMED_RNN_TESTCASES) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_gru(self, num_units, input_size, num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + self._test_gru_helper(num_units, input_size, num_layers, + cudnn_rnn_ops.CUDNN_RNN_UNIDIRECTION) + + @parameterized.named_parameters((c["testcase_name"], c["num_units"], + c["input_size"], c["num_layers"]) + for c in NAMED_RNN_TESTCASES) @unittest.skipUnless(test.is_built_with_cuda(), "Test only applicable when running on GPUs") - def DISABLED_testSimpleTraining(self): - # TODO(jamesqin): fix b/117989214 - test_configs = [ - { - "rnn_mode": cudnn_rnn_ops.CUDNN_LSTM, - "dtype": dtypes.float64, - "delta": 1e-4, - "tolerance": 5e-6, - "shape": { - "num_layers": 2, - "num_units": 3, - "input_size": 4, - "batch_size": 3, - "seq_length": 4, - "dir_count": 1, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_GRU, - "dtype": dtypes.float64, - "delta": 1e-4, - "tolerance": 5e-6, - "shape": { - "num_layers": 2, - "num_units": 3, - "input_size": 4, - "batch_size": 3, - "seq_length": 4, - "dir_count": 1, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_RNN_TANH, - "dtype": dtypes.float64, - "delta": 1e-4, - "tolerance": 5e-6, - "shape": { - "num_layers": 2, - "num_units": 3, - "input_size": 4, - "batch_size": 3, - "seq_length": 4, - "dir_count": 1, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_RNN_RELU, - "dtype": dtypes.float64, - "delta": 1e-4, - "tolerance": 5e-6, - "shape": { - "num_layers": 2, - "num_units": 3, - "input_size": 4, - "batch_size": 3, - "seq_length": 4, - "dir_count": 1, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_LSTM, - "dtype": dtypes.float32, - "tolerance": 1.5e-2, - "shape": { - "num_layers": 2, - "num_units": 3, - "input_size": 4, - "batch_size": 3, - "seq_length": 4, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_GRU, - "dtype": dtypes.float32, - "tolerance": 4e-3, - "shape": { - "num_layers": 2, - "num_units": 3, - "input_size": 4, - "batch_size": 3, - "seq_length": 4, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_RNN_TANH, - "dtype": dtypes.float32, - "tolerance": 5e-3, - "shape": { - "num_layers": 2, - "num_units": 3, - "input_size": 4, - "batch_size": 3, - "seq_length": 4, - }, - }, - { - "rnn_mode": cudnn_rnn_ops.CUDNN_RNN_RELU, - "dtype": dtypes.float32, - "tolerance": 5e-1, - "shape": { - "num_layers": 2, - "num_units": 3, - "input_size": 4, - "batch_size": 3, - "seq_length": 4, - }, - }, - ] - dropouts = [0., 0.5, 1.] - dir_counts = [1] - for config, dropout, dir_count in itertools.product(test_configs, dropouts, - dir_counts): - rnn_mode = config["rnn_mode"] - dtype = config.get("dtype", dtypes.float32) - delta = config.get("delta", 1e-3) - tolerance = config["tolerance"] - shape = config["shape"] - with ops.Graph().as_default(): - self._testOneSimpleTraining(rnn_mode, shape["num_layers"], - shape["num_units"], shape["input_size"], - shape["batch_size"], shape["seq_length"], - dir_count, dropout, dtype, delta, tolerance) + def test_gru_bidi(self, num_units, input_size, num_layers): + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + self._test_gru_helper(num_units, input_size, num_layers, + cudnn_rnn_ops.CUDNN_RNN_BIDIRECTION) + + +class CudnnRnnSaveRestoreTest(TensorFlowTestCase, parameterized.TestCase): + """Class for testing various Cudnn Rnn SaveableObjects.""" + + def _create_opaque_param(self, + rnn_mode, + num_units, + input_size, + num_layers, + direction, + name=None): + param_size_t = cudnn_rnn_ops.cudnn_rnn_opaque_params_size( + rnn_mode, num_layers, num_units, input_size, direction=direction) + init_val = random_ops.random_uniform([param_size_t]) + return variable_scope.get_variable( + name or "opaque_param", initializer=init_val, validate_shape=False) + + def _create_saveable(self, opaque_param, rnn_mode, num_units, input_size, + num_layers, direction): + if rnn_mode == CUDNN_LSTM: + fn = cudnn_rnn_ops.CudnnLSTMSaveable + elif rnn_mode == CUDNN_GRU: + fn = cudnn_rnn_ops.CudnnGRUSaveable + elif rnn_mode == CUDNN_RNN_TANH: + fn = cudnn_rnn_ops.CudnnRNNTanhSaveable + elif rnn_mode == CUDNN_RNN_RELU: + fn = cudnn_rnn_ops.CudnnRNNReluSaveable + saveable = fn( + opaque_param, num_layers, num_units, input_size, direction=direction) + return saveable + + def _compare_weights(self, lhs, rhs): + self.assertLen(rhs, len(lhs)) + for lw, rw in zip(lhs, rhs): + self.assertAllEqual(lw, rw) + + def _compare_biases(self, lhs, rhs): + self.assertLen(rhs, len(lhs)) + for lf, rt in zip(lhs, rhs): + self.assertAllEqual(lf, rt) + + @parameterized.named_parameters( + ExpandNamedTestCases( + NAMED_RNN_TESTCASES, "time", "batch_size", **{ + "rnn_mode": [ + CUDNN_LSTM, CUDNN_GRU, CUDNN_RNN_RELU, CUDNN_RNN_TANH + ], + "direction": [CUDNN_RNN_UNIDIRECTION, CUDNN_RNN_BIDIRECTION] + })) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_save_restore_variable(self, rnn_mode, num_units, input_size, + num_layers, direction): + # Verify the restored opaque param, once converted to tf_canonical format, + # is the same as the tf canonicals of the pre-restored param. + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + with self.session(use_gpu=True) as sess: + opaque_param = self._create_opaque_param(rnn_mode, num_units, input_size, + num_layers, direction) + saveable = self._create_saveable(opaque_param, rnn_mode, num_units, + input_size, num_layers, direction) + ops.add_to_collection(ops.GraphKeys.SAVEABLE_OBJECTS, saveable) + weights_op, biases_op = saveable.format_converter.opaque_to_tf_canonical( + saveable._variables) + + save_path = os.path.join(self.get_temp_dir(), "save_restore_var_test") + saver = saver_lib.Saver(write_version=saver_pb2.SaverDef.V2) + + init_op = variables.global_variables_initializer() + reset_op = state_ops.assign(opaque_param, + array_ops.zeros_like(opaque_param)) + sess.run(init_op) + self.assertEqual(save_path, saver.save(sess, save_path)) + + # Get the tf canonical vals before reset-restore + weights, biases = sess.run([weights_op, biases_op]) + + # Reset the opaque param value + sess.run(reset_op) + # Assert reset happened. + weights_z, biases_z = sess.run([weights_op, biases_op]) + for w in weights_z: + self.assertAllClose(w, np.zeros_like(w)) + for b in biases_z: + self.assertAllClose(b, np.zeros_like(b)) + + # Restore opaque param value from checkpoint. + saver.restore(sess, save_path) + weights_r, biases_r = sess.run([weights_op, biases_op]) + self._compare_weights(weights, weights_r) + self._compare_biases(biases, biases_r) + + @parameterized.named_parameters( + ExpandNamedTestCases( + NAMED_RNN_TESTCASES, "time", "batch_size", **{ + "rnn_mode": [ + CUDNN_LSTM, CUDNN_GRU, CUDNN_RNN_RELU, CUDNN_RNN_TANH + ], + "direction": [CUDNN_RNN_UNIDIRECTION, CUDNN_RNN_BIDIRECTION] + })) + @unittest.skipUnless(test.is_built_with_cuda(), + "Test only applicable when running on GPUs") + def test_save_restore_multi_variables(self, rnn_mode, num_units, input_size, + num_layers, direction): + # Verify the restored opaque param, once converted to tf_canonical format, + # is the same as the tf canonicals of the pre-restored param. + if not context.context().num_gpus(): + self.skipTest("No GPUs found") + with self.session(use_gpu=True) as sess: + opaque_params = [] + saveables = [] + num_opaque_params = 2 + for i in range(num_opaque_params): + opaque_params.append( + self._create_opaque_param( + rnn_mode, + num_units, + input_size, + num_layers, + direction, + name="opaque_param_%d" % i)) + saveable = self._create_saveable(opaque_params[i], rnn_mode, num_units, + input_size, num_layers, direction) + ops.add_to_collection(ops.GraphKeys.SAVEABLE_OBJECTS, saveable) + saveables.append(saveable) + + weights_ops, biases_ops = [], [] + for i in range(num_opaque_params): + weights_op, biases_op = ( + saveables[i].format_converter.opaque_to_tf_canonical( + saveables[i]._variables)) + weights_ops.append(weights_op) + biases_ops.append(biases_op) + + save_path = os.path.join(self.get_temp_dir(), "save_restore_var_test") + saver = saver_lib.Saver(write_version=saver_pb2.SaverDef.V2) + + init_op = variables.global_variables_initializer() + reset_ops = [] + for i in range(num_opaque_params): + reset_ops.append( + state_ops.assign(opaque_params[i], + array_ops.zeros_like(opaque_params[i]))) + sess.run(init_op) + self.assertEqual(save_path, saver.save(sess, save_path)) + + # Get the tf canonical vals before reset-restore + for i in range(num_opaque_params): + weights, biases = sess.run([weights_ops[i], biases_ops[i]]) + + # Reset the opaque param value + sess.run(reset_ops[i]) + + # Assert reset happened. + weights_z, biases_z = sess.run([weights_ops[i], biases_ops[i]]) + for w in weights_z: + self.assertAllClose(w, np.zeros_like(w)) + for b in biases_z: + self.assertAllClose(b, np.zeros_like(b)) + + # Restore opaque param value from checkpoint. + saver.restore(sess, save_path) + weights_r, biases_r = sess.run([weights_ops[i], biases_ops[i]]) + self._compare_weights(weights, weights_r) + self._compare_biases(biases, biases_r) if __name__ == "__main__": diff --git a/tensorflow/contrib/cudnn_rnn/python/kernel_tests/cudnn_rnn_test.py b/tensorflow/contrib/cudnn_rnn/python/kernel_tests/cudnn_rnn_test.py index 1954f6717b..7e1b4062ce 100644 --- a/tensorflow/contrib/cudnn_rnn/python/kernel_tests/cudnn_rnn_test.py +++ b/tensorflow/contrib/cudnn_rnn/python/kernel_tests/cudnn_rnn_test.py @@ -536,7 +536,9 @@ class CudnnRNNTestSaveRestore(test_util.TensorFlowTestCase): save_path = os.path.join(self.get_temp_dir(), "save-restore-variable-test") saver = saver_lib.Saver() - weights, biases = model.rnn.saveable._OpaqueParamsToCanonical() + weights, biases = ( + model.rnn.saveable.format_converter._opaque_to_cu_canonical( + model.rnn.saveable._variables)) opaque_params = rnn.trainable_variables[0] # CudnnTestModel() creates CudnnOpaqueParamsSaveable that helps saver save # Cudnn vars in canonical format. @@ -583,8 +585,12 @@ class CudnnRNNTestSaveRestore(test_util.TensorFlowTestCase): dtype=dtype) opaque_params = (model1.rnn.trainable_variables[0], model2.rnn.trainable_variables[0]) - weights1, biases1 = model1.rnn.saveable._OpaqueParamsToCanonical() - weights2, biases2 = model2.rnn.saveable._OpaqueParamsToCanonical() + saveable1 = model1.rnn.saveable + weights1, biases1 = saveable1.format_converter._opaque_to_cu_canonical( + saveable1._variables) + saveable2 = model1.rnn.saveable + weights2, biases2 = saveable2.format_converter._opaque_to_cu_canonical( + saveable2._variables) reset_params = [ state_ops.assign(params, array_ops.zeros_like(params, dtype=dtype)) @@ -1039,8 +1045,8 @@ class CudnnRNNTestParamsSize(test_util.TensorFlowTestCase): # Min param size estimate = sum(weights.size) + sum(biases.size) min_params_size = ( - np.sum(list(map(np.prod, rnn.canonical_weight_shapes))) + - np.sum([sp[0] for sp in rnn.canonical_bias_shapes])) + sum(map(np.prod, rnn.canonical_weight_shapes)) + + sum(sp[0] for sp in rnn.canonical_bias_shapes)) opaque_params = rnn.trainable_variables[0] with self.test_session(use_gpu=True, graph=ops.get_default_graph()): diff --git a/tensorflow/contrib/cudnn_rnn/python/layers/cudnn_rnn.py b/tensorflow/contrib/cudnn_rnn/python/layers/cudnn_rnn.py index 8bbcc7cd03..8e25637ed9 100644 --- a/tensorflow/contrib/cudnn_rnn/python/layers/cudnn_rnn.py +++ b/tensorflow/contrib/cudnn_rnn/python/layers/cudnn_rnn.py @@ -21,6 +21,7 @@ from tensorflow.contrib.cudnn_rnn.python.ops import cudnn_rnn_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.keras.engine import input_spec from tensorflow.python.layers import base as base_layer from tensorflow.python.ops import array_ops from tensorflow.python.ops import init_ops @@ -322,7 +323,7 @@ class _CudnnRNN(base_layer.Layer): raise ValueError("The last dimension of the inputs to `CudnnRNN` " "should be defined. Found `None`.") self._input_size = input_shape[-1].value - self.input_spec = base_layer.InputSpec(ndim=3, axes={-1: self._input_size}) + self.input_spec = input_spec.InputSpec(ndim=3, axes={-1: self._input_size}) self._set_scope(None) diff --git a/tensorflow/contrib/cudnn_rnn/python/ops/cudnn_rnn_ops.py b/tensorflow/contrib/cudnn_rnn/python/ops/cudnn_rnn_ops.py index d06d0c6bda..1ce29b42d5 100644 --- a/tensorflow/contrib/cudnn_rnn/python/ops/cudnn_rnn_ops.py +++ b/tensorflow/contrib/cudnn_rnn/python/ops/cudnn_rnn_ops.py @@ -738,7 +738,7 @@ class CudnnOpaqueParamsSaveable(saver.BaseSaverBuilder.SaveableObject): self._variables, opaque_params, validate_shape=False) def _checkpointable_save(self, save_buffer): - weights, biases = self.format_converter.opaque_params_to_tf_canonical( + weights, biases = self.format_converter.opaque_to_tf_canonical( self._variables) for name, tensor in zip(self._param_names, weights + biases): save_buffer[name] = array_ops.identity(tensor) diff --git a/tensorflow/contrib/data/python/kernel_tests/assert_element_shape_test.py b/tensorflow/contrib/data/python/kernel_tests/assert_element_shape_test.py index 0456463a19..6c5f8c6b00 100644 --- a/tensorflow/contrib/data/python/kernel_tests/assert_element_shape_test.py +++ b/tensorflow/contrib/data/python/kernel_tests/assert_element_shape_test.py @@ -46,7 +46,7 @@ class AssertElementShapeTest(test_base.DatasetTestBase): result = dataset.apply(batching.assert_element_shape(expected_shapes)) self.assertEqual(expected_shapes, result.output_shapes) - iterator = result.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(result) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: @@ -88,7 +88,7 @@ class AssertElementShapeTest(test_base.DatasetTestBase): result = dataset.apply(batching.assert_element_shape(expected_shapes)) self.assertEqual(expected_shapes, result.output_shapes) - iterator = result.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(result) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: @@ -115,9 +115,8 @@ class AssertElementShapeTest(test_base.DatasetTestBase): wrong_shapes = (tensor_shape.TensorShape(2), tensor_shape.TensorShape((3, 10))) - iterator = ( - dataset.apply(batching.assert_element_shape(wrong_shapes)) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset.apply(batching.assert_element_shape(wrong_shapes))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: @@ -142,7 +141,7 @@ class AssertElementShapeTest(test_base.DatasetTestBase): tensor_shape.TensorShape((3, 4))) self.assertEqual(actual_shapes, result.output_shapes) - iterator = result.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(result) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: @@ -184,7 +183,7 @@ class AssertElementShapeTest(test_base.DatasetTestBase): result = dataset.apply(batching.assert_element_shape(expected_shapes)) self.assertEqual(expected_shapes, result.output_shapes) - iterator = result.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(result) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: @@ -211,9 +210,8 @@ class AssertElementShapeTest(test_base.DatasetTestBase): wrong_shapes = (tensor_shape.TensorShape(2), tensor_shape.TensorShape((None, 10))) - iterator = ( - dataset.apply(batching.assert_element_shape(wrong_shapes)) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset.apply(batching.assert_element_shape(wrong_shapes))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: diff --git a/tensorflow/contrib/data/python/kernel_tests/lmdb_dataset_op_test.py b/tensorflow/contrib/data/python/kernel_tests/lmdb_dataset_op_test.py index d2a72272db..b9840b1ff1 100644 --- a/tensorflow/contrib/data/python/kernel_tests/lmdb_dataset_op_test.py +++ b/tensorflow/contrib/data/python/kernel_tests/lmdb_dataset_op_test.py @@ -23,6 +23,7 @@ import shutil from tensorflow.contrib.data.python.ops import readers from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors @@ -48,7 +49,7 @@ class LMDBDatasetTest(test_base.DatasetTestBase): num_repeats = 2 dataset = readers.LMDBDataset(filenames).repeat(num_repeats) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() diff --git a/tensorflow/contrib/data/python/kernel_tests/slide_dataset_op_test.py b/tensorflow/contrib/data/python/kernel_tests/slide_dataset_op_test.py index c5a7862322..2527706709 100644 --- a/tensorflow/contrib/data/python/kernel_tests/slide_dataset_op_test.py +++ b/tensorflow/contrib/data/python/kernel_tests/slide_dataset_op_test.py @@ -63,13 +63,13 @@ class SlideDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): # The pipeline is TensorSliceDataset -> MapDataset(square_3) -> # RepeatDataset(count) -> # _SlideDataset(window_size, window_shift, window_stride). - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(components).map(_map_fn) .repeat(count).apply( sliding.sliding_window_batch( window_size=window_size_t, window_shift=window_shift_t, - window_stride=window_stride_t)).make_initializable_iterator()) + window_stride=window_stride_t))) init_op = iterator.initializer get_next = iterator.get_next() @@ -127,13 +127,13 @@ class SlideDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): # The pipeline is TensorSliceDataset -> MapDataset(square_3) -> # RepeatDataset(count) -> _SlideDataset(window_size, stride, window_stride). - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(components).map(_map_fn) .repeat(count).apply( sliding.sliding_window_batch( window_size=window_size_t, stride=stride_t, - window_stride=window_stride_t)).make_initializable_iterator()) + window_stride=window_stride_t))) init_op = iterator.initializer get_next = iterator.get_next() @@ -173,12 +173,12 @@ class SlideDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): window_shift_t = array_ops.placeholder(dtypes.int64, shape=[]) window_stride_t = array_ops.placeholder(dtypes.int64, shape=[]) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.range(10).map(lambda x: x).repeat(count_t).apply( sliding.sliding_window_batch( window_size=window_size_t, window_shift=window_shift_t, - window_stride=window_stride_t)).make_initializable_iterator()) + window_stride=window_stride_t))) init_op = iterator.initializer with self.cached_session() as sess: @@ -204,9 +204,9 @@ class SlideDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): return sparse_tensor.SparseTensorValue( indices=[[0]], values=(i * [1]), dense_shape=[1]) - iterator = dataset_ops.Dataset.range(10).map(_sparse).apply( - sliding.sliding_window_batch( - window_size=5, window_shift=3)).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10).map(_sparse).apply( + sliding.sliding_window_batch(window_size=5, window_shift=3))) init_op = iterator.initializer get_next = iterator.get_next() @@ -233,9 +233,9 @@ class SlideDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): values=array_ops.fill([math_ops.to_int32(i)], i), dense_shape=[i]) - iterator = dataset_ops.Dataset.range(10).map(_sparse).apply( - sliding.sliding_window_batch( - window_size=5, window_shift=3)).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10).map(_sparse).apply( + sliding.sliding_window_batch(window_size=5, window_shift=3))) init_op = iterator.initializer get_next = iterator.get_next() @@ -265,11 +265,10 @@ class SlideDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): return sparse_tensor.SparseTensorValue( indices=[[0]], values=(i * [1]), dense_shape=[1]) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.range(10).map(_sparse).apply( sliding.sliding_window_batch(window_size=4, window_shift=2)).apply( - sliding.sliding_window_batch(window_size=3, window_shift=1)) - .make_initializable_iterator()) + sliding.sliding_window_batch(window_size=3, window_shift=1))) init_op = iterator.initializer get_next = iterator.get_next() @@ -305,11 +304,10 @@ class SlideDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): yield [4.0, 5.0, 6.0] yield [7.0, 8.0, 9.0, 10.0] - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_generator( generator, dtypes.float32, output_shapes=[None]).apply( - sliding.sliding_window_batch(window_size=3, window_shift=1)) - .make_initializable_iterator()) + sliding.sliding_window_batch(window_size=3, window_shift=1))) next_element = iterator.get_next() with self.cached_session() as sess: diff --git a/tensorflow/contrib/data/python/ops/BUILD b/tensorflow/contrib/data/python/ops/BUILD index 34dc2379d0..0fb406f116 100644 --- a/tensorflow/contrib/data/python/ops/BUILD +++ b/tensorflow/contrib/data/python/ops/BUILD @@ -188,8 +188,7 @@ py_library( "//tensorflow/python:framework_ops", "//tensorflow/python:function", "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/data/util:nest", - "//tensorflow/python/data/util:sparse", + "//tensorflow/python/data/util:structure", ], ) diff --git a/tensorflow/contrib/data/python/ops/readers.py b/tensorflow/contrib/data/python/ops/readers.py index 4601376dff..aa42782807 100644 --- a/tensorflow/contrib/data/python/ops/readers.py +++ b/tensorflow/contrib/data/python/ops/readers.py @@ -355,7 +355,7 @@ def read_batch_features(file_pattern, shuffle=randomize_input, num_epochs=num_epochs, shuffle_buffer_size=capacity) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) outputs = iterator.get_next() return outputs @@ -379,15 +379,13 @@ class LMDBDataset(dataset_ops.DatasetSource): (key value) pairs sequentially. For example: ```python + tf.enable_eager_execution() + dataset = tf.contrib.lmdb.LMDBDataset("/foo/bar.mdb") - iterator = dataset.make_one_shot_iterator() - next_element = iterator.get_next() + # Prints the (key, value) pairs inside a lmdb file. - while True: - try: - print(sess.run(next_element)) - except tf.errors.OutOfRangeError: - break + for key, value in dataset: + print(key, value) ``` Args: filenames: A `tf.string` tensor containing one or more filenames. diff --git a/tensorflow/contrib/data/python/ops/sliding.py b/tensorflow/contrib/data/python/ops/sliding.py index bcc383587c..9ebdca317f 100644 --- a/tensorflow/contrib/data/python/ops/sliding.py +++ b/tensorflow/contrib/data/python/ops/sliding.py @@ -18,11 +18,10 @@ from __future__ import division from __future__ import print_function from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.data.util import nest +from tensorflow.python.data.util import structure from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops -from tensorflow.python.framework import tensor_shape -from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops from tensorflow.python.util import deprecation @@ -40,29 +39,31 @@ class _SlideDataset(dataset_ops.UnaryDataset): self._window_shift = ops.convert_to_tensor( window_shift, dtype=dtypes.int64, name="window_shift") + # pylint: disable=protected-access + input_structure = structure.Structure._from_legacy_structure( + input_dataset.output_types, input_dataset.output_shapes, + input_dataset.output_classes) + self._output_structure = input_structure._batch(None) + def _as_variant_tensor(self): - return gen_dataset_ops.slide_dataset( + return ged_ops.experimental_sliding_window_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access window_size=self._window_size, window_shift=self._window_shift, window_stride=self._window_stride, - **dataset_ops.flat_structure(self)) + **dataset_ops.flat_structure(structure=self._output_structure)) @property def output_classes(self): - return self._input_dataset.output_classes + return self._output_structure._to_legacy_output_classes() # pylint: disable=protected-access @property def output_shapes(self): - input_shapes = self._input_dataset.output_shapes - return nest.pack_sequence_as(input_shapes, [ - tensor_shape.vector(None).concatenate(s) - for s in nest.flatten(self._input_dataset.output_shapes) - ]) + return self._output_structure._to_legacy_output_shapes() # pylint: disable=protected-access @property def output_types(self): - return self._input_dataset.output_types + return self._output_structure._to_legacy_output_types() # pylint: disable=protected-access @deprecation.deprecated_args( diff --git a/tensorflow/contrib/distribute/BUILD b/tensorflow/contrib/distribute/BUILD index a87a5624c8..3ecd755d86 100644 --- a/tensorflow/contrib/distribute/BUILD +++ b/tensorflow/contrib/distribute/BUILD @@ -26,7 +26,6 @@ py_library( visibility = ["//tensorflow:internal"], deps = [ "//tensorflow/contrib/distribute/python:collective_all_reduce_strategy", - "//tensorflow/contrib/distribute/python:cross_tower_ops", "//tensorflow/contrib/distribute/python:mirrored_strategy", "//tensorflow/contrib/distribute/python:monitor", "//tensorflow/contrib/distribute/python:one_device_strategy", @@ -35,6 +34,7 @@ py_library( "//tensorflow/contrib/distribute/python:tpu_strategy", "//tensorflow/python:training", "//tensorflow/python:util", + "//tensorflow/python/distribute:cross_device_ops", "//tensorflow/python/distribute:distribute_config", "//tensorflow/python/distribute:distribute_coordinator", ], diff --git a/tensorflow/contrib/distribute/README.md b/tensorflow/contrib/distribute/README.md index a938f8629d..81574a2047 100644 --- a/tensorflow/contrib/distribute/README.md +++ b/tensorflow/contrib/distribute/README.md @@ -134,7 +134,7 @@ def model_fn(features, labels, mode): return tf.estimator.EstimatorSpec(mode, loss=loss) if mode == tf.estimator.ModeKeys.TRAIN: - train_op = tf.train.GradientDescentOptimizer(0.2).minimize(loss_fn()) + train_op = tf.train.GradientDescentOptimizer(0.2).minimize(loss) return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op) ``` @@ -251,10 +251,10 @@ start multi-worker training using `tf.estimator.train_and_evaluate`: ```python def model_main(): - estimator = ... distribution = tf.contrib.distribute.CollectiveAllReduceStrategy( num_gpus_per_worker=2) config = tf.estimator.RunConfig(train_distribute=distribution) + estimator = tf.estimator.Estimator(model_fn=model_fn, config=config) train_spec = tf.estimator.TrainSpec(input_fn=input_fn) eval_spec = tf.estimator.EvalSpec(input_fn=eval_input_fn) tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec) @@ -327,13 +327,13 @@ start training. On your laptop, you can run ```python -estimator = ... distribution = tf.contrib.distribute.CollectiveAllReduceStrategy( num_gpus_per_worker=2) config = tf.estimator.RunConfig( experimental_distribute=tf.contrib.distribute.DistributeConfig( train_distribute=distribution, remote_cluster={"worker": ["host1:port", "host2:port", "host3:port"]})) +estimator = tf.estimator.Estimator(model_fn=model_fn, config=config) train_spec = tf.estimator.TrainSpec(input_fn=input_fn) eval_spec = tf.estimator.EvalSpec(input_fn=eval_input_fn) tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec) diff --git a/tensorflow/contrib/distribute/__init__.py b/tensorflow/contrib/distribute/__init__.py index ab2f221dc6..8ec73654e3 100644 --- a/tensorflow/contrib/distribute/__init__.py +++ b/tensorflow/contrib/distribute/__init__.py @@ -25,13 +25,13 @@ from __future__ import print_function # pylint: disable=unused-import,wildcard-import from tensorflow.contrib.distribute.python.collective_all_reduce_strategy import CollectiveAllReduceStrategy -from tensorflow.contrib.distribute.python.cross_tower_ops import * from tensorflow.contrib.distribute.python.mirrored_strategy import MirroredStrategy from tensorflow.contrib.distribute.python.monitor import Monitor from tensorflow.contrib.distribute.python.one_device_strategy import OneDeviceStrategy from tensorflow.contrib.distribute.python.parameter_server_strategy import ParameterServerStrategy from tensorflow.contrib.distribute.python.step_fn import * from tensorflow.contrib.distribute.python.tpu_strategy import TPUStrategy +from tensorflow.python.distribute.cross_device_ops import * from tensorflow.python.distribute.distribute_config import DistributeConfig from tensorflow.python.distribute.distribute_coordinator import run_standard_tensorflow_server from tensorflow.python.training.distribute import * @@ -46,6 +46,7 @@ _allowed_symbols = [ 'CrossDeviceOps', 'DistributeConfig', 'DistributionStrategy', + 'DistributionStrategyExtended', 'MirroredStrategy', 'Monitor', 'MultiWorkerAllReduce', @@ -62,6 +63,7 @@ _allowed_symbols = [ 'get_loss_reduction', 'get_replica_context', 'has_distribution_strategy', + 'in_cross_replica_context', 'require_replica_context', 'run_standard_tensorflow_server', 'UpdateContext', diff --git a/tensorflow/contrib/distribute/python/BUILD b/tensorflow/contrib/distribute/python/BUILD index 4094e52169..4c9c35da5a 100644 --- a/tensorflow/contrib/distribute/python/BUILD +++ b/tensorflow/contrib/distribute/python/BUILD @@ -16,45 +16,26 @@ load("//tensorflow:tensorflow.bzl", "cuda_py_test") # TODO(priyag): Figure out testonly issues that are preventing us from # including our tests in pip for now. -py_library( - name = "values", - srcs = ["values.py"], - visibility = ["//tensorflow:internal"], - deps = [ - ":input_ops", - "//tensorflow/python:array_ops", - "//tensorflow/python:control_flow_ops", - "//tensorflow/python:device_util", - "//tensorflow/python:distribute", - "//tensorflow/python:framework_ops", - "//tensorflow/python:resource_variable_ops", - "//tensorflow/python:training", - "//tensorflow/python:util", - "//tensorflow/python/data/ops:multi_device_iterator_ops", - "//tensorflow/python/eager:context", - "//tensorflow/python/training/checkpointable:base", - "@six_archive//:six", - ], -) - cuda_py_test( name = "values_test", srcs = ["values_test.py"], additional_deps = [ + ":combinations", ":mirrored_strategy", ":multi_worker_test_base", - ":values", + "@absl_py//absl/testing:parameterized", "//tensorflow/core:protos_all_py", - "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python:errors", "//tensorflow/python:array_ops", "//tensorflow/python:constant_op", + "//tensorflow/python:errors", "//tensorflow/python:framework_ops", "//tensorflow/python:framework_test_lib", "//tensorflow/python:training", "//tensorflow/python:variable_scope", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/distribute:device_util", + "//tensorflow/python/distribute:values", "//tensorflow/python/eager:context", - "//tensorflow/python:device_util", "//tensorflow/python/eager:test", "//tensorflow/python/estimator:estimator_py", ], @@ -68,25 +49,9 @@ py_library( srcs = ["mirrored_strategy.py"], visibility = ["//tensorflow:internal"], deps = [ - ":cross_tower_ops", - ":shared_variable_creator", - ":values", - "//tensorflow/core:protos_all_py", - "//tensorflow/python:array_ops", - "//tensorflow/python:constant_op", - "//tensorflow/python:control_flow_ops", - "//tensorflow/python:device", - "//tensorflow/python:device_util", - "//tensorflow/python:distribute", - "//tensorflow/python:framework_ops", - "//tensorflow/python:pywrap_tensorflow", - "//tensorflow/python:training", - "//tensorflow/python:util", - "//tensorflow/python:variable_scope", - "//tensorflow/python:variables", - "//tensorflow/python/distribute:multi_worker_util", - "//tensorflow/python/eager:context", - "//tensorflow/python/eager:tape", + "//tensorflow/python/distribute:distribute_lib", + "//tensorflow/python/distribute:mirrored_strategy", + "//tensorflow/python/distribute:values", ], ) @@ -95,16 +60,17 @@ py_library( srcs = ["parameter_server_strategy.py"], visibility = ["//tensorflow:internal"], deps = [ - ":cross_tower_ops", ":mirrored_strategy", - ":values", "//tensorflow/core:protos_all_py", "//tensorflow/python:array_ops", "//tensorflow/python:framework_ops", "//tensorflow/python:resource_variable_ops", "//tensorflow/python:training", "//tensorflow/python:util", + "//tensorflow/python/distribute:cross_device_ops", "//tensorflow/python/distribute:multi_worker_util", + "//tensorflow/python/distribute:reduce_util", + "//tensorflow/python/distribute:values", "//tensorflow/python/eager:context", ], ) @@ -116,7 +82,7 @@ cuda_py_test( ":combinations", ":multi_worker_test_base", ":parameter_server_strategy", - ":values", + ":strategy_test_lib", "@absl_py//absl/testing:parameterized", "//tensorflow/core:protos_all_py", "//tensorflow/python:array_ops", @@ -127,10 +93,12 @@ cuda_py_test( "//tensorflow/python:gradients", "//tensorflow/python:layers", "//tensorflow/python:session", + "//tensorflow/python:tensor_util", "//tensorflow/python:training", "//tensorflow/python:variable_scope", "//tensorflow/python:variables", "//tensorflow/python/distribute:multi_worker_util", + "//tensorflow/python/distribute:values", "//tensorflow/python/eager:context", "//tensorflow/python/estimator:estimator_py", ], @@ -145,12 +113,13 @@ py_library( srcs = ["one_device_strategy.py"], visibility = ["//tensorflow:internal"], deps = [ - ":values", - "//tensorflow/contrib/eager/python:datasets", "//tensorflow/python:array_ops", - "//tensorflow/python:distribute", + "//tensorflow/python:dtypes", "//tensorflow/python:framework_ops", "//tensorflow/python:math_ops", + "//tensorflow/python/distribute:distribute_lib", + "//tensorflow/python/distribute:reduce_util", + "//tensorflow/python/distribute:values", "//tensorflow/python/eager:context", "@six_archive//:six", ], @@ -161,16 +130,16 @@ py_library( srcs = ["collective_all_reduce_strategy.py"], visibility = ["//tensorflow:internal"], deps = [ - ":cross_tower_ops", - ":cross_tower_utils", ":mirrored_strategy", - ":values", "//tensorflow/core:protos_all_py", "//tensorflow/python:array_ops", "//tensorflow/python:collective_ops", "//tensorflow/python:framework_ops", "//tensorflow/python:training", + "//tensorflow/python/distribute:cross_device_ops", + "//tensorflow/python/distribute:cross_device_utils", "//tensorflow/python/distribute:multi_worker_util", + "//tensorflow/python/distribute:values", "//tensorflow/python/eager:context", ], ) @@ -187,11 +156,11 @@ py_library( "//tensorflow/core:protos_all_py", "//tensorflow/python:array_ops", "//tensorflow/python:constant_op", - "//tensorflow/python:distribute", "//tensorflow/python:framework_ops", "//tensorflow/python:layers", "//tensorflow/python:training", "//tensorflow/python:variables", + "//tensorflow/python/distribute:distribute_lib", "//tensorflow/python/eager:backprop", "//tensorflow/python/eager:context", "//tensorflow/python/eager:test", @@ -212,10 +181,10 @@ py_library( ":tpu_strategy", "//tensorflow/contrib/cluster_resolver:cluster_resolver_pip", "//tensorflow/contrib/optimizer_v2:training", - "//tensorflow/python:distribute", "//tensorflow/python:framework_ops", "//tensorflow/python:training", "//tensorflow/python:util", + "//tensorflow/python/distribute:distribute_lib", "//tensorflow/python/eager:context", "@absl_py//absl/testing:parameterized", ], @@ -233,28 +202,6 @@ py_test( ], ) -py_test( - name = "mirrored_strategy_test", - srcs = ["mirrored_strategy_test.py"], - srcs_version = "PY2AND3", - tags = [ - "no_pip", - ], - deps = [ - ":mirrored_strategy", - ":multi_worker_test_base", - ":strategy_test_lib", - "//tensorflow/python:constant_op", - "//tensorflow/python:distribute", - "//tensorflow/python:framework_ops", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:training", - "//tensorflow/python:variable_scope", - "//tensorflow/python/eager:context", - "//tensorflow/python/eager:test", - ], -) - py_test( name = "one_device_strategy_test", srcs = ["one_device_strategy_test.py"], @@ -270,35 +217,32 @@ py_test( ], ) +# TODO(priyag): Rename this test to mirrored_strategy_test cuda_py_test( name = "mirrored_strategy_multigpu_test", srcs = ["mirrored_strategy_multigpu_test.py"], additional_deps = [ + ":combinations", ":mirrored_strategy", ":multi_worker_test_base", - ":values", ":strategy_test_lib", - "//tensorflow/python:distribute", "//tensorflow/core:protos_all_py", "//tensorflow/python:array_ops", "//tensorflow/python:constant_op", + "//tensorflow/python:framework_test_lib", "//tensorflow/python:layers", "//tensorflow/python:state_ops", "//tensorflow/python:variable_scope", - "//tensorflow/python:framework_test_lib", + "//tensorflow/python/distribute:distribute_lib", + "//tensorflow/python/distribute:values", "//tensorflow/python/eager:context", "//tensorflow/python/eager:test", ], + shard_count = 5, tags = [ "guitar", - "no_pip", "multi_and_single_gpu", - # Do not perform the extra analysis on this test, because it is already - # performed for the `:mirrored_strategy_test` target. - "no_oss", - "noasan", - "notap", - "notsan", + "no_pip", ], ) @@ -337,12 +281,15 @@ py_library( visibility = ["//tensorflow:internal"], deps = [ ":one_device_strategy", - ":values", "//tensorflow/contrib/tpu:tpu_lib", "//tensorflow/python:constant_op", "//tensorflow/python:control_flow_ops", + "//tensorflow/python:dtypes", "//tensorflow/python:framework_ops", + "//tensorflow/python:tensor_util", "//tensorflow/python:util", + "//tensorflow/python/distribute:reduce_util", + "//tensorflow/python/distribute:values", ], ) @@ -352,7 +299,6 @@ cuda_py_test( additional_deps = [ ":collective_all_reduce_strategy", ":combinations", - ":cross_tower_utils", ":multi_worker_test_base", ":strategy_test_lib", "@absl_py//absl/testing:parameterized", @@ -368,6 +314,7 @@ cuda_py_test( "//tensorflow/python:layers", "//tensorflow/python:variable_scope", "//tensorflow/python:variables", + "//tensorflow/python/distribute:cross_device_utils", "//tensorflow/python/eager:context", "//tensorflow/python/estimator:estimator_py", ], @@ -469,6 +416,7 @@ cuda_py_test( "multi_and_single_gpu", "no_oss", # http://b/119349471 "no_pip", + "tf_integration_test", ], ) @@ -476,28 +424,18 @@ cuda_py_test( name = "keras_optimizer_v2_test", srcs = ["keras_optimizer_v2_test.py"], additional_deps = [ - ":combinations", - "@absl_py//absl/testing:parameterized", - "//third_party/py/numpy", - "//tensorflow/contrib/optimizer_v2:training", - "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/eager:test", - "//tensorflow/python/estimator:estimator_py", - "//tensorflow/python/feature_column", - "//tensorflow/python:framework_ops", - "//tensorflow/python:platform", - "//tensorflow/python:summary", + ":keras_test_lib", ], tags = [ "multi_and_single_gpu", "no_oss", # http://b/119349471 "no_pip", + "tf_integration_test", ], ) cuda_py_test( name = "estimator_training_test", - size = "large", srcs = ["estimator_training_test.py"], additional_deps = [ ":collective_all_reduce_strategy", @@ -508,7 +446,9 @@ cuda_py_test( "//third_party/py/numpy", "//tensorflow/contrib/optimizer_v2:training", "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/distribute", + "//tensorflow/python/distribute:distribute_config", + "//tensorflow/python/distribute:distribute_coordinator", + "//tensorflow/python/distribute:distribute_coordinator_context", "//tensorflow/python/eager:test", "//tensorflow/python/estimator:estimator_py", "//tensorflow/python/feature_column", @@ -516,7 +456,7 @@ cuda_py_test( "//tensorflow/python:platform", "//tensorflow/python:summary", ], - shard_count = 5, + shard_count = 48, tags = [ "multi_and_single_gpu", "no_pip", @@ -524,6 +464,7 @@ cuda_py_test( "noasan", "nomsan", "notsan", + "no_oss", # http://b/119349471 ], ) @@ -599,52 +540,16 @@ cuda_py_test( ], ) -py_library( - name = "shared_variable_creator", - srcs = ["shared_variable_creator.py"], - visibility = ["//tensorflow:internal"], -) - -py_test( - name = "shared_variable_creator_test", - srcs = ["shared_variable_creator_test.py"], - srcs_version = "PY2AND3", - deps = [ - ":shared_variable_creator", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:variable_scope", - "//tensorflow/python/eager:test", - ], -) - -py_library( - name = "cross_tower_utils", - srcs = ["cross_tower_utils.py"], - srcs_version = "PY2AND3", - deps = [ - ":values", - "//tensorflow/contrib/all_reduce:all_reduce_py", - "//tensorflow/python:array_ops", - "//tensorflow/python:collective_ops", - "//tensorflow/python:device", - "//tensorflow/python:dtypes", - "//tensorflow/python:framework_ops", - "//tensorflow/python:gradients", - "//tensorflow/python:math_ops", - "//tensorflow/python:nccl_ops", - ], -) - cuda_py_test( - name = "cross_tower_utils_test", - srcs = ["cross_tower_utils_test.py"], + name = "cross_device_utils_test", + srcs = ["cross_device_utils_test.py"], additional_deps = [ ":combinations", - ":cross_tower_utils", "@absl_py//absl/testing:parameterized", "//tensorflow/python:constant_op", "//tensorflow/python:framework_ops", "//tensorflow/python:math_ops", + "//tensorflow/python/distribute:cross_device_utils", "//tensorflow/python/eager:context", "//tensorflow/python/eager:test", ], @@ -653,40 +558,20 @@ cuda_py_test( ], ) -py_library( - name = "cross_tower_ops", - srcs = ["cross_tower_ops.py"], - srcs_version = "PY2AND3", - deps = [ - ":cross_tower_utils", - ":values", - "//tensorflow/python:array_ops", - "//tensorflow/python:device_lib", - "//tensorflow/python:framework_ops", - "//tensorflow/python:math_ops", - "//tensorflow/python:platform", - "//tensorflow/python:resource_variable_ops", - "//tensorflow/python:training", - "//tensorflow/python:variable_scope", - "//tensorflow/python/eager:context", - "@six_archive//:six", - ], -) - cuda_py_test( - name = "cross_tower_ops_test", - srcs = ["cross_tower_ops_test.py"], + name = "cross_device_ops_test", + srcs = ["cross_device_ops_test.py"], additional_deps = [ ":combinations", - ":cross_tower_ops", ":multi_worker_test_base", ":mirrored_strategy", - ":values", "@absl_py//absl/testing:parameterized", "//tensorflow/python:array_ops", "//tensorflow/python:constant_op", "//tensorflow/python:framework_ops", "//tensorflow/python:math_ops", + "//tensorflow/python/distribute:cross_device_ops", + "//tensorflow/python/distribute:values", "//tensorflow/python/eager:context", "//tensorflow/python/eager:test", ], @@ -696,37 +581,6 @@ cuda_py_test( ], ) -py_library( - name = "input_ops", - srcs = ["input_ops.py"], - visibility = ["//tensorflow:internal"], - deps = [ - "//tensorflow/python:framework_ops", - "//tensorflow/python/data/util:nest", - ], -) - -cuda_py_test( - name = "input_ops_test", - srcs = ["input_ops_test.py"], - additional_deps = [ - ":input_ops", - "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/contrib/data/python/ops:batching", - "//tensorflow/contrib/data/python/ops:interleave_ops", - "//tensorflow/python:errors", - "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_ops", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:io_ops", - "//tensorflow/python/data/ops:readers", - "//tensorflow/python:util", - ], - tags = [ - "no_pip", - ], -) - py_library( name = "keras_test_lib", testonly = 1, @@ -737,6 +591,7 @@ py_library( "//tensorflow/contrib/distribute/python:tpu_strategy", "//tensorflow/python:client_testlib", "//tensorflow/python:training", + "//tensorflow/python/eager:test", "//tensorflow/python/estimator:estimator_py", "//tensorflow/python/keras", "//third_party/py/numpy", @@ -766,7 +621,6 @@ py_library( srcs = ["metrics_v1_test.py"], deps = [ ":combinations", - "//tensorflow/contrib/data/python/ops:batching", "//tensorflow/python:math_ops", "//tensorflow/python:metrics", "//tensorflow/python:variables", diff --git a/tensorflow/contrib/distribute/python/checkpoint_utils_test.py b/tensorflow/contrib/distribute/python/checkpoint_utils_test.py index d38bdb592a..31bd0e996a 100644 --- a/tensorflow/contrib/distribute/python/checkpoint_utils_test.py +++ b/tensorflow/contrib/distribute/python/checkpoint_utils_test.py @@ -43,7 +43,9 @@ class CheckpointUtilsWithDistributionStrategyTest( distribution=[combinations.default_strategy, combinations.one_device_strategy, combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus], + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus], in_replica_mode=[True, False], mode=["graph"])) def testInitFromCheckpoint(self, distribution, in_replica_mode): diff --git a/tensorflow/contrib/distribute/python/collective_all_reduce_strategy.py b/tensorflow/contrib/distribute/python/collective_all_reduce_strategy.py index efa99d1fc5..e988b63a28 100644 --- a/tensorflow/contrib/distribute/python/collective_all_reduce_strategy.py +++ b/tensorflow/contrib/distribute/python/collective_all_reduce_strategy.py @@ -18,12 +18,16 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.contrib.distribute.python import cross_tower_ops as cross_tower_ops_lib -from tensorflow.contrib.distribute.python import cross_tower_utils +import copy + from tensorflow.contrib.distribute.python import mirrored_strategy -from tensorflow.contrib.distribute.python import values from tensorflow.core.protobuf import rewriter_config_pb2 +from tensorflow.python.distribute import cross_device_ops as cross_device_ops_lib +from tensorflow.python.distribute import cross_device_utils +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribute_lib from tensorflow.python.distribute import multi_worker_util +from tensorflow.python.distribute import values from tensorflow.python.eager import context from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops @@ -32,7 +36,7 @@ from tensorflow.python.platform import tf_logging as logging # TODO(yuefengz): support in-graph replication. -class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): +class CollectiveAllReduceStrategy(distribute_lib.DistributionStrategy): """Distribution strategy that uses collective ops for all-reduce. It is similar to the MirroredStrategy but it uses collective ops for @@ -53,6 +57,17 @@ class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): num_gpus_per_worker: number of local GPUs or GPUs per worker, the default is 0 meaning CPU only. """ + super(CollectiveAllReduceStrategy, self).__init__( + CollectiveAllReduceExtended(self, num_gpus_per_worker)) + + +class CollectiveAllReduceExtended(mirrored_strategy.MirroredExtended): + """Implementation of CollectiveAllReduceStrategy.""" + + def __init__(self, container_strategy, num_gpus_per_worker): + distribute_lib.DistributionStrategyExtended.__init__( + self, container_strategy) + self._cross_device_ops = None self._num_gpus_per_worker = num_gpus_per_worker self._initialize_local_worker(num_gpus_per_worker) @@ -67,14 +82,14 @@ class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): ] else: local_devices = ["/device:CPU:0"] + self._worker_device = device_util.canonicalize("/device:CPU:0") - self._collective_keys = cross_tower_utils.CollectiveKeys() - super(CollectiveAllReduceStrategy, self).__init__( - devices=local_devices, - cross_tower_ops=cross_tower_ops_lib.CollectiveAllReduce( - num_workers=1, - num_gpus_per_worker=num_gpus_per_worker, - collective_keys=self._collective_keys)) + self._collective_keys = cross_device_utils.CollectiveKeys() + self._initialize_local(local_devices) + self._cross_tower_ops = cross_device_ops_lib.CollectiveAllReduce( + num_workers=self._num_workers, + num_gpus_per_worker=num_gpus_per_worker, + collective_keys=self._collective_keys) self._cluster_spec = None self._task_type = None @@ -94,8 +109,7 @@ class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): "Unrecognized task_type: %r, valid task types are: \"chief\", " "\"worker\"." % task_type) cluster_spec = multi_worker_util.normalize_cluster_spec(cluster_spec) - self._num_workers = len(cluster_spec.as_dict().get("worker", [])) + len( - cluster_spec.as_dict().get("chief", [])) + self._num_workers = multi_worker_util.worker_count(cluster_spec, task_type) if not self._num_workers: raise ValueError("No `worker` or `chief` tasks can be found in " "`cluster_spec`.") @@ -103,22 +117,21 @@ class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): self._is_chief = multi_worker_util.is_chief(cluster_spec, task_type, task_id) - worker_device = "/job:%s/task:%d" % (task_type, task_id) + self._worker_device = "/job:%s/task:%d" % (task_type, task_id) if num_gpus_per_worker: local_devices = [ - "%s/device:GPU:%d" % (worker_device, i) + "%s/device:GPU:%d" % (self._worker_device, i) for i in range(num_gpus_per_worker) ] else: - local_devices = [worker_device] + local_devices = [self._worker_device] - self._collective_keys = cross_tower_utils.CollectiveKeys() - super(CollectiveAllReduceStrategy, self).__init__( - devices=local_devices, - cross_tower_ops=cross_tower_ops_lib.CollectiveAllReduce( - num_workers=self._num_workers, - num_gpus_per_worker=num_gpus_per_worker, - collective_keys=self._collective_keys)) + self._collective_keys = cross_device_utils.CollectiveKeys() + self._initialize_local(local_devices) + self._cross_tower_ops = cross_device_ops_lib.CollectiveAllReduce( + num_workers=self._num_workers, + num_gpus_per_worker=num_gpus_per_worker, + collective_keys=self._collective_keys) # Add a default device so that ops without specified devices will not end up # on other workers. @@ -202,17 +215,40 @@ class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): return mirrored_strategy._create_mirrored_variable( devices, _real_mirrored_creator, *args, **kwargs) - def distribute_dataset(self, dataset_fn): + def _distribute_dataset(self, dataset_fn): """Distributes the dataset to each local GPU.""" # TODO(yuefengz): shard the dataset. return values.PerReplicaDataset( self._call_dataset_fn(dataset_fn), self._devices, True) - def configure(self, - session_config=None, - cluster_spec=None, - task_type=None, - task_id=None): + def _make_dataset_iterator(self, dataset): + worker_device_pairs = [(self._worker_device, self._devices)] + return values.DatasetIterator(dataset, worker_device_pairs, + self._num_replicas_in_sync) + + def _make_input_fn_iterator( + self, + input_fn, + replication_mode=distribute_lib.InputReplicationMode.PER_WORKER): + """Distributes the dataset to each local GPU.""" + if self._cluster_spec is None: + input_pipeline_id = 0 + else: + input_pipeline_id = multi_worker_util.id_in_cluster( + self._cluster_spec, self._task_type, self._task_id) + input_context = distribute_lib.InputContext( + num_input_pipelines=self._num_workers, + input_pipeline_id=input_pipeline_id, + num_replicas_in_sync=self._num_replicas_in_sync) + + return values.InputFunctionIterator( + input_fn, [(self._worker_device, self._devices)], [input_context]) + + def _configure(self, + session_config=None, + cluster_spec=None, + task_type=None, + task_id=None): """Configures the object. Args: @@ -232,13 +268,15 @@ class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): self._initialize_multi_worker(self._num_gpus_per_worker, cluster_spec, task_type, task_id) - if not session_config: - return + if session_config: + session_config.CopyFrom(self._update_config_proto(session_config)) + def _update_config_proto(self, config_proto): + updated_config = copy.deepcopy(config_proto) # Enable the scoped allocator optimization for CollectiveOps. This # optimization converts many small all-reduces into fewer larger # all-reduces. - rewrite_options = session_config.graph_options.rewrite_options + rewrite_options = updated_config.graph_options.rewrite_options rewrite_options.scoped_allocator_optimization = ( rewriter_config_pb2.RewriterConfig.ON) # We turn on ScopedAllocator only for CollectiveReduce op, i.e. enable_op = @@ -248,7 +286,7 @@ class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): rewrite_options.scoped_allocator_opts.enable_op.append("CollectiveReduce") if not self._cluster_spec: - return + return updated_config assert self._task_type assert self._task_id is not None @@ -256,26 +294,28 @@ class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): # Collective group leader is needed for collective ops to coordinate # workers. if "chief" in self._cluster_spec.jobs: - session_config.experimental.collective_group_leader = ( + updated_config.experimental.collective_group_leader = ( "/job:chief/replica:0/task:0") else: if "worker" not in self._cluster_spec.jobs: raise ValueError( "You must have `chief` or `worker` jobs in the `cluster_spec`.") - session_config.experimental.collective_group_leader = ( + updated_config.experimental.collective_group_leader = ( "/job:worker/replica:0/task:0") # The device filters prevent communication between workers. - del session_config.device_filters[:] - session_config.device_filters.append( + del updated_config.device_filters[:] + updated_config.device_filters.append( "/job:%s/task:%d" % (self._task_type, self._task_id)) + return updated_config + @property - def between_graph(self): + def experimental_between_graph(self): return True @property - def should_init(self): + def experimental_should_init(self): return True @property @@ -287,6 +327,10 @@ class CollectiveAllReduceStrategy(mirrored_strategy.MirroredStrategy): return self._is_chief @property - def num_replicas_in_sync(self): + def _num_replicas_in_sync(self): return len(self._devices) * self._num_workers + # TODO(priyag): Delete this once all strategies use global batch size. + @property + def _global_batch_size(self): + return False diff --git a/tensorflow/contrib/distribute/python/collective_all_reduce_strategy_test.py b/tensorflow/contrib/distribute/python/collective_all_reduce_strategy_test.py index e3d919dd0d..8a9e583f0a 100644 --- a/tensorflow/contrib/distribute/python/collective_all_reduce_strategy_test.py +++ b/tensorflow/contrib/distribute/python/collective_all_reduce_strategy_test.py @@ -23,13 +23,19 @@ import numpy as np from tensorflow.contrib.distribute.python import collective_all_reduce_strategy from tensorflow.contrib.distribute.python import combinations -from tensorflow.contrib.distribute.python import cross_tower_utils from tensorflow.contrib.distribute.python import multi_worker_test_base +from tensorflow.contrib.distribute.python import strategy_test_lib from tensorflow.core.protobuf import config_pb2 +from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.python import keras +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.distribute import cross_device_utils +from tensorflow.python.distribute import reduce_util +from tensorflow.python.distribute import values from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.layers import core from tensorflow.python.ops import array_ops @@ -51,9 +57,6 @@ class CollectiveAllReduceStrategyTestBase( collective_key_base = 0 def setUp(self): - self._run_options = config_pb2.RunOptions() - self._run_options.experimental.collective_graph_key = 6 - # We use a different key_base for each test so that collective keys won't be # reused. # TODO(yuefengz, tucker): enable it to reuse collective keys in different @@ -71,15 +74,16 @@ class CollectiveAllReduceStrategyTestBase( cluster_spec=self._cluster_spec, task_type=task_type, task_id=task_id) - collective_keys = cross_tower_utils.CollectiveKeys( + collective_keys = cross_device_utils.CollectiveKeys( group_key_start=10 * num_gpus + CollectiveAllReduceStrategyTestBase.collective_key_base, instance_key_start=num_gpus * 100 + CollectiveAllReduceStrategyTestBase.collective_key_base, instance_key_with_id_start=num_gpus * 10000 + CollectiveAllReduceStrategyTestBase.collective_key_base) - distribution._collective_keys = collective_keys - distribution._cross_tower_ops._collective_keys = collective_keys + distribution.extended._collective_keys = collective_keys + distribution.extended._inferred_cross_device_ops._collective_keys = ( + collective_keys) if task_type and task_id is not None: return distribution, 'grpc://' + self._cluster_spec[task_type][ task_id], session_config @@ -93,7 +97,8 @@ class CollectiveAllReduceStrategyTestBase( self.cached_session(config=config, target=master_target) as sess, \ d.scope(): - l = core.Dense(1, use_bias=False, name='gpu_%d' % d._num_gpus_per_worker) + l = core.Dense(1, use_bias=False, + name='gpu_%d' % d.extended._num_gpus_per_worker) def loss_fn(x): y = array_ops.reshape(l(x), []) - constant_op.constant(1.) @@ -127,8 +132,8 @@ class CollectiveAllReduceStrategyTestBase( before_list.append(fetched) with ops.control_dependencies([fetched]): # TODO(yuefengz): support non-Mirrored variable as destinations. - g = d.reduce( - variable_scope.VariableAggregation.SUM, g, destinations=v) + g = d.extended.reduce_to( + reduce_util.ReduceOp.SUM, g, destinations=v) with ops.control_dependencies( d.update(v, update, g, grouped=False)): after_list.append(d.read_var(v)) @@ -136,14 +141,13 @@ class CollectiveAllReduceStrategyTestBase( before_out, after_out = step() - if context.num_gpus() < d._num_gpus_per_worker: + if context.num_gpus() < d.extended._num_gpus_per_worker: return True - sess.run( - variables.global_variables_initializer(), options=self._run_options) + sess.run(variables.global_variables_initializer()) for i in range(10): - b, a = sess.run((before_out, after_out), options=self._run_options) + b, a = sess.run((before_out, after_out)) if i == 0: before, = b after, = a @@ -222,26 +226,54 @@ class CollectiveAllReduceStrategyTestBase( return array_ops.identity(x) x = distribution.call_for_each_replica(model_fn) - reduced_x = distribution.unwrap( - distribution.reduce( - variable_scope.VariableAggregation.MEAN, x, - destinations='/cpu:0'))[0] + reduced_x = distribution.reduce(reduce_util.ReduceOp.MEAN, x) x = distribution.unwrap(x)[0] - sess.run( - variables.global_variables_initializer(), options=self._run_options) + sess.run(variables.global_variables_initializer()) - x_value, reduced_x_value = sess.run([x, reduced_x], - options=self._run_options) + x_value, reduced_x_value = sess.run([x, reduced_x]) self.assertTrue( np.allclose(x_value, reduced_x_value, atol=1e-5), msg=('x_value = %r, reduced_x_value = %r' % (x_value, reduced_x_value))) return np.allclose(x_value, reduced_x_value, atol=1e-5) + def _test_input_fn_iterator(self, task_type, task_id, num_gpus, input_fn, + expected_values): + distribution, master_target, config = self._get_test_object( + task_type, task_id, num_gpus) + devices = distribution.extended.worker_devices + + with ops.Graph().as_default(), \ + self.cached_session(config=config, + target=master_target) as sess: + iterator = distribution.make_input_fn_iterator(input_fn) + sess.run(iterator.initialize()) + + for expected_value in expected_values: + next_element = iterator.get_next() + computed_value = sess.run( + [values.select_device(d, next_element) for d in devices]) + self.assertEqual(expected_value, computed_value) + + with self.assertRaises(errors.OutOfRangeError): + next_element = iterator.get_next() + sess.run([values.select_device(d, next_element) for d in devices]) + + # After re-initializing the iterator, should be able to iterate again. + sess.run(iterator.initialize()) + + for expected_value in expected_values: + next_element = iterator.get_next() + computed_value = sess.run( + [values.select_device(d, next_element) for d in devices]) + self.assertEqual(expected_value, computed_value) + class DistributedCollectiveAllReduceStrategyTest( - CollectiveAllReduceStrategyTestBase, parameterized.TestCase): + CollectiveAllReduceStrategyTestBase, + strategy_test_lib.DistributionTestBase, + parameterized.TestCase): @classmethod def setUpClass(cls): @@ -269,7 +301,7 @@ class DistributedCollectiveAllReduceStrategyTest( combinations.combine(mode=['graph'], num_gpus=[0, 1, 2], required_gpus=1)) def testVariableInitialization(self, num_gpus): if context.num_gpus() < num_gpus: - return + self.skipTest('Not enough GPUs') self._run_between_graph_clients( self._test_variable_initialization, self._cluster_spec, @@ -279,10 +311,56 @@ class DistributedCollectiveAllReduceStrategyTest( combinations.combine(mode=['graph'], num_gpus=[0, 1, 2], required_gpus=1)) def testComplexModel(self, num_gpus): if context.num_gpus() < num_gpus: - return + self.skipTest('Not enough GPUs') self._run_between_graph_clients( self._test_complex_model, self._cluster_spec, num_gpus=num_gpus) + # TODO(yuefengz): Update how we use num_gpus and required_gpus + @combinations.generate( + combinations.combine(mode=['graph'], num_gpus=[0, 1, 2], required_gpus=1)) + def testMakeInputFnIterator(self, num_gpus): + if context.num_gpus() < num_gpus: + self.skipTest('Not enough GPUs') + dataset_fn = lambda: dataset_ops.Dataset.range(100) + # We use CPU as the device when num_gpus = 0 + devices_per_worker = max(1, num_gpus) + expected_values = [[i+j for j in range(devices_per_worker)] + for i in range(0, 100, devices_per_worker)] + + input_fn = self._input_fn_to_test_input_context( + dataset_fn, + expected_num_replicas_in_sync=3*devices_per_worker, + expected_num_input_pipelines=3, + expected_input_pipeline_id=1) # because task_id = 1 + self._test_input_fn_iterator('worker', 1, num_gpus, + input_fn, expected_values) + + def testUpdateConfigProto(self): + distribution = collective_all_reduce_strategy.CollectiveAllReduceStrategy( + num_gpus_per_worker=2) + distribution.configure( + cluster_spec=self._cluster_spec, task_type='worker', task_id=1) + + config_proto = config_pb2.ConfigProto(device_filters=['to_be_overridden']) + rewrite_options = config_proto.graph_options.rewrite_options + rewrite_options.scoped_allocator_opts.enable_op.append('to_be_removed') + + new_config = distribution.update_config_proto(config_proto) + + # Verify group leader + self.assertEqual('/job:worker/replica:0/task:0', + new_config.experimental.collective_group_leader) + + # Verify device filters. + self.assertEqual(['/job:worker/task:1'], new_config.device_filters) + + # Verify rewrite options. + new_rewrite_options = new_config.graph_options.rewrite_options + self.assertEqual(rewriter_config_pb2.RewriterConfig.ON, + new_rewrite_options.scoped_allocator_optimization) + self.assertEqual(['CollectiveReduce'], + new_rewrite_options.scoped_allocator_opts.enable_op) + class DistributedCollectiveAllReduceStrategyTestWithChief( CollectiveAllReduceStrategyTestBase, parameterized.TestCase): @@ -293,10 +371,6 @@ class DistributedCollectiveAllReduceStrategyTestWithChief( cls._cluster_spec = multi_worker_test_base.create_in_process_cluster( num_workers=3, num_ps=0, has_chief=True) - def setUp(self): - super(DistributedCollectiveAllReduceStrategyTestWithChief, self).setUp() - self._run_options.experimental.collective_graph_key = 7 - @combinations.generate( combinations.combine(mode=['graph'], num_gpus=[0, 1, 2], required_gpus=1)) def testMinimizeLossGraph(self, num_gpus): @@ -323,20 +397,36 @@ class DistributedCollectiveAllReduceStrategyTestWithChief( class LocalCollectiveAllReduceStrategy(CollectiveAllReduceStrategyTestBase, + strategy_test_lib.DistributionTestBase, parameterized.TestCase): def testMinimizeLossGraph(self, num_gpus=2): # Collective ops doesn't support strategy with one device. if context.num_gpus() < num_gpus: - return + self.skipTest('Not enough GPUs') self._test_minimize_loss_graph(None, None, num_gpus) def testComplexModel(self, num_gpus=2): # Collective ops doesn't support strategy with one device. if context.num_gpus() < num_gpus: - return + self.skipTest('Not enough GPUs') self._test_complex_model(None, None, num_gpus) + def testMakeInputFnIterator(self, num_gpus=2): + # Collective ops doesn't support strategy with one device. + if context.num_gpus() < num_gpus: + self.skipTest('Not enough GPUs') + dataset_fn = lambda: dataset_ops.Dataset.range(10) + expected_values = [[i, i+1] for i in range(0, 10, 2)] + + input_fn = self._input_fn_to_test_input_context( + dataset_fn, + expected_num_replicas_in_sync=num_gpus, + expected_num_input_pipelines=1, + expected_input_pipeline_id=0) + self._test_input_fn_iterator(None, None, num_gpus, + input_fn, expected_values) + if __name__ == '__main__': test.main() diff --git a/tensorflow/contrib/distribute/python/combinations.py b/tensorflow/contrib/distribute/python/combinations.py index a513716540..365ce5cdec 100644 --- a/tensorflow/contrib/distribute/python/combinations.py +++ b/tensorflow/contrib/distribute/python/combinations.py @@ -53,11 +53,11 @@ from tensorflow.contrib.distribute.python import tpu_strategy as tpu_lib from tensorflow.contrib.optimizer_v2 import adagrad as adagrad_v2 from tensorflow.contrib.optimizer_v2 import adam as adam_v2 from tensorflow.contrib.optimizer_v2 import gradient_descent as gradient_descent_v2 +from tensorflow.python.distribute import distribution_strategy_context from tensorflow.python.eager import context from tensorflow.python.framework import ops from tensorflow.python.training import adagrad from tensorflow.python.training import adam -from tensorflow.python.training import distribution_strategy_context from tensorflow.python.training import gradient_descent from tensorflow.python.training import rmsprop from tensorflow.python.util import tf_inspect @@ -168,6 +168,8 @@ def _augment_with_special_arguments(test_method): if GPU_TEST: self.skipTest("Test that doesn't require GPUs.") elif context.num_gpus() < required_gpus: + # TODO(priyag): Consider allowing tests in graph mode using soft + # placement. self.skipTest( "{} GPUs are not available for this test. {} GPUs are available". format(required_gpus, context.num_gpus())) @@ -190,7 +192,7 @@ def _augment_with_special_arguments(test_method): kwargs_to_pass[arg] = kwargs[arg] if mode == "eager": - with ops.Graph().as_default(), context.eager_mode(): + with context.eager_mode(): if distribution: kwargs_to_pass["distribution"] = distribution.strategy test_method(**kwargs_to_pass) @@ -335,6 +337,13 @@ tpu_strategy_one_step = NamedDistribution( "TPUOneStep", lambda: tpu_lib.TPUStrategy( TPUClusterResolver(""), steps_per_run=1), required_tpu=True) +mirrored_strategy_with_one_cpu = NamedDistribution( + "Mirrored1CPU", + lambda: mirrored_lib.MirroredStrategy(["/cpu:0"])) +mirrored_strategy_with_one_gpu = NamedDistribution( + "Mirrored1GPU", + lambda: mirrored_lib.MirroredStrategy(["/gpu:0"]), + required_gpus=1) mirrored_strategy_with_gpu_and_cpu = NamedDistribution( "MirroredCPUAndGPU", lambda: mirrored_lib.MirroredStrategy(["/gpu:0", "/cpu:0"]), @@ -343,6 +352,21 @@ mirrored_strategy_with_two_gpus = NamedDistribution( "Mirrored2GPUs", lambda: mirrored_lib.MirroredStrategy(["/gpu:0", "/gpu:1"]), required_gpus=2) +core_mirrored_strategy_with_one_cpu = NamedDistribution( + "CoreMirrored1CPU", + lambda: mirrored_lib.CoreMirroredStrategy(["/cpu:0"])) +core_mirrored_strategy_with_one_gpu = NamedDistribution( + "CoreMirrored1GPU", + lambda: mirrored_lib.CoreMirroredStrategy(["/gpu:0"]), + required_gpus=1) +core_mirrored_strategy_with_gpu_and_cpu = NamedDistribution( + "CoreMirroredCPUAndGPU", + lambda: mirrored_lib.CoreMirroredStrategy(["/gpu:0", "/cpu:0"]), + required_gpus=1) +core_mirrored_strategy_with_two_gpus = NamedDistribution( + "CoreMirrored2GPUs", + lambda: mirrored_lib.CoreMirroredStrategy(["/gpu:0", "/gpu:1"]), + required_gpus=2) gradient_descent_optimizer_v1_fn = NamedObject( @@ -373,8 +397,11 @@ def distributions_and_v1_optimizers(): """A common set of combination with DistributionStrategies and Optimizers.""" return combine( distribution=[ - one_device_strategy, mirrored_strategy_with_gpu_and_cpu, - mirrored_strategy_with_two_gpus + one_device_strategy, + mirrored_strategy_with_gpu_and_cpu, + mirrored_strategy_with_two_gpus, + core_mirrored_strategy_with_gpu_and_cpu, + core_mirrored_strategy_with_two_gpus, ], optimizer_fn=optimizers_v1) @@ -383,7 +410,10 @@ def distributions_and_v2_optimizers(): """DistributionStrategies and V2 Optimizers.""" return combine( distribution=[ - one_device_strategy, mirrored_strategy_with_gpu_and_cpu, - mirrored_strategy_with_two_gpus + one_device_strategy, + mirrored_strategy_with_gpu_and_cpu, + mirrored_strategy_with_two_gpus, + core_mirrored_strategy_with_gpu_and_cpu, + core_mirrored_strategy_with_two_gpus, ], optimizer_fn=optimizers_v2) diff --git a/tensorflow/contrib/distribute/python/cross_tower_ops_test.py b/tensorflow/contrib/distribute/python/cross_device_ops_test.py similarity index 79% rename from tensorflow/contrib/distribute/python/cross_tower_ops_test.py rename to tensorflow/contrib/distribute/python/cross_device_ops_test.py index 3e274ba67c..d6e9521c1c 100644 --- a/tensorflow/contrib/distribute/python/cross_tower_ops_test.py +++ b/tensorflow/contrib/distribute/python/cross_device_ops_test.py @@ -24,24 +24,24 @@ from absl.testing import parameterized import numpy as np from tensorflow.contrib.distribute.python import combinations -from tensorflow.contrib.distribute.python import cross_tower_ops as cross_tower_ops_lib -from tensorflow.contrib.distribute.python import cross_tower_utils from tensorflow.contrib.distribute.python import mirrored_strategy from tensorflow.contrib.distribute.python import multi_worker_test_base -from tensorflow.contrib.distribute.python import values as value_lib from tensorflow.core.protobuf import config_pb2 +from tensorflow.python.distribute import cross_device_ops as cross_device_ops_lib +from tensorflow.python.distribute import cross_device_utils +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import reduce_util +from tensorflow.python.distribute import values as value_lib from tensorflow.python.eager import context from tensorflow.python.eager import test from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops -from tensorflow.python.ops import variable_scope as vs -from tensorflow.python.training import device_util def _make_per_replica(values, devices, regroup=False): - devices = cross_tower_ops_lib.get_devices_from(devices) + devices = cross_device_ops_lib.get_devices_from(devices) assert len(values) == len(devices) # We simulate the result of regroup called on PerReplica which strips the @@ -66,7 +66,7 @@ def _fake_mirrored(value, devices): All components of the returned Mirrored have the same objects, which is not true in reality. """ - devices = cross_tower_ops_lib.get_devices_from(devices) + devices = cross_device_ops_lib.get_devices_from(devices) return value_lib.Mirrored( {d: v for d, v in zip(devices, [value] * len(devices))}) @@ -118,8 +118,8 @@ class CrossDeviceOpsTestBase(test.TestCase, parameterized.TestCase): self.assertEqual( sess.run(list(left._index.values())), list(right._index.values())) - def _testReductionAndBroadcast(self, cross_tower_ops, distribution): - devices = distribution.worker_devices + def _testReductionAndBroadcast(self, cross_device_ops, distribution): + devices = distribution.extended.worker_devices values = [constant_op.constant(float(d)) for d in range(len(devices))] per_replica = _make_per_replica(values, devices) @@ -132,35 +132,33 @@ class CrossDeviceOpsTestBase(test.TestCase, parameterized.TestCase): destination_mirrored = _fake_mirrored(1., devices) destination_different = _fake_mirrored(1., _cpu_device) destination_str = _cpu_device - destination_list = devices all_destinations = [ destination_mirrored, destination_different, destination_str, - destination_list ] # test reduce() for destinations in all_destinations: self._assert_values_equal( - cross_tower_ops.reduce( - vs.VariableAggregation.MEAN, + cross_device_ops.reduce( + reduce_util.ReduceOp.MEAN, per_replica, destinations=destinations), _fake_mirrored(mean, destinations)) self._assert_values_equal( - cross_tower_ops.reduce( - vs.VariableAggregation.MEAN, + cross_device_ops.reduce( + reduce_util.ReduceOp.MEAN, per_replica_2, destinations=destinations), _fake_mirrored(mean_2, destinations)) self._assert_values_equal( - cross_tower_ops.reduce( - vs.VariableAggregation.SUM, per_replica, + cross_device_ops.reduce( + reduce_util.ReduceOp.SUM, per_replica, destinations=destinations), _fake_mirrored(mean * len(devices), destinations)) self._assert_values_equal( - cross_tower_ops.reduce( - vs.VariableAggregation.SUM, + cross_device_ops.reduce( + reduce_util.ReduceOp.SUM, per_replica_2, destinations=destinations), _fake_mirrored(mean_2 * len(devices), destinations)) @@ -168,16 +166,16 @@ class CrossDeviceOpsTestBase(test.TestCase, parameterized.TestCase): # test batch_reduce() for d1, d2 in itertools.product(all_destinations, all_destinations): self._assert_values_equal( - cross_tower_ops.batch_reduce( - vs.VariableAggregation.MEAN, + cross_device_ops.batch_reduce( + reduce_util.ReduceOp.MEAN, [(per_replica, d1), (per_replica_2, d2)]), [ _fake_mirrored(mean, d1), _fake_mirrored(mean_2, d2) ]) self._assert_values_equal( - cross_tower_ops.batch_reduce( - vs.VariableAggregation.SUM, + cross_device_ops.batch_reduce( + reduce_util.ReduceOp.SUM, [(per_replica, d1), (per_replica_2, d2)]), [ _fake_mirrored(mean * len(devices), d1), @@ -187,7 +185,7 @@ class CrossDeviceOpsTestBase(test.TestCase, parameterized.TestCase): # test broadcast() for destinations in all_destinations: self._assert_values_equal( - cross_tower_ops.broadcast(constant_op.constant(1.), destinations), + cross_device_ops.broadcast(constant_op.constant(1.), destinations), _fake_mirrored(1., destinations)) @@ -196,62 +194,65 @@ class SingleWorkerCrossDeviceOpsTest(CrossDeviceOpsTestBase): # combinations module so that we can pass in devices instead of a distribution # strategy. reduction_to_one_combinations = combinations.combine( - cross_tower_ops=[ + cross_device_ops=[ combinations.NamedObject( "DefaultReductionToOneDeviceCrossDeviceOps", - cross_tower_ops_lib.ReductionToOneDeviceCrossDeviceOps()), + cross_device_ops_lib.ReductionToOneDeviceCrossDeviceOps()), combinations.NamedObject( "ReductionToCPUDeviceCrossDeviceOps", - cross_tower_ops_lib.ReductionToOneDeviceCrossDeviceOps( + cross_device_ops_lib.ReductionToOneDeviceCrossDeviceOps( reduce_to_device=_cpu_device)), combinations.NamedObject( "AccumulateNCrossDeviceOp", - cross_tower_ops_lib.ReductionToOneDeviceCrossDeviceOps( + cross_device_ops_lib.ReductionToOneDeviceCrossDeviceOps( accumulation_fn=math_ops.accumulate_n)), ], distribution=[ combinations.one_device_strategy, combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus ], mode=["graph", "eager"]) allreduce_combinations = combinations.combine( - cross_tower_ops=[ + cross_device_ops=[ combinations.NamedObject( "AllReduce", - cross_tower_ops_lib.AllReduceCrossDeviceOps("nccl", 1, 0, 0)), + cross_device_ops_lib.AllReduceCrossDeviceOps("nccl", 1, 0, 0)), combinations.NamedObject( "HierarchicalCopy", - cross_tower_ops_lib.AllReduceCrossDeviceOps( + cross_device_ops_lib.AllReduceCrossDeviceOps( "hierarchical_copy", 8, 0, 0)), combinations.NamedObject( "AllReduceNoGradientRepacking", - cross_tower_ops_lib.AllReduceCrossDeviceOps("nccl", 0, 0, 0)), + cross_device_ops_lib.AllReduceCrossDeviceOps("nccl", 0, 0, 0)), combinations.NamedObject( "HierarchicalCopyAggregateSmallTensors", - cross_tower_ops_lib.AllReduceCrossDeviceOps( + cross_device_ops_lib.AllReduceCrossDeviceOps( "hierarchical_copy", 0, 100, 10)) ], - distribution=[combinations.mirrored_strategy_with_two_gpus], + distribution=[combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], mode=["graph", "eager"]) @combinations.generate(reduction_to_one_combinations + allreduce_combinations) - def testReductionAndBroadcast(self, cross_tower_ops, distribution): + def testReductionAndBroadcast(self, cross_device_ops, distribution): with distribution.scope(): - self._testReductionAndBroadcast(cross_tower_ops, distribution) + self._testReductionAndBroadcast(cross_device_ops, distribution) def testChooseAlgorithm(self): device_links = [[1, 2, 3, 4], [0, 2, 3, 5], [0, 1, 3, 6], [0, 1, 2, 7], [0, 5, 6, 7], [1, 4, 6, 7], [2, 4, 5, 7], [3, 4, 5, 6]] - result = cross_tower_ops_lib._choose_all_reduce_algorithm(device_links) - self.assertIsInstance(result, cross_tower_ops_lib.AllReduceCrossDeviceOps) + result = cross_device_ops_lib._choose_all_reduce_algorithm(device_links) + self.assertIsInstance(result, cross_device_ops_lib.AllReduceCrossDeviceOps) self.assertEqual(result._all_reduce_alg, "hierarchical_copy") self.assertEqual(result._num_packs, 8) # if there are only 4 devices device_links = [[1, 2, 3, 4], [0, 2, 3, 5], [0, 1, 3, 6], [0, 1, 2, 7]] - result = cross_tower_ops_lib._choose_all_reduce_algorithm(device_links) - self.assertIsInstance(result, cross_tower_ops_lib.AllReduceCrossDeviceOps) + result = cross_device_ops_lib._choose_all_reduce_algorithm(device_links) + self.assertIsInstance(result, cross_device_ops_lib.AllReduceCrossDeviceOps) self.assertEqual(result._all_reduce_alg, "nccl") self.assertEqual(result._num_packs, 1) @@ -259,16 +260,16 @@ class SingleWorkerCrossDeviceOpsTest(CrossDeviceOpsTestBase): device_links = [[0, 1, 2, 3, 4], [0, 1, 2, 3, 5], [0, 1, 2, 3, 6], [0, 1, 2, 3, 7], [0, 4, 5, 6, 7], [1, 4, 5, 6, 7], [2, 4, 5, 6, 7], [3, 4, 5, 6, 7]] - result = cross_tower_ops_lib._choose_all_reduce_algorithm(device_links) - self.assertIsInstance(result, cross_tower_ops_lib.AllReduceCrossDeviceOps) + result = cross_device_ops_lib._choose_all_reduce_algorithm(device_links) + self.assertIsInstance(result, cross_device_ops_lib.AllReduceCrossDeviceOps) self.assertEqual(result._all_reduce_alg, "hierarchical_copy") self.assertEqual(result._num_packs, 8) # if not dgx1-like links device_links = [[0, 2, 3, 5], [0, 1, 3, 6], [0, 1, 2, 7], [0, 5, 6, 7], [1, 4, 6, 7], [2, 4, 5, 7], [3, 4, 5, 6], [1, 2, 3, 4]] - result = cross_tower_ops_lib._choose_all_reduce_algorithm(device_links) - self.assertIsInstance(result, cross_tower_ops_lib.AllReduceCrossDeviceOps) + result = cross_device_ops_lib._choose_all_reduce_algorithm(device_links) + self.assertIsInstance(result, cross_device_ops_lib.AllReduceCrossDeviceOps) self.assertEqual(result._all_reduce_alg, "nccl") self.assertEqual(result._num_packs, 1) @@ -280,8 +281,8 @@ class SingleWorkerCrossDeviceOpsTest(CrossDeviceOpsTestBase): t0 = _make_indexed_slices([[1., 2.]], [1], [5, 2], devices[0]) t1 = _make_indexed_slices([[3., 4.], [5., 6.]], [1, 3], [5, 2], devices[1]) per_replica = value_lib.PerReplica({devices[0]: t0, devices[1]: t1}) - result = cross_tower_ops_lib._simple_reduce( - per_replica, devices[0], math_ops.add_n, vs.VariableAggregation.SUM) + result = cross_device_ops_lib._simple_reduce( + per_replica, devices[0], math_ops.add_n, reduce_util.ReduceOp.SUM) # Test that the result is semantically equal to both the concatenated # IndexedSlices with and without duplicate indices. @@ -294,19 +295,19 @@ class SingleWorkerCrossDeviceOpsTest(CrossDeviceOpsTestBase): @combinations.generate( combinations.combine( - cross_tower_ops_instance=[ + cross_device_ops_instance=[ combinations.NamedObject( "ReductionToOneDeviceCrossDeviceOps", - cross_tower_ops_lib.ReductionToOneDeviceCrossDeviceOps()), + cross_device_ops_lib.ReductionToOneDeviceCrossDeviceOps()), combinations.NamedObject( "AllReduceCrossDeviceOps", - cross_tower_ops_lib.AllReduceCrossDeviceOps()) + cross_device_ops_lib.AllReduceCrossDeviceOps()) ], - aggregation=[vs.VariableAggregation.SUM, vs.VariableAggregation.MEAN], + reduce_op=[reduce_util.ReduceOp.SUM, reduce_util.ReduceOp.MEAN], batch_reduce=[True, False], mode=["graph", "eager"], required_gpus=1)) - def testIndexedSlicesAllReduce(self, cross_tower_ops_instance, aggregation, + def testIndexedSlicesAllReduce(self, cross_device_ops_instance, reduce_op, batch_reduce): devices = ["/cpu:0", "/gpu:0"] dense_shape = [5, 2] @@ -316,20 +317,20 @@ class SingleWorkerCrossDeviceOpsTest(CrossDeviceOpsTestBase): per_replica = value_lib.PerReplica({devices[0]: t0, devices[1]: t1}) if batch_reduce: - result = cross_tower_ops_instance.batch_reduce( - aggregation, [(per_replica, devices)]) + result = cross_device_ops_instance.batch_reduce( + reduce_op, [(per_replica, per_replica)]) else: - result = cross_tower_ops_instance.reduce( - aggregation, per_replica, devices) + result = cross_device_ops_instance.reduce( + reduce_op, per_replica, per_replica) total_indices_with_dups = [1, 1, 3] total_indices_without_dups = [1, 3] - if aggregation == vs.VariableAggregation.SUM: + if reduce_op == reduce_util.ReduceOp.SUM: total_values_with_dups = [[1., 2.], [3., 4.], [5., 6.]] total_values_without_dups = [[4., 6.], [5., 6.]] else: - assert aggregation == vs.VariableAggregation.MEAN + assert reduce_op == reduce_util.ReduceOp.MEAN total_values_with_dups = [[0.5, 1.], [1.5, 2.], [2.5, 3.]] total_values_without_dups = [[2., 3.], [2.5, 3.]] @@ -356,49 +357,63 @@ class MultiWorkerCrossDeviceOpsTest(multi_worker_test_base.MultiWorkerTestBase, "/job:worker/replica:0/task:0", "/job:worker/replica:0/task:1" ] multi_worker_allreduce_combinations = combinations.combine( - cross_tower_ops=[ + cross_device_ops=[ combinations.NamedObject( "MultiWorkerAllReduce", - cross_tower_ops_lib.MultiWorkerAllReduce( + cross_device_ops_lib.MultiWorkerAllReduce( worker_devices, 2, ("pscpu/pscpu", 2, -1), 0, 0, 0)), combinations.NamedObject( "MultiWorkerAllReducePack", - cross_tower_ops_lib.MultiWorkerAllReduce( + cross_device_ops_lib.MultiWorkerAllReduce( worker_devices, 2, ("pscpu/pscpu", 2, -1), 1, 0, 0)), combinations.NamedObject( "MultiWorkerAllReduceAggregation", - cross_tower_ops_lib.MultiWorkerAllReduce( + cross_device_ops_lib.MultiWorkerAllReduce( worker_devices, 2, ("pscpu/pscpu", 2, -1), 0, 100, 10)), combinations.NamedObject( "MultiWorkerAllReduceMultipleSpecs", - cross_tower_ops_lib.MultiWorkerAllReduce( + cross_device_ops_lib.MultiWorkerAllReduce( worker_devices, 2, [("pscpu/pscpu", 2, 100), ("xring", 2, -1)], 0, 0, 0)), ], distribution=[ combinations.NamedDistribution( "MirroredCPU", - lambda: mirrored_strategy.MirroredStrategy(num_gpus=0), + lambda: mirrored_strategy.MirroredStrategy(num_gpus_per_worker=0), required_gpus=0), combinations.NamedDistribution( "Mirrored1GPU", - lambda: mirrored_strategy.MirroredStrategy(num_gpus=1), + lambda: mirrored_strategy.MirroredStrategy(num_gpus_per_worker=1), required_gpus=1), combinations.NamedDistribution( "Mirrored2GPUs", - lambda: mirrored_strategy.MirroredStrategy(num_gpus=2), + lambda: mirrored_strategy.MirroredStrategy(num_gpus_per_worker=2), + required_gpus=2), + # pylint: disable=g-long-lambda + combinations.NamedDistribution( + "CoreMirroredCPU", + lambda: mirrored_strategy.CoreMirroredStrategy(["/device:CPU:0"]), + required_gpus=0), + combinations.NamedDistribution( + "CoreMirrored1GPU", + lambda: mirrored_strategy.CoreMirroredStrategy(["/device:GPU:0"]), + required_gpus=1), + combinations.NamedDistribution( + "CoreMirrored2GPUs", + lambda: mirrored_strategy.CoreMirroredStrategy( + ["/device:GPU:0", "/device:GPU:1"]), required_gpus=2), ], mode=["graph"]) @combinations.generate(multi_worker_allreduce_combinations) - def testReductionAndBroadcast(self, cross_tower_ops, distribution): + def testReductionAndBroadcast(self, cross_device_ops, distribution): distribution.configure(cluster_spec={ "worker": ["/job:worker/replica:0/task:0", "/job:worker/replica:0/task:1"] }) with distribution.scope(): - self._testReductionAndBroadcast(cross_tower_ops, distribution) + self._testReductionAndBroadcast(cross_device_ops, distribution) class MultiWorkerCollectiveAllReduceTest( @@ -419,7 +434,7 @@ class MultiWorkerCollectiveAllReduceTest( MultiWorkerCollectiveAllReduceTest.collective_key_base += 100000 def _get_test_objects(self, task_type, task_id, num_gpus=0, local_mode=False): - collective_keys = cross_tower_utils.CollectiveKeys( + collective_keys = cross_device_utils.CollectiveKeys( group_key_start=10 * num_gpus + MultiWorkerCollectiveAllReduceTest.collective_key_base, instance_key_start=num_gpus * 100 + @@ -427,7 +442,7 @@ class MultiWorkerCollectiveAllReduceTest( instance_key_with_id_start=num_gpus * 10000 + MultiWorkerCollectiveAllReduceTest.collective_key_base) if local_mode: - collective_all_reduce_ops = cross_tower_ops_lib.CollectiveAllReduce( + collective_all_reduce_ops = cross_device_ops_lib.CollectiveAllReduce( 1, num_gpus, collective_keys=collective_keys) if num_gpus: devices = ["/device:GPU:%d" % i for i in range(num_gpus)] @@ -435,7 +450,7 @@ class MultiWorkerCollectiveAllReduceTest( devices = ["/device:CPU:0"] return collective_all_reduce_ops, devices, "" else: - collective_all_reduce_ops = cross_tower_ops_lib.CollectiveAllReduce( + collective_all_reduce_ops = cross_device_ops_lib.CollectiveAllReduce( 3, num_gpus, collective_keys=collective_keys) if num_gpus: devices = [ @@ -491,37 +506,35 @@ class MultiWorkerCollectiveAllReduceTest( destination_mirrored = _fake_mirrored(1., devices) destination_different = _fake_mirrored(1., _cpu_device) destination_str = _cpu_device - destination_list = devices all_destinations = [ - destination_different, destination_mirrored, destination_str, - destination_list + destination_different, destination_mirrored, destination_str ] # test reduce() for destinations in all_destinations: self._assert_values_equal( collective_all_reduce.reduce( - vs.VariableAggregation.MEAN, + reduce_util.ReduceOp.MEAN, per_replica, destinations=destinations), _fake_mirrored(mean, destinations), sess) self._assert_values_equal( collective_all_reduce.reduce( - vs.VariableAggregation.MEAN, + reduce_util.ReduceOp.MEAN, per_replica_2, destinations=destinations), _fake_mirrored(mean_2, destinations), sess) self._assert_values_equal( collective_all_reduce.reduce( - vs.VariableAggregation.SUM, + reduce_util.ReduceOp.SUM, per_replica, destinations=destinations), _fake_mirrored(mean * len(devices) * num_workers, destinations), sess) self._assert_values_equal( collective_all_reduce.reduce( - vs.VariableAggregation.SUM, + reduce_util.ReduceOp.SUM, per_replica_2, destinations=destinations), _fake_mirrored(mean_2 * len(devices) * num_workers, destinations), @@ -530,7 +543,7 @@ class MultiWorkerCollectiveAllReduceTest( # test batch_reduce() for d1, d2 in itertools.product(all_destinations, all_destinations): self._assert_values_equal( - collective_all_reduce.batch_reduce(vs.VariableAggregation.MEAN, + collective_all_reduce.batch_reduce(reduce_util.ReduceOp.MEAN, [(per_replica, d1), (per_replica_2, d2)]), [ @@ -538,7 +551,7 @@ class MultiWorkerCollectiveAllReduceTest( _fake_mirrored(mean_2, d2) ], sess) self._assert_values_equal( - collective_all_reduce.batch_reduce(vs.VariableAggregation.SUM, + collective_all_reduce.batch_reduce(reduce_util.ReduceOp.SUM, [(per_replica, d1), (per_replica_2, d2)]), [ diff --git a/tensorflow/contrib/distribute/python/cross_tower_utils_test.py b/tensorflow/contrib/distribute/python/cross_device_utils_test.py similarity index 83% rename from tensorflow/contrib/distribute/python/cross_tower_utils_test.py rename to tensorflow/contrib/distribute/python/cross_device_utils_test.py index e46240abbf..2303a31677 100644 --- a/tensorflow/contrib/distribute/python/cross_tower_utils_test.py +++ b/tensorflow/contrib/distribute/python/cross_device_utils_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for cross_tower_utils.""" +"""Tests for cross_device_utils.""" from __future__ import absolute_import from __future__ import division @@ -21,14 +21,14 @@ from __future__ import print_function from absl.testing import parameterized from tensorflow.contrib.distribute.python import combinations -from tensorflow.contrib.distribute.python import cross_tower_utils -from tensorflow.contrib.distribute.python import values as value_lib +from tensorflow.python.distribute import cross_device_utils +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import values as value_lib from tensorflow.python.eager import test from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops -from tensorflow.python.training import device_util class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): @@ -43,7 +43,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): t0 = constant_op.constant([[1., 2.], [0, 0], [3., 4.]]) t1 = constant_op.constant([[0., 0.], [5, 6], [7., 8.]]) total = constant_op.constant([[1., 2.], [5, 6], [10., 12.]]) - result = cross_tower_utils.aggregate_tensors_or_indexed_slices([t0, t1]) + result = cross_device_utils.aggregate_tensors_or_indexed_slices([t0, t1]) self._assert_values_equal(total, result) @test_util.run_in_graph_and_eager_modes @@ -53,7 +53,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): t1 = math_ops._as_indexed_slices( constant_op.constant([[0., 0.], [5, 6], [7., 8.]])) total = constant_op.constant([[1., 2.], [5, 6], [10., 12.]]) - result = cross_tower_utils.aggregate_tensors_or_indexed_slices([t0, t1]) + result = cross_device_utils.aggregate_tensors_or_indexed_slices([t0, t1]) self.assertIsInstance(result, ops.IndexedSlices) self._assert_values_equal(total, result) @@ -62,7 +62,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): t = constant_op.constant([[1., 2.], [0, 0], [3., 4.]]) n = 2 expected = constant_op.constant([[0.5, 1.], [0, 0], [1.5, 2.]]) - result = cross_tower_utils.divide_by_n_tensors_or_indexed_slices(t, n) + result = cross_device_utils.divide_by_n_tensors_or_indexed_slices(t, n) self._assert_values_equal(expected, result) @test_util.run_in_graph_and_eager_modes @@ -71,7 +71,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): constant_op.constant([[1., 2.], [0, 0], [3., 4.]])) n = 2 expected = constant_op.constant([[0.5, 1.], [0, 0], [1.5, 2.]]) - result = cross_tower_utils.divide_by_n_tensors_or_indexed_slices(t, n) + result = cross_device_utils.divide_by_n_tensors_or_indexed_slices(t, n) self.assertIsInstance(result, ops.IndexedSlices) self._assert_values_equal(expected, result) @@ -79,7 +79,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): def testIsIndexedSlices(self): t = math_ops._as_indexed_slices( constant_op.constant([[1., 2.], [0, 0], [3., 4.]])) - self.assertTrue(cross_tower_utils.contains_indexed_slices(t)) + self.assertTrue(cross_device_utils.contains_indexed_slices(t)) @test_util.run_in_graph_and_eager_modes def testContainsIndexedSlices_List(self): @@ -87,7 +87,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): constant_op.constant([[1., 2.], [0, 0], [3., 4.]])) t1 = math_ops._as_indexed_slices( constant_op.constant([[0., 0.], [5, 6], [7., 8.]])) - self.assertTrue(cross_tower_utils.contains_indexed_slices([t0, t1])) + self.assertTrue(cross_device_utils.contains_indexed_slices([t0, t1])) @test_util.run_in_graph_and_eager_modes def testContainsIndexedSlices_Tuple(self): @@ -95,7 +95,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): constant_op.constant([[1., 2.], [0, 0], [3., 4.]])) t1 = math_ops._as_indexed_slices( constant_op.constant([[0., 0.], [5, 6], [7., 8.]])) - self.assertTrue(cross_tower_utils.contains_indexed_slices((t0, t1))) + self.assertTrue(cross_device_utils.contains_indexed_slices((t0, t1))) @test_util.run_in_graph_and_eager_modes def testContainsIndexedSlices_PerReplica(self): @@ -104,7 +104,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): t1 = math_ops._as_indexed_slices( constant_op.constant([[0., 0.], [5, 6], [7., 8.]])) per_replica = value_lib.PerReplica({"/gpu:0": t0, "/cpu:0": t1}) - self.assertTrue(cross_tower_utils.contains_indexed_slices(per_replica)) + self.assertTrue(cross_device_utils.contains_indexed_slices(per_replica)) @combinations.generate(combinations.combine( mode=["graph", "eager"], @@ -113,7 +113,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): with ops.device("/cpu:0"): t = constant_op.constant([[1., 2.], [0, 0], [3., 4.]]) destination = "/gpu:0" - result = cross_tower_utils.copy_tensor_or_indexed_slices_to_device( + result = cross_device_utils.copy_tensor_or_indexed_slices_to_device( t, destination) self._assert_values_equal(t, result) @@ -128,7 +128,7 @@ class IndexedSlicesUtilsTest(test.TestCase, parameterized.TestCase): t = math_ops._as_indexed_slices( constant_op.constant([[1., 2.], [0, 0], [3., 4.]])) destination = "/gpu:0" - result = cross_tower_utils.copy_tensor_or_indexed_slices_to_device( + result = cross_device_utils.copy_tensor_or_indexed_slices_to_device( t, destination) self.assertIsInstance(result, ops.IndexedSlices) diff --git a/tensorflow/contrib/distribute/python/estimator_integration_test.py b/tensorflow/contrib/distribute/python/estimator_integration_test.py index a1355c0b09..e17085628b 100644 --- a/tensorflow/contrib/distribute/python/estimator_integration_test.py +++ b/tensorflow/contrib/distribute/python/estimator_integration_test.py @@ -34,7 +34,7 @@ from tensorflow.python.estimator.canned import dnn_linear_combined from tensorflow.python.estimator.canned import prediction_keys from tensorflow.python.estimator.export import export from tensorflow.python.estimator.inputs import numpy_io -from tensorflow.python.feature_column import feature_column +from tensorflow.python.feature_column import feature_column_lib as feature_column from tensorflow.python.framework import ops from tensorflow.python.platform import gfile from tensorflow.python.summary.writer import writer_cache @@ -63,7 +63,9 @@ class DNNLinearCombinedClassifierIntegrationTest(test.TestCase, distribution=[ combinations.one_device_strategy, combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus ], use_train_and_evaluate=[True, False])) def test_complete_flow_with_mode(self, distribution, use_train_and_evaluate): @@ -75,12 +77,12 @@ class DNNLinearCombinedClassifierIntegrationTest(test.TestCase, train_input_fn = self.dataset_input_fn( x={'x': data}, y=data, - batch_size=batch_size // len(distribution.worker_devices), + batch_size=batch_size // distribution.num_replicas_in_sync, shuffle=True) eval_input_fn = self.dataset_input_fn( x={'x': data}, y=data, - batch_size=batch_size // len(distribution.worker_devices), + batch_size=batch_size // distribution.num_replicas_in_sync, shuffle=False) predict_input_fn = numpy_io.numpy_input_fn( x={'x': data}, batch_size=batch_size, shuffle=False) diff --git a/tensorflow/contrib/distribute/python/estimator_training_test.py b/tensorflow/contrib/distribute/python/estimator_training_test.py index 8f82b4c92a..b369a7fefe 100644 --- a/tensorflow/contrib/distribute/python/estimator_training_test.py +++ b/tensorflow/contrib/distribute/python/estimator_training_test.py @@ -24,7 +24,6 @@ import json import os import sys import tempfile -import threading from absl.testing import parameterized import numpy as np @@ -45,11 +44,13 @@ from tensorflow.python.estimator import training as estimator_training from tensorflow.python.estimator.canned import dnn_linear_combined from tensorflow.python.estimator.canned import prediction_keys from tensorflow.python.estimator.export import export as export_lib -from tensorflow.python.feature_column import feature_column +from tensorflow.python.feature_column import feature_column_lib as feature_column from tensorflow.python.platform import gfile from tensorflow.python.platform import test from tensorflow.python.summary import summary_iterator from tensorflow.python.summary.writer import writer_cache +from tensorflow.python.training import session_manager + BATCH_SIZE = 10 LABEL_DIMENSION = 2 @@ -68,57 +69,19 @@ PS = dc._TaskType.PS original_run_std_server = dc._run_std_server -class MockOsEnv(dict): - - def __init__(self, *args): - self._thread_local = threading.local() - super(MockOsEnv, self).__init__(*args) - - def get(self, key, default): - if not hasattr(self._thread_local, "dict"): - self._thread_local.dict = dict() - if key == "TF_CONFIG": - return dict.get(self._thread_local.dict, key, default) - else: - return dict.get(self, key, default) - - def __getitem__(self, key): - if not hasattr(self._thread_local, "dict"): - self._thread_local.dict = dict() - if key == "TF_CONFIG": - return dict.__getitem__(self._thread_local.dict, key) - else: - return dict.__getitem__(self, key) - - def __setitem__(self, key, val): - if not hasattr(self._thread_local, "dict"): - self._thread_local.dict = dict() - if key == "TF_CONFIG": - return dict.__setitem__(self._thread_local.dict, key, val) - else: - return dict.__setitem__(self, key, val) - - -class DistributeCoordinatorIntegrationTest(test.TestCase, - parameterized.TestCase): +class DistributeCoordinatorIntegrationTest( + multi_worker_test_base.IndependentWorkerTestBase, parameterized.TestCase): @classmethod def setUpClass(cls): """Create a local cluster with 2 workers.""" + super(DistributeCoordinatorIntegrationTest, cls).setUpClass() cls._cluster_spec = multi_worker_test_base.create_in_process_cluster( num_workers=3, num_ps=2, has_eval=True) def setUp(self): self._model_dir = tempfile.mkdtemp() - self._mock_os_env = MockOsEnv() - self._mock_context = test.mock.patch.object(os, "environ", - self._mock_os_env) super(DistributeCoordinatorIntegrationTest, self).setUp() - self._mock_context.__enter__() - - def tearDown(self): - self._mock_context.__exit__(None, None, None) - super(DistributeCoordinatorIntegrationTest, self).tearDown() def dataset_input_fn(self, x, y, batch_size, shuffle): @@ -141,8 +104,8 @@ class DistributeCoordinatorIntegrationTest(test.TestCase, def _extract_loss_and_global_step(self, event_folder): """Returns the loss and global step in last event.""" event_paths = glob.glob(os.path.join(event_folder, "events*")) - self.assertGreater(len(event_paths), 0, - msg="Event file not found in dir %s" % event_folder) + self.assertNotEmpty( + event_paths, msg="Event file not found in dir %s" % event_folder) loss = None global_step_count = None @@ -202,10 +165,10 @@ class DistributeCoordinatorIntegrationTest(test.TestCase, train_input_fn = self.dataset_input_fn( x={"x": DATA}, y=DATA, - batch_size=BATCH_SIZE // len(train_distribute.worker_devices), + batch_size=BATCH_SIZE // train_distribute.num_replicas_in_sync, shuffle=True) if eval_distribute: - eval_batch_size = BATCH_SIZE // len(eval_distribute.worker_devices) + eval_batch_size = BATCH_SIZE // eval_distribute.num_replicas_in_sync else: eval_batch_size = BATCH_SIZE eval_input_fn = self.dataset_input_fn( @@ -285,27 +248,34 @@ class DistributeCoordinatorIntegrationTest(test.TestCase, ]) self.assertAllEqual((BATCH_SIZE, LABEL_DIMENSION), predicted_proba.shape) + def _get_strategy_object(self, strategy_cls): + if strategy_cls == mirrored_strategy.CoreMirroredStrategy: + return strategy_cls(mirrored_strategy.all_local_devices()) + else: + return strategy_cls(num_gpus_per_worker=context.num_gpus()) + @combinations.generate( combinations.combine( mode=["graph"], train_distribute_cls=[ collective_all_reduce_strategy.CollectiveAllReduceStrategy, mirrored_strategy.MirroredStrategy, + mirrored_strategy.CoreMirroredStrategy, parameter_server_strategy.ParameterServerStrategy ], eval_distribute_cls=[ - None, mirrored_strategy.MirroredStrategy, + None, + mirrored_strategy.MirroredStrategy, + mirrored_strategy.CoreMirroredStrategy, parameter_server_strategy.ParameterServerStrategy, ], required_gpus=[0, 1])) def test_complete_flow_standalone_client(self, train_distribute_cls, eval_distribute_cls): - train_distribute = train_distribute_cls( - num_gpus_per_worker=context.num_gpus()) + train_distribute = self._get_strategy_object(train_distribute_cls) if eval_distribute_cls: - eval_distribute = eval_distribute_cls( - num_gpus_per_worker=context.num_gpus()) + eval_distribute = self._get_strategy_object(eval_distribute_cls) else: eval_distribute = None @@ -322,20 +292,20 @@ class DistributeCoordinatorIntegrationTest(test.TestCase, mode=["graph"], train_distribute_cls=[ mirrored_strategy.MirroredStrategy, + mirrored_strategy.CoreMirroredStrategy, ], eval_distribute_cls=[ None, mirrored_strategy.MirroredStrategy, + mirrored_strategy.CoreMirroredStrategy, ], required_gpus=[0, 1])) def test_estimator_standalone_client(self, train_distribute_cls, eval_distribute_cls): - train_distribute = train_distribute_cls( - num_gpus_per_worker=context.num_gpus()) + train_distribute = self._get_strategy_object(train_distribute_cls) if eval_distribute_cls: - eval_distribute = eval_distribute_cls( - num_gpus_per_worker=context.num_gpus()) + eval_distribute = self._get_strategy_object(eval_distribute_cls) else: eval_distribute = None @@ -355,47 +325,15 @@ class DistributeCoordinatorIntegrationTest(test.TestCase, self._barrier.wait() return ret - def _task_thread(self, train_distribute, eval_distribute, tf_config): - os.environ["TF_CONFIG"] = json.dumps(tf_config) + def _independent_worker_fn( + self, + train_distribute, + eval_distribute, + ): with test.mock.patch.object(dc, "_run_std_server", self._mock_run_std_server): self._complete_flow(train_distribute, eval_distribute) - def _run_task_in_thread(self, cluster_spec, task_type, task_id, - train_distribute, eval_distribute): - if task_type: - tf_config = { - "cluster": cluster_spec, - "task": { - "type": task_type, - "index": task_id - } - } - else: - tf_config = { - "cluster": cluster_spec, - "task": { - "type": task_type, - "index": task_id - } - } - t = threading.Thread( - target=self._task_thread, - args=(train_distribute, eval_distribute, tf_config)) - t.start() - return t - - def _run_multiple_tasks_in_threads(self, cluster_spec, train_distribute, - eval_distribute): - threads = {} - for task_type in cluster_spec.keys(): - threads[task_type] = [] - for task_id in range(len(cluster_spec[task_type])): - t = self._run_task_in_thread(cluster_spec, task_type, task_id, - train_distribute, eval_distribute) - threads[task_type].append(t) - return threads - @combinations.generate( combinations.combine( mode=["graph"], @@ -405,21 +343,20 @@ class DistributeCoordinatorIntegrationTest(test.TestCase, ], eval_distribute_cls=[ None, mirrored_strategy.MirroredStrategy, + mirrored_strategy.CoreMirroredStrategy, parameter_server_strategy.ParameterServerStrategy, ], required_gpus=[0, 1])) def test_complete_flow_indepedent_worker_between_graph( self, train_distribute_cls, eval_distribute_cls): - train_distribute = train_distribute_cls( - num_gpus_per_worker=context.num_gpus()) - if (context.num_gpus() < 2 and eval_distribute_cls == collective_all_reduce_strategy.CollectiveAllReduceStrategy): self.skipTest("`CollectiveAllReduceStrategy` needs at least two towers.") + train_distribute = self._get_strategy_object(train_distribute_cls) + if eval_distribute_cls: - eval_distribute = eval_distribute_cls( - num_gpus_per_worker=context.num_gpus()) + eval_distribute = self._get_strategy_object(eval_distribute_cls) else: eval_distribute = None @@ -435,8 +372,9 @@ class DistributeCoordinatorIntegrationTest(test.TestCase, # 3 workers and 1 evaluator. self._barrier = dc._Barrier(4) - threads = self._run_multiple_tasks_in_threads( - cluster_spec, train_distribute, eval_distribute) + threads = self.run_multiple_tasks_in_threads(self._independent_worker_fn, + cluster_spec, train_distribute, + eval_distribute) for task_type, ts in threads.items(): if task_type == PS: continue @@ -449,17 +387,22 @@ class DistributeCoordinatorIntegrationTest(test.TestCase, @combinations.generate( combinations.combine( mode=["graph"], - train_distribute_cls=[mirrored_strategy.MirroredStrategy], - eval_distribute_cls=[None, mirrored_strategy.MirroredStrategy], + train_distribute_cls=[ + mirrored_strategy.MirroredStrategy, + mirrored_strategy.CoreMirroredStrategy + ], + eval_distribute_cls=[ + None, + mirrored_strategy.MirroredStrategy, + mirrored_strategy.CoreMirroredStrategy + ], required_gpus=[0, 1])) def test_complete_flow_indepedent_worker_in_graph(self, train_distribute_cls, eval_distribute_cls): - train_distribute = train_distribute_cls( - num_gpus_per_worker=context.num_gpus()) + train_distribute = self._get_strategy_object(train_distribute_cls) if eval_distribute_cls: - eval_distribute = eval_distribute_cls( - num_gpus_per_worker=context.num_gpus()) + eval_distribute = self._get_strategy_object(eval_distribute_cls) else: eval_distribute = None @@ -467,8 +410,9 @@ class DistributeCoordinatorIntegrationTest(test.TestCase, num_workers=3, num_ps=0, has_eval=True) # 3 workers and 1 evaluator. self._barrier = dc._Barrier(4) - threads = self._run_multiple_tasks_in_threads( - cluster_spec, train_distribute, eval_distribute) + threads = self.run_multiple_tasks_in_threads(self._independent_worker_fn, + cluster_spec, train_distribute, + eval_distribute) threads[WORKER][0].join() threads[EVALUATOR][0].join() @@ -506,7 +450,8 @@ class RunConfigTest(test.TestCase): "os.environ", {"TF_CONFIG": json.dumps(TF_CONFIG_WITHOUT_TASK)}): run_config_lib.RunConfig( experimental_distribute=DistributeConfig( - train_distribute=mirrored_strategy.MirroredStrategy(num_gpus=2))) + train_distribute=mirrored_strategy.CoreMirroredStrategy( + ["/device:GPU:0", "/device:GPU:1"]))) def test_should_run_distribute_coordinator(self): """Tests that should_run_distribute_coordinator return a correct value.""" @@ -529,10 +474,12 @@ class RunConfigTest(test.TestCase): {"TF_CONFIG": json.dumps(TF_CONFIG_WITH_CHIEF)}): config_with_train_distribute = run_config_lib.RunConfig( experimental_distribute=DistributeConfig( - train_distribute=mirrored_strategy.MirroredStrategy(num_gpus=2))) + train_distribute=mirrored_strategy.CoreMirroredStrategy( + ["/device:GPU:0", "/device:GPU:1"]))) config_with_eval_distribute = run_config_lib.RunConfig( experimental_distribute=DistributeConfig( - eval_distribute=mirrored_strategy.MirroredStrategy(num_gpus=2))) + eval_distribute=mirrored_strategy.CoreMirroredStrategy( + ["/device:GPU:0", "/device:GPU:1"]))) self.assertTrue( dc_training.should_run_distribute_coordinator( config_with_train_distribute)) @@ -545,26 +492,27 @@ class RunConfigTest(test.TestCase): {"TF_CONFIG": json.dumps(TF_CONFIG_WITH_MASTER)}): config = run_config_lib.RunConfig( experimental_distribute=DistributeConfig( - train_distribute=mirrored_strategy.MirroredStrategy(num_gpus=2))) + train_distribute=mirrored_strategy.CoreMirroredStrategy( + ["/device:GPU:0", "/device:GPU:1"]))) self.assertFalse(dc_training.should_run_distribute_coordinator(config)) def test_init_run_config_duplicate_distribute(self): with self.assertRaises(ValueError): run_config_lib.RunConfig( - train_distribute=mirrored_strategy.MirroredStrategy(), + train_distribute=mirrored_strategy.CoreMirroredStrategy(), experimental_distribute=DistributeConfig( - train_distribute=mirrored_strategy.MirroredStrategy())) + train_distribute=mirrored_strategy.CoreMirroredStrategy())) with self.assertRaises(ValueError): run_config_lib.RunConfig( - eval_distribute=mirrored_strategy.MirroredStrategy(), + eval_distribute=mirrored_strategy.CoreMirroredStrategy(), experimental_distribute=DistributeConfig( - eval_distribute=mirrored_strategy.MirroredStrategy())) + eval_distribute=mirrored_strategy.CoreMirroredStrategy())) def test_init_run_config_none_distribute_coordinator_mode(self): # We don't use distribute coordinator for local training. config = run_config_lib.RunConfig( - train_distribute=mirrored_strategy.MirroredStrategy()) + train_distribute=mirrored_strategy.CoreMirroredStrategy()) dc_training.init_run_config(config, {}) self.assertIsNone(config._distribute_coordinator_mode) @@ -572,7 +520,7 @@ class RunConfigTest(test.TestCase): with test.mock.patch.dict("os.environ", {"TF_CONFIG": json.dumps(TF_CONFIG_WITH_MASTER)}): config = run_config_lib.RunConfig( - train_distribute=mirrored_strategy.MirroredStrategy()) + train_distribute=mirrored_strategy.CoreMirroredStrategy()) self.assertIsNone(config._distribute_coordinator_mode) # When `train_distribute` is not specified, don't use distribute @@ -588,7 +536,7 @@ class RunConfigTest(test.TestCase): with test.mock.patch.dict("os.environ", {"TF_CONFIG": json.dumps(TF_CONFIG_WITH_CHIEF)}): config = run_config_lib.RunConfig( - train_distribute=mirrored_strategy.MirroredStrategy()) + train_distribute=mirrored_strategy.CoreMirroredStrategy()) self.assertEqual(config._distribute_coordinator_mode, dc.CoordinatorMode.INDEPENDENT_WORKER) @@ -597,7 +545,7 @@ class RunConfigTest(test.TestCase): # `experimental.remote_cluster` is set use distribute coordinator with # STANDALONE_CLIENT mode. config = run_config_lib.RunConfig( - train_distribute=mirrored_strategy.MirroredStrategy(), + train_distribute=mirrored_strategy.CoreMirroredStrategy(), experimental_distribute=DistributeConfig( remote_cluster={"chief": ["fake_worker"]})) self.assertEqual(config._distribute_coordinator_mode, @@ -605,5 +553,15 @@ class RunConfigTest(test.TestCase): if __name__ == "__main__": + # Reduce `recovery_wait_secs` from 30 seconds so the test completes quickly. + orig_init = session_manager.SessionManager.__init__ + + def new_init(*args, **kwargs): + kwargs.pop("recovery_wait_secs", None) + kwargs["recovery_wait_secs"] = 0.5 + orig_init(*args, **kwargs) + + session_manager.SessionManager.__init__ = new_init + with test.mock.patch.object(sys, "exit", os._exit): test.main() diff --git a/tensorflow/contrib/distribute/python/examples/keras_mnist.py b/tensorflow/contrib/distribute/python/examples/keras_mnist.py index 0fd3acd045..60fda99664 100644 --- a/tensorflow/contrib/distribute/python/examples/keras_mnist.py +++ b/tensorflow/contrib/distribute/python/examples/keras_mnist.py @@ -20,6 +20,10 @@ from __future__ import print_function import tensorflow as tf +from tensorflow.python.distribute import mirrored_strategy +from tensorflow.python.keras.optimizer_v2 import rmsprop + + NUM_CLASSES = 10 @@ -102,18 +106,23 @@ def main(_): # Build the train and eval datasets from the MNIST data. Also return the # input shape which is constructed based on the `image_data_format` # i.e channels_first or channels_last. + tf.enable_eager_execution() + train_ds, eval_ds, input_shape = get_input_datasets() model = get_model(input_shape) # Instantiate the MirroredStrategy object. If we don't specify `num_gpus` or # the `devices` argument then all the GPUs available on the machine are used. - strategy = tf.contrib.distribute.MirroredStrategy() + # TODO(priyag): Use `tf.distribute.MirroredStrategy` once available. + strategy = mirrored_strategy.MirroredStrategy(['/gpu:0', '/cpu:0']) + + optimizer = rmsprop.RMSProp(learning_rate=0.001) # Compile the model by passing the distribution strategy object to the # `distribute` argument. `fit`, `evaluate` and `predict` will be distributed # based on the strategy instantiated. model.compile(loss=tf.keras.losses.categorical_crossentropy, - optimizer=tf.train.RMSPropOptimizer(learning_rate=0.001), + optimizer=optimizer, metrics=['accuracy'], distribute=strategy) diff --git a/tensorflow/contrib/distribute/python/keras_optimizer_v2_test.py b/tensorflow/contrib/distribute/python/keras_optimizer_v2_test.py index 46a1cf41c5..6dfd85bcc4 100644 --- a/tensorflow/contrib/distribute/python/keras_optimizer_v2_test.py +++ b/tensorflow/contrib/distribute/python/keras_optimizer_v2_test.py @@ -25,18 +25,23 @@ import numpy as np import six from tensorflow.contrib.distribute.python import combinations -from tensorflow.contrib.distribute.python import mirrored_strategy from tensorflow.core.protobuf import config_pb2 +from tensorflow.python import keras from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.eager import context +from tensorflow.python.distribute import distribution_strategy_context as ds_context from tensorflow.python.estimator import run_config from tensorflow.python.estimator import training from tensorflow.python.estimator.canned import dnn_linear_combined from tensorflow.python.estimator.canned import prediction_keys from tensorflow.python.estimator.export import export from tensorflow.python.estimator.inputs import numpy_io -from tensorflow.python.feature_column import feature_column +from tensorflow.python.feature_column import feature_column_lib as feature_column +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops from tensorflow.python.keras.optimizer_v2 import adam +from tensorflow.python.keras.optimizer_v2 import gradient_descent +from tensorflow.python.ops import math_ops from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables from tensorflow.python.platform import gfile @@ -64,7 +69,9 @@ class KerasOptimizerV2IntegrationTest(test.TestCase, parameterized.TestCase): distribution=[ combinations.one_device_strategy, combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus ], use_train_and_evaluate=[True, False])) def test_complete_flow_with_mode(self, distribution, use_train_and_evaluate): @@ -76,11 +83,11 @@ class KerasOptimizerV2IntegrationTest(test.TestCase, parameterized.TestCase): train_input_fn = self.dataset_input_fn( x={'x': data}, y=data, - batch_size=batch_size // len(distribution.worker_devices)) + batch_size=batch_size // distribution.num_replicas_in_sync) eval_input_fn = self.dataset_input_fn( x={'x': data}, y=data, - batch_size=batch_size // len(distribution.worker_devices)) + batch_size=batch_size // distribution.num_replicas_in_sync) predict_input_fn = numpy_io.numpy_input_fn( x={'x': data}, batch_size=batch_size, shuffle=False) @@ -136,44 +143,51 @@ class KerasOptimizerV2IntegrationTest(test.TestCase, parameterized.TestCase): shutil.rmtree(self._model_dir) -class MirroredStrategyOptimizerV2Test(test.TestCase): +def get_model(): + x = keras.layers.Input(shape=(3,), name='input') + y = keras.layers.Dense(4, name='dense')(x) + model = keras.Model(x, y) + return model - def testKerasOptimizerWithUnequalInput(self): - if context.num_gpus() < 1: - self.skipTest('Not enough GPUs.') - def create_fn(device_id): +class MirroredStrategyOptimizerV2Test(test.TestCase, parameterized.TestCase): + + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=['graph'])) + def testKerasOptimizerWithUnequalInput(self, distribution): + def create_fn(): var = variables.Variable( 2.0, name='var', aggregation=variable_scope.VariableAggregation.SUM) # grad for cpu is 1, grad for gpu is 2, avg grad is 1.5. - loss = (device_id + 1) * var + loss = math_ops.cast(_replica_id() + 1, dtype=dtypes.float32) * var optimizer = adam.Adam(learning_rate=0.01, beta_1=0.2, beta_2=0.2) train_op = optimizer.minimize(loss, var_list=[var]) m = optimizer.get_slot(var, 'm') v = optimizer.get_slot(var, 'v') - return (var, m, v, train_op, optimizer.iteration) + return (var, m, v, train_op, optimizer.iterations) devices = ['/device:GPU:0', '/device:CPU:0'] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): - (var, m, v, op, counter) = dist.call_for_each_replica( - create_fn, args=[dist.worker_device_index]) + with distribution.scope(): + (var, m, v, op, counter) = distribution.call_for_each_replica(create_fn) self.evaluate(variables.global_variables_initializer()) var_val = [2.0, 2.0, 2.0] self.assertAllClose( var_val, self.evaluate( - [dist.read_var(var), + [distribution.read_var(var), var.get(devices[0]), var.get(devices[1])])) self.assertAllClose([0, 0, 0], self.evaluate([ - dist.read_var(counter), + distribution.read_var(counter), counter.get(devices[0]), counter.get(devices[1]) ])) - train_op = dist.unwrap(op) + train_op = distribution.unwrap(op) self.evaluate(train_op) # m(1) = beta1 * m(0) + (1-beta1) * grad = 0.2 * 0 + 0.8 * (1 + 2) / 2 m_val = [1.2, 1.2, 1.2] @@ -181,7 +195,7 @@ class MirroredStrategyOptimizerV2Test(test.TestCase): self.assertAllClose( m_val, self.evaluate( - [dist.read_var(m), + [distribution.read_var(m), m.get(devices[0]), m.get(devices[1])])) # v(1) = beta2 * v(0) + (1-beta2) * grad^2 = 0.2 * 0 + 0.8 * 2.25 @@ -189,7 +203,7 @@ class MirroredStrategyOptimizerV2Test(test.TestCase): self.assertAllClose( v_val, self.evaluate( - [dist.read_var(v), + [distribution.read_var(v), v.get(devices[0]), v.get(devices[1])])) # var(1) = var(0) - lr * m(1) * sqrt(1 - beta2) / sqrt(v(1)) / (1 - beta1) @@ -198,12 +212,12 @@ class MirroredStrategyOptimizerV2Test(test.TestCase): self.assertAllClose( var_val, self.evaluate( - [dist.read_var(var), + [distribution.read_var(var), var.get(devices[0]), var.get(devices[1])])) self.assertAllClose([1, 1, 1], self.evaluate([ - dist.read_var(counter), + distribution.read_var(counter), counter.get(devices[0]), counter.get(devices[1]) ])) @@ -214,7 +228,7 @@ class MirroredStrategyOptimizerV2Test(test.TestCase): self.assertAllClose( m_val, self.evaluate( - [dist.read_var(m), + [distribution.read_var(m), m.get(devices[0]), m.get(devices[1])])) # v(2) = beta2 * v(1) + (1-beta2) * grad^2 = 0.2 * 1.8 + 0.8 * 2.25 @@ -222,16 +236,50 @@ class MirroredStrategyOptimizerV2Test(test.TestCase): self.assertAllClose( v_val, self.evaluate( - [dist.read_var(v), + [distribution.read_var(v), v.get(devices[0]), v.get(devices[1])])) self.assertAllClose([2, 2, 2], self.evaluate([ - dist.read_var(counter), + distribution.read_var(counter), counter.get(devices[0]), counter.get(devices[1]) ])) + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=['graph'])) + def testOptimizerWithKerasModelAndNumpyArrays(self, distribution): + + with self.cached_session(): + model = get_model() + optimizer = gradient_descent.SGD(0.001) + loss = 'mse' + metrics = ['mae'] + model.compile(optimizer, loss, metrics=metrics, distribute=distribution) + + inputs = np.zeros((64, 3), dtype=np.float32) + targets = np.zeros((64, 4), dtype=np.float32) + + model.fit( + inputs, + targets, + epochs=1, + batch_size=2, + verbose=0, + validation_data=(inputs, targets)) + model.evaluate(inputs, targets) + model.predict(inputs) + + +def _replica_id(): + replica_id = ds_context.get_replica_context().replica_id_in_sync_group + if not isinstance(replica_id, ops.Tensor): + replica_id = constant_op.constant(replica_id) + return replica_id + if __name__ == '__main__': test.main() diff --git a/tensorflow/contrib/distribute/python/keras_test.py b/tensorflow/contrib/distribute/python/keras_test.py index 0db5844e4c..e530ab6f17 100644 --- a/tensorflow/contrib/distribute/python/keras_test.py +++ b/tensorflow/contrib/distribute/python/keras_test.py @@ -24,9 +24,10 @@ import numpy as np from tensorflow.contrib.distribute.python import combinations from tensorflow.contrib.distribute.python import mirrored_strategy from tensorflow.contrib.distribute.python import tpu_strategy -from tensorflow.contrib.distribute.python import values from tensorflow.python import keras from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.distribute import values +from tensorflow.python.eager import test from tensorflow.python.estimator import keras as keras_lib from tensorflow.python.estimator import run_config as run_config_lib from tensorflow.python.framework import constant_op @@ -35,14 +36,13 @@ from tensorflow.python.framework import random_seed from tensorflow.python.framework import test_util from tensorflow.python.keras import testing_utils from tensorflow.python.keras.engine import distributed_training_utils +from tensorflow.python.keras.optimizer_v2 import gradient_descent as gradient_descent_keras from tensorflow.python.ops.parsing_ops import gen_parsing_ops from tensorflow.python.platform import gfile -from tensorflow.python.platform import test from tensorflow.python.summary.writer import writer_cache from tensorflow.python.training import gradient_descent from tensorflow.python.training import rmsprop - _RANDOM_SEED = 1337 _TRAIN_SIZE = 200 _INPUT_SIZE = (10,) @@ -212,13 +212,18 @@ def multi_input_output_model(): return model -def get_correctness_test_inputs(use_numpy, with_distribution, +def get_correctness_test_inputs(use_numpy, use_validation_data, + with_distribution, x_train, y_train, x_predict): """Generates the inputs for correctness check when enable Keras with DS.""" global_batch_size = 64 batch_size = global_batch_size # TODO(b/118776054): Use global batch size for Keras/DS support. - if with_distribution: + use_per_core_batch_size = ( + with_distribution and + not distributed_training_utils.global_batch_size_supported( + with_distribution)) + if use_per_core_batch_size: batch_size //= with_distribution.num_replicas_in_sync if use_numpy: @@ -229,16 +234,17 @@ def get_correctness_test_inputs(use_numpy, with_distribution, 'epochs': 1, 'shuffle': False, } - eval_inputs = { - 'batch_size': batch_size, - 'x': x_train, - 'y': y_train, - } + + if use_validation_data: + eval_inputs = None + training_inputs['validation_data'] = (x_train, y_train) + else: + eval_inputs = { + 'batch_size': batch_size, + 'x': x_train, + 'y': y_train, + } predict_inputs = { - # TODO(b/119318587): We should not require batch_size when distribution - # is enabled. - 'batch_size': (len(x_predict) // with_distribution.num_replicas_in_sync - if with_distribution else None), 'x': np.array(x_predict, dtype=np.float32), } else: @@ -256,20 +262,28 @@ def get_correctness_test_inputs(use_numpy, with_distribution, 'shuffle': False, 'steps_per_epoch': len(x_train) // global_batch_size, } - eval_inputs = { - 'batch_size': None, - 'x': x, - 'y': None, - 'steps': 20, - } + if use_validation_data: + eval_inputs = None # Remove the eval_inputs + eval_dataset = dataset_ops.Dataset.from_tensor_slices( + (x_train, y_train)) + x = batch_wrapper(eval_dataset, batch_size, with_distribution) + training_inputs['validation_data'] = x + training_inputs['validation_steps'] = 5 + else: + eval_inputs = { + 'batch_size': None, + 'x': x, + 'y': None, + 'steps': 20, + } + predict_batch_size = len(x_predict) - if with_distribution: + if use_per_core_batch_size: predict_batch_size //= with_distribution.num_replicas_in_sync predict_dataset = dataset_ops.Dataset.from_tensor_slices(x_predict) predict_dataset = batch_wrapper(predict_dataset, predict_batch_size, with_distribution) predict_inputs = { - 'batch_size': None, 'steps': 1, 'x': predict_dataset, } @@ -277,47 +291,71 @@ def get_correctness_test_inputs(use_numpy, with_distribution, return training_inputs, eval_inputs, predict_inputs -strategies = [combinations.default_strategy, - combinations.one_device_strategy, - combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus, - combinations.tpu_strategy, # steps_per_run=2 - combinations.tpu_strategy_one_step] +strategies_minus_tpu = [ + combinations.default_strategy, + combinations.one_device_strategy, + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus] + +tpu_strategies = [ + combinations.tpu_strategy, # steps_per_run=2 + combinations.tpu_strategy_one_step] def strategy_minus_tpu_combinations(): return combinations.combine( - distribution=[combinations.default_strategy, - combinations.one_device_strategy, - combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus], - mode=['graph']) + distribution=strategies_minus_tpu, + mode=['graph', 'eager']) -def strategy_combinations(): +def tpu_strategy_combinations(): return combinations.combine( - distribution=strategies, + distribution=tpu_strategies, mode=['graph']) -def strategy_and_optimizer_combinations(): - return combinations.combine( - distribution=strategies, - optimizer=[combinations.adagrad_optimizer_v1_fn, - combinations.adam_optimizer_v1_fn, - combinations.gradient_descent_optimizer_v1_fn, - combinations.rmsprop_optimizer_v1_fn], - mode=['graph']) +def all_strategy_combinations(): + return strategy_minus_tpu_combinations() + tpu_strategy_combinations() -def strategy_and_inputs(): +# TODO(priyag): Add v2 optimizers here. +def strategy_and_optimizer_combinations(): + return combinations.times( + all_strategy_combinations(), + combinations.combine( + optimizer=[combinations.adagrad_optimizer_v1_fn, + combinations.adam_optimizer_v1_fn, + combinations.gradient_descent_optimizer_v1_fn, + combinations.rmsprop_optimizer_v1_fn])) + + +def strategy_and_input_combinations(): + return ( + combinations.times( + combinations.combine(distribution=strategies_minus_tpu), + combinations.combine(mode=['graph'], + use_numpy=[True, False], + use_validation_data=[True, False]) + + combinations.combine(mode=['eager'], + use_numpy=[False], + use_validation_data=[False])) + + combinations.times( + combinations.combine(distribution=tpu_strategies), + combinations.combine(mode=['graph'], + use_numpy=[True, False], + use_validation_data=[True, False]))) + + +def strategy_for_numpy_input_combinations(): return combinations.combine( - distribution=strategies, - use_numpy=[True, False], + distribution=strategies_minus_tpu + tpu_strategies, mode=['graph']) -class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): +class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase, + parameterized.TestCase): def setUp(self): self._base_dir = os.path.join(self.get_temp_dir(), @@ -325,17 +363,18 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): gfile.MakeDirs(self._base_dir) self._config = run_config_lib.RunConfig( tf_random_seed=_RANDOM_SEED, model_dir=self._base_dir) - self._dist = mirrored_strategy.MirroredStrategy( - devices=['/device:GPU:0', '/device:GPU:1']) def tearDown(self): writer_cache.FileWriterCache.clear() if os.path.isdir(self._base_dir): gfile.DeleteRecursively(self._base_dir) - def test_train_functional_with_distribution_strategy(self): - dist = mirrored_strategy.MirroredStrategy( - devices=['/device:GPU:0', '/device:GPU:1']) + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], + mode=['graph'])) + def test_train_functional_with_distribution_strategy(self, distribution): keras_model = simple_functional_model() keras_model.compile( loss='categorical_crossentropy', @@ -343,8 +382,8 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): optimizer=rmsprop.RMSPropOptimizer(learning_rate=0.01)) config = run_config_lib.RunConfig(tf_random_seed=_RANDOM_SEED, model_dir=self._base_dir, - train_distribute=dist, - eval_distribute=dist) + train_distribute=distribution, + eval_distribute=distribution) with self.cached_session(): est_keras = keras_lib.model_to_estimator( keras_model=keras_model, config=config) @@ -358,9 +397,12 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): writer_cache.FileWriterCache.clear() gfile.DeleteRecursively(self._config.model_dir) - def test_train_sequential_with_distribution_strategy(self): - dist = mirrored_strategy.MirroredStrategy( - devices=['/device:GPU:0', '/device:GPU:1']) + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], + mode=['graph'])) + def test_train_sequential_with_distribution_strategy(self, distribution): keras_model = simple_sequential_model() keras_model.compile( loss='categorical_crossentropy', @@ -368,7 +410,7 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): optimizer=rmsprop.RMSPropOptimizer(learning_rate=0.01)) config = run_config_lib.RunConfig(tf_random_seed=_RANDOM_SEED, model_dir=self._base_dir, - train_distribute=dist) + train_distribute=distribution) with self.cached_session(): est_keras = keras_lib.model_to_estimator( keras_model=keras_model, config=config) @@ -382,7 +424,12 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): writer_cache.FileWriterCache.clear() gfile.DeleteRecursively(self._config.model_dir) - def test_multi_inputs_multi_outputs_with_input_fn_as_dict(self): + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], + mode=['graph'])) + def test_multi_inputs_multi_outputs_with_input_fn_as_dict(self, distribution): train_data, test_data = get_multi_inputs_multi_outputs_data() def train_input_fn(): @@ -412,14 +459,14 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): output_dict)).batch(16) self.do_test_multi_inputs_multi_outputs_with_input_fn( - train_input_fn, eval_input_fn) + distribution, train_input_fn, eval_input_fn) - def do_test_multi_inputs_multi_outputs_with_input_fn(self, train_input_fn, - eval_input_fn): + def do_test_multi_inputs_multi_outputs_with_input_fn( + self, distribution, train_input_fn, eval_input_fn): config = run_config_lib.RunConfig( tf_random_seed=_RANDOM_SEED, model_dir=self._base_dir, - train_distribute=self._dist) + train_distribute=distribution) with self.cached_session(): model = multi_inputs_multi_outputs_model() est_keras = keras_lib.model_to_estimator(keras_model=model, config=config) @@ -429,9 +476,12 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): eval_results = est_keras.evaluate(input_fn=eval_input_fn, steps=1) self.assertLess(eval_results['loss'], baseline_eval_results['loss']) - def test_keras_optimizer_with_distribution_strategy(self): - dist = mirrored_strategy.MirroredStrategy( - devices=['/device:GPU:0', '/device:GPU:1']) + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], + mode=['graph'])) + def test_keras_optimizer_with_distribution_strategy(self, distribution): keras_model = simple_sequential_model() keras_model.compile( loss='categorical_crossentropy', @@ -439,7 +489,7 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): config = run_config_lib.RunConfig(tf_random_seed=_RANDOM_SEED, model_dir=self._base_dir, - train_distribute=dist) + train_distribute=distribution) with self.cached_session(): est_keras = keras_lib.model_to_estimator(keras_model=keras_model, config=config) @@ -455,7 +505,7 @@ class TestEstimatorDistributionStrategy(test_util.TensorFlowTestCase): class TestDistributionStrategyWithNumpyArrays(test.TestCase, parameterized.TestCase): - @combinations.generate(strategy_combinations()) + @combinations.generate(strategy_for_numpy_input_combinations()) def test_creating_var_with_numpy_arrays(self, distribution): with self.cached_session(): x = np.asarray(np.random.random((64, 3)), dtype=np.float32) @@ -464,84 +514,135 @@ class TestDistributionStrategyWithNumpyArrays(test.TestCase, # Verify that the numpy value is copied to the variable. self.assertAllEqual(x, val) - def test_calculating_batch_params(self): - # This verifies that we calculate the number of steps when the batch size - # is specified. + @combinations.generate(strategy_for_numpy_input_combinations()) + def test_calculating_input_params_no_steps_no_batch_size(self, distribution): + # Calculate the per_replica_batch_size scaling factor for strategies + # that use per_core_batch_size + replica_scale_factor = 1.0 + if not distributed_training_utils.global_batch_size_supported(distribution): + replica_scale_factor = distribution.num_replicas_in_sync + with self.cached_session(): - # 64 is the number of input samples. - inputs = np.zeros((64, 3), dtype=np.float32) - # The number of replicas is equal to 3. - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:0', - '/device:CPU:0', - '/device:GPU:1']) - - with self.assertRaisesRegexp(ValueError, 'Please specify a batch_size ' - 'that is smaller than'): - # The batch size(128) is larger than the number of input - # samples(64). - distributed_training_utils.get_input_batch_params(inputs, - 128, - strategy) - - with self.assertRaisesRegexp(ValueError, 'is smaller than the number ' - 'of replicas'): - # The batch size(32) * num_replicas_in_sync(3) is 96 which is greater - # than the number of input samples(64). - distributed_training_utils.get_input_batch_params(inputs, - 32, - strategy) - - # The number of replicas now is equal to 2. - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:0', - '/device:CPU:0']) - # 32 is the batch size per replica. - steps = distributed_training_utils.get_input_batch_params(inputs, - 32, - strategy) - # The number of batches is the ratio of input samples(64) to - # batch size(32) which is 2. The number of steps(1) is the ratio of - # number of batches(2) to the number of replicas(2). + # Input samples of different sizes + input_20_samples = np.zeros((20, 3), dtype=np.float32) + input_63_samples = np.zeros((63, 3), dtype=np.float32) + input_64_samples = np.zeros((64, 3), dtype=np.float32) + + # Default global batch size 32 for input with 64 samples run in 2 steps + steps, batch_size = distributed_training_utils.get_input_params( + distribution, input_64_samples, steps=None, batch_size=None) + self.assertEqual(batch_size, 32 // replica_scale_factor) + self.assertEqual(steps, 2) + + # Computed global batch size 20 is lower than 32 if we pass less samples. + steps, batch_size = distributed_training_utils.get_input_params( + distribution, input_20_samples, steps=None, batch_size=None) + self.assertEqual(batch_size, 20 // replica_scale_factor) + self.assertEqual(steps, 1) + + # Default global batch size 32 cannot be used with 63 samples. + with self.assertRaisesRegexp(ValueError, 'not divisible by batch size'): + distributed_training_utils.get_input_params( + distribution, input_63_samples, steps=None, batch_size=None) + + @combinations.generate(strategy_for_numpy_input_combinations()) + def test_calculating_input_params_with_steps_no_batch_size(self, + distribution): + # Calculate the per_replica_batch_size scaling factor for strategies + # that use per_core_batch_size + replica_scale_factor = 1.0 + if not distributed_training_utils.global_batch_size_supported(distribution): + replica_scale_factor = distribution.num_replicas_in_sync + + with self.cached_session(): + # Input samples of different sizes + input_63_samples = np.zeros((63, 3), dtype=np.float32) + input_64_samples = np.zeros((64, 3), dtype=np.float32) + + # Computed global batch size is correct for number of specified 1 step + steps, batch_size = distributed_training_utils.get_input_params( + distribution, input_64_samples, steps=1, batch_size=None) + self.assertEqual(batch_size, 64 // replica_scale_factor) self.assertEqual(steps, 1) - # 16 is the batch size per replica. - steps = distributed_training_utils.get_input_batch_params(inputs, - 16, - strategy) - # The number of batches is the ratio of input samples(64) to - # batch size(16) which is 4. The number of steps(2) is the ratio of - # number of batches(4) to the number of replicas(2). + # Computed global batch size is correct for number of specified 2 steps + steps, batch_size = distributed_training_utils.get_input_params( + distribution, input_64_samples, steps=2, batch_size=None) + self.assertEqual(batch_size, 32 // replica_scale_factor) self.assertEqual(steps, 2) - def test_calculating_batch_size(self): + # All samples can not be consumed in specified number of steps + with self.assertRaisesRegexp(ValueError, 'not divisible by steps'): + distributed_training_utils.get_input_params( + distribution, input_63_samples, steps=2, batch_size=None) + + # This cases is different for different strategies due to the + # difference in supported batch size being global or per-replica. + if replica_scale_factor == 1: + # Computed global batch size is correct even if not sharadable + steps, batch_size = distributed_training_utils.get_input_params( + distribution, input_63_samples, steps=3, batch_size=None) + self.assertEqual(batch_size, 21) + self.assertEqual(steps, 3) + else: + # Computed global batch size can not be sharded across replicas + with self.assertRaisesRegexp(ValueError, 'could not be sharded evenly ' + 'across the sync replicas'): + distributed_training_utils.get_input_params( + distribution, input_63_samples, steps=1, batch_size=None) + + @combinations.generate(strategy_for_numpy_input_combinations()) + def test_calculating_input_params_no_steps_with_batch_size(self, + distribution): + # Calculate the per_replica_batch_size scaling factor for strategies + # that use per_core_batch_size + replica_scale_factor = 1.0 + if not distributed_training_utils.global_batch_size_supported(distribution): + replica_scale_factor = distribution.num_replicas_in_sync + with self.cached_session(): - # 64 is the number of input samples. - inputs = np.zeros((64, 3), dtype=np.float32) - targets = np.zeros((64, 4), dtype=np.float32) + input_64_samples = np.zeros((64, 3), dtype=np.float32) + + # Computed steps is correct for specified batch size + steps, batch_size = distributed_training_utils.get_input_params( + distribution, input_64_samples, steps=None, batch_size=16) + self.assertEqual(batch_size, 16) + self.assertEqual(steps, 4 // replica_scale_factor) + + # Computed steps is correct for specified batch size + steps, batch_size = distributed_training_utils.get_input_params( + distribution, input_64_samples, steps=None, batch_size=32) + self.assertEqual(batch_size, 32) + self.assertEqual(steps, 2 // replica_scale_factor) + + # Number of samples is not divisible by the global batch size + with self.assertRaisesRegexp(ValueError, 'not divisible by batch size'): + distributed_training_utils.get_input_params( + distribution, input_64_samples, steps=None, batch_size=20) + + # Number of samples is not divisible by the global batch size + with self.assertRaisesRegexp(ValueError, 'not divisible by batch size'): + distributed_training_utils.get_input_params( + distribution, input_64_samples, steps=None, batch_size=3) + + @combinations.generate(strategy_for_numpy_input_combinations()) + def test_calculating_input_params_with_steps_with_batch_size(self, + distribution): + with self.cached_session(): + input_64_samples = np.zeros((64, 3), dtype=np.float32) - model = get_model() - optimizer = gradient_descent.GradientDescentOptimizer(0.001) - loss = 'mse' - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:0', - '/device:CPU:0']) - strategy._require_static_shapes = True - - model.compile(optimizer, loss, distribute=strategy) - iterator = model._distribution_standardize_user_data(inputs, - targets, - batch_size=None, - check_steps=True, - steps_name='steps', - steps=3) - - # The global batch size(21) across all replicas is the ratio of the input - # samples(64) to the steps(3). - # The batch size(10) per device is the ratio of the global batch size(21) - # to the number of replicas(2). - # The global batch size and batch size are rounded integer values. - self.assertEqual(10, distributed_training_utils.get_batch_dimension( - iterator._iterator)) - - @combinations.generate(strategy_combinations()) + # No change to steps and batch size if both specified and feasible + steps, batch_size = distributed_training_utils.get_input_params( + distribution, input_64_samples, steps=5, batch_size=3) + self.assertEqual(batch_size, 3) + self.assertEqual(steps, 5) + + # Number of samples is less than global batch size * steps + with self.assertRaisesRegexp(ValueError, 'less than samples required'): + distributed_training_utils.get_input_params( + distribution, input_64_samples, steps=10, batch_size=13) + + @combinations.generate(strategy_for_numpy_input_combinations()) def test_calling_model_with_numpy_arrays(self, distribution): with self.cached_session(): model = get_model() @@ -572,7 +673,7 @@ class TestDistributionStrategyWithNumpyArrays(test.TestCase, # with batch_size model.predict(inputs, batch_size=8) - @combinations.generate(strategy_combinations()) + @combinations.generate(strategy_for_numpy_input_combinations()) def test_calling_model_with_nested_numpy_arrays(self, distribution): with self.cached_session(): model = multi_input_output_model() @@ -606,21 +707,22 @@ class TestDistributionStrategyWithNumpyArrays(test.TestCase, # with batch_size model.predict(inputs, batch_size=8) - @combinations.generate(strategy_minus_tpu_combinations()) + @combinations.generate(combinations.combine( + distribution=strategies_minus_tpu, mode=['graph'])) def test_numpy_with_sample_weights(self, distribution): model = get_model() optimizer = rmsprop.RMSPropOptimizer(learning_rate=0.001) loss = 'mse' model.compile(optimizer, loss, distribute=distribution) - inputs = np.zeros((10, 3), np.float32) - targets = np.zeros((10, 4), np.float32) - sample_weights = np.ones((10), np.float32) + inputs = np.zeros((20, 3), np.float32) + targets = np.zeros((20, 4), np.float32) + sample_weights = np.ones((20), np.float32) model.fit(inputs, targets, sample_weight=sample_weights, epochs=1, steps_per_epoch=2, verbose=1) - @combinations.generate(strategy_combinations()) + @combinations.generate(strategy_for_numpy_input_combinations()) def test_flatten_predict_outputs(self, distribution): with self.cached_session(): model = multi_input_output_model() @@ -638,7 +740,7 @@ class TestDistributionStrategyWithNumpyArrays(test.TestCase, # `predict` a list that is equal in length to the number of model outputs. # In this test our model has two outputs and each element of `outs` # corresponds to all the samples of one of the model outputs. - self.assertEqual(2, len(outs)) + self.assertLen(outs, 2) # Each of the output samples have a dimension of 7. We should process all # the available input samples(6). self.assertAllEqual([6, 7], outs[0].shape) @@ -648,7 +750,7 @@ class TestDistributionStrategyWithNumpyArrays(test.TestCase, class TestDistributionStrategyWithDatasets(test.TestCase, parameterized.TestCase): - @combinations.generate(strategy_combinations()) + @combinations.generate(all_strategy_combinations()) def test_calling_model_on_same_dataset(self, distribution): with self.cached_session(): model = get_model() @@ -667,7 +769,7 @@ class TestDistributionStrategyWithDatasets(test.TestCase, validation_data=dataset, validation_steps=2) model.predict(get_predict_dataset(distribution), steps=2) - @combinations.generate(strategy_combinations()) + @combinations.generate(all_strategy_combinations()) def test_model_interleaved_eval_same_as_direct_eval(self, distribution): with self.cached_session(): user_controlled_model = get_model() @@ -710,16 +812,20 @@ class TestDistributionStrategyWithDatasets(test.TestCase, # TODO(priyag): Enable this test for TPU. Currently tuples/dict don't work # as clone_model's input_tensors argument only seems to accept list and not # tuples or dict. - def test_fit_with_tuple_and_dict_dataset_inputs(self): + + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=['graph', 'eager'])) + def test_fit_with_tuple_and_dict_dataset_inputs(self, distribution): with self.cached_session(): model = multi_input_output_model() optimizer = gradient_descent.GradientDescentOptimizer(learning_rate=0.001) loss = 'mse' metrics = ['mae', keras.metrics.CategoricalAccuracy()] - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:0', - '/device:CPU:0']) - model.compile(optimizer, loss, metrics=metrics, distribute=strategy) + model.compile(optimizer, loss, metrics=metrics, distribute=distribution) input_a_np = np.random.random((10, 3)) input_b_np = np.random.random((10, 5)) @@ -743,7 +849,7 @@ class TestDistributionStrategyWithDatasets(test.TestCase, model.fit(dataset_dict, epochs=1, steps_per_epoch=2, verbose=1) - @combinations.generate(strategy_combinations()) + @combinations.generate(all_strategy_combinations()) def test_fit_eval_and_predict_methods_on_dataset(self, distribution): with self.cached_session(): model = get_model() @@ -792,35 +898,48 @@ class TestDistributionStrategyWithDatasets(test.TestCase, model.evaluate(dataset, steps=2, verbose=1) model.predict(dataset, steps=2) - def test_dataset_input_shape_validation(self): + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], + mode=['graph', 'eager'])) + def test_dataset_wrong_input_shape(self, distribution): with self.cached_session(): model = get_model() optimizer = rmsprop.RMSPropOptimizer(learning_rate=0.001) loss = 'mse' - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:1', - '/device:GPU:0']) - - model.compile(optimizer, loss, distribute=strategy) + model.compile(optimizer, loss, distribute=distribution) - # User forgets to batch the dataset - inputs = np.zeros((10, 3), dtype=np.float32) + # Wrong input shape + inputs = np.zeros((10, 5), dtype=np.float32) targets = np.zeros((10, 4), dtype=np.float32) dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) dataset = dataset.repeat(100) + dataset = dataset.batch(10) - with self.assertRaisesRegexp(ValueError, 'expected input to have shape'): + with self.assertRaisesRegexp(ValueError, + 'expected input to have shape'): model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0) - # Wrong input shape - inputs = np.zeros((10, 5), dtype=np.float32) + @combinations.generate(combinations.combine( + distribution=[combinations.mirrored_strategy_with_two_gpus], + mode=['graph', 'eager'])) + def test_dataset_no_batch_input_validation(self, distribution): + with self.cached_session(): + model = get_model() + + optimizer = rmsprop.RMSPropOptimizer(learning_rate=0.001) + loss = 'mse' + model.compile(optimizer, loss, distribute=distribution) + + # User forgets to batch the dataset + inputs = np.zeros((10, 3), dtype=np.float32) targets = np.zeros((10, 4), dtype=np.float32) dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) dataset = dataset.repeat(100) - dataset = dataset.batch(10) - with self.assertRaisesRegexp(ValueError, - 'expected input to have shape'): + with self.assertRaisesRegexp(ValueError, 'expected input to have shape'): model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0) @combinations.generate(combinations.combine( @@ -842,7 +961,12 @@ class TestDistributionStrategyWithDatasets(test.TestCase, with self.assertRaisesRegexp(ValueError, 'requires fully defined shapes'): model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0) - def test_learning_phase_value(self): + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], + mode=['graph', 'eager'])) + def test_learning_phase_value(self, distribution): # TODO(anjalisridhar): Modify this test to use Lambdas since we can compare # meaningful values. Currently we don't pass the learning phase if the # Lambda layer uses the learning phase. @@ -856,15 +980,17 @@ class TestDistributionStrategyWithDatasets(test.TestCase, optimizer = gradient_descent.GradientDescentOptimizer(0.005) loss = 'mse' metrics = ['acc'] - strategy = mirrored_strategy.MirroredStrategy( - ['/device:GPU:0', '/device:GPU:1']) + model.compile(optimizer, loss, metrics=metrics, distribute=distribution) - model.compile(optimizer, loss, metrics=metrics, distribute=strategy) + batch_size = 8 + if isinstance(distribution, mirrored_strategy.CoreMirroredStrategy): + # CoreMirroredStrategy uses global batch size. + batch_size = 8 * distribution.num_replicas_in_sync inputs = np.ones((10, 1), dtype=np.float32) targets = np.ones((10, 1), dtype=np.float32) dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) - dataset = dataset.repeat().batch(8) + dataset = dataset.repeat().batch(batch_size) hist = model.fit(dataset, epochs=1, steps_per_epoch=20, verbose=1) self.assertAlmostEqual(hist.history['acc'][0], 0, 0) @@ -875,24 +1001,51 @@ class TestDistributionStrategyWithDatasets(test.TestCase, inputs = np.ones((10, 1), dtype=np.float32) predict_dataset = dataset_ops.Dataset.from_tensor_slices(inputs) - predict_dataset = predict_dataset.repeat().batch(5) + + predict_dataset = predict_dataset.repeat().batch(batch_size) output = model.predict(predict_dataset, steps=10) - # `predict` runs for 10 steps and in each step you process 100 samples. - ref_output = np.ones((100, 1), dtype=np.float32) + # `predict` runs for 10 steps + ref_output = np.ones((160, 1), dtype=np.float32) self.assertArrayNear(output, ref_output, 1e-1) + @combinations.generate(strategy_minus_tpu_combinations()) + def testOptimizerWithCallbacks(self, distribution): + with self.cached_session(): + model = get_model() + + optimizer = gradient_descent_keras.SGD(0.01) + loss = 'mse' + model.compile(optimizer, loss, distribute=distribution) + + dataset = get_dataset(distribution) + + def schedule(_): + return 0.001 + + model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0, + callbacks=[keras.callbacks.LearningRateScheduler(schedule)]) + grouped_models = distribution.unwrap(model._grouped_model) + with distribution.scope(): + for m in grouped_models: + self.assertAllClose(0.001, keras.backend.get_value( + m.optimizer.lr), atol=1e-05, rtol=1e-05) + class TestDistributionStrategyErrorCases(test.TestCase, parameterized.TestCase): - def test_validating_dataset_input_tensors_with_shape_mismatch(self): + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=['graph', 'eager'])) + def test_validating_dataset_input_tensors_with_shape_mismatch(self, + distribution): with self.cached_session(): - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:0', - '/device:CPU:0']) a = constant_op.constant([1, 2], shape=(1, 2)) b = constant_op.constant([[1, 2], [1, 2]], shape=(2, 2)) x = values.DistributedValues({'/device:CPU:0': a, '/device:GPU:0': b}) y = values.DistributedValues({'/device:CPU:0': a, '/device:GPU:0': a}) - with strategy.scope(): + with distribution.scope(): # Removed device and input tensor shape details from the error message # since the order of the device and the corresponding input tensor shape # is not deterministic over different runs. @@ -901,17 +1054,21 @@ class TestDistributionStrategyErrorCases(test.TestCase, parameterized.TestCase): 'distributed tensor inputs ' 'DistributedValues:.+'): distributed_training_utils.validate_distributed_dataset_inputs( - strategy, x, y) + distribution, x, y) - def test_validating_dataset_input_tensors_with_dtype_mismatch(self): + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=['graph', 'eager'])) + def test_validating_dataset_input_tensors_with_dtype_mismatch(self, + distribution): with self.cached_session(): - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:0', - '/device:CPU:0']) a = constant_op.constant([1, 2], shape=(1, 2), dtype=dtypes.int32) b = constant_op.constant([1, 2], shape=(1, 2), dtype=dtypes.float64) x = values.DistributedValues({'/device:CPU:0': a, '/device:GPU:0': b}) y = values.DistributedValues({'/device:CPU:0': a, '/device:GPU:0': a}) - with strategy.scope(): + with distribution.scope(): # Removed device and input tensor dtype details from the error message # since the order of the device and the corresponding input tensor dtype # is not deterministic over different runs. @@ -920,21 +1077,23 @@ class TestDistributionStrategyErrorCases(test.TestCase, parameterized.TestCase): 'distributed tensor inputs ' 'DistributedValues:.+'): distributed_training_utils.validate_distributed_dataset_inputs( - strategy, x, y) + distribution, x, y) - def test_unsupported_features(self): + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], + mode=['graph', 'eager'])) + def test_unsupported_features(self, distribution): with self.cached_session(): model = get_model() optimizer = gradient_descent.GradientDescentOptimizer(0.001) loss = 'mse' metrics = ['mae'] - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:1', - '/device:GPU:0']) - - model.compile(optimizer, loss, metrics=metrics, distribute=strategy) + model.compile(optimizer, loss, metrics=metrics, distribute=distribution) - dataset = get_dataset(strategy) + dataset = get_dataset(distribution) # Test with validation split with self.assertRaisesRegexp( @@ -969,30 +1128,33 @@ class TestDistributionStrategyErrorCases(test.TestCase, parameterized.TestCase): 'you should specify the `steps` argument'): model.predict(dataset, verbose=0) - def test_calling_with_unsupported_predefined_callbacks(self): + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], + mode=['graph', 'eager'])) + def test_calling_with_unsupported_predefined_callbacks(self, distribution): with self.cached_session(): model = get_model() optimizer = gradient_descent.GradientDescentOptimizer(0.001) loss = 'mse' metrics = ['mae'] - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:1', - '/device:GPU:0']) - model.compile(optimizer, loss, metrics=metrics, distribute=strategy) + model.compile(optimizer, loss, metrics=metrics, distribute=distribution) - dataset = get_dataset(strategy) + dataset = get_dataset(distribution) def schedule(_): return 0.001 with self.assertRaisesRegexp(ValueError, - 'LearningRateScheduler callback is not ' - 'supported with DistributionStrategy.'): + 'You must specify a Keras Optimizer V2 when ' + 'using'): model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0, callbacks=[keras.callbacks.LearningRateScheduler(schedule)]) with self.assertRaisesRegexp(ValueError, - 'ReduceLROnPlateau callback is not ' - 'supported with DistributionStrategy.'): + 'You must specify a Keras Optimizer V2 when ' + 'using'): model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0, callbacks=[keras.callbacks.ReduceLROnPlateau()]) with self.assertRaisesRegexp(ValueError, @@ -1003,11 +1165,17 @@ class TestDistributionStrategyErrorCases(test.TestCase, parameterized.TestCase): callbacks=[keras.callbacks.TensorBoard(histogram_freq=10)]) -class TestDistributionStrategyWithLossMasking(test.TestCase): +class TestDistributionStrategyWithLossMasking(test.TestCase, + parameterized.TestCase): # TODO(priyag): Enable all strategies for this test. Currently it does not # work for TPU due to some invalid datatype. - def test_masking(self): + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_two_gpus], + mode=['graph', 'eager'])) + def test_masking(self, distribution): with self.cached_session(): np.random.seed(1337) x = np.array([[[1], [1]], [[0], [0]]]) @@ -1016,12 +1184,9 @@ class TestDistributionStrategyWithLossMasking(test.TestCase): model.add( keras.layers.TimeDistributed( keras.layers.Dense(1, kernel_initializer='one'))) - strategy = mirrored_strategy.MirroredStrategy(['/device:GPU:1', - '/device:GPU:0']) - model.compile(loss='mse', optimizer=gradient_descent.GradientDescentOptimizer(0.01), - distribute=strategy) + distribute=distribution) y = np.array([[[1], [1]], [[1], [1]]]) dataset = dataset_ops.Dataset.from_tensor_slices((x, y)) dataset = dataset.repeat(100) @@ -1033,7 +1198,7 @@ class TestDistributionStrategyWithLossMasking(test.TestCase): class TestDistributionStrategyWithNormalizationLayer( test.TestCase, parameterized.TestCase): - @combinations.generate(strategy_combinations()) + @combinations.generate(all_strategy_combinations()) def test_batchnorm_correctness(self, distribution): with self.cached_session(): model = keras.models.Sequential() @@ -1065,7 +1230,7 @@ class TestDistributionStrategyWithNormalizationLayer( class TestDistributionStrategyCorrectness(test.TestCase, parameterized.TestCase): - @combinations.generate(strategy_combinations()) + @combinations.generate(all_strategy_combinations()) def test_metric_correctness(self, distribution): with self.cached_session(): keras.backend.set_image_data_format('channels_last') @@ -1088,22 +1253,32 @@ class TestDistributionStrategyCorrectness(test.TestCase, distribute=distribution) batch_size = 64 - batch_size //= distribution.num_replicas_in_sync + if not distributed_training_utils.global_batch_size_supported( + distribution): + batch_size //= distribution.num_replicas_in_sync train_dataset = dataset_ops.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = batch_wrapper(train_dataset, batch_size, distribution) history = model.fit(x=train_dataset, epochs=1, steps_per_epoch=10) self.assertEqual(history.history['binary_accuracy'], [1.0]) - @combinations.generate(strategy_and_inputs()) - def test_correctness(self, distribution, use_numpy): + @combinations.generate(strategy_and_input_combinations()) + def test_correctness(self, distribution, use_numpy, use_validation_data): + with self.cached_session(): tolerance = 1e-5 - if isinstance(distribution, mirrored_strategy.MirroredStrategy): + if isinstance(distribution, (mirrored_strategy.MirroredStrategy, + mirrored_strategy.CoreMirroredStrategy)): # TODO(b/119257215): use the default one once the flakyness is fixed. tolerance = 1e-4 + if (use_validation_data and + not isinstance(distribution, tpu_strategy.TPUStrategy)): + # TODO(b/120435565): Enable tests with use_validation_data once the + # the underlying bug is fixed. + return + keras.backend.set_image_data_format('channels_last') np.random.seed(_RANDOM_SEED) random_seed.set_random_seed(_RANDOM_SEED) @@ -1123,49 +1298,72 @@ class TestDistributionStrategyCorrectness(test.TestCase, # This is used to initialize the model for both the distribution and # non-distribution run. In addition, we add few non-linear layers to make # it non-trivial. - model = keras.Sequential() - model.add(keras.layers.Dense(10, activation='relu', input_shape=(1,))) - model.add(keras.layers.Dense(10, activation='relu')) - model.add(keras.layers.Dense(10, activation='relu')) - model.add(keras.layers.Dense(1)) + def _create_model(): + model = keras.Sequential() + model.add(keras.layers.Dense(10, activation='relu', input_shape=(1,))) + model.add(keras.layers.Dense(10, activation='relu')) + model.add(keras.layers.Dense(10, activation='relu')) + model.add(keras.layers.Dense(1)) + return model + + model = _create_model() initial_weights = model.get_weights() + del model # avoid accident usage. - def fit_and_predict(with_distribution=None): + def fit_eval_and_predict(with_distribution=None): + model = _create_model() # We have initialized the model to the same weight for the distribution # and non-distribution run. model.set_weights(initial_weights) model.compile( loss=keras.losses.mean_squared_error, - optimizer=gradient_descent.GradientDescentOptimizer(0.5), + optimizer=gradient_descent_keras.SGD(0.5), distribute=with_distribution) training_inputs, eval_inputs, predict_inputs = ( - get_correctness_test_inputs(use_numpy, with_distribution, + get_correctness_test_inputs(use_numpy, use_validation_data, + with_distribution, x_train, y_train, x_predict)) - model.fit(**training_inputs) - eval_result = model.evaluate(**eval_inputs) + traning_history = model.fit(**training_inputs).history + + if eval_inputs is not None: + eval_result = model.evaluate(**eval_inputs) + else: + # Creates a dummy identical eval_result to be compared later. + eval_result = 1.0 + weights = model.get_weights() predict_result = model.predict(**predict_inputs) - return weights, eval_result, predict_result + return weights, traning_history, eval_result, predict_result + + wts_with_ds, history_with_ds, eval_with_ds, predict_with_ds = ( + fit_eval_and_predict(with_distribution=distribution)) - wts_with_ds, eval_with_ds, predict_with_ds = fit_and_predict( - with_distribution=distribution) - wts_without_ds, eval_without_ds, predict_without_ds = fit_and_predict( - with_distribution=None) + (wts_without_ds, history_without_ds, eval_without_ds, + predict_without_ds) = fit_eval_and_predict(with_distribution=None) - # Verify that the weights, eval results, predict outputs are the same - # within some limits of tolerance. + # Verify that the weights, training history, eval results, predict outputs + # are the same within some limits of tolerance. self.assertAllClose( - wts_with_ds, wts_without_ds, atol=tolerance, rtol=tolerance) + wts_with_ds, wts_without_ds, atol=tolerance, rtol=tolerance, + msg='Fail to assert weights after training.') + self.assertAllClose( - eval_with_ds, eval_without_ds, atol=tolerance, rtol=tolerance) + eval_with_ds, eval_without_ds, atol=tolerance, rtol=tolerance, + msg='Fail to assert eval results.') self.assertAllClose( - predict_with_ds, predict_without_ds, atol=tolerance, rtol=tolerance) - - -# TODO(priyag): Add a test for TPUStrategy with steps_per_run > 1. + predict_with_ds, predict_without_ds, atol=tolerance, rtol=tolerance, + msg='Fail to assert predict results.') + + if not (isinstance(distribution, tpu_strategy.TPUStrategy) + and distribution.extended.steps_per_run > 1): + # TODO(b/119894254): Enable this test for all cases once the underlying + # bug is fixed. + self.assertAllClose( + history_with_ds, history_without_ds, atol=tolerance, rtol=tolerance, + msg='Fail to assert training history.') if __name__ == '__main__': diff --git a/tensorflow/contrib/distribute/python/metrics_v1_test.py b/tensorflow/contrib/distribute/python/metrics_v1_test.py index c28ab41651..8ac659abe9 100644 --- a/tensorflow/contrib/distribute/python/metrics_v1_test.py +++ b/tensorflow/contrib/distribute/python/metrics_v1_test.py @@ -72,14 +72,14 @@ def _regression_dataset_fn(): "predictions": [1., .75, .25, 0.]}).repeat() -# TODO(priyag): Add TPU Strategy to this once metrics aggregate correctly using -# ReplicaLocalVariables on TPUs. Submit http://cl/208914352. def all_combinations(): return combinations.combine( distribution=[combinations.default_strategy, combinations.one_device_strategy, combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus], + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus], mode=["graph"]) @@ -100,18 +100,19 @@ class MetricsV1Test(test.TestCase, parameterized.TestCase): if isinstance(distribution, tpu_strategy.TPUStrategy): def step_fn(ctx, inputs): value, update = distribution.call_for_each_replica( - metric_fn, args=[inputs]) + metric_fn, args=inputs) ctx.set_non_tensor_output(name="value", output=value) return distribution.group(update) ctx = distribution.run_steps_on_dataset( - step_fn, iterator, iterations=distribution.steps_per_run) + step_fn, iterator, iterations=distribution.extended.steps_per_run) update = ctx.run_op value = ctx.non_tensor_outputs["value"] # In each run, we run multiple steps, and each steps consumes as many # batches as number of replicas. batches_per_update = ( - distribution.num_replicas_in_sync * distribution.steps_per_run) + distribution.num_replicas_in_sync * + distribution.extended.steps_per_run) else: value, update = distribution.call_for_each_replica( metric_fn, iterator.get_next()) diff --git a/tensorflow/contrib/distribute/python/minimize_loss_test.py b/tensorflow/contrib/distribute/python/minimize_loss_test.py index c6562463ed..dcc9df4cda 100644 --- a/tensorflow/contrib/distribute/python/minimize_loss_test.py +++ b/tensorflow/contrib/distribute/python/minimize_loss_test.py @@ -25,6 +25,7 @@ from tensorflow.contrib.distribute.python import combinations from tensorflow.contrib.distribute.python.single_loss_example import batchnorm_example from tensorflow.contrib.distribute.python.single_loss_example import minimize_loss_example from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.distribute import reduce_util from tensorflow.python.eager import context from tensorflow.python.eager import test from tensorflow.python.framework import constant_op @@ -63,7 +64,7 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): model_fn, dataset_fn, layer = minimize_loss_example( optimizer_fn, use_bias=True, use_callable_loss=use_callable_loss) - def step_fn(ctx, *inputs): + def step_fn(ctx, inputs): del ctx # Unused return distribution.group( distribution.call_for_each_replica(model_fn, args=inputs)) @@ -157,7 +158,7 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): use_callable_loss=True, create_optimizer_inside_model_fn=True) - def step_fn(ctx, *inputs): + def step_fn(ctx, inputs): del ctx # Unused return distribution.group( distribution.call_for_each_replica(model_fn, args=inputs)) @@ -226,7 +227,7 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): renorm=renorm, update_ops_in_replica_mode=not update_ops_in_cross_replica_mode) - def step_fn(ctx, *inputs): + def step_fn(ctx, inputs): del ctx # Unused fetches = distribution.unwrap( distribution.call_for_each_replica(model_fn, args=inputs)) @@ -285,7 +286,9 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): distribution=[ combinations.one_device_strategy, combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus ]), combinations.combine( mode=["graph"], use_callable_loss=[True, False]) + @@ -321,10 +324,10 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): labels = dataset_ops.Dataset.from_tensors([[6.], [21.]]) return dataset_ops.Dataset.zip((features, labels)).repeat() - def step_fn(ctx, x, y): + def step_fn(ctx, inputs): del ctx # Unused return distribution.group( - distribution.call_for_each_replica(model_fn, args=(x, y))) + distribution.call_for_each_replica(model_fn, args=inputs)) iterator = self._get_iterator(distribution.distribute_dataset(dataset_fn)) @@ -341,7 +344,7 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): run_step() v = all_vars[0] - self.assertTrue(all([v is vi for vi in all_vars[1:]])) + self.assertTrue(all(v is vi for vi in all_vars[1:])) weight = numpy.squeeze(self.evaluate(v)) # Our model is: # predict = x * w @@ -402,21 +405,21 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): train_op = optimizer.minimize(loss_fn) loss = loss_fn() output_context.set_last_step_output( - name="replica_loss_agg", + name="replica_loss_reduced", output=loss, - aggregation=variables_lib.VariableAggregation.MEAN) + reduce_op=reduce_util.ReduceOp.MEAN) output_context.set_non_tensor_output(key1, value1) return (train_op, loss) - def step_fn(output_context, *inputs): + def step_fn(output_context, inputs): (train_op, loss) = distribution.call_for_each_replica( model_fn, args=(output_context,) + inputs) output_context.set_last_step_output( - name="cross_replica_loss_agg", + name="cross_replica_loss_reduced", output=loss, - aggregation=variables_lib.VariableAggregation.MEAN) + reduce_op=reduce_util.ReduceOp.MEAN) output_context.set_last_step_output( - name="cross_replica_loss_noagg", + name="cross_replica_loss_not_reduced", output=loss) return distribution.group(train_op) @@ -424,16 +427,16 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): def run_step(): initial_loss = lambda: constant_op.constant(1e7) - # Initial values corresponding to aggregated losses are just single - # tensors. But for non aggregated losses, we need to have initial + # Initial values corresponding to reduced losses are just single + # tensors. But for non reduced losses, we need to have initial # values that are of the same structure as non reduced losses. In # MirroredStrategy, this will be a list of losses, in TPUStrategy # it will be single tensor. Using `broadcast` followed by `unwrap` # gives us the desired initial value structure. initial_loop_values = { - "replica_loss_agg": initial_loss(), - "cross_replica_loss_agg": initial_loss(), - "cross_replica_loss_noagg": + "replica_loss_reduced": initial_loss(), + "cross_replica_loss_reduced": initial_loss(), + "cross_replica_loss_not_reduced": distribution.unwrap(distribution.broadcast(initial_loss())) } ctx = distribution.run_steps_on_dataset( @@ -443,17 +446,17 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): self.assertEqual({key1: [value1]}, ctx.non_tensor_outputs) self._verify_loss_output( initial_loss(), - loss_output=ctx.last_step_outputs["replica_loss_agg"], - aggregated=True, distribution=distribution) + loss_output=ctx.last_step_outputs["replica_loss_reduced"], + reduced=True, distribution=distribution) self._verify_loss_output( initial_loss(), - loss_output=ctx.last_step_outputs["cross_replica_loss_agg"], - aggregated=True, distribution=distribution) + loss_output=ctx.last_step_outputs["cross_replica_loss_reduced"], + reduced=True, distribution=distribution) self._verify_loss_output( initial_loss(), - loss_output=ctx.last_step_outputs["cross_replica_loss_noagg"], - aggregated=False, distribution=distribution) - return (ctx.run_op, ctx.last_step_outputs["replica_loss_agg"]) + loss_output=ctx.last_step_outputs["cross_replica_loss_not_reduced"], + reduced=False, distribution=distribution) + return (ctx.run_op, ctx.last_step_outputs["replica_loss_reduced"]) self.evaluate(distribution.initialize()) if not context.executing_eagerly(): @@ -478,18 +481,16 @@ class MinimizeLossStepTest(test.TestCase, parameterized.TestCase): error_is_not_increasing = all(y <= x for x, y in zip(error, error[1:])) self.assertTrue(error_is_not_increasing) - def _verify_loss_output(self, initial_loss, loss_output, aggregated, + def _verify_loss_output(self, initial_loss, loss_output, reduced, distribution): - if not aggregated: - self.assertEqual(distribution.num_replicas_in_sync, - len(distribution.unwrap(loss_output))) - loss_output = distribution.reduce( - aggregation=variables_lib.VariableAggregation.MEAN, - value=loss_output, destinations="/device:CPU:0") - - unwrapped_output = distribution.unwrap(loss_output) - self.assertEqual(1, len(unwrapped_output)) - loss_tensor = unwrapped_output[0] + if not reduced: + self.assertLen(distribution.unwrap(loss_output), + distribution.num_replicas_in_sync) + loss_tensor = distribution.reduce(reduce_util.ReduceOp.MEAN, loss_output) + else: + unwrapped_output = distribution.unwrap(loss_output) + self.assertLen(unwrapped_output, 1) + loss_tensor = unwrapped_output[0] self.assertEqual(initial_loss.dtype, loss_tensor.dtype) self.assertEqual(initial_loss.shape, loss_tensor.shape) diff --git a/tensorflow/contrib/distribute/python/mirrored_strategy.py b/tensorflow/contrib/distribute/python/mirrored_strategy.py index 2d75024e7a..20f1a08d42 100644 --- a/tensorflow/contrib/distribute/python/mirrored_strategy.py +++ b/tensorflow/contrib/distribute/python/mirrored_strategy.py @@ -12,293 +12,35 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Class MirroredStrategy implementing DistributionStrategy.""" +"""Contrib version of MirroredStrategy.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import contextlib -from functools import partial -import threading +import functools -from tensorflow.contrib.distribute.python import cross_tower_ops as cross_tower_ops_lib -from tensorflow.contrib.distribute.python import shared_variable_creator -from tensorflow.contrib.distribute.python import values -from tensorflow.python import pywrap_tensorflow -from tensorflow.python.distribute import multi_worker_util -from tensorflow.python.eager import context -from tensorflow.python.eager import tape -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import device as tf_device -from tensorflow.python.framework import ops -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import control_flow_ops -from tensorflow.python.ops import variable_scope -from tensorflow.python.ops import variables as variables_lib -from tensorflow.python.training import coordinator -from tensorflow.python.training import device_util -from tensorflow.python.training import distribute as distribute_lib -from tensorflow.python.util import nest +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import mirrored_strategy +from tensorflow.python.distribute import values -# TODO(josh11b): Replace asserts in this file with if ...: raise ... - - -@contextlib.contextmanager -def _enter_graph(g): - if context.executing_eagerly(): - with g.as_default(), context.eager_mode(): - yield - else: - with g.as_default(): - yield - - -def _cpu_device(device): - cpu_device = tf_device.DeviceSpec.from_string(device) - cpu_device.merge_from(tf_device.DeviceSpec(device_type="CPU", device_index=0)) - return cpu_device.to_string() - - -class _RequestedStop(Exception): - pass - - -# _call_for_each_replica and _reduce_non_distributed_value are not members of -# MirroredStrategy so that they are generally not allowed to use anything -# specific to MirroredStrategy and thus can be shared with other distribution -# strategies. - - -# TODO(yuefengz): maybe create a common class for those who need to call this -# _call_for_each_replica. -def _call_for_each_replica(distribution, fn, args, kwargs): - """Run `fn` in separate threads, once per replica/worker device. - - Args: - distribution: the DistributionStrategy object. - fn: function to run (will be run once per device, each in its own thread). - args: positional arguments for `fn` - kwargs: keyword arguments for `fn`. - - Returns: - Merged return value of `fn` across all replicas. - - Raises: - RuntimeError: If fn() calls get_replica_context().merge_call() a different - number of times from the available devices. - """ - # TODO(josh11b): Add this option once we add synchronization to variable - # creation. Until then, this is pretty unsafe to use. - run_concurrently = False - if not context.executing_eagerly(): - # Needed for per-thread device, etc. contexts in graph mode. - ops.get_default_graph().switch_to_thread_local() - - coord = coordinator.Coordinator(clean_stop_exception_types=(_RequestedStop,)) - - shared_variable_store = {} - - # TODO(isaprykin): Create these threads once instead of during every run() - # call. - threads = [] - for index, d in enumerate(distribution.worker_devices): - variable_creator_fn = shared_variable_creator.make_fn( - shared_variable_store, index) - t = MirroredStrategy._MirroredReplicaThread( # pylint: disable=protected-access - distribution, coord, d, variable_creator_fn, fn, - *values.select_device(d, args), **values.select_device(d, kwargs)) - threads.append(t) - - for t in threads: - t.start() - - # When `fn` starts `should_run` event is set on _MirroredReplicaThread - # (`MRT`) threads. The execution waits until - # `MRT.has_paused` is set, which indicates that either `fn` is - # complete or a `get_replica_context().merge_call()` is called. If `fn` is - # complete, then `MRT.done` is set to True. Otherwise, arguments - # of `get_replica_context().merge_call` from all paused threads are grouped - # and the `merge_fn` is performed. Results of the - # `get_replica_context().merge_call` are then set to `MRT.merge_result`. - # Each such `get_replica_context().merge_call` call returns the - # `MRT.merge_result` for that thread when `MRT.should_run` event - # is reset again. Execution of `fn` resumes. - - try: - with coord.stop_on_exception(): - all_done = False - while not all_done and not coord.should_stop(): - done = [] - if run_concurrently: - for t in threads: - t.should_run.set() - for t in threads: - t.has_paused.wait() - t.has_paused.clear() - if coord.should_stop(): - return None - done.append(t.done) - else: - for t in threads: - t.should_run.set() - t.has_paused.wait() - t.has_paused.clear() - if coord.should_stop(): - return None - done.append(t.done) - if coord.should_stop(): - return None - all_done = all(done) - if not all_done: - if any(done): - raise RuntimeError("Some replicas made a different number of " - "replica_context().merge_call() calls.") - # get_replica_context().merge_call() case - merge_args = values.regroup({t.device: t.merge_args for t in threads}) - merge_kwargs = values.regroup( - {t.device: t.merge_kwargs for t in threads}) - # We capture the name_scope of the MRT when we call merge_fn - # to ensure that if we have opened a name scope in the MRT, - # it will be respected when executing the merge function. We only - # capture the name_scope from the first MRT and assume it is - # the same for all other MRTs. - mtt_captured_name_scope = threads[0].captured_name_scope - with ops.name_scope(mtt_captured_name_scope): - merge_result = threads[0].merge_fn(distribution, *merge_args, - **merge_kwargs) - for t in threads: - t.merge_result = values.select_device(t.device, merge_result) - finally: - for t in threads: - t.should_run.set() - coord.join(threads) - - return values.regroup({t.device: t.main_result for t in threads}) - - -def _reduce_non_distributed_value(distribution, aggregation, value, - destinations): - """Reduce a non-DistributedValue `value` to `destinations`.""" - if isinstance(value, values.DistributedValues): - raise ValueError("You are passing a `DistributedValue` to " - "`_reduce_non_distributed_value`, which is not allowed.") - - # If the same value is present on all replicas then the PerReplica value will - # be a single value. We also handle the case when `value` is a single value - # and equal to 0. - if value == 0: - return 0 - # If the aggregation type is MEAN or ONLY_FIRST_REPLICA, then this - # essentially means that the same value should be on all destinations. - if aggregation in ( - variable_scope.VariableAggregation.MEAN, - variable_scope.VariableAggregation.ONLY_FIRST_REPLICA): - return value - - cross_tower_ops_lib.validate_destinations(destinations) - # We do not support an aggregation type of SUM if the value is the same across - # all replicas. We call this as part of assign functions for MirroredVariables - # and summing up identical values across replicas is not clearly defined. - if (len(distribution.worker_devices) != 1 or - not cross_tower_ops_lib.check_destinations(destinations)): - raise ValueError("A non-DistributedValues value %s cannot be reduced with " - "the given aggregation %s." % (value, aggregation)) - # TODO(anjalisridhar): Moves these methods to a device utility file? - devices = cross_tower_ops_lib.get_devices_from(destinations) - if len(devices) == 1: - with ops.device(devices[0]): - return array_ops.identity(value) - else: - value_updates = {} - for d in devices: - with ops.device(d): - value_updates[d] = array_ops.identity(value) - return values.Mirrored(value_updates) - - -def _create_mirrored_variable(devices, real_mirrored_creator, *args, **kwargs): # pylint: disable=g-missing-docstring - # Figure out what collections this variable should be added to. - # We'll add the MirroredVariable to those collections instead. - collections = kwargs.pop("collections", None) - if collections is None: - collections = [ops.GraphKeys.GLOBAL_VARIABLES] - kwargs["collections"] = [] - - # Get synchronization value - synchronization = kwargs.get("synchronization", - variable_scope.VariableSynchronization.ON_WRITE) - if synchronization == variable_scope.VariableSynchronization.NONE: - raise ValueError("`NONE` variable synchronization mode is not " - "supported with `Mirrored` distribution strategy. Please" - " change the `synchronization` for variable: " + - kwargs["name"]) - elif synchronization == variable_scope.VariableSynchronization.ON_READ: - # Variables that are to be synced on read are replica local. - is_replica_local = True - kwargs["trainable"] = False - elif (synchronization == variable_scope.VariableSynchronization.ON_WRITE or - synchronization == variable_scope.VariableSynchronization.AUTO): - # `AUTO` synchronization for `MirroredStrategy` is `ON_WRITE`. - is_replica_local = False - else: - raise ValueError("Invalid variable synchronization mode: " + - synchronization + " for variable: " + kwargs["name"]) - - # Get aggregation value - aggregation = kwargs.pop("aggregation", - variable_scope.VariableAggregation.NONE) - if aggregation not in ( - variable_scope.VariableAggregation.NONE, - variable_scope.VariableAggregation.SUM, - variable_scope.VariableAggregation.MEAN, - variable_scope.VariableAggregation.ONLY_FIRST_REPLICA - ): - raise ValueError("Invalid variable aggregation mode: " + aggregation + - " for variable: " + kwargs["name"]) - - # Ignore user-specified caching device, not needed for mirrored variables. - kwargs.pop("caching_device", None) - - # TODO(josh11b,apassos): It would be better if variable initialization - # was never recorded on the tape instead of having to do this manually - # here. - with tape.stop_recording(): - index = real_mirrored_creator(devices, *args, **kwargs) - - if is_replica_local: - result = values.ReplicaLocalVariable( - index, index[devices[0]], aggregation) - else: - result = values.MirroredVariable(index, index[devices[0]], aggregation) - - # Add the wrapped variable to the requested collections. - # The handling of eager mode and the global step matches - # ResourceVariable._init_from_args(). - if not context.executing_eagerly(): - g = ops.get_default_graph() - # If "trainable" is True, next_creator() will add the member variables - # to the TRAINABLE_VARIABLES collection, so we manually remove - # them and replace with the MirroredVariable. We can't set - # "trainable" to False for next_creator() since that causes functions - # like implicit_gradients to skip those variables. - if kwargs.get("trainable", True): - collections.append(ops.GraphKeys.TRAINABLE_VARIABLES) - l = g.get_collection_ref(ops.GraphKeys.TRAINABLE_VARIABLES) - for v in index.values(): - if v in l: - l.remove(v) - g.add_to_collections(collections, result) - elif ops.GraphKeys.GLOBAL_STEP in collections: - ops.add_to_collections(ops.GraphKeys.GLOBAL_STEP, result) - - return result +# pylint: disable=protected-access,invalid-name +_call_for_each_replica = mirrored_strategy._call_for_each_replica +_reduce_non_distributed_value = mirrored_strategy._reduce_non_distributed_value +_create_mirrored_variable = mirrored_strategy._create_mirrored_variable +all_local_devices = mirrored_strategy.all_local_devices +CoreMirroredStrategy = mirrored_strategy.MirroredStrategy +CoreMirroredExtended = mirrored_strategy.MirroredExtended +# pylint: enable=protected-access,invalid-name class MirroredStrategy(distribute_lib.DistributionStrategy): """Mirrors vars to distribute across multiple devices and machines. + *** contrib version *** + This strategy uses one replica per device and sync replication for its multi-GPU version. @@ -353,468 +95,66 @@ class MirroredStrategy(distribute_lib.DistributionStrategy): cross_device_ops=None, auto_shard_dataset=False, cross_tower_ops=None): - super(MirroredStrategy, self).__init__() - assert not (cross_device_ops and cross_tower_ops) - self._cross_tower_ops = cross_device_ops or cross_tower_ops - self._auto_shard_dataset = auto_shard_dataset - # Remember num GPUs which might be needed by `configure` method. if num_gpus is not None and num_gpus_per_worker is not None: raise ValueError( "You cannot specify both `num_gpus` and `num_gpus_per_worker`.") - if num_gpus is not None: - self._num_gpus = num_gpus - else: - self._num_gpus = num_gpus_per_worker - - self._initialize_local(self._num_gpus, devices) - - def _initialize_local(self, num_gpus, devices): - """Initializes the object for local training.""" - self._cluster_spec = None - # Convert `num_gpus` into `devices`, shouldn't specify both. - if devices is None: - if num_gpus is None: - num_gpus = context.num_gpus() - if num_gpus == 0: - devices = ["/device:CPU:0"] - else: - devices = ["/device:GPU:%d" % d for d in range(num_gpus)] - elif num_gpus is not None: - raise ValueError("Must only specify one of `devices` and `num_gpus`.") - self._num_gpus = num_gpus - # TODO(yuefengz): consider setting the default device. - - assert devices, "Must specify at least one device." - assert len(set(devices)) == len(devices), ( - "No duplicates allowed in `devices` argument.") - # TODO(josh11b): Require at least 2 devices? - self._devices = [device_util.resolve(d) for d in devices] - self._canonical_device_set = set(self._devices) - self._device_index = values.PerReplica( - {d: i for i, d in enumerate(devices)}) - - def _initialize_multi_worker(self, num_gpus, cluster_spec): - """Initializes the object for multi-worker training.""" - cluster_spec = multi_worker_util.normalize_cluster_spec(cluster_spec) - self._cluster_spec = cluster_spec - - self._workers = [] - for job in ["chief", "worker"]: - for task in range(len(cluster_spec.as_dict().get(job, []))): - self._workers.append("/job:%s/task:%d" % (job, task)) - if num_gpus is None: - raise ValueError("`num_gpus` is required if `cluster_spec` is given.") - if num_gpus > 0: - self._worker_devices = [ - (worker, [ - device_util.canonicalize(worker + "/device:GPU:%d" % gpu) - for gpu in range(num_gpus) - ]) for worker in self._workers - ] - else: - self._worker_devices = [ - (worker, [device_util.canonicalize(worker, "/device:CPU:0")]) - for worker in self._workers - ] - - devices = nest.flatten([l for _, l in self._worker_devices]) - - # Setting `_default_device` will add a device scope in the - # distribution.scope. We set the default device to the first worker. When - # users specify device under distribution.scope by - # with tf.device("/cpu:0"): - # ... - # their ops will end up on the cpu device of its first worker, e.g. - # "/job:worker/task:0/device:CPU:0". Note this is not used in replica mode. - self._default_device = self._workers[0] - - assert devices, "Must specify at least one device." - assert len(set(devices)) == len(devices), ( - "No duplicates allowed in `devices` argument.") - # TODO(josh11b): Require at least 2 devices? - self._devices = [device_util.resolve(d) for d in devices] - self._canonical_device_set = set(self._devices) - self._device_index = values.PerReplica( - {d: i for i, d in enumerate(devices)}) + num_gpus = num_gpus_per_worker + extended = MirroredExtended(self, devices, num_gpus, + cross_device_ops or cross_tower_ops, + auto_shard_dataset) + super(MirroredStrategy, self).__init__(extended) - def _create_variable(self, next_creator, *args, **kwargs): - """Create a mirrored variable. See `DistributionStrategy.scope`.""" - colocate_with = kwargs.pop("colocate_with", None) - devices = self._get_devices_from(colocate_with) - def _real_mirrored_creator(devices, *args, **kwargs): # pylint: disable=g-missing-docstring - index = {} - for i, d in enumerate(devices): - with ops.device(d): - if i > 0: - # Give replicas meaningful distinct names: - var0name = index[devices[0]].name.split(":")[0] - # We append a / to variable names created on replicas with id > 0 to - # ensure that we ignore the name scope and instead use the given - # name as the absolute name of the variable. - kwargs["name"] = "%s/replica_%d/" % (var0name, i) - # Initialize replicas with the same value: - def initial_value_fn(device=d): - if context.executing_eagerly(): - init_value = index[devices[0]].value() - return array_ops.identity(init_value) - else: - with ops.device(device): - init_value = index[devices[0]].initial_value - return array_ops.identity(init_value) - kwargs["initial_value"] = initial_value_fn - with context.context().device_policy(context.DEVICE_PLACEMENT_SILENT): - # Don't record operations (e.g. other variable reads) during - # variable creation. - with tape.stop_recording(): - v = next_creator(*args, **kwargs) - assert not isinstance(v, values.DistributedVariable) - index[d] = v - return index +class MirroredExtended(CoreMirroredExtended): + """Implementation of (contrib) MirroredStrategy.""" - return _create_mirrored_variable(devices, _real_mirrored_creator, *args, - **kwargs) + def __init__(self, + container_strategy, + devices=None, + num_gpus_per_worker=None, + cross_device_ops=None, + auto_shard_dataset=False): + if devices is None: + devices = mirrored_strategy.all_local_devices(num_gpus_per_worker) + elif num_gpus_per_worker is not None: + raise ValueError( + "Must only specify one of `devices` and `num_gpus_per_worker`.") + super(MirroredExtended, self).__init__(container_strategy, devices, + cross_device_ops) + self._auto_shard_dataset = auto_shard_dataset - def distribute_dataset(self, dataset_fn): - if self._cluster_spec: - return values.MultiWorkerDataset( - partial(self._call_dataset_fn, dataset_fn), self._worker_devices, - auto_shard=self._auto_shard_dataset) + def _make_dataset_iterator(self, dataset): + """Make iterator from dataset without splitting the batch. + + This implementation is different than the one in + `tf.distribute.MirroredStrategy` for purposes of backward compatibility. + We treat the incoming dataset's batch size as per replica batch size. + + Args: + dataset: `tf.data.Dataset` for input. + Returns: + An `InputIterator` which returns inputs for each step of the computation. + """ + if self._local_mode: + worker = device_util.canonicalize("/device:CPU:0") + worker_device_pairs = [(worker, self._devices)] else: + worker_device_pairs = self._worker_devices + return values.DatasetIterator(dataset, worker_device_pairs) + + def _distribute_dataset(self, dataset_fn): + if self._local_mode: return values.PerReplicaDataset( self._call_dataset_fn(dataset_fn), self._devices) - - # TODO(priyag): Deal with OutOfRange errors once b/111349762 is fixed. - def _run_steps_on_dataset(self, fn, iterator, iterations, - initial_loop_values=None): - if initial_loop_values is None: - initial_loop_values = {} - initial_loop_values = nest.flatten(initial_loop_values) - - ctx = values.MultiStepContext() - def body(i, *args): - """A wrapper around `fn` to create the while loop body.""" - del args - fn_inputs = iterator.get_next() - if not isinstance(fn_inputs, tuple): - fn_inputs = (fn_inputs,) - fn_result = fn(ctx, *fn_inputs) - for (name, output) in ctx.last_step_outputs.items(): - # Convert all outputs to tensors, potentially from `DistributedValues`. - ctx.last_step_outputs[name] = self.unwrap(output) - flat_last_step_outputs = nest.flatten(ctx.last_step_outputs) - with ops.control_dependencies([fn_result]): - return [i + 1] + flat_last_step_outputs - - # We capture the control_flow_context at this point, before we run `fn` - # inside a while_loop. This is useful in cases where we might need to exit - # these contexts and get back to the outer context to do some things, for - # e.g. create an op which should be evaluated only once at the end of the - # loop on the host. One such usage is in creating metrics' value op. - self._outer_control_flow_context = ( - ops.get_default_graph()._get_control_flow_context()) # pylint: disable=protected-access - - cond = lambda i, *args: i < iterations - i = constant_op.constant(0) - loop_result = control_flow_ops.while_loop( - cond, body, [i] + initial_loop_values, name="", - parallel_iterations=1, back_prop=False, swap_memory=False, - return_same_structure=True) - del self._outer_control_flow_context - - ctx.run_op = control_flow_ops.group(loop_result) - - # Convert the last_step_outputs from a list to the original dict structure - # of last_step_outputs. - last_step_tensor_outputs = loop_result[1:] - last_step_tensor_outputs_dict = nest.pack_sequence_as( - ctx.last_step_outputs, last_step_tensor_outputs) - - for (name, aggregation) in ctx._last_step_outputs_aggregations.items(): # pylint: disable=protected-access - output = last_step_tensor_outputs_dict[name] - # For outputs that have already been aggregated, wrap them in a Mirrored - # container, else in a PerReplica container. - if aggregation is variables_lib.VariableAggregation.NONE: - last_step_tensor_outputs_dict[name] = values.regroup( - {d: t for d, t in zip(self._devices, output)}, values.PerReplica) - else: - assert len(output) == 1 - last_step_tensor_outputs_dict[name] = output[0] - - ctx._set_last_step_outputs(last_step_tensor_outputs_dict) # pylint: disable=protected-access - return ctx - - def _broadcast(self, tensor, destinations): - # TODO(josh11b): In eager mode, use one thread per device, or async mode. - return self._get_cross_tower_ops().broadcast(tensor, destinations or - self._devices) - - def _call_for_each_replica(self, fn, args, kwargs): - return _call_for_each_replica(self, fn, args, kwargs) - - def configure(self, - session_config=None, - cluster_spec=None, - task_type=None, - task_id=None): - del task_type, task_id - - if session_config: - session_config.isolate_session_state = True - - if cluster_spec: - self._initialize_multi_worker(self._num_gpus, cluster_spec) - - if self._cross_tower_ops is None: - if self._cluster_spec: - # It currently cannot detect the toplogy of remote workers. So we - # hard-code the multi-worker all-reduce algorithm for now. - if len(self._workers) == 1: - # The default is "nccl". - self._cross_tower_ops = cross_tower_ops_lib.AllReduceCrossDeviceOps() - else: - # The default is hierarchical reduce and broadcast. - self._cross_tower_ops = cross_tower_ops_lib.MultiWorkerAllReduce( - self._workers, self._num_gpus) - else: - self._cross_tower_ops = cross_tower_ops_lib.choose_the_best( - self._devices, session_config=session_config) - - def _get_cross_tower_ops(self): - if self._cross_tower_ops is None: - self._cross_tower_ops = ( - cross_tower_ops_lib.ReductionToOneDeviceCrossDeviceOps()) - return self._cross_tower_ops - - def _reduce(self, aggregation, value, destinations): - assert not isinstance(value, values.Mirrored) - if not isinstance(value, values.DistributedValues): - # This function handles reducing values that are not PerReplica or - # Mirrored values. For example, the same value could be present on all - # replicas in which case `value` would be a single value or value could - # be 0. - return _reduce_non_distributed_value(self, aggregation, value, - destinations) - if aggregation == variable_scope.VariableAggregation.ONLY_FIRST_REPLICA: - value = value.get(self._devices[0]) - if isinstance(value, (int, float)): - return value - return self.broadcast(value, destinations) - return self._get_cross_tower_ops().reduce( - aggregation, value, destinations=destinations) - - def _batch_reduce(self, aggregation, value_destination_pairs): - if aggregation == variable_scope.VariableAggregation.ONLY_FIRST_REPLICA: - return [self.broadcast(v.get(self._devices[0]), d) - for v, d in value_destination_pairs] - return self._get_cross_tower_ops().batch_reduce(aggregation, - value_destination_pairs) - - def _update(self, var, options, fn, *args, **kwargs): - # TODO(josh11b): In eager mode, use one thread per device. - assert isinstance(var, values.DistributedVariable) - should_group = options.pop("grouped") - assert not options # Validate that we are processing all of the options. - updates = {} - for d, v in var._index.items(): # pylint: disable=protected-access - name = "update_%d" % self._device_index.get(d) - with ops.device(d), distribute_lib.UpdateContext(d), ops.name_scope(name): - # If args and kwargs are not mirrored, the value is returned as is. - updates[d] = fn(v, - *values.select_device_mirrored(d, args), - **values.select_device_mirrored(d, kwargs)) - return values.update_regroup(self, updates, should_group) - - def _update_non_slot(self, colocate_with, options, fn, *args, **kwargs): - assert isinstance(colocate_with, list) - should_group = options.pop("grouped") - assert not options # Validate that we are processing all of the options. - # TODO(josh11b): In eager mode, use one thread per device. - updates = {} - for d in colocate_with: - name = "update_%d" % self._device_index.get(d) - with ops.device(d), distribute_lib.UpdateContext(d), ops.name_scope(name): - updates[d] = fn(*values.select_device_mirrored(d, args), - **values.select_device_mirrored(d, kwargs)) - return values.update_regroup(self, updates, should_group) - - def read_var(self, replica_local_var): - """Read the aggregate value of a replica-local variable.""" - if isinstance(replica_local_var, values.ReplicaLocalVariable): - return replica_local_var._get_cross_replica() # pylint: disable=protected-access - assert isinstance(replica_local_var, values.Mirrored) - return array_ops.identity(replica_local_var.get()) - - def _unwrap(self, val): - if isinstance(val, values.DistributedValues): - # Return in a deterministic order. - if set(val.devices) == self._canonical_device_set: - return [val.get(device=d) for d in self._devices] - return [val.get(device=d) for d in sorted(val.devices)] - return [val] - - def value_container(self, val): - return values.value_container(val) - - @property - def num_replicas(self): - return len(self._devices) - - @property - def num_replicas_in_sync(self): - return len(self._devices) - - def _worker_device_index(self): - return self._device_index - - @property - def worker_devices(self): - # Make a copy to prevent users from accidentally mutating our copy. - return list(self._devices) - - @property - def parameter_devices(self): - return list(self._devices) - - @property - def between_graph(self): - return False - - @property - def should_init(self): - return True - - @property - def should_checkpoint(self): - return True - - @property - def should_save_summary(self): - return True - - def non_slot_devices(self, var_list): - del var_list - return list(self._devices) - - def _get_devices_from(self, colocate_with=None): - if colocate_with is None: - return self._devices else: - return cross_tower_ops_lib.get_devices_from(colocate_with) - - class _MirroredReplicaThread(threading.Thread): - """A thread that runs() a function on a device.""" - - def __init__(self, dist, coord, device, variable_creator_fn, fn, *args, - **kwargs): - super(MirroredStrategy._MirroredReplicaThread, self).__init__() # pylint: disable=protected-access - self.coord = coord - self.distribution = dist - self.device = device - self.replica_id = dist.worker_devices.index(device) - self.variable_creator_fn = variable_creator_fn - # State needed to run and return the results of `fn`. - self.main_fn = fn - self.main_args = args - self.main_kwargs = kwargs - self.main_result = None - self.done = False - # State needed to run the next merge_call() (if any) requested via - # ReplicaContext. - self.merge_fn = None - self.merge_args = None - self.merge_kwargs = None - self.merge_result = None - self.captured_name_scope = None - # We use a thread.Event for the main thread to signal when this - # thread should start running (`should_run`), and another for - # this thread to transfer control back to the main thread - # (`has_paused`, either when it gets to a - # `get_replica_context().merge_call` or when `fn` returns). In - # either case the event starts cleared, is signaled by calling - # set(). The receiving thread waits for the signal by calling - # wait() and then immediately clearing the event using clear(). - self.should_run = threading.Event() - self.has_paused = threading.Event() - # These fields have to do with inheriting various contexts from the - # parent thread: - # pylint: disable=protected-access - self.context_mode = context.context()._eager_context.mode - if not context.context()._context_handle: - context.context()._initialize_handle_and_devices() - self.context_device_policy = ( - pywrap_tensorflow.TFE_ContextGetDevicePlacementPolicy( - context.context()._context_handle)) - self.graph = ops.get_default_graph() - self._variable_creator_stack = self.graph._variable_creator_stack[:] - self._captured_var_scope = variable_scope.get_variable_scope() - # Adding a "/" at end lets us re-enter this scope later. - self._name_scope = self.graph.get_name_scope() - if self._name_scope: - self._name_scope += "/" - if self.replica_id > 0: - if not self._name_scope: - self._name_scope = "" - self._name_scope += "replica_%d/" % self.replica_id - - def run(self): - # pylint: disable=protected-access - self.graph._variable_creator_stack = self._variable_creator_stack - self.should_run.wait() - self.should_run.clear() - try: - if self.coord.should_stop(): - return - with self.coord.stop_on_exception(), \ - context.context()._mode(self.context_mode), \ - context.context().device_policy(self.context_device_policy), \ - _enter_graph(self.graph), \ - MirroredReplicaContext(self.distribution, self.replica_id), \ - ops.device(self.device), \ - ops.name_scope(self._name_scope), \ - variable_scope.variable_scope( - self._captured_var_scope, reuse=self.replica_id > 0), \ - variable_scope.variable_creator_scope(self.variable_creator_fn): - self.main_result = self.main_fn(*self.main_args, **self.main_kwargs) - self.done = True - finally: - self.has_paused.set() - - -class MirroredReplicaContext(distribute_lib.ReplicaContext): - """ReplicaContext used in MirroredStrategy.call_for_each_replica(). - - Opened in `_MirroredReplicaThread`, to allow the user to invoke - `MirroredStrategy`'s specific implementation of `merge_call()`, - which works by delegating the function and its arguments to - the main thread (the one that invoked - `MirroredStrategy.call_for_each_replica()`). - """ - - def _merge_call(self, fn, args, kwargs): - """Delegate to the main thread to actually perform merge_call().""" - t = threading.current_thread() # a _MirroredReplicaThread - t.merge_fn = fn - t.merge_args = args - t.merge_kwargs = kwargs - t.captured_name_scope = t.graph.get_name_scope() - # Adding a "/" at end lets us re-enter this scope later. - if t.captured_name_scope: - t.captured_name_scope += "/" - t.has_paused.set() - t.should_run.wait() - t.should_run.clear() - if t.coord.should_stop(): - raise _RequestedStop() - return t.merge_result - - @property - def device(self): - raise RuntimeError("Use .devices instead") + return values.MultiWorkerDataset( + functools.partial(self._call_dataset_fn, dataset_fn), + self._worker_devices, + auto_shard=self._auto_shard_dataset) + # TODO(priyag): Delete this once all strategies use global batch size. @property - def devices(self): - distribute_lib.require_replica_context(self) - return [self._distribution_strategy.worker_devices[self._replica_id]] + def _global_batch_size(self): + return False diff --git a/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py b/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py index 1fd18e09c0..66512f983e 100644 --- a/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py +++ b/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py @@ -20,22 +20,27 @@ from __future__ import print_function import sys +from absl.testing import parameterized import numpy as np +from tensorflow.contrib.distribute.python import combinations from tensorflow.contrib.distribute.python import mirrored_strategy from tensorflow.contrib.distribute.python import multi_worker_test_base from tensorflow.contrib.distribute.python import strategy_test_lib -from tensorflow.contrib.distribute.python import values from tensorflow.core.protobuf import config_pb2 from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribution_strategy_context as ds_context +from tensorflow.python.distribute import reduce_util +from tensorflow.python.distribute import values from tensorflow.python.eager import backprop from tensorflow.python.eager import context from tensorflow.python.eager import function from tensorflow.python.eager import test from tensorflow.python.framework import constant_op +from tensorflow.python.framework import func_graph from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops -from tensorflow.python.framework import test_util from tensorflow.python.keras.engine import training as keras_training from tensorflow.python.keras.layers import core as keras_core from tensorflow.python.layers import core @@ -46,8 +51,6 @@ from tensorflow.python.ops import rnn_cell_impl from tensorflow.python.ops import state_ops from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables -from tensorflow.python.training import device_util -from tensorflow.python.training import distribution_strategy_context from tensorflow.python.training import gradient_descent from tensorflow.python.training import optimizer as optimizer_lib from tensorflow.python.training import server_lib @@ -56,248 +59,229 @@ from tensorflow.python.training import server_lib GPU_TEST = "test_gpu" in sys.argv[0] -class MirroredTwoDeviceDistributionTest(strategy_test_lib.DistributionTestBase): +@combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus], + mode=["graph", "eager"])) +class MirroredTwoDeviceDistributionTest(strategy_test_lib.DistributionTestBase, + parameterized.TestCase): - def _get_distribution_strategy(self): - devices = ["/device:CPU:0", "/device:GPU:0"] - if GPU_TEST: - self.assertGreater(context.num_gpus(), 0) - if context.num_gpus() > 1: - devices = ["/device:GPU:0", "/device:GPU:1"] - print(self.id().split(".")[-1], "devices:", ", ".join(devices)) - return mirrored_strategy.MirroredStrategy(devices) + def testMinimizeLoss(self, distribution): + if context.executing_eagerly(): + self._test_minimize_loss_eager(distribution) + else: + self._test_minimize_loss_graph(distribution) - def testMinimizeLossEager(self): - if not GPU_TEST: - self.skipTest("Not GPU test") - self._test_minimize_loss_eager(self._get_distribution_strategy()) + def testReplicaId(self, distribution): + self._test_replica_id(distribution) - def testMinimizeLossGraph(self): - soft_placement = not GPU_TEST - print("testMinimizeLossGraph soft_placement:", soft_placement) - self._test_minimize_loss_graph( - self._get_distribution_strategy(), soft_placement=soft_placement) - - def testDeviceIndex(self): - if not GPU_TEST: - self.skipTest("Not GPU test") - self._test_device_index(self._get_distribution_strategy()) - - def testReplicaId(self): - if not GPU_TEST: - self.skipTest("Not GPU test") - self._test_replica_id(self._get_distribution_strategy()) - - def testNumReplicas(self): - if not GPU_TEST: - self.skipTest("Not GPU test") - self.assertEqual(2, self._get_distribution_strategy().num_replicas) - - def testNumReplicasInSync(self): - if not GPU_TEST: - self.skipTest("Not GPU test") - self.assertEqual(2, self._get_distribution_strategy(). - num_replicas_in_sync) - - @test_util.run_in_graph_and_eager_modes - def testCallAndMergeExceptions(self): - if not GPU_TEST: - self.skipTest("Not GPU test") - self._test_call_and_merge_exceptions(self._get_distribution_strategy()) - - @test_util.run_in_graph_and_eager_modes - def testRunRegroupError(self): - - def run_fn(device_id): + def testNumReplicasInSync(self, distribution): + self.assertEqual(2, distribution.num_replicas_in_sync) + + def testCallAndMergeExceptions(self, distribution): + self._test_call_and_merge_exceptions(distribution) + + def testRunRegroupError(self, distribution): + def run_fn(): + replica_id = int(self.evaluate(_replica_id())) # Generates a list with different lengths on different devices. # Will fail in _regroup() (if more than one device). - return list(range(device_id)) - - dist = self._get_distribution_strategy() - with dist.scope(), self.assertRaises(AssertionError): - dist.call_for_each_replica(run_fn, args=(dist.worker_device_index,)) - - @test_util.run_in_graph_and_eager_modes - def testReduceToCpu(self): - if not GPU_TEST: - self.skipTest("Not GPU test") - - def run_fn(device_id): - return device_id - - dist = self._get_distribution_strategy() - with dist.scope(): - result = dist.call_for_each_replica( - run_fn, args=(dist.worker_device_index,)) - reduced = dist.reduce( - variable_scope.VariableAggregation.SUM, - result, - destinations="/device:CPU:0") - unwrapped = dist.unwrap(reduced) - self.assertEqual(1, len(unwrapped)) - expected = sum(range(len(dist.worker_devices))) - self.assertEqual(expected, self.evaluate(unwrapped[0])) - - @test_util.run_in_graph_and_eager_modes - def testReduceOnlyFirstReplicaUpdates(self): - if not GPU_TEST: - self.skipTest("Not GPU test") - - def run_fn(device_id): - return constant_op.constant(3 + 5 * device_id) - - dist = self._get_distribution_strategy() - with dist.scope(): - result = dist.call_for_each_replica( - run_fn, args=(dist.worker_device_index,)) - reduced = dist.reduce( - variable_scope.VariableAggregation.ONLY_FIRST_REPLICA, - result, - destinations="/device:CPU:0") - unwrapped = dist.unwrap(reduced) - self.assertEqual(1, len(unwrapped)) - self.assertEqual(3, self.evaluate(unwrapped[0])) - - @test_util.run_in_graph_and_eager_modes() - def testReduceToMultipleDestinations(self): - if not GPU_TEST: - self.skipTest("Not GPU test") - - devices = ["/device:GPU:0"] - if GPU_TEST: - self.assertGreater(context.num_gpus(), 0) - print(self.id().split(".")[-1], "devices:", ", ".join(devices)) - - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): - reduced = dist.reduce( - variable_scope.VariableAggregation.SUM, - 1.0, - destinations=["/device:CPU:0", "/device:GPU:0"]) - unwrapped = dist.unwrap(reduced) - self.assertEqual(2, len(unwrapped)) - self.assertEqual(1.0, self.evaluate(unwrapped[0])) + return list(range(replica_id)) + + with distribution.scope(), self.assertRaises(AssertionError): + distribution.extended.call_for_each_replica(run_fn) + + def testReduceToCpu(self, distribution): + with distribution.scope(): + result = distribution.extended.call_for_each_replica(_replica_id) + reduced = distribution.reduce(reduce_util.ReduceOp.SUM, result) + expected = sum(range(distribution.num_replicas_in_sync)) + self.assertEqual(expected, self.evaluate(reduced)) + + def testMakeInputFnIterator(self, distribution): + dataset_fn = lambda: dataset_ops.Dataset.range(10) + expected_values = [[i, i+1] for i in range(0, 10, 2)] + + input_fn = self._input_fn_to_test_input_context( + dataset_fn, + expected_num_replicas_in_sync=2, + expected_num_input_pipelines=1, + expected_input_pipeline_id=0) + iterator = distribution.make_input_fn_iterator(input_fn) + self._test_input_fn_iterator(iterator, distribution.extended.worker_devices, + expected_values) + + def testGlobalStepUpdate(self, distribution): + self._test_global_step_update(distribution) + + +def one_device_combinations(): + return combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_one_cpu, + combinations.mirrored_strategy_with_one_gpu, + combinations.core_mirrored_strategy_with_one_cpu, + combinations.core_mirrored_strategy_with_one_gpu], + mode=["graph", "eager"]) + + +class MirroredOneDeviceDistributionTest( + strategy_test_lib.DistributionTestBase, + parameterized.TestCase): + + @combinations.generate(one_device_combinations()) + def testMinimizeLoss(self, distribution): + if context.executing_eagerly(): + self._test_minimize_loss_eager(distribution) + else: + self._test_minimize_loss_graph(distribution) + + @combinations.generate(one_device_combinations()) + def testReplicaId(self, distribution): + self._test_replica_id(distribution) + + @combinations.generate(one_device_combinations()) + def testCallAndMergeExceptions(self, distribution): + self._test_call_and_merge_exceptions(distribution) +class MirroredStrategyVariableCreatorStackTest( + test.TestCase, parameterized.TestCase): + + @combinations.generate(combinations.combine( + distribution=[combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=["graph"])) + def testCreatorStacksAreThreadLocal(self, distribution): + def model_fn(): + replica_id_str = str(self.evaluate(_replica_id())) + + def thread_creator_fn(next_creator, *args, **kwargs): + return next_creator(*args, **kwargs) + ":thread_" + replica_id_str + + with variable_scope.variable_creator_scope(thread_creator_fn): + # Create a variable in this scope. + v = variable_scope.variable(1.0) + + # This will pause the current thread, and execute the other thread. + ds_context.get_replica_context().merge_call(lambda _: _) + return v + + def main_thread_creator(next_creator, *args, **kwargs): + # We are not using the underlying next_creator for test purposes. + del next_creator, args, kwargs + return "main_thread" + + with context.graph_mode(), \ + distribution.scope(), \ + variable_scope.variable_creator_scope(main_thread_creator): + result = distribution.extended.call_for_each_replica(model_fn) + result = distribution.unwrap(result) + expected = ["main_thread:thread_0", "main_thread:thread_1"] + self.assertEqual(expected, result) + + +@combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=["graph", "eager"])) class MirroredStrategyVariableCreationTest(test.TestCase): - config = config_pb2.ConfigProto() - config.allow_soft_placement = True + # TODO(priyag): Modify more tests to use this helper and check more + # properties. + def _test_mv_properties(self, var, name): + self.assertIsInstance(var, values.MirroredVariable) + self.assertEqual(name, var.name) + for d in var.devices: + self.assertEqual(d, var.get(d).device) + + def testVariableInFuncGraph(self, distribution): + def model_fn(): + v = variable_scope.variable(2.0, name="bar") + ds_context.get_replica_context().merge_call(lambda _: _) + return v - def _skip_eager_if_gpus_less_than(self, num_gpus): - if context.num_gpus() < num_gpus and context.executing_eagerly(): - self.skipTest("Enough GPUs not available for this test in eager mode.") + with func_graph.FuncGraph("fg").as_default(), distribution.scope(): + v1 = variable_scope.variable(1.0, name="foo") + v2 = distribution.extended.call_for_each_replica(model_fn) - @test_util.run_in_graph_and_eager_modes(config=config) - def testSingleVariable(self): - self._skip_eager_if_gpus_less_than(1) + self._test_mv_properties(v1, "foo:0") + self._test_mv_properties(v2, "bar:0") + def testSingleVariable(self, distribution): def model_fn(): # This variable should be created only once across the threads because of - # special variable_creator functions used by `dist.call_for_each_replica`. + # special variable_creator functions used by + # `distribution.extended.call_for_each_replica`. v = variable_scope.variable(1.0, name="foo") - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) return v - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - result = dist.call_for_each_replica(model_fn) - self.assertIsInstance(result, values.MirroredVariable) - self.assertEquals("foo:0", result.name) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testUnnamedVariable(self): - self._skip_eager_if_gpus_less_than(1) + with distribution.scope(): + result = distribution.extended.call_for_each_replica(model_fn) + self._test_mv_properties(result, "foo:0") + def testUnnamedVariable(self, distribution): def model_fn(): v = variable_scope.variable(1.0) - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) return v - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - result = dist.call_for_each_replica(model_fn) - self.assertIsInstance(result, values.MirroredVariable) - # Default name of "Variable" will be used. - self.assertEquals("Variable:0", result.name) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testMultipleVariables(self): - self._skip_eager_if_gpus_less_than(1) + with distribution.scope(): + result = distribution.extended.call_for_each_replica(model_fn) + self._test_mv_properties(result, "Variable:0") + def testMultipleVariables(self, distribution): def model_fn(): vs = [] for i in range(5): vs.append(variable_scope.variable(1.0, name="foo" + str(i))) - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) return vs - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - result = dist.call_for_each_replica(model_fn) + with distribution.scope(): + result = distribution.extended.call_for_each_replica(model_fn) for i, v in enumerate(result): - self.assertIsInstance(v, values.MirroredVariable) - self.assertEquals("foo" + str(i) + ":0", v.name) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testMultipleVariablesWithSameCanonicalName(self): - self._skip_eager_if_gpus_less_than(1) + self._test_mv_properties(v, "foo" + str(i) + ":0") + def testMultipleVariablesWithSameCanonicalName(self, distribution): def model_fn(): vs = [] vs.append(variable_scope.variable(1.0, name="foo/bar")) vs.append(variable_scope.variable(1.0, name="foo_1/bar")) vs.append(variable_scope.variable(1.0, name="foo_1/bar_1")) vs.append(variable_scope.variable(1.0, name="foo/bar_1")) - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) return vs - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - result = dist.call_for_each_replica(model_fn) + with distribution.scope(): + result = distribution.extended.call_for_each_replica(model_fn) for v in result: self.assertIsInstance(v, values.MirroredVariable) - self.assertEquals(4, len(result)) - self.assertEquals("foo/bar:0", result[0].name) - self.assertEquals("foo_1/bar:0", result[1].name) - self.assertEquals("foo_1/bar_1:0", result[2].name) - self.assertEquals("foo/bar_1:0", result[3].name) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testVariableWithSameCanonicalNameAcrossThreads(self): - self._skip_eager_if_gpus_less_than(1) - - def model_fn(device_id): - v = variable_scope.variable(1.0, name="foo_" + str(device_id)) - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) - return v + self.assertEqual(4, len(result)) + self.assertEqual("foo/bar:0", result[0].name) + self.assertEqual("foo_1/bar:0", result[1].name) + self.assertEqual("foo_1/bar_1:0", result[2].name) + self.assertEqual("foo/bar_1:0", result[3].name) - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) + def testVariableWithSameCanonicalNameAcrossThreads(self, distribution): + def model_fn(): + replica_id = self.evaluate(_replica_id()) + v = variable_scope.variable(1.0, name="foo_" + str(replica_id)) + ds_context.get_replica_context().merge_call(lambda _: _) + return v - with dist.scope(): - result = dist.call_for_each_replica( - model_fn, args=(dist.worker_device_index,)) + with distribution.scope(): + result = distribution.extended.call_for_each_replica(model_fn) self.assertIsInstance(result, values.MirroredVariable) # The resulting mirrored variable will use the name from the first device. - self.assertEquals("foo_0:0", result.name) + self.assertEqual("foo_0:0", result.name) - @test_util.run_in_graph_and_eager_modes(config=config) - def testWithLayers(self): - self._skip_eager_if_gpus_less_than(1) + def testWithLayers(self, distribution): def model_fn(features): with variable_scope.variable_scope("common"): layer1 = core.Dense(1) @@ -305,17 +289,14 @@ class MirroredStrategyVariableCreationTest(test.TestCase): layer2 = core.Dense(1) layer2(features) # This will pause the current thread, and execute the other thread. - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) layer3 = core.Dense(1) layer3(features) return [(layer1.kernel, layer1.bias), (layer2.kernel, layer2.bias), (layer3.kernel, layer3.bias)] - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - ds = dist.distribute_dataset( + ds = distribution.distribute_dataset( lambda: dataset_ops.Dataset.from_tensors([[1.]]).repeat(10)) if context.executing_eagerly(): iterator = ds.make_one_shot_iterator() @@ -325,26 +306,23 @@ class MirroredStrategyVariableCreationTest(test.TestCase): features = iterator.get_next() - with dist.scope(): - result = dist.call_for_each_replica(model_fn, args=(features,)) + with distribution.scope(): + result = distribution.extended.call_for_each_replica( + model_fn, args=(features,)) suffixes = ["", "_1", "_2"] for (kernel, bias), suffix in zip(result, suffixes): self.assertIsInstance(kernel, values.MirroredVariable) - self.assertEquals("common/dense" + suffix + "/kernel:0", kernel.name) + self.assertEqual("common/dense" + suffix + "/kernel:0", kernel.name) self.assertIsInstance(bias, values.MirroredVariable) - self.assertEquals("common/dense" + suffix + "/bias:0", bias.name) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testWithVariableAndVariableScope(self): - self._skip_eager_if_gpus_less_than(1) + self.assertEqual("common/dense" + suffix + "/bias:0", bias.name) + def testWithVariableAndVariableScope(self, distribution): def model_fn(): v0 = variable_scope.variable(1.0, name="var0", aggregation=None) with variable_scope.variable_scope("common"): v1 = variable_scope.variable(1.0, name="var1") # This will pause the current thread, and execute the other thread. - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) v2 = variable_scope.variable( 1.0, name="var2", @@ -358,37 +336,31 @@ class MirroredStrategyVariableCreationTest(test.TestCase): return v0, v1, v2, v3 - devices = ["/device:CPU:0", "/device:GPU:0"] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): + with distribution.scope(): v = variable_scope.variable(1.0, name="var-main0") - self.assertEquals("var-main0:0", v.name) + self.assertEqual("var-main0:0", v.name) - result = dist.call_for_each_replica(model_fn) - self.assertEquals(4, len(result)) + result = distribution.extended.call_for_each_replica(model_fn) + self.assertEqual(4, len(result)) v0, v1, v2, v3 = result self.assertIsInstance(v0, values.MirroredVariable) - self.assertEquals("var0:0", v0.name) + self.assertEqual("var0:0", v0.name) self.assertIsInstance(v1, values.MirroredVariable) - self.assertEquals("common/var1:0", v1.name) + self.assertEqual("common/var1:0", v1.name) self.assertIsInstance(v2, values.ReplicaLocalVariable) - self.assertEquals("common/var2:0", v2.name) - self.assertEquals(variable_scope.VariableAggregation.SUM, v2.aggregation) + self.assertEqual("common/var2:0", v2.name) + self.assertEqual(variable_scope.VariableAggregation.SUM, v2.aggregation) self.assertIsInstance(v3, values.MirroredVariable) - self.assertEquals("common/var3:0", v3.name) - self.assertEquals(variable_scope.VariableAggregation.MEAN, v3.aggregation) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testWithGetVariableAndVariableScope(self): - self._skip_eager_if_gpus_less_than(1) + self.assertEqual("common/var3:0", v3.name) + self.assertEqual(variable_scope.VariableAggregation.MEAN, v3.aggregation) + def testWithGetVariableAndVariableScope(self, distribution): def model_fn(): v0 = variable_scope.get_variable("var0", [1]) with variable_scope.variable_scope("common"): v1 = variable_scope.get_variable("var1", [1]) # This will pause the current thread, and execute the other thread. - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) v2 = variable_scope.get_variable( "var2", [1], synchronization=variable_scope.VariableSynchronization.ON_READ, @@ -400,33 +372,28 @@ class MirroredStrategyVariableCreationTest(test.TestCase): return v0, v1, v2, v3 - devices = ["/device:CPU:0", "/device:GPU:0"] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): + with distribution.scope(): with variable_scope.variable_scope("main"): v = variable_scope.get_variable("var-main0", [1]) - self.assertEquals("main/var-main0:0", v.name) + self.assertEqual("main/var-main0:0", v.name) - result = dist.call_for_each_replica(model_fn) - self.assertEquals(4, len(result)) + result = distribution.extended.call_for_each_replica(model_fn) + self.assertEqual(4, len(result)) v0, v1, v2, v3 = result self.assertIsInstance(v0, values.MirroredVariable) - self.assertEquals("main/var0:0", v0.name) + self.assertEqual("main/var0:0", v0.name) self.assertIsInstance(v1, values.MirroredVariable) - self.assertEquals("main/common/var1:0", v1.name) + self.assertEqual("main/common/var1:0", v1.name) self.assertIsInstance(v2, values.ReplicaLocalVariable) - self.assertEquals("main/common/var2:0", v2.name) - self.assertEquals(variable_scope.VariableAggregation.SUM, - v2.aggregation) + self.assertEqual("main/common/var2:0", v2.name) + self.assertEqual(variable_scope.VariableAggregation.SUM, + v2.aggregation) self.assertIsInstance(v3, values.MirroredVariable) - self.assertEquals("main/common/var3:0", v3.name) - self.assertEquals(variable_scope.VariableAggregation.MEAN, - v3.aggregation) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testOnlyFirstReplicaUpdatesVariables(self): - self._skip_eager_if_gpus_less_than(1) + self.assertEqual("main/common/var3:0", v3.name) + self.assertEqual(variable_scope.VariableAggregation.MEAN, + v3.aggregation) + def testOnlyFirstReplicaUpdatesVariables(self, distribution): def create_fn(): aggregation = variable_scope.VariableAggregation.ONLY_FIRST_REPLICA v0 = variable_scope.variable( @@ -442,71 +409,73 @@ class MirroredStrategyVariableCreationTest(test.TestCase): return v0, v1 devices = ["/device:GPU:0", "/device:CPU:0"] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): - v0, v1 = dist.call_for_each_replica(create_fn) + with distribution.scope(): + v0, v1 = distribution.extended.call_for_each_replica(create_fn) self.evaluate(v0.initializer) self.assertEqual(2.0, self.evaluate(v0.get(devices[0]))) self.assertEqual(2.0, self.evaluate(v0.get(devices[1]))) - self.assertEqual(2.0, self.evaluate(dist.read_var(v0))) + self.assertEqual(2.0, self.evaluate(distribution.extended.read_var(v0))) self.evaluate(v1.initializer) self.assertEqual(3.0, self.evaluate(v1.get(devices[0]))) self.assertEqual(3.0, self.evaluate(v1.get(devices[1]))) - self.assertEqual(3.0, self.evaluate(dist.read_var(v1))) + self.assertEqual(3.0, self.evaluate(distribution.extended.read_var(v1))) + + def replica_id_plus_one(): + return math_ops.cast(_replica_id() + 1, dtype=dtypes.float32) # Update using the assign_add member function. - def update_member_fn(device_id): - update0 = v0.assign_add(5.0 * (device_id + 1)) - update1 = v1.assign_add(7.0 * (device_id + 1)) + def update_member_fn(): + update0 = v0.assign_add(5.0 * replica_id_plus_one()) + update1 = v1.assign_add(7.0 * replica_id_plus_one()) return update0, update1 - update0a, update1a = dist.call_for_each_replica( - update_member_fn, args=(dist.worker_device_index,)) + update0a, update1a = distribution.extended.call_for_each_replica( + update_member_fn) # Update "sync on read" variable. - self.evaluate(dist.group(update0a)) + self.evaluate(distribution.group(update0a)) self.assertEqual(2.0 + 5.0, self.evaluate(v0.get(devices[0]))) # Writes are not synchronized for "sync on read" variables, # so device[1] can end up with a different value. self.assertEqual(2.0 + 2*5.0, self.evaluate(v0.get(devices[1]))) # Always reads from device 0. - self.assertEqual(2.0 + 5.0, self.evaluate(dist.read_var(v0))) + self.assertEqual(2.0 + 5.0, self.evaluate( + distribution.extended.read_var(v0))) # Update "sync on write" variable. - self.evaluate(dist.group(update1a)) + self.evaluate(distribution.group(update1a)) self.assertEqual(3.0 + 7.0, self.evaluate(v1.get(devices[0]))) # Writes are synchronized for v1, only the argument to assign_add on # device[0] is used. self.assertEqual(3.0 + 7.0, self.evaluate(v1.get(devices[1]))) - self.assertEqual(3.0 + 7.0, self.evaluate(dist.read_var(v1))) + self.assertEqual(3.0 + 7.0, self.evaluate( + distribution.extended.read_var(v1))) # Update using state_ops.assign_add global function. - def update_state_ops_fn(device_id): - update0 = state_ops.assign_add(v0, 11.0 * (device_id + 1)) - update1 = state_ops.assign_add(v1, 13.0 * (device_id + 1)) + def update_state_ops_fn(): + update0 = state_ops.assign_add(v0, 11.0 * replica_id_plus_one()) + update1 = state_ops.assign_add(v1, 13.0 * replica_id_plus_one()) return update0, update1 - update0b, update1b = dist.call_for_each_replica( - update_state_ops_fn, args=(dist.worker_device_index,)) - self.evaluate(dist.group(update0b)) + update0b, update1b = distribution.extended.call_for_each_replica( + update_state_ops_fn) + self.evaluate(distribution.group(update0b)) # Update "sync on read" variable. self.assertEqual(2.0 + 5.0 + 11.0, self.evaluate(v0.get(devices[0]))) self.assertEqual(2.0 + 2*5.0 + 2*11.0, self.evaluate(v0.get(devices[1]))) - self.assertEqual(2.0 + 5.0 + 11.0, self.evaluate(dist.read_var(v0))) + self.assertEqual(2.0 + 5.0 + 11.0, self.evaluate( + distribution.extended.read_var(v0))) # Update "sync on write" variable. - self.evaluate(dist.group(update1b)) + self.evaluate(distribution.group(update1b)) self.assertEqual(3.0 + 7.0 + 13.0, self.evaluate(v1.get(devices[0]))) self.assertEqual(3.0 + 7.0 + 13.0, self.evaluate(v1.get(devices[1]))) - self.assertEqual(3.0 + 7.0 + 13.0, self.evaluate(dist.read_var(v1))) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testNoneSynchronizationWithGetVariable(self): - self._skip_eager_if_gpus_less_than(1) - devices = ["/device:CPU:0", "/device:GPU:0"] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): + self.assertEqual(3.0 + 7.0 + 13.0, self.evaluate( + distribution.extended.read_var(v1))) + + def testNoneSynchronizationWithGetVariable(self, distribution): + with distribution.scope(): with self.assertRaisesRegexp( ValueError, "`NONE` variable synchronization mode is not " "supported with `Mirrored` distribution strategy. Please change " @@ -515,12 +484,8 @@ class MirroredStrategyVariableCreationTest(test.TestCase): "v", [1], synchronization=variable_scope.VariableSynchronization.NONE) - @test_util.run_in_graph_and_eager_modes(config=config) - def testNoneSynchronizationWithVariable(self): - self._skip_eager_if_gpus_less_than(1) - devices = ["/device:CPU:0", "/device:GPU:0"] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): + def testNoneSynchronizationWithVariable(self, distribution): + with distribution.scope(): with self.assertRaisesRegexp( ValueError, "`NONE` variable synchronization mode is not " "supported with `Mirrored` distribution strategy. Please change " @@ -530,23 +495,15 @@ class MirroredStrategyVariableCreationTest(test.TestCase): name="v", synchronization=variable_scope.VariableSynchronization.NONE) - @test_util.run_in_graph_and_eager_modes(config=config) - def testInvalidSynchronizationWithVariable(self): - self._skip_eager_if_gpus_less_than(1) - devices = ["/device:CPU:0", "/device:GPU:0"] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): + def testInvalidSynchronizationWithVariable(self, distribution): + with distribution.scope(): with self.assertRaisesRegexp( ValueError, "Invalid variable synchronization mode: Invalid for " "variable: v"): variable_scope.variable(1.0, name="v", synchronization="Invalid") - @test_util.run_in_graph_and_eager_modes(config=config) - def testInvalidAggregationWithGetVariable(self): - self._skip_eager_if_gpus_less_than(1) - devices = ["/device:CPU:0", "/device:GPU:0"] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): + def testInvalidAggregationWithGetVariable(self, distribution): + with distribution.scope(): with self.assertRaisesRegexp( ValueError, "Invalid variable aggregation mode: invalid for " "variable: v"): @@ -555,12 +512,8 @@ class MirroredStrategyVariableCreationTest(test.TestCase): synchronization=variable_scope.VariableSynchronization.ON_WRITE, aggregation="invalid") - @test_util.run_in_graph_and_eager_modes(config=config) - def testInvalidAggregationWithVariable(self): - self._skip_eager_if_gpus_less_than(1) - devices = ["/device:CPU:0", "/device:GPU:0"] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): + def testInvalidAggregationWithVariable(self, distribution): + with distribution.scope(): with self.assertRaisesRegexp( ValueError, "Invalid variable aggregation mode: invalid for " "variable: v"): @@ -570,55 +523,28 @@ class MirroredStrategyVariableCreationTest(test.TestCase): synchronization=variable_scope.VariableSynchronization.ON_WRITE, aggregation="invalid") - @test_util.run_in_graph_and_eager_modes(config=config) - def testThreeDevices(self): - self._skip_eager_if_gpus_less_than(2) - - def model_fn(): - v = variable_scope.variable(1.0, name="foo") - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) - return v - - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:GPU:1", "/device:CPU:0"]) - - with dist.scope(): - result = dist.call_for_each_replica(model_fn) - self.assertIsInstance(result, values.MirroredVariable) - self.assertEquals("foo:0", result.name) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testNonMatchingVariableCreation(self): - self._skip_eager_if_gpus_less_than(1) - + def testNonMatchingVariableCreation(self, distribution): def model_fn(name): v = variable_scope.variable(1.0, name=name) - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) return v - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): + with distribution.scope(): names = values.DistributedValues({ "/device:CPU:0": "foo", "/device:GPU:0": "bar" }) with self.assertRaises(RuntimeError): - _ = dist.call_for_each_replica(model_fn, args=(names,)) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testReplicaLocalVariable(self): - self._skip_eager_if_gpus_less_than(1) + _ = distribution.extended.call_for_each_replica(model_fn, args=(names,)) + def testReplicaLocalVariable(self, distribution): all_v_sum = {} all_v_mean = {} components_sum = {} components_mean = {} - def model_fn(device_id): + def model_fn(): + replica_id = self.evaluate(_replica_id()) v_sum = variable_scope.variable( 1.0, synchronization=variable_scope.VariableSynchronization.ON_READ, @@ -629,26 +555,22 @@ class MirroredStrategyVariableCreationTest(test.TestCase): aggregation=variable_scope.VariableAggregation.MEAN) self.assertTrue(isinstance(v_sum, values.ReplicaLocalVariable)) self.assertTrue(isinstance(v_mean, values.ReplicaLocalVariable)) - updates = [v_sum.assign_add(2.0 + device_id), - v_mean.assign(6.0 * device_id)] - all_v_sum[device_id] = v_sum - all_v_mean[device_id] = v_mean + updates = [v_sum.assign_add(2.0 + replica_id), + v_mean.assign(6.0 * replica_id)] + all_v_sum[replica_id] = v_sum + all_v_mean[replica_id] = v_mean c_sum = v_sum.get() c_mean = v_mean.get() - components_sum[device_id] = c_sum - components_mean[device_id] = c_mean + components_sum[replica_id] = c_sum + components_mean[replica_id] = c_mean self.assertIsNot(v_sum, c_sum) self.assertIsNot(v_mean, c_mean) return updates, v_sum, v_mean, c_sum, c_mean - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): + with distribution.scope(): # Create "sum" and "mean" versions of ReplicaLocalVariables. ret_ops, ret_v_sum, ret_v_mean, regrouped_sum, regrouped_mean = ( - dist.call_for_each_replica( - model_fn, args=(dist.worker_device_index,))) + distribution.extended.call_for_each_replica(model_fn)) # Should see the same wrapping instance in all replicas. self.assertIs(all_v_sum[0], ret_v_sum) self.assertIs(all_v_mean[0], ret_v_mean) @@ -663,10 +585,10 @@ class MirroredStrategyVariableCreationTest(test.TestCase): # Apply updates self.evaluate(variables.global_variables_initializer()) - self.evaluate([y for x in ret_ops for y in dist.unwrap(x)]) + self.evaluate([y for x in ret_ops for y in distribution.unwrap(x)]) expected_sum = 0.0 expected_mean = 0.0 - for i, d in enumerate(dist.worker_devices): + for i, d in enumerate(distribution.extended.worker_devices): # Should see different values on different devices. v_sum_value = self.evaluate(ret_v_sum.get(d).read_value()) v_mean_value = self.evaluate(ret_v_mean.get(d).read_value()) @@ -676,69 +598,125 @@ class MirroredStrategyVariableCreationTest(test.TestCase): expected = i * 6.0 self.assertEqual(expected, v_mean_value) expected_mean += expected - expected_mean /= len(dist.worker_devices) + expected_mean /= len(distribution.extended.worker_devices) # Without get(device), should return the value you get by # applying the reduction across all replicas (whether you use # read_var(), get(), or nothing). - self.assertEqual(expected_sum, self.evaluate(dist.read_var(ret_v_sum))) - self.assertEqual(expected_mean, self.evaluate(dist.read_var(ret_v_mean))) + self.assertEqual(expected_sum, self.evaluate( + distribution.extended.read_var(ret_v_sum))) + self.assertEqual(expected_mean, self.evaluate( + distribution.extended.read_var(ret_v_mean))) self.assertEqual(expected_sum, self.evaluate(ret_v_sum.get())) self.assertEqual(expected_mean, self.evaluate(ret_v_mean.get())) self.assertEqual(expected_sum, self.evaluate(ret_v_sum)) self.assertEqual(expected_mean, self.evaluate(ret_v_mean)) + # TODO(priyag): Update this test to work in eager mode as well. + def testDynamicRnnVariables(self, distribution): + def model_fn(): + inputs = constant_op.constant(2 * [2 * [[0.0, 1.0, 2.0, 3.0, 4.0]]]) + cell_fw = rnn_cell_impl.LSTMCell(300) + cell_bw = rnn_cell_impl.LSTMCell(300) + (outputs, _) = rnn.bidirectional_dynamic_rnn( + cell_fw, + cell_bw, + inputs, + dtype=dtypes.float32) + return outputs + + with context.graph_mode(), distribution.scope(): + result = distribution.extended.call_for_each_replica(model_fn) + # Two variables are created by the RNN layer. + self.assertEqual(2, len(result)) + for v in result: + self.assertIsInstance(v, values.DistributedValues) + _, v1 = distribution.unwrap(v) + self.assertStartsWith(v1._op.name, "replica_1/") + + def testReplicaLocalVariableUpdate(self, distribution): + def model_fn(): + v_sum = variable_scope.variable( + 1.0, + synchronization=variable_scope.VariableSynchronization.ON_READ, + aggregation=variable_scope.VariableAggregation.SUM) + self.assertTrue(isinstance(v_sum, values.ReplicaLocalVariable)) + return v_sum + + def update(var, value): + return var.assign(value) + + with distribution.scope(): + ret_v_sum = distribution.extended.call_for_each_replica(model_fn) + + # Initialize variables. + self.evaluate(variables.global_variables_initializer()) + # Assert that the aggregated value of the replica local vars is the sum + # of the individual values before running the update ops. + self.assertEqual(1.0, self.evaluate(ret_v_sum.get( + distribution.extended.worker_devices[0]).read_value())) + self.assertEqual(2.0, self.evaluate(ret_v_sum)) + + # Apply updates. + update_ops = distribution.extended.update( + ret_v_sum, update, args=(5.0,), group=False) + self.evaluate(update_ops) + # Assert that the aggregated value of the replica local vars is the sum + # of the individual values after running the update ops. + self.assertEqual(5.0, self.evaluate(ret_v_sum.get( + distribution.extended.worker_devices[0]).read_value())) + self.assertEqual(10.0, self.evaluate(ret_v_sum)) + + +@combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=["graph"])) +class MirroredStrategyNameScopeTest(test.TestCase): # NOTE(priyag): Names and name scopes are ignored in eager, hence we are not # testing this in eager mode. - def testNameScope(self): + def testNameScope(self, distribution): def model_fn(): with ops.name_scope("foo"): a = constant_op.constant(1.0, name="a") - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) b = constant_op.constant(1.0, name="b") return a, b - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with context.graph_mode(), dist.scope(): + with context.graph_mode(), distribution.scope(): with ops.name_scope("main"): - result = dist.call_for_each_replica(model_fn) - self.assertEquals(2, len(result)) + result = distribution.extended.call_for_each_replica(model_fn) + self.assertEqual(2, len(result)) for v, name in zip(result, ["a", "b"]): self.assertIsInstance(v, values.DistributedValues) - v0, v1 = dist.unwrap(v) - self.assertEquals("main/foo/" + name + ":0", v0.name) - self.assertEquals("main/replica_1/foo/" + name + ":0", v1.name) + v0, v1 = distribution.unwrap(v) + self.assertEqual("main/foo/" + name + ":0", v0.name) + self.assertEqual("main/replica_1/foo/" + name + ":0", v1.name) - def testWithDefaultName(self): + def testWithDefaultName(self, distribution): def model_fn(): with ops.name_scope(None, "foo"): a = constant_op.constant(1.0, name="a") - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) + ds_context.get_replica_context().merge_call(lambda _: _) b = constant_op.constant(2.0, name="b") return a, b - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with context.graph_mode(), dist.scope(): - result = dist.call_for_each_replica(model_fn) - self.assertEquals(2, len(result)) + with context.graph_mode(), distribution.scope(): + result = distribution.extended.call_for_each_replica(model_fn) + self.assertEqual(2, len(result)) for v, name in zip(result, ["a", "b"]): self.assertIsInstance(v, values.DistributedValues) - v0, v1 = dist.unwrap(v) - self.assertEquals("foo/" + name + ":0", v0.name) - self.assertEquals("replica_1/foo/" + name + ":0", v1.name) + v0, v1 = distribution.unwrap(v) + self.assertEqual("foo/" + name + ":0", v0.name) + self.assertEqual("replica_1/foo/" + name + ":0", v1.name) # variable_scope.variable() respects name scopes when creating # variables. On the other hand variable_scope.get_variable() ignores name # scopes when creating variables. We test both methods of creating variables # to make sure that we have the same variable names in both cases. - def testNameScopeWithVariable(self): + def testNameScopeWithVariable(self, distribution): def in_cross_replica(_): c = variable_scope.variable(1.0, name="c") return c @@ -746,32 +724,28 @@ class MirroredStrategyVariableCreationTest(test.TestCase): def model_fn(): b = variable_scope.variable(1.0, name="b") with ops.name_scope("foo"): - c = distribution_strategy_context.get_replica_context().merge_call( - in_cross_replica) + c = ds_context.get_replica_context().merge_call(in_cross_replica) return b, c - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with context.graph_mode(), dist.scope(): + with context.graph_mode(), distribution.scope(): with ops.name_scope("main"): a = variable_scope.variable(1.0, name="a") - result = dist.call_for_each_replica(model_fn) + result = distribution.extended.call_for_each_replica(model_fn) result_b = result[0] result_c = result[1] self.assertIsInstance(result_b, values.DistributedValues) self.assertIsInstance(result_c, values.DistributedValues) - a0, a1 = dist.unwrap(a) - b0, b1 = dist.unwrap(result_b) - c0, c1 = dist.unwrap(result_c) - self.assertEquals("main/a:0", a0.name) - self.assertEquals("main/a/replica_1:0", a1.name) - self.assertEquals("main/b:0", b0.name) - self.assertEquals("main/b/replica_1:0", b1.name) - self.assertEquals("main/foo/c:0", c0.name) - self.assertEquals("main/foo/c/replica_1:0", c1.name) - - def testNameScopeWithGetVariable(self): + a0, a1 = distribution.unwrap(a) + b0, b1 = distribution.unwrap(result_b) + c0, c1 = distribution.unwrap(result_c) + self.assertEqual("main/a:0", a0.name) + self.assertEqual("main/a/replica_1:0", a1.name) + self.assertEqual("main/b:0", b0.name) + self.assertEqual("main/b/replica_1:0", b1.name) + self.assertEqual("main/foo/c:0", c0.name) + self.assertEqual("main/foo/c/replica_1:0", c1.name) + + def testNameScopeWithGetVariable(self, distribution): def in_cross_replica(_): c = variable_scope.get_variable("c", [1]) return c @@ -779,118 +753,80 @@ class MirroredStrategyVariableCreationTest(test.TestCase): def model_fn(): b = variable_scope.get_variable("b", [1]) with ops.name_scope("foo"): - c = distribution_strategy_context.get_replica_context().merge_call( - in_cross_replica) + c = ds_context.get_replica_context().merge_call(in_cross_replica) return b, c - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with context.graph_mode(), dist.scope(): + with context.graph_mode(), distribution.scope(): with ops.name_scope("main"): a = variable_scope.get_variable("a", [1]) - result = dist.call_for_each_replica(model_fn) + result = distribution.extended.call_for_each_replica(model_fn) result_b = result[0] result_c = result[1] self.assertIsInstance(result_b, values.DistributedValues) self.assertIsInstance(result_c, values.DistributedValues) - a0, a1 = dist.unwrap(a) - b0, b1 = dist.unwrap(result_b) - c0, c1 = dist.unwrap(result_c) - self.assertEquals("a:0", a0.name) - self.assertEquals("a/replica_1:0", a1.name) - self.assertEquals("b:0", b0.name) - self.assertEquals("b/replica_1:0", b1.name) - self.assertEquals("c:0", c0.name) - self.assertEquals("c/replica_1:0", c1.name) - - def testDynamicRnnVariables(self): + a0, a1 = distribution.unwrap(a) + b0, b1 = distribution.unwrap(result_b) + c0, c1 = distribution.unwrap(result_c) + self.assertEqual("a:0", a0.name) + self.assertEqual("a/replica_1:0", a1.name) + self.assertEqual("b:0", b0.name) + self.assertEqual("b/replica_1:0", b1.name) + self.assertEqual("c:0", c0.name) + self.assertEqual("c/replica_1:0", c1.name) + + +@combinations.generate( + combinations.combine( + distribution=[ + combinations.NamedDistribution( + "Mirrored3Devices", + # pylint: disable=g-long-lambda + lambda: mirrored_strategy.MirroredStrategy( + ["/device:GPU:0", "/device:GPU:1", "/device:CPU:0"]), + required_gpus=2), + combinations.NamedDistribution( + "CoreMirrored3Devices", + # pylint: disable=g-long-lambda + lambda: mirrored_strategy.CoreMirroredStrategy( + ["/device:GPU:0", "/device:GPU:1", "/device:CPU:0"]), + required_gpus=2) + ], + mode=["graph", "eager"])) +class MirroredThreeDeviceDistributionTest( + strategy_test_lib.DistributionTestBase, + parameterized.TestCase): + + def testThreeDevices(self, distribution): def model_fn(): - inputs = constant_op.constant(2 * [2 * [[0.0, 1.0, 2.0, 3.0, 4.0]]]) - cell_fw = rnn_cell_impl.LSTMCell(300) - cell_bw = rnn_cell_impl.LSTMCell(300) - (outputs, _) = rnn.bidirectional_dynamic_rnn( - cell_fw, - cell_bw, - inputs, - dtype=dtypes.float32) - return outputs - - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with context.graph_mode(), dist.scope(): - result = dist.call_for_each_replica(model_fn) - # Two variables are created by the RNN layer. - self.assertEquals(2, len(result)) - for v in result: - self.assertIsInstance(v, values.DistributedValues) - _, v1 = dist.unwrap(v) - self.assertStartsWith(v1.name, "replica_1/") - - @test_util.run_in_graph_and_eager_modes(config=config) - def testReplicaLocalVariableUpdate(self): - with context.graph_mode(): - - def model_fn(): - v_sum = variable_scope.variable( - 1.0, - synchronization=variable_scope.VariableSynchronization.ON_READ, - aggregation=variable_scope.VariableAggregation.SUM) - self.assertTrue(isinstance(v_sum, values.ReplicaLocalVariable)) - return v_sum - - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:GPU:1"]) - - def update(var, value): - return var.assign(value) - - with dist.scope(): - ret_v_sum = dist.call_for_each_replica(model_fn) - update_ops = dist.update(ret_v_sum, update, 5.0, grouped=False) - - # Initialize variables. - self.evaluate(variables.global_variables_initializer()) - # Assert that the aggregated value of the replica local vars is the sum - # of the individual values before running the update ops. - self.assertEquals(1.0, self.evaluate( - ret_v_sum.get(dist._devices[0]).read_value())) - self.assertEquals(2.0, self.evaluate(ret_v_sum)) + v = variable_scope.variable(1.0, name="foo") + ds_context.get_replica_context().merge_call(lambda _: _) + return v - # Apply updates. - self.evaluate(update_ops) - # Assert that the aggregated value of the replica local vars is the sum - # of the individual values after running the update ops. - self.assertEquals(5.0, self.evaluate( - ret_v_sum.get(dist._devices[0]).read_value())) - self.assertEquals(10.0, self.evaluate(ret_v_sum)) + with distribution.scope(): + result = distribution.extended.call_for_each_replica(model_fn) + self.assertIsInstance(result, values.MirroredVariable) + self.assertEqual("foo:0", result.name) +@combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=["graph", "eager"])) class MirroredVariableUpdateTest(test.TestCase): # The following tests check assign, assign_add and assign_sub on Mirrored # variables in replica and cross replica context. - config = config_pb2.ConfigProto() - config.allow_soft_placement = True - - def _skip_eager_if_gpus_less_than(self, num_gpus): - if context.num_gpus() < num_gpus and context.executing_eagerly(): - self.skipTest("Enough GPUs not available for this test in eager mode.") - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignMirroredVarReplicaContextWithoutAggregationType(self): + def testAssignMirroredVarReplicaContextWithoutAggregationType(self, + distribution): # Test that we always have an aggregation type set on the mirrored variable # if we assign to it in replica mode. - self._skip_eager_if_gpus_less_than(1) def var_fn(): v = variable_scope.variable(1.0, name="foo") return v - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) @@ -900,23 +836,19 @@ class MirroredVariableUpdateTest(test.TestCase): with self.assertRaisesRegexp( ValueError, "You must specify an aggregation method to update a " "MirroredVariable in Replica Context."): - self.evaluate(dist.unwrap(dist.call_for_each_replica(model_fn))) + self.evaluate(distribution.unwrap( + distribution.extended.call_for_each_replica(model_fn))) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignMirroredVarReplicaContextWithSum(self): + def testAssignMirroredVarReplicaContextWithSum(self, distribution): # Test that we don't reduce a non-per-replica value with the "sum" # aggregation type. - self._skip_eager_if_gpus_less_than(1) def var_fn(): v = variable_scope.variable( 1.0, name="foo", aggregation=variable_scope.VariableAggregation.SUM) return v - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) @@ -925,219 +857,184 @@ class MirroredVariableUpdateTest(test.TestCase): with self.assertRaisesRegexp( ValueError, "A non-DistributedValues value 5.0 cannot be reduced " - "with the given aggregation VariableAggregation.SUM."): - self.evaluate(dist.unwrap(dist.call_for_each_replica(model_fn))) + "with the given reduce op ReduceOp.SUM."): + self.evaluate(distribution.unwrap( + distribution.extended.call_for_each_replica(model_fn))) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignMirroredVarCrossDeviceContext(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignMirroredVarCrossDeviceContext(self, distribution): def var_fn(): return variable_scope.variable(1.0, name="foo") - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) - self.assertEquals(1.0, self.evaluate(mirrored_var)) + self.assertEqual(1.0, self.evaluate(mirrored_var)) mirrored_var_result = self.evaluate(mirrored_var.assign(6.0)) - self.assertEquals(6.0, mirrored_var_result) + self.assertEqual(6.0, mirrored_var_result) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignMirroredVarReplicaContext(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignMirroredVarReplicaContext(self, distribution): def var_fn(): return variable_scope.variable( 1.0, name="foo", aggregation=variable_scope.VariableAggregation.MEAN) - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) - self.assertEquals(1.0, self.evaluate(mirrored_var)) + self.assertEqual(1.0, self.evaluate(mirrored_var)) def model_fn(): value = math_ops.cast( - distribution_strategy_context.get_replica_context().replica_id, + ds_context.get_replica_context().replica_id_in_sync_group, mirrored_var.dtype) return mirrored_var.assign(value) - self.evaluate(dist.unwrap(dist.call_for_each_replica(model_fn))) - self.assertEquals(0.5, self.evaluate(mirrored_var)) + self.evaluate(distribution.unwrap( + distribution.extended.call_for_each_replica(model_fn))) + self.assertEqual(0.5, self.evaluate(mirrored_var)) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignMirroredVarReplicaContextWithSingleValue(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignMirroredVarReplicaContextWithSingleValue(self, distribution): def var_fn(): return variable_scope.variable( 1.0, name="foo", aggregation=variable_scope.VariableAggregation.MEAN) - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) - self.assertEquals(1.0, self.evaluate(mirrored_var)) + self.assertEqual(1.0, self.evaluate(mirrored_var)) def model_fn(): return mirrored_var.assign(5.0) - self.evaluate(dist.unwrap(dist.call_for_each_replica(model_fn))) - self.assertEquals(5.0, self.evaluate(mirrored_var)) + self.evaluate(distribution.unwrap( + distribution.extended.call_for_each_replica(model_fn))) + self.assertEqual(5.0, self.evaluate(mirrored_var)) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignAddMirroredVarCrossDeviceContext(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignAddMirroredVarCrossDeviceContext(self, distribution): def var_fn(): return variable_scope.variable(1.0, name="foo") - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) - self.assertEquals(1.0, self.evaluate(mirrored_var)) + self.assertEqual(1.0, self.evaluate(mirrored_var)) # read_value == True mirrored_var_result = self.evaluate( mirrored_var.assign_add(6.0, read_value=True)) - self.assertEquals(7.0, mirrored_var_result) - self.assertEquals(7.0, self.evaluate(mirrored_var.get("/device:CPU:0"))) - self.assertEquals(7.0, self.evaluate(mirrored_var.get("/device:GPU:0"))) + self.assertEqual(7.0, mirrored_var_result) + self.assertEqual(7.0, self.evaluate(mirrored_var.get("/device:CPU:0"))) + self.assertEqual(7.0, self.evaluate(mirrored_var.get("/device:GPU:0"))) # read_value == False self.evaluate(mirrored_var.assign_add(2.0, read_value=False)) - self.assertEquals(9.0, self.evaluate(mirrored_var.get("/device:CPU:0"))) - self.assertEquals(9.0, self.evaluate(mirrored_var.get("/device:GPU:0"))) + self.assertEqual(9.0, self.evaluate(mirrored_var.get("/device:CPU:0"))) + self.assertEqual(9.0, self.evaluate(mirrored_var.get("/device:GPU:0"))) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignAddMirroredVarReplicaContext(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignAddMirroredVarReplicaContext(self, distribution): def var_fn(): return variable_scope.variable( 1.0, name="foo", aggregation=variable_scope.VariableAggregation.MEAN) - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) - self.assertEquals(1.0, self.evaluate(mirrored_var)) + self.assertEqual(1.0, self.evaluate(mirrored_var)) def model_fn(): value = math_ops.cast( - distribution_strategy_context.get_replica_context().replica_id, + ds_context.get_replica_context().replica_id_in_sync_group, mirrored_var.dtype) return mirrored_var.assign_add(value) - self.evaluate(dist.unwrap(dist.call_for_each_replica(model_fn))) - self.assertEquals(1.5, self.evaluate(mirrored_var)) + self.evaluate(distribution.unwrap( + distribution.extended.call_for_each_replica(model_fn))) + self.assertEqual(1.5, self.evaluate(mirrored_var)) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignAddMirroredVarReplicaContextWithSingleValue(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignAddMirroredVarReplicaContextWithSingleValue(self, distribution): def var_fn(): return variable_scope.variable( 1.0, name="foo", aggregation=variable_scope.VariableAggregation.MEAN) - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) - self.assertEquals(1.0, self.evaluate(mirrored_var)) + self.assertEqual(1.0, self.evaluate(mirrored_var)) def model_fn(): return mirrored_var.assign_add(5.0) - self.evaluate(dist.unwrap(dist.call_for_each_replica(model_fn))) - self.assertEquals(6.0, self.evaluate(mirrored_var)) + self.evaluate(distribution.unwrap( + distribution.extended.call_for_each_replica(model_fn))) + self.assertEqual(6.0, self.evaluate(mirrored_var)) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignSubMirroredVarCrossDeviceContext(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignSubMirroredVarCrossDeviceContext(self, distribution): def var_fn(): return variable_scope.variable(5.0, name="foo") - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) - self.assertEquals(5.0, self.evaluate(mirrored_var)) + self.assertEqual(5.0, self.evaluate(mirrored_var)) mirrored_var_result = self.evaluate(mirrored_var.assign_sub(2.0)) - self.assertEquals(3.0, mirrored_var_result) - self.assertEquals(3.0, self.evaluate(mirrored_var.get("/device:GPU:0"))) - self.assertEquals(3.0, self.evaluate(mirrored_var.get("/device:CPU:0"))) + self.assertEqual(3.0, mirrored_var_result) + self.assertEqual(3.0, self.evaluate(mirrored_var.get("/device:GPU:0"))) + self.assertEqual(3.0, self.evaluate(mirrored_var.get("/device:CPU:0"))) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignSubMirroredVarReplicaContext(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignSubMirroredVarReplicaContext(self, distribution): def var_fn(): return variable_scope.variable( 5.0, name="foo", aggregation=variable_scope.VariableAggregation.MEAN) - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) - self.assertEquals(5.0, self.evaluate(mirrored_var)) + self.assertEqual(5.0, self.evaluate(mirrored_var)) def model_fn(): value = math_ops.cast( - distribution_strategy_context.get_replica_context().replica_id, + ds_context.get_replica_context().replica_id_in_sync_group, mirrored_var.dtype) return mirrored_var.assign_sub(value) - self.evaluate(dist.unwrap(dist.call_for_each_replica(model_fn))) - self.assertEquals(4.5, self.evaluate(mirrored_var)) + self.evaluate(distribution.unwrap( + distribution.extended.call_for_each_replica(model_fn))) + self.assertEqual(4.5, self.evaluate(mirrored_var)) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignSubMirroredVarReplicaContextWithSingleValue(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignSubMirroredVarReplicaContextWithSingleValue(self, distribution): def var_fn(): return variable_scope.variable( 5.0, name="foo", aggregation=variable_scope.VariableAggregation.MEAN) - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.evaluate(variables.global_variables_initializer()) - self.assertEquals(5.0, self.evaluate(mirrored_var)) + self.assertEqual(5.0, self.evaluate(mirrored_var)) def model_fn(): return mirrored_var.assign_sub(1.0) - self.evaluate(dist.unwrap(dist.call_for_each_replica(model_fn))) - self.assertEquals(4.0, self.evaluate(mirrored_var)) + self.evaluate(distribution.unwrap( + distribution.extended.call_for_each_replica(model_fn))) + self.assertEqual(4.0, self.evaluate(mirrored_var)) +@combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=["graph", "eager"])) class MirroredAndReplicaLocalVariableInitializerTest(test.TestCase): - config = config_pb2.ConfigProto() - config.allow_soft_placement = True - def testAssignMirroredVarInitializer(self): + def testAssignMirroredVarInitializer(self, distribution): # This test is not eager compatible since in eager variables are initialized # upon construction instead of once the initialization op is run. with context.graph_mode(): @@ -1145,17 +1042,14 @@ class MirroredAndReplicaLocalVariableInitializerTest(test.TestCase): v = variable_scope.variable(1.0, name="foo") return v - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - mirrored_var = dist.call_for_each_replica(var_fn) + with distribution.scope(): + mirrored_var = distribution.extended.call_for_each_replica(var_fn) self.assertIsInstance(mirrored_var, values.MirroredVariable) self.assertFalse(self.evaluate(mirrored_var.is_initialized())) self.evaluate(mirrored_var.initializer) self.assertTrue(self.evaluate(mirrored_var.is_initialized())) - def testAssignReplicaLocalVarInitializer(self): + def testAssignReplicaLocalVarInitializer(self, distribution): # This test is not eager compatible since in eager variables are initialized # upon construction instead of once the initialization op is run. with context.graph_mode(): @@ -1167,11 +1061,9 @@ class MirroredAndReplicaLocalVariableInitializerTest(test.TestCase): self.assertTrue(isinstance(v_sum, values.ReplicaLocalVariable)) return v_sum - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - replica_local_var = dist.call_for_each_replica(model_fn) + with distribution.scope(): + replica_local_var = distribution.extended.call_for_each_replica( + model_fn) self.assertTrue(isinstance(replica_local_var, values.ReplicaLocalVariable)) self.assertFalse(self.evaluate(replica_local_var.is_initialized())) @@ -1179,17 +1071,14 @@ class MirroredAndReplicaLocalVariableInitializerTest(test.TestCase): self.assertTrue(self.evaluate(replica_local_var.is_initialized())) +@combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=["graph", "eager"])) class ReplicaLocalVariableAssignTest(test.TestCase): - config = config_pb2.ConfigProto() - config.allow_soft_placement = True - def _skip_eager_if_gpus_less_than(self, num_gpus): - if context.num_gpus() < num_gpus and context.executing_eagerly(): - self.skipTest("Not enough GPUs available for this test in eager mode.") - - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignReplicaLocalVarSumAggregation(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignReplicaLocalVarSumAggregation(self, distribution): def model_fn(): v_sum = variable_scope.variable( 1.0, @@ -1197,18 +1086,16 @@ class ReplicaLocalVariableAssignTest(test.TestCase): aggregation=variable_scope.VariableAggregation.SUM) return v_sum - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - replica_local_var = dist.call_for_each_replica(model_fn) + with distribution.scope(): + replica_local_var = distribution.extended.call_for_each_replica(model_fn) self.assertTrue(isinstance(replica_local_var, values.ReplicaLocalVariable)) self.evaluate(variables.global_variables_initializer()) # Each replica has a value of 1.0 assigned to it in replica context. # When we read the value using `read_var` we should see the SUM of each of # values on each of the replicas. - self.assertEqual(2.0, self.evaluate(dist.read_var(replica_local_var))) + self.assertEqual(2.0, self.evaluate( + distribution.read_var(replica_local_var))) # Assigning 6.0 in cross replica context will assign a value of # 6.0/num_replicas to each replica. tlv_ops = replica_local_var.assign(6.0) @@ -1216,11 +1103,10 @@ class ReplicaLocalVariableAssignTest(test.TestCase): # On reading the replica local var we should get the assigned value back. # The value on all the replicas are added before being returned by # `read_var`. - self.assertEqual(6.0, self.evaluate(dist.read_var(replica_local_var))) + self.assertEqual(6.0, self.evaluate( + distribution.read_var(replica_local_var))) - @test_util.run_in_graph_and_eager_modes(config=config) - def testAssignReplicaLocalVarMeanAggregation(self): - self._skip_eager_if_gpus_less_than(1) + def testAssignReplicaLocalVarMeanAggregation(self, distribution): def model_fn(): v_sum = variable_scope.variable( 1.0, @@ -1228,23 +1114,22 @@ class ReplicaLocalVariableAssignTest(test.TestCase): aggregation=variable_scope.VariableAggregation.MEAN) return v_sum - dist = mirrored_strategy.MirroredStrategy( - ["/device:GPU:0", "/device:CPU:0"]) - - with dist.scope(): - replica_local_var = dist.call_for_each_replica(model_fn) + with distribution.scope(): + replica_local_var = distribution.extended.call_for_each_replica(model_fn) self.assertTrue(isinstance(replica_local_var, values.ReplicaLocalVariable)) self.evaluate(variables.global_variables_initializer()) # Each replica has a value of 1.0 assigned to it in replica context. # When we read the value using `read_var` we should see the MEAN of values # on all replicas which is the value assigned in replica context. - self.assertEqual(1.0, self.evaluate(dist.read_var(replica_local_var))) + self.assertEqual(1.0, self.evaluate( + distribution.read_var(replica_local_var))) tlv_ops = replica_local_var.assign(6.0) self.evaluate(tlv_ops) # On reading the replica local var we should get the MEAN of all values # which is equal to the value assigned. - self.assertEqual(6.0, self.evaluate(dist.read_var(replica_local_var))) + self.assertEqual(6.0, self.evaluate( + distribution.read_var(replica_local_var))) class MockModel(object): @@ -1278,24 +1163,25 @@ class MiniModel(keras_training.Model): return self.fc(inputs) +@combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=["graph", "eager"])) class MirroredStrategyDefunTest(test.TestCase): - def _skip_eager_if_gpus_less_than(self, num_gpus): - if context.num_gpus() < num_gpus and context.executing_eagerly(): - self.skipTest("Not enough GPUs available for this test in eager mode.") - - def _call_and_check(self, model_fn, inputs, expected_result, defuns, - two_variables=False): + def _call_and_check(self, distribution, model_fn, inputs, expected_result, + defuns, two_variables=False): cpu_dev = device_util.canonicalize("CPU:0") gpu_dev = device_util.canonicalize("GPU:0") devices = [cpu_dev, gpu_dev] - dist = mirrored_strategy.MirroredStrategy(devices) - with dist.scope(): + with distribution.scope(): mock_model = MockModel(two_variables) self.evaluate(variables.global_variables_initializer()) - result = dist.call_for_each_replica(model_fn, args=[mock_model] + inputs) + result = distribution.extended.call_for_each_replica( + model_fn, args=[mock_model] + inputs) for device in devices: device_result = values.select_device(device, result) device_expected_result = values.select_device(device, expected_result) @@ -1307,17 +1193,15 @@ class MirroredStrategyDefunTest(test.TestCase): # call_for_each has one trace per device. To check that the expected set # of variables was accessed on each trace, we first retrieve each # device-specific graph function. - per_replica_graph_functions = dist.call_for_each_replica( - defun.get_concrete_function, args=[mock_model] + inputs) + per_replica_graph_functions = ( + distribution.extended.call_for_each_replica( + defun.get_concrete_function, args=[mock_model] + inputs)) for device in devices: graph_function = per_replica_graph_functions.get(device=device) self.assertEqual(set(mock_model.variables), set(graph_function.graph.variables)) - @test_util.run_in_graph_and_eager_modes() - def testVariableInDefun(self): - self._skip_eager_if_gpus_less_than(1) - + def testVariableInDefun(self, distribution): @function.defun def times_two(mock_model): return mock_model() @@ -1325,12 +1209,9 @@ class MirroredStrategyDefunTest(test.TestCase): def model_fn(mock_model): return times_two(mock_model) - self._call_and_check(model_fn, [], 2.5, [times_two]) - - @test_util.run_in_graph_and_eager_modes() - def testVariableInNestedDefun(self): - self._skip_eager_if_gpus_less_than(1) + self._call_and_check(distribution, model_fn, [], 2.5, [times_two]) + def testVariableInNestedDefun(self, distribution): @function.defun def times_two(mock_model): return mock_model() @@ -1342,12 +1223,10 @@ class MirroredStrategyDefunTest(test.TestCase): def model_fn(mock_model): return two_x_plus_one(mock_model) - self._call_and_check(model_fn, [], 3.5, [times_two, two_x_plus_one]) - - @test_util.run_in_graph_and_eager_modes() - def testTwoVariablesInNestedDefun(self): - self._skip_eager_if_gpus_less_than(1) + self._call_and_check(distribution, model_fn, [], 3.5, + [times_two, two_x_plus_one]) + def testTwoVariablesInNestedDefun(self, distribution): @function.defun def fn1(mock_model): return mock_model() @@ -1359,12 +1238,10 @@ class MirroredStrategyDefunTest(test.TestCase): def model_fn(mock_model): return fn2(mock_model) - self._call_and_check(model_fn, [], 5.5, [fn1, fn2], two_variables=True) - - @test_util.run_in_graph_and_eager_modes() - def testGradientTapeOverNestedDefuns(self): - self._skip_eager_if_gpus_less_than(1) + self._call_and_check(distribution, model_fn, [], 5.5, [fn1, fn2], + two_variables=True) + def testGradientTapeOverNestedDefuns(self, distribution): @function.defun def fn1(mock_model): return mock_model() @@ -1380,13 +1257,10 @@ class MirroredStrategyDefunTest(test.TestCase): [v.get() for v in mock_model.variables]) return grads - self._call_and_check(model_fn, [], [2.0, 1.0], [fn1, fn2], + self._call_and_check(distribution, model_fn, [], [2.0, 1.0], [fn1, fn2], two_variables=True) - @test_util.run_in_graph_and_eager_modes() - def testPassPerReplica(self): - self._skip_eager_if_gpus_less_than(1) - + def testPassPerReplica(self, distribution): @function.defun def fn1(mock_model, factor): return mock_model(factor) @@ -1394,18 +1268,10 @@ class MirroredStrategyDefunTest(test.TestCase): factors = values.PerReplica({"CPU:0": 5.0, "GPU:0": 3.0}) expected_result = values.PerReplica({"CPU:0": 5.0 * 1.25, "GPU:0": 3.0 * 1.25}) - self._call_and_check(fn1, [factors], expected_result, [fn1]) - - @test_util.run_in_graph_and_eager_modes() - def testTrain(self): - self._skip_eager_if_gpus_less_than(1) + self._call_and_check(distribution, fn1, [factors], expected_result, [fn1]) - cpu_dev = device_util.canonicalize("CPU:0") - gpu_dev = device_util.canonicalize("GPU:0") - devices = [cpu_dev, gpu_dev] - dist = mirrored_strategy.MirroredStrategy(devices) - - with dist.scope(): + def testTrain(self, distribution): + with distribution.scope(): mock_model = MiniModel() mock_model.call = function.defun(mock_model.call) @@ -1415,10 +1281,11 @@ class MirroredStrategyDefunTest(test.TestCase): gradients_fn = backprop.implicit_grad(loss_fn) gradients_fn = optimizer_lib.get_filtered_grad_fn(gradients_fn) - grads_and_vars = dist.call_for_each_replica(gradients_fn, args=(None,)) + grads_and_vars = distribution.extended.call_for_each_replica( + gradients_fn, args=(None,)) optimizer = gradient_descent.GradientDescentOptimizer(0.25) - update_ops = optimizer._distributed_apply(dist, grads_and_vars) # pylint: disable=protected-access + update_ops = optimizer._distributed_apply(distribution, grads_and_vars) # pylint: disable=protected-access if not context.executing_eagerly(): self.evaluate(variables.global_variables_initializer()) @@ -1430,30 +1297,82 @@ class MirroredStrategyDefunTest(test.TestCase): self.assertAllEqual([0.5], updated_var_values[1]) +@combinations.generate( + combinations.combine( + distribution=[ + combinations.NamedDistribution( + "Mirrored", + # pylint: disable=g-long-lambda + lambda: mirrored_strategy.MirroredStrategy(num_gpus_per_worker= + context.num_gpus()), + required_gpus=1), + combinations.NamedDistribution( + "CoreMirrored", + # pylint: disable=g-long-lambda + lambda: mirrored_strategy.CoreMirroredStrategy( + mirrored_strategy.all_local_devices()), + required_gpus=1) + ], + mode=["graph"])) class MultiWorkerMirroredStrategyTest( multi_worker_test_base.MultiWorkerTestBase, strategy_test_lib.DistributionTestBase): - def _get_distribution_strategy(self): + def _configure_distribution_strategy(self, distribution): cluster_spec = server_lib.ClusterSpec({ "worker": ["/job:worker/task:0", "/job:worker/task:1"] }) - strategy = mirrored_strategy.MirroredStrategy(num_gpus=context.num_gpus()) - strategy.configure(cluster_spec=cluster_spec) - return strategy - - def test_num_replicas_in_sync(self): - if not GPU_TEST: - self.skipTest("Not GPU test") + distribution.configure(cluster_spec=cluster_spec) - strategy = self._get_distribution_strategy() + def test_num_replicas_in_sync(self, distribution): + self._configure_distribution_strategy(distribution) # We calculate the total number of gpus across the workers(2) specified in # the cluster spec. - self.assertEqual(context.num_gpus() * 2, strategy.num_replicas_in_sync) - - def testMinimizeLossGraph(self): - self._test_minimize_loss_graph(self._get_distribution_strategy(), - learning_rate=0.05) + self.assertEqual(context.num_gpus() * 2, distribution.num_replicas_in_sync) + + def testMinimizeLossGraph(self, distribution): + self._configure_distribution_strategy(distribution) + self._test_minimize_loss_graph(distribution, learning_rate=0.05) + + def testDeviceScope(self, distribution): + """Test the device scope of multi-worker MirroredStrategy.""" + self._configure_distribution_strategy(distribution) + with distribution.scope(): + a = constant_op.constant(1.) + with ops.device("/cpu:0"): + b = constant_op.constant(1.) + self.assertEqual(a.device, "/job:worker/task:0") + self.assertEqual(b.device, "/job:worker/task:0/device:CPU:0") + + def testMakeInputFnIterator(self, distribution): + self._configure_distribution_strategy(distribution) + dataset_fn = lambda: dataset_ops.Dataset.range(100) + num_gpus = context.num_gpus() + num_workers = 2 + + expected_values = [[i+j for j in range(num_gpus)] * num_workers + for i in range(0, 100, num_gpus)] + + with context.graph_mode(), self.cached_session() as sess: + # `expected_input_pipeline_id` is None because the input_fn will be called + # multiple times, each with a different input_pipeline_id. + input_fn = self._input_fn_to_test_input_context( + dataset_fn, + expected_num_replicas_in_sync=num_workers*num_gpus, + expected_num_input_pipelines=num_workers, + expected_input_pipeline_id=None) + iterator = distribution.make_input_fn_iterator(input_fn) + self._test_input_fn_iterator( + iterator, distribution.extended.worker_devices, expected_values, sess) + + def testUpdateConfigProto(self, distribution): + distribution.configure(cluster_spec={"worker": ["fake1", "fake2"]}) + + config_proto = config_pb2.ConfigProto() + new_config = distribution.update_config_proto(config_proto) + + # Verify isolate_session_state + self.assertTrue(new_config.isolate_session_state) class MultiWorkerMirroredStrategyTestWithChief( @@ -1473,6 +1392,19 @@ class MultiWorkerMirroredStrategyTestWithChief( strategy.configure(cluster_spec=self._cluster_spec) self._test_minimize_loss_graph(strategy, learning_rate=0.05) + def testMinimizeLossGraphCoreMirroredStrategy(self): + strategy = mirrored_strategy.CoreMirroredStrategy( + mirrored_strategy.all_local_devices()) + strategy.configure(cluster_spec=self._cluster_spec) + self._test_minimize_loss_graph(strategy, learning_rate=0.05) + + +def _replica_id(): + replica_id = ds_context.get_replica_context().replica_id_in_sync_group + if not isinstance(replica_id, ops.Tensor): + replica_id = constant_op.constant(replica_id) + return replica_id + if __name__ == "__main__": test.main() diff --git a/tensorflow/contrib/distribute/python/mirrored_strategy_test.py b/tensorflow/contrib/distribute/python/mirrored_strategy_test.py deleted file mode 100644 index bea684e77c..0000000000 --- a/tensorflow/contrib/distribute/python/mirrored_strategy_test.py +++ /dev/null @@ -1,107 +0,0 @@ -# Copyright 2018 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for class MirroredStrategy.""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -from tensorflow.contrib.distribute.python import mirrored_strategy -from tensorflow.contrib.distribute.python import strategy_test_lib -from tensorflow.python.eager import context -from tensorflow.python.eager import test -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import ops -from tensorflow.python.framework import test_util -from tensorflow.python.ops import variable_scope -from tensorflow.python.training import distribution_strategy_context - - -class MirroredOneCPUDistributionTest(strategy_test_lib.DistributionTestBase): - - def _get_distribution_strategy(self): - return mirrored_strategy.MirroredStrategy(["/device:CPU:0"]) - - def testMinimizeLossEager(self): - self._test_minimize_loss_eager(self._get_distribution_strategy()) - - def testMinimizeLossGraph(self): - self._test_minimize_loss_graph(self._get_distribution_strategy()) - - def testDeviceIndex(self): - self._test_device_index(self._get_distribution_strategy()) - - def testReplicaId(self): - self._test_replica_id(self._get_distribution_strategy()) - - @test_util.run_in_graph_and_eager_modes - def testCallAndMergeExceptions(self): - self._test_call_and_merge_exceptions(self._get_distribution_strategy()) - - -class VariableCreatorStackTest(test.TestCase): - - def testCreatorStacksAreThreadLocal(self): - devices = ["/device:CPU:0", "/device:GPU:0"] - dist = mirrored_strategy.MirroredStrategy(devices) - - def model_fn(device_id): - assert isinstance(device_id, int) - - def thread_creator_fn(next_creator, *args, **kwargs): - return next_creator(*args, **kwargs) + ":thread_" + str(device_id) - - with variable_scope.variable_creator_scope(thread_creator_fn): - # Create a variable in this scope. - v = variable_scope.variable(1.0) - - # This will pause the current thread, and execute the other thread. - distribution_strategy_context.get_replica_context().merge_call( - lambda _: _) - return v - - def main_thread_creator(next_creator, *args, **kwargs): - # We are not using the underlying next_creator for test purposes. - del next_creator, args, kwargs - return "main_thread" - - with context.graph_mode(), \ - dist.scope(), \ - variable_scope.variable_creator_scope(main_thread_creator): - result = dist.call_for_each_replica( - model_fn, args=(dist.worker_device_index,)) - result = dist.unwrap(result) - expected = ["main_thread:thread_0", "main_thread:thread_1"] - self.assertEquals(expected, result) - - -class MultiWorkerMirroredStrategyTest(test.TestCase): - - def testDeviceScope(self): - """Test the device scope of multi-worker MirroredStrategy.""" - with context.graph_mode(): - strategy = mirrored_strategy.MirroredStrategy(num_gpus=context.num_gpus()) - strategy.configure( - cluster_spec={"worker": ["/job:worker/task:0", "/job:worker/task:1"]}) - with strategy.scope(): - a = constant_op.constant(1.) - with ops.device("/cpu:0"): - b = constant_op.constant(1.) - self.assertEqual(a.device, "/job:worker/task:0") - self.assertEqual(b.device, "/job:worker/task:0/device:CPU:0") - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/contrib/distribute/python/moving_averages_test.py b/tensorflow/contrib/distribute/python/moving_averages_test.py index 7ecc852d20..c492d8bafc 100644 --- a/tensorflow/contrib/distribute/python/moving_averages_test.py +++ b/tensorflow/contrib/distribute/python/moving_averages_test.py @@ -32,7 +32,8 @@ from tensorflow.python.training import moving_averages all_combinations = combinations.combine( distribution=[combinations.default_strategy, combinations.one_device_strategy, - combinations.mirrored_strategy_with_gpu_and_cpu], + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], mode=["graph"]) diff --git a/tensorflow/contrib/distribute/python/multi_worker_test_base.py b/tensorflow/contrib/distribute/python/multi_worker_test_base.py index 8eec3dc0f6..147c9b83f8 100644 --- a/tensorflow/contrib/distribute/python/multi_worker_test_base.py +++ b/tensorflow/contrib/distribute/python/multi_worker_test_base.py @@ -18,8 +18,11 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import collections import contextlib import copy +import json +import os import threading import numpy as np @@ -271,7 +274,6 @@ class MultiWorkerTestBase(test.TestCase): return config - def _run_client(self, client_fn, task_type, task_id, num_gpus, *args, **kwargs): result = client_fn(task_type, task_id, num_gpus, *args, **kwargs) @@ -303,3 +305,101 @@ class MultiWorkerTestBase(test.TestCase): for t in threads: t.join() self.assertEqual(self._result, len(threads)) + + +class MockOsEnv(collections.Mapping): + """A class that allows per-thread TF_CONFIG.""" + + def __init__(self, *args): + self._dict = dict() + self._thread_local = threading.local() + super(MockOsEnv, self).__init__(*args) + + def get(self, key, default=None): + if not hasattr(self._thread_local, 'dict'): + self._thread_local.dict = dict() + if key == 'TF_CONFIG': + return dict.get(self._thread_local.dict, key, default) + else: + return dict.get(self._dict, key, default) + + def __getitem__(self, key): + if not hasattr(self._thread_local, 'dict'): + self._thread_local.dict = dict() + if key == 'TF_CONFIG': + return dict.__getitem__(self._thread_local.dict, key) + else: + return dict.__getitem__(self._dict, key) + + def __setitem__(self, key, val): + if not hasattr(self._thread_local, 'dict'): + self._thread_local.dict = dict() + if key == 'TF_CONFIG': + return dict.__setitem__(self._thread_local.dict, key, val) + else: + return dict.__setitem__(self._dict, key, val) + + def __iter__(self): + if not hasattr(self._thread_local, 'dict'): + self._thread_local.dict = dict() + for x in self._thread_local.dict.items(): + yield x + for x in self._dict.items(): + yield x + + def __len__(self): + if not hasattr(self._thread_local, 'dict'): + self._thread_local.dict = dict() + return self._thread_local.dict.__len__() + self._dict.__len__() + + +class IndependentWorkerTestBase(test.TestCase): + """Testing infra for independent workers.""" + + def setUp(self): + self._mock_os_env = MockOsEnv() + self._mock_context = test.mock.patch.object(os, 'environ', + self._mock_os_env) + super(IndependentWorkerTestBase, self).setUp() + self._mock_context.__enter__() + + def tearDown(self): + self._mock_context.__exit__(None, None, None) + super(IndependentWorkerTestBase, self).tearDown() + + def _task_thread(self, task_fn, tf_config, *args, **kwargs): + os.environ['TF_CONFIG'] = json.dumps(tf_config) + task_fn(*args, **kwargs) + + def _run_task_in_thread(self, task_fn, cluster_spec, task_type, task_id, + *args, **kwargs): + if task_type: + tf_config = { + 'cluster': cluster_spec, + 'task': { + 'type': task_type, + 'index': task_id + } + } + else: + tf_config = { + 'cluster': cluster_spec, + } + t = threading.Thread( + target=self._task_thread, + args=(task_fn, tf_config) + args, + kwargs=kwargs) + t.start() + return t + + def run_multiple_tasks_in_threads(self, task_fn, cluster_spec, *args, + **kwargs): + # The task_fn should create std_server by itself. + threads = {} + for task_type in cluster_spec.keys(): + threads[task_type] = [] + for task_id in range(len(cluster_spec[task_type])): + t = self._run_task_in_thread(task_fn, cluster_spec, task_type, task_id, + *args, **kwargs) + threads[task_type].append(t) + return threads diff --git a/tensorflow/contrib/distribute/python/one_device_strategy.py b/tensorflow/contrib/distribute/python/one_device_strategy.py index a0d8f93887..e322b6acb8 100644 --- a/tensorflow/contrib/distribute/python/one_device_strategy.py +++ b/tensorflow/contrib/distribute/python/one_device_strategy.py @@ -20,12 +20,14 @@ from __future__ import print_function import six -from tensorflow.contrib.distribute.python import values +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import values from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops -from tensorflow.python.training import distribute as distribute_lib from tensorflow.python.util import nest @@ -39,7 +41,14 @@ class OneDeviceStrategy(distribute_lib.DistributionStrategy): # implementations? def __init__(self, device): - super(OneDeviceStrategy, self).__init__() + super(OneDeviceStrategy, self).__init__(OneDeviceExtended(self, device)) + + +class OneDeviceExtended(distribute_lib.DistributionStrategyExtended): + """Implementation of OneDeviceStrategy.""" + + def __init__(self, container_strategy, device): + super(OneDeviceExtended, self).__init__(container_strategy) self._device = device self._default_device = device @@ -58,17 +67,33 @@ class OneDeviceStrategy(distribute_lib.DistributionStrategy): with ops.colocate_with(colocate_with): return next_creator(*args, **kwargs) - def distribute_dataset(self, dataset_fn): + def _make_dataset_iterator(self, dataset): + """Make iterator from dataset without splitting the batch.""" + worker = device_util.canonicalize("/device:CPU:0") + worker_device_pairs = [(worker, [self._device])] + return values.DatasetIterator(dataset, worker_device_pairs) + + def _distribute_dataset(self, dataset_fn): return values.PerReplicaDataset( self._call_dataset_fn(dataset_fn), [self._device]) - def _broadcast(self, tensor, destinations): + def _make_input_fn_iterator( + self, + input_fn, + replication_mode=distribute_lib.InputReplicationMode.PER_WORKER): + worker = device_util.canonicalize("/device:CPU:0") + worker_device_pairs = [(worker, [self._device])] + return values.InputFunctionIterator( + input_fn, worker_device_pairs, + [distribute_lib.InputContext()]) + + def _broadcast_to(self, tensor, destinations): del destinations return tensor # TODO(priyag): Deal with OutOfRange errors once b/111349762 is fixed. - def _run_steps_on_dataset(self, fn, iterator, iterations, - initial_loop_values=None): + def _experimental_run_steps_on_iterator(self, fn, iterator, iterations, + initial_loop_values=None): if initial_loop_values is None: initial_loop_values = {} initial_loop_values = nest.flatten(initial_loop_values) @@ -80,7 +105,7 @@ class OneDeviceStrategy(distribute_lib.DistributionStrategy): fn_inputs = iterator.get_next() if not isinstance(fn_inputs, tuple): fn_inputs = (fn_inputs,) - fn_result = fn(ctx, *fn_inputs) + fn_result = fn(ctx, fn_inputs) flat_last_step_outputs = nest.flatten(ctx.last_step_outputs) with ops.control_dependencies([fn_result]): return [i + 1] + flat_last_step_outputs @@ -114,25 +139,24 @@ class OneDeviceStrategy(distribute_lib.DistributionStrategy): return ctx def _call_for_each_replica(self, fn, args, kwargs): - with ops.device(self._device), _OneDeviceReplicaContext(self): + strategy = self._container_strategy() + with ops.device(self._device), _OneDeviceReplicaContext(strategy): return fn(*args, **kwargs) - def _reduce(self, aggregation, value, destinations): - del aggregation, destinations + def _reduce_to(self, reduce_op, value, destinations): + del reduce_op, destinations return value - def _update(self, var, options, fn, *args, **kwargs): + def _update(self, var, fn, args, kwargs, group): # The implementations of _update() and _update_non_slot() are identical # except _update() passes `var` as the first argument to `fn()`. - return self._update_non_slot(var, options, fn, var, *args, **kwargs) + return self._update_non_slot(var, fn, (var,) + tuple(args), kwargs, group) - def _update_non_slot(self, colocate_with, options, fn, *args, **kwargs): + def _update_non_slot(self, colocate_with, fn, args, kwargs, group): del colocate_with - should_group = options.pop("grouped") - assert not options # Validate that we are processing all of the options. with ops.device(self._device), distribute_lib.UpdateContext(self._device): result = fn(*args, **kwargs) - if should_group: + if group: return result else: return nest.map_structure(self._unwrap, result) @@ -148,11 +172,7 @@ class OneDeviceStrategy(distribute_lib.DistributionStrategy): return value @property - def num_replicas(self): - return 1 - - @property - def num_replicas_in_sync(self): + def _num_replicas_in_sync(self): return 1 @property @@ -167,8 +187,22 @@ class OneDeviceStrategy(distribute_lib.DistributionStrategy): del var_list return [self._device] - def _worker_device_index(self): - return 0 + @property + def experimental_should_init(self): + return True + + @property + def should_checkpoint(self): + return True + + @property + def should_save_summary(self): + return True + + # TODO(priyag): Delete this once all strategies use global batch size. + @property + def _global_batch_size(self): + return True class _OneDeviceReplicaContext(distribute_lib.ReplicaContext): @@ -176,12 +210,10 @@ class _OneDeviceReplicaContext(distribute_lib.ReplicaContext): def __init__(self, distribution_strategy): distribute_lib.ReplicaContext.__init__( - self, distribution_strategy, replica_id=0) - - @property - def device(self): - raise RuntimeError("Use .devices instead") + self, + distribution_strategy, + replica_id_in_sync_group=constant_op.constant(0, dtypes.int32)) @property def devices(self): - return [self._distribution_strategy.worker_devices[0]] + return [self._distribution_strategy.extended.worker_devices[0]] diff --git a/tensorflow/contrib/distribute/python/one_device_strategy_test.py b/tensorflow/contrib/distribute/python/one_device_strategy_test.py index 95f4cdb786..d46cd6f529 100644 --- a/tensorflow/contrib/distribute/python/one_device_strategy_test.py +++ b/tensorflow/contrib/distribute/python/one_device_strategy_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.contrib.distribute.python import one_device_strategy from tensorflow.contrib.distribute.python import strategy_test_lib +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.eager import test from tensorflow.python.framework import test_util @@ -35,9 +36,6 @@ class OneDeviceStrategyTest(strategy_test_lib.DistributionTestBase): def testMinimizeLossGraph(self): self._test_minimize_loss_graph(self._get_distribution_strategy()) - def testDeviceIndex(self): - self._test_device_index(self._get_distribution_strategy()) - def testReplicaId(self): self._test_replica_id(self._get_distribution_strategy()) @@ -45,6 +43,20 @@ class OneDeviceStrategyTest(strategy_test_lib.DistributionTestBase): def testCallAndMergeExceptions(self): self._test_call_and_merge_exceptions(self._get_distribution_strategy()) + @test_util.run_in_graph_and_eager_modes + def testMakeInputFnIterator(self): + d = one_device_strategy.OneDeviceStrategy("/device:CPU:0") + dataset_fn = lambda: dataset_ops.Dataset.range(10) + expected_values = [[i] for i in range(10)] + input_fn = self._input_fn_to_test_input_context( + dataset_fn, + expected_num_replicas_in_sync=1, + expected_num_input_pipelines=1, + expected_input_pipeline_id=0) + iterator = d.make_input_fn_iterator(input_fn) + self._test_input_fn_iterator( + iterator, d.extended.worker_devices, expected_values) + if __name__ == "__main__": test.main() diff --git a/tensorflow/contrib/distribute/python/parameter_server_strategy.py b/tensorflow/contrib/distribute/python/parameter_server_strategy.py index 790b37f860..eaeb4d7030 100644 --- a/tensorflow/contrib/distribute/python/parameter_server_strategy.py +++ b/tensorflow/contrib/distribute/python/parameter_server_strategy.py @@ -18,10 +18,14 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.contrib.distribute.python import cross_tower_ops as cross_tower_ops_lib +import copy + from tensorflow.contrib.distribute.python import mirrored_strategy -from tensorflow.contrib.distribute.python import values +from tensorflow.python.distribute import cross_device_ops as cross_device_ops_lib +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribute_lib from tensorflow.python.distribute import multi_worker_util +from tensorflow.python.distribute import values from tensorflow.python.eager import context from tensorflow.python.framework import device as tf_device from tensorflow.python.framework import ops @@ -30,8 +34,6 @@ from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import variable_scope as vs from tensorflow.python.platform import tf_logging as logging from tensorflow.python.training import device_setter -from tensorflow.python.training import device_util -from tensorflow.python.training import distribute as distribute_lib from tensorflow.python.util import nest _LOCAL_CPU = "/device:CPU:0" @@ -94,13 +96,21 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): ValueError: if `cluster_spec` is given but `task_type` or `task_id` is not. """ - super(ParameterServerStrategy, self).__init__() + super(ParameterServerStrategy, self).__init__( + ParameterServerExtended(self, num_gpus_per_worker)) + + +class ParameterServerExtended(distribute_lib.DistributionStrategyExtended): + """Implementation of ParameterServerStrategy.""" + + def __init__(self, container_strategy, num_gpus_per_worker): + super(ParameterServerExtended, self).__init__(container_strategy) self._num_gpus_per_worker = num_gpus_per_worker self._initialize_local(num_gpus_per_worker) # We typically don't need to do all-reduce in this strategy. - self._cross_tower_ops = ( - cross_tower_ops_lib.ReductionToOneDeviceCrossDeviceOps( + self._cross_device_ops = ( + cross_device_ops_lib.ReductionToOneDeviceCrossDeviceOps( reduce_to_device=_LOCAL_CPU)) def _initialize_multi_worker(self, num_gpus_per_worker, cluster_spec, @@ -189,6 +199,7 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): def _initialize_local(self, num_gpus_per_worker): """Initialize internal devices for local training.""" + self._worker_device = device_util.canonicalize("/device:CPU:0") # Define compute devices which is a list of device strings and one for each # replica. When there are GPUs, replicate operations on these GPUs. # Otherwise, place operations on CPU. @@ -221,15 +232,48 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): "ParameterServerStrategy with compute_devices = %r, " "variable_device = %r", self._compute_devices, self._variable_device) - def distribute_dataset(self, dataset_fn): + def _distribute_dataset(self, dataset_fn): """Distributes the dataset to each local GPU.""" return values.PerReplicaDataset( self._call_dataset_fn(dataset_fn), self._compute_devices, True) - def _broadcast(self, tensor, destinations): - if not cross_tower_ops_lib.check_destinations(destinations): + def _make_dataset_iterator(self, dataset): + worker_device_pairs = [(self._worker_device, self._compute_devices)] + return values.DatasetIterator(dataset, worker_device_pairs, + self._num_replicas_in_sync) + + def _make_input_fn_iterator( + self, + input_fn, + replication_mode=distribute_lib.InputReplicationMode.PER_WORKER): + """Distributes the dataset to each local GPU.""" + if self._cluster_spec: + input_pipeline_id = multi_worker_util.id_in_cluster( + self._cluster_spec, self._task_type, self._task_id) + num_input_pipelines = multi_worker_util.worker_count( + self._cluster_spec, self._task_type) + else: + input_pipeline_id = 0 + num_input_pipelines = 1 + input_context = distribute_lib.InputContext( + num_input_pipelines=num_input_pipelines, + input_pipeline_id=input_pipeline_id, + num_replicas_in_sync=self._num_replicas_in_sync) + worker_device_pairs = [(self._worker_device, self._compute_devices)] + return values.InputFunctionIterator( + input_fn, worker_device_pairs, [input_context]) + + def _broadcast_to(self, tensor, destinations): + # This is both a fast path for Python constants, and a way to delay + # converting Python values to a tensor until we know what type it + # should be converted to. Otherwise we have trouble with: + # global_step.assign_add(1) + # since the `1` gets broadcast as an int32 but global_step is int64. + if isinstance(tensor, (float, int)): + return tensor + if not cross_device_ops_lib.check_destinations(destinations): destinations = self._compute_devices - return self._cross_tower_ops.broadcast(tensor, destinations) + return self._cross_device_ops.broadcast(tensor, destinations) def _allow_variable_partition(self): return not context.executing_eagerly() @@ -237,7 +281,7 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): # TODO(yuefengz): not all ops in device_setter.STANDARD_PS_OPS will go through # this creator, such as "MutableHashTable". def _create_variable(self, next_creator, *args, **kwargs): - if self.num_replicas_in_sync > 1: + if self._num_replicas_in_sync > 1: aggregation = kwargs.pop("aggregation", vs.VariableAggregation.NONE) if aggregation not in ( vs.VariableAggregation.NONE, @@ -293,39 +337,35 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): def _call_for_each_replica(self, fn, args, kwargs): # pylint: disable=protected-access - return mirrored_strategy._call_for_each_replica(self, fn, args, kwargs) + return mirrored_strategy._call_for_each_replica( + self._container_strategy(), fn, args, kwargs) def _verify_destinations_not_different_worker(self, destinations): if not self._cluster_spec: return if destinations is None: return - for d in cross_tower_ops_lib.get_devices_from(destinations): + for d in cross_device_ops_lib.get_devices_from(destinations): d_spec = tf_device.DeviceSpec.from_string(d) if d_spec.job == self._task_type and d_spec.task != self._task_id: raise ValueError( "Cannot reduce to another worker: %r, current worker is %r" % (d, self._worker_device)) - def _reduce(self, aggregation, value, destinations): + def _reduce_to(self, reduce_op, value, destinations): self._verify_destinations_not_different_worker(destinations) if not isinstance(value, values.DistributedValues): # pylint: disable=protected-access return mirrored_strategy._reduce_non_distributed_value( - self, aggregation, value, destinations) - if aggregation == vs.VariableAggregation.ONLY_FIRST_REPLICA: - return self.broadcast(value.get(self._compute_devices[0]), destinations) - return self._cross_tower_ops.reduce( - aggregation, value, destinations=destinations) - - def _batch_reduce(self, aggregation, value_destination_pairs): - if aggregation == vs.VariableAggregation.ONLY_FIRST_REPLICA: - return [self.broadcast(v.get(self._compute_devices[0]), d) - for v, d in value_destination_pairs] + self, reduce_op, value, destinations) + return self._cross_device_ops.reduce( + reduce_op, value, destinations=destinations) + + def _batch_reduce_to(self, reduce_op, value_destination_pairs): for _, destinations in value_destination_pairs: self._verify_destinations_not_different_worker(destinations) - return self._cross_tower_ops.batch_reduce(aggregation, - value_destination_pairs) + return self._cross_device_ops.batch_reduce(reduce_op, + value_destination_pairs) def _select_single_value(self, structured): """Select any single values in `structured`.""" @@ -349,30 +389,26 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): return nest.map_structure(_select_fn, structured) - def _update(self, var, options, fn, *args, **kwargs): + def _update(self, var, fn, args, kwargs, group): if isinstance(var, values.AggregatingVariable): var = var.get() if not isinstance(var, resource_variable_ops.ResourceVariable): raise ValueError( "You can not update `var` %r. It must be a Variable." % var) - should_group = options.pop("grouped") - assert not options # Validate that we are processing all of the options. with ops.colocate_with(var), distribute_lib.UpdateContext(var.device): result = fn(var, *self._select_single_value(args), **self._select_single_value(kwargs)) - if should_group: + if group: return result else: return nest.map_structure(self._unwrap, result) # TODO(yuefengz): does it need to call _select_single_value? - def _update_non_slot(self, colocate_with, options, fn, *args, **kwargs): - should_group = options.pop("grouped") - assert not options # Validate that we are processing all of the options. + def _update_non_slot(self, colocate_with, fn, args, kwargs, group): with ops.device( colocate_with.device), distribute_lib.UpdateContext(colocate_with): result = fn(*args, **kwargs) - if should_group: + if group: return result else: return nest.map_structure(self._unwrap, result) @@ -398,11 +434,11 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): # variables. return array_ops.identity(var) - def configure(self, - session_config=None, - cluster_spec=None, - task_type=None, - task_id=None): + def _configure(self, + session_config=None, + cluster_spec=None, + task_type=None, + task_id=None): """Configures the strategy class. The strategy object will be re-initialized if `cluster_spec` is given but @@ -433,28 +469,30 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): self._initialize_multi_worker(self._num_gpus_per_worker, self._cluster_spec, task_type, task_id) - if not session_config or not self._cluster_spec: - return + if session_config: + session_config.CopyFrom(self._update_config_proto(session_config)) - session_config.isolate_session_state = False + def _update_config_proto(self, config_proto): + updated_config = copy.deepcopy(config_proto) + if not self._cluster_spec: + updated_config.isolate_session_state = True + return updated_config + + updated_config.isolate_session_state = False - assert self._cluster_spec assert self._task_type assert self._task_id is not None # The device filters prevent communication between workers. if self._task_type not in ["chief", "worker"]: - return - del session_config.device_filters[:] - session_config.device_filters.extend( + return updated_config + del updated_config.device_filters[:] + updated_config.device_filters.extend( ["/job:%s/task:%d" % (self._task_type, self._task_id), "/job:ps"]) + return updated_config @property - def num_replicas(self): - return len(self._compute_devices) - - @property - def num_replicas_in_sync(self): + def _num_replicas_in_sync(self): return len(self._compute_devices) @property @@ -470,11 +508,12 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): return min(var_list, key=lambda x: x.name) @property - def between_graph(self): + def experimental_between_graph(self): + # TODO(yuefengz): Should this return False in the local case? return True @property - def should_init(self): + def experimental_should_init(self): return self._is_chief @property @@ -484,3 +523,8 @@ class ParameterServerStrategy(distribute_lib.DistributionStrategy): @property def should_save_summary(self): return self._is_chief + + # TODO(priyag): Delete this once all strategies use global batch size. + @property + def _global_batch_size(self): + return False diff --git a/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py b/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py index 81a23c8903..83d7473666 100644 --- a/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py +++ b/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py @@ -25,14 +25,21 @@ from absl.testing import parameterized from tensorflow.contrib.distribute.python import combinations from tensorflow.contrib.distribute.python import multi_worker_test_base from tensorflow.contrib.distribute.python import parameter_server_strategy -from tensorflow.contrib.distribute.python import values +from tensorflow.contrib.distribute.python import strategy_test_lib from tensorflow.core.protobuf import config_pb2 +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribution_strategy_context as ds_context from tensorflow.python.distribute import multi_worker_util +from tensorflow.python.distribute import reduce_util +from tensorflow.python.distribute import values from tensorflow.python.eager import backprop from tensorflow.python.eager import context from tensorflow.python.estimator import run_config from tensorflow.python.framework import constant_op +from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_util from tensorflow.python.layers import core from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops @@ -41,8 +48,6 @@ from tensorflow.python.ops import partitioned_variables from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables from tensorflow.python.platform import test -from tensorflow.python.training import device_util -from tensorflow.python.training import distribution_strategy_context from tensorflow.python.training import training_util CHIEF = run_config.TaskType.CHIEF @@ -50,6 +55,13 @@ WORKER = run_config.TaskType.WORKER PS = run_config.TaskType.PS +def _get_replica_id_integer(): + replica_id = ds_context.get_replica_context().replica_id_in_sync_group + if isinstance(replica_id, ops.Tensor): + replica_id = tensor_util.constant_value(replica_id) + return replica_id + + class ParameterServerStrategyTestBase( multi_worker_test_base.MultiWorkerTestBase): @@ -94,9 +106,8 @@ class ParameterServerStrategyTestBase( if num_gpus == 0: last_part_device = 'device:CPU:0' else: - last_part_device = ( - 'device:GPU:%d' % - distribution_strategy_context.get_replica_context().replica_id) + replica_id = _get_replica_id_integer() + last_part_device = ('device:GPU:%d' % replica_id) a = constant_op.constant(1.0) b = constant_op.constant(2.0) @@ -261,18 +272,16 @@ class ParameterServerStrategyTestBase( if 'CPU' in compute_device: replica_compute_device = '/device:CPU:0' else: - replica_compute_device = ( - '/device:GPU:%d' % - distribution_strategy_context.get_replica_context().replica_id) + replica_id = _get_replica_id_integer() + replica_compute_device = ('/device:GPU:%d' % replica_id) replica_compute_device = device_util.canonicalize( replica_compute_device) if 'CPU' in variable_device: replica_variable_device = '/device:CPU:0' else: - replica_variable_device = ( - '/device:GPU:%d' % - distribution_strategy_context.get_replica_context().replica_id) + replica_id = _get_replica_id_integer() + replica_variable_device = ('/device:GPU:%d' % replica_id) replica_variable_device = device_util.canonicalize( replica_variable_device) @@ -354,9 +363,9 @@ class ParameterServerStrategyTestBase( def _test_simple_increment(self, task_type, task_id, num_gpus): d, master_target, sess_config = self._get_test_objects( task_type, task_id, num_gpus) - if hasattr(d, '_cluster_spec') and d._cluster_spec: - num_workers = len(d._cluster_spec.as_dict().get(WORKER)) - if 'chief' in d._cluster_spec.as_dict(): + if d.extended._cluster_spec: + num_workers = len(d.extended._cluster_spec.as_dict().get(WORKER)) + if 'chief' in d.extended._cluster_spec.as_dict(): num_workers += 1 else: num_workers = 1 @@ -389,7 +398,7 @@ class ParameterServerStrategyTestBase( x, y, z, train_op = d.call_for_each_replica(model_fn) train_op = d.group(train_op) - if context.num_gpus() < d._num_gpus_per_worker: + if context.num_gpus() < d.extended._num_gpus_per_worker: return True if task_id == 0: @@ -426,9 +435,9 @@ class ParameterServerStrategyTestBase( task_type, task_id, num_gpus) if task_type: # Multi-worker - assert hasattr(d, '_cluster_spec') and d._cluster_spec - num_workers = len(d._cluster_spec.as_dict().get(WORKER)) - if CHIEF in d._cluster_spec.as_dict(): + assert hasattr(d.extended, '_cluster_spec') and d.extended._cluster_spec + num_workers = len(d.extended._cluster_spec.as_dict().get(WORKER)) + if CHIEF in d.extended._cluster_spec.as_dict(): num_workers += 1 else: # local @@ -472,8 +481,8 @@ class ParameterServerStrategyTestBase( before_list.append(fetched) with ops.control_dependencies([fetched]): # TODO(yuefengz): support non-Mirrored variable as destinations. - g = d.reduce( - variable_scope.VariableAggregation.SUM, g, destinations=v) + g = d.extended.reduce_to( + reduce_util.ReduceOp.SUM, g, destinations=v) with ops.control_dependencies( d.update(v, update, g, grouped=False)): after_list.append(d.read_var(v)) @@ -481,11 +490,12 @@ class ParameterServerStrategyTestBase( before_out, after_out = step() - if context.num_gpus() < d._num_gpus_per_worker: + if context.num_gpus() < d.extended._num_gpus_per_worker: return True if (not task_type or - multi_worker_util.is_chief(d._cluster_spec, task_type, task_id)): + multi_worker_util.is_chief( + d.extended._cluster_spec, task_type, task_id)): variables.global_variables_initializer().run() # Workers waiting for chief worker's initializing variables. @@ -508,8 +518,40 @@ class ParameterServerStrategyTestBase( self.assertLess(error_after, error_before) return error_after < error_before + def _test_input_fn_iterator(self, task_type, task_id, num_gpus, input_fn, + expected_values): + distribution, master_target, config = self._get_test_objects( + task_type, task_id, num_gpus) + devices = distribution.extended.worker_devices + + with ops.Graph().as_default(), \ + self.cached_session(config=config, + target=master_target) as sess: + iterator = distribution.make_input_fn_iterator(input_fn) + sess.run(iterator.initialize()) + + for expected_value in expected_values: + next_element = iterator.get_next() + computed_value = sess.run( + [values.select_device(d, next_element) for d in devices]) + self.assertEqual(expected_value, computed_value) + + with self.assertRaises(errors.OutOfRangeError): + next_element = iterator.get_next() + sess.run([values.select_device(d, next_element) for d in devices]) + + # After re-initializing the iterator, should be able to iterate again. + sess.run(iterator.initialize()) + + for expected_value in expected_values: + next_element = iterator.get_next() + computed_value = sess.run( + [values.select_device(d, next_element) for d in devices]) + self.assertEqual(expected_value, computed_value) + class ParameterServerStrategyTest(ParameterServerStrategyTestBase, + strategy_test_lib.DistributionTestBase, parameterized.TestCase): @classmethod @@ -574,6 +616,73 @@ class ParameterServerStrategyTest(ParameterServerStrategyTestBase, def testMinimizeLossGraphLocal(self, num_gpus): self._test_minimize_loss_graph(None, None, num_gpus) + # TODO(priyag): Refactor this and other multi worker tests. + @combinations.generate( + combinations.combine(mode=['graph'], num_gpus=[1, 2], required_gpus=1)) + def testMakeInputFnIteratorDistributed(self, num_gpus): + if context.num_gpus() < num_gpus: + self.skipTest('Not enough GPUs') + dataset_fn = lambda: dataset_ops.Dataset.range(100) + expected_values = [[i+j for j in range(num_gpus)] + for i in range(0, 100, num_gpus)] + + input_fn = self._input_fn_to_test_input_context( + dataset_fn, + expected_num_replicas_in_sync=num_gpus, + expected_num_input_pipelines=3, + expected_input_pipeline_id=1) # because task_id = 1 + self._test_input_fn_iterator('worker', 1, num_gpus, + input_fn, expected_values) + + @combinations.generate( + combinations.combine(mode=['graph'], num_gpus=[1, 2], required_gpus=1)) + def testMakeInputFnIteratorLocal(self, num_gpus): + if context.num_gpus() < num_gpus: + self.skipTest('Not enough GPUs') + dataset_fn = lambda: dataset_ops.Dataset.range(100) + expected_values = [[i+j for j in range(num_gpus)] + for i in range(0, 100, num_gpus)] + + input_fn = self._input_fn_to_test_input_context( + dataset_fn, + expected_num_replicas_in_sync=num_gpus, + expected_num_input_pipelines=1, + expected_input_pipeline_id=0) # only one worker and pipeline for local. + self._test_input_fn_iterator(None, None, num_gpus, + input_fn, expected_values) + + def testGlobalStepUpdate(self): + strategy = parameter_server_strategy.ParameterServerStrategy( + num_gpus_per_worker=context.num_gpus()) + self._test_global_step_update(strategy) + + def testUpdateConfigProtoMultiWorker(self): + distribution = parameter_server_strategy.ParameterServerStrategy( + num_gpus_per_worker=2) + distribution.configure( + cluster_spec=self._cluster_spec, task_type='worker', task_id=1) + + config_proto = config_pb2.ConfigProto(device_filters=['to_be_overridden']) + + new_config = distribution.update_config_proto(config_proto) + + # Verify device filters. + self.assertEqual(['/job:worker/task:1', '/job:ps'], + new_config.device_filters) + + # Verify isolate_session_state + self.assertFalse(new_config.isolate_session_state) + + def testUpdateConfigProtoLocal(self): + distribution = parameter_server_strategy.ParameterServerStrategy( + num_gpus_per_worker=2) + + config_proto = config_pb2.ConfigProto() + new_config = distribution.update_config_proto(config_proto) + + # Verify isolate_session_state + self.assertTrue(new_config.isolate_session_state) + class ParameterServerStrategyWithChiefTest(ParameterServerStrategyTestBase, parameterized.TestCase): @@ -616,9 +725,9 @@ class ParameterServerStrategyWithChiefTest(ParameterServerStrategyTestBase, v = variable_scope.get_variable('v', initializer=10.0) _ = v * v v, = tape.watched_variables() - w = distribution.value_container(v) + w = distribution.extended.value_container(v) self.assertIs(values.AggregatingVariable, type(w)) - distribution.call_for_each_replica(f) + distribution.extended.call_for_each_replica(f) if __name__ == '__main__': diff --git a/tensorflow/contrib/distribute/python/step_fn.py b/tensorflow/contrib/distribute/python/step_fn.py index 3dc815f037..c928b6d9f1 100644 --- a/tensorflow/contrib/distribute/python/step_fn.py +++ b/tensorflow/contrib/distribute/python/step_fn.py @@ -94,7 +94,7 @@ class StandardSingleLossStep(StandardInputStep): def __call__(self): with self._distribution.scope(): - def step_fn(ctx, *inputs): + def step_fn(ctx, inputs): """Function to run one iteration with one input.""" gradients_fn = backprop.implicit_grad(self._loss_fn) gradients_fn = optimizer_lib.get_filtered_grad_fn(gradients_fn) diff --git a/tensorflow/contrib/distribute/python/strategy_test_lib.py b/tensorflow/contrib/distribute/python/strategy_test_lib.py index 3c0c10430e..d50b142c5e 100644 --- a/tensorflow/contrib/distribute/python/strategy_test_lib.py +++ b/tensorflow/contrib/distribute/python/strategy_test_lib.py @@ -19,16 +19,21 @@ from __future__ import division from __future__ import print_function from tensorflow.core.protobuf import config_pb2 +from tensorflow.python.distribute import distribution_strategy_context as ds_context +from tensorflow.python.distribute import reduce_util +from tensorflow.python.distribute import values from tensorflow.python.eager import backprop from tensorflow.python.eager import context from tensorflow.python.eager import test from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.layers import core from tensorflow.python.ops import array_ops +from tensorflow.python.ops import init_ops from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables -from tensorflow.python.training import distribution_strategy_context from tensorflow.python.training import optimizer @@ -45,8 +50,7 @@ def _raise_exception_fn(_=None): # Must be the argument to a distribution.call_for_each_replica() call, calls a # get_replica_context().merge_call() that raises an exception. def _merge_raises_fn(): - distribution_strategy_context.get_replica_context().merge_call( - _raise_exception_fn) + ds_context.get_replica_context().merge_call(_raise_exception_fn) # Must be the argument to a get_replica_context().merge_call() call, calls @@ -59,8 +63,7 @@ def _call_raises_fn(dist): # calls a get_replica_context().merge_call() that calls a # call_for_each_replica() that raises an exception. def _merge_call_raises_fn(): - distribution_strategy_context.get_replica_context().merge_call( - _call_raises_fn) + ds_context.get_replica_context().merge_call(_call_raises_fn) # Must be the argument to a get_replica_context().merge_call() call, calls @@ -74,8 +77,7 @@ def _call_merge_raises_fn(dist): # get_replica_context().merge_call() that calls a call_for_each_replica() that # calls a get_replica_context().merge_call() that raises an exception. def _merge_call_merge_raises_fn(): - distribution_strategy_context.get_replica_context().merge_call( - _call_merge_raises_fn) + ds_context.get_replica_context().merge_call(_call_merge_raises_fn) class DistributionTestBase(test.TestCase): @@ -114,8 +116,8 @@ class DistributionTestBase(test.TestCase): before_list.append(fetched) # control_dependencies irrelevant but harmless in eager execution with ops.control_dependencies([fetched]): - g = d.reduce( - variable_scope.VariableAggregation.SUM, g, destinations=v) + g = d.extended.reduce_to( + reduce_util.ReduceOp.SUM, g, destinations=v) with ops.control_dependencies(d.update( v, update, g, grouped=False)): after_list.append(d.read_var(v)) @@ -169,8 +171,8 @@ class DistributionTestBase(test.TestCase): fetched = d.read_var(v) before_list.append(fetched) with ops.control_dependencies([fetched]): - g = d.reduce( - variable_scope.VariableAggregation.SUM, g, destinations=v) + g = d.extended.reduce_to( + reduce_util.ReduceOp.SUM, g, destinations=v) with ops.control_dependencies(d.update( v, update, g, grouped=False)): after_list.append(d.read_var(v)) @@ -189,31 +191,20 @@ class DistributionTestBase(test.TestCase): # Error should go down self.assertLess(error_after, error_before) - def _test_device_index(self, d): - with d.scope(): - expected_devices = [False] * len(d.worker_devices) - - def mark_devices_fn(device_id): - self.assertLess(device_id, len(d.worker_devices)) - self.assertFalse(expected_devices[device_id]) - expected_devices[device_id] = True - - d.call_for_each_replica(mark_devices_fn, args=(d.worker_device_index,)) - self.assertAllEqual(expected_devices, [True] * len(d.worker_devices)) - def _test_replica_id(self, d): with d.scope(): - expected_devices = [False] * len(d.worker_devices) + expected_devices = [False] * len(d.extended.worker_devices) def mark_devices_fn(): - replica_id = ( - distribution_strategy_context.get_replica_context().replica_id) - self.assertLess(replica_id, len(d.worker_devices)) + replica_id = self.evaluate( + ds_context.get_replica_context().replica_id_in_sync_group) + self.assertLess(replica_id, len(d.extended.worker_devices)) self.assertFalse(expected_devices[replica_id]) expected_devices[replica_id] = True d.call_for_each_replica(mark_devices_fn) - self.assertAllEqual(expected_devices, [True] * len(d.worker_devices)) + self.assertAllEqual(expected_devices, + [True] * len(d.extended.worker_devices)) def _test_call_and_merge_exceptions(self, dist): with dist.scope(): @@ -225,3 +216,78 @@ class DistributionTestBase(test.TestCase): dist.call_for_each_replica(_merge_call_raises_fn) with self.assertRaises(_TestException): dist.call_for_each_replica(_merge_call_merge_raises_fn) + + def _input_fn_to_test_input_context(self, + dataset_fn, + expected_num_replicas_in_sync, + expected_num_input_pipelines, + expected_input_pipeline_id): + # Use a list of one element as counter so that it can be captured by the + # `_input_fn`. This counter is incremented by 1 each time an input_fn is + # called. We use this counter to check whether the `input_pipeline_id` + # matches the counter in the in-graph replication. + worker_id_counter = [0] + + def _input_fn(input_context): + """Input fn for testing.""" + self.assertIsNotNone(input_context) + self.assertEqual(expected_num_replicas_in_sync, + input_context.num_replicas_in_sync) + self.assertEqual(expected_num_input_pipelines, + input_context.num_input_pipelines) + if expected_input_pipeline_id is not None: + self.assertEqual(expected_input_pipeline_id, + input_context.input_pipeline_id) + else: + self.assertEqual(worker_id_counter[0], input_context.input_pipeline_id) + worker_id_counter[0] += 1 + + return dataset_fn() + + return _input_fn + + def _test_input_fn_iterator(self, iterator, devices, expected_values, + sess=None): + evaluate = lambda x: sess.run(x) if sess else self.evaluate(x) + evaluate(iterator.initialize()) + + for expected_value in expected_values: + next_element = iterator.get_next() + computed_value = evaluate( + [values.select_device(d, next_element) for d in devices]) + self.assertEqual(expected_value, computed_value) + + with self.assertRaises(errors.OutOfRangeError): + next_element = iterator.get_next() + evaluate([values.select_device(d, next_element) for d in devices]) + + # After re-initializing the iterator, should be able to iterate again. + evaluate(iterator.initialize()) + + for expected_value in expected_values: + next_element = iterator.get_next() + computed_value = evaluate( + [values.select_device(d, next_element) for d in devices]) + self.assertEqual(expected_value, computed_value) + + def _test_global_step_update(self, strategy): + with strategy.scope(): + global_step = variable_scope.get_variable( + "global_step", + shape=[], + dtype=dtypes.int64, + initializer=init_ops.zeros_initializer(), + trainable=False, + aggregation=variables.VariableAggregation.ONLY_FIRST_REPLICA) + self.evaluate(variables.global_variables_initializer()) + + def model_fn(): + train_op = global_step.assign_add(1) + value = global_step.read_value() + return train_op, value + + train_ops, value = strategy.call_for_each_replica(model_fn) + self.evaluate(strategy.group(train_ops)) + global_step_tensors = strategy.unwrap(value) + global_step_values = self.evaluate(global_step_tensors) + self.assertEqual([1] * len(global_step_tensors), global_step_values) diff --git a/tensorflow/contrib/distribute/python/tpu_strategy.py b/tensorflow/contrib/distribute/python/tpu_strategy.py index f5b4531ba8..39ed8f7cf1 100644 --- a/tensorflow/contrib/distribute/python/tpu_strategy.py +++ b/tensorflow/contrib/distribute/python/tpu_strategy.py @@ -21,25 +21,28 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import copy import functools -from tensorflow.contrib.distribute.python import cross_tower_ops as cross_tower_ops_lib -from tensorflow.contrib.distribute.python import values from tensorflow.contrib.tpu.python.ops import tpu_ops from tensorflow.contrib.tpu.python.tpu import tpu from tensorflow.contrib.tpu.python.tpu import tpu_system_metadata as tpu_system_metadata_lib from tensorflow.contrib.tpu.python.tpu import training_loop +from tensorflow.python.distribute import cross_device_ops as cross_device_ops_lib +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import reduce_util +from tensorflow.python.distribute import values from tensorflow.python.eager import context from tensorflow.python.eager import tape from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import variable_scope as vs -from tensorflow.python.ops import variables as variables_lib -from tensorflow.python.training import device_util -from tensorflow.python.training import distribute as distribute_lib from tensorflow.python.util import nest @@ -130,8 +133,21 @@ class TPUStrategy(distribute_lib.DistributionStrategy): num_cores: Number of cores to use on the TPU. If None specified, then auto-detect the cores and topology of the TPU system. """ - super(TPUStrategy, self).__init__() + super(TPUStrategy, self).__init__(TPUExtended( + self, tpu_cluster_resolver, steps_per_run, num_cores)) + @property + def steps_per_run(self): + """DEPRECATED: use .extended.steps_per_run instead.""" + return self._extended.steps_per_run + + +class TPUExtended(distribute_lib.DistributionStrategyExtended): + """Implementation of TPUStrategy.""" + + def __init__(self, container_strategy, tpu_cluster_resolver, steps_per_run, + num_cores=None): + super(TPUExtended, self).__init__(container_strategy) self._tpu_cluster_resolver = tpu_cluster_resolver self._tpu_metadata = get_tpu_system_metadata(self._tpu_cluster_resolver) # TODO(sourabhbajaj): Change this from num_cores to metadata_override @@ -145,7 +161,7 @@ class TPUStrategy(distribute_lib.DistributionStrategy): self._host_device = self.get_host_cpu_device(0) self._tpu_devices = sorted(device_map.keys()) # Only create variables for the number of replicas we're running. - self._tpu_devices = self._tpu_devices[:self.num_replicas] + self._tpu_devices = self._tpu_devices[:self._num_replicas_in_sync] # TODO(sourabhbajaj): Remove this once performance of running one step # at a time is comparable to multiple steps. @@ -214,7 +230,17 @@ class TPUStrategy(distribute_lib.DistributionStrategy): return enqueue_op_per_host - def distribute_dataset(self, dataset_fn): + def _make_dataset_iterator(self, dataset): + """Make iterators for each of the TPU hosts.""" + + worker_devices = [ + (self.get_host(hid), [self.get_host_cpu_device(hid)]) + for hid in range(self.num_hosts) + ] + return values.DatasetIterator(dataset, worker_devices, + self._num_replicas_in_sync) + + def _distribute_dataset(self, dataset_fn): worker_devices = [ (self.get_host(hid), [self.get_host_cpu_device(hid)]) for hid in range(self.num_hosts) @@ -225,12 +251,11 @@ class TPUStrategy(distribute_lib.DistributionStrategy): # TODO(priyag): Deal with OutOfRange errors once b/111349762 is fixed. # TODO(sourabhbajaj): Remove the initial_loop_values parameter when we have # a mechanism to infer the outputs of `fn`. Pending b/110550782. - def _run_steps_on_dataset(self, fn, multi_worker_iterator, iterations, - initial_loop_values=None): - + def _experimental_run_steps_on_iterator( + self, fn, multi_worker_iterator, iterations, initial_loop_values=None): output_shapes = multi_worker_iterator.output_shapes shapes = nest.flatten(output_shapes) - if any([not s.is_fully_defined() for s in shapes]): + if any(not s.is_fully_defined() for s in shapes): raise ValueError( "TPU currently requires fully defined shapes. Either use " "set_shape() on the input tensors or use " @@ -251,13 +276,13 @@ class TPUStrategy(distribute_lib.DistributionStrategy): initial_loop_values = {} initial_loop_values = nest.flatten(initial_loop_values) ctx = values.MultiStepContext() - def run_fn(*args, **kwargs): + + def run_fn(): """Single step on the TPU device.""" - del args, kwargs fn_inputs = dequeue_fn() if not isinstance(fn_inputs, tuple): fn_inputs = (fn_inputs,) - fn_result = fn(ctx, *fn_inputs) + fn_result = fn(ctx, fn_inputs) flat_last_step_outputs = nest.flatten(ctx.last_step_outputs) if flat_last_step_outputs: with ops.control_dependencies([fn_result]): @@ -265,11 +290,6 @@ class TPUStrategy(distribute_lib.DistributionStrategy): else: return fn_result - # TODO(sourabhbajaj): The input to while loop should be based on the output - # type of the step_fn - def iterate_on_tpu(): - return training_loop.repeat(iterations, run_fn, initial_loop_values) - # We capture the control_flow_context at this point, before we run `fn` # inside a while_loop and TPU replicate context. This is useful in cases # where we might need to exit these contexts and get back to the outer @@ -279,38 +299,70 @@ class TPUStrategy(distribute_lib.DistributionStrategy): self._outer_control_flow_context = ( ops.get_default_graph()._get_control_flow_context()) # pylint: disable=protected-access - replicate_inputs = [[]] * self.num_replicas - replicate_outputs = tpu.replicate(iterate_on_tpu, replicate_inputs) + def rewrite_fn(*args): + """The rewritten step fn running on TPU.""" + del args + replicate_inputs = [[]] * self._num_replicas_in_sync + replicate_outputs = tpu.replicate(run_fn, replicate_inputs) + + # If run_fn has tensor outputs, tpu.replicate returns a list of list. We + # will flatten it in this case. If run_fn has no tensor outputs, + # tpu.replicate returns a list of no_ops, we will keep the output as it + # is. + if isinstance(replicate_outputs[0], list): + replicate_outputs = nest.flatten(replicate_outputs) + + return replicate_outputs + + # TODO(sourabhbajaj): The input to while loop should be based on the output + # type of the step_fn + assert isinstance(initial_loop_values, list) + initial_loop_values = initial_loop_values * self._num_replicas_in_sync + + # Put the while loop op on host 0. + with ops.device(self.get_host_cpu_device(0)): + replicate_outputs = training_loop.repeat(iterations, rewrite_fn, + initial_loop_values) + del self._outer_control_flow_context ctx.run_op = control_flow_ops.group(replicate_outputs, enqueue_ops) - # Filter out any ops from the outputs, typically this would be the case - # when there were no tensor outputs. - last_step_tensor_outputs = [x for x in replicate_outputs - if not isinstance(x, ops.Operation)] - - # Outputs are currently of the structure (grouped by device) - # [[output0_device0, output1_device0, output2_device0], - # [output0_device1, output1_device1, output2_device1]] - # Convert this to the following structure instead: (grouped by output) - # [[output0_device0, output0_device1], - # [output1_device0, output1_device1], - # [output2_device0, output2_device1]] - last_step_tensor_outputs = [list(x) for x in zip(*last_step_tensor_outputs)] + if isinstance(replicate_outputs, list): + # Filter out any ops from the outputs, typically this would be the case + # when there were no tensor outputs. + last_step_tensor_outputs = [ + x for x in replicate_outputs if not isinstance(x, ops.Operation) + ] + + # Outputs are currently of the structure (flattened) + # [output0_device0, output1_device0, output2_device0, + # output0_device1, output1_device1, output2_device1, + # ...] + # Convert this to the following structure instead: (grouped by output) + # [[output0_device0, output0_device1], + # [output1_device0, output1_device1], + # [output2_device0, output2_device1]] + output_num = len(last_step_tensor_outputs) // self._num_replicas_in_sync + last_step_tensor_outputs = [ + last_step_tensor_outputs[i::output_num] for i in range(output_num) + ] + else: + # no tensors returned. + last_step_tensor_outputs = [] # Convert replicate_outputs to the original dict structure of # last_step_outputs. last_step_tensor_outputs_dict = nest.pack_sequence_as( ctx.last_step_outputs, last_step_tensor_outputs) - for (name, aggregation) in ctx._last_step_outputs_aggregations.items(): # pylint: disable=protected-access + for name, reduce_op in ctx._last_step_outputs_reduce_ops.items(): # pylint: disable=protected-access output = last_step_tensor_outputs_dict[name] - # For outputs that have already been aggregated, take the first value + # For outputs that have already been reduced, take the first value # from the list as each value should be the same. Else return the full # list of values. - # TODO(josh11b): If aggregation is NONE, we should return a PerReplica + # TODO(josh11b): If reduce_op is NONE, we should return a PerReplica # value. - if aggregation is not variables_lib.VariableAggregation.NONE: + if reduce_op is not None: # TODO(priyag): Should this return the element or a list with 1 element last_step_tensor_outputs_dict[name] = output[0] ctx._set_last_step_outputs(last_step_tensor_outputs_dict) # pylint: disable=protected-access @@ -320,10 +372,10 @@ class TPUStrategy(distribute_lib.DistributionStrategy): def _call_for_each_replica(self, fn, args, kwargs): # TODO(jhseu): Consider making it so call_for_each_replica implies that # we're in a tpu.rewrite(), and update TPUMirroredVariable accordingly. - with _TPUReplicaContext(self): + with _TPUReplicaContext(self._container_strategy()): return fn(*args, **kwargs) - def initialize(self): + def _initialize(self): if context.executing_eagerly(): # TODO(priyag): Add appopriate call here when eager is supported for TPUs. raise NotImplementedError("Eager mode not supported in TPUStrategy.") @@ -338,7 +390,7 @@ class TPUStrategy(distribute_lib.DistributionStrategy): tpu.initialize_system()) return graph.get_collection(_TPU_INITIALIZE_SYSTEM_COLLECTION) - def finalize(self): + def _finalize(self): if context.executing_eagerly(): # TODO(priyag): Add appopriate call here when eager is supported for TPUs. raise NotImplementedError("Eager mode not supported in TPUStrategy.") @@ -346,7 +398,7 @@ class TPUStrategy(distribute_lib.DistributionStrategy): return [tpu.shutdown_system()] def _get_devices_from(self, colocate_with=None): - # TODO(jhseu): Change this when we support model parallelism. + # TODO(jhseu): Change this when we support model parallelism. return self._tpu_devices def _create_variable(self, next_creator, *args, **kwargs): @@ -383,12 +435,12 @@ class TPUStrategy(distribute_lib.DistributionStrategy): return _create_tpu_mirrored_variable(devices, _real_mirrored_creator, *args, **kwargs) - def _reduce(self, aggregation, value, destinations): + def _reduce_to(self, reduce_op, value, destinations): if values._enclosing_tpu_context() is not None: # pylint: disable=protected-access - if aggregation == vs.VariableAggregation.MEAN: + if reduce_op == reduce_util.ReduceOp.MEAN: # TODO(jhseu): Revisit once we support model-parallelism. - value *= (1. / self.num_replicas) - elif aggregation != vs.VariableAggregation.SUM: + value *= (1. / self._num_replicas_in_sync) + elif reduce_op != reduce_util.ReduceOp.SUM: raise NotImplementedError( "Currently only support sum & mean in TPUStrategy.") return tpu_ops.cross_replica_sum(value) @@ -396,27 +448,22 @@ class TPUStrategy(distribute_lib.DistributionStrategy): # Validate that the destination is same as the host device # Note we don't do this when in replicate context as the reduction is # performed on the TPU device itself. - devices = cross_tower_ops_lib.get_devices_from(destinations) + devices = cross_device_ops_lib.get_devices_from(destinations) if len(devices) == 1: assert device_util.canonicalize(devices[0]) == device_util.canonicalize( self._host_device) else: raise ValueError("Multiple devices are not supported for TPUStrategy") - if aggregation == vs.VariableAggregation.ONLY_FIRST_REPLICA: - return value[0] output = math_ops.add_n(value) - if aggregation == vs.VariableAggregation.MEAN: + if reduce_op == reduce_util.ReduceOp.MEAN: return output * (1. / len(value)) return output - def _update(self, var, options, fn, *args, **kwargs): + def _update(self, var, fn, args, kwargs, group): assert isinstance(var, values.TPUMirroredVariable) - should_group = options.pop("grouped") - assert not options # Validate that we are processing all of the options. - if values._enclosing_tpu_context() is not None: # pylint: disable=protected-access - if should_group: + if group: return fn(var, *args, **kwargs) else: return [fn(var, *args, **kwargs)] @@ -431,9 +478,7 @@ class TPUStrategy(distribute_lib.DistributionStrategy): updates[d] = fn(v, *values.select_device_mirrored(d, args), **values.select_device_mirrored(d, kwargs)) - return values.update_regroup(self, updates, should_group) - - # TODO(josh11b): Need to implement _update_non_slot()! + return values.update_regroup(self, updates, group) def read_var(self, var): assert isinstance(var, values.TPUMirroredVariable) @@ -453,14 +498,10 @@ class TPUStrategy(distribute_lib.DistributionStrategy): def value_container(self, value): return value - def _broadcast(self, tensor, destinations): + def _broadcast_to(self, tensor, destinations): del destinations return tensor - @property - def num_replicas(self): - return self._num_cores_override or self._tpu_metadata.num_cores - @property def num_hosts(self): return self._tpu_metadata.num_hosts @@ -470,15 +511,15 @@ class TPUStrategy(distribute_lib.DistributionStrategy): return self._tpu_metadata.num_of_cores_per_host @property - def num_replicas_in_sync(self): - return self.num_replicas + def _num_replicas_in_sync(self): + return self._num_cores_override or self._tpu_metadata.num_cores @property - def between_graph(self): + def experimental_between_graph(self): return False @property - def should_init(self): + def experimental_should_init(self): return True @property @@ -500,14 +541,12 @@ class TPUStrategy(distribute_lib.DistributionStrategy): def non_slot_devices(self, var_list): return self._host_device - def _update_non_slot(self, colocate_with, options, fn, *args, **kwargs): + def _update_non_slot(self, colocate_with, fn, args, kwargs, group): del colocate_with - should_group = options.pop("grouped") - assert not options # Validate that we are processing all of the options. with ops.device(self._host_device), distribute_lib.UpdateContext( self._host_device): result = fn(*args, **kwargs) - if should_group: + if group: return result else: return nest.map_structure(self._unwrap, result) @@ -521,17 +560,27 @@ class TPUStrategy(distribute_lib.DistributionStrategy): def get_host_cpu_device(self, host_id): return self.get_host(host_id) + "/device:CPU:0" - def configure(self, - session_config=None, - cluster_spec=None, - task_type=None, - task_id=None): + def _configure(self, + session_config=None, + cluster_spec=None, + task_type=None, + task_id=None): del cluster_spec, task_type, task_id if session_config: - session_config.isolate_session_state = True - cluster_spec = self._tpu_cluster_resolver.cluster_spec() - if cluster_spec: - session_config.cluster_def.CopyFrom(cluster_spec.as_cluster_def()) + session_config.CopyFrom(self._update_config_proto(session_config)) + + def _update_config_proto(self, config_proto): + updated_config = copy.deepcopy(config_proto) + updated_config.isolate_session_state = True + cluster_spec = self._tpu_cluster_resolver.cluster_spec() + if cluster_spec: + updated_config.cluster_def.CopyFrom(cluster_spec.as_cluster_def()) + return updated_config + + # TODO(priyag): Delete this once all strategies use global batch size. + @property + def _global_batch_size(self): + return True class _TPUReplicaContext(distribute_lib.ReplicaContext): @@ -540,13 +589,14 @@ class _TPUReplicaContext(distribute_lib.ReplicaContext): # TODO(sourabhbajaj): Call for each tower should be updating this. def __init__(self, distribution_strategy): distribute_lib.ReplicaContext.__init__( - self, distribution_strategy, replica_id=0) - - @property - def device(self): - raise RuntimeError("Use .devices instead") + self, + distribution_strategy, + # TODO(b/118385803): properly initialize replica_id, instead of always 0 + replica_id_in_sync_group=constant_op.constant(0, dtypes.int32)) @property def devices(self): distribute_lib.require_replica_context(self) - return [self._distribution_strategy.worker_devices[self._replica_id]] + ds = self._distribution_strategy + replica_id = tensor_util.constant_value(self._replica_id_in_sync_group) + return [ds.extended.worker_devices[replica_id]] diff --git a/tensorflow/contrib/distribute/python/values_test.py b/tensorflow/contrib/distribute/python/values_test.py index 268393ee80..538b859f3d 100644 --- a/tensorflow/contrib/distribute/python/values_test.py +++ b/tensorflow/contrib/distribute/python/values_test.py @@ -19,12 +19,15 @@ from __future__ import division from __future__ import print_function import os +from absl.testing import parameterized -from tensorflow.contrib.distribute.python import mirrored_strategy +from tensorflow.contrib.distribute.python import combinations from tensorflow.contrib.distribute.python import multi_worker_test_base -from tensorflow.contrib.distribute.python import values from tensorflow.core.protobuf import config_pb2 from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import values from tensorflow.python.eager import context from tensorflow.python.eager import test from tensorflow.python.estimator import model_fn as model_fn_lib @@ -34,10 +37,10 @@ from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables as variables_lib -from tensorflow.python.training import device_util from tensorflow.python.training import saver as saver_lib from tensorflow.python.util import nest @@ -324,20 +327,20 @@ class RegroupAndSelectDeviceTest(test.TestCase): self.assertTrue( isinstance(merged_estimator_spec, model_fn_lib.EstimatorSpec)) - self.assertEquals(model_fn_lib.ModeKeys.TRAIN, merged_estimator_spec.mode) + self.assertEqual(model_fn_lib.ModeKeys.TRAIN, merged_estimator_spec.mode) for device_id in range(3): d = _device_str(device_id) - self.assertEquals(created_estimator_specs[device_id].loss, - merged_estimator_spec.loss.get(d)) - self.assertEquals(created_estimator_specs[device_id].train_op, - merged_estimator_spec.train_op.get(d)) + self.assertEqual(created_estimator_specs[device_id].loss, + merged_estimator_spec.loss.get(d)) + self.assertEqual(created_estimator_specs[device_id].train_op, + merged_estimator_spec.train_op.get(d)) # Scaffold is populated by `EstimatorSpec.__new__`. - self.assertEquals(created_estimator_specs[device_id].scaffold, - merged_estimator_spec.scaffold.get(d)) + self.assertEqual(created_estimator_specs[device_id].scaffold, + merged_estimator_spec.scaffold.get(d)) # Also test that we can undo the merge using select_device() - self.assertEquals(created_estimator_specs[device_id], - values.select_device(_device_str(device_id), - merged_estimator_spec)) + self.assertEqual(created_estimator_specs[device_id], + values.select_device(_device_str(device_id), + merged_estimator_spec)) class PerReplicaDatasetTest(test.TestCase): @@ -568,7 +571,184 @@ class MultiWorkerDatasetTest(multi_worker_test_base.MultiWorkerTestBase): multi_worker_iterator.get_next() -class MirroredVariableTest(test.TestCase): +class InputIteratorTestBase(test.TestCase): + + def _test_iterator(self, input_type, dataset_fn, worker_device_pairs, + expected_values, sess=None, split_batch_by=None): + devices = nest.flatten([ds for _, ds in worker_device_pairs]) + + if input_type == "input_fn": + input_contexts = [ + distribute_lib.InputContext() for _ in worker_device_pairs] + input_fn = lambda _: dataset_fn() + iterator = values.InputFunctionIterator(input_fn, worker_device_pairs, + input_contexts) + else: + iterator = values.DatasetIterator(dataset_fn(), worker_device_pairs, + split_batch_by) + + evaluate = lambda x: sess.run(x) if sess else self.evaluate(x) + + evaluate(control_flow_ops.group(iterator.initialize())) + + for expected_value in expected_values: + next_element = iterator.get_next() + computed_value = evaluate( + [values.select_device(d, next_element) for d in devices]) + self.assertAllEqual(expected_value, computed_value) + + with self.assertRaises(errors.OutOfRangeError): + next_element = iterator.get_next() + evaluate([values.select_device(d, next_element) for d in devices]) + + # After re-initializing the iterator, should be able to iterate again. + evaluate(control_flow_ops.group(iterator.initialize())) + + for expected_value in expected_values: + next_element = iterator.get_next() + computed_value = evaluate( + [values.select_device(d, next_element) for d in devices]) + self.assertAllEqual(expected_value, computed_value) + + +class InputIteratorSingleWorkerTest(InputIteratorTestBase, + parameterized.TestCase): + + @combinations.generate(combinations.combine( + mode=["graph", "eager"], + input_type=["input_fn", "dataset"])) + def testOneDeviceCPU(self, input_type): + worker_device_pairs = [("", ["/device:CPU:0"])] + dataset_fn = lambda: dataset_ops.Dataset.range(10) + + expected_values = [[i] for i in range(10)] + + self._test_iterator(input_type, dataset_fn, worker_device_pairs, + expected_values) + + @combinations.generate(combinations.combine( + mode=["graph", "eager"], + input_type=["input_fn", "dataset"], + required_gpus=1)) + def testTwoDevicesOneGPUOneCPU(self, input_type): + worker_device_pairs = [("", ["/device:GPU:0", "/device:CPU:0"])] + dataset_fn = lambda: dataset_ops.Dataset.range(10) + + expected_values = [[i, i+1] for i in range(0, 10, 2)] + + self._test_iterator(input_type, dataset_fn, worker_device_pairs, + expected_values) + + @combinations.generate(combinations.combine( + mode=["graph", "eager"], + input_type=["input_fn", "dataset"], + required_gpus=1)) + def testTupleDataset(self, input_type): + worker_device_pairs = [("", ["/device:GPU:0", "/device:CPU:0"])] + def dataset_fn(): + dataset1 = dataset_ops.Dataset.range(10) + dataset2 = dataset_ops.Dataset.range(10).map(lambda x: x**2) + return dataset_ops.Dataset.zip((dataset1, dataset2)) + + expected_values = [[(i, i**2), (i+1, (i+1)**2)] for i in range(0, 10, 2)] + + self._test_iterator(input_type, dataset_fn, worker_device_pairs, + expected_values) + + @combinations.generate(combinations.combine( + mode=["graph", "eager"], + input_type=["input_fn", "dataset"], + required_gpus=1)) + def testUnevenDatasetBatches(self, input_type): + worker_device_pairs = [("", ["/device:GPU:0", "/device:CPU:0"])] + dataset_fn = lambda: dataset_ops.Dataset.range(11) + + expected_values = [[i, i+1] for i in range(0, 10, 2)] + self._test_iterator(input_type, dataset_fn, worker_device_pairs, + expected_values) + + @combinations.generate(combinations.combine( + mode=["graph", "eager"], + input_type=["dataset"], + split_batch_by=[None, 2], + required_gpus=1)) + def testBatchSplitting(self, input_type, split_batch_by): + worker_device_pairs = [("", ["/device:GPU:0", "/device:CPU:0"])] + batch_size = 10 + dataset_fn = lambda: dataset_ops.Dataset.range(100).batch(batch_size) + + updated_batch_size = ( + batch_size // split_batch_by if split_batch_by else batch_size) + expected_values = [[range(i, i+updated_batch_size), + range(i+updated_batch_size, i+2*updated_batch_size)] + for i in range(0, 100, updated_batch_size*2)] + + self._test_iterator(input_type, dataset_fn, worker_device_pairs, + expected_values, sess=None, + split_batch_by=split_batch_by) + + +class InputIteratorMultiWorkerTest( + multi_worker_test_base.MultiWorkerTestBase, InputIteratorTestBase, + parameterized.TestCase): + + def _cpu_devices(self): + return [ + ("/job:worker/replica:0/task:0", + ["/job:worker/replica:0/task:0/device:CPU:0"]), + ("/job:worker/replica:0/task:1", + ["/job:worker/replica:0/task:1/device:CPU:0"])] + + def _cpu_and_one_gpu_devices(self): + return [ + ("/job:worker/replica:0/task:0", [ + "/job:worker/replica:0/task:0/device:GPU:0", + "/job:worker/replica:0/task:0/device:CPU:0" + ]), + ("/job:worker/replica:0/task:1", [ + "/job:worker/replica:0/task:1/device:GPU:0", + "/job:worker/replica:0/task:1/device:CPU:0" + ]) + ] + + @combinations.generate(combinations.combine( + mode=["graph"], + input_type=["input_fn", "dataset"])) + def testOneDevicePerWorker(self, input_type): + worker_devices = self._cpu_devices() + with context.graph_mode(), self.cached_session() as sess: + dataset_fn = lambda: dataset_ops.Dataset.range(4) + self._test_iterator(input_type, dataset_fn, worker_devices, + [[0, 0], [1, 1], [2, 2], [3, 3]], sess) + + @combinations.generate(combinations.combine( + mode=["graph"], + input_type=["input_fn", "dataset"], + required_gpus=1)) + def testTwoDevicesPerWorker(self, input_type): + worker_devices = self._cpu_and_one_gpu_devices() + with context.graph_mode(), self.cached_session() as sess: + dataset_fn = lambda: dataset_ops.Dataset.range(4) + self._test_iterator(input_type, dataset_fn, worker_devices, + [[0, 1, 0, 1], [2, 3, 2, 3]], sess) + + @combinations.generate(combinations.combine( + mode=["graph"], + input_type=["input_fn", "dataset"])) + def testTupleDataset(self, input_type): + worker_devices = self._cpu_devices() + with context.graph_mode(), self.cached_session() as sess: + def dataset_fn(): + dataset1 = dataset_ops.Dataset.range(4) + dataset2 = dataset_ops.Dataset.range(4).map(lambda x: x**2) + return dataset_ops.Dataset.zip((dataset1, dataset2)) + + expected_values = [[(i, i**2), (i, i**2)] for i in range(0, 4)] + self._test_iterator(input_type, dataset_fn, worker_devices, + expected_values, sess) + + +class MirroredVariableTest(test.TestCase, parameterized.TestCase): config = config_pb2.ConfigProto() config.allow_soft_placement = True @@ -580,9 +760,9 @@ class MirroredVariableTest(test.TestCase): v, _, mirrored = _make_mirrored() - self.assertEquals(v[0].name, mirrored.name) - self.assertEquals(v[0].dtype, mirrored.dtype) - self.assertEquals(v[0].shape, mirrored.shape) + self.assertEqual(v[0].name, mirrored.name) + self.assertEqual(v[0].dtype, mirrored.dtype) + self.assertEqual(v[0].shape, mirrored.shape) @test_util.run_in_graph_and_eager_modes(config=config) def testVariableOnAnotherDevice(self): @@ -592,9 +772,9 @@ class MirroredVariableTest(test.TestCase): mirrored = values.MirroredVariable(index, v, variable_scope.VariableAggregation.MEAN) - self.assertEquals(v.name, mirrored.name) - self.assertEquals(v.dtype, mirrored.dtype) - self.assertEquals(v.shape, mirrored.shape) + self.assertEqual(v.name, mirrored.name) + self.assertEqual(v.dtype, mirrored.dtype) + self.assertEqual(v.shape, mirrored.shape) def _assign_mirrored(self, devices, v, new): for d, var, n in zip(devices, v, new): @@ -714,14 +894,13 @@ class MirroredVariableTest(test.TestCase): save_path = self._save_normal() self._restore_mirrored(save_path) - @test_util.run_in_graph_and_eager_modes(config=config) - def testFetchAMirroredVariable(self): - if context.num_gpus() < 1 or context.executing_eagerly(): - self.skipTest("A GPU is not available for this test or it's eager mode.") - - with self.session( - graph=ops.Graph()) as sess, mirrored_strategy.MirroredStrategy( - ["/device:GPU:0"]).scope(): + @combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_one_gpu, + combinations.core_mirrored_strategy_with_one_gpu], + mode=["graph"])) + def testFetchAMirroredVariable(self, distribution): + with self.session(graph=ops.Graph()) as sess, distribution.scope(): with ops.device("/device:GPU:0"): v = variable_scope.get_variable( name="v", initializer=1., use_resource=True) @@ -747,7 +926,7 @@ def _make_replica_local(method): return v, replica_local -class ReplicaLocalVariableTest(test.TestCase): +class ReplicaLocalVariablePropertiesTest(test.TestCase): config = config_pb2.ConfigProto() config.allow_soft_placement = True @@ -756,15 +935,14 @@ class ReplicaLocalVariableTest(test.TestCase): def testProperties(self): if context.num_gpus() < 1 and context.executing_eagerly(): self.skipTest("A GPU is not available for this test in eager mode.") - v, replica_local = _make_replica_local( variable_scope.VariableAggregation.SUM) - self.assertEquals(v[0].name, replica_local.name) - self.assertEquals(v[0].dtype, replica_local.dtype) - self.assertEquals(v[0].shape, replica_local.shape) - self.assertEquals(variable_scope.VariableAggregation.SUM, - replica_local.aggregation) + self.assertEqual(v[0].name, replica_local.name) + self.assertEqual(v[0].dtype, replica_local.dtype) + self.assertEqual(v[0].shape, replica_local.shape) + self.assertEqual(variable_scope.VariableAggregation.SUM, + replica_local.aggregation) @test_util.run_in_graph_and_eager_modes(config=config) def testVariableOnAnotherDevice(self): @@ -774,11 +952,32 @@ class ReplicaLocalVariableTest(test.TestCase): replica_local = values.ReplicaLocalVariable( index, v, variable_scope.VariableAggregation.MEAN) - self.assertEquals(v.name, replica_local.name) - self.assertEquals(v.dtype, replica_local.dtype) - self.assertEquals(v.shape, replica_local.shape) - self.assertEquals(variable_scope.VariableAggregation.MEAN, - replica_local.aggregation) + self.assertEqual(v.name, replica_local.name) + self.assertEqual(v.dtype, replica_local.dtype) + self.assertEqual(v.shape, replica_local.shape) + self.assertEqual(variable_scope.VariableAggregation.MEAN, + replica_local.aggregation) + + def testTensorConversion(self): + with context.graph_mode(): + _, replica_local = _make_replica_local( + variable_scope.VariableAggregation.SUM) + converted = ops.internal_convert_to_tensor(replica_local, as_ref=False) + self.assertIsInstance(converted, ops.Tensor) + self.assertEqual(converted.dtype, replica_local.dtype) + + converted = ops.internal_convert_to_tensor(replica_local, as_ref=True) + # Resources variable are converted to tensors as well when as_ref is True. + self.assertIsInstance(converted, ops.Tensor) + self.assertEqual(converted.dtype, replica_local.dtype) + + +@combinations.generate(combinations.combine( + distribution=[ + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_gpu_and_cpu], + mode=["graph", "eager"])) +class ReplicaLocalVariableTest(test.TestCase, parameterized.TestCase): def _assign_replica_local(self, devices, v, new): for d, var, n in zip(devices, v, new): @@ -795,22 +994,15 @@ class ReplicaLocalVariableTest(test.TestCase): save_path, _ = self._save_return_saver(sess, var) return save_path - def _dist_scope(self): - return mirrored_strategy.MirroredStrategy(_devices).scope() - - @test_util.run_in_graph_and_eager_modes(config=config) - def testSaveAndRestoreReplicaLocalSumOneGraph(self): - if context.num_gpus() < 1 and context.executing_eagerly(): - self.skipTest("A GPU is not available for this test in eager mode.") - - with self.cached_session(config=self.config) as sess: + def testSaveAndRestoreReplicaLocalSumOneGraph(self, distribution): + with self.cached_session() as sess: v, replica_local = _make_replica_local( variable_scope.VariableAggregation.SUM) # Overwrite the initial values. self._assign_replica_local(_devices, v, [3., 4.]) - with self._dist_scope(): + with distribution.scope(): # Saves the current value of v[0] + v[1], 7. save_path, saver = self._save_return_saver(sess, replica_local) @@ -822,19 +1014,18 @@ class ReplicaLocalVariableTest(test.TestCase): saver.restore(sess, save_path) self.assertEqual([3.5, 3.5], self.evaluate([v[0], v[1]])) - @test_util.run_in_graph_and_eager_modes(config=config) - def testSaveAndRestoreReplicaLocalMeanOneGraph(self): + def testSaveAndRestoreReplicaLocalMeanOneGraph(self, distribution): if context.num_gpus() < 1 and context.executing_eagerly(): self.skipTest("A GPU is not available for this test in eager mode.") - with self.cached_session(config=self.config) as sess: + with self.cached_session() as sess: v, replica_local = _make_replica_local( variable_scope.VariableAggregation.MEAN) # Overwrite the initial values. self._assign_replica_local(_devices, v, [3., 4.]) - with self._dist_scope(): + with distribution.scope(): # Saves the current value of (v[0] + v[1])/2, 3.5. save_path, saver = self._save_return_saver(sess, replica_local) @@ -845,7 +1036,7 @@ class ReplicaLocalVariableTest(test.TestCase): saver.restore(sess, save_path) self.assertEqual([3.5, 3.5], self.evaluate([v[0], v[1]])) - def _save_replica_local_mean(self): + def _save_replica_local_mean(self, distribution): """Save variables with mirroring, returns save_path.""" with self.session(graph=ops.Graph()) as sess: v, replica_local = _make_replica_local( @@ -854,7 +1045,7 @@ class ReplicaLocalVariableTest(test.TestCase): # Overwrite the initial values. self._assign_replica_local(_devices, v, [3., 4.]) - with self._dist_scope(): + with distribution.scope(): # Saves the current value of (v[0] + v[1])/2, 3.5 save_path = self._save(sess, replica_local) @@ -862,7 +1053,7 @@ class ReplicaLocalVariableTest(test.TestCase): self._assign_replica_local(_devices, v, [5., 6.]) return save_path - def _save_replica_local_sum(self): + def _save_replica_local_sum(self, distribution): """Save variables with mirroring, returns save_path.""" with self.session(graph=ops.Graph()) as sess: v, replica_local = _make_replica_local("sum") @@ -870,7 +1061,7 @@ class ReplicaLocalVariableTest(test.TestCase): # Overwrite the initial values. self._assign_replica_local(_devices, v, [1.5, 2.]) - with self._dist_scope(): + with distribution.scope(): # Saves the current value of v[0] + v[1], 3.5 save_path = self._save(sess, replica_local) @@ -908,7 +1099,7 @@ class ReplicaLocalVariableTest(test.TestCase): saver.restore(sess, save_path) self.assertEqual(3.5, self.evaluate(var)) - def _restore_replica_local_mean(self, save_path): + def _restore_replica_local_mean(self, save_path, distribution): """Restore to variables with mirroring in a fresh graph.""" with self.session(graph=ops.Graph()) as sess: v, replica_local = _make_replica_local( @@ -917,13 +1108,13 @@ class ReplicaLocalVariableTest(test.TestCase): # Overwrite the initial values. self._assign_replica_local(_devices, v, [7., 8.]) - with self._dist_scope(): + with distribution.scope(): # Restores the saved value of 3.5 to both variables. saver = saver_lib.Saver(var_list=[replica_local]) saver.restore(sess, save_path) self.assertEqual([3.5, 3.5], self.evaluate([v[0], v[1]])) - def _restore_replica_local_sum(self, save_path): + def _restore_replica_local_sum(self, save_path, distribution): """Restore to variables with mirroring in a fresh graph.""" with self.session(graph=ops.Graph()) as sess: v, replica_local = _make_replica_local( @@ -932,72 +1123,35 @@ class ReplicaLocalVariableTest(test.TestCase): # Overwrite the initial values. self._assign_replica_local(_devices, v, [7., 8.]) - with self._dist_scope(): + with distribution.scope(): # Restores the saved value of 3.5 to both variables. saver = saver_lib.Saver(var_list=[replica_local]) saver.restore(sess, save_path) self.assertEqual([1.75, 1.75], self.evaluate([v[0], v[1]])) - @test_util.run_in_graph_and_eager_modes(config=config) - def testSaveReplicaLocalRestoreReplicaLocalMean(self): - if context.num_gpus() < 1 and context.executing_eagerly(): - self.skipTest("A GPU is not available for this test in eager mode.") + def testSaveReplicaLocalRestoreReplicaLocalMean(self, distribution): + save_path = self._save_replica_local_mean(distribution) + self._restore_replica_local_mean(save_path, distribution) - save_path = self._save_replica_local_mean() - self._restore_replica_local_mean(save_path) + def testSaveReplicaLocalRestoreReplicaLocalSum(self, distribution): + save_path = self._save_replica_local_sum(distribution) + self._restore_replica_local_sum(save_path, distribution) - @test_util.run_in_graph_and_eager_modes(config=config) - def testSaveReplicaLocalRestoreReplicaLocalSum(self): - if context.num_gpus() < 1 and context.executing_eagerly(): - self.skipTest("A GPU is not available for this test in eager mode.") - - save_path = self._save_replica_local_sum() - self._restore_replica_local_sum(save_path) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testSaveReplicaLocalMeanRestoreNormal(self): - if context.num_gpus() < 1 and context.executing_eagerly(): - self.skipTest("A GPU is not available for this test in eager mode.") - - save_path = self._save_replica_local_mean() + def testSaveReplicaLocalMeanRestoreNormal(self, distribution): + save_path = self._save_replica_local_mean(distribution) self._restore_normal(save_path) - @test_util.run_in_graph_and_eager_modes(config=config) - def testSaveReplicaLocalSumRestoreNormal(self): - if context.num_gpus() < 1 and context.executing_eagerly(): - self.skipTest("A GPU is not available for this test in eager mode.") - - save_path = self._save_replica_local_sum() + def testSaveReplicaLocalSumRestoreNormal(self, distribution): + save_path = self._save_replica_local_sum(distribution) self._restore_normal(save_path) - @test_util.run_in_graph_and_eager_modes(config=config) - def testSaveNormalRestoreReplicaLocalMean(self): - if context.num_gpus() < 1 and context.executing_eagerly(): - self.skipTest("A GPU is not available for this test in eager mode.") - + def testSaveNormalRestoreReplicaLocalMean(self, distribution): save_path = self._save_normal() - self._restore_replica_local_mean(save_path) - - @test_util.run_in_graph_and_eager_modes(config=config) - def testSaveNormalRestoreReplicaLocalSum(self): - if context.num_gpus() < 1 and context.executing_eagerly(): - self.skipTest("A GPU is not available for this test in eager mode.") + self._restore_replica_local_mean(save_path, distribution) + def testSaveNormalRestoreReplicaLocalSum(self, distribution): save_path = self._save_normal() - self._restore_replica_local_sum(save_path) - - def testTensorConversion(self): - with context.graph_mode(): - _, replica_local = _make_replica_local( - variable_scope.VariableAggregation.SUM) - converted = ops.internal_convert_to_tensor(replica_local, as_ref=False) - self.assertIsInstance(converted, ops.Tensor) - self.assertEqual(converted.dtype, replica_local.dtype) - - converted = ops.internal_convert_to_tensor(replica_local, as_ref=True) - # Resources variable are converted to tensors as well when as_ref is True. - self.assertIsInstance(converted, ops.Tensor) - self.assertEqual(converted.dtype, replica_local.dtype) + self._restore_replica_local_sum(save_path, distribution) if __name__ == "__main__": diff --git a/tensorflow/contrib/distribute/python/warm_starting_util_test.py b/tensorflow/contrib/distribute/python/warm_starting_util_test.py index 5d57d144c1..b0bcf9b174 100644 --- a/tensorflow/contrib/distribute/python/warm_starting_util_test.py +++ b/tensorflow/contrib/distribute/python/warm_starting_util_test.py @@ -44,7 +44,9 @@ class WarmStartingUtilWithDistributionStrategyTest( distribution=[combinations.default_strategy, combinations.one_device_strategy, combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus], + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus], save_with_distribution=[True, False], restore_with_distribution=[True, False], mode=["graph"])) diff --git a/tensorflow/contrib/distributions/BUILD b/tensorflow/contrib/distributions/BUILD index 60f6b90edc..3079175015 100644 --- a/tensorflow/contrib/distributions/BUILD +++ b/tensorflow/contrib/distributions/BUILD @@ -72,7 +72,6 @@ py_library( "//tensorflow/python:nn", "//tensorflow/python:nn_ops", "//tensorflow/python:random_ops", - "//tensorflow/python:spectral_ops", "//tensorflow/python:state_ops", "//tensorflow/python:tensor_util", "//tensorflow/python:util", @@ -80,6 +79,7 @@ py_library( "//tensorflow/python:variables", "//tensorflow/python/ops/distributions", "//tensorflow/python/ops/linalg", + "//tensorflow/python/ops/signal", "//third_party/py/numpy", "@six_archive//:six", ], diff --git a/tensorflow/contrib/distributions/python/kernel_tests/normal_conjugate_posteriors_test.py b/tensorflow/contrib/distributions/python/kernel_tests/normal_conjugate_posteriors_test.py index 29eeaf43c5..ab3c07172a 100644 --- a/tensorflow/contrib/distributions/python/kernel_tests/normal_conjugate_posteriors_test.py +++ b/tensorflow/contrib/distributions/python/kernel_tests/normal_conjugate_posteriors_test.py @@ -82,7 +82,7 @@ class NormalTest(test.TestCase): x = constant_op.constant( [[-2.5, 2.5, 4.0, 0.0, -1.0, 2.0], [2.5, -2.5, -4.0, 0.0, 1.0, -2.0]], dtype=dtypes.float32) - s = math_ops.reduce_sum(x, reduction_indices=[1]) + s = math_ops.reduce_sum(x, axis=[1]) x = array_ops.transpose(x) # Reshape to shape (6, 2) n = constant_op.constant([6] * 2) prior = distributions.Normal(loc=mu0, scale=sigma0) diff --git a/tensorflow/contrib/distributions/python/kernel_tests/wishart_test.py b/tensorflow/contrib/distributions/python/kernel_tests/wishart_test.py index a60056c444..cdee30bbc4 100644 --- a/tensorflow/contrib/distributions/python/kernel_tests/wishart_test.py +++ b/tensorflow/contrib/distributions/python/kernel_tests/wishart_test.py @@ -147,14 +147,13 @@ class WishartCholeskyTest(test.TestCase): x = chol_w.sample(10000, seed=42) self.assertAllEqual((10000, 3, 3), x.get_shape()) - moment1_estimate = math_ops.reduce_mean(x, reduction_indices=[0]).eval() + moment1_estimate = math_ops.reduce_mean(x, axis=[0]).eval() self.assertAllClose(chol_w.mean().eval(), moment1_estimate, rtol=0.05) # The Variance estimate uses the squares rather than outer-products # because Wishart.Variance is the diagonal of the Wishart covariance # matrix. - variance_estimate = (math_ops.reduce_mean( - math_ops.square(x), reduction_indices=[0]) - + variance_estimate = (math_ops.reduce_mean(math_ops.square(x), axis=[0]) - math_ops.square(moment1_estimate)).eval() self.assertAllClose( chol_w.variance().eval(), variance_estimate, rtol=0.05) diff --git a/tensorflow/contrib/distributions/python/ops/bijectors/softmax_centered.py b/tensorflow/contrib/distributions/python/ops/bijectors/softmax_centered.py index 15c241d5d7..74765f19e5 100644 --- a/tensorflow/contrib/distributions/python/ops/bijectors/softmax_centered.py +++ b/tensorflow/contrib/distributions/python/ops/bijectors/softmax_centered.py @@ -168,7 +168,7 @@ class SoftmaxCentered(bijector.Bijector): # log_normalization = 1 + reduce_sum(exp(logits)) # -log_normalization + reduce_sum(logits - log_normalization) log_normalization = nn_ops.softplus( - math_ops.reduce_logsumexp(x, axis=-1, keep_dims=True)) + math_ops.reduce_logsumexp(x, axis=-1, keepdims=True)) return array_ops.squeeze( (-log_normalization + math_ops.reduce_sum( x - log_normalization, axis=-1, keepdims=True)), axis=-1) diff --git a/tensorflow/contrib/distributions/python/ops/sample_stats.py b/tensorflow/contrib/distributions/python/ops/sample_stats.py index aa680a92be..978e627d66 100644 --- a/tensorflow/contrib/distributions/python/ops/sample_stats.py +++ b/tensorflow/contrib/distributions/python/ops/sample_stats.py @@ -29,8 +29,8 @@ from tensorflow.python.ops import clip_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import nn_ops -from tensorflow.python.ops import spectral_ops from tensorflow.python.ops.distributions import util +from tensorflow.python.ops.signal import fft_ops __all__ = [ "auto_correlation", @@ -157,11 +157,11 @@ def auto_correlation( dtype.real_dtype.as_numpy_dtype(0.)) # Autocorrelation is IFFT of power-spectral density (up to some scaling). - fft_x_rotated_pad = spectral_ops.fft(x_rotated_pad) + fft_x_rotated_pad = fft_ops.fft(x_rotated_pad) spectral_density = fft_x_rotated_pad * math_ops.conj(fft_x_rotated_pad) # shifted_product is R[m] from above detailed explanation. # It is the inner product sum_n X[n] * Conj(X[n - m]). - shifted_product = spectral_ops.ifft(spectral_density) + shifted_product = fft_ops.ifft(spectral_density) # Cast back to real-valued if x was real to begin with. shifted_product = math_ops.cast(shifted_product, dtype) diff --git a/tensorflow/contrib/eager/python/datasets.py b/tensorflow/contrib/eager/python/datasets.py index 3aed121233..34614b86a7 100644 --- a/tensorflow/contrib/eager/python/datasets.py +++ b/tensorflow/contrib/eager/python/datasets.py @@ -52,12 +52,6 @@ class Iterator(iterator_ops.EagerIterator): TypeError: If `dataset` is an unsupported type. RuntimeError: When invoked without eager execution enabled. """ - if isinstance(dataset, prefetching_ops._PrefetchToDeviceDataset): # pylint: disable=protected-access - raise TypeError( - "`tf.data.experimental.prefetch_to_device()` is not compatible with " - "`tf.contrib.eager.Iterator`. Use `for ... in dataset:` to iterate " - "over the dataset instead.") - if not context.context().device_spec.device_type: is_remote_device = False else: diff --git a/tensorflow/contrib/eager/python/datasets_test.py b/tensorflow/contrib/eager/python/datasets_test.py index 6a508fc6ba..257d02057a 100644 --- a/tensorflow/contrib/eager/python/datasets_test.py +++ b/tensorflow/contrib/eager/python/datasets_test.py @@ -26,7 +26,6 @@ import numpy as np from tensorflow.contrib import lookup from tensorflow.contrib.eager.python import datasets from tensorflow.python.data import Dataset -from tensorflow.python.data.experimental.ops import prefetching_ops from tensorflow.python.data.experimental.ops import threadpool from tensorflow.python.data.experimental.ops import unique from tensorflow.python.eager import test @@ -208,18 +207,6 @@ class IteratorTest(test.TestCase): y = math_ops.add(x, x) self.assertAllEqual([0., 2.], y.numpy()) - def testTensorsExplicitPrefetchToDevice(self): - ds = Dataset.from_tensor_slices([0., 1.]) - ds = ds.apply(prefetching_ops.prefetch_to_device(test.gpu_device_name())) - - with self.assertRaisesRegexp(TypeError, 'prefetch_to_device'): - datasets.Iterator(ds) - - for i, x in enumerate(ds): - with ops.device(test.gpu_device_name()): - x = math_ops.add(x, x) - self.assertEqual(float(i) + float(i), x.numpy()) - def testOverrideThreadPool(self): def get_thread_id(_): diff --git a/tensorflow/contrib/eager/python/evaluator.py b/tensorflow/contrib/eager/python/evaluator.py index 7949a3f6da..51443d2482 100644 --- a/tensorflow/contrib/eager/python/evaluator.py +++ b/tensorflow/contrib/eager/python/evaluator.py @@ -22,6 +22,7 @@ import six from tensorflow.contrib.eager.python import datasets from tensorflow.contrib.eager.python import metrics +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.eager import context from tensorflow.python.eager import function from tensorflow.python.framework import errors_impl @@ -164,8 +165,8 @@ class Evaluator(object): self.__call__(example, *args, **kwargs) return self.all_metric_results(summary_logdir) # Graph construction - call_op = self.__call__(dataset.make_one_shot_iterator().get_next(), *args, - **kwargs) + call_op = self.__call__( + dataset_ops.make_one_shot_iterator(dataset).get_next(), *args, **kwargs) init_op = self.init_variables() results_op = self.all_metric_results(summary_logdir) return (init_op, call_op, results_op) diff --git a/tensorflow/contrib/eager/python/examples/densenet/BUILD b/tensorflow/contrib/eager/python/examples/densenet/BUILD index 2dc196f550..e2154fcc5f 100644 --- a/tensorflow/contrib/eager/python/examples/densenet/BUILD +++ b/tensorflow/contrib/eager/python/examples/densenet/BUILD @@ -3,6 +3,7 @@ licenses(["notice"]) # Apache 2.0 package(default_visibility = ["//tensorflow:internal"]) load("//tensorflow:tensorflow.bzl", "cuda_py_test") +load("//tensorflow:tensorflow.bzl", "py_binary") py_binary( name = "densenet", diff --git a/tensorflow/contrib/eager/python/examples/densenet/densenet_graph_test.py b/tensorflow/contrib/eager/python/examples/densenet/densenet_graph_test.py index 4b3cb624bc..24f6b007b5 100644 --- a/tensorflow/contrib/eager/python/examples/densenet/densenet_graph_test.py +++ b/tensorflow/contrib/eager/python/examples/densenet/densenet_graph_test.py @@ -119,7 +119,8 @@ class DensenetBenchmark(tf.test.Benchmark): with tf.Graph().as_default(): np_images, np_labels = random_batch(batch_size) dataset = tf.data.Dataset.from_tensors((np_images, np_labels)).repeat() - (images, labels) = dataset.make_one_shot_iterator().get_next() + (images, labels) = tf.compat.v1.data.make_one_shot_iterator( + dataset).get_next() model = densenet.DenseNet(self.depth, self.growth_rate, self.num_blocks, self.output_classes, diff --git a/tensorflow/contrib/eager/python/examples/gan/mnist_graph_test.py b/tensorflow/contrib/eager/python/examples/gan/mnist_graph_test.py index 12b39b0cde..e73841fbf7 100644 --- a/tensorflow/contrib/eager/python/examples/gan/mnist_graph_test.py +++ b/tensorflow/contrib/eager/python/examples/gan/mnist_graph_test.py @@ -42,7 +42,8 @@ class MnistGraphGanBenchmark(tf.test.Benchmark): # Generate some random data. images_data = np.random.randn(batch_size, 784).astype(np.float32) dataset = tf.data.Dataset.from_tensors(images_data) - images = dataset.repeat().make_one_shot_iterator().get_next() + images = tf.compat.v1.data.make_one_shot_iterator( + dataset.repeat()).get_next() # Create the models and optimizers generator = mnist.Generator(data_format()) diff --git a/tensorflow/contrib/eager/python/examples/generative_examples/cvae.ipynb b/tensorflow/contrib/eager/python/examples/generative_examples/cvae.ipynb index ca27a85a22..1a08cc0fd0 100644 --- a/tensorflow/contrib/eager/python/examples/generative_examples/cvae.ipynb +++ b/tensorflow/contrib/eager/python/examples/generative_examples/cvae.ipynb @@ -470,7 +470,7 @@ "\n", " if epoch % 1 == 0:\n", " loss = tfe.metrics.Mean()\n", - " for test_x in test_dataset.make_one_shot_iterator():\n", + " for test_x in test_dataset:\n", " loss(compute_loss(model, test_x))\n", " elbo = -loss.result()\n", " display.clear_output(wait=False)\n", diff --git a/tensorflow/contrib/eager/python/examples/generative_examples/image_captioning_with_attention.ipynb b/tensorflow/contrib/eager/python/examples/generative_examples/image_captioning_with_attention.ipynb index 3acecd283c..12c5eff2b4 100644 --- a/tensorflow/contrib/eager/python/examples/generative_examples/image_captioning_with_attention.ipynb +++ b/tensorflow/contrib/eager/python/examples/generative_examples/image_captioning_with_attention.ipynb @@ -1,1184 +1,1174 @@ { - "nbformat": 4, - "nbformat_minor": 0, - "metadata": { + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "K2s1A9eLRPEj" + }, + "source": [ + "##### Copyright 2018 The TensorFlow Authors.\n", + "\n", + "Licensed under the Apache License, Version 2.0 (the \"License\").\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "Cffg2i257iMS" + }, + "source": [ + "# Image Captioning with Attention\n", + "\n", + "
\n", + "\n", + " Run in Google Colab \n", + "\n", + "View source on GitHub
" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "QASbY_HGo4Lq" + }, + "source": [ + "Image captioning is the task of generating a caption for an image. Given an image like this:\n", + "\n", + "![Man Surfing](https://tensorflow.org/images/surf.jpg) \n", + "\n", + "[Image Source](https://commons.wikimedia.org/wiki/Surfing#/media/File:Surfing_in_Hawaii.jpg), License: Public Domain\n", + "\n", + "Our goal is to generate a caption, such as \"a surfer riding on a wave\". Here, we'll use an attention-based model. This enables us to see which parts of the image the model focuses on as it generates a caption.\n", + "\n", + "![Prediction](https://tensorflow.org/images/imcap_prediction.png)\n", + "\n", + "This model architecture below is similar to [Show, Attend and Tell: Neural Image Caption Generation with Visual Attention](https://arxiv.org/abs/1502.03044). \n", + "\n", + "The code uses [tf.keras](https://www.tensorflow.org/programmers_guide/keras) and [eager execution](https://www.tensorflow.org/programmers_guide/eager), which you can learn more about in the linked guides.\n", + "\n", + "This notebook is an end-to-end example. If you run it, it will download the [MS-COCO](http://cocodataset.org/#home) dataset, preprocess and cache a subset of the images using Inception V3, train an encoder-decoder model, and use it to generate captions on new images.\n", + "\n", + "The code requires TensorFlow version >=1.9. If you're running this in [Colab]()\n", + "\n", + "In this example, we're training on a relatively small amount of data as an example. On a single P100 GPU, this example will take about ~2 hours to train. We train on the first 30,000 captions (corresponding to about ~20,000 images depending on shuffling, as there are multiple captions per image in the dataset)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { "colab": { - "name": "image_captioning_with_attention.ipynb", - "version": "0.3.2", - "views": {}, - "default_view": {}, - "provenance": [ - { - "file_id": "1HI8OK2sMjcx9CTWVn0122QAHOuXaOaMg", - "timestamp": 1530222436922 - } - ], - "private_outputs": true, - "collapsed_sections": [], - "toc_visible": true + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "accelerator": "GPU" + "colab_type": "code", + "id": "U8l4RJ0XRPEm" + }, + "outputs": [], + "source": [ + "# Import TensorFlow and enable eager execution\n", + "# This code requires TensorFlow version >=1.9\n", + "import tensorflow as tf\n", + "tf.enable_eager_execution()\n", + "\n", + "# We'll generate plots of attention in order to see which parts of an image\n", + "# our model focuses on during captioning\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Scikit-learn includes many helpful utilities\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.utils import shuffle\n", + "\n", + "import re\n", + "import numpy as np\n", + "import os\n", + "import time\n", + "import json\n", + "from glob import glob\n", + "from PIL import Image\n", + "import pickle" + ] }, - "cells": [ - { - "metadata": { - "id": "K2s1A9eLRPEj", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "##### Copyright 2018 The TensorFlow Authors.\n", - "\n", - "Licensed under the Apache License, Version 2.0 (the \"License\").\n" - ] - }, - { - "metadata": { - "id": "Cffg2i257iMS", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "# Image Captioning with Attention\n", - "\n", - "
\n", - "\n", - " Run in Google Colab \n", - "\n", - "View source on GitHub
" - ] - }, - { - "metadata": { - "id": "QASbY_HGo4Lq", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "Image captioning is the task of generating a caption for an image. Given an image like this:\n", - "\n", - "![Man Surfing](https://tensorflow.org/images/surf.jpg) \n", - "\n", - "[Image Source](https://commons.wikimedia.org/wiki/Surfing#/media/File:Surfing_in_Hawaii.jpg), License: Public Domain\n", - "\n", - "Our goal is to generate a caption, such as \"a surfer riding on a wave\". Here, we'll use an attention-based model. This enables us to see which parts of the image the model focuses on as it generates a caption.\n", - "\n", - "![Prediction](https://tensorflow.org/images/imcap_prediction.png)\n", - "\n", - "This model architecture below is similar to [Show, Attend and Tell: Neural Image Caption Generation with Visual Attention](https://arxiv.org/abs/1502.03044). \n", - "\n", - "The code uses [tf.keras](https://www.tensorflow.org/programmers_guide/keras) and [eager execution](https://www.tensorflow.org/programmers_guide/eager), which you can learn more about in the linked guides.\n", - "\n", - "This notebook is an end-to-end example. If you run it, it will download the [MS-COCO](http://cocodataset.org/#home) dataset, preprocess and cache a subset of the images using Inception V3, train an encoder-decoder model, and use it to generate captions on new images.\n", - "\n", - "The code requires TensorFlow version >=1.9. If you're running this in [Colab]()\n", - "\n", - "In this example, we're training on a relatively small amount of data as an example. On a single P100 GPU, this example will take about ~2 hours to train. We train on the first 30,000 captions (corresponding to about ~20,000 images depending on shuffling, as there are multiple captions per image in the dataset)\n" - ] - }, - { - "metadata": { - "id": "U8l4RJ0XRPEm", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# Import TensorFlow and enable eager execution\n", - "# This code requires TensorFlow version >=1.9\n", - "import tensorflow as tf\n", - "tf.enable_eager_execution()\n", - "\n", - "# We'll generate plots of attention in order to see which parts of an image\n", - "# our model focuses on during captioning\n", - "import matplotlib.pyplot as plt\n", - "\n", - "# Scikit-learn includes many helpful utilities\n", - "from sklearn.model_selection import train_test_split\n", - "from sklearn.utils import shuffle\n", - "\n", - "import re\n", - "import numpy as np\n", - "import os\n", - "import time\n", - "import json\n", - "from glob import glob\n", - "from PIL import Image\n", - "import pickle" - ], - "execution_count": 0, - "outputs": [] - }, - { - "metadata": { - "id": "b6qbGw8MRPE5", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Download and prepare the MS-COCO dataset\n", - "\n", - "We will use the [MS-COCO dataset](http://cocodataset.org/#home) to train our model. This dataset contains >82,000 images, each of which has been annotated with at least 5 different captions. The code below will download and extract the dataset automatically. \n", - "\n", - "**Caution: large download ahead**. We'll use the training set, it's a 13GB file." - ] - }, - { - "metadata": { - "id": "krQuPYTtRPE7", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "annotation_zip = tf.keras.utils.get_file('captions.zip', \n", - " cache_subdir=os.path.abspath('.'),\n", - " origin = 'http://images.cocodataset.org/annotations/annotations_trainval2014.zip',\n", - " extract = True)\n", - "annotation_file = os.path.dirname(annotation_zip)+'/annotations/captions_train2014.json'\n", - "\n", - "name_of_zip = 'train2014.zip'\n", - "if not os.path.exists(os.path.abspath('.') + '/' + name_of_zip):\n", - " image_zip = tf.keras.utils.get_file(name_of_zip, \n", - " cache_subdir=os.path.abspath('.'),\n", - " origin = 'http://images.cocodataset.org/zips/train2014.zip',\n", - " extract = True)\n", - " PATH = os.path.dirname(image_zip)+'/train2014/'\n", - "else:\n", - " PATH = os.path.abspath('.')+'/train2014/'" - ], - "execution_count": 0, - "outputs": [] - }, - { - "metadata": { - "id": "aANEzb5WwSzg", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Optionally, limit the size of the training set for faster training\n", - "For this example, we'll select a subset of 30,000 captions and use these and the corresponding images to train our model. As always, captioning quality will improve if you choose to use more data." - ] - }, - { - "metadata": { - "id": "4G3b8x8_RPFD", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# read the json file\n", - "with open(annotation_file, 'r') as f:\n", - " annotations = json.load(f)\n", - "\n", - "# storing the captions and the image name in vectors\n", - "all_captions = []\n", - "all_img_name_vector = []\n", - "\n", - "for annot in annotations['annotations']:\n", - " caption = ' ' + annot['caption'] + ' '\n", - " image_id = annot['image_id']\n", - " full_coco_image_path = PATH + 'COCO_train2014_' + '%012d.jpg' % (image_id)\n", - " \n", - " all_img_name_vector.append(full_coco_image_path)\n", - " all_captions.append(caption)\n", - "\n", - "# shuffling the captions and image_names together\n", - "# setting a random state\n", - "train_captions, img_name_vector = shuffle(all_captions,\n", - " all_img_name_vector,\n", - " random_state=1)\n", - "\n", - "# selecting the first 30000 captions from the shuffled set\n", - "num_examples = 30000\n", - "train_captions = train_captions[:num_examples]\n", - "img_name_vector = img_name_vector[:num_examples]" - ], - "execution_count": 0, - "outputs": [] - }, - { - "metadata": { - "id": "mPBMgK34RPFL", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "len(train_captions), len(all_captions)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "metadata": { - "id": "8cSW4u-ORPFQ", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Preprocess the images using InceptionV3\n", - "Next, we will use InceptionV3 (pretrained on Imagenet) to classify each image. We will extract features from the last convolutional layer. \n", - "\n", - "First, we will need to convert the images into the format inceptionV3 expects by:\n", - "* Resizing the image to (299, 299)\n", - "* Using the [preprocess_input](https://www.tensorflow.org/api_docs/python/tf/keras/applications/inception_v3/preprocess_input) method to place the pixels in the range of -1 to 1 (to match the format of the images used to train InceptionV3)." - ] - }, - { - "metadata": { - "id": "zXR0217aRPFR", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "def load_image(image_path):\n", - " img = tf.read_file(image_path)\n", - " img = tf.image.decode_jpeg(img, channels=3)\n", - " img = tf.image.resize_images(img, (299, 299))\n", - " img = tf.keras.applications.inception_v3.preprocess_input(img)\n", - " return img, image_path" - ], - "execution_count": 0, - "outputs": [] - }, - { - "metadata": { - "id": "MDvIu4sXRPFV", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Initialize InceptionV3 and load the pretrained Imagenet weights\n", - "\n", - "To do so, we'll create a tf.keras model where the output layer is the last convolutional layer in the InceptionV3 architecture. \n", - "* Each image is forwarded through the network and the vector that we get at the end is stored in a dictionary (image_name --> feature_vector). \n", - "* We use the last convolutional layer because we are using attention in this example. The shape of the output of this layer is ```8x8x2048```. \n", - "* We avoid doing this during training so it does not become a bottleneck. \n", - "* After all the images are passed through the network, we pickle the dictionary and save it to disk." - ] - }, - { - "metadata": { - "id": "RD3vW4SsRPFW", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "image_model = tf.keras.applications.InceptionV3(include_top=False, \n", - " weights='imagenet')\n", - "new_input = image_model.input\n", - "hidden_layer = image_model.layers[-1].output\n", - "\n", - "image_features_extract_model = tf.keras.Model(new_input, hidden_layer)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "metadata": { - "id": "rERqlR3WRPGO", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Caching the features extracted from InceptionV3\n", - "\n", - "We will pre-process each image with InceptionV3 and cache the output to disk. Caching the output in RAM would be faster but memory intensive, requiring 8 \\* 8 \\* 2048 floats per image. At the time of writing, this would exceed the memory limitations of Colab (although these may change, an instance appears to have about 12GB of memory currently). \n", - "\n", - "Performance could be improved with a more sophisticated caching strategy (e.g., by sharding the images to reduce random access disk I/O) at the cost of more code.\n", - "\n", - "This will take about 10 minutes to run in Colab with a GPU. If you'd like to see a progress bar, you could: install [tqdm](https://github.com/tqdm/tqdm) (```!pip install tqdm```), then change this line: \n", - "\n", - "```for img, path in image_dataset:``` \n", - "\n", - "to:\n", - "\n", - "```for img, path in tqdm(image_dataset):```." - ] - }, - { - "metadata": { - "id": "Dx_fvbVgRPGQ", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# getting the unique images\n", - "encode_train = sorted(set(img_name_vector))\n", - "\n", - "# feel free to change the batch_size according to your system configuration\n", - "image_dataset = tf.data.Dataset.from_tensor_slices(\n", - " encode_train).map(load_image).batch(16)\n", - "\n", - "for img, path in image_dataset:\n", - " batch_features = image_features_extract_model(img)\n", - " batch_features = tf.reshape(batch_features, \n", - " (batch_features.shape[0], -1, batch_features.shape[3]))\n", - "\n", - " for bf, p in zip(batch_features, path):\n", - " path_of_feature = p.numpy().decode(\"utf-8\")\n", - " np.save(path_of_feature, bf.numpy())" - ], - "execution_count": 0, - "outputs": [] - }, - { - "metadata": { - "id": "nyqH3zFwRPFi", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Preprocess and tokenize the captions\n", - "\n", - "* First, we'll tokenize the captions (e.g., by splitting on spaces). This will give us a vocabulary of all the unique words in the data (e.g., \"surfing\", \"football\", etc).\n", - "* Next, we'll limit the vocabulary size to the top 5,000 words to save memory. We'll replace all other words with the token \"UNK\" (for unknown).\n", - "* Finally, we create a word --> index mapping and vice-versa.\n", - "* We will then pad all sequences to the be same length as the longest one. " - ] - }, - { - "metadata": { - "id": "HZfK8RhQRPFj", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# This will find the maximum length of any caption in our dataset\n", - "def calc_max_length(tensor):\n", - " return max(len(t) for t in tensor)" - ], - "execution_count": 0, - "outputs": [] - }, - { - "metadata": { - "id": "oJGE34aiRPFo", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# The steps above is a general process of dealing with text processing\n", - "\n", - "# choosing the top 5000 words from the vocabulary\n", - "top_k = 5000\n", - "tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=top_k, \n", - " oov_token=\"\", \n", - " filters='!\"#$%&()*+.,-/:;=?@[\\]^_`{|}~ ')\n", - "tokenizer.fit_on_texts(train_captions)\n", - "train_seqs = tokenizer.texts_to_sequences(train_captions)" - ], - "execution_count": 0, - "outputs": [] + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "b6qbGw8MRPE5" + }, + "source": [ + "## Download and prepare the MS-COCO dataset\n", + "\n", + "We will use the [MS-COCO dataset](http://cocodataset.org/#home) to train our model. This dataset contains >82,000 images, each of which has been annotated with at least 5 different captions. The code below will download and extract the dataset automatically. \n", + "\n", + "**Caution: large download ahead**. We'll use the training set, it's a 13GB file." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "8Q44tNQVRPFt", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "tokenizer.word_index = {key:value for key, value in tokenizer.word_index.items() if value <= top_k}\n", - "# putting token in the word2idx dictionary\n", - "tokenizer.word_index[tokenizer.oov_token] = top_k + 1\n", - "tokenizer.word_index[''] = 0" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "krQuPYTtRPE7" + }, + "outputs": [], + "source": [ + "annotation_zip = tf.keras.utils.get_file('captions.zip', \n", + " cache_subdir=os.path.abspath('.'),\n", + " origin = 'http://images.cocodataset.org/annotations/annotations_trainval2014.zip',\n", + " extract = True)\n", + "annotation_file = os.path.dirname(annotation_zip)+'/annotations/captions_train2014.json'\n", + "\n", + "name_of_zip = 'train2014.zip'\n", + "if not os.path.exists(os.path.abspath('.') + '/' + name_of_zip):\n", + " image_zip = tf.keras.utils.get_file(name_of_zip, \n", + " cache_subdir=os.path.abspath('.'),\n", + " origin = 'http://images.cocodataset.org/zips/train2014.zip',\n", + " extract = True)\n", + " PATH = os.path.dirname(image_zip)+'/train2014/'\n", + "else:\n", + " PATH = os.path.abspath('.')+'/train2014/'" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "aANEzb5WwSzg" + }, + "source": [ + "## Optionally, limit the size of the training set for faster training\n", + "For this example, we'll select a subset of 30,000 captions and use these and the corresponding images to train our model. As always, captioning quality will improve if you choose to use more data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "0fpJb5ojRPFv", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# creating the tokenized vectors\n", - "train_seqs = tokenizer.texts_to_sequences(train_captions)" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "4G3b8x8_RPFD" + }, + "outputs": [], + "source": [ + "# read the json file\n", + "with open(annotation_file, 'r') as f:\n", + " annotations = json.load(f)\n", + "\n", + "# storing the captions and the image name in vectors\n", + "all_captions = []\n", + "all_img_name_vector = []\n", + "\n", + "for annot in annotations['annotations']:\n", + " caption = ' ' + annot['caption'] + ' '\n", + " image_id = annot['image_id']\n", + " full_coco_image_path = PATH + 'COCO_train2014_' + '%012d.jpg' % (image_id)\n", + " \n", + " all_img_name_vector.append(full_coco_image_path)\n", + " all_captions.append(caption)\n", + "\n", + "# shuffling the captions and image_names together\n", + "# setting a random state\n", + "train_captions, img_name_vector = shuffle(all_captions,\n", + " all_img_name_vector,\n", + " random_state=1)\n", + "\n", + "# selecting the first 30000 captions from the shuffled set\n", + "num_examples = 30000\n", + "train_captions = train_captions[:num_examples]\n", + "img_name_vector = img_name_vector[:num_examples]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "olQArbgbRPF1", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# creating a reverse mapping (index -> word)\n", - "index_word = {value:key for key, value in tokenizer.word_index.items()}" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "mPBMgK34RPFL" + }, + "outputs": [], + "source": [ + "len(train_captions), len(all_captions)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "8cSW4u-ORPFQ" + }, + "source": [ + "## Preprocess the images using InceptionV3\n", + "Next, we will use InceptionV3 (pretrained on Imagenet) to classify each image. We will extract features from the last convolutional layer. \n", + "\n", + "First, we will need to convert the images into the format inceptionV3 expects by:\n", + "* Resizing the image to (299, 299)\n", + "* Using the [preprocess_input](https://www.tensorflow.org/api_docs/python/tf/keras/applications/inception_v3/preprocess_input) method to place the pixels in the range of -1 to 1 (to match the format of the images used to train InceptionV3)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "AidglIZVRPF4", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# padding each vector to the max_length of the captions\n", - "# if the max_length parameter is not provided, pad_sequences calculates that automatically\n", - "cap_vector = tf.keras.preprocessing.sequence.pad_sequences(train_seqs, padding='post')" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "zXR0217aRPFR" + }, + "outputs": [], + "source": [ + "def load_image(image_path):\n", + " img = tf.read_file(image_path)\n", + " img = tf.image.decode_jpeg(img, channels=3)\n", + " img = tf.image.resize_images(img, (299, 299))\n", + " img = tf.keras.applications.inception_v3.preprocess_input(img)\n", + " return img, image_path" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "MDvIu4sXRPFV" + }, + "source": [ + "## Initialize InceptionV3 and load the pretrained Imagenet weights\n", + "\n", + "To do so, we'll create a tf.keras model where the output layer is the last convolutional layer in the InceptionV3 architecture. \n", + "* Each image is forwarded through the network and the vector that we get at the end is stored in a dictionary (image_name --> feature_vector). \n", + "* We use the last convolutional layer because we are using attention in this example. The shape of the output of this layer is ```8x8x2048```. \n", + "* We avoid doing this during training so it does not become a bottleneck. \n", + "* After all the images are passed through the network, we pickle the dictionary and save it to disk." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "gL0wkttkRPGA", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# calculating the max_length \n", - "# used to store the attention weights\n", - "max_length = calc_max_length(train_seqs)" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "RD3vW4SsRPFW" + }, + "outputs": [], + "source": [ + "image_model = tf.keras.applications.InceptionV3(include_top=False, \n", + " weights='imagenet')\n", + "new_input = image_model.input\n", + "hidden_layer = image_model.layers[-1].output\n", + "\n", + "image_features_extract_model = tf.keras.Model(new_input, hidden_layer)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "rERqlR3WRPGO" + }, + "source": [ + "## Caching the features extracted from InceptionV3\n", + "\n", + "We will pre-process each image with InceptionV3 and cache the output to disk. Caching the output in RAM would be faster but memory intensive, requiring 8 \\* 8 \\* 2048 floats per image. At the time of writing, this would exceed the memory limitations of Colab (although these may change, an instance appears to have about 12GB of memory currently). \n", + "\n", + "Performance could be improved with a more sophisticated caching strategy (e.g., by sharding the images to reduce random access disk I/O) at the cost of more code.\n", + "\n", + "This will take about 10 minutes to run in Colab with a GPU. If you'd like to see a progress bar, you could: install [tqdm](https://github.com/tqdm/tqdm) (```!pip install tqdm```), then change this line: \n", + "\n", + "```for img, path in image_dataset:``` \n", + "\n", + "to:\n", + "\n", + "```for img, path in tqdm(image_dataset):```." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "M3CD75nDpvTI", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Split the data into training and testing" - ] + "colab_type": "code", + "id": "Dx_fvbVgRPGQ" + }, + "outputs": [], + "source": [ + "# getting the unique images\n", + "encode_train = sorted(set(img_name_vector))\n", + "\n", + "# feel free to change the batch_size according to your system configuration\n", + "image_dataset = tf.data.Dataset.from_tensor_slices(\n", + " encode_train).map(load_image).batch(16)\n", + "\n", + "for img, path in image_dataset:\n", + " batch_features = image_features_extract_model(img)\n", + " batch_features = tf.reshape(batch_features, \n", + " (batch_features.shape[0], -1, batch_features.shape[3]))\n", + "\n", + " for bf, p in zip(batch_features, path):\n", + " path_of_feature = p.numpy().decode(\"utf-8\")\n", + " np.save(path_of_feature, bf.numpy())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "nyqH3zFwRPFi" + }, + "source": [ + "## Preprocess and tokenize the captions\n", + "\n", + "* First, we'll tokenize the captions (e.g., by splitting on spaces). This will give us a vocabulary of all the unique words in the data (e.g., \"surfing\", \"football\", etc).\n", + "* Next, we'll limit the vocabulary size to the top 5,000 words to save memory. We'll replace all other words with the token \"UNK\" (for unknown).\n", + "* Finally, we create a word --> index mapping and vice-versa.\n", + "* We will then pad all sequences to the be same length as the longest one. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "iS7DDMszRPGF", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# Create training and validation sets using 80-20 split\n", - "img_name_train, img_name_val, cap_train, cap_val = train_test_split(img_name_vector, \n", - " cap_vector, \n", - " test_size=0.2, \n", - " random_state=0)" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "HZfK8RhQRPFj" + }, + "outputs": [], + "source": [ + "# This will find the maximum length of any caption in our dataset\n", + "def calc_max_length(tensor):\n", + " return max(len(t) for t in tensor)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "XmViPkRFRPGH", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "len(img_name_train), len(cap_train), len(img_name_val), len(cap_val)" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "oJGE34aiRPFo" + }, + "outputs": [], + "source": [ + "# The steps above is a general process of dealing with text processing\n", + "\n", + "# choosing the top 5000 words from the vocabulary\n", + "top_k = 5000\n", + "tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=top_k, \n", + " oov_token=\"\", \n", + " filters='!\"#$%&()*+.,-/:;=?@[\\]^_`{|}~ ')\n", + "tokenizer.fit_on_texts(train_captions)\n", + "train_seqs = tokenizer.texts_to_sequences(train_captions)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "uEWM9xrYcg45", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Our images and captions are ready! Next, let's create a tf.data dataset to use for training our model.\n", - "\n" - ] + "colab_type": "code", + "id": "8Q44tNQVRPFt" + }, + "outputs": [], + "source": [ + "tokenizer.word_index[''] = 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "Q3TnZ1ToRPGV", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# feel free to change these parameters according to your system's configuration\n", - "\n", - "BATCH_SIZE = 64\n", - "BUFFER_SIZE = 1000\n", - "embedding_dim = 256\n", - "units = 512\n", - "vocab_size = len(tokenizer.word_index)\n", - "# shape of the vector extracted from InceptionV3 is (64, 2048)\n", - "# these two variables represent that\n", - "features_shape = 2048\n", - "attention_features_shape = 64" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "0fpJb5ojRPFv" + }, + "outputs": [], + "source": [ + "# creating the tokenized vectors\n", + "train_seqs = tokenizer.texts_to_sequences(train_captions)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "SmZS2N0bXG3T", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# loading the numpy files \n", - "def map_func(img_name, cap):\n", - " img_tensor = np.load(img_name.decode('utf-8')+'.npy')\n", - " return img_tensor, cap" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "AidglIZVRPF4" + }, + "outputs": [], + "source": [ + "# padding each vector to the max_length of the captions\n", + "# if the max_length parameter is not provided, pad_sequences calculates that automatically\n", + "cap_vector = tf.keras.preprocessing.sequence.pad_sequences(train_seqs, padding='post')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "FDF_Nm3tRPGZ", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "dataset = tf.data.Dataset.from_tensor_slices((img_name_train, cap_train))\n", - "\n", - "# using map to load the numpy files in parallel\n", - "# NOTE: Be sure to set num_parallel_calls to the number of CPU cores you have\n", - "# https://www.tensorflow.org/api_docs/python/tf/py_func\n", - "dataset = dataset.map(lambda item1, item2: tf.py_func(\n", - " map_func, [item1, item2], [tf.float32, tf.int32]), num_parallel_calls=8)\n", - "\n", - "# shuffling and batching\n", - "dataset = dataset.shuffle(BUFFER_SIZE)\n", - "# https://www.tensorflow.org/api_docs/python/tf/contrib/data/batch_and_drop_remainder\n", - "dataset = dataset.batch(BATCH_SIZE)\n", - "dataset = dataset.prefetch(1)" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "gL0wkttkRPGA" + }, + "outputs": [], + "source": [ + "# calculating the max_length \n", + "# used to store the attention weights\n", + "max_length = calc_max_length(train_seqs)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "M3CD75nDpvTI" + }, + "source": [ + "## Split the data into training and testing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "nrvoDphgRPGd", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Model\n", - "\n", - "Fun fact, the decoder below is identical to the one in the example for [Neural Machine Translation with Attention]( https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb).\n", - "\n", - "The model architecture is inspired by the [Show, Attend and Tell](https://arxiv.org/pdf/1502.03044.pdf) paper.\n", - "\n", - "* In this example, we extract the features from the lower convolutional layer of InceptionV3 giving us a vector of shape (8, 8, 2048). \n", - "* We squash that to a shape of (64, 2048).\n", - "* This vector is then passed through the CNN Encoder(which consists of a single Fully connected layer).\n", - "* The RNN(here GRU) attends over the image to predict the next word." - ] + "colab_type": "code", + "id": "iS7DDMszRPGF" + }, + "outputs": [], + "source": [ + "# Create training and validation sets using 80-20 split\n", + "img_name_train, img_name_val, cap_train, cap_val = train_test_split(img_name_vector, \n", + " cap_vector, \n", + " test_size=0.2, \n", + " random_state=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "AAppCGLKRPGd", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "def gru(units):\n", - " # If you have a GPU, we recommend using the CuDNNGRU layer (it provides a \n", - " # significant speedup).\n", - " if tf.test.is_gpu_available():\n", - " return tf.keras.layers.CuDNNGRU(units, \n", - " return_sequences=True, \n", - " return_state=True, \n", - " recurrent_initializer='glorot_uniform')\n", - " else:\n", - " return tf.keras.layers.GRU(units, \n", - " return_sequences=True, \n", - " return_state=True, \n", - " recurrent_activation='sigmoid', \n", - " recurrent_initializer='glorot_uniform')" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "XmViPkRFRPGH" + }, + "outputs": [], + "source": [ + "len(img_name_train), len(cap_train), len(img_name_val), len(cap_val)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "uEWM9xrYcg45" + }, + "source": [ + "## Our images and captions are ready! Next, let's create a tf.data dataset to use for training our model.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "ja2LFTMSdeV3", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "class BahdanauAttention(tf.keras.Model):\n", - " def __init__(self, units):\n", - " super(BahdanauAttention, self).__init__()\n", - " self.W1 = tf.keras.layers.Dense(units)\n", - " self.W2 = tf.keras.layers.Dense(units)\n", - " self.V = tf.keras.layers.Dense(1)\n", - " \n", - " def call(self, features, hidden):\n", - " # features(CNN_encoder output) shape == (batch_size, 64, embedding_dim)\n", - " \n", - " # hidden shape == (batch_size, hidden_size)\n", - " # hidden_with_time_axis shape == (batch_size, 1, hidden_size)\n", - " hidden_with_time_axis = tf.expand_dims(hidden, 1)\n", - " \n", - " # score shape == (batch_size, 64, hidden_size)\n", - " score = tf.nn.tanh(self.W1(features) + self.W2(hidden_with_time_axis))\n", - " \n", - " # attention_weights shape == (batch_size, 64, 1)\n", - " # we get 1 at the last axis because we are applying score to self.V\n", - " attention_weights = tf.nn.softmax(self.V(score), axis=1)\n", - " \n", - " # context_vector shape after sum == (batch_size, hidden_size)\n", - " context_vector = attention_weights * features\n", - " context_vector = tf.reduce_sum(context_vector, axis=1)\n", - " \n", - " return context_vector, attention_weights" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "Q3TnZ1ToRPGV" + }, + "outputs": [], + "source": [ + "# feel free to change these parameters according to your system's configuration\n", + "\n", + "BATCH_SIZE = 64\n", + "BUFFER_SIZE = 1000\n", + "embedding_dim = 256\n", + "units = 512\n", + "vocab_size = len(tokenizer.word_index)\n", + "# shape of the vector extracted from InceptionV3 is (64, 2048)\n", + "# these two variables represent that\n", + "features_shape = 2048\n", + "attention_features_shape = 64" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "AZ7R1RxHRPGf", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "class CNN_Encoder(tf.keras.Model):\n", - " # Since we have already extracted the features and dumped it using pickle\n", - " # This encoder passes those features through a Fully connected layer\n", - " def __init__(self, embedding_dim):\n", - " super(CNN_Encoder, self).__init__()\n", - " # shape after fc == (batch_size, 64, embedding_dim)\n", - " self.fc = tf.keras.layers.Dense(embedding_dim)\n", - " \n", - " def call(self, x):\n", - " x = self.fc(x)\n", - " x = tf.nn.relu(x)\n", - " return x" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "SmZS2N0bXG3T" + }, + "outputs": [], + "source": [ + "# loading the numpy files \n", + "def map_func(img_name, cap):\n", + " img_tensor = np.load(img_name.decode('utf-8')+'.npy')\n", + " return img_tensor, cap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "V9UbGQmERPGi", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "class RNN_Decoder(tf.keras.Model):\n", - " def __init__(self, embedding_dim, units, vocab_size):\n", - " super(RNN_Decoder, self).__init__()\n", - " self.units = units\n", - "\n", - " self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)\n", - " self.gru = gru(self.units)\n", - " self.fc1 = tf.keras.layers.Dense(self.units)\n", - " self.fc2 = tf.keras.layers.Dense(vocab_size)\n", - " \n", - " self.attention = BahdanauAttention(self.units)\n", - " \n", - " def call(self, x, features, hidden):\n", - " # defining attention as a separate model\n", - " context_vector, attention_weights = self.attention(features, hidden)\n", - " \n", - " # x shape after passing through embedding == (batch_size, 1, embedding_dim)\n", - " x = self.embedding(x)\n", - " \n", - " # x shape after concatenation == (batch_size, 1, embedding_dim + hidden_size)\n", - " x = tf.concat([tf.expand_dims(context_vector, 1), x], axis=-1)\n", - " \n", - " # passing the concatenated vector to the GRU\n", - " output, state = self.gru(x)\n", - " \n", - " # shape == (batch_size, max_length, hidden_size)\n", - " x = self.fc1(output)\n", - " \n", - " # x shape == (batch_size * max_length, hidden_size)\n", - " x = tf.reshape(x, (-1, x.shape[2]))\n", - " \n", - " # output shape == (batch_size * max_length, vocab)\n", - " x = self.fc2(x)\n", - "\n", - " return x, state, attention_weights\n", - "\n", - " def reset_state(self, batch_size):\n", - " return tf.zeros((batch_size, self.units))" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "FDF_Nm3tRPGZ" + }, + "outputs": [], + "source": [ + "dataset = tf.data.Dataset.from_tensor_slices((img_name_train, cap_train))\n", + "\n", + "# using map to load the numpy files in parallel\n", + "# NOTE: Be sure to set num_parallel_calls to the number of CPU cores you have\n", + "# https://www.tensorflow.org/api_docs/python/tf/py_func\n", + "dataset = dataset.map(lambda item1, item2: tf.py_func(\n", + " map_func, [item1, item2], [tf.float32, tf.int32]), num_parallel_calls=8)\n", + "\n", + "# shuffling and batching\n", + "dataset = dataset.shuffle(BUFFER_SIZE)\n", + "# https://www.tensorflow.org/api_docs/python/tf/contrib/data/batch_and_drop_remainder\n", + "dataset = dataset.batch(BATCH_SIZE)\n", + "dataset = dataset.prefetch(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "nrvoDphgRPGd" + }, + "source": [ + "## Model\n", + "\n", + "Fun fact, the decoder below is identical to the one in the example for [Neural Machine Translation with Attention]( https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb).\n", + "\n", + "The model architecture is inspired by the [Show, Attend and Tell](https://arxiv.org/pdf/1502.03044.pdf) paper.\n", + "\n", + "* In this example, we extract the features from the lower convolutional layer of InceptionV3 giving us a vector of shape (8, 8, 2048). \n", + "* We squash that to a shape of (64, 2048).\n", + "* This vector is then passed through the CNN Encoder(which consists of a single Fully connected layer).\n", + "* The RNN(here GRU) attends over the image to predict the next word." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "Qs_Sr03wRPGk", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "encoder = CNN_Encoder(embedding_dim)\n", - "decoder = RNN_Decoder(embedding_dim, units, vocab_size)" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "AAppCGLKRPGd" + }, + "outputs": [], + "source": [ + "def gru(units):\n", + " # If you have a GPU, we recommend using the CuDNNGRU layer (it provides a \n", + " # significant speedup).\n", + " if tf.test.is_gpu_available():\n", + " return tf.keras.layers.CuDNNGRU(units, \n", + " return_sequences=True, \n", + " return_state=True, \n", + " recurrent_initializer='glorot_uniform')\n", + " else:\n", + " return tf.keras.layers.GRU(units, \n", + " return_sequences=True, \n", + " return_state=True, \n", + " recurrent_activation='sigmoid', \n", + " recurrent_initializer='glorot_uniform')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "-bYN7xA0RPGl", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "optimizer = tf.train.AdamOptimizer()\n", - "\n", - "# We are masking the loss calculated for padding\n", - "def loss_function(real, pred):\n", - " mask = 1 - np.equal(real, 0)\n", - " loss_ = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=real, logits=pred) * mask\n", - " return tf.reduce_mean(loss_)" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "ja2LFTMSdeV3" + }, + "outputs": [], + "source": [ + "class BahdanauAttention(tf.keras.Model):\n", + " def __init__(self, units):\n", + " super(BahdanauAttention, self).__init__()\n", + " self.W1 = tf.keras.layers.Dense(units)\n", + " self.W2 = tf.keras.layers.Dense(units)\n", + " self.V = tf.keras.layers.Dense(1)\n", + " \n", + " def call(self, features, hidden):\n", + " # features(CNN_encoder output) shape == (batch_size, 64, embedding_dim)\n", + " \n", + " # hidden shape == (batch_size, hidden_size)\n", + " # hidden_with_time_axis shape == (batch_size, 1, hidden_size)\n", + " hidden_with_time_axis = tf.expand_dims(hidden, 1)\n", + " \n", + " # score shape == (batch_size, 64, hidden_size)\n", + " score = tf.nn.tanh(self.W1(features) + self.W2(hidden_with_time_axis))\n", + " \n", + " # attention_weights shape == (batch_size, 64, 1)\n", + " # we get 1 at the last axis because we are applying score to self.V\n", + " attention_weights = tf.nn.softmax(self.V(score), axis=1)\n", + " \n", + " # context_vector shape after sum == (batch_size, hidden_size)\n", + " context_vector = attention_weights * features\n", + " context_vector = tf.reduce_sum(context_vector, axis=1)\n", + " \n", + " return context_vector, attention_weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "PHod7t72RPGn", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Training\n", - "\n", - "* We extract the features stored in the respective `.npy` files and then pass those features through the encoder.\n", - "* The encoder output, hidden state(initialized to 0) and the decoder input (which is the start token) is passed to the decoder.\n", - "* The decoder returns the predictions and the decoder hidden state.\n", - "* The decoder hidden state is then passed back into the model and the predictions are used to calculate the loss.\n", - "* Use teacher forcing to decide the next input to the decoder.\n", - "* Teacher forcing is the technique where the target word is passed as the next input to the decoder.\n", - "* The final step is to calculate the gradients and apply it to the optimizer and backpropagate.\n" - ] + "colab_type": "code", + "id": "AZ7R1RxHRPGf" + }, + "outputs": [], + "source": [ + "class CNN_Encoder(tf.keras.Model):\n", + " # Since we have already extracted the features and dumped it using pickle\n", + " # This encoder passes those features through a Fully connected layer\n", + " def __init__(self, embedding_dim):\n", + " super(CNN_Encoder, self).__init__()\n", + " # shape after fc == (batch_size, 64, embedding_dim)\n", + " self.fc = tf.keras.layers.Dense(embedding_dim)\n", + " \n", + " def call(self, x):\n", + " x = self.fc(x)\n", + " x = tf.nn.relu(x)\n", + " return x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "Vt4WZ5mhJE-E", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# adding this in a separate cell because if you run the training cell \n", - "# many times, the loss_plot array will be reset\n", - "loss_plot = []" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "V9UbGQmERPGi" + }, + "outputs": [], + "source": [ + "class RNN_Decoder(tf.keras.Model):\n", + " def __init__(self, embedding_dim, units, vocab_size):\n", + " super(RNN_Decoder, self).__init__()\n", + " self.units = units\n", + "\n", + " self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)\n", + " self.gru = gru(self.units)\n", + " self.fc1 = tf.keras.layers.Dense(self.units)\n", + " self.fc2 = tf.keras.layers.Dense(vocab_size)\n", + " \n", + " self.attention = BahdanauAttention(self.units)\n", + " \n", + " def call(self, x, features, hidden):\n", + " # defining attention as a separate model\n", + " context_vector, attention_weights = self.attention(features, hidden)\n", + " \n", + " # x shape after passing through embedding == (batch_size, 1, embedding_dim)\n", + " x = self.embedding(x)\n", + " \n", + " # x shape after concatenation == (batch_size, 1, embedding_dim + hidden_size)\n", + " x = tf.concat([tf.expand_dims(context_vector, 1), x], axis=-1)\n", + " \n", + " # passing the concatenated vector to the GRU\n", + " output, state = self.gru(x)\n", + " \n", + " # shape == (batch_size, max_length, hidden_size)\n", + " x = self.fc1(output)\n", + " \n", + " # x shape == (batch_size * max_length, hidden_size)\n", + " x = tf.reshape(x, (-1, x.shape[2]))\n", + " \n", + " # output shape == (batch_size * max_length, vocab)\n", + " x = self.fc2(x)\n", + "\n", + " return x, state, attention_weights\n", + "\n", + " def reset_state(self, batch_size):\n", + " return tf.zeros((batch_size, self.units))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "UlA4VIQpRPGo", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "EPOCHS = 20\n", - "\n", - "for epoch in range(EPOCHS):\n", - " start = time.time()\n", - " total_loss = 0\n", - " \n", - " for (batch, (img_tensor, target)) in enumerate(dataset):\n", - " loss = 0\n", - " \n", - " # initializing the hidden state for each batch\n", - " # because the captions are not related from image to image\n", - " hidden = decoder.reset_state(batch_size=target.shape[0])\n", - "\n", - " dec_input = tf.expand_dims([tokenizer.word_index['']] * BATCH_SIZE, 1)\n", - " \n", - " with tf.GradientTape() as tape:\n", - " features = encoder(img_tensor)\n", - " \n", - " for i in range(1, target.shape[1]):\n", - " # passing the features through the decoder\n", - " predictions, hidden, _ = decoder(dec_input, features, hidden)\n", - "\n", - " loss += loss_function(target[:, i], predictions)\n", - " \n", - " # using teacher forcing\n", - " dec_input = tf.expand_dims(target[:, i], 1)\n", - " \n", - " total_loss += (loss / int(target.shape[1]))\n", - " \n", - " variables = encoder.variables + decoder.variables\n", - " \n", - " gradients = tape.gradient(loss, variables) \n", - " \n", - " optimizer.apply_gradients(zip(gradients, variables), tf.train.get_or_create_global_step())\n", - " \n", - " if batch % 100 == 0:\n", - " print ('Epoch {} Batch {} Loss {:.4f}'.format(epoch + 1, \n", - " batch, \n", - " loss.numpy() / int(target.shape[1])))\n", - " # storing the epoch end loss value to plot later\n", - " loss_plot.append(total_loss / len(cap_vector))\n", - " \n", - " print ('Epoch {} Loss {:.6f}'.format(epoch + 1, \n", - " total_loss/len(cap_vector)))\n", - " print ('Time taken for 1 epoch {} sec\\n'.format(time.time() - start))" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "Qs_Sr03wRPGk" + }, + "outputs": [], + "source": [ + "encoder = CNN_Encoder(embedding_dim)\n", + "decoder = RNN_Decoder(embedding_dim, units, vocab_size)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "1Wm83G-ZBPcC", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "plt.plot(loss_plot)\n", - "plt.xlabel('Epochs')\n", - "plt.ylabel('Loss')\n", - "plt.title('Loss Plot')\n", - "plt.show()" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "-bYN7xA0RPGl" + }, + "outputs": [], + "source": [ + "optimizer = tf.train.AdamOptimizer()\n", + "\n", + "# We are masking the loss calculated for padding\n", + "def loss_function(real, pred):\n", + " mask = 1 - np.equal(real, 0)\n", + " loss_ = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=real, logits=pred) * mask\n", + " return tf.reduce_mean(loss_)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "PHod7t72RPGn" + }, + "source": [ + "## Training\n", + "\n", + "* We extract the features stored in the respective `.npy` files and then pass those features through the encoder.\n", + "* The encoder output, hidden state(initialized to 0) and the decoder input (which is the start token) is passed to the decoder.\n", + "* The decoder returns the predictions and the decoder hidden state.\n", + "* The decoder hidden state is then passed back into the model and the predictions are used to calculate the loss.\n", + "* Use teacher forcing to decide the next input to the decoder.\n", + "* Teacher forcing is the technique where the target word is passed as the next input to the decoder.\n", + "* The final step is to calculate the gradients and apply it to the optimizer and backpropagate.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "xGvOcLQKghXN", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Caption!\n", - "\n", - "* The evaluate function is similar to the training loop, except we don't use teacher forcing here. The input to the decoder at each time step is its previous predictions along with the hidden state and the encoder output.\n", - "* Stop predicting when the model predicts the end token.\n", - "* And store the attention weights for every time step." - ] + "colab_type": "code", + "id": "Vt4WZ5mhJE-E" + }, + "outputs": [], + "source": [ + "# adding this in a separate cell because if you run the training cell \n", + "# many times, the loss_plot array will be reset\n", + "loss_plot = []" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "RCWpDtyNRPGs", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "def evaluate(image):\n", - " attention_plot = np.zeros((max_length, attention_features_shape))\n", - "\n", - " hidden = decoder.reset_state(batch_size=1)\n", - "\n", - " temp_input = tf.expand_dims(load_image(image)[0], 0)\n", - " img_tensor_val = image_features_extract_model(temp_input)\n", - " img_tensor_val = tf.reshape(img_tensor_val, (img_tensor_val.shape[0], -1, img_tensor_val.shape[3]))\n", - "\n", - " features = encoder(img_tensor_val)\n", - "\n", - " dec_input = tf.expand_dims([tokenizer.word_index['']], 0)\n", - " result = []\n", - "\n", - " for i in range(max_length):\n", - " predictions, hidden, attention_weights = decoder(dec_input, features, hidden)\n", - "\n", - " attention_plot[i] = tf.reshape(attention_weights, (-1, )).numpy()\n", - "\n", - " predicted_id = tf.argmax(predictions[0]).numpy()\n", - " result.append(index_word[predicted_id])\n", - "\n", - " if index_word[predicted_id] == '':\n", - " return result, attention_plot\n", - "\n", - " dec_input = tf.expand_dims([predicted_id], 0)\n", - "\n", - " attention_plot = attention_plot[:len(result), :]\n", - " return result, attention_plot" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "UlA4VIQpRPGo" + }, + "outputs": [], + "source": [ + "EPOCHS = 20\n", + "\n", + "for epoch in range(EPOCHS):\n", + " start = time.time()\n", + " total_loss = 0\n", + " \n", + " for (batch, (img_tensor, target)) in enumerate(dataset):\n", + " loss = 0\n", + " \n", + " # initializing the hidden state for each batch\n", + " # because the captions are not related from image to image\n", + " hidden = decoder.reset_state(batch_size=target.shape[0])\n", + "\n", + " dec_input = tf.expand_dims([tokenizer.word_index['']] * BATCH_SIZE, 1)\n", + " \n", + " with tf.GradientTape() as tape:\n", + " features = encoder(img_tensor)\n", + " \n", + " for i in range(1, target.shape[1]):\n", + " # passing the features through the decoder\n", + " predictions, hidden, _ = decoder(dec_input, features, hidden)\n", + "\n", + " loss += loss_function(target[:, i], predictions)\n", + " \n", + " # using teacher forcing\n", + " dec_input = tf.expand_dims(target[:, i], 1)\n", + " \n", + " total_loss += (loss / int(target.shape[1]))\n", + " \n", + " variables = encoder.variables + decoder.variables\n", + " \n", + " gradients = tape.gradient(loss, variables) \n", + " \n", + " optimizer.apply_gradients(zip(gradients, variables), tf.train.get_or_create_global_step())\n", + " \n", + " if batch % 100 == 0:\n", + " print ('Epoch {} Batch {} Loss {:.4f}'.format(epoch + 1, \n", + " batch, \n", + " loss.numpy() / int(target.shape[1])))\n", + " # storing the epoch end loss value to plot later\n", + " loss_plot.append(total_loss / len(cap_vector))\n", + " \n", + " print ('Epoch {} Loss {:.6f}'.format(epoch + 1, \n", + " total_loss/len(cap_vector)))\n", + " print ('Time taken for 1 epoch {} sec\\n'.format(time.time() - start))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "fD_y7PD6RPGt", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "def plot_attention(image, result, attention_plot):\n", - " temp_image = np.array(Image.open(image))\n", - "\n", - " fig = plt.figure(figsize=(10, 10))\n", - " \n", - " len_result = len(result)\n", - " for l in range(len_result):\n", - " temp_att = np.resize(attention_plot[l], (8, 8))\n", - " ax = fig.add_subplot(len_result//2, len_result//2, l+1)\n", - " ax.set_title(result[l])\n", - " img = ax.imshow(temp_image)\n", - " ax.imshow(temp_att, cmap='gray', alpha=0.6, extent=img.get_extent())\n", - "\n", - " plt.tight_layout()\n", - " plt.show()" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "1Wm83G-ZBPcC" + }, + "outputs": [], + "source": [ + "plt.plot(loss_plot)\n", + "plt.xlabel('Epochs')\n", + "plt.ylabel('Loss')\n", + "plt.title('Loss Plot')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "xGvOcLQKghXN" + }, + "source": [ + "## Caption!\n", + "\n", + "* The evaluate function is similar to the training loop, except we don't use teacher forcing here. The input to the decoder at each time step is its previous predictions along with the hidden state and the encoder output.\n", + "* Stop predicting when the model predicts the end token.\n", + "* And store the attention weights for every time step." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "io7ws3ReRPGv", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "# captions on the validation set\n", - "rid = np.random.randint(0, len(img_name_val))\n", - "image = img_name_val[rid]\n", - "real_caption = ' '.join([index_word[i] for i in cap_val[rid] if i not in [0]])\n", - "result, attention_plot = evaluate(image)\n", - "\n", - "print ('Real Caption:', real_caption)\n", - "print ('Prediction Caption:', ' '.join(result))\n", - "plot_attention(image, result, attention_plot)\n", - "# opening the image\n", - "Image.open(img_name_val[rid])" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "RCWpDtyNRPGs" + }, + "outputs": [], + "source": [ + "def evaluate(image):\n", + " attention_plot = np.zeros((max_length, attention_features_shape))\n", + "\n", + " hidden = decoder.reset_state(batch_size=1)\n", + "\n", + " temp_input = tf.expand_dims(load_image(image)[0], 0)\n", + " img_tensor_val = image_features_extract_model(temp_input)\n", + " img_tensor_val = tf.reshape(img_tensor_val, (img_tensor_val.shape[0], -1, img_tensor_val.shape[3]))\n", + "\n", + " features = encoder(img_tensor_val)\n", + "\n", + " dec_input = tf.expand_dims([tokenizer.word_index['']], 0)\n", + " result = []\n", + "\n", + " for i in range(max_length):\n", + " predictions, hidden, attention_weights = decoder(dec_input, features, hidden)\n", + "\n", + " attention_plot[i] = tf.reshape(attention_weights, (-1, )).numpy()\n", + "\n", + " predicted_id = tf.argmax(predictions[0]).numpy()\n", + " result.append(tokenizer.index_word[predicted_id])\n", + "\n", + " if tokenizer.index_word[predicted_id] == '':\n", + " return result, attention_plot\n", + "\n", + " dec_input = tf.expand_dims([predicted_id], 0)\n", + "\n", + " attention_plot = attention_plot[:len(result), :]\n", + " return result, attention_plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "Rprk3HEvZuxb", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "## Try it on your own images\n", - "For fun, below we've provided a method you can use to caption your own images with the model we've just trained. Keep in mind, it was trained on a relatively small amount of data, and your images may be different from the training data (so be prepared for weird results!)\n" - ] + "colab_type": "code", + "id": "fD_y7PD6RPGt" + }, + "outputs": [], + "source": [ + "def plot_attention(image, result, attention_plot):\n", + " temp_image = np.array(Image.open(image))\n", + "\n", + " fig = plt.figure(figsize=(10, 10))\n", + " \n", + " len_result = len(result)\n", + " for l in range(len_result):\n", + " temp_att = np.resize(attention_plot[l], (8, 8))\n", + " ax = fig.add_subplot(len_result//2, len_result//2, l+1)\n", + " ax.set_title(result[l])\n", + " img = ax.imshow(temp_image)\n", + " ax.imshow(temp_att, cmap='gray', alpha=0.6, extent=img.get_extent())\n", + "\n", + " plt.tight_layout()\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, - { - "metadata": { - "id": "9Psd1quzaAWg", - "colab_type": "code", - "colab": { - "autoexec": { - "startup": false, - "wait_interval": 0 - } - } - }, - "cell_type": "code", - "source": [ - "image_url = 'https://tensorflow.org/images/surf.jpg'\n", - "image_extension = image_url[-4:]\n", - "image_path = tf.keras.utils.get_file('image'+image_extension, \n", - " origin=image_url)\n", - "\n", - "result, attention_plot = evaluate(image_path)\n", - "print ('Prediction Caption:', ' '.join(result))\n", - "plot_attention(image_path, result, attention_plot)\n", - "# opening the image\n", - "Image.open(image_path)" - ], - "execution_count": 0, - "outputs": [] + "colab_type": "code", + "id": "io7ws3ReRPGv" + }, + "outputs": [], + "source": [ + "# captions on the validation set\n", + "rid = np.random.randint(0, len(img_name_val))\n", + "image = img_name_val[rid]\n", + "real_caption = ' '.join([tokenizer.index_word[i] for i in cap_val[rid] if i not in [0]])\n", + "result, attention_plot = evaluate(image)\n", + "\n", + "print ('Real Caption:', real_caption)\n", + "print ('Prediction Caption:', ' '.join(result))\n", + "plot_attention(image, result, attention_plot)\n", + "# opening the image\n", + "Image.open(img_name_val[rid])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "Rprk3HEvZuxb" + }, + "source": [ + "## Try it on your own images\n", + "For fun, below we've provided a method you can use to caption your own images with the model we've just trained. Keep in mind, it was trained on a relatively small amount of data, and your images may be different from the training data (so be prepared for weird results!)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "autoexec": { + "startup": false, + "wait_interval": 0 + } }, + "colab_type": "code", + "id": "9Psd1quzaAWg" + }, + "outputs": [], + "source": [ + "image_url = 'https://tensorflow.org/images/surf.jpg'\n", + "image_extension = image_url[-4:]\n", + "image_path = tf.keras.utils.get_file('image'+image_extension, \n", + " origin=image_url)\n", + "\n", + "result, attention_plot = evaluate(image_path)\n", + "print ('Prediction Caption:', ' '.join(result))\n", + "plot_attention(image_path, result, attention_plot)\n", + "# opening the image\n", + "Image.open(image_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "colab_type": "text", + "id": "VJZXyJco6uLO" + }, + "source": [ + "# Next steps\n", + "\n", + "Congrats! You've just trained an image captioning model with attention. Next, we recommend taking a look at this example [Neural Machine Translation with Attention]( https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb). It uses a similar architecture to translate between Spanish and English sentences. You can also experiment with training the code in this notebook on a different dataset." + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "collapsed_sections": [], + "default_view": {}, + "name": "image_captioning_with_attention.ipynb", + "private_outputs": true, + "provenance": [ { - "metadata": { - "id": "VJZXyJco6uLO", - "colab_type": "text" - }, - "cell_type": "markdown", - "source": [ - "# Next steps\n", - "\n", - "Congrats! You've just trained an image captioning model with attention. Next, we recommend taking a look at this example [Neural Machine Translation with Attention]( https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb). It uses a similar architecture to translate between Spanish and English sentences. You can also experiment with training the code in this notebook on a different dataset." - ] + "file_id": "1HI8OK2sMjcx9CTWVn0122QAHOuXaOaMg", + "timestamp": 1530222436922 } - ] + ], + "toc_visible": true, + "version": "0.3.2", + "views": {} + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 } diff --git a/tensorflow/contrib/eager/python/examples/linear_regression/linear_regression_graph_test.py b/tensorflow/contrib/eager/python/examples/linear_regression/linear_regression_graph_test.py index 557ad42752..d412b25b36 100644 --- a/tensorflow/contrib/eager/python/examples/linear_regression/linear_regression_graph_test.py +++ b/tensorflow/contrib/eager/python/examples/linear_regression/linear_regression_graph_test.py @@ -36,7 +36,7 @@ class GraphLinearRegressionBenchmark(tf.test.Benchmark): noise_level=0.01, batch_size=batch_size, num_batches=num_batches) - iterator = dataset.make_initializable_iterator() + iterator = tf.compat.v1.data.make_initializable_iterator(dataset) x, y = iterator.get_next() model = linear_regression.LinearModel() diff --git a/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb b/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb index 480777d948..66d52a7494 100644 --- a/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb +++ b/tensorflow/contrib/eager/python/examples/nmt_with_attention/nmt_with_attention.ipynb @@ -768,7 +768,7 @@ }, "outputs": [], "source": [ - "translate('hace mucho frio aqui.', encoder, decoder, inp_lang, targ_lang, max_length_inp, max_length_targ)" + "translate(u'hace mucho frio aqui.', encoder, decoder, inp_lang, targ_lang, max_length_inp, max_length_targ)" ] }, { @@ -781,7 +781,7 @@ }, "outputs": [], "source": [ - "translate('esta es mi vida.', encoder, decoder, inp_lang, targ_lang, max_length_inp, max_length_targ)" + "translate(u'esta es mi vida.', encoder, decoder, inp_lang, targ_lang, max_length_inp, max_length_targ)" ] }, { @@ -794,7 +794,7 @@ }, "outputs": [], "source": [ - "translate('¿todavia estan en casa?', encoder, decoder, inp_lang, targ_lang, max_length_inp, max_length_targ)" + "translate(u'todavia estan en casa?', encoder, decoder, inp_lang, targ_lang, max_length_inp, max_length_targ)" ] }, { @@ -808,7 +808,7 @@ "outputs": [], "source": [ "# wrong translation\n", - "translate('trata de averiguarlo.', encoder, decoder, inp_lang, targ_lang, max_length_inp, max_length_targ)" + "translate(u'trata de averiguarlo.', encoder, decoder, inp_lang, targ_lang, max_length_inp, max_length_targ)" ] }, { diff --git a/tensorflow/contrib/eager/python/examples/resnet50/resnet50_graph_test.py b/tensorflow/contrib/eager/python/examples/resnet50/resnet50_graph_test.py index f3bb978875..fb7975d8fe 100644 --- a/tensorflow/contrib/eager/python/examples/resnet50/resnet50_graph_test.py +++ b/tensorflow/contrib/eager/python/examples/resnet50/resnet50_graph_test.py @@ -142,7 +142,8 @@ class ResNet50Benchmarks(tf.test.Benchmark): with tf.Graph().as_default(): np_images, np_labels = random_batch(batch_size) dataset = tf.data.Dataset.from_tensors((np_images, np_labels)).repeat() - (images, labels) = dataset.make_one_shot_iterator().get_next() + images, labels = tf.compat.v1.data.make_one_shot_iterator( + dataset).get_next() model = resnet50.ResNet50(data_format()) logits = model(images, training=True) diff --git a/tensorflow/contrib/eager/python/examples/revnet/main.py b/tensorflow/contrib/eager/python/examples/revnet/main.py index b702e91f92..9585f3565f 100644 --- a/tensorflow/contrib/eager/python/examples/revnet/main.py +++ b/tensorflow/contrib/eager/python/examples/revnet/main.py @@ -72,14 +72,11 @@ def main(_): train_one_iter(model, x, y, optimizer, global_step=global_step) if global_step.numpy() % config.log_every == 0: - it_test = ds_test.make_one_shot_iterator() - acc_test, loss_test = evaluate(model, it_test) + acc_test, loss_test = evaluate(model, ds_test) if FLAGS.validate: - it_train = ds_train_one_shot.make_one_shot_iterator() - it_validation = ds_validation.make_one_shot_iterator() - acc_train, loss_train = evaluate(model, it_train) - acc_validation, loss_validation = evaluate(model, it_validation) + acc_train, loss_train = evaluate(model, ds_train_one_shot) + acc_validation, loss_validation = evaluate(model, ds_validation) print("Iter {}, " "training set accuracy {:.4f}, loss {:.4f}; " "validation set accuracy {:.4f}, loss {:.4f}; " @@ -218,11 +215,11 @@ def train_one_iter(model, inputs, labels, optimizer, global_step=None): return logits, loss -def evaluate(model, iterator): +def evaluate(model, dataset): """Compute accuracy with the given dataset iterator.""" mean_loss = tfe.metrics.Mean() accuracy = tfe.metrics.Accuracy() - for x, y in iterator: + for x, y in dataset: logits, _ = model(x, training=False) loss = model.compute_loss(logits=logits, labels=y) accuracy( diff --git a/tensorflow/contrib/eager/python/examples/rnn_ptb/rnn_ptb_graph_test.py b/tensorflow/contrib/eager/python/examples/rnn_ptb/rnn_ptb_graph_test.py index 63b5c4c54d..770484abed 100644 --- a/tensorflow/contrib/eager/python/examples/rnn_ptb/rnn_ptb_graph_test.py +++ b/tensorflow/contrib/eager/python/examples/rnn_ptb/rnn_ptb_graph_test.py @@ -82,7 +82,7 @@ class PTBBenchmark(tf.test.Benchmark): tf.ones( [PTBBenchmark.SEQ_LEN, PTBBenchmark.BATCH_SIZE], dtype=tf.int64)).repeat(num_iters + num_warmup) - inputs = dataset.make_one_shot_iterator().get_next() + inputs = tf.compat.v1.data.make_one_shot_iterator(dataset).get_next() with tf.device(tf.test.gpu_device_name()): outputs = model(inputs, training=True) @@ -124,7 +124,8 @@ class PTBBenchmark(tf.test.Benchmark): dtype=tf.int64)).repeat(num_iters + num_warmup) # inputs and labels have the same shape dataset = tf.data.Dataset.zip((dataset, dataset)) - (inputs, labels) = dataset.make_one_shot_iterator().get_next() + (inputs, labels) = tf.compat.v1.data.make_one_shot_iterator( + dataset).get_next() with tf.device(tf.test.gpu_device_name()): optimizer = tf.train.GradientDescentOptimizer(learning_rate=1.0) diff --git a/tensorflow/contrib/eager/python/metrics_impl.py b/tensorflow/contrib/eager/python/metrics_impl.py index c88c0f52ee..566246de49 100644 --- a/tensorflow/contrib/eager/python/metrics_impl.py +++ b/tensorflow/contrib/eager/python/metrics_impl.py @@ -24,6 +24,7 @@ from tensorflow.python.eager import context from tensorflow.python.eager import function from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import smart_cond from tensorflow.python.ops import array_ops from tensorflow.python.ops import check_ops from tensorflow.python.ops import control_flow_ops @@ -354,9 +355,10 @@ class Mean(Metric): def write_summary_f(): summary_ops.scalar(name=self.name, tensor=t) return t - control_flow_ops.cond(write_summary, + smart_cond.smart_cond(write_summary, write_summary_f, - lambda: t) + lambda: t, + name="") return t diff --git a/tensorflow/contrib/eager/python/metrics_test.py b/tensorflow/contrib/eager/python/metrics_test.py index 9d2d172752..39e5957f5d 100644 --- a/tensorflow/contrib/eager/python/metrics_test.py +++ b/tensorflow/contrib/eager/python/metrics_test.py @@ -49,18 +49,6 @@ class MetricsTest(test.TestCase): self.assertEqual(dtypes.float64, m.dtype) self.assertEqual(dtypes.float64, m.result().dtype) - def testSummaryArg(self): - m = metrics.Mean() - m([1, 10, 100]) - m(1000) - m([10000.0, 100000.0]) - self.assertEqual(111111.0/6, m.result(write_summary=True).numpy()) - self.assertEqual(111111.0/6, m.result(write_summary=False).numpy()) - with self.assertRaises(ValueError): - m.result(write_summary=5) - with self.assertRaises(ValueError): - m.result(write_summary=[True]) - def testVariableCollections(self): with context.graph_mode(), ops.Graph().as_default(): m = metrics.Mean() diff --git a/tensorflow/contrib/eager/python/network.py b/tensorflow/contrib/eager/python/network.py index f801d9a47b..5cc0c4f23d 100644 --- a/tensorflow/contrib/eager/python/network.py +++ b/tensorflow/contrib/eager/python/network.py @@ -24,7 +24,7 @@ import weakref from tensorflow.python.eager import context from tensorflow.python.framework import ops -from tensorflow.python.keras.engine import base_layer as keras_base_layer +from tensorflow.python.keras.engine import base_layer_utils from tensorflow.python.layers import base from tensorflow.python.ops import variable_scope from tensorflow.python.platform import tf_logging as logging @@ -220,7 +220,7 @@ class Network(base.Layer): avoid_names = parent_network._owned_layers name_uid_map = parent_network._sub_layer_name_uids else: - name_uid_map = keras_base_layer.get_default_graph_uid_map() + name_uid_map = base_layer_utils.get_default_graph_uid_map() # Figure out which names we have to avoid based on which variable scope # we're nested in. strip_name = self._default_parent_variable_scope.name diff --git a/tensorflow/contrib/eager/python/saver.py b/tensorflow/contrib/eager/python/saver.py index f9c716360c..1d0d6c6c14 100644 --- a/tensorflow/contrib/eager/python/saver.py +++ b/tensorflow/contrib/eager/python/saver.py @@ -115,6 +115,11 @@ def restore_variables_on_create(save_path, map_func=None): class Saver(object): """A tf.train.Saver adapter for use when eager execution is enabled. + + `Saver`'s name-based checkpointing strategy is fragile. Please switch to + `tf.train.Checkpoint` or `tf.keras.Model.save_weights`, which perform a more + robust object-based saving. These APIs will load checkpoints written by + `Saver`. """ def __init__(self, var_list): diff --git a/tensorflow/contrib/eager/python/tfe_test.py b/tensorflow/contrib/eager/python/tfe_test.py index 4454abfb96..8c35dddb5a 100644 --- a/tensorflow/contrib/eager/python/tfe_test.py +++ b/tensorflow/contrib/eager/python/tfe_test.py @@ -87,8 +87,8 @@ class TFETest(test_util.TensorFlowTestCase): x += 1. # Without a device context, heuristics are used to place ops. # In this case, ops.reduce_mean runs on the GPU. - reduction_indices = range(x.shape.ndims) - m = math_ops.reduce_mean(x, reduction_indices) + axis = range(x.shape.ndims) + m = math_ops.reduce_mean(x, axis) # m is on GPU, bring it back to CPU and compare. self.assertEqual(3.5, m.cpu().numpy()) diff --git a/tensorflow/contrib/estimator/BUILD b/tensorflow/contrib/estimator/BUILD index 37f253d9c1..a888379f13 100644 --- a/tensorflow/contrib/estimator/BUILD +++ b/tensorflow/contrib/estimator/BUILD @@ -16,7 +16,6 @@ py_library( srcs_version = "PY2AND3", deps = [ ":boosted_trees", - ":dnn", ":dnn_with_layer_annotations", ":early_stopping", ":expect_tensorflow_estimator_installed", @@ -25,7 +24,6 @@ py_library( ":extenders", ":head", ":hooks", - ":linear", ":logit_fns", ":multi_head", ":replicate_model_fn", @@ -47,18 +45,6 @@ py_library( ], ) -py_library( - name = "dnn", - srcs = ["python/estimator/dnn.py"], - srcs_version = "PY2AND3", - deps = [ - ":expect_tensorflow_estimator_installed", - "//tensorflow:tensorflow_py_no_contrib", - "//tensorflow/python/estimator", - "//tensorflow/python/estimator:dnn", - ], -) - py_library( name = "dnn_with_layer_annotations", srcs = ["python/estimator/dnn_with_layer_annotations.py"], @@ -144,17 +130,6 @@ py_library( ], ) -py_library( - name = "linear", - srcs = ["python/estimator/linear.py"], - srcs_version = "PY2AND3", - deps = [ - ":expect_tensorflow_estimator_installed", - "//tensorflow/python/estimator", - "//tensorflow/python/estimator:linear", - ], -) - py_library( name = "logit_fns", srcs = [ diff --git a/tensorflow/contrib/estimator/__init__.py b/tensorflow/contrib/estimator/__init__.py index 80d5962762..7d61247e7e 100644 --- a/tensorflow/contrib/estimator/__init__.py +++ b/tensorflow/contrib/estimator/__init__.py @@ -58,8 +58,6 @@ _allowed_symbols = [ 'multi_label_head', 'poisson_regression_head', 'regression_head', - 'DNNEstimator', - 'LinearEstimator', 'boosted_trees_classifier_train_in_memory', 'boosted_trees_regressor_train_in_memory', 'call_logit_fn', diff --git a/tensorflow/contrib/estimator/python/estimator/dnn_linear_combined.py b/tensorflow/contrib/estimator/python/estimator/dnn_linear_combined.py deleted file mode 100644 index 7894418c4a..0000000000 --- a/tensorflow/contrib/estimator/python/estimator/dnn_linear_combined.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2018 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""dnn_linear_combined python module. - -Importing from tensorflow.python.estimator is unsupported -and will soon break! -""" -# pylint: disable=unused-import,g-bad-import-order,g-import-not-at-top,wildcard-import - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -from tensorflow_estimator.contrib.estimator.python.estimator import dnn_linear_combined - -# Include attrs that start with single underscore. -_HAS_DYNAMIC_ATTRIBUTES = True -dnn_linear_combined.__all__ = [ - s for s in dir(dnn_linear_combined) if not s.startswith('__') -] - -from tensorflow_estimator.contrib.estimator.python.estimator.dnn_linear_combined import * diff --git a/tensorflow/contrib/factorization/python/ops/kmeans.py b/tensorflow/contrib/factorization/python/ops/kmeans.py index f384d761a8..3eb396a29c 100644 --- a/tensorflow/contrib/factorization/python/ops/kmeans.py +++ b/tensorflow/contrib/factorization/python/ops/kmeans.py @@ -26,7 +26,7 @@ from tensorflow.contrib.factorization.python.ops import clustering_ops from tensorflow.python.estimator import estimator from tensorflow.python.estimator import model_fn as model_fn_lib from tensorflow.python.estimator.export import export_output -from tensorflow.python.feature_column import feature_column as fc +from tensorflow.python.feature_column import feature_column_lib as fc from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops diff --git a/tensorflow/contrib/factorization/python/ops/kmeans_test.py b/tensorflow/contrib/factorization/python/ops/kmeans_test.py index 1ab5418fe4..2f7cd131d3 100644 --- a/tensorflow/contrib/factorization/python/ops/kmeans_test.py +++ b/tensorflow/contrib/factorization/python/ops/kmeans_test.py @@ -27,7 +27,7 @@ from sklearn.cluster import KMeans as SklearnKMeans # pylint: disable=g-import-not-at-top from tensorflow.contrib.factorization.python.ops import kmeans as kmeans_lib from tensorflow.python.estimator import run_config -from tensorflow.python.feature_column import feature_column as fc +from tensorflow.python.feature_column import feature_column_lib as fc from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops diff --git a/tensorflow/contrib/feature_column/BUILD b/tensorflow/contrib/feature_column/BUILD index bbe335be3e..1cd83bdb5d 100644 --- a/tensorflow/contrib/feature_column/BUILD +++ b/tensorflow/contrib/feature_column/BUILD @@ -14,6 +14,7 @@ py_library( srcs_version = "PY2AND3", deps = [ ":sequence_feature_column", + ":sequence_feature_column_v2", "//tensorflow/python:util", ], ) @@ -32,7 +33,7 @@ py_library( "//tensorflow/python:sparse_ops", "//tensorflow/python:tensor_shape", "//tensorflow/python:variable_scope", - "//tensorflow/python/feature_column", + "//tensorflow/python/feature_column:feature_column_py", ], ) @@ -51,7 +52,7 @@ py_test( "//tensorflow/python:parsing_ops", "//tensorflow/python:sparse_tensor", "//tensorflow/python:training", - "//tensorflow/python/feature_column", + "//tensorflow/python/feature_column:feature_column_py", "//third_party/py/numpy", "@absl_py//absl/testing:parameterized", ], @@ -69,7 +70,7 @@ py_test( "//tensorflow/python:parsing_ops", "//tensorflow/python:training", "//tensorflow/python:util", - "//tensorflow/python/feature_column", + "//tensorflow/python/feature_column:feature_column_py", "//tensorflow/python/keras:layers", ], ) @@ -89,7 +90,7 @@ py_library( "//tensorflow/python:tensor_shape", "//tensorflow/python:variable_scope", "//tensorflow/python/feature_column", - "//tensorflow/python/feature_column:feature_column_v2", + "//tensorflow/python/feature_column:feature_column_py", ], ) @@ -110,7 +111,7 @@ py_test( "//tensorflow/python:sparse_tensor", "//tensorflow/python:training", "//tensorflow/python/feature_column", - "//tensorflow/python/feature_column:feature_column_v2", + "//tensorflow/python/feature_column:feature_column_py", "//third_party/py/numpy", "@absl_py//absl/testing:parameterized", ], diff --git a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column.py b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column.py index dd6da35ed0..9b3a5c58aa 100644 --- a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column.py +++ b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column.py @@ -222,10 +222,8 @@ def sequence_categorical_column_with_identity( ValueError: if `default_value` is not in range `[0, num_buckets)`. """ return fc._SequenceCategoricalColumn( - fc.categorical_column_with_identity( - key=key, - num_buckets=num_buckets, - default_value=default_value)) + fc._categorical_column_with_identity( + key=key, num_buckets=num_buckets, default_value=default_value)) def sequence_categorical_column_with_hash_bucket( @@ -265,10 +263,8 @@ def sequence_categorical_column_with_hash_bucket( ValueError: `dtype` is neither string nor integer. """ return fc._SequenceCategoricalColumn( - fc.categorical_column_with_hash_bucket( - key=key, - hash_bucket_size=hash_bucket_size, - dtype=dtype)) + fc._categorical_column_with_hash_bucket( + key=key, hash_bucket_size=hash_bucket_size, dtype=dtype)) def sequence_categorical_column_with_vocabulary_file( @@ -324,7 +320,7 @@ def sequence_categorical_column_with_vocabulary_file( ValueError: `dtype` is neither string nor integer. """ return fc._SequenceCategoricalColumn( - fc.categorical_column_with_vocabulary_file( + fc._categorical_column_with_vocabulary_file( key=key, vocabulary_file=vocabulary_file, vocabulary_size=vocabulary_size, @@ -384,7 +380,7 @@ def sequence_categorical_column_with_vocabulary_list( ValueError: if `dtype` is not integer or string. """ return fc._SequenceCategoricalColumn( - fc.categorical_column_with_vocabulary_list( + fc._categorical_column_with_vocabulary_list( key=key, vocabulary_list=vocabulary_list, dtype=dtype, diff --git a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_integration_test.py b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_integration_test.py index d8ca363627..bcc25b8de8 100644 --- a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_integration_test.py +++ b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_integration_test.py @@ -53,19 +53,20 @@ class SequenceFeatureColumnIntegrationTest(test.TestCase): return example def _build_feature_columns(self): - col = fc.categorical_column_with_identity( - 'int_ctx', num_buckets=100) + col = fc._categorical_column_with_identity('int_ctx', num_buckets=100) ctx_cols = [ - fc.embedding_column(col, dimension=10), - fc.numeric_column('float_ctx')] + fc._embedding_column(col, dimension=10), + fc._numeric_column('float_ctx') + ] identity_col = sfc.sequence_categorical_column_with_identity( 'int_list', num_buckets=10) bucket_col = sfc.sequence_categorical_column_with_hash_bucket( 'bytes_list', hash_bucket_size=100) seq_cols = [ - fc.embedding_column(identity_col, dimension=10), - fc.embedding_column(bucket_col, dimension=20)] + fc._embedding_column(identity_col, dimension=10), + fc._embedding_column(bucket_col, dimension=20) + ] return ctx_cols, seq_cols @@ -148,8 +149,8 @@ class SequenceExampleParsingTest(test.TestCase): """ example = _make_sequence_example() columns = [ - fc.categorical_column_with_identity('int_ctx', num_buckets=100), - fc.numeric_column('float_ctx'), + fc._categorical_column_with_identity('int_ctx', num_buckets=100), + fc._numeric_column('float_ctx'), col_fn(col_name, col_arg) ] context, seq_features = parsing_ops.parse_single_sequence_example( diff --git a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_test.py b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_test.py index 2163af0b43..d5f7402829 100644 --- a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_test.py +++ b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.contrib.feature_column.python.feature_column import sequence_feature_column as sfc from tensorflow.python.feature_column import feature_column as fc +from tensorflow.python.feature_column import feature_column_lib as fc_lib from tensorflow.python.feature_column.feature_column import _LazyBuilder from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors @@ -109,13 +110,15 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): categorical_column_a = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column_a = fc.embedding_column( - categorical_column_a, dimension=embedding_dimension_a, + embedding_column_a = fc._embedding_column( + categorical_column_a, + dimension=embedding_dimension_a, initializer=_get_initializer(embedding_dimension_a, embedding_values_a)) categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - embedding_column_b = fc.embedding_column( - categorical_column_b, dimension=embedding_dimension_b, + embedding_column_b = fc._embedding_column( + categorical_column_b, + dimension=embedding_dimension_b, initializer=_get_initializer(embedding_dimension_b, embedding_values_b)) input_layer, sequence_length = sfc.sequence_input_layer( @@ -148,10 +151,9 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): values=(2, 0, 1), dense_shape=(2, 2)) - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column_a = fc.embedding_column( - categorical_column_a, dimension=2) + embedding_column_a = fc._embedding_column(categorical_column_a, dimension=2) with self.assertRaisesRegexp( ValueError, @@ -206,7 +208,7 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) # Test that columns are reordered alphabetically. - shared_embedding_columns = fc.shared_embedding_columns( + shared_embedding_columns = fc_lib.shared_embedding_columns( [categorical_column_b, categorical_column_a], dimension=embedding_dimension, initializer=_get_initializer(embedding_dimension, embedding_values)) @@ -244,11 +246,11 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): values=(2, 0, 1), dense_shape=(2, 2)) - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - shared_embedding_columns = fc.shared_embedding_columns( + shared_embedding_columns = fc_lib.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) with self.assertRaisesRegexp( @@ -315,10 +317,10 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): categorical_column_a = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size_a) - indicator_column_a = fc.indicator_column(categorical_column_a) + indicator_column_a = fc._indicator_column(categorical_column_a) categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size_b) - indicator_column_b = fc.indicator_column(categorical_column_b) + indicator_column_b = fc._indicator_column(categorical_column_b) input_layer, sequence_length = sfc.sequence_input_layer( features={ 'aaa': sparse_input_a, @@ -342,9 +344,9 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): values=(2, 0, 1), dense_shape=(2, 2)) - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - indicator_column_a = fc.indicator_column(categorical_column_a) + indicator_column_a = fc._indicator_column(categorical_column_a) with self.assertRaisesRegexp( ValueError, @@ -530,7 +532,7 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): sparse_input = sparse_tensor.SparseTensorValue(**sparse_input_args) categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=3) - indicator_column = fc.indicator_column(categorical_column) + indicator_column = fc._indicator_column(categorical_column) input_layer, _ = sfc.sequence_input_layer( features={'aaa': sparse_input}, feature_columns=[indicator_column]) @@ -616,8 +618,7 @@ class InputLayerTest(test.TestCase): categorical_column_a = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column_a = fc.embedding_column( - categorical_column_a, dimension=2) + embedding_column_a = fc._embedding_column(categorical_column_a, dimension=2) with self.assertRaisesRegexp( ValueError, @@ -639,7 +640,7 @@ class InputLayerTest(test.TestCase): categorical_column_a = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - indicator_column_a = fc.indicator_column(categorical_column_a) + indicator_column_a = fc._indicator_column(categorical_column_a) with self.assertRaisesRegexp( ValueError, @@ -918,8 +919,9 @@ class SequenceEmbeddingColumnTest( categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + embedding_column = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, initializer=_initializer) embedding_lookup, _ = embedding_column._get_sequence_dense_tensor( @@ -956,8 +958,7 @@ class SequenceEmbeddingColumnTest( categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=2) + embedding_column = fc._embedding_column(categorical_column, dimension=2) _, sequence_length = embedding_column._get_sequence_dense_tensor( _LazyBuilder({'aaa': inputs})) @@ -984,8 +985,7 @@ class SequenceEmbeddingColumnTest( categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=2) + embedding_column = fc._embedding_column(categorical_column, dimension=2) _, sequence_length = embedding_column._get_sequence_dense_tensor( _LazyBuilder({'aaa': sparse_input})) @@ -1055,7 +1055,7 @@ class SequenceSharedEmbeddingColumnTest(test.TestCase): key='aaa', num_buckets=vocabulary_size) categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - shared_embedding_columns = fc.shared_embedding_columns( + shared_embedding_columns = fc_lib.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=embedding_dimension, initializer=_initializer) @@ -1101,7 +1101,7 @@ class SequenceSharedEmbeddingColumnTest(test.TestCase): expected_sequence_length_b = [2, 1] categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - shared_embedding_columns = fc.shared_embedding_columns( + shared_embedding_columns = fc_lib.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) sequence_length_a = shared_embedding_columns[0]._get_sequence_dense_tensor( @@ -1152,7 +1152,7 @@ class SequenceSharedEmbeddingColumnTest(test.TestCase): categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - shared_embedding_columns = fc.shared_embedding_columns( + shared_embedding_columns = fc_lib.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) sequence_length_a = shared_embedding_columns[0]._get_sequence_dense_tensor( @@ -1218,7 +1218,7 @@ class SequenceIndicatorColumnTest(test.TestCase, parameterized.TestCase): categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - indicator_column = fc.indicator_column(categorical_column) + indicator_column = fc._indicator_column(categorical_column) indicator_tensor, _ = indicator_column._get_sequence_dense_tensor( _LazyBuilder({'aaa': inputs})) @@ -1250,7 +1250,7 @@ class SequenceIndicatorColumnTest(test.TestCase, parameterized.TestCase): categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - indicator_column = fc.indicator_column(categorical_column) + indicator_column = fc._indicator_column(categorical_column) _, sequence_length = indicator_column._get_sequence_dense_tensor( _LazyBuilder({'aaa': inputs})) @@ -1277,7 +1277,7 @@ class SequenceIndicatorColumnTest(test.TestCase, parameterized.TestCase): categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - indicator_column = fc.indicator_column(categorical_column) + indicator_column = fc._indicator_column(categorical_column) _, sequence_length = indicator_column._get_sequence_dense_tensor( _LazyBuilder({'aaa': sparse_input})) diff --git a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_v2.py b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_v2.py index 67ffb93966..0d34ad1618 100644 --- a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_v2.py +++ b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_v2.py @@ -26,7 +26,7 @@ import collections from tensorflow.python.feature_column import feature_column as fc_old -from tensorflow.python.feature_column import feature_column_v2 as fc +from tensorflow.python.feature_column import feature_column_lib as fc from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape @@ -226,10 +226,8 @@ def sequence_categorical_column_with_identity( ValueError: if `default_value` is not in range `[0, num_buckets)`. """ return fc_old._SequenceCategoricalColumn( - fc_old.categorical_column_with_identity( - key=key, - num_buckets=num_buckets, - default_value=default_value)) + fc_old._categorical_column_with_identity( + key=key, num_buckets=num_buckets, default_value=default_value)) def sequence_categorical_column_with_hash_bucket( @@ -269,10 +267,8 @@ def sequence_categorical_column_with_hash_bucket( ValueError: `dtype` is neither string nor integer. """ return fc_old._SequenceCategoricalColumn( - fc_old.categorical_column_with_hash_bucket( - key=key, - hash_bucket_size=hash_bucket_size, - dtype=dtype)) + fc_old._categorical_column_with_hash_bucket( + key=key, hash_bucket_size=hash_bucket_size, dtype=dtype)) def sequence_categorical_column_with_vocabulary_file( @@ -328,7 +324,7 @@ def sequence_categorical_column_with_vocabulary_file( ValueError: `dtype` is neither string nor integer. """ return fc_old._SequenceCategoricalColumn( - fc_old.categorical_column_with_vocabulary_file( + fc_old._categorical_column_with_vocabulary_file( key=key, vocabulary_file=vocabulary_file, vocabulary_size=vocabulary_size, @@ -388,7 +384,7 @@ def sequence_categorical_column_with_vocabulary_list( ValueError: if `dtype` is not integer or string. """ return fc_old._SequenceCategoricalColumn( - fc_old.categorical_column_with_vocabulary_list( + fc_old._categorical_column_with_vocabulary_list( key=key, vocabulary_list=vocabulary_list, dtype=dtype, @@ -441,7 +437,7 @@ def sequence_numeric_column( ValueError: if any dimension in shape is not a positive integer. ValueError: if `dtype` is not convertible to `tf.float32`. """ - shape = fc._check_shape(shape=shape, key=key) + shape = fc_old._check_shape(shape=shape, key=key) if not (dtype.is_integer or dtype.is_floating): raise ValueError('dtype must be convertible to float. ' 'dtype: {}, key: {}'.format(dtype, key)) diff --git a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_v2_test.py b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_v2_test.py index 5ecd85807c..ca4398a142 100644 --- a/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_v2_test.py +++ b/tensorflow/contrib/feature_column/python/feature_column/sequence_feature_column_v2_test.py @@ -25,7 +25,7 @@ import numpy as np from tensorflow.contrib.feature_column.python.feature_column import sequence_feature_column as sfc_old from tensorflow.contrib.feature_column.python.feature_column import sequence_feature_column_v2 as sfc from tensorflow.python.feature_column import feature_column as fc_old -from tensorflow.python.feature_column import feature_column_v2 as fc +from tensorflow.python.feature_column import feature_column_lib as fc from tensorflow.python.feature_column.feature_column import _LazyBuilder from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors @@ -111,13 +111,15 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): categorical_column_a = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column_a = fc_old.embedding_column( - categorical_column_a, dimension=embedding_dimension_a, + embedding_column_a = fc_old._embedding_column( + categorical_column_a, + dimension=embedding_dimension_a, initializer=_get_initializer(embedding_dimension_a, embedding_values_a)) categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - embedding_column_b = fc_old.embedding_column( - categorical_column_b, dimension=embedding_dimension_b, + embedding_column_b = fc_old._embedding_column( + categorical_column_b, + dimension=embedding_dimension_b, initializer=_get_initializer(embedding_dimension_b, embedding_values_b)) input_layer, sequence_length = sfc.sequence_input_layer( @@ -150,9 +152,9 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): values=(2, 0, 1), dense_shape=(2, 2)) - categorical_column_a = fc_old.categorical_column_with_identity( + categorical_column_a = fc_old._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column_a = fc_old.embedding_column( + embedding_column_a = fc_old._embedding_column( categorical_column_a, dimension=2) with self.assertRaisesRegexp( @@ -208,7 +210,7 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) # Test that columns are reordered alphabetically. - shared_embedding_columns = fc_old.shared_embedding_columns( + shared_embedding_columns = fc.shared_embedding_columns( [categorical_column_b, categorical_column_a], dimension=embedding_dimension, initializer=_get_initializer(embedding_dimension, embedding_values)) @@ -246,11 +248,11 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): values=(2, 0, 1), dense_shape=(2, 2)) - categorical_column_a = fc_old.categorical_column_with_identity( + categorical_column_a = fc_old._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - categorical_column_b = fc_old.categorical_column_with_identity( + categorical_column_b = fc_old._categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - shared_embedding_columns = fc_old.shared_embedding_columns( + shared_embedding_columns = fc.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) with self.assertRaisesRegexp( @@ -317,10 +319,10 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): categorical_column_a = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size_a) - indicator_column_a = fc_old.indicator_column(categorical_column_a) + indicator_column_a = fc_old._indicator_column(categorical_column_a) categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size_b) - indicator_column_b = fc_old.indicator_column(categorical_column_b) + indicator_column_b = fc_old._indicator_column(categorical_column_b) input_layer, sequence_length = sfc.sequence_input_layer( features={ 'aaa': sparse_input_a, @@ -344,9 +346,9 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): values=(2, 0, 1), dense_shape=(2, 2)) - categorical_column_a = fc_old.categorical_column_with_identity( + categorical_column_a = fc_old._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - indicator_column_a = fc_old.indicator_column(categorical_column_a) + indicator_column_a = fc_old._indicator_column(categorical_column_a) with self.assertRaisesRegexp( ValueError, @@ -532,7 +534,7 @@ class SequenceInputLayerTest(test.TestCase, parameterized.TestCase): sparse_input = sparse_tensor.SparseTensorValue(**sparse_input_args) categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=3) - indicator_column = fc_old.indicator_column(categorical_column) + indicator_column = fc_old._indicator_column(categorical_column) input_layer, _ = sfc.sequence_input_layer( features={'aaa': sparse_input}, feature_columns=[indicator_column]) @@ -618,7 +620,7 @@ class InputLayerTest(test.TestCase): categorical_column_a = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column_a = fc_old.embedding_column( + embedding_column_a = fc_old._embedding_column( categorical_column_a, dimension=2) with self.assertRaisesRegexp( @@ -641,7 +643,7 @@ class InputLayerTest(test.TestCase): categorical_column_a = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - indicator_column_a = fc_old.indicator_column(categorical_column_a) + indicator_column_a = fc_old._indicator_column(categorical_column_a) with self.assertRaisesRegexp( ValueError, @@ -920,8 +922,9 @@ class SequenceEmbeddingColumnTest( categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc_old.embedding_column( - categorical_column, dimension=embedding_dimension, + embedding_column = fc_old._embedding_column( + categorical_column, + dimension=embedding_dimension, initializer=_initializer) embedding_lookup, _ = embedding_column._get_sequence_dense_tensor( @@ -958,8 +961,7 @@ class SequenceEmbeddingColumnTest( categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc_old.embedding_column( - categorical_column, dimension=2) + embedding_column = fc_old._embedding_column(categorical_column, dimension=2) _, sequence_length = embedding_column._get_sequence_dense_tensor( _LazyBuilder({'aaa': inputs})) @@ -986,8 +988,7 @@ class SequenceEmbeddingColumnTest( categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc_old.embedding_column( - categorical_column, dimension=2) + embedding_column = fc_old._embedding_column(categorical_column, dimension=2) _, sequence_length = embedding_column._get_sequence_dense_tensor( _LazyBuilder({'aaa': sparse_input})) @@ -1057,7 +1058,7 @@ class SequenceSharedEmbeddingColumnTest(test.TestCase): key='aaa', num_buckets=vocabulary_size) categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - shared_embedding_columns = fc_old.shared_embedding_columns( + shared_embedding_columns = fc.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=embedding_dimension, initializer=_initializer) @@ -1103,7 +1104,7 @@ class SequenceSharedEmbeddingColumnTest(test.TestCase): expected_sequence_length_b = [2, 1] categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - shared_embedding_columns = fc_old.shared_embedding_columns( + shared_embedding_columns = fc.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) sequence_length_a = shared_embedding_columns[0]._get_sequence_dense_tensor( @@ -1154,7 +1155,7 @@ class SequenceSharedEmbeddingColumnTest(test.TestCase): categorical_column_b = sfc.sequence_categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - shared_embedding_columns = fc_old.shared_embedding_columns( + shared_embedding_columns = fc.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) sequence_length_a = shared_embedding_columns[0]._get_sequence_dense_tensor( @@ -1220,7 +1221,7 @@ class SequenceIndicatorColumnTest(test.TestCase, parameterized.TestCase): categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - indicator_column = fc_old.indicator_column(categorical_column) + indicator_column = fc_old._indicator_column(categorical_column) indicator_tensor, _ = indicator_column._get_sequence_dense_tensor( _LazyBuilder({'aaa': inputs})) @@ -1252,7 +1253,7 @@ class SequenceIndicatorColumnTest(test.TestCase, parameterized.TestCase): categorical_column = sfc.sequence_categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - indicator_column = fc_old.indicator_column(categorical_column) + indicator_column = fc_old._indicator_column(categorical_column) _, sequence_length = indicator_column._get_sequence_dense_tensor( _LazyBuilder({'aaa': inputs})) diff --git a/tensorflow/contrib/framework/BUILD b/tensorflow/contrib/framework/BUILD index cd747df4d6..dad50a3a73 100644 --- a/tensorflow/contrib/framework/BUILD +++ b/tensorflow/contrib/framework/BUILD @@ -47,6 +47,11 @@ tf_custom_op_py_library( ":variable_ops_op_lib", ], srcs_version = "PY2AND3", + visibility = [ + "//learning/brain:__subpackages__", + "//tensorflow:__subpackages__", + "//video/youtube/personalization:__subpackages__", + ], deps = [ ":gen_variable_ops", "//tensorflow/contrib/util:util_py", @@ -66,6 +71,7 @@ tf_custom_op_py_library( "//tensorflow/python:resource_variable_ops", "//tensorflow/python:script_ops", "//tensorflow/python:smart_cond", + "//tensorflow/python:sort_ops", "//tensorflow/python:sparse_tensor", "//tensorflow/python:state_ops", "//tensorflow/python:state_ops_gen", @@ -311,17 +317,3 @@ py_test( "//third_party/py/numpy", ], ) - -py_test( - name = "sort_ops_test", - size = "medium", - srcs = ["python/ops/sort_ops_test.py"], - srcs_version = "PY2AND3", - deps = [ - ":framework_py", - "//tensorflow/python:array_ops", - "//tensorflow/python:client_testlib", - "//tensorflow/python:random_ops", - "//third_party/py/numpy", - ], -) diff --git a/tensorflow/contrib/framework/python/ops/sort_ops.py b/tensorflow/contrib/framework/python/ops/sort_ops.py index 1921a77c1e..42184a4e55 100644 --- a/tensorflow/contrib/framework/python/ops/sort_ops.py +++ b/tensorflow/contrib/framework/python/ops/sort_ops.py @@ -22,173 +22,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import numpy as np +from tensorflow.python.ops import sort_ops -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import ops as framework_ops -from tensorflow.python.framework import tensor_util -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import nn_ops - - -def sort(values, axis=-1, direction='ASCENDING', name=None): - """Sorts a tensor. - - Args: - values: 1-D or higher numeric `Tensor`. - axis: The axis along which to sort. The default is -1, which sorts the last - axis. - direction: The direction in which to sort the values (`'ASCENDING'` or - `'DESCENDING'`). - name: Optional name for the operation. - - Returns: - A `Tensor` with the same dtype and shape as `values`, with the elements - sorted along the given `axis`. - - Raises: - ValueError: If axis is not a constant scalar, or the direction is invalid. - """ - with framework_ops.name_scope(name, 'sort'): - return _sort_or_argsort(values, axis, direction, return_argsort=False) - - -def argsort(values, axis=-1, direction='ASCENDING', stable=False, name=None): - """Returns the indices of a tensor that give its sorted order along an axis. - - For a 1D tensor, `tf.gather(values, tf.argsort(values))` is equivalent to - `tf.sort(values)`. For higher dimensions, the output has the same shape as - `values`, but along the given axis, values represent the index of the sorted - element in that slice of the tensor at the given position. - - Args: - values: 1-D or higher numeric `Tensor`. - axis: The axis along which to sort. The default is -1, which sorts the last - axis. - direction: The direction in which to sort the values (`'ASCENDING'` or - `'DESCENDING'`). - stable: If True, equal elements in the original tensor will not be - re-ordered in the returned order. Unstable sort is not yet implemented, - but will eventually be the default for performance reasons. If you - require a stable order, pass `stable=True` for forwards compatibility. - name: Optional name for the operation. - - Returns: - An int32 `Tensor` with the same shape as `values`. The indices that would - sort each slice of the given `values` along the given `axis`. - - Raises: - ValueError: If axis is not a constant scalar, or the direction is invalid. - """ - del stable # Unused. - with framework_ops.name_scope(name, 'argsort'): - return _sort_or_argsort(values, axis, direction, return_argsort=True) - - -def _sort_or_argsort(values, axis, direction, return_argsort): - """Internal sort/argsort implementation. - - Args: - values: The input values. - axis: The axis along which to sort. - direction: 'ASCENDING' or 'DESCENDING'. - return_argsort: Whether to return the argsort result. - - Returns: - Either the sorted values, or the indices of the sorted values in the - original tensor. See the `sort` and `argsort` docstrings. - - Raises: - ValueError: If axis is not a constant scalar, or the direction is invalid. - """ - if direction not in _SORT_IMPL: - raise ValueError('%s should be one of %s' % - (direction, ', '.join(sorted(_SORT_IMPL.keys())))) - # Axis must be an integer, not a Tensor. - axis = framework_ops.convert_to_tensor(axis, name='axis') - axis_static = tensor_util.constant_value(axis) - if axis.shape.ndims != 0 or axis_static is None: - raise ValueError('axis must be a constant scalar') - axis_static = int(axis_static) # Avoids NumPy casting error - - values = framework_ops.convert_to_tensor(values, name='values') - - return _SORT_IMPL[direction](values, axis_static, return_argsort) - - -def _descending_sort(values, axis, return_argsort=False): - """Sorts values in reverse using `top_k`. - - Args: - values: Tensor of numeric values. - axis: Index of the axis which values should be sorted along. - return_argsort: If False, return the sorted values. If True, return the - indices that would sort the values. - - Returns: - The sorted values. - """ - k = array_ops.shape(values)[axis] - rank = array_ops.rank(values) - static_rank = values.shape.ndims - # Fast path: sorting the last axis. - if axis == -1 or axis + 1 == values.get_shape().ndims: - top_k_input = values - transposition = None - else: - # Otherwise, transpose the array. Swap axes `axis` and `rank - 1`. - if axis < 0: - # Calculate the actual axis index if counting from the end. Use the static - # rank if available, or else make the axis back into a tensor. - axis += static_rank or rank - if static_rank is not None: - # Prefer to calculate the transposition array in NumPy and make it a - # constant. - transposition = constant_op.constant( - np.r_[ - # Axes up to axis are unchanged. - np.arange(axis), - # Swap axis and rank - 1. - [static_rank - 1], - # Axes in [axis + 1, rank - 1) are unchanged. - np.arange(axis + 1, static_rank - 1), - # Swap axis and rank - 1. - [axis]], - name='transposition') - else: - # Generate the transposition array from the tensors. - transposition = array_ops.concat( - [ - # Axes up to axis are unchanged. - math_ops.range(axis), - # Swap axis and rank - 1. - [rank - 1], - # Axes in [axis + 1, rank - 1) are unchanged. - math_ops.range(axis + 1, rank - 1), - # Swap axis and rank - 1. - [axis] - ], - axis=0) - top_k_input = array_ops.transpose(values, transposition) - - values, indices = nn_ops.top_k(top_k_input, k) - return_value = indices if return_argsort else values - if transposition is not None: - # transposition contains a single cycle of length 2 (swapping 2 elements), - # so it is an involution (it is its own inverse). - return_value = array_ops.transpose(return_value, transposition) - return return_value - - -def _ascending_sort(values, axis, return_argsort=False): - # Negate the values to get the ascending order from descending sort. - values_or_indices = _descending_sort(-values, axis, return_argsort) - # If not argsort, negate the values again. - return values_or_indices if return_argsort else -values_or_indices - - -_SORT_IMPL = { - 'ASCENDING': _ascending_sort, - 'DESCENDING': _descending_sort, -} +sort = sort_ops.sort +argsort = sort_ops.argsort diff --git a/tensorflow/contrib/gan/python/estimator/python/gan_estimator_impl.py b/tensorflow/contrib/gan/python/estimator/python/gan_estimator_impl.py index 219cc199d7..3593b501bb 100644 --- a/tensorflow/contrib/gan/python/estimator/python/gan_estimator_impl.py +++ b/tensorflow/contrib/gan/python/estimator/python/gan_estimator_impl.py @@ -113,7 +113,8 @@ class GANEstimator(estimator.Estimator): add_summaries=None, use_loss_summaries=True, config=None, - warm_start_from=None): + warm_start_from=None, + is_chief=True): """Initializes a GANEstimator instance. Args: @@ -154,6 +155,8 @@ class GANEstimator(estimator.Estimator): config: `RunConfig` object to configure the runtime settings. warm_start_from: A filepath to a checkpoint or saved model, or a WarmStartSettings object to configure initialization. + is_chief: Whether or not this Estimator is running on a chief or worker. + Needs to be set appropriately if using SyncReplicasOptimizers. Raises: ValueError: If loss functions aren't callable. @@ -187,7 +190,7 @@ class GANEstimator(estimator.Estimator): return _get_estimator_spec( mode, gan_model, generator_loss_fn, discriminator_loss_fn, get_eval_metric_ops_fn, generator_optimizer, discriminator_optimizer, - get_hooks_fn, use_loss_summaries) + get_hooks_fn, use_loss_summaries, is_chief) super(GANEstimator, self).__init__( model_fn=_model_fn, model_dir=model_dir, config=config, @@ -215,7 +218,7 @@ def _get_gan_model( def _get_estimator_spec( mode, gan_model, generator_loss_fn, discriminator_loss_fn, get_eval_metric_ops_fn, generator_optimizer, discriminator_optimizer, - get_hooks_fn=None, use_loss_summaries=True): + get_hooks_fn=None, use_loss_summaries=True, is_chief=True): """Get the EstimatorSpec for the current mode.""" if mode == model_fn_lib.ModeKeys.PREDICT: estimator_spec = model_fn_lib.EstimatorSpec( @@ -236,7 +239,7 @@ def _get_estimator_spec( else discriminator_optimizer) get_hooks_fn = get_hooks_fn or tfgan_train.get_sequential_train_hooks() estimator_spec = _get_train_estimator_spec( - gan_model, gan_loss, gopt, dopt, get_hooks_fn) + gan_model, gan_loss, gopt, dopt, get_hooks_fn, is_chief=is_chief) return estimator_spec @@ -321,11 +324,11 @@ def _get_eval_estimator_spec(gan_model, gan_loss, get_eval_metric_ops_fn=None, def _get_train_estimator_spec( gan_model, gan_loss, generator_optimizer, discriminator_optimizer, - get_hooks_fn, train_op_fn=tfgan_train.gan_train_ops): + get_hooks_fn, train_op_fn=tfgan_train.gan_train_ops, is_chief=True): """Return an EstimatorSpec for the train case.""" scalar_loss = gan_loss.generator_loss + gan_loss.discriminator_loss train_ops = train_op_fn(gan_model, gan_loss, generator_optimizer, - discriminator_optimizer) + discriminator_optimizer, is_chief=is_chief) training_hooks = get_hooks_fn(train_ops) return model_fn_lib.EstimatorSpec( loss=scalar_loss, diff --git a/tensorflow/contrib/gan/python/estimator/python/gan_estimator_test.py b/tensorflow/contrib/gan/python/estimator/python/gan_estimator_test.py index 3d6bdab0ad..bc9021050b 100644 --- a/tensorflow/contrib/gan/python/estimator/python/gan_estimator_test.py +++ b/tensorflow/contrib/gan/python/estimator/python/gan_estimator_test.py @@ -48,6 +48,7 @@ from tensorflow.python.platform import test from tensorflow.python.summary.writer import writer_cache from tensorflow.python.training import input as input_lib from tensorflow.python.training import learning_rate_decay +from tensorflow.python.training import sync_replicas_optimizer from tensorflow.python.training import training from tensorflow.python.training import training_util @@ -82,7 +83,7 @@ class GetGANModelTest(test.TestCase, parameterized.TestCase): self.assertEqual(generator_inputs, gan_model.generator_inputs) self.assertIsNotNone(gan_model.generated_data) - self.assertEqual(2, len(gan_model.generator_variables)) # 1 FC layer + self.assertLen(gan_model.generator_variables, 2) # 1 FC layer self.assertIsNotNone(gan_model.generator_fn) if mode == model_fn_lib.ModeKeys.PREDICT: self.assertIsNone(gan_model.real_data) @@ -95,7 +96,7 @@ class GetGANModelTest(test.TestCase, parameterized.TestCase): self.assertIsNotNone(gan_model.real_data) self.assertIsNotNone(gan_model.discriminator_real_outputs) self.assertIsNotNone(gan_model.discriminator_gen_outputs) - self.assertEqual(2, len(gan_model.discriminator_variables)) # 1 FC layer + self.assertLen(gan_model.discriminator_variables, 2) # 1 FC layer self.assertIsNotNone(gan_model.discriminator_scope) self.assertIsNotNone(gan_model.discriminator_fn) @@ -121,6 +122,7 @@ def get_dummy_gan_model(): def dummy_loss_fn(gan_model, add_summaries=True): + del add_summaries return math_ops.reduce_sum(gan_model.discriminator_real_outputs - gan_model.discriminator_gen_outputs) @@ -168,6 +170,35 @@ class GetEstimatorSpecTest(test.TestCase, parameterized.TestCase): self.assertShapeEqual(np.array(0), spec.loss) # must be a scalar self.assertIsNotNone(spec.eval_metric_ops) + def test_get_sync_estimator_spec(self): + """Make sure spec is loaded with sync hooks for sync opts.""" + + def get_sync_optimizer(): + return sync_replicas_optimizer.SyncReplicasOptimizer( + training.GradientDescentOptimizer(learning_rate=1.0), + replicas_to_aggregate=1) + + with ops.Graph().as_default(): + self._gan_model = get_dummy_gan_model() + g_opt = get_sync_optimizer() + d_opt = get_sync_optimizer() + + spec = estimator._get_estimator_spec( + model_fn_lib.ModeKeys.TRAIN, + self._gan_model, + generator_loss_fn=dummy_loss_fn, + discriminator_loss_fn=dummy_loss_fn, + get_eval_metric_ops_fn=get_metrics, + generator_optimizer=g_opt, + discriminator_optimizer=d_opt) + + self.assertLen(spec.training_hooks, 4) + sync_opts = [ + hook._sync_optimizer for hook in spec.training_hooks if + isinstance(hook, sync_replicas_optimizer._SyncReplicasOptimizerHook)] + self.assertLen(sync_opts, 2) + self.assertSetEqual(frozenset(sync_opts), frozenset((g_opt, d_opt))) + # TODO(joelshor): Add pandas test. class GANEstimatorIntegrationTest(test.TestCase): diff --git a/tensorflow/contrib/gan/python/losses/python/losses_impl.py b/tensorflow/contrib/gan/python/losses/python/losses_impl.py index df0342c80c..a0a86c6337 100644 --- a/tensorflow/contrib/gan/python/losses/python/losses_impl.py +++ b/tensorflow/contrib/gan/python/losses/python/losses_impl.py @@ -36,7 +36,6 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import numpy as np from tensorflow.contrib.framework.python.ops import variables as contrib_variables_lib from tensorflow.python.framework import ops @@ -47,7 +46,6 @@ from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import variable_scope -from tensorflow.python.ops.distributions import distribution as ds from tensorflow.python.ops.losses import losses from tensorflow.python.ops.losses import util from tensorflow.python.summary import summary @@ -740,11 +738,16 @@ def least_squares_discriminator_loss( def _validate_distributions(distributions): if not isinstance(distributions, (list, tuple)): raise ValueError('`distributions` must be a list or tuple. Instead, ' - 'found %s.', type(distributions)) + 'found %s.' % type(distributions)) for x in distributions: - if not isinstance(x, ds.Distribution): + # We used to check with `isinstance(x, tf.distributions.Distribution)`. + # However, distributions have migrated to `tfp.distributions.Distribution`, + # which is a new code repo, so we can't check this way anymore until + # TF-GAN is migrated to a new repo as well. + # This new check is not sufficient, but is a useful heuristic for now. + if not callable(getattr(x, 'log_prob', None)): raise ValueError('`distributions` must be a list of `Distributions`. ' - 'Instead, found %s.', type(x)) + 'Instead, found %s.' % type(x)) def _validate_information_penalty_inputs( @@ -817,7 +820,7 @@ def _numerically_stable_global_norm(tensor_list): Returns: A scalar tensor with the global norm. """ - if np.all([x is None for x in tensor_list]): + if all(x is None for x in tensor_list): return 0.0 list_max = math_ops.reduce_max([math_ops.reduce_max(math_ops.abs(x)) for x in diff --git a/tensorflow/contrib/gan/python/namedtuples.py b/tensorflow/contrib/gan/python/namedtuples.py index b9ac1bf151..969b68449d 100644 --- a/tensorflow/contrib/gan/python/namedtuples.py +++ b/tensorflow/contrib/gan/python/namedtuples.py @@ -213,7 +213,8 @@ class GANTrainOps( collections.namedtuple('GANTrainOps', ( 'generator_train_op', 'discriminator_train_op', - 'global_step_inc_op' + 'global_step_inc_op', + 'train_hooks' ))): """GANTrainOps contains the training ops. @@ -221,8 +222,17 @@ class GANTrainOps( generator_train_op: Op that performs a generator update step. discriminator_train_op: Op that performs a discriminator update step. global_step_inc_op: Op that increments the shared global step. + train_hooks: a list or tuple containing hooks related to training that need + to be populated when training ops are instantiated. Used primarily for + sync hooks. """ + def __new__(cls, generator_train_op, discriminator_train_op, + global_step_inc_op, train_hooks=()): + return super(GANTrainOps, cls).__new__(cls, generator_train_op, + discriminator_train_op, + global_step_inc_op, train_hooks) + class GANTrainSteps( collections.namedtuple('GANTrainSteps', ( diff --git a/tensorflow/contrib/gan/python/train.py b/tensorflow/contrib/gan/python/train.py index 7ee39f304a..4c7bee41b3 100644 --- a/tensorflow/contrib/gan/python/train.py +++ b/tensorflow/contrib/gan/python/train.py @@ -114,7 +114,7 @@ def gan_model( discriminator_gen_outputs = discriminator_fn(generated_data, generator_inputs) with variable_scope.variable_scope(dis_scope, reuse=True): - real_data = ops.convert_to_tensor(real_data) + real_data = _convert_tensor_or_l_or_d(real_data) discriminator_real_outputs = discriminator_fn(real_data, generator_inputs) if check_shapes: @@ -924,6 +924,7 @@ def gan_train_ops( generator_optimizer, discriminator_optimizer, check_for_unused_update_ops=True, + is_chief=True, # Optional args to pass directly to the `create_train_op`. **kwargs): """Returns GAN train ops. @@ -939,6 +940,8 @@ def gan_train_ops( discriminator_optimizer: The optimizer for the discriminator updates. check_for_unused_update_ops: If `True`, throws an exception if there are update ops outside of the generator or discriminator scopes. + is_chief: Specifies whether or not the training is being run by the primary + replica during replica training. **kwargs: Keyword args to pass directly to `training.create_train_op` for both the generator and discriminator train op. @@ -980,6 +983,9 @@ def gan_train_ops( kwargs, model.generator_scope.name, model.discriminator_scope.name, check_for_unused_update_ops) + # Get the sync hooks if these are needed. + sync_hooks = [] + generator_global_step = None if isinstance(generator_optimizer, sync_replicas_optimizer.SyncReplicasOptimizer): @@ -995,6 +1001,7 @@ def gan_train_ops( trainable=False, collections=[ops.GraphKeys.GLOBAL_VARIABLES]) gen_update_ops += [generator_global_step.assign(global_step)] + sync_hooks.append(generator_optimizer.make_session_run_hook(is_chief)) with ops.name_scope('generator_train'): gen_train_op = training.create_train_op( total_loss=loss.generator_loss, @@ -1016,6 +1023,7 @@ def gan_train_ops( trainable=False, collections=[ops.GraphKeys.GLOBAL_VARIABLES]) dis_update_ops += [discriminator_global_step.assign(global_step)] + sync_hooks.append(discriminator_optimizer.make_session_run_hook(is_chief)) with ops.name_scope('discriminator_train'): disc_train_op = training.create_train_op( total_loss=loss.discriminator_loss, @@ -1025,7 +1033,8 @@ def gan_train_ops( update_ops=dis_update_ops, **kwargs) - return namedtuples.GANTrainOps(gen_train_op, disc_train_op, global_step_inc) + return namedtuples.GANTrainOps(gen_train_op, disc_train_op, global_step_inc, + sync_hooks) # TODO(joelshor): Implement a dynamic GAN train loop, as in `Real-Time Adaptive @@ -1066,13 +1075,24 @@ def get_sequential_train_hooks(train_steps=namedtuples.GANTrainSteps(1, 1)): train_steps.generator_train_steps) discriminator_hook = RunTrainOpsHook(train_ops.discriminator_train_op, train_steps.discriminator_train_steps) - return [generator_hook, discriminator_hook] + return [generator_hook, discriminator_hook] + list(train_ops.train_hooks) return get_hooks +def _num_joint_steps(train_steps): + g_steps = train_steps.generator_train_steps + d_steps = train_steps.discriminator_train_steps + # Get the number of each type of step that should be run. + num_d_and_g_steps = min(g_steps, d_steps) + num_g_steps = g_steps - num_d_and_g_steps + num_d_steps = d_steps - num_d_and_g_steps + + return num_d_and_g_steps, num_g_steps, num_d_steps + + def get_joint_train_hooks(train_steps=namedtuples.GANTrainSteps(1, 1)): - """Returns a hooks function for sequential GAN training. + """Returns a hooks function for joint GAN training. When using these train hooks, IT IS RECOMMENDED TO USE `use_locking=True` ON ALL OPTIMIZERS TO AVOID RACE CONDITIONS. @@ -1105,12 +1125,7 @@ def get_joint_train_hooks(train_steps=namedtuples.GANTrainSteps(1, 1)): Returns: A function that takes a GANTrainOps tuple and returns a list of hooks. """ - g_steps = train_steps.generator_train_steps - d_steps = train_steps.discriminator_train_steps - # Get the number of each type of step that should be run. - num_d_and_g_steps = min(g_steps, d_steps) - num_g_steps = g_steps - num_d_and_g_steps - num_d_steps = d_steps - num_d_and_g_steps + num_d_and_g_steps, num_g_steps, num_d_steps = _num_joint_steps(train_steps) def get_hooks(train_ops): g_op = train_ops.generator_train_op @@ -1120,7 +1135,7 @@ def get_joint_train_hooks(train_steps=namedtuples.GANTrainSteps(1, 1)): g_hook = RunTrainOpsHook(g_op, num_g_steps) d_hook = RunTrainOpsHook(d_op, num_d_steps) - return [joint_hook, g_hook, d_hook] + return [joint_hook, g_hook, d_hook] + list(train_ops.train_hooks) return get_hooks diff --git a/tensorflow/contrib/gan/python/train_test.py b/tensorflow/contrib/gan/python/train_test.py index 64d6706199..841f25cd7f 100644 --- a/tensorflow/contrib/gan/python/train_test.py +++ b/tensorflow/contrib/gan/python/train_test.py @@ -519,7 +519,7 @@ class GANLossTest(test.TestCase, parameterized.TestCase): """Test output type.""" loss = train.gan_loss(get_gan_model_fn(), add_summaries=True) self.assertIsInstance(loss, namedtuples.GANLoss) - self.assertGreater(len(ops.get_collection(ops.GraphKeys.SUMMARIES)), 0) + self.assertNotEmpty(ops.get_collection(ops.GraphKeys.SUMMARIES)) @parameterized.named_parameters( ('cyclegan', create_cyclegan_model), @@ -528,7 +528,7 @@ class GANLossTest(test.TestCase, parameterized.TestCase): def test_cyclegan_output_type(self, get_gan_model_fn): loss = train.cyclegan_loss(get_gan_model_fn(), add_summaries=True) self.assertIsInstance(loss, namedtuples.CycleGANLoss) - self.assertGreater(len(ops.get_collection(ops.GraphKeys.SUMMARIES)), 0) + self.assertNotEmpty(ops.get_collection(ops.GraphKeys.SUMMARIES)) @parameterized.named_parameters( ('gan', create_gan_model, False), @@ -759,7 +759,7 @@ class TensorPoolAdjusteModelTest(test.TestCase): # For [pool_size, ?), the pool is full, tensor2 must be equal to some # historical values of tensor1 (which is previously stored in the # pool). - self.assertTrue(any([(v == t2).all() for v in history_values])) + self.assertTrue(any((v == t2).all() for v in history_values)) def _make_new_model_and_check(self, model, pool_size): pool_fn = lambda x: random_tensor_pool.tensor_pool(x, pool_size=pool_size) @@ -836,6 +836,9 @@ class GANTrainOpsTest(test.TestCase, parameterized.TestCase): self.assertIsInstance(train_ops, namedtuples.GANTrainOps) + # Make sure there are no training hooks populated accidentally. + self.assertEmpty(train_ops.train_hooks) + # TODO(joelshor): Add a test to check that custom update op is run. @parameterized.named_parameters( ('gan', create_gan_model, False), @@ -923,8 +926,15 @@ class GANTrainOpsTest(test.TestCase, parameterized.TestCase): model, loss, generator_optimizer=g_opt, discriminator_optimizer=d_opt) self.assertIsInstance(train_ops, namedtuples.GANTrainOps) # No new trainable variables should have been added. - self.assertEqual(num_trainable_vars, - len(variables_lib.get_trainable_variables())) + self.assertLen(variables_lib.get_trainable_variables(), num_trainable_vars) + + # Sync hooks should be populated in the GANTrainOps. + self.assertLen(train_ops.train_hooks, 2) + for hook in train_ops.train_hooks: + self.assertIsInstance( + hook, sync_replicas_optimizer._SyncReplicasOptimizerHook) + sync_opts = [hook._sync_optimizer for hook in train_ops.train_hooks] + self.assertSetEqual(frozenset(sync_opts), frozenset((g_opt, d_opt))) g_sync_init_op = g_opt.get_init_tokens_op(num_tokens=1) d_sync_init_op = d_opt.get_init_tokens_op(num_tokens=1) @@ -959,6 +969,32 @@ class GANTrainOpsTest(test.TestCase, parameterized.TestCase): coord.request_stop() coord.join(g_threads + d_threads) + @parameterized.named_parameters( + ('is_chief', True), + ('is_not_chief', False), + ) + def test_is_chief_in_train_hooks(self, is_chief): + """Make sure is_chief is propagated correctly to sync hooks.""" + model = create_gan_model() + loss = train.gan_loss(model) + g_opt = get_sync_optimizer() + d_opt = get_sync_optimizer() + train_ops = train.gan_train_ops( + model, + loss, + g_opt, + d_opt, + is_chief=is_chief, + summarize_gradients=True, + colocate_gradients_with_ops=True) + + self.assertLen(train_ops.train_hooks, 2) + for hook in train_ops.train_hooks: + self.assertIsInstance( + hook, sync_replicas_optimizer._SyncReplicasOptimizerHook) + is_chief_list = [hook._is_chief for hook in train_ops.train_hooks] + self.assertListEqual(is_chief_list, [is_chief, is_chief]) + class GANTrainTest(test.TestCase, parameterized.TestCase): """Tests for `gan_train`.""" @@ -1036,6 +1072,44 @@ class GANTrainTest(test.TestCase, parameterized.TestCase): self.assertTrue(np.isscalar(final_loss)) self.assertEqual(17.0, final_loss) + @parameterized.named_parameters( + ('gan', create_gan_model), + ('callable_gan', create_callable_gan_model), + ('infogan', create_infogan_model), + ('callable_infogan', create_callable_infogan_model), + ('acgan', create_acgan_model), + ('callable_acgan', create_callable_acgan_model), + ) + def test_train_hooks_exist_in_get_hooks_fn(self, create_gan_model_fn): + model = create_gan_model_fn() + loss = train.gan_loss(model) + + g_opt = get_sync_optimizer() + d_opt = get_sync_optimizer() + train_ops = train.gan_train_ops( + model, + loss, + g_opt, + d_opt, + summarize_gradients=True, + colocate_gradients_with_ops=True) + + sequential_train_hooks = train.get_sequential_train_hooks()(train_ops) + self.assertLen(sequential_train_hooks, 4) + sync_opts = [ + hook._sync_optimizer for hook in sequential_train_hooks if + isinstance(hook, sync_replicas_optimizer._SyncReplicasOptimizerHook)] + self.assertLen(sync_opts, 2) + self.assertSetEqual(frozenset(sync_opts), frozenset((g_opt, d_opt))) + + joint_train_hooks = train.get_joint_train_hooks()(train_ops) + self.assertLen(joint_train_hooks, 5) + sync_opts = [ + hook._sync_optimizer for hook in joint_train_hooks if + isinstance(hook, sync_replicas_optimizer._SyncReplicasOptimizerHook)] + self.assertLen(sync_opts, 2) + self.assertSetEqual(frozenset(sync_opts), frozenset((g_opt, d_opt))) + class PatchGANTest(test.TestCase, parameterized.TestCase): """Tests that functions work on PatchGAN style output.""" diff --git a/tensorflow/contrib/gdr/gdr_rendezvous_mgr.cc b/tensorflow/contrib/gdr/gdr_rendezvous_mgr.cc index 94f522c04e..fbccbead03 100644 --- a/tensorflow/contrib/gdr/gdr_rendezvous_mgr.cc +++ b/tensorflow/contrib/gdr/gdr_rendezvous_mgr.cc @@ -170,6 +170,14 @@ class GdrRemoteRendezvous : public BaseRemoteRendezvous { // Record "call" in active_ so that it can be aborted cleanly. RegisterCall(call); + // RendezvousMgr already aborted, shouldn't send RPC call any more + if (!call->status().ok()) { + done(call->status(), Args(), Args(), Tensor(), false); + session()->worker_cache->ReleaseWorker(src_worker, rwi); + delete call; + return; + } + // Start "call". Ref(); call->Start([this, call, src_worker, rwi, done]() { diff --git a/tensorflow/contrib/hadoop/python/kernel_tests/hadoop_test.py b/tensorflow/contrib/hadoop/python/kernel_tests/hadoop_test.py index f7f1189bb9..bc941ae9f2 100644 --- a/tensorflow/contrib/hadoop/python/kernel_tests/hadoop_test.py +++ b/tensorflow/contrib/hadoop/python/kernel_tests/hadoop_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import os from tensorflow.contrib.hadoop.python.ops import hadoop_dataset_ops +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors @@ -47,7 +48,7 @@ class SequenceFileDatasetTest(test.TestCase): dataset = hadoop_dataset_ops.SequenceFileDataset(filenames).repeat( num_repeats) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() diff --git a/tensorflow/contrib/hadoop/python/ops/hadoop_dataset_ops.py b/tensorflow/contrib/hadoop/python/ops/hadoop_dataset_ops.py index bf398b838d..d3fcc8cb2a 100644 --- a/tensorflow/contrib/hadoop/python/ops/hadoop_dataset_ops.py +++ b/tensorflow/contrib/hadoop/python/ops/hadoop_dataset_ops.py @@ -40,15 +40,12 @@ class SequenceFileDataset(dataset_ops.DatasetSource): For example: ```python + tf.enable_eager_execution() + dataset = tf.contrib.hadoop.SequenceFileDataset("/foo/bar.seq") - iterator = dataset.make_one_shot_iterator() - next_element = iterator.get_next() # Prints the (key, value) pairs inside a hadoop sequence file. - while True: - try: - print(sess.run(next_element)) - except tf.errors.OutOfRangeError: - break + for key, value in dataset: + print(key, value) ``` Args: diff --git a/tensorflow/contrib/ignite/README.md b/tensorflow/contrib/ignite/README.md index c7db0b77e2..5a8c650fb9 100644 --- a/tensorflow/contrib/ignite/README.md +++ b/tensorflow/contrib/ignite/README.md @@ -54,14 +54,12 @@ jdbc:ignite:thin://localhost/> INSERT INTO KITTEN_CACHE VALUES (3, 'LITTLE BALL ```python >>> import tensorflow as tf >>> from tensorflow.contrib.ignite import IgniteDataset ->>> +>>> tf.enable_eager_execution() +>>> >>> dataset = IgniteDataset(cache_name="SQL_PUBLIC_KITTEN_CACHE") ->>> iterator = dataset.make_one_shot_iterator() ->>> next_obj = iterator.get_next() >>> ->>> with tf.Session() as sess: ->>> for _ in range(3): ->>> print(sess.run(next_obj)) +>>> for element in dataset: +>>> print(element) {'key': 1, 'val': {'NAME': b'WARM KITTY'}} {'key': 2, 'val': {'NAME': b'SOFT KITTY'}} @@ -74,23 +72,22 @@ jdbc:ignite:thin://localhost/> INSERT INTO KITTEN_CACHE VALUES (3, 'LITTLE BALL ```python >>> import tensorflow as tf >>> from tensorflow.contrib.ignite import IgniteDataset ->>> +>>> tf.enable_eager_execution() +>>> >>> dataset = IgniteDataset(cache_name="IMAGES") ->>> iterator = dataset.make_one_shot_iterator() ->>> next_obj = iterator.get_next() >>> ->>> with tf.Session() as sess: ->>> print(sess.run(next_obj)) +>>> for element in dataset.take(1): +>>> print(element) { - 'key': 'kitten.png', + 'key': 'kitten.png', 'val': { 'metadata': { 'file_name': b'kitten.png', 'label': b'little ball of fur', - width: 800, + width: 800, height: 600 - }, + }, 'pixels': [0, 0, 0, 0, ..., 0] } } @@ -100,13 +97,11 @@ jdbc:ignite:thin://localhost/> INSERT INTO KITTEN_CACHE VALUES (3, 'LITTLE BALL ```python >>> import tensorflow as tf >>> from tensorflow.contrib.ignite import IgniteDataset ->>> +>>> >>> dataset = IgniteDataset(cache_name="IMAGES").map(lambda obj: obj['val']['pixels']) ->>> iterator = dataset.make_one_shot_iterator() ->>> next_obj = iterator.get_next() >>> ->>> with tf.Session() as sess: ->>> print(sess.run(next_obj)) +>>> for element in dataset: +>>> print(element) [0, 0, 0, 0, ..., 0] ``` @@ -126,18 +121,18 @@ Ignite Dataset allows using these two aspects of distributed neural network trai ```python >>> import tensorflow as tf >>> from tensorflow.contrib.ignite import IgniteDataset ->>> +>>> >>> dataset = IgniteDataset("IMAGES") >>> >>> # Compute gradients locally on every worker node. ->>> gradients = [] +>>> gradients = [] >>> for i in range(5): >>> with tf.device("/job:WORKER/task:%d" % i): ->>> device_iterator = dataset.make_one_shot_iterator() +>>> device_iterator = tf.compat.v1.data.make_one_shot_iterator(dataset) >>> device_next_obj = device_iterator.get_next() >>> gradient = compute_gradient(device_next_obj) ->>> gradients.append(gradient) ->>> +>>> gradients.append(gradient) +>>> >>> # Aggregate them on master node. >>> result_gradient = tf.reduce_sum(gradients) >>> @@ -145,7 +140,7 @@ Ignite Dataset allows using these two aspects of distributed neural network trai >>> print(sess.run(result_gradient)) ``` -High-level TensorFlow API for [distributed training](https://www.tensorflow.org/api_docs/python/tf/contrib/distribute/DistributionStrategy) is supported as well. +High-level TensorFlow API for [distributed training](https://www.tensorflow.org/api_docs/python/tf/contrib/distribute/DistributionStrategy) is supported as well. ### Distributed File System diff --git a/tensorflow/contrib/ignite/python/tests/ignite_dataset_test.py b/tensorflow/contrib/ignite/python/tests/ignite_dataset_test.py index ef29b5f14a..ff5d4c458c 100644 --- a/tensorflow/contrib/ignite/python/tests/ignite_dataset_test.py +++ b/tensorflow/contrib/ignite/python/tests/ignite_dataset_test.py @@ -21,6 +21,7 @@ import os from tensorflow.contrib.ignite import IgniteDataset from tensorflow.python.client import session +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.platform import test @@ -65,7 +66,7 @@ class IgniteDatasetTest(test.TestCase): self.assertEqual(dtypes.string, dataset.output_types["val"]["NAME"]) self.assertEqual(dtypes.int64, dataset.output_types["val"]["VAL"]) - it = dataset.make_one_shot_iterator() + it = dataset_ops.make_one_shot_iterator(dataset) ne = it.get_next() with session.Session() as sess: diff --git a/tensorflow/contrib/image/kernels/adjust_hsv_in_yiq_op.cc b/tensorflow/contrib/image/kernels/adjust_hsv_in_yiq_op.cc index 478b716d88..108da04494 100644 --- a/tensorflow/contrib/image/kernels/adjust_hsv_in_yiq_op.cc +++ b/tensorflow/contrib/image/kernels/adjust_hsv_in_yiq_op.cc @@ -115,7 +115,7 @@ class AdjustHsvInYiqOp : public AdjustHsvInYiqOpBase { *context->device()->tensorflow_cpu_worker_threads(); Shard(worker_threads.num_threads, worker_threads.workers, channel_count, kCostPerChannel, - [channel_count, &input_data, &output_data, &tranformation_matrix]( + [&input_data, &output_data, &tranformation_matrix]( int64 start_channel, int64 end_channel) { // Applying projection matrix to input RGB vectors. const float* p = input_data.data() + start_channel * kChannelSize; diff --git a/tensorflow/contrib/image/python/ops/dense_image_warp.py b/tensorflow/contrib/image/python/ops/dense_image_warp.py index 9c7ada7afb..7930b8317b 100644 --- a/tensorflow/contrib/image/python/ops/dense_image_warp.py +++ b/tensorflow/contrib/image/python/ops/dense_image_warp.py @@ -25,7 +25,7 @@ from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops - +from tensorflow.python.ops import check_ops def _interpolate_bilinear(grid, query_points, @@ -60,28 +60,40 @@ def _interpolate_bilinear(grid, msg = 'Grid must be 4 dimensional. Received size: ' raise ValueError(msg + str(grid.get_shape())) - batch_size, height, width, channels = shape + batch_size, height, width, channels = (array_ops.shape(grid)[0], + array_ops.shape(grid)[1], + array_ops.shape(grid)[2], + array_ops.shape(grid)[3]) + + shape = [batch_size, height, width, channels] query_type = query_points.dtype grid_type = grid.dtype - if (query_points.shape.rank != 3 or - query_points.shape.dims[2].value != 2): - msg = ('Query points must be 3 dimensional and size 2 in dim 2. Received ' - 'size: ') - raise ValueError(msg + str(query_points.get_shape())) - - _, num_queries, _ = query_points.get_shape().as_list() - - if height < 2 or width < 2: - msg = 'Grid must be at least batch_size x 2 x 2 in size. Received size: ' - raise ValueError(msg + str(grid.get_shape())) - - alphas = [] - floors = [] - ceils = [] - - index_order = [0, 1] if indexing == 'ij' else [1, 0] - unstacked_query_points = array_ops.unstack(query_points, axis=2) + with ops.control_dependencies([ + check_ops.assert_equal( + len(query_points.get_shape()), + 3, + message='Query points must be 3 dimensional.'), + check_ops.assert_equal( + array_ops.shape(query_points)[2], + 2, + message='Query points must be size 2 in dim 2.')]): + num_queries = array_ops.shape(query_points)[1] + + with ops.control_dependencies([ + check_ops.assert_greater_equal( + height, + 2, + message='Grid height must be at least 2.'), + check_ops.assert_greater_equal( + width, + 2, + message='Grid width must be at least 2.')]): + alphas = [] + floors = [] + ceils = [] + index_order = [0, 1] if indexing == 'ij' else [1, 0] + unstacked_query_points = array_ops.unstack(query_points, axis=2) for dim in index_order: with ops.name_scope('dim-' + str(dim)): @@ -112,16 +124,17 @@ def _interpolate_bilinear(grid, alpha = array_ops.expand_dims(alpha, 2) alphas.append(alpha) - if batch_size * height * width > np.iinfo(np.int32).max / 8: - error_msg = """The image size or batch size is sufficiently large - that the linearized addresses used by array_ops.gather - may exceed the int32 limit.""" - raise ValueError(error_msg) - - flattened_grid = array_ops.reshape(grid, - [batch_size * height * width, channels]) - batch_offsets = array_ops.reshape( - math_ops.range(batch_size) * height * width, [batch_size, 1]) + with ops.control_dependencies([ + check_ops.assert_less_equal( + math_ops.cast(batch_size * height * width, dtype=dtypes.float32), + np.iinfo(np.int32).max / 8, + message="""The image size or batch size is sufficiently large + that the linearized addresses used by array_ops.gather + may exceed the int32 limit.""")]): + flattened_grid = array_ops.reshape( + grid, [batch_size * height * width, channels]) + batch_offsets = array_ops.reshape( + math_ops.range(batch_size) * height * width, [batch_size, 1]) # This wraps array_ops.gather. We reshape the image data such that the # batch, y, and x coordinates are pulled into the first dimension. @@ -182,7 +195,11 @@ def dense_image_warp(image, flow, name='dense_image_warp'): of dimensions. """ with ops.name_scope(name): - batch_size, height, width, channels = image.get_shape().as_list() + batch_size, height, width, channels = (array_ops.shape(image)[0], + array_ops.shape(image)[1], + array_ops.shape(image)[2], + array_ops.shape(image)[3]) + # The flow is defined on the image grid. Turn the flow into a list of query # points in the grid space. grid_x, grid_y = array_ops.meshgrid( diff --git a/tensorflow/contrib/keras/api/keras/layers/__init__.py b/tensorflow/contrib/keras/api/keras/layers/__init__.py index 3327a9f9a6..9e19884df8 100644 --- a/tensorflow/contrib/keras/api/keras/layers/__init__.py +++ b/tensorflow/contrib/keras/api/keras/layers/__init__.py @@ -20,7 +20,7 @@ from __future__ import print_function # Generic layers. # pylint: disable=g-bad-import-order -from tensorflow.python.keras.engine.base_layer import InputSpec +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.engine.base_layer import Layer from tensorflow.python.keras.engine.input_layer import Input from tensorflow.python.keras.engine.input_layer import InputLayer diff --git a/tensorflow/contrib/keras/api/keras/utils/__init__.py b/tensorflow/contrib/keras/api/keras/utils/__init__.py index 47cd01b924..3b9fa1b230 100644 --- a/tensorflow/contrib/keras/api/keras/utils/__init__.py +++ b/tensorflow/contrib/keras/api/keras/utils/__init__.py @@ -30,6 +30,7 @@ from tensorflow.python.keras.utils.generic_utils import Progbar from tensorflow.python.keras.utils.generic_utils import serialize_keras_object from tensorflow.python.keras.utils.io_utils import HDF5Matrix from tensorflow.python.keras.utils.layer_utils import convert_all_kernels_in_model +from tensorflow.python.keras.utils.losses_utils import squeeze_or_expand_dimensions from tensorflow.python.keras.utils.np_utils import normalize from tensorflow.python.keras.utils.np_utils import to_categorical from tensorflow.python.keras.utils.vis_utils import plot_model diff --git a/tensorflow/contrib/kernel_methods/python/kernel_estimators.py b/tensorflow/contrib/kernel_methods/python/kernel_estimators.py index de7530231d..1626e55b9b 100644 --- a/tensorflow/contrib/kernel_methods/python/kernel_estimators.py +++ b/tensorflow/contrib/kernel_methods/python/kernel_estimators.py @@ -90,7 +90,7 @@ def _update_features_and_columns(features, feature_columns, mapped_column_name = column_name + "_MAPPED" # Construct new feature columns based on provided kernel_mappers. column_kernel_mappers = kernel_mappers_dict[feature_column] - new_dim = sum([mapper.output_dim for mapper in column_kernel_mappers]) + new_dim = sum(mapper.output_dim for mapper in column_kernel_mappers) mapped_columns.add( layers.feature_column.real_valued_column(mapped_column_name, new_dim)) diff --git a/tensorflow/contrib/kinesis/python/ops/kinesis_dataset_ops.py b/tensorflow/contrib/kinesis/python/ops/kinesis_dataset_ops.py index 75806dbbeb..c392adbb1d 100644 --- a/tensorflow/contrib/kinesis/python/ops/kinesis_dataset_ops.py +++ b/tensorflow/contrib/kinesis/python/ops/kinesis_dataset_ops.py @@ -34,15 +34,12 @@ class KinesisDataset(dataset_ops.DatasetSource): For example, we can construct and use the KinesisDataset as follows: ```python + tf.enable_eager_execution() + dataset = tf.contrib.kinesis.KinesisDataset( "kinesis_stream_name", read_indefinitely=False) - next = dataset.make_one_shot_iterator().get_next() - with tf.Session() as sess: - while True: - try: - print(sess.run(nxt)) - except tf.errors.OutOfRangeError: - break + for element in dataset: + print(element) ``` Since Kinesis is a data streaming service, data may not be available diff --git a/tensorflow/contrib/layers/BUILD b/tensorflow/contrib/layers/BUILD index e6596bfdfb..9ca6f8df5d 100644 --- a/tensorflow/contrib/layers/BUILD +++ b/tensorflow/contrib/layers/BUILD @@ -78,6 +78,11 @@ tf_custom_op_py_library( ":sparse_feature_cross_op_op_lib", ], srcs_version = "PY2AND3", + visibility = [ + "//learning/brain:__subpackages__", + "//tensorflow:__subpackages__", + "//video/youtube/personalization:__subpackages__", + ], deps = [ ":sparse_feature_cross_op", "//tensorflow/contrib/framework:framework_py", @@ -253,7 +258,7 @@ py_test( "//tensorflow/python:training", "//tensorflow/python:variable_scope", "//tensorflow/python:variables", - "//tensorflow/python/feature_column", + "//tensorflow/python/feature_column:feature_column_py", "//third_party/py/numpy", ], ) @@ -277,7 +282,7 @@ py_test( "//tensorflow/python:sparse_tensor", "//tensorflow/python:variable_scope", "//tensorflow/python:variables", - "//tensorflow/python/feature_column", + "//tensorflow/python/feature_column:feature_column_py", "//third_party/py/numpy", ], ) diff --git a/tensorflow/contrib/layers/python/layers/embedding_ops_test.py b/tensorflow/contrib/layers/python/layers/embedding_ops_test.py index 124515e5a6..295c721fce 100644 --- a/tensorflow/contrib/layers/python/layers/embedding_ops_test.py +++ b/tensorflow/contrib/layers/python/layers/embedding_ops_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import itertools import math +import sys import numpy as np @@ -36,6 +37,7 @@ from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import init_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import partitioned_variables +from tensorflow.python.ops import variable_scope from tensorflow.python.platform import test from tensorflow.python.util import compat @@ -48,11 +50,13 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): assert num_shards > 0 assert num_shards <= vocab_size - embedding_weights = partitioned_variables.create_partitioned_variables( + initializer = init_ops.truncated_normal_initializer( + mean=0.0, stddev=1.0 / math.sqrt(vocab_size), dtype=dtypes.float32) + embedding_weights = list(variable_scope.get_variable( + "embedding_weights", shape=[vocab_size, embed_dim], - slicing=[num_shards, 1], - initializer=init_ops.truncated_normal_initializer( - mean=0.0, stddev=1.0 / math.sqrt(vocab_size), dtype=dtypes.float32)) + partitioner=partitioned_variables.fixed_size_partitioner(num_shards), + initializer=initializer)) for w in embedding_weights: w.initializer.run() embedding_weights = [w.eval() for w in embedding_weights] @@ -256,6 +260,13 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): embedding_weights, sparse_ids, sparse_weights) +# pylint: disable=invalid-name +def local_variable_scope(): + """Create a variable scope named like the caller function.""" + return variable_scope.variable_scope(sys._getframe(1).f_code.co_name) +# pylint: enable=invalid-name + + class ScatteredEmbeddingLookupTest(test.TestCase): def setUp(self): @@ -266,17 +277,18 @@ class ScatteredEmbeddingLookupTest(test.TestCase): assert num_shards > 0 assert num_shards <= size - embedding_weights = partitioned_variables.create_partitioned_variables( + embedding_weights = list(variable_scope.get_variable( + "embedding_weights", shape=[size], - slicing=[num_shards], + partitioner=partitioned_variables.fixed_size_partitioner(num_shards), initializer=init_ops.truncated_normal_initializer( - mean=0.0, stddev=1.0, dtype=dtypes.float32)) + mean=0.0, stddev=1.0, dtype=dtypes.float32))) for w in embedding_weights: w.initializer.run() return embedding_weights def test_scattered_embedding_consistency(self): - with self.cached_session(): + with self.cached_session(), local_variable_scope(): embedding_weights = self._random_weights() values = constant_op.constant(["foo", "foo"]) @@ -288,7 +300,7 @@ class ScatteredEmbeddingLookupTest(test.TestCase): embedding_lookup_result[1]) def test_scattered_embedding_multiple_partition(self): - with self.cached_session(): + with self.cached_session(), local_variable_scope(): embedding_weights = self._random_weights(num_shards=7) values = constant_op.constant([4, 4, 5]) @@ -304,7 +316,7 @@ class ScatteredEmbeddingLookupTest(test.TestCase): self.assertGreater(embedding_diff, 0) def test_scattered_embedding_coverage(self): - with self.cached_session(): + with self.cached_session(), local_variable_scope(): size = 8 embedding_weights = self._random_weights(size=size, num_shards=3) values = constant_op.constant(["foo"]) @@ -316,7 +328,7 @@ class ScatteredEmbeddingLookupTest(test.TestCase): self.assertEqual(len(np.unique(embedding_lookup_result[0])), size) def test_scattered_embedding_multi_dimension(self): - with self.cached_session(): + with self.cached_session(), local_variable_scope(): embedding_weights = self._random_weights() values = constant_op.constant([["foo", "bar", "bar"], ["bar", "bar", "foo"]]) @@ -329,7 +341,7 @@ class ScatteredEmbeddingLookupTest(test.TestCase): embedding_lookup_result[1][2]) def test_scattered_embedding_lookup_sparse(self): - with self.cached_session(): + with self.cached_session(), local_variable_scope(): embedding_weights = self._random_weights(num_shards=3) sparse_tensor = sparse_tensor_lib.SparseTensor( values=["foo", "bar", "foo", "bar"], @@ -358,7 +370,7 @@ class ScatteredEmbeddingLookupTest(test.TestCase): embeds = np.random.randn(n_embed, d_embed) idx = np.random.randint(0, n_embed, idx_shape) - with self.cached_session(): + with self.cached_session(), local_variable_scope(): embedded_np = embeds[idx] embedded_tf = embedding_ops.embedding_lookup_unique(embeds, idx).eval() @@ -370,7 +382,7 @@ class ScatteredEmbeddingLookupTest(test.TestCase): idx = np.random.randint(0, 5, 10) idx2d = np.random.randint(0, 5, (10, 2)) - with self.cached_session(): + with self.cached_session(), local_variable_scope(): embedded_np = embeds[idx] embedded_np2d = embeds[idx2d] embedded_tf = embedding_ops.embedding_lookup_unique(embeds, idx).eval() @@ -398,17 +410,18 @@ class SampledScatteredEmbeddingLookupTest(test.TestCase): assert num_shards > 0 assert num_shards <= size - embedding_weights = partitioned_variables.create_partitioned_variables( + embedding_weights = list(variable_scope.get_variable( + "embedding_weights", shape=[size], - slicing=[num_shards], + partitioner=partitioned_variables.fixed_size_partitioner(num_shards), initializer=init_ops.truncated_normal_initializer( - mean=0.0, stddev=1.0, dtype=dtypes.float32)) + mean=0.0, stddev=1.0, dtype=dtypes.float32))) for w in embedding_weights: w.initializer.run() return embedding_weights def test_hashed_embedding_consistency(self): - with self.cached_session(): + with self.cached_session(), local_variable_scope(): embedding_weights = self._random_weights() values = constant_op.constant(["foo", "foo"]) # The first three sampled_candidates are equal, so the first three @@ -429,7 +442,7 @@ class SampledScatteredEmbeddingLookupTest(test.TestCase): embedding_lookup_result[1][3]) def test_hashed_embedding_multi_dimension(self): - with self.cached_session(): + with self.cached_session(), local_variable_scope(): embedding_weights = self._random_weights() values = constant_op.constant([["foo", "bar", "bar"], ["bar", "bar", "foo"]]) @@ -691,7 +704,6 @@ class EmbeddingLookupSparseWithDistributedAggregationTest(test.TestCase): index += num_val return grouped_vals - @test_util.enable_c_shapes def testEmbeddingLookupSparse(self): vocab_size = 13 batch_size = 10 diff --git a/tensorflow/contrib/layers/python/layers/encoders.py b/tensorflow/contrib/layers/python/layers/encoders.py index f42112206d..3671633c8d 100644 --- a/tensorflow/contrib/layers/python/layers/encoders.py +++ b/tensorflow/contrib/layers/python/layers/encoders.py @@ -84,8 +84,7 @@ def bow_encoder(ids, if isinstance(ids, sparse_tensor.SparseTensor): raise TypeError('ids are expected to be dense Tensor, got: %s', ids) return math_ops.reduce_mean( - embedding_ops.embedding_lookup(embeddings, ids), - reduction_indices=1) + embedding_ops.embedding_lookup(embeddings, ids), axis=1) def embed_sequence(ids, diff --git a/tensorflow/contrib/layers/python/layers/feature_column.py b/tensorflow/contrib/layers/python/layers/feature_column.py index 222404b19d..00d819ed0e 100644 --- a/tensorflow/contrib/layers/python/layers/feature_column.py +++ b/tensorflow/contrib/layers/python/layers/feature_column.py @@ -1015,8 +1015,7 @@ class _OneHotColumn( dense_id_tensor, depth=self.length, on_value=1.0, off_value=0.0) # Reduce to get a multi-hot per example. - return math_ops.reduce_sum( - one_hot_id_tensor, reduction_indices=[output_rank - 1]) + return math_ops.reduce_sum(one_hot_id_tensor, axis=[output_rank - 1]) @property def _variable_shape(self): diff --git a/tensorflow/contrib/layers/python/layers/feature_column_ops_test.py b/tensorflow/contrib/layers/python/layers/feature_column_ops_test.py index 6fb4b9ff35..7e6eafaa0d 100644 --- a/tensorflow/contrib/layers/python/layers/feature_column_ops_test.py +++ b/tensorflow/contrib/layers/python/layers/feature_column_ops_test.py @@ -27,7 +27,7 @@ from tensorflow.contrib.layers.python.layers import feature_column from tensorflow.contrib.layers.python.layers import feature_column_ops from tensorflow.core.example import example_pb2 from tensorflow.core.example import feature_pb2 -from tensorflow.python.feature_column import feature_column as fc_core +from tensorflow.python.feature_column import feature_column_lib as fc_core from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops diff --git a/tensorflow/contrib/layers/python/layers/feature_column_test.py b/tensorflow/contrib/layers/python/layers/feature_column_test.py index d90d6ecf7f..cab8da808b 100644 --- a/tensorflow/contrib/layers/python/layers/feature_column_test.py +++ b/tensorflow/contrib/layers/python/layers/feature_column_test.py @@ -27,7 +27,7 @@ import numpy as np from tensorflow.contrib.layers.python.layers import feature_column as fc from tensorflow.contrib.layers.python.layers import feature_column_ops -from tensorflow.python.feature_column import feature_column as fc_core +from tensorflow.python.feature_column import feature_column_lib as fc_core from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor as sparse_tensor_lib diff --git a/tensorflow/contrib/layers/python/layers/layers.py b/tensorflow/contrib/layers/python/layers/layers.py index ac9561c769..403b522ce4 100644 --- a/tensorflow/contrib/layers/python/layers/layers.py +++ b/tensorflow/contrib/layers/python/layers/layers.py @@ -35,6 +35,7 @@ from tensorflow.python.framework import function from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape +from tensorflow.python.keras.engine import input_spec from tensorflow.python.layers import base from tensorflow.python.layers import convolutional as convolutional_layers from tensorflow.python.layers import core as core_layers @@ -1958,7 +1959,7 @@ class GDN(base.Layer): self._reparam_offset = reparam_offset self.data_format = data_format self._channel_axis() # trigger ValueError early - self.input_spec = base.InputSpec(min_ndim=3, max_ndim=5) + self.input_spec = input_spec.InputSpec(min_ndim=3, max_ndim=5) def _channel_axis(self): try: @@ -2015,7 +2016,7 @@ class GDN(base.Layer): raise ValueError('The channel dimension of the inputs to `GDN` ' 'must be defined.') self._input_rank = input_shape.ndims - self.input_spec = base.InputSpec( + self.input_spec = input_spec.InputSpec( ndim=input_shape.ndims, axes={ channel_axis: num_channels }) diff --git a/tensorflow/contrib/layers/python/layers/layers_test.py b/tensorflow/contrib/layers/python/layers/layers_test.py index 8ead6336a0..0a4d2c6d4c 100644 --- a/tensorflow/contrib/layers/python/layers/layers_test.py +++ b/tensorflow/contrib/layers/python/layers/layers_test.py @@ -3811,7 +3811,7 @@ class UnitNormTests(test.TestCase): image = random_ops.random_uniform((height, width, 3)) output = _layers.unit_norm(image, dim=dim, epsilon=1e-6) norms = math_ops.sqrt( - math_ops.reduce_sum(math_ops.square(output), reduction_indices=dim)) + math_ops.reduce_sum(math_ops.square(output), axis=dim)) shape = [height, width, 3] del shape[dim] @@ -3847,7 +3847,7 @@ class UnitNormTests(test.TestCase): image = array_ops.placeholder(dtypes.float32, (None, None, 3)) output = _layers.unit_norm(image, dim=dim, epsilon=1e-6) norms = math_ops.sqrt( - math_ops.reduce_sum(math_ops.square(output), reduction_indices=dim)) + math_ops.reduce_sum(math_ops.square(output), axis=dim)) with self.cached_session(): actual = norms.eval({image: placeholder_value}) diff --git a/tensorflow/contrib/layers/python/layers/regularizers_test.py b/tensorflow/contrib/layers/python/layers/regularizers_test.py index 51faba30c7..5cb00b7684 100644 --- a/tensorflow/contrib/layers/python/layers/regularizers_test.py +++ b/tensorflow/contrib/layers/python/layers/regularizers_test.py @@ -141,7 +141,7 @@ class RegularizerTest(test.TestCase): dummy_regularizer = lambda x: math_ops.reduce_sum(2 * x) array_weights_list = [[1.5], [2, 3, 4.2], [10, 42, 666.6]] tensor_weights_list = [constant_op.constant(x) for x in array_weights_list] - expected = sum([2 * x for l in array_weights_list for x in l]) + expected = sum(2 * x for l in array_weights_list for x in l) with self.cached_session(): result = regularizers.apply_regularization(dummy_regularizer, tensor_weights_list) diff --git a/tensorflow/contrib/learn/BUILD b/tensorflow/contrib/learn/BUILD index 61185f65a9..14065fcee5 100644 --- a/tensorflow/contrib/learn/BUILD +++ b/tensorflow/contrib/learn/BUILD @@ -24,6 +24,11 @@ py_library( exclude = ["python/learn/**/*_test.py"], ), srcs_version = "PY2AND3", + visibility = [ + "//learning/brain:__subpackages__", + "//tensorflow:__subpackages__", + "//video/youtube/personalization:__subpackages__", + ], # This library should not depend on sklearn, even though some of the code # refers to it. (The code handles the presence of sklearn conditionally.) deps = [ @@ -269,6 +274,7 @@ py_test( name = "estimator_test", size = "medium", srcs = ["python/learn/estimators/estimator_test.py"], + shard_count = 2, srcs_version = "PY2AND3", tags = [ "manual", diff --git a/tensorflow/contrib/learn/python/learn/estimators/dnn.py b/tensorflow/contrib/learn/python/learn/estimators/dnn.py index eabebb7e88..10fbd60ba2 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/dnn.py +++ b/tensorflow/contrib/learn/python/learn/estimators/dnn.py @@ -28,7 +28,6 @@ import six from tensorflow.contrib import layers from tensorflow.contrib.framework import deprecated from tensorflow.contrib.framework import deprecated_arg_values -from tensorflow.python.training import training_util from tensorflow.contrib.layers.python.layers import feature_column from tensorflow.contrib.layers.python.layers import optimizers from tensorflow.contrib.learn.python.learn import metric_spec @@ -38,11 +37,12 @@ from tensorflow.contrib.learn.python.learn.estimators import head as head_lib from tensorflow.contrib.learn.python.learn.estimators import model_fn from tensorflow.contrib.learn.python.learn.estimators import prediction_key from tensorflow.contrib.learn.python.learn.utils import export -from tensorflow.python.feature_column import feature_column as fc_core +from tensorflow.python.feature_column import feature_column_lib as fc_core from tensorflow.python.ops import nn from tensorflow.python.ops import partitioned_variables from tensorflow.python.ops import variable_scope from tensorflow.python.summary import summary +from tensorflow.python.training import training_util # The default learning rate of 0.05 is a historical artifact of the initial # implementation, but seems a reasonable choice. @@ -150,10 +150,10 @@ def _dnn_model_fn(features, labels, mode, params, config=None): "input_from_feature_columns", values=tuple(six.itervalues(features)), partitioner=input_layer_partitioner) as input_layer_scope: - if all([ + if all( isinstance(fc, feature_column._FeatureColumn) # pylint: disable=protected-access for fc in feature_columns - ]): + ): net = layers.input_from_feature_columns( columns_to_tensors=features, feature_columns=feature_columns, diff --git a/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined.py b/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined.py index 3d85533d92..2ade6b7b6c 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined.py +++ b/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined.py @@ -38,7 +38,7 @@ from tensorflow.contrib.learn.python.learn.estimators import head as head_lib from tensorflow.contrib.learn.python.learn.estimators import model_fn from tensorflow.contrib.learn.python.learn.estimators import prediction_key from tensorflow.contrib.learn.python.learn.utils import export -from tensorflow.python.feature_column import feature_column as fc_core +from tensorflow.python.feature_column import feature_column_lib as fc_core from tensorflow.python.framework import ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import nn @@ -236,10 +236,10 @@ def _dnn_linear_combined_model_fn(features, labels, mode, params, config=None): "input_from_feature_columns", values=tuple(six.itervalues(features)), partitioner=input_layer_partitioner) as dnn_input_scope: - if all([ + if all( isinstance(fc, feature_column_lib._FeatureColumn) # pylint: disable=protected-access for fc in dnn_feature_columns - ]): + ): net = layers.input_from_feature_columns( columns_to_tensors=features, feature_columns=dnn_feature_columns, @@ -292,8 +292,8 @@ def _dnn_linear_combined_model_fn(features, labels, mode, params, config=None): linear_parent_scope, values=tuple(six.itervalues(features)), partitioner=linear_partitioner) as scope: - if all([isinstance(fc, feature_column_lib._FeatureColumn) # pylint: disable=protected-access - for fc in linear_feature_columns]): + if all(isinstance(fc, feature_column_lib._FeatureColumn) # pylint: disable=protected-access + for fc in linear_feature_columns): if joint_linear_weights: linear_logits, _, _ = layers.joint_weighted_sum_from_feature_columns( columns_to_tensors=features, diff --git a/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined_test.py b/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined_test.py index 4e65c180d8..d46a873bfa 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined_test.py +++ b/tensorflow/contrib/learn/python/learn/estimators/dnn_linear_combined_test.py @@ -36,7 +36,7 @@ from tensorflow.contrib.learn.python.learn.estimators import run_config from tensorflow.contrib.learn.python.learn.estimators import test_data from tensorflow.contrib.learn.python.learn.metric_spec import MetricSpec from tensorflow.contrib.metrics.python.ops import metric_ops -from tensorflow.python.feature_column import feature_column as fc_core +from tensorflow.python.feature_column import feature_column_lib as fc_core from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops diff --git a/tensorflow/contrib/learn/python/learn/estimators/dnn_test.py b/tensorflow/contrib/learn/python/learn/estimators/dnn_test.py index 2bd57597c2..ee25cebd48 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/dnn_test.py +++ b/tensorflow/contrib/learn/python/learn/estimators/dnn_test.py @@ -38,7 +38,7 @@ from tensorflow.contrib.learn.python.learn.estimators import run_config from tensorflow.contrib.learn.python.learn.estimators import test_data from tensorflow.contrib.learn.python.learn.metric_spec import MetricSpec from tensorflow.contrib.metrics.python.ops import metric_ops -from tensorflow.python.feature_column import feature_column as fc_core +from tensorflow.python.feature_column import feature_column_lib as fc_core from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor diff --git a/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator_test.py b/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator_test.py index 1d8a59281a..28c4964527 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator_test.py +++ b/tensorflow/contrib/learn/python/learn/estimators/dynamic_rnn_estimator_test.py @@ -668,7 +668,7 @@ class DynamicRNNEstimatorLearningTest(test.TestCase): sequences = centers + noise inputs = array_ops.expand_dims(sequences, 2) - labels = math_ops.reduce_mean(sequences, reduction_indices=[1]) + labels = math_ops.reduce_mean(sequences, axis=[1]) return {'inputs': inputs}, labels return input_fn @@ -722,8 +722,8 @@ class DynamicRNNEstimatorLearningTest(test.TestCase): inputs = array_ops.expand_dims(math_ops.to_float(random_sequence), 2) labels = math_ops.to_int32( array_ops.squeeze( - math_ops.reduce_sum( - inputs, reduction_indices=[1]) > (sequence_length / 2.0))) + math_ops.reduce_sum(inputs, axis=[1]) > ( + sequence_length / 2.0))) return {'inputs': inputs}, labels return input_fn diff --git a/tensorflow/contrib/learn/python/learn/estimators/estimator.py b/tensorflow/contrib/learn/python/learn/estimators/estimator.py index 8bc869db89..9132b2209b 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/estimator.py +++ b/tensorflow/contrib/learn/python/learn/estimators/estimator.py @@ -1066,11 +1066,11 @@ class BaseEstimator(sklearn.BaseEstimator, evaluable.Evaluable, chief_hooks = [] if (self._config.save_checkpoints_secs or self._config.save_checkpoints_steps): - saver_hook_exists = any([ + saver_hook_exists = any( isinstance(h, basic_session_run_hooks.CheckpointSaverHook) for h in (all_hooks + model_fn_ops.training_hooks + chief_hooks + model_fn_ops.training_chief_hooks) - ]) + ) if not saver_hook_exists: chief_hooks = [ basic_session_run_hooks.CheckpointSaverHook( @@ -1493,7 +1493,7 @@ class Estimator(BaseEstimator): # pylint: disable=protected-access class SKCompat(sklearn.BaseEstimator): """Scikit learn wrapper for TensorFlow Learn Estimator. - + THIS CLASS IS DEPRECATED. See [contrib/learn/README.md](https://www.tensorflow.org/code/tensorflow/contrib/learn/README.md) for general migration instructions. diff --git a/tensorflow/contrib/learn/python/learn/estimators/linear.py b/tensorflow/contrib/learn/python/learn/estimators/linear.py index e100bc7a1e..9ee8d8004b 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/linear.py +++ b/tensorflow/contrib/learn/python/learn/estimators/linear.py @@ -37,7 +37,7 @@ from tensorflow.contrib.learn.python.learn.estimators import head as head_lib from tensorflow.contrib.learn.python.learn.estimators import prediction_key from tensorflow.contrib.learn.python.learn.utils import export from tensorflow.contrib.linear_optimizer.python import sdca_optimizer -from tensorflow.python.feature_column import feature_column as fc_core +from tensorflow.python.feature_column import feature_column_lib as fc_core from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor @@ -155,8 +155,8 @@ def _linear_model_fn(features, labels, mode, params, config=None): parent_scope, values=tuple(six.itervalues(features)), partitioner=partitioner) as scope: - if all([isinstance(fc, feature_column._FeatureColumn) # pylint: disable=protected-access - for fc in feature_columns]): + if all(isinstance(fc, feature_column._FeatureColumn) # pylint: disable=protected-access + for fc in feature_columns): if joint_weights: layer_fn = layers.joint_weighted_sum_from_feature_columns else: diff --git a/tensorflow/contrib/learn/python/learn/estimators/linear_test.py b/tensorflow/contrib/learn/python/learn/estimators/linear_test.py index 597ca4e86d..dfc76bfde6 100644 --- a/tensorflow/contrib/learn/python/learn/estimators/linear_test.py +++ b/tensorflow/contrib/learn/python/learn/estimators/linear_test.py @@ -37,7 +37,7 @@ from tensorflow.contrib.learn.python.learn.estimators import test_data from tensorflow.contrib.learn.python.learn.metric_spec import MetricSpec from tensorflow.contrib.linear_optimizer.python import sdca_optimizer as sdca_optimizer_lib from tensorflow.contrib.metrics.python.ops import metric_ops -from tensorflow.python.feature_column import feature_column as fc_core +from tensorflow.python.feature_column import feature_column_lib as fc_core from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor @@ -1745,7 +1745,7 @@ class LinearRegressorTest(test.TestCase): 'place_holder': constant_op.constant([[0.0]] * num_examples), }, constant_op.constant( - [[1 if i % 4 is 0 else 0] for i in range(num_examples)]) + [[1 if i % 4 == 0 else 0] for i in range(num_examples)]) place_holder = feature_column_lib.real_valued_column('place_holder') sdca_optimizer = sdca_optimizer_lib.SDCAOptimizer( diff --git a/tensorflow/contrib/learn/python/learn/learn_io/numpy_io.py b/tensorflow/contrib/learn/python/learn/learn_io/numpy_io.py index 29552d24f1..59a67636ae 100644 --- a/tensorflow/contrib/learn/python/learn/learn_io/numpy_io.py +++ b/tensorflow/contrib/learn/python/learn/learn_io/numpy_io.py @@ -27,7 +27,7 @@ from tensorflow.python.estimator.inputs.numpy_io import numpy_input_fn as core_n from tensorflow.python.util.deprecation import deprecated -@deprecated(None, 'Use tf.estimator.inputs.numpy_input_fn.') +@deprecated(None, 'Use tf.compat.v1.estimator.inputs.numpy_input_fn.') def numpy_input_fn(x, y=None, batch_size=128, diff --git a/tensorflow/contrib/learn/python/learn/learn_io/pandas_io.py b/tensorflow/contrib/learn/python/learn/learn_io/pandas_io.py index b4ef055f5a..e9df7258a3 100644 --- a/tensorflow/contrib/learn/python/learn/learn_io/pandas_io.py +++ b/tensorflow/contrib/learn/python/learn/learn_io/pandas_io.py @@ -53,7 +53,7 @@ PANDAS_DTYPES = { } -@deprecated(None, 'Please use tf.estimator.inputs.pandas_input_fn') +@deprecated(None, 'Please use tf.compat.v1.estimator.inputs.pandas_input_fn') def pandas_input_fn(x, y=None, batch_size=128, diff --git a/tensorflow/contrib/linear_optimizer/python/sdca_estimator_test.py b/tensorflow/contrib/linear_optimizer/python/sdca_estimator_test.py index 6476671882..7a5354222f 100644 --- a/tensorflow/contrib/linear_optimizer/python/sdca_estimator_test.py +++ b/tensorflow/contrib/linear_optimizer/python/sdca_estimator_test.py @@ -524,7 +524,7 @@ class SDCALinearRegressorTest(test.TestCase): # LinearClassifier requires at least one column. 'place_holder': constant_op.constant([[0.0]] * num_examples), - }, constant_op.constant([[1 if i % 4 is 0 else 0] + }, constant_op.constant([[1 if i % 4 == 0 else 0] for i in range(num_examples)]) with self._single_threaded_test_session(): diff --git a/tensorflow/contrib/lookup/lookup_ops_test.py b/tensorflow/contrib/lookup/lookup_ops_test.py index 5e99ef4605..9b2c2dd87c 100644 --- a/tensorflow/contrib/lookup/lookup_ops_test.py +++ b/tensorflow/contrib/lookup/lookup_ops_test.py @@ -25,6 +25,7 @@ import six from tensorflow.contrib import lookup from tensorflow.python.client import session from tensorflow.python.data.experimental.ops import counter +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes @@ -2737,7 +2738,7 @@ class MutableHashTableBenchmark(test.Benchmark): def benchmark_many_repeated_scalar_insert_scalar(self): table = self._create_table() - c = counter.Counter().make_one_shot_iterator().get_next() + c = dataset_ops.make_one_shot_iterator(counter.Counter()).get_next() value = variables.Variable(1.0) insert = table.insert(c, value) size = table.size() @@ -2758,7 +2759,7 @@ class MutableHashTableBenchmark(test.Benchmark): def benchmark_many_repeated_batch_32_insert_scalar(self): table = self._create_table() - c = counter.Counter().make_one_shot_iterator().get_next() + c = dataset_ops.make_one_shot_iterator(counter.Counter()).get_next() value = variables.Variable([1.0] * 32) insert = table.insert(32 * c + list(range(32)), value) size = table.size() diff --git a/tensorflow/contrib/losses/python/losses/loss_ops.py b/tensorflow/contrib/losses/python/losses/loss_ops.py index 619294b518..709a042bbc 100644 --- a/tensorflow/contrib/losses/python/losses/loss_ops.py +++ b/tensorflow/contrib/losses/python/losses/loss_ops.py @@ -22,7 +22,6 @@ from __future__ import division from __future__ import print_function from tensorflow.contrib.framework.python.ops import add_arg_scope -from tensorflow.python.compat import compat from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops @@ -60,41 +59,12 @@ def _scale_losses(losses, weights): """ # First, compute the sum of the losses over all elements: start_index = max(0, weights.get_shape().ndims) - reduction_indices = list(range(start_index, losses.get_shape().ndims)) - reduced_losses = math_ops.reduce_sum( - losses, reduction_indices=reduction_indices) + axis = list(range(start_index, losses.get_shape().ndims)) + reduced_losses = math_ops.reduce_sum(losses, axis=axis) reduced_losses = math_ops.multiply(reduced_losses, weights) return math_ops.reduce_sum(reduced_losses) -def _safe_div(numerator, denominator, name="value"): - """Computes a safe divide which returns 0 if the denominator is zero. - - Note that the function contains an additional conditional check that is - necessary for avoiding situations where the loss is zero causing NaNs to - creep into the gradient computation. - - Args: - numerator: An arbitrary `Tensor`. - denominator: A `Tensor` whose shape matches `numerator` and whose values are - assumed to be non-negative. - name: An optional name for the returned op. - - Returns: - The element-wise value of the numerator divided by the denominator. - """ - if compat.forward_compatible(2018, 11, 1): - return math_ops.div_no_nan(numerator, denominator, name=name) - return array_ops.where( - math_ops.greater(denominator, 0), - math_ops.div(numerator, - array_ops.where( - math_ops.equal(denominator, 0), - array_ops.ones_like(denominator), denominator)), - array_ops.zeros_like(numerator), - name=name) - - def _safe_mean(losses, num_present): """Computes a safe mean of the losses. @@ -107,7 +77,7 @@ def _safe_mean(losses, num_present): then zero is returned. """ total_loss = math_ops.reduce_sum(losses) - return _safe_div(total_loss, num_present, name="value") + return math_ops.div_no_nan(total_loss, num_present, name="value") @deprecated("2016-12-30", "Use tf.losses.compute_weighted_loss instead.") @@ -187,10 +157,9 @@ def _num_present(losses, weights, per_batch=False): # First, count the number of nonzero weights: if weights.get_shape().ndims >= 1: - reduction_indices = list(range(1, weights.get_shape().ndims)) + axis = list(range(1, weights.get_shape().ndims)) num_nonzero_per_batch = math_ops.reduce_sum( - math_ops.to_float(math_ops.not_equal(weights, 0)), - reduction_indices=reduction_indices) + math_ops.to_float(math_ops.not_equal(weights, 0)), axis=axis) # Next, determine the number of elements that weights would broadcast to: broadcast_dims = array_ops.slice( @@ -606,20 +575,20 @@ def mean_pairwise_squared_error(predictions, if weights.get_shape().ndims is None: raise ValueError("weights.get_shape().ndims cannot be None") - reduction_indices = list(range(1, diffs.get_shape().ndims)) + axis = list(range(1, diffs.get_shape().ndims)) sum_squares_diff_per_batch = math_ops.reduce_sum( - math_ops.square(diffs), reduction_indices=reduction_indices) + math_ops.square(diffs), axis=axis) num_present_per_batch = _num_present(diffs, weights, per_batch=True) - term1 = 2.0 * _safe_div(sum_squares_diff_per_batch, - num_present_per_batch, - name="value") + term1 = 2.0 * math_ops.div_no_nan( + sum_squares_diff_per_batch, num_present_per_batch, name="value") - sum_diff = math_ops.reduce_sum(diffs, reduction_indices=reduction_indices) - term2 = 2.0 * _safe_div(math_ops.square(sum_diff), - math_ops.square(num_present_per_batch), - name="value") + sum_diff = math_ops.reduce_sum(diffs, axis=axis) + term2 = 2.0 * math_ops.div_no_nan( + math_ops.square(sum_diff), + math_ops.square(num_present_per_batch), + name="value") loss = _scale_losses(term1 - term2, weights) @@ -674,7 +643,7 @@ def cosine_distance(predictions, radial_diffs = math_ops.multiply(predictions, labels) losses = 1 - math_ops.reduce_sum( - radial_diffs, reduction_indices=[ + radial_diffs, axis=[ axis, ]) return compute_weighted_loss(losses, weights, scope=scope) diff --git a/tensorflow/contrib/makefile/download_dependencies.sh b/tensorflow/contrib/makefile/download_dependencies.sh index 0a07588f07..b396c52767 100755 --- a/tensorflow/contrib/makefile/download_dependencies.sh +++ b/tensorflow/contrib/makefile/download_dependencies.sh @@ -34,7 +34,7 @@ NSYNC_URL="$(grep -o 'https://mirror.bazel.build/github.com/google/nsync/.*tar\. # 1.10 branch does not work. `make distclean` fails and blocks the build # process. For now we're hardcoding to the version which is used by # TensorFlow 1.9. -PROTOBUF_URL="https://mirror.bazel.build/github.com/google/protobuf/archive/396336eb961b75f03b25824fe86cf6490fb75e3a.tar.gz" +PROTOBUF_URL="https://mirror.bazel.build/github.com/google/protobuf/archive/v3.6.0.tar.gz" # TODO (yongtang): Replace the following with 'https://mirror.bazel.build/github.com/google/re2/.*tar\.gz' once # the archive has been propagated in mirror.bazel.build. RE2_URL="$(grep -o 'https://github.com/google/re2/.*tar\.gz' "${BZL_FILE_PATH}" | head -n1)" diff --git a/tensorflow/contrib/makefile/tf_op_files.txt b/tensorflow/contrib/makefile/tf_op_files.txt index e779eff689..655c7eefcb 100644 --- a/tensorflow/contrib/makefile/tf_op_files.txt +++ b/tensorflow/contrib/makefile/tf_op_files.txt @@ -157,6 +157,7 @@ tensorflow/core/kernels/mirror_pad_op_cpu_impl_2.cc tensorflow/core/kernels/mirror_pad_op_cpu_impl_3.cc tensorflow/core/kernels/mirror_pad_op_cpu_impl_4.cc tensorflow/core/kernels/mirror_pad_op_cpu_impl_5.cc +tensorflow/core/kernels/multinomial_op.cc tensorflow/core/kernels/no_op.cc tensorflow/core/kernels/non_max_suppression_op.cc tensorflow/core/kernels/one_hot_op.cc @@ -252,6 +253,7 @@ tensorflow/core/kernels/split_op.cc tensorflow/core/kernels/split_v_op.cc tensorflow/core/kernels/stack.cc tensorflow/core/kernels/stack_ops.cc +tensorflow/core/kernels/stateless_random_ops.cc tensorflow/core/kernels/strided_slice_op.cc tensorflow/core/kernels/strided_slice_op_inst_0.cc tensorflow/core/kernels/strided_slice_op_inst_1.cc diff --git a/tensorflow/contrib/metrics/python/metrics/classification.py b/tensorflow/contrib/metrics/python/metrics/classification.py index ac12360865..062deb74b1 100644 --- a/tensorflow/contrib/metrics/python/metrics/classification.py +++ b/tensorflow/contrib/metrics/python/metrics/classification.py @@ -175,7 +175,7 @@ def f1_score(labels, predictions, weights=None, num_thresholds=200, return best_f1 best_f1 = distribution_strategy_context.get_replica_context().merge_call( - f1_across_replicas, values) + f1_across_replicas, args=(values,)) update_op = compute_best_f1_score(tp=update_ops['tp'], fp=update_ops['fp'], fn=update_ops['fn'], name='update') diff --git a/tensorflow/contrib/metrics/python/metrics/classification_test.py b/tensorflow/contrib/metrics/python/metrics/classification_test.py index d6a670f97b..e789d2cb9d 100644 --- a/tensorflow/contrib/metrics/python/metrics/classification_test.py +++ b/tensorflow/contrib/metrics/python/metrics/classification_test.py @@ -291,12 +291,11 @@ class F1ScoreTest(test.TestCase): labels = labels.astype(np.float32) predictions = predictions.astype(np.float32) - tf_predictions, tf_labels = (dataset_ops.Dataset - .from_tensor_slices((predictions, labels)) - .repeat() - .batch(batch_size) - .make_one_shot_iterator() - .get_next()) + tf_predictions, tf_labels = dataset_ops.make_one_shot_iterator( + dataset_ops.Dataset + .from_tensor_slices((predictions, labels)) + .repeat() + .batch(batch_size)).get_next() f1, f1_op = classification.f1_score(tf_labels, tf_predictions, num_thresholds=3) diff --git a/tensorflow/contrib/metrics/python/ops/metric_ops.py b/tensorflow/contrib/metrics/python/ops/metric_ops.py index d6932f6e4b..7b432f8bd2 100644 --- a/tensorflow/contrib/metrics/python/ops/metric_ops.py +++ b/tensorflow/contrib/metrics/python/ops/metric_ops.py @@ -24,7 +24,6 @@ from __future__ import print_function import collections as collections_lib -from tensorflow.python.compat import compat from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops @@ -46,32 +45,6 @@ from tensorflow.python.util.deprecation import deprecated _EPSILON = 1e-7 -def _safe_div(numerator, denominator): - """Computes a safe divide which returns 0 if the denominator is zero. - - Note that the function contains an additional conditional check that is - necessary for avoiding situations where the loss is zero causing NaNs to - creep into the gradient computation. - - Args: - numerator: An arbitrary `Tensor`. - denominator: A `Tensor` whose shape matches `numerator` and whose values are - assumed to be non-negative. - - Returns: - The element-wise value of the numerator divided by the denominator. - """ - if compat.forward_compatible(2018, 11, 1): - return math_ops.div_no_nan(numerator, denominator) - return array_ops.where( - math_ops.greater(denominator, 0), - math_ops.div(numerator, - array_ops.where( - math_ops.equal(denominator, 0), - array_ops.ones_like(denominator), denominator)), - array_ops.zeros_like(numerator)) - - @deprecated(None, 'Please switch to tf.metrics.true_positives. Note that the ' 'order of the labels and predictions arguments has been switched.') def streaming_true_positives(predictions, @@ -3247,24 +3220,20 @@ def streaming_covariance(predictions, # We update the means by Delta=Error*BatchCount/(BatchCount+PrevCount) # batch_mean_prediction is E[x_B] in the update equation - batch_mean_prediction = _safe_div( - math_ops.reduce_sum(weighted_predictions), - batch_count) - delta_mean_prediction = _safe_div( - (batch_mean_prediction - mean_prediction) * batch_count, - update_count) + batch_mean_prediction = math_ops.div_no_nan( + math_ops.reduce_sum(weighted_predictions), batch_count) + delta_mean_prediction = math_ops.div_no_nan( + (batch_mean_prediction - mean_prediction) * batch_count, update_count) update_mean_prediction = state_ops.assign_add(mean_prediction, delta_mean_prediction) # prev_mean_prediction is E[x_A] in the update equation prev_mean_prediction = update_mean_prediction - delta_mean_prediction # batch_mean_label is E[y_B] in the update equation - batch_mean_label = _safe_div( - math_ops.reduce_sum(weighted_labels), - batch_count) - delta_mean_label = _safe_div( - (batch_mean_label - mean_label) * batch_count, - update_count) + batch_mean_label = math_ops.div_no_nan( + math_ops.reduce_sum(weighted_labels), batch_count) + delta_mean_label = math_ops.div_no_nan( + (batch_mean_label - mean_label) * batch_count, update_count) update_mean_label = state_ops.assign_add(mean_label, delta_mean_label) # prev_mean_label is E[y_A] in the update equation prev_mean_label = update_mean_label - delta_mean_label @@ -3447,7 +3416,7 @@ def streaming_mean_cosine_distance(predictions, predictions.get_shape().assert_is_compatible_with(labels.get_shape()) radial_diffs = math_ops.multiply(predictions, labels) radial_diffs = math_ops.reduce_sum( - radial_diffs, reduction_indices=[ + radial_diffs, axis=[ dim, ], keepdims=True) mean_distance, update_op = streaming_mean(radial_diffs, weights, None, None, @@ -3926,9 +3895,8 @@ def cohen_kappa(labels, po_sum = math_ops.reduce_sum(po) total = math_ops.reduce_sum(pe_row) pe_sum = math_ops.reduce_sum( - _safe_div( - math_ops.to_double(pe_row * pe_col), - math_ops.to_double(total))) + math_ops.div_no_nan( + math_ops.to_double(pe_row * pe_col), math_ops.to_double(total))) po_sum, pe_sum, total = (math_ops.to_double(po_sum), math_ops.to_double(pe_sum), math_ops.to_double(total)) diff --git a/tensorflow/contrib/mixed_precision/python/loss_scale_manager_test.py b/tensorflow/contrib/mixed_precision/python/loss_scale_manager_test.py index 1b0383d24c..c922d0cd11 100644 --- a/tensorflow/contrib/mixed_precision/python/loss_scale_manager_test.py +++ b/tensorflow/contrib/mixed_precision/python/loss_scale_manager_test.py @@ -29,7 +29,7 @@ from tensorflow.python.platform import test def _GetExampleIter(inputs): dataset = dataset_ops.Dataset.from_tensor_slices(inputs) - return dataset.make_one_shot_iterator() + return dataset_ops.make_one_shot_iterator(dataset) class FixedLossScaleManagerTest(test.TestCase): diff --git a/tensorflow/contrib/mixed_precision/python/loss_scale_optimizer_test.py b/tensorflow/contrib/mixed_precision/python/loss_scale_optimizer_test.py index 9009df0eef..33f9a43e80 100644 --- a/tensorflow/contrib/mixed_precision/python/loss_scale_optimizer_test.py +++ b/tensorflow/contrib/mixed_precision/python/loss_scale_optimizer_test.py @@ -132,7 +132,7 @@ class LossScaleOptimizerTest(test.TestCase): x = variable_scope.get_variable("x", initializer=1., dtype=dtypes.float32) dataset = dataset_ops.Dataset.from_tensor_slices([np.nan, np.inf, 0.1]) - itr = dataset.make_one_shot_iterator() + itr = dataset_ops.make_one_shot_iterator(dataset) lr = 1 opt = gd.GradientDescentOptimizer(lr) @@ -182,7 +182,7 @@ class LossScaleOptimizerTest(test.TestCase): x = variable_scope.get_variable("x", initializer=1., dtype=dtypes.float32) dataset = dataset_ops.Dataset.from_tensor_slices([np.nan, np.inf, 0.1]) - itr = dataset.make_one_shot_iterator() + itr = dataset_ops.make_one_shot_iterator(dataset) lr = 1 init_loss_scale = 8 diff --git a/tensorflow/contrib/model_pruning/python/layers/core_layers.py b/tensorflow/contrib/model_pruning/python/layers/core_layers.py index f0ce6fe039..1fa5c8cb48 100644 --- a/tensorflow/contrib/model_pruning/python/layers/core_layers.py +++ b/tensorflow/contrib/model_pruning/python/layers/core_layers.py @@ -21,6 +21,7 @@ from __future__ import print_function from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.keras.engine import input_spec from tensorflow.python.layers import base from tensorflow.python.layers import utils from tensorflow.python.ops import array_ops @@ -119,7 +120,7 @@ class _MaskedConv(base.Layer): self.bias_initializer = bias_initializer self.kernel_regularizer = kernel_regularizer self.bias_regularizer = bias_regularizer - self.input_spec = base.InputSpec(ndim=self.rank + 2) + self.input_spec = input_spec.InputSpec(ndim=self.rank + 2) def build(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape) @@ -171,7 +172,7 @@ class _MaskedConv(base.Layer): dtype=self.dtype) else: self.bias = None - self.input_spec = base.InputSpec( + self.input_spec = input_spec.InputSpec( ndim=self.rank + 2, axes={channel_axis: input_dim}) self.built = True @@ -393,14 +394,14 @@ class MaskedFullyConnected(base.Layer): self.bias_initializer = bias_initializer self.kernel_regularizer = kernel_regularizer self.bias_regularizer = bias_regularizer - self.input_spec = base.InputSpec(min_ndim=2) + self.input_spec = input_spec.InputSpec(min_ndim=2) def build(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape) if tensor_shape.dimension_value(input_shape[-1]) is None: raise ValueError('The last dimension of the inputs to `Dense` ' 'should be defined. Found `None`.') - self.input_spec = base.InputSpec( + self.input_spec = input_spec.InputSpec( min_ndim=2, axes={-1: tensor_shape.dimension_value(input_shape[-1])}) self.kernel = self.add_variable( diff --git a/tensorflow/contrib/opt/python/training/lars_optimizer.py b/tensorflow/contrib/opt/python/training/lars_optimizer.py index a8dafd9a4c..205d6c3949 100644 --- a/tensorflow/contrib/opt/python/training/lars_optimizer.py +++ b/tensorflow/contrib/opt/python/training/lars_optimizer.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import linalg_ops from tensorflow.python.ops import math_ops @@ -162,3 +163,14 @@ class LARSOptimizer(optimizer.Optimizer): math_ops.cast(self._momentum_tensor, grad.dtype), use_locking=self._use_locking, use_nesterov=self._use_nesterov) + + def _prepare(self): + learning_rate = self._learning_rate + if callable(learning_rate): + learning_rate = learning_rate() + self._learning_rate_tensor = ops.convert_to_tensor(learning_rate, + name="learning_rate") + momentum = self._momentum + if callable(momentum): + momentum = momentum() + self._momentum_tensor = ops.convert_to_tensor(momentum, name="momentum") \ No newline at end of file diff --git a/tensorflow/contrib/opt/python/training/nadam_optimizer.py b/tensorflow/contrib/opt/python/training/nadam_optimizer.py index 155ff5b3f4..960826407b 100644 --- a/tensorflow/contrib/opt/python/training/nadam_optimizer.py +++ b/tensorflow/contrib/opt/python/training/nadam_optimizer.py @@ -18,6 +18,7 @@ from __future__ import division from __future__ import print_function from tensorflow.python.framework import ops +from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import state_ops @@ -83,14 +84,14 @@ class NadamOptimizer(adam.AdamOptimizer): with ops.control_dependencies([m_t]): m_t = scatter_add(m, indices, m_scaled_g_values) # m_bar = (1 - beta1) * g_t + beta1 * m_t - m_bar = m_scaled_g_values + beta1_t * m_t + m_bar = m_scaled_g_values + beta1_t * array_ops.gather(m_t, indices) # v_t = beta2 * v + (1 - beta2) * (g_t * g_t) v = self.get_slot(var, "v") v_scaled_g_values = (grad * grad) * (1 - beta2_t) v_t = state_ops.assign(v, v * beta2_t, use_locking=self._use_locking) with ops.control_dependencies([v_t]): v_t = scatter_add(v, indices, v_scaled_g_values) - v_sqrt = math_ops.sqrt(v_t) - var_update = state_ops.assign_sub( - var, lr * m_bar / (v_sqrt + epsilon_t), use_locking=self._use_locking) + v_t_slice = array_ops.gather(v_t, indices) + v_sqrt = math_ops.sqrt(v_t_slice) + var_update = scatter_add(var, indices, -lr * m_bar / (v_sqrt + epsilon_t)) return control_flow_ops.group(*[var_update, m_bar, v_t]) diff --git a/tensorflow/contrib/opt/python/training/nadam_optimizer_test.py b/tensorflow/contrib/opt/python/training/nadam_optimizer_test.py index 85e05ce71c..a4372f6487 100644 --- a/tensorflow/contrib/opt/python/training/nadam_optimizer_test.py +++ b/tensorflow/contrib/opt/python/training/nadam_optimizer_test.py @@ -52,14 +52,19 @@ def nadam_update_numpy(param, class NadamOptimizerTest(test.TestCase): def doTestSparse(self, use_resource=False): + # need to use a larger value of epsilon here so that + # np.sqrt(v_t) + epsilon doesn't get rounded to 0 when + # the dtype is half and np.sqrt(v_t) = 0, as is the case + # when the gradient is 0 + sparse_epsilon = 1e-7 for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): # Initialize variables for numpy implementation. m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 - var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) - grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) - var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) - grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + var0_np = np.array([1.0, 1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0, 0.01], dtype=dtype.as_numpy_dtype) if use_resource: var0 = resource_variable_ops.ResourceVariable(var0_np) @@ -67,21 +72,21 @@ class NadamOptimizerTest(test.TestCase): else: var0 = variables.Variable(var0_np) var1 = variables.Variable(var1_np) - grads0_np_indices = np.array([0, 1], dtype=np.int32) + grads0_np_indices = np.array([0, 2], dtype=np.int32) grads0 = ops.IndexedSlices( - constant_op.constant(grads0_np), - constant_op.constant(grads0_np_indices), constant_op.constant([2])) - grads1_np_indices = np.array([0, 1], dtype=np.int32) + constant_op.constant(grads0_np[grads0_np_indices]), + constant_op.constant(grads0_np_indices), constant_op.constant([3])) + grads1_np_indices = np.array([0, 2], dtype=np.int32) grads1 = ops.IndexedSlices( - constant_op.constant(grads1_np), - constant_op.constant(grads1_np_indices), constant_op.constant([2])) - opt = nadam_optimizer.NadamOptimizer() + constant_op.constant(grads1_np[grads1_np_indices]), + constant_op.constant(grads1_np_indices), constant_op.constant([3])) + opt = nadam_optimizer.NadamOptimizer(epsilon=sparse_epsilon) update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 1.0, 2.0], var0.eval()) + self.assertAllClose([3.0, 3.0, 4.0], var1.eval()) beta1_power, beta2_power = opt._get_beta_accumulators() @@ -91,8 +96,10 @@ class NadamOptimizerTest(test.TestCase): self.assertAllCloseAccordingToType(0.999**t, beta2_power.eval()) update.run() - var0_np, m0, v0 = nadam_update_numpy(var0_np, grads0_np, t, m0, v0) - var1_np, m1, v1 = nadam_update_numpy(var1_np, grads1_np, t, m1, v1) + var0_np, m0, v0 = nadam_update_numpy(var0_np, grads0_np, t, m0, v0, + epsilon=sparse_epsilon) + var1_np, m1, v1 = nadam_update_numpy(var1_np, grads1_np, t, m1, v1, + epsilon=sparse_epsilon) # Validate updated params self.assertAllCloseAccordingToType(var0_np, var0.eval()) diff --git a/tensorflow/contrib/optimizer_v2/BUILD b/tensorflow/contrib/optimizer_v2/BUILD index 3ba3ee29ec..6e40140630 100644 --- a/tensorflow/contrib/optimizer_v2/BUILD +++ b/tensorflow/contrib/optimizer_v2/BUILD @@ -48,7 +48,6 @@ py_library( srcs_version = "PY2AND3", deps = [ "//tensorflow/python:control_flow_ops", - "//tensorflow/python:distribute", "//tensorflow/python:framework", "//tensorflow/python:math_ops", "//tensorflow/python:resource_variable_ops", @@ -56,6 +55,8 @@ py_library( "//tensorflow/python:training", "//tensorflow/python:variable_scope", "//tensorflow/python:variables", + "//tensorflow/python/distribute:distribute_lib", + "//tensorflow/python/distribute:reduce_util", ], ) diff --git a/tensorflow/contrib/optimizer_v2/optimizer_v2.py b/tensorflow/contrib/optimizer_v2/optimizer_v2.py index 467dd86d8f..73a556f0b2 100644 --- a/tensorflow/contrib/optimizer_v2/optimizer_v2.py +++ b/tensorflow/contrib/optimizer_v2/optimizer_v2.py @@ -24,6 +24,8 @@ import abc import six +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import reduce_util as ds_reduce_util from tensorflow.python.eager import backprop from tensorflow.python.eager import context from tensorflow.python.framework import dtypes @@ -34,7 +36,6 @@ from tensorflow.python.ops import math_ops from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables -from tensorflow.python.training import distribute as distribute_lib from tensorflow.python.training import distribution_strategy_context as distribute_ctx from tensorflow.python.training import optimizer as optimizer_v1 from tensorflow.python.training import slot_creator @@ -446,7 +447,7 @@ class _OptimizerV2State(object): if v is None: if colocate_with is None: colocate_with = self._non_slot_devices - with self._distribution.colocate_vars_with(colocate_with): + with self._distribution.extended.colocate_vars_with(colocate_with): # TODO(josh11b): Use get_variable() except for the legacy Adam use case. v = variable_scope.variable(initial_value, name=name, trainable=False) self._non_slot_dict[name] = v @@ -657,7 +658,6 @@ class OptimizerV2(optimizer_v1.Optimizer): var_list=None, gate_gradients=GATE_OP, aggregation_method=None, - colocate_gradients_with_ops=False, name=None, grad_loss=None, stop_gradients=None, @@ -680,8 +680,6 @@ class OptimizerV2(optimizer_v1.Optimizer): `GATE_NONE`, `GATE_OP`, or `GATE_GRAPH`. aggregation_method: Specifies the method used to combine gradient terms. Valid values are defined in the class `AggregationMethod`. - colocate_gradients_with_ops: If True, try colocating gradients with the - corresponding op. name: Optional name for the returned operation. grad_loss: Optional. A `Tensor` holding the gradient computed for `loss`. stop_gradients: Optional. A Tensor or list of tensors not to differentiate @@ -704,8 +702,8 @@ class OptimizerV2(optimizer_v1.Optimizer): Minimization (and gradient computation) is done with respect to the elements of `var_list` if not None, else with respect to any trainable variables created during the execution of the `loss` function. - `gate_gradients`, `aggregation_method`, `colocate_gradients_with_ops` and - `grad_loss` are ignored when eager execution is enabled. + `gate_gradients`, `aggregation_method`, and `grad_loss` are ignored when + eager execution is enabled. @end_compatibility """ grads_and_vars = self.compute_gradients( @@ -713,7 +711,6 @@ class OptimizerV2(optimizer_v1.Optimizer): var_list=var_list, gate_gradients=gate_gradients, aggregation_method=aggregation_method, - colocate_gradients_with_ops=colocate_gradients_with_ops, grad_loss=grad_loss, stop_gradients=stop_gradients, scale_loss_by_num_replicas=scale_loss_by_num_replicas) @@ -733,7 +730,6 @@ class OptimizerV2(optimizer_v1.Optimizer): var_list=None, gate_gradients=GATE_OP, aggregation_method=None, - colocate_gradients_with_ops=False, grad_loss=None, stop_gradients=None, scale_loss_by_num_replicas=None): @@ -756,8 +752,6 @@ class OptimizerV2(optimizer_v1.Optimizer): `GATE_NONE`, `GATE_OP`, or `GATE_GRAPH`. aggregation_method: Specifies the method used to combine gradient terms. Valid values are defined in the class `AggregationMethod`. - colocate_gradients_with_ops: If True, try colocating gradients with the - corresponding op. grad_loss: Optional. A `Tensor` holding the gradient computed for `loss`. stop_gradients: Optional. A Tensor or list of tensors not to differentiate through. @@ -776,8 +770,8 @@ class OptimizerV2(optimizer_v1.Optimizer): not callable. @compatibility(eager) - When eager execution is enabled, `gate_gradients`, `aggregation_method`, - and `colocate_gradients_with_ops` are ignored. + When eager execution is enabled, `gate_gradients`, and `aggregation_method` + are ignored. @end_compatibility """ # TODO(josh11b): Test that we handle weight decay in a reasonable way. @@ -832,7 +826,6 @@ class OptimizerV2(optimizer_v1.Optimizer): grad_ys=grad_loss, gate_gradients=(gate_gradients == optimizer_v1.Optimizer.GATE_OP), aggregation_method=aggregation_method, - colocate_gradients_with_ops=colocate_gradients_with_ops, stop_gradients=stop_gradients) if gate_gradients == optimizer_v1.Optimizer.GATE_GRAPH: grads = control_flow_ops.tuple(grads) @@ -848,8 +841,7 @@ class OptimizerV2(optimizer_v1.Optimizer): """Scale loss for the number of replicas.""" if scale_loss_by_num_replicas is None: scale_loss_by_num_replicas = ( - distribute_lib.get_loss_reduction() == variable_scope - .VariableAggregation.MEAN) + distribute_lib.get_loss_reduction() == ds_reduce_util.ReduceOp.MEAN) if scale_loss_by_num_replicas: num_replicas = \ distribute_ctx.get_distribution_strategy().num_replicas_in_sync @@ -892,7 +884,8 @@ class OptimizerV2(optimizer_v1.Optimizer): raise ValueError("No gradients provided for any variable: %s." % ([str(v) for _, v in grads_and_vars],)) return distribute_ctx.get_replica_context().merge_call( - self._distributed_apply, filtered, global_step=global_step, name=name) + self._distributed_apply, args=(filtered,), + kwargs={"global_step": global_step, "name": name}) def _get_or_create_state(self, var_list=None): """Either looks up or creates `_OptimizerV2State`. @@ -927,8 +920,8 @@ class OptimizerV2(optimizer_v1.Optimizer): def _distributed_apply(self, distribution, grads_and_vars, global_step, name): """`apply_gradients` for use with a `DistributionStrategy`.""" - reduced_grads = distribution.batch_reduce( - variable_scope.VariableAggregation.SUM, grads_and_vars) + reduced_grads = distribution.extended.batch_reduce_to( + ds_reduce_util.ReduceOp.SUM, grads_and_vars) var_list = [v for _, v in grads_and_vars] grads_and_vars = zip(reduced_grads, var_list) @@ -944,7 +937,7 @@ class OptimizerV2(optimizer_v1.Optimizer): with ops.name_scope(name, self._name) as name: per_graph_state = self._get_or_create_state(var_list=unwrapped_var_list) # Include the current value of any dynamic hyper parameters in `state`. - non_slot_devices = distribution.non_slot_devices(var_list) + non_slot_devices = distribution.extended.non_slot_devices(var_list) state = per_graph_state._copy_with_dynamic_hyper( # pylint: disable=protected-access self._hyper, distribution, non_slot_devices) @@ -989,7 +982,8 @@ class OptimizerV2(optimizer_v1.Optimizer): # Use the processors to update the variables. update_ops = [] for grad, var in grads_and_vars: - update_ops.extend(distribution.update(var, update, grad, grouped=False)) + update_ops.extend(distribution.extended.update( + var, update, args=(grad,), group=False)) # Give the child class a chance to do something after applying # gradients @@ -1001,8 +995,8 @@ class OptimizerV2(optimizer_v1.Optimizer): update_ops = control_flow_ops.group(update_ops) with ops.control_dependencies([update_ops]): - finish_updates = distribution.update_non_slot( - non_slot_devices, finish, grouped=False) + finish_updates = distribution.extended.update_non_slot( + non_slot_devices, finish, group=False) # We said grouped=False, which means finish_updates is always a list. # It will be [None] when finish() returns None. if finish_updates == [None]: @@ -1017,8 +1011,8 @@ class OptimizerV2(optimizer_v1.Optimizer): def update_global_step(global_step, name): return global_step.assign_add(1, read_value=False, name=name) - apply_updates = distribution.update(global_step, update_global_step, - name) + apply_updates = distribution.extended.update( + global_step, update_global_step, args=(name,)) # Add the training op to the TRAIN_OP graph collection in graph mode. if not eager_execution: diff --git a/tensorflow/contrib/predictor/BUILD b/tensorflow/contrib/predictor/BUILD index d50b52b8ff..53a3bc63e1 100644 --- a/tensorflow/contrib/predictor/BUILD +++ b/tensorflow/contrib/predictor/BUILD @@ -42,6 +42,7 @@ py_library( name = "saved_model_predictor", srcs = ["saved_model_predictor.py"], srcs_version = "PY2AND3", + visibility = ["//learning/brain/contrib/learn/tpu:__subpackages__"], deps = [ ":base_predictor", "//tensorflow/contrib/saved_model:saved_model_py", diff --git a/tensorflow/contrib/quantize/README.md b/tensorflow/contrib/quantize/README.md index a1f2b59026..9085d9fa71 100644 --- a/tensorflow/contrib/quantize/README.md +++ b/tensorflow/contrib/quantize/README.md @@ -28,7 +28,7 @@ Since it's difficult to add these fake quantization operations to all the required locations in the model, there's a function available that rewrites the training graph. To create a fake quantized training graph: -``` +```python # Build forward pass of model. loss = tf.losses.get_total_loss() @@ -51,7 +51,7 @@ The rewritten *eval graph* is non-trivially different from the *training graph* since the quantization ops affect the batch normalization step. Because of this, we've added a separate rewrite for the *eval graph*: -``` +```python # Build eval model logits = tf.nn.softmax_cross_entropy_with_logits_v2(...) diff --git a/tensorflow/contrib/quantize/python/quant_ops.py b/tensorflow/contrib/quantize/python/quant_ops.py index 6f659347fb..8619708cda 100644 --- a/tensorflow/contrib/quantize/python/quant_ops.py +++ b/tensorflow/contrib/quantize/python/quant_ops.py @@ -138,7 +138,7 @@ def LastValueQuantize(inputs, if per_channel: if input_dim >= 2: batch_min = math_ops.reduce_min( - inputs, reduction_indices=reduce_dims, name='BatchMin') + inputs, axis=reduce_dims, name='BatchMin') else: batch_min = inputs else: @@ -147,7 +147,7 @@ def LastValueQuantize(inputs, if per_channel: if input_dim >= 2: batch_max = math_ops.reduce_max( - inputs, reduction_indices=reduce_dims, name='BatchMax') + inputs, axis=reduce_dims, name='BatchMax') else: batch_max = inputs else: @@ -263,7 +263,7 @@ def MovingAvgQuantize(inputs, if per_channel: if input_dim >= 2: batch_min = math_ops.reduce_min( - inputs, reduction_indices=reduce_dims, name='BatchMin') + inputs, axis=reduce_dims, name='BatchMin') else: batch_min = inputs else: @@ -272,7 +272,7 @@ def MovingAvgQuantize(inputs, if per_channel: if input_dim >= 2: batch_max = math_ops.reduce_max( - inputs, reduction_indices=reduce_dims, name='BatchMax') + inputs, axis=reduce_dims, name='BatchMax') else: batch_max = inputs else: diff --git a/tensorflow/contrib/quantize/python/quantize.py b/tensorflow/contrib/quantize/python/quantize.py index 338923f751..21d1b12130 100644 --- a/tensorflow/contrib/quantize/python/quantize.py +++ b/tensorflow/contrib/quantize/python/quantize.py @@ -160,7 +160,7 @@ def Quantize(graph, # shouldn't quantize it, since the activation will be Fused into the # Add at inference time. consumers = input_to_ops_map.ConsumerOperations(layer_match.bypass_op) - if any([consumer.type in _ACTIVATION_TYPES for consumer in consumers]): + if any(consumer.type in _ACTIVATION_TYPES for consumer in consumers): logging.info('Skipping %s, because its followed by an activation.', layer_match.bypass_op.name) else: @@ -195,7 +195,7 @@ def Quantize(graph, # Add at inference time. consumers = input_to_ops_map.ConsumerOperations( layer_match.post_activation_bypass_op) - if any([consumer.type in _RELU_TYPES for consumer in consumers]): + if any(consumer.type in _RELU_TYPES for consumer in consumers): logging.info('Skipping %s, because its followed by an activation.', layer_match.post_activation_bypass_op.name) else: diff --git a/tensorflow/contrib/resampler/BUILD b/tensorflow/contrib/resampler/BUILD index 38fcca0311..bbf1099675 100644 --- a/tensorflow/contrib/resampler/BUILD +++ b/tensorflow/contrib/resampler/BUILD @@ -13,6 +13,7 @@ load( ) load("//tensorflow:tensorflow.bzl", "cuda_py_test") load("//tensorflow:tensorflow.bzl", "tf_custom_op_py_library") +load("//tensorflow/compiler/tests:build_defs.bzl", "tf_xla_py_test") tf_custom_op_py_library( name = "resampler_py", @@ -50,10 +51,14 @@ tf_kernel_library( prefix = "resampler_ops", deps = [ ":resampler_ops_op_lib", - "//tensorflow/compiler/tf2xla/kernels:resampler_ops", "//tensorflow/core:framework", "//tensorflow/core:lib", - ], + ] + select({ + "//tensorflow:with_xla_support": [ + "//tensorflow/compiler/tf2xla/kernels:resampler_ops", + ], + "//conditions:default": [], + }), alwayslink = 1, ) @@ -94,3 +99,26 @@ cuda_py_test( "//tensorflow/python:array_ops", ], ) + +tf_xla_py_test( + name = "resampler_ops_xla_test", + size = "small", + srcs = ["xla/resampler_ops_xla_test.py"], + disabled_backends = [ + # TODO(b/74459949) Support BatchDot in CPU backend. + "cpu", + "cpu_ondemand", + ], + # TODO(b/112295522): the OSS build will not likely work in the short to medium term, currently it is blocked by the fact that bazel does not allow py_library to depend on cc_library: https://github.com/bazelbuild/bazel/issues/701 which may not be resolvable. + tags = ["no_oss"], + deps = [ + "//tensorflow/compiler/tests:xla_test", + "//tensorflow/compiler/tf2xla/kernels:resampler_ops", + "//tensorflow/contrib/resampler:resampler_ops", + "//tensorflow/contrib/resampler:resampler_py", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:platform_test", + "//third_party/py/numpy", + ], +) diff --git a/tensorflow/compiler/tests/resampler_ops_test.py b/tensorflow/contrib/resampler/xla/resampler_ops_xla_test.py similarity index 76% rename from tensorflow/compiler/tests/resampler_ops_test.py rename to tensorflow/contrib/resampler/xla/resampler_ops_xla_test.py index f87ac3360c..d8ca0eab27 100644 --- a/tensorflow/compiler/tests/resampler_ops_test.py +++ b/tensorflow/contrib/resampler/xla/resampler_ops_xla_test.py @@ -63,8 +63,8 @@ class ResamplerOpsTest(xla_test.XLATestCase): def testSimple(self): for dtype in self.float_types: input_shape = [1, 2, 2, 1] - input_rgb_data = [0, 5, 13, 54] - input_np = np.array(input_rgb_data, dtype=dtype).reshape(input_shape) + input_data = [0, 5, 13, 54] + input_np = np.array(input_data, dtype=dtype).reshape(input_shape) warp_shape = [1, 2] warp_data = [0.7, 0.6] @@ -151,6 +151,55 @@ class ResamplerOpsTest(xla_test.XLATestCase): expected_grad_data, expected_grad_warp) + def testOutOfBoundWarps(self): + # (x, y) are both less than 0. + for dtype in self.float_types: + input_shape = [1, 2, 2, 1] + input_data = [10, 5, 13, 54] + input_np = np.array(input_data, dtype=dtype).reshape(input_shape) + + warp_shape = [1, 2, 2] + warp_data = [-1, -1, 0.7, 0.6] + warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) + expected = [[[0.0], [27.62]]] + self._assertForwardOpMatchesExpected(input_np, warp_np, expected) + + # One of (x, y) is less than 0. + for dtype in self.float_types: + input_shape = [1, 2, 2, 1] + input_data = [10, 5, 13, 54] + input_np = np.array(input_data, dtype=dtype).reshape(input_shape) + + warp_shape = [1, 2, 2] + warp_data = [-1, 0.1, 0.7, 0.6] + warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) + expected = [[[0.0], [27.62]]] + self._assertForwardOpMatchesExpected(input_np, warp_np, expected) + + # Both of (x, y) are greater than image size. + for dtype in self.float_types: + input_shape = [1, 2, 2, 1] + input_data = [10, 5, 13, 54] + input_np = np.array(input_data, dtype=dtype).reshape(input_shape) + + warp_shape = [1, 2, 2] + warp_data = [-0.1, 0.1, 1.2, 2.1] + warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) + expected = [[[0.0], [0.0]]] + self._assertForwardOpMatchesExpected(input_np, warp_np, expected) + + # One of (x, y) is greater than image size. + for dtype in self.float_types: + input_shape = [1, 2, 2, 1] + input_data = [10, 5, 13, 54] + input_np = np.array(input_data, dtype=dtype).reshape(input_shape) + + warp_shape = [1, 2, 2] + warp_data = [0.1, -0.1, 1.2, 0.1] + warp_np = np.array(warp_data, dtype=dtype).reshape(warp_shape) + expected = [[[0.0], [0.0]]] + self._assertForwardOpMatchesExpected(input_np, warp_np, expected) + if __name__ == '__main__': test.main() diff --git a/tensorflow/contrib/rnn/python/kernel_tests/core_rnn_cell_test.py b/tensorflow/contrib/rnn/python/kernel_tests/core_rnn_cell_test.py index 245fa68eae..7d57b0413a 100644 --- a/tensorflow/contrib/rnn/python/kernel_tests/core_rnn_cell_test.py +++ b/tensorflow/contrib/rnn/python/kernel_tests/core_rnn_cell_test.py @@ -906,7 +906,7 @@ class DropoutWrapperTest(test.TestCase): def testDropoutWrapperKeepNoOutput(self): keep_all = variable_scope.get_variable("all", initializer=1.0) - keep_none = variable_scope.get_variable("none", initializer=1e-10) + keep_none = variable_scope.get_variable("none", initializer=1e-6) res = self._testDropoutWrapper( input_keep_prob=keep_all, output_keep_prob=keep_none, @@ -922,7 +922,7 @@ class DropoutWrapperTest(test.TestCase): def testDropoutWrapperKeepNoStateExceptLSTMCellMemory(self): keep_all = variable_scope.get_variable("all", initializer=1.0) - keep_none = variable_scope.get_variable("none", initializer=1e-10) + keep_none = variable_scope.get_variable("none", initializer=1e-6) # Even though we dropout state, by default DropoutWrapper never # drops out the memory ("c") term of an LSTMStateTuple. res = self._testDropoutWrapper( @@ -943,7 +943,7 @@ class DropoutWrapperTest(test.TestCase): def testDropoutWrapperKeepNoInput(self): keep_all = variable_scope.get_variable("all", initializer=1.0) - keep_none = variable_scope.get_variable("none", initializer=1e-10) + keep_none = variable_scope.get_variable("none", initializer=1e-6) true_full_output = np.array( [[[0.751109, 0.751109, 0.751109]], [[0.895509, 0.895509, 0.895509]]], dtype=np.float32) diff --git a/tensorflow/contrib/rnn/python/kernel_tests/core_rnn_test.py b/tensorflow/contrib/rnn/python/kernel_tests/core_rnn_test.py index 5cba54dd3d..ef372b947c 100644 --- a/tensorflow/contrib/rnn/python/kernel_tests/core_rnn_test.py +++ b/tensorflow/contrib/rnn/python/kernel_tests/core_rnn_test.py @@ -227,7 +227,7 @@ class RNNTest(test.TestCase): def testDropout(self): cell = Plus1RNNCell() full_dropout_cell = rnn_cell.DropoutWrapper( - cell, input_keep_prob=1e-12, seed=0) + cell, input_keep_prob=1e-6, seed=0) (name, dep), = full_dropout_cell._checkpoint_dependencies self.assertIs(dep, cell) self.assertEqual("cell", name) diff --git a/tensorflow/contrib/rnn/python/ops/gru_ops.py b/tensorflow/contrib/rnn/python/ops/gru_ops.py index b30ca7882f..251a933eae 100644 --- a/tensorflow/contrib/rnn/python/ops/gru_ops.py +++ b/tensorflow/contrib/rnn/python/ops/gru_ops.py @@ -21,7 +21,7 @@ from tensorflow.contrib.rnn.ops import gen_gru_ops from tensorflow.contrib.util import loader from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape -from tensorflow.python.layers import base as base_layer +from tensorflow.python.keras.engine import input_spec from tensorflow.python.ops import array_ops from tensorflow.python.ops import init_ops from tensorflow.python.ops import math_ops @@ -165,7 +165,7 @@ class GRUBlockCell(LayerRNNCell): num_units = cell_size self._cell_size = num_units # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) @property def state_size(self): diff --git a/tensorflow/contrib/rnn/python/ops/lstm_ops.py b/tensorflow/contrib/rnn/python/ops/lstm_ops.py index 4db431f85a..b043026bc5 100644 --- a/tensorflow/contrib/rnn/python/ops/lstm_ops.py +++ b/tensorflow/contrib/rnn/python/ops/lstm_ops.py @@ -25,6 +25,7 @@ from tensorflow.contrib.rnn.ops import gen_lstm_ops from tensorflow.contrib.util import loader from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.keras.engine import input_spec from tensorflow.python.layers import base as base_layer from tensorflow.python.ops import array_ops from tensorflow.python.ops import init_ops @@ -385,7 +386,7 @@ class LSTMBlockCell(LayerRNNCell): "scope": "lstm_cell" } # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) @property def state_size(self): @@ -628,7 +629,7 @@ class LSTMBlockFusedCell(LSTMBlockWrapper): self._use_peephole = use_peephole # Inputs must be 3-dimensional. - self.input_spec = base_layer.InputSpec(ndim=3) + self.input_spec = input_spec.InputSpec(ndim=3) @property def num_units(self): diff --git a/tensorflow/contrib/rnn/python/ops/rnn_cell.py b/tensorflow/contrib/rnn/python/ops/rnn_cell.py index e159dc9579..8a1c09f171 100644 --- a/tensorflow/contrib/rnn/python/ops/rnn_cell.py +++ b/tensorflow/contrib/rnn/python/ops/rnn_cell.py @@ -30,7 +30,7 @@ from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.keras import activations from tensorflow.python.keras import initializers -from tensorflow.python.layers import base as base_layer +from tensorflow.python.keras.engine import input_spec from tensorflow.python.ops import array_ops from tensorflow.python.ops import clip_ops from tensorflow.python.ops import gen_array_ops @@ -2752,7 +2752,7 @@ class SRUCell(rnn_cell_impl.LayerRNNCell): self._activation = activation or math_ops.tanh # Restrict inputs to be 2-dimensional matrices - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) @property def state_size(self): @@ -3089,7 +3089,7 @@ class IndRNNCell(rnn_cell_impl.LayerRNNCell): super(IndRNNCell, self).__init__(_reuse=reuse, name=name, dtype=dtype) # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) self._num_units = num_units self._activation = activation or math_ops.tanh @@ -3183,7 +3183,7 @@ class IndyGRUCell(rnn_cell_impl.LayerRNNCell): super(IndyGRUCell, self).__init__(_reuse=reuse, name=name, dtype=dtype) # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) self._num_units = num_units self._activation = activation or math_ops.tanh @@ -3323,7 +3323,7 @@ class IndyLSTMCell(rnn_cell_impl.LayerRNNCell): super(IndyLSTMCell, self).__init__(_reuse=reuse, name=name, dtype=dtype) # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) self._num_units = num_units self._forget_bias = forget_bias @@ -3444,7 +3444,7 @@ class MinimalRNNCell(rnn_cell_impl.LayerRNNCell): super(MinimalRNNCell, self).__init__(name=name, dtype=dtype, **kwargs) # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) self.units = units self.activation = activations.get(activation) @@ -3558,7 +3558,7 @@ class CFNCell(rnn_cell_impl.LayerRNNCell): super(CFNCell, self).__init__(name=name, dtype=dtype, **kwargs) # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) self.units = units self.activation = activations.get(activation) diff --git a/tensorflow/contrib/saved_model/BUILD b/tensorflow/contrib/saved_model/BUILD index f0947fe423..269443b2c6 100644 --- a/tensorflow/contrib/saved_model/BUILD +++ b/tensorflow/contrib/saved_model/BUILD @@ -102,7 +102,10 @@ py_test( size = "medium", srcs = ["python/saved_model/keras_saved_model_test.py"], srcs_version = "PY2AND3", - tags = ["no_windows"], + tags = [ + "no_oss", # TODO(b/119349471): Re-enable + "no_windows", + ], deps = [ ":keras_saved_model", "//tensorflow/python:client_testlib", diff --git a/tensorflow/contrib/saved_model/python/saved_model/keras_saved_model.py b/tensorflow/contrib/saved_model/python/saved_model/keras_saved_model.py index 27b5b6d22e..ffba514bb9 100644 --- a/tensorflow/contrib/saved_model/python/saved_model/keras_saved_model.py +++ b/tensorflow/contrib/saved_model/python/saved_model/keras_saved_model.py @@ -25,7 +25,6 @@ from tensorflow.python.client import session from tensorflow.python.estimator import keras as estimator_keras_util from tensorflow.python.estimator import model_fn as model_fn_lib from tensorflow.python.estimator.export import export as export_helpers -from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.keras import backend as K from tensorflow.python.keras import models as models_lib @@ -126,7 +125,7 @@ def save_keras_model( export_dir = export_helpers.get_timestamped_export_dir(saved_model_path) temp_export_dir = export_helpers.get_temp_export_dir(export_dir) - builder = saved_model_builder.SavedModelBuilder(temp_export_dir) + builder = saved_model_builder._SavedModelBuilder(temp_export_dir) # Manually save variables to export them in an object-based checkpoint. This # skips the `builder.add_meta_graph_and_variables()` step, which saves a @@ -228,9 +227,10 @@ def _export_mode( g.add_to_collection(ops.GraphKeys.GLOBAL_STEP, clone.optimizer.iterations) # Extract update and train ops from train/test/predict functions. + train_op = None if mode == model_fn_lib.ModeKeys.TRAIN: clone._make_train_function() - builder._add_train_op(clone.train_function.updates_op) + train_op = clone.train_function.updates_op elif mode == model_fn_lib.ModeKeys.EVAL: clone._make_test_function() else: @@ -265,7 +265,8 @@ def _export_mode( model_fn_lib.EXPORT_TAG_MAP[mode], signature_def_map=_create_signature_def_map(clone, mode), saver=saver_lib.Saver(clone_var_list), - main_op=variables.local_variables_initializer()) + init_op=variables.local_variables_initializer(), + train_op=train_op) return None @@ -307,31 +308,11 @@ def _create_signature_def_map(model, mode): serving_only=(mode == model_fn_lib.ModeKeys.PREDICT)) -def _assert_same_non_optimizer_objects(model, model_graph, clone, clone_graph): +def _assert_same_non_optimizer_objects(model, model_graph, clone, clone_graph): # pylint: disable=unused-argument """Assert model and clone contain the same checkpointable objects.""" - def get_non_optimizer_objects(m, g): - """Gather set of model and optimizer checkpointable objects.""" - # Set default graph because optimizer.variables() returns optimizer - # variables defined in the default graph. - with g.as_default(): - all_objects = set(checkpointable_utils.list_objects(m)) - optimizer_and_variables = set() - for obj in all_objects: - if isinstance(obj, optimizers.TFOptimizer): - optimizer_and_variables.update(checkpointable_utils.list_objects(obj)) - optimizer_and_variables.update(set(obj.optimizer.variables())) - return all_objects - optimizer_and_variables - - model_objects = get_non_optimizer_objects(model, model_graph) - clone_objects = get_non_optimizer_objects(clone, clone_graph) - - if len(model_objects) != len(clone_objects): - raise errors.InternalError( - None, None, - 'Model and clone must use the same variables.' - '\n\tModel variables: %s\n\t Clone variables: %s' - % (model_objects, clone_objects)) + # TODO(fchollet, kathywu): make sure this works in eager mode. + return True def load_keras_model(saved_model_path): diff --git a/tensorflow/contrib/saved_model/python/saved_model/keras_saved_model_test.py b/tensorflow/contrib/saved_model/python/saved_model/keras_saved_model_test.py index a65b2ce466..93d73e1b48 100644 --- a/tensorflow/contrib/saved_model/python/saved_model/keras_saved_model_test.py +++ b/tensorflow/contrib/saved_model/python/saved_model/keras_saved_model_test.py @@ -29,14 +29,12 @@ from tensorflow.python import keras from tensorflow.python.client import session from tensorflow.python.eager import context from tensorflow.python.estimator import model_fn as model_fn_lib -from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.framework import test_util from tensorflow.python.keras.engine import training from tensorflow.python.keras.utils import tf_utils from tensorflow.python.ops import array_ops from tensorflow.python.platform import test -from tensorflow.python.saved_model import constants from tensorflow.python.saved_model import loader_impl from tensorflow.python.saved_model import signature_constants from tensorflow.python.training import training as training_module @@ -255,7 +253,7 @@ def load_model(sess, path, mode): outputs = { k: sess.graph.get_tensor_by_name(v.name) for k, v in meta_graph_def.signature_def[sig_def_key].outputs.items()} - return inputs, outputs + return inputs, outputs, meta_graph_def @test_util.run_all_in_graph_and_eager_modes @@ -332,8 +330,8 @@ class TestModelSavedModelExport(test.TestCase, parameterized.TestCase): # Load predict graph, and test predictions with session.Session(graph=ops.Graph()) as sess: - inputs, outputs = load_model(sess, output_path, - model_fn_lib.ModeKeys.PREDICT) + inputs, outputs, _ = load_model(sess, output_path, + model_fn_lib.ModeKeys.PREDICT) predictions = sess.run(outputs[output_name], {inputs[input_name]: input_arr}) @@ -342,19 +340,21 @@ class TestModelSavedModelExport(test.TestCase, parameterized.TestCase): if optimizer: # Load eval graph, and test predictions, loss and metric values with session.Session(graph=ops.Graph()) as sess: - inputs, outputs = load_model(sess, output_path, - model_fn_lib.ModeKeys.EVAL) + inputs, outputs, _ = load_model(sess, output_path, + model_fn_lib.ModeKeys.EVAL) # First obtain the loss and predictions, and run the metric update op by # feeding in the inputs and targets. loss, predictions, _ = sess.run( (outputs['loss'], outputs['predictions/' + output_name], - outputs['metrics/mae/update_op']), - {inputs[input_name]: input_arr, inputs[target_name]: target_arr}) + outputs['metrics/mean_absolute_error/update_op']), { + inputs[input_name]: input_arr, + inputs[target_name]: target_arr + }) # The metric value should be run after the update op, to ensure that it # reflects the correct value. - metric_value = sess.run(outputs['metrics/mae/value']) + metric_value = sess.run(outputs['metrics/mean_absolute_error/value']) self.assertEqual(int(train_before_export), sess.run(training_module.get_global_step())) @@ -364,17 +364,17 @@ class TestModelSavedModelExport(test.TestCase, parameterized.TestCase): # Load train graph, and check for the train op, and prediction values with session.Session(graph=ops.Graph()) as sess: - inputs, outputs = load_model(sess, output_path, - model_fn_lib.ModeKeys.TRAIN) + inputs, outputs, meta_graph_def = load_model( + sess, output_path, model_fn_lib.ModeKeys.TRAIN) self.assertEqual(int(train_before_export), sess.run(training_module.get_global_step())) self.assertIn('loss', outputs) - self.assertIn('metrics/mae/update_op', outputs) - self.assertIn('metrics/mae/value', outputs) + self.assertIn('metrics/mean_absolute_error/update_op', outputs) + self.assertIn('metrics/mean_absolute_error/value', outputs) self.assertIn('predictions/' + output_name, outputs) # Train for a step - train_op = ops.get_collection(constants.TRAIN_OP_KEY) + train_op = loader_impl.get_train_op(meta_graph_def) train_outputs, _ = sess.run( [outputs, train_op], {inputs[input_name]: input_arr, inputs[target_name]: target_arr}) @@ -401,8 +401,8 @@ class TestModelSavedModelExport(test.TestCase, parameterized.TestCase): output_path = keras_saved_model.save_keras_model( model, saved_model_path, custom_objects={'relu6': relu6}) with session.Session(graph=ops.Graph()) as sess: - inputs, outputs = load_model(sess, output_path, - model_fn_lib.ModeKeys.PREDICT) + inputs, outputs, _ = load_model(sess, output_path, + model_fn_lib.ModeKeys.PREDICT) input_name = model.input_names[0] output_name = model.output_names[0] predictions = sess.run( @@ -463,11 +463,6 @@ class TestModelSavedModelExport(test.TestCase, parameterized.TestCase): clone.compile(loss='mse', optimizer=keras.optimizers.RMSprop(lr=0.0001)) clone.train_on_batch(input_arr, target_arr) - with self.assertRaisesRegexp( - errors.InternalError, 'Model and clone must use the same variables.'): - keras_saved_model._assert_same_non_optimizer_objects( - model, model_graph, clone, clone_graph) - def testSaveSeqModelWithoutInputShapesRaisesError(self): """A Sequential model that hasn't been built should raise an error.""" model = sequential_model_without_input_shape(True) diff --git a/tensorflow/contrib/seq2seq/python/kernel_tests/attention_wrapper_test.py b/tensorflow/contrib/seq2seq/python/kernel_tests/attention_wrapper_test.py index 8668c67cf9..922f21b98b 100644 --- a/tensorflow/contrib/seq2seq/python/kernel_tests/attention_wrapper_test.py +++ b/tensorflow/contrib/seq2seq/python/kernel_tests/attention_wrapper_test.py @@ -154,8 +154,8 @@ class AttentionWrapperTest(test.TestCase): if attention_layer_sizes is not None: # Compute sum of attention_layer_sizes. Use encoder_output_depth if None. - attention_depth = sum([attention_layer_size or encoder_output_depth - for attention_layer_size in attention_layer_sizes]) + attention_depth = sum(attention_layer_size or encoder_output_depth + for attention_layer_size in attention_layer_sizes) elif attention_layers is not None: # Compute sum of attention_layers output depth. attention_depth = sum( diff --git a/tensorflow/contrib/summary/summary_ops_test.py b/tensorflow/contrib/summary/summary_ops_test.py index 4d1807130c..10e4556dac 100644 --- a/tensorflow/contrib/summary/summary_ops_test.py +++ b/tensorflow/contrib/summary/summary_ops_test.py @@ -152,6 +152,27 @@ class EagerFileTest(test_util.TensorFlowTestCase): self.assertEqual(len(events), 2) self.assertEqual(events[1].summary.value[0].tag, 'scalar') + def testRecordEveryNGlobalSteps(self): + step = training_util.get_or_create_global_step() + logdir = tempfile.mkdtemp() + + def run_step(): + summary_ops.scalar('scalar', i, step=step) + step.assign_add(1) + + with summary_ops.create_file_writer( + logdir).as_default(), summary_ops.record_summaries_every_n_global_steps( + 2, step): + for i in range(10): + run_step() + # And another 10 steps as a graph function. + run_step_fn = function.defun(run_step) + for i in range(10): + run_step_fn() + + events = summary_test_util.events_from_logdir(logdir) + self.assertEqual(len(events), 11) + def testMaxQueue(self): logs = tempfile.mkdtemp() with summary_ops.create_file_writer( @@ -279,12 +300,9 @@ class EagerDbTest(summary_test_util.SummaryDbTest): def testDbURIOpen(self): tmpdb_path = os.path.join(self.get_temp_dir(), 'tmpDbURITest.sqlite') - tmpdb_uri = six.moves.urllib_parse.urljoin("file:", tmpdb_path) - tmpdb_writer = summary_ops.create_db_writer( - tmpdb_uri, - "experimentA", - "run1", - "user1") + tmpdb_uri = six.moves.urllib_parse.urljoin('file:', tmpdb_path) + tmpdb_writer = summary_ops.create_db_writer(tmpdb_uri, 'experimentA', + 'run1', 'user1') with summary_ops.always_record_summaries(): with tmpdb_writer.as_default(): summary_ops.scalar('t1', 2.0) diff --git a/tensorflow/contrib/tensorboard/db/summary_file_writer.cc b/tensorflow/contrib/tensorboard/db/summary_file_writer.cc index 3f24f58f03..22b6f09d0c 100644 --- a/tensorflow/contrib/tensorboard/db/summary_file_writer.cc +++ b/tensorflow/contrib/tensorboard/db/summary_file_writer.cc @@ -73,7 +73,16 @@ class SummaryFileWriter : public SummaryWriterInterface { e->set_step(global_step); e->set_wall_time(GetWallTime()); Summary::Value* v = e->mutable_summary()->add_value(); - t.AsProtoTensorContent(v->mutable_tensor()); + + if (t.dtype() == DT_STRING) { + // Treat DT_STRING specially, so that tensor_util.MakeNdarray in Python + // can convert the TensorProto to string-type numpy array. MakeNdarray + // does not work with strings encoded by AsProtoTensorContent() in + // tensor_content. + t.AsProtoField(v->mutable_tensor()); + } else { + t.AsProtoTensorContent(v->mutable_tensor()); + } v->set_tag(tag); if (!serialized_metadata.empty()) { v->mutable_metadata()->ParseFromString(serialized_metadata); diff --git a/tensorflow/contrib/tensorboard/db/summary_file_writer_test.cc b/tensorflow/contrib/tensorboard/db/summary_file_writer_test.cc index cd3f712256..ffbfb9533e 100644 --- a/tensorflow/contrib/tensorboard/db/summary_file_writer_test.cc +++ b/tensorflow/contrib/tensorboard/db/summary_file_writer_test.cc @@ -15,6 +15,7 @@ limitations under the License. #include "tensorflow/contrib/tensorboard/db/summary_file_writer.h" #include "tensorflow/core/framework/summary.pb.h" +#include "tensorflow/core/framework/tensor.pb.h" #include "tensorflow/core/lib/core/errors.h" #include "tensorflow/core/lib/core/refcount.h" #include "tensorflow/core/lib/io/path.h" @@ -104,6 +105,23 @@ TEST_F(SummaryFileWriterTest, WriteTensor) { CHECK_EQ(e.summary().value_size(), 1); EXPECT_EQ(e.summary().value(0).tag(), "name"); })); + TF_CHECK_OK(SummaryTestHelper( + "string_tensor_test", + [](SummaryWriterInterface* writer) { + Tensor hello(DT_STRING, TensorShape({})); + hello.scalar()() = "hello"; + TF_RETURN_IF_ERROR(writer->WriteTensor( + 2, hello, "name", SummaryMetadata().SerializeAsString())); + TF_RETURN_IF_ERROR(writer->Flush()); + return Status::OK(); + }, + [](const Event& e) { + EXPECT_EQ(e.step(), 2); + CHECK_EQ(e.summary().value_size(), 1); + EXPECT_EQ(e.summary().value(0).tag(), "name"); + EXPECT_EQ(e.summary().value(0).tensor().dtype(), DT_STRING); + EXPECT_EQ(e.summary().value(0).tensor().string_val()[0], "hello"); + })); } TEST_F(SummaryFileWriterTest, WriteScalar) { diff --git a/tensorflow/contrib/tensorrt/BUILD b/tensorflow/contrib/tensorrt/BUILD index 20bcd2447e..784acce444 100644 --- a/tensorflow/contrib/tensorrt/BUILD +++ b/tensorflow/contrib/tensorrt/BUILD @@ -29,6 +29,10 @@ load( "if_tensorrt", ) +exports_files(glob([ + "test/testdata/*", +])) + tf_cuda_cc_test( name = "tensorrt_test_cc", size = "small", @@ -491,6 +495,7 @@ cuda_py_tests( "test/memory_alignment_test.py", "test/multi_connection_neighbor_engine_test.py", "test/neighboring_engine_test.py", + "test/quantization_test.py", "test/rank_two_test.py", "test/reshape_transpose_test.py", "test/vgg_block_nchw_test.py", @@ -527,6 +532,30 @@ cuda_py_tests( ], ) +cuda_py_test( + name = "quantization_mnist_test", + srcs = ["test/quantization_mnist_test.py"], + additional_deps = [ + ":tf_trt_integration_test_base", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python/keras:keras", + "//tensorflow/python/estimator:estimator", + ], + data = [ + "test/testdata/checkpoint", + "test/testdata/model.ckpt-46900.data-00000-of-00001", + "test/testdata/model.ckpt-46900.index", + ], + tags = [ + "no_cuda_on_cpu_tap", + "no_pip", + "no_tap", # It is not able to download the mnist data. + "no_windows", + "nomac", + ], +) + cc_library( name = "utils", srcs = ["convert/utils.cc"], diff --git a/tensorflow/contrib/tensorrt/convert/convert_graph.cc b/tensorflow/contrib/tensorrt/convert/convert_graph.cc index 26d54eb156..812948bb30 100644 --- a/tensorflow/contrib/tensorrt/convert/convert_graph.cc +++ b/tensorflow/contrib/tensorrt/convert/convert_graph.cc @@ -82,60 +82,76 @@ std::vector GetLoadedTensorRTVersion() { } TrtCandidateSelector::TrtCandidateSelector( - const grappler::GraphProperties& graph_properties) - : graph_properties_(graph_properties) {} + const grappler::GraphProperties& graph_properties, int precision_mode) + : graph_properties_(graph_properties), precision_mode_(precision_mode) {} Status TrtCandidateSelector::IsTensorRTCandidate(const tensorflow::Node* node) { // TODO(laigd): move this set to TrtNodeValidator where it should belong. // LINT.IfChange static const std::set candidate_ops = { - "Identity", - "Snapshot", - "Const", - "Conv2D", - "MaxPool", - "BiasAdd", - "Relu", - "Add", - "Mul", - "Sub", - "Rsqrt", - "Pad", - "Mean", - "AvgPool", - "ConcatV2", - "DepthwiseConv2dNative", - "FusedBatchNorm", - "FusedBatchNormV2", - "Div", - "RealDiv", - "Rsqrt", - "Reciprocal", - "Exp", - "Log", - "Sqrt", - "Abs", - "Neg", - "Transpose", - "Reshape", - "MatMul", - "BatchMatMul", - "Softmax", - "Minimum", - "Maximum", - "TopKV2", - "Sum", - "Prod", - "Max", - "Min", + "Identity", + "Snapshot", + "Const", + "Conv2D", + "MaxPool", + "BiasAdd", + "Relu", + "Sigmoid", + "Tanh", + "Add", + "Mul", + "Sub", + "Rsqrt", + "Pad", + "Mean", + "AvgPool", + "ConcatV2", + "DepthwiseConv2dNative", + "FusedBatchNorm", + "FusedBatchNormV2", + "Div", + "RealDiv", + "Rsqrt", + "Reciprocal", + "Exp", + "Log", + "Sqrt", + "Abs", + "Neg", + "Transpose", + "Reshape", + "MatMul", + "BatchMatMul", + "Softmax", + "Minimum", + "Maximum", + "TopKV2", + "Sum", + "Prod", + "Max", + "Min", + "Relu6", + "Square", }; - // LINT.ThenChange(//tensorflow/contrib/tensorrt/convert/convert_nodes.cc) - const bool is_supported_op_type = + bool is_supported_op_type = (candidate_ops.count(node->type_string()) || PluginFactoryTensorRT::GetInstance()->IsPlugin(node->type_string())); + static const std::set quantize_ops = { + "QuantizeAndDequantizeV2", + "QuantizeAndDequantizeV3", + "FakeQuantWithMinMaxVars", + "FakeQuantWithMinMaxArgs", + }; + // In INT8 mode, we will always apply the quantization ranges provided by + // these ops to the relevant tensors. This happens regardless of the value of + // use_calibration. + if (precision_mode_ == INT8MODE && quantize_ops.count(node->type_string())) { + is_supported_op_type = true; + } + // LINT.ThenChange(//tensorflow/contrib/tensorrt/convert/convert_nodes.cc) if (!is_supported_op_type) { return errors::Unimplemented("Op type ", node->type_string(), - " is not supported."); + " is not supported"); } std::vector input_edges; @@ -170,7 +186,7 @@ tensorflow::Status BuildNodeMap( tensorflow::Status ConvertCalibGraphToInferGraph( const tensorflow::GraphDef& graph_def, tensorflow::GraphDef* infer_graph, bool is_dyn_op) { - VLOG(0) << "Starting Calib Conversion"; + LOG(INFO) << "Starting Calib Conversion"; infer_graph->CopyFrom(graph_def); auto trt_rm = TRTResourceManager::instance(); auto calib_rm = trt_rm->getManager("TRTCalibration"); @@ -220,18 +236,19 @@ tensorflow::Status ConvertGraphDefToTensorRT( const std::vector& output_names, size_t max_batch_size, size_t max_workspace_size_bytes, tensorflow::GraphDef* new_graph_def, int precision_mode, int minimum_segment_size, bool is_dyn_op, - int max_cached_engines, std::vector cached_engine_batches) { + int max_cached_engines, std::vector cached_engine_batches, + bool use_calibration) { // Create GrapplerItem. tensorflow::grappler::GrapplerItem item; item.fetch = output_names; item.graph = graph_def; - // TODO(aaroey): we should have used single machine cluster like the - // following, but the problem is then wrap_conversion will depend on - // direct_session and cause double linking problems. To fix this we need to - // fix or get rid of the swig dependency. Here we use VirtualCluster - // as a work around, and we need to create a session to initialize the - // underlying device before calling this method. +// TODO(aaroey): we should have used single machine cluster like the +// following, but the problem is then wrap_conversion will depend on +// direct_session and cause double linking problems. To fix this we need to +// fix or get rid of the swig dependency. Here we use VirtualCluster +// as a work around, and we need to create a session to initialize the +// underlying device before calling this method. #if 0 // Create single machine cluster. Note that this will create a session and // initialize the gpu devices. @@ -264,7 +281,9 @@ tensorflow::Status ConvertGraphDefToTensorRT( #endif // Create RewriterConfig. - tensorflow::RewriterConfig rw_cfg; + tensorflow::ConfigProto config_proto; + auto& rw_cfg = + *config_proto.mutable_graph_options()->mutable_rewrite_options(); // TODO(aaroey): use only const folding and layout for the time being since // new optimizers break the graph for trt. rw_cfg.add_optimizers("constfold"); @@ -285,9 +304,10 @@ tensorflow::Status ConvertGraphDefToTensorRT( list->add_i(batch); } } + parameters["use_calibration"].set_b(use_calibration); // Run optimizer. - tensorflow::grappler::MetaOptimizer meta_opt(nullptr, rw_cfg); + tensorflow::grappler::MetaOptimizer meta_opt(nullptr, config_proto); TF_RETURN_IF_ERROR(meta_opt.Optimize(cluster.get(), item, new_graph_def)); if (VLOG_IS_ON(5)) { @@ -433,7 +453,8 @@ tensorflow::Status GetEngineInfo( << "but this shouldn't have happened"; info->device = *segment_devices.begin(); } else { - LOG(ERROR) << "Can't find a device placement for the op!"; + VLOG(1) << "No device is assigned to the segment. " + << "A device will be assigned during graph execution (inference)."; } return Status::OK(); } @@ -564,27 +585,30 @@ tensorflow::Status CreateTRTNode(const std::vector& infos, int pos, } } } + + const bool calibrate_int8 = + (info.precision_mode == INT8MODE && info.use_calibration); + // Build the engine and get its serialized representation. string segment_string; - if (info.engine_type == EngineInfo::EngineType::TRTStatic || - info.precision_mode == INT8MODE) { + if (info.engine_type == EngineInfo::EngineType::TRTStatic || calibrate_int8) { // Create static engine for fp32/fp16 mode, and test validity of the engine - // for int8 mode. We don't want engine to fail at the calibration time. - // So we are constructing a FP32 engine here to check its validity, and if - // it is a valid engine then we put the serialized graphdef to the op. - // Otherwise we skip node creation for this engine. + // for int8 calibration mode. We don't want engine to fail at the + // calibration time. So we are constructing a FP32 engine here to check its + // validity, and if it is a valid engine then we put the serialized graphdef + // to the op. Otherwise we skip node creation for this engine. Logger trt_logger; TrtUniquePtrType engine; // TODO(sami): What happens if 1st dim is not batch? TF_RETURN_IF_ERROR(ConvertGraphDefToEngine( - info.segment_graph_def, - info.precision_mode == INT8MODE ? FP32MODE : info.precision_mode, + info.segment_graph_def, calibrate_int8 ? FP32MODE : info.precision_mode, max_batch_size, info.max_workspace_size_bytes, input_shapes, &trt_logger, alloc, /*calibrator=*/nullptr, &engine, + info.use_calibration, /*convert_successfully=*/nullptr)); TrtUniquePtrType engine_data(engine->serialize()); segment_string = string((const char*)engine_data->data(), engine_data->size()); - if (info.precision_mode == INT8MODE) { + if (calibrate_int8) { // See above comment about why not putting this inside the 'else' branch. segment_string = info.segment_graph_def.SerializeAsString(); } @@ -596,7 +620,7 @@ tensorflow::Status CreateTRTNode(const std::vector& infos, int pos, // conversion. string prec_string; TF_RETURN_IF_ERROR(GetPrecisionModeName(info.precision_mode, &prec_string)); - if (info.precision_mode == INT8MODE && + if (info.precision_mode == INT8MODE && calibrate_int8 && !TRTResourceManager::instance()->getManager("TRTCalibration")) { LOG(ERROR) << "Failed to construct calibration storage"; } @@ -632,6 +656,7 @@ tensorflow::Status CreateTRTNode(const std::vector& infos, int pos, .Attr("cached_engine_batches", {max_batch_size}) .Attr("workspace_size_bytes", info.max_workspace_size_bytes) .Attr("precision_mode", prec_string) + .Attr("use_calibration", info.use_calibration) .Attr("OutT", out_types) .Finalize(&trt_node); if (!status.ok()) { @@ -864,19 +889,17 @@ tensorflow::Status ConvertAfterShapes(ConversionParams& params) { } segment_options.minimum_segment_size = params.minimum_segment_size; tensorflow::tensorrt::segment::SegmentNodesVector initial_segments; - TrtCandidateSelector candidate_selector(*params.graph_properties); + TrtCandidateSelector candidate_selector(*params.graph_properties, + params.precision_mode); TF_RETURN_IF_ERROR(tensorrt::segment::SegmentGraph( - &graph, - std::bind(&TrtCandidateSelector::IsTensorRTCandidate, &candidate_selector, - std::placeholders::_1), + &graph, std::bind(&TrtCandidateSelector::IsTensorRTCandidate, + &candidate_selector, std::placeholders::_1), // Input validation is already done by TrtCandidateSelector, so we don't // need to check the input edges. [](const Edge* edge) { return true; }, OutputEdgeValidator(), segment_options, &initial_segments)); - if (initial_segments.size() > 1) { - VLOG(0) << "MULTIPLE tensorrt candidate conversion: " + LOG(INFO) << "Number of TensorRT candidate segments: " << initial_segments.size(); - } // Get the EngineInfo for each segment. std::unordered_map node_map; @@ -902,13 +925,17 @@ tensorflow::Status ConvertAfterShapes(ConversionParams& params) { continue; } curr_engine.precision_mode = params.precision_mode; - curr_engine.engine_type = - (params.is_dyn_op || params.precision_mode == INT8MODE - ? EngineInfo::EngineType::TRTDynamic - : EngineInfo::EngineType::TRTStatic); + if (params.use_calibration && params.precision_mode != INT8MODE) { + return errors::InvalidArgument( + "Calibration with FP32 or FP16 is not supported."); + } + curr_engine.engine_type = ((params.is_dyn_op || params.use_calibration) + ? EngineInfo::EngineType::TRTDynamic + : EngineInfo::EngineType::TRTStatic); + curr_engine.use_calibration = params.use_calibration; curr_engine.cached_engine_batches = params.cached_engine_batches; curr_engine.maximum_cached_engines = params.max_cached_engines; - StrAppend(&curr_engine.engine_name, "my_trt_op_", t); + StrAppend(&curr_engine.engine_name, "TRTEngineOp_", t); status = RegisterSegmentFunctionToFunctionLibrary( &graph, curr_engine.segment_graph_def, curr_engine.engine_name); if (!status.ok()) { @@ -969,16 +996,9 @@ tensorflow::Status ConvertAfterShapes(ConversionParams& params) { &graph, alloc.get(), &engine_nodes); // If status is ok, we successfully added the node to the graph and can // remove segment ops. Otherwise graph is not modified. - string msg = StrCat("Engine ", engine.engine_name, " creation for segment ", - i, ", composed of ", + string msg = StrCat("TensorRT node ", engine.engine_name, + " added for segment ", i, " consisting of ", converted_segments.at(i).first.size(), " nodes"); - if (VLOG_IS_ON(1)) { - StrAppend(&msg, " ("); - for (const string& node_name : converted_segments.at(i).first) { - StrAppend(&msg, node_name, ", "); - } - StrAppend(&msg, ")"); - } if (status.ok()) { LOG(INFO) << msg << " succeeded."; for (auto node_name : converted_segments.at(i).first) { @@ -986,7 +1006,14 @@ tensorflow::Status ConvertAfterShapes(ConversionParams& params) { } } else { // Graph is not modified. - LOG(WARNING) << msg << " failed: " << status << ". Skipping..."; + LOG(WARNING) << msg << " failed: " << status << ". Fallback to TF..."; + } + if (VLOG_IS_ON(1)) { + msg = "Segment consists of nodes: "; + for (const string& node_name : converted_segments.at(i).first) { + StrAppend(&msg, node_name, ", "); + } + VLOG(1) << msg; } } cudaSetDevice(old_cuda_device); diff --git a/tensorflow/contrib/tensorrt/convert/convert_graph.h b/tensorflow/contrib/tensorrt/convert/convert_graph.h index 1c9d82105a..1f39f56f63 100644 --- a/tensorflow/contrib/tensorrt/convert/convert_graph.h +++ b/tensorflow/contrib/tensorrt/convert/convert_graph.h @@ -35,7 +35,8 @@ namespace convert { // supported by TRT. class TrtCandidateSelector { public: - TrtCandidateSelector(const grappler::GraphProperties& graph_properties); + TrtCandidateSelector(const grappler::GraphProperties& graph_properties, + int precision_mode); // Returns OK iff 'node' is a TF-TRT conversion candidate, which will be added // to TRT subgraph and later converted into TRT engine. @@ -49,6 +50,9 @@ class TrtCandidateSelector { // GraphProperties of the graph whose nodes are to be validated by // IsTensorRTCandidate(). const grappler::GraphProperties& graph_properties_; + + // Quantization ops are only converted when using quantized precisions. + const int precision_mode_; }; struct ConversionParams { @@ -63,6 +67,7 @@ struct ConversionParams { cluster(nullptr), is_dyn_op(false), fixed_input_size(true), + use_calibration(true), max_cached_engines(1) {} const tensorflow::GraphDef* input_graph_def; const std::vector* output_names; @@ -76,6 +81,7 @@ struct ConversionParams { bool is_dyn_op; // Whether to create engine on conversion or execution time bool fixed_input_size; // Assume non-batch ranks of input tensors are fixed int max_cached_engines; // maximum number of cached engines + bool use_calibration; std::vector cached_engine_batches; // list of cached engines }; @@ -95,7 +101,7 @@ tensorflow::Status ConvertGraphDefToTensorRT( size_t max_workspace_size_bytes, tensorflow::GraphDef* new_graph_def, int precision_mode = 1, int minimum_segment_size = 3, bool is_dyn_op = false, int max_cached_engines = 1, - std::vector cached_engine_batches = {}); + std::vector cached_engine_batches = {}, bool use_calibration = true); // Method to call from optimization pass tensorflow::Status ConvertAfterShapes(ConversionParams& params); diff --git a/tensorflow/contrib/tensorrt/convert/convert_graph_test.cc b/tensorflow/contrib/tensorrt/convert/convert_graph_test.cc index f10729987f..2d2bfeb192 100644 --- a/tensorflow/contrib/tensorrt/convert/convert_graph_test.cc +++ b/tensorflow/contrib/tensorrt/convert/convert_graph_test.cc @@ -85,27 +85,42 @@ TEST(TrtCandidateSelector, Basics) { ops::MatMul(s.WithOpName("matmul_with_incompatible_input"), incompatible_feed, const_2); + // Quantize ops. + auto quantize_attrs = ops::FakeQuantWithMinMaxArgs::Min(-6.0f).Max(6.0f); + auto quantize = ops::FakeQuantWithMinMaxArgs(s.WithOpName("quantize"), feed, + quantize_attrs); + + // Get GrapplerItem and GraphProperties. grappler::GrapplerItem item; TF_EXPECT_OK(s.ToGraphDef(&item.graph)); Tensor feed_tensor(DT_FLOAT, input_shape); item.feed.push_back(std::make_pair("feed", feed_tensor)); - grappler::GraphProperties graph_properties(item); TF_EXPECT_OK(graph_properties.InferStatically(true)); - TrtCandidateSelector selector(graph_properties); - TF_EXPECT_OK(selector.IsTensorRTCandidate(matmul.operation.node())); - ExpectStatus( - selector.IsTensorRTCandidate(incompatible_matmul.operation.node()), - error::INVALID_ARGUMENT, - "transpose_a is not supported for TensorRT FullyConnected " - "(op: MatMul), at: incompatible_matmul"); - ExpectStatus(selector.IsTensorRTCandidate(unsupported_op.operation.node()), - error::UNIMPLEMENTED, "Op type Sin is not supported"); - ExpectStatus(selector.IsTensorRTCandidate( - matmul_with_incompatible_input.operation.node()), - error::INTERNAL, - "Failed to convert input with index 0 to a TRT_TensorOrWeights"); + for (const int precision_mode : {FP32MODE, INT8MODE}) { + TrtCandidateSelector selector(graph_properties, precision_mode); + TF_EXPECT_OK(selector.IsTensorRTCandidate(matmul.operation.node())); + ExpectStatus( + selector.IsTensorRTCandidate(incompatible_matmul.operation.node()), + error::INVALID_ARGUMENT, + "transpose_a is not supported for TensorRT FullyConnected " + "(op: MatMul), at: incompatible_matmul"); + ExpectStatus(selector.IsTensorRTCandidate(unsupported_op.operation.node()), + error::UNIMPLEMENTED, "Op type Sin is not supported"); + ExpectStatus( + selector.IsTensorRTCandidate( + matmul_with_incompatible_input.operation.node()), + error::INTERNAL, + "Failed to convert input with index 0 to a TRT_TensorOrWeights"); + if (precision_mode == INT8MODE) { + TF_EXPECT_OK(selector.IsTensorRTCandidate(quantize.operation.node())); + } else { + ExpectStatus(selector.IsTensorRTCandidate(quantize.operation.node()), + error::UNIMPLEMENTED, + "Op type FakeQuantWithMinMaxArgs is not supported"); + } + } } class FakeCluster : public grappler::Cluster { diff --git a/tensorflow/contrib/tensorrt/convert/convert_nodes.cc b/tensorflow/contrib/tensorrt/convert/convert_nodes.cc index e2988f5f2a..25a34dd350 100644 --- a/tensorflow/contrib/tensorrt/convert/convert_nodes.cc +++ b/tensorflow/contrib/tensorrt/convert/convert_nodes.cc @@ -54,10 +54,10 @@ limitations under the License. // would work! #define TFTRT_CHECK_EQ_TYPE(val1, val2) CHECK_EQ((int)val1, (int)val2) -#define TFTRT_INTERNAL_ERROR_AT_NODE(node) \ - do { \ - return tensorflow::errors::Internal( \ - "TFTRT::", __FUNCTION__, "failed to add TRT layer, at: ", node); \ +#define TFTRT_INTERNAL_ERROR_AT_NODE(node) \ + do { \ + return tensorflow::errors::Internal( \ + "TFTRT::", __FUNCTION__, " failed to add TRT layer, at: ", node); \ } while (0) #define TFTRT_RETURN_ERROR_IF_FALSE(status, node) \ @@ -130,7 +130,7 @@ void GetOutputProperties(const grappler::GraphProperties& graph_properties, *dtype = out_shape.dtype(); *shape = out_shape.shape(); } else { - VLOG(0) << "Unknown output shape" << node->name(); + LOG(INFO) << "Unknown output shape" << node->name(); *dtype = node->output_type(out_port); } } @@ -181,16 +181,55 @@ Status ValidateTensorProperties(const string& producer_node_type, if (shape.dim_size(d) < 0) { return errors::InvalidArgument( "Input tensor with shape ", shape.DebugString(), - " has an unknown non-batch dimemension at dim ", d); + " has an unknown non-batch dimension at dim ", d); } } return Status::OK(); } +string DebugString(const nvinfer1::DimensionType type) { + switch (type) { + case nvinfer1::DimensionType::kSPATIAL: + return "kSPATIAL"; + case nvinfer1::DimensionType::kCHANNEL: + return "kCHANNEL"; + case nvinfer1::DimensionType::kINDEX: + return "kINDEX"; + case nvinfer1::DimensionType::kSEQUENCE: + return "kSEQUENCE"; + default: + return StrCat(static_cast(type), "=unknown"); + } +} + +string DebugString(const nvinfer1::DataType trt_dtype) { + switch (trt_dtype) { + case nvinfer1::DataType::kFLOAT: + return "kFLOAT"; + case nvinfer1::DataType::kHALF: + return "kHALF"; + case nvinfer1::DataType::kINT8: + return "kINT8"; + case nvinfer1::DataType::kINT32: + return "kINT32"; + default: + return "Invalid TRT data type"; + } +} + string DebugString(const nvinfer1::Dims& dims) { string out = StrCat("nvinfer1::Dims(nbDims=", dims.nbDims, ", d="); for (int i = 0; i < dims.nbDims; ++i) { - StrAppend(&out, dims.d[i], ","); + StrAppend(&out, dims.d[i], "[", DebugString(dims.type[i]), "],"); + } + StrAppend(&out, ")"); + return out; +} + +string DebugString(const nvinfer1::Permutation& permutation, int len) { + string out = "nvinfer1::Permutation("; + for (int i = 0; i < len; ++i) { + StrAppend(&out, permutation.order[i], ","); } StrAppend(&out, ")"); return out; @@ -198,16 +237,15 @@ string DebugString(const nvinfer1::Dims& dims) { string DebugString(const nvinfer1::ITensor& tensor) { return StrCat("nvinfer1::ITensor(@", reinterpret_cast(&tensor), - ", shape=", DebugString(tensor.getDimensions()), ")"); + ", name=", tensor.getName(), + ", dtype=", DebugString(tensor.getType()), + ", dims=", DebugString(tensor.getDimensions()), ")"); } -// Return whether or not the broadcast is feasible; -bool TensorRTGetBroadcastShape(const nvinfer1::Dims& operand_l, - const bool operand_l_is_tensor, - const nvinfer1::Dims& operand_r, - const bool operand_r_is_tensor, - nvinfer1::Dims* operand_l_new_shape, - nvinfer1::Dims* operand_r_new_shape) { +Status Converter::GetTrtBroadcastShape( + const TRT_TensorOrWeights& operand_l, const TRT_TensorOrWeights& operand_r, + nvinfer1::Dims* operand_l_new_dims, + nvinfer1::Dims* operand_r_new_dims) const { // *************************************************************************** // TensorRT Elementwise op supports broadcast but requires both tensor to be // of Identical rank @@ -232,52 +270,59 @@ bool TensorRTGetBroadcastShape(const nvinfer1::Dims& operand_l, // -> T: 1 1 1 -1 3 5 1 // -> W: 1 1 1 1 3 5 1 // *************************************************************************** - const int max_nb_dims = nvinfer1::Dims::MAX_DIMS + 1; - const size_t element_size = sizeof(operand_l.d[0]); - - // fill in dimensions - int l_s[max_nb_dims]; - std::fill(l_s, l_s + max_nb_dims, 1); - int l_d = operand_l_is_tensor ? operand_l.nbDims + 1 : operand_l.nbDims; - int r_s[max_nb_dims]; - std::fill(r_s, r_s + max_nb_dims, 1); - int r_d = operand_r_is_tensor ? operand_r.nbDims + 1 : operand_r.nbDims; - - int max_d = std::max(l_d, r_d); - std::memcpy(l_s + max_d - operand_l.nbDims, operand_l.d, - operand_l.nbDims * element_size); - std::memcpy(r_s + max_d - operand_r.nbDims, operand_r.d, - operand_r.nbDims * element_size); - - // set -1 for batch dimension, since batch size is not supposed to be - // broadcasted - if (operand_l_is_tensor) { - if (max_d != l_d) { // if broadcast beyond batch dimension, fail - return false; - } - l_s[0] = -1; - } - if (operand_r_is_tensor) { - if (max_d != r_d) { // if broadcast beyond batch dimension, fail - return false; - } - r_s[0] = -1; + if (!operand_l.is_tensor() && !operand_r.is_tensor()) { + return errors::InvalidArgument( + "Broadcasting requires at least one of the operands be tensors"); } - // compare broadcast feasibility - for (int i = max_d - 1; i >= 0; i--) { - if ((l_s[i] != r_s[i]) && (l_s[i] != 1) && (r_s[i] != 1)) { - return false; + const int max_nb_dims = nvinfer1::Dims::MAX_DIMS + 1; + auto compute_output_dims = + [max_nb_dims](const TRT_TensorOrWeights& input, int broadcast_num_dims, + int* output_dims_array, nvinfer1::Dims* output_dims) { + const nvinfer1::Dims input_dims = input.GetTrtDims(); + std::fill(output_dims_array, output_dims_array + max_nb_dims, 1); + std::copy(input_dims.d, input_dims.d + input_dims.nbDims, + output_dims_array + broadcast_num_dims - input_dims.nbDims); + if (input.is_tensor()) { + const int true_input_dims = input_dims.nbDims + 1; + if (true_input_dims < broadcast_num_dims) { + return errors::InvalidArgument( + "Broadcasting beyond batch dimension is not supported ", + "(tensor #dims ", true_input_dims, " vs broadcast #dims ", + broadcast_num_dims, ")"); + } + // Set the batch dimension to -1, since batch size is not supposed to + // be broadcasted. + output_dims_array[0] = -1; + } + // Copy to output dimensions (stripping the batch dimension). + output_dims->nbDims = broadcast_num_dims - 1; + std::copy(output_dims_array + 1, output_dims_array + broadcast_num_dims, + output_dims->d); + return Status::OK(); + }; + + // Compute the output dimensions. + const int broadcast_num_dims = + std::max(operand_l.GetTrtDims().nbDims + (operand_l.is_tensor() ? 1 : 0), + operand_r.GetTrtDims().nbDims + (operand_r.is_tensor() ? 1 : 0)); + int output_l[max_nb_dims], output_r[max_nb_dims]; + TF_RETURN_IF_ERROR(compute_output_dims(operand_l, broadcast_num_dims, + output_l, operand_l_new_dims)); + TF_RETURN_IF_ERROR(compute_output_dims(operand_r, broadcast_num_dims, + output_r, operand_r_new_dims)); + + // Compare broadcast feasibility + for (int i = 0; i < broadcast_num_dims; ++i) { + if ((output_l[i] != output_r[i]) && (output_l[i] != 1) && + (output_r[i] != 1)) { + return errors::InvalidArgument( + "Infeasible broadcast scheme (", "batch_dim: ", output_l[0], ", ", + DebugString(*operand_l_new_dims), " vs ", "batch_dim: ", output_r[0], + ", ", DebugString(*operand_r_new_dims), ")"); } } - - // output new TensorRT Dimension (stripping the batch dimension) - operand_l_new_shape->nbDims = max_d - 1; - std::memcpy(operand_l_new_shape->d, l_s + 1, (max_d - 1) * element_size); - operand_r_new_shape->nbDims = max_d - 1; - std::memcpy(operand_r_new_shape->d, r_s + 1, (max_d - 1) * element_size); - - return true; + return Status::OK(); } inline bool DimsEqual(const nvinfer1::Dims& dim_l, @@ -381,8 +426,8 @@ size_t TRT_ShapedWeights::size_bytes() const { string TRT_ShapedWeights::DebugString() const { return StrCat("TRT_ShapedWeights(shape=", convert::DebugString(shape_), - ", type=", type_, - ", values=", reinterpret_cast(GetValues()), ")"); + ", type=", DataTypeString(type_), ", values=", + reinterpret_cast(GetValues()), ")"); } // A fake ITensor implementation used to check whether the TF-TRT converter can @@ -425,7 +470,9 @@ class TRT_TensorOrWeights::SimpleITensor : public nvinfer1::ITensor { void setLocation(nvinfer1::TensorLocation location) override {} #if NV_TENSORRT_MAJOR >= 5 - bool setDynamicRange(float min, float max) override {} + bool setDynamicRange(float min, float max) override { return true; } + + float getDynamicRange() const override { return 0; } #endif private: @@ -489,8 +536,7 @@ nvinfer1::Dims TRT_TensorOrWeights::GetTrtDims() const { string TRT_TensorOrWeights::DebugString() const { string output = "TRT_TensorOrWeights(type="; if (is_tensor()) { - StrAppend(&output, "tensor @", reinterpret_cast(tensor()), - ", shape=", convert::DebugString(tensor()->getDimensions()), + StrAppend(&output, "tensor=", convert::DebugString(*tensor()), ", batch_size=", batch_size_); } else { StrAppend(&output, "weights=", weights_.DebugString()); @@ -627,11 +673,10 @@ void ReorderCKtoKC(const TRT_ShapedWeights& iweights, break; } case tensorflow::DataType::DT_HALF: { - Reorder2( - {k, c}, static_cast(iweights.GetValues()), - istrides, - static_cast(const_cast(oweights->GetValues())), - ostrides); + Reorder2({k, c}, static_cast(iweights.GetValues()), + istrides, static_cast( + const_cast(oweights->GetValues())), + ostrides); break; } default: @@ -753,8 +798,9 @@ Status TrtNodeValidator::ValidateNode( Status status = ConvertToTensorOrWeights( *pair.first, pair.second, graph_properties, &tensor_or_weights); if (!status.ok()) { - return errors::Internal("Failed to convert input with index ", i, - " to a TRT_TensorOrWeights"); + return errors::Internal( + "Failed to convert input with index ", i, + " to a TRT_TensorOrWeights: ", status.error_message()); } inputs.push_back(tensor_or_weights); } @@ -786,8 +832,11 @@ Status TrtNodeValidator::ConvertConstToWeights( return status; } -Converter::Converter(nvinfer1::INetworkDefinition* trt_network, bool is_fp16) - : trt_network_(trt_network), is_fp16_(is_fp16) { +Converter::Converter(nvinfer1::INetworkDefinition* trt_network, + int precision_mode, bool use_calibration) + : trt_network_(trt_network), + precision_mode_(precision_mode), + use_calibration_(use_calibration) { this->RegisterOpConverters(); } @@ -812,13 +861,18 @@ Status Converter::ConvertNode(const NodeDef& node_def) { TRT_TensorOrWeights& output = outputs[i]; string output_name = node_def.name(); if (i != 0) output_name = StrCat(output_name, ":", i); - // We need to check the name before setting it. For Identity op where the - // output is the input, if its input is one of the engine input, setting - // the name here will overwrite engine input bindings which will cause - // runtime error. + // We need to check the name before setting it. If the input is one of the + // engine input, setting the name here will overwrite engine input + // bindings which will cause runtime error. if (output.is_tensor()) { const char* tensor_name = output.tensor()->getName(); - if (tensor_name == nullptr || std::strlen(tensor_name) == 0) { + if (!tensorflow::str_util::StartsWith(tensor_name, kInputPHName)) { + // TRT initializes tensor names as "(Unnamed ITensor* N)". We rename + // them to match their corresponding TensorFlow name. + // Note: ITensors that we create internally within TF-TRT which are + // not inputs or outputs of a node will not be renamed. This is a + // potential cause of confusion if an error message or warning + // mentions the unnamed tensor. output.tensor()->setName(output_name.c_str()); } } @@ -930,11 +984,14 @@ Status Converter::TransposeTensor(nvinfer1::ITensor* input_tensor, nvinfer1::IShuffleLayer* layer = this->network()->addShuffle(*input_tensor); TFTRT_RETURN_ERROR_IF_NULLPTR(layer, "TF-TRT Internal Transpose"); + MarkQuantizationRangesAsInferrable(input_tensor, layer->getOutput(0)); nvinfer1::Permutation permutation; for (int32_t i = 0; i < dims.nbDims; ++i) { permutation.order[i] = order_with_batch_dim[i + 1] - 1; } + VLOG(1) << "TransposeTensor permutation: " + << DebugString(permutation, dims.nbDims); layer->setFirstTranspose(permutation); nvinfer1::Dims reshape_dims; @@ -950,6 +1007,38 @@ Status Converter::TransposeTensor(nvinfer1::ITensor* input_tensor, return tensorflow::Status::OK(); } +Status Converter::GetWeightRange(const TRT_ShapedWeights& weights, + float* out_min, float* out_max) const { + switch (weights.type_) { + case DataType::DT_FLOAT: { + auto inp = static_cast(weights.GetValues()); + auto result = std::minmax_element(inp, inp + weights.count()); + *out_min = *result.first; + *out_max = *result.second; + break; + } + case DataType::DT_HALF: { + auto inp = static_cast(weights.GetValues()); + auto result = std::minmax_element(inp, inp + weights.count()); + *out_min = Eigen::half_impl::half_to_float(*result.first); + *out_max = Eigen::half_impl::half_to_float(*result.second); + break; + } + case DataType::DT_INT32: { + auto inp = static_cast(weights.GetValues()); + auto result = std::minmax_element(inp, inp + weights.count()); + *out_min = static_cast(*result.first); + *out_max = static_cast(*result.second); + break; + } + default: + return errors::Unimplemented( + "Data type not supported for GetWeightRange: ", + DataTypeString(weights.type_)); + } + return Status::OK(); +} + Status Converter::PrepareTensorForShape(const TRT_TensorOrWeights& input, const nvinfer1::Dims& dims, const nvinfer1::ITensor** tensor) { @@ -964,8 +1053,9 @@ Status Converter::PrepareTensorForShape(const TRT_TensorOrWeights& input, } if (can_check_shapes && TrtDimsNumElements(input.GetTrtDims()) != TrtDimsNumElements(dims)) { - return tensorflow::errors::InvalidArgument( - "Reshape shapes are not compatible."); + return errors::InvalidArgument("Reshape shapes are not compatible (", + DebugString(input.GetTrtDims()), " vs ", + DebugString(dims), ")"); } if (input.is_tensor()) { @@ -976,6 +1066,8 @@ Status Converter::PrepareTensorForShape(const TRT_TensorOrWeights& input, *const_cast(input.tensor())); TFTRT_RETURN_ERROR_IF_NULLPTR(layer, "TF-TRT Internal Reshape"); layer->setReshapeDimensions(dims); + MarkQuantizationRangesAsInferrable( + const_cast(input.tensor()), layer->getOutput(0)); *tensor = layer->getOutput(0); } } else { @@ -983,10 +1075,123 @@ Status Converter::PrepareTensorForShape(const TRT_TensorOrWeights& input, this->network()->addConstant(dims, input.weights().GetTrtWeights()); TFTRT_RETURN_ERROR_IF_NULLPTR(layer, "TF-TRT Internal Reshape"); *tensor = layer->getOutput(0); + if (precision_mode() == INT8MODE && !use_calibration()) { + // If we are in int8 mode and not calibrating, we need to explicitly set a + // quantization range for the output tensor of the IConstantLayer. Here we + // set the range to [min(weights), max(weights)]. + float min_range = 0.0f; + float max_range = 0.0f; + TF_RETURN_IF_ERROR( + GetWeightRange(input.weights(), &min_range, &max_range)); + // Avoid setting range to 0 because TRT will throw an error. If the + // weights are zero then the range doesn't matter: using 127.0f should + // ensure the quantized weight will be exactly zero. + if (min_range == 0.0f && max_range == 0.0f) { + min_range = -127.0f; + max_range = 127.0f; + } + ProvideQuantizationRange(const_cast(*tensor), + min_range, max_range); + } } return tensorflow::Status::OK(); } +void Converter::MarkQuantizationRangesAsInferrable(nvinfer1::ITensor* input, + nvinfer1::ITensor* output) { + quantization_infer_.push_back({input, output}); + quantization_infer_.push_back({output, input}); +} + +void Converter::ProvideQuantizationRange(nvinfer1::ITensor* tensor, + float min_range, float max_range) { + float symmetric_range = std::max(std::abs(min_range), std::abs(max_range)); + quantization_ranges_[tensor] = symmetric_range; +} + +void Converter::MaybeApplyQuantizationRanges() { + if (precision_mode() != INT8MODE) return; + + // Infer ranges across marked ops. + PropagateQuantizationRanges(); + // Apply ranges. +#if NV_TENSORRT_MAJOR >= 5 + for (auto pair : quantization_ranges_) { + nvinfer1::ITensor* tensor = pair.first; + const float range = pair.second; + VLOG(1) << "Setting range for: " << tensor->getName() << ": " << range; + // TODO(laigd): if 'tensor' already has a range set which doesn't match + // 'range', it should report error. + tensor->setDynamicRange(-range, range); + } +#endif + + // Warn user about tensors that are missing ranges. If TRT fuses some layers + // then these tensors may not actually be required, which is why this is + // just a warning. If we are still missing ranges even after fusion, + // Builder::buildCudaEngine() will return nullptr and we will catch the + // error at that point. + if (!use_calibration()) { + // Get all tensors from network + std::set all_tensors; + for (int i = 0; i < this->network()->getNbLayers(); i++) { + nvinfer1::ILayer* layer = this->network()->getLayer(i); + for (int j = 0; j < layer->getNbInputs(); j++) { + all_tensors.insert(layer->getInput(j)); + } + for (int j = 0; j < layer->getNbOutputs(); j++) { + all_tensors.insert(layer->getOutput(j)); + } + } + // Find tensors with no ranges + for (auto tensor : all_tensors) { + if (!quantization_ranges_.count(tensor)) { + // Note: there may be some warnings for "(Unnamed ITensor* N)". These + // are tensors which are created internally by TF-TRT. The ranges for + // these unnamed ITensors are always inferred from user provided ranges, + // thus there will also be a warning for the range(s) the user missed. + LOG(WARNING) << "Quantization range was not found for " + << tensor->getName() << ". " + << "This is okay if TensorRT does not need the range " + << "(e.g. due to node fusion)."; + } + } + } +} + +void Converter::PropagateQuantizationRanges() { + // Propagate ranges across edges in quantization_infer_ until no new + // information is added. + // Note: this function modifies quantization_infer_, it might be better to + // modify a copy instead if we for some reason need quantization_infer_ + // later. + bool information_added = true; + while (information_added) { + information_added = false; + for (auto it = quantization_infer_.begin(); + it != quantization_infer_.end();) { + auto input_tensor_range = quantization_ranges_.find(it->first); + auto output_tensor_range = quantization_ranges_.find(it->second); + if (input_tensor_range != quantization_ranges_.end() && + output_tensor_range == quantization_ranges_.end()) { + // Input has range but output doesn't: copy range + // TODO(laigd): consider reporting error if it a different range is + // already set. + quantization_ranges_[it->second] = input_tensor_range->second; + information_added = true; + VLOG(1) << "Copy quantization range: " << it->first->getName() << " -> " + << it->second->getName(); + } + // We can remove edges when the output range is known + if (quantization_ranges_.find(it->second) != quantization_ranges_.end()) { + it = quantization_infer_.erase(it); + } else { + ++it; + } + } + } +} + Status Converter::GetInputs(const tensorflow::NodeDef& node_def, std::vector* inputs) const { for (auto const& input_name : node_def.input()) { @@ -1043,12 +1248,11 @@ TRT_ShapedWeights ConvertFP32ToFP16(TrtWeightStore* store, } // **************************************************************************** -// Constant folding functions -// TODO(jie): once optimizer kicks in, we should have done constant folding -// there. +// Constant folding functions for weights. +// TODO(laigd): we should probably use eigen directly. // ***************************************************************************** struct LambdaFactory { - enum class OP_CATEGORY : int { RSQRT = 0, NEG, ADD, MUL, SUB, RECIP }; + enum class OP_CATEGORY : int { RSQRT = 0, NEG, RECIP }; OP_CATEGORY op; template @@ -1063,84 +1267,10 @@ struct LambdaFactory { case OP_CATEGORY::RECIP: return [](T t) -> T { return 1.0 / t; }; default: - VLOG(2) << "Not supported op for unary: " << static_cast(op); + LOG(ERROR) << "Not supported op for unary: " << static_cast(op); return nullptr; } } - - template - std::function binary() { - switch (op) { - case OP_CATEGORY::ADD: - return [](T l, T r) -> T { return l + r; }; - case OP_CATEGORY::SUB: - return [](T l, T r) -> T { return l - r; }; - case OP_CATEGORY::MUL: - return [](T l, T r) -> T { return l * r; }; - default: - LOG(WARNING) << "Not supported op for binary: " << static_cast(op); - } - return [](T l, T r) -> T { - LOG(FATAL) << "Unsupported op type "; - return l; - }; - } - - template - std::function broadcast_r(T val) { - VLOG(2) << "LAMBDA VAL : " << val; - switch (op) { - case OP_CATEGORY::ADD: - return [val](T l) -> T { - VLOG(2) << "LAMBDA VAL : " << val; - return l + val; - }; - case OP_CATEGORY::SUB: - return [val](T l) -> T { - VLOG(2) << "LAMBDA VAL : " << val; - return l - val; - }; - case OP_CATEGORY::MUL: - return [val](T l) -> T { - VLOG(2) << "LAMBDA VAL : " << val; - return l * val; - }; - default: - LOG(WARNING) << "Not supported op for binary: " << static_cast(op); - } - return [val](T l) -> T { - LOG(FATAL) << "Unsupported op type "; - return l; - }; - } - - template - std::function broadcast_l(T val) { - VLOG(2) << "LAMBDA VAL : " << val; - switch (op) { - case OP_CATEGORY::ADD: - return [val](T l) -> T { - VLOG(2) << "LAMBDA VAL : " << val; - return val + l; - }; - case OP_CATEGORY::SUB: - return [val](T l) -> T { - VLOG(2) << "LAMBDA VAL : " << val; - return val - l; - }; - case OP_CATEGORY::MUL: - return [val](T l) -> T { - VLOG(2) << "LAMBDA VAL : " << val; - return val * l; - }; - default: - LOG(ERROR) << "Not supported op for binary: " << static_cast(op); - } - return [val](T l) -> T { - LOG(FATAL) << "Unsupported op type "; - return l; - }; - } }; template <> @@ -1148,15 +1278,18 @@ std::function LambdaFactory::unary() { switch (op) { case OP_CATEGORY::RSQRT: { VLOG(2) << "RSQRT GETS DONE"; - return [](Eigen::half t) -> Eigen::half { + return [](Eigen::half t) { return Eigen::half(1.0 / sqrt(static_cast(t))); }; } case OP_CATEGORY::NEG: - return [](Eigen::half t) -> Eigen::half { return -t; }; - // TODO(aaroey): can we support RECIP? + return [](Eigen::half t) { return -t; }; + case OP_CATEGORY::RECIP: + return [](Eigen::half t) { + return Eigen::half(1.0 / static_cast(t)); + }; default: - VLOG(2) << "Not supported op for unary: " << static_cast(op); + LOG(ERROR) << "Not supported op for unary: " << static_cast(op); return nullptr; } } @@ -1188,50 +1321,48 @@ tensorflow::Status UnaryCompute(const TRT_ShapedWeights& iweights, return tensorflow::Status::OK(); } +// If swapped_inputs is false, 'tensor' is the left operand and 'weights' is the +// right operand. If swapped_inputs is true, those two are swapped. +// // TODO(jie): broadcast is needed yet not implemented. -// Only implemented channel wise for the time being -tensorflow::Status BinaryTensorOpWeight(OpConverterParams* params, - const nvinfer1::ITensor* tensor, - TRT_ShapedWeights weights, - bool swapped_inputs) { +// Only implemented channel wise for the time being. +Status BinaryTensorOpWeight(OpConverterParams* params, + const nvinfer1::ITensor* tensor, + TRT_ShapedWeights weights, bool swapped_inputs) { + static const std::unordered_set supported_ops = {"Sub", "Add", "Mul", + "Div", "RealDiv"}; const auto& node_def = params->node_def; - // tensor is the left operand while weights is the right operand; - // when swapped_inputs set to true, those two are swapped. - // TODO(aaroey): use a set. - if (node_def.op() != "Sub" && node_def.op() != "Add" && - node_def.op() != "Mul" && node_def.op() != "Div" && - node_def.op() != "RealDiv") { - return tensorflow::errors::Unimplemented( - "op not supported: " + node_def.op() + ", at: " + node_def.name()); + if (!supported_ops.count(node_def.op())) { + return errors::Unimplemented(node_def.op(), " is not supported, at ", + node_def.name()); } - // Check type consistency - nvinfer1::DataType ttype; - TF_RETURN_IF_ERROR(ConvertDType(weights.type_, &ttype)); + // Check type consistency. + nvinfer1::DataType trt_dtype; + TF_RETURN_IF_ERROR(ConvertDType(weights.type_, &trt_dtype)); - // Check scale mode + // Check scale mode. auto dims_w = weights.shape_; - auto dims_t = tensor->getDimensions(); + const auto dims_t = tensor->getDimensions(); // TODO(jie): addScale checks for input tensor dimension if (dims_t.nbDims != 3) { - return tensorflow::errors::InvalidArgument( - "addScale requires tensor with rank 3, " + node_def.name()); + return errors::InvalidArgument("addScale requires tensor with rank 3, at ", + node_def.name()); } - // default to element-wise + // Default to element-wise auto scale_mode = nvinfer1::ScaleMode::kELEMENTWISE; // TODO(jie): maybe use a permutation instead to support more cases; - bool permutation_flag = false; + bool need_to_permute = false; if (weights.count() == 1) { - VLOG(2) << "UNIFORM"; scale_mode = nvinfer1::ScaleMode::kUNIFORM; } else { - // no broadcasting on Batch dimension; - VLOG(2) << "WEIGHTS DIM: " << dims_w.nbDims - << " tensor DIM: " << dims_t.nbDims; + VLOG(2) << "weights dims: " << DebugString(dims_w) + << "; tensor dims: " << DebugString(dims_t); + // Make sure no broadcasting on batch dimension. if (dims_w.nbDims == dims_t.nbDims + 1) { if (dims_w.d[0] == 1) { for (int i = 1; i < dims_w.nbDims; i++) { @@ -1239,72 +1370,70 @@ tensorflow::Status BinaryTensorOpWeight(OpConverterParams* params, } dims_w.nbDims--; } else { - return tensorflow::errors::InvalidArgument( - "Binary op cannot operate on batch, " + node_def.name()); + return errors::InvalidArgument("Binary op cannot operate on batch, at ", + node_def.name()); } } if (dims_w.nbDims == dims_t.nbDims && dims_w.d[0] == dims_t.d[0]) { scale_mode = nvinfer1::ScaleMode::kELEMENTWISE; - // default is element; + // Default is element-wise for (int i = 1; i < dims_w.nbDims; i++) { if (dims_w.d[i] != dims_t.d[i]) { - // if dimension does not match, switch back to channel; - VLOG(2) << "channel"; + // If dimension does not match, switch back to per-channel scale_mode = nvinfer1::ScaleMode::kCHANNEL; break; } } - // if channel as candidate, validate it + // If the mode is per-channel, since channel dimension is assumed to be + // the third to last dimension, we need to make sure all other dimensions + // have size 1. if (scale_mode == nvinfer1::ScaleMode::kCHANNEL) { for (int i = 1; i < dims_w.nbDims; i++) { if (dims_w.d[i] != 1) - return tensorflow::errors::InvalidArgument( - "Weight shape not compatible at, " + node_def.name()); + return errors::InvalidArgument( + "Weight dims not compatible for channel-wise broadcast at ", + node_def.name()); } - } else { - VLOG(2) << "elementwise"; } } else if (dims_w.nbDims == 1 && dims_w.d[0] == dims_t.d[dims_t.nbDims - 1]) { - // channel wise and broadcast required; - permutation_flag = true; + // Channel wise and broadcast required. We compare the last dimension of + // the tensor shape because of tensorflow default broadcasting rules. + need_to_permute = true; scale_mode = nvinfer1::ScaleMode::kCHANNEL; } else { - return tensorflow::errors::InvalidArgument( - "Weight shape not compatible at, " + node_def.name()); + return errors::InvalidArgument("Weight dims not compatible at ", + node_def.name()); } } + // TODO(laigd): we should add validation_only support in TransposeTensor() and + // PrepareTensorForShape(). + if (params->validation_only) return Status::OK(); - // transpose last dimension + // Transpose last dimension. std::vector permutation(dims_t.nbDims + 1); - if (permutation_flag) { - if (scale_mode == nvinfer1::ScaleMode::kCHANNEL && dims_t.nbDims > 1) { - // we swap the last dimension into channel for trt. - // because of tensorflow default broadcasting rules. - for (int i = 0; i < static_cast(permutation.size()); i++) { - permutation[i] = i; - } - permutation[1] = dims_t.nbDims; - permutation[dims_t.nbDims] = 1; - TF_RETURN_IF_ERROR(params->converter->TransposeTensor( - const_cast(tensor), permutation, &tensor)); - } else { - return tensorflow::errors::InvalidArgument( - "Transpose cannot be applied, " + node_def.name()); - } + if (need_to_permute) { + // We swap the last dimension into channel for trt, because of tensorflow + // default broadcasting rules. + for (int i = 0; i < static_cast(permutation.size()); i++) { + permutation[i] = i; + } + permutation[1] = dims_t.nbDims; + permutation[dims_t.nbDims] = 1; + TF_RETURN_IF_ERROR(params->converter->TransposeTensor( + const_cast(tensor), permutation, &tensor)); } - if (params->converter->is_fp16()) { + if (params->converter->precision_mode() == FP16MODE) { weights = ConvertFP32ToFP16(params->weight_store, weights); } - // prepare weights + // Prepare weights TRT_ShapedWeights shift_weights(weights.type_); TRT_ShapedWeights scale_weights(weights.type_); TRT_ShapedWeights power_weights(weights.type_); - // Maybe I should do a switch if (node_def.op() == "Sub") { if (swapped_inputs) { shift_weights = weights; @@ -1312,6 +1441,10 @@ tensorflow::Status BinaryTensorOpWeight(OpConverterParams* params, *const_cast(tensor), nvinfer1::UnaryOperation::kNEG); TFTRT_RETURN_ERROR_IF_NULLPTR(layer, node_def.name()); + // Since quantization ranges are symmetric, the same range as the input + // will work for the negation of the input. + params->converter->MarkQuantizationRangesAsInferrable( + const_cast(tensor), layer->getOutput(0)); tensor = layer->getOutput(0); } else { TRT_ShapedWeights neg_weights = @@ -1323,6 +1456,25 @@ tensorflow::Status BinaryTensorOpWeight(OpConverterParams* params, } } else if (node_def.op() == "Div" || node_def.op() == "RealDiv") { if (swapped_inputs) { + // We need to infer the quantization range for this intermediate tensor. + // + // x -> [Recip] -> 1/x -> [Scale] -> s/x + // ^ + // need range for this + // + // We have the quantization scales for x and s/x - can we divide the scale + // for s/x by s? Only if it is a scalar. + // + // Because of this issue, fall back to BinaryTensorOpTensor if we are + // doing INT8 with no calibration. There is most likely no performance + // penalty by falling back here. + if (params->converter->precision_mode() == INT8MODE && + !params->converter->use_calibration()) { + return errors::Unimplemented( + "Intermediate quantization range cannot be determined without" + " calibration. Falling back to BinaryTensorOpTensor for ", + node_def.op(), ", at ", node_def.name()); + } scale_weights = weights; nvinfer1::IUnaryLayer* layer = params->converter->network()->addUnary( *const_cast(tensor), @@ -1342,8 +1494,8 @@ tensorflow::Status BinaryTensorOpWeight(OpConverterParams* params, } else if (node_def.op() == "Add") { shift_weights = weights; } else { - return tensorflow::errors::Unimplemented("Binary op not supported: " + - node_def.op()); + // This should not happen. + return errors::Unimplemented("Binary op not supported at ", node_def.op()); } nvinfer1::IScaleLayer* layer = params->converter->network()->addScale( @@ -1353,8 +1505,8 @@ tensorflow::Status BinaryTensorOpWeight(OpConverterParams* params, TFTRT_RETURN_ERROR_IF_NULLPTR(layer, node_def.name()); const nvinfer1::ITensor* output_tensor = layer->getOutput(0); - // transpose back dimension - if (permutation_flag) { + // Transpose back dimension + if (need_to_permute) { TF_RETURN_IF_ERROR(params->converter->TransposeTensor( const_cast(output_tensor), permutation, &output_tensor)); @@ -1398,7 +1550,7 @@ tensorflow::Status ConvertConv2DHelper(OpConverterParams* params, int group) { return tensorflow::errors::Internal( "Conv2D expects kernel of dimension 4, at: " + node_def.name()); } - if (params->converter->is_fp16()) { + if (params->converter->precision_mode() == FP16MODE) { weights_rsck = ConvertFP32ToFP16(params->weight_store, inputs.at(1).weights()); } @@ -1445,6 +1597,8 @@ tensorflow::Status ConvertConv2DHelper(OpConverterParams* params, int group) { nvinfer1::DimsHW(padding[0].first, padding[1].first), nvinfer1::DimsHW(padding[0].second, padding[1].second)); TFTRT_RETURN_ERROR_IF_NULLPTR(pad_layer, node_def.name()); + params->converter->MarkQuantizationRangesAsInferrable( + const_cast(tensor), pad_layer->getOutput(0)); padding = {{0, 0}, {0, 0}}; tensor = pad_layer->getOutput(0); VLOG(2) << "TENSOR after: " << DebugString(tensor->getDimensions()); @@ -1486,9 +1640,9 @@ tensorflow::Status ConvertConv2DHelper(OpConverterParams* params, params->node_def.name()); } -tensorflow::Status BinaryTensorOpTensor(OpConverterParams* params, - const TRT_TensorOrWeights& operand_l, - const TRT_TensorOrWeights& operand_r) { +Status BinaryTensorOpTensor(OpConverterParams* params, + const TRT_TensorOrWeights& operand_l, + const TRT_TensorOrWeights& operand_r) { const auto& node_def = params->node_def; static const std::unordered_map ops{ {"Add", nvinfer1::ElementWiseOperation::kSUM}, @@ -1499,50 +1653,52 @@ tensorflow::Status BinaryTensorOpTensor(OpConverterParams* params, {"Minimum", nvinfer1::ElementWiseOperation::kMIN}, {"Maximum", nvinfer1::ElementWiseOperation::kMAX}, }; + auto op_pair = ops.find(node_def.op()); + if (op_pair == ops.end()) { + return errors::Unimplemented("Binary op ", node_def.op(), + " not supported at: ", node_def.name()); + } - const nvinfer1::ITensor* tensor_l; - const nvinfer1::ITensor* tensor_r; - - nvinfer1::Dims dim_l; - nvinfer1::Dims dim_r; - - if (!TensorRTGetBroadcastShape(operand_l.GetTrtDims(), operand_l.is_tensor(), - operand_r.GetTrtDims(), operand_r.is_tensor(), - &dim_l, &dim_r)) { - return tensorflow::errors::InvalidArgument( - "Binary op broadcast scheme not supported by TensorRT op: " + - node_def.op() + ", at: " + node_def.name()); + nvinfer1::Dims broadcasted_dims_l, broadcasted_dims_r; + Status status = params->converter->GetTrtBroadcastShape( + operand_l, operand_r, &broadcasted_dims_l, &broadcasted_dims_r); + if (!status.ok()) { + return errors::InvalidArgument( + "Unsupported binary op broadcast scheme for op ", node_def.name(), ": ", + status.error_message()); } + if (params->validation_only) return Status::OK(); - TF_RETURN_IF_ERROR( - params->converter->PrepareTensorForShape(operand_l, dim_l, &tensor_l)); - TF_RETURN_IF_ERROR( - params->converter->PrepareTensorForShape(operand_r, dim_r, &tensor_r)); + const nvinfer1::ITensor* tensor_l = nullptr; + const nvinfer1::ITensor* tensor_r = nullptr; + status = params->converter->PrepareTensorForShape( + operand_l, broadcasted_dims_l, &tensor_l); + if (status.ok()) { + status = params->converter->PrepareTensorForShape( + operand_r, broadcasted_dims_r, &tensor_r); + } + if (!status.ok()) { + return errors::Internal("Failed to convert binary op ", node_def.name(), + ": ", status.error_message()); + } - // get trt type & shape + // Check type consistency. TFAttrs attrs(node_def); - // maybe this part has to be moved into the block of rsqrt later nvinfer1::DataType dtype = attrs.get("T"); + TFTRT_CHECK_EQ_TYPE(tensor_l->getType(), dtype) + << DebugString(tensor_l->getType()) << " vs " << DebugString(dtype); + TFTRT_CHECK_EQ_TYPE(tensor_r->getType(), dtype) + << DebugString(tensor_r->getType()) << " vs " << DebugString(dtype); - // check type consistency - TFTRT_CHECK_EQ_TYPE(tensor_l->getType(), dtype); - TFTRT_CHECK_EQ_TYPE(tensor_r->getType(), dtype); - auto op_pair = ops.find(node_def.op()); - if (op_pair == ops.end()) { - return tensorflow::errors::Unimplemented( - "binary op: ", node_def.op(), " not supported at: ", node_def.name()); - } - + // Add ElementWise layer. nvinfer1::IElementWiseLayer* layer = params->converter->network()->addElementWise( - // TODO(aaroey): will tensor_l/tensor_r get modified? *const_cast(tensor_l), *const_cast(tensor_r), op_pair->second); TFTRT_RETURN_ERROR_IF_NULLPTR(layer, node_def.name()); - nvinfer1::ITensor* output_tensor = layer->getOutput(0); - // pass the output + // Pass the output params->outputs->push_back(TRT_TensorOrWeights(output_tensor)); return tensorflow::Status::OK(); } @@ -1789,6 +1945,8 @@ tensorflow::Status ConvertPool(OpConverterParams* params) { nvinfer1::DimsHW(padding[0].first, padding[1].first), nvinfer1::DimsHW(padding[0].second, padding[1].second)); TFTRT_RETURN_ERROR_IF_NULLPTR(pad_layer, node_def.name()); + params->converter->MarkQuantizationRangesAsInferrable( + const_cast(tensor), pad_layer->getOutput(0)); padding = {{0, 0}, {0, 0}}; tensor = pad_layer->getOutput(0); } @@ -1796,6 +1954,11 @@ tensorflow::Status ConvertPool(OpConverterParams* params) { nvinfer1::IPoolingLayer* layer = params->converter->network()->addPooling( *const_cast(tensor), type, ksize); TFTRT_RETURN_ERROR_IF_NULLPTR(layer, node_def.name()); + // TODO(tmorris): Average pooling may not be entirely safe to infer + // quantization range through (at least forwards - backwards should be fine). + // Max pooling is okay. + params->converter->MarkQuantizationRangesAsInferrable( + const_cast(tensor), layer->getOutput(0)); layer->setStride(stride); layer->setPadding({padding[0].first, padding[1].first}); @@ -1813,110 +1976,290 @@ tensorflow::Status ConvertPool(OpConverterParams* params) { } tensorflow::Status ConvertActivation(OpConverterParams* params) { - const nvinfer1::ITensor* tensor = params->inputs.at(0).tensor(); + const auto& inputs = params->inputs; + const auto& node_def = params->node_def; + if (inputs.size() != 1) { + return tensorflow::errors::InvalidArgument( + node_def.op(), " expects one input, at ", node_def.name()); + } + if (!inputs.at(0).is_tensor()) { + return tensorflow::errors::Unimplemented( + node_def.op(), " is only implemented for tensors, at ", + node_def.name()); + } + static const std::unordered_map ops{ + {"Relu", nvinfer1::ActivationType::kRELU}, + {"Sigmoid", nvinfer1::ActivationType::kSIGMOID}, + {"Tanh", nvinfer1::ActivationType::kTANH}, + }; + auto op_pair = ops.find(node_def.op()); + if (op_pair == ops.end()) { + return tensorflow::errors::Unimplemented("Activation op: ", node_def.op(), + " not supported at: ", + node_def.name()); + } + if (params->validation_only) return tensorflow::Status::OK(); + + // Start conversion. + const nvinfer1::ITensor* tensor = inputs.at(0).tensor(); nvinfer1::IActivationLayer* layer = params->converter->network()->addActivation( - *const_cast(tensor), - nvinfer1::ActivationType::kRELU); - TFTRT_RETURN_ERROR_IF_NULLPTR(layer, params->node_def.name()); + *const_cast(tensor), op_pair->second); + TFTRT_RETURN_ERROR_IF_NULLPTR(layer, node_def.name()); nvinfer1::ITensor* output_tensor = layer->getOutput(0); + // Set quantization range for output of Sigmoid, Tanh. + if (node_def.op() == "Sigmoid") { + params->converter->ProvideQuantizationRange(output_tensor, 0.0f, 1.0f); + } else if (node_def.op() == "Tanh") { + params->converter->ProvideQuantizationRange(output_tensor, -1.0f, 1.0f); + } params->outputs->push_back(TRT_TensorOrWeights(output_tensor)); return tensorflow::Status::OK(); } -tensorflow::Status ConvertScale(OpConverterParams* params) { +Status ConvertQuantize(OpConverterParams* params) { const auto& inputs = params->inputs; const auto& node_def = params->node_def; - if (inputs.size() != 2 || !inputs.at(0).is_tensor() || - !inputs.at(1).is_weights()) { + if ((inputs.size() == 0) || + (node_def.op() == "FakeQuantWithMinMaxArgs" && inputs.size() != 1) || + (node_def.op() == "FakeQuantWithMinMaxVars" && inputs.size() != 3) || + (node_def.op() == "QuantizeAndDequantizeV2" && inputs.size() != 3) || + (node_def.op() == "QuantizeAndDequantizeV3" && inputs.size() != 4)) { + return errors::InvalidArgument("Invalid number of inputs for ", + node_def.op(), ", at ", node_def.name()); + } + if (inputs.at(0).is_weights()) { + // TensorRT will automatically quantize weights, so we will ignore ranges + // for weights. + params->outputs->push_back(inputs.at(0)); + return Status::OK(); + } + float min_range = 0.0f; + float max_range = 0.0f; + if (node_def.op() == "FakeQuantWithMinMaxArgs") { + // Get ranges via node attributes. + TFAttrs attrs(node_def); + if (attrs.count("min") == 0 || attrs.count("max") == 0) { + return errors::InvalidArgument("Min or max attribute not found for ", + node_def.op(), " at ", node_def.name()); + } + min_range = attrs.get("min"); + max_range = attrs.get("max"); + } else if (node_def.op() == "FakeQuantWithMinMaxVars" || + node_def.op() == "QuantizeAndDequantizeV2" || + node_def.op() == "QuantizeAndDequantizeV3") { + // Get ranges via inputs. + if (!inputs.at(1).is_weights() || !inputs.at(2).is_weights()) { + return errors::InvalidArgument("Min and max inputs for ", node_def.op(), + " must be weights not tensors, at ", + node_def.name()); + } + auto get_weights_value = [&inputs](int index) { + auto raw_weights = static_cast( + const_cast(inputs.at(index).weights().GetValues())); + return raw_weights[0]; + }; + min_range = get_weights_value(1); + max_range = get_weights_value(2); + } else { + return errors::InvalidArgument("Unknown quantization op ", node_def.op(), + ", at ", node_def.name()); + } + if (params->validation_only) return Status::OK(); + + // Store ranges for tensor + params->converter->ProvideQuantizationRange( + const_cast(inputs.at(0).tensor()), min_range, + max_range); + // Sometimes, TRT may not quantize a tensor, either because it chooses to + // execute a higher precision kernel or because of op fusion. In these cases, + // accuracy will suffer if the model was trained to expect quantization at + // that tensor. We should consider adding a clip(tensor, min_range, max_range) + // operation here to ensure that any arbitrarily placed quantize node will + // execute as expected. However, this will negatively affect performance. If + // users train their models in a way which models inference as close as + // possible (i.e. not quantizing in place where fusion will occur), then there + // is no problem with the current implementation. + params->outputs->push_back(inputs.at(0)); + return Status::OK(); +} + +// TODO(pdavoodi): we should update relu6 implementation once TensorRT supports +// Relu6 natively. +tensorflow::Status ConvertRelu6(OpConverterParams* params) { + const auto& inputs = params->inputs; + const auto& node_def = params->node_def; + if (inputs.size() != 1) { + return tensorflow::errors::InvalidArgument( + "Invalid number of inputs for Relu6, at ", node_def.name()); + } + if (inputs.at(0).is_weights()) { return tensorflow::errors::Unimplemented( - "ConvertScale only supports tensorweight: ", node_def.name()); + "Relu6 is only implemented for tensors, not weights, at ", + node_def.name()); } + if (params->validation_only) return Status::OK(); + // *************************************************************************** + // TensorRT does not implement Relu6 natively. This function converts Relu6 op + // to available TensorRT ops: Relu6(x) = min(Relu(x), 6) + // *************************************************************************** + // Input Tensor const nvinfer1::ITensor* tensor = inputs.at(0).tensor(); - TRT_ShapedWeights weights = inputs.at(1).weights(); - if (params->converter->is_fp16()) { - weights = ConvertFP32ToFP16(params->weight_store, inputs.at(1).weights()); - } - TRT_ShapedWeights empty_weights(weights.type_); - TFAttrs attrs(node_def); + // Relu operation i.e. Relu(x) = max(0, x) + nvinfer1::IActivationLayer* relu_layer = + params->converter->network()->addActivation( + *const_cast(tensor), + nvinfer1::ActivationType::kRELU); + TFTRT_RETURN_ERROR_IF_NULLPTR(relu_layer, node_def.name()); + + // Large range of relu is problematic during quantization in INT8 precision + // mode. Setting dynamic range of relu = [0.f, 6.0f] helps with quantization. + // TRT only uses dynamic ranges in INT8 precision mode, + // and this does not affect the FP32 path. + params->converter->ProvideQuantizationRange(relu_layer->getOutput(0), 0.0f, + 6.0f); + + // Create a constant layer to store the floating point weight i.e. 6.0f This + // tensor will be broadcasted uniformly during elementwise `min` operation. + // The constant has to have the same rank as the input in order for TRT to + // broadcast + nvinfer1::Dims dims; + dims.nbDims = relu_layer->getOutput(0)->getDimensions().nbDims; + for (int i = 0; i < dims.nbDims; i++) { + dims.d[i] = 1; + } + TRT_ShapedWeights weights = params->weight_store->GetTempWeights( + tensorflow::DataType::DT_FLOAT, dims); + auto weights_ptr = + static_cast(const_cast(weights.GetValues())); + weights_ptr[0] = 6.0f; + nvinfer1::IConstantLayer* const6_layer = + params->converter->network()->addConstant(dims, weights.GetTrtWeights()); + TFTRT_RETURN_ERROR_IF_NULLPTR(const6_layer, node_def.name()); + params->converter->ProvideQuantizationRange(const6_layer->getOutput(0), 0.0f, + 6.0f); + + // ElementWise Min Operation + // Min op is a nop for INT8 execution path, as the input tensor + // to this layer will only have values in range [0.f, 6.0f]. + const nvinfer1::ITensor* tensor_l = relu_layer->getOutput(0); + const nvinfer1::ITensor* tensor_r = const6_layer->getOutput(0); + nvinfer1::IElementWiseLayer* relu6_layer = + params->converter->network()->addElementWise( + *const_cast(tensor_l), + *const_cast(tensor_r), + nvinfer1::ElementWiseOperation::kMIN); + TFTRT_RETURN_ERROR_IF_NULLPTR(relu6_layer, node_def.name()); + nvinfer1::ITensor* output_tensor = relu6_layer->getOutput(0); + params->converter->ProvideQuantizationRange(output_tensor, 0.0f, 6.0f); - const auto data_format = attrs.get("data_format"); - int channel_index; - const auto dims = tensor->getDimensions(); - if (data_format == "NHWC") { - // 1). NHWC is really N+C - channel_index = dims.nbDims - 1; // batch dimension is implicit here! - } else { - // 2). NCHW is really N+CHW - channel_index = 0; // batch dimension is implicit here! - } + params->outputs->push_back(TRT_TensorOrWeights(output_tensor)); + return Status::OK(); +} - nvinfer1::Permutation permutation; - for (int32_t i = 0; i < dims.nbDims; ++i) { - permutation.order[i] = i; +tensorflow::Status ConvertBiasAdd(OpConverterParams* params) { + const auto& inputs = params->inputs; + const auto& node_def = params->node_def; + if (inputs.size() != 2 || !inputs.at(0).is_tensor() || + !inputs.at(1).is_weights()) { + return errors::InvalidArgument("Input expects tensor and weights, at ", + node_def.name()); } + if (params->validation_only) return Status::OK(); - if (channel_index >= 0) { + nvinfer1::ITensor* tensor = + const_cast(inputs.at(0).tensor()); + const nvinfer1::Dims original_dims = tensor->getDimensions(); + TFAttrs attrs(node_def); + const string data_format = attrs.get("data_format"); + const int channel_index = + (data_format == "NHWC" ? original_dims.nbDims - 1 : 0); + + nvinfer1::Permutation permutation; + if (channel_index != 0) { + // Permute the dimensions so that the channel dimension is the first + // dimension. + for (int i = 0; i < original_dims.nbDims; ++i) { + permutation.order[i] = i; + } permutation.order[0] = channel_index; permutation.order[channel_index] = 0; - } else { - return tensorflow::errors::Unimplemented( - "TFTRT::BiasAdd cannot apply on batch dimension, at ", node_def.name()); + VLOG(1) << "ConvertBiasAdd permutation: " + << DebugString(permutation, original_dims.nbDims); } // TensorRT addScale requires input to be of rank 3, we need to apply - // transpose as well as reshape - if (channel_index != 0 || dims.nbDims != 3) { + // transpose as well as reshape. + // TODO(laigd): this doesn't match what the TRT doc says, fix the doc? + if (channel_index != 0 || original_dims.nbDims != 3) { nvinfer1::IShuffleLayer* shuffle_layer = - params->converter->network()->addShuffle( - *const_cast(tensor)); + params->converter->network()->addShuffle(*tensor); TFTRT_RETURN_ERROR_IF_NULLPTR(shuffle_layer, node_def.name()); + params->converter->MarkQuantizationRangesAsInferrable( + tensor, shuffle_layer->getOutput(0)); + + // NOTE(laigd): for some reason we need to apply the reshape + // unconditionally. The default shape has nbDims==-1 and it seems the + // behavior is undefined in some cases. nvinfer1::Dims reshape_dims; reshape_dims.nbDims = 3; - reshape_dims.d[0] = 0; // 0 copy from the input - reshape_dims.d[1] = dims.nbDims >= 2 ? 0 : 1; // 0 copy from the input - reshape_dims.d[2] = dims.nbDims >= 3 ? -1 : 1; // -1 infer from the rest + // 0 means copying from input; -1 means inferring from the rest. + reshape_dims.d[0] = 0; + reshape_dims.d[1] = original_dims.nbDims >= 2 ? 0 : 1; + reshape_dims.d[2] = original_dims.nbDims >= 3 ? -1 : 1; + shuffle_layer->setReshapeDimensions(reshape_dims); + if (channel_index != 0) { - // maybe we do not need this check. concerned about TRT optimization shuffle_layer->setFirstTranspose(permutation); } - shuffle_layer->setReshapeDimensions(reshape_dims); tensor = shuffle_layer->getOutput(0); } + TRT_ShapedWeights weights = inputs.at(1).weights(); + if (params->converter->precision_mode() == FP16MODE) { + weights = ConvertFP32ToFP16(params->weight_store, weights); + } nvinfer1::ScaleMode mode = nvinfer1::ScaleMode::kCHANNEL; if (weights.shape_.d[0] == 1) { mode = nvinfer1::ScaleMode::kUNIFORM; } + TRT_ShapedWeights empty_weights(weights.type_); nvinfer1::IScaleLayer* layer = params->converter->network()->addScale( - *const_cast(tensor), mode, weights.GetTrtWeights(), - empty_weights.GetTrtWeights(), empty_weights.GetTrtWeights()); + *tensor, mode, weights.GetTrtWeights(), empty_weights.GetTrtWeights(), + empty_weights.GetTrtWeights()); TFTRT_RETURN_ERROR_IF_NULLPTR(layer, node_def.name()); nvinfer1::ITensor* output_tensor = layer->getOutput(0); - // restore transpose & reshape - if (channel_index != 0 || dims.nbDims != 3) { + // Restore transpose & reshape. + if (channel_index != 0 || original_dims.nbDims != 3) { nvinfer1::IShuffleLayer* shuffle_layer = - params->converter->network()->addShuffle( - *const_cast(output_tensor)); + params->converter->network()->addShuffle(*output_tensor); TFTRT_RETURN_ERROR_IF_NULLPTR(shuffle_layer, node_def.name()); - nvinfer1::Dims reshape_dims = dims; - int tmp = reshape_dims.d[channel_index]; - reshape_dims.d[channel_index] = reshape_dims.d[0]; - reshape_dims.d[0] = tmp; + // NOTE: for same reason as mentioned above we need to apply the reshape + // unconditionally. + nvinfer1::Dims reshape_dims = original_dims; + if (channel_index != 0) { + // NOTE: according to NVIDIA dimension types are deprecated, so we don't + // need to copy them back. + reshape_dims.d[channel_index] = original_dims.d[0]; + reshape_dims.d[0] = original_dims.d[channel_index]; + } shuffle_layer->setReshapeDimensions(reshape_dims); + if (channel_index != 0) { shuffle_layer->setSecondTranspose(permutation); } + params->converter->MarkQuantizationRangesAsInferrable( + output_tensor, shuffle_layer->getOutput(0)); output_tensor = shuffle_layer->getOutput(0); } params->outputs->push_back(TRT_TensorOrWeights(output_tensor)); - return tensorflow::Status::OK(); + return Status::OK(); } Status GetTensorDimsWithProtoShape(const Tensor& tensor, @@ -2053,9 +2396,9 @@ tensorflow::Status ConvertConst(OpConverterParams* params) { uint8* data = reinterpret_cast(temp_weights.data()); std::copy(data, data + tensor.NumElements(), dst); } else { - return errors::FailedPrecondition( - "Unexpected data type: ", DataTypeString(dtype), - " at: ", node_def.name()); + return errors::FailedPrecondition("Unexpected data type: ", + DataTypeString(dtype), " at: ", + node_def.name()); } } } @@ -2070,32 +2413,41 @@ tensorflow::Status ConvertConst(OpConverterParams* params) { } tensorflow::Status ConvertIdentity(OpConverterParams* params) { + // TODO(tmorris): TRT's Identity layer does not get optimized away as of TRT + // 5.0, however once we know that it does it would be nice to use that + // instead. params->outputs->push_back(params->inputs.at(0)); return tensorflow::Status::OK(); } -tensorflow::Status ConvertBinary(OpConverterParams* params) { +Status ConvertBinary(OpConverterParams* params) { const auto& inputs = params->inputs; const auto& node_def = params->node_def; if (inputs.size() != 2) { - return tensorflow::errors::FailedPrecondition( - "Binary ops require two tensor input, at ", node_def.name()); + return errors::InvalidArgument("Binary ops require two inputs, at ", + node_def.name()); } // Constant folding should have been done by TensorFlow - if (inputs.at(0).is_weights() && inputs.at(1).is_weights()) { - return tensorflow::errors::Unimplemented( + return errors::Unimplemented( "Constant folding is falled back to TensorFlow, binary op received " "both input as constant at: ", node_def.name()); } - // Try to convert into Scale layer first (for better performance) + // TODO(tmorris): TRT plans to deprecate IScaleLayer and will replace it with + // IElementwiseLayer. At that point, we can remove BinaryTensorOpWeight. For + // now, the performance will be slightly better with IScaleLayer because it + // can be fused in more situations. However, most of the benefits of + // IScaleLayer are when the layer performs both a shift and a scale, which we + // don't do except for convolutions. + // + // Try to convert into Scale layer first (for better performance). // Since scale layer supports restricted broadcast policy and op types, we // allow failure and try to handle it through Elementwise op - // (BinaryTensorOpTensor) - Status status = tensorflow::Status::OK(); + // (BinaryTensorOpTensor). + Status status = Status::OK(); if (inputs.at(0).is_tensor() && inputs.at(1).is_weights()) { status = BinaryTensorOpWeight(params, inputs.at(0).tensor(), inputs.at(1).weights(), false); @@ -2103,7 +2455,10 @@ tensorflow::Status ConvertBinary(OpConverterParams* params) { status = BinaryTensorOpWeight(params, inputs.at(1).tensor(), inputs.at(0).weights(), true); } + // If both input are tensors, or one of them is weights but the conversion + // above failed, try the conversion using BinaryTensorOpTensor. if ((inputs.at(0).is_tensor() && inputs.at(1).is_tensor()) || !status.ok()) { + if (!status.ok()) VLOG(1) << status; status = BinaryTensorOpTensor(params, inputs.at(0), inputs.at(1)); } return status; @@ -2133,6 +2488,20 @@ tensorflow::Status ConvertUnary(OpConverterParams* params) { nvinfer1::IUnaryLayer* layer; if (node_def.op() == "Rsqrt") { + // We will need a quantization range for intermediate tensor if not using + // calibration. + // + // x -> [Sqrt] -> sqrt(x) -> [Recip] -> 1/sqrt(x) + // ^ + // need range here + if (params->converter->precision_mode() == INT8MODE && + !params->converter->use_calibration()) { + return errors::Unimplemented( + "Intermediate quantization range cannot be determined without" + " calibration for Rsqrt, consider replacing with " + "Sqrt -> FakeQuant -> Reciprocal ops, at ", + node_def.name()); + } layer = params->converter->network()->addUnary( *const_cast(tensor), nvinfer1::UnaryOperation::kSQRT); @@ -2156,6 +2525,48 @@ tensorflow::Status ConvertUnary(OpConverterParams* params) { return tensorflow::Status::OK(); } +tensorflow::Status ConvertSquare(OpConverterParams* params) { + const auto& inputs = params->inputs; + const auto& node_def = params->node_def; + if (inputs.size() != 1) { + return tensorflow::errors::InvalidArgument("Square expects one input, at ", + node_def.name()); + } + if (inputs.at(0).is_weights()) { + return tensorflow::errors::Unimplemented( + "Square is only implemented for tensors, at ", node_def.name()); + } + if (params->validation_only) return Status::OK(); + + // Constant 2 with same rank as input + nvinfer1::Dims dims = inputs.at(0).GetTrtDims(); + for (int i = 0; i < dims.nbDims; i++) { + dims.d[i] = 1; + } + TRT_ShapedWeights weights = params->weight_store->GetTempWeights( + tensorflow::DataType::DT_FLOAT, dims); + auto weights_ptr = + static_cast(const_cast(weights.GetValues())); + weights_ptr[0] = 2.f; + nvinfer1::IConstantLayer* const2_layer = + params->converter->network()->addConstant(dims, weights.GetTrtWeights()); + TFTRT_RETURN_ERROR_IF_NULLPTR(const2_layer, node_def.name()); + + // ElementWise Pow Operation + const nvinfer1::ITensor* tensor_l = inputs.at(0).tensor(); + const nvinfer1::ITensor* tensor_r = const2_layer->getOutput(0); + nvinfer1::IElementWiseLayer* layer = + params->converter->network()->addElementWise( + *const_cast(tensor_l), + *const_cast(tensor_r), + nvinfer1::ElementWiseOperation::kPOW); + TFTRT_RETURN_ERROR_IF_NULLPTR(layer, node_def.name()); + nvinfer1::ITensor* output_tensor = layer->getOutput(0); + + params->outputs->push_back(TRT_TensorOrWeights(output_tensor)); + return tensorflow::Status::OK(); +} + tensorflow::Status ConvertReduce(OpConverterParams* params) { const auto& inputs = params->inputs; const auto& node_def = params->node_def; @@ -2692,6 +3103,8 @@ tensorflow::Status ConvertSoftmax(OpConverterParams* params) { layer->setAxes(1 << (nbDims - 1)); nvinfer1::ITensor* output_tensor = layer->getOutput(0); + // Quantization range for SoftMax is always (0, 1) + params->converter->ProvideQuantizationRange(output_tensor, 0.0f, 1.0f); params->outputs->push_back(TRT_TensorOrWeights(output_tensor)); return tensorflow::Status::OK(); } @@ -2716,9 +3129,9 @@ tensorflow::Status ConvertTopK(OpConverterParams* params) { op = nvinfer1::TopKOperation::kMAX; reducedAxes |= 1 << (nbDims - 1); } else { - return tensorflow::errors::Unimplemented( - "Operation: " + node_def.op() + - " not implemented, at: " + node_def.name()); + return tensorflow::errors::Unimplemented("Operation: " + node_def.op() + + " not implemented, at: " + + node_def.name()); } nvinfer1::ITopKLayer* layer = params->converter->network()->addTopK( @@ -2732,40 +3145,52 @@ tensorflow::Status ConvertTopK(OpConverterParams* params) { return tensorflow::Status::OK(); } -void TrtNodeValidator::RegisterOpValidators() { +static void RegisterValidatableOpConverters( + std::unordered_map* registration) { // TODO(laigd): support all op types. - op_validators_["Const"] = ConvertConst; - op_validators_["Transpose"] = ConvertTranspose; - op_validators_["Reshape"] = ConvertReshape; - op_validators_["MatMul"] = ConvertMatMul; + (*registration)["BiasAdd"] = ConvertBiasAdd; + (*registration)["Const"] = ConvertConst; + (*registration)["Transpose"] = ConvertTranspose; + (*registration)["Reshape"] = ConvertReshape; + (*registration)["MatMul"] = ConvertMatMul; + (*registration)["Relu6"] = ConvertRelu6; + (*registration)["Square"] = ConvertSquare; + + for (auto quantization_op_type : + {"QuantizeAndDequantizeV2", "QuantizeAndDequantizeV3", + "FakeQuantWithMinMaxVars", "FakeQuantWithMinMaxArgs"}) { + (*registration)[quantization_op_type] = ConvertQuantize; + } + for (auto binary_op_type : + {"Add", "Mul", "Sub", "Div", "RealDiv", "Maximum", "Minimum"}) { + (*registration)[binary_op_type] = ConvertBinary; + } + for (auto activation_op_type : {"Relu", "Sigmoid", "Tanh"}) { + (*registration)[activation_op_type] = ConvertActivation; + } +} + +void TrtNodeValidator::RegisterOpValidators() { + RegisterValidatableOpConverters(&op_validators_); } void Converter::RegisterOpConverters() { - // vgg_16 slim implementation + RegisterValidatableOpConverters(&op_registry_); + op_registry_["Conv2D"] = ConvertConv2D; op_registry_["DepthwiseConv2dNative"] = ConvertConv2DDepthwise; - op_registry_["Relu"] = ConvertActivation; op_registry_["MaxPool"] = ConvertPool; op_registry_["AvgPool"] = ConvertPool; - op_registry_["BiasAdd"] = ConvertScale; - op_registry_["Const"] = ConvertConst; // TODO(ben,jie): this is a temp hack. op_registry_["Identity"] = ConvertIdentity; // Identity should be removed op_registry_["Snapshot"] = ConvertIdentity; // Snapshot should be removed - // resnet_50_v1 slim implementation - op_registry_["Add"] = ConvertBinary; - op_registry_["Mul"] = ConvertBinary; - op_registry_["Sub"] = ConvertBinary; op_registry_["Pad"] = ConvertPad; op_registry_["ConcatV2"] = ConvertConcat; op_registry_["FusedBatchNorm"] = ConvertFusedBatchNorm; op_registry_["FusedBatchNormV2"] = ConvertFusedBatchNorm; - op_registry_["Div"] = ConvertBinary; - op_registry_["RealDiv"] = ConvertBinary; - op_registry_["Rsqrt"] = ConvertUnary; op_registry_["Reciprocal"] = ConvertUnary; op_registry_["Exp"] = ConvertUnary; @@ -2774,20 +3199,19 @@ void Converter::RegisterOpConverters() { op_registry_["Abs"] = ConvertUnary; op_registry_["Neg"] = ConvertUnary; - op_registry_["Transpose"] = ConvertTranspose; - op_registry_["Reshape"] = ConvertReshape; - op_registry_["Sum"] = ConvertReduce; op_registry_["Prod"] = ConvertReduce; op_registry_["Max"] = ConvertReduce; op_registry_["Min"] = ConvertReduce; op_registry_["Mean"] = ConvertReduce; - op_registry_["Maximum"] = ConvertBinary; - op_registry_["Minimum"] = ConvertBinary; op_registry_["Softmax"] = ConvertSoftmax; - op_registry_["MatMul"] = ConvertMatMul; op_registry_["BatchMatMul"] = ConvertBatchMatMul; op_registry_["TopKV2"] = ConvertTopK; + op_registry_["Relu6"] = ConvertRelu6; + op_registry_["QuantizeAndDequantizeV2"] = ConvertQuantize; + op_registry_["QuantizeAndDequantizeV3"] = ConvertQuantize; + op_registry_["FakeQuantWithMinMaxVars"] = ConvertQuantize; + op_registry_["FakeQuantWithMinMaxArgs"] = ConvertQuantize; plugin_converter_ = ConvertPlugin; } @@ -2798,7 +3222,7 @@ tensorflow::Status ConvertGraphDefToEngine( const std::vector& input_shapes, Logger* logger, nvinfer1::IGpuAllocator* allocator, TRTInt8Calibrator* calibrator, - TrtUniquePtrType* engine, + TrtUniquePtrType* engine, bool use_calibration, bool* convert_successfully) { engine->reset(); if (convert_successfully) *convert_successfully = false; @@ -2813,7 +3237,11 @@ tensorflow::Status ConvertGraphDefToEngine( builder->setHalf2Mode(true); } else if (precision_mode == INT8MODE) { builder->setInt8Mode(true); - builder->setInt8Calibrator(calibrator); + if (use_calibration) { + builder->setInt8Calibrator(calibrator); + } else { + builder->setInt8Calibrator(nullptr); + } } // Create the network. @@ -2826,7 +3254,7 @@ tensorflow::Status ConvertGraphDefToEngine( // Build the network VLOG(1) << "Starting engine conversion "; - Converter converter(trt_network.get(), precision_mode == FP16MODE); + Converter converter(trt_network.get(), precision_mode, use_calibration); std::vector> output_tensors; // Graph nodes are already topologically sorted during construction for (const auto& node_def : gdef.node()) { @@ -2882,6 +3310,9 @@ tensorflow::Status ConvertGraphDefToEngine( TF_RETURN_IF_ERROR(converter.RenameAndMarkOutputTensors(output_tensors)); if (convert_successfully) *convert_successfully = true; + // Apply user provided quantization ranges to tensors + converter.MaybeApplyQuantizationRanges(); + // Build the engine. VLOG(1) << "Starting engine creation"; engine->reset(builder->buildCudaEngine(*converter.network())); @@ -3026,7 +3457,8 @@ tensorflow::Status ConvertSegmentToGraphDef( } } *common_scope = local_scope; - VLOG(0) << "Segment @scope '" << local_scope << "', converted to graph"; + VLOG(1) << "Converted TensorRT candidate segment @scope '" << local_scope + << "' to a GraphDef"; return tensorflow::Status::OK(); } diff --git a/tensorflow/contrib/tensorrt/convert/convert_nodes.h b/tensorflow/contrib/tensorrt/convert/convert_nodes.h index 5cc28b33e7..f1c4c121ae 100644 --- a/tensorflow/contrib/tensorrt/convert/convert_nodes.h +++ b/tensorflow/contrib/tensorrt/convert/convert_nodes.h @@ -92,7 +92,8 @@ struct EngineInfo { EngineInfo() : engine_type(EngineType::TRTStatic), max_workspace_size_bytes(0), - precision_mode(FP32MODE) {} + precision_mode(FP32MODE), + use_calibration(true) {} string engine_name; string device; @@ -109,6 +110,7 @@ struct EngineInfo { int maximum_cached_engines; std::vector cached_engine_batches; int precision_mode; + bool use_calibration; }; // Constructs a graphdef from the segment in the given graph. Adds placeholder @@ -145,7 +147,7 @@ tensorflow::Status ConvertGraphDefToEngine( const std::vector& input_shapes, Logger* logger, nvinfer1::IGpuAllocator* allocator, TRTInt8Calibrator* calibrator, - TrtUniquePtrType* engine, + TrtUniquePtrType* engine, bool use_calibration, bool* convert_successfully); // Helper class for the segmenter to determine whether an output edge from the @@ -392,7 +394,8 @@ class TrtNodeValidator { // Class to convert TF nodes to TRT network. class Converter { public: - Converter(nvinfer1::INetworkDefinition* trt_network, bool is_fp16); + Converter(nvinfer1::INetworkDefinition* trt_network, int precision_mode, + bool use_calibration); ////////////////////////////////////////////////////////////////////////////// // Methods used by the TRT engine builder to build a TRT network from a TF @@ -422,8 +425,43 @@ class Converter { // to add TRT layers. nvinfer1::INetworkDefinition* network() { return trt_network_; } - // Is the converter operating in fp16 mode? - bool is_fp16() const { return is_fp16_; } + // What precision are we targeting? + int precision_mode() const { return precision_mode_; } + + // Calibration will be or was previously performed on this network? + bool use_calibration() const { return use_calibration_; } + + // This should be called on the inputs and outputs of any layer we create + // where we know that the quantization range does not change during that + // operation. (e.g. Reshape, Transpose, Identity, MaxPool). + void MarkQuantizationRangesAsInferrable(nvinfer1::ITensor* input, + nvinfer1::ITensor* output); + + // This function should be called when we know the quantization range of a + // tensor, either from a quantize/dequantize node or when the output is a + // fixed range (e.g. SoftMax, Relu6, Sigmoid). + void ProvideQuantizationRange(nvinfer1::ITensor* tensor, float min_range, + float max_range); + + // Should be called when full TRT network has been constructed and before + // building the engine. + void MaybeApplyQuantizationRanges(); + + // This should be called on the inputs and outputs of any layer we create + // where we know that the quantization range does not change during that + // operation. (e.g. Reshape, Transpose, Identity, MaxPool). + void MarkQuantizationRangesAsInferrable(nvinfer1::ITensor* input, + nvinfer1::ITensor* output); + + // This function should be called when we know the quantization range of a + // tensor, either from a quantize/dequantize node or when the output is a + // fixed range (e.g. SoftMax, Relu6, Sigmoid). + void ProvideQuantizationRange(nvinfer1::ITensor* tensor, + float min_range, float max_range); + + // Should be called when full TRT network has been constructed and before + // building the engine. + void ApplyQuantizationRanges(bool warn_missing_ranges); // Below are helper methods for op converters to add different layers to the // TRT network. @@ -440,6 +478,13 @@ class Converter { const nvinfer1::Dims& dims, const nvinfer1::ITensor** tensor); + // Return OK if the broadcast scheme is supported and compute the shapes after + // broadcasting. + Status GetTrtBroadcastShape(const TRT_TensorOrWeights& operand_l, + const TRT_TensorOrWeights& operand_r, + nvinfer1::Dims* operand_l_new_dims, + nvinfer1::Dims* operand_r_new_dims) const; + private: // Verify the provided batch_size is consistent with batch_size_ and update it // if necessary. @@ -457,6 +502,12 @@ class Converter { void RegisterOpConverters(); + void PropagateQuantizationRanges(); + + // Gets the min and max value in a TRT_ShapedWeights + Status GetWeightRange(const TRT_ShapedWeights& weights, float* out_min, + float* out_max) const; + // Registered op converters by op type. std::unordered_map op_registry_; @@ -472,7 +523,25 @@ class Converter { // Store the weights added during construction of trt_network_. TrtWeightStore weight_store_; - const bool is_fp16_; + // During conversion, this table is populated with quantization ranges per + // tensor. MaybeApplyQuantizationRanges() will use this table to set the TRT + // quantization ranges. Since TRT only supports symmetric ranges, we will + // store the range as a single float = max(abs(min_range), abs(max_range)). + // Range refers to the floating point values, e.g. min_range = 0.0f, max_range + // = 6.0f for Relu6. + std::unordered_map quantization_ranges_; + + // Edges where quantization ranges can be inferred (copied) across ops - from + // first tensor to second tensor. PropagateQuantizationRanges() will propagate + // known ranges from quantization_ranges_ across these edges, adding the new + // ranges to quantization_ranges_ so that they can be applied in + // MaybeApplyQuantizationRanges(). + std::vector> + quantization_infer_; + + const int precision_mode_; + + const bool use_calibration_; // Batch size of inputs to trt_network_ added by AddInputTensor(). During // network construction it will update this, use it to verify the batch diff --git a/tensorflow/contrib/tensorrt/convert/convert_nodes_test.cc b/tensorflow/contrib/tensorrt/convert/convert_nodes_test.cc index c3a39395f3..a95ab8dfbb 100644 --- a/tensorflow/contrib/tensorrt/convert/convert_nodes_test.cc +++ b/tensorflow/contrib/tensorrt/convert/convert_nodes_test.cc @@ -35,7 +35,10 @@ limitations under the License. #include "tensorflow/core/grappler/costs/graph_properties.h" #include "tensorflow/core/lib/core/status.h" #include "tensorflow/core/lib/core/status_test_util.h" +#include "tensorflow/core/lib/strings/strcat.h" #include "tensorflow/core/platform/test.h" +#include "tensorflow/core/protobuf/config.pb.h" // NOLINT +#include "tensorflow/core/public/session.h" #if GOOGLE_CUDA #if GOOGLE_TENSORRT @@ -47,7 +50,9 @@ namespace tensorflow { namespace tensorrt { namespace convert { +using ::tensorflow::strings::StrCat; using ::testing::ElementsAre; +using ::testing::ElementsAreArray; // TODO(laigd): put this into some test utils file. void ExpectStatus(Status status, error::Code code = error::OK, @@ -69,6 +74,32 @@ nvinfer1::Dims GetTestDims(const std::vector& d) { return dims; } +nvinfer1::DataType TfDataTypeToTrt(DataType tf_dtype) { + switch (tf_dtype) { + case DT_FLOAT: + return nvinfer1::DataType::kFLOAT; + case DT_HALF: + return nvinfer1::DataType::kHALF; + case DT_INT32: + return nvinfer1::DataType::kINT32; + default: + QCHECK(false) << "Unexpected data type " << DataTypeString(tf_dtype); + } +} + +DataType TrtDataTypeToTf(nvinfer1::DataType trt_dtype) { + switch (trt_dtype) { + case nvinfer1::DataType::kFLOAT: + return DT_FLOAT; + case nvinfer1::DataType::kHALF: + return DT_HALF; + case nvinfer1::DataType::kINT32: + return DT_INT32; + default: + QCHECK(false) << "Unexpected data type " << static_cast(trt_dtype); + } +} + NodeDef MakeNodeDef(const string& name, const string& op, const std::vector& inputs) { NodeDef node_def; @@ -111,6 +142,35 @@ bool TrtDimsEqualsArray(const std::vector& lhs, return TrtDimsEquals(GetTestDims(lhs), rhs); } +// TODO(laigd): define a parameterized matcher that can compare against the +// vector. +void ExpectTrtDimsEqualsArray(const std::vector& lhs, + const nvinfer1::Dims& rhs) { + EXPECT_TRUE(TrtDimsEqualsArray(lhs, rhs)) + << "expected: " << DebugString(GetTestDims(lhs)) << "\n" + << " actual: " << DebugString(rhs); +} + +template +void ExpectArrayNear(const std::vector& lhs, const std::vector& rhs) { + ASSERT_EQ(lhs.size(), rhs.size()); + for (int i = 0; i < lhs.size(); i++) { + EXPECT_FLOAT_EQ(lhs[i], rhs[i]); + } +} + +// Eigen::half cannot implicitly convert to float which is required for +// EXPECT_FLOAT_EQ. +template <> +void ExpectArrayNear(const std::vector& lhs, + const std::vector& rhs) { + ASSERT_EQ(lhs.size(), rhs.size()); + for (int i = 0; i < lhs.size(); i++) { + EXPECT_FLOAT_EQ(Eigen::half_impl::half_to_float(lhs[i]), + Eigen::half_impl::half_to_float(rhs[i])); + } +} + bool TrtShapedWeightsEquals(const TRT_ShapedWeights& lhs, const TRT_ShapedWeights& rhs) { return TrtDimsEquals(lhs.shape_, rhs.shape_) && lhs.type_ == rhs.type_ && @@ -121,8 +181,7 @@ template void ValidateWeights(const TRT_ShapedWeights& weights, const std::vector& expected_dims, const std::vector& expected_value) { - EXPECT_TRUE(TrtDimsEqualsArray(expected_dims, weights.shape_)) - << weights.DebugString(); + ExpectTrtDimsEqualsArray(expected_dims, weights.shape_); ASSERT_EQ(expected_value.size(), weights.count()) << weights.DebugString(); const T* actual_values = static_cast(weights.GetValues()); for (int i = 0; i < expected_value.size(); ++i) { @@ -133,11 +192,12 @@ void ValidateWeights(const TRT_ShapedWeights& weights, // Fake ITensor implementation for testing purposes. class FakeITensor : public nvinfer1::ITensor { public: - FakeITensor() {} + FakeITensor() : dynamic_range_(0.0f) {} - FakeITensor(const nvinfer1::Dims& dims) : dims_(dims) {} + FakeITensor(const nvinfer1::Dims& dims) : dims_(dims), dynamic_range_(0.0f) {} - FakeITensor(const std::vector& dims) : dims_(GetTestDims(dims)) {} + FakeITensor(const std::vector& dims) + : dims_(GetTestDims(dims)), dynamic_range_(0.0f) {} void setName(const char* name) override { name_ = name; } @@ -166,7 +226,12 @@ class FakeITensor : public nvinfer1::ITensor { } #if NV_TENSORRT_MAJOR >= 5 - bool setDynamicRange(float min, float max) override {} + bool setDynamicRange(float min, float max) override { + dynamic_range_ = std::max(std::abs(min), std::abs(max)); + return true; + } + + float getDynamicRange() const override { return dynamic_range_; } #endif private: @@ -174,6 +239,7 @@ class FakeITensor : public nvinfer1::ITensor { nvinfer1::Dims dims_; nvinfer1::DataType type_; nvinfer1::TensorLocation location_; + float dynamic_range_; }; TEST(TRT_ShapedWeights_Test, Basic) { @@ -265,9 +331,7 @@ TEST(TRT_TensorOrWeights_Test, Basic) { EXPECT_EQ(1, ptr->batch_size()); } EXPECT_EQ(&itensor, ptr->tensor()); - EXPECT_TRUE(TrtDimsEqualsArray({1}, ptr->GetTrtDims())) - << "- expected: " << DebugString(dims) - << "\n vs\n- actual: " << DebugString(ptr->GetTrtDims()); + ExpectTrtDimsEqualsArray({1}, ptr->GetTrtDims()); } } } @@ -286,9 +350,7 @@ TEST(TRT_TensorOrWeights_Test, Basic) { EXPECT_EQ(false, ptr->is_weights()); EXPECT_EQ(1, ptr->batch_size()); EXPECT_NE(nullptr, ptr->tensor()); - EXPECT_TRUE(TrtDimsEqualsArray({1}, ptr->GetTrtDims())) - << "- expected: " << DebugString(dims) - << "\n vs\n- actual: " << DebugString(ptr->GetTrtDims()); + ExpectTrtDimsEqualsArray({1}, ptr->GetTrtDims()); } } // Test constructor with TRT_ShapedWeights argument. @@ -305,9 +367,7 @@ TEST(TRT_TensorOrWeights_Test, Basic) { nvinfer1::Dims dims; dims.nbDims = 0; - EXPECT_TRUE(TrtDimsEqualsArray({}, ptr->GetTrtDims())) - << "- expected: " << DebugString(dims) - << "\n vs\n- actual: " << DebugString(ptr->GetTrtDims()); + ExpectTrtDimsEqualsArray({}, ptr->GetTrtDims()); } } } @@ -341,34 +401,50 @@ TEST_F(ValidatorTest, ConvertToTensorOrWeights) { graph_properties, &output)); ValidateWeights(output.weights(), {2}, {1.0, 2.0}); } - // Convert non-Const. We test the case where the non-batch dimemsion is - // unknown as well, to make sure the validator allows that. - for (const int32 non_batch_dim : {-1, 2}) { - const int32 batch_size = 12; + // Helper method to run ConvertToTensorOrWeights() with predefined parameters. + auto convert_to_tensor_or_weights = [this](const std::vector& dims, + TRT_TensorOrWeights* output) { Scope s = Scope::NewRootScope(); - ops::Placeholder::Attrs attrs; - TF_EXPECT_OK(TensorShapeUtils::MakeShape( - std::vector{batch_size, non_batch_dim}, &attrs.shape_)); + const auto attrs = ops::Placeholder::Shape(PartialTensorShape{dims}); auto feed = ops::Placeholder(s.WithOpName("feed"), DT_FLOAT, attrs); auto add = ops::Add(s.WithOpName("add"), feed, feed); grappler::GrapplerItem item; TF_EXPECT_OK(s.ToGraphDef(&item.graph)); - grappler::GraphProperties graph_properties(item); TF_EXPECT_OK(graph_properties.InferStatically(true)); - - auto& node_def = add.operation.node()->def(); + const NodeDef& node_def = add.operation.node()->def(); + return this->ConvertToTensorOrWeights(node_def, /*output_port=*/0, + graph_properties, output); + }; + // Convert non-Const with #dims > nvinfer1::Dims::MAX_DIMS+1. + { TRT_TensorOrWeights output; - ExpectStatus(ConvertToTensorOrWeights(node_def, /*output_port=*/0, - graph_properties, &output)); + ExpectStatus( + convert_to_tensor_or_weights( + std::vector(nvinfer1::Dims::MAX_DIMS + 2, 1), &output), + error::OUT_OF_RANGE, "Input tensor rank is greater than 9"); + } + // Convert non-Const with #dims < 2. + { + TRT_TensorOrWeights output; + ExpectStatus( + convert_to_tensor_or_weights({1}, &output), error::INVALID_ARGUMENT, + "Input tensor with rank<2 is not supported since the first dimension " + "is treated as batch dimension by TRT"); + } + // Convert non-Const. We test the case where the non-batch dimemsion is + // unknown as well, to make sure the validator allows that. + for (const int32 non_batch_dim : {-1, 2}) { + const int32 batch_size = 12; + TRT_TensorOrWeights output; + ExpectStatus( + convert_to_tensor_or_weights({batch_size, non_batch_dim}, &output)); EXPECT_EQ(true, output.is_tensor()); EXPECT_EQ(batch_size, output.batch_size()); EXPECT_NE(nullptr, output.tensor()); - EXPECT_TRUE(TrtDimsEqualsArray({non_batch_dim}, output.GetTrtDims())) - << "- expected: {" << non_batch_dim << "} \n vs\n" - << "- actual: " << DebugString(output.GetTrtDims()); + ExpectTrtDimsEqualsArray({non_batch_dim}, output.GetTrtDims()); } } @@ -405,7 +481,9 @@ class ConverterTest : public ::testing::Test { ConverterTest() { builder_.reset(nvinfer1::createInferBuilder(logger_)); network_.reset(builder_->createNetwork()); - converter_.reset(new Converter(network_.get(), /*fp16=*/false)); + converter_.reset(new Converter(network_.get(), + /*precision_mode=*/FP32MODE, + /*use_calibration=*/false)); weight_store_ = &converter_->weight_store_; } @@ -432,8 +510,21 @@ class ConverterTest : public ::testing::Test { return converter_->GetInputs(node_def, inputs); } + Status GetWeightRange(const TRT_ShapedWeights& weights, float* out_min, + float* out_max) const { + return converter_->GetWeightRange(weights, out_min, out_max); + } + + void PropagateQuantizationRanges() { + converter_->PropagateQuantizationRanges(); + } + int batch_size() const { return converter_->batch_size_; } + std::unordered_map& quantization_ranges() { + return converter_->quantization_ranges_; + } + private: Logger logger_; // These members are ordered in a way such that the destruction order is: @@ -504,9 +595,9 @@ TEST_F(ConverterTest, AddAndGetInputs) { EXPECT_EQ(nvinfer1::DataType::kFLOAT, inputs[0].tensor()->getType()); EXPECT_EQ(nvinfer1::DataType::kINT32, inputs[2].tensor()->getType()); EXPECT_EQ(nvinfer1::DataType::kHALF, inputs[3].tensor()->getType()); - EXPECT_TRUE(TrtDimsEqualsArray({1}, inputs[0].tensor()->getDimensions())); - EXPECT_TRUE(TrtDimsEqualsArray({2, 3}, inputs[2].tensor()->getDimensions())); - EXPECT_TRUE(TrtDimsEqualsArray({5, 3}, inputs[3].tensor()->getDimensions())); + ExpectTrtDimsEqualsArray({1}, inputs[0].tensor()->getDimensions()); + ExpectTrtDimsEqualsArray({2, 3}, inputs[2].tensor()->getDimensions()); + ExpectTrtDimsEqualsArray({5, 3}, inputs[3].tensor()->getDimensions()); } TEST_F(ConverterTest, RenameAndMarkOutputTensors) { @@ -552,7 +643,7 @@ TEST_F(ConverterTest, RenameAndMarkOutputTensors) { {{"my_op", "my_output"}, {"my_op:1", "my_output_1"}})); EXPECT_EQ(2, output_tensors.size()); for (auto output_tensor : output_tensors) { - EXPECT_TRUE(TrtDimsEqualsArray({2, 1}, output_tensor->getDimensions())); + ExpectTrtDimsEqualsArray({2, 1}, output_tensor->getDimensions()); } EXPECT_EQ("my_output", string(output_tensors[0]->getName())); EXPECT_EQ("my_output_1", string(output_tensors[1]->getName())); @@ -577,8 +668,7 @@ TEST_F(ConverterTest, TransposeTensor) { // OK. TF_EXPECT_OK( converter_->TransposeTensor(input_tensor, {0, 3, 1, 2}, &output_tensor)); - EXPECT_TRUE(TrtDimsEqualsArray({5, 2, 3}, output_tensor->getDimensions())) - << DebugString(*output_tensor); + ExpectTrtDimsEqualsArray({5, 2, 3}, output_tensor->getDimensions()); } TEST_F(ConverterTest, PrepareTensorForShape_Tensor) { @@ -590,7 +680,7 @@ TEST_F(ConverterTest, PrepareTensorForShape_Tensor) { // Shape size doesn't match. ExpectStatus(converter_->PrepareTensorForShape(tw, GetTestDims({2, 3, 6}), &output_tensor), - error::INVALID_ARGUMENT, "Reshape shapes are not compatible."); + error::INVALID_ARGUMENT, "Reshape shapes are not compatible"); // TODO(aaroey): we should check the case where uninferred dimensions are not // an exact divisor of input dim ensions, e.g. for dims {-1, 7}. @@ -598,14 +688,12 @@ TEST_F(ConverterTest, PrepareTensorForShape_Tensor) { // Infer shape, ok. TF_EXPECT_OK(converter_->PrepareTensorForShape(tw, GetTestDims({-1, 2}), &output_tensor)); - EXPECT_TRUE(TrtDimsEqualsArray({15, 2}, output_tensor->getDimensions())) - << DebugString(*output_tensor); + ExpectTrtDimsEqualsArray({15, 2}, output_tensor->getDimensions()); // Regular shape. TF_EXPECT_OK(converter_->PrepareTensorForShape(tw, GetTestDims({10, 3}), &output_tensor)); - EXPECT_TRUE(TrtDimsEqualsArray({10, 3}, output_tensor->getDimensions())) - << DebugString(*output_tensor); + ExpectTrtDimsEqualsArray({10, 3}, output_tensor->getDimensions()); } TEST_F(ConverterTest, PrepareTensorForShape_Weights) { @@ -615,8 +703,7 @@ TEST_F(ConverterTest, PrepareTensorForShape_Weights) { const nvinfer1::ITensor* output_tensor = nullptr; TF_EXPECT_OK(converter_->PrepareTensorForShape(tw, GetTestDims({10, 3}), &output_tensor)); - EXPECT_TRUE(TrtDimsEqualsArray({10, 3}, output_tensor->getDimensions())) - << DebugString(*output_tensor); + ExpectTrtDimsEqualsArray({10, 3}, output_tensor->getDimensions()); } TEST_F(ConverterTest, MaybeUpdateBatchSize) { @@ -656,6 +743,178 @@ TEST_F(ConverterTest, AddAndGetTensorOrWeights) { "tensor/weights my_tensor already exist"); } +template +void TestGetWeightRange(ConverterTest* test, TrtWeightStore* weight_store) { + TRT_ShapedWeights weights = + weight_store->GetTempWeights(DataTypeToEnum::v(), GetTestDims({2, 3})); + const std::vector values = {T(3), T(1), T(2), T(6), T(5), T(4)}; + memcpy(const_cast(weights.GetValues()), values.data(), + weights.size_bytes()); + + float out_min = 0.0f; + float out_max = 0.0f; + TF_EXPECT_OK(test->GetWeightRange(weights, &out_min, &out_max)); + EXPECT_EQ(1.0f, out_min); + EXPECT_EQ(6.0f, out_max); +} + +TEST_F(ConverterTest, GetWeightRange) { + TestGetWeightRange(this, weight_store_); + TestGetWeightRange(this, weight_store_); + TestGetWeightRange(this, weight_store_); +} + +TEST_F(ConverterTest, ProvideQuantizationRange) { + FakeITensor fake_tensor; + // Assymetric range + converter_->ProvideQuantizationRange(&fake_tensor, 0.0f, 6.0f); + EXPECT_EQ(6.0f, quantization_ranges()[&fake_tensor]); + converter_->ProvideQuantizationRange(&fake_tensor, 1.0f, 6.0f); + EXPECT_EQ(6.0f, quantization_ranges()[&fake_tensor]); + converter_->ProvideQuantizationRange(&fake_tensor, -8.0f, 6.0f); + EXPECT_EQ(8.0f, quantization_ranges()[&fake_tensor]); + converter_->ProvideQuantizationRange(&fake_tensor, -8.123f, -6.123f); + EXPECT_EQ(8.123f, quantization_ranges()[&fake_tensor]); + // Symmetric range + converter_->ProvideQuantizationRange(&fake_tensor, -6.123f, 6.123f); + EXPECT_EQ(6.123f, quantization_ranges()[&fake_tensor]); +} + +TEST_F(ConverterTest, MaybeApplyQuantizationRanges) { + // input -> infer1 -> infer2 -> infer3 + FakeITensor input, infer_1, infer_2, infer_3; + FakeITensor not_infer; + Converter int8_converter(/*trt_network=*/nullptr, INT8MODE, + /*use_calibration=*/true); + int8_converter.ProvideQuantizationRange(&input, -5.0f, 5.0f); + int8_converter.ProvideQuantizationRange(¬_infer, -100.0f, 100.0f); + int8_converter.MarkQuantizationRangesAsInferrable(&input, &infer_1); + int8_converter.MarkQuantizationRangesAsInferrable(&infer_1, &infer_2); + int8_converter.MarkQuantizationRangesAsInferrable(&infer_2, &infer_3); + + // Input range should be inferred along the chain and applied to tensors. + int8_converter.MaybeApplyQuantizationRanges(); +#if NV_TENSORRT_MAJOR >= 5 + EXPECT_EQ(input.getDynamicRange(), 5.0f); + EXPECT_EQ(infer_1.getDynamicRange(), 5.0f); + EXPECT_EQ(infer_2.getDynamicRange(), 5.0f); + EXPECT_EQ(infer_3.getDynamicRange(), 5.0f); + EXPECT_EQ(not_infer.getDynamicRange(), 100.0f); +#endif +} + +TEST_F(ConverterTest, PropagateQuantizationRanges) { + // infer0 <-> infer1 <-> infer2 <-> infer3 + // | + // infer4 <-> infer5 + FakeITensor infer[6]; + FakeITensor not_infer; + converter_->ProvideQuantizationRange(&infer[4], -5.0f, 5.0f); + converter_->MarkQuantizationRangesAsInferrable(&infer[0], &infer[1]); + converter_->MarkQuantizationRangesAsInferrable(&infer[1], &infer[2]); + converter_->MarkQuantizationRangesAsInferrable(&infer[3], &infer[2]); + converter_->MarkQuantizationRangesAsInferrable(&infer[4], &infer[1]); + converter_->MarkQuantizationRangesAsInferrable(&infer[4], &infer[5]); + + // Input range should be inferred along the chain. + PropagateQuantizationRanges(); + auto ranges = quantization_ranges(); + for (int i = 0; i < 6; ++i) { + EXPECT_EQ(5.0f, ranges[&infer[i]]); + } + EXPECT_EQ(ranges.count(¬_infer), 0); +} + +TEST_F(ConverterTest, GetTrtBroadcastShape) { + const bool kIsTensor = true; + const bool kIsNotTensor = false; + auto symmetric_test = [this](const std::vector& operand_1_shape, + const std::vector& operand_2_shape, + const bool operand_1_is_tensor, + const bool operand_2_is_tensor, + const std::vector& expected_operand_1_shape, + const std::vector& expected_operand_2_shape, + error::Code expected_code = error::OK, + const char* expected_error_msg_substr = nullptr, + const int operand_1_batch_size = -1, + const int operand_2_batch_size = -1) { + auto create_tensor_or_weights = [](const std::vector& shape, + bool is_tensor, int batch_size = -1) { + if (is_tensor) { + return TRT_TensorOrWeights{nvinfer1::DataType::kFLOAT, + GetTestDims(shape), batch_size}; + } + TRT_ShapedWeights weights; + weights.shape_ = GetTestDims(shape); + return TRT_TensorOrWeights(weights); + }; + + nvinfer1::Dims operand_1_new_dims, operand_2_new_dims; + TRT_TensorOrWeights operand_1 = create_tensor_or_weights( + operand_1_shape, operand_1_is_tensor, operand_1_batch_size); + TRT_TensorOrWeights operand_2 = create_tensor_or_weights( + operand_2_shape, operand_2_is_tensor, operand_2_batch_size); + + // operand_1 broadcast operand_2 + ExpectStatus( + this->converter_->GetTrtBroadcastShape( + operand_1, operand_2, &operand_1_new_dims, &operand_2_new_dims), + expected_code, expected_error_msg_substr); + if (expected_code == error::OK) { + ExpectTrtDimsEqualsArray(expected_operand_1_shape, operand_1_new_dims); + ExpectTrtDimsEqualsArray(expected_operand_2_shape, operand_2_new_dims); + } + // operand_2 broadcast operand_1 + ExpectStatus( + this->converter_->GetTrtBroadcastShape( + operand_2, operand_1, &operand_2_new_dims, &operand_1_new_dims), + expected_code, expected_error_msg_substr); + if (expected_code == error::OK) { + ExpectTrtDimsEqualsArray(expected_operand_1_shape, operand_1_new_dims); + ExpectTrtDimsEqualsArray(expected_operand_2_shape, operand_2_new_dims); + } + }; + + // Both inputs are weights. + symmetric_test( + {1}, {1}, kIsNotTensor, kIsNotTensor, {}, {}, error::INVALID_ARGUMENT, + "Broadcasting requires at least one of the operands be tensors"); + + // One tensor and one weights. + symmetric_test({1, 1, 1}, {2}, kIsTensor, kIsNotTensor, {1, 1, 1}, {1, 1, 2}); + symmetric_test({1, 1, 2}, {2}, kIsTensor, kIsNotTensor, {1, 1, 2}, {1, 1, 2}); + symmetric_test({1, 3, 2}, {1}, kIsTensor, kIsNotTensor, {1, 3, 2}, {1, 1, 1}); + symmetric_test({1, 1, 1}, {2, 3}, kIsTensor, kIsNotTensor, {1, 1, 1}, + {1, 2, 3}); + symmetric_test({1, 1, 1}, {2, 3, 4}, kIsTensor, kIsNotTensor, {1, 1, 1}, + {2, 3, 4}); + symmetric_test({1, 1, 1}, {1, 2, 3, 4}, kIsTensor, kIsNotTensor, {1, 1, 1}, + {2, 3, 4}); + symmetric_test({1, 3, 4}, {1, 2, 1, 4}, kIsTensor, kIsNotTensor, {1, 3, 4}, + {2, 1, 4}); + symmetric_test({1, 1, 1}, {2, 1, 1, 1}, kIsTensor, kIsNotTensor, {}, {}, + error::INVALID_ARGUMENT, "Infeasible broadcast scheme"); + symmetric_test({1, 1, 1}, {2, 1, 1, 1}, kIsTensor, kIsNotTensor, {}, {}, + error::INVALID_ARGUMENT, "Infeasible broadcast scheme", + /*operand_1_batch_size=*/2); + symmetric_test({1, 1, 1}, {1, 1, 1, 1, 1}, kIsTensor, kIsNotTensor, {}, {}, + error::INVALID_ARGUMENT, + "Broadcasting beyond batch dimension is not supported " + "(tensor #dims 4 vs broadcast #dims 5)"); + + // Both inputs are tensors. + symmetric_test({1, 1, 1}, {1, 1}, kIsTensor, kIsTensor, {}, {}, + error::INVALID_ARGUMENT, + "Broadcasting beyond batch dimension is not supported " + "(tensor #dims 3 vs broadcast #dims 4)"); + symmetric_test({1, 3, 4}, {2, 1, 4}, kIsTensor, kIsTensor, {1, 3, 4}, + {2, 1, 4}); + symmetric_test({1, 1, 1}, {1, 1, 1, 1}, kIsTensor, kIsTensor, {}, {}, + error::INVALID_ARGUMENT, + "Broadcasting beyond batch dimension is not supported " + "(tensor #dims 4 vs broadcast #dims 5)"); +} + // Class to test various op converters, using both a TrtNodeValidator and // Converter. class OpConverterTest : public ::testing::Test { @@ -684,15 +943,21 @@ class OpConverterTest : public ::testing::Test { // Reset the validator and converter. validator_.reset(new TrtNodeValidator); - converter_.reset(new Converter(network_.get(), /*fp16=*/false)); + converter_.reset(new Converter(network_.get(), + /*precision_mode=*/FP32MODE, + /*use_calibration=*/false)); // Reset other related artifacts. scope_ = Scope::NewRootScope(); validator_inputs_.clear(); } - void BuildAndRun(const char* input_name, const std::vector& input_data, - const char* output_name, std::vector* output_data) { + // TODO(laigd): test fp16 and int8 support. + template + void BuildAndRun( + const std::vector>>& + input_data, + const char* output_name, std::vector* output_data) { // Mark the output tensor as TRT engine output. TF_EXPECT_OK(converter_->RenameAndMarkOutputTensors( {{string(output_name), string(output_name)}})); @@ -703,25 +968,33 @@ class OpConverterTest : public ::testing::Test { CHECK_NOTNULL(engine_.get()); // Execute the TRT engine. - const int input_size = input_data.size() * sizeof(float); - const int output_size = output_data->size() * sizeof(float); - const int input_index = engine_->getBindingIndex(input_name); - const int output_index = engine_->getBindingIndex(output_name); + ASSERT_LE(input_data.size() + 1, 3); + void* buffers[3]; + for (const auto name_and_data : input_data) { + const int input_size = name_and_data.second.size() * sizeof(T); + const int input_index = engine_->getBindingIndex(name_and_data.first); + ASSERT_EQ(0, cudaMalloc(&buffers[input_index], input_size)); + ASSERT_EQ( + 0, cudaMemcpyAsync(buffers[input_index], name_and_data.second.data(), + input_size, cudaMemcpyHostToDevice, stream_)); + } - ASSERT_EQ(engine_->getNbBindings(), 2); - void* buffers[2]; - ASSERT_EQ(0, cudaMalloc(&buffers[input_index], input_size)); + const int output_size = output_data->size() * sizeof(T); + const int output_index = engine_->getBindingIndex(output_name); ASSERT_EQ(0, cudaMalloc(&buffers[output_index], output_size)); - ASSERT_EQ(0, cudaMemcpyAsync(buffers[input_index], input_data.data(), - input_size, cudaMemcpyHostToDevice, stream_)); + + ASSERT_EQ(engine_->getNbBindings(), input_data.size() + 1); + TrtUniquePtrType execution_context( engine_->createExecutionContext()); execution_context->enqueue(/*batchSize=*/1, buffers, stream_, nullptr); ASSERT_EQ(0, cudaMemcpyAsync(output_data->data(), buffers[output_index], output_size, cudaMemcpyDeviceToHost, stream_)); cudaStreamSynchronize(stream_); - ASSERT_EQ(0, cudaFree(buffers[input_index])); - ASSERT_EQ(0, cudaFree(buffers[output_index])); + + for (int i = 0; i < input_data.size() + 1; ++i) { + ASSERT_EQ(0, cudaFree(buffers[i])); + } } bool HasStaticShape(const nvinfer1::Dims& dims) const { @@ -736,18 +1009,7 @@ class OpConverterTest : public ::testing::Test { void AddTestTensor( const char* name, const std::vector& dims, int batch_size = 1, nvinfer1::DataType trt_dtype = nvinfer1::DataType::kFLOAT) { - DataType tf_dtype = DT_FLOAT; - switch (trt_dtype) { - case nvinfer1::DataType::kFLOAT: - tf_dtype = DT_FLOAT; - break; - case nvinfer1::DataType::kINT32: - tf_dtype = DT_INT32; - break; - default: - ASSERT_TRUE(false) << "Unexpected data type " - << static_cast(trt_dtype); - } + DataType tf_dtype = TrtDataTypeToTf(trt_dtype); ops::Placeholder::Attrs attrs; TF_EXPECT_OK(TensorShapeUtils::MakeShape(dims, &attrs.shape_)); attrs.shape_.InsertDim(0, batch_size); @@ -826,6 +1088,11 @@ class OpConverterTest : public ::testing::Test { } } + // Expose quantization_ranges_ for tests + std::unordered_map& quantization_ranges() { + return converter_->quantization_ranges_; + } + std::unique_ptr converter_; std::unique_ptr validator_; @@ -835,6 +1102,11 @@ class OpConverterTest : public ::testing::Test { TrtUniquePtrType network_; TrtUniquePtrType engine_; cudaStream_t stream_; + // Used to create placeholders with shape and data type information. The + // created placeholders will be used as inputs to the node to be verified, + // thus we need the shape and data type information to get a non-empty + // GraphProperties. + // TODO(laigd): consider use this Scope to create the NodeDef to verify. Scope scope_; std::unordered_map validator_inputs_; }; @@ -958,15 +1230,15 @@ TEST_F(OpConverterTest, ConvertTranspose) { Reset(); AddTestTensor("input", {1, 2, 3}); AddTestWeights("weights", {4}, {0, 3, 1, 2}); - RunConversion(node_def); + RunValidationAndConversion(node_def); TRT_TensorOrWeights output; TF_EXPECT_OK(GetTensorOrWeights("my_transpose", &output)); EXPECT_TRUE(output.is_tensor()); - EXPECT_TRUE(TrtDimsEqualsArray({3, 1, 2}, output.tensor()->getDimensions())) - << output.DebugString(); + ExpectTrtDimsEqualsArray({3, 1, 2}, output.tensor()->getDimensions()); std::vector output_data(6); - BuildAndRun("input", {1, 2, 3, 4, 5, 6}, "my_transpose", &output_data); + BuildAndRun({{"input", {1, 2, 3, 4, 5, 6}}}, "my_transpose", + &output_data); EXPECT_THAT(output_data, ElementsAre(1, 4, 2, 5, 3, 6)); } } @@ -1048,15 +1320,15 @@ TEST_F(OpConverterTest, ConvertReshape) { Reset(); AddTestTensor("input", ok_params[i].tensor_dims, ok_params[i].batch_size); AddTestWeights("weights", {4}, ok_params[i].shape); - RunConversion(node_def); + RunValidationAndConversion(node_def); TRT_TensorOrWeights output; TF_EXPECT_OK(GetTensorOrWeights("my_reshape", &output)); EXPECT_TRUE(output.is_tensor()); - EXPECT_TRUE(TrtDimsEqualsArray({1, 3, 2}, output.tensor()->getDimensions())) - << output.DebugString(); + ExpectTrtDimsEqualsArray({1, 3, 2}, output.tensor()->getDimensions()); std::vector output_data(6); - BuildAndRun("input", {1, 2, 3, 4, 5, 6}, "my_reshape", &output_data); + BuildAndRun({{"input", {1, 2, 3, 4, 5, 6}}}, "my_reshape", + &output_data); EXPECT_THAT(output_data, ElementsAre(1, 2, 3, 4, 5, 6)); } } @@ -1070,15 +1342,14 @@ TEST_F(OpConverterTest, ConvertMatMul) { "Input expects tensor and weights, at my_matmul"); } - // Get the NodeDef for Reshape. + // Get the NodeDef for MatMul. auto get_matmul_nodedef = [](DataType dtype, bool transpose_a, bool transpose_b) -> NodeDef { Scope s = Scope::NewRootScope(); auto input = ops::Placeholder(s.WithOpName("input"), dtype); auto weights = ops::Placeholder(s.WithOpName("weights"), dtype); - ops::MatMul::Attrs matmul_attrs; - matmul_attrs.transpose_a_ = transpose_a; - matmul_attrs.transpose_b_ = transpose_b; + const auto matmul_attrs = + ops::MatMul::TransposeA(transpose_a).TransposeB(transpose_b); auto matmul = ops::MatMul(s.WithOpName("my_matmul"), input, weights, matmul_attrs); return matmul.operation.node()->def(); @@ -1094,45 +1365,845 @@ TEST_F(OpConverterTest, ConvertMatMul) { node_def, error::UNIMPLEMENTED, "Data type is not supported, for node my_matmul got int32"); } - { - // transpose_a is set. - for (bool transpose_b : {false, true}) { - Reset(); - NodeDef node_def = - get_matmul_nodedef(DT_FLOAT, /*transpose_a=*/true, transpose_b); - AddTestTensor("input", {2}, /*batch_size=*/1); - AddTestWeights("weights", {2, 2}, {0, 1, 2, 3}); - RunValidationAndConversion( - node_def, error::INVALID_ARGUMENT, - "transpose_a is not supported for TensorRT FullyConnected"); + // transpose_a is set. + for (bool transpose_b : {false, true}) { + Reset(); + NodeDef node_def = + get_matmul_nodedef(DT_FLOAT, /*transpose_a=*/true, transpose_b); + AddTestTensor("input", {2}, /*batch_size=*/1); + AddTestWeights("weights", {2, 2}, {0, 1, 2, 3}); + RunValidationAndConversion( + node_def, error::INVALID_ARGUMENT, + "transpose_a is not supported for TensorRT FullyConnected"); + } + // OK. + for (bool transpose_b : {false, true}) { + Reset(); + NodeDef node_def = + get_matmul_nodedef(DT_FLOAT, /*transpose_a=*/false, transpose_b); + AddTestTensor("input", {2}, /*batch_size=*/1); + AddTestWeights("weights", {2, 2}, {0, 1, 2, 3}); + RunValidationAndConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_matmul", &output)); + EXPECT_TRUE(output.is_tensor()); + ExpectTrtDimsEqualsArray({2}, output.tensor()->getDimensions()); + + std::vector output_data(2); + BuildAndRun({{"input", {0, 1}}}, "my_matmul", &output_data); + if (transpose_b) { + EXPECT_THAT(output_data, ElementsAre(1, 3)); + } else { + EXPECT_THAT(output_data, ElementsAre(2, 3)); } } - { - // OK. - for (bool transpose_b : {false, true}) { - Reset(); - NodeDef node_def = - get_matmul_nodedef(DT_FLOAT, /*transpose_a=*/false, transpose_b); - AddTestTensor("input", {2}, /*batch_size=*/1); - AddTestWeights("weights", {2, 2}, {0, 1, 2, 3}); - RunConversion(node_def); +} + +template +void TestConvertBiasAdd(OpConverterTest* test) { + // Get the NodeDef for BiasAdd. + auto get_biasadd_nodedef = [](const string& data_format) -> NodeDef { + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), dtype); + auto weights = ops::Placeholder(s.WithOpName("weights"), dtype); + const auto biasadd_attrs = ops::BiasAdd::DataFormat(data_format); + auto biasadd = + ops::BiasAdd(s.WithOpName("my_biasadd"), input, weights, biasadd_attrs); + return biasadd.operation.node()->def(); + }; + + typedef typename EnumToDataType::Type CType; + for (const string& data_format : {"NHWC", "NCHW"}) { + for (const int trt_input_rank : {1, 2, 3, 4}) { + test->Reset(); + NodeDef node_def = get_biasadd_nodedef(data_format); + + // Add input, dims_array will be like {2, 1, ..., 1, 3} + std::vector dims_array(trt_input_rank, 1); + if (trt_input_rank == 1) { + dims_array[0] = (data_format == "NHWC" ? 3 : 2); + } else { + dims_array[0] = 2; + dims_array[trt_input_rank - 1] = 3; + } + test->AddTestTensor("input", dims_array, /*batch_size=*/1, + TfDataTypeToTrt(dtype)); + + // Add bias weights. + const int channel_size = (data_format == "NHWC" ? 3 : 2); + std::vector bias(channel_size); + for (int i = 0; i < channel_size; ++i) { + bias[i] = CType(i + 1); // bias will be {1, 2, 3, ...} + } + test->AddTestWeights("weights", {channel_size}, bias); + + // Run the conversion. + test->RunValidationAndConversion(node_def); TRT_TensorOrWeights output; - TF_EXPECT_OK(GetTensorOrWeights("my_matmul", &output)); + TF_EXPECT_OK(test->GetTensorOrWeights("my_biasadd", &output)); EXPECT_TRUE(output.is_tensor()); - EXPECT_TRUE(TrtDimsEqualsArray({2}, output.tensor()->getDimensions())) - << output.DebugString(); - - std::vector output_data(2); - BuildAndRun("input", {0, 1}, "my_matmul", &output_data); - if (transpose_b) { - EXPECT_THAT(output_data, ElementsAre(1, 3)); + ExpectTrtDimsEqualsArray(dims_array, output.tensor()->getDimensions()); + + // Build and run the engine. + const int num_input = TrtDimsNumElements(GetTestDims(dims_array)); + ASSERT_EQ(trt_input_rank > 1 ? 6 : (data_format == "NHWC" ? 3 : 2), + num_input); + std::vector output_data(num_input); + test->BuildAndRun( + {{"input", std::vector(num_input, CType(0))}}, "my_biasadd", + &output_data); + if (trt_input_rank == 1) { + if (data_format == "NHWC") { + EXPECT_THAT(output_data, ElementsAre(CType(1), CType(2), CType(3))); + } else { + EXPECT_THAT(output_data, ElementsAre(CType(1), CType(2))); + } } else { - EXPECT_THAT(output_data, ElementsAre(2, 3)); + if (data_format == "NHWC") { + EXPECT_THAT(output_data, ElementsAre(CType(1), CType(2), CType(3), + CType(1), CType(2), CType(3))); + } else { + EXPECT_THAT(output_data, ElementsAre(CType(1), CType(1), CType(1), + CType(2), CType(2), CType(2))); + } } } } } +TEST_F(OpConverterTest, ConvertQuantize) { + { + // Input list is empty, should fail. + NodeDef node_def = + MakeNodeDef("my_quantize", "QuantizeAndDequantizeV2", {}); + RunConversion( + node_def, error::INVALID_ARGUMENT, + "Invalid number of inputs for QuantizeAndDequantizeV2, at my_quantize"); + } + { + // FakeQuantWithMinMaxArgs attributes are empty, should fail. + NodeDef node_def = + MakeNodeDef("my_quantize", "FakeQuantWithMinMaxArgs", {"input"}); + AddTestTensor("input", {1, 2, 3}); + RunConversion(node_def, error::INVALID_ARGUMENT, + "Min or max attribute not found for FakeQuantWithMinMaxArgs " + "at my_quantize"); + } + { + // FakeQuantWithMinMaxArgs ranges set via attributes, ok. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + ops::FakeQuantWithMinMaxArgs::Attrs quantize_attrs; + quantize_attrs.min_ = -6.0f; + quantize_attrs.max_ = 6.0f; + auto quantize = ops::FakeQuantWithMinMaxArgs(s.WithOpName("my_quantize"), + input, quantize_attrs); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + RunConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_quantize", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(ranges.count(output.tensor()), 1); + EXPECT_EQ(ranges[output.tensor()], 6.0f); + } + { + // FakeQuantWithMinMaxVars ranges set via inputs, ok. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto weights_min = ops::Placeholder(s.WithOpName("weights_min"), DT_FLOAT); + auto weights_max = ops::Placeholder(s.WithOpName("weights_max"), DT_FLOAT); + auto quantize = ops::FakeQuantWithMinMaxVars( + s.WithOpName("my_quantize"), input, weights_min, weights_max); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + AddTestWeights("weights_min", {1}, {-6.0f}); + AddTestWeights("weights_max", {1}, {6.0f}); + RunConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_quantize", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(ranges.count(output.tensor()), 1); + EXPECT_EQ(ranges[output.tensor()], 6.0f); + } + { + // QuantizeAndDequantizeV2 ranges set via inputs, ok. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto weights_min = ops::Placeholder(s.WithOpName("weights_min"), DT_FLOAT); + auto weights_max = ops::Placeholder(s.WithOpName("weights_max"), DT_FLOAT); + auto quantize = ops::QuantizeAndDequantizeV2( + s.WithOpName("my_quantize"), input, weights_min, weights_max); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + AddTestWeights("weights_min", {1}, {-6.0f}); + AddTestWeights("weights_max", {1}, {6.0f}); + RunConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_quantize", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(ranges.count(output.tensor()), 1); + EXPECT_EQ(ranges[output.tensor()], 6.0f); + } + { + // QuantizeAndDequantizeV3 ranges set via inputs, ok. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto weights_min = ops::Placeholder(s.WithOpName("weights_min"), DT_FLOAT); + auto weights_max = ops::Placeholder(s.WithOpName("weights_max"), DT_FLOAT); + auto num_bits = ops::Placeholder(s.WithOpName("num_bits"), DT_INT32); + auto quantize = ops::QuantizeAndDequantizeV3( + s.WithOpName("my_quantize"), input, weights_min, weights_max, num_bits); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + AddTestWeights("weights_min", {1}, {-6.0f}); + AddTestWeights("weights_max", {1}, {6.0f}); + AddTestWeights("num_bits", {1}, {8}); + RunConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_quantize", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(ranges.count(output.tensor()), 1); + EXPECT_EQ(ranges[output.tensor()], 6.0f); + } + { + // QuantizeAndDequantizeV2 Range inputs are tensors, should fail. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto weights_min = ops::Placeholder(s.WithOpName("weights_min"), DT_FLOAT); + auto weights_max = ops::Placeholder(s.WithOpName("weights_max"), DT_FLOAT); + auto quantize = ops::QuantizeAndDequantizeV2( + s.WithOpName("my_quantize"), input, weights_min, weights_max); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + AddTestTensor("weights_min", {1}); + AddTestTensor("weights_max", {1}); + RunConversion( + node_def, error::INVALID_ARGUMENT, + "Min and max inputs for QuantizeAndDequantizeV2 must be weights not " + "tensors, at my_quantize"); + } +} + +TEST_F(OpConverterTest, ConvertRelu6) { + { + // Input list is empty, should fail. + NodeDef node_def = MakeNodeDef("my_relu6", "Relu6", {}); + RunConversion(node_def, error::INVALID_ARGUMENT, + "Invalid number of inputs for Relu6, at my_relu6"); + } + + // Get the NodeDef for Relu6. + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto relu6 = ops::Relu6(s.WithOpName("my_relu6"), input); + const NodeDef& node_def = relu6.operation.node()->def(); + + { + // Clip tensor values and set quantization ranges, ok. + Reset(); + AddTestTensor("input", {1, 2, 3}); + RunConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_relu6", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(ranges[output.tensor()], 6.0f); + + std::vector output_data(6); + BuildAndRun("input", {-100, -1, 0, 3, 5, 9}, "my_relu6", &output_data); + EXPECT_THAT(output_data, ElementsAre(0, 0, 0, 3, 5, 6)); + } + { + // Input is weights, should fail. + Reset(); + AddTestWeights("input", {1, 2, 3}, {-100, -1, 0, 3, 5, 9}); + RunConversion( + node_def, error::UNIMPLEMENTED, + "Relu6 is only implemented for tensors, not weights, at my_relu6"); + } +} + +TEST_F(OpConverterTest, ConvertBiasAdd) { + { + // Input list is empty, should fail. + NodeDef node_def = MakeNodeDef("my_biasadd", "BiasAdd", {}); + RunValidationAndConversion( + node_def, error::INVALID_ARGUMENT, + "Input expects tensor and weights, at my_biasadd"); + } + + // OK. Note that kINT32 is not supported by IScaleLayer, so we don't test + // DT_INT32 type here. + TestConvertBiasAdd(this); + TestConvertBiasAdd(this); +} + +template +NodeDef GetBinaryOpNodeDef(const string& input_name_l, + const string& input_name_r, DataType dtype) { + Scope s = Scope::NewRootScope(); + auto input_l = ops::Placeholder(s.WithOpName(input_name_l), dtype); + auto input_r = ops::Placeholder(s.WithOpName(input_name_r), dtype); + auto op = OpType(s.WithOpName("my_binary"), input_l, input_r); + return op.operation.node()->def(); +} + +void CheckAddedLayers(OpConverterTest* test, bool expect_scale_layer) { + bool element_wise_layer_found = false; + bool scale_layer_found = false; + for (int i = 0; i < test->converter_->network()->getNbLayers(); i++) { + nvinfer1::ILayer* layer = test->converter_->network()->getLayer(i); + if (dynamic_cast(layer)) { + scale_layer_found = true; + } else if (dynamic_cast(layer)) { + element_wise_layer_found = true; + } + } + EXPECT_EQ(expect_scale_layer, scale_layer_found); + EXPECT_NE(expect_scale_layer, element_wise_layer_found); +} + +template +void TestBinaryTensorOpWeightNoBroadcast(OpConverterTest* test) { + typedef typename EnumToDataType::Type CType; + for (auto swap_inputs : {false, true}) { + test->Reset(); + NodeDef node_def; + if (swap_inputs) { + node_def = GetBinaryOpNodeDef("weights", "input", dtype); + } else { + node_def = GetBinaryOpNodeDef("input", "weights", dtype); + } + + const std::vector operand1{CType(3), CType(7.5)}; + const std::vector operand2{CType(2), CType(3)}; + + // It requires the dims to be at least of rank 3 to apply an IScaleLayer. + test->AddTestTensor("input", /*dims=*/{1, 1, 2}, /*batch_size=*/1, + TfDataTypeToTrt(dtype)); + test->AddTestWeights("weights", /*dims=*/{1, 1, 2}, + /*values=*/swap_inputs ? operand1 : operand2); + test->RunValidationAndConversion(node_def); + + // Make sure it does use BinaryTensorOpWeight, not BinaryTensorOpTensor. + CheckAddedLayers(test, /*expect_scale_layer=*/true); + + // Check the dims of the output ITensor. + TRT_TensorOrWeights output; + TF_EXPECT_OK(test->GetTensorOrWeights("my_binary", &output)); + EXPECT_TRUE(output.is_tensor()); + ExpectTrtDimsEqualsArray({1, 1, 2}, output.tensor()->getDimensions()); + + std::vector output_data(2); + test->BuildAndRun( + {{"input", + /*input_data=*/swap_inputs ? operand2 : operand1}}, + "my_binary", &output_data); + if (node_def.op() == "Add") { + EXPECT_THAT(output_data, ElementsAre(CType(5), CType(10.5))); + } else if (node_def.op() == "Sub") { + EXPECT_THAT(output_data, ElementsAre(CType(1), CType(4.5))); + } else if (node_def.op() == "Mul") { + EXPECT_THAT(output_data, ElementsAre(CType(6), CType(22.5))); + } else if (node_def.op() == "Div") { + EXPECT_THAT(output_data, ElementsAre(CType(1.5), CType(2.5))); + } else if (node_def.op() == "RealDiv") { + EXPECT_THAT(output_data, ElementsAre(CType(1.5), CType(2.5))); + } else { + ASSERT_TRUE(false); + } + } +} + +template +void TestBinaryTensorOpWeightWithChannelWiseBroadcast(OpConverterTest* test) { + typedef typename EnumToDataType::Type CType; + const NodeDef node_def = + GetBinaryOpNodeDef("input", "weights", dtype); + const std::vector input{CType(1), CType(2), CType(3), CType(4)}; + const std::vector weights{CType(10), CType(20)}; + // There are two types of valid dim pairs which requires channel-wise + // broadcasting: + // - input dims (X Y Z) vs weights dims (X 1 1) + // - input dims (X Y Z) vs weights dims (Z) + // Here X=Z=2 and Y=1. + for (auto weights_dims : std::vector>{{2, 1, 1}, {2}}) { + test->Reset(); + test->AddTestTensor("input", /*dims=*/{2, 1, 2}, /*batch_size=*/1, + TfDataTypeToTrt(dtype)); + test->AddTestWeights("weights", weights_dims, weights); + test->RunValidationAndConversion(node_def); + + // Make sure it does use BinaryTensorOpWeight, not BinaryTensorOpTensor. + CheckAddedLayers(test, /*expect_scale_layer=*/true); + + // Check the dims of the output ITensor. + TRT_TensorOrWeights output; + TF_EXPECT_OK(test->GetTensorOrWeights("my_binary", &output)); + EXPECT_TRUE(output.is_tensor()); + ExpectTrtDimsEqualsArray({2, 1, 2}, output.tensor()->getDimensions()); + + std::vector output_data(4); + test->BuildAndRun({{"input", input}}, "my_binary", &output_data); + if (weights_dims.size() == 1) { + EXPECT_THAT(output_data, + ElementsAre(CType(11), CType(22), CType(13), CType(24))); + } else { + EXPECT_THAT(output_data, + ElementsAre(CType(11), CType(12), CType(23), CType(24))); + } + } +} + +template +void TestBinaryTensorOpWeightWithUniformlyBroadcast(OpConverterTest* test) { + typedef typename EnumToDataType::Type CType; + const NodeDef node_def = + GetBinaryOpNodeDef("input", "weights", dtype); + const std::vector input{CType(1), CType(2), CType(3), CType(4)}; + const std::vector weights{CType(10)}; + test->Reset(); + test->AddTestTensor("input", /*dims=*/{2, 1, 2}, /*batch_size=*/1, + TfDataTypeToTrt(dtype)); + test->AddTestWeights("weights", {1, 1, 1, 1}, weights); + test->RunValidationAndConversion(node_def); + + // Make sure it does use BinaryTensorOpWeight, not BinaryTensorOpTensor. + CheckAddedLayers(test, /*expect_scale_layer=*/true); + + // Check the dims of the output ITensor. + TRT_TensorOrWeights output; + TF_EXPECT_OK(test->GetTensorOrWeights("my_binary", &output)); + EXPECT_TRUE(output.is_tensor()); + ExpectTrtDimsEqualsArray({2, 1, 2}, output.tensor()->getDimensions()); + + std::vector output_data(4); + test->BuildAndRun({{"input", input}}, "my_binary", &output_data); + EXPECT_THAT(output_data, + ElementsAre(CType(11), CType(12), CType(13), CType(14))); +} + +template +void TestBinaryTensorOpWeightFallback(OpConverterTest* test, + const std::vector& input_dims, + const std::vector& weights_dims, + error::Code code = error::OK, + const char* error_msg_substr = nullptr, + const int input_batch_size = 1) { + const DataType dtype = DT_FLOAT; + typedef typename EnumToDataType::Type CType; + const size_t num_inputs = TrtDimsNumElements(GetTestDims(input_dims)); + const size_t num_weights = TrtDimsNumElements(GetTestDims(weights_dims)); + + test->Reset(); + const NodeDef node_def = + GetBinaryOpNodeDef("input", "weights", dtype); + test->AddTestTensor("input", /*dims=*/input_dims, input_batch_size, + TfDataTypeToTrt(dtype)); + test->AddTestWeights( + "weights", /*dims=*/weights_dims, + /*values=*/std::vector(num_weights, CType(1))); + test->RunValidationAndConversion(node_def, code, error_msg_substr); + if (code != error::OK) return; + + // Make sure it does use BinaryTensorOpTensor, not BinaryTensorOpWeight. + CheckAddedLayers(test, /*expect_scale_layer=*/false); + + TRT_TensorOrWeights output; + TF_EXPECT_OK(test->GetTensorOrWeights("my_binary", &output)); + EXPECT_TRUE(output.is_tensor()); + + // Check the dims of the output ITensor. + std::vector expected_output_dims = input_dims; + for (int i = expected_output_dims.size() - 1, j = weights_dims.size() - 1; + i >= 0 && j >= 0; --i, --j) { + if (expected_output_dims[i] == 1) { + expected_output_dims[i] = weights_dims[j]; + } + } + ExpectTrtDimsEqualsArray(expected_output_dims, + output.tensor()->getDimensions()); + + // Check the result of running the engine. + const int expected_num_outputs = + TrtDimsNumElements(GetTestDims(expected_output_dims)); + std::vector output_data(expected_num_outputs); + test->BuildAndRun( + {{"input", + /*input_data=*/std::vector(num_inputs, CType(2))}}, + "my_binary", &output_data); + if (node_def.op() == "Add") { + EXPECT_THAT(output_data, ElementsAreArray(std::vector( + expected_num_outputs, CType(3)))); + } else if (node_def.op() == "Minimum") { + EXPECT_THAT(output_data, ElementsAreArray(std::vector( + expected_num_outputs, CType(1)))); + } else { + ASSERT_TRUE(false); + } +} + +template +void TestBinaryTensorOpTensor(OpConverterTest* test) { + typedef typename EnumToDataType::Type CType; + test->Reset(); + const NodeDef node_def = + GetBinaryOpNodeDef("input1", "input2", dtype); + test->AddTestTensor("input1", /*dims=*/{1, 2}, /*batch_size=*/1, + TfDataTypeToTrt(dtype)); + test->AddTestTensor("input2", /*dims=*/{2, 1}, /*batch_size=*/1, + TfDataTypeToTrt(dtype)); + test->RunValidationAndConversion(node_def); + + // Make sure it does use BinaryTensorOpTensor, not BinaryTensorOpWeight. + CheckAddedLayers(test, /*expect_scale_layer=*/false); + + // Check output dims. + TRT_TensorOrWeights output; + TF_EXPECT_OK(test->GetTensorOrWeights("my_binary", &output)); + EXPECT_TRUE(output.is_tensor()); + ExpectTrtDimsEqualsArray({2, 2}, output.tensor()->getDimensions()); + + std::vector output_data(4); + // After broadcasting first input becomes {3, 6, 3, 6} and second input + // becomes {2, 3, 2, 3}. + test->BuildAndRun( + {{"input1", {CType(3), CType(6)}}, {"input2", {CType(2), CType(3)}}}, + "my_binary", &output_data); + if (node_def.op() == "Add") { + EXPECT_THAT(output_data, + ElementsAre(CType(5), CType(8), CType(6), CType(9))); + } else if (node_def.op() == "Sub") { + EXPECT_THAT(output_data, + ElementsAre(CType(1), CType(4), CType(0), CType(3))); + } else if (node_def.op() == "Mul") { + EXPECT_THAT(output_data, + ElementsAre(CType(6), CType(12), CType(9), CType(18))); + } else if (node_def.op() == "Div") { + EXPECT_THAT(output_data, + ElementsAre(CType(1.5), CType(3), CType(1), CType(2))); + } else if (node_def.op() == "RealDiv") { + EXPECT_THAT(output_data, + ElementsAre(CType(1.5), CType(3), CType(1), CType(2))); + } else if (node_def.op() == "Minimum") { + EXPECT_THAT(output_data, + ElementsAre(CType(2), CType(2), CType(3), CType(3))); + } else if (node_def.op() == "Maximum") { + EXPECT_THAT(output_data, + ElementsAre(CType(3), CType(6), CType(3), CType(6))); + } else { + ASSERT_TRUE(false); + } +} + +TEST_F(OpConverterTest, ConvertBinary) { + // Input size doesn't match, should fail. + for (size_t num_inputs = 0; num_inputs < 2; ++num_inputs) { + Reset(); + NodeDef node_def = MakeNodeDef("my_add", "Add", {num_inputs, "input"}); + AddTestTensor("input", {1}, /*batch_size=*/1, nvinfer1::DataType::kFLOAT); + RunValidationAndConversion(node_def, error::INVALID_ARGUMENT, + "Binary ops require two inputs, at my_add"); + } + { + // Both inputs are weights. + Reset(); + NodeDef node_def = MakeNodeDef("my_add", "Add", {"weights1", "weights2"}); + AddTestWeights("weights1", {1}, {1}); + AddTestWeights("weights2", {1}, {1}); + RunValidationAndConversion( + node_def, error::UNIMPLEMENTED, + "Constant folding is falled back to TensorFlow, binary op received " + "both input as constant at: my_add"); + } + + // Test BinaryTensorOpWeight() without broadcasting. + TestBinaryTensorOpWeightNoBroadcast(this); + TestBinaryTensorOpWeightNoBroadcast(this); + TestBinaryTensorOpWeightNoBroadcast(this); + TestBinaryTensorOpWeightNoBroadcast(this); + TestBinaryTensorOpWeightNoBroadcast(this); +#if 0 + // TODO(b/119560144): it doesn't support FP16 constants and the following test + // will fail. + TestBinaryTensorOpWeightNoBroadcast(this); + TestBinaryTensorOpWeightNoBroadcast(this); + TestBinaryTensorOpWeightNoBroadcast(this); + TestBinaryTensorOpWeightNoBroadcast(this); + TestBinaryTensorOpWeightNoBroadcast(this); +#endif + + // Test BinaryTensorOpWeight() with channel-wise broadcasting. + TestBinaryTensorOpWeightWithChannelWiseBroadcast(this); + + // Test BinaryTensorOpWeight() with uniformly broadcasting. + TestBinaryTensorOpWeightWithUniformlyBroadcast(this); + + // Test BinaryTensorOpWeight() falling back to BinaryTensorOpTensor(). + // Unsupported op. + TestBinaryTensorOpWeightFallback(this, {1, 1, 1}, {1}); + // Rank of input tensor dimension <3. + TestBinaryTensorOpWeightFallback(this, {1, 1}, {1}); + // Broadcast on batch dimension, should fail. + TestBinaryTensorOpWeightFallback( + this, {1, 1, 1}, {2, 1, 1, 1}, error::INVALID_ARGUMENT, + "Unsupported binary op broadcast scheme for op my_binary", + /*input_batch_size=*/2); + // Incompatible dims with per-channel mode. + TestBinaryTensorOpWeightFallback(this, {1, 1, 1}, {1, 2, 1}); + // Incompatible dims. + TestBinaryTensorOpWeightFallback(this, {1, 2, 1}, {2}); + + // Test BinaryTensorOpTensor() with broadcasting. + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); + TestBinaryTensorOpTensor(this); +} + +TEST_F(OpConverterTest, ConvertQuantize) { + for (const string& op : + {"FakeQuantWithMinMaxArgs", "FakeQuantWithMinMaxVars", + "QuantizeAndDequantizeV2", "QuantizeAndDequantizeV3"}) { + // Input list is empty, should fail. + NodeDef node_def = MakeNodeDef("my_quantize", op, {}); + RunValidationAndConversion( + node_def, error::INVALID_ARGUMENT, + StrCat("Invalid number of inputs for ", op, ", at my_quantize") + .c_str()); + } + { + // FakeQuantWithMinMaxArgs attributes are empty, should fail. + NodeDef node_def = + MakeNodeDef("my_quantize", "FakeQuantWithMinMaxArgs", {"input"}); + AddTestTensor("input", {1, 2, 3}); + RunValidationAndConversion( + node_def, error::INVALID_ARGUMENT, + "Min or max attribute not found for FakeQuantWithMinMaxArgs " + "at my_quantize"); + } + { + // FakeQuantWithMinMaxArgs ranges set via attributes, ok. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto quantize_attrs = ops::FakeQuantWithMinMaxArgs::Min(-6.0f).Max(6.0f); + auto quantize = ops::FakeQuantWithMinMaxArgs(s.WithOpName("my_quantize"), + input, quantize_attrs); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + RunValidationAndConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_quantize", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(1, ranges.count(output.tensor())); + EXPECT_EQ(6.0f, ranges[output.tensor()]); + } + { + // FakeQuantWithMinMaxVars ranges set via inputs, ok. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto weights_min = ops::Placeholder(s.WithOpName("weights_min"), DT_FLOAT); + auto weights_max = ops::Placeholder(s.WithOpName("weights_max"), DT_FLOAT); + auto quantize = ops::FakeQuantWithMinMaxVars( + s.WithOpName("my_quantize"), input, weights_min, weights_max); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + AddTestWeights("weights_min", {1}, {-6.0f}); + AddTestWeights("weights_max", {1}, {6.0f}); + RunValidationAndConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_quantize", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(1, ranges.count(output.tensor())); + EXPECT_EQ(6.0f, ranges[output.tensor()]); + } + { + // QuantizeAndDequantizeV2 ranges set via inputs, ok. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto weights_min = ops::Placeholder(s.WithOpName("weights_min"), DT_FLOAT); + auto weights_max = ops::Placeholder(s.WithOpName("weights_max"), DT_FLOAT); + auto quantize = ops::QuantizeAndDequantizeV2( + s.WithOpName("my_quantize"), input, weights_min, weights_max); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + AddTestWeights("weights_min", {1}, {-6.0f}); + AddTestWeights("weights_max", {1}, {6.0f}); + RunValidationAndConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_quantize", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(1, ranges.count(output.tensor())); + EXPECT_EQ(6.0f, ranges[output.tensor()]); + } + { + // QuantizeAndDequantizeV2 Range inputs are tensors, should fail. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto weights_min = ops::Placeholder(s.WithOpName("weights_min"), DT_FLOAT); + auto weights_max = ops::Placeholder(s.WithOpName("weights_max"), DT_FLOAT); + auto quantize = ops::QuantizeAndDequantizeV2( + s.WithOpName("my_quantize"), input, weights_min, weights_max); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + AddTestTensor("weights_min", {1}); + AddTestTensor("weights_max", {1}); + RunValidationAndConversion( + node_def, error::INVALID_ARGUMENT, + "Min and max inputs for QuantizeAndDequantizeV2 must be weights not " + "tensors, at my_quantize"); + } + { + // QuantizeAndDequantizeV3 ranges set via inputs, ok. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto weights_min = ops::Placeholder(s.WithOpName("weights_min"), DT_FLOAT); + auto weights_max = ops::Placeholder(s.WithOpName("weights_max"), DT_FLOAT); + auto num_bits = ops::Placeholder(s.WithOpName("num_bits"), DT_INT32); + auto quantize = ops::QuantizeAndDequantizeV3( + s.WithOpName("my_quantize"), input, weights_min, weights_max, num_bits); + const NodeDef& node_def = quantize.operation.node()->def(); + AddTestTensor("input", {1, 2, 3}); + AddTestWeights("weights_min", {1}, {-6.0f}); + AddTestWeights("weights_max", {1}, {6.0f}); + AddTestWeights("num_bits", {1}, {8}); + RunValidationAndConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_quantize", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(1, ranges.count(output.tensor())); + EXPECT_EQ(6.0f, ranges[output.tensor()]); + } +} + +TEST_F(OpConverterTest, ConvertRelu6) { + { + // Input list is empty, should fail. + NodeDef node_def = MakeNodeDef("my_relu6", "Relu6", {}); + RunValidationAndConversion( + node_def, error::INVALID_ARGUMENT, + "Invalid number of inputs for Relu6, at my_relu6"); + } + + // Get the NodeDef for Relu6. + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto relu6 = ops::Relu6(s.WithOpName("my_relu6"), input); + const NodeDef node_def = relu6.operation.node()->def(); + { + // Input is weights, should fail. + Reset(); + AddTestWeights("input", {1}, {1.0f}); + RunValidationAndConversion( + node_def, error::UNIMPLEMENTED, + "Relu6 is only implemented for tensors, not weights, at my_relu6"); + } + { + // Clip tensor values and set quantization ranges, ok. + Reset(); + AddTestTensor("input", {1, 2, 3}); + RunValidationAndConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(GetTensorOrWeights("my_relu6", &output)); + EXPECT_TRUE(output.is_tensor()); + auto ranges = quantization_ranges(); + EXPECT_EQ(ranges[output.tensor()], 6.0f); + + std::vector output_data(6); + BuildAndRun({{"input", {-100, -1, 0, 3, 5, 9}}}, "my_relu6", + &output_data); + EXPECT_THAT(output_data, ElementsAre(0, 0, 0, 3, 5, 6)); + } +} + +template +void TestConvertSquare(OpConverterTest* test) { + test->Reset(); + typedef typename EnumToDataType::Type CType; + + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), dtype); + auto square = ops::Square(s.WithOpName("my_square"), input); + NodeDef node_def = square.operation.node()->def(); + + test->AddTestTensor("input", {1, 20}); + test->RunValidationAndConversion(node_def); + TRT_TensorOrWeights output; + TF_EXPECT_OK(test->GetTensorOrWeights("my_square", &output)); + EXPECT_TRUE(output.is_tensor()); + ExpectTrtDimsEqualsArray({1, 20}, output.tensor()->getDimensions()); + + const int num_inputs = 20; + std::vector input_data(num_inputs); + std::vector expected_output_data(num_inputs); + for (int i = 0; i < 20; i++) { + const CType value = CType(i - 9); + input_data[i] = value; + expected_output_data[i] = value * value; + } + std::vector output_data(num_inputs); + test->BuildAndRun({{"input", input_data}}, "my_square", &output_data); + ExpectArrayNear(expected_output_data, output_data); +} + +TEST_F(OpConverterTest, ConvertSquare) { + { + // Input list is empty, should fail. + NodeDef node_def = MakeNodeDef("my_square", "Square", {}); + RunValidationAndConversion(node_def, error::INVALID_ARGUMENT, + "Square expects one input, at my_square"); + } + { + // Input is weights, should fail. + Reset(); + Scope s = Scope::NewRootScope(); + auto input = ops::Placeholder(s.WithOpName("input"), DT_FLOAT); + auto square = ops::Square(s.WithOpName("my_square"), input); + NodeDef node_def = square.operation.node()->def(); + AddTestWeights("input", {1, 2, 3}, {1, 2, 3, 4, -5, 6}); + RunValidationAndConversion( + node_def, error::UNIMPLEMENTED, + "Square is only implemented for tensors, at my_square"); + } + + // OK. Note that kINT32 is not supported by IElementWiseLayer, so we don't + // test DT_INT32 type here. + TestConvertSquare(this); + // TODO(tmorris): Looks like there may be a bug with this layer for FP16 + // inputs. Disabling for now. + // TestConvertSquare(this); +} + } // namespace convert } // namespace tensorrt } // namespace tensorflow diff --git a/tensorflow/contrib/tensorrt/convert/trt_optimization_pass.cc b/tensorflow/contrib/tensorrt/convert/trt_optimization_pass.cc index b30d94b028..4ac7e21d34 100644 --- a/tensorflow/contrib/tensorrt/convert/trt_optimization_pass.cc +++ b/tensorflow/contrib/tensorrt/convert/trt_optimization_pass.cc @@ -67,6 +67,9 @@ tensorflow::Status TRTOptimizationPass::Init( TF_RETURN_IF_ERROR(GetPrecisionMode( Uppercase(params.at("precision_mode").s()), &precision_mode_)); } + if (params.count("use_calibration")) { + use_calibration_ = params.at("use_calibration").b(); + } return tensorflow::Status::OK(); } @@ -222,6 +225,12 @@ tensorflow::Status TRTOptimizationPass::Optimize( TF_RETURN_IF_ERROR(static_graph_properties.InferStatically(true)); tensorflow::tensorrt::convert::ConversionParams cp; + if (use_calibration_ && precision_mode_ != INT8MODE) { + LOG(ERROR) << "Calibration with FP32 or FP16 is not implemented. " + << "Falling back to use_calibration = False."; + use_calibration_ = false; + } + std::vector nodes_to_preserve; for (const auto& n : item.NodesToPreserve()) { auto tokens = str_util::Split(n, ":"); @@ -250,6 +259,7 @@ tensorflow::Status TRTOptimizationPass::Optimize( cp.is_dyn_op = is_dynamic_op_; cp.cached_engine_batches = batches_; cp.max_cached_engines = max_cached_batches_; + cp.use_calibration = use_calibration_; auto status = tensorflow::tensorrt::convert::ConvertAfterShapes(cp); VLOG(1) << "Returning from " << name_; return status; diff --git a/tensorflow/contrib/tensorrt/convert/trt_optimization_pass.h b/tensorflow/contrib/tensorrt/convert/trt_optimization_pass.h index 71b51d1368..3e8dc0978e 100644 --- a/tensorflow/contrib/tensorrt/convert/trt_optimization_pass.h +++ b/tensorflow/contrib/tensorrt/convert/trt_optimization_pass.h @@ -38,7 +38,8 @@ class TRTOptimizationPass : public tensorflow::grappler::CustomGraphOptimizer { maximum_batch_size_(-1), is_dynamic_op_(false), max_cached_batches_(1), - max_workspace_size_bytes_(256LL << 20) { + max_workspace_size_bytes_(256LL << 20), + use_calibration_(true) { VLOG(1) << "Constructing " << name_; } @@ -67,6 +68,7 @@ class TRTOptimizationPass : public tensorflow::grappler::CustomGraphOptimizer { std::vector batches_; int max_cached_batches_; int64_t max_workspace_size_bytes_; + bool use_calibration_; }; } // namespace convert diff --git a/tensorflow/contrib/tensorrt/kernels/trt_engine_op.cc b/tensorflow/contrib/tensorrt/kernels/trt_engine_op.cc index 019446813a..117039683c 100644 --- a/tensorflow/contrib/tensorrt/kernels/trt_engine_op.cc +++ b/tensorflow/contrib/tensorrt/kernels/trt_engine_op.cc @@ -124,8 +124,10 @@ TRTEngineOp::TRTEngineOp(OpKernelConstruction* context) OP_REQUIRES_OK(context, context->GetAttr("segment_funcdef_name", &funcdef_name_)); OP_REQUIRES_OK(context, GetPrecisionMode(precision_string, &precision_mode_)); - calibration_mode_ = - (precision_mode_ == INT8MODE && calibration_data.size() == 0); + OP_REQUIRES_OK(context, + context->GetAttr("use_calibration", &use_calibration_)); + calibration_mode_ = (use_calibration_ && precision_mode_ == INT8MODE && + calibration_data.size() == 0); if (calibration_data.size()) { calibrator_.reset(new TRTInt8Calibrator(calibration_data)); calibration_data.resize(0); @@ -252,9 +254,8 @@ int TRTEngineOp::GetEngineBatch(OpKernelContext* ctx) { cached_engine_batches_.push_back(num_batch); VLOG(1) << "Running with batch size " << num_batch; } else { - string msg = - StrCat("Engine buffer is full. buffer limit=", max_cached_engines_, - ", current entries="); + string msg = StrCat("Engine buffer is full. buffer limit=", + max_cached_engines_, ", current entries="); for (auto i : cached_engine_batches_) StrAppend(&msg, i, ","); StrAppend(&msg, " requested batch=", num_batch); LOG(WARNING) << msg; @@ -308,7 +309,7 @@ bool TRTEngineOp::ExecuteTrtEngine( std::vector buffers(num_binding); for (int i = 0; i < ctx->num_inputs(); i++) { const string input_name = StrCat(kInputPHName, i); - const size_t binding_index = + const int binding_index = trt_engine_ptr->getBindingIndex(input_name.c_str()); if (binding_index == -1) { LOG(ERROR) << "Input node not found, at " << input_name; @@ -345,7 +346,7 @@ bool TRTEngineOp::ExecuteTrtEngine( for (int i = 0; i < ctx->num_outputs(); i++) { // Create an output tensor const string output_name = StrCat(kOutputPHName, i); - const size_t binding_index = + const int binding_index = trt_engine_ptr->getBindingIndex(output_name.c_str()); Tensor* output_tensor = nullptr; @@ -491,13 +492,14 @@ TRTEngineOp::EngineCtxPair& TRTEngineOp::GetEngine(int batch_size, } TrtUniquePtrType engine; bool convert_successfully = false; - VLOG(0) << name() << " Constructing a new engine with batch size " - << batch_size; + LOG(INFO) << "Building a new TensorRT engine for " << name() + << " with batch size " << batch_size; // Up to this point, calibrator_ can never be empty, since otherwise it // means calibration_mode_ is true and this path won't get executed. auto status = convert::ConvertGraphDefToEngine( segment_graph_, precision_mode_, batch_size, workspace_size_, shapes, - &logger, allocator, calibrator_.get(), &engine, &convert_successfully); + &logger, allocator, calibrator_.get(), &engine, use_calibration_, + &convert_successfully); if (!status.ok()) { if (convert_successfully) { // This means it fail to build the engine even when the network is built @@ -567,8 +569,8 @@ tensorflow::Status TRTEngineOp::AllocateCalibrationResources( const int64 workspace_size_bytes = workspace_size_; cres->thr_.reset(new std::thread([cres, label, segment_graph, shapes, platform_gpu_id, workspace_size_bytes]() { - VLOG(0) << "Starting calibration thread on device " << platform_gpu_id - << ", Calibration Resource @ " << cres; + LOG(INFO) << "Starting calibration thread on device " << platform_gpu_id + << ", Calibration Resource @ " << cres; auto err = cudaSetDevice(platform_gpu_id); if (err != cudaSuccess) { // TODO(aaroey): should return error here. @@ -586,6 +588,7 @@ tensorflow::Status TRTEngineOp::AllocateCalibrationResources( *segment_graph, INT8MODE, cres->calibrator_->getBatchSize(), workspace_size_bytes, shapes, &cres->logger_, cres->allocator_.get(), cres->calibrator_.get(), &cres->engine_, + /*use_calibration=*/true, /*convert_successfully=*/nullptr); if (!s.ok()) { LOG(ERROR) << "Calibration failed: " << s; diff --git a/tensorflow/contrib/tensorrt/kernels/trt_engine_op.h b/tensorflow/contrib/tensorrt/kernels/trt_engine_op.h index 8fe0675891..b545f497f3 100644 --- a/tensorflow/contrib/tensorrt/kernels/trt_engine_op.h +++ b/tensorflow/contrib/tensorrt/kernels/trt_engine_op.h @@ -130,6 +130,10 @@ class TRTEngineOp : public AsyncOpKernel { // The finalized calibrator for inference. std::unique_ptr calibrator_; + + // If true, create calibration graph for INT8 mode. Otherwise, we are using + // user-provided quantization ranges. + bool use_calibration_; }; } // namespace tensorrt diff --git a/tensorflow/contrib/tensorrt/ops/trt_engine_op.cc b/tensorflow/contrib/tensorrt/ops/trt_engine_op.cc index e0c7b62723..92405906eb 100644 --- a/tensorflow/contrib/tensorrt/ops/trt_engine_op.cc +++ b/tensorflow/contrib/tensorrt/ops/trt_engine_op.cc @@ -16,6 +16,7 @@ limitations under the License. #if GOOGLE_CUDA #if GOOGLE_TENSORRT +#include "tensorflow/core/framework/common_shape_fns.h" #include "tensorflow/core/framework/op.h" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/framework/shape_inference.h" @@ -39,18 +40,19 @@ REGISTER_OP("TRTEngineOp") .Attr("cached_engine_batches: list(int) = []") .Attr("max_cached_engines_count: int = 1") .Attr("workspace_size_bytes: int") - .Attr("precision_mode: {'FP32', 'FP16', 'INT8', 'INT8CALIB'}") + .Attr("precision_mode: {'FP32', 'FP16', 'INT8'}") .Attr("calibration_data: string = ''") + .Attr("use_calibration: bool = true") .Input("in_tensor: InT") - .Output("out_tensor: OutT"); -// TODO(jie): TF requires concrete output shape for concrete input shapes. -// This is tricky for batch dimension, since we cannot ensure which input -// would carry the correct batch dimension (for the current stage of the -// implementation, we do require all input tensor to carry the same batch -// size, but this could change in the future). Hence we disable shape -// inference function as a workaround. -// .SetShapeFn(shape_inference::TRTEngineOpShapeInference); - + .Output("out_tensor: OutT") + // TODO(jie): TF requires concrete output shape for concrete input shapes. + // This is tricky for batch dimension, since we cannot ensure which input + // would carry the correct batch dimension (for the current stage of the + // implementation, we do require all input tensor to carry the same batch + // size, but this could change in the future). Hence we disable shape + // inference function as a workaround. + // .SetShapeFn(shape_inference::TRTEngineOpShapeInference); + .SetShapeFn(shape_inference::UnknownShape); } // namespace tensorflow #endif // GOOGLE_TENSORRT diff --git a/tensorflow/contrib/tensorrt/python/trt_convert.py b/tensorflow/contrib/tensorrt/python/trt_convert.py index bb81fbf93f..74a2c2392a 100644 --- a/tensorflow/contrib/tensorrt/python/trt_convert.py +++ b/tensorflow/contrib/tensorrt/python/trt_convert.py @@ -63,19 +63,20 @@ class TrtPrecisionMode(object): return [TrtPrecisionMode.FP32, TrtPrecisionMode.FP16, TrtPrecisionMode.INT8] -def tensorrt_rewriter_config(rewriter_config=None, - max_batch_size=1, - max_workspace_size_bytes=2 << 20, - precision_mode=TrtPrecisionMode.FP32, - minimum_segment_size=3, - is_dynamic_op=False, - maximum_cached_engines=1, - cached_engine_batch_sizes=None): +def get_tensorrt_rewriter_config(rewriter_config=None, + max_batch_size=1, + max_workspace_size_bytes=2 << 20, + precision_mode=TrtPrecisionMode.FP32, + minimum_segment_size=3, + is_dynamic_op=False, + maximum_cached_engines=1, + cached_engine_batch_sizes=None, + use_calibration=True): """Returns a RewriterConfig proto for TRT transformation. Args: - rewriter_config: a RewriterConfig proto to append the TensorRTOptimizer to. - If None, it will create one with default settings. + rewriter_config: a template RewriterConfig proto used to create a + TRT-enabled RewriterConfig. If None, it will use a default one. max_batch_size: max size for the input batch max_workspace_size_bytes: the maximum GPU temporary memory which the TRT engine can use at execution time. This corresponds to the 'workspaceSize' @@ -95,6 +96,15 @@ def tensorrt_rewriter_config(rewriter_config=None, use this list to determine the batch sizes of the cached engines, instead of making the decision on the fly. This is useful when we know the most common batch size(s) the application is going to generate. + use_calibration: this argument is ignored if precision_mode is not INT8. if + set to True, a calibration graph will be created to calibrate the missing + ranges. The calibration graph must be converted to an inference graph + using calib_graph_to_infer_graph() after running calibration. if set to + False, quantization nodes will be expected for every tensor in the graph + (exlcuding those which will be fused). If a range is missing, an error + will occur. Please note that accuracy may be negatively affected if there + is a mismatch between which tensors TRT quantizes and which tensors were + trained with fake quantization. Returns: A RewriterConfig proto which sets a TensorRTOptimizer to run Grappler. @@ -107,13 +117,16 @@ def tensorrt_rewriter_config(rewriter_config=None, rewriter_config, rewriter_config_pb2.RewriterConfig): raise TypeError("rewriter_config should be a RewriterConfig proto.") + rewriter_config_with_trt = rewriter_config_pb2.RewriterConfig() if rewriter_config is None: - rewriter_config = rewriter_config_pb2.RewriterConfig() # Layout optimizer may add Const nodes followed by Reshape nodes, thus we # need to run constant folding again. - rewriter_config.optimizers.extend(["constfold", "layout", "constfold"]) - rewriter_config.meta_optimizer_iterations = ( + rewriter_config_with_trt.optimizers.extend( + ["constfold", "layout", "constfold"]) + rewriter_config_with_trt.meta_optimizer_iterations = ( rewriter_config_pb2.RewriterConfig.ONE) + else: + rewriter_config_with_trt.CopyFrom(rewriter_config) if precision_mode.upper() not in TrtPrecisionMode.supported_precision_modes(): raise ValueError(("precision mode '{}' is not supported." @@ -121,7 +134,7 @@ def tensorrt_rewriter_config(rewriter_config=None, precision_mode, TrtPrecisionMode.supported_precision_modes)) - optimizer = rewriter_config.custom_optimizers.add() + optimizer = rewriter_config_with_trt.custom_optimizers.add() optimizer.name = "TensorRTOptimizer" optimizer.parameter_map["minimum_segment_size"].i = minimum_segment_size optimizer.parameter_map["max_batch_size"].i = max_batch_size @@ -138,7 +151,8 @@ def tensorrt_rewriter_config(rewriter_config=None, "maximum_cached_engines items.") optimizer.parameter_map["cached_engine_batches"].list.i.extend( cached_engine_batch_sizes) - return rewriter_config + optimizer.parameter_map["use_calibration"].b = use_calibration + return rewriter_config_with_trt def create_inference_graph(input_graph_def, @@ -150,7 +164,7 @@ def create_inference_graph(input_graph_def, is_dynamic_op=False, maximum_cached_engines=1, cached_engine_batch_sizes=None, - rewriter_config=None, + use_calibration=True, input_saved_model_dir=None, input_saved_model_tags=None, output_saved_model_dir=None, @@ -182,8 +196,15 @@ def create_inference_graph(input_graph_def, use this list to determine the batch sizes of the cached engines, instead of making the decision on the fly. This is useful when we know the most common batch size(s) the application is going to generate. - rewriter_config: a RewriterConfig proto to append the TensorRTOptimizer to. - If None, it will create one with default settings. + use_calibration: this argument is ignored if precision_mode is not INT8. if + set to True, a calibration graph will be created to calibrate the missing + ranges. The calibration graph must be converted to an inference graph + using calib_graph_to_infer_graph() after running calibration. if set to + False, quantization nodes will be expected for every tensor in the graph + (exlcuding those which will be fused). If a range is missing, an error + will occur. Please note that accuracy may be negatively affected if there + is a mismatch between which tensors TRT quantizes and which tensors were + trained with fake quantization. input_saved_model_dir: the directory to load the SavedModel which contains the input graph to transforms. Used only when input_graph_def is None. input_saved_model_tags: list of tags to load the SavedModel. @@ -191,8 +212,9 @@ def create_inference_graph(input_graph_def, returned GraphDef and save it to the specified directory. This option only works when the input graph is loaded from a SavedModel, i.e. when input_saved_model_dir is specified and input_graph_def is None. - session_config: the ConfigProto used to create a Session. If not specified, - a default ConfigProto will be used. + session_config: the ConfigProto used to create a Session. It's also used as + a template to create a TRT-enabled ConfigProto for conversion. If not + specified, a default ConfigProto will be used. Returns: A GraphDef transformed from input_graph_def (or the SavedModel graph def @@ -322,21 +344,30 @@ def create_inference_graph(input_graph_def, grappler_meta_graph_def.collection_def["train_op"].CopyFrom( output_collection) - # Create RewriterConfig. - rewriter_config = tensorrt_rewriter_config( + # Create TRT-enabled ConfigProto. + session_config_with_trt = config_pb2.ConfigProto() + session_config_with_trt.CopyFrom(session_config) + rewriter_config = None + if (session_config_with_trt.HasField("graph_options") and + session_config_with_trt.graph_options.HasField("rewrite_options")): + rewriter_config = session_config_with_trt.graph_options.rewrite_options + rewriter_config_with_trt = get_tensorrt_rewriter_config( rewriter_config, max_batch_size, max_workspace_size_bytes, precision_mode, minimum_segment_size, is_dynamic_op, maximum_cached_engines, - cached_engine_batch_sizes) + cached_engine_batch_sizes, use_calibration) + session_config_with_trt.graph_options.rewrite_options.CopyFrom( + rewriter_config_with_trt) # Run Grappler. transformed_graph_def = tf_optimizer.OptimizeGraph( - rewriter_config, grappler_meta_graph_def, graph_id=b"tf_graph") + session_config_with_trt, grappler_meta_graph_def, graph_id=b"tf_graph") # Optionally write the transformed graphdef as SavedModel. if output_saved_model_dir is not None: saved_model_builder = builder.SavedModelBuilder(output_saved_model_dir) with ops.Graph().as_default(): importer.import_graph_def(transformed_graph_def, name="") + # We don't use TRT here. with session.Session(config=session_config) as sess: saved_model_builder.add_meta_graph_and_variables( sess, diff --git a/tensorflow/contrib/tensorrt/python/trt_convert_test.py b/tensorflow/contrib/tensorrt/python/trt_convert_test.py index 9f2eeac990..dbf8dd2614 100644 --- a/tensorflow/contrib/tensorrt/python/trt_convert_test.py +++ b/tensorflow/contrib/tensorrt/python/trt_convert_test.py @@ -47,9 +47,9 @@ from tensorflow.python.tools import saved_model_utils class TrtConvertTest(test_util.TensorFlowTestCase): """Class to test Tensorflow-TensorRT integration python API.""" - def testTensorrtRewriterConfig(self): - """Test case for trt_convert.tensorrt_rewriter_config().""" - rewriter_cfg = trt_convert.tensorrt_rewriter_config( + def testGetTensorrtRewriterConfig(self): + """Test case for trt_convert.get_tensorrt_rewriter_config().""" + rewriter_cfg = trt_convert.get_tensorrt_rewriter_config( rewriter_config=None, max_batch_size=128, max_workspace_size_bytes=1234, @@ -162,7 +162,7 @@ class TrtConvertTest(test_util.TensorFlowTestCase): node_name_to_op = {node.name: node.op for node in graph_def.node} self.assertEqual({ "input": "Placeholder", - "my_trt_op_0": "TRTEngineOp", + "TRTEngineOp_0": "TRTEngineOp", "output": "Identity" }, node_name_to_op) @@ -189,10 +189,11 @@ class TrtConvertTest(test_util.TensorFlowTestCase): execute_engine_test_value = ("done" if expect_engine_is_run else "") execute_native_segment_test_value = ("" if expect_engine_is_run else "done") self.assertEqual(execute_engine_test_value, - trt_convert.get_test_value("my_trt_op_0:ExecuteTrtEngine")) + trt_convert.get_test_value( + "TRTEngineOp_0:ExecuteTrtEngine")) self.assertEqual( execute_native_segment_test_value, - trt_convert.get_test_value("my_trt_op_0:ExecuteNativeSegment")) + trt_convert.get_test_value("TRTEngineOp_0:ExecuteNativeSegment")) def testCreateInferenceGraph_MinimumSegmentSize(self): if not trt_convert.is_tensorrt_enabled(): diff --git a/tensorflow/contrib/tensorrt/resources/trt_resources.h b/tensorflow/contrib/tensorrt/resources/trt_resources.h index 840da6e78d..aac9e5c7bd 100644 --- a/tensorflow/contrib/tensorrt/resources/trt_resources.h +++ b/tensorflow/contrib/tensorrt/resources/trt_resources.h @@ -39,7 +39,8 @@ namespace tensorrt { class TRTCalibrationResource : public tensorflow::ResourceBase { public: ~TRTCalibrationResource() { - VLOG(0) << "Destroying Calibration Resource " << std::endl << DebugString(); + LOG(INFO) << "Destroying Calibration Resource " << std::endl + << DebugString(); builder_.reset(); engine_.reset(); // We need to manually destroy the builder and engine before the allocator diff --git a/tensorflow/contrib/tensorrt/segment/segment.cc b/tensorflow/contrib/tensorrt/segment/segment.cc index 4f64b7a952..d8f63779e6 100644 --- a/tensorflow/contrib/tensorrt/segment/segment.cc +++ b/tensorflow/contrib/tensorrt/segment/segment.cc @@ -33,6 +33,7 @@ namespace tensorflow { namespace tensorrt { namespace segment { using ::tensorflow::strings::StrAppend; +using ::tensorflow::strings::StrCat; // A simple graph representation to mirror tensorflow::Graph. This structure // helps saving memory since segmenter modifies the graph in place, preventing @@ -406,22 +407,42 @@ tensorflow::Status SegmentGraph( // Use a union-find to collect the nodes that belong to the same // segment. A node value of nullptr indicates that the node is not a candidate // for TRT. + std::unordered_set unsupported_ops; + int num_unsupported_ops = 0; std::vector> node_segments; for (int i = 0; i < graph->num_node_ids(); ++i) { SimpleNode* node = graph->FindNodeId(i); if (options.exclude_node_list.count(node->name()) != 0) { - VLOG(1) << "Not a TF-TRT candidate: " << node->name() - << " (excluded by segmenter option)."; + VLOG(1) << "Not a TF-TRT candidate, " + << "(Op type: " << node->tf_node()->type_string() << "), " + << "(Op name: " << node->name() << "), " + << "(Reason: excluded by segmenter option)"; + unsupported_ops.emplace(node->tf_node()->type_string()); + num_unsupported_ops++; node = nullptr; } else { const Status status = candidate_fn(node->tf_node()); if (!status.ok()) { - VLOG(1) << "Not a TF-TRT candidate: " << node->name() << ": " << status; + VLOG(1) << "Not a TF-TRT candidate, " + << "(Op type: " << node->tf_node()->type_string() << "), " + << "(Op name: " << node->name() << "), " + << "(Reason: " << status << ")"; + unsupported_ops.emplace(node->tf_node()->type_string()); + num_unsupported_ops++; node = nullptr; } } node_segments.emplace_back(node); } + string msg = StrCat( + "There are ", num_unsupported_ops, " ops of ", unsupported_ops.size(), + " different types in the graph that", " are not converted to TensorRT: "); + for (const auto& elem : unsupported_ops) { + StrAppend(&msg, elem, ", "); + } + LOG(INFO) << msg << "(For more information see " + << "https://docs.nvidia.com/deeplearning" + << "/dgx/integrate-tf-trt/index.html#support-ops)."; // The segmentation algorithm below visits nodes in reverse topological order // and attempts to merge nodes along output edges. That means that subgraphs @@ -439,7 +460,8 @@ tensorflow::Status SegmentGraph( std::vector order; order.reserve(graph->num_node_ids()); StableDFS(*graph, /*reverse=*/false, {graph->source_node()}, - /*enter=*/nullptr, [&order](const SimpleNode* n) { + /*enter=*/nullptr, + [&order](const SimpleNode* n) { order.push_back(n); return true; }); @@ -548,7 +570,7 @@ tensorflow::Status SegmentGraph( std::set& segment_nodes = itr.second; VLOG(1) << "Segment original size: " << segment_nodes.size(); while (true) { - std::deque in_nodes_que, out_nodes_que; + std::deque in_nodes_que, out_nodes_que; // Find an input node that is not eligible and add it to the queue. // Nodes that has no incoming edges should not be treated as "input", // as there are really no inputs to them. Similar for output nodes. @@ -594,8 +616,7 @@ tensorflow::Status SegmentGraph( // their outputs. In this way, for common cases the number of removed // nodes should be minimum. auto remove_nodes = [&segment_nodes]( - bool is_input_nodes, - std::deque* que) { + bool is_input_nodes, std::deque* que) { // Run a BFS on the queue to find all the input/output nodes. std::set visited; std::set logged(que->begin(), que->end()); diff --git a/tensorflow/contrib/tensorrt/test/base_test.py b/tensorflow/contrib/tensorrt/test/base_test.py index 18096e0ff1..03faf1df24 100644 --- a/tensorflow/contrib/tensorrt/test/base_test.py +++ b/tensorflow/contrib/tensorrt/test/base_test.py @@ -56,8 +56,9 @@ class SimpleSingleEngineTest(trt_test.TfTrtIntegrationTestBase): strides=[1, 2, 2, 1], padding="SAME", name="conv") - bias = constant_op.constant( - [4., 1.5, 2., 3., 5., 7.], name="bias", dtype=dtype) + bias = constant_op.constant([4., 1.5, 2., 3., 5., 7.], + name="bias", + dtype=dtype) added = nn.bias_add(conv, bias, name="bias_add") relu = nn.relu(added, "relu") identity = array_ops.identity(relu, "identity") @@ -73,11 +74,12 @@ class SimpleSingleEngineTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" - # TODO(aaroey): LayoutOptimizer adds additional nodes to the graph which - # breaks the connection check, fix it. - # - my_trt_op_0 should have ["weights", "conv", "bias", "bias_add", - # "relu", "identity", "max_pool"] - return ["my_trt_op_0"] + return { + "my_trt_op_0": [ + "weights", "conv", "bias", "bias_add", "relu", "identity", + "max_pool" + ] + } class SimpleMultiEnginesTest(trt_test.TfTrtIntegrationTestBase): @@ -92,7 +94,7 @@ class SimpleMultiEnginesTest(trt_test.TfTrtIntegrationTestBase): g = ops.Graph() with g.as_default(): inp = array_ops.placeholder( - dtype=dtype, shape=[None] + input_dims[1:], name=input_name) + dtype=dtype, shape=input_dims, name=input_name) with g.device("/GPU:0"): conv_filter = constant_op.constant( [[[[1., 0.5, 4., 6., 0.5, 1.], [1., 0.5, 1., 1., 0.5, 1.]]]], @@ -105,10 +107,10 @@ class SimpleMultiEnginesTest(trt_test.TfTrtIntegrationTestBase): padding="SAME", name="conv") c1 = constant_op.constant( - np.random.randn(input_dims[0], 12, 12, 6), dtype=dtype, name="c1") + np.random.randn(12, 12, 6), dtype=dtype, name="c1") p = math_ops.mul(conv, c1, name="mul") c2 = constant_op.constant( - np.random.randn(input_dims[0], 12, 12, 6), dtype=dtype, name="c2") + np.random.randn(12, 12, 6), dtype=dtype, name="c2") q = math_ops.div(conv, c2, name="div") edge = self.trt_incompatible_op(q, name="incompatible") @@ -129,22 +131,21 @@ class SimpleMultiEnginesTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" - # TODO(aaroey): LayoutOptimizer adds additional nodes to the graph which - # breaks the connection check, fix it. - # - my_trt_op_0 should have ["mul", "sub", "div1", "mul1", "add1", - # "add", "sub1"]; - # - my_trt_op_1 should have ["weights","conv", "div"] - return ["my_trt_op_0", "my_trt_op_1"] + return { + "my_trt_op_0": [ + "add", "add1", "c1", "div1", "mul", "mul1", "sub", "sub1" + ], + "my_trt_op_1": ["c2", "conv", "div", "weights"] + } - def ShouldRunTest(self, run_params): - # TODO(aaroey): LayoutOptimizer adds Transpose(Const, Const) to the graph - # which breaks the conversion. We should fix it as: - # - Detect the invalid NodeDef earlier before adding them to segment - # - Let it able to change the RewriterConfig when calling - # create_inference_graph(). - # It will be good to add debugging feature for Grappler to print the graph - # after running each optimizer. - return False + def GetConversionParams(self, run_params): + """Return a ConversionParams for test.""" + return super( + SimpleMultiEnginesTest, self + ).GetConversionParams(run_params)._replace( + # Disable layout optimizer, since it'll add Transpose(Const, Const) to + # the graph and breaks the conversion check. + rewriter_config=trt_test.OptimizerDisabledRewriterConfig()) class PartiallyConvertedTestA(trt_test.TfTrtIntegrationTestBase): @@ -153,7 +154,7 @@ class PartiallyConvertedTestA(trt_test.TfTrtIntegrationTestBase): """Setup method.""" super(PartiallyConvertedTestA, self).setUp() # Let it fail to build the second engine. - trt_convert.add_test_value("my_trt_op_1:CreateTRTNode", "fail") + trt_convert.add_test_value("TRTEngineOp_1:CreateTRTNode", "fail") def GetParams(self): """Create a graph containing two segment.""" @@ -190,14 +191,16 @@ class PartiallyConvertedTestA(trt_test.TfTrtIntegrationTestBase): """Return the expected engines to build.""" return { # Only the first engine is built. - "my_trt_op_0": ["c0", "c1", "add0", "add1", "mul0", "mul1"] + "TRTEngineOp_0": ["c0", "c1", "add0", "add1", "mul0", "mul1"] } def ShouldRunTest(self, run_params): """Whether to run the test.""" # Disable the test in fp16 mode since multiple matmul and add ops together # can cause overflow. - return run_params.precision_mode != "FP16" + return ((run_params.precision_mode != "FP16") and + not (trt_test.IsQuantizationMode(run_params.precision_mode) and + not run_params.use_calibration)) class PartiallyConvertedTestB(PartiallyConvertedTestA): @@ -207,13 +210,13 @@ class PartiallyConvertedTestB(PartiallyConvertedTestA): super(PartiallyConvertedTestB, self).setUp() # Let it fail to build the first engine. trt_convert.clear_test_values("") - trt_convert.add_test_value("my_trt_op_0:CreateTRTNode", "fail") + trt_convert.add_test_value("TRTEngineOp_0:CreateTRTNode", "fail") def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" return { # Only the second engine is built. - "my_trt_op_1": ["c2", "c3", "add2", "add3", "mul2", "mul3"] + "TRTEngineOp_1": ["c2", "c3", "add2", "add3", "mul2", "mul3"] } @@ -257,8 +260,8 @@ class ConstInputTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" return { - "my_trt_op_0": ["add", "add1", "mul"], - "my_trt_op_1": ["add2", "add3", "mul1"] + "TRTEngineOp_0": ["add", "add1", "mul"], + "TRTEngineOp_1": ["add2", "add3", "mul1"] } @@ -289,7 +292,7 @@ class ConstDataInputSingleEngineTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" - return {"my_trt_op_0": ["c", "add", "add1", "mul"]} + return {"TRTEngineOp_0": ["c", "add", "add1", "mul"]} class ConstDataInputMultipleEnginesTest(trt_test.TfTrtIntegrationTestBase): @@ -324,12 +327,12 @@ class ConstDataInputMultipleEnginesTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" return { - "my_trt_op_0": ["add2", "add3", "mul1"], + "TRTEngineOp_0": ["add2", "add3", "mul1"], # Why segment ["add", "add1", "mul"] was assigned segment id 1 # instead of 0: the parent node of this segment is actually const # node 'c', but it's removed later since it's const output of the # segment which is not allowed. - "my_trt_op_1": ["add", "add1", "mul"] + "TRTEngineOp_1": ["add", "add1", "mul"] } @@ -373,8 +376,8 @@ class ControlDependencyTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" return { - "my_trt_op_0": ["c1", "add", "add1", "mul"], - "my_trt_op_1": ["c2", "add2", "add3", "mul1"] + "TRTEngineOp_0": ["c1", "add", "add1", "mul"], + "TRTEngineOp_1": ["c2", "add2", "add3", "mul1"] } diff --git a/tensorflow/contrib/tensorrt/test/batch_matmul_test.py b/tensorflow/contrib/tensorrt/test/batch_matmul_test.py index 4b88808178..f42308ecb7 100644 --- a/tensorflow/contrib/tensorrt/test/batch_matmul_test.py +++ b/tensorflow/contrib/tensorrt/test/batch_matmul_test.py @@ -79,12 +79,12 @@ class BatchMatMulTest(trt_test.TfTrtIntegrationTestBase): """Return the expected engines to build.""" if (run_params.dynamic_engine and not trt_test.IsQuantizationMode(run_params.precision_mode)): - return ["my_trt_op_0", "my_trt_op_1"] - return ["my_trt_op_1"] + return ["TRTEngineOp_0", "TRTEngineOp_1"] + return ["TRTEngineOp_1"] def ExpectedEnginesToRun(self, run_params): """Return the expected engines to run.""" - return ["my_trt_op_1"] + return ["TRTEngineOp_1"] def ShouldRunTest(self, run_params): """Whether to run the test.""" diff --git a/tensorflow/contrib/tensorrt/test/biasadd_matmul_test.py b/tensorflow/contrib/tensorrt/test/biasadd_matmul_test.py index 7545bb9df2..053b38ff1c 100644 --- a/tensorflow/contrib/tensorrt/test/biasadd_matmul_test.py +++ b/tensorflow/contrib/tensorrt/test/biasadd_matmul_test.py @@ -41,6 +41,7 @@ class BiasaddMatMulTest(trt_test.TfTrtIntegrationTestBase): input_name = "input" input_matrix_rows = 4 input_matrix_columns = 144 + # Note that tf.nn.bias_add supports up to 5 dimensions. input_dims = [input_matrix_rows, input_matrix_columns] output_name = "output" g = ops.Graph() @@ -74,18 +75,18 @@ class BiasaddMatMulTest(trt_test.TfTrtIntegrationTestBase): x5 = nn.bias_add(x5, b) x5 = gen_array_ops.reshape(x5, [4, -1]) - x6 = gen_array_ops.reshape(x, [4, 12, 12]) - b = self._ConstOp((12,)) + x6 = gen_array_ops.reshape(x, [4, 24, 6]) + b = self._ConstOp((6,)) x6 = nn.bias_add(x6, b, data_format="NHWC") x6 = gen_array_ops.reshape(x6, [4, -1]) - x7 = gen_array_ops.reshape(x, [4, 12, 3, 4]) - b = self._ConstOp((4,)) + x7 = gen_array_ops.reshape(x, [4, 12, 4, 3]) + b = self._ConstOp((3,)) x7 = nn.bias_add(x7, b, data_format="NHWC") x7 = gen_array_ops.reshape(x7, [4, -1]) - x8 = gen_array_ops.reshape(x, [4, 12, 3, 2, 2]) - b = self._ConstOp((2,)) + x8 = gen_array_ops.reshape(x, [4, 4, 3, 2, 6]) + b = self._ConstOp((6,)) x8 = nn.bias_add(x8, b, data_format="NHWC") x8 = gen_array_ops.reshape(x8, [4, -1]) @@ -94,13 +95,13 @@ class BiasaddMatMulTest(trt_test.TfTrtIntegrationTestBase): x9 = nn.bias_add(x9, b, data_format="NCHW") x9 = gen_array_ops.reshape(x9, [4, -1]) - x10 = gen_array_ops.reshape(x, [4, 12, 3, 4]) - b = self._ConstOp((12,)) + x10 = gen_array_ops.reshape(x, [4, 3, 4, 12]) + b = self._ConstOp((3,)) x10 = nn.bias_add(x10, b, data_format="NCHW") x10 = gen_array_ops.reshape(x10, [4, -1]) - x11 = gen_array_ops.reshape(x, [4, 12, 12]) - b = self._ConstOp((12,)) + x11 = gen_array_ops.reshape(x, [4, 6, 24]) + b = self._ConstOp((6,)) x11 = nn.bias_add(x11, b, data_format="NCHW") x11 = gen_array_ops.reshape(x11, [4, -1]) @@ -116,13 +117,18 @@ class BiasaddMatMulTest(trt_test.TfTrtIntegrationTestBase): def GetConversionParams(self, run_params): """Return a ConversionParams for test.""" - return super(BiasaddMatMulTest, - self).GetConversionParams(run_params)._replace( - max_batch_size=4, maximum_cached_engines=1) + conversion_params = super(BiasaddMatMulTest, + self).GetConversionParams(run_params) + return conversion_params._replace( + max_batch_size=4, + maximum_cached_engines=1, + # Disable layout optimizer, since it will convert BiasAdd with NHWC + # format to NCHW format under four dimentional input. + rewriter_config=trt_test.OptimizerDisabledRewriterConfig()) def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" - return ["my_trt_op_0"] + return ["TRTEngineOp_0"] def ShouldRunTest(self, run_params): """Whether to run the test.""" diff --git a/tensorflow/contrib/tensorrt/test/binary_tensor_weight_broadcast_test.py b/tensorflow/contrib/tensorrt/test/binary_tensor_weight_broadcast_test.py index b53cb3c091..169835956c 100644 --- a/tensorflow/contrib/tensorrt/test/binary_tensor_weight_broadcast_test.py +++ b/tensorflow/contrib/tensorrt/test/binary_tensor_weight_broadcast_test.py @@ -26,7 +26,6 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_array_ops -from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -56,10 +55,10 @@ class BinaryTensorWeightBroadcastTest(trt_test.TfTrtIntegrationTestBase): ]: a = self._ConstOp(weights_shape) f = x + a - x = math_ops.sigmoid(f) + x = self.trt_incompatible_op(f) a = self._ConstOp(weights_shape) f = a + x - x = math_ops.sigmoid(f) + x = self.trt_incompatible_op(f) gen_array_ops.reshape(x, [5, -1], name=output_name) return trt_test.TfTrtIntegrationTestParams( gdef=g.as_graph_def(), @@ -70,7 +69,7 @@ class BinaryTensorWeightBroadcastTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" - return ["my_trt_op_%d" % i for i in range(16)] + return ["TRTEngineOp_%d" % i for i in range(16)] if __name__ == "__main__": diff --git a/tensorflow/contrib/tensorrt/test/concatenation_test.py b/tensorflow/contrib/tensorrt/test/concatenation_test.py index 465cb02296..c3576f81d9 100644 --- a/tensorflow/contrib/tensorrt/test/concatenation_test.py +++ b/tensorflow/contrib/tensorrt/test/concatenation_test.py @@ -79,7 +79,7 @@ class ConcatenationTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" - return ["my_trt_op_0"] + return ["TRTEngineOp_0"] if __name__ == "__main__": diff --git a/tensorflow/contrib/tensorrt/test/const_broadcast_test.py b/tensorflow/contrib/tensorrt/test/const_broadcast_test.py index e32f047866..c1c883312d 100644 --- a/tensorflow/contrib/tensorrt/test/const_broadcast_test.py +++ b/tensorflow/contrib/tensorrt/test/const_broadcast_test.py @@ -64,7 +64,7 @@ class ConstBroadcastTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" - return ['my_trt_op_0'] + return ['TRTEngineOp_0'] def ExpectedAbsoluteTolerance(self, run_params): """The absolute tolerance to compare floating point results.""" diff --git a/tensorflow/contrib/tensorrt/test/memory_alignment_test.py b/tensorflow/contrib/tensorrt/test/memory_alignment_test.py index bc7c90081f..104bac43a0 100644 --- a/tensorflow/contrib/tensorrt/test/memory_alignment_test.py +++ b/tensorflow/contrib/tensorrt/test/memory_alignment_test.py @@ -68,7 +68,7 @@ class MemoryAlignmentTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" - return ["my_trt_op_0"] + return ["TRTEngineOp_0"] def ExpectedAbsoluteTolerance(self, run_params): """The absolute tolerance to compare floating point results.""" diff --git a/tensorflow/contrib/tensorrt/test/multi_connection_neighbor_engine_test.py b/tensorflow/contrib/tensorrt/test/multi_connection_neighbor_engine_test.py index 11be4feaf7..293f93d8a7 100644 --- a/tensorflow/contrib/tensorrt/test/multi_connection_neighbor_engine_test.py +++ b/tensorflow/contrib/tensorrt/test/multi_connection_neighbor_engine_test.py @@ -25,8 +25,6 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops -from tensorflow.python.ops import gen_math_ops -from tensorflow.python.ops import math_ops from tensorflow.python.ops import nn from tensorflow.python.platform import test @@ -60,14 +58,14 @@ class MultiConnectionNeighborEngineTest(trt_test.TfTrtIntegrationTestBase): b = constant_op.constant( np.random.normal(5.0, 1.0, [1, 4, 1, 1]), name="bias", dtype=dtype) q = conv - b - edge = math_ops.sigmoid(q) + edge = self.trt_incompatible_op(q) b = constant_op.constant( np.random.normal(5.0, 1.0, [1, 4, 1, 1]), name="bias", dtype=dtype) d = b + conv - edge3 = math_ops.sigmoid(d) + edge3 = self.trt_incompatible_op(d) - edge1 = gen_math_ops.tan(conv) + edge1 = self.trt_incompatible_op(conv) t = t - edge1 q = q + edge t = t + q @@ -83,7 +81,7 @@ class MultiConnectionNeighborEngineTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" - return ["my_trt_op_0", "my_trt_op_1"] + return ["TRTEngineOp_0", "TRTEngineOp_1"] if __name__ == "__main__": diff --git a/tensorflow/contrib/tensorrt/test/neighboring_engine_test.py b/tensorflow/contrib/tensorrt/test/neighboring_engine_test.py index eddeafa38b..3e1e4b088b 100644 --- a/tensorflow/contrib/tensorrt/test/neighboring_engine_test.py +++ b/tensorflow/contrib/tensorrt/test/neighboring_engine_test.py @@ -66,8 +66,8 @@ class NeighboringEngineTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" return { - "my_trt_op_0": ["bias", "mul", "sub"], - "my_trt_op_1": ["weights", "conv"] + "TRTEngineOp_0": ["bias", "mul", "sub"], + "TRTEngineOp_1": ["weights", "conv"] } diff --git a/tensorflow/contrib/tensorrt/test/quantization_mnist_test.py b/tensorflow/contrib/tensorrt/test/quantization_mnist_test.py new file mode 100644 index 0000000000..31cbef89e2 --- /dev/null +++ b/tensorflow/contrib/tensorrt/test/quantization_mnist_test.py @@ -0,0 +1,290 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Script to test TF-TRT INT8 conversion without calibration on Mnist model.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.contrib.tensorrt.python import trt_convert +# pylint: disable=unused-import +from tensorflow.contrib.tensorrt.python.ops import trt_engine_op +# pylint: enable=unused-import +from tensorflow.core.protobuf import config_pb2 +from tensorflow.python import data +from tensorflow.python import keras +from tensorflow.python.estimator.estimator import Estimator +from tensorflow.python.estimator.model_fn import EstimatorSpec +from tensorflow.python.estimator.model_fn import ModeKeys +from tensorflow.python.estimator.run_config import RunConfig +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import graph_util +from tensorflow.python.framework import importer +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util +from tensorflow.python.keras.datasets import mnist +from tensorflow.python.layers import layers +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gen_array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import metrics +from tensorflow.python.ops import nn +from tensorflow.python.ops import variable_scope +from tensorflow.python.ops.losses import losses +from tensorflow.python.platform import test +from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.summary import summary +from tensorflow.python.training import saver +from tensorflow.python.training.adam import AdamOptimizer +from tensorflow.python.training.checkpoint_management import latest_checkpoint +from tensorflow.python.training.training_util import get_global_step + +INPUT_NODE_NAME = 'input' +OUTPUT_NODE_NAME = 'output' + + +class QuantizationAwareTrainingMNISTTest(test_util.TensorFlowTestCase): + + def _BuildGraph(self, x): + + def _Quantize(x, r): + x = gen_array_ops.quantize_and_dequantize_v2(x, -r, r) + return x + + def _DenseLayer(x, num_inputs, num_outputs, quantization_range, name): + """Dense layer with quantized outputs. + + Args: + x: input to the dense layer + num_inputs: number of input columns of x + num_outputs: number of output columns + quantization_range: the min/max range for quantization + name: name of the variable scope + + Returns: + The output of the layer. + """ + with variable_scope.variable_scope(name): + kernel = variable_scope.get_variable( + 'kernel', + shape=[num_inputs, num_outputs], + dtype=dtypes.float32, + initializer=keras.initializers.glorot_uniform()) + bias = variable_scope.get_variable( + 'bias', + shape=[num_outputs], + dtype=dtypes.float32, + initializer=keras.initializers.zeros()) + x = math_ops.matmul(x, kernel) + x = _Quantize(x, quantization_range) + x = nn.bias_add(x, bias) + x = _Quantize(x, quantization_range) + return x + + x = _Quantize(x, 1) + # Conv + Bias + Relu6 + x = layers.conv2d(x, filters=32, kernel_size=3, use_bias=True) + x = nn.relu6(x) + # Conv + Bias + Relu6 + x = layers.conv2d(x, filters=64, kernel_size=3, use_bias=True) + x = nn.relu6(x) + # Reduce + x = math_ops.reduce_mean(x, [1, 2]) + x = _Quantize(x, 6) + # FC1 + x = _DenseLayer(x, 64, 512, 6, name='dense') + x = nn.relu6(x) + # FC2 + x = _DenseLayer(x, 512, 10, 25, name='dense_1') + x = array_ops.identity(x, name=OUTPUT_NODE_NAME) + return x + + def _GetGraphDef(self, use_trt, max_batch_size, model_dir): + """Get the frozen mnist GraphDef. + + Args: + use_trt: whether use TF-TRT to convert the graph. + max_batch_size: the max batch size to apply during TF-TRT conversion. + model_dir: the model directory to load the checkpoints. + + Returns: + The frozen mnist GraphDef. + """ + graph = ops.Graph() + with self.session(graph=graph) as sess: + with graph.device('/GPU:0'): + x = array_ops.placeholder( + shape=(None, 28, 28, 1), dtype=dtypes.float32, name=INPUT_NODE_NAME) + self._BuildGraph(x) + # Load weights + mnist_saver = saver.Saver() + checkpoint_file = latest_checkpoint(model_dir) + mnist_saver.restore(sess, checkpoint_file) + # Freeze + graph_def = graph_util.convert_variables_to_constants( + sess, sess.graph_def, output_node_names=[OUTPUT_NODE_NAME]) + # Convert with TF-TRT + if use_trt: + logging.info('Number of nodes before TF-TRT conversion: %d', + len(graph_def.node)) + graph_def = trt_convert.create_inference_graph( + graph_def, + outputs=[OUTPUT_NODE_NAME], + max_batch_size=max_batch_size, + precision_mode='INT8', + max_workspace_size_bytes=4096 << 19, + minimum_segment_size=2, + use_calibration=False, + ) + logging.info('Number of nodes after TF-TRT conversion: %d', + len(graph_def.node)) + num_engines = len( + [1 for n in graph_def.node if str(n.op) == 'TRTEngineOp']) + self.assertEqual(1, num_engines) + return graph_def + + def _Run(self, is_training, use_trt, batch_size, num_epochs, model_dir): + """Train or evaluate the model. + + Args: + is_training: whether to train or evaluate the model. In training mode, + quantization will be simulated where the quantize_and_dequantize_v2 are + placed. + use_trt: if true, use TRT INT8 mode for evaluation, which will perform + real quantization. Otherwise use native TensorFlow which will perform + simulated quantization. Ignored if is_training is True. + batch_size: batch size. + num_epochs: how many epochs to train. Ignored if is_training is False. + model_dir: where to save or load checkpoint. + + Returns: + The Estimator evaluation result. + """ + # Get dataset + train_data, test_data = mnist.load_data() + + def _PreprocessFn(x, y): + x = math_ops.cast(x, dtypes.float32) + x = array_ops.expand_dims(x, axis=2) + x = 2.0 * (x / 255.0) - 1.0 + y = math_ops.cast(y, dtypes.int32) + return x, y + + def _EvalInputFn(): + mnist_x, mnist_y = test_data + dataset = data.Dataset.from_tensor_slices((mnist_x, mnist_y)) + dataset = dataset.apply( + data.experimental.map_and_batch( + map_func=_PreprocessFn, + batch_size=batch_size, + num_parallel_calls=8)) + dataset = dataset.repeat(count=1) + iterator = data.make_one_shot_iterator(dataset) + features, labels = iterator.get_next() + return features, labels + + def _TrainInputFn(): + mnist_x, mnist_y = train_data + dataset = data.Dataset.from_tensor_slices((mnist_x, mnist_y)) + dataset = dataset.shuffle(2 * len(mnist_x)) + dataset = dataset.apply( + data.experimental.map_and_batch( + map_func=_PreprocessFn, + batch_size=batch_size, + num_parallel_calls=8)) + dataset = dataset.repeat(count=num_epochs) + iterator = data.make_one_shot_iterator(dataset) + features, labels = iterator.get_next() + return features, labels + + def _ModelFn(features, labels, mode): + if is_training: + logits_out = self._BuildGraph(features) + else: + graph_def = self._GetGraphDef(use_trt, batch_size, model_dir) + logits_out = importer.import_graph_def( + graph_def, + input_map={INPUT_NODE_NAME: features}, + return_elements=[OUTPUT_NODE_NAME + ':0'], + name='')[0] + + loss = losses.sparse_softmax_cross_entropy( + labels=labels, logits=logits_out) + summary.scalar('loss', loss) + + classes_out = math_ops.argmax(logits_out, axis=1, name='classes_out') + accuracy = metrics.accuracy( + labels=labels, predictions=classes_out, name='acc_op') + summary.scalar('accuracy', accuracy[1]) + + if mode == ModeKeys.EVAL: + return EstimatorSpec( + mode, loss=loss, eval_metric_ops={'accuracy': accuracy}) + elif mode == ModeKeys.TRAIN: + optimizer = AdamOptimizer(learning_rate=1e-2) + train_op = optimizer.minimize(loss, global_step=get_global_step()) + return EstimatorSpec(mode, loss=loss, train_op=train_op) + + config_proto = config_pb2.ConfigProto() + config_proto.gpu_options.allow_growth = True + estimator = Estimator( + model_fn=_ModelFn, + model_dir=model_dir if is_training else None, + config=RunConfig(session_config=config_proto)) + + if is_training: + estimator.train(_TrainInputFn) + results = estimator.evaluate(_EvalInputFn) + logging.info('accuracy: %s', str(results['accuracy'])) + return results + + # To generate the checkpoint, set a different model_dir and call self._Run() + # by setting is_training=True and num_epochs=1000, e.g.: + # model_dir = '/tmp/quantization_mnist' + # self._Run( + # is_training=True, + # use_trt=False, + # batch_size=128, + # num_epochs=100, + # model_dir=model_dir) + def testEval(self): + if not trt_convert.is_tensorrt_enabled(): + return + model_dir = test.test_src_dir_path('contrib/tensorrt/test/testdata') + + accuracy_tf_native = self._Run( + is_training=False, + use_trt=False, + batch_size=128, + num_epochs=None, + model_dir=model_dir)['accuracy'] + logging.info('accuracy_tf_native: %f', accuracy_tf_native) + self.assertAllClose(accuracy_tf_native, 0.9662) + + if trt_convert.get_linked_tensorrt_version()[0] < 5: + return + + accuracy_tf_trt = self._Run( + is_training=False, + use_trt=True, + batch_size=128, + num_epochs=None, + model_dir=model_dir)['accuracy'] + logging.info('accuracy_tf_trt: %f', accuracy_tf_trt) + self.assertAllClose(accuracy_tf_trt, 0.9677) + + +if __name__ == '__main__': + test.main() diff --git a/tensorflow/contrib/tensorrt/test/quantization_test.py b/tensorflow/contrib/tensorrt/test/quantization_test.py new file mode 100644 index 0000000000..28353273ed --- /dev/null +++ b/tensorflow/contrib/tensorrt/test/quantization_test.py @@ -0,0 +1,144 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Model script to test TF-TensorRT integration.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.contrib.tensorrt.python import trt_convert +from tensorflow.contrib.tensorrt.test import tf_trt_integration_test_base as trt_test +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gen_array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import test + + +def _GetParams(add_quantization_nodes, dtype=dtypes.float32): + input_name = "input" + input_dims = [8, 8] + output_name = "output" + + def _Quantize(x, r): + if add_quantization_nodes: + x = gen_array_ops.fake_quant_with_min_max_vars(x, -r, r) + return x + + g = ops.Graph() + with g.as_default(): + x = array_ops.placeholder( + dtype=dtype, shape=[None] + input_dims[1:], name=input_name) + x = _Quantize(x, 10.0) + x = x + 5 + x = _Quantize(x, 15.0) + x = x - 5 + x = _Quantize(x, 10.0) + x = x * 0.1 + x = _Quantize(x, 1.0) + w = constant_op.constant(np.ones((8, 1)), dtype=dtypes.float32) + x = math_ops.matmul(x, w) + x = _Quantize(x, 10.0) + x = array_ops.identity(x, name=output_name) + + return trt_test.TfTrtIntegrationTestParams( + gdef=g.as_graph_def(), + input_names=[input_name], + input_dims=[input_dims], + output_names=[output_name], + expected_output_dims=[(8, 1)]) + + +class QuantizationMissingAllRangesTest(trt_test.TfTrtIntegrationTestBase): + + def GetParams(self): + """Create a graph containing single segment with no quantization ranges.""" + return _GetParams(add_quantization_nodes=False) + + def ShouldRunTest(self, run_params): + if trt_convert.get_linked_tensorrt_version()[0] < 5: + return False + # Only test static engine mode, with or without calibration. + return (trt_test.IsQuantizationMode(run_params.precision_mode) and + not run_params.use_optimizer and not run_params.dynamic_engine) + + def ExpectedEnginesToBuild(self, run_params): + """Return the expected engines to build.""" + if run_params.use_calibration: + # In static engine mode with calibration, it should build a calibration + # engine. + return ["my_trt_op_0"] + # In static engine mode without calibration, the engine building will fail + # since no quantization ranges are set, which results in no TRT nodes. + return [] + + +class QuantizationWithRangesTest(trt_test.TfTrtIntegrationTestBase): + + def GetParams(self): + """Create a graph containing single segment with no quantization ranges.""" + return _GetParams(add_quantization_nodes=True) + + def ShouldRunTest(self, run_params): + if trt_convert.get_linked_tensorrt_version()[0] < 5: + return False + # Test static/dynamic engine with/without calibration. + return (trt_test.IsQuantizationMode(run_params.precision_mode) and + not run_params.use_optimizer) + + def ExpectedEnginesToBuild(self, run_params): + """Return the expected engines to build.""" + return ["my_trt_op_0"] + + def ExpectedAbsoluteTolerance(self, run_params): + """The absolute tolerance to compare floating point results.""" + return 1.e-05 if run_params.precision_mode == "FP32" else 1.e-01 + + def ExpectedRelativeTolerance(self, run_params): + """The relative tolerance to compare floating point results.""" + return 1.e-05 if run_params.precision_mode == "FP32" else 1.e-01 + + +class NonQuantizedPrecisionsWithRangesTest(trt_test.TfTrtIntegrationTestBase): + + def GetParams(self): + """Create a graph containing single segment with no quantization ranges.""" + return _GetParams(add_quantization_nodes=True) + + def ShouldRunTest(self, run_params): + # Only test FP32/FP16 mode. + return not trt_test.IsQuantizationMode(run_params.precision_mode) + + def ExpectedEnginesToBuild(self, run_params): + """Return the expected engines to build.""" + # The fake quant ops are not supported in FP32/FP16 mode, and will split the + # graph into three TRT segments. + return ["my_trt_op_0", "my_trt_op_1", "my_trt_op_2", "my_trt_op_3"] + + def ExpectedAbsoluteTolerance(self, run_params): + """The absolute tolerance to compare floating point results.""" + return 1.e-05 if run_params.precision_mode == "FP32" else 1.e-01 + + def ExpectedRelativeTolerance(self, run_params): + """The relative tolerance to compare floating point results.""" + return 1.e-05 if run_params.precision_mode == "FP32" else 1.e-01 + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/contrib/tensorrt/test/rank_two_test.py b/tensorflow/contrib/tensorrt/test/rank_two_test.py index 74a4a05925..0cd733dca1 100644 --- a/tensorflow/contrib/tensorrt/test/rank_two_test.py +++ b/tensorflow/contrib/tensorrt/test/rank_two_test.py @@ -68,11 +68,11 @@ class RankTwoTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" return { - "my_trt_op_0": [ + "TRTEngineOp_0": [ "add0_1", "add0_2", "add0_3", "c0_1", "c0_2", "c0_3", "abs0_1", "abs0_2" ], - "my_trt_op_1": [ + "TRTEngineOp_1": [ "add", "add1_1", "add1_2", "add1_3", "c1_1", "c1_2", "c1_3", "abs1_1", "abs1_2", "reciprocal0", "reciprocal1" ], diff --git a/tensorflow/contrib/tensorrt/test/reshape_transpose_test.py b/tensorflow/contrib/tensorrt/test/reshape_transpose_test.py index bbc724ab18..207944468a 100644 --- a/tensorflow/contrib/tensorrt/test/reshape_transpose_test.py +++ b/tensorflow/contrib/tensorrt/test/reshape_transpose_test.py @@ -79,8 +79,8 @@ class ReshapeTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" return { - "my_trt_op_0": ["reshape-%d" % i for i in range(7)] + - ["reshape-%d/shape" % i for i in range(7)] + "TRTEngineOp_0": ["reshape-%d" % i for i in range(7)] + + ["reshape-%d/shape" % i for i in range(7)] } def ShouldRunTest(self, run_params): @@ -117,7 +117,7 @@ class TransposeTest(trt_test.TfTrtIntegrationTestBase): # Note: by default Grappler will run the TRT optimizer twice. At the # first time it will group the two transpose ops below to same segment # then fail the conversion due to the expected batch dimension problem. - # At the second time, since the input of bridge op is my_trt_op_0, it + # At the second time, since the input of bridge op is TRTEngineOp_0, it # will fail to do shape inference which then cause conversion to fail. # TODO(laigd): support shape inference, make TRT optimizer run only # once, and fix this. @@ -136,7 +136,7 @@ class TransposeTest(trt_test.TfTrtIntegrationTestBase): def ExpectedEnginesToBuild(self, run_params): """Return the expected engines to build.""" return { - "my_trt_op_0": [ + "TRTEngineOp_0": [ "transpose-1", "transpose-1/perm", "transposeback", "transposeback/perm" ] diff --git a/tensorflow/contrib/tensorrt/test/testdata/checkpoint b/tensorflow/contrib/tensorrt/test/testdata/checkpoint new file mode 100644 index 0000000000..a603e1aec9 --- /dev/null +++ b/tensorflow/contrib/tensorrt/test/testdata/checkpoint @@ -0,0 +1,3 @@ +model_checkpoint_path: "model.ckpt-46900" +all_model_checkpoint_paths: "model.ckpt-0" +all_model_checkpoint_paths: "model.ckpt-46900" diff --git a/tensorflow/contrib/tensorrt/test/testdata/model.ckpt-46900.data-00000-of-00001 b/tensorflow/contrib/tensorrt/test/testdata/model.ckpt-46900.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..88a998f184b275121e1e76eb51d2310da149f10a GIT binary patch literal 686728 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

n|U(L*sXt#p& z#!vqQPum*r!og`zS1JP~>=PC&BHBz%^K}*t3%7yw-{#p5HydOZGS2+@6s!hW48%U8 z?+5nxtEZo^%D;43zWtAzq~+5c^4mESK7!Tmu2q7o&9c!U+N~h_9{KHttKT?Z5S*Sq zT{;671F2b4WDFJuu?gXvd}*s6+znv&MCb~E!xNjHhSx?|(|;j{3^*?Rq#lCJK-YV> zpv&B^wB$T+ngOY`{);+x2NJ`F*NFMR{pRdz3HJBBNL{#jAidTT zh#&v3@qM{t%3W5lABz7ufa3>b20A|8{SmAG1f8CP%Z$fn53%aqa{a1#7t6J6E~?io zvQ|RoJ&L6fb2wqExWRU#+lPz4L^%QMXOR4y{nB8))6BTQG)N4Dy=RKU)qwc;a6|WV z3!k5mcDZxKH>`dD>3^5kjWz!D9`u3r_~~E78a@$8uXZ>~|F_uN(QUcuy9Xqm_5 z%Zq0l?yP>i%)BP9)zZ}x(nr*7-3j;q-mNEzb}Pv28`rMD)xSIs@ppPRY9Hc8EFz3R zdhlWIZx^?Hd9xhs_A@;uaCf2Wxhk&#PUq<29vcO~X{Vk20oV+5`OrYSopxHwcC;N< zwQO@11gHN636S&#QhTZNAMD@5Q5}jMX38kLvHtnf-CwItDvSp=CYb@O`!5 z6TF?JdWIbypCI!H;T1)T!C?qeCtgtw)@%5r3nlFNrY*zi50E}&Tp-_K$?68l+X5kw zaUf)Q7~4}P9>orrcB(%cdmG+P1JfY+IG;MK`ap8n@a+H2 z@bs^1vL5W-4cGa=?uV&=yu}x;1}27!4lT~IsJg5V_M2)qYB(b6nYI=C_@B3>IygN> zZ1BSBk7aee7KiQUn(tU=Xvt;82KM)Dj|EtZ)W0E(~H5!mn$1EtIra!Qq$j2(=zX)+^A4n6pO~cRSArcK^Z6zrpDM zSq{YhCwq8D!IyH&RgA)x&%5lvVe~@U8D5q+gclQ?S3%~P1~S9#sr#G+wp+6KCtM7q zW}74NWeNvRmgSQR+re=-?IZ4S^UeeJz-a_zJ~DoBay3{yBasbEBg=uhNLS z__>yucV>X~XMODhrzdRcWj-;(-Ha^H{~0p>d387T`Jq0;q#f<;f>x!RN|r7vtHAMp z#Y6}mU+Q;H;ItFj9vJ)obI6!4h##*r59}sgu10u%0*OC&sU+I}N46ifJi7K6*#D(m zL16cR%s|KU6(IE-y7(4zCa|8A@=IVd(B)0cm3DBQceS+0YP2lP)CK$X!UB1CnqOL_ zLbO{!W~-*B!PO^pKxhJ9RGk($jBI0A;qGJJdJ&!$(Cx&=uXvjPFE3b`A?p?9YpjQx z2hy|R=sA?|0EywkB`yyw>is3a>Z9NAz|BTi&yyt%t|QRJMLu|f?LJu%2d2^G^+V2B z>`Pm?^OKgp#p$AZ;IJycW(N23oVloTSLpiD`R6Yn*2`~PD+CTt=|WGG{6C4~778ET z3}n9d+g}z2MVes0Wq6ii^#e$K&co+e3IViROMdG+1|6uaBBiC_P`PI9NEi7BN0 zG`0FQ&TxC@hkbto^ILVWU(%KDVhx`xkNFl!uahk={g`R-H4PF*mIa7@=Ia-FB>DfI z;Y+xBL1)O^HzyYRe#Y#%PRzltQ>9+5qe`hWi$ z)VawuO1RhYqnjJ%&t>VE2HC@LNCeUjKvx6eFOfL~w->~RVU_dOz~YR&sB6$*@~1Z) z-nny^@XmUsjaE$IE?~9R_l3dX4N~(pk+k*i9uHT8!w{r*&Vwc3_;P6p0q0+k7zjUe z{QyrRAU;0aZRuz=rC$#0o?M+goch*Hxd3)Mx>>ba<={Ls@Z2ppUV7+`77JzAx7zk^J5I_FMvwHdV z?`@Fs@ADzV+8U5K$k_TKWRC!{7>HdIdlwuZn|2=r`wb+9j29;!-rnT1$#Tz=O3VF0 zki82nPnf{uiau&0J%hC4VTT$F?H}ekMe2^Y|*xZq6$LB+kvAdT)j=}R5x}I<1khv=i z@duFg=(p9TfZc*FU!r)-ywTU&^63>v3&RI|V85=sJQH5#-&v1+-2}QhFuq{@CAeQ1 zts!gA-Y#K4iJK~0+~YVfb6_-Q@f8cPtsG$Y1baZ%Q^Dkr=@z%+f$lUK!4}#MKh)oPWJ2x1fMp-7ZgW3M!LMZ9|`X^1W zI5Fn&O#5d(*%{LQXW#J~oDQ(*Gq_<04kL6q`^ptyzp(W(VwI2Hy3gY9^L3WGO+PKR zc6o!{`7`eYy!?;Zi&)Q$ZZv7OF!79(>a%IQD_bS_u&beVRw;f{s-sdS` zJs|x7tQ_Dl0kMg}E<#V?>7{etA#i!xUVs=+1)1@@Clsy*#K(tyruJBdZ><2kXGwu8 z*gS0N7nokg>OYQFNS(oz_!+CbxXhXzx;p|as%`IBy!)mKwuf~mWE~L5p54a+iFPYU zy>$p=%ooId%Tff^o4BC?OoPNg_^vAMek@2H87u9swR~Qj3D!SXKL^~FLzaiJ&uJ=S zP2XA%{)5xtMpX^0@%VVIr)3tmgXJ{FBbJ8GyTIXlbkhxZ`n)aE3AP(%4^*e* zU<>vex_odiqnYj}G0XIA!j@Z?hJwS$?`s}BoD-~2_pYJqN9Q}=tB1Q$qGdJM9A_!i zetTvT?r|J+^Qx_W@7yZA8|?r7PItK3=<3+cuz=N|i#OXr)*~%^c@%5<50_fG)3}M- z@}0?U%QI6U`<|+IoQH>%=DkPYI7BxW7eB2WvHt5|&RVcJ_xmrQxVz~R{s-*u?!%C|D0F?rbARm$SZ!pn2 z*Fp^gupW@wQ1x3xyA`BkE@8@X&p3Un;O$r%RQb?!Sxj5;{{+EWR42c zMsS`0v5CR69cAJ9|K8-i;ILD9a~e#;^ow{R_K3m6aM9N%Fj>hYLiT^WTqTNP4ziwN zyGL04R~_6B_J6&`cdYV?F$;H|PSf4l-nQLh+gnHn%GhF3Bwf=k2|#dEjQF>-p%l4y*r6s~}@gMUL3Z z$4gq#JL|F+TgZp5-yZFE7M#Cg8uq~b&ya|^cNN`Ubbj^K3Gnb*E~*N4ul)~1od{CD z(|#{Xc!0!kVb0xKEaJY)f!!mYjk_<#XC{x;%xOCzby=%k1K137dn6iNw>Rq5?06uN zZ5id$46dg-nOlrt>UISp_5#7g@X>*LI>2QJNKM;}X0ZPSg;3Z3zcXyb>Q;~*bbRS4 zuhpL^kToo;IeD@A0i;Lhh7i{H7e96sY}Y#$$QUX}Ei#tUE!tUDzs|yBiq6hCagcK+ z*4jzI&6@fS_m~s1IWYFU2Z;SrI!ci9WEu_ygTn!)=2jf;b=)vDFnVc*pyja_hr#aY zoq(8IfXTz?3L(@zRxt60y~^M)+nJ0y1`U&MFz(p)^>vS>?bGGRC5+>g}1v*BqAWIi%pz*PwjBV;iU`^S06+OaEP z*vE%f%l_DLTza8-Rcf=P>cIrC{{!C5f~OVLf*`OTKxPqx1tk&Vg{!?F=|6-MweCF< zP5k_Cx$sVl%zG=q?ke8D38(*;6{5~Dz}%|LvILy|HyxS|_Y+JGME_grVqT$`V7X50 zlSS4g|3dRUl42jznlg+Ge}|ge7L)i^;T#4{nc;UCJ-NnuT?GYd%PGjW(KljmKtg6 zKe>(iitXxwmlwqy`rxql zTj>v`Vd`(DL*fL+$49ejcUhh~x(e*}`^#{z8>oNL3Qi;FX1%-sS^x4i-V*L7WHq0x z+P0s)W3_8>{(8$BtQKH*uDgm@E45ScI5LsAspJn~%=Fe+#nb86?i#s{nTI-n)=>bs#YiUY=qH4_^=;A69)7W%2(n1K4lP z{n+CWq(A4^F>o3Iv5~R5I^^7|Oa9$pzah(k*vF*ucdneoyK8o5o29fJqz*B(Ld=zO zt$Rk+X3Ga7i|W~1x# z75j3=R%8g#ZUwnXSQgR# z>5o?14H65oLY;eXev2q0K=SzT_7Wzm?^~{d<3QX5at*6!}mw?rv>)&#S860-?0@&M!JW=<}Cw=U-$j^4O z{P(;A9RCs=AK~To*-gK}WjMOIxcJ|FTH)?^`F0K1|FN==bzm?(*(~#Lrel~I7@hZ{ z-(pwxMQ|P5`W3OZ9wrZ?Q-Auy?S+Yf=-l&$VE-TahW#AFqO&Wu*Cf2RXmvPZd24St z*bHT(3E*%5=`WbL609G@CI;XBbPBFMSs#)YE>A}-?_?$?67B!U?uebInYV${wv_>5 zZWY}v-SykSZbuitd-ovNJ=gUhYjM%#U)*}TqapFrj!E^;Ewfp~!0r;e;|kUTQmf5F z+WDVfQxM~Y8;$0J&0%S21m`P|c_6%+l?7}Mh)oEai>K{);sjaSKecKHI6Yz0Q~d{f z`)<$b<>2(YIolX(_>>*HZZ7%J({jF4vjx|KEU-I8xI@7-$R1BMdpH}!Cxq2=FN6II zQa2+Ivi>VJ4|V*5wQC#E{x{kA+hWoI$a<`c9BnxLACmR~tN)5u`-Ah&*F*`pyFhM( z;XS5HEX><>?tHgG(DK_X$o$Isd1dhQpFGnTt3H^1bUKC^F-FtYlngfKxIigN7^Z%K z?6X1Fi;W*~^pfS1bja9U?P5Nh{{K017FPf7`Og6sm(;ldb_=>4RWdtwe2nq1Jb%^9 zszdAySnbP3#5~Ka5GkB?qMHTctE)lIPy(^zmqYeK`zxJ6@&B>a>O`BV=Ok`1s{>Mo z={I9v;|j8C#stV7DG(bOt8ae`j=z&{H=(!zrp9rFkfjpy!X1~VYgzQVdZ$6UbW-@IcMVDms` zpyT4Hh&_wQa#@Lxx%Ov@kiFf=av*lfBlewVFY#K;3;w)AZ|?!H|2NP03Z_Bw&#q&y zH$ZaOuEmEMy)WrarQHD@u64#Iez{O{VV1Q9J=omml{`#aV9TJ3!V* zp_`$m0qM(fKHvw3A-eqX?wvbxzCPbEX`!ZNhXmxTpTH+-aQ}C6hU2so-7FCQ)ha~W z?pk0nSTFlq$UX>=JP4oDx(XHtu?gW5bE2C3cc@Gd1*e&o zOvo8}82VmLu<%!Vxnsp6MXR1B$oYEd3lZo4%(WuEtpYOJT@SHF>9N{xa5_(~T!9kb zV#gkV#X;%`VXKOC%Z8GQR{xH#6=(eGI?jc= z8Cm~V0m%OUm*T8gKZFx`+I$BV=6!NDU#puCZ#Xzz!vF9==(HY7Vkq*G-T;vdCf}c8Ja=aQfFX z^~36aHKs`x@8nY~7biZpyuS<5M!LNOah5R44@emfGK&~2lZ9B@5&q;3*#DN*sB2Rf zKE}O{8{LjW!4oad&WG%KTX17C*e~d6K>YKEA!mev*vOdM{{c8ok6c`c)&ENt9=7=U zcZTH?23hk{dY<6)^|MD09Nr*vtX?yM(=dol3|_DWv9`<38q#0me2+Tc5n2P87bC_z zlT+N5CUMnZ_cYJJz5c=b4rGiF-OR0bEy4blo63ka>^2mn?DUa}*l}{EgQd+~$XP+l z4a~sh0LZMvt08NmL2P1hPatHx1*G^wUKvhR~S zZ4p*KfXp~<4LQ3I#74$mGd#fkpYp}n`^W7|?Je8QPh0*xmSAxxe+}6DxMz_17GzHS zLDaL0L1Osu-d8bTGeBydHbCx?=@WvSgAWn|;U&$#!TAEjCWN~VGg&Q?hm8A9&Bc8e zkKu;N;CRL`?-AtezylYtkB`};o!x$E(?c`GtX~!nS3&mBW)~y&QgEIk?fld8Gc(}% z#b)a^}n|?q^*5s zk2}`ziTK-UF>_zPh0BXG7E@nA&ObCMMYI)ngg-`cJJ>QjM7e7-+;7wUe}Ubb!iK05 zKw2%Y6F>f|_h;6QNKMGuR{!6(;&jWOzo=&nf$RZeFG#(A%jGY)Z37lVBCMIbcfRnS zWwCf2pXH|BMZAd;qmWQ#uKA@g402AkW3|aU0tgagz7cg-ceYN=hj)?{;JGJj= zSv7YVfaj&o86(bTw^>M9{NG%SSfjh_7v%nzoQe7uBHg9TR?K?SnTs@%cOsh z{?9)DSK#nOR|Dd!-j71D10)8*$}Ydab=utC%UI>b);MmLIR4e5HNL}AR+A4L&aV$$ zgsc6fV+F21L1qzyO%o7j`=2O-oH-M47jmxxOn>kV4R{`biQ%G?=1jIMO@^EwvtbH9 zPXFJ3fn$C@;1jqm+h}SJ_8YoA>*Z8-y81lZvFYGL%Qh3p`Qo?Dbm40COlJ`tS0J-% zzah>)TJuXB9FB44Q1>1PBoSZ!AHH;N`>CmrH3c^p{=n%LR!7Jg2_QEhu!Fo2y zVPF4VrkJrk#BQO5h3G7cG%3g#(Xj^HV0VMeS+bV+y{aJf_m(2ozukKdG4D|OdANBX zH5EIsuT=!eq2o8PtvjA`rGw)mt5_QB7j!ise%llauo@5>86We6?EhdTmgT^+vGU8BHF;!|KYP zM_@6KS;Szgt%&;%xWXap9K8;r=DmRF#IGrow!3Y4upY85dv-blI2^FK!|5sF&OT)M zS(71qkLH^~?!iHp1F^j{thV3zxX1j4tB9qD0OYL1GbI6V{~u39l;J~kQ%)O*#l)}veiEF*WJ&q5ON5(hn+^jqcSgb)}A*K2_)6K<8*w6n6ErZ-OX}kve z{J<9J-8-FhqO3e$9ky1Z5QC_<+GFs*u4s=sOkTr zCnQ}EW8R`&vn(21rh?OUS_PtRLDyTfBmyOjVe$txAZG@|UWJUI!Ng(os=pq)-f8Pw z{xY3swKcK?Y{nbreeiVVs7L%>Es&W@w<6BE(pw1G|F~w-Ih1_cEmaFQAEXB#UL+!D zq42W~9H#0s48b%u^$MpTZDe%0=h~2dq1$Hcb0_ABK|5~r1X)Nd+hS?F46=qe<;Q<` zng2)%QJ>J zLe>jndpAPnG#)&L?8O9$A>&JVGk2_GNU*55yTQDkWePanJ7i_y?$wKbZdikLAA$lfdqY_`VM8K9Jey*tn?*oJP>aYqxQO z_3qo(0gqE;HD8=+Ej~4Io1J#8w9NPr4^Ed6>z9G`fYhD%3>m`$v5CQ{OCfCtklLsv zhr#A0H6Yg0fW!?F4Z-Cih)oC!YMr!@VTY`36i7zYE$I3lec}SAU3778p+&oBj|DtB9JvLVuw-NU@&#>wq3XQYT0hNTkMwkx->`Tz;Sgj#)#cI;l(J`^67l8#0<&Y5TYMq?$NR#1DCQu$rLY?N__xAK$l9~qt&qMQ zvK|mSdqcW~$EylUTbD$Ow)&;u@GVjE0;d^}e7ry6K1UFr5H9Qsf~OrTvk73fv=r*z zlhP9xz~Y3=0?8jtRN5ha4stKA@-E!_ANDRqjM;+p!El`hmltxm^h4XQIp)c zQ)<0s6K|?zZjKE&eBTxz&dPSlBL1u{keR+625`Ui?Sh!V4# z|KfiKq|F1e=VrrkaDH-1hKwtM#6Y;r0rxl_NFEt?xdmC?4S}3(A$4s6RzHH&Zxcp6 zV+(8;AcV@NaZZ-yR+jZGF7jQlR>A$N*{8|N&`XlA4 z@VH&F0W$v0cl0sbJdm2Ehmd`NAT}YqZDp#({4HO>`A4Aj7Cc>|>s#Gui?#fpoCR4I zw3js(tKNOnxptpy>)I}_?qK=+=P$55zuqC{>)DqPKUN8H(~~O#aC=T_Le?v?K1oFJ ze}L6Oa6SX6Cxki7$}CE@I)n9pNkg4SMb@jg0DJtJ8$j0m%V}ZH|LY#wZoesNYuRu3 z#PX5<5wQPftVGO}ewc-O%@wl!Fm_Hr6Wni~?I3kw@sAXgbgS;40#^gmhl{TH@^R-G zRmj@a`fZT;DQs$wp2Xh%wQ`*gE_+T`BH|QTzt^T?I~e?@o8LHHYpL)Ma_^gL17iMT z-X`Mrs)5Wcxbg+=x5-+OV0JxsA-Eg>$%F8_ql>}fAT}XFFmABEqXz~vxFZOVGm&i`V{gq(Q-(ra4Z2~K-&6;a0? zpZ+6$O>wLIhMj(mkbeI*Z$#MwG9MXd=AoW32$L(G0vUTPd=8mIf{DZE>8i7KB&YAR zh*%_Kaq`wuaQ?4e3E2k(QZrX?BREVzY+~@%+mJhCL29$2CxYXD`U2E@TRuxG!s`f- zI(*oy@~`E^4?n=}l0Anwmjhjo^4&g^G6p6;V_P>k-dSg2pC9MGtGctiE7;<2=Oc^C z$B?z|>uw>|S-9?i%wfXJBSdpR&pZRE^Hs6|r}GKbYf;keV=H%}{eR)jI?H8FkhN_G zZX?##fy_t7OWB*T`v1yFZEzZ7ZiS5PA?pFLCFa|2b1%BIy|<#u#I6r=&vwn$Rq*s* z5`-wvLFx(NRj$+Fe!CYE1or=}vOVB=WtiSI?1(dRVPd%Ga%L9G4;LV7`?s0|g3}W= zwGV5tpa1_S*b%Jf;6X>M;iDlGvh%lcwq^HGBg=yQkaREh?It+PK=zyuM)ZY2d_wqC zFJ!(Aq%L#z5pcY-+g5?oFGvi859C}%sSiM6xG?kWMLQ&)M1kGD>m!ae4h#$oe_xh^ z(>c01^&*h7lR8Bq-$(cCW(XXW%dcsdc{&Il~piCI)}_ zjF>NxW9b5?Bg;vlVE4oH?^kRBDkRxvSvn+FMTnS z3twWXtl|N7@1lKT;BWw$EyqrLTLq+EJq5Dn8N^mP%nUYX!y-|Xu-86M{F=i26IXXO zpN|8#?H|oW+${n!9~n>7nGTOLWO0kUU~qiMu|wMS$Z{aI&$lx>)F(VL@1K6z;>lV` zuzMSCBhKe9a9sor6OdYB@REnF;4%-SR;>lHZt*L#2a5j-G+4m)fYcDeciyw@%&~|D z>zA8>d;jPEbnJaYtxu4;EY%hJ_+Zq^SvziQeq%BBptfa9iVoOa3nLKoOm}s2z+!~l z36pnQ{s$gjz4IaKzTS8L1IGbO&5}~Y9T_k&Ty$>jr5zI^6T$Jn_xwqC-GZ*(>xt_H;4cOSAx2*gIlxeFj;Iy<-^XQ(2}f!M2Fe%PVE zZnC9U&~!_wj`Lvi`K%G=Rj;oBt2Am|@oM1Dee~E(243L@`$4P7d2em-fYJ&7y?Sq{AxR2QdB@NjI7ozY%YH{Ik z!_MsoOT)n7cjaI^JYLY%Ule8rt3el+S_wI8_wWtu^M5Zlx9zybF0`X8 zrwU}g1!UGN9$%u}3Q|8~h88?+xA;TiYa@#{I9x&UAbcb7J<(=fXI{4>YcJ$(&kG#5 z@4xu9_J8&dYy2nmLH5Ooi9_zt zMb|e!W8ThlYW?OqE*4h5b0KR4k1_ec{g85*__G>8W?RfdjBRb43u*s`-h#{nf#gBB z>*@~*g3o(uJ%qF@pJVcGn-`)XIoh$w1LgZ`GC4M^=T+%KPN~%AuK5^w5!7Z2{>*& z5>>%8Ha#o8qRz3y)SUW17o3+fE@R(2Sk@80gH!gl*|tAYmX@KAb4r%w9{{@>WX1`_ zh4A_e#3zJ3Qy^^~kUFaw#$dg7br9=GLE?OY*vFzka_D$zqmV`S4aj`_ifu2!enD3Q z;-3w|emCe&7RcI(v+q#H;6Zvo*rQ9(!bEa{<%!$;mU6-O!RDX%YXndKVox%O9;*YH zm-rEJwq5;y$oS`S7S#LRw#5*Cr`!*Y<(6{nSHbZvb`@u zU#^?8^M&FL^S%!gEcrqpb3GCvui)ulMip{?GO`}LY<#&Qh{U_M})f*w_Gh)*d$br56v)K10IR1YdVqYIF)BJ4b((_dom-U#f z&OEUM`+MhP#5{w3VhPr8#pVW(*ow)JJ?|j4?03l8t9|Pr?Ld$i2-~Yb>RAw*5YBmU z$>MMIbg&yrODChuBOvQ#RKdQ#vtS?OJg!qcVc>8;)&pYyh&{i{wP&`)DhE%?ql&x-XQ+2LXdf>nq1&G2eGd{gOu~@l`7%o2}pd_A;`QCh)oC!ub;j1yd7k0 zYs-B$aQtA?!zKF*97gDJlh_=(0zd32=%g3=6WtpeUXSRETjxAl9$VT5kZsYj6eKlHw0?;o$u{mZr#GnH)n z*R|Aq{W)E5e3fjA1=|Nwck&oy{Tzr*4F2~QQMSKygp7snDL|Yj0y5(R*A#F*1F;EV zzGi+aw)>FtALMnN;9-ldPyb~g*7%Qbh0I5oDPdn9X(V!bXPjGxMfR>6J0|o&#;%@B ztA?93`6FrLpNpUNfa`pa`|5ol>;BD`M5Cl310LMxxPbH_W5;ejf@+PK=vMgeF<4Zjw}aa&&{5@(~FhM(z-|9Lc?_nxcqNA3RyD;l21@3 zeykFt{y>@pJdS)?A>+K_yAkCHNR9s`#2H~AK0ds)%4_GFt+T=T-_E8JZZ^7}H?c-o z{jcZ>Y11qg+k-WKobXw+({!<|g@(Pgg(EX$o-Wk$AAHS+ohNDce~0pHfxB^fF=RiX z|0&cpM0qNRGZNALfzH>QwrxiduMId}&Wkf+^&?16ZaMb#&Fim=fz#fSmymOCKx&ck z6}dL^-`8@sUuLMc=xk?9K2kE{nDyT}N!c7UZ6(ic{^D+P`}n7-&* z;`7whJLfEZ{mTZId-wUiV~s!cJ+(_A^IYiSk*Sb5=%s0hJ^jdPq*7EYCUYuU%}WTfJgV#o z4(G4Ah_fP?^AU5Q$og=xV^5~R!){(O7AJkiO}>mN@+Zl1IjVhW-{T9?4++ zng+Pnf1Z=UUN-U<^n%k&`K(N^8OUaX*jGZ8c0LRKX7O%Dlf~i(kaI~dKY-LXAbEyh z+;>iZ<n*?khRoAn7DJp*F<~>}JSTkagvnJ4A;zdC zY=hkU_kUeS^eh-W%-mU*g+UcBb;_ z?htQ#%)Z(Z38j(=ZKe(-tP*!0Naxc`05Oiys#@j>$@IB%ott=9fv5xP~`@?YCG%cISZ zd*455Bkn6zISeTi(e>fthj}CRKZ?wSOk-yLWhV%(0k%uia903Z%WN{`49=y&CZnKUN8HPxgL$cpj}g zwHnNp_=S4*{Es$7841#Z56i3H-yyrc9~=koRB_+`Y_R}x&po4reD)76Qd0*A6$p5(@V96>=^}_^?5C6=l`wjodFNK>LOKeezje~j$*fuODxWE z9AqalPB1uX!96=3oQJ>PhpYoemWQ#=Jr+dCV=!^cdH!4{~T}IQQQDCW3l_;ohN_B?+oU2wA6@g0>{%&k3(P@ zq=xTS0ZuzX^60oV407fdNPN;82e96S-ywTYL1G|m{{?qF4w6U4d`+D@-xfgD_Qh61 z#;1|xVeF8%h;=70F%TW0u@78koX;wR`w1it!xoRXoBQ{1Te2o(TJ~(N2j>-zu;=jd zN`Ki4@E8V6Jt6v(7UCTKgp_+=|9?_NjsNK{iN8~NpL3gKSmzROIbyKv7(8#GyWLBm`2wpsxGxNyK%Nf!$EPYJ&zz~MDuzFgTn!&_VyOi_W$y0K<-cn z={-3Ea?Z=%O^|jFNDPF3uP1&@<@~ZEJ1$u>gU>(7JBc`#6J!oDHd=?hp4xQLzDsMdw+%X;e*~xhtXAytuPe}Nv5M8o z@|}3G<%A&U9huq7;qhN(30XgjZXYiGt*74Lvc)(sSIvetBFES=*1U*I-4jg}dfC%e$(tEY__iT3}m_^_Q72f4s?`yy7zcoN8LbR6>lb&Ul~{%+7N zaGgG<6q2`L;xKw+?Fx%6M!`F}eU4Zt|b}LW(KJ_>J4ebg4o31=m5n2SGO7= zuz8C^&!L3#Z?pVXt^@WW;&HZkEo#QewIiQmBE=%<2F?@)>T^p)s5 z^;Oe)m#iWy*#8s1;XaG`@KMOvCAypVkH&$+CGmJ2N*ut{-CdQrGwYRrMWcn1<+7=1 z;Ih(LAqgCBAT{RVGr$43blxEp6JhpgA?j}ZpDA0!XL91%0&YCwE^SpCloODmx$aC)h{Y7CAaZ0g_K z2t~02rY0!zE?Cdnxsb6vm^h5Cb#2`tyAy?O|_&oC5|@V||18vkF1# zEkve+;~c~`?}Us6?A=fXPJ#=duWN^$qo{GA6mL-vUTixfp-vx<|e_`W|+mqKp?){aTi@V+IBW#7$|NB@W>)wSQs$dPf?G-n6 z^{Q^)u~>1v#e_YxO+fBexr$iB`(JG;(Rmf5x9c5Z|DR0Bdayrt9E03J2a*S2q1TXe z!9Z+6Sn>A8?Jot^g7fZD;e2pg2Adw$jt^MnPW*xew_P6v@P z%NbMmgZn-GwUG8ENS)kT$QTBQO$Y)KC48B#B;MX<&NHuIH59x zNISS30Liy`;XZQ^B#(~UP9fAU|8o)SPfL4Alr$v$h6h|GqwB@SU!~e$xse-kcAe7X zojCOsopQ&T{`Z_-2KK+?1nm8Pu}1|Kod$)LMf=&zk4Dc0mz5iP3gBTiB@%a^8=HGs zRT1k&>JLN84$qb#6nA@EJ%AD(*vx^6@qg~#G5<28?7A911MC-=95UVKkc~C{7e>th z`$^}sCzwXo17fq(oZYcld(w_M(Rr5f#U5ZYp0F;1t39{<9Xu_7)Dyzh?>E8qZodz? zdp_U_Wc&`M_jTwKl<TJ}Wn5ju6B~#=f7q!D)HJ5)rKVqw&k{9h+@3 zEsZW~Sl(U~IUR{35prJ`61^5g47ejDZRlvorE;Oai>3f1ByAw zdJkX2-oBG~0XhHl-mHgM{eP@!<4*nm?=75;$ym<#dkq{O>y=L3-W3;1!5xq;-- zam@$FdD9?q(?gK^3ij|o)|G?AKv+KnaxWH$O$dMfzTdKy&kdZ0D`w$7i@oU-hg2Lzgcr58lD{c&(*jQodE8ObpoHKUyK@K!DT=l_K&ph))Rbhwk|S zsnfbR6KtNWn*&PNzh6lF`p*UV-j+3HSHS-F*1=uH3{r8Ng3&D0LUx(ZS1#%ZM ze%-fp2cKD|rQ~}yiyJPGGr|PSeZlsD)K#0T2kQs1iNVIR5dEJYQu^SqzY>*#Qf_Zv z)lGE%*NAZ6-XE#}j=OyaA@ix&+)>#9Dd*7T9(7#N zvt|4~Z?Jo>`dtB+86b5xz9aT?f%t?l>uto?-r>wluz5}&5bH@n`dg0%c?HZ>g$Fg$EH$Nr8?aKgb zh`T{%9m!I|S>}M`(ea0ch_Q{Ob&&NM+jk=NQ-aigQ6&EUkLUCIcgX*Qw0~7ERB40s zW5fSa5N9?c%daqojEm3m#eV)vU&VZjy6;OYO`Uu#XYulb*L@`$AnuCLe}g#B2iaU) zY>nCR;5Y}#|9J~N3-?Bdr-p=KB;A+tIqw`PwueM~&4h4tb?Tv@Arg4y-uhsb|c7Vh{xIPxr|Cgyp zoM{UZhhfF@j=Pp_?6zdjWwk0l2dP6YW>1M73h4(U%YoSGx0h~H zZa8UiO1RO|>=fjlYF&$MaQA*nWW{MGNIyDWYK~|xyNP`R$J;Jp)O}kM{#Otk|HtP> zSS8;14^F%P-me3jhi)f`&v6RX4v-iKpZx}zkJ07#1DgR7L&opZ1$MEpMp@-}>RGW0 zK-$^sWFdV!?r(f;3+xX(f|U_03D>%ZbY zH@J2EXK+3Txd9p5o-hZei%GZi!8EcQhUShy zAOB#oSqb)c!+q@MxXfGRVWCztbw^wtm(|vyso-+YBpoqcv2zM(`@h%aA;vbdg&}u` zxagzSAr<+==c&!}6?eYAJ^>v6a>sDT|K%r;aUS%rdGn+loR@d}fvkf=mlqG)vh(TV z1(u7x%&}a1p#mIMU0?Ts^?=lxIc~<9u0V3w@cg6}xZc9ekaJ!&93kgG!qkiO?Ik)* zS=vWgUb+l9FXenICr-D_b8rQ_9cBlN=3faJGc)PDhqdh_YoWDspWVtGdBG-(Ps{% z!PWECLGD8OnSgq3)vX>sqW%AC{$$HkJq57;V^;O!)Hh|xEv)`?y9}B4jeV&KHUr)5 zjT6I!)Cal49$gLBN!!}Q#% zUy9QoFf}mx*e_12T>_AEU!LE~#F_sYd0u1ne;La}aGW+T!M=9jW6RW?hpd!$ZVrvI zYBy*GtDP6H5#G*tnSId_ejBIlVb*hYEOueFDz-@khi{-4WWEuk zM#6x!^UrrWvB3Rr68jzO-mVYqU>al|2#4%m1y=*&a?=-^B@#y|3~rvKnC#bCRp{$;=_ zf2DAq`P0?CJ5JB)u{_?r51dYWw?NLD2DxpE6QVo=@d;t36BFQW^eup#*H{(B0X7$= z_t|aY%Re)He@pknieR_zk}3wLWtch0^ujvq>znuzpM%>Tyy;W0>TTlm-C>vDXQ39+ zVRFgT^k)}ZESb5*(mOi|oL7F$-3xaw|1{F}Ki#X$fcx#t>}}w@^EMeW zt^l$Rgcm&j2DS&pCWM_fgzb3p9nvq?j6|HRg0AnF%rm%~k>xHfo(GQ8w`(D1`ytDL z*sre1nL7s^viuOCY^C|M4qWfq-|&L_A*K?NhCynH!JEV(YaT&rjpRka@g)+9y54W5 zj09L5q=pbKJ-c`Nq06b@wC$|mjn$7JGa_Okn|JZ!S_fr;97ba}K z(8CB$mwpE6;BWw`_55=U&Ia)b;eCvY!EObqn|1+mp0b=R>K+2y&nJmCv*~op&U0RN z;CSDB&ki0hAoG#2#&YcE`y7~g3T)T5b=b#;%tO9xH!qjAWY{NZ$(G*YE% zWHlgmOxtX*8W0;9mrsYx%j)|%%%_ukp;!eRMfD?iwb`Py~h@CM2M zy_N)LgZPASsx#ugV8(wp!2Yy;x)YqPV0uHn5Pc+=7%p17aEWEWX~-V#_QSaAjp=3( zHR$Gqa6;C-U9S9yH6AxOyxVbM8%2rFG4~xNN1tZe^AE8ym?^OfYz4hHBcpS}` z_!jK{kH=8gZQE?V3>F8eCxpN8Zrgr(5@cpYp$#U$KR>9 ztl+psmIJX@eDm4aYqimGTlZ$mEhUgO#2c0%)>$sx^aY%MKx&D>{gy&-cf3-C+#~+o z9dZUEO#kIbNShqS$4BpBey~F$<2=~RqRrUXFoE>nSpFL9PY@d!?~ynI_BUIzE>?fk za8B51-t)@x-nlE5+apea%dYrL$bBmyb2h)gz2^)hkB${C{)ER7YZ&DGqf4fxYG;S zi4u;;dbebs!Rr4BSDL_Krw|nhrjhl4*f(G9+wso%@{W_4i*`sW^n=Z~t%bO+xa>FT z-E|;6_%JIcV*Nkc&G}&WIy`~gUkTIqcLwBMU>F}C-F}CC=LgehaQo-*Q$*hiU5{)( z;@kyfxuwypU^jdW4#(>Mok8_GJ1XW|ESYu3l0_*4T>r_3K+b^&nKLZ`_naF@9vz=a zw};0q>zxl^yZ;5)gX0gT_J}d@^Z(zNEO!PFHa zxCJcEv7#8OUisF;79XP1EakSBSXyjM0FQsLbwK7VK>F`b$OHQU#3ly+Dn;b=lS}x) zdiUF+u3Jfv#l999oB7|i?YD@oDhJ2Ei#P7Qs54~cz-rLVh?89mu6uvZ#6JITsi&}G z#-f83mz89!j_kJr=iNG8Yj8RMnf2xbY3CpAe~Fm?{>B11ujkrN$og%Nc_3UNiF+S6 zNFEuNB|Nbx`_2ybn^iXC9B5>D7(4dM z0i2Y)mvKipKFgbEP+&qwejn4OAdq8YLSm(01 zh5ai?d9+FtG7pAL&xVfaD0aZq#FRtI9>J%RvC1zfXSVQK+p%N2_%=(2--6)yKPCuS z2MRLd<5A-CDoDM_)RSN{K5Z~?Ii;q)Wz<|o8*!0~@F z1p680ATyXtmSXkaJ_VJOUt{--s=2f&R?US=IE`i*y?W-&gckkIc#C#6O z9zrPk!}Iu=`&92>oz@r7l8I^=Fc{*REmJh7=O+dT~&M(A?AzajVE?YG2!{>P1v);m?#&$PUJ z^tR=Bdke4`tPMxNc?M+G8kuEqHi%CMORRJPn*mZc&lA!Y>=HPSlJ;JFBYsTDL+puV z{};%;Jf(gC;PM1yHab>4h$yp=Stf7Vq!zsxrvO6o|eRj^!du6%ov<^6pBnLsp3_*$x2sz-i6C{t0Pyba1n*kD^ zCu9vS=My)fuFaeg0+|;EsUd`QYhx_C%^~YQH<+}5&BLZA?>6ck128o;3pRoMAERai zPD3zp7#$e5e8<`(gPqxdi!GVgX@mV5w_-B5%?MJn(T}wBf57n%*bI=~GhL9ouqSd} z0lNVt2EvlAlX3b3B#(@nR)$*L`@nQ6rcaU?@W*9)u zfrN>}XyKf`osO)TJ35t{th`@C);$(PLC%2zsrepH+Wg?Sc0vX?20w3%^13Z-B%=SVtuf94;U> zA?$MC`py$SA!i$%H~9_@2W)z7PHuzOJIL~rL$-qZGO>>lZ5m|xT!H8v_qv=c|4TPo zo(uc~PWPpvkbD4Aw{AD&{zMR)7<_QiO|YLqYL_WM?h(9p0kWH*(RCMa{+C-+g)`kK zT!q{bfNtL1iGRRhrXq*E{i7ao-{Q^Zj-9%X_F2|khl~;XUV)s04l*l!8>9>av5CR) zoyBlBmfVA!fBB_37$yH_FcE+M(>Z3YT}93*FIPFBY3&dZag4q8iCTtB(3*m1b zprm(?i!0&ggY@9TyE5W;MdS;D&p)bPiYS-R^|&`-zu)WsC&*os{dr3uc?eCTL%#j4 zpIc=t4{vL*y1y54E-P!tOt8B_N+&Os#;Ok_hYg?LSObs$)JKr@f29SxP{L3vhxj!$ zYdVxHKg@^3%k3+Oz6HA7@v#QrG=eUE*g%!8oIhrbTkW%8D9XXRm2%kF5% z9WgRn!{C1I=R}<6iLMtLzkWG8JZ`;PAnSZ%=0f)Gz|`~B;XcO`rUph&tZ>`8n&lJN z4_&_ybL%j97_IaVb&V-ZT;y2-*gdj*Mqo2w;xKy4%ch;2_oi5Gd?0Rh;y>iBK%c*m zbO2J5bg~AlAH*gGbN_t?Pdj2;uY=3eqo+{okYnj3DCq&8xlLa+cV62KIsb(>1^2wM zLJ#)w|ME7-{?GW=YFPcBZz{QCre?3DvFKe(`$Whca@iLl`?f&tDwaZw=YjZy@QYK3 z{U6SYJi-1H&PAMw1k%5N3AH{1iQ&RN95K7(E?)$v?U28??@bH)i@ksEo81VGzo>$4 zc$!AGYxCBZJHIfTu(%Z6W*ImevW7nC17Z*V(j!l?h8waO$ZY4U4ewx(9aAyXKMfulN;Bo22)3Bf62+|*Pwg{^`EB`^lW&LWznI0hZFuX8m z*A5G}{X1HD?Y4Vc%mS|=Fp@WioAt-Nfzt(uO$g8O`(m!f4)KGXDq?O0UEh^T?CW3dKT-nwWfJQvFpaKnp4jXiGtvtz zC*NqZ*gGQ}?AOBfTVNWb_TE^9ka3BC z1jJl%!p+GjZb!ElonNvVasPqLZ^-<=S-Jp<8M1Z6@2M-k7`J1hu`M|N>l}iNC!yO3 z;s>9>e*UMQR07!F5A_ghIzj4T__qz;F1dyGEp<${S~7Y*%+I9fYL6wJ;JLF@?v>HVRLxFZ3?$A?QQy|>@Ky%OAhYO+PlOQ7p1od}udLKmOs z*bB~UeJx+XW}wUW@7FV5oX>0-nd4=d$7&0%uO#$3!Rw7dYM(FYfahlrpAgO~Tn!Fy zkh;Rv=;Hkfkh{}+ z&n(93j~5SHcX7NDwdm*iWieqLUcuWVZ2Hnh=L8f4Fain#*$ZE`|`t3Zy=CD)toR#GhDTv#f zZc4)aU%Lcyh6S=7eC%g>kTc&vY6>nv_7iL8yP|~sotua=qCo2K;dIH<7W1Yb0GEHi za$@0m3tdn8JM8;AdO9q@@u8rAeSWYz&3I?hR1r&NFDWbL*^qNDt-}!gpVs1^@UTF) z6C3~HVmEkxd1VJVw`{Kf>b-q4DpAJ+u$coBbN>Hf=lujo-L7*L5}q(QWSZv&WR4VB z48$&V3I)4=nkwXMACMR_wv0ZsJ*n@Pg{AX+%M}+Ef$u$e)_4~jW*~JTJ*aD!L1Or@ zj>Q7F-Uo9b?f(ToTEK3A>61G=6|FbMPT@QlYwT1_>4g_SD+z#j&1|SX*_{nX=c`3R1 zkh(DI`Z{nPglRX;g`5iqe~c1Zsj*-U)wZ{&S4}0Y!m66V{5%l}~Y-^YKDy=>imkTx{T4KVuqf}h(ju3l&M zn&Xirr|)#Id*`)rz|GqC3(=l~>A^>v=pp)x65k-_-0ZlFFb||x=po{cSP&l{PG_9C z^KucS4|dym4m@np_1LVi1BVg1xZ~P?V83t|VxJ!_aXDnJc6qO*rc#$h<7&tm=}DRF z;5-8|%jgI0F&B_LI-Z%f6<*f6|M3N%|NoL3_3lB=HN>C)nR#@Ad8PP2uzS|*L5xeF z+v_VRiq-$u`TN1*Eq4)f+Q@nl2PR>+|f{T#70(M!5u(F#%{9F~tT(4M2 zdIPc7&E5%)uiLLt-L3i(_dXVoK4hF1{%XfNJuYzh8Mhv?o&Z@M#>?qpMZuyU~&+=TwYjFAZ`T-}H2C0ib3^{uR#3lw$=s=XwS9R`#<6lkV4NAG) zwV(Jj)gI4bIlmmzcNJuB2bWLS+@Wmlj@5r9Paxy|=Qd=4^ANh;pS3r3yv_;QvGn^_ z%jwz$U^8NuK+f#~sqNAtZT|Dk48-{tZC4;?hu+U^BC;U{dONw>`wpA0Tu_DPYCz>E#J2H>{GD*W6!4H)c5D|cd#0C^Dg|_ z25$eHc@Tp&{%d2Sc1R!ly}c;K)3Uh;a(1U^8e|+CWR~z8$eb{UO$^?75OKCu_9I9= zw|fcd+O#Q`ao^*BZpY~f*DOoDA@}jEFE|NK%jjxA{GWQ*=f;^!Ann2j)(^pH8>AK) zui7rR)4TVV<)meeRx=X5fz?!QU<1=2b)M?D!yF`!j{i0w&i4QL0kRkVcRlKQugVL& zIO7rByoXGo7C~zJz;SnNS%z%J)FbP`X$g)Q{e&8|Q&W+%*@{=2+-vUx=zi=A3`~b0u!OO+I!2LGY z;04&c7nVEWVjwddi4*Owm?1x_RA;$g2KcQ0Hk zeU3H$e?Cs!ng8$qPU+R`RxELldmjXBSmEw-oC!G-0Nq?%{K>kAHCj*eg2C=(FGB36 z1?ej{MC_3O@nM)}P7uc-&1HOHr&YMN6=(`yow%0Y^z?m`79j&uU)x#yFZEVvu5{%P zxMia*cSggA?|z4kK+v*B{FB^$xgTrDnrXi1;$fIHnSTnuwA3L-dA=tN#{65>b?du* zW9I);_}{eDWIF#VK_UJ(&e!>7oYLmHXIIFb8`NRKdhoc(k-0w%yzaQ0eGK};Uwn3w zv0U0F{#`GsxZb|GW@f?klw-1o3!g-cux#y$P5h1%rf}Vu*2Aq4@t9v*?j2vq_NTlD zcs;mzcK7jwCCQmu>F?tT+qs9|IM>HC<^Kl0BYioBZ#8oHjrC6O9f%X)FJ#d-73|>U zm#!D(``*{j?;JgupUZGQ|B40X?1JI#{B`|(Tt0KfMJ6xl61chcg=yU08>Xcl1p+dj z0!9ZP?Gf->VJaUeb&hY%5^lkpo7V_9>uKI7=|?O)6_Yv0{0FiZ9UzmI4O|4g3S92=|taxU+3Fq^gaq$%6pbfbA;pUpy- zF$%sGYcx}R(6J96SsJpZKV8M{)-6@$yJ=IUn#5E-9VN$C7r# zWZk?DQ{$$&yjdS5OeZ%k+jKnW|SzuXng{ z|CbTr&S&%BD|xG9_DEfkhe3HM&!XBM!3bL>e$DtVyd`lLIo4fl;Voxe%sG{pQ&^wv z3vYdWj9G5O0aM2-vb?Fig{JM=pZRj-{bYZd@$r>!3*!@U+0M7St&)4;^2??P(O0>i zW+?D^clq*ZP4VIub+qC0-6(E)bNLjWrxtU~nr$5g13q=|PBD1RdvoDg&b-ic4%d^Z zroVGkOdqaDGnwt{ZhD)ymye~E-Ask$6|dq{X6{FSWz54DnQ<@XdBOYf)mw?6U(@(} zuBLGIgz$4OmRQMkCSW`7yuamKO?3u5CaY$#zxN3-)vog9@;Z5z&u5j0Swuo1w{`k? zvoBocJQZ{MxNpoUxwteZmY=+lcc52WtC`7*9zE7TVsDi>Vjne>EMk#R5s!+l?cBZseQgoNXq=_)Oqjuf4zuk7xW%vL;;O zHYVKfc5s?*(QY(#jIcIVc`0wodfrKJbJ%p#d3)aqi2c0HseZT9eBx~*&M!MB@`aTx zkgsiACJ-%B!8IX9g*zr^GQWqWyuduk3A}-qEV!HVM0xUOmz(OY%;x&8{8&IlUC?az zr6j(31xM4%))M?d;$?ixZaE9E%iEiE1$hYU^3CK|D4Z%#>@-c_oAd(#Ya2fHb&Q4r zzwaL9l5H^&Iby0U`1ayfaL(6nkzj$p&Dbpltvr1KxWvs$n|+EehZ z=Ou1+?u*7x8)ozTPC6hU;S?eB`J5nM*x5}2uMfEyD}LbT&uR2GUV1`J@XX~l0d)@( zfkPi|b5*suwQ$5ibbDryT6-ge0jzs?)5j7 z1XE^8n_ix?obOafr^)4C@%%qK7V|OYwF>kbzA$Fy%oq5cJC|S2TT<}#+-0ziU z3l1#g^qgSHQ@tpb)!FYbPv&wpjwz?VajJXTbC+ui@-QZEi$`$g>nO$2-#_V9c z6h~~2JntFV1{0^k6fV^xQD*s1e{db$v5E7_zOUT%FXhc9F39EXs(HpWW4)$;b<=L1 z0OMAkMXy*m)1s#FcJQ@uJm+Q<;Mg=-EOzfoGoK`7v$RSF-ZI6drd#vY@NLRvmeFgB z=RJHOlh0#yDW9~-AFj*k5vGlaNnD#vIQYJPJED5>*&(ivyc~S*(xw|T-+RE*GJmC6 zk?l93)v~Dxz6b3vOa2LdgMdDY1DLnQ~$qFW}n|T@=14Un#P5E=ly1X zirwIusoCZbX)e)&4ZOK(-vqNxMe!YZb)92>PXPCc^NV<%UGL_N{hGpE)mF+QKbL{K zQRJ|hS9l0FYsoY|qql~p!C4GERzj;xgXidQakAXt(mYYeyTIDl>_F%*uACN59{D4- zLMe|W_?}s7^Dfp9Ta%Mk1v|GZ|36Zd(X(P^@m0CVc~pUsrUxI9}4Nl7oyhi zMctJ(3!nW_RD72apZfhYzEd0rx#X@oaI19hG+BR<$CPLHMALxu1k(x24)LwsY-ZB) z=ON$m`D|R*%CgMleox`peqcGTLS_f+olFJ(^LN>}ujRht5|hv5kNl*?x6?D7ck5{f z?$?H!xaY}gTjaI}a;*;&<5&8)+=SiCp6_8_hw@Yy~cRpVbIhqshy?##BI5 z-_%s*o(o@si@uTJ2Wb(7aCU(|Wi$9ip80T^J-x*lD>BXac3HfsoK>iadj1=e+cT5} zS1Se@1r#k7NDhwWGAju*GF+O%B^?~W2WqF@3CI$VT_eJoz&nY1N$hJr+tZKuZ?SRl zmZcl>)ToznpL?{{B!0Cdw~*r^0d~b&Q@y8`c;#f)8lTV4<-7CX3h%xS1_3kqH6}*) z9`J`n2=afvmMuI{Bv?RhLW4lC@DEO|VsqXLT{Ahmzt#$_IDLSZ=gc3|6>pZ9`KL4T zKK>*Kz=<}$C`qQlCs<|gyW9d_YR+04paz2A## z`G-lornB~Q&DvAXV-#?kz3t`!Q|=FExR__J;In%_%`9TmO|ELQ31&ZXI=Io_-S&oQC4i8_2X9#Xtkl4m%=rgHL4T{(%9_ug-Tt?s^jwT6$( zwtTfTyK+a5uhx*ql*`14{{UyPsshzLcz{QklLLPs_8AWM@-L`z$8BYAG-7Wa%GB|OIFJv}-&tk~E zbK+{gmPvl9TyMW{eHGfn_x|N76FG~UJl*EsP4Dp>7Bb{@;B#ko;5+e|h3iCP7}tTX zUraQk?M&6R)J%6@^)@}QrhxylS)Pf^+UtDFuXJ$UNi#CNl>3>h`G^Q#a?WJ|2gh%G z!SUjpW#Qf26D4MHFNg`?J1X76-Em|KPvEy$u9H@tW>>GNa^J7;;{V~PZ<=B{m%H|= zkg06{2JSr*o%l{ZaW$jyV*vIeoyjNC;uaB=hN`gQ6Su_7M zwk)3KOutNQ1ov}^$h_whdB7lD`nHyP{&7zJ>&JLZ8_ulcZJNVrCSST*Ft^NrPv`Uu zzSV5u+>0mmbDcdNXu2k}!{nWKqw&phF4N{I&itAQ_GUZV5Anq?wR6uXcx$%Dx{Evd zKtEr)F_XYq#~gnC?l)Xgf0%ikguJ=U4o~9qu?gVbR_D&Ur{pu|qcvToM;^@PR{k)T z-+9pl(~j()+_R-6%)GBM^W;|qaKE}2$5;1*(`;(A9nV?yy*!^bu?rf@2=Xuf%gU#l zv6Z!U_g}uMR8`JpLeatwa~|-k*X%bl|FqWZQ}cTM(luhH?|g*>_AhIe`>*5AclT4E zK-V;W0qHtrt``<}%vSOkbDikv;J;eUCEsQj$u;$46~E4@lg9OnHF#(34>7ClJj#Fi zt`Yx+SC{yn%$&$|e7Y59UC1=E26+c_kNx*e=JT6be2TIVSmMEJ*w%iD|B&2T&f7}^ zO#hn{bIPbp;XV2Ez2f0b8~DFEPv)xfw&iL{o5~X+EXaR#`!}u&r)+qvoE_LrLz2zC z*Xwa@a(c^Oo7ikR_ni+pYWWc{HuP? z;GZyMFMrwVCXSxCr~EA+t++RR))MYnep|paRNwUe>{(`}YTE^rJ{~f8>7XQdL-3j0 zhPyue@5Q48Zx!(g0!#gEO`pzK$)6y| zYQ}qDwa~R+CIU)%pZU*izRX$mVlo$RrL9@!;VGt%P5+sEnzg`m(qccsh@%tDk^|2O z9N^!Ev6V$t1^8uEX2E&5>`ef)n4QFCEk217GoMHzMpG}N;dDs`CF8Jm3Z<={xRUVn%m38mRZ4F)X>2DP|1bs zJckF*w(uNIZRs;+AKR92#h+iur|CGy#BuUPuD|_yCU?3{bNb0LaSE=D;pLfBYU;r> zox9?jJWu15TY{UtW%v$Or10h&ZRbq(x8l9pbf05+-VK4}N4t4TH_bA?;U;EY;jh4Z zE?U#PZc!uOW{ahg(;g@AHlG&aTeDlAZ}o!5T&uam&1_zHar*LJ=8Z8}A-C}AO^&-I z>v*|&bj-~Auk)m;_M3ik_Y=weBEx$+bR(~(%_6ST?}fSEF`JtyY?x!d`R7a1)V!Hy z&W0?!`-)|ZGB@nzJ-^74EB0KBDdQ0Xt|k2vyxB}l@>|!3@>LZq;yPjG!})w#7k5`m z6z|>z+FXBlI=L11x^T?RFEURyoW$9DJ(KVCf%#@LR%dcQF)KHo?qkMPxLuTcszW;O zObbD?;$B7Gi`GxMH=oH9zOjOl&oBEsuju<{Oh??l@*B6Ba#i$w5eRAcA}}Rh&U~T7 zN%MQluLw+;chFo|NkVXn`#;I;zoq#Xm{bT(W#AUP9udUt{`G?CkD72EyYJls&b)TA zN!L&F%AKzgSQIhSY|Z^`eD8y}%}$902^ADM2;94JnqO_V4_6E4OHSpg0yB?Y8D>vi zj+u$~beVjgkuE5qa?~U@^qoNCs}mfW?(@uiTh4GQx_0ojt&vk(8?a2^P|j)&Z#g6G z`dQullYL|bs>8Z?YyYq0G4~VW*^!fG_Iq^?cf$Hd0_O9Z%%^bq^6?!yY8JBhGvB>R z6TXhA_5%LL&YD^VS_pjbjO5?7c(%y8FVh8-`OXNac`o9VOih`jHn(wlGcawMKHH4~BImuusaVN!DC<9Ya;&wR#BzL5StZnw%n)0yYuxwn0+ z=iBq%Tw$pNA9san1>dWg8;srW$n)x1JvTex%OmW`eUW#fp#b0O3-h>|j+ZDsQUhbFJ#(^ggxNY=spQx1ogupZhdPm3N7I_!@fK zIUDBR;?C@D<*|Jy!na_`EbfOk%Xwx@lje@p*=Y7|O#*i!uNXfYi;LO*awZ<($S5% zZ2PX08#M=uPB<DT;luWJ;XDPmJ zg*%*VMymuSU3<=(pVeuye3h7)x}7Pn@5>g`7yI1T;5rCi(3(J>kEMYtw{O z-V5dh?28*$@cE=);9QsM!Nthq$s_f34==-^^<2}lN_c!{2Xa*~w3=zRpW%97b(b$M zbdd>%SPXY^UY7ClhQpj&{uXgYT5RGqdYx!`+fa<>u#i8G>Y1y;<}yiqx7`o%KK^r; z!_cpd|J!02u4C)A2p_p!BhXbd&$LWU-7KUuUcmQ#o#BJKvjq$n9+aE)WEY>(LMB1h zB@+auyj;npB|Fi~UoMqfP*XzSrGSSV;~@dwqf6KYJocS5T5^`1@3x_q+1~nefyF1T z^4Hvq=VvtB$~jTuCO5a3k!c%yk*T5m2cuaty3LS zC%@-hm>kY`_-eR9D!0CXl2SXDwOAPUtS`6tl!e#vi|l&E^Ze*zF2BT7?(fYuX89hQ zI16{y3)tS$GtC#;$9qKVg3;>SG`>lPmh$eFyv3i_*=}mfaEt%ix{rL9_!$L$9a0e3 zcQ938!n$kRzb`)GTlqMGdzoYdUqNOQpCC7*neGfGEIvUCVQfcYAD{7Ay7w!s(RjeM)M7thbIW6st@0mufADFV za!xuSbpE<5pJ~7hzP;bsxxL#Spnk9qPs z8U**;|HJp`(;hzFRm|L>YZUpO%zMJca%rK^>w{N#->Br8UCWF#YtA$0Z3(qD_1yM= z@56m2Io)|myaA1kd=1^re7vcvxL0nmH`Bi;$jw-1#K)ItD0_BRIoD55KE4vRX-2C) z`S8|zn3zoy4CZCg%;6O-+Q<8IWhNJw<$5k2Q)V;$Nzcq?pQ%!&Nb)%CVK zKH6qH(k^`b>yOy;UDEl%Ymmpo{v!S;Pd?{jcJC%v{%)pq!WEpyO+u%tn19-7!LwJU z&}ZA~v(S-V>ajIxM_zZl`L>1TN;d6mXR% zXy*pwIPSOHx9(3fRdDVW^HY)KS-zy4XR*dq&a^jyoW`BHCJM?7rZy#NW)q)HH08=L z;+0iCZoK#NU!MK@{WzX3?=ur|7UtNol9wmW@gSSzJTKnRk3TsX-iLB2_)2r>+;=KC*ZeN)1@|E&ubixWsy5LY_G zX?tcL-#yN&M$O?=Nvm=^9`$&zNg`N7-;S0woMsIn+K2xRl?J@~-2!Cjhr+Ghuz zw8N=<2d_@#Vl~s{ExB32;awqQE+uh?i~Cn6|8CA;)2hZv+;dk>H$MDiFSmZ@Y)+fs zjeK+7C78t7PvH?so5Az)hM=JKliz$7u6OgP1ij&Sw0H0w1oTX~x3u zqFZ?1EonDh&6aBtqbAHdspW#nE&CY0JHef@;+Nui&#jT*bF^pUi-_OF9d><^Y5oT> zuI7Y8yftN0rHYF4xDG#@#v2)}Zn`>nJI}prbF)=R*93p&Nb%13R><4FV1+3gj zX})HEcLtkYwdgWVW)L;~5_gx^!|;&V7lR$VUYtzaM-^1fr*?efvI`33O;o0@ zJ7~eg6_@*%EB0tTkMm4t-hf}9xf*Ux<+l9U!ui+vwTWK75C`AMaK1-Dv1WOi%ekE= zx0&hKrty4tPU24OR^{E#5@@#1^&>a0^*e4!erthydvEeidfm<2HJO3!`*ulzy$W1h z{8?`V9nYN*i#o8-Y**}lQ<2qw1gxDojcyeM3PyHLkhA*b&!5IVLvVYkfnYDU7`Ny; zIWv{&I-bPn4FV1Gn3V)CeCItgW43@tSd{UB0ABv}m0f1nd=&+^e9RGenX4qgep80~ zJf{xVql7c24?J1S_OAGCY#}$(T*$Rla9LS^vBG;1!4T2;Tya~&&0>ZBaAXM1=Ti-T zDN@}0QsDd>e(ux--??sEY~}a3<|#1$@OIvu`e2^h+qHQF`L3Bw&llxh*DfL$YqZwH z|NKTBn3JU%9Udtbu++mhB@t~Q1(JcN1w;v`q@3IRlF0e)%LT{xhcPeE(k?@rxW&Ffnap;@`x7(`44unfyoU`T31Z zuJf^!OypwPxsJPXr>+T8`v(&{hQ}t4A5Aiyb%aYGLoC)POKl^6m%wAL2Y=6*<`!M$ z^w$jIt86!r;JmqvfAgoyT;EcRE*> z)^7ekEOv&iAshKD9QlpEyEX93WG?6PdMU}zDrsRVuf)RN@|2g4$2&scb8SDr&a1in zckM2+&j@ShzqL7*`$(IX@P*bcfjMPe<~deL<{Q`x1gd9FHNCWPkAO4hKDnK@ZtGUX@wau4g=6RSp8?UQLSkRc7)j-4qfyppa===2^slwT#P*WplGY z_q==jMl5ao@xfZ0CpNC&D!K5~^wqvsreAVqmrx&VuQ@8ozkQ#MY1EVV{EysJ`6K1t@}Dl!H|y&=&2N@*gRjE`@Y&W3Qob z<(NAE=_i?jAB8vss~3LbeyzR2?05KXKK_QY(&s$psJ=5_!Dn@2g-~s5zWHC1nfwK6 zk*2Lyw*>m8S%ByNPi{-&ijtG&ejs+s;&8$gv-ZVeW>@OtEz>V}2yVNbWA6Orfxukz zE!<_^`sM+p+c_WUvhceXJE{Aw+aVxzUYL8Sl{k-4QISBkn3%w%tUSK%Egn27Gj{Xb z+Qng79hb`egYCLN#f~_0?N1K;Ggh23bGpeQ&?OPefBL_f!0PVnW;_1s2zUti@&Dbp zMxax2fk5(aQ^B+U6}eqf-S{?NKFt*oaz!Yle=6U9E;h4}nzyF4x90HXPi!z1owSIb zV`ZaEjQ%7(Y45*$FZZVNPhUQrhaz2tG8$JG~&##y= zurJ{AOAh9q6F$+5zvDOe@nt=HJoTEYS#Ny#MZWIkywQ4vyLI&&E{&5_d>6wmao4iT z^1jM$WWRIY+H?hP0e4>QME=c>B+b^8v~#C>o0*A-a`ALeI>z0yCE)^Fr&tx<(OU;z!Wq&1S z)~584kGHy3Mn6l8&*pX*-^##GxyJ0#IXS)+MpJk#FMr_mUUh);y4g$)&a4#EnASa}b=DH5ZL1nhlJ`&K zd!Dk*R6qU&@3wwj?wYOJ%vSAj;jS!u#p}G=MkTOv2H)$nGn~BT;@sUOzqyVt-^lA3 zY{9kviU!ZrY5p7s?njw*Z0X^8rgWa~#NRqIe%(rLcV=_*IZ>KCw%ayv7pA)Mdi~Zm zyScrSJNN!E?&xrLp-kT>KEGH8Uggwqj^)|7b1WKi{vWAqtFwhAa*OsydJPm#s48dXpE$?fWy!v~cMa)2Y*En9fu- zH=SkVD%d!k!_>z7t-uZ$2Cn0i`^~=2xXS6Svw+V)RZeV5_acGV-z{7la=N%Ths@@m zEiEg+9975r{n`}n#8_4C5Z4|v4IW#r?{gjs$oTM@>?ld%0(P6@`JWx1D!A>*WC5>#cLgq-zQm?I(NN$F`!=qYXU-xH^4fx7mKROT zqSH((`9uVFXsVjIXXOc&DKqn{)@AamUtBG?^R$N`!|li1V)+clN3YJ{`SNL>fZdNs zfw#5_eEqGP1^yZPo9Nu<; z5Bcq@(*6R!SB0j<2b{7wCz1T4)T2s~S+BDiErEaxP9a~|`*`#GX^I11R$E8+1A z3NY9E@WJ#&EiVtNoQ>&B2|eBqZ+xVy@}+r1S2OT>e|f^QIar13WxkH-f0@8EX!0Yti-0yG8^5|dh<=7$9z)`6<(WLzU zH&dONQl=dzcbPo8yoskteW~fwwhSI&Azsd=*mb61lkakhe{~Cb#$U4e%DBPN3 zWA-Y}>k9w5nmUDerp)@p(edsC7vp0?&i1#$<~^}ZoM!$Cyy5GTOq&{FxF#H|HJkmQ zf$PAUY7X_pZ`@bxWz4c9*|=XtpWxcOhFhR2YZs4KXAsX`mqw13lpNk#8!e6&D^I?Y zZ$63_zVk7w7B)6}6&b)Q{#D8Ba?BFGuCtBOt0H@OFG*(c6}#v2O+LrO{cQGR)50%P zxRxrg^M$iHDtFyv=aRqik2hd(kg?}pUf!iS+svBM4-4#(PvgzJvXHm?S1A{JcNgdH zJzA#XYKCS@_j#M@COVjfDYx)(?4N3)?eUZMjkN-2Nb4ulN6R$0c3z6%?U#5g@Mc#$ zU%@;bPTc@q?&K@8xeNdG@E(l3$G!HjEstRwFE@|!ZZjb_EAIFW)A^b&@S5FvqQ!GK z`kLvA**%K%O+mg3Z=^d%p{E zuU+&*V50+%c$z?#S@LX7^G3-ez4q<+ANiOa;yTZ5^Zmi^2DAD0t^wfj*(v*YTd)}|)GIUO`u)M6#b*Dm;&Ehwc&-iAlRM01IF8 z1@^}zahLpiXSB-i9`_GD8v!k$ISMy;lzD?=Oa3pS zacz5>!l!fYil9(^mVoxfK2GHc`P{!G-thI?KH~S!5#VLZy3EbiFq!-L-DxI|HlO3V z=(R|oW4fbhpw)BU+3!V+uS-<(t(d{WS0%$N@FwlBiSf$U`~{PR_^(~NC6p~5EFkaP zA@J##0+)lTDX-tmtDOH0W(r=HKg_FZENaI3-^OfDJtMC=!wj=W6L;}ldr%{#H|r?x zHAQ|t@8HRN2d#E-cgFjea;Q3Thpdef-m)vwGbnc&}qH%qPc~$tb`2>6Vxj)xW;ojPkWV+gFmf2?SD<=Ns1*VJ7zU5uywaU;T zteme)Yd2Tot6e7h7Kd||HLl>Tw@>28yzq@L-uN~5)0u0zkIU@loA-;2Ph!$Mp3^hp zc|QMK%D!>pTr=BRFD?mR9{&GX%BFgYZ}Y0|dSxgnF2eURqM0|Qo{z71$|Dn>&X>HI zNh^6WZMy_BbyxCD{kWX(L=Q8k!7*pPZkZ;o{*4_%=4t)nizXg1<3B2CHve!3UwQ8} zQ!VLqe);sLQX6*!^95u(^Piq&!XFl*#$CSM)O1ndW$qhKR`7+Lc%ia&p(wY-!`*xv zOJYp_N510G_$FbdB{H8sb&fCJxpl#Odal-7TI!QHgREFhb7h3h)^(Sf9!r%o-J6uo z|51#|r1SQ5zR<-UTo-o7nHHHyaA(x<@M&d9GhKM{i?4agVNUmXwcOuz7jlJe@Z#H} zx|I99W&qE^6@6U0S6G={7f|KiUgyovBKF$!#99WP{FYSH{9lYbT$}lMewBaZy}QG~ zH0TREZ%KwIukzYDL6#k-_!w>{^UaUyV9(~f$M+-PA_u?lBEdM-+x(ic24)L-9nHRL zZsPx-BV~5Gj8&lQHjB)(LuGuH$=(8`>MR1`lg+t)-?1}YzB8GNe{~Umd!(GQn4AQ6 zT4x2n|FnlDcN4UD4CI7N#WhPr_FS;wFP*)e?~luB_P%;gj@Q=(P1T(5n!fg9GTl9G ztI4dRP6B7x_nIvIcZUDftYEI%ikYT6!UeeM#jo=&O?uAM;XISye(p~Wx2eWl>laG# z1byP-ce^^Dt2M@yTjd!uJJ*!erZ;%saHy@i#qT~b#ALqYHtwcl-ll)QMe$q=ox?3* zV91|5$IA4CtvJ7bvN#{-vIfC|1zr3-vdj5zZhye_`B)cU+S9dMx(s)P8pKxeeX4n8 zX0)f<^v1t!yvvS-n6j_g&);|Bpp5RfgM7CqOY;A9Z{m+OYU63S`QPOD?={>(_n-5n zScveSdAN=Hss%THUVMYexqoYTCmqu>ixXSI`+b`&U)c2Zd`Am|xfP#W;?h07-}LI1 z9+MBfOHHO)d^4G{-Hrc^qd+)|4mAej88F(lvtiGX(i_ZXf22=7?cyEM?#i{>aP0lG`NI zR{enAa{d9+jWzLRF*+Ohe@@deOP(euaE4z*Zhu@NpBPh+fG>l9fY|a*u96K`&F-jw z=RE(souBPas7#sQOfGHxYJQo_t;PYFYP@Dgn@uI-5A(A;FyKGaa*6M8Wiwa5avW!5 z*etX8kJQZFrY4!@y*p~Yx86{Ivxdd^{GcZ>nFe!pjRA z_^)S8<+9mW%_YRNlIOar2>+!nDekz5iaair-#NMEtjtgGT;~CvRjwD;QyE2 z!kuQ|Dx~xCw!o{5du9vvdzvpw*d}mh$qX}tRZ4+pB(_ zvMt?v2` zx+x*TJ6mo6=Sw>dAseIZyh__Qo8^i>HLL%s!n-80&ZP2uJzt9P30ba9Gk6=8JM#st zw&&A)wwl|kNzp9EQiCh*5(D4wq*|42yPY{N2R!0Uy>`~*j^7lXi7X;!**~rbh{Z

(u53Zi|>OUYUFmuAY)@+~zxZ#1~s# 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 kmi}G5*R6iv-W%pe_iH$@?Ay6RVqaQxx1E+b z@BY-T1$$3-sO;l16}I&(S!t3hUd|jrTfenk_H4}$_Wt@h*ETHC+4gTu zlg--OJ=Q9Y%lG!?E#9kjv3hTY(eu5=7PI%yb;|J%s%hZbGx%vu~m2Z->Wno9D@LR=eguw^NK-x<~Yak^Sn|TzeN( zUa^ZjcXz)^sL?)=0}T5v%_!fyao>x*KQ~?9EBHCmZkzc1J(6!U_THajxhLzR*50+Z zr1zBvPu;Jpt~OWi%i1fvnYPc9;rw0`vE}d;Pu{MKAZ3Xl3mS*5TRrdrA4eKiX>he!W<= zS5V&EZqjLqy&D>r?kPOowco#lZLbAmo6RYv(!H%`YxYX+xw z-OXq3e!IcubR+M9Gku}9zf{Hc9&UYTbC~gwZQfsB+x1W0+ho@i?&Vm=ux~qa;_l65 zclSET9Ni_d;?~|NFCzB-V%ccdJ$J+2qilEgdb#rMd$x1t-j6W{_Zl*vwh^#5+c&9K z)Ao;H^WHhtR(lNIujj=v)=3vF4x=3#_wQvwkCS-V%66Dv0<*dkl8y-d*jSICl9!ie(t@fRJ3xZ_#&05-RJLindUbm&P_J(I>?^7t^+V?Pd z|DMv|Y9lMt96IcGUSLRaH zUYo~md-Q~V>~$#Y-1l50cwb1T*e*0x>ZBC{{Vs$lPZ z!8N;oL`UzLz*V?+Cy(O3*!yn#8nw>u-F>@tpUTgyy~c8dd$0fR-+M`n>44H6@qL?a zi|-TY`n&hL_tHJRJN4|O5&9ANPFky;TAGe)j#}y`^pDUIQ+^ebZ*L z?GwHwV>hd)f3H*Muf5g1A$vo2iS6Urw%b1QOUbUNv-$SIx1a6p6c^mfx#{V?M;(Uy zrl{rb`QkQr@5-aq`z=&+_N?GpJY;+jW$PTXX)%YSfkk80?@eY+=C?CqXmz4uR3yUpPRjW#nE%h{*Q zKel(vpKp8DX9nyIv}WF4yZHDXw#||@X{OWmt}S?IrPdg<=i%%pd*h3E_I)-F-Ipq1 z=Wv&Ouib%LyX^n0Te~NR<^0~#uQq#?8|3UGwa)JKp7(#RCEx75^{pCq75+;5f^9f# zTTGts`TcB}&Fa{cea%zS?KPi-?<+o!*}(q4;Sc%Q4tMVko^boZ(YD(}lo{;@aQ zOL(7a`rEz7V^j7`J|4JhlU3W^jOw*}|8HX0$0Kxf@9j11d%X{C*?ax}-90?Z9_$TW zW#I5#==9#&&6D>y3peg-65P6PL-cc75$m-5OA|%+y|m=r_c6M`zW(H_z3mq)53G~m z-h zEe-l;bGH2c-u#ru_V4Dk@Bceh##Um5UWMb}hGEZ=S*@;m!GPc`p< z>mzxf<@Oz$7bRi)Zy!?G|L6Zro1`@#_G}BXwN=${*kTX}R}%fIdW*%Tu89jaYzv#_yx?-qe}yQhb{_NM=v zy4Sku$zG;)Y5O$4UD!MG&<~pfPSUmv34NAlk4@e?#hZ2CqOS}0cD`S37tk%b?}9Af zzH7C)`zz-4?a}wEbg(}%&)VMjmUZ)%HTzFVhTHevp1jxK4)^{U59T^dyF6|0_Irx^ z?3ldwE!{D3@9_fToxMj)_nw`~Yy0ucroGt>wR>|fs_ir1;AnF^bC1om#*=%Czb)LC zmAHBDjRy_(OS-jfe!qORm(gH>y{}xPP0ivbdrOvV-xss|;a>jyt@grS_U$cd{;}8O zeB<7Qx1Q`R3t`-MO+IVix^KsAErk;HzMQmaKd-{&y-X#y_q(?9`I_q>kS zuy;%S;l1~R&+JL@<=Dsh!`0@gR)_5_A&0#VCE^YxUA_BOx@p;cd(LE2+F7`Fpl?Xu~3YiTpFUc&bITDv_{xf}N0ka}a& zaad^YDvi#)1vzrI8DYQn*?TRb&B12*uDyGHAK%OI!fPK( z_TIfZ+q?J0TwvJWw{5+BtLW|hw<4|VV^>?-cm5Bwm*h|0W1afKMyo^CMqH;75j>Ky7tcV>DcSv*u48b^Xt8H&;8kJ`(*Wjd0OZ8n|(Dnuy?8X z-r$+~4h@Ts?p52zu>WW@@BUZE&hK|OTD$jC?VBCtYmV<_Z{*p_CDgHZ!sT<;k9802 z{oA$FCVk<#y}!I#_HWc!vd4S>#J&GgT&@30G25(@SY^u)yMNz8yEQgkTOaL-agpEa zY8$(E?XEbRk7_-8r{!(hD|~dxfpw4X@0D9}es5oc-k#-N8unB3H`{TWz1&+qE8xJf z9Z#(%e>rKFVYFxOk`FQVVlUNge}^sDr?Jrd!2Y*C>;<&spzw(r%xAZz{HvDfZiyx_iV6aVjR{yS^`WW|ELv2n}oYVzXuYnU+AmY}*ysMBXAylbL4EmzOsef`waIp+6es3vC9)w*jIh=?_QDkuA^HmwUH_#O|Hd*}HF=*3G?}x8K~qOliaJIm$cs zUbrv3k8efH-o*b0_V{ek+kci@$~Gj`&|V{F`ksI_Jp05HgZ3`zlG-Oe@9w@Jvjcmr zKC|x4dii;;;{~Pz`{l0fy$~w3@7GoJy=}`F_P+dcWv|lI1ADbrP2cle__MPvzSfU8)m`3H}tvq{!5`Ad$(!o+n(7X zyzhKU`reCnQ}*AJ*4eMd>$uM*BzfBQ4)49vWfMM6}HM76$t%>Qe zIqM{6JIm8*pJ4B?z5C7{+52ltlkNPn#d}xom$f~T!?;g^Y35$OwIchx;`sLE?R{-; z_JnocpZ?u@jj9&!YkET{ryiC%R5*oo!b-fNXH@H;L=_dp$&VEWm)Y1;FYm&pQ+^DNY`IBl41S( zW?LM!FR^Ia!zjSLzkkb(J&Nyd?KPQwZa=g5gnb?9)_d1KDz@?7b!)Fz?q# zO19}CKlfggUc9%Z^n;C2()_)47ccIWGBmRNyyWA)!%O=2na(lY+gJE(->OjCy{-&h zw#%#B_kNgtcy~qG9NQnB=d4+N=mTs`k`f$j0HS5$prtY8i>=4;+vrByU-qV+aZMWLJ+0`2_wD0N> zwcYk7g>0pKSM4?X>TbjEH^nArL%i*(xQ{joH&5^0;j+(G@4&k~JE~Xj-LE{!Rxz5_ z?rpn--BH2qd)GYa-uqeRw#`9igdK_EelZv14jl_g)=_4SO%dO51i^6R~Mdp1sGU#l==8 zOVw^dB!g{;7t_AOPT4l!yZ`OA+O%o!fe?kgTt1I%;_rp*jk~#h@5ed+_Wlt)W?feF z+D6Is%icKOrM3;%C)nPLTxcU9!M@ixi(?;`?osOo)00+vrmnV8Vc^~4;iX~A!FY4G z|APL#amw5F{#=}~C&S?6o)2bgZJ*wA+#9g8aqq1&$M&{7=C$2)V4khP^vBi*KJMIY z!a99#LgcpH%YQ}LoZiG?+ak5oHs?C8-L()Q+sfVdZNKeVY|E0pWN+ZfqP_e<*Y|$< zvA{OK|DTP@ZNWXtmeRY|EmE_MSt_t6HF&-4YUAR)iU0oFG^|*+r>LiA?_#f>-PsrZ z+f2D7W$R@6)8-f_!@l2A7xz@(K5iS{dS$PE?jf5u6GCkLJ_y;lPTgShNp{xW?Y1** z+Z6=&On5SRZ_bIOds535?C`$DxHtH;(!LIDzC9ir)%MK!)@d6O;JRn(r*F11ycSqj z1n}8(uUxlB@V?Go8{dhx_mWg?^Jg>LS?pl2UD^KGW2Tm#|&jtYo|B zRQ=u?x1wxydUx%~vYlZ&q?U{?KZ~Fy+xZ-_uMr)u~*~Bu03`UT_1-%^f_A%Nx9FyA4i#JW z{xTKc`=Do+?XGJcdvpG??hSdKzUN%lB3r&7$Gunef7{f*FyEW1HN|G%3TeBa9=v<| zE@|z3+9qYUkb}uaPf&H=8>zxQ(-M#Fc_6E}H(#~Ic85mEu0wx1_r4NYwl|%JjUzX79a5#FaEH(v--^5BjvC6 zL{&uZ<~jOp*OXPgdw;NU?LG1D_MRifUABwY#O$5VAZvSAyWZAihQ^-yzt*;8^)-8o z=I`H|FyX?UW1hw~ftP35@E-ZO=g!~Fw%ZC=Y*%$$+*=X5*ydHphrN!CcWivGt=rq- zW^KJKn`bZoOSZk2*RR`KSaixpI4;em*#djxf>_B>GC zYf~TdU~j^mlY9QIu(y@BU%mIi{54r7Vy?qIDPM4{;j)g7p?8wdwX-? zULCWUHcPu6**HA^wmac}^`7=U%KI3&H`uPvzOpwddcN&v{vUh$Rx9i&y=`U7aCVxt z`B^r*rD4nVPI7Lt?S9>}cTaF<5X z)Ufxc*k0QR>5108%N1>(ya=_mIA6U-f2!2JwK8Y-W@-r7vdHeSwW;N?eIk8)55wF5 z8!syn+uLtCZMS^1wCVRZ+53wp+QwCfdH1>bi*1;%YTGKEW!@*vw$bKj$%Q?W46STC zy1jOOp3S;%Y2#ztRCzVqpbo`-5|d`_^$pr)yTPEu=JkuYd(AQ~*n_-ErArPl2_jZT;!pHpfpH?KRhZX=|b+ zzt2b!bldi>y>7F2%bUF~k1yQ&pm~{X?{87NkZbO?Xa0P*y%A<; z!}G#zZ&s+^Ub8UKeTPIR+vI7S*eji=DEAxH%o)1}7dyaAc+RMA3=Kz1qyFH=XyY`;d z%d(d>n7a3m$kx4kT3_zF7Q(+zPJXhz!T*VNL6ev7TQz<8{!_dGd(GpY?A<#{z}{{C zoIUprW$ekm#ke4E(wx4=jsxNc1owqq*lx@7(~d=(CBSyXI-0+#RP4?M8f`Mt%ylgkSCYTgpq zx52J`ulT~rds7+p_sp}>+wUI;Yn)a;xb->!0O?v;7D_3kzwKMOJyUo1s z!TK9}e}4aDBjW02ch9I|Pv^<_s zV$Y4ed-wW2W<8MmZ0p|DvHbRJRk!wL9eA|YZGzRFy;hU`#(c1i7XI_b1eEZ~Bz zk*Ljq9FxU+lQX;b)=6HsO?SAu_tcH8``^ec+v|32<6gar6T7+hZrL07{LJ3`mBxGj zDXQ$t(o^1ZK(ue4WrgOxEALJA3p+9IJ1{$S|BuTd4wpD3_wD$myXU>?x4lwJrP z{m&_|k5`ZHz{;&__X@VZ+q-qO@qxJWv-gVqJ+NoGQ_r6Ft77*W#;o1<|FQQznOJT6 zDgICGx_9r{CsJEy@6uVZe}9&%Er-~vJw6?(`+vkW}Ds&A^UaT&+p|wT)9{A zf`?rztH8c0>l1q;N@DDnob0pTW&dnnsf@Ml*13&)`Q63#xm=O9z0)ysZ~M&E)>?8w zdnHPNwe2fN^Y=DiV%^96if^CJRbyLbq0YU=;dgC?t19+iE&986 zy6gcvja!|2t|*o5HI+8oqdig3LDAyfZtbmod*zd!?B$(w&PGBpVZXQL@x4)jSN6Xs z{A061!NsPFHGiLyo9Mm`r+)AKygq#Ihn-vZEt) z_a89vp160}F0h+;{ML!rtHWWA>l%cx>DLZP^}U=DWLBw6Cx$-1Kg*Szh?w z46Da`d-;uQXLktO?E2cWN8G#JditTxJ+c+74quI|?X(P^@0SqL+4Fl&w#^^YS$oSC z-nTpYS!iD?m&9J>l#abD>kjU7^@_9=pQ&tX$1Jo@Q1|WLwGV3S-hGa?`!^?WUsplS zzSZ&T_uE!}+4F48McV`SU+p?%yk+l~r=RzBYMI;AJ(Sp&6yULMuklWsFG+{?h8gbI z$0{Sf??2nkz2}ax*!FFive#+x%{?DJ&fa_2J9+|6I{9B|o}D^j-a>t?Af*5rhCh>Z1&z+xzc_Q?><|p3d4O_ z3_1Is9JJW`{mQJpZ>#6n{Il!Z7rCq3W_dy3-t#RLd(ZiV?cMup&wk&s1^YRFZnXIs zG|&FD#+kjmm)`EZ6jJ4oUBj}^e*2!imtP;;+pr^R-`#^B?fPUl?`8WCyMNnHxqYTS zBKw}Iwe2h3W3%rQ`|Q0-HZ|>!b^EhVBEQ2nqEK>=!L_+oFD^Rl+5RVW|EbM~_SX8i z@4LQo{=NsPANNKYUfi2o{d#X+g!;ZiKXq-n&)wPkNB+#-A2tkowd|JL&NrF3*Sh=I zUf(cz+cUS?_nx24wO_%!XP^;8{w(jL~+h@yfzi02VM0cCpXZP&QYEjyg$9vmm-&?MI`;@r$mEQQh=fn3S zHveRl_Dp(e5C^RYR5 zE*)pEJ<6xMr}5k5z499CZ70t%vXe~Rz30@~N4xurC)*Z?7TBKNmAcpW;<~;2yLa!c z?t8vh?AA=1w+2i1{_uEl+YyOSP_J$TMvw6h}lsI%#y<-mG%p`{FPEzN&|_cRNkx-22ZWeUC+;x6Q}y z4|}cqckf*ucYN=X8SD0(ahzcLHfHi(*OqJ6wKH4xZi?7w^JKvV+ngCKd+ufw+OCmb zw6~%;Vo$)$se4ZCpSbteoE|H;M@#px&7QTl#A3sq{qc=^^U}8O73q|+P0?SmSHypU z?ThQnY!oCG+N#`IyLVA5%f1$^9eca}$?OX_$iGkT=aXGLpY&`W?1|g`??1Pl`c(nD ztqw_hnU;OpyZolzIQL9 zli;2LE=IcvEAH=g+I7~pfvd=-*`dp}$TfQJhwRJN-LIJU2{3Kn`}iEsz8`GLd!_sq z?$S=%ws-ciReNsmtM18Bv)B`0Q)DC8ZfPqkv(&cJ#cGdPda>=J(9L`6HlDKm^0ds> zPRVoc_hM7qZ{Mfx{W9Uj-nTW^_LkgH-sk+Tb?^2nmVJ|S1okORv)Q8%@zusaRbiib z*Xg~YdmLu<`jZ5}{ zJ(Dlbx4p#nYmfb$mOT&rn)cq*yKa*h^Ks9sjaT;eW|iBDYVFnnTuj!dyB zxHI1-^q;cbYPW~B2~r(Q&ii8Wm}KpXc1(hT`Qm%NN$zUMX$0?SJLG zSN_Nan`dj+?%_9y-Rr5ywNH$-WG|ymneB|CM|(VWMDNY`qi-v-`=d?JU#Goh?_chn z^of7pr912QewZ(`FLhqG?F+uWdksu4?zMWxWycYwxi@R^eA}JwHG7vC{<8^RK51|1 zXARqT@7V0bGP`XXP6XS!q;TzV5wF}Uc)V}#6ZzA&r-at+`MM%}ufPT`Xz3a9_r^xR>wouL$HTQXzoo`rk#_87!Jv?(y&Z=-P1+E$}Cd#_%0m-X`O z9X5w&zt|hScIw`HUsU#fS@Y92*LmvRp1c*dKbQTt-Kn$RMnbu3uiB&N-4{8O_D#EG zX1&)#W6z-{j(e^0oA<6Wp1IdaP{?-C_o;i86KC%|rK4n6>3bJHF5LTX{^q?;?*HE#yJGrY$r&uR{Kj?G zvxMf^-dMnGdwbf)z2|FJ?$!9`V>{t@`tAo4@7qY6(%ie};q$%sMON%desju}c~|b< zt4YlFBnKoa$y7vA|=dok_ zV!gMc=ENT5sXO;%%;4K+Xyt9QF8$7)tLts|JTX4E%gUbD_C)#~8-qsz0q=4|_V(<_^6FX!3@wsGxyxqItgDT_aQm)y8( z`}DQW-mfZtd#CM{vt{^GWOYs`W{+N{(%yz^Z+2%sJik{_H+Qe#kIcPl=2vXDEMeQX zcfYnzsT%;ePfr+rj|Q4?^KQU>TKlRdwI!DE882__9_Xo z?%h#Yyr)X8-DbhR9eahY&apK-?QOf@_p9C8r*GN&l6&jkN*9TJADQRvJ*;wJ@537s zd&P3it-~tX_xgnS**4D!-rbv}Y+E_=(cTlutos5t@7o)2TGUomNN+Dw?p)if^*(zf z{}fq2TDQ$MMS0Gi8|jLBd(60OD|kI^Q?{_!8Y>F#E6EYDy&lA4^S*WJ-fx!{+HQ4` zu@mu_v*+-kZri3)oAwrz1=}w0_+xXCVbva!Pup#ciZgBA+ga~zxxdl2HDr~I&KrZh zJ2w^Xby)4b*O^siuY>Ot>mt|Sy=v!p_s-+&-h24Ol)dZE9*?V#C?KABA%qv>=KDe>NhDS1P?^kb~Z zJ^gpTb!*6{y~fHedwpvR_WEyV-P57)*|vWw|30B)?Y$a%^lWE&Z?g&5eP(wulk(oY zm=(5eH<#L~X05ZyeP3 zw@0hT)~w;m?g`Vq_s)EEa!*an37h-Z7T9teuiv}ioVKm-9?^XYt@m~>_+)IO=qh06 zXmeoin;ZA`$WJ}BH{Xic)@Jj9y&8@`ZDLp$_g%LW-uH{OY44vy|Mn<8{AjyHfB7Dn z=$(6C2Lb_XcRG*oAej+neo>W6N-Ez0C&!PTOfALVGS;`?8lqhkuW8<&wQ=SI=U$y_ z+ilzapR~34G-2<1+fbV*uSt6u^lfb>%{XiuKIzh~0~XKsPTJ3Hcc_2X-sLNV?Pi`? zvL__)(VnH!S$ihvJ-1c~*<$NE_2^#Cr59~atkkvTIJnBT%KWKq<55Ao+0IAydL5Rq z>up%Fcaq5#+yCV|Z5i4R*<5xLw#{JJyf-X9m#xm~=Dlsg)_Z#QN$(5z z{J`dmTJ>J;5)E7X`{H&9i#G20IZwszlVhtb%d8iBdqoe}oKxO5%=l{F!wj1iL zZNsK=@6GG;ww*U&gDt-XzvaxT^?PqkV&1E9Ud*;^tBmaz2Kjv=D|l^RiOt`epenm} zBG2MIPrfX(4GtC9r}3w1&yMDjy$%x&TV43}d$+;WFMHVk&E0!K>+jzG-D~!0Jaw}T zV65JoSg5#LCqU75#f^nF`xvG6Xn0@SGb7#0=HK4^dynlsV^bovVef@Mi+7*8@q2Gl z$c;TWZmh7qu6bzh0)tt5TV&jK-RBS8Ta?>r8}xYI-iEdsTL$qu+XlDQyH_V0+A6Rv z+5J5ybuZtF_j|)VoA-!Cy|!JZbjP-9!ATpx04clOW-DzCZS_L4O_YF{;a-idu_eD?X&A1d*AQCA)xE~KH{p%a zo(Cs=Y+W=wZ0~GbX#F&CyX}F1)?I&`lx(+c{=TQjxohu*!f2Z*(T{9?{LHm|@nZF^ zId!}Ca;*Gi^YJ~)-h#4SyRYOPv%O+>*E&Ax*4~^2+O`M!6ZdfXYwwxCdTH;EYm@dq z?_jj+Em7P1f4}IyUounomMh!(GG`H@38vfjd`^3k+z8VR8jcS!_9Xx*SQR95Rd%1qG?Te%;+ZQ~Fd%B#~*#=y2 zw@tmgZm*%;MVspCm3z188QRKr8t#48o3gJmQGVZ&$$$2~$z8tRS9pT0{t>DD5AT@U zDd{oV_eaYd_{uiTW@321J?EOfeUqY!_x_OkvDaCXW3Sn-yY`zDj_#YkG;&{;%P!l^ z;e7iF5^mY)>{i=nJng~0#f)?IILhShoe*zezmvgnFScW&+9*nNGkhVjY0+dnScckg!NZsp`_`wJI@ z?Gf%5-d8q#uFVC>^Lu4ap5I$o?YoboYWJSd?k6_)=Tz*U)}gX5>BSK{2`2e{dDi!A z&XzXsF}8cUCvt1Hc9Mz zSJr16w)xcFotsYVeYxt+-XrmP`+C25+5XY2w*A04&6c}X-=RypZ6908$GwkNU*7Bc z_4(e3tDE*ODec>Ps>@{mtr?2@K<5*j?b&Uw*(AB|RO81zD^@e^b@l@_c5#z-nZt&6PpZ^uzml79rsuVH|`CbJ9l47hyR|8r?2epWvsWERneEjyGyc73-%syea`au5PHIrBDnY(!A zekPaidpY{H?`?FDvv+%UeJ@wq>b*NQvOAPto?)}#v+~{z!k_K>Ek$kF#IEdXCI6Aru`K+-tE1U&#^y%Q(~Wr_U*mzKF-{4c2~^i ze!z_V+X^r3eJ=UQ_V?TBy&r}B?7ZA;ZL`Dm_pxet?)SG>w=Yu8+U1+vz0ZPakG+?q z;l7`o>ih1$GvC)P#kp?_!$LdXTk89G3;*op@87WZud?XAr<)}9Pnw>&@8p^ZdmC?T z*?Yt4=f2~-^KJGw>Dr$0RzL7{QH729rImX+KkTtT6R>h`NmhgKIR(O`aIgO z$E0iS-uQ@#`@1vU_nk`kyf^c|-(GD7*L~9Rocoq+=&^gPduMOj?%utp3bpp9ytmt1 zT;^|Y89mK@_U5wvU5u;;u1;&-`!HE$e_!_eJ@en)u`xa#zHb^6_r52xYWx1_PTR}$ z=l`A`cdpn3Ox3o%+E`#4ae`yNFxR5Ju|`|$roHL0wOCqbdyJEDAID2>hwTq-_MVMl z+Z)uxvv1on$Gu_Jn)Z7%QugYzH11C;7qX2zE4J^7LFvA(^(K2n7QVKr$cx;Y(tX0# zO{Z)B%$TIT>pyAksR~%JC+&ygzRpve4s&gm*v>wBc>li1jQiTxv+R>DcDAq9T4$sD zopImmmS$KEsbFLrO)dC{)j`^w&1T$=m+*SxizrYy5h>r?CAPW6vA`o6vU_i6R) zR*?9%_nCvl-i-Led-u-Sy7$oUjW(9|U96{e>+SV>qhR}qQE|tU$CvhMzrM4laFV0_ zsjiKCjQ*~(FELHs`$JiM@9wIJd++%h*@p(T*j&2Jw9nIB-TJs`xZV0)=C(zzIri~< z`m^^t&pIoi?LGTDPtDywY1!qy{hnU?o`0Wi?THrFZlP(l-{{-dee&ipM&=8Pv5&^kNX<~Th4+X`_9VT+Sjpb7OfA+kl zec~J5*ckl|vbi)z)PC;r*ZUsJChUzDx3YJsDJ4>7;!w)2;UBEbH65FaFqGj{b#vu7oz)URcMx?|$^P zy&qO`?akG@xYyXbYIMcbe zVxEMZ+YV{F4IAd}ee+k&PW16&o6YRPwz9Lg*w&xovRmO}VY8%6!Sx0H#mJ=)YHt-wmEtq_K_kwIko9dE3 zd-^sC@3R+MZOgERXAM_iWDI z)UW<~J&j-66c>u_)so(~S9nk7-n5&iZBM8O+R7Cz*gMH=s_mXKUfbm@Q*G}1vD)tV z)VQZ>!qmOj1ibcc73SRcr*fT*)Z>Y^R*f=t0WZ(kuyeiH^JrR_?Ngpbw(El?+Wa>& z-kVr?Z;wF4ZyRAh$GrhRf9;my7TLRK?^WB`8uGSb583SI`MlV>;ln%|PfJO=iqIW4 z7dP?R)i2+(H^(=7?}N2gwm(%@?|HfU-rfg)m+d|2!eg_fblctqz1FsyPVU+p&BkZT zc6h$+ia>F@2u3B_^pDYdHytwFd!pTZPp53%9h^$!f^XulU_!<*Z-F8-Weiq_s;6T-sZX6_D-C3 zcCWzCH8zs}cJF;*$G?|L=ec!5?>bxNS(j`qJ~rCk^0{YotVn$Cm3<4X4<0*Z^HN2~ zR@jT#Zgb({-4*`>ZC^Lb?PJl@vc0u%r)>hOkL?799Gflg6!-2pblB$6%k8!dn%;Zv zr`_9=cK4sn$)8vDupB*SJK6of-kpEW*|hlb?bCWa-FE(C|Gg)#?%Vrde(Y`r|DAh3 z$eiD^?~AnEf^dty%d$CbS^7)HER+-mQ(7w`A}k!-R}++%55WZGhzl)S*UH@3<8!spF~v# z+dE6AS4w7uY!z#?Ul=XHeQ(*ZPaaC_gFt&u=m@6vwPM3 zR_)c)GTvMI*LBar*gbn$YtQVx+* zEw_=k6FD(vx#A|&AM$dE45(y%T@zS$eEwuf$0yTaR__dmSV{*i`hj?5(*X zXtyA)a*xKdg|-6qp0-W`B73GvF12C!pk)2WS#ICmv~HVcpO)Cp*w(W*#H`lVDQTVU z^A$?_YV=m`J#p;#9*^~>Y(C81y*uh>i!JN_Hrw2dJ$r**3hz6x_|F~*`6YYSsY>px z%v@^AoOpTf6^3RTt{2N}f6ZOI=f~kwdw&$$+Zwd5-BUF0;@&=9iM=yyw%Uqnrr2I` z=C$TJx5uVGjmehJV4dw|fAPIB>66BxScpQFXdq-t~?G4%eHmnV^_Ldc-+9cdH+g^*oXb+1F5;-2yuC-;b~J#9T(F??@B0*j5q+)CR67tij^etOk*S@rI{!W($^F_^O0 zgy@&ss)kGL6BJ{%O^{cy;XTi?ui?Z>+q{!!ZGFUL?6Pf??4}4V*gMftz%KjK%)MLI z9<*hedCS&kj^y5m95dTxzu5Lp$how;Pqf|k=w~_GS)2dc?krB+yT+8y&Njn-?*!o- z+bf(~_9R^pv{T|cu=l@O&E5sP4SN<8FS0&5W34sECr8@{ekr@Tnp^hdyfC+|+MBx9 z>i;_11)rsCcRu`L+itpa*PAUT_A30oV{_Jy({9o16Sf?G+HK2!`Ro-qCAZfszSDNc z+EcbWZtmTCX8M=CV#eETET9s|XGTg#1y_A;!tvTZlqu*bD@n(YP&UfT&- z_ierWe(zl`bzqmvr8e7k4-VTeQf;=JZ@=#8*&w-BER|*7o&Ke^8GS9b&Ka9*7p&2< zt~i*#=W(6%p2ePv_e|XIbJsD0Q`S8tr}l)*_1ybm@+VFPI zylv^W^S-&*KD)Paui* z3dw!XFB$A*+sU>!f628yCtUgV)G4*@eZJ+OhDY!lZ1+sl7*tF7_2(|hb} z-tIkclz(4tzOqf|VzE6ZXe6<3&cR1}w>_-iyYIg9p0qNKeLlt4_Eb;k-xDWQv-kG#44dCpmv>K%`es`Z zS!BD|o@0+#>1NyAmt1WFdp&F?-Y8+`D&0YlQ9k>IZwhezw?J24CAdDdV!$H?&L~gc!#nZIo+pg%wywL3 z_x@P_+x9BMti9LdnQUjo_wP|&_SE)j-J?C33?jC&ZfEwU$BFNI^G?xLD|+4DgsvFd z<+BoOcTZeoJJYOg@9RLuJtaSv+HzY3?(z;iwzsjqVXxM-Q+xG~7VZ69(!94hBxLWF zd2;*wxb64ol!WhjDsk0jFUPXo2O6BMJqns^J>?(Uo|$!f&%*hNdww0ix>xqt^}YZ7 zmh64|t9$Qelk>K9leXF%V7qRe^doNXf{$l*8@e*usv61L-kB$2`+Rzi?Jp+rJv(J4 z*&dk3VEdYZecy&yS-YS$H}_Po%&~Qn>fHO1XVKmd?KXRQ3cl?AEyuX8W4gCZpZvtV zpU>Ufn;Ms~*SJP(uZ8g6y_G-sc7NUJuxC^3-aYDv+ilzJj@jxRVcA>KxYAaxXo+p^ zV#_^_#*1ytUz+XxwSKX+O~!c}p-|4f9n(Z?KX2c=cSD4nZN!g@w#V5o@4b-|W#f>_ zX)`fH)HWfee)rM)L3aik_~&J-> zr?z_HUW-o-wz>WnZ6}zVx7{#zvbDRX{2r5FuDu0$Ypl=wo4r@rV#cmh3x)S`ZtL57 zV8gaOvALRib^hVQ#iRKRehdNR;heyq3*YHB!QEv7zd|jy5&hCRtY7Z>vph z&#nG$Ey8rrW*``%K z-@|^gd2jWBt$Sv0a@gv;XxVe7C2VhAt-zk8*T33snQ_8aZtDHLVw#ioUUcNxC#-p5 zZ^;6-ecQY^_WnEKYHKk6*Pa#9&9-@c+xD*dEVxJKuA7ZQjm&QMpNseYaJgn9p|IAb z&S3T47raxfzijfdJ#tFjwnsL|_FL!AJ=s+uR)sT|_ubgRYS%H{!sb?o@7|b|$M;BZ ziS9jon`2+K$V6L1*|fa|Zh^M7`W<^e?R&M?WUJHOH#Tec*nVxcP8Qp2+ptY^uSofZ zJrzDRHs`L*+uOY}%4P<$zHP1)n~g!f%ii}U)qAZyPueOAE!tCOF1s)M+x)#7H2U|Z z{#Li`xSDG-_s{vgE4NSIJ7Md6n+*s5*hFzpwAH`AelOq3&wHhEQ&-?;ZLbE|C^ z@3~zw3TN6fco*%}K6}}AMfm}n<4bt#X55P1yS%^ARy^mt&AWY*_qOsa*gL_m-?sh6 zY1=C~Kld&;@O$sJsO~+HF%7mAT#ska zJvExPw*Dv9*uGmT5k>1Bs=C}8{^u)bu&tI@rn)lUK zYDcK;>?2e5zS4MR`!K9~cT{MrE!R{HJNY)|y?L*i_I~GIWi#>HgFU{UT>BRE-rU`M zR(x-QcGlh%JTLcHe2d+C{^(tsTfFmaG95qeb=f=7wqu9i-tcETZC|$~?dkr0X>aLA zSzE*Ou)T9NPwYwEe`YV^F1x)`R3`0lQ{88~>-CmBq1HV6c#nkdU8uj;#;s4$Hqv74 z9#@mITVPwV*v!@@-pV%S;9d)_ ze`>b9&ogZn2OYPw!p04R_=DwUIw;lHZ5}s z_ReV9V)MZMf%SwQ6Wf^ep?epU%(8v*p>gl2%vHO$9O&Fz@FaK7?Bc053|GQ-HBLCV z*W$P1o`xrhw$TE)b|$y<_X=c8w$&)_uv-(peXsZB?fa%b3Ems0x6qd5*aX{vN0Y2Y z?2g*;+z_xeys>@nCy5h#8!}z?{F$F++n{p9n(0`t9n%-~z1F>J_iEHnww)uvY`cMb z_ueBZ{d=5p7VRxEX_WIbZaJ;@JPjiB;!UJ3Dh!SO+=S7iw&+whx`+z58&!2}|Y&+L)-1|bA z%jU(RS9@%<#BB{$<=O_AX4_8C-);SL&Q4ne*+(|!+q(9yc*AP&FS1+KQ&cg)-CcP@M{vy1iKIhK?6=5-#it&kJlbK;Tp9u|#TdtU5vwVmd9*4Cn( zZO^jMjkXag5w1XdGEW`M8}5gOzRM!O*>bG|$>9 zwcGE_km=adv2Ba37RP$qYfSBXUw!J?`=Mg$?f|2;d+NV0+xz5=qOC*Z_dRz`hTDq$ z4%j<;%EY~v5tsKymoD1(b%V*?E8_CD9!uD5bSzHU9zVN&uWkpseI57Gy$?7`b{l+p zWW%t?$NE8pqVI1-2fYG&W-zeZMl9O3 z_g48qTi42id*5W9-+M)eVXw=PCAJLui>*tXf9`p-=*(V`D?EFRyf*L6dFf}HHFe?M zaQP#4ADWVFbS4$--Br7G@3c7%d$(mR-a9R8{oV)v584LY;RJXk$DZKaY-mrbY zejKn>n4n?%tF3i!%A+(}zHf7E?-;z>_hHfl>zq|Nw!6Ed_O-F>+`H!FF9&>Z zxA*~#l2xZ8*I%p&+dJwa^9|>q;gLP&tcmT3x&NW zUe(%mRc^9P_;ki*NAs;cdWGtHi{zKss&^i;eXx1At<0ZIHYt-f?s+hG^4?vEx_f6_ z_O}NaSSjt|rl})w^qV0QHW_H**q#fB+Rvo-g?SSRpFZWt)1rB7}9^2Dq zyR&WfJ{yL)wno$9?dByteX zGJov$FxKBAGVio)qUx4?43~^-+J(06{WZhVF0H1~cGtazz4pgH@B4P+@ZMDwCVT(% z&9-UmvfcYabI0C;eXI96cx&38SY}}BB-CTOW6oKd*K5x0{Z|{jH?8aIz7rBxY&h&& zZNIIP+RLnIyZ2K2THE@!o9t5F9p9r-!@uXqnxnQBOI2(wvzzvs3hmx|<4p733Ud|P z2-o?x(w8##wuFh<9?8wO{UN+@@78pqy_fo(_deKOv-?47kB!@n<9p5SG}>+mN!eq1 zrEK4m_IG=J?6$~k(!Hk2W;Q$QRpn){lo6w9+T@E_J;Uvu{}`m%bG*c z#dhH*`@Lrs4fggkP1&2$x54H>+@{?u3uf84Z7JC+yMot#N%=gR*)P}c)408F?;rm) zw)ZS=+bO*9wkeyyyI1PoNm~iYEBo9`)c0Qac6-kk_se^}W;E=5Ip1!t=&4nEi&pKk zo$+&xZOqI5y&sC^S|@B>ZnJICIa~Yd<$FbL9NCk(%xmxMi+uL#)f#($y_{wHV{Vy^ zMbR4@YxmN<#rI10K1-6`d+tQ9EsMi;TNCe9dmbz_wUxbha_>jkb$c0n+boUdZ?wJA zFyD4YMXJr~nU(uC@>=cPX;o;~;PS{ufm?G=#9T8Q&S(646{i2+(-Y8a)AV$vZP{YJ zy%!4R?w#{=xs5=~Me7qbJ8dOyGVO^;_Oe}Iy~tK@!QQ<^Z{OI7XfCsPA^6-T=H|*h z2{-C&8Kh6{KEUE{`+4>3y_L$x_LeK3-0Nr2Yb*9^#@5Xk}}>qv!>53;!W3{Wd~N<3YZ<*+Y=zV zS5BDM?vdpQ+gn*ads&K(*#6Dsw|!Q8e(#xwjkdbt+wIOold(Xsa+d_Lu`*b?c94{ zevqw3iEwpWG{#c-;0z@$5ahJxBKb*|BU7$9@CbjT#ku zZ|w5ko6#g|yZP(xJ#yi5tV9-w?!CP2l67w5XWJ*{i}srT{=BF9p_lC`b+*0vjL&Tw zzLxEk_|$3hGH8R1L9wLuO}>P^A8tz6o-$p#ch0fRdpn}aZRPas?W{FZZ7;mfw$XT5 zU^C?b@7{x({A`c+8t<*s`>|K-=z+ako~^KL>}a-?UiRMByDY+XN5ZB($D^3`W*C|6 zeUz%akHP8r9;sh<_AJzyw)d#s&b`<3B=&8pZrUs0vdgyG%y;hs3;8|bNptr`E3?@x z+0V8&NlRvL>4na{A2puZGM~F?E0XqSkH?tuqhnPY~YAb929KQbQEB7eSKes5XPqb0 z-j2$fd+xZb-pe7vyYHd!y1lR0@a=oKz<969-TQmlpOx$-KSB=@0j=KO|<8 zaB#WptGiolZ$*~d2>bHvn{#0M9t}H5+gj5nwlS4c_AZ(8&AQ?P(?0z|@qIf|cx{>V zpY6G+yTbaL!gSleA7|U>YpvdUZjpeU@0BRqeVw9vOZ1y;r1z-pE;&2JMu+9mUMHhu z8(oHgz0ap9@Ac#SYNLJKe(#s7n)yKPu*d?SEBFB?)d)?_dc2GZF}_91)FC-+4j{MZ{F)6x@50o%#FP|3T=A} zrF?8txt7?T(zvtNZ8Dpk*mJpk$_meHMSjZct+eRe8#0OAcALgC>j`~wdzYPly7ymi z`W}xtS8NJ;()Kd`PT4afB+}-qr|;hXKW^9@{Qq>XncUO8rxknlWL2x$8BCGe`~JnD zy)tUHwl=0r`vMB4?iHMN-1fooox9a1huHFDeYK5WJIQ8gRKebDLB6(0r!4n&Ywq9c zwT@@+DqB6)KBl5EwDyZ3&q=e1?JvwUx8(U-l-&u-Xk zxw_LP_Hp;#mZxiNbe;Fu9$ox+4~O1N8!71sTNVw+z4F%ZuA~FSg&f_h>`&-Wpla zy>6T5*#0X$Y0Kl5v6r1$bnk%`68j!}kh5OUddEh71;@Va)${kx{~==6an8ba&6l+{ z1rpr0XMb4R8n=Gmv+wzqJ*^6p_m*|5>?^o7+Y_s?0!M*>wyY_m?CGVTft(fbx zhv`{^4TrbJo}DMl_Nx3g+Q&LUcW+YX`Mndu_SziC6y9gK*K5xyjp{wjKkD~R+aSMB zd~)XA{!ZOJ84notbuH%Hd;OfS&6N75dlRR7+H#)YvAur#(BAVhn{2aRvF=+ln`JMH z)ifLP%u3s{8ohgO)vNB6j}x^GaILW2Qp{v~a*4Gq&)Q{sbQXWKQLp~8_w=TddwvV? z?BjD)-OGFV|L&#Yk+zmk3T@X}GuZj`ZQbi&K6j6fY_M&yqSU@vVO~3r@F1IGy6-V%Qi{E=p zWUY-u>gm0$uJ89oHOTJWI)~Fv!R^&v`<1-=R{of|x5?RPr|KoneFgJP_GZmB+iRvg z*?N!VCEJJ)r@e9<&9;Xty!KvRG1u0eTg3K4_tU)-`qcKMg-qUievihU4cnjW*$`j9 z*Gh%oc3yAj-YGTg`(}6X>{Iq?+4DlLcW?0l`Mo>N7TbPX7`a>DS8|`_w{T*;J=J=F8dksri@L?7mdK z_fq@rz0dab*zjNcYLk+BY40MhhkNT8Wo+ZR4OfKDHy`f;w zk#ep*ruKmonui&M(t&M}*-XP8$C|%n{<}&-jIy3i5D+}3u)%CNr z(`DbQkTcijbCvwwPktQx<~_HtJ>Xus*NMB^*8J}cTdx!Q_CB2d(V9c=>z)VmXY4ib zUS_M%QE2^OvZ+l_!B^X;v~#x8LKoX^TXoL%GDH7fhUXJ@S_pO8@SHzsyCG-k-u~|E zw$3sAdktT0-@D})>)w?e8}^t*T-%fJ*T>dqU&CGoy~lgA|FrLY7tw0FL3@sk(uq&D zYpkB_tys;vr(%V_&83N|d#~56-Fw0Bh7HG+9Gi2~O7?ni@$Pvga$;}8)ofcU*0jA0 zRX;5ctkmCQ^gU^>M1Z@^AEWEGELW2DE?A#pTjI{Nw}zv0uY~#=+bN+>_pDy`)>`oI z#JvocwD)T4NVZMyWUDC}U%YMmyheHNPj5lHqTbVc z<95%nofAxZ@rrIUNcXNy%7(x_O#ud zy4OBr>E3UPoc2bpP1~Ej(rk}I;^$qPDtm3iHuKo2yb!XDyI#0At>vg~r{bZ#6B_2( zOmIGBEA!vMRwr`C-UZV0Y!<{Xx0%nXxi>X^flY#__`bR6OnV=!HL>M;KYOphpRhf5 z*mv(e`c}~Hnt1;nVTGh!8Png{JU<({XTs4Nwp#txd&9f~_pYhmZR_-Sjcv?IjXeT_ zPB!8D9^34ZY_R=wS!^$h+8o=6PsTPXE39o<_BPp`SLC-#;OVxmI^4XQW$U`VDGYUc z+k!UQ>WJ*Je)n72?(W)8dpF2lwU#nqw*B^Ry6vuOlWh5?tl9g?{Qhp~H5Y99u7BQR zkS4p&L7~Q`-hb;}p=nR{2wF1QD)Xf8&7YuXn=IJ4mv#T1y|0oN@AcWFZnK6X*|vmH z(00l44YpzLrT4y@EWOXmBzN!bLJ_;XxM#M`Pv_ajE|1t-ttVx-sbTM4gXYV-Kk9|q z9$gl+_eE*z-UP|dHg6Jo_vpXy-klJ4)q3)$_cn8W-Pv<5+;MODo_~8Ug}&R<#?iBP z*_YL}yb7Xwo7-3J-Nn|tSEEL3&l52dTb@1rd#`W0Z~N)Wj6FN-ZtdAI#bqz+GmX7_ z4}9HgZ^>x;f8n0Ji)5JXo~{z!_uzxj?hP_r`$ATC*&J}0v0FrLgYA>UnzkIf*leCR zH|*VcK+JBY8;`AD@5;Rq7oXW4``ct&wPLmHL(A{B`-F=2F1UKf_QCA;HVhtHY%7je z>}kmevNhs+WXpF^aqrU1N46FZ4EGwShwhnmcdhLLt<%;zmuK!-vQ%QPN&l?f9{rp4 zM!X8#YqiDGw);T+-d&TdYsez7Tc%1Q8ugN|LxT?IB&aCjBW4!*Dbb}?Kj$*Debh4beFd=zY)CmVW_NK z&D_g-74EOM{brH1w^ena?V2Q0+lty&+r-NAwp?~EZ0|~K+v75I?e6ui7i)3l>|D|1(ym5OQ)Z46jcqZ9w{Jhb&V3*Mz&3L1|HPWoM zi5quX_qr?Xy|6vqMkIaj-pS`H_P9B)?0s=-%igMm^K7|IPc4Y>0B+huW2Kr-L9$fc2-$td$mtp+RGNs zYx~6Ull2x=!@VjpqIMchzI$etv)g(YS=z44>e-t+=Ys9Z-KKjib5!iwCtu#{Y~Z^$ zp=I0NA2N-$S=C2&-+sFuI+d1#f*=8mQ+No^u*!xD*%=SjU>7Iwiw{6y# z9kWSnwzrKaziZ?Ep3PP!aOUo8lg)cBas=*mGdQ<*7E8Y{=GLecJEn{@y@pX!2{b2X9nA@iR<>VC;i#mGPBpV zX9?Hd>(;YvZ&XdU<>F?xd9cH5kBB#u?W)iBY10ePa{5 zmdDm&S=Jt(u)aMDv{h{8^DyuGmGs0`XR?HC*uN)x7nCsXS^KnlZ)jJo_0gFQwwabK zd*!dr+%wbr*6t^#;%(i{_t-N0oMzLPaAGfC(@NWwZJ(_*{7&v+?z(Dwbeq@i53VM* zW*;W**|4#|)-rq1-rv4Ic2Dx_vi((lc5j>7e$aUpdsj(3-lN^(v-f<{3)`9yJKHP% zqI;84*6uA(wYF_?Pu^3`KXEUY&L-Q9F7GW@GaTA0zA0|6cGvE`-*UFw{xIBVt755V z)6zS2?}gX}d+voyw*A8`Z_Dxcy3LnYVK#3jzP53&>fbB9cduUc{?=J3u}j(=PE**sV3y_H zoJ)GPKe9Y*Pc;A7vtj=?8{IzTJ$@X+Fq=mv3H8%yFDumZEU%_Rjt?_OWLI$+O}ui zncFt3&*k$9^Cs%!M3%90i;~6EpBkMNp1=ZbKs+4V`csTcMv6rzuU}9-KgY%{J z#;Hg4d}!6*qgME4FZ)g{>kcLHeOLM=>@2?@u;p3oZ|gjDgydqp%@Y-NH>ZEX@|ZEa80?|s{KXzyxIMcV+=UYiS>l5K2!J#CwBs@Sf*EWGZMW7|D#rES#e-n}mS7wqlb`O9WWvy9yVE=lV| zA8tE~sLM8dug>mm-h9(G$@1i$gn33bzg`^LJGZOLHe_S(9-dZ(z0cog?-iK#*Jgoq zicMDd{XKi9bnQwxJkM5(&vdWE!6|zu2ko@sNVl@>IG<~Cd`ID)Ir;K?7td7MyZj;J zzA0}kY)?G;V>5SO=3b8A+`U>y&f3nIxn<8f!6&v8UNYM)yL8;PT#L!>-m<-W`eKgQ zx*m|;Ym~os@0w&e8;TaDKj_SCCfu<89OXLsnE zskMMmo{hmREnB}iJk|+kzS>yb6}5T8_;Rn~^H(-v<~M9M@E_dECfa2qFqdzyhQ8X~ zCz<=KimHY8iJhHc%em~{&I@rod-tta{pf0hb#6@{c?P7 z#*#g@OT(mXuYDKXE1E8_SHO7nUgmm%JzJH<_VsR>yO%lGX7Ag-#y?-HkTqn%~;&ofo%v=fP{X9`iTZnr@l3_wl*^dwwwZ+sp|zvz=hJWlzG?P}>jH z(`}vp-`rDlNpx=r$JadzX0Y1otlqoFh;xT6Z*usan^Qj6tUoSbw?kx?t;rEy+vLlp zd)sGh*()LyWNT3N!Iop^2b<#;t@d6JYPS~Yc)fSG#_GKb%&hk$&g9s4SnJ$gh9IlG zMK&^fdlcJkFH7g|zNo{xPh`#4Jzb5n_ZU18-Lv6V?`|=>qqgg|J+oatd&k~AG8KC@ zt=H|jA@XGJ5q1{aTb>LyumAM!$t`+ot05R=`_;2&@2_14ZEvJ4vsKyHzUNlU*1Z)n z6ZZBlIAeS9=mXoC3)uE49hhi)Y9`m-oDZFQUD{l%m;IT!*Z7&d-9!#A+otjfdxfnx z?YXvl-X5>xu{JA$X4rnINVjd6T521zh}mYHJHy_{!wI&M6Ta*fyY^)F^RzE}uD$-Y z_tj<2eY2*|v$bp%-*@%Vo;`J%EOv9>3E8dqu+LWSU#qRnC6T?q;??&iWR%%(TAkf{ z$6>9_-7SiCyOh`3Hr%a1_nR@fep`($Hc z@qSOU%y!!g*VpgiXnSSjbJuY1g1_tbrWj<|Zg|aZ8#znGmj5H;9u}TF+hfHtc23Ks zY=4SQ*<14S%iaf{me|aQo3@ATp`xA0zQcRU414z;G|}F>BcIv!md*LSE;Dx9gj~A1 zr@_9*CjWnz&5~uFw)N5n_5>WiVI7}(clYK!%=^Bany@$EjLlxXd$Vo79W1um(Zamf zMqtBUtGA4H>oczG`T0|I?}CpjY<@_K+wL~`W4o!4+s;^3-qyf?bx+E@>9$7C`1kGZ z=Cox$F?H{An+-NP*XP?By*g^U&FJ`^I};Y|Et%Z2=N{;eQMrfKDUWPy&u;!~yFB*0 z?bc1J_CDtJwee48+UKxo?w*M{7xo?~O|k80Z`ymsyJt_s=Hq)Z%vRgVE56ygrBmMS z!-O@vnY#AdN-GNPyll{7!{gVn_s2s)yDv@$Y!B@4wvEtwYI|kn{yjO$%=;SlmhTl4 zYPW51@Y_43q1;wQWUuXxv*&Cp+NAfoJT|m_asBxNbL ztvW52?s?_HweQH5EZc=o|Ly*8{mY)Btb2P?*f-nWi#cH%5y!Dd(?iz!UrO)Zh5L5x zEmiBbNzYTYT~?yLx9`<;+k(i(-41Pv`{W%xY()-m+s3%fx7k{zwRc(f)V-TB)b^?_ z%-DOkz-_OX$_886_@2E99m{RxS@W#bFK)BSlFGH^ntWmJtJTCe-cP!`d)I8(y7xkE-kv|ZSMFWGxMOdUgtkqCN~^7C zPWj%1^Ci}0bLQJB$cOF~iz(h4HLqvy&jX@%6Xv<>$>E!7yR`6>ZSjo8y;3)M?RXev zZ8bARY&S4T*e;n-Z7Zp^Vy~(B2HSOsZ3xu)uw`3p8d}=SlCkKC@VT@1ldPw&95)dxeaa+s^1y*elyG!-l;?(QeNn zK3g4ExxFg)-|U?b-fz3*;g!8Lf%>*hC4#oe2TS+ zckf+tlPa+p}n>_a|G@F z+KAa6{(sn}pqz7WXrzqYg1RfVF6%$;{lT$kkND*BJvJBS*zn}v*dt^sw%7QGkll;b z0(%3WoUkb{RoNHNztsBN(SSW41C#d%SiRa?b4=S-e_`96%U`DKHGI2tZ{#zUy$6>3 z*`wgvWs~>q)_43 zN4Ie9+j6+o_JYO?n}+q*_MBs!YWv0T^xh3Zk+u?1Q}^6hxOVUQpj&(9UA=3g9ACJ1 zTJ=g>Nu33IC+t49H|Z9GolNz-J*OU4S(_%_-g7~^(OQI2*LK3(AlrYtckY#TEZqCM z_=Jsu#-rUG*CyNkv7TqMf0L@6fbR0$JnuQ}_TBBaQJL{)54)F!txfg@+gXnTcXKV} z*lY8&*S6>1@jZFGQ}(7Bf3)2>>)-Bd*`IqBx%Jzo%xm7u5WUd)!rQ<-CLL34i)82Q zX=Qn6YcJTe$1&>J-nE{hb`B9UZ5dB}-lKC-%I3Auwmmy1O53fNb#ssCqu#v=#f$e& zkk7Qyh*#LVfh*Q_>63Xj6{06?511Xd3FPM6XL7q??+SS>+kNdXZFVZpvduUjZxdU7 zcF#$PKepL+^0qrn-tGA@QGajvqEmZ~*L}6&lV4%Gw_Ry(U97!rsqEj~+Z5LBz3|+{ zcI$7wy}D`h_tbl2*zCx0u)T2egw4(~^Q|7Vt+U?Hu+}zZHlwXW@$@|&X9{h_cvbd_ zt=6=ya#(14bf1$=@yvO9V`A3Z7Ca2Jy-<>~_sib|Hx0dH0nAt$QxC?b@3)>B*k$mt$?OHY~JV>K?pTB#-IHgX-OH%*($*pOfz9h#Gxshq5_ssNdvHj9uZ=1&0zjs6UbXz0oCfmr{8GA1%?cJ->yl`*)qGP)avn6e}{0_F& zshex7zvad#{I!o^8e55St&8@Aew(&bBo_^LNjkXzsnA@`U$wZWY-hzN2B+Zqeg= zAFYtKjkq+!wrBmyz0rq0>^;HSY|~ccy0<5L!`@GyW$e~$K5ct|v3)P|%(UI|$2ZyX ze5~7DAh*Nzn5h5Wh|cGGHoQ2n_sD^XHk;nKTIYA1*;}CU)yA5c)z13fI~xJr*)|>> z%6k_y2=2aib>r@7ix%42o!!6tk#@iBf%2xkPybo&%~^ZjmdjaUPu3gRJvtAqY;T1A z*|YnrJ`&g|u1lDgO8?n#?npH27735>Iyu;aOHjq5SnMV-@amsT4{f&shFC}i)A`o3##+qXx1 z|Jv=cnUXYZZ~W=Ad+k>2w>2tTYWwHlEL*8KhP`qV=kGo9>bFhAABH^%5;}XQ)lRm} zSi@*@xMBXDY`vMgs&mS1ul60;)3T#*?+Hsro7pDbduPs6*t2ronY;I{e9*CXovhTpcU(C;PpZi7UARGP@7s^1w#rPW_P&j; z+q=$GX78(~tM@XdsO??m=&<*IpwC_z)dpLR@a=n_tlDLJprdc^T=!o#*K&pJj`Pjk zJ4s31mg|F&ZP1;&wmDs0wx|Dnx4pIgrERhotCZBLhb@!rf^ zllR_BPuP2cxo)p5<6r9vnV3BiMmzSNewDp9ZnBb%M`rxqgY#|nN`}nYYuR7CNBP4~ zTY;IAZ4(x*-791oW4mKQs_mf!*}Xn8pKTJB#@T#Yw_xw0J)8HgV%oCz#E*$`LZBrtlWEU}!-S*ErcDo?*Lp8!mgL^$o;J4b?;hF|R%q@sICO8Xm7vf*t{_c2RqM%n-#t&Z+3q7` zoBCm!ZPOQLo4z{+d#e;|Y%5N^-t+ow*6uT1QMMW_;(Jw}_v}3v_-Hrx_fF0OCy=A%V>9NvaopAC|-Q~t8iX2B&c+bbIHZSy7acF$dqy*K1= z+n(5_t9u(xp57B1$+GWLaEq;l*B0w9W;6B*@v`mxeD2I%k(X^YN@9w8=QPZ<{j`#M zUya0py{FP8Y_|$+w3%9CWS99QZSQXPJA3N$U)dCxf7@$fyU*54MbQ%zxwdAv?XPu<_NGK=+V1l)*sH4Q zyVq=n-`ATI2`iQ-^E8F)jUZ}cPg|X2l#FgLn-s8i2H*Ctc zwONyGd*eI1-Oj^1tv6`5*_u|Iv7T(WXs>US$KFXHoA&bftk^qe-U1t?mD_E6*G=Ee zEY-a?V&wuGiyHqu1`V#Zr&KI#P4=zWo3O%f@9g!TcN>V^vi=r(&UUt?k!`|dKWo;s z`n{RYx9nZ0EnwTNc4V)x;QGA@v6pQAPwcWS`0>xi{^;tx%NK63FyKARM+ml&UD*WLT`&rVW`|bDf5qe=DC>J23fH0)nV=1>wJ9n?n7Q|`)1rfYvaGr zd(ZkGr}uXLW8SCn)^hhusUF+NiQM~S7-sEpNt$k(rsHTkZR)GN-&=V1E`!dPh z)@SV_>pPF9@3p_aZf{2Z`91wYSN9ZFIPBSZZpH4O++BN$-4E^UDP-H{{;+!QtU@un zHTjOV`z%{*xu%@lTg*9mZ-lDIo|A{Z?hP_#w0mQ;b?*i3$Gi8NFWT!->SVLGtACFQ zubHjzvE;q?ik9x>nHOYxOY4j6zjrfiB_8du-LP$nZE|V*leWe0#_eP5I*esE`w70bT z&ED{)-PV5|G3{eW*s%S6{>iS;>(=KYHm{AI?p26+zPC(j&EB}FyY^bK{K=Nxyhtv=hNy%I;K?Y-7B_g%DoR8G@J?jfE?n$|`#x{!eylpFwpn{o}p&gah|9X{_C|d##P_j=&dt_fOlsSHC^n zwm?>F@3L+4Y^@p1Y^0?=@7Z_F4zj6PBY)X_m|#F+xOFb_r7KK+iS5~*oNg~yA7lKw!H#H-8Q?n zN$fq*J!9|k7fbfq&0M&5``ib%r*h`*o%>i|-+ji2z4G4=?-h0UxmQZVWACb-ZF}Av z?$}!(J$G-(Kk+>i9?R{u*HPKqyyY{}iIbqL+d-M0KmHlBGIG@9=Vd3vxcjhhFo0i70w~A+nZGx7YP3Qv^yM-xi zcDn41wklegwsr5$+s;T?X&b;KZ#RDmm$min6E5xs>`>D18t(+tH)6Z&Qwfo$;2pd&Oq{+?%jG)mFpl^xkPJv-f5_ z-(_3yQ_r?1Eq+hdt`mE8_=W5$>Q2}&7*4kRu|s>Wc8SCuhbs!Uz3xA(_x)C}(_eaY zZx%=Y9+`+!dziM%*}lJg-G;+s&YpKA+xN^c3D~nkifxbSjP-ln-!bgH^;p(+i;{}1 zZ^aocVv-f1h~#cTWcn3U}YIkUY+du8@IdGYOivGtGbjtiwW zDy~axzt7xnTaz?%Z{&=nDip{j{3jPBw3bb-3{9y<1i|?G2y3 z+4e~fgWZmjUAyI*Bk6tppkOMD_RD zil__O{9C7Dcg;U$Z&cNny>Gat*}8novYpG=xo7j-wKj{2y7#VLynQdDoBZDWBDZa2 zVz_L@y4`GZ*jL-m|HHL!RpveGTW4?X$vSml?}Fb+Hm}?{>4> zp6umK{$ZQx_`%lf>OmWZ_+_?PiA(pgFwfcRV&b?r;M*jdL$&j4+1IP?SzUK(Z;+Vm z-lVTju*&v^ zt)Y!~?5VvT<$QaR+UD+cGP+^2G+)MUK}!AJSFOf->z9RF8{Ct!{d-u>_G`89-tz`-y$XUfsQ+=0hch$_jr;h*Fn>WRDkBW=vz6se?wzstUY_p$9?wgRrz0XI3)%N=4 z>9%UFCN}5qp4k&!CcbZ(gOuHdKWuv^PEodtKmO7>%i!GJm{a%n7|j*1(<|R;d&{T8 zR<&)RZSuA~))!VxvF&-?w>N9Tb=y>~OM6%XT5V>`{Z8Mca*X^KIkS)$QFVaAt49jSYKu zo^jsmAbZz3*D~IA0Xx^;sqXf+0+Rdo227XV`(2`AuisYT-A23BZQ=`B_FmUau{9BY zyXV6skG&-^HnyKd#O!X*d9tVR)mqyRkDB*t$hh0Q>YTOr-|4-3C(ggTH#BeCUb{m) zdt^8+*ve!y?EO*mXwM>-CAJ54v+cR@e8t`yhrZbe`A*w=pefZ_e9vT?3zw^H7tIj0 z&C%xG8~^s{?tMD@Z8PoX@BN~?+ScG+-d+=PL)(-GT>IAR3fSFAh}ip3fA5}EN!xAf z8YA}J*|WrQ-@GtehTr`*8h_^Pxt1wx_bpP|HZs}Ix^XVE^^#pvZ7UwEw|U6A#&)KF z!oI~bc=x@UIoIZGGOKOy4o;91TpTtyK zS?`;B*SHtiKA6F_*W&#On>m)V_6Sb)w{3Cr+Z)w9*H-1(;k_Cz6?--vzQ1Qf?UTLX z4DW6CuQ;^Zr(b!WiEq$ema0v*pEFhLg5J%wZO~P*J#r;^?*_IK+jog)_kQB9-0R28 zZ|AY#fz9WTki8dQ-L~Chx6ro4=f&Ri)6#Y_o&WYSFTA_=#^mxnOldpzy5~ymVR&%F zmh0LY+q6KPT@yHu@7;57vQ5w3gL^r?1njNU$+el>%W3Cvpl5HmrSQHAn}2&2U6j}t z=&@$cqfa09NO1Dm9$=qi6>xIy-rF-}?LNO*Yg_TKd2a%P$ljw3`}gqX2Jd~Tp@3LVmqyWYO&ZYaAmfews()M`R}5=_6w``KGYYoaX9qdIw!5dc4g+WJuBAn z*a{aN+S~O@#_nB2^{%CJp4z@#7O;0Fd%A5_efwVaWyWRq@7@gC zCsLhi3o z%qrQtOhnw)Ez)K0n$-vQ=qG%&Rd}|4_o;&2dyUle_6np5*i7k*vz6=?u`6)cXB|+d zy+>_MgzZ<(w7s8oL-y)*?6=M2?Y5b?q-d{X-H*M>dmq>)2_CZ5dc$hhbIX12zsMGw zlV)pet%`Q;RWVW7yCrghZNpMU+eF3xd*psG?JbPlx9h?bL7Nw!*X)&0d1Dhb!m#HY;avX!-axJzH{Js3A*@4p)6y>dsC_E-wA?Q!q;XDjBj z&-#Gf*S)EFwtEdeY~AH(%Dzv>e}V0FG<*)KecqP${itF(U5Dq_cngt-On)7 zCSr4_ZTPOKwjth9`=qu!+AGvEWp78vMBBgv$$K><7T7HN^2s`t%hNVXX_1X`Bi~;4 zwzYfCwC~v4!8do$fwjSVB<{%C{yw;MFT+-B*Tb~m-dmT3I+O1QOYMXtg zcW?PmQ(KN>NB3^H#<17I&C7}8wR$|bgw6jtnMmpNc##k+HFz)u^SdiTz~({s6Or`w;hu@*kKXPT+x zUa4ZCz0bO5?e%NYu}xRW+IxUY!&>x!-CizkS(}^A8*N%1JKIhav9%Tb+ittee3z}> z+-G|?^X}c-Q}K3h#!^??FMQ|s-n+_aE7fpiug|U$+h?BDdsXx@Y#TYkZNtK!*v?2a z+|w7BY@_?XanGb~FWdc}_U&a2Yua-l{i4mAyR9}S_inLWF;~aNHd1)sij{%3o@|nK z3#T>hZMe;DlhHKU=Jh1|z47mw_HGPz-#cMR=k7^=XYEaW=k|dd+)+y z%WSJAzT0d6(0lJsmb|?SR-W4XCo9zUYr^Kef6ew<$624YY2v%R=Zf~my#|6Z`&2w4 zZD*u@u#v53vzk0{l8xj<4;!IF)AzD+2ils>Ja239@s^E^eUr_bDuunOT~T}g+}dut za4zRQt}k2L!rmi?B=%apwcGun?vw2T1v9%_ zGv?VI`_p9Gk$q>c-~FAoKbUxI8-MQGyG-|uwGV5C?Zuw{y(xcJ**e^m-TOp-vTeiG z*gcw)EOslujiAS^lr8(^_JRK{ZM!Bp|pP6)gOXv*Oe>m{dI1k?OyIfdkq$e+I=gZvuC|9 z|6Y!l2lmbo{%!5@{}E}u5rhAx`0x5}M+m&=KT zw#zgm_hxzQvo-#;Xzxw!_Pr~^boLcq`?7cS*R6YBl}xn#(^a;2XRF%Yf)@h&mKY1! z-qCrm_rN`&J=~j*+b+H(x9>!Uz`nwzA8ln{i|)dDkM(=6-e}w#A!nyUsP$=KX@~z3(&j?|snHZL^*8qAj0v_uifA+xFydb=n_O5kZwDtwn|l#_V9>rwh=eC-z)m0Vo%VyGq$XYe%nk7@7e2oaE9$mmV0|| zbY0#3guC2!>M{0xOSUev4W2&Dwn{+Kc7f}@y(fK^?6qo}z4!P!1>3Dft$WSiWLUlH z?%g|^d!Y?iee@ouLz8zYY&WqM&JfzS?3%#7FOogBALsJfZIyGdv73BvZ?aI^o|{*W z+ot{VQ7V7sApm(3HE&3nJMCE8|aDeN)%dvuSH4evfqHS_vMzo zXG6sH&Gxm~y>0Dr+p3%Tmd!O*yRQVz+G{bV*mnK=i?-UU_-r@yD%)-jv9oo(d&fqn zcgkLetEsk(i}~za61#1G8H(?1%#PgKa*W;1tI*um%iDbSCr=SO!7svlS3Zs3;}_j) ztN&r|UcD3dZI4ZSxA!yaW?SJWu6sJRJlbo~CTz1W`l#(9ak;%~);8OU8qC<^`M+`R zt(gM0slSx13peuE9cekVSLGbzz7Mjut+Q4n><#$Cw(r!18rx}38}|C|I%ji#q13*= zLXWIP=O5nvC!@$hO9MDdP2G4l`GY*q8z%k$!x zt>%h|y~Z1o*1as8HhUdTecba* zVawi%<9)VQt=`#2@rCWVDcZCr<$L$u$77$4P3A$(y&dy-Y*&3gV!L7A zp1lGq=UC6tUuf&i$+ItWncUth$D8-syz<_g6UMM_=}HdU2jArP$e-icmw7*SkNL9d zz0cIQ?)~uNn9Yu}^0wBEv3r98nrt^+UT>?SzRlL8H`Mx28_V7^llyFLm`mAMSm@eD zS=sM3bGU6i#Xa2CLuj*Y#|E`QeElhnsyS9lb)u93-+476}5X?$YVEAZM_ZCQl@=x)=aY%XsFtgoi@Ryg(+k2@kLU058rX_69|vk z(~?zVTjO}q+VpwfUX8$sd!uu2>|Og$dfx}jFE*<#=k1;RfyJ&uM0TIT!c*2iAL#5o zu*Au>U?Pw03|;fRw)@+6-`E#o+vYvlHdw{OnqkQYn`ajr_BMVF*xS$^Zo6t#74D<3<2AWWVSsOlg`>oSueD+N zHfXV#wd9X2)9&MYUua#l;pH;0bu3cexAAVr9;5iVdjlU;Sr_Zg*^~SF$i+??~T)Jwx=Tx?>%rJXU_^2|2;X&PT58uIBRptQ(>P8^IV%Y^A6j2Z{_!;gs|)m z5}ab|F5a|vaU7T3y&!QrhL~SFHt{drE77~h=0tM1t;r@v+uBccRuk@>-<>6YdhdjF z#e zXMYm1;$OPcMnyr%F2mi=*5QGHjl>K)n-v>1Y%lB!u;rNFxwl44*w%pQs_l{e+iZUE zHtf!kU2Yq@(ZyCPrNed+=N{WLZ+^VPS-62_FQ*@8hcFGAI zn+LgHY!4jnveuYvWLHU%efX8m@0GCTP6SlnC zyMOA&JwLWd@7+_qYLCa~UpC@yOX|12b&D-Z-?Ebw}BrOAdK^pWL`@%Wx)s_j+5-eLe{sdsoi9z31fH zmc3W(Lu{KbGuQ>R@Y^yjF4_H~BHZTnvqYPT^IL57Q}y<`)b#CUygg$NPygP%60>CY z86VNwtMbxp@2ZW0b}GsjY-<%fZ9BS{?6Mh-?=G3$vxnis?HvmomhJsgo@1-F>5;9# z{9U_O7S!&I5>~KfjDBo8Px{{8bUXgQ(|^k$`$OMJbtw2&5!oIISRjQ8m_lm)iKYu z^_nBJ*I@G{Yej?Odk-AHZT(NU)%L+EM!Q!xj_=*YF>SAj_F0>0GV^Q%KEJThJms-> z&ZGN#7w!|^vq^ZN?W{@x>+|fbw!40L?p@7tb?*+J(!H73h;G^=VB@%_fIHLn$q|LUCyE#C z2{|EP+orR7@1B5`y~l+f>=p_2-qZM|X|KQq@jYB0_t}0sxyUx~)+O5&2XE{Zh<$0p z*{ZgORdCzh59ObBuf06qR$5!ejzhxS_DeF0T|&0XUWrd{_FVe$+?L05$=-%H=l2Rd znP;PLbN-%Lo??4T%&zY}C+WV&+1_NY;#w&?_n)G+VKxi*Op;!=*Vt>bt;V{1+chUE zY?CwdZ56UIcDHj+-Xs2T!`=fe3br5K?y|X2^4+E(O5Rq^z+&&DFN|Jn&ZLiy(X|{W;-q|EhH?vLq z8NQd{!wwts9|g7xa&GQf(ABv6tx%-3fE@3E!?#}U{bHrH*Ck`Y0rSHv_DW2jzxTcR z!u?m6IQKnYyZnI5<8=Eh#TomLeSK!vf6di)7vJvvE9AKB^B*tVt0?NYmuqE>jc#nBs7i`=2_3;Y(TTd44 zd-YUpueG@NzNp_i`;Vkw-E-vhlD)rIN$s=tZr``TMquA#uChH}KF04|r#F4C&)Z3R zEH6sgez{_{S0$DE;PWZcd;2?=?Bxn-+Hc18XwSZFd+6t#_+IukR$=>%|xAvq;KG}O? ziuT^OW&-=ZInT2ZxH@ldw(XOBH!hU#P3wtv$Pt^eS8BbZZQ0C=2i`P%+^aqH@}6DG z7Vm4)KW?MO#dAPbl*@M8ZNt6kNh156Gnnt&Y_rH(F*tkQ3rER)>|ZKvrd(sPH@rA! zulwQ&_Og}Xdy|;#cbdL-+`Hr$tF72=Rokimnf9sngzt?qy|p(Z=k(smT>-n61(xhR zJ7L@25IyOA;Tr|^y{TQZ*H-23-j;7lwz~fh@2%>5wRhKoi+fKri0+$e{B5s=pTC2( z7015nqYQS}yC3YWzRIxY+F?Wcjuo8yg5(nHdQCg`Dn%LDDt%Mg?;5jV&*o*<_IxsI zww||*dtW&7ZOm8BeOyjiyB#(k-`jC7#bJgmhi$|*BbyDpH*5os zJ+xi5rORe-R+sH=tIc~A=I*i0C_1%wq9(__jlxs*7E4awyKwD+y;95c_g$P(x3_rT zXZ|&BHboT8N^7*%KYswP4O(F*SI zzPRno-p(Zg`_8Xu-RnDh%l;Q$k8RQd>>cdOwD+c(weMZS%W@$5hxeZ1ESbF;OYhrj z+BMp*_S(6h&1=1l@lG}yzB8h>FI-b?Ego|3eYD)tw&k_cz8%l+?0p|Mb6`S-zM!=%QxHmIFX~X1ihC!M(rkKHPgp`;@J+ z=fr(=+m!cieHpTMfdR|DV-K76a&BweQ>gZ3kNW%Oy`G65_c6^mVY@$pXa7162OFbr zC-?8x7uk1AxpA+X`$v1X-feq#Z#;RRiXqbGdRUA7O?jq$PmEah-7cSaAoEPK!z=eW zyUX@49=I+j>hSBp#l0~+Z2MK-XYHG%Y_RV_v97)9hjV*>pA+8ab$8}oKC{_-W0uU= z`+2(dK2<;7y*Jlw+56jls=eup4|{dvuk0;-Ahq9ef%x7ew}L&p_9-1;XxFx#ad+YV z+on_YO@BLK@1glK_wEQ(*vB|0@<94yi+wJZm-il%X0uU=o3ziaCflYp(!gQqxh;EN ze+=BW-+yBU_+2heDYQrS; ze(ynzZu>|9seO;KR_|5a=CijWV3Xy_na2)Dc#wkUtvYb&g4 z`^^5^-u$XNw)1E6>{F}?-FMCRy^Z@U?Y(6MkM?Q^x$iZ)ZM@%4kI{DJq1*PqB$nI$ znajT~OwY{j*?ObB@z*^-W)x$n8=`~&6H0eg>56W?c>)UoH1_(!|kTPyc^v7NOM%@^C-l)vA`X3B%TjP{v( z&n#MNYxUA@@61h$4}>{N*sI&M9!P()aqn-5cY9X|$y>|j+Z}jy>eb!|k7%1yYczK0 zWEbq`ad>L8;jQ=M&8RT6?+n{$w`!IDzLa&I`$V(T_qX@{-NVoI$v(U& zVDHys0k%B;DSI!kP~R)OZ~NY&iAnn`uRY#7z2ViKZ!FCF{V$!}6Obai_k@tq-sG8@ z`%cHNw9WhOy*Fxij-7Vri#_ssvuylbC+&;p2;LWXxPAX0YstMW-nlkrYxMRQ@GLm6 zHHytXLf7QLjYRoEXUCJLY})Ii-7&ZI5obwb!B4*7n5VHk+=KJ+>Bd7JC-#iQijm7HRuU{;+kS+^fBF{SuoVjIAuvPZ0W`yR2>BR2J?KJK~HEMq76{_36^ zoEkRP882)ntX*OqBoJzA%Kvlkrac#IGq~5eXwGK&8>@j_rwYQ+ADCr z(MB}m*`EB<9Cmxp=)wz5sru-*IR#r!?x?g#glsCL+h)nB&_O1{6>q3x$l8I$s!jmLi5?CI zE#5Xy_}lmXjh<_}+h~Jr+P=CylMUGSi7Z^ar-!wB@5FOIY%gU_*n8zpxb2d^QoB1o z-`Klhulrs(eeQiNJkxBBELgr*C3K!m!W8G-eRodSs%|#g%Xjw2Uf)Pv+tW9jZPRXi zvfV%5V6UG1QCpGq^K7HTHtoIIy1~|Yi;{Io<1U*umtt%)7fRY)jg_%8ir>8V|E)S( z(`Q*3qI18gN;AKxpoc9unapY1;s0Zg<)P3$TLk~@DZg{thNrg4cFHqn+p@c#_A<;gus$6tYx_*8 zcu$4$8e5mE8}{mbU%1zJ-ml%eZQS=d*cI)m3z%oS_Q^LJoq%iBdu96fCjKtn6Z}Zd zE_N-iU5eDgy%XBr*d!#a+q-$+r@ewZ*V{<&J>1hU_lNboQ1;y!`!#GDqTX4pcvN9q zlFYw%YQuk9<@l1lLdBAHLe^Vtt98HcnQ!}b&z1HXTNZ!ey{iPI_SW6eww^KfgpJEj z&OK#J2ljr@x3|r>K7CI{&T`xAJ)8E{b3e0Pxm0wY?p3LM4quMj{>kjHEfW5|Cq-M$ zmLXbV?-L6p+lp*%yNI?-n;Yl%+bru|ym!;@g?klVckQ;8zp=L2R)w-AO_$k{3$EWQ1 z>-}<%!s7+DR}6Y>{$IMjm!09o-WuUpTQ%io+im%gdu(=y?u&cFyI1S5sEuFL58KK< zk$pV#&+M^V{BOsW74P<}$iHsuv;EYb2NwIRvkq(RPFQ)v=0LTYt-wvDeK#{C?PjPh zvSkcixc73-72Aiuqij`6yY@;-ckXHHc)WMPP1d~}Hyrjvu-vtIciwTY%EoE7wQsBT zepsuyH#lL*-WNIdZPJq~_p-g%ZhKwiifwna+}`x8xi%U)wzfWeeS4PLu-Tlxu+o-q zo6^3%+OvCW`VDRO{90~PuDRa!wu{N$KO($)i{2i!`OV9=_p9Z}z0R+v+xnWT?md)a zw72faJKLf}+r3$bmh64p-)P%5U2@-qSUwvy0V!LB?H8;s$bPg5KEt(d)(Ww`$CXR= z^2-oMCwDvyW=CeKVedXSu zj!Cv#t_SZeep9|z^VY<@C+b!9x=%9N6Im#?w}5~BUcUAPd*yBZ?-6<7Y7vdsVem zY&l;|+IvvBXp{U@aVv$@e|U&_4Id#jeQ?%j6v(O!#hJ8X?QSMIfpylngJ_JzIE-*WDov6N|F_o_>~ zzwEuSSLPFo?Tsfl_FVq?)pm!Kkgd;(ioItPe%bKfh}}D1O~m$&h@)+USKQunmPhv9 zD1EiJ|3cK>Q-Q8~7u{6c`?8wHPRMb~UXe+XcKh{P_9i%Q*n4eu|K7{Gt+utyGi+z( zZQ6TSr^Pn?d-C3Ir{CBtw->N8HxaYVUd6h1XY)tflpnc!BmPaa>K{^xSrDd#TO zp1j~^JJaci&8G+RtzVsW-@D{GuU+FmF&iOqS=$a>KHK}375AkC#_T=$q0`nTV%^>; zrI+`#nX=o>x+=3TOMJU+M!b@(ZSJhSlP2@+dvb64-pSWAtP`?5_a5kAvQ?ShwCC*f z$$Jl2neTDU+_(4E67Ic=9&gZjQ4*>_5C&sv+7JzF%-?h)V2vG0M&&Ao@N@3OoW%Vjqs&KG^`4uL zW?Gw^Dcd`D!E;+7_w}}s{<*exrmy$>NbTPHqwD1EAMOwKir1Iy{q&4+&k;4Qy;FS> z_jY&O+}pK>$F6MOy*)n|4(&~Mvi&wks~Ywcd3x;O(qOlp+Ss?Z^Eijy z5hbJ8@CM-YIoEYy~@A_g-MyZ+jtq*6vliv#l=%)a;#UGTHW( zx|rRxm-;r6e&_eT->tLPHEj0YJs)@N6pw1$dx3w)-u7)XZEF}BZ0Cx`*gSDuyT|)s z;hs(Nw(o5W7PH&yzi!WEjwYLnQssNUs@m<%%(32MA>6Y!gOhV#lHgt&@vWVES$^p5 z*~{!?vw=;?=7OF4Ud5;ldl_9N?Ub{2>|MNWxeY_X1FIt%v-avA>E7GYwr%fPlU23? zD< zZ0jd6J8aKdKHiWrx)Vx3<0WtY+;w>im4Kb9<2Oi4{L~Z%$pir$L!zSDG^S zzCiO?ww`L8d(XW6X|w8slAVkUk8Mfaro9$3zt||QYPOJ(-l z)Z(&rn!vU%>XeF27wek6jec!=GF@`^_62I%Y@B~>FQ3=Wy=@i}d(T}_vYJ;Uw)g#% z6MOB&m)lqc-rd`o*l%0n8@yNS)XTkc$9~z|ukW$eIKX53?;zj415pR}?kV4Avw;7W zO<8iEt;q40d-XbB*<8$jZyU93&Yoo&dv?9c3A5SrMR8v}^ZLC-Q`xL%^!M+TEalqw zRk?Q$>rSz~+deI@E#CBOPkdIw-j-dDZSS@k?zwT7dG8th?%mItb8MEWys}w7y>-v@ zyH{;LpR(NZ@u=C}P@7|WLjRZA7%nZ^tHHs%cd6~|JsHv6w&^cU*uIT_zvr#$8rui2 zvuu2yY`3<4Hg8Yv*7JKdv&igC<66GgJ^$q1t-buV{{s{EzKA%nCtZzzgeI0CV zwx6yaw0ZUR<6e#2AX`tLvwNri7ut7I)@IKY>2TX6Qv~;|>2$M^a5migEM&WlWVPg; z`4z1D{^YjVurKAb*`V3CS4g{Q&o{pgTZYZwY%I>n?R7ZMvrl-T=Du>}%{GGVB6}FD zZ(CZYcJ0*;x3GPq_IK|+NyEKoMS5(~p0-;3FjciRUwgy$zrY*Y=F2~9x4ie+o6~z@ zZ~DF$yVjl-+l-gZIGL7Qtch4(f4mF@krRCC|UU(I{>OqjLTGosyQR@Z^O zpQ?9SpL9L6*G$IH);;Xi-f5p$Y%kh2*`~zT+6uj@ve_+sWlw^M)NY^8-}ioZowYYQ z`?jsQgTP+ydC&KTy)&@cxZs;@%IButR`#4We7m}B4_X}DTPLx_R(G$=z6%=jt$SzA zw0*SZuw6YS&e`kCEw@)%hSj=d*3rF|N|m-JmettgZs@Vi*w3+Vm#^dAch?m5 zO5E7K=kB&+HV56-*kpKU*e;o%Wp{z^@$QO$X?wW^jrJ}{4z}HK|L~rm{_8puWw7=HBd2icjbBV)TsRrY(+o)zrPEBv-cA}VtK$2DuL6HHF+{l0Mho~Vbq`_^n= z-g};dd0+3u>wDb}#_bJ^KfC9D-txT)isrVii&7od$5!usTff3qZk6bMQI$=5-!9l{ zrw}T=_j&rly%Q&L+Bc~S9LPM+v2Q`#LfePRZ|xpmZm`jgli54>#sb@y6Tk1VYmVI8 zkSMY{Ys-sWm5e;LCP&QnDIRCt_vrP-y%B5JY`01t*{#f1ysPi;O`A;S^!+&-YxbDT zX543TS#!R^KY-vl|6eZ{ly%f6ujBP`&E9wu*sdh$NM<;HnEA?#2!?%EnFABXTH$tz2e=w z_V)a>v^&W#ZEyAcpL@F(Xxr>f%HJED&9rAyKJ&h1sf>GH35x9txOaA!eHZUO-tx$O zLjCo&RTsVY%v%;}Tg9?)pYr;iea_lFd-)cy?ql+m-fL{UeVAL^Gx8l9>Tj%cESysMxo3y+AjFW;62WqD7%Vlu3Rj)g>hv&P* zUfG}Rd#_aJJLu>|?A`UBeP1WbEL+vX*Y-S*T)21X-YokY;>`P2O=Yq@^x4nO{=sjX znpI}@>gFzcSxcq%)@aw+m!)sCKCZ31FIcjDSEHc#o;6|D_Utmhy4NUa{a%jxO?%!< zNVT>9vvu#g{dW87L+$o;_jT<0EE0D>Xm`Htm&Y9Y#59WbO^m*~N8{!UyO{RLwr>1y z_ec7lwP$k?JaFKCy`7QBT|04?*?Uet?z1l59cx$m`yKL1chf5AM`_vDz?YnU8i_Nuf3^rzZXZ9X@v1qTIO`lD% z>BN22rOWmTni=i8(*Ao-{^!qjzxL1Bt9qwxFY9-%19R5yusPEEX3vXzCi~YgRoMRR z4A>(j!oM$TuZit8BZIw}Hy!sn9BE-xpI%(#zxx!+wQ&7jCSq&o3ebb z;l{7K*?o8HoimqvAD^n)zEzEq`~GHU@3VdCXVYDIZqLlSd-lG4&9FB%?ApGtEob(o zPtdYka4KSN#8<|BXP39wGSpqMv(PI$&~X3S-c4L)_PZGb_ohe-@BgmkVDoFmCc9Gk zqP?xkCi~R-|Ly;%!S7Ht_4D4n+A8}QSxomkY)-dT+jL-`&z2uHdr!^VYo(7C8dw&-%*((#tvoAN-dB05Ax_zq@`1c+78NIjX+UNa!cl!5;-x1ySy`q1Aoz={} zs@yO4HdMdZ-x0{aZ3X{v#=6#DXD_qW@YuKKEUWasJ+=4t%xn_eCu7^Nr}@JwJISvH zZ6cqyTXQ5w?tQ>MYp=}$!@bg)d+d+wNZXVDbMD^ujmrCU-5d6-*gxN{dYb0m0O9p} zb1%s3bLD2*_c29qpW!k;TgTPR``&CkvS;FDj=cwx+V`!E<+XLSklVAX)66O01D|V_>|OnH#_sZo z@AqzKQQ2$vZMMzlF7bV0X54#^#d+^%sS)3M>e#y7U*kmf@!3DKP7d+ib7iOKK3m!S zd#jB-9VRdz+G}uGVUKBdpzXTc(7l)LNAI0H?a1yOA#<#M-Cn#$MI+R{Cy-~azWlGf zn~iqw4OHUX^NB}h??$0xHpwj#`{E)k_qm>2XA`L=wf_P`+5UhNl6y|-ece0p`DdG$ z865k?=A7G`ClzU9AuF>_L~ViXr*4tGTYI&+wMSs(q6^3oP87OzV7i#6|>zPlDYSnWBp!sQOSKjem>lLs^8nz*^p!J87q1F zgyEW|e9^Q>N_s&a8*t_wXh3(S?OZV+rxzFbHrH^}0zbf0Oeq_Twy)Gqt z)lEG12kjp2Y2SKz&%@{12Y9Ed+a;WOZC_Z`V|!}#7dxiJeS5XnG#vP0JICgf1LvME zPd3=UXu4zL|4MAHqL#|u{DdugCvVQSOWxAE*X^3A?R!bZJz}z}?09X@+w+=q?w$3; z+d=lvOq;)kYi**wJ>TzOWxJ1^w|noe+8;KrIkWa1)>b+&sZ4p_T=tB8Hu)_3&YWhp z^?qVx|I3JD-*mg$z3l>x`;LA!-FxRyc=p}o!@;`ip9`oCvITigD#u0s31)$ZMQ zE2Gu^sS>lT*ScGKlcYrU{<_&|lPj3Kw@iGi)p0w!y>3k#_SPlt*z56Q-QN7Uo_kq( zh4<}{IkIs|-%>kuBg-eq5F6`d2SF8Q}-b~gf zw(NbYZTqbI_C!g??2Vh^y_Z2fem6%}!XA;5(|eTJ1onQZzp!&xS>4{+H%Ip#JAY!Y zXT&dC{eQ4{cszGI8n{u+=E%R-W;V0U$qO&{YB8_e z``Eb6cI_^my*u^h+ID9a*v^PiwRKjJwA<4dZ@YZ8g55O3KHF~s>-V-?-eD8v)S%c zm$!2`-L`kj=bL-3KHX;9@UUc$fo_-WKEBg?FHA46nKIYW)>Hq8?S(Tkwk^ucwkvYq z*yJc`?%m#BwU@V3((ZNSCEME8w>Eyub@z6ZvfI?Za@+f536Jd}*C1O{&fB(^qBqzC z+|}OGYpG!OqvVv8ZfDWnr;Ek+id<>5)wh^xV^V*7PtKwpHr29!Y#9<8cF(yRWb2(6!$KOJho@?nnIf|0&8t^PqNr{Htx4cUGZ^Ggx@h+n`O#&`p<>!9Fx{s z^KgjS{?W!QK2cTVKWz3&)B_R2~6*gVL(x!3%|$-QivYxd5SPTE`aMQ6|A_v$wF z_a^Vn`@DAVw-#Yrv$&K!pAPoe9?iOAb3RYRmO;yIcTLRQJ@5V;+dHM?iS4Z@C0k2l zA=|?zs%($D%-X}a`M&K6`K5cl@|W*fGnr?v*{crQ{+%3lS^DpGJ1jeAGo@76cJtw2 zoAb@iwhGR#Y*y_^vHejod#`njmaVz#4{NVASNDefVBEXDX4c-QD!x5BZmajy2zc2B zFs|BDP+MxV#dhA_$*OF&4-&WTwR$jTZ`tOWy{l9|*i>||?fdU9XWNuJdGE>X);6<~ z_U|=N5Vw{6qHK3YK**M1M#zqi>Li=~t$Mbcm)iHfJAKraH!{Fh?}xnI3s;Ffr?_X? zCWpH3i8y@Dwr|s1>j>wry&|bSdul=s?Ahb8%cl72%{>mUuJ3xdP}1(nbHRPRHO+fE zcQow{tt#5PLE^}69$iIS4_{u}>v{_NJeGFZ8dW~BDShj_SNI^mZNuD;dzSfM++EG= zv-fpZi)}*4Y+FW$>3eS^B<%HD^=e~ zZKH6l z&31FAq}_d)t+uf&3U*S{&+Uyb=Cuppez3>zXQM59w2*BS!@|8ShtAoy2(7c_KXP>M zhUbT^?@U;1+nj!D@8nN?wrkg4+2d>AY;*eK-o3FKB=?QU(*eHg+!V6Mu=6~EQz?hM`7ZYy))u!Y`1(+w0oGc*>(x<2^-Twr@hOH zn)bFdownH$*=xJ^_R77tij?f${t~rgkj}FeN$9o_Q#i1|8g)X+Uk<}um*lwZ1sVQ-+V9izZrA?uF4AF>wgoN({W-WkT# zHtcz|yZ4t#*kvsIZWA$)#nwfk$HwRDo;`t<=WJVcP2W9x`mH^?H?rGJza?vz_4|=+ z%7d%B*WYH}*R*=x-l@!|_fAlmV=KnNY_nK%w{5_+r#25teRpTA;j;4yUvFEs<%n%S z(&OC?i3hA)Ynp5Yp0(}q$k}gWG&5yyj#bOv4QF3k>+p8(UE4Rw_MVB#-em_8_ilc$ zZtwQDEB7Al`(~54W!>HdR`J&J%T#T(7M$C&ptH}~&uWRS#+)g8wWikZ-Tu&hZ`$h^ z>x}8EY<9WLvWeKVX0KZH_Prc@LAG`;F6{krQ*3X;u7B1a+`9H&2#K=oY1(8{wv%t) zS`NiMCetU`+!NcfXVG)+eUS}5wo`SQ_g>vPY0p0iIa{MkA$xx@&$K;oHq>@Sx0C;hAWP{CkVFfUG--3-no(M_IiHGwGFZswLR*byLZE~qt>DO z%56R^xMVY>nANWF|CK!+j$t-gwKMk?PW)%v@0?*{u&HU-7_z_YUhV3= z$F_HY^{od2d#$(pw*7PRm#u|p;ojga`}X{Q|7-8%;F7&XV#2$hXwBO5Ct;y&YLMc- zf75vEQj)E0m9!ddPYE;IZe07_c5dzdy(bd{?G9OQw-r9ScklZP3^x2MNA~JAi`q2^ zUbdFWW!oE6#k==<+Je0$0`j&pAHVE*?(Myo$%xB#h5E|9=NKnhJ8V(iEisYDuH{zC z-WvTHM>Y_w2dF2d>_h+*iG6iFJJUA$tZ}^}X}c=j=`5dcSXu{HMM7D_QKfp32`Z z6tQIQdUat3n?vIJrY6s`*S~FPub>fSyYuUpy^8flwoI+O_FMHE_HFu|vTwocSvH5- z-t7rGzIxw_po6w%@!1D@Q#|&v{#OKE`ub0&9TXJpQ-ul|L*73sH4l%V{ z`;z@9+AL}4wUQ2>w5ROfa z*qQL!IBYK3XY+K6&DQVk2Yys5*_zE!u(=Q`Xn)nldH?A+;eE@Vdh9=|;CSG;(yKkc z3_SLn>l593`tj*~Ut`bMeD3Jq%VP0oulbhiHbRjpd)0JT?UhshwdYya%sr3iIoOH> zm+YItreXVH<9+*}x$b)kndSE0&DdzKm?*Yy{f_s0Irnw#dzkaZR+B^8p|$s$O(VmG zy}XCd?J?z8yXWCz8{7B)jrQrZEZg(z{3Kg;o(Oy0iA(lO{UWyii{&*diy1mL+csa@ zvsP&LUX}O1t*l*n_JwH3+dMzsy7%#Vmwmq0k-NV|=Gr{k-)lYG+QPj?#?^aO z{X=b5CZ6A`r7E^B?~VGtb59KSu`cP{EA5`WH%{xu{$CrT_euPg*zLE}b8r2& zSsuuBowoPY$H#UDy0!Oxx;$Yov+UsmhD(p_efFkd=cid$Z0@UH*xN97|Neavv-j%H zm)KXLq_sEg^yb|M~?R^qie0JOJ9k#u$sb#CiS7Z0b=J4Lfh7o(`nndiKBFboUg>~BAi#Lw# zTl!hp#>z@^AM-VZ{gPJ%?W)Rd?Ri(;y;tDUBHOji$M@Sb-`ndbt+c0V=Ip(BTl4lL z82;Gv_MrUUl;Dfj3)YwIsff(C;qfrs7x?V7ZS^&eeVZ1v+i1L6y?^_XS9?QVOtNCW z(z*X|{^LDAUj^E&Jac59U2)PLiA~w|9Z5y|=S(uP?J456V?8r>Pk-yXJu90t_H&CY z*uO%Cc~9o8B8MA}uWVjV@Y#FR%hUcq#nrt{HfQ%pCrRx4e^Y($8?jycf|6PG9oqS1 zZ+QP}+klLw-CRrg_eu%M?2VW_Y2Ve<*1d8j^Y?|guiv8^almfcf~>te8T@P&e5daZ zIc#Jb&_92-1m`~68-K6wJ=~nPPoP_SztWOpy9yiG_8!~)-R36)!+{kH7WM%KANIf7 z^l@+K3a$fx^cih$USrw!<>#6G?T6bBNKb6qTUIi`mPaUTZ_#znRuXw!b%XL~aCrI%0NyPxme-XBvL zZEsZ6?Dd<-y{D1qldZmz{660gr|d)u|L)zhUtoW*T*2NNmr^?=s~-En_(gjK?35f_ zGY;&PYIQo$U7uvTS#{U`dC?nfs@3}Uadg@4ce-(4|H+?B`xqPF+Vxn*+fUfHcW=-7 z!2OFG8}=z}S-vNU?X-Q@E$+Q8yI<@*_L_h1{|WlGdiJdQ)wE*wc`WSM>!)&JZ+*v6 z8}@9WeJhuJ-@9FwSxD^(q=)^hBXYI?dS;Y`r}H1&hl&XdyY zU;bEoAcN(z-DT?~`=^yJvXQxEV{5ZN$7V%5yWJhthJDRfFYmp(ee>S7N6faSZ=c&7 zSvYy`R@2X57m8vciZ+cvQFOH5Y)BLW?6{srNfqc z^Dms-`_FxrZJqpF+v7&!`-8u~*xT^TYxi%yQrk5$-nO5V)AxGEu@Bu( zcDMH$neN>yF@4Q`%^0bD|8=JB^)LUnSN+byy@%s<_r{x<*%~M-?Oo`w($>uH(Ej5) zZS6DrwmB5szOeh?G3k9S+HJN+0`KgLe_^yY-FS!XE35N1kAs%&`|8H9Z(9ttUm3xjYk=vUv|JL4AiP(J%wXHUvj6(P7xOLjI z>(92;Aeb+Ex)MrzTyuIc4j8i_GiC1zCSW_k^POCuKSYL z%kS^JTxSzfXSBaxNp<(+BNz7sYn|GkSG;cDrb7?+O8?zu+s9Y8@Axb!hb3BDtPcyn z-`i0qxNouMV+YfHg8TnBUD)e8{o($F)r)QYQ|kA=6jE`B4b9xwy1QYoO&8<7&<3}C zlGP9PUu538Tm9-ndx1+$yO*D^+-sntVz+Qr%05BCXM3l+9oYXnu4msQ4Vk@9t~lGy zuG?;-;=a*VR#*g&TMH+(y=$bL_wAbb&gRQc)_v>G zZ?L(ik!YI}B5Lb#P1mN0k!kPY{~mkGkM-~A`o3)6{NjdvZu-u9w_VrR$6!}(YyC}V zFB4yx?ZX%5d*}S@x8>OKWtU}#^R!HM+n>D1rq|13uZ6JW-q{ly zZROK7_qx1Pw2d!L-@8v-!S1qN-rf%-A8aeVt87bo*!FIFu*25W`oE1$it*ml`}Azr zCm!098=t!OoX`BdS2Xl&c1YXp-Qag`k45m5z3iEn_bk#qu=j?`+)cg!X#J zGwi9?+^{FEM`^F4uj;;892;%FTmH1o3ADGJ5R^`5%`=ztd-<-k*?yGSxhG8g$lm4y+L2Y^c+$PQ<(j+g$?zMtX*yDS8($__P5Y9y zx8-^0-X5cydzurbSgvK>Y?Cd~YQw>-Y{Pl|&E8K|Yiw_4h1x{eaqhdkU&_Yf#G}1u z(kAY8|NdvU^&9QIO;?%sC9VFqXZxC~dzQpau&uhbz~%)n&mM=Rv#i@^^6Wd+uf5lm zS9dSRoEqB(hADeqpIl+qx5BY#?-HA7w%pIp z?iF|;Z2K!KS zi>iBV-DFSiomf9}cgy6-dl!Tpvp)ZOI+6Sg;wP)|GUVUZHm(P1_4(%kn)r8?M;y zNd95P7;n1wpEifxi<+x8eqWB;%2jOJb4J(9_GMd(?E;A_yO&*`Yb(H_w6`Ou%2xQ= z%)KUjXLtGPh}q8X;kK(&Uu4_azGHWTREG7!KU??y*ScbLJ5X%To((>>vnH_a6IPe8 z{(bz1wMF&my(^yk?K$vUdf$rZLwjG`f4N8e!h7r5hJ`kzQapQ?h4$~2^y0Vsu~=a5 zQz{d$MfuH;+So;dHxwi$c8_nc^XZu8Zh!_Gjx!scw2r|tGF zGi~GJr|rpj&$-XXsN7a!+uc30u20@OGofWK*M|n%g5Asa{PU69_rY=N-dj5k*~+=C z*sE}Tx%Kqxdu?(V-r0Ko7TUXJ-aH$hkFmCho2b{|k8Syi-=%CN(Xw zHD#Y^`{B%go1$AsOBj%>G?sb+V*vBw!Lu6a_>VKo_#!u4z{M>pV(enaKzT3N^^O0)|F5qDOOVQ=YH25s|gq+x36a-rz>9y;HYe z-m`KRuT9K55nGn~T6?$tTE6#`vxDt{Lyp#7-V=9UR%F;`In!!yywB9V*5#-6&iSNZ zn^LgPR_*D$z5liy-jg7lVf)~m@ot9cy?Yllez(045U}?;1MdO}&3<@5`ck+XkEcyN-3P+WSV)-S$HDkTWwTW+|Er(R|-hz51o1><|drdDp@4X#*cTdE@ zg?lR3>)9-{WwKqOkYcOzN!d0_T;9&XDP?yB>o1$?evdu;Q;ym+6i?Wzymx~2@*LK^ zH!aWadGEf|_Cdytz2|-`vHg5)mraa!0VQlRklA`*z9(3&bKX$k=j>Z!)?Pk*U|DoDdS#;V?z6u{*biu?~=AvS$cS{O z`9`XHUrT@3BOvW$BiX!X?;D~0dsQCH+8cAGWshG)uWjd{3wv*Gn7emk<-NTgv!rdN z9bddxZpMxs1;-k83m@0p^VXPi@8d3|eHy%swn4&M_D(;s%ht1O#@>R8o7QV5Y}~8E zcxm^q7u@?C7jxLnS;u6z$U)K0V3we5@m+yE8{BqUKk^XSx3be@&ySGOy&cY(whVjN z_sOZ0?_KdvVz1NluswwJmK25|K7~EwP{$sCv|`K-V^E~d*_S3wryEBX;1atPkU0%Wbd`8n!T6p z+6vq4ZB4cc&v))EIv}~X#ZJn$Zx`!cH@0QA8#GT?A9(g?&kLr5dm|2RwTW5#XU_vp z&)pBIyll>|x@PNqWai#^6{~Cy}FZC?v-d_w*9}yyQU?aKz(H)3BFsXUpFFqWrzTe@wCM_q({qa6!P{cimt2rk>fhw}EHR z-u8`?Y%R`y+S~j2^j`njtoszV{@){TtKGV7%agqUj~Vt!O`dAI%uQtP9DmQfZ`Zro z-dwV6?@95VJ>^B~_qX} zg}uFjhxbOCEZw`oYm;rq2Q%BtvQuo7_MO{vM>)av#FUP`1y_&m;gs94cb4@;+nLi7 z_s-aQch~DLNA~6wy6lbUVA>Zkz0KxA*$P{UgEF?Wb^h#Sy3%E9H*3;fvBjrt%_151 z#ze^My>_F^_SRV`yOIYPwx(;_ZNHc=-sAbGaaT`LpzRi$|9gB|dF}W=73}5eUupZ{ z!h0)4uQRp}mO9v8ThL+4!M)1X*3NG4qWO#VrZC^$<7@udHnq-WZ&v;in`QHN+CFjY zv+caWU?Zmzv1jA%Hd`Zin>`a4n{4|lV)nKQAK&AYwZvAA<<=f;yXCgmucq&P;ICrW zG}&}-bY1n{*h6#n-Za$Os~P{$cG>pHwvTL^_C{XSh@Sujmvv78+dGmcb&3z2-e<{9l>h5P2=tE+Pw$& zZs=TPeP^$*tw!aey(aDV_gHT`wYMj2>z*0B$M&AN^JouGlbo%C{AR27NhfSSR~gs} zeV=C=aB+&Y#q;fZr!ckbRcJb}yJ2$v-s_QewrNui?b+w$zc<>(b+2V@!UtRT{$y|1TXjld?*rA9)&{bi zwi|Y>u;w^aYIC{ileO?8Q(OH|kG;!Up4x6Ktg&sHx@hlrsj@u>4E6T@pZjX>hsM6W zo0X#WykXyB^WiM3O#pko?TP)ldo_ZN*ruPkX!F-RbWeLN^S)^t`fYDE$nMi~wBGyt zfZ85mUp;FFr8ic0`bGB|FDtM;)K_C`F#E)w2bP;{MX%ZJop^)Cmh1Z!+tVFwdyg}% zv^D)PXZJc4MZ1lUF58&i;oZmoe)(SGWn1@7R93M&q}Xe_FG0y}%eCcut*Tk~8voO^ znY`|}ZH6iP-o~$s_DWW_?wxU6&E}kL$hPjQ1c7*NoBR6b0 z9u@9=I!WKAXZ_wi4tI5T-)a@H`;ilF+xLI9ZNXXTy-GnbHa>dS_B;{XvuEFF3EQ>d zTlccnGVS#`D7Wuc=u8{Mw7%V6zxeOD{!C!shBKvm{n>BYzV6T3D`L!HJNdx5y&E!K zSev&T+I!2JW#88(*}Xj%C+&SX$=Q1G64|{)Ym#k0yU6YH=1{h?`MYa(s5Hmk{ZI7v zE?87xyYs}kJskZLY(2MF?loDNY!l>{yH~Gl;@$wAxV=e6zI#8t)ZDu{`=;$#wS{{c zMCz?gdRFc2e5$z5<5t8Ti9!ZDm!BH8LX91^I`_}+u`{2x$Ie~KjzNiW&oi@|*4H(= z_Rdre+#Aj#Z}*k!oOPPi8ryT{8TL9V?z3emHnNHTe93&T=>5GXDzo-1%u=(ho#(Rm zg5b2hvu~{3!~B8Au4Qkp?LRxly{fA`t(|uX>`6Gly^rt3iair%sM;#6ZLtkIFwN%X zxkY;$J}TJ#-I}>~POgXT28~3Uia$JicU)_I$a@(m}rtOgkm9`BpNwSp`{cW3`dS|bGRnJ~;pVfPA{HWS% zedVt0k11`o8Nny^p0|E$d*i*EjgDFA-UDHIyLZjsZX0f~$VUIC(B7uWRkj&#xUCsB z%(oQym~Shx;=-PQp4qmUxBYBRobBFwpl8nB6Dy0Xc|{l4eC9Z@cS>UC-Zk$g+2s74 zzt<~Lb+4}Yti4BnUfT12UCrKEsdx8gE_$;!UvJJ{hsHBD_1eq#e*ALWMv8s%-ZkPu zwk~_(Y@hln@0;v>+2;T4{ypm3Gi*I}n(y6ui*Zkm{rVzI7e8 zB~i<53;dM#U9ooFyKD6p+s^en_qL_4v0WRmXYUllraj-9llJ`5=Ge>ncivvWe!Wn*=SSc_>m9N#wsTHB+jA~a zbZ?E~>^&{LW_!ch3vJCZHW({Zo*=hp%ak?UnikdrGv|?VWM+g-y!5 z`+HX};wDHDbMBk3=Ct>H)0w>nXY_0zp6jv6X>GA}V3D&e zJayDYan@B^k3JLIqD7N!8#hVrog|&K_r=-gdm5Lw?Oh_UY;Seo(zY3ea(l`i9o%a?wP|n4az5+bT$MH*??v}r2=2B$xo+Q{ z0|ra>v=mC)mQ7%`dC@k}CVBg(J#o)FZEh{vX>~zQ!?uS*+SWu;(Qe=E`+M>p>FiBw z{<-(d3=v!LmQQUW`xLyXdu&&D~QUY%hJdV#QG* zXCuS0#MWp**WQM8skRBOUw1DI`n&f*^o_mZ@&0>0DEI8Sr6ptc^y>b-fu4+e-?P}- zNQdd{jZqV|-LdVj%>pO2y$TlcHVfv&?af~7w%51(+1|8;k8R37RPT8?`ZjN)`^&kHZ_y3w3Edht{HeOOk2Uw$8Yf-f9h?|qn=K)_PdR`0-ddUXy{-0>_kMl4 zY)@QukM)(@F59S>X?wf>9o(zevvco*ZR|GI%&+#m$lGH3{AGsiqLmkIo~m`(M2Xed zG+SP=StFKZtGJB8#!Pg%t+c!6-v3;gd+aa$-uo_A*X~}z!M*b5zV3No?QX*`_vG%@ zUo&hIeBRrBJ=d#&_J*Und-qrr`pRK&-X&aR# z2lg(p+qn1PrN_1(uidiF3Gdn?%*3(pE#q^WB~c6aa?L%vSA6>Wy=@w+ZKXn__WrWC zv*)9-sa?D;lih|?=6$z0qHWit3EJ-1e8I-r&&ry?dhedfJx{Hr6uNB>*9+`B;i|ny zroV6RB9C|06D^MJEjg@c`+?up)B(+Z;VXNqS>^0D&Um`_yxhgTdD=7gsx7^~ch$y?wpOd>+t@uU z+H1FamF=T8uD$O~*Y8c=chSaAK5p;BJA8ZdrT6X4-l@MgZ{IVU{jTb^+v2zF-MMVt z-rvV2?=j7OxYuyM<6g}_2lwclk+OCC_RThJ#TT2Tqcis^fB3OC!Xs&Kq5PD+4lyw{ zHY&^a7JV__dpOU>dgbIvdw;Wa?w#pqWE)Y*X0zUQ%3k9+Wj1UI5BDwz{BC{T$lOjy z{^Q>L6Pj!{pAxW>dA-b5^sMe)Z=GE>6`McUOzn=do&NK{?z7hg_G;YSv&Y4C{~pGb zZ2Q!&U)u_n3?N#$LHfn7b z_ncoLYP00QG@Hn#4BMbXEqj;MP1tL)_U&%Ty;e4AYAL%frx@+EN>j0INVD79@X*e- z_}cuv-JP|z4qg_vHg(K1_J6nsT zOna|r%Gx%ao^5+zxy&A+`8#dq-EZ03aqgYXbB_aiFFKvw-LKWTS5K9BZ?R~e?Xg3h zdxe;FZQ^d9+#8j7V{g*JMSH6v#P)27i?gxMOxU|c>74E91+jZ4SU1_YPJgo3Gq=~e zWA{m0$A1_0{!o0mhjU5l-ty=n^& z-TQEJm#x~3^?OUZ?(CUX_-F6beox!~@A&K{-4C#KUNUV@ufzh|wBrRfTV|Ns9!Orl zS81AnoyF<>d+qGl?8G^a?7d`kY;Qy``#wPifqfr3XYHO=y>{3CE>DqhW+sEuX{qDEjg`J+emmb@^w@+Vezh~YW8#ft;eIe1y_J#W$-1qbDQt_U-$iRT4v8%$LnxIMsx4Wb-VXQ_uB5|DcrEXKzY{QEtc!{ z-Z&w@Z+3RmzWqAhHolHAd*xE)Z5Jfj?OFAgV{c=l(O$E|B6}roc-b5b-n}>M&Z0eX zrmXvy{^H%2Wgfe?%DQ#0g1hzJ)}9Y`DX%T|NrcSWD`9)g<_)LG{%-E`dkn8$+H>pS zeA~wwbN8%##BPCV_mz=%lN_f95_l^B~ZU6J`Tljm0?em|G`~D|9 z*>lKl=l+H^ro93$_-$F2Chb2Uad5Bg1-^YRk0kDk_^Z6{&yDx{7Hqz{r?%tnUL~{E zy>tF9-}_Q+%iiX5toxS#K5DZjqsgXg#ul5snI~ABW~|+Rav6*5<@RU$9E#5EN=Z(3FzffUZ-2qG zPj2;rz0RyG`(|ypy;nO$X|Hy+x}A0Elf5@4l<(D9|9#KSl{;+w-skVFp0~p8arc3} z+&RsAwo3}ze+mD&H_2q}ehJMjdwLz)_9hgn+dn=rac`l}qrJzH>-Lxn^6y(Kw_$Ix z&)dB%j^g`H*xt4Izw^l6t%?iwOnSn(ufjKLpY$J}y#)uR+bix~v-i8Fi*4{U#eJ&t z+IK~$XWGsEF=6+*4N3>(el6d3^a=C+Wy@s_OwT@HzjXT1y)&d%?cvA@+qc<%;r_~k zrah~*?(P3rFSqZ7q36EbPrvue&b(%w%YSe0m8}ZNS``jk+?K5%PzPIwj2J7SBobC4?leb@G_i*35Xo-CX z?6UWtD0HwfxVvqi^gV(7H3g{-(kIMsZA6d#+Z%Md-zKSR+McTi z*6n3cRo%Vyq}9HdrPucCzPM;L%UFESBDH6673Txh*;P_+TT=kd(94AigT{`cZ{W=FO zJG+mKcDC(O`#3vxSx=Lz-DC58`{d7tlr&qw{HKr zIL3YHmR$P|1P0iZ=`q;ePv5rp;w%-1@|Nj)O^?+cxP5oczSVq&`{pcJy7w9LbQ{~w zo%{B?_3iV?Fxuy-cVX|<_PP5Wb=TP1*Wa=~({*r9u(icLy;~yt6WmqyR&Q+Cm$Pk$ zT|;~Feoxs?`_wl5+tWL*!?yOa&CWHJpZE4P@b3@$SGo6Zzt&#$f3mjxwOTu5E^FAX zTT-@Xn<$s9o>SZ21#4gI-8i{z|AeJ8_oht0zDGx2Vh>Ac`2Gr(yL&mV+S^*zoZtI& zX0dJi@=5z5YlQY`NbcQti+A;IXPftXn72>gr}oTqPiU#G?G-PDea~jT-0L!F`+lo6 zj(hhgaND|V=G=E-%KJU`>XiiO7a{H-!tC{xiFP*kw|I|%4_bzW) zv9~Bo>Oh4_>)uBX-Ng+ zyYcMCURR&ey)&3(q zS@uf(EPKDVT(s%vkFs5@vwNSpcDZ%`g^4zE{b%gGxop>7w#XTKtM&iw&13J`weRhg zz3D6Y_lwV4xL>4w%|2f#r+r!BE_R2K^mg}7n7Dt_-nDyW*9q=DCD3oehvf>nEOL(u#Kxs(3vty!A4r=r=?=0C=U>%04TCho1-wrg+CpRRq*;+OaGr3&qjc8+oipW2m!d)xm!v335%V9UVt%x1yaleT*=8|}T{r@!+qdwsqyv7J5P|IW2B$M#w*f4_I{G>yIG$B)~3 zC`H;dMNZqh;ftlMv5vr=S+1gc-%Pz@yWjVL?fo^uyZy{h?!6Lhuy@KW7u$yn6Zif& z@p!j#hn{Vj#cEq7xpg*o&%E4g;5ucG&soWRh0YxNQUg}+Rg1p5_n8IfKKY3k_8Lk2 zv6)dRwr^RS(cXN^^1W~T&)Z5=blI$w4%)jz&dYX5+LFD6MooLZt531Xn!9w*0Zm2Q z8w>XA4O(ivJ3zb8R)fLZmX){B<^bC`~TlF#4vDzd2BG9~)$u@>27TbDE2 zc6I1W+r2)LcCD7*_Fmi;wb#h$wC(YX zuT4yum~B92tgXy6=iLV?W%lJPPO;U{%*Nxj+an|IPS;F#s! z8*761NSr!k^IVg4U)c@ueZ2d=?G@R$XHS{dO`8d)6!z-WgxGeg?b>S>p>Dfqis@dy zvh{m+i_F-o_*`^fun^Ne<0D7*-uSTC_N4OlJ!Wogdl_2f>_Vyq_Pq)9+pFSC}9Sif|S=8T5DeXkq#a<{12O+PqwZ{58uwz&t+ z?{3Ijvdd|?{$9;=`@Q)mS@-?pooU;+Rb)@)H0`|seavOm}*vo%mwe_qHC0md6LN;5agzfe&k=n1(KZaB&3hM5%(C^*GP2#!Cbw_y&8EFee@(Hu{G-b{#*>*;~)qyqD+l1l#L7zU+-L3=CO2h3c>FJrL8d_e0dr-ETOb+q`&ide55VrF$8?CHBY{ z7VULvli#DlG{-h)=V6;`eH?q!)-~Ji?clUy3Yxt)STe*moK;oeOKYX*C(6NT4HhO-bmk|Jp~qFw#{5Ady@};-+Swd zjNL8E$GfxGMfYx7>br;S=^WcXzfbM?Qa5pLUJvu$?+$HyZ6`?ChBa2~mHN?Svo(O% zPTSYUM(=;iUc0pYHcQ(*ZGXMlz4uOrn{CR{kd>3b2|?Gkrw9KNl$QE~OydqmyQ);}k0?;ES8JqJ1; zTNN)^W&5<9ai53f*}c4PME3=>`tGTJs&4!DRqXCd;zD~G&h%TQWv$#DQowEdc0H?Y zO1qZrtc^W3UICo8jK>7_Sg&x|doGE|RxtLJ&Cc7$_nr!zY`NfYgRQy!`@L;!v-Xx{ zNblWtKztvs?wP$MFRN|0Ft_jasb9P2($C4ZP17Z9)gLUgwhfBiqpqR9_p~R!t-a@K zoBB7e_rxq&W2;uXVeivQ@qKeED)!7WTWI@~>%?BMw+(xrTwh{4!{5S&yK<%N^UwNw z8?3+VUE`l-n~}T7)<1Q@98x?!CJ>Ryt?`>0iwbx!@!roSg zdwY%ca_wW!D&D*2=dL{~ge~?i`0ZosW4dE6-;e3LcjT#AtK~njwT^As+x|Ui_qmCu z_J%Ii-_vkW$XX~?aqq5M8MYs+G;F@eb=$5z{djNBu7!KP&C<1haf{8)Go5?6{)z38pB`lU?qk8;jg?Ba4KpqFFce+geZ76VjbwfQ z-i-Isb`q7nHVF^P_b7a?-gDu1iEXam!acTbO#8amp4_8hzj|-NCKsD@gDtkwU+?Y} z_KUJzvTD9drHfzlP?49AianB1QH{0V@ z_x4ujN9{ea+rYM&VW#b0mhim`qL15tc+YINV!ou^#TT!4n@tPb?JNCl_XdgEwp&AX z?QODKXnXf?y{+=AQ@elh@a}rvKV{Fl?bB>!61eRgf=qTRX6Eb_)>gNj^8VIdxt6Va z{i}laN~>D$^*4XGS74%wtwhiHy+3lzZSz%RZMHNovU&0B)6xB_bN%`?_IHJy6p{? z`aPP9nZd(-oj?DSlRJC>I}U$N0@u|e$Eov z`>Eyl-gOJo_g+_{KD%4((ePP?ByHwri%RBvoD8ZpKObyor0%`4U;(AzUDeP+v5WNZ4UYU-1A!b z=$;Q@ZMJt7JKE}>JGW=jS6RC`n@-xYR2A)E=MCG_?I^LYMX1^K{PM%L2fN$$nEUbV zd$H(*?RU-zd(UL`+U{B+Z^xL-ZCB*J(&oXs&9>8)y|O+l-(kD%`i{NwcFlWJF74m@ z{Ib%%?dJdYgg0KZ<>7j?Y$vqY%`-*!)B&%olX7q_cnpNi}w20 z$nV|dueV#jm1!T31;d`hb46_Xc}(`$39Pl1e%819)-?&c7+v4J59Ju`o_6=`+4V-t zcE3vc9Hpv-iy0yOX(Pud4sHy(t%z_8w@MwAa{h|K4r34126+uIz$iMtxhx@?U!{?=iLI5IkwiVB>3LEO>X1>ZHYc=iGd4Yb5Nt*UIa$%@vUedvCsM zvfT_hQ0wI<`(-i=Qd?7inP-(~}^@V>PTrASI;at~k4xOK5yJ+sjy-xcX_WpSLdoRf z-ff#vG0#S8;qSd#E)_PbN)z@9+s?O1sqNUqdQQSNR$5?Rg3vPCO3{h7yVKX~DfM96 zE1%S0tvYG<-j>C8_iC44*c&K0+qOAIYM*Hg7GzZTZ9ko6ml~ZCxFA@0DA3d3(d1 z%ezi{&)&=BylSuQg|xjh7T?<4qu8})fkL9~HRsU1CG&f2=2o!oOS6~UtLipm?+Zpz zo6WQK>~&E+XRErXdv8|T3)`M=vu&4M_t~r8ec0OW@dcaW2QoIZc0IK@^nd2wnsws) znkLQN`&%+>Z}`h;HZ_I2Y!bdm?VBDw-)0qa)82mnXM2szHrg7TSiif%XS;3dJ6{{M zBhzdh(=_%P9*woJv1+hwh-}&2mGgCP@pSop-Fs^HOljuayVNm!ZwupE+XeqC_wEX; z-@BmLf3N{~TMrpTc`< z-x%$l68d*<&>6OUEhm@nz2JRy@4VhAdq4Ac*_`QpzT4in(bi;>jqM!vKHIy0lWkqH zx@?w*+}iWbJl^)?LZ-cI(gkd{I6byqc|*r0TvK+h><_=a6D4%_tewiT_sYe2wvUR% zY#)8@-^);&wnwN{anGqw^KCWeG}-L_DQ7F_H*IfLw6g6{>AyBiN%O5|bE)iow?V}2 z=ez8^bqoyqb~SYF`M2o$-g>zcwoxg)whl=~w$B0-_Ig~&!IXI1mW()M)9 zPTRox_Pu(GIQK1{*0z_)fA3z8UHP^}>kjS>eS6Zj@ZiL~ihJ5@L@!3zycO!Q)r^0> z*CDFb=4jk=TO}zbJIRR;Y)=2_*vqobz&2Gk$7ZF@wY?waPPI8wd}Z(Eez|>Vt!HeL zzm)H_^1!{78m%hJXb13eJ?bi;WeaRe`Y~?MV?3p3QvhV8ZINK-wNwy`1 z1$!54x?^)})nwb8XZQ9h79{TNS2|()@KycZFT&UME_{|}Yp}N0wqd>e-psa!J0{`O54ZqNOG@W z)Xcr%9Km}H*IMq~GJV!w_fXZnCiPaf^;XaJ+Ft#+?{n|mJtC5ZHc`*4Y?8N0?9*=4 z*_X$7XS>a#?>3FrNA~84-`}gDyVq{Qmvwt}Y{PB4qv!5vm=v|!j45&NxhpgF{%CC5 z`|Fh1-l}W7`|7+J_9WCSwY_-SZ!d!h>mHYNi}tqWuCtpxOJ?ue6U}>Prv&buP`GCA z1^JV9U;P^P>S{>XvpF`|F4mE@%ky>H$54D>FSmr$K9iJf*2k(fY|EQ3?EQO|-};Q7 zsCDgS6I;{!tb3CCrT3iAQ?OY&=l+*wrLByZuR9)h^@A;n*IAIyS=-=PT70GDc|O5klmieRmb*53w^RH zj=!+S_vuoqdwoY7ma<32n-n}<6 zBlpCKA! z80!=4rs_oQ-E8b<`$Oh}?edcecK^Tr-y1!D=iUhleb$kaR_(Rak=i$H+vmLvVte;K z2sppn$M4hLrOO=bSdJasYc%cA?i2SEZ9}?+Z1Wl4?^R`0*=tw#+III;rhWDk1@?VB zpISY_Hz;88+z~jrTAFvhGzE3*Wau(thuR<*NG}_HfzW-kZD6lUdxx+-S|- zGpYSyTs<&UbUS(`yL;EyGP(}s%@;e+n%HQ&+c2s_;&Bl1YKLJ;!k^x8`v}s%N7dI8y_Fn(6uhE%x-wh)R+XtuD*c@-Vxrd))qxHlh zE?ZvC)BCh?|Lm1D(An4iS<>2f&D*^@4j1h;`zvnKc=Y&Q+bdanwAsU*Rf^OzRrcS_vV>ivVI=LxbG{=_q}O%j@dHH_3h0#tz+wWW%k~H?^kxuUbt>w zXh-4R=*DF>7RwcEW47JiRUwhE@9JH~eadDR?bx>p?6Y8F*ekrX*Dj-7cwequx6PRx zu6^w;Ec+_t-S+By3)y?-0LQ*%oAhjF%;n!#61Lhd%S7FV`Jl$Wx3|o8oeH(zb86D` zy;^@??&Y7geebG!vu$d{H}093{=~*o%6jj$eUogR6`S`2{+?u`v47ca(}FjiTePqAsp_7s zUuyQ%Y?HRVGskLg=H8!sDpPrF&tK8r+a1QWPd)Yg-aV3%c9-PN?F|#XY`rF~b#Juf z!@X_cYwY~o&h4viXW4hb=84VJ>5}`tNW9#e{_p-ih3b=gRW$DIEtu45Vkdy+OS+ADqZy!UxO3mdOHXVs@pjuqx$E0@{SvZ& z`M=v{)~3~VJ0kDzP0oqiJNxucJ1dp5cIVSIZH<23*lSSy%cl9zs(lw{E!->jxM#0Z zXYStjTR!i5ef-6~BfUrVy88XJtvoqtuctE4Zu^cF+mvW$+Y6mC`%ao4+`D3jo$cOf ztM*+}-nv)o+*#YBe|B3pN@?wVdwYuA$*NhlE0&4aR`GJ$sj^Podt$1+?Xj~}d;jUk z?_1&U(5B>4lHH-?roBnhy|yz9n(daPE!(?IL~SppY{cG_y?px&9w*xt3ft}3D=~L3 zf0y7sfzEw4U02lhEJ@z7SLTJd?FT)_J>tpgb_-T~w0UZ7y|?%MwLK*V7TfOG(PtB9 z!C))4Y5HFAAJKdLH>BCBIkN3rTKs))q|>y$ueQvzwfUlK8$C14hM{)S-nGkx?KUX0 z+dN`tuzS~}u(xk!yX~6=+dj+o5S|`8F-|cYe*WRM#i*3UG=GeSr zGqcSMEwGM@P}}?BV$PnXTH(Fw_c``8Tv%i^=kHuw`Ob%X0s^+}+0whvwrH8E?c>C$ zdtM~Zwe3*Tuw87$xo_elew)4q{ylyC%Wbu7#O!X=ncJ;y=H6!=xpuGltZlXzIcC^u ztzENM;AXb1gQ>~hn(4Fl);Y}Gb83Cwp3wcmwn;OZZCzqD_I^ltzITU5-`+WA7VeFZ zdAQf3-Q0$2<;A_pSKIcO#3fn3R!QBfx+&4-GL!e-`!~J!zI!UWC-vdS-HZ$^d$-^D zYHhym%btcUtF4#m-PqedBWkab5A&X`@aR1@cMt9PGKbCf+q0UzA9pbBV`M*TbK%`~ z+X|I58`0uTwyJA(?OkVOu~#q1+V;bZ54*iT&Doo_cgfy8f*!W2pXctaTM)L_%!$p` zq4SH)^W@jo+1su5{uMa2H^@ME@2ba>_k5nlw(rh@8#diRy?fPuys%-pR=?NcQRv=D z&ocMA=6>H}{XxO*&&$hu*Uf*lclwhPwmi(McK)^exYu+E_uif7)dtB02*lwD4!8Z8VSsUib zNB8D(%I{udRa^Di@*1CZ(E+&uA6dl`z~fm+kMFXx5r!0U~jj-nqB$QuX}y?jrRJ5 z>)9PJJYxH!yw29AN7Yt;RjaM-OhenYD7`&D*0t<0E#}#G?8Q9WHqq@iv8w;}u1kBg zSAsiiPiOIs-4(3gY*w5;xTkz>n)NGR2iqq}y|(rihxZ6~U)}Te&CR_Q7VdjE*0$|g zRv>9Rl|S8@bEEKHP2SkO-AN34FGOCjEo_)fnLdB7gQ$h= znr~lixPOZ54Re~fS149`-xHmGdshVu?cH_5&h}C8^S#?eGWTBOI=I)}dCp!QDR0|| zrQ7xv8?o(klVI7Wns9cn?8G=*k8-g+IeYin)@?kpSEK*k-ar3BZ7nC=-OuAmNH`;<>@5Ku{_pW4~w)ZN>G}{-K zmhbs`^14mm3VFMd7iag_tXpfl<5JWf3GvlCGq_auYTeB6wRC+6_( zQ*}|ZyP&~sD{H=Buk1=5+jm!`_r)n#?hWGhuvPoJ%O=Qbu`Q$M#62D?8*TY_&)LFl+7J4}bjj%=+lDN1Z=@@47WB_N)kI*mwO;ob3a?&wJ;+?%cD6 zam(J>Nqu{d#4+wYa_Qfm=zx`bYPWCLE4|?1-buDAZ6{i+*?YY5;U16rZ+pF7yxwDb zY1-a{uE%T?`q-_x(wO$%J#lmI?eN8W4SwCVDQx&;6PA6=oOVk?zw9yI#ACO@XU1NJo0sPun7$ zy&e1^drM++Y}ZWMx_9r+SgS2kSN0yd_IGd8(|@)fTGs7x-p##l&+J!wt#fN_zFrX9 z=fAIeucmkJ-nd0tc1ud*Y&@nG+vFXN-dnGHc<+Y(Y@16ZSvH|xOl+ssH19pf+qGxu z6fH}Z{#e_Gx4CW49z1OG=AHhYe@&BY-+#Peb5QX8Ui%Q9efRcC?tA<%*4E>8ovq~g z8@u;Mp5NQkJJI&M?cTi?%4PR%kS^Tw*Fk)r^^DznSw2VE_QbUAy`8LU^Gxo=UhS0% zdmc_cu=fJj{JoRIIrs4v-q^FDVZN=Zmf*fFmwPs5S10ThO>ec$W9-~}a%<+^YyS@0 zu5K3H%NgFimxbZY?oBtEZ0_;J?d88LW;=z4#ja?Pw$-G1t-U(&nR~Y`*}u2s5#PSQ z%!l`yi$~Zp2Q%yoSt7a5iGStZ10CCKo35?0>05Sxuk6!jd+({evrfrTu*+MpChEpp+p^6Jd&T*sY(fr;+o>jq?VTFBX77|!cDC_+0(GRz+g8=)Xw&R zOq=a7fyvgQH{18dzhmAf@J!3rp>y8eyj{I}8;ft+#PLqvNdo2WF_S~tNuq%UE%hqz*(Y?=?iSC`?^lz`mch9{a_HVIuxvX#7 z%w1qx>3GTJ?xRdw%`92FSyuhFhI#Y%I=pkS{km_OjnM3ydvs@>->Wv|^IoOZ?tA-t zh3p(u-q=>z-LRdKePfSV@w+_&>ldju(6TkQVyb!jx`%UuRWRoj{V%MX~du%zJ*!K3ZitdYT-neH{v;3Y&x17DNRKMXS@9~+jd*6Fr+pAE&+4j}k{kF?r$k=pwrtFovxNEP3L(|?_it&54 zNQv$hel22Gvwg*0sp%8;=HC^wZMnMN=BA|7-fgWNd(ZMQ?lm|Qzjx}FpSBt1rgjzU z^Y(H@U){Tw&vvic6oF$z{rtY& z7HS*zw*BMZr+4}6-p9Ld?WwiQ*&Ffg}k&1tDwqjd!<=nUnSe2y*~>4Y>pcW?EA1$ z#I}9A(7w+8{d0<*r}T~?awQ0 z8x$n%?w%{M-4yW1#(SpzUco)7dlKGUv^^B|Y47eui}ya}$={>(%6;$E$@+!Fh)tr6HeU#n-&2M+1o4T=nV-!Sg8eWko~uj`xqy@%YJtX1b2*lL=c z-1D&f&EC6`+IxR&mA5(j^|Ou3>>OLq`+WP<wY|C*HEs9p+-579{C97`d6s>0Nyls_FZSKDjVs&c;JIx!|NqU}tJD8r&qc4- zwqO40*nXeWw)f`Q@3yB|XYS2uP_T&>71?Xn^2w$~^!nbTI_-PX4)X5Rm07U&o%fu* z?^|c=4RiLhm2;c0_x{mmdsuq8Z3TH=+K7Blv#n`=yO-ZW$@XF0!#%wsr}rlQthSvh zA-(tUZ85uR4`=T+44%8^z|tvJj8^~m_OhGrc9@m9XPY+X-hV-Mdu_T^ZR>V0?Kzn9 zdCz}0R@)D6I`^zv6Sikn=?PoTKK^}jhbGu+bZ@r)EmLoktRlK^)+%wkUCGk>T8gjk zo-fsAtCD+X&t8V~y(X9c?Rvr|x9`QbG@EV7BKv+!o^1PV`}Dm%%q@F=UO8kNC9%@> z!<%V)(<2o3b$^z&byE@F*EPR-PeRF`Jy$O>?n`zQ+q-|!sXfUX#P^jn?zX;A+P!z1 zbMxMnd%xJYwQ}uaH&fcM!y|35_sr$Xwp$l3-Fs{^ zldUlCFPqMsReKY+EVb=VVX(d3{cNv1&!oNcvcKCXoMW_>72UM=Vd2_6htAyE!z13Y z_w8;TyFHENwyl#xt(jM}?&US^u{l3um5oc2(cX@SX|^6acG{G`Te0`1Hm7ZD*#+D1 zIm~vOl`ij1+Oux&)op<`^(}Aq$os6`Ykxh+OcrVyk=zX>|Y!b+QxR8}s?j zULD0(duK&Q*|gtXyeCx4Xzvpd2HO*gGW$;EN!vK3`0V*&WMRuu!?Q% z;a7WJT|TzATD@gYr@oBs1>xzoj^~tYy^gQkbN&SPzN0_x?Db9Gws(q_zV+D~#e02& z_-%e%ys&5elm5MVPmb;7jBVbt;%ejGteht{A#HB92bQ<&X3l@IXP?@KJ$@ob_mnwt zSRYSZZY4AG+TQ8zC-z8Nyt7&H@vrRy-o-ZgH{16<4mR2wHG7V2b7;k0!QQERL(LiX z-Hc}5w_(>b+h*rkdsqHjzW1<|*gk%-oqG-1T5Jr08}@wpbA6B2JIlR?r*5~|wSCTB zE3O~5H5X^v=r;K5o#nV;_hhM+dyTx}_f8gDzgKfxk`33MuD$-kLVLd}eXxDo@yB-3 zpA~xxrB7JPSGIz?0J&!Zo9H;^WI-EtE{U7 z#P`PfKi~7xceahqtxJ0@K2WsT!633Xe1gMX58e|tKh1aAtT=RN@5}Xn_D)IZvDug| zXtN+TX?M{2w|n<$cJ9r1m2JZ?3PwXvkr@x4P!s}dkI4xCWnm`vYzmFWDhJa` zh?cduzXPV`)ki^V7#l_>{yVu7#>Pb-yLE-28eDpb6*spyf)Oq!wokzDd-RHSirgaZ zaz+*8Ci#D#tVD`)G3*4%eRvj!RU9OTj<>CBAX+WDUKl_A+FYXjBykZlOhD$GE#icy zYfqhUI2$Av*zf?J20(mL@VX%1RWS83>@#q>({oyj`8=J%oo%kxU^NGKy#~`Ty`r<4 zFyay>hfMEj?N>qO6U+V^6oFzNNFV#vI&e7L-hCPDf4A=9^`oaE8esmq~*5|*> z;9&#O8)f-oHHb#Xx>9D#(8aLv)%CS8+LqpGhlxcqZXeU>#d(K{D!W6=gD?(cph3T2Tr#z`8(pfEnw{awj>Pq=n0m9 z^}*B>>|z9`O%VU`#SXaKCWj#TIzHz|@mM8>u7w=JqxoBVQMnv0%6d-F*HT90b*% z>milTlcT;HUC*ismofaF{)Mvo)=NiJ9c0h1rGnP`V@_iA*S~$Uv5JHAq2nTrPNLPK z>xJ>1e?#?EwStm$nh^G|qKZ7Di~qGmZCW}6dcHz7KI&J=iAeP(hRPIvmBQ`lvd zuy&_*)g-VQjUTFD8fN}GZ*3Ge!Nk$&qWh}g_8Gc3A%69XFckYh>UY&G1KatEYYMn5 z+!EWf0wj)%cN}%GlJ<%Q>t&0{QFypY8q9vKEhP_A7xmj3rG9{kBhz~h34`qdiFy2Z z1!t@D?*g+u?`^>-V^(Iq5eKP9$J=(!gqP#Ua(zo}!2UoMqm-SpW($Uy6Tf6&loQ0- zv%Cb7caB>;g_}F=_)~b=1exQu@yHqwjgB7)1Q1n+^ViJA2+PNl&tb$Zy7}n*W6oKY z{wwB5Y*lN4yA`CyNJ>!?M3aKAGOx#Q6Dj&(YJYRlS5D1JPnLnyk{b6foifB*%a98qszfs@g@gT9Db;@IqB%tnR?3 z*6Iu&MjV3FWjp)9!^+NG9?k~IAT^J9?BH?qCeIJdzEB{J;l7Xd zK4KvC=s2%R0z)lGjrW{jus=X-YT*wlg&5^a;huY7H&tVCU~FpBPn9-e9sj4cJ)`E0hQMeDjE2By z2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kW! z5TJetbh*!m?@6#YUWIY~&!=f2@H1t!zbpZtX(9gS8(a^}MVUTQDEla2;vib~upd|- zhz-Lx#k%495q|w*z>tTj!$#Yvn8Muzlb^PK9)_Dha#MdtuFdxE!YT)nCk9WNhd2W< zC_ob9-sJTQ12No#ZmzzvBtbRkdPwE7gkQz5Yh@ zGHH02b7l0v+2)^@gZ-VmN)crb9LQ|(_8zR~|0GSse$LWjIm|QNK;}?_Z8mv;{flfy znSd}xIe{#XkDZ&X4-U&l#fflp{VgGTAYuAW)qa7eDVP|Dp2@nBsQrIJ8!*p$RM_1} z^7%go#VGt9 zUGjg;H+Y!yNJ(J0=Y`87lr(r>;}O^#kR8uCe#7Nb)~|-AUyvLK&rjctAqEnMVaJ3i zG&}#VPca65-X6@pQF=54MnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU}%Ow&8hA1HH#aji(=gW^E}`td_5%paVGHkMgNOV@HLMxUuVisfZv+{6NAx> z{(>0lHCAP}z~qmVzJ$90CWenL6iUTdmzlC-2UauoWv8vV{X7<{96mdc<-Dsq;9;<| zLF-GR+K?LXM>ihh(K1W%_6rXcRc2AL7$ zF_-N4E7Y90ghV0%IC{(j;M*x&gMwitK!=*~VP3Q~iPgA|T}-GDAGa_lNWccAMb z#22r)1r8fzbu(IgFv)^nkfwSiaby^D|Mx_5F8dbzFLIiBC>I+_Q#D4Kd>1 zs{Ufc2fDtwr)0t5>EIg&4r`cvz?EFM-f4oEcSzlM$171~R^3 zpagdlOnl|jxfpH&$+i0}UUq1z0o;!uF;elanQHJhUrrJqM!Vi~GvWU9*NuD_ZYI?o zgw*$!T*9zp;_5jV;bKto0`4C|W@3}?{wEFYU%q;I-74QT0K-m@p337HSj9nd==gGs z8_{af^}_f*^({o3p|jN&YkE`O`W7Bmfs><9)O3E^gfo4^+<=P?m>LG}3mx^^f-~$( z7HRHCUE62*{arWME`uGcD1JI-J{j&lTy{|+&Rb!J;kM;#v%%qzTwM>ATeYqOV~_H; z=P{P0E{R~b#!k2-7LjQLR%@=S3GZ_}-#XcZklX4rdBJvp)J55vb#=FNn$@zFm5v{1|gsr|FKdp?LJ1)FSV0>_EUA`ukx zq-P&dBE=k#+K>x9C}x1f$ie^a^b<5EOWzormoENA9lQPFl?@Mb1#=CIF_MD@{9t`B zceNJw!1@0DX5g>@$<12ciV^=g`xat|fz-nAuKYVh#T`sNDfFJqEm+6NNHJqn?Pv&$ zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin;0S>d%RTV*i$2Yq z82A5ulvxa3iwbgWW!6RT`o#lt{lPRy42Cmp!*H&-R56%^q5egD1pNL#j{lk%@-TC; z(MwM+fV&AM?{V!A+#fJ85WVl(j5V9~_G6U;$rFQFzP7;qR>M<@vHt&G4>~+ZwD-NAN& z+`6x74V+!MTN=!E_+bcNn+;L}!jBtyu-^Y?cVaDuUqI>)>G5Ki0TQPK*Z$d#VP=G6 z9!5DqtR3t7qQGIvt0hh(Y59p(WcWX`y$@l-&yS_&;1KDk)u|0Za}= zPu%;P9pIz<-8#+GWGgf%^!jt_^6YgwFwvq5G=_an}L z0`W<~LEmHGd$rs|OK|$tiOU@>T_BZm*uBVNAhz0f4vaD#Bu)wD zw!}QQrmJ8QINZoF_fIFJKf(TW4&1Fy+!Im!{%Q6AZ-$<0}cO&ne9OP?~_Y?$2g z>7pKK0oe z_rT$qbz&PznvdGF10F7xf&1WWm|6c!r=hsW!W$B>r-uz6 zi{Rnui#DM8CjJtLECzV7DfPEK``^ z{ScgAwq{S1huL#kTOOmo36q1-7r%zW{r9uL18gryZr#^SVDT$Lr@-cd#9&yPM@<68 zMy8prx?rdU$!~pi0_+bEn_Bq4N`~N)8^}yz0b00P_*L#@pn>+t6hMPco zxm;t`q=@@rl>^BWgM;$};OXG+=@5)KY?ZY~NkiDoWD<=as0N!pQp9HIuwc}qsiFrl z{64{7oFccJVUz-o|3}%bu;RSD0;^eHr}|?R$L61Zbt*)w#ik!5)^>Oo(Ps2Mz<&Pk zA>S@|Seef#MoE(kK8D~--yr+(VV`Fm@c#eRszva$gs#VL{S5Padl;+|OjE&Xq%2U! z|Ls0ww&l>x0P(w?Igr)=-+lKLN*N9^OY$;g{QrfA71&LRvLP7tOWAB+%bI{M;PCGg z=#e|IP7WM)Z0B6y{eN%Wxm!Wz;lnqY5q+se7Z7KuhVHNe#|v+(5|~CdBm4R$to{Fu z?t8%QMOF)9S9l}N)CKXWfhVuF!*JKHiy!sXLn7FNt|cN}+_ewzoOSRg2Ni7F5mqjJY0@Fc#LuW55q>p`~XPLsYp4n zIUu%!I^>)x5c?qWW^f(=v0->q&l?Oem>h_HfAc-f`u}2v%dz(VLH3T~(GVC7fzc2c z4S~@R7!84u6#~BDGvVzQG4osN(S83&2{As>+A|m2emSv13QQxb<$4l~v+dTs$pl0F zL5J_~vks@te+_p7vYEKp-V+K@+H4?o&7PrH%{W&gu==X$X{>S}eZ=7PYuw>}3m3M+ z=>Na5pNiogbaT~t3<#=0*F!3Q(Hjno{(nWwb(DSs$jo)q4#NEd;**NGCM*Y!FMo}= zY1Q{@C02j!Z!5(rj?J!TH&TdJi%maB?8kQE$28LNZ7|X!$c!j2$UQS4cDC476gBVm zUm)100O`YqXCD-T_y5)Trr-?wMFM7)%Xd$)6m5l^gPQC0A4M&T_Z6bjab)-kviko5 z-?C8b1NkNR!*p;sd}lKO%kA{Jg3(7@rv24Iq-qN|4rlW5$Q$`X=ELh(_QCuA>dnCf z*Z)o1%mlUzWUqU49-MvC<|H@`3-#YO2gxC09%e7B=bBcQ&jY&`SuKeD-j|2$cm(Ok zhMx-6Vb~?w%Y{)+VAG3DjQi;`uz7x=jqtu`Z!+rH&zE0CVD0}u`#hVd`TrurLa-gk z_KTZu#)w;Fd2DPob&j2%RcDF4;XMbABbb^WyH0`U2w{9;=vK)T3^x&@4_(b#zRd*V z_<(;eI4`Bl(gdelm>J*ST!V-Cv zofzXDHXbo(5k3 z*ZHNZCS!%mReT)qoL`*-QSzeKAAnT-u^`iHsp5t}-YSW@|8tm(ldyB995V#Nba z>mcpiPit->0mWRi}!$Om|a&`A?xa3 zd|Y(bM<4L~3@&+G;)Xd)DE5KWy<~O*hr`5~FTwtgiN@Uj?>>Rk>YbK7I309|te1b- z+zB2NW!-zc-CgS%0KQdDU$0y7@5PfWAC&t=NkT^b^l+CnLwjo`dn{7Wz7^EfKCwcv!#$02t zzwy~ejNIOxzcBoUuCG{>9UPt?-mF2flOyFM+#jkFi!sb8K|5DMBX||q9FX}-*b#MU z=@!g+;<)TAylFz3&5~yO|L=Z@h3~fmxpfqehQMeDjE2By2#kinXb6mkz-S1JhQMeD zjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk zz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By z2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kW!5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5TIQMd@MN$KU2GCx0pV1KsKdhuq#hd%loE!UflZzo zVyiDqz;K6y?raRdpXT~Ukz1x5W>5mTcVFUDtCIO<7ipq}@ZO7M3%~;I1GL-W^4)MvF8?T*AynrqcrarIGo>vVRoq2HT6Q-bZc@I80cwq`>)`WqAw6 z9i`_i>@8od)PuWKuzWh$oVaz1;b-$(Yz;F*HWwRP=d2#sE|6T!#?^54x4+lG{`RSS zgK__FN0eF%NIg1ExZMVJ1G@P43Ev3bLyWG65MO4RCWc)N{S0`|ddFv`Q`$qYdCbhK zz+nzj`@anm1|T*FUp;gdey0S855uO{Z%v1>@zH*J*Q2CwklHds7%-}eJ>HQlPK-4|NF!dnX&OQk2ZxEXjte*FopgA*NaD&~u&K#20VD<^du7ron zM-$Aux^=o+!1`e7H3Ev^>2#r|6+FIbyBEO4VQNjgMKQ!+av*v^Yt;e}O$*%h@PHsK z%pEmzGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhomhk)`P#901zcEgS6 zF5a@o2|li8pbokB_k?6N#yEzLCT7PM8KB2hF)O1AhN+-k%nN2_7%4dl2``uhm!q7YC^W;Z<*rV2FXlVR-eS88o~9_vrJ9qxb*90(z7l4S~@R z7!85Z5Eu=C5gr1mrxEMsq<0)$j~*OvE5kKC+uYZ~%_kirvmtn)|4v-u=wl2)TnjS0uPKT$Hy$$s!YS?bv z$CN+4rP!mmu?TvHKle zP|O3VbG+e8)Yt(?EexmVEZb4D=cVYz*J>#F!!)pioXu#o1)i2cav+?y zY&V7&NF0WjD%>P1-@^3cqgUpI&A=x=DmNMeqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFnmHFfgLe_@p$Xm4d_10^6!SvcZkG7 z&I0iZ#hgDibdQD4o1mNV;3Mi>Do8%at{lGppS4#E@4N^|Ju+^H&w;xMCa$*WH+=2| zCI+GlU(8t((!CC=97vuRY_eSe?zhG#E*SHA4-Q0QxCh-_xr!u$YS8tN$}ck)*^REJ zxPBsr-#75MQRJ4`jZWb8|BEl4u{zc<2di0nraoB3(cK5)_dX%ehz{6_&l?fJihUrl_=79K;V`QJvNquR?Fq|4;>bA7 ze!nHJ{#vlV4oL^ef3$?0t)jhj6MX%@;=eBh=l_GhGlJ~`nf)}T6V9&txg6~8BT=95J0NAQokbJe z+-sY1!C?S1EuQ3m|F^f06TlxY;0mAS|+_2_tSn;`p#N(+YDYXG?MQ z`%)<39XWRq$?N~i?Z`i43)zjHTQpGIf-DDPvlvVQhv%C>UvRpGiQC?_fQQS=wNo(G zo8&ibLrH^TYuMrGG~qVl{3=Dxsc>3KIY1@eeHj^xRes5FZ_{UbUO;PJ1WED&L3f=yEFi zR$Uhc7Lfji)>L+}djYH)m9~KG1&M)h z|F(lD{9yHq9MdnlqqymNB0qaqwgA}dWVUV0Ablr~nQ%lfva@k@7I4fr_66Hfy@VI+ zH;_CC&$kuf;5v4ME&gg13+K^9j$8jEz;>ynvx3cHZtLWj&@=}u22#KM-*ncM?N7jF zW%X$?v*u}Vg2b&a8F2)gbhFQ&%)oXhU=n+ZJ~!BX&7!x#wAjO!VDms~kDA(YByTlk zH`boO@wI(5SbTz;4TsWKknqgE``FZ7fHPNC5)_LkC9yql8H#o8KpHu$iCYRo+)j zL{e(NW~Zef%;4C694rPkioxjn6tEeJYgyUf{@laf@^&(q&lK;$aXg5heb$ouVD&34 zCxOLb`ih=pbKEvy<+%6t3j5D*N5O7C^+T97yfU3kF~@SAjCtgIcA`t9M@k+Xa$C#+voh*$*o}We-n%&&FQc&RVui1gtMq zaSF$#&YA2@ddJx}hD?B)dpWBaEPwf%9LK-+oE#bE!fbMP-hty^cv&CVJ=<7Mu!cRK z&+5}+4;EK5y~&aCnU&M;*;jBL0NMZM;(Qjz7jwb#U-G*-K9+1^I~2bjYf7Lc7FY`1F`XWp9S9B*7-bEFsZvtL>L zn9XeVN%lz}*0Q~y#ss$SGoL%yJnxse95qvOz;=W5UY~H0UDNv_SPsMo;SWkD*{@~> zz{NO!xx(3pHlByD^IRY_0|UdqzX#y)_caQ#UHF`28V@DgV<1hr?nyiAh!MP-~8+Eg!38pMRBcuc0s@=cmXd+d`s0OzKwY=xI}d3 z@PEx+EMU4yol|A49p4{ESt{L|= zTO$FFY8#&7lnr3Ffz(aDoWaXvb`I>fB3(v-;7#1zdKEYLG)p(~9GSnGKYQt8-kc3{ z*`1#;@cf)1At1C^5A6OuTUhy|<5T$9@-A~;`N$;jNbEJwzux71vLeyobhC2x9`+MH zY5dKn*YWY?d-94JbMQ?$#U>D~#lU&^#Z<6=rlj!jUc1-9HGi5d&sA+zo|SxW`T90Y z1Iv|_PT|`6>l0u9b4ONlZ9lHRHfH<@iu3vEINSNm(&fQ^RCq7W^?i;e=eeGRyjNU< zc>*ppaV+9}%zgdWKE55c=eSi)F@xhoZ*LQ8W9}KSxo3_zvPsu+fZ0JgtNGYgF9owf zVe!(=hxfm=D%kyz3pxcRW!(b%)x)`i*Lq=zz`M(5c!TU_^2g-9U|;+A3|~hR1Fx@G zEm*(%(OCWy#fp5v8y51LXvcARo)zKK{8T64v_g=7-|<7d+mDy?=I>PGk8I`QwdtM9 zwPbA<5C0Y(4!&h9d@31-c(2a6!FQx>H$R7KKHGw12VTkBVPLyY73}1Hx=4^~k=h|H zkQ*acwC-0<;egTuO7W|IC{5kfVSpW{FD77*! zi^(0l1%}_aZf{<}>pQcTqpSJ>SfBROdiI6#ufTZ(WZs-ZQM?W&FZu4NPUqTqpo_ap zcN5?GOaTGk3rqrgCpzjg{5Cz({7V}ZdB4Rl@OIDr$-DByJh1%P zZ<7RipT+}zLirow|=WSJF5%A~CvXEwhQD5zE7agUhCr4@LYU$poMAOF_t zd>5Bn3f%m=0PHT1TQ>i2;#ib4ozw2?7J-|O^w`3g{rLGdrSmEN7U!9~YAOd~N)tGY zKx+RqF9pZjtXv2F``h~X+Ryg#-TNBCw^Ce1Ks$0e?_2Fgo)0ga_@(}L^Q7*V1G{m1 z`fA=A87cfTb!E7(WXAIEo#DcDMftISVPqKh>gHv<5?4|=S6MCO0h!N|a)A5&JwCn* zN3Qehob2N6-pnkJYT3=1Y^BI&x}ujaH@BW|O%bEumK#gC%T*Kw_UGGx{lOZl&9%ba zkB_nbDEE$Q-+0S^C9^l5(E#Va4ZCf)?%S#Jtznbpt=f2;H)ul_x9QDR{tcIYg3F%o z0xNiY)&058xozcUX8XYBx4E1D)=fXYYg;4*<{#X^FKMg5->M+PyFg!@zfo*2I6ZKO z7Vu`Nyyx$`s>>~TX(^Z6L@|DyEe3pt_TA^rZok1VUi=q} zmh;>!ROCI$$-#FZ+K%5+pN-3MRTp32p#(({C8kdE{J+L1@c3zn|jh|!XT6W8X9yVc#SpL;F4|9mGxypZW z?F4=<`#c`kZAtuQk%}BuejH#ujC%zI)HGkS?Ot#m%r6zV!J}s`AyD&`g*$z!g}_{Y zA1?QMxdPASJ|#5a6aR=H&6rnwPV{nJ~#Gc z0Z(340Z(OXfoq?=`S!VJ^RcYRZQWgd7clL`} zcz^cs$-1fX$&_s8X!$XVLt>H~=egd4yzPgy_)i_14-V`2gWtHm-+0G4N5Mj1`|cZ@ z>%0$hExLG-qxMD^pS!Fh7w6(N0<1aCEOA*v?22I(0&=X$oX4(8f&H>w-+`mKZ!(AZ zT^4YhPSe@Ve*4A;u(`KcSU3x7773Uiy~FSS&7Sl9)Svv%J}Yy*DOke&Pu&8nzK2hj z>rmJ-?#Ppz+>;~@^DTJR2`?`;?B2tt6`RJV@NuO;@#G1d?~cskGfbJmAGA4CV8ykg z{Fw{B^ZNhU!DW~##k2eNLZ0)gLA(m5dHIeUH{dCJeTBnebq_e7h~~HPJG5;TU=5za zdHKj1e(7K9`E8`*1Uw7p2&|g_o3|v(lsj_obpEN{4PZB!FI&Xz*?a++M$D>}~$ zT=&%(*YoW?-NtUe^%hsl0VeK=Y3X3IKXozi?Feq?zQ2AG*w2y^CJC55jp8ogwBgRM zju6O;VgkE|`Rs3jH&>s6{bILXhWo3ID3~q2RG!;^S2Wk+osL}65i7Ws+_?j`oAb#& zu)Qnhnj{!p-|0x&^Er zq~A^GDtpg~+gxrr@4;^Ts#VE$`Em>U>r5t2f#+J>s}tKfD$h&;tKanYJ*R75BKwoq zm)QQ)go4#qZTSn91DOTFvJ<9oB>(usx&8QO&gLDR9IBja!0LXTR0h+!jJvt2_I!ow z$-6AU$$1OXj2Ghzm23Qvt9(Th_nDkVu>6JSF80IhDsX#lZes?E*DP#i4JZ!;vq5^1vB(8=&f-m_ z;Pxm;+}fs(%gN_H7iV!lSFZdyj>WpG!G2&1iUWt`Q-_0WF?tknZ=3|T`@wG$jw`z2V6#B>aXU1C z&0tm1;9B_UE&K0R?O^`$587OFlZrX_@^XRoN`I3B$A9f-7dEHkUF@oBL%0QQb+Vfo z2y@#0Z3C-mh+n~C!MBR5(2WmlM)RSEYzrSf2ebJ?mvYD-+XW9BkllT`Zk$_Z=W^ss z`pOyWvWsK+!donDk0D{ak#i~7Opv*LfG`mF|=5VQMot-!-v-)jD4l z1G~-6{2*K|_oX^#`IoLHaxgv7^ zfc1TLTidXS^GnVbFh9mXgFAH1c20)MX`Bf> zciG|>hk@;zoU@g!;^ZqZ8>AX&q~M zpaZwsh38;*fYgC-ll5D$KA$Z!xHLmv!Q%@g2f`os#dBPjB`n`pxo{eflM5 zE@Ng{_J V0|EaKv*hr2H0)lp8o7>*?w`p*`maLzgLy3Y0VOjlE6}KF>PJ0lGiC* zoQaSzmmkN^f%R)GeFfI1`>==0Qt%L`wPOp{k5$__oV zYXO%ye|~o6s5`*RG3#^_*UP2HxSU?~a#@_HWe@n%0X8e~94FW;kbi#thNLkN`{2EL z&U@OeU^(Zd>p1pLJH;8-#lsP3IGb~4<`V9Hq5YgWP7A?d15!WL1yXK<*bx$wxHuO; z>Hsi5AeVimbRee@O96M$v56et?r1X~-`B(;vc8`^=5#)%_<>ZeyM0aYa8-_o;dmN# z58N;77f#{g@|g*C>z)!P?k!i{z;^CouHw{dn#pN!>?!-7qtn=P>mX_D{PtF`T9Ca0 z!Qouf)&_#jeg0RPV^=p5k4mKumuY!2hu85RTo%Wlva=rg$NWO-0ay+563AF6Nbi5y zYPdNdJ_yS;wR7o-o#DE9d=WTpuh`TM4j+)*0*~SySPptJHX0p-!9ZqY0C3w+BKnQ zeRJVWeG$UDq#@&9FQ3PACry|tm@N7P?8Z;`bh(#%dvQ<6S`Bs=%)GZzj$nBZzw6L+ zk(?L>?uX~sag}V{3AVRlF62`>t{Otz9I%eRqTiNNobkH?9{3Y{CV#uAIBC zih#rHk>qK(Ss*njm-yN3Zo6?FJj2bwkg|~T)L$WRTE6i{1?+};`4-_68Fp}Z%5v5S zInCoZT(y+;fy?YXF&R3k8d?`OcHAbyBp*#!z+uyaS3AY-G_*05FduC zqF#gT0P!`|T7~5}mAOSuFms1H*Kn6{WwYx)UII2x`Gyvl2B~B2(-+B^I+$1 zrf{xq7XhcGOWDUbdNvvezh=A$wlC&dC&xS=A+Wx0%k)`$0)64(0rH3F%cjT3b^Nn+qGkW`NY4Y!wqu;D{BfG*}@VFtJaB$)ZtcGEY7@ z4Y<{97Bpv#6xtZRjr)FIky#AbY!zsn+Ud3CG!?%wj{()p?gnp1}dxq`wyh{i6S?gU940qn8x%T zY^Fk`K9|>XUSYltSz*2T;ov^N8b3>L*cxxw;t|5I+mQV*`_F{guJ$Cg%5ZSIX&fak1{^dYUvJEC$juab-8y&9fuV za0UHs7TFNd$}Jjk3!G0r{Fp1qem+O|*xAEeO`lan!)?y9IQgyNyjS;|dsdgBi0m&& zTZV0htI#V`17Y4Lt=zTgmHaF76h(aByybK@Rt5XjpnVQ^Y>ueVC%uIn@ymF@VG6Rl z)6rfKM1yd2({9^7flb88*5C`e7rzaFr8z1JagPJJI) zxF4{YfYpKIVc5?ikA21a4!v!RNEOZaY-mQDMW~o~Xvx%s4X}xR!=V6fC z=}JwmZ<&Uo5p(_7Pox%e7*AQpc74rs?r+NbMV9ee@XVOiF1)w=FxS<7NPX|Bb^~l~ zP1PH49BACMq`Z@b84Gb_#oVI|zMq5p-_ zYs-Zu-^${y-Mp23LR}i%-zPt*^CVjoa>nEcb0?ax@UIsRhtwPjKRR z`xnv%bt`G-^k`D&(p$Ni*>PqH=b4&YLUIA~xqj8kf$askZR;UnaJe0p;UnDX)X&W} zDHiMokeps(zDVbe47uPg9 zaCj+ZzT}YIqX$l_3iT=6)Bgv9)vr4)DU$uIktbxDm5BD!|D2JP6Sx!kT)^>g%Q25L zt}~y*P-+%9d_iv3$qfVB8NHPY+{Xur$=;L{iOTKe`n*8~9A;Yus=;Q1xhJ~<->0RfphK7o>hJn`3;@;u%3gzui|eX#jK7M{GbFR}9!D24HT zI%~y$*}01M#OApI`%L%qw#}0O+XpghK`aAUJ&5hIAy(kQ&pkX38?u%A_)%OJ-5zrzp7H_I=GjG^XJSQ z{-)JzV7VyEbe@7Wkn%e0YABC`{5t*#>vj06Be$Knh@`Av>|I&P#7V-i&q8d1@B-Hth-SfGE{l9_Ds{Ox`pFfzJ zkJX4r;PSB)9?gprcrtUY2&Bm7@tZG-;d^@V39nmN8vnEEA|4ZaRUXYBdc2a`6nJLG znR1)X6XDtS%7=gBYhkck?i^*~4VK~t+g;mZA)tKb3OD1uec=44xP1;!B;Pi^b^qkS z@^7Lu!E~Z*mq4U=3(u42w*n;+EBK`>j&Z%-_#YfjvmUE*D?i`HYdK4dN5WzzkD&z@ z_razRuzBwdtk_#UA>jlHn@H`eyo+2d`S}>8aC2pv@|>S_im&2Yvw#Its(_@33U9FK zKCpjdBMf*iUaaPq)Strt@UJ2_Z_*L&x~bQBeRnZ{{qSh(XD}V|_7v~sK4ZR@;Vj^A z4UAA{e{AXrPJgB%y=;CrtOZOjNbpA)Tk=1-zDD599A2=0KyEqw>J;Z6aaQiUiE?1| z0dtn~KfCptFD%uTJt%uFcN?=I*i4XGrpA|G_5*_{{F}6o^6`Y8=1aM>kr@;Dr zcHTU*%iK?r_w#SI_2oJJv<~ctd>3nOea3tI@3iMIuX?hZUwZdDo?mAj!FIL8hVh-} z?&jDYKNp&%bvVt}eYQ`)QSL84$KpBs9-^%r z&fALk*;o7rhZ~2c8MoWP2(bB}aFL!;&d;d*iR*#(R6dC(S9$6m#q&$3PUElr>Bx8c z@*Z$Fh%I>p_M^;XJ}_TARfgy5fyrR=KxV*jK+_a~eUT1)_1mw4)q%t<4=&*kpKHwR zU&zFhZ)(feuegf;gvJz3Pu7=wlHZ^3E_`~EJMUl&-}wx0-h%gm{ChXP5xB<~2-d&) zal3%X)5(0^w>I*db3foQIj0P+XF%pU{(lWtGxOd#&Zrw#`6nFy!tL_hP9UX-TVPw; z9$uyD!~E|B3b}*+>;}8j)}lpV7kePf&X)_pe6@`MJd1go1Sb0O^UQcPPoQ=8avtf_ zZ33GQ-Q+&-`#JyRQ>(elcgz5X)32VdJU)A`2|VKQ5jcG*3LN%n<#+k^`W+H@rqM1C zA-P!K!O|1FAq$uBJrg{`zaZuaXWG7N0v8T!7ij)@jdy#`8v&WVN`dWaj(les=L;;~ zpUHi$ozQr<=_$RFT3l4{})EM4`>8rUvoSiS=y0wdA@y{nbYwrBu zN_gJF_aGsj=bMeB;JsI;cru<#a&4`<2KJZN^H*TAK;gN6(njtMn^oXCP~U@-=Zm;I zSk1vsGwzLt*#*OGodwdW*K^OgZzCYh_?xHk<9ptzx_`j!Rev@Ou9=GZJnzvYQKQxZWV#+3;}#+QyX{< zkDlc630=XyXtoZYyW@GDyQejHmKEsnT!=aVHp~CP9{xUO8Nu#l>0DeN6a{%aHltBrH|CtzXop7V941#e2kF@eU_Zs0I7b(KpM>^=el%SBL7QvR?LL8vCvxQT+-~vy5nwmhSu#a-F^hp%_jNUk zmGi!HdAwsbXZxe7?tS|!@5XP+{1cfo1m?@-{)Ig|Hfm|b1^n3ri)GhY^eAZLx= zWTDm5ySQ0*6bSH6umGF4`eP&S=X@uypHn`cFk?~9;+lBHhd(OXTc<^8m!Q!z1M|r) zQ`rU5S-IIbrpvXwT%vLNDJQpp=@G4!aV}<;9~H45%v-^4=yFleY0e_yZv&*_a7uf$bZ{vzr9{Hv$sa$l(}6$iybnCc_b%2gbkpW|70v*i5DzX_h; zYd#yo@3%mPbE|hNXSBAP8RKUS-nrotoO9d1^BKO&=JQ-C#J9;$8{8fgR4n0Iv5eU~ z?2#L<6lb}@XJ%s&D+@l(=S%AOqQmmJIaGIZ$;9sxtSR}x>a3?B&9A#gs4Z28=kuhU z;JlW9JdIC!QwunM3B?I>Up(3(Ag`s*rMdei-yscmf#v!O!Rq`&7n#S*xGelYa-N9r zxhDRyw<;XJ{g#_qE?mgF&R0~%?Y6(5x|fhZ|6(Dt8vi_g^Y!mI<$NspkGQA{gw@$f zyh&KVyZ$*p?-{l!{7V^?1g|7r=c;vGz;ki=Wv;B7to;0I4$Fr6Df2IN;nYx!&u1^) zy1@LVl(bpts&KC4h_(E;_j9w`^Izj!B%a7UuS4GajnQ$ww*6(C)B4N#1Uv1yP4Au; z`2N60Zku+eh`?V5fhqobq=Uazb6UMVUbv-_*B;@2%pj;R-}f^= zyJr#4JbMnId5z)9AI)|sKD554By_4<<6_?vGm#(8{5SdhS(Z-~mRiiuBzyX0DVMhB zTr<%4e?mm35dW@f^97UV2vp8l$9wXVsP>}U-KM!!-^B_#yZP+=nFUlfK;{EMZu$Nt zltal*LHuQJxxlHpQv8Cy9tqA3d?l7CIFmQ>=w;3eH}Z`@>Oh!Pn%~Ug+Xq1lQ9HpC zF$NNIwlwoS*dW6zsdPWigqiCm-J6$zS!%6r`vAtBUZxW);<=9t~!D zyd?NnyUgKon>bA%;8h?`w&WDPs{JRqJ|F7>*C%IuE^~BT7(3>3d7s>8s&{lRXYIi| zB3C3^IcHv4FUj2a&ur_FEnFL)&MvSE(t zUWOR+qZfF&&Q@&K*kP(h3g%l2^7pZOn6}xR;Cr$05;zZEIi$cR zzbjKhy^~X5fwwu&#IARIXP(QMJL>52g)A53QaQkA&br_upG2b__uJeqvsoWk@cwO0 zGfNDX5n<;(1y1k3oWFA>eV(c|*)oXzxr_z}z z<#*lsl;iLlE`f|+tIh9jKFKwygy^Q^fljFzzay*kCei#?G2LlvZ*=@KQS zv?=xy|CGlIIroNt=bzfg%sJub5;GBw&zyxZ)ut+rENm+;Fbm{1{5H9Gc!GxXdtCwF z$usy%G+*g~?B5??!)GHWCvY!gfly%%gMiEo6)FC&iF{QR-BO_O|Gxoh0{i*+1#~0- za+xn_73$JjDY~SJk8i&#r#bU(J|TwrhxlUt)$wy5a^cFE@J@a6Iuqe1f4=Z*^kfU{ zbL^JA;@!`ATj4IJX5$AI>k27;6XR37scsj9r0s$^wX`gRmA*NfUa_4dJ->8?3CKN% z;xBT!hJNOp(!NCUHP8 zYUAQHj+7GIl_+2qy{d{MDqx{3$gB_NoH&ZB7J$pW^?X}7p4+YvlFiGI8sS$@XSGT#ivLa7Ftb^vt*Y`MHu5=REYjr|C z`ca|)-x(``-b_(-u9}_TzB$PM${!(P4hm<()R&jW@UIjP;y?D5RgUYG33qMq5w2XJ z-MqmmErM58Cv)vsVZq;Fewb^;+v(sk^414u0b?mSp7@!vTxpN^1@@FAONudV6+F6h zw}9B53E=R(!D24(Y`e4Bi`;znuX)iTF&$rxt8{a?eps&+SfT$${^gg8{1#P8=GS+e zkaOC&R=jWLbc?-RN4fO4^ekMCUsRvH_#dxex-fs&n!N(Q@>iIx$jK71T)iJs=WRT| z-Qmh7#(6PBv`~c2;@__=JW^{56xQtCAeVkfM3M35Z80x(LyirFVcfrB^UbZT4)WCm zJMyjGdWpO4E32^B%4VLwn8EO4}IVaDx>Wny#n|rpLM%F(~%b$H*I-gQ>^wu|+9VtxU=6X7r|E!UT$Yd*R zv8pa>aCsRW&(7oTG@t**9S{DX#uMC0^UC<&TxA!K`*DlAk|R#?)f@|+OED8oLmxA6 zRc%Y>pCH3;G3ihzpBQf|sQzbD(^=1X-f5EgzkYt+_q(0A-!k~tDG&W*5rt6cxf$~$NiJPGLn_`_f8)3|8Gw5F|atvFrMcSx@O}dXdAc8d_T9Y z0FVAF&OH+r3LHz?C$RWdiU(l&?6v|-5=>fcvi)2tY9Gu!y|l~~1@CYk{(h8y)`dLo;8GLrSQ|@jd9$PD<&w4n z!ZDY)udUP*a$9P|ZGLC3(5}Au@+%IRiD^Y{6Sy#Ufz1AZXPoE#c7V^>W;gB=*yz?T zJ4sNK%WhM?z_o3wcveo-2Ga zOy0eb|II;0fje^+D|*F*2spfN;=g;SSu|v=f@+PLj?%om-zqg>sTx17T`|)REaK1H zwVaDpXNFXdUZt#7S|E=B?;`W|8cFs!h9`ypHp^KwlrRahYtG@lwbfPI$?1t1o8TEq z+p{zIK7WuBu)Nv_b{EJkALbt6j4l5zQMGiQfW|QcUPIm&LRqh6B_^&5<(re)$@ya5 zFL2oiQk%6Z!u+CQqlmHFY+;W=Rmt>wx%}c8<$SVoLBGU68^K6ecUUYcYxE%nsc%| zZ`!<7B2ORSe-nL?dw0+jfgY|3&h74(MH&{Z74dUCFMQ(%v*3!On|aqt%ob|cFUi%d z&>^zpw+C0vBysatgEic%g|x(v`Zsc}vXPfM;`YXTpOh2#xy}Vij)98Q^f+wRyjQ{c~2SCok6V&$LkG`E;nBU(|k<`G?J$`A^(5<25+(!~978 z1b&4}?L3n%-ZWQEpTgVMo@*}U|63$iKoi{OnZ&Y)vvq}rhV5TLj`)0M*5!#Myldb2 zu({vy6bNZrXD(;x$FJIckUv+=QL&!QR7kRLyW+BnUNcFSInuZ9aVS*WzRzo1+ACK5 z={olv#}`~o{tqSE|F&^ga$4~@ukRAr>)Z+sQ~Qvm0$T!<_)Q(%rOp&^@K|-;kpjgf z2)l@F<=|dj#Q$)E3%kRoI|8z)ZWel;);upZ@0T%Xn#z5!*oEi!OT4|@<6SOt}||SaW)pON&+Co@ zbW$KY%YY+Ba4}on@l(?G9oK30#K-e43vCjV*<@z^WT6Y!%()$MAiw2G>vCJn{KWsP zc`~{pP0gY*?7F;(Z`BaQE`2UKmve>p>naBU66i?0mW`WJVXzE59{}>d)2Re-`U_cc zK~uY96Mw(3wSf1X3^_f&cCOFI4Y+^*=Hk7Ydr?Gf-Xqp~Au0lj3ny}4Eb;-DkxV_6 z0`-Dw{I@o`aT^5x;IG`RCjDerx5%xVrv;8r(~tp~|8cE8{}Rmy;Pw^ckth7;nxy#V zJi5jC-DaJ@T#ZcdI6{3&1lSGzi!JzXM&^R^-R@Kka2^Jk5wwAe|5<5^z_XQpd~agb zfXxDlgK&!64gP2BTY2|<@Z{eXQOv#U%|))C^>W+}S2yr%TOSOre;F>TaZR7%&n5k= zfbR!)I$y-xZ%(Dz z-TV;;E^xaw^s_QuV&yiRdXs-`XEWH1T?HLHGmdca^+YFe{C&QI-#WXIeRrk|+$_-e ze^t6Ce>3|5zVa&@c{-je@+PvL;Sbq!n6*^b9_*j_U)S^g{dbAel7pASl5GLoG3gb2 z4=ftMa_x@dT>LwhfWzp`2X@Zv%y)chf8zO?m$dMu%4&hd_vifp$BFT|RlN7VW^#c1 z6Bl`eOW|r2-_A=h+?Rgaf#sQE!#V2KF9MqjQq%W&8CZW^^6E~X#am|mgs*zm9HiS zuLzexkuO)vj6l9cF*CqsN!(q@b$6!(IGi~z^zhFRe#>g|?HJfEn#(8gFl}e$>k}6T zx7lX&9|6+`rhnq!QWVL(E2v)JuLLuH^q*vQ7Do@TKj*Gq!CrV`4sTljcTSJ9joh#P zu4UajqX=x?&y@QdS6@_t!wwWS+hZAd8l2Yfeg3P%@olR-SJSjUKF8D7_!Z1<@J~1$ zz!ThB40hv8aY^nSZx-{luRF~*&v`GW#iC1`#+pey{#G?$`3KzX;50p7@&wm2#X4S4 z{SPwV`SAs|uA-A*IkwF^*qeUN;@|CbpYJ{23O?UZae-~K5o?9~692MUyfS1p)1C}g zZ`v!tul22iS39qj{Qx^Z*UN6mI3CE{=MCK~AX-b1pZ}Ux4R7MVXg={0559P9c7Z*c z1$etFr*W!8T;rQpI+ttt&O_jENw{jyHPMxse_F;7rZyW*{*?QhIBx{)2HSPR*n%g! zYAKsE!z6Gxb(g&2I?~p{b8hZl{-@WoxN;n>f&JMntitDAvVm_&3o{?@?%M*f+b6TP zUUPIZOI0`uV9GANAB&EOQHk-4E zt23v7KgVk>I6mfNa&n3I*1=6n8ceDz{}IQB#%$g-;{q&R}^>s zqFAuHuXk&~Y3P>d9I*R%-^p@i*CWaWkU1c%Rq~zRi0viM(V$?kK9Ja+5^;V%w}qUY z2|YZ0d6hhe1dj2|?_A1$gZB+@a;7YIZ~9iYy`3+3FMpfIbzCcludX3dV2Q>?aQGiu z$|E4h&&&7DuaEy(w;lU#V>9r&Fp#6GWy&RB-guDvd$q8DcxjKoO70o_3#(Mv?2R^afyVz+eNFie`a$Ml*U1!u z=fPnC3eQb$SK4K4f4-#hxxRz!qXn6}^I-vB zn!695-hxq zO?V{}4Y{{^|Kv@OwDHA0jk_^@ z2iH25-(a=T+C>7}moH}b+F8kETPY!+ANdUI{(DV(1z_XRt&Z@0vGq&A2Zo zTy#FbsHUofBcXZ+@86PI`TR*A`Rpw?%{Qf7mY%vTOKk2D4U1>4m7F`5{xkceHBX)8 zt~KB1?$bPT8_W1O)AG%Jrc4q#dvY1rubo_eJYl<3h2J}Kh(up#F{_q$}dj}tw9(CyA3F%qPlNw;oQQ^5ousOz(Q|pjBul&SH@c6%q zx(E-u-B)lrNhs(rQ;JvP{C-N8x5%7VS7Gi&LFR+H=1*T3b1s=5!Rh;(MP60nqIyoB zCC>~ER&AM00%rc*580~9cJXS-aSM6wLA?r@d>$xpZ}Xjb*;4?CxsH`|$YN6mKfoAJ~IGw}HBDq-LBE{pToo&{zf z-R|&w(ocpmnt zl>&?_q&d#+H{i{UGT>8qBFYoKv6c1kZ4>i47aoymo1O}9y0645Wd4Kg{qZ2PIbJik z42;xdzIol{j};IT(30&k`}og|yY=`Awre|8_yxUMdD1wnCAPG`=lFHy0@t-m>-ilt zA_Wg$UC3F_$j%j>?#{7Mu#NY<=?a;nEB^5mJaN_d^K}<{%(E9}OAl=^1@-^;-Ji$v z?`Ii%&%UEk<}(S2e9Wokvz@hl9im(DTrZQo?g*A;gVT-GkSX2@0|#0gIGpg3{L zKgD_Fkb-L9Bvl?B240TH-udQpL-z4XwQc2jcF0lTVyLV@khnGPwzOG-X=k=8oyuoc za{TY7RFqY%ao6Ra*}In?ctGR-xtymZq|dU;KHts4{%dKN*_#Rv*4W@xLM<85=2`Yl zyehY5@})K#YCnv;Z)y}-BJSv9&tuWy&%31vv4(WjE+)=z4sznH(c5^Vx|Z<%b9yJ( zz_?zl_--KY!TdcO7gk3bgWL?lPwoeqY06I*6#X+vOwHO#Kd`_2yBj?IuXe;t_;ItE>hq*{v$7=zc~&>C=Dh#yF>hkK0=MYw zP;OBDFFxl4xL)1MEX(nz{*3aq$+LMXBWyX?|G(x@(4Ng@Fn@}$GrOCR+3b@-TYgO7 zHT%ZEnd#6ec(MCDN6C{y;e+Zy9Q|pJP0OxM<#;P*D4Ly+!LfTwgJe&zuNh;QIY(}x zw%G%ZGdznm-fLc7GKpQkJ4Pma-W*=r!_0iIIW5e-aVMI48OpF7KAxvOOIg*NqhE_h z{h6jBLo<_5?Qw4IPj}~;SiGLZ;aj{5oQF52|7P!>VkDt;NLt|d|7Bd((VKW`qjs20 z(=Fwi`l*3u-nQ*#+3hksuX+VI|FNGl`?6e#hjDg#g$XuqzA*@2@Rb0#vdpE<%Vk$zc~eY(_Bo(qP3yqbG{f%6>07ek&lo~69o z_A^O3#yfH*_}+n!|4Ys|##MU4-n>+28gq7MKCjZLF!lrg9`PnP+%uozafq|tSW~({ z--7ot?+y;BvTIDolRUv~mlIrXz-f7%%SMGGUvqdr+lX<79Notgbb1!MZQOseYgR(+ z-V@DDZ_lscn0(KayEpT<>Du>?)Gy{P=H+4B!h7&?2YCGd)6OQYg^LAw)HJRMP2s!2 z)65qu)$uZu`*XVvX#Ag5iMN3_V~#0r@`D`CLoADg+Hc$y<(RRXd&>(&^JgNyLQ$dY zd~4R<;WMe6!FKlPTJ^gJbA%^m*70`mecCagm;Ix|7AkT4il`zMHYZoLz_5ZaKeH?u*JGuNS^M$+D zT;jZN<|?nbrY2|bh9cIvI`^a`+b(N-7vIaZy3vCFSgneg&a3Yn0?Ajw{nIb(^_(W} ze}m)tJkw7$V{JEq>ruMA@t>};b5HG+nk$jY@_T6*XLe5@e{hf@PjP7=Cy#(S>+2H& z<`0&v<@wUJfNkD}J^^k0MeMmN-^iCukWpPZ=>yOCueRL9pYlxY;51<~z)5p!|{! z{_v@ee2rqa1vk516BtTYTa_=NittTYHtjilh4cy?L&@b29??bcqM-{iyiRhtg*FD_-{|9`RpT+YM^ z?BZVLcnfT@EyzSH%4z;-|4eJ;Qh!_KF3K8#OjD=+KUuxdWn{I~oTuRnw3H+dcd)8GA+ z1TUBK^0%y%rk<$hVC5_J(bIocj;+{(oi6zi+h+@3w!C{oT1& z-*YogUkolgL1Az(+>f6j_%;8n4|92Id06>^R_){O*Ao`}e2hcz`_)6dAC|O${mYS` z!}sBYguvpx1_I}!j__S~R^*#HeHH)D53|7XyJyT1^t}|!by{W;f8LQ^{>!qK+$MYl z?B4hPaXC(45DM;*=6b})!s*C*PC)x3gTQK&Tm0vGyab(-AY(otw^&xJzR<W1mXCKbzmad2w=zE*R*K7P$@To-@ zC;#?T{uL&NxTb#+0f$Y(kp})LAH(^1%pV9;G|BPLzAhvfVmX1`UAT`wNOUnjv-@=Z z)62PpY-c~=Q7DiTjE+1H)^}!)6W{%i5dLE;&G;Y8jN*T7HG@s8&<5hHm!c%#SMLLk>*VMl{s-Ux3q-6q!08?t$MMcZR^Z;F8GKXC*6?RZ z74u!$&LN=V;45(7;SE1u)e3=HNj|QkpO3)yb#oen!^NX5n0MK2$QcQsu-(2%7~Hm4 zo?{?rwO}!S@Tmr{x<@l7v(#JgHtlHYqmn!pAz7M{N9bpG4Ex%|>g z=J2-UP33P8|HHTT@@;;Rcin3INNu+a39bs5yv)c(%4-ay1-_o=t~OvCr#%3 z_SF*1U%KrmZ*7OPp!b|s-mgy`1sCT`=X-y%L@<0;FRxb00fFwN$9dTgIS3xzd6#p0 ziV~k}ev_a>=|cgg<8#4bQKB-3|CfKUU?;zZprDtN;Pch3{C<-%`O8yh3bdL?aO(wC z30l925=?qn&ad1!MNoIPqTo+S75>$Uwt|@(@A0m<*UNu5bEd$bo##0}1}F(mRQbur zEblC6`gXhE;iWm_h>TTgVzo`>q<}ZZ~1wVuk6`&!TE9Lc~#5; zxaZ_F3R*tn;5hN)HrOv)t{!FE%3Q=-`sp5+fA?zn&=4=?|2Wm*39AGY((JJi7UW#tyW_O|(a z>wcT_{C;tT=fXKLa30>(u~@)g|A63jzeC)sPHq>dG~X(4W^1Hih4MVXY!6}nx34;R z*A&kXcvlJ;Cvg&%;a3&82F^$EhA#xI=I`U@(`^+{-mAb@@^gY@mf| z>Wdinq0AVrTcMWR{k4f;x5l-EgY8sb{y~PFbvanCX}!3@n{8fP{u497`~~iD+`cI) z;P7xfo5FcGL5b^rSPo}m%pC4eamX4?5eZiwCL;!UmmgQa=7H?wvtG$%{J4W>m0Tmw znKo6hKe$a&ReLf8?4$^-mo(0?%O3ZHMDmkbHcFWzRmlVWP z=Wy%j3-EY1xpG%^Fmb(q{#f2lM}XDiPZGE-IZaB0)90|3{A}?_+@IG#_UJg(UE>aI z-p93AVkP%Y(=XiDtYf+In)}!eEVkly%{Jjs%F6}217z>aZ#i85BqoE+y3GAsZvIVn z1(5iIbLTmBZK`EkJuMd;b|05MlRx6Z$+M4d33%P9|Kw7z85(BZoDSVL*{`tg;jwBL z;fiGS<2uSK2@bzI;_tXGG=Jpod$*cXpJfy4lJ0dJtKYYP&1=6P&-Fq41=yb;`#_lY zd<&nEhXD81dy6@ruE>-x^}Nfq)~J+I=-eN+)3z31eSaQzvWDl(;`S4|4Axtv-z66* z^hcgc9&%>GW{c_Ia5d(A$I1LFRpG87_s-t z91QV7JTLe^fXxTFV}YwKS7!_#_tQ|wIR;NQ_;UwX%YgN^_1bb@QCkKM1CZL}39rE6 z6)W|Q!_6;?t6OFx2lMVMw#|t;+zp;dGJiXQ4rO zj1LmrQ_pPY4k(0}-+JyIc#IIF288D?ZsR_z+0VH=OPovPnHtw=opoUUHBPtWNijaj zefVKN_xy{HwF^_!B)KFx8^Hd!5ber+{oZvsKJipeiIsD}dfpzb;!=NnLt%+a3%7c0 zsGOh23@)v*CjR5MH}I_evz6yk$479O3h{oD?+G|4m;98U4yA{JJiAYP=ZbnL%%NGC%l-E6X0C%fPI8AP zo&dY=M(ZN3fa9uMd%R|_&ozLU12PkY|7me^Kg?%QyfHPNV{y3**M;8SoXiJZIUnZm zDg6sI=dQf4gge}0Cr{{8HgKLr|~X#(SsSBQ%@Y@84o4>>O%ILPG?d5KM7mL^XU*GX>k zn;*GTr+(tl-qHy+*H26sZ07a|8`)|0lfn8xVSCigf`g&j46Noj(;qIk)?DsKK`PvL zdMdaYwr%CPztn=;JcR??Rsg9N-2^!&Av}1B{H+Z>+%Lr-`*A^XA1*3$&F`Bi*YoEL zPj}Wejvsej#pksfa6bF2EdT7mbFMP}h1{AAo498lfQ0L5m#thsKJEhhN$qbJ_nDW` zU^mt>u_&1QgY2PKzxJDJ!uHehk(ZRYmgdgndc}Scte(qk0at~^E^u09*7oK)T;m1S zt9t#9{O!U9-t-mCqRG<)IZNeOxEEREa7LtYa31@3iu>ikx6IcI0>J(Sxw%E98=Phy zzF7;;;~y5Y@|=sv;4zJu2UhoE1~1rb|FAs9gMrRG|8$eVd^g9tT<>|hS>GHm=80VH z2UZI*GbsqNPYA@ed{xA^*K#koT{FGdgZF6bV($NnUA%cS3i-l>uY>cc_k<=eee60n zuWG|Ya9F?LgPa2jGDG6SLB5y^BK&KD)OpXwK+gF9iGy%Jiy`l!`cR&~;m>#`N?ZoF zcR}KRZI|$EoEiu=YjWIdzB9Yd@pwG+;k~rci>I5Fng7vjA^uKo0sf=!PJrzO>2Yun z0=pB$mRVHE^QDf7x6jcAEN{iz#jT{&&dsA8%)7blEZ;*vA>I?=hr#OOn@jmP|MByw zq#WRzdRYQ&CttNKSPo@fy_6(paoB}%Ze8AtlFW+HMQ7= z``~|HKKrl#;N~rMcjDS^)Xw{SCZrFZc}0e%jM0= z$@jn2g?EnB1g>Jf3p`KnPXoJU|G&-Puxcwv1G^EV?`V+@SnRUw3f}SuM|fw%OM%^H zw!a-bKLSz%!ZnGC{Ocv1dAS$Q=B+fl%;%9F2X@DuC|kMm z01cb4S@Pw|v%V6&F)Z{^!uag0w> zFayj7*?V__Ew^rm8^4j`W6taqvV5obr}JvEG4an4y3D3E{}k9?FM~LEgg0*in+?+A zy;UC0c74Fe$M5LOQ=oB;SNXaw-`(?td}*`g*=-#s@Gs4Qi~)i4fH2cd9cULE^z>U3;6zLa`16^W%6xlgS3rStzhBV($>JU&D5QHr`8*=IUqAZ_~a}>a2(C7 z{lUd_xRlrTO)l@NI7L3*yK%fLxi0g?wO-~q@8QnN)dpF=v*;cqAJpDn3N}ZNSDjDn zb2snZzQx>2>}T+*JkI1>d9|C{YQq%X1FWrF@i#Z~CJ2gy-MahvT<%ZzHlJ;a9bfQv0q$#zS{$eK z*!dgy+4+C5HS&Hrah@x68zh}a>p{*p2Ki_5iS=N+K&*$)h zcb ztl`Uh$e1t43{4eo0e!VB!K-OL{GFAM@p6zj2-hc`5ZLik6=+KxWP9oW~iSZ7R_GY(4)Z^%cAiRowVoQ+Ej5h!^0f z7c&Eg&D+A|e6#&m^4xp(V9TRjtO zF34@OuTKK&Uo0fYzg?ykF5bG7le1s?F1Q}4QPmUN9;*lTt7xP$e_y7v;2Mv6e3^dP z0>2in;E>TY;(yoC$s_QM8?1klsgA&u?|b-SOD79x2fXLm^5Oz-$Lk2eACI>4$Ijiw zm*BCA&oSyWzdCa+?;h8s+=&efc&|JS=1Bcf$KzVPlK0#69DbXKtzfg*-B$2?IuAJ~ znt6J^fXY)*-dTK*vSPa~KRDgr`NIu%+jVzH+i}yQ+X8oDpYsZQP8a0c_M1Oop#xX( z6+^H;Yd>r9ZvMH3kE3NK&yD{qd>t0SJZ~a9!TGt%Ci7p_ zWaZsIQ<^vP+eH4$(mMrIHysf$>RZkG@@+EMjWdIo_{y6m@i&^E=D)drC9mPNHl7s) zi})_*`Ge){8p^?GY|`=7d=m}t@ugVb0Jo(sZdu4F9|RfC=lr6;_F1?~fa}*W{-0GJoc?Sam{>KTeyQukW%zSW_EVU&G=!-b%jdd=AI$`OZA!1>1W_ z{4rSXbmKj|JBwQRvp2Z#g-IInyBV?Z#c5Xw%n(=w*88ifU}nt)xOeqdyir zUt@#$H4`529?;F^pP=C)xPTjSesJ4s4#CASKln`a+XU(qEcnXS{f3vvuFjD4qY-)` zTwhz?@xNa>iO2fJYyoctFM*lz34CWaI|;Ni1@b6eIstZPzW6zTRWpxrWN(3-$I|62 z#ka%hoPeb47Vhjve1glO_V5P(G!^tIzsqyMyH8-dy#%kLp%OT*&0Jl1Rj;TEGN0-c z*w0b|4vX{21^j(S90a@j-v}Hm5fuC#f0j@1!+kz!)k=ZC+O3@3FAW4+Cd&%y`84r; z{}UkiyJ5A!yST554|`#4kxKH;1y&@L^+Q*-5sfZCA;-souze7SXB!DFEZ z{)_P{v6t~4YdFVo^LrKlmd=OZG7@C2cwr3xN;Y$T_YduY8cWo8U(E~UPv4&_U?T8S zKqjVBz|Hb6-=)pUe2aFA@tR4^;eA&t&S%oo&%<8Q#(giGm%Fbt2khVL`#S`r_4)-X z7q)SSZVDARUy>=1`hi(cyU9r~>;WU6#ugvmWwJp6Qg0z^Ri~Yl=hN(I1IHgj{3Jp1 z_w9V8aft$3K05Qhs*Dxv(l_Am?R=(SSWde!1Jq{`TE1n1q^zN z_)SZac~xpm`A*$q=buw^2b_+C&7Js~x|DhQ7V7bD(hB6C_Og#}qslFTDTlZ7NtEV- z?E{&$qv#-5J&2vUV7b78uWMVPD0=wk=d(UmF`={;~-?*QNUT7;kSBV0h6E zR)KZfXh&AfrH)p)Z+jFmu zk7Lbpf!T+eSo2mIf&FvkObp*ozk579ib}lBdPg~rP443_-|PdH`|Y@r$4L=VPDngF z&g;799KTMDFaL%`8vMIbA#;3@M=il|)iY@mpZ-S3Syz*0Oy!gR@6NyMFcaUVBarhU zm7i;H{k(^$=O3JgtSy%Ot<7I}st{}+$p0#N#@r?gAmfNq8&w2@?&^a5`bL10ztT`s z@QLyazR!xW0@6N<*)J5@@;}+IkcX`mQvauL2@0rtY~fR8tr1|=m*aJc5#{SnGZQr0 zw4eWqz*;`14b%A~IM(u?-tWa*Ca=b$kk-$eW2?vcHR%XXT-!_Dj<03>+|iIWO0?=x z9+g{H!G5!JX%{G+6v;cMAQH?sp7x2iG|P$KbG8H6Z5R1&fW^y~9u>I$MS<`CBsW0^ zlb8IyobR|^^QnW&^C?D6ytSMyeEVCk^K^bU<(qwaD$j4-z2LOJEhCxx=}$;I3KRxP zV*B{!JZa*9-n~UC8}2ai74B{ae7{J8{cI-o3YH z@cmlR$oKE_LvWl4)I2~7VEX^(LvtMJ~s zmBLlTc%QHT+)92~4i15bahm+kBDM%jE+`RTFA@=0CaJ;Y%Xg3ebaXw~>@>CpJ{8-E zV7Gz7W#^9d{NH{l@tApO@aL~t%NrZn!ryQ9pMOcBHveI1Td=y8y31giLlV$20rv8>?J;nWZ)%AL&9ocRyz zPQFh&1vIt(bL@zM?(I@M&0BSMr@(SeEH$19q-yqZhrbo!7dUPvut+n2{SNm9 zfe&Rud>xT51e`v{3SM4YE6~$BjcYC^A8+QDMz&5PA%0VZ3t)fLE{60E6RkhUn^eVuxSP8{2%W1Vg3SXR$&4g7W@?GnQtukV1o!Bn~gGW_D(Z_O{uZq ze)ybE$$YBp)!_JBY}hLJk!c^_BnN!~*QPe!DMGe_^Z8u)PxD#x^ByhXQ|c0cb>3WYk9qRzX?=y7lOt4A{Pk$a8dxbm#k&Hxy4I)!0w#-N`U9<%=cXN{nNO) zMZ&qG^C0IPZ(5!Q4%>O*h_N(~J7Bm&w2$j@od*xwggs#MVd5ZK*lsD8(CmY3ecL~B zWjY1I{SdP!nXADUawnL?12yibDre4Vldpp9Df5!y{@s+#y+VE`*j*rVKv?`g;;eBH zzdG8N`$6+o6g91_lR4`SJq3&D`o93X$0Rh3TgYe{XZ*j3tcDz#U^|%Fo4|4)b3l06 zzAn!1Kb+W?noVLey!)T)-aI?7yv+XdVD;HMoVZPHNrTI6kop5tl{wby&I0poe+O}& zoD&DO^UQk4ijNj07p zXI-%T-=`b77D+?qkU?ttYoEZ?FG!pZXM^Nmn0Y(od|VjcnJ0`pVOcHrm#B5zTc&Vv zavAD?&4$T?=;}pZIAYx*x!s~6Vfr$Zm%C%zWv(Xc^IYaf?{Hh+tL3noCc>V+05W%c z^<6F843@?`6nAvYgUs_KMs#s$BrM`;aq9=G4V-Aloiz0bSGop2n4iYO29JM`8}|1I z^XwE~%JEAkk!y`vFIdgHH~L)llWuVB{ICpc$CQcl*_JiT0LvwdK4IO~wg(&^ApIcB zA-{utPHPxP<(f85u`Ca+WBCs`{T4ca^==J-+&chL_j4K}H?Iw3Ee(jj-sTARjvJ}q z_?x)wDA-IZ(?#4lZH65G8~1|8VnFJ${z2xKKx|~ZVYMnxPSabLL|KhFi1BOrSn{_wGF*##MU{K==lT^?n`-L&r$*qko^JzzUt z#2@9^88SAU+6} z>uT`0t~7I=V%O8yKW_9-zZ2djt3DY4!Kvk*UasN>s=hXoXg|A0$9(s zeqByRc~+kL*S2ykT9C{!Rl*yrZdo^C&h1z*;?ACm!^T`D)vaLnKUdG?DqDJuOId6Q z=gqpaoF~|?bKg!}#w8^P8NUL#qs;UKJX};aXK-h4h1{P4k^|xSyKb@Ph3N9UD_#Uw z_qe8kW4C5H*ZKfG?)Ev?!R`U6)!8D?k?{BwxQ}RkO^xeGxCJ<^C#PC-H+e$l(63xG z;QnR=S=03>*nw+9ZzH%&X}@Czb~DHv(~Wbu@3XxJ`=9-tB)5GO2k-NZvD|YOaBv;2 zX@%RzrE(Ok=3+nO9srQu`{#J!=79JhoWJ@Z*F2r6+={wq!E!mz)!=3<={4o~_!Ls- zXtrd5#rI56<&k&EX9np7VS~e=;B*IKuY4@Ut5!1EY;NuW?z!@}g>NiBY+NC8m3znf z)jUfYZz#GoZs2cBT48zpx}`jy)eG@x|9-2hZIax(eXT8TR4>vDka^GN_5MDO2csN6 ztNR9vmlr1pn`JhG_b>1nx$(BCJ`}xi%2Mph^tqPZoj-XhbQqMZPX3YKBh{{a@4!c~ zV?t9|r|>T2{wcA*LTuk(ZgHh;+y@R_<6gklEFvHs!!!FZGmlK#esKHdUcDK&-b!Pz z+n2pyvShx`$>TI{65n%kUcDFl9fdNs?Y2DC6TrFpZ4OU>Oupj8o6ogYWX17*5&WqW zqBzmwiy#B%?}=M@TD4{ih0JXcy{=^lZqI?j;eP)z?%j3Md8Z#z()?2R4{XOVBcmCo17Kc@t_|~&z zbIs|L<4N~j$9*ENj&rG#goyjIEOx(qUY@6On=Dr{F626Pwn6dWx>nK73-&zH+cS9l zZXf3{eNxN)`lhas=+=E4N9JFV)mqalI@j$spU?w)uzy>vzj5#HJP&4by^rAiD1BYv z%=%!?vRZAybq^YN3vNjAS*MG!w|>8Asder2-3ozqR=GXeZADru|$E{>}n3KCj~5y@F9%dP49^~lRk5aCh!f5)P|Mv}A1Z-Vf*j{;WG7iD>a zW-aE|&pN8xz2cGi(f=`$Uq0U9TFrlvr)|S`aQ*_hCE>?z&c6qIrDU|P@o*fG5nN{F zF0}FFWXTg{DST0r+_=4rg~5BHKx$tu;Is@oXe|6E@xP#YxV@Ci$_YFh_nzc5sQ$oR zm2%eHN?6x2D9OU&=C&e^e=kKWKzbsc?h>t%&QSk2VWLI(>bX3|%7?gLiK+6g%Kyi$ z71F}nY5kBx`3oC3Ju90f@|Z2>RlUlP!F{OnAot?qth}K*zTAgCDT@lTtq`ql@D`pU z&chqVC&?X~!z$GNGl^S9bJkluNSSBw)^gJ z^Dkd+;ge;_bIi_2=djIso`e-V^3Tps0A zcs9y%T9hdGDop3t6!}?9=k+9>jw2tr{vCZJ^>vFS&(W`@JSUGS^X5MK29D#4EbKgv zYftc*m|vF;Ik|}A)46o;{xneB9ALfAqpP>Wa#2DHhr~N3-c1?2T(b^e;wxNYWOYqw z8jrERm|T~ZHJ@cl8+S;LI;&gb5wP18{UP)3%9%#W&zP6-Otjs{ozwb-+xXWUuA>`m zESF9@#ZeIDX}(UzncXF1J@1hnLKfyS%e6{&}D^&@f`hQ zBD^zGLhuuQhlSsnv^H(61YI~*&vcJml~-oc%mo57>}T~zpbxTwUVsVqElEQ>7H z#%vODynL7M%G1mIhyHhSta_xVb&vOou=vtDJgY6Q@H}dnCGRWA%(9IC1~?qJ^j7n$ z2}*PO?QIq=__&UJ&MP62O9`dsHmav(@2oipKL2OtELI*Rsg>NpmUpBR^F6rU%(CbH zeqM-Y-5E}?+yjwZ_SNfn3l8k!E;%U8IrZ=i*{09_+RA_a@`dkTCUmTl&%!HPgMHl4~# zAGqJmROOp=+=*M;;frPL&vIU^OZ7TkTQ_nAos-~MbzD*@RC$lk&GraEv6~k)BDNWd zf#MZ}XJ!2cw^PL3EVM3pHVZ^ewHMlYSWJP{>@9a_+js6qdm2ydFmoR^IUs$R?;}TQ26XRJHE0qRq#5+ua^yY9kw=u z%Z+I(o^qGIJ;SMX+L1@{odWNtBv){p&)%~H+|F1~)WBsOZ3HiWLGA>$!Obox z$kWTJ%2lFvoOe#)72cKMmw9(Cl!e;|+EWSA3&Q9AyK)BA?&Yql3I@AztM`324j)6# z95x}I?jMtRC+ltHOxK32xx4p8op;{Pb39vjP2xS&d<|^gi(g;Bc@Sh42)C!7%TSF zv}_?~1%cF@_nQUQubU#y$)0%!Yz9aiglBXFfY*eIs^##OG;xE|2}oS(P%W4BK{4(P zu@StTTr8Zsv$eqbSS=*McIzxGWX}kk$GzTxg*VtX3@qnzyn<`R(>hM3AJcd?-oM8) z$Iy!N#PM#<9g1;WhXn7lK4N4A`xRuqv%@K##_0`k`(#@odv8qVCGehDoylXmE(UC- zUFk;7+DCV|%NL}8!;p2$8L+t6*(#1T_ZZn(GkJJ4bep(?S|d2(@0x+-UY%Rd^ZoH8 z&K++c>t|Md9SO*MRM=&hqT#2`i@01^Dec3jAwB+C4>Fe(b8H z4^kJk>wW6tEqjGS_9T&&-8zwj*Hxe@GUkldz_`)oSp?mTaH%7eq$cFR1j z@c(nc^1+E$z;O#w2f{q&31IUT56j- z*Kk%0x2*hnup4ewX!EkE_wa_hnS%KsyJt`O&bjO#WR0%#n`1nFCmnb^S8n7jOOE9* z`oRMZm*8SEZdbuJu-za%kB)DK>%Xw@EKlnaZEmxQSv*SOUwAar6nFz<-gB(b3FUj= zbr`M=q_4+(H#q(2RIlM!Zp;P_Gmtn8U$XqkQ{T(UbM}oHTu#!^8f>pu(h|=7@w>RB zw0ps3=2^X9{~mFQm;ZAnx3{hg*NH#!ybg0t^AuT`^FChu6`aSG&;G%AqUj@7UKA5o z{Dlo*b6|F*E`*$2vu4pI&aB@TxxZK2@iduV=8?;q!TrQ}I`90*8Ql4IO?kX4T)|;^ z!f-9v-X(2?U~`ggKIb{LTac&uu>jX2zFMAMOJiQ`Q`~Hm&t>yWoc*2SUtbeX)4AW^ zI4V^;$u+s`6|a)|EifPChX2nzV-g3) zKQ^uduQqdJ=)L7l)llKBcHVOInJ2(!bfvn zd&3|wKeO~0*uJjn1h(TdAoo{CS3<_0*B+k3A?nc1qr4h2C&ITni1%Cm3eHOb_rP&< zKS7Z9kj+lcRhw=x<;*(6`zw4iuW*+qkHfdMoc{wLbA>{=kHKyM`6nr;792hxwvNIw z9+AzgV7sSX{L6V_^-Fe%g>Sene=X#`uyQxI-21mYYTvZM;RsTnd@2R5_t3L>ys?~! z^7d8kB=$QC-f{`sMR4AqF`sLDRSFAFTO_BWdJuQ~{bcSXl}|YJ{rcc$ed-G5`l)vc z?5>QwM_eE0-UgfPPkj&SM?<1 zjt3AMhPArHId{&l!=r*+fz>{3e6AYbc#ck|sW5Lm~vny0wNiofvb60SdK;sPc1s=T2Ip**VF0{CpDS_Sk1?ZE2AlP&lr z?(OG0bN46j!(Y(?H5P(AnrRF8OwRRz$8)Z*Hgn`$xXIt~$(%p4^ce5UTONGuCu#)x zvU=HldLZ{M9Z$c(yKT}Oo=^4$JXLoaxE6AU^8e2i1czI!n-7nzwj+2x()RB}UapIa z_^bV7`T5)4@O@>6td&Wv`T&kA-l|x>t*;xnnCw$nL$3w%+1--o&)T+w*Kt}LIGsK7 z5#VxZg3P0V{G7i(18nX@BVm5a6dkaAAaT?1PVQa}$XUo1ia!N9g#Uo!itGAHK8ez| z0#E+i@bOMo5y+i0nKkn(JO7tH5uTav?tsmzdvt=os91wf{i3$O`_kP!EW5pUch&w9 zi1W_iUo|s_Pk)_1Um#lvzu*Q=-gy_#b5C&5;r-+{o#W_vH=b@E7v6*^F8q0gUSPLq zp5)<8-JS%tdz!tQKwG31@16g0V1Ce7Yu*Vfx%lIgAnX5bsX_AAtJS>%%BxCvBl)-l ztu8O;U*W!l>$uwwa9o{K)8)0E$;&tG?i8ND6<$14*w>JXZ0qSh|Yu3-@YH zjd(7$6@R_p?p|)H2_B16kzB~XVfrGz-k)OpVwbP-t&*K0@X_rKZ~r|Lu0Ii*_$QUf z@_PKp1IO9A!>@Q`H4pMT-4No;d~}#U{Hhi2xsYJNvUg=1(?7L?*Z*BM+XXHswVN9G zmRMir-LltP;48Nd--Wz-f%+4StQQi`@V)w_!oT9~RlWd~azQ!%Fz(XWP5~Vb$Q~6d zEo0tx<>|aO4R(D07~}cof8b&Lz7KN7#f`)@yxf_h{F{?y`Fvzo@%f)+yxU@P7;E;>ya{%csm9%jf#v3Y3Tx^Kqs<vajFInuaFXY*p{z$+p#a>`j@OE%~b0~B3 zU$ed|@NnBCfyTCt0zAwb;5a(p!6A?^wUE=I;i16U6UPMhCYJJ97cvTZ*_8=|Z7t?| z^L)8Lfax~wrzNlX9Cot`teBa=&Mh@Tz}MwI?~+-|1s2R#5Hwt4C$K0aiZev(Fpq4w z8ta8=NBO>6L-zB`@rT@BG;hL9-jh7D`Kuy%!1?LdE+)R__(Cq_v#SM6-?MYR37*Hh zLu@8jUg&E+?@6|Naf{^yjbqz+qCY?8oP77Xz=bPQ*&6R$0>>*TJi{Y)@vO{)oDo@f zQjPb+Zpb=bIc72L)%(Q-jUTuQELbbTbCsh&V7WmcFPGALUY=(;;P$2T2_s$^Z$@68 z!|OO^?D6CObaFRX9AxesCLaE2xhMH1x+w~B=}+U)EEeMbeNs>$;`e%iU0d`7Vv`&B z4loGw#qM9kef7&Eo~m!Jc~8xm%(LR%G%nYo`CP02Wr54JB?){2RsZz_?RGJ8zi^Qi za9FP(z_w_=z@AEWK{tnMyc0ej;Bnr?Ca^g$4;(-0Q?>Y}BA6}%QH$$xy?cfS3LUHI&07V(;xNrA%=TNE%=;QIdG{F5d>;w{`d zEJ*^2{v{ehsi|z-O0(5LZUN!fIt6^w{G!f3 zqcJ~Jtr2*#{ugI|a3nZvJ?=y)eNPPGP3d^f>v(X#T13NK{=_?$V7VD#`MjUk zx+{U~68+E3cV*>!ez^nL{Lk00@!KsG2mA5FyLY_q^2gP$2=wti?^_H`>(Vp0_!%DL z^Ox>k!T02~09fqjsuV7cd(B{TLFRGY-U!xzQYM`Lx^N9#JS)+Z_u=2Q;P`C)Xe?-I z3R&y8t5raAQ>L)sR{wOq=WkmDZkjCQ_}KDQnfF@|@0TiNu>N%`83ew>GAgk@$`uG$ zF@aZa^KZToOF6;cx{?CTChPdVELy@h{mo_m`HT~J`D-|NW$qO6ZtHx{{YRFWPwCoj zzD@my`CrFO0Gl=G(@N#%7uTqO+!_=P)kygW5h{I#zS^UO+W z2j@Gk%&pw&_aJ-OKx#vUg!mnKdiXiF^zr_^c!{@5M^!`7W`}^O#v*}RhunG3#zD#> zhMBy4QNK>|XY)SgFJfNDSGD1b;Jn!L%7>Rg_IBJ9(HFct;Ul5q|W9>J{Erex|Rr{Hd=$3w*b8g!qSnfgx@|16R>8 zL*AUTvEcM7`2Q_`=ifN~SK4w;!|2l#NdrtLnVAkD7YE<2v<0SK7t|1I{J>SaUqj%^Uol>uo67{Q%$%q3{fa985-wQ*=DmL0^CTf{ ziH?7J1YYu2aXKu14NgD(>XUgN?c61x_gs|MTJFAp!g*i5?)8nDHWE?1)2qZ(imID= z>&34NG|KZR-u`x-H`!la&~bIQfPogjGRS`63>E$_N4W$GZyXXhfAxXDho1)gmrCXM z{WvuRw$@MODwY!#yv6cgAj40SpYepQ;7;2s0zc2+=4%Vus`R}ppSSj-8Gq(23jvGw zHk{A-^%ZnqEZ|#l_^p6hc)Z{di(Ubt$NJnYh6{KVkFl{g9+cs~ZhRN)Zk30s?y9SAxgvA9yV1>#kGf(R}hlpw@c<*N3h^zKIokxutJ)@n1HX&gYVoD5%gq zk$2@=UhXd+6$OJLqB+z$AbW$#zOGmB-KxO5O|TT4=X<9tS54}bUP58yf&6i!V` zTltS{za@9+g1ca|`!gPq*z@8FentYvmTgq`ip>`2?VZFI{O2g2Y?Xof(>(=z9jp8K zmY=axR*~4q?f7dsk4D#hu$!J3>8ra*3TW=nJw`6lD@{$b?kyQ;Vy!Y6tuM7 zJl5fjzhEHn&Sn=le(r=G;k#(w4lWn!eooOyHB9Aa%Zrem%yW&mR9I7RCc`xTiy{X6 zZ#_2iIUMWf+uYOz_AkiIIu~`pb@`7&cfodp#J*0?;=d4bpI5+jJ#XAPS>~?&kTYgu z#3lI;H&ya2`%nuG3x01C!3%%tc)Ntd`2JmC6MXP`A~-Bc4z3b>ckn1UpDYV$<#jKG zob`P$VG>VI+g>h)hf{evWSV$?YpevTU$Or%xSr8Sl;!3shOA=)xdVoOSs&z8=#%FA zx*Wy)d~2b;>;4%)Z^feRbE05(`kO4{-8*kRcY2x_ zkCDPRuALnWe4pm<@i~4F<8#vF2D<^I=S4DN57nj1!CVhG<#^m@EdskuKRk`&LE%m= z#~+qF$vrQ5ZOl!%FX_vES|eNXK=6bkp+uCZG+VLhYAsA`>g7D!^`tQn_D2ypZCtw*Whq#;AG;ISA>jr zgWNT@5fa{+#x`7=Un1@-0Lc};uLjSxn0Tz?m1%^WO#~A6yPV1$vwAXDP{U&0_})z% z0j!X7Vyad{?oJfD&d#yK{}1=9nPI$Nsvz!aV~^(+OI^lwhW#{88HX0{fiu@RjiUE+ zw)%H)v*rbJEO2T9rx%d4=ed?Vo_#+ifX!?@#>vev{VdqN z1!a&r38W5$?S6NF&2QzJ!1-d$eV%Eoo;0@-`8zkd`W& z2r>q$!Ze4sefv$`lTXXQ>Ogis)Y{K^<)a(lPo)QJfu_fKW|U9o`ObQm_w&EsoIZ5{ z;Bbj9k>S=dxC!$@o4t?LeOXg-|ISJnj? zQv&G$;Zw^+z+uQ9xr~do1hFOrBnQIohxvH#G2i5#nGV@M1rpo$8M1#%^3f5l466|C zKW&h6CCYkrxy+eF`6}<;;hy|Wn!Eg55%0=X%)HEO1-#o2LhiZ`sqNx=w|6dghtLMD z+`1QVH-pTLuulNTQD~hq*RoJ19_v|-Ja6_(@J24T#o7emw+NjnFI>kEY?Rn4;OZU(~e_O z1((TVIj)t*qqrMAw{gqZ#Pi(TB*VLo4RRL*NWDxGWKIXfX1;xuH{yFe*bN~5rCMc9 z#S^_;ANN&qe|dP1%aqfH?Of9=j!mlKJip?Pao;ZWVxQJ>1{^0K_18}^adQjK2bXhG zjZSi{Z-<8RJE0Em7Il{bg0W-jMi)a^s&Djyh#Jf8QQa^#z%oT;) zX#ry2?5XEpbyx$^-Z;)D;2U~|*E~j#J67eZzzvZOu>Jt8hkTdsin4vbwT6FP!Va+7 z!Z+4nIglAU-{$c5TkaLOx3`jSgFIxs4I~c2ZS@iYjjAGiduK1_mk&4N`O!6m(wu=B*~T*Q^VCY1~C@EPUJe&$ry?dcn!Sc`|N0_xEZY0he`<`Pb{OfAM@gxPkYv ziVMeoabbZ+@3^=`@*#U?K<2Joy@%}%V>AEf>g{~dA@g{TL_g)ds3$2PvHS~5f&k=P z+C`q4ysHkpBS z1)ty#Gq4{ycV>dqa6uc}@A z4<3Bw5T3e|&vu?M7w63>V6)C_&fJ|etROf#t%X6yEk9+uxo~MN5oFy%w}rguFbs0SAXa<*sKYLhq>1rnFIFQ zjN?!E`@E)c-aW?*=HJrny!bz*e=Lg<&sVfj?#u-;4%gj1{+1Kc#VSJ z@wL1&WEWVujx(XIhp+R3ia^pDNde}M^LW(j`oL~n|Gb|^S6-O^&P-!|j<*ZA{Ng@y zc1q6VskyNXEYBRd3Y^CJczz;4sN%D>^p1uiC@d}DPL^U zTfR*(Ndo7ktHAyN$(ii8=G>5_#2&|R0c=*TR3QIji3+fvbZ6;sSuW*+yZdO-BQU$J z$bo;kk1OA`+BQDPvL?Q5`ep(z;@#gGVoyAOf7nUx58aUQBdZ5%xN2@g?pM+A zE8^d}!H@e(=|8Yt4}~Z5g3tetn+gu+4`(-WTYGZx8ejRzzcpQ&d)6$-9ypd0W_+oO zR`Eq77xHCviwgd{^^s%y7CnL1Es$}fQ~v+Bg#R4iiI9KA6(uJP&foJG?7((NF7)8` z=*#B|`ya_0uT;S6P$S2qP&k#}GyE2KE~97dB<>}<|8N9YigB;Cf6HfR(9Lh|?8dh- zTU%f{=XU-y#%O+M>^EmwxQazb{ROr@0fdzjk^59k3tID?sKj6;HBryVqud-3l@ThTr|P5)j@nf!8an z2OP&B@!Dkp{GO(!TpsmxTrLy0^Xlig^BYtfbDZX?<>S(L#J%B33D*mu_q=JH=G@}X zKJk6go+F^j{u>;JDRtHYy@zf1Oy>0RpI8Ff8v!yCgbnLfgYB@8_Tylml*`{D6UBM` z{4f5`>sIiekvYb#klDe1*)WUSdmUsS#u_dy0X5CntS?MD!0G4asl{9sf7AuO2+rs7 zI2|f5$?zxV#&uN!mWQ8kGHzMI&p2ZX$F%$ia6C-d>C59=&?#_j_Amak!qwn(^vz}_ zU**C!0pCnxfjF%g0S_lp-Zi(4`DA4$@$Xva%yBfJS72^#sX(LQKJI%f=LqEX3JF9h zKI6Tq6ClugIhSMMqyoN~FPHHDN{D3H`%6P$;?(0jwf}H8@PBXVrkqv1?B!@-lO&@h`WBoK;cVF@@W9-#xCQue`wb|7?C5 z$@PYzg0rvaJ#VnhVa_|8M+M?E^ti*8_;Tb4LC#K);AH^UWuWkkxyH=U>dR^K@&I@Le=oMq zzxVi7EP>pK1(N%dx`>an%AM~h-ys2}hxXisTYCAP@U7zS+mt0Bap^k0$b3n@lLxZ6 zA0$2DsO^yET6<|7FVFriZoZoz*j2CBa8(G3fXju0CKLFx8mfyqs13_?glvU-%@RCH@T3Nx1E(jDn`2YLz;V1?EgYOyKw>+2^Z2H1Si&uA z(g5!NsnkQxxbDjQ#T{0?otr5Ua%S$#l`91H{Q1b~A=AqJ!LUN$;~@>OdxAa-!OJx7 zHaXsciL$11SWUT4Clm;m?mTGdJ|~R(;zDD-M|af~4reaqf0#MLJd;gG_L=r-(f1Z> zEmRpQxejItnr}VEpz$DM3EzhavAipHALsk>%EYY9{+p1{rcYqM-uchStIxes_}3FH z5slF8=2JFV@%&i$M_y+Jo1FJXK1HTxfAIZ3E6Ss}Ga6IPIJ3*SUtN96vwQ*{_wqvv z1uI&PbKiBm#@n&=HrTxa?;JR<8Jq-%gW*>X^Pk0@+*gc0@qS9_(z$U}OXx`YDf23~ zJskYAn0RKjH_PkBGHLdlUe5DW!dd(AVF@#?=}TDo(+~2-N=6F#evuUEZBT`m8DB3@}3DegOg0^oZ-=Ey8IOYU=HZ@jjE^XRz-^I`#2Uf<0k zyvL04Db4Yi##(I<#4UKDJpo`B#S*XG>ZG@(N^=_ zb_cl5zK~Z~!ShMDc*QF2@co;3q7%4yF6M6M`nVuT=;SpyF6Q;qrB5C+5ni^pn2&Ew z9N3NQwd}mX@jhVo2bteIQgP;j|JjAv+r+o>eqfr!w@$8|H+*9&+l@IK7LkijiD(PU zh#Z-}nl~wjn^S5XzxjoBCGLrdTV+&czTm%bu}k2e-3zm@gS&YeCcR@9oYlm?^tlV~ zo>Pk@7FD-$hj~ut_UzLWINWkZ(E0xdu1_lY+&umdxO^nv@t&;bl)HI+5pU#kInBTY zZ0w2;mz%dcE;j?+|MU9kdEPSB$y`#wzqq(|KI8c(dcxdPaWzi|uP*o1eaifb?pwI$ z?K;T6qN`iJWmbj=qwyr(h|M-K&MMhlzt(1h*AAzw><|!9)sPXeox!zp*F?Vh#+7`6 zN|3(ep_h5=X<7fl`2my<_Oq38uU;IlvTf~Vp5RjrTpXST7SFyP=KXHk$7?&+O8)(Z z=>n@eR`B>f-6?1(Xswz(?Uv%1ohMb+2dq=So*8U@S?C&%-o@>#m$<%5Zsu*1t&i;D z)(LrG2CDyq5_yDeR~cK#J>lWAVqxRIBT%Wme!r|4Lq>!6>(nkDJN2u)55x|F(;~<% zrMnihpLF{papj2!U(iBdKJMm8LSbvd#4mL0;Psm)!g(O$GW`CZMcaMM?aXGIw>soq(?}-RZV!hy9=L@`j-knn|GO0mLby2>~;kAmgTIX z_ohteT>QgA>h^-^=1-efaB=omn#tCf@~m9yr;(&%&hx%ZMb_xBIv;;rE8p~c?B-Y3 z9ykB%V!&PU{IB}QOGnM`FJ`Gqi`bb>i>LhJmffoaF6-aTPUOWiUfjGnI_d=nnK>=C^{}+I{O4_rOy`tY{D)U+>k{+cLtA(%8De>M ze%`LI;Uu?U(}7#2C{$$TCcX*8<*A*92kyGufxlfdS=32F2qlB(p8+VJZ zF7GUPK|W?N$oj+|Cpmaym2LTKm={UP=yGyS>Inw#3j)Rc6Yi(nQyia|d#O!gmuWl9 zyM~LA_1UL+d`63%Ep{Zv@Ywz~lgZ$|!ke`G3Ap~4@o^J49|zrJ;aUCu9gA^rlfs0s z244PYw%p6-wenhT>*D&cyv4k%RD|RFl^Lct(l|ITb1Cx*eV=dE;QLPFi=aH8hD;Cd zM77EKAp1A|)aPI?FXWwiKukFNRV{BtrM;AQ)Ks3tY9{IL`{r}lUAoNMc5?>rk>n-Z zA@Wy+I(gZ|Ce2agNqKY3{Iz7S5bGgTzSPn@{?a6M&OTl@jd!=^2%j+9!s~FrlJC4t zm+aff$*dmTXTa?)85srshx41cHJ*wJGf#QVu}!;3m{q6OG$F}K=BKS8IITv<&*4_p zcjH!@`&H6)YZu3D=6hV;%WS#TQf~+wg*I|#uZrS3a(*-C{j=ZMJ1noG&t?+5XAiHvja+oVSc)BWGAcs(`lsB96j(OT~5F zy{Z#MF7U332;_QFmty)x`?FkWE{{djmahUYLzHC>Uy|eA$D3fzslJZ0_`eHpb`ppA z?4R2eCZ$SneP!3@VE)l4Xf}79`F)$?Lh+I%>>6gLd5!-RnD3c%N%Qlrc0Rx4LW|wk z&hz|vb%{r+LdD{nh!>CHhb7#pF{k+WHZJAl`pjrCp=b_IXy9b6?a%&mdi7o7b(tTa z@b9jTz`VE@e7X^{)s}D06#>O72rry*4P4#{Gc{|>xMCx~qn#w6_d!6eF_Ry3E<1PZ zd=oyer56NRD-Liqgq-HJJI=<_JPES)@W`W^ym#mMb5^h2&wVAtp6{Kjj`*}}F(JDt zxB0H8Lhk=rGtrxGbpz!5M6rD{c)3DKx%3Wi=Jm7H<&$)d0Ozr1;gGww+(o@#dAgkE!P_-^&M5F5UD6IVpWCT`Z-Fuv4zcitjh)b){vXYlh@>8t_k+i|W7 zOlyP(@HwXK<=wj1lh42nvX{*3?RONjf*u^_{(HfWYfsHeu4B91c#eikfc^SY19Hye zo9i8HF7Gdb-3zimew`@mao2RP8rfV+-YbtG_X)U(UgbTk-pjj}L4#NO(Nvx}29R;P zF0I{Q`+fyL_O*k|SXc0XkAY8=XHTp%UuY+!|DSb8np+?ju|N9LycT#JQ$F_=*bIbGi5b{lc?!c{1324@?!nG{_7PKG40ASAN-Co?RZ<+&NDna|Bk4t$81HUgW;E z$qj6#@6W$H>kpWM+2MdO4IEFK z-n|0n9gsTxtV=w)N|3o~5ITQI9@^O>KCxU z(=3P&!goiWw|q%Cuk*~qylj0}z-mBp$oS!{ zpM3ikU*`!mjNw)GoXw}{4Ox?XC0m)#@^A{zu6NbEd(|Lk;ezzt<#Yg>oAzisul|Qj z-ammm_<9o|?O?S9D<^;H3^cHO!Ke6pPv`8FQh1$H~g9M{xaTst>H z&JDb!EySzu)XDq71JX~QE%pek&UQx!r}ZMp*~1_`2QNMVn+IY)^qa-o$UU7~d)9Vd zjScdA(kG0-{wvZ=;g{aI1g;LGwr4iv40 z^FZqSp3dc7*9=*|4&panf5>-P1Tq&fS*wz7*_BDWomaLZ>@@P{Zu|<_=W?_jQYL`( zfiPEo3^>k~ovr2an|YWg`H(1Y_6b?O)jSTo#XcwaQsO}yweZO<5_oXDbHy;NIpr;dJFd3+<88{H;WH~`)(_@9_H2+xy&c} z0rl*M1;#UZ_y6zUk$5S`U9p*o+xuod@2Oqqc|i03LCucfd=PW_EuT>bFJEb^BEPjz z64-2z`<( zv=#6bPT_@{|Kp_~c>W)x_xR)_pG)yi?yn$}c}gVIJohPTWVcJGfju!+8!(G3E_i`jwZ{e-hXXka~s(`EYkkT)2ua zG~+znT#$TrU(R#X;Z{;j`u>O+*`@mx(AUj`N>g4;<`4cRD zEvuVPphtnfzUUI4(VA7f=h`59Ktbx(cR=ncIx>?1tQI83BwLQ+evnvlk~nvF_ypeW zM93V(=^xDCbOn-I{n(06V4^%Y?2BHAg3Z~v%ZhK>4Ic1V0Z7f#g>7*4i}{s!ukXKM z9Ob=$TjTUb;f$nILwB)Wo}XqHcssUTmTzUc!EY3N*qkBHMfObEZIP=SlPvlq=5r|> z5;fl;yHVZl_anYAUN_!-7nS(+XHPQA*vlYn07Y-2dm99Ln>4`eAT*c-ZrpC&x7K_)k^iV~FwA{(jm`sN8?6`B%ktoJS@} z^RB3wFVF17qWOH18!zvhm0As%QD(DZW^($Ozu}E}Un(SABp@<%=Y4QEfx^UaNfyuc z;y&J!Qb9b6s#$r}KlJk^SM23luPX??|F^7TwV6U=2-hi%6`b#!dd%+yE#jHO&(Gtx zK!z>FC!Z(VRNG7^cnU}_`S@6H`72Q#J>gY+OV(NNta)t7=eUtcZi??T-U?YKjmZ`HY?+T= zm@hjYXvX2ahi7X|BJU)tI&LS;CLZ+_ZoJo{H<+*PXX5?a8_UzkCBV-o&cge+W3gbc zMuU98Ol{ECyxD|K;+R3rxzDl>MuBiu?WsOaA*}Ec{HnAnVf$ z?QXKG+=a{qfa1))rj7fd#yq9#uMhBL#&vM7GXHP>qTvniimm5)>aK|@d?Y{`s!vcWHh=T(2G5>)e%1xXGo`o|E|YC`d(30PamH-p z>NT7?v!jKVL<(6X{Qb;(N3w{2dt{&Xygjc>&rNtEc66FLPi5UcUW+p~;OS?2jTM*R z*PY@I7$5SkzsDr_@qUU>LbZp)163iu(jYtT6$TpMz1kpmiz{%O+ZFW))xJC~cu?+^ z#8n|D9-YiBTwScHy!Dz&rZ&u3=I@L>O?84gS+6xagZorM**+qhU)iYU>DHMU-r?Z& zlby*^QZB*wcy$YR@i|G}PV0y44<6=&-81VxA8*y{S&EkLC-U^MOyYUDL!Z~YKA!t< z+9?t7&(@;lAFYK=pB?43o2t$AGC)|!wp^7*S7(Cgjs8d6PlQWNdjr<-NCZw7eWv8k zImK_Cl*YAq^YY3Vo;ym@%_ekM@vd#;)%+V&%RBR^qwL*_b$n|q%AFG;`~USv;H<-|`%H%`)e*n#FD2+sx}-A#PsH7RGyI&QCM;xBjBG z_vV28Dz({<=Z?rOwXesyxURSDXAKDS;k%<=%010)Id7K2HuDRcdUy=A&+#8k=v4R~ z;U&oTdZ~h9?Kfk#Ys;hs9yZA>UZBe!Kg&-{fmxQ<(}stKV_t*g#%*VK{yo>_Jzlk% z_ux`NaGsM<(%_k}F`dt7uCr8%H9xnoa3j3`e|5n;o*y%=m_K!T!*O}f7T(sU&pFq; zoy4bPWNPtHB8FGY(ppArmldB}EoA*k`83GBWFI|EUQqx4todt&<|Qq>7e8C`$Xh<+ zseHbO+m1)fJna=H*SQ8m(?D%jt{}Uayl1#>n11-YQlr4&4ev37KfFs)8^Qhm-G^kj z%Dm?A-kYu=%ynFycc=X<$#_2|-gv*c(%#NnIbU{8=DlGd&b#~rFYlw{+`{siJ)+Wq z<~;51H<}xCED(C}s*_K?a4Y{UJ5@HHoR{kM9Vdi~g)j2{@Z;y>+Bh5B4;ONR?0uef zHJ3lM(2YmoPM)yab6&1xZ@&mvA6ROVQk*RPuFVyE#>M--lROVO!+757GfCbr*v`2& zouB7!_&x4c4l$9G=Sw*2xpesSEZ=c=>6UWVS$>uNniruNvwAw;M#n%Q_g#!;a)&Ee zBhRe@+k1ZQKCa(-@42OvKe0J5S#gK1b`x&Vv*6X2{>#N9Jz4rT!+vgm+Ya9J$8rL) zf;D{AuG}0KpQp01WE?c-Y;ESPZ+^_h-kd00xBDp9>$+Zroozj;!slP{B`T=%tejbC z+L-i6ZtJoC=32^%f{zdncAAEaP33%gXiCoR2rMO^Hvw-#}vT#sfm17jEVIV6qH+H=eLnCcoJ{ z$Qs$^IA#H-2cLM?876}EG6`%lQ39uZ8-rJ3Z}WZG1q~yTXd`(-=!`l`hxoMI-0^*_qe0iEP__v(8&D|>|z*F-%l*dDZl~3e0 zWc||4g^#%QHw%beo*l@Se`*(>cJC1`gR_PL&zabH{=b8qO$;)NZOuKfdqC_*UpNKS zM3!@zEjh$@LSBID_OCVkkCv?vIj^;b<#2uzcWJAXK(L?%*o}=En|L_Sd5iwMFomp6MK-ATO2ZHUh5sl z8<+Ey^S9VWF8v>oJZB64@WozO3ij*91R1WCE3bpwS_h7v;Jh)_jDNGrV!lhZd3?2@ zkoo@~-4R@QGv|sdowkm*<((ntGWoNt>-Pw7PkpwTZ_UIeZVBI=;5NF-2PZc3W7oju zg50)YCnuO46|j)6wP_ug4HDmSX*E}O!c4FpJ(XSoj+Pp5*ldo_<~O^M<^z|PMbab_+5g$6+`w^hPChwrrs9BpRe-+cHV z?~0NxUN;72{uh4RxDUil;9A@FooAZWdd>r;n%w`{*?D4bZR8X1*$p=9x?2<9j(`Q= zHrda0=lH+HFmPt|DS^|hk;OIf%2n2Ur3NPb7CGQCukULzI1iM~=KboC>@g z^KSE9U$v66*?ThAi__hF*N$@ubQ$vroW0u3lll^}cH4x|1_{4R=F<}5WZW=>XDPly=mbt(ELBU+lFJz(s|N+rkB15oZ`OCerZh~ zhf>95{)7Er`R4Ds#kXL+t3dWf)O+C03;pK!xnd`H?rY*=bACl{Wj;opTO6m)$8hHC zf!z56a(A-wQgGiO)>DuF_D_AjX&T*p0`D66ERs|O5AFZ?Wno_th7W zGh@~NWpK}(*UV%Gmf0<*9Jz+KK#6Ak8=E6 z`IO&x!wm6&!fo90U#j>oewX4Ddvh8b&T=_o0=w7)S#uh-!G76u#(-PpoTxxSkpowj zhLeEwRbH+du^fSjkJ+61IqqT)Gw*O1n0gDa#zwI|d7&rvmAhPELgEGfr0up~^Pcrj z;(HrjDX`^2 zS5EQH+~^~Ied<20=nejS?ANF9=b0a1)8SSUcow;uM?b<^AVXrazzL(<{L>GwX8)<@ z#WjDe8uNc+2R@%b$QcjUb=kpjpRq5DcU>V5f7piE;IQV1xX$IbtC!O<&_dwB-s9|> zUYK(I{OruJXTxq@ztyfBb3`@>eE7k|we4^N`|d+I0+*En8DB=N0*A$!oFxo4yERxJ zpS%ao=hK}e*?(Sy?Bh+B*}`E}xmw`t%lrJhj-_yBo3INcS@Cc!Y3}5{)nEu#zigob z>(SX=+%dhjVjS;x^PLlH=K#eK2){~cH?&CT-v6JtQzl*Cc5LaHE9RelRDdIN zF=zb8_53SeY~b%vXcJNtnkJAEc2oS6vlTc0*~$FVSPa1Nv$K?$+b{hxxLn|L;1HL{ zeaSuVyF35MV~aVTzn?BpTExp={IHcTXmJnk)|X{GSGTSJha3eSGgY2)} zxAiaIOP>>9wN?ooV84OfW4Eh{@0I^4{`C$qyk!b&!TALw4#Kx;e(_~pWarhJ-N$Fz zEx=MZl|0Wgof9H;Hzl?I^-}%%Z z9A?b3=JUw>E#qEnSi!k*ss;Z{y-JQpHCkZ1LFR(+_k$&TO+`k$8^iAMbS}8f<273v zY;W?qt6=}+9`NBh=bgp1>*OvDtNs|4*=r>EEQ%oeV0%j?xOo&IXWXyqdBb^*y^Zf> z;A`HEHxqeNW(0%V8TNl2!EWDst&xYF_d57Y5jm3|+|&2)^PQe`k-P7^KRBLuPfg=U zu7})<0CE?Tb`0458?X8Jy6cvL*&y*9-NG!YnTcRM-FZ9t=SV~5ew#QQP3+{%~JHh%7s@w5R-POj+?Apt>%J(;??He&peT7VZc42A0 z3p1DVd`x-E9d0JYmzy-3^KxV&*W4Xp+bfsk{sSDg6?7Qb$&!~aUuhC7w1g}-dQ zJKr`IPR=xyqu}^xmC@$faAhjDwT3wN(gSa}YFRqi*Id~P*7s^t0sHo}ePBO>!hrR3 zEcezs?0g3oIdk_zP^;@~)}eRpP>|hfMUq=Gt_x=ANRX&MPw z-_PwaUyAR|uF3q@7D3i+CrlIMpYte+H?!ptZ`ldNxxgTE_nn8dMeg|6vqs)p#wX+T zi{*>US-y*__VQ($+VaG&Gv(vj6v?@<5t5F(LUh1k$|wWbslW$<1G4yPt(7Ji569-PO66Zt#tUE+UYDZ=mkXcEhf3sT@XW4zqX zdu4SpIInKY(gdfs@|q_+54I)qF~%$cn{n1{1D9511lLgk5B}I5L)L)5+d=F9IF@i< z;!bDR;%rMi!GGZ7JC4tVd)U9QLFR4+>9yjkTQYnRCE?dp2E=!#xXf7scKM z+MFJi3;1Ktu<&;;Vdhx*Z42K&b$_n5|LeF@4`_qOx0e`NaK3Ug+%$2+Ok5?{Vl-FNn4*z^65pE0R5?=Nf?R-;TOy*yfdzH`N*K!_Fzk6K%X^k9e z99Eo0i4%EZ#2#=j)avDMSZTvGg(DW6Pc%dY_?o}2=ilth#LgS_girqWCBBuLr}1xD zeVU&~f`MD3E|7D|#&vxAdxXJ$=wnFWK3xboM`mJ^fWXI}JUq|eXY+18vY0c`rj0+Q zESN8DN(k@7ss}tbAJ661=SSp;+p8yn{WZ-C(mw?GW3>u9??ewf4#NeIe%1Ov#p_cm-@$YjW7^tOn;hrg!Old8Ti< zF0j||aD4f}8DRF5Z&lqvu-t#1ot!t1K<=@0+b79$I#`hZ(dHR^XAW)U`)c_B?8h~2 ze&F=oBJ9L>Tn=(~uAtOx9>y@~9+MCnMx37Aoz>EpOd`=pR`5SKuaad}k@%81a z@p!*+2b+63X)1sE;#@wfq@Vnu3lzDh7;EvKTDMamxl5A2RY8U?*NBtPk5`u8z4jl^ z&pY{?g;FBCEsBC1g~w!ga>TTGLxj8dyt?JV@v<=NCbz2fB5)h0t`f_ z{rYO@7T&)L`uKA1+xmHlvteh*rcU$2uU*7RDZs`Z|+_#iC z`I(ln3TQ{D3dG-Vvef$?T&FT;Z)*V?7jdjfBw%+ zft4Gr*pBil@dlps;A7}`2#yQRFAF$lJ(Uz>dNh&s{u>TXkDOclHB;R9|A<}Vv$RVR zxSR40>`#zeHi>1hOK&aWW){2z4wtRlb@*fUJmlTE+=1&s{(TOm4#a-bBU-z_Wm4%= zZ~g^!X?zFX9OIMM+|K71WF^qxBEk18A)BWvOqAbLhJ|;TE~NjzqgILcnu!Ac>$lUn zOzV>Qk3ZYa{j85&(9wDhdx_$1UN=oEj;Yb|VE5>2z2iCmUx4qt zGE3I(1A_c#)`#;1N;dI*FHqs#$G?itkgtLNUwRbp?b*lqS>NwxDd#={w(oD=IdFRU z=s8-LWXI`)hk8l0CJ`1oH2n{z+D!Xyy#ViLb9?_{2J25b4F+d{a* z>tn!qbl-19Q2(D}-Z5uzIOzMn<(1f@Bp|ACoQ=sgOJM)&c%FKrxdMj*S96~YVG%IT zTE+c78FJo+MBYZ8xw9GtvRL->FDiwc378{yiSM!W3IXYbP6C$miUgwmbnw03sl=yt z@hShL4{OExv0?n3+ycc`C1eSb0AW*XKF#r1r?>QM6t+~Fxy2ARnU;^LG&Boxc*9nB=>#67D zd6_P;^2e{=1pfr`+uJIS$hQ7POw*G1~zgHaFfp=Qi?C0q3bFi%d9=?7S#&T<{q` zx6}l#Tf#vC&twm9Z(n{s7KvAaj)k=JN$H z&*59Y@|8eU_$nTkuBCh_GcNPn-Zv2NUwwoB)RBBXCDuhed9Dw69tG*~W2VwF1A32NkMN!l=l`UYu<~R>5R`(5Z&Z>o&8P~Mn5RM%$x;Q*CAm<(} z*dGe^GsqkePFi=Cjq7;^`|H0h9I6$w**l+32m8g^1ada4^8*9U{Z6^y_5w(~U~@cs z)hfu@kd7gjIM+uV0h^b2eK*JbjdGmo)o)m{Te~?XPK4a!a*+XY7fr#Oxo|&x`Pt3o z8f(J!;P)Xe*FSb({dW(SaOTW91GXDv&yP#OU~v$eUz!Wf2JvAyx*4+G6ULu*^a!Ww z2|uo+NhMspN*`IO8ZggCZP?n#YHwc7_1nJ6Hexyb`FMXwVdG&4qPi0``L2% zCE08(Ap57UC4B^|1KHtsQxNVx5MR50Cz$`jnUQnPX$H>CK7YV!t%Hg<+dpe_PL=x& z=8JM}1;-0W4+wuc+R1fn>rFQ2Ge#ULu5n;FYh!8l(AZy`p>vAxg5?Me`a{t zFNqH4y0KmyEWgJ~0!%;n>BIF!WD)zD3P`^SWd516>hLrR;=}OW;2B&&mmue9fyCx% z-Q);+wu<#c+B~pZ7v#U>U_P4xHuv$98E|_+YI`IhX%NIda^Vpt_us$ZboDXqGl$f2 z8?f4C(TBi#*|tK`6-aGhU@KVNb*)rRV-04mDZY?9a6od%SSI2S*AC~$Op_KbU^CoR z%hg{2NjF#ir*Rd1eZmnEyOEQl)CU~iAboPnA#3E^*yeNY{IAJ*MRP7^qSIQi{gv~D z!RjveZRYgsJ;9kfFAAJTk2lJ4uj3Wqu2L-o^Fij^uWMsjaS3wI%cjX^ID-m9I454X z3wHAhJ;;4qt?O&qLsAjzh?RFw1&0?%e-D!>r|uMY&WE*cIWNs$&(Zz#GuRDT=h?VV zWkb>_NF4}Qyn^(tGAD_E-3Jmw#)|jXaa^v{;1d2h7u@Fo$-P^Z3Aby4gFMGMjty|P zOBjCOdMO6k>%U=cB3I7-CU(XP)8O*|X0mg*T$l^if7%doCN9WK5T2Z;1QxG+)WV+i z?-gs%1};|T51E`&`Fl9IC;jD`_BoqV%R!oJ?%qXUbuO-ubHk^HZUehLk2#X#d*?+? z52vY|7p{b}%LUkj{Vi2`9Gn)~&a-fCJrCK_{r{K|*ZrIqoJrS&;BEuCp>(4)_sm2+ z&YLcLT=Tpha|YaK;+&9sgA>&Mzrn@;zQcxVsR>tk`bExp{5;&Ae-ZmpZP}AJ+zMWR z-3BrXgy#x9;bNOT5iV9&{u$2ZSX={k-vvn>u=_yjxxOOC&Z-;$C|om71z-}9-NkfPVD^c$HC^RB`txQ^?uo5uv(DbB~xqJCwSR{)vQ|B z&+)HOnA4z6f!)yMB1g@qY$j9lTY4)8px|BV42E~jrqbA|j)hnod5Pop`7BhUOA z*JE}jxOlD)UevT*G+ zKfqzQ)(e~lKHf;B1f@5SFZ(#ra~NB$vl)NT0Fd93;0ozm+;#@+e*ehZ?C!xvtp6siWHl;10v0pmvqlNm zWi2tB0*~t1EfgF$4I)xGXU7(R{rrLd9hhF;Tg=fe!w6=B?3SG%!ZKy86WENkl@mB} zDtCb8#B1C*96H`|Y*2a2Ca{^GvF-%q{)Y3MkoLwW+fKN9m(1zq@LIscRd&vjD|X#% zu=u0eyBr7o4}sYrd$we%gY5vZpKf=7i-Y(uEIS!BT*UarIW4?2xcrPya9))RV4t%v z6dw05J!iJ<=hP{f#kInt5^VmupH5uoCC_q{ZClCCniU@-D1~tj`JyybECA(7INHXVB!2K3`rZCl*Bn^>(ztxDQx0lpPf1Z>|T(55Ki^s z;*jx)=WL#Ll=G*S1n05so}79=t-$VS+6X!03Z$<3R~JXdA|9|fi0_^4#TA%m2R7>v zGo;Stc00&<^r1HAn+gwb8Ud;MbXW;qwt)CBe0zr?SF0W5tbdT$*Pogkxsf6)N7(hi zY41z4EXNNvCve%JqL&G`7o@h<#S6~2{rZ)C!m*QJevH;u4v!>A-7;DWsrk&;bTeKMLCXhKN?;T~IdmVC5MEVhBt_$gB*e_LEf#qYn`oQL#-aV7U z{0?Ls9Hd9KR2wW0VlVtMjbpVVyy_A7=fXxU$QIDpj7TOkj2 zAES9Uia1CPgoW>Rvwsdb$$s#AH&`7=Y@@v&oc-J@m7P6u8Q6S~99#NbPUG)FV6!fy zA7Q^8c!GoR2jZ@iD;etSGZJFK@@qakfSUu-``hviSp1M~Bm2jtX`Gwiuy80XWM}`} zXvgW_`I+l|5F=+!?Ng3DX4}E(VSNB(p61*kNV-0_PlxkQP!5O6zRMgRS>?E5{_%j# zvwd6urZcLxar`+32|t&Q$(*&z^*P)BLDDYBeh^mV+|G4u#w+#))_t5`HcD|VG~-}A z>uSK2Ftw1)r;8u#&-NlMt~nmAT(RsLT(z2zz3d>pFV5w%g>HtlH$i+5=5u%DdX%yi zY(I$qxpzK1o|ZPKfz5NCJPR&=PFE1l*1u`ZB@vzrRs+&2Xt9KIhuBPTm^~}j;BdM7 zo%6uv1MJJ(Cb6C9oemavXSfOu8<2YQj~Z~c=@t`Cor-5*v$+p5afGk<&9Q0DG4@DH zE6#%I1B`@%^PL zY=`|0a_qX{&S_VP=rgph-oUX3WEVK0v$2GlgoHZR!!RltRAnM6k$EI+$*ZF|OgO#U%%}#JIrVd`K6NQht?v6u(}1@R~Bbj z7;oAn`&sd>Si&Az@I7t2ME4}>l1-#C2b9XOK{TDs+yZpN7&wY`{+tLU6Km#nux*TuV#vi0?orQr4d*>xV~JTD>pARW|1E!^FjxprQQ z=Q3xy&&lzpmwQrHIC%Z~-5GK`cb4AcUOgd^d$#gwu30Pk!C@i3{1*4;3=xZBJsx)V zB})}Vc-9HesORH-a_=#hUf^7w2OLj0I37+Acs|vMvyN@LjGnTp2&hisW@87}Ki&(o zxGeukfycx)u6o9%u|JBhwB4Qkk}W^K`CIJYiiODLR#CIK)gt{j4)b*G zzs??dy3o8uViRk?{!Ce!m|X(dO9FV+r$(Ajn_tGG9hb))6#9fKG$od6z40{3{Jci) zc|yfJ^X@6}sTTg?%jDR}b<*oL_msJiy6)&*YdP)oE8Ipbnwp?+%Sbp`K z^E8!Z(PEklKk{2l(Vqy;2T!Yeq&^wS%H1o{=Y6fKY7V;pSB_6yX!_E%7UzP!c%S~? z#4_XUD(#0NTg;+MDkRPa<#XQYTFm2Ks0)q{kUM6l?crqoJz3(4XES%^&13v?EFAGEFAn;-rjq~_3~$$ndSFS z=HHsGg4g}eW$FdfH9TG-@@)H5r5T;fTl98tAKCSdd*wOE89fK1B*FO|Ie;iR#}!F4;iZ=V04=$STIpltCx?p?pvm_8D=<9I#y zC)jR~TVLwLNVZr*)=XNP?c(BhZK*_{ln%GB|+?LRTFvtCOiVC4?*dz z<~>_nL=Cd4!0Ej;{3X|BhuP|Tca(A5e+s#KOqg{i*R$LW+({2oEMB-A;&h0f#@jNd zO|dB3hnML`l;UBbL#B`CO2{xZmxI?pCm%Ex)nk(6-97O;m+g0d$=WTecn&0A=T`bD z&eJp%lJ1K~s+rWLoM}8^*(c!Z|KkPRxqqHXwD_q1hQrk+llwXUSFZCN z!91}l&n?8?O7e#7EtTO?Tge%*(U|wEOCjrQuV}FUkEy%{)9vnC6fbYt&8@59&b?Jv zl$$Ntgy*{8Tl2a@BHYZz4^0=}Y2{{Z3gQlS+-2rm&ZwCY&(2%**OEIvMa%#chB;S0 zvd=dY=8MsEqc}pk*tv5PdbvW}`FW>EE)(=f*e`ZL zWD=LDTDFDu23Nu2nU-8NHz9iy3`96J!?!02HDsRS3A*0TbM(I$IE;>5xeLyB&tAOZ zXf~b8S-1L;;PHP#JbX4iLZVLEW>e2K$gH_k22QISXJ+xZ$Te_nm~{mlM$UEGJOP?r zoKAveA`^d2;)zcY<=v56!#yea702;LF&Vo)ZmmWe6W-h-YJx?Lg62~!l(^5l(gNFS zvSJ7KHrEy4d^&~cHRqk2B%uz+BV29~N4VCVekvX4uF5lY&I2CN=^b2`{@C*@JO#Pa z>(Ze_i}DM1c~1A8;dCneD5&y#J!f9Klw!w51~vWy7QQ!;AzZ(LrkTb3u#xvm>$Xtc zwVHRqsWUSF?rh=7-SGjO*5Y<-=2}q|V6G#Pq4Y1^lI!B0-P}%W?841F-WG-_6Ty4Z z4$Ys=qw@2Bd29P0P2)?ec)02gSd<)`#BRnb$R$31s>Sd2Ox~T3PV=b$^WZ%spT-qE zwbR1SD~`AFkAybQ*IV2X5|g<9{yVFnAk!)M{M8)(i}M3C6en&K0mUl_R~$G7PUrF_ zvow6}dGV@V`^T>>J6-N^><;clllO6-+c|?-A*4n?_eLAbO^fBsRh^wYT^^7#1B42@ zc+RYU!K5#j&$GICCHJmX`I6sN4he1v-^**^qYFN(nOkr^zxy6F(-Q4E?k8Vch5er` zH(H#|#nYw2D%jq7NkPGSCcpXAB^L4eZgMStQ^X3(N-eJ)jpTkGWMq-NuUUgpwvW%~ zb}xU(&L;v-yz|UgZT%)Rw{iuz&QlCa<@M?564`yPLR2DWlEqOwA>Nx4z9<+wT$am< zv{RBXjS{VFVqw|&iK z7-uLT+jf_`^y+$W89wXiRCDfgdpK9C+VN<=F1FZQrp5mz;}Ac4e*+iGt5e*LQ>UA6 z{%*}zy>v2HL~RCtSLA!X?`u2xPTe&YzHE}kE_X$W$BQx9LTTYe-njQ}3Qr35i^zCY z@vL_L&G(~aF3;l|aooo_S%p5yed2VgYLh8p+5Nfyrxr9Tg`|C&mxv zS5$xSSjB9UHJfr&(0Sqvf#6rO%{NwERIgq`! zAhp{5_j!$~V^wk&@bYQQpUov>d)i{sZCe38Ee(M`%R3c!F5M}>trW`bxvEd-iOLey zf)}5a>Rt(`YKT42cyrdzg6Z6Te$f5DwH$iV-gCm`Txx1~bX@w)LHGY|i2zC6cldxJ*$;X^^j7zi8310u7k@{;c*c~P`nKs^O8$>H%DL4n!e~HkBrDo+02RvzTpI*X3p zXMEiE43%^w?1f&4CGo$zxXzSE!iwMK$R2RG$+`yfUQv828B*^p$T)L4&$au0{8vPZ zEhc_z;M-Zrz|;8K#o}mDCjVjXzdT_pc`f=H`S?m)znE{&TP7-Y6LKyh_u_W$O_fj8 z_bxTyG>8yq&57T|C$PSei!UukK=Rle3-+h;`Hi-_@yF&>Dl*QK5=<1mptxY_TvL_( zAu`63nB=ccQ0CUneIyz?WfITRg%R9yKJSp^5_IBeohHPu@M5)q@*X*Go_jCnE+Do~ zg1_k8N~u#v9&pv%5(3{X0*d=fT^sr9K5Vjh{fwF8%l5_mPML9BymICO>*dufy`2{E zOe|oR^;7%DyRz^y_g9xf7TW-O(ELBERK*e=(Eh*q!p{|dv^Waf_+G*-6`d_G?X($p z)m#;e#(RdGu_Xp(u9xdL850u)%(P~i$yG&a%EitT@T?OPII}7RT>s1VZ{U+T+#~SO zR!(^GyBq<_6&IzZHP7NZc937@`DQ=PRWs%Y{N`;F@cPxmbNeK}@Yl{aVmfJ>eCAxs zEx32h5bD;j;#b|GC-8i_7MI`?R?WX#4hc8y$`&yH_Cz4Xtx4`+L^j7~`2=pz`u{UB z$M}N`;`pwu_7$GM|BCC$wY|a&?8Ro=GqYs+0 zKJMB$Rvv-yc9DhQd>kLp~xn4QF5Q^jA5!g6Qlk3e^FPYy9in;SP-{BFC=NE9; ztHJj$VIhZJ%unv5j~guv)#Uk;mPB){IdE8Lrt?|O)s<5f`DQ1pRjOPTxO7aH`%>aB zGu<6CA4mqYR84jlX4IG=R|u@!7ovV< ziz2w~4N6D(T;-b=^-YkwVmH^4 zwvT)pT0414taQO`wdaer3n(_Zb9X4#@|P^dXXTQFrpCAj`?`V}D1 zbL*1XxAPa-ee|6~6#vaI>6&H6Eo*j8Kw5gKf^={Mzn7@DMMK*R`5KjJ62YHxE$@V1 z;__@zuuPcFsG(}Tp7%hh4FB)#_XOU**k}GXd$!2UA1dJe|EGVQ<*pLhA@*tOD$!5H zS1q#MKjpc1T}N@-%7yaBwni%XEH4tTY+~W~EiseZj=#hrYbpo-?PuY9PZu5L{-$w2 zc(VKqo}YZr1%zcqz~;TI3gN5Qft)3KLxRJi!f_({n{xgL1;2c0(fDr{ z2hRt8o?9h8@?TfSXg{Ci#>IEmNmsV-jk)HGwOnGW*75r@Xo(!&+alJG4LM_7Us9E) zuHgv(zQ+apE)(*&*ZeQxpT;RIU_A3W_kwd%C9gK_<<6GYG4s7s!zE$W#lJG=mBrJ) zOZg%%EaZQ7!GQC?Tutsat;rV8FNyL_vts2|E!o2-^t+i)jpsODCDRt+WwH}^To?Iq zHyOBCERM6_Z)AL-$bQ#Kto)?{k4T*Z-;6mSJa5a@xdJTK3!Mwx&+g#mC&TLfN+hZ| zfmezRvd-Rm#S`AgQzXITAoVY~xV`Pzg%X}5aju!yE3lxMCEfmxt`}j}=19n!=Wpf?pjKcOx6dOn zAts%_ptCfEGS9XsoVgGp_ObMVz}XjTWlPueakAMg0@wcyU(E#O?C+8@&VJ1`rM_RF zaV-mPa5yJ8Jy-wz&aQ9;F<-|2M@As|&^=-M-`Ttr(@7px1Ui@@iDVvE!t;4KMQ+8dm`6bpqem~i0F7^|Xq!-Pomb>n5 z#Ivic%Hn{b0Y~++?ZOL=zqLrHl@-*zet~z%PgxzaHEHIof8wOn=dI!kyl*A&Y;ObD zU7&pWyZ<4_wWJx633>Yk7}rk)-EAq{K5M(|^JI-BMxPA=eZILu+R9>TKM~zpP*)ci4g#;B{Fot;RgzMnS57w|wCLsdto{ z+hUDCvG78!brL+HKWYL+HHFs+pL#1Ncv*TUZ=__3P?g3(F6{(v(eufC+@7Ut%!_Br z^L)?UEIx%Zo->qPS^Ddoy%vW!CUT#=zry^-?H7D?$GdboZ|L&4osyEf{H~8XRYLn9}ZYwGA@bs+FYIw?Ed1mz!etUr*N~NbdL>Afl34AZ*GQajWh<|iSZ^Vu^&b#;nWyJTIMi_U-NEuVbjUcp`hAzm%zmw|>WU3jyCv{Pk6vc>YY@Zjroh zHE;5@dFFvDzlh#@3%Min@M8{crmupUcZ_dx*<`7*Z~ZZ!x3A|J$5P*X0nLkX7W!*S z_#aBf3iQ5JR+=dMNbvi~SxP%L`kOcZ?U1=3`c;9ik%doZtBN?!IWL|SvCdq(g`P;( z?Rw3vnPkt$?Y3Az>fk$p?{EcV5rHw0Raoub>39tX#vmWsuxOT_FtlyqP zrMQuw_tbh$&gvfmcRq<*2HCXnbYEE{dnhA;`pZBGO>mT-#)s7 zUud=?*G=DRGWxpq+~<87c^a7K@(cf+%AX`(!P#o(&S!U%&2rasTRwv~p`4fgP7^-y zX$n{CO>L!ZiY022F_#6hlm793W)!o?lWRH@5m9R+ z@I7ZMImuAw~Ph z+YbV_^SCYjk{tPzS$g=7{^+pe+#$u=U;m$*vweoZndcQ8n=LpjCz?Lx;jC)azUqFS zD{<{ifi{te3N0U-gjPyu3Ud72rkVXf6~3P}rHUV%r}GWFwN6Av@y|2+Do~YFEN`Z3 z&s}D*g6sUoblz`!Zi_rFp1>-6(oo>DfDlj6V#rc~ zU1K;yL}K5=5I|ttN*(b&$}f%kN?%bqXOb_Gt9QHO%eKM zKNCDQA}g_wr?^EzBxY`ph~L}~=Ios+Jh9fo3YS-D%N0FNR9t#I64d`^-hRZ5+x^82 zv)(IVeA6!;=L@Jkz{RaIQE1;310H_i^8y`5AZI5}X4%Ob-Y^|p=Dz7}GGDlujeCbf zKEKexE!uTSErR~JY!(%t_1HX(A9DMhIw+rURY!AO(*~|{yDhXWS2LQQ_O<6^`^_(~ zP7)@31Z|Ks7eEquW*Am;+;zLDi_4V*2|{z8ZAzxyn{md@D% zOWGi39>&+&TP&B85~V2tLXyyd=8S=)Zg(=STc>5>%~_7?>3DB8XYgVyzgG(Y0v(`d48fP zfA_~zvRuJd{4=h|gUCavGQH{?bU7LI7@6!UEZNc&j=U9r!rLPna*>gjBG3Q+ldkr^m*>NdWmVZv? zCmChSG%ij3?R*S;|9LrnUjdK*-Hi)n2`ZBVw}(M-GIP^^-Vi1Y~YJ3u@YEUw9J$tKGb|?9;caQH3RRl)!yJf z)#V!uA{sYWsH$6UFtcZ><3D__jmx=&Meyv4`8<>F&f`1J-OW`{ybav{-)=RZd;i(_ z$~Fpr`O^$txmny)1!leS<+iflF8qE&r?3Z8qtJU_3BkGbJ9v)f*9aaq%H>jd#w@bb zHJyvcz1;NR*KF>o-u9x0qHc2X%$X{s^s3OjAgGONPj92y#CwLk@AF=0Dwj^@esow} zHb0Jo*FR(rpW=aDGu9Sfi{|qM+%3Ji8j7~F%&pX~^4&Qbtax+YYQec@Bl$(r-_^#2|8xOf0ui;x&PHXzUAW2IHxgqn`dv#v>WZq);n|J-hK=ZZx3Pg0?i-7Y*vE~D=hW;eb_&+E6-YqN&FLU@#J(J`6WfIzB;RK|S@}Weu-zro zB4aW0=7MpB0!i*eT~Y~Ttin!vq%hOCHs@JkM*bteT>o{Dn5 z%jjV@YThh;YeJjmML8wj>lYaW=b215V`kXL@-d+gTt7*#*}%cEga_R3`KY49x%c`5 z!Ge;X{9SLCa5_}=NQ>Q-<4RV%!hO6-oBvZ_0I!d-80XGvWu7!QQH$!|O#EWs4sb|0 zJ`hX{ui)fU-=NTIQmZQNcS0a2yPR|FVOO*0{*Q8d%VjL4oYEKg&Fn98=)@K-&xK3O z?=|k?*?m!*@8bOFW{Wm3C>>=L;`G(p%UNi)O~{H}(8A3@M`+s{39eV{C;8v?nwY0- z&(m6QXq$j=RI^3;-6PzmIM?tiY}c{q<~+s|wxF3iJN>o5ndcRpH-nTcrnJcO{At^$ z)%p4!=f{7G1QwUZDx7YK6+C)XUcmgOlzQQ*LiqT95$hLlc^5fHUiF#E0luw;KlxL| zJme;Zh;!A>YU7@}#hy>&T8ChpZXstGlNi5ed=>Yj=r!OugUcsZ3QR8l&E5KhmwQq~ zzQFBE2I8xD&Io#c6&BpEJp??yVlah~?|Ilma2vz->@D88hRi&7ibZ(mB%ATuv9*KC zlVo0Ru)K8iBR+c>FL1uw`+PdQ?Bn_n#}|+k#$R^QoyT`~F)t`jz_8pYV?L$6CZ1O{ zLVQn!_waov+Rv%Cayi$Y>x=j}lp*IwW_Qlvt?*ai+QqYkN8!|J-prU2yc?rF2-`?=}~&$?m>-l%>_j!8OKdG&gy@RZdY;qE@o!xwVx z7N6#tKCoM^H=f~L(Za&JOj?kad+%Ys+kL$pd#>xi%>|kF@Zt>KBkJ3@5<}H_Q;alu z`BUeC<(X&f0@Lo6lDsnS{&7ExdCWfb)kBv219Nzji;jWKKglqUN9Z6ESlyk6FL@5E z3FPzpzmE6emb2WI;gIuSe|ji@)pn(-aLriK1G17Ke&bKx>FQs3=gD2<6}7trE(=a) ze&Px{tpYX+r0C0g6EM3{OpGt-qAHjT5(nW!Jtx5NES6Eof5t`+95y>6O1KU5Tlu_v zGrt-0FU&?vE{~zz^Cq>+<+_S*?`}WE3{#d}wmr(kFSBuY+N13mjUWbUnrkn>%)etN+jvQm!cNPP}Zm^mx=Q{4vchv|?z=Waa8;_B>x?3n`jzv^=@ zw|>M#-cTK0o{g&)@+_*@$rJnTE}xK$4`1^2B5v2N9NE0uj#D6Kb+S9zgTp2ItU6!Q0v6u8ypT2Jo>~elcE+~g^bWEw_=rOcXzHh-&_tO-ljuAV7vBzpA6prFE3*NE-NO;$@1N@oy}Vx^o>{X>`vah4@Tgo2W?M>n+Y=a{0T_-RfmXiT~Fxe zEBbec+vPwDU+G1Sd`qOvc=NR6xy=spg3X$^VL6z-aOy4CoMn-Bc<1HK=PUAx z(^55AYadOU6MLOjL1Q9QisXM)vk7wO=+eNCCaG;T2;@1nKfb!Q9f z`FW(GLij4C$M6-nNAs1ul;T^=Y{h$hl_u{kNkJ}#+!K5X%jWU@e<8tF{OTp&&u23H zfBJ9p+|t^|=ekImeO=yd9xoQip1u#tS9m3EPUHB){h06m0Zaa)mAm*F4P65c zOl{)Y9A0GUd`1*My?{IKUN;3ebum5Lufy+Noc-~=o$6a0rS#LMTb_$OY*F&(m zDZR6~r!el}+Z|WR_wmGIZk7FsyoI{Id7Kg<;R@2bV!92_hMjjf?+2}8>Mru(i+^ni zH#b2yjW^ptn%nj29KKcgb=*PUxABO2E#Wm%)#sNA)ZlxS@r=8*;V|!^2TRyGeoo@N zr9FwKE0&2z$GM69((y&y{573mf6t9Sz|)oci!WZXgnd8DM!xukiG1QOocVvh&*o2_ z`i$r8rgF|CBUZj|iU+{!`KmHc@dgR60Q+;!k;(iA8z=Cs;o;#TFwl9iY8ZS=>^b{~CL>~Ca_m)xDf}`=5jFj41F-6(K7Q9t`Tzen( zn-@O6q`tE_k#F`!8~#T#rwCkWVlY3gI8(^G>nync&-2Tgr+=}9u>Pt^A_d}y%%zv+ za(~!N%mIR5ydHf7s2hE)NmHAs|r8NMB5hg&3QG6PdKKX(`>?iA@*InxXVs% z7TC|%4>qsV-Hb2vDdb+>w(5HGIc-8*J9v2bqoTca3b;QB9u{M@(C^sK(sz%UJ9o<~ z`HDIn&27Ihty%9`~S=*`SZ{3ddU~n zCB)mzwUtlp!gKz0bH#Y7|CWRM|Ke|X%pJ>ja};;Y=gvB~&%8A8E#K~mbNOdpUdXAo z`v7N4;TbPip zpnmtR@HF>U&SQ^tl)}H`onwj`VraxMGyGo_ixacT#?Uu^16Td~Am}d37WofYbi|yILGq z*T#X_AhpvbxALwmKcpNyp_=!p{cnyhyPue+v)%|M&OX z389V~aTY>lF9hE2wdK9zHA!1#vYgq{)33!}+pOdJ%wR4Mx2zppkAvK@%`J%|NRv&B z?cj2O*9#i?UmuneI-Hd!el2S|&nZu7PEngSBak`}W=+sDKXv7r;Ef5bg7Qi%;^uzS z`QkQB=KIAYB+%sc!_;1Fo_XDx-==dK_;^m9mk0N$Zhn#$mXYgGIp`Z_R&mRQUt;?t zuIqEo3QWJ~&Sihfjn8bE3)k1Sso?U-K>9e>M3rXc%BTzc8B8u*HcUJMzrV3@Ni5zb zY+$-n*d^zoQ04+ALC#h0xU0_{6}%F-p7VZ&naI{jj9d&Et4;5_?c;o?w_D`fzg?W4 zYHOtSsHdAR(`@E?KIMd&S<_>loN6&G#$_VheL|eFTqh6nnCPtFFG(si-5+IOQT1Ps z>x5C2#<6Wz%xm|C@rjmYDG0Hu3oTgQ%D*%)-!#2jmp>GKK{eN?d6`89^W@`pQbxCf`AcGOaV z`}vNFC973U+I442-@I`~_D(?uw^`Cskz?C9x%C1SIptR!k$7IG%oW`|n{V>#3W2|G zyTSInUZpJ%ekzzxyMMK0PTeB*ON+wb{r@)^Tlvo&kg`y^d567yr3SzL{RWPJ1a5(K z@1|KW^D%N4M%1Zr`nJp}HUPWM1^c;cipeM3s>E;|hclUC> zvtP{2{NW;B{o04T=eJ%Gy7Ebk(=l3Kc%I8L(}}+Q(sj-L;5jaZ_N`n+$M$nh`!-op z{GuS&h555M_c4Cw?06_IoWjq~X;8O7AhW8FtF@+u{hrx;=^d#{H7|c;=4BQ9EReOb z#cZi*EJuphRdE0RH`iwN^vvJ<{u4g2yuFpgF~JDcpwD>K3*U+xhQ-knJ38Mn8^A2F1y0*xkpsu|THTh4;7QUPP%|7`a{*2s#igQyrVI`n$1n0rs&VY z%Nf=b%`VBmTgXp>-9n>zve0H|P-_TOYC2B`C9J>+M8U?-qh>m+y1?<3bLsXd%;PFnEhALbE^ zYbfFp*f)jmq0kyG@ikY$ZHDSCodRojBy;s83UfXAt0ADu*(|R1=dB>?hZh1hKRChj zD}S7L1#Zk<0v=!K445Ur?Y5IIJC>by!t+u=X7j7ycGp}@U;YzQCUa~yR2O&~qAv(K z|M#eMBsgDy-1y7?F28Y*o#3%_VScA?#bC2Q;vg)AL6Y%5e%;TL1ul~ z4ml$R#J1C!A~4_m5D(k7IQ|=za@!i56g4)=rI|J~*U zuO#P2z7};xp3d7H0*T9*c$nv`<~wjpgB4`f%GG-~tTnj>bZ_VK3-O-e4P$WUD`J=- z5I>!VRqYdG&V9lyExrr?A93wy4&f1$%0K>RyL9>R@`uAb{M){8cN_}h{SoEIli<$F(<*1otG2?M|4la}p1a>} z=b1Hw6YRH-)$sz|wfa1Q&pv_uq8U7icU6-ZKeGV`SbnQ_JeZD|w_ZRZJePN8y}lsh z`Q!ZN-Xa z!O6S)ohi@02_k%KaoS+{Ku&YP`}_jz|K_je6@1Xk2kQU3Z8*lfs&5B}t7EU=`$#K} ztI4l8)Vxv!X3O{Rmn-M-2XNjKxLoG}_7BJ{;{RuHeP*1?b)P*DoL=M8FY&Vltmj+z zN|iHtxgYoUie#`KKx#9pzk%cJuG$Iy`|(To?rUrDZ`0x6KjpSd;BOEs-|EGT+($VN z@{6pO;^oeSobB}>l99Kq`T>7RpeRRu(Fgvc3s`v-^IHUu%C@ja-bm!@w0_7DNIVLcF`XRnw+Ij*y@2Bw;tG9sd0oj?e+g>2M>l4e(6lc!a z7q0P7*q6;6m{KAj@>@Y*$HHU03;6g1`acx&bhz4q{jHq13{?NKYaEBn*L1tI@N`^T zDIm(7#S?0HM}Q%HI*;N>c0vDnU%Bj0I1B9jp2^*?=DEN$!F`MZU7oyaO4tQ|>*Wgs znH>Pfx5rBhesK#v!6%hF1cm$1| zNy>sAy?p|@|LXa!q+b*$+!D)uX6s+RM^;J#PebRkT|Bp4AfR$K?_JMJ0!!|C2*&M6 z7f8^Y!O5^Ko5#H)pS9%~GrylTq)&2UDr7D8{}U{Hha1=Ps~$E4hxNKEF}#nbb@8mz zJO?`emm~20PM*pm$=p+-Z}KfQKgjJn(@Aidyf4q~8D}|HU1Jg~nxeyz)DF4p2z35$ z^7H*%9LI&jrk`sR&yC>*rY*bDU?*cP)Y3d_J)Hg%A9AGa?hg<-+eh zg@UQiQurn>_|I>pWz3VgU0u+P$A~|oNR@v>vj?Bl3MXF2dP{IPg510&1hUuk-;-6~ zJPHzc6Jor#NjMu8cO` z^yyCo9{!&L?mHFR^a}p-Vga`iG}tY<&ly9`|4J8*!4+zelvxGI*d;=cXQ53HZ<=|zsV zo?b8;tY&XJ*bWeTa)2{j9K?s=$A1uWF(5J3Hxk@#K7Y8lE~;^#tW@DhT>c$y21p)+ zxioY+Efh_;=elu&#`!){gmd!pe_Z8-ZtSyG^s`QrhMd_jbF~EA?%6)F za6f>|QdhnSHsfC9b*`mTcXFy!oCd3HHax}ket84iKS5S-eB8Y&3#LJOK)6D(jQf+0 z5+`5&NlqoFi(oz9gmgJnq}#aO2SdU@^{@l$qel#2eM_&YaNN2KIjaJsAA}{B?PI?Y zJ&`j}ZYtN|wu2lzo0~ayT!Gw~p(zI0GYwMLCXmdv!$<<`P7wd+=5FpS-N(RbVUHI? z+%`Uhn|HA+J81nMNDT;EocIg28^lJ&pMw{2XD&B^%LRW4V_PBH&no-{vgh_012dN_ z2M0Ku+Gmu*?FE^!zm)?#4hLcfou9_#l*|E6i<)BlIJ24r!ES1kYz6BTSg{BkE+Dmr zd<(@9Bjs1^+Imbe+FDX ze{A78c(VkqcXR(*u>41DZZ7dRom}e+wYU%GL(U)Y)`Og_yTQSNOYdL<*UQH3U^o12 zIlz6giH+xrtP_|IvU?q?GsipO?_jgeygb3BbAJx!iabad*howT+qZV}Vvg>!Tfl6P zp0!elG9$^yjZ;%jfJ<@BX0GNSCazaH0${TW^v`o|TaCCk6Qu9y9mu|@zgDREA0!9D zSveK#s!wgWpU6PUIgr?r1V~>B#P-rLTsLR^Wyy4 z$_VCzlcLd<9BakW=rko;FwS>Y3^O? zoH=?DA?N8h@Z@k$X6xswT(Oqha{p$q9U#4*vzfR~JVcxa0TNsID4qMfLJ-)UAbtxI z@UJ;wZMt0^704HUUh7)R%KxfYpN7KF@@iW!~$6X1xg3X=YyoKwekS34+v|C)Qb2~Zr3Paiy zAa#q_Hh|5ED?0#Bm)&k%@NfmG0pSPX=Qu5sO}J8mCBbH<|3} zrlUAz?i_ub@#PBn_pYTIvFD;~^gTCv>Xmfm-b*Vj9FjJBTT`&#~=zo+q= zIp@UlLIM-z!E4?WROWG&1!jxNUU(u>{%ya-_MHwq>z^1azACkr|6#O7>2825c%9>n z8!X)SKHN9w(Usu&yds6KNMSCw#u7*2<~kl8HK9%XhhIa+;CBD?;+CG(2o9quszDab z$${JwyFK`3-J7TTg8w*wLn)(W!-;KNYZ}&a?+IP1aII*aR{Xm}E|)c~I&s^6n4iqZB=IzQ|siD$jsuolCzB0VAnI=Wm-A>;tj#<->gF= zLE$9Pd(OQ3*)q=e9ho>;EdgXBP~(ZgK4AmSJYGXb@86%8P2^xbW&J zpJ-hm-)8lvJYW8w28V^^RX&~>CYvm@@|$?9wS^U*+x7|j&UEKl`>v0Vty-Puf;&I= z;&vDQN;7Tl?S1O9-~7&tScabG-d}MJ+_!lbzL>A;669Wh76x^$CoVU6eQ!+WDxAZ> ze>6l;zxNqUh;c6LD%PY1o?3lcnW~`d5SgdCqUNyX^@DRQ z8a_V;hpk*;h%~S1Avva5cerhT{s!;=TkZTsFh17Z@|5>G{*8Bpcwap1)tO&mWNvZr zuf)gYUVOE$YWekEYJ=Sca?4ix-&{-oMoXT#^pgK_{Azv+iEaEwHCrV1eMsR^ivQ24 zp5SEyQU}7ut1K+$Ty7P}VEV$}XT>MUA^dS!L3?hkW{XShxfH4f($%MR9o*qzUis@er|E)h77$2e*I;lNWdYjVt``jW=_L zU+xs?EM(;DPJL-+p1g|tQKY}vYpWS-kMH(L|BtP*urKH5J{Wt#TyMok-V4`XYqd7L z=h2pSkn_5;jQil8Ndix1OfhG4=COQen8!V@B3U!#-wlg7vpM*5{80^xnR^iTnRragCJ~Gr4{_tztW}=R6O0 zq&WAMZBzNH>KHAxtk?2s>D}So#dBCOMwN-5*_U1EjLIuhQdmyC6^;5oQuCZAyOK7Mf{$eH%L`hN25eiy^bxc`e(U`q!Vdr2F7 z{r|N{X1>MNtd=Gb>TDSa8vJT=?r`w#Q{`uHYPIZc=i+&FTUT~|<7}QRe-o|>qb00j z??U)@u?MnlX>0<=S1+%K67R(r{+;k!%=?y z0$-}UrTK^NXEnvY9pYb^Sj>NhcRzUjf7U%W-W9D1{7a&J1=E6^__dr$q|Y3=%3HQ8 zMrO^CWt_X>% z@qcG;~}Te50z||WuENA zWBGZSMMsk;kLF@UUW=$V=BrzFDP>%E&AA}QnB$;D z11;KrF4g+7U0mR^U5@3W|4X^LQf~1TT{N(K-crJwV!np^ex#Rx&zfyq=StNqUA2{X zJEk4hz80avbz@sQ|IbT7isqtxLhEEE^Iw=~q*2h<1mFKRo41i26sBCMGMa5a?(m*H zx=G;JOE>vx;j-K&7hSpi4SRTaHgpNFOV8&Ni?ids{&N9O`xMBzCjEcc@=v@F%U#L2 zi|3%!V}6-mk&;)G(uAh=L<#Ji3)%l?7o5dYv+XK4Kl*hw@aXp)$`X&2Q25jw~+h2{!Gs999Ire56Ic0#{MnvHWo;4*Wc;vYqY(% zcOU=E>GfZbduJ77?50TUKiKb4oozgs-w^%mppEj}v#$Ar<-F&f=AP&L3~bjna|5mb zy+StmJU0%(88f-UxHf>r*~9I?Zu%0p8SaNy?@n^J+)3b>$;-)m@3azFKF$0co3m#i zIL<-t;x5<+)(>JofA}2E2JvBd+A7HXIxv2(iy#j>`%>=cn2+4zyNtLhO(FM;z~n)+ z9lHeg}n^&5(BJJx0hnDUcoz)>it- zGr^{j-9Da^`%m9qu%6CMnOs`ZN4UM8LHhrif15cb@7MvB^HRFVA%A)YnMId)((tF+j;CnP-v zyL8>aVJ0AjtzG4U@?}g ziQIx&@;tdNd*N~*vtU?;$)6{e`vH5j$X=;gzbQU~?@#LGl+!3>kaB zkL7$_rNy&)0}I@IhwDyYJs@>kZdq|}3M{YkL6m2~`55+qBu;Su z8zlek`A5!*-GN~FRjr%gW`g8at0aQOe{Y_`5u|dCYrb?3m+hTP+=_xRT-m3)d79=< z;^q}G;W61523Ggt*L*O&8 zkn>QlUcCobZxMD7>|T&NUTt2@$q@rNH~!Ys9b7_n)46^2Cvc^kZQ|;ZyvNh*;KLnz zN)w)*A~!L@&C%W@!1Lr?88{3y$+mAKBWw%Z5nt^}i%JPLCf!Rr1ko64=n21$#5yP7yoe1VKn zf3}32^$arS{<#O-FPB2@uB*2_!uIsmQeNE*cAhzT&0LBe>*4PGRHy`I_s&@gwg;p) zWyedf{UA0BH{U(Y{p4^y4_ovTusX9^9k5$K@|uowc^FIfG# zt0DVt^aLPwfXs8O-^tg@AIv}dh#=3pyN}^!gXETN=HmM&(#mt^=U?7KS339~)F0z~ zVR(=8+MjEDZA=MZdz;du`R-+|=9c4A<4s(?hIjh4xqR166#3UnU*`K05(QQRGHYv8 z2G~6ywzAAM-pGys-ZzRHdH7Z~aCRTH;+@PP#%sG_Do>H?CO!dy`Fyr#GQfKI#8dgU zq@Ut7@KfPCxO@iR0_r$cY^PX@z4rVVuy`OjG`2@agf3NVKZCB-a z9u1kV{8~8$EPwv{Ij-eDw7}=J{kXJ@@6z52yzi!j@U2vWl$%Ub^|_`OFoNv_xvMBi z2F$*q_ntSh6ml0CNF0RwqxR*DT|D-Eq&F3EmbuPg*?0i8ilermghb@iAE? z^3JN74fZR4W)aWScU-(~Y!P64XXHWr^7WxTpH00K*GX*~zJ;o*c(*9dBk4^Ie;Nl4oZ|6THlL`7azi{|mBDZjmk@)9z|+RvvBMZ?7)%-7NkC)(4U+ zh;ZRrc;y|B@a8RGzxGz2;@ve5lKvL>3WM_@NF4}oS_`=!VUo)mo*5tP_%eI{^GNu$ za+$tU=2Q9Q!gHZUk2CA_IlkxuC60tWkbM!l*Qc=^m;>44d3Z7hU+$6PypLY_gWVQl zQOpCn|8L!D$QkSTW%v1%%8v4~M{nWX!qmsdt7rpu)A`3zd^-iE@f>)>!?)v(1pnk$ zyV$$mMDZD120BlEDvkNL7PxAJD(^y0U=rp!|+W6yg- zw2*a&eiHYWCp*AqZ!~(&#^H4k%m#%^jQ@Y$HS=RQBNspBRY~FH%f8je7hW5|lbGhk zZ`cXhU$b$=3UHbC#|d(V5Tk7~4^Pl9lrjfomXqpgzJS&)-aGyIV84OHN>7>d@oTWN zZ}ywSTmJhWZ~C_^u-)lN`*~UXPV%jKbc<)=)1|!GQ*8KtR#@@Pe0P~Id&@Gg{>ujG zygbb^yfbYWd9(e(!TLaEf-uX>R&aV*#lDH_oo6}UJng+aoArA5*lrv1Et0#)7qDp) zkD8S=_j5i*a9HN$LiQGY+6Ecdd}X7;7vP)C_rGf$PpqmkU%?g*zSZqhczwU9@J=*3 z#bdb7i1)(&4PZa|HZbsP+GfIk_hu6xqb4J`5A!sVkxTy+H{bX5zj-H4dCALuTaVB8 zM+!M$^XHeu^PPBbfcpdqS5l@0BWF*Mbh7OY!GH#334 zMEAvFa2f-#KZn-x{N6r?*K~R)IK2NFrh(1Y_15GPsg~y3Dg6>$-hADCg)j46GUw#- z-@FrQIlyW_`ejs}!Py`_Px>18dcz~}=iy@yAUP1evhk!Uhz8-?=Rc@{=-)jrRX{W{ ze#XiRSBESPV%PJ$2kQf|v0;PyRT$=BQwI}^C{l%+r*X{#Tqb-`m)ne6w>>l!B2}#=dNIrgnGvz#0MT*k;J;K6q=yo`-h~DOl5Wi4wZ{HS&kRcAn~t1H0)-LmN2mk=5P(eP6}UE*b2v#L&|c z+pPM*dXUvjE>FZT8(AL2UY&9fu1{9e$J%YPY)8MxFD z5>L9Bgf;Gw_081a2Csq7c)kfG9H(D)h3j4NIT1w;q(66#6^dB=*{N{#e{%ZZVLHYA zABsAVUe0nR3^9;63~#%ZhLN{maId=lzzesU`AO?5-DSkq{z5(}n#-r#kUAoE^Ld+M0epK;vhc5;q0SfdF;ZZ<{5+mQQxE=_r`6zo_&&!F&JF+n z^WPI~1x17j#nPCr);FE7nsh!XR9dxvn)RT2p&zaxZz?ka9DCP%;w|%_mL~b`7m=@ zdK}*$E;jzT3EOzZ^|pfJ-F=@i$E~tBu(=>VrKxqLsC_wa4wnZ*BC(t}rM&U|jG0~2{Wjudh_ z-bEK1lwI97%I^E`yWq^1Y|tU;1L7g&(q)eCPcD< zs1VgbC!wos^!S9A6P{)6ASxz_wW!yguJ%e&9D zP|(+8JKNske7-7iVNM+u$og8&|1yVit2{GF(7XEpm%)!I0xSF=^UyD9dwEqibnxwLbK_IE^Nz2~LW5=6$3@^Ude``b zS6_cE0eAaDk= z1Hj{)UbAKkbP0s;wXyyHt8<^x&vt0bA^yHOvw3ESPvK1~{lU9CXEy)A`ZHY9eaiWg zt2+7qeg>U;uF21G^9Apm>C!uO=`|KtSA;Pv2)gynWSF z<|j~WDaGEjF@tN>iaGo(_wVtDvE~STn#U&~-0Q*jL|sH++0$ko*=sMs?mVS9MZnX& zg=5)41u);c(U9+g(*%KcUmCdIpFA(1F!Knnd@_rmt~n#Gw_%h(`UxT4H{X8f=x%>A%=KFgI zl23&#Pdy&&7ts3uB~l{1I}Ss};d|SIc(?2JgUz*Ab%M*i*i`V~haiCqU*vdX^wtT; zZ&}8BwLyq)r}FRUoyHUGTzcA-)ySINc@3=IQ0p#l=H@0|54%Ee|6ga9 ztf1Nc?L5^lt9hqf+A1Iy54mq@QAvehj0@y`ugmLJ@jkk=1?(@ggRH!l7tZC%*m;FV zN_`>k#^;bZ@Y?5)dD3nx$T{pFHy~p%`~AEwr&ajwrwD@WMV4EzqnD@ASB!g7|0iw+ zH^f;Vf-_lp-ES@dtN%886>nIcB=i*ZUN~<#{Z3HpoqWIvEaF)u%A=$wgoy%Id9E}%wISseSy2%vuP99 zFEI126+!A`WB2*I9*OIDYTY2`DwwR2;=W~lm;3B<$UIUHTMmjlE5FO}ZoNE%`+KMe z_rVEA!Dc!io5SOFJdj&vwFQ{}XyPtzbMXmawr>?LxBdAbFdJsKtez;3*0pY)zDcKf z_Pk%ovt&jz@3VQc!C@INMF&iS)J8hr;eJ+!SofN?cp7iqbBMY_%r;=Z@ff@Fz0J(# zDp7#kLkZF+cN#KA3}PeWFD*-WZ%pup`^RazKIg_OraUEqGr@L#PfX;_|85C(>+e|$ zz~;mB7k>1Gr`aDer+7a7g3N7~*|6|P>f8p`EAocEV6(H2&VZ|p^H>ZvPxSL99x*8e z-u?2Bv!P(-!swHWbot5@1-XNi#dy|v-ryDE+XvRyW01#tZ`E|JjXisK=03d$HXo#C zT~!oV{;!7wZ_IHHp2g=r@~*hn2No+h1=(9C=U>aqZ=A{_7}fz6*LZrKx0gedZ|X5t zFdt-&PIo8A$xKUd-ut|{k^AR|4LpoXJHhq@*0q4uIai8u{az{zRs+)05cm)*4r1#n zz2P}FyM-h8u?nyJIdt;$6!HnJI^BGOO$C2mqkVv-0t0l5`30y-eCT_lz!eP4=(fc?(qlP57K)j zL!C=L8H=M4oA%V!`59p0$D9BYwY{=c4~U za5@N5m*M11e~5{ zE|-VP%bIKhyA>oKt-X%dc>-k34~VaLEtq$Q7-WBe)uS1__Cj2IGnnS`Y`ZSawT`I? zYzD_7gnNvl1>k0_lUU1>KkXsdul&D%bE)~8a{HT4;(Gh%D);ZihdfNF%)F_)u7k}0 z*~M|d6R!6I^JQK~=Nn+Rg5*GW;jT)q@68i<{;Gd~i@Sed;GX^SCwI>3UtDH+C*fwD z`p?KM(;WnkTd#vNxLKEd0Gqv0)t{$g17z+a;y@EGo2xWfO}E@!-Xr;{VEs^#&^ewy@?kRjoAXE+lJ{CB+wtqCh~4+}EY}w^eQ;Q0HUHxB(C^?{k`l!AWu`gTW}TDZG^eN82lij`^-o}RAbrSq z9eX?HtZAy;!Mh-9wvgqrO}}yezR$oGmz2vHDuGz17W8K}*W7E6b#9?C-#P2Qui;$D z!38!yDOiF_=+zu9bqU0r2gpp1FQF*oTI?DXT)zY$_pO5DLHJzO0(P#xqhNDxEpi0A zUs9ZrYu~O*>~H$du{AUO1(zF>WR8I6&OmxV*s3aw-EH$XPS>g)&is~M4)6DnI$)hz zFj)QMfBU#*J_rG`LF$*RxW*ySaSJ>*vn2XD*ZIXQU_1Y~EaE7b|B-zYGY@BzzzvSI z8_dAs5p1i$G|O4Y`YwPiZ4Y;lRLE!gUz3x&%oue zp^e?3XQ!k6_3 zYX_IQ&H=EV^^-2Lojn8DU#NO?FNf!qd+;~_nc?2b&N=D8RMy+9i#R6lvg4FK@6U05 zGh~fgmI-7p9!TBZ9XmMV+xx-k7{s6P{xg?X?`5!Ab60)vwENaWhB^giB{G;&Pb)DbqlF_gS3mYmX{$kZblC$yoEU=$=GC06ANF4|t z|8*B`ezKQ1SL>UZV87<^t>g@`D+8ygeXRCibF5~)f$QBX0?DT*&j032cG|-A=?{vAhhRe#m$C68u=#5jadPiWYv!6%8pw4eP8{y9uRS}!^3w57 zI71KUaxuTN<+`N-x$E}Ptb z`z*NvX5V8ej@tzer!_tr+)?}u@NfXBRb~|jn_Fdu*rNs#hvBFD*K?@HZsbx+HV2yl z5pnRJne3}sVmxwDDn z6zq22xsZF5IeJ;(pQtXYNg~8@&eLBTen{L3x zbH+(r(?3GrY*fcPN1I$oZ;`GY&yogn^orYN|)fs`XSOp^j#;qvP9 zc;Rdwdq1vtE@!xUPM!UnKR-Kz?VI*FohxWgw9 zZ99;?x|6cmqa?J!a_e}UIZC^Yx%QhjbEvHN!NKg?&Yd8|&Gn0G0XS`e)SoFp#PP>T zJzV@J_JHjL$${{l@15+A!>hO@pHG0hH`r(ro7065PLE|OTmssNea>_F{<2zUvV-G5 ziQk9o-*(77+A4RQxHA`e|Fc}mWqEl! zS7_8hupI>|9&j`I-+$)vy#`5-TOusL;;j}pxW2EP2%n2d?t$!k1DW-`a|JKM^&8;! z#zy`lJiG25=RE&yIS*&{V%|B$E5YHqbM^(W+igXrg5w>e4;lMU{>u9_!#8>`@u5}winKi zc-Dql^1dtzpQ*J$yt z@8jNW4CzNN*AnA?e`hM#Y?vA0YZ`c5I+%IQSj2ewSugXPh}goL@d2`So=xu$I7~rm zPib^;7n)1J^?tFaJ3jJEUIQ6dx-suD zw{4&nSnb^)NSMudgxL4)>Imrrw|+Xr^Jo_j?~M~-;B*c$6B&1hC-61hTf+VSl_L+w zB^f@^eu(*PQ3kw1->rE-XR3ZOgq$l3(kGa#3=S8bZdcx}XKcKi{l4-l2&jSGo^*LT z*pBU?eY{)tyYoDlDg+k4K6@Xp>N_UBmgX&By&!WgWbtq{=v9H$-!VVL(^@crM|TVvFx0;vPxoK=UwdCy~!A~=15#E|jIOl98GVo9EBJD0%2I<5n99vDd7%Xto5l1Kl; z-QMA2!{_IG9c)(gfqve*@jAR`Zf^kF4^nR`d6H9}=POwL+&;)UR**OdD>5^I-6G%^ z!)3^@m3z+yYaUJ+9bTpwC!WYv27D(@c5!QZr}F&NnGg2&^_Qk#bH6Nw^da>k^?Cbv zHu3cLe&w2*{e)+aDrBA6vIB`}s~I*zVS7A+Er`Hhd}j8{lpSxnaAA0MCJg zGr3hNFL3I-Xy!hvY{+v^l$+<4q#$SOs~&JZ;Hh%q`(VF}H*-n^-=r0gvlT#kWhcMl z_S>Tfb`yvX!h4_Y=Urw4nXd!!MI#Vph~dI?uz!o%AnSfX^5-}pV}2mELeL4`RLyj7 zItKBVxHj_^J~apHQFKt_`@Te=A*BYmBNt2G2t z{%Wppaq5Z<_))2gC>ARd;LHPd$6U6QB&)|5NJK z4mKMkw{Nu?Z)X2du%5=MwP17NiiCI@H+R6>5#PUDg{wC;J|GO2L0Y-i+8 zUH_JEM{qmur}k`tC);=Ne!j&Io;LxRwK;SS*c~9YNx84UpY;qp^0i$2-&L8}zmzcu zJPPgLd62n^`}50*yxaTT1!lWL#+#4da_3#_GJ)^>L1$h&1{r}nJ-l2-+o!_KO53W= zdVlL0ex6lk{2`9kyvh@A@hZI-q69g!`2hb8o@X)%{C9QF@~I2$1FG=_Z8*xnwuWxv~T*%7R!5%Tjld+ zK3!97uv@rpMsdGfG9R2y9D+myf>!bK%rAwEqfS0Ik+<9=lkdTN$hu&~ec!<9zQ`pB za0IU6Uf%dlz-LJVzty4xoIH$>Gto>uz$N&%JP1? z{fqCmkuCpPju|W)CO5DO$L`_HXF36vU+|p?oW_<;c*xr+BE=V~Yy-|eAUm>5AoKYk z_V;&u0yAxb_#>aP@hi=qAfT`t;%|_g%%mM0&u@O>-p|DbHmk}ih~GiuCOH2oRP5q> z$^q%qfz9ez-Y--+fXC&jNEu z{I94v%$Bk>8th*Eh>863R`&DA{!{_m^}!U<{wsTH3l67>wdZ)x`kL^(@X!#@yVuHV z9_I~?t0hVI_|BVH^M6d%EA>c8^E9Pi<`_b}!QPP_p2`ywkfuzlqk`@#80MDh|BmoH{JNKr6c z;O!D#-V+{c!TLbvUubUSZ>dpb7P%nJs~9ki_v{28{*_*~>|4Sd`JSik;4SvE;r_S$ z6yHi`4&K(tyL>5Ej|*5?+y>j@SKKXNwY7;)Znc=e-`+%Uyn@UGVT~VxU_X>4?C1O< z7|mbS_lEo6B~^hXErv6pah%~VyIjkCL=Dmw@^T3R-T%wdUJS_>3vR6C4gBmO zP|dxYOX2VYf&9fEc>LCH6FANv$@86EP#`YWl4q*&2CyBBwb?w){VN5|@B7WKdx#6% zcQ!kJhwl}`d4d1C^90zurwhE9$->9+wqr?*%6F?QDmPH_JCd_Ihbl+4HV7k>`Kt_84qNYpoeLeDd$tfZcrd|1+LB z#_u`5p7G;jS4`&ZWBef?`pSzZ?$0bvxo@+^=>AE;P?9ZWoZxm$~VUe zGX4sZo5VJYZ%gVtz64! z{{(ptUMuF|_;iae)^URKs!*<=VBG$@yz4f7^*GUf}SADSUIP ze(*_2ZsEPEn!^3wW-DB8%FSQk_Q%7I&ERwoGVgxO8@}4*6L`#jbAZd!HNum?VOYSt zgXhomwLFzfTflV*dl%&O6^16oLF$a)d7*;6X!MD=w4WE^v zGOt^L4>(Q218;HrN-nLi z7S7$ZksLxdOu^>b_FMw1Tc6Oylfa7TgRE<+;+z%)Ss!skZVFFn;UTd4qwUgse`7xJ zW?b{(ePeu&=SyNFSiH?M2Ar;fu0zHjKz6DtzvHvp*~yXDB+vJ7mpV9%KR>YLxLBkC z)&o*w{P+}@EpHpd_G8jduo)n6WGs}{&v%Ep3m)#}KX`fib}#1EztzhZRNug5XadvD^?!9fI214W51ViHM9QZ zPW_?Hx_}*Vp4Xn!dw8w9OyKci(F++r+8o@&7ddw-Z^pLyV0VfuUFUqGp3n120+PP| zSVQ`KwHwwkC#0@tHPn~k^}5`}^Ck5oXOTE$u93Iq9q+eIr@8XeApK9SNw;`JS}uaa zz?$xm%rk1~{%(xgKNoXnf4;^jn+v zd!Y$isAm$-wZo9Jagr+_X*X1y4eUmczPPI*;Iw$gteuy6!aUw3ERehDKyt`yRJVjBYz=R&!=XZn(pm0xp~1D4pQCcjYus^J_I;c~wQe2^;S7 zWCgwCUV6|Dfp7-B&$oSa2lgivJr?~hx9D$52f$aBj%VUeq_Tp*fDdSmJ*2eu-bP3O2 zE-_xK<_;cj=dGMSRie21yxmxjW^?doAF$`^PLSkZt*XcU>!v+89WG>_&119w88{xg zdLet0KecD`{pk$j+qi54xZikag*jMW+~5X_h@~gEtm<}xjP=wlp3L&qYZ`B-x&&D5 zI+=1l1sip)vRyIYbic^ol<&x{r(Bk?oNQCl|M6MN-RBFLBgy+^%~Gy;pCS7T8<{tN z>wA!YTztC0c7fQ;EJt~JFF@A(Ow)AW=2sBmV83g?)34XYM)x#GxA7(?BKa$ z>%e*94Wu6eQXgOOoBLba0kFFceRSrYcS!(j56i9j+?%dL_8i)qm-F!+cjB%%C&Fs? ze;1#}%zUt#4S9$;zRBE6`F_7J1jqfJjH7%v-QMy&di#w}TKf{O8!HbF-}i4!J6Ks+ zZ#6^qw?7Uw2b%$MgU4LR8MYuc46`OUav4a4@*eDhj8BEOTZ7F8$+sPT!+V!Y8tmu% z`;c_R_V^L+qx;?9xB#hH)H(;QKHWK==k#*OxU5?I6du-R`P>R>3_RO!&f@)&1leQD zlwl1H)Ai-sc-xP!1G6tan+i??AoDC`mh-#{dC&XOdlmOYHq>(|Y-We>aJ4aW1xo1f z=m&E1{`QM!pJBkjZmZeATeuI>empVh5I0X31J|BE5F!eGe|&wh(7Mk)59sxo%Z_y_cwtX+#bszZP?OVko6oq z(vx}CuSblTS$`DeDLDQO9L`g>3h?NymI8;1^|Vf|o=KZ{E=e}?ynIu^Rs90e-VlhA z0=wN;8?wd`WT*J1Hl9C0Z+O&%Uh?D}hpd0$e#^u)cUeDJElAA|hnryb<0J2QF6-ri z*&uNc4!QgYT)(AnWaN|f6#=`&l97Y+(y1OE_3chPFE0x4uDSh=^Vg*lJgjX-TyL9P zz;1MrdCxWNFcWX`jTD|Q&mikyia)I5=@Zr9IrH=eSJE19o|&E3xGj0MbN#tFllwwo z1Lw5pJ7Dvx-CNoCS}*V%n|l$QFDA_m9cL zp&gL3BF^rI)VJnVEWE2iI=BjV^6|cUsn2t>sh7*YvK#C-c^6a8X}g_yy1%XFc3OUl z&QTGZ&(b(~gq$a{PIZvyeipx*o9*Fz-WcXI9-pF3 zTxX}A2D|xItS{#rEqUH=iikCzRjYM*?YABS+ZlHa(*M=xQsD_VpT~W`5OR+mD2ykp zLaeQvXZoIpf9*9+GpSIX+S|drd*cMa`a$Zt-6OdcxOT9$+=q^xu3Le^GZ zc)OS9UWYQz{DL1mx($%=qPyYRyml*E!Qm91?9AQLlFwV&s^QY`sB!K&c~XWdHiQT}Qdznvp^Biky;gQjUth1WL)x>kMWIfN^18=x~F&^R3xmU`Q#IudZY*jq3*FRyf`^tir zaObyQCatksl!#4c8g1)tDS4^;q|<0%Nw~1%C$Hhydh)v;W@LwVFU6{ z$wtVT_aOER?G>E=SRnHgeIN?@7FV=T0WduO{c*dCDjWm94} z1b^*@i0REGMD z7u@;zu3BB@Jjt8PeyjK-I4nTs?C((JS;DOduG3RA)%l)I?c$w2i;?&5qa9qUJ|5;_ z%(dX%{qq!O{V7eJP2aV+_c}x7L_m74?o$Srv$@QWIen1W+sW^_*KwWTmNbU+TeO=X z{gAsMU7X2JH}T|HIfBD-jj{*t36|IFY|e9ezK229nu7Gpa3R_k+e_KFxBh~hJ+E|% zhdXn*2ABNLhn$SJWw<3(AmgB2?x(R<>1z98aHe?Zd#U6jSnvWu^V0|FqMD$l1ZUqIntTle^MfzG{Ct*=?-Z zz9mJo-L%;Y_P^7yOK>|Dy;MRm&x`#dSdMYa63!QUBss3HhV&1bbvQUT?+N1ApZpMP zM*lC!Iax3_oZkJDYv%e5oJA|{v87n`gVm%Yz2f-ezlCe(7s$Dbr;iD6sb=ti7)tgnNaq5JwG=bz%moFC3Ja{upV=9+k`jMMGZ2eA9P48DTh1yb9iC&H=tWE(jD zg7_Dr4sh-K%?vj85VH+9UH#-`3UgfS z2;%;n0l5#sLUA^i?7ue7>zdMBH`jB3;~k{_z@1dE{T*L#a`o2ra{emx<4Rfc4IGBY zE<(<#>n^V0I%&6(vt1l={{Q8b`rPNfsd9hiMeJ8*uPWx)TLm%q<|0w9b){!GCVyW8 zHoNTvWFM2`ol9&6S60C7{x}n{eplUV64z@rYp#>~7I7{4tH^Gob{ed=kaInEVxs|E z56I1v+v%MT>E`B?&eIWIqT`DT?Ply!i&F@79Z) z-SbVknD4T4+7}(*N|;*6w#G04oNmr6{l}$|_mk_}Y+_l#sYd}H#FY6#{{z2@cGE2bjyDqK(z@x;IIVA@!l5V z+95U*>;_Jq{TwSiIl0g6<>i_X($D_rIb@x$4a*a_`Zes3J5xY<>;DC^g(NnE-BysY zgPo--iF0#NGRF!_15U}~8r-x09pKVB2RS^6~D^l_&#?6*bf|)=egFd zPXVXLkG=Of4_#mfi?1!r@(E{3YspdhYP$7JTFD zeG(&ZJD1D6HIPgA5c3=G{DQe{4ByJNJ;E2}9uR4n{l)Bhz8&ZP9yj?-mNl|<69N=j zT@=A*4ORS`!d_iaVa7X`pKqzSJYU?|Nvw-DbqQ4)adLn7U?C7%cnoabjnsv_sb?W` zW=al>W<3YhISyPp%YQf0TPGsPRfsXW+kEN_PF9weUpbaPm?r1MyhPLgh63-ueID9B z_D?k9F^pxqknhhg=U*-qC~hzE=!FirO}5W5gyZR+n|${edidCR7x46QhVhFWp2S}p zypzYW?*;fg4E{MsOuaam*$>WQ=Y3uO-7G_A9$%f67XPCaoSdZ@y=-kU=gl504dmC3 zI?HtV!*srlcZB#fW?kkLIjA8db)T8TX}$^P^vzo4Pwi&#F24Oro}oEaB&%;7N9}i3 zK39X)oXZV4xE_cZ3(Y;eo+V~Vxb*Dc_d=CjQv8R{Le5C!n{tO&`d$lo+@>okl-KId zb%AvbQ`~Qx)}SScc;x)6-kMF5?v$m)uEODy8A>n&Di&5+djPI zU4PzBW@ej?;GO3`1QyR_GoQS?j(_e?1&*i%TLqRR@(6rojFfnGpo3THlL)WA*K+~m z!`B35Og3>I<=@T|w6L2~^|ro%_nGIi{G9XoFYTYAJ~ekb*NSO#%-7zxHY;5f&b_*M zE`RwAPsYmqv)O}`mH56K7dQVCVZ?9r(1-Qo23G!nx$8M+SL_kk_5P5&mcR)SwImq< z?Xy><{>Lxn*!9)K9F!jC6wMIOtuvRA7n{f75IddU@yAYn_EnJf5VzEIrrzauzXxuq|(mGyGQ7x4#6O$9E^ zT)-zk$yX?!$COM_@Znm&61L=`xa28(M=%Om;S8euX>sh`g)+wBM7qbO^ z%vi_k_u7%aN?e#bx@ajlJvXwR;c$;ypmapsm!EleAG=rCKK}de@3}pb3`ELO3x$6d z=?c%A+$+#^m4UZMR$izf%9^Wmj;@F~w>_t;{!>#mQFHeF2Zco$9!qlTZOfN@9nfHY zATWh9;P?i!u5}Z5Z#)mx_~4Mo`Gn<)%&wnX`1-hI`0TYU%wpX;%>{QoWMbI1NPXkc zZu8cIeEeDyRTOvjl?VmiG39^r_9$GPA#ZTe*|K7}9;$*qfj3m63D@D?V@ z@=tu>Wxn>zBEDr6LfrlgJ>~@$*YfSWuEE*2|EC$V;0wO>kCn^>R%VIp=ga};1%H*# z?EkVv)h0H)VSg@T!s05|%fI%W5Bs&doB8K%>oMNv_N*Q=5bCB z;iGI)E6iE*%6bL(3tD(5ZSxb(yD*tUB4e5Gj+Un;(riDa=NRakg4~nf5zN_hR-GgF zZKUL($70;4j;nJlyVK9Z@w!F$6LS=&qr0a--=AZgYY(NfSEuXF{7K?sBESHQ`^^dBm)$OkL~B+IWGv?+=&@JkRFc zcHuu?hj53vI-?LT_vujf>NB1K&)kLCTOwDP?=GCqWxsy87W*tgRx^Du0h9f`@{Wi0 z33OkR5%{-AU0v?Cq6jD)K{)x)RB#z{@K%7v&FX3akBi!Z93^LEwI3RC)eGkG{7YHP z&-AWEFumnJ*8%3^{I;wS97-QHfZGoWt$YGM-{0cqDivbW6W_)kv+k1E?zJL9w)_(X z4(e-w!#B{amRmj?GPhgq&B+~m>mzFu4-;3wv2^a=vTwk91|FQA3@&pQm)`^DTadeu zagK^B_s#`j+#8O1f!jXFatja6;_5x7$aZ;o6IY5VBYaHcVGkGQlWQly?)*JfhWp2j z8EoMjS;74MkDhZS&-}{uaB~~D{Q@(uFC22W5{$o2=p@%7TR(94z{JWKs#xXbZUyU8 z`32dZwQt=*uIpm@oJ(JQ;GC8N+1vGX{S2_5VEW=Gc5r^&Xw1IIr;&AnzZ=_%Ly)~< z+c~trW=S_MW4~Hx3-^CXf*t3_iV0x%N|^F+WibYU-J#hn&gGE$iYxlde9jjK>pApK zLGJ1D_lMjOcJ9FoupW@TcW$61k#lC`LXPQl z;kvse2P`+s$AUv@8N|HDYnxas7@AT1@|Sf7N9au*uGpDs+yY$dIZt?cb6M&`_TWr= z%?UOGWS5JV2&dM+?{K}74v2DhS^fuyZFGD)n7+e4mD{RoGkbfDB$yA)>T<4(B=*|P}}o1CY_p`LnSn%uY%-9kU9|lGIuIi9K;rR zWXiSFgaaIYyjt0u@!Xrid8j07E7 zY_91)buNp{V9q}=kh@64+g-upz5i}j9~qxGogzj=j8)I|4vr$awmxHg@YWH?C7bDqwXWIYn>8 zSTL8;d-gtk#9173r+0Fv{;&tDEqNx&y>?{+SI2kA`W}#84#7h9`jwErntXvf+|3}l z=xJSGefuV^U~^*S0{lW}N(~LOc=oCAeltS97?ELH4D5P+t$$-?g_E z?5CaxVOFcd{#;c7eO%8}Z*oQ&2!rJhwyJ{7mHu^(GfWVY2cD`_a1}V1bEm%A4^N{Y zHynDN$G!CEW{#klEL{6sw7Fi}EZ_`VB+NbO!&){m-8^u9UEJ!=&7=5&i^VUL+cFp8 zSCHP0erXPM3B*_jNbDkm9rw!1ko{vI{=o|uz-|JulNMbD+g-v1IS(Hsmd<|>>{bwa zvC4C<*8h-up+Wq|ZIiediy-ax{9lY*2L(g8?fJMk7sPt7+Xq6%g_^Swdu|@5w}JBj zNN<;hAjfAth&#?sPvdar_{;JBr4NUyIzMMi`VKB5HCL{UPiBC_5v2aUCc@t5PA=Sc zZRFtT6D0re;7N{43QXL+>&)QdTRC>Ji*QwPrf>D-;%bH5g$Ys{&#uPx$YBO}tZuO@ zC+FvC$oTKqquE?MJ&^q@jPJs^`n{UK?mb=5#+7^uV*fApW^fpR%u(nH<=$9c33g+_ zHbL&_Nq4zZt3GgLxt-@MyloB^2dU$InFThdT?OXXghM#lkO)lYjLxD<5NAUT7PG2B*K!eQtk;NmR zdOA!{hr@^8c-~~NSs-x`mVduqV9l8gd?%7k1QHjX{T)T;N}u=-ydXFM)zm1dJtP<%~AnRvFAKa z$4dFbMM8NWxrGR9kMZWSedoe^JNyh^_4YLa;m2Qt)z_aq#`pe)E`L4qHoh;llLUCa z8uA8s&EXe&WC@O=sx)D)dmm*5*dlxQ8Gr2M{b%LH_epn&Krp8|``2rbyO_`Nm-4AP z=<-%6`0@UaoX2(JK_7qDKQFLfuc}?={g`4?Y7gbP3G1O>hYwIbj+|2V^xE1|j*Y%a*391FX_ z`lAnt^Xueg!^JaSiSWb-L+;hxDWEKd^kyRkZZ#-W^u-oV~pL%tYfPripSIgKZn%W9FUw zEK3r3wQua^K6<;Eced(z&eYeRc~rh}@QFE=^JfUo0lOtX=`c?&uP!*8b@w(4OfcES z%cXV@>{kVLalRkBZTU0PA?yDf+(g0Z3U3?|;H%K)6SndYH0giLFDWU*U1ntn_NU&A z+q`F1Eas~|C(WCF%bSmRf&y=oAS>9s2}+hc!cmYpa8TGx-@2Pm?{G7}3F}hc*YXp1 z*QwX??{iuwV3V~*pqyhJ?~`v6P#X`SX|-X|B{D)^OxCNPag}j_4@7v`vIi3 zQYa3bZ)1$?UKlzHtIedYI=w1aoG$r5n5@G$W5 zO=M;f*tyP}TicLDAhqK3nSpOdtRVk} z30L?s?g;RgS!l5Q4u1d+Bm1L?e1+b*{JULa_-@3@@=x)b#J6*Qs(?%ecK#l7?CVX%3iuw~hO3Y@23ai0+AXL-T*_pKDz{UZO>I4YO^;y-y+gxAt` z3-9W{7{0;@&-ht(oZ>pXb06OU8+Lw=kMDW5q{{Kna`+yARm;^9eKU6j)=tn_F1zyFkX(JibI; zc|lRZ7T%|YMFM|suHn5Gz%4jy-bD79J9>H7ER+)TtF9MFUkF*xQo7BL-)^V6;EvL> z0`LF-6Y$>joG&r^4&Q~`Ac6fwnp~?tNDKCVn+jz6YoAPY=H52g113 z^;P+we`V!Y*bpaJ^xlJ)+hh;dW)5+|n9w~OZ5OVB(=O=zzu!HxcvEyBXN*l$`N^xa zb1B%|Kitc>yO_cSZQr&CH2T-@%x2v$aEn)fZ_bNSKH(n7`l-a|O}wWp{CSg&`MJCl zrt%xqAo`H*@4fjuR?73If6Ef|I>pW#^TCXN-xd#nrlYR}!WR|_sBFH;r{i#z?^xJ; zUiNPid?~?_d>Y~Myj}CddDdD_;;wQM1N--)Z>j)CUbW!7tPF0$<$eM)Rs98Y7Jd}) zI$bs?YPBx_Nyye?!zG&wfaJj%?(kVD`DKEcme2Bo-Z_jz-pE(Nd zT<*Xx#UIMgbZ-)0)m$Im+ZN$q|ANwUTo(_x4*&i_5S&LrVs-WL{NhrxcikO^~mpkehFI#RRY(-CQTZnshhbhzY!Wf@U8D;_gA(-A`&43EEpt1m}~s zDsKT>K`+zmE&S|X`9g(_RdkJaF8RrOw7E&}r;?V!zRlZtKU`a4zSogiZdp*jIFtDy z3!&6h_C~hz=6%z?s$V;`nukT{J%9ET8^Ms6mu74Jo)JEC=@aH=1c1__iGbSA=egQ6b0gat=grA@67F}6x0xpNM>vFi3 z^C}7i89(5!Wg#&>E^ce$Uph^IKOb~258EtZ(|yd`ozpq_y4&WP z8*=~U(@EW^AY3;^bj>Pv{uTQ#@MV0M!M8?uDOc{}BZ9|I_HkZjV3pyNx+T(*Hiz>g zI~&-~rm}W?Jmv}DbTP|u3x|v8H-Vx@2e{@>`p#dp>8U{Mi$1>ajjine)r>6?_8W<| zTQ`WBI+zG>ZvDY&oi1x0_ui5BhUa3L9Wk#2t>^U#q}e)~FN&EVV6@^fuffVfzS(tw zf-i%1OO}8C$!BM($=?)nieL5UUcr+Mp*%|j5A(W+M{%ZkOyMx^ZaCV*x4>+% z(1ry~@-IKMiKeZM6>MB}S*EPqj@x5V894k7n6>ir_q)h$+7!v_th<`e@M0hDh7J#K z+V@$K%2Rmb6qpUN`(^)mzJ*OoRi7ww^YP|i=4BLhx0vz1QNSX7nZS-Y(TZMox&)@Y z@8Z^7DIlsiqfKQiW1P}|r2rL`^-P-Cr{c{WLSzM6kM?oSe-$cq_UUBVm98uJRWsDg zuiv`E^;he@kbarC#ahF4g8B|BTnnGf(q6q_rdi1;QOU5|ru<=BUkRk1Mw|`E_4y8$ zVf{>rnDdc>(QZ=(6i==ZeBZJ};{B2R+;_jGa;<#u3_kv^`9aS7z{yIHn16jjmXB>E zmp;qj_gNXrzqV$VK;GqPX1CRv%_}PZn^`RS#9J6w1|I*EQpeT})-2%1i;RI9+~&^UDPeH)^mx zU`P>>O#LMCwquKs|CtSfYx&o5AH3fuC={K=yZ+EKk&pKZ_*_rUHQThpf`9+M|6&23 zFEDeKL`gl}lWT6{beXTBVV7B^;vzntW9PM;J3jLrQnHq{zkHC_ELKgR;{k*Di@?w3 zMcbC~%bfeIvHkF8^S`G#`R{lASIiE1CT!atE>PgN$Ta^9hrmY{$ek}`-$nSHrmvS= z?QxCIR_-sy=BbPL+uEm_-)eW}55N42PygR?bL-{20;Y$)@y}g9-8{R{mFw|0F7xQm z7esa>#(?uh#l=YOd%-i*dAjd&)-5>2I`h~+&deDJ+&xq03TWNfFsFxTe-xI{nE8zI$cH(q79`xq46X3+i#R2(CZV z#xKmeQ>asvMPiLnAm91(hs~#O-WR%N!_P0quP(s!eHW|yyo(yCCX0m^thg%hveQX$ zlE4qyEyp#u-(2qI-Ks0Zp0`tt|H%2xe1)&B3g2dV&zHpaNNBE^iP`emD`c{!Re;l~ z{nP(^x&N6stnzP4op>{YQ+M`4z8&ooxhpuD#PV_?`A=}W3C3Ugz|48Mt;Q==Grk`d@A%nF6XYD1sPL(t z=jKaby~=iBMu*78vjVJ@_pJH+{EPUexiN#w0nYE%g155H@s>Eo@vWAbE5Q6=kEFP) zyU29ccESEn^T6TzFlHU!fj^LYsS0K!^WJT*=Dshrnb&gD6uz(b?EZ0*+r zn+tLmGXAF^#?Lt2jDO+bi4gTjlEH71cr6?hdEDRq;8`Rk4X(dH(){N*_?J3KfYnca z_ma=zx-swF6_ESbWbgX&Kjw4fuYQpL&f_5UAbda68k`qFY!H@Oro_v6CLP61d*)2x zZMByM>+6^%2&SjK+rsC1K7#MqB|-kCe~@!CVwezTCV3eys< zU(H2eb4&JWfXz6$M3#5ew@$EoLF!GOv2h72IfL6-3Hv_q7^gwvDeQI!Upc!TpZ%}% zydgquyiF@q!FqgTA!p$7Dcl8zCCChmR8RhurcXG(Z}I1=+t>g$>$qMFm+JwALU#qa$^5r1aQ$@3+vf#MYdrt9a1^SBb%&9egBU#--^?y{^#tj{fKaYC{0<_^f&mX=&^ z__lb9@%ep++|_oNVK3J_xvM;Gs~~qM+VMfodw{v&hO0d9;syiWE1LqjqFE1t-8h}e zo^RRgMI0XUAnWM!e{}MS&w#A&eIeV%!xXU;tPW#})&vYy}-HB#U=yIBP`f693izF(Gyd3U^<#9Qhjn2mVoWLXn7oLhgHE$z8Uvbd4=>LXV%vQ?dQA2%Eo`0YZKUPkU6=j+&o-r zv%%^)4|wr0?A*eeECg}mjO@=~f0d}O;!ZC-4>lX5r`Z>B&nAc+(4fSZF!=<}`g&o$ z6LWg`6dU(~)$I?z!q0L`9?S-*17ZGf$ox?6(m(LH0*S-$wTei-p7tW%`%lHdW8Wb0 z&;=9VW*FDIaoYyz!TGC29QosQc))()naZ$^9c@m=HU;3cic+b%v&c*-1q|xCJF+_$Tzl zf%zc&LD<9YA@|YbEj+i1EqS(fW%K^g>fmkcGzXpk!__~n6&yy5+avhhTif|woUP;E zBZgRmx#mzGkKQ!YGmRS0Y~j;UL5%Uvo81hz?`3Z@*gU6_=U{h&>|e|SIcp8XcAa^S z&r}w21`UWmU49~8;Zw*sci75o{s%YA__+eSc&}^R;o|Dy28W69weRqF`XG)lOV!Su zZ?7%nE&v(MS=^c5L^#(-R`W1^+r`rpAJ0?G5yAJ}4>Aq`vWwBp5$>jodXoJ6^bz~! zLGsJG_VRRoT*NVpMGzckAhC`gnLH{5CwMf)1-J$8@`K$25|4DQ<*}5X1s<3E`h=02 z$E^`;_TDQCI90e0fZ5?0*ZJB%LFT3sm&@>1Hmp_I$|94$6C%@6!8DMi=9rgJ; zHt6!VZ1?Ba-E7Kd@C9+i_dxVZy7j{#D%+<_5Z53`H7@zo~y7|WgF z;FdND5_UU(*Z`!a_R|4A;ZN)3`!6N)Kl6EP9(qPWT3n@3#CvXs1;Z02?yAM>%=Sn~ zYdk6I;1jR&;AP>E;Q#e)nVHMEH9}uMHG#(?W*s-=b!>hkWT9UyVpOJM{w$G+{pj+q z@&^vjm7ViFN72%2C3u}fk=H#o&MWF>SDd(c_eI$7L<=^svp*~m(#dG$oKmoZZ?jD| z*u2&Ivv_{5R|3adsfncdv$M0OH5I^E^||*LukzVYcYXCDxmd=J9f`&=qyx1{@~lld)#;f`;^&J z*>73Inz=cK^105v!JHWw9v+TxHt#rQCdC?Qw2p{%-k} zudjq3s%o$$ecbkjHl4= zBDZXmsS?Bi}az{Bn|;UVAek{dF&W_j{m&(Bbg|FnyfQ_9=?P#A;R z*6Tf7DLeW3jGoG{zt@*!^_ODc)zUa>zO>Pj@2J5HHofZ;`6}P8VB7snT42)zL-{L{ zqD2m}uI9Vl)hKbg@GQGA>tb-<;gnXi!1TS#rOndKS=y8M`IE0Mlpi-QXZ$-_1 z!DGu?RFuC-D?M54p;Yy3oBDjaMdr0z8h9VK?qFGZAV+ff-gw#Bk90URI-J1nc*b~F z=x4EnMRw$2TTd?&_! zY#HA@3l)B$KdeIit4zdQBo+DGQ#x56u3<3(sRLmNRb}%R2M!9Ff7>T07B)xBMq8Qp z-sC+zH}(1WjN(mA4L3%ZD<7O@>Y9F@hskppKBMntj@`0^u-4pVx-zLs8v;6skJABF!^({>|m~I{2E>qpaz_+_6mH&jRf%zNg};^kauZ|V`Q)TM;pK@z>$BUTSonaS$x19a@>pqF(twGFp;}-KAxZA_0CzS*) zZ)RI&@x@%6&BvAQD0wI|mhp)M3%vioF7_^O;H>%PY1}5P`PXuJ+YhZ`Vv%U!Fa76f zF^7SH-8NcZ`seOtymML?u}hU*V=DLJ=2O#r&F zvweJRQryD#4?FO^vr>_?;NQX%w31sIl-}weMDi_V^5UCYahYX#$3-D_R$~$Mv`Aj3 zOHa)O+gpV$?djqx_KfA06AuDi&|Hs=8=d$3-K#P!?F zT&m44SZh-nxQoh830;nP!`yH4nD2A-cJN#`!-^j1eT;^hk&hF28hR!Qd>4Lcnl8VZ zJzP^3+&}elujbHc=HT<6@CjUhS+vd-eB8R4SK-bl*4E_tQj@IsIP6b2bErDZ=KmAK z%F{1!l;xMne9nW9mzaN?8wgG#FO6LV@9)3Ek+^<|Jd=vI>KxuXd`H(Ra+Q{GnodYH zmHTdS-n_zMmjJhlxJ==NBP=3yA?6BGCh%-*ir{&qE2VMOyqohF&-ELI ztk>7>;XCr0g{yhnIrAr*cd&2ESfmAtn^{k1^1bf&P&gE8Ah7O(2>;d%tg0yzN8$JJ z?&R78?kmje%2%1RUQFQ5dk2BvQ)*@BT$W<{?-%Y_F5+Yg=QdTYzUKeMNe z=~?kxaJrhlzJt%8R-C7Pf*z}r5+9#=$y>4O_s9GlTDR_7R?{Dji<;)>)j( zxmox<1HSRqzL4Pmzxy4y{RJ}5)a3*?K0)j^i#~Hqna0QavU4)HU%_HOf%VWSE6&xW z>b#c@-sZb~riAm=97sEQ!p=Cp7iRx>m84ek{XY-c$IiW05bS4=Ss?tm?*$Lb_D1f{ z50$w$9a_dEeuNvG?S2szp-C>8%@R<0l2dke^tI4OT z^O)E5ehY7VxG-;SaTi$pb8#hD?}_Pqz-=>-o!pxl`7_?eateMm;B(x29PH1cVo}cX z3+IFNfYjW)a01LW+O(KmIhG5>&BZon!13JYxqz?O5E1T5Z0H^a^~#YQ`$V8bG*T3gTe-c*Vp{#ab2*Cm(yeuulWa zQ!<37wM_%AHz3@cZ^p-Pu)6J0khOLpUp)8^@&@pPDnsrA0-67@O$DB2m#wSiyrRg> z>AtI*{p*WxzDZ)tVE=&BExbC3Yd=db@6T0Fz-glL?j7#uHz9X2YM!uzlyxA53=9m1 z8JC0k3!{BG&ZmFim0!uhtJliO@pPs?&kIAyJy5b&mV?dKUTzF_BS`DIE6QN8Y~4=Y zN2*(Sw&aJE&UP_2aJZ!3xx=faagR60=Oy2?myq*z^pzUHc1(HY%csJ@%KLQ-WF5nj!Y;nP za|ijB{)U`M46=LPqlw&wsjgu4;x5~HSM4w7tv&aYuZQ73`)-vqus@_9v2j1GfTRbI zo|j3iV0VDnC7c&|TVFHq^nbq1>r$-2C&gUA_xnW%N6fz-{`MTm*-;>MAgpuW8k`=V zJ#FVc(b*19iy%1=PMz|b*FSa>&*U9*AZ-l>28Jvf$oSJ~gDV`#@3pwi*Fnxe*8T0w zaeXEO|M$=LdDMTqaC+Tn;0yT8%y&~if-lg~7Hqak^g*r{i8pwTE&b2lT>Jp;W{_PM zZg7G9cHZ>_*OBO_Jp6|8y!(vJ`0Ae<@vb=Vo9}MC2hWQ-3*Pr^kUa}?6Cmf4hrizh zHfK_Z7~h(|@w^Y_+w#m4D&{@Iq{JF;hT%Az+$>_4Sb)3%lS?+L)K4b8MuPe zh>-aMHl7a1p35wI$Qe?1x@WMRJU^4y%|#ZhH|t_2pF)!%XOi<(aM+p8x91DqF2F5# z`!;*UaTfld#UJ_lzlrh+g-+orY=+c5Dhm*6njHS@O3YjN!t@n_T_u|X7oeG2*Pf+g8dG%*C}l$-`CUj;CvDG z^akIzw@m!{ADH-KUOwP`R_?`9U9^CsF8dJMo(s`ne;2NC2Ad7i8?xpwIGuyoFr33x z#`S($EbpD|_rdCqh1-J72FWL{l;mSAxCPcD7aj^WCoY1Eug&cfxPAetk(#m^u0CU- zIA8D9Sg<+?rNcab?XPiIOq1blis9yCIOGftckA8aVDn7YLB?=EW+3Cf!ZN-SlUMOw zw*3lLk1Th%crMQe?ibvXU+v=Fc%~U{uOd?r--HJ#VD+8u&V2j!ui!bX0I8?AX0GBp zn7f8=tr;RNKxQhfg`8&$VuSFX57T&@w;;}g1&PUC<>X}+hQz^+Lde}^C7XHqTn$$6 zdQ2_nE0RkErw7C7kU9&b2ZSYVF6X)SgpbST-FD7(x94-L*!>f%Zu#aOaMWB(*q8mxCp z%Y1NHg3M?-HH%O6P9?|ed&haR*jd2wBlc65{bLYhPd-SE$Gkdl7=hSD&6~hxfY``* zzMvb}jW98l##-+FU@o3_ugv)-X&G=`i-erV50eMc=Bz7toD44US}wB(n<-v+hb!Bn zn(Ot73|_d{^ApHD${_t9yixHFkBLkeuM(3tZ(PJg-XtG&zN;r8 zXQfY)Mx4Pd_?V3+diGj)SeiQA;=P#`2j**ZLiX6-t7GK%inihb-TwJNFBuj+;SXG-u*PUb)hUguLH;Q0L%+Q_|oI%K|RQCA+kEC892`eQ#hu0ia_ zNfUXKgnonFk#$jpXa8OSaCk3&7zMUh;prPNAEb7&++nbN+nze}KKm2QD_FS|tOg{9 zi~~i_@#R~s<(Y9)pLdOPJKx6ck6`n;E-vCtp3KO*XE`UYm4rH6ukphLV0p2|&Ae}w zPV%1Y?c>|K5pwo>yrK~}&q^B#@#P2E@hDb7{JcR)lF!gMgU_iIa>fhDer6Xv?y~}r zxx{?V#k_3s%Di^*Gr;ypU4-m^UQ<1j+wf)xSPY~m_AeyufY^NVmhx^;6XZ#(ZsIlf zzRsKRS{$tI(>ybN-eag~=W#t`J^Xe7NIL+e9~t}c@8Ru8+0S!X333JlNKU~NvVIH1 z&J)?p_5CWuFChNz^fi1J8X)b)W2;5^l$R{yy*dMOUN1=A_>n%>xr>l`{-4e)u)9Fw zAl%sY031h_q5WK4N0;#gn2GR~l%3?g&(p?ZyQGcp-lsSoM*&G*wG-&WOk25+I34EOeG#%g z4rD(F*In}EUMp?RV`ev(TQ6q;&&z+ecp`22ctS4Ja-Qup2B*n~EC=}xc(U_}8r%En=voQBrcaRY2l0h}oCDhrVlUcM0ygirFJc~WbpqtB zc#!-dIUT-|=a4fIKzuK!54;`M7J&5}QQ6K{EisMH*oBAp*2Xlh#~&eQ)EPg3+{Fb} zAAn@mmc_hUzL2%{dbj^`b%uRnmJB(}J=;}-r|qT}&!PHLygAxw~o=S4!=x*+zN zGi`iHb5Q4p{wr2iMxg4DfrfW)_y89Uf)kQig|HE_6r*f2cp5);>wZF;=t z7N&yZ?D|?(aJmA?gU+?)c7l{41+QO&<@dBr;FXhq4?dd_q=tt*6t4b>y((YJm+{Fm8tAincFI2FR=l{KzyrFXr@g=Zr=UUXE$o zcAWv6^TA1uU+_ERyteZT=W}nKyNB_%g0Dn=67RHAJ9vaIMewfquE*QX7tQsIXAY0y;Zs~< z{wuhx#lpCzrrUF`Qk}uO(-Tr|ufAc#C3X#R_vie8Og^2pQ+eE1eF6Km&;1g2b*CvW z*KA06_u)l9IE*f?YURsXqsx7E`ZGRL-sQYH_f@&CHbMIT-5<+&T7HZ1tc=X(iIK?Q zo-*MgS1d2&?6?cw>p0I`H36FqinnRLz1$p2`g#BV&Et_P;o#-jxRYn;r`dcOInjKV zSRZoTOn{tioDlz+^ZcSiys4+R@jC8$#dZ6u6IYX+IeNf^m(tuwDA;$ zPvU!LB*_(Z@hivK>*joAlQ(ju+Cc8W`L=x}mz$<2-$TZ^>~RjDY^u>WH6dU-o+RCvBL%;ufZlER-g zF@uwTOAntZeMJC$t?SnQt`57A8!H;Zi(uk@A4 zd;)tQdE!{L12`O~n=J>s@5uCcp2@n9x&>qg3{Om6!I#X;%ncreCKr_bMV6X zx_ondRd~e~Y4CnDP3LVY6atUofb4tgx}JCE6Axyt7Y1A%tulNcue5QC3MB9yGycuX z`p=2aTPTY+XGbvmUoJ@d!^>ha-!Aq*may1sV7IkTUdIz#I+^cfS`m*ocRyd*Z#mxY zb5`<|EKB6^-%`xm6;;kNP1*n)W?6a;JYA23`P(P^^A-0(&OWpLaf+vS_B=k<$}+w@ z?n=IMJnwk!-Id^dK7AE0sQ#bOvYRhp`AR-6R!P2=6TkT`pZUc1&borf`_mS_>I(}w zx3^5>5%SjKbDj5*dBvmvKFPiouI7c;_zLf<@asrq@tsRIXTM{7lP5B)fGIVqlPC09 zJvi+5O@!RXKB4O;Hp?7IX72G~rFX zY{nnQ*~Vl4T!d@GG{~KBFLsoJ(-9~<<6^IK^K!<3^Wdjdwmf%^K-SrKIP!9DeEgd) zv&D-~CW4zMuTPI}&oma^D;qia9>ocQ%fhMsd^~E07`a|)m$B`#QRF-M5VE!hWNzJG zS>7vrDm*;rzw)I9ad3-!z2`Z(h>Nc>?H*sOqbA?x7+Idh-{ZT38@E=2{h+_#3hyPI3UEG}85zNEr&`DNWY2fr7w%hmW?kOR=lF^|t^YT3S*2ZYk-?nj*&Ckuhm-lg>xT)Sh%^!H@`c>D_$ZBmbIw;C{;;J?{73nZ zb4etv;n}A*mH$zsKS#y1$r5u6L%Ax>eKfn>R>i&OtQ`;gpZn%13lsPrwa4)(|wv#`73@wDMiF_`-XzcLLwd2@b-0e{SP?={J#kdB$e*`9&vqwN9>- zFMaAD+I7l+*Gim)ue8;Jr*Ja|C)bC2f@jV*aw?nh%D7H@B>aC83)hO365zCONqicw z@3DArJYU#&m!phHUa-n6h;!nEUj8#zzwrl6InN6^|L4n$A`9=wa-#RNltp{Fc=-Qy z_j3e2(Kr9jIE8!8CreqqrkR5CniT}X*?rAF@0!5BaoS35nN$s4;oJm)M-7)G8^12$ zUG($^?+ZZz{?gey1O+nQa$d<%=3TpI9jBG;eVz$&vT|lJ&w05zvcT*AlT(B(mbE`K z<2^Bzhb17I|MdnX9+!*%xcRx;*ykP=vpBbcm#?Cok=L)?NpR^WX&wbbRiWi;Hpzz; znTSe>lnHQcE0x)>G@awdjU;gRmHzkVmolCtyJliCchurpyiCSi+}}cT!0EZmYBiU~ z>QXQplm=#sOY)lB5m4P+7Q#FGf)dXY!48WLUS0fK?``KVd84K1tFfEks9+m63-5A~ zU#?44JS-L|*?(+MQ4O1}acKS$bFCwe{6cQ+oNfiJQcF%elFi#UiTCT_=VsjjNgOA= zZVRpH^Rf`TxVOb`|h>)qUXiv9JJ_2Ozhk1Z?E!k&uvx zo17=`^subJF870i^AbfRl$r#%E4XKHK0a;%U;p3gn_+(F_&4F*DcwRhCvZw$)Gy{^ za*N~p_~ADHhhz`414YZs_dHu*rp8mkQ_da&UXQ@-wMXR5(^ab9uBe%>KmMDqxZorA zmv^%T*6ecRV)rQKk+_n|e)0rl-%rukDBix*Y06SQOZh8~N%Mx+ZsLC;)54aZE+ulk zYoW;Bs$D`ZOZE#GSpDW?nbIgYlR<%d`+->^5uYS@<~|EH<8tKXHPUDkn-M>Yao*2O zQfqg*o10I{;|UJDXU5>Si6^usK+C-GAWzB57+KIcq)&>H1wMBEF*Cg>XmPByjdvo~ zVU2b2Ocvp1r}DnfxTUyk-(ukx^DOye76+NS?~&kNWw{0%ZY#NG@X8-dlT_$p7x-T| zjU!;ra=zIKYt6MHHt~LY)y3PXyWBkBl{WvEOM7__r|&g?f9wut>q1>~Cu42Vn!PK* zbq#mURnC=+J?aGqnK^lqf?3rr%;a3W^B~t0u66ux&hT0^9Ms@%IdGWIJE2L@dBJl5 z!_{$$_ai2l1{}XGeeCorx!v+cTq1ik#7@_0@TPxM;V$*nmb9*(!?U*eF7L{@`T~Mm z9KiW+K`gt#*X5S{RSil~0@sasm+LKp&;OUkE#?&y4YQ-J&K+XjAj z(Fqo9skXdqO^q_U>L+juSuEh~s@=n;D!P`xflGno>-1MV$5vT!%wJrusH?b>UqnQL zOW+chz?0t#cs|X(Z0=aUle_Budea*z@;r8?rUKh51I+qG88jyy;1Nh{@#eo2yc9hD zALcQi@3^nGz|QB-g|x%?1cWP$rHgc?@&2i(lHT)}o#W_QMFGXVVggbfcD&V^n}r&Z zpNL61%JQ;i3Rt`;ydyMY>Sf-@T4Vkx(KlI+ah}v@6I>zu)A0#^MnI@Q!8IniH6J!| z?%W)}ozJ|OHE^jMpJ@L^-qg~E!d5BUc@lQs5RzyWG3)!_Ci5)I8=O|1@{aPzXl`Ox zyS7)#^gTOA?%ocbVoM#)p#P1c&$|M6_cR0uT(CXBWfXjXBgFHn^k&yXnxV2&c^H45 z7G%w4HRsPf#NF%t7(D;)Hb^z(c+zx2w!znGUqYD4?^1di#XMs`4yQC98g_W zH$`B}`%~Or;#Fq@l|3YAMQl)=XSmUQ3K;PEV-72H`0R>HAg- zY8rj!?=)PZ&J^+lye^1nVi=E&vt8bJOpIykkx=M`a!rB|G zx&A^TQP-!j^4*)n<8r~Ar>M{$+`lM#<0()osK#?rK$|DaW+(ruutLctD^ClTo$3&{ zY_kn8DGpkU2wfJvtT`c9&0e4|Gy_(dD&(H3u7X{`PA^rVld5Y$;Q_ly8*2B z->uDHF_0T2nr!%%y#2&~_5%-J;Hzq|JV+dbALf_yo6b<;HO$(@*Zg8Sj{w6(uH*-A zxSqdN=bLZ`a<+81L?d@P_YaPndyn#&oQdZ>w{&edxw3(lW*yQKIfT;Z&}7d`Yhl^S#aR=R7v!5;se?CfFa9Paxww<^CyrM-zKE zcNfKj$5FmzUEw{z$q82T*zFhR2Gfb)crwyH&9#5^KHj5>t-KGzbNKQ-(!uUaTmBQ= zj>{B>+wgtH%D>=XS3{k?%Z38 z!FKW1yyH5y=rGTt?~wMaMaU*jo$qJCW=vcChOaYiBG-|tkTEOyX&$`m+oteJzDNSs z+0G@9xww-_G5kxWHgYMas|y@h?asICe;bEv4CF4+#Sya% zbN0AG&Un#gn8(o=0qOsN!lwH}Ezi_AM!syD)109F_fMxT;VT!C<>$Sh#{c3;Bu|!; zA2=L!FEnvGI|cG?mVE;DKS;0YiF3U2#V^2dv*V;aIF0>km*hFAbdcwN<6iJQCPi|-WDcdzO5A^d_4AD{0p{1#w=t%H1mFHQsh1_#{+gF zNT0YeWFN=n-Ti!ymT$Rwe?aa(27kPe$BtZ5Y1??mwsZc6{M;8(Ggf*YSEO&*D`+z{(rM z@P&`DG?l0DqZ-&9lT0D&vCW#Y!Ew3Rdq3y(M>cRXK;Z}Tydd{;i_@OQWNbNV0L%%3M9%WbfOMPUCj6E3;G zQ~0N-*K#rUu!G}E>cVcW(|NP_)qXyQ`->~AlFwK~NMLcN|rQY(6MF zKPDi?%1Tdd=ejws9c=Drof6LLqM8Dha|HNrYh2`XzH^`dx#VrGRYg0%?f~iCvZaNq zLM#N#f3?(vmv=ehoCYtmtGvIoeE7~C^c0wp+rZ7E{f+n75_NuE6FL66G%5Z?|2X*? zc@XRE&wSd+9TYy1+fMK*+f`Ko&aUiwup6}nyZEcsECqrJ#5mt|bn@-tzshI-NQeJb zGR3Z2AHYH;|izb*FQeN1p=w!LH#uzjK-w&kBxC{w}t;T+Pw^0x~_) zJS`O!d|ca7cqG+saPE6;2-llr5C^WyXBR-ui~^ZAYiAr^x6mi9?I|H(_bmM105`z?9J~BU zeus?Lyg{W#oVEtB(eN^$Lg}=B2k*eBvvZA0r@r(1Ndd zHDsRy$ZQbaP;!8OmeK}ZhH?k~jD_d9!r#2$GMKNyouzx7$9OGd4@=SsJI<8vtek9` z5q$Ci;e21)c{sN{dcd#8*};80r3Gvs$gI19kTohG_V+ux`8Pkk$O&8$fs0bHG*_VV-ALhjmIyW5!O$&DMlMg0#s#8c<+Pb=8XvDPL5oQ6SW zfyV#e8LIME{a(Vyv2ZRA-(p!_yB%x5VREGe(hhjWJB2spm>fs{+B=bXckyRbM99py;RxWu z>?v(qlKF!-0aRAKE zV7COT+tGZ5-#FtQm(;&#fw*ID`JQU5=Q!u90#5TO`GOqN1E%u^)ji;FlMm+-U)IO* ze?vQ1|Ej`iZ0|qug8dBgf0x4)o|oPe_;%dz;`lXX5~pZbBVW^^b^Q7Y`}ys+%JZ-& zLh3!kGjF+jRyOeM+_9c7QP7gpK%|!A>ed1t-AXU8A0!m>z-cV(bsblEcs%c$3J>_$ zF0;!zupG#~b-P;mHJA_a@kMsU+ol1kdTPtl5IR3AMe&uuUpUTVT=E!F^*M)EH><9b|vjlm0FNv^o2_NCB zo@~e6YCjtsE{&7KINQ(P1hX@hxcMzyW^+zUf}Fwh=h{J@Dsf@f<-(A=CT?A?@#onw?_WgZocq% z2bp`64^oFkc?+-`n_uFaI#H87S+SqL?t&@*gGnp63Z+c=_ldmYkP3#}N9me!gnt)% zAd7+bHLy8BCsy$2JU+}HoXy6WBgrKo`!a;%{VQDohTn5IYK2?*1M@pLI!$H4=_+mG zd~SAWc>%AP&HSq7=fPoLe>RoRx871fdD&zB5+Pmz%a#Q^g(tW2M!5y>Px`QyRqc=jSu==H0RM2mfX6-)wz#pLloIxq;J&@Q-)=Chi!po0oS^%Ezf9ra`zi}L-^)0+AAFz2>D8Zk(i9f*DTqXY&9FAR z#<`HWljG3O*Zi?PhO9!S{G5zMci5_Vop|^B7GOU*CqsaD>uC<7%9U)foT6ZV)rLaO zpaq4eTss5DywcxbzwN(vg6){m9EiB7^dV$aX1(^xLeScN>+HT46b-T0(_(xpl+MA%u7s`{#&*Sik zUwm~Ne{JkX-p?{yIhngfINaumb2c%t^Dey|&G9o>o;_x@Fw3)A$o(`^jui8=8FUMD zFH7fKWb4QOBq*LgX9c6c^b~6WrG+QC)~4`s^Rs*N-(8&!E=NAzli-S;+64CJxsDzI zZ6_w~j_r2*rsc^TOTL8*IJryl8SupMm0pqHReJD@>zp)VJ)g>CS8y5;zYjSR66BAr zZU;UmkExt0g0sP4wCV;A*zCyubnZ1%UvZkna)a};SyZ4vjq+M7vj+*p> z%biE}7J=1+%vw@;iGTNT3ot)xSE;~-jiSP<*`IT(zm^m1zA_(N-hAKpPN?bfG@-Bm zH}X%l=My42n;r=ki2WMJr*?_7@`C?iupGH`v9uG*+5-i)x4fV|f~{ z;wxeB-an98DYcM!S`hoE*Lx9W%QkLhFJb=qpO^6--oqmBNqCCLWS=7L<$|KTCv>a@ z>WbRI`zS6>+s^lcKU+jO?f}moYc2t+;}duzG*9xcocRYFPMecuxx7sF@qfxLZ2>DH>P_*&7CNf9I~^UBe?R`dyBPe}BRku$;u~H(b*) zxWz#3id*ByQ+`pMe|y)I8)3_!0rZ_SHg1*97YxmiG1HyF@fU=B>s4*1n<==iQxLQ zUBLauR6hBxIcvt6iacy%{;SDyQ!fCy$ zl=t4ORl@3SNBLeU#DU%NJt0u2@#$yqc@-xsm<9UGUvnQi^#$DizHN72)M@5Zz7tdS zgWHkiZe?J4`MGdm#|5f<@0}P0=bkI$SGb?SdBe&NYzFV6t=uP+R7Aet6ynY{@Bp3X z$eksg05(r8N0Y0m199eUM0O{ifU&G-i2O9}&gBcZRh;`orQ#I?z8vxsF!MOhyJICU z*o`MnF5-Rn^po(58`Fg!{0I~}$;~e2nHVixH4Sn{xB7*Rf*pBnA~|_=yb%(UL`oFS zbMUvvvnDoN7L5>f5lr0qnDdEJlE~B9GeuqAP351ng_&PjrbocE3$lLz6dz9ddpHh7 zH*s6;W(B9$o9vPNS*f%5I^WIWj=$*6F@uu{>_3p&`>!^G(~6o|2fuCxJO7>yjQs5H z9`eO_WeddcGm72|5EI?jZ(4is|#xfmeOR38Bj-?ltGo)`bN3NKOS;JuUN#_wu8f%QjjyFlH#WYMCl zvv_X4;1;p}ah7*+6A!=s^xHhor#=ukzNQ4M_iVDBNbTMg!a*x@d3R(e6&=+MGk|y*R%;wTw}@it3$Prc&h zOZPY6ZG7s?{fbqc|De$vp0yTp`N~!w6fm%btpDWVoh5K!Ngm(68PkNW#xU@n6_^W- z7f^g|4_6e3k-j7%Rd2?*G(n9&XHqHmlLU1E*&9biOHIUiF9$>jr}V7gVoHRJ?L19% z6L_WV!s+L67aU*q$C`xoLcImJmW6TIPn{&ddSogOhy6U!M}LoTv#{(CZCrJo+l7Ch zK=a#jp>=bg3vo8h74VRJ$6uVb8az(Cp-6y#f7dO6)mpUzGcL^*Sp7^%FfiMO&+H?U zP?W|b4!e@g0-<$_1y-{9^WN*ZF7RrttbpAadA^7#-69)wSMW5h-pbd+cY^&oqQu8y?q1s z;R;#K|8n~UIZU>Te6xY9t@K)cTG;IUZtgYZn&7g^L`H%qcS;aAA9uas;}TuMD(H~T zC*bvfoqNHVsv|qw{5Mj(4)W`)s^LUgfXld-4j>#sbCDv)u)v z^Y(R!TJIJYWK`niHR{b5Y}n`}%oB7}k$l@u2JfcV63Itx_6DgP`!T(~; zeqMFXMLb3uc7xL_$j$Yi)`9D&Q#)+I;Q8`*&nO5GSixxZ#{z(FV_pS!J-}IE6V9}N?u(>reSOor_Y6I(k z;y6X%^RK;R#OaXopI>f<5IEh>^@8mE0J-N~)=vIM zJo18^Q@Qw4uVsSG0*Qn0-jFVVa~+L*|B`tG?mw>QGvWEnW0ky#_m$8jzV=>-89y)C z@_Nl^;VIBn;NS8{i9gU}KJOuec>))TFYr#@?*O(BWR`ye;#>sHjwXStJ)At|U3UDP zQ_OizIj9Qc#5eF>TX%;$#<`Vu=d~t*epblZo$!q(d1Kwq@U5M0!F%+3yuhhQe;#E^ zA$S<4ZB^$iz4V1&_bd>*<6aB;Jf z{ak&!uY&7;j;$XBoM%GTh6`04=Hs8jD!5H^Jzs*4qCm!ZbvC}!pZR2;#__y)e-Lce zYwy?mtt$R}OD)|6c;2e=*cUYMet07!cqq7nf2Mm2-_dMGzP7r4{!fQ^c~u@dajPxP zZkoWdpasDs;MPRpN`)BcZTIqqy^C<<60$;OveFc{(TO>_+((O|Dj?Hf2 zp2fMGcgE6F+%NY+#*0B?4aXxzz-EKOra8ZeuPw}xpLrG^&q-e{9+TPb{Ql?b1$J#| z6ZrTlo%gz^IM|KeF>86(dAsrJGIjA!({$jSbXS#U$qW-dn-FfWywDR3a2k8Q<~i?! z^Zk6?0ZHKaaS>GHToh0TmNPrp$|`={QQ&`B4gbX!6aGfgBLWxw_rcu~>9L(nNB_Hd$=tUofeYPv#3hfAlYQ{-+1$ z2<)jd=G%0gm*-*abpA;;uDl!OK*msQS-p9=E!OatvS)D4nRAezDQXcR-ZcN%i85bL!}uI{-Dz-b3$1`J#CP7_FGwBfs%{0^MvLE;?=Yx(0N zU3nG++w;Dg`GQy9Viy1XIytUY$Ljbrtk?7IwOqjcEtiphS%M(1!7Ua3RSj%{SvMf# ze@*}P2^93K|zh(IN1W(pDyrp4sWe(kHA%hdt49A4hy_v zZ^w#<0vB#N2r$+_&U-G6Q|7;Rm`$*@ zeWAeGQ>O%U!YcWycTeVvtQLg z<>x-}1>9T$4(~)O$iC6$>8E%VU$pc0bwK967VNO&eY!uNb9eL_0iA2hIrcsOz;lyL zjLSmo5#MuxSY919bwT;L4LtSHCpleAZ-M>g!!;Kiub}YUUnh1oo%ixQKg`a*^O=mms-J5GbmrR#OgXfL&#SY9H)iev z9>FE5yh*)(c%MDV=kb1XoJ+Jfk6UpQJcjdSfcJK?R@0S%|-?T;G z)&y3;4X=ZE_uPKU1G+oP`^f~b-Jdqw@}>q_g7d06tFNH+_4mBGH^l@xzqjxlD3lg_ z9{7fD+Ab~rP1lV0P9>h@nRAg3>|c@uDPXGnYhlJps{ z`f068d2^kQ@x)(~2j|J|yJCXZqL%O+R9(u${BEnj$`z0~mfY>xg5f27;CY33gXjDc zVj<@Z`(J7km_PXmAJ^Y_Uemn>g0_6n{doG*_*4X^ax8i}i~n2FZ2_UwRMrY^#J=6= z<+J!7x-kiU_xj9N`_mol7LeOPc;k~)fiM#fzAZ&J`HwiX@}GL$&NHdxDNmfjUcN>j z$oWMEGJbr;8#8&Xy|(A~nRbFt^2{2(Q_hV7+U7U-tRob`;RZ6ReaA6yx&yKGcSQ)i zc+bac$}7p={Wyh7L`*S$A9J;fCp=^-@AkX)0ya;h*t1>sgUgSJ zam)D5{$b$dQFP#byOn|KbCLqT*iSaFUv*}F;#nsN+20{ha*Fr;>Ja`1?Wg(V0|of+ ztb)}4ylWw6vs7-)<1;8-%lY$=IqL_8Eqp9{ck!9NQs7f4(*VaakM|AE=kZ!#b3y*B zzxNaDho=rXe4L2_aPc`3^SEkG?FQFVhaRjGc%K5R>)^0t|fAEGf->a!c0!ROg@m8p6@XQit6x?`Mgx}*(Hs6uX zWqdOiE;rP%_X(r56b&Eyt*;Zo0kCnkh@ z&zsX=H3o;vd6ycr@V&hy&inU#B~OmkBA(?&!eD*R91e3g?)neU2i}>id~Bu4{EHJE zc@_4R@J1Sk^I!L}7f3o5C*V=2%KJwFGPdaOnx9vA%@4kRg;xBPw>Wrw%B;96=C$zM z3VsF-k5#G?g6*$Pu-ATL;y2o(%lD?jg9~*2zslKt?B$zc1?L`64=Qm_}?_I~3yo!{eWDPMUDH-EXyKR%`MCV^eqx_s?6aa=F|CGlUJbA+crOBw7& zp;&I7^(R93b-KGbZdA_WSF4)Idn(9LFnd}RyH?w2-t4NS?6P+ud%BwMT;+SVznr&9 z%tb&wubb~gexyKwYbujhk_5j~Y9)W|O=rFZ+tLM3KD@zso;gln@0wTOFulEZI+~PRLm^lz3Fxg9DY?!TpSE-v-z8q%(*A{ ze&Ut$JHq?A(ubep+#U|u4eWgXE^OoTe{h<|>LCli(ryR7kko5@Zv$@$LTFZSkHGOW*5Bv-(O-Vz&ka7Rn4-KOWoOq|3}kW9@T5=0vk3Q=bzlV zk8jeaC;W46>hLsfgRB>djY|~h_FK&M=2R!x53SAxe70#x0#&SSJlE$e6{wOG;A>;Q zBj9hs!h0skUcgnwiFd{F^8$BI_Of|-*zzc?-YGD>mP=r}z(R1DQFv62|C{=I0S(4B z0f+Qe0#`)Z`0n4#=i^8f7dZ6oFQ@3uqXKOWn+0|mpW@5Wdn+I{+d@Dfh?_5HLzh75 zl_OlT77O{hKRx4TmwwE8GE4-%&Y!BcNJn8X=|9^A?N4JJLZ)K?`%l(1vx`y)6pW{?3I@MX%kq$X@&KKGau){5bhMuHUZbIUF<${*mX_)gG=1{3`@>yc<}|4nyXe&*Us&Sbq2wk7hq)kD-Z7H}6ct zEU>xFvpTqEsS63-aF!Ra$=Z(?=GLfG_!nx$={>}Jg=?e`^VbA zH&=Npm-^x-pfZBjpOcU0y|kMBbGV zqRgBwOTpn&bw-lcP?3}G>LJLz;C2sw3j{UK<^J~l8*h|;gTUDs$XJNFvyI@6v(v!o zcTN19{T4qS@Aq+CWxxK$y!|ffZTpX3U2nJ5vdQk-%&h&~VQzL)%0JrsuVl1#Xn46( zJn50e%e_Xs8naICNaZTo{fJsXdY80Xa3c$)uM6^n?=I^ ztLEz_C0XcaKQZ^Yc;9^UQF{x8^EMWW!Cf}%{nTv5PWA2Od~t8jxwUupJbZS__TV!n zJG)|yz5N^QZ6rAo_J(sku``+HX7B!V@;>%MQxE){%zZ%f*}4N~KB(>WG1##G+v8Ps zX%pHHR2=TybHV2B-t5CyY+hJN?fW$~X0N=`9qTjEA=dTf{QDN}+GIU>{e``s<}9$C zy3TQ*tEz@gdrqBgDQ|~OuY!Qx`tbdFu&kI-V(+V`R3F);caM3mPx%WQj*DmaT=&Y~tKqz3&#RcFcAsbV9@sfQ zd;gp4TYFBazu(vP@qzv8ONRT?w`Co0j(4%!Az`s!t-F06tB#{BkNna7?2Zlg^Yx7E zcSb$kAK|oR?{E1o+k0D{?d7wRv%j=fa{qx6CHskr?shxs{@b>1?cVq5Q~JJ*U%v0F z3A5X;s#3h~Xpyn~>Q|ZjL#E!_f0exDbJg|q={h002J!fp?-=4AkntN?;L&kpV zUoFym4SZbpmjC0hzUIxk*V38C*5`%kUbg$o_ii{XWqUj~WN$*b#J&zcj(r|VEA}pW z?Yr;SYhinS_exvFD{XsEC+*+&^4S3!hI1Tt6EA7*zf`PX8_S(;BbBFMcgv2!Zpo*# zz1$%hcD{Fv_RVllw)sY<+lI%FOR)pqSgm)vX&hTj^?*F z3plYqzwxBKZd?6AfGXYwR;Q?rD=h zb-C^H(9e55rCaWG2xzvOTIXV`@~FaYWs}*y@~%7kr41$Q9hyV;si-;GeOVZ8&(t(= ze;ZrsK2^a;`+&27`wjZ{?LWBbr(M6_g#AeeQum9Le6YKq+-8^XzSGXES!Mr?@5lE| zIQ?;7rhv5VcX@9+?&fd%8qb98&p!CpUWi+G{}txTw#|h}``CTu?ayl~?vH-2WT!B1 z^PabS&uv#~rP_WJ7Tuq?r+)9gXRqv@ub95~Q9y!Cmr}GXL;CH#PZ^|b=I^_-=MC#= zn;!|w_SR|swDGc^u-7D9$997EVOxPC+%{5g-`Q|Hb+R=t54L&eud4>`h#>?AH|b?|b=TnVs&CdpTJW!3<#T(x)`}{do}U%AcdCu-q>9hlXid9qYbEu5Z@BWj zeJQrP_VTcO-OGD5-FEXvW?Q?2WE*S6&9>Xl+3hiQ6W(iiXvyyHTPE6M^Gn()KR&U0 z`p1iV=4yQ3%VsONH~vzH?GcZ)HhYBXZOwUj_C;Teuy!gD-m7*{dtdJhQCkrvzrFqJ zfwtjyAKSz&=GiM`CBN_HW$wM2X>0c~#zgO0@WFo1sp;OfJmo)Z?m6(=wtlPGdpzKT z?VIGPy^X?WZI`_NwCDcTlY3`W+_p)JFt9d0ZoSXlZc@S?q<#te1`?w8r9 z)o|~2Sh8pD{mJIGX?8_6ir?Ao${0S|s7M9uHMZ2*8~AFvtwNmezMFYBY&ong_BOvw z-tNJtIDz7Zt!{c z_KrV$`=?9qD{AN5yHw-V-nDZi?Ot9uwU;Mk@}6ns-}j2Fo3__#Tfp8@?=ag9CS^96 z5%#vL80PGK%`a!`<1)j})8&%g$p^vvySPv7T^P8_j^lOc{{1%Q``_rCwtHoDU~gXG zcAIj;jW(KBm+x(wV6vw=VUBH<{wiCurRuhyCcWQ%dXc#8uAp1CD)Fs*XEL+cb@CVQ zPrjmSuVg-Lzlmb+{%uuP>@54&*)z_Zbl|wVzWu!KtM?1)OtG%JxXRY(XVczH73;lk z+8b?}Ii~M*_Y|_N6N|K+bmFj$1?NdycF~?a3w7l8KAxg&^M&V$&HRGCJqx^d?=3uA zvA0x9!&XQ7z}^LSunNa zKfS@z?va6peSfU|zO^fl>`yuTXMf&|$@Yc!Sr0H>zPs=8jhnWMl5gzuowwXRWER8T zCmFBzO13#$7hJrs=g2Q-n>~E0wkv*5++&-*Z%xIrwQ=?F~CTYyZ=F0SCtU z+xH)ydv(8U>74zhQjhj;*Z5*LO-tF%%1FxguUgq&hpB3|pPnAHo!Pr=uWh*9-Ze*_ z*}nbgWmA@>xc3(G%)QGZf7xDgxnUFjK-ktsm&Z1&IATx1$ND{jcjfnn*I&22$NbA? z=dCR^3sha~_V7sT^L2c<_sde=z0nP~_a1Mw+Pjs>!sfg1#69}^9@zHsiSF5Ky1*`j z$7Qc%=d^uN$GU9phH>wW%|Ekm|LLl||BvhK6Hf}Ub7;J<_ghiSo;AGjHZ@On@7cY1 zrmb1?#JyJ>B5h<^5AD5hi+3Mmg|zKW*=e>JuS@n!ubOOIR-?YR<@!RK^B0TuvWG9+ zJMl%?-hBry@71W+wYgHTdGCX>C-$uFG_ZX$E8XUV9?QNry&Lx){n2Q9Wy0A#Vhe8W zm1tVAN9~vK-crR)HVs=j_w_Ebwe`8YWY5OLOSZh`swyxMSt76LDu4#<><}0Y!+CGuBQ!6{VTky;tTSLXEHZ`*g ztriux*(_biV|(;<++K#Y-2481dAs*g*Qs3%R=scPI0icyq&an){;WorOU5c z=UsnfvpdJx#;pG4o(si`_cnfH+80uCc#r8$=6yGKs`u0j@$LQV!@XB^Hq$AIK8R(kJSuQz)y#0%{W{v>3(CgFxnTWtN_4{Q$hpO{?_y68{0|EPMyPG{{o z`+euv@2`l+ITlY@B_te&ZkCAOR!;!s_|AlS;w#?tV^2y1) zeg2^~CvJtz-Om1=|DR*?T|A z?6Tc6S=)Zb)b0D{GO*dtUMIBQH^STgrOv{=InGP%xt7edfBr`Iz(&SJ`=#gj?!CWV z%vH8Vdu-hU>X|GweyDg)B+n$%r4z}~}+}nG4#@4<2L)G_&NebF7bGp2D@hmR8 z?&_a5Ya@5qs^kmo6RkUD+hEXa{lH#i59^*&HX>(R_uh~$-y1xUfA7>R?ma0>N^O0o zKiX3`k)PACdo}so_x`(R zwD+ai+Pw>wHtb#CdB`SD`PbfrOZK)Cex2Ww_egZ#=YR9}fNY3ESKMlAXD~ zg~w>$o!W_ZLccfcJJ;H>SKZ{V4G(YNzQFw8-HScn?djt|i&N2l&Es2kRh4u0#qTQGpPuz|ANPDI`#K4qeMk4*w_SAc z&_1EOv$h-!8*H!sO5WSKA=b93Z0{aMqs%>f%BtwsB{@Xlwm^w#`bN!+W-IuH2jKaemKvll`_)b1v`o z6;ZPLz;NAm!;PrDYUbQ~Lzev9qY%kww<_kKwNla3Jvqw`SaW`UyjOSmq`k`aJ+{5P zzil3uuebI1@o4WocQL!PkIegQ1!wJDX>--~>W$_-D>=$-1eclYDY&s_FQ38|n`;5l zdvbM^t&?L{?yc|R-fQ%>#md+6%--vF{@L7kG~MRpg)@8o^LN;4gub!mv9I5odyspt zt}e4}561$VdiS>7tDQLP;-1{Ku`iU{=f1Ul4-@B-{n7e!_x+ps)NaRmY5Pt2sr#Id znb_`F)wS=!Q(Jp`+fDm-);_n(>@?fQw{el}{A;uKF0I_VckvOB`38Geaz)!3#Xa5I z{p|1F_uZFm7vIs|$MN^}-k_QBdt)M|>|L##xhF`9V{hfBw|n{7Rc+*dt+G97uySwA z{#iDv`WtL#zg)04tmEunmh4A+EHah%PTYIbcELF+_EpMw+I#4e&01~uf!Fmyl<5@e|*6q`d zy;|!vY}Z8??%ivAbg$!~dwVoP5^TN%*z8p~+h`;At!!`YtcNxMfg5da_Vw+3(xbcg z!MrcloU5evx|-WMZ!n+5kpiniO#`WLzPQK0aio4dK~LUxDkv%12t@12RyKGk}^eKnI` z+s@r>weQ`j9J}K4RkkITclKVg^Rm&~q-!Umzs2Uk5>s2rSJJk5cA9%jtGIS|SDNkS zUoT`G@=a^+T)tpdsuyxJSte8J}JNydF_-R(B3kG#VNbk$~(4dmoD##bd#{VYt^~W z=#k96UqwPG`42xy97h(XM~L*7P-dD;V4CjUQjLo8We6Z|PJY+lg-6cAu(JY)(J@ zv*(BIciY$#=WKj#bL{PwZ?lR@wX;!s`C{K|*_rz{v`g6ita7&FjtSrY(S3@Yjp^k5 z_Ir2ltDGrgukFol@4Ia4-b>#&_WA2t+O787YxC!=(>}G=Zg!f6$83Ln|8DEI>%|_G z7FIik9m{Ou-j(dRB7A#KytTiLUsd|vs~00}-3`3=aUJirxjQF#kAQmpp4bD~`@^JG z?Y|V?vR_MC^nk;r$M)Pml@16l*tYLt`{R8vrGNK}oi?@K{_4ygtHTzyu3kxd@AZW5 zHBwL76U1@ZHu3|X9p{X$y>WeUw&mYX*j)XlWLInRz=rF0<6cSMw!M3^ukMlae!bU2 zqiFYS%bT{YdVhDRl+3j#J!fz0u%Kn{-)}cky2ke0Iz~Iy|4O!d;tlOJ z_oUeUG4Hco^Im%Yat zpH|y`JyN~bswc@daQ_xtf#b5f@4rvj?QJD!CvUcWPv4)ldl$_-X-RjF>acfJKC^A7DXZPBOPlv9D0*9YnI_pr zhY9WT`SZ!vPG*s<;!TmgM^-S~sdc*U(QixK%XWB^?Jd40H(OIS$m@ zA7!nvmskB^ch&Uv{))>Q`yM=H-Jh|x)lO`~|NR9g%=fpv6Sj7IdC7*AbN`+Tt0(T| z+{b0DXs&I0=CF>f^f&Fjxm8JfXC8TAywnF+`Hft=f0$H{(TR2huf_z&)X-z`^R40n{)Sh|5~;8UiR<3jP8f6 zgikKC-LQgTpL|gL-rY+N?p^aid5@mcP1~9B$8EOwUD%_1pl7e`McIAnA;vbB8hQ84 zEitq4+q%o9>#m~RRWlRY2|?Ai^G$#6O_*`kdXdbhy}wIMZD-lA?>qMA{ocGM+I#0Y zFW)^it#i+eX|1+wGv8V}Hg2^kT$^w6sHt<0wEKTs-J9vQd;U$e@%++i%W2)Y=Y)#r zJ^{a`y?cwc*nIoQx$mIu!Ts(V=Ix8QxOLy*xvTf@zP#Gr?(-45&xgkCI+5A>LWcy@x^WL1-H}~4;oV86Vm)tv{_rsny)&_fxZPoW`ADC%7F=&x( zdkoLsfHPC~>||2hyD9Xbjp4gs+nw*&Y>f;a?{(q7Xk-3(iA~Xd0b8H&c-vXo=C}}Dq-DfQ4W&5K{)b7oLS$nhR1lS4o8`#NL+^`l|J#+8x z9A>*)ZEN?3_!#fc3q4~UVS2$Xt4DA@ugf*tR!gh zaNmWS?0c1s0_^w>t+d+~S-j`d+>E{QzXkU$`MPSa#(jCaTahz&y%iF-``;;Kw^MzS zjpdroJ-@m%E{D(OG`mxl`BLimRXA`>3?t_5j<- z-6uYMvwf^})#kC`!M$@W!fei3w%fj$F@5h{J-+>$qD}V4`sdhRpR#G6+dirNGYW)k zqxsL+rSF?!^H1!fU1RX%eK$U?wNXys-*-G_?_RNINA?=6w%9Wx%5$&%52L-$p0V4# z_;SML`)Wno%i#vL-%TszcFpEfl0$&-|hW-FO_%OF7vbA^M`MlZT>Xh zy{1~{_Od=$zGt$g*1tCYx|ZzqS-NwN@S7gndlQOm zE2hZU2<-0OExKxt?HR=zdoMhwwn4N6dt6)=odR+hqUkz0;co_AOpM!FJ&iseRuszubLMqs!*!H>Q0; zuWa|~UE$tqcZ9|EXUkbzuNOMDT$@vE`JGnp{hztOwwHVU-W%F3d;dz!-)o+|z;@QX zVB1>mJ$s+2*4qZ(J7;?*V4;nNnupB-ee=C{-yGXJqf&kEN50#84=jISbHL#1-g|P! zd%yR%?EQJiZC_;5`Mo;*T(&){-EB<6ChZaB3fwFCag&|I%m_Q5N1Aq(^EmCQR(S6J ze)RahBd_P!Wx5}=SFV1#FWh#wZD!H*y}|rhdp*oK_s-k-$VTAJ&fWbH%zLwgg>8|A9%_TSslynoq)+_whz7<+n!p}wRd6olie#W zitJUE@z{69u7BT#ndkP^MDMg?f8S^KndOMxf4@w-pKUAb9@RzI=}aiFdlFY|eZAp} z-HLS1eJztt?1}!Cw=Za3)V^0!rtQo4)wgeZkitHtd2{#0&G)s}?a16e`)Itqhu}Ip z&h0JxQ-4M8-&p*A-!ThOJLMmI`~D}c-nZcKqW#G;6zm;R829f>=dlm-iQbNJ zW~cqDr5tvCl9%@yNgc3TSK)4dHS5VflVqI(PF3&sANc8M7hCss-{DjFc6M!D_LIH` z?4LF9g?;Rc|9iJRU$EaQW4>K>e72q1p^*JE-#XgubZy=z*TZSMCv?F+mA(u6RH6?Z zc<(3YsP(Qq3d_$*+=i4 z9A{`7sG70&yjQF3#tjFop9@y+eY&81Pfdl7t@^KI+piw-HW7zj@4j!Xu($Dn(moc> zT{itI{r8sJuGw2~S7D#`45fXo!qe@XoO||vn7L;6%$oLn8$(a*vDz}vHnG0MzRk#D z{|CeO`!=Zc*k)FL*c-!9xBpIloZX+Nj&|w)lJ@ik*xSWi*|l$5ThqSTy8HHK=sE3c z`Z3M+(&QG~IgAZ^D<+%Ts;BJRqj*->c3!mq-ifOEd$pK1?Y+M;z_v)@qWvGv!}i7^ zEeGy8EVMhC(!1YoMZf*2AE)=9$&%f_#D1cEy<)G8pO>f2-|uC6Zy%Uv)9v87`*+wP zn+MW@yG7-d_a2l9+RLKZwU=*Ni0zz(n`~>lO!oP=aqO*Kw#z15@6cXh7jL^IE(`Xq zYjfHww5iKhXUj&L$94PdXB4ipPwH2-4_qd>U&<}XzI6W6{d@j2>~}QVX7^e6*#3hd zQv2V&n7yaYuz7E<50{O+ocZ27M|<1nE|s>I4!yFq4v5%$V{MV`1m+N1E?X&^Y*~jr z!ghRiZ+k!4szw>?W1X{TPgqdY-sCr7d$az8?|pr_XK(id**)UVukJ76U11mWXSv-o zrSkosEq>d5>t{HyD#^~CjWu+iLrT#8YM%N71(#Or>!?Vw`+U5_{>Ubl1CvYd+3t2- zzyH|nZFVI;Z`$hVOtb$TzSFke*W7;B|26yP7QEh@<$7@6t+j9W8tjPQ%eKjRzu^)4 z{SR*k?EBNcc(1-~qHS_%zO96nlwG~xvAu?D^?PQQ@35J2VVjN5lKVEs-}8 zb(8R}Z9KgDoGT{mVec}wU3pV&Z;RQrJ#p%j_S$T{zdPlW@V;Ja^}Rb@G1_*D3hp~m zJYmld+u61=j?A^;cp+wc^NGLhT}>SqV--YBizlk(Ko?rE&K-OM$s_l3o**tea3$v%gyCOiEPRyLWTO|}^q zLu?|xUbHQnWoNr2aKWCQKp7j^nIikPA7rpQD3WW-RuN*ya#mvB-Cv>mZWVX#H9Nqw zZ<(B{-ETXmePW+x>|3UG(q;=s$Ue&}5w>le^Y^TD^|QU*cgN;Pr{ zU-@+J$wPd0YT=UmrhMCLd+T}3{=MC*cH4Ia*sTlG+keDI-mZ8;u-%I98+Tn-XRxzK zf3kP!c~jev-~)RN?N8adXX)EcKk;jK$IK(UpQo$r`=7mGuPdv^-W^g3`~L1N-osj! zx7Wab`Ch>lZ}xiX$J^d$=HB<=*zG+Ja~<|hxvD&Eu38!nYke>6pD(0z zAm*Cn{#T~z2NE~-?&l6~u$@@?Z-3g#!u?k^sO()~p|`i8?8Tm(ReSfIQm(Mg_nNlX zg*9mJyY9}tYiBRBZ84g+$LnRs-g~MHwym=U$dGcWh>Bp0W*K z-M6=HR;KNY)p7ehJlGv}v@Eb==v}qnU}lPa{;!AoTc4=gxBoh1duy-E{#|Rl>|5qd zwUwOEYj>MX-j;KI?%s2{dA9F29NGJFQIl@$!3YtL1CPN|*SdwENnjkwI0T|N0z_nZv>ySHe5uWkCH_qHkz z=k4(}Y~Is&^Mm!Hx|6mWdFR`(9^%bf0P}1ApPzo`)|Gxc30T0?Bx$wu)imA&Vj-M z@9i_n`46xJ9No{{rRcCgb^h&9^WfAnpSoyfU!r8}>e%>0tXMIDcP}+jhIzld|?Z z{aLX$@Il+|n}!K?Z&YvX6P&HGZ}q`D`&R#o+Glb;z@G0o@BV`ir|mbceY}q^DQ2JP zhvoZQH?6U|!#H)nOn#XCx;KvYdHmx0CnO~9SDYqwz?9?ae(~Z2dv@!n{f-;k>evFtycQeaJTdsi&=Mpr{?IM2l@hX3d`e;!pOhJ(_6y z;-u8R)T^wvh9_0`u97U9tjkqw3#XdfhJM()NAybA-u{OMcK>@X z@4XW5xTmL|Yai3)hkIrR=*a+zu6l1#x7vCQ{CLLci&g8eKp~$t)%BJ+&#bGoQ=qY zn7!|~toHJ=G}-zZ^V`0g#A#c>TV-qI*0=Y?EkoP;?>5=aIe5YLhRu~dRxg*^e3SLw zeQD+2J>Kn1d#7k++lG8!Z2MFqbk~#y#=SS=s`j(lY_v}@+-N5}o%g__KJNXe=3m+$ ze^6z=>$e^IOn1-Q|HoBy|MoxOHebqjTX)2~-^=N;(l)y%!S-B)gUzS@qkFvXui3jN z$Jgfm%RM$fWBKi_hif3x_s&{x?^@5Vwl7aS+@~y-Y5R!Z##ZwEo4sD;?Rx{~l-N49 zEUe4e2~)`|$ID zJu9m=+AtQMwfXDIv9I`r&R&J@ulF|oa@-@T=3_H);)%Vt4t?H}6=iE1{!YU7fpO*D zh+ILt{eN2b%KM+TPUdd3Sr@j$_9)ZNJySou+I?XWm)(vslf7OtVS8P&4%p7j4zrb= zTCg|%#g09E@{_d=Y;${_@7=V$WKWG;qD|TipS@S6%h`Iez1m}EGixtjnyl@bomB_A z|DCgM$v?J_`^!3e>sJ@{9k$Q4@0qb^ztJ{D+wAIy12OAo+b{X|W>1ymD=W_qJzJl* z!PYA4gl(6sp0T&(|KGi~2TbFJp>g~76)FkXt$yFI zPp>L+ul13Adjk$c?qldYu(#;qsojP1f9>g%+qjowY1rP&zpmNL`Xaq=x%G0_S6K&->X`@r_^;c4*1K`PVndMqIqyV!nIkLqbL_pizb)Q(pXq}ed%py&x8472 z!(QJ>A~tIUSK3MizSujtZ-Lc$%}kpM9M5fXl~>wmIuz}H9L{+_#_p%poz5k8b6S5} zM;%*i|E_7$el?@z_A|qK_Puq@+h6XivM(fG$!0~D>AwEVlD(#N%C;KzX0{PxjeBLT zX4_UKU$9*f`g-p*i%oVMXA1T$h-EmikZbAwRi{4g=l7M`Kbuu%AFt-aeTteY`}M5X z*nKx@+7lVxvG?AeZUEB8bj>hI+@I<$vRUeV6y4X54mpQ?KUwJL13b#2(Us^P>w zp6Q$HMD%Oz#N|Eh!{lxDJ>X!s|I8n{KUnmso$A~d`*uBcwNv{aY&$9F(B5^E`}XDw z7w=8hWVTsn8N1hlrNLS}opqmBZo=MH9yz;J61Vq0Tz_h>Qr4_}-;RB<6*=Q-d(A;_ zUqf<)-I{m(c8x49`{ZVxvMYBo+NasscwqD8qyyQ!J`Nk7ecpGdsCB=sq^3Q?lJ5Qa zUDx&-TspNsMc>SRe_MzB`wuJaUpBEGkhhq(e~ZVq{iflb`=5G6+0D2qxc_6(Z<`wn z8TP%kQ`=kbq-R~<{bJAg^|$t#%d*;*?AW#2_T-*D!R~8zJI`*k*VwStCTH{I{WFCc z_E|fv+V|kX?EPt+Ci|ymO|fb3FSfIHX4-e1NkS?ayx7ynDu%t+rc#U*D^3`FYR%J4Sm8-*DQsZ=bYxAN!0w zD>cvW@msQGuhi^1`_37b_DB9c+b>aaYX7{DY4-C1WcEj`XxVT3c(>gg%jx@{czv{L zia)k@$(mJmy(`Y{y}8hNUuHeC?Gi8Uy&7|5_il~Q-ea`%&mQ4beEYt!1luZk&apkv zd2}z|vw*!V3lnX4mM7Y%$xGQi{J3(j@3KVOl!qJknzOX+Kb(|qA9l^h{&BppLw3%V z{Rh`JA2{3`df?bjU;Fs=d+mOCNZLPK_h@gIU$>2`p|j1MlS}rxAJf~@uyNAf57 zy>dD1CS*;t>0o+byV*oxpIo7kUFJ!ly>BddZ7*6V*a`2D-6w0zy6@xqEZe><>bB99 zMtgZRm+rOUmf73L(qXIc({N9cfZJXp!-acK@s!xMSlzRkvUY+E%bU)iG-U z++RF-@A^#&wmQed_SzRa?X@{}+ve))*u6m$O>O=NKea7AE^D9a#bs|9%(mausmwlc z`<}i2h9B&d8J5|x9{;(obd#dpMEC#umWj&RZWeN}`@5NK-@SFtduJYR+Slkb#a8(S z(_SBA;eF+;t$WJbnfIO3Twzno%e3#^4E4Q}Wxm^TnRM8!-^IE&sQ3v551(Xn}aB*>oQ zcFq2CkGJm6oT+7}ojPgXW2Qd4P4@Hm?cTH5Rv|XSKIT26{pQ<=d(!4e*>2f*Xz#~| z+ItV=_t@;){K+<1aFXr2<*WBdU+%J<7qoY;# z+5QthZQIbpw)fjR?>*5Pmu%FHYSjwclS&)yE4YvJD6N9XQ2bzIUm z(D01Stva!YSRJ>wGjOHN&7`Y)ST?<~^<24n z?{ZPIy36#J7q7I~zi+X$-ODT?yI_<4-TU>;-b-7vZ8a`U*pn~ZYb&_xg)Q%j*LxRCS+#rX zwWPf3eJ4W%dS0weLMNb*jzz4}7+LPj>FTeZP6Hapi2=*@t%TQ~5A!-^skY``0<<+2&q3 zZ(AS5X7Bol;egW#Ci_zi&9;6e=KJ=%kl(v><+ObqGnec+x^UV)Rux7Y_g8v$DjDW` zw|Z{ad#PoKZRIhZee6{}`#M9C_KMlo+dlm^*-orKXz$ln7TdU_#JwD6@9eRuI=6Rs zJkQ?MuP*MrojSqR;Nx7I#t#c@7747hiQKtx@BWs(d#;r}v3c-!-QJ@qd3$Gz_3za? zEoP@<-?Hze$p5`jJG%Gnu|K)zYuo&NvUgJUEK*)(tFYwEUWTSV+jI3?`#$Mg?=^7v zzc*@q$=>-|y?ff$ud=n8#cBJZ=I!puM^D*b`0;rkV_nJqS+}0q2OQ+xzu^V<{zcE4 z9j@x{wC}s|$i8Ur^8JkWr|nf)Ds6M@{v(_6s%D$_>+SYhY;CY9+qQp?fiSzRpQ-rX zZJr#vCE57)F>e;IRQ6tK>$zXc?q%yvTbZ{R`|cewx7oqCaqp+ahxU4uuHAc$C3W8l zgFHKCwOYFb{W^Pwdqw-}l~e7WU(m5XpyIRdxKZ8y0Fzz&4=J?Rip9y>ma2B`U1YJ& zW*x`#J>Oqnw~hbYwO3tW%3g+RY<6pNe(pUv`^moEC?C6Nw!7`PZhG2j#p&H^Z+`3TXTG@8?!WIr+uJvI?U^@x+beBbV)te3OuI#b@%z>(d)jfX>Ds?l zg5Un~mS=m5(x2NoKIGZ&q4B`Z^!j4^uR6i@|If(mFMo4v|9itf`y>8w*j`PvvGh*b zvZr0n-zIUP%-)9ZBR2QnKe35>HDh<EckEl zglEfarRF@{?ZB_Qch8Z`y-&2XY>(cXv-j!Ub$jpoMcFPo`NQVzJ5yV~Np*YfD&F5~ zZEj}!-lTr-D*qEUjVinBn1oK+y)eE7v)cNb;b51%FW1+D6^R?OCA_@0 z$HGEvf3D)O{go4H`(1XqZS|CSdqozw?)^S}neDzQ>-Oe8u-ofU8M=3cxvtHHx?b!0 zo5tzq_AE~PyqEQm#oon# z-q>UoE!;EXteb7^{dId^%c<^tuEJ*5``mwTtjv6CWnbp~j~A@nx8(B!JO9H|?0So@ z**GSK*)^%ovfT*;$a&AkIh$>4bL4Fw zXdSc7PAS}b(cWi6+?XZoS z=C$wjW5>Pr9(!$LW-Yfd2q?69k@#TG_4$Ww|J@R{Jz9CoHsdM#o->vYZ5o!e?G0Ic zWsk#6FYEF}3vIVt-nMt*&+E1f!p=5}JXrPyYpk@jn<>55*3isD=j<6*igGb zd9?$r5?k%rH@@4Sz^rWFB+j^(sdusM_4v9yPQhCHcusw_*-_54@Am2~dtVy%+d7mT z*gMBYWN(f8vc1hJs&*f)O}0JZxzNT$tZeUO(fxZ?^orW95>VT#_t#~Qmi`9I;0YGC z3z#EqKX>x%Tj6`&Qjt-_?rNohtxHX(ZT}|8y?5qR>``H!Yui3Q(njaJmhH_&DSI8K zUb5{C5VG}at=hZPhRN=O`<312+cWk~D?PjS!m42x}C7=`V4 zRF~{M?5Aw2&G^$U=kvM!Dvzhz_INz8i;G)pXEL$hwt7vM-Q5pT`+uI)uoumg-|rZ8 zz_wQ>eeZ<>!8Wcx9_=Zz{c3xt^WR=6MYnxcMbftCe>Uzlyw0>YV~>d4u|+0(A5_lS z^UbBrhJ*dko_$jC`=SKeZ0c$^?`e^>uxz2kGTCs?KH1f~S03fqxARu4?OXGWd)W?O-NUCXxUV+v?q0P` z%zI~Rwb%$0^XyZbEwk_IaWUJ6R~4<9r*E_|duFhAg`2$X^y)CW^)^Cp9wt9Jcu1(RENZW~(%C_v1H}@QvQ)PE@@$P*Ww<_&h_TR#; z_*B>aH&>tSJ5k1BZ+w`|jwQX%PNK?d|J0Btd!F2zWBo+^_ui+%k8HPCRN2nHf57&4 zrR&~TQ7wDx{w&zrur|x8>EQdl8TLzT%d47pA7?&mqnrBBwsUKRP3fwFy~>xx?Oy%) zZ&SZq)sC^Wac|{!vpq$RChzS_uH2ha!?90ozs}xwM?-D3o=&!PC}XudBi3PaFH*tw z`(sbrzvox%-ddq=tGa~EZpVym)>jgwZS773+w^PK?wuO!XIt3)d+)D3nhwGVr}k?d zn!SJX)`|As4txiubuk~f(-CA}b1&S^Fz~fi{2O1}!{2W2NzHBDd-$^3-t#-R+H7wU z+~=os!S z58(5*|EA|^D{=j;ZA@6-ULD6-dzEi3vOce=y|?4%`n_V8me{VGvBx@e{q)0qQ(AuWz>$_7C$?>chaTI9gozVyO`7Z0Qoj}fu`SGVkK%3?Ka zv$Z|;K5IX2Gw*Sat+#!Mt$=Hit!(@q+w~5bd*4d6?W%m)Y5VYeh;7=Z3Y$D9OZ(41 zMeLtzT-;ajuVcT%Ar(9Br(OFiQ*YbxRjKVyj`ZAjeV^L?KT`cR>rY&>t(hHT+jZE{ zMnk}Uuj!6EwsVEjY^8a6_SUMt*<)>Azju`wll`v^JM5kxFWvtqc*(vQCLMOq&N14n zHrDTT&g!$X7rAfuNjhlXQq~t%p4`#4zF(|tuQkoxd%=Kd-)W<-d-T7t?_0m+!QM0X z7Vq7f?O=2A%dOpgyDDv&_BGmu*Zj5p@=ngS*fnvlq|jgM<7fD6AMAZ(8)t86mmq(>^?}CZawkpiOY^+RP?Ntx*w@SIU%+|ljac@NM zdE2GQ3-=seH^t_TdyVa$9mcj=3S#@^*Eretz1Ftp<>TJB_y*s8o#~rxZWIRZ%e^VL z|5N2D8{35Qd!v&7T24vJu$f+a(dPKn3%2*?<=F~pFSAWL<6^Vqv%%iE&tC3{O@6$$ z;(L_+mq5+~r*)L}_bS%x7mR+p|6Y8*{e(r!?R&-E?`M9!)V}W?&z?I4^K55Z=oAznXPC?DROQIxg+|P3CowPT{mR(k2pWXXsdz=N_EfTjg?wJ|& zVQ<<_QMq zM)IHAdqsKTp2ZK&>{;}RWiQXAr?waOa_!^UvvAMclVW>%^k?r4ieR%{qGWCJ=&pzL z=^4vy&bUO`vAaLtH;?n`-X(>T_X~T7+P}85uy;~owbyf5zMr3Ww%vPeuKnk3i|rL@ zso1CQb=r2ugLK;oz43daE8A`V8EfoazAAffkZkeZ#nZiQHiri8d0soicE-$mdph)u z_g>!e!`eFHxb6NB3mdQfhxSf4VzoJDvcu+k5UcI%qt|UyLi25N_nz95!E$4d@e?K6 z3U%SVIw?nOoHUQvcBV($Rs~Mj&n4Vp_okoUjm+|^TTemaZn+qz=ro(7L~d$}0b z?G;_0VY^^aigZF{0oc+WXj-Q8XK2W_w3-D2B#^3Sfn zp{H#RrRdoTWW3l@XT-m^^-TW0687V^MJHa`6!V<6apYWU`z&>uZRo9b+wiBqZ5F6+ zviTe+Wh<>Bvgh`<<9olw|JvKIQGAd2$}77U?_9B`t!0|c{udm!N12@VRHdEY`;*mg z-AnTUoaAtA#{w0NJ`{O3R+P|!f^MKBNnf-yMd+d#sqV^py(YCL6(P#JNs=@vj zKX?u}1?kz{^kKKp`>|(>F==npg=pJA-RZVRrcbje`?zQ?)BMK0i+CCLPSN_aCt%|# zYx`?8duN7U-aCQK(UzC>iFMnaqkGM^^V^-+pJx5jNp9a$D;C>h1vmCAKVh?Xx9~#9X<(ryL?}vTTj__PylUckZEwt>@$Gds}wM@0&Pz z@7~3Av3pniW!-xw^YY&Bipy;M)YjQNysT%d-lMU%-|4rlkn{7sXA9+Q(_$9xjjpNP z!*gcWp1B{m_MNm6+C9IJWABRULwlPUI&Ch0mDoF7O?dCAEr$DM8sE0bH~+G?G;p)s zyfw`BUM?*A)}8R$cQw#$-`+)xwg)eK*{3<bmoNV(N18vn0&fRz6?@ZSGnI?Txt}zjxK0=G}M0ckeN&_1~+!X~NzQO>6h;e7x6= zE#%z3wiB)UX3jiryIf6hznn~!-HOe>_Ds=X-@mC#+}_^ll${!1yZyIvQ~RdERklG5 zs=GI6$?e~_*k=FlJq!0v&s)5YEu4FAd?Vw2<1XWU+b=QM9!jmUHRmhd8!S3;kGsXi zy$Z@d_EvqpW4ris{=WR6z&&O+EceBqblo?n(rn+N1GD$a?GfI$hU14Vzw;5B{8^6s zcD|WlJ2|y`-(}7P`$Kvg>{6JtZS^w0?tkgA#lB7AjNP7s19lJR8XQnO^l0zaW1ai_ zcG}v`YwEY%a+-Tz(lNU|-kD{4mWyicJN=PsFZZT}w%pRw_sU#dygRw@ubuV0==~ZG zw%ARGu(m(3GSrrTQ{DcV4|Dfl=+xZbd}zNN1Anls(S$17gv>|QGJ8GuX4WpXo$|YT zuT%x|-pL-@ZH2q*_eN}}wt1P|YwO(Zvgf*r#=iXyhiy_+`S-E4neRPjX0UJSg2%RU zq1tVvp8~ZXRf{N?PD!_rf<*LTjca^Pyf{3z0vbIZBHL>wz1rIfA>Q9Cc7fD+I?C^ z@_V=Lnr9#VK5d)U6zmZW_?(ls`Tc7=NzBwB6fFf7??`=Q!4$*^jVK|!?5r$?T) zf=3SQ$-1a$E8k#k%kX}JjhOK(+m8NywzsMTY`4D_uzjKXX>ZY9l|47qSK1n_71?)= zo!QPlW7|H-#S`uRl@!}~rdZn-SnKRht+3hat9jh+@H-BBF|{wY8sSX)`OEojm%Goh z-M#eVUgla3+q}p1HU}(3_x&yVyjMZ#lI?{eAzMZNg|@2qlx+Jh3fkR?zOd_6f`Lt< zis)WeMy-9HXY}m-Sj21>nPz4?t18|0quvUeJ_q)FXYU`h+2@sMs}*u(@A8NLZ0`DS z?=$~lX3Ll6u(wXR!8S72crUNZjlJ*As_hHC=)br3)7rf=^^WWn`N3ct_wCN^qCVk$ zfq_f+ESlNB*XxCh1@=`<7qVmg&9-k< z+83MsY=>>~9o=mMQcv%lq$#=g(mn@Uhqy0$pVKRrsy*LZcp%=kLzCUs%BOX2QwXPRnw+QY zy}$2mw?EyuN7kWy@0XrQd#xBdcJFfXwu&*c-W$@lZm*`G3kGL1mcTg+n@fdooz|xpw&Nt?|#cV+?pb zyQg9opN%Wa&V82_Fzq|sr)qo7F=Ox9&?$RL`mgMXp5kH`{ikTJXXvB7YZETo6#4wy z_ulca-46ik+nU z3*YX&HAiZ%P31?Mj}M&o8Z~;_o~>E2cj`{=J>p+OZ58JS+8#Rles|&P&9;~R?XYF@ zUcA>9@Hbm9>BO?~{9%ES<6Mx{BKV61ms=oPM*~KdEiE z-+qegK+YXQ`$fML4@BhE*hx9Q+poW+d%xg3?Y%Vu=C-f)^zWTq?YGB0`Gk#Tbf<0d zWi#6vcTStazcss;3m@GpBs_n=p<~LvIt2wgEs;pOLX94~c#qaSQz9JpyX@?FP*vL-O+@~xubuXu<%HHh<)%GTJZm?1MXSnBj63gDKb#wQezOvk2 zX6ftwYihaoZ|RWQ|FCSEy`ZqffeF>E`$Kfo?Xy$w+MOt9x6iW{uqoTOXb+DP!|wl! z1Z@?$HrjBh&b4h1?BDzLM5gV(ORM+XzBR>Gq5Ad?`#I`%#{bh*6$jhcsjQMuNEDU+P+pIsBO z^KcW|FLnB`J(qBR-Ilp??RpFz?sFEHYoGF`dB4X5ul?4aC)l#Ap0iiBM0%glvW@#X zgjU*KSj}R0KuO-V-0G)|<3)A5xeFFq)xzbyVvsd zpIv?%F7Lg0z1T)*>cKtnQycd-2wmM{U)8X8?_@#iog0tZFt=#f)jX5kr)p+m_b5!; z?%lEJd(QIB->0!Ce&3g_$F^cT7j26l8rn_dQFVB^uEYL~=wW+dQN9DbXU+CoPO7li zdfv6azF+9TOKrmg$xnQCyM&tWo3d@UP4+$T&aAyr?c#r zt(?wI+Z^kIHic7T_8eyxw3Xo9W1D~G=I)IZL3_7ywC+jtliJ6;>8^dh^zwbpwaoU` zQ-ANf^|{#o?+3L5EvMV<6*dRieLf|1;D&?ce(AVdb|pgdZ1X<&*n7NLv^V}*^1jq9 z%j{=Jb?!fr{9>O`!!iAhAyxbW8$@KIo@V_bXwA0HMZ-!KOPU*bK!)p zt?I*bHXDvx+Rr+C^g!KLBZr)*&Gv=284j%YlXbvrwUhmcMHBZcIj!AiutjnIw5P}R zzCE+k=HnVA+vu!)dv3av>^}R-bdNUYqrDw}xb3dmYwexS@OW=Z-P64ZyI<{@zhH@N zh51XHJtkeY=cG*bxcr&E=a=Yv+wen0wl`L6ws|0b*}mx5Wc%E8yoDDE-$f@kxblkri6Fz@%p2-(I-Uq*|@RVZn-{VZ{MNidrv(K zw|%mvW6#4mSN8nWTD~WJR-aA&YCRjhKRVXC*Jkb(xN&XoLD|4P$IUqGcIBz;ElF#& zj#HG`>&wJzcS!l{o}xRIdnGl%zGr*A_d0mg*&Dv}IxuH0uU*^Iwfk4b zHtf^-bAJDHYfXD`W9b8Vd13agfphFawsP++Jcgrem+h*As+nuu8 zY)`m(?hVLQxBdJ!#&$Y)%U;<^4m)Pfvoo^o%2sZ+Ejhf@HY2CiZvU(7eXXz8?2C^pvlVUi zx64lLw7Xg#vTvG1>%N$jzt&S%XWFXr8`xd@xx+^HyN&H~$3uHLkJ;{fxonGVvX4bn9acozg^7zEsF~ZbfA7?<`xq6N56paZV1K~6nfs@H?b%;6D|mmfhQmGy zg;qPSuW|eCUl7=vuXD%t;p&QgHWw}IUffz?dyO&BcH1tieR7(8d-ts{v3*{*(e~l8 zZMM%#R@(NQxVg8WTzF5;qWOEJXYbxSYjwUYgG=llosBbW5>$M5*GDe4_1F?=vsYk) z?VPW^d$Z?GvyF4Mvo&;>ZtG+H-{z)MueHz12YaJ4jBKV$NZIZCvUTt2bfJAupGoe$ z>&U!!YY>+mqkh`nS8#k5NR$X%b-tc*cZ1VylZP&lvxR+<&@x6{p zuJ)3DIP6b7vD+th?eOktvli|9Z+U3{*Q@&bF4bM!S5P`<-{Z#n`<|%_+O1F8yLYo^ zsjbKsHQRUG#`~VL_1henti9LrZ|z@P{H*xA5JHCFQy+5zH7`ND4HA02z=o3{Jpb}8+3i|@5t z^vrkv`-hwDrYpAZH+!UJd&QmIE;>wXUq$7An>9O6+lC8p>`Ue3wk=SNB|gywm1F-uk_q_8GR!4wtQCj(YF?Hhrya`igTl9xpv?-#lJq>)WNU zPuNyqugbazo5!yiY`C8!+fL#$-aBvlp*_D|Y_Q(@=*(WzYxnl%zuaS&Z6&c!y>roC zvmXZgCKPwuYBmJzQ@W_R@1dRLUL&EIdvgy=+UvHQ$7b97e%pnMxc2PGPS`u`tiJ7P zOW}RXmvijBD9dLj&8xU?S?5gK){J+yf(y6qughLH{?E4C9e>%pi?g;hb7$RqHB!vZ}6jhWuyI5 zXP@$uG@I9zTy{pWH?31VUhZ}L_GgdqQ=h%dw7B-%alCH*S74&;Lv;bWvrhW9qCa|U z7hm++Yv6d!_Tx8xTQ*6*z0DqFd!` zmK@sW)BkL=t?;b07PTzgyK&`yyYPBtI}cemyP9X4>`XV9+wxgS z+1+eW+BfytIolVJhWmEjG1`ASMP}cLH|K5KZ@jhbNj$e#WTwyFDRo}9pLSZ>KDaJm zBmGclZ^4|ty&o3`+MM6&xWD0*z`mn4C-?rJFJ*te{=@#W{eHGzf1ld>x_k3JOPwWl zqBhs|ZAullwaGlcr})BF+XLD2uMT8xwOIO9zisz)i}HB^#*G4(Empj%wK&y$+$`Y9#~s9&MT(k>LdP^r ziW)cWc`IOG#KWO-^MJJm6Kj~({)hg9 z&kX)s%t+p9+2^ryhZawk)uG=PtY$g?-bJjv*I836#npRva_^XI8NcSH`K@4%okfrN zcKvI9Z23KCwx!KIFUuQ_EJT|}ti9A$XDnxG@j|tChw=vT9pzi5Sr~*@>3*XI)6CG9rJNb*VSE<=?imM>OxSeM{4f_R3tz_Tap|sjpXetkr}+zc9(_}W zpBoKQLk&E2;XO;$+MXTGhU_~UpZjiKH&w>GcbSFRhaeNH^3|Kn->&Bzt&or_oq;5*y0RkpI?puE}aU0O9$uWNnWH%a1b?i|_b<k zHKoe7A1zn1=q-rdac70)&YP;HJHHAXr+Ph2tUpH84et=RQrBrNafH=ykB;KbS>N{T zsNAAr@})A%!u6`W@g4DJ=C4#9T7)}EQoVc;vUjzrd)2=4^^HcW&3UKHUg@9P=^o3x z+h|&gRo(1ntDS7KEzUfiHR$UtmhxDOYlkd$zV};cS$)0HLRb2XnLg9`oqCC@&HWhk zceI*0?O2uIGn#)X%tlS&QdSd-zU|m^i)W`*<(6H?e{pZuyL!U1_fC%`lckN7LEc0w z)&AXsKD|&F45QjdLtt2kfTjO@tI2%pcTS!5d*>UkN!!l)FWlKHG121IhV_>BR(e@% zsIA}0-7{zBU=M^x#T}MYMfi6-xzMw7CR2muOQDk%+g~VKUKY8&W1@76<-$!*Ej=4M z27P(e@jletsBW+MF6Vg`E!CS$CFQ$z?Wk`v_X+c|ddzuy$F!Op^V;wAqxIWhPmn{@ zeVx|IG9ag4vz1W;(I=g_C4C$tB%~)EQSv+fNqJl8X&$|K{6Zi(V(`k2g_bVs`i;L{ zDK=x7)3oFLmpeP!?D{Q=mI_++cD*#w)$9u9sT^~2B&f%yr~%w?rhwtZVPbLYNkN*1r5=k1hVyvO`S zT7=~zz55nF@B5jrpZ=Wc;|xPL#0H1UPX#xce|3#E-4O1#L!h;GN08Y!Q%;+U($PKT3G=B@wMTYfQH zXZbaJ0oCilA3n#dzO{YdS>>X5TeV%lJS{`mJDa*2n`O3jw-csC)?`1D;)OC6P47B@1#44d)$!IArhzbhP< znP~sg;8?LB-AqfWE=4@*uD9yTq#C);4-7SUGj8dedoo3Cy2o@SYKO$6Y(>inHXS>+ z1}R&v^Y+@&An|smf$lYnsMjAYH|w$OI^^PKS;ihR;`+6z3*TByKl$1sR?K<(m(@Eh z&c66=_UBof*=G06=JVzIEEm7**nV@H)UG2(r7fRc;4ltbqrH=-IDE&yu&d@JmR6Q$ z8rE8HE==Cez5cir`_f0d6nEV;dve9YqB$XR+t0Uqjg~sRF;@)AHdT9b-%KNUho!)? z^%jpFa}Zsgu6%gJ{AvCP6HiWtU2auDmbpp=o68<*najRX-Y#%_hN+s!a*M1!`vHr$ zRrVjv{ha%DNLF`SD1CprZE3UUt~yym%N;BGEK6K`cV6UKY56aD+IDKE=TY;phky?2 z90`z2JyQaB%~q6Yv)Jv%CNZyF^CUY1rzo-bbqiFaSQ0&c05WS758n{jbcDe?b>VA^ zqt=WTQQMxH-o7KV;~RsZd9e9DGv=;%izD{F7NK8?2L1SRoZMO~->Y)w;yX`nSGQ)f zP)VL^A-k}7Cx5^U%N&Op+Z$Kj-&rZ!LUg(Nm3_bEX^nH(IO(%aEC?0oj*(dy>z{* z>z3KVOpRS!&%~Zc?t+yiMhg{LYfsbIqSO zq?=u9Vcz+}K*s!K+NWJ>YS&vPb?-FKJg;Z<`_3fGpBHXg2>iZk)qJ;y==k8)(FBKI z(62pGOE*vAyLe)O;H_l=Tuh?&BD+?`C|cSk2qzvE6td)Hw%jkQv2!+mwAF^hDLelC zm|~H?WWmmNF{L|<+s+Xr_%!|zCTFo)fvb|=S9kke3wZ+s-Z>p>@%W+4e*z_2S*8X^t z*ODto`yZf4p#VSZ5V!tm|7VBxgxsC)uFT$EUh~}YQ3%TpZDo5a-Q|C`OZ|Inx$a;J z)yET;CNo&wSRuaS+sCilOF|}_*yICwa@Dk2hi?<4Dw2!<(l!Zd>@Tx>EmZ>Ir!*Cpex zdv}>-nz`%832Zea*1S=5qaiR7LqP2QF^eN!OLxeNyxzfm_WX8>zFRxgX87)$745Pk zFDKP%>4}mZ2cK`Fdc8&Mu+HYVWVP|1#jeHC6RmdCneH+@zIoS;Cjz^zBEDJ8`*GIl zzZ&DNO^Z#4ZYNUPeWT_L%@9y4oMz$9;kj!jPuPx&;>z0t7B%nkKYV`2YX?EAq_06% z*UB6%&n{R>^myIX4f8FIZl7T>W5*Kn9p6>ATRgmGs&`V?oPX8?^N+W7m?us6Xqk3V zpX%u}>@utQ!F1^z{fEw&oj{&>9+P|U4)bomC26UVkG=+3iLFEm=SE;4+NT3+cwouQeEFkQVaKtK{C`lR5R zn(_G{W~0dtBD1t4#IHZUAr<_vRGC@Wj&Hh@EuDw7@J?C;F-mfba57PE)wasJ^OQlmZ_3LzkHdzICmRHGf& zR&wv?|E{p>fa+rlYaRLRzYnTdF=yO1|9f-#&L>vARPQegg|MNf8yk8#Ei*TK-#)41 z;1;&!OHAbXW}C0g+HBI^JZ*cF(-d>7DMz>JKKem){r2Iij#XYL&#sW2Cw6{WduUhB zzHK`q53k*^-Fuzo&brlBuV*Z_C_X-L`zohe5|SN!Ik%cfC(U;Ycp+uKAqeZU4=FRhC=) z_+?9_Zc46k} zM5h;Ore%;>&!*qCXjTo`b$rua%dT(c+y50FwVXJ?WtUoa+s-!jn^s-NmRSnCYovO) zQTcE0c7{y09n01{+8I!D!Lnh(&+T>$^S2dmU2Wkldd1?Y_eV=!HR9Jxf&4-YcAwN_ zHG8SXPQ^X#mJ7bBT6E4@U>VVGW`6T^`;P0TGM4w9PFXHLLHxNr#Mns-HHr>Q)_$D6 z7Jr^k+Lijs)N-&OvB_3^-{G?PS|IjyqeZorPL7y)R9BqY8N7oCUFuKkAc^=ep^F_57(q z`EOPVJZ4zRU-ogoK)>h#p*eY{OkyvbFnKAl)ktlfrtTa2y(W7DxnVFp4 zx!35v*G{7?WemI%?ACKjA64fzw_@WF(l_Hyle@vaS)7;K*U*i7%6E3|puMZOT2dwm zZ{gDwd?>U?xGPghLMXJ>Jj~?CDukk+$GwRGvcRiJOA@? z7@pb5x%(~~SMX1Fu82-ot{u0f1S6U!@z(_S^L5X25Nt2y6I`)zjbG(AOw3X0yy~y;wbwwQ=BJ=ysr_k%^BdE7 z^-oOX-MING-_je!-1Boz@o?(T=iX7aiueDK8GLDZCVV1?nt5dA8=KGdwKU!-`qk{` zrekJp*Q8DJel9m}Xkalv8|PcMm*Hi^LDT8xTMGCT#5@szDnz2o?`C=>* zkJ&!Tw)IBKyy2W7oh{KO!`a3z`fU0$QDr_SVM(zif*WNuME}^&7t~qmBW&EPE_!BK zu+aCfjUtWaA53)$O-)mSmzoJp+h?w{uiZ44Ws&)#fcd5Z9!_T8RxC7+JGI8FY{p{F zGieXluFhs>w_C5k&RMgaZBa=KyMUE2dvSU74w*7dGX{=D&}F8+s*ww_X>BjTQW!UR#DEkX)4@IQpw!Y)`xQ* z4-FL7`mtK1JH%gT5l5_$VxG20RQ@TU6E~&^r>k!jzWQXl(6WpBggg1OMAlj{3I417 zAu?-MlIRDv`+}e5wTPbX)fS%XVkF$`w@@UEPf9q`OWxe(J%ef7q{F5~Mu~bW0*;tH zc;jYPd#}$t;Do>N?&+~+f(1*=>edu-mrdBnv!vdKdtTZ!?yOhcTu+>LuuE9%<=XI9 zlbh4cntMT{68F^ zg%(9Yg;IWVh2n%Zg+oc7qfa_^kQ$K%GY##5fk%e!jwbaUZ%ou&qdc+8l? zo|;UE=`l@RyTo+r`$Y4s2})*B8E4EqUM@BJ^6?@+i@p)R^_{)E3$6d~--r(9KWTlH zf3kZDZ^M%oz9}YO_-fPK1>T;TEx_ilBhbw2$fI)hG5_{Ik^C#ldIZ)=&EQM6>E#Jq z-NxtC|5?B&{wD9_FUz_8v?RG_ryk;y*d)fMSNN4@Yt{tLO7+h?ZGk6wGp1kXWhrT;9bE8+bNI z&f)Vgz=ceGUn=C4%~y582xlXf;wpjdwgf1SWiKJEp7`4y`^@tgdc#Jlr*2;UO% zJ$y0SIKgB0pfD$dSETU>)KBT-_b@c%5n+@Q(CzBvf3WES|CHHNdBbF!`1(Ul_-|@O z2(*?hVC&@*HS_QB-2na#~w ztZGbuX!n|JuZ=T%^S8+~xZKwK_B&m(fBULUmv50WcDL#md$5&go!`5l9&Iou%CdgNsPeRjpF>4f)WDBQ>ODfXny0J zadSO?$w6uURKAORc`_IHt$ETUWwJT-ZhqM(n>XvS#Ojh-Wu59B(s9OKa;e#zdU;cL zrB8Z#Df9oV6h5=_yiiS$k+AxQOySc@9|`>v$`Stee53HIyRyP!do+Y&Hcb)wcmJsQ zOmAJY8ku9}#W`GN%vrkT&7b9M39lNxrwq4tx)fY~YJvZ0Gv@Fqi9k!*8yJH@UozUf$;kvf9b@ z<7+F&e3ek1`lAzgBA2oAzV*|Pk^H?!dXoAIh1!ez6c|jIrT5e`Dn6QaSXwr*RX(CR zMxH}^x2%wvu)5nDZPkgl7pXcXIx0Rd;nmjf*ssL#(nWRE1r?3y8pl=GPH}3_G7jdf zEVgEe(hy>gyncY~-IQ}IC(T!}t@lf1Yse~RJ)z;m#xFIAwd$(9PT%7?ouJEkT5K6# zw89dW>ExZ@(0QOTO@~L_S7%?ikq+0d7990t>pQyd*}%Mb$ce% zaLQUl>Y$)7`@Pdb>vLxdGaURRH2Wd9$cFk|!bztO3mIyC61oszCCvD~LbO`mQ83sfXk14!T^-lzjpIa>OJ~LSGhNP50l|LJQcm=nB(Y`~1`_8cOT{K(FlNA=s z(=WZBZ|2eMe66p4^OYVF;S;`~$IJPMlTYcRKYy1Ro6x;56+vUS*?j)}#|00`rwLw> zFcz98xLqJ#{4D>q-x~zhwagP@Y{?N6d(tV;&?&&n)1xhTl2=d9iJ9Hp};#Z8SII zp6TDNSq3q0!%g>JZ8g2LY`w|H^8Y;Cd9!$>R>$*d)XwIsJ@=PaE8l~sh3PbRzUNV1 zZN6!|`^*dYs(v2iNzxGHJ+n%d^ZR^B?gcu0oGz)KxKq!3;MsPUiMz>6n1{pOmY2n1l7D{OdA@J^A92r}x{+TrB8va5 zp_xGZg*|+sZdZ9X#XREs`*DH5`mkvnm)MecwKimPujsPmoRRLzzWVzdcmfu3| z*jKgO2R%7B9=~AZIm4UJy^?(@uN2cA-V|qMUg4k1c(-5CM%MdPK zkRmeCkWu*CO-9l5y%U75KHn?!M9Es@mB|@lpBiQM!>(Oixv$mO-x#>FGhXjyuj21u z@3swN-_8=k-fyDAen({%`v#VLo)(V`?*C_wa=%@|%k^90D%Xuez3gu-F0p?VW93%d zF37$6moxX{7<04jNs~?I&+ah4(7|Xi^SZuSQ}1u{stqz`+x|{8bJ}ypJa_pWGoSPE zLh*Wc1qC%@`5Jom3%SIk!{p)&mB4yDcxoEMLTk6xcF|3+?t6kDR6?##v@7 zZm;1d*0HWj?8~v;Voq}DV(~$1d7iNG@Jth3%Cn+1lmD61bv}!BPu^L2m$}%#@bjHD zZR1Oe+{eeq6vkJzk&Ac6SrhK*ht&92&D_XWq*}?VyM8|R-S9ZxG+!S+Q&l^@t$XZv zYmXk{3Hw{gTTuIj|7=Vcf4(jwU**jy+`ic>`QAR|=byGOiJ$fEE}mx}#`&udl+99;aC zk2!FMK-A$@{-9NA{B>8m_$yu?;&q=@&uhir%#*2foM*DrBp#Eh$=uoE!Q37b40xQy z4sad)`GjLmmWssZnSUit|NA4=!7y2>&)PzA`_w5?%=bAYqKtP+z4@_R!ui!+$t^yd zqU&tfg>AzU#e_w-iH7kPi~LQPA{rJpPc*O1M1=9uCDA`cyG1|m`_3=)$dvz$M*v@y zZ#Vym%qzSX+)wgtb-Bdb!rsHHvsIsO@$wmb(`&i-+gD!UD>ppGQxccWf5YJzUq#Fc zK9($B9g}p4R7wFIKgc`B7)HzcLep9CkS{Lx$uYk5c3QnFmqFg)z-`UsH$#KeF{>LHlOo1aZ)tGBtbsLB7>p+3| zw0Hc{9VZNE^HnD z_4{Y}u7xb(PLFFANL^^jcX5fSki0>(;I;j;c<&s3AXwbgA$Wgxv5<}OA%WZXH}j{n z-V(^<^;B?7&=owoGPowkw~r*;v-THZ2cgG;94o!!+J(s`00; zCUdS8HKu~$d}ebm=9sPQQ#QN5qr+V48K3wX#cGj^RXfD*ojfQ$mrF;iu5+3=7mKIZ zZOLF!kthN2Yb=c7if=ZH99R=5&5lOy`YY*NE5kk6<)(CUt39+c{nc-2l4PA?X2^EPjO!E`nvWL9r5 zklq@)kDq;-9Jg%xI&L#vd;XJ-c6{sSF6MRE#m;|arvQKR3KxMbOyc~TOdbmyVVfy% z^3P}f^cF*bAjKK{I$1CI(@qESovo4QXF6giu+?`Tzo7LY(+>M7rk{nDn)Zb*GhTAu z#audYuSsR?M6(OKHk)29zG%vD__*13KXIX3%^89|Ez7na;mUl%GF3Ka%^kiy`07552sSR&xBh{L^^! z7l?B@8s6tAcoE5erye#L!eLa+Nz z2-@ka72=On6=Y8i70|pTA$WbCsBoQ?uacR^J`K|^GcpIC*qwg1-S_I*xb}L2#b$OEv#syj zZ1&=4pMk>8vu0}s3KxjUA0v%K9Bz~lAp zD~HxCRyGjb^iY&FJK+V(dL|e}##=U?rgoN(xs9BDQcmVYGftT{uq`pqo~>%0^ex})0+WJ8 zz^rg{%lB{0ICtzd57TWkKPXWp80?iGkpG^MuOYfrP<^V9;Qyoh1Z@xb3M^2b!Qbbc zAi%m%U5LADF4wK5**sJHCh;h8`|@qszm|8s)D@mgizghnH?r||?|0^1xoICSqr406 zo{4G#t2l1*8kM^6wTMOVPxlt%zxt?*&w~9eUtkswUx`!!-_uWdyh|^wWarNmULqoG;&qhxf=L4Q_GEPTuboa(us|)cAPMSP3MoJHu^w^dxT}do};ftB?36o9^ek z)^wO(MdUNTU3$2{sVY0Z%2zLC3{P~)KCM_N&(9{T&@34tXE3ozUQdxx#^U=mdF_Ww z<@(gh|S$!NB> z5-vv+B_3O5$+$n>E1@53CJ_~BDD&p;O^MfBOx&u93%NywE_1p|2k@AmsprmoFUxhw zwx4Ui{w9u9CoXfA$;$Cuo6lsv`r$M)jWs3arHbX|KFd7J!%UmZgtU81|AwqE|2XxW z`Ri&uqR;25y3ophW7c#&+ega<{>z96IBaj>=c)4Ji@MUnzvZJpe~~MTU}RGrzoxpm zw8G(C5)IrfGU>BRr3}&=rK;Kcq!#aFmi?<0FX=DlC*%0kRr;V$8{e~RU7muJ9Xzo) zssfDHI{0TP8SqK(5aMp1=%0PxSNnD(7>3c<_Md{^{+!$x6YyR+tyA^QV;@Hpo`OwKFAOh&2JOfIy;vq-dS9* zZ_!bKU;7se3ML8)-1xYTuileaVBZ=}p$(fd1%KvJC9wBZw4m&PfBd#z-1rqL*9fd$*d{nzqg!Bw zM($zKoGP!fIeQT}K3MumS0JW8!W{c4Z1 zRMd;56*XR|X{pQ97^oarzf0Zm8Hd`_?rUn_wSK66JeH`s?y#s)Pkf)j)|!)M%ewf? z7Y5lH?HAZ##;P{gDBzQ&i8-sO*%Yy6lU7$&p^Hxq1?QAD@y2k^6lB<~FDNUjD&*Ri zD9|<4lK;G4w}3%@hfwJ+ezpjf4z53EYT0gZUSjLJz|Wz*qLw}RDL?zEiTBx8nIB~{ z(URl{XqqB*W+JPY>-28PtJmcub|pWSP+!R@snNPxs?y-57(;f4RG8Wp$;UApWV>%F z$cSJ5A*T_MBBzC%*%MVJ zi}fZ)%qE|oX?A~6yLrx69`mOqM&?3XjAs9?UNDonl_T`CF-FjBb_?G_cRL}ryibB3 zM0N>9uQC^$^VC$}r-`-TZfynO%TrDHG{kjy&p6xjwl>e^*~hYsC-AujZ=>!-?i+!c zJlW6Z@tm_%<&oacqV;D*i^dHFah(N{COYp{y;NhYUal#pudbS-;;QxQRlLsE*vlGj zZVL?5^xv5rm3v^Sm^|C;M$Q70!dpgW*DvrH3hs+A%R8=ZDrUxOW~nq&khSG(uIzhloQ-Y%xi+)Gc-;}h5=$8Tw3&%bYGo7g17 zpF$_^UXy%$L|*)>b3US5>awJ)MA)R#9tKJLP7jyzk2xV&Bz|6icSk#~;+tN< zgf|X?(_Ey4o|{Y*XlV83zj$z>08@9fkpG1OLCL0eKH19k{N_tn3N*E^=X=^B$;Y51 z%x`&0j>peDM_|EzA%3xMoI?8yQw2R#ivbCU`FQ?GgRpx^C*7*tM-G40D z{#ium537*G&c-dG!e1Urc$Ke~Q1NFIcQJS?v9@cE_>HJ@;>C|*C1&mZBi_Vs%V&4W znm4n-i>LEnERSZ1GS7x?Cmx@4PM&_d*WAk=d-BLHjN^9O)6BEGeL9Eu^a(r`zkcz$ z@i+5Y3z+bfly`7nzg5nCUwJam#dtqniMtc@?H2Daii_(p6fJnArliVU!^M*^ZX0;bqni)*&F{>0x zGgTLTXr^&9L&&`|L3o?~O~Ic%nou$SiVTTELIL7=s{F#5AMJ%6%}C(?dw;XgxwSSzAD5~N z_k^_z{=L6hKz-t5!Q*^=!m|p!cw!4K@s>yi@H8!N;I&P=#``6HHm|*TIPbIN!A~W5eLWXxvHk-?? zsy45k|K23As=@4I=zmiWMnBU%M>s4VL{2telXuw2;emk}XF0Q}o<^zBDvqfp1!6oV zRYl#VWldeCe%|sX(gnPx;pg6SM@KB?`^vI~`?#$a&&+#QxQ>e~vAN?>c+W67%hg7$5?=>FX?$pdX9P z?ZbLZub*Qx|1fo)nZ@PxX79zE&Aop13SQnaQ$T#aBHyHxc)`s=9|Z!0_Y0b;sR`W9 zoXlVM&R?LRTTw_swT)}n>xEp06J)ra`}*@NpUuvr^|XakKqH&G`1(ig+Y5tvl5Kjq zy?ee03FK)BO}Sdf=Rdzos9}ky(5^51!U?Q_f+D`j0vnI#32r)CBy7zxi&yLIe4h9! z7VdQ8&)m=Uf9J|8{KjRzc{aD`vqxNK?o8)CrJBfX|9BS97a?2T9}D`p{TE!|>D(g1 zlb9vMvq8Oq`>%m4kJzb39)*jmxdJwovqb+r%+lrG$#U}EOqQo*i&<=I_pxltxWlsf zW;+YRnPco>8>3i+IkN;Vub&{GE3M7XfAS>%r;Q)^FCAFK`(14{|A)FKeCL#I^R00E zNp$&a;V_9e>a#9yx$jKw8;_XzrnmX?GF}Sex!WJY6SjQ^_v-1fyj7A{d88hu%eSw8 zti0xtv7CfjreXlMsPgvXmy}c1wJLV!+9}1b`pVBTVNz~A_nI&5&{Q4`?c+R$Gq>`u zZHeJOXx+ts?P@Ha=vz&`KdvA7w2tx##OjyvM9J&(ut(PNNEhhvYhPZ?_x-5>@7rC= zxo7Kq-9OFH%bqXVz+YZtKk=JSW|CxwT^XM7-Wc z3GPx@DdLgGE*ds9V*jQ=*y(4LNLrkk zNH6OFVTXJt5%uee!iybvgoMqV1n1t?=KC7BOYm25nBa<510l(bg#!Hxm+`Z?FBVYl zo+ET(J|B0~tak3F%x>I!cdg>wy=Ma#iv|z(VWDH3`9YZX|pFfFB;b0G&IqM4cuovlUJUwgJ7VVnK z)-m6dt$}+PdzVHGTgggh$!v*OiMV|#(i`p1Nv2BFh8l zHPuvQ>lU-aoS~*#FB;7z)Za2IdhKl1Z?a4%?2ok2d-F$pyhl`pf+x)sOb=Wj)M0W# zK>LK6K=lJw!Rh{Xj065?<)6& z{lEPA6U%r5+|ziQ7A@q7km}@}wPimK&m1&N=46Es^_@r~h*nkIVhp(vfxM zlBb`@%0B(SKt{a4NqV2jH7SFvm(tBgTcnIEuE{8RTFa;^>+@87vE%X4)8yf-UdB89 zDmQN!hYRoRBd@tNd0udzWnGx-N7kvLO5P!jjPkfCW|5O(p{$+n7 z`PQ9M5|9*H!e6mnlEHGwfxTlO}KCd)PE9Gn~UYT227%VS0ElXuEU!S$XRMy_ljGyP3dC($P^W*Q{@NCp- z;d0-(fqPF+4Bzv;`+3hf&gGF7Xy-m{Yr&IfXTV#aJ%#tw-bjsw-aFOJB{kH(*xRXI zo_18d>enXKMe?)M?=JhME+lhC&Av%j{Z{uJ)2Oe<%vk=4nlIbVYaZ|3WS)O&otcP= zx5;*+r{)pc>`e(^|zERo|+`Mj6^ykQc5G-DW_LNOz+ym}R1 zU&u$^K*2-24&KxG`@it=^#yF=w)h{zS-+x+^Tg6~9K7DfoD_6at1dkV&vD+#r+&JtK{_nN=9X^{ZKiXNeg6W`32 zrr4RZcHTEz+jY(?sX)O@@R_lB@x>1F$sBu3AMZ1_=(n0_t|#9NS_>q2lf9PjiGY?+ z@Q&SrCJIZ0W*M*vev;7?s9q{87DAUWbG}MN(~Yy4%{1b^ab0p|;hbnK%6a9^EzT(uu5lED?Xh+7pfi+l6Pi`_Yf`}g;zPP`}cCM(`@JL-1(Z@jagk?@l2F@Uzd}b`R{H;R;5sN_rP|w zYr#qyYg{L*{1INFwj<+%>iwJf>=UZ^8BAc`Iu2P=+!0LO#rZGxBa0jn}T_yOJ!L(DDm-jsv_ohXioEg&-xw1De z;7aRF;Fjf5;gr7gi!)uOpG(`2i3?=r?&Mo6OC(u%qj~RhZ7KN9uuH0o2P8h5zYgpM z5Sw{dhLGNa!-6-K2lHL|#UNy9*DUz%Lxs?P>6HTe*S_FC6L??X?wiX(i+}DnR+DKl zy_C*s-Ymb${N`~t(-(P<%ofN>8K2xQWxo9DJ<~e}r<-bfWC}Kyr_Q*r%+vkE8na>&24h zth3y#-jjm=|HKF$vuzoJ3#`hT^ z%j0a za>*NK>6q$0Qj`DBk-So}MJ|2&bg2~CcIh=I4JD`Puat@XI8`#ue~;W+S4r_dBB!Mp zV)sgBGFfpR%}iyNcX-X|#cIvY7ypi9MV%T)*IPl3>J!`8bFGhY)K$*qC|`3$)YL{p z)H|P5OlMn+n4FMysu94=wKY1IUTZ#i;-UlUKQ_ohe zFR$kCE>*w5JK4;h@5B{$iFBJYqQ{>INEQd4k+9jNBi`?lDj}S3TiirkOT6{}6N#Nl zED}mqKe$d9?dF-T@5UomJehCJwJ*H9#ano8&adU%!|ca9=k{7&<+m?*I}@i0um?}% z&lHj1UEHu(z-E@dz@?t60u!DY@L#ll#3#IeDgU20R)XK}2Mevcwn0#7!Y{r9tgi(v zm{JAjZ;27A)7vHx@`gb`wfBg?&CK0GX_XFw@zbUY1f@yvd@nyNU}GC7kk+0kX!LXr z|5M8_zIxvs{58)G5xwr;sS#%}x9=qPn z7k2Ij{}#In-p=p*d`Bft@p5zV@f&`d!uRR)4Bm4lOL%X&{p3~t_n$YDV<#W4%Xx{# z=^MnSY(Fe1_(D+9((;GIdZQr8G~N}Gm*?FP_fCEw8JhN7;y=e*PA~80+$HiqxhLfu zRc@;gJaA;@&)I6Yoh*4!)-WZhUoXgr(+pESA(`^OXwsy)5N0`>&+(^KQx4 z-P0tB()LR6&)q1s_8X@(D6dl!J7%#9dOyC%Zx;K5H-EE?V20fRfq9|Hg1*1+@@qBO z^Ot?s6-YUIOmIW#TvN-}Tg?J)ds)15(zYm&zG=2x=&N~V;#`xflh`cYrY|sizhRkq z2*WB)*-xq5(+@4<D1x^98rF9TiCJ zIKkU7DM`?cPe9PJ`;lN{gTFv_qY=OMuXq6-b~ho`x^S*Pjagg{S;sl|is*COGu-0b z>s8IU$}f&H_3}2(Z)HjH#GJ=nqtwlpuk5pJF{_8hi`r)|wsfjbp z|0sm=6wRN<$!5vTBQLy}uXQ66pG4{gp7P)SxW23@<~?`mA@5Xw3BHh`C(=LlPD!M% zn;?DaQ<>DSYkJb5uPmfux-?~_Ed(W^Ic;T&_!XrOO049K2)V+Ukh_e>I(ifTmwIu2 z)$5mdolo>~9a!Mbw|nzhzC-mw{M=bye3sXGxGpqS^SllI&(Fyd!O!xam(TwL54YWp zYQBfU!u+Ogp5XS{O_B5L9cqUdwt2`hI*E3$fzrj7MZ>am5$235|MYzjzf*zka@D{>Mnw?A7d*W^vOQ z&9}MPnWntkvYA}|rNG6_s!eZ+G_piQ99PhVha zB7@*kzZv|^#bJC)ESveWP8A7uaxxjOt=wo@)^*+Z^@4U|hwRNJ{jXV!bqj@!OpV3N z#G)Pumm-uNi6g7>k|xn>?gTc;!Z*KAaH zr!8g{oYOy7z-({0;OmL!`M*D6;h%6+NI>`1R>7Iu()Ih4GIeiSOwm{Pzf5mc&Sc%I zUuWz6yet;xj-`Y-D4?D z&V5pGTVpxa@oBS09n)aF5vI=CnWx9vDW${8;Ah0TGftOP{;LJ+@1s_%ta7qK!rq#K ztE}(wrk#B!C=)ta@Qi-(c(Rn z^@8XB`bE44AJ68FzdM`zG{<$G>AU~&SV%qREoI{2{kkreSH5K?&k++z?)Pt= zbF1Cq<1O{P%M)}iig(lPL&5>~ZwT6!z86*zixhDwj}<;GxJ4v&da3Y@%$dT*pE*Td zznv_6n7dY3!%I?(``KLKkBMmz6jXfU%($TM_RCHU6a6JJ8r>18!dsLh}--rCx7r8 zrnL$lyHhK~@M(eI1tBy3m46k4y3cMAymMfV&}}wO!JC`p1U^J@3I1nb71m8Q;1WBt zfT#FjE7y^k6`c9EOS#sUeBn&XY2mmoX~W?-gMn+g10$EOd5q@6fOL&lbM@3We@at1 zD%P#(>^faN_Wx4NTsb%O3UM>_{zdQ99tE+8yspv`dT6I2Vwf^fghBP9@Zvj6qOviQ zgyk->hy=`07m3bNu+chij&tD34pmbnd99IXrew3_Q;Bow?=t zq&QEmzs@yr%S3LM*`7S_x-(fX+U(}gw5Vq7u4`f4Ex3_YN^u{n@v&p9(IOLBZ!-6> zN^j3#ZT)vwAn5e5ON;`)Q^ai|k;_SnqJ}YIBI$~SA`2I!ikS8(i}=jj&3!+^ndkgDF5V{!XL&UgWq747ujk$> z>dBt%#LT-dd=Ag%%LjSCv)&alUocUyP^3ZFYObEhnnSY$_sdv_Tk~$Q%&EiZ8l*J{$c#LY{uaW#>$>A zbn~j@OP5Kc;$4m_~gRl_>zr{c=q%4bB9Owa5uI+;GJ12!fTy%nmajGg1xqW6VH#s z=Xj2`ck`~Ay;ox5OL3{VmEw{HW^YB7=rv1j*nVAn>#tDB+ULfS`wJz+8}(O-H>S&S z`K=OWUvuz28?(`OwtIVju_;dxWS@9SpZ!zkDKHSFka!`M|Z|f+qV_hh>~s z(=)i__6Bk~J=)1N$Mp}F&$?1>vtuhckDO}fRt%WNIcdE=TP902o0UK_n|omhn|NG3 z8%ui=+n%EyY<`@bY;T_Avb__1EEMpJTh!QKn$VP{*`v#R>)6|Q!-ToG&i#1D%e;0L-+|gwe9VCs zLbB@%1#6v_^GU`374-hxD|kpOTWE*xI{~&x9s$Fw8v+Y1oDuTl7UkU_{**U#(^a0G z`J8Jb^<0@|@l(&fTk2$Z0U4g8SpY=RBX7HuG#vxx#NMUd7#3&A=}p zzevDz(-A(2`P_os3#anANCfd^ZqE{M5I)7#f0@^`)Wh6t#)@uJa}EcS&HpRRCe^B# z?oD4|%JxjpbZM!XN#;ap(_LFGbICRw=i$)Y#`C!B2=8q+Q{Md9ecVC81>8)>ckoA6zI1BKm1Ky@5z{6C zsZmuD7jir{9i*ZM#XYt-#&dBRkaGvi@ zmk}T9{M$V3omJcud#>?L4`k!pcr%f&g1eR5%4Q$OjXg^_r|59;Zuha~**^6tm+ke< zoP|u2xf9aNcxJDE#eG6YR$x(>BmZaPw|s@^jr^adoAU7}f8d)i_a*P{gbBP3Au9Zv zb_?=ngskQU#h>{(AC7rESJ>V>I>K6ECc#pFLXqcx@FYgoDKVUF*O=KdlzKQB9p~`u ze5S{noqLPVoXwKYSnwrJ)W<)ZT$h*g3QoGs%bef9_upd?*U1(OUa!{^xo#?*;k=|f zo$JUnJuZpUN}SVpm$1v`nsI$w^ORHOT&MZ88h6t8H_@$~3eB3rA^b_ynRja|{prCMq;Vk9P zydd_;3IF94cdV1QU1TG#WSJmqslHTUPTPO^$D&S(#hom&&%y*1@6X&VA0fn|(j;T2 zxHis3RrSL`)g7$+m6%%RshTtIRZg~htXvy%S@nM1Tb0Jy;)06b-tnI?KFYh=msQXr zbG^Wo6^(+LEI0Y**fH|IImIau(0)mdd9Ct}JC$S)-1;T|ef|+S0k(4a_s{j@q#pLl+ihDX8}!3iLDk$}-ekF@xo71m zvy5gd%i05HEwV#u%=p_iEq!FxnH4BWSWMZIV!lk=&wTNuK%tZX4xt|zDnd-WqCziu z*oC6zND6s{^$4w-CL^ThK3|aYmbuUib_+>IcQL7b9X>L5_P>$dn=UM!!#PnpjWJwu zS7EjEgZJ~L{MJ@V%kB)}dAQh)r~bYKuia{U{_h)B^C^8u<(*t9#Z~q5GVc!)H$KUu z=lLY>OPQU{i8PsAHqR{F@R%u^{sPl^WgAV)&D%_iu8Eu7U2xX)v~{}KrMNKOPZl@% z?mn{RPM3YdBdh$0OYg=+?*72lyc!HkSo5MRd9x2m@lNpx7V|E9{t-QJ0`FS_w>T&;{?Z_>;Jd?Y*wwtFid>YT=iN@TYWlXsl zHz{-Nx-86_m>A3RJ28<<_NxuY#k~qV*TPhI=53kIBlV}Ne2qsC_5Eys3<a~0cNute&&j30h_(LLhk}+n?8E^*6e^rtC^458`BrQ zdS>4jwwSH@6K1-E!{1zl)7x}{)G^bR*3C-4Iixky(rh$snRaVbeUQ*(i_XyC%WhIH zQwvv(Tot5Rw?yk1l#)U}aKuv%0>;6B@X0fW^y zg$^iOH)GY&G8XBQHuui2H)Al~X8LINN0Xe(U1rRJnWo2NTg~E*x0}VT+`>JpQJD9v z|1z$Fsb@GHy_a%*iV5JzRJ_LdsaB55D@~P~`;HiwOawRY#z`f-lQ{%6!6(-8NzMoo&{r z}1vC98^PF0>A6%xpum*!^kW`Yj8mo%KCWhx%m3Tk>pTkkaqsd)c z`Gs%eE)%{e9Z_B%q4Qk+Kd10=$Z+sU7rOEZUgZ%g-eo8_H#uxGEJj%m5z^^NXA z8aMX~Bzm^+i*j!ekZ4^ebW>~sc-{zPhiXhPD~K+B>Ij}=01>R|Jv-NnV7k7!dbHy5{4ELUMo%G-e+1Iw|{89+OC^DMRpd?vO+(eeQT!h z`F)e&`<8f{XM05vr?8y^@9i5)d6haj_~curs2mM7)vQ`>rgh!z?QxnslVMpKbi7@|pP)r%mQ<)+prm6tw5N@^lNIjlnCT&vgl7U{_Zz*{R68 zH(f&WZ;SYHt{Lh-U%wMOev3=~I$b#I{)SH5squy}MX|-#UVscWY=b z&(3WTykXbQ@)oFG;awvC7rbY?_%e&&?w~$?$A(h^TkJ~t|F2@^pY5I_&>mPS5Fy7Y zkY3Lw`0$c0zn-YF+@kDe>4KhMxsA@YvL}>OWEm87WE*B$%E?9DmMUGdSg!diqpXg# zCAV|C1MfNxH{Op;tNC9j3-Zt9*u<+98_E+fXF1=3U6=SACK>Wy{=0^2;_P%@lV^8% z7j(4q&t7|t?|?}^@1fc%uKy8A_aP=gYSV z3I=lso_KdusORuCw*0yWEKVP^IN}ysbLt8?ux%2V%lYJzCx?K@oonMyaP#Mz8TO7xRMv)T zd6+am_n9SpM}u2=x6eMs{brg5@6X~KKD`PSzIBI`_LB*`Qf^WFL2%Jut$m>uuPw?oxFhMPU4WYQzD+Qij zE8$=IZn3}}lSx7*wV!wd!a{f>W)<`7eszfFV7e4)5?{J*hPcDMkAj(T48jXP%oc2U%qduE!Y!=P6fST}eYH^0 zlIKFpR?ZfjD|Ae7^OoB}mfW&J?y{o%<>@U#8NS>?Uu*vhJv|>OsB)@VK=@FMVCkMH z;og7K#cMdNL??YKmt3&YRDRO*jUxBgo66^K{1B7znkl|%#taFT&kMlkS`m}aO`tbl F0{~I{!JYsB literal 0 HcmV?d00001 diff --git a/tensorflow/contrib/tensorrt/test/testdata/model.ckpt-46900.index b/tensorflow/contrib/tensorrt/test/testdata/model.ckpt-46900.index new file mode 100644 index 0000000000000000000000000000000000000000..537976571337508ab1798d33646c51d62a146ecc GIT binary patch literal 652 zcmaFOHiLnIje}8&iGz`Wn>#7BB+)RwAiq4dh=WmxL4(C~S+$@Q3p=k-yr}2_1r`k! z(^q#&7Bg@QCFkdr8KvkaWhNGLFbc5xp;aA-6znmW$Aki*R?tnZkTm@6v9(!t0m ztxz&qF+_k#INnfFf`N%qBA}zWW2OTm9LvBZnv$AV zoGN(QhgFD~qk%=C;|Z@ugMjI}C*iCN{IW`d)q?5_Us%;8!oGXB^D~LE<_k)(wD2)H zN`$;~X<}oO61~m9$#|YO*<=czMneOKsQ|ZvC=aWYV3d&(1A`c=k_77c{dB~nipQ* 0" % number_of_tuple_elements) @@ -293,9 +291,8 @@ class InfeedQueue(object): self.number_of_tuple_elements """ if len(input_tensors) != self.number_of_tuple_elements: - raise ValueError( - "input_tensors is %s, but should be a list of %d Tensors", ( - str(input_tensors), self.number_of_tuple_elements)) + raise ValueError("input_tensors is %s, but should be a list of %d Tensors" + % (str(input_tensors), self.number_of_tuple_elements)) self.set_tuple_shapes([t.shape for t in input_tensors]) self.set_tuple_types([t.dtype for t in input_tensors]) @@ -451,8 +448,8 @@ class InfeedQueue(object): for i in xrange(1, self.number_of_tuple_elements): if devices[0] != devices[i]: raise ValueError( - "input devices for shard %d are %s, but should all be the same", - index, str(devices)) + "input devices for shard %d are %s, but should all be the same" % + (index, str(devices))) with ops.colocate_with(inputs[0]): return tpu_ops.infeed_enqueue_tuple( inputs=inputs, @@ -792,18 +789,14 @@ class _PartitionedInfeedQueue(InfeedQueue): Args: tensor: Input tensor for partitioning. - dims: A list of integer describes how to partition the input tensor. + dims: 1-D np.array of the list of integer describes how to partition the + input tensor. Raises: ValueError: If the tensor can't be partitioned by dims or the num_cores_per_replica doesn't match the number of partitions(dims.prod()). """ - if dims is None: - return - - dims = np.array(dims) - if (dims < 1).any(): raise ValueError("All input partition dims must be >= 1.") @@ -823,11 +816,6 @@ class _PartitionedInfeedQueue(InfeedQueue): "partition dims = {}).".format(tensor.shape.as_list(), dims)) tensor.shape.assert_is_fully_defined() - if (np.array(tensor.shape.as_list()) % dims != 0).any(): - raise ValueError( - "All input partition dims must divide exactly into the `Tensor` " - "shape (tensor shape = {}, input partition dims = {}).".format( - tensor.shape.as_list(), dims)) def _partition_or_replicate_on_host(self, tensor, dims): """Partitions or replicates the input tensor. @@ -840,16 +828,39 @@ class _PartitionedInfeedQueue(InfeedQueue): Returns: An iterator of `Tensor`s or a list of partioned tensors. """ - self._check_input_partition_dims(tensor, dims) if dims is None: return itertools.repeat(tensor) - else: - output = [tensor] - for axis, dim in enumerate(dims): - if dim > 1: - output = [array_ops.split(x, dim, axis=axis) for x in output] - output = nest.flatten(output) - return output + dims = np.array(dims) + self._check_input_partition_dims(tensor, dims) + output = [tensor] + shape_list = np.array(tensor.shape.as_list()) + quotients, remainders = np.divmod(shape_list, dims) + for axis, (quotient, remainder, dim, original_size) in enumerate( + zip(quotients, remainders, dims, shape_list)): + if dim <= 1: + continue + if remainder > 0: + # For each dimension, when it cannot be evenly partitioned, XLA assumes + # tensors are partitioned in a greedy manner by using + # ceil_ratio(size/dim) first. E.g. 2D tensor with shape (5, 14) and dims + # are (2, 4). Since 5 % 2 = 1 and 14 % 4 = 2, [5, 14] => + # [[(3, 4), (3, 4), (2, 4), (2, 2)], + # [(2, 4), (2, 4), (2, 4), (2, 2)]] + ceil_ratio = quotient + 1 + num_full_slots, left_over = np.divmod(original_size, ceil_ratio) + num_or_size_splits = [ceil_ratio] * num_full_slots + [left_over] + if len(num_or_size_splits) < dim: + num_or_size_splits += [0] * (dim - len(num_or_size_splits)) + new_output = [] + for x in output: + new_output.append( + array_ops.split( + x, num_or_size_splits=num_or_size_splits, axis=axis)) + output = new_output + else: + output = [array_ops.split(x, dim, axis=axis) for x in output] + output = nest.flatten(output) + return output def _tag_sharding_attribute_for_dequeued_tensor(self, tensor, dims): """Tags appropriate XLA sharding attribute to the dequeued tensor. @@ -866,13 +877,9 @@ class _PartitionedInfeedQueue(InfeedQueue): elif np.prod(dims) == 1: return xla_sharding.assign_device(tensor, 0) else: - tile_shape = np.array(tensor.shape.as_list()) // dims tile_assignment = np.arange(np.prod(dims)).reshape(dims) return xla_sharding.tile( tensor=tensor, - tile_shape=xla_shape.CreateShapeFromDtypeAndTuple( - dtype=np.dtype(tensor.dtype.as_numpy_dtype), - shape_tuple=tile_shape), tile_assignment=tile_assignment) def _tag_sharding_attribute_for_dequeued_tensors(self, dequeues, dims): diff --git a/tensorflow/contrib/tpu/python/tpu/training_loop.py b/tensorflow/contrib/tpu/python/tpu/training_loop.py index b6c350ecd7..0187b4bec6 100644 --- a/tensorflow/contrib/tpu/python/tpu/training_loop.py +++ b/tensorflow/contrib/tpu/python/tpu/training_loop.py @@ -166,8 +166,8 @@ def while_loop(condition, body, inputs=None, infeed_queue=None, name=None): # control dependencies from any side-effecting operations. if input_arity == 0: inputs = [array_ops.constant(0)] - return control_flow_ops.while_loop(condition_wrapper, body_wrapper, inputs, - name="") + return control_flow_ops.while_loop( + condition_wrapper, body_wrapper, inputs, name="", parallel_iterations=1) def repeat(n, body, inputs=None, infeed_queue=None, name=None): diff --git a/tensorflow/contrib/tpu/tpu_estimator.md b/tensorflow/contrib/tpu/tpu_estimator.md index b6514e19dc..552febd80b 100644 --- a/tensorflow/contrib/tpu/tpu_estimator.md +++ b/tensorflow/contrib/tpu/tpu_estimator.md @@ -89,12 +89,9 @@ handle training: dataset = tf.data.TFRecordDataset( filename, buffer_size=FLAGS.dataset_reader_buffer_size) - dataset = dataset.map(parser).cache().repeat().batch(batch_size) - images, labels = dataset.make_one_shot_iterator().get_next() - # set_shape to give inputs statically known shapes. - images.set_shape([batch_size, 28 * 28]) - labels.set_shape([batch_size]) - return images, labels + dataset = dataset.map(parser).cache().repeat().batch( + batch_size, drop_remainder=True) + return dataset return input_fn diff --git a/tensorflow/contrib/training/BUILD b/tensorflow/contrib/training/BUILD index 00295f57f6..f6427ae05a 100644 --- a/tensorflow/contrib/training/BUILD +++ b/tensorflow/contrib/training/BUILD @@ -26,7 +26,6 @@ py_library( "python/training/resample.py", "python/training/sampling_ops.py", "python/training/sequence_queueing_state_saver.py", - "python/training/tensor_queue_dataset.py", "python/training/training.py", "python/training/tuner.py", ], @@ -287,28 +286,6 @@ py_test( ], ) -py_test( - name = "tensor_queue_dataset_test", - size = "large", - srcs = ["python/training/tensor_queue_dataset_test.py"], - srcs_version = "PY2AND3", - tags = ["notsan"], - deps = [ - ":training_py", - "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_for_generated_wrappers", - "//tensorflow/python:gradients", - "//tensorflow/python:math_ops", - "//tensorflow/python:platform", - "//tensorflow/python:random_seed", - "//tensorflow/python:training", - "//tensorflow/python:variables", - "//tensorflow/python/data", - "//tensorflow/python/data/experimental/kernel_tests/serialization:dataset_serialization_test_base", - "//third_party/py/numpy", - ], -) - tf_proto_library( name = "protos_all", srcs = glob(["**/*.proto"]), diff --git a/tensorflow/contrib/training/__init__.py b/tensorflow/contrib/training/__init__.py index 3547e71184..87ce57ef06 100644 --- a/tensorflow/contrib/training/__init__.py +++ b/tensorflow/contrib/training/__init__.py @@ -59,8 +59,6 @@ from tensorflow.contrib.training.python.training.hparam import * from tensorflow.contrib.training.python.training.resample import * from tensorflow.contrib.training.python.training.sampling_ops import * from tensorflow.contrib.training.python.training.sequence_queueing_state_saver import * -from tensorflow.contrib.training.python.training.tensor_queue_dataset import enqueue_in_queue_dataset -from tensorflow.contrib.training.python.training.tensor_queue_dataset import prepend_from_queue_and_padded_batch_dataset from tensorflow.contrib.training.python.training.training import add_gradients_summaries from tensorflow.contrib.training.python.training.training import clip_gradient_norms from tensorflow.contrib.training.python.training.training import clip_gradient_norms_fn @@ -79,7 +77,6 @@ _allowed_symbols = [ 'FeedingQueueRunner', 'get_or_create_eval_step', 'StopAfterNEvalsHook', 'SummaryAtEndHook', 'wait_for_new_checkpoint', 'add_gradients_summaries', 'clip_gradient_norms', 'clip_gradient_norms_fn', 'create_train_op', - 'multiply_gradients', 'enqueue_in_queue_dataset', - 'prepend_from_queue_and_padded_batch_dataset', 'train'] + 'multiply_gradients', 'train'] remove_undocumented(__name__, _allowed_symbols) diff --git a/tensorflow/contrib/training/python/training/tensor_queue_dataset.py b/tensorflow/contrib/training/python/training/tensor_queue_dataset.py deleted file mode 100644 index 8896a95327..0000000000 --- a/tensorflow/contrib/training/python/training/tensor_queue_dataset.py +++ /dev/null @@ -1,201 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Python wrappers for Datasets and Iterators.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.data.util import convert -from tensorflow.python.data.util import nest -from tensorflow.python.data.util import sparse -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import ops -from tensorflow.python.framework import tensor_shape -from tensorflow.python.framework import tensor_util -from tensorflow.python.ops import gen_dataset_ops -from tensorflow.python.util import nest as tf_nest - - -class _PrependFromQueueAndPaddedBatchDataset(dataset_ops.UnaryDataset): - """A `Dataset` that prepends a queue to another `Dataset`. - - A vector of handles to the queue is returned as the first component of - the associated iterator. This vector can be passed to - `enqueue_in_queue_dataset` to add new elements to the queue. - """ - - def __init__(self, input_dataset, batch_size, padded_shapes, padding_values): - """Initialize `PrependFromQueueAndPaddedBatchDataset`.""" - super(_PrependFromQueueAndPaddedBatchDataset, self).__init__(input_dataset) - if sparse.any_sparse(input_dataset.output_classes): - raise TypeError( - "Batching of padded sparse tensors is not currently supported") - self._input_dataset = input_dataset - self._batch_size = ops.convert_to_tensor( - batch_size, dtype=dtypes.int64, name="batch_size") - if padded_shapes is None: - self._padded_shapes = nest.map_structure( - convert.partial_shape_to_tensor, input_dataset.output_shapes) - else: - self._padded_shapes = nest.map_structure_up_to( - input_dataset.output_shapes, convert.partial_shape_to_tensor, - padded_shapes) - # pylint: disable=protected-access - padding_values = ( - padding_values if padding_values is not None else - dataset_ops._default_padding(input_dataset)) - self._padding_values = nest.map_structure_up_to( - input_dataset.output_shapes, dataset_ops._padding_value_to_tensor, - padding_values, input_dataset.output_types) - # pylint: enable=protected-access - - def _as_variant_tensor(self): - # pylint: disable=protected-access - return gen_dataset_ops.prepend_from_queue_and_padded_batch_dataset( - self._input_dataset._as_variant_tensor(), - batch_size=self._batch_size, - padded_shapes=[ - ops.convert_to_tensor(s, dtype=dtypes.int64) - for s in nest.flatten(self._padded_shapes) - ], - padding_values=nest.flatten(self._padding_values), - output_shapes=nest.flatten( - sparse.as_dense_shapes(self.output_shapes, self.output_classes))) - # pylint: enable=protected-access - - @property - def output_classes(self): - return (ops.Tensor, self._input_dataset.output_classes) - - def _as_batch_shape(self, shape_like): - return tensor_shape.vector(None).concatenate( - tensor_util.constant_value_as_shape(shape_like)) - - @property - def output_shapes(self): - # First output is a variant representing the Queue - return (tensor_shape.vector(None), - nest.map_structure(self._as_batch_shape, self._padded_shapes)) - - @property - def output_types(self): - # First output is a variant representing the Queue - return (dtypes.variant, self._input_dataset.output_types) - - -def prepend_from_queue_and_padded_batch_dataset(batch_size, - padding_values=None, - padded_shapes=None): - """A transformation that prepends a queue to a `Dataset` and batches results. - - A vector of handles to the queue is returned as the first component of the - associated iterator. This vector can be passed to `enqueue_in_queue_dataset` - to add new elements to the queue. - - Below is an example of how this dataset might be used to split incoming - variable-length sequences into "head" and "rest" parts, where "rest" parts - are re-enqueued back into the dataset. A more realistic example would - perform some calculation on the "head" and modify some components of "rest" - with the result (before re-enqueueing). - - ```python - dataset = tf.data.Dataset.from_tensor_slices([2*x for x in range(10)]) - # Make a dataset of variable-length vectors and their lengths. - dataset = dataset.map(lambda count: (count, tf.ones((count,)))) - # Emit a queue we can prepend to, and counts/values as padded batch. - dataset = dataset.apply( - tf.contrib.training.prepend_from_queue_and_padded_batch_dataset( - batch_size=10)) - dataset = dataset.prefetch(1) - - iterator = dataset.make_one_shot_iterator() - queue, (count, padded_value) = iterator.get_next() - - # Split the padded_value into two pieces: head and rest - rest_indices = tf.squeeze(tf.where(count > 3), axis=1) - bound = tf.minimum(3, tf.reduce_max(count)) - value_head = padded_value[:, :bound] - count_rest = tf.gather(count - 3, rest_indices) - value_rest = tf.gather(padded_value[:, bound:], rest_indices) - queue_rest = tf.gather(queue, rest_indices) - enqueue_rest_op = tf.contrib.training.enqueue_in_queue_dataset( - queue_rest, (count_rest, value_rest)) - with tf.control_dependencies([enqueue_rest_op]): - calculation = fn(value_head) - - while True: # Will raise OutOfRange when finished with all pieces. - session.run(calculation) - ``` - - Args: - batch_size: `int64` scalar tensor. The batch size to use when performing - padded batching. - padding_values: (optional) Nested tuple of scalar tensors. If provided, - the structure and dtypes of padding_values should match that of - incoming dataset's `output_types`. - padded_shapes: (optional) Nested tuple of `int64` vector tensors. - If provided, the structure must match that of the incoming dataset's - `output_types`. If not provided, the incoming dataset's `output_shapes` - is used. Any unknown (`None` or `-1`) dimensions in the shapes are - treated as being unique per-batch: for each batch time, an unknown - dimension is replaced with the maximum given value of this dimension - across all tensors for the given component in the batch. - - Returns: - A `Dataset` transformation function, which can be passed to - `tf.data.Dataset.apply`. - """ - - def _apply_fn(dataset): - return _PrependFromQueueAndPaddedBatchDataset( - dataset, - batch_size=batch_size, - padding_values=padding_values, - padded_shapes=padded_shapes) - - return _apply_fn - - -def enqueue_in_queue_dataset(queue, components): - """Enqueue components into queue from `PrependFromQueueAndPaddedBatchDataset`. - - The components' dtypes and shapes must be compatible with the `output_shapes` - attribute of the `dataset` created by - `prepend_from_queue_and_padded_batch_dataset`. This operation supports both - non-batched and batched modes. - - For more details, see the example in the docstring for - `prepend_from_queue_and_padded_batch_dataset`. - - Args: - queue: `variant` scalar or vector tensor. - The tensor emitted by the first component of the iterator associated with - `prepend_from_queue_and_padded_batch_dataset`. If this is a scalar, - then the `components` input tensors should not have a prepended batch - dimension. - components: Nested tuple of tensors, each with a leading batch dimension - if `queue` is a vector. The structure, dtypes, and shapes - (excluding batch dimension) must match the nested tuples - `dataset.output_types[1]` and `dataset.output_shapes[1]` (the non-queue - output types and shapes) of the `dataset` emitted by - the original `prepend_from_queue_and_padded_batch_dataset` call. - - Returns: - An `Operation` that enqueues `components` into the dataset(s) associated - with entries of `queue`. - """ - return gen_dataset_ops.enqueue_in_queue_dataset( - queue=queue, components=tf_nest.flatten(components)) diff --git a/tensorflow/contrib/training/python/training/tensor_queue_dataset_test.py b/tensorflow/contrib/training/python/training/tensor_queue_dataset_test.py deleted file mode 100644 index c1657fec7b..0000000000 --- a/tensorflow/contrib/training/python/training/tensor_queue_dataset_test.py +++ /dev/null @@ -1,355 +0,0 @@ -# Copyright 2016 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for TensorQueueDataset.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import numpy as np - -from tensorflow.contrib.training.python.training import tensor_queue_dataset as tqd -from tensorflow.python.data.experimental.kernel_tests.serialization import dataset_serialization_test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import ops -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import string_ops -from tensorflow.python.platform import test - - -class PrependFromQueueAndPaddedBatchDatasetTest(test.TestCase): - - def testNoEnqueue(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0, 1, 2]) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=1)) - self.assertEqual((dtypes.variant, dtypes.int32), dataset.output_types) - self.assertAllEqual(([None],) * 2, - [x.as_list() for x in dataset.output_shapes]) - iterator = dataset.make_one_shot_iterator() - _, value = iterator.get_next() - self.assertEqual([0], self.evaluate(value)) - self.assertEqual([1], self.evaluate(value)) - self.assertEqual([2], self.evaluate(value)) - with self.assertRaisesOpError("End of sequence"): - self.evaluate(value) - - def testBatchedNoEnqueue(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0, 1, 2]) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=2)) - iterator = dataset.make_one_shot_iterator() - _, value = iterator.get_next() - self.assertAllEqual([0, 1], self.evaluate(value)) - self.assertAllEqual([2], self.evaluate(value)) - with self.assertRaisesOpError("End of sequence"): - self.evaluate(value) - - def testBatchedWithBiggerPaddingNoEnqueue(self): - dataset = dataset_ops.Dataset.from_tensor_slices([[0], [1], [2]]) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset( - batch_size=2, padded_shapes=[3])) - iterator = dataset.make_one_shot_iterator() - _, value = iterator.get_next() - self.assertAllEqual([[0, 0, 0], [1, 0, 0]], self.evaluate(value)) - self.assertAllEqual([[2, 0, 0]], self.evaluate(value)) - with self.assertRaisesOpError("End of sequence"): - self.evaluate(value) - - def testBatchedWithBiggerPaddingOneEnqueue(self): - dataset = dataset_ops.Dataset.from_tensor_slices([[0], [1], [2]]) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset( - batch_size=1, padded_shapes=[3])) - iterator = dataset.make_one_shot_iterator() - queue_handle, value = iterator.get_next() - enqueue_negative = tqd.enqueue_in_queue_dataset(queue_handle, -value) - with self.cached_session() as sess: - self.assertAllEqual([[0, 0, 0]], sess.run(value)) - value_1, _ = sess.run([value, enqueue_negative]) - self.assertAllEqual([[1, 0, 0]], value_1) - value_2, _ = sess.run([value, enqueue_negative]) - self.assertAllEqual([[-1, 0, 0]], value_2) - value_3 = sess.run(value) - self.assertAllEqual([[1, 0, 0]], value_3) - value_4, _ = sess.run([value, enqueue_negative]) - self.assertAllEqual([[2, 0, 0]], value_4) - value_5 = sess.run(value) - self.assertAllEqual([[-2, 0, 0]], value_5) - with self.assertRaisesOpError("End of sequence"): - sess.run(value) - - def testOneEnqueue(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0, 1, 2]) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=1)) - iterator = dataset.make_one_shot_iterator() - queue_handle, value = iterator.get_next() - enqueue_negative = tqd.enqueue_in_queue_dataset(queue_handle, -value) - with self.cached_session() as sess: - self.assertEqual([0], sess.run(value)) - value_1, _ = sess.run([value, enqueue_negative]) - self.assertEqual([1], value_1) - value_2, _ = sess.run([value, enqueue_negative]) - self.assertEqual([-1], value_2) - value_3 = sess.run(value) - self.assertEqual([1], value_3) - value_4, _ = sess.run([value, enqueue_negative]) - self.assertEqual([2], value_4) - value_5 = sess.run(value) - self.assertEqual([-2], value_5) - with self.assertRaisesOpError("End of sequence"): - sess.run(value) - - def testBatchedOneEnqueue(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0, 1, 2]) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=2)) - iterator = dataset.make_one_shot_iterator() - queue_handle, value = iterator.get_next() - enqueue_negative = tqd.enqueue_in_queue_dataset(queue_handle, -value) - enqueue_zeroth = tqd.enqueue_in_queue_dataset([queue_handle[0]], - array_ops.expand_dims( - value[0], axis=0)) - with self.cached_session() as sess: - value_0, _ = sess.run([value, enqueue_negative]) - self.assertAllEqual([0, 1], value_0) - value_1, _ = sess.run([value, enqueue_zeroth]) - self.assertAllEqual([0, -1], value_1) - value_2, _ = sess.run([value, enqueue_negative]) - self.assertAllEqual([0, 2], value_2) - self.assertAllEqual([0, -2], sess.run(value)) - with self.assertRaisesOpError("End of sequence"): - sess.run(value) - - def testManyEnqueue(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0, 1]) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=1)) - iterator = dataset.make_one_shot_iterator() - queue_handle, value = iterator.get_next() - enqueue_many_more = [ - tqd.enqueue_in_queue_dataset(queue_handle, value + 100 + i) - for i in range(1000) - ] - with self.cached_session() as sess: - value_0, _ = sess.run((value, enqueue_many_more)) - self.assertEqual([0], value_0) - rest = [] - for _ in range(1000): - rest.append(sess.run(value)) - self.assertEquals([[100 + i] for i in range(1000)], sorted(rest)) - # Going back to the original input. - value_1, _ = sess.run((value, enqueue_many_more)) - self.assertEqual(1, value_1) - rest = [] - for _ in range(1000): - rest.append(sess.run(value)) - self.assertEquals([[100 + i + 1] for i in range(1000)], sorted(rest)) - with self.assertRaisesOpError("End of sequence"): - sess.run(value) - - def testEnqueueWithPrefetch(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0]) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=1)) - # Prefetching will request additional values before they are - # available to the queue. - dataset = dataset.prefetch(buffer_size=3) - iterator = dataset.make_one_shot_iterator() - queue_handle, value = iterator.get_next() - enqueue = tqd.enqueue_in_queue_dataset(queue_handle, value + 1) - with self.cached_session() as sess: - i = 0 - while i < 4: - received, _ = sess.run((value, enqueue)) - if received.size > 0: - self.assertAllEqual([i], received) - i += 1 - received_last = False - while True: - try: - received = sess.run(value) - if received.size > 0: - self.assertAllEqual([4], received) - received_last = True - except errors.OutOfRangeError: - break - self.assertTrue(received_last) - - def testDatasetWithPaddedShapeSmallerThanInputFails(self): - dataset = dataset_ops.Dataset.from_tensor_slices([[0, 0, 0]]).repeat(None) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset( - batch_size=1, padded_shapes=[2])) - iterator = dataset.make_one_shot_iterator() - _, value = iterator.get_next() - with self.cached_session() as sess: - with self.assertRaisesOpError( - r"Incompatible input shapes at component 0 between " - r"input dataset this dataset: \[3\] vs. \[2\]"): - sess.run(value) - - def testEnqueueWithIncompatibleInputsFailsWithInformativeError(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0]).repeat(None) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=1)) - iterator = dataset.make_one_shot_iterator() - queue_handle, value = iterator.get_next() - - enqueue_bad_structure = tqd.enqueue_in_queue_dataset( - queue_handle, (value, value)) - enqueue_bad_dtype = tqd.enqueue_in_queue_dataset(queue_handle, - np.array( - [1.0], - dtype=np.float32)) - enqueue_bad_shape_no_batch_dim = tqd.enqueue_in_queue_dataset( - queue_handle, ([1],)) - enqueue_bad_shape = tqd.enqueue_in_queue_dataset(queue_handle, - np.array( - [[1]], dtype=np.int32)) - - with self.cached_session() as sess: - with self.assertRaisesOpError( - "mismatched number of tensors. Queue expects 1 tensors but " - "tried to insert 2"): - sess.run(enqueue_bad_structure) - with self.assertRaisesOpError(r"Expected component 0 to have batched " - r"shape \[1,...\], but saw shape: \[\]"): - sess.run(enqueue_bad_shape_no_batch_dim) - with self.assertRaisesOpError( - r"mismatched shapes at component 0. Attempted to insert tensor " - r"with shape \[1\] but queue expected shape: \[\]"): - sess.run(enqueue_bad_shape) - with self.assertRaisesOpError( - r"mismatched dtypes at component 0. Attempted to insert tensor " - r"of type float but queue expected type: int32"): - sess.run(enqueue_bad_dtype) - - def testEnqueueWithPaddedBatchFailsWithInformativeError(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0, 1, 2]) - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=1)) - with self.assertRaisesRegexp( - TypeError, r"Unable to create padding for field of type 'variant'"): - dataset.padded_batch(batch_size=10, padded_shapes=[1]) - - def testOneEnqueueWithPadding(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0, 2, 4, 6]) - # Make a dataset of variable-length vectors and their lengths. - dataset = dataset.map( - lambda c: (c, c * array_ops.ones((c,), dtype=c.dtype))) - # Emit a queue we can prepend to, and counts/values as padded - # batch. - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=3)) - - iterator = dataset.make_one_shot_iterator() - queue, (count, padded_value) = iterator.get_next() - - # Split the padded_value into two pieces: head and rest - rest_indices = array_ops.squeeze(array_ops.where(count > 2), axis=1) - bound = math_ops.minimum(2, math_ops.reduce_max(count)) - value_head = padded_value[:, :bound] - count_rest = array_ops.gather(count - 2, rest_indices) - value_rest = array_ops.gather(padded_value, rest_indices)[:, bound:] - queue_rest = array_ops.gather(queue, rest_indices) - enqueue_rest_op = tqd.enqueue_in_queue_dataset(queue_rest, - (count_rest, value_rest)) - with ops.control_dependencies([enqueue_rest_op]): - calc = array_ops.identity(value_head) - - with self.cached_session() as sess: - self.assertAllEqual([[0, 0], [2, 2], [4, 4]], sess.run(calc)) - self.assertAllEqual([[4, 4], [6, 6]], sess.run(calc)) - self.assertAllEqual([[6, 6]], sess.run(calc)) - self.assertAllEqual([[6, 6]], sess.run(calc)) - # Get some final batches due to prefetching. - for _ in range(3): - try: - self.assertAllEqual( - np.empty(shape=(0, 0), dtype=np.int32), sess.run(calc)) - except errors.OutOfRangeError as e: - self.assertTrue(str(e).startswith("End of sequence")) - - def testNonstandardPadding(self): - dataset = dataset_ops.Dataset.from_tensor_slices([0, 2, 4, 6]) - # Make a dataset of variable-length vectors and their lengths. - dataset = dataset.map( - lambda c: (c, c * array_ops.ones((c,), dtype=c.dtype))) - # Emit a queue we can prepend to, and counts/values as padded - # batch. - dataset = dataset.apply( - tqd.prepend_from_queue_and_padded_batch_dataset( - batch_size=3, padding_values=( - 0, - -1, - ))) - - iterator = dataset.make_one_shot_iterator() - _, (unused_count, padded_value) = iterator.get_next() - - with self.cached_session() as sess: - self.assertAllEqual([[-1, -1, -1, -1], [2, 2, -1, -1], [4, 4, 4, 4]], - sess.run(padded_value)) - self.assertAllEqual([[6] * 6], sess.run(padded_value)) - with self.assertRaisesOpError("End of sequence"): - sess.run(padded_value) - - -# TODO(ebrevdo): Figure out how to use run_core_tests to test state -# saving of an iterator that's had some tensors enqueued into its queue. -class PrependFromQueueAndPaddedBatchDatasetSerializationTest( - dataset_serialization_test_base.DatasetSerializationTestBase): - - def testPrependFromQueueAndPaddedBatch(self): - - def build_dataset(seq_lens): - return dataset_ops.Dataset.from_tensor_slices(seq_lens).map( - lambda x: array_ops.fill([x], x)).apply( - tqd.prepend_from_queue_and_padded_batch_dataset(batch_size=4)) - - seq_lens1 = np.random.randint(1, 20, size=(32,)).astype(np.int32) - seq_lens2 = np.random.randint(21, 40, size=(32,)).astype(np.int32) - self.run_core_tests(lambda: build_dataset(seq_lens1), - lambda: build_dataset(seq_lens2), 8) - - def testPrependFromQueueAndPaddedBatchNonDefaultPadding(self): - - def build_dataset(seq_lens): - - def fill_tuple(x): - filled = array_ops.fill([x], x) - return (filled, string_ops.as_string(filled)) - - padded_shape = [-1] - return dataset_ops.Dataset.from_tensor_slices(seq_lens).map( - fill_tuple).apply( - tqd.prepend_from_queue_and_padded_batch_dataset( - batch_size=4, - padded_shapes=(padded_shape, padded_shape), - padding_values=(-1, ""))) - - seq_lens1 = np.random.randint(1, 20, size=(32,)).astype(np.int32) - seq_lens2 = np.random.randint(21, 40, size=(32,)).astype(np.int32) - self.run_core_tests(lambda: build_dataset(seq_lens1), - lambda: build_dataset(seq_lens2), 8) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/contrib/verbs/rdma.cc b/tensorflow/contrib/verbs/rdma.cc index f7c979e863..9db80f6b57 100644 --- a/tensorflow/contrib/verbs/rdma.cc +++ b/tensorflow/contrib/verbs/rdma.cc @@ -30,7 +30,6 @@ limitations under the License. #include "tensorflow/core/distributed_runtime/rendezvous_mgr_interface.h" #include "tensorflow/core/distributed_runtime/rpc/grpc_util.h" #include "tensorflow/core/distributed_runtime/session_mgr.h" -#include "tensorflow/core/distributed_runtime/rpc/grpc_util.h" #include "tensorflow/core/framework/rendezvous.h" #include "tensorflow/core/framework/tensor.h" #include "tensorflow/core/lib/core/status.h" @@ -1028,7 +1027,10 @@ Status RdmaTensorResponse::PrepareRecvTensor( return errors::Aborted( "RecvTensor expects a different device incarnation: ", parsed.src_incarnation, " vs. ", (*src_dev)->attributes().incarnation(), - ". Your worker job was probably restarted. Check your " + ". Your worker job (\"", + channel_->adapter_->worker_env_->session_mgr->LegacySession() + ->worker_name, + "\") was probably restarted. Check your " "worker job for the reason why it was restarted."); } diff --git a/tensorflow/core/BUILD b/tensorflow/core/BUILD index a701b38d4b..575edfe7a9 100644 --- a/tensorflow/core/BUILD +++ b/tensorflow/core/BUILD @@ -95,7 +95,8 @@ load("//tensorflow:tensorflow.bzl", "tf_cc_test_gpu") load("//tensorflow:tensorflow.bzl", "tf_cc_tests_gpu") load("//tensorflow:tensorflow.bzl", "tf_cuda_cc_test") load("//tensorflow:tensorflow.bzl", "tf_version_info_genrule") -load("//tensorflow:tensorflow.bzl", "if_not_tx2_llvm_or_windows_cuda") +load("//tensorflow:tensorflow.bzl", "if_nccl") +load("//tensorflow:tensorflow.bzl", "tensorflow_opensource_extra_deps") load("//tensorflow:tensorflow.bzl", "tf_cuda_only_cc_test") # For platform specific build config @@ -112,6 +113,7 @@ load( "tf_additional_device_tracer_test_flags", "tf_additional_gdr_lib_defines", "tf_additional_human_readable_json_deps", + "tf_additional_logger_deps", "tf_additional_lib_defines", "tf_additional_lib_deps", "tf_additional_lib_hdrs", @@ -300,6 +302,7 @@ filegroup( "platform/env_time.h", "platform/logging.h", "platform/macros.h", + "platform/platform_strings.h", "platform/types.h", ], visibility = ["//visibility:private"], @@ -442,6 +445,18 @@ cc_library( ] + tf_additional_human_readable_json_deps(), ) +cc_library( + name = "logger", + srcs = tf_platform_srcs(["logger.cc"]), + hdrs = ["platform/logger.h"] + tf_platform_hdrs(["logger.h"]), + copts = tf_copts(), + visibility = ["//visibility:public"], + deps = [ + ":lib", + ":lib_internal", + ] + tf_additional_logger_deps(), +) + filegroup( name = "platform_env_hdrs", srcs = [ @@ -519,6 +534,19 @@ cc_library( ], ) +cc_library( + name = "platform_strings", + srcs = tf_platform_srcs([ + "platform/platform_strings.cc", + "platform/platform_strings_computed.h", + ]), + hdrs = [ + "platform/platform_strings.h", + ], + visibility = ["//tensorflow/core:__subpackages__"], + deps = [":lib"], +) + filegroup( name = "platform_other_hdrs", srcs = [ @@ -841,6 +869,7 @@ tf_cuda_library( "framework/dataset_stateful_op_whitelist.h", "framework/device_base.h", "framework/function.h", + "framework/function_handle_cache.h", "framework/graph_def_util.h", "framework/graph_to_functiondef.h", "framework/kernel_def_builder.h", @@ -884,6 +913,7 @@ tf_cuda_library( "util/bcast.h", "util/cuda_kernel_helper.h", "util/device_name_utils.h", + "util/dump_graph.h", "util/events_writer.h", "util/example_proto_fast_parsing.h", "util/example_proto_helper.h", @@ -901,6 +931,7 @@ tf_cuda_library( "util/stream_executor_util.h", "util/strided_slice_op.h", "util/tensor_format.h", + "util/tensor_ops_util.h", "util/tensor_slice_reader.h", "util/tensor_slice_reader_cache.h", "util/tensor_slice_writer.h", @@ -1038,6 +1069,7 @@ tf_gen_op_libs( "batch_ops", "bitwise_ops", "boosted_trees_ops", + "tensor_forest_ops", "candidate_sampling_ops", "checkpoint_ops", "collective_ops", @@ -1085,7 +1117,11 @@ tf_gen_op_libs( op_lib_names = [ "string_ops", ], - deps = ["@com_google_absl//absl/strings"], + deps = [ + ":lib_internal", + ":lib_proto_parsing", + "@com_google_absl//absl/strings", + ], ) tf_gen_op_libs( @@ -1187,6 +1223,7 @@ cc_library( ":batch_ops_op_lib", ":bitwise_ops_op_lib", ":boosted_trees_ops_op_lib", + ":tensor_forest_ops_op_lib", ":candidate_sampling_ops_op_lib", ":checkpoint_ops_op_lib", ":collective_ops_op_lib", @@ -1340,6 +1377,7 @@ cc_library( "//tensorflow/core/kernels:batch_kernels", "//tensorflow/core/kernels:bincount_op", "//tensorflow/core/kernels:boosted_trees_ops", + "//tensorflow/core/kernels:tensor_forest_ops", "//tensorflow/core/kernels:candidate_sampler_ops", "//tensorflow/core/kernels:checkpoint_ops", "//tensorflow/core/kernels:collective_ops", @@ -1386,9 +1424,7 @@ cc_library( "//tensorflow/core/kernels:summary_kernels", "//tensorflow/core/kernels:training_ops", "//tensorflow/core/kernels:word2vec_kernels", - ] + tf_additional_cloud_kernel_deps() + if_not_tx2_llvm_or_windows_cuda([ - "//tensorflow/core/kernels:nccl_kernels", - ]) + if_not_windows([ + ] + tf_additional_cloud_kernel_deps() + if_not_windows([ "//tensorflow/core/kernels:fact_op", "//tensorflow/core/kernels:array_not_windows", "//tensorflow/core/kernels:math_not_windows", @@ -1413,6 +1449,8 @@ cc_library( ]) + if_cuda([ "//tensorflow/core/grappler/optimizers:gpu_swapping_kernels", "//tensorflow/core/grappler/optimizers:gpu_swapping_ops", + ]) + if_nccl([ + "//tensorflow/core/kernels:nccl_kernels", ]), ) @@ -1437,7 +1475,7 @@ tf_cuda_library( ":gpu_runtime", ":lib", ":ops", - ], + ] + tensorflow_opensource_extra_deps(), ) cc_library( @@ -1577,6 +1615,8 @@ filegroup( "util/stats_calculator.*", "util/reporter.*", "platform/**/cuda_libdevice_path.*", + "platform/**/logger.cc", + "platform/**/logger.h", "platform/default/test_benchmark.*", "platform/cuda.h", "platform/google/**/*", @@ -1671,8 +1711,8 @@ cc_library( cc_library( name = "mobile_additional_lib_deps", deps = tf_additional_lib_deps() + [ + "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/strings", - "@com_google_absl//absl/time", ], ) @@ -1763,7 +1803,7 @@ cc_library( # registration of ops to prune code size. cc_library( name = "android_tensorflow_lib_selective_registration", - srcs = if_android(["//tensorflow/core:android_srcs"]), + srcs = if_android(["//tensorflow/core:android_srcs_only_runtime"]), copts = tf_copts(android_optimization_level_override = None) + [ "-DSUPPORT_SELECTIVE_REGISTRATION", ], @@ -1775,9 +1815,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":protos_all_cc_impl", - "//third_party/eigen3", - "@double_conversion//:double-conversion", - "@nsync//:nsync_cpp", + "@com_google_absl//absl/container:flat_hash_set", "@protobuf_archive//:protobuf", ], alwayslink = 1, @@ -1787,7 +1825,7 @@ cc_library( # no proto_rtti. cc_library( name = "android_tensorflow_lib_selective_registration_nortti", - srcs = if_android(["//tensorflow/core:android_srcs"]), + srcs = if_android(["//tensorflow/core:android_srcs_only_runtime"]), copts = tf_copts(android_optimization_level_override = None) + tf_opts_nortti_if_android() + [ "-DSUPPORT_SELECTIVE_REGISTRATION", ], @@ -1799,9 +1837,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":protos_all_cc_impl", - "//third_party/eigen3", - "@double_conversion//:double-conversion", - "@nsync//:nsync_cpp", + "@com_google_absl//absl/container:flat_hash_set", "@protobuf_archive//:protobuf", ], alwayslink = 1, @@ -2045,9 +2081,7 @@ tf_proto_library_cc( srcs = ["protobuf/master.proto"], cc_api_version = 2, protodeps = tf_additional_all_protos(), - visibility = [ - "//tensorflow:internal", - ], + visibility = ["//tensorflow:internal"], ) tf_proto_library_cc( @@ -2187,6 +2221,7 @@ cc_library( "platform/**/env_time.cc", "platform/**/cuda_libdevice_path.cc", "platform/**/device_tracer.cc", + "platform/**/logger.cc", "platform/**/logging.cc", "platform/**/human_readable_json.cc", "platform/abi.cc", @@ -2199,6 +2234,7 @@ cc_library( "platform/**/stream_executor.h", "platform/**/env_time.cc", "platform/**/device_tracer.cc", + "platform/**/logger.cc", "platform/**/logging.cc", "platform/**/human_readable_json.cc", "platform/abi.cc", @@ -2641,6 +2677,8 @@ tf_cuda_library( ":stats_calculator_portable", ":version_lib", "@com_google_absl//absl/base", + "@com_google_absl//absl/container:flat_hash_set", + "@com_google_absl//absl/strings", "//tensorflow/core/platform/default/build_config:platformlib", "//tensorflow/core/kernels:bounds_check", "//third_party/eigen3", @@ -2943,6 +2981,7 @@ tf_cuda_library( ":lib_internal", ":proto_text", ":protos_all_cc", + "@com_google_absl//absl/memory", "//third_party/eigen3", "//tensorflow/core/grappler:grappler_item", ] + mkl_deps(), @@ -3008,7 +3047,6 @@ tf_cuda_library( hdrs = ["common_runtime/metrics.h"], deps = [ ":lib", - "@com_google_absl//absl/time", ], ) @@ -3033,7 +3071,6 @@ tf_cuda_library( ":protos_all_cc", "//tensorflow/core/debug:debug_graph_utils", "//tensorflow/core/kernels:function_ops", - "@com_google_absl//absl/time", ], alwayslink = 1, ) @@ -3393,6 +3430,7 @@ tf_cc_tests( "platform/profile_utils/cpu_utils_test.cc", "platform/stacktrace_handler_test.cc", "platform/subprocess_test.cc", + "platform/vmodule_benchmark_test.cc", ], deps = [ ":lib", @@ -3406,6 +3444,20 @@ tf_cc_tests( ], ) +tf_cc_test( + name = "vmodule_test", + srcs = ["platform/vmodule_test.cc"], + tags = ["optonly"], + deps = [ + ":lib", + ":lib_internal", + ":lib_test_internal", + ":protos_all_cc", + ":test", + "//third_party/eigen3", + ], +) + tf_cc_test( name = "lib_random_random_distributions_test", srcs = ["lib/random/random_distributions_test.cc"], @@ -3421,6 +3473,16 @@ tf_cc_test( ], ) +tf_cc_test( + name = "platform_strings_test", + size = "small", + srcs = ["platform/platform_strings_test.cc"], + deps = [ + ":lib", + ":platform_strings", + ], +) + tf_cc_test( name = "platform_env_test", size = "small", @@ -3668,6 +3730,7 @@ tf_cc_tests( "util/bcast_test.cc", "util/command_line_flags_test.cc", "util/device_name_utils_test.cc", + "util/dump_graph_test.cc", "util/equal_graph_def_test.cc", "util/events_writer_test.cc", "util/example_proto_fast_parsing_test.cc", @@ -3798,6 +3861,7 @@ tf_cc_tests_gpu( ":test", ":test_main", ":testlib", + "@com_google_absl//absl/memory", ], ) @@ -3826,6 +3890,7 @@ tf_cc_tests_gpu( ":test", ":test_main", ":testlib", + "@com_google_absl//absl/memory", ], ) @@ -4099,6 +4164,7 @@ tf_cc_test( "//tensorflow/core/kernels:identity_op", "//tensorflow/core/kernels:immutable_constant_op", "//tensorflow/core/kernels:matmul_op", + "//tensorflow/core/kernels:topk_op", "//third_party/eigen3", ], ) @@ -4392,6 +4458,7 @@ tf_cc_test( "//tensorflow/core/kernels:random_ops", "//tensorflow/core/kernels:shape_ops", "//third_party/eigen3", + "@com_google_absl//absl/memory", "@com_google_absl//absl/strings", ], ) @@ -4871,6 +4938,7 @@ transitive_hdrs( "//tensorflow/core:core_cpu", "//tensorflow/core:framework", "//tensorflow/core:lib", + "//tensorflow/core:platform_strings", "//tensorflow/core:protos_all_cc", "//tensorflow/core:stream_executor", ], diff --git a/tensorflow/core/api_def/api_test.cc b/tensorflow/core/api_def/api_test.cc index 6f98856915..d38a8424eb 100644 --- a/tensorflow/core/api_def/api_test.cc +++ b/tensorflow/core/api_def/api_test.cc @@ -182,11 +182,14 @@ void TestDeprecationVersionSetCorrectly( for (const auto& name_and_api_def : api_defs_map) { const auto& name = name_and_api_def.first; const auto& api_def = name_and_api_def.second; - ASSERT_TRUE(api_def.deprecation_version() == 0 || - api_def.deprecation_message().empty()) - << "ApiDef that includes deprecation_version > 0 must also specify " - << "a deprecation_message. Op " << name - << " has deprecation_version > 0 but deprecation_message is not set."; + if (api_def.deprecation_version() != 0) { + ASSERT_TRUE(api_def.deprecation_version() > 0) + << "Found ApiDef with negative deprecation_version"; + ASSERT_FALSE(api_def.deprecation_message().empty()) + << "ApiDef that includes deprecation_version > 0 must also specify " + << "a deprecation_message. Op " << name + << " has deprecation_version > 0 but deprecation_message is not set."; + } } } } // namespace diff --git a/tensorflow/core/api_def/base_api/api_def_BatchDataset.pbtxt b/tensorflow/core/api_def/base_api/api_def_BatchDataset.pbtxt index 639d962874..32def912f8 100644 --- a/tensorflow/core/api_def/base_api/api_def_BatchDataset.pbtxt +++ b/tensorflow/core/api_def/base_api/api_def_BatchDataset.pbtxt @@ -1,5 +1,6 @@ op { graph_op_name: "BatchDataset" + visibility: HIDDEN in_arg { name: "batch_size" description: <

p|CUUfqAK?1t+tjXQexoFAw@s(GyY zXKBxGyr_QV|EBF-_Q#Sh8^3+~e&fgKpBH|0{kHh?|L+fm3CvemX0dK#d&Rzo<2uJ- zjy;@vxMg`+d24w}cy{qj;Bn%%;{46d$`Qq}gkvRVJ@-W3G=4t;9RUx4T){m;Wx{`i z?}>aBy(xB1?189==vNUTQC?94(Ve2x#gfD`#b=52h)xhO70wo%$8W|L&8x|q$y>*}u$zqWqc@cq}1LqE%Yh5ugk`^2w?pXooQ zeRurc`u)jw@gGS)e*T#H^V!ecKLdX{{=D{c_pb@R8~(`rQ)6ghT+XP$c!*&x!z_li z43dnkOsiP*+3ML=vZ=BMv;Sk8$=1NOn~j0JicOl8nPm@iIdcKiAqLL>7ytVFW&eBW zkM&=de-i)2|C{|g_-E7aw%@CN=l*8;z2X?O@7<@ zhWE9|%U92Mo_0Jod?fL3!GjwQiXKWnYJC*{==npwM}Hn|f9&;y@0rTWGp~i-=Df{# zoAGwa+vK(BMQxxzPIv~s-A|SF_#9Xvk^u6dkv3ugv zCH6>!ODIT0OGrpe6-yF{6*?fWg};$sSU^EAOvqSRPFP0hy+E?SMu8N;mx6^t{=&8* z>qXi`6hwXtXNp*ez7y>cGZnuft|Dfg_a8i2_F%@Bit+;Bs4?7 zn?Hf?Iu8rC4Oa_SFqbUnZuawRmTa3?*;or$Ro8V#yrB`1b#W z|Md+0jCRZgtd;DSIHWnlIE>iK*_N>#WPiiq#3{h}mZOZLkbM$cHQOJy@9bfmXSghR zx_ATlGWneNg!ne{I`GQy%JMStO7LFbJAX`9C&_Zahu#{+_=yj1U z5lPWAqUmDk;`=2INJ>bZm#mazlk$*$FTG4UO}bp#S^A$;w)7mCJF;1FUu1X4I7mxN zO_SUzDJUf&bxG1sQboc-%v|J=kiO7XL0Q2-fh7JczHnX+o-D2n9M{X5}z*{{z( zSbx0wzT^9%Z{=Sme*E>$>8<&j4Xzl+EBAKJT=u&xDop9g$DU*8&k^#6?eCI5T#@Atot z|IYjE`n%`1{GTg-ru;4bxA6ZX1`Eb;hUEWx|G)if|Hu1(0>d=MWsJRyvl!Pg-e-Kt z_?Phl6Dx}YODJ;-Qwb9X^DO3IWR0& zQ}%}JCD{zwaG4)ctWxQcPbC&fbV;O0ESC5oAuRDhR6^vgkc(gw|6;zae9`=W_`~_V zc@J_g;$FjT%Ke<{0oQgeZ>}cJg&ejVAskX1Z0zN%N-VX^vzRZj$g$^g-r{QFuIBFL za^zgZ@sOjFQ-`aKE1yfAioC_u?nyi=c{lJC@Sox56yO$^$^VismoJ#Fh3^pG zT|NzdR)L=aS%L|Iw*)@%xAJoc%oKPe@IY{iaIZ+BNTbL`Q5ErMiJOuerKiXW%de5I zlW&q&P?(`$qo68(L6%QeMYc}%i|k`LErr7hYzm%oxiX^C@lu9TE>e#q=SVyfQxQ!O z-Xs_((9CbiZ^Ez7|BBC-&ztuHcRQC4rv`@@yBFIP*7K}fY$|NJY^iKgYztXbnB$mQ z8Jiih84MYJGkP-}VO+xS^#8H{0smwEP5rC$_w*meKmEU6|G4m-{ricpdp;L^oc2EG zUHaSaZ@Au`coXwl^X02&6;H$-9eXh0f$M{i`>*aw-SNC7d~@E7-8aH-3g6m#EC06G z9p5`icQ)K{zUz8#*?qf*p^urKoqSRMI^mu3$F9#Gzf^tg`ugVU<8PO~ul`Z^%k6K` ze|3hb3=0`oGQ~5SvUIY>uuF0N=CtNI#x<4u4fjOubzFNm>p3;KRJdh%Vt7~adGWvH zyTN;z=P=J*-T;0(fkgrb1x^WE6xblpF7QC$qTpkp1H$eig(4?K+(orTQ$)&z3xtvd zR|=fw&*4+yb>eB~UdeTh;}GjTCMm|)|89R({)GO?{gd?D>*wolwqHHI1b_DWbmC*x z$2%Xsz2EW9`|Xd@pQpdC|K|H6^LO{Z^#9xb>HORE@8KE&nYUHZYuJ5ND|QSNEs$SKg0X-`c*-_{RP1@t4@oyFYe*nEJl{ z-O;xb-iEw=^(O1htk;`f{dy_z^6~Q*&%B@gdaCy9z_VG;*Sxs)a?dNJ*9Ts8zHEQ7 z=|$GdA1}pTi@#m}?!`O5cQ@Y(zI*j<*Zb-Z%^!U}Nq!3WnD-(1{lRy;-=)9He|z%H zk2jazroVUo*!Ahxr-Pr4eT@5{^?uwhqPZ}slZ+rYPhZ)U!p_?qL*i8n28 zUEbBb*ZjEX)49)ozxaRK_TBC0r(X~Lu>H4WY-Y}6)nPMZ>tb_cf6Bg*;|=Fr?lxW- z{=NK*`Ty}}3x)}w7TF}~E;dzcwiuV#N0BIzVd1P^SV|X4 zc}rDDO_w?^Wh>nz?Jqr9%2P5$e7fjbkpPk1!v4aM!jFV%1)uQm;S=OL&s)!Xf`^MI znY)myjZ>9Vj?;kCigOBwJUc7fb=DxZdF*wZ54k3D3-c)OJm41RdBY>i*Uq0Hz$6gO z@5>*_Z_1y@&m!u5cMji` zy1(v0>7$uX)SlmYY4wKh-KzK3KK%P|@yr3mrXBOU)#SedN1_x>POK}W}n`EEc&?UU{V3 z(fD)EuZrI$fAs$D`fK=4>;HuRYyK_#d-Ko!-%Ed~|C0Mv`Agz=-|zjuGk>T3n)8$K z*ZE(~zi0mu`RD%MfMFTKR)%Codu9XH1U3QoICdxY(`-jstyx|&*)e4>-udtSuj%iq zzls0;{k!n*)L*qfpMFmLzUHg%m*UStpJhH>dSCKZ@{PdjhcB65w!J8Q!ToaU%O@|D zU+sAH^VRxS46kfnE_@;PV*hi)7h*4iUi!b>_R`~J^K;E-m!390t$CXNY~J&p7t3Du zzuNlh(yOJfpTCiOcmLh{cPHOTy?1y&|DDvk?00M4eS2H;M)LK%R~E0C-gv%Yc=P2| z;Y;rqe9z^d$~+N&D)4Of)6Y*%J~{KG{VC^jix*-qV_uzk{rb(1w_@*2Kg53Q`gG{C z=GQmh;(o^cVf%lX!GmcYb27^kmVB1K%w{ZWS(DlAINo!}b1`!N;hN6Xz@@~!nJ1mk zkADXLFaC6aSpppb8UhRg4FZn^JOrlla|<*GstEgubc^tcSPQcYJr|fM@J--=;CG>S z!j2;EMSR7Q#Wf^?B`c)Dq$kOU$_2{TDm+*GtrV+lro2pvOX;%WBgK!37Zno}wBn>6ZB_>H65O)+iEg~b_BbX*&z+b^<&EG8W zPvEtHoS?Fhrbw087x5B_LJ56|%i=lWhs5f|?8O-+qQ&ov?h#=TaTJ~?BqQ`&utq3e zc(-t|u!AtC@FBtF{1$xMc*A*vcxCu@^7Zmv<&zW07TCq7&AXVFkN-ITQ~qXw+k%F| z0wT{v`bFo8T8U{$cu9s!>=i#Lp(E)dAuCZJaY_7=*gH`@5i21+A$wsdkw}qrk-Nf$ zLMZ~~e1~|Fcyf3cdERk}b3R~GV6|kq#{8Rk1`9hYJL?aYQ!EiIKbZ5G)0vJjIy0SQ zI?8mCX(Q84MrQ`&|NZ|q{&o0s`&ad^SHGV9a{0yeEB#mbuVX*Y{!sXF`TOGUE#Kq5 zD}Gn_9{v5@x9+b#U*>+^{VD9@oA*E8oqDJ7{^Pr8Z*RZ8{_@AOGmldrp1W^z|Hu8+ z55C^#x$k*@|NRyBpWW|$@aw_Shx;G3JXU`)?PSQ9 zZ@#|xvHZ8sU&DXg|797>7*(16G3ByMVe{fx$FY)QF6RX9D&ADSEWQH14}5?49`p9` z2=mDE=D!Nj%QFOgXzHqV7B0(R4JiaELYg`_j2iZTdmM~W`u>NcL0(7<9QeJ?%2DAcY$x+-sHTQ`1ZlOukUw$2>$r;qvWTVA5}hP zf8_cU{VDTP|EGta(m#Ly9Q`Hli|-fVFKa)a_~iES#rrMqw|$WNl=OMlmpfmteG~h> z@!RTe&%d+%;{Mb3_x?WyhE)u03~T-$`ltD?|8LKq{NE>j&HUB$%m3G>pYMLG{MPY# z?T74lwQuZSo4js({q)tMm-}AKcyai}>KCpr7+wUuc=#gzrRJ+CuhrgKzH50W_pb3R z-`lNka^LvBDSLD2P59fTZ#~{Ryb*g{{A$iC?$<7_KfgZs_SSoyk7}P*e%|+W?f32< z;y>)ZKmOMFt^RA^ms_7DzT|$<`eODu{!`+o6Q3@A^7~Zsap4Ef4=(RT--*9vdwcoq zk#~3B?RvZZ&EGc%-)?#v|5oDN+V{yH_kWu8x%dn7w-?`8f9Cu&{k7$H$KQ(oRgC7$ z(^<6GKC$2AaN}6cZo?75`JZzR*GldOJb!o}^4aol)GUHk$9x%^*v=kUbwJmS&ht>%5srzm(^s7kmsp#6o0) z@GGHUp+|zp1jU5Hh2({<3a%IQ71R*uM3-%lyj)ErjDmibU^;oslq< zx+K{s@k?A$;*q$q_zST{@hXX368FTviCq$775^ZXC*~r$Mc7X0wZJ}pLH>VycKj3h zZTKsA<+)FAx^vcXOk$5^=i*T1e9C#0vyAg4=O(VJT=rZiI3II5bIEgsaxUU1#!`2Ih9=SSB6DNsN_D+DtbXX8u?IKjZ(&|GobX{<-@* z^7reX%0C3YFZ&kv?aNozuTh^&x*hH|9<|J{%7!iD?>MZJ)eTGw}8^2fs; zir;^G8~0ZB-M)8E-j=+%^P2HZ>YLwh_P?F@uI+umhu9CN-}}DjfB*2^m3QagRlHmE zmgg<&+skj(zh3(4-K!(7_r7*`?fLr3YqvK>Z+5&Ed875NslYmHasFU?+lezEn1^~-OsZoFxIoBDS0Tj_T# z?~cD?eLwTP=ttAf`d_)eyZkKv&HLB*pW}Zs27kt@Og${zZ0YPWoD$p}JVLyQyb^qN z{L=+$1?LL>66_Ra6MZI`K}&)Ae2%<9Jg<3<^QQ35;W^6V%FDzX!DGmC zisu1uCEt5qMP41=`MhPk`*<9AHuJFXN%Q;iPvd_nP$^_4Y$_}){9ovv&?=!$p=CmE zg=&SHMSMjCMT?;^E$S<_QLI4RU*d;2@`O@q%l`^MfKFWy7M#x6X zUX^i^iI!O-GfgH{X042`>;X=afq<*VEw>6ow4+P-#`6- ztbcF+j{kG(Z|lGKe;NM{{yYBf%U_j0KYp70xcJTY>yFR0pI(04_>uWz>wAlL-{1at zEBvYaOc4DL4E zy?;0M-m!b~_wU{R^?>^k<71g8E>FdtoqzV@x$8^jSGBL^zSeka^lsa`$oIM*u6>aC zc=N;L4}U-Oe02R-@j>ZB;)l5(^gpn?mv|TW?#;Vr@6NvKe}C)4g^v=Sc6>Db$n=r% z+myPr{5!dKq3@F3&3||P{j`rtpZ&gseGUIs^S$o}+fS~a>OUiXR{y;Iv+bAr zZ^1u5{~Y}L<8S`oJAZ8cI{Z8O@A1Dg{}UM}F^MuaGi$SaV2NinVtv4Jgr$MyKC=$< za;7?_gG}d{elp%=uwmHzf9Jo5zgK^k{7U{A{X^&b_pj%^?EcL9Ir)?F#|`f}-~WGi z_uc$=i{5>GSNi_)`}glnKm7Wz|D(aDo=;~!UHSC?Q`+a{pNl_V`}F6d{>Q=(k?#fH z`MmXh+x~XZ+l6o6zrFVE&U^C@Y9D5OX#B|e>A=T#9~eJqytjP!@6DChQm+rcTKDSg ztGllbzq-FK+hh7W3e(-Ygi_quN&%~Z?c_Q%i*3+lYI9}+!^nYdWy6N?-*Z*Fx ze>3~-=Xa|=WPB3%()hLboA>usKN5d2|5^7p<^L51C8m|k{;ZSOjM;nGf3Vwg9AQ7h zR?PN|t)E?*Lz=UWYaTZ{&w1_??%!M`TrW5ebEa`^<8J2l<)00|u*gcwO_P^Z%vb7DZc`Cby{+<4 zxlO4+@uk9Pg-Z%DimwzIl&>jwsfek@sD`OJs>Z7BQWaIRQVUY6QCp|>NR3-vUENIG zUp+~^P`yX}v3jnCkmg>^ADS(iuQX<96luh0lxfV>_@%K{(^^YU>%3;2rlw|>#vAoX z>h|h8)S}g5)k4$`sPd``sGe6%Qj1lyR?}DeuBxSaQrS<5PjR*U3E2i|KgrAD@5Mfd z?h?5q>>+$m=!M{ZfgFBCzJokM+&Y|H?73{OSdXyAvL>?>GwU+{V{&53WcRX7=kX zuVdbPeUtTe=iB*jzrH#2TIrR^i@<07Pj)`K`JnB-;QcrErrzVc*KqgPo%-85Z=SpU z@2cyS=a(EWnP0NHq;sk3lKU}-*<<=MPuNS}iep~tN*0-DAa=vwa_5E_~ zQ|!mf@9p0Gev|)Z&YP&W+3%{}$A5VJ;l+o>4?-XAz5n_??8BQ6T^}Vrt@>2)x$=wJ zSL3fgzuf$C{L7{%Vz_mi{{VBmBGlw>@8&KJWUt^~0O@_ufBxKly#}`@Z)P?-}3k zdN<|W<98MB|Gr=HA?@R)kI5hReqj5M^Pcg2)w`~@6W;uI9rAkdE3Q}XUsOH+@{H$s z!Lx%;S)bi~w)naKiv=$_UL?NIezEHL=Vu|$o5IiL4!j6`$^NS6mHX=%Z>GIn_%`e9oVSnOdc1q{Zpr)Y zA8I~@eR=vd`un;c=YM|r#qx*kuj9W-|IaeSFh#K#vCU(D%VEgHz}?R6!_&`e#s65~ zx8MaKArS}BJkc*AEh4cZB_b0=YDEr;h>Ar@{E^C&^^!lP5T&$MSwn?MWudaH@?0f< zB_Sm>B^zZuRde+p8u41T+RQqCb(ZKZ)Q!_M)y>m2(sR&{HV8HRXXs^QVRX*W!?4!C zUq4Xqpl*?_x2~A(Or6`>x3zw1F4qjxWY_$yDWY>!w@dGk-UK~CJzrfJof}%WHKjFs zG_*B1HS{!kHDomRX@1k3tSP3MrQxO?q^749sOF;Pt~ObXS=~`RKs{0YyV^5V4%I@H z1$+F$vu*NBvU2h zCUaDJskE}p7MVy{VL1^wM%g>kPSRCUZjvDqC&UxQZ;Q2x-W3iM4i(-ev_h~z;5XkK zUOAptE?v$e?1F4tSQ40LGx{+kFeo!_WIW6m!+4RwogwW1-M=k=j{Tndd-?Chzjyw= z^n26qMZc|o@B4Y>yTG?6pXYw$djItG{Fe`&Z+=?$pqVA8S9Ye!l1J^e-O2 zJOAta`T1?)_x(Sme;@mE+nzETgEHL ztH<+&tBdO>S1Q*;&KS(=X;Ob{DR9+!B1#_)qdb<=@S($^VzHiEk}WE~h)|Q^xoIx&C_m z`2Bg;2gSGCua>?rd_MU}=OcwjrytIL5PLuVUc%jzcTU_XyqkYt<5BzLGmoD=dHi(S zlln*VAAWv#_aVo__y?EnSKT{%$N$c^J9F+Hx!ZMj*B#5-Q*LtK{B}#{{?*4qFV4Kt z{50YFtUt>cCNO_voy-1>y@tJtjfr(3b12hC2ABVP{z&{%_?h{$_?O^cVTPZKXPDJl z3t6I>lbC-q?O=Suu$V!Z(U?hzS(4=@t26sjb{mc#9B(;xaa41hW0PTd!)VB$^RMo= z$q$dO8ee{Vx&5vBhwV?EUjn~%e)s;W{%QH6^ykGt>;CTi3a&pE?cU0IYlk~vk`^*C+$dUsvCtTx);!kN_$ySNi;%h|Bg?9@n z3%T*#8u^_tt2KUJ_xaGs#1 zu$t&p(Hs$JVRNAqf}e$g#h4|xNxTu?C&3`KSK3FeTHacoOJTO6l#-N^o^p(;wYr!F zw`QwWnD#~OeL5Vve7a(KZhCWdB6ViyF4X>^wnl|l<*DLYg(4*um1vc8H9yTenu?l2 znqSo;RMnNwDV&$hl|3ncSAktoR{5jKQssXNhvhy>TS=S~aTe+on9Og%SHZoSeKqrL zh8h3o{oDA5?N9n2=HG%p>wf(Hw&Ans$B7^QeOUkT`NztS3qPED|LDE=hwbmA-zdB+ zf7+U4q-hOM|t!+0SUVC+U z+T{gTn6G$W`gPIrip2Gz>k`+FUv0Qra;5o7>eZ5~E3a^0R=HSx{_UB&r~J>bo)0-c z(We5>-a2o4@y_|Ov$`9R;CX-ZQ*s;$&XPxRY@+lOoeo20sQ~21y1@hE9e15R^zeZnZl*Qk;QtAiI?%=|H}WT{@eX``d9t0=AX&m@;_aF z{QgM%dGOo$x7IJgA4k3>e_8w~>qGqe&UdwMufL6bSNzuL?a_CvAF4jw{ZRMugpXI+KemVc;#Mg=6S$`${w)=hL_sKsof0X{X{^k02;a?_01>+2+ zpDgp(Gq}=tjrm*o_4zIM#RVSmr}8b}Gvepr{lGPwi<|Q`n-se$hapERM>*$W4r|s& zj1~<3|7?EG`yu+>=Uec%l5gDKCVjj5L+;mvA9CN`eO~e*0y!}Y+Mo%eP;Hh!x3{NPLemrgJG zUhI78_K5e9_~V=>E1vFrI^)^5=P#bAKaF}S@J#R7q~{yo?EUQYz2!UaPoZBS-F8^8qPJ!wCN&Nb}K3ref9oVmMdhjgcZsq>SGm$rkx1MJWcMH!g?mryKoUgeJ zx!-dx;nw3@FHj_`EE*+tSz@|$h0Idvzfx{e%@SwDk4wtQw8~zQOObDt3zyv_`%vMR zYMEAxuC;!t{ulknhO3O6PeqXeVmT)QZz))a}yu zG?=A#UFU~Zj`{}W9g15O)Z{ zpWYwe-wnT+{>1-D`}6nDyT1&7Fa5gmljB#aVu6+9Z@$JX`AMbti`1Il9=Z}$}7kv5ih3o6YFO{FwKh=J$|J3}&;j7&j zsn4fA%DzAQ`s)k5XG5x32H(-s!%pd$;SI$-9GZ7QeQ6)A`ono$h;!4`v@0z2E)5{zKhI?@x@M z-hEj8LGvTe$LxN;*?d|1ar%3!x07Fgf3^IT_-nB@3UoI zHs)>n+x@S7UY5TUeEsot(wovZ%x@;VPJcb~_4e1-Uafd}`Nh-cQqMm=b9jFJ`Ge=3 z&lz8=c(MD%wih8Ul%6kodi!zEqu_@N?^oVUxFdEa=T6Jrx%W)&|GHOmx9s-Bn_4%% zUr)NhdUNzlm(ep_M$dHlGH<8;n?utGTdZhID^rMPLx{qc) zRC#Ff;K==74@w@cesJLdA$ggH2ObnW)Ol?Fl>LRo>*BZR?|!|V@^;$Wk8dpA1io4S zhWqV;x8?7u-Y@yE=~LU+&hIHdQhr?izW@8m?-##K`}Xqdrq3y#wZ0tvc;TJ-yXo)F zeOUN;-sh8_ZNGi`ru1#rx9IQ1KWu&<{>RT`&GMV&9P2VRBX&{Fsod(k_56`Srb4&) zU+^*WJMit~eZsqjC!Om#X8?B$?*smJK^?)_{1UvsIS;TeX8X;0khPpOoh6A$pD~zu zJDVc=Y}VB*Y%CL*=P^kzu46P|_F;O@_?_98MU#0Eb1(}x%QEJFOesuP8Rsx){xAGH z`*-#4-@o_$=KIIT+{bFedXe=o+eTJ5=2%8whLryo{{{WeWBA3ef#IuV(we`iu1;Yb&cg>kgJk7B`lD=HE>D%vQ{Q7&RCR89e_#{P*df+P^D* zCjOrN)AoD+*Vmtqe~kN}`Tp9Q@>i>0L_YI>^5_xs1MWN7H}_uOb5-R^@MXnIi_V*z znRUYK=!rvX557APabW#{9S1cJdmhy|&U7O4M9GO;$61cI9$S7)^|<|U;o}pJ?>h0| zWWlNWQyHfePKBMaIqi5_1fq7HlvcshVm!4eSe5LZ*r5jnduH9C;D|ThJ%)U;DA*bK{r&UoU_2{2uTl_Git{tv~ntO#6}Wjrohf z$6fDy-&()Xcys&Bk~itE#a^+ztb8%y#f=wnFDJcXd&Bznz}uPcUcT#pH{spYcU#}h zeW&m~;e+a@^3Mrh)W50zVEsAiXWlQ9-;@5V`e(~v$#{hEE`!4V-hU4NfBjEoIL5%w zSji~D^n%Hp!B%3IENM?dmzqqtWw16A$W3H-~*Gp7p2Pc{cO4z_8m^(^MhhnaerMOaFi%b9nx)UYP7 zYO$VTnZUA^#g3(eS&{i7lL&Jf%VSm<_Gpe`P8lvKu3*kY4rUH3j+q?aI9fPex$3xt zxb|?CasK95$f3c($X>?!mpO<@ok8}W!e6Vu%l>Np`}Obne|Ltg|NH;y{K@;}@#Flr zzHiUIE&P7(N8_*LKX?DC|GWEFIlkXk9!*J)y?b2I6uD`!3bXELn z!&T{PUf18;5V;w1ZP6w93z6q0o(Vfscy9Iu#f$8h6t70#@W0t{bKmXK`|}>9K4E^k z`suRgJ6^`WlzHC$l3!?+d<~e%<(;>sR$phaa3jSNz)eOY=w1 zXVdrHZzsJ~eB1d}>SNirzdu*}RR4D4+X_`2e|`md$G&i&Z_b^oUuAL2jE`)K=x z|9kzreeEqfi^Q=$PKVAIv`QwK7uiu<` z+5POm6R)Sy&y8N~cysH`^;gqhYQ8%6%Hh@Y7uL_7J)ZLD`J?P7HqU0g`1D%uo#~su z&!QjgxUYQA{jU36_4|fTa$f1Z%lk0xi}FvMU!C8ZJ{N!B`Y`E3>U*B|8K1jf4d8KR(-k{QTDE&BHf2Z#TSAd|m&-{3++-h)0r-U7s<( zE`7)R;qQluAMbrU^=abgq))8xd0yAN*zv;u_2zd|J~4e4{w4EM_sgz#Z(g&!p7-+h zi*K)4KSh3L|K0honyHcP21h%43CnZlrL42rEZFyOZsbiAEEfJQv_?RL?**3~J15&> z4tbt$ya9Z5ypy;)ImvI`ls%u#p8XP6E`Nt`x|oMVl++!Wk8+b0 zJ}6F8G?A~Ay(H(TbX+xCbCNEn0gv8)jmIi;l~@%#Wd&u66q;4*HM6w!bo~rw7-bsr z=w)c9Yn{?MuRUGIQcuT7$!xXR36nhI0wYU<>AG8Vrs=&lJZZehXr_Loj=0ux%{5xm zIz~(OsB5bIQ&V0`R;Nk7)o6yv5i=3XE~~>Qgk0`sc7r!Y8kj1 z-!*w|ywpHSr${|i`IG!nxoE}vs#2OF+Qz!f`bqlxb#1lS)EB8OQ8!SZqqbecTIaUz zQ=NLPUFz#pZYl7}o|WDzYpk$BL0V2(a-pz4{~zug&dD6_IodfI+47kM8J7HI`fK!8 z`>){NCx1%+1pYbqr|Iw0zxIFU|El=5`_q&U>>nHretZ2j z=i9R%YQOIJx$Doqe=itPnRFOM{xSb~_507C=zojF?Kn;(l}eQ2x^J;nUkwZzA9LzUhBs_2%iTke3WE{ypP;?)oD7W#h{=FHgOi z^hW93@^>@dK7M8K{NH1@M=u_-K8|>{>s8d-A8$6l+VDL0$?pe~?sD95xYz#3;OWVy zOP)=9!T5^hW!cljN1Gp|KKc6i%OlyR6J931x&E5zW$4q?hlY0#-F$!J&aF##{T^68 zY`xEX=kbkC*QQ*3ccta3@b#%TuHRU5{p7VB*U#SEep~0R_q|E?TOaO!ocpx++4*OF z&k~=`d&2(YAhz=pFe+k z?$NP_rypH=%=JX>3D2{6uWH{3zuWRE@wxPqrU%ORTwWNB z^|!Jga=(~-@BOj%=k}kQzyJNx^f~*B%#XW&BpFUImN3h)zGi*K(#Tl%ujl_Yro+tV zm^ZQu@f{TWAP~nJ#c9d5h}n&C5@QhCZ5}znt%6ScCfp3{%*?v~r~di-``n)ge?R|K z__ONg!5_9icmDkG)ArZxUkm;u{Lf+3WeQ|k!?^iB=ifuWx_*lP>iF~I{|ctV%*o7A zOdbp;{;>a=_3P)~H;lVkCbL$sHn3%|o3U6Td$FX7+>W$I5SlUlqPQ{j%&^^!I@8 zJAOF+=KAaPkB1?Wk%MvH|Kfidf1muG^E=^h2Lm6o1d9vHTIN5D=l`$%$H{QU{dC%? zjc3v>Y`WBc#pQa{EqfbwA$Bjeb1Z+Dau~fCPX0^(bN*+?ceSq*Kc#$l{EqqE(YO6? zx4yamn&Zu#H|cM?-mZOn{%z;mEpKMNPI~44a@&iwFS1^gKW}?x`i$k7*Hhjn2Oq6? zc>ICfgLC)q+?RZi@nF$|+6Nczf4*0KFZ7<-y|;IJ?iSpgez)xI`8(!!{@uQPyY=?X zTUT$I+^o5I@8;5*2XFG+o_#0mZpdA^yApS!?l#>GygTLYqkAhJs6Q%teDz7|v(6Xs zuO_^`6SHE5NR^pxbd$SK8Kj?gn`1t1I-cJsnJwB&@X8R)bweZ`~@ArNj z`MLF1$M0pom49#iwfh(IZ@J&1zb$?j|6cU_$nVR)=l_2GJLoUZ|NsAgG2CbR!V<&g z#QuT3pF^6HpVNt>h~1D~l>GwRR<^Hfz3hb?N}PI}lAIekZ*YC#KE{*8dxZBH?-E`W z-q}1(JXSnKJaIfTxDRnvag}qKa_!}e;{koY~NWG z*(}+Pvf8p*vxc#LVM$>LWD#M_VmraUhC`fFfO89n6~{F8oovo*GuVEy?PlX=D`(YZ zwPuxN?PU>T;b1w%{GaI^;}-^JhCBb4{rCFc|8MHw^MAbl%>BLNm&mUZKRbRp|9t(! z^~aj;E55J!&hb6x+mvrFzn%Y9_092{@3$@APJiS5CiJ!a%j3_FK5>0I{*mER>8H(~ z_I+~syyQ#rH|Zafe)jyb`TgN{)}IxBRR8+?`}hAC<2R--=AFzPECH;CSe4kC*)Fk( zu^X~KU~6QX&i0P&F`Err2V?*NEqf$BW+BfHD)E?|*jvI`Av#m(S10AJ4yU``-3l=6m%wi*HN5*?e#MKI8k%@2)>4{@DA2 z@8`asyMJx_ZS;rz&xGIZzwLkX{4V|V>gSrDZ9k)auJ|GRJ?CrAmzd8_KJNN({{5VH z9&dNPKKU~HMf{81FVbHueSYg1$1{bex=-vMAAEG-(Yi;UADTRT|G?#8*rVHzKRn5O zy6Wk=r(sVoJ!yaP_Q~_7GoE!lb9*NL?Ap_^r{Yf!Jem9C^OMS_-A|35K7TUl$)CqR zA5D8G`{4P#2X~*`k-O7(JMi|>+xmBs?lj&JxcmLC@O_mBA`g=unLOG5blS7n=d)gX zeEI8D-RnuOJ6`X6&GyFr&9OJk@0Pr0`^f(3)+dH9Z@;?y(EU~WJNnPPKXQL1{$BpW z{8#p0?0*G@Vg_G^$Nx9{ulRrcU-rMf|E&Kz|3Cik*5BoS3V-YW+WaH!`|fYEzdipp z>AUL>#-BRBw*G$hr}ppbzw7=z{cp*b&UBJ_7Hd5Fc8>j=cexUHT=}E~@&)6B;)Q33 zoEF_J<|E!JUM~JkY=fwYh^z2VAzxuNk)t9aqEkef#lDFeis^_?mSC28B6UbANUBy! zO8SkoyzF*4FNIXar;2A4-4vH77$_W(*OjlATOeC46DI8-B`>KZF-zP_{IJ+{(VrrF zMSh7yik=Wv5pxhz7ds^SN5n_utMFFg8etXT9HHrgT!Iw>Q~B@l&EkvX`_FrXcRQ~e zACo|+ke*1ssDoIySc#an*jCXUq6ft8iT@BU6c-WyBKA^@S3F02o%j`T5eX*=6$xF5 z2@?Ayrc1a;w1_u~of9n;6%#!ua!Vvkbe5>P=q=%wf?xPk`4;lHad~hEv43FgW07H= z#MsP`${^0b^k41Yhre_Fa{ul4Bl+jiZ=pZNe_sE-^t<`b#lL?47c-&3 zA&B8P!vw}1j0KEm7>@pD{r}~k%>VfRiVPl%MojaV<}&#+Jz&gbT*Kh z<1epYyuZ4Bs{ge4S@hHN=k6c%KMwww__O-g$6va?Yk$Z8ZvWN%bJ~y7-`l?@exLcR z=4;oN_Ro_(9sl_J1Jj4#_pR?*-}bzj`g-cCl`oII`1(BNIrnqP=ZBvkc(L~7v{zeS zH@wMz^ZoVn*8y+dz1i|M_uc<@+umD$Q26lcef@{!A6-5xeck-+=l8guvwy|?milA< zH|1Z_e`SW*438O#7&Dk=F`s2w#VW}b#TLZ&jP(`k6E-G}!yMt9GdLG>GH^w5sd4dg z&El%%w&%IZ49xvZ9~u1_%Ku6HUH6;$SL%CmVM7)-L9sauJ_3>9NFBiS|_WbQL^sE%g-J@({je~%)is7XQa-2J@xbC z-IHfet~j~yr1D9t6St3_Jf3?z={Wm|MJJY>Xg{&;1k1@yC!J1DIeX>&l#6VarLWAs zGV98jE0?c^U3a-L_eRvs@LRWTIo?jVbN=p`d&}?dcu@Rs-$TwvYL9v!&Umo<{@HsM z?{eIoc*pCG`W=fqTkh1{{eE}nU8}pLcgyaT-M4zs`f$qQB~RU+pMA0RmEl|I4`)Bw ze?9;G_fLc0KYla(mHp@P-=3kDVGF}nMt9~_EFo+*9NnBnTvpu5+^$@rT&&#wJh{Bm zd`*0U{6+kc{8{|3`6~oc1fL6;ifD>Dh-ry;h%XbLDV`xdU))dPpTs7~Ia2qe7s@Ki zhsn#y-<5x;;IH^Y(OkJpg-xwY-BRPD#w4w5oo%}N^;YYzHDEPjF;+0HHQs2FY5Ly8 z&m_-em&s(43KM73Vl!RyhvwHUm@Q*1R$5eAh1&So-n7-Sdu?NFxzCi-?3l$<%axX! ztbSQ1S!Y`Insb>~Sv;~_W1(Z3X;7}^s=8HqhU#|>Dcu8x?@iB|>zVl)PcxD?%G7mH zt(3bfEiHFZ*+cW34y!?-(HsK?O&vK0(Q?6d{pH2^IYN!<$owJMdY*OUD=be z=Vd0#eNyDvQ@NJBtvwo_aI z7Fo;}!7+*X48yGdssC3qu(AARvt--JRQLbYpAA24zRY@E^|<5V?0drSPyFEfdH&bIe@~fPIo5FP z=6uG%&#l56!QIV%l*NEqowwivezAd~)+y>lxcv5+OaeA@mu;#MpGoNSp@%QZSo4+i7JN&8s`}Kc3a~;bH z#-_iVzbk(A{;K`O_v_=2$6vKR?t1&;4bNMacN`xrzC8PK^>ghfi;tQgMBatH?0i!D zc+wO0r#qgpysm%0>ZAULqF2`*wckm+zW&n5^ViSGotM41{_@N#T~~E(#@r3N|M7nA z1K)>|kG-GVe)Rl7(!-8NYaV9bkG|`3XVIO2yRCNx?pr?=cz*Yp_2d2bCGMTL^Y)h2 zEymk3ZYkZ^a5e4n+za*RTP{joVY#~RO2=j2ORF#GUp{f+*_nT*-k;(-{r2?nb8{~L zyit5-!<~X#h1b?xOgQ%lvjcUH?_u+UyZ7y$JV#ef{%A!^?%Q zKfh^yr~7Hox4S=se-;1u^40na|L4h{GC#ln!uc)jTg%r?pQS&)`*P;H*RNl{oBv$- zllU)&;ExuYCTCFkF zHF~YTPxqkq9j$HJ2D%NpJ9V6OYIQE^?lv$oW-|U@c))1CiHg~7vt?$|W+G-M%u>u# zEtIU2?Q@-HyEeJ9xO{Q!wr8?6vEnfoG~H*)ZC+qjVLHQXwZ&@72bM}!cGizXWZ*~_Vdc}uI9SVK9kLn;}91kw=H)s z|5VZ4;s-_hgkJJVb2o4lu$ypj@O%|C6N?v15N_ZP<~hVEz|O`h$hw2=HTydDHEgnM z8El)`0@*y-irD=)*Klv;>kw2DmKV7pQYLap=#zk|K%>A-L0OUeVvLeak`5A+L_LMn z1r`eY6Iv-cPdr!RvV^Bpg|wTbzNogyM6ouBbjiiix8-wG{;M5U{j9i3&O+v;M6%ds zaZ8!23T4V^%B+e~a>u2oO6G|#7rQ4eC{-n`FTGLHUZPJtT>Q4!dr?`jyAoezm=xrd z)~L)?TcaAF#4rC-W`%T-w5F_tLXOf_WnYz@%1ag1)-Fme>VKt{zvmq`%l(y9A77XtNZ@pd)cqm z|4uSmF&+7@`Mc%Yr%#*SbG^OsCjNcsr|8eCKkB@zdFA=s^GW%`()-WvO}lUQp!9zA z-DS5Q-+Fkf@|NpOhMSJJ58b=_nWeMPvWU2l5ca=119*0)HYpyT4>3O%{VZ@`1`-g8c z-1NG3{xaj`y;pADIC1yogEtQt?!UTIbzAq=)*Ea$Y;V50opvwae#E_Rcl7Tz+`D?O z|K9Wa%O72PqWSF1^K&nyU!Q%Y^)leO#xvz-JDyK{W%u^hyQcTY-$lF;ekuGc{K>;7 zI?o+m{&?l~Hvaw9_m|(jd~@ZM_p6xKYHyt18h+&ZZuNWnAJsowe|mh2{+#%6x= zS>HbVdh*xwU)Y~5KV`pf{POx!;iuHk-Cr+#ulq6UyVv(gKQexu`~CLMzJKo-Ygsed zudy3)d}iOwn#^?N|KxwC|A{mHWZA}XhwD7|1D;x5As$XH4sJ>QlS2DNg2jR*G^Hj< zt&sRFsv`PB^nw_##2Km6a=FT>>H!+-RBtOP%5h5-h{=oQisei8$()p(DdQ@2Oq^Nt zlOQj@F|PryC0_=gHSaO*A6$RARJg0SR&us*UFNyUw@83Z_^HS)kzYcu1lagPd3|^; z@jT-DE8rzmCaf*8T*!xiD^DoTG~Q%>Zo!R0S4Aqsev0lB&Jf(hf0yqkUq8Q{ptxwF zG`p5rVFD^vIX|9>X`-tb%H56d6T-)z4s ze{TEv<7d#XX}_oZ?f4(e_>^fgvjwvu89&;7PyH{=tjqeCHf#Tl)%EwdW`irTN^7Y)0zLX8Fn-6VG&|? z<2ui)C!ix>%J+l2oQsR=Cf7k8C4ohvOQmJyr^p|d}NT3 z`6$_aQhOzO#kL4f6lxL46}OeNllm@|Ej?8_MOs>VqVyM;b~zD+Uy2#ZY|3X9805^Q zwI%XJcZxKL@k;)aDwUZayGk}(=9%Pf@dM%o?Bl*Ltgly=EW$)1s3Ed5ei zT-IE{PDMz4ow~Bx0;Soq2gQE~F5(U3uH{naw&p#|C(ftEqruhAZpD(tc;|ogf9?OD z|H}Sm__6uxvCqdpPWzS`kygvVq<73}P z)laKFP5LnB&DB?OZw|g~eYfSk#HYDma=*^~Jo`iHyZE<)Z!f;(`>^lx^dF3Wng84T zTl{(#O*uZ+<-K z@v6r&o)|xS{yg^O;aApgtlsW?Q}gQH^DR$J9v^&g;DPmH@29_??t2#X+~`@xW6uYs z_eAbF-1mGi=VAAgJ{`{L4FSb10 z^JL@GHA03@?~?Sy|Y)**~)vvSl$>F+E{^!s5dEmTfEN zeC{&tT+ZukKUoA>9x=19nsCVT<_paf`z&!(GD&i$c%0~D;b7rIBEsS+lCz~7Wsl1K zlHMaJDd8fvR76U&Mm$AwpJbWjXNk??zeF`eKZur!KayA_3Wwj0!L8Ytm9`d@1 zhg2*yq_jS0hHKQS-d9kU-Yj-Y#7g9ZaE^$WSd-Xnk%NMd`Et2uv43MxV6kLTV~Jp1 z%NX(h+aLDde||dtn(_P9pUZz${y$-eVZ8Z&>)+46nSb5;-u`XRH_so;zbb#-`+4o> zyPr?LmwmDPyy45ruQ^}me+&I7|7*o}tuJmLC%;pEWA}R98@CV2Ul;wH{paRi>AyFA z?)y^sUh1{oi?7cfJzM>}?&Xr#j&J&2J$YXHl>PDM2a*r=JzVXD^;dzUq0a_Tk-!W$*3ZTD(qqS^aF%C=bLD&JCn z9Q+maXVGu9pRc}ge(n8~{~_-~@2A6GWq)4(z2)z{Av05_j~4#Uq9l0PWip( ze<9O3MrMW!|5E<`{C(t4CxZ#wG@b&X`C?p>lO+4ZuL^GwVBq)U+sC&-AWqm-Oj`1m zRFIU4#3xZFkt;$uLQjQR#Ab`F7VQz4Bs@(hMaV{2T|``Tmsq<*x}=5VFYywo-@mAS{rX+$_oTnt46m3R zS?ZY=Fn;?l{eSa6sefnw8vK9ESiro4$%fI9!TSHFzcc>E{AXhR&eq6j!*!5TfTNe? z)Bl=3BEL(2N&E`>o$@b^QJ1-qrQdb3Hh8Zmn_I{lCM`~1({f5}YWSod=HbD40(apbYOFzxs+{%_vjx&O8?7%<;u zt>e(GCY)v|``ER>mRBWx$oemCdcqeUd|sZ3fF6=ABIZOj1k+%wa6om^Uz5{TKZk^?T2+ zi@$gM3ueyd_|7fQyPU_5JA%`K{XVM#+jI5=E;HWQ0+)nuh<+2(6Aux+Cuqj+&8NfX z$rsBvnRhj}IcFD}4NEBVcIHf$sjPe1pK(@lwR8G#sIcd;<}xo}TEIM;^)&l_PAl#j zo~^vsdEtYi`^(N3#xM3gSAS;wr1J5@ z$K_8-p1M94eEH+$@s|@`%z1Y6$%n@wkFPzt`}q2^u9uCka$dW?<$723CiRu=%jy@m zpC5VN`6Bz(lsCL@gI~XWap~F3CsmJEKR)+#^UHH@=e?i#uHenLm+PMWePsK9_rBeI zwFg-bGapMlD|&JArOK;UFGQX#do205_p#Iy{--R@1fL~6UGhZxN&1tTr~98VzIgER zI&tAVUe?9%p+_%%-dB5*`|L|SL+YN7A-^RV|eRJte$vfTm zzuwM&eecEEXaAlSJp1_k?CXUei@q8Di2H8*HRaRaciOL=U+jF&^m5KC`!}!Ns=w#| zaPULMhwJZ*-=@Fmd$Z}S-}@~eq(9|;UjCW!v&rX8U%J1o`!VbH?0=OEZyAgjJpVQQ zuKY3atHbB2Php=GzleT$_~r69mG5j{qdup7&i(xN)9TL;zP|r)_4l7Y3V)n_&;OnD zr}3`^!$+3CTzdpA3f~g87nT=@IQ)S-D z9F#Sadn)%qK2_nLyqSELT(ew+e3e4HqOX#o@*^cz#WMMDxdz#LGS6h$6&+Q4)I2n% zXl>Qz)h^N8tiC|4U9Cs0U(HpcLOV(KrA~?VH_f{m*ERYy8MTk;Eiid%VPGj|zR;xJ zkWKf1dayE|VuONd6Um`I9C){0At?hv{s@QnWtzm%Y$@OP1qqD#eQiJOVv6Hyh;72Yq*F3c@F zStLWuLHwWSPNB2>bNO!avh&LD?H3dfdn)lrB2p|>SXoe+?<{8kn=Gq6YYQtATO|8r z&L7-5ye&M)7{j?BHzS3gXJ)C}n-d zWW{*yzsdhPh6zj)m`zxwv&OS|u|_iQV?4*8!SL^2@84H{Ef~@m1sEj%P5LAI`}t4n zpTR$O{WfN}&J@9D|L^PX)SuN~T|O4Qd;8Y<{nrm?KJEQ_@MqXx$^X0mZT=JcOaEuZ z&)Q$zznA>^_V?SrOaC_fRsWmw?;C?G^DE{b%zv5xGQIkL{dfG2179zGKK5z-C;iXM zKX-oC`~2zC#E*6F7~h1vPJI>nqU*WmOYJwI?_A$8ym5Hd{p#Q=omZT1rhPp1egE(K zf3E(H`xW;y`TLj8tsg5tHh((*`PWy4pKt!`V+dy6&%BYTf$;~!3`TC|Vit4OOxC9? zHq6}&BL6b~y8b)=PygS_znA|y|5g6|;)nB(Ge7KqO8lz(6Zro%10U0W=2fhBS@l@A zv)p9KXWhuUhjk{q6Spld1CI#TLyi`9D>fyz@9b?n3xs})ZWCbDs?* ze^mZ-{XX=|?6=I{`hP$E&iwu8`{mDU{x@8&Q(o1*e*8B4-H+FkUV6W1 zddBxe<8jv0Gp`2h~A6wtAd%fYs*XQ$JEPWaOO6&Fdx1T=F`pWx#_qSbN zpMRPBrR>X-FGs)4`T6a)*WX2dga0c2Q(%l@dBw`duFbiM>n-OWb|=la9t#kGRtKD!aeUG~FldhDw?gLxkCy6}DE&E`uG&=NW=94=v{V5UA_ z>$P^Jj)2Zgtw0S|HA6KS4IQnU+OzaHjNL8%*zB;kbl739Xy0L%V#i=F7FOEm;n{3}%@3g2lX42oHqoS>? zxmhhj#aMZRvagD{@*nxD()JQ7L?eY~3pNQR3RMc}3QF)Z^V;x8@#^z!=DWxLTJWUM zWq3jz@WPx$-z_;`{yL)kC0=CW*OVq-kXpv@%C?8H>akoj-g zpW@%=eqH{R@wb&Jgsp(>2g_V$4#ws`UEgazpZE~|KIPq{x0Bx*zBl~D`t{@2bzhcz zy7M9HeapL+caiVUf6)5G_$lDS$9HevrMy4*zUV{4$B<9{pFBTac|ZGI`CGp?i(fx| zz3$EQw~yYv{=oV9(dU%UI-e(e-t{T+L&H1qcUJE_-qpNSe!c6(&F4YSwV%~J`}lI@ zJIzmdpW8lFeTaV7_j<;2u_rZ;zCWyZX!r2wL&L}6PiH*8@S^%f$#bvgK`+W*#=c^H z)A6qI!}SlMA5z}Gcz^KY;m?s@^}aj(bpN&OXXlUd?|$EOzH)qJ_;%>qg>M_aZ~NK( zOZjKc_pWalU!yd@uWX-jAfecm8et_wt|l zzk|P5{w(=v_Dkk>)*qvPQ4D6x&)NLAZg6*UzvQ~X^@{5ymp6A1&tYCBenEaFzF6Ks zK2?E@f|rFh2rm)-EXd6NnEMNd58F1D{VY|i>}<2y>e$;kIys+kdUO8d2<7bLFlW2Y z;=p>Cbv>&I>v?7drvD7g4AcMF|4(Js;W)&_&t1=H&*s4N<*)3|+Al62b>GXr^>{u1 zRr71dw+G&_yr2B`$E%tbY|rJMIXr#*B{rhJh9Dd;Z(CP8~CyGxVJ)ZxB_esFR?{{5pzqtAB=8c1OjDUwGy45!`^Wu%2g5f;O=e}5?<_8C)$G0;m$|<4 z{}!1d?k2H7yg~G=P^y3#Uk=XKiiZ>|6oM6bRSv4N>xk)_>UZmY*Ur^Cpuwkc zNW)0$rgnzzPrWF^2PRJ~{A~W)ZnAx1^T|fScCF1zn?AcXhYOBnPP3inI|)0#cCK>i za0zi)>n!bb+rjgp6AQyo{nxts zI#pUfG)}1Js@JP8Q)kp%ryZo*p~J7$tY)R;EO%cjO`KgMUQm^vicN&9o~=PRF8zu0|N{`Bjk^U+WDJ{f$@ z{Jiy3!$!UB)UsyhG`?&vu{|B}Y?jMvsIe(q}W9Dzazf=D#`4#w6_=nH8 zS6^hmIDg*rso~SlkHw#Yzq0&X`P=R9x4*mp{`~v-pZS0G|I7?Jj5`>z{y+LB|9{v2 z`wU)8Cd}5%6PZ>q?qRs~-}(RS|GbQUm_k@KusE^`us`SM<4omh;Q7m|&HI;&jq?M0 z3HwgALRMWC7UoHes~G+=2r`MVM6hde&E)dr3}rvZ!p@ZQfAXJWKPP`T`C9Yo@`pzs z3_czClJfoZ_vml&UuS>${%PIEJ0B}Qo&5CY)B8{FKE3^X`Rlsx$v?0Civ4}%m*B6$ zpDjP^zidCz>G>OA@K=;K4LhZ>J6o=$z4`o`_u z)%UYLeEzWSXI{@VkHPi-kAIQ>_y3>#zxKZ@!zTtYrimWG7&|QJYh$nO#;YA=03yyit9Va61E1Gc&3RAk_>K)YnlEqc{2ZF(PB^Ih~{MD z{>t;8H=lO~_b<)`oHIE8bF^?w8vL|uUM*fN8Oul3(*e@y-v{LAxC&%YD@GXL!VQS?>h^STcc-d4YgcyZ)e;M3A4i=SM4 zn)BT8McVV6r;(2}9`3#O?2h{#!8;7-#(eVp@bk^0SKKfEKAZkz)1zGvH$Ieo)cNSmW9jFNulK)|et-8p z&xhjo&F>W7#lK5>xAE=5H+x&&=OuzgPU0{B!oV z|8LLVCBF~-KJ#bVKY4~(3|Ib({(JZP&(F>uHQz11fBJ6qWB<2XUsilc`5OGS>+AaO z{lC8d-v3+T_vv46ex3UD`lr&*%AX~_%zi8X(f(J=_@AYa-GYOOBZu9E?LJF3iyLb! z+X1%yY}V|N96LF;ax?Qk5Sk$RO-xW?i-fiWkGQAUF42!74}@cdW($<^JM!o9-{xN{ z@Km6RKb2RMM}>POry%ETt_I#Ed~5gu_>T+Z3kiu_5&b3ZE+r+MCHYlsiRg8aOyLuP zdj$LiY6R{GSO{Jc>KEH4B__)zw^44soVu)?bfA=ql%eDcF*T83L1{h*?li7;?$10& zcscl%@aFI&a7|#}#Bz~oEu#)Y{=cNZ=6`4Xz3^`V10$0a(@e%?3?2V-{vG?v`7ir_ z1Y?=QR!e6#4)%onlGK0SW&@WlhChwmO4J)QgP^0Up))SqcSDSWu* zzS@1|`zH5=@1MPAcYp4K2M?D$YJIHtWd7rvM^7H^edzG8>0#C5z^6P<&p&Q|eEjj| z$AV8XpGH4Vc-i>s?@N=HFJ4}KCHm^Xi?c7jzqEYa{>Jc~z{j$$Z9g@C%l-cUOZV5c z@0MTLzc74x^jYq+fZvWx< z8|4%ZOFiWv;vXnF5WID^#%Dj-}6zdeW(`-uYnH>K(A8>uk*E%yo`d^g{FzT6@4PQO=Pn01mPZ$deOt8-lCc! z_l10fehG1lN=UqtVwY8sH&c{Q;!&Ed^ho)T$`=&|)l$_TYEhcAwKwQ$8+Qz6{6yl>O}cmi$HS^W;zLpEy2ty_bLI z^490g+gER1slL7VZo*ru*SxP7U*3Mk{zU5GpL@seG2UN%_u-v$_f?;$J)8gR!1KZv zY|rOD5q-Sp(b7jUkC-1e-d}r{_fF|;^E;;Z7$07I{N!oCbI})caw;Rs{ zo<44Ut`{8h+3&NhWar^J&hwM6PC!v`i$Ep+WZrsiPp(~@YdQMa@3Oz)Fz0OGe9oo8 zQ_gM0`IgO|bpy*$Rt1i5u9e)2dD?m9__px1@ka~%70egSkua5*BDPq}S^SUaKH*d$ zTcM9a_QJM87DBT`FG=c1>qrO4e3bbuby&PvbdHFc$aA430s(x5JZrdoITJX4aXImp z@}~i_69h5GdvO$a$VKjB6q1GxjH}i-fELoCDm z|4ILT{$>4V_qXuR$3KaGZ~o^0`RJSL*XqwLpQe5;`TFLo%-7s6=RYs_)bY{%cT z%A*yJ_CIugu;5CkGyDK7Rk`(xV5D zvLDAkk$L*>3FDKOkD?wmKgxOh?+MfMyD#Rwba^T8Qu*cd7eOz6ytH_;_RaCvysztC zZF(90Lg`uBlmAbqKimH7<1>a=dG8WFp8v%0MfPjO*ArhRe%Af$_@(-5`B%3uPd=G_ zO8VsXneQv(kBr|z|I!%}7~C0$Sj3o>nM#@TSUlKfaBSrM z!6z>`MevZo8vY>uH2%kY+^ zqSr-#iq?vCh=u$U{Jz{{!DTzLmVExwSd>vh8B!Wn*SP#?i>#&nG81O(FL9M?DuIc~BAu)4EsV~%F7V)kWG zVg1LF%2LmAkEMtupJh7RR?hES|2dmDGTCj|G+4A5dH(DF|MI`_|J{Ea3~!irvL0ZY z!FrWhhxs|vEXLRWBmXb|KlgvjzmPwFf6n}2@}uyF=g;zAE`Or_cQJV|uVpl6$oT*F zuh*Z_-(A0*{z(1R|GVN3<6n_~!vC)QS@-+LFSB1Ce*XA1@6YDH@&A1Ozx_Y)|L1>g z|Ccd(u^eTsV7{vq ze=h%x{-^va`rG+ut`Zd;Jg3AICq@f9?N$`YZM4%FmNO zPX3tn_b>z^4v ziheBm!TK}um+>FjzubST{%Zcq{j2_G#-FTz*Z#LN)G*BXKlxwC-^yP*z8(0o@JrDb zi!a(=Yrb#&wfFCif9L<&{@w9c>ffusYyTek8}jecKjnXdf42S<`LX`H#E-%s**`n~ zbTjN>y2bRK@%R74zplSye@^i`i5;7jZT4bn=Pw zYw-ICGKn%sa7YzM|CRnPT`FxW$uCwaGDqZ#h?Ll8iHS1X6mF{&si~`*+uac}%sjQ~>PfkRRLvD^-y8Jc;c9p{#-P-Zm)>>0Eo~mXkhbg%#Jy1HQ%%M`C z9IiZ9`L>dmVt_)E{43db855beGD5QZWxmO1%2voENcT$ROD&UjkyVr3B>hrKPO4Bm zPq>%gmnV$tBBv{7H%B>V2zNF2JkF=x8PpvI8&&+K=__xqpYK7N1i z_HNso$!}MDi2j`Q<^1QpA7{N^`*!K8jOSCHO?L}0J%22pEZGmQKZT5h&g$8@2=l&e!Ks3!QYI3S%3I`2mQM7z4yzDPxYTZek}Sp=R?^$fj668`M%_T z{_RQm}az zH&t)^xXyM{?{@ROQx9)FI{PsB!OZ)o?^i#FcyQo8^Mi&5%nugaE4X8M>*mc>w~}tD z+>*F!_2|melII;S*1zC*(f&N`S;Z6OCm)`gJU{uY@tOGZoacSdOJ3-_ocE&bMe?f~ zZyMj7cwhRl47QB^TXFLKcSDuFS2}punxPO!c)|pDMSipsJ_xMulf`1+tT59?N`|nJq0Z zl`3f@VI}rOL|bIB&_qF3p+w=G!V^UL#J-C+irb1!6n!Gqvn8_`qr|^ezqb8Y_&xmV zuTN(_MSfZJjs2(Luk}AWe<*yn`(p6n+}jgxyWcK(lk?`z>!UA^Ki~7r>M6rx=0_Zl zmp{4qG~n6Ur{+(;KXrY+?fHl2+%JE={Q2VMv;LmoI)2`QF3%$y5 z?ZJ(kxBc#l-@SMH-K}T0KHfTfOZ2wjo#wkS_t@_m-uioe+O_(tORnTzesW3tYSxXw zn@6vET?@SW?Q+E>tBY0_$}T*(7=5YY;_(aB7dS5DoL4>HaQ@19%L`nW;;+z}uUWrGf2V<=ai_^? z;|+$V^1pa7(D|oRrYB+~V#a9^YT;$kYW~qA-SD5DvR;6mpn;H4jL}lVz4{C~ zCYr4p(i*!p)@mu})ay>xyR6Hk%cA>Vd#2VMtyZ0%x~6(AdVBPz8eTTk)ZeYSQf0oP zko;QNZn;*4P0I4>x79W&y_0K`JtDJDdYg2#%r)r=QtXmKVtqm{_#OFP@E+xT!Lypz zPvDoJu<#U-y&~zt#{~EBujYNjv!2(AuYfm>r-hrBiF5_Ef6&7{I>c1hsF8{dk-SBJR=fhtXe!u$D{a4mc z-k)246n&rd&FowLSMe_^Kkj@d|0ecj#&g4GTOM0H6o1(I=>HSr7gJu{c^&tr{k7T4 zpl6&bz3+F5ZlAm*e%t02$IXj3Y;H>3T78T0_S`#d_ss7Z-RZy0 ze7Ekd#vO*cwGYxCWjrjo7ksPbI{Wp2YbUPcUA4a%dbi`g_=AP_&F_cY=f1!E-iv#8 z@9n!MbHC@_$2*R<7v5~XvGTghwWzBnt}@;Tywmr9@v;4rM~`P50X$Z~wkG z`o#0;%loXik6%xHJ?WLqt7C6YfB5uy#aHRC)n6pO$^2;gdG^=#-xvNE|7-hK@t5Vd z(T_*ps=i(Sn)kK;tH}4IzmEPhWHMxV%>0$n|G&r|$DaW|WPVxyUHos&Kk@$@|6~5; z{4MVssTRb`p4v` z$pljY(^E!#hWdv6MiWgU&0d-Ln>SdLTU<0P@w9~TF^49XzQq>aI*3!w>GFG3e7O(MJqeuO< zTCWC!)7GT$=()dHUd4)f3F>E~=^ zzsr)%sPeDt_qw0^zUO~?`2Fv%^1n0x8U5qadHMZi>dQk<_dHa& z|Md3P8-6!0-S)o!_VMj!a?kvqh&(QMc;x=F`#ld1J6;`8nFw<}+#eDZu-`{LG<*oQs$=R92W%=ESC+oHG6-%Nci z@M`;u{^!S@>%9E?a@)(LFT$RyKWlvw|48$}`#a4yXWq!WRdM&xgNKigJpKN3`ja`2 z;vaC|FL}`Vc;nOhXI@WVJ?y)8=uXL8=kEN!x#Px}o7?VoJlg#<$kRbcm$0_$!g?!b?QeBm-qk;o zZgAGf$Yh4eLQ@0tiRMn`CFXG!)mDwR<@QhPgB`3L?>ZRTJ+oSG;ci}Ow#)2{`4UTY zn-8{%b~|nF+3MS=+0D1hvtMnu)8?BZ7@QWK>(WTIs5NGgfWj{EPW>==ZZf68}9J<(UmwzA#^4TEMu2L5yMR|E~Xm z|117!{)zcf^JU*Bv(KfUr+(`E^y%}(FScK{ea`x_{j0+Fw4XQsNHQE{Ok&Dp{>rkD z^(;#vvlWvB=im^mu3To#(gU@8F%t zvzXhDb1U0c)@N*+ICt=<^M?!06h0vOPpmL>S8%m) zuH)A$Wus7C|p=lY?4HSq@%-6$X#`S>>9&t>Tg)6Qw0kGrUSrT*H=>oM2gUX8f& z_R^M%ofl_Z;=O$AV$JziXSz=vI}v+)!_mUSY6lq(q#f9Lu>A0cqZ3c8J~{8iw_{yL zuOD_kRCkc+VCjL@{SJHI>!2psV| zR&m_qc=ypChfg2wKJx3x)g$+gEI6uqeD{eTCoi0ya_;qo>6gN<*j|geG4WRSo$`AJ z?x)@Vc{kvW=dHsxTyHkrw!Fvn@bF`&r$tY{KIMNN`+Vl}=`XLnaemM7q4Y!jrz>Ay z{b2ds|9k$gu%DN|U-)|Ui^n(LpIU!z{LT5d=%3R6nWr@=g+7e~r!s0z*m7-gPKMI-)z7RYl>@K!g zLQ`t0)Ktk3@dlAKg5vxtymCAi+&-M@?0TRRvDjX)FXF7>TFbSI>pYh|cL9$9-w}R6 z!9t-lVQFE0p(TQ4LhFTvML2~o3JCG_a>sENv9qvCa{BN%^ZD{U=UvWcEFdeGD<~l3 zDr_LKS@^1;kidO@IYAwvErLJ!9r-Ts3h{>t@`}tBZ+xT1iS`}D5w~DjsvoJ7=Gm$rLH}o?oH{5NKZys-P z*IdNxgz-zm-TFDYrMead4~-@p%NS2I>M^=*BxH0-ze#t2&KsSty5{lHyZE%7yF&=Lj|kUl1`D$rH8~J};=m-^)9Pw}n@j zN0;*s>lNli=4fUM=A%q|8F?5Z7=svBGvqREV&2X&pV^8jopA}ns{d~P*8iFRd-*Tt zAC6z1yq9|u_43v8InO(v|9!^x%2pD%sB;pOvJS6?PQ zk9xxP@bTUMxAxpPexvaAkGsbAX5ERn6>vlQdc?Jks~4|&To<|#aXt20?6now%Wv+w zx%Rs6RlO_oFGpV1x{`nG=gsGLT_1Em=zH+uf%1c}dr5aY@0Q-3bVu@b`OW4VZ*ElI z^173Mcjn#ycl7Tt-T8P&?Vi;Aw+}8o-uG1W*^XybFG62!d2RjX;A_X%;;(PNT=V?q zGnW@fU)jEGd&m1O_-+5&nQuS7x%#Hy?aR04-X478{yP2j?zgocOg~-twE5HXPbWWr z{;d8v?eo_!9bcWlq|eR}_wJp$M0Oq7IcaCn&V-$*I~VPY+NCgC(M79Y)g6_z6+D%fXlQB8R=p^@MB=R!k5aJOU6l-lV%ZDwE7b~hPZ;@`vsx@R zT&=cImQiMvf}IMd!fDZ2yz6-`3rLCV5_-k!&h?aY6_+W`E&droegbSxCb;|1ka&`Puir>-ntbI`8?u&HEbs zKKZ57i=fwj?=HR7eii@h{u8rjxvyq^SpT))yVEzG&zc_?KW_i>`D_2j)i33q?0IVT zM&P5+r;8s}yj%BX?Q5Sm9UpFgU-@U*FM}`4ALf3J|C`FXpLNy${vQ*+?)ZNCcgeqJ z{{sI#{MW{Gkt2@(pK!h?lkjKWIb4A}ih|2Tz6qb_TglnMwO*i0?5Jd%)MN>NvCSfV z!goX&Wv3~LC^Ufju0quUy#l|4-%G~GYb!R$ znMnQ=xh--|f>|y|K~46kxSbe>q@~Oc*}JlzrEf@n5#K0QD`l&)MEjKH0fj(uA<>I6 zo7JXj_$jeU7m6O(-o^aFBJN@zMf!vs zghWLY#TJNf6@M?HEpUXpmFp4zG^y1}l1egCh5|x7vjyKuMo628uID|)d5!B7AHPtq zP_V#!o*GVP&d)p*La#)(id^Sg%$~?n!*-4HA(t6vAgc#sE5lRf?;LY^+IeK@RREw=YPiE z`CoKD$b8!Squ}4F|3!Z{|C;!#=l^&18@v~IQd!o0?|Ap`o#fZAKmLE8_Sx#4#OtfC z&%A&C`N3zk51ZbVeVq1<{ohO0T+UVO%bC9aiTrKBkjD0#-Irzi-#0&&{nBRK#~Q)P z&h+GO=I?p`)Y%L9c=?$)9RBotp7h1|&v~XFEPhO4e~o`>|DN)9*8koAlm7<)R{7J( zz|Ofv$V%KyB#_6Lg^%$OvlK@&=Mpw4hNr)>|IA`~!ZwX<7n920uAh&8moi&%zv27F zeVS?NuPeWHF}!AZ$kNMD^K;9WwO=-W>;1v;bNe^F&vQSfexCQ^)W29p$$$3WUcHrk zt@eJ`7lH3$U*$g3ze#>4{H6WJ)*rE7-oAbLvhMY*k77U9{W1Jy_}TKU;M?+#@4otd zU;0_+jo-8Or#3HMzOs1r_G!qY2@g*_;(y-%cJl}8x5-a;-*voQeqZew`zwtX>JOQ2 zN8eU>u<3E)W6S$@Zce)X`R3mHhn}5!b@sW_eXZ*}S3Is&-kx$l`d;`A%gZ+|MP4hs zb^liXwT_D-=Rcp{c%}6g*WC-Zg|26u_d4x+!TA>7ql1q>+}m^W+wFai9zC7?CoYx-l_@BPefoYq{^*|?cJnWH)Fd8K*NxJ=l#GcRBXXOH8_6IK_C z5SYw%<$uM0SJo@K39HL|9JVW^lPD4EpPk3e)&`R-};Ztmt$|1yqWk>;%ng7Tc1qdr@Y(t zvF6*E-+BzY|2O_V^+WuZ?f)>=*KBG`tv_GAH+c2_P1YCbA8OyYKVSb~^S=Cj+{bSp zJ3oATr}*CJ^MhYyjEceHc*THmUFcmHGmSNUtn_cz~}ezE+u_`mY+m7i7L zcYHtg`!Z7jTQ`&UudYvx?-snz|5EGNj~-kkev`eXX{10O|SZG77Q zocrB_&kk)^(UJjU;cdk z`}j}r?~Gq{zt{e=Vyyq~`0MgF?jH<)jxlcIxW%2vKIQ+`-@E>Gv0mf)$MuNKmw77F zO{O9iRSrfj362cbXckTm4k4aYs@JF3{rmUT>Ye+Wr|&(!-T2$Xw2fiY zpQ(Q=88le>SbqO!{FU_G|CbO`5x0YozEB)z$Y0HGhrhk~Q^u^px}4GG@3r6A|9Ti5 z89x0g{Ql<0{J+bYB{+k*6}jHC{{ENuYx!SmwyV4|1@`bU@~-B;EUGVkO8T<6y^t&K zMIHwc8~Kx}St@H~(uGg(y7IeAJW^s;Z&8`3n4=V|{z!*OuS1JbLqqd|_6q$ZQ#;Fk zb1_2!%}$lSYMXVh8Fd)F(eYIKt29d`SJPc*kLGseU2;zHJJi?=#VnhwvWzU$1QZ@9 zP13qzC}gt0z*+l;x|zmjt@*m=br))%(G1X1*L61VF(}ZkRf?2w5n3YrSn`kjHO1?) zQ^hkx?ur^pE|vlfCQ+|fd*Vi!dx3o`MBaBtvl zocmdf|IhxjmSHXDOTj=9Grk{; zU%&19)cf_=?;OV0%r#8)|MmYrVbEvT{72x>_o zf6n~Q{Ql{q)4LgO!`>TxnDaK^Md~Bt`znw2zdZAS<8#tGuO}OBUcan-wdvNHyYY7< zZ_c`=c5UXhOIL-icwO$gEPQ3^RiT@Tcg62D+?;nY;*7^xh0E)1mfn%P<$bO5>b2`H zZoa*_`$o$(#mlEIp1gYb?#pLq-z2=Mc-VI9$xWSm7oG&a`uTeGtF5Xm=}#8i_q-E& z=k`6j2etPb?!Lbjck{-Lxz|OnExoLK&h^B+~$@;K^V=k>>zK3qC?ea_vghYKD@Jo)l?%45+d z?N1jy(|T6&)bZJ^7gyireRlrp^Xbf6p4ZxMSU!|~X8e}@W7)6fKQ({u{A&5#^pA@n zhrx|$GW%D-Y?<$}SHw#Bj&oSE|KYUdyDQisGDCEh=p#`zF;B6*V*KJ~#N(y3)|+qIFG)PnK1tM~+{~OYN>!jot)<6#ZIlSIvA4G1W^7I`UjfirU$x1?Ddd{-__9 z*Oy))T_?L(ZjQoJ#S8_0xpJA)QW6s8B8dWe{Bwl9NV+S|R7p_YC08%OAtEEpAbMOP zPsUv?UhcK@Z}BZ+r^MJrj0KMJT@o~qG1F|->(*YR)~nbjyHSQ&cB-tsLbsBp;$^ve zayR84$azU06MH1wEK(=IDEmatK{iq1k>Ej|TrL^zFMN^0g`&-(hlQsKP8UiO$ro(m z-p!uH@q_QVc#E`{q^78);4;4be1G_!@y!!BDcH@wk>@LS22UE#Aub1YOP04RIh^)< zj|5}|zwvG1w&I$_J)i%i=mV)0(gu=~M9YQF3Z50z=6B+@<-EfcD|lN%SL&093$GjN zt^bGrG5vq~zn%F!+eg-P=2J{{%-zgUOjj6`7!(+tS=>3QximNnSSI~@^-JUr7t<=v z>wEzMZ}>iONwFm`&td%bSNfOe&;P$CFmK?o72Lu9i|ZSUF2k39iy7vz6mZ?(d&zIX ze}uQ1`yGcZTP^c@#=}fLYS0*> zSLZjw?{)v!*_R5&NG3>c5`V<+&Ed+@!KBGtz;TJ+TjZtaPcb#|6{1|iEBOC&vvbYk z&J_?7W0b5D%i)jZuw!H8I>&!lSXAtf_ydW{5+@~WB@T#riar;v7VZ?kEFY}4S$&>r zkz#|4pyVI1m!j$tCuAPVO_j}%iIKS`tt!BkWG{SEe6OsrLWt}Q@fhKMf>k2- zC6-9HNq>^GmN+AJQ1pSwEn#aRW`U)A+5!?H|Hb^o-U-@r*RXi~H~xL}hyJgde=YvE z{k{Fm_s55C&EIUl@P80|_vQV)Pj5b-`S|(uxyLGZZEqLdJO9M;^{=-IZw|juefI5< z2ag1YTFJP&R(%V#fVU$Jy)nN`-C- ztmP78@n=+L*5v5qn<%UzHdR7FdV*B0xT)w3;Y6X|f}+A!VrOKuR8FYzD~Cwe2~}{P zV?V?e#V*BJ$z{wnheL$z8q?kX`F{<5Kl|nIuadcgU4|opS@O@zAHu(n{}uiJ;eS5E zJVpiPSVrr=#()0&o%1*Pm*Ds0Z~Z@S|Be3l_9xS4(Kl0`?|a7fLibhcTbB>g9}M2v zyvcmk{<7m`|BDUJSG-;4AY0I0wr}G|iJX-(6@kRLSZEs$`z5TB0wf$4Y$7)ZtpY4D8^y!orM?Y-; zUC6-y=iBG(H+s(%o=to4{mqZh(|_0fv;ULzW9pZcAGJS7ybpZO`&ss9^30kav?^1sf%@_tPG_WaB0&t+ft{p00%E37Ykp2v=*=WpY$ zf8RyFwf>yWaGjZ-Y1+TWU##D^e!2DW!u#frSH7P4ss20WN7ZNd4?*uu-fw(=`2+js zn(tkI7X7XM9r=6SpVr@MKmLDi`^56oo~4{ine!8K@!!-RG2fKGp8E3ahcm+@R!ep# zwr$LtnVgu*80-J_|BGXEWEJD^W82J_!mydCh=qq$iERpdHRmTTPYyRG8Wn0d$@lWR;>3<3g;Y=4JL9(Pk;IMmHTG_24nW!EGd7jzec^=_VUtG#m7INO1#_l z`O&9}_mOWNyfl2#^K|PY$tNu@H^1}xIQIkV+sn_FJ+i(3^ltXOB@dT9Gkksct?gUm zSEA3D9wy%wyf*pr&KolyuYINeYW-8U2j6Z_y!r0>x9hv^Bt5Noll6Yy2iA{aA11x` zdFS)y@at`F+dgjiy79Z@_X%Iszo>nw_We;iSwHZvxzJcSjpALJo%s0KT8H{=5uU^Ia7E%`1bQmXU}95{*(P<{dcB6 zlUbN~BKhLEC$P-@d;7x0{t);T_UrpEpFc5oUBA4)%5@WA+y+B3~pQ(ymjarg1XhfYreU$(vKd-eU*>NjiO&3hyJ zZ1sJ^+k0=^zWMszpQq_>Hov!jm+@lWgYKKJuasYAxDs?V;)ea*TMrYStax(f@xRB# zPvf8UJ^%Uo{HG7!*?->o%Jre}P4nCJ@3lVu{ru|tv_F>__c1duocZbZMg8NVkI7#X ze@ih-b9M2oQ z#Ttbc^S$Qn=DWgIz@IKSS!|N5sKPJl-=bXt>$xjAb+|PI_KADTJ1GBFS|o2GHB%%_ zppo|(cRG&;|61V{;uj<~iMK?!Pd?4kj0m+i2W8T2h*wlPyWyUzvQ3zKZ$>m z3}GyOY-!9q|B`;Z`ke5o;FHMb)87*Q9%S0i62do{7`HP%XWGRYz}d|c z!nd49m}4$$1iLub8lFahUQs8RnkAQt=8ANRR)}{>rz#4oMyq(rpBMir zR3h|3@D+cuzerJWH^1-tw(y(y4~akiOg5mcKTNCto%)&m zb?&F6kHv!hwh#z;pNPiOgsQgLh z%ek+d-=}@o{=VlM*Y^$Iqkla7A^mg4FX4Z08D21){p%DY=>6NlB*V3sf3|=;Zw*@j<7|dThJ$~< z|FZsV{ojN2Gy6AYqrbvGY`$*&!u0L*cf(&@f3$yFeARw0{^sGUd9RkdzW7$}+{_MPwn34eBJg% z|NXTW4i9B|Hoc7rDS;L#ZA1gjfemeC|`{kWS zj`yPOZhkcDjpdhh-!^@F`gPZrj?Z!*8eZl-KJu{Tsoh(%FVf$9KF7cN^|I_m@ypQH zz3);#t^d5|rb`cYJRQxJNe&)-znd2d=mM*;rq;g!OW5@ zo0%3fod3U`A@u*gpUz+UKY4x0`|6b#TIA77Z6nXyYx!{XOulV2Ky3_i=&FsL${%_yU>p#l>>}Q_A{Y$`K=pz3&o)0|Qe3tzD zLW{(trEH{2rIIC;q?Bd$%gmDgD|JO?hT?AZex1p>>RRhnt|}~1s8YGCm2O~fe9Bne zc)igzBWt7Y`nPm0Xie5>Ho9ctV{_BygjJCFWRr_VZw&7kJu^9M+HLa9@SnbmL7Abk zVU)gv?rLpborAh_^(N|gt8Z24m3}T6FXO0KrCO{WtuCo{RaIR*NPV$NwBmF5Qwn*? z57d~ng0ydG%Bp9mnyK2UJyfsONLRn1VybXQszO3TGEDN4_!hAc@fyiK8A7%aNzq{82BCGru40Cg8PX4=3dEWOym>6S4sjmk zQst@P5#rv=evf%AV-VwI#??$Z%uAUi*e-Fo^D*#hv)}$d|JSsiVt=w3RM@h4<_c&F zmhgY#;o^G8md>oo!2F+;QJl4ab3b=2*LAiT%!`=VS<2a7b6nugE{p=grzOYZ=-YgI)vPi^0D2negmovv#mQ;qOzsLR^ zU=HJQ<7X8(%Uj4jkCTxjls$+ehU)iI&RZPK z9CtZxaB#7wFnj-h_-Fdx$p3u*_5ZH@6ZU@viymhc=N`6q%z=!Y|G)lYX4=Uv&v#BR zT<{hjEAKX*3p}OVr#Xz+f3x>-UE^IMuugEMKp|fVj|}%eu6CZEytjEuIE&d_+3Yz3 zc$V^5@Z9Cq68s>-C=nvDT(nHEoJWI0p52@4sz8Xu2bpe}OA-%7x`iwSCHcj90=a&1 zdGh)QY!*%w(-GSzw2N;Yj}mVu|1H7Af@%C#yq~#?xu0;caIRq6!aAAlB8Lw5BJNnu zIu`A}{$H28fBE+Ghw^U`zaISD@=f!z!iVW^-Cyg!YQYJJ0DJdbm6hY6QL(zPhY*@de`@f`>W{J_n&k>n7&ha_u-@3Pp$vw8Jz#;|7HGH z%^1(}l6g7f-~aRfdopUUuHm@Fv5{4PiHG6f|Dy~un65A{X7*xw!63^R#(a@gjNOxc zBD*eUF?Rz`9?u-^D2_5FyT6}*|M|b3eIf59-n*Q!tj^y}Nt8@_mb zpZs(8&#>=IpEtf!f1C4u!6)0#ZXfI4?R(As>gY?(SKP1Xy>gP^?76?|w(N~x*W|AsyZ-f7$%7e>-#)l->(te> zD<`k%-mvGm5@8}T=n-duC*^PQvj3m&rF|9qY6;=%L(uk5+2 z^VIl7#|y@nEiaj09)4c_?D3POkJdhz`Y_>n+J__GM7~9S{QCCI8>6=q-|cB^jFRg`QOrvIc$&EyqOajiWq#DUNL`WUe8?1@`?E>!;k;|EcZDrdHA>& za8z?#<`(B?=4a<=VPC~G<-aw9Jc}sDe-0fsN5*}Bm;e3vFZBP0e+&QY`1$ik-5(3) zhaC2tw^{EpOS7zDdC7W@-H>A+YdK@q-yeTIFqE@4v9D#H%l?uhfaf{?BY~~FmhAT! zKK)JkpTly4%Zs0le;ZdS`%8|MJWKgJ_*{78xE#3l@bC&a2}_7f6OiV9&Hji(jkjB{ zP$-(eohyND3X1}39Ge(>E8A_Br!0{i8a(fKBDt(t8UA21@7m`z^3@qNGqlZg_GmL`f6&%7xMz}YmS8%^ z=!mYEMudX@WD`9s3T z&JRo8*}uL2*6pLxw;4Yl{@nJX^+)5+y5ArFUi=sKC;xlS=ZBy2zuf#9@qNROmY+|5 z_5O+ad+G1ezXyL6e--%X^51%~_dn)#{{R!K%6)!wqCBJTaBmCyq zi?}D&4>cbrzT)`E{b~PunRiZa|Gv?GQ}Dv(arXVhJN&nn-r9ec^+Ejo;ya&jG+e8^ zrhj9>&BB|{u6bU5ebMRinkx^l_+D|ka_nmF^<_8q-THX<^*y0G>Nh;D9lbu`PT0c( z56ka`-tM~PbLZh*nLE}uXWmf1sd-E5uF)fx=iaZ*y?pyD=4saRudi;sIrOIdb=#}! zuV=nn^+D|u&ZieX$R~Y-5PqTbsiDXG( z_F?|bI)!T=&r#0FEUy^rnT0t%aW`=bbFi_BF<)X@%~Ha4nN5eyfF*~Kk0FGSk>wD} z7RF6~oPQep6#w1wr~1#2U)Dbsem(q!<=gQe8-54;Rs5^@XWyUs|Ff8km}343{S5s2 z>&wm`QvaSYm@;_(Q~CS<@67)N|0n+|_$U2$`mgL?9RKDsrL*)hmH(gn_upSrh7(L& zEH{|K{VNEvhZ$Eh{${+u{F!Y9rw`YE_Bdva|EmA^m>#l!;VR$?=cs4< z$+nG?i{~%THy%@-2|Nw_f+Bp9A7$KSwWOwtaftpEjh9#|xl??eaHPOG{#Sw;VoxQx zr5{LcmAEO%Aj_i=qZptNA!{OKB`G2ktthV=sJc{XlDxCLucDyRQw2%+Z!!(iiZXKY z(JE^+UA0eZ>{ZQGnW0jzx>nU&*-WlXf?0H`Xu5>3)H%tW5IzqkLY`FoV<0-FfC0L!}n z-G8k9*!}JJTmHx8m&1?T9}T~K89G@$vZ}BIGfFb>GAc0NVG(3K$#m-9#6PS42{QMv zt!Fo2OJVV1UBZ5!qk(fCXCV7NCa(Wp|9>;}vrT4~XOm|>%}~u~%<_?SHES!&bLLkp zZ`uEHd+?VCIP&&bGV%`%VcA)h(lF)mpS84d+59c~{^UN$)vX%-jOT6TV}A6y$a=dmwhO<{S> z;>xy(bq8bB?`7Xwzg_vc`_KMA4}b3c{_5x5zsvqlW3XZhXX^cL_1oY_(a+ug_A^al zWdB?8v;L>=AM<~!|ET}W`we{D3UM0W2^Sb)2%}3R*Ro^v!RU{r>QK_n+#2 z4;hk}ZZOXK@AlX6PstyhKNUZtzTErJ^(p_`h3~t+m3%4r*!N!Mebu{!ce~ynd$01Q z;aT*fmybkVc)Trm7x~)vnb70f$9YdKJ}P=(et+jZq5HWHK0oYxtoBsz>4isM@2|Zl zey{h=jGOvb|6Y*3&~nMQaoTZ?b2-u`=Q!yT9Vxet##`ts=SL&b;BA4)ypf2#gC_u-Al z_AeFRrF=a4>Bpx9U;cl;`^)xU0&_ci7ROq)tIR8zw{Y0-z2lp~?Zqz2+Ri?S+nGm$ z`!n}K-eA5azC`{uAwCH=8BG~GDN88^nftO?a``fwCB>z@WberrEACagt8_@oRHZ^~ zvxbEBJe{xF4jQgXZu0!fvo*Rj&D7>8-jM55*sq+eoTiwr*r=E%FDlz0<1Y7Hu~x-d zSxbRM-b|rWQB3iY>~{%Uv0GvR67MATNW2rz5dST+;Y5kcxUq@a|d&~@qFan&9{T+BYP^-jsIy(itG$r%3LNKDQvUYgSb|6P3Bz4 znZqf=?#nWn`7!HePF5Z#?oJL#wocX*w)JdhSfm;M{$2I=u=pR2yD z`ug=-{?Cfv%74E6I{PE?d))VgAM=0y`+4en?&rTBazEetF8izZ=l^dHKcD=>{iX0L z%lAV+cmMwItM!NQcfKEof64rv|M%1HD?b)}d-`qW_s?G?J}r7T>+O?wb|2?|cKo{g z>x8fCzlwji_%-S8)PG!mO@3?rF8TYAVL9^xmI&q^hLism{lCe`$TETT3oAG4EapC@ z80Lj+I$Xir+FTnsv^WlN+~mB(Y0jR>+{5U~#K987R>V=lq0PRZ{W;eSzBhumh2{#* z<`3iB%J)_vTll7Mq2P4hYg`sw%ejKM^>|iu@8USgI*qlO{Ss#-&lbLNzE9j|I2|}m zIqf)3vzYxi`z`hR#GeCym;GJ*=l<``KiB{M{P+03)c+U1oqjz0D*9Fa+uQHeKhnRK zd|mzd{pS_m+6mt-t>K9P!!q^SMtEA1=QxerfT>;^Uz&+rQ2D{^7g) z&!xYde)s);`@8mc@Gs||%YKIa^<{2g|IY5twv%NZiwoN|4kqr!+{s)C9D3}N*ef{~ z@bC%r3hD^-@JaA13b698;a~!Jn#AECvgvF z+~4wm`|)1J_~miq^L;Nuo*O)6dAi`m+;<(HCx5;5 zRrK5LZ(-kGe)s#?{QJS5*gpcl(|#TNHQ~4F@AMx{Uj@G|{r3BZ!*7;9L4UaaPi0DC zc4C%dt!3}wVB)yV8ph(tR>V1vvzbkgxr`}2IG%Ex;A-Hl z;XfweE_6E(3$ctu)>58R^JQsW+U?nUn zwnQ{f=nCHzo+LgIp%UR_p+2Dn!tBC2LjQ$kiR6pTm$)l=Q&LrGqtr>sPh#7Jy7)|a z=5U|ne#x_+uRy>=C`mX{s7)Y1piMxEUz5j~V>0UlHYqMEE+uv=ma|NMnF?8wSoK(o zSpTuMvf8ljW((jH<=MpNC-6)lK`>CzQlOSkhKGeSgl!MYW#$*mHmqma?y-wJV>jySoFGGTS?jb`F2GJuE@Y;*1^t4*qWZ zdF3bjADh3@f0O=X|7!pK`|GN2IX|xd{PUCJ=Yk(QexCYu`{(s0t^@qey=TK_T`6qwhs_OtI~ z*JNMM{*L1n=U=XV?ipO?Ior4m_~iMm_xJr|T zq;e&ui1UfB5O$W&6jE?+(0u^0x79`WuzkL9c3G3BSJhO7j)ptHUo# zUi^7J>(z~S8Xr48u)JIUYX0+WPxd~DxZ8er!2_`;ZqEvzsXu-HIPvl8#|}@ko<4li z_N@Qq-B;INg}&y0lki684d3gzFI8TidwKm;*qaCMQa(QU=>Orx+srqM-*SDN{#oOT z+Lxc7AAQpMaQ8Le3-9MTFO}acdiVXE$h!~kxIVu6DE~?S^Vu(o-@bkm`TpYD-)|=0 z7kqR1%Jb#LC&`Z&-nV_I{?zkD`J3>!pP!jOzIx~Ue$U54pWVMq`m*WE+Rv9hD8Kpk zoZ zPTB3Vw(%t-fy!Tav6GhdU9Ki6Z9X!bg` zc(yFoD@?u&C;oddwlD{?TCiEMwX%k>gfpiwuVwLO`^z?!Er3mjy@A7(^EXEty9%oo zOBkyYJ3HrNE(ac0o-N#c+$*_-d7ODC^C|Hc^VuoqGjuEdL39 zUH&V)F5HjVomdN4Ua-Wo%Cl;-#;_Z6FXX+%!^dU8p2&KL#hi5(+f|O!T-@AeIV(6e zu!pjLU^~xh#8S!Zz;d6pf!&?Mmff878gm}=HfA+eclJgO9ggR0UaXodiY!7b`y{HnZ(uv14@nxBSo3-{ODP{$2XNn8A(V)BlHPN-OMvtoLD@WW0@8(J!ckSk!Cvg|MkD3|K$vi7(^M~|2y~Z{{MxHXP9@eMzJNc z?qKd@>So%_T*i8uO_`mEeLA}}=Qpm~-0!&qx!-aIa-3pc%+bdg%4x!Jm+dU;IaYo4 zO&pAzK^)2K_u2S3q_|J;cJn>v3lcaZSSzF{{7;x)L__$3;BtZE0-Zwlh4%^R3&`^o z@J!(H=QQPP;B@Bv&c2WJ2lI7iUzRv#DaJ4V9{&ye_x=BL#uJPg48{Lu{<-kW?Ptyp z<{vTN`@h+IOaHd-+wyPfUtfHj|Bm z)%g38?~A_)e|_`0=ktrt-@f>Llljj5J^I_Oudlx{f4}hE`TNSRR$p4a-2JBUQ~qb# z_jO;HzjS_D_{sOn;jhZyu6%X-n)3DPx8*--fA;)5^>gX3)IT!+d71i|KQm2be9Tb7 z@Z!G-LmcB(Mk~g(3@;cWnQpVhvpKRJW%|OP#^Au9!N|j;%hbxq$I$a{^1pxoA28T6 z9QtSVcg`RGzxDtA{G0#p=HKkUxBgE0SMsmxZ^WOrUwS{5e7pP2|3~r9CqE{CU*KLTi^J+O@G_*=J2bk7tfxBKIeb=>E)Ievz{_M5_)j;LExh~ zk2XBo@p$SJy(i(1H$Iy4u>bztI}>l(-I#lm`Hu75cXuY={&~~<=H;7Sw;AsS->bU! z@~+;!fA=>%GJP8OtorGW$FCm!c^v<&{Ds`h^Dj=m(0aN0WzVZ8uXW#kee3>i#=GeE z)*qZcu)pVg%kx_9mHX@BcmF@ieewLV@$W{QvmjgV~3Z@1MN?@jmB$;kzksH@`jmZr=Ol?|D94_&D`T{P&2TOurueeD?Fq zuSb98{-4WO$aINm4byi0@oYv67CqTaIPy{i@B1yvbhd&o@HlYUBEP# z$(XfOG#Uo`TF-LT}aF?)*sH(V~!~^jvv070fF*$KD z@y}vQ#H+;@iJFP9idKtXmHZ_sCf*>tQP5HFhX9}8OTm2Mc+o#%lf(~;e-W=2w-Hko z4HPvImy`;Xc`Z{V<0cabe^|~;c7t@d^jhg2 z>7!B+lEUIiB7Q>q1YZcbie`(y5bqXq7kMP8FQ6;XFK8`vK!BTXC$}D#7^fRYH~S2> za@GwjuUQ_jhOuR_&R~Ac$jf+}VHSfZL(~67|1AFo{WN|)UGy*dKhOW#zxlss{QC0S{9o4pi2oA*-TzxX0zeGmGmx+e7AGjLeJ| z7~U|jGo~`0XI#nnk>St(zyH4e&HbbPE9pn?kK;dGezpF5{9XLphcA~u-}pH5{l&Ky zZ*IK`c{TBs`0MW13a>3+_CA~Qi3(l zcl+L|ztMj^cX3jw^!drykmQ}?oIvcs@G@UbiONpum3*eo%uVj_wzpJ zeT@1b`R>YVme>8S_r4K%=k@;f`}X%y??pfS_;Bdsnoo+K-+wy(>HR13&)J_1Kc{~( z|7iB%%lo7cIv?MBeEae1hnV+I-!6IU{4VX?!MCDs9=_cB^80J`w_2|gpPN6~`bg~& z$D{T~3Xl08TRyt`VEKK<`&IY0-JN@<tpffv@g%UJpN+vW!dLjpUu9oe+l}$>XYH;y3|YX(2@+f1%HU?7~7~1`_2GuO*I4UX^?;xl8J()FsIbi7YWO(R5K) zu~%X-VxNUS2|5Vv6e$;v5nm|kE}ANmBXmnJMJPvjs&Iy2rU08zig1ZYyU2N=-GVLx z2YL7NUf};CxK3D5m{aJzkbv-gp*oQyvAN=>#Se*Zl&qGSB$qBPDJLcOP{BwkSn04b zgKCS4jnYDeH;SRkiKbf#PqZ;%jR>rug~-(Ht!FM^l9b@?)oJ8Ctq*@ zo973OHyggs=St!^^ljVEg(6L?lWxdgm-$o4JLPZnE7v!@-;zK4e^JlisbDUV@U{HO z;%7$hCox>%Y2#YYR{!_b%l-Gv9;LiF^V8z@vNu~_-C|lQ8Ond>dBwT(yP;nkzrOfb z^x@OP+jl2@asRdb;hvlOUnzWl^s}};l zdYA(KP5nOW%d9^IJYK>ZxzZR;{Py^K@U7WT0fwYEZPzB;aD1l!Ve*f@A1p5e?tZ!} zaI5?Jok!>27yn^kfApL6`I@H@A9wtm@niWbu7?({lfN>)yYeLC8RL_PYoeDmo{Rre z{lDuK)Aa|J8E+kXp#EmopXVIeEDdk9Z-w3CdT0D@`Q3oK`rkO1AN=Y5Tk&JbGmmGj zAN$__diDFwn=k5&>i+{iANi*CC;I#AUvK|~e6{;n^WEfE%D+mM-+#M5<@}NpS|eG@ zX7Rm)sgpmKVaLk_pOy<5DK-gN{w#kU^ql+a)xS5sS-+nDvhjn)&wH#~yxab=zMt{; zGPeSYDeD@6YrOevtC$zER*7ttD(8O2&MTP9|B<(h>-nFie?eTASj(BS1aC_05Nze# z$7aK_{Ga*%KV0o%%SEoSU16BZWy90@JL<#d@4>8G9CQDve!uxUgLTP2ljmH|_cF>d zUVD1^j@JD(4~$>=y;Xkm>3hPjzfa#>{d(Qyq4cvgkGk%>y2*3r_5`T9$`lZPm z!}Ef{kmZ3$sU%oJ7x5U0QXZv$8~-S9C~$85pUL)5-~)@m&-Z`i{y$@m<#yz9;?v{z z`)~4>mA#rNk}Xzf5r@;?^Gp}nquCgkG8ju(8UO$Iwu0drk2K#G?ih|f<~l|;_SpiO zd?8G4|Nmr(VOQt;$y+I?$1BUVkXMGgi8o&Ey22)rZ$gz~i)G&`2gt5de4;BN|CrBH zYP{wDHvNm-SF*HQ8xyW0Yku#gIjFzx-;ctD>8v zAE{iDKP+k>;LFD+utK0u#8fs|(uKcV7P~o`GIPFK>_nF_c-tYXz%`-#LhIPjGpf7ri+w_OfzOQGT&Dj3Q z@xzQ?Q~pT&lVHkEfb z!!nizzS(>{T+O_RqWV&&rKgCU=HcS~D%q=gU*(&G1Wzyf7v2Lhk?P%wy+U$aiab;J zm-Fo4Naubf=qGkUD2Ba^!Gqa=Z7!4IuUlUdei||!V`*Zn|8Dhl9fJ*X)%QhTc>f(` zv0Y(J|0n-h>c#x0_HU1T-1H&lligSEpL70d{#f`<;H}HM zv+v_ROn%w*BKX^fzuMnzK6!kZ`D6K?Z@*7|wfG?Oe)Y#$-~Rp1{R=t{*!cI2Unak% z|G4&T#;;e5x0zEI*8Y3)&-QQZe<98tyv}UJ|IYpGV7SK&y5>lY_3uBCUm|}57&kD? z`#XunL1>xKJJ#HP_x@b@;qaq|@ges=zTNzB{E2M){;dD6#pcZ>#gg}b+pkZ5otcyV zXMdjm^4)8*A9YN!?C&^=*=!i9e+&GW`^EPsFNeE;C-)xKO-!5r2!3b$F^lm8*LpU` zzmtBS{H6Y*=2yg@v|oRJ$^6RyyzHaJ53ZjU?@XUqJhgwj=7Z`>&3o5w+T1>Scg+Kx zXJv0W-}pUzf5-B!=e70c@1JEmYjtJi-Mcqj&WfKXIC1xM?y2Gfefz7={kVShqR@$w z18;Wa?)`jZ&heY4K3@89DgM;H<3*?BPi7z9a3KAJ`^7(JYfr_UWjeumDE-9KGY)4O z&IO*$IkV{8=aWij9UokMGU2-6C7X*TrxqOAzi;v3Md#A41YcitC+6Xgr~956-JN@W z=gDp7k6vGPW%=2L3+dN(Ts?oK?B@AfV%PTEdiONyf&CS(TQ6U{{Mzte@VD(p>(7tA z=6<;K#`^=)pK^{H9HK08j5*({-nhO#{4VtCdxle-7x}%VTom6(Jmm~w4d5vi{VCI~ z5F{rovtH(o^hBxslD49rf**x#B=$?*6+bMLF3c;_DCa1pC7mSgC!#8_OZbeEI~!#nKDP!3RP^ym+|c7Eatv1@I_Q!Sea)fmkDSaI(~M zp$Kke(X&zyMURWz=T~E0$SlUWl>eJ}t(3Y1vv{T8TAmq#CgS^~{>n|4Stq6=;w|JO zUZONj`ILf|)+dwcM!6cDik^zy${$tw)k}3J8a~#Ut3Frfy5VF)X46zNeZ%jDVP*%6 z^tHLv7O1|^Jfio+DBJXvnYr~Q8*8)cx|(X`3XkMV6s1(twAN`oQL|N9r?yMSM02M6 zJ2_XGJtEB#Gi4Yhr%M~jnaTtx993E_yGp`X*jr$Qh`NNCs0ZH@j$fP{yz_ZXIrp>G zac>k_E?O?7F1?pOm!p>}k*l1uiQ_n{7}tG~0GYqiD}}zWGq6^(?qO>G8~JO=KW|P> z{w|KI|3Ca;`kD7@KWhpT@8_Z~kw2T6>wZXo z*L=V9`Q68>AMbmc|Ml_vyjRa(&w2m&t?@Je7t7yAy)=H5_O$A?=J$mE{XeolZg{8j zn)@C1NA9y__wffprjL_W-Tr}yT-8_5q&-_n0c{!aKa@y~-l>F#~DvfK6~_%``w98 zmp=V?z2UL#{owmD4=Nw@Jq>xW@?Ewksp-+g=K{j%_x)g#}R zvp)8|6@97tcK6419~<7pTDNj$iG_tIUJyJ`31pDI4*dwS@}*+)VT zq#n9GaJkp;$m`kXXVczU|M>W0>(}g0;_o{@e*T*M<=f}$-#7eF_;vb!!M|@`ZhhGC zx%8Xtuatk=|EB)l^f&bX!`}`+&U~}{q5ZFm@$=txzyJOH&Je}S!gS^D3x1yX zx07MQ|Dz0xe(ifd``yy_EU(*N7`{k)dEsr|o5hdU-+6jt+jZ}oo;O!qlf1-u`oYnF z6CW?$ylwJe@1yfiBpyt<{_}FcwcU3%Jyf_CckR?=&1=b5rOq8WseL~2D(|)3SKePT zx_tbG{{80<-5)Hub^Ti7O~<>HcOCAE+<*LN;>$Vjx4k|6%(7{O!5-8E@ae%l#_&bMe2otjC!z{E7VM&nCc~ z%JqTu9fJ+iG4?+8jqH{DCxxB}bPMqd%;gOi<`7KgIU+t!ij#W-=RUEw(h1Vv!~=yz z#FC^UBz_8K^B>^V6f_e~7pax}Eww;ohd`q6ZqYQUG_~h?<+{BZcJkjuc8Vm5Efsnv z@?NSzI$WkvrcLaszmjcr|2DqMJZ9YUxG(Y;@l4{J#-`5F!xYM>&rr%RpXn2e z6We~aTDEMq7i=qj~GLk3s_iKlUYibKQljK`NCq$`h``7?GNi>)-5bXtaTjX zJfXbJJnGyE+$(tt1X2W!^C|G{;GN8KjXRr1l8;HCQ1G|VS`i0Pf6*2(LvasL8R2|k zc2PMoKe1aP2|||y`uLrAUAeWnR&mT=D`m-Lie)NbE#P>~F2_2HNrLe)!)8V)raHzN zhUEXp{xSbw^nVLO1=A(w-^^9aElj@{H2$CejV}UUd_Pxx zD*9yhx#jbpPYR!Ae(e3!_4VkF-#>YO27Pz@CiFf3XWsA7KR5rJ{B!lU-0#)DxBq$d z$M4Ub-^+go{g(bM{QK4~$6t;=`G3@ZkN7d`r_Rsy-}Zmr{gLIP_z8{l6Jb(A- z?c;anKTi8%_I1iPSFQ2)69qu$5E?;pOadLQvo^E3CConN@V>3z@qKJWYO z@9(~~ekuMq^BwzJ=eH*B!rpbfm49>S74PfkZ@#{bdh7g#@3rKs)vqqUx&LnN`+e^w zzd80Q`E|s*o{y5BCwpSfe6aZR{gcFJhR+{AMSp(sS@-k54{qTl-0 z?tPi_?Db>D$0d&+KH2$9|Ap+!s+WE*8(((5+Wad1#gQi*kCY#BJ(~2G>&czRT2FR7 ziFx|^+1(dgUnaeL_~P-4f>(_1_I`}`ocihS`vY(D-paj~`*{8%`^S0jBi}W?O?=z= zF5yG>#|Iw+KP~&b?d!ttLO-g%@qbDA6#hx-%aU&_KNfti{?_re{A=_#`|t7JEx+e{ zxA}4Jmmfna+ZN7UoK_sO*cP+CWxdRHlud-Skm>3Fo&UHP6qygPzGhQl?_`(aoXtIl zH;Zo)A3xtl9yuOiz7)X*;R@juf?E7_yxhDwJf&O{*w3;2WV*w&gT;b<3Wq<30J}MB zCbJ0hRu)Y*Ue-N~+5Z^+e*4SCkjhxk_>JKrgEG@1mI-WD?B(p*?2A}+SZ=Zyup4li za4ujAWwvDMWL6DA>$bz;mCciC%PkB#RJ zmj%yZehFbWkx#-igwF}D7C9rjR_wBvpqQuV8PNjqa}vgqbrLFKib4nZ!uV7LWQ78R zuL_5Yh>6yU8jCuLToMWs{LOF8|DK;;C`@Fk=mJr0(U&6DVk;&5q~xVqB>2VjMdphf z5nCYPC%I8#mAIwE3aQUBFJ%SgrpmsTej<5QqENC&dadkt+3zyBGSg*PWn*PoWj$qN zWfsd+%C^Z(kl!rdFSl2QQCePVl~j%NCMhL}$08*{mO>we1;zNp9mNDiSBM6PPZ0ki zdO(;39c91rM#DUm-C$D zy2TmI{e$-sUqA0A?sBf>Tns$Eyz+bp`Ofk07Q89^NJLt+Lexc6MVLb%obN4Pt>97- z7BP2GUXhPNX9VX9aPc4Fy~OLlm&$9(lfuKudx~3@!+?3-{~7;f7`++F|0e$4`0MAd z%-E&jRwNAwS=A7{V+`@Z8x^-tlS8Q)qyIemEYVd`h=ZwtQt`10%1)DM1dZC*LP zV0te9%=2mPlPymypL@M}_-gHoOHad|q&|OEw5wV6u&Ka zH~0Olj|;yr{owf}^i%7b?3Zbuk9{uw^8L%9FG^oNeq#Li>HUchPd_?*bb7zx?bf$* z-)nz5`|19Nf_J`er@wvo_Sc*4*OIRVUgy7Jcy;zw_Zz-<@7~3}U-mxh!>x~cpL;$p z`n3N8^Lw9ni{EW{-~1uq!>@N!-u!&o|6CW9d6Yd?m-}^w|(XGdxPYa*@e%A1e=jpjeZV#T_`+9%d zqrFe&KH2w3^MTX7uXp#~%fIh`zx3XcySwjxy*J~5_QMjd`?9)I4sJa4(Xcqa2j z3or@1=AF&6n|H5(zlgo~42d=g4vBT*tP*{aZ=_RYkIQgL$4VWRc9xqZuO-(m^+rrV z^qh#Zh=g#FP_fWw!M_5l1#$$h3HgaIh@KMJF47^|FZM+&R4hW|zu+9flfsw8UP^dM zN=gWeg^D~D{wlIdY`wUs_$kq9(cNO%5_2Rbi|rDgBG@P}OW=i|yvQaoU5Q%p$D&(A zKa2eo_mJ2kQ7+jp#V_L^Yb~oRV=DDoe3_WEc&X%bncs3NW!0tX#ZQT`h`Wh%iTjA9 zi+vZrE7>i5TP9y-o}_}<5n(0aB#}#Ewf~_KdM4d!z1+xXN3%(J$DWoWLUqDjezCe*spGd8ErKG1snTVCZ zVO~bQ7XBCfANk(#M)FGY2JlAl%JQz}ea9yta9!|^h@Qj|Nd`$(u`uDALMucV#f>DI z#ixiyiS&uQ6|obk5sDHJ;uq$>$p2N)T`W_|T>8I+zSu&MQzFKqPlde&llb%bGI@9K zXz+IP`3NWo3J6@{+ra-=@VHR4;AOr--ZnmE!C>K^!U@8CLQ91v37d-)h};udC!#LA zT5yh_tnfim0SQxyLa}oqQ$;F7Tg4WMm5Htsz9#sH--T}*uN2>9zT12*yt3TNTx?uY zoQK%1FsCpvvg~2M&h?plI=38GF}n(jGNb(BIGQorJVNBs5wm-AQo z_og3?-*vt{`MmGLf_MJ!j=xiXulC;go%)-mm%h&fpQ%1)eyRM*>D9zn;jj7MM84s8 z^XpaV%kUR@FaEvsc_a8P?H%Xa8!rW(sXeKABJuRwlPOQko;-Yf;c@1Z?5CX1Ha=~7 zvix!W6OCsto_&5A{Y3S#&ZE+Y?2q<8=6bsM>B?u~FaE#OeUtq5?VC5R-@np++5SA` zh34yHZ{*)tzq57WE&POtVp2VI>O`trvcr}v^CUVPm1MfaQ1SF=yQ-kH5seEaq7+V=sU z#J*ntHuKxkFPlHfeX9M`^6AsZjF0)BG`>yxCH-geFY_O+-`;+0|8DW~`OkH~Qhwk2 zdG=f7*Y96{e%<;t>f5XD<-eBxJ@7yO|K&dpKdrvSe7XO5!k5Oc6TWTy9`-%*%f%17 z-lu-}`#$E~__i5p$+n*kNYWfuTant+E_e~!(K5qYT z<$d&fix1+Tia)RW{NR)QM~(NwZ);vRygvW-`v=ue=RRb=FMeMb1J~_T`e1`nX`DXE*;cpZCFLX=TMp#$Ch37HXI-XqqWrESdQX)3O%7Pd9ta-ok zY~-EGcbxyc;0%$8;yh9prA#F`#XbnN3mzBZ7VDN=ES)V~FIg=fE_PeAQ}m=ryzoUK zNzuC!)1)jVUBwOwJ><9KKP8|nTrTP$zD@kG*k#d=B2pr=g?9=+65b^IQMg64TYROs zmFROpNB*b0`FuMCmJ3ISofg*0K2N%bE4iB!K+~;`?@?PY7!*4F| zj&B*y7OoP`C{9!EFTC>n7JR)tSGc%1o!QT@O0(v(7O~xD-_5y~yO_t5>nLjhBgg-S ze@6f77&w?tGgq;iv#GF6V0+50%Xyu1C08&{Io~mXc|yrTi}+J{ZgV+v-{E29Hx;}j zv`l!DFstxVL1Tef{#$%2`EKyH2xW`5i1SN?h~*0B3f>Z61MNW-x+BCdtRcKps8rBO zU^agp9~aLlP9Cm>Jfi%${I_^3xnFUdWShzQjb#qYN|r8`cg!=GS1{W#>oA>W@cbY5 zZ^^$y|KBoXG4?YY_{Z`0`S1AO_P_uC^8aQ2^U!zmZ)snnzHa%l^V9SX8t-5)GUoU-K|4R5(;A`=>4euJ?uXu0t zKH`1thua^wd|L7;;-k`g@waPUZ+g}I%JlW0*QegRetY-b_V;`rSAX>U@aOH;H=1uR zy^H+t|AXvD#*aHcoc+N6asCIV4~idaJ|%yS`?CJ)(r@wKHhj_il2vy*WuM(YO1#s0eeI?2>kV%|zPI{h`ZeUc z{`aJ>7N1vs{PW@Dhsz%xe0=`p%#WqNLVj-iHuKAx&zC>je_8pZ`|I*=U%&BxtNh~h zS>yA>&(l6NdqVEFV8oaiDk@>9s zS>*GA=WCzMfBN~!%O~5O+<0vMc+caBPmVk(ezN273wD=RAM-T;k=Cmt8MKUNOG8`}WqmJ?~e4komanWA5j?uM*#yzUqBF z@zv#3$X>-|r|UkZO1{+<3e^M5Nt3gZ!`erA29KmQ;8yYa8?|0;&p zj4aGoncp#MGIKN8F)A`{U@T(V#z}v3_5OVM!|~7T|3!vM=2}*E*1t^VjMEs*7!8>oF?q4fVSB{R!tTO4mAQ%W z)c=qFqZt=5HL--Sr*r0V-eiwp-OKczL5d-l!IvqNHI^fktAlG2=M#=jj%V!Z?04DJ zI3l=R`A+aP@E+st;>zVR;Wp>l#LFVkE_6`XRaihsSg=W;PvEgYmLR*ZnAisiUa8fR zD)znyqwAsZ!ZWr9;I^WwP>PB_pK{ zMSsPqirW;AD*jbmr&z5JD9DnDP2T~1n#O@6Jsu6%>6xAZ1SVaYiXNfK8jrb;f5 z`X;?V##<&snoDYhgoeZvi2})Hsa|OYnE>exl5fRx#rQCEtmn7wwgtP$?Cu2-`+oS z|K9nZ%GAnonDr6sJeEC-pZ~J_e)^O1*P>r(zZ3p^`+N0&JwxCB`TsWltNDMO;VDx* zYc=~cjujmL*l(~IvIVnkW(#1?<53kelb2Lo-nRk92eO6*?+U$V;ACV=e)o%kDZx)KARnD zDswy2U8bqbP0UtIOpM1FW;5*jzx3btzX$$q`K$H!{BMn45Bq-EAGW`r_^$8mhd1lrv$^roX=S+VYLeTb;Mjub;lS|NPkt>(}?*%70k!k^58q$LbGJ?|t8uyyboy z_15xT`1|=EzJ9#*iR-i3r@{}v-o1FY>wVP+;g1(TwtQ0k6!5|4UE14%w_D$OysLRH z_)+82{g3b7|9m6)D&xh)7aFfs-?@Eo{rLN1@u#?tYu*XG$$k~~GUdg^=TR?2Ud?=+ z`Fh>Uy601#3OwnvK>-x{8 z->m)?{4e^=_jBtX4Q40y*Bqvt(d;>Fh3rynn#|rzj4Xj16S(Ja1#z9{>E>(XbK-5~ zeJqe5n8YW>SId*m7S1BeQN(qY^B4PV)?2J=*dMcBWOHJ#=Ul|IgD-%0E;j?;OMx(f zL_T$1CEhsRi9DZqr1;mU z=Pck-=la2!$9a{*hifBu0nZG+dwe!LE!^e2mHZ3&E%^HQI0d-*_w!EVtKdJuXU5yZ z>(3w0_mbxvUx~mXfvZBs;wm!gay60~LPdOAd98WVc*Xh41zzzB@(1$=^RMS?=Tqg6 z5NH#;DDa*)h9`~Jmv>G2nsR;O-pRX;FNn{9r;y8s`wIV8 zkuRc|qKV>8Qu}1f6<*05mH8?YCv#V7y~G1iF3}JXHsSBWTq3?g0m92f|B0`c{w3oo zB`9`BaI1iVkhfqf{}=w{0;~ee{FVGK1$9N@L}kP~rF>-hr8C4Hi{uC=2viF+2+rcq z7Jrv01gy4Wi@e{&jeY-gRu`kYOM#p?gEf0OhoTXZ%m=-{Sur|5yB5^9JV=r#Ks(xel{>R6EACo@_e3<@m%jfA|0>0RM z4f(O=cjKR$-;IBI|4sR~|9>viea3J9UH@nNV_>XcTg3K|`5KEETP|A$dm_6edlCCm zwlFqtwtSXI7EQJdtO~4aS$$YGGu>yJ$GnoYn)5x+Ufv_z+c`Bj*0VM{0V0=|{W|MIUlKs(s}CSo7(L=S?qNUtD`C@T}^2$up%V zHy&?$TJgN#`IBddU+#G?{MqdDw=dhi>->oM?)h!;mx#}%pXYwL^R4Oo^zVkh;{LTU zEn{ov@M3RalV(59x{_%-<8|hPtTn90ETt^Q?4n#++&j4?dA0eu1YZiU^Bv&&%jv+w z!GD2Ynct9a3NI`FRY4V@EdG98Ile!<#@z2Yd^nZ38oADKP2;-G>Bv#ZmdobA9?B8U zy_GkOcLDEB-Yo7J9B0^sS)*BYvv9KNu`;s0WSP&}!`{jz&9j&5D~BA17yEYhnVjxi z8#qu{k-Hk(t%Y|n??^j-4z7BpFK{J6| z{?md%B432rg!%>41Of%P1wQlD@|tq@vfHsTaOm@06WS`gTHptF4VNKLCbt25J98Lg z07Dj24%<48@0@`=i}+Lp(}ZsbI`BQ=&F9w^C=pyQBre1z=py)0Xt&5*(c5BkBrZuN zOTU*%kO`G8l71y+CwWKwuh>hmx#AzhFG%c{E|ImAR*;mG{2^{EK1pJ`c$0{saJg`+ z$Q03N5e?yJk#NxjvCR@QB+VrKBo|0*6k`^x68S7#Bshg{7q32V2G1Uzd|p95J3emS zMLd&unR%yj2k;2+<@2&|t8>lcdd4No^MXg7TbHww<2Sn~`&*WijEetG|LFUA<-6jq z6+abzn*Uh&eaerSKT3b({G9!x`P=KSlfG7bVgI7|#s2fNZn^vL^R;DhA*8y?(weC_$n*Eiqvy{UhD^DXb|InNoNKYGsi zoaw3LlNFEUA1{2Y^YrAie=nB4zVznq8`HP4Z!%wrym|fZ|GT;G?B26|;P|-v1J4KR zPcmPZeyjZP?8lSuB|jVgB>k=X0u8CEg{u?Dj5V%x#W#D0){Hd`@U99t>t8@59ny6n8HcbV&% z_?UOIc(OcTdd)b4QIN6aFZ0hGKX(5L{XO^B^B-+LT7P~0_4mh{?+3qM{I>k-<1aTp zulf}E>GVha4|m=teE9P2{F?=@zrV70{q1$n8@;zH-^jjx^U~sl>$Bfa@}6vYs`O0$ zvC^Zer;aZsz2bPA`zGl1(>I*&uDs2AXZqgy{hN0o?{>et_wnY}-QVSYe)_%k-&zI@ zCS#^`jQbcQ{#X6aWAtQfU=U_}&dASvfw_hGBy&5d7X9Dx zPv*bP{|kT1{`~$oheeY;hwT{K4K_p8#mpv*ul`p4Hv8G|UHRLx&jO!?z8ZXW{=)tB z)0YLGQa*fnfAoXshe>bC-gLfcdTsM+;mg#Qp)dJf%zJwA$+f4up1M9+_UPFI&j-d2 ztsh1`sCdxuVE6r%_uC(Ac=-6yp~pc_YM-oqqWEm#^Bd2DUR-$T^7`~^w%7MwO?)f& zG5z!XFOpv$e17+-?Nil9lMg;06hA%tT>C}stMB)MU#5Te{Hy!_grS#tBI`z04>k^t z^X!*dcd;a~>|_yTOJzUDd4o4vfI(1ENLF~gP@rHT{~_Ka-n)DY1hxnS3d|L}BFrVa zP2{L>hp>R~cY(XS`?<Q9__DuXJ;t(#rH*A0b0dpA$5U=W-ap(ST-}^%oJt%; zY`a*pSRS)vu|%*eV12=6!I8z;!`a1I!0F7P$ezR&%=(Z;n$?-Lh&7*eDeDII)m-Pf zS987Q{J<5J*6 zDtxzjTDZzNjX1hlHCakoy*XZT^>J5nWpUo%VCKkUb6|;Py2mKXoXYZ-IgI%z%K`S^ zoYS~CxDIn1Vt3(~!&$`T#m&HblJ7KsrocBrUy*a7DPpqXr^Fp3rb_fnbV|5NtQ6Om zxGVWYDo0vf=9G+!Y@ckeY_RMfnR_xyGG8TwC4PvX5;GFj5ZNpwD5M~KNZ4OwvDi1s z3o_ee4@xUZP8F9IlN3o6dM@}^uv$<2eKnGQ2HGyP>=$g+S%m^G3`kcpRJ!QaMTzCQzh-u~YAt?m1ZANzi^e&6#= z{=58-??2pr{{2z*)BgAQ-&=oP{&wQa(a)bhv3zWPzv9ERPm?~~_)z{%;f?RB%P*{- z?|9PtaLxV1`{MV-@B2Iuel+3n=f{SRCp^l0-;tsL?k5$u=PirKEP7PA$z7qER`S;;b=me0&$EHcc& zjI;m$`_uDF{`c`e$$xhKzWqD&x5IDMKhyuj{XOt+=RdZ;3cug}T=7%)XXW>@uP;7d z{KWRj?_z-#kU-g{%Wznlyuhzb_ zcq#pg@y)llBJbTleEQh&srl2vPf4FPd^-1~_8aeawI8lOtA3vT!TiJFhxN~^zn=U( z%V5gX$1KJw&eq6g!m7%ApUH{2g(-(|JHrfye8xm3KBglK9t;%>4cP*Mf)+x1g{4Fb zMX!r=iAai`5lt6M7vC>&KvF{Lykw;$o0Nz2d+BA;Y0~A=&eH#+vZd$9+>yfZ^! z%YJ?S!TRIX_Z{CCeJlSm@#C*|PH)ZMY>h!PSr&Wm%RM{s_%{EJB|-u zKkol5@-_RLzz?&Z&ws}JzV}y?VLoFS({H8?%j^&?mqn$RHRdaEqTu;Ecc~ zL35#ap@Tvx!pDUt3x5`37qSyPEWjghl5aC_A@5G!^Sm0oTe-J$=Ca>qQDO4`fAi0@ z-(kNae%<_D^R?*9^Uv&`y*_Dwa{ct;Ht|Mc?nu`dN*96xJ(+Vb)8N8?X@pPD~? z`Dpub=ZE4CxgR!si2hjkY0qbtueRTEzt{h$`RVfO-mjwH27i?P*8B@*NMMR&abn}- zc+GK&<0wZvr$5&}uIW6i{L=)^2^qDvx0VzI;z31Nv3q7ou^gT=`t`T+Cb!T!*W=3v;hXbr?7k6xQ~1`_ zTlu%e?)ctGy0hVq^Ig|_%kJAf41LV>?Bt93*9q^OKX!fo_@(M=*Vi{+AAh^_ef5vR zUv7Vk{;M-gWmw3#k}00ql%Wk%F|MiHZ@4FNujAUoS17X=>+9T0XGDHJ&=;x4K!nj%sz zTp*MzxKiLWe-57tuMw^W;yfKF<5t z_DSnA-{(W08a~;6^7yp>Q_1JNFKfSk|7QPV($A~E9{g_pv*l0yAAvsye_#5o{b%kU z=f7_MJpNbxKl1P5-*11M{yhDC{WsqqnZLXLrT^ddPv_sRe>eX>W7x(R!t|Y~m^p-b zF_R{fJkw9cLdJ6px(qA+Z~1S@uz}$$gE&LYzq&u2zw&eowwmye&nc;@}=*Hg7;2cFG(zUIZXmwR3*y*}`& z^JV*sO)s)u{&*?&TKw($cQ4-gy}S8V@ZGC-yWUrSX#VK)N%B*`$Gi{8?+?D){Vx4o z{@aspe!RK#HvPTx$F5JmJ{|mY>|@*qt@jJx@xK52UjKvXd#iVM-Uhx6d^7X)#Mc~e zPP}P(>+-Jdz2?V7pU!>$`^Ep;w(o8~KmB^}hwZ;5V>5Fms}7qPTNj%n`&0If9B(-1 za<}oy@bBec%>R!+TQE%cw8$n=cd@Brv&Fc?K8i$%923zNy&$3^(j;sud{fw4^sv}5 z@%Q36;!NVp#rVV`#Uv!oOIAp2mwF_1PHKzPLaAv|AEhox&z6ywT_LM4=PY+sR!7!T z#!|Xa%3G>JYP!^UDO>3#X@BX-Ql642;?qUfiUf%47WNm86n-RBEBJ(e51%04dER>7 z6Fgiz$=ropZJer{a-0U7R-98fNqJOP&&*Y@RnfF}xFb|MIr* zCGf4{P2v5|dy{V_|1NO8EY8T7`Yi{{S)|m^taOQzrSw$68-(` zx80wP-y47B{#y2nHG5W z^V+AkADz8__>TDPtGABdvc9ErGvj*NRjwx9c0negyFw8n$3+drEX69tCWzIFRf!3Rv54LlekWusR4JGv zAjQ9lx0+jpV-d??#<~CF{$2U&@ptzh?LU`)b^rMNb>U~#Pn$me`q1)z?Yq8rd){We z+4_3M>*Ck4uOnaOzifKR`r7_&(R-nfS3in=GW+!QW6{S&ANPE^^10y4@h^A2@P7UD zRp-0MkH(*SepUQ7`J?xD*I&bbTK^~fU-NI_-RY%3l({`+o2Lo%uWM z*PNe>zs~<^{yqDT$Upc01`Nv>wlX9$+A|xlCa?*x$FV!HpJqGCYR&SJ$&M+5@y>tm ze@%Z^{Z0J$@85-gr~az_`Sf$@_cdRAzZ8EK`YiM5()*IPl5YfFKYYpjvh79b3+|U& zUp{%M{A$OmpRd-xVt8fqa^VZP7yF+Zz7TsE^wR(3wwE3+o1bewyY#g2Y0cC8XY-!- zyjb?K|JBx4mtHM>{rrvOyZi6nzdQL(>b=AJ`R}COWxreV?%Ug%H(_67ycK(I`XTmX z*QZ0DHNU?37WXr5bPRrU44zhF@Q$Nn@S|h!qhs)+WALM6@S|h!qhs)+WALM6@RW|h zkE}%;qYcQ>MI5wP#GyL6h+}jS$LJ!C(M24ii#SFXaf~kFz`clr0Sq>aP_~%kf9Su{ z{}LI*nHR90WXWRsz-Z3+=3n98oO*8aZtC+jcf zpK;&Ue0BSx`#JT~t&g0a>^}#8N%%VPyZ6uPpRB()f5-ja`{&euVWzK451BPs_1JE) z)v&v9q;V>9yYTMglj2w8Kh6JJ;I!Zu!MlP-1wDl1g?WUFggy#Yh+Gp55OWlJBQ{5T zpIDaYVUb(HT|& zl)!3UEp7+SJsh(*Cvjco%HX!=y~B5ePk?V8?`od4+zi}poLn3-9IYI0*#+6>vgNXE zVas55;Ber~<&xp9U^AS^7uv@87@w|8HeF$l}5Jhb56U zg6$;RLAC>IMQr?R)7b8_dvO|bALD(+&nVa-ctY@|{ zl4O>;BFQajC=oAiEZ!&XCq7B6QS7N$p_qo~3t<7_B%x=5Izk(TJ;Y8+a7*2nl#q;* z_$>ZP{Gj-AF?KOov6Es6;;+TMB+4Z=OU#jI5YHEF5uPo?C3Ih)nZKLwIBx*&8lGJ4 zxm+{3ZgR?UY-iibI)$Z|xrZr}aXUjBgC+wDLkfd8!`J`)3^y3E{=57;_s{PCf`2>y z9{3~o$LUYbpT)mrel7nY`J?d1)gK%`^M1Dftp4Hg&Fb@^_xf+!UQc?t;rX&>0Z%79 z=6^izG2@f?C%>QAJze^w_mi2=R9@7)Y=7nX zdi(2judQAuziNNE;3ebhM{g#-EBx^0)2}bHzwZ6&_-)U(Dc@Co2L8J8YvJ$Jf7t(S z{p0>e=8wgn&Of4mMgN`uf1A;f`6RO}%Mun}){U&5tXeE@nG%?OFnwY6VEN7x$9|5} zlBv7MYaj7$5{+m1Xw;Y%d*U1napCrqQ~-&xry0=`8E>^QyJr7 z#zLl(OodDj8ILlSFbXs5`*-l4`TvLinEzS*jrpVVyX$Aw_iJC{z9xK)`pWSw;CsoB zuAlP19{zCq_W1Lzk3R1M-WI;Gebew}@!PrY&wsrCx%R8}x6NNWzw~{c{W<>&+t>GB zmVKG^Wx*GdFE>B$`jY=`_JalGe{=VIjk!!@0& zflG;dGfz67AO8&gU;OC;vjjQ>Gz1s~8U!8-cnD18=N4!XR1x+Q=@#J?u@+_*dM+?i z;G4h!!S6!vgdIiRi};Eqi)%;(OIApQNl%gyl?#-wRd}xWTParAOnI3Sm(pd$M~WX6 zFDfP|Zc&g_u#sOZYcBIh`kC|w=?l`rGTWr(rRPc&NE%9*OH7hDAnqu3T0};;M=(vm zfWLyzn!j1#pTKJYIYDJ1O_3_GFXANJ1)cGe#(r&uCbelX`V zr!yU6bY?oqbd>2N(?+J9jLr(_`}pSl&v&QZX}tgVZra=1udl!S z@$Agw)Q9Kp+uZ+gfAxc}_j&Gn-rs+J#rKYqQt)U&*|V zd;Rp)Rp7rI<*K6OzzHj`t`rGsGY`?hw^!>g6kAYzoLmR`I|A+o*{_FqS^C$oJiC;5+ zHU0Ac_37ukA1l9gd|vw@`(5oD``0F~8(%+twdm!(7c*WQezE$6>kEb#K`$P@h<~a1 zYRYT1x0df(-pRdde9QNC>zmv+{%^|OTzV7!cIjJ>w+?T_UKhWb^NRbm%j?gt55B$i zUgx9Qr##`-k`syYG*`b$+Y=8u;bbXNfPlU$nlMeUAT>`02!_i=X^Hm3&u-p0R`c(?X_^2hz3W_>RH!u;*Uch;Xd zKTUsa`Q7oi;(ryRIrDTDEw)eWH#yummb2S%L~#D+oWr$}`vK1%-iLg){2TdI1rG>a z6WS`sE*L5}TToKaNkCfQsDQoTErB2W<@_J{%>>PbYK5i?)eChC$_eoD8}sepE#o`I z&n57H-$HP!aDwO;(H60-;s%n@Qtzb-q}ybS<<84LP}r&XMaf>JTqRpsK}lXwO@Uwj zjI4mn2T5&-0C6qx>0%0^uY^ws8wu+QrtpXIf8$pb_{2YvKZE~2|7-yxfw}yO0=$CO zf)@np1a=8b6`Uo+D7;RHUC2c+Qy`LGk8d$=1YZ}wfIu$)7v4EMaXgQBGQF2p{s)H1$_lI1UmWZc`xx!<6Fc#$H}dtzrK45cnfHcI>wSCn`pZY=&ntWms5Vwc1{@o!?6#8|~Yh~nfK$*9p$Y zoX%YGT%nwcILbKuIJU7bWfNnKVD@M7X6k3MXIjX3fsui^ojI0Chj9{PC6hMO4ThQj z)&I}_f$z({#eMtomGx`X=hTlY-fO;F^oH&Ash2`8MP8^p zoA)^Cp}_;c2Xh~My3cZ7@&5Gtg7;KDf2IE!{NKvZ&1lQGiD3qVHp9_>dVll& z?EW+7ujjv}f1dwU7!NS6z9-j%V7Dz)XFH!;PijfKcl~uzn*A@B-SW%f z=brB}-zvT^f4=W(m3_DG-IKQ^Z|=Nie3Sa-_nZB1C%$WYAMhde!|C_F z@A=<9e0SyD`F9oXR=wqU%lh{6oAs}kzIylS$m_kY9bS9BzVh1bjp3UeuSMQyy({@3 z{BgpE_z$ihy50x8<9l2F=JT7KZ}-1Vd|UPQ!CQuRi{I{e6Z=}@RryP^m!Ds3ePR9b z+p8OITHmI=o%~k%UCX=U?^xf@d@uUZ^t1j~uJ0~Ci+}U}HU8)L-;BYZ@hVdf3pZOj zy9}oUcL$FUZz8V*pB?{nfm*@2g1-bih1o=(iDZbFi%t|fCw5shN<=`|Q)r{$Q-Ns$ zg@XHql7zK{7YG#zofXm*77{)pG({*>=$4?PV4r}7K$C!-;9|jDf*%F932BNP5j`z7 zRs5qwij=6dp!6ZBQmJGqJE>sFbK*P162+9oCW>Aa`6PT)C|l4{;69%tZxGLGp5weJ zymNSt^0@Lc@ka0%@|@y%z+1`po>!4qhj%`28Sg$GN1n|*EPT@ZzWmepUkX$TnF*T; z3k&}jx+kift4t5cik(A+cO?npD0t zyG*6bDVdKlqOuXP(Xv-%++?C<*2qkgNtIbE<12eYmQ&6_j$Qt^!WyMT$_Xm^YQY+6 znhhGs>g8(ZRR5?PP(Gt{P02|4u@bXVhGMK@q2eor3i+k7AEfQ1rc20+-xW0xEfPH- z$|zbYtSjUt*eGy;Kb$|DUr8WPP+Z7Jh(Tzhps(OEfj)jGz5w1UJl;Hk+^SsioMs#% z>^oRLFi&SJ{onUb{~zn$+rQ)g-1^)4FaBS~zk~md|NHV+<> zA2)tv{@D87;@$VRKi&$zt$h9bWycG(=gXe5JZXQF_ps(c#QoEEKi*Ei_3ftHt@2wv zw{&iE-I;pl-W`Lx4R`O~jlFm5p8WlL_kTU$e#H1#=84Nwv1jL>{dn&BlKEBbtGTZ= z-Wt8z_Ac_h?uTn1WIo>fF!{sZ4?Q1UKURED`jGfx?g#x3Ebk@W1-^Up?%BJu@A}{0 z`f%Z+#HSq}O+PYyWc>K@!^01cKe&8s{iObd=WEB;o!?S^O#G?#tLfLVU&_C?{Equ$ z@i*_^>i^9Qw-}Z&2ry?UzIZ`0rU zze{-c>}|xmY45#09C#o1?#G+!ud7}yej)yR=qta);FJWK9ztw#2`@!~; z>!`u8I{WJGtHZA@zw&y0`1PUJ0JJ&81imzWE&k^HebtY|U(A2j{Z09Qg+YmFC9^;4 zBsOFA9`+yX_8dpp&#)DtmB%;&CYY4JB9l(VMRMKUb1(sI+} zWfk+4`jp#Lgj8>a9ZJ#f{fxTMF!<-%3UgAsxhizs*b9$s=HK0)vVNl z)N0h$sXbETR##UyQ}khSsFzeF&bqWb2WZxtktyE z($hMxS*NL~*`@JDeUiGp`VO^dwOF+fwF9cWssgI#Rg=_W)vVR@)xN80sh(8!Q{q!x zEq_9`LE2C9viN(k52Cw7E(v=G9~62axL+WLUy<)1j}W&GXBT@e+bh;1tg)=gEXB;a z%>S62m@*l^G3;kpz_5_vAcH*P8^-NSmzm6%LKvkP%>S|dQTWB<3*uRFe2fARgy z@M-1;llLdz7QUJNddusWH(%dmz1{hC{@br_4!u@-W%45MS^txrk8VC_yDxbE&AqAj zIPW#wJ$9%5_RgEbm5A`NrkXmpQIzUP-=k;)>hVg;#%G zHMwSYt?ru0_2lcp*ORZ`xE^_9#|_b&r*CT9-g)QS-Cy?%9%Ma?e8l~@@$tRKtxsy7 z&VDBL;>t_q*DqdgeAD$->YdWNX>VV>X?PRx#_mnzn^SN0yk&jQ_Mzg#!4Ho=O#R^S z!T5vZ2gwiTKCJ%u`s2NiET4it@qdo_viqyqcf+5GzkU8N{GIXl;@{T4?0@I}S@cKu z@7=$J|E~Od`)}Ppvwxj`*Zi6DJK~r6&x9Y_zpwnZ;%nO1@~?Vd4}H1y#rx~UufE?_ ze!KPU=C_=0U0;2_T>BLJ@$!4Scfa4{znSwU>TUMBs`v39UVnJ;q49&zhkNh8z7PBG z=0n#(4JYza0Ov>C1{QY+rf5m3$Ze>GJ!=-z)#s81tDXFmthd zWZuvGp1G7|HA@PM9ZM_=3rhgAHnT7DYo;wsVa)z4Q&}_E?Kt;viSh9B2JznF>E-^w zIh`Yl{Wt3emR^=^ED@}ySY25^G8ZuIW!U;}-k+tvPW}l0ZvSo17pBj+OU$KVFBt zUi^yd)%zD!&%Zq5d0z1B;8WITcb_eO?*C%Ji;fqGFSK8*dj9!Y$g}59=RP%ldhH3z z)6GvEpG|)D^O@W8Urh3^7bmEJkee*xzy( zaxrkXbNlf0^IGvg7WgfAK}bl%K{QYFi%5$|tVoH-M3GvNgCe40krIET@?^c_k10ec ztyR`gVNzMBEUP?M$zMrGNlnQ{Sx?nm{f9=pmaR6k&R?A+x(jvVbWL^hbdB^J^rH8Ce*eGxRX5HSpID)H|qKr0cCKraM#Tw)SnUpPI`x!!+47e`|{99M$d8JES*3 zPf*WSS4QWC)@@B`%^nSH4NeU`jb05I&3&5RG$(6{X=Z7-sRya)sRgRJsJW|6R%2Fo zR1Z*3RR6B_OqD~mP-TJgTcvI#Q>98JcjXPrhm^l4zfi7FmQq$zZc*N*9HKl^>9*o# z1$X)Ra$RzdWFN^?$+*cJm0l{XEVD%>QdU?_M2=DRjm6V%gh{Or;MDg2Vt)h2@ z1BF9{w+XEfED-q3H-}e_rE)`+xUu z%b#Pv=l)*)d-3m`zc2mX^n1~7>)-o+UimKY?aAl4AGzK?eLer>gXf!{);&4)DEEHr zec#90PphBrc{}}!$M4SnI)8qCoA`bIPwC&s{@nOA^PA8Y?e~9QFu%C_yzzdF|EZ^b5IX<4(Okw&PItKFK{zyV-Z2+_iRB+^&dSM!RP0)Y-|f^Y4y1JE!lO zyZh}P!+mV~TlR||Sbk9Yh}^NbzVqf6ZlA3@lX))s!mSHuFXdj} zb0_oRi>G&9y?USXMfykn@1_6FF-&1BWO8AtVKd>J#^cXFS)f>;ls|?)UO-4-58p4o z!~Eg=%=|k1Q}~wg%JJ&)eBtWiI?9#GHIXxh^Dk!yw<_OJ0XgAdu{n~Hq+Mmd%caUk z%de52Dz{YHSAt3OkzhRkYMzxGPnc8wEB(&@9`JSk7qc%cUygiX{^tAb?$>4C?0i^gO0{(9O)AQ%o?_fA9a9^Q-sI%Rf{9wEUI$|DB|E~VK^l$lpUq(}=U(8+XE?n=pCHSWCpX7haznfo^|1Vz? z-&&qrPIuO)jPL(*{q^|q`}3|3if_4JEq!75eDagdM+%QlKb-#{_I~`mgu5s2oVZhX zH~+rIqxQ#V9zT2X`02JM^^fL1{QU6lLym{>4=&xWx_9=D|DA7l=G;AUx9je%JC?Vn z+~mIb?Uv5{tB-|VoOz@9X~Oqef0i>$VE)EBm;D=i4SN+E6YE0eP^OOzF8}xZk@%(X zGxKNhFTuaU3_lsqFsri`vP3f{G5==T!T5w>F@rFpF_RLrB+E@!XZEG+HXJ`V-g4~X zsOC7wCd2ZE(U3vsU)^t$A0A&dzWn%d`&;!7+n+qY1b*xM?)_E$)AC2@&x?Q7{oVP; z?=Rcm;6L;JJ28FwKl%SWCP`)%mWdo8oYAbktWPlIaoY0r^3LXH z;b`EG6KfH@BPcGWDibQnE^%FfTP;b+PdQ6VSJzK_jrKbI)5a2}EGAD4GxXi{cI%$e zTB(tyJyG|b)Wb=R=y2$I8lE!_GUhS9XdG&~!tAn1kU_0ZxW*5~ zpVGXNtrD-r*NB=6?-o)Pa^t(l$;YM3dzW`P4H<4k9}!@88i zpUal(HMc8&s$iGkJV8xiHPNY}IU>@+=0Ya~KMMtmF-vZfcq6_~fdeqxsQp82jS8>IQ^mCk zMM^9x(JJX`ej0Z)6*Yx4zp6*5swzXgBR{rLTD!)Mcv6F>a>u>RxokCh)6 zemM93(R=X^+uupQQFvMYwC|zaJ=@z1H~-#Pax3|E!>#C>x;H*u6TH6mM&T{KJ8E~= z-ATT^{nor&+ipI*_UiJq%L}eBU-7>5>!RfqiR(qzC9WO6+HkexO7oS}t0h-gUg5s1 za8;k zo%3a9bI-_}xqW)VnTYfDSDJ4K-gY# zI>1!Uw1nvovjxj9CLv}QmL)77SZ=cZVyof!$SKIJ#$&@Xg-eAai}e~4FXO}imH$uu zxBKt(ulirjKa;=Zf4cto{gL?d;J5Q{tzUvaj(ko2viMWhhxqrM?`q#(e;fO*_^s31 zqwiQhRDHPnq3+|!Pf1@?z6O6?^R@Bo~~4aHa7Y^SAQr^IPzX3q0aa*%Oa83+TlLSG@fFJfc4ICH9ygxVTx&Vjaop#+%-za8 zg_l8qo&PFt3;#($H=$gCBtBjKwE~<1)A^J5^?7}`zOp;8U*YuNS;pPU{gG!PZw_xg z&l>I)o?G01IFdPEa~pEM=Ul?A$G2XfNLX1kO6;=4bmMH z)a(--S2<31SZl9u_tLu8YO7_TMXQB`)eox~){?d#ZKZABS!J7N7?&8B>f7m8>%Y@0 z(e2Pq)S9Ukr_HF_rSEAlOYgeQ53L;a4az$dw<@T~f0E&no+qg%;U(@X{zi;R)Lv*g zzYA|W_fIZ$uHWo8Sgn{p{=4+s`S+w>PQMKQy#H(bujZfkKgGYXfBgRx{i*oF^~dq| zmR~8qQ~tjAXZWAkelz`v|C9FT@1J*n8U9}Sb>%0=ubyAue=Yod;%^#5 zG~;x}bBwnc%>J+aTl&Z0Pxv3VKcD{a{+sr{g-MS!kxhZUgDr!lk4c~5&YxYs&i?%P zgX1Ujuk*hQf4lv5{~iD9`S&SbO}yDw6oPkoeqfA;m)7kbZ@JpTWXOW?A`teOLEx*E^GU2j47yZS$t{t;0Lr_ZA<_ zJ}i2_`+fa~x{uzU7(c!Hu=<1MN1l(_ACG)~{q@IJ$!~7oZ+x@)vi9Tj_f~HwzyAJe z`780)VsFadTz}K`w)kz#+xEBnU;Df)e<}F-WLS866U-b0$`u;|mb-KB zncV+%ujX#q?TI(FZhXI8L)JT!T5S*B@b6W zxbQ&c;eiJQ4|N`!KV^R*@w)hJ`nz9mr@Wo^_Tw9iH-T@~zu|tn;BEQ4s`pDiZ2Hvp zwex$*kCY#mzwiIP^83Ya)4sj@y6JPuXRR+sKVEoe{%-oaa~~Fdp7;6WXWMU|zA1g1 z^)32)@eiBdhyU?2S+o3RImfz;&4^u;b1JtwZ#{pckg3ou{ug}A{0@9Od7tpE;YsIu z&KbZR!~1~0T~J4GHopY#Z_Weki`jm&9%L|84)x8D=uxV!X!K z%&f(>fy0OUChs+VDZ%N2lLV&-`14)iVc^}#PqQ#qq3Q!cX(OCReMwo7c!*tW10u)bsY%3{Fc%d&+Gx9KCu2` zeaPC%YR|fZC6dLBrJwmXQ$Dj5^B+bH#zF?q{}2Ct`lt5q%Abk9XaBVQ-v9OW=i?va zK4`wb_NM&R>KBpE{GU8}#QcE!PWH{c*Y{jixe|O?@zSF6CTC`yFgtqU(AtCV4n!PS ze_+Q!&BLBYHI6f#$UISU;?{AN$|u`S{5j5aV#>*Dr>oAsIcIUf{bISf@o`!CXub01heh>H&`?Kcf)}MQRru|6x#{5O#`^Gyt(~m$(!`oVy{?U zR=$|<;>L@(my=$xydQoAB=HyRGl$zEgOg@Im!c`R9Z$>fcmPF% zGw+wl?@51F{j+7TWIV!nmqFow?>~qCzy7B(9An^TtYj2ndckDQa*s8FeFKLwmkjp| z?k1jfywQAX`QrFj2nY&E3x5?}EV5nXp2${FS+P1%KG77>m7-Fj>LR;@8ALXVoEAMU z<|V#HoL|CQB2gktqD$hfM6<+p@o@1yVxnTnVvoh##M32CNG1pZNRgPrNWNv-lnS8bU;rw=d8+l%F1#miYc(6ya-C}iSox`HV+RSFk z?#AxJp2Yr|eK&_F=Wh;cPB|_f?oRF}+|zkFcsKFA=HD#9DCjBZDOe?7#Lv%nnn#7Z znNx-1Cz}Hs2ir8(dKPo$!%V%*A}poM<;=TTYFHCkwOCKFOki2dV#m_KtjK(kNrX9# zyEBV1Yca<&moXn^KF_j%Z7zoc*HrG+JZZe&d4u`5_;Psz zcvE=gd9!((xUX_v;Yi|;;+V_+jje;tj;(_=l4T>4GUG#rGRB#VR~XruXRz?H@v{rC zx3H9b#F-^szmWzRjCM}aSgKUu(But@N%K%BrwfzyIMLejz}BG*L(MZ-mx ziVBKt7IPHeAg(HLTjH){m(*6N_fpl;sxs$fjAXlIKghn3T`ub{Ya_E#YP+PpWTr%k z_JJzx8L7pyvuo4@NVt9IqyEaRd{>q&9gTj->iJY@TUBA!E3YEZm&FE+P$cM zw&;n{G|^4I`1t$ z7JfSP`R$k1uU%gSzux(>=BzZ*LxN)(`$G0Yjxf%*oJCxm+)KC( zdFJy-@J{Bv#jC~F#OKa8hxaJ23IA$=>4F@>DWa#v-$|~N-Y&CR_KRGP{9d^QvNE#g zWfEnWWh7<9WuMFGDyS)NC|p;Vso1QjuJ}P=ze0$@9Qj>x_hcnxi)0>2Ye^?a@kz~> zx+(om#z^*?%x#(1GVf)+$%M*=$<3GFqL8V0UC~Twzmm7|dgW)zzm*>;Pg35hq^DRV z&nqV-yH3VWW`neYw4rp1)G~>4VjN-%MK6fV6y_7E5b))H$NPlak?Rqs7FPk+PA+}! zzuXMG-Mpr}F+5J(e>qok#Iwt@>9c-gF=I_;$U~3E22ahOeR!t+LhohFOTL%)UwnUI z_p+6YcFTKC>QRB<)Zwf!_elh<^__vsW zgXtC166PwFF4jUeK6W_{1}<5iqr5EqxdM4YZ$;e1B_&Tv)yV9TRhHW&ds613^aSZR z>3>pFq%@?CNQO%GOL&Sai)D(=7r83DN|;ZiT0~fsTkNY?zxY3KVTr}!JmO_ydqtf^ zZA61aO+Woh}+6`d`FK^q#1z*mBVe!lwkY1Wfr`c`tFFud-hdqL9FMQ%b89v?qrl_+Rk*J$)AatX)@CKi7RO|9t+l?HAK8ouBV~D*m+dW7UVO_xIn; zcvtZ*=bi66y>}MxINlY#{rG0*o6hEp*G|){(e|9h_gV#$kZFK@lN`zrO7)2ozM^IqM1rT=>W>+5e!-le=(`_TR2 z{0GU8svqxt=>4$tgU-jVAB#V!e7g2=$EQhO+`p~)p8xaW@9=-R491KtOlw$T*=Df0 zvzf9L>1dAAnJQgk&wh%TGzAtn{ zFi&6se=NT~|4hE+yia&`@Z90i=l#VSz<)zPMCgH#vap!2sIa~8BH?I}e9@C)!V)(m zzDT^2;E^nnl$2U51)60`lwB&9B_|-aN3KV{UH+CFr(C1#a@qf~JaXA`=j7)qURE+z zwor~x-m3gmdAV|gvWIf6@>J!O%9+X^lp2*JmHZX86rAL3?Tf4z<?ykh$sJl&f1Mg0``{>?^2kMWC9$$UZ`mFOs{HqDC?cSV!6Zm%a+tqK^y_I+; z{@(1v#}7ImBR;YP#lIK*KJxqW@A75l*yY+9v zKZpM}{|7NFWzc7|Wa419W}d;kh2=791Y0DV9NTwRMK(*eqpY^9)~sQyUszID0$D^@ zv)E3sui+5q6yV&#VZ||xeJ7hU+YGi}Y`fX`*~(dUS*=-RS$kQ;SU6ZtG5=?J$M}W8 znc>d=W&geY_y3#v_xvBPKXZTY_$Bh|#LteO&OcxOaQ(67`-<;tzH@xf`8MU-OA3}% zejf?TD!-loR`t#CoA0+R-%fwy{U-Fa{mbLek3MmII{uO2Q|YJ8pZ0xn`Ml&y@;B)p zlYaL6vibetch;X3e^mea{QLL+7~?mlFy@`i9V`K?hgg-^n%OR~iLo29KVWNQo6h!* z?J=7TTL|k!mS@cB%=Jva8EY8z7>yY>GW`3e{a5@C-|rPpdx0e|-IM)hDLUii2wT=jX1^MPH76RsHVpgZXFj&nZ98 Z|9tcF@Xt>_SN+oZ4Otty=hvH`O#nK_LPY=o literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/4e7cbb27667bcfca92838aa8020749990013a9b1 b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/4e7cbb27667bcfca92838aa8020749990013a9b1 new file mode 100644 index 0000000000000000000000000000000000000000..898584d96f6bfcd76ebed9dcde3b7df88442af78 GIT binary patch literal 66423 zcmWIYbaQJ+V`K<-40BD(Em06)U|?WmU}SJv!@$rH!N|bG01{z<0&gh&4@$$Rp#T5> z!`P$rXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeD zjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinpbY`G zLF=+nhmD57Xb6mkz-S1N83K-E>KoNI8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71* zAut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@? z8UmvsFd71*Aut*OqaiRF0;3^7-w^mu381f2M{OGofzc2c4S~@R7!85Z5Eu=C(GVC7 zfzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7_=eKFlb#i>afue7!85Z5Eu=C(GVC7fzc2c z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C z(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7{nnkx)65|N6x6zMnhmU1V%$( yGz3ONU^E0qLtr!nMnhmU1V%$(Gz3OY2>cy6ULE!6Xb6mg(GVC7fzc2kHv|Buph`Ue literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/585e469231d202812bfba8285fb30c8e31c857b9 b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/585e469231d202812bfba8285fb30c8e31c857b9 new file mode 100644 index 0000000000000000000000000000000000000000..a4994c208300b6cba20708367337667fbbd8dabc GIT binary patch literal 70833 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 a^1bW(=WkKp9KW@FJN=E}yZQIV?~4Iw^;b^- literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/6874d5b1c7a64b596c61f24877d422e89bebe58b b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/6874d5b1c7a64b596c61f24877d422e89bebe58b new file mode 100644 index 0000000000000000000000000000000000000000..e054ad5f14723fa1bd5829725e38de4a681cb3e8 GIT binary patch literal 25086 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 y{p6Aw_lRRg8j`jT93%@Qt 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 literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/782051f8120182b860c7fe1b265179cfa2fe03fd b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/782051f8120182b860c7fe1b265179cfa2fe03fd new file mode 100644 index 0000000000000000000000000000000000000000..a0d8a6ec48c983fc3870d173c5b4c73eb474eecd GIT binary patch literal 66439 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 literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/8210dc595a2652f2f812093b01e239e7918ea065 b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/8210dc595a2652f2f812093b01e239e7918ea065 new file mode 100644 index 0000000000000000000000000000000000000000..46316baf29ff126da46159bf6c16fb11eb9cb23e GIT binary patch literal 55329 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 literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/92c065286f956f086e977556358f6b54b12bcacc b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/92c065286f956f086e977556358f6b54b12bcacc new file mode 100644 index 0000000000000000000000000000000000000000..77b8f518b4c46b2cef89bd7a12f23ea49c8505ab GIT binary patch literal 315 zcmWIYbaQJ+V`K<-40BD(Em06)U|?WmU|@7v!@$rH!N|bGAi$84Sdti%#>nvK>-x_I z->m)?{4e^=_jBtX4Q40y*Bqvt(d;>Fh3t%M-cp)OEX;u%6S(Ja1#z9{>E>(X!)`t! z11|GTG0cAgHD8KNli8bzkpezysmri*M&?Dd?Bcy{mw@XqCC;Cm_X I_Q|U-0IQK?#{d8T literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/a35c9bb71792b60a13dea23a41b41847ad4b93d6 b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/a35c9bb71792b60a13dea23a41b41847ad4b93d6 new file mode 100644 index 0000000000000000000000000000000000000000..45d6b6fa606fe4a25d00476bd4ff785bb80fbba4 GIT binary patch literal 44 xcmWIYbaQJ+V`K<-40BD(Em06)U|?WmU}SJv!@$tt&B(ySAi$842vQZ~2>{n92^atX literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/a6ea960c7b4d42772888280277b26e645ceee904 b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/a6ea960c7b4d42772888280277b26e645ceee904 new file mode 100644 index 0000000000000000000000000000000000000000..14954c595882e6d35c5f77f36dfcb9ad315c606c GIT binary patch literal 22470 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≫`yR2!n1|AgzgJ8^LO(d=MCUp!;{NBmun{1O-@;k z?QC0Fr?B)g_b_ELZf9s?&}3j?NMZ11`1-$};RZw2f0uvf{@MLs@NdW81ApZHIQ_}_ zv-r2nujM}^e-!?>`h(+V-p}@*)jvGGS$#hAUjJ>|>q##+JYV)K;OT_N{Ez27W_%L= zc8E8r+?M|YW|u0 zE&tQ?$M28Cp9jC4e{1~`{Bh)K@|VS*vOdJW?|fJL_WIk{cg1g=-X49&`l0H>-4Asi zPku`JqVhHP>zc2PUnhV0_gVf+;+OMZPJEsCo%L7JZ@b?|exLjk^GE5A>tC*a7ye~3 zR4~q9`pGhnJ%cNa*OMEBVI#ZPK@^KjeN*_#yZ0-RC7AGTwN-nEPbM!!!5t zZa==U|7yX-unU@(bS`CIJbv-X#m|?#ul&07`C`-MpI3OVIb09C*?DirW82>bsYD(E_1hXPvK<{VCTQe+rocR z&`l^;Ac;?xf2{zgz;ym3etljauCMG4>{mEFc$RUua)0ER$eY7k&$EWRh36LcAC6?s z*W8BO?>U!n>+!7@C=yl{jS{;oFIzCFNvVWv|Gk$hXRc%Wjf= zsPId*OshrLTEA5Pi~eK7RmN{jw9VF;dK-rt-8X)0y2^aArLFY^8#Vhx$5oEg9oE|G z+r6~zwc2V~XwhmRVfDjmhP9;aM_XyzcUIZv8O9|BruugJ)%x%BN_0E46SZb)#c4C@ zcIkT>%+kBA^Fu2~eS`82#jOfz@}Fe5q~}TMNqC9-ioX$K615jv&hNt8&i#{1o$ELI z4OT1WkN+>vL>MSm*(aQ$)oz2#TR@07nU{u%z~ z{Lk=D?~m{AhTlwo;{T-m`TOVHUxvSzeqH&=@vG<8_g@QtpZJ@`5Y0H9@f_oA2DATb z|Cau7_!Iue?a!w_y#J>CZ(-77O=MGG?_kSd>0{DoxbtV%ud_ct{^0n@{OkNL!{2Vd z-G9gbdj5UNSCcPSK7Ic9_T&DK_da@j`tb4d$H>nMzWn*Z^>yNx%FpVbYCqP0YX0Kz z)$WVb=TjeL-=BT`^@ZNEC6E6<wb+~TH`m{E zy)Awl^S1r%{?|S)%U=q<{`flSP3arvHxpi`zn=Me`|E43R=m9Y;^}j#=O3RrJiq?@ z!Sl}Nj4xKa*!^PLi;x#e&lf$t{W$1R@WX}oEAJ-U5xbLfr{(V4dnWgP-K)74V}E_hr1uIl}g51T%lzi#@R@>%Q4(T^A2nZKL4nG<($f`&RfqPDP$^ii~j{5Grt4hPTnWHYk1PRo^u9p$M8PjZx_@N zoXs!6`PNUbd_-qgXaIjzq5Z=|Ni}Z-*3Kue9V2UHmny}53_A#bz_cY z^kqo-fAL??|2&3Y3@aE!7)t(6{O9v8@qaOc5~B~30MnWO^Zq6O)BgMJ&(Xg#{}}w@ z{1Nh1^^4KBH$RsA{`7Ae!?*uU|Lgy|{%`(&TT+&>YD28Y7><^6fY{6DOAWO%1@E+ zl<$z=Dt}g9NP$`LnBpOYC33>DUDBr|oh1)RvPzwh{4G%?!6P|Ya+BmNDK?pnviszl z75e3U<+5b%OWI0I5l)m3$&`THH!(g@~l^8o?@oIQ|;GgS>paxjf3;dpR`N zW-wo2`0(%1KLv(UjE9+bu;#E$VV%a(!yL;P{{Pg!@_#k|*cmo4vNP#2t!0|e)W{UY z%*S$w`51E^OAU)3%W9TwEbc6-EHW%gEGt<0S#{aW*(S3!u)ktE$CAXH!&J^F%9P8j z!_vokh3yjCGqx>k1+4E_zOopw__C~F&13t>_LIGw<2w6lwhyeoSRb;svf8umV2NaL zW9eu9&6Lk<#r%g+gRzjo^Z&ztpZ=-+yYgq^@7X_XzxRKA{rULExDT4|ue~XMwfaTm zGyf-#9x*@QzLR}(@AW-bRjveIR=l+6yvdnaC(MqXIJEZQy8{si)*sk$Q1h_oQH|qF zCo)fzoVazI<#_9{<;PTy+aDJ`KJoaj6Aw-noT@*SaZ2G-*eRRSj;A$FtvtEnr1HtO z6Mv2~otSd++UcsZZ_Zgi)~OFV?^Cdhz!8lovZ*`oEs~R{j0o_iH~^d~W=*|Lf&% zp5Ft0#Qv=Lx%KCspJ_i5zA=9h__*tx?_29P8gFjDS@I_Rwb(0`mz6Ijytwfq?&YLc zY;RcK9(X(R-OG3V?TD~~` z6#{}n(!yVb7mI8cxhJw!R937`lutB8bfu`2sJh55VFr=SBBw==fve;uWH}Q0dladdltYwsCon#Yb56MiB>KB(5i576lG#-$tHSTmhVp93Je^Y`0jQS?925u{N`rvb(YSuqUyb7Fe@@&WD;RcV|mOf!ye61%qhbq z#TCq%$id8E#W9oP8%GPLD_0$t5Z4~gGS1%|3pq467}?8M|1t+LsWZs_Q}}E3ciCU9 zf4}}c|L@L_^?(0goj-ZMJbs-2*7xn%w}s#D{b>A^{O9gp^?!H&iv0Wh@5%qk44#Z` zObW~e%@94nY*K73Z2Iii z*>`db+F8w5rTG86(+l*$=XBWS7hO%i74Sl-e$7FPSM(BK}`2MqEy!Q6gQU zL4rZjTk^I9pG3U)J+V@;Kcb1E4x%?iUBqO?UWrzU&J%egEG^6;^hjVHzXP8V?{Ds1 zTxwhnT#{VYoCnyKv9d5LF`WH#^oPLLqo3qHs=qILoAKuA>ou>-UMsv#dL8)2^6mGx z8Sir56}(&fZqB<8Zx!C2dh_hf$2TkAFuW;$UGUoMwc9I?mv%4epDlW#^tkh({(}Se z&)>gr|KWXw2O$qUAMif7dO!Mp!@Wg!f86LoDV*K>iq2sDwixSf4a&e0k=Ty;n7^|Gn|#R_&eJcW>T1e}BTmt&dxuetN$Awa$BskAOC$c8F~``*)5=t|0Co+{rw_ zJd3z%xEeVtIhnY)xps24b2@VF;E>>$#=elfkRy!qEoTuIC-)L=L!S9O61-o(pu69QhZYLrEW^UlQEM0CUaZn zwaj~&Z!)2>VRG~3wmwUbMq`!6>GZ#SnW{_EUVyI>} zd*<@w{zKCTy!UPH+28ZIFY?givB6XGXCI!aztDRb^OEo7{TJU~*u5-$+3>RYWz)+I zFWG{QHwa*ql-Tg%6$=%0a9?L)Z|M>Z1?iw1l~erHi$Y zjgMW9gMmwy=O`}=f385D&|48VaY@OOQZ+JrWR>N1$)1$?C_O*N(E!nB zqKsnxqW46cM5l`ei2fI`61^wtDz;qog77K9ECEygR^Ch8C%LM*=5Q5o&E^#6T+CU> z70u<#`JR0hTM+Ac=5nSJj5`_SnYJ_CXYyxaW}3|Oiz$JrhtZAEmQj>(EyJGw-T&78 z)%ZL8&xzlkezpGE@{8rS%x|IJ8ov{MH~#+dtK;XT@4LU*ecSx?*O#s@SHJB2YW%JD z>-jGizSMs?`6=K7(>s$l2Vc3ptbA_x%>LP{XL8RYo_D@j@#^85zIWB{wLkp&u2{8;rN>;3(AGu~Ca%X#PfPVb$? zJC1inZ$G}-`KI*E+1DptrN3PDe9u$8C+?4UMI~I4i zZwuWrxwYh$$*tm>H8<669l6DR+v&F69iDst?yEoC@zCwjiATJT%^x>C7Jc&LiR?3% z=l`DTzgY6(+RIz7?!HQW<@74$)x1~tUg^Ky|N8nHlXofa)jo88IR8QNqw2?dA9_D5 z{h;&l>&N0xDxa=>-0^AB7x!;#zUTkE_&fZcE`u>+3)32wShg8#?rf%P5^T3vPqMye zoyaD`af|a0mnM%UU%0?E!A(NB!b~E8BEcd?B9Dd3g)M~5gzpO-5zG@` z3nkpe?Zq~ThKn8&*(RJQ^jV;lUxlxeXE|38rvj$}X97nfyA8V#yBFIzmOo56jNS|< z|E2#q|Fh$}+SiGnQa(I>$NcW-+y1v(-`s!A@#fB(^tWAa*S>j`#`4VTDesemk5)W9{y^@*x%+qSOFqbWu;@YUgA4aR-z&ctde7|M z+q*q?3+_(8TXy&S9rHW?Zr{G$di&!Qr@lO1`*@urGbUsFW zeDiVdCx_1-pVL3HeUbWF`0eQTdq0l+-1@8I_p;y0zc>Ec{fqgx+;7p}7Qc&sFZzAt z_vPR7e?R{n^q1%V|Np-j?lXO1iD7eM|G?hQABLdQZpbdmet~T(+gG+;_CgLN zPCZUZ&W)TmxV~^7<4NK@!uyPO39kz8Y#t{bE1n{rIG!2Yhq$V^%DGIr_HssXT5wu$ zKIHh!eu!-Y>qeH@%eVpz(c z&uGcS!EDVugLw&q zzwv$(`r7{G@#jaMxIP{K$ndH3)8X$V)F0lz-2bHhU;UrYV8Iy4w3Yc5OFHWm)}5?xS*;cW+vBz^5a`teZ;QYX8 z$EC$>%kzlm3U5CD1c8|XK?3yxLW0i(4+w<_9}~6^(G*D+o+jiclq$4Z=(5mbAy45L zkzJza#j?d~#Ph}D#czup5IrrDEs`mcF2X0`EWAcQJPhXEysm)+`n^W+o;N#*YlzjL#UgnR*y`8SNNd89y+*W{73H%&5U6$<)u7 z!l=*W!hD?h4D)8@iOiYIf0;Cx7BYTjOk(n2`op-Jv7NDu(U`HGVeNm(|E>St|F!&E z`N#CnqCeOF`2K1AE%^JvuWP?v{Nnm;`+MPUxj%M)Ui@zPZU1}suS-9d{V4yQ_-+1I z+pllF%>1(O%j++5zbyDXeboL~^zq%toKM}Kct6#B z%=?(}k^dvh#|w{-e3|_s{>APW=`WT(zx9mcnZi@uC-#pI zKDzK|-J{PBO&-2~;PNo+(e1|{p5#7V^>p3Su&0-vv_E@ciC`yHD=O-RZj>czfw>{X0o_8t(|) z{eD;YzRClUhe?l2p6q`*?OE*eSuZ}m{Pn8t^`zGwuXny?dt?9R*c;||OWw16WdC&Q z6T_FcUtNCa{;K^Q{pa2vxxW&BFaKfwEBi0@zXC%sgD=D5{~P{S{J;J$``_Mw*8iRV zAOCmj@A5x|zx97@{*m^5_qW;Ko`0M4-Sr3KPn};|e?R+E`}g(Vb^o6Jw`5FbI>|hX zHJ*Jt$9~ScTnRj`d{P4Wf^kCe!ZSopi|!Wl5pNYQ7yl-6pqO2%Gb*+ zkgb*plXj4jm(-G&CGI7DSnRs!Pm#SMzeFNMPl&3BIf$u?9TNQ`;v@1^c&l)Yu!?Yw z&~!mA!3u$?{P*}~@kR3e=RLx^o!5L`++3tLP5V17i2Ye~1@~ zi->;_dnv{%o+G|a{EE1Ugp-7dgs#K{iTx7OC0rz0#2dxViI$3ri5?WWB@!k&OH^I- zmhel#FZ`)|3whkQJUE2dKd|<($S_Z0Y-UJh5NBZeulDc5-#LG||91S5{PXCy&>!PJ zuYX_q-Tdd`U%&s08PXZM88(28NB^__|ME}ffBb(%1`kFf zrg=5gp-ro;@MgHRawf<+}&yJsNKSh3=_@@8u>DS9&JHH+L z{^-ZupW(k)e!c!#_Up>8Q@>99+V`vRm)9@eUtK@df7<*k`f2)e_mBD?2Y*cbS^ewd zFWuj@zvF+m|7!j@?Z@fw?cWo>&-_;Nwd+g!=SiQAe|-Ld=|k}Q)_1LMd)`caJ@wVf zm&aaweIE0i`?=)v!_N=ASo?C?tF5ma-sHde{`&drfH&{nYLoN+w!@3iR|sWV?s{XBX1c6x^m{q<*Q-WU2e?15p^^C)~#EPw-fH1zkBB1 z^7}g;6hGYekn@q+quz%z9_+q<_TI(29Cs()@w%ga$KuYGJ2iK|-`#oF>Tc=XvU_Fs ztsb;Kobq_dQ@7`5U#xv)_*VME*-!Rg&wu~@)8O}y-wc0c|GE6PXXs_v!myRmop}{Y z2%8N@H)j!-6}K|CE0-u2E4M#SF0V9S6Q3Y|5q~6q7XNGh3V{^C=R&3;nxYP3TH+nz z%fx4jXNb=i_mlW1u}N}{)II5ivWoIy@^bQbPLjO2|nbzM{|qGB*D3{eSgm z!%v$pvtCy{?s)k7$?_K(Z+3l*{%-X1_E*_=wNLlmx4bjshQu}ZYvwmZZXdfl=U&!* zi^sXo-#k})R{XT&ncs^uFT|edKYsD}_fw~*OCGA-U2yB>oyLdrAFDjcc=qCX;!~c7 z*Y9fH3B2>-?)rN&cav_)T-|r+(WS?i<*)JGe)XW}$^IwDAL%^|ekAeu@V(X>53lLn zJab#_!QJP*AK1PJ{k;9H;p6ky4$sq{2t6);`1nD^lZP*p-vqyH_~7!@;OD1bBEN!v z#{BVMnDhV2Z`WU2f9L-d{JZ++sjv25SATc^b@9)k|IZl%m<}*R{|)=~=;y~@XMSh? zar|@om(R}=Klpy0|8?-+Q|4BVHC($npK^mL|o#W zM7r2dfn2U4wofcym~Hu5qvi*ZcVRC(pVU5{^o0HCj%O^d>))^XsQ;np)wM_McM`9!zjX5a z^>cFPWiPJ3Jo8G|Rh^qLcf;;~yr28P_o3ut?s^8S){h0A-+gBNc>jHgdnfL^y=8Ta@%D^cN;fuKO}jkzLjC!ci;`DZuI{_iaoP9M z>Pz~UPh5C*=HIFJr}$34J$?M#oXbCN6yMo!r{GrMwKW$L&OJKgemd>c#xrRbHeKq! z;&Q#}mi;}xhs_V}-nV;_^NR6J_N$w(T;AS(r~WSW_0Ja#FBiW4{HFPx?x#K9?*0t^ zRs7@2SL-kQpC^CH{QUk4=eM+PEnhc%mj3+i%bD+9zkdC0{&VF|;=eQoOGa+SiwrXv z_At0G9bo0*_7gM`KPf#yPFVh(te8xVPj;*3%fvd(h3@;%Cn)$gmjsvpyI z(CyGu)|;!#rT0d^*l@Z*g5GDH=Q?L}FX{cz7c;K5_-buvwZ>G}=(YYn-Gkb9w6+p2^n4ipN~gbe}1=d4XAl=?t^g7OO2ESSnfBSwFJvcG&5lVc%o-$+i1$T@}CDa8>%6*Y!6yL~h1hTXaeOLgcxLXTr`Do|}C^@gn;r#jDXb{BL&L z+;_Y5{=7%2Pne&se!A@Wj+gN-WuA9GWqNAy#QX93$A_L}zM20~?(?gUq8|-E)V(!- z_58)Mmk(c=y#D%9?nU_XN6+uSc=Yn@t3|IrzuEJS=fm6&*&n}ss{JDMb>^4fpRa$> z|L*Y~x76>>pVdF&e;)hw?$`aFl|QC_pZeYG`+~2gUpIc|`c?hY z;Rol>6~8wA()`i$+4Oz)+evQ~-*�`dIeu@6Q!K)xX{NxZ<7Ro2-{L&mTRvfBE&r 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

2u?j5^`Y2=~c!F;R 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 literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/f38c61da15f2cb7a39ff02e69f0b00e99f37ec86 b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/f38c61da15f2cb7a39ff02e69f0b00e99f37ec86 new file mode 100644 index 0000000000000000000000000000000000000000..0900eb1352b10576bebda11b0e2b943d77877d57 GIT binary patch literal 66555 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

p|CUUfqAK?1t+tjXQexoFAw@s(GyY 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 rum@O>EoE$4hU literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/fa79819c5de04bc06c69bec3fa7f2e982826ea2f b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/fa79819c5de04bc06c69bec3fa7f2e982826ea2f new file mode 100644 index 0000000000000000000000000000000000000000..2fd41a34fe5b503756e93b68aaa4f90301a78950 GIT binary patch literal 20280 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 literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/decode_wav/fce08de222896ac3a20657a3b4f42d5b6c54a96a b/tensorflow/core/kernels/fuzzing/corpus/decode_wav/fce08de222896ac3a20657a3b4f42d5b6c54a96a new file mode 100644 index 0000000000000000000000000000000000000000..35a99bc97d93c9beeea6a917453685fabf853ab2 GIT binary patch literal 69522 zcmWIYbaQJ+V`K<-40BD(Em06)U|?WmU}SJv!@$rH!N|bG01{z<0&gh&4@$$Rp#T5> z!`P$rXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeD zjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk zz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By z2#kgRO+$d`)`Hv0_njUFK8$@JdVl%73-`A_=)3pr=G$xgu5;g6_ekzV*o*Wh3+{W~ z3B7asp524m`we&B--^3=7vDzs4L$uK0K#=_V?LY7saoNUAcGe=?TfBoku61*mElBjOV#E z=OoYBo?|^f_rkA>4=+qQXLau4#mhIpJZyO!b+7aK<4Yedox48gZq>sDk0YLZc|7H@ z=#%!Ri=JscD|zbp?AD8`Z}UDofA#rv<}J@_?KdnRN=2nDI!pACsG69k*j_Py@iXG_Qd;uA zRTt~5)C50j%xNhJ33HJ|0X_aXLSH1^6=$j>DDRT1m*5bQ5oQoQ zE|DkWE*CHNTKc#67O_)e>>|bjNBJ%Z8pxPww(50jFH-AO?33Ln!z?>h)?T4oNmKE% z+&#IQ@(<*^q>qU`5^ff$lVFs6BIh8RDDg<}AWtrr4EGnlNZ~@!X3@jKQw66BrHSMV zHgWG}&*J#O_guV1T1-+?)KYL6-+sP7e9!pi37iz{=HJNkl{5Tb3M7 zd%i~kvV!0Ews2c<&ElTVe^T^;)Cy?>$w{K+LT3ff3TpE^aocj<;ffW!Euky*NyLTM zjrG?5!~dB6KmFg%e4gziYdZ5OraIVFZt%V2 zx8Og*Th0BB!*i#P2QgQuL>on)nJ)F5wmY|GC+@ z=5gl=h>0;u)`{it$8y-Qv2vZ`KP)UN_DB4I#AS(-61EZt#5_fx3s(zwieHuwR@KAVlDHgI9zA3&})>t7#_J(+j@IS#S zk^2%$q}!xFNm@&s5j!aQK;)LNwGgwwQa)_~36cL|eq!$gZMkb$y#5>iKKeud*Ui5c z|J(lF{^k4Q!?)&dwqN)^2)_IB{@$lIpU-^!{QBHumAkgLi|(C&V)^>lTZK1=U#LF& z_DJ&n<~!ndlJ2a%$Nhxk^{)^AKf8WbeZTOf#Z!^Tmmbf4aq@lZm-An~d}8>>`~K6L z<*y80ZhNKqq5Hen-y{F{ertZd@aoMojhEu@8@_(}nf#mcH^;B{-wnQA|781d{zuNQ z$-h1`^m0`3E$08m{g~zNAL}0%e>nbCVLrj}mq&r$iGKpGD_1BRKXWnTex~E>b$q2l zw*=O5iLv-IsxxbHbn;CURuP*jp&&g$Dp%Z8^oDSv&~HIeVJopSGFmDp)cBP{r0aw# zxX-a4VvAyz;;iH{=99gpYDbM#kV|$_ds`ahQ2k8$6 z?`+;=zG{Ej@v{HLhUY6@M!)TRANbDrrRw9C4<9|{d6n{J{#&)T(_b6Etb43}NBri) zo11Q4zJB@Yy{n10wV&*HzVz{lyI*gH-`H?7^X`U+ho1Soj(nZ-{Kw&ed-d*5|_68^O1P2bab4>=yKf8zKe{PngsuixH&SM}Qdsp4a`r`pf;BpQ$@($%%gT@1A0*xfzUTcc`?LD5>)-i5 zwtrH6zu+DBhfkm6zhC^_%dmjijA{8_=U;h0CVqSVW%cK>ulxS-^1Kz+7e3Ep$I|n+ z@z=laqTgD7PG`8z%+ECKU*j*W`Rj%3n`?dG^DZVG^q) zyA#_s=FLn_%w>%A|N8&MF*>q}arm)qW=vt&%v8j}!>YtKg}s{d6PG848GFvfR_`B?P*B>K>Ys^fnW{j-ATE8TG`ucI_ zr?#(&zgQW}SQaxg{;T@I@pbiwpRZ|J5sw-^8UmvsFd71*Aut*OqaiRF0;3@?8Umvs zFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aux19V03fV=;o}^%~_+Hvqm>( zjc(2w-JFGgbJp~ie_y$O7GN-D-_4Tp*ZOPJyKOHoJym@C^QpwUZJ!@~s(2sy=D|zD z7d=n6K9YRW@^bS#ua9#-u)e+geAy%0`%mv?-&^u<*)zk}hu_-1HGU=fjOk(WZNY1k zFYmlD^YPkO`mfeMb$jsb_Qad-u7A6}>rT?siZ@yB=Y3%P81`Y(d!KhcZw|lS_O|Wg zhOZmHOMaj5RsD};BFrlBTWYbitF(d48M*BW>55yGHmOLfw`itnZd3cK{8RC`qP7Z$ zdW_~}Z5F*Y{jK^hbZxYyG(V_^s+(%;(_L%!*?OCmy{V0!hNg?Ujv9lSq-L3(n^CY) zvwpR)-3bydY@yy}6#4(-YA(uG6 zsW6+!B7v1$eaw^pN&T~Aux38Tc9=7T$AfP_&vf=oM&Uo%Kh}R|`ZJk@nJ1Djo_hkz z+`qSfT>A3kW9(MKiBq$oVbxaOpe-~N5b0%~BVe4nS{-@@r{&%HsJHJ)` zZ23E%p@dO@VaMOizwLjvea-ze|5NwZrtj9@cs~`q>3k9KV%N(oEH@v;~#_gN0 z@BMk2{$}%g`*#^H<~``X`T9!vWriz3S0irN-@WxP;mL|8XCD81T>LctS>N-Yug`z_ z@SXkVov&OU3g0xpUH@L|><{=4w+eMTYn(_9C5e)Di}|7I^@m0)?uvV?=1Peiy;tWc~`XffYw-fq4t zd2@@CQ>s+(gYfLpK+)2c<`?k zULk%#Vw2cgp$5KPoE&W3EDu?H*^1b2v2rk-`v2tr{Qpb-iT{)MC&>`T;>VW8%=0hl z$E(i?p9(&Sd_Mgx;qO7F?JQBu-VAsD3I0$1>-=lpPrg4M{~s_;X1d8B^Ka?zBR?nn z?E78uFOu;E^Gud2Otp+9OwKG@Sy!<2vommC6DSw17r4yr%<+<~k)w*Mhx;d=mdJTg zap4fYZ5+#4;+VfM+W)uv=gHu}V!&a+na;+@yohl-<8!86tO1`{rEBDO-G1k*(wq^~P1RgqMkqNpKTFV!uvRP2T5d$C(mFBR@6Ur^wZ z)(}0-pT)DDtA%SfU#-|=X>I8{Vr2rSxmL5Avd&_f&a{!uk#~o%iTGO4L;QgpeN4~) zhyQ={e?8+W=DkdX|EhjH`Em36u5Sy!iT{xJadGX=&$ID-Je(U{@_;2}V+7Hg}6+c*hcmA3A_s~DRe=fi0{iyzN^jE^aJVtru z^{j6>O?bMwbl7c}<^I3^bMKGdza306T#NZ<3&``)+P@Jy<`p ze`7ZKEBwRe>((z!-%fuw{MGeG`?tkc?f2qu9=@9QYRT)1Z}mRT|0?h^?`O%kDIcD_ zba^`M(V~ZuPxIft{A~C2@<+ed0?!saS^DVs-M6KzcYW#jEcc<|W!~c>4_ltvy*2wH{mtid{JUQ-%U%?}41L}EF7?y;&wD;D ze6ROj;=Rc`vA3LW55KeiRQs*w*P6eR|4sOv^6kbakU;h~VSNb>W*Q;-zzb^lN=;zm8yMI0YVf8KK^V1KpAAWq4{1W&z z;j8-B*I(_v@A~HViS0G}li2%D?n*rLd%pFR{Y#B!OCAS4Qh#**0qb3{oATFRT;F)x z<^lJk4fi8%Nn9(tw)m#`9kF{C@1410cO(AN*)v~G`kb15y5x-gS>E&AmsVWszp?*n z`ZwO-|_!V-llmCIV`2KL6MjMa_T8(lN9Hu|oA zOXq^tWSwTCOBOyhH*HP~-46e#%SS_CGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0q zLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!n24x5^4@y^!I%+foMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$( zGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONV33BuLdHSr zuu*4?hQMeDjE2By2#kinC>RZa(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R K7!3h>hX4Te88qSm literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split/4c01a1504da9de2216894743ecc44424 b/tensorflow/core/kernels/fuzzing/corpus/string_split/4c01a1504da9de2216894743ecc44424 new file mode 100644 index 0000000000..eb84b9e610 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split/4c01a1504da9de2216894743ecc44424 @@ -0,0 +1 @@ +./,abcd.efgh/abcd,efgh.abcd/efgh,abcd.efgh/a \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split/5bf16424630b5afbcffe711fb9834440 b/tensorflow/core/kernels/fuzzing/corpus/string_split/5bf16424630b5afbcffe711fb9834440 new file mode 100644 index 0000000000..4cd522da7b --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split/5bf16424630b5afbcffe711fb9834440 @@ -0,0 +1 @@ +.ab.cd.ef.gh.ab.cd.ef.gh.ab.cd.ef.gh.ab.cd \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split/a7185605aef0a8fd682fcb4656e4a736 b/tensorflow/core/kernels/fuzzing/corpus/string_split/a7185605aef0a8fd682fcb4656e4a736 new file mode 100644 index 0000000000..03cfb6256f --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split/a7185605aef0a8fd682fcb4656e4a736 @@ -0,0 +1 @@ +./, abcde.fghab/cdefg,habcd efgha.bcdef/ghabc \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split/d5606def44fdbb9385dd764612069db0 b/tensorflow/core/kernels/fuzzing/corpus/string_split/d5606def44fdbb9385dd764612069db0 new file mode 100644 index 0000000000000000000000000000000000000000..304b0d66fe08fd1a29827488727702dd9b9bce3e GIT binary patch literal 42 ScmZQbOiE5kO-s)pNCN;-W)Kzt literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split/dbac766f3160de65894bf5153f478146 b/tensorflow/core/kernels/fuzzing/corpus/string_split/dbac766f3160de65894bf5153f478146 new file mode 100644 index 0000000000..a8740444aa --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split/dbac766f3160de65894bf5153f478146 @@ -0,0 +1 @@ +./, ?abcdef.ghabcd/efghab,cdefgh abcdef?ghabcd \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split/e85ff62f6d457666f54a37a19a115a24 b/tensorflow/core/kernels/fuzzing/corpus/string_split/e85ff62f6d457666f54a37a19a115a24 new file mode 100644 index 0000000000..47d551466a --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split/e85ff62f6d457666f54a37a19a115a24 @@ -0,0 +1 @@ +./abc.def/gha.bcd/efg.hab/cde.fgh/abc.def/g \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/00fd47bf73afcb72e7ed51bffd5f5fec b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/00fd47bf73afcb72e7ed51bffd5f5fec new file mode 100644 index 0000000000..f1410e184b --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/00fd47bf73afcb72e7ed51bffd5f5fec @@ -0,0 +1 @@ +./abc./de./fg./ha./bc./de./fg./ha./bc./de./ \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/14908973e6720513a5f37676cb9fcc29 b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/14908973e6720513a5f37676cb9fcc29 new file mode 100644 index 0000000000..e118d2d351 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/14908973e6720513a5f37676cb9fcc29 @@ -0,0 +1 @@ +./, abcde./, fg./, ha./, bc./, de./, fg./, ha \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/2779ba7c4d23eee9f79efa3660084c5d b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/2779ba7c4d23eee9f79efa3660084c5d new file mode 100644 index 0000000000..9a6c809197 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/2779ba7c4d23eee9f79efa3660084c5d @@ -0,0 +1 @@ +./,abcd./,ef./,gh./,ab./,cd./,ef./,gh./,ab./ \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/5bf16424630b5afbcffe711fb9834440 b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/5bf16424630b5afbcffe711fb9834440 new file mode 100644 index 0000000000..4cd522da7b --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/5bf16424630b5afbcffe711fb9834440 @@ -0,0 +1 @@ +.ab.cd.ef.gh.ab.cd.ef.gh.ab.cd.ef.gh.ab.cd \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/89734a96b93275e495a9498b806fafe1 b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/89734a96b93275e495a9498b806fafe1 new file mode 100644 index 0000000000..5301a91d8e --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/89734a96b93275e495a9498b806fafe1 @@ -0,0 +1 @@ +./, ?abcdef./, ?gh./, ?ab./, ?cd./, ?ef./, ?gh \ No newline at end of file diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/d5606def44fdbb9385dd764612069db0 b/tensorflow/core/kernels/fuzzing/corpus/string_split_v2/d5606def44fdbb9385dd764612069db0 new file mode 100644 index 0000000000000000000000000000000000000000..304b0d66fe08fd1a29827488727702dd9b9bce3e GIT binary patch literal 42 ScmZQbOiE5kO-s)pNCN;-W)Kzt literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/2db83ea58639b6d7d585fa12e3947a82 b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/2db83ea58639b6d7d585fa12e3947a82 new file mode 100644 index 0000000000..3de80927d5 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/2db83ea58639b6d7d585fa12e3947a82 @@ -0,0 +1 @@ +6.023e+23 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/36b4a931886b941dc41180050d12ca94 b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/36b4a931886b941dc41180050d12ca94 new file mode 100644 index 0000000000..d531129b28 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/36b4a931886b941dc41180050d12ca94 @@ -0,0 +1 @@ +6.023e-23 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/50a2fabfdd276f573ff97ace8b11c5f4 b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/50a2fabfdd276f573ff97ace8b11c5f4 new file mode 100644 index 0000000000..d81cc0710e --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/50a2fabfdd276f573ff97ace8b11c5f4 @@ -0,0 +1 @@ +42 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/62edb2a1eee34b001652cd86584becf2 b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/62edb2a1eee34b001652cd86584becf2 new file mode 100644 index 0000000000..72f88139d0 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/62edb2a1eee34b001652cd86584becf2 @@ -0,0 +1 @@ +0xabcdef diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/90013d1ec28c46a5c00574e60c70b6fc b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/90013d1ec28c46a5c00574e60c70b6fc new file mode 100644 index 0000000000..c1113b83e8 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/90013d1ec28c46a5c00574e60c70b6fc @@ -0,0 +1 @@ +3.14159265359 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/94f3e3cee6957ce5815326d6788c85f4 b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/94f3e3cee6957ce5815326d6788c85f4 new file mode 100644 index 0000000000..320aa3f00e --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/94f3e3cee6957ce5815326d6788c85f4 @@ -0,0 +1 @@ +0.69314718056 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/96f547bc04bb913da0bc08915238ebd8 b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/96f547bc04bb913da0bc08915238ebd8 new file mode 100644 index 0000000000..51b7b732f6 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/96f547bc04bb913da0bc08915238ebd8 @@ -0,0 +1 @@ +6.023e23 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/d3a903d18fc11e1f35c572ad4da690ed b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/d3a903d18fc11e1f35c572ad4da690ed new file mode 100644 index 0000000000..9a0be0764b --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/d3a903d18fc11e1f35c572ad4da690ed @@ -0,0 +1 @@ +1.61803 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/e3b629c92af44260c189deb32d6f06f3 b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/e3b629c92af44260c189deb32d6f06f3 new file mode 100644 index 0000000000..6a0e60d48b --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/e3b629c92af44260c189deb32d6f06f3 @@ -0,0 +1 @@ +-42 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/f03eecf3bcfe4967a1888156a3115c8d b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/f03eecf3bcfe4967a1888156a3115c8d new file mode 100644 index 0000000000..ea9cd255bc --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/f03eecf3bcfe4967a1888156a3115c8d @@ -0,0 +1 @@ +6.023E+23 diff --git a/tensorflow/core/kernels/fuzzing/corpus/string_to_number/fa54ca9186f77122ae2a82684a062e16 b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/fa54ca9186f77122ae2a82684a062e16 new file mode 100644 index 0000000000..00f1e2ed8f --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/corpus/string_to_number/fa54ca9186f77122ae2a82684a062e16 @@ -0,0 +1 @@ +2.71828182846 diff --git a/tensorflow/core/kernels/fuzzing/dictionaries/decode_json_example.dict b/tensorflow/core/kernels/fuzzing/dictionaries/decode_json_example.dict new file mode 100644 index 0000000000..5fe4ca23d1 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/dictionaries/decode_json_example.dict @@ -0,0 +1,6 @@ +"features" +"feature" +"bytes_list" +"float_list" +"int64_list" +"value" diff --git a/tensorflow/core/kernels/fuzzing/dictionaries/decode_png.dict b/tensorflow/core/kernels/fuzzing/dictionaries/decode_png.dict new file mode 100644 index 0000000000..d795ae7f71 --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/dictionaries/decode_png.dict @@ -0,0 +1,50 @@ +header_87a="87a" +header_89a="89a" +header_gif="GIF" +header_jfif="JFIF\x00" +header_jfxx="JFXX\x00" +header_png="\x89PNG\x0d\x0a\x1a\x0a" +marker_2c="," +marker_3b=";" +section_2101="!\x01\x12" +section_21f9="!\xf9\x04" +section_21fe="!\xfe" +section_21ff="!\xff\x11" +section_IDAT="IDAT" +section_IEND="IEND" +section_IHDR="IHDR" +section_PLTE="PLTE" +section_bKGD="bKGD" +section_cHRM="cHRM" +section_fRAc="fRAc" +section_ffc0="\xff\xc0" +section_ffc2="\xff\xc2" +section_ffc4="\xff\xc4" +section_ffd0="\xff\xd0" +section_ffd8="\xff\xd8" +section_ffd9="\xff\xd9" +section_ffda="\xff\xda" +section_ffdb="\xff\xdb" +section_ffdd="\xff\xdd" +section_ffe0="\xff\xe0" +section_ffe1="\xff\xe1" +section_fffe="\xff\xfe" +section_gAMA="gAMA" +section_gIFg="gIFg" +section_gIFt="gIFt" +section_gIFx="gIFx" +section_hIST="hIST" +section_iCCP="iCCP" +section_iTXt="iTXt" +section_oFFs="oFFs" +section_pCAL="pCAL" +section_pHYs="pHYs" +section_sBIT="sBIT" +section_sCAL="sCAL" +section_sPLT="sPLT" +section_sRGB="sRGB" +section_sTER="sTER" +section_tEXt="tEXt" +section_tIME="tIME" +section_tRNS="tRNS" +section_zTXt="zTXt" diff --git a/tensorflow/core/kernels/fuzzing/dictionaries/decode_wav.dict b/tensorflow/core/kernels/fuzzing/dictionaries/decode_wav.dict new file mode 100644 index 0000000000..eab65386ce --- /dev/null +++ b/tensorflow/core/kernels/fuzzing/dictionaries/decode_wav.dict @@ -0,0 +1,4 @@ +header_RIFF="RIFF" +header_WAVE="WAVE" +section_fmt="fmt " +section_data="data" diff --git a/tensorflow/core/kernels/fuzzing/encode_base64_fuzz.cc b/tensorflow/core/kernels/fuzzing/encode_base64_fuzz.cc index a8f07f4bad..b8d779fb13 100644 --- a/tensorflow/core/kernels/fuzzing/encode_base64_fuzz.cc +++ b/tensorflow/core/kernels/fuzzing/encode_base64_fuzz.cc @@ -19,7 +19,7 @@ limitations under the License. namespace tensorflow { namespace fuzzing { -class FuzzEncodeBase64 : public FuzzSession { +class FuzzEncodeBase64 : public FuzzStringInputOp { SINGLE_INPUT_OP_BUILDER(DT_STRING, EncodeBase64); }; diff --git a/tensorflow/core/kernels/fuzzing/fuzz_session.h b/tensorflow/core/kernels/fuzzing/fuzz_session.h index 9777be1ae8..57d562ddf4 100644 --- a/tensorflow/core/kernels/fuzzing/fuzz_session.h +++ b/tensorflow/core/kernels/fuzzing/fuzz_session.h @@ -72,11 +72,11 @@ class FuzzSession { // By convention, the graph should have inputs named "input1", ... // "inputN", and one output node, named "output". // Users of FuzzSession should override this method to create their graph. - virtual void BuildGraph(const Scope& scope) {} + virtual void BuildGraph(const Scope& scope) = 0; // Implements the logic that converts an opaque byte buffer // from the fuzzer to Tensor inputs to the graph. Users must override. - virtual void FuzzImpl(const uint8_t* data, size_t size) {} + virtual void FuzzImpl(const uint8_t* data, size_t size) = 0; // Initializes the FuzzSession. Not safe for multithreading. // Separate init function because the call to virtual BuildGraphDef diff --git a/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc b/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc index 87a548a999..2564f8ed03 100644 --- a/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc +++ b/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc @@ -37,8 +37,7 @@ class FuzzStringSplit : public FuzzSession { // The spec for split is that the delimeter should be 0 or 1 characters. // Naturally, fuzz it with something larger. (This omits the possibility // of handing it a > int32_max size string, which should be tested for in - // an - // explicit test). + // an explicit test). size_t delim_len = static_cast(data[0]); if (delim_len > size) { delim_len = size - 1; diff --git a/tensorflow/core/kernels/fuzzing/tf_ops_fuzz_target_lib.bzl b/tensorflow/core/kernels/fuzzing/tf_ops_fuzz_target_lib.bzl index f752b59568..e932213359 100644 --- a/tensorflow/core/kernels/fuzzing/tf_ops_fuzz_target_lib.bzl +++ b/tensorflow/core/kernels/fuzzing/tf_ops_fuzz_target_lib.bzl @@ -1,13 +1,25 @@ """Fuzzing template for TensorFlow ops.""" def tf_ops_fuzz_target_lib(name): - native.cc_library( - name = name + "_fuzz_lib", - srcs = [name + "_fuzz.cc"], - deps = [ - "//tensorflow/core/kernels/fuzzing:fuzz_session", - "//tensorflow/cc:cc_ops", - ], - tags = ["no_windows"], - alwayslink = 1, - ) + native.cc_library( + name = name + "_fuzz_lib", + srcs = [name + "_fuzz.cc"], + deps = [ + "//tensorflow/core/kernels/fuzzing:fuzz_session", + "//tensorflow/cc:cc_ops", + ], + tags = ["no_windows"], + alwayslink = 1, + ) + +def tf_oss_fuzz_corpus(name): + native.filegroup( + name = name + "_corpus", + srcs = native.glob(["corpus/" + name + "/*"]), + ) + +def tf_oss_fuzz_dict(name): + native.filegroup( + name = name + "_dict", + srcs = native.glob(["dictionaries/" + name + ".dict"]), + ) diff --git a/tensorflow/core/kernels/list_kernels.cc b/tensorflow/core/kernels/list_kernels.cc index 5f244b1b10..42fad1d4b0 100644 --- a/tensorflow/core/kernels/list_kernels.cc +++ b/tensorflow/core/kernels/list_kernels.cc @@ -483,9 +483,19 @@ REGISTER_KERNEL_BUILDER(Name("TensorListGetItem").Device(DEVICE_CPU), #if GOOGLE_CUDA -REGISTER_KERNEL_BUILDER( - Name("TensorListGetItem").Device(DEVICE_GPU).HostMemory("index"), - TensorListGetItem); +#define REGISTER_TENSOR_LIST_GET_ITEM_GPU(T) \ + REGISTER_KERNEL_BUILDER(Name("TensorListGetItem") \ + .TypeConstraint("element_dtype") \ + .Device(DEVICE_GPU) \ + .HostMemory("index"), \ + TensorListGetItem); + +TF_CALL_GPU_NUMBER_TYPES(REGISTER_TENSOR_LIST_GET_ITEM_GPU); +TF_CALL_complex64(REGISTER_TENSOR_LIST_GET_ITEM_GPU); +TF_CALL_complex128(REGISTER_TENSOR_LIST_GET_ITEM_GPU); +TF_CALL_int64(REGISTER_TENSOR_LIST_GET_ITEM_GPU); +REGISTER_TENSOR_LIST_GET_ITEM_GPU(bfloat16) +#undef REGISTER_TENSOR_LIST_GET_ITEM_GPU #endif // GOOGLE_CUDA @@ -537,9 +547,19 @@ REGISTER_KERNEL_BUILDER(Name("TensorListSetItem").Device(DEVICE_CPU), #if GOOGLE_CUDA -REGISTER_KERNEL_BUILDER( - Name("TensorListSetItem").Device(DEVICE_GPU).HostMemory("index"), - TensorListSetItem); +#define REGISTER_TENSOR_LIST_SET_ITEM_GPU(T) \ + REGISTER_KERNEL_BUILDER(Name("TensorListSetItem") \ + .TypeConstraint("element_dtype") \ + .Device(DEVICE_GPU) \ + .HostMemory("index"), \ + TensorListSetItem); + +TF_CALL_GPU_NUMBER_TYPES(REGISTER_TENSOR_LIST_SET_ITEM_GPU); +TF_CALL_complex64(REGISTER_TENSOR_LIST_SET_ITEM_GPU); +TF_CALL_complex128(REGISTER_TENSOR_LIST_SET_ITEM_GPU); +TF_CALL_int64(REGISTER_TENSOR_LIST_SET_ITEM_GPU); +REGISTER_TENSOR_LIST_SET_ITEM_GPU(bfloat16) +#undef REGISTER_TENSOR_LIST_SET_ITEM_GPU #endif // GOOGLE_CUDA @@ -660,7 +680,11 @@ REGISTER_TENSOR_LIST_PUSH_BACK_BATCH_CPU(bfloat16); REGISTER_KERNEL_BUILDER(Name("TensorListGather") \ .TypeConstraint("element_dtype") \ .Device(DEVICE_CPU), \ - TensorListGather) + TensorListGather) \ + REGISTER_KERNEL_BUILDER(Name("TensorListConcat") \ + .TypeConstraint("element_dtype") \ + .Device(DEVICE_CPU), \ + TensorListConcat) TF_CALL_POD_STRING_TYPES(REGISTER_TENSOR_LIST_STACK_CPU); REGISTER_TENSOR_LIST_STACK_CPU(quint8); @@ -680,7 +704,11 @@ REGISTER_TENSOR_LIST_STACK_CPU(bfloat16); REGISTER_KERNEL_BUILDER(Name("TensorListScatter") \ .TypeConstraint("element_dtype") \ .Device(DEVICE_CPU), \ - TensorListScatter) + TensorListScatter) \ + REGISTER_KERNEL_BUILDER(Name("TensorListSplit") \ + .TypeConstraint("element_dtype") \ + .Device(DEVICE_CPU), \ + TensorListSplit) TF_CALL_POD_STRING_TYPES(REGISTER_TENSOR_LIST_FROM_TENSOR_CPU); REGISTER_TENSOR_LIST_FROM_TENSOR_CPU(quint8); diff --git a/tensorflow/core/kernels/list_kernels.cu.cc b/tensorflow/core/kernels/list_kernels.cu.cc index a00bf700ca..23f552642c 100644 --- a/tensorflow/core/kernels/list_kernels.cu.cc +++ b/tensorflow/core/kernels/list_kernels.cu.cc @@ -45,7 +45,12 @@ typedef Eigen::GpuDevice GPUDevice; .TypeConstraint("element_dtype") \ .Device(DEVICE_GPU) \ .HostMemory("indices"), \ - TensorListGather) + TensorListGather) \ + REGISTER_KERNEL_BUILDER(Name("TensorListConcat") \ + .TypeConstraint("element_dtype") \ + .Device(DEVICE_GPU) \ + .HostMemory("lengths"), \ + TensorListConcat) TF_CALL_GPU_NUMBER_TYPES(REGISTER_TENSOR_LIST_STACK_GPU); REGISTER_TENSOR_LIST_STACK_GPU(bfloat16); @@ -82,7 +87,13 @@ REGISTER_TENSOR_LIST_PUSH_BACK_BATCH_GPU(bool); .Device(DEVICE_GPU) \ .HostMemory("element_shape") \ .HostMemory("indices"), \ - TensorListScatter) + TensorListScatter) \ + REGISTER_KERNEL_BUILDER(Name("TensorListSplit") \ + .TypeConstraint("element_dtype") \ + .Device(DEVICE_GPU) \ + .HostMemory("element_shape") \ + .HostMemory("lengths"), \ + TensorListSplit) TF_CALL_GPU_NUMBER_TYPES(REGISTER_TENSOR_LIST_FROM_TENSOR_GPU); REGISTER_TENSOR_LIST_FROM_TENSOR_GPU(bfloat16); diff --git a/tensorflow/core/kernels/list_kernels.h b/tensorflow/core/kernels/list_kernels.h index c2591f5314..686679474c 100644 --- a/tensorflow/core/kernels/list_kernels.h +++ b/tensorflow/core/kernels/list_kernels.h @@ -30,6 +30,8 @@ limitations under the License. #include "tensorflow/core/kernels/concat_lib.h" #include "tensorflow/core/lib/core/coding.h" #include "tensorflow/core/lib/core/errors.h" +#include "tensorflow/core/lib/gtl/array_slice.h" +#include "tensorflow/core/util/tensor_ops_util.h" #include "tensorflow/core/util/util.h" namespace tensorflow { @@ -76,26 +78,30 @@ class TensorListStack : public OpKernel { ~TensorListStack() {} void Compute(OpKernelContext* c) override { - const TensorList* l = c->input(0).scalar()().get(); - OP_REQUIRES(c, l != nullptr, + const TensorList* tensor_list = + c->input(0).scalar()().get(); + OP_REQUIRES(c, tensor_list != nullptr, errors::InvalidArgument( "Input handle is not a list. Saw: '", c->input(0).scalar()().DebugString(), "'")); - OP_REQUIRES(c, element_dtype_ == l->element_dtype, - errors::InvalidArgument("Invalid data types; op elements ", - DataTypeString(element_dtype_), - " but list elements ", - DataTypeString(l->element_dtype))); - OP_REQUIRES(c, !l->tensors.empty() || l->element_shape.IsFullyDefined(), - errors::InvalidArgument("Tried to stack elements of a empty ", - "list with non-fully-defined shape: ", - l->element_shape.DebugString())); + OP_REQUIRES( + c, element_dtype_ == tensor_list->element_dtype, + errors::InvalidArgument( + "Invalid data types; op elements ", DataTypeString(element_dtype_), + " but list elements ", DataTypeString(tensor_list->element_dtype))); + OP_REQUIRES( + c, + !tensor_list->tensors.empty() || + tensor_list->element_shape.IsFullyDefined(), + errors::InvalidArgument("Tried to stack elements of a empty ", + "list with non-fully-defined shape: ", + tensor_list->element_shape.DebugString())); if (num_elements_ != -1) { - OP_REQUIRES(c, l->tensors.size() == num_elements_, - errors::InvalidArgument("Operation expected a list with ", - num_elements_, - " elements but got a list with ", - l->tensors.size(), " elements.")); + OP_REQUIRES(c, tensor_list->tensors.size() == num_elements_, + errors::InvalidArgument( + "Operation expected a list with ", num_elements_, + " elements but got a list with ", + tensor_list->tensors.size(), " elements.")); } // Compute the shape of the output tensor. // If `element_shape` is fully-defined it gets used. It is assumed that all @@ -104,11 +110,11 @@ class TensorListStack : public OpKernel { // tensor is used and it is checked that all other tensors have the same // shape. TensorShape resulting_shape; - if (!l->element_shape.AsTensorShape(&resulting_shape)) { - const Tensor& t = l->tensors[0]; + if (!tensor_list->element_shape.AsTensorShape(&resulting_shape)) { + const Tensor& t = tensor_list->tensors[0]; resulting_shape = t.shape(); - for (int i = 1; i < l->tensors.size(); ++i) { - const Tensor& t = l->tensors[i]; + for (int i = 1; i < tensor_list->tensors.size(); ++i) { + const Tensor& t = tensor_list->tensors[i]; OP_REQUIRES(c, t.shape() == resulting_shape, errors::InvalidArgument( "Tried to stack tensors with unequal shapes: ", @@ -116,7 +122,7 @@ class TensorListStack : public OpKernel { t.shape().DebugString())); } } - resulting_shape.InsertDim(0, l->tensors.size()); + resulting_shape.InsertDim(0, tensor_list->tensors.size()); Tensor* output; OP_REQUIRES_OK(c, c->allocate_output(0, resulting_shape, &output)); if (output->NumElements() == 0) { @@ -124,8 +130,8 @@ class TensorListStack : public OpKernel { } ConstMatrixVector inputs_flat; - inputs_flat.reserve(l->tensors.size()); - for (const auto& t : l->tensors) { + inputs_flat.reserve(tensor_list->tensors.size()); + for (const auto& t : tensor_list->tensors) { inputs_flat.emplace_back(new typename TTypes::ConstMatrix( t.shaped({1, t.NumElements()}))); } @@ -145,6 +151,200 @@ class TensorListStack : public OpKernel { DataType element_dtype_; }; +template +class TensorListConcat : public OpKernel { + public: + using ConstMatrixVector = + std::vector::ConstMatrix>>; + explicit TensorListConcat(OpKernelConstruction* c) : OpKernel(c) { + OP_REQUIRES_OK(c, c->GetAttr("element_dtype", &element_dtype_)); + } + + ~TensorListConcat() {} + + void Compute(OpKernelContext* c) override { + // Check that the input Variant tensor is indeed a TensorList and has the + // correct element type. + const TensorList* tensor_list = + c->input(0).scalar()().get(); + OP_REQUIRES(c, tensor_list != nullptr, + errors::InvalidArgument( + "Input handle is not a list. Saw: '", + c->input(0).scalar()().DebugString(), "'")); + OP_REQUIRES( + c, element_dtype_ == tensor_list->element_dtype, + errors::InvalidArgument( + "Invalid data types; op elements ", DataTypeString(element_dtype_), + " but list elements ", DataTypeString(tensor_list->element_dtype))); + // If the TensorList is empty, its element_shape must be fully defined + // except for the first dimension. + PartialTensorShape shape_except_first_dim; + if (!tensor_list->element_shape.unknown_rank()) { + OP_REQUIRES(c, tensor_list->element_shape.dims() >= 1, + errors::InvalidArgument( + "Concat requires elements to be at least vectors, ", + "found scalars instead.")); + shape_except_first_dim = PartialTensorShape( + gtl::ArraySlice(tensor_list->element_shape.dim_sizes()) + .subspan(1)); + } + OP_REQUIRES(c, + !tensor_list->tensors.empty() || + shape_except_first_dim.IsFullyDefined(), + errors::InvalidArgument( + "All except the first dimension must be fully defined ", + "when concating an empty tensor list. element_shape: ", + tensor_list->element_shape.DebugString())); + // 1. Compute the shape of the output tensor. + // If `shape_except_first_dim` is fully-defined we just prepend the leading + // dim to it. Otherwise we use the shape of the first element tensor and + // check to make sure shapes of all tensors are compatible. + TensorShape output_shape; + if (!shape_except_first_dim.AsTensorShape(&output_shape)) { + const Tensor& element_tensor = tensor_list->tensors[0]; + OP_REQUIRES( + c, TensorShapeUtils::IsVectorOrHigher(element_tensor.shape()), + errors::InvalidArgument("Concat saw a scalar shape at index ", 0, + " but requires at least vectors.")); + output_shape = + TensorShape(gtl::ArraySlice(element_tensor.shape().dim_sizes()) + .subspan(1)); + for (int i = 1; i < tensor_list->tensors.size(); ++i) { + const Tensor& element_tensor = tensor_list->tensors[i]; + OP_REQUIRES( + c, TensorShapeUtils::IsVectorOrHigher(element_tensor.shape()), + errors::InvalidArgument("Concat saw a scalar shape at index ", i, + " but requires at least vectors.")); + TensorShape actual_shape( + gtl::ArraySlice(element_tensor.shape().dim_sizes()) + .subspan(1)); + OP_REQUIRES(c, actual_shape.dim_sizes() == output_shape.dim_sizes(), + errors::InvalidArgument( + "Tried to concat tensors with unequal shapes: ", + output_shape.DebugString(), " vs ", + actual_shape.DebugString())); + } + } + // 2. Build the lengths_tensor and leading dim of the output tensor by + // iterating over all element tensors. + Tensor* lengths_tensor = nullptr; + OP_REQUIRES_OK( + c, + c->allocate_output( + 1, TensorShape({static_cast(tensor_list->tensors.size())}), + &lengths_tensor)); + auto lengths_tensor_vec = lengths_tensor->vec(); + int64 leading_dim = 0; + for (size_t i = 0; i < tensor_list->tensors.size(); i++) { + int64 dim = tensor_list->tensors[i].shape().dim_size(0); + leading_dim += dim; + lengths_tensor_vec(i) = dim; + } + output_shape.InsertDim(0, leading_dim); + Tensor* output; + // 3. Allocate the output tensor and fill it up with the concated element + // tensors. + OP_REQUIRES_OK(c, c->allocate_output(0, output_shape, &output)); + if (output->NumElements() == 0) { + return; + } + + ConstMatrixVector inputs_flat; + inputs_flat.reserve(tensor_list->tensors.size()); + for (const auto& element_tensor : tensor_list->tensors) { + inputs_flat.emplace_back(new typename TTypes::ConstMatrix( + element_tensor.shaped({1, element_tensor.NumElements()}))); + } + auto output_flat = output->shaped({1, output->NumElements()}); + +#if GOOGLE_CUDA + if (std::is_same::value) { + ConcatGPU(c, inputs_flat, output, &output_flat); + return; + } +#endif // GOOGLE_CUDA + ConcatCPU(c->device(), inputs_flat, &output_flat); + } + + private: + DataType element_dtype_; +}; + +template +class TensorListSplit : public OpKernel { + public: + TensorListSplit(OpKernelConstruction* c) : OpKernel(c) {} + + void Compute(OpKernelContext* c) override { + Tensor* output_tensor; + AllocatorAttributes attr; + attr.set_on_host(true); + OP_REQUIRES_OK(c, c->allocate_output(0, {}, &output_tensor, attr)); + PartialTensorShape element_shape; + OP_REQUIRES_OK(c, TensorShapeFromTensor(c->input(1), &element_shape)); + OP_REQUIRES(c, element_shape.unknown_rank() || element_shape.dims() >= 1, + errors::InvalidArgument( + "TensorListSplit requires element_shape to be at least of ", + "rank 1, but saw: ", element_shape.DebugString())); + TensorList output_list; + const Tensor& input_tensor = c->input(0); + output_list.element_dtype = input_tensor.dtype(); + OP_REQUIRES(c, TensorShapeUtils::IsVectorOrHigher(input_tensor.shape()), + errors::InvalidArgument( + "Tensor must be at least a vector, but saw shape: ", + input_tensor.shape().DebugString())); + TensorShape tensor_shape_without_first_dim(input_tensor.shape()); + tensor_shape_without_first_dim.RemoveDim(0); + PartialTensorShape element_shape_without_first_dim; + if (!element_shape.unknown_rank()) { + element_shape_without_first_dim = + PartialTensorShape(element_shape.dim_sizes()); + element_shape_without_first_dim.RemoveDim(0); + } + OP_REQUIRES(c, + element_shape_without_first_dim.IsCompatibleWith( + tensor_shape_without_first_dim), + errors::InvalidArgument( + "tensor shape ", input_tensor.shape().DebugString(), + " is not compatible with element_shape ", + element_shape.DebugString())); + output_list.element_shape = element_shape; + const Tensor& lengths = c->input(2); + OP_REQUIRES(c, TensorShapeUtils::IsVector(lengths.shape()), + errors::InvalidArgument( + "Expected lengths to be a vector, received shape: ", + lengths.shape().DebugString())); + output_list.tensors.reserve(lengths.shape().dim_size(0)); + int64 start = 0; + int64 end = 0; + for (int i = 0; i < lengths.shape().dim_size(0); ++i) { + int64 length = lengths.vec()(i); + OP_REQUIRES( + c, length >= 0, + errors::InvalidArgument("Invalid value in lengths: ", length)); + end = start + length; + OP_REQUIRES(c, end <= input_tensor.shape().dim_size(0), + errors::InvalidArgument("Attempting to slice [", start, ", ", + end, "] from tensor with length ", + input_tensor.shape().dim_size(0))); + Tensor tmp = input_tensor.Slice(start, end); + start = end; + // TODO(apassos) maybe not always align; but weird compiler bugs seem to + // prevent this. + Tensor aligned; + OP_REQUIRES_OK(c, c->allocate_temp(tmp.dtype(), tmp.shape(), &aligned)); + aligned.flat().device(c->eigen_device()) = + tmp.unaligned_flat(); + output_list.tensors.emplace_back(aligned); + } + OP_REQUIRES(c, end == input_tensor.shape().dim_size(0), + errors::InvalidArgument( + "Unused values in tensor. Length of tensor: ", + input_tensor.shape().dim_size(0), " Values used: ", end)); + output_tensor->scalar()() = std::move(output_list); + } +}; + template class TensorListGather : public OpKernel { public: @@ -155,22 +355,25 @@ class TensorListGather : public OpKernel { } void Compute(OpKernelContext* c) override { - const TensorList* l = c->input(0).scalar()().get(); - OP_REQUIRES(c, l != nullptr, + const TensorList* tensor_list = + c->input(0).scalar()().get(); + OP_REQUIRES(c, tensor_list != nullptr, errors::InvalidArgument( "Input handle is not a list. Saw: '", c->input(0).scalar()().DebugString(), "'")); - OP_REQUIRES(c, element_dtype_ == l->element_dtype, - errors::InvalidArgument("Invalid data types; op elements ", - DataTypeString(element_dtype_), - " but list elements ", - DataTypeString(l->element_dtype))); + OP_REQUIRES( + c, element_dtype_ == tensor_list->element_dtype, + errors::InvalidArgument( + "Invalid data types; op elements ", DataTypeString(element_dtype_), + " but list elements ", DataTypeString(tensor_list->element_dtype))); Tensor indices = c->input(1); - OP_REQUIRES(c, - indices.NumElements() > 0 || l->element_shape.IsFullyDefined(), - errors::InvalidArgument("Tried to gather 0-elements from " - "a list with non-fully-defined shape: ", - l->element_shape.DebugString())); + OP_REQUIRES( + c, + indices.NumElements() > 0 || + tensor_list->element_shape.IsFullyDefined(), + errors::InvalidArgument("Tried to gather 0-elements from " + "a list with non-fully-defined shape: ", + tensor_list->element_shape.DebugString())); // Compute the shape of the output tensor. // If `element_shape` is fully-defined it gets used. It is assumed that all // requested tensors have the same shape. @@ -178,17 +381,17 @@ class TensorListGather : public OpKernel { // tensor is used and it is checked that all other tensors have the same // shape. TensorShape resulting_shape; - if (!l->element_shape.AsTensorShape(&resulting_shape)) { + if (!tensor_list->element_shape.AsTensorShape(&resulting_shape)) { const int i = indices.flat()(0); OP_REQUIRES( - c, i < l->tensors.size(), + c, i < tensor_list->tensors.size(), errors::InvalidArgument("Index ", i, " out o range; list only has ", - l->tensors.size(), " elements.")); - const Tensor& t = l->tensors[i]; + tensor_list->tensors.size(), " elements.")); + const Tensor& t = tensor_list->tensors[i]; resulting_shape = t.shape(); for (int index = 1; index < indices.NumElements(); ++index) { const int i = indices.flat()(index); - const Tensor& t = l->tensors[i]; + const Tensor& t = tensor_list->tensors[i]; OP_REQUIRES(c, t.shape() == resulting_shape, errors::InvalidArgument( "Tried to gather elements with unequal shapes: ", @@ -204,14 +407,14 @@ class TensorListGather : public OpKernel { } ConstMatrixVector inputs_flat; - inputs_flat.reserve(l->tensors.size()); + inputs_flat.reserve(tensor_list->tensors.size()); for (int index = 0; index < indices.NumElements(); ++index) { const int i = indices.flat()(index); OP_REQUIRES( - c, i < l->tensors.size(), + c, i < tensor_list->tensors.size(), errors::InvalidArgument("Index ", i, " out o range; list only has ", - l->tensors.size(), " elements.")); - const Tensor& t = l->tensors[i]; + tensor_list->tensors.size(), " elements.")); + const Tensor& t = tensor_list->tensors[i]; inputs_flat.emplace_back(new typename TTypes::ConstMatrix( t.shaped({1, t.NumElements()}))); } @@ -289,13 +492,13 @@ class TensorListScatter : public OpKernel { PartialTensorShape element_shape; OP_REQUIRES_OK(c, TensorShapeFromTensor(c->input(2), &element_shape)); TensorList output_list; - const Tensor& t = c->input(0); - output_list.element_dtype = t.dtype(); - OP_REQUIRES(c, TensorShapeUtils::IsVectorOrHigher(t.shape()), + const Tensor& input_tensor = c->input(0); + output_list.element_dtype = input_tensor.dtype(); + OP_REQUIRES(c, TensorShapeUtils::IsVectorOrHigher(input_tensor.shape()), errors::InvalidArgument( "Tensor must be at least a vector, but saw shape: ", - t.shape().DebugString())); - TensorShape output_shape(t.shape()); + input_tensor.shape().DebugString())); + TensorShape output_shape(input_tensor.shape()); output_shape.RemoveDim(0); OP_REQUIRES(c, element_shape.IsCompatibleWith(output_shape), errors::InvalidArgument( @@ -305,11 +508,11 @@ class TensorListScatter : public OpKernel { output_list.tensors.reserve(indices.NumElements()); for (int index = 0; index < indices.NumElements(); ++index) { const int i = indices.flat()(index); - OP_REQUIRES(c, i < t.shape().dim_size(0), - errors::InvalidArgument("Trying to scatter index ", i, - " from tensor with ", - t.shape().dim_size(0), " rows.")); - Tensor tmp = t.Slice(i, i + 1); + OP_REQUIRES(c, i < input_tensor.shape().dim_size(0), + errors::InvalidArgument( + "Trying to scatter index ", i, " from tensor with ", + input_tensor.shape().dim_size(0), " rows.")); + Tensor tmp = input_tensor.Slice(i, i + 1); TensorShape tmp_shape = tmp.shape(); tmp_shape.RemoveDim(0); OP_REQUIRES(c, tmp.CopyFrom(tmp, tmp_shape), @@ -357,40 +560,10 @@ Status TensorListBinaryAdd(OpKernelContext* c, const TensorList& a, for (int i = 0; i < a.tensors.size(); ++i) { const Tensor& a_tensor = a.tensors[i]; const Tensor& b_tensor = b.tensors[i]; - if (a_tensor.dtype() == DT_INVALID) { - out->tensors.push_back(b_tensor); - continue; - } - if (b_tensor.dtype() == DT_INVALID) { - out->tensors.push_back(a_tensor); - continue; - } - if (a_tensor.shape() != b_tensor.shape()) { - // TODO(apassos) support broadcasting additions here? - return errors::InvalidArgument( - "Trying to add two tensors with incompatible element shapes. " - "One is ", - a_tensor.shape().DebugString(), " and the other is ", - b_tensor.shape().DebugString(), " in position ", i); - } Tensor out_tensor; TF_RETURN_IF_ERROR( - c->allocate_temp(a_tensor.dtype(), a_tensor.shape(), &out_tensor)); + BinaryAddTensors(c, a_tensor, b_tensor, &out_tensor)); out->tensors.push_back(out_tensor); - switch (out_tensor.dtype()) { -#define DTYPE_CASE(dtype) \ - case DataTypeToEnum::value: \ - out_tensor.flat().device(c->eigen_device()) = \ - a_tensor.flat() + b_tensor.flat(); \ - break; - - TF_CALL_NUMBER_TYPES(DTYPE_CASE) - -#undef DTYPE_CASE - default: - return errors::InvalidArgument("Trying to add unsupported dtype ", - out_tensor.dtype()); - } } return Status::OK(); } @@ -403,46 +576,7 @@ Status TensorListZerosLike(OpKernelContext* c, const TensorList& x, y->tensors.reserve(x.tensors.size()); for (const Tensor& t : x.tensors) { Tensor out_tensor; - AllocatorAttributes attr; - if (t.dtype() == DT_VARIANT) { - attr.set_on_host(true); - } - TF_RETURN_IF_ERROR( - c->allocate_temp(t.dtype(), t.shape(), &out_tensor, attr)); - switch (out_tensor.dtype()) { -#define DTYPE_CASE(dtype) \ - case DataTypeToEnum::value: \ - out_tensor.flat().device(c->eigen_device()) = \ - out_tensor.flat().constant(dtype(0)); \ - break; - - TF_CALL_POD_TYPES(DTYPE_CASE) - -#undef DTYPE_CASE - - case DT_INVALID: { - // Uninitialized tensor in the TensorList. - out_tensor = Tensor(DT_INVALID); - break; - } - case DataTypeToEnum::value: { - const TensorList* inner_x = t.scalar()().get(); - if (inner_x == nullptr) { - return errors::InvalidArgument("Input handle is not a list. Saw: '", - t.scalar()().DebugString(), - "'"); - } - TensorList inner_y; - TF_RETURN_IF_ERROR(TensorListZerosLike(c, *inner_x, &inner_y)); - out_tensor.scalar()() = std::move(inner_y); - break; - } - - default: - return errors::InvalidArgument( - "Trying to compute zeros_like for unsupported dtype ", - DataTypeString(out_tensor.dtype())); - } + TF_RETURN_IF_ERROR(ZerosLikeTensor(c, t, &out_tensor)); y->tensors.emplace_back(out_tensor); } return Status::OK(); diff --git a/tensorflow/core/kernels/maxpooling_op_gpu.cu.cc b/tensorflow/core/kernels/maxpooling_op_gpu.cu.cc index 0c7a236b2f..89ffe6494e 100644 --- a/tensorflow/core/kernels/maxpooling_op_gpu.cu.cc +++ b/tensorflow/core/kernels/maxpooling_op_gpu.cu.cc @@ -384,6 +384,8 @@ bool MaxPoolForwardNoMask_NCHW_VECT_C::operator()( int32* top_data, const Eigen::GpuDevice& d) { const int kThreadsPerBlock = 1024; const int output_size = batch * channels * pooled_height * pooled_width; + if (output_size == 0) + return true; MaxPoolForwardNoMaskKernel_NCHW_VECT_C<<< (output_size + kThreadsPerBlock - 1) / kThreadsPerBlock, kThreadsPerBlock, 0, d.stream()>>>(output_size, bottom_data, height, width, channels, @@ -402,6 +404,8 @@ bool MaxPoolForwardWithOptionalArgmax::operator()( int64* mask, const Eigen::GpuDevice& d, bool propagate_nans) { const int kThreadsPerBlock = 1024; const int output_size = batch * channels * pooled_height * pooled_width; + if (output_size == 0) + return true; if (propagate_nans) { MaxPoolForwardNHWC <<<(output_size + kThreadsPerBlock - 1) / kThreadsPerBlock, @@ -430,6 +434,8 @@ bool MaxPoolBackwardNoMask::operator()( const int kThreadsPerBlock = 1024; const int bottom_size = batch * channels * height * width; + if (bottom_size == 0) + return true; SetZero<<<(bottom_size + kThreadsPerBlock - 1) / kThreadsPerBlock, kThreadsPerBlock, 0, d.stream()>>>(bottom_size, bottom_diff); @@ -449,6 +455,8 @@ bool MaxPoolBackwardWithArgmax::operator()( const int64* mask, const int top_offset, const int bottom_offset, T* bottom_diff, const Eigen::GpuDevice& d) { const int kThreadsPerBlock = 1024; + if (input_size == 0) + return true; SetZero<<<(input_size + kThreadsPerBlock - 1) / kThreadsPerBlock, kThreadsPerBlock, 0, d.stream()>>>(input_size, bottom_diff); MaxPoolBackward<<<(output_size + kThreadsPerBlock - 1) / kThreadsPerBlock, @@ -466,6 +474,8 @@ bool MaxPoolGradBackwardNoMask::operator()( const int pad_l, const T* top_diff, T* bottom_diff, const Eigen::GpuDevice& d) { const int num_kernels = batch * channels * pooled_height * pooled_width; + if (num_kernels == 0) + return true; CudaLaunchConfig config = GetCudaLaunchConfig(num_kernels, d); if (data_format == FORMAT_NHWC) { @@ -489,6 +499,8 @@ bool MaxPoolGradBackwardWithArgmax::operator()( const int output_size, const int input_size, const T* top_diff, const int64* mask, const int top_offset, const int bottom_offset, T* bottom_diff, const Eigen::GpuDevice& d) { + if (input_size == 0) + return true; CudaLaunchConfig config = GetCudaLaunchConfig(output_size, d); MaxPoolGradBackward<<>>(output_size, top_diff, mask, top_offset, diff --git a/tensorflow/core/kernels/mkl_avgpooling_op.cc b/tensorflow/core/kernels/mkl_avgpooling_op.cc index 2409f7e9dc..939cbd6f96 100644 --- a/tensorflow/core/kernels/mkl_avgpooling_op.cc +++ b/tensorflow/core/kernels/mkl_avgpooling_op.cc @@ -357,22 +357,21 @@ class MklAvgPoolingGradOp : public OpKernel { if (!outbackprop_in_mkl_format) { // For avgpooling, tensor_in_shape should have 1 dimension, and 4 // elements. - OP_REQUIRES( - context, - tensor_in_shape.dims() == 1 && tensor_in_shape.NumElements() == 4, - errors::InvalidArgument("original input shape must be " - "1-dimensional and 4 elements")); + OP_REQUIRES(context, tensor_in_shape.dims() == 1 && + tensor_in_shape.NumElements() == 4, + errors::InvalidArgument("original input shape must be " + "1-dimensional and 4 elements")); // For avgpooling, out_backprop should have 4 dimensions. - OP_REQUIRES(context, out_backprop.dims() == 4, - errors::InvalidArgument("out_backprop must be " - "4-dimensional")); + OP_REQUIRES( + context, out_backprop.dims() == 4, + errors::InvalidArgument("out_backprop must be 4-dimensional")); } else { // Input in MKL format. // For avgpooling, out_backprop should have 4 dimensions. - OP_REQUIRES(context, out_backprop_shape.GetDimension() == 4, - errors::InvalidArgument("out_backprop must be " - "4-dimensional")); + OP_REQUIRES( + context, out_backprop_shape.GetDimension() == 4, + errors::InvalidArgument("out_backprop must be 4-dimensional")); } // TODO(inteltf): Get outbackprop layout. @@ -484,9 +483,9 @@ class MklAvgPoolingOp : public MklPoolingForwardOpBase { dnn_shape_input.IsMklTensor() ? dnn_shape_input.GetSizesAsMklDnnDims() : is_pool2d ? TFShapeToMklDnnDimsInNCHW(input_tensor.shape(), - this->data_format_tf_) - : TFShapeToMklDnnDimsInNCDHW(input_tensor.shape(), - this->data_format_tf_); + this->data_format_tf_) + : TFShapeToMklDnnDimsInNCDHW(input_tensor.shape(), + this->data_format_tf_); memory::desc input_md = dnn_shape_input.IsMklTensor() ? dnn_shape_input.GetMklLayout() : memory::desc(src_dims, MklDnnType(), @@ -494,9 +493,17 @@ class MklAvgPoolingOp : public MklPoolingForwardOpBase { // Get an average pooling primitive from the op pool MklPoolingFwdPrimitive* pooling_fwd = nullptr; + prop_kind pooling_prop_kind; + bool int8_forward_inference = + std::is_same::value || std::is_same::value; + if (int8_forward_inference) + pooling_prop_kind = prop_kind::forward_inference; + else + pooling_prop_kind = prop_kind::forward_training; MklPoolingParams fwdParams(src_dims, output_dims_mkl_order, filter_dims, strides, padding_left, padding_right, - algorithm::pooling_avg_exclude_padding); + algorithm::pooling_avg_exclude_padding, + pooling_prop_kind); pooling_fwd = MklPoolingFwdPrimitiveFactory::Get(fwdParams); // allocate output tensor @@ -523,10 +530,30 @@ class MklAvgPoolingOp : public MklPoolingForwardOpBase { // execute pooling pooling_fwd->Execute(src_data, dst_data); + + // Pass min, max from input to output + if (int8_forward_inference) { + const Tensor& min_input_t = MklGetInput(context, 1); + const Tensor& max_input_t = MklGetInput(context, 2); + const float min_input = min_input_t.flat()(0); + const float max_input = max_input_t.flat()(0); + + Tensor* output_min = nullptr; + Tensor* output_max = nullptr; + MklDnnShape output_min_mkl_shape, output_max_mkl_shape; + output_min_mkl_shape.SetMklTensor(false); + output_max_mkl_shape.SetMklTensor(false); + AllocateOutputSetMklShape(context, 1, &output_min, {}, + output_min_mkl_shape); + AllocateOutputSetMklShape(context, 2, &output_max, {}, + output_max_mkl_shape); + output_min->flat()(0) = min_input; + output_max->flat()(0) = max_input; + } } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK( context, errors::Aborted("Operation received an exception:", error_msg)); @@ -576,24 +603,26 @@ class MklAvgPoolingGradOp : public MklPoolingBackwardOpBase { orig_input_mkl_shape.IsMklTensor() ? orig_input_mkl_shape.GetSizesAsMklDnnDims() : is_pool2d ? TFShapeToMklDnnDimsInNCHW(orig_input_shape, - this->data_format_tf_) - : TFShapeToMklDnnDimsInNCDHW(orig_input_shape, - this->data_format_tf_); + this->data_format_tf_) + : TFShapeToMklDnnDimsInNCDHW(orig_input_shape, + this->data_format_tf_); memory::dims diff_dst_dims = grad_mkl_shape.IsMklTensor() ? grad_mkl_shape.GetSizesAsMklDnnDims() : is_pool2d ? TFShapeToMklDnnDimsInNCHW(grad_tensor.shape(), - this->data_format_tf_) - : TFShapeToMklDnnDimsInNCDHW(grad_tensor.shape(), - this->data_format_tf_); + this->data_format_tf_) + : TFShapeToMklDnnDimsInNCDHW(grad_tensor.shape(), + this->data_format_tf_); memory::dims output_dims_mkl_order; this->GetOutputDims(pool_params, &output_dims_mkl_order); - MklPoolingParams bwdParams(orig_input_dims_mkl_order, - output_dims_mkl_order, filter_dims, strides, - padding_left, padding_right, - algorithm::pooling_avg_exclude_padding); + // Pass prop_kind::forward_training to create a forward primitive + // that is used in the backward pass + MklPoolingParams bwdParams( + orig_input_dims_mkl_order, output_dims_mkl_order, filter_dims, + strides, padding_left, padding_right, + algorithm::pooling_avg_exclude_padding, prop_kind::forward_training); MklPoolingBwdPrimitive* pooling_bwd = MklPoolingBwdPrimitiveFactory::Get(bwdParams); @@ -624,9 +653,9 @@ class MklAvgPoolingGradOp : public MklPoolingBackwardOpBase { // execute pooling op pooling_bwd->Execute(diff_dst_data, diff_src_data); } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK(context, errors::Aborted("Compute received an exception:", error_msg)); } @@ -645,28 +674,26 @@ class MklAvgPoolingGradOp : public MklPoolingBackwardOpBase { const MklDnnShape& original_input_mkl_shape, const MklDnnShape& input_gradient_mkl_shape) { if (!original_input_mkl_shape.IsMklTensor()) { - OP_REQUIRES( - context, - tensor_in_shape.dims() == 1 && tensor_in_shape.NumElements() == 4, - errors::InvalidArgument("original input shape must be " - "1-dimensional and 4 elements")); + OP_REQUIRES(context, tensor_in_shape.dims() == 1 && + tensor_in_shape.NumElements() == 4, + errors::InvalidArgument("original input shape must be " + "1-dimensional and 4 elements")); } else { - OP_REQUIRES(context, - original_input_mkl_shape.GetDimension() == 1 && - original_input_mkl_shape.DimSize(0) == 4, + OP_REQUIRES(context, original_input_mkl_shape.GetDimension() == 1 && + original_input_mkl_shape.DimSize(0) == 4, errors::InvalidArgument("original input shape must be " "1-dimensional and 4 elements")); } if (!input_gradient_mkl_shape.IsMklTensor()) { // For avgpooling, input_gradient_diff_dst should have 4 dimensions. - OP_REQUIRES(context, input_gradient_tensor.dims() == 4, - errors::InvalidArgument("Gradient shape must be " - "4-dimensional")); + OP_REQUIRES( + context, input_gradient_tensor.dims() == 4, + errors::InvalidArgument("Gradient shape must be 4-dimensional")); } else { - OP_REQUIRES(context, input_gradient_mkl_shape.GetDimension() == 4, - errors::InvalidArgument("Gradient shape must be " - "4-dimensional")); + OP_REQUIRES( + context, input_gradient_mkl_shape.GetDimension() == 4, + errors::InvalidArgument("Gradient shape must be 4-dimensional")); } } }; // MklAvgPoolingGradOp @@ -691,6 +718,18 @@ REGISTER_KERNEL_BUILDER(Name("_MklAvgPool") .Label(mkl_op_registry::kMklOpLabel), MklAvgPoolingOp); +REGISTER_KERNEL_BUILDER(Name("_MklQuantizedAvgPool") + .Device(DEVICE_CPU) + .TypeConstraint("T") + .Label(mkl_op_registry::kMklQuantizedOpLabel), + MklAvgPoolingOp); + +REGISTER_KERNEL_BUILDER(Name("_MklQuantizedAvgPool") + .Device(DEVICE_CPU) + .TypeConstraint("T") + .Label(mkl_op_registry::kMklQuantizedOpLabel), + MklAvgPoolingOp); + REGISTER_KERNEL_BUILDER(Name("_MklAvgPoolGrad") .Device(DEVICE_CPU) .TypeConstraint("T") diff --git a/tensorflow/core/kernels/mkl_conv_ops.cc b/tensorflow/core/kernels/mkl_conv_ops.cc index 14d134e2d0..75f08956b4 100644 --- a/tensorflow/core/kernels/mkl_conv_ops.cc +++ b/tensorflow/core/kernels/mkl_conv_ops.cc @@ -465,19 +465,18 @@ class MklConvOp : public OpKernel { filter.shape().DebugString())); for (int i = 0; i < 3; i++) { - OP_REQUIRES( - context, - FastBoundsCheck(filter.dim_size(i), std::numeric_limits::max()), - errors::InvalidArgument("filter too large")); + OP_REQUIRES(context, FastBoundsCheck(filter.dim_size(i), + std::numeric_limits::max()), + errors::InvalidArgument("filter too large")); } const int64 input_depth = input_in_mkl_format ? GetMklTensorDim(mkl_context.input_shape, 'C') : GetTensorDim(input, data_format_, 'C'); - OP_REQUIRES(context, input_depth == filter.dim_size(2), - errors::InvalidArgument( - "input and filter must have the same depth: ", input_depth, - " vs ", filter.dim_size(2))); + OP_REQUIRES( + context, input_depth == filter.dim_size(2), + errors::InvalidArgument("input and filter must have the same depth: ", + input_depth, " vs ", filter.dim_size(2))); // The last dimension for filter is out_depth. const int out_depth = static_cast(filter.dim_size(3)); @@ -486,10 +485,9 @@ class MklConvOp : public OpKernel { const int64 input_rows_raw = input_in_mkl_format ? GetMklTensorDim(mkl_context.input_shape, 'H') : GetTensorDim(input, data_format_, 'H'); - OP_REQUIRES( - context, - FastBoundsCheck(input_rows_raw, std::numeric_limits::max()), - errors::InvalidArgument("Input rows too large")); + OP_REQUIRES(context, FastBoundsCheck(input_rows_raw, + std::numeric_limits::max()), + errors::InvalidArgument("Input rows too large")); const int input_rows = static_cast(input_rows_raw); const int filter_rows = static_cast(filter.dim_size(0)); @@ -498,10 +496,9 @@ class MklConvOp : public OpKernel { const int64 input_cols_raw = input_in_mkl_format ? GetMklTensorDim(mkl_context.input_shape, 'W') : GetTensorDim(input, data_format_, 'W'); - OP_REQUIRES( - context, - FastBoundsCheck(input_cols_raw, std::numeric_limits::max()), - errors::InvalidArgument("Input cols too large")); + OP_REQUIRES(context, FastBoundsCheck(input_cols_raw, + std::numeric_limits::max()), + errors::InvalidArgument("Input cols too large")); const int input_cols = static_cast(input_cols_raw); const int filter_cols = static_cast(filter.dim_size(1)); @@ -509,10 +506,9 @@ class MklConvOp : public OpKernel { const int64 input_batch_raw = input_in_mkl_format ? GetMklTensorDim(mkl_context.input_shape, 'N') : GetTensorDim(input, data_format_, 'N'); - OP_REQUIRES( - context, - FastBoundsCheck(input_batch_raw, std::numeric_limits::max()), - errors::InvalidArgument("batch is too large")); + OP_REQUIRES(context, FastBoundsCheck(input_batch_raw, + std::numeric_limits::max()), + errors::InvalidArgument("batch is too large")); const int batch = static_cast(input_batch_raw); // For now we take the stride from the second and third dimensions only (we @@ -893,17 +889,15 @@ class MklConvOp : public OpKernel { OP_REQUIRES(context, dilations_.size() == 5, errors::InvalidArgument("Dilation rates field must " "specify 5 dimensions")); - OP_REQUIRES(context, - (GetTensorDim(dilations_, data_format_, 'N') == 1 && - GetTensorDim(dilations_, data_format_, 'C') == 1), + OP_REQUIRES(context, (GetTensorDim(dilations_, data_format_, 'N') == 1 && + GetTensorDim(dilations_, data_format_, 'C') == 1), errors::InvalidArgument( "Current implementation does not yet support " "dilations rates in the batch and depth dimensions.")); OP_REQUIRES( - context, - (GetTensorDim(dilations_, data_format_, '0') > 0 && - GetTensorDim(dilations_, data_format_, '1') > 0 && - GetTensorDim(dilations_, data_format_, '2') > 0), + context, (GetTensorDim(dilations_, data_format_, '0') > 0 && + GetTensorDim(dilations_, data_format_, '1') > 0 && + GetTensorDim(dilations_, data_format_, '2') > 0), errors::InvalidArgument("Dilated rates should be larger than 0.")); } } @@ -1067,8 +1061,14 @@ class MklConvOp : public OpKernel { Tfilter* filter_data = nullptr; if (filter_md.data.format != conv_fwd->GetFilterMemoryFormat()) { filter.SetUsrMem(filter_md, &filter_tensor); - filter.CheckReorderToOpMem(conv_fwd_pd.get()->weights_primitive_desc(), - filter.GetTensorBuffer(filter_out_tensor)); + if (filter_out_tensor == nullptr) { + filter.CheckReorderToOpMem( + conv_fwd_pd.get()->weights_primitive_desc()); + } else { + filter.CheckReorderToOpMem( + conv_fwd_pd.get()->weights_primitive_desc(), + filter.GetTensorBuffer(filter_out_tensor)); + } filter_data = static_cast(filter.GetOpMem().get_data_handle()); } else { @@ -1468,7 +1468,7 @@ class MklQuantizedConv2DSumReluOp {"sum", {scale_summand / scale_output}}); else params.post_op_params.push_back( - {"sum", {2.0 * scale_summand / scale_output}}); + {"sum", {2.0f * scale_summand / scale_output}}); } else { params.post_op_params.push_back({"sum", {1.0}}); } @@ -1533,8 +1533,8 @@ class MklQuantizedConv2DSumReluOp const float max_filter = context->input(5 + bias_index_offset).flat()(0); - reorder_sum_scale = 255.0 * 127.0 / - (std::max(std::abs(max_input), std::abs(min_input)) * + reorder_sum_scale = + 255.0 * 127.0 / (std::max(std::abs(max_input), std::abs(min_input)) * std::max(std::abs(max_filter), std::abs(min_filter))); std::vector scales; scales.push_back(reorder_sum_scale); diff --git a/tensorflow/core/kernels/mkl_lrn_op.cc b/tensorflow/core/kernels/mkl_lrn_op.cc index 22ff4cd80f..407ce5d653 100644 --- a/tensorflow/core/kernels/mkl_lrn_op.cc +++ b/tensorflow/core/kernels/mkl_lrn_op.cc @@ -22,32 +22,26 @@ limitations under the License. #define EIGEN_USE_THREADS #include -#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" +#include "mkldnn.hpp" #include "tensorflow/core/framework/op_kernel.h" #include "tensorflow/core/framework/register_types.h" #include "tensorflow/core/framework/tensor.h" #include "tensorflow/core/kernels/bounds_check.h" #include "tensorflow/core/kernels/ops_util.h" #include "tensorflow/core/lib/core/errors.h" +#include "tensorflow/core/util/mkl_util.h" #include "tensorflow/core/util/tensor_format.h" +#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" #if !defined(IS_MOBILE_PLATFORM) #include "tensorflow/core/util/work_sharder.h" #endif -#ifndef INTEL_MKL_ML_ONLY -#include "mkldnn.hpp" using mkldnn::lrn_across_channels; using mkldnn::lrn_backward; using mkldnn::lrn_forward; using mkldnn::prop_kind; using mkldnn::stream; -#else -#include "mkl_dnn.h" -#include "mkl_dnn_types.h" -#endif - -#include "tensorflow/core/util/mkl_util.h" namespace tensorflow { @@ -69,672 +63,6 @@ void GetBandMatrix(int depth, int depth_radius, } // namespace -#ifdef INTEL_MKL_ML_ONLY - -template -class MklLRNOp : public OpKernel { - public: - ~MklLRNOp() {} - - explicit MklLRNOp(OpKernelConstruction* context) : OpKernel(context) { - int64 depth_radius64; - OP_REQUIRES_OK(context, context->GetAttr("depth_radius", &depth_radius64)); - OP_REQUIRES( - context, - FastBoundsCheck(depth_radius64, std::numeric_limits::max()), - errors::InvalidArgument("depth_radius = ", depth_radius64, - " larger than int max")); - depth_radius_ = static_cast(depth_radius64); - - OP_REQUIRES_OK(context, context->GetAttr("bias", &bias_)); - OP_REQUIRES_OK(context, context->GetAttr("alpha", &alpha_)); - OP_REQUIRES_OK(context, context->GetAttr("beta", &beta_)); - workspace_enabled_ = false; - OP_REQUIRES_OK(context, - context->GetAttr("workspace_enabled", &workspace_enabled_)); - } - - void Compute(OpKernelContext* context) override { - MklLRNOpContext mkl_context; - - const Tensor& input = MklGetInput(context, 0); - GetMklShape(context, 0, &mkl_context.input_shape); - bool input_in_mkl_format = mkl_context.input_shape.IsMklTensor(); - - // Sanity checks - mkl_context.in_dims = input_in_mkl_format - ? mkl_context.input_shape.GetDimension() - : input.dims(); - OP_REQUIRES(context, mkl_context.in_dims == 4, - errors::InvalidArgument("input must be 4-dimensional")); - OP_REQUIRES( - context, - FastBoundsCheck(input.NumElements(), std::numeric_limits::max()), - errors::InvalidArgument("argument to LRN too large")); - - if (!input_in_mkl_format) { - mkl_context.MklDefaultToEigen(context, depth_radius_, bias_, alpha_, - beta_, input); - return; - } - - if (input_in_mkl_format) { - // MKL supports normalization over channel dimension only - if (mkl_context.input_shape.tf_dim_idx(mkl_context.in_dims - 1) == - MklDims::C) { - mkl_context.lt_input = - static_cast(mkl_context.input_shape.GetCurLayout()); - workspace_enabled_ = true; - } else { - Tensor converted_tensor = - ConvertMklToTF(context, input, mkl_context.input_shape); - mkl_context.MklDefaultToEigen(context, depth_radius_, bias_, alpha_, - beta_, converted_tensor); - return; - } - } - - int kernel_size = 2 * depth_radius_ + 1; - - CHECK_EQ(dnnLRNCreateForward_F32( - &mkl_context.lrn_fwd, NULL, mkl_context.lt_input, kernel_size, - static_cast(alpha_ * kernel_size), beta_, bias_), - E_SUCCESS); - - // Allocate output tensor and shape - Tensor* output = nullptr; - Tensor* workspace = nullptr; - - // Convert Inputs if needed - Tensor mkl_tmp_input_buf_tensor; - mkl_context.MklPrepareLRNInputs(context, &mkl_tmp_input_buf_tensor); - - // Allocate Layer Outputs - mkl_context.MklAllocateOutputs(context, &output, &workspace, - workspace_enabled_); - - Tensor mkl_tmp_workspace_buf_tensor; - mkl_context.MklPrepareLRNOutputs(context, output, workspace, - &mkl_tmp_workspace_buf_tensor, - workspace_enabled_); - - // Execute LRN. - CHECK_EQ(dnnExecute_F32(mkl_context.lrn_fwd, mkl_context.lrn_res), - E_SUCCESS); - - // Release MKL resources. - mkl_context.MklCleanup(); - } - - private: - typedef struct { - size_t in_dims; - size_t in_sizes[4]; - size_t in_strides[4]; - size_t out_sizes[4]; - size_t out_strides[4]; - MklShape input_shape; - dnnPrimitive_t lrn_fwd = nullptr; - dnnPrimitive_t convert_input = nullptr; - dnnLayout_t lt_input = nullptr; - dnnLayout_t lt_internal_input = nullptr; - dnnLayout_t lt_internal_workspace = nullptr; - dnnLayout_t lt_internal_output = nullptr; - void* lrn_res[dnnResourceNumber]; - - // Convert Inputs if needed - void MklPrepareLRNInputs(OpKernelContext* context, - Tensor* mkl_tmp_input_buf_tensor) { - const Tensor& input = MklGetInput(context, 0); - void* mkl_buf_input = - const_cast(static_cast(input.flat().data())); - - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32(<_internal_input, lrn_fwd, - dnnResourceSrc), - E_SUCCESS); - - void* mkl_buf_convert_input = nullptr; - bool mkl_convert_input = false; - mkl_convert_input = !dnnLayoutCompare_F32(lt_internal_input, lt_input); - - if (mkl_convert_input) { - CHECK_EQ(dnnConversionCreate_F32(&convert_input, lt_input, - lt_internal_input), - E_SUCCESS); - AllocTmpBuffer(context, mkl_tmp_input_buf_tensor, lt_internal_input, - &mkl_buf_convert_input); - CHECK_EQ(dnnConversionExecute_F32(convert_input, mkl_buf_input, - mkl_buf_convert_input), - E_SUCCESS); - dnnDelete_F32(convert_input); - } - - lrn_res[dnnResourceSrc] = - (mkl_convert_input) ? mkl_buf_convert_input : mkl_buf_input; - } - - // Allocate Layer Outputs - void MklAllocateOutputs(OpKernelContext* context, Tensor** output, - Tensor** workspace, bool workspace_enabled_) { - TensorShape mkl_output_tf_shape; /* First tensor */ - MklShape mkl_output_mkl_shape; /* Second tensor */ - - mkl_output_mkl_shape.SetMklTensor(true); - mkl_output_mkl_shape.SetMklLayout(lrn_fwd, dnnResourceDst); - mkl_output_mkl_shape.SetTfLayout(in_dims, input_shape.GetSizes(), - input_shape.GetStrides()); - mkl_output_mkl_shape.SetTfDimOrder(in_dims, - input_shape.GetTfToMklDimMap()); - mkl_output_tf_shape.AddDim( - dnnLayoutGetMemorySize_F32( - static_cast(mkl_output_mkl_shape.GetMklLayout())) / - sizeof(T)); - AllocateOutputSetMklShape(context, 0, output, - mkl_output_tf_shape /* First tensor */, - mkl_output_mkl_shape /* Second Tensor */); - - if (workspace_enabled_) { - TensorShape mkl_workspace_tf_shape; /* First tensor */ - MklShape mkl_workspace_mkl_shape; /* Second tensor */ - mkl_workspace_mkl_shape.SetMklTensor(false); - mkl_workspace_mkl_shape.SetMklLayout(lrn_fwd, dnnResourceWorkspace); - // Assumes workspace has same TF layout and TF dim order as input - mkl_workspace_mkl_shape.SetTfLayout(in_dims, input_shape.GetSizes(), - input_shape.GetStrides()); - mkl_workspace_mkl_shape.SetTfDimOrder(in_dims, - input_shape.GetTfToMklDimMap()); - mkl_workspace_tf_shape.AddDim( - dnnLayoutGetMemorySize_F32(static_cast( - mkl_workspace_mkl_shape.GetMklLayout())) / - sizeof(T)); - AllocateOutputSetMklShape(context, 1, workspace, - mkl_workspace_tf_shape /* First tensor */, - mkl_workspace_mkl_shape /* Second Tensor */); - } - } - - void MklPrepareLRNOutputs(OpKernelContext* context, Tensor* output, - Tensor* workspace, - Tensor* mkl_tmp_workspace_buf_tensor, - bool workspace_enabled_) { - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32(<_internal_workspace, lrn_fwd, - dnnResourceWorkspace), - E_SUCCESS); - - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32(<_internal_output, lrn_fwd, - dnnResourceDst), - E_SUCCESS); - - void* mkl_buf_output = - const_cast(static_cast(output->flat().data())); - lrn_res[dnnResourceDst] = mkl_buf_output; - - void* mkl_buf_workspace = nullptr; - if (workspace_enabled_) { - mkl_buf_workspace = const_cast( - static_cast(workspace->flat().data())); - } else { - AllocTmpBuffer(context, mkl_tmp_workspace_buf_tensor, - lt_internal_workspace, &mkl_buf_workspace); - } - lrn_res[dnnResourceWorkspace] = mkl_buf_workspace; - } - - // Fallback implementation - Taken from lrn_op.cc - // TODO(inteltf) Check if we can use EigenLRNOp directly instead of making a - // copy. - void MklDefaultToEigen(OpKernelContext* context, int depth_radius_, - float bias_, float alpha_, float beta_, - const Tensor& input) { - const int batch = static_cast(input.dim_size(0)); - const int rows = static_cast(input.dim_size(1)); - const int cols = static_cast(input.dim_size(2)); - const int depth = static_cast(input.dim_size(3)); - const int nodes = cols * rows; - - auto in_shaped = input.shaped({nodes * batch, depth}); - // Multiplying the input with the band matrix has the effect of reducing - // the - // correct patch along the depth. - Eigen::Tensor multiplier(depth, depth); - GetBandMatrix(depth, depth_radius_, &multiplier); - - Tensor *output, *workspace; - MklShape mkl_output_mkl_shape, mkl_workspace_mkl_shape; - mkl_output_mkl_shape.SetMklTensor(false); - mkl_output_mkl_shape.SetDimensions(4); - AllocateOutputSetMklShape(context, 0, &output, input.shape(), - mkl_output_mkl_shape); - - mkl_workspace_mkl_shape.SetMklTensor(false); - mkl_workspace_mkl_shape.SetDimensions(4); - AllocateOutputSetMklShape(context, 1, &workspace, input.shape(), - mkl_workspace_mkl_shape); - - auto out_shaped = output->shaped({nodes * batch, depth}); - Eigen::array dims = {{DimPair(1, 0)}}; - auto tmp = in_shaped.square().contract(multiplier, dims) * alpha_ + bias_; - if (beta_ == T(1)) { - out_shaped.device(context->eigen_cpu_device()) = - in_shaped * tmp.inverse(); - } else if (beta_ == T(0.5)) { - out_shaped.device(context->eigen_cpu_device()) = - in_shaped * tmp.rsqrt(); - } else { - out_shaped.device(context->eigen_cpu_device()) = - in_shaped * (tmp.log() * -beta_).exp(); - } - } - - // Release MKL resources. - void MklCleanup() { - dnnDelete_F32(lrn_fwd); - dnnLayoutDelete_F32(lt_internal_input); - dnnLayoutDelete_F32(lt_internal_workspace); - dnnLayoutDelete_F32(lt_internal_output); - } - } MklLRNOpContext; - - typedef typename Eigen::Tensor::DimensionPair DimPair; - - bool workspace_enabled_; - int depth_radius_; - float bias_; - float alpha_; - float beta_; -}; - -template -class MklLRNGradOp : public OpKernel { - public: - explicit MklLRNGradOp(OpKernelConstruction* context) : OpKernel(context) { - int64 depth_radius64; - OP_REQUIRES_OK(context, context->GetAttr("depth_radius", &depth_radius64)); - OP_REQUIRES( - context, - FastBoundsCheck(depth_radius64, std::numeric_limits::max()), - errors::InvalidArgument("depth_radius = ", depth_radius64, - " larger than int max")); - depth_radius_ = static_cast(depth_radius64); - OP_REQUIRES_OK(context, context->GetAttr("bias", &bias_)); - OP_REQUIRES_OK(context, context->GetAttr("alpha", &alpha_)); - OP_REQUIRES_OK(context, context->GetAttr("beta", &beta_)); - workspace_enabled_ = false; - OP_REQUIRES_OK(context, - context->GetAttr("workspace_enabled", &workspace_enabled_)); - } - - void Compute(OpKernelContext* context) override { - MklLRNGradOpContext mkl_context; - mkl_context.depth_radius_ = depth_radius_; - mkl_context.bias_ = bias_; - mkl_context.alpha_ = alpha_; - mkl_context.beta_ = beta_; - - const Tensor& in_grads = MklGetInput(context, 0); - const Tensor& in_image = MklGetInput(context, 1); - const Tensor& out_image = MklGetInput(context, 2); - - GetMklShape(context, 0, &mkl_context.ingrad_shape); - GetMklShape(context, 1, &mkl_context.inimage_shape); - GetMklShape(context, 2, &mkl_context.outimage_shape); - - bool ingrad_in_mkl_format = mkl_context.ingrad_shape.IsMklTensor(); - bool inimage_in_mkl_format = mkl_context.inimage_shape.IsMklTensor(); - bool outimage_in_mkl_format = mkl_context.outimage_shape.IsMklTensor(); - - mkl_context.in_dims = inimage_in_mkl_format - ? mkl_context.inimage_shape.GetDimension() - : in_image.dims(); - OP_REQUIRES(context, mkl_context.in_dims == 4, - errors::InvalidArgument("input images must be 4-dimensional")); - - if (!workspace_enabled_) { - mkl_context.MklDefaultToEigen(context); - return; - } - - if (ingrad_in_mkl_format || inimage_in_mkl_format) { - const MklShape* tmp_mkl_shape = (ingrad_in_mkl_format) - ? &mkl_context.ingrad_shape - : &mkl_context.inimage_shape; - if (tmp_mkl_shape->tf_dim_idx(mkl_context.in_dims - 1) != MklDims::C) { - // Fallback to eigen - mkl_context.MklDefaultToEigen(context); - return; - } else { // MKL supports normalization over channel dimension only - for (int i = 0; i < mkl_context.in_dims; i++) { - mkl_context.in_sizes[i] = mkl_context.out_sizes[i] = - tmp_mkl_shape->GetSizes()[i]; - mkl_context.in_strides[i] = mkl_context.out_strides[i] = - tmp_mkl_shape->GetStrides()[i]; - } - } - } else { - // Fallback to eigen - mkl_context.MklDefaultToEigen(context); - return; - } - - // Dimensions check for sanity purpose - if (ingrad_in_mkl_format) { - OP_REQUIRES( - context, mkl_context.ingrad_shape.GetDimension() == 4, - errors::InvalidArgument("input gradient must be 4-dimensional")); - } else { - OP_REQUIRES( - context, in_grads.dims() == 4, - errors::InvalidArgument("input gradient must be 4-dimensional")); - } - - if (outimage_in_mkl_format) { - OP_REQUIRES( - context, mkl_context.outimage_shape.GetDimension() == 4, - errors::InvalidArgument("Output image must be 4-dimensional")); - } else { - OP_REQUIRES( - context, out_image.dims() == 4, - errors::InvalidArgument("Output image must be 4-dimensional")); - } - - // Prepare mkl input layout - mkl_context.MklPrepareLRNInputsLayouts(context); - int ksize = 2 * depth_radius_ + 1; - - CHECK_EQ(dnnLRNCreateBackward_F32( - &mkl_context.lrn_bwd, NULL, mkl_context.lt_input, - mkl_context.lt_output, ksize, - static_cast(alpha_ * ksize), beta_, bias_), - E_SUCCESS); - - // Allocate output tensor and shape. - TensorShape mkl_output_tf_shape; /* First tensor */ - MklShape mkl_output_mkl_shape; /* Second tensor */ - mkl_output_mkl_shape.SetMklTensor(true); - CHECK_NE(mkl_context.lrn_bwd, nullptr); - mkl_output_mkl_shape.SetMklLayout(mkl_context.lrn_bwd, dnnResourceDiffSrc); - mkl_output_mkl_shape.SetTfLayout(mkl_context.in_dims, mkl_context.out_sizes, - mkl_context.out_strides); - if (ingrad_in_mkl_format) { - mkl_output_mkl_shape.SetTfDimOrder( - mkl_context.in_dims, mkl_context.ingrad_shape.GetTfToMklDimMap()); - } else { - mkl_output_mkl_shape.SetTfDimOrder( - mkl_context.in_dims, mkl_context.inimage_shape.GetTfToMklDimMap()); - } - mkl_output_tf_shape.AddDim( - dnnLayoutGetMemorySize_F32( - static_cast(mkl_output_mkl_shape.GetMklLayout())) / - sizeof(T)); - Tensor* output = nullptr; - AllocateOutputSetMklShape(context, 0, &output, mkl_output_tf_shape, - mkl_output_mkl_shape); - - // Get pointers to output data. - void* user_output = - const_cast(static_cast(output->flat().data())); - - Tensor mkl_tmp_input_buf_tensor, mkl_tmp_image_buf_tensor, - mkl_tmp_outimage_buf_tensor; - // Convert Inputs if needed - mkl_context.MklPrepareLRNGradInput(context, &mkl_tmp_input_buf_tensor, - &mkl_tmp_image_buf_tensor, - &mkl_tmp_outimage_buf_tensor); - - // We do not do any conversion for output. But we simply emit it - // in MKL format. - mkl_context.res_lrn_bwd[dnnResourceDiffSrc] = user_output; - // Execute LRN backward using dnnExecute - CHECK_EQ(dnnExecute_F32(mkl_context.lrn_bwd, mkl_context.res_lrn_bwd), - E_SUCCESS); - // Release MKL resources. - mkl_context.Mklcleanup(); - } - - private: - typedef struct { - int depth_radius_; - float bias_; - float alpha_; - float beta_; - size_t in_dims; - size_t in_sizes[4]; - size_t in_strides[4]; - size_t out_sizes[4]; - size_t out_strides[4]; - MklShape ingrad_shape, inimage_shape, outimage_shape; - dnnPrimitive_t lrn_bwd = nullptr; - dnnPrimitive_t convert_input = nullptr; - dnnLayout_t lt_input = nullptr; - dnnLayout_t lt_output = nullptr; - dnnLayout_t lt_bdw_input = nullptr; - dnnLayout_t lt_workspace = nullptr; - dnnLayout_t lt_internal_input = nullptr; - void* res_lrn_bwd[dnnResourceNumber]; - - // prepare mkl input - void MklPrepareLRNInputsLayouts(OpKernelContext* context) { - bool ingrad_in_mkl_format = ingrad_shape.IsMklTensor(); - bool inimage_in_mkl_format = inimage_shape.IsMklTensor(); - if (!ingrad_in_mkl_format) { - CHECK_EQ(dnnLayoutCreate_F32(<_input, in_dims, in_sizes, in_strides), - E_SUCCESS); - } else { - lt_input = static_cast(ingrad_shape.GetCurLayout()); - } - - if (!inimage_in_mkl_format) { - CHECK_EQ( - dnnLayoutCreate_F32(<_output, in_dims, out_sizes, out_strides), - E_SUCCESS); - } else { - lt_output = static_cast(inimage_shape.GetCurLayout()); - } - } - - // convert input if needed - void MklPrepareLRNGradInput(OpKernelContext* context, - Tensor* mkl_tmp_input_buf_tensor, - Tensor* mkl_tmp_image_buf_tensor, - Tensor* mkl_tmp_outimage_buf_tensor) { - const Tensor& in_grads = MklGetInput(context, 0); - const Tensor& in_image = MklGetInput(context, 1); - const Tensor& workspace = MklGetInput( - context, - 3); /*Worskpsace is enabled, get the buffer to the workspace */ - - void* user_input = const_cast( - static_cast(in_grads.flat().data())); - void* user_fwd_input = const_cast( - static_cast(in_image.flat().data())); - void* workspace_buffer = const_cast( - static_cast(workspace.flat().data())); - - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32(<_workspace, lrn_bwd, - dnnResourceWorkspace), - E_SUCCESS); - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32(<_bdw_input, lrn_bwd, - dnnResourceDiffDst), - E_SUCCESS); - CHECK_EQ(dnnLayoutCreateFromPrimitive_F32(<_internal_input, lrn_bwd, - dnnResourceSrc), - E_SUCCESS); - - bool ingrad_in_mkl_format = ingrad_shape.IsMklTensor(); - if (ingrad_in_mkl_format) { - if (!dnnLayoutCompare_F32(lt_bdw_input, lt_input)) { - AllocTmpBuffer(context, mkl_tmp_input_buf_tensor, lt_bdw_input, - &res_lrn_bwd[dnnResourceDiffDst]); - ingrad_shape.GetConvertedFlatData(lt_bdw_input, user_input, - res_lrn_bwd[dnnResourceDiffDst]); - } else { - res_lrn_bwd[dnnResourceDiffDst] = user_input; - } - } else { - if (!dnnLayoutCompare_F32(lt_bdw_input, lt_input)) { - CHECK_EQ( - dnnConversionCreate_F32(&convert_input, lt_input, lt_bdw_input), - E_SUCCESS); - - AllocTmpBuffer(context, mkl_tmp_input_buf_tensor, lt_bdw_input, - &res_lrn_bwd[dnnResourceDiffDst]); - CHECK_EQ(dnnConversionExecute_F32(convert_input, user_input, - res_lrn_bwd[dnnResourceDiffDst]), - E_SUCCESS); - dnnDelete_F32(convert_input); - } else { - res_lrn_bwd[dnnResourceDiffDst] = user_input; - } - } - - bool inimage_in_mkl_format = inimage_shape.IsMklTensor(); - if (inimage_in_mkl_format) { - if (!dnnLayoutCompare_F32( - lt_internal_input, - static_cast(inimage_shape.GetCurLayout()))) { - AllocTmpBuffer(context, mkl_tmp_image_buf_tensor, lt_internal_input, - &res_lrn_bwd[dnnResourceSrc]); - ingrad_shape.GetConvertedFlatData(lt_internal_input, user_fwd_input, - res_lrn_bwd[dnnResourceSrc]); - } else { - res_lrn_bwd[dnnResourceSrc] = user_fwd_input; - } - } else { - if (!dnnLayoutCompare_F32( - lt_internal_input, - static_cast(inimage_shape.GetCurLayout()))) { - CHECK_EQ(dnnConversionCreate_F32( - &convert_input, - static_cast(inimage_shape.GetCurLayout()), - lt_internal_input), - E_SUCCESS); - - AllocTmpBuffer(context, mkl_tmp_image_buf_tensor, lt_internal_input, - &res_lrn_bwd[dnnResourceSrc]); - CHECK_EQ(dnnConversionExecute_F32(convert_input, user_fwd_input, - res_lrn_bwd[dnnResourceSrc]), - E_SUCCESS); - dnnDelete_F32(convert_input); - } else { - res_lrn_bwd[dnnResourceSrc] = user_fwd_input; - } - } - - res_lrn_bwd[dnnResourceWorkspace] = workspace_buffer; - } - - // Fallback implementation - Taken from lrn_op.cc - // TODO(intelft) Check if we can use EigenLRNOp directly instead of making a - // copy. - void MklDefaultToEigen(OpKernelContext* context) { - Tensor in_grads; - Tensor in_image; - Tensor out_image; - - GetMklShape(context, 0, &ingrad_shape); - GetMklShape(context, 1, &inimage_shape); - GetMklShape(context, 2, &outimage_shape); - - if (ingrad_shape.IsMklTensor()) { - in_grads = - ConvertMklToTF(context, MklGetInput(context, 0), ingrad_shape); - } else { - in_grads = MklGetInput(context, 0); - } - - if (inimage_shape.IsMklTensor()) { - in_image = - ConvertMklToTF(context, MklGetInput(context, 1), inimage_shape); - } else { - in_image = MklGetInput(context, 1); - } - - if (outimage_shape.IsMklTensor()) { - out_image = - ConvertMklToTF(context, MklGetInput(context, 2), outimage_shape); - } else { - out_image = MklGetInput(context, 2); - } - - const int64 batch = static_cast(in_grads.dim_size(0)); - const int64 rows = static_cast(in_grads.dim_size(1)); - const int64 cols = static_cast(in_grads.dim_size(2)); - const int64 depth = static_cast(in_grads.dim_size(3)); - const auto nodes = cols * rows; - - auto grads_shaped = in_grads.shaped({nodes * batch, depth}); - - auto in_shaped = in_image.shaped({nodes * batch, depth}); - auto activations = out_image.shaped({nodes * batch, depth}); - - Tensor* output; - MklShape mkl_output_mkl_shape; - mkl_output_mkl_shape.SetMklTensor(false); - mkl_output_mkl_shape.SetDimensions(4); - AllocateOutputSetMklShape(context, 0, &output, in_grads.shape(), - mkl_output_mkl_shape); - - auto out_shaped = output->shaped({nodes * batch, depth}); - out_shaped.setZero(); - auto shard = [this, activations, in_shaped, grads_shaped, out_shaped, - depth](int64 begin, int64 end) { - for (int64 i = begin; i < end; ++i) { - for (int64 j = 0; j < depth; ++j) { - int64 depth_begin = std::max(0, j - depth_radius_); - int64 depth_end = std::min(depth, j + depth_radius_ + 1); - - T norm(0); - for (int64 k = depth_begin; k < depth_end; ++k) { - norm += in_shaped(i, k) * in_shaped(i, k); - } - norm = alpha_ * norm + bias_; - DCHECK_GT(norm, T(1e-6)); - for (int64 k = depth_begin; k < depth_end; ++k) { - T dyi = T(-2) * alpha_ * beta_ * in_shaped(i, k) * - activations(i, j) / norm; - if (k == j) { - dyi += Eigen::numext::pow(norm, -beta_); - } - dyi *= grads_shaped(i, j); - const_cast::Tensor&>(out_shaped)(i, k) += - dyi; - } - } - } - }; - auto worker_threads = - *(context->device()->tensorflow_cpu_worker_threads()); - Shard(worker_threads.num_threads, worker_threads.workers, nodes * batch, - depth * depth, shard); - } - - // release mkl resources - void Mklcleanup() { - bool ingrad_in_mkl_format = ingrad_shape.IsMklTensor(); - bool inimage_in_mkl_format = inimage_shape.IsMklTensor(); - if (!ingrad_in_mkl_format) { - CHECK_EQ(dnnLayoutDelete_F32(lt_input), E_SUCCESS); - } - - if (!inimage_in_mkl_format) { - CHECK_EQ(dnnLayoutDelete_F32(lt_output), E_SUCCESS); - } - dnnDelete_F32(lrn_bwd); - dnnLayoutDelete_F32(lt_bdw_input); - dnnLayoutDelete_F32(lt_workspace); - } - } MklLRNGradOpContext; - - typedef typename Eigen::Tensor::DimensionPair DimPair; - bool workspace_enabled_; - int depth_radius_; - float bias_; - float alpha_; - float beta_; -}; - -#else - template class MklLRNOp : public OpKernel { public: @@ -743,11 +71,10 @@ class MklLRNOp : public OpKernel { explicit MklLRNOp(OpKernelConstruction* context) : OpKernel(context) { int64 depth_radius64; OP_REQUIRES_OK(context, context->GetAttr("depth_radius", &depth_radius64)); - OP_REQUIRES( - context, - FastBoundsCheck(depth_radius64, std::numeric_limits::max()), - errors::InvalidArgument("depth_radius = ", depth_radius64, - " larger than int max")); + OP_REQUIRES(context, FastBoundsCheck(depth_radius64, + std::numeric_limits::max()), + errors::InvalidArgument("depth_radius = ", depth_radius64, + " larger than int max")); depth_radius_ = static_cast(depth_radius64); OP_REQUIRES_OK(context, context->GetAttr("bias", &bias_)); @@ -833,9 +160,9 @@ class MklLRNOp : public OpKernel { PrepareAndExecuteNet(lrn_prim_desc, &src_dnn_data, &dst_dnn_data, &workspace_dnn_data); } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK( context, errors::Aborted("Operation received an exception:", error_msg)); @@ -847,7 +174,6 @@ class MklLRNOp : public OpKernel { MklDnnData* src_dnn_data, MklDnnData* dst_dnn_data, MklDnnData* wksp_dnn_data = nullptr) { - // Check for input reorder src_dnn_data->CheckReorderToOpMem(lrn_fwd_desc.src_primitive_desc()); @@ -965,16 +291,14 @@ class MklLRNOp : public OpKernel { if (src_dnn_shape.IsMklTensor()) { OP_REQUIRES(context, src_dnn_shape.GetDimension() == 4, errors::InvalidArgument("input must be 4-dimensional")); - OP_REQUIRES(context, - FastBoundsCheck(src_tensor.NumElements(), - std::numeric_limits::max()), + OP_REQUIRES(context, FastBoundsCheck(src_tensor.NumElements(), + std::numeric_limits::max()), errors::InvalidArgument("argument to LRN too large")); } else { OP_REQUIRES(context, src_tensor.dims() == 4, errors::InvalidArgument("input must be 4-dimensional")); - OP_REQUIRES(context, - FastBoundsCheck(src_tensor.NumElements(), - std::numeric_limits::max()), + OP_REQUIRES(context, FastBoundsCheck(src_tensor.NumElements(), + std::numeric_limits::max()), errors::InvalidArgument("argument to LRN too large")); } } @@ -994,11 +318,10 @@ class MklLRNGradOp : public OpKernel { explicit MklLRNGradOp(OpKernelConstruction* context) : OpKernel(context) { int64 depth_radius64; OP_REQUIRES_OK(context, context->GetAttr("depth_radius", &depth_radius64)); - OP_REQUIRES( - context, - FastBoundsCheck(depth_radius64, std::numeric_limits::max()), - errors::InvalidArgument("depth_radius = ", depth_radius64, - " larger than int max")); + OP_REQUIRES(context, FastBoundsCheck(depth_radius64, + std::numeric_limits::max()), + errors::InvalidArgument("depth_radius = ", depth_radius64, + " larger than int max")); depth_radius_ = static_cast(depth_radius64); OP_REQUIRES_OK(context, context->GetAttr("bias", &bias_)); OP_REQUIRES_OK(context, context->GetAttr("alpha", &alpha_)); @@ -1105,9 +428,9 @@ class MklLRNGradOp : public OpKernel { memory::primitive_desc(target_diff_dst_md, cpu_engine), &workspace_dnn_data); } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK( context, errors::Aborted("Operation received an exception:", error_msg)); @@ -1160,7 +483,6 @@ class MklLRNGradOp : public OpKernel { MklDnnData* output_diff_src, const memory::primitive_desc& target_diff_dst_pd, const MklDnnData* workspace_dnn_data = nullptr) { - // Check for input reordering on the diff dst input input_gradient_diff_dst->CheckReorderToOpMem( lrn_bkwd_desc.diff_dst_primitive_desc()); @@ -1345,8 +667,6 @@ class MklLRNGradOp : public OpKernel { float beta_; }; -#endif // INTEL_MKL_ML_ONLY - #define REGISTER_MKL_LRN_CPU(T) \ REGISTER_KERNEL_BUILDER(Name("_MklLRN") \ .Device(DEVICE_CPU) \ diff --git a/tensorflow/core/kernels/mkl_maxpooling_op.cc b/tensorflow/core/kernels/mkl_maxpooling_op.cc index 256d48f4d5..0697251c7d 100644 --- a/tensorflow/core/kernels/mkl_maxpooling_op.cc +++ b/tensorflow/core/kernels/mkl_maxpooling_op.cc @@ -399,19 +399,18 @@ class MklMaxPoolingGradOp : public OpKernel { if (workspace_enabled == false) { if (convert_input != nullptr) { if (input_in_mkl_format == false) { - CHECK_EQ(dnnConversionExecute_F32( - convert_input, - const_cast(static_cast( - tensor_in.flat().data())), - input_buf), - E_SUCCESS); + CHECK_EQ( + dnnConversionExecute_F32( + convert_input, const_cast(static_cast( + tensor_in.flat().data())), + input_buf), + E_SUCCESS); CHECK_EQ(dnnDelete_F32(convert_input), E_SUCCESS); convert_input = nullptr; } else { input_shape.GetConvertedFlatData( - lt_input_prim, - const_cast( - static_cast(tensor_in.flat().data())), + lt_input_prim, const_cast(static_cast( + tensor_in.flat().data())), input_buf); } pooling_resfwd[dnnResourceSrc] = input_buf; @@ -456,9 +455,8 @@ class MklMaxPoolingGradOp : public OpKernel { CHECK_EQ(dnnDelete_F32(convert_outbackprop), E_SUCCESS); } else { output_backprop_shape.GetConvertedFlatData( - lt_outbackprop_prim, - const_cast( - static_cast(out_backprop.flat().data())), + lt_outbackprop_prim, const_cast(static_cast( + out_backprop.flat().data())), outbackprop_buf); } pooling_res[dnnResourceDiffDst] = outbackprop_buf; @@ -520,7 +518,6 @@ class MklMaxPoolingOp : public MklPoolingForwardOpBase { MklDnnData dnn_data_input(&cpu_engine); MklDnnData dnn_data_output(&cpu_engine); - MklDnnData dnn_data_wksp(&cpu_engine); // initialize variables for the pooling op MklPoolParameters pool_params; @@ -550,13 +547,13 @@ class MklMaxPoolingOp : public MklPoolingForwardOpBase { dnn_shape_input.IsMklTensor() ? dnn_shape_input.GetMklLayout() : is_pool2d ? memory::desc( - TFShapeToMklDnnDimsInNCHW(input_tensor_shape, - this->data_format_tf_), - MklDnnType(), this->data_format_mkldnn_) - : memory::desc( - TFShapeToMklDnnDimsInNCDHW( - input_tensor_shape, this->data_format_tf_), - MklDnnType(), this->data_format_mkldnn_); + TFShapeToMklDnnDimsInNCHW( + input_tensor_shape, this->data_format_tf_), + MklDnnType(), this->data_format_mkldnn_) + : memory::desc( + TFShapeToMklDnnDimsInNCDHW( + input_tensor_shape, this->data_format_tf_), + MklDnnType(), this->data_format_mkldnn_); // Get src/filter/stride/padding information memory::dims src_dims = @@ -564,17 +561,24 @@ class MklMaxPoolingOp : public MklPoolingForwardOpBase { ? dnn_shape_input.GetSizesAsMklDnnDims() : is_pool2d ? TFShapeToMklDnnDimsInNCHW(input_tensor.shape(), this->data_format_tf_) - : TFShapeToMklDnnDimsInNCDHW(input_tensor.shape(), - this->data_format_tf_); + : TFShapeToMklDnnDimsInNCDHW(input_tensor.shape(), + this->data_format_tf_); memory::dims filter_dims, strides, padding_left, padding_right; this->PoolParamsToDims(&pool_params, &filter_dims, &strides, &padding_left, &padding_right, is_pool2d); // Get a pooling op from the cached pool MklPoolingFwdPrimitive* pooling_fwd = nullptr; + prop_kind pooling_prop_kind; + bool int8_forward_inference = + std::is_same::value || std::is_same::value; + if (int8_forward_inference) + pooling_prop_kind = prop_kind::forward_inference; + else + pooling_prop_kind = prop_kind::forward_training; MklPoolingParams fwdParams(src_dims, output_dims_mkl_order, filter_dims, strides, padding_left, padding_right, - algorithm::pooling_max); + algorithm::pooling_max, pooling_prop_kind); pooling_fwd = MklPoolingFwdPrimitiveFactory::Get(fwdParams); // allocate output tensor @@ -586,10 +590,6 @@ class MklMaxPoolingOp : public MklPoolingForwardOpBase { pooling_fwd->GetDstMemoryFormat(), output_tensor); - AllocateWorkspaceTensor(context, *(pooling_fwd->GetPoolingFwdPd()), - &dnn_data_wksp); - OP_REQUIRES_OK(context, context->status()); - // check wehther we need to reorder src const T* src_data = input_tensor.flat().data(); if (input_md.data.format != pooling_fwd->GetSrcMemoryFormat()) { @@ -603,14 +603,43 @@ class MklMaxPoolingOp : public MklPoolingForwardOpBase { } T* dst_data = output_tensor->flat().data(); - void* ws_data = dnn_data_wksp.GetOpMem().get_data_handle(); - // execute pooling op - pooling_fwd->Execute(src_data, dst_data, ws_data); + if (int8_forward_inference) { + // Execute pooling op + pooling_fwd->Execute(src_data, dst_data); + + // pass min, max from input to output + const Tensor& min_input_t = MklGetInput(context, 1); + const Tensor& max_input_t = MklGetInput(context, 2); + const float min_input = min_input_t.flat()(0); + const float max_input = max_input_t.flat()(0); + + Tensor* output_min = nullptr; + Tensor* output_max = nullptr; + MklDnnShape output_min_mkl_shape, output_max_mkl_shape; + output_min_mkl_shape.SetMklTensor(false); + output_max_mkl_shape.SetMklTensor(false); + AllocateOutputSetMklShape(context, 1, &output_min, {}, + output_min_mkl_shape); + AllocateOutputSetMklShape(context, 2, &output_max, {}, + output_max_mkl_shape); + output_min->flat()(0) = min_input; + output_max->flat()(0) = max_input; + } else { + MklDnnData dnn_data_wksp(&cpu_engine); + AllocateWorkspaceTensor(context, *(pooling_fwd->GetPoolingFwdPd()), + &dnn_data_wksp); + OP_REQUIRES_OK(context, context->status()); + T* ws_data = + static_cast(dnn_data_wksp.GetOpMem().get_data_handle()); + + // execute pooling op + pooling_fwd->Execute(src_data, dst_data, ws_data); + } } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + - ", message: " + string(e.message) + ", in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + ", message: " + + string(e.message) + ", in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK(context, errors::Aborted("Compute received an exception:", error_msg)); } @@ -684,24 +713,25 @@ class MklMaxPoolingGradOp : public MklPoolingBackwardOpBase { orig_input_mkl_shape.IsMklTensor() ? orig_input_mkl_shape.GetSizesAsMklDnnDims() : is_pool2d ? TFShapeToMklDnnDimsInNCHW(orig_input_shape, - this->data_format_tf_) - : TFShapeToMklDnnDimsInNCDHW(orig_input_shape, - this->data_format_tf_); + this->data_format_tf_) + : TFShapeToMklDnnDimsInNCDHW(orig_input_shape, + this->data_format_tf_); memory::dims diff_dst_dims = grad_mkl_shape.IsMklTensor() ? grad_mkl_shape.GetSizesAsMklDnnDims() : is_pool2d ? TFShapeToMklDnnDimsInNCHW(grad_tensor.shape(), - this->data_format_tf_) - : TFShapeToMklDnnDimsInNCDHW(grad_tensor.shape(), - this->data_format_tf_); + this->data_format_tf_) + : TFShapeToMklDnnDimsInNCDHW(grad_tensor.shape(), + this->data_format_tf_); memory::dims output_dims_mkl_order; this->GetOutputDims(pool_params, &output_dims_mkl_order); MklPoolingParams bwdParams( orig_input_dims_mkl_order, output_dims_mkl_order, filter_dims, - strides, padding_left, padding_right, algorithm::pooling_max); + strides, padding_left, padding_right, algorithm::pooling_max, + prop_kind::forward_training); MklPoolingBwdPrimitive* pooling_bwd = MklPoolingBwdPrimitiveFactory::Get(bwdParams); @@ -751,9 +781,9 @@ class MklMaxPoolingGradOp : public MklPoolingBackwardOpBase { // execute pooling pooling_bwd->Execute(diff_dst_data, diff_src_data, ws_data); } catch (mkldnn::error& e) { - string error_msg = "Status:" + std::to_string(e.status) + - ", message: " + string(e.message) + ". in file " + - string(__FILE__) + ":" + std::to_string(__LINE__); + string error_msg = "Status:" + std::to_string(e.status) + ", message: " + + string(e.message) + ". in file " + string(__FILE__) + + ":" + std::to_string(__LINE__); OP_REQUIRES_OK(context, errors::Aborted("Compute received an exception:", error_msg)); } @@ -788,39 +818,38 @@ class MklMaxPoolingGradOp : public MklPoolingBackwardOpBase { const MklDnnShape& workspace_mkl_shape) { if (!orig_input_mkl_shape.IsMklTensor()) { OP_REQUIRES(context, orig_input_tensor.dims() == 4, - errors::InvalidArgument("Original input shape must be " - "4-dimensional")); + errors::InvalidArgument( + "Original input shape must be 4-dimensional")); } else { OP_REQUIRES(context, orig_input_mkl_shape.GetDimension() == 4, - errors::InvalidArgument("Original input shape must be " - "4-dimensional")); + errors::InvalidArgument( + "Original input shape must be 4-dimensional")); } if (!orig_output_mkl_shape.IsMklTensor()) { - OP_REQUIRES(context, orig_output_tensor.dims() == 4, - errors::InvalidArgument("Original output must be " - "4-dimensional")); + OP_REQUIRES( + context, orig_output_tensor.dims() == 4, + errors::InvalidArgument("Original output must be 4-dimensional")); } else { - OP_REQUIRES(context, orig_output_mkl_shape.GetDimension() == 4, - errors::InvalidArgument("Original output must be " - "4-dimensional")); + OP_REQUIRES( + context, orig_output_mkl_shape.GetDimension() == 4, + errors::InvalidArgument("Original output must be 4-dimensional")); } if (!grad_mkl_shape.IsMklTensor()) { OP_REQUIRES(context, grad_tensor.dims() == 4, errors::InvalidArgument("Gradient must be 4-dimensional")); } else { OP_REQUIRES(context, grad_mkl_shape.GetDimension() == 4, - errors::InvalidArgument("Gradient must be " - "4-dimensional")); + errors::InvalidArgument("Gradient must be 4-dimensional")); } if (this->workspace_enabled_) { // The workspace should not be an MKL tensor OP_REQUIRES(context, workspace_mkl_shape.IsMklTensor() == false, - errors::InvalidArgument("Workspace tensor should not" - " be an MKL Tensor.")); + errors::InvalidArgument( + "Workspace tensor should not be an MKL Tensor.")); // It should only have one dimension - OP_REQUIRES(context, workspace_tensor.dims() == 1, - errors::InvalidArgument("Workspace tensor must be " - "1-dimensional")); + OP_REQUIRES( + context, workspace_tensor.dims() == 1, + errors::InvalidArgument("Workspace tensor must be 1-dimensional")); } else { OP_REQUIRES( context, this->workspace_enabled_, @@ -852,6 +881,18 @@ REGISTER_KERNEL_BUILDER(Name("_MklMaxPool") .Label(mkl_op_registry::kMklOpLabel), MklMaxPoolingOp); +REGISTER_KERNEL_BUILDER(Name("_MklQuantizedMaxPool") + .Device(DEVICE_CPU) + .TypeConstraint("T") + .Label(mkl_op_registry::kMklQuantizedOpLabel), + MklMaxPoolingOp); + +REGISTER_KERNEL_BUILDER(Name("_MklQuantizedMaxPool") + .Device(DEVICE_CPU) + .TypeConstraint("T") + .Label(mkl_op_registry::kMklQuantizedOpLabel), + MklMaxPoolingOp); + REGISTER_KERNEL_BUILDER(Name("_MklMaxPoolGrad") .Device(DEVICE_CPU) .TypeConstraint("T") diff --git a/tensorflow/core/kernels/mkl_pooling_ops_common.cc b/tensorflow/core/kernels/mkl_pooling_ops_common.cc index 5398e6113f..dc84d3941e 100644 --- a/tensorflow/core/kernels/mkl_pooling_ops_common.cc +++ b/tensorflow/core/kernels/mkl_pooling_ops_common.cc @@ -41,28 +41,33 @@ void MklPoolingFwdPrimitive::Setup(const MklPoolingParams& fwdParams) { << "Pooling algorithm kind is not supported"; context_.alg_kind = fwdParams.alg_kind; + context_.prop_kind = fwdParams.prop_kind; + // create memory desc // FIXME: Pooling doesn't expose to get the src_primitive_desc, // so src format is currently hard-coded. // A utility function is used to do this, // which may be broken with future CPU architectures bool is_2d = (fwdParams.src_dims.size() == 4); - context_.src_md.reset( - new memory::desc({fwdParams.src_dims}, MklDnnType(), - get_desired_format(fwdParams.src_dims[1], is_2d))); + if (std::is_same::value || std::is_same::value) + context_.src_fmt = is_2d ? memory::format::nhwc : memory::format::ndhwc; + else + context_.src_fmt = get_desired_format(fwdParams.src_dims[1], is_2d); + + context_.src_md.reset(new memory::desc({fwdParams.src_dims}, MklDnnType(), + context_.src_fmt)); context_.dst_md.reset(new memory::desc({fwdParams.dst_dims}, MklDnnType(), memory::format::any)); // create a pooling descriptor context_.fwd_desc.reset(new pooling_forward::desc( - prop_kind::forward_training, fwdParams.alg_kind, *context_.src_md, + fwdParams.prop_kind, fwdParams.alg_kind, *context_.src_md, *context_.dst_md, fwdParams.strides, fwdParams.filter_dims, fwdParams.padding_left, fwdParams.padding_right, padding_kind::zero)); context_.fwd_pd.reset( new pooling_forward::primitive_desc(*context_.fwd_desc, cpu_engine_)); // store expected primitive format - context_.src_fmt = get_desired_format(fwdParams.src_dims[1], is_2d); context_.dst_fmt = static_cast( context_.fwd_pd.get()->dst_primitive_desc().desc().data.format); @@ -74,7 +79,8 @@ void MklPoolingFwdPrimitive::Setup(const MklPoolingParams& fwdParams) { new memory(context_.fwd_pd.get()->dst_primitive_desc(), DummyData)); // for max pooling, need to return workspace(ws) for backward computing - if (fwdParams.alg_kind == pooling_max) { + if (fwdParams.alg_kind == pooling_max && + fwdParams.prop_kind == prop_kind::forward_training) { auto ws_pd = context_.fwd_pd.get()->workspace_primitive_desc().desc().data; // store workspace's dims and format to create workspace tensor context_.ws_fmt = static_cast(ws_pd.format); @@ -101,7 +107,9 @@ void MklPoolingFwdPrimitive::Execute(const T* src_data, T* dst_data, context_.src_mem->set_data_handle( static_cast(const_cast(src_data))); context_.dst_mem->set_data_handle(static_cast(dst_data)); - if (context_.alg_kind == pooling_max) { // max pooling must have ws + if (context_.alg_kind == pooling_max && + context_.prop_kind == + prop_kind::forward_training) { // max pooling must have ws DCHECK(ws_data != nullptr); context_.ws_mem->set_data_handle(ws_data); } @@ -110,13 +118,17 @@ void MklPoolingFwdPrimitive::Execute(const T* src_data, T* dst_data, // set back data handle context_.src_mem->set_data_handle(DummyData); context_.dst_mem->set_data_handle(DummyData); - if (context_.alg_kind == pooling_max) { // max pooling must have ws + if (context_.alg_kind == pooling_max && + context_.prop_kind == + prop_kind::forward_training) { // max pooling must have ws DCHECK(ws_data != nullptr); context_.ws_mem->set_data_handle(DummyData); } } template class MklPoolingFwdPrimitive; +template class MklPoolingFwdPrimitive; +template class MklPoolingFwdPrimitive; template void MklPoolingBwdPrimitive::Setup(const MklPoolingParams& bwdParams) { @@ -143,7 +155,7 @@ void MklPoolingBwdPrimitive::Setup(const MklPoolingParams& bwdParams) { // create a forward primitive, // which will be used as a hint for creating backward primitive context_.fwd_desc.reset(new pooling_forward::desc( - prop_kind::forward_training, bwdParams.alg_kind, *context_.diff_src_md, + bwdParams.prop_kind, bwdParams.alg_kind, *context_.diff_src_md, *context_.diff_dst_md, bwdParams.strides, bwdParams.filter_dims, bwdParams.padding_left, bwdParams.padding_right, padding_kind::zero)); context_.fwd_pd.reset( diff --git a/tensorflow/core/kernels/mkl_pooling_ops_common.h b/tensorflow/core/kernels/mkl_pooling_ops_common.h index 49f799d7ba..8a60c3be91 100644 --- a/tensorflow/core/kernels/mkl_pooling_ops_common.h +++ b/tensorflow/core/kernels/mkl_pooling_ops_common.h @@ -18,8 +18,8 @@ limitations under the License. #ifdef INTEL_MKL #include -#include #include +#include #include "tensorflow/core/util/mkl_util.h" #include "tensorflow/core/util/padding.h" @@ -50,18 +50,20 @@ struct MklPoolingParams { memory::dims padding_left; memory::dims padding_right; mkldnn::algorithm alg_kind; + mkldnn::prop_kind prop_kind; MklPoolingParams(memory::dims src_dims, memory::dims dst_dims, memory::dims filter_dims, memory::dims strides, memory::dims padding_left, memory::dims padding_right, - mkldnn::algorithm alg_kind) + mkldnn::algorithm alg_kind, mkldnn::prop_kind prop_kind) : src_dims(src_dims), dst_dims(dst_dims), filter_dims(filter_dims), strides(strides), padding_left(padding_left), padding_right(padding_right), - alg_kind(alg_kind) {} + alg_kind(alg_kind), + prop_kind(prop_kind) {} }; template @@ -97,6 +99,9 @@ class MklPoolingFwdPrimitive : public MklPrimitive { // algorithm mkldnn::algorithm alg_kind; + // Kind of propagation, forward or backward + mkldnn::prop_kind prop_kind; + // expected memory format memory::format src_fmt; memory::format dst_fmt; @@ -187,6 +192,7 @@ class MklPoolingFwdPrimitiveFactory : public MklPrimitiveFactory { key_creator.AddAsKey(fwdParams.padding_left); key_creator.AddAsKey(fwdParams.padding_right); key_creator.AddAsKey(static_cast(fwdParams.alg_kind)); + key_creator.AddAsKey(static_cast(fwdParams.prop_kind)); return key_creator.GetKey(); } @@ -443,7 +449,12 @@ class MklPoolingOpBase : public OpKernel { explicit MklPoolingOpBase(OpKernelConstruction* context) : OpKernel(context), workspace_enabled_(false) { string data_format; - OP_REQUIRES_OK(context, context->GetAttr("data_format", &data_format)); + if (std::is_same::value || std::is_same::value) { + // current quantized convolution doesn't have data_format attribute. + data_format = "NHWC"; + } else { + OP_REQUIRES_OK(context, context->GetAttr("data_format", &data_format)); + } OP_REQUIRES(context, FormatFromString(data_format, &this->data_format_tf_), errors::InvalidArgument("Invalid data format")); OP_REQUIRES_OK(context, context->GetAttr("ksize", &this->ksize_)); @@ -461,7 +472,7 @@ class MklPoolingOpBase : public OpKernel { bool is_pool2d = (this->ksize_.size() == 4); this->data_format_mkldnn_ = is_pool2d ? TFDataFormatToMklDnnDataFormat(this->data_format_tf_) - : TFDataFormatToMklDnn3DDataFormat(this->data_format_tf_); + : TFDataFormatToMklDnn3DDataFormat(this->data_format_tf_); // We may not get this attribute for this node if it does not go through // graph rewrite pass. So we do not check for error while retrieving this @@ -655,10 +666,10 @@ class MklPoolingForwardOpBase : public MklPoolingOpBase { OP_REQUIRES(context, input_tensor.dims() == 4 || input_tensor.dims() == 5, errors::InvalidArgument("Input must be 4 or 5-dimensional")); } else { - OP_REQUIRES(context, input_mkl_shape.GetDimension() == 4 || - input_mkl_shape.GetDimension() == 5, - errors::InvalidArgument("Input shape must be " - "4 or 5-dimensional")); + OP_REQUIRES( + context, input_mkl_shape.GetDimension() == 4 || + input_mkl_shape.GetDimension() == 5, + errors::InvalidArgument("Input shape must be 4 or 5-dimensional")); } } // .Input("value: T") diff --git a/tensorflow/core/kernels/mkl_quantized_pooling_ops_test.cc b/tensorflow/core/kernels/mkl_quantized_pooling_ops_test.cc new file mode 100644 index 0000000000..7c1e32d6e3 --- /dev/null +++ b/tensorflow/core/kernels/mkl_quantized_pooling_ops_test.cc @@ -0,0 +1,201 @@ +/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifdef INTEL_MKL +#define EIGEN_USE_THREADS + +#include "tensorflow/core/framework/allocator.h" +#include "tensorflow/core/framework/fake_input.h" +#include "tensorflow/core/framework/node_def_builder.h" +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/tensor.h" +#include "tensorflow/core/framework/tensor_testutil.h" +#include "tensorflow/core/framework/types.h" +#include "tensorflow/core/framework/types.pb.h" +#include "tensorflow/core/kernels/ops_testutil.h" +#include "tensorflow/core/kernels/ops_util.h" +#include "tensorflow/core/kernels/quantization_utils.h" +#include "tensorflow/core/lib/core/status_test_util.h" +#include "tensorflow/core/platform/test.h" + +namespace tensorflow { + +// Helper class for converting MKL tensors to TF tensors and comparing to +// expected values + +static const uint8 dummy_tensor[] = {0, 0, 0, 0, 0, 0, 0, 0}; +static const TensorShape dummy_shape({8}); + +class ConvMklToTF : public OpsTestBase { + public: + template + void ConvertMKL2TF(DataType dtype, const Tensor& first, const Tensor& second, + Tensor& output) { + // Create an MKL to TF conversion node and execute it + TF_EXPECT_OK(NodeDefBuilder("mkl_to_tf_op", "_MklToTf") + .Input(FakeInput(dtype)) // Input + .Input(FakeInput(DT_UINT8)) // Mkl second tensor + .Attr("T", dtype) + .Attr("_kernel", "MklOp") + .Finalize(node_def())); + TF_EXPECT_OK(InitOp()); + AddInputFromArray(first.shape(), first.flat()); + AddInputFromArray(second.shape(), second.flat()); + TF_ASSERT_OK(RunOpKernel()); + + output = *GetOutput(0); + } + void TestBody(){}; +}; + +class QuantizedPoolingTest : public OpsTestBase {}; + +TEST_F(QuantizedPoolingTest, SmallAveragePooling) { + const int ksize = 2; + const int stride = 2; + TF_ASSERT_OK(NodeDefBuilder("quantized_avg_pool_op", "_MklQuantizedAvgPool") + .Input(FakeInput(DT_QUINT8)) + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_UINT8)) // MKl second tensor + .Input(FakeInput(DT_UINT8)) // MKl second tensor + .Input(FakeInput(DT_UINT8)) // MKl second tensor + .Attr("T", DataTypeToEnum::v()) + .Attr("ksize", {1, ksize, ksize, 1}) + .Attr("strides", {1, stride, stride, 1}) + .Attr("padding", "SAME") + .Attr("_kernel", "QuantizedMklOp") + .Finalize(node_def())); + TF_ASSERT_OK(InitOp()); + const float input_min = 0.0f; + const float input_max = 255.0f; + const int input_height = 4; + const int input_width = 4; + const int input_channels = 2; + Tensor input_float(DT_FLOAT, {1, input_height, input_width, input_channels}); + test::FillValues( + &input_float, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}); + Tensor input_quantized = + FloatTensorToQuantized(input_float, input_min, input_max); + + const int expected_width = input_width / stride; + const int expected_height = input_height / stride; + + // The input pools we are averaging. (NHWC input, quantized.) + // 0th channel 1st channel + // 1 3 | 5 7 2 4 | 6 8 + // 9 11 | 13 15 10 12 | 14 16 + // ------------- ------------- + // 17 19 | 21 23 18 20 | 22 24 + // 25 27 | 29 31 26 28 | 30 32 + Tensor expected_float(DT_FLOAT, + {1, expected_height, expected_width, input_channels}); + test::FillValues(&expected_float, {6, 7, 10, 11, 22, 23, 26, 27}); + + AddInputFromArray(input_quantized.shape(), + input_quantized.flat()); + AddInputFromArray(TensorShape({1}), {input_min}); + AddInputFromArray(TensorShape({1}), {input_max}); + AddInputFromArray(dummy_shape, dummy_tensor); + AddInputFromArray(dummy_shape, dummy_tensor); + AddInputFromArray(dummy_shape, dummy_tensor); + + TF_ASSERT_OK(RunOpKernel()); + + const Tensor& output = *GetOutput(0); + const Tensor& mkl_shape_tensor = *GetOutput(3); + ConvMklToTF conv_comp; + Tensor output_quantized; + conv_comp.ConvertMKL2TF(DT_QUINT8, output, mkl_shape_tensor, + output_quantized); + + const float output_min = GetOutput(1)->flat()(0); + const float output_max = GetOutput(2)->flat()(0); + Tensor output_float = + QuantizedTensorToFloat(output_quantized, output_min, output_max); + + test::ExpectTensorNear(expected_float, output_float, 0.2); +} + +TEST_F(QuantizedPoolingTest, SmallMaxPooling) { + const int ksize = 2; + const int stride = 2; + TF_ASSERT_OK(NodeDefBuilder("quantized_max_pool_op", "_MklQuantizedMaxPool") + .Input(FakeInput(DT_QUINT8)) + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_UINT8)) // MKl second tensor + .Input(FakeInput(DT_UINT8)) // MKl second tensor + .Input(FakeInput(DT_UINT8)) // MKl second tensor + .Attr("T", DataTypeToEnum::v()) + .Attr("ksize", {1, ksize, ksize, 1}) + .Attr("strides", {1, stride, stride, 1}) + .Attr("padding", "SAME") + .Attr("_kernel", "QuantizedMklOp") + .Finalize(node_def())); + TF_ASSERT_OK(InitOp()); + const float input_min = 0.0f; + const float input_max = 255.0f; + const int input_height = 4; + const int input_width = 4; + const int input_channels = 2; + Tensor input_float(DT_FLOAT, {1, input_height, input_width, input_channels}); + test::FillValues( + &input_float, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}); + Tensor input_quantized = + FloatTensorToQuantized(input_float, input_min, input_max); + const int expected_width = input_width / stride; + const int expected_height = input_height / stride; + + // The max is computed from these input pools. (NHWC input, quantized.) + // 0th channel 1st channel + // 1 3 | 5 7 2 4 | 6 8 + // 9 11 | 13 15 10 12 | 14 16 + // ------------- ------------- + // 17 19 | 21 23 18 20 | 22 24 + // 25 27 | 29 31 26 28 | 30 32 + + Tensor expected_float(DT_FLOAT, + {1, expected_height, expected_width, input_channels}); + test::FillValues(&expected_float, {11, 12, 15, 16, 27, 28, 31, 32}); + AddInputFromArray(input_quantized.shape(), + input_quantized.flat()); + AddInputFromArray(TensorShape({1}), {input_min}); + AddInputFromArray(TensorShape({1}), {input_max}); + AddInputFromArray(dummy_shape, dummy_tensor); + AddInputFromArray(dummy_shape, dummy_tensor); + AddInputFromArray(dummy_shape, dummy_tensor); + + TF_ASSERT_OK(RunOpKernel()); + + const Tensor& output = *GetOutput(0); + const Tensor& mkl_shape_tensor = *GetOutput(3); + ConvMklToTF conv_comp; + Tensor output_quantized; + conv_comp.ConvertMKL2TF(DT_QUINT8, output, mkl_shape_tensor, + output_quantized); + + const float output_min = GetOutput(1)->flat()(0); + const float output_max = GetOutput(2)->flat()(0); + Tensor output_float = + QuantizedTensorToFloat(output_quantized, output_min, output_max); + + test::ExpectTensorNear(expected_float, output_float, 0.2); +} +} // namespace tensorflow +#endif diff --git a/tensorflow/core/kernels/mkl_softmax_op.cc b/tensorflow/core/kernels/mkl_softmax_op.cc index cfab529662..3bf17bc449 100644 --- a/tensorflow/core/kernels/mkl_softmax_op.cc +++ b/tensorflow/core/kernels/mkl_softmax_op.cc @@ -56,7 +56,7 @@ class MklSoftmaxOp : public OpKernel { MklDnnShape src_mkl_shape; GetMklShape(context, src_idx, &src_mkl_shape); - // src_dims is the dimenstion of src_tensor + // src_dims is the dimension of src_tensor // dim of the dst will also be same as src_dims auto src_tf_shape = src_mkl_shape.IsMklTensor() ? src_mkl_shape.GetTfShape() @@ -68,7 +68,7 @@ class MklSoftmaxOp : public OpKernel { // Here "x" data format in MKL is used for 1 dim tensor, "nc" for 2 dim tensor, // "tnc" for 3 dim tensor, "nchw" for 4 dim tensor, and "ncdhw" for 5 dim tensor. // Each of the simbols has the following meaning: - // n = batch, c = channels, t = sequence lenght, h = height, + // n = batch, c = channels, t = sequence length, h = height, // w = width, d = depth switch (input_dims) { case 1: diff --git a/tensorflow/core/kernels/partitioned_function_ops.cc b/tensorflow/core/kernels/partitioned_function_ops.cc index 71e506e5e6..30a8be141c 100644 --- a/tensorflow/core/kernels/partitioned_function_ops.cc +++ b/tensorflow/core/kernels/partitioned_function_ops.cc @@ -28,6 +28,7 @@ limitations under the License. #include "tensorflow/core/grappler/grappler_item.h" #include "tensorflow/core/grappler/optimizers/meta_optimizer.h" #include "tensorflow/core/grappler/utils/functions.h" +#include "tensorflow/core/protobuf/config.pb.h" #include "tensorflow/core/protobuf/rewriter_config.pb.h" #include "tensorflow/core/util/ptr_util.h" #include "tensorflow/core/util/reffed_status_callback.h" @@ -50,12 +51,29 @@ class PartitionedCallOp : public AsyncOpKernel { public: explicit PartitionedCallOp(OpKernelConstruction* ctx) : AsyncOpKernel(ctx) { OP_REQUIRES_OK(ctx, ctx->GetAttr("f", &func_)); - string rewriter_config_serialized; - OP_REQUIRES_OK(ctx, ctx->GetAttr("config", &rewriter_config_serialized)); + string deprecated_config_serialized; + OP_REQUIRES_OK(ctx, ctx->GetAttr("config", &deprecated_config_serialized)); + string config_proto_serialized; + OP_REQUIRES_OK(ctx, ctx->GetAttr("config_proto", &config_proto_serialized)); OP_REQUIRES( - ctx, rewriter_config_.ParseFromString(rewriter_config_serialized), - errors::InvalidArgument("Unable to parse rewriter_config string as " - "tensorflow::RewriterConfig proto.")); + ctx, + deprecated_config_serialized.empty() || config_proto_serialized.empty(), + errors::InvalidArgument("Provided both 'config' and 'config_proto' but " + "only one should be provided. Note the " + "'config' option is deprecated.")); + if (!deprecated_config_serialized.empty()) { + OP_REQUIRES(ctx, + config_proto_.mutable_graph_options() + ->mutable_rewrite_options() + ->ParseFromString(deprecated_config_serialized), + errors::InvalidArgument("Unable to parse config string as " + "tensorflow::RewriteOptions proto.")); + } else { + OP_REQUIRES( + ctx, config_proto_.ParseFromString(config_proto_serialized), + errors::InvalidArgument("Unable to parse config_proto string as " + "tensorflow::ConfigProto proto.")); + } OP_REQUIRES_OK(ctx, ctx->GetAttr("executor_type", &executor_type_)); } @@ -435,7 +453,7 @@ class PartitionedCallOp : public AsyncOpKernel { }, rendez, std::move(done), std::placeholders::_1); auto* refcounted_done = new ReffedStatusCallback(std::move(callback)); - for (int i = 1; i < handles->size(); ++i) { + for (int i = 0; i < handles->size(); ++i) { refcounted_done->Ref(); } @@ -489,6 +507,7 @@ class PartitionedCallOp : public AsyncOpKernel { }); } } + refcounted_done->Unref(); } string UniquifyFunctionName(const FunctionLibraryDefinition* function_library, @@ -506,12 +525,18 @@ class PartitionedCallOp : public AsyncOpKernel { FunctionLibraryDefinition* flib, const DeviceSet& device_set, Device* cpu_device, std::unique_ptr* graph) { - if (!tensorflow::grappler::MetaOptimizerEnabled(rewriter_config_)) { + if (!tensorflow::grappler::MetaOptimizerEnabled(config_proto_)) { return Status::OK(); } tensorflow::grappler::GrapplerItem item; + // Add all available devices so that inlined function can be placed. + for (const Device* d : device_set.devices()) { + Status added_device = item.AddDevice(d->name()); + if (!added_device.ok()) VLOG(3) << added_device.error_message(); + } + // Add fetches so that the graph can be pruned. for (Node* node : ret_nodes) { item.fetch.push_back(node->name()); @@ -530,7 +555,7 @@ class PartitionedCallOp : public AsyncOpKernel { // TODO(nareshmodi): Consider adding and using the more generic GraphOptions // proto (which also contain the OptimizerOptions). TF_RETURN_IF_ERROR(tensorflow::grappler::RunMetaOptimizer( - item, rewriter_config_, cpu_device, &cluster, &out_graph)); + item, config_proto_, cpu_device, &cluster, &out_graph)); std::unique_ptr optimized_graph(new Graph(OpRegistry::Global())); TF_RETURN_IF_ERROR(ConvertGraphDefToGraph( @@ -562,7 +587,7 @@ class PartitionedCallOp : public AsyncOpKernel { } NameAttrList func_; - RewriterConfig rewriter_config_; + ConfigProto config_proto_; string executor_type_; // Contains maps from device names to handles of function partitions, keyed by // FunctionLibraryRuntime pointers. (Because this kernel may be instantiated diff --git a/tensorflow/core/kernels/quantize_and_dequantize_op.cc b/tensorflow/core/kernels/quantize_and_dequantize_op.cc index dadc15b69e..f13341e0af 100644 --- a/tensorflow/core/kernels/quantize_and_dequantize_op.cc +++ b/tensorflow/core/kernels/quantize_and_dequantize_op.cc @@ -49,6 +49,21 @@ class QuantizeAndDequantizeV2Op : public OpKernel { errors::InvalidArgument("num_bits is out of range: ", num_bits_, " with signed_input_ ", signed_input_)); OP_REQUIRES_OK(ctx, ctx->GetAttr("range_given", &range_given_)); + + string round_mode_string; + OP_REQUIRES_OK(ctx, ctx->GetAttr("round_mode", &round_mode_string)); + OP_REQUIRES( + ctx, + (round_mode_string == "HALF_UP" || round_mode_string == "HALF_TO_EVEN"), + errors::InvalidArgument("Round mode string must be " + "'HALF_UP' or " + "'HALF_TO_EVEN', is '" + + round_mode_string + "'")); + if (round_mode_string == "HALF_UP") { + round_mode_ = ROUND_HALF_UP; + } else if (round_mode_string == "HALF_TO_EVEN") { + round_mode_ = ROUND_HALF_TO_EVEN; + } } void Compute(OpKernelContext* ctx) override { @@ -76,13 +91,15 @@ class QuantizeAndDequantizeV2Op : public OpKernel { functor::QuantizeAndDequantizeOneScaleFunctor f; f(ctx->eigen_device(), input.flat(), signed_input_, num_bits_, - range_given_, &input_min_tensor, &input_max_tensor, output->flat()); + range_given_, &input_min_tensor, &input_max_tensor, round_mode_, + output->flat()); } private: bool signed_input_; int num_bits_; bool range_given_; + QuantizerRoundMode round_mode_; }; // Simulate quantization precision loss in a float tensor by: @@ -135,7 +152,8 @@ class QuantizeAndDequantizeV3Op : public OpKernel { functor::QuantizeAndDequantizeOneScaleFunctor f; f(ctx->eigen_device(), input.flat(), signed_input_, num_bits_val, - range_given_, &input_min_tensor, &input_max_tensor, output->flat()); + range_given_, &input_min_tensor, &input_max_tensor, ROUND_HALF_TO_EVEN, + output->flat()); } private: @@ -180,7 +198,7 @@ class QuantizeAndDequantizeOp : public OpKernel { functor::QuantizeAndDequantizeOneScaleFunctor functor; functor(ctx->eigen_device(), input.flat(), signed_input_, num_bits_, range_given_, &input_min_tensor, &input_max_tensor, - output->flat()); + ROUND_HALF_TO_EVEN, output->flat()); } private: @@ -198,10 +216,11 @@ struct QuantizeAndDequantizeOneScaleFunctor { void operator()(const CPUDevice& d, typename TTypes::ConstVec input, const bool signed_input, const int num_bits, const bool range_given, Tensor* input_min_tensor, - Tensor* input_max_tensor, typename TTypes::Vec out) { + Tensor* input_max_tensor, QuantizerRoundMode round_mode, + typename TTypes::Vec out) { QuantizeAndDequantizeOneScaleImpl::Compute( d, input, signed_input, num_bits, range_given, input_min_tensor, - input_max_tensor, out); + input_max_tensor, round_mode, out); } }; } // namespace functor diff --git a/tensorflow/core/kernels/quantize_and_dequantize_op.h b/tensorflow/core/kernels/quantize_and_dequantize_op.h index 6b0c5e5a46..a495e8b71f 100644 --- a/tensorflow/core/kernels/quantize_and_dequantize_op.h +++ b/tensorflow/core/kernels/quantize_and_dequantize_op.h @@ -22,6 +22,20 @@ limitations under the License. #include "tensorflow/core/kernels/cwise_ops.h" namespace tensorflow { + +enum QuantizerRoundMode { + // Round half up: if the fraction of y is exactly 0.5, then + // round(y) = y + 0.5 + // E.g., -5.5 gets rounded to -5, -5.4 goes to -5, + // 5.4 goes to 5, and 5.5 goes to 6. + ROUND_HALF_UP, + // Round half to even: if the fraction of y is exactly 0.5, then round(y) is + // the nearest even integer to y. + // E.g., 23.5 gets rounded to 24, 24.5 gets rounded to 24, while -23.5 becomes + // -24, and -24.5 gets rounded to 24. + ROUND_HALF_TO_EVEN, +}; + namespace functor { // TODO(pauldonnelly): 'signed_input' should really be called 'signed_output'. @@ -31,15 +45,69 @@ struct QuantizeAndDequantizeOneScaleFunctor { void operator()(const Device& d, typename TTypes::ConstVec input, bool signed_input, int num_bits, bool range_given, Tensor* input_min_tensor, Tensor* input_max_tensor, - typename TTypes::Vec out); + QuantizerRoundMode round_mode, typename TTypes::Vec out); }; +// The implementation below runs on both CPU and GPU. +template +void ClampScaleAndRound(const Device& d, typename TTypes::ConstVec input, + T min_range, T max_range, T scale, T inverse_scale, + Func round_func, typename TTypes::Vec out) { + out.device(d) = (input.cwiseMin(max_range).cwiseMax(min_range) * scale) + .unaryExpr(round_func) * + inverse_scale; +} + +// The implementation below runs on both CPU and GPU. +template +void ClampScaleAndRound(const Device& d, typename TTypes::ConstVec input, + T min_range, T max_range, T scale, T inverse_scale, + QuantizerRoundMode round_mode, + typename TTypes::Vec out) { + switch (round_mode) { + case ROUND_HALF_TO_EVEN: + ClampScaleAndRound(d, input, min_range, max_range, scale, inverse_scale, + Eigen::internal::scalar_round_op_google(), out); + break; + case ROUND_HALF_UP: + ClampScaleAndRound(d, input, min_range, max_range, scale, inverse_scale, + Eigen::internal::scalar_round_up_op(), out); + break; + } +} + +// The implementation below runs on both CPU and GPU. +template +void ScaleAndRound(const Device& d, typename TTypes::ConstVec input, T scale, + T inverse_scale, Func round_func, + typename TTypes::Vec out) { + out.device(d) = (input * scale).unaryExpr(round_func) * inverse_scale; +} + +// The implementation below runs on both CPU and GPU. +template +void ScaleAndRound(const Device& d, typename TTypes::ConstVec input, T scale, + T inverse_scale, QuantizerRoundMode round_mode, + typename TTypes::Vec out) { + switch (round_mode) { + case ROUND_HALF_TO_EVEN: + ScaleAndRound(d, input, scale, inverse_scale, + Eigen::internal::scalar_round_op_google(), out); + break; + case ROUND_HALF_UP: + ScaleAndRound(d, input, scale, inverse_scale, + Eigen::internal::scalar_round_up_op(), out); + break; + } +} + // The implementation below runs on both CPU and GPU. template struct QuantizeAndDequantizeOneScaleImpl { static void Compute(const Device& d, typename TTypes::ConstVec input, bool signed_input, int num_bits, bool range_given, Tensor* input_min_tensor, Tensor* input_max_tensor, + QuantizerRoundMode round_mode, typename TTypes::Vec out) { T min_range; T max_range; @@ -89,15 +157,10 @@ struct QuantizeAndDequantizeOneScaleImpl { // The semantics of the op does not guarantee to clamp to the specified // min_range and max_range - because we may have changed either min_range // or max_range. - out.device(d) = - (input.cwiseMin(max_range).cwiseMax(min_range) * scale) - .unaryExpr(Eigen::internal::scalar_round_op_google()) * - inverse_scale; + ClampScaleAndRound(d, input, min_range, max_range, scale, inverse_scale, + round_mode, out); } else { - out.device(d) = - (input * scale) - .unaryExpr(Eigen::internal::scalar_round_op_google()) * - inverse_scale; + ScaleAndRound(d, input, scale, inverse_scale, round_mode, out); } } }; diff --git a/tensorflow/core/kernels/quantize_and_dequantize_op_gpu.cu.cc b/tensorflow/core/kernels/quantize_and_dequantize_op_gpu.cu.cc index 61c79cf695..5745e418f3 100644 --- a/tensorflow/core/kernels/quantize_and_dequantize_op_gpu.cu.cc +++ b/tensorflow/core/kernels/quantize_and_dequantize_op_gpu.cu.cc @@ -32,10 +32,10 @@ struct QuantizeAndDequantizeOneScaleFunctor { void operator()(const GPUDevice& d, typename TTypes::ConstVec input, bool signed_input, int num_bits, bool range_given, Tensor* input_min_tensor, Tensor* input_max_tensor, - typename TTypes::Vec out) { + QuantizerRoundMode round_mode, typename TTypes::Vec out) { QuantizeAndDequantizeOneScaleImpl::Compute( d, input, signed_input, num_bits, range_given, input_min_tensor, - input_max_tensor, out); + input_max_tensor, round_mode, out); } }; } // end namespace functor diff --git a/tensorflow/core/kernels/quantize_and_dequantize_op_test.cc b/tensorflow/core/kernels/quantize_and_dequantize_op_test.cc index cddabf8a99..b9e015c96b 100644 --- a/tensorflow/core/kernels/quantize_and_dequantize_op_test.cc +++ b/tensorflow/core/kernels/quantize_and_dequantize_op_test.cc @@ -101,17 +101,51 @@ TEST_F(QuantizeAndDequantizeTest, Convert_1D_tensor_with_int8) { .Attr("range_given", false) .Finalize(node_def())); TF_ASSERT_OK(InitOp()); - AddInputFromArray(TensorShape({6}), {-1, -0.5, 0, 0.3, 0.8, 0.555}); + AddInputFromArray(TensorShape({7}), + {-1, -0.5, 0, 0.3, 0.8, 0.555, 0.50390625}); AddInputFromArray(TensorShape({}), {0.0}); // Min AddInputFromArray(TensorShape({}), {0.0}); // Max - // With int8, the tensor is quantized to {-128, -64, 0, 38, 102, 71}. + // With int8, the tensor is quantized to {-128, -64, 0, 38, 102, 71, 64}. // Scale is: 1/127 - // Then it is dequantized to {-1, -0.5, 0, 38.0/128, 102.0/128, 71.0/128} + // Then it is dequantized to {-1, -0.5, 0, 38.0/128, 102.0/128, 71.0/128, 0.5} TF_ASSERT_OK(RunOpKernel()); - Tensor expected(allocator(), DT_FLOAT, TensorShape({6})); - test::FillValues(&expected, - {-1, -0.5, 0, 38.0 / 128, 102.0 / 128, 71.0 / 128}); + Tensor expected(allocator(), DT_FLOAT, TensorShape({7})); + test::FillValues( + &expected, {-1, -0.5, 0, 38.0 / 128, 102.0 / 128, 71.0 / 128, 0.5}); + test::ExpectTensorNear(expected, *GetOutput(0), 1e-5); + + // Ensure that the inputs haven't been changed. + EXPECT_EQ(inputs_[1]->scalar()(), 0.0); + EXPECT_EQ(inputs_[2]->scalar()(), 0.0); +} + +// Convert a 1D tensor with signed 8 bits and round_mode half_up. +TEST_F(QuantizeAndDequantizeTest, Convert_1D_tensor_with_int8_round_half_up) { + TF_ASSERT_OK( + NodeDefBuilder("quantize_and_dequantize_op", "QuantizeAndDequantizeV2") + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Attr("signed_input", true) + .Attr("num_bits", 8) + .Attr("range_given", false) + .Attr("round_mode", "HALF_UP") + .Finalize(node_def())); + TF_ASSERT_OK(InitOp()); + AddInputFromArray(TensorShape({7}), + {-1, -0.5, 0, 0.3, 0.8, 0.555, 0.50390625}); + AddInputFromArray(TensorShape({}), {0.0}); // Min + AddInputFromArray(TensorShape({}), {0.0}); // Max + + // With int8, the tensor is quantized to {-128, -64, 0, 38, 102, 71, 65}. + // Scale is: 1/127 + // Then it is dequantized to {-1, -0.5, 0, 38.0/128, 102.0/128, 71.0/128, + // 65.0 /128} + TF_ASSERT_OK(RunOpKernel()); + Tensor expected(allocator(), DT_FLOAT, TensorShape({7})); + test::FillValues(&expected, {-1, -0.5, 0, 38.0 / 128, 102.0 / 128, + 71.0 / 128, 65.0 / 128}); test::ExpectTensorNear(expected, *GetOutput(0), 1e-5); // Ensure that the inputs haven't been changed. @@ -162,7 +196,7 @@ TEST_F(QuantizeAndDequantizeTest, Convert_1D_tensor_with_int4) { .Attr("range_given", false) .Finalize(node_def())); TF_ASSERT_OK(InitOp()); - AddInputFromArray(TensorShape({6}), {-1, -0.5, 0, 0.3, 0.8, 0.555}); + AddInputFromArray(TensorShape({6}), {-1, -0.5, 0, 0.3125, 0.8, 0.555}); AddInputFromArray(TensorShape({}), {0.0}); // Min AddInputFromArray(TensorShape({}), {0.0}); // Max @@ -178,6 +212,35 @@ TEST_F(QuantizeAndDequantizeTest, Convert_1D_tensor_with_int4) { EXPECT_EQ(inputs_[2]->scalar()(), 0.0); } +// Convert a 1D tensor with signed 4 bits and round_mode hafl_up. +TEST_F(QuantizeAndDequantizeTest, Convert_1D_tensor_with_int4_round_half_up) { + TF_ASSERT_OK( + NodeDefBuilder("quantize_and_dequantize_op", "QuantizeAndDequantizeV2") + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Attr("signed_input", true) + .Attr("num_bits", 4) + .Attr("range_given", false) + .Attr("round_mode", "HALF_UP") + .Finalize(node_def())); + TF_ASSERT_OK(InitOp()); + AddInputFromArray(TensorShape({6}), {-1, -0.5, 0, 0.3125, 0.8, 0.555}); + AddInputFromArray(TensorShape({}), {0.0}); // Min + AddInputFromArray(TensorShape({}), {0.0}); // Max + + // With int4, the tensor is quantized to {-8, -4, 0, 3, 6, 4}. + // Scale is: 1/8 + TF_ASSERT_OK(RunOpKernel()); + Tensor expected(allocator(), DT_FLOAT, TensorShape({6})); + test::FillValues(&expected, {-1, -0.5, 0, 0.375, 0.75, 0.5}); + test::ExpectTensorNear(expected, *GetOutput(0), 1e-5); + + // Ensure that the inputs haven't been changed. + EXPECT_EQ(inputs_[1]->scalar()(), 0.0); + EXPECT_EQ(inputs_[2]->scalar()(), 0.0); +} + // Convert a 1D tensor with signed 4 bits. TEST_F(QuantizeAndDequantizeTest, Convert_1D_tensor_with_int4_V3) { TF_ASSERT_OK( @@ -237,6 +300,38 @@ TEST_F(QuantizeAndDequantizeTest, Convert_2D_tensor_with_int8_range_given) { test::ExpectTensorNear(expected, *GetOutput(0), 1e-5); } +// Convert a 2D tensor with signed 8 bits, given range and round_mode half_up. +TEST_F(QuantizeAndDequantizeTest, + Convert_2D_tensor_with_int8_range_given_round_half_up) { + TF_ASSERT_OK( + NodeDefBuilder("quantize_and_dequantize_op", "QuantizeAndDequantizeV2") + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Attr("signed_input", true) + .Attr("num_bits", 8) + .Attr("range_given", true) + .Attr("round_mode", "HALF_UP") + .Finalize(node_def())); + TF_ASSERT_OK(InitOp()); + // Note that the last two values are saturated. + AddInputFromArray(TensorShape({2, 4}), + {-0.8, -0.5, 0, 0.3, 0.8, 0.555, -2, 33}); + AddInputFromArray(TensorShape({}), {-1.0}); // Min + AddInputFromArray(TensorShape({}), {1.0}); // Max + + // Note that the range is given as [-1, 1]. + // With int8, the tensor is quantized to {-102, -63, 0, 38, 102, 70, -128, + // 127}. + // Scale is: 1/127 + TF_ASSERT_OK(RunOpKernel()); + Tensor expected(allocator(), DT_FLOAT, TensorShape({2, 4})); + test::FillValues( + &expected, {-102.0 / 127, -63.0 / 127, 0, 38.0 / 127, 102.0 / 127, + 70.0 / 127, -128.0 / 127, 1}); + test::ExpectTensorNear(expected, *GetOutput(0), 1e-5); +} + // Convert a 2D tensor with signed 8 bits with given range. TEST_F(QuantizeAndDequantizeTest, Convert_2D_tensor_with_int8_range_given_V3) { TF_ASSERT_OK( @@ -293,6 +388,33 @@ TEST_F(QuantizeAndDequantizeTest, Convert_4D_tensor_with_uint8_range_given) { test::ExpectTensorNear(expected, *GetOutput(0), 1e-5); } +// Convert a 4D tensor with unsigned 8 bits, given range and round_mode half_up. +TEST_F(QuantizeAndDequantizeTest, + Convert_4D_tensor_with_uint8_range_given_round_half_up) { + TF_ASSERT_OK( + NodeDefBuilder("quantize_and_dequantize_op", "QuantizeAndDequantizeV2") + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Input(FakeInput(DT_FLOAT)) + .Attr("signed_input", false) + .Attr("num_bits", 8) + .Attr("range_given", true) + .Attr("round_mode", "HALF_UP") + .Finalize(node_def())); + TF_ASSERT_OK(InitOp()); + AddInputFromArray(TensorShape({2, 2, 1, 1}), {-0.5, 0, 0.3, 0.8}); + AddInputFromArray(TensorShape({}), {0.0}); // Min + AddInputFromArray(TensorShape({}), {1.0}); // Max + + // Note that the range is given as [0, 1]. + // With int8, the tensor is quantized to {0, 0, 77, 204} + // Scale is: 1/255 + TF_ASSERT_OK(RunOpKernel()); + Tensor expected(allocator(), DT_FLOAT, TensorShape({2, 2, 1, 1})); + test::FillValues(&expected, {0, 0, 77.0 / 255, 204.0 / 255}); + test::ExpectTensorNear(expected, *GetOutput(0), 1e-5); +} + // Convert a 4D tensor with unsigned 8 bits with given range. TEST_F(QuantizeAndDequantizeTest, Convert_4D_tensor_with_uint8_range_given_V3) { TF_ASSERT_OK( diff --git a/tensorflow/core/kernels/quantized_resize_bilinear_op_test.cc b/tensorflow/core/kernels/quantized_resize_bilinear_op_test.cc index e6133415d0..6fc4894592 100644 --- a/tensorflow/core/kernels/quantized_resize_bilinear_op_test.cc +++ b/tensorflow/core/kernels/quantized_resize_bilinear_op_test.cc @@ -273,7 +273,7 @@ void TestResizeBilinearOneDim() { << expected_val << ", " << resized_image_val; } - // Value testing with reference implemenatation + // Value testing with reference implementation CheckTensorValue(image_quantized_tensor.flat().data(), outputs.at(0).flat().data(), /*batch_size=*/1, diff --git a/tensorflow/core/kernels/ragged_gather_op.cc b/tensorflow/core/kernels/ragged_gather_op.cc index b2a342f637..903a97a960 100644 --- a/tensorflow/core/kernels/ragged_gather_op.cc +++ b/tensorflow/core/kernels/ragged_gather_op.cc @@ -236,8 +236,10 @@ class RaggedGatherOpBase : public OpKernel { values_shape.set_dim(0, num_values); TF_RETURN_IF_ERROR( context->allocate_output(values_index, values_shape, &values_out)); - int64 value_size = params_dense_values_in.NumElements() / - params_dense_values_in.dim_size(0); + const int64 num_elements = params_dense_values_in.NumElements(); + const int64 value_size = + num_elements == 0 ? 0 + : (num_elements / params_dense_values_in.dim_size(0)); CallWriteValueSlices(params_dense_values_in, value_slices, value_size, values_out); return ::tensorflow::Status::OK(); diff --git a/tensorflow/core/kernels/scan_ops_gpu.cu.cc b/tensorflow/core/kernels/scan_ops_gpu.cu.cc index ed6c6affce..ed66c02dc5 100644 --- a/tensorflow/core/kernels/scan_ops_gpu.cu.cc +++ b/tensorflow/core/kernels/scan_ops_gpu.cu.cc @@ -1,4 +1,4 @@ -/* Copyright 2016 The TensorFlow Authors. All Rights Reserved. +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,8 +17,20 @@ limitations under the License. #define EIGEN_USE_GPU +#if CUDA_VERSION >= 9000 +#define CUB_USE_COOPERATIVE_GROUPS +#endif // CUDA_VERSION >= 9000 + +#include "third_party/cub/block/block_load.cuh" +#include "third_party/cub/block/block_scan.cuh" +#include "third_party/cub/block/block_store.cuh" +#include "third_party/cub/iterator/counting_input_iterator.cuh" +#include "third_party/cub/iterator/transform_input_iterator.cuh" +#include "cuda/include/cuComplex.h" #include "tensorflow/core/framework/numeric_types.h" #include "tensorflow/core/framework/register_types.h" +#include "tensorflow/core/util/permutation_input_iterator.h" +#include "tensorflow/core/util/permutation_output_iterator.h" #include "tensorflow/core/kernels/scan_ops.h" @@ -27,6 +39,258 @@ namespace tensorflow { typedef Eigen::GpuDevice GPUDevice; typedef Eigen::Index Index; +namespace functor { + +// Map a contiguous range to the actual memory locations depending on which +// axis the scan is taking place over and whether or not reversed. +struct MapIndexToLocation { + __host__ __device__ MapIndexToLocation(int dimx, int dimy, int dimz, + bool reverse = false) + : dimx_(dimx), dimy_(dimy), dimz_(dimz), reverse_(reverse) {} + + __host__ __device__ int operator()(int id) const { + if (dimx_ == 1) { + int row = id % dimy_; + int col = id / dimy_; + + if (reverse_) return (dimy_ - row - 1) * dimz_ + col; + + return row * dimz_ + col; + } else if (dimz_ == 1) { + if (reverse_) { + int row = id / dimy_; + int col = id % dimy_; + return row * dimy_ + (dimy_ - col - 1); + } + return id; + } else { + int col = id % dimy_; + int tmp = id / dimy_; + + int row1 = id / (dimy_ * dimz_); + int col1 = tmp % dimz_; + + if (reverse_) + return row1 * dimy_ * dimz_ + (dimy_ - col - 1) * dimz_ + col1; + + return row1 * dimy_ * dimz_ + col * dimz_ + col1; + } + } + + int dimx_; + int dimy_; + int dimz_; + bool reverse_; +}; + +template +struct BlockPrefixCallbackOp { + // Running prefix + T running_total_; + Op op_; + + __device__ BlockPrefixCallbackOp(T running_total, Op op) + : running_total_(running_total), op_(op) {} + + // Callback operator to be entered by the first warp of threads in the block. + // tid 0 is responsible for returning a value for seeding the block-wide scan. + __device__ T operator()(T block_aggregate) { + T old_prefix = running_total_; + running_total_ = op_(old_prefix, block_aggregate); + return old_prefix; + } +}; + +template +struct Sum { + __host__ __device__ T operator()(const T& a, const T& b) const { + return a + b; + } +}; + +template +struct Prod { + __host__ __device__ T operator()(const T& a, const T& b) const { + return a * b; + } +}; + +template +struct IsSum { + constexpr static bool value = + (std::is_same>::value || + std::is_same>::value); +}; + +template +struct IsProd { + constexpr static bool value = + (std::is_same>::value || + std::is_same>::value); +}; + +template +struct IdentityValue { + static_assert(IsSum::value || IsProd::value, + "IdentityValue not yet defined for this type."); + + template + __host__ __device__ U operator()( + typename std::enable_if::value, U>::type t = U(0)) { + return t; + } + + template + __host__ __device__ U operator()( + typename std::enable_if::value, U>::type t = U(1)) { + return t; + } +}; + +// Each block is mapped to one sequence. A contiguous range is mapped to the +// appropriate locations in memory by the permutation iterators. This is +// ideal for 1-D and row based scans. Column scans would be better if they +// did a block load and then locally transposed. CUB's device wide scan is not +// used in the large 1D case, even though it would be more efficient, because +// it is not deterministic. +template +__global__ void scan_kernel(const T* in, T* out, int dimx, int dimy, int dimz, + bool exclusive, bool reverse, Op op) { + typedef cub::BlockLoad + BlockLoad; + typedef cub::BlockStore + BlockStore; + typedef cub::BlockScan BlockScan; + + // Allocate aliased shared memory for BlockLoad, BlockStore, and BlockScan + __shared__ union { + typename BlockLoad::TempStorage load; + typename BlockScan::TempStorage scan; + typename BlockStore::TempStorage store; + } temp_storage; + + int problem_length = dimy; + + // Initialize running total + BlockPrefixCallbackOp prefix_op(IdentityValue()(), op); + + MapIndexToLocation map_op(dimx, dimy, dimz, reverse); + int block_start = problem_length * blockIdx.x; + // Have the block iterate over segments of items + for (int block_offset = block_start; + block_offset < block_start + problem_length; + block_offset += BlockDim * ItemsPerThread) { + int valid_items = min(BlockDim * ItemsPerThread, + problem_length - (block_offset % problem_length)); + + // first construct a counting iterator that has the desired start point + typedef cub::TransformInputIterator> + MapIterType; + + cub::CountingInputIterator counting_iter(block_offset); + + // Next map the iterator to the actual locations in memory + MapIterType map_iter(counting_iter, map_op); + + PermutationInputIterator permutein_iter(in, + map_iter); + PermutationOutputIterator permuteout_iter(out, + map_iter); + + // Load a segment of consecutive items that are blocked across threads + T thread_data[ItemsPerThread]; + BlockLoad(temp_storage.load).Load(permutein_iter, thread_data, valid_items); + __syncthreads(); + + // Collectively compute the block-wide scan + if (exclusive) { + BlockScan(temp_storage.scan) + .ExclusiveScan(thread_data, thread_data, op, prefix_op); + } else { + BlockScan(temp_storage.scan) + .InclusiveScan(thread_data, thread_data, op, prefix_op); + } + __syncthreads(); + + // Store scanned items to output segment + BlockStore(temp_storage.store) + .Store(permuteout_iter, thread_data, valid_items); + __syncthreads(); + } +} + +template +void LaunchScan(const GPUDevice& d, typename TTypes::ConstTensor in, + typename TTypes::Tensor out, Op op, const bool reverse, + const bool exclusive) { + const int items_per_thread = 4; + + int dimx = in.dimension(0); + int dimy = in.dimension(1); + int dimz = in.dimension(2); + int num_blocks = dimx * dimz; + + int ideal_block_size = dimy / items_per_thread; + + // There seems to be a bug when the type is not float and block_size 1024. + // Launch on the smallest power of 2 block size that we can. + if (ideal_block_size >= 1024 && std::is_same::value) { + const int block_size = 1024; + scan_kernel + <<>>( + in.data(), out.data(), dimx, dimy, dimz, exclusive, reverse, op); + } else if (ideal_block_size >= 512) { + const int block_size = 512; + scan_kernel + <<>>( + in.data(), out.data(), dimx, dimy, dimz, exclusive, reverse, op); + } else if (ideal_block_size >= 256) { + const int block_size = 256; + scan_kernel + <<>>( + in.data(), out.data(), dimx, dimy, dimz, exclusive, reverse, op); + } else if (ideal_block_size >= 128) { + const int block_size = 128; + scan_kernel + <<>>( + in.data(), out.data(), dimx, dimy, dimz, exclusive, reverse, op); + } else if (ideal_block_size >= 64) { + const int block_size = 64; + scan_kernel + <<>>( + in.data(), out.data(), dimx, dimy, dimz, exclusive, reverse, op); + } else { + const int block_size = 32; + scan_kernel + <<>>( + in.data(), out.data(), dimx, dimy, dimz, exclusive, reverse, op); + } +} + +template +struct Scan, T> { + void operator()(const GPUDevice& d, typename TTypes::ConstTensor in, + typename TTypes::Tensor out, + const Eigen::internal::SumReducer& reducer, + const bool reverse, const bool exclusive) { + LaunchScan>(d, in, out, Sum(), reverse, exclusive); + } +}; + +template +struct Scan, T> { + void operator()(const GPUDevice& d, typename TTypes::ConstTensor in, + typename TTypes::Tensor out, + const Eigen::internal::ProdReducer& reducer, + const bool reverse, const bool exclusive) { + LaunchScan>(d, in, out, Prod(), reverse, exclusive); + } +}; + +} // namespace functor + #define DEFINE(REDUCER, T) template struct functor::Scan; #define DEFINE_FOR_ALL_REDUCERS(T) \ diff --git a/tensorflow/core/kernels/scan_ops_test.cc b/tensorflow/core/kernels/scan_ops_test.cc new file mode 100644 index 0000000000..588b606a99 --- /dev/null +++ b/tensorflow/core/kernels/scan_ops_test.cc @@ -0,0 +1,146 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/common_runtime/kernel_benchmark_testlib.h" +#include "tensorflow/core/framework/tensor.h" +#include "tensorflow/core/framework/types.h" +#include "tensorflow/core/platform/test.h" +#include "tensorflow/core/platform/test_benchmark.h" + +namespace tensorflow { + +template +static Graph* LargeOneDCumsum(int num_x, bool reverse = false) { + auto* g = new Graph(OpRegistry::Global()); + Tensor data(DataTypeToEnum::value, TensorShape({num_x})); + data.flat().setRandom(); + Tensor axes(DT_INT32, TensorShape({})); + axes.flat()(0) = 0; + test::graph::Cumsum(g, test::graph::Constant(g, data), + test::graph::Constant(g, axes)); + return g; +} + +static Graph* ColCumsum(int num_x, int num_y, bool reverse = false) { + auto* g = new Graph(OpRegistry::Global()); + Tensor data(DT_FLOAT, TensorShape({num_x, num_y})); + data.flat().setRandom(); + Tensor axes(DT_INT32, TensorShape({})); + axes.flat()(0) = 0; + test::graph::Cumsum(g, test::graph::Constant(g, data), + test::graph::Constant(g, axes)); + return g; +} + +static Graph* RowCumsum(int num_x, int num_y, bool reverse = false) { + auto* g = new Graph(OpRegistry::Global()); + Tensor data(DT_FLOAT, TensorShape({num_x, num_y})); + data.flat().setRandom(); + Tensor axes(DT_INT32, TensorShape({})); + axes.flat()(0) = 1; + test::graph::Cumsum(g, test::graph::Constant(g, data), + test::graph::Constant(g, axes)); + return g; +} + +static Graph* ThreeDYCumsum(int num_y, int num_z, bool reverse = false) { + auto* g = new Graph(OpRegistry::Global()); + Tensor data(DT_FLOAT, TensorShape({32, num_y, num_z})); + data.flat().setRandom(); + Tensor axes(DT_INT32, TensorShape({})); + axes.flat()(0) = 1; + test::graph::Cumsum(g, test::graph::Constant(g, data), + test::graph::Constant(g, axes)); + return g; +} + +template +static void LargeOneDimensional(int iters, const string& device, int num_x, + bool reverse = false) { + testing::ItemsProcessed(static_cast(iters) * num_x); + testing::BytesProcessed(static_cast(iters) * num_x * sizeof(T)); + test::Benchmark(device, LargeOneDCumsum(num_x, reverse)).Run(iters); +} + +static void DoRowCumsum(int iters, const string& device, int num_x, int num_y, + bool reverse = false) { + testing::ItemsProcessed(static_cast(iters) * num_x * num_y); + testing::BytesProcessed(static_cast(iters) * num_x * num_y * + sizeof(float)); + test::Benchmark(device, RowCumsum(num_x, num_y, reverse)).Run(iters); +} + +static void DoColCumsum(int iters, const string& device, int num_x, int num_y, + bool reverse = false) { + testing::ItemsProcessed(static_cast(iters) * num_x * num_y); + testing::BytesProcessed(static_cast(iters) * num_x * num_y * + sizeof(float)); + test::Benchmark(device, ColCumsum(num_x, num_y, reverse)).Run(iters); +} + +static void Do3DYCumsum(int iters, const string& device, int num_x, int num_y, + bool reverse = false) { + testing::ItemsProcessed(static_cast(iters) * num_x * num_y); + testing::BytesProcessed(static_cast(iters) * num_x * num_y * + sizeof(float)); + test::Benchmark(device, ThreeDYCumsum(num_x, num_y, reverse)).Run(iters); +} + +static void BM_OneDCumsumGPU(int iters, int num_x) { + LargeOneDimensional(iters, "gpu", num_x); +} +BENCHMARK(BM_OneDCumsumGPU)->Range(1, 1 << 21); + +static void BM_OneDCumsumGPUHalf(int iters, int num_x) { + LargeOneDimensional(iters, "gpu", num_x); +} +BENCHMARK(BM_OneDCumsumGPUHalf)->Range(1, 1 << 21); + +static void BM_Sum2DRowCumsumGPU(int iters, int num_x, int num_y) { + DoRowCumsum(iters, "gpu", num_x, num_y); +} +BENCHMARK(BM_Sum2DRowCumsumGPU)->RangePair(1, 8192, 1, 8192); + +static void BM_Sum2DColumnCumsumGPU(int iters, int num_x, int num_y) { + DoColCumsum(iters, "gpu", num_x, num_y); +} +BENCHMARK(BM_Sum2DColumnCumsumGPU)->RangePair(1, 8192, 1, 8192); + +static void BM_Sum3DYCumsumGPU(int iters, int num_x, int num_y) { + Do3DYCumsum(iters, "gpu", num_x, num_y); +} +BENCHMARK(BM_Sum3DYCumsumGPU)->RangePair(64, 4096, 64, 4096); + +static void BM_OneDCumsumGPU_reverse(int iters, int num_x) { + LargeOneDimensional(iters, "gpu", num_x, true); +} +BENCHMARK(BM_OneDCumsumGPU_reverse)->Range(1, 1 << 21); + +static void BM_Sum2DRowCumsumGPU_reverse(int iters, int num_x, int num_y) { + DoRowCumsum(iters, "gpu", num_x, num_y, true); +} +BENCHMARK(BM_Sum2DRowCumsumGPU_reverse)->RangePair(1, 8192, 1, 8192); + +static void BM_Sum2DColumnCumsumGPU_reverse(int iters, int num_x, int num_y) { + DoColCumsum(iters, "gpu", num_x, num_y, true); +} +BENCHMARK(BM_Sum2DColumnCumsumGPU_reverse)->RangePair(1, 8192, 1, 8192); + +static void BM_Sum3DYCumsumGPU_reverse(int iters, int num_x, int num_y) { + Do3DYCumsum(iters, "gpu", num_x, num_y, true); +} +BENCHMARK(BM_Sum3DYCumsumGPU_reverse)->RangePair(32, 2048, 32, 2048); + +} // end namespace tensorflow diff --git a/tensorflow/core/kernels/scatter_nd_op.cc b/tensorflow/core/kernels/scatter_nd_op.cc index fd54c6d6d7..63bb793fdc 100644 --- a/tensorflow/core/kernels/scatter_nd_op.cc +++ b/tensorflow/core/kernels/scatter_nd_op.cc @@ -29,6 +29,7 @@ limitations under the License. #include "tensorflow/core/kernels/bounds_check.h" #include "tensorflow/core/kernels/dense_update_functor.h" #include "tensorflow/core/kernels/fill_functor.h" +#include "tensorflow/core/kernels/inplace_ops_functor.h" #include "tensorflow/core/kernels/training_op_helpers.h" #include "tensorflow/core/kernels/variable_ops.h" #include "tensorflow/core/lib/strings/str_util.h" @@ -121,6 +122,90 @@ class ScatterNdOp : public OpKernel { } }; +template +class TensorScatterOp : public OpKernel { + public: + explicit TensorScatterOp(OpKernelConstruction* c) : OpKernel(c) { + const DataType dt = DataTypeToEnum::v(); + const DataType index_t = DataTypeToEnum::v(); + OP_REQUIRES_OK(c, c->MatchSignature({dt, index_t, dt}, {dt})); + } + + void Compute(OpKernelContext* c) override { + const Tensor& input = c->input(0); + const Tensor& indices = c->input(1); + const Tensor& updates = c->input(2); + + OP_REQUIRES(c, indices.shape().dims() >= 1, + errors::InvalidArgument( + "Indices shape must have rank at least one. Found:", + indices.shape().DebugString())); + OP_REQUIRES(c, updates.shape().dims() >= 1, + errors::InvalidArgument( + "Updates shape must have rank at least one. Found:", + updates.shape().DebugString())); + + TensorShape shape = input.shape(); + + OP_REQUIRES( + c, + (shape.num_elements() > 0 || (indices.shape().num_elements() == 0 && + updates.shape().num_elements() == 0)), + errors::InvalidArgument( + "Indices and updates specified for empty output shape")); + + const int64 outer_dims = indices.shape().dims() - 1; + + for (int i = 0; i < outer_dims; ++i) { + OP_REQUIRES(c, indices.shape().dim_size(i) == updates.shape().dim_size(i), + errors::InvalidArgument( + "Outer dimensions of indices and update must match. " + "Indices shape: ", + indices.shape().DebugString(), + ", updates shape:", updates.shape().DebugString())); + } + + const int64 ix = indices.shape().dim_size(outer_dims); + OP_REQUIRES( + c, updates.shape().dims() - outer_dims == shape.dims() - ix, + errors::InvalidArgument("Inner dimensions of output shape must match " + "inner dimensions of updates shape. Output: ", + shape.DebugString(), + " updates: ", updates.shape().DebugString())); + for (int i = 0; i + outer_dims < updates.shape().dims(); ++i) { + OP_REQUIRES( + c, updates.shape().dim_size(i + outer_dims) == shape.dim_size(ix + i), + errors::InvalidArgument( + "The inner ", shape.dims() - ix, + " dimensions of output.shape=", shape.DebugString(), + " must match the inner ", updates.shape().dims() - outer_dims, + " dimensions of updates.shape=", updates.shape().DebugString())); + } + + std::unique_ptr forwarded_input = c->forward_input( + 2, 0, input.dtype(), shape, DEVICE_MEMORY, AllocatorAttributes()); + + if (forwarded_input == nullptr) { + // We were not able to forward the input, so we deep copy the tensor and + // set the output. + Tensor* out; + OP_REQUIRES_OK(c, c->allocate_output(0, input.shape(), &out)); + + OP_REQUIRES_OK(c, tensorflow::functor::DoCopy(c->eigen_device(), + input, out)); + OP_REQUIRES_OK(c, + functor::DoScatterNd( + c, indices, updates, shape, out, false /*allocate*/)); + } else { + // Output forwarded, so simply perform the scatter. + OP_REQUIRES_OK(c, functor::DoScatterNd( + c, indices, updates, shape, forwarded_input.get(), + false /*allocate*/)); + } + } +}; + template class ScatterNdUpdateOp : public OpKernel { @@ -282,6 +367,56 @@ TF_CALL_bool(REGISTER_SCATTER_ND_ADD_SUB_CPU); TF_CALL_bool(REGISTER_SCATTER_ND_UPDATE_CPU); TF_CALL_bool(REGISTER_SCATTER_ND_CPU); +#define REGISTER_SCATTER_ND_TENSOR_UPDATE_TYPE_INDEX_TYPE(type, index_type, \ + dev) \ + REGISTER_KERNEL_BUILDER(Name("TensorScatterUpdate") \ + .Device(DEVICE_##dev) \ + .TypeConstraint("T") \ + .TypeConstraint("Tindices"), \ + TensorScatterOp) + +#define REGISTER_SCATTER_ND_TENSOR_ADD_TYPE_INDEX_TYPE(type, index_type, dev) \ + REGISTER_KERNEL_BUILDER(Name("TensorScatterAdd") \ + .Device(DEVICE_##dev) \ + .TypeConstraint("T") \ + .TypeConstraint("Tindices"), \ + TensorScatterOp) + +#define REGISTER_SCATTER_ND_TENSOR_SUB_TYPE_INDEX_TYPE(type, index_type, dev) \ + REGISTER_KERNEL_BUILDER(Name("TensorScatterSub") \ + .Device(DEVICE_##dev) \ + .TypeConstraint("T") \ + .TypeConstraint("Tindices"), \ + TensorScatterOp) + +#define REGISTER_SCATTER_ND_TENSOR_UPDATE_CPU(type) \ + REGISTER_SCATTER_ND_TENSOR_UPDATE_TYPE_INDEX_TYPE(type, int32, CPU); \ + REGISTER_SCATTER_ND_TENSOR_UPDATE_TYPE_INDEX_TYPE(type, int64, CPU); + +#define REGISTER_SCATTER_ND_TENSOR_ADD_CPU(type) \ + REGISTER_SCATTER_ND_TENSOR_ADD_TYPE_INDEX_TYPE(type, int32, CPU); \ + REGISTER_SCATTER_ND_TENSOR_ADD_TYPE_INDEX_TYPE(type, int64, CPU); + +#define REGISTER_SCATTER_ND_TENSOR_SUB_CPU(type) \ + REGISTER_SCATTER_ND_TENSOR_SUB_TYPE_INDEX_TYPE(type, int32, CPU); \ + REGISTER_SCATTER_ND_TENSOR_SUB_TYPE_INDEX_TYPE(type, int64, CPU); + +#define REGISTER_SCATTER_ND_TENSOR_CPU(type) \ + REGISTER_SCATTER_ND_TENSOR_UPDATE_CPU(type); \ + REGISTER_SCATTER_ND_TENSOR_ADD_CPU(type); \ + REGISTER_SCATTER_ND_TENSOR_SUB_CPU(type); + +// Register TensorScatterUpdate/Add/Sub for all number types. +TF_CALL_NUMBER_TYPES(REGISTER_SCATTER_ND_TENSOR_CPU); +// Register only TensorScatterUpdate for string/bool types as well. +TF_CALL_string(REGISTER_SCATTER_ND_TENSOR_UPDATE_CPU); +TF_CALL_bool(REGISTER_SCATTER_ND_TENSOR_UPDATE_CPU); + +#undef REGISTER_SCATTER_ND_TENSOR_CPU + // Registers GPU kernels. #if GOOGLE_CUDA @@ -319,6 +454,25 @@ TF_CALL_GPU_NUMBER_TYPES_NO_HALF(REGISTER_SCATTER_ND_UPDATE_SYCL); #undef REGISTER_SCATTER_ND_UPDATE_SYCL #endif // TENSORFLOW_USE_SYCL +#define REGISTER_SCATTER_ND_TENSOR_UPDATE_GPU(type) \ + REGISTER_SCATTER_ND_TENSOR_UPDATE_TYPE_INDEX_TYPE(type, int32, GPU); \ + REGISTER_SCATTER_ND_TENSOR_UPDATE_TYPE_INDEX_TYPE(type, int64, GPU); + +#define REGISTER_SCATTER_ND_TENSOR_ADD_GPU(type) \ + REGISTER_SCATTER_ND_TENSOR_ADD_TYPE_INDEX_TYPE(type, int32, GPU); \ + REGISTER_SCATTER_ND_TENSOR_ADD_TYPE_INDEX_TYPE(type, int64, GPU); + +#define REGISTER_SCATTER_ND_TENSOR_SUB_GPU(type) \ + REGISTER_SCATTER_ND_TENSOR_SUB_TYPE_INDEX_TYPE(type, int32, GPU); \ + REGISTER_SCATTER_ND_TENSOR_SUB_TYPE_INDEX_TYPE(type, int64, GPU); + +#define REGISTER_SCATTER_ND_TENSOR_GPU(type) \ + REGISTER_SCATTER_ND_TENSOR_ADD_GPU(type); \ + REGISTER_SCATTER_ND_TENSOR_UPDATE_GPU(type); \ + REGISTER_SCATTER_ND_TENSOR_SUB_GPU(type); + +TF_CALL_GPU_NUMBER_TYPES_NO_HALF(REGISTER_SCATTER_ND_TENSOR_GPU); + #undef REGISTER_SCATTER_ND_ADD #undef REGISTER_SCATTER_ND_ADD_SUB #undef REGISTER_SCATTER_ND_ADD_SUB_CPU @@ -328,6 +482,16 @@ TF_CALL_GPU_NUMBER_TYPES_NO_HALF(REGISTER_SCATTER_ND_UPDATE_SYCL); #undef REGISTER_SCATTER_ND_UPDATE_GPU #undef REGISTER_SCATTER_ND_KERNEL #undef REGISTER_SCATTER_ND_KERNEL_INDEX +#undef REGISTER_SCATTER_ND_TENSOR_TYPE_INDEX_TYPE +#undef REGISTER_SCATTER_ND_TENSOR_CPU +#undef REGISTER_SCATTER_ND_TENSOR_GPU +#undef REGISTER_SCATTER_ND_TENSOR_UPDATE_TYPE_INDEX_TYPE +#undef REGISTER_SCATTER_ND_TENSOR_ADD_TYPE_INDEX_TYPE +#undef REGISTER_SCATTER_ND_TENSOR_SUB_TYPE_INDEX_TYPE +#undef REGISTER_SCATTER_ND_TENSOR_UPDATE_GPU +#undef REGISTER_SCATTER_ND_TENSOR_ADD_GPU +#undef REGISTER_SCATTER_ND_TENSOR_SUB_GPU +#undef REGISTER_SCATTER_ND_TENSOR_GPU #endif // GOOGLE_CUDA diff --git a/tensorflow/core/kernels/stage_op.cc b/tensorflow/core/kernels/stage_op.cc index 73a02a34cf..c91bdc43cf 100644 --- a/tensorflow/core/kernels/stage_op.cc +++ b/tensorflow/core/kernels/stage_op.cc @@ -151,7 +151,7 @@ class Buffer : public ResourceBase { } // Are there a limit number of elements or a memory limit - // configued on this buffer? + // configured on this buffer? bool IsBounded() const { return capacity_ > 0 || memory_limit_ > 0; } bool IsCapacityFull() const { return buf_.size() >= capacity_; } diff --git a/tensorflow/core/kernels/tensor_array_ops.cc b/tensorflow/core/kernels/tensor_array_ops.cc index a97a71b344..aa85f546a8 100644 --- a/tensorflow/core/kernels/tensor_array_ops.cc +++ b/tensorflow/core/kernels/tensor_array_ops.cc @@ -352,9 +352,9 @@ class TensorArrayGradOp : public TensorArrayCreationOp { } const auto key = strings::StrCat(output_handle(0), output_handle(1)); - auto creator = [this, key, tensor_array, array_size, marked_size, - element_shape, shape_to_prepend, tensor_array_output_handle, - output_handle](TensorArray** ret) -> Status { + auto creator = [key, tensor_array, array_size, marked_size, element_shape, + shape_to_prepend, + tensor_array_output_handle](TensorArray** ret) -> Status { *ret = new TensorArray( key, tensor_array->ElemType(), *tensor_array_output_handle, array_size, element_shape, tensor_array->HasIdenticalElementShapes(), diff --git a/tensorflow/core/kernels/tensor_forest/BUILD b/tensorflow/core/kernels/tensor_forest/BUILD new file mode 100644 index 0000000000..df035506f7 --- /dev/null +++ b/tensorflow/core/kernels/tensor_forest/BUILD @@ -0,0 +1,53 @@ +# Description: +# OpKernels for tensor forest ops. + +package( + default_visibility = ["//tensorflow:internal"], +) + +licenses(["notice"]) # Apache 2.0 + +load("//tensorflow:tensorflow.bzl", "tf_kernel_library") + +cc_library( + name = "resources", + srcs = ["resources.cc"], + hdrs = ["resources.h"], + deps = [ + "//tensorflow/core:framework", + "//tensorflow/core:lib", + "//tensorflow/core/kernels/boosted_trees:boosted_trees_proto_cc", + ], +) + +tf_kernel_library( + name = "resource_ops", + srcs = ["resource_ops.cc"], + deps = [ + ":resources", + "//tensorflow/core:framework", + "//tensorflow/core:lib", + "//tensorflow/core:tensor_forest_ops_op_lib", + "//tensorflow/core/kernels/boosted_trees:boosted_trees_proto_cc", + ], +) + +tf_kernel_library( + name = "prediction_ops", + srcs = ["prediction_ops.cc"], + deps = [ + ":resources", + "//tensorflow/core:framework", + "//tensorflow/core:lib", + "//tensorflow/core:tensor_forest_ops_op_lib", + "//tensorflow/core/kernels/boosted_trees:boosted_trees_proto_cc", + ], +) + +tf_kernel_library( + name = "tensor_forest_ops", + deps = [ + ":prediction_ops", + ":resource_ops", + ], +) diff --git a/tensorflow/core/kernels/tensor_forest/prediction_ops.cc b/tensorflow/core/kernels/tensor_forest/prediction_ops.cc new file mode 100644 index 0000000000..877dfbc020 --- /dev/null +++ b/tensorflow/core/kernels/tensor_forest/prediction_ops.cc @@ -0,0 +1,93 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/resource_mgr.h" +#include "tensorflow/core/framework/tensor.h" +#include "tensorflow/core/framework/tensor_shape.h" +#include "tensorflow/core/framework/tensor_types.h" +#include "tensorflow/core/kernels/tensor_forest/resources.h" +#include "tensorflow/core/platform/thread_annotations.h" +#include "tensorflow/core/util/work_sharder.h" + +namespace tensorflow { + +class TensorForestTreePredictOp : public OpKernel { + public: + explicit TensorForestTreePredictOp(OpKernelConstruction* context) + : OpKernel(context) { + OP_REQUIRES_OK(context, + context->GetAttr("logits_dimension", &logits_dimension_)); + } + + void Compute(OpKernelContext* context) override { + TensorForestTreeResource* decision_tree_resource; + OP_REQUIRES_OK(context, LookupResource(context, HandleFromInput(context, 0), + &decision_tree_resource)); + mutex_lock l(*decision_tree_resource->get_mutex()); + core::ScopedUnref unref_me(decision_tree_resource); + + const Tensor* dense_features_t = nullptr; + OP_REQUIRES_OK(context, + context->input("dense_features", &dense_features_t)); + + auto dense_features = dense_features_t->matrix(); + const int32 batch_size = dense_features_t->dim_size(0); + + Tensor* output_predictions = nullptr; + OP_REQUIRES_OK(context, + context->allocate_output(0, {batch_size, logits_dimension_}, + &output_predictions)); + auto out = output_predictions->matrix(); + + if (decision_tree_resource->get_size() <= 0) { + out.setZero(); + return; + } + auto* worker_threads = context->device()->tensorflow_cpu_worker_threads(); + const int32 num_threads = worker_threads->num_threads; + + // TODO(yupbank): This was from contrib version. + // This cost would probably depend on the depth of the tree we have. + // We will need to run it on a number of trees of diff depth + // and see the num of cpu cycles + const int64 cost_per_traverse = 500; + auto traverse = [this, &out, &dense_features, decision_tree_resource, + batch_size](int64 start, int64 end) { + CHECK_LE(start, end) << "Start exceeding End"; + CHECK_LE(end, batch_size) << "End exceeding batch size"; + for (int example_id = start; example_id < end; ++example_id) { + const int32 leaf_id = + decision_tree_resource->TraverseTree(example_id, &dense_features); + set_output_value(example_id, leaf_id, decision_tree_resource, &out); + }; + }; + Shard(num_threads, worker_threads->workers, batch_size, cost_per_traverse, + traverse); + }; + + void set_output_value(const int32 example_id, const int32 leaf_id, + const TensorForestTreeResource* decision_tree_resource, + TTypes::Matrix* out) const { + for (int j = 0; j < logits_dimension_; ++j) { + const float logit = decision_tree_resource->get_prediction(leaf_id, j); + (*out)(example_id, j) = logit; + } + }; + + private: + int32 logits_dimension_; +}; + +REGISTER_KERNEL_BUILDER(Name("TensorForestTreePredict").Device(DEVICE_CPU), + TensorForestTreePredictOp); + +} // namespace tensorflow diff --git a/tensorflow/core/kernels/tensor_forest/resource_ops.cc b/tensorflow/core/kernels/tensor_forest/resource_ops.cc new file mode 100644 index 0000000000..aba97ea990 --- /dev/null +++ b/tensorflow/core/kernels/tensor_forest/resource_ops.cc @@ -0,0 +1,135 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/resource_mgr.h" +#include "tensorflow/core/framework/tensor.h" +#include "tensorflow/core/framework/tensor_shape.h" +#include "tensorflow/core/framework/tensor_types.h" +#include "tensorflow/core/kernels/tensor_forest/resources.h" + +namespace tensorflow { + +class TensorForestCreateTreeVariableOp : public OpKernel { + public: + explicit TensorForestCreateTreeVariableOp(OpKernelConstruction* context) + : OpKernel(context){}; + + void Compute(OpKernelContext* context) override { + const Tensor* tree_config_t; + OP_REQUIRES_OK(context, context->input("tree_config", &tree_config_t)); + + auto* const result = new TensorForestTreeResource(); + + if (!result->InitFromSerialized(tree_config_t->scalar()())) { + result->Unref(); + OP_REQUIRES(context, false, + errors::InvalidArgument("Unable to parse tree config.")); + } + + // Only create one, if one does not exist already. Report status for all + // other exceptions. + auto status = CreateResource(context, HandleFromInput(context, 0), result); + if (!status.ok() && status.code() != tensorflow::error::ALREADY_EXISTS) { + OP_REQUIRES(context, false, status); + } + } +}; + +// Op for serializing a model. +class TensorForestTreeSerializeOp : public OpKernel { + public: + explicit TensorForestTreeSerializeOp(OpKernelConstruction* context) + : OpKernel(context) {} + + void Compute(OpKernelContext* context) override { + TensorForestTreeResource* decision_tree_resource; + OP_REQUIRES_OK(context, LookupResource(context, HandleFromInput(context, 0), + &decision_tree_resource)); + mutex_lock l(*decision_tree_resource->get_mutex()); + core::ScopedUnref unref_me(decision_tree_resource); + Tensor* output_config_t = nullptr; + OP_REQUIRES_OK( + context, context->allocate_output(0, TensorShape(), &output_config_t)); + output_config_t->scalar()() = + decision_tree_resource->decision_tree().SerializeAsString(); + } +}; + +// Op for deserializing a tree variable from a checkpoint. +class TensorForestTreeDeserializeOp : public OpKernel { + public: + explicit TensorForestTreeDeserializeOp(OpKernelConstruction* context) + : OpKernel(context) {} + void Compute(OpKernelContext* context) override { + TensorForestTreeResource* decision_tree_resource; + OP_REQUIRES_OK(context, LookupResource(context, HandleFromInput(context, 0), + &decision_tree_resource)); + + mutex_lock l(*decision_tree_resource->get_mutex()); + core::ScopedUnref unref_me(decision_tree_resource); + + const Tensor* tree_config_t; + OP_REQUIRES_OK(context, context->input("tree_config", &tree_config_t)); + + // Deallocate all the previous objects on the resource. + decision_tree_resource->Reset(); + + if (!decision_tree_resource->InitFromSerialized( + tree_config_t->scalar()())) { + OP_REQUIRES(context, false, + errors::InvalidArgument("Unable to parse tree config.")); + } + } +}; + +// Op for getting tree size. +class TensorForestTreeSizeOp : public OpKernel { + public: + explicit TensorForestTreeSizeOp(OpKernelConstruction* context) + : OpKernel(context) {} + + void Compute(OpKernelContext* context) override { + TensorForestTreeResource* decision_tree_resource; + OP_REQUIRES_OK(context, LookupResource(context, HandleFromInput(context, 0), + &decision_tree_resource)); + mutex_lock l(*decision_tree_resource->get_mutex()); + core::ScopedUnref unref_me(decision_tree_resource); + Tensor* output_t = nullptr; + OP_REQUIRES_OK(context, + context->allocate_output(0, TensorShape(), &output_t)); + output_t->scalar()() = decision_tree_resource->get_size(); + } +}; + +REGISTER_RESOURCE_HANDLE_KERNEL(TensorForestTreeResource); + +REGISTER_KERNEL_BUILDER( + Name("TensorForestTreeIsInitializedOp").Device(DEVICE_CPU), + IsResourceInitialized); + +REGISTER_KERNEL_BUILDER( + Name("TensorForestCreateTreeVariable").Device(DEVICE_CPU), + TensorForestCreateTreeVariableOp); + +REGISTER_KERNEL_BUILDER(Name("TensorForestTreeSerialize").Device(DEVICE_CPU), + TensorForestTreeSerializeOp); + +REGISTER_KERNEL_BUILDER(Name("TensorForestTreeDeserialize").Device(DEVICE_CPU), + TensorForestTreeDeserializeOp); + +REGISTER_KERNEL_BUILDER(Name("TensorForestTreeSize").Device(DEVICE_CPU), + TensorForestTreeSizeOp); + +} // namespace tensorflow diff --git a/tensorflow/core/kernels/tensor_forest/resources.cc b/tensorflow/core/kernels/tensor_forest/resources.cc new file mode 100644 index 0000000000..9f8ceb9620 --- /dev/null +++ b/tensorflow/core/kernels/tensor_forest/resources.cc @@ -0,0 +1,59 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/kernels/tensor_forest/resources.h" +#include "tensorflow/core/kernels/boosted_trees/boosted_trees.pb.h" +#include "tensorflow/core/platform/protobuf.h" + +namespace tensorflow { + +const float TensorForestTreeResource::get_prediction( + const int32 id, const int32 dimension_id) const { + return decision_tree_->nodes(id).leaf().vector().value(dimension_id); +}; + +const int32 TensorForestTreeResource::TraverseTree( + const int32 example_id, + const TTypes::ConstMatrix* dense_data) const { + using boosted_trees::Node; + using boosted_trees::Tree; + int32 current_id = 0; + while (true) { + const Node& current = decision_tree_->nodes(current_id); + if (current.has_leaf()) { + return current_id; + }; + DCHECK_EQ(current.node_case(), Node::kDenseSplit); + const auto& split = current.dense_split(); + + if ((*dense_data)(example_id, split.feature_id()) <= split.threshold()) { + current_id = split.left_id(); + } else { + current_id = split.right_id(); + } + } +}; + +bool TensorForestTreeResource::InitFromSerialized(const string& serialized) { + return ParseProtoUnlimited(decision_tree_, serialized); +} + +void TensorForestTreeResource::Reset() { + arena_.Reset(); + CHECK_EQ(0, arena_.SpaceAllocated()); + decision_tree_ = protobuf::Arena::CreateMessage(&arena_); +} + +} // namespace tensorflow diff --git a/tensorflow/core/kernels/tensor_forest/resources.h b/tensorflow/core/kernels/tensor_forest/resources.h new file mode 100644 index 0000000000..34f61b2c0c --- /dev/null +++ b/tensorflow/core/kernels/tensor_forest/resources.h @@ -0,0 +1,63 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_CORE_KERNELS_TENSOR_FOREST_RESOURCES_H_ +#define TENSORFLOW_CORE_KERNELS_TENSOR_FOREST_RESOURCES_H_ + +#include "tensorflow/core/framework/resource_mgr.h" +#include "tensorflow/core/framework/tensor.h" +#include "tensorflow/core/kernels/boosted_trees/boosted_trees.pb.h" +#include "tensorflow/core/lib/strings/strcat.h" +#include "tensorflow/core/platform/mutex.h" +#include "tensorflow/core/platform/protobuf.h" + +namespace tensorflow { + +// Keep a tree ensemble in memory for efficient evaluation and mutation. +class TensorForestTreeResource : public ResourceBase { + public: + TensorForestTreeResource() + : decision_tree_( + protobuf::Arena::CreateMessage(&arena_)){}; + + string DebugString() override { + return strings::StrCat("TensorForestTree[size=", get_size(), "]"); + } + + mutex* get_mutex() { return &mu_; } + + bool InitFromSerialized(const string& serialized); + + // Resets the resource and frees the proto. + // Caller needs to hold the mutex lock while calling this. + void Reset(); + + const int32 get_size() const { return decision_tree_->nodes_size(); } + + const boosted_trees::Tree& decision_tree() const { return *decision_tree_; } + + const float get_prediction(const int32 id, const int32 dimension_id) const; + + const int32 TraverseTree(const int32 example_id, + const TTypes::ConstMatrix* dense_data) const; + + protected: + mutex mu_; + protobuf::Arena arena_; + boosted_trees::Tree* decision_tree_; +}; + +} // namespace tensorflow +#endif // TENSORFLOW_CORE_KERNELS_TENSOR_FOREST_RESOURCES_H_ diff --git a/tensorflow/core/kernels/training_ops.cc b/tensorflow/core/kernels/training_ops.cc index acf162deec..6504ad1b09 100644 --- a/tensorflow/core/kernels/training_ops.cc +++ b/tensorflow/core/kernels/training_ops.cc @@ -283,6 +283,22 @@ struct ApplyMomentum { } }; +template +struct ApplyKerasMomentum { + void operator()(const CPUDevice& d, typename TTypes::Flat var, + typename TTypes::Flat accum, + typename TTypes::ConstScalar lr, + typename TTypes::ConstFlat grad, + typename TTypes::ConstScalar momentum, bool use_nesterov) { + accum.device(d) = accum * momentum() - grad * lr(); + if (use_nesterov) { + var.device(d) += (accum * momentum() - grad * lr()); + } else { + var.device(d) += accum; + } + } +}; + template struct ApplyAdamNonCuda { void operator()(const Device& d, typename TTypes::Flat var, @@ -331,6 +347,28 @@ struct ApplyAdamSYCL { template struct ApplyAdam : ApplyAdamNonCuda {}; +template +struct ApplyAdamWithAmsgrad { + void operator()(const CPUDevice& d, typename TTypes::Flat var, + typename TTypes::Flat m, typename TTypes::Flat v, + typename TTypes::Flat vhat, + typename TTypes::ConstScalar beta1_power, + typename TTypes::ConstScalar beta2_power, + typename TTypes::ConstScalar lr, + typename TTypes::ConstScalar beta1, + typename TTypes::ConstScalar beta2, + typename TTypes::ConstScalar epsilon, + typename TTypes::ConstFlat grad) { + const T alpha = lr() * Eigen::numext::sqrt(T(1) - beta2_power()) / + (T(1) - beta1_power()); + + m.device(d) += (grad - m) * (T(1) - beta1()); + v.device(d) += (grad.square() - v) * (T(1) - beta2()); + vhat.device(d) = vhat.cwiseMax(v); + var.device(d) -= (m * alpha) / (vhat.sqrt() + epsilon()); + } +}; + template struct ApplyAdaMaxNonCuda { void operator()(const Device& d, typename TTypes::Flat var, @@ -2525,6 +2563,217 @@ TF_CALL_double(REGISTER_CPU_KERNELS); #undef REGISTER_CPU_KERNELS #undef REGISTER_KERNELS +template +class ApplyKerasMomentumOp : public OpKernel { + public: + explicit ApplyKerasMomentumOp(OpKernelConstruction* ctx) : OpKernel(ctx) { + OP_REQUIRES_OK(ctx, ctx->GetAttr("use_locking", &use_exclusive_lock_)); + OP_REQUIRES_OK(ctx, ctx->GetAttr("use_nesterov", &use_nesterov_)); + } + + void Compute(OpKernelContext* ctx) override { + auto locks = + MaybeLockVariableInputMutexesInOrder(ctx, use_exclusive_lock_, {0, 1}); + + Tensor var; + OP_REQUIRES_OK(ctx, GetInputTensorFromVariable( + ctx, 0, use_exclusive_lock_, false, &var)); + Tensor accum; + OP_REQUIRES_OK(ctx, GetInputTensorFromVariable( + ctx, 1, use_exclusive_lock_, false, &accum)); + OP_REQUIRES( + ctx, var.IsInitialized(), + errors::FailedPrecondition( + "Attempting to use uninitialized variables: ", requested_input(0))); + OP_REQUIRES( + ctx, accum.IsInitialized(), + errors::FailedPrecondition( + "Attempting to use uninitialized variables: ", requested_input(1))); + const Tensor& lr = ctx->input(2); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(lr.shape()), + errors::InvalidArgument("lr is not a scalar: ", + lr.shape().DebugString())); + const Tensor& grad = ctx->input(3); + OP_REQUIRES( + ctx, var.shape().IsSameSize(accum.shape()), + errors::InvalidArgument("var and accum do not have the same shape", + var.shape().DebugString(), " ", + accum.shape().DebugString())); + OP_REQUIRES( + ctx, var.shape().IsSameSize(grad.shape()), + errors::InvalidArgument("var and grad do not have the same shape", + var.shape().DebugString(), " ", + grad.shape().DebugString())); + + const Tensor& momentum = ctx->input(4); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(momentum.shape()), + errors::InvalidArgument("momentum is not a scalar: ", + momentum.shape().DebugString())); + + const Device& device = ctx->template eigen_device(); + functor::ApplyKerasMomentum()( + device, var.flat(), accum.flat(), lr.scalar(), grad.flat(), + momentum.scalar(), use_nesterov_); + MaybeForwardRefInputToRefOutput(ctx, 0, 0); + } + + private: + bool use_exclusive_lock_; + bool use_nesterov_; +}; + +#define REGISTER_KERNELS(D, T) \ + REGISTER_KERNEL_BUILDER(Name("ResourceApplyKerasMomentum") \ + .Device(DEVICE_##D) \ + .HostMemory("var") \ + .HostMemory("accum") \ + .TypeConstraint("T"), \ + ApplyKerasMomentumOp); +#define REGISTER_CPU_KERNELS(T) REGISTER_KERNELS(CPU, T); + +TF_CALL_half(REGISTER_CPU_KERNELS); +TF_CALL_bfloat16(REGISTER_CPU_KERNELS); +TF_CALL_float(REGISTER_CPU_KERNELS); +TF_CALL_double(REGISTER_CPU_KERNELS); + +#if GOOGLE_CUDA +// Forward declarations of the functor specializations for GPU. +namespace functor { +#define DECLARE_GPU_SPEC(T) \ + template <> \ + void ApplyKerasMomentum::operator()( \ + const GPUDevice& d, typename TTypes::Flat var, \ + typename TTypes::Flat accum, typename TTypes::ConstScalar lr, \ + typename TTypes::ConstFlat grad, \ + typename TTypes::ConstScalar momentum, bool use_nesterov); \ + extern template struct ApplyKerasMomentum; +DECLARE_GPU_SPEC(Eigen::half); +DECLARE_GPU_SPEC(float); +DECLARE_GPU_SPEC(double); +#undef DECLARE_GPU_SPEC +} // namespace functor + +REGISTER_KERNELS(GPU, Eigen::half); +REGISTER_KERNELS(GPU, float); +REGISTER_KERNELS(GPU, double); +#endif +#undef REGISTER_CPU_KERNELS +#undef REGISTER_KERNELS + +// Note, this op works on cpu only. +template +class SparseApplyKerasMomentumOp : public OpKernel { + public: + explicit SparseApplyKerasMomentumOp(OpKernelConstruction* ctx) + : OpKernel(ctx) { + OP_REQUIRES_OK(ctx, ctx->GetAttr("use_locking", &use_exclusive_lock_)); + OP_REQUIRES_OK(ctx, ctx->GetAttr("use_nesterov", &use_nesterov_)); + } + + void Compute(OpKernelContext* ctx) override NO_THREAD_SAFETY_ANALYSIS { + auto locks = + MaybeLockVariableInputMutexesInOrder(ctx, use_exclusive_lock_, {0, 1}); + + Tensor var; + OP_REQUIRES_OK(ctx, GetInputTensorFromVariable( + ctx, 0, use_exclusive_lock_, true, &var)); + Tensor accum; + OP_REQUIRES_OK(ctx, GetInputTensorFromVariable( + ctx, 1, use_exclusive_lock_, true, &accum)); + OP_REQUIRES( + ctx, var.IsInitialized(), + errors::FailedPrecondition( + "Attempting to use uninitialized variables: ", requested_input(0))); + OP_REQUIRES( + ctx, accum.IsInitialized(), + errors::FailedPrecondition( + "Attempting to use uninitialized variables: ", requested_input(1))); + OP_REQUIRES( + ctx, var.shape().IsSameSize(accum.shape()), + errors::InvalidArgument("var and accum do not have the same shape", + var.shape().DebugString(), " ", + accum.shape().DebugString())); + OP_REQUIRES(ctx, TensorShapeUtils::IsVectorOrHigher(var.shape()), + errors::InvalidArgument("var must be at least 1 dimensional")); + + const Tensor& lr = ctx->input(2); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(lr.shape()), + errors::InvalidArgument("lr is not a scalar : ", + lr.shape().DebugString())); + const Tensor& grad = ctx->input(3); + const Tensor& indices = ctx->input(4); + OP_REQUIRES(ctx, TensorShapeUtils::IsVector(indices.shape()), + errors::InvalidArgument("indices must be one-dimensional")); + + for (int d = 1; d < var.dims(); d++) { + OP_REQUIRES(ctx, var.dim_size(d) == grad.dim_size(d), + errors::InvalidArgument(strings::StrCat( + "var and grad must match in dimension ", d))); + } + const Tindex N = indices.dim_size(0); + OP_REQUIRES( + ctx, grad.dim_size(0) == N, + errors::InvalidArgument( + "grad must be the same size as indices in the first dimension.")); + + const Tensor& momentum = ctx->input(5); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(momentum.shape()), + errors::InvalidArgument("momentum is not a scalar: ", + momentum.shape().DebugString())); + + if (N > 0) { + const Tindex first_dim_size = var.dim_size(0); + auto indices_vec = indices.vec(); + auto var_flat = var.flat_outer_dims(); + auto accum_flat = accum.flat_outer_dims(); + auto grad_flat = grad.flat_outer_dims(); + T lr_scalar = lr.scalar()(); + T momentum_scalar = momentum.scalar()(); + + for (Tindex i = 0; i < N; i++) { + const Tindex index = internal::SubtleMustCopy(indices_vec(i)); + OP_REQUIRES(ctx, FastBoundsCheck(index, first_dim_size), + errors::InvalidArgument( + strings::StrCat("Index ", index, " at offset ", i, + " in indices is out of range"))); + auto a = accum_flat.template chip<0>(index); + auto g = grad_flat.template chip<0>(i); + auto v = var_flat.template chip<0>(index); + a = a * a.constant(momentum_scalar) - g * g.constant(lr_scalar); + if (use_nesterov_) { + v += a * a.constant(momentum_scalar) - g * g.constant(lr_scalar); + } else { + v += a; + } + } + } + + MaybeForwardRefInputToRefOutput(ctx, 0, 0); + } + + private: + bool use_exclusive_lock_; + bool use_nesterov_; +}; + +#define REGISTER_KERNELS(T, Tindices) \ + REGISTER_KERNEL_BUILDER(Name("ResourceSparseApplyKerasMomentum") \ + .Device(DEVICE_CPU) \ + .TypeConstraint("T") \ + .TypeConstraint("Tindices"), \ + SparseApplyKerasMomentumOp); +#define REGISTER_CPU_KERNELS(T) \ + REGISTER_KERNELS(T, int32); \ + REGISTER_KERNELS(T, int64); + +TF_CALL_half(REGISTER_CPU_KERNELS); +TF_CALL_bfloat16(REGISTER_CPU_KERNELS); +TF_CALL_float(REGISTER_CPU_KERNELS); +TF_CALL_double(REGISTER_CPU_KERNELS); + +#undef REGISTER_CPU_KERNELS +#undef REGISTER_KERNELS + template class ApplyAdamOp : public OpKernel { public: @@ -2786,6 +3035,147 @@ REGISTER_KERNELS(GPU, double); #undef REGISTER_CPU_KERNELS #undef REGISTER_KERNELS +template +class ApplyAdamWithAmsgradOp : public OpKernel { + public: + explicit ApplyAdamWithAmsgradOp(OpKernelConstruction* ctx) : OpKernel(ctx) { + OP_REQUIRES_OK(ctx, ctx->GetAttr("use_locking", &use_exclusive_lock_)); + } + + void Compute(OpKernelContext* ctx) override { + auto locks = MaybeLockVariableInputMutexesInOrder(ctx, use_exclusive_lock_, + {0, 1, 2}); + + Tensor var; + OP_REQUIRES_OK(ctx, GetInputTensorFromVariable( + ctx, 0, use_exclusive_lock_, false, &var)); + Tensor m; + OP_REQUIRES_OK(ctx, GetInputTensorFromVariable( + ctx, 1, use_exclusive_lock_, false, &m)); + Tensor v; + OP_REQUIRES_OK(ctx, GetInputTensorFromVariable( + ctx, 2, use_exclusive_lock_, false, &v)); + Tensor vhat; + OP_REQUIRES_OK(ctx, GetInputTensorFromVariable( + ctx, 3, use_exclusive_lock_, false, &vhat)); + OP_REQUIRES( + ctx, var.IsInitialized(), + errors::FailedPrecondition( + "Attempting to use uninitialized variables: ", requested_input(0))); + OP_REQUIRES( + ctx, m.IsInitialized(), + errors::FailedPrecondition( + "Attempting to use uninitialized variables: ", requested_input(1))); + OP_REQUIRES( + ctx, v.IsInitialized(), + errors::FailedPrecondition( + "Attempting to use uninitialized variables: ", requested_input(2))); + OP_REQUIRES( + ctx, vhat.IsInitialized(), + errors::FailedPrecondition( + "Attempting to use uninitialized variables: ", requested_input(2))); + + const Tensor& beta1_power = ctx->input(4); + const Tensor& beta2_power = ctx->input(5); + const Tensor& lr = ctx->input(6); + const Tensor& beta1 = ctx->input(7); + const Tensor& beta2 = ctx->input(8); + const Tensor& epsilon = ctx->input(9); + + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(beta1_power.shape()), + errors::InvalidArgument("beta1_power is not a scalar: ", + beta1_power.shape().DebugString())); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(beta2_power.shape()), + errors::InvalidArgument("beta2_power is not a scalar: ", + beta2_power.shape().DebugString())); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(lr.shape()), + errors::InvalidArgument("lr is not a scalar : ", + lr.shape().DebugString())); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(beta1.shape()), + errors::InvalidArgument("beta1 is not a scalar: ", + beta1.shape().DebugString())); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(beta2.shape()), + errors::InvalidArgument("beta2 is not a scalar: ", + beta2.shape().DebugString())); + OP_REQUIRES(ctx, TensorShapeUtils::IsScalar(epsilon.shape()), + errors::InvalidArgument("epsilon is not a scalar: ", + epsilon.shape().DebugString())); + + const Tensor& grad = ctx->input(10); + OP_REQUIRES(ctx, var.shape().IsSameSize(m.shape()), + errors::InvalidArgument("var and m do not have the same shape", + var.shape().DebugString(), " ", + m.shape().DebugString())); + OP_REQUIRES(ctx, var.shape().IsSameSize(v.shape()), + errors::InvalidArgument("var and v do not have the same shape", + var.shape().DebugString(), " ", + v.shape().DebugString())); + OP_REQUIRES( + ctx, var.shape().IsSameSize(grad.shape()), + errors::InvalidArgument("var and grad do not have the same shape", + var.shape().DebugString(), " ", + grad.shape().DebugString())); + + const Device& device = ctx->template eigen_device(); + functor::ApplyAdamWithAmsgrad()( + device, var.flat(), m.flat(), v.flat(), vhat.flat(), + beta1_power.scalar(), beta2_power.scalar(), lr.scalar(), + beta1.scalar(), beta2.scalar(), epsilon.scalar(), + grad.flat()); + + MaybeForwardRefInputToRefOutput(ctx, 0, 0); + } + + private: + bool use_exclusive_lock_; +}; + +#define REGISTER_KERNELS(D, T) \ + REGISTER_KERNEL_BUILDER(Name("ResourceApplyAdamWithAmsgrad") \ + .HostMemory("var") \ + .HostMemory("m") \ + .HostMemory("v") \ + .HostMemory("vhat") \ + .Device(DEVICE_##D) \ + .TypeConstraint("T"), \ + ApplyAdamWithAmsgradOp); +#define REGISTER_CPU_KERNELS(T) REGISTER_KERNELS(CPU, T); + +TF_CALL_half(REGISTER_CPU_KERNELS); +TF_CALL_bfloat16(REGISTER_CPU_KERNELS); +TF_CALL_float(REGISTER_CPU_KERNELS); +TF_CALL_double(REGISTER_CPU_KERNELS); + +#if GOOGLE_CUDA +// Forward declarations of the functor specializations for GPU. +namespace functor { +#define DECLARE_GPU_SPEC(T) \ + template <> \ + void ApplyAdamWithAmsgrad::operator()( \ + const GPUDevice& d, typename TTypes::Flat var, \ + typename TTypes::Flat m, typename TTypes::Flat v, \ + typename TTypes::Flat vhat, \ + typename TTypes::ConstScalar beta1_power, \ + typename TTypes::ConstScalar beta2_power, \ + typename TTypes::ConstScalar lr, \ + typename TTypes::ConstScalar beta1, \ + typename TTypes::ConstScalar beta2, \ + typename TTypes::ConstScalar epsilon, \ + typename TTypes::ConstFlat grad); \ + extern template struct ApplyAdamWithAmsgrad; +DECLARE_GPU_SPEC(Eigen::half); +DECLARE_GPU_SPEC(float); +DECLARE_GPU_SPEC(double); +#undef DECLARE_GPU_SPEC +} // namespace functor + +REGISTER_KERNELS(GPU, Eigen::half); +REGISTER_KERNELS(GPU, float); +REGISTER_KERNELS(GPU, double); +#endif +#undef REGISTER_CPU_KERNELS +#undef REGISTER_KERNELS + template class ApplyAdaMaxOp : public OpKernel { public: diff --git a/tensorflow/core/kernels/training_ops.h b/tensorflow/core/kernels/training_ops.h index e10a4cb125..054f07350e 100644 --- a/tensorflow/core/kernels/training_ops.h +++ b/tensorflow/core/kernels/training_ops.h @@ -126,6 +126,15 @@ struct ApplyMomentum { typename TTypes::ConstScalar momentum, bool use_nesterov); }; +template +struct ApplyKerasMomentum { + void operator()(const Device& d, typename TTypes::Flat var, + typename TTypes::Flat accum, + typename TTypes::ConstScalar lr, + typename TTypes::ConstFlat grad, + typename TTypes::ConstScalar momentum, bool use_nesterov); +}; + template struct ApplyAdam { void operator()(const Device& d, typename TTypes::Flat var, @@ -139,6 +148,20 @@ struct ApplyAdam { typename TTypes::ConstFlat grad, bool use_nesterov); }; +template +struct ApplyAdamWithAmsgrad { + void operator()(const Device& d, typename TTypes::Flat var, + typename TTypes::Flat m, typename TTypes::Flat v, + typename TTypes::Flat vhat, + typename TTypes::ConstScalar beta1_power, + typename TTypes::ConstScalar beta2_power, + typename TTypes::ConstScalar lr, + typename TTypes::ConstScalar beta1, + typename TTypes::ConstScalar beta2, + typename TTypes::ConstScalar epsilon, + typename TTypes::ConstFlat grad); +}; + template struct ApplyAdaMax { void operator()(const Device& d, typename TTypes::Flat var, diff --git a/tensorflow/core/kernels/training_ops_gpu.cu.cc b/tensorflow/core/kernels/training_ops_gpu.cu.cc index 4bd32592db..f45b9ffca7 100644 --- a/tensorflow/core/kernels/training_ops_gpu.cu.cc +++ b/tensorflow/core/kernels/training_ops_gpu.cu.cc @@ -101,6 +101,27 @@ struct ApplyMomentum { } }; +template +struct ApplyKerasMomentum { + void operator()(const GPUDevice& d, typename TTypes::Flat var, + typename TTypes::Flat accum, + typename TTypes::ConstScalar lr, + typename TTypes::ConstFlat grad, + typename TTypes::ConstScalar momentum, bool use_nesterov) { + Eigen::array::Tensor::Index, 1> bcast; + bcast[0] = grad.dimension(0); + Eigen::Sizes<1> single; + accum.device(d) = (accum * momentum.reshape(single).broadcast(bcast) - + grad * lr.reshape(single).broadcast(bcast)); + if (use_nesterov) { + var.device(d) += (accum * momentum.reshape(single).broadcast(bcast) - + grad * lr.reshape(single).broadcast(bcast)); + } else { + var.device(d) += accum; + } + } +}; + template struct ApplyAdam { void operator()(const GPUDevice& d, typename TTypes::Flat var, @@ -144,6 +165,39 @@ struct ApplyAdam { } }; +template +struct ApplyAdamWithAmsgrad { + void operator()(const GPUDevice& d, typename TTypes::Flat var, + typename TTypes::Flat m, typename TTypes::Flat v, + typename TTypes::Flat vhat, + typename TTypes::ConstScalar beta1_power, + typename TTypes::ConstScalar beta2_power, + typename TTypes::ConstScalar lr, + typename TTypes::ConstScalar beta1, + typename TTypes::ConstScalar beta2, + typename TTypes::ConstScalar epsilon, + typename TTypes::ConstFlat grad) { + Eigen::array::Tensor::Index, 1> bcast; + bcast[0] = grad.dimension(0); + Eigen::Sizes<1> single; + const auto one = static_cast(1.0); + m.device(d) = + m + (beta1.constant(one) - beta1).reshape(single).broadcast(bcast) * + (grad - m); + v.device(d) = + v + (beta2.constant(one) - beta2).reshape(single).broadcast(bcast) * + (grad.square() - v); + vhat.device(d) = vhat.cwiseMax(v); + + var.device(d) -= (lr * (beta2_power.constant(one) - beta2_power).sqrt() / + (beta1_power.constant(one) - beta1_power)) + .reshape(single) + .broadcast(bcast) * + m / + (epsilon.reshape(single).broadcast(bcast) + vhat.sqrt()); + } +}; + template struct ApplyAdaMax { void operator()(const GPUDevice& d, typename TTypes::Flat var, @@ -302,10 +356,18 @@ template struct functor::ApplyMomentum; template struct functor::ApplyMomentum; template struct functor::ApplyMomentum; +template struct functor::ApplyKerasMomentum; +template struct functor::ApplyKerasMomentum; +template struct functor::ApplyKerasMomentum; + template struct functor::ApplyAdam; template struct functor::ApplyAdam; template struct functor::ApplyAdam; +template struct functor::ApplyAdamWithAmsgrad; +template struct functor::ApplyAdamWithAmsgrad; +template struct functor::ApplyAdamWithAmsgrad; + template struct functor::ApplyAdaMax; template struct functor::ApplyAdaMax; template struct functor::ApplyAdaMax; diff --git a/tensorflow/core/kernels/training_ops_test.cc b/tensorflow/core/kernels/training_ops_test.cc index 2dcc4a500e..1ec57b4522 100644 --- a/tensorflow/core/kernels/training_ops_test.cc +++ b/tensorflow/core/kernels/training_ops_test.cc @@ -151,6 +151,40 @@ static void BM_Momentum(int iters, int params) { } BENCHMARK(BM_Momentum)->Arg(128 << 10)->Arg(256 << 10); +static void KerasMomentum(int32 n, Graph** init_g, Graph** train_g) { + TensorShape shape({n}); + { + Graph* g = new Graph(OpRegistry::Global()); + auto var = Var(g, n); + auto accum = Var(g, n); + auto zero = Zeros(g, n); + test::graph::Assign(g, var, zero); + test::graph::Assign(g, accum, zero); + *init_g = g; + } + { + Graph* g = new Graph(OpRegistry::Global()); + auto var = Var(g, n); + auto accum = Var(g, n); + auto lr = Scalar(g, 0.01); + auto grad = Random(g, n); + auto mom = Scalar(g, 0.01); + test::graph::Multi(g, "ApplyKerasMomentum", {var, accum, lr, grad, mom}); + *train_g = g; + } +} + +static void BM_KerasMomentum(int iters, int params) { + const int64 tot = static_cast(iters) * params; + testing::ItemsProcessed(tot); + testing::BytesProcessed(tot * sizeof(float)); + Graph* init; + Graph* train; + KerasMomentum(params, &init, &train); + test::Benchmark("cpu", train, GetOptions(), init).Run(iters); +} +BENCHMARK(BM_KerasMomentum)->Arg(128 << 10)->Arg(256 << 10); + static void Adam(int32 n, Graph** init_g, Graph** train_g) { TensorShape shape({n}); { @@ -194,6 +228,50 @@ static void BM_Adam(int iters, int params) { } BENCHMARK(BM_Adam)->Arg(128 << 10)->Arg(256 << 10); +static void AdamWithAmsgrad(int32 n, Graph** init_g, Graph** train_g) { + TensorShape shape({n}); + { + Graph* g = new Graph(OpRegistry::Global()); + auto var = Var(g, n); + auto m = Var(g, n); + auto v = Var(g, n); + auto zero = Zeros(g, n); + test::graph::Assign(g, var, zero); + test::graph::Assign(g, m, zero); + test::graph::Assign(g, v, zero); + *init_g = g; + } + { + Graph* g = new Graph(OpRegistry::Global()); + auto var = Var(g, n); + auto m = Var(g, n); + auto v = Var(g, n); + auto vhat = Var(g, n); + auto beta1_power = Scalar(g, 0.9); + auto beta2_power = Scalar(g, 0.99); + auto lr = Scalar(g, 0.01); + auto beta1 = Scalar(g, 0.9); + auto beta2 = Scalar(g, 0.99); + auto epsilon = Scalar(g, 1e-8); + auto grad = Random(g, n); + test::graph::Multi(g, "ApplyAdamWithAmsgrad", + {var, m, v, vhat, beta1_power, beta2_power, lr, beta1, + beta2, epsilon, grad}); + *train_g = g; + } +} + +static void BM_AdamWithAmsgrad(int iters, int params) { + const int64 tot = static_cast(iters) * params; + testing::ItemsProcessed(tot); + testing::BytesProcessed(tot * sizeof(float)); + Graph* init; + Graph* train; + AdamWithAmsgrad(params, &init, &train); + test::Benchmark("cpu", train, GetOptions(), init).Run(iters); +} +BENCHMARK(BM_AdamWithAmsgrad)->Arg(128 << 10)->Arg(256 << 10); + static void RMSProp(int32 n, Graph** init_g, Graph** train_g) { TensorShape shape({n}); { diff --git a/tensorflow/core/kernels/unicode_ops.cc b/tensorflow/core/kernels/unicode_ops.cc index dd4415711b..6c4ed1eaaf 100644 --- a/tensorflow/core/kernels/unicode_ops.cc +++ b/tensorflow/core/kernels/unicode_ops.cc @@ -13,9 +13,17 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include +#include +#include #include #include +#include +#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" +#include "unicode/appendable.h" // TF:icu +#include "unicode/schriter.h" // TF:icu +#include "unicode/uchar.h" // TF:icu #include "unicode/ucnv.h" // TF:icu #include "unicode/ucnv_err.h" // TF:icu #include "unicode/umachine.h" // TF:icu @@ -23,15 +31,57 @@ limitations under the License. #include "unicode/unistr.h" // TF:icu #include "unicode/uset.h" // TF:icu #include "unicode/utypes.h" // TF:icu +#include "tensorflow/core/framework/kernel_def_builder.h" +#include "tensorflow/core/framework/op.h" #include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/register_types.h" #include "tensorflow/core/framework/tensor.h" +#include "tensorflow/core/framework/tensor_shape.h" +#include "tensorflow/core/framework/tensor_types.h" +#include "tensorflow/core/framework/types.h" +#include "tensorflow/core/kernels/bounds_check.h" #include "tensorflow/core/kernels/string_util.h" #include "tensorflow/core/lib/core/errors.h" #include "tensorflow/core/lib/core/status.h" +#include "tensorflow/core/lib/core/stringpiece.h" +#include "tensorflow/core/platform/types.h" #include "tensorflow/core/util/bcast.h" #include "tensorflow/core/util/ptr_util.h" namespace tensorflow { +namespace { + +void Encode(const UnicodeEncoding encoding, const icu::UnicodeString& in, + string* out) { + if (encoding == UnicodeEncoding::UTF8) { + out->clear(); + in.toUTF8String(*out); + } else if (encoding == UnicodeEncoding::UTF16BE) { + // TODO(gbillock): consider using the + // extract(char *dest, int32_t destCapacity, UConverter *cnv) + // for UTF16/32 + out->clear(); // subtle: must come before reserve() + out->reserve(2 * in.length() + 1); + const char16_t* buf = in.getBuffer(); + for (int i = 0; i < in.length(); ++i) { + // Emit big-endian encoding for UTF-16 always. + out->push_back((buf[i] & 0xFF00) >> 8); + out->push_back(buf[i] & 0x00FF); + } + } else if (encoding == UnicodeEncoding::UTF32BE) { + out->clear(); // subtle: must come before reserve() + out->reserve(4 * in.countChar32() + 1); + icu::StringCharacterIterator it(in); + UChar32 ch; + while (it.hasNext()) { + ch = it.next32PostInc(); + out->push_back((ch & 0xFF000000) >> 24); + out->push_back((ch & 0x00FF0000) >> 16); + out->push_back((ch & 0x0000FF00) >> 8); + out->push_back((ch & 0x000000FF)); + } + } +} // This error callback is only useful for finding illegal encoding errors when // we want to be strict -- otherwise illegal encodings are replaced on read @@ -146,40 +196,66 @@ class WrappedConverter { string name_; }; +struct ErrorOptions { + UChar32 subst = 0xFFFD; + bool elide_replacement = false; + bool replace_control_chars = false; + bool error_on_malformatting = false; +}; + +Status GetErrorOptions(OpKernelConstruction* ctx, ErrorOptions* out) { + *out = ErrorOptions(); + + string error_policy; + TF_RETURN_IF_ERROR(ctx->GetAttr("errors", &error_policy)); + + if (error_policy == "replace") { + out->elide_replacement = false; + } else if (error_policy == "ignore") { + out->elide_replacement = true; + } else if (error_policy == "strict") { + out->error_on_malformatting = true; + } else { + return errors::InvalidArgument( + "errors policy must be one of 'strict', 'replace', or 'ignore'"); + } + + int32 replacement_char; + TF_RETURN_IF_ERROR(ctx->GetAttr("replacement_char", &replacement_char)); + + if (replacement_char >= UCHAR_MIN_VALUE && + replacement_char <= UCHAR_MAX_VALUE) { + out->subst = replacement_char; + } else { + return errors::InvalidArgument( + "replacement_char out of unicode codepoint range"); + } + + if (ctx->HasAttr("replace_control_characters")) { + TF_RETURN_IF_ERROR(ctx->GetAttr("replace_control_characters", + &(out->replace_control_chars))); + } + + return Status::OK(); +} + +inline bool ShouldHandleFormatError(const ErrorOptions& error_options, + UChar32 ch, bool format_error) { + return ((error_options.replace_control_chars && ch <= 0x1F) || format_error); +} + +} // namespace + class UnicodeTranscodeOp : public OpKernel { public: explicit UnicodeTranscodeOp(OpKernelConstruction* ctx) : OpKernel(ctx) { - string error_policy; - OP_REQUIRES_OK(ctx, ctx->GetAttr("errors", &error_policy)); - if (error_policy == "replace") { - elide_replacement_ = false; - } else if (error_policy == "ignore") { - elide_replacement_ = true; - } else if (error_policy == "strict") { - error_on_malformatting_ = true; - } else { - ctx->CtxFailure(errors::InvalidArgument( - "errors policy must be one of 'strict', 'replace', or 'ignore'")); - } - - int32 replacement_char; - OP_REQUIRES_OK(ctx, ctx->GetAttr("replacement_char", &replacement_char)); - if (replacement_char >= UCHAR_MIN_VALUE && - replacement_char <= UCHAR_MAX_VALUE) { - subst_ = replacement_char; - } else { - ctx->CtxFailure(errors::InvalidArgument( - "replacement_char out of unicode codepoint range")); - } + OP_REQUIRES_OK(ctx, GetErrorOptions(ctx, &error_options_)); string output_encoding; OP_REQUIRES_OK(ctx, ctx->GetAttr("output_encoding", &output_encoding)); OP_REQUIRES_OK(ctx, ParseUnicodeEncoding(output_encoding, &output_encoding_)); - OP_REQUIRES_OK(ctx, ctx->GetAttr("replace_control_characters", - &replace_control_chars_)); - OP_REQUIRES_OK(ctx, ctx->GetAttr("input_encoding", &input_encoding_)); // Make a temporary UConverter to ensure it will create without error // at execution time (and to warm any data caches the converter needs). @@ -228,7 +304,7 @@ class UnicodeTranscodeOp : public OpKernel { Transcode(&(output_flat(i)), input_encoder->converter_, &found_any_format_error); } - if (error_on_malformatting_ && found_any_format_error) { + if (error_options_.error_on_malformatting && found_any_format_error) { ctx->CtxFailure( errors::InvalidArgument("Invalid formatting on input string")); } @@ -240,12 +316,12 @@ class UnicodeTranscodeOp : public OpKernel { // out-of-range inputs. void TranslateCodepoints(icu::UnicodeString* s, bool* found_any_format_error, UChar32 ch, int src_bytes, bool format_error) { - if ((replace_control_chars_ && ch <= 0x1F) || format_error) { + if (ShouldHandleFormatError(error_options_, ch, format_error)) { *found_any_format_error = true; - if (elide_replacement_) { + if (error_options_.elide_replacement) { return; } else { - ch = subst_; + ch = error_options_.subst; } } s->append(ch); @@ -263,45 +339,202 @@ class UnicodeTranscodeOp : public OpKernel { found_any_format_error, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - if (output_encoding_ == UnicodeEncoding::UTF8) { - s->clear(); - source.toUTF8String(*s); - } else if (output_encoding_ == UnicodeEncoding::UTF16BE) { - // TODO(gbillock): consider using the - // extract(char *dest, int32_t destCapacity, UConverter *cnv) - // for UTF16/32 - s->clear(); // subtle: must come before reserve() - s->reserve(2 * source.length() + 1); - const char16_t* buf = source.getBuffer(); - for (int i = 0; i < source.length(); ++i) { - // Emit big-endian encoding for UTF-16 always. - s->push_back((buf[i] & 0xFF00) >> 8); - s->push_back(buf[i] & 0x00FF); - } - } else if (output_encoding_ == UnicodeEncoding::UTF32BE) { - s->clear(); // subtle: must come before reserve() - s->reserve(4 * source.countChar32() + 1); - for (int i = 0; i < source.countChar32(); ++i) { - // Emit big-endian encoding for UTF-32 always. - UChar32 ch = source.char32At(i); - s->push_back((ch & 0xFF000000) >> 24); - s->push_back((ch & 0x00FF0000) >> 16); - s->push_back((ch & 0x0000FF00) >> 8); - s->push_back((ch & 0x000000FF)); - } - } + Encode(output_encoding_, source, s); } - UChar32 subst_ = 0xFFFD; - bool elide_replacement_ = false; - bool replace_control_chars_ = false; - bool error_on_malformatting_ = false; - string input_encoding_; + ErrorOptions error_options_; UnicodeEncoding output_encoding_ = UnicodeEncoding::UTF8; }; REGISTER_KERNEL_BUILDER(Name("UnicodeTranscode").Device(DEVICE_CPU), UnicodeTranscodeOp); +class UnicodeDecodeWithOffsetsOp : public OpKernel { + public: + explicit UnicodeDecodeWithOffsetsOp(OpKernelConstruction* ctx) + : OpKernel(ctx) { + OP_REQUIRES_OK(ctx, GetErrorOptions(ctx, &error_options_)); + OP_REQUIRES_OK(ctx, ctx->GetAttr("input_encoding", &input_encoding_)); + // Make a temporary UConverter to ensure it will create without error + // at execution time (and to warm any data caches the converter needs). + // This instance is not used. + std::unique_ptr input_encoder = + absl::make_unique(); + input_encoder->init(input_encoding_); + OP_REQUIRES(ctx, input_encoder->converter_, + errors::InvalidArgument( + "Could not create converter for input encoding: " + + input_encoding_)); + } + + void Decode(OpKernelContext* ctx, std::vector* char_values, + std::vector* offset_values, int* string_length, + int64* next_row_split, UChar32 char_value, int char_length, + bool found_any_format_error) { + if (error_options_.error_on_malformatting && found_any_format_error) { + ctx->CtxFailure( + errors::InvalidArgument("Invalid formatting on input string")); + } + UChar32 decoded_value = char_value; + if (ShouldHandleFormatError(error_options_, char_value, + found_any_format_error)) { + if (error_options_.elide_replacement) { + return; + } else { + decoded_value = error_options_.subst; + } + } + + // Emit the char value. + char_values->push_back(decoded_value); + + // Emit the byte offset + offset_values->push_back(*string_length); + *string_length += char_length; + *next_row_split += 1; + } + + void Compute(OpKernelContext* ctx) override { + const Tensor* input_tensor; + OP_REQUIRES_OK(ctx, ctx->input("input", &input_tensor)); + + // Go through all the strings in `input`. + const auto& input_vec = input_tensor->flat(); + + std::unique_ptr input_encoder = + absl::make_unique(); + input_encoder->init(input_encoding_); + OP_REQUIRES(ctx, input_encoder->converter_, + errors::InvalidArgument( + "Could not create converter for input encoding: " + + input_encoding_)); + + std::vector char_values; + std::vector offset_values; + + Tensor* output_row_splits; + OP_REQUIRES_OK(ctx, ctx->allocate_output("row_splits", + {input_tensor->NumElements() + 1}, + &output_row_splits)); + auto out_row_splits = output_row_splits->vec(); + + int row_split_index = 0; + int64 next_row_split = 0; + for (int i = 0; i < input_vec.size(); ++i) { + const string& input = input_vec(i); + // Convert input strings into unicode values. Output to a list of + // char_values, record row splits and char_to_byte_starts, which are all + // the fields needed to construct a RaggedTensor. + out_row_splits(row_split_index) = next_row_split; + row_split_index++; + int string_length = 0; + IterateUnicodeString( + input, input_encoder->converter_, + std::bind(&UnicodeDecodeWithOffsetsOp::Decode, this, ctx, + &char_values, &offset_values, &string_length, + &next_row_split, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3)); + } + out_row_splits(row_split_index) = next_row_split; + + DCHECK(offset_values.size() == char_values.size()); + Tensor* output_char_values; + OP_REQUIRES_OK( + ctx, ctx->allocate_output("char_values", + {static_cast(char_values.size())}, + &output_char_values)); + Tensor* output_offset_values; + OP_REQUIRES_OK( + ctx, ctx->allocate_output("char_to_byte_starts", + {static_cast(offset_values.size())}, + &output_offset_values)); + auto out_char_values = output_char_values->vec(); + auto out_offset_values = output_offset_values->vec(); + + // Load output tensors from intermediate value arrays. + for (int i = 0; i < char_values.size(); ++i) { + out_char_values(i) = static_cast(char_values[i]); + out_offset_values(i) = offset_values[i]; + } + } + + private: + string input_encoding_; + ErrorOptions error_options_; +}; + +REGISTER_KERNEL_BUILDER(Name("UnicodeDecodeWithOffsets").Device(DEVICE_CPU), + UnicodeDecodeWithOffsetsOp); + +class UnicodeEncodeOp : public OpKernel { + public: + explicit UnicodeEncodeOp(OpKernelConstruction* ctx) : OpKernel(ctx) { + string encoding_tmp; + OP_REQUIRES_OK(ctx, ctx->GetAttr("output_encoding", &encoding_tmp)); + OP_REQUIRES_OK(ctx, ParseUnicodeEncoding(encoding_tmp, &encoding_)); + OP_REQUIRES_OK(ctx, GetErrorOptions(ctx, &error_options_)); + } + + /** + * Encodes Unicode codepoints into the desired string representation. + * + * We lose a dimension while encoding, since a series of integer codepoints is + * encoded into a single string. + * + * This accepts two input tensors: a rank 1 tensor of code point values and + * a single rank 1 tensor of splits which determine where each string begins + * and ends from the provided code points. + */ + void Compute(OpKernelContext* context) override { + // Get inputs + const Tensor& input_tensor = context->input(0); + const auto input_tensor_flat = input_tensor.flat(); + const Tensor& input_splits = context->input(1); + const auto input_splits_flat = input_splits.flat(); + + // Since we limit to a 2-D input (inner_values of rank 1 and a single splits + // tensor), our output dimension will be 1 with it's size equal to the + // number of splits (outer dimension or ragged tensor). + TensorShape output_shape({input_splits.dim_size(0) - 1}); + Tensor* output_tensor; + OP_REQUIRES_OK(context, context->allocate_output("output", output_shape, + &output_tensor)); + auto output_tensor_flat = output_tensor->flat(); + + // Use a single index over the flattened input values tensor. + int idx = 0; + // Loop through our split dimension to create a new string at each split. + for (int i = 1; i < input_splits_flat.size(); ++i) { + icu::UnicodeString unicode_string; + icu::UnicodeStringAppendable appendable_unicode_string(unicode_string); + for (; idx < input_splits_flat(i); ++idx) { + int32 code_point = input_tensor_flat(idx); + // Check for invalid code point + if (code_point > UCHAR_MAX_VALUE || code_point < UCHAR_MIN_VALUE) { + if (error_options_.error_on_malformatting) { + context->CtxFailure(errors::InvalidArgument( + "Code point value out of valid Unicode range.")); + return; + } else if (!error_options_.elide_replacement) { + code_point = error_options_.subst; + } + } + appendable_unicode_string.appendCodePoint(code_point); + } + // Encode our string and save in the output. + string result; + Encode(encoding_, unicode_string, &result); + output_tensor_flat(i - 1) = result; + } + } + + private: + UnicodeEncoding encoding_; + ErrorOptions error_options_; +}; + +REGISTER_KERNEL_BUILDER(Name("UnicodeEncode").Device(DEVICE_CPU), + UnicodeEncodeOp); + } // namespace tensorflow diff --git a/tensorflow/core/lib/core/threadpool.cc b/tensorflow/core/lib/core/threadpool.cc index 42689a6c3b..e929ff45a1 100644 --- a/tensorflow/core/lib/core/threadpool.cc +++ b/tensorflow/core/lib/core/threadpool.cc @@ -22,6 +22,7 @@ limitations under the License. #include "tensorflow/core/platform/denormal.h" #include "tensorflow/core/platform/logging.h" #include "tensorflow/core/platform/mutex.h" +#include "tensorflow/core/platform/numa.h" #include "tensorflow/core/platform/setround.h" #include "tensorflow/core/platform/tracing.h" #include "tensorflow/core/platform/types.h" @@ -54,6 +55,9 @@ struct EigenEnvironment { port::ScopedFlushDenormal flush; // Set the processor rounding mode to ROUND TO NEAREST. port::ScopedSetRound round(FE_TONEAREST); + if (thread_options_.numa_node != port::kNUMANoAffinity) { + port::NUMASetThreadNodeAffinity(thread_options_.numa_node); + } f(); }); } @@ -83,35 +87,38 @@ struct EigenEnvironment { struct ThreadPool::Impl : Eigen::ThreadPoolTempl { Impl(Env* env, const ThreadOptions& thread_options, const string& name, - int num_threads, bool low_latency_hint) + int num_threads, bool low_latency_hint, Eigen::Allocator* allocator) : Eigen::ThreadPoolTempl( num_threads, low_latency_hint, - EigenEnvironment(env, thread_options, name)) {} + EigenEnvironment(env, thread_options, name)), + allocator_(allocator) {} void ParallelFor(int64 total, int64 cost_per_unit, std::function fn) { CHECK_GE(total, 0); CHECK_EQ(total, (int64)(Eigen::Index)total); - Eigen::ThreadPoolDevice device(this, this->NumThreads()); + Eigen::ThreadPoolDevice device(this, this->NumThreads(), allocator_); device.parallelFor( total, Eigen::TensorOpCost(0, 0, cost_per_unit), [&fn](Eigen::Index first, Eigen::Index last) { fn(first, last); }); } + + Eigen::Allocator* allocator_; }; ThreadPool::ThreadPool(Env* env, const string& name, int num_threads) - : ThreadPool(env, ThreadOptions(), name, num_threads, true) {} + : ThreadPool(env, ThreadOptions(), name, num_threads, true, nullptr) {} ThreadPool::ThreadPool(Env* env, const ThreadOptions& thread_options, const string& name, int num_threads) - : ThreadPool(env, thread_options, name, num_threads, true) {} + : ThreadPool(env, thread_options, name, num_threads, true, nullptr) {} ThreadPool::ThreadPool(Env* env, const ThreadOptions& thread_options, const string& name, int num_threads, - bool low_latency_hint) { + bool low_latency_hint, Eigen::Allocator* allocator) { CHECK_GE(num_threads, 1); impl_.reset(new ThreadPool::Impl(env, thread_options, "tf_" + name, - num_threads, low_latency_hint)); + num_threads, low_latency_hint, allocator)); } ThreadPool::~ThreadPool() {} diff --git a/tensorflow/core/lib/core/threadpool.h b/tensorflow/core/lib/core/threadpool.h index 3da7dcb632..90c9f29447 100644 --- a/tensorflow/core/lib/core/threadpool.h +++ b/tensorflow/core/lib/core/threadpool.h @@ -22,6 +22,9 @@ limitations under the License. #include "tensorflow/core/platform/macros.h" #include "tensorflow/core/platform/types.h" +namespace Eigen { +class Allocator; +} // namespace Eigen namespace tensorflow { namespace thread { @@ -37,7 +40,8 @@ class ThreadPool { // // REQUIRES: num_threads > 0 ThreadPool(Env* env, const ThreadOptions& thread_options, const string& name, - int num_threads, bool low_latency_hint); + int num_threads, bool low_latency_hint, + Eigen::Allocator* allocator = nullptr); // Constructs a pool for low-latency ops that contains "num_threads" threads // with specified "name". env->StartThread() is used to create individual diff --git a/tensorflow/core/lib/png/png_io.cc b/tensorflow/core/lib/png/png_io.cc index bc52180265..e8dbcb97b9 100644 --- a/tensorflow/core/lib/png/png_io.cc +++ b/tensorflow/core/lib/png/png_io.cc @@ -92,7 +92,11 @@ void StringReader(png_structp png_ptr, png_bytep data, png_size_t length) { DecodeContext* const ctx = absl::bit_cast(png_get_io_ptr(png_ptr)); if (static_cast(ctx->data_left) < length) { - memset(data, 0, length); + // Don't zero out the data buffer as it has been lazily allocated (copy on + // write) and zeroing it out here can produce an OOM. Since the buffer is + // only used for reading data from the image, this doesn't result in any + // data leak, so it is safe to just leave the buffer be as it is and just + // exit with error. png_error(png_ptr, "More bytes requested to read than available"); } else { memcpy(data, ctx->data, length); diff --git a/tensorflow/core/nccl/BUILD b/tensorflow/core/nccl/BUILD index 50d9a2e8da..4be33b2a0c 100644 --- a/tensorflow/core/nccl/BUILD +++ b/tensorflow/core/nccl/BUILD @@ -11,6 +11,10 @@ exports_files(["LICENSE"]) load("//tensorflow:tensorflow.bzl", "tf_cuda_cc_test") load("//tensorflow:tensorflow.bzl", "tf_copts") load("@local_config_cuda//cuda:build_defs.bzl", "if_cuda") +load( + "//tensorflow/core:platform/default/build_config_root.bzl", + "tf_cuda_tests_tags", +) cc_library( name = "nccl_lib", @@ -34,27 +38,17 @@ cc_library( tf_cuda_cc_test( name = "nccl_manager_test", size = "medium", - srcs = if_cuda( - [ - "nccl_manager_test.cc", - ], - [], - ), - # Disabled on jenkins until errors finding nvmlShutdown are found. - tags = [ - "manual", - "multi_gpu", - "no_oss", - "noguitar", - "notap", + srcs = ["nccl_manager_test.cc"], + tags = tf_cuda_tests_tags() + [ + "no_cuda_on_cpu_tap", # TODO(b/120284216): re-enable multi_gpu ], - deps = - if_cuda([ - ":nccl_lib", - "@local_config_nccl//:nccl", - "//tensorflow/core:cuda", - "//tensorflow/core:test", - "//tensorflow/core:test_main", - "//tensorflow/core:testlib", - ]), + deps = [ + "//tensorflow/core:test", + "//tensorflow/core:test_main", + "//tensorflow/core:testlib", + ] + if_cuda([ + ":nccl_lib", + "@local_config_nccl//:nccl", + "//tensorflow/core:cuda", + ]), ) diff --git a/tensorflow/core/nccl/nccl_manager.cc b/tensorflow/core/nccl/nccl_manager.cc index f8e8c75222..df49bf1b97 100644 --- a/tensorflow/core/nccl/nccl_manager.cc +++ b/tensorflow/core/nccl/nccl_manager.cc @@ -24,6 +24,22 @@ limitations under the License. namespace tensorflow { +#define NCCL_RETURN_IF_ERROR(...) \ + do { \ + ncclResult_t nccl_status = (__VA_ARGS__); \ + if (nccl_status != ncclSuccess) { \ + return errors::Internal(ncclGetErrorString(nccl_status)); \ + } \ + } while (0) + +#define CUDA_RETURN_IF_ERROR(...) \ + do { \ + cudaError_t cuda_status = (__VA_ARGS__); \ + if (cuda_status != cudaSuccess) { \ + return errors::Internal(cudaGetErrorString(cuda_status)); \ + } \ + } while (0) + using se::cuda::ScopedActivateExecutorContext; // Contains data for a single stream used for nccl communication; this includes @@ -177,8 +193,8 @@ NcclManager* NcclManager::instance() { return instance; } -NcclManager::Communicator* NcclManager::GetCommunicator( - NcclManager::Collective* collective) { +Status NcclManager::GetCommunicator(NcclManager::Collective* collective, + NcclManager::Communicator** communicator) { // Sort by executor to make ordering of executors deterministic. std::sort(collective->participants.begin(), collective->participants.end(), [](const std::unique_ptr& a, @@ -217,7 +233,10 @@ NcclManager::Communicator* NcclManager::GetCommunicator( break; } } - if (i == num_devices) return comm.get(); + if (i == num_devices) { + *communicator = comm.get(); + return Status::OK(); + } } } @@ -264,37 +283,36 @@ NcclManager::Communicator* NcclManager::GetCommunicator( // NCCL2 prevents InitAll for more communicators than devices (but doesn't // check that device ids are unique). Work around it by initializing each // rank individually. - cudaGetDeviceCount(&device_count); + CUDA_RETURN_IF_ERROR(cudaGetDeviceCount(&device_count)); #endif std::vector nccl_comms(num_devices); if (num_devices <= device_count) { - auto result = - ncclCommInitAll(nccl_comms.data(), num_devices, devices.data()); - CHECK_EQ(result, ncclSuccess) << ncclGetErrorString(result); + NCCL_RETURN_IF_ERROR( + ncclCommInitAll(nccl_comms.data(), num_devices, devices.data())); } else { int savedDevice = 0; - CHECK_EQ(cudaGetDevice(&savedDevice), cudaSuccess); + CUDA_RETURN_IF_ERROR(cudaGetDevice(&savedDevice)); ncclUniqueId commId; - ncclGetUniqueId(&commId); + NCCL_RETURN_IF_ERROR(ncclGetUniqueId(&commId)); #if NCCL_MAJOR >= 2 - CHECK_EQ(ncclGroupStart(), ncclSuccess); + NCCL_RETURN_IF_ERROR(ncclGroupStart()); #endif for (int rank = 0; rank < num_devices; ++rank) { - cudaSetDevice(devices[rank]); - auto result = - ncclCommInitRank(nccl_comms.data() + rank, num_devices, commId, rank); - CHECK_EQ(result, ncclSuccess) << ncclGetErrorString(result); + CUDA_RETURN_IF_ERROR(cudaSetDevice(devices[rank])); + NCCL_RETURN_IF_ERROR(ncclCommInitRank(nccl_comms.data() + rank, + num_devices, commId, rank)); } #if NCCL_MAJOR >= 2 - CHECK_EQ(ncclGroupEnd(), ncclSuccess); + NCCL_RETURN_IF_ERROR(ncclGroupEnd()); #endif - cudaSetDevice(savedDevice); + CUDA_RETURN_IF_ERROR(cudaSetDevice(savedDevice)); } for (int rank = 0; rank < num_devices; ++rank) { members[rank].nccl_comm = nccl_comms[rank]; } communicators_.emplace_back(new Communicator(std::move(members))); - return communicators_.back().get(); + *communicator = communicators_.back().get(); + return Status::OK(); } void NcclManager::AddToAllReduce(int num_devices, const string& key, @@ -400,10 +418,18 @@ void NcclManager::AddParticipant(int num_devices, const string& key, void NcclManager::RunCollective(const string& key, Collective* collective) { static mutex collective_mu(LINKER_INITIALIZED); - auto* communicator = GetCommunicator(collective); - collective->communicator = communicator; - const int size = communicator->num_devices; + Communicator* communicator = nullptr; + const int size = static_cast(collective->participants.size()); + Status s = GetCommunicator(collective, &communicator); + if (!s.ok()) { + for (int i = 0; i < size; ++i) { + collective->participants[i]->done_callback(s); + } + delete collective; + return; + } + collective->communicator = communicator; for (int rank = 0; rank < size; ++rank) { Participant* p = collective->participants[rank].get(); NcclStream* nccl_stream = communicator->members[rank].nccl_stream; diff --git a/tensorflow/core/nccl/nccl_manager.h b/tensorflow/core/nccl/nccl_manager.h index 76b49101d4..5da4fe5554 100644 --- a/tensorflow/core/nccl/nccl_manager.h +++ b/tensorflow/core/nccl/nccl_manager.h @@ -103,7 +103,13 @@ class NcclManager { struct NcclStream; struct Participant; - Communicator* GetCommunicator(Collective* collective); + // Gets the `Communicator` object that will be used to enqueue NCCL kernels + // for `collective`, and returns it via `communicator`. + // + // This may involve creating CUDA streams and NCCL initialization. If a NCCL + // or CUDA error occurs in the process, this returns an INTERNAL error with + // the corresponding NCCL/CUDA error string. + Status GetCommunicator(Collective* collective, Communicator** communicator); void AddParticipant(int num_devices, const string& key, std::unique_ptr participant, diff --git a/tensorflow/core/nccl/nccl_manager_test.cc b/tensorflow/core/nccl/nccl_manager_test.cc index dbc07865f0..f43103e120 100644 --- a/tensorflow/core/nccl/nccl_manager_test.cc +++ b/tensorflow/core/nccl/nccl_manager_test.cc @@ -28,8 +28,8 @@ limitations under the License. namespace tensorflow { -static std::vector GetGPUDevices() { - std::vector devices; +static std::vector> GetGPUDevices() { + std::vector> devices; SessionOptions session_options; session_options.config.mutable_gpu_options() ->set_per_process_gpu_memory_fraction(0.1); @@ -37,12 +37,12 @@ static std::vector GetGPUDevices() { Status s = DeviceFactory::GetFactory(DEVICE_GPU) ->AddDevices(session_options, "", &devices); TF_CHECK_OK(s); - std::vector gpus; - for (Device* d : devices) { - if (d->device_type() == "GPU") { - gpus.push_back(static_cast(d)); - } else { - delete d; + std::vector> gpus; + for (std::unique_ptr& device : devices) { + if (device->device_type() == "GPU") { + // If `device_type()` is GPU, this `Device` is guaranteed to be a + // `BaseGPUDevice`, which is a subclass of `Device`. + gpus.emplace_back(static_cast(device.release())); } } return gpus; @@ -64,16 +64,14 @@ class NcclManagerTest : public ::testing::Test { }; static void SetUpTestCase() { - setenv("NCCL_DEBUG", "INFO", 1 /* replace */); - devices_ = new std::vector(GetGPUDevices()); - CHECK(!devices_->empty()); + setenv("NCCL_DEBUG", "WARN", 1 /* replace */); + devices_ = new std::vector>(GetGPUDevices()); LOG(ERROR) << "Running test with " << devices_->size() << " gpus"; } - static void TearDownTestCase() { - for (auto device : *devices_) delete device; - delete devices_; - } + static int32 NumGPUs() { return static_cast(devices_->size()); } + + static void TearDownTestCase() { delete devices_; } TestCase* MakeTestCase(int num_ranks, ncclRedOp_t reduction_op, TensorShape shape, float value_offset) { @@ -153,7 +151,7 @@ class NcclManagerTest : public ::testing::Test { stream->ThenMemcpy(out_cpu.flat().data(), out_gpu_mem, out_cpu.TotalBytes()); SE_ASSERT_OK(stream->BlockHostUntilDone()); - test::ExpectTensorNear(test_case->expected, out_cpu, 0.01); + test::ExpectClose(test_case->expected, out_cpu); } } @@ -166,7 +164,7 @@ class NcclManagerTest : public ::testing::Test { } static BaseGPUDevice* GetDevice(size_t rank) { - return devices_->at(rank % devices_->size()); + return devices_->at(rank % devices_->size()).get(); } private: @@ -181,13 +179,14 @@ class NcclManagerTest : public ::testing::Test { } private: - static std::vector* devices_; + static std::vector>* devices_; static const DataType data_type_; static const Scalar max_; }; template -std::vector* NcclManagerTest::devices_ = nullptr; +std::vector>* NcclManagerTest::devices_ = + nullptr; template const DataType NcclManagerTest::data_type_ = DataTypeToEnum::value; @@ -195,13 +194,13 @@ template const Scalar NcclManagerTest::max_ = Eigen::NumTraits::highest(); -// Instantiate tests for float and half. -using TypeList = ::testing::Types; +// Instantiate tests for float and double. +using TypeList = ::testing::Types; TYPED_TEST_CASE(NcclManagerTest, TypeList); // Test basic sum reduction. TYPED_TEST(NcclManagerTest, BasicSumReduction) { - const int num_ranks = 3; + const int num_ranks = this->NumGPUs(); for (int op = 0; op < 4; ++op) { ncclRedOp_t reduction_op = static_cast(op); @@ -230,10 +229,10 @@ TYPED_TEST(NcclManagerTest, BasicSumReduction) { // To test the higher settings, increase num_ranks, // num_collectives_per_iteration and time_limit_micros. TYPED_TEST(NcclManagerTest, MultipleCallers) { - const int num_ranks = 1; // 2; - const int num_collectives_per_iteration = 1; // 1000; + const int num_ranks = this->NumGPUs(); + const int num_collectives_per_iteration = 10; // 1000; const int num_threads = 3; - const int time_limit_micros = 1; // 60 * 30 * 1000 * 1000; + const int time_limit_micros = 100; // 60 * 30 * 1000 * 1000; int64 start = Env::Default()->NowMicros(); srand(Env::Default()->NowMicros()); diff --git a/tensorflow/core/ops/array_ops.cc b/tensorflow/core/ops/array_ops.cc index f55562ec99..281e2996ed 100644 --- a/tensorflow/core/ops/array_ops.cc +++ b/tensorflow/core/ops/array_ops.cc @@ -2743,6 +2743,9 @@ REGISTER_OP("QuantizeAndDequantizeV2") .Attr("range_given: bool = false") .Output("output: T") .Attr("T: {bfloat16, half, float, double}") + .Attr( + "round_mode: {'HALF_TO_EVEN', 'HALF_UP'} = " + "'HALF_TO_EVEN'") .SetShapeFn([](InferenceContext* c) { ShapeHandle unused; TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); @@ -2878,14 +2881,9 @@ REGISTER_OP("QuantizedInstanceNorm") namespace { -Status ScatterNdShape(InferenceContext* c) { - ShapeHandle indices_shape; - TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(0), 1, &indices_shape)); - ShapeHandle updates_shape; - TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(1), 1, &updates_shape)); - ShapeHandle output_shape; - TF_RETURN_IF_ERROR(c->MakeShapeFromShapeTensor(2, &output_shape)); - +Status ScatterNdShapeHelper(InferenceContext* c, ShapeHandle indices_shape, + ShapeHandle updates_shape, + ShapeHandle output_shape) { if (c->Value(c->NumElements(output_shape)) == 0 && (c->Value(c->NumElements(indices_shape)) > 0 || c->Value(c->NumElements(updates_shape)) > 0)) { @@ -2940,6 +2938,26 @@ Status ScatterNdShape(InferenceContext* c) { return Status::OK(); } +Status ScatterNdShape(InferenceContext* c) { + ShapeHandle indices_shape; + TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(0), 1, &indices_shape)); + ShapeHandle updates_shape; + TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(1), 1, &updates_shape)); + ShapeHandle output_shape; + TF_RETURN_IF_ERROR(c->MakeShapeFromShapeTensor(2, &output_shape)); + return ScatterNdShapeHelper(c, indices_shape, updates_shape, output_shape); +} + +Status ScatterNdTensorShape(InferenceContext* c) { + ShapeHandle output_shape; + TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(0), 1, &output_shape)); + ShapeHandle indices_shape; + TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(1), 1, &indices_shape)); + ShapeHandle updates_shape; + TF_RETURN_IF_ERROR(c->WithRankAtLeast(c->input(2), 1, &updates_shape)); + return ScatterNdShapeHelper(c, indices_shape, updates_shape, output_shape); +} + } // namespace REGISTER_OP("UpperBound") @@ -2979,6 +2997,33 @@ REGISTER_OP("ScatterNd") .Attr("Tindices: {int32, int64}") .SetShapeFn(ScatterNdShape); +REGISTER_OP("TensorScatterUpdate") + .Input("tensor: T") + .Input("indices: Tindices") + .Input("updates: T") + .Output("output: T") + .Attr("T: type") + .Attr("Tindices: {int32, int64}") + .SetShapeFn(ScatterNdTensorShape); + +REGISTER_OP("TensorScatterAdd") + .Input("tensor: T") + .Input("indices: Tindices") + .Input("updates: T") + .Output("output: T") + .Attr("T: type") + .Attr("Tindices: {int32, int64}") + .SetShapeFn(ScatterNdTensorShape); + +REGISTER_OP("TensorScatterSub") + .Input("tensor: T") + .Input("indices: Tindices") + .Input("updates: T") + .Output("output: T") + .Attr("T: type") + .Attr("Tindices: {int32, int64}") + .SetShapeFn(ScatterNdTensorShape); + REGISTER_OP("ScatterNdNonAliasingAdd") .Input("input: T") .Input("indices: Tindices") diff --git a/tensorflow/core/ops/compat/ops_history.v1.pbtxt b/tensorflow/core/ops/compat/ops_history.v1.pbtxt index bfcc92dcb0..8022c390c6 100644 --- a/tensorflow/core/ops/compat/ops_history.v1.pbtxt +++ b/tensorflow/core/ops/compat/ops_history.v1.pbtxt @@ -12076,33 +12076,6 @@ op { type: "list(float)" } } -op { - name: "BytesProducedStatsDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "tag" - type: DT_STRING - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "CTCBeamSearchDecoder" input_arg { @@ -17326,21 +17299,6 @@ op { minimum: 1 } } -op { - name: "DatasetToTFRecord" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "filename" - type: DT_STRING - } - input_arg { - name: "compression_type" - type: DT_STRING - } -} op { name: "DebugGradientIdentity" input_arg { @@ -18487,69 +18445,6 @@ op { } } } -op { - name: "DenseToSparseBatchDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "batch_size" - type: DT_INT64 - } - input_arg { - name: "row_shape" - type: DT_INT64 - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} -op { - name: "DenseToSparseBatchDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "batch_size" - type: DT_INT64 - } - input_arg { - name: "row_shape" - type: DT_INT64 - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "DenseToSparseSetOperation" input_arg { @@ -21153,24 +21048,6 @@ op { type: DT_STRING } } -op { - name: "EnqueueInQueueDataset" - input_arg { - name: "queue" - type: DT_VARIANT - } - input_arg { - name: "components" - type_list_attr: "Tcomponents" - } - attr { - name: "Tcomponents" - type: "list(type)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} op { name: "EnsureShape" input_arg { @@ -21626,6 +21503,33 @@ op { minimum: 1 } } +op { + name: "ExperimentalBytesProducedStatsDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "tag" + type: DT_STRING + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} op { name: "ExperimentalCSVDataset" input_arg { @@ -21691,6 +21595,84 @@ op { } is_stateful: true } +op { + name: "ExperimentalDatasetToTFRecord" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "filename" + type: DT_STRING + } + input_arg { + name: "compression_type" + type: DT_STRING + } +} +op { + name: "ExperimentalDenseToSparseBatchDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "batch_size" + type: DT_INT64 + } + input_arg { + name: "row_shape" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + is_stateful: true +} +op { + name: "ExperimentalDenseToSparseBatchDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "batch_size" + type: DT_INT64 + } + input_arg { + name: "row_shape" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} op { name: "ExperimentalDirectedInterleaveDataset" input_arg { @@ -21726,50 +21708,129 @@ op { } } op { - name: "ExperimentalFunctionBufferingResource" + name: "ExperimentalGroupByReducerDataset" input_arg { - name: "string_arg" - type: DT_STRING + name: "input_dataset" + type: DT_VARIANT } input_arg { - name: "target_device" - type: DT_STRING + name: "key_func_other_arguments" + type_list_attr: "Tkey_func_other_arguments" + } + input_arg { + name: "init_func_other_arguments" + type_list_attr: "Tinit_func_other_arguments" + } + input_arg { + name: "reduce_func_other_arguments" + type_list_attr: "Treduce_func_other_arguments" + } + input_arg { + name: "finalize_func_other_arguments" + type_list_attr: "Tfinalize_func_other_arguments" } output_arg { - name: "resource" - type: DT_RESOURCE + name: "handle" + type: DT_VARIANT } attr { - name: "shared_name" - type: "string" + name: "key_func" + type: "func" } attr { - name: "container" - type: "string" + name: "init_func" + type: "func" } attr { - name: "f" + name: "reduce_func" type: "func" } attr { - name: "buffer_size" - type: "int" + name: "finalize_func" + type: "func" + } + attr { + name: "Tkey_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Tinit_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Treduce_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Tfinalize_func_other_arguments" + type: "list(type)" + has_minimum: true } attr { name: "output_types" type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 } is_stateful: true } op { - name: "ExperimentalFunctionBufferingResourceGetNext" + name: "ExperimentalGroupByWindowDataset" input_arg { - name: "function_buffer_resource" - type: DT_RESOURCE + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "key_func_other_arguments" + type_list_attr: "Tkey_func_other_arguments" + } + input_arg { + name: "reduce_func_other_arguments" + type_list_attr: "Treduce_func_other_arguments" + } + input_arg { + name: "window_size_func_other_arguments" + type_list_attr: "Twindow_size_func_other_arguments" } output_arg { - name: "output" - type_list_attr: "output_types" + name: "handle" + type: DT_VARIANT + } + attr { + name: "key_func" + type: "func" + } + attr { + name: "reduce_func" + type: "func" + } + attr { + name: "window_size_func" + type: "func" + } + attr { + name: "Tkey_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Treduce_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Twindow_size_func_other_arguments" + type: "list(type)" + has_minimum: true } attr { name: "output_types" @@ -21777,15 +21838,75 @@ op { has_minimum: true minimum: 1 } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } is_stateful: true } op { - name: "ExperimentalFunctionBufferingResourceReset" + name: "ExperimentalGroupByWindowDataset" input_arg { - name: "function_buffer_resource" - type: DT_RESOURCE + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "key_func_other_arguments" + type_list_attr: "Tkey_func_other_arguments" + } + input_arg { + name: "reduce_func_other_arguments" + type_list_attr: "Treduce_func_other_arguments" + } + input_arg { + name: "window_size_func_other_arguments" + type_list_attr: "Twindow_size_func_other_arguments" + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "key_func" + type: "func" + } + attr { + name: "reduce_func" + type: "func" + } + attr { + name: "window_size_func" + type: "func" + } + attr { + name: "Tkey_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Treduce_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Twindow_size_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 } - is_stateful: true } op { name: "ExperimentalIdentityIndexedDataset" @@ -21898,6 +22019,136 @@ op { } is_stateful: true } +op { + name: "ExperimentalLatencyStatsDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "tag" + type: DT_STRING + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalMapAndBatchDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "other_arguments" + type_list_attr: "Targuments" + } + input_arg { + name: "batch_size" + type: DT_INT64 + } + input_arg { + name: "num_parallel_calls" + type: DT_INT64 + } + input_arg { + name: "drop_remainder" + type: DT_BOOL + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "f" + type: "func" + } + attr { + name: "Targuments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalMapDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "other_arguments" + type_list_attr: "Targuments" + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "f" + type: "func" + } + attr { + name: "Targuments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + attr { + name: "use_inter_op_parallelism" + type: "bool" + default_value { + b: true + } + } +} +op { + name: "ExperimentalMatchingFilesDataset" + input_arg { + name: "patterns" + type: DT_STRING + } + output_arg { + name: "handle" + type: DT_VARIANT + } + is_stateful: true +} op { name: "ExperimentalMaterializedIndexDatasetHandle" output_arg { @@ -21926,6 +22177,33 @@ op { } is_stateful: true } +op { + name: "ExperimentalMaxIntraOpParallelismDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "max_intra_op_parallelism" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} op { name: "ExperimentalNonSerializableDataset" input_arg { @@ -21997,6 +22275,346 @@ op { minimum: 1 } } +op { + name: "ExperimentalParallelInterleaveDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "other_arguments" + type_list_attr: "Targuments" + } + input_arg { + name: "cycle_length" + type: DT_INT64 + } + input_arg { + name: "block_length" + type: DT_INT64 + } + input_arg { + name: "sloppy" + type: DT_BOOL + } + input_arg { + name: "buffer_output_elements" + type: DT_INT64 + } + input_arg { + name: "prefetch_input_elements" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "f" + type: "func" + } + attr { + name: "Targuments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalParseExampleDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "num_parallel_calls" + type: DT_INT64 + } + input_arg { + name: "dense_defaults" + type_list_attr: "Tdense" + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "sparse_keys" + type: "list(string)" + has_minimum: true + } + attr { + name: "dense_keys" + type: "list(string)" + has_minimum: true + } + attr { + name: "sparse_types" + type: "list(type)" + has_minimum: true + allowed_values { + list { + type: DT_FLOAT + type: DT_INT64 + type: DT_STRING + } + } + } + attr { + name: "Tdense" + type: "list(type)" + has_minimum: true + allowed_values { + list { + type: DT_FLOAT + type: DT_INT64 + type: DT_STRING + } + } + } + attr { + name: "dense_shapes" + type: "list(shape)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalParseExampleDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "num_parallel_calls" + type: DT_INT64 + } + input_arg { + name: "dense_defaults" + type_list_attr: "Tdense" + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "sparse_keys" + type: "list(string)" + has_minimum: true + } + attr { + name: "dense_keys" + type: "list(string)" + has_minimum: true + } + attr { + name: "sparse_types" + type: "list(type)" + has_minimum: true + allowed_values { + list { + type: DT_FLOAT + type: DT_INT64 + type: DT_STRING + } + } + } + attr { + name: "Tdense" + type: "list(type)" + has_minimum: true + allowed_values { + list { + type: DT_FLOAT + type: DT_INT64 + type: DT_STRING + } + } + } + attr { + name: "dense_shapes" + type: "list(shape)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + attr { + name: "sloppy" + type: "bool" + default_value { + b: false + } + } +} +op { + name: "ExperimentalPrivateThreadPoolDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "num_threads" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalRandomDataset" + input_arg { + name: "seed" + type: DT_INT64 + } + input_arg { + name: "seed2" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + is_stateful: true +} +op { + name: "ExperimentalScanDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "initial_state" + type_list_attr: "Tstate" + } + input_arg { + name: "other_arguments" + type_list_attr: "Targuments" + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "f" + type: "func" + } + attr { + name: "Tstate" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "Targuments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalSetStatsAggregatorDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "stats_aggregator" + type: DT_RESOURCE + } + input_arg { + name: "tag" + type: DT_STRING + } + input_arg { + name: "counter_prefix" + type: DT_STRING + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + is_stateful: true +} op { name: "ExperimentalSleepDataset" input_arg { @@ -22024,6 +22642,107 @@ op { minimum: 1 } } +op { + name: "ExperimentalSlidingWindowDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "window_size" + type: DT_INT64 + } + input_arg { + name: "window_shift" + type: DT_INT64 + } + input_arg { + name: "window_stride" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalSqlDataset" + input_arg { + name: "driver_name" + type: DT_STRING + } + input_arg { + name: "data_source_name" + type: DT_STRING + } + input_arg { + name: "query" + type: DT_STRING + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + is_stateful: true +} +op { + name: "ExperimentalStatsAggregatorHandle" + output_arg { + name: "handle" + type: DT_RESOURCE + } + attr { + name: "container" + type: "string" + default_value { + s: "" + } + } + attr { + name: "shared_name" + type: "string" + default_value { + s: "" + } + } + is_stateful: true +} +op { + name: "ExperimentalStatsAggregatorSummary" + input_arg { + name: "iterator" + type: DT_RESOURCE + } + output_arg { + name: "summary" + type: DT_STRING + } + is_stateful: true +} op { name: "ExperimentalThreadPoolDataset" input_arg { @@ -22089,6 +22808,29 @@ op { } is_stateful: true } +op { + name: "ExperimentalUnbatchDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} op { name: "ExperimentalUniqueDataset" input_arg { @@ -26313,207 +27055,6 @@ op { } } } -op { - name: "GroupByReducerDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "key_func_other_arguments" - type_list_attr: "Tkey_func_other_arguments" - } - input_arg { - name: "init_func_other_arguments" - type_list_attr: "Tinit_func_other_arguments" - } - input_arg { - name: "reduce_func_other_arguments" - type_list_attr: "Treduce_func_other_arguments" - } - input_arg { - name: "finalize_func_other_arguments" - type_list_attr: "Tfinalize_func_other_arguments" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "key_func" - type: "func" - } - attr { - name: "init_func" - type: "func" - } - attr { - name: "reduce_func" - type: "func" - } - attr { - name: "finalize_func" - type: "func" - } - attr { - name: "Tkey_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Tinit_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Treduce_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Tfinalize_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} -op { - name: "GroupByWindowDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "key_func_other_arguments" - type_list_attr: "Tkey_func_other_arguments" - } - input_arg { - name: "reduce_func_other_arguments" - type_list_attr: "Treduce_func_other_arguments" - } - input_arg { - name: "window_size_func_other_arguments" - type_list_attr: "Twindow_size_func_other_arguments" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "key_func" - type: "func" - } - attr { - name: "reduce_func" - type: "func" - } - attr { - name: "window_size_func" - type: "func" - } - attr { - name: "Tkey_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Treduce_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Twindow_size_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} -op { - name: "GroupByWindowDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "key_func_other_arguments" - type_list_attr: "Tkey_func_other_arguments" - } - input_arg { - name: "reduce_func_other_arguments" - type_list_attr: "Treduce_func_other_arguments" - } - input_arg { - name: "window_size_func_other_arguments" - type_list_attr: "Twindow_size_func_other_arguments" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "key_func" - type: "func" - } - attr { - name: "reduce_func" - type: "func" - } - attr { - name: "window_size_func" - type: "func" - } - attr { - name: "Tkey_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Treduce_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Twindow_size_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "GuaranteeConst" input_arg { @@ -29031,151 +29572,124 @@ op { } } op { - name: "LRNGrad" - input_arg { - name: "input_grads" - type_attr: "T" - } - input_arg { - name: "input_image" - type_attr: "T" - } - input_arg { - name: "output_image" - type_attr: "T" - } - output_arg { - name: "output" - type_attr: "T" - } - attr { - name: "depth_radius" - type: "int" - default_value { - i: 5 - } - } - attr { - name: "bias" - type: "float" - default_value { - f: 1 - } - } - attr { - name: "alpha" - type: "float" - default_value { - f: 1 - } - } - attr { - name: "beta" - type: "float" - default_value { - f: 0.5 - } - } - attr { - name: "T" - type: "type" - default_value { - type: DT_FLOAT - } - allowed_values { - list { - type: DT_FLOAT - type: DT_HALF - } - } - } -} -op { - name: "LRNGrad" - input_arg { - name: "input_grads" - type_attr: "T" - } - input_arg { - name: "input_image" - type_attr: "T" - } - input_arg { - name: "output_image" - type_attr: "T" - } - output_arg { - name: "output" - type_attr: "T" - } - attr { - name: "depth_radius" - type: "int" - default_value { - i: 5 - } - } - attr { - name: "bias" - type: "float" - default_value { - f: 1 - } - } - attr { - name: "alpha" - type: "float" - default_value { - f: 1 - } - } - attr { - name: "beta" - type: "float" - default_value { - f: 0.5 - } - } - attr { - name: "T" - type: "type" - default_value { - type: DT_FLOAT - } - allowed_values { - list { - type: DT_HALF - type: DT_BFLOAT16 - type: DT_FLOAT - } - } - } -} -op { - name: "LatencyStatsDataset" + name: "LRNGrad" input_arg { - name: "input_dataset" - type: DT_VARIANT + name: "input_grads" + type_attr: "T" } input_arg { - name: "tag" - type: DT_STRING + name: "input_image" + type_attr: "T" + } + input_arg { + name: "output_image" + type_attr: "T" } output_arg { - name: "handle" - type: DT_VARIANT + name: "output" + type_attr: "T" } attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 + name: "depth_radius" + type: "int" + default_value { + i: 5 + } } attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 + name: "bias" + type: "float" + default_value { + f: 1 + } + } + attr { + name: "alpha" + type: "float" + default_value { + f: 1 + } + } + attr { + name: "beta" + type: "float" + default_value { + f: 0.5 + } + } + attr { + name: "T" + type: "type" + default_value { + type: DT_FLOAT + } + allowed_values { + list { + type: DT_FLOAT + type: DT_HALF + } + } + } +} +op { + name: "LRNGrad" + input_arg { + name: "input_grads" + type_attr: "T" + } + input_arg { + name: "input_image" + type_attr: "T" + } + input_arg { + name: "output_image" + type_attr: "T" + } + output_arg { + name: "output" + type_attr: "T" + } + attr { + name: "depth_radius" + type: "int" + default_value { + i: 5 + } + } + attr { + name: "bias" + type: "float" + default_value { + f: 1 + } + } + attr { + name: "alpha" + type: "float" + default_value { + f: 1 + } + } + attr { + name: "beta" + type: "float" + default_value { + f: 0.5 + } + } + attr { + name: "T" + type: "type" + default_value { + type: DT_FLOAT + } + allowed_values { + list { + type: DT_HALF + type: DT_BFLOAT16 + type: DT_FLOAT + } + } } } op { @@ -30635,102 +31149,6 @@ op { } is_stateful: true } -op { - name: "MapAndBatchDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "other_arguments" - type_list_attr: "Targuments" - } - input_arg { - name: "batch_size" - type: DT_INT64 - } - input_arg { - name: "num_parallel_batches" - type: DT_INT64 - } - input_arg { - name: "drop_remainder" - type: DT_BOOL - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "f" - type: "func" - } - attr { - name: "Targuments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} -op { - name: "MapAndBatchDatasetV2" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "other_arguments" - type_list_attr: "Targuments" - } - input_arg { - name: "batch_size" - type: DT_INT64 - } - input_arg { - name: "num_parallel_calls" - type: DT_INT64 - } - input_arg { - name: "drop_remainder" - type: DT_BOOL - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "f" - type: "func" - } - attr { - name: "Targuments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "MapClear" attr { @@ -31392,72 +31810,60 @@ op { } } op { - name: "MatMul" - input_arg { - name: "a" - type_attr: "T" - } - input_arg { - name: "b" - type_attr: "T" - } - output_arg { - name: "product" - type_attr: "T" - } - attr { - name: "transpose_a" - type: "bool" - default_value { - b: false - } - } - attr { - name: "transpose_b" - type: "bool" - default_value { - b: false - } - } - attr { - name: "T" - type: "type" - allowed_values { - list { - type: DT_BFLOAT16 - type: DT_HALF - type: DT_FLOAT - type: DT_DOUBLE - type: DT_INT32 - type: DT_INT64 - type: DT_COMPLEX64 - type: DT_COMPLEX128 - } - } - } -} -op { - name: "MatchingFiles" + name: "MatMul" input_arg { - name: "pattern" - type: DT_STRING + name: "a" + type_attr: "T" + } + input_arg { + name: "b" + type_attr: "T" } output_arg { - name: "filenames" - type: DT_STRING + name: "product" + type_attr: "T" + } + attr { + name: "transpose_a" + type: "bool" + default_value { + b: false + } + } + attr { + name: "transpose_b" + type: "bool" + default_value { + b: false + } + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_BFLOAT16 + type: DT_HALF + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT32 + type: DT_INT64 + type: DT_COMPLEX64 + type: DT_COMPLEX128 + } + } } } op { - name: "MatchingFilesDataset" + name: "MatchingFiles" input_arg { - name: "patterns" + name: "pattern" type: DT_STRING } output_arg { - name: "handle" - type: DT_VARIANT + name: "filenames" + type: DT_STRING } - is_stateful: true } op { name: "MatrixBandPart" @@ -39011,62 +39417,6 @@ op { type: "type" } } -op { - name: "ParallelInterleaveDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "other_arguments" - type_list_attr: "Targuments" - } - input_arg { - name: "cycle_length" - type: DT_INT64 - } - input_arg { - name: "block_length" - type: DT_INT64 - } - input_arg { - name: "sloppy" - type: DT_BOOL - } - input_arg { - name: "buffer_output_elements" - type: DT_INT64 - } - input_arg { - name: "prefetch_input_elements" - type: DT_INT64 - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "f" - type: "func" - } - attr { - name: "Targuments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "ParallelInterleaveDatasetV2" input_arg { @@ -39561,153 +39911,6 @@ op { has_minimum: true } } -op { - name: "ParseExampleDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "num_parallel_calls" - type: DT_INT64 - } - input_arg { - name: "dense_defaults" - type_list_attr: "Tdense" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "sparse_keys" - type: "list(string)" - has_minimum: true - } - attr { - name: "dense_keys" - type: "list(string)" - has_minimum: true - } - attr { - name: "sparse_types" - type: "list(type)" - has_minimum: true - allowed_values { - list { - type: DT_FLOAT - type: DT_INT64 - type: DT_STRING - } - } - } - attr { - name: "Tdense" - type: "list(type)" - has_minimum: true - allowed_values { - list { - type: DT_FLOAT - type: DT_INT64 - type: DT_STRING - } - } - } - attr { - name: "dense_shapes" - type: "list(shape)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} -op { - name: "ParseExampleDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "num_parallel_calls" - type: DT_INT64 - } - input_arg { - name: "dense_defaults" - type_list_attr: "Tdense" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "sparse_keys" - type: "list(string)" - has_minimum: true - } - attr { - name: "dense_keys" - type: "list(string)" - has_minimum: true - } - attr { - name: "sparse_types" - type: "list(type)" - has_minimum: true - allowed_values { - list { - type: DT_FLOAT - type: DT_INT64 - type: DT_STRING - } - } - } - attr { - name: "Tdense" - type: "list(type)" - has_minimum: true - allowed_values { - list { - type: DT_FLOAT - type: DT_INT64 - type: DT_STRING - } - } - } - attr { - name: "dense_shapes" - type: "list(shape)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - attr { - name: "sloppy" - type: "bool" - default_value { - b: false - } - } -} op { name: "ParseSequenceExample" input_arg { @@ -40276,6 +40479,52 @@ op { } } } +op { + name: "PartitionedCall" + input_arg { + name: "args" + type_list_attr: "Tin" + } + output_arg { + name: "output" + type_list_attr: "Tout" + } + attr { + name: "Tin" + type: "list(type)" + has_minimum: true + } + attr { + name: "Tout" + type: "list(type)" + has_minimum: true + } + attr { + name: "f" + type: "func" + } + attr { + name: "config" + type: "string" + default_value { + s: "" + } + } + attr { + name: "config_proto" + type: "string" + default_value { + s: "" + } + } + attr { + name: "executor_type" + type: "string" + default_value { + s: "" + } + } +} op { name: "Placeholder" output_arg { @@ -40591,48 +40840,6 @@ op { minimum: 1 } } -op { - name: "PrependFromQueueAndPaddedBatchDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "batch_size" - type: DT_INT64 - } - input_arg { - name: "padded_shapes" - type: DT_INT64 - number_attr: "N" - } - input_arg { - name: "padding_values" - type_list_attr: "Toutput_types" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "Toutput_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - attr { - name: "N" - type: "int" - has_minimum: true - minimum: 1 - } -} op { name: "PreventGradient" input_arg { @@ -41460,20 +41667,228 @@ op { b: false } } - attr { - name: "input_min" - type: "float" - default_value { - f: 0 - } - } - attr { - name: "input_max" - type: "float" - default_value { - f: 0 - } - } + attr { + name: "input_min" + type: "float" + default_value { + f: 0 + } + } + attr { + name: "input_max" + type: "float" + default_value { + f: 0 + } + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_BFLOAT16 + type: DT_HALF + type: DT_FLOAT + type: DT_DOUBLE + } + } + } + deprecation { + version: 22 + } +} +op { + name: "QuantizeAndDequantizeV2" + input_arg { + name: "input" + type_attr: "T" + } + input_arg { + name: "input_min" + type_attr: "T" + } + input_arg { + name: "input_max" + type_attr: "T" + } + output_arg { + name: "output" + type_attr: "T" + } + attr { + name: "signed_input" + type: "bool" + default_value { + b: true + } + } + attr { + name: "num_bits" + type: "int" + default_value { + i: 8 + } + } + attr { + name: "range_given" + type: "bool" + default_value { + b: false + } + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + } + } + } +} +op { + name: "QuantizeAndDequantizeV2" + input_arg { + name: "input" + type_attr: "T" + } + input_arg { + name: "input_min" + type_attr: "T" + } + input_arg { + name: "input_max" + type_attr: "T" + } + output_arg { + name: "output" + type_attr: "T" + } + attr { + name: "signed_input" + type: "bool" + default_value { + b: true + } + } + attr { + name: "num_bits" + type: "int" + default_value { + i: 8 + } + } + attr { + name: "range_given" + type: "bool" + default_value { + b: false + } + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_BFLOAT16 + type: DT_FLOAT + type: DT_DOUBLE + } + } + } +} +op { + name: "QuantizeAndDequantizeV2" + input_arg { + name: "input" + type_attr: "T" + } + input_arg { + name: "input_min" + type_attr: "T" + } + input_arg { + name: "input_max" + type_attr: "T" + } + output_arg { + name: "output" + type_attr: "T" + } + attr { + name: "signed_input" + type: "bool" + default_value { + b: true + } + } + attr { + name: "num_bits" + type: "int" + default_value { + i: 8 + } + } + attr { + name: "range_given" + type: "bool" + default_value { + b: false + } + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_BFLOAT16 + type: DT_HALF + type: DT_FLOAT + type: DT_DOUBLE + } + } + } +} +op { + name: "QuantizeAndDequantizeV2" + input_arg { + name: "input" + type_attr: "T" + } + input_arg { + name: "input_min" + type_attr: "T" + } + input_arg { + name: "input_max" + type_attr: "T" + } + output_arg { + name: "output" + type_attr: "T" + } + attr { + name: "signed_input" + type: "bool" + default_value { + b: true + } + } + attr { + name: "num_bits" + type: "int" + default_value { + i: 8 + } + } + attr { + name: "range_given" + type: "bool" + default_value { + b: false + } + } attr { name: "T" type: "type" @@ -41486,159 +41901,16 @@ op { } } } - deprecation { - version: 22 - } -} -op { - name: "QuantizeAndDequantizeV2" - input_arg { - name: "input" - type_attr: "T" - } - input_arg { - name: "input_min" - type_attr: "T" - } - input_arg { - name: "input_max" - type_attr: "T" - } - output_arg { - name: "output" - type_attr: "T" - } - attr { - name: "signed_input" - type: "bool" - default_value { - b: true - } - } - attr { - name: "num_bits" - type: "int" - default_value { - i: 8 - } - } - attr { - name: "range_given" - type: "bool" - default_value { - b: false - } - } - attr { - name: "T" - type: "type" - allowed_values { - list { - type: DT_FLOAT - type: DT_DOUBLE - } - } - } -} -op { - name: "QuantizeAndDequantizeV2" - input_arg { - name: "input" - type_attr: "T" - } - input_arg { - name: "input_min" - type_attr: "T" - } - input_arg { - name: "input_max" - type_attr: "T" - } - output_arg { - name: "output" - type_attr: "T" - } - attr { - name: "signed_input" - type: "bool" - default_value { - b: true - } - } - attr { - name: "num_bits" - type: "int" - default_value { - i: 8 - } - } - attr { - name: "range_given" - type: "bool" - default_value { - b: false - } - } - attr { - name: "T" - type: "type" - allowed_values { - list { - type: DT_BFLOAT16 - type: DT_FLOAT - type: DT_DOUBLE - } - } - } -} -op { - name: "QuantizeAndDequantizeV2" - input_arg { - name: "input" - type_attr: "T" - } - input_arg { - name: "input_min" - type_attr: "T" - } - input_arg { - name: "input_max" - type_attr: "T" - } - output_arg { - name: "output" - type_attr: "T" - } - attr { - name: "signed_input" - type: "bool" - default_value { - b: true - } - } attr { - name: "num_bits" - type: "int" - default_value { - i: 8 - } - } - attr { - name: "range_given" - type: "bool" + name: "round_mode" + type: "string" default_value { - b: false + s: "HALF_TO_EVEN" } - } - attr { - name: "T" - type: "type" allowed_values { list { - type: DT_BFLOAT16 - type: DT_HALF - type: DT_FLOAT - type: DT_DOUBLE + s: "HALF_TO_EVEN" + s: "HALF_UP" } } } @@ -44844,34 +45116,6 @@ op { } is_stateful: true } -op { - name: "RandomDataset" - input_arg { - name: "seed" - type: DT_INT64 - } - input_arg { - name: "seed2" - type: DT_INT64 - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} op { name: "RandomGamma" input_arg { @@ -48760,21 +49004,89 @@ op { list { type: DT_FLOAT type: DT_DOUBLE - type: DT_INT64 + type: DT_INT64 + type: DT_INT32 + type: DT_UINT8 + type: DT_UINT16 + type: DT_INT16 + type: DT_INT8 + type: DT_COMPLEX64 + type: DT_COMPLEX128 + type: DT_QINT8 + type: DT_QUINT8 + type: DT_QINT32 + type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 + type: DT_BFLOAT16 + } + } + } + attr { + name: "use_locking" + type: "bool" + default_value { + b: false + } + } + is_stateful: true +} +op { + name: "ResourceApplyAdagradDA" + input_arg { + name: "var" + type: DT_RESOURCE + } + input_arg { + name: "gradient_accumulator" + type: DT_RESOURCE + } + input_arg { + name: "gradient_squared_accumulator" + type: DT_RESOURCE + } + input_arg { + name: "grad" + type_attr: "T" + } + input_arg { + name: "lr" + type_attr: "T" + } + input_arg { + name: "l1" + type_attr: "T" + } + input_arg { + name: "l2" + type_attr: "T" + } + input_arg { + name: "global_step" + type: DT_INT64 + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE type: DT_INT32 type: DT_UINT8 - type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_COMPLEX128 + type: DT_INT64 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 type: DT_HALF type: DT_UINT32 type: DT_UINT64 - type: DT_BFLOAT16 } } } @@ -48788,21 +49100,25 @@ op { is_stateful: true } op { - name: "ResourceApplyAdagradDA" + name: "ResourceApplyAdam" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "gradient_accumulator" + name: "m" type: DT_RESOURCE } input_arg { - name: "gradient_squared_accumulator" + name: "v" type: DT_RESOURCE } input_arg { - name: "grad" + name: "beta1_power" + type_attr: "T" + } + input_arg { + name: "beta2_power" type_attr: "T" } input_arg { @@ -48810,16 +49126,20 @@ op { type_attr: "T" } input_arg { - name: "l1" + name: "beta1" type_attr: "T" } input_arg { - name: "l2" + name: "beta2" type_attr: "T" } input_arg { - name: "global_step" - type: DT_INT64 + name: "epsilon" + type_attr: "T" + } + input_arg { + name: "grad" + type_attr: "T" } attr { name: "T" @@ -48828,21 +49148,18 @@ op { list { type: DT_FLOAT type: DT_DOUBLE + type: DT_INT64 type: DT_INT32 type: DT_UINT8 + type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_INT64 + type: DT_COMPLEX128 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 - type: DT_BFLOAT16 - type: DT_UINT16 - type: DT_COMPLEX128 type: DT_HALF - type: DT_UINT32 - type: DT_UINT64 } } } @@ -48926,6 +49243,13 @@ op { b: false } } + attr { + name: "use_nesterov" + type: "bool" + default_value { + b: false + } + } is_stateful: true } op { @@ -48989,6 +49313,8 @@ op { type: DT_QUINT8 type: DT_QINT32 type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 } } } @@ -49071,6 +49397,7 @@ op { type: DT_HALF type: DT_UINT32 type: DT_UINT64 + type: DT_BFLOAT16 } } } @@ -49139,21 +49466,21 @@ op { list { type: DT_FLOAT type: DT_DOUBLE - type: DT_INT64 type: DT_INT32 type: DT_UINT8 - type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_COMPLEX128 + type: DT_INT64 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 type: DT_HALF type: DT_UINT32 type: DT_UINT64 - type: DT_BFLOAT16 } } } @@ -49174,7 +49501,7 @@ op { is_stateful: true } op { - name: "ResourceApplyAdam" + name: "ResourceApplyAdamWithAmsgrad" input_arg { name: "var" type: DT_RESOURCE @@ -49187,6 +49514,10 @@ op { name: "v" type: DT_RESOURCE } + input_arg { + name: "vhat" + type: DT_RESOURCE + } input_arg { name: "beta1_power" type_attr: "T" @@ -49247,8 +49578,64 @@ op { b: false } } + is_stateful: true +} +op { + name: "ResourceApplyAddSign" + input_arg { + name: "var" + type: DT_RESOURCE + } + input_arg { + name: "m" + type: DT_RESOURCE + } + input_arg { + name: "lr" + type_attr: "T" + } + input_arg { + name: "alpha" + type_attr: "T" + } + input_arg { + name: "sign_decay" + type_attr: "T" + } + input_arg { + name: "beta" + type_attr: "T" + } + input_arg { + name: "grad" + type_attr: "T" + } attr { - name: "use_nesterov" + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT64 + type: DT_INT32 + type: DT_UINT8 + type: DT_UINT16 + type: DT_INT16 + type: DT_INT8 + type: DT_COMPLEX64 + type: DT_COMPLEX128 + type: DT_QINT8 + type: DT_QUINT8 + type: DT_QINT32 + type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 + } + } + } + attr { + name: "use_locking" type: "bool" default_value { b: false @@ -49305,8 +49692,142 @@ op { type: DT_QUINT8 type: DT_QINT32 type: DT_HALF - type: DT_UINT32 - type: DT_UINT64 + type: DT_UINT32 + type: DT_UINT64 + type: DT_BFLOAT16 + } + } + } + attr { + name: "use_locking" + type: "bool" + default_value { + b: false + } + } + is_stateful: true +} +op { + name: "ResourceApplyAddSign" + input_arg { + name: "var" + type: DT_RESOURCE + } + input_arg { + name: "m" + type: DT_RESOURCE + } + input_arg { + name: "lr" + type_attr: "T" + } + input_arg { + name: "alpha" + type_attr: "T" + } + input_arg { + name: "sign_decay" + type_attr: "T" + } + input_arg { + name: "beta" + type_attr: "T" + } + input_arg { + name: "grad" + type_attr: "T" + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT32 + type: DT_UINT8 + type: DT_INT16 + type: DT_INT8 + type: DT_COMPLEX64 + type: DT_INT64 + type: DT_QINT8 + type: DT_QUINT8 + type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 + type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 + } + } + } + attr { + name: "use_locking" + type: "bool" + default_value { + b: false + } + } + is_stateful: true +} +op { + name: "ResourceApplyCenteredRMSProp" + input_arg { + name: "var" + type: DT_RESOURCE + } + input_arg { + name: "mg" + type: DT_RESOURCE + } + input_arg { + name: "ms" + type: DT_RESOURCE + } + input_arg { + name: "mom" + type: DT_RESOURCE + } + input_arg { + name: "lr" + type_attr: "T" + } + input_arg { + name: "rho" + type_attr: "T" + } + input_arg { + name: "momentum" + type_attr: "T" + } + input_arg { + name: "epsilon" + type_attr: "T" + } + input_arg { + name: "grad" + type_attr: "T" + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT64 + type: DT_INT32 + type: DT_UINT8 + type: DT_UINT16 + type: DT_INT16 + type: DT_INT8 + type: DT_COMPLEX64 + type: DT_COMPLEX128 + type: DT_QINT8 + type: DT_QUINT8 + type: DT_QINT32 + type: DT_HALF } } } @@ -49320,13 +49841,21 @@ op { is_stateful: true } op { - name: "ResourceApplyAddSign" + name: "ResourceApplyCenteredRMSProp" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "m" + name: "mg" + type: DT_RESOURCE + } + input_arg { + name: "ms" + type: DT_RESOURCE + } + input_arg { + name: "mom" type: DT_RESOURCE } input_arg { @@ -49334,15 +49863,15 @@ op { type_attr: "T" } input_arg { - name: "alpha" + name: "rho" type_attr: "T" } input_arg { - name: "sign_decay" + name: "momentum" type_attr: "T" } input_arg { - name: "beta" + name: "epsilon" type_attr: "T" } input_arg { @@ -49370,7 +49899,6 @@ op { type: DT_HALF type: DT_UINT32 type: DT_UINT64 - type: DT_BFLOAT16 } } } @@ -49384,13 +49912,21 @@ op { is_stateful: true } op { - name: "ResourceApplyAddSign" + name: "ResourceApplyCenteredRMSProp" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "m" + name: "mg" + type: DT_RESOURCE + } + input_arg { + name: "ms" + type: DT_RESOURCE + } + input_arg { + name: "mom" type: DT_RESOURCE } input_arg { @@ -49398,15 +49934,15 @@ op { type_attr: "T" } input_arg { - name: "alpha" + name: "rho" type_attr: "T" } input_arg { - name: "sign_decay" + name: "momentum" type_attr: "T" } input_arg { - name: "beta" + name: "epsilon" type_attr: "T" } input_arg { @@ -49420,21 +49956,21 @@ op { list { type: DT_FLOAT type: DT_DOUBLE + type: DT_INT64 type: DT_INT32 type: DT_UINT8 + type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_INT64 + type: DT_COMPLEX128 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 - type: DT_BFLOAT16 - type: DT_UINT16 - type: DT_COMPLEX128 type: DT_HALF type: DT_UINT32 type: DT_UINT64 + type: DT_BFLOAT16 } } } @@ -49492,18 +50028,21 @@ op { list { type: DT_FLOAT type: DT_DOUBLE - type: DT_INT64 type: DT_INT32 type: DT_UINT8 - type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_COMPLEX128 + type: DT_INT64 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 } } } @@ -49517,41 +50056,37 @@ op { is_stateful: true } op { - name: "ResourceApplyCenteredRMSProp" + name: "ResourceApplyFtrl" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "mg" - type: DT_RESOURCE - } - input_arg { - name: "ms" + name: "accum" type: DT_RESOURCE } input_arg { - name: "mom" + name: "linear" type: DT_RESOURCE } input_arg { - name: "lr" + name: "grad" type_attr: "T" } input_arg { - name: "rho" + name: "lr" type_attr: "T" } input_arg { - name: "momentum" + name: "l1" type_attr: "T" } input_arg { - name: "epsilon" + name: "l2" type_attr: "T" } input_arg { - name: "grad" + name: "lr_power" type_attr: "T" } attr { @@ -49573,8 +50108,6 @@ op { type: DT_QUINT8 type: DT_QINT32 type: DT_HALF - type: DT_UINT32 - type: DT_UINT64 } } } @@ -49588,41 +50121,37 @@ op { is_stateful: true } op { - name: "ResourceApplyCenteredRMSProp" + name: "ResourceApplyFtrl" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "mg" - type: DT_RESOURCE - } - input_arg { - name: "ms" + name: "accum" type: DT_RESOURCE } input_arg { - name: "mom" + name: "linear" type: DT_RESOURCE } input_arg { - name: "lr" + name: "grad" type_attr: "T" } input_arg { - name: "rho" + name: "lr" type_attr: "T" } input_arg { - name: "momentum" + name: "l1" type_attr: "T" } input_arg { - name: "epsilon" + name: "l2" type_attr: "T" } input_arg { - name: "grad" + name: "lr_power" type_attr: "T" } attr { @@ -49646,7 +50175,6 @@ op { type: DT_HALF type: DT_UINT32 type: DT_UINT64 - type: DT_BFLOAT16 } } } @@ -49660,41 +50188,37 @@ op { is_stateful: true } op { - name: "ResourceApplyCenteredRMSProp" + name: "ResourceApplyFtrl" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "mg" - type: DT_RESOURCE - } - input_arg { - name: "ms" + name: "accum" type: DT_RESOURCE } input_arg { - name: "mom" + name: "linear" type: DT_RESOURCE } input_arg { - name: "lr" + name: "grad" type_attr: "T" } input_arg { - name: "rho" + name: "lr" type_attr: "T" } input_arg { - name: "momentum" + name: "l1" type_attr: "T" } input_arg { - name: "epsilon" + name: "l2" type_attr: "T" } input_arg { - name: "grad" + name: "lr_power" type_attr: "T" } attr { @@ -49704,21 +50228,21 @@ op { list { type: DT_FLOAT type: DT_DOUBLE + type: DT_INT64 type: DT_INT32 type: DT_UINT8 + type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_INT64 + type: DT_COMPLEX128 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 - type: DT_BFLOAT16 - type: DT_UINT16 - type: DT_COMPLEX128 type: DT_HALF type: DT_UINT32 type: DT_UINT64 + type: DT_BFLOAT16 } } } @@ -49772,18 +50296,21 @@ op { list { type: DT_FLOAT type: DT_DOUBLE - type: DT_INT64 type: DT_INT32 type: DT_UINT8 - type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_COMPLEX128 + type: DT_INT64 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 } } } @@ -49797,7 +50324,7 @@ op { is_stateful: true } op { - name: "ResourceApplyFtrl" + name: "ResourceApplyFtrlV2" input_arg { name: "var" type: DT_RESOURCE @@ -49826,6 +50353,10 @@ op { name: "l2" type_attr: "T" } + input_arg { + name: "l2_shrinkage" + type_attr: "T" + } input_arg { name: "lr_power" type_attr: "T" @@ -49849,8 +50380,6 @@ op { type: DT_QUINT8 type: DT_QINT32 type: DT_HALF - type: DT_UINT32 - type: DT_UINT64 } } } @@ -49864,7 +50393,7 @@ op { is_stateful: true } op { - name: "ResourceApplyFtrl" + name: "ResourceApplyFtrlV2" input_arg { name: "var" type: DT_RESOURCE @@ -49893,6 +50422,10 @@ op { name: "l2" type_attr: "T" } + input_arg { + name: "l2_shrinkage" + type_attr: "T" + } input_arg { name: "lr_power" type_attr: "T" @@ -49918,7 +50451,6 @@ op { type: DT_HALF type: DT_UINT32 type: DT_UINT64 - type: DT_BFLOAT16 } } } @@ -49932,7 +50464,7 @@ op { is_stateful: true } op { - name: "ResourceApplyFtrl" + name: "ResourceApplyFtrlV2" input_arg { name: "var" type: DT_RESOURCE @@ -49961,6 +50493,10 @@ op { name: "l2" type_attr: "T" } + input_arg { + name: "l2_shrinkage" + type_attr: "T" + } input_arg { name: "lr_power" type_attr: "T" @@ -49972,21 +50508,21 @@ op { list { type: DT_FLOAT type: DT_DOUBLE + type: DT_INT64 type: DT_INT32 type: DT_UINT8 + type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_INT64 + type: DT_COMPLEX128 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 - type: DT_BFLOAT16 - type: DT_UINT16 - type: DT_COMPLEX128 type: DT_HALF type: DT_UINT32 type: DT_UINT64 + type: DT_BFLOAT16 } } } @@ -50044,18 +50580,21 @@ op { list { type: DT_FLOAT type: DT_DOUBLE - type: DT_INT64 type: DT_INT32 type: DT_UINT8 - type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_COMPLEX128 + type: DT_INT64 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 } } } @@ -50069,41 +50608,62 @@ op { is_stateful: true } op { - name: "ResourceApplyFtrlV2" + name: "ResourceApplyGradientDescent" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "accum" - type: DT_RESOURCE - } - input_arg { - name: "linear" - type: DT_RESOURCE - } - input_arg { - name: "grad" + name: "alpha" type_attr: "T" } input_arg { - name: "lr" + name: "delta" type_attr: "T" } - input_arg { - name: "l1" - type_attr: "T" + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT64 + type: DT_INT32 + type: DT_UINT8 + type: DT_UINT16 + type: DT_INT16 + type: DT_INT8 + type: DT_COMPLEX64 + type: DT_COMPLEX128 + type: DT_QINT8 + type: DT_QUINT8 + type: DT_QINT32 + type: DT_HALF + } + } } + attr { + name: "use_locking" + type: "bool" + default_value { + b: false + } + } + is_stateful: true +} +op { + name: "ResourceApplyGradientDescent" input_arg { - name: "l2" - type_attr: "T" + name: "var" + type: DT_RESOURCE } input_arg { - name: "l2_shrinkage" + name: "alpha" type_attr: "T" } input_arg { - name: "lr_power" + name: "delta" type_attr: "T" } attr { @@ -50140,41 +50700,17 @@ op { is_stateful: true } op { - name: "ResourceApplyFtrlV2" + name: "ResourceApplyGradientDescent" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "accum" - type: DT_RESOURCE - } - input_arg { - name: "linear" - type: DT_RESOURCE - } - input_arg { - name: "grad" - type_attr: "T" - } - input_arg { - name: "lr" - type_attr: "T" - } - input_arg { - name: "l1" - type_attr: "T" - } - input_arg { - name: "l2" - type_attr: "T" - } - input_arg { - name: "l2_shrinkage" + name: "alpha" type_attr: "T" } input_arg { - name: "lr_power" + name: "delta" type_attr: "T" } attr { @@ -50212,41 +50748,17 @@ op { is_stateful: true } op { - name: "ResourceApplyFtrlV2" + name: "ResourceApplyGradientDescent" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "accum" - type: DT_RESOURCE - } - input_arg { - name: "linear" - type: DT_RESOURCE - } - input_arg { - name: "grad" - type_attr: "T" - } - input_arg { - name: "lr" - type_attr: "T" - } - input_arg { - name: "l1" - type_attr: "T" - } - input_arg { - name: "l2" - type_attr: "T" - } - input_arg { - name: "l2_shrinkage" + name: "alpha" type_attr: "T" } input_arg { - name: "lr_power" + name: "delta" type_attr: "T" } attr { @@ -50284,62 +50796,25 @@ op { is_stateful: true } op { - name: "ResourceApplyGradientDescent" + name: "ResourceApplyKerasMomentum" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "alpha" - type_attr: "T" + name: "accum" + type: DT_RESOURCE } input_arg { - name: "delta" + name: "lr" type_attr: "T" } - attr { - name: "T" - type: "type" - allowed_values { - list { - type: DT_FLOAT - type: DT_DOUBLE - type: DT_INT64 - type: DT_INT32 - type: DT_UINT8 - type: DT_UINT16 - type: DT_INT16 - type: DT_INT8 - type: DT_COMPLEX64 - type: DT_COMPLEX128 - type: DT_QINT8 - type: DT_QUINT8 - type: DT_QINT32 - type: DT_HALF - } - } - } - attr { - name: "use_locking" - type: "bool" - default_value { - b: false - } - } - is_stateful: true -} -op { - name: "ResourceApplyGradientDescent" - input_arg { - name: "var" - type: DT_RESOURCE - } input_arg { - name: "alpha" + name: "grad" type_attr: "T" } input_arg { - name: "delta" + name: "momentum" type_attr: "T" } attr { @@ -50349,68 +50824,21 @@ op { list { type: DT_FLOAT type: DT_DOUBLE - type: DT_INT64 type: DT_INT32 type: DT_UINT8 - type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_COMPLEX128 + type: DT_INT64 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 - type: DT_HALF - type: DT_UINT32 - type: DT_UINT64 - } - } - } - attr { - name: "use_locking" - type: "bool" - default_value { - b: false - } - } - is_stateful: true -} -op { - name: "ResourceApplyGradientDescent" - input_arg { - name: "var" - type: DT_RESOURCE - } - input_arg { - name: "alpha" - type_attr: "T" - } - input_arg { - name: "delta" - type_attr: "T" - } - attr { - name: "T" - type: "type" - allowed_values { - list { - type: DT_FLOAT - type: DT_DOUBLE - type: DT_INT64 - type: DT_INT32 - type: DT_UINT8 + type: DT_BFLOAT16 type: DT_UINT16 - type: DT_INT16 - type: DT_INT8 - type: DT_COMPLEX64 type: DT_COMPLEX128 - type: DT_QINT8 - type: DT_QUINT8 - type: DT_QINT32 type: DT_HALF type: DT_UINT32 type: DT_UINT64 - type: DT_BFLOAT16 } } } @@ -50421,49 +50849,8 @@ op { b: false } } - is_stateful: true -} -op { - name: "ResourceApplyGradientDescent" - input_arg { - name: "var" - type: DT_RESOURCE - } - input_arg { - name: "alpha" - type_attr: "T" - } - input_arg { - name: "delta" - type_attr: "T" - } attr { - name: "T" - type: "type" - allowed_values { - list { - type: DT_FLOAT - type: DT_DOUBLE - type: DT_INT32 - type: DT_UINT8 - type: DT_INT16 - type: DT_INT8 - type: DT_COMPLEX64 - type: DT_INT64 - type: DT_QINT8 - type: DT_QUINT8 - type: DT_QINT32 - type: DT_BFLOAT16 - type: DT_UINT16 - type: DT_COMPLEX128 - type: DT_HALF - type: DT_UINT32 - type: DT_UINT64 - } - } - } - attr { - name: "use_locking" + name: "use_nesterov" type: "bool" default_value { b: false @@ -54254,21 +54641,107 @@ op { list { type: DT_FLOAT type: DT_DOUBLE - type: DT_INT64 + type: DT_INT64 + type: DT_INT32 + type: DT_UINT8 + type: DT_UINT16 + type: DT_INT16 + type: DT_INT8 + type: DT_COMPLEX64 + type: DT_COMPLEX128 + type: DT_QINT8 + type: DT_QUINT8 + type: DT_QINT32 + type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 + type: DT_BFLOAT16 + } + } + } + attr { + name: "Tindices" + type: "type" + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } + } + } + attr { + name: "use_locking" + type: "bool" + default_value { + b: false + } + } + is_stateful: true +} +op { + name: "ResourceSparseApplyFtrlV2" + input_arg { + name: "var" + type: DT_RESOURCE + } + input_arg { + name: "accum" + type: DT_RESOURCE + } + input_arg { + name: "linear" + type: DT_RESOURCE + } + input_arg { + name: "grad" + type_attr: "T" + } + input_arg { + name: "indices" + type_attr: "Tindices" + } + input_arg { + name: "lr" + type_attr: "T" + } + input_arg { + name: "l1" + type_attr: "T" + } + input_arg { + name: "l2" + type_attr: "T" + } + input_arg { + name: "l2_shrinkage" + type_attr: "T" + } + input_arg { + name: "lr_power" + type_attr: "T" + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE type: DT_INT32 type: DT_UINT8 - type: DT_UINT16 type: DT_INT16 type: DT_INT8 type: DT_COMPLEX64 - type: DT_COMPLEX128 + type: DT_INT64 type: DT_QINT8 type: DT_QUINT8 type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 type: DT_HALF type: DT_UINT32 type: DT_UINT64 - type: DT_BFLOAT16 } } } @@ -54292,7 +54765,7 @@ op { is_stateful: true } op { - name: "ResourceSparseApplyFtrlV2" + name: "ResourceSparseApplyKerasMomentum" input_arg { name: "var" type: DT_RESOURCE @@ -54302,8 +54775,8 @@ op { type: DT_RESOURCE } input_arg { - name: "linear" - type: DT_RESOURCE + name: "lr" + type_attr: "T" } input_arg { name: "grad" @@ -54314,23 +54787,7 @@ op { type_attr: "Tindices" } input_arg { - name: "lr" - type_attr: "T" - } - input_arg { - name: "l1" - type_attr: "T" - } - input_arg { - name: "l2" - type_attr: "T" - } - input_arg { - name: "l2_shrinkage" - type_attr: "T" - } - input_arg { - name: "lr_power" + name: "momentum" type_attr: "T" } attr { @@ -54375,6 +54832,13 @@ op { b: false } } + attr { + name: "use_nesterov" + type: "bool" + default_value { + b: false + } + } is_stateful: true } op { @@ -57111,52 +57575,6 @@ op { } } } -op { - name: "ScanDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "initial_state" - type_list_attr: "Tstate" - } - input_arg { - name: "other_arguments" - type_list_attr: "Targuments" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "f" - type: "func" - } - attr { - name: "Tstate" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "Targuments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "ScatterAdd" input_arg { @@ -60889,42 +61307,6 @@ op { } } } -op { - name: "SetStatsAggregatorDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "stats_aggregator" - type: DT_RESOURCE - } - input_arg { - name: "tag" - type: DT_STRING - } - input_arg { - name: "counter_prefix" - type: DT_STRING - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} op { name: "Shape" input_arg { @@ -61771,41 +62153,6 @@ op { } } } -op { - name: "SlideDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "window_size" - type: DT_INT64 - } - input_arg { - name: "window_shift" - type: DT_INT64 - } - input_arg { - name: "window_stride" - type: DT_INT64 - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "Snapshot" input_arg { @@ -70964,38 +71311,6 @@ op { } } } -op { - name: "SqlDataset" - input_arg { - name: "driver_name" - type: DT_STRING - } - input_arg { - name: "data_source_name" - type: DT_STRING - } - input_arg { - name: "query" - type: DT_STRING - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} op { name: "Sqrt" input_arg { @@ -71827,6 +72142,53 @@ op { } is_stateful: true } +op { + name: "StatefulPartitionedCall" + input_arg { + name: "args" + type_list_attr: "Tin" + } + output_arg { + name: "output" + type_list_attr: "Tout" + } + attr { + name: "Tin" + type: "list(type)" + has_minimum: true + } + attr { + name: "Tout" + type: "list(type)" + has_minimum: true + } + attr { + name: "f" + type: "func" + } + attr { + name: "config" + type: "string" + default_value { + s: "" + } + } + attr { + name: "config_proto" + type: "string" + default_value { + s: "" + } + } + attr { + name: "executor_type" + type: "string" + default_value { + s: "" + } + } + is_stateful: true +} op { name: "StatelessIf" input_arg { @@ -72509,40 +72871,6 @@ op { } } } -op { - name: "StatsAggregatorHandle" - output_arg { - name: "handle" - type: DT_RESOURCE - } - attr { - name: "container" - type: "string" - default_value { - s: "" - } - } - attr { - name: "shared_name" - type: "string" - default_value { - s: "" - } - } - is_stateful: true -} -op { - name: "StatsAggregatorSummary" - input_arg { - name: "iterator" - type: DT_RESOURCE - } - output_arg { - name: "summary" - type: DT_STRING - } - is_stateful: true -} op { name: "StopGradient" input_arg { @@ -75378,6 +75706,127 @@ op { } is_stateful: true } +op { + name: "TensorForestCreateTreeVariable" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + input_arg { + name: "tree_config" + type: DT_STRING + } + is_stateful: true +} +op { + name: "TensorForestTreeDeserialize" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + input_arg { + name: "tree_config" + type: DT_STRING + } + is_stateful: true +} +op { + name: "TensorForestTreeIsInitializedOp" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + output_arg { + name: "is_initialized" + type: DT_BOOL + } + is_stateful: true +} +op { + name: "TensorForestTreePredict" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + input_arg { + name: "dense_features" + type: DT_FLOAT + } + output_arg { + name: "logits" + type: DT_FLOAT + } + attr { + name: "logits_dimension" + type: "int" + } + is_stateful: true +} +op { + name: "TensorForestTreeResourceHandleOp" + output_arg { + name: "resource" + type: DT_RESOURCE + } + attr { + name: "container" + type: "string" + default_value { + s: "" + } + } + attr { + name: "shared_name" + type: "string" + default_value { + s: "" + } + } + is_stateful: true +} +op { + name: "TensorForestTreeSerialize" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + output_arg { + name: "tree_config" + type: DT_STRING + } + is_stateful: true +} +op { + name: "TensorForestTreeSize" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + output_arg { + name: "tree_size" + type: DT_INT32 + } + is_stateful: true +} +op { + name: "TensorListConcat" + input_arg { + name: "input_handle" + type: DT_VARIANT + } + output_arg { + name: "tensor" + type_attr: "element_dtype" + } + output_arg { + name: "lengths" + type: DT_INT64 + } + attr { + name: "element_dtype" + type: "type" + } +} op { name: "TensorListConcatLists" input_arg { @@ -75448,26 +75897,175 @@ op { } } op { - name: "TensorListGather" - input_arg { - name: "input_handle" - type: DT_VARIANT - } - input_arg { - name: "indices" - type: DT_INT32 - } - output_arg { - name: "values" - type_attr: "element_dtype" - } - attr { - name: "element_dtype" - type: "type" - } -} -op { - name: "TensorListGetItem" + name: "TensorListGather" + input_arg { + name: "input_handle" + type: DT_VARIANT + } + input_arg { + name: "indices" + type: DT_INT32 + } + output_arg { + name: "values" + type_attr: "element_dtype" + } + attr { + name: "element_dtype" + type: "type" + } +} +op { + name: "TensorListGetItem" + input_arg { + name: "input_handle" + type: DT_VARIANT + } + input_arg { + name: "index" + type: DT_INT32 + } + output_arg { + name: "item" + type_attr: "element_dtype" + } + attr { + name: "element_dtype" + type: "type" + } +} +op { + name: "TensorListLength" + input_arg { + name: "input_handle" + type: DT_VARIANT + } + output_arg { + name: "length" + type: DT_INT32 + } +} +op { + name: "TensorListPopBack" + input_arg { + name: "input_handle" + type: DT_VARIANT + } + output_arg { + name: "output_handle" + type: DT_VARIANT + } + output_arg { + name: "tensor" + type_attr: "element_dtype" + } + attr { + name: "element_dtype" + type: "type" + } +} +op { + name: "TensorListPushBack" + input_arg { + name: "input_handle" + type: DT_VARIANT + } + input_arg { + name: "tensor" + type_attr: "element_dtype" + } + output_arg { + name: "output_handle" + type: DT_VARIANT + } + attr { + name: "element_dtype" + type: "type" + } +} +op { + name: "TensorListPushBackBatch" + input_arg { + name: "input_handles" + type: DT_VARIANT + } + input_arg { + name: "tensor" + type_attr: "element_dtype" + } + output_arg { + name: "output_handles" + type: DT_VARIANT + } + attr { + name: "element_dtype" + type: "type" + } +} +op { + name: "TensorListReserve" + input_arg { + name: "element_shape" + type_attr: "shape_type" + } + input_arg { + name: "num_elements" + type: DT_INT32 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "element_dtype" + type: "type" + } + attr { + name: "shape_type" + type: "type" + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } + } + } +} +op { + name: "TensorListScatter" + input_arg { + name: "tensor" + type_attr: "element_dtype" + } + input_arg { + name: "indices" + type: DT_INT32 + } + input_arg { + name: "element_shape" + type_attr: "shape_type" + } + output_arg { + name: "output_handle" + type: DT_VARIANT + } + attr { + name: "element_dtype" + type: "type" + } + attr { + name: "shape_type" + type: "type" + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } + } + } +} +op { + name: "TensorListSetItem" input_arg { name: "input_handle" type: DT_VARIANT @@ -75476,103 +76074,98 @@ op { name: "index" type: DT_INT32 } - output_arg { + input_arg { name: "item" type_attr: "element_dtype" } + output_arg { + name: "output_handle" + type: DT_VARIANT + } attr { name: "element_dtype" type: "type" } } op { - name: "TensorListLength" + name: "TensorListSplit" input_arg { - name: "input_handle" - type: DT_VARIANT + name: "tensor" + type_attr: "element_dtype" } - output_arg { - name: "length" - type: DT_INT32 + input_arg { + name: "element_shape" + type_attr: "shape_type" } -} -op { - name: "TensorListPopBack" input_arg { - name: "input_handle" - type: DT_VARIANT + name: "lengths" + type: DT_INT64 } output_arg { name: "output_handle" type: DT_VARIANT } - output_arg { - name: "tensor" - type_attr: "element_dtype" - } attr { name: "element_dtype" type: "type" } + attr { + name: "shape_type" + type: "type" + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } + } + } } op { - name: "TensorListPushBack" + name: "TensorListStack" input_arg { name: "input_handle" type: DT_VARIANT } - input_arg { + output_arg { name: "tensor" type_attr: "element_dtype" } - output_arg { - name: "output_handle" - type: DT_VARIANT - } attr { name: "element_dtype" type: "type" } + attr { + name: "num_elements" + type: "int" + default_value { + i: -1 + } + } } op { - name: "TensorListPushBackBatch" - input_arg { - name: "input_handles" - type: DT_VARIANT - } + name: "TensorScatterAdd" input_arg { name: "tensor" - type_attr: "element_dtype" - } - output_arg { - name: "output_handles" - type: DT_VARIANT - } - attr { - name: "element_dtype" - type: "type" + type_attr: "T" } -} -op { - name: "TensorListReserve" input_arg { - name: "element_shape" - type_attr: "shape_type" + name: "indices" + type_attr: "Tindices" } input_arg { - name: "num_elements" - type: DT_INT32 + name: "updates" + type_attr: "T" } output_arg { - name: "handle" - type: DT_VARIANT + name: "output" + type_attr: "T" } attr { - name: "element_dtype" + name: "T" type: "type" } attr { - name: "shape_type" + name: "Tindices" type: "type" allowed_values { list { @@ -75583,29 +76176,29 @@ op { } } op { - name: "TensorListScatter" + name: "TensorScatterSub" input_arg { name: "tensor" - type_attr: "element_dtype" + type_attr: "T" } input_arg { name: "indices" - type: DT_INT32 + type_attr: "Tindices" } input_arg { - name: "element_shape" - type_attr: "shape_type" + name: "updates" + type_attr: "T" } output_arg { - name: "output_handle" - type: DT_VARIANT + name: "output" + type_attr: "T" } attr { - name: "element_dtype" + name: "T" type: "type" } attr { - name: "shape_type" + name: "Tindices" type: "type" allowed_values { list { @@ -75616,47 +76209,35 @@ op { } } op { - name: "TensorListSetItem" + name: "TensorScatterUpdate" input_arg { - name: "input_handle" - type: DT_VARIANT + name: "tensor" + type_attr: "T" } input_arg { - name: "index" - type: DT_INT32 + name: "indices" + type_attr: "Tindices" } input_arg { - name: "item" - type_attr: "element_dtype" + name: "updates" + type_attr: "T" } output_arg { - name: "output_handle" - type: DT_VARIANT + name: "output" + type_attr: "T" } attr { - name: "element_dtype" + name: "T" type: "type" } -} -op { - name: "TensorListStack" - input_arg { - name: "input_handle" - type: DT_VARIANT - } - output_arg { - name: "tensor" - type_attr: "element_dtype" - } attr { - name: "element_dtype" + name: "Tindices" type: "type" - } - attr { - name: "num_elements" - type: "int" - default_value { - i: -1 + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } } } } @@ -76810,29 +77391,6 @@ op { type: "type" } } -op { - name: "UnbatchDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "UnbatchGrad" input_arg { @@ -76874,6 +77432,104 @@ op { type: "type" } } +op { + name: "UnicodeDecodeWithOffsets" + input_arg { + name: "input" + type: DT_STRING + } + output_arg { + name: "row_splits" + type: DT_INT64 + } + output_arg { + name: "char_values" + type: DT_INT32 + } + output_arg { + name: "char_to_byte_starts" + type: DT_INT64 + } + attr { + name: "input_encoding" + type: "string" + } + attr { + name: "errors" + type: "string" + default_value { + s: "replace" + } + allowed_values { + list { + s: "strict" + s: "replace" + s: "ignore" + } + } + } + attr { + name: "replacement_char" + type: "int" + default_value { + i: 65533 + } + } + attr { + name: "replace_control_characters" + type: "bool" + default_value { + b: false + } + } +} +op { + name: "UnicodeEncode" + input_arg { + name: "input_values" + type: DT_INT32 + } + input_arg { + name: "input_splits" + type: DT_INT64 + } + output_arg { + name: "output" + type: DT_STRING + } + attr { + name: "errors" + type: "string" + default_value { + s: "replace" + } + allowed_values { + list { + s: "ignore" + s: "replace" + s: "strict" + } + } + } + attr { + name: "output_encoding" + type: "string" + allowed_values { + list { + s: "UTF-8" + s: "UTF-16-BE" + s: "UTF-32-BE" + } + } + } + attr { + name: "replacement_char" + type: "int" + default_value { + i: 65533 + } + } +} op { name: "UnicodeScript" input_arg { diff --git a/tensorflow/core/ops/dataset_ops.cc b/tensorflow/core/ops/dataset_ops.cc index 8402f250f9..b2ea637464 100644 --- a/tensorflow/core/ops/dataset_ops.cc +++ b/tensorflow/core/ops/dataset_ops.cc @@ -83,13 +83,6 @@ REGISTER_OP("GeneratorDataset") // stateful to inhibit constant folding. .SetShapeFn(shape_inference::ScalarShape); -REGISTER_OP("UnbatchDataset") - .Input("input_dataset: variant") - .Output("handle: variant") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn(shape_inference::ScalarShape); - REGISTER_OP("ZipDataset") .Input("input_datasets: N * variant") .Output("handle: variant") @@ -142,57 +135,6 @@ REGISTER_OP("SkipDataset") return shape_inference::ScalarShape(c); }); -REGISTER_OP("BytesProducedStatsDataset") - .Input("input_dataset: variant") - .Input("tag: string") - .Output("handle: variant") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn([](shape_inference::InferenceContext* c) { - shape_inference::ShapeHandle tag_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &tag_shape)); - return shape_inference::ScalarShape(c); - }); - -REGISTER_OP("LatencyStatsDataset") - .Input("input_dataset: variant") - .Input("tag: string") - .Output("handle: variant") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn([](shape_inference::InferenceContext* c) { - shape_inference::ShapeHandle tag_shape; - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &tag_shape)); - return shape_inference::ScalarShape(c); - }); - -REGISTER_OP("ParseExampleDataset") - .Input("input_dataset: variant") - .Input("num_parallel_calls: int64") - .Input("dense_defaults: Tdense") - .Output("handle: variant") - .Attr("sparse_keys: list(string) >= 0") - .Attr("dense_keys: list(string) >= 0") - .Attr("sparse_types: list({float,int64,string}) >= 0") - .Attr("Tdense: list({float,int64,string}) >= 0") - .Attr("dense_shapes: list(shape) >= 0") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") // Output components will be - // sorted by key (dense_keys and - // sparse_keys combined) here. - .Attr("sloppy: bool = false") - .SetShapeFn(shape_inference::ScalarShape); - -REGISTER_OP("SetStatsAggregatorDataset") - .Input("input_dataset: variant") - .Input("stats_aggregator: resource") - .Input("tag: string") - .Input("counter_prefix: string") - .Output("handle: variant") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn(shape_inference::ScalarShape); - REGISTER_OP("MapDataset") .Input("input_dataset: variant") .Input("other_arguments: Targuments") @@ -217,58 +159,6 @@ REGISTER_OP("ParallelMapDataset") .Attr("sloppy: bool = false") .SetShapeFn(shape_inference::ScalarShape); -REGISTER_OP("MapAndBatchDataset") - .Input("input_dataset: variant") - .Input("other_arguments: Targuments") - .Input("batch_size: int64") - .Input("num_parallel_batches: int64") - .Input("drop_remainder: bool") - .Output("handle: variant") - .Attr("f: func") - .Attr("Targuments: list(type) >= 0") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn([](shape_inference::InferenceContext* c) { - // Use index from the end to retrieve the Input shapes, - // so that to avoid guessing the length of "other_arguments". - // batch_size, num_parallel_batches, and drop_remainder are 0-D scalars. - shape_inference::ShapeHandle unused; - TF_RETURN_IF_ERROR( - c->WithRank(c->input(c->num_inputs() - 3), 0, &unused)); - TF_RETURN_IF_ERROR( - c->WithRank(c->input(c->num_inputs() - 2), 0, &unused)); - TF_RETURN_IF_ERROR( - c->WithRank(c->input(c->num_inputs() - 1), 0, &unused)); - - return shape_inference::ScalarShape(c); - }); - -REGISTER_OP("MapAndBatchDatasetV2") - .Input("input_dataset: variant") - .Input("other_arguments: Targuments") - .Input("batch_size: int64") - .Input("num_parallel_calls: int64") - .Input("drop_remainder: bool") - .Output("handle: variant") - .Attr("f: func") - .Attr("Targuments: list(type) >= 0") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn([](shape_inference::InferenceContext* c) { - // Use index from the end to retrieve the Input shapes, - // so that to avoid guessing the length of "other_arguments". - // batch_size, num_parallel_calls, and drop_remainder are 0-D scalars. - shape_inference::ShapeHandle unused; - TF_RETURN_IF_ERROR( - c->WithRank(c->input(c->num_inputs() - 3), 0, &unused)); - TF_RETURN_IF_ERROR( - c->WithRank(c->input(c->num_inputs() - 2), 0, &unused)); - TF_RETURN_IF_ERROR( - c->WithRank(c->input(c->num_inputs() - 1), 0, &unused)); - - return shape_inference::ScalarShape(c); - }); - REGISTER_OP("PrefetchDataset") .Input("input_dataset: variant") .Input("buffer_size: int64") @@ -282,18 +172,6 @@ REGISTER_OP("PrefetchDataset") return shape_inference::ScalarShape(c); }); -REGISTER_OP("ScanDataset") - .Input("input_dataset: variant") - .Input("initial_state: Tstate") - .Input("other_arguments: Targuments") - .Output("handle: variant") - .Attr("f: func") - .Attr("Tstate: list(type) >= 1") - .Attr("Targuments: list(type) >= 0") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn(shape_inference::ScalarShape); - REGISTER_OP("FlatMapDataset") .Input("input_dataset: variant") .Input("other_arguments: Targuments") @@ -316,21 +194,6 @@ REGISTER_OP("InterleaveDataset") .Attr("output_shapes: list(shape) >= 1") .SetShapeFn(shape_inference::ScalarShape); -REGISTER_OP("ParallelInterleaveDataset") - .Input("input_dataset: variant") - .Input("other_arguments: Targuments") - .Input("cycle_length: int64") - .Input("block_length: int64") - .Input("sloppy: bool") - .Input("buffer_output_elements: int64") - .Input("prefetch_input_elements: int64") - .Output("handle: variant") - .Attr("f: func") - .Attr("Targuments: list(type) >= 0") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn(shape_inference::ScalarShape); - REGISTER_OP("ParallelInterleaveDatasetV2") .Input("input_dataset: variant") .Input("other_arguments: Targuments") @@ -345,43 +208,6 @@ REGISTER_OP("ParallelInterleaveDatasetV2") .Attr("sloppy: bool = false") .SetShapeFn(shape_inference::ScalarShape); -REGISTER_OP("GroupByReducerDataset") - .Input("input_dataset: variant") - .Input("key_func_other_arguments: Tkey_func_other_arguments") - .Input("init_func_other_arguments: Tinit_func_other_arguments") - .Input("reduce_func_other_arguments: Treduce_func_other_arguments") - .Input("finalize_func_other_arguments: Tfinalize_func_other_arguments") - .Output("handle: variant") - .Attr("key_func: func") - .Attr("init_func: func") - .Attr("reduce_func: func") - .Attr("finalize_func: func") - .Attr("Tkey_func_other_arguments: list(type) >= 0") - .Attr("Tinit_func_other_arguments: list(type) >= 0") - .Attr("Treduce_func_other_arguments: list(type) >= 0") - .Attr("Tfinalize_func_other_arguments: list(type) >= 0") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetIsStateful() - .SetShapeFn(shape_inference::ScalarShape); - -REGISTER_OP("GroupByWindowDataset") - .Input("input_dataset: variant") - .Input("key_func_other_arguments: Tkey_func_other_arguments") - .Input("reduce_func_other_arguments: Treduce_func_other_arguments") - .Input( - "window_size_func_other_arguments: Twindow_size_func_other_arguments") - .Output("handle: variant") - .Attr("key_func: func") - .Attr("reduce_func: func") - .Attr("window_size_func: func") - .Attr("Tkey_func_other_arguments: list(type) >= 0") - .Attr("Treduce_func_other_arguments: list(type) >= 0") - .Attr("Twindow_size_func_other_arguments: list(type) >= 0") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn(shape_inference::ScalarShape); - REGISTER_OP("FilterDataset") .Input("input_dataset: variant") .Input("other_arguments: Targuments") @@ -447,23 +273,6 @@ REGISTER_OP("BatchDatasetV2") return shape_inference::ScalarShape(c); }); -REGISTER_OP("SlideDataset") - .Input("input_dataset: variant") - .Input("window_size: int64") - .Input("window_shift: int64") - .Input("window_stride: int64") - .Output("handle: variant") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn([](shape_inference::InferenceContext* c) { - shape_inference::ShapeHandle unused; - // window_size, window_shift, and window_stride should be scalars. - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); - TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 0, &unused)); - TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 0, &unused)); - return shape_inference::ScalarShape(c); - }); - // TODO(mrry): Validate that `padded_shapes` are all vectors, the lengths of // `output_types` and `output_shapes` are `N` the `output_shapes` are (as far as // possible to tell statically) compatible with `padded_shapes`, and that @@ -504,22 +313,6 @@ REGISTER_OP("PaddedBatchDatasetV2") return shape_inference::ScalarShape(c); }); -REGISTER_OP("DenseToSparseBatchDataset") - .Input("input_dataset: variant") - .Input("batch_size: int64") - .Input("row_shape: int64") - .Output("handle: variant") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetShapeFn([](shape_inference::InferenceContext* c) { - shape_inference::ShapeHandle unused; - // batch_size should be a scalar. - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); - // row_shape should be a 1-D vector. - TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 1, &unused)); - return shape_inference::ScalarShape(c); - }); - REGISTER_OP("RangeDataset") .Input("start: int64") .Input("stop: int64") @@ -538,22 +331,6 @@ REGISTER_OP("RangeDataset") return shape_inference::ScalarShape(c); }); -REGISTER_OP("RandomDataset") - .Input("seed: int64") - .Input("seed2: int64") - .Output("handle: variant") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetIsStateful() // TODO(b/65524810): Source dataset ops must be marked - // stateful to inhibit constant folding. - .SetShapeFn([](shape_inference::InferenceContext* c) { - shape_inference::ShapeHandle unused; - // buffer_size, seed, and seed2 should be scalars. - TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 0, &unused)); - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); - return shape_inference::ScalarShape(c); - }); - REGISTER_OP("ShuffleDataset") .Input("input_dataset: variant") .Input("buffer_size: int64") @@ -622,36 +399,6 @@ REGISTER_OP("TextLineDataset") return shape_inference::ScalarShape(c); }); -REGISTER_OP("MatchingFilesDataset") - .Input("patterns: string") - .Output("handle: variant") - .SetIsStateful() // TODO(b/65524810): Source dataset ops must be marked - // stateful to inhibit constant folding. - .SetShapeFn([](shape_inference::InferenceContext* c) { - shape_inference::ShapeHandle unused; - // `patterns` must be a scalar or a vector. - TF_RETURN_IF_ERROR(c->WithRankAtMost(c->input(0), 1, &unused)); - return shape_inference::ScalarShape(c); - }); - -REGISTER_OP("SqlDataset") - .Input("driver_name: string") - .Input("data_source_name: string") - .Input("query: string") - .Output("handle: variant") - .Attr("output_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .SetIsStateful() // TODO(b/65524810): Source dataset ops must be marked - // stateful to inhibit constant folding. - .SetShapeFn([](shape_inference::InferenceContext* c) { - shape_inference::ShapeHandle unused; - // driver_name, data_source_name, and query should be scalars. - TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 0, &unused)); - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); - TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 0, &unused)); - return shape_inference::ScalarShape(c); - }); - REGISTER_OP("FixedLengthRecordDataset") .Input("filenames: string") .Input("header_bytes: int64") @@ -838,53 +585,6 @@ REGISTER_OP("DeserializeIterator") .Input("serialized: variant") .SetShapeFn(shape_inference::NoOutputs); -REGISTER_OP("StatsAggregatorHandle") - .Output("handle: resource") - .SetShapeFn(shape_inference::ScalarShape) - .Attr("container: string = ''") - .Attr("shared_name: string = ''"); - -REGISTER_OP("StatsAggregatorSummary") - .Input("iterator: resource") - .Output("summary: string") - .SetShapeFn(shape_inference::ScalarShape); - -REGISTER_OP("PrependFromQueueAndPaddedBatchDataset") - .Input("input_dataset: variant") - .Input("batch_size: int64") - .Input("padded_shapes: N * int64") - .Input("padding_values: Toutput_types") - .Output("handle: variant") - .Attr("Toutput_types: list(type) >= 1") - .Attr("output_shapes: list(shape) >= 1") - .Attr("N: int >= 1") - // TODO(ebrevdo): Validate that `padded_shapes` are all vectors, the lengths - // of `Toutput_types` and `output_shapes` are `N`, that the - // length of `output_types` is `N`, the `output_shapes` are - // (as far as possible to tell statically) compatible with `padded_shapes`, - // and that `padding_values` are all scalars. - .SetShapeFn([](shape_inference::InferenceContext* c) { - shape_inference::ShapeHandle unused; - // batch_size should be a scalar. - TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); - return shape_inference::ScalarShape(c); - }); - -REGISTER_OP("EnqueueInQueueDataset") - .Input("queue: variant") - .Input("components: Tcomponents") - .Attr("Tcomponents: list(type) >= 1") - .SetIsStateful() // To avoid CSE on multiple calls to Enqueue. - // TODO(ebrevdo): SetShapeFn to test input dtypes and shapes by - // reading from queue handle (is that even possible?). - .SetShapeFn(shape_inference::NoOutputs); - -REGISTER_OP("DatasetToTFRecord") - .Input("input_dataset: variant") - .Input("filename: string") - .Input("compression_type: string") - .SetShapeFn(shape_inference::NoOutputs); - REGISTER_OP("DatasetToGraph") .Input("input_dataset: variant") .Output("graph: string") diff --git a/tensorflow/core/ops/experimental_dataset_ops.cc b/tensorflow/core/ops/experimental_dataset_ops.cc index 9733cf2776..0711034118 100644 --- a/tensorflow/core/ops/experimental_dataset_ops.cc +++ b/tensorflow/core/ops/experimental_dataset_ops.cc @@ -17,14 +17,17 @@ limitations under the License. namespace tensorflow { -REGISTER_OP("ExperimentalDirectedInterleaveDataset") - .Input("selector_input_dataset: variant") - .Input("data_input_datasets: N * variant") +REGISTER_OP("ExperimentalBytesProducedStatsDataset") + .Input("input_dataset: variant") + .Input("tag: string") .Output("handle: variant") .Attr("output_types: list(type) >= 1") .Attr("output_shapes: list(shape) >= 1") - .Attr("N: int >= 1") - .SetShapeFn(shape_inference::ScalarShape); + .SetShapeFn([](shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle tag_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &tag_shape)); + return shape_inference::ScalarShape(c); + }); REGISTER_OP("ExperimentalCSVDataset") .Input("filenames: string") @@ -68,6 +71,79 @@ REGISTER_OP("ExperimentalCSVDataset") return shape_inference::ScalarShape(c); }); +REGISTER_OP("ExperimentalDatasetCardinality") + .Input("input_dataset: variant") + .Output("cardinality: int64") + .SetShapeFn(shape_inference::ScalarShape); + +REGISTER_OP("ExperimentalDatasetToTFRecord") + .Input("input_dataset: variant") + .Input("filename: string") + .Input("compression_type: string") + .SetShapeFn(shape_inference::NoOutputs); + +REGISTER_OP("ExperimentalDenseToSparseBatchDataset") + .Input("input_dataset: variant") + .Input("batch_size: int64") + .Input("row_shape: int64") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn([](shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle unused; + // batch_size should be a scalar. + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); + // row_shape should be a 1-D vector. + TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 1, &unused)); + return shape_inference::ScalarShape(c); + }); + +REGISTER_OP("ExperimentalDirectedInterleaveDataset") + .Input("selector_input_dataset: variant") + .Input("data_input_datasets: N * variant") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .Attr("N: int >= 1") + .SetShapeFn(shape_inference::ScalarShape); + +REGISTER_OP("ExperimentalGroupByReducerDataset") + .Input("input_dataset: variant") + .Input("key_func_other_arguments: Tkey_func_other_arguments") + .Input("init_func_other_arguments: Tinit_func_other_arguments") + .Input("reduce_func_other_arguments: Treduce_func_other_arguments") + .Input("finalize_func_other_arguments: Tfinalize_func_other_arguments") + .Output("handle: variant") + .Attr("key_func: func") + .Attr("init_func: func") + .Attr("reduce_func: func") + .Attr("finalize_func: func") + .Attr("Tkey_func_other_arguments: list(type) >= 0") + .Attr("Tinit_func_other_arguments: list(type) >= 0") + .Attr("Treduce_func_other_arguments: list(type) >= 0") + .Attr("Tfinalize_func_other_arguments: list(type) >= 0") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetIsStateful() + .SetShapeFn(shape_inference::ScalarShape); + +REGISTER_OP("ExperimentalGroupByWindowDataset") + .Input("input_dataset: variant") + .Input("key_func_other_arguments: Tkey_func_other_arguments") + .Input("reduce_func_other_arguments: Treduce_func_other_arguments") + .Input( + "window_size_func_other_arguments: Twindow_size_func_other_arguments") + .Output("handle: variant") + .Attr("key_func: func") + .Attr("reduce_func: func") + .Attr("window_size_func: func") + .Attr("Tkey_func_other_arguments: list(type) >= 0") + .Attr("Treduce_func_other_arguments: list(type) >= 0") + .Attr("Twindow_size_func_other_arguments: list(type) >= 0") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn(shape_inference::ScalarShape); + REGISTER_OP("ExperimentalIgnoreErrorsDataset") .Input("input_dataset: variant") .Output("handle: variant") @@ -75,6 +151,44 @@ REGISTER_OP("ExperimentalIgnoreErrorsDataset") .Attr("output_shapes: list(shape) >= 1") .SetShapeFn(shape_inference::ScalarShape); +REGISTER_OP("ExperimentalLatencyStatsDataset") + .Input("input_dataset: variant") + .Input("tag: string") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn([](shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle tag_shape; + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &tag_shape)); + return shape_inference::ScalarShape(c); + }); + +REGISTER_OP("ExperimentalMapAndBatchDataset") + .Input("input_dataset: variant") + .Input("other_arguments: Targuments") + .Input("batch_size: int64") + .Input("num_parallel_calls: int64") + .Input("drop_remainder: bool") + .Output("handle: variant") + .Attr("f: func") + .Attr("Targuments: list(type) >= 0") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn([](shape_inference::InferenceContext* c) { + // Use index from the end to retrieve the Input shapes, + // so that to avoid guessing the length of "other_arguments". + // batch_size, num_parallel_calls, and drop_remainder are 0-D scalars. + shape_inference::ShapeHandle unused; + TF_RETURN_IF_ERROR( + c->WithRank(c->input(c->num_inputs() - 3), 0, &unused)); + TF_RETURN_IF_ERROR( + c->WithRank(c->input(c->num_inputs() - 2), 0, &unused)); + TF_RETURN_IF_ERROR( + c->WithRank(c->input(c->num_inputs() - 1), 0, &unused)); + + return shape_inference::ScalarShape(c); + }); + REGISTER_OP("ExperimentalMapDataset") .Input("input_dataset: variant") .Input("other_arguments: Targuments") @@ -86,6 +200,18 @@ REGISTER_OP("ExperimentalMapDataset") .Attr("use_inter_op_parallelism: bool = true") .SetShapeFn(shape_inference::ScalarShape); +REGISTER_OP("ExperimentalMatchingFilesDataset") + .Input("patterns: string") + .Output("handle: variant") + .SetIsStateful() // TODO(b/65524810): Source dataset ops must be marked + // stateful to inhibit constant folding. + .SetShapeFn([](shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle unused; + // `patterns` must be a scalar or a vector. + TF_RETURN_IF_ERROR(c->WithRankAtMost(c->input(0), 1, &unused)); + return shape_inference::ScalarShape(c); + }); + REGISTER_OP("ExperimentalNonSerializableDataset") .Input("input_dataset: variant") .Output("handle: variant") @@ -93,6 +219,76 @@ REGISTER_OP("ExperimentalNonSerializableDataset") .Attr("output_shapes: list(shape) >= 1") .SetShapeFn(shape_inference::ScalarShape); +REGISTER_OP("ExperimentalParallelInterleaveDataset") + .Input("input_dataset: variant") + .Input("other_arguments: Targuments") + .Input("cycle_length: int64") + .Input("block_length: int64") + .Input("sloppy: bool") + .Input("buffer_output_elements: int64") + .Input("prefetch_input_elements: int64") + .Output("handle: variant") + .Attr("f: func") + .Attr("Targuments: list(type) >= 0") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn(shape_inference::ScalarShape); + +REGISTER_OP("ExperimentalParseExampleDataset") + .Input("input_dataset: variant") + .Input("num_parallel_calls: int64") + .Input("dense_defaults: Tdense") + .Output("handle: variant") + .Attr("sparse_keys: list(string) >= 0") + .Attr("dense_keys: list(string) >= 0") + .Attr("sparse_types: list({float,int64,string}) >= 0") + .Attr("Tdense: list({float,int64,string}) >= 0") + .Attr("dense_shapes: list(shape) >= 0") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") // Output components will be + // sorted by key (dense_keys and + // sparse_keys combined) here. + .Attr("sloppy: bool = false") + .SetShapeFn(shape_inference::ScalarShape); + +REGISTER_OP("ExperimentalRandomDataset") + .Input("seed: int64") + .Input("seed2: int64") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetIsStateful() // TODO(b/65524810): Source dataset ops must be marked + // stateful to inhibit constant folding. + .SetShapeFn([](shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle unused; + // buffer_size, seed, and seed2 should be scalars. + TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 0, &unused)); + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); + return shape_inference::ScalarShape(c); + }); + +REGISTER_OP("ExperimentalScanDataset") + .Input("input_dataset: variant") + .Input("initial_state: Tstate") + .Input("other_arguments: Targuments") + .Output("handle: variant") + .Attr("f: func") + .Attr("Tstate: list(type) >= 1") + .Attr("Targuments: list(type) >= 0") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn(shape_inference::ScalarShape); + +REGISTER_OP("ExperimentalSetStatsAggregatorDataset") + .Input("input_dataset: variant") + .Input("stats_aggregator: resource") + .Input("tag: string") + .Input("counter_prefix: string") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn(shape_inference::ScalarShape); + REGISTER_OP("ExperimentalSleepDataset") .Input("input_dataset: variant") .Input("sleep_microseconds: int64") @@ -107,6 +303,59 @@ REGISTER_OP("ExperimentalSleepDataset") return shape_inference::ScalarShape(c); }); +REGISTER_OP("ExperimentalSlidingWindowDataset") + .Input("input_dataset: variant") + .Input("window_size: int64") + .Input("window_shift: int64") + .Input("window_stride: int64") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn([](shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle unused; + // window_size, window_shift, and window_stride should be scalars. + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); + TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 0, &unused)); + TF_RETURN_IF_ERROR(c->WithRank(c->input(3), 0, &unused)); + return shape_inference::ScalarShape(c); + }); + +REGISTER_OP("ExperimentalSqlDataset") + .Input("driver_name: string") + .Input("data_source_name: string") + .Input("query: string") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetIsStateful() // TODO(b/65524810): Source dataset ops must be marked + // stateful to inhibit constant folding. + .SetShapeFn([](shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle unused; + // driver_name, data_source_name, and query should be scalars. + TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 0, &unused)); + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 0, &unused)); + TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 0, &unused)); + return shape_inference::ScalarShape(c); + }); + +REGISTER_OP("ExperimentalStatsAggregatorHandle") + .Output("handle: resource") + .SetShapeFn(shape_inference::ScalarShape) + .Attr("container: string = ''") + .Attr("shared_name: string = ''"); + +REGISTER_OP("ExperimentalStatsAggregatorSummary") + .Input("iterator: resource") + .Output("summary: string") + .SetShapeFn(shape_inference::ScalarShape); + +REGISTER_OP("ExperimentalUnbatchDataset") + .Input("input_dataset: variant") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn(shape_inference::ScalarShape); + REGISTER_OP("ExperimentalUniqueDataset") .Input("input_dataset: variant") .Output("handle: variant") @@ -119,26 +368,21 @@ REGISTER_OP("ExperimentalIteratorGetDevice") .Output("device: string") .SetShapeFn(shape_inference::ScalarShape); -REGISTER_OP("ExperimentalFunctionBufferingResource") - .Input("string_arg: string") - .Input("target_device: string") - .Output("resource: resource") - .Attr("shared_name: string") - .Attr("container: string") - .Attr("f: func") - .Attr("buffer_size: int") - .Attr("output_types: list(type)") - .SetShapeFn(shape_inference::UnknownShape); - -REGISTER_OP("ExperimentalFunctionBufferingResourceGetNext") - .Input("function_buffer_resource: resource") - .Attr("output_types: list(type)") - .Output("output: output_types") - .SetShapeFn(shape_inference::UnknownShape); - -REGISTER_OP("ExperimentalFunctionBufferingResourceReset") - .Input("function_buffer_resource: resource") - .SetShapeFn(shape_inference::UnknownShape); +REGISTER_OP("ExperimentalMaxIntraOpParallelismDataset") + .Input("input_dataset: variant") + .Input("max_intra_op_parallelism: int64") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn(shape_inference::ScalarShape); + +REGISTER_OP("ExperimentalPrivateThreadPoolDataset") + .Input("input_dataset: variant") + .Input("num_threads: int64") + .Output("handle: variant") + .Attr("output_types: list(type) >= 1") + .Attr("output_shapes: list(shape) >= 1") + .SetShapeFn(shape_inference::ScalarShape); REGISTER_OP("ExperimentalThreadPoolDataset") .Input("input_dataset: variant") diff --git a/tensorflow/core/ops/functional_ops.cc b/tensorflow/core/ops/functional_ops.cc index ee14a851eb..5e0bdd888c 100644 --- a/tensorflow/core/ops/functional_ops.cc +++ b/tensorflow/core/ops/functional_ops.cc @@ -226,6 +226,7 @@ REGISTER_OP("PartitionedCall") .Attr("Tout: list(type) >= 0") .Attr("f: func") .Attr("config: string = ''") + .Attr("config_proto: string = ''") .Attr("executor_type: string = ''") .SetShapeFn(shape_inference::UnknownShape); @@ -235,7 +236,8 @@ REGISTER_OP("StatefulPartitionedCall") .Attr("Tin: list(type) >= 0") .Attr("Tout: list(type) >= 0") .Attr("f: func") - .Attr("config: string = ''") + .Attr("config: string = ''") // Deprecated in favor of config_proto + .Attr("config_proto: string = ''") .Attr("executor_type: string = ''") .SetIsStateful() .SetShapeFn(shape_inference::UnknownShape); diff --git a/tensorflow/core/ops/list_ops.cc b/tensorflow/core/ops/list_ops.cc index 88d6d14c30..01ebcd1543 100644 --- a/tensorflow/core/ops/list_ops.cc +++ b/tensorflow/core/ops/list_ops.cc @@ -28,13 +28,14 @@ REGISTER_OP("EmptyTensorList") .Attr("shape_type: {int32, int64}") .SetShapeFn([](shape_inference::InferenceContext* c) { c->set_output(0, c->Scalar()); - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); - shape_inference::ShapeHandle s; - TF_RETURN_IF_ERROR( - c->MakeShapeFromShapeTensorTreatScalarAsUnknownShape(0, &s)); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); + shape_inference::ShapeHandle element_shape; + TF_RETURN_IF_ERROR(c->MakeShapeFromShapeTensorTreatScalarAsUnknownShape( + 0, &element_shape)); c->set_output_handle_shapes_and_types( - 0, std::vector{{s, t}}); + 0, std::vector{ + {element_shape, element_dtype}}); return Status::OK(); }); @@ -45,9 +46,9 @@ REGISTER_OP("TensorListPushBack") .Attr("element_dtype: type") .SetShapeFn([](shape_inference::InferenceContext* c) { c->set_output(0, c->Scalar()); - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); - shape_inference::ShapeHandle s = c->UnknownShape(); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); + shape_inference::ShapeHandle element_shape = c->UnknownShape(); auto* handle_data = c->input_handle_shapes_and_types(0); if (handle_data != nullptr && handle_data->size() != 1) { @@ -57,18 +58,21 @@ REGISTER_OP("TensorListPushBack") if (handle_data != nullptr) { const shape_inference::ShapeAndType& list_shape_type = (*handle_data)[0]; - if (list_shape_type.dtype != t) { + if (list_shape_type.dtype != element_dtype) { return errors::InvalidArgument( "Trying to push to list with wrong element dtype. List has type ", DataTypeString(list_shape_type.dtype), - " but trying to push element with type ", DataTypeString(t)); + " but trying to push element with type ", + DataTypeString(element_dtype)); } shape_inference::ShapeHandle ignored; - TF_RETURN_IF_ERROR(c->Merge(s, list_shape_type.shape, &ignored)); - s = list_shape_type.shape; + TF_RETURN_IF_ERROR( + c->Merge(element_shape, list_shape_type.shape, &ignored)); + element_shape = list_shape_type.shape; } c->set_output_handle_shapes_and_types( - 0, std::vector{{s, t}}); + 0, std::vector{ + {element_shape, element_dtype}}); return Status::OK(); }); @@ -89,9 +93,9 @@ REGISTER_OP("TensorListPushBackBatch") c->set_output(0, input_handles); - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); - shape_inference::ShapeHandle s = c->UnknownShape(); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); + shape_inference::ShapeHandle element_shape = c->UnknownShape(); auto* handle_data = c->input_handle_shapes_and_types(0); if (handle_data != nullptr && handle_data->size() != 1) { @@ -101,18 +105,21 @@ REGISTER_OP("TensorListPushBackBatch") if (handle_data != nullptr) { const shape_inference::ShapeAndType& list_shape_type = (*handle_data)[0]; - if (list_shape_type.dtype != t) { + if (list_shape_type.dtype != element_dtype) { return errors::InvalidArgument( "Trying to push to list with wrong element dtype. List has type ", DataTypeString(list_shape_type.dtype), - " but trying to push element with type ", DataTypeString(t)); + " but trying to push element with type ", + DataTypeString(element_dtype)); } shape_inference::ShapeHandle ignored; - TF_RETURN_IF_ERROR(c->Merge(s, list_shape_type.shape, &ignored)); - s = list_shape_type.shape; + TF_RETURN_IF_ERROR( + c->Merge(element_shape, list_shape_type.shape, &ignored)); + element_shape = list_shape_type.shape; } c->set_output_handle_shapes_and_types( - 0, std::vector{{s, t}}); + 0, std::vector{ + {element_shape, element_dtype}}); return Status::OK(); }); @@ -127,9 +134,9 @@ REGISTER_OP("TensorListPopBack") .Output("tensor: element_dtype") .Attr("element_dtype: type") .SetShapeFn([](shape_inference::InferenceContext* c) { - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); - shape_inference::ShapeHandle s = c->UnknownShape(); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); + shape_inference::ShapeHandle tensor_shape = c->UnknownShape(); auto* handle_data = c->input_handle_shapes_and_types(0); if (handle_data != nullptr && handle_data->size() != 1) { return errors::InvalidArgument( @@ -138,19 +145,21 @@ REGISTER_OP("TensorListPopBack") if (handle_data != nullptr) { const shape_inference::ShapeAndType& list_shape_type = (*handle_data)[0]; - if (list_shape_type.dtype != t) { + if (list_shape_type.dtype != element_dtype) { return errors::InvalidArgument( "Trying to read from list with wrong element dtype. List has " "type ", DataTypeString(list_shape_type.dtype), - " but trying to push element with type ", DataTypeString(t)); + " but trying to push element with type ", + DataTypeString(element_dtype)); } shape_inference::ShapeHandle ignored; - TF_RETURN_IF_ERROR(c->Merge(s, list_shape_type.shape, &ignored)); + TF_RETURN_IF_ERROR( + c->Merge(tensor_shape, list_shape_type.shape, &ignored)); c->set_output_handle_shapes_and_types(0, *handle_data); - s = list_shape_type.shape; + tensor_shape = list_shape_type.shape; } - c->set_output(1, s); + c->set_output(1, tensor_shape); c->set_output(0, c->Scalar()); return Status::OK(); }); @@ -161,9 +170,9 @@ REGISTER_OP("TensorListStack") .Attr("element_dtype: type") .Attr("num_elements: int = -1") .SetShapeFn([](shape_inference::InferenceContext* c) { - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); - shape_inference::ShapeHandle s = c->UnknownShape(); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); + shape_inference::ShapeHandle element_shape = c->UnknownShape(); auto* handle_data = c->input_handle_shapes_and_types(0); if (handle_data != nullptr && handle_data->size() != 1) { return errors::InvalidArgument( @@ -172,16 +181,17 @@ REGISTER_OP("TensorListStack") if (handle_data != nullptr) { const shape_inference::ShapeAndType& list_shape_type = (*handle_data)[0]; - if (list_shape_type.dtype != t) { + if (list_shape_type.dtype != element_dtype) { return errors::InvalidArgument( "Trying to read from list with wrong element dtype. List has " "type ", DataTypeString(list_shape_type.dtype), " but expectec type ", - DataTypeString(t)); + DataTypeString(element_dtype)); } shape_inference::ShapeHandle ignored; - TF_RETURN_IF_ERROR(c->Merge(s, list_shape_type.shape, &ignored)); - s = list_shape_type.shape; + TF_RETURN_IF_ERROR( + c->Merge(element_shape, list_shape_type.shape, &ignored)); + element_shape = list_shape_type.shape; } int expected_num_elements = -1; TF_RETURN_IF_ERROR(c->GetAttr("num_elements", &expected_num_elements)); @@ -192,11 +202,88 @@ REGISTER_OP("TensorListStack") num_elements = c->MakeShape({expected_num_elements}); } shape_inference::ShapeHandle result; - TF_RETURN_IF_ERROR(c->Concatenate(num_elements, s, &result)); + TF_RETURN_IF_ERROR(c->Concatenate(num_elements, element_shape, &result)); c->set_output(0, result); return Status::OK(); }); +REGISTER_OP("TensorListConcat") + .Input("input_handle: variant") + .Output("tensor: element_dtype") + .Output("lengths: int64") + .Attr("element_dtype: type") + .SetShapeFn([](shape_inference::InferenceContext* c) { + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); + shape_inference::ShapeHandle element_shape = c->UnknownShape(); + auto* handle_data = c->input_handle_shapes_and_types(0); + if (handle_data != nullptr && handle_data->size() != 1) { + return errors::InvalidArgument( + "Trying to read from list with wrong variant data."); + } + if (handle_data != nullptr) { + const shape_inference::ShapeAndType& list_shape_type = + (*handle_data)[0]; + if (list_shape_type.dtype != element_dtype) { + return errors::InvalidArgument( + "Trying to read from list with wrong element dtype. List has " + "type ", + DataTypeString(list_shape_type.dtype), " but expected type ", + DataTypeString(element_dtype)); + } + shape_inference::ShapeHandle ignored; + TF_RETURN_IF_ERROR( + c->Merge(element_shape, list_shape_type.shape, &ignored)); + element_shape = list_shape_type.shape; + } + if (c->RankKnown(element_shape)) { + shape_inference::ShapeHandle result; + TF_RETURN_IF_ERROR(c->Subshape(element_shape, 1, &result)); + TF_RETURN_IF_ERROR( + c->Concatenate(c->MakeShape({c->UnknownDim()}), result, &result)); + c->set_output(0, result); + } else { + c->set_output(0, c->UnknownShape()); + } + c->set_output(1, c->MakeShape({c->UnknownDim()})); + return Status::OK(); + }); + +REGISTER_OP("TensorListSplit") + .Input("tensor: element_dtype") + .Input("element_shape: shape_type") + .Input("lengths: int64") + .Output("output_handle: variant") + .Attr("element_dtype: type") + .Attr("shape_type: {int32, int64}") + .SetShapeFn([](shape_inference::InferenceContext* c) { + c->set_output(0, c->Scalar()); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); + shape_inference::ShapeHandle tensor_shape = c->input(0); + shape_inference::ShapeHandle ignored; + // Check that tensor is at least a vector. + TF_RETURN_IF_ERROR(c->WithRankAtLeast(tensor_shape, 1, &ignored)); + // Check that lengths is a vector. + TF_RETURN_IF_ERROR(c->WithRank(c->input(2), 1, &ignored)); + shape_inference::ShapeHandle element_shape_from_tensor_shape; + TF_RETURN_IF_ERROR( + c->Subshape(tensor_shape, 1, &element_shape_from_tensor_shape)); + TF_RETURN_IF_ERROR(c->Concatenate(c->MakeShape({c->UnknownDim()}), + element_shape_from_tensor_shape, + &element_shape_from_tensor_shape)); + shape_inference::ShapeHandle element_shape; + TF_RETURN_IF_ERROR(c->MakeShapeFromShapeTensorTreatScalarAsUnknownShape( + 1, &element_shape)); + TF_RETURN_IF_ERROR(c->Merge(element_shape_from_tensor_shape, + element_shape, + &element_shape_from_tensor_shape)); + c->set_output_handle_shapes_and_types( + 0, std::vector{ + {element_shape, element_dtype}}); + return Status::OK(); + }); + REGISTER_OP("TensorListFromTensor") .Input("tensor: element_dtype") .Input("element_shape: shape_type") @@ -205,17 +292,20 @@ REGISTER_OP("TensorListFromTensor") .Attr("shape_type: {int32, int64}") .SetShapeFn([](shape_inference::InferenceContext* c) { c->set_output(0, c->Scalar()); - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); - shape_inference::ShapeHandle s = c->input(0); - shape_inference::ShapeHandle o; - TF_RETURN_IF_ERROR(c->Subshape(s, 1, &o)); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); + shape_inference::ShapeHandle tensor_shape = c->input(0); + shape_inference::ShapeHandle tensor_shape_except_first_dim; + TF_RETURN_IF_ERROR( + c->Subshape(tensor_shape, 1, &tensor_shape_except_first_dim)); shape_inference::ShapeHandle element_shape; TF_RETURN_IF_ERROR(c->MakeShapeFromShapeTensorTreatScalarAsUnknownShape( 1, &element_shape)); - TF_RETURN_IF_ERROR(c->Merge(o, element_shape, &o)); + TF_RETURN_IF_ERROR(c->Merge(tensor_shape_except_first_dim, element_shape, + &tensor_shape_except_first_dim)); c->set_output_handle_shapes_and_types( - 0, std::vector{{element_shape, t}}); + 0, std::vector{ + {element_shape, element_dtype}}); return Status::OK(); }); @@ -241,13 +331,14 @@ REGISTER_OP("TensorListReserve") .Attr("shape_type: {int32, int64}") .SetShapeFn([](shape_inference::InferenceContext* c) { c->set_output(0, c->Scalar()); - shape_inference::ShapeHandle s; - TF_RETURN_IF_ERROR( - c->MakeShapeFromShapeTensorTreatScalarAsUnknownShape(0, &s)); - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); + shape_inference::ShapeHandle element_shape; + TF_RETURN_IF_ERROR(c->MakeShapeFromShapeTensorTreatScalarAsUnknownShape( + 0, &element_shape)); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); c->set_output_handle_shapes_and_types( - 0, std::vector{{s, t}}); + 0, std::vector{ + {element_shape, element_dtype}}); return Status::OK(); }); @@ -257,17 +348,17 @@ REGISTER_OP("TensorListGetItem") .Output("item: element_dtype") .Attr("element_dtype: type") .SetShapeFn([](shape_inference::InferenceContext* c) { - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); auto* handle_data = c->input_handle_shapes_and_types(0); shape_inference::ShapeHandle element_shape = c->UnknownShape(); if (handle_data != nullptr) { const shape_inference::ShapeAndType& list_shape_type = (*handle_data)[0]; element_shape = list_shape_type.shape; - if (list_shape_type.dtype != t) { + if (list_shape_type.dtype != element_dtype) { return errors::InvalidArgument("Expected list with element dtype ", - DataTypeString(t), + DataTypeString(element_dtype), " but got list with element dtype ", DataTypeString(list_shape_type.dtype)); } @@ -283,17 +374,19 @@ REGISTER_OP("TensorListSetItem") .Output("output_handle: variant") .Attr("element_dtype: type") .SetShapeFn([](shape_inference::InferenceContext* c) { - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); auto* handle_data = c->input_handle_shapes_and_types(0); c->set_output(0, c->Scalar()); if (handle_data == nullptr) { - c->set_output_handle_shapes_and_types(0, {{c->UnknownShape(), t}}); + c->set_output_handle_shapes_and_types( + 0, {{c->UnknownShape(), element_dtype}}); return Status::OK(); } const shape_inference::ShapeAndType& list_shape_type = (*handle_data)[0]; - shape_inference::ShapeHandle s = c->input(2); - TF_RETURN_IF_ERROR(c->Merge(s, list_shape_type.shape, &s)); + shape_inference::ShapeHandle item_shape = c->input(2); + TF_RETURN_IF_ERROR( + c->Merge(item_shape, list_shape_type.shape, &item_shape)); c->set_output_handle_shapes_and_types(0, *handle_data); return Status::OK(); }); @@ -304,17 +397,17 @@ REGISTER_OP("TensorListGather") .Output("values: element_dtype") .Attr("element_dtype: type") .SetShapeFn([](shape_inference::InferenceContext* c) { - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); auto* handle_data = c->input_handle_shapes_and_types(0); shape_inference::ShapeHandle element_shape = c->UnknownShape(); if (handle_data != nullptr) { const shape_inference::ShapeAndType& list_shape_type = (*handle_data)[0]; element_shape = list_shape_type.shape; - if (list_shape_type.dtype != t) { + if (list_shape_type.dtype != element_dtype) { return errors::InvalidArgument("Expected list with element dtype ", - DataTypeString(t), + DataTypeString(element_dtype), " but got list with element dtype ", DataTypeString(list_shape_type.dtype)); } @@ -333,12 +426,13 @@ REGISTER_OP("TensorListScatter") .Attr("element_dtype: type") .Attr("shape_type: {int32, int64}") .SetShapeFn([](shape_inference::InferenceContext* c) { - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); - shape_inference::ShapeHandle s; - TF_RETURN_IF_ERROR( - c->MakeShapeFromShapeTensorTreatScalarAsUnknownShape(2, &s)); - c->set_output_handle_shapes_and_types(0, {{s, t}}); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); + shape_inference::ShapeHandle element_shape; + TF_RETURN_IF_ERROR(c->MakeShapeFromShapeTensorTreatScalarAsUnknownShape( + 2, &element_shape)); + c->set_output_handle_shapes_and_types(0, + {{element_shape, element_dtype}}); c->set_output(0, c->Scalar()); return Status::OK(); }); @@ -354,28 +448,29 @@ REGISTER_OP("TensorListConcatLists") TF_RETURN_IF_ERROR(c->Merge(input_a, input_b, &input_a)); c->set_output(0, input_a); - DataType t; - TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &t)); + DataType element_dtype; + TF_RETURN_IF_ERROR(c->GetAttr("element_dtype", &element_dtype)); auto* handle_data_a = c->input_handle_shapes_and_types(0); auto* handle_data_b = c->input_handle_shapes_and_types(1); if (handle_data_a == nullptr && handle_data_b == nullptr) { - c->set_output_handle_shapes_and_types(0, {{c->UnknownShape(), t}}); + c->set_output_handle_shapes_and_types( + 0, {{c->UnknownShape(), element_dtype}}); return Status::OK(); } shape_inference::ShapeAndType list_shape_type_a = (handle_data_a) ? handle_data_a->at(0) : handle_data_b->at(0); const shape_inference::ShapeAndType& list_shape_type_b = (handle_data_b) ? handle_data_b->at(0) : handle_data_a->at(0); - if (list_shape_type_a.dtype != t) { + if (list_shape_type_a.dtype != element_dtype) { return errors::InvalidArgument("input_a.type != element_dtype: ", DataTypeString(list_shape_type_a.dtype), - " vs. ", DataTypeString(t)); + " vs. ", DataTypeString(element_dtype)); } - if (list_shape_type_b.dtype != t) { + if (list_shape_type_b.dtype != element_dtype) { return errors::InvalidArgument("input_b.type != element_dtype: ", DataTypeString(list_shape_type_b.dtype), - " vs. ", DataTypeString(t)); + " vs. ", DataTypeString(element_dtype)); } TF_RETURN_IF_ERROR(c->Merge(list_shape_type_a.shape, list_shape_type_b.shape, diff --git a/tensorflow/core/ops/nn_ops.cc b/tensorflow/core/ops/nn_ops.cc index 4dfd95b019..7ff9c46943 100644 --- a/tensorflow/core/ops/nn_ops.cc +++ b/tensorflow/core/ops/nn_ops.cc @@ -327,6 +327,9 @@ REGISTER_OP("_FusedConv2D") .Attr(GetConvnetDataFormatAttrString()) .Attr("dilations: list(int) = [1, 1, 1, 1]") .Attr("fused_ops: list(string) = []") + // Attributes for the FusedBatchNorm ------------------------------------ // + .Attr("epsilon: float = 0.0001") + // ---------------------------------------------------------------------- // .SetShapeFn(shape_inference::Conv2DShape) .Doc(R"doc( *NOTE*: Do not invoke this operator directly in Python. Grappler is @@ -2190,11 +2193,7 @@ REGISTER_OP("_MklLRN") .Input("input: T") .Input("mkl_input: uint8") .Output("output: T") -#ifdef INTEL_MKL_ML_ONLY - .Output("workspace: T") -#else .Output("workspace: uint8") -#endif .Output("mkl_output: uint8") .Output("mkl_workspace: uint8") .Attr("depth_radius: int = 5") @@ -2218,11 +2217,7 @@ REGISTER_OP("_MklLRNGrad") .Input("input_grads: T") .Input("input_image: T") .Input("output_image: T") -#ifdef INTEL_MKL_ML_ONLY - .Input("workspace: T") -#else .Input("workspace: uint8") -#endif .Input("mkl_input_grads: uint8") .Input("mkl_input_image: uint8") .Input("mkl_output_image: uint8") diff --git a/tensorflow/core/ops/ops.pbtxt b/tensorflow/core/ops/ops.pbtxt index 430212ee1d..a9c712e138 100644 --- a/tensorflow/core/ops/ops.pbtxt +++ b/tensorflow/core/ops/ops.pbtxt @@ -4944,33 +4944,6 @@ op { type: "list(float)" } } -op { - name: "BytesProducedStatsDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "tag" - type: DT_STRING - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "CTCBeamSearchDecoder" input_arg { @@ -7915,21 +7888,6 @@ op { minimum: 1 } } -op { - name: "DatasetToTFRecord" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "filename" - type: DT_STRING - } - input_arg { - name: "compression_type" - type: DT_STRING - } -} op { name: "DebugGradientIdentity" input_arg { @@ -8599,37 +8557,6 @@ op { } } } -op { - name: "DenseToSparseBatchDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "batch_size" - type: DT_INT64 - } - input_arg { - name: "row_shape" - type: DT_INT64 - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "DenseToSparseSetOperation" input_arg { @@ -9834,24 +9761,6 @@ op { type: DT_STRING } } -op { - name: "EnqueueInQueueDataset" - input_arg { - name: "queue" - type: DT_VARIANT - } - input_arg { - name: "components" - type_list_attr: "Tcomponents" - } - attr { - name: "Tcomponents" - type: "list(type)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} op { name: "EnsureShape" input_arg { @@ -10089,6 +9998,33 @@ op { minimum: 1 } } +op { + name: "ExperimentalBytesProducedStatsDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "tag" + type: DT_STRING + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} op { name: "ExperimentalCSVDataset" input_arg { @@ -10154,6 +10090,52 @@ op { } is_stateful: true } +op { + name: "ExperimentalDatasetToTFRecord" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "filename" + type: DT_STRING + } + input_arg { + name: "compression_type" + type: DT_STRING + } +} +op { + name: "ExperimentalDenseToSparseBatchDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "batch_size" + type: DT_INT64 + } + input_arg { + name: "row_shape" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} op { name: "ExperimentalDirectedInterleaveDataset" input_arg { @@ -10189,50 +10171,66 @@ op { } } op { - name: "ExperimentalFunctionBufferingResource" + name: "ExperimentalGroupByReducerDataset" input_arg { - name: "string_arg" - type: DT_STRING + name: "input_dataset" + type: DT_VARIANT } input_arg { - name: "target_device" - type: DT_STRING + name: "key_func_other_arguments" + type_list_attr: "Tkey_func_other_arguments" + } + input_arg { + name: "init_func_other_arguments" + type_list_attr: "Tinit_func_other_arguments" + } + input_arg { + name: "reduce_func_other_arguments" + type_list_attr: "Treduce_func_other_arguments" + } + input_arg { + name: "finalize_func_other_arguments" + type_list_attr: "Tfinalize_func_other_arguments" } output_arg { - name: "resource" - type: DT_RESOURCE + name: "handle" + type: DT_VARIANT } attr { - name: "shared_name" - type: "string" + name: "key_func" + type: "func" } attr { - name: "container" - type: "string" + name: "init_func" + type: "func" } attr { - name: "f" + name: "reduce_func" type: "func" } attr { - name: "buffer_size" - type: "int" + name: "finalize_func" + type: "func" } attr { - name: "output_types" + name: "Tkey_func_other_arguments" type: "list(type)" + has_minimum: true } - is_stateful: true -} -op { - name: "ExperimentalFunctionBufferingResourceGetNext" - input_arg { - name: "function_buffer_resource" - type: DT_RESOURCE + attr { + name: "Tinit_func_other_arguments" + type: "list(type)" + has_minimum: true } - output_arg { - name: "output" - type_list_attr: "output_types" + attr { + name: "Treduce_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Tfinalize_func_other_arguments" + type: "list(type)" + has_minimum: true } attr { name: "output_types" @@ -10240,48 +10238,108 @@ op { has_minimum: true minimum: 1 } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } is_stateful: true } op { - name: "ExperimentalFunctionBufferingResourceReset" + name: "ExperimentalGroupByWindowDataset" input_arg { - name: "function_buffer_resource" - type: DT_RESOURCE + name: "input_dataset" + type: DT_VARIANT } - is_stateful: true -} -op { - name: "ExperimentalIdentityIndexedDataset" input_arg { - name: "size" - type: DT_UINT64 + name: "key_func_other_arguments" + type_list_attr: "Tkey_func_other_arguments" } - output_arg { - name: "handle" - type: DT_VARIANT + input_arg { + name: "reduce_func_other_arguments" + type_list_attr: "Treduce_func_other_arguments" } - is_stateful: true -} -op { - name: "ExperimentalIgnoreErrorsDataset" input_arg { - name: "input_dataset" - type: DT_VARIANT + name: "window_size_func_other_arguments" + type_list_attr: "Twindow_size_func_other_arguments" } output_arg { name: "handle" type: DT_VARIANT } attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 + name: "key_func" + type: "func" } attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true + name: "reduce_func" + type: "func" + } + attr { + name: "window_size_func" + type: "func" + } + attr { + name: "Tkey_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Treduce_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "Twindow_size_func_other_arguments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalIdentityIndexedDataset" + input_arg { + name: "size" + type: DT_UINT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + is_stateful: true +} +op { + name: "ExperimentalIgnoreErrorsDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true minimum: 1 } } @@ -10343,9 +10401,500 @@ op { name: "filenames" type: DT_STRING } - output_arg { - name: "handle" - type: DT_VARIANT + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + is_stateful: true +} +op { + name: "ExperimentalLatencyStatsDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "tag" + type: DT_STRING + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalMapAndBatchDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "other_arguments" + type_list_attr: "Targuments" + } + input_arg { + name: "batch_size" + type: DT_INT64 + } + input_arg { + name: "num_parallel_calls" + type: DT_INT64 + } + input_arg { + name: "drop_remainder" + type: DT_BOOL + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "f" + type: "func" + } + attr { + name: "Targuments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalMapDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "other_arguments" + type_list_attr: "Targuments" + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "f" + type: "func" + } + attr { + name: "Targuments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + attr { + name: "use_inter_op_parallelism" + type: "bool" + default_value { + b: true + } + } +} +op { + name: "ExperimentalMatchingFilesDataset" + input_arg { + name: "patterns" + type: DT_STRING + } + output_arg { + name: "handle" + type: DT_VARIANT + } + is_stateful: true +} +op { + name: "ExperimentalMaterializedIndexDatasetHandle" + output_arg { + name: "handle" + type: DT_RESOURCE + } + attr { + name: "container" + type: "string" + } + attr { + name: "shared_name" + type: "string" + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + is_stateful: true +} +op { + name: "ExperimentalMaxIntraOpParallelismDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "max_intra_op_parallelism" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalNonSerializableDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalNumaMapAndBatchDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "other_arguments" + type_list_attr: "Targuments" + } + input_arg { + name: "batch_size" + type: DT_INT64 + } + input_arg { + name: "num_parallel_calls" + type: DT_INT64 + } + input_arg { + name: "drop_remainder" + type: DT_BOOL + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "f" + type: "func" + } + attr { + name: "Targuments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalParallelInterleaveDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "other_arguments" + type_list_attr: "Targuments" + } + input_arg { + name: "cycle_length" + type: DT_INT64 + } + input_arg { + name: "block_length" + type: DT_INT64 + } + input_arg { + name: "sloppy" + type: DT_BOOL + } + input_arg { + name: "buffer_output_elements" + type: DT_INT64 + } + input_arg { + name: "prefetch_input_elements" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "f" + type: "func" + } + attr { + name: "Targuments" + type: "list(type)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalParseExampleDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "num_parallel_calls" + type: DT_INT64 + } + input_arg { + name: "dense_defaults" + type_list_attr: "Tdense" + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "sparse_keys" + type: "list(string)" + has_minimum: true + } + attr { + name: "dense_keys" + type: "list(string)" + has_minimum: true + } + attr { + name: "sparse_types" + type: "list(type)" + has_minimum: true + allowed_values { + list { + type: DT_FLOAT + type: DT_INT64 + type: DT_STRING + } + } + } + attr { + name: "Tdense" + type: "list(type)" + has_minimum: true + allowed_values { + list { + type: DT_FLOAT + type: DT_INT64 + type: DT_STRING + } + } + } + attr { + name: "dense_shapes" + type: "list(shape)" + has_minimum: true + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + attr { + name: "sloppy" + type: "bool" + default_value { + b: false + } + } +} +op { + name: "ExperimentalPrivateThreadPoolDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "num_threads" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} +op { + name: "ExperimentalRandomDataset" + input_arg { + name: "seed" + type: DT_INT64 + } + input_arg { + name: "seed2" + type: DT_INT64 + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + is_stateful: true +} +op { + name: "ExperimentalScanDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "initial_state" + type_list_attr: "Tstate" + } + input_arg { + name: "other_arguments" + type_list_attr: "Targuments" + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "f" + type: "func" + } + attr { + name: "Tstate" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "Targuments" + type: "list(type)" + has_minimum: true } attr { name: "output_types" @@ -10359,21 +10908,28 @@ op { has_minimum: true minimum: 1 } - is_stateful: true } op { - name: "ExperimentalMaterializedIndexDatasetHandle" - output_arg { - name: "handle" + name: "ExperimentalSetStatsAggregatorDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + input_arg { + name: "stats_aggregator" type: DT_RESOURCE } - attr { - name: "container" - type: "string" + input_arg { + name: "tag" + type: DT_STRING } - attr { - name: "shared_name" - type: "string" + input_arg { + name: "counter_prefix" + type: DT_STRING + } + output_arg { + name: "handle" + type: DT_VARIANT } attr { name: "output_types" @@ -10390,11 +10946,15 @@ op { is_stateful: true } op { - name: "ExperimentalNonSerializableDataset" + name: "ExperimentalSleepDataset" input_arg { name: "input_dataset" type: DT_VARIANT } + input_arg { + name: "sleep_microseconds" + type: DT_INT64 + } output_arg { name: "handle" type: DT_VARIANT @@ -10413,40 +10973,27 @@ op { } } op { - name: "ExperimentalNumaMapAndBatchDataset" + name: "ExperimentalSlidingWindowDataset" input_arg { name: "input_dataset" type: DT_VARIANT } input_arg { - name: "other_arguments" - type_list_attr: "Targuments" - } - input_arg { - name: "batch_size" + name: "window_size" type: DT_INT64 } input_arg { - name: "num_parallel_calls" + name: "window_shift" type: DT_INT64 } input_arg { - name: "drop_remainder" - type: DT_BOOL + name: "window_stride" + type: DT_INT64 } output_arg { name: "handle" type: DT_VARIANT } - attr { - name: "f" - type: "func" - } - attr { - name: "Targuments" - type: "list(type)" - has_minimum: true - } attr { name: "output_types" type: "list(type)" @@ -10461,14 +11008,18 @@ op { } } op { - name: "ExperimentalSleepDataset" + name: "ExperimentalSqlDataset" input_arg { - name: "input_dataset" - type: DT_VARIANT + name: "driver_name" + type: DT_STRING } input_arg { - name: "sleep_microseconds" - type: DT_INT64 + name: "data_source_name" + type: DT_STRING + } + input_arg { + name: "query" + type: DT_STRING } output_arg { name: "handle" @@ -10486,6 +11037,41 @@ op { has_minimum: true minimum: 1 } + is_stateful: true +} +op { + name: "ExperimentalStatsAggregatorHandle" + output_arg { + name: "handle" + type: DT_RESOURCE + } + attr { + name: "container" + type: "string" + default_value { + s: "" + } + } + attr { + name: "shared_name" + type: "string" + default_value { + s: "" + } + } + is_stateful: true +} +op { + name: "ExperimentalStatsAggregatorSummary" + input_arg { + name: "iterator" + type: DT_RESOURCE + } + output_arg { + name: "summary" + type: DT_STRING + } + is_stateful: true } op { name: "ExperimentalThreadPoolDataset" @@ -10552,6 +11138,29 @@ op { } is_stateful: true } +op { + name: "ExperimentalUnbatchDataset" + input_arg { + name: "input_dataset" + type: DT_VARIANT + } + output_arg { + name: "handle" + type: DT_VARIANT + } + attr { + name: "output_types" + type: "list(type)" + has_minimum: true + minimum: 1 + } + attr { + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } +} op { name: "ExperimentalUniqueDataset" input_arg { @@ -12708,178 +13317,40 @@ op { } } } -} -op { - name: "GreaterEqual" - input_arg { - name: "x" - type_attr: "T" - } - input_arg { - name: "y" - type_attr: "T" - } - output_arg { - name: "z" - type: DT_BOOL - } - attr { - name: "T" - type: "type" - allowed_values { - list { - type: DT_FLOAT - type: DT_DOUBLE - type: DT_INT32 - type: DT_UINT8 - type: DT_INT16 - type: DT_INT8 - type: DT_INT64 - type: DT_BFLOAT16 - type: DT_UINT16 - type: DT_HALF - type: DT_UINT32 - type: DT_UINT64 - } - } - } -} -op { - name: "GroupByReducerDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "key_func_other_arguments" - type_list_attr: "Tkey_func_other_arguments" - } - input_arg { - name: "init_func_other_arguments" - type_list_attr: "Tinit_func_other_arguments" - } - input_arg { - name: "reduce_func_other_arguments" - type_list_attr: "Treduce_func_other_arguments" - } - input_arg { - name: "finalize_func_other_arguments" - type_list_attr: "Tfinalize_func_other_arguments" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "key_func" - type: "func" - } - attr { - name: "init_func" - type: "func" - } - attr { - name: "reduce_func" - type: "func" - } - attr { - name: "finalize_func" - type: "func" - } - attr { - name: "Tkey_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Tinit_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Treduce_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Tfinalize_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} -op { - name: "GroupByWindowDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "key_func_other_arguments" - type_list_attr: "Tkey_func_other_arguments" - } +} +op { + name: "GreaterEqual" input_arg { - name: "reduce_func_other_arguments" - type_list_attr: "Treduce_func_other_arguments" + name: "x" + type_attr: "T" } input_arg { - name: "window_size_func_other_arguments" - type_list_attr: "Twindow_size_func_other_arguments" + name: "y" + type_attr: "T" } output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "key_func" - type: "func" - } - attr { - name: "reduce_func" - type: "func" - } - attr { - name: "window_size_func" - type: "func" - } - attr { - name: "Tkey_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Treduce_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "Twindow_size_func_other_arguments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 + name: "z" + type: DT_BOOL } attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT32 + type: DT_UINT8 + type: DT_INT16 + type: DT_INT8 + type: DT_INT64 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 + } + } } } op { @@ -14422,33 +14893,6 @@ op { } } } -op { - name: "LatencyStatsDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "tag" - type: DT_STRING - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "LeakyRelu" input_arg { @@ -15319,102 +15763,6 @@ op { } is_stateful: true } -op { - name: "MapAndBatchDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "other_arguments" - type_list_attr: "Targuments" - } - input_arg { - name: "batch_size" - type: DT_INT64 - } - input_arg { - name: "num_parallel_batches" - type: DT_INT64 - } - input_arg { - name: "drop_remainder" - type: DT_BOOL - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "f" - type: "func" - } - attr { - name: "Targuments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} -op { - name: "MapAndBatchDatasetV2" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "other_arguments" - type_list_attr: "Targuments" - } - input_arg { - name: "batch_size" - type: DT_INT64 - } - input_arg { - name: "num_parallel_calls" - type: DT_INT64 - } - input_arg { - name: "drop_remainder" - type: DT_BOOL - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "f" - type: "func" - } - attr { - name: "Targuments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "MapClear" attr { @@ -15894,18 +16242,6 @@ op { type: DT_STRING } } -op { - name: "MatchingFilesDataset" - input_arg { - name: "patterns" - type: DT_STRING - } - output_arg { - name: "handle" - type: DT_VARIANT - } - is_stateful: true -} op { name: "MatrixBandPart" input_arg { @@ -19429,80 +19765,24 @@ op { type: DT_INT32 number_attr: "N" } - input_arg { - name: "data" - type_attr: "T" - number_attr: "N" - } - output_arg { - name: "merged" - type_attr: "T" - } - attr { - name: "N" - type: "int" - has_minimum: true - minimum: 1 - } - attr { - name: "T" - type: "type" - } -} -op { - name: "ParallelInterleaveDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "other_arguments" - type_list_attr: "Targuments" - } - input_arg { - name: "cycle_length" - type: DT_INT64 - } - input_arg { - name: "block_length" - type: DT_INT64 - } - input_arg { - name: "sloppy" - type: DT_BOOL - } - input_arg { - name: "buffer_output_elements" - type: DT_INT64 - } - input_arg { - name: "prefetch_input_elements" - type: DT_INT64 - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "f" - type: "func" + input_arg { + name: "data" + type_attr: "T" + number_attr: "N" } - attr { - name: "Targuments" - type: "list(type)" - has_minimum: true + output_arg { + name: "merged" + type_attr: "T" } attr { - name: "output_types" - type: "list(type)" + name: "N" + type: "int" has_minimum: true minimum: 1 } attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 + name: "T" + type: "type" } } op { @@ -19760,83 +20040,6 @@ op { has_minimum: true } } -op { - name: "ParseExampleDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "num_parallel_calls" - type: DT_INT64 - } - input_arg { - name: "dense_defaults" - type_list_attr: "Tdense" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "sparse_keys" - type: "list(string)" - has_minimum: true - } - attr { - name: "dense_keys" - type: "list(string)" - has_minimum: true - } - attr { - name: "sparse_types" - type: "list(type)" - has_minimum: true - allowed_values { - list { - type: DT_FLOAT - type: DT_INT64 - type: DT_STRING - } - } - } - attr { - name: "Tdense" - type: "list(type)" - has_minimum: true - allowed_values { - list { - type: DT_FLOAT - type: DT_INT64 - type: DT_STRING - } - } - } - attr { - name: "dense_shapes" - type: "list(shape)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - attr { - name: "sloppy" - type: "bool" - default_value { - b: false - } - } -} op { name: "ParseSequenceExample" input_arg { @@ -20340,6 +20543,13 @@ op { s: "" } } + attr { + name: "config_proto" + type: "string" + default_value { + s: "" + } + } attr { name: "executor_type" type: "string" @@ -20516,48 +20726,6 @@ op { minimum: 1 } } -op { - name: "PrependFromQueueAndPaddedBatchDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "batch_size" - type: DT_INT64 - } - input_arg { - name: "padded_shapes" - type: DT_INT64 - number_attr: "N" - } - input_arg { - name: "padding_values" - type_list_attr: "Toutput_types" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "Toutput_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - attr { - name: "N" - type: "int" - has_minimum: true - minimum: 1 - } -} op { name: "PreventGradient" input_arg { @@ -20986,6 +21154,19 @@ op { } } } + attr { + name: "round_mode" + type: "string" + default_value { + s: "HALF_TO_EVEN" + } + allowed_values { + list { + s: "HALF_TO_EVEN" + s: "HALF_UP" + } + } + } } op { name: "QuantizeAndDequantizeV3" @@ -22816,34 +22997,6 @@ op { } is_stateful: true } -op { - name: "RandomDataset" - input_arg { - name: "seed" - type: DT_INT64 - } - input_arg { - name: "seed2" - type: DT_INT64 - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} op { name: "RandomGamma" input_arg { @@ -24900,8 +25053,83 @@ op { type_attr: "T" } input_arg { - name: "grad" - type_attr: "T" + name: "grad" + type_attr: "T" + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT32 + type: DT_UINT8 + type: DT_INT16 + type: DT_INT8 + type: DT_COMPLEX64 + type: DT_INT64 + type: DT_QINT8 + type: DT_QUINT8 + type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 + type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 + } + } + } + attr { + name: "use_locking" + type: "bool" + default_value { + b: false + } + } + attr { + name: "update_slots" + type: "bool" + default_value { + b: true + } + } + is_stateful: true +} +op { + name: "ResourceApplyAdagradDA" + input_arg { + name: "var" + type: DT_RESOURCE + } + input_arg { + name: "gradient_accumulator" + type: DT_RESOURCE + } + input_arg { + name: "gradient_squared_accumulator" + type: DT_RESOURCE + } + input_arg { + name: "grad" + type_attr: "T" + } + input_arg { + name: "lr" + type_attr: "T" + } + input_arg { + name: "l1" + type_attr: "T" + } + input_arg { + name: "l2" + type_attr: "T" + } + input_arg { + name: "global_step" + type: DT_INT64 } attr { name: "T" @@ -24935,31 +25163,28 @@ op { b: false } } - attr { - name: "update_slots" - type: "bool" - default_value { - b: true - } - } is_stateful: true } op { - name: "ResourceApplyAdagradDA" + name: "ResourceApplyAdam" input_arg { name: "var" type: DT_RESOURCE } input_arg { - name: "gradient_accumulator" + name: "m" type: DT_RESOURCE } input_arg { - name: "gradient_squared_accumulator" + name: "v" type: DT_RESOURCE } input_arg { - name: "grad" + name: "beta1_power" + type_attr: "T" + } + input_arg { + name: "beta2_power" type_attr: "T" } input_arg { @@ -24967,16 +25192,20 @@ op { type_attr: "T" } input_arg { - name: "l1" + name: "beta1" type_attr: "T" } input_arg { - name: "l2" + name: "beta2" type_attr: "T" } input_arg { - name: "global_step" - type: DT_INT64 + name: "epsilon" + type_attr: "T" + } + input_arg { + name: "grad" + type_attr: "T" } attr { name: "T" @@ -25010,10 +25239,17 @@ op { b: false } } + attr { + name: "use_nesterov" + type: "bool" + default_value { + b: false + } + } is_stateful: true } op { - name: "ResourceApplyAdam" + name: "ResourceApplyAdamWithAmsgrad" input_arg { name: "var" type: DT_RESOURCE @@ -25026,6 +25262,10 @@ op { name: "v" type: DT_RESOURCE } + input_arg { + name: "vhat" + type: DT_RESOURCE + } input_arg { name: "beta1_power" type_attr: "T" @@ -25086,13 +25326,6 @@ op { b: false } } - attr { - name: "use_nesterov" - type: "bool" - default_value { - b: false - } - } is_stateful: true } op { @@ -25419,6 +25652,69 @@ op { } is_stateful: true } +op { + name: "ResourceApplyKerasMomentum" + input_arg { + name: "var" + type: DT_RESOURCE + } + input_arg { + name: "accum" + type: DT_RESOURCE + } + input_arg { + name: "lr" + type_attr: "T" + } + input_arg { + name: "grad" + type_attr: "T" + } + input_arg { + name: "momentum" + type_attr: "T" + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT32 + type: DT_UINT8 + type: DT_INT16 + type: DT_INT8 + type: DT_COMPLEX64 + type: DT_INT64 + type: DT_QINT8 + type: DT_QUINT8 + type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 + type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 + } + } + } + attr { + name: "use_locking" + type: "bool" + default_value { + b: false + } + } + attr { + name: "use_nesterov" + type: "bool" + default_value { + b: false + } + } + is_stateful: true +} op { name: "ResourceApplyMomentum" input_arg { @@ -26690,6 +26986,83 @@ op { } is_stateful: true } +op { + name: "ResourceSparseApplyKerasMomentum" + input_arg { + name: "var" + type: DT_RESOURCE + } + input_arg { + name: "accum" + type: DT_RESOURCE + } + input_arg { + name: "lr" + type_attr: "T" + } + input_arg { + name: "grad" + type_attr: "T" + } + input_arg { + name: "indices" + type_attr: "Tindices" + } + input_arg { + name: "momentum" + type_attr: "T" + } + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT32 + type: DT_UINT8 + type: DT_INT16 + type: DT_INT8 + type: DT_COMPLEX64 + type: DT_INT64 + type: DT_QINT8 + type: DT_QUINT8 + type: DT_QINT32 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_COMPLEX128 + type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 + } + } + } + attr { + name: "Tindices" + type: "type" + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } + } + } + attr { + name: "use_locking" + type: "bool" + default_value { + b: false + } + } + attr { + name: "use_nesterov" + type: "bool" + default_value { + b: false + } + } + is_stateful: true +} op { name: "ResourceSparseApplyMomentum" input_arg { @@ -27768,71 +28141,25 @@ op { name: "summary" type: DT_STRING } - attr { - name: "T" - type: "type" - allowed_values { - list { - type: DT_FLOAT - type: DT_DOUBLE - type: DT_INT32 - type: DT_UINT8 - type: DT_INT16 - type: DT_INT8 - type: DT_INT64 - type: DT_BFLOAT16 - type: DT_UINT16 - type: DT_HALF - type: DT_UINT32 - type: DT_UINT64 - } - } - } -} -op { - name: "ScanDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "initial_state" - type_list_attr: "Tstate" - } - input_arg { - name: "other_arguments" - type_list_attr: "Targuments" - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "f" - type: "func" - } - attr { - name: "Tstate" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "Targuments" - type: "list(type)" - has_minimum: true - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 + attr { + name: "T" + type: "type" + allowed_values { + list { + type: DT_FLOAT + type: DT_DOUBLE + type: DT_INT32 + type: DT_UINT8 + type: DT_INT16 + type: DT_INT8 + type: DT_INT64 + type: DT_BFLOAT16 + type: DT_UINT16 + type: DT_HALF + type: DT_UINT32 + type: DT_UINT64 + } + } } } op { @@ -29272,42 +29599,6 @@ op { } } } -op { - name: "SetStatsAggregatorDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "stats_aggregator" - type: DT_RESOURCE - } - input_arg { - name: "tag" - type: DT_STRING - } - input_arg { - name: "counter_prefix" - type: DT_STRING - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} op { name: "Shape" input_arg { @@ -29771,41 +30062,6 @@ op { } } } -op { - name: "SlideDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - input_arg { - name: "window_size" - type: DT_INT64 - } - input_arg { - name: "window_shift" - type: DT_INT64 - } - input_arg { - name: "window_stride" - type: DT_INT64 - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "Snapshot" input_arg { @@ -32996,38 +33252,6 @@ op { } } } -op { - name: "SqlDataset" - input_arg { - name: "driver_name" - type: DT_STRING - } - input_arg { - name: "data_source_name" - type: DT_STRING - } - input_arg { - name: "query" - type: DT_STRING - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } - is_stateful: true -} op { name: "Sqrt" input_arg { @@ -33513,6 +33737,13 @@ op { s: "" } } + attr { + name: "config_proto" + type: "string" + default_value { + s: "" + } + } attr { name: "executor_type" type: "string" @@ -33913,40 +34144,6 @@ op { } } } -op { - name: "StatsAggregatorHandle" - output_arg { - name: "handle" - type: DT_RESOURCE - } - attr { - name: "container" - type: "string" - default_value { - s: "" - } - } - attr { - name: "shared_name" - type: "string" - default_value { - s: "" - } - } - is_stateful: true -} -op { - name: "StatsAggregatorSummary" - input_arg { - name: "iterator" - type: DT_RESOURCE - } - output_arg { - name: "summary" - type: DT_STRING - } - is_stateful: true -} op { name: "StopGradient" input_arg { @@ -35916,12 +36113,133 @@ op { minimum: 1 } attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 + name: "output_shapes" + type: "list(shape)" + has_minimum: true + minimum: 1 + } + is_stateful: true +} +op { + name: "TensorForestCreateTreeVariable" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + input_arg { + name: "tree_config" + type: DT_STRING + } + is_stateful: true +} +op { + name: "TensorForestTreeDeserialize" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + input_arg { + name: "tree_config" + type: DT_STRING + } + is_stateful: true +} +op { + name: "TensorForestTreeIsInitializedOp" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + output_arg { + name: "is_initialized" + type: DT_BOOL + } + is_stateful: true +} +op { + name: "TensorForestTreePredict" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + input_arg { + name: "dense_features" + type: DT_FLOAT + } + output_arg { + name: "logits" + type: DT_FLOAT + } + attr { + name: "logits_dimension" + type: "int" + } + is_stateful: true +} +op { + name: "TensorForestTreeResourceHandleOp" + output_arg { + name: "resource" + type: DT_RESOURCE + } + attr { + name: "container" + type: "string" + default_value { + s: "" + } + } + attr { + name: "shared_name" + type: "string" + default_value { + s: "" + } + } + is_stateful: true +} +op { + name: "TensorForestTreeSerialize" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + output_arg { + name: "tree_config" + type: DT_STRING + } + is_stateful: true +} +op { + name: "TensorForestTreeSize" + input_arg { + name: "tree_handle" + type: DT_RESOURCE + } + output_arg { + name: "tree_size" + type: DT_INT32 + } + is_stateful: true +} +op { + name: "TensorListConcat" + input_arg { + name: "input_handle" + type: DT_VARIANT + } + output_arg { + name: "tensor" + type_attr: "element_dtype" + } + output_arg { + name: "lengths" + type: DT_INT64 + } + attr { + name: "element_dtype" + type: "type" } - is_stateful: true } op { name: "TensorListConcatLists" @@ -36183,6 +36501,39 @@ op { type: "type" } } +op { + name: "TensorListSplit" + input_arg { + name: "tensor" + type_attr: "element_dtype" + } + input_arg { + name: "element_shape" + type_attr: "shape_type" + } + input_arg { + name: "lengths" + type: DT_INT64 + } + output_arg { + name: "output_handle" + type: DT_VARIANT + } + attr { + name: "element_dtype" + type: "type" + } + attr { + name: "shape_type" + type: "type" + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } + } + } +} op { name: "TensorListStack" input_arg { @@ -36205,6 +36556,105 @@ op { } } } +op { + name: "TensorScatterAdd" + input_arg { + name: "tensor" + type_attr: "T" + } + input_arg { + name: "indices" + type_attr: "Tindices" + } + input_arg { + name: "updates" + type_attr: "T" + } + output_arg { + name: "output" + type_attr: "T" + } + attr { + name: "T" + type: "type" + } + attr { + name: "Tindices" + type: "type" + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } + } + } +} +op { + name: "TensorScatterSub" + input_arg { + name: "tensor" + type_attr: "T" + } + input_arg { + name: "indices" + type_attr: "Tindices" + } + input_arg { + name: "updates" + type_attr: "T" + } + output_arg { + name: "output" + type_attr: "T" + } + attr { + name: "T" + type: "type" + } + attr { + name: "Tindices" + type: "type" + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } + } + } +} +op { + name: "TensorScatterUpdate" + input_arg { + name: "tensor" + type_attr: "T" + } + input_arg { + name: "indices" + type_attr: "Tindices" + } + input_arg { + name: "updates" + type_attr: "T" + } + output_arg { + name: "output" + type_attr: "T" + } + attr { + name: "T" + type: "type" + } + attr { + name: "Tindices" + type: "type" + allowed_values { + list { + type: DT_INT32 + type: DT_INT64 + } + } + } +} op { name: "TensorSliceDataset" input_arg { @@ -36822,29 +37272,6 @@ op { type: "type" } } -op { - name: "UnbatchDataset" - input_arg { - name: "input_dataset" - type: DT_VARIANT - } - output_arg { - name: "handle" - type: DT_VARIANT - } - attr { - name: "output_types" - type: "list(type)" - has_minimum: true - minimum: 1 - } - attr { - name: "output_shapes" - type: "list(shape)" - has_minimum: true - minimum: 1 - } -} op { name: "UnbatchGrad" input_arg { @@ -36886,6 +37313,104 @@ op { type: "type" } } +op { + name: "UnicodeDecodeWithOffsets" + input_arg { + name: "input" + type: DT_STRING + } + output_arg { + name: "row_splits" + type: DT_INT64 + } + output_arg { + name: "char_values" + type: DT_INT32 + } + output_arg { + name: "char_to_byte_starts" + type: DT_INT64 + } + attr { + name: "input_encoding" + type: "string" + } + attr { + name: "errors" + type: "string" + default_value { + s: "replace" + } + allowed_values { + list { + s: "strict" + s: "replace" + s: "ignore" + } + } + } + attr { + name: "replacement_char" + type: "int" + default_value { + i: 65533 + } + } + attr { + name: "replace_control_characters" + type: "bool" + default_value { + b: false + } + } +} +op { + name: "UnicodeEncode" + input_arg { + name: "input_values" + type: DT_INT32 + } + input_arg { + name: "input_splits" + type: DT_INT64 + } + output_arg { + name: "output" + type: DT_STRING + } + attr { + name: "errors" + type: "string" + default_value { + s: "replace" + } + allowed_values { + list { + s: "ignore" + s: "replace" + s: "strict" + } + } + } + attr { + name: "output_encoding" + type: "string" + allowed_values { + list { + s: "UTF-8" + s: "UTF-16-BE" + s: "UTF-32-BE" + } + } + } + attr { + name: "replacement_char" + type: "int" + default_value { + i: 65533 + } + } +} op { name: "UnicodeScript" input_arg { diff --git a/tensorflow/core/ops/sparse_ops.cc b/tensorflow/core/ops/sparse_ops.cc index bc0cb2095d..de08a10784 100644 --- a/tensorflow/core/ops/sparse_ops.cc +++ b/tensorflow/core/ops/sparse_ops.cc @@ -401,7 +401,7 @@ REGISTER_OP("SparseReduceMax") .Attr("keep_dims: bool = False") .Output("output: T") .Attr("T: realnumbertype") - .SetShapeFn(shape_inference::UnknownShape); + .SetShapeFn(shape_inference::SparseReduceShapeFn); REGISTER_OP("SparseReduceMaxSparse") .Input("input_indices: int64") @@ -423,7 +423,7 @@ REGISTER_OP("SparseReduceSum") .Attr("keep_dims: bool = False") .Output("output: T") .Attr("T: numbertype") - .SetShapeFn(shape_inference::UnknownShape); + .SetShapeFn(shape_inference::SparseReduceShapeFn); REGISTER_OP("SparseReduceSumSparse") .Input("input_indices: int64") diff --git a/tensorflow/core/ops/sparse_ops_test.cc b/tensorflow/core/ops/sparse_ops_test.cc index 6a9b5ce4d3..00283c5993 100644 --- a/tensorflow/core/ops/sparse_ops_test.cc +++ b/tensorflow/core/ops/sparse_ops_test.cc @@ -133,6 +133,13 @@ TEST(SparseOpsTest, SparseToDense_ShapeFn) { TEST(SparseOpsTest, SparseReduceSum_ShapeFn) { ShapeInferenceTestOp op("SparseReduceSum"); + TF_ASSERT_OK(NodeDefBuilder("test", "SparseReduceSum") + .Input({"input_indices", 0, DT_INT64}) + .Input({"input_values", 1, DT_INT64}) + .Input({"input_shape", 2, DT_INT64}) + .Input({"reduction_axes", 3, DT_INT32}) + .Attr("keep_dims", false) + .Finalize(&op.node_def)); // Shape fn always yields unknown. INFER_OK(op, "?;?;?;?", "?"); diff --git a/tensorflow/core/ops/string_ops.cc b/tensorflow/core/ops/string_ops.cc index 352253135c..8ea74f1d43 100644 --- a/tensorflow/core/ops/string_ops.cc +++ b/tensorflow/core/ops/string_ops.cc @@ -13,13 +13,24 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include +#include + #include "absl/strings/str_split.h" #include "tensorflow/core/framework/common_shape_fns.h" #include "tensorflow/core/framework/op.h" #include "tensorflow/core/framework/shape_inference.h" +#include "tensorflow/core/lib/core/errors.h" +#include "tensorflow/core/lib/core/status.h" +#include "tensorflow/core/lib/strings/strcat.h" +#include "tensorflow/core/platform/types.h" namespace tensorflow { +namespace shape_inference { +class InferenceContext; +} // namespace shape_inference + using shape_inference::DimensionHandle; using shape_inference::InferenceContext; using shape_inference::ShapeHandle; @@ -250,6 +261,31 @@ REGISTER_OP("UnicodeScript") .Output("output: int32") .SetShapeFn(shape_inference::UnchangedShape); +REGISTER_OP("UnicodeEncode") + .Input("input_values: int32") + .Input("input_splits: int64") + .Attr("errors: {'ignore', 'replace', 'strict'} = 'replace'") + .Attr("output_encoding: {'UTF-8', 'UTF-16-BE', 'UTF-32-BE'}") + .Attr("replacement_char: int = 65533") // 0xFFFD unicode replacement char + .Output("output: string") + .SetShapeFn([](InferenceContext* c) { + // Check rank of inner values + ShapeHandle input_inner_values_shape = c->input(0); + ShapeHandle unused; + TF_RETURN_IF_ERROR(c->WithRank(input_inner_values_shape, 1, &unused)); + + // Check rank of input_splits + ShapeHandle splits_shape = c->input(1); + TF_RETURN_IF_ERROR(c->WithRank(splits_shape, 1, &unused)); + + // Output shape is a 1-D tensor with size equal to number of splits. + std::vector dims(1); + TF_RETURN_IF_ERROR(c->Subtract(c->Dim(splits_shape, 0), 1, &dims[0])); + c->set_output(0, c->MakeShape(dims)); + + return Status::OK(); + }); + REGISTER_OP("UnicodeTranscode") .Input("input: string") .Output("output: string") @@ -259,4 +295,28 @@ REGISTER_OP("UnicodeTranscode") .Attr("replacement_char: int = 65533") // 0xFFFD unicode replacement char .Attr("replace_control_characters: bool = false") .SetShapeFn(shape_inference::UnchangedShape); + +REGISTER_OP("UnicodeDecodeWithOffsets") + .Input("input: string") + .Output("row_splits: int64") + .Output("char_values: int32") + .Output("char_to_byte_starts: int64") + .Attr("input_encoding: string") + .Attr("errors: {'strict', 'replace', 'ignore'} = 'replace'") + .Attr("replacement_char: int = 65533") // 0xFFFD unicode replacement char + .Attr("replace_control_characters: bool = false") + .SetShapeFn([](InferenceContext* c) { + // row_splits.shape == [input.size() + 1] + DimensionHandle num_row_splits; + DimensionHandle input_size = c->NumElements(c->input(0)); + TF_RETURN_IF_ERROR(c->Add(input_size, 1, &num_row_splits)); + c->set_output(0, c->Vector(num_row_splits)); + + // char_values.shape == offset_values.shape == [num_chars] + DimensionHandle num_chars = c->UnknownDim(); + c->set_output(1, c->Vector(num_chars)); + c->set_output(2, c->Vector(num_chars)); + return Status::OK(); + }); + } // namespace tensorflow diff --git a/tensorflow/core/ops/tensor_forest_ops.cc b/tensorflow/core/ops/tensor_forest_ops.cc new file mode 100644 index 0000000000..b4b6ba318e --- /dev/null +++ b/tensorflow/core/ops/tensor_forest_ops.cc @@ -0,0 +1,79 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "tensorflow/core/framework/common_shape_fns.h" +#include "tensorflow/core/framework/op.h" +#include "tensorflow/core/framework/resource_mgr.h" +#include "tensorflow/core/framework/shape_inference.h" + +namespace tensorflow { + +REGISTER_RESOURCE_HANDLE_OP(TensorForestTreeResource); + +REGISTER_OP("TensorForestTreeIsInitializedOp") + .Input("tree_handle: resource") + .Output("is_initialized: bool") + .SetShapeFn([](shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle unused_input; + TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 0, &unused_input)); + c->set_output(0, c->Scalar()); + return Status::OK(); + }); + +REGISTER_OP("TensorForestCreateTreeVariable") + .Input("tree_handle: resource") + .Input("tree_config: string") + .SetShapeFn(tensorflow::shape_inference::NoOutputs); + +REGISTER_OP("TensorForestTreeSerialize") + .Input("tree_handle: resource") + .Output("tree_config: string") + .SetShapeFn(tensorflow::shape_inference::ScalarShape); + +REGISTER_OP("TensorForestTreeDeserialize") + .Input("tree_handle: resource") + .Input("tree_config: string") + .SetShapeFn([](shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle unused_input; + TF_RETURN_IF_ERROR(c->WithRank(c->input(0), 0, &unused_input)); + return Status::OK(); + }); + +REGISTER_OP("TensorForestTreeSize") + .Input("tree_handle: resource") + .Output("tree_size: int32") + .SetShapeFn(tensorflow::shape_inference::ScalarShape); + +REGISTER_OP("TensorForestTreePredict") + .Attr("logits_dimension: int") + .Input("tree_handle: resource") + .Input("dense_features: float") + .Output("logits: float") + .SetShapeFn([](tensorflow::shape_inference::InferenceContext* c) { + shape_inference::ShapeHandle shape_handle; + shape_inference::DimensionHandle batch_size = c->UnknownDim(); + + TF_RETURN_IF_ERROR(c->WithRank(c->input(1), 2, &shape_handle)); + + batch_size = c->Dim(shape_handle, 0); + + int logits_dimension; + TF_RETURN_IF_ERROR(c->GetAttr("logits_dimension", &logits_dimension)); + c->set_output(0, c->Matrix(batch_size, logits_dimension)); + return Status::OK(); + }); +} // namespace tensorflow diff --git a/tensorflow/core/ops/training_ops.cc b/tensorflow/core/ops/training_ops.cc index 94ff092a85..995ed42d53 100644 --- a/tensorflow/core/ops/training_ops.cc +++ b/tensorflow/core/ops/training_ops.cc @@ -685,6 +685,34 @@ REGISTER_OP("ResourceSparseApplyMomentum") return ApplyMomentumShapeFn(c, true /* sparse */); }); +REGISTER_OP("ResourceApplyKerasMomentum") + .Input("var: resource") + .Input("accum: resource") + .Input("lr: T") + .Input("grad: T") + .Input("momentum: T") + .Attr("T: numbertype") + .Attr("use_locking: bool = false") + .Attr("use_nesterov: bool = false") + .SetShapeFn([](InferenceContext* c) { + return ApplyMomentumShapeFn(c, false /* sparse */); + }); + +REGISTER_OP("ResourceSparseApplyKerasMomentum") + .Input("var: resource") + .Input("accum: resource") + .Input("lr: T") + .Input("grad: T") + .Input("indices: Tindices") + .Input("momentum: T") + .Attr("T: numbertype") + .Attr("Tindices: {int32, int64}") + .Attr("use_locking: bool = false") + .Attr("use_nesterov: bool = false") + .SetShapeFn([](InferenceContext* c) { + return ApplyMomentumShapeFn(c, true /* sparse */); + }); + static Status ApplyAdamShapeFn(InferenceContext* c, bool sparse) { ShapeHandle unused; ShapeHandle s = ShapeOrHandleShape(c, 0); // var @@ -741,6 +769,44 @@ REGISTER_OP("ResourceApplyAdam") return ApplyAdamShapeFn(c, false /* sparse */); }); +static Status ApplyAdamWithAmsgradShapeFn(InferenceContext* c, bool sparse) { + ShapeHandle unused; + ShapeHandle s = ShapeOrHandleShape(c, 0); // var + TF_RETURN_IF_ERROR(c->Merge(s, ShapeOrHandleShape(c, 1), &s)); // m + TF_RETURN_IF_ERROR(c->Merge(s, ShapeOrHandleShape(c, 2), &s)); // v + TF_RETURN_IF_ERROR(c->Merge(s, ShapeOrHandleShape(c, 3), &s)); // vhat + TF_RETURN_IF_ERROR(c->WithRank(c->input(4), 0, &unused)); // beta1_power + TF_RETURN_IF_ERROR(c->WithRank(c->input(5), 0, &unused)); // beta2_power + TF_RETURN_IF_ERROR(c->WithRank(c->input(6), 0, &unused)); // lr + TF_RETURN_IF_ERROR(c->WithRank(c->input(7), 0, &unused)); // beta1 + TF_RETURN_IF_ERROR(c->WithRank(c->input(8), 0, &unused)); // beta2 + TF_RETURN_IF_ERROR(c->WithRank(c->input(9), 0, &unused)); // epsilon + TF_RETURN_IF_ERROR( + HandleGradAndIndicesInputs(c, sparse, 10 /* grad_idx */, &s)); + if (c->num_outputs() > 0) { + c->set_output(0, s); + } + return Status::OK(); +} + +REGISTER_OP("ResourceApplyAdamWithAmsgrad") + .Input("var: resource") + .Input("m: resource") + .Input("v: resource") + .Input("vhat: resource") + .Input("beta1_power: T") + .Input("beta2_power: T") + .Input("lr: T") + .Input("beta1: T") + .Input("beta2: T") + .Input("epsilon: T") + .Input("grad: T") + .Attr("T: numbertype") + .Attr("use_locking: bool = false") + .SetShapeFn([](InferenceContext* c) { + return ApplyAdamWithAmsgradShapeFn(c, false /* sparse */); + }); + static Status ApplyAdaMaxShapeFn(InferenceContext* c, bool sparse) { ShapeHandle unused; ShapeHandle s = ShapeOrHandleShape(c, 0); // var diff --git a/tensorflow/core/platform/cpu_feature_guard.cc b/tensorflow/core/platform/cpu_feature_guard.cc index 9d00aa7b7f..2efe0c0876 100644 --- a/tensorflow/core/platform/cpu_feature_guard.cc +++ b/tensorflow/core/platform/cpu_feature_guard.cc @@ -41,7 +41,7 @@ void CheckFeatureOrDie(CPUFeature feature, const string& feature_name) { } } -// Check if CPU feature is inclued in the TensorFlow binary. +// Check if CPU feature is included in the TensorFlow binary. void CheckIfFeatureUnused(CPUFeature feature, const string& feature_name, string& missing_instructions) { if (TestCPUFeature(feature)) { diff --git a/tensorflow/core/platform/default/build_config.bzl b/tensorflow/core/platform/default/build_config.bzl index 3a4415f229..0428715130 100644 --- a/tensorflow/core/platform/default/build_config.bzl +++ b/tensorflow/core/platform/default/build_config.bzl @@ -543,6 +543,9 @@ def tf_additional_proto_srcs(): def tf_additional_human_readable_json_deps(): return [] +def tf_additional_logger_deps(): + return [] + def tf_additional_all_protos(): return ["//tensorflow/core:protos_all"] diff --git a/tensorflow/core/platform/default/device_tracer.cc b/tensorflow/core/platform/default/device_tracer.cc index cf8b477b83..8351362e05 100644 --- a/tensorflow/core/platform/default/device_tracer.cc +++ b/tensorflow/core/platform/default/device_tracer.cc @@ -297,19 +297,16 @@ CUPTIManager *GetCUPTIManager() { // for the duration of the CUPTI API callback. TF_STATIC_THREAD_LOCAL_POD(const char *, tls_current_annotation); -class DeviceTracerImpl : public DeviceTracer, - public CUPTIClient, - public tracing::TraceCollector { +class TraceCollectorImpl : public tracing::TraceCollector { public: - DeviceTracerImpl(CUPTIManager *cupti_manager); - ~DeviceTracerImpl() override; + TraceCollectorImpl() { tracing::SetTraceCollector(this); } - // DeviceTracer interface: - Status Start() override; - Status Stop() override; - Status Collect(StepStatsCollector *collector) override; + ~TraceCollectorImpl() override { + DCHECK(!active_trace_session_) + << "Unexpected active trace session detected. "; + } - // tracing::TraceCollector interface: + // Note the method can be called after a call to Stop(). virtual std::unique_ptr CreateAnnotationHandle( StringPiece name_part1, StringPiece name_part2) const { struct Impl : public tracing::TraceCollector::Handle { @@ -332,8 +329,7 @@ class DeviceTracerImpl : public DeviceTracer, } bool IsEnabledForAnnotations() const override { - // We are always enabled for 'Annotations'. - return true; + return active_trace_session_.load(std::memory_order_relaxed); } bool IsEnabledForActivities(bool is_expensive) const override { @@ -341,6 +337,36 @@ class DeviceTracerImpl : public DeviceTracer, return false; } + void Start() { + DCHECK(!active_trace_session_) + << "Unexpected active trace session detected. "; + active_trace_session_ = true; + } + + void Stop() { + DCHECK(active_trace_session_) << "No active trace session detected. "; + active_trace_session_ = false; + } + + private: + std::atomic active_trace_session_; +}; + +TraceCollectorImpl *GlobalDefaultTraceCollector() { + static auto *instance = new TraceCollectorImpl(); + return instance; +} + +class DeviceTracerImpl : public DeviceTracer, public CUPTIClient { + public: + DeviceTracerImpl(CUPTIManager *cupti_manager); + ~DeviceTracerImpl() override; + + // DeviceTracer interface: + Status Start() override; + Status Stop() override; + Status Collect(StepStatsCollector *collector) override; + protected: // This callback is used exclusively by CUPTIManager. friend class CUPTIManager; @@ -430,7 +456,7 @@ Status DeviceTracerImpl::Start() { } // Register as a TraceEngine to receive ScopedAnnotations. - tracing::SetTraceCollector(this); + GlobalDefaultTraceCollector()->Start(); // Intercept launch and memcpy calls to capture the Op name annotation. // TODO(pbar) Add callbacks for memcpy variants. @@ -478,7 +504,8 @@ Status DeviceTracerImpl::Stop() { return Status::OK(); } CUPTI_CALL(Unsubscribe(subscriber_)); - tracing::SetTraceCollector(nullptr); + GlobalDefaultTraceCollector()->Stop(); + TF_RETURN_IF_ERROR(cupti_manager_->DisableTrace()); end_walltime_us_ = NowInUsec(); CUPTI_CALL(GetTimestamp(&end_timestamp_)); diff --git a/tensorflow/core/platform/default/logger.cc b/tensorflow/core/platform/default/logger.cc new file mode 100644 index 0000000000..54b1a1a67c --- /dev/null +++ b/tensorflow/core/platform/default/logger.cc @@ -0,0 +1,34 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/platform/logger.h" + +#include "tensorflow/core/platform/logging.h" + +namespace tensorflow { + +Logger* Logger::Singleton() { + class DefaultLogger : public Logger { + private: + void DoLogProto(google::protobuf::Any* proto) override { + VLOG(2) << proto->ShortDebugString(); + } + void DoFlush() override {} + }; + static Logger* instance = new DefaultLogger(); + return instance; +} + +} // namespace tensorflow diff --git a/tensorflow/core/platform/default/logging.cc b/tensorflow/core/platform/default/logging.cc index 34db490106..26bd8542fd 100644 --- a/tensorflow/core/platform/default/logging.cc +++ b/tensorflow/core/platform/default/logging.cc @@ -21,18 +21,18 @@ limitations under the License. #include #include #include -#include #endif #include +#include #include +#include +#include + namespace tensorflow { namespace internal { -LogMessage::LogMessage(const char* fname, int line, int severity) - : fname_(fname), line_(line), severity_(severity) {} - #if defined(PLATFORM_POSIX_ANDROID) void LogMessage::GenerateLogMessage() { int android_log_level; @@ -94,55 +94,156 @@ void LogMessage::GenerateLogMessage() { namespace { +int ParseInteger(const char* str, size_t size) { + // Ideally we would use env_var / safe_strto64, but it is + // hard to use here without pulling in a lot of dependencies, + // so we use std:istringstream instead + string integer_str(str, size); + std::istringstream ss(integer_str); + int level = 0; + ss >> level; + return level; +} + // Parse log level (int64) from environment variable (char*) int64 LogLevelStrToInt(const char* tf_env_var_val) { if (tf_env_var_val == nullptr) { return 0; } + return ParseInteger(tf_env_var_val, strlen(tf_env_var_val)); +} - // Ideally we would use env_var / safe_strto64, but it is - // hard to use here without pulling in a lot of dependencies, - // so we use std:istringstream instead - string min_log_level(tf_env_var_val); - std::istringstream ss(min_log_level); - int64 level; - if (!(ss >> level)) { - // Invalid vlog level setting, set level to default (0) - level = 0; +// Using StringPiece breaks Windows build. +struct StringData { + struct Hasher { + size_t operator()(const StringData& sdata) const { + // For dependency reasons, we cannot use hash.h here. Use DBJHash instead. + size_t hash = 5381; + const char* data = sdata.data; + for (const char* top = data + sdata.size; data < top; ++data) { + hash = ((hash << 5) + hash) + (*data); + } + return hash; + } + }; + + StringData() = default; + StringData(const char* data, size_t size) : data(data), size(size) {} + + bool operator==(const StringData& rhs) const { + return size == rhs.size && memcmp(data, rhs.data, size) == 0; } - return level; + const char* data = nullptr; + size_t size = 0; +}; + +using VmoduleMap = std::unordered_map; + +// Returns a mapping from module name to VLOG level, derived from the +// TF_CPP_VMOUDLE environment variable; ownership is transferred to the caller. +VmoduleMap* VmodulesMapFromEnv() { + // The value of the env var is supposed to be of the form: + // "foo=1,bar=2,baz=3" + const char* env = getenv("TF_CPP_VMODULE"); + if (env == nullptr) { + // If there is no TF_CPP_VMODULE configuration (most common case), return + // nullptr so that the ShouldVlogModule() API can fast bail out of it. + return nullptr; + } + // The memory returned by getenv() can be invalidated by following getenv() or + // setenv() calls. And since we keep references to it in the VmoduleMap in + // form of StringData objects, make a copy of it. + const char* env_data = strdup(env); + VmoduleMap* result = new VmoduleMap(); + while (true) { + const char* eq = strchr(env_data, '='); + if (eq == nullptr) { + break; + } + const char* after_eq = eq + 1; + + // Comma either points at the next comma delimiter, or at a null terminator. + // We check that the integer we parse ends at this delimiter. + const char* comma = strchr(after_eq, ','); + const char* new_env_data; + if (comma == nullptr) { + comma = strchr(after_eq, '\0'); + new_env_data = comma; + } else { + new_env_data = comma + 1; + } + (*result)[StringData(env_data, eq - env_data)] = + ParseInteger(after_eq, comma - after_eq); + env_data = new_env_data; + } + return result; } } // namespace int64 MinLogLevelFromEnv() { + // We don't want to print logs during fuzzing as that would slow fuzzing down + // by almost 2x. So, if we are in fuzzing mode (not just running a test), we + // return a value so that nothing is actually printed. Since LOG uses >= + // (see ~LogMessage in this file) to see if log messages need to be printed, + // the value we're interested on to disable printing is the maximum severity. + // See also http://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + return tensorflow::NUM_SEVERITIES; +#else const char* tf_env_var_val = getenv("TF_CPP_MIN_LOG_LEVEL"); return LogLevelStrToInt(tf_env_var_val); +#endif } int64 MinVLogLevelFromEnv() { + // We don't want to print logs during fuzzing as that would slow fuzzing down + // by almost 2x. So, if we are in fuzzing mode (not just running a test), we + // return a value so that nothing is actually printed. Since VLOG uses <= + // (see VLOG_IS_ON in logging.h) to see if log messages need to be printed, + // the value we're interested on to disable printing is 0. + // See also http://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + return 0; +#else const char* tf_env_var_val = getenv("TF_CPP_MIN_VLOG_LEVEL"); return LogLevelStrToInt(tf_env_var_val); +#endif } +LogMessage::LogMessage(const char* fname, int line, int severity) + : fname_(fname), line_(line), severity_(severity) {} + LogMessage::~LogMessage() { // Read the min log level once during the first call to logging. static int64 min_log_level = MinLogLevelFromEnv(); - if (TF_PREDICT_TRUE(severity_ >= min_log_level)) GenerateLogMessage(); + if (severity_ >= min_log_level) { + GenerateLogMessage(); + } } int64 LogMessage::MinVLogLevel() { - // We don't want to print logs during fuzzing as that would slow fuzzing down - // by almost 2x. So, if we are in fuzzing mode (not just running a test), we - // return maximum value so that nothing is actually printed - // See also http://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode -#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - return tensorflow::NUM_SEVERITIES; -#else static int64 min_vlog_level = MinVLogLevelFromEnv(); return min_vlog_level; -#endif +} + +bool LogMessage::VmoduleActivated(const char* fname, int level) { + if (level <= MinVLogLevel()) { + return true; + } + static VmoduleMap* vmodules = VmodulesMapFromEnv(); + if (TF_PREDICT_TRUE(vmodules == nullptr)) { + return false; + } + const char* last_slash = strrchr(fname, '/'); + const char* module_start = last_slash == nullptr ? fname : last_slash + 1; + const char* dot_after = strchr(module_start, '.'); + const char* module_limit = + dot_after == nullptr ? strchr(fname, '\0') : dot_after; + StringData module(module_start, module_limit - module_start); + auto it = vmodules->find(module); + return it != vmodules->end() && it->second >= level; } LogMessageFatal::LogMessageFatal(const char* file, int line) diff --git a/tensorflow/core/platform/default/logging.h b/tensorflow/core/platform/default/logging.h index 08a692fff7..bb8735ed32 100644 --- a/tensorflow/core/platform/default/logging.h +++ b/tensorflow/core/platform/default/logging.h @@ -46,6 +46,17 @@ class LogMessage : public std::basic_ostringstream { // but VLOG(3) will not. Defaults to 0. static int64 MinVLogLevel(); + // Returns whether VLOG level lvl is activated for the file fname. + // + // E.g. if the environment variable TF_CPP_VMODULE contains foo=3 and fname is + // foo.cc and lvl is <= 3, this will return true. It will also return true if + // the level is lower or equal to TF_CPP_MIN_VLOG_LEVEL (default zero). + // + // It is expected that the result of this query will be cached in the VLOG-ing + // call site to avoid repeated lookups. This routine performs a hash-map + // access against the VLOG-ing specification provided by the env var. + static bool VmoduleActivated(const char* fname, int level); + protected: void GenerateLogMessage(); @@ -55,6 +66,13 @@ class LogMessage : public std::basic_ostringstream { int severity_; }; +// Uses the lower operator & precedence to voidify a LogMessage reference, so +// that the ternary VLOG() implementation is balanced, type wise. +struct Voidifier { + template + void operator&(const T&)const {} +}; + // LogMessageFatal ensures the process will exit in failure after // logging this message. class LogMessageFatal : public LogMessage { @@ -77,18 +95,30 @@ class LogMessageFatal : public LogMessage { #define LOG(severity) _TF_LOG_##severity #ifdef IS_MOBILE_PLATFORM + // Turn VLOG off when under mobile devices for considerations of binary size. #define VLOG_IS_ON(lvl) ((lvl) <= 0) + #else -// Otherwise, Set TF_CPP_MIN_VLOG_LEVEL environment to update minimum log level -// of VLOG -#define VLOG_IS_ON(lvl) \ - ((lvl) <= ::tensorflow::internal::LogMessage::MinVLogLevel()) + +// Otherwise, set TF_CPP_MIN_VLOG_LEVEL environment to update minimum log level +// of VLOG, or TF_CPP_VMODULE to set the minimum log level for individual +// translation units. +#define VLOG_IS_ON(lvl) \ + (([](int level, const char* fname) { \ + static const bool vmodule_activated = \ + ::tensorflow::internal::LogMessage::VmoduleActivated(fname, level); \ + return vmodule_activated; \ + })(lvl, __FILE__)) + #endif -#define VLOG(lvl) \ - if (TF_PREDICT_FALSE(VLOG_IS_ON(lvl))) \ - ::tensorflow::internal::LogMessage(__FILE__, __LINE__, tensorflow::INFO) +#define VLOG(level) \ + TF_PREDICT_TRUE(!VLOG_IS_ON(level)) \ + ? (void)0 \ + : ::tensorflow::internal::Voidifier() & \ + ::tensorflow::internal::LogMessage(__FILE__, __LINE__, \ + tensorflow::INFO) // CHECK dies with a fatal error if condition is not true. It is *not* // controlled by NDEBUG, so the check will be executed regardless of diff --git a/tensorflow/core/platform/env.h b/tensorflow/core/platform/env.h index 5732271f15..7374fccdc2 100644 --- a/tensorflow/core/platform/env.h +++ b/tensorflow/core/platform/env.h @@ -28,6 +28,7 @@ limitations under the License. #include "tensorflow/core/platform/file_system.h" #include "tensorflow/core/platform/macros.h" #include "tensorflow/core/platform/mutex.h" +#include "tensorflow/core/platform/numa.h" #include "tensorflow/core/platform/protobuf.h" #include "tensorflow/core/platform/types.h" @@ -395,6 +396,7 @@ struct ThreadOptions { size_t stack_size = 0; // 0: use system default value /// Guard area size to use near thread stacks to use (in bytes) size_t guard_size = 0; // 0: use system default value + int numa_node = port::kNUMANoAffinity; }; /// A utility routine: copy contents of `src` in file system `src_fs` diff --git a/tensorflow/core/platform/logger.h b/tensorflow/core/platform/logger.h new file mode 100644 index 0000000000..5d304bea63 --- /dev/null +++ b/tensorflow/core/platform/logger.h @@ -0,0 +1,51 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_CORE_PLATFORM_LOGGER_H_ +#define TENSORFLOW_CORE_PLATFORM_LOGGER_H_ + +#include "google/protobuf/any.pb.h" +#include "tensorflow/core/platform/protobuf.h" + +namespace tensorflow { + +// Abstract logging interface. Contrary to logging.h, this class describes an +// interface, not a concrete logging mechanism. This is useful when we want to +// log anything to a non-local place, e.g. a database. +class Logger { + public: + static Logger* Singleton(); + + virtual ~Logger() = default; + + // Logs a typed proto. + template + void LogProto(const ProtoType& proto) { + google::protobuf::Any any; + any.PackFrom(proto); + DoLogProto(&any); + } + + // Flushes any pending log. Blocks until everything is flushed. + void Flush() { DoFlush(); } + + private: + virtual void DoLogProto(google::protobuf::Any* proto) = 0; + virtual void DoFlush() = 0; +}; + +} // namespace tensorflow + +#endif // TENSORFLOW_CORE_PLATFORM_LOGGER_H_ diff --git a/tensorflow/core/platform/numa_test.cc b/tensorflow/core/platform/numa_test.cc index 8b39ecd59c..91789efd1e 100644 --- a/tensorflow/core/platform/numa_test.cc +++ b/tensorflow/core/platform/numa_test.cc @@ -44,7 +44,7 @@ TEST(Numa, Malloc) { TEST(Numa, SetNodeAffinity) { // NOTE(tucker): This test is not reliable when executed under tap because - // the virtual machine may not have access to all of the availble NUMA + // the virtual machine may not have access to all of the available NUMA // nodes. Not sure what to do about that. EXPECT_EQ(-1, port::NUMAGetThreadNodeAffinity()); if (port::NUMAEnabled()) { diff --git a/tensorflow/core/platform/platform_strings.cc b/tensorflow/core/platform/platform_strings.cc new file mode 100644 index 0000000000..c1852633d5 --- /dev/null +++ b/tensorflow/core/platform/platform_strings.cc @@ -0,0 +1,64 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/platform/platform_strings.h" + +#include +#include + +#include +#include + +#include "tensorflow/core/lib/core/status.h" + +namespace tensorflow { + +int GetPlatformStrings(const std::string& path, + std::vector* found) { + int result; + FILE* ifp = fopen(path.c_str(), "rb"); + if (ifp != nullptr) { + static const char prefix[] = TF_PLAT_STR_MAGIC_PREFIX_; + int first_char = prefix[1]; + int last_char = -1; + int c; + while ((c = getc(ifp)) != EOF) { + if (c == first_char && last_char == 0) { + int i = 2; + while (prefix[i] != 0 && (c = getc(ifp)) == prefix[i]) { + i++; + } + if (prefix[i] == 0) { + std::string str; + while ((c = getc(ifp)) != EOF && c != 0) { + str.push_back(c); + } + if (!str.empty()) { + found->push_back(str); + } + } + } + last_char = c; + } + + result = (ferror(ifp) == 0) ? 0 : errno; + fclose(ifp); + } else { + result = errno; + } + return result; +} + +} // namespace tensorflow diff --git a/tensorflow/core/platform/platform_strings.h b/tensorflow/core/platform/platform_strings.h new file mode 100644 index 0000000000..5b1dbd130e --- /dev/null +++ b/tensorflow/core/platform/platform_strings.h @@ -0,0 +1,364 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_CORE_PLATFORM_PLATFORM_STRINGS_H_ +#define TENSORFLOW_CORE_PLATFORM_PLATFORM_STRINGS_H_ + +// This header defines the macro TF_PLATFORM_STRINGS() which should be used +// once in each dynamically loadable TensorFlow module. It embeds static +// strings into the compilation unit that allow TensorFlow to determine what +// compilation options were in effect when the compilation unit was built. All +// compilation units within the same dynamically loadable library should be +// built with the same options (or at least, the strings should be embedded in +// the compilation unit built with the most restrictive options). + +// The platform strings embedded into a binary may be retrieved with the +// GetPlatformStrings function. + +// Rationale: +// We wish to load only those libraries that this CPU can execute. For +// example, we should not load a library compiled with avx256 instructions on a +// CPU that cannot execute them. +// +// One might think that one could dlopen() the library, and call a routine that +// would return which cpu type it was compiled for. Alas, this does not work, +// because at dlopen() time, a library containing C++ will execute constructors +// of class variables with static storage class. Even code that looks +// innocuous may use optional platform-specific instructions. For example, +// the fastest way to zero a region of memory might use optional instructions. +// +// One might think one could run a tool such as "objdump" to read flags from +// the libraries' headers, or perhaps disassemble each library to look for +// particular instructions. Unfortunately, the desired flags are not present +// in the headers, and disassembly can be prohibitively slow ("objdump -d" is +// very slow, for example). Moreover, a tool to examine the library may not +// be present on the system unless the user has installed special packages (for +// example, on Windows). +// +// Instead, we adopt a crude but straightforward solution: We require +// developers to use the macro TF_PLATFORM_STRINGS() in their library, to +// embed the compilation options as constant strings. The compiler's +// predefined macros pick which strings are included. We then search for the +// strings in the files, and then dlopen() only those libraries that have or +// lack strings as needed. +// +// We adopt the approach of placing in the binary a fairly raw copy of the +// predefined macros, rather than trying to interpret them in complex ways at +// compile time. This allows the loading binary to alter its interpretation of +// the strings without library developers having to recompile. + +#include + +#include +#include + +// Aside from the header guard, the internal macros defined here have the form: +// TF_PLAT_STR_* + +// If a macro is removed from the list of tested macros, the major version in +// the following version number should be incremented, and the minor version +// set to zero. Otherwise, if a macro is added to the list of tested macros, +// the minor number should be incremented. +#define TF_PLAT_STR_VERSION_ "1.0" + +// Prefix of each option string indicator in the binary. +// After the prefix, such strings have the form: +// [A-Za-z_0-9]= +// followed by a terminating nul. To simplify searching, this prefix is all +// ASCII, starts with a nul, and contains no character twice. +#define TF_PLAT_STR_MAGIC_PREFIX_ "\0S\\s\":^p*L}" + +// A helper macro for TF_PLAT_STR_AS_STR_(). +#define TF_PLAT_STR_STR_1_(x) #x + +// Yield a constant string corresponding to x, after macro expansion. +#define TF_PLAT_STR_AS_STR_(x) TF_PLAT_STR_STR_1_(x) + +// An empty definition to make lists more uniform. +#define TF_PLAT_STR_TERMINATOR_ + +// TF_PLAT_STR_(x) introduces a constant string indicating whether a +// particular compilation option has been turned on. +// +// In gcc and clang, we might imagine using something like +// #define TF_PLAT_STR_(x) \ +// (sizeof (#x) != sizeof (TF_PLAT_STR_AS_STR_ (x))? \ +// TF_PLAT_STR_MAGIC_PREFIX_ #x "=" TF_PLAT_STR_AS_STR_ (x) : \ +// TF_PLAT_STR_MAGIC_PREFIX_ #x "=0"), +// but some compilers (notably MSVC) place both "foo" and "bar" in the binary +// when presented with +// (true? "foo" : "bar") +// so we must use #if to select the strings we need, which is rather verbose. +#define TF_PLAT_STR_(x) TF_PLAT_STR_MAGIC_PREFIX_ #x "=" TF_PLAT_STR_AS_STR_(x) + +// Include the #if machinery that sets the macros used below. +// platform_strings_computed.h can be generated by filtering this header file +// through: +// awk ' +// header == "" { print; } +// /\*\// && header == "" { +// print "// Generated from platform_strings.h."; +// print ""; +// print "#ifndef TENSORFLOW_CORE_PLATFORM_PLATFORM_STRINGS_COMPUTED_H_"; +// print "#define TENSORFLOW_CORE_PLATFORM_PLATFORM_STRINGS_COMPUTED_H_"; +// print ""; +// header = 1; +// } +// /^#define TF_PLAT_STR_LIST_[a-zA-Z0-9_]*\(\) *\\$/ { active = 1; } +// /TF_PLAT_STR_TERMINATOR_/ { active = 0; } +// /^ *TF_PLAT_STR_[A-Za-z0-9_]* *\\$/ && active { +// x = $0; +// sub(/^ *TF_PLAT_STR_/, "", x); +// sub(/ *\\$/, "", x); +// printf ("#if defined(%s)\n", x); +// printf ("#define TF_PLAT_STR_%s TF_PLAT_STR_(%s)\n", x, x); +// printf ("#else\n"); +// printf ("#define TF_PLAT_STR_%s\n", x); +// printf ("#endif\n"); +// } +// END { +// print ""; +// print "#endif // TENSORFLOW_CORE_PLATFORM_PLATFORM_STRINGS_COMPUTED_H_"; +// }' +#include "tensorflow/core/platform/platform_strings_computed.h" + +// clang-format butchers the following lines. +// clang-format off + +// x86_64 and x86_32 optional features. +#define TF_PLAT_STR_LIST___x86_64__() \ + TF_PLAT_STR__M_IX86_FP \ + TF_PLAT_STR__NO_PREFETCHW \ + TF_PLAT_STR___3dNOW_A__ \ + TF_PLAT_STR___3dNOW__ \ + TF_PLAT_STR___ABM__ \ + TF_PLAT_STR___ADX__ \ + TF_PLAT_STR___AES__ \ + TF_PLAT_STR___AVX2__ \ + TF_PLAT_STR___AVX512BW__ \ + TF_PLAT_STR___AVX512CD__ \ + TF_PLAT_STR___AVX512DQ__ \ + TF_PLAT_STR___AVX512ER__ \ + TF_PLAT_STR___AVX512F__ \ + TF_PLAT_STR___AVX512IFMA__ \ + TF_PLAT_STR___AVX512PF__ \ + TF_PLAT_STR___AVX512VBMI__ \ + TF_PLAT_STR___AVX512VL__ \ + TF_PLAT_STR___AVX__ \ + TF_PLAT_STR___BMI2__ \ + TF_PLAT_STR___BMI__ \ + TF_PLAT_STR___CLFLUSHOPT__ \ + TF_PLAT_STR___CLZERO__ \ + TF_PLAT_STR___F16C__ \ + TF_PLAT_STR___FMA4__ \ + TF_PLAT_STR___FMA__ \ + TF_PLAT_STR___FP_FAST_FMA \ + TF_PLAT_STR___FP_FAST_FMAF \ + TF_PLAT_STR___FSGSBASE__ \ + TF_PLAT_STR___FXSR__ \ + TF_PLAT_STR___LWP__ \ + TF_PLAT_STR___LZCNT__ \ + TF_PLAT_STR___MMX__ \ + TF_PLAT_STR___MWAITX__ \ + TF_PLAT_STR___PCLMUL__ \ + TF_PLAT_STR___PKU__ \ + TF_PLAT_STR___POPCNT__ \ + TF_PLAT_STR___PRFCHW__ \ + TF_PLAT_STR___RDRND__ \ + TF_PLAT_STR___RDSEED__ \ + TF_PLAT_STR___RTM__ \ + TF_PLAT_STR___SHA__ \ + TF_PLAT_STR___SSE2_MATH__ \ + TF_PLAT_STR___SSE2__ \ + TF_PLAT_STR___SSE_MATH__ \ + TF_PLAT_STR___SSE__ \ + TF_PLAT_STR___SSE3__ \ + TF_PLAT_STR___SSE4A__ \ + TF_PLAT_STR___SSE4_1__ \ + TF_PLAT_STR___SSE4_2__ \ + TF_PLAT_STR___SSSE3__ \ + TF_PLAT_STR___TBM__ \ + TF_PLAT_STR___XOP__ \ + TF_PLAT_STR___XSAVEC__ \ + TF_PLAT_STR___XSAVEOPT__ \ + TF_PLAT_STR___XSAVES__ \ + TF_PLAT_STR___XSAVE__ \ + TF_PLAT_STR_TERMINATOR_ + +// PowerPC (64- and 32-bit) optional features. +#define TF_PLAT_STR_LIST___powerpc64__() \ + TF_PLAT_STR__SOFT_DOUBLE \ + TF_PLAT_STR__SOFT_FLOAT \ + TF_PLAT_STR___ALTIVEC__ \ + TF_PLAT_STR___APPLE_ALTIVEC__ \ + TF_PLAT_STR___CRYPTO__ \ + TF_PLAT_STR___FLOAT128_HARDWARE__ \ + TF_PLAT_STR___FLOAT128_TYPE__ \ + TF_PLAT_STR___FP_FAST_FMA \ + TF_PLAT_STR___FP_FAST_FMAF \ + TF_PLAT_STR___HTM__ \ + TF_PLAT_STR___NO_FPRS__ \ + TF_PLAT_STR___NO_LWSYNC__ \ + TF_PLAT_STR___POWER8_VECTOR__ \ + TF_PLAT_STR___POWER9_VECTOR__ \ + TF_PLAT_STR___PPC405__ \ + TF_PLAT_STR___QUAD_MEMORY_ATOMIC__ \ + TF_PLAT_STR___RECIPF__ \ + TF_PLAT_STR___RECIP_PRECISION__ \ + TF_PLAT_STR___RECIP__ \ + TF_PLAT_STR___RSQRTEF__ \ + TF_PLAT_STR___RSQRTE__ \ + TF_PLAT_STR___TM_FENCE__ \ + TF_PLAT_STR___UPPER_REGS_DF__ \ + TF_PLAT_STR___UPPER_REGS_SF__ \ + TF_PLAT_STR___VEC__ \ + TF_PLAT_STR___VSX__ \ + TF_PLAT_STR_TERMINATOR_ + +// aarch64 and 32-bit arm optional features +#define TF_PLAT_STR_LIST___aarch64__() \ + TF_PLAT_STR___ARM_ARCH \ + TF_PLAT_STR___ARM_FEATURE_CLZ \ + TF_PLAT_STR___ARM_FEATURE_CRC32 \ + TF_PLAT_STR___ARM_FEATURE_CRC32 \ + TF_PLAT_STR___ARM_FEATURE_CRYPTO \ + TF_PLAT_STR___ARM_FEATURE_DIRECTED_ROUNDING \ + TF_PLAT_STR___ARM_FEATURE_DSP \ + TF_PLAT_STR___ARM_FEATURE_FMA \ + TF_PLAT_STR___ARM_FEATURE_IDIV \ + TF_PLAT_STR___ARM_FEATURE_LDREX \ + TF_PLAT_STR___ARM_FEATURE_NUMERIC_MAXMIN \ + TF_PLAT_STR___ARM_FEATURE_QBIT \ + TF_PLAT_STR___ARM_FEATURE_QRDMX \ + TF_PLAT_STR___ARM_FEATURE_SAT \ + TF_PLAT_STR___ARM_FEATURE_SIMD32 \ + TF_PLAT_STR___ARM_FEATURE_UNALIGNED \ + TF_PLAT_STR___ARM_FP \ + TF_PLAT_STR___ARM_NEON_FP \ + TF_PLAT_STR___ARM_NEON__ \ + TF_PLAT_STR___ARM_WMMX \ + TF_PLAT_STR___IWMMXT2__ \ + TF_PLAT_STR___IWMMXT__ \ + TF_PLAT_STR___VFP_FP__ \ + TF_PLAT_STR_TERMINATOR_ + +// Generic features, including indication of architecture and OS. +// The _M_* macros are defined by Visual Studio. +// It doesn't define __LITTLE_ENDIAN__ or __BYTE_ORDER__; +// Windows is assumed to be little endian. +#define TF_PLAT_STR_LIST___generic__() \ + TF_PLAT_STR_TARGET_IPHONE_SIMULATOR \ + TF_PLAT_STR_TARGET_OS_IOS \ + TF_PLAT_STR_TARGET_OS_IPHONE \ + TF_PLAT_STR__MSC_VER \ + TF_PLAT_STR__M_ARM \ + TF_PLAT_STR__M_ARM64 \ + TF_PLAT_STR__M_ARM_ARMV7VE \ + TF_PLAT_STR__M_ARM_FP \ + TF_PLAT_STR__M_IX86 \ + TF_PLAT_STR__M_X64 \ + TF_PLAT_STR__WIN32 \ + TF_PLAT_STR__WIN64 \ + TF_PLAT_STR___ANDROID__ \ + TF_PLAT_STR___APPLE__ \ + TF_PLAT_STR___BYTE_ORDER__ \ + TF_PLAT_STR___CYGWIN__ \ + TF_PLAT_STR___FreeBSD__ \ + TF_PLAT_STR___LITTLE_ENDIAN__ \ + TF_PLAT_STR___NetBSD__ \ + TF_PLAT_STR___OpenBSD__ \ + TF_PLAT_STR_____MSYS__ \ + TF_PLAT_STR___aarch64__ \ + TF_PLAT_STR___alpha__ \ + TF_PLAT_STR___arm__ \ + TF_PLAT_STR___i386__ \ + TF_PLAT_STR___i686__ \ + TF_PLAT_STR___ia64__ \ + TF_PLAT_STR___linux__ \ + TF_PLAT_STR___mips32__ \ + TF_PLAT_STR___mips64__ \ + TF_PLAT_STR___powerpc64__ \ + TF_PLAT_STR___powerpc__ \ + TF_PLAT_STR___riscv___ \ + TF_PLAT_STR___s390x__ \ + TF_PLAT_STR___sparc64__ \ + TF_PLAT_STR___sparc__ \ + TF_PLAT_STR___x86_64__ \ + TF_PLAT_STR_TERMINATOR_ + +#if !defined(__x86_64__) && !defined(_M_X64) && \ + !defined(__i386__) && !defined(_M_IX86) +#undef TF_PLAT_STR_LIST___x86_64__ +#define TF_PLAT_STR_LIST___x86_64__() +#endif +#if !defined(__powerpc64__) && !defined(__powerpc__) +#undef TF_PLAT_STR_LIST___powerpc64__ +#define TF_PLAT_STR_LIST___powerpc64__() +#endif +#if !defined(__aarch64__) && !defined(_M_ARM64) && \ + !defined(__arm__) && !defined(_M_ARM) +#undef TF_PLAT_STR_LIST___aarch64__ +#define TF_PLAT_STR_LIST___aarch64__() +#endif + +// Macro to be used in each dynamically loadable library. +// +// The BSS global variable tf_cpu_option_global and the class +// instance tf_cpu_option_avoid_omit_class are needed to prevent +// compilers/linkers such as clang from omitting the static variable +// tf_cpu_option[], which would otherwise appear to be unused. We cannot make +// tf_cpu_option[] global, because we then might get multiply-defined symbols +// if TF_PLAT_STR() is used twice in the same library. +// (tf_cpu_option_global doesn't see such errors because it is +// defined in BSS, so multiple definitions are combined by the linker.) gcc's +// __attribute__((used)) is insufficient because it seems to be ignored by +// linkers. +#define TF_PLATFORM_STRINGS() \ + static const char tf_cpu_option[] = \ + TF_PLAT_STR_MAGIC_PREFIX_ "TF_PLAT_STR_VERSION=" TF_PLAT_STR_VERSION_ \ + TF_PLAT_STR_LIST___x86_64__() \ + TF_PLAT_STR_LIST___powerpc64__() \ + TF_PLAT_STR_LIST___aarch64__() \ + TF_PLAT_STR_LIST___generic__() \ + ; \ + const char *tf_cpu_option_global; \ + namespace { \ + class TFCPUOptionHelper { \ + public: \ + TFCPUOptionHelper() { \ + /* Compilers/linkers remove unused variables aggressively. The */ \ + /* following gyrations subvert most such optimizations. */ \ + tf_cpu_option_global = tf_cpu_option; \ + /* Nothing is printed because the string starts with a nul. */ \ + printf("%s", tf_cpu_option); \ + } \ + } tf_cpu_option_avoid_omit_class; \ + } /* anonymous namespace */ +// clang-format on + +namespace tensorflow { + +class Status; + +// Retrieves the platform strings from the file at the given path and appends +// them to the given vector. If the returned int is non-zero, an error occurred +// reading the file and vector may or may not be modified. The returned error +// code is suitable for use with strerror(). +int GetPlatformStrings(const std::string& path, + std::vector* found); + +} // namespace tensorflow + +#endif // TENSORFLOW_CORE_PLATFORM_PLATFORM_STRINGS_H_ diff --git a/tensorflow/core/platform/platform_strings_computed.h b/tensorflow/core/platform/platform_strings_computed.h new file mode 100644 index 0000000000..6a17f3bfc3 --- /dev/null +++ b/tensorflow/core/platform/platform_strings_computed.h @@ -0,0 +1,735 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +// Generated from platform_strings.h. + +#ifndef TENSORFLOW_CORE_PLATFORM_PLATFORM_STRINGS_COMPUTED_H_ +#define TENSORFLOW_CORE_PLATFORM_PLATFORM_STRINGS_COMPUTED_H_ + +#if defined(_M_IX86_FP) +#define TF_PLAT_STR__M_IX86_FP TF_PLAT_STR_(_M_IX86_FP) +#else +#define TF_PLAT_STR__M_IX86_FP +#endif +#if defined(_NO_PREFETCHW) +#define TF_PLAT_STR__NO_PREFETCHW TF_PLAT_STR_(_NO_PREFETCHW) +#else +#define TF_PLAT_STR__NO_PREFETCHW +#endif +#if defined(__3dNOW_A__) +#define TF_PLAT_STR___3dNOW_A__ TF_PLAT_STR_(__3dNOW_A__) +#else +#define TF_PLAT_STR___3dNOW_A__ +#endif +#if defined(__3dNOW__) +#define TF_PLAT_STR___3dNOW__ TF_PLAT_STR_(__3dNOW__) +#else +#define TF_PLAT_STR___3dNOW__ +#endif +#if defined(__ABM__) +#define TF_PLAT_STR___ABM__ TF_PLAT_STR_(__ABM__) +#else +#define TF_PLAT_STR___ABM__ +#endif +#if defined(__ADX__) +#define TF_PLAT_STR___ADX__ TF_PLAT_STR_(__ADX__) +#else +#define TF_PLAT_STR___ADX__ +#endif +#if defined(__AES__) +#define TF_PLAT_STR___AES__ TF_PLAT_STR_(__AES__) +#else +#define TF_PLAT_STR___AES__ +#endif +#if defined(__AVX2__) +#define TF_PLAT_STR___AVX2__ TF_PLAT_STR_(__AVX2__) +#else +#define TF_PLAT_STR___AVX2__ +#endif +#if defined(__AVX512BW__) +#define TF_PLAT_STR___AVX512BW__ TF_PLAT_STR_(__AVX512BW__) +#else +#define TF_PLAT_STR___AVX512BW__ +#endif +#if defined(__AVX512CD__) +#define TF_PLAT_STR___AVX512CD__ TF_PLAT_STR_(__AVX512CD__) +#else +#define TF_PLAT_STR___AVX512CD__ +#endif +#if defined(__AVX512DQ__) +#define TF_PLAT_STR___AVX512DQ__ TF_PLAT_STR_(__AVX512DQ__) +#else +#define TF_PLAT_STR___AVX512DQ__ +#endif +#if defined(__AVX512ER__) +#define TF_PLAT_STR___AVX512ER__ TF_PLAT_STR_(__AVX512ER__) +#else +#define TF_PLAT_STR___AVX512ER__ +#endif +#if defined(__AVX512F__) +#define TF_PLAT_STR___AVX512F__ TF_PLAT_STR_(__AVX512F__) +#else +#define TF_PLAT_STR___AVX512F__ +#endif +#if defined(__AVX512IFMA__) +#define TF_PLAT_STR___AVX512IFMA__ TF_PLAT_STR_(__AVX512IFMA__) +#else +#define TF_PLAT_STR___AVX512IFMA__ +#endif +#if defined(__AVX512PF__) +#define TF_PLAT_STR___AVX512PF__ TF_PLAT_STR_(__AVX512PF__) +#else +#define TF_PLAT_STR___AVX512PF__ +#endif +#if defined(__AVX512VBMI__) +#define TF_PLAT_STR___AVX512VBMI__ TF_PLAT_STR_(__AVX512VBMI__) +#else +#define TF_PLAT_STR___AVX512VBMI__ +#endif +#if defined(__AVX512VL__) +#define TF_PLAT_STR___AVX512VL__ TF_PLAT_STR_(__AVX512VL__) +#else +#define TF_PLAT_STR___AVX512VL__ +#endif +#if defined(__AVX__) +#define TF_PLAT_STR___AVX__ TF_PLAT_STR_(__AVX__) +#else +#define TF_PLAT_STR___AVX__ +#endif +#if defined(__BMI2__) +#define TF_PLAT_STR___BMI2__ TF_PLAT_STR_(__BMI2__) +#else +#define TF_PLAT_STR___BMI2__ +#endif +#if defined(__BMI__) +#define TF_PLAT_STR___BMI__ TF_PLAT_STR_(__BMI__) +#else +#define TF_PLAT_STR___BMI__ +#endif +#if defined(__CLFLUSHOPT__) +#define TF_PLAT_STR___CLFLUSHOPT__ TF_PLAT_STR_(__CLFLUSHOPT__) +#else +#define TF_PLAT_STR___CLFLUSHOPT__ +#endif +#if defined(__CLZERO__) +#define TF_PLAT_STR___CLZERO__ TF_PLAT_STR_(__CLZERO__) +#else +#define TF_PLAT_STR___CLZERO__ +#endif +#if defined(__F16C__) +#define TF_PLAT_STR___F16C__ TF_PLAT_STR_(__F16C__) +#else +#define TF_PLAT_STR___F16C__ +#endif +#if defined(__FMA4__) +#define TF_PLAT_STR___FMA4__ TF_PLAT_STR_(__FMA4__) +#else +#define TF_PLAT_STR___FMA4__ +#endif +#if defined(__FMA__) +#define TF_PLAT_STR___FMA__ TF_PLAT_STR_(__FMA__) +#else +#define TF_PLAT_STR___FMA__ +#endif +#if defined(__FP_FAST_FMA) +#define TF_PLAT_STR___FP_FAST_FMA TF_PLAT_STR_(__FP_FAST_FMA) +#else +#define TF_PLAT_STR___FP_FAST_FMA +#endif +#if defined(__FP_FAST_FMAF) +#define TF_PLAT_STR___FP_FAST_FMAF TF_PLAT_STR_(__FP_FAST_FMAF) +#else +#define TF_PLAT_STR___FP_FAST_FMAF +#endif +#if defined(__FSGSBASE__) +#define TF_PLAT_STR___FSGSBASE__ TF_PLAT_STR_(__FSGSBASE__) +#else +#define TF_PLAT_STR___FSGSBASE__ +#endif +#if defined(__FXSR__) +#define TF_PLAT_STR___FXSR__ TF_PLAT_STR_(__FXSR__) +#else +#define TF_PLAT_STR___FXSR__ +#endif +#if defined(__LWP__) +#define TF_PLAT_STR___LWP__ TF_PLAT_STR_(__LWP__) +#else +#define TF_PLAT_STR___LWP__ +#endif +#if defined(__LZCNT__) +#define TF_PLAT_STR___LZCNT__ TF_PLAT_STR_(__LZCNT__) +#else +#define TF_PLAT_STR___LZCNT__ +#endif +#if defined(__MMX__) +#define TF_PLAT_STR___MMX__ TF_PLAT_STR_(__MMX__) +#else +#define TF_PLAT_STR___MMX__ +#endif +#if defined(__MWAITX__) +#define TF_PLAT_STR___MWAITX__ TF_PLAT_STR_(__MWAITX__) +#else +#define TF_PLAT_STR___MWAITX__ +#endif +#if defined(__PCLMUL__) +#define TF_PLAT_STR___PCLMUL__ TF_PLAT_STR_(__PCLMUL__) +#else +#define TF_PLAT_STR___PCLMUL__ +#endif +#if defined(__PKU__) +#define TF_PLAT_STR___PKU__ TF_PLAT_STR_(__PKU__) +#else +#define TF_PLAT_STR___PKU__ +#endif +#if defined(__POPCNT__) +#define TF_PLAT_STR___POPCNT__ TF_PLAT_STR_(__POPCNT__) +#else +#define TF_PLAT_STR___POPCNT__ +#endif +#if defined(__PRFCHW__) +#define TF_PLAT_STR___PRFCHW__ TF_PLAT_STR_(__PRFCHW__) +#else +#define TF_PLAT_STR___PRFCHW__ +#endif +#if defined(__RDRND__) +#define TF_PLAT_STR___RDRND__ TF_PLAT_STR_(__RDRND__) +#else +#define TF_PLAT_STR___RDRND__ +#endif +#if defined(__RDSEED__) +#define TF_PLAT_STR___RDSEED__ TF_PLAT_STR_(__RDSEED__) +#else +#define TF_PLAT_STR___RDSEED__ +#endif +#if defined(__RTM__) +#define TF_PLAT_STR___RTM__ TF_PLAT_STR_(__RTM__) +#else +#define TF_PLAT_STR___RTM__ +#endif +#if defined(__SHA__) +#define TF_PLAT_STR___SHA__ TF_PLAT_STR_(__SHA__) +#else +#define TF_PLAT_STR___SHA__ +#endif +#if defined(__SSE2_MATH__) +#define TF_PLAT_STR___SSE2_MATH__ TF_PLAT_STR_(__SSE2_MATH__) +#else +#define TF_PLAT_STR___SSE2_MATH__ +#endif +#if defined(__SSE2__) +#define TF_PLAT_STR___SSE2__ TF_PLAT_STR_(__SSE2__) +#else +#define TF_PLAT_STR___SSE2__ +#endif +#if defined(__SSE_MATH__) +#define TF_PLAT_STR___SSE_MATH__ TF_PLAT_STR_(__SSE_MATH__) +#else +#define TF_PLAT_STR___SSE_MATH__ +#endif +#if defined(__SSE__) +#define TF_PLAT_STR___SSE__ TF_PLAT_STR_(__SSE__) +#else +#define TF_PLAT_STR___SSE__ +#endif +#if defined(__SSE3__) +#define TF_PLAT_STR___SSE3__ TF_PLAT_STR_(__SSE3__) +#else +#define TF_PLAT_STR___SSE3__ +#endif +#if defined(__SSE4A__) +#define TF_PLAT_STR___SSE4A__ TF_PLAT_STR_(__SSE4A__) +#else +#define TF_PLAT_STR___SSE4A__ +#endif +#if defined(__SSE4_1__) +#define TF_PLAT_STR___SSE4_1__ TF_PLAT_STR_(__SSE4_1__) +#else +#define TF_PLAT_STR___SSE4_1__ +#endif +#if defined(__SSE4_2__) +#define TF_PLAT_STR___SSE4_2__ TF_PLAT_STR_(__SSE4_2__) +#else +#define TF_PLAT_STR___SSE4_2__ +#endif +#if defined(__SSSE3__) +#define TF_PLAT_STR___SSSE3__ TF_PLAT_STR_(__SSSE3__) +#else +#define TF_PLAT_STR___SSSE3__ +#endif +#if defined(__TBM__) +#define TF_PLAT_STR___TBM__ TF_PLAT_STR_(__TBM__) +#else +#define TF_PLAT_STR___TBM__ +#endif +#if defined(__XOP__) +#define TF_PLAT_STR___XOP__ TF_PLAT_STR_(__XOP__) +#else +#define TF_PLAT_STR___XOP__ +#endif +#if defined(__XSAVEC__) +#define TF_PLAT_STR___XSAVEC__ TF_PLAT_STR_(__XSAVEC__) +#else +#define TF_PLAT_STR___XSAVEC__ +#endif +#if defined(__XSAVEOPT__) +#define TF_PLAT_STR___XSAVEOPT__ TF_PLAT_STR_(__XSAVEOPT__) +#else +#define TF_PLAT_STR___XSAVEOPT__ +#endif +#if defined(__XSAVES__) +#define TF_PLAT_STR___XSAVES__ TF_PLAT_STR_(__XSAVES__) +#else +#define TF_PLAT_STR___XSAVES__ +#endif +#if defined(__XSAVE__) +#define TF_PLAT_STR___XSAVE__ TF_PLAT_STR_(__XSAVE__) +#else +#define TF_PLAT_STR___XSAVE__ +#endif +#if defined(_SOFT_DOUBLE) +#define TF_PLAT_STR__SOFT_DOUBLE TF_PLAT_STR_(_SOFT_DOUBLE) +#else +#define TF_PLAT_STR__SOFT_DOUBLE +#endif +#if defined(_SOFT_FLOAT) +#define TF_PLAT_STR__SOFT_FLOAT TF_PLAT_STR_(_SOFT_FLOAT) +#else +#define TF_PLAT_STR__SOFT_FLOAT +#endif +#if defined(__ALTIVEC__) +#define TF_PLAT_STR___ALTIVEC__ TF_PLAT_STR_(__ALTIVEC__) +#else +#define TF_PLAT_STR___ALTIVEC__ +#endif +#if defined(__APPLE_ALTIVEC__) +#define TF_PLAT_STR___APPLE_ALTIVEC__ TF_PLAT_STR_(__APPLE_ALTIVEC__) +#else +#define TF_PLAT_STR___APPLE_ALTIVEC__ +#endif +#if defined(__CRYPTO__) +#define TF_PLAT_STR___CRYPTO__ TF_PLAT_STR_(__CRYPTO__) +#else +#define TF_PLAT_STR___CRYPTO__ +#endif +#if defined(__FLOAT128_HARDWARE__) +#define TF_PLAT_STR___FLOAT128_HARDWARE__ TF_PLAT_STR_(__FLOAT128_HARDWARE__) +#else +#define TF_PLAT_STR___FLOAT128_HARDWARE__ +#endif +#if defined(__FLOAT128_TYPE__) +#define TF_PLAT_STR___FLOAT128_TYPE__ TF_PLAT_STR_(__FLOAT128_TYPE__) +#else +#define TF_PLAT_STR___FLOAT128_TYPE__ +#endif +#if defined(__FP_FAST_FMA) +#define TF_PLAT_STR___FP_FAST_FMA TF_PLAT_STR_(__FP_FAST_FMA) +#else +#define TF_PLAT_STR___FP_FAST_FMA +#endif +#if defined(__FP_FAST_FMAF) +#define TF_PLAT_STR___FP_FAST_FMAF TF_PLAT_STR_(__FP_FAST_FMAF) +#else +#define TF_PLAT_STR___FP_FAST_FMAF +#endif +#if defined(__HTM__) +#define TF_PLAT_STR___HTM__ TF_PLAT_STR_(__HTM__) +#else +#define TF_PLAT_STR___HTM__ +#endif +#if defined(__NO_FPRS__) +#define TF_PLAT_STR___NO_FPRS__ TF_PLAT_STR_(__NO_FPRS__) +#else +#define TF_PLAT_STR___NO_FPRS__ +#endif +#if defined(__NO_LWSYNC__) +#define TF_PLAT_STR___NO_LWSYNC__ TF_PLAT_STR_(__NO_LWSYNC__) +#else +#define TF_PLAT_STR___NO_LWSYNC__ +#endif +#if defined(__POWER8_VECTOR__) +#define TF_PLAT_STR___POWER8_VECTOR__ TF_PLAT_STR_(__POWER8_VECTOR__) +#else +#define TF_PLAT_STR___POWER8_VECTOR__ +#endif +#if defined(__POWER9_VECTOR__) +#define TF_PLAT_STR___POWER9_VECTOR__ TF_PLAT_STR_(__POWER9_VECTOR__) +#else +#define TF_PLAT_STR___POWER9_VECTOR__ +#endif +#if defined(__PPC405__) +#define TF_PLAT_STR___PPC405__ TF_PLAT_STR_(__PPC405__) +#else +#define TF_PLAT_STR___PPC405__ +#endif +#if defined(__QUAD_MEMORY_ATOMIC__) +#define TF_PLAT_STR___QUAD_MEMORY_ATOMIC__ TF_PLAT_STR_(__QUAD_MEMORY_ATOMIC__) +#else +#define TF_PLAT_STR___QUAD_MEMORY_ATOMIC__ +#endif +#if defined(__RECIPF__) +#define TF_PLAT_STR___RECIPF__ TF_PLAT_STR_(__RECIPF__) +#else +#define TF_PLAT_STR___RECIPF__ +#endif +#if defined(__RECIP_PRECISION__) +#define TF_PLAT_STR___RECIP_PRECISION__ TF_PLAT_STR_(__RECIP_PRECISION__) +#else +#define TF_PLAT_STR___RECIP_PRECISION__ +#endif +#if defined(__RECIP__) +#define TF_PLAT_STR___RECIP__ TF_PLAT_STR_(__RECIP__) +#else +#define TF_PLAT_STR___RECIP__ +#endif +#if defined(__RSQRTEF__) +#define TF_PLAT_STR___RSQRTEF__ TF_PLAT_STR_(__RSQRTEF__) +#else +#define TF_PLAT_STR___RSQRTEF__ +#endif +#if defined(__RSQRTE__) +#define TF_PLAT_STR___RSQRTE__ TF_PLAT_STR_(__RSQRTE__) +#else +#define TF_PLAT_STR___RSQRTE__ +#endif +#if defined(__TM_FENCE__) +#define TF_PLAT_STR___TM_FENCE__ TF_PLAT_STR_(__TM_FENCE__) +#else +#define TF_PLAT_STR___TM_FENCE__ +#endif +#if defined(__UPPER_REGS_DF__) +#define TF_PLAT_STR___UPPER_REGS_DF__ TF_PLAT_STR_(__UPPER_REGS_DF__) +#else +#define TF_PLAT_STR___UPPER_REGS_DF__ +#endif +#if defined(__UPPER_REGS_SF__) +#define TF_PLAT_STR___UPPER_REGS_SF__ TF_PLAT_STR_(__UPPER_REGS_SF__) +#else +#define TF_PLAT_STR___UPPER_REGS_SF__ +#endif +#if defined(__VEC__) +#define TF_PLAT_STR___VEC__ TF_PLAT_STR_(__VEC__) +#else +#define TF_PLAT_STR___VEC__ +#endif +#if defined(__VSX__) +#define TF_PLAT_STR___VSX__ TF_PLAT_STR_(__VSX__) +#else +#define TF_PLAT_STR___VSX__ +#endif +#if defined(__ARM_ARCH) +#define TF_PLAT_STR___ARM_ARCH TF_PLAT_STR_(__ARM_ARCH) +#else +#define TF_PLAT_STR___ARM_ARCH +#endif +#if defined(__ARM_FEATURE_CLZ) +#define TF_PLAT_STR___ARM_FEATURE_CLZ TF_PLAT_STR_(__ARM_FEATURE_CLZ) +#else +#define TF_PLAT_STR___ARM_FEATURE_CLZ +#endif +#if defined(__ARM_FEATURE_CRC32) +#define TF_PLAT_STR___ARM_FEATURE_CRC32 TF_PLAT_STR_(__ARM_FEATURE_CRC32) +#else +#define TF_PLAT_STR___ARM_FEATURE_CRC32 +#endif +#if defined(__ARM_FEATURE_CRC32) +#define TF_PLAT_STR___ARM_FEATURE_CRC32 TF_PLAT_STR_(__ARM_FEATURE_CRC32) +#else +#define TF_PLAT_STR___ARM_FEATURE_CRC32 +#endif +#if defined(__ARM_FEATURE_CRYPTO) +#define TF_PLAT_STR___ARM_FEATURE_CRYPTO TF_PLAT_STR_(__ARM_FEATURE_CRYPTO) +#else +#define TF_PLAT_STR___ARM_FEATURE_CRYPTO +#endif +#if defined(__ARM_FEATURE_DIRECTED_ROUNDING) +#define TF_PLAT_STR___ARM_FEATURE_DIRECTED_ROUNDING \ + TF_PLAT_STR_(__ARM_FEATURE_DIRECTED_ROUNDING) +#else +#define TF_PLAT_STR___ARM_FEATURE_DIRECTED_ROUNDING +#endif +#if defined(__ARM_FEATURE_DSP) +#define TF_PLAT_STR___ARM_FEATURE_DSP TF_PLAT_STR_(__ARM_FEATURE_DSP) +#else +#define TF_PLAT_STR___ARM_FEATURE_DSP +#endif +#if defined(__ARM_FEATURE_FMA) +#define TF_PLAT_STR___ARM_FEATURE_FMA TF_PLAT_STR_(__ARM_FEATURE_FMA) +#else +#define TF_PLAT_STR___ARM_FEATURE_FMA +#endif +#if defined(__ARM_FEATURE_IDIV) +#define TF_PLAT_STR___ARM_FEATURE_IDIV TF_PLAT_STR_(__ARM_FEATURE_IDIV) +#else +#define TF_PLAT_STR___ARM_FEATURE_IDIV +#endif +#if defined(__ARM_FEATURE_LDREX) +#define TF_PLAT_STR___ARM_FEATURE_LDREX TF_PLAT_STR_(__ARM_FEATURE_LDREX) +#else +#define TF_PLAT_STR___ARM_FEATURE_LDREX +#endif +#if defined(__ARM_FEATURE_NUMERIC_MAXMIN) +#define TF_PLAT_STR___ARM_FEATURE_NUMERIC_MAXMIN \ + TF_PLAT_STR_(__ARM_FEATURE_NUMERIC_MAXMIN) +#else +#define TF_PLAT_STR___ARM_FEATURE_NUMERIC_MAXMIN +#endif +#if defined(__ARM_FEATURE_QBIT) +#define TF_PLAT_STR___ARM_FEATURE_QBIT TF_PLAT_STR_(__ARM_FEATURE_QBIT) +#else +#define TF_PLAT_STR___ARM_FEATURE_QBIT +#endif +#if defined(__ARM_FEATURE_QRDMX) +#define TF_PLAT_STR___ARM_FEATURE_QRDMX TF_PLAT_STR_(__ARM_FEATURE_QRDMX) +#else +#define TF_PLAT_STR___ARM_FEATURE_QRDMX +#endif +#if defined(__ARM_FEATURE_SAT) +#define TF_PLAT_STR___ARM_FEATURE_SAT TF_PLAT_STR_(__ARM_FEATURE_SAT) +#else +#define TF_PLAT_STR___ARM_FEATURE_SAT +#endif +#if defined(__ARM_FEATURE_SIMD32) +#define TF_PLAT_STR___ARM_FEATURE_SIMD32 TF_PLAT_STR_(__ARM_FEATURE_SIMD32) +#else +#define TF_PLAT_STR___ARM_FEATURE_SIMD32 +#endif +#if defined(__ARM_FEATURE_UNALIGNED) +#define TF_PLAT_STR___ARM_FEATURE_UNALIGNED \ + TF_PLAT_STR_(__ARM_FEATURE_UNALIGNED) +#else +#define TF_PLAT_STR___ARM_FEATURE_UNALIGNED +#endif +#if defined(__ARM_FP) +#define TF_PLAT_STR___ARM_FP TF_PLAT_STR_(__ARM_FP) +#else +#define TF_PLAT_STR___ARM_FP +#endif +#if defined(__ARM_NEON_FP) +#define TF_PLAT_STR___ARM_NEON_FP TF_PLAT_STR_(__ARM_NEON_FP) +#else +#define TF_PLAT_STR___ARM_NEON_FP +#endif +#if defined(__ARM_NEON__) +#define TF_PLAT_STR___ARM_NEON__ TF_PLAT_STR_(__ARM_NEON__) +#else +#define TF_PLAT_STR___ARM_NEON__ +#endif +#if defined(__ARM_WMMX) +#define TF_PLAT_STR___ARM_WMMX TF_PLAT_STR_(__ARM_WMMX) +#else +#define TF_PLAT_STR___ARM_WMMX +#endif +#if defined(__IWMMXT2__) +#define TF_PLAT_STR___IWMMXT2__ TF_PLAT_STR_(__IWMMXT2__) +#else +#define TF_PLAT_STR___IWMMXT2__ +#endif +#if defined(__IWMMXT__) +#define TF_PLAT_STR___IWMMXT__ TF_PLAT_STR_(__IWMMXT__) +#else +#define TF_PLAT_STR___IWMMXT__ +#endif +#if defined(__VFP_FP__) +#define TF_PLAT_STR___VFP_FP__ TF_PLAT_STR_(__VFP_FP__) +#else +#define TF_PLAT_STR___VFP_FP__ +#endif +#if defined(TARGET_IPHONE_SIMULATOR) +#define TF_PLAT_STR_TARGET_IPHONE_SIMULATOR \ + TF_PLAT_STR_(TARGET_IPHONE_SIMULATOR) +#else +#define TF_PLAT_STR_TARGET_IPHONE_SIMULATOR +#endif +#if defined(TARGET_OS_IOS) +#define TF_PLAT_STR_TARGET_OS_IOS TF_PLAT_STR_(TARGET_OS_IOS) +#else +#define TF_PLAT_STR_TARGET_OS_IOS +#endif +#if defined(TARGET_OS_IPHONE) +#define TF_PLAT_STR_TARGET_OS_IPHONE TF_PLAT_STR_(TARGET_OS_IPHONE) +#else +#define TF_PLAT_STR_TARGET_OS_IPHONE +#endif +#if defined(_MSC_VER) +#define TF_PLAT_STR__MSC_VER TF_PLAT_STR_(_MSC_VER) +#else +#define TF_PLAT_STR__MSC_VER +#endif +#if defined(_M_ARM) +#define TF_PLAT_STR__M_ARM TF_PLAT_STR_(_M_ARM) +#else +#define TF_PLAT_STR__M_ARM +#endif +#if defined(_M_ARM64) +#define TF_PLAT_STR__M_ARM64 TF_PLAT_STR_(_M_ARM64) +#else +#define TF_PLAT_STR__M_ARM64 +#endif +#if defined(_M_ARM_ARMV7VE) +#define TF_PLAT_STR__M_ARM_ARMV7VE TF_PLAT_STR_(_M_ARM_ARMV7VE) +#else +#define TF_PLAT_STR__M_ARM_ARMV7VE +#endif +#if defined(_M_ARM_FP) +#define TF_PLAT_STR__M_ARM_FP TF_PLAT_STR_(_M_ARM_FP) +#else +#define TF_PLAT_STR__M_ARM_FP +#endif +#if defined(_M_IX86) +#define TF_PLAT_STR__M_IX86 TF_PLAT_STR_(_M_IX86) +#else +#define TF_PLAT_STR__M_IX86 +#endif +#if defined(_M_X64) +#define TF_PLAT_STR__M_X64 TF_PLAT_STR_(_M_X64) +#else +#define TF_PLAT_STR__M_X64 +#endif +#if defined(_WIN32) +#define TF_PLAT_STR__WIN32 TF_PLAT_STR_(_WIN32) +#else +#define TF_PLAT_STR__WIN32 +#endif +#if defined(_WIN64) +#define TF_PLAT_STR__WIN64 TF_PLAT_STR_(_WIN64) +#else +#define TF_PLAT_STR__WIN64 +#endif +#if defined(__ANDROID__) +#define TF_PLAT_STR___ANDROID__ TF_PLAT_STR_(__ANDROID__) +#else +#define TF_PLAT_STR___ANDROID__ +#endif +#if defined(__APPLE__) +#define TF_PLAT_STR___APPLE__ TF_PLAT_STR_(__APPLE__) +#else +#define TF_PLAT_STR___APPLE__ +#endif +#if defined(__BYTE_ORDER__) +#define TF_PLAT_STR___BYTE_ORDER__ TF_PLAT_STR_(__BYTE_ORDER__) +#else +#define TF_PLAT_STR___BYTE_ORDER__ +#endif +#if defined(__CYGWIN__) +#define TF_PLAT_STR___CYGWIN__ TF_PLAT_STR_(__CYGWIN__) +#else +#define TF_PLAT_STR___CYGWIN__ +#endif +#if defined(__FreeBSD__) +#define TF_PLAT_STR___FreeBSD__ TF_PLAT_STR_(__FreeBSD__) +#else +#define TF_PLAT_STR___FreeBSD__ +#endif +#if defined(__LITTLE_ENDIAN__) +#define TF_PLAT_STR___LITTLE_ENDIAN__ TF_PLAT_STR_(__LITTLE_ENDIAN__) +#else +#define TF_PLAT_STR___LITTLE_ENDIAN__ +#endif +#if defined(__NetBSD__) +#define TF_PLAT_STR___NetBSD__ TF_PLAT_STR_(__NetBSD__) +#else +#define TF_PLAT_STR___NetBSD__ +#endif +#if defined(__OpenBSD__) +#define TF_PLAT_STR___OpenBSD__ TF_PLAT_STR_(__OpenBSD__) +#else +#define TF_PLAT_STR___OpenBSD__ +#endif +#if defined(____MSYS__) +#define TF_PLAT_STR_____MSYS__ TF_PLAT_STR_(____MSYS__) +#else +#define TF_PLAT_STR_____MSYS__ +#endif +#if defined(__aarch64__) +#define TF_PLAT_STR___aarch64__ TF_PLAT_STR_(__aarch64__) +#else +#define TF_PLAT_STR___aarch64__ +#endif +#if defined(__alpha__) +#define TF_PLAT_STR___alpha__ TF_PLAT_STR_(__alpha__) +#else +#define TF_PLAT_STR___alpha__ +#endif +#if defined(__arm__) +#define TF_PLAT_STR___arm__ TF_PLAT_STR_(__arm__) +#else +#define TF_PLAT_STR___arm__ +#endif +#if defined(__i386__) +#define TF_PLAT_STR___i386__ TF_PLAT_STR_(__i386__) +#else +#define TF_PLAT_STR___i386__ +#endif +#if defined(__i686__) +#define TF_PLAT_STR___i686__ TF_PLAT_STR_(__i686__) +#else +#define TF_PLAT_STR___i686__ +#endif +#if defined(__ia64__) +#define TF_PLAT_STR___ia64__ TF_PLAT_STR_(__ia64__) +#else +#define TF_PLAT_STR___ia64__ +#endif +#if defined(__linux__) +#define TF_PLAT_STR___linux__ TF_PLAT_STR_(__linux__) +#else +#define TF_PLAT_STR___linux__ +#endif +#if defined(__mips32__) +#define TF_PLAT_STR___mips32__ TF_PLAT_STR_(__mips32__) +#else +#define TF_PLAT_STR___mips32__ +#endif +#if defined(__mips64__) +#define TF_PLAT_STR___mips64__ TF_PLAT_STR_(__mips64__) +#else +#define TF_PLAT_STR___mips64__ +#endif +#if defined(__powerpc64__) +#define TF_PLAT_STR___powerpc64__ TF_PLAT_STR_(__powerpc64__) +#else +#define TF_PLAT_STR___powerpc64__ +#endif +#if defined(__powerpc__) +#define TF_PLAT_STR___powerpc__ TF_PLAT_STR_(__powerpc__) +#else +#define TF_PLAT_STR___powerpc__ +#endif +#if defined(__riscv___) +#define TF_PLAT_STR___riscv___ TF_PLAT_STR_(__riscv___) +#else +#define TF_PLAT_STR___riscv___ +#endif +#if defined(__s390x__) +#define TF_PLAT_STR___s390x__ TF_PLAT_STR_(__s390x__) +#else +#define TF_PLAT_STR___s390x__ +#endif +#if defined(__sparc64__) +#define TF_PLAT_STR___sparc64__ TF_PLAT_STR_(__sparc64__) +#else +#define TF_PLAT_STR___sparc64__ +#endif +#if defined(__sparc__) +#define TF_PLAT_STR___sparc__ TF_PLAT_STR_(__sparc__) +#else +#define TF_PLAT_STR___sparc__ +#endif +#if defined(__x86_64__) +#define TF_PLAT_STR___x86_64__ TF_PLAT_STR_(__x86_64__) +#else +#define TF_PLAT_STR___x86_64__ +#endif + +#endif // TENSORFLOW_CORE_PLATFORM_PLATFORM_STRINGS_COMPUTED_H_ diff --git a/tensorflow/core/platform/platform_strings_test.cc b/tensorflow/core/platform/platform_strings_test.cc new file mode 100644 index 0000000000..5251f10d41 --- /dev/null +++ b/tensorflow/core/platform/platform_strings_test.cc @@ -0,0 +1,146 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Test for the platform_strings.h header file. + +#include +#include +#include +#include + +#include +#include + +#include "tensorflow/core/lib/io/path.h" +#include "tensorflow/core/lib/strings/str_util.h" +#include "tensorflow/core/platform/env.h" +#include "tensorflow/core/platform/init_main.h" +#include "tensorflow/core/platform/logging.h" +#include "tensorflow/core/platform/platform_strings.h" + +// Embed the platform strings in this binary. +TF_PLATFORM_STRINGS() + +// A vector of strings. +typedef std::vector string_vec; + +// Append to *found the strings within the named file with the platform_strings +// magic prefix, and return true; or return false on error. + +// Print the platform strings embedded in the binary file_name and return 0, +// on on error return 2. +static int PrintStrings(const std::string file_name) { + int rc = 0; + string_vec str; + if (!tensorflow::GetPlatformStrings(file_name, &str)) { + for (int i = 0; i != str.size(); i++) { + printf("%s\n", str[i].c_str()); + } + } else { + perror(file_name.c_str()); + rc = 2; + } + return rc; +} + +// Return whether str[] conatins a string with prefix "macro_name="; if so, +// set *pvalue to the suffix. +static bool GetValue(const string_vec &str, const std::string ¯o_name, + std::string *pvalue) { + std::string nam_eq = macro_name + "="; + int i = 0; + while (i != str.size() && !tensorflow::str_util::StartsWith(str[i], nam_eq)) { + i++; + } + bool found = (i != str.size()); + if (found) { + *pvalue = str[i].substr(nam_eq.size()); + } + return found; +} + +// If macro_name[] is not equal to value[], check that str[] contains the +// string "macro_name=value". Otherwise, check that str[] does not contain any +// string starting with macro_name=". +static void CheckStr(const string_vec &str, const std::string ¯o_name, + const std::string &value) { + std::string value_from_str; + if (GetValue(str, macro_name, &value_from_str)) { + if (value != value_from_str) { + // Output everything found, to aid debugging. + LOG(ERROR) << "===== value=" << value + << " value_from_str=" << value_from_str; + for (int i = 0; i != str.size(); i++) { + LOG(ERROR) << "% " << str[i]; + } + LOG(ERROR) << "====="; + } + CHECK_EQ(value, value_from_str) << " " << macro_name << ": bad value"; + } else { + // If the string is not found, we expect value to be macro_name. + if (value != macro_name) { + // Output everything found, to aid debugging. + LOG(ERROR) << "===== value=" << value << " macro_name=" << macro_name; + for (int i = 0; i != str.size(); i++) { + LOG(ERROR) << "% " << str[i]; + } + LOG(ERROR) << "====="; + } + CHECK_EQ(value, macro_name) << " " << macro_name << ": not found in binary"; + } +} + +// Helper for AS_STR(), below, to perform macro expansion. +#define AS_STR_1_(x) #x + +// Yield x after macro expansion as a nul-terminated constant string. +#define AS_STR(x) AS_STR_1_(x) + +// Run the test, and return 0 on success, 2 otherwise. +static int RunTest(const std::string &binary_name) { + int rc = 0; + string_vec str; + + if (!tensorflow::GetPlatformStrings(binary_name, &str)) { + CheckStr(str, "__linux__", AS_STR(__linux__)); + CheckStr(str, "_WIN32", AS_STR(_WIN32)); + CheckStr(str, "__APPLE__", AS_STR(__APPLE__)); + CheckStr(str, "__x86_64__", AS_STR(__x86_64__)); + CheckStr(str, "__aarch64__", AS_STR(__aarch64__)); + CheckStr(str, "__powerpc64__", AS_STR(__powerpc64__)); + CheckStr(str, "TF_PLAT_STR_VERSION", TF_PLAT_STR_VERSION_); + } else { + perror(binary_name.c_str()); + rc = 2; + } + + return rc; +} + +int main(int argc, char *argv[]) { + tensorflow::Env *env = tensorflow::Env::Default(); + static const char usage[] = "usage: platform_strings_test [file...]"; + int rc = 0; + tensorflow::port::InitMain(usage, &argc, &argv); + if (argc == 1) { + printf("rc=%d\n", PrintStrings(env->GetExecutablePath())); + rc = RunTest(env->GetExecutablePath()); + } else { + for (int argn = 1; argn != argc; argn++) { + rc |= PrintStrings(argv[argn]); + } + } + return rc; +} diff --git a/tensorflow/core/platform/posix/posix_file_system.cc b/tensorflow/core/platform/posix/posix_file_system.cc index c7afab9583..fc48cab564 100644 --- a/tensorflow/core/platform/posix/posix_file_system.cc +++ b/tensorflow/core/platform/posix/posix_file_system.cc @@ -240,11 +240,14 @@ Status PosixFileSystem::DeleteFile(const string& fname) { } Status PosixFileSystem::CreateDir(const string& name) { - Status result; - if (mkdir(TranslateName(name).c_str(), 0755) != 0) { - result = IOError(name, errno); + string translated = TranslateName(name); + if (translated.empty()) { + return errors::AlreadyExists(name); } - return result; + if (mkdir(translated.c_str(), 0755) != 0) { + return IOError(name, errno); + } + return Status::OK(); } Status PosixFileSystem::DeleteDir(const string& name) { diff --git a/tensorflow/core/platform/regexp.h b/tensorflow/core/platform/regexp.h index a4eedf3045..ca9ca1e244 100644 --- a/tensorflow/core/platform/regexp.h +++ b/tensorflow/core/platform/regexp.h @@ -16,6 +16,7 @@ limitations under the License. #ifndef TENSORFLOW_PLATFORM_REGEXP_H_ #define TENSORFLOW_PLATFORM_REGEXP_H_ +#include "absl/strings/string_view.h" #include "tensorflow/core/platform/platform.h" #include "tensorflow/core/platform/types.h" @@ -23,7 +24,7 @@ limitations under the License. defined(GOOGLE_RE2) #include "tensorflow/core/platform/google/build_config/re2.h" namespace tensorflow { -typedef ::StringPiece RegexpStringPiece; +typedef absl::string_view RegexpStringPiece; } // namespace tensorflow #else diff --git a/tensorflow/core/platform/windows/windows_file_system.cc b/tensorflow/core/platform/windows/windows_file_system.cc index 6cf79634d7..993b9906b1 100644 --- a/tensorflow/core/platform/windows/windows_file_system.cc +++ b/tensorflow/core/platform/windows/windows_file_system.cc @@ -439,6 +439,9 @@ Status WindowsFileSystem::DeleteFile(const string& fname) { Status WindowsFileSystem::CreateDir(const string& name) { Status result; std::wstring ws_name = Utf8ToWideChar(name); + if (ws_name.empty()) { + return errors::AlreadyExists(name); + } if (_wmkdir(ws_name.c_str()) != 0) { result = IOError("Failed to create a directory: " + name, errno); } diff --git a/tensorflow/core/profiler/internal/tfprof_code.cc b/tensorflow/core/profiler/internal/tfprof_code.cc index 744e1e95de..0c26855a43 100644 --- a/tensorflow/core/profiler/internal/tfprof_code.cc +++ b/tensorflow/core/profiler/internal/tfprof_code.cc @@ -183,7 +183,7 @@ class Samples { // This method adds the statistics of graph nodes created by the python // call. void Add(const CodeNode* node, const std::vector& location_ids) { - // displayed leaf might not be true leaf. Retrive the true leaves for + // displayed leaf might not be true leaf. Retrieve the true leaves for // stats. std::vector all_leaf = FetchAllLeaf(node); CHECK(!all_leaf.empty()) << node->name(); diff --git a/tensorflow/core/profiler/internal/tfprof_node.cc b/tensorflow/core/profiler/internal/tfprof_node.cc index 86cb20de7b..8796234be0 100644 --- a/tensorflow/core/profiler/internal/tfprof_node.cc +++ b/tensorflow/core/profiler/internal/tfprof_node.cc @@ -151,7 +151,7 @@ void ExecStep::AddMemoryStats(const string& dev, } // TODO(xpan): Make this more accurate: - // High level: Memory tracking is suspicous and requires large scale + // High level: Memory tracking is suspicious and requires large scale // clean up. // Investigte the memory usage difference between CPU/GPU with OpViewTest. // diff --git a/tensorflow/core/protobuf/config.proto b/tensorflow/core/protobuf/config.proto index 4689af06af..b3dc5dccc0 100644 --- a/tensorflow/core/protobuf/config.proto +++ b/tensorflow/core/protobuf/config.proto @@ -291,6 +291,13 @@ message RPCOptions { // transport for client-master communication that avoids the RPC // stack. This option is primarily for used testing the RPC stack. bool use_rpc_for_inprocess_master = 1; + + // The compression algorithm to be used. One of "deflate", "gzip". + string compression_algorithm = 2; + + // If compression_algorithm is set, the compression level to be used. + // From 0 (no compression), up to 3. + int32 compression_level = 3; }; // Session configuration parameters. @@ -413,6 +420,11 @@ message ConfigProto { // Any positive value sets the max chunk size. 0 defaults to 4096. // Any negative value indicates no max, i.e. one chunk only. int32 recv_buf_max_chunk = 4; + + // If true, and supported by the platform, the runtime will attempt to + // use NUMA affinity where applicable. One consequence will be the + // existence of as many CPU devices as there are available NUMA nodes. + bool use_numa_affinity = 5; }; Experimental experimental = 16; diff --git a/tensorflow/core/protobuf/master.proto b/tensorflow/core/protobuf/master.proto index 03022875e6..c104463c51 100644 --- a/tensorflow/core/protobuf/master.proto +++ b/tensorflow/core/protobuf/master.proto @@ -224,7 +224,7 @@ message CloseSessionResponse { message ResetRequest { // A list of container names, which may be empty. // - // If 'container' is not empty, releases resoures in the given + // If 'container' is not empty, releases resources in the given // containers in all devices. // // If 'container' is empty, releases resources in the default diff --git a/tensorflow/core/protobuf/rewriter_config.proto b/tensorflow/core/protobuf/rewriter_config.proto index d68f273536..515d673828 100644 --- a/tensorflow/core/protobuf/rewriter_config.proto +++ b/tensorflow/core/protobuf/rewriter_config.proto @@ -38,7 +38,7 @@ message RewriterConfig { } // Enum controlling the number of times to run optimizers. The default is to - // run them once. + // run them twice. enum NumIterationsType { DEFAULT_NUM_ITERS = 0; ONE = 1; diff --git a/tensorflow/core/util/dump_graph.cc b/tensorflow/core/util/dump_graph.cc new file mode 100644 index 0000000000..523d37ecc2 --- /dev/null +++ b/tensorflow/core/util/dump_graph.cc @@ -0,0 +1,131 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Helper functions for dumping Graphs, GraphDefs, and FunctionDefs to files for +// debugging. + +#include "tensorflow/core/util/dump_graph.h" + +#include "absl/strings/str_cat.h" +#include "tensorflow/core/lib/strings/proto_serialization.h" +#include "tensorflow/core/platform/env.h" +#include "tensorflow/core/platform/mutex.h" + +namespace tensorflow { + +namespace { + +struct NameCounts { + mutex counts_mutex; + std::unordered_map counts; +}; + +string MakeUniqueFilename(string name) { + static NameCounts& instance = *new NameCounts; + + // Remove illegal characters from `name`. + for (int i = 0; i < name.size(); ++i) { + char ch = name[i]; + if (ch == '/' || ch == '[' || ch == ']' || ch == '*' || ch == '?') { + name[i] = '_'; + } + } + + int count; + { + mutex_lock lock(instance.counts_mutex); + count = instance.counts[name]++; + } + + string filename = name; + if (count > 0) { + absl::StrAppend(&filename, "_", count); + } + absl::StrAppend(&filename, ".pbtxt"); + return filename; +} + +#if defined(TENSORFLOW_LITE_PROTOS) +Status WriteToFile(const string& filepath, + const ::tensorflow::protobuf::MessageLite& proto) { + string s; + if (!SerializeToStringDeterministic(proto, &s)) { + return errors::Internal("Failed to serialize proto to string."); + } + return WriteStringToFile(Env::Default(), filepath, s); +} +#else +Status WriteToFile(const string& filepath, + const ::tensorflow::protobuf::Message& proto) { + return WriteTextProto(Env::Default(), filepath, proto); +} +#endif + +template +string WriteTextProtoToUniqueFile(Env* env, const string& name, + const char* proto_type, T& proto, + const string& dirname) { + const char* dir = nullptr; + if (!dirname.empty()) { + dir = dirname.c_str(); + } else { + dir = getenv("TF_DUMP_GRAPH_PREFIX"); + } + if (!dir) { + return "(TF_DUMP_GRAPH_PREFIX not specified)"; + } + Status status = env->RecursivelyCreateDir(dir); + if (!status.ok()) { + LOG(WARNING) << "Failed to create " << dir << " for dumping " << proto_type + << ": " << status; + return "(unavailable)"; + } + string filepath = absl::StrCat(dir, "/", MakeUniqueFilename(name)); + status = WriteToFile(filepath, proto); + if (!status.ok()) { + LOG(WARNING) << "Failed to dump " << proto_type << " to file: " << filepath + << " : " << status; + return "(unavailable)"; + } + LOG(INFO) << "Dumped " << proto_type << " to " << filepath; + return filepath; +} + +} // anonymous namespace + +string DumpGraphDefToFile(const string& name, GraphDef const& graph_def, + const string& dirname) { + return WriteTextProtoToUniqueFile(Env::Default(), name, "GraphDef", graph_def, + dirname); +} + +string DumpGraphToFile(const string& name, Graph const& graph, + const FunctionLibraryDefinition* flib_def, + const string& dirname) { + GraphDef graph_def; + graph.ToGraphDef(&graph_def); + if (flib_def) { + *graph_def.mutable_library() = flib_def->ToProto(); + } + return DumpGraphDefToFile(name, graph_def, dirname); +} + +string DumpFunctionDefToFile(const string& name, FunctionDef const& fdef, + const string& dirname) { + return WriteTextProtoToUniqueFile(Env::Default(), name, "FunctionDef", fdef, + dirname); +} + +} // namespace tensorflow diff --git a/tensorflow/core/util/dump_graph.h b/tensorflow/core/util/dump_graph.h new file mode 100644 index 0000000000..03dc807a2b --- /dev/null +++ b/tensorflow/core/util/dump_graph.h @@ -0,0 +1,52 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +// Helper functions for dumping Graphs, GraphDefs, and FunctionDefs to files for +// debugging. + +#ifndef TENSORFLOW_CORE_UTIL_DUMP_GRAPH_H_ +#define TENSORFLOW_CORE_UTIL_DUMP_GRAPH_H_ + +#include "tensorflow/core/framework/function.h" +#include "tensorflow/core/framework/graph.pb.h" +#include "tensorflow/core/graph/graph.h" + +namespace tensorflow { + +// Dumps 'graph_def' to a file, as a GraphDef text proto. Returns the file name +// chosen. +// +// Automatically picks a file name. Prefixes 'name' with the value of the +// TF_DUMP_GRAPH_PREFIX environment variable if 'dirname' is empty, and suffixes +// 'name' with ".pbtxt" to form a name. If a graph has already been dumped by +// this process with the same name, suffixes with "_n.pbtxt", where 'n' is a +// sequence number. +string DumpGraphDefToFile(const string& name, GraphDef const& graph_def, + const string& dirname = ""); + +// Similar to DumpGraphDefToFile, but builds the GraphDef to dump from a 'graph' +// and an optional function library 'flib_def'. Returns the file name chosen. +string DumpGraphToFile(const string& name, Graph const& graph, + const FunctionLibraryDefinition* flib_def = nullptr, + const string& dirname = ""); + +// Similar to DumpGraphDefToFile, but dumps a function as a FunctionDef text +// proto. Returns the file name chosen. +string DumpFunctionDefToFile(const string& name, FunctionDef const& fdef, + const string& dirname = ""); + +} // namespace tensorflow + +#endif // TENSORFLOW_CORE_UTIL_DUMP_GRAPH_H_ diff --git a/tensorflow/core/util/dump_graph_test.cc b/tensorflow/core/util/dump_graph_test.cc new file mode 100644 index 0000000000..d01c1c5a02 --- /dev/null +++ b/tensorflow/core/util/dump_graph_test.cc @@ -0,0 +1,62 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/util/dump_graph.h" +#include "tensorflow/core/graph/graph.h" +#include "tensorflow/core/graph/node_builder.h" +#include "tensorflow/core/lib/io/path.h" +#include "tensorflow/core/lib/strings/proto_serialization.h" +#include "tensorflow/core/platform/env.h" +#include "tensorflow/core/platform/test.h" + +namespace tensorflow { +namespace { + +TEST(DumpGraph, DumpGraphToFileSuccess) { + Graph graph(OpRegistry::Global()); + Node* node; + TF_CHECK_OK(NodeBuilder("A", "NoOp").Finalize(&graph, &node)); + + setenv("TF_DUMP_GRAPH_PREFIX", testing::TmpDir().c_str(), 1); + string ret = DumpGraphToFile("graph", graph); + EXPECT_EQ(ret, io::JoinPath(testing::TmpDir(), "graph.pbtxt")); + ret = DumpGraphToFile("graph", graph); + EXPECT_EQ(ret, io::JoinPath(testing::TmpDir(), "graph_1.pbtxt")); + + GraphDef gdef; + TF_CHECK_OK(ReadTextProto( + Env::Default(), io::JoinPath(testing::TmpDir(), "graph.pbtxt"), &gdef)); + string read, written; + gdef.AppendToString(&read); + graph.ToGraphDefDebug().AppendToString(&written); + EXPECT_EQ(read, written); +} + +TEST(DumpGraph, DumpGraphToFileNoEnvPrefix) { + Graph graph(OpRegistry::Global()); + unsetenv("TF_DUMP_GRAPH_PREFIX"); + string ret = DumpGraphToFile("graph", graph); + EXPECT_EQ(ret, "(TF_DUMP_GRAPH_PREFIX not specified)"); +} + +TEST(DumpGraph, DumpFunctionDefToFileSuccess) { + FunctionDef fdef; + setenv("TF_DUMP_GRAPH_PREFIX", testing::TmpDir().c_str(), 1); + string ret = DumpFunctionDefToFile("function", fdef); + EXPECT_EQ(ret, io::JoinPath(testing::TmpDir(), "function.pbtxt")); +} + +} // namespace +} // namespace tensorflow diff --git a/tensorflow/core/util/mkl_util.h b/tensorflow/core/util/mkl_util.h index b7a6e0b690..928807458a 100644 --- a/tensorflow/core/util/mkl_util.h +++ b/tensorflow/core/util/mkl_util.h @@ -1644,6 +1644,9 @@ class MklDnnData { cpu_engine_(e) {} ~MklDnnData() { + if (allocated_buffer_ != nullptr) { + cpu_allocator()->DeallocateRaw(allocated_buffer_); + } cpu_engine_ = nullptr; // We don't own this. delete (user_memory_); delete (reorder_memory_); diff --git a/tensorflow/core/util/permutation_input_iterator.h b/tensorflow/core/util/permutation_input_iterator.h index f6375b2515..649318ebf3 100644 --- a/tensorflow/core/util/permutation_input_iterator.h +++ b/tensorflow/core/util/permutation_input_iterator.h @@ -13,8 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#ifndef TENSORFLOW_UTIL_PERMUTATION_INPUT_ITERATOR_H_ -#define TENSORFLOW_UTIL_PERMUTATION_INPUT_ITERATOR_H_ +#ifndef TENSORFLOW_CORE_UTIL_PERMUTATION_INPUT_ITERATOR_H_ +#define TENSORFLOW_CORE_UTIL_PERMUTATION_INPUT_ITERATOR_H_ #include #include @@ -131,4 +131,4 @@ class PermutationInputIterator { } // end namespace tensorflow -#endif // TENSORFLOW_UTIL_PERMUTATION_INPUT_ITERATOR_H_ +#endif // TENSORFLOW_CORE_UTIL_PERMUTATION_INPUT_ITERATOR_H_ diff --git a/tensorflow/core/util/permutation_output_iterator.h b/tensorflow/core/util/permutation_output_iterator.h new file mode 100644 index 0000000000..638c0f4545 --- /dev/null +++ b/tensorflow/core/util/permutation_output_iterator.h @@ -0,0 +1,129 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_CORE_UTIL_PERMUTATION_OUTPUT_ITERATOR_H_ +#define TENSORFLOW_CORE_UTIL_PERMUTATION_OUTPUT_ITERATOR_H_ + +#include +#include + +namespace tensorflow { + +template +class PermutationOutputIterator { + public: + // Required iterator traits + typedef PermutationOutputIterator self_type; ///< My own type + typedef OffsetT difference_type; ///< Type to express the result of + ///< subtracting one iterator from another + typedef ValueType + value_type; ///< The type of the element the iterator can point to + typedef ValueType* pointer; ///< The type of a pointer to an element the + ///< iterator can point to + typedef ValueType& reference; ///< The type of a reference to an element the + ///< iterator can point to + + typedef std::random_access_iterator_tag + iterator_category; ///< The iterator category + + private: + OutputIteratorT output_itr; + IndexIteratorT index_itr; + + public: + /// Constructor + __host__ __device__ __forceinline__ PermutationOutputIterator( + OutputIteratorT output_itr, ///< Input iterator to wrap + IndexIteratorT index_itr) ///< Conversion functor to wrap + : output_itr(output_itr), index_itr(index_itr) {} + + /// Postfix increment + __host__ __device__ __forceinline__ self_type operator++(int) { + self_type retval = *this; + index_itr++; + return retval; + } + + /// Prefix increment + __host__ __device__ __forceinline__ self_type operator++() { + index_itr++; + return *this; + } + + /// Indirection + __host__ __device__ __forceinline__ reference operator*() const { + return output_itr[*index_itr]; + } + + /// Addition + template + __host__ __device__ __forceinline__ self_type operator+(Distance n) const { + self_type retval(output_itr, index_itr + n); + return retval; + } + + /// Addition assignment + template + __host__ __device__ __forceinline__ self_type& operator+=(Distance n) { + index_itr += n; + return *this; + } + + /// Subtraction + template + __host__ __device__ __forceinline__ self_type operator-(Distance n) const { + self_type retval(output_itr, index_itr - n); + return retval; + } + + /// Subtraction assignment + template + __host__ __device__ __forceinline__ self_type& operator-=(Distance n) { + index_itr -= n; + return *this; + } + + /// Distance + __host__ __device__ __forceinline__ difference_type + operator-(self_type other) const { + return index_itr - other.index_itr; + } + + /// Array subscript + template + __host__ __device__ __forceinline__ reference operator[](Distance n) const { + return output_itr[index_itr[n]]; + } + + /// Equal to + __host__ __device__ __forceinline__ bool operator==(const self_type& rhs) { + return (index_itr == rhs.index_itr && output_itr == rhs.output_itr); + } + + /// Not equal to + __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs) { + return !(*this == rhs); + } + + /// ostream operator + friend std::ostream& operator<<(std::ostream& os, const self_type& itr) { + return os; + } +}; + +} // end namespace tensorflow + +#endif // TENSORFLOW_CORE_UTIL_PERMUTATION_OUTPUT_ITERATOR_H_ diff --git a/tensorflow/core/util/sparse/sparse_tensor.h b/tensorflow/core/util/sparse/sparse_tensor.h index b9ca8ab395..89c163aa51 100644 --- a/tensorflow/core/util/sparse/sparse_tensor.h +++ b/tensorflow/core/util/sparse/sparse_tensor.h @@ -238,15 +238,6 @@ class SparseTensor { static Status Split(const SparseTensor& tensor, const int split_dim, const int num_split, std::vector* result); - template - ABSL_DEPRECATED( - "Use the form of Split() that takes an output pointer and returns a " - "status instead.") - static std::vector Split(const SparseTensor& tensor, - const int split_dim, - const int num_split, - Status* status = nullptr); - // Slice() will slice the input SparseTensor into a SparseTensor based on // specified start and size. Both start and size are 1-D array with each // element of the array representing one dimension. The start is the start @@ -578,10 +569,9 @@ SparseTensor SparseTensor::Concat( } template -std::vector SparseTensor::Split(const SparseTensor& input_tensor, - const int split_dim, - const int num_split, - Status* status /* = nullptr */) { +Status SparseTensor::Split(const SparseTensor& input_tensor, + const int split_dim, const int num_split, + std::vector* result) { std::vector output_indices; std::vector output_values; std::vector output_shapes; @@ -601,17 +591,15 @@ std::vector SparseTensor::Split(const SparseTensor& input_tensor, const int split_dim_size = input_tensor.shape()[split_dim]; const int split_size = split_dim_size / num_split; - if (!(num_split > 0 && num_split <= split_dim_size) && status != nullptr) { - *status = Status(error::INVALID_ARGUMENT, - strings::StrCat("num_split must be in the interval (0, ", - split_dim_size, "]")); - return {}; + if (!(num_split > 0 && num_split <= split_dim_size)) { + return Status(error::INVALID_ARGUMENT, + strings::StrCat("num_split must be in the interval (0, ", + split_dim_size, "]")); } if (!(split_dim >= 0 && split_dim < num_dim)) { - *status = Status( + return Status( error::INVALID_ARGUMENT, strings::StrCat("num_dim must be in the interval [0, ", num_dim, ")")); - return {}; } const int residual = split_dim_size % num_split; @@ -649,28 +637,18 @@ std::vector SparseTensor::Split(const SparseTensor& input_tensor, } } - std::vector output_tensors; - output_tensors.reserve(num_split); + result->clear(); + result->reserve(num_split); for (int i = 0; i < num_split; ++i) { SparseTensor tensor; Status create_status = Create(output_indices[i], output_values[i], output_shapes[i], &tensor); - if (!create_status.ok() && status != nullptr) { - *status = create_status; - return {}; + if (!create_status.ok()) { + return create_status; } - output_tensors.push_back(std::move(tensor)); + result->push_back(std::move(tensor)); } - return output_tensors; -} - -template -Status SparseTensor::Split(const SparseTensor& input_tensor, - const int split_dim, const int num_split, - std::vector* result) { - Status status; - *result = Split(input_tensor, split_dim, num_split, &status); - return status; + return Status::OK(); } template diff --git a/tensorflow/core/util/stats_calculator.cc b/tensorflow/core/util/stats_calculator.cc index eb07754650..bce650f245 100644 --- a/tensorflow/core/util/stats_calculator.cc +++ b/tensorflow/core/util/stats_calculator.cc @@ -53,7 +53,7 @@ std::string StatsCalculator::HeaderString(const std::string& title) const { << " ==============================" << std::endl; InitField(stream, 24) << "[node type]"; - InitField(stream, 9) << "[start]"; + InitField(stream, 17) << "[start]"; InitField(stream, 9) << "[first]"; InitField(stream, 9) << "[avg ms]"; InitField(stream, 8) << "[%]"; @@ -77,7 +77,7 @@ std::string StatsCalculator::ColumnString(const Detail& detail, std::stringstream stream; InitField(stream, 24) << detail.type; - InitField(stream, 9) << start_ms; + InitField(stream, 17) << start_ms; InitField(stream, 9) << first_time_ms; InitField(stream, 9) << avg_time_ms; InitField(stream, 7) << percentage << "%"; diff --git a/tensorflow/core/util/strided_slice_op.cc b/tensorflow/core/util/strided_slice_op.cc index ad8a44a518..55688e5808 100644 --- a/tensorflow/core/util/strided_slice_op.cc +++ b/tensorflow/core/util/strided_slice_op.cc @@ -83,10 +83,17 @@ static Status TF_MUST_USE_RESULT BuildDenseSpec( { int full_index = 0; - const auto& strides_flat = sparse.strides_tensor.flat(); + const T* const strides_flat = sparse.strides_tensor.vec().data(); dense->begin_valid = sparse.begin_tensor != nullptr; dense->end_valid = sparse.end_tensor != nullptr; + const T* const begin_flat = sparse.begin_tensor != nullptr + ? sparse.begin_tensor->vec().data() + : nullptr; + const T* const end_flat = sparse.end_tensor != nullptr + ? sparse.end_tensor->vec().data() + : nullptr; + for (int i = 0; i < sparse.dims; i++) { if ((1 << i) & sparse.ellipsis_mask) { // Expand the ellipsis into the appropriate indices @@ -112,16 +119,14 @@ static Status TF_MUST_USE_RESULT BuildDenseSpec( } // Gather slicing spec into appropriate index - if (sparse.begin_tensor != nullptr) { - const auto& begin_flat = sparse.begin_tensor->flat(); - dense->begin[full_index] = internal::SubtleMustCopy(begin_flat(i)); + if (begin_flat != nullptr) { + dense->begin[full_index] = internal::SubtleMustCopy(begin_flat[i]); } - if (sparse.end_tensor != nullptr) { - const auto& end_flat = sparse.end_tensor->flat(); - dense->end[full_index] = internal::SubtleMustCopy(end_flat(i)); + if (end_flat != nullptr) { + dense->end[full_index] = internal::SubtleMustCopy(end_flat[i]); } dense->strides[full_index] = - internal::SubtleMustCopy(strides_flat(i)); + internal::SubtleMustCopy(strides_flat[i]); if (sparse.begin_mask & (1 << i)) { dense->begin_mask |= (1 << full_index); } diff --git a/tensorflow/core/util/tensor_bundle/tensor_bundle.cc b/tensorflow/core/util/tensor_bundle/tensor_bundle.cc index 2dcb57a1f9..3709ee5ae3 100644 --- a/tensorflow/core/util/tensor_bundle/tensor_bundle.cc +++ b/tensorflow/core/util/tensor_bundle/tensor_bundle.cc @@ -785,7 +785,7 @@ Status BundleReader::GetBundleEntryProto(StringPiece key, TF_RETURN_IF_ERROR( ParseEntryProto(iter_->key(), iter_->value(), &entry_copy)); if (!TensorShape::IsValid(entry_copy.shape())) { - return errors::DataLoss("Invaid tensor shape: ", key, " ", + return errors::DataLoss("Invalid tensor shape: ", key, " ", ProtoShortDebugString(entry_copy.shape())); } @@ -895,7 +895,7 @@ Status BundleReader::ReadCurrent(Tensor* val) { BundleEntryProto entry; TF_RETURN_IF_ERROR(ParseEntryProto(iter_->key(), iter_->value(), &entry)); if (!TensorShape::IsValid(entry.shape())) { - return errors::DataLoss("Invaid tensor shape: ", iter_->key(), " ", + return errors::DataLoss("Invalid tensor shape: ", iter_->key(), " ", ProtoShortDebugString(entry.shape())); } diff --git a/tensorflow/core/util/tensor_format.h b/tensorflow/core/util/tensor_format.h index b0c349dd90..a296fb447e 100644 --- a/tensorflow/core/util/tensor_format.h +++ b/tensorflow/core/util/tensor_format.h @@ -498,7 +498,8 @@ inline TensorShape ShapeFromFormat(TensorFormat format, int64 N, dim_sizes[GetTensorBatchDimIndex(dims, format)] = N; for (int dim = 0; static_cast(dim) < spatial.size(); dim++) { auto dim_size = spatial[dim]; - if (format == FORMAT_NHWC_VECT_W && dim == spatial.size() - 1) { + if (format == FORMAT_NHWC_VECT_W && + static_cast(dim) == spatial.size() - 1) { CHECK_EQ(0, dim_size % 4) << "FORMAT_NHWC_VECT_W requires W to be a multiple of 4, but W=" << dim_size; diff --git a/tensorflow/core/util/tensor_ops_util.h b/tensorflow/core/util/tensor_ops_util.h new file mode 100644 index 0000000000..615f088a9b --- /dev/null +++ b/tensorflow/core/util/tensor_ops_util.h @@ -0,0 +1,128 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_CORE_UTIL_TENSOR_OPS_UTIL_H_ +#define TENSORFLOW_CORE_UTIL_TENSOR_OPS_UTIL_H_ + +#define EIGEN_USE_THREADS + +#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" +#include "tensorflow/core/framework/op_kernel.h" +#include "tensorflow/core/framework/register_types.h" +#include "tensorflow/core/framework/tensor.h" +#include "tensorflow/core/framework/types.h" +#include "tensorflow/core/framework/variant_op_registry.h" +#include "tensorflow/core/lib/core/status.h" + +namespace tensorflow { + +typedef Eigen::ThreadPoolDevice CPUDevice; +typedef Eigen::GpuDevice GPUDevice; + +template +Status ZerosLikeTensor(OpKernelContext* ctx, const Tensor& x, Tensor* out) { + AllocatorAttributes attr; + if (x.dtype() == DT_VARIANT) { + attr.set_on_host(true); + } + TF_RETURN_IF_ERROR(ctx->allocate_temp(x.dtype(), x.shape(), out, attr)); + + switch (out->dtype()) { +#define DTYPE_CASE(dtype) \ + case DataTypeToEnum::value: \ + /* TODO(skyewm): use SetZeroFunctor like in ZerosLikeOp? */ \ + out->flat().device(ctx->eigen_device()) = \ + out->flat().constant(dtype(0)); \ + break; + + TF_CALL_POD_TYPES(DTYPE_CASE) +#undef DTYPE_CASE + + case DT_INVALID: { + *out = Tensor(DT_INVALID); + break; + } + case DataTypeToEnum::value: { + Variant* out_variant = out->scalar().data(); + TF_RETURN_IF_ERROR( + UnaryOpVariant(ctx, ZEROS_LIKE_VARIANT_UNARY_OP, + x.scalar()(), out_variant)); + break; + } + default: + return errors::InvalidArgument( + "Trying to compute zeros_like for unsupported dtype ", + DataTypeString(out->dtype())); + } + return Status::OK(); +} + +template +Status BinaryAddTensors(OpKernelContext* ctx, const Tensor& a, const Tensor& b, + Tensor* out) { + if (a.dtype() == DT_INVALID) { + *out = b; + return Status::OK(); + } + if (b.dtype() == DT_INVALID) { + *out = a; + return Status::OK(); + } + if (a.dtype() != b.dtype()) { + return errors::InvalidArgument( + "Trying to add two tensors with incompatible element types. ", + "One is ", DataTypeString(a.dtype()), " and the other is ", + DataTypeString(b.dtype())); + } + if (a.shape() != b.shape()) { + // TODO(apassos) support broadcasting additions here? + return errors::InvalidArgument( + "Trying to add two tensors with incompatible element shapes. ", + "One is ", a.shape().DebugString(), " and the other is ", + b.shape().DebugString()); + } + + AllocatorAttributes attr; + if (a.dtype() == DT_VARIANT) { + attr.set_on_host(true); + } + TF_RETURN_IF_ERROR(ctx->allocate_temp(a.dtype(), a.shape(), out, attr)); + + switch (out->dtype()) { +#define DTYPE_CASE(dtype) \ + case DataTypeToEnum::value: \ + out->flat().device(ctx->eigen_device()) = \ + a.flat() + b.flat(); \ + break; + + TF_CALL_NUMBER_TYPES(DTYPE_CASE) +#undef DTYPE_CASE + + case DataTypeToEnum::value: { + Variant* out_variant = out->scalar().data(); + TF_RETURN_IF_ERROR(BinaryOpVariants( + ctx, ADD_VARIANT_BINARY_OP, a.scalar()(), + b.scalar()(), out_variant)); + break; + } + default: + return errors::InvalidArgument("Trying to add unsupported dtype ", + out->dtype()); + } + return Status::OK(); +} + +} // namespace tensorflow + +#endif // TENSORFLOW_CORE_UTIL_TENSOR_OPS_UTIL_H_ diff --git a/tensorflow/examples/adding_an_op/fact_test.py b/tensorflow/examples/adding_an_op/fact_test.py index 11163e7ba5..46beaebe0c 100644 --- a/tensorflow/examples/adding_an_op/fact_test.py +++ b/tensorflow/examples/adding_an_op/fact_test.py @@ -19,10 +19,12 @@ from __future__ import division from __future__ import print_function import tensorflow as tf +from tensorflow.python.framework import test_util class FactTest(tf.test.TestCase): + @test_util.run_deprecated_v1 def test(self): with self.cached_session(): print(tf.user_ops.my_fact().eval()) diff --git a/tensorflow/examples/adding_an_op/zero_out_1_test.py b/tensorflow/examples/adding_an_op/zero_out_1_test.py index 342d3a020c..459ac2dc27 100644 --- a/tensorflow/examples/adding_an_op/zero_out_1_test.py +++ b/tensorflow/examples/adding_an_op/zero_out_1_test.py @@ -23,10 +23,12 @@ import os.path import tensorflow as tf from tensorflow.examples.adding_an_op import zero_out_op_1 +from tensorflow.python.framework import test_util class ZeroOut1Test(tf.test.TestCase): + @test_util.run_deprecated_v1 def test(self): with self.cached_session(): result = zero_out_op_1.zero_out([5, 4, 3, 2, 1]) diff --git a/tensorflow/examples/adding_an_op/zero_out_2_test.py b/tensorflow/examples/adding_an_op/zero_out_2_test.py index 4504597817..650fd9546b 100644 --- a/tensorflow/examples/adding_an_op/zero_out_2_test.py +++ b/tensorflow/examples/adding_an_op/zero_out_2_test.py @@ -24,20 +24,24 @@ import tensorflow as tf from tensorflow.examples.adding_an_op import zero_out_grad_2 # pylint: disable=unused-import from tensorflow.examples.adding_an_op import zero_out_op_2 +from tensorflow.python.framework import test_util class ZeroOut2Test(tf.test.TestCase): + @test_util.run_deprecated_v1 def test(self): with self.cached_session(): result = zero_out_op_2.zero_out([5, 4, 3, 2, 1]) self.assertAllEqual(result.eval(), [5, 0, 0, 0, 0]) + @test_util.run_deprecated_v1 def test_2d(self): with self.cached_session(): result = zero_out_op_2.zero_out([[6, 5, 4], [3, 2, 1]]) self.assertAllEqual(result.eval(), [[6, 0, 0], [0, 0, 0]]) + @test_util.run_deprecated_v1 def test_grad(self): with self.cached_session(): shape = (5,) @@ -46,6 +50,7 @@ class ZeroOut2Test(tf.test.TestCase): err = tf.test.compute_gradient_error(x, shape, y, shape) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def test_grad_2d(self): with self.cached_session(): shape = (2, 3) diff --git a/tensorflow/examples/adding_an_op/zero_out_3_test.py b/tensorflow/examples/adding_an_op/zero_out_3_test.py index 15d62495aa..8cbe2b6793 100644 --- a/tensorflow/examples/adding_an_op/zero_out_3_test.py +++ b/tensorflow/examples/adding_an_op/zero_out_3_test.py @@ -21,31 +21,36 @@ from __future__ import print_function import tensorflow as tf from tensorflow.examples.adding_an_op import zero_out_op_3 +from tensorflow.python.framework import test_util class ZeroOut3Test(tf.test.TestCase): + @test_util.run_deprecated_v1 def test(self): with self.cached_session(): result = zero_out_op_3.zero_out([5, 4, 3, 2, 1]) self.assertAllEqual(result.eval(), [5, 0, 0, 0, 0]) + @test_util.run_deprecated_v1 def testAttr(self): with self.cached_session(): result = zero_out_op_3.zero_out([5, 4, 3, 2, 1], preserve_index=3) self.assertAllEqual(result.eval(), [0, 0, 0, 2, 0]) + @test_util.run_deprecated_v1 def testNegative(self): with self.cached_session(): result = zero_out_op_3.zero_out([5, 4, 3, 2, 1], preserve_index=-1) with self.assertRaisesOpError("Need preserve_index >= 0, got -1"): - result.eval() + self.evaluate(result) + @test_util.run_deprecated_v1 def testLarge(self): with self.cached_session(): result = zero_out_op_3.zero_out([5, 4, 3, 2, 1], preserve_index=17) with self.assertRaisesOpError("preserve_index out of range"): - result.eval() + self.evaluate(result) if __name__ == "__main__": diff --git a/tensorflow/examples/autograph/integration_tests/BUILD b/tensorflow/examples/autograph/integration_tests/BUILD index d20c17b63b..2a4a0f75e7 100644 --- a/tensorflow/examples/autograph/integration_tests/BUILD +++ b/tensorflow/examples/autograph/integration_tests/BUILD @@ -22,7 +22,6 @@ py_test( "keras_test.py", ], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ "//tensorflow:tensorflow_py", ], @@ -34,7 +33,6 @@ py_test( "list_literals_test.py", ], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ "//tensorflow:tensorflow_py", ], diff --git a/tensorflow/examples/autograph/integration_tests/keras_test.py b/tensorflow/examples/autograph/integration_tests/keras_test.py index dca7c07b47..3fe33df920 100644 --- a/tensorflow/examples/autograph/integration_tests/keras_test.py +++ b/tensorflow/examples/autograph/integration_tests/keras_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import tensorflow as tf from tensorflow.python import autograph +from tensorflow.python.framework import test_util class MinimalKeras(tf.keras.Model): @@ -84,6 +85,7 @@ class KerasTest(tf.test.TestCase): model = ModelWithStaticConditional(True) self.assertEqual(model.call(), 25) + @test_util.run_deprecated_v1 def test_recursive_true(self): with self.assertRaisesRegexp(NotImplementedError, 'Object conversion is not yet supported.'): @@ -93,10 +95,10 @@ class KerasTest(tf.test.TestCase): init = tf.global_variables_initializer() with tf.Session() as sess: - sess.run(init) + self.evaluate(init) sample_input = tf.random_uniform((1, 10, 10, 1)) output = model(sample_input) # pylint: disable=not-callable - self.assertEqual(sess.run(output).shape, (1, 3)) + self.assertEqual(self.evaluate(output).shape, (1, 3)) if __name__ == '__main__': diff --git a/tensorflow/examples/autograph/integration_tests/list_literals_test.py b/tensorflow/examples/autograph/integration_tests/list_literals_test.py index 917f5ff9d8..e85d4abcfc 100644 --- a/tensorflow/examples/autograph/integration_tests/list_literals_test.py +++ b/tensorflow/examples/autograph/integration_tests/list_literals_test.py @@ -34,7 +34,7 @@ class ListLiteralsTest(tf.test.TestCase): result = converted() with self.cached_session() as sess: - self.assertAllEqual(sess.run(result), [1, 2, 3]) + self.assertAllEqual(self.evaluate(result), [1, 2, 3]) if __name__ == '__main__': diff --git a/tensorflow/examples/get_started/regression/custom_regression.py b/tensorflow/examples/get_started/regression/custom_regression.py index 2e34362c5c..7b7cbb7866 100644 --- a/tensorflow/examples/get_started/regression/custom_regression.py +++ b/tensorflow/examples/get_started/regression/custom_regression.py @@ -100,12 +100,11 @@ def main(argv): # that the examples are well mixed. train.shuffle(1000).batch(128) # Repeat forever - .repeat().make_one_shot_iterator().get_next()) + .repeat()) # Build the validation input_fn. def input_test(): - return (test.shuffle(1000).batch(128) - .make_one_shot_iterator().get_next()) + return test.shuffle(1000).batch(128) # The first way assigns a unique weight to each category. To do this you must # specify the category's vocabulary (values outside this specification will diff --git a/tensorflow/examples/get_started/regression/dnn_regression.py b/tensorflow/examples/get_started/regression/dnn_regression.py index 951c93b52e..94669a5082 100644 --- a/tensorflow/examples/get_started/regression/dnn_regression.py +++ b/tensorflow/examples/get_started/regression/dnn_regression.py @@ -45,12 +45,11 @@ def main(argv): # that the examples are well mixed. train.shuffle(1000).batch(128) # Repeat forever - .repeat().make_one_shot_iterator().get_next()) + .repeat()) # Build the validation input_fn. def input_test(): - return (test.shuffle(1000).batch(128) - .make_one_shot_iterator().get_next()) + return test.shuffle(1000).batch(128) # The first way assigns a unique weight to each category. To do this you must # specify the category's vocabulary (values outside this specification will diff --git a/tensorflow/examples/get_started/regression/linear_regression_categorical.py b/tensorflow/examples/get_started/regression/linear_regression_categorical.py index e2ad415fbc..5312272a95 100644 --- a/tensorflow/examples/get_started/regression/linear_regression_categorical.py +++ b/tensorflow/examples/get_started/regression/linear_regression_categorical.py @@ -45,12 +45,11 @@ def main(argv): # that the examples are well mixed. train.shuffle(1000).batch(128) # Repeat forever - .repeat().make_one_shot_iterator().get_next()) + .repeat()) # Build the validation input_fn. def input_test(): - return (test.shuffle(1000).batch(128) - .make_one_shot_iterator().get_next()) + return test.shuffle(1000).batch(128) # The following code demonstrates two of the ways that `feature_columns` can # be used to build a model with categorical inputs. diff --git a/tensorflow/examples/how_tos/reading_data/fully_connected_reader.py b/tensorflow/examples/how_tos/reading_data/fully_connected_reader.py index 7402247448..5c52a2c846 100644 --- a/tensorflow/examples/how_tos/reading_data/fully_connected_reader.py +++ b/tensorflow/examples/how_tos/reading_data/fully_connected_reader.py @@ -126,7 +126,7 @@ def inputs(train, batch_size, num_epochs): dataset = dataset.repeat(num_epochs) dataset = dataset.batch(batch_size) - iterator = dataset.make_one_shot_iterator() + iterator = tf.compat.v1.data.make_one_shot_iterator(dataset) return iterator.get_next() diff --git a/tensorflow/examples/learn/iris_custom_decay_dnn.py b/tensorflow/examples/learn/iris_custom_decay_dnn.py index 4a219694d1..73bf20fada 100644 --- a/tensorflow/examples/learn/iris_custom_decay_dnn.py +++ b/tensorflow/examples/learn/iris_custom_decay_dnn.py @@ -76,12 +76,12 @@ def main(unused_argv): classifier = tf.estimator.Estimator(model_fn=my_model) # Train. - train_input_fn = tf.estimator.inputs.numpy_input_fn( + train_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( x={X_FEATURE: x_train}, y=y_train, num_epochs=None, shuffle=True) classifier.train(input_fn=train_input_fn, steps=1000) # Predict. - test_input_fn = tf.estimator.inputs.numpy_input_fn( + test_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( x={X_FEATURE: x_test}, y=y_test, num_epochs=1, shuffle=False) predictions = classifier.predict(input_fn=test_input_fn) y_predicted = np.array(list(p['class'] for p in predictions)) diff --git a/tensorflow/examples/learn/iris_custom_model.py b/tensorflow/examples/learn/iris_custom_model.py index c6bdb86ba5..bf34d72ba0 100644 --- a/tensorflow/examples/learn/iris_custom_model.py +++ b/tensorflow/examples/learn/iris_custom_model.py @@ -73,12 +73,12 @@ def main(unused_argv): classifier = tf.estimator.Estimator(model_fn=my_model) # Train. - train_input_fn = tf.estimator.inputs.numpy_input_fn( + train_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( x={X_FEATURE: x_train}, y=y_train, num_epochs=None, shuffle=True) classifier.train(input_fn=train_input_fn, steps=1000) # Predict. - test_input_fn = tf.estimator.inputs.numpy_input_fn( + test_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( x={X_FEATURE: x_test}, y=y_test, num_epochs=1, shuffle=False) predictions = classifier.predict(input_fn=test_input_fn) y_predicted = np.array(list(p['class'] for p in predictions)) diff --git a/tensorflow/examples/speech_commands/freeze_test.py b/tensorflow/examples/speech_commands/freeze_test.py index 0c7ca9bc01..9ed9050035 100644 --- a/tensorflow/examples/speech_commands/freeze_test.py +++ b/tensorflow/examples/speech_commands/freeze_test.py @@ -19,11 +19,13 @@ from __future__ import division from __future__ import print_function from tensorflow.examples.speech_commands import freeze +from tensorflow.python.framework import test_util from tensorflow.python.platform import test class FreezeTest(test.TestCase): + @test_util.run_deprecated_v1 def testCreateInferenceGraphWithMfcc(self): with self.cached_session() as sess: freeze.create_inference_graph( @@ -43,6 +45,7 @@ class FreezeTest(test.TestCase): ops = [node.op for node in sess.graph_def.node] self.assertEqual(1, ops.count('Mfcc')) + @test_util.run_deprecated_v1 def testCreateInferenceGraphWithoutMfcc(self): with self.cached_session() as sess: freeze.create_inference_graph( @@ -62,6 +65,7 @@ class FreezeTest(test.TestCase): ops = [node.op for node in sess.graph_def.node] self.assertEqual(0, ops.count('Mfcc')) + @test_util.run_deprecated_v1 def testFeatureBinCount(self): with self.cached_session() as sess: freeze.create_inference_graph( diff --git a/tensorflow/examples/speech_commands/input_data_test.py b/tensorflow/examples/speech_commands/input_data_test.py index b766ba6de0..9269bb6c0b 100644 --- a/tensorflow/examples/speech_commands/input_data_test.py +++ b/tensorflow/examples/speech_commands/input_data_test.py @@ -26,6 +26,7 @@ import tensorflow as tf from tensorflow.contrib.framework.python.ops import audio_ops as contrib_audio from tensorflow.examples.speech_commands import input_data from tensorflow.examples.speech_commands import models +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -35,7 +36,7 @@ class InputDataTest(test.TestCase): with self.cached_session() as sess: sample_data = tf.zeros([32000, 2]) wav_encoder = contrib_audio.encode_wav(sample_data, 16000) - wav_data = sess.run(wav_encoder) + wav_data = self.evaluate(wav_encoder) return wav_data def _saveTestWavFile(self, filename, wav_data): @@ -96,6 +97,7 @@ class InputDataTest(test.TestCase): input_data.which_set("foo_nohash_0.wav", 10, 10), input_data.which_set("foo_nohash_1.wav", 10, 10)) + @test_util.run_deprecated_v1 def testPrepareDataIndex(self): tmp_dir = self.get_temp_dir() self._saveWavFolders(tmp_dir, ["a", "b", "c"], 100) @@ -125,6 +127,7 @@ class InputDataTest(test.TestCase): 10, self._model_settings(), tmp_dir) self.assertTrue("Expected to find" in str(e.exception)) + @test_util.run_deprecated_v1 def testPrepareBackgroundData(self): tmp_dir = self.get_temp_dir() background_dir = os.path.join(tmp_dir, "_background_noise_") @@ -156,6 +159,7 @@ class InputDataTest(test.TestCase): self.assertIsNotNone(loaded_data) self.assertEqual(16000, len(loaded_data)) + @test_util.run_deprecated_v1 def testPrepareProcessingGraph(self): tmp_dir = self.get_temp_dir() wav_dir = os.path.join(tmp_dir, "wavs") @@ -186,15 +190,19 @@ class InputDataTest(test.TestCase): self.assertIsNotNone(audio_processor.background_volume_placeholder_) self.assertIsNotNone(audio_processor.output_) + @test_util.run_deprecated_v1 def testGetDataAverage(self): self._runGetDataTest("average", 10) + @test_util.run_deprecated_v1 def testGetDataAverageLongWindow(self): self._runGetDataTest("average", 30) + @test_util.run_deprecated_v1 def testGetDataMfcc(self): self._runGetDataTest("mfcc", 30) + @test_util.run_deprecated_v1 def testGetUnprocessedData(self): tmp_dir = self.get_temp_dir() wav_dir = os.path.join(tmp_dir, "wavs") @@ -216,6 +224,7 @@ class InputDataTest(test.TestCase): self.assertEqual(10, len(result_data)) self.assertEqual(10, len(result_labels)) + @test_util.run_deprecated_v1 def testGetFeaturesForWav(self): tmp_dir = self.get_temp_dir() wav_dir = os.path.join(tmp_dir, "wavs") diff --git a/tensorflow/examples/speech_commands/label_wav_test.py b/tensorflow/examples/speech_commands/label_wav_test.py index f0af2a4798..77a88f98e1 100644 --- a/tensorflow/examples/speech_commands/label_wav_test.py +++ b/tensorflow/examples/speech_commands/label_wav_test.py @@ -33,7 +33,7 @@ class LabelWavTest(test.TestCase): with self.cached_session() as sess: sample_data = tf.zeros([1000, 2]) wav_encoder = contrib_audio.encode_wav(sample_data, 16000) - wav_data = sess.run(wav_encoder) + wav_data = self.evaluate(wav_encoder) return wav_data def _saveTestWavFile(self, filename, wav_data): diff --git a/tensorflow/examples/speech_commands/models_test.py b/tensorflow/examples/speech_commands/models_test.py index 04478c0962..cb9304eab8 100644 --- a/tensorflow/examples/speech_commands/models_test.py +++ b/tensorflow/examples/speech_commands/models_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import tensorflow as tf from tensorflow.examples.speech_commands import models +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -47,6 +48,7 @@ class ModelsTest(test.TestCase): feature_bin_count=40, preprocess="mfcc")) + @test_util.run_deprecated_v1 def testCreateModelConvTraining(self): model_settings = self._modelSettings() with self.cached_session() as sess: @@ -58,6 +60,7 @@ class ModelsTest(test.TestCase): self.assertIsNotNone(sess.graph.get_tensor_by_name(logits.name)) self.assertIsNotNone(sess.graph.get_tensor_by_name(dropout_prob.name)) + @test_util.run_deprecated_v1 def testCreateModelConvInference(self): model_settings = self._modelSettings() with self.cached_session() as sess: @@ -67,6 +70,7 @@ class ModelsTest(test.TestCase): self.assertIsNotNone(logits) self.assertIsNotNone(sess.graph.get_tensor_by_name(logits.name)) + @test_util.run_deprecated_v1 def testCreateModelLowLatencyConvTraining(self): model_settings = self._modelSettings() with self.cached_session() as sess: @@ -78,6 +82,7 @@ class ModelsTest(test.TestCase): self.assertIsNotNone(sess.graph.get_tensor_by_name(logits.name)) self.assertIsNotNone(sess.graph.get_tensor_by_name(dropout_prob.name)) + @test_util.run_deprecated_v1 def testCreateModelFullyConnectedTraining(self): model_settings = self._modelSettings() with self.cached_session() as sess: @@ -98,6 +103,7 @@ class ModelsTest(test.TestCase): "bad_architecture", True) self.assertTrue("not recognized" in str(e.exception)) + @test_util.run_deprecated_v1 def testCreateModelTinyConvTraining(self): model_settings = self._modelSettings() with self.cached_session() as sess: diff --git a/tensorflow/examples/speech_commands/wav_to_features_test.py b/tensorflow/examples/speech_commands/wav_to_features_test.py index 87f2987693..6234490b26 100644 --- a/tensorflow/examples/speech_commands/wav_to_features_test.py +++ b/tensorflow/examples/speech_commands/wav_to_features_test.py @@ -24,6 +24,7 @@ import tensorflow as tf from tensorflow.contrib.framework.python.ops import audio_ops as contrib_audio from tensorflow.examples.speech_commands import wav_to_features +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -33,7 +34,7 @@ class WavToFeaturesTest(test.TestCase): with self.cached_session() as sess: sample_data = tf.zeros([32000, 2]) wav_encoder = contrib_audio.encode_wav(sample_data, 16000) - wav_data = sess.run(wav_encoder) + wav_data = self.evaluate(wav_encoder) return wav_data def _saveTestWavFile(self, filename, wav_data): @@ -49,6 +50,7 @@ class WavToFeaturesTest(test.TestCase): file_path = os.path.join(dir_name, "some_audio_%d.wav" % i) self._saveTestWavFile(file_path, wav_data) + @test_util.run_deprecated_v1 def testWavToFeatures(self): tmp_dir = self.get_temp_dir() wav_dir = os.path.join(tmp_dir, "wavs") diff --git a/tensorflow/examples/tutorials/layers/cnn_mnist.py b/tensorflow/examples/tutorials/layers/cnn_mnist.py index 1e8d7d05e1..670e929236 100644 --- a/tensorflow/examples/tutorials/layers/cnn_mnist.py +++ b/tensorflow/examples/tutorials/layers/cnn_mnist.py @@ -134,7 +134,7 @@ def main(unused_argv): tensors=tensors_to_log, every_n_iter=50) # Train the model - train_input_fn = tf.estimator.inputs.numpy_input_fn( + train_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( x={"x": train_data}, y=train_labels, batch_size=100, @@ -146,11 +146,8 @@ def main(unused_argv): hooks=[logging_hook]) # Evaluate the model and print results - eval_input_fn = tf.estimator.inputs.numpy_input_fn( - x={"x": eval_data}, - y=eval_labels, - num_epochs=1, - shuffle=False) + eval_input_fn = tf.compat.v1.estimator.inputs.numpy_input_fn( + x={"x": eval_data}, y=eval_labels, num_epochs=1, shuffle=False) eval_results = mnist_classifier.evaluate(input_fn=eval_input_fn) print(eval_results) diff --git a/tensorflow/go/README.md b/tensorflow/go/README.md index 3989f9b25a..f53f6fc989 100644 --- a/tensorflow/go/README.md +++ b/tensorflow/go/README.md @@ -23,7 +23,7 @@ from source. - [bazel](https://www.bazel.build/versions/master/docs/install.html) - Environment to build TensorFlow from source code - ([Linux of macOS](https://www.tensorflow.org/install/source)). + ([Linux or macOS](https://www.tensorflow.org/install/source)). If you don't need GPU support, then try the following: ```sh diff --git a/tensorflow/go/graph.go b/tensorflow/go/graph.go index 67e42aa961..6ff41ca916 100644 --- a/tensorflow/go/graph.go +++ b/tensorflow/go/graph.go @@ -112,9 +112,17 @@ func (g *Graph) ImportWithOptions(def []byte, options GraphImportOptions) error C.TF_ImportGraphDefOptionsSetPrefix(opts, cprefix) if len(options.Device) != 0 { - cdev := C.CString(options.Device) - defer C.free(unsafe.Pointer(cdev)) - C.TF_ImportGraphDefOptionsSetDefaultDevice(opts, cdev) + // TODO(ashankar): Remove this error and uncomment below + // when a release of the C library which includes + // https://github.com/tensorflow/tensorflow/commit/e0af5ac53e5a8ad9b07cdd5738c0a8e12f938c4e + // has been made. + // See https://github.com/tensorflow/tensorflow/issues/23257 + return fmt.Errorf("GraphImportOptions.Device is only supported with the TensorFlow C library versions after 1.12 (or built from master). See https://github.com/tensorflow/tensorflow/issues/23257") + /* + cdev := C.CString(options.Device) + defer C.free(unsafe.Pointer(cdev)) + C.TF_ImportGraphDefOptionsSetDefaultDevice(opts, cdev) + */ } buf := C.TF_NewBuffer() @@ -174,6 +182,68 @@ func (g *Graph) Operations() []Operation { return ops } +// AddGradients adds operations to compute the partial derivatives of the sum of tensors in y +// with respect to tensors in x, i.e., d(y[0] + y[1] + ...) / d x[0], d(y[0] + y[1] + ... ) / d x[1] etc. +// +// prefix, if non-empty, is the name prefix used for all operations added to the graph to compute +// these gradients. +func (g *Graph) AddGradients(prefix string, y []Output, x []Output, dx []Output) ([]Output, error) { + var ( + cprefix *C.char + + cy = make([]C.TF_Output, len(y)) + cx = make([]C.TF_Output, len(x)) + cdx = make([]C.TF_Output, len(dx)) + cdy = make([]C.TF_Output, len(x)) + + pcy *C.TF_Output + pcx *C.TF_Output + pcdx *C.TF_Output + pcdy *C.TF_Output + + status = newStatus() + ) + + if len(y) > 0 { + pcy = &cy[0] + for i, o := range y { + cy[i] = o.c() + } + } + if len(x) > 0 { + pcx = &cx[0] + for i, o := range x { + cx[i] = o.c() + } + pcdy = &cdy[0] + } + if len(dx) > 0 { + pcdx = &cdx[0] + for i, o := range dx { + cdx[i] = o.c() + } + } + + // If prefix is "", the C.TF_AddGradientsWithPrefix need cprefix to be nil but not "" + if len(prefix) != 0 { + cprefix = C.CString(prefix) + defer C.free(unsafe.Pointer(cprefix)) + } + + C.TF_AddGradientsWithPrefix(g.c, cprefix, pcy, C.int(len(y)), pcx, C.int(len(x)), pcdx, status.c, pcdy) + + if err := status.Err(); err != nil { + return nil, err + } + dy := make([]Output, len(x)) + for i, co := range cdy { + op := &Operation{co.oper, g} + dy[i] = Output{op, int(co.index)} + } + + return dy, nil +} + // OpSpec is the specification of an Operation to be added to a Graph // (using Graph.AddOperation). type OpSpec struct { diff --git a/tensorflow/go/graph_test.go b/tensorflow/go/graph_test.go index b8d65c54f6..067c7db5c3 100644 --- a/tensorflow/go/graph_test.go +++ b/tensorflow/go/graph_test.go @@ -19,6 +19,7 @@ package tensorflow import ( "bytes" "fmt" + "strings" "testing" ) @@ -80,3 +81,260 @@ func TestGraphWriteToAndImport(t *testing.T) { t.Error(err) } } + +func TestGraphAddGradients(t *testing.T) { + g := NewGraph() + x1, err := Placeholder(g, "x1", Float) + if err != nil { + t.Fatal(err) + } + x2, err := Placeholder(g, "x2", Float) + if err != nil { + t.Fatal(err) + } + op0, err := g.AddOperation(OpSpec{ + Type: "Square", + Name: "y0", + Input: []Input{x1}, + }) + if err != nil { + t.Fatal(err) + } + y0 := op0.Output(0) + op1, err := g.AddOperation(OpSpec{ + Type: "Square", + Name: "y1", + Input: []Input{y0}, + }) + if err != nil { + t.Fatal(err) + } + y1 := op1.Output(0) + op2, err := g.AddOperation(OpSpec{ + Type: "AddN", + Input: []Input{OutputList([]Output{y0, x2})}, + }) + if err != nil { + t.Fatal(err) + } + y2 := op2.Output(0) + + grads0, err := g.AddGradients("", []Output{y1}, []Output{x1}, nil) + if err != nil { + t.Fatal(err) + } + if len(grads0) != 1 { + t.Fatal(len(grads0)) + } + if grads0[0].DataType() != Float { + t.Fatalf("Got DataType %v, wanted %v", grads0[0].DataType(), Float) + } + + grads1, err := g.AddGradients("", []Output{y2}, []Output{x1, x2}, nil) + if err != nil { + t.Fatal(err) + } + if len(grads1) != 2 { + t.Fatal(len(grads1)) + } + if grads1[0].DataType() != Float { + t.Fatalf("Got DataType %v, wanted %v", grads1[0].DataType(), Float) + } + if grads1[1].DataType() != Float { + t.Fatalf("Got DataType %v, wanted %v", grads1[1].DataType(), Float) + } + + sess, err := NewSession(g, nil) + if err != nil { + t.Fatal(err) + } + + c1, _ := NewTensor(float32(3.0)) + c2, _ := NewTensor(float32(2.0)) + outputs, err := sess.Run( + map[Output]*Tensor{x1: c1, x2: c2}, + []Output{grads0[0], grads1[0], grads1[1]}, + nil) + if err != nil { + t.Fatal(err) + } + if len(outputs) != 3 { + t.Fatal(len(outputs)) + } + if outputs[0].Value().(float32) != 108.0 { + t.Fatalf("Got %v, wanted float 108.0", outputs[0].Value()) + } + if outputs[1].Value().(float32) != 6.0 { + t.Fatalf("Got %v, wanted float 6.0", outputs[1].Value()) + } + if outputs[2].Value().(float32) != 1.0 { + t.Fatalf("Got %v, wanted float 1.0", outputs[2].Value()) + } +} + +func TestGraphAddGradientsSums(t *testing.T) { + g := NewGraph() + x, err := Placeholder(g, "x", Float) + if err != nil { + t.Fatal(err) + } + op0, err := g.AddOperation(OpSpec{ + Type: "Square", + Name: "y0", + Input: []Input{x}, + }) + if err != nil { + t.Fatal(err) + } + y0 := op0.Output(0) + op1, err := g.AddOperation(OpSpec{ + Type: "Square", + Name: "y1", + Input: []Input{y0}, + }) + y1 := op1.Output(0) + + grad, err := g.AddGradients("", []Output{y0, y1}, []Output{x}, nil) + if err != nil { + t.Fatal(err) + } + if len(grad) != 1 { + t.Fatal(len(grad)) + } + if grad[0].DataType() != Float { + t.Fatalf("Got DataType %v, wanted %v", grad[0].DataType(), Float) + } + + sess, err := NewSession(g, nil) + if err != nil { + t.Fatal(err) + } + + c, _ := NewTensor(float32(3.0)) + outputs, err := sess.Run( + map[Output]*Tensor{x: c}, + []Output{grad[0]}, + nil) + if err != nil { + t.Fatal(err) + } + if outputs[0].Value().(float32) != 114.0 { + t.Fatalf("Got %v, wanted float 114.0", outputs[0].Value()) + } +} + +func TestGraphAddGradientsWithInitialValues(t *testing.T) { + g := NewGraph() + x, err := Placeholder(g, "x", Float) + op0, err := g.AddOperation(OpSpec{ + Type: "Square", + Name: "y0", + Input: []Input{x}, + }) + if err != nil { + t.Fatal(err) + } + y0 := op0.Output(0) + op1, err := g.AddOperation(OpSpec{ + Type: "Square", + Name: "y1", + Input: []Input{y0}, + }) + if err != nil { + t.Fatal(err) + } + y1 := op1.Output(0) + + grads0, err := g.AddGradients("", []Output{y1}, []Output{y0}, nil) + if err != nil { + t.Fatal(err) + } + if len(grads0) != 1 { + t.Fatal(len(grads0)) + } + if grads0[0].DataType() != Float { + t.Fatalf("Got DataType %v, wanted %v", grads0[0].DataType(), Float) + } + + grads1, err := g.AddGradients("", []Output{y0}, []Output{x}, []Output{grads0[0]}) + if err != nil { + t.Fatal(err) + } + if len(grads1) != 1 { + t.Fatal(len(grads1)) + } + if grads1[0].DataType() != Float { + t.Fatalf("Got DataType %v, wanted %v", grads1[0].DataType(), Float) + } + + sess, err := NewSession(g, nil) + if err != nil { + t.Fatal(err) + } + + c, _ := NewTensor(float32(3.0)) + outputs, err := sess.Run( + map[Output]*Tensor{x: c}, + []Output{grads1[0]}, + nil) + if err != nil { + t.Fatal(err) + } + if outputs[0].Value().(float32) != 108.0 { + t.Fatalf("Got %v, wanted float 108.0", outputs[0].Value()) + } +} + +func TestGraphValidateGradientsNames(t *testing.T) { + g := NewGraph() + x, err := Placeholder(g, "x", Float) + if err != nil { + t.Fatal(err) + } + op0, err := g.AddOperation(OpSpec{ + Type: "Square", + Name: "y0", + Input: []Input{x}, + }) + if err != nil { + t.Fatal(err) + } + y0 := op0.Output(0) + + grads0, err := g.AddGradients("", []Output{y0}, []Output{x}, nil) + if err != nil { + t.Fatal(err) + } + if !strings.HasPrefix(grads0[0].Op.Name(), "gradients/") { + t.Fatalf("Got name %v, wanted started with gradients/", grads0[0].Op.Name()) + } + + grads1, err := g.AddGradients("", []Output{y0}, []Output{x}, nil) + if err != nil { + t.Fatal(err) + } + if !strings.HasPrefix(grads1[0].Op.Name(), "gradients_1/") { + t.Fatalf("Got name %v, wanted started with gradients_1/", grads1[0].Op.Name()) + } + + grads2, err := g.AddGradients("more_gradients", []Output{y0}, []Output{x}, nil) + if err != nil { + t.Fatal(err) + } + if !strings.HasPrefix(grads2[0].Op.Name(), "more_gradients/") { + t.Fatalf("Got name %v, wanted started with more_gradients/", grads2[0].Op.Name()) + } + + grads3, err := g.AddGradients("even_more_gradients", []Output{y0}, []Output{x}, nil) + if err != nil { + t.Fatal(err) + } + if !strings.HasPrefix(grads3[0].Op.Name(), "even_more_gradients/") { + t.Fatalf("Got name %v, wanted started with even_more_gradients/", grads3[0].Op.Name()) + } + + _, err = g.AddGradients("even_more_gradients", []Output{y0}, []Output{x}, nil) + if err == nil { + t.Error("AddGradients should have failed if gradients name is already existing") + } +} diff --git a/tensorflow/go/op/gradients.go b/tensorflow/go/op/gradients.go new file mode 100644 index 0000000000..9f892e1da6 --- /dev/null +++ b/tensorflow/go/op/gradients.go @@ -0,0 +1,50 @@ +/* +Copyright 2016 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package op + +import ( + "fmt" + + tf "github.com/tensorflow/tensorflow/tensorflow/go" +) + + +// Gradients adds gradients computation ops to the graph according to scope. +// +// Arguments: +// y: output of the function to derive +// x: inputs of the function for which partial derivatives are computed +// dx: if not null, the partial derivatives of some loss function L w.r.t. y +// +// return the partial derivatives +func Gradients(scope *Scope, y []tf.Output, x []tf.Output, dx ...tf.Output) (output []tf.Output) { + if len(scope.controlDependencies) > 0 { + scope.UpdateErr("Gradients", fmt.Errorf("Gradients does not currently support control dependencies (via Scope.WithControlDependencies).")) + return + } + if scope.device != "" { + scope.UpdateErr("Gradients", fmt.Errorf("Gradients does not currently support device annotations (via Scope.WithDevice).")) + return + } + + var err error + if output, err = scope.graph.AddGradients(scope.opName("Gradients"), y, x, dx); err != nil { + scope.UpdateErr("Gradients", err) + return + } + return output +} diff --git a/tensorflow/go/op/gradients_test.go b/tensorflow/go/op/gradients_test.go new file mode 100644 index 0000000000..3d1d57b77e --- /dev/null +++ b/tensorflow/go/op/gradients_test.go @@ -0,0 +1,246 @@ +/* +Copyright 2016 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package op + +import ( + "strings" + "testing" + + tf "github.com/tensorflow/tensorflow/tensorflow/go" +) + +func TestAddGradients(t *testing.T) { + var ( + s = NewScope() + x1 = Placeholder(s.SubScope("x1"), tf.Float) + x2 = Placeholder(s.SubScope("x2"), tf.Float) + y0 = Square(s.SubScope("y0"), x1) + y1 = Square(s.SubScope("y1"), y0) + y2 = AddN(s.SubScope("y2"), []tf.Output{y0, x2}) + ) + + grads0 := Gradients(s, []tf.Output{y1}, []tf.Output{x1}) + if err := s.Err(); err != nil { + t.Fatal(err) + } + if len(grads0) != 1 { + t.Fatal(len(grads0)) + } + if grads0[0].DataType() != tf.Float { + t.Fatalf("Got DataType %v, wanted %v", grads0[0].DataType(), tf.Float) + } + + sub := s.SubScope("sub") + grads1 := Gradients(sub, []tf.Output{y2}, []tf.Output{x1, x2}) + if err := sub.Err(); err != nil { + t.Fatal(err) + } + if len(grads1) != 2 { + t.Fatal(len(grads1)) + } + if grads1[0].DataType() != tf.Float { + t.Fatalf("Got DataType %v, wanted %v", grads1[0].DataType(), tf.Float) + } + if grads1[1].DataType() != tf.Float { + t.Fatalf("Got DataType %v, wanted %v", grads1[1].DataType(), tf.Float) + } + + graph, err := sub.Finalize() + if err != nil { + t.Fatal(err) + } + sess, err := tf.NewSession(graph, nil) + if err != nil { + t.Fatal(err) + } + + c1, _ := tf.NewTensor(float32(3.0)) + c2, _ := tf.NewTensor(float32(3.0)) + outputs, err := sess.Run( + map[tf.Output]*tf.Tensor{x1: c1, x2: c2}, + []tf.Output{grads0[0], grads1[0], grads1[1]}, + nil) + if err != nil { + t.Fatal(err) + } + if len(outputs) != 3 { + t.Fatal(len(outputs)) + } + if outputs[0].Value().(float32) != 108.0 { + t.Fatalf("Got %v, wanted float 108.0", outputs[0].Value()) + } + if outputs[1].Value().(float32) != 6.0 { + t.Fatalf("Got %v, wanted float 6.0", outputs[1].Value()) + } + if outputs[2].Value().(float32) != 1.0 { + t.Fatalf("Got %v, wanted float 1.0", outputs[2].Value()) + } +} + +func TestAddGradientsSums(t *testing.T) { + var ( + s = NewScope() + x = Placeholder(s.SubScope("x"), tf.Float) + y0 = Square(s.SubScope("y0"), x) + y1 = Square(s.SubScope("y1"), y0) + ) + + grad := Gradients(s, []tf.Output{y0, y1}, []tf.Output{x}) + if err := s.Err(); err != nil { + t.Fatal(err) + } + if len(grad) != 1 { + t.Fatal(len(grad)) + } + if grad[0].DataType() != tf.Float { + t.Fatalf("Got DataType %v, wanted %v", grad[0].DataType(), tf.Float) + } + + graph, err := s.Finalize() + if err != nil { + t.Fatal(err) + } + sess, err := tf.NewSession(graph, nil) + if err != nil { + t.Fatal(err) + } + + c, _ := tf.NewTensor(float32(3.0)) + outputs, err := sess.Run( + map[tf.Output]*tf.Tensor{x: c}, + []tf.Output{grad[0]}, + nil) + if err != nil { + t.Fatal(err) + } + if outputs[0].Value().(float32) != 114.0 { + t.Fatalf("Got %v, wanted float 114.0", outputs[0].Value()) + } +} + +func TestAddGradientsWithInitialValues(t *testing.T) { + var ( + s = NewScope() + x = Placeholder(s.SubScope("x1"), tf.Float) + y0 = Square(s.SubScope("y0"), x) + y1 = Square(s.SubScope("y1"), y0) + ) + + grads0 := Gradients(s, []tf.Output{y1}, []tf.Output{y0}) + if err := s.Err(); err != nil { + t.Fatal(err) + } + if len(grads0) != 1 { + t.Fatal(len(grads0)) + } + if grads0[0].DataType() != tf.Float { + t.Fatalf("Got DataType %v, wanted %v", grads0[0].DataType(), tf.Float) + } + + sub := s.SubScope("sub") + grads1 := Gradients(sub, []tf.Output{y0}, []tf.Output{x}, grads0[0]) + if err := sub.Err(); err != nil { + t.Fatal(err) + } + if len(grads1) != 1 { + t.Fatal(len(grads1)) + } + if grads1[0].DataType() != tf.Float { + t.Fatalf("Got DataType %v, wanted %v", grads1[0].DataType(), tf.Float) + } + + graph, err := sub.Finalize() + if err != nil { + t.Fatal(err) + } + sess, err := tf.NewSession(graph, nil) + if err != nil { + t.Fatal(err) + } + + c, _ := tf.NewTensor(float32(3.0)) + outputs, err := sess.Run( + map[tf.Output]*tf.Tensor{x: c}, + []tf.Output{grads1[0]}, + nil) + if err != nil { + t.Fatal(err) + } + if outputs[0].Value().(float32) != 108.0 { + t.Fatalf("Got %v, wanted float 108.0", outputs[0].Value()) + } +} + +func TestValidateGradientsNames(t *testing.T) { + var ( + s = NewScope() + x = Placeholder(s.SubScope("x"), tf.Float) + y0 = Square(s.SubScope("y0"), x) + ) + + grads0 := Gradients(s, []tf.Output{y0}, []tf.Output{x}) + if err := s.Err(); err != nil { + t.Fatal(err) + } + if !strings.HasPrefix(grads0[0].Op.Name(), "Gradients/") { + t.Fatalf("Got name %v, wanted started with Gradients/", grads0[0].Op.Name()) + } + + sub := s.SubScope("sub") + grads1 := Gradients(sub, []tf.Output{y0}, []tf.Output{x}) + if err := s.Err(); err != nil { + t.Fatal(err) + } + if !strings.HasPrefix(grads1[0].Op.Name(), "sub/Gradients/") { + t.Fatalf("Got name %v, wanted started with sub/Gradients/", grads1[0].Op.Name()) + } + + Gradients(sub, []tf.Output{y0}, []tf.Output{x}) + if err := s.Err(); err == nil { + t.Error("Gradients should have failed if executed more than once for scope of the same namespace") + } +} + +func TestAddGradientsWithControlDependencies(t *testing.T) { + var ( + s = NewScope() + zero = Const(s.SubScope("zero"), int32(0)) + x = Placeholder(s.SubScope("x"), tf.Float) + y0 = Square(s.SubScope("y0"), x) + variable = VarHandleOp(s, tf.Int32, tf.ScalarShape()) + init = AssignVariableOp(s, variable, zero) + readDeps = []*tf.Operation{init} + ) + s = s.WithControlDependencies(readDeps...) + Gradients(s, []tf.Output{y0}, []tf.Output{x}) + if err := s.Err(); err == nil { + t.Error("Gradients should have failed when control dependencies are set") + } +} + +func TestAddGradientsWithDevice(t *testing.T) { + var ( + s = NewScope() + x = Placeholder(s.SubScope("x"), tf.Float) + y0 = Square(s.SubScope("y0"), x) + ) + s = s.WithDevice("/device:GPU:0") + Gradients(s, []tf.Output{y0}, []tf.Output{x}) + if err := s.Err(); err == nil { + t.Error("Gradients should have failed when device is set") + } +} diff --git a/tensorflow/go/op/wrappers.go b/tensorflow/go/op/wrappers.go index baf43f84f8..5cd06299b9 100644 --- a/tensorflow/go/op/wrappers.go +++ b/tensorflow/go/op/wrappers.go @@ -463,6 +463,14 @@ func QuantizeAndDequantizeV2RangeGiven(value bool) QuantizeAndDequantizeV2Attr { } } +// QuantizeAndDequantizeV2RoundMode sets the optional round_mode attribute to value. +// If not specified, defaults to "HALF_TO_EVEN" +func QuantizeAndDequantizeV2RoundMode(value string) QuantizeAndDequantizeV2Attr { + return func(m optionalAttr) { + m["round_mode"] = value + } +} + // Quantizes then dequantizes a tensor. // // This op simulates the precision loss from the quantized forward pass by: @@ -3487,30 +3495,6 @@ func BoostedTreesQuantileStreamResourceFlush(scope *Scope, quantile_stream_resou return scope.AddOperation(opspec) } -// Add the quantile summaries to each quantile stream resource. -// -// An op that adds a list of quantile summaries to a quantile stream resource. Each -// summary Tensor is rank 2, containing summaries (value, weight, min_rank, max_rank) -// for a single feature. -// -// Arguments: -// quantile_stream_resource_handle: resource handle referring to a QuantileStreamResource. -// summaries: string; List of Rank 2 Tensor each containing the summaries for a single feature. -// -// Returns the created operation. -func BoostedTreesQuantileStreamResourceAddSummaries(scope *Scope, quantile_stream_resource_handle tf.Output, summaries []tf.Output) (o *tf.Operation) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "BoostedTreesQuantileStreamResourceAddSummaries", - Input: []tf.Input{ - quantile_stream_resource_handle, tf.OutputList(summaries), - }, - } - return scope.AddOperation(opspec) -} - // Makes the summary of quantiles for the batch. // // An op that takes a list of tensors and outputs the quantile summaries for each tensor. @@ -5547,6 +5531,63 @@ func OrderedMapPeek(scope *Scope, key tf.Output, indices tf.Output, dtypes []tf. return values } +// MapIncompleteSizeAttr is an optional argument to MapIncompleteSize. +type MapIncompleteSizeAttr func(optionalAttr) + +// MapIncompleteSizeCapacity sets the optional capacity attribute to value. +// If not specified, defaults to 0 +// +// REQUIRES: value >= 0 +func MapIncompleteSizeCapacity(value int64) MapIncompleteSizeAttr { + return func(m optionalAttr) { + m["capacity"] = value + } +} + +// MapIncompleteSizeMemoryLimit sets the optional memory_limit attribute to value. +// If not specified, defaults to 0 +// +// REQUIRES: value >= 0 +func MapIncompleteSizeMemoryLimit(value int64) MapIncompleteSizeAttr { + return func(m optionalAttr) { + m["memory_limit"] = value + } +} + +// MapIncompleteSizeContainer sets the optional container attribute to value. +// If not specified, defaults to "" +func MapIncompleteSizeContainer(value string) MapIncompleteSizeAttr { + return func(m optionalAttr) { + m["container"] = value + } +} + +// MapIncompleteSizeSharedName sets the optional shared_name attribute to value. +// If not specified, defaults to "" +func MapIncompleteSizeSharedName(value string) MapIncompleteSizeAttr { + return func(m optionalAttr) { + m["shared_name"] = value + } +} + +// Op returns the number of incomplete elements in the underlying container. +func MapIncompleteSize(scope *Scope, dtypes []tf.DataType, optional ...MapIncompleteSizeAttr) (size tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{"dtypes": dtypes} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "MapIncompleteSize", + + Attrs: attrs, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // Compute the regularized incomplete beta integral \\(I_x(a, b)\\). // // The regularized incomplete beta integral is defined as: @@ -5612,34 +5653,6 @@ func Atan2(scope *Scope, y tf.Output, x tf.Output) (z tf.Output) { return op.Output(0) } -// Creates a dataset that passes a sliding window over `input_dataset`. -// -// Arguments: -// -// window_size: A scalar representing the number of elements in the -// sliding window. -// window_shift: A scalar representing the steps moving the sliding window -// forward in one iteration. It must be positive. -// window_stride: A scalar representing the stride of the input elements of the sliding window. -// It must be positive. -// -// -func SlideDataset(scope *Scope, input_dataset tf.Output, window_size tf.Output, window_shift tf.Output, window_stride tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"output_types": output_types, "output_shapes": output_shapes} - opspec := tf.OpSpec{ - Type: "SlideDataset", - Input: []tf.Input{ - input_dataset, window_size, window_shift, window_stride, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // EditDistanceAttr is an optional argument to EditDistance. type EditDistanceAttr func(optionalAttr) @@ -6279,6 +6292,71 @@ func Asin(scope *Scope, x tf.Output) (y tf.Output) { return op.Output(0) } +// SparseToDenseAttr is an optional argument to SparseToDense. +type SparseToDenseAttr func(optionalAttr) + +// SparseToDenseValidateIndices sets the optional validate_indices attribute to value. +// +// value: If true, indices are checked to make sure they are sorted in +// lexicographic order and that there are no repeats. +// If not specified, defaults to true +func SparseToDenseValidateIndices(value bool) SparseToDenseAttr { + return func(m optionalAttr) { + m["validate_indices"] = value + } +} + +// Converts a sparse representation into a dense tensor. +// +// Builds an array `dense` with shape `output_shape` such that +// +// ``` +// # If sparse_indices is scalar +// dense[i] = (i == sparse_indices ? sparse_values : default_value) +// +// # If sparse_indices is a vector, then for each i +// dense[sparse_indices[i]] = sparse_values[i] +// +// # If sparse_indices is an n by d matrix, then for each i in [0, n) +// dense[sparse_indices[i][0], ..., sparse_indices[i][d-1]] = sparse_values[i] +// ``` +// +// All other values in `dense` are set to `default_value`. If `sparse_values` is a +// scalar, all sparse indices are set to this single value. +// +// Indices should be sorted in lexicographic order, and indices must not +// contain any repeats. If `validate_indices` is true, these properties +// are checked during execution. +// +// Arguments: +// sparse_indices: 0-D, 1-D, or 2-D. `sparse_indices[i]` contains the complete +// index where `sparse_values[i]` will be placed. +// output_shape: 1-D. Shape of the dense output tensor. +// sparse_values: 1-D. Values corresponding to each row of `sparse_indices`, +// or a scalar value to be used for all sparse indices. +// default_value: Scalar value to set for indices not specified in +// `sparse_indices`. +// +// Returns Dense output tensor of shape `output_shape`. +func SparseToDense(scope *Scope, sparse_indices tf.Output, output_shape tf.Output, sparse_values tf.Output, default_value tf.Output, optional ...SparseToDenseAttr) (dense tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "SparseToDense", + Input: []tf.Input{ + sparse_indices, output_shape, sparse_values, default_value, + }, + Attrs: attrs, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // Computes the sum along sparse segments of a tensor. // // Like `SparseSegmentSum`, but allows missing ids in `segment_ids`. If an id is @@ -6370,21 +6448,6 @@ func Sin(scope *Scope, x tf.Output) (y tf.Output) { return op.Output(0) } -// Computes the complementary error function of `x` element-wise. -func Erfc(scope *Scope, x tf.Output) (y tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "Erfc", - Input: []tf.Input{ - x, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Computes Psi, the derivative of Lgamma (the log of the absolute value of // // `Gamma(x)`), element-wise. @@ -6829,61 +6892,6 @@ func Reciprocal(scope *Scope, x tf.Output) (y tf.Output) { return op.Output(0) } -// ParseExampleDatasetAttr is an optional argument to ParseExampleDataset. -type ParseExampleDatasetAttr func(optionalAttr) - -// ParseExampleDatasetSloppy sets the optional sloppy attribute to value. -// If not specified, defaults to false -func ParseExampleDatasetSloppy(value bool) ParseExampleDatasetAttr { - return func(m optionalAttr) { - m["sloppy"] = value - } -} - -// Transforms `input_dataset` containing `Example` protos as vectors of DT_STRING into a dataset of `Tensor` or `SparseTensor` objects representing the parsed features. -// -// Arguments: -// -// -// dense_defaults: A dict mapping string keys to `Tensor`s. -// The keys of the dict must match the dense_keys of the feature. -// sparse_keys: A list of string keys in the examples features. -// The results for these keys will be returned as `SparseTensor` objects. -// dense_keys: A list of Ndense string Tensors (scalars). -// The keys expected in the Examples features associated with dense values. -// sparse_types: A list of `DTypes` of the same length as `sparse_keys`. -// Only `tf.float32` (`FloatList`), `tf.int64` (`Int64List`), -// and `tf.string` (`BytesList`) are supported. -// dense_shapes: List of tuples with the same length as `dense_keys`. -// The shape of the data for each dense feature referenced by `dense_keys`. -// Required for any input tensors identified by `dense_keys`. Must be -// either fully defined, or may contain an unknown first dimension. -// An unknown first dimension means the feature is treated as having -// a variable number of blocks, and the output shape along this dimension -// is considered unknown at graph build time. Padding is applied for -// minibatch elements smaller than the maximum number of blocks for the -// given feature along this dimension. -// output_types: The type list for the return values. -// output_shapes: The list of shapes being produced. -func ParseExampleDataset(scope *Scope, input_dataset tf.Output, num_parallel_calls tf.Output, dense_defaults []tf.Output, sparse_keys []string, dense_keys []string, sparse_types []tf.DataType, dense_shapes []tf.Shape, output_types []tf.DataType, output_shapes []tf.Shape, optional ...ParseExampleDatasetAttr) (handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"sparse_keys": sparse_keys, "dense_keys": dense_keys, "sparse_types": sparse_types, "dense_shapes": dense_shapes, "output_types": output_types, "output_shapes": output_shapes} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "ParseExampleDataset", - Input: []tf.Input{ - input_dataset, num_parallel_calls, tf.OutputList(dense_defaults), - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Returns a batched matrix tensor with new batched diagonal values. // // Given `input` and `diagonal`, this operation returns a tensor with the @@ -7956,28 +7964,6 @@ func LeakyRelu(scope *Scope, features tf.Output, optional ...LeakyReluAttr) (act return op.Output(0) } -// Writes the given dataset to the given file using the TFRecord format. -// -// Arguments: -// input_dataset: A variant tensor representing the dataset to write. -// filename: A scalar string tensor representing the filename to use. -// compression_type: A scalar string tensor containing either (i) the empty string (no -// compression), (ii) "ZLIB", or (iii) "GZIP". -// -// Returns the created operation. -func DatasetToTFRecord(scope *Scope, input_dataset tf.Output, filename tf.Output, compression_type tf.Output) (o *tf.Operation) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "DatasetToTFRecord", - Input: []tf.Input{ - input_dataset, filename, compression_type, - }, - } - return scope.AddOperation(opspec) -} - // Computes rectified linear 6: `min(max(features, 0), 6)`. func Relu6(scope *Scope, features tf.Output) (activations tf.Output) { if scope.Err() != nil { @@ -9441,6 +9427,178 @@ func BesselI1e(scope *Scope, x tf.Output) (y tf.Output) { return op.Output(0) } +// MapClearAttr is an optional argument to MapClear. +type MapClearAttr func(optionalAttr) + +// MapClearCapacity sets the optional capacity attribute to value. +// If not specified, defaults to 0 +// +// REQUIRES: value >= 0 +func MapClearCapacity(value int64) MapClearAttr { + return func(m optionalAttr) { + m["capacity"] = value + } +} + +// MapClearMemoryLimit sets the optional memory_limit attribute to value. +// If not specified, defaults to 0 +// +// REQUIRES: value >= 0 +func MapClearMemoryLimit(value int64) MapClearAttr { + return func(m optionalAttr) { + m["memory_limit"] = value + } +} + +// MapClearContainer sets the optional container attribute to value. +// If not specified, defaults to "" +func MapClearContainer(value string) MapClearAttr { + return func(m optionalAttr) { + m["container"] = value + } +} + +// MapClearSharedName sets the optional shared_name attribute to value. +// If not specified, defaults to "" +func MapClearSharedName(value string) MapClearAttr { + return func(m optionalAttr) { + m["shared_name"] = value + } +} + +// Op removes all elements in the underlying container. +// +// Returns the created operation. +func MapClear(scope *Scope, dtypes []tf.DataType, optional ...MapClearAttr) (o *tf.Operation) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{"dtypes": dtypes} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "MapClear", + + Attrs: attrs, + } + return scope.AddOperation(opspec) +} + +// DecodeCSVAttr is an optional argument to DecodeCSV. +type DecodeCSVAttr func(optionalAttr) + +// DecodeCSVFieldDelim sets the optional field_delim attribute to value. +// +// value: char delimiter to separate fields in a record. +// If not specified, defaults to "," +func DecodeCSVFieldDelim(value string) DecodeCSVAttr { + return func(m optionalAttr) { + m["field_delim"] = value + } +} + +// DecodeCSVUseQuoteDelim sets the optional use_quote_delim attribute to value. +// +// value: If false, treats double quotation marks as regular +// characters inside of the string fields (ignoring RFC 4180, Section 2, +// Bullet 5). +// If not specified, defaults to true +func DecodeCSVUseQuoteDelim(value bool) DecodeCSVAttr { + return func(m optionalAttr) { + m["use_quote_delim"] = value + } +} + +// DecodeCSVNaValue sets the optional na_value attribute to value. +// +// value: Additional string to recognize as NA/NaN. +// If not specified, defaults to "" +func DecodeCSVNaValue(value string) DecodeCSVAttr { + return func(m optionalAttr) { + m["na_value"] = value + } +} + +// DecodeCSVSelectCols sets the optional select_cols attribute to value. +// If not specified, defaults to <> +func DecodeCSVSelectCols(value []int64) DecodeCSVAttr { + return func(m optionalAttr) { + m["select_cols"] = value + } +} + +// Convert CSV records to tensors. Each column maps to one tensor. +// +// RFC 4180 format is expected for the CSV records. +// (https://tools.ietf.org/html/rfc4180) +// Note that we allow leading and trailing spaces with int or float field. +// +// Arguments: +// records: Each string is a record/row in the csv and all records should have +// the same format. +// record_defaults: One tensor per column of the input record, with either a +// scalar default value for that column or an empty vector if the column is +// required. +// +// Returns Each tensor will have the same shape as records. +func DecodeCSV(scope *Scope, records tf.Output, record_defaults []tf.Output, optional ...DecodeCSVAttr) (output []tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "DecodeCSV", + Input: []tf.Input{ + records, tf.OutputList(record_defaults), + }, + Attrs: attrs, + } + op := scope.AddOperation(opspec) + if scope.Err() != nil { + return + } + var idx int + var err error + if output, idx, err = makeOutputList(op, idx, "output"); err != nil { + scope.UpdateErr("DecodeCSV", err) + return + } + return output +} + +// Convert JSON-encoded Example records to binary protocol buffer strings. +// +// This op translates a tensor containing Example records, encoded using +// the [standard JSON +// mapping](https://developers.google.com/protocol-buffers/docs/proto3#json), +// into a tensor containing the same records encoded as binary protocol +// buffers. The resulting tensor can then be fed to any of the other +// Example-parsing ops. +// +// Arguments: +// json_examples: Each string is a JSON object serialized according to the JSON +// mapping of the Example proto. +// +// Returns Each string is a binary Example protocol buffer corresponding +// to the respective element of `json_examples`. +func DecodeJSONExample(scope *Scope, json_examples tf.Output) (binary_examples tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "DecodeJSONExample", + Input: []tf.Input{ + json_examples, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // Transforms a Tensor into a serialized TensorProto proto. // // Arguments: @@ -10499,6 +10657,31 @@ func ParseExample(scope *Scope, serialized tf.Output, names tf.Output, sparse_ke return sparse_indices, sparse_values, sparse_shapes, dense_values } +// Compute the pairwise cross product. +// +// `a` and `b` must be the same shape; they can either be simple 3-element vectors, +// or any shape where the innermost dimension is 3. In the latter case, each pair +// of corresponding 3-element vectors is cross-multiplied independently. +// +// Arguments: +// a: A tensor containing 3-element vectors. +// b: Another tensor, of same type and shape as `a`. +// +// Returns Pairwise cross product of the vectors in `a` and `b`. +func Cross(scope *Scope, a tf.Output, b tf.Output) (product tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "Cross", + Input: []tf.Input{ + a, b, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // CudnnRNNAttr is an optional argument to CudnnRNN. type CudnnRNNAttr func(optionalAttr) @@ -11417,66 +11600,6 @@ func RandomStandardNormal(scope *Scope, shape tf.Output, dtype tf.DataType, opti return op.Output(0) } -// RandomUniformIntAttr is an optional argument to RandomUniformInt. -type RandomUniformIntAttr func(optionalAttr) - -// RandomUniformIntSeed sets the optional seed attribute to value. -// -// value: If either `seed` or `seed2` are set to be non-zero, the random number -// generator is seeded by the given seed. Otherwise, it is seeded by a -// random seed. -// If not specified, defaults to 0 -func RandomUniformIntSeed(value int64) RandomUniformIntAttr { - return func(m optionalAttr) { - m["seed"] = value - } -} - -// RandomUniformIntSeed2 sets the optional seed2 attribute to value. -// -// value: A second seed to avoid seed collision. -// If not specified, defaults to 0 -func RandomUniformIntSeed2(value int64) RandomUniformIntAttr { - return func(m optionalAttr) { - m["seed2"] = value - } -} - -// Outputs random integers from a uniform distribution. -// -// The generated values are uniform integers in the range `[minval, maxval)`. -// The lower bound `minval` is included in the range, while the upper bound -// `maxval` is excluded. -// -// The random integers are slightly biased unless `maxval - minval` is an exact -// power of two. The bias is small for values of `maxval - minval` significantly -// smaller than the range of the output (either `2^32` or `2^64`). -// -// Arguments: -// shape: The shape of the output tensor. -// minval: 0-D. Inclusive lower bound on the generated integers. -// maxval: 0-D. Exclusive upper bound on the generated integers. -// -// Returns A tensor of the specified shape filled with uniform random integers. -func RandomUniformInt(scope *Scope, shape tf.Output, minval tf.Output, maxval tf.Output, optional ...RandomUniformIntAttr) (output tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "RandomUniformInt", - Input: []tf.Input{ - shape, minval, maxval, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // FusedResizeAndPadConv2DAttr is an optional argument to FusedResizeAndPadConv2D. type FusedResizeAndPadConv2DAttr func(optionalAttr) @@ -13530,6 +13653,39 @@ func StatelessRandomNormal(scope *Scope, shape tf.Output, seed tf.Output, option return op.Output(0) } +// Computes the complementary error function of `x` element-wise. +func Erfc(scope *Scope, x tf.Output) (y tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "Erfc", + Input: []tf.Input{ + x, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + +// Returns the number of tensors in the input tensor list. +// +// input_handle: the input list +// length: the number of tensors in the list +func TensorListLength(scope *Scope, input_handle tf.Output) (length tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "TensorListLength", + Input: []tf.Input{ + input_handle, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // Determine the script codes of a given tensor of Unicode integer code points. // // This operation converts Unicode code points to script codes corresponding to @@ -13747,6 +13903,126 @@ func ResourceApplyMomentum(scope *Scope, var_ tf.Output, accum tf.Output, lr tf. return scope.AddOperation(opspec) } +// SubstrAttr is an optional argument to Substr. +type SubstrAttr func(optionalAttr) + +// SubstrUnit sets the optional unit attribute to value. +// +// value: The unit that is used to create the substring. One of: `"BYTE"` (for +// defining position and length by bytes) or `"UTF8_CHAR"` (for the UTF-8 +// encoded Unicode code points). The default is `"BYTE"`. Results are undefined if +// `unit=UTF8_CHAR` and the `input` strings do not contain structurally valid +// UTF-8. +// If not specified, defaults to "BYTE" +func SubstrUnit(value string) SubstrAttr { + return func(m optionalAttr) { + m["unit"] = value + } +} + +// Return substrings from `Tensor` of strings. +// +// For each string in the input `Tensor`, creates a substring starting at index +// `pos` with a total length of `len`. +// +// If `len` defines a substring that would extend beyond the length of the input +// string, then as many characters as possible are used. +// +// A negative `pos` indicates distance within the string backwards from the end. +// +// If `pos` specifies an index which is out of range for any of the input strings, +// then an `InvalidArgumentError` is thrown. +// +// `pos` and `len` must have the same shape, otherwise a `ValueError` is thrown on +// Op creation. +// +// *NOTE*: `Substr` supports broadcasting up to two dimensions. More about +// broadcasting +// [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html) +// +// --- +// +// Examples +// +// Using scalar `pos` and `len`: +// +// ```python +// input = [b'Hello', b'World'] +// position = 1 +// length = 3 +// +// output = [b'ell', b'orl'] +// ``` +// +// Using `pos` and `len` with same shape as `input`: +// +// ```python +// input = [[b'ten', b'eleven', b'twelve'], +// [b'thirteen', b'fourteen', b'fifteen'], +// [b'sixteen', b'seventeen', b'eighteen']] +// position = [[1, 2, 3], +// [1, 2, 3], +// [1, 2, 3]] +// length = [[2, 3, 4], +// [4, 3, 2], +// [5, 5, 5]] +// +// output = [[b'en', b'eve', b'lve'], +// [b'hirt', b'urt', b'te'], +// [b'ixtee', b'vente', b'hteen']] +// ``` +// +// Broadcasting `pos` and `len` onto `input`: +// +// ``` +// input = [[b'ten', b'eleven', b'twelve'], +// [b'thirteen', b'fourteen', b'fifteen'], +// [b'sixteen', b'seventeen', b'eighteen'], +// [b'nineteen', b'twenty', b'twentyone']] +// position = [1, 2, 3] +// length = [1, 2, 3] +// +// output = [[b'e', b'ev', b'lve'], +// [b'h', b'ur', b'tee'], +// [b'i', b've', b'hte'], +// [b'i', b'en', b'nty']] +// ``` +// +// Broadcasting `input` onto `pos` and `len`: +// +// ``` +// input = b'thirteen' +// position = [1, 5, 7] +// length = [3, 2, 1] +// +// output = [b'hir', b'ee', b'n'] +// ``` +// +// Arguments: +// input: Tensor of strings +// pos: Scalar defining the position of first character in each substring +// len: Scalar defining the number of characters to include in each substring +// +// Returns Tensor of substrings +func Substr(scope *Scope, input tf.Output, pos tf.Output, len tf.Output, optional ...SubstrAttr) (output tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "Substr", + Input: []tf.Input{ + input, pos, len, + }, + Attrs: attrs, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // Exits the current frame to its parent frame. // // Exit makes its input `data` available to the parent frame. @@ -14946,75 +15222,6 @@ func ResourceApplyAdagrad(scope *Scope, var_ tf.Output, accum tf.Output, lr tf.O return scope.AddOperation(opspec) } -// Return the shape of s0 op s1 with broadcast. -// -// Given `s0` and `s1`, tensors that represent shapes, compute `r0`, the -// broadcasted shape. `s0`, `s1` and `r0` are all integer vectors. -func BroadcastArgs(scope *Scope, s0 tf.Output, s1 tf.Output) (r0 tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "BroadcastArgs", - Input: []tf.Input{ - s0, s1, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// DataFormatDimMapAttr is an optional argument to DataFormatDimMap. -type DataFormatDimMapAttr func(optionalAttr) - -// DataFormatDimMapSrcFormat sets the optional src_format attribute to value. -// -// value: source data format. -// If not specified, defaults to "NHWC" -func DataFormatDimMapSrcFormat(value string) DataFormatDimMapAttr { - return func(m optionalAttr) { - m["src_format"] = value - } -} - -// DataFormatDimMapDstFormat sets the optional dst_format attribute to value. -// -// value: destination data format. -// If not specified, defaults to "NCHW" -func DataFormatDimMapDstFormat(value string) DataFormatDimMapAttr { - return func(m optionalAttr) { - m["dst_format"] = value - } -} - -// Returns the dimension index in the destination data format given the one in -// -// the source data format. -// -// Arguments: -// x: A Tensor with each element as a dimension index in source data format. -// Must be in the range [-4, 4). -// -// Returns A Tensor with each element as a dimension index in destination data format. -func DataFormatDimMap(scope *Scope, x tf.Output, optional ...DataFormatDimMapAttr) (y tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "DataFormatDimMap", - Input: []tf.Input{ - x, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Retrieves the tree ensemble resource stamp token, number of trees and growing statistics. // // Arguments: @@ -16696,6 +16903,124 @@ func SparseReduceSum(scope *Scope, input_indices tf.Output, input_values tf.Outp return op.Output(0) } +// SparseTensorDenseMatMulAttr is an optional argument to SparseTensorDenseMatMul. +type SparseTensorDenseMatMulAttr func(optionalAttr) + +// SparseTensorDenseMatMulAdjointA sets the optional adjoint_a attribute to value. +// +// value: Use the adjoint of A in the matrix multiply. If A is complex, this +// is transpose(conj(A)). Otherwise it's transpose(A). +// If not specified, defaults to false +func SparseTensorDenseMatMulAdjointA(value bool) SparseTensorDenseMatMulAttr { + return func(m optionalAttr) { + m["adjoint_a"] = value + } +} + +// SparseTensorDenseMatMulAdjointB sets the optional adjoint_b attribute to value. +// +// value: Use the adjoint of B in the matrix multiply. If B is complex, this +// is transpose(conj(B)). Otherwise it's transpose(B). +// If not specified, defaults to false +func SparseTensorDenseMatMulAdjointB(value bool) SparseTensorDenseMatMulAttr { + return func(m optionalAttr) { + m["adjoint_b"] = value + } +} + +// Multiply SparseTensor (of rank 2) "A" by dense matrix "B". +// +// No validity checking is performed on the indices of A. However, the following +// input format is recommended for optimal behavior: +// +// if adjoint_a == false: +// A should be sorted in lexicographically increasing order. Use SparseReorder +// if you're not sure. +// if adjoint_a == true: +// A should be sorted in order of increasing dimension 1 (i.e., "column major" +// order instead of "row major" order). +// +// Arguments: +// a_indices: 2-D. The `indices` of the `SparseTensor`, size `[nnz, 2]` Matrix. +// a_values: 1-D. The `values` of the `SparseTensor`, size `[nnz]` Vector. +// a_shape: 1-D. The `shape` of the `SparseTensor`, size `[2]` Vector. +// b: 2-D. A dense Matrix. +func SparseTensorDenseMatMul(scope *Scope, a_indices tf.Output, a_values tf.Output, a_shape tf.Output, b tf.Output, optional ...SparseTensorDenseMatMulAttr) (product tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "SparseTensorDenseMatMul", + Input: []tf.Input{ + a_indices, a_values, a_shape, b, + }, + Attrs: attrs, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + +// ResourceApplyRMSPropAttr is an optional argument to ResourceApplyRMSProp. +type ResourceApplyRMSPropAttr func(optionalAttr) + +// ResourceApplyRMSPropUseLocking sets the optional use_locking attribute to value. +// +// value: If `True`, updating of the var, ms, and mom tensors is protected +// by a lock; otherwise the behavior is undefined, but may exhibit less +// contention. +// If not specified, defaults to false +func ResourceApplyRMSPropUseLocking(value bool) ResourceApplyRMSPropAttr { + return func(m optionalAttr) { + m["use_locking"] = value + } +} + +// Update '*var' according to the RMSProp algorithm. +// +// Note that in dense implementation of this algorithm, ms and mom will +// update even if the grad is zero, but in this sparse implementation, ms +// and mom will not update in iterations during which the grad is zero. +// +// mean_square = decay * mean_square + (1-decay) * gradient ** 2 +// Delta = learning_rate * gradient / sqrt(mean_square + epsilon) +// +// ms <- rho * ms_{t-1} + (1-rho) * grad * grad +// mom <- momentum * mom_{t-1} + lr * grad / sqrt(ms + epsilon) +// var <- var - mom +// +// Arguments: +// var_: Should be from a Variable(). +// ms: Should be from a Variable(). +// mom: Should be from a Variable(). +// lr: Scaling factor. Must be a scalar. +// rho: Decay rate. Must be a scalar. +// +// epsilon: Ridge term. Must be a scalar. +// grad: The gradient. +// +// Returns the created operation. +func ResourceApplyRMSProp(scope *Scope, var_ tf.Output, ms tf.Output, mom tf.Output, lr tf.Output, rho tf.Output, momentum tf.Output, epsilon tf.Output, grad tf.Output, optional ...ResourceApplyRMSPropAttr) (o *tf.Operation) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "ResourceApplyRMSProp", + Input: []tf.Input{ + var_, ms, mom, lr, rho, momentum, epsilon, grad, + }, + Attrs: attrs, + } + return scope.AddOperation(opspec) +} + // Returns immutable tensor from memory region. // // The current implementation memmaps the tensor from a file. @@ -18017,119 +18342,6 @@ func ResourceApplyCenteredRMSProp(scope *Scope, var_ tf.Output, mg tf.Output, ms return scope.AddOperation(opspec) } -// Computes the gradient for the inverse of `x` wrt its input. -// -// Specifically, `grad = -dy * y*y`, where `y = 1/x`, and `dy` -// is the corresponding input gradient. -func ReciprocalGrad(scope *Scope, y tf.Output, dy tf.Output) (z tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "ReciprocalGrad", - Input: []tf.Input{ - y, dy, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// Returns the min of x and y (i.e. x < y ? x : y) element-wise. -// -// *NOTE*: `Minimum` supports broadcasting. More about broadcasting -// [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html) -func Minimum(scope *Scope, x tf.Output, y tf.Output) (z tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "Minimum", - Input: []tf.Input{ - x, y, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// MfccAttr is an optional argument to Mfcc. -type MfccAttr func(optionalAttr) - -// MfccUpperFrequencyLimit sets the optional upper_frequency_limit attribute to value. -// -// value: The highest frequency to use when calculating the -// ceptstrum. -// If not specified, defaults to 4000 -func MfccUpperFrequencyLimit(value float32) MfccAttr { - return func(m optionalAttr) { - m["upper_frequency_limit"] = value - } -} - -// MfccLowerFrequencyLimit sets the optional lower_frequency_limit attribute to value. -// -// value: The lowest frequency to use when calculating the -// ceptstrum. -// If not specified, defaults to 20 -func MfccLowerFrequencyLimit(value float32) MfccAttr { - return func(m optionalAttr) { - m["lower_frequency_limit"] = value - } -} - -// MfccFilterbankChannelCount sets the optional filterbank_channel_count attribute to value. -// -// value: Resolution of the Mel bank used internally. -// If not specified, defaults to 40 -func MfccFilterbankChannelCount(value int64) MfccAttr { - return func(m optionalAttr) { - m["filterbank_channel_count"] = value - } -} - -// MfccDctCoefficientCount sets the optional dct_coefficient_count attribute to value. -// -// value: How many output channels to produce per time slice. -// If not specified, defaults to 13 -func MfccDctCoefficientCount(value int64) MfccAttr { - return func(m optionalAttr) { - m["dct_coefficient_count"] = value - } -} - -// Transforms a spectrogram into a form that's useful for speech recognition. -// -// Mel Frequency Cepstral Coefficients are a way of representing audio data that's -// been effective as an input feature for machine learning. They are created by -// taking the spectrum of a spectrogram (a 'cepstrum'), and discarding some of the -// higher frequencies that are less significant to the human ear. They have a long -// history in the speech recognition world, and https://en.wikipedia.org/wiki/Mel-frequency_cepstrum -// is a good resource to learn more. -// -// Arguments: -// spectrogram: Typically produced by the Spectrogram op, with magnitude_squared -// set to true. -// sample_rate: How many samples per second the source audio used. -func Mfcc(scope *Scope, spectrogram tf.Output, sample_rate tf.Output, optional ...MfccAttr) (output tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "Mfcc", - Input: []tf.Input{ - spectrogram, sample_rate, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // AudioSummaryAttr is an optional argument to AudioSummary. type AudioSummaryAttr func(optionalAttr) @@ -18240,23 +18452,6 @@ func Qr(scope *Scope, input tf.Output, optional ...QrAttr) (q tf.Output, r tf.Ou return op.Output(0), op.Output(1) } -// Records the bytes size of each element of `input_dataset` in a StatsAggregator. -func BytesProducedStatsDataset(scope *Scope, input_dataset tf.Output, tag tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"output_types": output_types, "output_shapes": output_shapes} - opspec := tf.OpSpec{ - Type: "BytesProducedStatsDataset", - Input: []tf.Input{ - input_dataset, tag, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Check if the input matches the regex pattern. // // The input is a string tensor of any shape. The pattern is the @@ -18372,6 +18567,29 @@ func RFFT(scope *Scope, input tf.Output, fft_length tf.Output) (output tf.Output return op.Output(0) } +// Adds a value to the current value of a variable. +// +// Any ReadVariableOp with a control dependency on this op is guaranteed to +// see the incremented value or a subsequent newer one. +// +// Arguments: +// resource: handle to the resource in which to store the variable. +// value: the value by which the variable will be incremented. +// +// Returns the created operation. +func AssignAddVariableOp(scope *Scope, resource tf.Output, value tf.Output) (o *tf.Operation) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "AssignAddVariableOp", + Input: []tf.Input{ + resource, value, + }, + } + return scope.AddOperation(opspec) +} + // QuantizedReluAttr is an optional argument to QuantizedRelu. type QuantizedReluAttr func(optionalAttr) @@ -19161,149 +19379,6 @@ func TensorArrayV2(scope *Scope, size tf.Output, dtype tf.DataType, optional ... return op.Output(0) } -// DecodeCSVAttr is an optional argument to DecodeCSV. -type DecodeCSVAttr func(optionalAttr) - -// DecodeCSVFieldDelim sets the optional field_delim attribute to value. -// -// value: char delimiter to separate fields in a record. -// If not specified, defaults to "," -func DecodeCSVFieldDelim(value string) DecodeCSVAttr { - return func(m optionalAttr) { - m["field_delim"] = value - } -} - -// DecodeCSVUseQuoteDelim sets the optional use_quote_delim attribute to value. -// -// value: If false, treats double quotation marks as regular -// characters inside of the string fields (ignoring RFC 4180, Section 2, -// Bullet 5). -// If not specified, defaults to true -func DecodeCSVUseQuoteDelim(value bool) DecodeCSVAttr { - return func(m optionalAttr) { - m["use_quote_delim"] = value - } -} - -// DecodeCSVNaValue sets the optional na_value attribute to value. -// -// value: Additional string to recognize as NA/NaN. -// If not specified, defaults to "" -func DecodeCSVNaValue(value string) DecodeCSVAttr { - return func(m optionalAttr) { - m["na_value"] = value - } -} - -// DecodeCSVSelectCols sets the optional select_cols attribute to value. -// If not specified, defaults to <> -func DecodeCSVSelectCols(value []int64) DecodeCSVAttr { - return func(m optionalAttr) { - m["select_cols"] = value - } -} - -// Convert CSV records to tensors. Each column maps to one tensor. -// -// RFC 4180 format is expected for the CSV records. -// (https://tools.ietf.org/html/rfc4180) -// Note that we allow leading and trailing spaces with int or float field. -// -// Arguments: -// records: Each string is a record/row in the csv and all records should have -// the same format. -// record_defaults: One tensor per column of the input record, with either a -// scalar default value for that column or an empty vector if the column is -// required. -// -// Returns Each tensor will have the same shape as records. -func DecodeCSV(scope *Scope, records tf.Output, record_defaults []tf.Output, optional ...DecodeCSVAttr) (output []tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "DecodeCSV", - Input: []tf.Input{ - records, tf.OutputList(record_defaults), - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - if scope.Err() != nil { - return - } - var idx int - var err error - if output, idx, err = makeOutputList(op, idx, "output"); err != nil { - scope.UpdateErr("DecodeCSV", err) - return - } - return output -} - -// MapClearAttr is an optional argument to MapClear. -type MapClearAttr func(optionalAttr) - -// MapClearCapacity sets the optional capacity attribute to value. -// If not specified, defaults to 0 -// -// REQUIRES: value >= 0 -func MapClearCapacity(value int64) MapClearAttr { - return func(m optionalAttr) { - m["capacity"] = value - } -} - -// MapClearMemoryLimit sets the optional memory_limit attribute to value. -// If not specified, defaults to 0 -// -// REQUIRES: value >= 0 -func MapClearMemoryLimit(value int64) MapClearAttr { - return func(m optionalAttr) { - m["memory_limit"] = value - } -} - -// MapClearContainer sets the optional container attribute to value. -// If not specified, defaults to "" -func MapClearContainer(value string) MapClearAttr { - return func(m optionalAttr) { - m["container"] = value - } -} - -// MapClearSharedName sets the optional shared_name attribute to value. -// If not specified, defaults to "" -func MapClearSharedName(value string) MapClearAttr { - return func(m optionalAttr) { - m["shared_name"] = value - } -} - -// Op removes all elements in the underlying container. -// -// Returns the created operation. -func MapClear(scope *Scope, dtypes []tf.DataType, optional ...MapClearAttr) (o *tf.Operation) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"dtypes": dtypes} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "MapClear", - - Attrs: attrs, - } - return scope.AddOperation(opspec) -} - // ThreadUnsafeUnigramCandidateSamplerAttr is an optional argument to ThreadUnsafeUnigramCandidateSampler. type ThreadUnsafeUnigramCandidateSamplerAttr func(optionalAttr) @@ -19523,6 +19598,119 @@ func MutableDenseHashTableV2(scope *Scope, empty_key tf.Output, deleted_key tf.O return op.Output(0) } +// Computes the gradient for the inverse of `x` wrt its input. +// +// Specifically, `grad = -dy * y*y`, where `y = 1/x`, and `dy` +// is the corresponding input gradient. +func ReciprocalGrad(scope *Scope, y tf.Output, dy tf.Output) (z tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "ReciprocalGrad", + Input: []tf.Input{ + y, dy, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + +// Returns the min of x and y (i.e. x < y ? x : y) element-wise. +// +// *NOTE*: `Minimum` supports broadcasting. More about broadcasting +// [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html) +func Minimum(scope *Scope, x tf.Output, y tf.Output) (z tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "Minimum", + Input: []tf.Input{ + x, y, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + +// MfccAttr is an optional argument to Mfcc. +type MfccAttr func(optionalAttr) + +// MfccUpperFrequencyLimit sets the optional upper_frequency_limit attribute to value. +// +// value: The highest frequency to use when calculating the +// ceptstrum. +// If not specified, defaults to 4000 +func MfccUpperFrequencyLimit(value float32) MfccAttr { + return func(m optionalAttr) { + m["upper_frequency_limit"] = value + } +} + +// MfccLowerFrequencyLimit sets the optional lower_frequency_limit attribute to value. +// +// value: The lowest frequency to use when calculating the +// ceptstrum. +// If not specified, defaults to 20 +func MfccLowerFrequencyLimit(value float32) MfccAttr { + return func(m optionalAttr) { + m["lower_frequency_limit"] = value + } +} + +// MfccFilterbankChannelCount sets the optional filterbank_channel_count attribute to value. +// +// value: Resolution of the Mel bank used internally. +// If not specified, defaults to 40 +func MfccFilterbankChannelCount(value int64) MfccAttr { + return func(m optionalAttr) { + m["filterbank_channel_count"] = value + } +} + +// MfccDctCoefficientCount sets the optional dct_coefficient_count attribute to value. +// +// value: How many output channels to produce per time slice. +// If not specified, defaults to 13 +func MfccDctCoefficientCount(value int64) MfccAttr { + return func(m optionalAttr) { + m["dct_coefficient_count"] = value + } +} + +// Transforms a spectrogram into a form that's useful for speech recognition. +// +// Mel Frequency Cepstral Coefficients are a way of representing audio data that's +// been effective as an input feature for machine learning. They are created by +// taking the spectrum of a spectrogram (a 'cepstrum'), and discarding some of the +// higher frequencies that are less significant to the human ear. They have a long +// history in the speech recognition world, and https://en.wikipedia.org/wiki/Mel-frequency_cepstrum +// is a good resource to learn more. +// +// Arguments: +// spectrogram: Typically produced by the Spectrogram op, with magnitude_squared +// set to true. +// sample_rate: How many samples per second the source audio used. +func Mfcc(scope *Scope, spectrogram tf.Output, sample_rate tf.Output, optional ...MfccAttr) (output tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "Mfcc", + Input: []tf.Input{ + spectrogram, sample_rate, + }, + Attrs: attrs, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // Compute the Hurwitz zeta function \\(\zeta(x, q)\\). // // The Hurwitz zeta function is defined as: @@ -19627,63 +19815,6 @@ func IFFT2D(scope *Scope, input tf.Output) (output tf.Output) { return op.Output(0) } -// ResourceApplyRMSPropAttr is an optional argument to ResourceApplyRMSProp. -type ResourceApplyRMSPropAttr func(optionalAttr) - -// ResourceApplyRMSPropUseLocking sets the optional use_locking attribute to value. -// -// value: If `True`, updating of the var, ms, and mom tensors is protected -// by a lock; otherwise the behavior is undefined, but may exhibit less -// contention. -// If not specified, defaults to false -func ResourceApplyRMSPropUseLocking(value bool) ResourceApplyRMSPropAttr { - return func(m optionalAttr) { - m["use_locking"] = value - } -} - -// Update '*var' according to the RMSProp algorithm. -// -// Note that in dense implementation of this algorithm, ms and mom will -// update even if the grad is zero, but in this sparse implementation, ms -// and mom will not update in iterations during which the grad is zero. -// -// mean_square = decay * mean_square + (1-decay) * gradient ** 2 -// Delta = learning_rate * gradient / sqrt(mean_square + epsilon) -// -// ms <- rho * ms_{t-1} + (1-rho) * grad * grad -// mom <- momentum * mom_{t-1} + lr * grad / sqrt(ms + epsilon) -// var <- var - mom -// -// Arguments: -// var_: Should be from a Variable(). -// ms: Should be from a Variable(). -// mom: Should be from a Variable(). -// lr: Scaling factor. Must be a scalar. -// rho: Decay rate. Must be a scalar. -// -// epsilon: Ridge term. Must be a scalar. -// grad: The gradient. -// -// Returns the created operation. -func ResourceApplyRMSProp(scope *Scope, var_ tf.Output, ms tf.Output, mom tf.Output, lr tf.Output, rho tf.Output, momentum tf.Output, epsilon tf.Output, grad tf.Output, optional ...ResourceApplyRMSPropAttr) (o *tf.Operation) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "ResourceApplyRMSProp", - Input: []tf.Input{ - var_, ms, mom, lr, rho, momentum, epsilon, grad, - }, - Attrs: attrs, - } - return scope.AddOperation(opspec) -} - // Returns element-wise remainder of division. This emulates C semantics in that // // the result here is consistent with a truncating divide. E.g. `truncate(x / y) * @@ -20760,67 +20891,6 @@ func AddSparseToTensorsMap(scope *Scope, sparse_indices tf.Output, sparse_values return op.Output(0) } -// SparseTensorDenseMatMulAttr is an optional argument to SparseTensorDenseMatMul. -type SparseTensorDenseMatMulAttr func(optionalAttr) - -// SparseTensorDenseMatMulAdjointA sets the optional adjoint_a attribute to value. -// -// value: Use the adjoint of A in the matrix multiply. If A is complex, this -// is transpose(conj(A)). Otherwise it's transpose(A). -// If not specified, defaults to false -func SparseTensorDenseMatMulAdjointA(value bool) SparseTensorDenseMatMulAttr { - return func(m optionalAttr) { - m["adjoint_a"] = value - } -} - -// SparseTensorDenseMatMulAdjointB sets the optional adjoint_b attribute to value. -// -// value: Use the adjoint of B in the matrix multiply. If B is complex, this -// is transpose(conj(B)). Otherwise it's transpose(B). -// If not specified, defaults to false -func SparseTensorDenseMatMulAdjointB(value bool) SparseTensorDenseMatMulAttr { - return func(m optionalAttr) { - m["adjoint_b"] = value - } -} - -// Multiply SparseTensor (of rank 2) "A" by dense matrix "B". -// -// No validity checking is performed on the indices of A. However, the following -// input format is recommended for optimal behavior: -// -// if adjoint_a == false: -// A should be sorted in lexicographically increasing order. Use SparseReorder -// if you're not sure. -// if adjoint_a == true: -// A should be sorted in order of increasing dimension 1 (i.e., "column major" -// order instead of "row major" order). -// -// Arguments: -// a_indices: 2-D. The `indices` of the `SparseTensor`, size `[nnz, 2]` Matrix. -// a_values: 1-D. The `values` of the `SparseTensor`, size `[nnz]` Vector. -// a_shape: 1-D. The `shape` of the `SparseTensor`, size `[2]` Vector. -// b: 2-D. A dense Matrix. -func SparseTensorDenseMatMul(scope *Scope, a_indices tf.Output, a_values tf.Output, a_shape tf.Output, b tf.Output, optional ...SparseTensorDenseMatMulAttr) (product tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "SparseTensorDenseMatMul", - Input: []tf.Input{ - a_indices, a_values, a_shape, b, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Deserialize and concatenate `SparseTensors` from a serialized minibatch. // // The input `serialized_sparse` must be a string matrix of shape `[N x 3]` where @@ -20903,151 +20973,6 @@ func BitwiseAnd(scope *Scope, x tf.Output, y tf.Output) (z tf.Output) { return op.Output(0) } -// SubstrAttr is an optional argument to Substr. -type SubstrAttr func(optionalAttr) - -// SubstrUnit sets the optional unit attribute to value. -// -// value: The unit that is used to create the substring. One of: `"BYTE"` (for -// defining position and length by bytes) or `"UTF8_CHAR"` (for the UTF-8 -// encoded Unicode code points). The default is `"BYTE"`. Results are undefined if -// `unit=UTF8_CHAR` and the `input` strings do not contain structurally valid -// UTF-8. -// If not specified, defaults to "BYTE" -func SubstrUnit(value string) SubstrAttr { - return func(m optionalAttr) { - m["unit"] = value - } -} - -// Return substrings from `Tensor` of strings. -// -// For each string in the input `Tensor`, creates a substring starting at index -// `pos` with a total length of `len`. -// -// If `len` defines a substring that would extend beyond the length of the input -// string, then as many characters as possible are used. -// -// A negative `pos` indicates distance within the string backwards from the end. -// -// If `pos` specifies an index which is out of range for any of the input strings, -// then an `InvalidArgumentError` is thrown. -// -// `pos` and `len` must have the same shape, otherwise a `ValueError` is thrown on -// Op creation. -// -// *NOTE*: `Substr` supports broadcasting up to two dimensions. More about -// broadcasting -// [here](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html) -// -// --- -// -// Examples -// -// Using scalar `pos` and `len`: -// -// ```python -// input = [b'Hello', b'World'] -// position = 1 -// length = 3 -// -// output = [b'ell', b'orl'] -// ``` -// -// Using `pos` and `len` with same shape as `input`: -// -// ```python -// input = [[b'ten', b'eleven', b'twelve'], -// [b'thirteen', b'fourteen', b'fifteen'], -// [b'sixteen', b'seventeen', b'eighteen']] -// position = [[1, 2, 3], -// [1, 2, 3], -// [1, 2, 3]] -// length = [[2, 3, 4], -// [4, 3, 2], -// [5, 5, 5]] -// -// output = [[b'en', b'eve', b'lve'], -// [b'hirt', b'urt', b'te'], -// [b'ixtee', b'vente', b'hteen']] -// ``` -// -// Broadcasting `pos` and `len` onto `input`: -// -// ``` -// input = [[b'ten', b'eleven', b'twelve'], -// [b'thirteen', b'fourteen', b'fifteen'], -// [b'sixteen', b'seventeen', b'eighteen'], -// [b'nineteen', b'twenty', b'twentyone']] -// position = [1, 2, 3] -// length = [1, 2, 3] -// -// output = [[b'e', b'ev', b'lve'], -// [b'h', b'ur', b'tee'], -// [b'i', b've', b'hte'], -// [b'i', b'en', b'nty']] -// ``` -// -// Broadcasting `input` onto `pos` and `len`: -// -// ``` -// input = b'thirteen' -// position = [1, 5, 7] -// length = [3, 2, 1] -// -// output = [b'hir', b'ee', b'n'] -// ``` -// -// Arguments: -// input: Tensor of strings -// pos: Scalar defining the position of first character in each substring -// len: Scalar defining the number of characters to include in each substring -// -// Returns Tensor of substrings -func Substr(scope *Scope, input tf.Output, pos tf.Output, len tf.Output, optional ...SubstrAttr) (output tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "Substr", - Input: []tf.Input{ - input, pos, len, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// Creates a Dataset that returns pseudorandom numbers. -// -// Arguments: -// seed: A scalar seed for the random number generator. If either seed or -// seed2 is set to be non-zero, the random number generator is seeded -// by the given seed. Otherwise, a random seed is used. -// seed2: A second scalar seed to avoid seed collision. -// -// -func RandomDataset(scope *Scope, seed tf.Output, seed2 tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"output_types": output_types, "output_shapes": output_shapes} - opspec := tf.OpSpec{ - Type: "RandomDataset", - Input: []tf.Input{ - seed, seed2, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Inverse real-valued fast Fourier transform. // // Computes the inverse 1-dimensional discrete Fourier transform of a real-valued @@ -22230,6 +22155,34 @@ func MatrixTriangularSolve(scope *Scope, matrix tf.Output, rhs tf.Output, option return op.Output(0) } +// Saves tensors in V2 checkpoint format. +// +// By default, saves the named tensors in full. If the caller wishes to save +// specific slices of full tensors, "shape_and_slices" should be non-empty strings +// and correspondingly well-formed. +// +// Arguments: +// prefix: Must have a single element. The prefix of the V2 checkpoint to which we +// write the tensors. +// tensor_names: shape {N}. The names of the tensors to be saved. +// shape_and_slices: shape {N}. The slice specs of the tensors to be saved. +// Empty strings indicate that they are non-partitioned tensors. +// tensors: `N` tensors to save. +// +// Returns the created operation. +func SaveV2(scope *Scope, prefix tf.Output, tensor_names tf.Output, shape_and_slices tf.Output, tensors []tf.Output) (o *tf.Operation) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "SaveV2", + Input: []tf.Input{ + prefix, tensor_names, shape_and_slices, tf.OutputList(tensors), + }, + } + return scope.AddOperation(opspec) +} + // UnicodeTranscodeAttr is an optional argument to UnicodeTranscode. type UnicodeTranscodeAttr func(optionalAttr) @@ -25011,6 +24964,75 @@ func Cumsum(scope *Scope, x tf.Output, axis tf.Output, optional ...CumsumAttr) ( return op.Output(0) } +// Return the shape of s0 op s1 with broadcast. +// +// Given `s0` and `s1`, tensors that represent shapes, compute `r0`, the +// broadcasted shape. `s0`, `s1` and `r0` are all integer vectors. +func BroadcastArgs(scope *Scope, s0 tf.Output, s1 tf.Output) (r0 tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "BroadcastArgs", + Input: []tf.Input{ + s0, s1, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + +// DataFormatDimMapAttr is an optional argument to DataFormatDimMap. +type DataFormatDimMapAttr func(optionalAttr) + +// DataFormatDimMapSrcFormat sets the optional src_format attribute to value. +// +// value: source data format. +// If not specified, defaults to "NHWC" +func DataFormatDimMapSrcFormat(value string) DataFormatDimMapAttr { + return func(m optionalAttr) { + m["src_format"] = value + } +} + +// DataFormatDimMapDstFormat sets the optional dst_format attribute to value. +// +// value: destination data format. +// If not specified, defaults to "NCHW" +func DataFormatDimMapDstFormat(value string) DataFormatDimMapAttr { + return func(m optionalAttr) { + m["dst_format"] = value + } +} + +// Returns the dimension index in the destination data format given the one in +// +// the source data format. +// +// Arguments: +// x: A Tensor with each element as a dimension index in source data format. +// Must be in the range [-4, 4). +// +// Returns A Tensor with each element as a dimension index in destination data format. +func DataFormatDimMap(scope *Scope, x tf.Output, optional ...DataFormatDimMapAttr) (y tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "DataFormatDimMap", + Input: []tf.Input{ + x, + }, + Attrs: attrs, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // CumprodAttr is an optional argument to Cumprod. type CumprodAttr func(optionalAttr) @@ -26322,24 +26344,6 @@ func TensorArrayReadV3(scope *Scope, handle tf.Output, index tf.Output, flow_in return op.Output(0) } -// Computes the gradient for the tanh of `x` wrt its input. -// -// Specifically, `grad = dy * (1 - y*y)`, where `y = tanh(x)`, and `dy` -// is the corresponding input gradient. -func TanhGrad(scope *Scope, y tf.Output, dy tf.Output) (z tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "TanhGrad", - Input: []tf.Input{ - y, dy, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Reduces sparse updates into the variable referenced by `resource` using the `max` operation. // // This operation computes @@ -26381,6 +26385,24 @@ func ResourceScatterMax(scope *Scope, resource tf.Output, indices tf.Output, upd return scope.AddOperation(opspec) } +// Computes the gradient for the tanh of `x` wrt its input. +// +// Specifically, `grad = dy * (1 - y*y)`, where `y = tanh(x)`, and `dy` +// is the corresponding input gradient. +func TanhGrad(scope *Scope, y tf.Output, dy tf.Output) (z tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "TanhGrad", + Input: []tf.Input{ + y, dy, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // Outputs a `Summary` protocol buffer with scalar values. // // The input `tags` and `values` must have the same shape. The generated summary @@ -26669,24 +26691,6 @@ func MergeSummary(scope *Scope, inputs []tf.Output) (summary tf.Output) { return op.Output(0) } -// Returns the number of tensors in the input tensor list. -// -// input_handle: the input list -// length: the number of tensors in the list -func TensorListLength(scope *Scope, input_handle tf.Output) (length tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "TensorListLength", - Input: []tf.Input{ - input_handle, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // The shape of the elements of the given list, as a tensor. // // input_handle: the list @@ -27361,35 +27365,6 @@ func MatrixSquareRoot(scope *Scope, input tf.Output) (output tf.Output) { return op.Output(0) } -// Convert JSON-encoded Example records to binary protocol buffer strings. -// -// This op translates a tensor containing Example records, encoded using -// the [standard JSON -// mapping](https://developers.google.com/protocol-buffers/docs/proto3#json), -// into a tensor containing the same records encoded as binary protocol -// buffers. The resulting tensor can then be fed to any of the other -// Example-parsing ops. -// -// Arguments: -// json_examples: Each string is a JSON object serialized according to the JSON -// mapping of the Example proto. -// -// Returns Each string is a binary Example protocol buffer corresponding -// to the respective element of `json_examples`. -func DecodeJSONExample(scope *Scope, json_examples tf.Output) (binary_examples tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "DecodeJSONExample", - Input: []tf.Input{ - json_examples, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // SvdAttr is an optional argument to Svd. type SvdAttr func(optionalAttr) @@ -28426,6 +28401,49 @@ func ReaderReadUpToV2(scope *Scope, reader_handle tf.Output, queue_handle tf.Out return op.Output(0), op.Output(1) } +// Adds v into specified rows of x. +// +// Computes y = x; y[i, :] += v; return y. +// +// Arguments: +// x: A `Tensor` of type T. +// i: A vector. Indices into the left-most dimension of `x`. +// v: A `Tensor` of type T. Same dimension sizes as x except the first dimension, which must be the same as i's size. +// +// Returns A `Tensor` of type T. An alias of `x`. The content of `y` is undefined if there are duplicates in `i`. +func InplaceAdd(scope *Scope, x tf.Output, i tf.Output, v tf.Output) (y tf.Output) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "InplaceAdd", + Input: []tf.Input{ + x, i, v, + }, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + +// Restore a Reader to its initial clean state. +// +// Arguments: +// reader_handle: Handle to a Reader. +// +// Returns the created operation. +func ReaderResetV2(scope *Scope, reader_handle tf.Output) (o *tf.Operation) { + if scope.Err() != nil { + return + } + opspec := tf.OpSpec{ + Type: "ReaderResetV2", + Input: []tf.Input{ + reader_handle, + }, + } + return scope.AddOperation(opspec) +} + // BatchAttr is an optional argument to Batch. type BatchAttr func(optionalAttr) @@ -29711,71 +29729,6 @@ func CropAndResizeGradBoxes(scope *Scope, grads tf.Output, image tf.Output, boxe return op.Output(0) } -// Saves tensors in V2 checkpoint format. -// -// By default, saves the named tensors in full. If the caller wishes to save -// specific slices of full tensors, "shape_and_slices" should be non-empty strings -// and correspondingly well-formed. -// -// Arguments: -// prefix: Must have a single element. The prefix of the V2 checkpoint to which we -// write the tensors. -// tensor_names: shape {N}. The names of the tensors to be saved. -// shape_and_slices: shape {N}. The slice specs of the tensors to be saved. -// Empty strings indicate that they are non-partitioned tensors. -// tensors: `N` tensors to save. -// -// Returns the created operation. -func SaveV2(scope *Scope, prefix tf.Output, tensor_names tf.Output, shape_and_slices tf.Output, tensors []tf.Output) (o *tf.Operation) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "SaveV2", - Input: []tf.Input{ - prefix, tensor_names, shape_and_slices, tf.OutputList(tensors), - }, - } - return scope.AddOperation(opspec) -} - -// StatsAggregatorHandleAttr is an optional argument to StatsAggregatorHandle. -type StatsAggregatorHandleAttr func(optionalAttr) - -// StatsAggregatorHandleContainer sets the optional container attribute to value. -// If not specified, defaults to "" -func StatsAggregatorHandleContainer(value string) StatsAggregatorHandleAttr { - return func(m optionalAttr) { - m["container"] = value - } -} - -// StatsAggregatorHandleSharedName sets the optional shared_name attribute to value. -// If not specified, defaults to "" -func StatsAggregatorHandleSharedName(value string) StatsAggregatorHandleAttr { - return func(m optionalAttr) { - m["shared_name"] = value - } -} - -// Creates a statistics manager resource. -func StatsAggregatorHandle(scope *Scope, optional ...StatsAggregatorHandleAttr) (handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "StatsAggregatorHandle", - - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Greedily selects a subset of bounding boxes in descending order of score, // // pruning away boxes that have high intersection-over-union (IOU) overlap @@ -29955,116 +29908,64 @@ func FakeParam(scope *Scope, dtype tf.DataType, shape tf.Shape) (output tf.Outpu return op.Output(0) } -// A substitute for `InterleaveDataset` on a fixed list of `N` datasets. -// -// Arguments: -// selector_input_dataset: A dataset of scalar `DT_INT64` elements that determines which of the -// `N` data inputs should produce the next output element. -// data_input_datasets: `N` datasets with the same type that will be interleaved according to -// the values of `selector_input_dataset`. -// +// Computes the gradient for the inverse of `x` wrt its input. // -func ExperimentalDirectedInterleaveDataset(scope *Scope, selector_input_dataset tf.Output, data_input_datasets []tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (handle tf.Output) { +// Specifically, `grad = -dy * y*y`, where `y = 1/x`, and `dy` +// is the corresponding input gradient. +func InvGrad(scope *Scope, y tf.Output, dy tf.Output) (z tf.Output) { if scope.Err() != nil { return } - attrs := map[string]interface{}{"output_types": output_types, "output_shapes": output_shapes} opspec := tf.OpSpec{ - Type: "ExperimentalDirectedInterleaveDataset", + Type: "InvGrad", Input: []tf.Input{ - selector_input_dataset, tf.OutputList(data_input_datasets), + y, dy, }, - Attrs: attrs, } op := scope.AddOperation(opspec) return op.Output(0) } -// Gets the next element from a FunctionBufferingResource. -// -// Arguments: -// function_buffer_resource: The FunctionBufferingResource handle. -// output_types: The type list for the return values. +// List of the given size with empty elements. // -// Returns A list of return values. -func ExperimentalFunctionBufferingResourceGetNext(scope *Scope, function_buffer_resource tf.Output, output_types []tf.DataType) (output []tf.Output) { +// element_shape: the shape of the future elements of the list +// num_elements: the number of elements to reserve +// handle: the output list +// element_dtype: the desired type of elements in the list. +func TensorListReserve(scope *Scope, element_shape tf.Output, num_elements tf.Output, element_dtype tf.DataType) (handle tf.Output) { if scope.Err() != nil { return } - attrs := map[string]interface{}{"output_types": output_types} + attrs := map[string]interface{}{"element_dtype": element_dtype} opspec := tf.OpSpec{ - Type: "ExperimentalFunctionBufferingResourceGetNext", + Type: "TensorListReserve", Input: []tf.Input{ - function_buffer_resource, + element_shape, num_elements, }, Attrs: attrs, } op := scope.AddOperation(opspec) - if scope.Err() != nil { - return - } - var idx int - var err error - if output, idx, err = makeOutputList(op, idx, "output"); err != nil { - scope.UpdateErr("ExperimentalFunctionBufferingResourceGetNext", err) - return - } - return output -} - -// Adds v into specified rows of x. -// -// Computes y = x; y[i, :] += v; return y. -// -// Arguments: -// x: A `Tensor` of type T. -// i: A vector. Indices into the left-most dimension of `x`. -// v: A `Tensor` of type T. Same dimension sizes as x except the first dimension, which must be the same as i's size. -// -// Returns A `Tensor` of type T. An alias of `x`. The content of `y` is undefined if there are duplicates in `i`. -func InplaceAdd(scope *Scope, x tf.Output, i tf.Output, v tf.Output) (y tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "InplaceAdd", - Input: []tf.Input{ - x, i, v, - }, - } - op := scope.AddOperation(opspec) return op.Output(0) } -// Restore a Reader to its initial clean state. +// A substitute for `InterleaveDataset` on a fixed list of `N` datasets. // // Arguments: -// reader_handle: Handle to a Reader. +// selector_input_dataset: A dataset of scalar `DT_INT64` elements that determines which of the +// `N` data inputs should produce the next output element. +// data_input_datasets: `N` datasets with the same type that will be interleaved according to +// the values of `selector_input_dataset`. // -// Returns the created operation. -func ReaderResetV2(scope *Scope, reader_handle tf.Output) (o *tf.Operation) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "ReaderResetV2", - Input: []tf.Input{ - reader_handle, - }, - } - return scope.AddOperation(opspec) -} - -// A dataset that splits the elements of its input into multiple elements. -func UnbatchDataset(scope *Scope, input_dataset tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (handle tf.Output) { +// +func ExperimentalDirectedInterleaveDataset(scope *Scope, selector_input_dataset tf.Output, data_input_datasets []tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (handle tf.Output) { if scope.Err() != nil { return } attrs := map[string]interface{}{"output_types": output_types, "output_shapes": output_shapes} opspec := tf.OpSpec{ - Type: "UnbatchDataset", + Type: "ExperimentalDirectedInterleaveDataset", Input: []tf.Input{ - input_dataset, + selector_input_dataset, tf.OutputList(data_input_datasets), }, Attrs: attrs, } @@ -30072,184 +29973,48 @@ func UnbatchDataset(scope *Scope, input_dataset tf.Output, output_types []tf.Dat return op.Output(0) } -// OrderedMapStageAttr is an optional argument to OrderedMapStage. -type OrderedMapStageAttr func(optionalAttr) +// RandomUniformIntAttr is an optional argument to RandomUniformInt. +type RandomUniformIntAttr func(optionalAttr) -// OrderedMapStageCapacity sets the optional capacity attribute to value. -// -// value: Maximum number of elements in the Staging Area. If > 0, inserts -// on the container will block when the capacity is reached. -// If not specified, defaults to 0 +// RandomUniformIntSeed sets the optional seed attribute to value. // -// REQUIRES: value >= 0 -func OrderedMapStageCapacity(value int64) OrderedMapStageAttr { - return func(m optionalAttr) { - m["capacity"] = value - } -} - -// OrderedMapStageMemoryLimit sets the optional memory_limit attribute to value. +// value: If either `seed` or `seed2` are set to be non-zero, the random number +// generator is seeded by the given seed. Otherwise, it is seeded by a +// random seed. // If not specified, defaults to 0 -// -// REQUIRES: value >= 0 -func OrderedMapStageMemoryLimit(value int64) OrderedMapStageAttr { - return func(m optionalAttr) { - m["memory_limit"] = value - } -} - -// OrderedMapStageContainer sets the optional container attribute to value. -// -// value: If non-empty, this queue is placed in the given container. Otherwise, -// a default container is used. -// If not specified, defaults to "" -func OrderedMapStageContainer(value string) OrderedMapStageAttr { - return func(m optionalAttr) { - m["container"] = value - } -} - -// OrderedMapStageSharedName sets the optional shared_name attribute to value. -// -// value: It is necessary to match this name to the matching Unstage Op. -// If not specified, defaults to "" -func OrderedMapStageSharedName(value string) OrderedMapStageAttr { - return func(m optionalAttr) { - m["shared_name"] = value - } -} - -// Stage (key, values) in the underlying container which behaves like a ordered -// -// associative container. Elements are ordered by key. -// -// Arguments: -// key: int64 -// -// values: a list of tensors -// dtypes A list of data types that inserted values should adhere to. -// -// -// Returns the created operation. -func OrderedMapStage(scope *Scope, key tf.Output, indices tf.Output, values []tf.Output, dtypes []tf.DataType, optional ...OrderedMapStageAttr) (o *tf.Operation) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"dtypes": dtypes} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "OrderedMapStage", - Input: []tf.Input{ - key, indices, tf.OutputList(values), - }, - Attrs: attrs, - } - return scope.AddOperation(opspec) -} - -// RpcAttr is an optional argument to Rpc. -type RpcAttr func(optionalAttr) - -// RpcProtocol sets the optional protocol attribute to value. -// -// value: RPC protocol to use. Empty string means use the default protocol. -// Options include 'grpc'. -// If not specified, defaults to "" -func RpcProtocol(value string) RpcAttr { - return func(m optionalAttr) { - m["protocol"] = value - } -} - -// RpcFailFast sets the optional fail_fast attribute to value. -// -// value: `boolean`. If `true` (default), then failures to connect -// (i.e., the server does not immediately respond) cause an RPC failure. -// If not specified, defaults to true -func RpcFailFast(value bool) RpcAttr { +func RandomUniformIntSeed(value int64) RandomUniformIntAttr { return func(m optionalAttr) { - m["fail_fast"] = value + m["seed"] = value } } -// RpcTimeoutInMs sets the optional timeout_in_ms attribute to value. +// RandomUniformIntSeed2 sets the optional seed2 attribute to value. // -// value: `int`. If `0` (default), then the kernel will run the RPC -// request and only time out if the RPC deadline passes or the session times out. -// If this value is greater than `0`, then the op will raise an exception if -// the RPC takes longer than `timeout_in_ms`. +// value: A second seed to avoid seed collision. // If not specified, defaults to 0 -func RpcTimeoutInMs(value int64) RpcAttr { +func RandomUniformIntSeed2(value int64) RandomUniformIntAttr { return func(m optionalAttr) { - m["timeout_in_ms"] = value + m["seed2"] = value } } -// Perform batches of RPC requests. -// -// This op asynchronously performs either a single RPC request, or a batch -// of requests. RPC requests are defined by three main parameters: -// -// - `address` (the host+port or BNS address of the request) -// - `method` (the RPC method name for the request) -// - `request` (the serialized proto string, or vector of strings, -// of the RPC request argument). -// -// For example, if you have an RPC service running on port localhost:2345, -// and its interface is configured with the following proto declaration: -// -// ``` -// service MyService { -// rpc MyMethod(MyRequestProto) returns (MyResponseProto) { -// } -// }; -// ``` -// -// then call this op with arguments: -// -// ``` -// address = "localhost:2345" -// method = "MyService/MyMethod" -// ``` -// -// The `request` tensor is a string tensor representing serialized `MyRequestProto` -// strings; and the output string tensor `response` will have the same shape -// and contain (upon successful completion) corresponding serialized -// `MyResponseProto` strings. -// -// For example, to send a single, empty, `MyRequestProto`, call -// this op with `request = ""`. To send 5 **parallel** empty requests, -// call this op with `request = ["", "", "", "", ""]`. -// -// More generally, one can create a batch of `MyRequestProto` serialized protos -// from regular batched tensors using the `encode_proto` op, and convert -// the response `MyResponseProto` serialized protos to batched tensors -// using the `decode_proto` op. -// -// **NOTE** Working with serialized proto strings is faster than instantiating -// actual proto objects in memory, so no performance degradation is expected -// compared to writing custom kernels for this workflow. +// Outputs random integers from a uniform distribution. // -// If the connection fails or the remote worker returns an error -// status, the op reraises this exception locally. +// The generated values are uniform integers in the range `[minval, maxval)`. +// The lower bound `minval` is included in the range, while the upper bound +// `maxval` is excluded. // -// See the `TryRpc` op if you prefer to handle RPC failures manually in the graph. +// The random integers are slightly biased unless `maxval - minval` is an exact +// power of two. The bias is small for values of `maxval - minval` significantly +// smaller than the range of the output (either `2^32` or `2^64`). // // Arguments: -// address: `0-D` or `1-D`. The address (i.e. host_name:port) of the RPC server. -// If this tensor has more than 1 element, then multiple parallel rpc requests -// are sent. This argument broadcasts with `method` and `request`. -// method: `0-D` or `1-D`. The method address on the RPC server. -// If this tensor has more than 1 element, then multiple parallel rpc requests -// are sent. This argument broadcasts with `address` and `request`. -// request: `0-D` or `1-D`. Serialized proto strings: the rpc request argument. -// If this tensor has more than 1 element, then multiple parallel rpc requests -// are sent. This argument broadcasts with `address` and `method`. +// shape: The shape of the output tensor. +// minval: 0-D. Inclusive lower bound on the generated integers. +// maxval: 0-D. Exclusive upper bound on the generated integers. // -// Returns Same shape as `request`. Serialized proto strings: the rpc responses. -func Rpc(scope *Scope, address tf.Output, method tf.Output, request tf.Output, optional ...RpcAttr) (response tf.Output) { +// Returns A tensor of the specified shape filled with uniform random integers. +func RandomUniformInt(scope *Scope, shape tf.Output, minval tf.Output, maxval tf.Output, optional ...RandomUniformIntAttr) (output tf.Output) { if scope.Err() != nil { return } @@ -30258,9 +30023,9 @@ func Rpc(scope *Scope, address tf.Output, method tf.Output, request tf.Output, o a(attrs) } opspec := tf.OpSpec{ - Type: "Rpc", + Type: "RandomUniformInt", Input: []tf.Input{ - address, method, request, + shape, minval, maxval, }, Attrs: attrs, } @@ -30268,59 +30033,25 @@ func Rpc(scope *Scope, address tf.Output, method tf.Output, request tf.Output, o return op.Output(0) } -// StackPushV2Attr is an optional argument to StackPushV2. -type StackPushV2Attr func(optionalAttr) - -// StackPushV2SwapMemory sets the optional swap_memory attribute to value. -// -// value: Swap `elem` to CPU. Default to false. -// If not specified, defaults to false -func StackPushV2SwapMemory(value bool) StackPushV2Attr { - return func(m optionalAttr) { - m["swap_memory"] = value - } -} - -// Push an element onto the stack. -// -// Arguments: -// handle: The handle to a stack. -// elem: The tensor to be pushed onto the stack. +// Add the quantile summaries to each quantile stream resource. // -// Returns The same tensor as the input 'elem'. -func StackPushV2(scope *Scope, handle tf.Output, elem tf.Output, optional ...StackPushV2Attr) (output tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "StackPushV2", - Input: []tf.Input{ - handle, elem, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// Resets the FunctionBufferingResource. +// An op that adds a list of quantile summaries to a quantile stream resource. Each +// summary Tensor is rank 2, containing summaries (value, weight, min_rank, max_rank) +// for a single feature. // // Arguments: -// function_buffer_resource: The FunctionBufferingResource handle. +// quantile_stream_resource_handle: resource handle referring to a QuantileStreamResource. +// summaries: string; List of Rank 2 Tensor each containing the summaries for a single feature. // // Returns the created operation. -func ExperimentalFunctionBufferingResourceReset(scope *Scope, function_buffer_resource tf.Output) (o *tf.Operation) { +func BoostedTreesQuantileStreamResourceAddSummaries(scope *Scope, quantile_stream_resource_handle tf.Output, summaries []tf.Output) (o *tf.Operation) { if scope.Err() != nil { return } opspec := tf.OpSpec{ - Type: "ExperimentalFunctionBufferingResourceReset", + Type: "BoostedTreesQuantileStreamResourceAddSummaries", Input: []tf.Input{ - function_buffer_resource, + quantile_stream_resource_handle, tf.OutputList(summaries), }, } return scope.AddOperation(opspec) @@ -30615,168 +30346,6 @@ func ConcatenateDataset(scope *Scope, input_dataset tf.Output, another_dataset t return op.Output(0) } -// Adds a value to the current value of a variable. -// -// Any ReadVariableOp with a control dependency on this op is guaranteed to -// see the incremented value or a subsequent newer one. -// -// Arguments: -// resource: handle to the resource in which to store the variable. -// value: the value by which the variable will be incremented. -// -// Returns the created operation. -func AssignAddVariableOp(scope *Scope, resource tf.Output, value tf.Output) (o *tf.Operation) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "AssignAddVariableOp", - Input: []tf.Input{ - resource, value, - }, - } - return scope.AddOperation(opspec) -} - -// Records the latency of producing `input_dataset` elements in a StatsAggregator. -func LatencyStatsDataset(scope *Scope, input_dataset tf.Output, tag tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"output_types": output_types, "output_shapes": output_shapes} - opspec := tf.OpSpec{ - Type: "LatencyStatsDataset", - Input: []tf.Input{ - input_dataset, tag, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// MapSizeAttr is an optional argument to MapSize. -type MapSizeAttr func(optionalAttr) - -// MapSizeCapacity sets the optional capacity attribute to value. -// If not specified, defaults to 0 -// -// REQUIRES: value >= 0 -func MapSizeCapacity(value int64) MapSizeAttr { - return func(m optionalAttr) { - m["capacity"] = value - } -} - -// MapSizeMemoryLimit sets the optional memory_limit attribute to value. -// If not specified, defaults to 0 -// -// REQUIRES: value >= 0 -func MapSizeMemoryLimit(value int64) MapSizeAttr { - return func(m optionalAttr) { - m["memory_limit"] = value - } -} - -// MapSizeContainer sets the optional container attribute to value. -// If not specified, defaults to "" -func MapSizeContainer(value string) MapSizeAttr { - return func(m optionalAttr) { - m["container"] = value - } -} - -// MapSizeSharedName sets the optional shared_name attribute to value. -// If not specified, defaults to "" -func MapSizeSharedName(value string) MapSizeAttr { - return func(m optionalAttr) { - m["shared_name"] = value - } -} - -// Op returns the number of elements in the underlying container. -func MapSize(scope *Scope, dtypes []tf.DataType, optional ...MapSizeAttr) (size tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"dtypes": dtypes} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "MapSize", - - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// SparseToDenseAttr is an optional argument to SparseToDense. -type SparseToDenseAttr func(optionalAttr) - -// SparseToDenseValidateIndices sets the optional validate_indices attribute to value. -// -// value: If true, indices are checked to make sure they are sorted in -// lexicographic order and that there are no repeats. -// If not specified, defaults to true -func SparseToDenseValidateIndices(value bool) SparseToDenseAttr { - return func(m optionalAttr) { - m["validate_indices"] = value - } -} - -// Converts a sparse representation into a dense tensor. -// -// Builds an array `dense` with shape `output_shape` such that -// -// ``` -// # If sparse_indices is scalar -// dense[i] = (i == sparse_indices ? sparse_values : default_value) -// -// # If sparse_indices is a vector, then for each i -// dense[sparse_indices[i]] = sparse_values[i] -// -// # If sparse_indices is an n by d matrix, then for each i in [0, n) -// dense[sparse_indices[i][0], ..., sparse_indices[i][d-1]] = sparse_values[i] -// ``` -// -// All other values in `dense` are set to `default_value`. If `sparse_values` is a -// scalar, all sparse indices are set to this single value. -// -// Indices should be sorted in lexicographic order, and indices must not -// contain any repeats. If `validate_indices` is true, these properties -// are checked during execution. -// -// Arguments: -// sparse_indices: 0-D, 1-D, or 2-D. `sparse_indices[i]` contains the complete -// index where `sparse_values[i]` will be placed. -// output_shape: 1-D. Shape of the dense output tensor. -// sparse_values: 1-D. Values corresponding to each row of `sparse_indices`, -// or a scalar value to be used for all sparse indices. -// default_value: Scalar value to set for indices not specified in -// `sparse_indices`. -// -// Returns Dense output tensor of shape `output_shape`. -func SparseToDense(scope *Scope, sparse_indices tf.Output, output_shape tf.Output, sparse_values tf.Output, default_value tf.Output, optional ...SparseToDenseAttr) (dense tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{} - for _, a := range optional { - a(attrs) - } - opspec := tf.OpSpec{ - Type: "SparseToDense", - Input: []tf.Input{ - sparse_indices, output_shape, sparse_values, default_value, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Computes the grayscale dilation of 4-D `input` and 3-D `filter` tensors. // // The `input` tensor has shape `[batch, in_height, in_width, depth]` and the @@ -30910,52 +30479,6 @@ func PaddedBatchDataset(scope *Scope, input_dataset tf.Output, batch_size tf.Out return op.Output(0) } -// Creates a dataset that batches input elements into a SparseTensor. -// -// Arguments: -// input_dataset: A handle to an input dataset. Must have a single component. -// batch_size: A scalar representing the number of elements to accumulate in a -// batch. -// row_shape: A vector representing the dense shape of each row in the produced -// SparseTensor. The shape may be partially specified, using `-1` to indicate -// that a particular dimension should use the maximum size of all batch elements. -// -// -func DenseToSparseBatchDataset(scope *Scope, input_dataset tf.Output, batch_size tf.Output, row_shape tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"output_types": output_types, "output_shapes": output_shapes} - opspec := tf.OpSpec{ - Type: "DenseToSparseBatchDataset", - Input: []tf.Input{ - input_dataset, batch_size, row_shape, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// Deprecated. Use TensorArrayGradV3 -// -// DEPRECATED at GraphDef version 26: Use TensorArrayGradV3 -func TensorArrayGradV2(scope *Scope, handle tf.Output, flow_in tf.Output, source string) (grad_handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"source": source} - opspec := tf.OpSpec{ - Type: "TensorArrayGradV2", - Input: []tf.Input{ - handle, flow_in, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Creates a dataset that shuffles and repeats elements from `input_dataset` // // pseudorandomly. @@ -31561,46 +31084,6 @@ func FIFOQueueV2(scope *Scope, component_types []tf.DataType, optional ...FIFOQu return op.Output(0) } -// Produces a summary of any statistics recorded by the given statistics manager. -func StatsAggregatorSummary(scope *Scope, iterator tf.Output) (summary tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "StatsAggregatorSummary", - Input: []tf.Input{ - iterator, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// Compute the pairwise cross product. -// -// `a` and `b` must be the same shape; they can either be simple 3-element vectors, -// or any shape where the innermost dimension is 3. In the latter case, each pair -// of corresponding 3-element vectors is cross-multiplied independently. -// -// Arguments: -// a: A tensor containing 3-element vectors. -// b: Another tensor, of same type and shape as `a`. -// -// Returns Pairwise cross product of the vectors in `a` and `b`. -func Cross(scope *Scope, a tf.Output, b tf.Output) (product tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "Cross", - Input: []tf.Input{ - a, b, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Constructs an Optional variant from a tuple of tensors. func OptionalFromValue(scope *Scope, components []tf.Output) (optional tf.Output) { if scope.Err() != nil { @@ -31769,30 +31252,6 @@ func OptionalHasValue(scope *Scope, optional tf.Output) (has_value tf.Output) { return op.Output(0) } -// Creates a dataset that executes a SQL query and emits rows of the result set. -// -// Arguments: -// driver_name: The database type. Currently, the only supported type is 'sqlite'. -// data_source_name: A connection string to connect to the database. -// query: A SQL query to execute. -// -// -func SqlDataset(scope *Scope, driver_name tf.Output, data_source_name tf.Output, query tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"output_types": output_types, "output_shapes": output_shapes} - opspec := tf.OpSpec{ - Type: "SqlDataset", - Input: []tf.Input{ - driver_name, data_source_name, query, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // Returns the value stored in an Optional variant or raises an error if none exists. func OptionalGetValue(scope *Scope, optional tf.Output, output_types []tf.DataType, output_shapes []tf.Shape) (components []tf.Output) { if scope.Err() != nil { @@ -32208,46 +31667,6 @@ func ParallelDynamicStitch(scope *Scope, indices []tf.Output, data []tf.Output) return op.Output(0) } -// Computes the gradient for the inverse of `x` wrt its input. -// -// Specifically, `grad = -dy * y*y`, where `y = 1/x`, and `dy` -// is the corresponding input gradient. -func InvGrad(scope *Scope, y tf.Output, dy tf.Output) (z tf.Output) { - if scope.Err() != nil { - return - } - opspec := tf.OpSpec{ - Type: "InvGrad", - Input: []tf.Input{ - y, dy, - }, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - -// List of the given size with empty elements. -// -// element_shape: the shape of the future elements of the list -// num_elements: the number of elements to reserve -// handle: the output list -// element_dtype: the desired type of elements in the list. -func TensorListReserve(scope *Scope, element_shape tf.Output, num_elements tf.Output, element_dtype tf.DataType) (handle tf.Output) { - if scope.Err() != nil { - return - } - attrs := map[string]interface{}{"element_dtype": element_dtype} - opspec := tf.OpSpec{ - Type: "TensorListReserve", - Input: []tf.Input{ - element_shape, num_elements, - }, - Attrs: attrs, - } - op := scope.AddOperation(opspec) - return op.Output(0) -} - // PriorityQueueV2Attr is an optional argument to PriorityQueueV2. type PriorityQueueV2Attr func(optionalAttr) @@ -32786,6 +32205,241 @@ func StackV2(scope *Scope, max_size tf.Output, elem_type tf.DataType, optional . return op.Output(0) } +// OrderedMapStageAttr is an optional argument to OrderedMapStage. +type OrderedMapStageAttr func(optionalAttr) + +// OrderedMapStageCapacity sets the optional capacity attribute to value. +// +// value: Maximum number of elements in the Staging Area. If > 0, inserts +// on the container will block when the capacity is reached. +// If not specified, defaults to 0 +// +// REQUIRES: value >= 0 +func OrderedMapStageCapacity(value int64) OrderedMapStageAttr { + return func(m optionalAttr) { + m["capacity"] = value + } +} + +// OrderedMapStageMemoryLimit sets the optional memory_limit attribute to value. +// If not specified, defaults to 0 +// +// REQUIRES: value >= 0 +func OrderedMapStageMemoryLimit(value int64) OrderedMapStageAttr { + return func(m optionalAttr) { + m["memory_limit"] = value + } +} + +// OrderedMapStageContainer sets the optional container attribute to value. +// +// value: If non-empty, this queue is placed in the given container. Otherwise, +// a default container is used. +// If not specified, defaults to "" +func OrderedMapStageContainer(value string) OrderedMapStageAttr { + return func(m optionalAttr) { + m["container"] = value + } +} + +// OrderedMapStageSharedName sets the optional shared_name attribute to value. +// +// value: It is necessary to match this name to the matching Unstage Op. +// If not specified, defaults to "" +func OrderedMapStageSharedName(value string) OrderedMapStageAttr { + return func(m optionalAttr) { + m["shared_name"] = value + } +} + +// Stage (key, values) in the underlying container which behaves like a ordered +// +// associative container. Elements are ordered by key. +// +// Arguments: +// key: int64 +// +// values: a list of tensors +// dtypes A list of data types that inserted values should adhere to. +// +// +// Returns the created operation. +func OrderedMapStage(scope *Scope, key tf.Output, indices tf.Output, values []tf.Output, dtypes []tf.DataType, optional ...OrderedMapStageAttr) (o *tf.Operation) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{"dtypes": dtypes} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "OrderedMapStage", + Input: []tf.Input{ + key, indices, tf.OutputList(values), + }, + Attrs: attrs, + } + return scope.AddOperation(opspec) +} + +// RpcAttr is an optional argument to Rpc. +type RpcAttr func(optionalAttr) + +// RpcProtocol sets the optional protocol attribute to value. +// +// value: RPC protocol to use. Empty string means use the default protocol. +// Options include 'grpc'. +// If not specified, defaults to "" +func RpcProtocol(value string) RpcAttr { + return func(m optionalAttr) { + m["protocol"] = value + } +} + +// RpcFailFast sets the optional fail_fast attribute to value. +// +// value: `boolean`. If `true` (default), then failures to connect +// (i.e., the server does not immediately respond) cause an RPC failure. +// If not specified, defaults to true +func RpcFailFast(value bool) RpcAttr { + return func(m optionalAttr) { + m["fail_fast"] = value + } +} + +// RpcTimeoutInMs sets the optional timeout_in_ms attribute to value. +// +// value: `int`. If `0` (default), then the kernel will run the RPC +// request and only time out if the RPC deadline passes or the session times out. +// If this value is greater than `0`, then the op will raise an exception if +// the RPC takes longer than `timeout_in_ms`. +// If not specified, defaults to 0 +func RpcTimeoutInMs(value int64) RpcAttr { + return func(m optionalAttr) { + m["timeout_in_ms"] = value + } +} + +// Perform batches of RPC requests. +// +// This op asynchronously performs either a single RPC request, or a batch +// of requests. RPC requests are defined by three main parameters: +// +// - `address` (the host+port or BNS address of the request) +// - `method` (the RPC method name for the request) +// - `request` (the serialized proto string, or vector of strings, +// of the RPC request argument). +// +// For example, if you have an RPC service running on port localhost:2345, +// and its interface is configured with the following proto declaration: +// +// ``` +// service MyService { +// rpc MyMethod(MyRequestProto) returns (MyResponseProto) { +// } +// }; +// ``` +// +// then call this op with arguments: +// +// ``` +// address = "localhost:2345" +// method = "MyService/MyMethod" +// ``` +// +// The `request` tensor is a string tensor representing serialized `MyRequestProto` +// strings; and the output string tensor `response` will have the same shape +// and contain (upon successful completion) corresponding serialized +// `MyResponseProto` strings. +// +// For example, to send a single, empty, `MyRequestProto`, call +// this op with `request = ""`. To send 5 **parallel** empty requests, +// call this op with `request = ["", "", "", "", ""]`. +// +// More generally, one can create a batch of `MyRequestProto` serialized protos +// from regular batched tensors using the `encode_proto` op, and convert +// the response `MyResponseProto` serialized protos to batched tensors +// using the `decode_proto` op. +// +// **NOTE** Working with serialized proto strings is faster than instantiating +// actual proto objects in memory, so no performance degradation is expected +// compared to writing custom kernels for this workflow. +// +// If the connection fails or the remote worker returns an error +// status, the op reraises this exception locally. +// +// See the `TryRpc` op if you prefer to handle RPC failures manually in the graph. +// +// Arguments: +// address: `0-D` or `1-D`. The address (i.e. host_name:port) of the RPC server. +// If this tensor has more than 1 element, then multiple parallel rpc requests +// are sent. This argument broadcasts with `method` and `request`. +// method: `0-D` or `1-D`. The method address on the RPC server. +// If this tensor has more than 1 element, then multiple parallel rpc requests +// are sent. This argument broadcasts with `address` and `request`. +// request: `0-D` or `1-D`. Serialized proto strings: the rpc request argument. +// If this tensor has more than 1 element, then multiple parallel rpc requests +// are sent. This argument broadcasts with `address` and `method`. +// +// Returns Same shape as `request`. Serialized proto strings: the rpc responses. +func Rpc(scope *Scope, address tf.Output, method tf.Output, request tf.Output, optional ...RpcAttr) (response tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "Rpc", + Input: []tf.Input{ + address, method, request, + }, + Attrs: attrs, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + +// StackPushV2Attr is an optional argument to StackPushV2. +type StackPushV2Attr func(optionalAttr) + +// StackPushV2SwapMemory sets the optional swap_memory attribute to value. +// +// value: Swap `elem` to CPU. Default to false. +// If not specified, defaults to false +func StackPushV2SwapMemory(value bool) StackPushV2Attr { + return func(m optionalAttr) { + m["swap_memory"] = value + } +} + +// Push an element onto the stack. +// +// Arguments: +// handle: The handle to a stack. +// elem: The tensor to be pushed onto the stack. +// +// Returns The same tensor as the input 'elem'. +func StackPushV2(scope *Scope, handle tf.Output, elem tf.Output, optional ...StackPushV2Attr) (output tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{} + for _, a := range optional { + a(attrs) + } + opspec := tf.OpSpec{ + Type: "StackPushV2", + Input: []tf.Input{ + handle, elem, + }, + Attrs: attrs, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // FusedBatchNormGradV2Attr is an optional argument to FusedBatchNormGradV2. type FusedBatchNormGradV2Attr func(optionalAttr) @@ -33169,6 +32823,25 @@ func TensorArraySizeV3(scope *Scope, handle tf.Output, flow_in tf.Output) (size return op.Output(0) } +// Deprecated. Use TensorArrayGradV3 +// +// DEPRECATED at GraphDef version 26: Use TensorArrayGradV3 +func TensorArrayGradV2(scope *Scope, handle tf.Output, flow_in tf.Output, source string) (grad_handle tf.Output) { + if scope.Err() != nil { + return + } + attrs := map[string]interface{}{"source": source} + opspec := tf.OpSpec{ + Type: "TensorArrayGradV2", + Input: []tf.Input{ + handle, flow_in, + }, + Attrs: attrs, + } + op := scope.AddOperation(opspec) + return op.Output(0) +} + // SparseReduceMaxAttr is an optional argument to SparseReduceMax. type SparseReduceMaxAttr func(optionalAttr) @@ -33941,47 +33614,47 @@ func MapUnstage(scope *Scope, key tf.Output, indices tf.Output, dtypes []tf.Data return values } -// MapIncompleteSizeAttr is an optional argument to MapIncompleteSize. -type MapIncompleteSizeAttr func(optionalAttr) +// MapSizeAttr is an optional argument to MapSize. +type MapSizeAttr func(optionalAttr) -// MapIncompleteSizeCapacity sets the optional capacity attribute to value. +// MapSizeCapacity sets the optional capacity attribute to value. // If not specified, defaults to 0 // // REQUIRES: value >= 0 -func MapIncompleteSizeCapacity(value int64) MapIncompleteSizeAttr { +func MapSizeCapacity(value int64) MapSizeAttr { return func(m optionalAttr) { m["capacity"] = value } } -// MapIncompleteSizeMemoryLimit sets the optional memory_limit attribute to value. +// MapSizeMemoryLimit sets the optional memory_limit attribute to value. // If not specified, defaults to 0 // // REQUIRES: value >= 0 -func MapIncompleteSizeMemoryLimit(value int64) MapIncompleteSizeAttr { +func MapSizeMemoryLimit(value int64) MapSizeAttr { return func(m optionalAttr) { m["memory_limit"] = value } } -// MapIncompleteSizeContainer sets the optional container attribute to value. +// MapSizeContainer sets the optional container attribute to value. // If not specified, defaults to "" -func MapIncompleteSizeContainer(value string) MapIncompleteSizeAttr { +func MapSizeContainer(value string) MapSizeAttr { return func(m optionalAttr) { m["container"] = value } } -// MapIncompleteSizeSharedName sets the optional shared_name attribute to value. +// MapSizeSharedName sets the optional shared_name attribute to value. // If not specified, defaults to "" -func MapIncompleteSizeSharedName(value string) MapIncompleteSizeAttr { +func MapSizeSharedName(value string) MapSizeAttr { return func(m optionalAttr) { m["shared_name"] = value } } -// Op returns the number of incomplete elements in the underlying container. -func MapIncompleteSize(scope *Scope, dtypes []tf.DataType, optional ...MapIncompleteSizeAttr) (size tf.Output) { +// Op returns the number of elements in the underlying container. +func MapSize(scope *Scope, dtypes []tf.DataType, optional ...MapSizeAttr) (size tf.Output) { if scope.Err() != nil { return } @@ -33990,7 +33663,7 @@ func MapIncompleteSize(scope *Scope, dtypes []tf.DataType, optional ...MapIncomp a(attrs) } opspec := tf.OpSpec{ - Type: "MapIncompleteSize", + Type: "MapSize", Attrs: attrs, } diff --git a/tensorflow/java/README.md b/tensorflow/java/README.md index 2fa81ed88f..6415290745 100644 --- a/tensorflow/java/README.md +++ b/tensorflow/java/README.md @@ -1,7 +1,7 @@ # TensorFlow for Java > *WARNING*: The TensorFlow Java API is not currently covered by the TensorFlow -> [API stability guarantees](https://www.tensorflow.org/guide/version_semantics). +> [API stability guarantees](https://www.tensorflow.org/guide/version_compat). > > For using TensorFlow on Android refer instead to > [contrib/android](https://www.tensorflow.org/code/tensorflow/contrib/android), diff --git a/tensorflow/java/src/test/java/org/tensorflow/TensorTest.java b/tensorflow/java/src/test/java/org/tensorflow/TensorTest.java index 1bd00a763d..3229cce277 100644 --- a/tensorflow/java/src/test/java/org/tensorflow/TensorTest.java +++ b/tensorflow/java/src/test/java/org/tensorflow/TensorTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.DoubleBuffer; @@ -100,7 +101,7 @@ public class TensorTest { : ByteOrder.LITTLE_ENDIAN) .asDoubleBuffer() .put(doubles); - buf.flip(); + flipBuffer(buf); try (Tensor t = Tensor.create(new long[] {doubles.length}, buf)) { double[] actual = new double[doubles.length]; assertArrayEquals(doubles, t.copyTo(actual), EPSILON); @@ -179,30 +180,30 @@ public class TensorTest { { ByteBuffer bbuf = ByteBuffer.allocate(1024).order(ByteOrder.nativeOrder()); - bbuf.clear(); // FLOAT + clearBuffer(bbuf); // FLOAT tfloats.writeTo(bbuf); assertEquals(tfloats.numBytes(), bbuf.position()); - bbuf.flip(); + flipBuffer(bbuf); assertEquals(floats[0], bbuf.asFloatBuffer().get(0), EPSILON); - bbuf.clear(); // DOUBLE + clearBuffer(bbuf); // DOUBLE tdoubles.writeTo(bbuf); assertEquals(tdoubles.numBytes(), bbuf.position()); - bbuf.flip(); + flipBuffer(bbuf); assertEquals(doubles[0], bbuf.asDoubleBuffer().get(0), EPSILON); - bbuf.clear(); // INT32 + clearBuffer(bbuf); // INT32 tints.writeTo(bbuf); assertEquals(tints.numBytes(), bbuf.position()); - bbuf.flip(); + flipBuffer(bbuf); assertEquals(ints[0], bbuf.asIntBuffer().get(0)); - bbuf.clear(); // INT64 + clearBuffer(bbuf); // INT64 tlongs.writeTo(bbuf); assertEquals(tlongs.numBytes(), bbuf.position()); - bbuf.flip(); + flipBuffer(bbuf); assertEquals(longs[0], bbuf.asLongBuffer().get(0)); - bbuf.clear(); // BOOL + clearBuffer(bbuf); // BOOL tbools.writeTo(bbuf); assertEquals(tbools.numBytes(), bbuf.position()); - bbuf.flip(); + flipBuffer(bbuf); assertEquals(bools[0], bbuf.get(0) != 0); } @@ -254,7 +255,7 @@ public class TensorTest { : ByteOrder.LITTLE_ENDIAN) .asDoubleBuffer(); tdoubles.writeTo(foreignBuf); - foreignBuf.flip(); + flipBuffer(foreignBuf); double[] actual = new double[foreignBuf.remaining()]; foreignBuf.get(actual); assertArrayEquals(doubles, actual, EPSILON); @@ -547,4 +548,25 @@ public class TensorTest { // expected. } } + + // Workaround for cross compiliation + // (e.g., javac -source 1.9 -target 1.8). + // + // In Java 8 and prior, subclasses of java.nio.Buffer (e.g., java.nio.DoubleBuffer) inherited the + // "flip()" and "clear()" methods from java.nio.Buffer resulting in the signature: + // Buffer flip(); + // In Java 9 these subclasses had their own methods like: + // DoubleBuffer flip(); + // As a result, compiling for 1.9 source for a target of JDK 1.8 would result in errors at runtime + // like: + // + // java.lang.NoSuchMethodError: java.nio.DoubleBuffer.flip()Ljava/nio/DoubleBuffer + private static void flipBuffer(Buffer buf) { + buf.flip(); + } + + // See comment for flipBuffer() + private static void clearBuffer(Buffer buf) { + buf.clear(); + } } diff --git a/tensorflow/lite/BUILD b/tensorflow/lite/BUILD index be84fc5db1..bb2c53b8c9 100644 --- a/tensorflow/lite/BUILD +++ b/tensorflow/lite/BUILD @@ -131,6 +131,7 @@ cc_library( name = "framework", srcs = [ "allocation.cc", + "core/subgraph.cc", "graph_info.cc", "interpreter.cc", "model.cc", @@ -155,6 +156,7 @@ cc_library( "allocation.h", "context.h", "context_util.h", + "core/subgraph.h", "error_reporter.h", "graph_info.h", "interpreter.h", diff --git a/tensorflow/lite/build_def.bzl b/tensorflow/lite/build_def.bzl index bc98dc57bc..5eaf719494 100644 --- a/tensorflow/lite/build_def.bzl +++ b/tensorflow/lite/build_def.bzl @@ -221,6 +221,7 @@ def json_to_tflite(name, src, out): # generated_test_models_failing(). def generated_test_models(): return [ + "abs", "add", "arg_min_max", "avg_pool", @@ -236,18 +237,21 @@ def generated_test_models(): "equal", "exp", "expand_dims", + "fill", "floor", "floor_div", "floor_mod", "fully_connected", "fused_batch_norm", "gather", + "gather_buggy", "global_batch_norm", "greater", "greater_equal", "sum", "l2norm", "l2_pool", + "leaky_relu", "less", "less_equal", "local_response_norm", @@ -261,6 +265,7 @@ def generated_test_models(): "maximum", "mean", "minimum", + "mirror_pad", "mul", "neg", "not_equal", @@ -268,6 +273,7 @@ def generated_test_models(): "pack", "pad", "padv2", + "placeholder_with_default", "prelu", "pow", "range", @@ -290,17 +296,21 @@ def generated_test_models(): "space_to_depth", "sparse_to_dense", "split", + "splitv", "sqrt", "square", + "squared_difference", "squeeze", "strided_slice", "strided_slice_1d_exhaustive", + "strided_slice_buggy", "sub", "tile", "topk", "transpose", "transpose_conv", "unpack", + "unroll_batch_matmul", "where", "zeros_like", ] diff --git a/tensorflow/lite/builtin_ops.h b/tensorflow/lite/builtin_ops.h index b8c05f57bb..f97d3ac4bf 100644 --- a/tensorflow/lite/builtin_ops.h +++ b/tensorflow/lite/builtin_ops.h @@ -123,6 +123,11 @@ typedef enum { kTfLiteBuiltinFloorMod = 95, kTfLiteBuiltinRange = 96, kTfLiteBuiltinResizeNearestNeighbor = 97, + kTfLiteBuiltinLeakyRelu = 98, + kTfLiteBuiltinSquaredDifference = 99, + kTfLiteBuiltinMirrorPad = 100, + kTfLiteBuiltinAbs = 101, + kTfLiteBuiltinSplitV = 102, } TfLiteBuiltinOperator; #ifdef __cplusplus diff --git a/tensorflow/lite/c/builtin_op_data.h b/tensorflow/lite/c/builtin_op_data.h index 855983d60d..6a5a027a9d 100644 --- a/tensorflow/lite/c/builtin_op_data.h +++ b/tensorflow/lite/c/builtin_op_data.h @@ -35,11 +35,21 @@ typedef enum { kTfLitePaddingValid, } TfLitePadding; +typedef enum { + kTfLiteMirrorPaddingUnknown = 0, + kTfLiteMirrorPaddingReflect, + kTfLiteMirrorPaddingSymmetric, +} TfLiteMirrorPaddingMode; + typedef struct { int width; int height; } TfLitePaddingValues; +typedef struct { + TfLiteMirrorPaddingMode mode; +} TfLiteMirrorPaddingParams; + // Possible fused activation functions. // TODO(aselle): rename to TfLiteActivation typedef enum { @@ -267,6 +277,10 @@ typedef struct { int num_splits; } TfLiteSplitParams; +typedef struct { + int num_splits; +} TfLiteSplitVParams; + typedef struct { // TODO(ahentz): We can't have dynamic data in this struct, at least not yet. // For now we will fix the maximum possible number of dimensions. @@ -328,6 +342,10 @@ typedef struct { int axis; } TfLiteUnpackParams; +typedef struct { + float alpha; +} TfLiteLeakyReluParams; + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/tensorflow/lite/c/builtin_op_data_test.cc b/tensorflow/lite/c/builtin_op_data_test.cc index 0e33dcd8c8..4ce7c481e1 100644 --- a/tensorflow/lite/c/builtin_op_data_test.cc +++ b/tensorflow/lite/c/builtin_op_data_test.cc @@ -63,6 +63,7 @@ TEST(IntArray, CanCompileStructs) { TfLiteTransposeParams transpose_params; TfLiteReducerParams reducer_params; TfLiteSplitParams split_params; + TfLiteSplitVParams split_v_params; TfLiteSqueezeParams squeeze_params; TfLiteStridedSliceParams strided_slice_params; TfLiteArgMaxParams arg_max_params; diff --git a/tensorflow/lite/c/c_api_internal.c b/tensorflow/lite/c/c_api_internal.c index b131f06774..2923dbad4e 100644 --- a/tensorflow/lite/c/c_api_internal.c +++ b/tensorflow/lite/c/c_api_internal.c @@ -59,7 +59,7 @@ void TfLiteIntArrayPrint(const char* s, TfLiteIntArray* a) { printf("]\n"); } -TfLiteIntArray* TfLiteIntArrayCopy(TfLiteIntArray* src) { +TfLiteIntArray* TfLiteIntArrayCopy(const TfLiteIntArray* src) { if (!src) return NULL; TfLiteIntArray* ret = TfLiteIntArrayCreate(src->size); if (ret) { @@ -125,6 +125,8 @@ const char* TfLiteTypeGetName(TfLiteType type) { return "INT32"; case kTfLiteUInt8: return "UINT8"; + case kTfLiteInt8: + return "INT8"; case kTfLiteInt64: return "INT64"; case kTfLiteBool: @@ -137,3 +139,14 @@ const char* TfLiteTypeGetName(TfLiteType type) { return "Unknown type"; } +TfLiteDelegate TfLiteDelegateCreate() { + TfLiteDelegate d = { + .data_ = NULL, + .Prepare = NULL, + .CopyFromBufferHandle = NULL, + .CopyToBufferHandle = NULL, + .FreeBufferHandle = NULL, + .flags = kTfLiteDelegateFlagsNone, + }; + return d; +} diff --git a/tensorflow/lite/c/c_api_internal.h b/tensorflow/lite/c/c_api_internal.h index e05fd19936..1cd84eff5c 100644 --- a/tensorflow/lite/c/c_api_internal.h +++ b/tensorflow/lite/c/c_api_internal.h @@ -96,7 +96,7 @@ int TfLiteIntArrayEqualsArray(TfLiteIntArray* a, int b_size, int b_data[]); // Create a copy of an array passed as `src`. // You are expected to free memory with TfLiteIntArrayFree -TfLiteIntArray* TfLiteIntArrayCopy(TfLiteIntArray* src); +TfLiteIntArray* TfLiteIntArrayCopy(const TfLiteIntArray* src); // Free memory of array `v`. void TfLiteIntArrayFree(TfLiteIntArray* v); @@ -179,6 +179,7 @@ typedef enum { kTfLiteBool = 6, kTfLiteInt16 = 7, kTfLiteComplex64 = 8, + kTfLiteInt8 = 9, } TfLiteType; // Return the name of a given type, for error reporting purposes. @@ -203,6 +204,7 @@ typedef union { bool* b; int16_t* i16; TfLiteComplex64* c64; + int8_t* int8; } TfLitePtrUnion; // Memory allocation strategies. kTfLiteMmapRo is for read-only memory-mapped @@ -486,19 +488,20 @@ typedef struct _TfLiteDelegate { // delegated subgraphs of the original graph. TfLiteStatus (*Prepare)(TfLiteContext* context, TfLiteDelegate* delegate); - // Copy the data from delegate buffer handle to raw memory. - // This can be null if the delegate doesn't use its own buffer. + // Copy the data from delegate buffer handle into raw memory of the given + // 'tensor'. This cannot be null. The delegate is allowed to allocate the raw + // bytes as long as it follows the rules for kTfLiteDynamic tensors. TfLiteStatus (*CopyFromBufferHandle)(TfLiteContext* context, TfLiteDelegate* delegate, TfLiteBufferHandle buffer_handle, - void* data, size_t size); + TfLiteTensor* tensor); - // Copy the data from raw memory to delegate buffer handle. - // This can be null if the delegate doesn't use its own buffer. + // Copy the data from raw memory of the given 'tensor' to delegate buffer + // handle. This can be null if the delegate doesn't use its own buffer. TfLiteStatus (*CopyToBufferHandle)(TfLiteContext* context, TfLiteDelegate* delegate, TfLiteBufferHandle buffer_handle, - void* data, size_t size); + TfLiteTensor* tensor); // Free the Delegate Buffer Handle. Note: This only frees the handle, but // this doesn't release the underlying resource (e.g. textures). The @@ -511,6 +514,10 @@ typedef struct _TfLiteDelegate { int64_t flags; } TfLiteDelegate; +// Build a 'null' delegate, with all the fields properly set to their default +// values. +TfLiteDelegate TfLiteDelegateCreate(); + // WARNING: This is an experimental interface that is subject to change. // // Currently, TfLiteDelegateParams has to be allocated in a way that it's diff --git a/tensorflow/lite/c/c_api_internal_test.cc b/tensorflow/lite/c/c_api_internal_test.cc index e21823c41f..acf0dfc5be 100644 --- a/tensorflow/lite/c/c_api_internal_test.cc +++ b/tensorflow/lite/c/c_api_internal_test.cc @@ -74,6 +74,7 @@ TEST(Types, TestTypeNames) { EXPECT_EQ(type_name(kTfLiteInt16), "INT16"); EXPECT_EQ(type_name(kTfLiteInt32), "INT32"); EXPECT_EQ(type_name(kTfLiteUInt8), "UINT8"); + EXPECT_EQ(type_name(kTfLiteInt8), "INT8"); EXPECT_EQ(type_name(kTfLiteInt64), "INT64"); EXPECT_EQ(type_name(kTfLiteBool), "BOOL"); EXPECT_EQ(type_name(kTfLiteComplex64), "COMPLEX64"); diff --git a/tensorflow/lite/core/api/flatbuffer_conversions.cc b/tensorflow/lite/core/api/flatbuffer_conversions.cc index 8cd3faabb7..c00a0a3a54 100644 --- a/tensorflow/lite/core/api/flatbuffer_conversions.cc +++ b/tensorflow/lite/core/api/flatbuffer_conversions.cc @@ -61,6 +61,9 @@ TfLiteStatus ConvertTensorType(TensorType tensor_type, TfLiteType* type, case TensorType_UINT8: *type = kTfLiteUInt8; break; + case TensorType_INT8: + *type = kTfLiteInt8; + break; case TensorType_INT64: *type = kTfLiteInt64; break; @@ -503,6 +506,14 @@ TfLiteStatus ParseOpData(const Operator* op, BuiltinOperator op_type, *builtin_data = reinterpret_cast(params); break; } + case BuiltinOperator_SPLIT_V: { + auto* params = allocator->AllocatePOD(); + if (auto* schema_params = op->builtin_options_as_SplitVOptions()) { + params->num_splits = schema_params->num_splits(); + } + *builtin_data = reinterpret_cast(params); + break; + } case BuiltinOperator_SQUEEZE: { auto* params = allocator->AllocatePOD(); if (auto* schema_params = op->builtin_options_as_SqueezeOptions()) { @@ -617,8 +628,31 @@ TfLiteStatus ParseOpData(const Operator* op, BuiltinOperator op_type, *builtin_data = reinterpret_cast(params); break; } + case BuiltinOperator_LEAKY_RELU: { + TfLiteLeakyReluParams* params = + allocator->AllocatePOD(); + if (auto* leaky_relu_params = op->builtin_options_as_LeakyReluOptions()) { + params->alpha = leaky_relu_params->alpha(); + } + *builtin_data = reinterpret_cast(params); + break; + } + case BuiltinOperator_MIRROR_PAD: { + TfLiteMirrorPaddingParams* params = + allocator->AllocatePOD(); + auto* mirror_pad_params = op->builtin_options_as_MirrorPadOptions(); + if (mirror_pad_params != nullptr) { + params->mode = + mirror_pad_params->mode() == tflite::MirrorPadMode_REFLECT + ? TfLiteMirrorPaddingMode::kTfLiteMirrorPaddingReflect + : TfLiteMirrorPaddingMode::kTfLiteMirrorPaddingSymmetric; + } + *builtin_data = reinterpret_cast(params); + break; + } // Below are the ops with no builtin_data strcture. + case BuiltinOperator_ABS: case BuiltinOperator_BATCH_TO_SPACE_ND: // TODO(aselle): Implement call in BuiltinOptions, but nullptrs are // ok for now, since there is no call implementation either. @@ -668,6 +702,7 @@ TfLiteStatus ParseOpData(const Operator* op, BuiltinOperator op_type, case BuiltinOperator_FILL: case BuiltinOperator_FLOOR_MOD: case BuiltinOperator_RANGE: + case BuiltinOperator_SQUARED_DIFFERENCE: break; } return kTfLiteOk; diff --git a/tensorflow/lite/core/subgraph.cc b/tensorflow/lite/core/subgraph.cc new file mode 100644 index 0000000000..90361faeae --- /dev/null +++ b/tensorflow/lite/core/subgraph.cc @@ -0,0 +1,970 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/core/subgraph.h" +#include "tensorflow/lite/arena_planner.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/context_util.h" +#include "tensorflow/lite/graph_info.h" +#include "tensorflow/lite/nnapi_delegate.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { + +namespace { +TfLiteStatus ReportOpError(TfLiteContext* context, const TfLiteNode& node, + const TfLiteRegistration& registration, + int node_index, const char* message) { + context->ReportError( + context, "Node number %d (%s) %s.\n", node_index, + registration.custom_name + ? registration.custom_name + : EnumNameBuiltinOperator( + static_cast(registration.builtin_code)), + message); + return kTfLiteError; +} + +// Stub method which returns kTfLiteError when the function is forbidden. +// We're registrating this function to several different function to save +// compiled binary size. Please note the restrictions: +// * The type of first parameter have to be `TfLiteContext*`. +// * All paramteters must be trivailly destructible. (E.g. No C++ class) +TfLiteStatus ForbiddenContextFunction(TfLiteContext* context, ...) { + context->ReportError(context, + "The function is forbidden if not calling in delegate."); + return kTfLiteError; +} + +// Set the ForbiddenContextFunction to a compatible function pointer. +template +void SetForbiddenContextFunction(FunctionType* func) { + *func = reinterpret_cast(ForbiddenContextFunction); +} + +// Returns true if at least one tensor in the given list is kTfLiteDynamic. +template +bool HasDynamicTensorImpl(const TfLiteContext& context, + const TensorIntArray& int_array) { + for (int i : int_array) { + const TfLiteTensor& tensor = context.tensors[i]; + if (tensor.allocation_type == kTfLiteDynamic) { + return true; + } + } + return false; +} + +bool HasDynamicTensor(const TfLiteContext& context, + const TfLiteIntArray* int_array) { + return HasDynamicTensorImpl(context, TfLiteIntArrayView{int_array}); +} + +} // namespace + +// A trivial implementation of GraphInfo around the Interpreter. +// NOTE: this interpreter info represents the subset of the +// graph that is executed according to execution plan. Thus, +// the indices are execution plan indices rather than raw node +// indices. +class InterpreterInfo : public GraphInfo { + public: + explicit InterpreterInfo(Subgraph* subgraph) : subgraph_(subgraph) {} + + size_t num_tensors() const override { return subgraph_->tensors().size(); } + TfLiteTensor* tensor(size_t index) override { + return &subgraph_->tensors()[index]; + } + size_t num_nodes() const override { + return subgraph_->execution_plan().size(); + } + const TfLiteNode& node(size_t index) const override { + int node_index = subgraph_->execution_plan()[index]; + return subgraph_->nodes_and_registration()[node_index].first; + } + const std::vector& inputs() const override { + return subgraph_->inputs(); + } + const std::vector& outputs() const override { + return subgraph_->outputs(); + } + const std::vector& variables() const override { + return subgraph_->variables(); + } + + public: + Subgraph* subgraph_; +}; + +Subgraph::Subgraph(ErrorReporter* error_reporter, + TfLiteExternalContext** external_contexts, + std::vector>* subgraphs) + : context_(&owned_context_), + error_reporter_(error_reporter), + next_execution_plan_index_to_prepare_(0), + external_contexts_(external_contexts), + subgraphs_(subgraphs) { + context_->impl_ = static_cast(this); + context_->ResizeTensor = ResizeTensor; + context_->ReportError = ReportErrorC; + context_->AddTensors = AddTensors; + context_->tensors = nullptr; + context_->tensors_size = 0; + context_->allow_fp32_relax_to_fp16 = false; + context_->recommended_num_threads = -1; + context_->GetExternalContext = GetExternalContext; + context_->SetExternalContext = SetExternalContext; + + // Reserve some space for the tensors to avoid excessive resizing. + tensors_.reserve(kTensorsReservedCapacity); + nodes_and_registration().reserve(kTensorsReservedCapacity); + // Invalid to call these these except from TfLiteDelegate + SwitchToKernelContext(); +} + +Subgraph::~Subgraph() { + for (auto& node_and_reg : nodes_and_registration_) { + TfLiteNode& node = node_and_reg.first; + TfLiteIntArrayFree(node.inputs); + TfLiteIntArrayFree(node.outputs); + TfLiteIntArrayFree(node.temporaries); + if (node.builtin_data) free(node.builtin_data); + OpFree(node_and_reg.second, node.user_data); + node.builtin_data = nullptr; + } + + for (size_t i = 0; i < context_->tensors_size; i++) { + TfLiteTensor* tensor = &context_->tensors[i]; + if (tensor->buffer_handle != kTfLiteNullBufferHandle && + tensor->delegate->FreeBufferHandle != nullptr) { + tensor->delegate->FreeBufferHandle(context_, tensor->delegate, + &tensor->buffer_handle); + } + TfLiteTensorFree(tensor); + } +} + +TfLiteStatus Subgraph::ReplaceNodeSubsetsWithDelegateKernels( + TfLiteContext* context, TfLiteRegistration registration, + const TfLiteIntArray* nodes_to_replace, TfLiteDelegate* delegate) { + return static_cast(context->impl_) + ->ReplaceNodeSubsetsWithDelegateKernels(registration, nodes_to_replace, + delegate); +} + +namespace { + +// Copy a std::vector to an existing TfLiteIntArray. +// This is a low-level data manipulation function, and it's caller's +// responsibility to ensure TfLiteIntArray has enough size. +void CopyVectorToTfLiteIntArray(const std::vector& vec, + TfLiteIntArray* arr) { + arr->size = vec.size(); + memcpy(arr->data, vec.data(), sizeof(int) * arr->size); +} + +// This function allocates a continuous memory space that contains a +// TfLiteDelegateParams followed by a several TfLiteIntArray. +// When calling `free` at TfLiteDelegateParams*, all the allocated space +// will be freed together. +// +// +-----------------------------------+ +// | TfLiteDelegateParams | +// | TfLiteDelegate* delegate; | +// | TfLiteIntArray* nodes_to_replace; |--\ +// | TfLiteIntArray* input_tensors; |--+--\ +// | TfLiteIntArray* output_tensors; |--+--+--\ +// +-----------------------------------+ | | | +// | TfLiteIntArray (variable size) |<-/ | | +// +-----------------------------------+ | | +// | TfLiteIntArray (variable size) |<----/ | +// +-----------------------------------+ | +// | TfLiteIntArray (variable size) |<-------/ +// +-----------------------------------+ +TfLiteDelegateParams* CreateDelegateParams(TfLiteDelegate* delegate, + const NodeSubset& node_subset) { + // Step 1: Calculate the allocation size. + int allocation_size = sizeof(TfLiteDelegateParams); + + int nodes_to_replace_size = + TfLiteIntArrayGetSizeInBytes(node_subset.nodes.size()); + allocation_size += nodes_to_replace_size; + + int input_tensors_size = + TfLiteIntArrayGetSizeInBytes(node_subset.input_tensors.size()); + allocation_size += input_tensors_size; + + int output_tensors_size = + TfLiteIntArrayGetSizeInBytes(node_subset.output_tensors.size()); + allocation_size += output_tensors_size; + + // Step 2: Allocate the memory. + // Use `char*` for conveniently step through the allocated space by bytes. + char* allocation = reinterpret_cast(malloc(allocation_size)); + + // Step 3: Fill all data structures structures. + TfLiteDelegateParams* params = + reinterpret_cast(allocation); + params->delegate = delegate; + allocation += sizeof(TfLiteDelegateParams); + + params->nodes_to_replace = reinterpret_cast(allocation); + CopyVectorToTfLiteIntArray(node_subset.nodes, params->nodes_to_replace); + allocation += nodes_to_replace_size; + + params->input_tensors = reinterpret_cast(allocation); + CopyVectorToTfLiteIntArray(node_subset.input_tensors, params->input_tensors); + allocation += input_tensors_size; + + params->output_tensors = reinterpret_cast(allocation); + CopyVectorToTfLiteIntArray(node_subset.output_tensors, + params->output_tensors); + allocation += output_tensors_size; + + return params; +} + +} // namespace + +TfLiteStatus Subgraph::ReplaceNodeSubsetsWithDelegateKernels( + TfLiteRegistration registration, const TfLiteIntArray* nodes_to_replace, + TfLiteDelegate* delegate) { + // Annotate the registration as DELEGATE op. + registration.builtin_code = BuiltinOperator_DELEGATE; + + // Analyze the graph to find all independent node_subsets that are either + // fully not-this-delegate or this-delegate computation. + InterpreterInfo info(this); + std::vector node_subsets; + PartitionGraphIntoIndependentNodeSubsets(&info, nodes_to_replace, + &node_subsets); + + execution_plan_.clear(); + + for (auto& node_subset : node_subsets) { + // Subsets calimed by the delegate should have a "macro" op created, the + // other node_subsets (kTfNonPartition) just have their nodes added back to + // the execution plan. + switch (node_subset.type) { + case NodeSubset::kTfNonPartition: + for (auto it = node_subset.nodes.begin(); it != node_subset.nodes.end(); + ++it) { + execution_plan_.push_back(*it); + } + break; + case NodeSubset::kTfPartition: { + int node_index; + + TfLiteDelegateParams* params = + CreateDelegateParams(delegate, node_subset); + TF_LITE_ENSURE_STATUS(AddNodeWithParameters( + node_subset.input_tensors, node_subset.output_tensors, nullptr, 0, + params, ®istration, &node_index)); + + // Initialize the output tensors's delegate-related fields. + for (int tensor_index : node_subset.output_tensors) { + TfLiteTensor* tensor = &tensors_[tensor_index]; + TF_LITE_ENSURE(context_, tensor->delegate == nullptr || + tensor->delegate == delegate); + tensor->delegate = delegate; + } + + // Associate the node with the delegate. + TfLiteNode* node = &nodes_and_registration_[node_index].first; + node->delegate = delegate; + } break; + case NodeSubset::kTfUnexplored: + return kTfLiteError; + break; + } + } + return kTfLiteOk; +} + +TfLiteExternalContext* Subgraph::GetExternalContext( + TfLiteExternalContextType type) { + if (type >= 0 && type < kTfLiteMaxExternalContexts) { + return external_contexts_[type]; + } + return nullptr; +} + +TfLiteExternalContext* Subgraph::GetExternalContext( + struct TfLiteContext* context, TfLiteExternalContextType type) { + return static_cast(context->impl_)->GetExternalContext(type); +} + +void Subgraph::SetExternalContext(TfLiteExternalContextType type, + TfLiteExternalContext* ctx) { + if (type >= 0 && type < kTfLiteMaxExternalContexts) { + external_contexts_[type] = ctx; + } +} + +void Subgraph::SetExternalContext(struct TfLiteContext* context, + TfLiteExternalContextType type, + TfLiteExternalContext* ctx) { + return static_cast(context->impl_)->SetExternalContext(type, ctx); +} + +// Gets an TfLiteIntArray* representing the execution plan. The interpreter owns +// this memory and it is only guaranteed to exist during the invocation of the +// delegate prepare. +TfLiteStatus Subgraph::GetExecutionPlan(TfLiteIntArray** execution_plan) { + // TODO(aselle): Do not make a copy here + plan_cache_.reset(TfLiteIntArrayCreate(execution_plan_.size())); + *execution_plan = plan_cache_.get(); + static_assert(sizeof(plan_cache_->data[0]) == sizeof(execution_plan_[0]), + "TfLiteIntArray and execution_plan do not contain same type."); + std::memcpy(plan_cache_->data, execution_plan_.data(), + sizeof(plan_cache_->data[0]) * execution_plan_.size()); + return kTfLiteOk; +} + +// WARNING: This is an experimental interface that is subject to change. +// Entry point for C node plugin API to get the execution plan +TfLiteStatus Subgraph::GetExecutionPlan(struct TfLiteContext* context, + TfLiteIntArray** execution_plan) { + return static_cast(context->impl_) + ->GetExecutionPlan(execution_plan); +} + +TfLiteStatus Subgraph::SetInputs(std::vector inputs) { + TF_LITE_ENSURE_OK(&context_, + CheckTensorIndices("inputs", inputs.data(), inputs.size())); + inputs_ = std::move(inputs); + return kTfLiteOk; +} + +TfLiteStatus Subgraph::SetOutputs(std::vector outputs) { + TF_LITE_ENSURE_OK( + &context_, CheckTensorIndices("outputs", outputs.data(), outputs.size())); + outputs_ = std::move(outputs); + return kTfLiteOk; +} + +TfLiteStatus Subgraph::SetVariables(std::vector variables) { + TF_LITE_ENSURE_OK(&context_, CheckTensorIndices("variables", variables.data(), + variables.size())); + variables_ = std::move(variables); + return kTfLiteOk; +} + +TfLiteStatus Subgraph::CheckTensorIndices(const char* label, const int* indices, + int length) { + // Making sure kOptionalTensor is not re-defined to something other than -1. + static_assert(kOptionalTensor == -1, "kOptionalTensor should be defined -1"); + + for (int i = 0; i < length; i++) { + int index = indices[i]; + // Continue if index == kOptionalTensor before additional comparisons below, + // size_t(-1) is always >= context_tensors_size. + if (index == kOptionalTensor) { + continue; + } + if (index < 0 || static_cast(index) >= context_->tensors_size) { + ReportError("Invalid tensor index %d in %s\n", index, label); + consistent_ = false; + return kTfLiteError; + } + } + return kTfLiteOk; +} + +TfLiteStatus Subgraph::BytesRequired(TfLiteType type, const int* dims, + size_t dims_size, size_t* bytes) { + // TODO(aselle): Check for overflow here using overflow.h in TensorFlow + // MultiplyWithoutOverflow. + TF_LITE_ENSURE(context_, bytes != nullptr); + size_t count = 1; + for (int k = 0; k < dims_size; k++) count *= dims[k]; + switch (type) { + case kTfLiteFloat32: + *bytes = sizeof(float) * count; + break; + case kTfLiteInt16: + *bytes = sizeof(int16_t) * count; + break; + case kTfLiteInt32: + *bytes = sizeof(int32_t) * count; + break; + case kTfLiteUInt8: + *bytes = sizeof(uint8_t) * count; + break; + case kTfLiteInt64: + *bytes = sizeof(int64_t) * count; + break; + case kTfLiteBool: + *bytes = sizeof(bool) * count; + break; + case kTfLiteComplex64: + *bytes = sizeof(std::complex) * count; + break; + case kTfLiteInt8: + *bytes = sizeof(int8_t) * count; + break; + default: + ReportError( + "Only float32, int8, int16, int32, int64, uint8, bool, complex64 " + "supported currently."); + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus Subgraph::AllocateTensors() { + if (!consistent_) { + ReportError("AllocateTensors() called on inconsistent model."); + return kTfLiteError; + } + + // Explicit (re)allocation is necessary if nodes have been changed or tensors + // have been resized. For inputs marked as dynamic, we can't short-circuit the + // allocation as the client may have done the resize manually. + if (state_ != kStateUninvokable && + !HasDynamicTensorImpl(*context_, inputs())) { + return kTfLiteOk; + } + + next_execution_plan_index_to_prepare_ = 0; + if (memory_planner_) { + TF_LITE_ENSURE_STATUS(memory_planner_->ResetAllocations()); + } + + TF_LITE_ENSURE_STATUS(PrepareOpsAndTensors()); + + state_ = kStateInvokable; + + // Reset the variable tensors to zero after (re)allocating the tensors. + // Developers shouldn't rely on the side effect of this function to reset + // variable tesnsors. They should call `ResetVariableTensors` directly + // instead. + ResetVariableTensors(); + + return kTfLiteOk; +} + +// TODO(ycling): Support non-zero default values. +TfLiteStatus Subgraph::ResetVariableTensors() { + for (auto& tensor : tensors_) { + if (!tensor.is_variable) { + continue; + } + + // Variable tensors have to be `kTfLiteArenaRwPersistent`, and must be + // allocated after the initial `PrepareOpsAndTensors()` is called. + TF_LITE_ENSURE_EQ(context_, tensor.allocation_type, + kTfLiteArenaRwPersistent); + TF_LITE_ENSURE(context_, tensor.data.raw != nullptr); + + memset(tensor.data.raw, 0, tensor.bytes); + } + return kTfLiteOk; +} + +TfLiteStatus Subgraph::AddNodeWithParameters( + const std::vector& inputs, const std::vector& outputs, + const char* init_data, size_t init_data_size, void* builtin_data, + const TfLiteRegistration* registration, int* node_index) { + if (state_ == kStateInvokableAndImmutable) { + ReportError("AddNodeWithParameters is disallowed when graph is immutable."); + return kTfLiteError; + } + state_ = kStateUninvokable; + + std::unique_ptr builtin_data_deleter(builtin_data, + free); + + TF_LITE_ENSURE_OK(context_, CheckTensorIndices("node inputs", inputs.data(), + inputs.size())); + TF_LITE_ENSURE_OK( + &context_, + CheckTensorIndices("node outputs", outputs.data(), outputs.size())); + + int new_node_index = nodes_and_registration_.size(); + if (node_index) *node_index = new_node_index; + nodes_and_registration_.resize(nodes_and_registration_.size() + 1); + auto& node_and_reg = nodes_and_registration_.back(); + TfLiteNode& node = node_and_reg.first; + if (node.inputs) TfLiteIntArrayFree(node.inputs); + if (node.outputs) TfLiteIntArrayFree(node.outputs); + if (node.temporaries) TfLiteIntArrayFree(node.temporaries); + + // NOTE, here we are not using move semantics yet, since our internal + // representation isn't std::vector, but in the future we would like to avoid + // copies, so we want the interface to take r-value references now. + node.inputs = ConvertVectorToTfLiteIntArray(inputs); + node.outputs = ConvertVectorToTfLiteIntArray(outputs); + node.temporaries = TfLiteIntArrayCreate(0); + if (init_data) { + node.user_data = OpInit(*registration, init_data, init_data_size); + } else { + node.user_data = + OpInit(*registration, + reinterpret_cast(builtin_data_deleter.get()), 0); + } + + node.builtin_data = builtin_data_deleter.release(); + // TODO(ycling): Filling `custom_initial_data` and `custom_initial_data_size` + // properly for nodes generated by ReplaceNodeSubsetsWithDelegateKernels. + + if (registration->builtin_code == BuiltinOperator_CUSTOM) { + // When it's a CUSTOM op, the `custom_options` field in the Flatbuffer + // `Operator` table is passed in. + node.custom_initial_data = init_data; + node.custom_initial_data_size = init_data_size; + } else { + node.custom_initial_data = nullptr; + node.custom_initial_data_size = 0; + } + + node.delegate = nullptr; + node_and_reg.second = *registration; + execution_plan_.push_back(new_node_index); + return kTfLiteOk; +} + +TfLiteStatus Subgraph::ResizeInputTensor(int tensor_index, + const std::vector& dims) { + if (state_ == kStateInvokableAndImmutable) { + ReportError("ResizeInputTensor is disallowed when graph is immutable."); + return kTfLiteError; + } + + // TODO(aselle): All bounds checks can be implemented as one-sided bounds + // checks by casting to unsigned for efficiency. Profile before doing this. + TF_LITE_ENSURE(context_, + tensor_index < context_->tensors_size && tensor_index >= 0); + TfLiteTensor* tensor = &context_->tensors[tensor_index]; + + // Short-circuit the state change if the dimensions don't change, avoiding + // unnecessary (re)allocations. + if (EqualArrayAndTfLiteIntArray(tensor->dims, dims.size(), dims.data())) { + return kTfLiteOk; + } + + state_ = kStateUninvokable; + return ResizeTensorImpl(tensor, ConvertVectorToTfLiteIntArray(dims)); +} + +TfLiteStatus Subgraph::PrepareOpsStartingAt( + int first_execution_plan_index, int* last_execution_plan_index_prepared) { + if (first_execution_plan_index == 0) { + has_dynamic_tensors_ = false; + } + for (int execution_plan_index = first_execution_plan_index; + execution_plan_index < execution_plan_.size(); execution_plan_index++) { + int node_index = execution_plan_[execution_plan_index]; + TfLiteNode& node = nodes_and_registration_[node_index].first; + const TfLiteRegistration& registration = + nodes_and_registration_[node_index].second; + EnsureTensorsVectorCapacity(); + if (OpPrepare(registration, &node) == kTfLiteError) { + return ReportOpError(context_, node, registration, node_index, + "failed to prepare"); + } + + *last_execution_plan_index_prepared = execution_plan_index; + + // Discontinue if the node has dynamic outputs. Note that we don't + // stop for dynamic temporary tensors since they won't affect the + // sizes of other tensors in the graph. + if (HasDynamicTensor(*context_, node.outputs)) { + has_dynamic_tensors_ = true; + return kTfLiteOk; + } + } + return kTfLiteOk; +} + +TfLiteStatus Subgraph::PrepareOpsAndTensors() { + if (!memory_planner_) { + memory_planner_.reset(new ArenaPlanner( + context_, std::unique_ptr(new InterpreterInfo(this)), + /*preserve_inputs=*/true, /*preserve_intermediates*/ false)); + memory_planner_->PlanAllocations(); + } + + int last_exec_plan_index_prepared = 0; + + TF_LITE_ENSURE_STATUS(PrepareOpsStartingAt( + next_execution_plan_index_to_prepare_, &last_exec_plan_index_prepared)); + TF_LITE_ENSURE_STATUS(memory_planner_->ExecuteAllocations( + next_execution_plan_index_to_prepare_, last_exec_plan_index_prepared)); + + next_execution_plan_index_to_prepare_ = last_exec_plan_index_prepared + 1; + return kTfLiteOk; +} + +TfLiteStatus Subgraph::Invoke() { + if (!consistent_) { + ReportError("Invoke called on model that is not consistent."); + return kTfLiteError; + } + + TfLiteStatus status = kTfLiteOk; + if (state_ == kStateUninvokable) { + ReportError("Invoke called on model that is not ready."); + return kTfLiteError; + } + + if (nnapi_delegate_) { + if (next_execution_plan_index_to_prepare_ == execution_plan_.size()) { + TF_LITE_ENSURE_OK(context_, nnapi_delegate_->Invoke(this)); + return kTfLiteOk; + } else { + // TODO(aselle): In the future, we would like this to be an + // automatic tflite CPU fallback. + ReportError( + "NNAPI was requested, but dependent sized tensors " + "being used.\n"); + return kTfLiteError; + } + } + + // Invocations are always done in node order. + // Note that calling Invoke repeatedly will cause the original memory plan to + // be reused, unless either ResizeInputTensor() or AllocateTensors() has been + // called. + for (int execution_plan_index = 0; + execution_plan_index < execution_plan_.size(); execution_plan_index++) { + if (execution_plan_index == next_execution_plan_index_to_prepare_) { + TF_LITE_ENSURE_STATUS(PrepareOpsAndTensors()); + TF_LITE_ENSURE(context_, next_execution_plan_index_to_prepare_ >= + execution_plan_index); + } + int node_index = execution_plan_[execution_plan_index]; + TfLiteNode& node = nodes_and_registration_[node_index].first; + const TfLiteRegistration& registration = + nodes_and_registration_[node_index].second; + SCOPED_OPERATOR_PROFILE(profiler_, node_index); + + // TODO(ycling): This is an extra loop through inputs to check if the data + // need to be copied from Delegate buffer to raw memory, which is often not + // needed. We may want to cache this in prepare to know if this needs to be + // done for a node or not. + for (int i = 0; i < node.inputs->size; ++i) { + int tensor_index = node.inputs->data[i]; + if (tensor_index == kOptionalTensor) { + continue; + } + TfLiteTensor* tensor = &tensors_[tensor_index]; + if (tensor->delegate && tensor->delegate != node.delegate && + tensor->data_is_stale) { + EnsureTensorDataIsReadable(tensor_index); + } + } + + EnsureTensorsVectorCapacity(); + tensor_resized_since_op_invoke_ = false; + if (OpInvoke(registration, &node) == kTfLiteError) { + status = ReportOpError(context_, node, registration, node_index, + "failed to invoke"); + } + + // Force execution prep for downstream ops if the latest op triggered the + // resize of a dynamic tensor. + if (tensor_resized_since_op_invoke_ && + HasDynamicTensor(*context_, node.outputs)) { + next_execution_plan_index_to_prepare_ = execution_plan_index + 1; + } + } + + return status; +} + +TfLiteStatus Subgraph::ResizeTensor(TfLiteContext* context, + TfLiteTensor* tensor, + TfLiteIntArray* new_size) { + // Note here that context->impl_ is recovering the this pointer for an + // instance of Interpreter to call into the member function ResizeTensorImpl + // (this function is static). + return static_cast(context->impl_) + ->ResizeTensorImpl(tensor, new_size); +} + +void Subgraph::ReportErrorImpl(const char* format, va_list args) { + error_reporter_->Report(format, args); +} + +void Subgraph::ReportErrorC(TfLiteContext* context, const char* format, ...) { + va_list args; + va_start(args, format); + auto* f = static_cast(context->impl_); + // Note here that context->impl_ is recovering the this pointer for an + // instance of Subgraph to call into the member function ReportErrorImpl + // (this function is static). + f->ReportErrorImpl(format, args); + va_end(args); +} + +// Entry point for C node plugin API to report an error. +void Subgraph::ReportError(const char* format, ...) { + va_list args; + va_start(args, format); + auto* f = static_cast(context_->impl_); + // Note here that context->impl_ is recovering the this pointer for an + // instance of Subgraph to call into the member function ReportErrorImpl + // (this function is static). + f->ReportErrorImpl(format, args); + va_end(args); +} + +TfLiteStatus Subgraph::AddTensors(int tensors_to_add, + int* first_new_tensor_index) { + const size_t base_index = tensors_.size(); + if (first_new_tensor_index) *first_new_tensor_index = base_index; + tensors_.resize(tensors_.size() + tensors_to_add); + for (size_t i = base_index; i < tensors_.size(); i++) { + memset(&tensors_[i], 0, sizeof(tensors_[i])); + tensors_[i].buffer_handle = kTfLiteNullBufferHandle; + } + context_->tensors = tensors_.data(); + context_->tensors_size = tensors_.size(); + return kTfLiteOk; +} + +TfLiteStatus Subgraph::AddTensors(TfLiteContext* context, int tensors_to_add, + int* first_new_tensor_index) { + // Note here that context->impl_ is recovering the this pointer for an + // instance of Interpreter to call into the member function AddTensors + // (this function is static). + return static_cast(context->impl_) + ->AddTensors(tensors_to_add, first_new_tensor_index); +} + +TfLiteStatus Subgraph::GetNodeAndRegistration( + int node_index, TfLiteNode** node, TfLiteRegistration** registration) { + TF_LITE_ENSURE(context_, node_index >= 0); + auto nodes_size = nodes_and_registration_.size(); + TF_LITE_ENSURE(context_, static_cast(node_index) < nodes_size); + TF_LITE_ENSURE(context_, node != nullptr && registration != nullptr); + auto& node_and_reg = nodes_and_registration_[node_index]; + *node = &node_and_reg.first; + *registration = &node_and_reg.second; + return kTfLiteOk; +} + +TfLiteStatus Subgraph::GetNodeAndRegistration( + struct TfLiteContext* context, int node_index, TfLiteNode** node, + TfLiteRegistration** registration) { + return static_cast(context->impl_) + ->GetNodeAndRegistration(node_index, node, registration); +} + +TfLiteStatus Subgraph::SetTensorParametersReadOnly( + int tensor_index, TfLiteType type, const char* name, const size_t rank, + const int* dims, TfLiteQuantizationParams quantization, const char* buffer, + size_t bytes, const Allocation* allocation) { + if (state_ == kStateInvokableAndImmutable) { + ReportError( + "SetTensorParametersReadOnly is disallowed when graph is immutable."); + return kTfLiteError; + } + + TF_LITE_ENSURE(context_, + tensor_index < context_->tensors_size && tensor_index >= 0); + // For most tensors we know exactly how much memory is necessary so we can + // ensure the buffer is large enough. However, we need to skip string tensors + // because their sizes change with the contents of the individual strings. + if (type != kTfLiteString) { + size_t required_bytes; + TF_LITE_ENSURE_OK(context_, + BytesRequired(type, dims, rank, &required_bytes)); + TF_LITE_ENSURE_EQ(context_, required_bytes, bytes); + } + + TfLiteTensor& tensor = context_->tensors[tensor_index]; + if (type == tensor.type && + EqualArrayAndTfLiteIntArray(tensor.dims, rank, dims)) { + // Fast path which does not invalidate the invokable property. + TfLiteTensorDataFree(&tensor); + tensor.data.raw = const_cast(buffer); + if (!tensor.dims) tensor.dims = ConvertArrayToTfLiteIntArray(rank, dims); + tensor.params = quantization; + tensor.allocation_type = kTfLiteMmapRo; + tensor.allocation = allocation; + } else { + state_ = kStateUninvokable; + TfLiteTensorReset(type, name, ConvertArrayToTfLiteIntArray(rank, dims), + quantization, const_cast(buffer), bytes, + kTfLiteMmapRo, allocation, false, &tensor); + } + return kTfLiteOk; +} + +// Set description of inputs/outputs/data/fptrs for node `node_index`. +// This variant assumes an external buffer has been allocated of size +// bytes. The lifetime of buffer must be ensured to be greater or equal +// to Interpreter. +TfLiteStatus Subgraph::SetTensorParametersReadWrite( + int tensor_index, TfLiteType type, const char* name, const size_t rank, + const int* dims, TfLiteQuantizationParams quantization, bool is_variable) { + if (state_ == kStateInvokableAndImmutable) { + ReportError( + "SetTensorParametersReadWrite is disallowed when graph is immutable."); + return kTfLiteError; + } + TF_LITE_ENSURE(context_, + tensor_index < context_->tensors_size && tensor_index >= 0); + size_t required_bytes = 0; + if (type != kTfLiteString) { + // These types will be allocated in our arena so we need to record how + // many bytes we will need based on the dimensions. String tensors are + // allocated dynamically and we can't know ahead of time how much space + // they will require. + TF_LITE_ENSURE_OK(context_, + BytesRequired(type, dims, rank, &required_bytes)); + } + + TfLiteAllocationType allocation_type = kTfLiteArenaRw; + if (type == kTfLiteString) { + if (is_variable) { + // We don't have a real use case for string variable tensor. + ReportError("String variable tensor isn't supported."); + return kTfLiteError; + } + allocation_type = kTfLiteDynamic; + } else if (is_variable) { + allocation_type = kTfLiteArenaRwPersistent; + } + + TfLiteTensorReset(type, name, ConvertArrayToTfLiteIntArray(rank, dims), + quantization, + /*buffer=*/nullptr, required_bytes, allocation_type, + nullptr, is_variable, &context_->tensors[tensor_index]); + return kTfLiteOk; +} + +TfLiteStatus Subgraph::SetExecutionPlan(const std::vector& new_plan) { + for (int node_index : new_plan) { + TF_LITE_ENSURE(context_, node_index >= 0 && + node_index < nodes_and_registration_.size()); + } + execution_plan_ = new_plan; + return kTfLiteOk; +} + +TfLiteStatus Subgraph::ResizeTensorImpl(TfLiteTensor* tensor, + TfLiteIntArray* new_size) { + // Note that in theory we could resize kTfLiteArenaRwPersistent tensors too. + if (tensor->allocation_type == kTfLiteArenaRw || + tensor->allocation_type == kTfLiteDynamic || + tensor->allocation_type == kTfLiteArenaRwPersistent) { + tensor_resized_since_op_invoke_ |= + TfLiteIntArrayEqual(tensor->dims, new_size) == 0; + if (tensor->type != kTfLiteString) { + size_t bytesRequired; + TfLiteStatus status = BytesRequired(tensor->type, new_size->data, + new_size->size, &bytesRequired); + if (status != kTfLiteOk) { + TfLiteIntArrayFree(new_size); + return kTfLiteError; + } + + // Realloc space for kTfLiteDynamic tensors. + TfLiteTensorRealloc(bytesRequired, tensor); + tensor->bytes = bytesRequired; + } + if (tensor->dims) TfLiteIntArrayFree(tensor->dims); + tensor->dims = new_size; + + if (tensor->allocation_type != kTfLiteDynamic) { + tensor->data.raw = nullptr; + } + } else { + // kTfLiteMmapRo tensors are stored in the flatbuffer and are therefore + // of fixed size. + TfLiteIntArrayFree(new_size); + ReportError("Attempting to resize a fixed-size tensor."); + return kTfLiteError; + } + return kTfLiteOk; +} + +void Subgraph::UseNNAPI(bool enable) { + // TODO(aselle): This is a workaround for finding if NNAPI exists. + // We also need to make sure getLibraryHandle() is renamed to be NNAPI + // prefixed. + if (!NNAPIDelegate::IsSupported()) enable = false; + if (!enable) { + nnapi_delegate_.reset(); + } else if (!nnapi_delegate_) { + nnapi_delegate_.reset(new NNAPIDelegate); + } +} + +void Subgraph::SwitchToDelegateContext() { + context_->GetNodeAndRegistration = GetNodeAndRegistration; + context_->ReplaceNodeSubsetsWithDelegateKernels = + ReplaceNodeSubsetsWithDelegateKernels; + context_->GetExecutionPlan = GetExecutionPlan; +} + +void Subgraph::SwitchToKernelContext() { + context_->GetNodeAndRegistration = [](struct TfLiteContext* context, + int node_index, TfLiteNode** node, + TfLiteRegistration** registration) { + return ForbiddenContextFunction(context); + }; + context_->ReplaceNodeSubsetsWithDelegateKernels = + [](TfLiteContext* context, TfLiteRegistration registration, + const TfLiteIntArray* nodes_to_replace, TfLiteDelegate* delegate) { + return ForbiddenContextFunction(context); + }; + context_->GetExecutionPlan = [](struct TfLiteContext* context, + TfLiteIntArray**) { + return ForbiddenContextFunction(context); + }; +} + +TfLiteStatus Subgraph::ModifyGraphWithDelegate(TfLiteDelegate* delegate) { + if (!(delegate->flags & kTfLiteDelegateFlagsAllowDynamicTensors)) { + int last_execution_plan_index_prepared; + TF_LITE_ENSURE_OK(&context_, PrepareOpsStartingAt( + 0, &last_execution_plan_index_prepared)); + if (has_dynamic_tensors_) { + ReportError( + "Attempting to use a delegate that only supports static-sized " + "tensors with a graph that has dynamic-sized tensors."); + return kTfLiteError; + } + } + + // TODO(aselle): Consider if it is worth storing pointers to delegates. + // Setup additional context interface. + SwitchToDelegateContext(); + + TfLiteStatus status = delegate->Prepare(context_, delegate); + + // Remove additional context info. + SwitchToKernelContext(); + + TF_LITE_ENSURE_OK(context_, status); + + if (!(delegate->flags & kTfLiteDelegateFlagsAllowDynamicTensors)) { + // Reset the state to force tensor/op reallocation. + state_ = kStateUninvokable; + TF_LITE_ENSURE_OK(context_, AllocateTensors()); + TF_LITE_ENSURE_EQ(context_, state_, kStateInvokable); + // After using a delegate which doesn't support dynamic tensors, make the + // entire graph immutable. + state_ = kStateInvokableAndImmutable; + } + + return status; +} + +} // namespace tflite diff --git a/tensorflow/lite/core/subgraph.h b/tensorflow/lite/core/subgraph.h new file mode 100644 index 0000000000..2a7c3a7c32 --- /dev/null +++ b/tensorflow/lite/core/subgraph.h @@ -0,0 +1,501 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_CORE_SUBGRAPH_H_ +#define TENSORFLOW_LITE_CORE_SUBGRAPH_H_ + +#include +#include + +#include "tensorflow/lite/allocation.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/memory_planner.h" +#include "tensorflow/lite/profiling/profiler.h" +#include "tensorflow/lite/util.h" + +namespace tflite { + +// Forward declare since NNAPIDelegate uses Interpreter. +class NNAPIDelegate; + +class Subgraph { + public: + friend class Interpreter; + + Subgraph(ErrorReporter* error_reporter, + TfLiteExternalContext** external_contexts, + std::vector>* subgraphs); + + Subgraph(const Subgraph&) = delete; + + // Subgraphs should be movable but not copyable. + Subgraph(Subgraph&&) = default; + Subgraph& operator=(const Subgraph&) = delete; + virtual ~Subgraph(); + + // Provide a list of tensor indexes that are inputs to the model. + // Each index is bound check and this modifies the consistent_ flag of the + // interpreter. + TfLiteStatus SetInputs(std::vector inputs); + + // Provide a list of tensor indexes that are outputs to the model + // Each index is bound check and this modifies the consistent_ flag of the + // interpreter. + TfLiteStatus SetOutputs(std::vector outputs); + + // Provide a list of tensor indexes that are variable tensors. + // Each index is bound check and this modifies the consistent_ flag of the + // interpreter. + TfLiteStatus SetVariables(std::vector variables); + + // Adds a node with the given parameters and returns the index of the new + // node in `node_index` (optionally). Interpreter will take ownership of + // `builtin_data` and destroy it with `free`. Ownership of 'init_data' + // remains with the caller. + TfLiteStatus AddNodeWithParameters(const std::vector& inputs, + const std::vector& outputs, + const char* init_data, + size_t init_data_size, void* builtin_data, + const TfLiteRegistration* registration, + int* node_index); + + // Adds `tensors_to_add` tensors, preserving pre-existing Tensor entries. + // The value pointed to by `first_new_tensor_index` will be set to the + // index of the first new tensor if `first_new_tensor_index` is non-null. + TfLiteStatus AddTensors(int tensors_to_add, int* first_new_tensor_index); + + // Set description of inputs/outputs/data/fptrs for node `node_index`. + // This variant assumes an external buffer has been allocated of size + // bytes. The lifetime of buffer must be ensured to be greater or equal + // to Interpreter. + TfLiteStatus SetTensorParametersReadOnly( + int tensor_index, TfLiteType type, const char* name, const size_t rank, + const int* dims, TfLiteQuantizationParams quantization, + const char* buffer, size_t bytes, const Allocation* allocation); + + // Set description of inputs/outputs/data/fptrs for node `node_index`. + // This variant assumes an external buffer has been allocated of size + // bytes. The lifetime of buffer must be ensured to be greater or equal + // to Interpreter. + TfLiteStatus SetTensorParametersReadWrite( + int tensor_index, TfLiteType type, const char* name, const size_t rank, + const int* dims, TfLiteQuantizationParams quantization, bool is_variable); + + // WARNING: Experimental interface, subject to change + // Overrides execution plan. This bounds checks indices sent in. + TfLiteStatus SetExecutionPlan(const std::vector& new_plan); + + // Get a mutable tensor data structure. + // TODO(aselle): Create a safe ArrayHandle interface to avoid exposing this + // read/write access to structure + TfLiteTensor* tensor(int tensor_index) { + if (tensor_index < 0 || + static_cast(tensor_index) >= context_->tensors_size) { + return nullptr; + } + return &context_->tensors[tensor_index]; + } + + // Get an immutable tensor data structure. + const TfLiteTensor* tensor(int tensor_index) const { + if (tensor_index < 0 || + static_cast(tensor_index) >= context_->tensors_size) { + return nullptr; + } + return &context_->tensors[tensor_index]; + } + + // Read only access to list of inputs. + std::vector& inputs() { return inputs_; } + + // Read only access to list of inputs. + const std::vector& inputs() const { return inputs_; } + + // Read only access to list of outputs. + std::vector& outputs() { return outputs_; } + + // Read only access to list of outputs. + const std::vector& outputs() const { return outputs_; } + + // Read only access to list of variable tensors. + std::vector& variables() { return variables_; } + + // Read only access to list of variable tensors. + const std::vector& variables() const { return variables_; } + + size_t tensors_size() const { return tensors_.size(); } + + // Return the number of ops in the model. + size_t nodes_size() const { return nodes_and_registration_.size(); } + + // Read only access to list of variable tensors. + std::vector& execution_plan() { return execution_plan_; } + + // Read only access to list of variable tensors. + const std::vector& execution_plan() const { return execution_plan_; } + + // Mutable form of tensors (TEMPORARY for refactor). + // TODO(b/119495520): remove when refactoring complete. + std::vector& tensors() { return tensors_; } + // Mutable form of tensors (TEMPORARY for refactor). + // TODO(b/119495520): remove when refactoring complete. + std::vector>& + nodes_and_registration() { + return nodes_and_registration_; + } + + const std::vector>& + nodes_and_registration() const { + return nodes_and_registration_; + } + + // Get a pointer to an operation and registration data structure if in bounds. + const std::pair* node_and_registration( + int node_index) const { + if (node_index < 0 || static_cast(node_index) >= nodes_size()) + return nullptr; + return &nodes_and_registration_[node_index]; + } + + // Change the dimensionality of a given tensor. Note, this is only acceptable + // for tensor indices that are inputs. + // Returns status of failure or success. + // TODO(aselle): Consider implementing ArraySlice equivalent to make this + // more adept at accepting data without an extra copy. Use absl::ArraySlice + // if our partners determine that dependency is acceptable. + TfLiteStatus ResizeInputTensor(int tensor_index, + const std::vector& dims); + + // Update allocations for all tensors. This will redim dependent tensors using + // the input tensor dimensionality as given. This is relatively expensive. + // If you know that your sizes are not changing, you need not call this. + // Returns status of success or failure. + TfLiteStatus AllocateTensors(); + + // Invoke the subgraph (run the whole graph in dependency order). + // + // NOTE: It is possible that the interpreter is not in a ready state + // to evaluate (i.e. if a ResizeTensor() has been performed without an + // AllocateTensors(). + // Returns status of success or failure. + TfLiteStatus Invoke(); + + // Entry point for C node plugin API to report an error. + void ReportError(const char* format, ...); + + void UseNNAPI(bool enable); + + // Return the subgraph specific context. + TfLiteContext* context() { return context_; } + + // Set the value of an external context. + void SetExternalContext(TfLiteExternalContextType type, + TfLiteExternalContext* ctx); + // Get the half precision flag. + // WARNING: This is an experimental API and subject to change. + bool GetAllowFp16PrecisionForFp32() const { + return context_->allow_fp32_relax_to_fp16; + } + + // Ensure the data in `tensor.data` is readable. In case delegate is used, + // it might require to copy the data from delegate buffer to raw memory. + // WARNING: This is an experimental API and subject to change. + // TODO(b/119495520): make this private when refactoring complete. + TfLiteStatus EnsureTensorDataIsReadable(int tensor_index) { + TfLiteTensor* t = &tensors_[tensor_index]; + TF_LITE_ENSURE(context_, t != nullptr); + if (t->data_is_stale) { + TF_LITE_ENSURE(context_, t->delegate != nullptr); + TF_LITE_ENSURE(context_, t->buffer_handle != kTfLiteNullBufferHandle); + TF_LITE_ENSURE(context_, t->delegate->CopyFromBufferHandle != nullptr); + // TODO(b/120420546): we must add a test that exercise this code. + TF_LITE_ENSURE_STATUS(t->delegate->CopyFromBufferHandle( + context_, t->delegate, t->buffer_handle, t)); + t->data_is_stale = false; + } + return kTfLiteOk; + } + + // The default capacity of `tensors_` vector. + static constexpr int kTensorsReservedCapacity = 128; + // The capacity headroom of `tensors_` vector before calling ops' + // `prepare` and `invoke` function. In these functions, it's guaranteed + // allocating up to `kTensorsCapacityHeadroom` more tensors won't invalidate + // pointers to existing tensors. + static constexpr int kTensorsCapacityHeadroom = 16; + + // Reset all variable tensors to the default value. + // If a variable tensor doesn't have a buffer, reset it to zero. + // TODO(b/115961645): Implement - If a variable tensor has a buffer, reset it + // to the value of the buffer. + // WARNING: This is an experimental API and subject to change. + TfLiteStatus ResetVariableTensors(); + + void SetProfiler(profiling::Profiler* profiler) { profiler_ = profiler; } + + profiling::Profiler* GetProfiler() { return profiler_; } + + // Returns a pointer to vector of subgraphs. + // WARNING: This is an experimental API and subject to change. + std::vector>* GetSubgraphs() { return subgraphs_; } + + // True if all tensors in the graph has static size after calling + // `AllocateTensors` function. + // Before `AllocateTensors` is called, this will always return true; + bool HasDynamicTensors() { return has_dynamic_tensors_; } + + private: + // Prevent 'context_' from accessing functions that are only available to + // delegated kernels. + void SwitchToKernelContext(); + + // Add delegate-only functions to 'context_'. + void SwitchToDelegateContext(); + + // Give 'op_reg' a chance to initialize itself using the contents of + // 'buffer'. + void* OpInit(const TfLiteRegistration& op_reg, const char* buffer, + size_t length) { + if (op_reg.init == nullptr) return nullptr; + return op_reg.init(context_, buffer, length); + } + + // Let 'op_reg' release any memory it might have allocated via 'OpInit'. + void OpFree(const TfLiteRegistration& op_reg, void* buffer) { + if (op_reg.free == nullptr) return; + if (buffer) { + op_reg.free(context_, buffer); + } + } + + // Prepare the given 'node' for execution. + TfLiteStatus OpPrepare(const TfLiteRegistration& op_reg, TfLiteNode* node) { + if (op_reg.prepare == nullptr) return kTfLiteOk; + return op_reg.prepare(context_, node); + } + + // Invoke the operator represented by 'node'. + TfLiteStatus OpInvoke(const TfLiteRegistration& op_reg, TfLiteNode* node) { + if (op_reg.invoke == nullptr) return kTfLiteError; + return op_reg.invoke(context_, node); + } + + // Call OpPrepare() for as many ops as possible, allocating memory for their + // tensors. If an op containing dynamic tensors is found, preparation will be + // postponed until this function is called again. This allows the interpreter + // to wait until Invoke() to resolve the sizes of dynamic tensors. + TfLiteStatus PrepareOpsAndTensors(); + + // Call OpPrepare() for all ops starting at 'first_node'. Stop when a + // dynamic tensors is found or all ops have been prepared. Fill + // 'last_node_prepared' with the id of the op containing dynamic tensors, or + // the last in the graph. + TfLiteStatus PrepareOpsStartingAt(int first_execution_plan_index, + int* last_execution_plan_index_prepared); + + // Tensors needed by the interpreter. Use `AddTensors` to add more blank + // tensor entries. Note, `tensors_.data()` needs to be synchronized to the + // `context_` whenever this std::vector is reallocated. Currently this + // only happens in `AddTensors()`. + std::vector tensors_; + + // Check if an array of tensor indices are valid with respect to the Tensor + // array. + // NOTE: this changes consistent_ to be false if indices are out of bounds. + TfLiteStatus CheckTensorIndices(const char* label, const int* indices, + int length); + + // Compute the number of bytes required to represent a tensor with dimensions + // specified by the array dims (of length dims_size). Returns the status code + // and bytes. + TfLiteStatus BytesRequired(TfLiteType type, const int* dims, size_t dims_size, + size_t* bytes); + + // Request an tensor be resized implementation. If the given tensor is of + // type kTfLiteDynamic it will also be allocated new memory. + TfLiteStatus ResizeTensorImpl(TfLiteTensor* tensor, TfLiteIntArray* new_size); + + // Report a detailed error string (will be printed to stderr). + // TODO(aselle): allow user of class to provide alternative destinations. + void ReportErrorImpl(const char* format, va_list args); + + // Entry point for C node plugin API to request an tensor be resized. + static TfLiteStatus ResizeTensor(TfLiteContext* context, TfLiteTensor* tensor, + TfLiteIntArray* new_size); + // Entry point for C node plugin API to report an error. + static void ReportErrorC(TfLiteContext* context, const char* format, ...); + + // Entry point for C node plugin API to add new tensors. + static TfLiteStatus AddTensors(TfLiteContext* context, int tensors_to_add, + int* first_new_tensor_index); + + // WARNING: This is an experimental API and subject to change. + // Entry point for C API ReplaceNodeSubsetsWithDelegateKernels + static TfLiteStatus ReplaceNodeSubsetsWithDelegateKernels( + TfLiteContext* context, TfLiteRegistration registration, + const TfLiteIntArray* nodes_to_replace, TfLiteDelegate* delegate); + + // Update the execution graph to replace some of the nodes with stub + // nodes. Specifically any node index that has `nodes[index]==1` will be + // slated for replacement with a delegate kernel specified by registration. + // Ownership of 'nodes_to_replace' and 'delegate' remains with the caller. + // WARNING: This is an experimental interface that is subject to change. + TfLiteStatus ReplaceNodeSubsetsWithDelegateKernels( + TfLiteRegistration registration, const TfLiteIntArray* nodes_to_replace, + TfLiteDelegate* delegate); + + // WARNING: This is an experimental interface that is subject to change. + // Gets the internal pointer to a TensorFlow lite node by node_index. + TfLiteStatus GetNodeAndRegistration(int node_index, TfLiteNode** node, + TfLiteRegistration** registration); + + // WARNING: This is an experimental interface that is subject to change. + // Entry point for C node plugin API to get a node by index. + static TfLiteStatus GetNodeAndRegistration(struct TfLiteContext*, + int node_index, TfLiteNode** node, + TfLiteRegistration** registration); + + // WARNING: This is an experimental interface that is subject to change. + // Gets an TfLiteIntArray* representing the execution plan. The interpreter + // owns this memory and it is only guaranteed to exist during the invocation + // of the delegate prepare. + TfLiteStatus GetExecutionPlan(TfLiteIntArray** execution_plan); + + // WARNING: This is an experimental interface that is subject to change. + // Entry point for C node plugin API to get the execution plan. + static TfLiteStatus GetExecutionPlan(struct TfLiteContext* context, + TfLiteIntArray** execution_plan); + + // Retrieve an existing external context by type. + TfLiteExternalContext* GetExternalContext(TfLiteExternalContextType type); + static TfLiteExternalContext* GetExternalContext( + struct TfLiteContext* context, TfLiteExternalContextType type); + + // Set the value of an external context. + static void SetExternalContext(struct TfLiteContext* context, + TfLiteExternalContextType type, + TfLiteExternalContext* ctx); + + // Allow a delegate to look at the graph and modify the graph to handle + // parts of the graph themselves. After this is called, the graph may + // contain new nodes that replace 1 more nodes. + // WARNING: This is an experimental API and subject to change. + TfLiteStatus ModifyGraphWithDelegate(TfLiteDelegate* delegate); + + // Ensures that `tensors_` has at least `kTensorsCapacityHeadroom` extra + // capacity. Calling this function may invalidate existing pointers to + // tensors. After calling this function, adding `kTensorsCapacityHeadroom` + // more tensors won't invalidate the pointer to existing tensors. + void EnsureTensorsVectorCapacity() { + const size_t required_capacity = tensors_.size() + kTensorsCapacityHeadroom; + if (required_capacity > tensors_.capacity()) { + tensors_.reserve(required_capacity); + context_->tensors = tensors_.data(); + } + } + + // The state of the Interpreter. + enum State { + // The interpreter isn't ready to be invoked. + // `AllocateTensor` need to be called to enter an invokable state. + kStateUninvokable = 0, + // The interpreter is ready to be invoked. + kStateInvokable, + // The interpreter is ready to be invoked, and graph can't be further + // modified. The interpreter will enter this state when calling + // `ModifyGraphWithDelegate` with `allow_dynamic_tensors=false`. + kStateInvokableAndImmutable, + }; + State state_ = kStateUninvokable; + + // A pure C data structure used to communicate with the pure C plugin + // interface. To avoid copying tensor metadata, this is also the definitive + // structure to store tensors. + // TODO(b/119495520): Get rid of owned and just make context_ a instance. + TfLiteContext owned_context_; + TfLiteContext* context_; + + // Node inputs/outputs are stored in TfLiteNode and TfLiteRegistration stores + // function pointers to actual implementation. + std::vector> + nodes_and_registration_; + + // Whether the model is consistent. That is to say if the inputs and outputs + // of every node and the global inputs and outputs are valid indexes into + // the tensor array. + bool consistent_ = true; + + // Array of indices representing the tensors that are inputs to the + // interpreter. + std::vector inputs_; + + // Array of indices representing the tensors that are outputs to the + // interpreter. + std::vector outputs_; + + // Array of indices representing the tensors that are variable tensors. + std::vector variables_; + + // The error reporter delegate that tflite will forward queries errors to. + ErrorReporter* error_reporter_; + + // Index of the next node to prepare. + // During Invoke(), Interpreter will allocate input tensors first, which are + // known to be fixed size. Then it will allocate outputs from nodes as many + // as possible. When there is a node that produces dynamic sized tensor. + // Interpreter will stop allocating tensors, set the value of next allocate + // node id, and execute the node to generate the output tensor before continue + // to allocate successors. This process repeats until all nodes are executed. + // NOTE: this relies on the order of nodes that is in topological order. + int next_execution_plan_index_to_prepare_; + + // WARNING: This is an experimental interface that is subject to change. + // This is a list of node indices (to index into nodes_and_registration). + // This represents a valid topological sort (dependency ordered) execution + // plan. In particular, it is valid for this ordering to contain only a + // subset of the node indices. + std::vector execution_plan_; + + // In the future, we'd like a TfLiteIntArray compatible representation. + // TODO(aselle): replace execution_plan_ with this. + std::unique_ptr plan_cache_; + + // Whether to delegate to NN API + std::unique_ptr nnapi_delegate_; + + std::unique_ptr memory_planner_; + + // Tracking bit for whether a tensor was resized in the course of an op + // invocation. This is a useful hint to ensure that dynamic tensor outputs + // trigger downstream reallocation after op invocation. + bool tensor_resized_since_op_invoke_ = false; + + // External contexts (kTfLiteMaxExternalContexts). + TfLiteExternalContext** external_contexts_; + + // Profiler for this interpreter instance. + profiling::Profiler* profiler_ = nullptr; + + // A pointer to vector of subgraphs. The vector is owned by the interpreter. + std::vector>* subgraphs_ = nullptr; + + // True if all tensors in the graph has static size after calling + // `PrepareOpsStartingAt` function (which is called by the `AllocateTensors` + // public function). + // The value is invalid before `PrepareOpStartingAt` is called. + bool has_dynamic_tensors_ = true; +}; + +} // namespace tflite +#endif // TENSORFLOW_LITE_CORE_SUBGRAPH_H_ diff --git a/tensorflow/lite/delegates/flex/BUILD b/tensorflow/lite/delegates/flex/BUILD index 222a043a88..75083bf95a 100644 --- a/tensorflow/lite/delegates/flex/BUILD +++ b/tensorflow/lite/delegates/flex/BUILD @@ -83,8 +83,10 @@ cc_library( ":delegate_data", ":kernel", ":util", + "@com_google_absl//absl/strings:strings", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite:kernel_api", + "//tensorflow/lite:string_util", "//tensorflow/lite:util", ] + select({ "//tensorflow:android": [ @@ -116,6 +118,7 @@ cc_library( hdrs = ["delegate_data.h"], deps = [ ":buffer_map", + "@com_google_absl//absl/memory", "//tensorflow/core/common_runtime/eager:context", ] + select({ "//tensorflow:android": [ diff --git a/tensorflow/lite/delegates/flex/buffer_map.cc b/tensorflow/lite/delegates/flex/buffer_map.cc index 9a6c5e74a7..262ca9e089 100644 --- a/tensorflow/lite/delegates/flex/buffer_map.cc +++ b/tensorflow/lite/delegates/flex/buffer_map.cc @@ -93,6 +93,11 @@ class TfLiteTensorBuffer : public BaseTfLiteTensorBuffer { class StringTfLiteTensorBuffer : public BaseTfLiteTensorBuffer { public: explicit StringTfLiteTensorBuffer(const TfLiteTensor* tensor) { + if (tensor->data.raw == nullptr) { + num_strings_ = 0; + data_ = nullptr; + return; + } num_strings_ = GetStringCount(tensor->data.raw); data_ = tensorflow::cpu_allocator()->Allocate(num_strings_); diff --git a/tensorflow/lite/delegates/flex/delegate.cc b/tensorflow/lite/delegates/flex/delegate.cc index 4fc2d82b49..ca7314fbae 100644 --- a/tensorflow/lite/delegates/flex/delegate.cc +++ b/tensorflow/lite/delegates/flex/delegate.cc @@ -16,12 +16,14 @@ limitations under the License. #include +#include "absl/strings/str_cat.h" +#include "tensorflow/core/lib/core/status.h" #include "tensorflow/lite/context_util.h" #include "tensorflow/lite/delegates/flex/buffer_map.h" #include "tensorflow/lite/delegates/flex/kernel.h" #include "tensorflow/lite/delegates/flex/util.h" +#include "tensorflow/lite/string_util.h" #include "tensorflow/lite/util.h" -#include "tensorflow/core/lib/core/status.h" namespace tflite { namespace flex { @@ -57,8 +59,8 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteDelegate* delegate) { TfLiteStatus CopyFromBufferHandle(TfLiteContext* context, TfLiteDelegate* delegate, - TfLiteBufferHandle buffer_handle, void* data, - size_t size) { + TfLiteBufferHandle buffer_handle, + TfLiteTensor* output) { BufferMap* buffer_map = reinterpret_cast(delegate->data_)->GetBufferMap(context); @@ -68,15 +70,38 @@ TfLiteStatus CopyFromBufferHandle(TfLiteContext* context, } tensorflow::Tensor t = buffer_map->GetTensor(buffer_handle); + + if (output->type == kTfLiteString) { + if (t.dtype() != tensorflow::DT_STRING) { + context->ReportError(context, + "Inconsistent type for TF string tensor index %d.", + buffer_handle); + return kTfLiteError; + } + DynamicBuffer dynamic_buffer; + + auto tf_data = t.flat(); + for (int i = 0; i < t.NumElements(); ++i) { + dynamic_buffer.AddString(tf_data(i).data(), tf_data(i).size()); + } + + dynamic_buffer.WriteToTensor(output, /*new_shape=*/nullptr); + return kTfLiteOk; + } + tensorflow::StringPiece t_data = t.tensor_data(); - if (size != t_data.size()) { - context->ReportError( - context, "Not enough space to store TensorFlow's aligned buffer."); + if (output->bytes != t_data.size()) { + context->ReportError(context, + absl::StrCat("The given ", output->bytes, + " bytes are not enough to store " + "TensorFlow's aligned buffer of size ", + t_data.size(), " bytes.") + .c_str()); return kTfLiteError; } - memcpy(data, t_data.data(), t_data.size()); + memcpy(output->data.raw, t_data.data(), t_data.size()); return kTfLiteOk; } @@ -104,14 +129,13 @@ std::unique_ptr FlexDelegate::Create() { } FlexDelegate::FlexDelegate(std::unique_ptr delegate_data) - : TfLiteDelegate{ - /*data_=*/delegate_data.get(), - /*nullptr,*/ &flex::delegate::Prepare, - /*CopyFromBufferHandle=*/&flex::delegate::CopyFromBufferHandle, - /*CopyToBufferHandle=*/nullptr, - /*FreeBufferHandle=*/nullptr, - /*flags=*/kTfLiteDelegateFlagsAllowDynamicTensors}, - delegate_data_(std::move(delegate_data)) {} + : TfLiteDelegate(TfLiteDelegateCreate()), + delegate_data_(std::move(delegate_data)) { + data_ = delegate_data_.get(); + Prepare = &flex::delegate::Prepare; + CopyFromBufferHandle = &flex::delegate::CopyFromBufferHandle; + flags = kTfLiteDelegateFlagsAllowDynamicTensors; +} FlexDelegate::~FlexDelegate() {} diff --git a/tensorflow/lite/delegates/flex/delegate_data.cc b/tensorflow/lite/delegates/flex/delegate_data.cc index b62479a448..1483a53038 100644 --- a/tensorflow/lite/delegates/flex/delegate_data.cc +++ b/tensorflow/lite/delegates/flex/delegate_data.cc @@ -14,20 +14,21 @@ limitations under the License. ==============================================================================*/ #include "tensorflow/lite/delegates/flex/delegate_data.h" +#include "absl/memory/memory.h" #include "tensorflow/core/common_runtime/device_factory.h" #include "tensorflow/core/lib/core/status.h" namespace tflite { namespace flex { tensorflow::Status DelegateData::Create(std::unique_ptr* data) { - std::vector devices; + std::vector> devices; TF_RETURN_IF_ERROR(tensorflow::DeviceFactory::AddDevices( tensorflow::SessionOptions(), "/job:localhost/replica:0/task:0", &devices)); - std::unique_ptr device_mgr( - new tensorflow::DeviceMgr(devices)); + std::unique_ptr device_mgr = + absl::make_unique(std::move(devices)); // Note that Rendezvous is ref-counted so it will be automatically deleted. tensorflow::Rendezvous* rendezvous = new tensorflow::IntraProcessRendezvous(device_mgr.get()); diff --git a/tensorflow/lite/delegates/flex/delegate_test.cc b/tensorflow/lite/delegates/flex/delegate_test.cc index e13029d9a5..1b2f476f03 100644 --- a/tensorflow/lite/delegates/flex/delegate_test.cc +++ b/tensorflow/lite/delegates/flex/delegate_test.cc @@ -93,6 +93,25 @@ TEST_F(DelegateTest, NonFloatTypeInference) { ASSERT_EQ(GetType(2), kTfLiteInt32); } +TEST_F(DelegateTest, StringInference) { + AddTensors(3, {0, 1}, {2}, kTfLiteString, {2}); + + AddTfOp(testing::kAdd, {0, 1}, {2}); + + ConfigureDelegate(); + + SetShape(0, {2, 2}); + SetStringValues(0, {"1", "2", "3", "4"}); + SetShape(1, {2, 2}); + SetStringValues(1, {"4", "3", "2", "1"}); + + ASSERT_TRUE(Invoke()); + + ASSERT_THAT(GetShape(2), ElementsAre(2, 2)); + ASSERT_THAT(GetStringValues(2), ElementsAre("14", "23", "32", "41")); + ASSERT_EQ(GetType(2), kTfLiteString); +} + TEST_F(DelegateTest, MixedGraph) { AddTensors(9, {0, 3}, {8}, kTfLiteFloat32, {3}); diff --git a/tensorflow/lite/delegates/flex/kernel.cc b/tensorflow/lite/delegates/flex/kernel.cc index c4fe142dff..02da1d1a22 100644 --- a/tensorflow/lite/delegates/flex/kernel.cc +++ b/tensorflow/lite/delegates/flex/kernel.cc @@ -15,6 +15,12 @@ limitations under the License. #include "tensorflow/lite/delegates/flex/kernel.h" #include "flatbuffers/flexbuffers.h" // TF:flatbuffers +#include "tensorflow/core/common_runtime/eager/context.h" +#include "tensorflow/core/common_runtime/eager/execute.h" +#include "tensorflow/core/common_runtime/eager/tensor_handle.h" +#include "tensorflow/core/framework/node_def.pb.h" +#include "tensorflow/core/framework/node_def_util.h" +#include "tensorflow/core/lib/core/errors.h" #include "tensorflow/lite/builtin_ops.h" #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/context_util.h" @@ -22,11 +28,6 @@ limitations under the License. #include "tensorflow/lite/delegates/flex/util.h" #include "tensorflow/lite/kernels/kernel_util.h" #include "tensorflow/lite/string.h" -#include "tensorflow/core/common_runtime/eager/context.h" -#include "tensorflow/core/common_runtime/eager/execute.h" -#include "tensorflow/core/common_runtime/eager/tensor_handle.h" -#include "tensorflow/core/framework/node_def.pb.h" -#include "tensorflow/core/framework/node_def_util.h" // Note: this is part of TF Lite's Flex delegation code which is to be // completed soon. @@ -78,11 +79,18 @@ tensorflow::Status ExecuteFlexOp(tensorflow::EagerContext* eager_context, const std::vector& inputs, const std::vector& outputs) { const tensorflow::AttrTypeMap* attr_types; + bool is_function = false; TF_RETURN_WITH_CONTEXT_IF_ERROR( - tensorflow::AttrTypeMapForOp(op_name.c_str(), &attr_types), + tensorflow::AttrTypeMapForOp(op_name.c_str(), &attr_types, &is_function), " (while processing attributes of '", op_name, "')"); - - tensorflow::EagerOperation op(eager_context, op_name.c_str(), attr_types); + if (is_function) { + return tensorflow::errors::NotFound( + "Operation '", op_name, + "' is not registered. (while processing attributes of '", op_name, + "')"); + } + tensorflow::EagerOperation op(eager_context, op_name.c_str(), + /*is_function=*/false, attr_types); for (const auto& attr : nodedef.attr()) { op.MutableAttrs()->Set(attr.first, attr.second); } diff --git a/tensorflow/lite/delegates/flex/kernel_test.cc b/tensorflow/lite/delegates/flex/kernel_test.cc index f55759594d..efb7300b0b 100644 --- a/tensorflow/lite/delegates/flex/kernel_test.cc +++ b/tensorflow/lite/delegates/flex/kernel_test.cc @@ -59,12 +59,12 @@ class KernelTest : public testing::FlexModelTest { delegate_.CopyFromBufferHandle = [](TfLiteContext* context, TfLiteDelegate* delegate, TfLiteBufferHandle buffer_handle, - void* data, size_t size) { + TfLiteTensor* output) { auto* delegate_data = reinterpret_cast(delegate->data_); tensorflow::StringPiece values = delegate_data->GetBufferMap(context) ->GetTensor(buffer_handle) .tensor_data(); - memcpy(data, values.data(), values.size()); + memcpy(output->data.raw, values.data(), values.size()); return kTfLiteOk; }; CHECK(interpreter_->ModifyGraphWithDelegate(&delegate_) == kTfLiteOk); diff --git a/tensorflow/lite/delegates/flex/test_util.cc b/tensorflow/lite/delegates/flex/test_util.cc index 08feb349e6..aa24675a7b 100644 --- a/tensorflow/lite/delegates/flex/test_util.cc +++ b/tensorflow/lite/delegates/flex/test_util.cc @@ -25,6 +25,29 @@ namespace testing { bool FlexModelTest::Invoke() { return interpreter_->Invoke() == kTfLiteOk; } +void FlexModelTest::SetStringValues(int tensor_index, + const std::vector& values) { + DynamicBuffer dynamic_buffer; + for (const string& s : values) { + dynamic_buffer.AddString(s.data(), s.size()); + } + dynamic_buffer.WriteToTensor(interpreter_->tensor(tensor_index), + /*new_shape=*/nullptr); +} + +std::vector FlexModelTest::GetStringValues(int tensor_index) const { + std::vector result; + + TfLiteTensor* tensor = interpreter_->tensor(tensor_index); + auto num_strings = GetStringCount(tensor->data.raw); + for (size_t i = 0; i < num_strings; ++i) { + auto ref = GetString(tensor->data.raw, i); + result.push_back(string(ref.str, ref.len)); + } + + return result; +} + void FlexModelTest::SetShape(int tensor_index, const std::vector& values) { ASSERT_EQ(interpreter_->ResizeInputTensor(tensor_index, values), kTfLiteOk); ASSERT_EQ(interpreter_->AllocateTensors(), kTfLiteOk); @@ -95,12 +118,22 @@ void FlexModelTest::AddTfOp(TfOpType op, const std::vector& inputs, return " attr{ key: '" + key + "' value {" + value + "}}"; }; - // Crude type attribution, will need fleshing out as more tests are added. - // TODO(b/113613439): Use nodedef string utilities to properly handle - // all types. - string type_attribute = attr("T", "type: DT_FLOAT"); - if (interpreter_->tensor(inputs[0])->type == kTfLiteInt32) { - type_attribute = attr("T", "type: DT_INT32"); + string type_attribute; + switch (interpreter_->tensor(inputs[0])->type) { + case kTfLiteInt32: + type_attribute = attr("T", "type: DT_INT32"); + break; + case kTfLiteFloat32: + type_attribute = attr("T", "type: DT_FLOAT"); + break; + case kTfLiteString: + type_attribute = attr("T", "type: DT_STRING"); + break; + default: + // TODO(b/113613439): Use nodedef string utilities to properly handle all + // types. + LOG(FATAL) << "Type not supported"; + break; } if (op == kUnpack) { diff --git a/tensorflow/lite/delegates/flex/test_util.h b/tensorflow/lite/delegates/flex/test_util.h index 4d3f5ad096..2cc2dc30e9 100644 --- a/tensorflow/lite/delegates/flex/test_util.h +++ b/tensorflow/lite/delegates/flex/test_util.h @@ -63,11 +63,13 @@ class FlexModelTest : public ::testing::Test { void SetValues(int tensor_index, const std::vector& values) { SetTypedValues(tensor_index, values); } + void SetStringValues(int tensor_index, const std::vector& values); // Returns the tensor's values at the given index. std::vector GetValues(int tensor_index) { return GetTypedValues(tensor_index); } + std::vector GetStringValues(int tensor_index) const; // Sets the tensor's shape at the given index. void SetShape(int tensor_index, const std::vector& values); diff --git a/tensorflow/lite/delegates/flex/util.cc b/tensorflow/lite/delegates/flex/util.cc index c786ffa1a2..c995b360f9 100644 --- a/tensorflow/lite/delegates/flex/util.cc +++ b/tensorflow/lite/delegates/flex/util.cc @@ -66,6 +66,8 @@ TF_DataType GetTensorFlowDataType(TfLiteType type) { return TF_INT32; case kTfLiteUInt8: return TF_UINT8; + case kTfLiteInt8: + return TF_INT8; case kTfLiteInt64: return TF_INT64; case kTfLiteComplex64: @@ -87,6 +89,8 @@ TfLiteType GetTensorFlowLiteType(TF_DataType type) { return kTfLiteInt32; case TF_UINT8: return kTfLiteUInt8; + case TF_INT8: + return kTfLiteInt8; case TF_INT64: return kTfLiteInt64; case TF_COMPLEX64: diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc index 9690c65921..4fe07004a8 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc @@ -1141,7 +1141,7 @@ class NNAPIDelegateKernel { TfLiteDelegate* NnApiDelegate() { static TfLiteDelegate delegate = { .data_ = nullptr, - .flags = kTfLiteDelegateFlagsAllowDynamicTensors, + .flags = kTfLiteDelegateFlagsNone, .Prepare = [](TfLiteContext* context, TfLiteDelegate* delegate) -> TfLiteStatus { // Do not check nodes_ if NN API is unavailable. diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc index 84a0a6a1d1..ca48af0c95 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc @@ -34,6 +34,11 @@ class SingleOpModelWithNNAPI : public SingleOpModel { interpreter->ModifyGraphWithDelegate(NnApiDelegate()); }); } + + TfLiteStatus ResizeInputTensor(int tensor_index, + const std::vector& dims) { + return interpreter_->ResizeInputTensor(tensor_index, dims); + } }; class FloatAddOpModel : public SingleOpModelWithNNAPI { @@ -97,6 +102,17 @@ TEST(NNAPIDelegate, AddWithRelu) { EXPECT_THAT(m.GetOutput(), ElementsAreArray({0.0, 0.4, 1.0, 1.3})); } +// Verify that resize attempts fail. +// TODO(b/113110851): Verify success after the delegate supports resizing. +TEST(NNAPIDelegate, ResizeFails) { + FloatAddOpModel m({TensorType_FLOAT32, {1, 2, 2, 1}}, + {TensorType_FLOAT32, {1, 2, 2, 1}}, + {TensorType_FLOAT32, {}}, ActivationFunctionType_NONE); + m.PopulateTensor(m.input1(), {-2.0, 0.2, 0.7, 0.8}); + m.PopulateTensor(m.input2(), {0.1, 0.2, 0.3, 0.5}); + EXPECT_EQ(m.ResizeInputTensor(m.input1(), {1, 3, 3, 1}), kTfLiteError); +} + class FloatMulOpModel : public SingleOpModelWithNNAPI { public: FloatMulOpModel(const TensorData& input1, const TensorData& input2, diff --git a/tensorflow/lite/examples/ios/camera/CameraExampleViewController.h b/tensorflow/lite/examples/ios/camera/CameraExampleViewController.h index 6bc94e9502..fb5800e86d 100644 --- a/tensorflow/lite/examples/ios/camera/CameraExampleViewController.h +++ b/tensorflow/lite/examples/ios/camera/CameraExampleViewController.h @@ -17,8 +17,8 @@ #include -#include "tensorflow/lite/kernels/register.h" -#include "tensorflow/lite/model.h" +#include "tensorflow/contrib/lite/kernels/register.h" +#include "tensorflow/contrib/lite/model.h" @interface CameraExampleViewController : UIViewController { diff --git a/tensorflow/lite/examples/ios/camera/CameraExampleViewController.mm b/tensorflow/lite/examples/ios/camera/CameraExampleViewController.mm index 1e6725592b..996cff2616 100644 --- a/tensorflow/lite/examples/ios/camera/CameraExampleViewController.mm +++ b/tensorflow/lite/examples/ios/camera/CameraExampleViewController.mm @@ -23,10 +23,10 @@ #include #include -#include "tensorflow/lite/kernels/register.h" -#include "tensorflow/lite/model.h" -#include "tensorflow/lite/string_util.h" -#include "tensorflow/lite/op_resolver.h" +#include "tensorflow/contrib/lite/kernels/register.h" +#include "tensorflow/contrib/lite/model.h" +#include "tensorflow/contrib/lite/string_util.h" +#include "tensorflow/contrib/lite/op_resolver.h" #define LOG(x) std::cerr diff --git a/tensorflow/lite/examples/ios/camera/Podfile b/tensorflow/lite/examples/ios/camera/Podfile index f460693122..96a0d23426 100644 --- a/tensorflow/lite/examples/ios/camera/Podfile +++ b/tensorflow/lite/examples/ios/camera/Podfile @@ -2,4 +2,4 @@ platform :ios, '8.0' inhibit_all_warnings! target 'tflite_camera_example' - pod 'TensorFlowLite', '1.10.1' + pod 'TensorFlowLite', '1.12.0' diff --git a/tensorflow/lite/examples/ios/simple/Podfile b/tensorflow/lite/examples/ios/simple/Podfile index ddb77088d9..931b72c1f5 100644 --- a/tensorflow/lite/examples/ios/simple/Podfile +++ b/tensorflow/lite/examples/ios/simple/Podfile @@ -2,4 +2,4 @@ platform :ios, '8.0' inhibit_all_warnings! target 'tflite_simple_example' - pod 'TensorFlowLite', '1.10.1' + pod 'TensorFlowLite', '1.12.0' diff --git a/tensorflow/lite/examples/ios/simple/RunModelViewController.mm b/tensorflow/lite/examples/ios/simple/RunModelViewController.mm index e5764944f6..650c73f732 100644 --- a/tensorflow/lite/examples/ios/simple/RunModelViewController.mm +++ b/tensorflow/lite/examples/ios/simple/RunModelViewController.mm @@ -22,10 +22,10 @@ #include #include -#include "tensorflow/lite/kernels/register.h" -#include "tensorflow/lite/model.h" -#include "tensorflow/lite/string_util.h" -#include "tensorflow/lite/op_resolver.h" +#include "tensorflow/contrib/lite/kernels/register.h" +#include "tensorflow/contrib/lite/model.h" +#include "tensorflow/contrib/lite/string_util.h" +#include "tensorflow/contrib/lite/op_resolver.h" #include "ios_image_load.h" diff --git a/tensorflow/lite/experimental/examples/lstm/unidirectional_sequence_lstm_test.py b/tensorflow/lite/experimental/examples/lstm/unidirectional_sequence_lstm_test.py index eeb48d1231..9c00d0501a 100644 --- a/tensorflow/lite/experimental/examples/lstm/unidirectional_sequence_lstm_test.py +++ b/tensorflow/lite/experimental/examples/lstm/unidirectional_sequence_lstm_test.py @@ -111,7 +111,7 @@ class UnidirectionalSequenceLstmTest(test_util.TensorFlowTestCase): # Initialize variables init = tf.global_variables_initializer() - sess.run(init) + self.evaluate(init) for _ in range(TRAIN_STEPS): batch_x, batch_y = self.mnist.train.next_batch( batch_size=self.batch_size, shuffle=False) diff --git a/tensorflow/lite/experimental/micro/README.md b/tensorflow/lite/experimental/micro/README.md index 673daed74c..cc2a62cb8a 100644 --- a/tensorflow/lite/experimental/micro/README.md +++ b/tensorflow/lite/experimental/micro/README.md @@ -126,3 +126,45 @@ debug logs here, along with the magic string `~~~ALL TESTS PASSED~~~`. This is the exact same code as before, just compiled and run on the STM32F103 rather than your desktop. We hope that the simplicity of this testing approach will help make adding support for new platforms as easy as possible. + +## Building for Apollo3 + +Follow these steps to get the pushbutton yes/no example working on Apollo 3: + +1. Make sure to run the "Getting Started" section before performing the following steps +2. Download Apollo3-SDK-2018.08.13 and place in tensorflow/lite/experimental/micro/tools/make/downloads +3. Copy and prepare files by running tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh from the toplevel of git +4. Install [Segger JLink tools](https://www.segger.com/downloads/jlink/) +5. Make sure the [GNU Arm Embedded Toolchain (gcc-arm-none-eabi-7-2018-q2-update)](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) is installed to tensorflow/lite/experimental/micro/tools/make/downloads + 1. Confirm directory is in $PATH +6. Compile the project with the following command: make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=apollo3evb pushbutton_cmsis_speech_test_bin +7. Connect the Apollo3 EVB (with mic shield) to the computer and power it on +8. Start the GDB server in a new terminal with the following command: JLinkGDBServer -select USB -device AMA3B1KK-KBR -endian little -if SWD -speed 1000 -noir -noLocalhostOnly + 1. The command has run successfully if you see the message "Waiting for GDB connection" +9. Back in the original terminal, run the program via the debugger + 1. Navigate to tensorflow/lite/experimental/micro/examples/micro_speech/apollo3 + 2. Start gdb by entering the following command: arm-none-eabi-gdb + 3. Run the command script by entering the following command: source pushbutton_cmsis_scores.cmd. This script does the following: + 1. Load the binary created in step 6 + 2. Set a breakpoint after inference scores have been computed + 3. Tell the debugger what variables should be printed out at this breakpoint + 4. Begin program execution + 5. Press Ctrl+c to exit + 4. Press BTN2. An LED will flash for 1 second. Speak your utterance during this one second + 5. The debugger will print out four numbers. They are the probabilites for 1) no speech, 2) unknown speech, 3) yes, 4) no + 6. The EVB LEDs will indicate detection. + 1. LED0 (rightmost LED) - ON when capturing 1sec of audio + 2. LED1 - ON when detecting silence + 3. LED2 - ON when detecting UNKNOWN utterance + 4. LED3 - ON when detecting YES utterance + 5. LED4 (leftmost LED) - ON when detecting NO utterance + +### Additional Apollo3 Instructions + +To flash a part with JFlash Lite, do the following: +1. At the command line: JFlashLiteExe +2. Device = AMA3B1KK-KBR +3. Interface = SWD at 1000 kHz +4. Data file = tensorflow/lite/experimental/micro/tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test.bin +5. Prog Addr = 0x0000C000 + diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/.gitignore b/tensorflow/lite/experimental/micro/examples/micro_speech/.gitignore new file mode 100644 index 0000000000..d8dd7532ab --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/.gitignore @@ -0,0 +1 @@ +*.wav diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/BUILD b/tensorflow/lite/experimental/micro/examples/micro_speech/BUILD index 07fb876411..799b2e5a5d 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/BUILD +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/BUILD @@ -10,18 +10,46 @@ load( "tflite_micro_cc_test", ) -tflite_micro_cc_test( - name = "micro_speech_test", +cc_library( + name = "model_settings", + srcs = [ + "model_settings.cc", + ], + hdrs = [ + "model_settings.h", + ], +) + +cc_library( + name = "tiny_conv_model_data", srcs = [ - "micro_speech_test.cc", - "no_features_data.cc", - "no_features_data.h", "tiny_conv_model_data.cc", + ], + hdrs = [ "tiny_conv_model_data.h", + ], +) + +cc_library( + name = "features_test_data", + srcs = [ + "no_features_data.cc", "yes_features_data.cc", + ], + hdrs = [ + "no_features_data.h", "yes_features_data.h", ], +) + +tflite_micro_cc_test( + name = "micro_speech_test", + srcs = [ + "micro_speech_test.cc", + ], deps = [ + ":features_test_data", + ":tiny_conv_model_data", "//tensorflow/lite:schema_fbs_version", "//tensorflow/lite/experimental/micro:micro_framework", "//tensorflow/lite/experimental/micro/kernels:all_ops_resolver", @@ -31,46 +59,185 @@ tflite_micro_cc_test( ], ) -tflite_micro_cc_test( - name = "preprocessor_reference_test", +cc_library( + name = "preprocessor_test_data", srcs = [ "no_30ms_sample_data.cc", - "no_30ms_sample_data.h", "no_power_spectrum_data.cc", + "yes_30ms_sample_data.cc", + "yes_power_spectrum_data.cc", + ], + hdrs = [ + "no_30ms_sample_data.h", "no_power_spectrum_data.h", + "yes_30ms_sample_data.h", + "yes_power_spectrum_data.h", + ], +) + +cc_library( + name = "preprocessor_reference", + srcs = [ "preprocessor.cc", + ], + hdrs = [ "preprocessor.h", + ], + deps = [ + ":model_settings", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +tflite_micro_cc_test( + name = "preprocessor_reference_test", + srcs = [ "preprocessor_test.cc", - "yes_30ms_sample_data.cc", - "yes_30ms_sample_data.h", - "yes_power_spectrum_data.cc", - "yes_power_spectrum_data.h", ], deps = [ + ":model_settings", + ":preprocessor_reference", + ":preprocessor_test_data", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", "//tensorflow/lite/experimental/micro/testing:micro_test", ], ) -tflite_micro_cc_test( - name = "preprocessor_fixed_test", +cc_library( + name = "preprocessor_fixed", srcs = [ "fixed_point/preprocessor.cc", - "no_30ms_sample_data.cc", - "no_30ms_sample_data.h", - "no_power_spectrum_data.cc", - "no_power_spectrum_data.h", + ], + hdrs = [ "preprocessor.h", + ], + deps = [ + ":model_settings", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +tflite_micro_cc_test( + name = "preprocessor_fixed_test", + srcs = [ "preprocessor_test.cc", - "yes_30ms_sample_data.cc", - "yes_30ms_sample_data.h", - "yes_power_spectrum_data.cc", - "yes_power_spectrum_data.h", ], deps = [ + ":model_settings", + ":preprocessor_fixed", + ":preprocessor_test_data", "//tensorflow/lite/c:c_api_internal", "//tensorflow/lite/experimental/micro:micro_framework", "//tensorflow/lite/experimental/micro/testing:micro_test", ], ) + +cc_library( + name = "audio_provider", + srcs = [ + "audio_provider.cc", + ], + hdrs = [ + "audio_provider.h", + ], + deps = [ + ":model_settings", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +tflite_micro_cc_test( + name = "audio_provider_test", + srcs = [ + "audio_provider_test.cc", + ], + deps = [ + ":audio_provider", + ":model_settings", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +cc_library( + name = "feature_provider", + srcs = [ + "feature_provider.cc", + ], + hdrs = [ + "feature_provider.h", + ], + deps = [ + ":audio_provider", + ":model_settings", + ":preprocessor_reference", + ":timer", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + ], +) + +tflite_micro_cc_test( + name = "feature_provider_test", + srcs = [ + "feature_provider_test.cc", + ], + deps = [ + ":audio_provider", + ":feature_provider", + ":model_settings", + ":timer", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +cc_library( + name = "timer", + srcs = [ + "timer.cc", + ], + hdrs = [ + "timer.h", + ], +) + +tflite_micro_cc_test( + name = "timer_test", + srcs = [ + "timer_test.cc", + ], + deps = [ + ":timer", + "//tensorflow/lite/c:c_api_internal", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/testing:micro_test", + ], +) + +cc_binary( + name = "micro_speech", + srcs = [ + "main.cc", + ], + deps = [ + ":audio_provider", + ":feature_provider", + ":features_test_data", + ":model_settings", + ":preprocessor_reference", + ":timer", + ":tiny_conv_model_data", + "//tensorflow/lite:schema_fbs_version", + "//tensorflow/lite/experimental/micro:micro_framework", + "//tensorflow/lite/experimental/micro/kernels:all_ops_resolver", + "//tensorflow/lite/experimental/micro/kernels:micro_ops", + "//tensorflow/lite/schema:schema_fbs", + ], +) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/README.md b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/README.md new file mode 100644 index 0000000000..fde48374c8 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/README.md @@ -0,0 +1,10 @@ +# Description of files + +* **arm_cmplx_mag_squared_q10p6.c**: Modified version of the ARM CMSIS function [arm_cmplx_mag_squared.c](http://arm-software.github.io/CMSIS_5/DSP/html/group__cmplx__mag__squared.html#ga45537f576102d960d467eb722b8431f2). The modification is that we have changed the amount of right-shift to make sure our data is in the correct range. We redistribute because the original content was created with the Apache 2.0 license. +* **arm_cmplx_mag_squared_q10p6.h**: Header file for arm_cmplx_mag_squared_q10p6.c +* **create_constants.py**: Python file used to create hanning.cc, hanning.h, sin_1k.cc, and sin_1k.h +* **hanning.cc**: Precomputed [Hann window](https://en.wikipedia.org/wiki/Hann_function) for use in the preprocessor. This file is created in ../create_constants.py +* **hanning.h**: Header file fro hanning.cc +* **preprocessor.cc**: CMSIS version of the preprocessor +* **sin_1k.cc**: A 1 kHZ sinusoid used for comparing the CMSIS preprocessor with the Micro-Lite fixed_point preprocessor +* **sin_1k.h**: Header file for sin_1k.cc diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.c b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.c new file mode 100644 index 0000000000..b050f6048d --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.c @@ -0,0 +1,141 @@ +/* This file is a modification of the ARM CMSIS library file arm_cmplx_mag_squared_q15.c + * We have retained the original copyright and header information, in + * accordance with the Apache 2.0 license terms. + */ + +/* ---------------------------------------------------------------------- + * Project: CMSIS DSP Library + * Title: arm_cmplx_mag_squared_q15.c + * Description: Q15 complex magnitude squared + * + * $Date: 27. January 2017 + * $Revision: V.1.5.1 + * + * Target Processor: Cortex-M cores + * -------------------------------------------------------------------- */ +/* + * Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "arm_math.h" + +/** + * @ingroup groupCmplxMath + */ + +/** + * @addtogroup cmplx_mag_squared + * @{ + */ + +/** + * @brief Q15 complex magnitude squared + * @param *pSrc points to the complex input vector + * @param *pDst points to the real output vector + * @param numSamples number of complex samples in the input vector + * @return none. + * + * Scaling and Overflow Behavior: + * \par + * The function implements 1.15 by 1.15 multiplications and finally output is converted into 3.13 format. + */ + +void arm_cmplx_mag_squared_q10p6( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples) +{ + q31_t acc0, acc1; /* Accumulators */ + +#if defined (ARM_MATH_DSP) + + /* Run the below code for Cortex-M4 and Cortex-M3 */ + uint32_t blkCnt; /* loop counter */ + q31_t in1, in2, in3, in4; + q31_t acc2, acc3; + + /*loop Unrolling */ + blkCnt = numSamples >> 2U; + + /* First part of the processing with loop unrolling. Compute 4 outputs at a time. + ** a second loop below computes the remaining 1 to 3 samples. */ + while (blkCnt > 0U) + { + /* C[0] = (A[0] * A[0] + A[1] * A[1]) */ + in1 = *__SIMD32(pSrc)++; + in2 = *__SIMD32(pSrc)++; + in3 = *__SIMD32(pSrc)++; + in4 = *__SIMD32(pSrc)++; + + acc0 = __SMUAD(in1, in1); + acc1 = __SMUAD(in2, in2); + acc2 = __SMUAD(in3, in3); + acc3 = __SMUAD(in4, in4); + + /* store the result in 3.13 format in the destination buffer. */ + *pDst++ = (q15_t) (acc0 >> 6); + *pDst++ = (q15_t) (acc1 >> 6); + *pDst++ = (q15_t) (acc2 >> 6); + *pDst++ = (q15_t) (acc3 >> 6); + + /* Decrement the loop counter */ + blkCnt--; + } + + /* If the numSamples is not a multiple of 4, compute any remaining output samples here. + ** No loop unrolling is used. */ + blkCnt = numSamples % 0x4U; + + while (blkCnt > 0U) + { + /* C[0] = (A[0] * A[0] + A[1] * A[1]) */ + in1 = *__SIMD32(pSrc)++; + acc0 = __SMUAD(in1, in1); + + /* store the result in 3.13 format in the destination buffer. */ + *pDst++ = (q15_t) (acc0 >> 6); + + /* Decrement the loop counter */ + blkCnt--; + } + +#else + + /* Run the below code for Cortex-M0 */ + q15_t real, imag; /* Temporary variables to store real and imaginary values */ + + while (numSamples > 0U) + { + /* out = ((real * real) + (imag * imag)) */ + real = *pSrc++; + imag = *pSrc++; + acc0 = (real * real); + acc1 = (imag * imag); + /* store the result in 3.13 format in the destination buffer. */ + *pDst++ = (q15_t) (((q63_t) acc0 + acc1) >> 6); + + /* Decrement the loop counter */ + numSamples--; + } + +#endif /* #if defined (ARM_MATH_DSP) */ + +} + +/** + * @} end of cmplx_mag_squared group + */ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h new file mode 100644 index 0000000000..24144615cc --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h @@ -0,0 +1,33 @@ +/* This file is a modification of the ARM CMSIS library file arm_math.h + * We have retained the original copyright and header information, in + * accordance with the Apache 2.0 license terms. + */ + +/****************************************************************************** + * @file arm_math.h + * @brief Public header file for CMSIS DSP LibraryU + * @version V1.5.3 + * @date 10. January 2018 + ******************************************************************************/ +/* + * Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +void arm_cmplx_mag_squared_q10p6( + q15_t * pSrc, + q15_t * pDst, + uint32_t numSamples); diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/create_constants.py b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/create_constants.py new file mode 100755 index 0000000000..c7cf8bf61b --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/create_constants.py @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import soundfile as sf +import numpy as np + +def to_cc(x, varname, directory='', scale_factor=1): + x = (x/np.max(np.abs(x)))*32768*scale_factor + x[x>32767] = 32767 + x[x<-32768] = -32768 + x = x.astype(int) + x = [str(v) if i%10!=0 else '\n '+str(v) for i,v in enumerate(x)] + + cmsis_path = "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS" + xstr = '#include "{}/{}.h"\n\n'.format(cmsis_path, varname) + xstr += 'const int g_{}_size = {};\n'.format(varname, len(x)) + xstr += 'const int16_t g_{}[{}] = {{{}}};\n'.format(varname, len(x), ', '.join(x)) + + with open(directory+varname+'.cc','w') as f: + f.write(xstr) + +def to_h(x, varname, directory=''): + tf_prepend = 'TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_' + xstr = '#ifndef {}{}_H_\n'.format(tf_prepend, varname.upper()) + xstr += '#define {}{}_H_\n\n'.format(tf_prepend, varname.upper()) + xstr += '#include \n\n' + xstr += 'extern const int g_{}_size;\n'.format(varname) + xstr += 'extern const int16_t g_{}[];\n\n'.format(varname) + xstr += '#endif' + + with open(directory+varname+'.h','w') as f: + f.write(xstr) + +#x = sf.read('yes_f2e59fea_nohash_1.wav')[0] +#to_cc(x, 'yes_waveform') +#to_h(x, 'yes_waveform') +# +#x = sf.read('no_f9643d42_nohash_4.wav')[0] +#to_cc(x, 'no_waveform') +#to_h(x, 'no_waveform') + + +# 30ms of data @ 16 kHz = 480 samples +hann = np.hanning(int(16000*0.03)) # Window 30ms of data +to_cc(hann, 'hanning', directory='./') +to_h(hann, 'hanning', directory='./') + +t = np.arange(16000.*0.03)/16000. +sin1k = np.sin(2*np.pi*1000*t) # Factor of 10 because micro preprocessing overflows otherwise +to_cc(sin1k, 'sin_1k', directory='./', scale_factor=0.1) +to_h(sin1k, 'sin_1k', directory='./') diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h deleted file mode 100644 index b610f79190..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h +++ /dev/null @@ -1 +0,0 @@ -q15_t hann[480] = {0, 1, 5, 12, 22, 35, 50, 69, 90, 114, 140, 170, 202, 237, 275, 316, 359, 405, 454, 506, 560, 617, 677, 739, 805, 873, 943, 1016, 1092, 1171, 1252, 1335, 1422, 1511, 1602, 1696, 1793, 1892, 1993, 2097, 2203, 2312, 2424, 2537, 2653, 2772, 2893, 3016, 3141, 3269, 3399, 3531, 3665, 3802, 3941, 4081, 4224, 4370, 4517, 4666, 4817, 4970, 5125, 5283, 5442, 5603, 5765, 5930, 6096, 6264, 6434, 6606, 6779, 6954, 7131, 7309, 7488, 7670, 7852, 8037, 8222, 8409, 8598, 8788, 8979, 9171, 9364, 9559, 9755, 9952, 10151, 10350, 10550, 10751, 10954, 11157, 11361, 11566, 11772, 11979, 12186, 12394, 12603, 12812, 13022, 13233, 13444, 13656, 13868, 14080, 14293, 14507, 14720, 14934, 15148, 15363, 15577, 15792, 16007, 16222, 16437, 16652, 16866, 17081, 17296, 17510, 17725, 17939, 18153, 18366, 18579, 18792, 19004, 19216, 19428, 19639, 19849, 20059, 20268, 20476, 20684, 20891, 21097, 21302, 21507, 21711, 21913, 22115, 22316, 22516, 22715, 22912, 23109, 23304, 23498, 23691, 23883, 24074, 24263, 24450, 24637, 24822, 25005, 25187, 25368, 25547, 25724, 25900, 26074, 26246, 26417, 26586, 26753, 26919, 27082, 27244, 27404, 27562, 27718, 27873, 28025, 28175, 28323, 28469, 28613, 28755, 28895, 29033, 29168, 29301, 29433, 29561, 29688, 29812, 29934, 30054, 30171, 30286, 30398, 30508, 30616, 30721, 30824, 30924, 31022, 31117, 31210, 31300, 31388, 31473, 31555, 31635, 31712, 31787, 31858, 31928, 31994, 32058, 32119, 32178, 32233, 32286, 32337, 32384, 32429, 32471, 32510, 32547, 32580, 32611, 32639, 32665, 32687, 32707, 32724, 32738, 32749, 32758, 32763, 32766, 32766, 32763, 32758, 32749, 32738, 32724, 32707, 32687, 32665, 32639, 32611, 32580, 32547, 32510, 32471, 32429, 32384, 32337, 32286, 32233, 32178, 32119, 32058, 31994, 31928, 31858, 31787, 31712, 31635, 31555, 31473, 31388, 31300, 31210, 31117, 31022, 30924, 30824, 30721, 30616, 30508, 30398, 30286, 30171, 30054, 29934, 29812, 29688, 29561, 29433, 29301, 29168, 29033, 28895, 28755, 28613, 28469, 28323, 28175, 28025, 27873, 27718, 27562, 27404, 27244, 27082, 26919, 26753, 26586, 26417, 26246, 26074, 25900, 25724, 25547, 25368, 25187, 25005, 24822, 24637, 24450, 24263, 24074, 23883, 23691, 23498, 23304, 23109, 22912, 22715, 22516, 22316, 22115, 21913, 21711, 21507, 21302, 21097, 20891, 20684, 20476, 20268, 20059, 19849, 19639, 19428, 19216, 19004, 18792, 18579, 18366, 18153, 17939, 17725, 17510, 17296, 17081, 16866, 16652, 16437, 16222, 16007, 15792, 15577, 15363, 15148, 14934, 14720, 14507, 14293, 14080, 13868, 13656, 13444, 13233, 13022, 12812, 12603, 12394, 12186, 11979, 11772, 11566, 11361, 11157, 10954, 10751, 10550, 10350, 10151, 9952, 9755, 9559, 9364, 9171, 8979, 8788, 8598, 8409, 8222, 8037, 7852, 7670, 7488, 7309, 7131, 6954, 6779, 6606, 6434, 6264, 6096, 5930, 5765, 5603, 5442, 5283, 5125, 4970, 4817, 4666, 4517, 4370, 4224, 4081, 3941, 3802, 3665, 3531, 3399, 3269, 3141, 3016, 2893, 2772, 2653, 2537, 2424, 2312, 2203, 2097, 1993, 1892, 1793, 1696, 1602, 1511, 1422, 1335, 1252, 1171, 1092, 1016, 943, 873, 805, 739, 677, 617, 560, 506, 454, 405, 359, 316, 275, 237, 202, 170, 140, 114, 90, 69, 50, 35, 22, 12, 5, 1, 0}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc new file mode 100644 index 0000000000..32aa5b2b7e --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h" + +const int g_hanning_size = 480; +const int16_t g_hanning[480] = { + 0, 1, 5, 12, 22, 35, 50, 69, 90, 114, + 140, 170, 202, 237, 275, 316, 359, 405, 454, 506, + 560, 617, 677, 740, 805, 873, 943, 1016, 1092, 1171, + 1252, 1336, 1422, 1511, 1602, 1696, 1793, 1892, 1993, 2097, + 2204, 2312, 2424, 2537, 2653, 2772, 2893, 3016, 3141, 3269, + 3399, 3531, 3665, 3802, 3941, 4082, 4225, 4370, 4517, 4666, + 4817, 4971, 5126, 5283, 5442, 5603, 5765, 5930, 6096, 6265, + 6435, 6606, 6779, 6954, 7131, 7309, 7489, 7670, 7853, 8037, + 8223, 8410, 8598, 8788, 8979, 9171, 9365, 9560, 9756, 9953, + 10151, 10350, 10551, 10752, 10954, 11157, 11362, 11567, 11772, 11979, + 12186, 12395, 12603, 12813, 13023, 13233, 13445, 13656, 13868, 14081, + 14294, 14507, 14721, 14935, 15149, 15363, 15578, 15793, 16008, 16222, + 16437, 16652, 16867, 17082, 17297, 17511, 17725, 17939, 18153, 18367, + 18580, 18793, 19005, 19217, 19428, 19639, 19850, 20059, 20269, 20477, + 20685, 20892, 21098, 21303, 21508, 21712, 21914, 22116, 22317, 22517, + 22716, 22913, 23110, 23305, 23499, 23692, 23884, 24075, 24264, 24451, + 24638, 24823, 25006, 25188, 25369, 25548, 25725, 25901, 26075, 26247, + 26418, 26587, 26754, 26920, 27083, 27245, 27405, 27563, 27719, 27874, + 28026, 28176, 28324, 28470, 28614, 28756, 28896, 29034, 29169, 29303, + 29434, 29563, 29689, 29813, 29935, 30055, 30172, 30287, 30400, 30510, + 30617, 30723, 30825, 30926, 31023, 31119, 31211, 31301, 31389, 31474, + 31556, 31636, 31713, 31788, 31860, 31929, 31996, 32059, 32121, 32179, + 32235, 32288, 32338, 32386, 32430, 32472, 32512, 32548, 32582, 32613, + 32641, 32666, 32689, 32708, 32725, 32739, 32751, 32759, 32765, 32767, + 32767, 32765, 32759, 32751, 32739, 32725, 32708, 32689, 32666, 32641, + 32613, 32582, 32548, 32512, 32472, 32430, 32386, 32338, 32288, 32235, + 32179, 32121, 32059, 31996, 31929, 31860, 31788, 31713, 31636, 31556, + 31474, 31389, 31301, 31211, 31119, 31023, 30926, 30825, 30723, 30617, + 30510, 30400, 30287, 30172, 30055, 29935, 29813, 29689, 29563, 29434, + 29303, 29169, 29034, 28896, 28756, 28614, 28470, 28324, 28176, 28026, + 27874, 27719, 27563, 27405, 27245, 27083, 26920, 26754, 26587, 26418, + 26247, 26075, 25901, 25725, 25548, 25369, 25188, 25006, 24823, 24638, + 24451, 24264, 24075, 23884, 23692, 23499, 23305, 23110, 22913, 22716, + 22517, 22317, 22116, 21914, 21712, 21508, 21303, 21098, 20892, 20685, + 20477, 20269, 20059, 19850, 19639, 19428, 19217, 19005, 18793, 18580, + 18367, 18153, 17939, 17725, 17511, 17297, 17082, 16867, 16652, 16437, + 16222, 16008, 15793, 15578, 15363, 15149, 14935, 14721, 14507, 14294, + 14081, 13868, 13656, 13445, 13233, 13023, 12813, 12603, 12395, 12186, + 11979, 11772, 11567, 11362, 11157, 10954, 10752, 10551, 10350, 10151, + 9953, 9756, 9560, 9365, 9171, 8979, 8788, 8598, 8410, 8223, + 8037, 7853, 7670, 7489, 7309, 7131, 6954, 6779, 6606, 6435, + 6265, 6096, 5930, 5765, 5603, 5442, 5283, 5126, 4971, 4817, + 4666, 4517, 4370, 4225, 4082, 3941, 3802, 3665, 3531, 3399, + 3269, 3141, 3016, 2893, 2772, 2653, 2537, 2424, 2312, 2204, + 2097, 1993, 1892, 1793, 1696, 1602, 1511, 1422, 1336, 1252, + 1171, 1092, 1016, 943, 873, 805, 740, 677, 617, 560, + 506, 454, 405, 359, 316, 275, 237, 202, 170, 140, + 114, 90, 69, 50, 35, 22, 12, 5, 1, 0}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h new file mode 100644 index 0000000000..0982f33c48 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_HANNING_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_HANNING_H_ + +#include + +extern const int g_hanning_size; +extern const int16_t g_hanning[]; + +#endif diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h deleted file mode 100644 index c19566bfb6..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -// This data was extracted from the larger feature data held in -// no_features_data.cc and consists of the 29th spectrogram slice of 43 values. -// This is the expected result of running the sample data in -// no_30ms_sample_data.cc through through the preprocessing pipeline. - -#ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_POWER_SPECTRUM_DATA_H_ -#define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_POWER_SPECTRUM_DATA_H_ - -#include - -constexpr int g_no_power_spectrum_data_size = 43; -extern const uint8_t g_no_power_spectrum_data[]; - -#endif // TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_NO_POWER_SPECTRUM_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc index 24119cbdda..6bc3c4cb77 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc @@ -18,11 +18,17 @@ extern "C" { #define IFFT_FLAG_R 0 #define BIT_REVERSE_FLAG 1 #define FFT_SIZE 512 + #define FFT_SIZE_DIV2 256 #include - #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hann.h" + #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h" + #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h" } - #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" + +void quantize(q15_t* bufA, q15_t* bufB, uint8_t* output); + + q15_t bufA[FFT_SIZE]; q15_t bufB[FFT_SIZE]; @@ -52,25 +58,49 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, return kTfLiteError; } - arm_mult_q15((q15_t *) input, hann, bufB, 512); + // 30ms at 16 kHz = 480 samples + // We want to pad the rest of the 512-sample buffer with zeros + arm_mult_q15((q15_t *) input, g_hanning, bufB, 480); + int i; + for(i=480; i<512; i++) { + bufB[i] = 0; + } // Should move init code outside of Preprocess() function arm_math_status = arm_rfft_init_q15(&S_arm_fft, FFT_SIZE, IFFT_FLAG_R, BIT_REVERSE_FLAG); arm_rfft_q15(&S_arm_fft, bufB, bufA); - arm_shift_q15(bufA, 5, bufB, FFT_SIZE); - arm_cmplx_mag_squared_q15(bufB, bufA, 256); - arm_shift_q15(bufA, 1, bufB, 256); + // The rfft function packs data as follows: + // {real[0], real[N/2], real[1], imag[1], ..., real[N/2-1], imag[N/2-1]} + // Below we pack as follows: + // {real[0], 0, real[1], imag[1], ..., real[N/2-1], imag[N/2-1, real[N/2], 0} + bufA[FFT_SIZE_DIV2] = bufA[1]; + bufA[FFT_SIZE_DIV2 + 1] = 0; + bufA[1] = 0; + arm_cmplx_mag_squared_q10p6(bufA, bufB, FFT_SIZE_DIV2 + 1); + + quantize(bufA, bufB, output); + return kTfLiteOk; +} + +void quantize(q15_t* bufA, q15_t* bufB, uint8_t* output) { int i; for (i=0; i<42; i++) { arm_mean_q15(bufB+6*i, 6, bufA+i); } - arm_mean_q15(bufB+252, 4, bufA+42); + arm_mean_q15(bufB+252, 5, bufA+42); for (i=0; i<43; i++) { output[i] = (uint8_t) (bufA[i] >> 5); } +} +TfLiteStatus Preprocess_1sec(tflite::ErrorReporter* error_reporter, + const int16_t* input, uint8_t* output) { + int i; + for(i=0; i<49; i++) { + Preprocess(error_reporter, input+i*320, 480, 43, output+i*43); + } return kTfLiteOk; } diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc deleted file mode 100644 index 5986fb4913..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.h" -#include "tensorflow/lite/c/c_api_internal.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" -#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" -#include "tensorflow/lite/experimental/micro/testing/micro_test.h" - -TF_LITE_MICRO_TESTS_BEGIN - -TF_LITE_MICRO_TEST(TestPreprocessor) { - tflite::MicroErrorReporter micro_error_reporter; - tflite::ErrorReporter* error_reporter = µ_error_reporter; - - uint8_t yes_calculated_data[g_yes_power_spectrum_data_size]; - TfLiteStatus yes_status = Preprocess( - error_reporter, g_yes_30ms_sample_data, g_yes_30ms_sample_data_size, - g_yes_power_spectrum_data_size, yes_calculated_data); - TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, yes_status); - - for (int i = 0; i < g_yes_power_spectrum_data_size; ++i) { - TF_LITE_MICRO_EXPECT_EQ(g_yes_power_spectrum_data[i], - yes_calculated_data[i]); - if (g_yes_power_spectrum_data[i] != yes_calculated_data[i]) { - error_reporter->Report("Expected value %d but found %d", - g_yes_power_spectrum_data[i], - yes_calculated_data[i]); - } - } - - uint8_t no_calculated_data[g_yes_power_spectrum_data_size]; - TfLiteStatus no_status = Preprocess( - error_reporter, g_no_30ms_sample_data, g_no_30ms_sample_data_size, - g_no_power_spectrum_data_size, no_calculated_data); - TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, no_status); - - for (int i = 0; i < g_no_power_spectrum_data_size; ++i) { - TF_LITE_MICRO_EXPECT_EQ(g_no_power_spectrum_data[i], no_calculated_data[i]); - if (g_no_power_spectrum_data[i] != no_calculated_data[i]) { - error_reporter->Report("Expected value %d but found %d", - g_no_power_spectrum_data[i], - no_calculated_data[i]); - } - } -} - -TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc new file mode 100644 index 0000000000..be66e5f548 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h" + +const int g_sin_1k_size = 480; +const int16_t g_sin_1k[480] = { + 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, + -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, + 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, + -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, + 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, + 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, + -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, + 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, + 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, + -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, + 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, + -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, + 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, + 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, + -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, + 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, + 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, + -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, + 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, + -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, + 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, + 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, + -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, + 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, + 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, + -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, + 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, + -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, + 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, + 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, + -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, + 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, + 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, + -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, + 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, + -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, + 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, + 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, + -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, + 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, + 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, + -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, + 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, + -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, + 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, + 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, + -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, + 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h new file mode 100644 index 0000000000..645e262aa1 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIN_1K_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIN_1K_H_ + +#include + +extern const int g_sin_1k_size; +extern const int16_t g_sin_1k[]; + +#endif diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h deleted file mode 100644 index b02853f2ea..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -// This data was extracted from the larger feature data held in -// no_features_data.cc and consists of the 26th spectrogram slice of 43 values. -// This is the expected result of running the sample data in -// yes_30ms_sample_data.cc through through the preprocessing pipeline. - -#ifndef TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_POWER_SPECTRUM_DATA_H_ -#define TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_POWER_SPECTRUM_DATA_H_ - -#include - -constexpr int g_yes_power_spectrum_data_size = 43; -extern const uint8_t g_yes_power_spectrum_data[]; - -#endif // TENSORFLOW_CONTRIB_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_YES_POWER_SPECTRUM_DATA_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/.gitignore b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/.gitignore new file mode 100644 index 0000000000..cb8d4d02c4 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/.gitignore @@ -0,0 +1,4 @@ +captured_data.txt +captured_data.wav +cmsis_*.txt +micro_*.txt diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md new file mode 100644 index 0000000000..967b833501 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md @@ -0,0 +1,72 @@ +# TODO + +* preprocessor_cmsis_test_bin + +# Description of Apollo3 Makefile targets + +* **pushbutton_cmsis_speech_test_bin**: + * When users press BTN2 on the Apollo3 EVK, 1 second of audio is captured. + * Then the audio is sent to the CMSIS version of the preprocessor and into the neural net + * To print out the neural net's inference scores, run GDB and source pushbutton\_cmsis\_scores.cmd + * To save the captured audio to a text file (captured\_data.txt), run GDB and source pushbutton\_cmsis\_voice.cmd + * Setup python + * sudo apt install python-pip + * sudo apt install python-tk + * pip install numpy + * pip install matplotlib + * pip install pysoundfile + * python captured_data_to_wav.py + * captured\_data.txt can be turned into a \*.wav file using captured\_data\_to\_wav.py by executing "python captured\_data\_to\_wav.py" +* **preprocessor_1k_cmsis_test_bin**: + * Sends a 1 kHz sine wave to the CMSIS fixed\_point version of the preprocessor + * **This test should be compiled with the -O0 option.** Otherwise, the breakpoints will not be reached + * In tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc change "-O3" to "-O0" on line 47 + * **DO NOT FORGET TO REVERT CHANGE AFTER EXPERIMENT** + * In future, enhance scripts to handle automatically, NOT manually! + * Clean project by running "make -f tensorflow/lite/experimental/micro/tools/make/Makefile clean" + * Compile BIN by running "make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=apollo3evb preprocessor_1k_cmsis_test_bin" + * Run with the preprocessor\_1k\_cmsis\_test.cmd GDB command file + * Produces four text files corresponding to outputs from the CMSIS fixed\_point version of this algorithm: + * cmsis_windowed_input.txt: the sinusoid after multiplying elementwise with a Hann window + * cmsis_dft.txt: the DFT of the windowed sinusoid + * cmsis_power.txt: the magnitude squared of the DFT + * cmsis_power_avg.txt: the 6-bin average of the magnitude squared of the DFT + * Run both verisons of the 1KHz pre-processor test and then compare. + * These files can be plotted with "python compare\_1k.py" + * Also prints out the number of cycles the code took to execute (using the DWT->CYCCNT register) +* **preprocessor_1k_micro_test_bin** + * Sends a 1 kHz sine wave to the Micro-Lite fixed\_point version of the preprocessor + * **This test should be compiled with the -O0 option.** Otherwise, the breakpoints will not be reached + * Run with the preprocessor\_1k\_micro\_test.cmd GDB command file + * Produces four text files corresponding to outputs from the Micro-Lite version of this algorithm: + * micro_windowed_input.txt: the sinusoid after multiplying elementwise with a Hann window + * micro_dft.txt: the DFT of the windowed sinusoid + * micro_power.txt: the magnitude squared of the DFT + * micro_power_avg.txt: the 6-bin average of the magnitude squared of the DFT + * Run both verisons of the 1KHz pre-processor test and then compare. + * These files can be plotted with "python compare\_1k.py" + * Also prints out the number of cycles the code took to execute (using the DWT->CYCCNT register) + +# Description of files + +* **.gitignore**: Git should ignore \*.txt and \*.wav files that result from experiments run in this directory +* **apollo3.h**: Apollo 3 version of the [CMSIS Device Header File (device.h)](https://www.keil.com/pack/doc/CMSIS/Core/html/device_h_pg.html). Available in the [Ambiq Keil Pack](http://s3.ambiqmicro.com/pack/AmbiqMicro.Apollo_DFP.1.1.0.pack). +* **captured\_data\_to\_wav.py**: Python script that parses a text file containing data dumped from GDB (specifically the verilog format) and creates a \*.wav file using [PySoundFile](https://pysoundfile.readthedocs.io/en/0.9.0/). +* **compare\_1k.py**: This script compares the intermediate variables and final outputs of the micro-lite fixed-point preprocessor function and the CMSIS version of this function. The stimulus provided to each preprocessor is the same: a 1 kHz sinusoid. +* **get\_yesno\_data.cmd**: A GDB command file that runs preprocessor_test (where TARGET=apollo3evb) and dumps the calculated data for the "yes" and "no" input wavfeorms to text files +* **\_main.c**: Point of entry for the micro_speech test +* **preprocessor_1k.cc**: A version of preprocessor.cc where a 1 kHz sinusoid is provided as input to the preprocessor +* **preprocessor_1k_cmsis_test.cmd**: GDB command file for the CMSIS preprocessor 1 kHz test +* **preprocessor_1k_micro_test.cmd**: GDB command file for the Micro-Lite preprocessor 1 kHz test +* **preprocessor_test.cmd**: GDB command file for the preprocessor test +* **pushbutton_cmsis_scores.cmd**: GDB command file that runs pushbutton_cmsis_speech_test_bin. It adds a breakpoint immediately after the scores are reported and prints out each score. Then it continues code execution. +* **pushbutton_cmsis_voice.cmd**: GDB command file that runs pushbutton_cmsis_speech_test_bin. Dumps the recorded 1 second of audio to captured_data.txt, which can then be processed by the python file captured_data_to_wav.py. +* **pushbutton_main.c**: Source file containing program point of entry \_main() for the pushbutton\_\* tests. Contains Interrupt Service Routines for PDM data capture and pushbuttons. Calls the main() function of pushbutton_test.cc +* **pushbutton_test.cc**: Source file containing main() function for the pushbutton\_\* tests. main() calls the preprocessor function and the neural net inference function. +* **system_apollo3.c**: Apollo 3 version of the [CMSIS System Configuration File system\_\.c](https://www.keil.com/pack/doc/CMSIS/Core/html/system_c_pg.html). Available in the [Ambiq Keil Pack](http://s3.ambiqmicro.com/pack/AmbiqMicro.Apollo_DFP.1.1.0.pack). +* **system_apollo3.h**: Apollo 3 version of the [CMSIS System Configuration File system\_\.h](https://www.keil.com/pack/doc/CMSIS/Core/html/system_c_pg.html). Available in the [Ambiq Keil Pack](http://s3.ambiqmicro.com/pack/AmbiqMicro.Apollo_DFP.1.1.0.pack). + + +# FFT scaling +See https://github.com/ARM-software/CMSIS_5/issues/220 +>And as @xizhizhang pointed, I think there may be an error on the internal downscaling, or at least on the documentation. It looks like during the fft computation, the downscaling factor reach 2**-9 for a 512 rfft operation, being the output in Q10.22, instead the documented 2**-8 and Q9.23. diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/_main.c b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/_main.c similarity index 100% rename from tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/_main.c rename to tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/_main.c diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h new file mode 100755 index 0000000000..af22270e32 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h @@ -0,0 +1,23332 @@ +/* + * Copyright (C) 2015-2017, Ambiq Micro + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of itscontributors may be used to endorse + * or promote products derived from thissoftware without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file apollo3.h + * @brief CMSIS HeaderFile + * @version 1.0 + * @date 10. August 2018 + * @note Generated by SVDConv V3.3.18 on Friday, 10.08.2018 16:52:09 + * from File 'apollo3.svd', + * last modified on Friday, 10.08.2018 20:01:31 + */ + + + +/** @addtogroup Ambiq Micro + * @{ + */ + + +/** @addtogroup apollo3 + * @{ + */ + + +#ifndef APOLLO3_H +#define APOLLO3_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @addtogroup Configuration_of_CMSIS + * @{ + */ + + + +/* =========================================================================================================================== */ +/* ================ Interrupt Number Definition ================ */ +/* =========================================================================================================================== */ + +typedef enum { +/* ======================================= ARM Cortex-M4 Specific Interrupt Numbers ======================================== */ + Reset_IRQn = -15, /*!< -15 Reset Vector, invoked on Power up and warm reset */ + NonMaskableInt_IRQn = -14, /*!< -14 Non maskable Interrupt, cannot be stopped or preempted */ + HardFault_IRQn = -13, /*!< -13 Hard Fault, all classes of Fault */ + MemoryManagement_IRQn = -12, /*!< -12 Memory Management, MPU mismatch, including Access Violation + and No Match */ + BusFault_IRQn = -11, /*!< -11 Bus Fault, Pre-Fetch-, Memory Access Fault, other address/memory + related Fault */ + UsageFault_IRQn = -10, /*!< -10 Usage Fault, i.e. Undef Instruction, Illegal State Transition */ + SVCall_IRQn = -5, /*!< -5 System Service Call via SVC instruction */ + DebugMonitor_IRQn = -4, /*!< -4 Debug Monitor */ + PendSV_IRQn = -2, /*!< -2 Pendable request for system service */ + SysTick_IRQn = -1, /*!< -1 System Tick Timer */ +/* ========================================== apollo3 Specific Interrupt Numbers =========================================== */ + BROWNOUT_IRQn = 0, /*!< 0 BROWNOUT */ + WDT_IRQn = 1, /*!< 1 WDT */ + RTC_IRQn = 2, /*!< 2 RTC */ + VCOMP_IRQn = 3, /*!< 3 VCOMP */ + IOSLAVE_IRQn = 4, /*!< 4 IOSLAVE */ + IOSLAVEACC_IRQn = 5, /*!< 5 IOSLAVEACC */ + IOMSTR0_IRQn = 6, /*!< 6 IOMSTR0 */ + IOMSTR1_IRQn = 7, /*!< 7 IOMSTR1 */ + IOMSTR2_IRQn = 8, /*!< 8 IOMSTR2 */ + IOMSTR3_IRQn = 9, /*!< 9 IOMSTR3 */ + IOMSTR4_IRQn = 10, /*!< 10 IOMSTR4 */ + IOMSTR5_IRQn = 11, /*!< 11 IOMSTR5 */ + BLE_IRQn = 12, /*!< 12 BLE */ + GPIO_IRQn = 13, /*!< 13 GPIO */ + CTIMER_IRQn = 14, /*!< 14 CTIMER */ + UART0_IRQn = 15, /*!< 15 UART0 */ + UART1_IRQn = 16, /*!< 16 UART1 */ + SCARD_IRQn = 17, /*!< 17 SCARD */ + ADC_IRQn = 18, /*!< 18 ADC */ + PDM_IRQn = 19, /*!< 19 PDM */ + MSPI_IRQn = 20, /*!< 20 MSPI */ + STIMER_IRQn = 22, /*!< 22 STIMER */ + STIMER_CMPR0_IRQn = 23, /*!< 23 STIMER_CMPR0 */ + STIMER_CMPR1_IRQn = 24, /*!< 24 STIMER_CMPR1 */ + STIMER_CMPR2_IRQn = 25, /*!< 25 STIMER_CMPR2 */ + STIMER_CMPR3_IRQn = 26, /*!< 26 STIMER_CMPR3 */ + STIMER_CMPR4_IRQn = 27, /*!< 27 STIMER_CMPR4 */ + STIMER_CMPR5_IRQn = 28, /*!< 28 STIMER_CMPR5 */ + STIMER_CMPR6_IRQn = 29, /*!< 29 STIMER_CMPR6 */ + STIMER_CMPR7_IRQn = 30, /*!< 30 STIMER_CMPR7 */ + CLKGEN_IRQn = 31 /*!< 31 CLKGEN */ +} IRQn_Type; + + + +/* =========================================================================================================================== */ +/* ================ Processor and Core Peripheral Section ================ */ +/* =========================================================================================================================== */ + +/* =========================== Configuration of the ARM Cortex-M4 Processor and Core Peripherals =========================== */ +#define __CM4_REV 0x0100U /*!< CM4 Core Revision */ +#define __NVIC_PRIO_BITS 3 /*!< Number of Bits used for Priority Levels */ +#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ +#define __MPU_PRESENT 1 /*!< MPU present or not */ +#define __FPU_PRESENT 1 /*!< FPU present or not */ + + +/** @} */ /* End of group Configuration_of_CMSIS */ + +#include "core_cm4.h" /*!< ARM Cortex-M4 processor and core peripherals */ +#include "system_apollo3.h" /*!< apollo3 System */ + +#ifndef __IM /*!< Fallback for older CMSIS versions */ + #define __IM __I +#endif +#ifndef __OM /*!< Fallback for older CMSIS versions */ + #define __OM __O +#endif +#ifndef __IOM /*!< Fallback for older CMSIS versions */ + #define __IOM __IO +#endif + + +/* ======================================== Start of section using anonymous unions ======================================== */ +#if defined (__CC_ARM) + #pragma push + #pragma anon_unions +#elif defined (__ICCARM__) + #pragma language=extended +#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wc11-extensions" + #pragma clang diagnostic ignored "-Wreserved-id-macro" + #pragma clang diagnostic ignored "-Wgnu-anonymous-struct" + #pragma clang diagnostic ignored "-Wnested-anon-types" +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning 586 +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#else + #warning Not supported compiler type +#endif + + +/* =========================================================================================================================== */ +/* ================ Device Specific Peripheral Section ================ */ +/* =========================================================================================================================== */ + + +/** @addtogroup Device_Peripheral_peripherals + * @{ + */ + + + +/* =========================================================================================================================== */ +/* ================ ADC ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Analog Digital Converter Control (ADC) + */ + +typedef struct { /*!< (@ 0x50010000) ADC Structure */ + + union { + __IOM uint32_t CFG; /*!< (@ 0x00000000) Configuration Register */ + + struct { + __IOM uint32_t ADCEN : 1; /*!< [0..0] This bit enables the ADC module. While the ADC is enabled, + the ADCCFG and SLOT Configuration regsiter settings must + remain stable and unchanged. All configuration register + settings, slot configuration settings and window comparison + settings should be written prior to setting the ADCEN bit + to '1'. */ + __IM uint32_t : 1; + __IOM uint32_t RPTEN : 1; /*!< [2..2] This bit enables Repeating Scan Mode. */ + __IOM uint32_t LPMODE : 1; /*!< [3..3] Select power mode to enter between active scans. */ + __IOM uint32_t CKMODE : 1; /*!< [4..4] Clock mode register */ + __IM uint32_t : 3; + __IOM uint32_t REFSEL : 2; /*!< [9..8] Select the ADC reference voltage. */ + __IM uint32_t : 2; + __IOM uint32_t DFIFORDEN : 1; /*!< [12..12] Destructive FIFO Read Enable. Setting this will enable + FIFO pop upon reading the FIFOPR register. */ + __IM uint32_t : 3; + __IOM uint32_t TRIGSEL : 3; /*!< [18..16] Select the ADC trigger source. */ + __IOM uint32_t TRIGPOL : 1; /*!< [19..19] This bit selects the ADC trigger polarity for external + off chip triggers. */ + __IM uint32_t : 4; + __IOM uint32_t CLKSEL : 2; /*!< [25..24] Select the source and frequency for the ADC clock. + All values not enumerated below are undefined. */ + } CFG_b; + } ; + + union { + __IOM uint32_t STAT; /*!< (@ 0x00000004) ADC Power Status */ + + struct { + __IOM uint32_t PWDSTAT : 1; /*!< [0..0] Indicates the power-status of the ADC. */ + } STAT_b; + } ; + + union { + __IOM uint32_t SWT; /*!< (@ 0x00000008) Software trigger */ + + struct { + __IOM uint32_t SWT : 8; /*!< [7..0] Writing 0x37 to this register generates a software trigger. */ + } SWT_b; + } ; + + union { + __IOM uint32_t SL0CFG; /*!< (@ 0x0000000C) Slot 0 Configuration Register */ + + struct { + __IOM uint32_t SLEN0 : 1; /*!< [0..0] This bit enables slot 0 for ADC conversions. */ + __IOM uint32_t WCEN0 : 1; /*!< [1..1] This bit enables the window compare function for slot + 0. */ + __IM uint32_t : 6; + __IOM uint32_t CHSEL0 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ + __IM uint32_t : 4; + __IOM uint32_t PRMODE0 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ + __IM uint32_t : 6; + __IOM uint32_t ADSEL0 : 3; /*!< [26..24] Select the number of measurements to average in the + accumulate divide module for this slot. */ + } SL0CFG_b; + } ; + + union { + __IOM uint32_t SL1CFG; /*!< (@ 0x00000010) Slot 1 Configuration Register */ + + struct { + __IOM uint32_t SLEN1 : 1; /*!< [0..0] This bit enables slot 1 for ADC conversions. */ + __IOM uint32_t WCEN1 : 1; /*!< [1..1] This bit enables the window compare function for slot + 1. */ + __IM uint32_t : 6; + __IOM uint32_t CHSEL1 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ + __IM uint32_t : 4; + __IOM uint32_t PRMODE1 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ + __IM uint32_t : 6; + __IOM uint32_t ADSEL1 : 3; /*!< [26..24] Select the number of measurements to average in the + accumulate divide module for this slot. */ + } SL1CFG_b; + } ; + + union { + __IOM uint32_t SL2CFG; /*!< (@ 0x00000014) Slot 2 Configuration Register */ + + struct { + __IOM uint32_t SLEN2 : 1; /*!< [0..0] This bit enables slot 2 for ADC conversions. */ + __IOM uint32_t WCEN2 : 1; /*!< [1..1] This bit enables the window compare function for slot + 2. */ + __IM uint32_t : 6; + __IOM uint32_t CHSEL2 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ + __IM uint32_t : 4; + __IOM uint32_t PRMODE2 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ + __IM uint32_t : 6; + __IOM uint32_t ADSEL2 : 3; /*!< [26..24] Select the number of measurements to average in the + accumulate divide module for this slot. */ + } SL2CFG_b; + } ; + + union { + __IOM uint32_t SL3CFG; /*!< (@ 0x00000018) Slot 3 Configuration Register */ + + struct { + __IOM uint32_t SLEN3 : 1; /*!< [0..0] This bit enables slot 3 for ADC conversions. */ + __IOM uint32_t WCEN3 : 1; /*!< [1..1] This bit enables the window compare function for slot + 3. */ + __IM uint32_t : 6; + __IOM uint32_t CHSEL3 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ + __IM uint32_t : 4; + __IOM uint32_t PRMODE3 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ + __IM uint32_t : 6; + __IOM uint32_t ADSEL3 : 3; /*!< [26..24] Select the number of measurements to average in the + accumulate divide module for this slot. */ + } SL3CFG_b; + } ; + + union { + __IOM uint32_t SL4CFG; /*!< (@ 0x0000001C) Slot 4 Configuration Register */ + + struct { + __IOM uint32_t SLEN4 : 1; /*!< [0..0] This bit enables slot 4 for ADC conversions. */ + __IOM uint32_t WCEN4 : 1; /*!< [1..1] This bit enables the window compare function for slot + 4. */ + __IM uint32_t : 6; + __IOM uint32_t CHSEL4 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ + __IM uint32_t : 4; + __IOM uint32_t PRMODE4 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ + __IM uint32_t : 6; + __IOM uint32_t ADSEL4 : 3; /*!< [26..24] Select the number of measurements to average in the + accumulate divide module for this slot. */ + } SL4CFG_b; + } ; + + union { + __IOM uint32_t SL5CFG; /*!< (@ 0x00000020) Slot 5 Configuration Register */ + + struct { + __IOM uint32_t SLEN5 : 1; /*!< [0..0] This bit enables slot 5 for ADC conversions. */ + __IOM uint32_t WCEN5 : 1; /*!< [1..1] This bit enables the window compare function for slot + 5. */ + __IM uint32_t : 6; + __IOM uint32_t CHSEL5 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ + __IM uint32_t : 4; + __IOM uint32_t PRMODE5 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ + __IM uint32_t : 6; + __IOM uint32_t ADSEL5 : 3; /*!< [26..24] Select number of measurements to average in the accumulate + divide module for this slot. */ + } SL5CFG_b; + } ; + + union { + __IOM uint32_t SL6CFG; /*!< (@ 0x00000024) Slot 6 Configuration Register */ + + struct { + __IOM uint32_t SLEN6 : 1; /*!< [0..0] This bit enables slot 6 for ADC conversions. */ + __IOM uint32_t WCEN6 : 1; /*!< [1..1] This bit enables the window compare function for slot + 6. */ + __IM uint32_t : 6; + __IOM uint32_t CHSEL6 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ + __IM uint32_t : 4; + __IOM uint32_t PRMODE6 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ + __IM uint32_t : 6; + __IOM uint32_t ADSEL6 : 3; /*!< [26..24] Select the number of measurements to average in the + accumulate divide module for this slot. */ + } SL6CFG_b; + } ; + + union { + __IOM uint32_t SL7CFG; /*!< (@ 0x00000028) Slot 7 Configuration Register */ + + struct { + __IOM uint32_t SLEN7 : 1; /*!< [0..0] This bit enables slot 7 for ADC conversions. */ + __IOM uint32_t WCEN7 : 1; /*!< [1..1] This bit enables the window compare function for slot + 7. */ + __IM uint32_t : 6; + __IOM uint32_t CHSEL7 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ + __IM uint32_t : 4; + __IOM uint32_t PRMODE7 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ + __IM uint32_t : 6; + __IOM uint32_t ADSEL7 : 3; /*!< [26..24] Select the number of measurements to average in the + accumulate divide module for this slot. */ + } SL7CFG_b; + } ; + + union { + __IOM uint32_t WULIM; /*!< (@ 0x0000002C) Window Comparator Upper Limits Register */ + + struct { + __IOM uint32_t ULIM : 20; /*!< [19..0] Sets the upper limit for the window comparator. */ + } WULIM_b; + } ; + + union { + __IOM uint32_t WLLIM; /*!< (@ 0x00000030) Window Comparator Lower Limits Register */ + + struct { + __IOM uint32_t LLIM : 20; /*!< [19..0] Sets the lower limit for the window comparator. */ + } WLLIM_b; + } ; + + union { + __IOM uint32_t SCWLIM; /*!< (@ 0x00000034) Scale Window Comparator Limits */ + + struct { + __IOM uint32_t SCWLIMEN : 1; /*!< [0..0] Scale the window limits compare values per precision + mode. When set to 0x0 (default), the values in the 20-bit + limits registers will compare directly with the FIFO values + regardless of the precision mode the slot is configured + to. When set to 0x1, the compare values will be divided + by the difference in precision bits while performing the + window limit comparisons. */ + } SCWLIM_b; + } ; + + union { + __IOM uint32_t FIFO; /*!< (@ 0x00000038) FIFO Data and Valid Count Register */ + + struct { + __IOM uint32_t DATA : 20; /*!< [19..0] Oldest data in the FIFO. */ + __IOM uint32_t COUNT : 8; /*!< [27..20] Number of valid entries in the ADC FIFO. */ + __IOM uint32_t SLOTNUM : 3; /*!< [30..28] Slot number associated with this FIFO data. */ + __IOM uint32_t RSVD : 1; /*!< [31..31] RESERVED. */ + } FIFO_b; + } ; + + union { + __IOM uint32_t FIFOPR; /*!< (@ 0x0000003C) FIFO Data and Valid Count Register */ + + struct { + __IOM uint32_t DATA : 20; /*!< [19..0] Oldest data in the FIFO. */ + __IOM uint32_t COUNT : 8; /*!< [27..20] Number of valid entries in the ADC FIFO. */ + __IOM uint32_t SLOTNUMPR : 3; /*!< [30..28] Slot number associated with this FIFO data. */ + __IOM uint32_t RSVDPR : 1; /*!< [31..31] RESERVED. */ + } FIFOPR_b; + } ; + __IM uint32_t RESERVED[112]; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000200) ADC Interrupt registers: Enable */ + + struct { + __IOM uint32_t CNVCMP : 1; /*!< [0..0] ADC conversion complete interrupt. */ + __IOM uint32_t SCNCMP : 1; /*!< [1..1] ADC scan complete interrupt. */ + __IOM uint32_t FIFOOVR1 : 1; /*!< [2..2] FIFO 75 percent full interrupt. */ + __IOM uint32_t FIFOOVR2 : 1; /*!< [3..3] FIFO 100 percent full interrupt. */ + __IOM uint32_t WCEXC : 1; /*!< [4..4] Window comparator voltage excursion interrupt. */ + __IOM uint32_t WCINC : 1; /*!< [5..5] Window comparator voltage incursion interrupt. */ + __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Transfer Complete */ + __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Condition */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) ADC Interrupt registers: Status */ + + struct { + __IOM uint32_t CNVCMP : 1; /*!< [0..0] ADC conversion complete interrupt. */ + __IOM uint32_t SCNCMP : 1; /*!< [1..1] ADC scan complete interrupt. */ + __IOM uint32_t FIFOOVR1 : 1; /*!< [2..2] FIFO 75 percent full interrupt. */ + __IOM uint32_t FIFOOVR2 : 1; /*!< [3..3] FIFO 100 percent full interrupt. */ + __IOM uint32_t WCEXC : 1; /*!< [4..4] Window comparator voltage excursion interrupt. */ + __IOM uint32_t WCINC : 1; /*!< [5..5] Window comparator voltage incursion interrupt. */ + __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Transfer Complete */ + __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Condition */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000208) ADC Interrupt registers: Clear */ + + struct { + __IOM uint32_t CNVCMP : 1; /*!< [0..0] ADC conversion complete interrupt. */ + __IOM uint32_t SCNCMP : 1; /*!< [1..1] ADC scan complete interrupt. */ + __IOM uint32_t FIFOOVR1 : 1; /*!< [2..2] FIFO 75 percent full interrupt. */ + __IOM uint32_t FIFOOVR2 : 1; /*!< [3..3] FIFO 100 percent full interrupt. */ + __IOM uint32_t WCEXC : 1; /*!< [4..4] Window comparator voltage excursion interrupt. */ + __IOM uint32_t WCINC : 1; /*!< [5..5] Window comparator voltage incursion interrupt. */ + __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Transfer Complete */ + __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Condition */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000020C) ADC Interrupt registers: Set */ + + struct { + __IOM uint32_t CNVCMP : 1; /*!< [0..0] ADC conversion complete interrupt. */ + __IOM uint32_t SCNCMP : 1; /*!< [1..1] ADC scan complete interrupt. */ + __IOM uint32_t FIFOOVR1 : 1; /*!< [2..2] FIFO 75 percent full interrupt. */ + __IOM uint32_t FIFOOVR2 : 1; /*!< [3..3] FIFO 100 percent full interrupt. */ + __IOM uint32_t WCEXC : 1; /*!< [4..4] Window comparator voltage excursion interrupt. */ + __IOM uint32_t WCINC : 1; /*!< [5..5] Window comparator voltage incursion interrupt. */ + __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Transfer Complete */ + __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Condition */ + } INTSET_b; + } ; + __IM uint32_t RESERVED1[12]; + + union { + __IOM uint32_t DMATRIGEN; /*!< (@ 0x00000240) DMA Trigger Enable Register */ + + struct { + __IOM uint32_t DFIFO75 : 1; /*!< [0..0] Trigger DMA upon FIFO 75 percent Full */ + __IOM uint32_t DFIFOFULL : 1; /*!< [1..1] Trigger DMA upon FIFO 100 percent Full */ + } DMATRIGEN_b; + } ; + + union { + __IOM uint32_t DMATRIGSTAT; /*!< (@ 0x00000244) DMA Trigger Status Register */ + + struct { + __IOM uint32_t D75STAT : 1; /*!< [0..0] Triggered DMA from FIFO 75 percent Full */ + __IOM uint32_t DFULLSTAT : 1; /*!< [1..1] Triggered DMA from FIFO 100 percent Full */ + } DMATRIGSTAT_b; + } ; + __IM uint32_t RESERVED2[14]; + + union { + __IOM uint32_t DMACFG; /*!< (@ 0x00000280) DMA Configuration Register */ + + struct { + __IOM uint32_t DMAEN : 1; /*!< [0..0] DMA Enable */ + __IM uint32_t : 1; + __IOM uint32_t DMADIR : 1; /*!< [2..2] Direction */ + __IM uint32_t : 5; + __IOM uint32_t DMAPRI : 1; /*!< [8..8] Sets the Priority of the DMA request */ + __IOM uint32_t DMADYNPRI : 1; /*!< [9..9] Enables dynamic priority based on FIFO fullness. When + FIFO is full, priority is automatically set to HIGH. Otherwise, + DMAPRI is used. */ + __IM uint32_t : 6; + __IOM uint32_t DMAHONSTAT : 1; /*!< [16..16] Halt New ADC conversions until DMA Status DMAERR and + DMACPL Cleared. */ + __IOM uint32_t DMAMSK : 1; /*!< [17..17] Mask the FIFOCNT and SLOTNUM when transferring FIFO + contents to memory */ + __IOM uint32_t DPWROFF : 1; /*!< [18..18] Power Off the ADC System upon DMACPL. */ + } DMACFG_b; + } ; + __IM uint32_t RESERVED3; + + union { + __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x00000288) DMA Total Transfer Count */ + + struct { + __IM uint32_t : 2; + __IOM uint32_t TOTCOUNT : 16; /*!< [17..2] Total Transfer Count */ + } DMATOTCOUNT_b; + } ; + + union { + __IOM uint32_t DMATARGADDR; /*!< (@ 0x0000028C) DMA Target Address Register */ + + struct { + __IOM uint32_t LTARGADDR : 19; /*!< [18..0] DMA Target Address */ + __IOM uint32_t UTARGADDR : 13; /*!< [31..19] SRAM Target */ + } DMATARGADDR_b; + } ; + + union { + __IOM uint32_t DMASTAT; /*!< (@ 0x00000290) DMA Status Register */ + + struct { + __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress */ + __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete */ + __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error */ + } DMASTAT_b; + } ; +} ADC_Type; /*!< Size = 660 (0x294) */ + + + +/* =========================================================================================================================== */ +/* ================ APBDMA ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief APB DMA Register Interfaces (APBDMA) + */ + +typedef struct { /*!< (@ 0x40011000) APBDMA Structure */ + + union { + __IOM uint32_t BBVALUE; /*!< (@ 0x00000000) Control Register */ + + struct { + __IOM uint32_t DATAOUT : 8; /*!< [7..0] Data Output Values */ + __IM uint32_t : 8; + __IOM uint32_t PIN : 8; /*!< [23..16] PIO values */ + } BBVALUE_b; + } ; + + union { + __IOM uint32_t BBSETCLEAR; /*!< (@ 0x00000004) Set/Clear Register */ + + struct { + __IOM uint32_t SET : 8; /*!< [7..0] Write 1 to Set PIO value (set hier priority than clear + if both bit set) */ + __IM uint32_t : 8; + __IOM uint32_t CLEAR : 8; /*!< [23..16] Write 1 to Clear PIO value */ + } BBSETCLEAR_b; + } ; + + union { + __IOM uint32_t BBINPUT; /*!< (@ 0x00000008) PIO Input Values */ + + struct { + __IOM uint32_t DATAIN : 8; /*!< [7..0] PIO values */ + } BBINPUT_b; + } ; + __IM uint32_t RESERVED[5]; + + union { + __IOM uint32_t DEBUGDATA; /*!< (@ 0x00000020) PIO Input Values */ + + struct { + __IOM uint32_t DEBUGDATA : 32; /*!< [31..0] Debug Data */ + } DEBUGDATA_b; + } ; + __IM uint32_t RESERVED1[7]; + + union { + __IOM uint32_t DEBUG; /*!< (@ 0x00000040) PIO Input Values */ + + struct { + __IOM uint32_t DEBUGEN : 4; /*!< [3..0] Debug Enable */ + } DEBUG_b; + } ; +} APBDMA_Type; /*!< Size = 68 (0x44) */ + + + +/* =========================================================================================================================== */ +/* ================ BLEIF ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief BLE Interface (BLEIF) + */ + +typedef struct { /*!< (@ 0x5000C000) BLEIF Structure */ + + union { + __IOM uint32_t FIFO; /*!< (@ 0x00000000) FIFO Access Port */ + + struct { + __IOM uint32_t FIFO : 32; /*!< [31..0] FIFO direct access. Only locations 0 - 3F will return + valid information. */ + } FIFO_b; + } ; + __IM uint32_t RESERVED[63]; + + union { + __IOM uint32_t FIFOPTR; /*!< (@ 0x00000100) FIFO size and remaining slots open values */ + + struct { + __IOM uint32_t FIFO0SIZ : 8; /*!< [7..0] The number of valid data bytes currently in the FIFO + 0 (written by MCU, read by interface) */ + __IOM uint32_t FIFO0REM : 8; /*!< [15..8] The number of remaining data bytes slots currently in + FIFO 0 (written by MCU, read by interface) */ + __IOM uint32_t FIFO1SIZ : 8; /*!< [23..16] The number of valid data bytes currently in FIFO 1 + (written by interface, read by MCU) */ + __IOM uint32_t FIFO1REM : 8; /*!< [31..24] The number of remaining data bytes slots currently + in FIFO 1 (written by interface, read by MCU) */ + } FIFOPTR_b; + } ; + + union { + __IOM uint32_t FIFOTHR; /*!< (@ 0x00000104) FIFO Threshold Configuration */ + + struct { + __IOM uint32_t FIFORTHR : 6; /*!< [5..0] FIFO read threshold in bytes. A value of 0 will disable + the read FIFO level from activating the threshold interrupt. + If this field is non-zero, it will trigger a threshold + interrupt when the read fifo contains FIFORTHR valid bytes + of data, as indicated by the FIFO1SIZ field. This is intended + to signal when a data transfer of FIFORTHR bytes can be + done from the IOM module to the host via the read fifo + to support large IOM read operations. */ + __IM uint32_t : 2; + __IOM uint32_t FIFOWTHR : 6; /*!< [13..8] FIFO write threshold in bytes. A value of 0 will disable + the write FIFO level from activating the threshold interrupt. + If this field is non-zero, it will trigger a threshold + interrupt when the write fifo contains FIFOWTHR free bytes, + as indicated by the FIFO0REM field. This is intended to + signal when a transfer of FIFOWTHR bytes can be done from + the host to the IOM write fifo to support large IOM write + operations. */ + } FIFOTHR_b; + } ; + + union { + __IOM uint32_t FIFOPOP; /*!< (@ 0x00000108) FIFO POP register */ + + struct { + __IOM uint32_t FIFODOUT : 32; /*!< [31..0] This register will return the read data indicated by + the current read pointer on reads. If the POPWR control + bit in the FIFOCTRL register is reset (0), the fifo read + pointer will be advanced by one word as a result of the + read.If the POPWR bit is set (1), the fifo read pointer + will only be advanced after a write operation to this register. + The write data is ignored for this register.If less than + a even word multiple is available, and the command is completed, + the module will return the word containing */ + } FIFOPOP_b; + } ; + + union { + __IOM uint32_t FIFOPUSH; /*!< (@ 0x0000010C) FIFO PUSH register */ + + struct { + __IOM uint32_t FIFODIN : 32; /*!< [31..0] This register is used to write the FIFORAM in FIFO mode + and will cause a push event to occur to the next open slot + within the FIFORAM. Writing to this register will cause + the write point to increment by 1 word(4 bytes). */ + } FIFOPUSH_b; + } ; + + union { + __IOM uint32_t FIFOCTRL; /*!< (@ 0x00000110) FIFO Control Register */ + + struct { + __IOM uint32_t POPWR : 1; /*!< [0..0] Selects the mode in which 'pop' events are done for the + fifo read operations. A value of '1' will prevent a pop + event on a read operation, and will require a write to + the FIFOPOP register to create a pop event.A value of '0' + in this register will allow a pop event to occur on the + read of the FIFOPOP register, and may cause inadvertant + fifo pops when used in a debugging mode. */ + __IOM uint32_t FIFORSTN : 1; /*!< [1..1] Active low manual reset of the fifo. Write to 0 to reset + fifo, and then write to 1 to remove the reset. */ + } FIFOCTRL_b; + } ; + + union { + __IOM uint32_t FIFOLOC; /*!< (@ 0x00000114) FIFO Pointers */ + + struct { + __IOM uint32_t FIFOWPTR : 4; /*!< [3..0] Current FIFO write pointer. Value is the index into the + outgoing FIFO (FIFO0), which is used during write operations + to external devices. */ + __IM uint32_t : 4; + __IOM uint32_t FIFORPTR : 4; /*!< [11..8] Current FIFO read pointer. Used to index into the incoming + FIFO (FIFO1), which is used to store read data returned + from external devices during a read operation. */ + } FIFOLOC_b; + } ; + __IM uint32_t RESERVED1[58]; + + union { + __IOM uint32_t CLKCFG; /*!< (@ 0x00000200) I/O Clock Configuration */ + + struct { + __IOM uint32_t IOCLKEN : 1; /*!< [0..0] Enable for the interface clock. Must be enabled prior + to executing any IO operations. */ + __IM uint32_t : 7; + __IOM uint32_t FSEL : 3; /*!< [10..8] Select the input clock frequency. */ + __IOM uint32_t CLK32KEN : 1; /*!< [11..11] Enable for the 32Khz clock to the BLE module */ + __IOM uint32_t DIV3 : 1; /*!< [12..12] Enable of the divide by 3 of the source IOCLK. */ + } CLKCFG_b; + } ; + __IM uint32_t RESERVED2[2]; + + union { + __IOM uint32_t CMD; /*!< (@ 0x0000020C) Command and offset Register */ + + struct { + __IOM uint32_t CMD : 5; /*!< [4..0] Command for submodule. */ + __IOM uint32_t OFFSETCNT : 2; /*!< [6..5] Number of offset bytes to use for the command - 0, 1, + 2, 3 are valid selections. The second (byte 1) and third + byte (byte 2) are read from the OFFSETHI register, and + the low order byte is pulled from this register in the + OFFSETLO field.Offset bytes are transmitted highest byte + first. EG if offsetcnt == 3, OFFSETHI[15:8] will be transmitted + first, then OFFSETHI[7:0] then OFFSETLO.If offsetcnt == + 2, OFFSETHI[7:0] will be transmitted, then OFFSETLO.If + offsetcnt == 1, only OFFSETLO will be transmitted. */ + __IOM uint32_t CONT : 1; /*!< [7..7] Contine to hold the bus after the current transaction + if set to a 1 with a new command issued. */ + __IOM uint32_t TSIZE : 12; /*!< [19..8] Defines the transaction size in bytes. The offset transfer + is not included in this size. */ + __IOM uint32_t CMDSEL : 2; /*!< [21..20] Command Specific selection information */ + __IM uint32_t : 2; + __IOM uint32_t OFFSETLO : 8; /*!< [31..24] This register holds the low order byte of offset to + be used in the transaction. The number of offset bytes + to use is set with bits 1:0 of the command. Offset bytes + are transferred starting from the highest byte first. */ + } CMD_b; + } ; + + union { + __IOM uint32_t CMDRPT; /*!< (@ 0x00000210) Command Repeat Register */ + + struct { + __IOM uint32_t CMDRPT : 5; /*!< [4..0] Count of number of times to repeat the next command. */ + } CMDRPT_b; + } ; + + union { + __IOM uint32_t OFFSETHI; /*!< (@ 0x00000214) High order offset bytes */ + + struct { + __IOM uint32_t OFFSETHI : 16; /*!< [15..0] Holds the high order bytes of the 2 or 3 byte offset + phase of a transaction. */ + } OFFSETHI_b; + } ; + + union { + __IOM uint32_t CMDSTAT; /*!< (@ 0x00000218) Command status */ + + struct { + __IOM uint32_t CCMD : 5; /*!< [4..0] current command that is being executed */ + __IOM uint32_t CMDSTAT : 3; /*!< [7..5] The current status of the command execution. */ + __IOM uint32_t CTSIZE : 12; /*!< [19..8] The current number of bytes still to be transferred + with this command. This field will count down to zero. */ + } CMDSTAT_b; + } ; + __IM uint32_t RESERVED3; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000220) IO Master Interrupts: Enable */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current + operation has completed. For repeated commands, this will + only be asserted when the final repeated command is completed. */ + __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted + when the number of free bytes in the write FIFO equals + or exceeds the WTHR field.For read operations, asserted + when the number of valid bytes in the read FIFO equals + of exceeds the value set in the RTHR field. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. Asserted when a pop operation + is done to a empty read FIFO. */ + __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software + tries to write to a full fifo. The current operation does + not stop. */ + __IOM uint32_t B2MST : 1; /*!< [4..4] B2M State change interrupt. Asserted on any change in + the B2M_STATE signal from the BLE Core. */ + __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is + a overflow or underflow event */ + __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is + written when an active command is in progress. */ + __IOM uint32_t BLECIRQ : 1; /*!< [7..7] BLE Core IRQ signal. Asserted when the BLE_IRQ signal + from the BLE Core is asserted, indicating the availability + of read data from the BLE Core. */ + __IOM uint32_t BLECSSTAT : 1; /*!< [8..8] BLE Core SPI Status interrupt. Asserted when the SPI_STATUS + signal from the BLE Core is asserted, indicating that SPI + writes can be done to the BLE Core.Transfers to the BLE + Core should only be done when this signal is high. */ + __IOM uint32_t DCMP : 1; /*!< [9..9] DMA Complete. Processing of the DMA operation has completed + and the DMA submodule is returned into the idle state */ + __IOM uint32_t DERR : 1; /*!< [10..10] DMA Error encountered during the processing of the + DMA command. The DMA error could occur when the memory + access specified in the DMA operation is not available + or incorrectly specified. */ + __IOM uint32_t CQPAUSED : 1; /*!< [11..11] Command queue is paused due to an active event enabled + in the PAUSEEN register. The interrupt is posted when the + event is enabled within the PAUSEEN register, the mask + is active in the CQIRQMASK field and the event occurs. */ + __IOM uint32_t CQUPD : 1; /*!< [12..12] Command queue write operation executed a register write + with the register address bit 0 set to 1. The low address + bits in the CQ address fields are unused and bit 0 can + be used to trigger an interrupt to indicate when this register + write is performed by the CQ operation. */ + __IOM uint32_t CQERR : 1; /*!< [13..13] Command queue error during processing. When an error + occurs, the system will stop processing and halt operations + to allow software to take recovery actions */ + __IOM uint32_t B2MSLEEP : 1; /*!< [14..14] The B2M_STATE from the BLE Core transitioned into the + sleep state */ + __IOM uint32_t B2MACTIVE : 1; /*!< [15..15] The B2M_STATE from the BLE Core transitioned into the + active state */ + __IOM uint32_t B2MSHUTDN : 1; /*!< [16..16] The B2M_STATE from the BLE Core transitioned into shutdown + state */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000224) IO Master Interrupts: Status */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current + operation has completed. For repeated commands, this will + only be asserted when the final repeated command is completed. */ + __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted + when the number of free bytes in the write FIFO equals + or exceeds the WTHR field.For read operations, asserted + when the number of valid bytes in the read FIFO equals + of exceeds the value set in the RTHR field. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. Asserted when a pop operation + is done to a empty read FIFO. */ + __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software + tries to write to a full fifo. The current operation does + not stop. */ + __IOM uint32_t B2MST : 1; /*!< [4..4] B2M State change interrupt. Asserted on any change in + the B2M_STATE signal from the BLE Core. */ + __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is + a overflow or underflow event */ + __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is + written when an active command is in progress. */ + __IOM uint32_t BLECIRQ : 1; /*!< [7..7] BLE Core IRQ signal. Asserted when the BLE_IRQ signal + from the BLE Core is asserted, indicating the availability + of read data from the BLE Core. */ + __IOM uint32_t BLECSSTAT : 1; /*!< [8..8] BLE Core SPI Status interrupt. Asserted when the SPI_STATUS + signal from the BLE Core is asserted, indicating that SPI + writes can be done to the BLE Core.Transfers to the BLE + Core should only be done when this signal is high. */ + __IOM uint32_t DCMP : 1; /*!< [9..9] DMA Complete. Processing of the DMA operation has completed + and the DMA submodule is returned into the idle state */ + __IOM uint32_t DERR : 1; /*!< [10..10] DMA Error encountered during the processing of the + DMA command. The DMA error could occur when the memory + access specified in the DMA operation is not available + or incorrectly specified. */ + __IOM uint32_t CQPAUSED : 1; /*!< [11..11] Command queue is paused due to an active event enabled + in the PAUSEEN register. The interrupt is posted when the + event is enabled within the PAUSEEN register, the mask + is active in the CQIRQMASK field and the event occurs. */ + __IOM uint32_t CQUPD : 1; /*!< [12..12] Command queue write operation executed a register write + with the register address bit 0 set to 1. The low address + bits in the CQ address fields are unused and bit 0 can + be used to trigger an interrupt to indicate when this register + write is performed by the CQ operation. */ + __IOM uint32_t CQERR : 1; /*!< [13..13] Command queue error during processing. When an error + occurs, the system will stop processing and halt operations + to allow software to take recovery actions */ + __IOM uint32_t B2MSLEEP : 1; /*!< [14..14] The B2M_STATE from the BLE Core transitioned into the + sleep state */ + __IOM uint32_t B2MACTIVE : 1; /*!< [15..15] The B2M_STATE from the BLE Core transitioned into the + active state */ + __IOM uint32_t B2MSHUTDN : 1; /*!< [16..16] The B2M_STATE from the BLE Core transitioned into shutdown + state */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000228) IO Master Interrupts: Clear */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current + operation has completed. For repeated commands, this will + only be asserted when the final repeated command is completed. */ + __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted + when the number of free bytes in the write FIFO equals + or exceeds the WTHR field.For read operations, asserted + when the number of valid bytes in the read FIFO equals + of exceeds the value set in the RTHR field. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. Asserted when a pop operation + is done to a empty read FIFO. */ + __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software + tries to write to a full fifo. The current operation does + not stop. */ + __IOM uint32_t B2MST : 1; /*!< [4..4] B2M State change interrupt. Asserted on any change in + the B2M_STATE signal from the BLE Core. */ + __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is + a overflow or underflow event */ + __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is + written when an active command is in progress. */ + __IOM uint32_t BLECIRQ : 1; /*!< [7..7] BLE Core IRQ signal. Asserted when the BLE_IRQ signal + from the BLE Core is asserted, indicating the availability + of read data from the BLE Core. */ + __IOM uint32_t BLECSSTAT : 1; /*!< [8..8] BLE Core SPI Status interrupt. Asserted when the SPI_STATUS + signal from the BLE Core is asserted, indicating that SPI + writes can be done to the BLE Core.Transfers to the BLE + Core should only be done when this signal is high. */ + __IOM uint32_t DCMP : 1; /*!< [9..9] DMA Complete. Processing of the DMA operation has completed + and the DMA submodule is returned into the idle state */ + __IOM uint32_t DERR : 1; /*!< [10..10] DMA Error encountered during the processing of the + DMA command. The DMA error could occur when the memory + access specified in the DMA operation is not available + or incorrectly specified. */ + __IOM uint32_t CQPAUSED : 1; /*!< [11..11] Command queue is paused due to an active event enabled + in the PAUSEEN register. The interrupt is posted when the + event is enabled within the PAUSEEN register, the mask + is active in the CQIRQMASK field and the event occurs. */ + __IOM uint32_t CQUPD : 1; /*!< [12..12] Command queue write operation executed a register write + with the register address bit 0 set to 1. The low address + bits in the CQ address fields are unused and bit 0 can + be used to trigger an interrupt to indicate when this register + write is performed by the CQ operation. */ + __IOM uint32_t CQERR : 1; /*!< [13..13] Command queue error during processing. When an error + occurs, the system will stop processing and halt operations + to allow software to take recovery actions */ + __IOM uint32_t B2MSLEEP : 1; /*!< [14..14] The B2M_STATE from the BLE Core transitioned into the + sleep state */ + __IOM uint32_t B2MACTIVE : 1; /*!< [15..15] The B2M_STATE from the BLE Core transitioned into the + active state */ + __IOM uint32_t B2MSHUTDN : 1; /*!< [16..16] The B2M_STATE from the BLE Core transitioned into shutdown + state */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000022C) IO Master Interrupts: Set */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current + operation has completed. For repeated commands, this will + only be asserted when the final repeated command is completed. */ + __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted + when the number of free bytes in the write FIFO equals + or exceeds the WTHR field.For read operations, asserted + when the number of valid bytes in the read FIFO equals + of exceeds the value set in the RTHR field. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. Asserted when a pop operation + is done to a empty read FIFO. */ + __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software + tries to write to a full fifo. The current operation does + not stop. */ + __IOM uint32_t B2MST : 1; /*!< [4..4] B2M State change interrupt. Asserted on any change in + the B2M_STATE signal from the BLE Core. */ + __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is + a overflow or underflow event */ + __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is + written when an active command is in progress. */ + __IOM uint32_t BLECIRQ : 1; /*!< [7..7] BLE Core IRQ signal. Asserted when the BLE_IRQ signal + from the BLE Core is asserted, indicating the availability + of read data from the BLE Core. */ + __IOM uint32_t BLECSSTAT : 1; /*!< [8..8] BLE Core SPI Status interrupt. Asserted when the SPI_STATUS + signal from the BLE Core is asserted, indicating that SPI + writes can be done to the BLE Core.Transfers to the BLE + Core should only be done when this signal is high. */ + __IOM uint32_t DCMP : 1; /*!< [9..9] DMA Complete. Processing of the DMA operation has completed + and the DMA submodule is returned into the idle state */ + __IOM uint32_t DERR : 1; /*!< [10..10] DMA Error encountered during the processing of the + DMA command. The DMA error could occur when the memory + access specified in the DMA operation is not available + or incorrectly specified. */ + __IOM uint32_t CQPAUSED : 1; /*!< [11..11] Command queue is paused due to an active event enabled + in the PAUSEEN register. The interrupt is posted when the + event is enabled within the PAUSEEN register, the mask + is active in the CQIRQMASK field and the event occurs. */ + __IOM uint32_t CQUPD : 1; /*!< [12..12] Command queue write operation executed a register write + with the register address bit 0 set to 1. The low address + bits in the CQ address fields are unused and bit 0 can + be used to trigger an interrupt to indicate when this register + write is performed by the CQ operation. */ + __IOM uint32_t CQERR : 1; /*!< [13..13] Command queue error during processing. When an error + occurs, the system will stop processing and halt operations + to allow software to take recovery actions */ + __IOM uint32_t B2MSLEEP : 1; /*!< [14..14] The B2M_STATE from the BLE Core transitioned into the + sleep state */ + __IOM uint32_t B2MACTIVE : 1; /*!< [15..15] The B2M_STATE from the BLE Core transitioned into the + active state */ + __IOM uint32_t B2MSHUTDN : 1; /*!< [16..16] The B2M_STATE from the BLE Core transitioned into shutdown + state */ + } INTSET_b; + } ; + + union { + __IOM uint32_t DMATRIGEN; /*!< (@ 0x00000230) DMA Trigger Enable Register */ + + struct { + __IOM uint32_t DCMDCMPEN : 1; /*!< [0..0] Trigger DMA upon command complete. Enables the trigger + of the DMA when a command is completed. When this event + is triggered, the number of words transferred will be the + lesser of the remaining TOTCOUNT bytes, or the number of + bytes in the FIFO when the command completed. If this is + disabled, and the number of bytes in the FIFO is equal + or greater than the TOTCOUNT bytes, a transfer of TOTCOUNT + bytes will be done to ensure read data is stored when the + DMA is completed. */ + __IOM uint32_t DTHREN : 1; /*!< [1..1] Trigger DMA upon THR level reached. For M2P DMA operations + (IOM writes), the trigger will assert when the write FIFO + has (WTHR/4) number of words free in the write FIFO, and + will transfer (WTHR/4) number of wordsor, if the number + of words left to transfer is less than the WTHR value, + will transfer the remaining byte count.For P2M DMA operations, + the trigger will assert when the read FIFO has (RTHR/4) + words available in the read FIFO, and will transfer (RTHR/4) + words to SRAM. This trigger will NOT asser */ + } DMATRIGEN_b; + } ; + + union { + __IOM uint32_t DMATRIGSTAT; /*!< (@ 0x00000234) DMA Trigger Status Register */ + + struct { + __IOM uint32_t DCMDCMP : 1; /*!< [0..0] Triggered DMA from Command complete event. Bit is read + only and can be cleared by disabling the DCMDCMP trigger + enable or by disabling DMA. */ + __IOM uint32_t DTHR : 1; /*!< [1..1] Triggered DMA from THR event. Bit is read only and can + be cleared by disabling the DTHR trigger enable or by disabling + DMA. */ + __IOM uint32_t DTOTCMP : 1; /*!< [2..2] DMA triggered when DCMDCMP = 0, and the amount of data + in the FIFO was enough to complete the DMA operation (greater + than or equal to current TOTCOUNT) when the command completed. + This trigger is default active when the DCMDCMP trigger + isdisabled and there is enough data in the FIFO to complete + the DMA operation. */ + } DMATRIGSTAT_b; + } ; + + union { + __IOM uint32_t DMACFG; /*!< (@ 0x00000238) DMA Configuration Register */ + + struct { + __IOM uint32_t DMAEN : 1; /*!< [0..0] DMA Enable. Setting this bit to EN will start the DMA + operation. This should be the last DMA related register + set prior to issuing the command */ + __IOM uint32_t DMADIR : 1; /*!< [1..1] Direction */ + __IM uint32_t : 6; + __IOM uint32_t DMAPRI : 1; /*!< [8..8] Sets the Priority of the DMA request */ + __IOM uint32_t DPWROFF : 1; /*!< [9..9] Power off module after DMA is complete. If this bit is + active, the module will request to power off the supply + it is attached to. If there are other units still requiring + power from the same domain, power down will not be performed. */ + } DMACFG_b; + } ; + + union { + __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x0000023C) DMA Total Transfer Count */ + + struct { + __IOM uint32_t TOTCOUNT : 12; /*!< [11..0] Triggered DMA from Command complete event occured. Bit + is read only and can be cleared by disabling the DTHR trigger + enable or by disabling DMA. */ + } DMATOTCOUNT_b; + } ; + + union { + __IOM uint32_t DMATARGADDR; /*!< (@ 0x00000240) DMA Target Address Register */ + + struct { + __IOM uint32_t TARGADDR : 20; /*!< [19..0] Bits [19:0] of the target byte address for source of + DMA (either read or write). The address can be any byte + alignment, and does not have to be word aligned. In cases + of non-word aligned addresses, the DMA logic will take + care for ensuring only the target bytes are read/written. */ + __IM uint32_t : 8; + __IOM uint32_t TARGADDR28 : 1; /*!< [28..28] Bit 28 of the target byte address for source of DMA + (either read or write). In cases of non-word aligned addresses, + the DMA logic will take care for ensuring only the target + bytes are read/written.Setting to '1' will select the SRAM. + Setting to '0' will select the flash */ + } DMATARGADDR_b; + } ; + + union { + __IOM uint32_t DMASTAT; /*!< (@ 0x00000244) DMA Status Register */ + + struct { + __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress indicator. 1 will indicate that + a DMA transfer is active. The DMA transfer may be waiting + on data, transferring data, or waiting for priority.All + of these will be indicated with a 1. A 0 will indicate + that the DMA is fully complete and no further transactions + will be done. This bit is read only. */ + __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete. This signals the end of the DMA + operation. This bit can be cleared by writing to 0. */ + __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error. This active high bit signals that an error + was encountered during the DMA operation. */ + } DMASTAT_b; + } ; + + union { + __IOM uint32_t CQCFG; /*!< (@ 0x00000248) Command Queue Configuration Register */ + + struct { + __IOM uint32_t CQEN : 1; /*!< [0..0] Command queue enable. When set, will enable the processing + of the command queue and fetches of address/data pairs + will proceed from the word address within the CQADDR register. + Can be disabledusing a CQ executed write to this bit as + well. */ + __IOM uint32_t CQPRI : 1; /*!< [1..1] Sets the Priority of the command queue dma request. */ + } CQCFG_b; + } ; + + union { + __IOM uint32_t CQADDR; /*!< (@ 0x0000024C) CQ Target Read Address Register */ + + struct { + __IM uint32_t : 2; + __IOM uint32_t CQADDR : 18; /*!< [19..2] Bits 19:2 of target byte address for source of CQ (read + only). The buffer must be aligned on a word boundary */ + __IM uint32_t : 8; + __IOM uint32_t CQADDR28 : 1; /*!< [28..28] Bit 28 of target byte address for source of CQ (read + only). Used to denote Flash (0) or SRAM (1) access */ + } CQADDR_b; + } ; + + union { + __IOM uint32_t CQSTAT; /*!< (@ 0x00000250) Command Queue Status Register */ + + struct { + __IOM uint32_t CQTIP : 1; /*!< [0..0] Command queue Transfer In Progress indicator. 1 will + indicate that a CQ transfer is active and this will remain + active even when paused waiting for external event. */ + __IOM uint32_t CQPAUSED : 1; /*!< [1..1] Command queue operation is currently paused. */ + __IOM uint32_t CQERR : 1; /*!< [2..2] Command queue processing Error. This active high bit + signals that an error was encountered during the CQ operation. */ + } CQSTAT_b; + } ; + + union { + __IOM uint32_t CQFLAGS; /*!< (@ 0x00000254) Command Queue Flag Register */ + + struct { + __IOM uint32_t CQFLAGS : 16; /*!< [15..0] Current flag status (read-only). Bits [7:0] are software + controllable and bits [15:8] are hardware status. */ + __IOM uint32_t CQIRQMASK : 16; /*!< [31..16] Provides for a per-bit mask of the flags used to invoke + an interrupt. A '1' in the bit position will enable the + pause event to trigger the interrupt, if the CQWT_int interrupt + is enabled.Bits definitions are the same as CQPAUSE */ + } CQFLAGS_b; + } ; + + union { + __IOM uint32_t CQSETCLEAR; /*!< (@ 0x00000258) Command Queue Flag Set/Clear Register */ + + struct { + __IOM uint32_t CQFSET : 8; /*!< [7..0] Set CQFlag status bits. Will set to 1 the value of any + SWFLAG with a '1' in the corresponding bit position of + this field */ + __IOM uint32_t CQFTGL : 8; /*!< [15..8] Toggle the indicated bit. Will toggle the value of any + SWFLAG with a '1' in the corresponding bit position of + this field */ + __IOM uint32_t CQFCLR : 8; /*!< [23..16] Clear CQFlag status bits. Will clear to 0 any SWFLAG + with a '1' in the corresponding bit position of this field */ + } CQSETCLEAR_b; + } ; + + union { + __IOM uint32_t CQPAUSEEN; /*!< (@ 0x0000025C) Command Queue Pause Enable Register */ + + struct { + __IOM uint32_t CQPEN : 16; /*!< [15..0] Enables the specified event to pause command processing + when active */ + } CQPAUSEEN_b; + } ; + + union { + __IOM uint32_t CQCURIDX; /*!< (@ 0x00000260) IOM Command Queue current index value . Compared + to the CQENDIDX reg contents to generate + the IDXEQ Pause event for command queue */ + + struct { + __IOM uint32_t CQCURIDX : 8; /*!< [7..0] Holds 8 bits of data that will be compared with the CQENDIX + register field. If the values match, the IDXEQ pause event + will be activated, which will cause the pausing of command + quue operation if the IDXEQ bit is enabled in CQPAUSEEN. */ + } CQCURIDX_b; + } ; + + union { + __IOM uint32_t CQENDIDX; /*!< (@ 0x00000264) IOM Command Queue current index value . Compared + to the CQCURIDX reg contents to generate + the IDXEQ Pause event for command queue */ + + struct { + __IOM uint32_t CQENDIDX : 8; /*!< [7..0] Holds 8 bits of data that will be compared with the CQCURIX + register field. If the values match, the IDXEQ pause event + will be activated, which will cause the pausing of command + quue operation if the IDXEQ bit is enabled in CQPAUSEEN. */ + } CQENDIDX_b; + } ; + + union { + __IOM uint32_t STATUS; /*!< (@ 0x00000268) IOM Module Status Register */ + + struct { + __IOM uint32_t ERR : 1; /*!< [0..0] Bit has been deprecated. Please refer to the other error + indicators. This will always return 0. */ + __IOM uint32_t CMDACT : 1; /*!< [1..1] Indicates if the active I/O Command is currently processing + a transaction, or command is complete, but the FIFO pointers + are still syncronizing internally. This bit will go high + atthe start of the transaction, and will go low when the + command is complete, and the data and pointers within the + FIFO have been syncronized. */ + __IOM uint32_t IDLEST : 1; /*!< [2..2] indicates if the active I/O state machine is IDLE. Note + - The state machine could be in idle state due to holdoffs + from data availability, or as the command gets propagated + into the logic from the registers. */ + } STATUS_b; + } ; + __IM uint32_t RESERVED4[37]; + + union { + __IOM uint32_t MSPICFG; /*!< (@ 0x00000300) SPI module master configuration */ + + struct { + __IOM uint32_t SPOL : 1; /*!< [0..0] This bit selects SPI polarity. */ + __IOM uint32_t SPHA : 1; /*!< [1..1] Selects the SPI phase; When 1, will shift the sampling + edge by 1/2 clock. */ + __IOM uint32_t FULLDUP : 1; /*!< [2..2] Full Duplex mode. Capture read data during writes operations */ + __IM uint32_t : 13; + __IOM uint32_t WTFC : 1; /*!< [16..16] Enables flow control of new write transactions based + on the SPI_STATUS signal from the BLE Core. */ + __IOM uint32_t RDFC : 1; /*!< [17..17] Enables flow control of new read transactions based + on the SPI_STATUS signal from the BLE Core. */ + __IM uint32_t : 3; + __IOM uint32_t WTFCPOL : 1; /*!< [21..21] Selects the write flow control signal polarity. The + transfers are halted when the selected flow control signal + is OPPOSITE polarity of this bit. (For example: WTFCPOL + = 0 will allow a SPI_STATUS=1 to pause transfers). */ + __IOM uint32_t RDFCPOL : 1; /*!< [22..22] Selects the read flow control signal polarity. When + set, the clock will be held low until the flow control + is de-asserted. */ + __IOM uint32_t SPILSB : 1; /*!< [23..23] Selects data transfer as MSB first (0) or LSB first + (1) for the data portion of the SPI transaction. The offset + bytes are always transmitted MSB first. */ + __IOM uint32_t DINDLY : 3; /*!< [26..24] Delay tap to use for the input signal (MISO). This + gives more hold time on the input data. */ + __IOM uint32_t DOUTDLY : 3; /*!< [29..27] Delay tap to use for the output signal (MOSI). This + give more hold time on the output data. */ + __IOM uint32_t MSPIRST : 1; /*!< [30..30] Bit is deprecated. setting it will have no effect. */ + } MSPICFG_b; + } ; + + union { + __IOM uint32_t BLECFG; /*!< (@ 0x00000304) BLE Core Control */ + + struct { + __IOM uint32_t PWRSMEN : 1; /*!< [0..0] Enable the power state machine for automatic sequencing + and control of power states of the BLE Core module. */ + __IOM uint32_t BLERSTN : 1; /*!< [1..1] Reset line to the BLE Core. This will reset the BLE core + when asserted ('0') and must be written to '1' prior to + performing any BTLE related operations to the core. */ + __IOM uint32_t WAKEUPCTL : 2; /*!< [3..2] WAKE signal override. Controls the source of the WAKE + signal to the BLE Core. */ + __IOM uint32_t DCDCFLGCTL : 2; /*!< [5..4] DCDCFLG signal override. The value of this field will + be sent to the BLE Core when the PWRSM is off. Otherwise, + the value is supplied from internal logic. */ + __IOM uint32_t BLEHREQCTL : 2; /*!< [7..6] BLEH power on request override. The value of this field + will be sent to the BLE Core when the PWRSM is off. Otherwise, + the value is supplied from internal logic. */ + __IOM uint32_t WT4ACTOFF : 1; /*!< [8..8] Debug control of BLEIF power state machine. Allows transition + into the active state in the BLEIF state without waiting + for dcdc req from BLE Core. */ + __IOM uint32_t MCUFRCSLP : 1; /*!< [9..9] Force power state machine to go to the sleep state. Intended + for debug only. Has no effect on the actual BLE Core state, + only the state of the BLEIF interface state machine. */ + __IOM uint32_t FRCCLK : 1; /*!< [10..10] Force the clock in the BLEIF to be always running */ + __IOM uint32_t STAYASLEEP : 1; /*!< [11..11] Set to prevent the BLE power control module from waking + up the BLE Core after going into power down. To be used + for graceful shutdown, set by software prior to powering + off and will allow assertion of reset from sleep state. */ + __IOM uint32_t PWRISOCTL : 2; /*!< [13..12] Configuration of BLEH isolation control for power related + signals. */ + __IOM uint32_t SPIISOCTL : 2; /*!< [15..14] Configuration of BLEH isolation controls for SPI related + signals. */ + } BLECFG_b; + } ; + + union { + __IOM uint32_t PWRCMD; /*!< (@ 0x00000308) BLE Power command interface */ + + struct { + __IOM uint32_t WAKEREQ : 1; /*!< [0..0] Wake request from the MCU. When asserted (1), the BLE + Interface logic will assert the wakeup request signal to + the BLE Core. Only recognized when in the sleep state */ + __IOM uint32_t RESTART : 1; /*!< [1..1] Restart the BLE Core after going into the shutdown state. + Only valid when in the shutdown state. */ + } PWRCMD_b; + } ; + + union { + __IOM uint32_t BSTATUS; /*!< (@ 0x0000030C) BLE Core status */ + + struct { + __IOM uint32_t B2MSTATE : 3; /*!< [2..0] State of the BLE Core logic. */ + __IOM uint32_t SPISTATUS : 1; /*!< [3..3] Value of the SPISTATUS signal from the BLE Core. The + signal is asserted when the BLE Core is able to accept + write data via the SPI interface. Data should be transmitted + to theBLE core only when this signal is 1. The hardware + will automatically wait for this signal prior to performing + a write operation if flow control is active. */ + __IOM uint32_t DCDCREQ : 1; /*!< [4..4] Value of the DCDCREQ signal from the BLE Core. The DCDCREQ + signal is sent from the core to the BLEIF module when the + BLE core requires BLEH power to be active. When activated, + this isindicated by DCDCFLAG going to 1. */ + __IOM uint32_t DCDCFLAG : 1; /*!< [5..5] Value of the DCDCFLAG signal to the BLE Core. The DCDCFLAG + is a signal to the BLE Core indicating that the BLEH ppower + is active. */ + __IOM uint32_t WAKEUP : 1; /*!< [6..6] Value of the WAKEUP signal to the BLE Core . The WAKEUP + signals is sent from the BLEIF to the BLECORE to request + the BLE Core transition from sleep state to active state. */ + __IOM uint32_t BLEIRQ : 1; /*!< [7..7] Status of the BLEIRQ signal from the BLE Core. A value + of 1 idicates that read data is available in the core and + a read operation needs to be performed. */ + __IOM uint32_t PWRST : 3; /*!< [10..8] Current status of the power state machine */ + __IOM uint32_t BLEHACK : 1; /*!< [11..11] Value of the BLEHACK signal from the power control + unit. If the signal is '1', the BLEH power is active and + ready for use. */ + __IOM uint32_t BLEHREQ : 1; /*!< [12..12] Value of the BLEHREQ signal to the power control unit. + The BLEHREQ signal is sent from the BLEIF module to the + power control module to request the BLEH power up. When + the BLEHACK signal is asserted,BLEH power is stable and + ready for use. */ + } BSTATUS_b; + } ; + __IM uint32_t RESERVED5[64]; + + union { + __IOM uint32_t BLEDBG; /*!< (@ 0x00000410) BLEIF Master Debug Register */ + + struct { + __IOM uint32_t DBGEN : 1; /*!< [0..0] Debug Enable. Setting this bit will enable the update + of data within this register, otherwise it is clock gated + for power savings */ + __IOM uint32_t IOCLKON : 1; /*!< [1..1] IOCLK debug clock control. Enable IO_CLK to be active + when this bit is '1'. Otherwise, the clock is controlled + with gating from the logic as needed. */ + __IOM uint32_t APBCLKON : 1; /*!< [2..2] APBCLK debug clock control. Enable APB_CLK to be active + when this bit is '1'. Otherwise, the clock is controlled + with gating from the logic as needed. */ + __IOM uint32_t DBGDATA : 29; /*!< [31..3] Debug data */ + } BLEDBG_b; + } ; +} BLEIF_Type; /*!< Size = 1044 (0x414) */ + + + +/* =========================================================================================================================== */ +/* ================ CACHECTRL ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Flash Cache Controller (CACHECTRL) + */ + +typedef struct { /*!< (@ 0x40018000) CACHECTRL Structure */ + + union { + __IOM uint32_t CACHECFG; /*!< (@ 0x00000000) Flash Cache Control Register */ + + struct { + __IOM uint32_t ENABLE : 1; /*!< [0..0] Enables the flash cache controller and enables power + to the cache SRAMs. The ICACHE_ENABLE and DCACHE_ENABLE + should be set to enable caching for each type of access. */ + __IOM uint32_t LRU : 1; /*!< [1..1] Sets the cache repleacment policy. 0=LRR (least recently + replaced), 1=LRU (least recently used). LRR minimizes writes + to the TAG SRAM. */ + __IOM uint32_t ENABLE_NC0 : 1; /*!< [2..2] Enable Non-cacheable region 0. See NCR0 registers to + define the region. */ + __IOM uint32_t ENABLE_NC1 : 1; /*!< [3..3] Enable Non-cacheable region 1. See NCR1 registers to + define the region. */ + __IOM uint32_t CONFIG : 4; /*!< [7..4] Sets the cache configuration */ + __IOM uint32_t ICACHE_ENABLE : 1; /*!< [8..8] Enable Flash Instruction Caching */ + __IOM uint32_t DCACHE_ENABLE : 1; /*!< [9..9] Enable Flash Data Caching. */ + __IOM uint32_t CACHE_CLKGATE : 1; /*!< [10..10] Enable clock gating of cache TAG RAM. Software should + enable this bit for optimal power efficiency. */ + __IOM uint32_t CACHE_LS : 1; /*!< [11..11] Enable LS (light sleep) of cache RAMs. Software should + DISABLE this bit since cache activity is too high to benefit + from LS usage. */ + __IM uint32_t : 8; + __IOM uint32_t DATA_CLKGATE : 1; /*!< [20..20] Enable aggressive clock gating of entire data array. + This bit should be set to 1 for optimal power efficiency. */ + __IM uint32_t : 3; + __IOM uint32_t ENABLE_MONITOR : 1; /*!< [24..24] Enable Cache Monitoring Stats. Cache monitoring consumes + additional power and should only be enabled when profiling + code and counters will increment when this bit is set. + Counter values will be retained when this is set to 0, + allowing software to enable/disable counting for multiple + code segments. */ + } CACHECFG_b; + } ; + + union { + __IOM uint32_t FLASHCFG; /*!< (@ 0x00000004) Flash Control Register */ + + struct { + __IOM uint32_t RD_WAIT : 4; /*!< [3..0] Sets read waitstates for normal (fast) operation. A value + of 1 is recommended. */ + __IOM uint32_t SEDELAY : 3; /*!< [6..4] Sets SE delay (flash address setup). A value of 5 is + recommended. */ + __IM uint32_t : 1; + __IOM uint32_t LPM_RD_WAIT : 4; /*!< [11..8] Sets flash waitstates when in LPM Mode 2 (RD_WAIT in + LPM mode 2 only) */ + __IOM uint32_t LPMMODE : 2; /*!< [13..12] Controls flash low power modes (control of LPM pin). */ + } FLASHCFG_b; + } ; + + union { + __IOM uint32_t CTRL; /*!< (@ 0x00000008) Cache Control */ + + struct { + __IOM uint32_t INVALIDATE : 1; /*!< [0..0] Writing a 1 to this bitfield invalidates the flash cache + contents. */ + __IOM uint32_t RESET_STAT : 1; /*!< [1..1] Reset Cache Statistics. When written to a 1, the cache + monitor counters will be cleared. The monitor counters + can be reset only when the CACHECFG.ENABLE_MONITOR bit + is set. */ + __IOM uint32_t CACHE_READY : 1; /*!< [2..2] Cache Ready Status (enabled and not processing an invalidate + operation) */ + __IM uint32_t : 1; + __IOM uint32_t FLASH0_SLM_STATUS : 1; /*!< [4..4] Flash Sleep Mode Status. 1 indicates that flash0 is in + sleep mode, 0 indicates flash0 is in normal mode. */ + __IOM uint32_t FLASH0_SLM_DISABLE : 1; /*!< [5..5] Disable Flash Sleep Mode. Write 1 to wake flash0 from + sleep mode (reading the array will also automatically wake + it). */ + __IOM uint32_t FLASH0_SLM_ENABLE : 1; /*!< [6..6] Enable Flash Sleep Mode. Write to 1 to put flash 0 into + sleep mode. NOTE: there is a 5us latency after waking flash + until the first access will be returned. */ + __IM uint32_t : 1; + __IOM uint32_t FLASH1_SLM_STATUS : 1; /*!< [8..8] Flash Sleep Mode Status. 1 indicates that flash1 is in + sleep mode, 0 indicates flash1 is in normal mode. */ + __IOM uint32_t FLASH1_SLM_DISABLE : 1; /*!< [9..9] Disable Flash Sleep Mode. Write 1 to wake flash1 from + sleep mode (reading the array will also automatically wake + it). */ + __IOM uint32_t FLASH1_SLM_ENABLE : 1; /*!< [10..10] Enable Flash Sleep Mode. Write to 1 to put flash 1 + into sleep mode. NOTE: there is a 5us latency after waking + flash until the first access will be returned. */ + } CTRL_b; + } ; + __IM uint32_t RESERVED; + + union { + __IOM uint32_t NCR0START; /*!< (@ 0x00000010) Flash Cache Noncachable Region 0 Start */ + + struct { + __IM uint32_t : 4; + __IOM uint32_t ADDR : 23; /*!< [26..4] Start address for non-cacheable region 0 */ + } NCR0START_b; + } ; + + union { + __IOM uint32_t NCR0END; /*!< (@ 0x00000014) Flash Cache Noncachable Region 0 End */ + + struct { + __IM uint32_t : 4; + __IOM uint32_t ADDR : 23; /*!< [26..4] End address for non-cacheable region 0 */ + } NCR0END_b; + } ; + + union { + __IOM uint32_t NCR1START; /*!< (@ 0x00000018) Flash Cache Noncachable Region 1 Start */ + + struct { + __IM uint32_t : 4; + __IOM uint32_t ADDR : 23; /*!< [26..4] Start address for non-cacheable region 1 */ + } NCR1START_b; + } ; + + union { + __IOM uint32_t NCR1END; /*!< (@ 0x0000001C) Flash Cache Noncachable Region 1 End */ + + struct { + __IM uint32_t : 4; + __IOM uint32_t ADDR : 23; /*!< [26..4] End address for non-cacheable region 1 */ + } NCR1END_b; + } ; + __IM uint32_t RESERVED1[8]; + + union { + __IOM uint32_t DMON0; /*!< (@ 0x00000040) Data Cache Total Accesses */ + + struct { + __IOM uint32_t DACCESS_COUNT : 32; /*!< [31..0] Total accesses to data cache. All performance metrics + should be relative to the number of accesses performed. */ + } DMON0_b; + } ; + + union { + __IOM uint32_t DMON1; /*!< (@ 0x00000044) Data Cache Tag Lookups */ + + struct { + __IOM uint32_t DLOOKUP_COUNT : 32; /*!< [31..0] Total tag lookups from data cache. */ + } DMON1_b; + } ; + + union { + __IOM uint32_t DMON2; /*!< (@ 0x00000048) Data Cache Hits */ + + struct { + __IOM uint32_t DHIT_COUNT : 32; /*!< [31..0] Cache hits from lookup operations. */ + } DMON2_b; + } ; + + union { + __IOM uint32_t DMON3; /*!< (@ 0x0000004C) Data Cache Line Hits */ + + struct { + __IOM uint32_t DLINE_COUNT : 32; /*!< [31..0] Cache hits from line cache */ + } DMON3_b; + } ; + + union { + __IOM uint32_t IMON0; /*!< (@ 0x00000050) Instruction Cache Total Accesses */ + + struct { + __IOM uint32_t IACCESS_COUNT : 32; /*!< [31..0] Total accesses to Instruction cache */ + } IMON0_b; + } ; + + union { + __IOM uint32_t IMON1; /*!< (@ 0x00000054) Instruction Cache Tag Lookups */ + + struct { + __IOM uint32_t ILOOKUP_COUNT : 32; /*!< [31..0] Total tag lookups from Instruction cache */ + } IMON1_b; + } ; + + union { + __IOM uint32_t IMON2; /*!< (@ 0x00000058) Instruction Cache Hits */ + + struct { + __IOM uint32_t IHIT_COUNT : 32; /*!< [31..0] Cache hits from lookup operations */ + } IMON2_b; + } ; + + union { + __IOM uint32_t IMON3; /*!< (@ 0x0000005C) Instruction Cache Line Hits */ + + struct { + __IOM uint32_t ILINE_COUNT : 32; /*!< [31..0] Cache hits from line cache */ + } IMON3_b; + } ; +} CACHECTRL_Type; /*!< Size = 96 (0x60) */ + + + +/* =========================================================================================================================== */ +/* ================ CLKGEN ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Clock Generator (CLKGEN) + */ + +typedef struct { /*!< (@ 0x40004000) CLKGEN Structure */ + + union { + __IOM uint32_t CALXT; /*!< (@ 0x00000000) XT Oscillator Control */ + + struct { + __IOM uint32_t CALXT : 11; /*!< [10..0] XT Oscillator calibration value. This register will + enable the hardware to increase or decrease the number + of cycles in a 16KHz clock derived from the original 32KHz + version. The most significant bit is the sign. A '1' is + a reduction, and a '0' is an addition. This calibration + value will add or reduce the number of cycles programmed + here across a 32 second interval. The maximum value that + is effective is from -1024 to 1023. */ + } CALXT_b; + } ; + + union { + __IOM uint32_t CALRC; /*!< (@ 0x00000004) RC Oscillator Control */ + + struct { + __IOM uint32_t CALRC : 18; /*!< [17..0] LFRC Oscillator calibration value. This register will + enable the hardware to increase or decrease the number + of cycles in a 512 Hz clock derived from the original 1024 + version. The most significant bit is the sign. A '1' is + a reduction, and a '0' is an addition. This calibration + value will add or reduce the number of cycles programmed + here across a 32 second interval. The range is from -131072 + (decimal) to 131071 (decimal). This register is normally + used in conjuction with ACALCTR register. The CAL */ + } CALRC_b; + } ; + + union { + __IOM uint32_t ACALCTR; /*!< (@ 0x00000008) Autocalibration Counter */ + + struct { + __IOM uint32_t ACALCTR : 24; /*!< [23..0] Autocalibration Counter result. Bits 17 down to 0 of + this is feed directly to the CALRC register if ACAL register + in OCTRL register is set to 1024SEC or 512SEC. */ + } ACALCTR_b; + } ; + + union { + __IOM uint32_t OCTRL; /*!< (@ 0x0000000C) Oscillator Control */ + + struct { + __IOM uint32_t STOPXT : 1; /*!< [0..0] Stop the XT Oscillator to the RTC */ + __IOM uint32_t STOPRC : 1; /*!< [1..1] Stop the LFRC Oscillator to the RTC */ + __IM uint32_t : 4; + __IOM uint32_t FOS : 1; /*!< [6..6] Oscillator switch on failure function. If this is set, + then LFRC clock source will switch from XT to RC. */ + __IOM uint32_t OSEL : 1; /*!< [7..7] Selects the RTC oscillator (1 => LFRC, 0 => XT) */ + __IOM uint32_t ACAL : 3; /*!< [10..8] Autocalibration control. This selects the source to + be used in the autocalibration flow. This flow can also + be used to measure an internal clock against an external + clock source, with the external clock normally used as + the reference. */ + } OCTRL_b; + } ; + + union { + __IOM uint32_t CLKOUT; /*!< (@ 0x00000010) CLKOUT Frequency Select */ + + struct { + __IOM uint32_t CKSEL : 6; /*!< [5..0] CLKOUT signal select */ + __IM uint32_t : 1; + __IOM uint32_t CKEN : 1; /*!< [7..7] Enable the CLKOUT signal */ + } CLKOUT_b; + } ; + + union { + __IOM uint32_t CLKKEY; /*!< (@ 0x00000014) Key Register for Clock Control Register */ + + struct { + __IOM uint32_t CLKKEY : 32; /*!< [31..0] Key register value. */ + } CLKKEY_b; + } ; + + union { + __IOM uint32_t CCTRL; /*!< (@ 0x00000018) HFRC Clock Control */ + + struct { + __IOM uint32_t CORESEL : 1; /*!< [0..0] Core Clock divisor */ + } CCTRL_b; + } ; + + union { + __IOM uint32_t STATUS; /*!< (@ 0x0000001C) Clock Generator Status */ + + struct { + __IOM uint32_t OMODE : 1; /*!< [0..0] Current RTC oscillator (1 => LFRC, 0 => XT). After an + RTC oscillator change, it may take up to 2 seconds for + this field to reflect the new oscillator. */ + __IOM uint32_t OSCF : 1; /*!< [1..1] XT Oscillator is enabled but not oscillating */ + } STATUS_b; + } ; + + union { + __IOM uint32_t HFADJ; /*!< (@ 0x00000020) HFRC Adjustment */ + + struct { + __IOM uint32_t HFADJEN : 1; /*!< [0..0] HFRC adjustment control */ + __IOM uint32_t HFADJCK : 3; /*!< [3..1] Repeat period for HFRC adjustment */ + __IM uint32_t : 4; + __IOM uint32_t HFXTADJ : 12; /*!< [19..8] Target HFRC adjustment value. */ + __IOM uint32_t HFWARMUP : 1; /*!< [20..20] XT warmup period for HFRC adjustment */ + __IOM uint32_t HFADJGAIN : 3; /*!< [23..21] Gain control for HFRC adjustment */ + } HFADJ_b; + } ; + __IM uint32_t RESERVED; + + union { + __IOM uint32_t CLOCKENSTAT; /*!< (@ 0x00000028) Clock Enable Status */ + + struct { + __IOM uint32_t CLOCKENSTAT : 32; /*!< [31..0] Clock enable status */ + } CLOCKENSTAT_b; + } ; + + union { + __IOM uint32_t CLOCKEN2STAT; /*!< (@ 0x0000002C) Clock Enable Status */ + + struct { + __IOM uint32_t CLOCKEN2STAT : 32; /*!< [31..0] Clock enable status 2 */ + } CLOCKEN2STAT_b; + } ; + + union { + __IOM uint32_t CLOCKEN3STAT; /*!< (@ 0x00000030) Clock Enable Status */ + + struct { + __IOM uint32_t CLOCKEN3STAT : 32; /*!< [31..0] Clock enable status 3 */ + } CLOCKEN3STAT_b; + } ; + + union { + __IOM uint32_t FREQCTRL; /*!< (@ 0x00000034) HFRC Frequency Control register */ + + struct { + __IOM uint32_t BURSTREQ : 1; /*!< [0..0] Frequency Burst Enable Request */ + __IOM uint32_t BURSTACK : 1; /*!< [1..1] Frequency Burst Request Acknowledge. Frequency burst + requested is always acknowledged whether burst is granted + or not depending on feature enable. */ + __IOM uint32_t BURSTSTATUS : 1; /*!< [2..2] This represents frequency burst status. */ + } FREQCTRL_b; + } ; + __IM uint32_t RESERVED1; + + union { + __IOM uint32_t BLEBUCKTONADJ; /*!< (@ 0x0000003C) BLE BUCK TON ADJUST */ + + struct { + __IOM uint32_t TONLOWTHRESHOLD : 10; /*!< [9..0] TON ADJUST LOW THRESHOLD. Suggested values are #A(94KHz) + #15(47KHz) #53(12Khz) #14D(3Khz) */ + __IOM uint32_t TONHIGHTHRESHOLD : 10; /*!< [19..10] TON ADJUST HIGH THRESHOLD. Suggested values are #15(94KHz) + #2A(47Khz) #A6(12Khz) #29A(3Khz) */ + __IOM uint32_t TONADJUSTPERIOD : 2; /*!< [21..20] TON ADJUST PERIOD */ + __IOM uint32_t TONADJUSTEN : 1; /*!< [22..22] TON ADJUST ENABLE */ + __IOM uint32_t ZEROLENDETECTTRIM : 4; /*!< [26..23] BLEBUCK ZERO LENGTH DETECT TRIM */ + __IOM uint32_t ZEROLENDETECTEN : 1; /*!< [27..27] BLEBUCK ZERO LENGTH DETECT ENABLE */ + } BLEBUCKTONADJ_b; + } ; + __IM uint32_t RESERVED2[48]; + + union { + __IOM uint32_t INTRPTEN; /*!< (@ 0x00000100) CLKGEN Interrupt Register: Enable */ + + struct { + __IOM uint32_t ACF : 1; /*!< [0..0] Autocalibration Fail interrupt */ + __IOM uint32_t ACC : 1; /*!< [1..1] Autocalibration Complete interrupt */ + __IOM uint32_t OF : 1; /*!< [2..2] XT Oscillator Fail interrupt */ + } INTRPTEN_b; + } ; + + union { + __IOM uint32_t INTRPTSTAT; /*!< (@ 0x00000104) CLKGEN Interrupt Register: Status */ + + struct { + __IOM uint32_t ACF : 1; /*!< [0..0] Autocalibration Fail interrupt */ + __IOM uint32_t ACC : 1; /*!< [1..1] Autocalibration Complete interrupt */ + __IOM uint32_t OF : 1; /*!< [2..2] XT Oscillator Fail interrupt */ + } INTRPTSTAT_b; + } ; + + union { + __IOM uint32_t INTRPTCLR; /*!< (@ 0x00000108) CLKGEN Interrupt Register: Clear */ + + struct { + __IOM uint32_t ACF : 1; /*!< [0..0] Autocalibration Fail interrupt */ + __IOM uint32_t ACC : 1; /*!< [1..1] Autocalibration Complete interrupt */ + __IOM uint32_t OF : 1; /*!< [2..2] XT Oscillator Fail interrupt */ + } INTRPTCLR_b; + } ; + + union { + __IOM uint32_t INTRPTSET; /*!< (@ 0x0000010C) CLKGEN Interrupt Register: Set */ + + struct { + __IOM uint32_t ACF : 1; /*!< [0..0] Autocalibration Fail interrupt */ + __IOM uint32_t ACC : 1; /*!< [1..1] Autocalibration Complete interrupt */ + __IOM uint32_t OF : 1; /*!< [2..2] XT Oscillator Fail interrupt */ + } INTRPTSET_b; + } ; +} CLKGEN_Type; /*!< Size = 272 (0x110) */ + + + +/* =========================================================================================================================== */ +/* ================ CTIMER ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Counter/Timer (CTIMER) + */ + +typedef struct { /*!< (@ 0x40008000) CTIMER Structure */ + + union { + __IOM uint32_t TMR0; /*!< (@ 0x00000000) Counter/Timer Register */ + + struct { + __IOM uint32_t CTTMRA0 : 16; /*!< [15..0] Counter/Timer A0. */ + __IOM uint32_t CTTMRB0 : 16; /*!< [31..16] Counter/Timer B0. */ + } TMR0_b; + } ; + + union { + __IOM uint32_t CMPRA0; /*!< (@ 0x00000004) Counter/Timer A0 Compare Registers */ + + struct { + __IOM uint32_t CMPR0A0 : 16; /*!< [15..0] Counter/Timer A0 Compare Register 0. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR1A0 : 16; /*!< [31..16] Counter/Timer A0 Compare Register 1. Holds the upper + limit for timer half A. */ + } CMPRA0_b; + } ; + + union { + __IOM uint32_t CMPRB0; /*!< (@ 0x00000008) Counter/Timer B0 Compare Registers */ + + struct { + __IOM uint32_t CMPR0B0 : 16; /*!< [15..0] Counter/Timer B0 Compare Register 0. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR1B0 : 16; /*!< [31..16] Counter/Timer B0 Compare Register 1. Holds the upper + limit for timer half B. */ + } CMPRB0_b; + } ; + + union { + __IOM uint32_t CTRL0; /*!< (@ 0x0000000C) Counter/Timer Control */ + + struct { + __IOM uint32_t TMRA0EN : 1; /*!< [0..0] Counter/Timer A0 Enable bit. */ + __IOM uint32_t TMRA0CLK : 5; /*!< [5..1] Counter/Timer A0 Clock Select. */ + __IOM uint32_t TMRA0FN : 3; /*!< [8..6] Counter/Timer A0 Function Select. */ + __IOM uint32_t TMRA0IE0 : 1; /*!< [9..9] Counter/Timer A0 Interrupt Enable bit based on COMPR0. */ + __IOM uint32_t TMRA0IE1 : 1; /*!< [10..10] Counter/Timer A0 Interrupt Enable bit based on COMPR1. */ + __IOM uint32_t TMRA0CLR : 1; /*!< [11..11] Counter/Timer A0 Clear bit. */ + __IOM uint32_t TMRA0POL : 1; /*!< [12..12] Counter/Timer A0 output polarity. */ + __IM uint32_t : 3; + __IOM uint32_t TMRB0EN : 1; /*!< [16..16] Counter/Timer B0 Enable bit. */ + __IOM uint32_t TMRB0CLK : 5; /*!< [21..17] Counter/Timer B0 Clock Select. */ + __IOM uint32_t TMRB0FN : 3; /*!< [24..22] Counter/Timer B0 Function Select. */ + __IOM uint32_t TMRB0IE0 : 1; /*!< [25..25] Counter/Timer B0 Interrupt Enable bit for COMPR0. */ + __IOM uint32_t TMRB0IE1 : 1; /*!< [26..26] Counter/Timer B0 Interrupt Enable bit for COMPR1. */ + __IOM uint32_t TMRB0CLR : 1; /*!< [27..27] Counter/Timer B0 Clear bit. */ + __IOM uint32_t TMRB0POL : 1; /*!< [28..28] Counter/Timer B0 output polarity. */ + __IM uint32_t : 2; + __IOM uint32_t CTLINK0 : 1; /*!< [31..31] Counter/Timer A0/B0 Link bit. */ + } CTRL0_b; + } ; + __IM uint32_t RESERVED; + + union { + __IOM uint32_t CMPRAUXA0; /*!< (@ 0x00000014) Counter/Timer A0 Compare Registers */ + + struct { + __IOM uint32_t CMPR2A0 : 16; /*!< [15..0] Counter/Timer A0 Compare Register 2. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR3A0 : 16; /*!< [31..16] Counter/Timer A0 Compare Register 3. Holds the upper + limit for timer half A. */ + } CMPRAUXA0_b; + } ; + + union { + __IOM uint32_t CMPRAUXB0; /*!< (@ 0x00000018) Counter/Timer B0 Compare Registers */ + + struct { + __IOM uint32_t CMPR2B0 : 16; /*!< [15..0] Counter/Timer B0 Compare Register 2. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR3B0 : 16; /*!< [31..16] Counter/Timer B0 Compare Register 3. Holds the upper + limit for timer half B. */ + } CMPRAUXB0_b; + } ; + + union { + __IOM uint32_t AUX0; /*!< (@ 0x0000001C) Counter/Timer Auxiliary */ + + struct { + __IOM uint32_t TMRA0LMT : 7; /*!< [6..0] Counter/Timer A0 Pattern Limit Count. */ + __IOM uint32_t TMRA0TRIG : 4; /*!< [10..7] Counter/Timer A0 Trigger Select. */ + __IOM uint32_t TMRA0NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ + __IOM uint32_t TMRA0TINV : 1; /*!< [12..12] Counter/Timer A0 Invert on trigger. */ + __IOM uint32_t TMRA0POL23 : 1; /*!< [13..13] Counter/Timer A0 Upper output polarity */ + __IOM uint32_t TMRA0EN23 : 1; /*!< [14..14] Counter/Timer A0 Upper compare enable. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB0LMT : 6; /*!< [21..16] Counter/Timer B0 Pattern Limit Count. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB0TRIG : 4; /*!< [26..23] Counter/Timer B0 Trigger Select. */ + __IOM uint32_t TMRB0NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ + __IOM uint32_t TMRB0TINV : 1; /*!< [28..28] Counter/Timer B0 Invert on trigger. */ + __IOM uint32_t TMRB0POL23 : 1; /*!< [29..29] Upper output polarity */ + __IOM uint32_t TMRB0EN23 : 1; /*!< [30..30] Counter/Timer B0 Upper compare enable. */ + } AUX0_b; + } ; + + union { + __IOM uint32_t TMR1; /*!< (@ 0x00000020) Counter/Timer Register */ + + struct { + __IOM uint32_t CTTMRA1 : 16; /*!< [15..0] Counter/Timer A1. */ + __IOM uint32_t CTTMRB1 : 16; /*!< [31..16] Counter/Timer B1. */ + } TMR1_b; + } ; + + union { + __IOM uint32_t CMPRA1; /*!< (@ 0x00000024) Counter/Timer A1 Compare Registers */ + + struct { + __IOM uint32_t CMPR0A1 : 16; /*!< [15..0] Counter/Timer A1 Compare Register 0. */ + __IOM uint32_t CMPR1A1 : 16; /*!< [31..16] Counter/Timer A1 Compare Register 1. */ + } CMPRA1_b; + } ; + + union { + __IOM uint32_t CMPRB1; /*!< (@ 0x00000028) Counter/Timer B1 Compare Registers */ + + struct { + __IOM uint32_t CMPR0B1 : 16; /*!< [15..0] Counter/Timer B1 Compare Register 0. */ + __IOM uint32_t CMPR1B1 : 16; /*!< [31..16] Counter/Timer B1 Compare Register 1. */ + } CMPRB1_b; + } ; + + union { + __IOM uint32_t CTRL1; /*!< (@ 0x0000002C) Counter/Timer Control */ + + struct { + __IOM uint32_t TMRA1EN : 1; /*!< [0..0] Counter/Timer A1 Enable bit. */ + __IOM uint32_t TMRA1CLK : 5; /*!< [5..1] Counter/Timer A1 Clock Select. */ + __IOM uint32_t TMRA1FN : 3; /*!< [8..6] Counter/Timer A1 Function Select. */ + __IOM uint32_t TMRA1IE0 : 1; /*!< [9..9] Counter/Timer A1 Interrupt Enable bit based on COMPR0. */ + __IOM uint32_t TMRA1IE1 : 1; /*!< [10..10] Counter/Timer A1 Interrupt Enable bit based on COMPR1. */ + __IOM uint32_t TMRA1CLR : 1; /*!< [11..11] Counter/Timer A1 Clear bit. */ + __IOM uint32_t TMRA1POL : 1; /*!< [12..12] Counter/Timer A1 output polarity. */ + __IM uint32_t : 3; + __IOM uint32_t TMRB1EN : 1; /*!< [16..16] Counter/Timer B1 Enable bit. */ + __IOM uint32_t TMRB1CLK : 5; /*!< [21..17] Counter/Timer B1 Clock Select. */ + __IOM uint32_t TMRB1FN : 3; /*!< [24..22] Counter/Timer B1 Function Select. */ + __IOM uint32_t TMRB1IE0 : 1; /*!< [25..25] Counter/Timer B1 Interrupt Enable bit for COMPR0. */ + __IOM uint32_t TMRB1IE1 : 1; /*!< [26..26] Counter/Timer B1 Interrupt Enable bit for COMPR1. */ + __IOM uint32_t TMRB1CLR : 1; /*!< [27..27] Counter/Timer B1 Clear bit. */ + __IOM uint32_t TMRB1POL : 1; /*!< [28..28] Counter/Timer B1 output polarity. */ + __IM uint32_t : 2; + __IOM uint32_t CTLINK1 : 1; /*!< [31..31] Counter/Timer A1/B1 Link bit. */ + } CTRL1_b; + } ; + __IM uint32_t RESERVED1; + + union { + __IOM uint32_t CMPRAUXA1; /*!< (@ 0x00000034) Counter/Timer A1 Compare Registers */ + + struct { + __IOM uint32_t CMPR2A1 : 16; /*!< [15..0] Counter/Timer A1 Compare Register 2. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR3A1 : 16; /*!< [31..16] Counter/Timer A1 Compare Register 3. Holds the upper + limit for timer half A. */ + } CMPRAUXA1_b; + } ; + + union { + __IOM uint32_t CMPRAUXB1; /*!< (@ 0x00000038) Counter/Timer B1 Compare Registers */ + + struct { + __IOM uint32_t CMPR2B1 : 16; /*!< [15..0] Counter/Timer B1 Compare Register 2. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR3B1 : 16; /*!< [31..16] Counter/Timer B1 Compare Register 3. Holds the upper + limit for timer half B. */ + } CMPRAUXB1_b; + } ; + + union { + __IOM uint32_t AUX1; /*!< (@ 0x0000003C) Counter/Timer Auxiliary */ + + struct { + __IOM uint32_t TMRA1LMT : 7; /*!< [6..0] Counter/Timer A1 Pattern Limit Count. */ + __IOM uint32_t TMRA1TRIG : 4; /*!< [10..7] Counter/Timer A1 Trigger Select. */ + __IOM uint32_t TMRA1NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ + __IOM uint32_t TMRA1TINV : 1; /*!< [12..12] Counter/Timer A1 Invert on trigger. */ + __IOM uint32_t TMRA1POL23 : 1; /*!< [13..13] Counter/Timer A1 Upper output polarity */ + __IOM uint32_t TMRA1EN23 : 1; /*!< [14..14] Counter/Timer A1 Upper compare enable. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB1LMT : 6; /*!< [21..16] Counter/Timer B1 Pattern Limit Count. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB1TRIG : 4; /*!< [26..23] Counter/Timer B1 Trigger Select. */ + __IOM uint32_t TMRB1NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ + __IOM uint32_t TMRB1TINV : 1; /*!< [28..28] Counter/Timer B1 Invert on trigger. */ + __IOM uint32_t TMRB1POL23 : 1; /*!< [29..29] Upper output polarity */ + __IOM uint32_t TMRB1EN23 : 1; /*!< [30..30] Counter/Timer B1 Upper compare enable. */ + } AUX1_b; + } ; + + union { + __IOM uint32_t TMR2; /*!< (@ 0x00000040) Counter/Timer Register */ + + struct { + __IOM uint32_t CTTMRA2 : 16; /*!< [15..0] Counter/Timer A2. */ + __IOM uint32_t CTTMRB2 : 16; /*!< [31..16] Counter/Timer B2. */ + } TMR2_b; + } ; + + union { + __IOM uint32_t CMPRA2; /*!< (@ 0x00000044) Counter/Timer A2 Compare Registers */ + + struct { + __IOM uint32_t CMPR0A2 : 16; /*!< [15..0] Counter/Timer A2 Compare Register 0. */ + __IOM uint32_t CMPR1A2 : 16; /*!< [31..16] Counter/Timer A2 Compare Register 1. */ + } CMPRA2_b; + } ; + + union { + __IOM uint32_t CMPRB2; /*!< (@ 0x00000048) Counter/Timer B2 Compare Registers */ + + struct { + __IOM uint32_t CMPR0B2 : 16; /*!< [15..0] Counter/Timer B2 Compare Register 0. */ + __IOM uint32_t CMPR1B2 : 16; /*!< [31..16] Counter/Timer B2 Compare Register 1. */ + } CMPRB2_b; + } ; + + union { + __IOM uint32_t CTRL2; /*!< (@ 0x0000004C) Counter/Timer Control */ + + struct { + __IOM uint32_t TMRA2EN : 1; /*!< [0..0] Counter/Timer A2 Enable bit. */ + __IOM uint32_t TMRA2CLK : 5; /*!< [5..1] Counter/Timer A2 Clock Select. */ + __IOM uint32_t TMRA2FN : 3; /*!< [8..6] Counter/Timer A2 Function Select. */ + __IOM uint32_t TMRA2IE0 : 1; /*!< [9..9] Counter/Timer A2 Interrupt Enable bit based on COMPR0. */ + __IOM uint32_t TMRA2IE1 : 1; /*!< [10..10] Counter/Timer A2 Interrupt Enable bit based on COMPR1. */ + __IOM uint32_t TMRA2CLR : 1; /*!< [11..11] Counter/Timer A2 Clear bit. */ + __IOM uint32_t TMRA2POL : 1; /*!< [12..12] Counter/Timer A2 output polarity. */ + __IM uint32_t : 3; + __IOM uint32_t TMRB2EN : 1; /*!< [16..16] Counter/Timer B2 Enable bit. */ + __IOM uint32_t TMRB2CLK : 5; /*!< [21..17] Counter/Timer B2 Clock Select. */ + __IOM uint32_t TMRB2FN : 3; /*!< [24..22] Counter/Timer B2 Function Select. */ + __IOM uint32_t TMRB2IE0 : 1; /*!< [25..25] Counter/Timer B2 Interrupt Enable bit for COMPR0. */ + __IOM uint32_t TMRB2IE1 : 1; /*!< [26..26] Counter/Timer B2 Interrupt Enable bit for COMPR1. */ + __IOM uint32_t TMRB2CLR : 1; /*!< [27..27] Counter/Timer B2 Clear bit. */ + __IOM uint32_t TMRB2POL : 1; /*!< [28..28] Counter/Timer B2 output polarity. */ + __IM uint32_t : 2; + __IOM uint32_t CTLINK2 : 1; /*!< [31..31] Counter/Timer A2/B2 Link bit. */ + } CTRL2_b; + } ; + __IM uint32_t RESERVED2; + + union { + __IOM uint32_t CMPRAUXA2; /*!< (@ 0x00000054) Counter/Timer A2 Compare Registers */ + + struct { + __IOM uint32_t CMPR2A2 : 16; /*!< [15..0] Counter/Timer A2 Compare Register 2. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR3A2 : 16; /*!< [31..16] Counter/Timer A2 Compare Register 3. Holds the upper + limit for timer half A. */ + } CMPRAUXA2_b; + } ; + + union { + __IOM uint32_t CMPRAUXB2; /*!< (@ 0x00000058) Counter/Timer B2 Compare Registers */ + + struct { + __IOM uint32_t CMPR2B2 : 16; /*!< [15..0] Counter/Timer B2 Compare Register 2. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR3B2 : 16; /*!< [31..16] Counter/Timer B2 Compare Register 3. Holds the upper + limit for timer half B. */ + } CMPRAUXB2_b; + } ; + + union { + __IOM uint32_t AUX2; /*!< (@ 0x0000005C) Counter/Timer Auxiliary */ + + struct { + __IOM uint32_t TMRA2LMT : 7; /*!< [6..0] Counter/Timer A2 Pattern Limit Count. */ + __IOM uint32_t TMRA2TRIG : 4; /*!< [10..7] Counter/Timer A2 Trigger Select. */ + __IOM uint32_t TMRA2NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ + __IOM uint32_t TMRA2TINV : 1; /*!< [12..12] Counter/Timer A2 Invert on trigger. */ + __IOM uint32_t TMRA2POL23 : 1; /*!< [13..13] Counter/Timer A2 Upper output polarity */ + __IOM uint32_t TMRA2EN23 : 1; /*!< [14..14] Counter/Timer A2 Upper compare enable. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB2LMT : 6; /*!< [21..16] Counter/Timer B2 Pattern Limit Count. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB2TRIG : 4; /*!< [26..23] Counter/Timer B2 Trigger Select. */ + __IOM uint32_t TMRB2NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ + __IOM uint32_t TMRB2TINV : 1; /*!< [28..28] Counter/Timer B2 Invert on trigger. */ + __IOM uint32_t TMRB2POL23 : 1; /*!< [29..29] Upper output polarity */ + __IOM uint32_t TMRB2EN23 : 1; /*!< [30..30] Counter/Timer B2 Upper compare enable. */ + } AUX2_b; + } ; + + union { + __IOM uint32_t TMR3; /*!< (@ 0x00000060) Counter/Timer Register */ + + struct { + __IOM uint32_t CTTMRA3 : 16; /*!< [15..0] Counter/Timer A3. */ + __IOM uint32_t CTTMRB3 : 16; /*!< [31..16] Counter/Timer B3. */ + } TMR3_b; + } ; + + union { + __IOM uint32_t CMPRA3; /*!< (@ 0x00000064) Counter/Timer A3 Compare Registers */ + + struct { + __IOM uint32_t CMPR0A3 : 16; /*!< [15..0] Counter/Timer A3 Compare Register 0. */ + __IOM uint32_t CMPR1A3 : 16; /*!< [31..16] Counter/Timer A3 Compare Register 1. */ + } CMPRA3_b; + } ; + + union { + __IOM uint32_t CMPRB3; /*!< (@ 0x00000068) Counter/Timer B3 Compare Registers */ + + struct { + __IOM uint32_t CMPR0B3 : 16; /*!< [15..0] Counter/Timer B3 Compare Register 0. */ + __IOM uint32_t CMPR1B3 : 16; /*!< [31..16] Counter/Timer B3 Compare Register 1. */ + } CMPRB3_b; + } ; + + union { + __IOM uint32_t CTRL3; /*!< (@ 0x0000006C) Counter/Timer Control */ + + struct { + __IOM uint32_t TMRA3EN : 1; /*!< [0..0] Counter/Timer A3 Enable bit. */ + __IOM uint32_t TMRA3CLK : 5; /*!< [5..1] Counter/Timer A3 Clock Select. */ + __IOM uint32_t TMRA3FN : 3; /*!< [8..6] Counter/Timer A3 Function Select. */ + __IOM uint32_t TMRA3IE0 : 1; /*!< [9..9] Counter/Timer A3 Interrupt Enable bit based on COMPR0. */ + __IOM uint32_t TMRA3IE1 : 1; /*!< [10..10] Counter/Timer A3 Interrupt Enable bit based on COMPR1. */ + __IOM uint32_t TMRA3CLR : 1; /*!< [11..11] Counter/Timer A3 Clear bit. */ + __IOM uint32_t TMRA3POL : 1; /*!< [12..12] Counter/Timer A3 output polarity. */ + __IM uint32_t : 2; + __IOM uint32_t ADCEN : 1; /*!< [15..15] Special Timer A3 enable for ADC function. */ + __IOM uint32_t TMRB3EN : 1; /*!< [16..16] Counter/Timer B3 Enable bit. */ + __IOM uint32_t TMRB3CLK : 5; /*!< [21..17] Counter/Timer B3 Clock Select. */ + __IOM uint32_t TMRB3FN : 3; /*!< [24..22] Counter/Timer B3 Function Select. */ + __IOM uint32_t TMRB3IE0 : 1; /*!< [25..25] Counter/Timer B3 Interrupt Enable bit for COMPR0. */ + __IOM uint32_t TMRB3IE1 : 1; /*!< [26..26] Counter/Timer B3 Interrupt Enable bit for COMPR1. */ + __IOM uint32_t TMRB3CLR : 1; /*!< [27..27] Counter/Timer B3 Clear bit. */ + __IOM uint32_t TMRB3POL : 1; /*!< [28..28] Counter/Timer B3 output polarity. */ + __IM uint32_t : 2; + __IOM uint32_t CTLINK3 : 1; /*!< [31..31] Counter/Timer A3/B3 Link bit. */ + } CTRL3_b; + } ; + __IM uint32_t RESERVED3; + + union { + __IOM uint32_t CMPRAUXA3; /*!< (@ 0x00000074) Counter/Timer A3 Compare Registers */ + + struct { + __IOM uint32_t CMPR2A3 : 16; /*!< [15..0] Counter/Timer A3 Compare Register 2. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR3A3 : 16; /*!< [31..16] Counter/Timer A3 Compare Register 3. Holds the upper + limit for timer half A. */ + } CMPRAUXA3_b; + } ; + + union { + __IOM uint32_t CMPRAUXB3; /*!< (@ 0x00000078) Counter/Timer B3 Compare Registers */ + + struct { + __IOM uint32_t CMPR2B3 : 16; /*!< [15..0] Counter/Timer B3 Compare Register 2. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR3B3 : 16; /*!< [31..16] Counter/Timer B3 Compare Register 3. Holds the upper + limit for timer half B. */ + } CMPRAUXB3_b; + } ; + + union { + __IOM uint32_t AUX3; /*!< (@ 0x0000007C) Counter/Timer Auxiliary */ + + struct { + __IOM uint32_t TMRA3LMT : 7; /*!< [6..0] Counter/Timer A3 Pattern Limit Count. */ + __IOM uint32_t TMRA3TRIG : 4; /*!< [10..7] Counter/Timer A3 Trigger Select. */ + __IOM uint32_t TMRA3NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ + __IOM uint32_t TMRA3TINV : 1; /*!< [12..12] Counter/Timer A3 Invert on trigger. */ + __IOM uint32_t TMRA3POL23 : 1; /*!< [13..13] Counter/Timer A3 Upper output polarity */ + __IOM uint32_t TMRA3EN23 : 1; /*!< [14..14] Counter/Timer A3 Upper compare enable. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB3LMT : 6; /*!< [21..16] Counter/Timer B3 Pattern Limit Count. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB3TRIG : 4; /*!< [26..23] Counter/Timer B3 Trigger Select. */ + __IOM uint32_t TMRB3NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ + __IOM uint32_t TMRB3TINV : 1; /*!< [28..28] Counter/Timer B3 Invert on trigger. */ + __IOM uint32_t TMRB3POL23 : 1; /*!< [29..29] Upper output polarity */ + __IOM uint32_t TMRB3EN23 : 1; /*!< [30..30] Counter/Timer B3 Upper compare enable. */ + } AUX3_b; + } ; + + union { + __IOM uint32_t TMR4; /*!< (@ 0x00000080) Counter/Timer Register */ + + struct { + __IOM uint32_t CTTMRA4 : 16; /*!< [15..0] Counter/Timer A4. */ + __IOM uint32_t CTTMRB4 : 16; /*!< [31..16] Counter/Timer B4. */ + } TMR4_b; + } ; + + union { + __IOM uint32_t CMPRA4; /*!< (@ 0x00000084) Counter/Timer A4 Compare Registers */ + + struct { + __IOM uint32_t CMPR0A4 : 16; /*!< [15..0] Counter/Timer A4 Compare Register 0. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR1A4 : 16; /*!< [31..16] Counter/Timer A4 Compare Register 1. Holds the upper + limit for timer half A. */ + } CMPRA4_b; + } ; + + union { + __IOM uint32_t CMPRB4; /*!< (@ 0x00000088) Counter/Timer B4 Compare Registers */ + + struct { + __IOM uint32_t CMPR0B4 : 16; /*!< [15..0] Counter/Timer B4 Compare Register 0. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR1B4 : 16; /*!< [31..16] Counter/Timer B4 Compare Register 1. Holds the upper + limit for timer half B. */ + } CMPRB4_b; + } ; + + union { + __IOM uint32_t CTRL4; /*!< (@ 0x0000008C) Counter/Timer Control */ + + struct { + __IOM uint32_t TMRA4EN : 1; /*!< [0..0] Counter/Timer A4 Enable bit. */ + __IOM uint32_t TMRA4CLK : 5; /*!< [5..1] Counter/Timer A4 Clock Select. */ + __IOM uint32_t TMRA4FN : 3; /*!< [8..6] Counter/Timer A4 Function Select. */ + __IOM uint32_t TMRA4IE0 : 1; /*!< [9..9] Counter/Timer A4 Interrupt Enable bit based on COMPR0. */ + __IOM uint32_t TMRA4IE1 : 1; /*!< [10..10] Counter/Timer A4 Interrupt Enable bit based on COMPR1. */ + __IOM uint32_t TMRA4CLR : 1; /*!< [11..11] Counter/Timer A4 Clear bit. */ + __IOM uint32_t TMRA4POL : 1; /*!< [12..12] Counter/Timer A4 output polarity. */ + __IM uint32_t : 3; + __IOM uint32_t TMRB4EN : 1; /*!< [16..16] Counter/Timer B4 Enable bit. */ + __IOM uint32_t TMRB4CLK : 5; /*!< [21..17] Counter/Timer B4 Clock Select. */ + __IOM uint32_t TMRB4FN : 3; /*!< [24..22] Counter/Timer B4 Function Select. */ + __IOM uint32_t TMRB4IE0 : 1; /*!< [25..25] Counter/Timer B4 Interrupt Enable bit for COMPR0. */ + __IOM uint32_t TMRB4IE1 : 1; /*!< [26..26] Counter/Timer B4 Interrupt Enable bit for COMPR1. */ + __IOM uint32_t TMRB4CLR : 1; /*!< [27..27] Counter/Timer B4 Clear bit. */ + __IOM uint32_t TMRB4POL : 1; /*!< [28..28] Counter/Timer B4 output polarity. */ + __IM uint32_t : 2; + __IOM uint32_t CTLINK4 : 1; /*!< [31..31] Counter/Timer A4/B4 Link bit. */ + } CTRL4_b; + } ; + __IM uint32_t RESERVED4; + + union { + __IOM uint32_t CMPRAUXA4; /*!< (@ 0x00000094) Counter/Timer A4 Compare Registers */ + + struct { + __IOM uint32_t CMPR2A4 : 16; /*!< [15..0] Counter/Timer A4 Compare Register 2. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR3A4 : 16; /*!< [31..16] Counter/Timer A4 Compare Register 3. Holds the upper + limit for timer half A. */ + } CMPRAUXA4_b; + } ; + + union { + __IOM uint32_t CMPRAUXB4; /*!< (@ 0x00000098) Counter/Timer B4 Compare Registers */ + + struct { + __IOM uint32_t CMPR2B4 : 16; /*!< [15..0] Counter/Timer B4 Compare Register 2. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR3B4 : 16; /*!< [31..16] Counter/Timer B4 Compare Register 3. Holds the upper + limit for timer half B. */ + } CMPRAUXB4_b; + } ; + + union { + __IOM uint32_t AUX4; /*!< (@ 0x0000009C) Counter/Timer Auxiliary */ + + struct { + __IOM uint32_t TMRA4LMT : 7; /*!< [6..0] Counter/Timer A4 Pattern Limit Count. */ + __IOM uint32_t TMRA4TRIG : 4; /*!< [10..7] Counter/Timer A4 Trigger Select. */ + __IOM uint32_t TMRA4NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ + __IOM uint32_t TMRA4TINV : 1; /*!< [12..12] Counter/Timer A4 Invert on trigger. */ + __IOM uint32_t TMRA4POL23 : 1; /*!< [13..13] Counter/Timer A4 Upper output polarity */ + __IOM uint32_t TMRA4EN23 : 1; /*!< [14..14] Counter/Timer A4 Upper compare enable. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB4LMT : 6; /*!< [21..16] Counter/Timer B4 Pattern Limit Count. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB4TRIG : 4; /*!< [26..23] Counter/Timer B4 Trigger Select. */ + __IOM uint32_t TMRB4NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ + __IOM uint32_t TMRB4TINV : 1; /*!< [28..28] Counter/Timer B4 Invert on trigger. */ + __IOM uint32_t TMRB4POL23 : 1; /*!< [29..29] Upper output polarity */ + __IOM uint32_t TMRB4EN23 : 1; /*!< [30..30] Counter/Timer B4 Upper compare enable. */ + } AUX4_b; + } ; + + union { + __IOM uint32_t TMR5; /*!< (@ 0x000000A0) Counter/Timer Register */ + + struct { + __IOM uint32_t CTTMRA5 : 16; /*!< [15..0] Counter/Timer A5. */ + __IOM uint32_t CTTMRB5 : 16; /*!< [31..16] Counter/Timer B5. */ + } TMR5_b; + } ; + + union { + __IOM uint32_t CMPRA5; /*!< (@ 0x000000A4) Counter/Timer A5 Compare Registers */ + + struct { + __IOM uint32_t CMPR0A5 : 16; /*!< [15..0] Counter/Timer A5 Compare Register 0. */ + __IOM uint32_t CMPR1A5 : 16; /*!< [31..16] Counter/Timer A5 Compare Register 1. */ + } CMPRA5_b; + } ; + + union { + __IOM uint32_t CMPRB5; /*!< (@ 0x000000A8) Counter/Timer B5 Compare Registers */ + + struct { + __IOM uint32_t CMPR0B5 : 16; /*!< [15..0] Counter/Timer B5 Compare Register 0. */ + __IOM uint32_t CMPR1B5 : 16; /*!< [31..16] Counter/Timer B5 Compare Register 1. */ + } CMPRB5_b; + } ; + + union { + __IOM uint32_t CTRL5; /*!< (@ 0x000000AC) Counter/Timer Control */ + + struct { + __IOM uint32_t TMRA5EN : 1; /*!< [0..0] Counter/Timer A5 Enable bit. */ + __IOM uint32_t TMRA5CLK : 5; /*!< [5..1] Counter/Timer A5 Clock Select. */ + __IOM uint32_t TMRA5FN : 3; /*!< [8..6] Counter/Timer A5 Function Select. */ + __IOM uint32_t TMRA5IE0 : 1; /*!< [9..9] Counter/Timer A5 Interrupt Enable bit based on COMPR0. */ + __IOM uint32_t TMRA5IE1 : 1; /*!< [10..10] Counter/Timer A5 Interrupt Enable bit based on COMPR1. */ + __IOM uint32_t TMRA5CLR : 1; /*!< [11..11] Counter/Timer A5 Clear bit. */ + __IOM uint32_t TMRA5POL : 1; /*!< [12..12] Counter/Timer A5 output polarity. */ + __IM uint32_t : 3; + __IOM uint32_t TMRB5EN : 1; /*!< [16..16] Counter/Timer B5 Enable bit. */ + __IOM uint32_t TMRB5CLK : 5; /*!< [21..17] Counter/Timer B5 Clock Select. */ + __IOM uint32_t TMRB5FN : 3; /*!< [24..22] Counter/Timer B5 Function Select. */ + __IOM uint32_t TMRB5IE0 : 1; /*!< [25..25] Counter/Timer B5 Interrupt Enable bit for COMPR0. */ + __IOM uint32_t TMRB5IE1 : 1; /*!< [26..26] Counter/Timer B5 Interrupt Enable bit for COMPR1. */ + __IOM uint32_t TMRB5CLR : 1; /*!< [27..27] Counter/Timer B5 Clear bit. */ + __IOM uint32_t TMRB5POL : 1; /*!< [28..28] Counter/Timer B5 output polarity. */ + __IM uint32_t : 2; + __IOM uint32_t CTLINK5 : 1; /*!< [31..31] Counter/Timer A5/B5 Link bit. */ + } CTRL5_b; + } ; + __IM uint32_t RESERVED5; + + union { + __IOM uint32_t CMPRAUXA5; /*!< (@ 0x000000B4) Counter/Timer A5 Compare Registers */ + + struct { + __IOM uint32_t CMPR2A5 : 16; /*!< [15..0] Counter/Timer A5 Compare Register 2. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR3A5 : 16; /*!< [31..16] Counter/Timer A5 Compare Register 3. Holds the upper + limit for timer half A. */ + } CMPRAUXA5_b; + } ; + + union { + __IOM uint32_t CMPRAUXB5; /*!< (@ 0x000000B8) Counter/Timer B5 Compare Registers */ + + struct { + __IOM uint32_t CMPR2B5 : 16; /*!< [15..0] Counter/Timer B5 Compare Register 2. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR3B5 : 16; /*!< [31..16] Counter/Timer B5 Compare Register 3. Holds the upper + limit for timer half B. */ + } CMPRAUXB5_b; + } ; + + union { + __IOM uint32_t AUX5; /*!< (@ 0x000000BC) Counter/Timer Auxiliary */ + + struct { + __IOM uint32_t TMRA5LMT : 7; /*!< [6..0] Counter/Timer A5 Pattern Limit Count. */ + __IOM uint32_t TMRA5TRIG : 4; /*!< [10..7] Counter/Timer A5 Trigger Select. */ + __IOM uint32_t TMRA5NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ + __IOM uint32_t TMRA5TINV : 1; /*!< [12..12] Counter/Timer A5 Invert on trigger. */ + __IOM uint32_t TMRA5POL23 : 1; /*!< [13..13] Counter/Timer A5 Upper output polarity */ + __IOM uint32_t TMRA5EN23 : 1; /*!< [14..14] Counter/Timer A5 Upper compare enable. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB5LMT : 6; /*!< [21..16] Counter/Timer B5 Pattern Limit Count. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB5TRIG : 4; /*!< [26..23] Counter/Timer B5 Trigger Select. */ + __IOM uint32_t TMRB5NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ + __IOM uint32_t TMRB5TINV : 1; /*!< [28..28] Counter/Timer B5 Invert on trigger. */ + __IOM uint32_t TMRB5POL23 : 1; /*!< [29..29] Upper output polarity */ + __IOM uint32_t TMRB5EN23 : 1; /*!< [30..30] Counter/Timer B5 Upper compare enable. */ + } AUX5_b; + } ; + + union { + __IOM uint32_t TMR6; /*!< (@ 0x000000C0) Counter/Timer Register */ + + struct { + __IOM uint32_t CTTMRA6 : 16; /*!< [15..0] Counter/Timer A6. */ + __IOM uint32_t CTTMRB6 : 16; /*!< [31..16] Counter/Timer B6. */ + } TMR6_b; + } ; + + union { + __IOM uint32_t CMPRA6; /*!< (@ 0x000000C4) Counter/Timer A6 Compare Registers */ + + struct { + __IOM uint32_t CMPR0A6 : 16; /*!< [15..0] Counter/Timer A6 Compare Register 0. */ + __IOM uint32_t CMPR1A6 : 16; /*!< [31..16] Counter/Timer A6 Compare Register 1. */ + } CMPRA6_b; + } ; + + union { + __IOM uint32_t CMPRB6; /*!< (@ 0x000000C8) Counter/Timer B6 Compare Registers */ + + struct { + __IOM uint32_t CMPR0B6 : 16; /*!< [15..0] Counter/Timer B6 Compare Register 0. */ + __IOM uint32_t CMPR1B6 : 16; /*!< [31..16] Counter/Timer B6 Compare Register 1. */ + } CMPRB6_b; + } ; + + union { + __IOM uint32_t CTRL6; /*!< (@ 0x000000CC) Counter/Timer Control */ + + struct { + __IOM uint32_t TMRA6EN : 1; /*!< [0..0] Counter/Timer A6 Enable bit. */ + __IOM uint32_t TMRA6CLK : 5; /*!< [5..1] Counter/Timer A6 Clock Select. */ + __IOM uint32_t TMRA6FN : 3; /*!< [8..6] Counter/Timer A6 Function Select. */ + __IOM uint32_t TMRA6IE0 : 1; /*!< [9..9] Counter/Timer A6 Interrupt Enable bit based on COMPR0. */ + __IOM uint32_t TMRA6IE1 : 1; /*!< [10..10] Counter/Timer A6 Interrupt Enable bit based on COMPR1. */ + __IOM uint32_t TMRA6CLR : 1; /*!< [11..11] Counter/Timer A6 Clear bit. */ + __IOM uint32_t TMRA6POL : 1; /*!< [12..12] Counter/Timer A6 output polarity. */ + __IM uint32_t : 3; + __IOM uint32_t TMRB6EN : 1; /*!< [16..16] Counter/Timer B6 Enable bit. */ + __IOM uint32_t TMRB6CLK : 5; /*!< [21..17] Counter/Timer B6 Clock Select. */ + __IOM uint32_t TMRB6FN : 3; /*!< [24..22] Counter/Timer B6 Function Select. */ + __IOM uint32_t TMRB6IE0 : 1; /*!< [25..25] Counter/Timer B6 Interrupt Enable bit for COMPR0. */ + __IOM uint32_t TMRB6IE1 : 1; /*!< [26..26] Counter/Timer B6 Interrupt Enable bit for COMPR1. */ + __IOM uint32_t TMRB6CLR : 1; /*!< [27..27] Counter/Timer B6 Clear bit. */ + __IOM uint32_t TMRB6POL : 1; /*!< [28..28] Counter/Timer B6 output polarity. */ + __IM uint32_t : 2; + __IOM uint32_t CTLINK6 : 1; /*!< [31..31] Counter/Timer A6/B6 Link bit. */ + } CTRL6_b; + } ; + __IM uint32_t RESERVED6; + + union { + __IOM uint32_t CMPRAUXA6; /*!< (@ 0x000000D4) Counter/Timer A6 Compare Registers */ + + struct { + __IOM uint32_t CMPR2A6 : 16; /*!< [15..0] Counter/Timer A6 Compare Register 2. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR3A6 : 16; /*!< [31..16] Counter/Timer A6 Compare Register 3. Holds the upper + limit for timer half A. */ + } CMPRAUXA6_b; + } ; + + union { + __IOM uint32_t CMPRAUXB6; /*!< (@ 0x000000D8) Counter/Timer B6 Compare Registers */ + + struct { + __IOM uint32_t CMPR2B6 : 16; /*!< [15..0] Counter/Timer B6 Compare Register 2. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR3B6 : 16; /*!< [31..16] Counter/Timer B6 Compare Register 3. Holds the upper + limit for timer half B. */ + } CMPRAUXB6_b; + } ; + + union { + __IOM uint32_t AUX6; /*!< (@ 0x000000DC) Counter/Timer Auxiliary */ + + struct { + __IOM uint32_t TMRA6LMT : 7; /*!< [6..0] Counter/Timer A6 Pattern Limit Count. */ + __IOM uint32_t TMRA6TRIG : 4; /*!< [10..7] Counter/Timer A6 Trigger Select. */ + __IOM uint32_t TMRA6NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ + __IOM uint32_t TMRA6TINV : 1; /*!< [12..12] Counter/Timer A6 Invert on trigger. */ + __IOM uint32_t TMRA6POL23 : 1; /*!< [13..13] Counter/Timer A6 Upper output polarity */ + __IOM uint32_t TMRA6EN23 : 1; /*!< [14..14] Counter/Timer A6 Upper compare enable. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB6LMT : 6; /*!< [21..16] Counter/Timer B6 Pattern Limit Count. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB6TRIG : 4; /*!< [26..23] Counter/Timer B6 Trigger Select. */ + __IOM uint32_t TMRB6NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ + __IOM uint32_t TMRB6TINV : 1; /*!< [28..28] Counter/Timer B6 Invert on trigger. */ + __IOM uint32_t TMRB6POL23 : 1; /*!< [29..29] Upper output polarity */ + __IOM uint32_t TMRB6EN23 : 1; /*!< [30..30] Counter/Timer B6 Upper compare enable. */ + } AUX6_b; + } ; + + union { + __IOM uint32_t TMR7; /*!< (@ 0x000000E0) Counter/Timer Register */ + + struct { + __IOM uint32_t CTTMRA7 : 16; /*!< [15..0] Counter/Timer A7. */ + __IOM uint32_t CTTMRB7 : 16; /*!< [31..16] Counter/Timer B7. */ + } TMR7_b; + } ; + + union { + __IOM uint32_t CMPRA7; /*!< (@ 0x000000E4) Counter/Timer A7 Compare Registers */ + + struct { + __IOM uint32_t CMPR0A7 : 16; /*!< [15..0] Counter/Timer A7 Compare Register 0. */ + __IOM uint32_t CMPR1A7 : 16; /*!< [31..16] Counter/Timer A7 Compare Register 1. */ + } CMPRA7_b; + } ; + + union { + __IOM uint32_t CMPRB7; /*!< (@ 0x000000E8) Counter/Timer B7 Compare Registers */ + + struct { + __IOM uint32_t CMPR0B7 : 16; /*!< [15..0] Counter/Timer B3 Compare Register 0. */ + __IOM uint32_t CMPR1B7 : 16; /*!< [31..16] Counter/Timer B3 Compare Register 1. */ + } CMPRB7_b; + } ; + + union { + __IOM uint32_t CTRL7; /*!< (@ 0x000000EC) Counter/Timer Control */ + + struct { + __IOM uint32_t TMRA7EN : 1; /*!< [0..0] Counter/Timer A7 Enable bit. */ + __IOM uint32_t TMRA7CLK : 5; /*!< [5..1] Counter/Timer A7 Clock Select. */ + __IOM uint32_t TMRA7FN : 3; /*!< [8..6] Counter/Timer A7 Function Select. */ + __IOM uint32_t TMRA7IE0 : 1; /*!< [9..9] Counter/Timer A7 Interrupt Enable bit based on COMPR0. */ + __IOM uint32_t TMRA7IE1 : 1; /*!< [10..10] Counter/Timer A7 Interrupt Enable bit based on COMPR1. */ + __IOM uint32_t TMRA7CLR : 1; /*!< [11..11] Counter/Timer A7 Clear bit. */ + __IOM uint32_t TMRA7POL : 1; /*!< [12..12] Counter/Timer A7 output polarity. */ + __IM uint32_t : 3; + __IOM uint32_t TMRB7EN : 1; /*!< [16..16] Counter/Timer B7 Enable bit. */ + __IOM uint32_t TMRB7CLK : 5; /*!< [21..17] Counter/Timer B7 Clock Select. */ + __IOM uint32_t TMRB7FN : 3; /*!< [24..22] Counter/Timer B7 Function Select. */ + __IOM uint32_t TMRB7IE0 : 1; /*!< [25..25] Counter/Timer B7 Interrupt Enable bit for COMPR0. */ + __IOM uint32_t TMRB7IE1 : 1; /*!< [26..26] Counter/Timer B7 Interrupt Enable bit for COMPR1. */ + __IOM uint32_t TMRB7CLR : 1; /*!< [27..27] Counter/Timer B7 Clear bit. */ + __IOM uint32_t TMRB7POL : 1; /*!< [28..28] Counter/Timer B7 output polarity. */ + __IM uint32_t : 2; + __IOM uint32_t CTLINK7 : 1; /*!< [31..31] Counter/Timer A7/B7 Link bit. */ + } CTRL7_b; + } ; + __IM uint32_t RESERVED7; + + union { + __IOM uint32_t CMPRAUXA7; /*!< (@ 0x000000F4) Counter/Timer A7 Compare Registers */ + + struct { + __IOM uint32_t CMPR2A7 : 16; /*!< [15..0] Counter/Timer A7 Compare Register 2. Holds the lower + limit for timer half A. */ + __IOM uint32_t CMPR3A7 : 16; /*!< [31..16] Counter/Timer A7 Compare Register 3. Holds the upper + limit for timer half A. */ + } CMPRAUXA7_b; + } ; + + union { + __IOM uint32_t CMPRAUXB7; /*!< (@ 0x000000F8) Counter/Timer B7 Compare Registers */ + + struct { + __IOM uint32_t CMPR2B7 : 16; /*!< [15..0] Counter/Timer B7 Compare Register 2. Holds the lower + limit for timer half B. */ + __IOM uint32_t CMPR3B7 : 16; /*!< [31..16] Counter/Timer B7 Compare Register 3. Holds the upper + limit for timer half B. */ + } CMPRAUXB7_b; + } ; + + union { + __IOM uint32_t AUX7; /*!< (@ 0x000000FC) Counter/Timer Auxiliary */ + + struct { + __IOM uint32_t TMRA7LMT : 7; /*!< [6..0] Counter/Timer A7 Pattern Limit Count. */ + __IOM uint32_t TMRA7TRIG : 4; /*!< [10..7] Counter/Timer A7 Trigger Select. */ + __IOM uint32_t TMRA7NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ + __IOM uint32_t TMRA7TINV : 1; /*!< [12..12] Counter/Timer A7 Invert on trigger. */ + __IOM uint32_t TMRA7POL23 : 1; /*!< [13..13] Counter/Timer A7 Upper output polarity */ + __IOM uint32_t TMRA7EN23 : 1; /*!< [14..14] Counter/Timer A7 Upper compare enable. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB7LMT : 6; /*!< [21..16] Counter/Timer B7 Pattern Limit Count. */ + __IM uint32_t : 1; + __IOM uint32_t TMRB7TRIG : 4; /*!< [26..23] Counter/Timer B7 Trigger Select. */ + __IOM uint32_t TMRB7NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ + __IOM uint32_t TMRB7TINV : 1; /*!< [28..28] Counter/Timer B7 Invert on trigger. */ + __IOM uint32_t TMRB7POL23 : 1; /*!< [29..29] Upper output polarity */ + __IOM uint32_t TMRB7EN23 : 1; /*!< [30..30] Counter/Timer B7 Upper compare enable. */ + } AUX7_b; + } ; + + union { + __IOM uint32_t GLOBEN; /*!< (@ 0x00000100) Counter/Timer Global Enable */ + + struct { + __IOM uint32_t ENA0 : 1; /*!< [0..0] Alternate enable for A0 */ + __IOM uint32_t ENB0 : 1; /*!< [1..1] Alternate enable for B0 */ + __IOM uint32_t ENA1 : 1; /*!< [2..2] Alternate enable for A1 */ + __IOM uint32_t ENB1 : 1; /*!< [3..3] Alternate enable for B1 */ + __IOM uint32_t ENA2 : 1; /*!< [4..4] Alternate enable for A2 */ + __IOM uint32_t ENB2 : 1; /*!< [5..5] Alternate enable for B2 */ + __IOM uint32_t ENA3 : 1; /*!< [6..6] Alternate enable for A3 */ + __IOM uint32_t ENB3 : 1; /*!< [7..7] Alternate enable for B3. */ + __IOM uint32_t ENA4 : 1; /*!< [8..8] Alternate enable for A4 */ + __IOM uint32_t ENB4 : 1; /*!< [9..9] Alternate enable for B4 */ + __IOM uint32_t ENA5 : 1; /*!< [10..10] Alternate enable for A5 */ + __IOM uint32_t ENB5 : 1; /*!< [11..11] Alternate enable for B5 */ + __IOM uint32_t ENA6 : 1; /*!< [12..12] Alternate enable for A6 */ + __IOM uint32_t ENB6 : 1; /*!< [13..13] Alternate enable for B6 */ + __IOM uint32_t ENA7 : 1; /*!< [14..14] Alternate enable for A7 */ + __IOM uint32_t ENB7 : 1; /*!< [15..15] Alternate enable for B7. */ + } GLOBEN_b; + } ; + + union { + __IOM uint32_t OUTCFG0; /*!< (@ 0x00000104) Counter/Timer Output Config 0 */ + + struct { + __IOM uint32_t CFG0 : 3; /*!< [2..0] Pad output 0 configuration */ + __IOM uint32_t CFG1 : 3; /*!< [5..3] Pad output 1 configuration */ + __IOM uint32_t CFG2 : 3; /*!< [8..6] Pad output 2 configuration */ + __IOM uint32_t CFG3 : 3; /*!< [11..9] Pad output 3 configuration */ + __IOM uint32_t CFG4 : 3; /*!< [14..12] Pad output 4 configuration */ + __IM uint32_t : 1; + __IOM uint32_t CFG5 : 3; /*!< [18..16] Pad output 5 configuration */ + __IOM uint32_t CFG6 : 3; /*!< [21..19] Pad output 6 configuration */ + __IOM uint32_t CFG7 : 3; /*!< [24..22] Pad output 7 configuration */ + __IOM uint32_t CFG8 : 3; /*!< [27..25] Pad output 8 configuration */ + __IOM uint32_t CFG9 : 3; /*!< [30..28] Pad output 9 configuration */ + } OUTCFG0_b; + } ; + + union { + __IOM uint32_t OUTCFG1; /*!< (@ 0x00000108) Counter/Timer Output Config 1 */ + + struct { + __IOM uint32_t CFG10 : 3; /*!< [2..0] Pad output 10 configuration */ + __IOM uint32_t CFG11 : 3; /*!< [5..3] Pad output 11 configuration */ + __IOM uint32_t CFG12 : 3; /*!< [8..6] Pad output 12 configuration */ + __IOM uint32_t CFG13 : 3; /*!< [11..9] Pad output 13 configuration */ + __IOM uint32_t CFG14 : 3; /*!< [14..12] Pad output 14 configuration */ + __IM uint32_t : 1; + __IOM uint32_t CFG15 : 3; /*!< [18..16] Pad output 15 configuration */ + __IOM uint32_t CFG16 : 3; /*!< [21..19] Pad output 16 configuration */ + __IOM uint32_t CFG17 : 3; /*!< [24..22] Pad output 17 configuration */ + __IOM uint32_t CFG18 : 3; /*!< [27..25] Pad output 18 configuration */ + __IOM uint32_t CFG19 : 3; /*!< [30..28] Pad output 19 configuration */ + } OUTCFG1_b; + } ; + + union { + __IOM uint32_t OUTCFG2; /*!< (@ 0x0000010C) Counter/Timer Output Config 2 */ + + struct { + __IOM uint32_t CFG20 : 3; /*!< [2..0] Pad output 20 configuration */ + __IOM uint32_t CFG21 : 3; /*!< [5..3] Pad output 21 configuration */ + __IOM uint32_t CFG22 : 3; /*!< [8..6] Pad output 22 configuration */ + __IOM uint32_t CFG23 : 3; /*!< [11..9] Pad output 23 configuration */ + __IOM uint32_t CFG24 : 3; /*!< [14..12] Pad output 24 configuration */ + __IM uint32_t : 1; + __IOM uint32_t CFG25 : 3; /*!< [18..16] Pad output 25 configuration */ + __IOM uint32_t CFG26 : 3; /*!< [21..19] Pad output 26 configuration */ + __IOM uint32_t CFG27 : 3; /*!< [24..22] Pad output 27 configuration */ + __IOM uint32_t CFG28 : 3; /*!< [27..25] Pad output 28 configuration */ + __IOM uint32_t CFG29 : 3; /*!< [30..28] Pad output 29 configuration */ + } OUTCFG2_b; + } ; + __IM uint32_t RESERVED8; + + union { + __IOM uint32_t OUTCFG3; /*!< (@ 0x00000114) Counter/Timer Output Config 3 */ + + struct { + __IOM uint32_t CFG30 : 3; /*!< [2..0] Pad output 30 configuration */ + __IOM uint32_t CFG31 : 3; /*!< [5..3] Pad output 31 configuration */ + } OUTCFG3_b; + } ; + + union { + __IOM uint32_t INCFG; /*!< (@ 0x00000118) Counter/Timer Input Config */ + + struct { + __IOM uint32_t CFGA0 : 1; /*!< [0..0] CTIMER A0 input configuration */ + __IOM uint32_t CFGB0 : 1; /*!< [1..1] CTIMER B0 input configuration */ + __IOM uint32_t CFGA1 : 1; /*!< [2..2] CTIMER A1 input configuration */ + __IOM uint32_t CFGB1 : 1; /*!< [3..3] CTIMER B1 input configuration */ + __IOM uint32_t CFGA2 : 1; /*!< [4..4] CTIMER A2 input configuration */ + __IOM uint32_t CFGB2 : 1; /*!< [5..5] CTIMER B2 input configuration */ + __IOM uint32_t CFGA3 : 1; /*!< [6..6] CTIMER A3 input configuration */ + __IOM uint32_t CFGB3 : 1; /*!< [7..7] CTIMER B3 input configuration */ + __IOM uint32_t CFGA4 : 1; /*!< [8..8] CTIMER A4 input configuration */ + __IOM uint32_t CFGB4 : 1; /*!< [9..9] CTIMER B4 input configuration */ + __IOM uint32_t CFGA5 : 1; /*!< [10..10] CTIMER A5 input configuration */ + __IOM uint32_t CFGB5 : 1; /*!< [11..11] CTIMER B5 input configuration */ + __IOM uint32_t CFGA6 : 1; /*!< [12..12] CTIMER A6 input configuration */ + __IOM uint32_t CFGB6 : 1; /*!< [13..13] CTIMER B6 input configuration */ + __IOM uint32_t CFGA7 : 1; /*!< [14..14] CTIMER A7 input configuration */ + __IOM uint32_t CFGB7 : 1; /*!< [15..15] CTIMER B7 input configuration */ + } INCFG_b; + } ; + __IM uint32_t RESERVED9[9]; + + union { + __IOM uint32_t STCFG; /*!< (@ 0x00000140) Configuration Register */ + + struct { + __IOM uint32_t CLKSEL : 4; /*!< [3..0] Selects an appropriate clock source and divider to use + for the System Timer clock. */ + __IM uint32_t : 4; + __IOM uint32_t COMPARE_A_EN : 1; /*!< [8..8] Selects whether compare is enabled for the corresponding + SCMPR register. If compare is enabled, the interrupt status + is set once the comparision is met. */ + __IOM uint32_t COMPARE_B_EN : 1; /*!< [9..9] Selects whether compare is enabled for the corresponding + SCMPR register. If compare is enabled, the interrupt status + is set once the comparision is met. */ + __IOM uint32_t COMPARE_C_EN : 1; /*!< [10..10] Selects whether compare is enabled for the corresponding + SCMPR register. If compare is enabled, the interrupt status + is set once the comparision is met. */ + __IOM uint32_t COMPARE_D_EN : 1; /*!< [11..11] Selects whether compare is enabled for the corresponding + SCMPR register. If compare is enabled, the interrupt status + is set once the comparision is met. */ + __IOM uint32_t COMPARE_E_EN : 1; /*!< [12..12] Selects whether compare is enabled for the corresponding + SCMPR register. If compare is enabled, the interrupt status + is set once the comparision is met. */ + __IOM uint32_t COMPARE_F_EN : 1; /*!< [13..13] Selects whether compare is enabled for the corresponding + SCMPR register. If compare is enabled, the interrupt status + is set once the comparision is met. */ + __IOM uint32_t COMPARE_G_EN : 1; /*!< [14..14] Selects whether compare is enabled for the corresponding + SCMPR register. If compare is enabled, the interrupt status + is set once the comparision is met. */ + __IOM uint32_t COMPARE_H_EN : 1; /*!< [15..15] Selects whether compare is enabled for the corresponding + SCMPR register. If compare is enabled, the interrupt status + is set once the comparision is met. */ + __IM uint32_t : 14; + __IOM uint32_t CLEAR : 1; /*!< [30..30] Set this bit to one to clear the System Timer register. + If this bit is set to '1', the system timer register will + stay cleared. It needs to be set to '0' for the system + timer to start running. */ + __IOM uint32_t FREEZE : 1; /*!< [31..31] Set this bit to one to freeze the clock input to the + COUNTER register. Once frozen, the value can be safely + written from the MCU. Unfreeze to resume. */ + } STCFG_b; + } ; + + union { + __IOM uint32_t STTMR; /*!< (@ 0x00000144) System Timer Count Register (Real Time Counter) */ + + struct { + __IOM uint32_t STTMR : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ + } STTMR_b; + } ; + + union { + __IOM uint32_t CAPTURECONTROL; /*!< (@ 0x00000148) Capture Control Register */ + + struct { + __IOM uint32_t CAPTURE0 : 1; /*!< [0..0] Selects whether capture is enabled for the specified + capture register. */ + __IOM uint32_t CAPTURE1 : 1; /*!< [1..1] Selects whether capture is enabled for the specified + capture register. */ + __IOM uint32_t CAPTURE2 : 1; /*!< [2..2] Selects whether capture is enabled for the specified + capture register. */ + __IOM uint32_t CAPTURE3 : 1; /*!< [3..3] Selects whether capture is enabled for the specified + capture register. */ + } CAPTURECONTROL_b; + } ; + __IM uint32_t RESERVED10; + + union { + __IOM uint32_t SCMPR0; /*!< (@ 0x00000150) Compare Register A */ + + struct { + __IOM uint32_t SCMPR0 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register + according to the match criterion, as selected in the COMPARE_A_EN + bit in the REG_CTIMER_STCGF register. */ + } SCMPR0_b; + } ; + + union { + __IOM uint32_t SCMPR1; /*!< (@ 0x00000154) Compare Register B */ + + struct { + __IOM uint32_t SCMPR1 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register + according to the match criterion, as selected in the COMPARE_B_EN + bit in the REG_CTIMER_STCGF register. */ + } SCMPR1_b; + } ; + + union { + __IOM uint32_t SCMPR2; /*!< (@ 0x00000158) Compare Register C */ + + struct { + __IOM uint32_t SCMPR2 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register + according to the match criterion, as selected in the COMPARE_C_EN + bit in the REG_CTIMER_STCGF register. */ + } SCMPR2_b; + } ; + + union { + __IOM uint32_t SCMPR3; /*!< (@ 0x0000015C) Compare Register D */ + + struct { + __IOM uint32_t SCMPR3 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register + according to the match criterion, as selected in the COMPARE_D_EN + bit in the REG_CTIMER_STCGF register. */ + } SCMPR3_b; + } ; + + union { + __IOM uint32_t SCMPR4; /*!< (@ 0x00000160) Compare Register E */ + + struct { + __IOM uint32_t SCMPR4 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register + according to the match criterion, as selected in the COMPARE_E_EN + bit in the REG_CTIMER_STCGF register. */ + } SCMPR4_b; + } ; + + union { + __IOM uint32_t SCMPR5; /*!< (@ 0x00000164) Compare Register F */ + + struct { + __IOM uint32_t SCMPR5 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register + according to the match criterion, as selected in the COMPARE_F_EN + bit in the REG_CTIMER_STCGF register. */ + } SCMPR5_b; + } ; + + union { + __IOM uint32_t SCMPR6; /*!< (@ 0x00000168) Compare Register G */ + + struct { + __IOM uint32_t SCMPR6 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register + according to the match criterion, as selected in the COMPARE_G_EN + bit in the REG_CTIMER_STCGF register. */ + } SCMPR6_b; + } ; + + union { + __IOM uint32_t SCMPR7; /*!< (@ 0x0000016C) Compare Register H */ + + struct { + __IOM uint32_t SCMPR7 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register + according to the match criterion, as selected in the COMPARE_H_EN + bit in the REG_CTIMER_STCGF register. */ + } SCMPR7_b; + } ; + __IM uint32_t RESERVED11[28]; + + union { + __IOM uint32_t SCAPT0; /*!< (@ 0x000001E0) Capture Register A */ + + struct { + __IOM uint32_t SCAPT0 : 32; /*!< [31..0] Whenever the event is detected, the value in the COUNTER + is copied into this register and the corresponding interrupt + status bit is set. */ + } SCAPT0_b; + } ; + + union { + __IOM uint32_t SCAPT1; /*!< (@ 0x000001E4) Capture Register B */ + + struct { + __IOM uint32_t SCAPT1 : 32; /*!< [31..0] Whenever the event is detected, the value in the COUNTER + is copied into this register and the corresponding interrupt + status bit is set. */ + } SCAPT1_b; + } ; + + union { + __IOM uint32_t SCAPT2; /*!< (@ 0x000001E8) Capture Register C */ + + struct { + __IOM uint32_t SCAPT2 : 32; /*!< [31..0] Whenever the event is detected, the value in the COUNTER + is copied into this register and the corresponding interrupt + status bit is set. */ + } SCAPT2_b; + } ; + + union { + __IOM uint32_t SCAPT3; /*!< (@ 0x000001EC) Capture Register D */ + + struct { + __IOM uint32_t SCAPT3 : 32; /*!< [31..0] Whenever the event is detected, the value in the COUNTER + is copied into this register and the corresponding interrupt + status bit is set. */ + } SCAPT3_b; + } ; + + union { + __IOM uint32_t SNVR0; /*!< (@ 0x000001F0) System Timer NVRAM_A Register */ + + struct { + __IOM uint32_t SNVR0 : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ + } SNVR0_b; + } ; + + union { + __IOM uint32_t SNVR1; /*!< (@ 0x000001F4) System Timer NVRAM_B Register */ + + struct { + __IOM uint32_t SNVR1 : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ + } SNVR1_b; + } ; + + union { + __IOM uint32_t SNVR2; /*!< (@ 0x000001F8) System Timer NVRAM_C Register */ + + struct { + __IOM uint32_t SNVR2 : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ + } SNVR2_b; + } ; + + union { + __IOM uint32_t SNVR3; /*!< (@ 0x000001FC) System Timer NVRAM_D Register */ + + struct { + __IOM uint32_t SNVR3 : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ + } SNVR3_b; + } ; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000200) Counter/Timer Interrupts: Enable */ + + struct { + __IOM uint32_t CTMRA0C0INT : 1; /*!< [0..0] Counter/Timer A0 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB0C0INT : 1; /*!< [1..1] Counter/Timer B0 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA1C0INT : 1; /*!< [2..2] Counter/Timer A1 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB1C0INT : 1; /*!< [3..3] Counter/Timer B1 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA2C0INT : 1; /*!< [4..4] Counter/Timer A2 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB2C0INT : 1; /*!< [5..5] Counter/Timer B2 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA3C0INT : 1; /*!< [6..6] Counter/Timer A3 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB3C0INT : 1; /*!< [7..7] Counter/Timer B3 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA4C0INT : 1; /*!< [8..8] Counter/Timer A4 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB4C0INT : 1; /*!< [9..9] Counter/Timer B4 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA5C0INT : 1; /*!< [10..10] Counter/Timer A5 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB5C0INT : 1; /*!< [11..11] Counter/Timer B5 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA6C0INT : 1; /*!< [12..12] Counter/Timer A6 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB6C0INT : 1; /*!< [13..13] Counter/Timer B6 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA7C0INT : 1; /*!< [14..14] Counter/Timer A7 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB7C0INT : 1; /*!< [15..15] Counter/Timer B7 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA0C1INT : 1; /*!< [16..16] Counter/Timer A0 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB0C1INT : 1; /*!< [17..17] Counter/Timer B0 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA1C1INT : 1; /*!< [18..18] Counter/Timer A1 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB1C1INT : 1; /*!< [19..19] Counter/Timer B1 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA2C1INT : 1; /*!< [20..20] Counter/Timer A2 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB2C1INT : 1; /*!< [21..21] Counter/Timer B2 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA3C1INT : 1; /*!< [22..22] Counter/Timer A3 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB3C1INT : 1; /*!< [23..23] Counter/Timer B3 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA4C1INT : 1; /*!< [24..24] Counter/Timer A4 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB4C1INT : 1; /*!< [25..25] Counter/Timer B4 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA5C1INT : 1; /*!< [26..26] Counter/Timer A5 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB5C1INT : 1; /*!< [27..27] Counter/Timer B5 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA6C1INT : 1; /*!< [28..28] Counter/Timer A6 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB6C1INT : 1; /*!< [29..29] Counter/Timer B6 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA7C1INT : 1; /*!< [30..30] Counter/Timer A7 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB7C1INT : 1; /*!< [31..31] Counter/Timer B7 interrupt based on COMPR1. */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) Counter/Timer Interrupts: Status */ + + struct { + __IOM uint32_t CTMRA0C0INT : 1; /*!< [0..0] Counter/Timer A0 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB0C0INT : 1; /*!< [1..1] Counter/Timer B0 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA1C0INT : 1; /*!< [2..2] Counter/Timer A1 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB1C0INT : 1; /*!< [3..3] Counter/Timer B1 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA2C0INT : 1; /*!< [4..4] Counter/Timer A2 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB2C0INT : 1; /*!< [5..5] Counter/Timer B2 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA3C0INT : 1; /*!< [6..6] Counter/Timer A3 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB3C0INT : 1; /*!< [7..7] Counter/Timer B3 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA4C0INT : 1; /*!< [8..8] Counter/Timer A4 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB4C0INT : 1; /*!< [9..9] Counter/Timer B4 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA5C0INT : 1; /*!< [10..10] Counter/Timer A5 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB5C0INT : 1; /*!< [11..11] Counter/Timer B5 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA6C0INT : 1; /*!< [12..12] Counter/Timer A6 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB6C0INT : 1; /*!< [13..13] Counter/Timer B6 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA7C0INT : 1; /*!< [14..14] Counter/Timer A7 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB7C0INT : 1; /*!< [15..15] Counter/Timer B7 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA0C1INT : 1; /*!< [16..16] Counter/Timer A0 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB0C1INT : 1; /*!< [17..17] Counter/Timer B0 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA1C1INT : 1; /*!< [18..18] Counter/Timer A1 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB1C1INT : 1; /*!< [19..19] Counter/Timer B1 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA2C1INT : 1; /*!< [20..20] Counter/Timer A2 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB2C1INT : 1; /*!< [21..21] Counter/Timer B2 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA3C1INT : 1; /*!< [22..22] Counter/Timer A3 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB3C1INT : 1; /*!< [23..23] Counter/Timer B3 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA4C1INT : 1; /*!< [24..24] Counter/Timer A4 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB4C1INT : 1; /*!< [25..25] Counter/Timer B4 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA5C1INT : 1; /*!< [26..26] Counter/Timer A5 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB5C1INT : 1; /*!< [27..27] Counter/Timer B5 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA6C1INT : 1; /*!< [28..28] Counter/Timer A6 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB6C1INT : 1; /*!< [29..29] Counter/Timer B6 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA7C1INT : 1; /*!< [30..30] Counter/Timer A7 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB7C1INT : 1; /*!< [31..31] Counter/Timer B7 interrupt based on COMPR1. */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000208) Counter/Timer Interrupts: Clear */ + + struct { + __IOM uint32_t CTMRA0C0INT : 1; /*!< [0..0] Counter/Timer A0 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB0C0INT : 1; /*!< [1..1] Counter/Timer B0 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA1C0INT : 1; /*!< [2..2] Counter/Timer A1 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB1C0INT : 1; /*!< [3..3] Counter/Timer B1 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA2C0INT : 1; /*!< [4..4] Counter/Timer A2 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB2C0INT : 1; /*!< [5..5] Counter/Timer B2 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA3C0INT : 1; /*!< [6..6] Counter/Timer A3 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB3C0INT : 1; /*!< [7..7] Counter/Timer B3 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA4C0INT : 1; /*!< [8..8] Counter/Timer A4 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB4C0INT : 1; /*!< [9..9] Counter/Timer B4 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA5C0INT : 1; /*!< [10..10] Counter/Timer A5 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB5C0INT : 1; /*!< [11..11] Counter/Timer B5 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA6C0INT : 1; /*!< [12..12] Counter/Timer A6 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB6C0INT : 1; /*!< [13..13] Counter/Timer B6 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA7C0INT : 1; /*!< [14..14] Counter/Timer A7 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB7C0INT : 1; /*!< [15..15] Counter/Timer B7 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA0C1INT : 1; /*!< [16..16] Counter/Timer A0 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB0C1INT : 1; /*!< [17..17] Counter/Timer B0 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA1C1INT : 1; /*!< [18..18] Counter/Timer A1 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB1C1INT : 1; /*!< [19..19] Counter/Timer B1 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA2C1INT : 1; /*!< [20..20] Counter/Timer A2 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB2C1INT : 1; /*!< [21..21] Counter/Timer B2 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA3C1INT : 1; /*!< [22..22] Counter/Timer A3 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB3C1INT : 1; /*!< [23..23] Counter/Timer B3 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA4C1INT : 1; /*!< [24..24] Counter/Timer A4 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB4C1INT : 1; /*!< [25..25] Counter/Timer B4 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA5C1INT : 1; /*!< [26..26] Counter/Timer A5 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB5C1INT : 1; /*!< [27..27] Counter/Timer B5 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA6C1INT : 1; /*!< [28..28] Counter/Timer A6 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB6C1INT : 1; /*!< [29..29] Counter/Timer B6 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA7C1INT : 1; /*!< [30..30] Counter/Timer A7 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB7C1INT : 1; /*!< [31..31] Counter/Timer B7 interrupt based on COMPR1. */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000020C) Counter/Timer Interrupts: Set */ + + struct { + __IOM uint32_t CTMRA0C0INT : 1; /*!< [0..0] Counter/Timer A0 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB0C0INT : 1; /*!< [1..1] Counter/Timer B0 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA1C0INT : 1; /*!< [2..2] Counter/Timer A1 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB1C0INT : 1; /*!< [3..3] Counter/Timer B1 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA2C0INT : 1; /*!< [4..4] Counter/Timer A2 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB2C0INT : 1; /*!< [5..5] Counter/Timer B2 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA3C0INT : 1; /*!< [6..6] Counter/Timer A3 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB3C0INT : 1; /*!< [7..7] Counter/Timer B3 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA4C0INT : 1; /*!< [8..8] Counter/Timer A4 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB4C0INT : 1; /*!< [9..9] Counter/Timer B4 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA5C0INT : 1; /*!< [10..10] Counter/Timer A5 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB5C0INT : 1; /*!< [11..11] Counter/Timer B5 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA6C0INT : 1; /*!< [12..12] Counter/Timer A6 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB6C0INT : 1; /*!< [13..13] Counter/Timer B6 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA7C0INT : 1; /*!< [14..14] Counter/Timer A7 interrupt based on COMPR0. */ + __IOM uint32_t CTMRB7C0INT : 1; /*!< [15..15] Counter/Timer B7 interrupt based on COMPR0. */ + __IOM uint32_t CTMRA0C1INT : 1; /*!< [16..16] Counter/Timer A0 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB0C1INT : 1; /*!< [17..17] Counter/Timer B0 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA1C1INT : 1; /*!< [18..18] Counter/Timer A1 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB1C1INT : 1; /*!< [19..19] Counter/Timer B1 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA2C1INT : 1; /*!< [20..20] Counter/Timer A2 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB2C1INT : 1; /*!< [21..21] Counter/Timer B2 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA3C1INT : 1; /*!< [22..22] Counter/Timer A3 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB3C1INT : 1; /*!< [23..23] Counter/Timer B3 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA4C1INT : 1; /*!< [24..24] Counter/Timer A4 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB4C1INT : 1; /*!< [25..25] Counter/Timer B4 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA5C1INT : 1; /*!< [26..26] Counter/Timer A5 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB5C1INT : 1; /*!< [27..27] Counter/Timer B5 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA6C1INT : 1; /*!< [28..28] Counter/Timer A6 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB6C1INT : 1; /*!< [29..29] Counter/Timer B6 interrupt based on COMPR1. */ + __IOM uint32_t CTMRA7C1INT : 1; /*!< [30..30] Counter/Timer A7 interrupt based on COMPR1. */ + __IOM uint32_t CTMRB7C1INT : 1; /*!< [31..31] Counter/Timer B7 interrupt based on COMPR1. */ + } INTSET_b; + } ; + __IM uint32_t RESERVED12[60]; + + union { + __IOM uint32_t STMINTEN; /*!< (@ 0x00000300) STIMER Interrupt registers: Enable */ + + struct { + __IOM uint32_t COMPAREA : 1; /*!< [0..0] COUNTER is greater than or equal to COMPARE register + A. */ + __IOM uint32_t COMPAREB : 1; /*!< [1..1] COUNTER is greater than or equal to COMPARE register + B. */ + __IOM uint32_t COMPAREC : 1; /*!< [2..2] COUNTER is greater than or equal to COMPARE register + C. */ + __IOM uint32_t COMPARED : 1; /*!< [3..3] COUNTER is greater than or equal to COMPARE register + D. */ + __IOM uint32_t COMPAREE : 1; /*!< [4..4] COUNTER is greater than or equal to COMPARE register + E. */ + __IOM uint32_t COMPAREF : 1; /*!< [5..5] COUNTER is greater than or equal to COMPARE register + F. */ + __IOM uint32_t COMPAREG : 1; /*!< [6..6] COUNTER is greater than or equal to COMPARE register + G. */ + __IOM uint32_t COMPAREH : 1; /*!< [7..7] COUNTER is greater than or equal to COMPARE register + H. */ + __IOM uint32_t OVERFLOW : 1; /*!< [8..8] COUNTER over flowed from 0xFFFFFFFF back to 0x00000000. */ + __IOM uint32_t CAPTUREA : 1; /*!< [9..9] CAPTURE register A has grabbed the value in the counter */ + __IOM uint32_t CAPTUREB : 1; /*!< [10..10] CAPTURE register B has grabbed the value in the counter */ + __IOM uint32_t CAPTUREC : 1; /*!< [11..11] CAPTURE register C has grabbed the value in the counter */ + __IOM uint32_t CAPTURED : 1; /*!< [12..12] CAPTURE register D has grabbed the value in the counter */ + } STMINTEN_b; + } ; + + union { + __IOM uint32_t STMINTSTAT; /*!< (@ 0x00000304) STIMER Interrupt registers: Status */ + + struct { + __IOM uint32_t COMPAREA : 1; /*!< [0..0] COUNTER is greater than or equal to COMPARE register + A. */ + __IOM uint32_t COMPAREB : 1; /*!< [1..1] COUNTER is greater than or equal to COMPARE register + B. */ + __IOM uint32_t COMPAREC : 1; /*!< [2..2] COUNTER is greater than or equal to COMPARE register + C. */ + __IOM uint32_t COMPARED : 1; /*!< [3..3] COUNTER is greater than or equal to COMPARE register + D. */ + __IOM uint32_t COMPAREE : 1; /*!< [4..4] COUNTER is greater than or equal to COMPARE register + E. */ + __IOM uint32_t COMPAREF : 1; /*!< [5..5] COUNTER is greater than or equal to COMPARE register + F. */ + __IOM uint32_t COMPAREG : 1; /*!< [6..6] COUNTER is greater than or equal to COMPARE register + G. */ + __IOM uint32_t COMPAREH : 1; /*!< [7..7] COUNTER is greater than or equal to COMPARE register + H. */ + __IOM uint32_t OVERFLOW : 1; /*!< [8..8] COUNTER over flowed from 0xFFFFFFFF back to 0x00000000. */ + __IOM uint32_t CAPTUREA : 1; /*!< [9..9] CAPTURE register A has grabbed the value in the counter */ + __IOM uint32_t CAPTUREB : 1; /*!< [10..10] CAPTURE register B has grabbed the value in the counter */ + __IOM uint32_t CAPTUREC : 1; /*!< [11..11] CAPTURE register C has grabbed the value in the counter */ + __IOM uint32_t CAPTURED : 1; /*!< [12..12] CAPTURE register D has grabbed the value in the counter */ + } STMINTSTAT_b; + } ; + + union { + __IOM uint32_t STMINTCLR; /*!< (@ 0x00000308) STIMER Interrupt registers: Clear */ + + struct { + __IOM uint32_t COMPAREA : 1; /*!< [0..0] COUNTER is greater than or equal to COMPARE register + A. */ + __IOM uint32_t COMPAREB : 1; /*!< [1..1] COUNTER is greater than or equal to COMPARE register + B. */ + __IOM uint32_t COMPAREC : 1; /*!< [2..2] COUNTER is greater than or equal to COMPARE register + C. */ + __IOM uint32_t COMPARED : 1; /*!< [3..3] COUNTER is greater than or equal to COMPARE register + D. */ + __IOM uint32_t COMPAREE : 1; /*!< [4..4] COUNTER is greater than or equal to COMPARE register + E. */ + __IOM uint32_t COMPAREF : 1; /*!< [5..5] COUNTER is greater than or equal to COMPARE register + F. */ + __IOM uint32_t COMPAREG : 1; /*!< [6..6] COUNTER is greater than or equal to COMPARE register + G. */ + __IOM uint32_t COMPAREH : 1; /*!< [7..7] COUNTER is greater than or equal to COMPARE register + H. */ + __IOM uint32_t OVERFLOW : 1; /*!< [8..8] COUNTER over flowed from 0xFFFFFFFF back to 0x00000000. */ + __IOM uint32_t CAPTUREA : 1; /*!< [9..9] CAPTURE register A has grabbed the value in the counter */ + __IOM uint32_t CAPTUREB : 1; /*!< [10..10] CAPTURE register B has grabbed the value in the counter */ + __IOM uint32_t CAPTUREC : 1; /*!< [11..11] CAPTURE register C has grabbed the value in the counter */ + __IOM uint32_t CAPTURED : 1; /*!< [12..12] CAPTURE register D has grabbed the value in the counter */ + } STMINTCLR_b; + } ; + + union { + __IOM uint32_t STMINTSET; /*!< (@ 0x0000030C) STIMER Interrupt registers: Set */ + + struct { + __IOM uint32_t COMPAREA : 1; /*!< [0..0] COUNTER is greater than or equal to COMPARE register + A. */ + __IOM uint32_t COMPAREB : 1; /*!< [1..1] COUNTER is greater than or equal to COMPARE register + B. */ + __IOM uint32_t COMPAREC : 1; /*!< [2..2] COUNTER is greater than or equal to COMPARE register + C. */ + __IOM uint32_t COMPARED : 1; /*!< [3..3] COUNTER is greater than or equal to COMPARE register + D. */ + __IOM uint32_t COMPAREE : 1; /*!< [4..4] COUNTER is greater than or equal to COMPARE register + E. */ + __IOM uint32_t COMPAREF : 1; /*!< [5..5] COUNTER is greater than or equal to COMPARE register + F. */ + __IOM uint32_t COMPAREG : 1; /*!< [6..6] COUNTER is greater than or equal to COMPARE register + G. */ + __IOM uint32_t COMPAREH : 1; /*!< [7..7] COUNTER is greater than or equal to COMPARE register + H. */ + __IOM uint32_t OVERFLOW : 1; /*!< [8..8] COUNTER over flowed from 0xFFFFFFFF back to 0x00000000. */ + __IOM uint32_t CAPTUREA : 1; /*!< [9..9] CAPTURE register A has grabbed the value in the counter */ + __IOM uint32_t CAPTUREB : 1; /*!< [10..10] CAPTURE register B has grabbed the value in the counter */ + __IOM uint32_t CAPTUREC : 1; /*!< [11..11] CAPTURE register C has grabbed the value in the counter */ + __IOM uint32_t CAPTURED : 1; /*!< [12..12] CAPTURE register D has grabbed the value in the counter */ + } STMINTSET_b; + } ; +} CTIMER_Type; /*!< Size = 784 (0x310) */ + + + +/* =========================================================================================================================== */ +/* ================ GPIO ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief General Purpose IO (GPIO) + */ + +typedef struct { /*!< (@ 0x40010000) GPIO Structure */ + + union { + __IOM uint32_t PADREGA; /*!< (@ 0x00000000) Pad Configuration Register A (Pads 0-3) */ + + struct { + __IOM uint32_t PAD0PULL : 1; /*!< [0..0] Pad 0 pullup enable */ + __IOM uint32_t PAD0INPEN : 1; /*!< [1..1] Pad 0 input enable */ + __IOM uint32_t PAD0STRNG : 1; /*!< [2..2] Pad 0 drive strength */ + __IOM uint32_t PAD0FNCSEL : 3; /*!< [5..3] Pad 0 function select */ + __IOM uint32_t PAD0RSEL : 2; /*!< [7..6] Pad 0 pullup resistor selection. */ + __IOM uint32_t PAD1PULL : 1; /*!< [8..8] Pad 1 pullup enable */ + __IOM uint32_t PAD1INPEN : 1; /*!< [9..9] Pad 1 input enable */ + __IOM uint32_t PAD1STRNG : 1; /*!< [10..10] Pad 1 drive strength */ + __IOM uint32_t PAD1FNCSEL : 3; /*!< [13..11] Pad 1 function select */ + __IOM uint32_t PAD1RSEL : 2; /*!< [15..14] Pad 1 pullup resistor selection. */ + __IOM uint32_t PAD2PULL : 1; /*!< [16..16] Pad 2 pullup enable */ + __IOM uint32_t PAD2INPEN : 1; /*!< [17..17] Pad 2 input enable */ + __IOM uint32_t PAD2STRNG : 1; /*!< [18..18] Pad 2 drive strength */ + __IOM uint32_t PAD2FNCSEL : 3; /*!< [21..19] Pad 2 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD3PULL : 1; /*!< [24..24] Pad 3 pullup enable */ + __IOM uint32_t PAD3INPEN : 1; /*!< [25..25] Pad 3 input enable. */ + __IOM uint32_t PAD3STRNG : 1; /*!< [26..26] Pad 3 drive strength. */ + __IOM uint32_t PAD3FNCSEL : 3; /*!< [29..27] Pad 3 function select */ + __IOM uint32_t PAD3PWRUP : 1; /*!< [30..30] Pad 3 VDD power switch enable */ + } PADREGA_b; + } ; + + union { + __IOM uint32_t PADREGB; /*!< (@ 0x00000004) Pad Configuration Register B (Pads 4-7) */ + + struct { + __IOM uint32_t PAD4PULL : 1; /*!< [0..0] Pad 4 pullup enable */ + __IOM uint32_t PAD4INPEN : 1; /*!< [1..1] Pad 4 input enable */ + __IOM uint32_t PAD4STRNG : 1; /*!< [2..2] Pad 4 drive strength */ + __IOM uint32_t PAD4FNCSEL : 3; /*!< [5..3] Pad 4 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD5PULL : 1; /*!< [8..8] Pad 5 pullup enable */ + __IOM uint32_t PAD5INPEN : 1; /*!< [9..9] Pad 5 input enable */ + __IOM uint32_t PAD5STRNG : 1; /*!< [10..10] Pad 5 drive strength */ + __IOM uint32_t PAD5FNCSEL : 3; /*!< [13..11] Pad 5 function select */ + __IOM uint32_t PAD5RSEL : 2; /*!< [15..14] Pad 5 pullup resistor selection. */ + __IOM uint32_t PAD6PULL : 1; /*!< [16..16] Pad 6 pullup enable */ + __IOM uint32_t PAD6INPEN : 1; /*!< [17..17] Pad 6 input enable */ + __IOM uint32_t PAD6STRNG : 1; /*!< [18..18] Pad 6 drive strength */ + __IOM uint32_t PAD6FNCSEL : 3; /*!< [21..19] Pad 6 function select */ + __IOM uint32_t PAD6RSEL : 2; /*!< [23..22] Pad 6 pullup resistor selection. */ + __IOM uint32_t PAD7PULL : 1; /*!< [24..24] Pad 7 pullup enable */ + __IOM uint32_t PAD7INPEN : 1; /*!< [25..25] Pad 7 input enable */ + __IOM uint32_t PAD7STRNG : 1; /*!< [26..26] Pad 7 drive strength */ + __IOM uint32_t PAD7FNCSEL : 3; /*!< [29..27] Pad 7 function select */ + } PADREGB_b; + } ; + + union { + __IOM uint32_t PADREGC; /*!< (@ 0x00000008) Pad Configuration Register C (Pads 8-11) */ + + struct { + __IOM uint32_t PAD8PULL : 1; /*!< [0..0] Pad 8 pullup enable */ + __IOM uint32_t PAD8INPEN : 1; /*!< [1..1] Pad 8 input enable */ + __IOM uint32_t PAD8STRNG : 1; /*!< [2..2] Pad 8 drive strength */ + __IOM uint32_t PAD8FNCSEL : 3; /*!< [5..3] Pad 8 function select */ + __IOM uint32_t PAD8RSEL : 2; /*!< [7..6] Pad 8 pullup resistor selection. */ + __IOM uint32_t PAD9PULL : 1; /*!< [8..8] Pad 9 pullup enable */ + __IOM uint32_t PAD9INPEN : 1; /*!< [9..9] Pad 9 input enable */ + __IOM uint32_t PAD9STRNG : 1; /*!< [10..10] Pad 9 drive strength */ + __IOM uint32_t PAD9FNCSEL : 3; /*!< [13..11] Pad 9 function select */ + __IOM uint32_t PAD9RSEL : 2; /*!< [15..14] Pad 9 pullup resistor selection */ + __IOM uint32_t PAD10PULL : 1; /*!< [16..16] Pad 10 pullup enable */ + __IOM uint32_t PAD10INPEN : 1; /*!< [17..17] Pad 10 input enable */ + __IOM uint32_t PAD10STRNG : 1; /*!< [18..18] Pad 10 drive strength */ + __IOM uint32_t PAD10FNCSEL : 3; /*!< [21..19] Pad 10 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD11PULL : 1; /*!< [24..24] Pad 11 pullup enable */ + __IOM uint32_t PAD11INPEN : 1; /*!< [25..25] Pad 11 input enable */ + __IOM uint32_t PAD11STRNG : 1; /*!< [26..26] Pad 11 drive strength */ + __IOM uint32_t PAD11FNCSEL : 3; /*!< [29..27] Pad 11 function select */ + } PADREGC_b; + } ; + + union { + __IOM uint32_t PADREGD; /*!< (@ 0x0000000C) Pad Configuration Register D (Pads 12-15) */ + + struct { + __IOM uint32_t PAD12PULL : 1; /*!< [0..0] Pad 12 pullup enable */ + __IOM uint32_t PAD12INPEN : 1; /*!< [1..1] Pad 12 input enable */ + __IOM uint32_t PAD12STRNG : 1; /*!< [2..2] Pad 12 drive strength */ + __IOM uint32_t PAD12FNCSEL : 3; /*!< [5..3] Pad 12 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD13PULL : 1; /*!< [8..8] Pad 13 pullup enable */ + __IOM uint32_t PAD13INPEN : 1; /*!< [9..9] Pad 13 input enable */ + __IOM uint32_t PAD13STRNG : 1; /*!< [10..10] Pad 13 drive strength */ + __IOM uint32_t PAD13FNCSEL : 3; /*!< [13..11] Pad 13 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD14PULL : 1; /*!< [16..16] Pad 14 pullup enable */ + __IOM uint32_t PAD14INPEN : 1; /*!< [17..17] Pad 14 input enable */ + __IOM uint32_t PAD14STRNG : 1; /*!< [18..18] Pad 14 drive strength */ + __IOM uint32_t PAD14FNCSEL : 3; /*!< [21..19] Pad 14 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD15PULL : 1; /*!< [24..24] Pad 15 pullup enable */ + __IOM uint32_t PAD15INPEN : 1; /*!< [25..25] Pad 15 input enable */ + __IOM uint32_t PAD15STRNG : 1; /*!< [26..26] Pad 15 drive strength */ + __IOM uint32_t PAD15FNCSEL : 3; /*!< [29..27] Pad 15 function select */ + } PADREGD_b; + } ; + + union { + __IOM uint32_t PADREGE; /*!< (@ 0x00000010) Pad Configuration Register E (Pads 16-19) */ + + struct { + __IOM uint32_t PAD16PULL : 1; /*!< [0..0] Pad 16 pullup enable */ + __IOM uint32_t PAD16INPEN : 1; /*!< [1..1] Pad 16 input enable */ + __IOM uint32_t PAD16STRNG : 1; /*!< [2..2] Pad 16 drive strength */ + __IOM uint32_t PAD16FNCSEL : 3; /*!< [5..3] Pad 16 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD17PULL : 1; /*!< [8..8] Pad 17 pullup enable */ + __IOM uint32_t PAD17INPEN : 1; /*!< [9..9] Pad 17 input enable */ + __IOM uint32_t PAD17STRNG : 1; /*!< [10..10] Pad 17 drive strength */ + __IOM uint32_t PAD17FNCSEL : 3; /*!< [13..11] Pad 17 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD18PULL : 1; /*!< [16..16] Pad 18 pullup enable */ + __IOM uint32_t PAD18INPEN : 1; /*!< [17..17] Pad 18 input enable */ + __IOM uint32_t PAD18STRNG : 1; /*!< [18..18] Pad 18 drive strength */ + __IOM uint32_t PAD18FNCSEL : 3; /*!< [21..19] Pad 18 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD19PULL : 1; /*!< [24..24] Pad 19 pullup enable */ + __IOM uint32_t PAD19INPEN : 1; /*!< [25..25] Pad 19 input enable */ + __IOM uint32_t PAD19STRNG : 1; /*!< [26..26] Pad 19 drive strength */ + __IOM uint32_t PAD19FNCSEL : 3; /*!< [29..27] Pad 19 function select */ + } PADREGE_b; + } ; + + union { + __IOM uint32_t PADREGF; /*!< (@ 0x00000014) Pad Configuration Register F (Pads 20-23) */ + + struct { + __IOM uint32_t PAD20PULL : 1; /*!< [0..0] Pad 20 pulldown enable */ + __IOM uint32_t PAD20INPEN : 1; /*!< [1..1] Pad 20 input enable */ + __IOM uint32_t PAD20STRNG : 1; /*!< [2..2] Pad 20 drive strength */ + __IOM uint32_t PAD20FNCSEL : 3; /*!< [5..3] Pad 20 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD21PULL : 1; /*!< [8..8] Pad 21 pullup enable */ + __IOM uint32_t PAD21INPEN : 1; /*!< [9..9] Pad 21 input enable */ + __IOM uint32_t PAD21STRNG : 1; /*!< [10..10] Pad 21 drive strength */ + __IOM uint32_t PAD21FNCSEL : 3; /*!< [13..11] Pad 21 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD22PULL : 1; /*!< [16..16] Pad 22 pullup enable */ + __IOM uint32_t PAD22INPEN : 1; /*!< [17..17] Pad 22 input enable */ + __IOM uint32_t PAD22STRNG : 1; /*!< [18..18] Pad 22 drive strength */ + __IOM uint32_t PAD22FNCSEL : 3; /*!< [21..19] Pad 22 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD23PULL : 1; /*!< [24..24] Pad 23 pullup enable */ + __IOM uint32_t PAD23INPEN : 1; /*!< [25..25] Pad 23 input enable */ + __IOM uint32_t PAD23STRNG : 1; /*!< [26..26] Pad 23 drive strength */ + __IOM uint32_t PAD23FNCSEL : 3; /*!< [29..27] Pad 23 function select */ + } PADREGF_b; + } ; + + union { + __IOM uint32_t PADREGG; /*!< (@ 0x00000018) Pad Configuration Register G (Pads 24-27) */ + + struct { + __IOM uint32_t PAD24PULL : 1; /*!< [0..0] Pad 24 pullup enable */ + __IOM uint32_t PAD24INPEN : 1; /*!< [1..1] Pad 24 input enable */ + __IOM uint32_t PAD24STRNG : 1; /*!< [2..2] Pad 24 drive strength */ + __IOM uint32_t PAD24FNCSEL : 3; /*!< [5..3] Pad 24 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD25PULL : 1; /*!< [8..8] Pad 25 pullup enable */ + __IOM uint32_t PAD25INPEN : 1; /*!< [9..9] Pad 25 input enable */ + __IOM uint32_t PAD25STRNG : 1; /*!< [10..10] Pad 25 drive strength */ + __IOM uint32_t PAD25FNCSEL : 3; /*!< [13..11] Pad 25 function select */ + __IOM uint32_t PAD25RSEL : 2; /*!< [15..14] Pad 25 pullup resistor selection. */ + __IOM uint32_t PAD26PULL : 1; /*!< [16..16] Pad 26 pullup enable */ + __IOM uint32_t PAD26INPEN : 1; /*!< [17..17] Pad 26 input enable */ + __IOM uint32_t PAD26STRNG : 1; /*!< [18..18] Pad 26 drive strength */ + __IOM uint32_t PAD26FNCSEL : 3; /*!< [21..19] Pad 26 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD27PULL : 1; /*!< [24..24] Pad 27 pullup enable */ + __IOM uint32_t PAD27INPEN : 1; /*!< [25..25] Pad 27 input enable */ + __IOM uint32_t PAD27STRNG : 1; /*!< [26..26] Pad 27 drive strength */ + __IOM uint32_t PAD27FNCSEL : 3; /*!< [29..27] Pad 27 function select */ + __IOM uint32_t PAD27RSEL : 2; /*!< [31..30] Pad 27 pullup resistor selection. */ + } PADREGG_b; + } ; + + union { + __IOM uint32_t PADREGH; /*!< (@ 0x0000001C) Pad Configuration Register H (Pads 28-31) */ + + struct { + __IOM uint32_t PAD28PULL : 1; /*!< [0..0] Pad 28 pullup enable */ + __IOM uint32_t PAD28INPEN : 1; /*!< [1..1] Pad 28 input enable */ + __IOM uint32_t PAD28STRNG : 1; /*!< [2..2] Pad 28 drive strength */ + __IOM uint32_t PAD28FNCSEL : 3; /*!< [5..3] Pad 28 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD29PULL : 1; /*!< [8..8] Pad 29 pullup enable */ + __IOM uint32_t PAD29INPEN : 1; /*!< [9..9] Pad 29 input enable */ + __IOM uint32_t PAD29STRNG : 1; /*!< [10..10] Pad 29 drive strength */ + __IOM uint32_t PAD29FNCSEL : 3; /*!< [13..11] Pad 29 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD30PULL : 1; /*!< [16..16] Pad 30 pullup enable */ + __IOM uint32_t PAD30INPEN : 1; /*!< [17..17] Pad 30 input enable */ + __IOM uint32_t PAD30STRNG : 1; /*!< [18..18] Pad 30 drive strength */ + __IOM uint32_t PAD30FNCSEL : 3; /*!< [21..19] Pad 30 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD31PULL : 1; /*!< [24..24] Pad 31 pullup enable */ + __IOM uint32_t PAD31INPEN : 1; /*!< [25..25] Pad 31 input enable */ + __IOM uint32_t PAD31STRNG : 1; /*!< [26..26] Pad 31 drive strength */ + __IOM uint32_t PAD31FNCSEL : 3; /*!< [29..27] Pad 31 function select */ + } PADREGH_b; + } ; + + union { + __IOM uint32_t PADREGI; /*!< (@ 0x00000020) Pad Configuration Register I (Pads 32-25) */ + + struct { + __IOM uint32_t PAD32PULL : 1; /*!< [0..0] Pad 32 pullup enable */ + __IOM uint32_t PAD32INPEN : 1; /*!< [1..1] Pad 32 input enable */ + __IOM uint32_t PAD32STRNG : 1; /*!< [2..2] Pad 32 drive strength */ + __IOM uint32_t PAD32FNCSEL : 3; /*!< [5..3] Pad 32 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD33PULL : 1; /*!< [8..8] Pad 33 pullup enable */ + __IOM uint32_t PAD33INPEN : 1; /*!< [9..9] Pad 33 input enable */ + __IOM uint32_t PAD33STRNG : 1; /*!< [10..10] Pad 33 drive strength */ + __IOM uint32_t PAD33FNCSEL : 3; /*!< [13..11] Pad 33 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD34PULL : 1; /*!< [16..16] Pad 34 pullup enable */ + __IOM uint32_t PAD34INPEN : 1; /*!< [17..17] Pad 34 input enable */ + __IOM uint32_t PAD34STRNG : 1; /*!< [18..18] Pad 34 drive strength */ + __IOM uint32_t PAD34FNCSEL : 3; /*!< [21..19] Pad 34 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD35PULL : 1; /*!< [24..24] Pad 35 pullup enable */ + __IOM uint32_t PAD35INPEN : 1; /*!< [25..25] Pad 35 input enable */ + __IOM uint32_t PAD35STRNG : 1; /*!< [26..26] Pad 35 drive strength */ + __IOM uint32_t PAD35FNCSEL : 3; /*!< [29..27] Pad 35 function select */ + } PADREGI_b; + } ; + + union { + __IOM uint32_t PADREGJ; /*!< (@ 0x00000024) Pad Configuration Register J (Pads 36-39) */ + + struct { + __IOM uint32_t PAD36PULL : 1; /*!< [0..0] Pad 36 pullup enable */ + __IOM uint32_t PAD36INPEN : 1; /*!< [1..1] Pad 36 input enable */ + __IOM uint32_t PAD36STRNG : 1; /*!< [2..2] Pad 36 drive strength */ + __IOM uint32_t PAD36FNCSEL : 3; /*!< [5..3] Pad 36 function select */ + __IOM uint32_t PAD36PWRUP : 1; /*!< [6..6] Pad 36 VDD power switch enable */ + __IM uint32_t : 1; + __IOM uint32_t PAD37PULL : 1; /*!< [8..8] Pad 37 pullup enable */ + __IOM uint32_t PAD37INPEN : 1; /*!< [9..9] Pad 37 input enable */ + __IOM uint32_t PAD37STRNG : 1; /*!< [10..10] Pad 37 drive strength */ + __IOM uint32_t PAD37FNCSEL : 3; /*!< [13..11] Pad 37 function select */ + __IM uint32_t : 1; + __IOM uint32_t PAD37PWRDN : 1; /*!< [15..15] Pad 37 VSS power switch enable */ + __IOM uint32_t PAD38PULL : 1; /*!< [16..16] Pad 38 pullup enable */ + __IOM uint32_t PAD38INPEN : 1; /*!< [17..17] Pad 38 input enable */ + __IOM uint32_t PAD38STRNG : 1; /*!< [18..18] Pad 38 drive strength */ + __IOM uint32_t PAD38FNCSEL : 3; /*!< [21..19] Pad 38 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD39PULL : 1; /*!< [24..24] Pad 39 pullup enable */ + __IOM uint32_t PAD39INPEN : 1; /*!< [25..25] Pad 39 input enable */ + __IOM uint32_t PAD39STRNG : 1; /*!< [26..26] Pad 39 drive strength */ + __IOM uint32_t PAD39FNCSEL : 3; /*!< [29..27] Pad 39 function select */ + __IOM uint32_t PAD39RSEL : 2; /*!< [31..30] Pad 39 pullup resistor selection. */ + } PADREGJ_b; + } ; + + union { + __IOM uint32_t PADREGK; /*!< (@ 0x00000028) Pad Configuration Register K (Pads 40-43) */ + + struct { + __IOM uint32_t PAD40PULL : 1; /*!< [0..0] Pad 40 pullup enable */ + __IOM uint32_t PAD40INPEN : 1; /*!< [1..1] Pad 40 input enable */ + __IOM uint32_t PAD40STRNG : 1; /*!< [2..2] Pad 40 drive strength */ + __IOM uint32_t PAD40FNCSEL : 3; /*!< [5..3] Pad 40 function select */ + __IOM uint32_t PAD40RSEL : 2; /*!< [7..6] Pad 40 pullup resistor selection. */ + __IOM uint32_t PAD41PULL : 1; /*!< [8..8] Pad 41 pullup enable */ + __IOM uint32_t PAD41INPEN : 1; /*!< [9..9] Pad 41 input enable */ + __IOM uint32_t PAD41STRNG : 1; /*!< [10..10] Pad 41 drive strength */ + __IOM uint32_t PAD41FNCSEL : 3; /*!< [13..11] Pad 41 function select */ + __IM uint32_t : 1; + __IOM uint32_t PAD41PWRDN : 1; /*!< [15..15] Pad 41 power switch enable */ + __IOM uint32_t PAD42PULL : 1; /*!< [16..16] Pad 42 pullup enable */ + __IOM uint32_t PAD42INPEN : 1; /*!< [17..17] Pad 42 input enable */ + __IOM uint32_t PAD42STRNG : 1; /*!< [18..18] Pad 42 drive strength */ + __IOM uint32_t PAD42FNCSEL : 3; /*!< [21..19] Pad 42 function select */ + __IOM uint32_t PAD42RSEL : 2; /*!< [23..22] Pad 42 pullup resistor selection. */ + __IOM uint32_t PAD43PULL : 1; /*!< [24..24] Pad 43 pullup enable */ + __IOM uint32_t PAD43INPEN : 1; /*!< [25..25] Pad 43 input enable */ + __IOM uint32_t PAD43STRNG : 1; /*!< [26..26] Pad 43 drive strength */ + __IOM uint32_t PAD43FNCSEL : 3; /*!< [29..27] Pad 43 function select */ + __IOM uint32_t PAD43RSEL : 2; /*!< [31..30] Pad 43 pullup resistor selection. */ + } PADREGK_b; + } ; + + union { + __IOM uint32_t PADREGL; /*!< (@ 0x0000002C) Pad Configuration Register L (Pads 44-47) */ + + struct { + __IOM uint32_t PAD44PULL : 1; /*!< [0..0] Pad 44 pullup enable */ + __IOM uint32_t PAD44INPEN : 1; /*!< [1..1] Pad 44 input enable */ + __IOM uint32_t PAD44STRNG : 1; /*!< [2..2] Pad 44 drive strength */ + __IOM uint32_t PAD44FNCSEL : 3; /*!< [5..3] Pad 44 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD45PULL : 1; /*!< [8..8] Pad 45 pullup enable */ + __IOM uint32_t PAD45INPEN : 1; /*!< [9..9] Pad 45 input enable */ + __IOM uint32_t PAD45STRNG : 1; /*!< [10..10] Pad 45 drive strength */ + __IOM uint32_t PAD45FNCSEL : 3; /*!< [13..11] Pad 45 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD46PULL : 1; /*!< [16..16] Pad 46 pullup enable */ + __IOM uint32_t PAD46INPEN : 1; /*!< [17..17] Pad 46 input enable */ + __IOM uint32_t PAD46STRNG : 1; /*!< [18..18] Pad 46 drive strength */ + __IOM uint32_t PAD46FNCSEL : 3; /*!< [21..19] Pad 46 function select */ + __IM uint32_t : 2; + __IOM uint32_t PAD47PULL : 1; /*!< [24..24] Pad 47 pullup enable */ + __IOM uint32_t PAD47INPEN : 1; /*!< [25..25] Pad 47 input enable */ + __IOM uint32_t PAD47STRNG : 1; /*!< [26..26] Pad 47 drive strength */ + __IOM uint32_t PAD47FNCSEL : 3; /*!< [29..27] Pad 47 function select */ + } PADREGL_b; + } ; + + union { + __IOM uint32_t PADREGM; /*!< (@ 0x00000030) Pad Configuration Register M (Pads 47-48) */ + + struct { + __IOM uint32_t PAD48PULL : 1; /*!< [0..0] Pad 48 pullup enable */ + __IOM uint32_t PAD48INPEN : 1; /*!< [1..1] Pad 48 input enable */ + __IOM uint32_t PAD48STRNG : 1; /*!< [2..2] Pad 48 drive strength */ + __IOM uint32_t PAD48FNCSEL : 3; /*!< [5..3] Pad 48 function select */ + __IOM uint32_t PAD48RSEL : 2; /*!< [7..6] Pad 48 pullup resistor selection. */ + __IOM uint32_t PAD49PULL : 1; /*!< [8..8] Pad 49 pullup enable */ + __IOM uint32_t PAD49INPEN : 1; /*!< [9..9] Pad 49 input enable */ + __IOM uint32_t PAD49STRNG : 1; /*!< [10..10] Pad 49 drive strength */ + __IOM uint32_t PAD49FNCSEL : 3; /*!< [13..11] Pad 49 function select */ + __IOM uint32_t PAD49RSEL : 2; /*!< [15..14] Pad 49 pullup resistor selection. */ + } PADREGM_b; + } ; + __IM uint32_t RESERVED[3]; + + union { + __IOM uint32_t CFGA; /*!< (@ 0x00000040) GPIO Configuration Register A (Pads 0-7) */ + + struct { + __IOM uint32_t GPIO0INCFG : 1; /*!< [0..0] GPIO0 input enable. */ + __IOM uint32_t GPIO0OUTCFG : 2; /*!< [2..1] GPIO0 output configuration. */ + __IOM uint32_t GPIO0INTD : 1; /*!< [3..3] GPIO0 interrupt direction. */ + __IOM uint32_t GPIO1INCFG : 1; /*!< [4..4] GPIO1 input enable. */ + __IOM uint32_t GPIO1OUTCFG : 2; /*!< [6..5] GPIO1 output configuration. */ + __IOM uint32_t GPIO1INTD : 1; /*!< [7..7] GPIO1 interrupt direction. */ + __IOM uint32_t GPIO2INCFG : 1; /*!< [8..8] GPIO2 input enable. */ + __IOM uint32_t GPIO2OUTCFG : 2; /*!< [10..9] GPIO2 output configuration. */ + __IOM uint32_t GPIO2INTD : 1; /*!< [11..11] GPIO2 interrupt direction. */ + __IOM uint32_t GPIO3INCFG : 1; /*!< [12..12] GPIO3 input enable. */ + __IOM uint32_t GPIO3OUTCFG : 2; /*!< [14..13] GPIO3 output configuration. */ + __IOM uint32_t GPIO3INTD : 1; /*!< [15..15] GPIO3 interrupt direction. */ + __IOM uint32_t GPIO4INCFG : 1; /*!< [16..16] GPIO4 input enable. */ + __IOM uint32_t GPIO4OUTCFG : 2; /*!< [18..17] GPIO4 output configuration. */ + __IOM uint32_t GPIO4INTD : 1; /*!< [19..19] GPIO4 interrupt direction. */ + __IOM uint32_t GPIO5INCFG : 1; /*!< [20..20] GPIO5 input enable. */ + __IOM uint32_t GPIO5OUTCFG : 2; /*!< [22..21] GPIO5 output configuration. */ + __IOM uint32_t GPIO5INTD : 1; /*!< [23..23] GPIO5 interrupt direction. */ + __IOM uint32_t GPIO6INCFG : 1; /*!< [24..24] GPIO6 input enable. */ + __IOM uint32_t GPIO6OUTCFG : 2; /*!< [26..25] GPIO6 output configuration. */ + __IOM uint32_t GPIO6INTD : 1; /*!< [27..27] GPIO6 interrupt direction. */ + __IOM uint32_t GPIO7INCFG : 1; /*!< [28..28] GPIO7 input enable. */ + __IOM uint32_t GPIO7OUTCFG : 2; /*!< [30..29] GPIO7 output configuration. */ + __IOM uint32_t GPIO7INTD : 1; /*!< [31..31] GPIO7 interrupt direction, nCE polarity. */ + } CFGA_b; + } ; + + union { + __IOM uint32_t CFGB; /*!< (@ 0x00000044) GPIO Configuration Register B (Pads 8-15) */ + + struct { + __IOM uint32_t GPIO8INCFG : 1; /*!< [0..0] GPIO8 input enable. */ + __IOM uint32_t GPIO8OUTCFG : 2; /*!< [2..1] GPIO8 output configuration. */ + __IOM uint32_t GPIO8INTD : 1; /*!< [3..3] GPIO8 interrupt direction. */ + __IOM uint32_t GPIO9INCFG : 1; /*!< [4..4] GPIO9 input enable. */ + __IOM uint32_t GPIO9OUTCFG : 2; /*!< [6..5] GPIO9 output configuration. */ + __IOM uint32_t GPIO9INTD : 1; /*!< [7..7] GPIO9 interrupt direction. */ + __IOM uint32_t GPIO10INCFG : 1; /*!< [8..8] GPIO10 input enable. */ + __IOM uint32_t GPIO10OUTCFG : 2; /*!< [10..9] GPIO10 output configuration. */ + __IOM uint32_t GPIO10INTD : 1; /*!< [11..11] GPIO10 interrupt direction. */ + __IOM uint32_t GPIO11INCFG : 1; /*!< [12..12] GPIO11 input enable. */ + __IOM uint32_t GPIO11OUTCFG : 2; /*!< [14..13] GPIO11 output configuration. */ + __IOM uint32_t GPIO11INTD : 1; /*!< [15..15] GPIO11 interrupt direction. */ + __IOM uint32_t GPIO12INCFG : 1; /*!< [16..16] GPIO12 input enable. */ + __IOM uint32_t GPIO12OUTCFG : 2; /*!< [18..17] GPIO12 output configuration. */ + __IOM uint32_t GPIO12INTD : 1; /*!< [19..19] GPIO12 interrupt direction. */ + __IOM uint32_t GPIO13INCFG : 1; /*!< [20..20] GPIO13 input enable. */ + __IOM uint32_t GPIO13OUTCFG : 2; /*!< [22..21] GPIO13 output configuration. */ + __IOM uint32_t GPIO13INTD : 1; /*!< [23..23] GPIO13 interrupt direction. */ + __IOM uint32_t GPIO14INCFG : 1; /*!< [24..24] GPIO14 input enable. */ + __IOM uint32_t GPIO14OUTCFG : 2; /*!< [26..25] GPIO14 output configuration. */ + __IOM uint32_t GPIO14INTD : 1; /*!< [27..27] GPIO14 interrupt direction. */ + __IOM uint32_t GPIO15INCFG : 1; /*!< [28..28] GPIO15 input enable. */ + __IOM uint32_t GPIO15OUTCFG : 2; /*!< [30..29] GPIO15 output configuration. */ + __IOM uint32_t GPIO15INTD : 1; /*!< [31..31] GPIO15 interrupt direction. */ + } CFGB_b; + } ; + + union { + __IOM uint32_t CFGC; /*!< (@ 0x00000048) GPIO Configuration Register C (Pads 16-23) */ + + struct { + __IOM uint32_t GPIO16INCFG : 1; /*!< [0..0] GPIO16 input enable. */ + __IOM uint32_t GPIO16OUTCFG : 2; /*!< [2..1] GPIO16 output configuration. */ + __IOM uint32_t GPIO16INTD : 1; /*!< [3..3] GPIO16 interrupt direction. */ + __IOM uint32_t GPIO17INCFG : 1; /*!< [4..4] GPIO17 input enable. */ + __IOM uint32_t GPIO17OUTCFG : 2; /*!< [6..5] GPIO17 output configuration. */ + __IOM uint32_t GPIO17INTD : 1; /*!< [7..7] GPIO17 interrupt direction. */ + __IOM uint32_t GPIO18INCFG : 1; /*!< [8..8] GPIO18 input enable. */ + __IOM uint32_t GPIO18OUTCFG : 2; /*!< [10..9] GPIO18 output configuration. */ + __IOM uint32_t GPIO18INTD : 1; /*!< [11..11] GPIO18 interrupt direction. */ + __IOM uint32_t GPIO19INCFG : 1; /*!< [12..12] GPIO19 input enable. */ + __IOM uint32_t GPIO19OUTCFG : 2; /*!< [14..13] GPIO19 output configuration. */ + __IOM uint32_t GPIO19INTD : 1; /*!< [15..15] GPIO19 interrupt direction. */ + __IOM uint32_t GPIO20INCFG : 1; /*!< [16..16] GPIO20 input enable. */ + __IOM uint32_t GPIO20OUTCFG : 2; /*!< [18..17] GPIO20 output configuration. */ + __IOM uint32_t GPIO20INTD : 1; /*!< [19..19] GPIO20 interrupt direction. */ + __IOM uint32_t GPIO21INCFG : 1; /*!< [20..20] GPIO21 input enable. */ + __IOM uint32_t GPIO21OUTCFG : 2; /*!< [22..21] GPIO21 output configuration. */ + __IOM uint32_t GPIO21INTD : 1; /*!< [23..23] GPIO21 interrupt direction. */ + __IOM uint32_t GPIO22INCFG : 1; /*!< [24..24] GPIO22 input enable. */ + __IOM uint32_t GPIO22OUTCFG : 2; /*!< [26..25] GPIO22 output configuration. */ + __IOM uint32_t GPIO22INTD : 1; /*!< [27..27] GPIO22 interrupt direction. */ + __IOM uint32_t GPIO23INCFG : 1; /*!< [28..28] GPIO23 input enable. */ + __IOM uint32_t GPIO23OUTCFG : 2; /*!< [30..29] GPIO23 output configuration. */ + __IOM uint32_t GPIO23INTD : 1; /*!< [31..31] GPIO23 interrupt direction. */ + } CFGC_b; + } ; + + union { + __IOM uint32_t CFGD; /*!< (@ 0x0000004C) GPIO Configuration Register D (Pads 24-31) */ + + struct { + __IOM uint32_t GPIO24INCFG : 1; /*!< [0..0] GPIO24 input enable. */ + __IOM uint32_t GPIO24OUTCFG : 2; /*!< [2..1] GPIO24 output configuration. */ + __IOM uint32_t GPIO24INTD : 1; /*!< [3..3] GPIO24 interrupt direction. */ + __IOM uint32_t GPIO25INCFG : 1; /*!< [4..4] GPIO25 input enable. */ + __IOM uint32_t GPIO25OUTCFG : 2; /*!< [6..5] GPIO25 output configuration. */ + __IOM uint32_t GPIO25INTD : 1; /*!< [7..7] GPIO25 interrupt direction. */ + __IOM uint32_t GPIO26INCFG : 1; /*!< [8..8] GPIO26 input enable. */ + __IOM uint32_t GPIO26OUTCFG : 2; /*!< [10..9] GPIO26 output configuration. */ + __IOM uint32_t GPIO26INTD : 1; /*!< [11..11] GPIO26 interrupt direction. */ + __IOM uint32_t GPIO27INCFG : 1; /*!< [12..12] GPIO27 input enable. */ + __IOM uint32_t GPIO27OUTCFG : 2; /*!< [14..13] GPIO27 output configuration. */ + __IOM uint32_t GPIO27INTD : 1; /*!< [15..15] GPIO27 interrupt direction. */ + __IOM uint32_t GPIO28INCFG : 1; /*!< [16..16] GPIO28 input enable. */ + __IOM uint32_t GPIO28OUTCFG : 2; /*!< [18..17] GPIO28 output configuration. */ + __IOM uint32_t GPIO28INTD : 1; /*!< [19..19] GPIO28 interrupt direction. */ + __IOM uint32_t GPIO29INCFG : 1; /*!< [20..20] GPIO29 input enable. */ + __IOM uint32_t GPIO29OUTCFG : 2; /*!< [22..21] GPIO29 output configuration. */ + __IOM uint32_t GPIO29INTD : 1; /*!< [23..23] GPIO29 interrupt direction. */ + __IOM uint32_t GPIO30INCFG : 1; /*!< [24..24] GPIO30 input enable. */ + __IOM uint32_t GPIO30OUTCFG : 2; /*!< [26..25] GPIO30 output configuration. */ + __IOM uint32_t GPIO30INTD : 1; /*!< [27..27] GPIO30 interrupt direction. */ + __IOM uint32_t GPIO31INCFG : 1; /*!< [28..28] GPIO31 input enable. */ + __IOM uint32_t GPIO31OUTCFG : 2; /*!< [30..29] GPIO31 output configuration. */ + __IOM uint32_t GPIO31INTD : 1; /*!< [31..31] GPIO31 interrupt direction. */ + } CFGD_b; + } ; + + union { + __IOM uint32_t CFGE; /*!< (@ 0x00000050) GPIO Configuration Register E (Pads 32-39) */ + + struct { + __IOM uint32_t GPIO32INCFG : 1; /*!< [0..0] GPIO32 input enable. */ + __IOM uint32_t GPIO32OUTCFG : 2; /*!< [2..1] GPIO32 output configuration. */ + __IOM uint32_t GPIO32INTD : 1; /*!< [3..3] GPIO32 interrupt direction. */ + __IOM uint32_t GPIO33INCFG : 1; /*!< [4..4] GPIO33 input enable. */ + __IOM uint32_t GPIO33OUTCFG : 2; /*!< [6..5] GPIO33 output configuration. */ + __IOM uint32_t GPIO33INTD : 1; /*!< [7..7] GPIO33 interrupt direction. */ + __IOM uint32_t GPIO34INCFG : 1; /*!< [8..8] GPIO34 input enable. */ + __IOM uint32_t GPIO34OUTCFG : 2; /*!< [10..9] GPIO34 output configuration. */ + __IOM uint32_t GPIO34INTD : 1; /*!< [11..11] GPIO34 interrupt direction. */ + __IOM uint32_t GPIO35INCFG : 1; /*!< [12..12] GPIO35 input enable. */ + __IOM uint32_t GPIO35OUTCFG : 2; /*!< [14..13] GPIO35 output configuration. */ + __IOM uint32_t GPIO35INTD : 1; /*!< [15..15] GPIO35 interrupt direction. */ + __IOM uint32_t GPIO36INCFG : 1; /*!< [16..16] GPIO36 input enable. */ + __IOM uint32_t GPIO36OUTCFG : 2; /*!< [18..17] GPIO36 output configuration. */ + __IOM uint32_t GPIO36INTD : 1; /*!< [19..19] GPIO36 interrupt direction. */ + __IOM uint32_t GPIO37INCFG : 1; /*!< [20..20] GPIO37 input enable. */ + __IOM uint32_t GPIO37OUTCFG : 2; /*!< [22..21] GPIO37 output configuration. */ + __IOM uint32_t GPIO37INTD : 1; /*!< [23..23] GPIO37 interrupt direction. */ + __IOM uint32_t GPIO38INCFG : 1; /*!< [24..24] GPIO38 input enable. */ + __IOM uint32_t GPIO38OUTCFG : 2; /*!< [26..25] GPIO38 output configuration. */ + __IOM uint32_t GPIO38INTD : 1; /*!< [27..27] GPIO38 interrupt direction. */ + __IOM uint32_t GPIO39INCFG : 1; /*!< [28..28] GPIO39 input enable. */ + __IOM uint32_t GPIO39OUTCFG : 2; /*!< [30..29] GPIO39 output configuration. */ + __IOM uint32_t GPIO39INTD : 1; /*!< [31..31] GPIO39 interrupt direction. */ + } CFGE_b; + } ; + + union { + __IOM uint32_t CFGF; /*!< (@ 0x00000054) GPIO Configuration Register F (Pads 40 -47) */ + + struct { + __IOM uint32_t GPIO40INCFG : 1; /*!< [0..0] GPIO40 input enable. */ + __IOM uint32_t GPIO40OUTCFG : 2; /*!< [2..1] GPIO40 output configuration. */ + __IOM uint32_t GPIO40INTD : 1; /*!< [3..3] GPIO40 interrupt direction. */ + __IOM uint32_t GPIO41INCFG : 1; /*!< [4..4] GPIO41 input enable. */ + __IOM uint32_t GPIO41OUTCFG : 2; /*!< [6..5] GPIO41 output configuration. */ + __IOM uint32_t GPIO41INTD : 1; /*!< [7..7] GPIO41 interrupt direction. */ + __IOM uint32_t GPIO42INCFG : 1; /*!< [8..8] GPIO42 input enable. */ + __IOM uint32_t GPIO42OUTCFG : 2; /*!< [10..9] GPIO42 output configuration. */ + __IOM uint32_t GPIO42INTD : 1; /*!< [11..11] GPIO42 interrupt direction. */ + __IOM uint32_t GPIO43INCFG : 1; /*!< [12..12] GPIO43 input enable. */ + __IOM uint32_t GPIO43OUTCFG : 2; /*!< [14..13] GPIO43 output configuration. */ + __IOM uint32_t GPIO43INTD : 1; /*!< [15..15] GPIO43 interrupt direction. */ + __IOM uint32_t GPIO44INCFG : 1; /*!< [16..16] GPIO44 input enable. */ + __IOM uint32_t GPIO44OUTCFG : 2; /*!< [18..17] GPIO44 output configuration. */ + __IOM uint32_t GPIO44INTD : 1; /*!< [19..19] GPIO44 interrupt direction. */ + __IOM uint32_t GPIO45INCFG : 1; /*!< [20..20] GPIO45 input enable. */ + __IOM uint32_t GPIO45OUTCFG : 2; /*!< [22..21] GPIO45 output configuration. */ + __IOM uint32_t GPIO45INTD : 1; /*!< [23..23] GPIO45 interrupt direction. */ + __IOM uint32_t GPIO46INCFG : 1; /*!< [24..24] GPIO46 input enable. */ + __IOM uint32_t GPIO46OUTCFG : 2; /*!< [26..25] GPIO46 output configuration. */ + __IOM uint32_t GPIO46INTD : 1; /*!< [27..27] GPIO46 interrupt direction. */ + __IOM uint32_t GPIO47INCFG : 1; /*!< [28..28] GPIO47 input enable. */ + __IOM uint32_t GPIO47OUTCFG : 2; /*!< [30..29] GPIO47 output configuration. */ + __IOM uint32_t GPIO47INTD : 1; /*!< [31..31] GPIO47 interrupt direction. */ + } CFGF_b; + } ; + + union { + __IOM uint32_t CFGG; /*!< (@ 0x00000058) GPIO Configuration Register G (Pads 48-49) */ + + struct { + __IOM uint32_t GPIO48INCFG : 1; /*!< [0..0] GPIO48 input enable. */ + __IOM uint32_t GPIO48OUTCFG : 2; /*!< [2..1] GPIO48 output configuration. */ + __IOM uint32_t GPIO48INTD : 1; /*!< [3..3] GPIO48 interrupt direction. */ + __IOM uint32_t GPIO49INCFG : 1; /*!< [4..4] GPIO49 input enable. */ + __IOM uint32_t GPIO49OUTCFG : 2; /*!< [6..5] GPIO49 output configuration. */ + __IOM uint32_t GPIO49INTD : 1; /*!< [7..7] GPIO49 interrupt direction. */ + } CFGG_b; + } ; + __IM uint32_t RESERVED1; + + union { + __IOM uint32_t PADKEY; /*!< (@ 0x00000060) Key Register for all pad configuration registers */ + + struct { + __IOM uint32_t PADKEY : 32; /*!< [31..0] Key register value. */ + } PADKEY_b; + } ; + __IM uint32_t RESERVED2[7]; + + union { + __IOM uint32_t RDA; /*!< (@ 0x00000080) GPIO Input Register A */ + + struct { + __IOM uint32_t RDA : 32; /*!< [31..0] GPIO31-0 read data. */ + } RDA_b; + } ; + + union { + __IOM uint32_t RDB; /*!< (@ 0x00000084) GPIO Input Register B */ + + struct { + __IOM uint32_t RDB : 18; /*!< [17..0] GPIO49-32 read data. */ + } RDB_b; + } ; + + union { + __IOM uint32_t WTA; /*!< (@ 0x00000088) GPIO Output Register A */ + + struct { + __IOM uint32_t WTA : 32; /*!< [31..0] GPIO31-0 write data. */ + } WTA_b; + } ; + + union { + __IOM uint32_t WTB; /*!< (@ 0x0000008C) GPIO Output Register B */ + + struct { + __IOM uint32_t WTB : 18; /*!< [17..0] GPIO49-32 write data. */ + } WTB_b; + } ; + + union { + __IOM uint32_t WTSA; /*!< (@ 0x00000090) GPIO Output Register A Set */ + + struct { + __IOM uint32_t WTSA : 32; /*!< [31..0] Set the GPIO31-0 write data. */ + } WTSA_b; + } ; + + union { + __IOM uint32_t WTSB; /*!< (@ 0x00000094) GPIO Output Register B Set */ + + struct { + __IOM uint32_t WTSB : 18; /*!< [17..0] Set the GPIO49-32 write data. */ + } WTSB_b; + } ; + + union { + __IOM uint32_t WTCA; /*!< (@ 0x00000098) GPIO Output Register A Clear */ + + struct { + __IOM uint32_t WTCA : 32; /*!< [31..0] Clear the GPIO31-0 write data. */ + } WTCA_b; + } ; + + union { + __IOM uint32_t WTCB; /*!< (@ 0x0000009C) GPIO Output Register B Clear */ + + struct { + __IOM uint32_t WTCB : 18; /*!< [17..0] Clear the GPIO49-32 write data. */ + } WTCB_b; + } ; + + union { + __IOM uint32_t ENA; /*!< (@ 0x000000A0) GPIO Enable Register A */ + + struct { + __IOM uint32_t ENA : 32; /*!< [31..0] GPIO31-0 output enables */ + } ENA_b; + } ; + + union { + __IOM uint32_t ENB; /*!< (@ 0x000000A4) GPIO Enable Register B */ + + struct { + __IOM uint32_t ENB : 18; /*!< [17..0] GPIO49-32 output enables */ + } ENB_b; + } ; + + union { + __IOM uint32_t ENSA; /*!< (@ 0x000000A8) GPIO Enable Register A Set */ + + struct { + __IOM uint32_t ENSA : 32; /*!< [31..0] Set the GPIO31-0 output enables */ + } ENSA_b; + } ; + + union { + __IOM uint32_t ENSB; /*!< (@ 0x000000AC) GPIO Enable Register B Set */ + + struct { + __IOM uint32_t ENSB : 18; /*!< [17..0] Set the GPIO49-32 output enables */ + } ENSB_b; + } ; + __IM uint32_t RESERVED3; + + union { + __IOM uint32_t ENCA; /*!< (@ 0x000000B4) GPIO Enable Register A Clear */ + + struct { + __IOM uint32_t ENCA : 32; /*!< [31..0] Clear the GPIO31-0 output enables */ + } ENCA_b; + } ; + + union { + __IOM uint32_t ENCB; /*!< (@ 0x000000B8) GPIO Enable Register B Clear */ + + struct { + __IOM uint32_t ENCB : 18; /*!< [17..0] Clear the GPIO49-32 output enables */ + } ENCB_b; + } ; + + union { + __IOM uint32_t STMRCAP; /*!< (@ 0x000000BC) STIMER Capture Control */ + + struct { + __IOM uint32_t STSEL0 : 6; /*!< [5..0] STIMER Capture 0 Select. */ + __IOM uint32_t STPOL0 : 1; /*!< [6..6] STIMER Capture 0 Polarity. */ + __IM uint32_t : 1; + __IOM uint32_t STSEL1 : 6; /*!< [13..8] STIMER Capture 1 Select. */ + __IOM uint32_t STPOL1 : 1; /*!< [14..14] STIMER Capture 1 Polarity. */ + __IM uint32_t : 1; + __IOM uint32_t STSEL2 : 6; /*!< [21..16] STIMER Capture 2 Select. */ + __IOM uint32_t STPOL2 : 1; /*!< [22..22] STIMER Capture 2 Polarity. */ + __IM uint32_t : 1; + __IOM uint32_t STSEL3 : 6; /*!< [29..24] STIMER Capture 3 Select. */ + __IOM uint32_t STPOL3 : 1; /*!< [30..30] STIMER Capture 3 Polarity. */ + } STMRCAP_b; + } ; + + union { + __IOM uint32_t IOM0IRQ; /*!< (@ 0x000000C0) IOM0 Flow Control IRQ Select */ + + struct { + __IOM uint32_t IOM0IRQ : 6; /*!< [5..0] IOMSTR0 IRQ pad select. */ + } IOM0IRQ_b; + } ; + + union { + __IOM uint32_t IOM1IRQ; /*!< (@ 0x000000C4) IOM1 Flow Control IRQ Select */ + + struct { + __IOM uint32_t IOM1IRQ : 6; /*!< [5..0] IOMSTR1 IRQ pad select. */ + } IOM1IRQ_b; + } ; + + union { + __IOM uint32_t IOM2IRQ; /*!< (@ 0x000000C8) IOM2 Flow Control IRQ Select */ + + struct { + __IOM uint32_t IOM2IRQ : 6; /*!< [5..0] IOMSTR2 IRQ pad select. */ + } IOM2IRQ_b; + } ; + + union { + __IOM uint32_t IOM3IRQ; /*!< (@ 0x000000CC) IOM3 Flow Control IRQ Select */ + + struct { + __IOM uint32_t IOM3IRQ : 6; /*!< [5..0] IOMSTR3 IRQ pad select. */ + } IOM3IRQ_b; + } ; + + union { + __IOM uint32_t IOM4IRQ; /*!< (@ 0x000000D0) IOM4 Flow Control IRQ Select */ + + struct { + __IOM uint32_t IOM4IRQ : 6; /*!< [5..0] IOMSTR4 IRQ pad select. */ + } IOM4IRQ_b; + } ; + + union { + __IOM uint32_t IOM5IRQ; /*!< (@ 0x000000D4) IOM5 Flow Control IRQ Select */ + + struct { + __IOM uint32_t IOM5IRQ : 6; /*!< [5..0] IOMSTR5 IRQ pad select. */ + } IOM5IRQ_b; + } ; + + union { + __IOM uint32_t BLEIFIRQ; /*!< (@ 0x000000D8) BLEIF Flow Control IRQ Select */ + + struct { + __IOM uint32_t BLEIFIRQ : 6; /*!< [5..0] BLEIF IRQ pad select. */ + } BLEIFIRQ_b; + } ; + + union { + __IOM uint32_t GPIOOBS; /*!< (@ 0x000000DC) GPIO Observation Mode Sample register */ + + struct { + __IOM uint32_t OBS_DATA : 16; /*!< [15..0] Sample of the data output on the GPIO observation port. + May have async sampling issues, as the data is not synronized + to the read operation. Intended for debug purposes only */ + } GPIOOBS_b; + } ; + + union { + __IOM uint32_t ALTPADCFGA; /*!< (@ 0x000000E0) Alternate Pad Configuration reg0 (Pads 3,2,1,0) */ + + struct { + __IOM uint32_t PAD0_DS1 : 1; /*!< [0..0] Pad 0 high order drive strength selection. Used in conjunction + with PAD0STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD0_SR : 1; /*!< [4..4] Pad 0 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD1_DS1 : 1; /*!< [8..8] Pad 1 high order drive strength selection. Used in conjunction + with PAD1STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD1_SR : 1; /*!< [12..12] Pad 1 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD2_DS1 : 1; /*!< [16..16] Pad 2 high order drive strength selection. Used in + conjunction with PAD2STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD2_SR : 1; /*!< [20..20] Pad 2 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD3_DS1 : 1; /*!< [24..24] Pad 3 high order drive strength selection. Used in + conjunction with PAD3STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD3_SR : 1; /*!< [28..28] Pad 3 slew rate selection. */ + } ALTPADCFGA_b; + } ; + + union { + __IOM uint32_t ALTPADCFGB; /*!< (@ 0x000000E4) Alternate Pad Configuration reg1 (Pads 7,6,5,4) */ + + struct { + __IOM uint32_t PAD4_DS1 : 1; /*!< [0..0] Pad 4 high order drive strength selection. Used in conjunction + with PAD4STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD4_SR : 1; /*!< [4..4] Pad 4 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD5_DS1 : 1; /*!< [8..8] Pad 5 high order drive strength selection. Used in conjunction + with PAD5STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD5_SR : 1; /*!< [12..12] Pad 5 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD6_DS1 : 1; /*!< [16..16] Pad 6 high order drive strength selection. Used in + conjunction with PAD6STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD6_SR : 1; /*!< [20..20] Pad 6 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD7_DS1 : 1; /*!< [24..24] Pad 7 high order drive strength selection. Used in + conjunction with PAD7STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD7_SR : 1; /*!< [28..28] Pad 7 slew rate selection. */ + } ALTPADCFGB_b; + } ; + + union { + __IOM uint32_t ALTPADCFGC; /*!< (@ 0x000000E8) Alternate Pad Configuration reg2 (Pads 11,10,9,8) */ + + struct { + __IOM uint32_t PAD8_DS1 : 1; /*!< [0..0] Pad 8 high order drive strength selection. Used in conjunction + with PAD8STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD8_SR : 1; /*!< [4..4] Pad 8 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD9_DS1 : 1; /*!< [8..8] Pad 9 high order drive strength selection. Used in conjunction + with PAD9STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD9_SR : 1; /*!< [12..12] Pad 9 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD10_DS1 : 1; /*!< [16..16] Pad 10 high order drive strength selection. Used in + conjunction with PAD10STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD10_SR : 1; /*!< [20..20] Pad 10 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD11_DS1 : 1; /*!< [24..24] Pad 11 high order drive strength selection. Used in + conjunction with PAD11STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD11_SR : 1; /*!< [28..28] Pad 11 slew rate selection. */ + } ALTPADCFGC_b; + } ; + + union { + __IOM uint32_t ALTPADCFGD; /*!< (@ 0x000000EC) Alternate Pad Configuration reg3 (Pads 15,14,13,12) */ + + struct { + __IOM uint32_t PAD12_DS1 : 1; /*!< [0..0] Pad 12 high order drive strength selection. Used in conjunction + with PAD12STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD12_SR : 1; /*!< [4..4] Pad 12 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD13_DS1 : 1; /*!< [8..8] Pad 13 high order drive strength selection. Used in conjunction + with PAD13STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD13_SR : 1; /*!< [12..12] Pad 13 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD14_DS1 : 1; /*!< [16..16] Pad 14 high order drive strength selection. Used in + conjunction with PAD14STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD14_SR : 1; /*!< [20..20] Pad 14 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD15_DS1 : 1; /*!< [24..24] Pad 15 high order drive strength selection. Used in + conjunction with PAD15STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD15_SR : 1; /*!< [28..28] Pad 15 slew rate selection. */ + } ALTPADCFGD_b; + } ; + + union { + __IOM uint32_t ALTPADCFGE; /*!< (@ 0x000000F0) Alternate Pad Configuration reg4 (Pads 19,18,17,16) */ + + struct { + __IOM uint32_t PAD16_DS1 : 1; /*!< [0..0] Pad 16 high order drive strength selection. Used in conjunction + with PAD16STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD16_SR : 1; /*!< [4..4] Pad 16 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD17_DS1 : 1; /*!< [8..8] Pad 17 high order drive strength selection. Used in conjunction + with PAD17STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD17_SR : 1; /*!< [12..12] Pad 17 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD18_DS1 : 1; /*!< [16..16] Pad 18 high order drive strength selection. Used in + conjunction with PAD18STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD18_SR : 1; /*!< [20..20] Pad 18 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD19_DS1 : 1; /*!< [24..24] Pad 19 high order drive strength selection. Used in + conjunction with PAD19STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD19_SR : 1; /*!< [28..28] Pad 19 slew rate selection. */ + } ALTPADCFGE_b; + } ; + + union { + __IOM uint32_t ALTPADCFGF; /*!< (@ 0x000000F4) Alternate Pad Configuration reg5 (Pads 23,22,21,20) */ + + struct { + __IOM uint32_t PAD20_DS1 : 1; /*!< [0..0] Pad 20 high order drive strength selection. Used in conjunction + with PAD20STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD20_SR : 1; /*!< [4..4] Pad 20 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD21_DS1 : 1; /*!< [8..8] Pad 21 high order drive strength selection. Used in conjunction + with PAD21STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD21_SR : 1; /*!< [12..12] Pad 21 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD22_DS1 : 1; /*!< [16..16] Pad 22 high order drive strength selection. Used in + conjunction with PAD22STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD22_SR : 1; /*!< [20..20] Pad 22 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD23_DS1 : 1; /*!< [24..24] Pad 23 high order drive strength selection. Used in + conjunction with PAD23STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD23_SR : 1; /*!< [28..28] Pad 23 slew rate selection. */ + } ALTPADCFGF_b; + } ; + + union { + __IOM uint32_t ALTPADCFGG; /*!< (@ 0x000000F8) Alternate Pad Configuration reg6 (Pads 27,26,25,24) */ + + struct { + __IOM uint32_t PAD24_DS1 : 1; /*!< [0..0] Pad 24 high order drive strength selection. Used in conjunction + with PAD24STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD24_SR : 1; /*!< [4..4] Pad 24 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD25_DS1 : 1; /*!< [8..8] Pad 25 high order drive strength selection. Used in conjunction + with PAD25STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD25_SR : 1; /*!< [12..12] Pad 25 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD26_DS1 : 1; /*!< [16..16] Pad 26 high order drive strength selection. Used in + conjunction with PAD26STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD26_SR : 1; /*!< [20..20] Pad 26 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD27_DS1 : 1; /*!< [24..24] Pad 27 high order drive strength selection. Used in + conjunction with PAD27STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD27_SR : 1; /*!< [28..28] Pad 27 slew rate selection. */ + } ALTPADCFGG_b; + } ; + + union { + __IOM uint32_t ALTPADCFGH; /*!< (@ 0x000000FC) Alternate Pad Configuration reg7 (Pads 31,30,29,28) */ + + struct { + __IOM uint32_t PAD28_DS1 : 1; /*!< [0..0] Pad 28 high order drive strength selection. Used in conjunction + with PAD28STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD28_SR : 1; /*!< [4..4] Pad 28 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD29_DS1 : 1; /*!< [8..8] Pad 29 high order drive strength selection. Used in conjunction + with PAD29STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD29_SR : 1; /*!< [12..12] Pad 29 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD30_DS1 : 1; /*!< [16..16] Pad 30 high order drive strength selection. Used in + conjunction with PAD30STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD30_SR : 1; /*!< [20..20] Pad 30 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD31_DS1 : 1; /*!< [24..24] Pad 31 high order drive strength selection. Used in + conjunction with PAD31STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD31_SR : 1; /*!< [28..28] Pad 31 slew rate selection. */ + } ALTPADCFGH_b; + } ; + + union { + __IOM uint32_t ALTPADCFGI; /*!< (@ 0x00000100) Alternate Pad Configuration reg8 (Pads 35,34,33,32) */ + + struct { + __IOM uint32_t PAD32_DS1 : 1; /*!< [0..0] Pad 32 high order drive strength selection. Used in conjunction + with PAD32STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD32_SR : 1; /*!< [4..4] Pad 32 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD33_DS1 : 1; /*!< [8..8] Pad 33 high order drive strength selection. Used in conjunction + with PAD33STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD33_SR : 1; /*!< [12..12] Pad 33 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD34_DS1 : 1; /*!< [16..16] Pad 34 high order drive strength selection. Used in + conjunction with PAD34STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD34_SR : 1; /*!< [20..20] Pad 34 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD35_DS1 : 1; /*!< [24..24] Pad 35 high order drive strength selection. Used in + conjunction with PAD35STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD35_SR : 1; /*!< [28..28] Pad 35 slew rate selection. */ + } ALTPADCFGI_b; + } ; + + union { + __IOM uint32_t ALTPADCFGJ; /*!< (@ 0x00000104) Alternate Pad Configuration reg9 (Pads 39,38,37,36) */ + + struct { + __IOM uint32_t PAD36_DS1 : 1; /*!< [0..0] Pad 36 high order drive strength selection. Used in conjunction + with PAD36STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD36_SR : 1; /*!< [4..4] Pad 36 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD37_DS1 : 1; /*!< [8..8] Pad 37 high order drive strength selection. Used in conjunction + with PAD37STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD37_SR : 1; /*!< [12..12] Pad 37 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD38_DS1 : 1; /*!< [16..16] Pad 38 high order drive strength selection. Used in + conjunction with PAD38STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD38_SR : 1; /*!< [20..20] Pad 38 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD39_DS1 : 1; /*!< [24..24] Pad 39 high order drive strength selection. Used in + conjunction with PAD39STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD39_SR : 1; /*!< [28..28] Pad 39 slew rate selection. */ + } ALTPADCFGJ_b; + } ; + + union { + __IOM uint32_t ALTPADCFGK; /*!< (@ 0x00000108) Alternate Pad Configuration reg10 (Pads 43,42,41,40) */ + + struct { + __IOM uint32_t PAD40_DS1 : 1; /*!< [0..0] Pad 40 high order drive strength selection. Used in conjunction + with PAD40STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD40_SR : 1; /*!< [4..4] Pad 40 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD41_DS1 : 1; /*!< [8..8] Pad 41 high order drive strength selection. Used in conjunction + with PAD41STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD41_SR : 1; /*!< [12..12] Pad 41 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD42_DS1 : 1; /*!< [16..16] Pad 42 high order drive strength selection. Used in + conjunction with PAD42STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD42_SR : 1; /*!< [20..20] Pad 42 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD43_DS1 : 1; /*!< [24..24] Pad 43 high order drive strength selection. Used in + conjunction with PAD43STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD43_SR : 1; /*!< [28..28] Pad 43 slew rate selection. */ + } ALTPADCFGK_b; + } ; + + union { + __IOM uint32_t ALTPADCFGL; /*!< (@ 0x0000010C) Alternate Pad Configuration reg11 (Pads 47,46,45,44) */ + + struct { + __IOM uint32_t PAD44_DS1 : 1; /*!< [0..0] Pad 44 high order drive strength selection. Used in conjunction + with PAD44STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD44_SR : 1; /*!< [4..4] Pad 44 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD45_DS1 : 1; /*!< [8..8] Pad 45 high order drive strength selection. Used in conjunction + with PAD45STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD45_SR : 1; /*!< [12..12] Pad 45 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD46_DS1 : 1; /*!< [16..16] Pad 46 high order drive strength selection. Used in + conjunction with PAD46STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD46_SR : 1; /*!< [20..20] Pad 46 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD47_DS1 : 1; /*!< [24..24] Pad 47 high order drive strength selection. Used in + conjunction with PAD47STRNG field to set the pad drive + strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD47_SR : 1; /*!< [28..28] Pad 47 slew rate selection. */ + } ALTPADCFGL_b; + } ; + + union { + __IOM uint32_t ALTPADCFGM; /*!< (@ 0x00000110) Alternate Pad Configuration reg12 (Pads 49,48) */ + + struct { + __IOM uint32_t PAD48_DS1 : 1; /*!< [0..0] Pad 48 high order drive strength selection. Used in conjunction + with PAD48STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD48_SR : 1; /*!< [4..4] Pad 48 slew rate selection. */ + __IM uint32_t : 3; + __IOM uint32_t PAD49_DS1 : 1; /*!< [8..8] Pad 49 high order drive strength selection. Used in conjunction + with PAD49STRNG field to set the pad drive strength. */ + __IM uint32_t : 3; + __IOM uint32_t PAD49_SR : 1; /*!< [12..12] Pad 49 slew rate selection. */ + } ALTPADCFGM_b; + } ; + + union { + __IOM uint32_t SCDET; /*!< (@ 0x00000114) SCARD Card Detect select */ + + struct { + __IOM uint32_t SCDET : 6; /*!< [5..0] SCARD card detect pad select. */ + } SCDET_b; + } ; + + union { + __IOM uint32_t CTENCFG; /*!< (@ 0x00000118) Counter/Timer Enable Config */ + + struct { + __IOM uint32_t EN0 : 1; /*!< [0..0] CT0 Enable */ + __IOM uint32_t EN1 : 1; /*!< [1..1] CT1 Enable */ + __IOM uint32_t EN2 : 1; /*!< [2..2] CT2 Enable */ + __IOM uint32_t EN3 : 1; /*!< [3..3] CT3 Enable */ + __IOM uint32_t EN4 : 1; /*!< [4..4] CT4 Enable */ + __IOM uint32_t EN5 : 1; /*!< [5..5] CT5 Enable */ + __IOM uint32_t EN6 : 1; /*!< [6..6] CT6 Enable */ + __IOM uint32_t EN7 : 1; /*!< [7..7] CT7 Enable */ + __IOM uint32_t EN8 : 1; /*!< [8..8] CT8 Enable */ + __IOM uint32_t EN9 : 1; /*!< [9..9] CT9 Enable */ + __IOM uint32_t EN10 : 1; /*!< [10..10] CT10 Enable */ + __IOM uint32_t EN11 : 1; /*!< [11..11] CT11 Enable */ + __IOM uint32_t EN12 : 1; /*!< [12..12] CT12 Enable */ + __IOM uint32_t EN13 : 1; /*!< [13..13] CT13 Enable */ + __IOM uint32_t EN14 : 1; /*!< [14..14] CT14 Enable */ + __IOM uint32_t EN15 : 1; /*!< [15..15] CT15 Enable */ + __IOM uint32_t EN16 : 1; /*!< [16..16] CT16 Enable */ + __IOM uint32_t EN17 : 1; /*!< [17..17] CT17 Enable */ + __IOM uint32_t EN18 : 1; /*!< [18..18] CT18 Enable */ + __IOM uint32_t EN19 : 1; /*!< [19..19] CT19 Enable */ + __IOM uint32_t EN20 : 1; /*!< [20..20] CT20 Enable */ + __IOM uint32_t EN21 : 1; /*!< [21..21] CT21 Enable */ + __IOM uint32_t EN22 : 1; /*!< [22..22] CT22 Enable */ + __IOM uint32_t EN23 : 1; /*!< [23..23] CT23 Enable */ + __IOM uint32_t EN24 : 1; /*!< [24..24] CT24 Enable */ + __IOM uint32_t EN25 : 1; /*!< [25..25] CT25 Enable */ + __IOM uint32_t EN26 : 1; /*!< [26..26] CT26 Enable */ + __IOM uint32_t EN27 : 1; /*!< [27..27] CT27 Enable */ + __IOM uint32_t EN28 : 1; /*!< [28..28] CT28 Enable */ + __IOM uint32_t EN29 : 1; /*!< [29..29] CT29 Enable */ + __IOM uint32_t EN30 : 1; /*!< [30..30] CT30 Enable */ + __IOM uint32_t EN31 : 1; /*!< [31..31] CT31 Enable */ + } CTENCFG_b; + } ; + __IM uint32_t RESERVED4[57]; + + union { + __IOM uint32_t INT0EN; /*!< (@ 0x00000200) GPIO Interrupt Registers 31-0: Enable */ + + struct { + __IOM uint32_t GPIO0 : 1; /*!< [0..0] GPIO0 interrupt. */ + __IOM uint32_t GPIO1 : 1; /*!< [1..1] GPIO1 interrupt. */ + __IOM uint32_t GPIO2 : 1; /*!< [2..2] GPIO2 interrupt. */ + __IOM uint32_t GPIO3 : 1; /*!< [3..3] GPIO3 interrupt. */ + __IOM uint32_t GPIO4 : 1; /*!< [4..4] GPIO4 interrupt. */ + __IOM uint32_t GPIO5 : 1; /*!< [5..5] GPIO5 interrupt. */ + __IOM uint32_t GPIO6 : 1; /*!< [6..6] GPIO6 interrupt. */ + __IOM uint32_t GPIO7 : 1; /*!< [7..7] GPIO7 interrupt. */ + __IOM uint32_t GPIO8 : 1; /*!< [8..8] GPIO8 interrupt. */ + __IOM uint32_t GPIO9 : 1; /*!< [9..9] GPIO9 interrupt. */ + __IOM uint32_t GPIO10 : 1; /*!< [10..10] GPIO10 interrupt. */ + __IOM uint32_t GPIO11 : 1; /*!< [11..11] GPIO11 interrupt. */ + __IOM uint32_t GPIO12 : 1; /*!< [12..12] GPIO12 interrupt. */ + __IOM uint32_t GPIO13 : 1; /*!< [13..13] GPIO13 interrupt. */ + __IOM uint32_t GPIO14 : 1; /*!< [14..14] GPIO14 interrupt. */ + __IOM uint32_t GPIO15 : 1; /*!< [15..15] GPIO15 interrupt. */ + __IOM uint32_t GPIO16 : 1; /*!< [16..16] GPIO16 interrupt. */ + __IOM uint32_t GPIO17 : 1; /*!< [17..17] GPIO17 interrupt. */ + __IOM uint32_t GPIO18 : 1; /*!< [18..18] GPIO18interrupt. */ + __IOM uint32_t GPIO19 : 1; /*!< [19..19] GPIO19 interrupt. */ + __IOM uint32_t GPIO20 : 1; /*!< [20..20] GPIO20 interrupt. */ + __IOM uint32_t GPIO21 : 1; /*!< [21..21] GPIO21 interrupt. */ + __IOM uint32_t GPIO22 : 1; /*!< [22..22] GPIO22 interrupt. */ + __IOM uint32_t GPIO23 : 1; /*!< [23..23] GPIO23 interrupt. */ + __IOM uint32_t GPIO24 : 1; /*!< [24..24] GPIO24 interrupt. */ + __IOM uint32_t GPIO25 : 1; /*!< [25..25] GPIO25 interrupt. */ + __IOM uint32_t GPIO26 : 1; /*!< [26..26] GPIO26 interrupt. */ + __IOM uint32_t GPIO27 : 1; /*!< [27..27] GPIO27 interrupt. */ + __IOM uint32_t GPIO28 : 1; /*!< [28..28] GPIO28 interrupt. */ + __IOM uint32_t GPIO29 : 1; /*!< [29..29] GPIO29 interrupt. */ + __IOM uint32_t GPIO30 : 1; /*!< [30..30] GPIO30 interrupt. */ + __IOM uint32_t GPIO31 : 1; /*!< [31..31] GPIO31 interrupt. */ + } INT0EN_b; + } ; + + union { + __IOM uint32_t INT0STAT; /*!< (@ 0x00000204) GPIO Interrupt Registers 31-0: Status */ + + struct { + __IOM uint32_t GPIO0 : 1; /*!< [0..0] GPIO0 interrupt. */ + __IOM uint32_t GPIO1 : 1; /*!< [1..1] GPIO1 interrupt. */ + __IOM uint32_t GPIO2 : 1; /*!< [2..2] GPIO2 interrupt. */ + __IOM uint32_t GPIO3 : 1; /*!< [3..3] GPIO3 interrupt. */ + __IOM uint32_t GPIO4 : 1; /*!< [4..4] GPIO4 interrupt. */ + __IOM uint32_t GPIO5 : 1; /*!< [5..5] GPIO5 interrupt. */ + __IOM uint32_t GPIO6 : 1; /*!< [6..6] GPIO6 interrupt. */ + __IOM uint32_t GPIO7 : 1; /*!< [7..7] GPIO7 interrupt. */ + __IOM uint32_t GPIO8 : 1; /*!< [8..8] GPIO8 interrupt. */ + __IOM uint32_t GPIO9 : 1; /*!< [9..9] GPIO9 interrupt. */ + __IOM uint32_t GPIO10 : 1; /*!< [10..10] GPIO10 interrupt. */ + __IOM uint32_t GPIO11 : 1; /*!< [11..11] GPIO11 interrupt. */ + __IOM uint32_t GPIO12 : 1; /*!< [12..12] GPIO12 interrupt. */ + __IOM uint32_t GPIO13 : 1; /*!< [13..13] GPIO13 interrupt. */ + __IOM uint32_t GPIO14 : 1; /*!< [14..14] GPIO14 interrupt. */ + __IOM uint32_t GPIO15 : 1; /*!< [15..15] GPIO15 interrupt. */ + __IOM uint32_t GPIO16 : 1; /*!< [16..16] GPIO16 interrupt. */ + __IOM uint32_t GPIO17 : 1; /*!< [17..17] GPIO17 interrupt. */ + __IOM uint32_t GPIO18 : 1; /*!< [18..18] GPIO18interrupt. */ + __IOM uint32_t GPIO19 : 1; /*!< [19..19] GPIO19 interrupt. */ + __IOM uint32_t GPIO20 : 1; /*!< [20..20] GPIO20 interrupt. */ + __IOM uint32_t GPIO21 : 1; /*!< [21..21] GPIO21 interrupt. */ + __IOM uint32_t GPIO22 : 1; /*!< [22..22] GPIO22 interrupt. */ + __IOM uint32_t GPIO23 : 1; /*!< [23..23] GPIO23 interrupt. */ + __IOM uint32_t GPIO24 : 1; /*!< [24..24] GPIO24 interrupt. */ + __IOM uint32_t GPIO25 : 1; /*!< [25..25] GPIO25 interrupt. */ + __IOM uint32_t GPIO26 : 1; /*!< [26..26] GPIO26 interrupt. */ + __IOM uint32_t GPIO27 : 1; /*!< [27..27] GPIO27 interrupt. */ + __IOM uint32_t GPIO28 : 1; /*!< [28..28] GPIO28 interrupt. */ + __IOM uint32_t GPIO29 : 1; /*!< [29..29] GPIO29 interrupt. */ + __IOM uint32_t GPIO30 : 1; /*!< [30..30] GPIO30 interrupt. */ + __IOM uint32_t GPIO31 : 1; /*!< [31..31] GPIO31 interrupt. */ + } INT0STAT_b; + } ; + + union { + __IOM uint32_t INT0CLR; /*!< (@ 0x00000208) GPIO Interrupt Registers 31-0: Clear */ + + struct { + __IOM uint32_t GPIO0 : 1; /*!< [0..0] GPIO0 interrupt. */ + __IOM uint32_t GPIO1 : 1; /*!< [1..1] GPIO1 interrupt. */ + __IOM uint32_t GPIO2 : 1; /*!< [2..2] GPIO2 interrupt. */ + __IOM uint32_t GPIO3 : 1; /*!< [3..3] GPIO3 interrupt. */ + __IOM uint32_t GPIO4 : 1; /*!< [4..4] GPIO4 interrupt. */ + __IOM uint32_t GPIO5 : 1; /*!< [5..5] GPIO5 interrupt. */ + __IOM uint32_t GPIO6 : 1; /*!< [6..6] GPIO6 interrupt. */ + __IOM uint32_t GPIO7 : 1; /*!< [7..7] GPIO7 interrupt. */ + __IOM uint32_t GPIO8 : 1; /*!< [8..8] GPIO8 interrupt. */ + __IOM uint32_t GPIO9 : 1; /*!< [9..9] GPIO9 interrupt. */ + __IOM uint32_t GPIO10 : 1; /*!< [10..10] GPIO10 interrupt. */ + __IOM uint32_t GPIO11 : 1; /*!< [11..11] GPIO11 interrupt. */ + __IOM uint32_t GPIO12 : 1; /*!< [12..12] GPIO12 interrupt. */ + __IOM uint32_t GPIO13 : 1; /*!< [13..13] GPIO13 interrupt. */ + __IOM uint32_t GPIO14 : 1; /*!< [14..14] GPIO14 interrupt. */ + __IOM uint32_t GPIO15 : 1; /*!< [15..15] GPIO15 interrupt. */ + __IOM uint32_t GPIO16 : 1; /*!< [16..16] GPIO16 interrupt. */ + __IOM uint32_t GPIO17 : 1; /*!< [17..17] GPIO17 interrupt. */ + __IOM uint32_t GPIO18 : 1; /*!< [18..18] GPIO18interrupt. */ + __IOM uint32_t GPIO19 : 1; /*!< [19..19] GPIO19 interrupt. */ + __IOM uint32_t GPIO20 : 1; /*!< [20..20] GPIO20 interrupt. */ + __IOM uint32_t GPIO21 : 1; /*!< [21..21] GPIO21 interrupt. */ + __IOM uint32_t GPIO22 : 1; /*!< [22..22] GPIO22 interrupt. */ + __IOM uint32_t GPIO23 : 1; /*!< [23..23] GPIO23 interrupt. */ + __IOM uint32_t GPIO24 : 1; /*!< [24..24] GPIO24 interrupt. */ + __IOM uint32_t GPIO25 : 1; /*!< [25..25] GPIO25 interrupt. */ + __IOM uint32_t GPIO26 : 1; /*!< [26..26] GPIO26 interrupt. */ + __IOM uint32_t GPIO27 : 1; /*!< [27..27] GPIO27 interrupt. */ + __IOM uint32_t GPIO28 : 1; /*!< [28..28] GPIO28 interrupt. */ + __IOM uint32_t GPIO29 : 1; /*!< [29..29] GPIO29 interrupt. */ + __IOM uint32_t GPIO30 : 1; /*!< [30..30] GPIO30 interrupt. */ + __IOM uint32_t GPIO31 : 1; /*!< [31..31] GPIO31 interrupt. */ + } INT0CLR_b; + } ; + + union { + __IOM uint32_t INT0SET; /*!< (@ 0x0000020C) GPIO Interrupt Registers 31-0: Set */ + + struct { + __IOM uint32_t GPIO0 : 1; /*!< [0..0] GPIO0 interrupt. */ + __IOM uint32_t GPIO1 : 1; /*!< [1..1] GPIO1 interrupt. */ + __IOM uint32_t GPIO2 : 1; /*!< [2..2] GPIO2 interrupt. */ + __IOM uint32_t GPIO3 : 1; /*!< [3..3] GPIO3 interrupt. */ + __IOM uint32_t GPIO4 : 1; /*!< [4..4] GPIO4 interrupt. */ + __IOM uint32_t GPIO5 : 1; /*!< [5..5] GPIO5 interrupt. */ + __IOM uint32_t GPIO6 : 1; /*!< [6..6] GPIO6 interrupt. */ + __IOM uint32_t GPIO7 : 1; /*!< [7..7] GPIO7 interrupt. */ + __IOM uint32_t GPIO8 : 1; /*!< [8..8] GPIO8 interrupt. */ + __IOM uint32_t GPIO9 : 1; /*!< [9..9] GPIO9 interrupt. */ + __IOM uint32_t GPIO10 : 1; /*!< [10..10] GPIO10 interrupt. */ + __IOM uint32_t GPIO11 : 1; /*!< [11..11] GPIO11 interrupt. */ + __IOM uint32_t GPIO12 : 1; /*!< [12..12] GPIO12 interrupt. */ + __IOM uint32_t GPIO13 : 1; /*!< [13..13] GPIO13 interrupt. */ + __IOM uint32_t GPIO14 : 1; /*!< [14..14] GPIO14 interrupt. */ + __IOM uint32_t GPIO15 : 1; /*!< [15..15] GPIO15 interrupt. */ + __IOM uint32_t GPIO16 : 1; /*!< [16..16] GPIO16 interrupt. */ + __IOM uint32_t GPIO17 : 1; /*!< [17..17] GPIO17 interrupt. */ + __IOM uint32_t GPIO18 : 1; /*!< [18..18] GPIO18interrupt. */ + __IOM uint32_t GPIO19 : 1; /*!< [19..19] GPIO19 interrupt. */ + __IOM uint32_t GPIO20 : 1; /*!< [20..20] GPIO20 interrupt. */ + __IOM uint32_t GPIO21 : 1; /*!< [21..21] GPIO21 interrupt. */ + __IOM uint32_t GPIO22 : 1; /*!< [22..22] GPIO22 interrupt. */ + __IOM uint32_t GPIO23 : 1; /*!< [23..23] GPIO23 interrupt. */ + __IOM uint32_t GPIO24 : 1; /*!< [24..24] GPIO24 interrupt. */ + __IOM uint32_t GPIO25 : 1; /*!< [25..25] GPIO25 interrupt. */ + __IOM uint32_t GPIO26 : 1; /*!< [26..26] GPIO26 interrupt. */ + __IOM uint32_t GPIO27 : 1; /*!< [27..27] GPIO27 interrupt. */ + __IOM uint32_t GPIO28 : 1; /*!< [28..28] GPIO28 interrupt. */ + __IOM uint32_t GPIO29 : 1; /*!< [29..29] GPIO29 interrupt. */ + __IOM uint32_t GPIO30 : 1; /*!< [30..30] GPIO30 interrupt. */ + __IOM uint32_t GPIO31 : 1; /*!< [31..31] GPIO31 interrupt. */ + } INT0SET_b; + } ; + + union { + __IOM uint32_t INT1EN; /*!< (@ 0x00000210) GPIO Interrupt Registers 49-32: Enable */ + + struct { + __IOM uint32_t GPIO32 : 1; /*!< [0..0] GPIO32 interrupt. */ + __IOM uint32_t GPIO33 : 1; /*!< [1..1] GPIO33 interrupt. */ + __IOM uint32_t GPIO34 : 1; /*!< [2..2] GPIO34 interrupt. */ + __IOM uint32_t GPIO35 : 1; /*!< [3..3] GPIO35 interrupt. */ + __IOM uint32_t GPIO36 : 1; /*!< [4..4] GPIO36 interrupt. */ + __IOM uint32_t GPIO37 : 1; /*!< [5..5] GPIO37 interrupt. */ + __IOM uint32_t GPIO38 : 1; /*!< [6..6] GPIO38 interrupt. */ + __IOM uint32_t GPIO39 : 1; /*!< [7..7] GPIO39 interrupt. */ + __IOM uint32_t GPIO40 : 1; /*!< [8..8] GPIO40 interrupt. */ + __IOM uint32_t GPIO41 : 1; /*!< [9..9] GPIO41 interrupt. */ + __IOM uint32_t GPIO42 : 1; /*!< [10..10] GPIO42 interrupt. */ + __IOM uint32_t GPIO43 : 1; /*!< [11..11] GPIO43 interrupt. */ + __IOM uint32_t GPIO44 : 1; /*!< [12..12] GPIO44 interrupt. */ + __IOM uint32_t GPIO45 : 1; /*!< [13..13] GPIO45 interrupt. */ + __IOM uint32_t GPIO46 : 1; /*!< [14..14] GPIO46 interrupt. */ + __IOM uint32_t GPIO47 : 1; /*!< [15..15] GPIO47 interrupt. */ + __IOM uint32_t GPIO48 : 1; /*!< [16..16] GPIO48 interrupt. */ + __IOM uint32_t GPIO49 : 1; /*!< [17..17] GPIO49 interrupt. */ + } INT1EN_b; + } ; + + union { + __IOM uint32_t INT1STAT; /*!< (@ 0x00000214) GPIO Interrupt Registers 49-32: Status */ + + struct { + __IOM uint32_t GPIO32 : 1; /*!< [0..0] GPIO32 interrupt. */ + __IOM uint32_t GPIO33 : 1; /*!< [1..1] GPIO33 interrupt. */ + __IOM uint32_t GPIO34 : 1; /*!< [2..2] GPIO34 interrupt. */ + __IOM uint32_t GPIO35 : 1; /*!< [3..3] GPIO35 interrupt. */ + __IOM uint32_t GPIO36 : 1; /*!< [4..4] GPIO36 interrupt. */ + __IOM uint32_t GPIO37 : 1; /*!< [5..5] GPIO37 interrupt. */ + __IOM uint32_t GPIO38 : 1; /*!< [6..6] GPIO38 interrupt. */ + __IOM uint32_t GPIO39 : 1; /*!< [7..7] GPIO39 interrupt. */ + __IOM uint32_t GPIO40 : 1; /*!< [8..8] GPIO40 interrupt. */ + __IOM uint32_t GPIO41 : 1; /*!< [9..9] GPIO41 interrupt. */ + __IOM uint32_t GPIO42 : 1; /*!< [10..10] GPIO42 interrupt. */ + __IOM uint32_t GPIO43 : 1; /*!< [11..11] GPIO43 interrupt. */ + __IOM uint32_t GPIO44 : 1; /*!< [12..12] GPIO44 interrupt. */ + __IOM uint32_t GPIO45 : 1; /*!< [13..13] GPIO45 interrupt. */ + __IOM uint32_t GPIO46 : 1; /*!< [14..14] GPIO46 interrupt. */ + __IOM uint32_t GPIO47 : 1; /*!< [15..15] GPIO47 interrupt. */ + __IOM uint32_t GPIO48 : 1; /*!< [16..16] GPIO48 interrupt. */ + __IOM uint32_t GPIO49 : 1; /*!< [17..17] GPIO49 interrupt. */ + } INT1STAT_b; + } ; + + union { + __IOM uint32_t INT1CLR; /*!< (@ 0x00000218) GPIO Interrupt Registers 49-32: Clear */ + + struct { + __IOM uint32_t GPIO32 : 1; /*!< [0..0] GPIO32 interrupt. */ + __IOM uint32_t GPIO33 : 1; /*!< [1..1] GPIO33 interrupt. */ + __IOM uint32_t GPIO34 : 1; /*!< [2..2] GPIO34 interrupt. */ + __IOM uint32_t GPIO35 : 1; /*!< [3..3] GPIO35 interrupt. */ + __IOM uint32_t GPIO36 : 1; /*!< [4..4] GPIO36 interrupt. */ + __IOM uint32_t GPIO37 : 1; /*!< [5..5] GPIO37 interrupt. */ + __IOM uint32_t GPIO38 : 1; /*!< [6..6] GPIO38 interrupt. */ + __IOM uint32_t GPIO39 : 1; /*!< [7..7] GPIO39 interrupt. */ + __IOM uint32_t GPIO40 : 1; /*!< [8..8] GPIO40 interrupt. */ + __IOM uint32_t GPIO41 : 1; /*!< [9..9] GPIO41 interrupt. */ + __IOM uint32_t GPIO42 : 1; /*!< [10..10] GPIO42 interrupt. */ + __IOM uint32_t GPIO43 : 1; /*!< [11..11] GPIO43 interrupt. */ + __IOM uint32_t GPIO44 : 1; /*!< [12..12] GPIO44 interrupt. */ + __IOM uint32_t GPIO45 : 1; /*!< [13..13] GPIO45 interrupt. */ + __IOM uint32_t GPIO46 : 1; /*!< [14..14] GPIO46 interrupt. */ + __IOM uint32_t GPIO47 : 1; /*!< [15..15] GPIO47 interrupt. */ + __IOM uint32_t GPIO48 : 1; /*!< [16..16] GPIO48 interrupt. */ + __IOM uint32_t GPIO49 : 1; /*!< [17..17] GPIO49 interrupt. */ + } INT1CLR_b; + } ; + + union { + __IOM uint32_t INT1SET; /*!< (@ 0x0000021C) GPIO Interrupt Registers 49-32: Set */ + + struct { + __IOM uint32_t GPIO32 : 1; /*!< [0..0] GPIO32 interrupt. */ + __IOM uint32_t GPIO33 : 1; /*!< [1..1] GPIO33 interrupt. */ + __IOM uint32_t GPIO34 : 1; /*!< [2..2] GPIO34 interrupt. */ + __IOM uint32_t GPIO35 : 1; /*!< [3..3] GPIO35 interrupt. */ + __IOM uint32_t GPIO36 : 1; /*!< [4..4] GPIO36 interrupt. */ + __IOM uint32_t GPIO37 : 1; /*!< [5..5] GPIO37 interrupt. */ + __IOM uint32_t GPIO38 : 1; /*!< [6..6] GPIO38 interrupt. */ + __IOM uint32_t GPIO39 : 1; /*!< [7..7] GPIO39 interrupt. */ + __IOM uint32_t GPIO40 : 1; /*!< [8..8] GPIO40 interrupt. */ + __IOM uint32_t GPIO41 : 1; /*!< [9..9] GPIO41 interrupt. */ + __IOM uint32_t GPIO42 : 1; /*!< [10..10] GPIO42 interrupt. */ + __IOM uint32_t GPIO43 : 1; /*!< [11..11] GPIO43 interrupt. */ + __IOM uint32_t GPIO44 : 1; /*!< [12..12] GPIO44 interrupt. */ + __IOM uint32_t GPIO45 : 1; /*!< [13..13] GPIO45 interrupt. */ + __IOM uint32_t GPIO46 : 1; /*!< [14..14] GPIO46 interrupt. */ + __IOM uint32_t GPIO47 : 1; /*!< [15..15] GPIO47 interrupt. */ + __IOM uint32_t GPIO48 : 1; /*!< [16..16] GPIO48 interrupt. */ + __IOM uint32_t GPIO49 : 1; /*!< [17..17] GPIO49 interrupt. */ + } INT1SET_b; + } ; +} GPIO_Type; /*!< Size = 544 (0x220) */ + + + +/* =========================================================================================================================== */ +/* ================ IOM0 ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief IO Peripheral Master (IOM0) + */ + +typedef struct { /*!< (@ 0x50004000) IOM0 Structure */ + + union { + __IOM uint32_t FIFO; /*!< (@ 0x00000000) FIFO Access Port */ + + struct { + __IOM uint32_t FIFO : 32; /*!< [31..0] FIFO direct access. Only locations 0 - 3F will return + valid information. */ + } FIFO_b; + } ; + __IM uint32_t RESERVED[63]; + + union { + __IOM uint32_t FIFOPTR; /*!< (@ 0x00000100) FIFO size and remaining slots open values */ + + struct { + __IOM uint32_t FIFO0SIZ : 8; /*!< [7..0] The number of valid data bytes currently in the FIFO + 0 (written by MCU, read by interface) */ + __IOM uint32_t FIFO0REM : 8; /*!< [15..8] The number of remaining data bytes slots currently in + FIFO 0 (written by MCU, read by interface) */ + __IOM uint32_t FIFO1SIZ : 8; /*!< [23..16] The number of valid data bytes currently in FIFO 1 + (written by interface, read by MCU) */ + __IOM uint32_t FIFO1REM : 8; /*!< [31..24] The number of remaining data bytes slots currently + in FIFO 1 (written by interface, read by MCU) */ + } FIFOPTR_b; + } ; + + union { + __IOM uint32_t FIFOTHR; /*!< (@ 0x00000104) FIFO Threshold Configuration */ + + struct { + __IOM uint32_t FIFORTHR : 6; /*!< [5..0] FIFO read threshold in bytes. A value of 0 will disable + the read FIFO level from activating the threshold interrupt. + If this field is non-zero, it will trigger a threshold + interrupt when the read fifo contains FIFORTHR valid bytes + of data, as indicated by the FIFO1SIZ field. This is intended + to signal when a data transfer of FIFORTHR bytes can be + done from the IOM module to the host via the read fifo + to support large IOM read operations. */ + __IM uint32_t : 2; + __IOM uint32_t FIFOWTHR : 6; /*!< [13..8] FIFO write threshold in bytes. A value of 0 will disable + the write FIFO level from activating the threshold interrupt. + If this field is non-zero, it will trigger a threshold + interrupt when the write fifo contains FIFOWTHR free bytes, + as indicated by the FIFO0REM field. This is intended to + signal when a transfer of FIFOWTHR bytes can be done from + the host to the IOM write fifo to support large IOM write + operations. */ + } FIFOTHR_b; + } ; + + union { + __IOM uint32_t FIFOPOP; /*!< (@ 0x00000108) FIFO POP register */ + + struct { + __IOM uint32_t FIFODOUT : 32; /*!< [31..0] This register will return the read data indicated by + the current read pointer on reads. If the POPWR control + bit in the FIFOCTRL register is reset (0), the fifo read + pointer will be advanced by one word as a result of the + read.If the POPWR bit is set (1), the fifo read pointer + will only be advanced after a write operation to this register. + The write data is ignored for this register.If less than + a even word multiple is available, and the command is completed, + the module will return the word containing */ + } FIFOPOP_b; + } ; + + union { + __IOM uint32_t FIFOPUSH; /*!< (@ 0x0000010C) FIFO PUSH register */ + + struct { + __IOM uint32_t FIFODIN : 32; /*!< [31..0] This register is used to write the FIFORAM in FIFO mode + and will cause a push event to occur to the next open slot + within the FIFORAM. Writing to this register will cause + the write point to increment by 1 word(4 bytes). */ + } FIFOPUSH_b; + } ; + + union { + __IOM uint32_t FIFOCTRL; /*!< (@ 0x00000110) FIFO Control Register */ + + struct { + __IOM uint32_t POPWR : 1; /*!< [0..0] Selects the mode in which 'pop' events are done for the + fifo read operations. A value of '1' will prevent a pop + event on a read operation, and will require a write to + the FIFOPOP register to create a pop event.A value of '0' + in this register will allow a pop event to occur on the + read of the FIFOPOP register, and may cause inadvertant + fifo pops when used in a debugging mode. */ + __IOM uint32_t FIFORSTN : 1; /*!< [1..1] Active low manual reset of the fifo. Write to 0 to reset + fifo, and then write to 1 to remove the reset. */ + } FIFOCTRL_b; + } ; + + union { + __IOM uint32_t FIFOLOC; /*!< (@ 0x00000114) FIFO Pointers */ + + struct { + __IOM uint32_t FIFOWPTR : 4; /*!< [3..0] Current FIFO write pointer. Value is the index into the + outgoing FIFO (FIFO0), which is used during write operations + to external devices. */ + __IM uint32_t : 4; + __IOM uint32_t FIFORPTR : 4; /*!< [11..8] Current FIFO read pointer. Used to index into the incoming + FIFO (FIFO1), which is used to store read data returned + from external devices during a read operation. */ + } FIFOLOC_b; + } ; + __IM uint32_t RESERVED1[58]; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000200) IO Master Interrupts: Enable */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current + operation has completed. For repeated commands, this will + only be asserted when the final repeated command is completed. */ + __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted + when the number of free bytes in the write FIFO equals + or exceeds the WTHR field.For read operations, asserted + when the number of valid bytes in the read FIFO equals + of exceeds the value set in the RTHR field. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. This occurs when software + tries to pop from an empty fifo. */ + __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software + tries to write to a full fifo. The current operation does + not stop. */ + __IOM uint32_t NAK : 1; /*!< [4..4] I2C NAK interrupt. Asserted when an unexpected NAK has + been received on the I2C bus. */ + __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is + a overflow or underflow event */ + __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is + written when an active command is in progress. */ + __IOM uint32_t START : 1; /*!< [7..7] START command interrupt. Asserted when another master + on the bus has signaled a START command. */ + __IOM uint32_t STOP : 1; /*!< [8..8] STOP command interrupt. Asserted when another master + on the bus has signaled a STOP command. */ + __IOM uint32_t ARB : 1; /*!< [9..9] Arbitration loss interrupt. Asserted when arbitration + is enabled and has been lost to another master on the bus. */ + __IOM uint32_t DCMP : 1; /*!< [10..10] DMA Complete. Processing of the DMA operation has completed + and the DMA submodule is returned into the idle state */ + __IOM uint32_t DERR : 1; /*!< [11..11] DMA Error encountered during the processing of the + DMA command. The DMA error could occur when the memory + access specified in the DMA operation is not available + or incorrectly specified. */ + __IOM uint32_t CQPAUSED : 1; /*!< [12..12] Command queue is paused due to an active event enabled + in the PAUSEEN register. The interrupt is posted when the + event is enabled within the PAUSEEN register, the mask + is active in the CQIRQMASK field and the event occurs. */ + __IOM uint32_t CQUPD : 1; /*!< [13..13] CQ write operation performed a register write with + the register address bit 0 set to 1. The low address bits + in the CQ address fields are unused and bit 0 can be used + to trigger an interrupt to indicate when this register + write is performed by the CQ operation. */ + __IOM uint32_t CQERR : 1; /*!< [14..14] Error during command queue operations */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) IO Master Interrupts: Status */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current + operation has completed. For repeated commands, this will + only be asserted when the final repeated command is completed. */ + __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted + when the number of free bytes in the write FIFO equals + or exceeds the WTHR field.For read operations, asserted + when the number of valid bytes in the read FIFO equals + of exceeds the value set in the RTHR field. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. This occurs when software + tries to pop from an empty fifo. */ + __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software + tries to write to a full fifo. The current operation does + not stop. */ + __IOM uint32_t NAK : 1; /*!< [4..4] I2C NAK interrupt. Asserted when an unexpected NAK has + been received on the I2C bus. */ + __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is + a overflow or underflow event */ + __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is + written when an active command is in progress. */ + __IOM uint32_t START : 1; /*!< [7..7] START command interrupt. Asserted when another master + on the bus has signaled a START command. */ + __IOM uint32_t STOP : 1; /*!< [8..8] STOP command interrupt. Asserted when another master + on the bus has signaled a STOP command. */ + __IOM uint32_t ARB : 1; /*!< [9..9] Arbitration loss interrupt. Asserted when arbitration + is enabled and has been lost to another master on the bus. */ + __IOM uint32_t DCMP : 1; /*!< [10..10] DMA Complete. Processing of the DMA operation has completed + and the DMA submodule is returned into the idle state */ + __IOM uint32_t DERR : 1; /*!< [11..11] DMA Error encountered during the processing of the + DMA command. The DMA error could occur when the memory + access specified in the DMA operation is not available + or incorrectly specified. */ + __IOM uint32_t CQPAUSED : 1; /*!< [12..12] Command queue is paused due to an active event enabled + in the PAUSEEN register. The interrupt is posted when the + event is enabled within the PAUSEEN register, the mask + is active in the CQIRQMASK field and the event occurs. */ + __IOM uint32_t CQUPD : 1; /*!< [13..13] CQ write operation performed a register write with + the register address bit 0 set to 1. The low address bits + in the CQ address fields are unused and bit 0 can be used + to trigger an interrupt to indicate when this register + write is performed by the CQ operation. */ + __IOM uint32_t CQERR : 1; /*!< [14..14] Error during command queue operations */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000208) IO Master Interrupts: Clear */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current + operation has completed. For repeated commands, this will + only be asserted when the final repeated command is completed. */ + __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted + when the number of free bytes in the write FIFO equals + or exceeds the WTHR field.For read operations, asserted + when the number of valid bytes in the read FIFO equals + of exceeds the value set in the RTHR field. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. This occurs when software + tries to pop from an empty fifo. */ + __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software + tries to write to a full fifo. The current operation does + not stop. */ + __IOM uint32_t NAK : 1; /*!< [4..4] I2C NAK interrupt. Asserted when an unexpected NAK has + been received on the I2C bus. */ + __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is + a overflow or underflow event */ + __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is + written when an active command is in progress. */ + __IOM uint32_t START : 1; /*!< [7..7] START command interrupt. Asserted when another master + on the bus has signaled a START command. */ + __IOM uint32_t STOP : 1; /*!< [8..8] STOP command interrupt. Asserted when another master + on the bus has signaled a STOP command. */ + __IOM uint32_t ARB : 1; /*!< [9..9] Arbitration loss interrupt. Asserted when arbitration + is enabled and has been lost to another master on the bus. */ + __IOM uint32_t DCMP : 1; /*!< [10..10] DMA Complete. Processing of the DMA operation has completed + and the DMA submodule is returned into the idle state */ + __IOM uint32_t DERR : 1; /*!< [11..11] DMA Error encountered during the processing of the + DMA command. The DMA error could occur when the memory + access specified in the DMA operation is not available + or incorrectly specified. */ + __IOM uint32_t CQPAUSED : 1; /*!< [12..12] Command queue is paused due to an active event enabled + in the PAUSEEN register. The interrupt is posted when the + event is enabled within the PAUSEEN register, the mask + is active in the CQIRQMASK field and the event occurs. */ + __IOM uint32_t CQUPD : 1; /*!< [13..13] CQ write operation performed a register write with + the register address bit 0 set to 1. The low address bits + in the CQ address fields are unused and bit 0 can be used + to trigger an interrupt to indicate when this register + write is performed by the CQ operation. */ + __IOM uint32_t CQERR : 1; /*!< [14..14] Error during command queue operations */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000020C) IO Master Interrupts: Set */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current + operation has completed. For repeated commands, this will + only be asserted when the final repeated command is completed. */ + __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted + when the number of free bytes in the write FIFO equals + or exceeds the WTHR field.For read operations, asserted + when the number of valid bytes in the read FIFO equals + of exceeds the value set in the RTHR field. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. This occurs when software + tries to pop from an empty fifo. */ + __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software + tries to write to a full fifo. The current operation does + not stop. */ + __IOM uint32_t NAK : 1; /*!< [4..4] I2C NAK interrupt. Asserted when an unexpected NAK has + been received on the I2C bus. */ + __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is + a overflow or underflow event */ + __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is + written when an active command is in progress. */ + __IOM uint32_t START : 1; /*!< [7..7] START command interrupt. Asserted when another master + on the bus has signaled a START command. */ + __IOM uint32_t STOP : 1; /*!< [8..8] STOP command interrupt. Asserted when another master + on the bus has signaled a STOP command. */ + __IOM uint32_t ARB : 1; /*!< [9..9] Arbitration loss interrupt. Asserted when arbitration + is enabled and has been lost to another master on the bus. */ + __IOM uint32_t DCMP : 1; /*!< [10..10] DMA Complete. Processing of the DMA operation has completed + and the DMA submodule is returned into the idle state */ + __IOM uint32_t DERR : 1; /*!< [11..11] DMA Error encountered during the processing of the + DMA command. The DMA error could occur when the memory + access specified in the DMA operation is not available + or incorrectly specified. */ + __IOM uint32_t CQPAUSED : 1; /*!< [12..12] Command queue is paused due to an active event enabled + in the PAUSEEN register. The interrupt is posted when the + event is enabled within the PAUSEEN register, the mask + is active in the CQIRQMASK field and the event occurs. */ + __IOM uint32_t CQUPD : 1; /*!< [13..13] CQ write operation performed a register write with + the register address bit 0 set to 1. The low address bits + in the CQ address fields are unused and bit 0 can be used + to trigger an interrupt to indicate when this register + write is performed by the CQ operation. */ + __IOM uint32_t CQERR : 1; /*!< [14..14] Error during command queue operations */ + } INTSET_b; + } ; + + union { + __IOM uint32_t CLKCFG; /*!< (@ 0x00000210) I/O Clock Configuration */ + + struct { + __IOM uint32_t IOCLKEN : 1; /*!< [0..0] Enable for the interface clock. Must be enabled prior + to executing any IO operations. */ + __IM uint32_t : 7; + __IOM uint32_t FSEL : 3; /*!< [10..8] Select the input clock frequency. */ + __IOM uint32_t DIV3 : 1; /*!< [11..11] Enable divide by 3 of the source IOCLK. Division by + 3 is done before the DIVEN programmable divider, and if + enabledwill provide the divided by 3 clock as the source + to the programmable divider. */ + __IOM uint32_t DIVEN : 1; /*!< [12..12] Enable clock division by TOTPER and LOWPER */ + __IM uint32_t : 3; + __IOM uint32_t LOWPER : 8; /*!< [23..16] Clock low clock count minus 1. This provides the number + of clocks the divided clock will be low when the DIVEN + = 1.Only applicable when DIVEN = 1. */ + __IOM uint32_t TOTPER : 8; /*!< [31..24] Clock total clock count minus 1. This provides the + total period of the divided clock -1 when the DIVEN is + active. Thesource clock is selected by FSEL. Only applicable + when DIVEN = 1. */ + } CLKCFG_b; + } ; + + union { + __IOM uint32_t SUBMODCTRL; /*!< (@ 0x00000214) Submodule control */ + + struct { + __IOM uint32_t SMOD0EN : 1; /*!< [0..0] Submodule 0 enable (1) or disable (0) */ + __IOM uint32_t SMOD0TYPE : 3; /*!< [3..1] Submodule 0 module type. This is the SPI Master interface. */ + __IOM uint32_t SMOD1EN : 1; /*!< [4..4] Submodule 1 enable (1) or disable (0) */ + __IOM uint32_t SMOD1TYPE : 3; /*!< [7..5] Submodule 0 module type. This is the I2C Master interface */ + } SUBMODCTRL_b; + } ; + + union { + __IOM uint32_t CMD; /*!< (@ 0x00000218) Command and offset Register */ + + struct { + __IOM uint32_t CMD : 5; /*!< [4..0] Command for submodule. */ + __IOM uint32_t OFFSETCNT : 2; /*!< [6..5] Number of offset bytes to use for the command - 0, 1, + 2, 3 are valid selections. The second (byte 1) and third + byte (byte 2) are read from the OFFSETHI register, and + the low order byte is pulled from this register in the + OFFSETLO field.Offset bytes are transmitted highest byte + first. EG if offsetcnt == 3, OFFSETHI[15:8] will be transmitted + first, then OFFSETHI[7:0] then OFFSETLO.If offsetcnt == + 2, OFFSETHI[7:0] will be transmitted, then OFFSETLO.If + offsetcnt == 1, only OFFSETLO will be transmitted. */ + __IOM uint32_t CONT : 1; /*!< [7..7] Contine to hold the bus after the current transaction + if set to a 1 with a new command issued. */ + __IOM uint32_t TSIZE : 12; /*!< [19..8] Defines the transaction size in bytes. The offset transfer + is not included in this size. */ + __IOM uint32_t CMDSEL : 2; /*!< [21..20] Command Specific selection information. Not used in + Master I2C. Used as CEn select for Master SPI transactions */ + __IM uint32_t : 2; + __IOM uint32_t OFFSETLO : 8; /*!< [31..24] This register holds the low order byte of offset to + be used in the transaction. The number of offset bytes + to use is set with bits 1:0 of the command. */ + } CMD_b; + } ; + + union { + __IOM uint32_t CMDRPT; /*!< (@ 0x0000021C) Command Repeat Register */ + + struct { + __IOM uint32_t CMDRPT : 5; /*!< [4..0] Count of number of times to repeat the next command. */ + } CMDRPT_b; + } ; + + union { + __IOM uint32_t OFFSETHI; /*!< (@ 0x00000220) High order 2 bytes of 3 byte offset for IO transaction */ + + struct { + __IOM uint32_t OFFSETHI : 16; /*!< [15..0] Holds the high order 2 bytes of the 3 byte addressing/offset + field to use with IO commands. The number of offset bytes + to use is specified in the command register */ + } OFFSETHI_b; + } ; + + union { + __IOM uint32_t CMDSTAT; /*!< (@ 0x00000224) Command status */ + + struct { + __IOM uint32_t CCMD : 5; /*!< [4..0] current command that is being executed */ + __IOM uint32_t CMDSTAT : 3; /*!< [7..5] The current status of the command execution. */ + __IOM uint32_t CTSIZE : 12; /*!< [19..8] The current number of bytes still to be transferred + with this command. This field will count down to zero. */ + } CMDSTAT_b; + } ; + __IM uint32_t RESERVED2[6]; + + union { + __IOM uint32_t DMATRIGEN; /*!< (@ 0x00000240) DMA Trigger Enable Register */ + + struct { + __IOM uint32_t DCMDCMPEN : 1; /*!< [0..0] Trigger DMA upon command complete. Enables the trigger + of the DMA when a command is completed. When this event + is triggered, the number of words transferred will be the + lesser of the remaining TOTCOUNT bytes, or */ + __IOM uint32_t DTHREN : 1; /*!< [1..1] Trigger DMA upon THR level reached. For M2P DMA operations + (IOM writes), the trigger will assert when the write FIFO + has (WTHR/4) number of words free in the write FIFO, and + will transfer (WTHR/4) number of wordsor, if the number + of words left to transfer is less than the WTHR value, + will transfer the remaining byte count.For P2M DMA operations, + the trigger will assert when the read FIFO has (RTHR/4) + words available in the read FIFO, and will transfer (RTHR/4) + words to SRAM. This trigger will NOT asser */ + } DMATRIGEN_b; + } ; + + union { + __IOM uint32_t DMATRIGSTAT; /*!< (@ 0x00000244) DMA Trigger Status Register */ + + struct { + __IOM uint32_t DCMDCMP : 1; /*!< [0..0] Triggered DMA from Command complete event. Bit is read + only and can be cleared by disabling the DCMDCMP trigger + enable or by disabling DMA. */ + __IOM uint32_t DTHR : 1; /*!< [1..1] Triggered DMA from THR event. Bit is read only and can + be cleared by disabling the DTHR trigger enable or by disabling + DMA. */ + __IOM uint32_t DTOTCMP : 1; /*!< [2..2] DMA triggered when DCMDCMP = 0, and the amount of data + in the FIFO was enough to complete the DMA operation (greater + than or equal to current TOTCOUNT) when the command completed. + This trigger is default active when the DCMDCMP trigger + isdisabled and there is enough data in the FIFO to complete + the DMA operation. */ + } DMATRIGSTAT_b; + } ; + __IM uint32_t RESERVED3[14]; + + union { + __IOM uint32_t DMACFG; /*!< (@ 0x00000280) DMA Configuration Register */ + + struct { + __IOM uint32_t DMAEN : 1; /*!< [0..0] DMA Enable. Setting this bit to EN will start the DMA + operation. This should be the last DMA related register + set prior to issuing the command */ + __IOM uint32_t DMADIR : 1; /*!< [1..1] Direction */ + __IM uint32_t : 6; + __IOM uint32_t DMAPRI : 1; /*!< [8..8] Sets the Priority of the DMA request */ + __IOM uint32_t DPWROFF : 1; /*!< [9..9] Power off module after DMA is complete. If this bit is + active, the module will request to power off the supply + it is attached to. If there are other units still requiring + power from the same domain, power down will not be performed. */ + } DMACFG_b; + } ; + __IM uint32_t RESERVED4; + + union { + __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x00000288) DMA Total Transfer Count */ + + struct { + __IOM uint32_t TOTCOUNT : 12; /*!< [11..0] Triggered DMA from Command complete event occured. Bit + is read only and can be cleared by disabling the DTHR trigger + enable or by disabling DMA. */ + } DMATOTCOUNT_b; + } ; + + union { + __IOM uint32_t DMATARGADDR; /*!< (@ 0x0000028C) DMA Target Address Register */ + + struct { + __IOM uint32_t TARGADDR : 20; /*!< [19..0] Bits [19:0] of the target byte address for source of + DMA (either read or write). The address can be any byte + alignment, and does not have to be word aligned. In cases + of non-word aligned addresses, the DMA logic will take + care for ensuring only the target bytes are read/written. */ + __IM uint32_t : 8; + __IOM uint32_t TARGADDR28 : 1; /*!< [28..28] Bit 28 of the target byte address for source of DMA + (either read or write). In cases of non-word aligned addresses, + the DMA logic will take care for ensuring only the target + bytes are read/written.Setting to '1' will select the SRAM. + Setting to '0' will select the flash */ + } DMATARGADDR_b; + } ; + + union { + __IOM uint32_t DMASTAT; /*!< (@ 0x00000290) DMA Status Register */ + + struct { + __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress indicator. 1 will indicate that + a DMA transfer is active. The DMA transfer may be waiting + on data, transferring data, or waiting for priority.All + of these will be indicated with a 1. A 0 will indicate + that the DMA is fully complete and no further transactions + will be done. This bit is read only. */ + __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete. This signals the end of the DMA + operation. This bit can be cleared by writing to 0, and + will also be cleared when a new DMA is started. */ + __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error. This active high bit signals an error was + encountered during the DMA operation. The bit can be cleared + by writing to 0. Once set, this bit will remain set until + cleared by software. */ + } DMASTAT_b; + } ; + + union { + __IOM uint32_t CQCFG; /*!< (@ 0x00000294) Command Queue Configuration Register */ + + struct { + __IOM uint32_t CQEN : 1; /*!< [0..0] Command queue enable. When set, will enable the processing + of the command queue and fetches of address/data pairs + will proceed from the word address within the CQADDR register. + Can be disabledusing a CQ executed write to this bit as + well. */ + __IOM uint32_t CQPRI : 1; /*!< [1..1] Sets the Priority of the command queue dma request */ + } CQCFG_b; + } ; + + union { + __IOM uint32_t CQADDR; /*!< (@ 0x00000298) CQ Target Read Address Register */ + + struct { + __IM uint32_t : 2; + __IOM uint32_t CQADDR : 18; /*!< [19..2] Bits 19:2 of target byte address for source of CQ (read + only). The buffer must be aligned on a word boundary */ + __IM uint32_t : 8; + __IOM uint32_t CQADDR28 : 1; /*!< [28..28] Bit 28 of target byte address for source of CQ (read + only). Used to denote Flash (0) or SRAM (1) access */ + } CQADDR_b; + } ; + + union { + __IOM uint32_t CQSTAT; /*!< (@ 0x0000029C) Command Queue Status Register */ + + struct { + __IOM uint32_t CQTIP : 1; /*!< [0..0] Command queue Transfer In Progress indicator. 1 will + indicate that a CQ transfer is active and this will remain + active even when paused waiting for external event. */ + __IOM uint32_t CQPAUSED : 1; /*!< [1..1] Command queue operation is currently paused. */ + __IOM uint32_t CQERR : 1; /*!< [2..2] Command queue processing Error. This active high bit + signals that an error was encountered during the CQ operation. */ + } CQSTAT_b; + } ; + + union { + __IOM uint32_t CQFLAGS; /*!< (@ 0x000002A0) Command Queue Flag Register */ + + struct { + __IOM uint32_t CQFLAGS : 16; /*!< [15..0] Current flag status (read-only). Bits [7:0] are software + controllable and bits [15:8] are hardware status. */ + __IOM uint32_t CQIRQMASK : 16; /*!< [31..16] Mask the bits used to generate the command queue interrupt. + A '1' in the bit position will enable the pause event to + trigger the interrupt, if the CQWT_int interrupt is enabled. + Bits definitions are the same as CQPAUSE */ + } CQFLAGS_b; + } ; + + union { + __IOM uint32_t CQSETCLEAR; /*!< (@ 0x000002A4) Command Queue Flag Set/Clear Register */ + + struct { + __IOM uint32_t CQFSET : 8; /*!< [7..0] Set CQFlag status bits. Will set to 1 the value of any + SWFLAG with a '1' in the corresponding bit position of + this field */ + __IOM uint32_t CQFTGL : 8; /*!< [15..8] Toggle the indicated bit. Will toggle the value of any + SWFLAG with a '1' in the corresponding bit position of + this field */ + __IOM uint32_t CQFCLR : 8; /*!< [23..16] Clear CQFlag status bits. Will clear to 0 any SWFLAG + with a '1' in the corresponding bit position of this field */ + } CQSETCLEAR_b; + } ; + + union { + __IOM uint32_t CQPAUSEEN; /*!< (@ 0x000002A8) Command Queue Pause Enable Register */ + + struct { + __IOM uint32_t CQPEN : 16; /*!< [15..0] Enables the specified event to pause command processing + when active */ + } CQPAUSEEN_b; + } ; + + union { + __IOM uint32_t CQCURIDX; /*!< (@ 0x000002AC) IOM Command Queue current index value . Compared + to the CQENDIDX reg contents to generate + the IDXEQ Pause event for command queue */ + + struct { + __IOM uint32_t CQCURIDX : 8; /*!< [7..0] Holds 8 bits of data that will be compared with the CQENDIX + register field. If the values match, the IDXEQ pause event + will be activated, which will cause the pausing of command + quue operation if the IDXEQ bit is enabled in CQPAUSEEN. */ + } CQCURIDX_b; + } ; + + union { + __IOM uint32_t CQENDIDX; /*!< (@ 0x000002B0) IOM Command Queue current index value . Compared + to the CQCURIDX reg contents to generate + the IDXEQ Pause event for command queue */ + + struct { + __IOM uint32_t CQENDIDX : 8; /*!< [7..0] Holds 8 bits of data that will be compared with the CQCURIX + register field. If the values match, the IDXEQ pause event + will be activated, which will cause the pausing of command + quue operation if the IDXEQ bit is enabled in CQPAUSEEN. */ + } CQENDIDX_b; + } ; + + union { + __IOM uint32_t STATUS; /*!< (@ 0x000002B4) IOM Module Status Register */ + + struct { + __IOM uint32_t ERR : 1; /*!< [0..0] Bit has been deprecated. Please refer to the other error + indicators. This will always return 0. */ + __IOM uint32_t CMDACT : 1; /*!< [1..1] Indicates if the active I/O Command is currently processing + a transaction, or command is complete, but the FIFO pointers + are still syncronizing internally. This bit will go high + atthe start of the transaction, and will go low when the + command is complete, and the data and pointers within the + FIFO have been syncronized. */ + __IOM uint32_t IDLEST : 1; /*!< [2..2] indicates if the active I/O state machine is IDLE. Note + - The state machine could be in idle state due to holdoffs + from data availability, or as the command gets propagated + into the logic from the registers. */ + } STATUS_b; + } ; + __IM uint32_t RESERVED5[18]; + + union { + __IOM uint32_t MSPICFG; /*!< (@ 0x00000300) SPI module master configuration */ + + struct { + __IOM uint32_t SPOL : 1; /*!< [0..0] selects SPI polarity. */ + __IOM uint32_t SPHA : 1; /*!< [1..1] selects SPI phase. */ + __IOM uint32_t FULLDUP : 1; /*!< [2..2] Enables full duplex mode for Master SPI write operations. + Data will be captured simultaneously into the read fifo */ + __IM uint32_t : 13; + __IOM uint32_t WTFC : 1; /*!< [16..16] enables write mode flow control. */ + __IOM uint32_t RDFC : 1; /*!< [17..17] enables read mode flow control. */ + __IOM uint32_t MOSIINV : 1; /*!< [18..18] inverts MOSI when flow control is enabled. */ + __IM uint32_t : 1; + __IOM uint32_t WTFCIRQ : 1; /*!< [20..20] selects the write mode flow control signal. */ + __IOM uint32_t WTFCPOL : 1; /*!< [21..21] selects the write flow control signal polarity. The + transfers are halted when the selected flow control signal + is OPPOSITE polarity of bit. (For example: WTFCPOL = 0 + will allow a IRQ=1 to pause transfers). */ + __IOM uint32_t RDFCPOL : 1; /*!< [22..22] selects the read flow control signal polarity. */ + __IOM uint32_t SPILSB : 1; /*!< [23..23] Selects data transfer as MSB first (0) or LSB first + (1) for the data portion of the SPI transaction. The offset + bytes are always transmitted MSB first. */ + __IOM uint32_t DINDLY : 3; /*!< [26..24] Delay tap to use for the input signal (MISO). This + gives more hold time on the input data. */ + __IOM uint32_t DOUTDLY : 3; /*!< [29..27] Delay tap to use for the output signal (MOSI). This + give more hold time on the output data */ + __IOM uint32_t MSPIRST : 1; /*!< [30..30] Not used. To reset the module, toggle the SMOD_EN for + the module */ + } MSPICFG_b; + } ; + __IM uint32_t RESERVED6[63]; + + union { + __IOM uint32_t MI2CCFG; /*!< (@ 0x00000400) I2C Master configuration */ + + struct { + __IOM uint32_t ADDRSZ : 1; /*!< [0..0] Sets the I2C master device address size to either 7b + (0) or 10b (1). */ + __IOM uint32_t I2CLSB : 1; /*!< [1..1] Direction of data transmit and receive, MSB(0) or LSB(1) + first. Default per I2C specification is MSB first. This + applies to both read and write data, and read data will + be bit */ + __IOM uint32_t ARBEN : 1; /*!< [2..2] Enables multi-master arbitration for the I2C master. + If the bus is known to have only a single master, this + function can be disabled to save clock cycles on I2C transactions */ + __IM uint32_t : 1; + __IOM uint32_t SDADLY : 2; /*!< [5..4] Delay to enable on the SDA output. Values are 0x0-0x3. */ + __IOM uint32_t MI2CRST : 1; /*!< [6..6] Not used. To reset the module, toggle the SMOD_EN for + the module */ + __IM uint32_t : 1; + __IOM uint32_t SCLENDLY : 4; /*!< [11..8] Number of IOCLK cycles to delay the rising edge of the + SCL output en (clock will go low on this edge). Used to + allow clock shaping. */ + __IOM uint32_t SDAENDLY : 4; /*!< [15..12] Number of IOCLK cycles to delay the SDA output en (all + transitions affected). Used to delay data relative to clock */ + __IOM uint32_t SMPCNT : 8; /*!< [23..16] Number of Base clk cycles to wait before sampling the + SCL clock to determine if a clock stretch event has occured */ + __IOM uint32_t STRDIS : 1; /*!< [24..24] Disable detection of clock stretch events smaller than + 1 cycle */ + } MI2CCFG_b; + } ; + + union { + __IOM uint32_t DEVCFG; /*!< (@ 0x00000404) I2C Device Configuration register */ + + struct { + __IOM uint32_t DEVADDR : 10; /*!< [9..0] I2C address of the device that the Master will use to + target for read/write operations. This can be either a + 7b or 10b address. */ + } DEVCFG_b; + } ; + __IM uint32_t RESERVED7[2]; + + union { + __IOM uint32_t IOMDBG; /*!< (@ 0x00000410) IOM Debug Register */ + + struct { + __IOM uint32_t DBGEN : 1; /*!< [0..0] Debug Enable. Setting bit will enable the update of data + within this register, otherwise it is clock gated for power + savings */ + __IOM uint32_t IOCLKON : 1; /*!< [1..1] IOCLK debug clock control. Enable IO_CLK to be active + when this bit is '1'. Otherwise, the clock is controlled + with gating from the logic as needed. */ + __IOM uint32_t APBCLKON : 1; /*!< [2..2] APBCLK debug clock control. Enable APB_CLK to be active + when this bit is '1'. Otherwise, the clock is controlled + with gating from the logic as needed. */ + __IOM uint32_t DBGDATA : 29; /*!< [31..3] Debug control for various options. DBGDATA[1:0] is used + to select between different debug data available in the + DBG0 and DBG1 registers. */ + } IOMDBG_b; + } ; +} IOM0_Type; /*!< Size = 1044 (0x414) */ + + + +/* =========================================================================================================================== */ +/* ================ IOSLAVE ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief I2C/SPI Slave (IOSLAVE) + */ + +typedef struct { /*!< (@ 0x50000000) IOSLAVE Structure */ + __IM uint32_t RESERVED[64]; + + union { + __IOM uint32_t FIFOPTR; /*!< (@ 0x00000100) Current FIFO Pointer */ + + struct { + __IOM uint32_t FIFOPTR : 8; /*!< [7..0] Current FIFO pointer. */ + __IOM uint32_t FIFOSIZ : 8; /*!< [15..8] The number of bytes currently in the hardware FIFO. */ + } FIFOPTR_b; + } ; + + union { + __IOM uint32_t FIFOCFG; /*!< (@ 0x00000104) FIFO Configuration */ + + struct { + __IOM uint32_t FIFOBASE : 5; /*!< [4..0] These bits hold the base address of the I/O FIFO in 8 + byte segments. The IO Slave FIFO is situated in LRAM at + (FIFOBASE*8) to (FIFOMAX*8-1). */ + __IM uint32_t : 3; + __IOM uint32_t FIFOMAX : 6; /*!< [13..8] These bits hold the maximum FIFO address in 8 byte segments. + It is also the beginning of the RAM area of the LRAM. Note + that no RAM area is configured if FIFOMAX is set to 0x1F. */ + __IM uint32_t : 10; + __IOM uint32_t ROBASE : 6; /*!< [29..24] Defines the read-only area. The IO Slave read-only + area is situated in LRAM at (ROBASE*8) to (FIFOBASE*8-1) */ + } FIFOCFG_b; + } ; + + union { + __IOM uint32_t FIFOTHR; /*!< (@ 0x00000108) FIFO Threshold Configuration */ + + struct { + __IOM uint32_t FIFOTHR : 8; /*!< [7..0] FIFO size interrupt threshold. */ + } FIFOTHR_b; + } ; + + union { + __IOM uint32_t FUPD; /*!< (@ 0x0000010C) FIFO Update Status */ + + struct { + __IOM uint32_t FIFOUPD : 1; /*!< [0..0] This bit indicates that a FIFO update is underway. */ + __IOM uint32_t IOREAD : 1; /*!< [1..1] This bitfield indicates an IO read is active. */ + } FUPD_b; + } ; + + union { + __IOM uint32_t FIFOCTR; /*!< (@ 0x00000110) Overall FIFO Counter */ + + struct { + __IOM uint32_t FIFOCTR : 10; /*!< [9..0] Virtual FIFO byte count */ + } FIFOCTR_b; + } ; + + union { + __IOM uint32_t FIFOINC; /*!< (@ 0x00000114) Overall FIFO Counter Increment */ + + struct { + __IOM uint32_t FIFOINC : 10; /*!< [9..0] Increment the Overall FIFO Counter by this value on a + write */ + } FIFOINC_b; + } ; + + union { + __IOM uint32_t CFG; /*!< (@ 0x00000118) I/O Slave Configuration */ + + struct { + __IOM uint32_t IFCSEL : 1; /*!< [0..0] This bit selects the I/O interface. */ + __IOM uint32_t SPOL : 1; /*!< [1..1] This bit selects SPI polarity. */ + __IOM uint32_t LSB : 1; /*!< [2..2] This bit selects the transfer bit ordering. */ + __IM uint32_t : 1; + __IOM uint32_t STARTRD : 1; /*!< [4..4] This bit holds the cycle to initiate an I/O RAM read. */ + __IM uint32_t : 3; + __IOM uint32_t I2CADDR : 12; /*!< [19..8] 7-bit or 10-bit I2C device address. */ + __IM uint32_t : 11; + __IOM uint32_t IFCEN : 1; /*!< [31..31] IOSLAVE interface enable. */ + } CFG_b; + } ; + + union { + __IOM uint32_t PRENC; /*!< (@ 0x0000011C) I/O Slave Interrupt Priority Encode */ + + struct { + __IOM uint32_t PRENC : 5; /*!< [4..0] These bits hold the priority encode of the REGACC interrupts. */ + } PRENC_b; + } ; + + union { + __IOM uint32_t IOINTCTL; /*!< (@ 0x00000120) I/O Interrupt Control */ + + struct { + __IOM uint32_t IOINTEN : 8; /*!< [7..0] These read-only bits indicate whether the IOINT interrupts + are enabled. */ + __IOM uint32_t IOINT : 8; /*!< [15..8] These bits read the IOINT interrupts. */ + __IOM uint32_t IOINTCLR : 1; /*!< [16..16] This bit clears all of the IOINT interrupts when written + with a 1. */ + __IM uint32_t : 7; + __IOM uint32_t IOINTSET : 8; /*!< [31..24] These bits set the IOINT interrupts when written with + a 1. */ + } IOINTCTL_b; + } ; + + union { + __IOM uint32_t GENADD; /*!< (@ 0x00000124) General Address Data */ + + struct { + __IOM uint32_t GADATA : 8; /*!< [7..0] The data supplied on the last General Address reference. */ + } GENADD_b; + } ; + __IM uint32_t RESERVED1[54]; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000200) IO Slave Interrupts: Enable */ + + struct { + __IOM uint32_t FSIZE : 1; /*!< [0..0] FIFO Size interrupt. */ + __IOM uint32_t FOVFL : 1; /*!< [1..1] FIFO Overflow interrupt. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] FIFO Underflow interrupt. */ + __IOM uint32_t FRDERR : 1; /*!< [3..3] FIFO Read Error interrupt. */ + __IOM uint32_t GENAD : 1; /*!< [4..4] I2C General Address interrupt. */ + __IOM uint32_t IOINTW : 1; /*!< [5..5] IO Write interrupt. */ + __IOM uint32_t XCMPRF : 1; /*!< [6..6] Transfer complete interrupt, read from FIFO space. */ + __IOM uint32_t XCMPRR : 1; /*!< [7..7] Transfer complete interrupt, read from register space. */ + __IOM uint32_t XCMPWF : 1; /*!< [8..8] Transfer complete interrupt, write to FIFO space. */ + __IOM uint32_t XCMPWR : 1; /*!< [9..9] Transfer complete interrupt, write to register space. */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) IO Slave Interrupts: Status */ + + struct { + __IOM uint32_t FSIZE : 1; /*!< [0..0] FIFO Size interrupt. */ + __IOM uint32_t FOVFL : 1; /*!< [1..1] FIFO Overflow interrupt. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] FIFO Underflow interrupt. */ + __IOM uint32_t FRDERR : 1; /*!< [3..3] FIFO Read Error interrupt. */ + __IOM uint32_t GENAD : 1; /*!< [4..4] I2C General Address interrupt. */ + __IOM uint32_t IOINTW : 1; /*!< [5..5] IO Write interrupt. */ + __IOM uint32_t XCMPRF : 1; /*!< [6..6] Transfer complete interrupt, read from FIFO space. */ + __IOM uint32_t XCMPRR : 1; /*!< [7..7] Transfer complete interrupt, read from register space. */ + __IOM uint32_t XCMPWF : 1; /*!< [8..8] Transfer complete interrupt, write to FIFO space. */ + __IOM uint32_t XCMPWR : 1; /*!< [9..9] Transfer complete interrupt, write to register space. */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000208) IO Slave Interrupts: Clear */ + + struct { + __IOM uint32_t FSIZE : 1; /*!< [0..0] FIFO Size interrupt. */ + __IOM uint32_t FOVFL : 1; /*!< [1..1] FIFO Overflow interrupt. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] FIFO Underflow interrupt. */ + __IOM uint32_t FRDERR : 1; /*!< [3..3] FIFO Read Error interrupt. */ + __IOM uint32_t GENAD : 1; /*!< [4..4] I2C General Address interrupt. */ + __IOM uint32_t IOINTW : 1; /*!< [5..5] IO Write interrupt. */ + __IOM uint32_t XCMPRF : 1; /*!< [6..6] Transfer complete interrupt, read from FIFO space. */ + __IOM uint32_t XCMPRR : 1; /*!< [7..7] Transfer complete interrupt, read from register space. */ + __IOM uint32_t XCMPWF : 1; /*!< [8..8] Transfer complete interrupt, write to FIFO space. */ + __IOM uint32_t XCMPWR : 1; /*!< [9..9] Transfer complete interrupt, write to register space. */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000020C) IO Slave Interrupts: Set */ + + struct { + __IOM uint32_t FSIZE : 1; /*!< [0..0] FIFO Size interrupt. */ + __IOM uint32_t FOVFL : 1; /*!< [1..1] FIFO Overflow interrupt. */ + __IOM uint32_t FUNDFL : 1; /*!< [2..2] FIFO Underflow interrupt. */ + __IOM uint32_t FRDERR : 1; /*!< [3..3] FIFO Read Error interrupt. */ + __IOM uint32_t GENAD : 1; /*!< [4..4] I2C General Address interrupt. */ + __IOM uint32_t IOINTW : 1; /*!< [5..5] IO Write interrupt. */ + __IOM uint32_t XCMPRF : 1; /*!< [6..6] Transfer complete interrupt, read from FIFO space. */ + __IOM uint32_t XCMPRR : 1; /*!< [7..7] Transfer complete interrupt, read from register space. */ + __IOM uint32_t XCMPWF : 1; /*!< [8..8] Transfer complete interrupt, write to FIFO space. */ + __IOM uint32_t XCMPWR : 1; /*!< [9..9] Transfer complete interrupt, write to register space. */ + } INTSET_b; + } ; + + union { + __IOM uint32_t REGACCINTEN; /*!< (@ 0x00000210) Register Access Interrupts: Enable */ + + struct { + __IOM uint32_t REGACC : 32; /*!< [31..0] Register access interrupts. */ + } REGACCINTEN_b; + } ; + + union { + __IOM uint32_t REGACCINTSTAT; /*!< (@ 0x00000214) Register Access Interrupts: Status */ + + struct { + __IOM uint32_t REGACC : 32; /*!< [31..0] Register access interrupts. */ + } REGACCINTSTAT_b; + } ; + + union { + __IOM uint32_t REGACCINTCLR; /*!< (@ 0x00000218) Register Access Interrupts: Clear */ + + struct { + __IOM uint32_t REGACC : 32; /*!< [31..0] Register access interrupts. */ + } REGACCINTCLR_b; + } ; + + union { + __IOM uint32_t REGACCINTSET; /*!< (@ 0x0000021C) Register Access Interrupts: Set */ + + struct { + __IOM uint32_t REGACC : 32; /*!< [31..0] Register access interrupts. */ + } REGACCINTSET_b; + } ; +} IOSLAVE_Type; /*!< Size = 544 (0x220) */ + + + +/* =========================================================================================================================== */ +/* ================ MCUCTRL ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief MCU Miscellaneous Control Logic (MCUCTRL) + */ + +typedef struct { /*!< (@ 0x40020000) MCUCTRL Structure */ + + union { + __IOM uint32_t CHIPPN; /*!< (@ 0x00000000) Chip Information Register */ + + struct { + __IOM uint32_t PARTNUM : 32; /*!< [31..0] BCD part number. */ + } CHIPPN_b; + } ; + + union { + __IOM uint32_t CHIPID0; /*!< (@ 0x00000004) Unique Chip ID 0 */ + + struct { + __IOM uint32_t CHIPID0 : 32; /*!< [31..0] Unique chip ID 0. */ + } CHIPID0_b; + } ; + + union { + __IOM uint32_t CHIPID1; /*!< (@ 0x00000008) Unique Chip ID 1 */ + + struct { + __IOM uint32_t CHIPID1 : 32; /*!< [31..0] Unique chip ID 1. */ + } CHIPID1_b; + } ; + + union { + __IOM uint32_t CHIPREV; /*!< (@ 0x0000000C) Chip Revision */ + + struct { + __IOM uint32_t REVMIN : 4; /*!< [3..0] Minor Revision ID. */ + __IOM uint32_t REVMAJ : 4; /*!< [7..4] Major Revision ID. */ + __IOM uint32_t SIPART : 12; /*!< [19..8] Silicon Part ID */ + } CHIPREV_b; + } ; + + union { + __IOM uint32_t VENDORID; /*!< (@ 0x00000010) Unique Vendor ID */ + + struct { + __IOM uint32_t VENDORID : 32; /*!< [31..0] Unique Vendor ID */ + } VENDORID_b; + } ; + + union { + __IOM uint32_t SKU; /*!< (@ 0x00000014) Unique Chip SKU */ + + struct { + __IOM uint32_t ALLOWBURST : 1; /*!< [0..0] Allow Burst feature */ + __IOM uint32_t ALLOWBLE : 1; /*!< [1..1] Allow BLE feature */ + __IOM uint32_t SECBOOT : 1; /*!< [2..2] Secure boot feature allowed */ + } SKU_b; + } ; + + union { + __IOM uint32_t FEATUREENABLE; /*!< (@ 0x00000018) Feature Enable on Burst and BLE */ + + struct { + __IOM uint32_t BLEREQ : 1; /*!< [0..0] Controls the BLE functionality */ + __IOM uint32_t BLEACK : 1; /*!< [1..1] ACK for BLEREQ */ + __IOM uint32_t BLEAVAIL : 1; /*!< [2..2] AVAILABILITY of the BLE functionality */ + __IM uint32_t : 1; + __IOM uint32_t BURSTREQ : 1; /*!< [4..4] Controls the Burst functionality */ + __IOM uint32_t BURSTACK : 1; /*!< [5..5] ACK for BURSTREQ */ + __IOM uint32_t BURSTAVAIL : 1; /*!< [6..6] Availability of Burst functionality */ + } FEATUREENABLE_b; + } ; + __IM uint32_t RESERVED; + + union { + __IOM uint32_t DEBUGGER; /*!< (@ 0x00000020) Debugger Control */ + + struct { + __IOM uint32_t LOCKOUT : 1; /*!< [0..0] Lockout of debugger (SWD). */ + } DEBUGGER_b; + } ; + __IM uint32_t RESERVED1[55]; + + union { + __IOM uint32_t BODCTRL; /*!< (@ 0x00000100) BOD control Register */ + + struct { + __IOM uint32_t BODLPWD : 1; /*!< [0..0] BODL Power Down. */ + __IOM uint32_t BODHPWD : 1; /*!< [1..1] BODH Power Down. */ + __IOM uint32_t BODCPWD : 1; /*!< [2..2] BODC Power Down. */ + __IOM uint32_t BODFPWD : 1; /*!< [3..3] BODF Power Down. */ + __IOM uint32_t BODLVREFSEL : 1; /*!< [4..4] BODL External Reference Select. Note: the SWE mux select + in PWRSEQ2SWE must be set for this to take effect. */ + __IOM uint32_t BODHVREFSEL : 1; /*!< [5..5] BODH External Reference Select. Note: the SWE mux select + in PWRSEQ2SWE must be set for this to take effect. */ + } BODCTRL_b; + } ; + + union { + __IOM uint32_t ADCPWRDLY; /*!< (@ 0x00000104) ADC Power Up Delay Control */ + + struct { + __IOM uint32_t ADCPWR0 : 8; /*!< [7..0] ADC Reference Buffer Power Enable delay in 64 ADC CLK + increments for ADC_CLKSEL = 0x1, 32 ADC CLOCK increments + for ADC_CLKSEL = 0x2. */ + __IOM uint32_t ADCPWR1 : 8; /*!< [15..8] ADC Reference Keeper enable delay in 16 ADC CLK increments + for ADC_CLKSEL = 0x1, 8 ADC CLOCK increments for ADC_CLKSEL + = 0x2. */ + } ADCPWRDLY_b; + } ; + __IM uint32_t RESERVED2; + + union { + __IOM uint32_t ADCCAL; /*!< (@ 0x0000010C) ADC Calibration Control */ + + struct { + __IOM uint32_t CALONPWRUP : 1; /*!< [0..0] Run ADC Calibration on initial power up sequence */ + __IOM uint32_t ADCCALIBRATED : 1; /*!< [1..1] Status for ADC Calibration */ + } ADCCAL_b; + } ; + + union { + __IOM uint32_t ADCBATTLOAD; /*!< (@ 0x00000110) ADC Battery Load Enable */ + + struct { + __IOM uint32_t BATTLOAD : 1; /*!< [0..0] Enable the ADC battery load resistor */ + } ADCBATTLOAD_b; + } ; + __IM uint32_t RESERVED3; + + union { + __IOM uint32_t ADCTRIM; /*!< (@ 0x00000118) ADC Trims */ + + struct { + __IOM uint32_t ADCREFKEEPIBTRIM : 2; /*!< [1..0] ADC Reference Ibias trim */ + __IM uint32_t : 4; + __IOM uint32_t ADCREFBUFTRIM : 5; /*!< [10..6] ADC Reference buffer trim */ + __IOM uint32_t ADCRFBUFIBTRIM : 2; /*!< [12..11] ADC reference buffer input bias trim */ + } ADCTRIM_b; + } ; + + union { + __IOM uint32_t ADCREFCOMP; /*!< (@ 0x0000011C) ADC Referece Keeper and Comparator Control */ + + struct { + __IOM uint32_t ADC_REFCOMP_OUT : 1; /*!< [0..0] Output of the ADC reference comparator */ + __IM uint32_t : 7; + __IOM uint32_t ADCREFKEEPTRIM : 5; /*!< [12..8] ADC Reference Keeper Trim */ + __IM uint32_t : 3; + __IOM uint32_t ADCRFCMPEN : 1; /*!< [16..16] ADC Reference comparator power down */ + } ADCREFCOMP_b; + } ; + + union { + __IOM uint32_t XTALCTRL; /*!< (@ 0x00000120) XTAL Oscillator Control */ + + struct { + __IOM uint32_t XTALSWE : 1; /*!< [0..0] XTAL Software Override Enable. */ + __IOM uint32_t FDBKDSBLXTAL : 1; /*!< [1..1] XTAL Oscillator Disable Feedback. */ + __IOM uint32_t BYPCMPRXTAL : 1; /*!< [2..2] XTAL Oscillator Bypass Comparator. */ + __IOM uint32_t PDNBCOREXTAL : 1; /*!< [3..3] XTAL Oscillator Power Down Core. */ + __IOM uint32_t PDNBCMPRXTAL : 1; /*!< [4..4] XTAL Oscillator Power Down Comparator. */ + __IOM uint32_t PWDBODXTAL : 1; /*!< [5..5] XTAL Power down on brown out. */ + __IOM uint32_t XTALIBUFTRIM : 2; /*!< [7..6] XTAL IBUFF trim */ + __IOM uint32_t XTALICOMPTRIM : 2; /*!< [9..8] XTAL ICOMP trim */ + } XTALCTRL_b; + } ; + + union { + __IOM uint32_t XTALGENCTRL; /*!< (@ 0x00000124) XTAL Oscillator General Control */ + + struct { + __IOM uint32_t ACWARMUP : 2; /*!< [1..0] Auto-calibration delay control */ + __IOM uint32_t XTALBIASTRIM : 6; /*!< [7..2] XTAL BIAS trim */ + __IOM uint32_t XTALKSBIASTRIM : 6; /*!< [13..8] XTAL IBIAS Kick start trim. This trim value is used + during the startup process to enable a faster lock. */ + } XTALGENCTRL_b; + } ; + __IM uint32_t RESERVED4[28]; + + union { + __IOM uint32_t MISCCTRL; /*!< (@ 0x00000198) Miscellaneous control register. */ + + struct { + __IOM uint32_t RESERVED_RW_0 : 5; /*!< [4..0] Reserved bits, always leave unchanged. The MISCCTRL register + must be modified via atomic RMW, leaving this bitfield + completely unmodified. Failure to do so will result in + unpredictable behavior. */ + __IOM uint32_t BLE_RESETN : 1; /*!< [5..5] BLE reset signal. */ + } MISCCTRL_b; + } ; + __IM uint32_t RESERVED5; + + union { + __IOM uint32_t BOOTLOADER; /*!< (@ 0x000001A0) Bootloader and secure boot functions */ + + struct { + __IOM uint32_t BOOTLOADERLOW : 1; /*!< [0..0] Determines whether the bootloader code is visible at + address 0x00000000 or not. Resets to 1, write 1 to clear. */ + __IOM uint32_t SBLOCK : 1; /*!< [1..1] Secure boot lock. Always resets to 1, write 1 to clear. + Enables system visibility to bootloader until set. */ + __IOM uint32_t PROTLOCK : 1; /*!< [2..2] Flash protection lock. Always resets to 1, write 1 to + clear. Enables writes to flash protection register set. */ + __IM uint32_t : 23; + __IOM uint32_t SECBOOTFEATURE : 2; /*!< [27..26] Indicates whether the secure boot feature is enabled. */ + __IOM uint32_t SECBOOT : 2; /*!< [29..28] Indicates whether the secure boot on cold reset is + enabled */ + __IOM uint32_t SECBOOTONRST : 2; /*!< [31..30] Indicates whether the secure boot on warm reset is + enabled */ + } BOOTLOADER_b; + } ; + + union { + __IOM uint32_t SHADOWVALID; /*!< (@ 0x000001A4) Register to indicate whether the shadow registers + have been successfully loaded from the Flash + Information Space. */ + + struct { + __IOM uint32_t VALID : 1; /*!< [0..0] Indicates whether the shadow registers contain valid + data from the Flash Information Space. */ + __IOM uint32_t BLDSLEEP : 1; /*!< [1..1] Indicates whether the bootloader should sleep or deep + sleep if no image loaded. */ + __IOM uint32_t INFO0_VALID : 1; /*!< [2..2] Indicates whether info0 contains valid data */ + } SHADOWVALID_b; + } ; + __IM uint32_t RESERVED6[2]; + + union { + __IOM uint32_t SCRATCH0; /*!< (@ 0x000001B0) Scratch register that is not reset by any reset */ + + struct { + __IOM uint32_t SCRATCH0 : 32; /*!< [31..0] Scratch register 0. */ + } SCRATCH0_b; + } ; + + union { + __IOM uint32_t SCRATCH1; /*!< (@ 0x000001B4) Scratch register that is not reset by any reset */ + + struct { + __IOM uint32_t SCRATCH1 : 32; /*!< [31..0] Scratch register 1. */ + } SCRATCH1_b; + } ; + __IM uint32_t RESERVED7[2]; + + union { + __IOM uint32_t ICODEFAULTADDR; /*!< (@ 0x000001C0) ICODE bus address which was present when a bus + fault occurred. */ + + struct { + __IOM uint32_t ICODEFAULTADDR : 32; /*!< [31..0] The ICODE bus address observed when a Bus Fault occurred. + Once an address is captured in this field, it is held until + the corresponding Fault Observed bit is cleared in the + FAULTSTATUS register. */ + } ICODEFAULTADDR_b; + } ; + + union { + __IOM uint32_t DCODEFAULTADDR; /*!< (@ 0x000001C4) DCODE bus address which was present when a bus + fault occurred. */ + + struct { + __IOM uint32_t DCODEFAULTADDR : 32; /*!< [31..0] The DCODE bus address observed when a Bus Fault occurred. + Once an address is captured in this field, it is held until + the corresponding Fault Observed bit is cleared in the + FAULTSTATUS register. */ + } DCODEFAULTADDR_b; + } ; + + union { + __IOM uint32_t SYSFAULTADDR; /*!< (@ 0x000001C8) System bus address which was present when a bus + fault occurred. */ + + struct { + __IOM uint32_t SYSFAULTADDR : 32; /*!< [31..0] SYS bus address observed when a Bus Fault occurred. + Once an address is captured in this field, it is held until + the corresponding Fault Observed bit is cleared in the + FAULTSTATUS register. */ + } SYSFAULTADDR_b; + } ; + + union { + __IOM uint32_t FAULTSTATUS; /*!< (@ 0x000001CC) Reflects the status of the bus decoders' fault + detection. Any write to this register will + clear all of the status bits within the + register. */ + + struct { + __IOM uint32_t ICODEFAULT : 1; /*!< [0..0] The ICODE Bus Decoder Fault Detected bit. When set, a + fault has been detected, and the ICODEFAULTADDR register + will contain the bus address which generated the fault. */ + __IOM uint32_t DCODEFAULT : 1; /*!< [1..1] DCODE Bus Decoder Fault Detected bit. When set, a fault + has been detected, and the DCODEFAULTADDR register will + contain the bus address which generated the fault. */ + __IOM uint32_t SYSFAULT : 1; /*!< [2..2] SYS Bus Decoder Fault Detected bit. When set, a fault + has been detected, and the SYSFAULTADDR register will contain + the bus address which generated the fault. */ + } FAULTSTATUS_b; + } ; + + union { + __IOM uint32_t FAULTCAPTUREEN; /*!< (@ 0x000001D0) Enable the fault capture registers */ + + struct { + __IOM uint32_t FAULTCAPTUREEN : 1; /*!< [0..0] Fault Capture Enable field. When set, the Fault Capture + monitors are enabled and addresses which generate a hard + fault are captured into the FAULTADDR registers. */ + } FAULTCAPTUREEN_b; + } ; + __IM uint32_t RESERVED8[11]; + + union { + __IOM uint32_t DBGR1; /*!< (@ 0x00000200) Read-only debug register 1 */ + + struct { + __IOM uint32_t ONETO8 : 32; /*!< [31..0] Read-only register for communication validation */ + } DBGR1_b; + } ; + + union { + __IOM uint32_t DBGR2; /*!< (@ 0x00000204) Read-only debug register 2 */ + + struct { + __IOM uint32_t COOLCODE : 32; /*!< [31..0] Read-only register for communication validation */ + } DBGR2_b; + } ; + __IM uint32_t RESERVED9[6]; + + union { + __IOM uint32_t PMUENABLE; /*!< (@ 0x00000220) Control bit to enable/disable the PMU */ + + struct { + __IOM uint32_t ENABLE : 1; /*!< [0..0] PMU Enable Control bit. When set, the MCU's PMU will + place the MCU into the lowest power consuming Deep Sleep + mode upon execution of a WFI instruction (dependent on + the setting of the SLEEPDEEP bit in the ARM SCR register). + When cleared, regardless of the requested sleep mode, the + PMU will not enter the lowest power Deep Sleep mode, instead + entering the Sleep mode. */ + } PMUENABLE_b; + } ; + __IM uint32_t RESERVED10[11]; + + union { + __IOM uint32_t TPIUCTRL; /*!< (@ 0x00000250) TPIU Control Register. Determines the clock enable + and frequency for the M4's TPIU interface. */ + + struct { + __IOM uint32_t ENABLE : 1; /*!< [0..0] TPIU Enable field. When set, the ARM M4 TPIU is enabled + and data can be streamed out of the MCU's SWO port using + the ARM ITM and TPIU modules. */ + __IM uint32_t : 7; + __IOM uint32_t CLKSEL : 3; /*!< [10..8] This field selects the frequency of the ARM M4 TPIU + port. */ + } TPIUCTRL_b; + } ; + __IM uint32_t RESERVED11[4]; + + union { + __IOM uint32_t OTAPOINTER; /*!< (@ 0x00000264) OTA (Over the Air) Update Pointer/Status. Reset + only by POA */ + + struct { + __IOM uint32_t OTAVALID : 1; /*!< [0..0] Indicates that an OTA update is valid */ + __IOM uint32_t OTASBLUPDATE : 1; /*!< [1..1] Indicates that the sbl_init has been updated */ + __IOM uint32_t OTAPOINTER : 30; /*!< [31..2] Flash page pointer with updated OTA image */ + } OTAPOINTER_b; + } ; + __IM uint32_t RESERVED12[6]; + + union { + __IOM uint32_t APBDMACTRL; /*!< (@ 0x00000280) DMA Control Register. Determines misc settings + for DMA operation */ + + struct { + __IOM uint32_t DMA_ENABLE : 1; /*!< [0..0] Enable the DMA controller. When disabled, DMA requests + will be ignored by the controller */ + __IOM uint32_t DECODEABORT : 1; /*!< [1..1] APB Decode Abort. When set, the APB bridge will issue + a data abort (bus fault) on transactions to peripherals + that are powered down. When set to 0, writes are quietly + discarded and reads return 0. */ + __IM uint32_t : 6; + __IOM uint32_t HYSTERESIS : 8; /*!< [15..8] This field determines how long the DMA will remain active + during deep sleep before shutting down and returning the + system to full deep sleep. Values are based on a 94KHz + clock and are roughly 10us increments for a range of ~10us + to 2.55ms */ + } APBDMACTRL_b; + } ; + + union { + __IOM uint32_t SRAMMODE; /*!< (@ 0x00000284) SRAM Controller mode bits */ + + struct { + __IOM uint32_t IPREFETCH : 1; /*!< [0..0] When set, instruction accesses to the SRAM banks will + be prefetched (normally 2 cycle read access). Generally, + this mode bit should be set for improved performance when + executing instructions from SRAM. */ + __IOM uint32_t IPREFETCH_CACHE : 1; /*!< [1..1] Secondary prefetch feature that will cache prefetched + data across bus waitstates (requires IPREFETCH to be set). */ + __IM uint32_t : 2; + __IOM uint32_t DPREFETCH : 1; /*!< [4..4] When set, data bus accesses to the SRAM banks will be + prefetched (normally 2 cycle read access). Use of this + mode bit is only recommended if the work flow has a large + number of sequential accesses. */ + __IOM uint32_t DPREFETCH_CACHE : 1; /*!< [5..5] Secondary prefetch feature that will cache prefetched + data across bus waitstates (requires DPREFETCH to be set). */ + } SRAMMODE_b; + } ; + __IM uint32_t RESERVED13[48]; + + union { + __IOM uint32_t KEXTCLKSEL; /*!< (@ 0x00000348) Key Register to enable the use of external clock + selects via the EXTCLKSEL reg */ + + struct { + __IOM uint32_t KEXTCLKSEL : 32; /*!< [31..0] Key register value. */ + } KEXTCLKSEL_b; + } ; + __IM uint32_t RESERVED14[4]; + + union { + __IOM uint32_t SIMOBUCK4; /*!< (@ 0x0000035C) SIMO Buck Control Reg1 */ + + struct { + __IOM uint32_t SIMOBUCKMEMLPLOWTONTRIM : 4;/*!< [3..0] simobuck_mem_lp_low_ton_trim */ + __IOM uint32_t SIMOBUCKMEMACTDRVSTRTRIM : 2;/*!< [5..4] simobuck_mem_act_drvstr_trim */ + __IOM uint32_t SIMOBUCKMEMLPDRVSTRTRIM : 2;/*!< [7..6] simobuck_mem_lp_drvstr_trim */ + __IOM uint32_t SIMOBUCKMEMLEAKAGETRIM : 2;/*!< [9..8] simobuck_mem_leakage_trim */ + __IOM uint32_t SIMOBUCKZXTRIM : 4; /*!< [13..10] simobuck_zx_trim */ + __IOM uint32_t SIMOBUCKUVLOCNTRTRIM : 3; /*!< [16..14] simobuck_uvlo_cntr_trim */ + __IOM uint32_t SIMOBUCKUVLODRVSTRTRIM : 3;/*!< [19..17] simobuck_uvlo_drvstr_trim */ + __IOM uint32_t SIMOBUCKEXTCLKSEL : 1; /*!< [20..20] simobuck_extclk_sel */ + __IOM uint32_t SIMOBUCKCLKDIVSEL : 2; /*!< [22..21] simobuck_clkdiv_sel */ + __IOM uint32_t SIMOBUCKCOMP2LPEN : 1; /*!< [23..23] simobuck_comp2_lp_en */ + __IOM uint32_t SIMOBUCKCOMP2TIMEOUTEN : 1;/*!< [24..24] simobuck_comp2_timeout_en */ + __IOM uint32_t SIMOBUCKPRIORITYSEL : 1; /*!< [25..25] simobuck_priority_sel */ + __IOM uint32_t SIMOBUCKUVLOMODE : 2; /*!< [27..26] simobuck_uvlo_mode */ + __IOM uint32_t SIMOBUCKIBIASTRIM : 4; /*!< [31..28] simobuck_bias_trim */ + } SIMOBUCK4_b; + } ; + __IM uint32_t RESERVED15[2]; + + union { + __IOM uint32_t BLEBUCK2; /*!< (@ 0x00000368) BLEBUCK2 Control Reg */ + + struct { + __IOM uint32_t BLEBUCKTONLOWTRIM : 6; /*!< [5..0] blebuck_ton_low_trim */ + __IOM uint32_t BLEBUCKTONHITRIM : 6; /*!< [11..6] blebuck_ton_hi_trim */ + __IOM uint32_t BLEBUCKTOND2ATRIM : 6; /*!< [17..12] blebuck_ton_trim */ + } BLEBUCK2_b; + } ; + __IM uint32_t RESERVED16[13]; + + union { + __IOM uint32_t FLASHWPROT0; /*!< (@ 0x000003A0) Flash Write Protection Bits */ + + struct { + __IOM uint32_t FW0BITS : 32; /*!< [31..0] Write protect flash 0x00000000 - 0x0007FFFF. Each bit + provides write protection for 16KB chunks of flash data + space. Bits are cleared by writing a 1 to the bit. When + read, 0 indicates the region is protected. Bits are sticky + (can be set when PROTLOCK is 1, but only cleared by reset) */ + } FLASHWPROT0_b; + } ; + + union { + __IOM uint32_t FLASHWPROT1; /*!< (@ 0x000003A4) Flash Write Protection Bits */ + + struct { + __IOM uint32_t FW1BITS : 32; /*!< [31..0] Write protect flash 0x00080000 - 0x000FFFFF. Each bit + provides write protection for 16KB chunks of flash data + space. Bits are cleared by writing a 1 to the bit. When + read, 0 indicates the region is protected. Bits are sticky + (can be set when PROTLOCK is 1, but only cleared by reset) */ + } FLASHWPROT1_b; + } ; + __IM uint32_t RESERVED17[2]; + + union { + __IOM uint32_t FLASHRPROT0; /*!< (@ 0x000003B0) Flash Read Protection Bits */ + + struct { + __IOM uint32_t FR0BITS : 32; /*!< [31..0] Copy (read) protect flash 0x00000000 - 0x0007FFFF. Each + bit provides read protection for 16KB chunks of flash. + Bits are cleared by writing a 1 to the bit. When read, + 0 indicates the region is protected. Bits are sticky (can + be set when PROTLOCK is 1, but only cleared by reset) */ + } FLASHRPROT0_b; + } ; + + union { + __IOM uint32_t FLASHRPROT1; /*!< (@ 0x000003B4) Flash Read Protection Bits */ + + struct { + __IOM uint32_t FR1BITS : 32; /*!< [31..0] Copy (read) protect flash 0x00080000 - 0x000FFFFF. Each + bit provides read protection for 16KB chunks of flash. + Bits are cleared by writing a 1 to the bit. When read, + 0 indicates the region is protected. Bits are sticky (can + be set when PROTLOCK is 1, but only cleared by reset) */ + } FLASHRPROT1_b; + } ; + __IM uint32_t RESERVED18[2]; + + union { + __IOM uint32_t DMASRAMWRITEPROTECT0; /*!< (@ 0x000003C0) SRAM write-protection bits. */ + + struct { + __IOM uint32_t DMA_WPROT0 : 32; /*!< [31..0] Write protect SRAM from DMA. Each bit provides write + protection for an 8KB region of memory. When set to 1, + the region will be protected from DMA writes, when set + to 0, DMA may write the region. */ + } DMASRAMWRITEPROTECT0_b; + } ; + + union { + __IOM uint32_t DMASRAMWRITEPROTECT1; /*!< (@ 0x000003C4) SRAM write-protection bits. */ + + struct { + __IOM uint32_t DMA_WPROT1 : 16; /*!< [15..0] Write protect SRAM from DMA. Each bit provides write + protection for an 8KB region of memory. When set to 1, + the region will be protected from DMA writes, when set + to 0, DMA may write the region. */ + } DMASRAMWRITEPROTECT1_b; + } ; + __IM uint32_t RESERVED19[2]; + + union { + __IOM uint32_t DMASRAMREADPROTECT0; /*!< (@ 0x000003D0) SRAM read-protection bits. */ + + struct { + __IOM uint32_t DMA_RPROT0 : 32; /*!< [31..0] Read protect SRAM from DMA. Each bit provides write + protection for an 8KB region of memory. When set to 1, + the region will be protected from DMA reads, when set to + 0, DMA may read the region. */ + } DMASRAMREADPROTECT0_b; + } ; + + union { + __IOM uint32_t DMASRAMREADPROTECT1; /*!< (@ 0x000003D4) SRAM read-protection bits. */ + + struct { + __IOM uint32_t DMA_RPROT1 : 16; /*!< [15..0] Read protect SRAM from DMA. Each bit provides write + protection for an 8KB region of memory. When set to 1, + the region will be protected from DMA reads, when set to + 0, DMA may read the region. */ + } DMASRAMREADPROTECT1_b; + } ; +} MCUCTRL_Type; /*!< Size = 984 (0x3d8) */ + + + +/* =========================================================================================================================== */ +/* ================ MSPI ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Multibit SPI Master (MSPI) + */ + +typedef struct { /*!< (@ 0x50014000) MSPI Structure */ + + union { + __IOM uint32_t CTRL; /*!< (@ 0x00000000) MSPI PIO Transfer Control/Status Register */ + + struct { + __IOM uint32_t START : 1; /*!< [0..0] Write to 1 to initiate a PIO transaction on the bus (typically + the entire register should be written at once with this + bit set). */ + __IOM uint32_t STATUS : 1; /*!< [1..1] Command status: 1 indicates command has completed. Cleared + by writing 1 to this bit or starting a new transfer. */ + __IOM uint32_t BUSY : 1; /*!< [2..2] Command status: 1 indicates controller is busy (command + in progress) */ + __IOM uint32_t QUADCMD : 1; /*!< [3..3] Flag indicating that the operation is a command that + should be replicated to both devices in paired QUAD mode. + This is typically only used when reading/writing configuration + registers in paired flash devices (do not set for memory + transfers). */ + __IM uint32_t : 1; + __IOM uint32_t CONT : 1; /*!< [5..5] Continuation transfer. When 1, indicates that the MSPI + will hold CE low after the transaction completes. This + is included for compatibility with IOM module since the + MSPI transfer module can handle most cases in a single + transfer. NOTE: CONT functionality only works with CLKDIV=2 + (24 MHz). */ + __IOM uint32_t BIGENDIAN : 1; /*!< [6..6] 1 indicates data in FIFO is in big endian format (MSB + first); 0 indicates little endian data (default, LSB first). */ + __IOM uint32_t ENTURN : 1; /*!< [7..7] Indicates whether TX->RX turnaround cycles should be + enabled for this operation (see TURNAROUND field in CFG + register). */ + __IOM uint32_t SENDA : 1; /*!< [8..8] Indicates whether an address phase should be sent (see + ADDR register and ASIZE field in CFG register) */ + __IOM uint32_t SENDI : 1; /*!< [9..9] Indicates whether an instruction phase should be sent + (see INSTR field and ISIZE field in CFG register) */ + __IOM uint32_t TXRX : 1; /*!< [10..10] 1 Indicates a TX operation, 0 indicates an RX operation + of XFERBYTES */ + __IOM uint32_t PIOSCRAMBLE : 1; /*!< [11..11] Enables data scrambling for PIO opertions. This should + only be used for data operations and never for commands + to a device. */ + __IM uint32_t : 4; + __IOM uint32_t XFERBYTES : 16; /*!< [31..16] Number of bytes to transmit or receive (based on TXRX + bit) */ + } CTRL_b; + } ; + + union { + __IOM uint32_t CFG; /*!< (@ 0x00000004) MSPI Transfer Configuration Register */ + + struct { + __IOM uint32_t DEVCFG : 4; /*!< [3..0] Flash configuration for XIP and AUTO DMA operations. + Controls value for SER (Slave Enable) for XIP operations + and address generation for DMA/XIP modes. Also used to + configure SPIFRF (frame format). */ + __IOM uint32_t ASIZE : 2; /*!< [5..4] Address Size. Address bytes to send from ADDR register + name = A1 value = 0x0 desc = Send one address byteenum + name = A2 value = 0x1 desc = Send two address bytesenum + name = A3 value = 0x2 desc = Send three address bytesenum + name = A4 value = 0x3 desc = Send four address bytes */ + __IOM uint32_t ISIZE : 1; /*!< [6..6] Instruction Sizeenum name = I8 value = 0x0 desc = Instruction + is 1 byteenum name = I16 value = 0x1 desc = Instruction + is 2 bytes */ + __IOM uint32_t SEPIO : 1; /*!< [7..7] Separate IO configuration. This bit should be set when + the target device has separate MOSI and MISO pins. Respective + IN/OUT bits below should be set to map pins. */ + __IOM uint32_t TURNAROUND : 6; /*!< [13..8] Number of turnaound cycles (for TX->RX transitions). + Qualified by ENTURN or XIPENTURN bit field. */ + __IM uint32_t : 2; + __IOM uint32_t CPHA : 1; /*!< [16..16] Serial clock phase. */ + __IOM uint32_t CPOL : 1; /*!< [17..17] Serial clock polarity. */ + } CFG_b; + } ; + + union { + __IOM uint32_t ADDR; /*!< (@ 0x00000008) MSPI Transfer Address Register */ + + struct { + __IOM uint32_t ADDR : 32; /*!< [31..0] Optional Address field to send (after optional instruction + field) - qualified by ASIZE in CMD register. NOTE: This + register is aliased to DMADEVADDR. */ + } ADDR_b; + } ; + + union { + __IOM uint32_t INSTR; /*!< (@ 0x0000000C) MSPI Transfer Instruction */ + + struct { + __IOM uint32_t INSTR : 16; /*!< [15..0] Optional Instruction field to send (1st byte) - qualified + by ISEND/ISIZE */ + } INSTR_b; + } ; + + union { + __IOM uint32_t TXFIFO; /*!< (@ 0x00000010) TX Data FIFO */ + + struct { + __IOM uint32_t TXFIFO : 32; /*!< [31..0] Data to be transmitted. Data should normall be aligned + to the LSB (pad the upper bits with zeros) unless BIGENDIAN + is set. */ + } TXFIFO_b; + } ; + + union { + __IOM uint32_t RXFIFO; /*!< (@ 0x00000014) RX Data FIFO */ + + struct { + __IOM uint32_t RXFIFO : 32; /*!< [31..0] Receive data. Data is aligned to the LSB (padded zeros + on upper bits) unless BIGENDIAN is set. */ + } RXFIFO_b; + } ; + + union { + __IOM uint32_t TXENTRIES; /*!< (@ 0x00000018) TX FIFO Entries */ + + struct { + __IOM uint32_t TXENTRIES : 5; /*!< [4..0] Number of 32-bit words/entries in TX FIFO */ + } TXENTRIES_b; + } ; + + union { + __IOM uint32_t RXENTRIES; /*!< (@ 0x0000001C) RX FIFO Entries */ + + struct { + __IOM uint32_t RXENTRIES : 5; /*!< [4..0] Number of 32-bit words/entries in RX FIFO */ + } RXENTRIES_b; + } ; + + union { + __IOM uint32_t THRESHOLD; /*!< (@ 0x00000020) TX/RX FIFO Threshhold Levels */ + + struct { + __IOM uint32_t TXTHRESH : 5; /*!< [4..0] Number of entries in TX FIFO that cause TXF interrupt */ + __IM uint32_t : 3; + __IOM uint32_t RXTHRESH : 5; /*!< [12..8] Number of entries in TX FIFO that cause RXE interrupt */ + } THRESHOLD_b; + } ; + __IM uint32_t RESERVED[55]; + + union { + __IOM uint32_t MSPICFG; /*!< (@ 0x00000100) MSPI Module Configuration */ + + struct { + __IOM uint32_t APBCLK : 1; /*!< [0..0] Enable continuous APB clock. For power-efficient operation, + APBCLK should be set to 0. */ + __IOM uint32_t RXCAP : 1; /*!< [1..1] Controls RX data capture phase. A setting of 0 (NORMAL) + captures read data at the normal capture point relative + to the internal clock launch point. However, to accomodate + chip/pad/board delays, a setting of RXCAP of 1 is expected + to be used to align the capture point with the return data + window. This bit is used in conjunction with RXNEG to provide + 4 unique capture points, all about 10ns apart. */ + __IOM uint32_t RXNEG : 1; /*!< [2..2] Adjusts the RX capture phase to the negedge of the 48MHz + internal clock (~10ns early). For normal operation, it + is expected that RXNEG will be set to 0. */ + __IOM uint32_t TXNEG : 1; /*!< [3..3] Launches TX data a half clock cycle (~10ns) early. This + should normally be programmed to zero (NORMAL). */ + __IOM uint32_t IOMSEL : 3; /*!< [6..4] Selects which IOM is selected for CQ handshake status. */ + __IM uint32_t : 1; + __IOM uint32_t CLKDIV : 6; /*!< [13..8] Clock Divider. Allows dividing 48 MHz base clock by + integer multiples. Enumerations are provided for common + frequency, but any integer divide from 48 MHz is allowed. + Odd divide ratios will result in a 33/66 percent duty cycle + with a long low clock pulse (to allow longer round-trip + for read data). */ + __IM uint32_t : 15; + __IOM uint32_t FIFORESET : 1; /*!< [29..29] Reset MSPI FIFO (active high). 1=reset FIFO, 0=normal + operation. May be used to manually flush the FIFO in error + handling. */ + __IOM uint32_t IPRSTN : 1; /*!< [30..30] IP block reset. Write to 0 to put the transfer module + in reset or 1 for normal operation. This may be required + after error conditions to clear the transfer on the bus. */ + __IOM uint32_t PRSTN : 1; /*!< [31..31] Peripheral reset. Master reset to the entire MSPI module + (DMA, XIP, and transfer state machines). 1=normal operation, + 0=in reset. */ + } MSPICFG_b; + } ; + + union { + __IOM uint32_t PADCFG; /*!< (@ 0x00000104) MSPI Output Pad Configuration */ + + struct { + __IOM uint32_t OUT3 : 1; /*!< [0..0] Output pad 3 configuration. 0=data[3] 1=CLK */ + __IOM uint32_t OUT4 : 1; /*!< [1..1] Output pad 4 configuration. 0=data[4] 1=data[0] */ + __IOM uint32_t OUT5 : 1; /*!< [2..2] Output pad 5 configuration. 0=data[5] 1=data[1] */ + __IOM uint32_t OUT6 : 1; /*!< [3..3] Output pad 6 configuration. 0=data[6] 1=data[2] */ + __IOM uint32_t OUT7 : 1; /*!< [4..4] Output pad 7 configuration. 0=data[7] 1=data[3] */ + __IM uint32_t : 11; + __IOM uint32_t IN0 : 2; /*!< [17..16] Data Input pad 0 pin muxing: 0=pad[0] 1=pad[4] 2=pad[1] + 3=pad[5] */ + __IOM uint32_t IN1 : 1; /*!< [18..18] Data Input pad 1 pin muxing: 0=pad[1] 1=pad[5] */ + __IOM uint32_t IN2 : 1; /*!< [19..19] Data Input pad 2 pin muxing: 0=pad[2] 1=pad[6] */ + __IOM uint32_t IN3 : 1; /*!< [20..20] Data Input pad 3 pin muxing: 0=pad[3] 1=pad[7] */ + __IOM uint32_t REVCS : 1; /*!< [21..21] Reverse CS connections. Allows CS1 to be associated + with lower data lanes and CS0 to be associated with upper + data lines */ + } PADCFG_b; + } ; + + union { + __IOM uint32_t PADOUTEN; /*!< (@ 0x00000108) MSPI Output Enable Pad Configuration */ + + struct { + __IOM uint32_t OUTEN : 9; /*!< [8..0] Output pad enable configuration. Indicates which pads + should be driven. Bits [3:0] are Quad0 data, [7:4] are + Quad1 data, and [8] is clock. */ + } PADOUTEN_b; + } ; + + union { + __IOM uint32_t FLASH; /*!< (@ 0x0000010C) Configuration for XIP/DMA support of SPI flash + modules. */ + + struct { + __IOM uint32_t XIPEN : 1; /*!< [0..0] Enable the XIP (eXecute In Place) function which effectively + enables the address decoding of the MSPI device in the + flash/cache address space at address 0x04000000-0x07FFFFFF. */ + __IM uint32_t : 1; + __IOM uint32_t XIPACK : 2; /*!< [3..2] Controls transmission of Micron XIP acknowledge cycles + (Micron Flash devices only) */ + __IOM uint32_t XIPBIGENDIAN : 1; /*!< [4..4] Indicates whether XIP/AUTO DMA data transfers are in + big or little endian format */ + __IOM uint32_t XIPENTURN : 1; /*!< [5..5] Indicates whether XIP/AUTO DMA operations should enable + TX->RX turnaround cycles */ + __IOM uint32_t XIPSENDA : 1; /*!< [6..6] Indicates whether XIP/AUTO DMA operations should send + an an address phase (see DMADEVADDR register and ASIZE + field in CFG) */ + __IOM uint32_t XIPSENDI : 1; /*!< [7..7] Indicates whether XIP/AUTO DMA operations should send + an instruction (see READINSTR field and ISIZE field in + CFG) */ + __IOM uint32_t XIPMIXED : 3; /*!< [10..8] Reserved. Set to 0x0 */ + __IM uint32_t : 5; + __IOM uint32_t WRITEINSTR : 8; /*!< [23..16] Write command sent for DMA operations */ + __IOM uint32_t READINSTR : 8; /*!< [31..24] Read command sent to flash for DMA/XIP operations */ + } FLASH_b; + } ; + __IM uint32_t RESERVED1[4]; + + union { + __IOM uint32_t SCRAMBLING; /*!< (@ 0x00000120) External Flash Scrambling Controls */ + + struct { + __IOM uint32_t SCRSTART : 10; /*!< [9..0] Scrambling region start address [25:16] (64K block granularity). + The START block is the FIRST block included in the scrambled + address range. */ + __IM uint32_t : 6; + __IOM uint32_t SCREND : 10; /*!< [25..16] Scrambling region end address [25:16] (64K block granularity). + The END block is the LAST block included in the scrambled + address range. */ + __IM uint32_t : 5; + __IOM uint32_t SCRENABLE : 1; /*!< [31..31] Enables Data Scrambling Region. When 1 reads and writes + to the range will be scrambled. When 0, data will be read/written + unmodified. Address range is specified in 64K granularity + and the START/END ranges are included within the range. */ + } SCRAMBLING_b; + } ; + __IM uint32_t RESERVED2[55]; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000200) MSPI Master Interrupts: Enable */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Transfer complete. Note that DMA and CQ operations are + layered, so CMDCMP, DCMP, and CQ* can all be signalled + simultaneously */ + __IOM uint32_t TXE : 1; /*!< [1..1] Transmit FIFO empty. */ + __IOM uint32_t TXO : 1; /*!< [2..2] Transmit FIFO Overflow (only occurs when SW writes to + a full FIFO). */ + __IOM uint32_t RXU : 1; /*!< [3..3] Receive FIFO underflow (only occurs when SW reads from + an empty FIFO) */ + __IOM uint32_t RXO : 1; /*!< [4..4] Receive FIFO overflow (cannot happen in MSPI design -- + MSPI bus pins will stall) */ + __IOM uint32_t RXF : 1; /*!< [5..5] Receive FIFO full */ + __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Complete Interrupt */ + __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Interrupt */ + __IOM uint32_t CQCMP : 1; /*!< [8..8] Command Queue Complete Interrupt */ + __IOM uint32_t CQUPD : 1; /*!< [9..9] Command Queue Update Interrupt. Issued whenever the CQ + performs an operation where address bit[0] is set. Useful + for triggering CURIDX interrupts. */ + __IOM uint32_t CQPAUSED : 1; /*!< [10..10] Command Queue is Paused. */ + __IOM uint32_t CQERR : 1; /*!< [11..11] Command Queue Error Interrupt */ + __IOM uint32_t SCRERR : 1; /*!< [12..12] Scrambling Alignment Error. Scrambling operations must + be aligned to word (4-byte) start address. */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) MSPI Master Interrupts: Status */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Transfer complete. Note that DMA and CQ operations are + layered, so CMDCMP, DCMP, and CQ* can all be signalled + simultaneously */ + __IOM uint32_t TXE : 1; /*!< [1..1] Transmit FIFO empty. */ + __IOM uint32_t TXO : 1; /*!< [2..2] Transmit FIFO Overflow (only occurs when SW writes to + a full FIFO). */ + __IOM uint32_t RXU : 1; /*!< [3..3] Receive FIFO underflow (only occurs when SW reads from + an empty FIFO) */ + __IOM uint32_t RXO : 1; /*!< [4..4] Receive FIFO overflow (cannot happen in MSPI design -- + MSPI bus pins will stall) */ + __IOM uint32_t RXF : 1; /*!< [5..5] Receive FIFO full */ + __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Complete Interrupt */ + __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Interrupt */ + __IOM uint32_t CQCMP : 1; /*!< [8..8] Command Queue Complete Interrupt */ + __IOM uint32_t CQUPD : 1; /*!< [9..9] Command Queue Update Interrupt. Issued whenever the CQ + performs an operation where address bit[0] is set. Useful + for triggering CURIDX interrupts. */ + __IOM uint32_t CQPAUSED : 1; /*!< [10..10] Command Queue is Paused. */ + __IOM uint32_t CQERR : 1; /*!< [11..11] Command Queue Error Interrupt */ + __IOM uint32_t SCRERR : 1; /*!< [12..12] Scrambling Alignment Error. Scrambling operations must + be aligned to word (4-byte) start address. */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000208) MSPI Master Interrupts: Clear */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Transfer complete. Note that DMA and CQ operations are + layered, so CMDCMP, DCMP, and CQ* can all be signalled + simultaneously */ + __IOM uint32_t TXE : 1; /*!< [1..1] Transmit FIFO empty. */ + __IOM uint32_t TXO : 1; /*!< [2..2] Transmit FIFO Overflow (only occurs when SW writes to + a full FIFO). */ + __IOM uint32_t RXU : 1; /*!< [3..3] Receive FIFO underflow (only occurs when SW reads from + an empty FIFO) */ + __IOM uint32_t RXO : 1; /*!< [4..4] Receive FIFO overflow (cannot happen in MSPI design -- + MSPI bus pins will stall) */ + __IOM uint32_t RXF : 1; /*!< [5..5] Receive FIFO full */ + __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Complete Interrupt */ + __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Interrupt */ + __IOM uint32_t CQCMP : 1; /*!< [8..8] Command Queue Complete Interrupt */ + __IOM uint32_t CQUPD : 1; /*!< [9..9] Command Queue Update Interrupt. Issued whenever the CQ + performs an operation where address bit[0] is set. Useful + for triggering CURIDX interrupts. */ + __IOM uint32_t CQPAUSED : 1; /*!< [10..10] Command Queue is Paused. */ + __IOM uint32_t CQERR : 1; /*!< [11..11] Command Queue Error Interrupt */ + __IOM uint32_t SCRERR : 1; /*!< [12..12] Scrambling Alignment Error. Scrambling operations must + be aligned to word (4-byte) start address. */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000020C) MSPI Master Interrupts: Set */ + + struct { + __IOM uint32_t CMDCMP : 1; /*!< [0..0] Transfer complete. Note that DMA and CQ operations are + layered, so CMDCMP, DCMP, and CQ* can all be signalled + simultaneously */ + __IOM uint32_t TXE : 1; /*!< [1..1] Transmit FIFO empty. */ + __IOM uint32_t TXO : 1; /*!< [2..2] Transmit FIFO Overflow (only occurs when SW writes to + a full FIFO). */ + __IOM uint32_t RXU : 1; /*!< [3..3] Receive FIFO underflow (only occurs when SW reads from + an empty FIFO) */ + __IOM uint32_t RXO : 1; /*!< [4..4] Receive FIFO overflow (cannot happen in MSPI design -- + MSPI bus pins will stall) */ + __IOM uint32_t RXF : 1; /*!< [5..5] Receive FIFO full */ + __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Complete Interrupt */ + __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Interrupt */ + __IOM uint32_t CQCMP : 1; /*!< [8..8] Command Queue Complete Interrupt */ + __IOM uint32_t CQUPD : 1; /*!< [9..9] Command Queue Update Interrupt. Issued whenever the CQ + performs an operation where address bit[0] is set. Useful + for triggering CURIDX interrupts. */ + __IOM uint32_t CQPAUSED : 1; /*!< [10..10] Command Queue is Paused. */ + __IOM uint32_t CQERR : 1; /*!< [11..11] Command Queue Error Interrupt */ + __IOM uint32_t SCRERR : 1; /*!< [12..12] Scrambling Alignment Error. Scrambling operations must + be aligned to word (4-byte) start address. */ + } INTSET_b; + } ; + __IM uint32_t RESERVED3[16]; + + union { + __IOM uint32_t DMACFG; /*!< (@ 0x00000250) DMA Configuration Register */ + + struct { + __IOM uint32_t DMAEN : 2; /*!< [1..0] DMA Enable. Setting this bit to EN will start the DMA + operation */ + __IOM uint32_t DMADIR : 1; /*!< [2..2] Direction */ + __IOM uint32_t DMAPRI : 2; /*!< [4..3] Sets the Priority of the DMA request */ + __IM uint32_t : 13; + __IOM uint32_t DMAPWROFF : 1; /*!< [18..18] Power off MSPI domain upon completion of DMA operation. */ + } DMACFG_b; + } ; + + union { + __IOM uint32_t DMASTAT; /*!< (@ 0x00000254) DMA Status Register */ + + struct { + __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress indicator. 1 will indicate that + a DMA transfer is active. The DMA transfer may be waiting + on data, transferring data, or waiting for priority. All + of these will be indicated with a 1. A 0 will indicate + that the DMA is fully complete and no further transactions + will be done. */ + __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete. This signals the end of the DMA + operation. */ + __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error. This active high bit signals that an error + was encountered during the DMA operation. */ + __IOM uint32_t SCRERR : 1; /*!< [3..3] Scrambling Access Alignment Error. This active high bit + signals that a scrambling operation was specified for a + non-word aligned DEVADDR. */ + } DMASTAT_b; + } ; + + union { + __IOM uint32_t DMATARGADDR; /*!< (@ 0x00000258) DMA Target Address Register */ + + struct { + __IOM uint32_t TARGADDR : 32; /*!< [31..0] Target byte address for source of DMA (either read or + write). In cases of non-word aligned addresses, the DMA + logic will take care for ensuring only the target bytes + are read/written. */ + } DMATARGADDR_b; + } ; + + union { + __IOM uint32_t DMADEVADDR; /*!< (@ 0x0000025C) DMA Device Address Register */ + + struct { + __IOM uint32_t DEVADDR : 32; /*!< [31..0] SPI Device address for automated DMA transactions (both + read and write). */ + } DMADEVADDR_b; + } ; + + union { + __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x00000260) DMA Total Transfer Count */ + + struct { + __IOM uint32_t TOTCOUNT : 16; /*!< [15..0] Total Transfer Count in bytes. */ + } DMATOTCOUNT_b; + } ; + + union { + __IOM uint32_t DMABCOUNT; /*!< (@ 0x00000264) DMA BYTE Transfer Count */ + + struct { + __IOM uint32_t BCOUNT : 8; /*!< [7..0] Burst transfer size in bytes. This is the number of bytes + transferred when a FIFO trigger event occurs. Recommended + values are 16 or 32. */ + } DMABCOUNT_b; + } ; + __IM uint32_t RESERVED4[4]; + + union { + __IOM uint32_t DMATHRESH; /*!< (@ 0x00000278) DMA Transmit Trigger Threshhold */ + + struct { + __IOM uint32_t DMATHRESH : 4; /*!< [3..0] DMA transfer FIFO level trigger. For read operations, + DMA is triggered when the FIFO level is greater than this + value. For write operations, DMA is triggered when the + FIFO level is less than this level. Each DMA operation + will consist of BCOUNT bytes. */ + } DMATHRESH_b; + } ; + __IM uint32_t RESERVED5[9]; + + union { + __IOM uint32_t CQCFG; /*!< (@ 0x000002A0) Command Queue Configuration Register */ + + struct { + __IOM uint32_t CQEN : 1; /*!< [0..0] Command queue enable. When set, will enable the processing + of the command queue */ + __IOM uint32_t CQPRI : 1; /*!< [1..1] Sets the Priority of the command queue dma request */ + __IOM uint32_t CQPWROFF : 1; /*!< [2..2] Power off MSPI domain upon completion of DMA operation. */ + __IOM uint32_t CQAUTOCLEARMASK : 1; /*!< [3..3] Eanble clear of CQMASK after each pause operation. This + may be useful when using software flags to pause CQ. */ + } CQCFG_b; + } ; + __IM uint32_t RESERVED6; + + union { + __IOM uint32_t CQADDR; /*!< (@ 0x000002A8) CQ Target Read Address Register */ + + struct { + __IOM uint32_t CQADDR : 29; /*!< [28..0] Address of command queue buffer in SRAM or flash. The + buffer address must be aligned to a word boundary. */ + } CQADDR_b; + } ; + + union { + __IOM uint32_t CQSTAT; /*!< (@ 0x000002AC) Command Queue Status Register */ + + struct { + __IOM uint32_t CQTIP : 1; /*!< [0..0] Command queue Transfer In Progress indicator. 1 will + indicate that a CQ transfer is active and this will remain + active even when paused waiting for external event. */ + __IOM uint32_t CQCPL : 1; /*!< [1..1] Command queue operation Complete. This signals the end + of the command queue operation. */ + __IOM uint32_t CQERR : 1; /*!< [2..2] Command queue processing Error. This active high bit + signals that an error was encountered during the CQ operation. */ + __IOM uint32_t CQPAUSED : 1; /*!< [3..3] Command queue is currently paused status. */ + } CQSTAT_b; + } ; + + union { + __IOM uint32_t CQFLAGS; /*!< (@ 0x000002B0) Command Queue Flag Register */ + + struct { + __IOM uint32_t CQFLAGS : 16; /*!< [15..0] Current flag status (read-only). Bits [7:0] are software + controllable and bits [15:8] are hardware status. */ + } CQFLAGS_b; + } ; + + union { + __IOM uint32_t CQSETCLEAR; /*!< (@ 0x000002B4) Command Queue Flag Set/Clear Register */ + + struct { + __IOM uint32_t CQFSET : 8; /*!< [7..0] Set CQFlag status bits. Set has priority over clear if + both are high. */ + __IOM uint32_t CQFTOGGLE : 8; /*!< [15..8] Toggle CQFlag status bits */ + __IOM uint32_t CQFCLR : 8; /*!< [23..16] Clear CQFlag status bits. */ + } CQSETCLEAR_b; + } ; + + union { + __IOM uint32_t CQPAUSE; /*!< (@ 0x000002B8) Command Queue Pause Mask Register */ + + struct { + __IOM uint32_t CQMASK : 16; /*!< [15..0] CQ will pause processing until all specified events + are satisfied. */ + } CQPAUSE_b; + } ; + __IM uint32_t RESERVED7; + + union { + __IOM uint32_t CQCURIDX; /*!< (@ 0x000002C0) Command Queue Current Index */ + + struct { + __IOM uint32_t CQCURIDX : 8; /*!< [7..0] Can be used to indicate the current position of the command + queue by having CQ operations write this field. A CQ hardware + status flag indicates when CURIDX and ENDIDX are not equal, + allowing SW to pause the CQ processing until the end index + is updated. */ + } CQCURIDX_b; + } ; + + union { + __IOM uint32_t CQENDIDX; /*!< (@ 0x000002C4) Command Queue End Index */ + + struct { + __IOM uint32_t CQENDIDX : 8; /*!< [7..0] Can be used to indicate the end position of the command + queue. A CQ hardware status bit indices when CURIDX != + ENDIDX so that the CQ can be paused when it reaches the + end pointer. */ + } CQENDIDX_b; + } ; +} MSPI_Type; /*!< Size = 712 (0x2c8) */ + + + +/* =========================================================================================================================== */ +/* ================ PDM ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief PDM Audio (PDM) + */ + +typedef struct { /*!< (@ 0x50011000) PDM Structure */ + + union { + __IOM uint32_t PCFG; /*!< (@ 0x00000000) PDM Configuration Register */ + + struct { + __IOM uint32_t PDMCOREEN : 1; /*!< [0..0] Data Streaming Control. */ + __IOM uint32_t SOFTMUTE : 1; /*!< [1..1] Soft mute control. */ + __IOM uint32_t CYCLES : 3; /*!< [4..2] Number of clocks during gain-setting changes. */ + __IOM uint32_t HPCUTOFF : 4; /*!< [8..5] High pass filter coefficients. */ + __IOM uint32_t ADCHPD : 1; /*!< [9..9] High pass filter control. */ + __IOM uint32_t SINCRATE : 7; /*!< [16..10] SINC decimation rate. */ + __IOM uint32_t MCLKDIV : 2; /*!< [18..17] PDM_CLK frequency divisor. */ + __IM uint32_t : 2; + __IOM uint32_t PGALEFT : 5; /*!< [25..21] Left channel PGA gain. */ + __IOM uint32_t PGARIGHT : 5; /*!< [30..26] Right channel PGA gain. */ + __IOM uint32_t LRSWAP : 1; /*!< [31..31] Left/right channel swap. */ + } PCFG_b; + } ; + + union { + __IOM uint32_t VCFG; /*!< (@ 0x00000004) Voice Configuration Register */ + + struct { + __IM uint32_t : 3; + __IOM uint32_t CHSET : 2; /*!< [4..3] Set PCM channels. */ + __IM uint32_t : 3; + __IOM uint32_t PCMPACK : 1; /*!< [8..8] PCM data packing enable. */ + __IM uint32_t : 7; + __IOM uint32_t SELAP : 1; /*!< [16..16] Select PDM input clock source. */ + __IOM uint32_t DMICKDEL : 1; /*!< [17..17] PDM clock sampling delay. */ + __IM uint32_t : 1; + __IOM uint32_t BCLKINV : 1; /*!< [19..19] I2S BCLK input inversion. */ + __IOM uint32_t I2SEN : 1; /*!< [20..20] I2S interface enable. */ + __IM uint32_t : 5; + __IOM uint32_t PDMCLKEN : 1; /*!< [26..26] Enable the serial clock. */ + __IOM uint32_t PDMCLKSEL : 3; /*!< [29..27] Select the PDM input clock. */ + __IOM uint32_t RSTB : 1; /*!< [30..30] Reset the IP core. */ + __IOM uint32_t IOCLKEN : 1; /*!< [31..31] Enable the IO clock. */ + } VCFG_b; + } ; + + union { + __IOM uint32_t VOICESTAT; /*!< (@ 0x00000008) Voice Status Register */ + + struct { + __IOM uint32_t FIFOCNT : 6; /*!< [5..0] Valid 32-bit entries currently in the FIFO. */ + } VOICESTAT_b; + } ; + + union { + __IOM uint32_t FIFOREAD; /*!< (@ 0x0000000C) FIFO Read */ + + struct { + __IOM uint32_t FIFOREAD : 32; /*!< [31..0] FIFO read data. */ + } FIFOREAD_b; + } ; + + union { + __IOM uint32_t FIFOFLUSH; /*!< (@ 0x00000010) FIFO Flush */ + + struct { + __IOM uint32_t FIFOFLUSH : 1; /*!< [0..0] FIFO FLUSH. */ + } FIFOFLUSH_b; + } ; + + union { + __IOM uint32_t FIFOTHR; /*!< (@ 0x00000014) FIFO Threshold */ + + struct { + __IOM uint32_t FIFOTHR : 5; /*!< [4..0] FIFO Threshold value. When the FIFO count is equal to, + or larger than this value (in words), a THR interrupt is + generated (if enabled) */ + } FIFOTHR_b; + } ; + __IM uint32_t RESERVED[122]; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000200) IO Master Interrupts: Enable */ + + struct { + __IOM uint32_t THR : 1; /*!< [0..0] This is the FIFO threshold interrupt. */ + __IOM uint32_t OVF : 1; /*!< [1..1] This is the FIFO overflow interrupt. */ + __IOM uint32_t UNDFL : 1; /*!< [2..2] This is the FIFO underflow interrupt. */ + __IOM uint32_t DCMP : 1; /*!< [3..3] DMA completed a transfer */ + __IOM uint32_t DERR : 1; /*!< [4..4] DMA Error receieved */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) IO Master Interrupts: Status */ + + struct { + __IOM uint32_t THR : 1; /*!< [0..0] This is the FIFO threshold interrupt. */ + __IOM uint32_t OVF : 1; /*!< [1..1] This is the FIFO overflow interrupt. */ + __IOM uint32_t UNDFL : 1; /*!< [2..2] This is the FIFO underflow interrupt. */ + __IOM uint32_t DCMP : 1; /*!< [3..3] DMA completed a transfer */ + __IOM uint32_t DERR : 1; /*!< [4..4] DMA Error receieved */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000208) IO Master Interrupts: Clear */ + + struct { + __IOM uint32_t THR : 1; /*!< [0..0] This is the FIFO threshold interrupt. */ + __IOM uint32_t OVF : 1; /*!< [1..1] This is the FIFO overflow interrupt. */ + __IOM uint32_t UNDFL : 1; /*!< [2..2] This is the FIFO underflow interrupt. */ + __IOM uint32_t DCMP : 1; /*!< [3..3] DMA completed a transfer */ + __IOM uint32_t DERR : 1; /*!< [4..4] DMA Error receieved */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000020C) IO Master Interrupts: Set */ + + struct { + __IOM uint32_t THR : 1; /*!< [0..0] This is the FIFO threshold interrupt. */ + __IOM uint32_t OVF : 1; /*!< [1..1] This is the FIFO overflow interrupt. */ + __IOM uint32_t UNDFL : 1; /*!< [2..2] This is the FIFO underflow interrupt. */ + __IOM uint32_t DCMP : 1; /*!< [3..3] DMA completed a transfer */ + __IOM uint32_t DERR : 1; /*!< [4..4] DMA Error receieved */ + } INTSET_b; + } ; + __IM uint32_t RESERVED1[12]; + + union { + __IOM uint32_t DMATRIGEN; /*!< (@ 0x00000240) DMA Trigger Enable Register */ + + struct { + __IOM uint32_t DTHR : 1; /*!< [0..0] Trigger DMA upon when FIFO iss filled to level indicated + by the FIFO THRESHOLD,at granularity of 16 bytes only */ + __IOM uint32_t DTHR90 : 1; /*!< [1..1] Trigger DMA at FIFO 90 percent full. This signal is also + used internally for AUTOHIP function */ + } DMATRIGEN_b; + } ; + + union { + __IOM uint32_t DMATRIGSTAT; /*!< (@ 0x00000244) DMA Trigger Status Register */ + + struct { + __IOM uint32_t DTHRSTAT : 1; /*!< [0..0] Triggered DMA from FIFO reaching threshold */ + __IOM uint32_t DTHR90STAT : 1; /*!< [1..1] Triggered DMA from FIFO reaching 90 percent full */ + } DMATRIGSTAT_b; + } ; + __IM uint32_t RESERVED2[14]; + + union { + __IOM uint32_t DMACFG; /*!< (@ 0x00000280) DMA Configuration Register */ + + struct { + __IOM uint32_t DMAEN : 1; /*!< [0..0] DMA Enable */ + __IM uint32_t : 1; + __IOM uint32_t DMADIR : 1; /*!< [2..2] Direction */ + __IM uint32_t : 5; + __IOM uint32_t DMAPRI : 1; /*!< [8..8] Sets the Priority of the DMA request */ + __IOM uint32_t DAUTOHIP : 1; /*!< [9..9] Raise priority to high on fifo full, and DMAPRI set to + low */ + __IOM uint32_t DPWROFF : 1; /*!< [10..10] Power Off the ADC System upon DMACPL. */ + } DMACFG_b; + } ; + __IM uint32_t RESERVED3; + + union { + __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x00000288) DMA Total Transfer Count */ + + struct { + __IOM uint32_t TOTCOUNT : 20; /*!< [19..0] Total Transfer Count. The transfer count must be a multiple + of the THR setting to avoid DMA overruns. */ + } DMATOTCOUNT_b; + } ; + + union { + __IOM uint32_t DMATARGADDR; /*!< (@ 0x0000028C) DMA Target Address Register */ + + struct { + __IOM uint32_t LTARGADDR : 20; /*!< [19..0] DMA Target Address. This register is not updated with + the current address of the DMA, but will remain static + with the original address during the DMA transfer. */ + __IOM uint32_t UTARGADDR : 12; /*!< [31..20] SRAM Target */ + } DMATARGADDR_b; + } ; + + union { + __IOM uint32_t DMASTAT; /*!< (@ 0x00000290) DMA Status Register */ + + struct { + __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress */ + __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete */ + __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error */ + } DMASTAT_b; + } ; +} PDM_Type; /*!< Size = 660 (0x294) */ + + + +/* =========================================================================================================================== */ +/* ================ PWRCTRL ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief PWR Controller Register Bank (PWRCTRL) + */ + +typedef struct { /*!< (@ 0x40021000) PWRCTRL Structure */ + + union { + __IOM uint32_t SUPPLYSRC; /*!< (@ 0x00000000) Voltage Regulator Select Register */ + + struct { + __IOM uint32_t BLEBUCKEN : 1; /*!< [0..0] Enables and Selects the BLE Buck as the supply for the + BLE power domain or for Burst LDO. It takes the initial + value from Customer INFO space. Buck will be powered up + only if there is an active request for BLEH domain or Burst + mode and appropriate feature is allowed. */ + } SUPPLYSRC_b; + } ; + + union { + __IOM uint32_t SUPPLYSTATUS; /*!< (@ 0x00000004) Voltage Regulators status */ + + struct { + __IOM uint32_t SIMOBUCKON : 1; /*!< [0..0] Indicates whether the Core/Mem low-voltage domains are + supplied from the LDO or the Buck. */ + __IOM uint32_t BLEBUCKON : 1; /*!< [1..1] Indicates whether the BLE (if supported) domain and burst + (if supported) domain is supplied from the LDO or the Buck. + Buck will be powered up only if there is an active request + for BLEH domain or Burst mode and appropriate reature is + allowed. */ + } SUPPLYSTATUS_b; + } ; + + union { + __IOM uint32_t DEVPWREN; /*!< (@ 0x00000008) Device Power Enables */ + + struct { + __IOM uint32_t PWRIOS : 1; /*!< [0..0] Power up IO Slave */ + __IOM uint32_t PWRIOM0 : 1; /*!< [1..1] Power up IO Master 0 */ + __IOM uint32_t PWRIOM1 : 1; /*!< [2..2] Power up IO Master 1 */ + __IOM uint32_t PWRIOM2 : 1; /*!< [3..3] Power up IO Master 2 */ + __IOM uint32_t PWRIOM3 : 1; /*!< [4..4] Power up IO Master 3 */ + __IOM uint32_t PWRIOM4 : 1; /*!< [5..5] Power up IO Master 4 */ + __IOM uint32_t PWRIOM5 : 1; /*!< [6..6] Power up IO Master 5 */ + __IOM uint32_t PWRUART0 : 1; /*!< [7..7] Power up UART Controller 0 */ + __IOM uint32_t PWRUART1 : 1; /*!< [8..8] Power up UART Controller 1 */ + __IOM uint32_t PWRADC : 1; /*!< [9..9] Power up ADC Digital Controller */ + __IOM uint32_t PWRSCARD : 1; /*!< [10..10] Power up SCARD Controller */ + __IOM uint32_t PWRMSPI : 1; /*!< [11..11] Power up MSPI Controller */ + __IOM uint32_t PWRPDM : 1; /*!< [12..12] Power up PDM block */ + __IOM uint32_t PWRBLEL : 1; /*!< [13..13] Power up BLE controller */ + } DEVPWREN_b; + } ; + + union { + __IOM uint32_t MEMPWDINSLEEP; /*!< (@ 0x0000000C) Powerdown SRAM banks in Deep Sleep mode */ + + struct { + __IOM uint32_t DTCMPWDSLP : 3; /*!< [2..0] power down DTCM in deep sleep */ + __IOM uint32_t SRAMPWDSLP : 10; /*!< [12..3] Selects which SRAM banks are powered down in deep sleep + mode, causing the contents of the bank to be lost. */ + __IOM uint32_t FLASH0PWDSLP : 1; /*!< [13..13] Powerdown flash0 in deep sleep */ + __IOM uint32_t FLASH1PWDSLP : 1; /*!< [14..14] Powerdown flash1 in deep sleep */ + __IM uint32_t : 16; + __IOM uint32_t CACHEPWDSLP : 1; /*!< [31..31] power down cache in deep sleep */ + } MEMPWDINSLEEP_b; + } ; + + union { + __IOM uint32_t MEMPWREN; /*!< (@ 0x00000010) Enables individual banks of the MEMORY array */ + + struct { + __IOM uint32_t DTCM : 3; /*!< [2..0] Power up DTCM */ + __IOM uint32_t SRAM : 10; /*!< [12..3] Power up SRAM groups */ + __IOM uint32_t FLASH0 : 1; /*!< [13..13] Power up Flash0 */ + __IOM uint32_t FLASH1 : 1; /*!< [14..14] Power up Flash1 */ + __IM uint32_t : 15; + __IOM uint32_t CACHEB0 : 1; /*!< [30..30] Power up Cache Bank 0. This works in conjunction with + Cache enable from flash_cache module. To power up cache + bank0, cache has to be enabled and this bit has to be set. */ + __IOM uint32_t CACHEB2 : 1; /*!< [31..31] Power up Cache Bank 2. This works in conjunction with + Cache enable from flash_cache module. To power up cache + bank2, cache has to be enabled and this bit has to be set. */ + } MEMPWREN_b; + } ; + + union { + __IOM uint32_t MEMPWRSTATUS; /*!< (@ 0x00000014) Mem Power ON Status */ + + struct { + __IOM uint32_t DTCM00 : 1; /*!< [0..0] This bit is 1 if power is supplied to DTCM GROUP0_0 */ + __IOM uint32_t DTCM01 : 1; /*!< [1..1] This bit is 1 if power is supplied to DTCM GROUP0_1 */ + __IOM uint32_t DTCM1 : 1; /*!< [2..2] This bit is 1 if power is supplied to DTCM GROUP1 */ + __IOM uint32_t SRAM0 : 1; /*!< [3..3] This bit is 1 if power is supplied to SRAM GROUP0 */ + __IOM uint32_t SRAM1 : 1; /*!< [4..4] This bit is 1 if power is supplied to SRAM GROUP1 */ + __IOM uint32_t SRAM2 : 1; /*!< [5..5] This bit is 1 if power is supplied to SRAM GROUP2 */ + __IOM uint32_t SRAM3 : 1; /*!< [6..6] This bit is 1 if power is supplied to SRAM GROUP3 */ + __IOM uint32_t SRAM4 : 1; /*!< [7..7] This bit is 1 if power is supplied to SRAM GROUP4 */ + __IOM uint32_t SRAM5 : 1; /*!< [8..8] This bit is 1 if power is supplied to SRAM GROUP5 */ + __IOM uint32_t SRAM6 : 1; /*!< [9..9] This bit is 1 if power is supplied to SRAM GROUP6 */ + __IOM uint32_t SRAM7 : 1; /*!< [10..10] This bit is 1 if power is supplied to SRAM GROUP7 */ + __IOM uint32_t SRAM8 : 1; /*!< [11..11] This bit is 1 if power is supplied to SRAM GROUP8 */ + __IOM uint32_t SRAM9 : 1; /*!< [12..12] This bit is 1 if power is supplied to SRAM GROUP9 */ + __IOM uint32_t FLASH0 : 1; /*!< [13..13] This bit is 1 if power is supplied to FLASH 0 */ + __IOM uint32_t FLASH1 : 1; /*!< [14..14] This bit is 1 if power is supplied to FLASH 1 */ + __IOM uint32_t CACHEB0 : 1; /*!< [15..15] This bit is 1 if power is supplied to Cache Bank 0 */ + __IOM uint32_t CACHEB2 : 1; /*!< [16..16] This bit is 1 if power is supplied to Cache Bank 2 */ + } MEMPWRSTATUS_b; + } ; + + union { + __IOM uint32_t DEVPWRSTATUS; /*!< (@ 0x00000018) Device Power ON Status */ + + struct { + __IOM uint32_t MCUL : 1; /*!< [0..0] This bit is 1 if power is supplied to MCUL */ + __IOM uint32_t MCUH : 1; /*!< [1..1] This bit is 1 if power is supplied to MCUH */ + __IOM uint32_t HCPA : 1; /*!< [2..2] This bit is 1 if power is supplied to HCPA domain (IO + SLAVE, UART0, UART1, SCARD) */ + __IOM uint32_t HCPB : 1; /*!< [3..3] This bit is 1 if power is supplied to HCPB domain (IO + MASTER 0, 1, 2) */ + __IOM uint32_t HCPC : 1; /*!< [4..4] This bit is 1 if power is supplied to HCPC domain (IO + MASTER4, 5, 6) */ + __IOM uint32_t PWRADC : 1; /*!< [5..5] This bit is 1 if power is supplied to ADC */ + __IOM uint32_t PWRMSPI : 1; /*!< [6..6] This bit is 1 if power is supplied to MSPI */ + __IOM uint32_t PWRPDM : 1; /*!< [7..7] This bit is 1 if power is supplied to PDM */ + __IOM uint32_t BLEL : 1; /*!< [8..8] This bit is 1 if power is supplied to BLEL */ + __IOM uint32_t BLEH : 1; /*!< [9..9] This bit is 1 if power is supplied to BLEH */ + __IM uint32_t : 19; + __IOM uint32_t CORESLEEP : 1; /*!< [29..29] This bit is 1 if CORE has been in SLEEP State. Write + '1' to this bit to clear it. */ + __IOM uint32_t COREDEEPSLEEP : 1; /*!< [30..30] This bit is 1 if CORE has been in Deep Sleep. Write + '1' to this bit to clear it. */ + __IOM uint32_t SYSDEEPSLEEP : 1; /*!< [31..31] This bit is 1 if SYSTEM has been in Deep Sleep. Write + '1' to this bit to clear it. */ + } DEVPWRSTATUS_b; + } ; + + union { + __IOM uint32_t SRAMCTRL; /*!< (@ 0x0000001C) SRAM Control register */ + + struct { + __IM uint32_t : 1; + __IOM uint32_t SRAMCLKGATE : 1; /*!< [1..1] This bit is 1 if clock gating is allowed for individual + system SRAMs */ + __IOM uint32_t SRAMMASTERCLKGATE : 1; /*!< [2..2] This bit is 1 when the master clock gate is enabled (top-level + clock gate for entire SRAM block) */ + __IM uint32_t : 5; + __IOM uint32_t SRAMLIGHTSLEEP : 12; /*!< [19..8] Light Sleep enable for each TCM/SRAM bank. When 1, corresponding + bank will be put into light sleep. For optimal power, banks + should be put into light sleep while the system is active + but the bank has minimal or no accesses. */ + } SRAMCTRL_b; + } ; + + union { + __IOM uint32_t ADCSTATUS; /*!< (@ 0x00000020) Power Status Register for ADC Block */ + + struct { + __IOM uint32_t ADCPWD : 1; /*!< [0..0] This bit indicates that the ADC is powered down */ + __IOM uint32_t BGTPWD : 1; /*!< [1..1] This bit indicates that the ADC Band Gap is powered down */ + __IOM uint32_t VPTATPWD : 1; /*!< [2..2] This bit indicates that the ADC temperature sensor input + buffer is powered down */ + __IOM uint32_t VBATPWD : 1; /*!< [3..3] This bit indicates that the ADC VBAT resistor divider + is powered down */ + __IOM uint32_t REFKEEPPWD : 1; /*!< [4..4] This bit indicates that the ADC REFKEEP is powered down */ + __IOM uint32_t REFBUFPWD : 1; /*!< [5..5] This bit indicates that the ADC REFBUF is powered down */ + } ADCSTATUS_b; + } ; + + union { + __IOM uint32_t MISC; /*!< (@ 0x00000024) Power Optimization Control Bits */ + + struct { + __IOM uint32_t SIMOBUCKEN : 1; /*!< [0..0] Enables and Selects the SIMO Buck as the supply for the + low-voltage power domain. It takes the initial value from + the bit set in Customer INFO space. */ + __IOM uint32_t FORCECOREVRLPPDM : 1; /*!< [1..1] Control bit to enable the core VR to go into LP mode + with HCPA/B/C/MSPI are powered off but PDM is powered on */ + __IOM uint32_t FORCECOREVRLPTIMERS : 1; /*!< [2..2] Control Bit to force Core VR to LP mode in deep sleep + even when hfrc based ctimer or stimer is running. */ + __IOM uint32_t FORCEMEMVRLPTIMERS : 1; /*!< [3..3] Control Bit to force Mem VR to LP mode in deep sleep + even when hfrc based ctimer or stimer is running. */ + __IOM uint32_t FORCEMEMVRADC : 2; /*!< [5..4] Control Bit to force mem VR to LP or ACT mode in deep + sleep when ADC is powered ON. 0x3 results in picking LP + mode. */ + __IOM uint32_t MEMVRLPBLE : 1; /*!< [6..6] Control Bit to let Mem VR go to lp mode in deep sleep + even when BLEL or BLEH is powered on given none of the + other domains require it. */ + __IOM uint32_t FORCEBLEBUCKACT : 1; /*!< [7..7] Control Bit to enable BLE Buck to be in active state + when BLE Buck is enabled. Default behavior is to be in + active only when Burst or BLEH power on are requested. */ + } MISC_b; + } ; + + union { + __IOM uint32_t DEVPWREVENTEN; /*!< (@ 0x00000028) Event enable register to control which DEVPWRSTATUS + bits are routed to event input of CPU. */ + + struct { + __IOM uint32_t MCULEVEN : 1; /*!< [0..0] Control MCUL power-on status event */ + __IOM uint32_t MCUHEVEN : 1; /*!< [1..1] Control MCUH power-on status event */ + __IOM uint32_t HCPAEVEN : 1; /*!< [2..2] Control HCPA power-on status event */ + __IOM uint32_t HCPBEVEN : 1; /*!< [3..3] Control HCPB power-on status event */ + __IOM uint32_t HCPCEVEN : 1; /*!< [4..4] Control HCPC power-on status event */ + __IOM uint32_t ADCEVEN : 1; /*!< [5..5] Control ADC power-on status event */ + __IOM uint32_t MSPIEVEN : 1; /*!< [6..6] Control MSPI power-on status event */ + __IOM uint32_t PDMEVEN : 1; /*!< [7..7] Control PDM power-on status event */ + __IOM uint32_t BLELEVEN : 1; /*!< [8..8] Control BLE power-on status event */ + __IM uint32_t : 20; + __IOM uint32_t BLEFEATUREEVEN : 1; /*!< [29..29] Control BLEFEATURE status event */ + __IOM uint32_t BURSTFEATUREEVEN : 1; /*!< [30..30] Control BURSTFEATURE status event */ + __IOM uint32_t BURSTEVEN : 1; /*!< [31..31] Control BURST status event */ + } DEVPWREVENTEN_b; + } ; + + union { + __IOM uint32_t MEMPWREVENTEN; /*!< (@ 0x0000002C) Event enable register to control which MEMPWRSTATUS + bits are routed to event input of CPU. */ + + struct { + __IOM uint32_t DTCMEN : 3; /*!< [2..0] Enable DTCM power-on status event */ + __IOM uint32_t SRAMEN : 10; /*!< [12..3] Control SRAM power-on status event */ + __IOM uint32_t FLASH0EN : 1; /*!< [13..13] Control Flash power-on status event */ + __IOM uint32_t FLASH1EN : 1; /*!< [14..14] Control Flash power-on status event */ + __IM uint32_t : 15; + __IOM uint32_t CACHEB0EN : 1; /*!< [30..30] Control CACHE BANK 0 power-on status event */ + __IOM uint32_t CACHEB2EN : 1; /*!< [31..31] Control CACHEB2 power-on status event */ + } MEMPWREVENTEN_b; + } ; +} PWRCTRL_Type; /*!< Size = 48 (0x30) */ + + + +/* =========================================================================================================================== */ +/* ================ RSTGEN ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief MCU Reset Generator (RSTGEN) + */ + +typedef struct { /*!< (@ 0x40000000) RSTGEN Structure */ + + union { + __IOM uint32_t CFG; /*!< (@ 0x00000000) Configuration Register */ + + struct { + __IOM uint32_t BODHREN : 1; /*!< [0..0] Brown out high (2.1v) reset enable. */ + __IOM uint32_t WDREN : 1; /*!< [1..1] Watchdog Timer Reset Enable. NOTE: The WDT module must + also be configured for WDT reset. This includes enabling + the RESEN bit in WDTCFG register in Watch dog timer block. */ + } CFG_b; + } ; + + union { + __IOM uint32_t SWPOI; /*!< (@ 0x00000004) Software POI Reset */ + + struct { + __IOM uint32_t SWPOIKEY : 8; /*!< [7..0] 0x1B generates a software POI reset. This is a write-only + register. Reading from this register will yield only all + 0s. */ + } SWPOI_b; + } ; + + union { + __IOM uint32_t SWPOR; /*!< (@ 0x00000008) Software POR Reset */ + + struct { + __IOM uint32_t SWPORKEY : 8; /*!< [7..0] 0xD4 generates a software POR reset. */ + } SWPOR_b; + } ; + __IM uint32_t RESERVED[2]; + + union { + __IOM uint32_t TPIURST; /*!< (@ 0x00000014) TPIU reset */ + + struct { + __IOM uint32_t TPIURST : 1; /*!< [0..0] Static reset for the TPIU. Write to '1' to assert reset + to TPIU. Write to '0' to clear the reset. */ + } TPIURST_b; + } ; + __IM uint32_t RESERVED1[122]; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000200) Reset Interrupt register: Enable */ + + struct { + __IOM uint32_t BODH : 1; /*!< [0..0] Enables an interrupt that triggers when VCC is below + BODH level. */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) Reset Interrupt register: Status */ + + struct { + __IOM uint32_t BODH : 1; /*!< [0..0] Enables an interrupt that triggers when VCC is below + BODH level. */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000208) Reset Interrupt register: Clear */ + + struct { + __IOM uint32_t BODH : 1; /*!< [0..0] Enables an interrupt that triggers when VCC is below + BODH level. */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000020C) Reset Interrupt register: Set */ + + struct { + __IOM uint32_t BODH : 1; /*!< [0..0] Enables an interrupt that triggers when VCC is below + BODH level. */ + } INTSET_b; + } ; + __IM uint32_t RESERVED2[67107708]; + + union { + __IOM uint32_t STAT; /*!< (@ 0x0FFFF000) Status Register (SBL) */ + + struct { + __IOM uint32_t EXRSTAT : 1; /*!< [0..0] Reset was initiated by an External Reset (SBL). */ + __IOM uint32_t PORSTAT : 1; /*!< [1..1] Reset was initiated by a Power-On Reset (SBL). */ + __IOM uint32_t BORSTAT : 1; /*!< [2..2] Reset was initiated by a Brown-Out Reset (SBL). */ + __IOM uint32_t SWRSTAT : 1; /*!< [3..3] Reset was a initiated by SW POR or AIRCR Reset (SBL). */ + __IOM uint32_t POIRSTAT : 1; /*!< [4..4] Reset was a initiated by Software POI Reset (SBL). */ + __IOM uint32_t DBGRSTAT : 1; /*!< [5..5] Reset was a initiated by Debugger Reset (SBL). */ + __IOM uint32_t WDRSTAT : 1; /*!< [6..6] Reset was initiated by a Watchdog Timer Reset (SBL). */ + __IOM uint32_t BOUSTAT : 1; /*!< [7..7] An Unregulated Supply Brownout Event occurred (SBL). */ + __IOM uint32_t BOCSTAT : 1; /*!< [8..8] A Core Regulator Brownout Event occurred (SBL). */ + __IOM uint32_t BOFSTAT : 1; /*!< [9..9] A Memory Regulator Brownout Event occurred (SBL). */ + __IOM uint32_t BOBSTAT : 1; /*!< [10..10] A BLE/Burst Regulator Brownout Event occurred (SBL). */ + __IM uint32_t : 19; + __IOM uint32_t FBOOT : 1; /*!< [30..30] Set if current boot was initiated by soft reset and + resulted in Fast Boot (SBL). */ + __IOM uint32_t SBOOT : 1; /*!< [31..31] Set when booting securely (SBL). */ + } STAT_b; + } ; +} RSTGEN_Type; /*!< Size = 268431364 (0xffff004) */ + + + +/* =========================================================================================================================== */ +/* ================ RTC ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Real Time Clock (RTC) + */ + +typedef struct { /*!< (@ 0x40004200) RTC Structure */ + __IM uint32_t RESERVED[16]; + + union { + __IOM uint32_t CTRLOW; /*!< (@ 0x00000040) RTC Counters Lower */ + + struct { + __IOM uint32_t CTR100 : 8; /*!< [7..0] 100ths of a second Counter */ + __IOM uint32_t CTRSEC : 7; /*!< [14..8] Seconds Counter */ + __IM uint32_t : 1; + __IOM uint32_t CTRMIN : 7; /*!< [22..16] Minutes Counter */ + __IM uint32_t : 1; + __IOM uint32_t CTRHR : 6; /*!< [29..24] Hours Counter */ + } CTRLOW_b; + } ; + + union { + __IOM uint32_t CTRUP; /*!< (@ 0x00000044) RTC Counters Upper */ + + struct { + __IOM uint32_t CTRDATE : 6; /*!< [5..0] Date Counter */ + __IM uint32_t : 2; + __IOM uint32_t CTRMO : 5; /*!< [12..8] Months Counter */ + __IM uint32_t : 3; + __IOM uint32_t CTRYR : 8; /*!< [23..16] Years Counter */ + __IOM uint32_t CTRWKDY : 3; /*!< [26..24] Weekdays Counter */ + __IOM uint32_t CB : 1; /*!< [27..27] Century */ + __IOM uint32_t CEB : 1; /*!< [28..28] Century enable */ + __IM uint32_t : 2; + __IOM uint32_t CTERR : 1; /*!< [31..31] Counter read error status. Error is triggered when + software reads the lower word of the counters, and fails + to read the upper counter within 1/100 second. This is + because when the lower counter is read, the upper counter + is held off from incrementing until it is read so that + the full time stamp can be read. */ + } CTRUP_b; + } ; + + union { + __IOM uint32_t ALMLOW; /*!< (@ 0x00000048) RTC Alarms Lower */ + + struct { + __IOM uint32_t ALM100 : 8; /*!< [7..0] 100ths of a second Alarm */ + __IOM uint32_t ALMSEC : 7; /*!< [14..8] Seconds Alarm */ + __IM uint32_t : 1; + __IOM uint32_t ALMMIN : 7; /*!< [22..16] Minutes Alarm */ + __IM uint32_t : 1; + __IOM uint32_t ALMHR : 6; /*!< [29..24] Hours Alarm */ + } ALMLOW_b; + } ; + + union { + __IOM uint32_t ALMUP; /*!< (@ 0x0000004C) RTC Alarms Upper */ + + struct { + __IOM uint32_t ALMDATE : 6; /*!< [5..0] Date Alarm */ + __IM uint32_t : 2; + __IOM uint32_t ALMMO : 5; /*!< [12..8] Months Alarm */ + __IM uint32_t : 3; + __IOM uint32_t ALMWKDY : 3; /*!< [18..16] Weekdays Alarm */ + } ALMUP_b; + } ; + + union { + __IOM uint32_t RTCCTL; /*!< (@ 0x00000050) RTC Control Register */ + + struct { + __IOM uint32_t WRTC : 1; /*!< [0..0] Counter write control */ + __IOM uint32_t RPT : 3; /*!< [3..1] Alarm repeat interval */ + __IOM uint32_t RSTOP : 1; /*!< [4..4] RTC input clock control */ + __IOM uint32_t HR1224 : 1; /*!< [5..5] Hours Counter mode */ + } RTCCTL_b; + } ; + __IM uint32_t RESERVED1[43]; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000100) RTC Interrupt Register: Enable */ + + struct { + __IOM uint32_t ALM : 1; /*!< [0..0] RTC Alarm interrupt */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000104) RTC Interrupt Register: Status */ + + struct { + __IOM uint32_t ALM : 1; /*!< [0..0] RTC Alarm interrupt */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000108) RTC Interrupt Register: Clear */ + + struct { + __IOM uint32_t ALM : 1; /*!< [0..0] RTC Alarm interrupt */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000010C) RTC Interrupt Register: Set */ + + struct { + __IOM uint32_t ALM : 1; /*!< [0..0] RTC Alarm interrupt */ + } INTSET_b; + } ; +} RTC_Type; /*!< Size = 272 (0x110) */ + + + +/* =========================================================================================================================== */ +/* ================ SCARD ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Serial ISO7816 (SCARD) + */ + +typedef struct { /*!< (@ 0x40080000) SCARD Structure */ + + union { + __IOM uint32_t SR; /*!< (@ 0x00000000) ISO7816 interrupt status */ + + struct { + __IOM uint32_t FNE : 1; /*!< [0..0] RX FIFO not empty. */ + __IOM uint32_t TBERBF : 1; /*!< [1..1] FIFO empty (transmit) or full (receive). */ + __IOM uint32_t FER : 1; /*!< [2..2] Framing error. */ + __IOM uint32_t OVR : 1; /*!< [3..3] RX FIFO overflow. */ + __IOM uint32_t PE : 1; /*!< [4..4] Parity Error. */ + __IOM uint32_t FT2REND : 1; /*!< [5..5] TX to RX finished. */ + __IOM uint32_t FHF : 1; /*!< [6..6] FIFO Half Full. */ + } SR_b; + } ; + __IM uint32_t RESERVED[3]; + + union { + __IOM uint32_t DR; /*!< (@ 0x00000010) ISO7816 data */ + + struct { + __IOM uint32_t DR : 8; /*!< [7..0] Data register. */ + } DR_b; + } ; + __IM uint32_t RESERVED1[3]; + + union { + __IOM uint32_t SR1; /*!< (@ 0x00000020) ISO7816 interrupt status 1 */ + + struct { + __IOM uint32_t ECNTOVER : 1; /*!< [0..0] ETU counter overflow. */ + __IOM uint32_t PRL : 1; /*!< [1..1] Card insert/remove. */ + __IOM uint32_t SYNCEND : 1; /*!< [2..2] Write complete synchronization. */ + __IOM uint32_t IDLE : 1; /*!< [3..3] ISO7816 idle. */ + } SR1_b; + } ; + __IM uint32_t RESERVED2[5]; + + union { + __IOM uint32_t RETXCNTRMI; /*!< (@ 0x00000038) ISO7816 resent count inquiry */ + + struct { + __IOM uint32_t RETXCNTRMI : 4; /*!< [3..0] Resent count inquiry register. */ + } RETXCNTRMI_b; + } ; + __IM uint32_t RESERVED3[49]; + + union { + __IOM uint32_t CLKCTRL; /*!< (@ 0x00000100) Clock Control */ + + struct { + __IOM uint32_t CLKEN : 1; /*!< [0..0] Enable the serial source clock for SCARD. */ + __IOM uint32_t APBCLKEN : 1; /*!< [1..1] Enable the SCARD APB clock to run continuously. */ + } CLKCTRL_b; + } ; +} SCARD_Type; /*!< Size = 260 (0x104) */ + + + +/* =========================================================================================================================== */ +/* ================ SECURITY ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Security Interfaces (SECURITY) + */ + +typedef struct { /*!< (@ 0x40030000) SECURITY Structure */ + + union { + __IOM uint32_t CTRL; /*!< (@ 0x00000000) Control Register */ + + struct { + __IOM uint32_t ENABLE : 1; /*!< [0..0] Function Enable. Software should set the ENABLE bit to + initiate a CRC operation. Hardware will clear the ENABLE + bit upon completion. */ + __IM uint32_t : 3; + __IOM uint32_t FUNCTION : 4; /*!< [7..4] Function Select */ + __IM uint32_t : 23; + __IOM uint32_t CRCERROR : 1; /*!< [31..31] CRC Error Status - Set to 1 if an error occurs during + a CRC operation. Cleared when CTRL register is written + (with any value). Usually indicates an invalid address + range. */ + } CTRL_b; + } ; + __IM uint32_t RESERVED[3]; + + union { + __IOM uint32_t SRCADDR; /*!< (@ 0x00000010) Source Addresss */ + + struct { + __IOM uint32_t ADDR : 32; /*!< [31..0] Source Buffer Address. Address may be byte aligned, + but the length must be a multiple of 4 bits. */ + } SRCADDR_b; + } ; + __IM uint32_t RESERVED1[3]; + + union { + __IOM uint32_t LEN; /*!< (@ 0x00000020) Length */ + + struct { + __IM uint32_t : 2; + __IOM uint32_t LEN : 18; /*!< [19..2] Buffer size (bottom two bits assumed to be zero to ensure + a multiple of 4 bytes) */ + } LEN_b; + } ; + __IM uint32_t RESERVED2[3]; + + union { + __IOM uint32_t RESULT; /*!< (@ 0x00000030) CRC Seed/Result Register */ + + struct { + __IOM uint32_t CRC : 32; /*!< [31..0] CRC Seed/Result. Software must seed the CRC with 0xFFFFFFFF + before starting a CRC operation (unless the CRC is continued + from a previous operation). */ + } RESULT_b; + } ; + __IM uint32_t RESERVED3[17]; + + union { + __IOM uint32_t LOCKCTRL; /*!< (@ 0x00000078) LOCK Control Register */ + + struct { + __IOM uint32_t SELECT : 8; /*!< [7..0] LOCK Function Select register. */ + } LOCKCTRL_b; + } ; + + union { + __IOM uint32_t LOCKSTAT; /*!< (@ 0x0000007C) LOCK Status Register */ + + struct { + __IOM uint32_t STATUS : 32; /*!< [31..0] LOCK Status register. This register is a bitmask for + which resources are currently unlocked. These bits are + one-hot per resource. */ + } LOCKSTAT_b; + } ; + + union { + __IOM uint32_t KEY0; /*!< (@ 0x00000080) Key0 Register */ + + struct { + __IOM uint32_t KEY0 : 32; /*!< [31..0] Bits [31:0] of the 128-bit key should be written to + this register. To protect key values, the register always + returns 0x00000000. */ + } KEY0_b; + } ; + + union { + __IOM uint32_t KEY1; /*!< (@ 0x00000084) Key1 Register */ + + struct { + __IOM uint32_t KEY1 : 32; /*!< [31..0] Bits [63:32] of the 128-bit key should be written to + this register. To protect key values, the register always + returns 0x00000000. */ + } KEY1_b; + } ; + + union { + __IOM uint32_t KEY2; /*!< (@ 0x00000088) Key2 Register */ + + struct { + __IOM uint32_t KEY2 : 32; /*!< [31..0] Bits [95:64] of the 128-bit key should be written to + this register. To protect key values, the register always + returns 0x00000000. */ + } KEY2_b; + } ; + + union { + __IOM uint32_t KEY3; /*!< (@ 0x0000008C) Key3 Register */ + + struct { + __IOM uint32_t KEY3 : 32; /*!< [31..0] Bits [127:96] of the 128-bit key should be written to + this register. To protect key values, the register always + returns 0x00000000. */ + } KEY3_b; + } ; +} SECURITY_Type; /*!< Size = 144 (0x90) */ + + + +/* =========================================================================================================================== */ +/* ================ UART0 ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Serial UART (UART0) + */ + +typedef struct { /*!< (@ 0x4001C000) UART0 Structure */ + + union { + __IOM uint32_t DR; /*!< (@ 0x00000000) UART Data Register */ + + struct { + __IOM uint32_t DATA : 8; /*!< [7..0] This is the UART data port. */ + __IOM uint32_t FEDATA : 1; /*!< [8..8] This is the framing error indicator. */ + __IOM uint32_t PEDATA : 1; /*!< [9..9] This is the parity error indicator. */ + __IOM uint32_t BEDATA : 1; /*!< [10..10] This is the break error indicator. */ + __IOM uint32_t OEDATA : 1; /*!< [11..11] This is the overrun error indicator. */ + } DR_b; + } ; + + union { + __IOM uint32_t RSR; /*!< (@ 0x00000004) UART Status Register */ + + struct { + __IOM uint32_t FESTAT : 1; /*!< [0..0] This is the framing error indicator. */ + __IOM uint32_t PESTAT : 1; /*!< [1..1] This is the parity error indicator. */ + __IOM uint32_t BESTAT : 1; /*!< [2..2] This is the break error indicator. */ + __IOM uint32_t OESTAT : 1; /*!< [3..3] This is the overrun error indicator. */ + } RSR_b; + } ; + __IM uint32_t RESERVED[4]; + + union { + __IOM uint32_t FR; /*!< (@ 0x00000018) Flag Register */ + + struct { + __IOM uint32_t CTS : 1; /*!< [0..0] This bit holds the clear to send indicator. */ + __IOM uint32_t DSR : 1; /*!< [1..1] This bit holds the data set ready indicator. */ + __IOM uint32_t DCD : 1; /*!< [2..2] This bit holds the data carrier detect indicator. */ + __IOM uint32_t BUSY : 1; /*!< [3..3] This bit holds the busy indicator. */ + __IOM uint32_t RXFE : 1; /*!< [4..4] This bit holds the receive FIFO empty indicator. */ + __IOM uint32_t TXFF : 1; /*!< [5..5] This bit holds the transmit FIFO full indicator. */ + __IOM uint32_t RXFF : 1; /*!< [6..6] This bit holds the receive FIFO full indicator. */ + __IOM uint32_t TXFE : 1; /*!< [7..7] This bit holds the transmit FIFO empty indicator. */ + __IOM uint32_t TXBUSY : 1; /*!< [8..8] This bit holds the transmit BUSY indicator. */ + } FR_b; + } ; + __IM uint32_t RESERVED1; + + union { + __IOM uint32_t ILPR; /*!< (@ 0x00000020) IrDA Counter */ + + struct { + __IOM uint32_t ILPDVSR : 8; /*!< [7..0] These bits hold the IrDA counter divisor. */ + } ILPR_b; + } ; + + union { + __IOM uint32_t IBRD; /*!< (@ 0x00000024) Integer Baud Rate Divisor */ + + struct { + __IOM uint32_t DIVINT : 16; /*!< [15..0] These bits hold the baud integer divisor. */ + } IBRD_b; + } ; + + union { + __IOM uint32_t FBRD; /*!< (@ 0x00000028) Fractional Baud Rate Divisor */ + + struct { + __IOM uint32_t DIVFRAC : 6; /*!< [5..0] These bits hold the baud fractional divisor. */ + } FBRD_b; + } ; + + union { + __IOM uint32_t LCRH; /*!< (@ 0x0000002C) Line Control High */ + + struct { + __IOM uint32_t BRK : 1; /*!< [0..0] This bit holds the break set. */ + __IOM uint32_t PEN : 1; /*!< [1..1] This bit holds the parity enable. */ + __IOM uint32_t EPS : 1; /*!< [2..2] This bit holds the even parity select. */ + __IOM uint32_t STP2 : 1; /*!< [3..3] This bit holds the two stop bits select. */ + __IOM uint32_t FEN : 1; /*!< [4..4] This bit holds the FIFO enable. */ + __IOM uint32_t WLEN : 2; /*!< [6..5] These bits hold the write length. */ + __IOM uint32_t SPS : 1; /*!< [7..7] This bit holds the stick parity select. */ + } LCRH_b; + } ; + + union { + __IOM uint32_t CR; /*!< (@ 0x00000030) Control Register */ + + struct { + __IOM uint32_t UARTEN : 1; /*!< [0..0] This bit is the UART enable. */ + __IOM uint32_t SIREN : 1; /*!< [1..1] This bit is the SIR ENDEC enable. */ + __IOM uint32_t SIRLP : 1; /*!< [2..2] This bit is the SIR low power select. */ + __IOM uint32_t CLKEN : 1; /*!< [3..3] This bit is the UART clock enable. */ + __IOM uint32_t CLKSEL : 3; /*!< [6..4] This bitfield is the UART clock select. */ + __IOM uint32_t LBE : 1; /*!< [7..7] This bit is the loopback enable. */ + __IOM uint32_t TXE : 1; /*!< [8..8] This bit is the transmit enable. */ + __IOM uint32_t RXE : 1; /*!< [9..9] This bit is the receive enable. */ + __IOM uint32_t DTR : 1; /*!< [10..10] This bit enables data transmit ready. */ + __IOM uint32_t RTS : 1; /*!< [11..11] This bit enables request to send. */ + __IOM uint32_t OUT1 : 1; /*!< [12..12] This bit holds modem Out1. */ + __IOM uint32_t OUT2 : 1; /*!< [13..13] This bit holds modem Out2. */ + __IOM uint32_t RTSEN : 1; /*!< [14..14] This bit enables RTS hardware flow control. */ + __IOM uint32_t CTSEN : 1; /*!< [15..15] This bit enables CTS hardware flow control. */ + } CR_b; + } ; + + union { + __IOM uint32_t IFLS; /*!< (@ 0x00000034) FIFO Interrupt Level Select */ + + struct { + __IOM uint32_t TXIFLSEL : 3; /*!< [2..0] These bits hold the transmit FIFO interrupt level. */ + __IOM uint32_t RXIFLSEL : 3; /*!< [5..3] These bits hold the receive FIFO interrupt level. */ + } IFLS_b; + } ; + + union { + __IOM uint32_t IER; /*!< (@ 0x00000038) Interrupt Enable */ + + struct { + __IOM uint32_t TXCMPMIM : 1; /*!< [0..0] This bit holds the modem TXCMP interrupt enable. */ + __IOM uint32_t CTSMIM : 1; /*!< [1..1] This bit holds the modem CTS interrupt enable. */ + __IOM uint32_t DCDMIM : 1; /*!< [2..2] This bit holds the modem DCD interrupt enable. */ + __IOM uint32_t DSRMIM : 1; /*!< [3..3] This bit holds the modem DSR interrupt enable. */ + __IOM uint32_t RXIM : 1; /*!< [4..4] This bit holds the receive interrupt enable. */ + __IOM uint32_t TXIM : 1; /*!< [5..5] This bit holds the transmit interrupt enable. */ + __IOM uint32_t RTIM : 1; /*!< [6..6] This bit holds the receive timeout interrupt enable. */ + __IOM uint32_t FEIM : 1; /*!< [7..7] This bit holds the framing error interrupt enable. */ + __IOM uint32_t PEIM : 1; /*!< [8..8] This bit holds the parity error interrupt enable. */ + __IOM uint32_t BEIM : 1; /*!< [9..9] This bit holds the break error interrupt enable. */ + __IOM uint32_t OEIM : 1; /*!< [10..10] This bit holds the overflow interrupt enable. */ + } IER_b; + } ; + + union { + __IOM uint32_t IES; /*!< (@ 0x0000003C) Interrupt Status */ + + struct { + __IOM uint32_t TXCMPMRIS : 1; /*!< [0..0] This bit holds the modem TXCMP interrupt status. */ + __IOM uint32_t CTSMRIS : 1; /*!< [1..1] This bit holds the modem CTS interrupt status. */ + __IOM uint32_t DCDMRIS : 1; /*!< [2..2] This bit holds the modem DCD interrupt status. */ + __IOM uint32_t DSRMRIS : 1; /*!< [3..3] This bit holds the modem DSR interrupt status. */ + __IOM uint32_t RXRIS : 1; /*!< [4..4] This bit holds the receive interrupt status. */ + __IOM uint32_t TXRIS : 1; /*!< [5..5] This bit holds the transmit interrupt status. */ + __IOM uint32_t RTRIS : 1; /*!< [6..6] This bit holds the receive timeout interrupt status. */ + __IOM uint32_t FERIS : 1; /*!< [7..7] This bit holds the framing error interrupt status. */ + __IOM uint32_t PERIS : 1; /*!< [8..8] This bit holds the parity error interrupt status. */ + __IOM uint32_t BERIS : 1; /*!< [9..9] This bit holds the break error interrupt status. */ + __IOM uint32_t OERIS : 1; /*!< [10..10] This bit holds the overflow interrupt status. */ + } IES_b; + } ; + + union { + __IOM uint32_t MIS; /*!< (@ 0x00000040) Masked Interrupt Status */ + + struct { + __IOM uint32_t TXCMPMMIS : 1; /*!< [0..0] This bit holds the modem TXCMP interrupt status masked. */ + __IOM uint32_t CTSMMIS : 1; /*!< [1..1] This bit holds the modem CTS interrupt status masked. */ + __IOM uint32_t DCDMMIS : 1; /*!< [2..2] This bit holds the modem DCD interrupt status masked. */ + __IOM uint32_t DSRMMIS : 1; /*!< [3..3] This bit holds the modem DSR interrupt status masked. */ + __IOM uint32_t RXMIS : 1; /*!< [4..4] This bit holds the receive interrupt status masked. */ + __IOM uint32_t TXMIS : 1; /*!< [5..5] This bit holds the transmit interrupt status masked. */ + __IOM uint32_t RTMIS : 1; /*!< [6..6] This bit holds the receive timeout interrupt status masked. */ + __IOM uint32_t FEMIS : 1; /*!< [7..7] This bit holds the framing error interrupt status masked. */ + __IOM uint32_t PEMIS : 1; /*!< [8..8] This bit holds the parity error interrupt status masked. */ + __IOM uint32_t BEMIS : 1; /*!< [9..9] This bit holds the break error interrupt status masked. */ + __IOM uint32_t OEMIS : 1; /*!< [10..10] This bit holds the overflow interrupt status masked. */ + } MIS_b; + } ; + + union { + __IOM uint32_t IEC; /*!< (@ 0x00000044) Interrupt Clear */ + + struct { + __IOM uint32_t TXCMPMIC : 1; /*!< [0..0] This bit holds the modem TXCMP interrupt clear. */ + __IOM uint32_t CTSMIC : 1; /*!< [1..1] This bit holds the modem CTS interrupt clear. */ + __IOM uint32_t DCDMIC : 1; /*!< [2..2] This bit holds the modem DCD interrupt clear. */ + __IOM uint32_t DSRMIC : 1; /*!< [3..3] This bit holds the modem DSR interrupt clear. */ + __IOM uint32_t RXIC : 1; /*!< [4..4] This bit holds the receive interrupt clear. */ + __IOM uint32_t TXIC : 1; /*!< [5..5] This bit holds the transmit interrupt clear. */ + __IOM uint32_t RTIC : 1; /*!< [6..6] This bit holds the receive timeout interrupt clear. */ + __IOM uint32_t FEIC : 1; /*!< [7..7] This bit holds the framing error interrupt clear. */ + __IOM uint32_t PEIC : 1; /*!< [8..8] This bit holds the parity error interrupt clear. */ + __IOM uint32_t BEIC : 1; /*!< [9..9] This bit holds the break error interrupt clear. */ + __IOM uint32_t OEIC : 1; /*!< [10..10] This bit holds the overflow interrupt clear. */ + } IEC_b; + } ; +} UART0_Type; /*!< Size = 72 (0x48) */ + + + +/* =========================================================================================================================== */ +/* ================ VCOMP ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Voltage Comparator (VCOMP) + */ + +typedef struct { /*!< (@ 0x4000C000) VCOMP Structure */ + + union { + __IOM uint32_t CFG; /*!< (@ 0x00000000) Configuration Register */ + + struct { + __IOM uint32_t PSEL : 2; /*!< [1..0] This bitfield selects the positive input to the comparator. */ + __IM uint32_t : 6; + __IOM uint32_t NSEL : 2; /*!< [9..8] This bitfield selects the negative input to the comparator. */ + __IM uint32_t : 6; + __IOM uint32_t LVLSEL : 4; /*!< [19..16] When the reference input NSEL is set to NSEL_DAC, this + bitfield selects the voltage level for the negative input + to the comparator. */ + } CFG_b; + } ; + + union { + __IOM uint32_t STAT; /*!< (@ 0x00000004) Status Register */ + + struct { + __IOM uint32_t CMPOUT : 1; /*!< [0..0] This bit is 1 if the positive input of the comparator + is greater than the negative input. */ + __IOM uint32_t PWDSTAT : 1; /*!< [1..1] This bit indicates the power down state of the voltage + comparator. */ + } STAT_b; + } ; + + union { + __IOM uint32_t PWDKEY; /*!< (@ 0x00000008) Key Register for Powering Down the Voltage Comparator */ + + struct { + __IOM uint32_t PWDKEY : 32; /*!< [31..0] Key register value. */ + } PWDKEY_b; + } ; + __IM uint32_t RESERVED[125]; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000200) Voltage Comparator Interrupt registers: Enable */ + + struct { + __IOM uint32_t OUTLOW : 1; /*!< [0..0] This bit is the vcompout low interrupt. */ + __IOM uint32_t OUTHI : 1; /*!< [1..1] This bit is the vcompout high interrupt. */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) Voltage Comparator Interrupt registers: Status */ + + struct { + __IOM uint32_t OUTLOW : 1; /*!< [0..0] This bit is the vcompout low interrupt. */ + __IOM uint32_t OUTHI : 1; /*!< [1..1] This bit is the vcompout high interrupt. */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000208) Voltage Comparator Interrupt registers: Clear */ + + struct { + __IOM uint32_t OUTLOW : 1; /*!< [0..0] This bit is the vcompout low interrupt. */ + __IOM uint32_t OUTHI : 1; /*!< [1..1] This bit is the vcompout high interrupt. */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000020C) Voltage Comparator Interrupt registers: Set */ + + struct { + __IOM uint32_t OUTLOW : 1; /*!< [0..0] This bit is the vcompout low interrupt. */ + __IOM uint32_t OUTHI : 1; /*!< [1..1] This bit is the vcompout high interrupt. */ + } INTSET_b; + } ; +} VCOMP_Type; /*!< Size = 528 (0x210) */ + + + +/* =========================================================================================================================== */ +/* ================ WDT ================ */ +/* =========================================================================================================================== */ + + +/** + * @brief Watchdog Timer (WDT) + */ + +typedef struct { /*!< (@ 0x40024000) WDT Structure */ + + union { + __IOM uint32_t CFG; /*!< (@ 0x00000000) Configuration Register */ + + struct { + __IOM uint32_t WDTEN : 1; /*!< [0..0] This bitfield enables the WDT. */ + __IOM uint32_t INTEN : 1; /*!< [1..1] This bitfield enables the WDT interrupt. Note : This + bit must be set before the interrupt status bit will reflect + a watchdog timer expiration. The IER interrupt register + must also be enabled for a WDT interrupt to be sent to + the NVIC. */ + __IOM uint32_t RESEN : 1; /*!< [2..2] This bitfield enables the WDT reset. This needs to be + set together with the WDREN bit in REG_RSTGEN_CFG register + (in reset gen) to trigger the reset. */ + __IM uint32_t : 5; + __IOM uint32_t RESVAL : 8; /*!< [15..8] This bitfield is the compare value for counter bits + 7:0 to generate a watchdog reset. This will cause a software + reset. */ + __IOM uint32_t INTVAL : 8; /*!< [23..16] This bitfield is the compare value for counter bits + 7:0 to generate a watchdog interrupt. */ + __IOM uint32_t CLKSEL : 3; /*!< [26..24] Select the frequency for the WDT. All values not enumerated + below are undefined. */ + } CFG_b; + } ; + + union { + __IOM uint32_t RSTRT; /*!< (@ 0x00000004) Restart the watchdog timer. */ + + struct { + __IOM uint32_t RSTRT : 8; /*!< [7..0] Writing 0xB2 to WDTRSTRT restarts the watchdog timer. + This is a write only register. Reading this register will + only provide all 0. */ + } RSTRT_b; + } ; + + union { + __IOM uint32_t LOCK; /*!< (@ 0x00000008) Locks the WDT */ + + struct { + __IOM uint32_t LOCK : 8; /*!< [7..0] Writing 0x3A locks the watchdog timer. Once locked, the + WDTCFG reg cannot be written and WDTEN is set. */ + } LOCK_b; + } ; + + union { + __IOM uint32_t COUNT; /*!< (@ 0x0000000C) Current Counter Value for WDT */ + + struct { + __IOM uint32_t COUNT : 8; /*!< [7..0] Read-Only current value of the WDT counter */ + } COUNT_b; + } ; + __IM uint32_t RESERVED[124]; + + union { + __IOM uint32_t INTEN; /*!< (@ 0x00000200) WDT Interrupt register: Enable */ + + struct { + __IOM uint32_t WDTINT : 1; /*!< [0..0] Watchdog Timer Interrupt. */ + } INTEN_b; + } ; + + union { + __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) WDT Interrupt register: Status */ + + struct { + __IOM uint32_t WDTINT : 1; /*!< [0..0] Watchdog Timer Interrupt. */ + } INTSTAT_b; + } ; + + union { + __IOM uint32_t INTCLR; /*!< (@ 0x00000208) WDT Interrupt register: Clear */ + + struct { + __IOM uint32_t WDTINT : 1; /*!< [0..0] Watchdog Timer Interrupt. */ + } INTCLR_b; + } ; + + union { + __IOM uint32_t INTSET; /*!< (@ 0x0000020C) WDT Interrupt register: Set */ + + struct { + __IOM uint32_t WDTINT : 1; /*!< [0..0] Watchdog Timer Interrupt. */ + } INTSET_b; + } ; +} WDT_Type; /*!< Size = 528 (0x210) */ + + +/** @} */ /* End of group Device_Peripheral_peripherals */ + + +/* =========================================================================================================================== */ +/* ================ Device Specific Peripheral Address Map ================ */ +/* =========================================================================================================================== */ + + +/** @addtogroup Device_Peripheral_peripheralAddr + * @{ + */ + +#define ADC_BASE 0x50010000UL +#define APBDMA_BASE 0x40011000UL +#define BLEIF_BASE 0x5000C000UL +#define CACHECTRL_BASE 0x40018000UL +#define CLKGEN_BASE 0x40004000UL +#define CTIMER_BASE 0x40008000UL +#define GPIO_BASE 0x40010000UL +#define IOM0_BASE 0x50004000UL +#define IOM1_BASE 0x50005000UL +#define IOM2_BASE 0x50006000UL +#define IOM3_BASE 0x50007000UL +#define IOM4_BASE 0x50008000UL +#define IOM5_BASE 0x50009000UL +#define IOSLAVE_BASE 0x50000000UL +#define MCUCTRL_BASE 0x40020000UL +#define MSPI_BASE 0x50014000UL +#define PDM_BASE 0x50011000UL +#define PWRCTRL_BASE 0x40021000UL +#define RSTGEN_BASE 0x40000000UL +#define RTC_BASE 0x40004200UL +#define SCARD_BASE 0x40080000UL +#define SECURITY_BASE 0x40030000UL +#define UART0_BASE 0x4001C000UL +#define UART1_BASE 0x4001D000UL +#define VCOMP_BASE 0x4000C000UL +#define WDT_BASE 0x40024000UL + +/** @} */ /* End of group Device_Peripheral_peripheralAddr */ + + +/* =========================================================================================================================== */ +/* ================ Peripheral declaration ================ */ +/* =========================================================================================================================== */ + + +/** @addtogroup Device_Peripheral_declaration + * @{ + */ + +#define ADC ((ADC_Type*) ADC_BASE) +#define APBDMA ((APBDMA_Type*) APBDMA_BASE) +#define BLEIF ((BLEIF_Type*) BLEIF_BASE) +#define CACHECTRL ((CACHECTRL_Type*) CACHECTRL_BASE) +#define CLKGEN ((CLKGEN_Type*) CLKGEN_BASE) +#define CTIMER ((CTIMER_Type*) CTIMER_BASE) +#define GPIO ((GPIO_Type*) GPIO_BASE) +#define IOM0 ((IOM0_Type*) IOM0_BASE) +#define IOM1 ((IOM0_Type*) IOM1_BASE) +#define IOM2 ((IOM0_Type*) IOM2_BASE) +#define IOM3 ((IOM0_Type*) IOM3_BASE) +#define IOM4 ((IOM0_Type*) IOM4_BASE) +#define IOM5 ((IOM0_Type*) IOM5_BASE) +#define IOSLAVE ((IOSLAVE_Type*) IOSLAVE_BASE) +#define MCUCTRL ((MCUCTRL_Type*) MCUCTRL_BASE) +#define MSPI ((MSPI_Type*) MSPI_BASE) +#define PDM ((PDM_Type*) PDM_BASE) +#define PWRCTRL ((PWRCTRL_Type*) PWRCTRL_BASE) +#define RSTGEN ((RSTGEN_Type*) RSTGEN_BASE) +#define RTC ((RTC_Type*) RTC_BASE) +#define SCARD ((SCARD_Type*) SCARD_BASE) +#define SECURITY ((SECURITY_Type*) SECURITY_BASE) +#define UART0 ((UART0_Type*) UART0_BASE) +#define UART1 ((UART0_Type*) UART1_BASE) +#define VCOMP ((VCOMP_Type*) VCOMP_BASE) +#define WDT ((WDT_Type*) WDT_BASE) + +/** @} */ /* End of group Device_Peripheral_declaration */ + + +/* ========================================= End of section using anonymous unions ========================================= */ +#if defined (__CC_ARM) + #pragma pop +#elif defined (__ICCARM__) + /* leave anonymous unions enabled */ +#elif (__ARMCC_VERSION >= 6010050) + #pragma clang diagnostic pop +#elif defined (__GNUC__) + /* anonymous unions are enabled by default */ +#elif defined (__TMS470__) + /* anonymous unions are enabled by default */ +#elif defined (__TASKING__) + #pragma warning restore +#elif defined (__CSMC__) + /* anonymous unions are enabled by default */ +#endif + + +/* =========================================================================================================================== */ +/* ================ Pos/Mask Peripheral Section ================ */ +/* =========================================================================================================================== */ + + +/** @addtogroup PosMask_peripherals + * @{ + */ + + + +/* =========================================================================================================================== */ +/* ================ ADC ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== CFG ========================================================== */ +#define ADC_CFG_CLKSEL_Pos (24UL) /*!< ADC CFG: CLKSEL (Bit 24) */ +#define ADC_CFG_CLKSEL_Msk (0x3000000UL) /*!< ADC CFG: CLKSEL (Bitfield-Mask: 0x03) */ +#define ADC_CFG_TRIGPOL_Pos (19UL) /*!< ADC CFG: TRIGPOL (Bit 19) */ +#define ADC_CFG_TRIGPOL_Msk (0x80000UL) /*!< ADC CFG: TRIGPOL (Bitfield-Mask: 0x01) */ +#define ADC_CFG_TRIGSEL_Pos (16UL) /*!< ADC CFG: TRIGSEL (Bit 16) */ +#define ADC_CFG_TRIGSEL_Msk (0x70000UL) /*!< ADC CFG: TRIGSEL (Bitfield-Mask: 0x07) */ +#define ADC_CFG_DFIFORDEN_Pos (12UL) /*!< ADC CFG: DFIFORDEN (Bit 12) */ +#define ADC_CFG_DFIFORDEN_Msk (0x1000UL) /*!< ADC CFG: DFIFORDEN (Bitfield-Mask: 0x01) */ +#define ADC_CFG_REFSEL_Pos (8UL) /*!< ADC CFG: REFSEL (Bit 8) */ +#define ADC_CFG_REFSEL_Msk (0x300UL) /*!< ADC CFG: REFSEL (Bitfield-Mask: 0x03) */ +#define ADC_CFG_CKMODE_Pos (4UL) /*!< ADC CFG: CKMODE (Bit 4) */ +#define ADC_CFG_CKMODE_Msk (0x10UL) /*!< ADC CFG: CKMODE (Bitfield-Mask: 0x01) */ +#define ADC_CFG_LPMODE_Pos (3UL) /*!< ADC CFG: LPMODE (Bit 3) */ +#define ADC_CFG_LPMODE_Msk (0x8UL) /*!< ADC CFG: LPMODE (Bitfield-Mask: 0x01) */ +#define ADC_CFG_RPTEN_Pos (2UL) /*!< ADC CFG: RPTEN (Bit 2) */ +#define ADC_CFG_RPTEN_Msk (0x4UL) /*!< ADC CFG: RPTEN (Bitfield-Mask: 0x01) */ +#define ADC_CFG_ADCEN_Pos (0UL) /*!< ADC CFG: ADCEN (Bit 0) */ +#define ADC_CFG_ADCEN_Msk (0x1UL) /*!< ADC CFG: ADCEN (Bitfield-Mask: 0x01) */ +/* ========================================================= STAT ========================================================== */ +#define ADC_STAT_PWDSTAT_Pos (0UL) /*!< ADC STAT: PWDSTAT (Bit 0) */ +#define ADC_STAT_PWDSTAT_Msk (0x1UL) /*!< ADC STAT: PWDSTAT (Bitfield-Mask: 0x01) */ +/* ========================================================== SWT ========================================================== */ +#define ADC_SWT_SWT_Pos (0UL) /*!< ADC SWT: SWT (Bit 0) */ +#define ADC_SWT_SWT_Msk (0xffUL) /*!< ADC SWT: SWT (Bitfield-Mask: 0xff) */ +/* ======================================================== SL0CFG ========================================================= */ +#define ADC_SL0CFG_ADSEL0_Pos (24UL) /*!< ADC SL0CFG: ADSEL0 (Bit 24) */ +#define ADC_SL0CFG_ADSEL0_Msk (0x7000000UL) /*!< ADC SL0CFG: ADSEL0 (Bitfield-Mask: 0x07) */ +#define ADC_SL0CFG_PRMODE0_Pos (16UL) /*!< ADC SL0CFG: PRMODE0 (Bit 16) */ +#define ADC_SL0CFG_PRMODE0_Msk (0x30000UL) /*!< ADC SL0CFG: PRMODE0 (Bitfield-Mask: 0x03) */ +#define ADC_SL0CFG_CHSEL0_Pos (8UL) /*!< ADC SL0CFG: CHSEL0 (Bit 8) */ +#define ADC_SL0CFG_CHSEL0_Msk (0xf00UL) /*!< ADC SL0CFG: CHSEL0 (Bitfield-Mask: 0x0f) */ +#define ADC_SL0CFG_WCEN0_Pos (1UL) /*!< ADC SL0CFG: WCEN0 (Bit 1) */ +#define ADC_SL0CFG_WCEN0_Msk (0x2UL) /*!< ADC SL0CFG: WCEN0 (Bitfield-Mask: 0x01) */ +#define ADC_SL0CFG_SLEN0_Pos (0UL) /*!< ADC SL0CFG: SLEN0 (Bit 0) */ +#define ADC_SL0CFG_SLEN0_Msk (0x1UL) /*!< ADC SL0CFG: SLEN0 (Bitfield-Mask: 0x01) */ +/* ======================================================== SL1CFG ========================================================= */ +#define ADC_SL1CFG_ADSEL1_Pos (24UL) /*!< ADC SL1CFG: ADSEL1 (Bit 24) */ +#define ADC_SL1CFG_ADSEL1_Msk (0x7000000UL) /*!< ADC SL1CFG: ADSEL1 (Bitfield-Mask: 0x07) */ +#define ADC_SL1CFG_PRMODE1_Pos (16UL) /*!< ADC SL1CFG: PRMODE1 (Bit 16) */ +#define ADC_SL1CFG_PRMODE1_Msk (0x30000UL) /*!< ADC SL1CFG: PRMODE1 (Bitfield-Mask: 0x03) */ +#define ADC_SL1CFG_CHSEL1_Pos (8UL) /*!< ADC SL1CFG: CHSEL1 (Bit 8) */ +#define ADC_SL1CFG_CHSEL1_Msk (0xf00UL) /*!< ADC SL1CFG: CHSEL1 (Bitfield-Mask: 0x0f) */ +#define ADC_SL1CFG_WCEN1_Pos (1UL) /*!< ADC SL1CFG: WCEN1 (Bit 1) */ +#define ADC_SL1CFG_WCEN1_Msk (0x2UL) /*!< ADC SL1CFG: WCEN1 (Bitfield-Mask: 0x01) */ +#define ADC_SL1CFG_SLEN1_Pos (0UL) /*!< ADC SL1CFG: SLEN1 (Bit 0) */ +#define ADC_SL1CFG_SLEN1_Msk (0x1UL) /*!< ADC SL1CFG: SLEN1 (Bitfield-Mask: 0x01) */ +/* ======================================================== SL2CFG ========================================================= */ +#define ADC_SL2CFG_ADSEL2_Pos (24UL) /*!< ADC SL2CFG: ADSEL2 (Bit 24) */ +#define ADC_SL2CFG_ADSEL2_Msk (0x7000000UL) /*!< ADC SL2CFG: ADSEL2 (Bitfield-Mask: 0x07) */ +#define ADC_SL2CFG_PRMODE2_Pos (16UL) /*!< ADC SL2CFG: PRMODE2 (Bit 16) */ +#define ADC_SL2CFG_PRMODE2_Msk (0x30000UL) /*!< ADC SL2CFG: PRMODE2 (Bitfield-Mask: 0x03) */ +#define ADC_SL2CFG_CHSEL2_Pos (8UL) /*!< ADC SL2CFG: CHSEL2 (Bit 8) */ +#define ADC_SL2CFG_CHSEL2_Msk (0xf00UL) /*!< ADC SL2CFG: CHSEL2 (Bitfield-Mask: 0x0f) */ +#define ADC_SL2CFG_WCEN2_Pos (1UL) /*!< ADC SL2CFG: WCEN2 (Bit 1) */ +#define ADC_SL2CFG_WCEN2_Msk (0x2UL) /*!< ADC SL2CFG: WCEN2 (Bitfield-Mask: 0x01) */ +#define ADC_SL2CFG_SLEN2_Pos (0UL) /*!< ADC SL2CFG: SLEN2 (Bit 0) */ +#define ADC_SL2CFG_SLEN2_Msk (0x1UL) /*!< ADC SL2CFG: SLEN2 (Bitfield-Mask: 0x01) */ +/* ======================================================== SL3CFG ========================================================= */ +#define ADC_SL3CFG_ADSEL3_Pos (24UL) /*!< ADC SL3CFG: ADSEL3 (Bit 24) */ +#define ADC_SL3CFG_ADSEL3_Msk (0x7000000UL) /*!< ADC SL3CFG: ADSEL3 (Bitfield-Mask: 0x07) */ +#define ADC_SL3CFG_PRMODE3_Pos (16UL) /*!< ADC SL3CFG: PRMODE3 (Bit 16) */ +#define ADC_SL3CFG_PRMODE3_Msk (0x30000UL) /*!< ADC SL3CFG: PRMODE3 (Bitfield-Mask: 0x03) */ +#define ADC_SL3CFG_CHSEL3_Pos (8UL) /*!< ADC SL3CFG: CHSEL3 (Bit 8) */ +#define ADC_SL3CFG_CHSEL3_Msk (0xf00UL) /*!< ADC SL3CFG: CHSEL3 (Bitfield-Mask: 0x0f) */ +#define ADC_SL3CFG_WCEN3_Pos (1UL) /*!< ADC SL3CFG: WCEN3 (Bit 1) */ +#define ADC_SL3CFG_WCEN3_Msk (0x2UL) /*!< ADC SL3CFG: WCEN3 (Bitfield-Mask: 0x01) */ +#define ADC_SL3CFG_SLEN3_Pos (0UL) /*!< ADC SL3CFG: SLEN3 (Bit 0) */ +#define ADC_SL3CFG_SLEN3_Msk (0x1UL) /*!< ADC SL3CFG: SLEN3 (Bitfield-Mask: 0x01) */ +/* ======================================================== SL4CFG ========================================================= */ +#define ADC_SL4CFG_ADSEL4_Pos (24UL) /*!< ADC SL4CFG: ADSEL4 (Bit 24) */ +#define ADC_SL4CFG_ADSEL4_Msk (0x7000000UL) /*!< ADC SL4CFG: ADSEL4 (Bitfield-Mask: 0x07) */ +#define ADC_SL4CFG_PRMODE4_Pos (16UL) /*!< ADC SL4CFG: PRMODE4 (Bit 16) */ +#define ADC_SL4CFG_PRMODE4_Msk (0x30000UL) /*!< ADC SL4CFG: PRMODE4 (Bitfield-Mask: 0x03) */ +#define ADC_SL4CFG_CHSEL4_Pos (8UL) /*!< ADC SL4CFG: CHSEL4 (Bit 8) */ +#define ADC_SL4CFG_CHSEL4_Msk (0xf00UL) /*!< ADC SL4CFG: CHSEL4 (Bitfield-Mask: 0x0f) */ +#define ADC_SL4CFG_WCEN4_Pos (1UL) /*!< ADC SL4CFG: WCEN4 (Bit 1) */ +#define ADC_SL4CFG_WCEN4_Msk (0x2UL) /*!< ADC SL4CFG: WCEN4 (Bitfield-Mask: 0x01) */ +#define ADC_SL4CFG_SLEN4_Pos (0UL) /*!< ADC SL4CFG: SLEN4 (Bit 0) */ +#define ADC_SL4CFG_SLEN4_Msk (0x1UL) /*!< ADC SL4CFG: SLEN4 (Bitfield-Mask: 0x01) */ +/* ======================================================== SL5CFG ========================================================= */ +#define ADC_SL5CFG_ADSEL5_Pos (24UL) /*!< ADC SL5CFG: ADSEL5 (Bit 24) */ +#define ADC_SL5CFG_ADSEL5_Msk (0x7000000UL) /*!< ADC SL5CFG: ADSEL5 (Bitfield-Mask: 0x07) */ +#define ADC_SL5CFG_PRMODE5_Pos (16UL) /*!< ADC SL5CFG: PRMODE5 (Bit 16) */ +#define ADC_SL5CFG_PRMODE5_Msk (0x30000UL) /*!< ADC SL5CFG: PRMODE5 (Bitfield-Mask: 0x03) */ +#define ADC_SL5CFG_CHSEL5_Pos (8UL) /*!< ADC SL5CFG: CHSEL5 (Bit 8) */ +#define ADC_SL5CFG_CHSEL5_Msk (0xf00UL) /*!< ADC SL5CFG: CHSEL5 (Bitfield-Mask: 0x0f) */ +#define ADC_SL5CFG_WCEN5_Pos (1UL) /*!< ADC SL5CFG: WCEN5 (Bit 1) */ +#define ADC_SL5CFG_WCEN5_Msk (0x2UL) /*!< ADC SL5CFG: WCEN5 (Bitfield-Mask: 0x01) */ +#define ADC_SL5CFG_SLEN5_Pos (0UL) /*!< ADC SL5CFG: SLEN5 (Bit 0) */ +#define ADC_SL5CFG_SLEN5_Msk (0x1UL) /*!< ADC SL5CFG: SLEN5 (Bitfield-Mask: 0x01) */ +/* ======================================================== SL6CFG ========================================================= */ +#define ADC_SL6CFG_ADSEL6_Pos (24UL) /*!< ADC SL6CFG: ADSEL6 (Bit 24) */ +#define ADC_SL6CFG_ADSEL6_Msk (0x7000000UL) /*!< ADC SL6CFG: ADSEL6 (Bitfield-Mask: 0x07) */ +#define ADC_SL6CFG_PRMODE6_Pos (16UL) /*!< ADC SL6CFG: PRMODE6 (Bit 16) */ +#define ADC_SL6CFG_PRMODE6_Msk (0x30000UL) /*!< ADC SL6CFG: PRMODE6 (Bitfield-Mask: 0x03) */ +#define ADC_SL6CFG_CHSEL6_Pos (8UL) /*!< ADC SL6CFG: CHSEL6 (Bit 8) */ +#define ADC_SL6CFG_CHSEL6_Msk (0xf00UL) /*!< ADC SL6CFG: CHSEL6 (Bitfield-Mask: 0x0f) */ +#define ADC_SL6CFG_WCEN6_Pos (1UL) /*!< ADC SL6CFG: WCEN6 (Bit 1) */ +#define ADC_SL6CFG_WCEN6_Msk (0x2UL) /*!< ADC SL6CFG: WCEN6 (Bitfield-Mask: 0x01) */ +#define ADC_SL6CFG_SLEN6_Pos (0UL) /*!< ADC SL6CFG: SLEN6 (Bit 0) */ +#define ADC_SL6CFG_SLEN6_Msk (0x1UL) /*!< ADC SL6CFG: SLEN6 (Bitfield-Mask: 0x01) */ +/* ======================================================== SL7CFG ========================================================= */ +#define ADC_SL7CFG_ADSEL7_Pos (24UL) /*!< ADC SL7CFG: ADSEL7 (Bit 24) */ +#define ADC_SL7CFG_ADSEL7_Msk (0x7000000UL) /*!< ADC SL7CFG: ADSEL7 (Bitfield-Mask: 0x07) */ +#define ADC_SL7CFG_PRMODE7_Pos (16UL) /*!< ADC SL7CFG: PRMODE7 (Bit 16) */ +#define ADC_SL7CFG_PRMODE7_Msk (0x30000UL) /*!< ADC SL7CFG: PRMODE7 (Bitfield-Mask: 0x03) */ +#define ADC_SL7CFG_CHSEL7_Pos (8UL) /*!< ADC SL7CFG: CHSEL7 (Bit 8) */ +#define ADC_SL7CFG_CHSEL7_Msk (0xf00UL) /*!< ADC SL7CFG: CHSEL7 (Bitfield-Mask: 0x0f) */ +#define ADC_SL7CFG_WCEN7_Pos (1UL) /*!< ADC SL7CFG: WCEN7 (Bit 1) */ +#define ADC_SL7CFG_WCEN7_Msk (0x2UL) /*!< ADC SL7CFG: WCEN7 (Bitfield-Mask: 0x01) */ +#define ADC_SL7CFG_SLEN7_Pos (0UL) /*!< ADC SL7CFG: SLEN7 (Bit 0) */ +#define ADC_SL7CFG_SLEN7_Msk (0x1UL) /*!< ADC SL7CFG: SLEN7 (Bitfield-Mask: 0x01) */ +/* ========================================================= WULIM ========================================================= */ +#define ADC_WULIM_ULIM_Pos (0UL) /*!< ADC WULIM: ULIM (Bit 0) */ +#define ADC_WULIM_ULIM_Msk (0xfffffUL) /*!< ADC WULIM: ULIM (Bitfield-Mask: 0xfffff) */ +/* ========================================================= WLLIM ========================================================= */ +#define ADC_WLLIM_LLIM_Pos (0UL) /*!< ADC WLLIM: LLIM (Bit 0) */ +#define ADC_WLLIM_LLIM_Msk (0xfffffUL) /*!< ADC WLLIM: LLIM (Bitfield-Mask: 0xfffff) */ +/* ======================================================== SCWLIM ========================================================= */ +#define ADC_SCWLIM_SCWLIMEN_Pos (0UL) /*!< ADC SCWLIM: SCWLIMEN (Bit 0) */ +#define ADC_SCWLIM_SCWLIMEN_Msk (0x1UL) /*!< ADC SCWLIM: SCWLIMEN (Bitfield-Mask: 0x01) */ +/* ========================================================= FIFO ========================================================== */ +#define ADC_FIFO_RSVD_Pos (31UL) /*!< ADC FIFO: RSVD (Bit 31) */ +#define ADC_FIFO_RSVD_Msk (0x80000000UL) /*!< ADC FIFO: RSVD (Bitfield-Mask: 0x01) */ +#define ADC_FIFO_SLOTNUM_Pos (28UL) /*!< ADC FIFO: SLOTNUM (Bit 28) */ +#define ADC_FIFO_SLOTNUM_Msk (0x70000000UL) /*!< ADC FIFO: SLOTNUM (Bitfield-Mask: 0x07) */ +#define ADC_FIFO_COUNT_Pos (20UL) /*!< ADC FIFO: COUNT (Bit 20) */ +#define ADC_FIFO_COUNT_Msk (0xff00000UL) /*!< ADC FIFO: COUNT (Bitfield-Mask: 0xff) */ +#define ADC_FIFO_DATA_Pos (0UL) /*!< ADC FIFO: DATA (Bit 0) */ +#define ADC_FIFO_DATA_Msk (0xfffffUL) /*!< ADC FIFO: DATA (Bitfield-Mask: 0xfffff) */ +/* ======================================================== FIFOPR ========================================================= */ +#define ADC_FIFOPR_RSVDPR_Pos (31UL) /*!< ADC FIFOPR: RSVDPR (Bit 31) */ +#define ADC_FIFOPR_RSVDPR_Msk (0x80000000UL) /*!< ADC FIFOPR: RSVDPR (Bitfield-Mask: 0x01) */ +#define ADC_FIFOPR_SLOTNUMPR_Pos (28UL) /*!< ADC FIFOPR: SLOTNUMPR (Bit 28) */ +#define ADC_FIFOPR_SLOTNUMPR_Msk (0x70000000UL) /*!< ADC FIFOPR: SLOTNUMPR (Bitfield-Mask: 0x07) */ +#define ADC_FIFOPR_COUNT_Pos (20UL) /*!< ADC FIFOPR: COUNT (Bit 20) */ +#define ADC_FIFOPR_COUNT_Msk (0xff00000UL) /*!< ADC FIFOPR: COUNT (Bitfield-Mask: 0xff) */ +#define ADC_FIFOPR_DATA_Pos (0UL) /*!< ADC FIFOPR: DATA (Bit 0) */ +#define ADC_FIFOPR_DATA_Msk (0xfffffUL) /*!< ADC FIFOPR: DATA (Bitfield-Mask: 0xfffff) */ +/* ========================================================= INTEN ========================================================= */ +#define ADC_INTEN_DERR_Pos (7UL) /*!< ADC INTEN: DERR (Bit 7) */ +#define ADC_INTEN_DERR_Msk (0x80UL) /*!< ADC INTEN: DERR (Bitfield-Mask: 0x01) */ +#define ADC_INTEN_DCMP_Pos (6UL) /*!< ADC INTEN: DCMP (Bit 6) */ +#define ADC_INTEN_DCMP_Msk (0x40UL) /*!< ADC INTEN: DCMP (Bitfield-Mask: 0x01) */ +#define ADC_INTEN_WCINC_Pos (5UL) /*!< ADC INTEN: WCINC (Bit 5) */ +#define ADC_INTEN_WCINC_Msk (0x20UL) /*!< ADC INTEN: WCINC (Bitfield-Mask: 0x01) */ +#define ADC_INTEN_WCEXC_Pos (4UL) /*!< ADC INTEN: WCEXC (Bit 4) */ +#define ADC_INTEN_WCEXC_Msk (0x10UL) /*!< ADC INTEN: WCEXC (Bitfield-Mask: 0x01) */ +#define ADC_INTEN_FIFOOVR2_Pos (3UL) /*!< ADC INTEN: FIFOOVR2 (Bit 3) */ +#define ADC_INTEN_FIFOOVR2_Msk (0x8UL) /*!< ADC INTEN: FIFOOVR2 (Bitfield-Mask: 0x01) */ +#define ADC_INTEN_FIFOOVR1_Pos (2UL) /*!< ADC INTEN: FIFOOVR1 (Bit 2) */ +#define ADC_INTEN_FIFOOVR1_Msk (0x4UL) /*!< ADC INTEN: FIFOOVR1 (Bitfield-Mask: 0x01) */ +#define ADC_INTEN_SCNCMP_Pos (1UL) /*!< ADC INTEN: SCNCMP (Bit 1) */ +#define ADC_INTEN_SCNCMP_Msk (0x2UL) /*!< ADC INTEN: SCNCMP (Bitfield-Mask: 0x01) */ +#define ADC_INTEN_CNVCMP_Pos (0UL) /*!< ADC INTEN: CNVCMP (Bit 0) */ +#define ADC_INTEN_CNVCMP_Msk (0x1UL) /*!< ADC INTEN: CNVCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define ADC_INTSTAT_DERR_Pos (7UL) /*!< ADC INTSTAT: DERR (Bit 7) */ +#define ADC_INTSTAT_DERR_Msk (0x80UL) /*!< ADC INTSTAT: DERR (Bitfield-Mask: 0x01) */ +#define ADC_INTSTAT_DCMP_Pos (6UL) /*!< ADC INTSTAT: DCMP (Bit 6) */ +#define ADC_INTSTAT_DCMP_Msk (0x40UL) /*!< ADC INTSTAT: DCMP (Bitfield-Mask: 0x01) */ +#define ADC_INTSTAT_WCINC_Pos (5UL) /*!< ADC INTSTAT: WCINC (Bit 5) */ +#define ADC_INTSTAT_WCINC_Msk (0x20UL) /*!< ADC INTSTAT: WCINC (Bitfield-Mask: 0x01) */ +#define ADC_INTSTAT_WCEXC_Pos (4UL) /*!< ADC INTSTAT: WCEXC (Bit 4) */ +#define ADC_INTSTAT_WCEXC_Msk (0x10UL) /*!< ADC INTSTAT: WCEXC (Bitfield-Mask: 0x01) */ +#define ADC_INTSTAT_FIFOOVR2_Pos (3UL) /*!< ADC INTSTAT: FIFOOVR2 (Bit 3) */ +#define ADC_INTSTAT_FIFOOVR2_Msk (0x8UL) /*!< ADC INTSTAT: FIFOOVR2 (Bitfield-Mask: 0x01) */ +#define ADC_INTSTAT_FIFOOVR1_Pos (2UL) /*!< ADC INTSTAT: FIFOOVR1 (Bit 2) */ +#define ADC_INTSTAT_FIFOOVR1_Msk (0x4UL) /*!< ADC INTSTAT: FIFOOVR1 (Bitfield-Mask: 0x01) */ +#define ADC_INTSTAT_SCNCMP_Pos (1UL) /*!< ADC INTSTAT: SCNCMP (Bit 1) */ +#define ADC_INTSTAT_SCNCMP_Msk (0x2UL) /*!< ADC INTSTAT: SCNCMP (Bitfield-Mask: 0x01) */ +#define ADC_INTSTAT_CNVCMP_Pos (0UL) /*!< ADC INTSTAT: CNVCMP (Bit 0) */ +#define ADC_INTSTAT_CNVCMP_Msk (0x1UL) /*!< ADC INTSTAT: CNVCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define ADC_INTCLR_DERR_Pos (7UL) /*!< ADC INTCLR: DERR (Bit 7) */ +#define ADC_INTCLR_DERR_Msk (0x80UL) /*!< ADC INTCLR: DERR (Bitfield-Mask: 0x01) */ +#define ADC_INTCLR_DCMP_Pos (6UL) /*!< ADC INTCLR: DCMP (Bit 6) */ +#define ADC_INTCLR_DCMP_Msk (0x40UL) /*!< ADC INTCLR: DCMP (Bitfield-Mask: 0x01) */ +#define ADC_INTCLR_WCINC_Pos (5UL) /*!< ADC INTCLR: WCINC (Bit 5) */ +#define ADC_INTCLR_WCINC_Msk (0x20UL) /*!< ADC INTCLR: WCINC (Bitfield-Mask: 0x01) */ +#define ADC_INTCLR_WCEXC_Pos (4UL) /*!< ADC INTCLR: WCEXC (Bit 4) */ +#define ADC_INTCLR_WCEXC_Msk (0x10UL) /*!< ADC INTCLR: WCEXC (Bitfield-Mask: 0x01) */ +#define ADC_INTCLR_FIFOOVR2_Pos (3UL) /*!< ADC INTCLR: FIFOOVR2 (Bit 3) */ +#define ADC_INTCLR_FIFOOVR2_Msk (0x8UL) /*!< ADC INTCLR: FIFOOVR2 (Bitfield-Mask: 0x01) */ +#define ADC_INTCLR_FIFOOVR1_Pos (2UL) /*!< ADC INTCLR: FIFOOVR1 (Bit 2) */ +#define ADC_INTCLR_FIFOOVR1_Msk (0x4UL) /*!< ADC INTCLR: FIFOOVR1 (Bitfield-Mask: 0x01) */ +#define ADC_INTCLR_SCNCMP_Pos (1UL) /*!< ADC INTCLR: SCNCMP (Bit 1) */ +#define ADC_INTCLR_SCNCMP_Msk (0x2UL) /*!< ADC INTCLR: SCNCMP (Bitfield-Mask: 0x01) */ +#define ADC_INTCLR_CNVCMP_Pos (0UL) /*!< ADC INTCLR: CNVCMP (Bit 0) */ +#define ADC_INTCLR_CNVCMP_Msk (0x1UL) /*!< ADC INTCLR: CNVCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define ADC_INTSET_DERR_Pos (7UL) /*!< ADC INTSET: DERR (Bit 7) */ +#define ADC_INTSET_DERR_Msk (0x80UL) /*!< ADC INTSET: DERR (Bitfield-Mask: 0x01) */ +#define ADC_INTSET_DCMP_Pos (6UL) /*!< ADC INTSET: DCMP (Bit 6) */ +#define ADC_INTSET_DCMP_Msk (0x40UL) /*!< ADC INTSET: DCMP (Bitfield-Mask: 0x01) */ +#define ADC_INTSET_WCINC_Pos (5UL) /*!< ADC INTSET: WCINC (Bit 5) */ +#define ADC_INTSET_WCINC_Msk (0x20UL) /*!< ADC INTSET: WCINC (Bitfield-Mask: 0x01) */ +#define ADC_INTSET_WCEXC_Pos (4UL) /*!< ADC INTSET: WCEXC (Bit 4) */ +#define ADC_INTSET_WCEXC_Msk (0x10UL) /*!< ADC INTSET: WCEXC (Bitfield-Mask: 0x01) */ +#define ADC_INTSET_FIFOOVR2_Pos (3UL) /*!< ADC INTSET: FIFOOVR2 (Bit 3) */ +#define ADC_INTSET_FIFOOVR2_Msk (0x8UL) /*!< ADC INTSET: FIFOOVR2 (Bitfield-Mask: 0x01) */ +#define ADC_INTSET_FIFOOVR1_Pos (2UL) /*!< ADC INTSET: FIFOOVR1 (Bit 2) */ +#define ADC_INTSET_FIFOOVR1_Msk (0x4UL) /*!< ADC INTSET: FIFOOVR1 (Bitfield-Mask: 0x01) */ +#define ADC_INTSET_SCNCMP_Pos (1UL) /*!< ADC INTSET: SCNCMP (Bit 1) */ +#define ADC_INTSET_SCNCMP_Msk (0x2UL) /*!< ADC INTSET: SCNCMP (Bitfield-Mask: 0x01) */ +#define ADC_INTSET_CNVCMP_Pos (0UL) /*!< ADC INTSET: CNVCMP (Bit 0) */ +#define ADC_INTSET_CNVCMP_Msk (0x1UL) /*!< ADC INTSET: CNVCMP (Bitfield-Mask: 0x01) */ +/* ======================================================= DMATRIGEN ======================================================= */ +#define ADC_DMATRIGEN_DFIFOFULL_Pos (1UL) /*!< ADC DMATRIGEN: DFIFOFULL (Bit 1) */ +#define ADC_DMATRIGEN_DFIFOFULL_Msk (0x2UL) /*!< ADC DMATRIGEN: DFIFOFULL (Bitfield-Mask: 0x01) */ +#define ADC_DMATRIGEN_DFIFO75_Pos (0UL) /*!< ADC DMATRIGEN: DFIFO75 (Bit 0) */ +#define ADC_DMATRIGEN_DFIFO75_Msk (0x1UL) /*!< ADC DMATRIGEN: DFIFO75 (Bitfield-Mask: 0x01) */ +/* ====================================================== DMATRIGSTAT ====================================================== */ +#define ADC_DMATRIGSTAT_DFULLSTAT_Pos (1UL) /*!< ADC DMATRIGSTAT: DFULLSTAT (Bit 1) */ +#define ADC_DMATRIGSTAT_DFULLSTAT_Msk (0x2UL) /*!< ADC DMATRIGSTAT: DFULLSTAT (Bitfield-Mask: 0x01) */ +#define ADC_DMATRIGSTAT_D75STAT_Pos (0UL) /*!< ADC DMATRIGSTAT: D75STAT (Bit 0) */ +#define ADC_DMATRIGSTAT_D75STAT_Msk (0x1UL) /*!< ADC DMATRIGSTAT: D75STAT (Bitfield-Mask: 0x01) */ +/* ======================================================== DMACFG ========================================================= */ +#define ADC_DMACFG_DPWROFF_Pos (18UL) /*!< ADC DMACFG: DPWROFF (Bit 18) */ +#define ADC_DMACFG_DPWROFF_Msk (0x40000UL) /*!< ADC DMACFG: DPWROFF (Bitfield-Mask: 0x01) */ +#define ADC_DMACFG_DMAMSK_Pos (17UL) /*!< ADC DMACFG: DMAMSK (Bit 17) */ +#define ADC_DMACFG_DMAMSK_Msk (0x20000UL) /*!< ADC DMACFG: DMAMSK (Bitfield-Mask: 0x01) */ +#define ADC_DMACFG_DMAHONSTAT_Pos (16UL) /*!< ADC DMACFG: DMAHONSTAT (Bit 16) */ +#define ADC_DMACFG_DMAHONSTAT_Msk (0x10000UL) /*!< ADC DMACFG: DMAHONSTAT (Bitfield-Mask: 0x01) */ +#define ADC_DMACFG_DMADYNPRI_Pos (9UL) /*!< ADC DMACFG: DMADYNPRI (Bit 9) */ +#define ADC_DMACFG_DMADYNPRI_Msk (0x200UL) /*!< ADC DMACFG: DMADYNPRI (Bitfield-Mask: 0x01) */ +#define ADC_DMACFG_DMAPRI_Pos (8UL) /*!< ADC DMACFG: DMAPRI (Bit 8) */ +#define ADC_DMACFG_DMAPRI_Msk (0x100UL) /*!< ADC DMACFG: DMAPRI (Bitfield-Mask: 0x01) */ +#define ADC_DMACFG_DMADIR_Pos (2UL) /*!< ADC DMACFG: DMADIR (Bit 2) */ +#define ADC_DMACFG_DMADIR_Msk (0x4UL) /*!< ADC DMACFG: DMADIR (Bitfield-Mask: 0x01) */ +#define ADC_DMACFG_DMAEN_Pos (0UL) /*!< ADC DMACFG: DMAEN (Bit 0) */ +#define ADC_DMACFG_DMAEN_Msk (0x1UL) /*!< ADC DMACFG: DMAEN (Bitfield-Mask: 0x01) */ +/* ====================================================== DMATOTCOUNT ====================================================== */ +#define ADC_DMATOTCOUNT_TOTCOUNT_Pos (2UL) /*!< ADC DMATOTCOUNT: TOTCOUNT (Bit 2) */ +#define ADC_DMATOTCOUNT_TOTCOUNT_Msk (0x3fffcUL) /*!< ADC DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xffff) */ +/* ====================================================== DMATARGADDR ====================================================== */ +#define ADC_DMATARGADDR_UTARGADDR_Pos (19UL) /*!< ADC DMATARGADDR: UTARGADDR (Bit 19) */ +#define ADC_DMATARGADDR_UTARGADDR_Msk (0xfff80000UL) /*!< ADC DMATARGADDR: UTARGADDR (Bitfield-Mask: 0x1fff) */ +#define ADC_DMATARGADDR_LTARGADDR_Pos (0UL) /*!< ADC DMATARGADDR: LTARGADDR (Bit 0) */ +#define ADC_DMATARGADDR_LTARGADDR_Msk (0x7ffffUL) /*!< ADC DMATARGADDR: LTARGADDR (Bitfield-Mask: 0x7ffff) */ +/* ======================================================== DMASTAT ======================================================== */ +#define ADC_DMASTAT_DMAERR_Pos (2UL) /*!< ADC DMASTAT: DMAERR (Bit 2) */ +#define ADC_DMASTAT_DMAERR_Msk (0x4UL) /*!< ADC DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ +#define ADC_DMASTAT_DMACPL_Pos (1UL) /*!< ADC DMASTAT: DMACPL (Bit 1) */ +#define ADC_DMASTAT_DMACPL_Msk (0x2UL) /*!< ADC DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ +#define ADC_DMASTAT_DMATIP_Pos (0UL) /*!< ADC DMASTAT: DMATIP (Bit 0) */ +#define ADC_DMASTAT_DMATIP_Msk (0x1UL) /*!< ADC DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ APBDMA ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== BBVALUE ======================================================== */ +#define APBDMA_BBVALUE_PIN_Pos (16UL) /*!< APBDMA BBVALUE: PIN (Bit 16) */ +#define APBDMA_BBVALUE_PIN_Msk (0xff0000UL) /*!< APBDMA BBVALUE: PIN (Bitfield-Mask: 0xff) */ +#define APBDMA_BBVALUE_DATAOUT_Pos (0UL) /*!< APBDMA BBVALUE: DATAOUT (Bit 0) */ +#define APBDMA_BBVALUE_DATAOUT_Msk (0xffUL) /*!< APBDMA BBVALUE: DATAOUT (Bitfield-Mask: 0xff) */ +/* ====================================================== BBSETCLEAR ======================================================= */ +#define APBDMA_BBSETCLEAR_CLEAR_Pos (16UL) /*!< APBDMA BBSETCLEAR: CLEAR (Bit 16) */ +#define APBDMA_BBSETCLEAR_CLEAR_Msk (0xff0000UL) /*!< APBDMA BBSETCLEAR: CLEAR (Bitfield-Mask: 0xff) */ +#define APBDMA_BBSETCLEAR_SET_Pos (0UL) /*!< APBDMA BBSETCLEAR: SET (Bit 0) */ +#define APBDMA_BBSETCLEAR_SET_Msk (0xffUL) /*!< APBDMA BBSETCLEAR: SET (Bitfield-Mask: 0xff) */ +/* ======================================================== BBINPUT ======================================================== */ +#define APBDMA_BBINPUT_DATAIN_Pos (0UL) /*!< APBDMA BBINPUT: DATAIN (Bit 0) */ +#define APBDMA_BBINPUT_DATAIN_Msk (0xffUL) /*!< APBDMA BBINPUT: DATAIN (Bitfield-Mask: 0xff) */ +/* ======================================================= DEBUGDATA ======================================================= */ +#define APBDMA_DEBUGDATA_DEBUGDATA_Pos (0UL) /*!< APBDMA DEBUGDATA: DEBUGDATA (Bit 0) */ +#define APBDMA_DEBUGDATA_DEBUGDATA_Msk (0xffffffffUL) /*!< APBDMA DEBUGDATA: DEBUGDATA (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= DEBUG ========================================================= */ +#define APBDMA_DEBUG_DEBUGEN_Pos (0UL) /*!< APBDMA DEBUG: DEBUGEN (Bit 0) */ +#define APBDMA_DEBUG_DEBUGEN_Msk (0xfUL) /*!< APBDMA DEBUG: DEBUGEN (Bitfield-Mask: 0x0f) */ + + +/* =========================================================================================================================== */ +/* ================ BLEIF ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= FIFO ========================================================== */ +#define BLEIF_FIFO_FIFO_Pos (0UL) /*!< BLEIF FIFO: FIFO (Bit 0) */ +#define BLEIF_FIFO_FIFO_Msk (0xffffffffUL) /*!< BLEIF FIFO: FIFO (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== FIFOPTR ======================================================== */ +#define BLEIF_FIFOPTR_FIFO1REM_Pos (24UL) /*!< BLEIF FIFOPTR: FIFO1REM (Bit 24) */ +#define BLEIF_FIFOPTR_FIFO1REM_Msk (0xff000000UL) /*!< BLEIF FIFOPTR: FIFO1REM (Bitfield-Mask: 0xff) */ +#define BLEIF_FIFOPTR_FIFO1SIZ_Pos (16UL) /*!< BLEIF FIFOPTR: FIFO1SIZ (Bit 16) */ +#define BLEIF_FIFOPTR_FIFO1SIZ_Msk (0xff0000UL) /*!< BLEIF FIFOPTR: FIFO1SIZ (Bitfield-Mask: 0xff) */ +#define BLEIF_FIFOPTR_FIFO0REM_Pos (8UL) /*!< BLEIF FIFOPTR: FIFO0REM (Bit 8) */ +#define BLEIF_FIFOPTR_FIFO0REM_Msk (0xff00UL) /*!< BLEIF FIFOPTR: FIFO0REM (Bitfield-Mask: 0xff) */ +#define BLEIF_FIFOPTR_FIFO0SIZ_Pos (0UL) /*!< BLEIF FIFOPTR: FIFO0SIZ (Bit 0) */ +#define BLEIF_FIFOPTR_FIFO0SIZ_Msk (0xffUL) /*!< BLEIF FIFOPTR: FIFO0SIZ (Bitfield-Mask: 0xff) */ +/* ======================================================== FIFOTHR ======================================================== */ +#define BLEIF_FIFOTHR_FIFOWTHR_Pos (8UL) /*!< BLEIF FIFOTHR: FIFOWTHR (Bit 8) */ +#define BLEIF_FIFOTHR_FIFOWTHR_Msk (0x3f00UL) /*!< BLEIF FIFOTHR: FIFOWTHR (Bitfield-Mask: 0x3f) */ +#define BLEIF_FIFOTHR_FIFORTHR_Pos (0UL) /*!< BLEIF FIFOTHR: FIFORTHR (Bit 0) */ +#define BLEIF_FIFOTHR_FIFORTHR_Msk (0x3fUL) /*!< BLEIF FIFOTHR: FIFORTHR (Bitfield-Mask: 0x3f) */ +/* ======================================================== FIFOPOP ======================================================== */ +#define BLEIF_FIFOPOP_FIFODOUT_Pos (0UL) /*!< BLEIF FIFOPOP: FIFODOUT (Bit 0) */ +#define BLEIF_FIFOPOP_FIFODOUT_Msk (0xffffffffUL) /*!< BLEIF FIFOPOP: FIFODOUT (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= FIFOPUSH ======================================================== */ +#define BLEIF_FIFOPUSH_FIFODIN_Pos (0UL) /*!< BLEIF FIFOPUSH: FIFODIN (Bit 0) */ +#define BLEIF_FIFOPUSH_FIFODIN_Msk (0xffffffffUL) /*!< BLEIF FIFOPUSH: FIFODIN (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= FIFOCTRL ======================================================== */ +#define BLEIF_FIFOCTRL_FIFORSTN_Pos (1UL) /*!< BLEIF FIFOCTRL: FIFORSTN (Bit 1) */ +#define BLEIF_FIFOCTRL_FIFORSTN_Msk (0x2UL) /*!< BLEIF FIFOCTRL: FIFORSTN (Bitfield-Mask: 0x01) */ +#define BLEIF_FIFOCTRL_POPWR_Pos (0UL) /*!< BLEIF FIFOCTRL: POPWR (Bit 0) */ +#define BLEIF_FIFOCTRL_POPWR_Msk (0x1UL) /*!< BLEIF FIFOCTRL: POPWR (Bitfield-Mask: 0x01) */ +/* ======================================================== FIFOLOC ======================================================== */ +#define BLEIF_FIFOLOC_FIFORPTR_Pos (8UL) /*!< BLEIF FIFOLOC: FIFORPTR (Bit 8) */ +#define BLEIF_FIFOLOC_FIFORPTR_Msk (0xf00UL) /*!< BLEIF FIFOLOC: FIFORPTR (Bitfield-Mask: 0x0f) */ +#define BLEIF_FIFOLOC_FIFOWPTR_Pos (0UL) /*!< BLEIF FIFOLOC: FIFOWPTR (Bit 0) */ +#define BLEIF_FIFOLOC_FIFOWPTR_Msk (0xfUL) /*!< BLEIF FIFOLOC: FIFOWPTR (Bitfield-Mask: 0x0f) */ +/* ======================================================== CLKCFG ========================================================= */ +#define BLEIF_CLKCFG_DIV3_Pos (12UL) /*!< BLEIF CLKCFG: DIV3 (Bit 12) */ +#define BLEIF_CLKCFG_DIV3_Msk (0x1000UL) /*!< BLEIF CLKCFG: DIV3 (Bitfield-Mask: 0x01) */ +#define BLEIF_CLKCFG_CLK32KEN_Pos (11UL) /*!< BLEIF CLKCFG: CLK32KEN (Bit 11) */ +#define BLEIF_CLKCFG_CLK32KEN_Msk (0x800UL) /*!< BLEIF CLKCFG: CLK32KEN (Bitfield-Mask: 0x01) */ +#define BLEIF_CLKCFG_FSEL_Pos (8UL) /*!< BLEIF CLKCFG: FSEL (Bit 8) */ +#define BLEIF_CLKCFG_FSEL_Msk (0x700UL) /*!< BLEIF CLKCFG: FSEL (Bitfield-Mask: 0x07) */ +#define BLEIF_CLKCFG_IOCLKEN_Pos (0UL) /*!< BLEIF CLKCFG: IOCLKEN (Bit 0) */ +#define BLEIF_CLKCFG_IOCLKEN_Msk (0x1UL) /*!< BLEIF CLKCFG: IOCLKEN (Bitfield-Mask: 0x01) */ +/* ========================================================== CMD ========================================================== */ +#define BLEIF_CMD_OFFSETLO_Pos (24UL) /*!< BLEIF CMD: OFFSETLO (Bit 24) */ +#define BLEIF_CMD_OFFSETLO_Msk (0xff000000UL) /*!< BLEIF CMD: OFFSETLO (Bitfield-Mask: 0xff) */ +#define BLEIF_CMD_CMDSEL_Pos (20UL) /*!< BLEIF CMD: CMDSEL (Bit 20) */ +#define BLEIF_CMD_CMDSEL_Msk (0x300000UL) /*!< BLEIF CMD: CMDSEL (Bitfield-Mask: 0x03) */ +#define BLEIF_CMD_TSIZE_Pos (8UL) /*!< BLEIF CMD: TSIZE (Bit 8) */ +#define BLEIF_CMD_TSIZE_Msk (0xfff00UL) /*!< BLEIF CMD: TSIZE (Bitfield-Mask: 0xfff) */ +#define BLEIF_CMD_CONT_Pos (7UL) /*!< BLEIF CMD: CONT (Bit 7) */ +#define BLEIF_CMD_CONT_Msk (0x80UL) /*!< BLEIF CMD: CONT (Bitfield-Mask: 0x01) */ +#define BLEIF_CMD_OFFSETCNT_Pos (5UL) /*!< BLEIF CMD: OFFSETCNT (Bit 5) */ +#define BLEIF_CMD_OFFSETCNT_Msk (0x60UL) /*!< BLEIF CMD: OFFSETCNT (Bitfield-Mask: 0x03) */ +#define BLEIF_CMD_CMD_Pos (0UL) /*!< BLEIF CMD: CMD (Bit 0) */ +#define BLEIF_CMD_CMD_Msk (0x1fUL) /*!< BLEIF CMD: CMD (Bitfield-Mask: 0x1f) */ +/* ======================================================== CMDRPT ========================================================= */ +#define BLEIF_CMDRPT_CMDRPT_Pos (0UL) /*!< BLEIF CMDRPT: CMDRPT (Bit 0) */ +#define BLEIF_CMDRPT_CMDRPT_Msk (0x1fUL) /*!< BLEIF CMDRPT: CMDRPT (Bitfield-Mask: 0x1f) */ +/* ======================================================= OFFSETHI ======================================================== */ +#define BLEIF_OFFSETHI_OFFSETHI_Pos (0UL) /*!< BLEIF OFFSETHI: OFFSETHI (Bit 0) */ +#define BLEIF_OFFSETHI_OFFSETHI_Msk (0xffffUL) /*!< BLEIF OFFSETHI: OFFSETHI (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMDSTAT ======================================================== */ +#define BLEIF_CMDSTAT_CTSIZE_Pos (8UL) /*!< BLEIF CMDSTAT: CTSIZE (Bit 8) */ +#define BLEIF_CMDSTAT_CTSIZE_Msk (0xfff00UL) /*!< BLEIF CMDSTAT: CTSIZE (Bitfield-Mask: 0xfff) */ +#define BLEIF_CMDSTAT_CMDSTAT_Pos (5UL) /*!< BLEIF CMDSTAT: CMDSTAT (Bit 5) */ +#define BLEIF_CMDSTAT_CMDSTAT_Msk (0xe0UL) /*!< BLEIF CMDSTAT: CMDSTAT (Bitfield-Mask: 0x07) */ +#define BLEIF_CMDSTAT_CCMD_Pos (0UL) /*!< BLEIF CMDSTAT: CCMD (Bit 0) */ +#define BLEIF_CMDSTAT_CCMD_Msk (0x1fUL) /*!< BLEIF CMDSTAT: CCMD (Bitfield-Mask: 0x1f) */ +/* ========================================================= INTEN ========================================================= */ +#define BLEIF_INTEN_B2MSHUTDN_Pos (16UL) /*!< BLEIF INTEN: B2MSHUTDN (Bit 16) */ +#define BLEIF_INTEN_B2MSHUTDN_Msk (0x10000UL) /*!< BLEIF INTEN: B2MSHUTDN (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_B2MACTIVE_Pos (15UL) /*!< BLEIF INTEN: B2MACTIVE (Bit 15) */ +#define BLEIF_INTEN_B2MACTIVE_Msk (0x8000UL) /*!< BLEIF INTEN: B2MACTIVE (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_B2MSLEEP_Pos (14UL) /*!< BLEIF INTEN: B2MSLEEP (Bit 14) */ +#define BLEIF_INTEN_B2MSLEEP_Msk (0x4000UL) /*!< BLEIF INTEN: B2MSLEEP (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_CQERR_Pos (13UL) /*!< BLEIF INTEN: CQERR (Bit 13) */ +#define BLEIF_INTEN_CQERR_Msk (0x2000UL) /*!< BLEIF INTEN: CQERR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_CQUPD_Pos (12UL) /*!< BLEIF INTEN: CQUPD (Bit 12) */ +#define BLEIF_INTEN_CQUPD_Msk (0x1000UL) /*!< BLEIF INTEN: CQUPD (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_CQPAUSED_Pos (11UL) /*!< BLEIF INTEN: CQPAUSED (Bit 11) */ +#define BLEIF_INTEN_CQPAUSED_Msk (0x800UL) /*!< BLEIF INTEN: CQPAUSED (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_DERR_Pos (10UL) /*!< BLEIF INTEN: DERR (Bit 10) */ +#define BLEIF_INTEN_DERR_Msk (0x400UL) /*!< BLEIF INTEN: DERR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_DCMP_Pos (9UL) /*!< BLEIF INTEN: DCMP (Bit 9) */ +#define BLEIF_INTEN_DCMP_Msk (0x200UL) /*!< BLEIF INTEN: DCMP (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_BLECSSTAT_Pos (8UL) /*!< BLEIF INTEN: BLECSSTAT (Bit 8) */ +#define BLEIF_INTEN_BLECSSTAT_Msk (0x100UL) /*!< BLEIF INTEN: BLECSSTAT (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_BLECIRQ_Pos (7UL) /*!< BLEIF INTEN: BLECIRQ (Bit 7) */ +#define BLEIF_INTEN_BLECIRQ_Msk (0x80UL) /*!< BLEIF INTEN: BLECIRQ (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_ICMD_Pos (6UL) /*!< BLEIF INTEN: ICMD (Bit 6) */ +#define BLEIF_INTEN_ICMD_Msk (0x40UL) /*!< BLEIF INTEN: ICMD (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_IACC_Pos (5UL) /*!< BLEIF INTEN: IACC (Bit 5) */ +#define BLEIF_INTEN_IACC_Msk (0x20UL) /*!< BLEIF INTEN: IACC (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_B2MST_Pos (4UL) /*!< BLEIF INTEN: B2MST (Bit 4) */ +#define BLEIF_INTEN_B2MST_Msk (0x10UL) /*!< BLEIF INTEN: B2MST (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_FOVFL_Pos (3UL) /*!< BLEIF INTEN: FOVFL (Bit 3) */ +#define BLEIF_INTEN_FOVFL_Msk (0x8UL) /*!< BLEIF INTEN: FOVFL (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_FUNDFL_Pos (2UL) /*!< BLEIF INTEN: FUNDFL (Bit 2) */ +#define BLEIF_INTEN_FUNDFL_Msk (0x4UL) /*!< BLEIF INTEN: FUNDFL (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_THR_Pos (1UL) /*!< BLEIF INTEN: THR (Bit 1) */ +#define BLEIF_INTEN_THR_Msk (0x2UL) /*!< BLEIF INTEN: THR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTEN_CMDCMP_Pos (0UL) /*!< BLEIF INTEN: CMDCMP (Bit 0) */ +#define BLEIF_INTEN_CMDCMP_Msk (0x1UL) /*!< BLEIF INTEN: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define BLEIF_INTSTAT_B2MSHUTDN_Pos (16UL) /*!< BLEIF INTSTAT: B2MSHUTDN (Bit 16) */ +#define BLEIF_INTSTAT_B2MSHUTDN_Msk (0x10000UL) /*!< BLEIF INTSTAT: B2MSHUTDN (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_B2MACTIVE_Pos (15UL) /*!< BLEIF INTSTAT: B2MACTIVE (Bit 15) */ +#define BLEIF_INTSTAT_B2MACTIVE_Msk (0x8000UL) /*!< BLEIF INTSTAT: B2MACTIVE (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_B2MSLEEP_Pos (14UL) /*!< BLEIF INTSTAT: B2MSLEEP (Bit 14) */ +#define BLEIF_INTSTAT_B2MSLEEP_Msk (0x4000UL) /*!< BLEIF INTSTAT: B2MSLEEP (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_CQERR_Pos (13UL) /*!< BLEIF INTSTAT: CQERR (Bit 13) */ +#define BLEIF_INTSTAT_CQERR_Msk (0x2000UL) /*!< BLEIF INTSTAT: CQERR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_CQUPD_Pos (12UL) /*!< BLEIF INTSTAT: CQUPD (Bit 12) */ +#define BLEIF_INTSTAT_CQUPD_Msk (0x1000UL) /*!< BLEIF INTSTAT: CQUPD (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_CQPAUSED_Pos (11UL) /*!< BLEIF INTSTAT: CQPAUSED (Bit 11) */ +#define BLEIF_INTSTAT_CQPAUSED_Msk (0x800UL) /*!< BLEIF INTSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_DERR_Pos (10UL) /*!< BLEIF INTSTAT: DERR (Bit 10) */ +#define BLEIF_INTSTAT_DERR_Msk (0x400UL) /*!< BLEIF INTSTAT: DERR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_DCMP_Pos (9UL) /*!< BLEIF INTSTAT: DCMP (Bit 9) */ +#define BLEIF_INTSTAT_DCMP_Msk (0x200UL) /*!< BLEIF INTSTAT: DCMP (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_BLECSSTAT_Pos (8UL) /*!< BLEIF INTSTAT: BLECSSTAT (Bit 8) */ +#define BLEIF_INTSTAT_BLECSSTAT_Msk (0x100UL) /*!< BLEIF INTSTAT: BLECSSTAT (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_BLECIRQ_Pos (7UL) /*!< BLEIF INTSTAT: BLECIRQ (Bit 7) */ +#define BLEIF_INTSTAT_BLECIRQ_Msk (0x80UL) /*!< BLEIF INTSTAT: BLECIRQ (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_ICMD_Pos (6UL) /*!< BLEIF INTSTAT: ICMD (Bit 6) */ +#define BLEIF_INTSTAT_ICMD_Msk (0x40UL) /*!< BLEIF INTSTAT: ICMD (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_IACC_Pos (5UL) /*!< BLEIF INTSTAT: IACC (Bit 5) */ +#define BLEIF_INTSTAT_IACC_Msk (0x20UL) /*!< BLEIF INTSTAT: IACC (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_B2MST_Pos (4UL) /*!< BLEIF INTSTAT: B2MST (Bit 4) */ +#define BLEIF_INTSTAT_B2MST_Msk (0x10UL) /*!< BLEIF INTSTAT: B2MST (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_FOVFL_Pos (3UL) /*!< BLEIF INTSTAT: FOVFL (Bit 3) */ +#define BLEIF_INTSTAT_FOVFL_Msk (0x8UL) /*!< BLEIF INTSTAT: FOVFL (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_FUNDFL_Pos (2UL) /*!< BLEIF INTSTAT: FUNDFL (Bit 2) */ +#define BLEIF_INTSTAT_FUNDFL_Msk (0x4UL) /*!< BLEIF INTSTAT: FUNDFL (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_THR_Pos (1UL) /*!< BLEIF INTSTAT: THR (Bit 1) */ +#define BLEIF_INTSTAT_THR_Msk (0x2UL) /*!< BLEIF INTSTAT: THR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSTAT_CMDCMP_Pos (0UL) /*!< BLEIF INTSTAT: CMDCMP (Bit 0) */ +#define BLEIF_INTSTAT_CMDCMP_Msk (0x1UL) /*!< BLEIF INTSTAT: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define BLEIF_INTCLR_B2MSHUTDN_Pos (16UL) /*!< BLEIF INTCLR: B2MSHUTDN (Bit 16) */ +#define BLEIF_INTCLR_B2MSHUTDN_Msk (0x10000UL) /*!< BLEIF INTCLR: B2MSHUTDN (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_B2MACTIVE_Pos (15UL) /*!< BLEIF INTCLR: B2MACTIVE (Bit 15) */ +#define BLEIF_INTCLR_B2MACTIVE_Msk (0x8000UL) /*!< BLEIF INTCLR: B2MACTIVE (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_B2MSLEEP_Pos (14UL) /*!< BLEIF INTCLR: B2MSLEEP (Bit 14) */ +#define BLEIF_INTCLR_B2MSLEEP_Msk (0x4000UL) /*!< BLEIF INTCLR: B2MSLEEP (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_CQERR_Pos (13UL) /*!< BLEIF INTCLR: CQERR (Bit 13) */ +#define BLEIF_INTCLR_CQERR_Msk (0x2000UL) /*!< BLEIF INTCLR: CQERR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_CQUPD_Pos (12UL) /*!< BLEIF INTCLR: CQUPD (Bit 12) */ +#define BLEIF_INTCLR_CQUPD_Msk (0x1000UL) /*!< BLEIF INTCLR: CQUPD (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_CQPAUSED_Pos (11UL) /*!< BLEIF INTCLR: CQPAUSED (Bit 11) */ +#define BLEIF_INTCLR_CQPAUSED_Msk (0x800UL) /*!< BLEIF INTCLR: CQPAUSED (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_DERR_Pos (10UL) /*!< BLEIF INTCLR: DERR (Bit 10) */ +#define BLEIF_INTCLR_DERR_Msk (0x400UL) /*!< BLEIF INTCLR: DERR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_DCMP_Pos (9UL) /*!< BLEIF INTCLR: DCMP (Bit 9) */ +#define BLEIF_INTCLR_DCMP_Msk (0x200UL) /*!< BLEIF INTCLR: DCMP (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_BLECSSTAT_Pos (8UL) /*!< BLEIF INTCLR: BLECSSTAT (Bit 8) */ +#define BLEIF_INTCLR_BLECSSTAT_Msk (0x100UL) /*!< BLEIF INTCLR: BLECSSTAT (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_BLECIRQ_Pos (7UL) /*!< BLEIF INTCLR: BLECIRQ (Bit 7) */ +#define BLEIF_INTCLR_BLECIRQ_Msk (0x80UL) /*!< BLEIF INTCLR: BLECIRQ (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_ICMD_Pos (6UL) /*!< BLEIF INTCLR: ICMD (Bit 6) */ +#define BLEIF_INTCLR_ICMD_Msk (0x40UL) /*!< BLEIF INTCLR: ICMD (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_IACC_Pos (5UL) /*!< BLEIF INTCLR: IACC (Bit 5) */ +#define BLEIF_INTCLR_IACC_Msk (0x20UL) /*!< BLEIF INTCLR: IACC (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_B2MST_Pos (4UL) /*!< BLEIF INTCLR: B2MST (Bit 4) */ +#define BLEIF_INTCLR_B2MST_Msk (0x10UL) /*!< BLEIF INTCLR: B2MST (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_FOVFL_Pos (3UL) /*!< BLEIF INTCLR: FOVFL (Bit 3) */ +#define BLEIF_INTCLR_FOVFL_Msk (0x8UL) /*!< BLEIF INTCLR: FOVFL (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_FUNDFL_Pos (2UL) /*!< BLEIF INTCLR: FUNDFL (Bit 2) */ +#define BLEIF_INTCLR_FUNDFL_Msk (0x4UL) /*!< BLEIF INTCLR: FUNDFL (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_THR_Pos (1UL) /*!< BLEIF INTCLR: THR (Bit 1) */ +#define BLEIF_INTCLR_THR_Msk (0x2UL) /*!< BLEIF INTCLR: THR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTCLR_CMDCMP_Pos (0UL) /*!< BLEIF INTCLR: CMDCMP (Bit 0) */ +#define BLEIF_INTCLR_CMDCMP_Msk (0x1UL) /*!< BLEIF INTCLR: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define BLEIF_INTSET_B2MSHUTDN_Pos (16UL) /*!< BLEIF INTSET: B2MSHUTDN (Bit 16) */ +#define BLEIF_INTSET_B2MSHUTDN_Msk (0x10000UL) /*!< BLEIF INTSET: B2MSHUTDN (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_B2MACTIVE_Pos (15UL) /*!< BLEIF INTSET: B2MACTIVE (Bit 15) */ +#define BLEIF_INTSET_B2MACTIVE_Msk (0x8000UL) /*!< BLEIF INTSET: B2MACTIVE (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_B2MSLEEP_Pos (14UL) /*!< BLEIF INTSET: B2MSLEEP (Bit 14) */ +#define BLEIF_INTSET_B2MSLEEP_Msk (0x4000UL) /*!< BLEIF INTSET: B2MSLEEP (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_CQERR_Pos (13UL) /*!< BLEIF INTSET: CQERR (Bit 13) */ +#define BLEIF_INTSET_CQERR_Msk (0x2000UL) /*!< BLEIF INTSET: CQERR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_CQUPD_Pos (12UL) /*!< BLEIF INTSET: CQUPD (Bit 12) */ +#define BLEIF_INTSET_CQUPD_Msk (0x1000UL) /*!< BLEIF INTSET: CQUPD (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_CQPAUSED_Pos (11UL) /*!< BLEIF INTSET: CQPAUSED (Bit 11) */ +#define BLEIF_INTSET_CQPAUSED_Msk (0x800UL) /*!< BLEIF INTSET: CQPAUSED (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_DERR_Pos (10UL) /*!< BLEIF INTSET: DERR (Bit 10) */ +#define BLEIF_INTSET_DERR_Msk (0x400UL) /*!< BLEIF INTSET: DERR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_DCMP_Pos (9UL) /*!< BLEIF INTSET: DCMP (Bit 9) */ +#define BLEIF_INTSET_DCMP_Msk (0x200UL) /*!< BLEIF INTSET: DCMP (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_BLECSSTAT_Pos (8UL) /*!< BLEIF INTSET: BLECSSTAT (Bit 8) */ +#define BLEIF_INTSET_BLECSSTAT_Msk (0x100UL) /*!< BLEIF INTSET: BLECSSTAT (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_BLECIRQ_Pos (7UL) /*!< BLEIF INTSET: BLECIRQ (Bit 7) */ +#define BLEIF_INTSET_BLECIRQ_Msk (0x80UL) /*!< BLEIF INTSET: BLECIRQ (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_ICMD_Pos (6UL) /*!< BLEIF INTSET: ICMD (Bit 6) */ +#define BLEIF_INTSET_ICMD_Msk (0x40UL) /*!< BLEIF INTSET: ICMD (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_IACC_Pos (5UL) /*!< BLEIF INTSET: IACC (Bit 5) */ +#define BLEIF_INTSET_IACC_Msk (0x20UL) /*!< BLEIF INTSET: IACC (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_B2MST_Pos (4UL) /*!< BLEIF INTSET: B2MST (Bit 4) */ +#define BLEIF_INTSET_B2MST_Msk (0x10UL) /*!< BLEIF INTSET: B2MST (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_FOVFL_Pos (3UL) /*!< BLEIF INTSET: FOVFL (Bit 3) */ +#define BLEIF_INTSET_FOVFL_Msk (0x8UL) /*!< BLEIF INTSET: FOVFL (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_FUNDFL_Pos (2UL) /*!< BLEIF INTSET: FUNDFL (Bit 2) */ +#define BLEIF_INTSET_FUNDFL_Msk (0x4UL) /*!< BLEIF INTSET: FUNDFL (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_THR_Pos (1UL) /*!< BLEIF INTSET: THR (Bit 1) */ +#define BLEIF_INTSET_THR_Msk (0x2UL) /*!< BLEIF INTSET: THR (Bitfield-Mask: 0x01) */ +#define BLEIF_INTSET_CMDCMP_Pos (0UL) /*!< BLEIF INTSET: CMDCMP (Bit 0) */ +#define BLEIF_INTSET_CMDCMP_Msk (0x1UL) /*!< BLEIF INTSET: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================= DMATRIGEN ======================================================= */ +#define BLEIF_DMATRIGEN_DTHREN_Pos (1UL) /*!< BLEIF DMATRIGEN: DTHREN (Bit 1) */ +#define BLEIF_DMATRIGEN_DTHREN_Msk (0x2UL) /*!< BLEIF DMATRIGEN: DTHREN (Bitfield-Mask: 0x01) */ +#define BLEIF_DMATRIGEN_DCMDCMPEN_Pos (0UL) /*!< BLEIF DMATRIGEN: DCMDCMPEN (Bit 0) */ +#define BLEIF_DMATRIGEN_DCMDCMPEN_Msk (0x1UL) /*!< BLEIF DMATRIGEN: DCMDCMPEN (Bitfield-Mask: 0x01) */ +/* ====================================================== DMATRIGSTAT ====================================================== */ +#define BLEIF_DMATRIGSTAT_DTOTCMP_Pos (2UL) /*!< BLEIF DMATRIGSTAT: DTOTCMP (Bit 2) */ +#define BLEIF_DMATRIGSTAT_DTOTCMP_Msk (0x4UL) /*!< BLEIF DMATRIGSTAT: DTOTCMP (Bitfield-Mask: 0x01) */ +#define BLEIF_DMATRIGSTAT_DTHR_Pos (1UL) /*!< BLEIF DMATRIGSTAT: DTHR (Bit 1) */ +#define BLEIF_DMATRIGSTAT_DTHR_Msk (0x2UL) /*!< BLEIF DMATRIGSTAT: DTHR (Bitfield-Mask: 0x01) */ +#define BLEIF_DMATRIGSTAT_DCMDCMP_Pos (0UL) /*!< BLEIF DMATRIGSTAT: DCMDCMP (Bit 0) */ +#define BLEIF_DMATRIGSTAT_DCMDCMP_Msk (0x1UL) /*!< BLEIF DMATRIGSTAT: DCMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== DMACFG ========================================================= */ +#define BLEIF_DMACFG_DPWROFF_Pos (9UL) /*!< BLEIF DMACFG: DPWROFF (Bit 9) */ +#define BLEIF_DMACFG_DPWROFF_Msk (0x200UL) /*!< BLEIF DMACFG: DPWROFF (Bitfield-Mask: 0x01) */ +#define BLEIF_DMACFG_DMAPRI_Pos (8UL) /*!< BLEIF DMACFG: DMAPRI (Bit 8) */ +#define BLEIF_DMACFG_DMAPRI_Msk (0x100UL) /*!< BLEIF DMACFG: DMAPRI (Bitfield-Mask: 0x01) */ +#define BLEIF_DMACFG_DMADIR_Pos (1UL) /*!< BLEIF DMACFG: DMADIR (Bit 1) */ +#define BLEIF_DMACFG_DMADIR_Msk (0x2UL) /*!< BLEIF DMACFG: DMADIR (Bitfield-Mask: 0x01) */ +#define BLEIF_DMACFG_DMAEN_Pos (0UL) /*!< BLEIF DMACFG: DMAEN (Bit 0) */ +#define BLEIF_DMACFG_DMAEN_Msk (0x1UL) /*!< BLEIF DMACFG: DMAEN (Bitfield-Mask: 0x01) */ +/* ====================================================== DMATOTCOUNT ====================================================== */ +#define BLEIF_DMATOTCOUNT_TOTCOUNT_Pos (0UL) /*!< BLEIF DMATOTCOUNT: TOTCOUNT (Bit 0) */ +#define BLEIF_DMATOTCOUNT_TOTCOUNT_Msk (0xfffUL) /*!< BLEIF DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xfff) */ +/* ====================================================== DMATARGADDR ====================================================== */ +#define BLEIF_DMATARGADDR_TARGADDR28_Pos (28UL) /*!< BLEIF DMATARGADDR: TARGADDR28 (Bit 28) */ +#define BLEIF_DMATARGADDR_TARGADDR28_Msk (0x10000000UL) /*!< BLEIF DMATARGADDR: TARGADDR28 (Bitfield-Mask: 0x01) */ +#define BLEIF_DMATARGADDR_TARGADDR_Pos (0UL) /*!< BLEIF DMATARGADDR: TARGADDR (Bit 0) */ +#define BLEIF_DMATARGADDR_TARGADDR_Msk (0xfffffUL) /*!< BLEIF DMATARGADDR: TARGADDR (Bitfield-Mask: 0xfffff) */ +/* ======================================================== DMASTAT ======================================================== */ +#define BLEIF_DMASTAT_DMAERR_Pos (2UL) /*!< BLEIF DMASTAT: DMAERR (Bit 2) */ +#define BLEIF_DMASTAT_DMAERR_Msk (0x4UL) /*!< BLEIF DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ +#define BLEIF_DMASTAT_DMACPL_Pos (1UL) /*!< BLEIF DMASTAT: DMACPL (Bit 1) */ +#define BLEIF_DMASTAT_DMACPL_Msk (0x2UL) /*!< BLEIF DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ +#define BLEIF_DMASTAT_DMATIP_Pos (0UL) /*!< BLEIF DMASTAT: DMATIP (Bit 0) */ +#define BLEIF_DMASTAT_DMATIP_Msk (0x1UL) /*!< BLEIF DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ +/* ========================================================= CQCFG ========================================================= */ +#define BLEIF_CQCFG_CQPRI_Pos (1UL) /*!< BLEIF CQCFG: CQPRI (Bit 1) */ +#define BLEIF_CQCFG_CQPRI_Msk (0x2UL) /*!< BLEIF CQCFG: CQPRI (Bitfield-Mask: 0x01) */ +#define BLEIF_CQCFG_CQEN_Pos (0UL) /*!< BLEIF CQCFG: CQEN (Bit 0) */ +#define BLEIF_CQCFG_CQEN_Msk (0x1UL) /*!< BLEIF CQCFG: CQEN (Bitfield-Mask: 0x01) */ +/* ======================================================== CQADDR ========================================================= */ +#define BLEIF_CQADDR_CQADDR28_Pos (28UL) /*!< BLEIF CQADDR: CQADDR28 (Bit 28) */ +#define BLEIF_CQADDR_CQADDR28_Msk (0x10000000UL) /*!< BLEIF CQADDR: CQADDR28 (Bitfield-Mask: 0x01) */ +#define BLEIF_CQADDR_CQADDR_Pos (2UL) /*!< BLEIF CQADDR: CQADDR (Bit 2) */ +#define BLEIF_CQADDR_CQADDR_Msk (0xffffcUL) /*!< BLEIF CQADDR: CQADDR (Bitfield-Mask: 0x3ffff) */ +/* ======================================================== CQSTAT ========================================================= */ +#define BLEIF_CQSTAT_CQERR_Pos (2UL) /*!< BLEIF CQSTAT: CQERR (Bit 2) */ +#define BLEIF_CQSTAT_CQERR_Msk (0x4UL) /*!< BLEIF CQSTAT: CQERR (Bitfield-Mask: 0x01) */ +#define BLEIF_CQSTAT_CQPAUSED_Pos (1UL) /*!< BLEIF CQSTAT: CQPAUSED (Bit 1) */ +#define BLEIF_CQSTAT_CQPAUSED_Msk (0x2UL) /*!< BLEIF CQSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ +#define BLEIF_CQSTAT_CQTIP_Pos (0UL) /*!< BLEIF CQSTAT: CQTIP (Bit 0) */ +#define BLEIF_CQSTAT_CQTIP_Msk (0x1UL) /*!< BLEIF CQSTAT: CQTIP (Bitfield-Mask: 0x01) */ +/* ======================================================== CQFLAGS ======================================================== */ +#define BLEIF_CQFLAGS_CQIRQMASK_Pos (16UL) /*!< BLEIF CQFLAGS: CQIRQMASK (Bit 16) */ +#define BLEIF_CQFLAGS_CQIRQMASK_Msk (0xffff0000UL) /*!< BLEIF CQFLAGS: CQIRQMASK (Bitfield-Mask: 0xffff) */ +#define BLEIF_CQFLAGS_CQFLAGS_Pos (0UL) /*!< BLEIF CQFLAGS: CQFLAGS (Bit 0) */ +#define BLEIF_CQFLAGS_CQFLAGS_Msk (0xffffUL) /*!< BLEIF CQFLAGS: CQFLAGS (Bitfield-Mask: 0xffff) */ +/* ====================================================== CQSETCLEAR ======================================================= */ +#define BLEIF_CQSETCLEAR_CQFCLR_Pos (16UL) /*!< BLEIF CQSETCLEAR: CQFCLR (Bit 16) */ +#define BLEIF_CQSETCLEAR_CQFCLR_Msk (0xff0000UL) /*!< BLEIF CQSETCLEAR: CQFCLR (Bitfield-Mask: 0xff) */ +#define BLEIF_CQSETCLEAR_CQFTGL_Pos (8UL) /*!< BLEIF CQSETCLEAR: CQFTGL (Bit 8) */ +#define BLEIF_CQSETCLEAR_CQFTGL_Msk (0xff00UL) /*!< BLEIF CQSETCLEAR: CQFTGL (Bitfield-Mask: 0xff) */ +#define BLEIF_CQSETCLEAR_CQFSET_Pos (0UL) /*!< BLEIF CQSETCLEAR: CQFSET (Bit 0) */ +#define BLEIF_CQSETCLEAR_CQFSET_Msk (0xffUL) /*!< BLEIF CQSETCLEAR: CQFSET (Bitfield-Mask: 0xff) */ +/* ======================================================= CQPAUSEEN ======================================================= */ +#define BLEIF_CQPAUSEEN_CQPEN_Pos (0UL) /*!< BLEIF CQPAUSEEN: CQPEN (Bit 0) */ +#define BLEIF_CQPAUSEEN_CQPEN_Msk (0xffffUL) /*!< BLEIF CQPAUSEEN: CQPEN (Bitfield-Mask: 0xffff) */ +/* ======================================================= CQCURIDX ======================================================== */ +#define BLEIF_CQCURIDX_CQCURIDX_Pos (0UL) /*!< BLEIF CQCURIDX: CQCURIDX (Bit 0) */ +#define BLEIF_CQCURIDX_CQCURIDX_Msk (0xffUL) /*!< BLEIF CQCURIDX: CQCURIDX (Bitfield-Mask: 0xff) */ +/* ======================================================= CQENDIDX ======================================================== */ +#define BLEIF_CQENDIDX_CQENDIDX_Pos (0UL) /*!< BLEIF CQENDIDX: CQENDIDX (Bit 0) */ +#define BLEIF_CQENDIDX_CQENDIDX_Msk (0xffUL) /*!< BLEIF CQENDIDX: CQENDIDX (Bitfield-Mask: 0xff) */ +/* ======================================================== STATUS ========================================================= */ +#define BLEIF_STATUS_IDLEST_Pos (2UL) /*!< BLEIF STATUS: IDLEST (Bit 2) */ +#define BLEIF_STATUS_IDLEST_Msk (0x4UL) /*!< BLEIF STATUS: IDLEST (Bitfield-Mask: 0x01) */ +#define BLEIF_STATUS_CMDACT_Pos (1UL) /*!< BLEIF STATUS: CMDACT (Bit 1) */ +#define BLEIF_STATUS_CMDACT_Msk (0x2UL) /*!< BLEIF STATUS: CMDACT (Bitfield-Mask: 0x01) */ +#define BLEIF_STATUS_ERR_Pos (0UL) /*!< BLEIF STATUS: ERR (Bit 0) */ +#define BLEIF_STATUS_ERR_Msk (0x1UL) /*!< BLEIF STATUS: ERR (Bitfield-Mask: 0x01) */ +/* ======================================================== MSPICFG ======================================================== */ +#define BLEIF_MSPICFG_MSPIRST_Pos (30UL) /*!< BLEIF MSPICFG: MSPIRST (Bit 30) */ +#define BLEIF_MSPICFG_MSPIRST_Msk (0x40000000UL) /*!< BLEIF MSPICFG: MSPIRST (Bitfield-Mask: 0x01) */ +#define BLEIF_MSPICFG_DOUTDLY_Pos (27UL) /*!< BLEIF MSPICFG: DOUTDLY (Bit 27) */ +#define BLEIF_MSPICFG_DOUTDLY_Msk (0x38000000UL) /*!< BLEIF MSPICFG: DOUTDLY (Bitfield-Mask: 0x07) */ +#define BLEIF_MSPICFG_DINDLY_Pos (24UL) /*!< BLEIF MSPICFG: DINDLY (Bit 24) */ +#define BLEIF_MSPICFG_DINDLY_Msk (0x7000000UL) /*!< BLEIF MSPICFG: DINDLY (Bitfield-Mask: 0x07) */ +#define BLEIF_MSPICFG_SPILSB_Pos (23UL) /*!< BLEIF MSPICFG: SPILSB (Bit 23) */ +#define BLEIF_MSPICFG_SPILSB_Msk (0x800000UL) /*!< BLEIF MSPICFG: SPILSB (Bitfield-Mask: 0x01) */ +#define BLEIF_MSPICFG_RDFCPOL_Pos (22UL) /*!< BLEIF MSPICFG: RDFCPOL (Bit 22) */ +#define BLEIF_MSPICFG_RDFCPOL_Msk (0x400000UL) /*!< BLEIF MSPICFG: RDFCPOL (Bitfield-Mask: 0x01) */ +#define BLEIF_MSPICFG_WTFCPOL_Pos (21UL) /*!< BLEIF MSPICFG: WTFCPOL (Bit 21) */ +#define BLEIF_MSPICFG_WTFCPOL_Msk (0x200000UL) /*!< BLEIF MSPICFG: WTFCPOL (Bitfield-Mask: 0x01) */ +#define BLEIF_MSPICFG_RDFC_Pos (17UL) /*!< BLEIF MSPICFG: RDFC (Bit 17) */ +#define BLEIF_MSPICFG_RDFC_Msk (0x20000UL) /*!< BLEIF MSPICFG: RDFC (Bitfield-Mask: 0x01) */ +#define BLEIF_MSPICFG_WTFC_Pos (16UL) /*!< BLEIF MSPICFG: WTFC (Bit 16) */ +#define BLEIF_MSPICFG_WTFC_Msk (0x10000UL) /*!< BLEIF MSPICFG: WTFC (Bitfield-Mask: 0x01) */ +#define BLEIF_MSPICFG_FULLDUP_Pos (2UL) /*!< BLEIF MSPICFG: FULLDUP (Bit 2) */ +#define BLEIF_MSPICFG_FULLDUP_Msk (0x4UL) /*!< BLEIF MSPICFG: FULLDUP (Bitfield-Mask: 0x01) */ +#define BLEIF_MSPICFG_SPHA_Pos (1UL) /*!< BLEIF MSPICFG: SPHA (Bit 1) */ +#define BLEIF_MSPICFG_SPHA_Msk (0x2UL) /*!< BLEIF MSPICFG: SPHA (Bitfield-Mask: 0x01) */ +#define BLEIF_MSPICFG_SPOL_Pos (0UL) /*!< BLEIF MSPICFG: SPOL (Bit 0) */ +#define BLEIF_MSPICFG_SPOL_Msk (0x1UL) /*!< BLEIF MSPICFG: SPOL (Bitfield-Mask: 0x01) */ +/* ======================================================== BLECFG ========================================================= */ +#define BLEIF_BLECFG_SPIISOCTL_Pos (14UL) /*!< BLEIF BLECFG: SPIISOCTL (Bit 14) */ +#define BLEIF_BLECFG_SPIISOCTL_Msk (0xc000UL) /*!< BLEIF BLECFG: SPIISOCTL (Bitfield-Mask: 0x03) */ +#define BLEIF_BLECFG_PWRISOCTL_Pos (12UL) /*!< BLEIF BLECFG: PWRISOCTL (Bit 12) */ +#define BLEIF_BLECFG_PWRISOCTL_Msk (0x3000UL) /*!< BLEIF BLECFG: PWRISOCTL (Bitfield-Mask: 0x03) */ +#define BLEIF_BLECFG_STAYASLEEP_Pos (11UL) /*!< BLEIF BLECFG: STAYASLEEP (Bit 11) */ +#define BLEIF_BLECFG_STAYASLEEP_Msk (0x800UL) /*!< BLEIF BLECFG: STAYASLEEP (Bitfield-Mask: 0x01) */ +#define BLEIF_BLECFG_FRCCLK_Pos (10UL) /*!< BLEIF BLECFG: FRCCLK (Bit 10) */ +#define BLEIF_BLECFG_FRCCLK_Msk (0x400UL) /*!< BLEIF BLECFG: FRCCLK (Bitfield-Mask: 0x01) */ +#define BLEIF_BLECFG_MCUFRCSLP_Pos (9UL) /*!< BLEIF BLECFG: MCUFRCSLP (Bit 9) */ +#define BLEIF_BLECFG_MCUFRCSLP_Msk (0x200UL) /*!< BLEIF BLECFG: MCUFRCSLP (Bitfield-Mask: 0x01) */ +#define BLEIF_BLECFG_WT4ACTOFF_Pos (8UL) /*!< BLEIF BLECFG: WT4ACTOFF (Bit 8) */ +#define BLEIF_BLECFG_WT4ACTOFF_Msk (0x100UL) /*!< BLEIF BLECFG: WT4ACTOFF (Bitfield-Mask: 0x01) */ +#define BLEIF_BLECFG_BLEHREQCTL_Pos (6UL) /*!< BLEIF BLECFG: BLEHREQCTL (Bit 6) */ +#define BLEIF_BLECFG_BLEHREQCTL_Msk (0xc0UL) /*!< BLEIF BLECFG: BLEHREQCTL (Bitfield-Mask: 0x03) */ +#define BLEIF_BLECFG_DCDCFLGCTL_Pos (4UL) /*!< BLEIF BLECFG: DCDCFLGCTL (Bit 4) */ +#define BLEIF_BLECFG_DCDCFLGCTL_Msk (0x30UL) /*!< BLEIF BLECFG: DCDCFLGCTL (Bitfield-Mask: 0x03) */ +#define BLEIF_BLECFG_WAKEUPCTL_Pos (2UL) /*!< BLEIF BLECFG: WAKEUPCTL (Bit 2) */ +#define BLEIF_BLECFG_WAKEUPCTL_Msk (0xcUL) /*!< BLEIF BLECFG: WAKEUPCTL (Bitfield-Mask: 0x03) */ +#define BLEIF_BLECFG_BLERSTN_Pos (1UL) /*!< BLEIF BLECFG: BLERSTN (Bit 1) */ +#define BLEIF_BLECFG_BLERSTN_Msk (0x2UL) /*!< BLEIF BLECFG: BLERSTN (Bitfield-Mask: 0x01) */ +#define BLEIF_BLECFG_PWRSMEN_Pos (0UL) /*!< BLEIF BLECFG: PWRSMEN (Bit 0) */ +#define BLEIF_BLECFG_PWRSMEN_Msk (0x1UL) /*!< BLEIF BLECFG: PWRSMEN (Bitfield-Mask: 0x01) */ +/* ======================================================== PWRCMD ========================================================= */ +#define BLEIF_PWRCMD_RESTART_Pos (1UL) /*!< BLEIF PWRCMD: RESTART (Bit 1) */ +#define BLEIF_PWRCMD_RESTART_Msk (0x2UL) /*!< BLEIF PWRCMD: RESTART (Bitfield-Mask: 0x01) */ +#define BLEIF_PWRCMD_WAKEREQ_Pos (0UL) /*!< BLEIF PWRCMD: WAKEREQ (Bit 0) */ +#define BLEIF_PWRCMD_WAKEREQ_Msk (0x1UL) /*!< BLEIF PWRCMD: WAKEREQ (Bitfield-Mask: 0x01) */ +/* ======================================================== BSTATUS ======================================================== */ +#define BLEIF_BSTATUS_BLEHREQ_Pos (12UL) /*!< BLEIF BSTATUS: BLEHREQ (Bit 12) */ +#define BLEIF_BSTATUS_BLEHREQ_Msk (0x1000UL) /*!< BLEIF BSTATUS: BLEHREQ (Bitfield-Mask: 0x01) */ +#define BLEIF_BSTATUS_BLEHACK_Pos (11UL) /*!< BLEIF BSTATUS: BLEHACK (Bit 11) */ +#define BLEIF_BSTATUS_BLEHACK_Msk (0x800UL) /*!< BLEIF BSTATUS: BLEHACK (Bitfield-Mask: 0x01) */ +#define BLEIF_BSTATUS_PWRST_Pos (8UL) /*!< BLEIF BSTATUS: PWRST (Bit 8) */ +#define BLEIF_BSTATUS_PWRST_Msk (0x700UL) /*!< BLEIF BSTATUS: PWRST (Bitfield-Mask: 0x07) */ +#define BLEIF_BSTATUS_BLEIRQ_Pos (7UL) /*!< BLEIF BSTATUS: BLEIRQ (Bit 7) */ +#define BLEIF_BSTATUS_BLEIRQ_Msk (0x80UL) /*!< BLEIF BSTATUS: BLEIRQ (Bitfield-Mask: 0x01) */ +#define BLEIF_BSTATUS_WAKEUP_Pos (6UL) /*!< BLEIF BSTATUS: WAKEUP (Bit 6) */ +#define BLEIF_BSTATUS_WAKEUP_Msk (0x40UL) /*!< BLEIF BSTATUS: WAKEUP (Bitfield-Mask: 0x01) */ +#define BLEIF_BSTATUS_DCDCFLAG_Pos (5UL) /*!< BLEIF BSTATUS: DCDCFLAG (Bit 5) */ +#define BLEIF_BSTATUS_DCDCFLAG_Msk (0x20UL) /*!< BLEIF BSTATUS: DCDCFLAG (Bitfield-Mask: 0x01) */ +#define BLEIF_BSTATUS_DCDCREQ_Pos (4UL) /*!< BLEIF BSTATUS: DCDCREQ (Bit 4) */ +#define BLEIF_BSTATUS_DCDCREQ_Msk (0x10UL) /*!< BLEIF BSTATUS: DCDCREQ (Bitfield-Mask: 0x01) */ +#define BLEIF_BSTATUS_SPISTATUS_Pos (3UL) /*!< BLEIF BSTATUS: SPISTATUS (Bit 3) */ +#define BLEIF_BSTATUS_SPISTATUS_Msk (0x8UL) /*!< BLEIF BSTATUS: SPISTATUS (Bitfield-Mask: 0x01) */ +#define BLEIF_BSTATUS_B2MSTATE_Pos (0UL) /*!< BLEIF BSTATUS: B2MSTATE (Bit 0) */ +#define BLEIF_BSTATUS_B2MSTATE_Msk (0x7UL) /*!< BLEIF BSTATUS: B2MSTATE (Bitfield-Mask: 0x07) */ +/* ======================================================== BLEDBG ========================================================= */ +#define BLEIF_BLEDBG_DBGDATA_Pos (3UL) /*!< BLEIF BLEDBG: DBGDATA (Bit 3) */ +#define BLEIF_BLEDBG_DBGDATA_Msk (0xfffffff8UL) /*!< BLEIF BLEDBG: DBGDATA (Bitfield-Mask: 0x1fffffff) */ +#define BLEIF_BLEDBG_APBCLKON_Pos (2UL) /*!< BLEIF BLEDBG: APBCLKON (Bit 2) */ +#define BLEIF_BLEDBG_APBCLKON_Msk (0x4UL) /*!< BLEIF BLEDBG: APBCLKON (Bitfield-Mask: 0x01) */ +#define BLEIF_BLEDBG_IOCLKON_Pos (1UL) /*!< BLEIF BLEDBG: IOCLKON (Bit 1) */ +#define BLEIF_BLEDBG_IOCLKON_Msk (0x2UL) /*!< BLEIF BLEDBG: IOCLKON (Bitfield-Mask: 0x01) */ +#define BLEIF_BLEDBG_DBGEN_Pos (0UL) /*!< BLEIF BLEDBG: DBGEN (Bit 0) */ +#define BLEIF_BLEDBG_DBGEN_Msk (0x1UL) /*!< BLEIF BLEDBG: DBGEN (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ CACHECTRL ================ */ +/* =========================================================================================================================== */ + +/* ======================================================= CACHECFG ======================================================== */ +#define CACHECTRL_CACHECFG_ENABLE_MONITOR_Pos (24UL) /*!< CACHECTRL CACHECFG: ENABLE_MONITOR (Bit 24) */ +#define CACHECTRL_CACHECFG_ENABLE_MONITOR_Msk (0x1000000UL) /*!< CACHECTRL CACHECFG: ENABLE_MONITOR (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CACHECFG_DATA_CLKGATE_Pos (20UL) /*!< CACHECTRL CACHECFG: DATA_CLKGATE (Bit 20) */ +#define CACHECTRL_CACHECFG_DATA_CLKGATE_Msk (0x100000UL) /*!< CACHECTRL CACHECFG: DATA_CLKGATE (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CACHECFG_CACHE_LS_Pos (11UL) /*!< CACHECTRL CACHECFG: CACHE_LS (Bit 11) */ +#define CACHECTRL_CACHECFG_CACHE_LS_Msk (0x800UL) /*!< CACHECTRL CACHECFG: CACHE_LS (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CACHECFG_CACHE_CLKGATE_Pos (10UL) /*!< CACHECTRL CACHECFG: CACHE_CLKGATE (Bit 10) */ +#define CACHECTRL_CACHECFG_CACHE_CLKGATE_Msk (0x400UL) /*!< CACHECTRL CACHECFG: CACHE_CLKGATE (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CACHECFG_DCACHE_ENABLE_Pos (9UL) /*!< CACHECTRL CACHECFG: DCACHE_ENABLE (Bit 9) */ +#define CACHECTRL_CACHECFG_DCACHE_ENABLE_Msk (0x200UL) /*!< CACHECTRL CACHECFG: DCACHE_ENABLE (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CACHECFG_ICACHE_ENABLE_Pos (8UL) /*!< CACHECTRL CACHECFG: ICACHE_ENABLE (Bit 8) */ +#define CACHECTRL_CACHECFG_ICACHE_ENABLE_Msk (0x100UL) /*!< CACHECTRL CACHECFG: ICACHE_ENABLE (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CACHECFG_CONFIG_Pos (4UL) /*!< CACHECTRL CACHECFG: CONFIG (Bit 4) */ +#define CACHECTRL_CACHECFG_CONFIG_Msk (0xf0UL) /*!< CACHECTRL CACHECFG: CONFIG (Bitfield-Mask: 0x0f) */ +#define CACHECTRL_CACHECFG_ENABLE_NC1_Pos (3UL) /*!< CACHECTRL CACHECFG: ENABLE_NC1 (Bit 3) */ +#define CACHECTRL_CACHECFG_ENABLE_NC1_Msk (0x8UL) /*!< CACHECTRL CACHECFG: ENABLE_NC1 (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CACHECFG_ENABLE_NC0_Pos (2UL) /*!< CACHECTRL CACHECFG: ENABLE_NC0 (Bit 2) */ +#define CACHECTRL_CACHECFG_ENABLE_NC0_Msk (0x4UL) /*!< CACHECTRL CACHECFG: ENABLE_NC0 (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CACHECFG_LRU_Pos (1UL) /*!< CACHECTRL CACHECFG: LRU (Bit 1) */ +#define CACHECTRL_CACHECFG_LRU_Msk (0x2UL) /*!< CACHECTRL CACHECFG: LRU (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CACHECFG_ENABLE_Pos (0UL) /*!< CACHECTRL CACHECFG: ENABLE (Bit 0) */ +#define CACHECTRL_CACHECFG_ENABLE_Msk (0x1UL) /*!< CACHECTRL CACHECFG: ENABLE (Bitfield-Mask: 0x01) */ +/* ======================================================= FLASHCFG ======================================================== */ +#define CACHECTRL_FLASHCFG_LPMMODE_Pos (12UL) /*!< CACHECTRL FLASHCFG: LPMMODE (Bit 12) */ +#define CACHECTRL_FLASHCFG_LPMMODE_Msk (0x3000UL) /*!< CACHECTRL FLASHCFG: LPMMODE (Bitfield-Mask: 0x03) */ +#define CACHECTRL_FLASHCFG_LPM_RD_WAIT_Pos (8UL) /*!< CACHECTRL FLASHCFG: LPM_RD_WAIT (Bit 8) */ +#define CACHECTRL_FLASHCFG_LPM_RD_WAIT_Msk (0xf00UL) /*!< CACHECTRL FLASHCFG: LPM_RD_WAIT (Bitfield-Mask: 0x0f) */ +#define CACHECTRL_FLASHCFG_SEDELAY_Pos (4UL) /*!< CACHECTRL FLASHCFG: SEDELAY (Bit 4) */ +#define CACHECTRL_FLASHCFG_SEDELAY_Msk (0x70UL) /*!< CACHECTRL FLASHCFG: SEDELAY (Bitfield-Mask: 0x07) */ +#define CACHECTRL_FLASHCFG_RD_WAIT_Pos (0UL) /*!< CACHECTRL FLASHCFG: RD_WAIT (Bit 0) */ +#define CACHECTRL_FLASHCFG_RD_WAIT_Msk (0xfUL) /*!< CACHECTRL FLASHCFG: RD_WAIT (Bitfield-Mask: 0x0f) */ +/* ========================================================= CTRL ========================================================== */ +#define CACHECTRL_CTRL_FLASH1_SLM_ENABLE_Pos (10UL) /*!< CACHECTRL CTRL: FLASH1_SLM_ENABLE (Bit 10) */ +#define CACHECTRL_CTRL_FLASH1_SLM_ENABLE_Msk (0x400UL) /*!< CACHECTRL CTRL: FLASH1_SLM_ENABLE (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CTRL_FLASH1_SLM_DISABLE_Pos (9UL) /*!< CACHECTRL CTRL: FLASH1_SLM_DISABLE (Bit 9) */ +#define CACHECTRL_CTRL_FLASH1_SLM_DISABLE_Msk (0x200UL) /*!< CACHECTRL CTRL: FLASH1_SLM_DISABLE (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CTRL_FLASH1_SLM_STATUS_Pos (8UL) /*!< CACHECTRL CTRL: FLASH1_SLM_STATUS (Bit 8) */ +#define CACHECTRL_CTRL_FLASH1_SLM_STATUS_Msk (0x100UL) /*!< CACHECTRL CTRL: FLASH1_SLM_STATUS (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CTRL_FLASH0_SLM_ENABLE_Pos (6UL) /*!< CACHECTRL CTRL: FLASH0_SLM_ENABLE (Bit 6) */ +#define CACHECTRL_CTRL_FLASH0_SLM_ENABLE_Msk (0x40UL) /*!< CACHECTRL CTRL: FLASH0_SLM_ENABLE (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CTRL_FLASH0_SLM_DISABLE_Pos (5UL) /*!< CACHECTRL CTRL: FLASH0_SLM_DISABLE (Bit 5) */ +#define CACHECTRL_CTRL_FLASH0_SLM_DISABLE_Msk (0x20UL) /*!< CACHECTRL CTRL: FLASH0_SLM_DISABLE (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CTRL_FLASH0_SLM_STATUS_Pos (4UL) /*!< CACHECTRL CTRL: FLASH0_SLM_STATUS (Bit 4) */ +#define CACHECTRL_CTRL_FLASH0_SLM_STATUS_Msk (0x10UL) /*!< CACHECTRL CTRL: FLASH0_SLM_STATUS (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CTRL_CACHE_READY_Pos (2UL) /*!< CACHECTRL CTRL: CACHE_READY (Bit 2) */ +#define CACHECTRL_CTRL_CACHE_READY_Msk (0x4UL) /*!< CACHECTRL CTRL: CACHE_READY (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CTRL_RESET_STAT_Pos (1UL) /*!< CACHECTRL CTRL: RESET_STAT (Bit 1) */ +#define CACHECTRL_CTRL_RESET_STAT_Msk (0x2UL) /*!< CACHECTRL CTRL: RESET_STAT (Bitfield-Mask: 0x01) */ +#define CACHECTRL_CTRL_INVALIDATE_Pos (0UL) /*!< CACHECTRL CTRL: INVALIDATE (Bit 0) */ +#define CACHECTRL_CTRL_INVALIDATE_Msk (0x1UL) /*!< CACHECTRL CTRL: INVALIDATE (Bitfield-Mask: 0x01) */ +/* ======================================================= NCR0START ======================================================= */ +#define CACHECTRL_NCR0START_ADDR_Pos (4UL) /*!< CACHECTRL NCR0START: ADDR (Bit 4) */ +#define CACHECTRL_NCR0START_ADDR_Msk (0x7fffff0UL) /*!< CACHECTRL NCR0START: ADDR (Bitfield-Mask: 0x7fffff) */ +/* ======================================================== NCR0END ======================================================== */ +#define CACHECTRL_NCR0END_ADDR_Pos (4UL) /*!< CACHECTRL NCR0END: ADDR (Bit 4) */ +#define CACHECTRL_NCR0END_ADDR_Msk (0x7fffff0UL) /*!< CACHECTRL NCR0END: ADDR (Bitfield-Mask: 0x7fffff) */ +/* ======================================================= NCR1START ======================================================= */ +#define CACHECTRL_NCR1START_ADDR_Pos (4UL) /*!< CACHECTRL NCR1START: ADDR (Bit 4) */ +#define CACHECTRL_NCR1START_ADDR_Msk (0x7fffff0UL) /*!< CACHECTRL NCR1START: ADDR (Bitfield-Mask: 0x7fffff) */ +/* ======================================================== NCR1END ======================================================== */ +#define CACHECTRL_NCR1END_ADDR_Pos (4UL) /*!< CACHECTRL NCR1END: ADDR (Bit 4) */ +#define CACHECTRL_NCR1END_ADDR_Msk (0x7fffff0UL) /*!< CACHECTRL NCR1END: ADDR (Bitfield-Mask: 0x7fffff) */ +/* ========================================================= DMON0 ========================================================= */ +#define CACHECTRL_DMON0_DACCESS_COUNT_Pos (0UL) /*!< CACHECTRL DMON0: DACCESS_COUNT (Bit 0) */ +#define CACHECTRL_DMON0_DACCESS_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL DMON0: DACCESS_COUNT (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= DMON1 ========================================================= */ +#define CACHECTRL_DMON1_DLOOKUP_COUNT_Pos (0UL) /*!< CACHECTRL DMON1: DLOOKUP_COUNT (Bit 0) */ +#define CACHECTRL_DMON1_DLOOKUP_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL DMON1: DLOOKUP_COUNT (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= DMON2 ========================================================= */ +#define CACHECTRL_DMON2_DHIT_COUNT_Pos (0UL) /*!< CACHECTRL DMON2: DHIT_COUNT (Bit 0) */ +#define CACHECTRL_DMON2_DHIT_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL DMON2: DHIT_COUNT (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= DMON3 ========================================================= */ +#define CACHECTRL_DMON3_DLINE_COUNT_Pos (0UL) /*!< CACHECTRL DMON3: DLINE_COUNT (Bit 0) */ +#define CACHECTRL_DMON3_DLINE_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL DMON3: DLINE_COUNT (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= IMON0 ========================================================= */ +#define CACHECTRL_IMON0_IACCESS_COUNT_Pos (0UL) /*!< CACHECTRL IMON0: IACCESS_COUNT (Bit 0) */ +#define CACHECTRL_IMON0_IACCESS_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL IMON0: IACCESS_COUNT (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= IMON1 ========================================================= */ +#define CACHECTRL_IMON1_ILOOKUP_COUNT_Pos (0UL) /*!< CACHECTRL IMON1: ILOOKUP_COUNT (Bit 0) */ +#define CACHECTRL_IMON1_ILOOKUP_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL IMON1: ILOOKUP_COUNT (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= IMON2 ========================================================= */ +#define CACHECTRL_IMON2_IHIT_COUNT_Pos (0UL) /*!< CACHECTRL IMON2: IHIT_COUNT (Bit 0) */ +#define CACHECTRL_IMON2_IHIT_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL IMON2: IHIT_COUNT (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= IMON3 ========================================================= */ +#define CACHECTRL_IMON3_ILINE_COUNT_Pos (0UL) /*!< CACHECTRL IMON3: ILINE_COUNT (Bit 0) */ +#define CACHECTRL_IMON3_ILINE_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL IMON3: ILINE_COUNT (Bitfield-Mask: 0xffffffff) */ + + +/* =========================================================================================================================== */ +/* ================ CLKGEN ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= CALXT ========================================================= */ +#define CLKGEN_CALXT_CALXT_Pos (0UL) /*!< CLKGEN CALXT: CALXT (Bit 0) */ +#define CLKGEN_CALXT_CALXT_Msk (0x7ffUL) /*!< CLKGEN CALXT: CALXT (Bitfield-Mask: 0x7ff) */ +/* ========================================================= CALRC ========================================================= */ +#define CLKGEN_CALRC_CALRC_Pos (0UL) /*!< CLKGEN CALRC: CALRC (Bit 0) */ +#define CLKGEN_CALRC_CALRC_Msk (0x3ffffUL) /*!< CLKGEN CALRC: CALRC (Bitfield-Mask: 0x3ffff) */ +/* ======================================================== ACALCTR ======================================================== */ +#define CLKGEN_ACALCTR_ACALCTR_Pos (0UL) /*!< CLKGEN ACALCTR: ACALCTR (Bit 0) */ +#define CLKGEN_ACALCTR_ACALCTR_Msk (0xffffffUL) /*!< CLKGEN ACALCTR: ACALCTR (Bitfield-Mask: 0xffffff) */ +/* ========================================================= OCTRL ========================================================= */ +#define CLKGEN_OCTRL_ACAL_Pos (8UL) /*!< CLKGEN OCTRL: ACAL (Bit 8) */ +#define CLKGEN_OCTRL_ACAL_Msk (0x700UL) /*!< CLKGEN OCTRL: ACAL (Bitfield-Mask: 0x07) */ +#define CLKGEN_OCTRL_OSEL_Pos (7UL) /*!< CLKGEN OCTRL: OSEL (Bit 7) */ +#define CLKGEN_OCTRL_OSEL_Msk (0x80UL) /*!< CLKGEN OCTRL: OSEL (Bitfield-Mask: 0x01) */ +#define CLKGEN_OCTRL_FOS_Pos (6UL) /*!< CLKGEN OCTRL: FOS (Bit 6) */ +#define CLKGEN_OCTRL_FOS_Msk (0x40UL) /*!< CLKGEN OCTRL: FOS (Bitfield-Mask: 0x01) */ +#define CLKGEN_OCTRL_STOPRC_Pos (1UL) /*!< CLKGEN OCTRL: STOPRC (Bit 1) */ +#define CLKGEN_OCTRL_STOPRC_Msk (0x2UL) /*!< CLKGEN OCTRL: STOPRC (Bitfield-Mask: 0x01) */ +#define CLKGEN_OCTRL_STOPXT_Pos (0UL) /*!< CLKGEN OCTRL: STOPXT (Bit 0) */ +#define CLKGEN_OCTRL_STOPXT_Msk (0x1UL) /*!< CLKGEN OCTRL: STOPXT (Bitfield-Mask: 0x01) */ +/* ======================================================== CLKOUT ========================================================= */ +#define CLKGEN_CLKOUT_CKEN_Pos (7UL) /*!< CLKGEN CLKOUT: CKEN (Bit 7) */ +#define CLKGEN_CLKOUT_CKEN_Msk (0x80UL) /*!< CLKGEN CLKOUT: CKEN (Bitfield-Mask: 0x01) */ +#define CLKGEN_CLKOUT_CKSEL_Pos (0UL) /*!< CLKGEN CLKOUT: CKSEL (Bit 0) */ +#define CLKGEN_CLKOUT_CKSEL_Msk (0x3fUL) /*!< CLKGEN CLKOUT: CKSEL (Bitfield-Mask: 0x3f) */ +/* ======================================================== CLKKEY ========================================================= */ +#define CLKGEN_CLKKEY_CLKKEY_Pos (0UL) /*!< CLKGEN CLKKEY: CLKKEY (Bit 0) */ +#define CLKGEN_CLKKEY_CLKKEY_Msk (0xffffffffUL) /*!< CLKGEN CLKKEY: CLKKEY (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= CCTRL ========================================================= */ +#define CLKGEN_CCTRL_CORESEL_Pos (0UL) /*!< CLKGEN CCTRL: CORESEL (Bit 0) */ +#define CLKGEN_CCTRL_CORESEL_Msk (0x1UL) /*!< CLKGEN CCTRL: CORESEL (Bitfield-Mask: 0x01) */ +/* ======================================================== STATUS ========================================================= */ +#define CLKGEN_STATUS_OSCF_Pos (1UL) /*!< CLKGEN STATUS: OSCF (Bit 1) */ +#define CLKGEN_STATUS_OSCF_Msk (0x2UL) /*!< CLKGEN STATUS: OSCF (Bitfield-Mask: 0x01) */ +#define CLKGEN_STATUS_OMODE_Pos (0UL) /*!< CLKGEN STATUS: OMODE (Bit 0) */ +#define CLKGEN_STATUS_OMODE_Msk (0x1UL) /*!< CLKGEN STATUS: OMODE (Bitfield-Mask: 0x01) */ +/* ========================================================= HFADJ ========================================================= */ +#define CLKGEN_HFADJ_HFADJGAIN_Pos (21UL) /*!< CLKGEN HFADJ: HFADJGAIN (Bit 21) */ +#define CLKGEN_HFADJ_HFADJGAIN_Msk (0xe00000UL) /*!< CLKGEN HFADJ: HFADJGAIN (Bitfield-Mask: 0x07) */ +#define CLKGEN_HFADJ_HFWARMUP_Pos (20UL) /*!< CLKGEN HFADJ: HFWARMUP (Bit 20) */ +#define CLKGEN_HFADJ_HFWARMUP_Msk (0x100000UL) /*!< CLKGEN HFADJ: HFWARMUP (Bitfield-Mask: 0x01) */ +#define CLKGEN_HFADJ_HFXTADJ_Pos (8UL) /*!< CLKGEN HFADJ: HFXTADJ (Bit 8) */ +#define CLKGEN_HFADJ_HFXTADJ_Msk (0xfff00UL) /*!< CLKGEN HFADJ: HFXTADJ (Bitfield-Mask: 0xfff) */ +#define CLKGEN_HFADJ_HFADJCK_Pos (1UL) /*!< CLKGEN HFADJ: HFADJCK (Bit 1) */ +#define CLKGEN_HFADJ_HFADJCK_Msk (0xeUL) /*!< CLKGEN HFADJ: HFADJCK (Bitfield-Mask: 0x07) */ +#define CLKGEN_HFADJ_HFADJEN_Pos (0UL) /*!< CLKGEN HFADJ: HFADJEN (Bit 0) */ +#define CLKGEN_HFADJ_HFADJEN_Msk (0x1UL) /*!< CLKGEN HFADJ: HFADJEN (Bitfield-Mask: 0x01) */ +/* ====================================================== CLOCKENSTAT ====================================================== */ +#define CLKGEN_CLOCKENSTAT_CLOCKENSTAT_Pos (0UL) /*!< CLKGEN CLOCKENSTAT: CLOCKENSTAT (Bit 0) */ +#define CLKGEN_CLOCKENSTAT_CLOCKENSTAT_Msk (0xffffffffUL) /*!< CLKGEN CLOCKENSTAT: CLOCKENSTAT (Bitfield-Mask: 0xffffffff) */ +/* ===================================================== CLOCKEN2STAT ====================================================== */ +#define CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_Pos (0UL) /*!< CLKGEN CLOCKEN2STAT: CLOCKEN2STAT (Bit 0) */ +#define CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_Msk (0xffffffffUL) /*!< CLKGEN CLOCKEN2STAT: CLOCKEN2STAT (Bitfield-Mask: 0xffffffff) */ +/* ===================================================== CLOCKEN3STAT ====================================================== */ +#define CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_Pos (0UL) /*!< CLKGEN CLOCKEN3STAT: CLOCKEN3STAT (Bit 0) */ +#define CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_Msk (0xffffffffUL) /*!< CLKGEN CLOCKEN3STAT: CLOCKEN3STAT (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= FREQCTRL ======================================================== */ +#define CLKGEN_FREQCTRL_BURSTSTATUS_Pos (2UL) /*!< CLKGEN FREQCTRL: BURSTSTATUS (Bit 2) */ +#define CLKGEN_FREQCTRL_BURSTSTATUS_Msk (0x4UL) /*!< CLKGEN FREQCTRL: BURSTSTATUS (Bitfield-Mask: 0x01) */ +#define CLKGEN_FREQCTRL_BURSTACK_Pos (1UL) /*!< CLKGEN FREQCTRL: BURSTACK (Bit 1) */ +#define CLKGEN_FREQCTRL_BURSTACK_Msk (0x2UL) /*!< CLKGEN FREQCTRL: BURSTACK (Bitfield-Mask: 0x01) */ +#define CLKGEN_FREQCTRL_BURSTREQ_Pos (0UL) /*!< CLKGEN FREQCTRL: BURSTREQ (Bit 0) */ +#define CLKGEN_FREQCTRL_BURSTREQ_Msk (0x1UL) /*!< CLKGEN FREQCTRL: BURSTREQ (Bitfield-Mask: 0x01) */ +/* ===================================================== BLEBUCKTONADJ ===================================================== */ +#define CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_Pos (27UL) /*!< CLKGEN BLEBUCKTONADJ: ZEROLENDETECTEN (Bit 27) */ +#define CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_Msk (0x8000000UL) /*!< CLKGEN BLEBUCKTONADJ: ZEROLENDETECTEN (Bitfield-Mask: 0x01) */ +#define CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Pos (23UL) /*!< CLKGEN BLEBUCKTONADJ: ZEROLENDETECTTRIM (Bit 23) */ +#define CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Msk (0x7800000UL) /*!< CLKGEN BLEBUCKTONADJ: ZEROLENDETECTTRIM (Bitfield-Mask: 0x0f) */ +#define CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_Pos (22UL) /*!< CLKGEN BLEBUCKTONADJ: TONADJUSTEN (Bit 22) */ +#define CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_Msk (0x400000UL) /*!< CLKGEN BLEBUCKTONADJ: TONADJUSTEN (Bitfield-Mask: 0x01) */ +#define CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_Pos (20UL) /*!< CLKGEN BLEBUCKTONADJ: TONADJUSTPERIOD (Bit 20) */ +#define CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_Msk (0x300000UL) /*!< CLKGEN BLEBUCKTONADJ: TONADJUSTPERIOD (Bitfield-Mask: 0x03) */ +#define CLKGEN_BLEBUCKTONADJ_TONHIGHTHRESHOLD_Pos (10UL) /*!< CLKGEN BLEBUCKTONADJ: TONHIGHTHRESHOLD (Bit 10) */ +#define CLKGEN_BLEBUCKTONADJ_TONHIGHTHRESHOLD_Msk (0xffc00UL) /*!< CLKGEN BLEBUCKTONADJ: TONHIGHTHRESHOLD (Bitfield-Mask: 0x3ff) */ +#define CLKGEN_BLEBUCKTONADJ_TONLOWTHRESHOLD_Pos (0UL) /*!< CLKGEN BLEBUCKTONADJ: TONLOWTHRESHOLD (Bit 0) */ +#define CLKGEN_BLEBUCKTONADJ_TONLOWTHRESHOLD_Msk (0x3ffUL) /*!< CLKGEN BLEBUCKTONADJ: TONLOWTHRESHOLD (Bitfield-Mask: 0x3ff) */ +/* ======================================================= INTRPTEN ======================================================== */ +#define CLKGEN_INTRPTEN_OF_Pos (2UL) /*!< CLKGEN INTRPTEN: OF (Bit 2) */ +#define CLKGEN_INTRPTEN_OF_Msk (0x4UL) /*!< CLKGEN INTRPTEN: OF (Bitfield-Mask: 0x01) */ +#define CLKGEN_INTRPTEN_ACC_Pos (1UL) /*!< CLKGEN INTRPTEN: ACC (Bit 1) */ +#define CLKGEN_INTRPTEN_ACC_Msk (0x2UL) /*!< CLKGEN INTRPTEN: ACC (Bitfield-Mask: 0x01) */ +#define CLKGEN_INTRPTEN_ACF_Pos (0UL) /*!< CLKGEN INTRPTEN: ACF (Bit 0) */ +#define CLKGEN_INTRPTEN_ACF_Msk (0x1UL) /*!< CLKGEN INTRPTEN: ACF (Bitfield-Mask: 0x01) */ +/* ====================================================== INTRPTSTAT ======================================================= */ +#define CLKGEN_INTRPTSTAT_OF_Pos (2UL) /*!< CLKGEN INTRPTSTAT: OF (Bit 2) */ +#define CLKGEN_INTRPTSTAT_OF_Msk (0x4UL) /*!< CLKGEN INTRPTSTAT: OF (Bitfield-Mask: 0x01) */ +#define CLKGEN_INTRPTSTAT_ACC_Pos (1UL) /*!< CLKGEN INTRPTSTAT: ACC (Bit 1) */ +#define CLKGEN_INTRPTSTAT_ACC_Msk (0x2UL) /*!< CLKGEN INTRPTSTAT: ACC (Bitfield-Mask: 0x01) */ +#define CLKGEN_INTRPTSTAT_ACF_Pos (0UL) /*!< CLKGEN INTRPTSTAT: ACF (Bit 0) */ +#define CLKGEN_INTRPTSTAT_ACF_Msk (0x1UL) /*!< CLKGEN INTRPTSTAT: ACF (Bitfield-Mask: 0x01) */ +/* ======================================================= INTRPTCLR ======================================================= */ +#define CLKGEN_INTRPTCLR_OF_Pos (2UL) /*!< CLKGEN INTRPTCLR: OF (Bit 2) */ +#define CLKGEN_INTRPTCLR_OF_Msk (0x4UL) /*!< CLKGEN INTRPTCLR: OF (Bitfield-Mask: 0x01) */ +#define CLKGEN_INTRPTCLR_ACC_Pos (1UL) /*!< CLKGEN INTRPTCLR: ACC (Bit 1) */ +#define CLKGEN_INTRPTCLR_ACC_Msk (0x2UL) /*!< CLKGEN INTRPTCLR: ACC (Bitfield-Mask: 0x01) */ +#define CLKGEN_INTRPTCLR_ACF_Pos (0UL) /*!< CLKGEN INTRPTCLR: ACF (Bit 0) */ +#define CLKGEN_INTRPTCLR_ACF_Msk (0x1UL) /*!< CLKGEN INTRPTCLR: ACF (Bitfield-Mask: 0x01) */ +/* ======================================================= INTRPTSET ======================================================= */ +#define CLKGEN_INTRPTSET_OF_Pos (2UL) /*!< CLKGEN INTRPTSET: OF (Bit 2) */ +#define CLKGEN_INTRPTSET_OF_Msk (0x4UL) /*!< CLKGEN INTRPTSET: OF (Bitfield-Mask: 0x01) */ +#define CLKGEN_INTRPTSET_ACC_Pos (1UL) /*!< CLKGEN INTRPTSET: ACC (Bit 1) */ +#define CLKGEN_INTRPTSET_ACC_Msk (0x2UL) /*!< CLKGEN INTRPTSET: ACC (Bitfield-Mask: 0x01) */ +#define CLKGEN_INTRPTSET_ACF_Pos (0UL) /*!< CLKGEN INTRPTSET: ACF (Bit 0) */ +#define CLKGEN_INTRPTSET_ACF_Msk (0x1UL) /*!< CLKGEN INTRPTSET: ACF (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ CTIMER ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= TMR0 ========================================================== */ +#define CTIMER_TMR0_CTTMRB0_Pos (16UL) /*!< CTIMER TMR0: CTTMRB0 (Bit 16) */ +#define CTIMER_TMR0_CTTMRB0_Msk (0xffff0000UL) /*!< CTIMER TMR0: CTTMRB0 (Bitfield-Mask: 0xffff) */ +#define CTIMER_TMR0_CTTMRA0_Pos (0UL) /*!< CTIMER TMR0: CTTMRA0 (Bit 0) */ +#define CTIMER_TMR0_CTTMRA0_Msk (0xffffUL) /*!< CTIMER TMR0: CTTMRA0 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRA0 ========================================================= */ +#define CTIMER_CMPRA0_CMPR1A0_Pos (16UL) /*!< CTIMER CMPRA0: CMPR1A0 (Bit 16) */ +#define CTIMER_CMPRA0_CMPR1A0_Msk (0xffff0000UL) /*!< CTIMER CMPRA0: CMPR1A0 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRA0_CMPR0A0_Pos (0UL) /*!< CTIMER CMPRA0: CMPR0A0 (Bit 0) */ +#define CTIMER_CMPRA0_CMPR0A0_Msk (0xffffUL) /*!< CTIMER CMPRA0: CMPR0A0 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRB0 ========================================================= */ +#define CTIMER_CMPRB0_CMPR1B0_Pos (16UL) /*!< CTIMER CMPRB0: CMPR1B0 (Bit 16) */ +#define CTIMER_CMPRB0_CMPR1B0_Msk (0xffff0000UL) /*!< CTIMER CMPRB0: CMPR1B0 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRB0_CMPR0B0_Pos (0UL) /*!< CTIMER CMPRB0: CMPR0B0 (Bit 0) */ +#define CTIMER_CMPRB0_CMPR0B0_Msk (0xffffUL) /*!< CTIMER CMPRB0: CMPR0B0 (Bitfield-Mask: 0xffff) */ +/* ========================================================= CTRL0 ========================================================= */ +#define CTIMER_CTRL0_CTLINK0_Pos (31UL) /*!< CTIMER CTRL0: CTLINK0 (Bit 31) */ +#define CTIMER_CTRL0_CTLINK0_Msk (0x80000000UL) /*!< CTIMER CTRL0: CTLINK0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRB0POL_Pos (28UL) /*!< CTIMER CTRL0: TMRB0POL (Bit 28) */ +#define CTIMER_CTRL0_TMRB0POL_Msk (0x10000000UL) /*!< CTIMER CTRL0: TMRB0POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRB0CLR_Pos (27UL) /*!< CTIMER CTRL0: TMRB0CLR (Bit 27) */ +#define CTIMER_CTRL0_TMRB0CLR_Msk (0x8000000UL) /*!< CTIMER CTRL0: TMRB0CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRB0IE1_Pos (26UL) /*!< CTIMER CTRL0: TMRB0IE1 (Bit 26) */ +#define CTIMER_CTRL0_TMRB0IE1_Msk (0x4000000UL) /*!< CTIMER CTRL0: TMRB0IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRB0IE0_Pos (25UL) /*!< CTIMER CTRL0: TMRB0IE0 (Bit 25) */ +#define CTIMER_CTRL0_TMRB0IE0_Msk (0x2000000UL) /*!< CTIMER CTRL0: TMRB0IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRB0FN_Pos (22UL) /*!< CTIMER CTRL0: TMRB0FN (Bit 22) */ +#define CTIMER_CTRL0_TMRB0FN_Msk (0x1c00000UL) /*!< CTIMER CTRL0: TMRB0FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL0_TMRB0CLK_Pos (17UL) /*!< CTIMER CTRL0: TMRB0CLK (Bit 17) */ +#define CTIMER_CTRL0_TMRB0CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL0: TMRB0CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL0_TMRB0EN_Pos (16UL) /*!< CTIMER CTRL0: TMRB0EN (Bit 16) */ +#define CTIMER_CTRL0_TMRB0EN_Msk (0x10000UL) /*!< CTIMER CTRL0: TMRB0EN (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRA0POL_Pos (12UL) /*!< CTIMER CTRL0: TMRA0POL (Bit 12) */ +#define CTIMER_CTRL0_TMRA0POL_Msk (0x1000UL) /*!< CTIMER CTRL0: TMRA0POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRA0CLR_Pos (11UL) /*!< CTIMER CTRL0: TMRA0CLR (Bit 11) */ +#define CTIMER_CTRL0_TMRA0CLR_Msk (0x800UL) /*!< CTIMER CTRL0: TMRA0CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRA0IE1_Pos (10UL) /*!< CTIMER CTRL0: TMRA0IE1 (Bit 10) */ +#define CTIMER_CTRL0_TMRA0IE1_Msk (0x400UL) /*!< CTIMER CTRL0: TMRA0IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRA0IE0_Pos (9UL) /*!< CTIMER CTRL0: TMRA0IE0 (Bit 9) */ +#define CTIMER_CTRL0_TMRA0IE0_Msk (0x200UL) /*!< CTIMER CTRL0: TMRA0IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL0_TMRA0FN_Pos (6UL) /*!< CTIMER CTRL0: TMRA0FN (Bit 6) */ +#define CTIMER_CTRL0_TMRA0FN_Msk (0x1c0UL) /*!< CTIMER CTRL0: TMRA0FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL0_TMRA0CLK_Pos (1UL) /*!< CTIMER CTRL0: TMRA0CLK (Bit 1) */ +#define CTIMER_CTRL0_TMRA0CLK_Msk (0x3eUL) /*!< CTIMER CTRL0: TMRA0CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL0_TMRA0EN_Pos (0UL) /*!< CTIMER CTRL0: TMRA0EN (Bit 0) */ +#define CTIMER_CTRL0_TMRA0EN_Msk (0x1UL) /*!< CTIMER CTRL0: TMRA0EN (Bitfield-Mask: 0x01) */ +/* ======================================================= CMPRAUXA0 ======================================================= */ +#define CTIMER_CMPRAUXA0_CMPR3A0_Pos (16UL) /*!< CTIMER CMPRAUXA0: CMPR3A0 (Bit 16) */ +#define CTIMER_CMPRAUXA0_CMPR3A0_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA0: CMPR3A0 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXA0_CMPR2A0_Pos (0UL) /*!< CTIMER CMPRAUXA0: CMPR2A0 (Bit 0) */ +#define CTIMER_CMPRAUXA0_CMPR2A0_Msk (0xffffUL) /*!< CTIMER CMPRAUXA0: CMPR2A0 (Bitfield-Mask: 0xffff) */ +/* ======================================================= CMPRAUXB0 ======================================================= */ +#define CTIMER_CMPRAUXB0_CMPR3B0_Pos (16UL) /*!< CTIMER CMPRAUXB0: CMPR3B0 (Bit 16) */ +#define CTIMER_CMPRAUXB0_CMPR3B0_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB0: CMPR3B0 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXB0_CMPR2B0_Pos (0UL) /*!< CTIMER CMPRAUXB0: CMPR2B0 (Bit 0) */ +#define CTIMER_CMPRAUXB0_CMPR2B0_Msk (0xffffUL) /*!< CTIMER CMPRAUXB0: CMPR2B0 (Bitfield-Mask: 0xffff) */ +/* ========================================================= AUX0 ========================================================== */ +#define CTIMER_AUX0_TMRB0EN23_Pos (30UL) /*!< CTIMER AUX0: TMRB0EN23 (Bit 30) */ +#define CTIMER_AUX0_TMRB0EN23_Msk (0x40000000UL) /*!< CTIMER AUX0: TMRB0EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX0_TMRB0POL23_Pos (29UL) /*!< CTIMER AUX0: TMRB0POL23 (Bit 29) */ +#define CTIMER_AUX0_TMRB0POL23_Msk (0x20000000UL) /*!< CTIMER AUX0: TMRB0POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX0_TMRB0TINV_Pos (28UL) /*!< CTIMER AUX0: TMRB0TINV (Bit 28) */ +#define CTIMER_AUX0_TMRB0TINV_Msk (0x10000000UL) /*!< CTIMER AUX0: TMRB0TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX0_TMRB0NOSYNC_Pos (27UL) /*!< CTIMER AUX0: TMRB0NOSYNC (Bit 27) */ +#define CTIMER_AUX0_TMRB0NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX0: TMRB0NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX0_TMRB0TRIG_Pos (23UL) /*!< CTIMER AUX0: TMRB0TRIG (Bit 23) */ +#define CTIMER_AUX0_TMRB0TRIG_Msk (0x7800000UL) /*!< CTIMER AUX0: TMRB0TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX0_TMRB0LMT_Pos (16UL) /*!< CTIMER AUX0: TMRB0LMT (Bit 16) */ +#define CTIMER_AUX0_TMRB0LMT_Msk (0x3f0000UL) /*!< CTIMER AUX0: TMRB0LMT (Bitfield-Mask: 0x3f) */ +#define CTIMER_AUX0_TMRA0EN23_Pos (14UL) /*!< CTIMER AUX0: TMRA0EN23 (Bit 14) */ +#define CTIMER_AUX0_TMRA0EN23_Msk (0x4000UL) /*!< CTIMER AUX0: TMRA0EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX0_TMRA0POL23_Pos (13UL) /*!< CTIMER AUX0: TMRA0POL23 (Bit 13) */ +#define CTIMER_AUX0_TMRA0POL23_Msk (0x2000UL) /*!< CTIMER AUX0: TMRA0POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX0_TMRA0TINV_Pos (12UL) /*!< CTIMER AUX0: TMRA0TINV (Bit 12) */ +#define CTIMER_AUX0_TMRA0TINV_Msk (0x1000UL) /*!< CTIMER AUX0: TMRA0TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX0_TMRA0NOSYNC_Pos (11UL) /*!< CTIMER AUX0: TMRA0NOSYNC (Bit 11) */ +#define CTIMER_AUX0_TMRA0NOSYNC_Msk (0x800UL) /*!< CTIMER AUX0: TMRA0NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX0_TMRA0TRIG_Pos (7UL) /*!< CTIMER AUX0: TMRA0TRIG (Bit 7) */ +#define CTIMER_AUX0_TMRA0TRIG_Msk (0x780UL) /*!< CTIMER AUX0: TMRA0TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX0_TMRA0LMT_Pos (0UL) /*!< CTIMER AUX0: TMRA0LMT (Bit 0) */ +#define CTIMER_AUX0_TMRA0LMT_Msk (0x7fUL) /*!< CTIMER AUX0: TMRA0LMT (Bitfield-Mask: 0x7f) */ +/* ========================================================= TMR1 ========================================================== */ +#define CTIMER_TMR1_CTTMRB1_Pos (16UL) /*!< CTIMER TMR1: CTTMRB1 (Bit 16) */ +#define CTIMER_TMR1_CTTMRB1_Msk (0xffff0000UL) /*!< CTIMER TMR1: CTTMRB1 (Bitfield-Mask: 0xffff) */ +#define CTIMER_TMR1_CTTMRA1_Pos (0UL) /*!< CTIMER TMR1: CTTMRA1 (Bit 0) */ +#define CTIMER_TMR1_CTTMRA1_Msk (0xffffUL) /*!< CTIMER TMR1: CTTMRA1 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRA1 ========================================================= */ +#define CTIMER_CMPRA1_CMPR1A1_Pos (16UL) /*!< CTIMER CMPRA1: CMPR1A1 (Bit 16) */ +#define CTIMER_CMPRA1_CMPR1A1_Msk (0xffff0000UL) /*!< CTIMER CMPRA1: CMPR1A1 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRA1_CMPR0A1_Pos (0UL) /*!< CTIMER CMPRA1: CMPR0A1 (Bit 0) */ +#define CTIMER_CMPRA1_CMPR0A1_Msk (0xffffUL) /*!< CTIMER CMPRA1: CMPR0A1 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRB1 ========================================================= */ +#define CTIMER_CMPRB1_CMPR1B1_Pos (16UL) /*!< CTIMER CMPRB1: CMPR1B1 (Bit 16) */ +#define CTIMER_CMPRB1_CMPR1B1_Msk (0xffff0000UL) /*!< CTIMER CMPRB1: CMPR1B1 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRB1_CMPR0B1_Pos (0UL) /*!< CTIMER CMPRB1: CMPR0B1 (Bit 0) */ +#define CTIMER_CMPRB1_CMPR0B1_Msk (0xffffUL) /*!< CTIMER CMPRB1: CMPR0B1 (Bitfield-Mask: 0xffff) */ +/* ========================================================= CTRL1 ========================================================= */ +#define CTIMER_CTRL1_CTLINK1_Pos (31UL) /*!< CTIMER CTRL1: CTLINK1 (Bit 31) */ +#define CTIMER_CTRL1_CTLINK1_Msk (0x80000000UL) /*!< CTIMER CTRL1: CTLINK1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRB1POL_Pos (28UL) /*!< CTIMER CTRL1: TMRB1POL (Bit 28) */ +#define CTIMER_CTRL1_TMRB1POL_Msk (0x10000000UL) /*!< CTIMER CTRL1: TMRB1POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRB1CLR_Pos (27UL) /*!< CTIMER CTRL1: TMRB1CLR (Bit 27) */ +#define CTIMER_CTRL1_TMRB1CLR_Msk (0x8000000UL) /*!< CTIMER CTRL1: TMRB1CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRB1IE1_Pos (26UL) /*!< CTIMER CTRL1: TMRB1IE1 (Bit 26) */ +#define CTIMER_CTRL1_TMRB1IE1_Msk (0x4000000UL) /*!< CTIMER CTRL1: TMRB1IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRB1IE0_Pos (25UL) /*!< CTIMER CTRL1: TMRB1IE0 (Bit 25) */ +#define CTIMER_CTRL1_TMRB1IE0_Msk (0x2000000UL) /*!< CTIMER CTRL1: TMRB1IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRB1FN_Pos (22UL) /*!< CTIMER CTRL1: TMRB1FN (Bit 22) */ +#define CTIMER_CTRL1_TMRB1FN_Msk (0x1c00000UL) /*!< CTIMER CTRL1: TMRB1FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL1_TMRB1CLK_Pos (17UL) /*!< CTIMER CTRL1: TMRB1CLK (Bit 17) */ +#define CTIMER_CTRL1_TMRB1CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL1: TMRB1CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL1_TMRB1EN_Pos (16UL) /*!< CTIMER CTRL1: TMRB1EN (Bit 16) */ +#define CTIMER_CTRL1_TMRB1EN_Msk (0x10000UL) /*!< CTIMER CTRL1: TMRB1EN (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRA1POL_Pos (12UL) /*!< CTIMER CTRL1: TMRA1POL (Bit 12) */ +#define CTIMER_CTRL1_TMRA1POL_Msk (0x1000UL) /*!< CTIMER CTRL1: TMRA1POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRA1CLR_Pos (11UL) /*!< CTIMER CTRL1: TMRA1CLR (Bit 11) */ +#define CTIMER_CTRL1_TMRA1CLR_Msk (0x800UL) /*!< CTIMER CTRL1: TMRA1CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRA1IE1_Pos (10UL) /*!< CTIMER CTRL1: TMRA1IE1 (Bit 10) */ +#define CTIMER_CTRL1_TMRA1IE1_Msk (0x400UL) /*!< CTIMER CTRL1: TMRA1IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRA1IE0_Pos (9UL) /*!< CTIMER CTRL1: TMRA1IE0 (Bit 9) */ +#define CTIMER_CTRL1_TMRA1IE0_Msk (0x200UL) /*!< CTIMER CTRL1: TMRA1IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL1_TMRA1FN_Pos (6UL) /*!< CTIMER CTRL1: TMRA1FN (Bit 6) */ +#define CTIMER_CTRL1_TMRA1FN_Msk (0x1c0UL) /*!< CTIMER CTRL1: TMRA1FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL1_TMRA1CLK_Pos (1UL) /*!< CTIMER CTRL1: TMRA1CLK (Bit 1) */ +#define CTIMER_CTRL1_TMRA1CLK_Msk (0x3eUL) /*!< CTIMER CTRL1: TMRA1CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL1_TMRA1EN_Pos (0UL) /*!< CTIMER CTRL1: TMRA1EN (Bit 0) */ +#define CTIMER_CTRL1_TMRA1EN_Msk (0x1UL) /*!< CTIMER CTRL1: TMRA1EN (Bitfield-Mask: 0x01) */ +/* ======================================================= CMPRAUXA1 ======================================================= */ +#define CTIMER_CMPRAUXA1_CMPR3A1_Pos (16UL) /*!< CTIMER CMPRAUXA1: CMPR3A1 (Bit 16) */ +#define CTIMER_CMPRAUXA1_CMPR3A1_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA1: CMPR3A1 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXA1_CMPR2A1_Pos (0UL) /*!< CTIMER CMPRAUXA1: CMPR2A1 (Bit 0) */ +#define CTIMER_CMPRAUXA1_CMPR2A1_Msk (0xffffUL) /*!< CTIMER CMPRAUXA1: CMPR2A1 (Bitfield-Mask: 0xffff) */ +/* ======================================================= CMPRAUXB1 ======================================================= */ +#define CTIMER_CMPRAUXB1_CMPR3B1_Pos (16UL) /*!< CTIMER CMPRAUXB1: CMPR3B1 (Bit 16) */ +#define CTIMER_CMPRAUXB1_CMPR3B1_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB1: CMPR3B1 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXB1_CMPR2B1_Pos (0UL) /*!< CTIMER CMPRAUXB1: CMPR2B1 (Bit 0) */ +#define CTIMER_CMPRAUXB1_CMPR2B1_Msk (0xffffUL) /*!< CTIMER CMPRAUXB1: CMPR2B1 (Bitfield-Mask: 0xffff) */ +/* ========================================================= AUX1 ========================================================== */ +#define CTIMER_AUX1_TMRB1EN23_Pos (30UL) /*!< CTIMER AUX1: TMRB1EN23 (Bit 30) */ +#define CTIMER_AUX1_TMRB1EN23_Msk (0x40000000UL) /*!< CTIMER AUX1: TMRB1EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX1_TMRB1POL23_Pos (29UL) /*!< CTIMER AUX1: TMRB1POL23 (Bit 29) */ +#define CTIMER_AUX1_TMRB1POL23_Msk (0x20000000UL) /*!< CTIMER AUX1: TMRB1POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX1_TMRB1TINV_Pos (28UL) /*!< CTIMER AUX1: TMRB1TINV (Bit 28) */ +#define CTIMER_AUX1_TMRB1TINV_Msk (0x10000000UL) /*!< CTIMER AUX1: TMRB1TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX1_TMRB1NOSYNC_Pos (27UL) /*!< CTIMER AUX1: TMRB1NOSYNC (Bit 27) */ +#define CTIMER_AUX1_TMRB1NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX1: TMRB1NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX1_TMRB1TRIG_Pos (23UL) /*!< CTIMER AUX1: TMRB1TRIG (Bit 23) */ +#define CTIMER_AUX1_TMRB1TRIG_Msk (0x7800000UL) /*!< CTIMER AUX1: TMRB1TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX1_TMRB1LMT_Pos (16UL) /*!< CTIMER AUX1: TMRB1LMT (Bit 16) */ +#define CTIMER_AUX1_TMRB1LMT_Msk (0x3f0000UL) /*!< CTIMER AUX1: TMRB1LMT (Bitfield-Mask: 0x3f) */ +#define CTIMER_AUX1_TMRA1EN23_Pos (14UL) /*!< CTIMER AUX1: TMRA1EN23 (Bit 14) */ +#define CTIMER_AUX1_TMRA1EN23_Msk (0x4000UL) /*!< CTIMER AUX1: TMRA1EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX1_TMRA1POL23_Pos (13UL) /*!< CTIMER AUX1: TMRA1POL23 (Bit 13) */ +#define CTIMER_AUX1_TMRA1POL23_Msk (0x2000UL) /*!< CTIMER AUX1: TMRA1POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX1_TMRA1TINV_Pos (12UL) /*!< CTIMER AUX1: TMRA1TINV (Bit 12) */ +#define CTIMER_AUX1_TMRA1TINV_Msk (0x1000UL) /*!< CTIMER AUX1: TMRA1TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX1_TMRA1NOSYNC_Pos (11UL) /*!< CTIMER AUX1: TMRA1NOSYNC (Bit 11) */ +#define CTIMER_AUX1_TMRA1NOSYNC_Msk (0x800UL) /*!< CTIMER AUX1: TMRA1NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX1_TMRA1TRIG_Pos (7UL) /*!< CTIMER AUX1: TMRA1TRIG (Bit 7) */ +#define CTIMER_AUX1_TMRA1TRIG_Msk (0x780UL) /*!< CTIMER AUX1: TMRA1TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX1_TMRA1LMT_Pos (0UL) /*!< CTIMER AUX1: TMRA1LMT (Bit 0) */ +#define CTIMER_AUX1_TMRA1LMT_Msk (0x7fUL) /*!< CTIMER AUX1: TMRA1LMT (Bitfield-Mask: 0x7f) */ +/* ========================================================= TMR2 ========================================================== */ +#define CTIMER_TMR2_CTTMRB2_Pos (16UL) /*!< CTIMER TMR2: CTTMRB2 (Bit 16) */ +#define CTIMER_TMR2_CTTMRB2_Msk (0xffff0000UL) /*!< CTIMER TMR2: CTTMRB2 (Bitfield-Mask: 0xffff) */ +#define CTIMER_TMR2_CTTMRA2_Pos (0UL) /*!< CTIMER TMR2: CTTMRA2 (Bit 0) */ +#define CTIMER_TMR2_CTTMRA2_Msk (0xffffUL) /*!< CTIMER TMR2: CTTMRA2 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRA2 ========================================================= */ +#define CTIMER_CMPRA2_CMPR1A2_Pos (16UL) /*!< CTIMER CMPRA2: CMPR1A2 (Bit 16) */ +#define CTIMER_CMPRA2_CMPR1A2_Msk (0xffff0000UL) /*!< CTIMER CMPRA2: CMPR1A2 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRA2_CMPR0A2_Pos (0UL) /*!< CTIMER CMPRA2: CMPR0A2 (Bit 0) */ +#define CTIMER_CMPRA2_CMPR0A2_Msk (0xffffUL) /*!< CTIMER CMPRA2: CMPR0A2 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRB2 ========================================================= */ +#define CTIMER_CMPRB2_CMPR1B2_Pos (16UL) /*!< CTIMER CMPRB2: CMPR1B2 (Bit 16) */ +#define CTIMER_CMPRB2_CMPR1B2_Msk (0xffff0000UL) /*!< CTIMER CMPRB2: CMPR1B2 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRB2_CMPR0B2_Pos (0UL) /*!< CTIMER CMPRB2: CMPR0B2 (Bit 0) */ +#define CTIMER_CMPRB2_CMPR0B2_Msk (0xffffUL) /*!< CTIMER CMPRB2: CMPR0B2 (Bitfield-Mask: 0xffff) */ +/* ========================================================= CTRL2 ========================================================= */ +#define CTIMER_CTRL2_CTLINK2_Pos (31UL) /*!< CTIMER CTRL2: CTLINK2 (Bit 31) */ +#define CTIMER_CTRL2_CTLINK2_Msk (0x80000000UL) /*!< CTIMER CTRL2: CTLINK2 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRB2POL_Pos (28UL) /*!< CTIMER CTRL2: TMRB2POL (Bit 28) */ +#define CTIMER_CTRL2_TMRB2POL_Msk (0x10000000UL) /*!< CTIMER CTRL2: TMRB2POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRB2CLR_Pos (27UL) /*!< CTIMER CTRL2: TMRB2CLR (Bit 27) */ +#define CTIMER_CTRL2_TMRB2CLR_Msk (0x8000000UL) /*!< CTIMER CTRL2: TMRB2CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRB2IE1_Pos (26UL) /*!< CTIMER CTRL2: TMRB2IE1 (Bit 26) */ +#define CTIMER_CTRL2_TMRB2IE1_Msk (0x4000000UL) /*!< CTIMER CTRL2: TMRB2IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRB2IE0_Pos (25UL) /*!< CTIMER CTRL2: TMRB2IE0 (Bit 25) */ +#define CTIMER_CTRL2_TMRB2IE0_Msk (0x2000000UL) /*!< CTIMER CTRL2: TMRB2IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRB2FN_Pos (22UL) /*!< CTIMER CTRL2: TMRB2FN (Bit 22) */ +#define CTIMER_CTRL2_TMRB2FN_Msk (0x1c00000UL) /*!< CTIMER CTRL2: TMRB2FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL2_TMRB2CLK_Pos (17UL) /*!< CTIMER CTRL2: TMRB2CLK (Bit 17) */ +#define CTIMER_CTRL2_TMRB2CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL2: TMRB2CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL2_TMRB2EN_Pos (16UL) /*!< CTIMER CTRL2: TMRB2EN (Bit 16) */ +#define CTIMER_CTRL2_TMRB2EN_Msk (0x10000UL) /*!< CTIMER CTRL2: TMRB2EN (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRA2POL_Pos (12UL) /*!< CTIMER CTRL2: TMRA2POL (Bit 12) */ +#define CTIMER_CTRL2_TMRA2POL_Msk (0x1000UL) /*!< CTIMER CTRL2: TMRA2POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRA2CLR_Pos (11UL) /*!< CTIMER CTRL2: TMRA2CLR (Bit 11) */ +#define CTIMER_CTRL2_TMRA2CLR_Msk (0x800UL) /*!< CTIMER CTRL2: TMRA2CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRA2IE1_Pos (10UL) /*!< CTIMER CTRL2: TMRA2IE1 (Bit 10) */ +#define CTIMER_CTRL2_TMRA2IE1_Msk (0x400UL) /*!< CTIMER CTRL2: TMRA2IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRA2IE0_Pos (9UL) /*!< CTIMER CTRL2: TMRA2IE0 (Bit 9) */ +#define CTIMER_CTRL2_TMRA2IE0_Msk (0x200UL) /*!< CTIMER CTRL2: TMRA2IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL2_TMRA2FN_Pos (6UL) /*!< CTIMER CTRL2: TMRA2FN (Bit 6) */ +#define CTIMER_CTRL2_TMRA2FN_Msk (0x1c0UL) /*!< CTIMER CTRL2: TMRA2FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL2_TMRA2CLK_Pos (1UL) /*!< CTIMER CTRL2: TMRA2CLK (Bit 1) */ +#define CTIMER_CTRL2_TMRA2CLK_Msk (0x3eUL) /*!< CTIMER CTRL2: TMRA2CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL2_TMRA2EN_Pos (0UL) /*!< CTIMER CTRL2: TMRA2EN (Bit 0) */ +#define CTIMER_CTRL2_TMRA2EN_Msk (0x1UL) /*!< CTIMER CTRL2: TMRA2EN (Bitfield-Mask: 0x01) */ +/* ======================================================= CMPRAUXA2 ======================================================= */ +#define CTIMER_CMPRAUXA2_CMPR3A2_Pos (16UL) /*!< CTIMER CMPRAUXA2: CMPR3A2 (Bit 16) */ +#define CTIMER_CMPRAUXA2_CMPR3A2_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA2: CMPR3A2 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXA2_CMPR2A2_Pos (0UL) /*!< CTIMER CMPRAUXA2: CMPR2A2 (Bit 0) */ +#define CTIMER_CMPRAUXA2_CMPR2A2_Msk (0xffffUL) /*!< CTIMER CMPRAUXA2: CMPR2A2 (Bitfield-Mask: 0xffff) */ +/* ======================================================= CMPRAUXB2 ======================================================= */ +#define CTIMER_CMPRAUXB2_CMPR3B2_Pos (16UL) /*!< CTIMER CMPRAUXB2: CMPR3B2 (Bit 16) */ +#define CTIMER_CMPRAUXB2_CMPR3B2_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB2: CMPR3B2 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXB2_CMPR2B2_Pos (0UL) /*!< CTIMER CMPRAUXB2: CMPR2B2 (Bit 0) */ +#define CTIMER_CMPRAUXB2_CMPR2B2_Msk (0xffffUL) /*!< CTIMER CMPRAUXB2: CMPR2B2 (Bitfield-Mask: 0xffff) */ +/* ========================================================= AUX2 ========================================================== */ +#define CTIMER_AUX2_TMRB2EN23_Pos (30UL) /*!< CTIMER AUX2: TMRB2EN23 (Bit 30) */ +#define CTIMER_AUX2_TMRB2EN23_Msk (0x40000000UL) /*!< CTIMER AUX2: TMRB2EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX2_TMRB2POL23_Pos (29UL) /*!< CTIMER AUX2: TMRB2POL23 (Bit 29) */ +#define CTIMER_AUX2_TMRB2POL23_Msk (0x20000000UL) /*!< CTIMER AUX2: TMRB2POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX2_TMRB2TINV_Pos (28UL) /*!< CTIMER AUX2: TMRB2TINV (Bit 28) */ +#define CTIMER_AUX2_TMRB2TINV_Msk (0x10000000UL) /*!< CTIMER AUX2: TMRB2TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX2_TMRB2NOSYNC_Pos (27UL) /*!< CTIMER AUX2: TMRB2NOSYNC (Bit 27) */ +#define CTIMER_AUX2_TMRB2NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX2: TMRB2NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX2_TMRB2TRIG_Pos (23UL) /*!< CTIMER AUX2: TMRB2TRIG (Bit 23) */ +#define CTIMER_AUX2_TMRB2TRIG_Msk (0x7800000UL) /*!< CTIMER AUX2: TMRB2TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX2_TMRB2LMT_Pos (16UL) /*!< CTIMER AUX2: TMRB2LMT (Bit 16) */ +#define CTIMER_AUX2_TMRB2LMT_Msk (0x3f0000UL) /*!< CTIMER AUX2: TMRB2LMT (Bitfield-Mask: 0x3f) */ +#define CTIMER_AUX2_TMRA2EN23_Pos (14UL) /*!< CTIMER AUX2: TMRA2EN23 (Bit 14) */ +#define CTIMER_AUX2_TMRA2EN23_Msk (0x4000UL) /*!< CTIMER AUX2: TMRA2EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX2_TMRA2POL23_Pos (13UL) /*!< CTIMER AUX2: TMRA2POL23 (Bit 13) */ +#define CTIMER_AUX2_TMRA2POL23_Msk (0x2000UL) /*!< CTIMER AUX2: TMRA2POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX2_TMRA2TINV_Pos (12UL) /*!< CTIMER AUX2: TMRA2TINV (Bit 12) */ +#define CTIMER_AUX2_TMRA2TINV_Msk (0x1000UL) /*!< CTIMER AUX2: TMRA2TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX2_TMRA2NOSYNC_Pos (11UL) /*!< CTIMER AUX2: TMRA2NOSYNC (Bit 11) */ +#define CTIMER_AUX2_TMRA2NOSYNC_Msk (0x800UL) /*!< CTIMER AUX2: TMRA2NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX2_TMRA2TRIG_Pos (7UL) /*!< CTIMER AUX2: TMRA2TRIG (Bit 7) */ +#define CTIMER_AUX2_TMRA2TRIG_Msk (0x780UL) /*!< CTIMER AUX2: TMRA2TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX2_TMRA2LMT_Pos (0UL) /*!< CTIMER AUX2: TMRA2LMT (Bit 0) */ +#define CTIMER_AUX2_TMRA2LMT_Msk (0x7fUL) /*!< CTIMER AUX2: TMRA2LMT (Bitfield-Mask: 0x7f) */ +/* ========================================================= TMR3 ========================================================== */ +#define CTIMER_TMR3_CTTMRB3_Pos (16UL) /*!< CTIMER TMR3: CTTMRB3 (Bit 16) */ +#define CTIMER_TMR3_CTTMRB3_Msk (0xffff0000UL) /*!< CTIMER TMR3: CTTMRB3 (Bitfield-Mask: 0xffff) */ +#define CTIMER_TMR3_CTTMRA3_Pos (0UL) /*!< CTIMER TMR3: CTTMRA3 (Bit 0) */ +#define CTIMER_TMR3_CTTMRA3_Msk (0xffffUL) /*!< CTIMER TMR3: CTTMRA3 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRA3 ========================================================= */ +#define CTIMER_CMPRA3_CMPR1A3_Pos (16UL) /*!< CTIMER CMPRA3: CMPR1A3 (Bit 16) */ +#define CTIMER_CMPRA3_CMPR1A3_Msk (0xffff0000UL) /*!< CTIMER CMPRA3: CMPR1A3 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRA3_CMPR0A3_Pos (0UL) /*!< CTIMER CMPRA3: CMPR0A3 (Bit 0) */ +#define CTIMER_CMPRA3_CMPR0A3_Msk (0xffffUL) /*!< CTIMER CMPRA3: CMPR0A3 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRB3 ========================================================= */ +#define CTIMER_CMPRB3_CMPR1B3_Pos (16UL) /*!< CTIMER CMPRB3: CMPR1B3 (Bit 16) */ +#define CTIMER_CMPRB3_CMPR1B3_Msk (0xffff0000UL) /*!< CTIMER CMPRB3: CMPR1B3 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRB3_CMPR0B3_Pos (0UL) /*!< CTIMER CMPRB3: CMPR0B3 (Bit 0) */ +#define CTIMER_CMPRB3_CMPR0B3_Msk (0xffffUL) /*!< CTIMER CMPRB3: CMPR0B3 (Bitfield-Mask: 0xffff) */ +/* ========================================================= CTRL3 ========================================================= */ +#define CTIMER_CTRL3_CTLINK3_Pos (31UL) /*!< CTIMER CTRL3: CTLINK3 (Bit 31) */ +#define CTIMER_CTRL3_CTLINK3_Msk (0x80000000UL) /*!< CTIMER CTRL3: CTLINK3 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRB3POL_Pos (28UL) /*!< CTIMER CTRL3: TMRB3POL (Bit 28) */ +#define CTIMER_CTRL3_TMRB3POL_Msk (0x10000000UL) /*!< CTIMER CTRL3: TMRB3POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRB3CLR_Pos (27UL) /*!< CTIMER CTRL3: TMRB3CLR (Bit 27) */ +#define CTIMER_CTRL3_TMRB3CLR_Msk (0x8000000UL) /*!< CTIMER CTRL3: TMRB3CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRB3IE1_Pos (26UL) /*!< CTIMER CTRL3: TMRB3IE1 (Bit 26) */ +#define CTIMER_CTRL3_TMRB3IE1_Msk (0x4000000UL) /*!< CTIMER CTRL3: TMRB3IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRB3IE0_Pos (25UL) /*!< CTIMER CTRL3: TMRB3IE0 (Bit 25) */ +#define CTIMER_CTRL3_TMRB3IE0_Msk (0x2000000UL) /*!< CTIMER CTRL3: TMRB3IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRB3FN_Pos (22UL) /*!< CTIMER CTRL3: TMRB3FN (Bit 22) */ +#define CTIMER_CTRL3_TMRB3FN_Msk (0x1c00000UL) /*!< CTIMER CTRL3: TMRB3FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL3_TMRB3CLK_Pos (17UL) /*!< CTIMER CTRL3: TMRB3CLK (Bit 17) */ +#define CTIMER_CTRL3_TMRB3CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL3: TMRB3CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL3_TMRB3EN_Pos (16UL) /*!< CTIMER CTRL3: TMRB3EN (Bit 16) */ +#define CTIMER_CTRL3_TMRB3EN_Msk (0x10000UL) /*!< CTIMER CTRL3: TMRB3EN (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_ADCEN_Pos (15UL) /*!< CTIMER CTRL3: ADCEN (Bit 15) */ +#define CTIMER_CTRL3_ADCEN_Msk (0x8000UL) /*!< CTIMER CTRL3: ADCEN (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRA3POL_Pos (12UL) /*!< CTIMER CTRL3: TMRA3POL (Bit 12) */ +#define CTIMER_CTRL3_TMRA3POL_Msk (0x1000UL) /*!< CTIMER CTRL3: TMRA3POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRA3CLR_Pos (11UL) /*!< CTIMER CTRL3: TMRA3CLR (Bit 11) */ +#define CTIMER_CTRL3_TMRA3CLR_Msk (0x800UL) /*!< CTIMER CTRL3: TMRA3CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRA3IE1_Pos (10UL) /*!< CTIMER CTRL3: TMRA3IE1 (Bit 10) */ +#define CTIMER_CTRL3_TMRA3IE1_Msk (0x400UL) /*!< CTIMER CTRL3: TMRA3IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRA3IE0_Pos (9UL) /*!< CTIMER CTRL3: TMRA3IE0 (Bit 9) */ +#define CTIMER_CTRL3_TMRA3IE0_Msk (0x200UL) /*!< CTIMER CTRL3: TMRA3IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL3_TMRA3FN_Pos (6UL) /*!< CTIMER CTRL3: TMRA3FN (Bit 6) */ +#define CTIMER_CTRL3_TMRA3FN_Msk (0x1c0UL) /*!< CTIMER CTRL3: TMRA3FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL3_TMRA3CLK_Pos (1UL) /*!< CTIMER CTRL3: TMRA3CLK (Bit 1) */ +#define CTIMER_CTRL3_TMRA3CLK_Msk (0x3eUL) /*!< CTIMER CTRL3: TMRA3CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL3_TMRA3EN_Pos (0UL) /*!< CTIMER CTRL3: TMRA3EN (Bit 0) */ +#define CTIMER_CTRL3_TMRA3EN_Msk (0x1UL) /*!< CTIMER CTRL3: TMRA3EN (Bitfield-Mask: 0x01) */ +/* ======================================================= CMPRAUXA3 ======================================================= */ +#define CTIMER_CMPRAUXA3_CMPR3A3_Pos (16UL) /*!< CTIMER CMPRAUXA3: CMPR3A3 (Bit 16) */ +#define CTIMER_CMPRAUXA3_CMPR3A3_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA3: CMPR3A3 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXA3_CMPR2A3_Pos (0UL) /*!< CTIMER CMPRAUXA3: CMPR2A3 (Bit 0) */ +#define CTIMER_CMPRAUXA3_CMPR2A3_Msk (0xffffUL) /*!< CTIMER CMPRAUXA3: CMPR2A3 (Bitfield-Mask: 0xffff) */ +/* ======================================================= CMPRAUXB3 ======================================================= */ +#define CTIMER_CMPRAUXB3_CMPR3B3_Pos (16UL) /*!< CTIMER CMPRAUXB3: CMPR3B3 (Bit 16) */ +#define CTIMER_CMPRAUXB3_CMPR3B3_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB3: CMPR3B3 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXB3_CMPR2B3_Pos (0UL) /*!< CTIMER CMPRAUXB3: CMPR2B3 (Bit 0) */ +#define CTIMER_CMPRAUXB3_CMPR2B3_Msk (0xffffUL) /*!< CTIMER CMPRAUXB3: CMPR2B3 (Bitfield-Mask: 0xffff) */ +/* ========================================================= AUX3 ========================================================== */ +#define CTIMER_AUX3_TMRB3EN23_Pos (30UL) /*!< CTIMER AUX3: TMRB3EN23 (Bit 30) */ +#define CTIMER_AUX3_TMRB3EN23_Msk (0x40000000UL) /*!< CTIMER AUX3: TMRB3EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX3_TMRB3POL23_Pos (29UL) /*!< CTIMER AUX3: TMRB3POL23 (Bit 29) */ +#define CTIMER_AUX3_TMRB3POL23_Msk (0x20000000UL) /*!< CTIMER AUX3: TMRB3POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX3_TMRB3TINV_Pos (28UL) /*!< CTIMER AUX3: TMRB3TINV (Bit 28) */ +#define CTIMER_AUX3_TMRB3TINV_Msk (0x10000000UL) /*!< CTIMER AUX3: TMRB3TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX3_TMRB3NOSYNC_Pos (27UL) /*!< CTIMER AUX3: TMRB3NOSYNC (Bit 27) */ +#define CTIMER_AUX3_TMRB3NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX3: TMRB3NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX3_TMRB3TRIG_Pos (23UL) /*!< CTIMER AUX3: TMRB3TRIG (Bit 23) */ +#define CTIMER_AUX3_TMRB3TRIG_Msk (0x7800000UL) /*!< CTIMER AUX3: TMRB3TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX3_TMRB3LMT_Pos (16UL) /*!< CTIMER AUX3: TMRB3LMT (Bit 16) */ +#define CTIMER_AUX3_TMRB3LMT_Msk (0x3f0000UL) /*!< CTIMER AUX3: TMRB3LMT (Bitfield-Mask: 0x3f) */ +#define CTIMER_AUX3_TMRA3EN23_Pos (14UL) /*!< CTIMER AUX3: TMRA3EN23 (Bit 14) */ +#define CTIMER_AUX3_TMRA3EN23_Msk (0x4000UL) /*!< CTIMER AUX3: TMRA3EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX3_TMRA3POL23_Pos (13UL) /*!< CTIMER AUX3: TMRA3POL23 (Bit 13) */ +#define CTIMER_AUX3_TMRA3POL23_Msk (0x2000UL) /*!< CTIMER AUX3: TMRA3POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX3_TMRA3TINV_Pos (12UL) /*!< CTIMER AUX3: TMRA3TINV (Bit 12) */ +#define CTIMER_AUX3_TMRA3TINV_Msk (0x1000UL) /*!< CTIMER AUX3: TMRA3TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX3_TMRA3NOSYNC_Pos (11UL) /*!< CTIMER AUX3: TMRA3NOSYNC (Bit 11) */ +#define CTIMER_AUX3_TMRA3NOSYNC_Msk (0x800UL) /*!< CTIMER AUX3: TMRA3NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX3_TMRA3TRIG_Pos (7UL) /*!< CTIMER AUX3: TMRA3TRIG (Bit 7) */ +#define CTIMER_AUX3_TMRA3TRIG_Msk (0x780UL) /*!< CTIMER AUX3: TMRA3TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX3_TMRA3LMT_Pos (0UL) /*!< CTIMER AUX3: TMRA3LMT (Bit 0) */ +#define CTIMER_AUX3_TMRA3LMT_Msk (0x7fUL) /*!< CTIMER AUX3: TMRA3LMT (Bitfield-Mask: 0x7f) */ +/* ========================================================= TMR4 ========================================================== */ +#define CTIMER_TMR4_CTTMRB4_Pos (16UL) /*!< CTIMER TMR4: CTTMRB4 (Bit 16) */ +#define CTIMER_TMR4_CTTMRB4_Msk (0xffff0000UL) /*!< CTIMER TMR4: CTTMRB4 (Bitfield-Mask: 0xffff) */ +#define CTIMER_TMR4_CTTMRA4_Pos (0UL) /*!< CTIMER TMR4: CTTMRA4 (Bit 0) */ +#define CTIMER_TMR4_CTTMRA4_Msk (0xffffUL) /*!< CTIMER TMR4: CTTMRA4 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRA4 ========================================================= */ +#define CTIMER_CMPRA4_CMPR1A4_Pos (16UL) /*!< CTIMER CMPRA4: CMPR1A4 (Bit 16) */ +#define CTIMER_CMPRA4_CMPR1A4_Msk (0xffff0000UL) /*!< CTIMER CMPRA4: CMPR1A4 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRA4_CMPR0A4_Pos (0UL) /*!< CTIMER CMPRA4: CMPR0A4 (Bit 0) */ +#define CTIMER_CMPRA4_CMPR0A4_Msk (0xffffUL) /*!< CTIMER CMPRA4: CMPR0A4 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRB4 ========================================================= */ +#define CTIMER_CMPRB4_CMPR1B4_Pos (16UL) /*!< CTIMER CMPRB4: CMPR1B4 (Bit 16) */ +#define CTIMER_CMPRB4_CMPR1B4_Msk (0xffff0000UL) /*!< CTIMER CMPRB4: CMPR1B4 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRB4_CMPR0B4_Pos (0UL) /*!< CTIMER CMPRB4: CMPR0B4 (Bit 0) */ +#define CTIMER_CMPRB4_CMPR0B4_Msk (0xffffUL) /*!< CTIMER CMPRB4: CMPR0B4 (Bitfield-Mask: 0xffff) */ +/* ========================================================= CTRL4 ========================================================= */ +#define CTIMER_CTRL4_CTLINK4_Pos (31UL) /*!< CTIMER CTRL4: CTLINK4 (Bit 31) */ +#define CTIMER_CTRL4_CTLINK4_Msk (0x80000000UL) /*!< CTIMER CTRL4: CTLINK4 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRB4POL_Pos (28UL) /*!< CTIMER CTRL4: TMRB4POL (Bit 28) */ +#define CTIMER_CTRL4_TMRB4POL_Msk (0x10000000UL) /*!< CTIMER CTRL4: TMRB4POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRB4CLR_Pos (27UL) /*!< CTIMER CTRL4: TMRB4CLR (Bit 27) */ +#define CTIMER_CTRL4_TMRB4CLR_Msk (0x8000000UL) /*!< CTIMER CTRL4: TMRB4CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRB4IE1_Pos (26UL) /*!< CTIMER CTRL4: TMRB4IE1 (Bit 26) */ +#define CTIMER_CTRL4_TMRB4IE1_Msk (0x4000000UL) /*!< CTIMER CTRL4: TMRB4IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRB4IE0_Pos (25UL) /*!< CTIMER CTRL4: TMRB4IE0 (Bit 25) */ +#define CTIMER_CTRL4_TMRB4IE0_Msk (0x2000000UL) /*!< CTIMER CTRL4: TMRB4IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRB4FN_Pos (22UL) /*!< CTIMER CTRL4: TMRB4FN (Bit 22) */ +#define CTIMER_CTRL4_TMRB4FN_Msk (0x1c00000UL) /*!< CTIMER CTRL4: TMRB4FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL4_TMRB4CLK_Pos (17UL) /*!< CTIMER CTRL4: TMRB4CLK (Bit 17) */ +#define CTIMER_CTRL4_TMRB4CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL4: TMRB4CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL4_TMRB4EN_Pos (16UL) /*!< CTIMER CTRL4: TMRB4EN (Bit 16) */ +#define CTIMER_CTRL4_TMRB4EN_Msk (0x10000UL) /*!< CTIMER CTRL4: TMRB4EN (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRA4POL_Pos (12UL) /*!< CTIMER CTRL4: TMRA4POL (Bit 12) */ +#define CTIMER_CTRL4_TMRA4POL_Msk (0x1000UL) /*!< CTIMER CTRL4: TMRA4POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRA4CLR_Pos (11UL) /*!< CTIMER CTRL4: TMRA4CLR (Bit 11) */ +#define CTIMER_CTRL4_TMRA4CLR_Msk (0x800UL) /*!< CTIMER CTRL4: TMRA4CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRA4IE1_Pos (10UL) /*!< CTIMER CTRL4: TMRA4IE1 (Bit 10) */ +#define CTIMER_CTRL4_TMRA4IE1_Msk (0x400UL) /*!< CTIMER CTRL4: TMRA4IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRA4IE0_Pos (9UL) /*!< CTIMER CTRL4: TMRA4IE0 (Bit 9) */ +#define CTIMER_CTRL4_TMRA4IE0_Msk (0x200UL) /*!< CTIMER CTRL4: TMRA4IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL4_TMRA4FN_Pos (6UL) /*!< CTIMER CTRL4: TMRA4FN (Bit 6) */ +#define CTIMER_CTRL4_TMRA4FN_Msk (0x1c0UL) /*!< CTIMER CTRL4: TMRA4FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL4_TMRA4CLK_Pos (1UL) /*!< CTIMER CTRL4: TMRA4CLK (Bit 1) */ +#define CTIMER_CTRL4_TMRA4CLK_Msk (0x3eUL) /*!< CTIMER CTRL4: TMRA4CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL4_TMRA4EN_Pos (0UL) /*!< CTIMER CTRL4: TMRA4EN (Bit 0) */ +#define CTIMER_CTRL4_TMRA4EN_Msk (0x1UL) /*!< CTIMER CTRL4: TMRA4EN (Bitfield-Mask: 0x01) */ +/* ======================================================= CMPRAUXA4 ======================================================= */ +#define CTIMER_CMPRAUXA4_CMPR3A4_Pos (16UL) /*!< CTIMER CMPRAUXA4: CMPR3A4 (Bit 16) */ +#define CTIMER_CMPRAUXA4_CMPR3A4_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA4: CMPR3A4 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXA4_CMPR2A4_Pos (0UL) /*!< CTIMER CMPRAUXA4: CMPR2A4 (Bit 0) */ +#define CTIMER_CMPRAUXA4_CMPR2A4_Msk (0xffffUL) /*!< CTIMER CMPRAUXA4: CMPR2A4 (Bitfield-Mask: 0xffff) */ +/* ======================================================= CMPRAUXB4 ======================================================= */ +#define CTIMER_CMPRAUXB4_CMPR3B4_Pos (16UL) /*!< CTIMER CMPRAUXB4: CMPR3B4 (Bit 16) */ +#define CTIMER_CMPRAUXB4_CMPR3B4_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB4: CMPR3B4 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXB4_CMPR2B4_Pos (0UL) /*!< CTIMER CMPRAUXB4: CMPR2B4 (Bit 0) */ +#define CTIMER_CMPRAUXB4_CMPR2B4_Msk (0xffffUL) /*!< CTIMER CMPRAUXB4: CMPR2B4 (Bitfield-Mask: 0xffff) */ +/* ========================================================= AUX4 ========================================================== */ +#define CTIMER_AUX4_TMRB4EN23_Pos (30UL) /*!< CTIMER AUX4: TMRB4EN23 (Bit 30) */ +#define CTIMER_AUX4_TMRB4EN23_Msk (0x40000000UL) /*!< CTIMER AUX4: TMRB4EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX4_TMRB4POL23_Pos (29UL) /*!< CTIMER AUX4: TMRB4POL23 (Bit 29) */ +#define CTIMER_AUX4_TMRB4POL23_Msk (0x20000000UL) /*!< CTIMER AUX4: TMRB4POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX4_TMRB4TINV_Pos (28UL) /*!< CTIMER AUX4: TMRB4TINV (Bit 28) */ +#define CTIMER_AUX4_TMRB4TINV_Msk (0x10000000UL) /*!< CTIMER AUX4: TMRB4TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX4_TMRB4NOSYNC_Pos (27UL) /*!< CTIMER AUX4: TMRB4NOSYNC (Bit 27) */ +#define CTIMER_AUX4_TMRB4NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX4: TMRB4NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX4_TMRB4TRIG_Pos (23UL) /*!< CTIMER AUX4: TMRB4TRIG (Bit 23) */ +#define CTIMER_AUX4_TMRB4TRIG_Msk (0x7800000UL) /*!< CTIMER AUX4: TMRB4TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX4_TMRB4LMT_Pos (16UL) /*!< CTIMER AUX4: TMRB4LMT (Bit 16) */ +#define CTIMER_AUX4_TMRB4LMT_Msk (0x3f0000UL) /*!< CTIMER AUX4: TMRB4LMT (Bitfield-Mask: 0x3f) */ +#define CTIMER_AUX4_TMRA4EN23_Pos (14UL) /*!< CTIMER AUX4: TMRA4EN23 (Bit 14) */ +#define CTIMER_AUX4_TMRA4EN23_Msk (0x4000UL) /*!< CTIMER AUX4: TMRA4EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX4_TMRA4POL23_Pos (13UL) /*!< CTIMER AUX4: TMRA4POL23 (Bit 13) */ +#define CTIMER_AUX4_TMRA4POL23_Msk (0x2000UL) /*!< CTIMER AUX4: TMRA4POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX4_TMRA4TINV_Pos (12UL) /*!< CTIMER AUX4: TMRA4TINV (Bit 12) */ +#define CTIMER_AUX4_TMRA4TINV_Msk (0x1000UL) /*!< CTIMER AUX4: TMRA4TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX4_TMRA4NOSYNC_Pos (11UL) /*!< CTIMER AUX4: TMRA4NOSYNC (Bit 11) */ +#define CTIMER_AUX4_TMRA4NOSYNC_Msk (0x800UL) /*!< CTIMER AUX4: TMRA4NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX4_TMRA4TRIG_Pos (7UL) /*!< CTIMER AUX4: TMRA4TRIG (Bit 7) */ +#define CTIMER_AUX4_TMRA4TRIG_Msk (0x780UL) /*!< CTIMER AUX4: TMRA4TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX4_TMRA4LMT_Pos (0UL) /*!< CTIMER AUX4: TMRA4LMT (Bit 0) */ +#define CTIMER_AUX4_TMRA4LMT_Msk (0x7fUL) /*!< CTIMER AUX4: TMRA4LMT (Bitfield-Mask: 0x7f) */ +/* ========================================================= TMR5 ========================================================== */ +#define CTIMER_TMR5_CTTMRB5_Pos (16UL) /*!< CTIMER TMR5: CTTMRB5 (Bit 16) */ +#define CTIMER_TMR5_CTTMRB5_Msk (0xffff0000UL) /*!< CTIMER TMR5: CTTMRB5 (Bitfield-Mask: 0xffff) */ +#define CTIMER_TMR5_CTTMRA5_Pos (0UL) /*!< CTIMER TMR5: CTTMRA5 (Bit 0) */ +#define CTIMER_TMR5_CTTMRA5_Msk (0xffffUL) /*!< CTIMER TMR5: CTTMRA5 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRA5 ========================================================= */ +#define CTIMER_CMPRA5_CMPR1A5_Pos (16UL) /*!< CTIMER CMPRA5: CMPR1A5 (Bit 16) */ +#define CTIMER_CMPRA5_CMPR1A5_Msk (0xffff0000UL) /*!< CTIMER CMPRA5: CMPR1A5 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRA5_CMPR0A5_Pos (0UL) /*!< CTIMER CMPRA5: CMPR0A5 (Bit 0) */ +#define CTIMER_CMPRA5_CMPR0A5_Msk (0xffffUL) /*!< CTIMER CMPRA5: CMPR0A5 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRB5 ========================================================= */ +#define CTIMER_CMPRB5_CMPR1B5_Pos (16UL) /*!< CTIMER CMPRB5: CMPR1B5 (Bit 16) */ +#define CTIMER_CMPRB5_CMPR1B5_Msk (0xffff0000UL) /*!< CTIMER CMPRB5: CMPR1B5 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRB5_CMPR0B5_Pos (0UL) /*!< CTIMER CMPRB5: CMPR0B5 (Bit 0) */ +#define CTIMER_CMPRB5_CMPR0B5_Msk (0xffffUL) /*!< CTIMER CMPRB5: CMPR0B5 (Bitfield-Mask: 0xffff) */ +/* ========================================================= CTRL5 ========================================================= */ +#define CTIMER_CTRL5_CTLINK5_Pos (31UL) /*!< CTIMER CTRL5: CTLINK5 (Bit 31) */ +#define CTIMER_CTRL5_CTLINK5_Msk (0x80000000UL) /*!< CTIMER CTRL5: CTLINK5 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRB5POL_Pos (28UL) /*!< CTIMER CTRL5: TMRB5POL (Bit 28) */ +#define CTIMER_CTRL5_TMRB5POL_Msk (0x10000000UL) /*!< CTIMER CTRL5: TMRB5POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRB5CLR_Pos (27UL) /*!< CTIMER CTRL5: TMRB5CLR (Bit 27) */ +#define CTIMER_CTRL5_TMRB5CLR_Msk (0x8000000UL) /*!< CTIMER CTRL5: TMRB5CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRB5IE1_Pos (26UL) /*!< CTIMER CTRL5: TMRB5IE1 (Bit 26) */ +#define CTIMER_CTRL5_TMRB5IE1_Msk (0x4000000UL) /*!< CTIMER CTRL5: TMRB5IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRB5IE0_Pos (25UL) /*!< CTIMER CTRL5: TMRB5IE0 (Bit 25) */ +#define CTIMER_CTRL5_TMRB5IE0_Msk (0x2000000UL) /*!< CTIMER CTRL5: TMRB5IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRB5FN_Pos (22UL) /*!< CTIMER CTRL5: TMRB5FN (Bit 22) */ +#define CTIMER_CTRL5_TMRB5FN_Msk (0x1c00000UL) /*!< CTIMER CTRL5: TMRB5FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL5_TMRB5CLK_Pos (17UL) /*!< CTIMER CTRL5: TMRB5CLK (Bit 17) */ +#define CTIMER_CTRL5_TMRB5CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL5: TMRB5CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL5_TMRB5EN_Pos (16UL) /*!< CTIMER CTRL5: TMRB5EN (Bit 16) */ +#define CTIMER_CTRL5_TMRB5EN_Msk (0x10000UL) /*!< CTIMER CTRL5: TMRB5EN (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRA5POL_Pos (12UL) /*!< CTIMER CTRL5: TMRA5POL (Bit 12) */ +#define CTIMER_CTRL5_TMRA5POL_Msk (0x1000UL) /*!< CTIMER CTRL5: TMRA5POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRA5CLR_Pos (11UL) /*!< CTIMER CTRL5: TMRA5CLR (Bit 11) */ +#define CTIMER_CTRL5_TMRA5CLR_Msk (0x800UL) /*!< CTIMER CTRL5: TMRA5CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRA5IE1_Pos (10UL) /*!< CTIMER CTRL5: TMRA5IE1 (Bit 10) */ +#define CTIMER_CTRL5_TMRA5IE1_Msk (0x400UL) /*!< CTIMER CTRL5: TMRA5IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRA5IE0_Pos (9UL) /*!< CTIMER CTRL5: TMRA5IE0 (Bit 9) */ +#define CTIMER_CTRL5_TMRA5IE0_Msk (0x200UL) /*!< CTIMER CTRL5: TMRA5IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL5_TMRA5FN_Pos (6UL) /*!< CTIMER CTRL5: TMRA5FN (Bit 6) */ +#define CTIMER_CTRL5_TMRA5FN_Msk (0x1c0UL) /*!< CTIMER CTRL5: TMRA5FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL5_TMRA5CLK_Pos (1UL) /*!< CTIMER CTRL5: TMRA5CLK (Bit 1) */ +#define CTIMER_CTRL5_TMRA5CLK_Msk (0x3eUL) /*!< CTIMER CTRL5: TMRA5CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL5_TMRA5EN_Pos (0UL) /*!< CTIMER CTRL5: TMRA5EN (Bit 0) */ +#define CTIMER_CTRL5_TMRA5EN_Msk (0x1UL) /*!< CTIMER CTRL5: TMRA5EN (Bitfield-Mask: 0x01) */ +/* ======================================================= CMPRAUXA5 ======================================================= */ +#define CTIMER_CMPRAUXA5_CMPR3A5_Pos (16UL) /*!< CTIMER CMPRAUXA5: CMPR3A5 (Bit 16) */ +#define CTIMER_CMPRAUXA5_CMPR3A5_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA5: CMPR3A5 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXA5_CMPR2A5_Pos (0UL) /*!< CTIMER CMPRAUXA5: CMPR2A5 (Bit 0) */ +#define CTIMER_CMPRAUXA5_CMPR2A5_Msk (0xffffUL) /*!< CTIMER CMPRAUXA5: CMPR2A5 (Bitfield-Mask: 0xffff) */ +/* ======================================================= CMPRAUXB5 ======================================================= */ +#define CTIMER_CMPRAUXB5_CMPR3B5_Pos (16UL) /*!< CTIMER CMPRAUXB5: CMPR3B5 (Bit 16) */ +#define CTIMER_CMPRAUXB5_CMPR3B5_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB5: CMPR3B5 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXB5_CMPR2B5_Pos (0UL) /*!< CTIMER CMPRAUXB5: CMPR2B5 (Bit 0) */ +#define CTIMER_CMPRAUXB5_CMPR2B5_Msk (0xffffUL) /*!< CTIMER CMPRAUXB5: CMPR2B5 (Bitfield-Mask: 0xffff) */ +/* ========================================================= AUX5 ========================================================== */ +#define CTIMER_AUX5_TMRB5EN23_Pos (30UL) /*!< CTIMER AUX5: TMRB5EN23 (Bit 30) */ +#define CTIMER_AUX5_TMRB5EN23_Msk (0x40000000UL) /*!< CTIMER AUX5: TMRB5EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX5_TMRB5POL23_Pos (29UL) /*!< CTIMER AUX5: TMRB5POL23 (Bit 29) */ +#define CTIMER_AUX5_TMRB5POL23_Msk (0x20000000UL) /*!< CTIMER AUX5: TMRB5POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX5_TMRB5TINV_Pos (28UL) /*!< CTIMER AUX5: TMRB5TINV (Bit 28) */ +#define CTIMER_AUX5_TMRB5TINV_Msk (0x10000000UL) /*!< CTIMER AUX5: TMRB5TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX5_TMRB5NOSYNC_Pos (27UL) /*!< CTIMER AUX5: TMRB5NOSYNC (Bit 27) */ +#define CTIMER_AUX5_TMRB5NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX5: TMRB5NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX5_TMRB5TRIG_Pos (23UL) /*!< CTIMER AUX5: TMRB5TRIG (Bit 23) */ +#define CTIMER_AUX5_TMRB5TRIG_Msk (0x7800000UL) /*!< CTIMER AUX5: TMRB5TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX5_TMRB5LMT_Pos (16UL) /*!< CTIMER AUX5: TMRB5LMT (Bit 16) */ +#define CTIMER_AUX5_TMRB5LMT_Msk (0x3f0000UL) /*!< CTIMER AUX5: TMRB5LMT (Bitfield-Mask: 0x3f) */ +#define CTIMER_AUX5_TMRA5EN23_Pos (14UL) /*!< CTIMER AUX5: TMRA5EN23 (Bit 14) */ +#define CTIMER_AUX5_TMRA5EN23_Msk (0x4000UL) /*!< CTIMER AUX5: TMRA5EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX5_TMRA5POL23_Pos (13UL) /*!< CTIMER AUX5: TMRA5POL23 (Bit 13) */ +#define CTIMER_AUX5_TMRA5POL23_Msk (0x2000UL) /*!< CTIMER AUX5: TMRA5POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX5_TMRA5TINV_Pos (12UL) /*!< CTIMER AUX5: TMRA5TINV (Bit 12) */ +#define CTIMER_AUX5_TMRA5TINV_Msk (0x1000UL) /*!< CTIMER AUX5: TMRA5TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX5_TMRA5NOSYNC_Pos (11UL) /*!< CTIMER AUX5: TMRA5NOSYNC (Bit 11) */ +#define CTIMER_AUX5_TMRA5NOSYNC_Msk (0x800UL) /*!< CTIMER AUX5: TMRA5NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX5_TMRA5TRIG_Pos (7UL) /*!< CTIMER AUX5: TMRA5TRIG (Bit 7) */ +#define CTIMER_AUX5_TMRA5TRIG_Msk (0x780UL) /*!< CTIMER AUX5: TMRA5TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX5_TMRA5LMT_Pos (0UL) /*!< CTIMER AUX5: TMRA5LMT (Bit 0) */ +#define CTIMER_AUX5_TMRA5LMT_Msk (0x7fUL) /*!< CTIMER AUX5: TMRA5LMT (Bitfield-Mask: 0x7f) */ +/* ========================================================= TMR6 ========================================================== */ +#define CTIMER_TMR6_CTTMRB6_Pos (16UL) /*!< CTIMER TMR6: CTTMRB6 (Bit 16) */ +#define CTIMER_TMR6_CTTMRB6_Msk (0xffff0000UL) /*!< CTIMER TMR6: CTTMRB6 (Bitfield-Mask: 0xffff) */ +#define CTIMER_TMR6_CTTMRA6_Pos (0UL) /*!< CTIMER TMR6: CTTMRA6 (Bit 0) */ +#define CTIMER_TMR6_CTTMRA6_Msk (0xffffUL) /*!< CTIMER TMR6: CTTMRA6 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRA6 ========================================================= */ +#define CTIMER_CMPRA6_CMPR1A6_Pos (16UL) /*!< CTIMER CMPRA6: CMPR1A6 (Bit 16) */ +#define CTIMER_CMPRA6_CMPR1A6_Msk (0xffff0000UL) /*!< CTIMER CMPRA6: CMPR1A6 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRA6_CMPR0A6_Pos (0UL) /*!< CTIMER CMPRA6: CMPR0A6 (Bit 0) */ +#define CTIMER_CMPRA6_CMPR0A6_Msk (0xffffUL) /*!< CTIMER CMPRA6: CMPR0A6 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRB6 ========================================================= */ +#define CTIMER_CMPRB6_CMPR1B6_Pos (16UL) /*!< CTIMER CMPRB6: CMPR1B6 (Bit 16) */ +#define CTIMER_CMPRB6_CMPR1B6_Msk (0xffff0000UL) /*!< CTIMER CMPRB6: CMPR1B6 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRB6_CMPR0B6_Pos (0UL) /*!< CTIMER CMPRB6: CMPR0B6 (Bit 0) */ +#define CTIMER_CMPRB6_CMPR0B6_Msk (0xffffUL) /*!< CTIMER CMPRB6: CMPR0B6 (Bitfield-Mask: 0xffff) */ +/* ========================================================= CTRL6 ========================================================= */ +#define CTIMER_CTRL6_CTLINK6_Pos (31UL) /*!< CTIMER CTRL6: CTLINK6 (Bit 31) */ +#define CTIMER_CTRL6_CTLINK6_Msk (0x80000000UL) /*!< CTIMER CTRL6: CTLINK6 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRB6POL_Pos (28UL) /*!< CTIMER CTRL6: TMRB6POL (Bit 28) */ +#define CTIMER_CTRL6_TMRB6POL_Msk (0x10000000UL) /*!< CTIMER CTRL6: TMRB6POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRB6CLR_Pos (27UL) /*!< CTIMER CTRL6: TMRB6CLR (Bit 27) */ +#define CTIMER_CTRL6_TMRB6CLR_Msk (0x8000000UL) /*!< CTIMER CTRL6: TMRB6CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRB6IE1_Pos (26UL) /*!< CTIMER CTRL6: TMRB6IE1 (Bit 26) */ +#define CTIMER_CTRL6_TMRB6IE1_Msk (0x4000000UL) /*!< CTIMER CTRL6: TMRB6IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRB6IE0_Pos (25UL) /*!< CTIMER CTRL6: TMRB6IE0 (Bit 25) */ +#define CTIMER_CTRL6_TMRB6IE0_Msk (0x2000000UL) /*!< CTIMER CTRL6: TMRB6IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRB6FN_Pos (22UL) /*!< CTIMER CTRL6: TMRB6FN (Bit 22) */ +#define CTIMER_CTRL6_TMRB6FN_Msk (0x1c00000UL) /*!< CTIMER CTRL6: TMRB6FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL6_TMRB6CLK_Pos (17UL) /*!< CTIMER CTRL6: TMRB6CLK (Bit 17) */ +#define CTIMER_CTRL6_TMRB6CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL6: TMRB6CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL6_TMRB6EN_Pos (16UL) /*!< CTIMER CTRL6: TMRB6EN (Bit 16) */ +#define CTIMER_CTRL6_TMRB6EN_Msk (0x10000UL) /*!< CTIMER CTRL6: TMRB6EN (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRA6POL_Pos (12UL) /*!< CTIMER CTRL6: TMRA6POL (Bit 12) */ +#define CTIMER_CTRL6_TMRA6POL_Msk (0x1000UL) /*!< CTIMER CTRL6: TMRA6POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRA6CLR_Pos (11UL) /*!< CTIMER CTRL6: TMRA6CLR (Bit 11) */ +#define CTIMER_CTRL6_TMRA6CLR_Msk (0x800UL) /*!< CTIMER CTRL6: TMRA6CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRA6IE1_Pos (10UL) /*!< CTIMER CTRL6: TMRA6IE1 (Bit 10) */ +#define CTIMER_CTRL6_TMRA6IE1_Msk (0x400UL) /*!< CTIMER CTRL6: TMRA6IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRA6IE0_Pos (9UL) /*!< CTIMER CTRL6: TMRA6IE0 (Bit 9) */ +#define CTIMER_CTRL6_TMRA6IE0_Msk (0x200UL) /*!< CTIMER CTRL6: TMRA6IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL6_TMRA6FN_Pos (6UL) /*!< CTIMER CTRL6: TMRA6FN (Bit 6) */ +#define CTIMER_CTRL6_TMRA6FN_Msk (0x1c0UL) /*!< CTIMER CTRL6: TMRA6FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL6_TMRA6CLK_Pos (1UL) /*!< CTIMER CTRL6: TMRA6CLK (Bit 1) */ +#define CTIMER_CTRL6_TMRA6CLK_Msk (0x3eUL) /*!< CTIMER CTRL6: TMRA6CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL6_TMRA6EN_Pos (0UL) /*!< CTIMER CTRL6: TMRA6EN (Bit 0) */ +#define CTIMER_CTRL6_TMRA6EN_Msk (0x1UL) /*!< CTIMER CTRL6: TMRA6EN (Bitfield-Mask: 0x01) */ +/* ======================================================= CMPRAUXA6 ======================================================= */ +#define CTIMER_CMPRAUXA6_CMPR3A6_Pos (16UL) /*!< CTIMER CMPRAUXA6: CMPR3A6 (Bit 16) */ +#define CTIMER_CMPRAUXA6_CMPR3A6_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA6: CMPR3A6 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXA6_CMPR2A6_Pos (0UL) /*!< CTIMER CMPRAUXA6: CMPR2A6 (Bit 0) */ +#define CTIMER_CMPRAUXA6_CMPR2A6_Msk (0xffffUL) /*!< CTIMER CMPRAUXA6: CMPR2A6 (Bitfield-Mask: 0xffff) */ +/* ======================================================= CMPRAUXB6 ======================================================= */ +#define CTIMER_CMPRAUXB6_CMPR3B6_Pos (16UL) /*!< CTIMER CMPRAUXB6: CMPR3B6 (Bit 16) */ +#define CTIMER_CMPRAUXB6_CMPR3B6_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB6: CMPR3B6 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXB6_CMPR2B6_Pos (0UL) /*!< CTIMER CMPRAUXB6: CMPR2B6 (Bit 0) */ +#define CTIMER_CMPRAUXB6_CMPR2B6_Msk (0xffffUL) /*!< CTIMER CMPRAUXB6: CMPR2B6 (Bitfield-Mask: 0xffff) */ +/* ========================================================= AUX6 ========================================================== */ +#define CTIMER_AUX6_TMRB6EN23_Pos (30UL) /*!< CTIMER AUX6: TMRB6EN23 (Bit 30) */ +#define CTIMER_AUX6_TMRB6EN23_Msk (0x40000000UL) /*!< CTIMER AUX6: TMRB6EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX6_TMRB6POL23_Pos (29UL) /*!< CTIMER AUX6: TMRB6POL23 (Bit 29) */ +#define CTIMER_AUX6_TMRB6POL23_Msk (0x20000000UL) /*!< CTIMER AUX6: TMRB6POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX6_TMRB6TINV_Pos (28UL) /*!< CTIMER AUX6: TMRB6TINV (Bit 28) */ +#define CTIMER_AUX6_TMRB6TINV_Msk (0x10000000UL) /*!< CTIMER AUX6: TMRB6TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX6_TMRB6NOSYNC_Pos (27UL) /*!< CTIMER AUX6: TMRB6NOSYNC (Bit 27) */ +#define CTIMER_AUX6_TMRB6NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX6: TMRB6NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX6_TMRB6TRIG_Pos (23UL) /*!< CTIMER AUX6: TMRB6TRIG (Bit 23) */ +#define CTIMER_AUX6_TMRB6TRIG_Msk (0x7800000UL) /*!< CTIMER AUX6: TMRB6TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX6_TMRB6LMT_Pos (16UL) /*!< CTIMER AUX6: TMRB6LMT (Bit 16) */ +#define CTIMER_AUX6_TMRB6LMT_Msk (0x3f0000UL) /*!< CTIMER AUX6: TMRB6LMT (Bitfield-Mask: 0x3f) */ +#define CTIMER_AUX6_TMRA6EN23_Pos (14UL) /*!< CTIMER AUX6: TMRA6EN23 (Bit 14) */ +#define CTIMER_AUX6_TMRA6EN23_Msk (0x4000UL) /*!< CTIMER AUX6: TMRA6EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX6_TMRA6POL23_Pos (13UL) /*!< CTIMER AUX6: TMRA6POL23 (Bit 13) */ +#define CTIMER_AUX6_TMRA6POL23_Msk (0x2000UL) /*!< CTIMER AUX6: TMRA6POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX6_TMRA6TINV_Pos (12UL) /*!< CTIMER AUX6: TMRA6TINV (Bit 12) */ +#define CTIMER_AUX6_TMRA6TINV_Msk (0x1000UL) /*!< CTIMER AUX6: TMRA6TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX6_TMRA6NOSYNC_Pos (11UL) /*!< CTIMER AUX6: TMRA6NOSYNC (Bit 11) */ +#define CTIMER_AUX6_TMRA6NOSYNC_Msk (0x800UL) /*!< CTIMER AUX6: TMRA6NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX6_TMRA6TRIG_Pos (7UL) /*!< CTIMER AUX6: TMRA6TRIG (Bit 7) */ +#define CTIMER_AUX6_TMRA6TRIG_Msk (0x780UL) /*!< CTIMER AUX6: TMRA6TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX6_TMRA6LMT_Pos (0UL) /*!< CTIMER AUX6: TMRA6LMT (Bit 0) */ +#define CTIMER_AUX6_TMRA6LMT_Msk (0x7fUL) /*!< CTIMER AUX6: TMRA6LMT (Bitfield-Mask: 0x7f) */ +/* ========================================================= TMR7 ========================================================== */ +#define CTIMER_TMR7_CTTMRB7_Pos (16UL) /*!< CTIMER TMR7: CTTMRB7 (Bit 16) */ +#define CTIMER_TMR7_CTTMRB7_Msk (0xffff0000UL) /*!< CTIMER TMR7: CTTMRB7 (Bitfield-Mask: 0xffff) */ +#define CTIMER_TMR7_CTTMRA7_Pos (0UL) /*!< CTIMER TMR7: CTTMRA7 (Bit 0) */ +#define CTIMER_TMR7_CTTMRA7_Msk (0xffffUL) /*!< CTIMER TMR7: CTTMRA7 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRA7 ========================================================= */ +#define CTIMER_CMPRA7_CMPR1A7_Pos (16UL) /*!< CTIMER CMPRA7: CMPR1A7 (Bit 16) */ +#define CTIMER_CMPRA7_CMPR1A7_Msk (0xffff0000UL) /*!< CTIMER CMPRA7: CMPR1A7 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRA7_CMPR0A7_Pos (0UL) /*!< CTIMER CMPRA7: CMPR0A7 (Bit 0) */ +#define CTIMER_CMPRA7_CMPR0A7_Msk (0xffffUL) /*!< CTIMER CMPRA7: CMPR0A7 (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMPRB7 ========================================================= */ +#define CTIMER_CMPRB7_CMPR1B7_Pos (16UL) /*!< CTIMER CMPRB7: CMPR1B7 (Bit 16) */ +#define CTIMER_CMPRB7_CMPR1B7_Msk (0xffff0000UL) /*!< CTIMER CMPRB7: CMPR1B7 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRB7_CMPR0B7_Pos (0UL) /*!< CTIMER CMPRB7: CMPR0B7 (Bit 0) */ +#define CTIMER_CMPRB7_CMPR0B7_Msk (0xffffUL) /*!< CTIMER CMPRB7: CMPR0B7 (Bitfield-Mask: 0xffff) */ +/* ========================================================= CTRL7 ========================================================= */ +#define CTIMER_CTRL7_CTLINK7_Pos (31UL) /*!< CTIMER CTRL7: CTLINK7 (Bit 31) */ +#define CTIMER_CTRL7_CTLINK7_Msk (0x80000000UL) /*!< CTIMER CTRL7: CTLINK7 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRB7POL_Pos (28UL) /*!< CTIMER CTRL7: TMRB7POL (Bit 28) */ +#define CTIMER_CTRL7_TMRB7POL_Msk (0x10000000UL) /*!< CTIMER CTRL7: TMRB7POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRB7CLR_Pos (27UL) /*!< CTIMER CTRL7: TMRB7CLR (Bit 27) */ +#define CTIMER_CTRL7_TMRB7CLR_Msk (0x8000000UL) /*!< CTIMER CTRL7: TMRB7CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRB7IE1_Pos (26UL) /*!< CTIMER CTRL7: TMRB7IE1 (Bit 26) */ +#define CTIMER_CTRL7_TMRB7IE1_Msk (0x4000000UL) /*!< CTIMER CTRL7: TMRB7IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRB7IE0_Pos (25UL) /*!< CTIMER CTRL7: TMRB7IE0 (Bit 25) */ +#define CTIMER_CTRL7_TMRB7IE0_Msk (0x2000000UL) /*!< CTIMER CTRL7: TMRB7IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRB7FN_Pos (22UL) /*!< CTIMER CTRL7: TMRB7FN (Bit 22) */ +#define CTIMER_CTRL7_TMRB7FN_Msk (0x1c00000UL) /*!< CTIMER CTRL7: TMRB7FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL7_TMRB7CLK_Pos (17UL) /*!< CTIMER CTRL7: TMRB7CLK (Bit 17) */ +#define CTIMER_CTRL7_TMRB7CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL7: TMRB7CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL7_TMRB7EN_Pos (16UL) /*!< CTIMER CTRL7: TMRB7EN (Bit 16) */ +#define CTIMER_CTRL7_TMRB7EN_Msk (0x10000UL) /*!< CTIMER CTRL7: TMRB7EN (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRA7POL_Pos (12UL) /*!< CTIMER CTRL7: TMRA7POL (Bit 12) */ +#define CTIMER_CTRL7_TMRA7POL_Msk (0x1000UL) /*!< CTIMER CTRL7: TMRA7POL (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRA7CLR_Pos (11UL) /*!< CTIMER CTRL7: TMRA7CLR (Bit 11) */ +#define CTIMER_CTRL7_TMRA7CLR_Msk (0x800UL) /*!< CTIMER CTRL7: TMRA7CLR (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRA7IE1_Pos (10UL) /*!< CTIMER CTRL7: TMRA7IE1 (Bit 10) */ +#define CTIMER_CTRL7_TMRA7IE1_Msk (0x400UL) /*!< CTIMER CTRL7: TMRA7IE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRA7IE0_Pos (9UL) /*!< CTIMER CTRL7: TMRA7IE0 (Bit 9) */ +#define CTIMER_CTRL7_TMRA7IE0_Msk (0x200UL) /*!< CTIMER CTRL7: TMRA7IE0 (Bitfield-Mask: 0x01) */ +#define CTIMER_CTRL7_TMRA7FN_Pos (6UL) /*!< CTIMER CTRL7: TMRA7FN (Bit 6) */ +#define CTIMER_CTRL7_TMRA7FN_Msk (0x1c0UL) /*!< CTIMER CTRL7: TMRA7FN (Bitfield-Mask: 0x07) */ +#define CTIMER_CTRL7_TMRA7CLK_Pos (1UL) /*!< CTIMER CTRL7: TMRA7CLK (Bit 1) */ +#define CTIMER_CTRL7_TMRA7CLK_Msk (0x3eUL) /*!< CTIMER CTRL7: TMRA7CLK (Bitfield-Mask: 0x1f) */ +#define CTIMER_CTRL7_TMRA7EN_Pos (0UL) /*!< CTIMER CTRL7: TMRA7EN (Bit 0) */ +#define CTIMER_CTRL7_TMRA7EN_Msk (0x1UL) /*!< CTIMER CTRL7: TMRA7EN (Bitfield-Mask: 0x01) */ +/* ======================================================= CMPRAUXA7 ======================================================= */ +#define CTIMER_CMPRAUXA7_CMPR3A7_Pos (16UL) /*!< CTIMER CMPRAUXA7: CMPR3A7 (Bit 16) */ +#define CTIMER_CMPRAUXA7_CMPR3A7_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA7: CMPR3A7 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXA7_CMPR2A7_Pos (0UL) /*!< CTIMER CMPRAUXA7: CMPR2A7 (Bit 0) */ +#define CTIMER_CMPRAUXA7_CMPR2A7_Msk (0xffffUL) /*!< CTIMER CMPRAUXA7: CMPR2A7 (Bitfield-Mask: 0xffff) */ +/* ======================================================= CMPRAUXB7 ======================================================= */ +#define CTIMER_CMPRAUXB7_CMPR3B7_Pos (16UL) /*!< CTIMER CMPRAUXB7: CMPR3B7 (Bit 16) */ +#define CTIMER_CMPRAUXB7_CMPR3B7_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB7: CMPR3B7 (Bitfield-Mask: 0xffff) */ +#define CTIMER_CMPRAUXB7_CMPR2B7_Pos (0UL) /*!< CTIMER CMPRAUXB7: CMPR2B7 (Bit 0) */ +#define CTIMER_CMPRAUXB7_CMPR2B7_Msk (0xffffUL) /*!< CTIMER CMPRAUXB7: CMPR2B7 (Bitfield-Mask: 0xffff) */ +/* ========================================================= AUX7 ========================================================== */ +#define CTIMER_AUX7_TMRB7EN23_Pos (30UL) /*!< CTIMER AUX7: TMRB7EN23 (Bit 30) */ +#define CTIMER_AUX7_TMRB7EN23_Msk (0x40000000UL) /*!< CTIMER AUX7: TMRB7EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX7_TMRB7POL23_Pos (29UL) /*!< CTIMER AUX7: TMRB7POL23 (Bit 29) */ +#define CTIMER_AUX7_TMRB7POL23_Msk (0x20000000UL) /*!< CTIMER AUX7: TMRB7POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX7_TMRB7TINV_Pos (28UL) /*!< CTIMER AUX7: TMRB7TINV (Bit 28) */ +#define CTIMER_AUX7_TMRB7TINV_Msk (0x10000000UL) /*!< CTIMER AUX7: TMRB7TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX7_TMRB7NOSYNC_Pos (27UL) /*!< CTIMER AUX7: TMRB7NOSYNC (Bit 27) */ +#define CTIMER_AUX7_TMRB7NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX7: TMRB7NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX7_TMRB7TRIG_Pos (23UL) /*!< CTIMER AUX7: TMRB7TRIG (Bit 23) */ +#define CTIMER_AUX7_TMRB7TRIG_Msk (0x7800000UL) /*!< CTIMER AUX7: TMRB7TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX7_TMRB7LMT_Pos (16UL) /*!< CTIMER AUX7: TMRB7LMT (Bit 16) */ +#define CTIMER_AUX7_TMRB7LMT_Msk (0x3f0000UL) /*!< CTIMER AUX7: TMRB7LMT (Bitfield-Mask: 0x3f) */ +#define CTIMER_AUX7_TMRA7EN23_Pos (14UL) /*!< CTIMER AUX7: TMRA7EN23 (Bit 14) */ +#define CTIMER_AUX7_TMRA7EN23_Msk (0x4000UL) /*!< CTIMER AUX7: TMRA7EN23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX7_TMRA7POL23_Pos (13UL) /*!< CTIMER AUX7: TMRA7POL23 (Bit 13) */ +#define CTIMER_AUX7_TMRA7POL23_Msk (0x2000UL) /*!< CTIMER AUX7: TMRA7POL23 (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX7_TMRA7TINV_Pos (12UL) /*!< CTIMER AUX7: TMRA7TINV (Bit 12) */ +#define CTIMER_AUX7_TMRA7TINV_Msk (0x1000UL) /*!< CTIMER AUX7: TMRA7TINV (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX7_TMRA7NOSYNC_Pos (11UL) /*!< CTIMER AUX7: TMRA7NOSYNC (Bit 11) */ +#define CTIMER_AUX7_TMRA7NOSYNC_Msk (0x800UL) /*!< CTIMER AUX7: TMRA7NOSYNC (Bitfield-Mask: 0x01) */ +#define CTIMER_AUX7_TMRA7TRIG_Pos (7UL) /*!< CTIMER AUX7: TMRA7TRIG (Bit 7) */ +#define CTIMER_AUX7_TMRA7TRIG_Msk (0x780UL) /*!< CTIMER AUX7: TMRA7TRIG (Bitfield-Mask: 0x0f) */ +#define CTIMER_AUX7_TMRA7LMT_Pos (0UL) /*!< CTIMER AUX7: TMRA7LMT (Bit 0) */ +#define CTIMER_AUX7_TMRA7LMT_Msk (0x7fUL) /*!< CTIMER AUX7: TMRA7LMT (Bitfield-Mask: 0x7f) */ +/* ======================================================== GLOBEN ========================================================= */ +#define CTIMER_GLOBEN_ENB7_Pos (15UL) /*!< CTIMER GLOBEN: ENB7 (Bit 15) */ +#define CTIMER_GLOBEN_ENB7_Msk (0x8000UL) /*!< CTIMER GLOBEN: ENB7 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENA7_Pos (14UL) /*!< CTIMER GLOBEN: ENA7 (Bit 14) */ +#define CTIMER_GLOBEN_ENA7_Msk (0x4000UL) /*!< CTIMER GLOBEN: ENA7 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENB6_Pos (13UL) /*!< CTIMER GLOBEN: ENB6 (Bit 13) */ +#define CTIMER_GLOBEN_ENB6_Msk (0x2000UL) /*!< CTIMER GLOBEN: ENB6 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENA6_Pos (12UL) /*!< CTIMER GLOBEN: ENA6 (Bit 12) */ +#define CTIMER_GLOBEN_ENA6_Msk (0x1000UL) /*!< CTIMER GLOBEN: ENA6 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENB5_Pos (11UL) /*!< CTIMER GLOBEN: ENB5 (Bit 11) */ +#define CTIMER_GLOBEN_ENB5_Msk (0x800UL) /*!< CTIMER GLOBEN: ENB5 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENA5_Pos (10UL) /*!< CTIMER GLOBEN: ENA5 (Bit 10) */ +#define CTIMER_GLOBEN_ENA5_Msk (0x400UL) /*!< CTIMER GLOBEN: ENA5 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENB4_Pos (9UL) /*!< CTIMER GLOBEN: ENB4 (Bit 9) */ +#define CTIMER_GLOBEN_ENB4_Msk (0x200UL) /*!< CTIMER GLOBEN: ENB4 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENA4_Pos (8UL) /*!< CTIMER GLOBEN: ENA4 (Bit 8) */ +#define CTIMER_GLOBEN_ENA4_Msk (0x100UL) /*!< CTIMER GLOBEN: ENA4 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENB3_Pos (7UL) /*!< CTIMER GLOBEN: ENB3 (Bit 7) */ +#define CTIMER_GLOBEN_ENB3_Msk (0x80UL) /*!< CTIMER GLOBEN: ENB3 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENA3_Pos (6UL) /*!< CTIMER GLOBEN: ENA3 (Bit 6) */ +#define CTIMER_GLOBEN_ENA3_Msk (0x40UL) /*!< CTIMER GLOBEN: ENA3 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENB2_Pos (5UL) /*!< CTIMER GLOBEN: ENB2 (Bit 5) */ +#define CTIMER_GLOBEN_ENB2_Msk (0x20UL) /*!< CTIMER GLOBEN: ENB2 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENA2_Pos (4UL) /*!< CTIMER GLOBEN: ENA2 (Bit 4) */ +#define CTIMER_GLOBEN_ENA2_Msk (0x10UL) /*!< CTIMER GLOBEN: ENA2 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENB1_Pos (3UL) /*!< CTIMER GLOBEN: ENB1 (Bit 3) */ +#define CTIMER_GLOBEN_ENB1_Msk (0x8UL) /*!< CTIMER GLOBEN: ENB1 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENA1_Pos (2UL) /*!< CTIMER GLOBEN: ENA1 (Bit 2) */ +#define CTIMER_GLOBEN_ENA1_Msk (0x4UL) /*!< CTIMER GLOBEN: ENA1 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENB0_Pos (1UL) /*!< CTIMER GLOBEN: ENB0 (Bit 1) */ +#define CTIMER_GLOBEN_ENB0_Msk (0x2UL) /*!< CTIMER GLOBEN: ENB0 (Bitfield-Mask: 0x01) */ +#define CTIMER_GLOBEN_ENA0_Pos (0UL) /*!< CTIMER GLOBEN: ENA0 (Bit 0) */ +#define CTIMER_GLOBEN_ENA0_Msk (0x1UL) /*!< CTIMER GLOBEN: ENA0 (Bitfield-Mask: 0x01) */ +/* ======================================================== OUTCFG0 ======================================================== */ +#define CTIMER_OUTCFG0_CFG9_Pos (28UL) /*!< CTIMER OUTCFG0: CFG9 (Bit 28) */ +#define CTIMER_OUTCFG0_CFG9_Msk (0x70000000UL) /*!< CTIMER OUTCFG0: CFG9 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG0_CFG8_Pos (25UL) /*!< CTIMER OUTCFG0: CFG8 (Bit 25) */ +#define CTIMER_OUTCFG0_CFG8_Msk (0xe000000UL) /*!< CTIMER OUTCFG0: CFG8 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG0_CFG7_Pos (22UL) /*!< CTIMER OUTCFG0: CFG7 (Bit 22) */ +#define CTIMER_OUTCFG0_CFG7_Msk (0x1c00000UL) /*!< CTIMER OUTCFG0: CFG7 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG0_CFG6_Pos (19UL) /*!< CTIMER OUTCFG0: CFG6 (Bit 19) */ +#define CTIMER_OUTCFG0_CFG6_Msk (0x380000UL) /*!< CTIMER OUTCFG0: CFG6 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG0_CFG5_Pos (16UL) /*!< CTIMER OUTCFG0: CFG5 (Bit 16) */ +#define CTIMER_OUTCFG0_CFG5_Msk (0x70000UL) /*!< CTIMER OUTCFG0: CFG5 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG0_CFG4_Pos (12UL) /*!< CTIMER OUTCFG0: CFG4 (Bit 12) */ +#define CTIMER_OUTCFG0_CFG4_Msk (0x7000UL) /*!< CTIMER OUTCFG0: CFG4 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG0_CFG3_Pos (9UL) /*!< CTIMER OUTCFG0: CFG3 (Bit 9) */ +#define CTIMER_OUTCFG0_CFG3_Msk (0xe00UL) /*!< CTIMER OUTCFG0: CFG3 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG0_CFG2_Pos (6UL) /*!< CTIMER OUTCFG0: CFG2 (Bit 6) */ +#define CTIMER_OUTCFG0_CFG2_Msk (0x1c0UL) /*!< CTIMER OUTCFG0: CFG2 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG0_CFG1_Pos (3UL) /*!< CTIMER OUTCFG0: CFG1 (Bit 3) */ +#define CTIMER_OUTCFG0_CFG1_Msk (0x38UL) /*!< CTIMER OUTCFG0: CFG1 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG0_CFG0_Pos (0UL) /*!< CTIMER OUTCFG0: CFG0 (Bit 0) */ +#define CTIMER_OUTCFG0_CFG0_Msk (0x7UL) /*!< CTIMER OUTCFG0: CFG0 (Bitfield-Mask: 0x07) */ +/* ======================================================== OUTCFG1 ======================================================== */ +#define CTIMER_OUTCFG1_CFG19_Pos (28UL) /*!< CTIMER OUTCFG1: CFG19 (Bit 28) */ +#define CTIMER_OUTCFG1_CFG19_Msk (0x70000000UL) /*!< CTIMER OUTCFG1: CFG19 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG1_CFG18_Pos (25UL) /*!< CTIMER OUTCFG1: CFG18 (Bit 25) */ +#define CTIMER_OUTCFG1_CFG18_Msk (0xe000000UL) /*!< CTIMER OUTCFG1: CFG18 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG1_CFG17_Pos (22UL) /*!< CTIMER OUTCFG1: CFG17 (Bit 22) */ +#define CTIMER_OUTCFG1_CFG17_Msk (0x1c00000UL) /*!< CTIMER OUTCFG1: CFG17 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG1_CFG16_Pos (19UL) /*!< CTIMER OUTCFG1: CFG16 (Bit 19) */ +#define CTIMER_OUTCFG1_CFG16_Msk (0x380000UL) /*!< CTIMER OUTCFG1: CFG16 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG1_CFG15_Pos (16UL) /*!< CTIMER OUTCFG1: CFG15 (Bit 16) */ +#define CTIMER_OUTCFG1_CFG15_Msk (0x70000UL) /*!< CTIMER OUTCFG1: CFG15 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG1_CFG14_Pos (12UL) /*!< CTIMER OUTCFG1: CFG14 (Bit 12) */ +#define CTIMER_OUTCFG1_CFG14_Msk (0x7000UL) /*!< CTIMER OUTCFG1: CFG14 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG1_CFG13_Pos (9UL) /*!< CTIMER OUTCFG1: CFG13 (Bit 9) */ +#define CTIMER_OUTCFG1_CFG13_Msk (0xe00UL) /*!< CTIMER OUTCFG1: CFG13 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG1_CFG12_Pos (6UL) /*!< CTIMER OUTCFG1: CFG12 (Bit 6) */ +#define CTIMER_OUTCFG1_CFG12_Msk (0x1c0UL) /*!< CTIMER OUTCFG1: CFG12 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG1_CFG11_Pos (3UL) /*!< CTIMER OUTCFG1: CFG11 (Bit 3) */ +#define CTIMER_OUTCFG1_CFG11_Msk (0x38UL) /*!< CTIMER OUTCFG1: CFG11 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG1_CFG10_Pos (0UL) /*!< CTIMER OUTCFG1: CFG10 (Bit 0) */ +#define CTIMER_OUTCFG1_CFG10_Msk (0x7UL) /*!< CTIMER OUTCFG1: CFG10 (Bitfield-Mask: 0x07) */ +/* ======================================================== OUTCFG2 ======================================================== */ +#define CTIMER_OUTCFG2_CFG29_Pos (28UL) /*!< CTIMER OUTCFG2: CFG29 (Bit 28) */ +#define CTIMER_OUTCFG2_CFG29_Msk (0x70000000UL) /*!< CTIMER OUTCFG2: CFG29 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG2_CFG28_Pos (25UL) /*!< CTIMER OUTCFG2: CFG28 (Bit 25) */ +#define CTIMER_OUTCFG2_CFG28_Msk (0xe000000UL) /*!< CTIMER OUTCFG2: CFG28 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG2_CFG27_Pos (22UL) /*!< CTIMER OUTCFG2: CFG27 (Bit 22) */ +#define CTIMER_OUTCFG2_CFG27_Msk (0x1c00000UL) /*!< CTIMER OUTCFG2: CFG27 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG2_CFG26_Pos (19UL) /*!< CTIMER OUTCFG2: CFG26 (Bit 19) */ +#define CTIMER_OUTCFG2_CFG26_Msk (0x380000UL) /*!< CTIMER OUTCFG2: CFG26 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG2_CFG25_Pos (16UL) /*!< CTIMER OUTCFG2: CFG25 (Bit 16) */ +#define CTIMER_OUTCFG2_CFG25_Msk (0x70000UL) /*!< CTIMER OUTCFG2: CFG25 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG2_CFG24_Pos (12UL) /*!< CTIMER OUTCFG2: CFG24 (Bit 12) */ +#define CTIMER_OUTCFG2_CFG24_Msk (0x7000UL) /*!< CTIMER OUTCFG2: CFG24 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG2_CFG23_Pos (9UL) /*!< CTIMER OUTCFG2: CFG23 (Bit 9) */ +#define CTIMER_OUTCFG2_CFG23_Msk (0xe00UL) /*!< CTIMER OUTCFG2: CFG23 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG2_CFG22_Pos (6UL) /*!< CTIMER OUTCFG2: CFG22 (Bit 6) */ +#define CTIMER_OUTCFG2_CFG22_Msk (0x1c0UL) /*!< CTIMER OUTCFG2: CFG22 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG2_CFG21_Pos (3UL) /*!< CTIMER OUTCFG2: CFG21 (Bit 3) */ +#define CTIMER_OUTCFG2_CFG21_Msk (0x38UL) /*!< CTIMER OUTCFG2: CFG21 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG2_CFG20_Pos (0UL) /*!< CTIMER OUTCFG2: CFG20 (Bit 0) */ +#define CTIMER_OUTCFG2_CFG20_Msk (0x7UL) /*!< CTIMER OUTCFG2: CFG20 (Bitfield-Mask: 0x07) */ +/* ======================================================== OUTCFG3 ======================================================== */ +#define CTIMER_OUTCFG3_CFG31_Pos (3UL) /*!< CTIMER OUTCFG3: CFG31 (Bit 3) */ +#define CTIMER_OUTCFG3_CFG31_Msk (0x38UL) /*!< CTIMER OUTCFG3: CFG31 (Bitfield-Mask: 0x07) */ +#define CTIMER_OUTCFG3_CFG30_Pos (0UL) /*!< CTIMER OUTCFG3: CFG30 (Bit 0) */ +#define CTIMER_OUTCFG3_CFG30_Msk (0x7UL) /*!< CTIMER OUTCFG3: CFG30 (Bitfield-Mask: 0x07) */ +/* ========================================================= INCFG ========================================================= */ +#define CTIMER_INCFG_CFGB7_Pos (15UL) /*!< CTIMER INCFG: CFGB7 (Bit 15) */ +#define CTIMER_INCFG_CFGB7_Msk (0x8000UL) /*!< CTIMER INCFG: CFGB7 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGA7_Pos (14UL) /*!< CTIMER INCFG: CFGA7 (Bit 14) */ +#define CTIMER_INCFG_CFGA7_Msk (0x4000UL) /*!< CTIMER INCFG: CFGA7 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGB6_Pos (13UL) /*!< CTIMER INCFG: CFGB6 (Bit 13) */ +#define CTIMER_INCFG_CFGB6_Msk (0x2000UL) /*!< CTIMER INCFG: CFGB6 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGA6_Pos (12UL) /*!< CTIMER INCFG: CFGA6 (Bit 12) */ +#define CTIMER_INCFG_CFGA6_Msk (0x1000UL) /*!< CTIMER INCFG: CFGA6 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGB5_Pos (11UL) /*!< CTIMER INCFG: CFGB5 (Bit 11) */ +#define CTIMER_INCFG_CFGB5_Msk (0x800UL) /*!< CTIMER INCFG: CFGB5 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGA5_Pos (10UL) /*!< CTIMER INCFG: CFGA5 (Bit 10) */ +#define CTIMER_INCFG_CFGA5_Msk (0x400UL) /*!< CTIMER INCFG: CFGA5 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGB4_Pos (9UL) /*!< CTIMER INCFG: CFGB4 (Bit 9) */ +#define CTIMER_INCFG_CFGB4_Msk (0x200UL) /*!< CTIMER INCFG: CFGB4 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGA4_Pos (8UL) /*!< CTIMER INCFG: CFGA4 (Bit 8) */ +#define CTIMER_INCFG_CFGA4_Msk (0x100UL) /*!< CTIMER INCFG: CFGA4 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGB3_Pos (7UL) /*!< CTIMER INCFG: CFGB3 (Bit 7) */ +#define CTIMER_INCFG_CFGB3_Msk (0x80UL) /*!< CTIMER INCFG: CFGB3 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGA3_Pos (6UL) /*!< CTIMER INCFG: CFGA3 (Bit 6) */ +#define CTIMER_INCFG_CFGA3_Msk (0x40UL) /*!< CTIMER INCFG: CFGA3 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGB2_Pos (5UL) /*!< CTIMER INCFG: CFGB2 (Bit 5) */ +#define CTIMER_INCFG_CFGB2_Msk (0x20UL) /*!< CTIMER INCFG: CFGB2 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGA2_Pos (4UL) /*!< CTIMER INCFG: CFGA2 (Bit 4) */ +#define CTIMER_INCFG_CFGA2_Msk (0x10UL) /*!< CTIMER INCFG: CFGA2 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGB1_Pos (3UL) /*!< CTIMER INCFG: CFGB1 (Bit 3) */ +#define CTIMER_INCFG_CFGB1_Msk (0x8UL) /*!< CTIMER INCFG: CFGB1 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGA1_Pos (2UL) /*!< CTIMER INCFG: CFGA1 (Bit 2) */ +#define CTIMER_INCFG_CFGA1_Msk (0x4UL) /*!< CTIMER INCFG: CFGA1 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGB0_Pos (1UL) /*!< CTIMER INCFG: CFGB0 (Bit 1) */ +#define CTIMER_INCFG_CFGB0_Msk (0x2UL) /*!< CTIMER INCFG: CFGB0 (Bitfield-Mask: 0x01) */ +#define CTIMER_INCFG_CFGA0_Pos (0UL) /*!< CTIMER INCFG: CFGA0 (Bit 0) */ +#define CTIMER_INCFG_CFGA0_Msk (0x1UL) /*!< CTIMER INCFG: CFGA0 (Bitfield-Mask: 0x01) */ +/* ========================================================= STCFG ========================================================= */ +#define CTIMER_STCFG_FREEZE_Pos (31UL) /*!< CTIMER STCFG: FREEZE (Bit 31) */ +#define CTIMER_STCFG_FREEZE_Msk (0x80000000UL) /*!< CTIMER STCFG: FREEZE (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_CLEAR_Pos (30UL) /*!< CTIMER STCFG: CLEAR (Bit 30) */ +#define CTIMER_STCFG_CLEAR_Msk (0x40000000UL) /*!< CTIMER STCFG: CLEAR (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_COMPARE_H_EN_Pos (15UL) /*!< CTIMER STCFG: COMPARE_H_EN (Bit 15) */ +#define CTIMER_STCFG_COMPARE_H_EN_Msk (0x8000UL) /*!< CTIMER STCFG: COMPARE_H_EN (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_COMPARE_G_EN_Pos (14UL) /*!< CTIMER STCFG: COMPARE_G_EN (Bit 14) */ +#define CTIMER_STCFG_COMPARE_G_EN_Msk (0x4000UL) /*!< CTIMER STCFG: COMPARE_G_EN (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_COMPARE_F_EN_Pos (13UL) /*!< CTIMER STCFG: COMPARE_F_EN (Bit 13) */ +#define CTIMER_STCFG_COMPARE_F_EN_Msk (0x2000UL) /*!< CTIMER STCFG: COMPARE_F_EN (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_COMPARE_E_EN_Pos (12UL) /*!< CTIMER STCFG: COMPARE_E_EN (Bit 12) */ +#define CTIMER_STCFG_COMPARE_E_EN_Msk (0x1000UL) /*!< CTIMER STCFG: COMPARE_E_EN (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_COMPARE_D_EN_Pos (11UL) /*!< CTIMER STCFG: COMPARE_D_EN (Bit 11) */ +#define CTIMER_STCFG_COMPARE_D_EN_Msk (0x800UL) /*!< CTIMER STCFG: COMPARE_D_EN (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_COMPARE_C_EN_Pos (10UL) /*!< CTIMER STCFG: COMPARE_C_EN (Bit 10) */ +#define CTIMER_STCFG_COMPARE_C_EN_Msk (0x400UL) /*!< CTIMER STCFG: COMPARE_C_EN (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_COMPARE_B_EN_Pos (9UL) /*!< CTIMER STCFG: COMPARE_B_EN (Bit 9) */ +#define CTIMER_STCFG_COMPARE_B_EN_Msk (0x200UL) /*!< CTIMER STCFG: COMPARE_B_EN (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_COMPARE_A_EN_Pos (8UL) /*!< CTIMER STCFG: COMPARE_A_EN (Bit 8) */ +#define CTIMER_STCFG_COMPARE_A_EN_Msk (0x100UL) /*!< CTIMER STCFG: COMPARE_A_EN (Bitfield-Mask: 0x01) */ +#define CTIMER_STCFG_CLKSEL_Pos (0UL) /*!< CTIMER STCFG: CLKSEL (Bit 0) */ +#define CTIMER_STCFG_CLKSEL_Msk (0xfUL) /*!< CTIMER STCFG: CLKSEL (Bitfield-Mask: 0x0f) */ +/* ========================================================= STTMR ========================================================= */ +#define CTIMER_STTMR_STTMR_Pos (0UL) /*!< CTIMER STTMR: STTMR (Bit 0) */ +#define CTIMER_STTMR_STTMR_Msk (0xffffffffUL) /*!< CTIMER STTMR: STTMR (Bitfield-Mask: 0xffffffff) */ +/* ==================================================== CAPTURECONTROL ===================================================== */ +#define CTIMER_CAPTURECONTROL_CAPTURE3_Pos (3UL) /*!< CTIMER CAPTURECONTROL: CAPTURE3 (Bit 3) */ +#define CTIMER_CAPTURECONTROL_CAPTURE3_Msk (0x8UL) /*!< CTIMER CAPTURECONTROL: CAPTURE3 (Bitfield-Mask: 0x01) */ +#define CTIMER_CAPTURECONTROL_CAPTURE2_Pos (2UL) /*!< CTIMER CAPTURECONTROL: CAPTURE2 (Bit 2) */ +#define CTIMER_CAPTURECONTROL_CAPTURE2_Msk (0x4UL) /*!< CTIMER CAPTURECONTROL: CAPTURE2 (Bitfield-Mask: 0x01) */ +#define CTIMER_CAPTURECONTROL_CAPTURE1_Pos (1UL) /*!< CTIMER CAPTURECONTROL: CAPTURE1 (Bit 1) */ +#define CTIMER_CAPTURECONTROL_CAPTURE1_Msk (0x2UL) /*!< CTIMER CAPTURECONTROL: CAPTURE1 (Bitfield-Mask: 0x01) */ +#define CTIMER_CAPTURECONTROL_CAPTURE0_Pos (0UL) /*!< CTIMER CAPTURECONTROL: CAPTURE0 (Bit 0) */ +#define CTIMER_CAPTURECONTROL_CAPTURE0_Msk (0x1UL) /*!< CTIMER CAPTURECONTROL: CAPTURE0 (Bitfield-Mask: 0x01) */ +/* ======================================================== SCMPR0 ========================================================= */ +#define CTIMER_SCMPR0_SCMPR0_Pos (0UL) /*!< CTIMER SCMPR0: SCMPR0 (Bit 0) */ +#define CTIMER_SCMPR0_SCMPR0_Msk (0xffffffffUL) /*!< CTIMER SCMPR0: SCMPR0 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCMPR1 ========================================================= */ +#define CTIMER_SCMPR1_SCMPR1_Pos (0UL) /*!< CTIMER SCMPR1: SCMPR1 (Bit 0) */ +#define CTIMER_SCMPR1_SCMPR1_Msk (0xffffffffUL) /*!< CTIMER SCMPR1: SCMPR1 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCMPR2 ========================================================= */ +#define CTIMER_SCMPR2_SCMPR2_Pos (0UL) /*!< CTIMER SCMPR2: SCMPR2 (Bit 0) */ +#define CTIMER_SCMPR2_SCMPR2_Msk (0xffffffffUL) /*!< CTIMER SCMPR2: SCMPR2 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCMPR3 ========================================================= */ +#define CTIMER_SCMPR3_SCMPR3_Pos (0UL) /*!< CTIMER SCMPR3: SCMPR3 (Bit 0) */ +#define CTIMER_SCMPR3_SCMPR3_Msk (0xffffffffUL) /*!< CTIMER SCMPR3: SCMPR3 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCMPR4 ========================================================= */ +#define CTIMER_SCMPR4_SCMPR4_Pos (0UL) /*!< CTIMER SCMPR4: SCMPR4 (Bit 0) */ +#define CTIMER_SCMPR4_SCMPR4_Msk (0xffffffffUL) /*!< CTIMER SCMPR4: SCMPR4 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCMPR5 ========================================================= */ +#define CTIMER_SCMPR5_SCMPR5_Pos (0UL) /*!< CTIMER SCMPR5: SCMPR5 (Bit 0) */ +#define CTIMER_SCMPR5_SCMPR5_Msk (0xffffffffUL) /*!< CTIMER SCMPR5: SCMPR5 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCMPR6 ========================================================= */ +#define CTIMER_SCMPR6_SCMPR6_Pos (0UL) /*!< CTIMER SCMPR6: SCMPR6 (Bit 0) */ +#define CTIMER_SCMPR6_SCMPR6_Msk (0xffffffffUL) /*!< CTIMER SCMPR6: SCMPR6 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCMPR7 ========================================================= */ +#define CTIMER_SCMPR7_SCMPR7_Pos (0UL) /*!< CTIMER SCMPR7: SCMPR7 (Bit 0) */ +#define CTIMER_SCMPR7_SCMPR7_Msk (0xffffffffUL) /*!< CTIMER SCMPR7: SCMPR7 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCAPT0 ========================================================= */ +#define CTIMER_SCAPT0_SCAPT0_Pos (0UL) /*!< CTIMER SCAPT0: SCAPT0 (Bit 0) */ +#define CTIMER_SCAPT0_SCAPT0_Msk (0xffffffffUL) /*!< CTIMER SCAPT0: SCAPT0 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCAPT1 ========================================================= */ +#define CTIMER_SCAPT1_SCAPT1_Pos (0UL) /*!< CTIMER SCAPT1: SCAPT1 (Bit 0) */ +#define CTIMER_SCAPT1_SCAPT1_Msk (0xffffffffUL) /*!< CTIMER SCAPT1: SCAPT1 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCAPT2 ========================================================= */ +#define CTIMER_SCAPT2_SCAPT2_Pos (0UL) /*!< CTIMER SCAPT2: SCAPT2 (Bit 0) */ +#define CTIMER_SCAPT2_SCAPT2_Msk (0xffffffffUL) /*!< CTIMER SCAPT2: SCAPT2 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== SCAPT3 ========================================================= */ +#define CTIMER_SCAPT3_SCAPT3_Pos (0UL) /*!< CTIMER SCAPT3: SCAPT3 (Bit 0) */ +#define CTIMER_SCAPT3_SCAPT3_Msk (0xffffffffUL) /*!< CTIMER SCAPT3: SCAPT3 (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= SNVR0 ========================================================= */ +#define CTIMER_SNVR0_SNVR0_Pos (0UL) /*!< CTIMER SNVR0: SNVR0 (Bit 0) */ +#define CTIMER_SNVR0_SNVR0_Msk (0xffffffffUL) /*!< CTIMER SNVR0: SNVR0 (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= SNVR1 ========================================================= */ +#define CTIMER_SNVR1_SNVR1_Pos (0UL) /*!< CTIMER SNVR1: SNVR1 (Bit 0) */ +#define CTIMER_SNVR1_SNVR1_Msk (0xffffffffUL) /*!< CTIMER SNVR1: SNVR1 (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= SNVR2 ========================================================= */ +#define CTIMER_SNVR2_SNVR2_Pos (0UL) /*!< CTIMER SNVR2: SNVR2 (Bit 0) */ +#define CTIMER_SNVR2_SNVR2_Msk (0xffffffffUL) /*!< CTIMER SNVR2: SNVR2 (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= SNVR3 ========================================================= */ +#define CTIMER_SNVR3_SNVR3_Pos (0UL) /*!< CTIMER SNVR3: SNVR3 (Bit 0) */ +#define CTIMER_SNVR3_SNVR3_Msk (0xffffffffUL) /*!< CTIMER SNVR3: SNVR3 (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= INTEN ========================================================= */ +#define CTIMER_INTEN_CTMRB7C1INT_Pos (31UL) /*!< CTIMER INTEN: CTMRB7C1INT (Bit 31) */ +#define CTIMER_INTEN_CTMRB7C1INT_Msk (0x80000000UL) /*!< CTIMER INTEN: CTMRB7C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA7C1INT_Pos (30UL) /*!< CTIMER INTEN: CTMRA7C1INT (Bit 30) */ +#define CTIMER_INTEN_CTMRA7C1INT_Msk (0x40000000UL) /*!< CTIMER INTEN: CTMRA7C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB6C1INT_Pos (29UL) /*!< CTIMER INTEN: CTMRB6C1INT (Bit 29) */ +#define CTIMER_INTEN_CTMRB6C1INT_Msk (0x20000000UL) /*!< CTIMER INTEN: CTMRB6C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA6C1INT_Pos (28UL) /*!< CTIMER INTEN: CTMRA6C1INT (Bit 28) */ +#define CTIMER_INTEN_CTMRA6C1INT_Msk (0x10000000UL) /*!< CTIMER INTEN: CTMRA6C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB5C1INT_Pos (27UL) /*!< CTIMER INTEN: CTMRB5C1INT (Bit 27) */ +#define CTIMER_INTEN_CTMRB5C1INT_Msk (0x8000000UL) /*!< CTIMER INTEN: CTMRB5C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA5C1INT_Pos (26UL) /*!< CTIMER INTEN: CTMRA5C1INT (Bit 26) */ +#define CTIMER_INTEN_CTMRA5C1INT_Msk (0x4000000UL) /*!< CTIMER INTEN: CTMRA5C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB4C1INT_Pos (25UL) /*!< CTIMER INTEN: CTMRB4C1INT (Bit 25) */ +#define CTIMER_INTEN_CTMRB4C1INT_Msk (0x2000000UL) /*!< CTIMER INTEN: CTMRB4C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA4C1INT_Pos (24UL) /*!< CTIMER INTEN: CTMRA4C1INT (Bit 24) */ +#define CTIMER_INTEN_CTMRA4C1INT_Msk (0x1000000UL) /*!< CTIMER INTEN: CTMRA4C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB3C1INT_Pos (23UL) /*!< CTIMER INTEN: CTMRB3C1INT (Bit 23) */ +#define CTIMER_INTEN_CTMRB3C1INT_Msk (0x800000UL) /*!< CTIMER INTEN: CTMRB3C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA3C1INT_Pos (22UL) /*!< CTIMER INTEN: CTMRA3C1INT (Bit 22) */ +#define CTIMER_INTEN_CTMRA3C1INT_Msk (0x400000UL) /*!< CTIMER INTEN: CTMRA3C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB2C1INT_Pos (21UL) /*!< CTIMER INTEN: CTMRB2C1INT (Bit 21) */ +#define CTIMER_INTEN_CTMRB2C1INT_Msk (0x200000UL) /*!< CTIMER INTEN: CTMRB2C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA2C1INT_Pos (20UL) /*!< CTIMER INTEN: CTMRA2C1INT (Bit 20) */ +#define CTIMER_INTEN_CTMRA2C1INT_Msk (0x100000UL) /*!< CTIMER INTEN: CTMRA2C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB1C1INT_Pos (19UL) /*!< CTIMER INTEN: CTMRB1C1INT (Bit 19) */ +#define CTIMER_INTEN_CTMRB1C1INT_Msk (0x80000UL) /*!< CTIMER INTEN: CTMRB1C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA1C1INT_Pos (18UL) /*!< CTIMER INTEN: CTMRA1C1INT (Bit 18) */ +#define CTIMER_INTEN_CTMRA1C1INT_Msk (0x40000UL) /*!< CTIMER INTEN: CTMRA1C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB0C1INT_Pos (17UL) /*!< CTIMER INTEN: CTMRB0C1INT (Bit 17) */ +#define CTIMER_INTEN_CTMRB0C1INT_Msk (0x20000UL) /*!< CTIMER INTEN: CTMRB0C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA0C1INT_Pos (16UL) /*!< CTIMER INTEN: CTMRA0C1INT (Bit 16) */ +#define CTIMER_INTEN_CTMRA0C1INT_Msk (0x10000UL) /*!< CTIMER INTEN: CTMRA0C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB7C0INT_Pos (15UL) /*!< CTIMER INTEN: CTMRB7C0INT (Bit 15) */ +#define CTIMER_INTEN_CTMRB7C0INT_Msk (0x8000UL) /*!< CTIMER INTEN: CTMRB7C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA7C0INT_Pos (14UL) /*!< CTIMER INTEN: CTMRA7C0INT (Bit 14) */ +#define CTIMER_INTEN_CTMRA7C0INT_Msk (0x4000UL) /*!< CTIMER INTEN: CTMRA7C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB6C0INT_Pos (13UL) /*!< CTIMER INTEN: CTMRB6C0INT (Bit 13) */ +#define CTIMER_INTEN_CTMRB6C0INT_Msk (0x2000UL) /*!< CTIMER INTEN: CTMRB6C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA6C0INT_Pos (12UL) /*!< CTIMER INTEN: CTMRA6C0INT (Bit 12) */ +#define CTIMER_INTEN_CTMRA6C0INT_Msk (0x1000UL) /*!< CTIMER INTEN: CTMRA6C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB5C0INT_Pos (11UL) /*!< CTIMER INTEN: CTMRB5C0INT (Bit 11) */ +#define CTIMER_INTEN_CTMRB5C0INT_Msk (0x800UL) /*!< CTIMER INTEN: CTMRB5C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA5C0INT_Pos (10UL) /*!< CTIMER INTEN: CTMRA5C0INT (Bit 10) */ +#define CTIMER_INTEN_CTMRA5C0INT_Msk (0x400UL) /*!< CTIMER INTEN: CTMRA5C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB4C0INT_Pos (9UL) /*!< CTIMER INTEN: CTMRB4C0INT (Bit 9) */ +#define CTIMER_INTEN_CTMRB4C0INT_Msk (0x200UL) /*!< CTIMER INTEN: CTMRB4C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA4C0INT_Pos (8UL) /*!< CTIMER INTEN: CTMRA4C0INT (Bit 8) */ +#define CTIMER_INTEN_CTMRA4C0INT_Msk (0x100UL) /*!< CTIMER INTEN: CTMRA4C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB3C0INT_Pos (7UL) /*!< CTIMER INTEN: CTMRB3C0INT (Bit 7) */ +#define CTIMER_INTEN_CTMRB3C0INT_Msk (0x80UL) /*!< CTIMER INTEN: CTMRB3C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA3C0INT_Pos (6UL) /*!< CTIMER INTEN: CTMRA3C0INT (Bit 6) */ +#define CTIMER_INTEN_CTMRA3C0INT_Msk (0x40UL) /*!< CTIMER INTEN: CTMRA3C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB2C0INT_Pos (5UL) /*!< CTIMER INTEN: CTMRB2C0INT (Bit 5) */ +#define CTIMER_INTEN_CTMRB2C0INT_Msk (0x20UL) /*!< CTIMER INTEN: CTMRB2C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA2C0INT_Pos (4UL) /*!< CTIMER INTEN: CTMRA2C0INT (Bit 4) */ +#define CTIMER_INTEN_CTMRA2C0INT_Msk (0x10UL) /*!< CTIMER INTEN: CTMRA2C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB1C0INT_Pos (3UL) /*!< CTIMER INTEN: CTMRB1C0INT (Bit 3) */ +#define CTIMER_INTEN_CTMRB1C0INT_Msk (0x8UL) /*!< CTIMER INTEN: CTMRB1C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA1C0INT_Pos (2UL) /*!< CTIMER INTEN: CTMRA1C0INT (Bit 2) */ +#define CTIMER_INTEN_CTMRA1C0INT_Msk (0x4UL) /*!< CTIMER INTEN: CTMRA1C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRB0C0INT_Pos (1UL) /*!< CTIMER INTEN: CTMRB0C0INT (Bit 1) */ +#define CTIMER_INTEN_CTMRB0C0INT_Msk (0x2UL) /*!< CTIMER INTEN: CTMRB0C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTEN_CTMRA0C0INT_Pos (0UL) /*!< CTIMER INTEN: CTMRA0C0INT (Bit 0) */ +#define CTIMER_INTEN_CTMRA0C0INT_Msk (0x1UL) /*!< CTIMER INTEN: CTMRA0C0INT (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define CTIMER_INTSTAT_CTMRB7C1INT_Pos (31UL) /*!< CTIMER INTSTAT: CTMRB7C1INT (Bit 31) */ +#define CTIMER_INTSTAT_CTMRB7C1INT_Msk (0x80000000UL) /*!< CTIMER INTSTAT: CTMRB7C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA7C1INT_Pos (30UL) /*!< CTIMER INTSTAT: CTMRA7C1INT (Bit 30) */ +#define CTIMER_INTSTAT_CTMRA7C1INT_Msk (0x40000000UL) /*!< CTIMER INTSTAT: CTMRA7C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB6C1INT_Pos (29UL) /*!< CTIMER INTSTAT: CTMRB6C1INT (Bit 29) */ +#define CTIMER_INTSTAT_CTMRB6C1INT_Msk (0x20000000UL) /*!< CTIMER INTSTAT: CTMRB6C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA6C1INT_Pos (28UL) /*!< CTIMER INTSTAT: CTMRA6C1INT (Bit 28) */ +#define CTIMER_INTSTAT_CTMRA6C1INT_Msk (0x10000000UL) /*!< CTIMER INTSTAT: CTMRA6C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB5C1INT_Pos (27UL) /*!< CTIMER INTSTAT: CTMRB5C1INT (Bit 27) */ +#define CTIMER_INTSTAT_CTMRB5C1INT_Msk (0x8000000UL) /*!< CTIMER INTSTAT: CTMRB5C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA5C1INT_Pos (26UL) /*!< CTIMER INTSTAT: CTMRA5C1INT (Bit 26) */ +#define CTIMER_INTSTAT_CTMRA5C1INT_Msk (0x4000000UL) /*!< CTIMER INTSTAT: CTMRA5C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB4C1INT_Pos (25UL) /*!< CTIMER INTSTAT: CTMRB4C1INT (Bit 25) */ +#define CTIMER_INTSTAT_CTMRB4C1INT_Msk (0x2000000UL) /*!< CTIMER INTSTAT: CTMRB4C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA4C1INT_Pos (24UL) /*!< CTIMER INTSTAT: CTMRA4C1INT (Bit 24) */ +#define CTIMER_INTSTAT_CTMRA4C1INT_Msk (0x1000000UL) /*!< CTIMER INTSTAT: CTMRA4C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB3C1INT_Pos (23UL) /*!< CTIMER INTSTAT: CTMRB3C1INT (Bit 23) */ +#define CTIMER_INTSTAT_CTMRB3C1INT_Msk (0x800000UL) /*!< CTIMER INTSTAT: CTMRB3C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA3C1INT_Pos (22UL) /*!< CTIMER INTSTAT: CTMRA3C1INT (Bit 22) */ +#define CTIMER_INTSTAT_CTMRA3C1INT_Msk (0x400000UL) /*!< CTIMER INTSTAT: CTMRA3C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB2C1INT_Pos (21UL) /*!< CTIMER INTSTAT: CTMRB2C1INT (Bit 21) */ +#define CTIMER_INTSTAT_CTMRB2C1INT_Msk (0x200000UL) /*!< CTIMER INTSTAT: CTMRB2C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA2C1INT_Pos (20UL) /*!< CTIMER INTSTAT: CTMRA2C1INT (Bit 20) */ +#define CTIMER_INTSTAT_CTMRA2C1INT_Msk (0x100000UL) /*!< CTIMER INTSTAT: CTMRA2C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB1C1INT_Pos (19UL) /*!< CTIMER INTSTAT: CTMRB1C1INT (Bit 19) */ +#define CTIMER_INTSTAT_CTMRB1C1INT_Msk (0x80000UL) /*!< CTIMER INTSTAT: CTMRB1C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA1C1INT_Pos (18UL) /*!< CTIMER INTSTAT: CTMRA1C1INT (Bit 18) */ +#define CTIMER_INTSTAT_CTMRA1C1INT_Msk (0x40000UL) /*!< CTIMER INTSTAT: CTMRA1C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB0C1INT_Pos (17UL) /*!< CTIMER INTSTAT: CTMRB0C1INT (Bit 17) */ +#define CTIMER_INTSTAT_CTMRB0C1INT_Msk (0x20000UL) /*!< CTIMER INTSTAT: CTMRB0C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA0C1INT_Pos (16UL) /*!< CTIMER INTSTAT: CTMRA0C1INT (Bit 16) */ +#define CTIMER_INTSTAT_CTMRA0C1INT_Msk (0x10000UL) /*!< CTIMER INTSTAT: CTMRA0C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB7C0INT_Pos (15UL) /*!< CTIMER INTSTAT: CTMRB7C0INT (Bit 15) */ +#define CTIMER_INTSTAT_CTMRB7C0INT_Msk (0x8000UL) /*!< CTIMER INTSTAT: CTMRB7C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA7C0INT_Pos (14UL) /*!< CTIMER INTSTAT: CTMRA7C0INT (Bit 14) */ +#define CTIMER_INTSTAT_CTMRA7C0INT_Msk (0x4000UL) /*!< CTIMER INTSTAT: CTMRA7C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB6C0INT_Pos (13UL) /*!< CTIMER INTSTAT: CTMRB6C0INT (Bit 13) */ +#define CTIMER_INTSTAT_CTMRB6C0INT_Msk (0x2000UL) /*!< CTIMER INTSTAT: CTMRB6C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA6C0INT_Pos (12UL) /*!< CTIMER INTSTAT: CTMRA6C0INT (Bit 12) */ +#define CTIMER_INTSTAT_CTMRA6C0INT_Msk (0x1000UL) /*!< CTIMER INTSTAT: CTMRA6C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB5C0INT_Pos (11UL) /*!< CTIMER INTSTAT: CTMRB5C0INT (Bit 11) */ +#define CTIMER_INTSTAT_CTMRB5C0INT_Msk (0x800UL) /*!< CTIMER INTSTAT: CTMRB5C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA5C0INT_Pos (10UL) /*!< CTIMER INTSTAT: CTMRA5C0INT (Bit 10) */ +#define CTIMER_INTSTAT_CTMRA5C0INT_Msk (0x400UL) /*!< CTIMER INTSTAT: CTMRA5C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB4C0INT_Pos (9UL) /*!< CTIMER INTSTAT: CTMRB4C0INT (Bit 9) */ +#define CTIMER_INTSTAT_CTMRB4C0INT_Msk (0x200UL) /*!< CTIMER INTSTAT: CTMRB4C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA4C0INT_Pos (8UL) /*!< CTIMER INTSTAT: CTMRA4C0INT (Bit 8) */ +#define CTIMER_INTSTAT_CTMRA4C0INT_Msk (0x100UL) /*!< CTIMER INTSTAT: CTMRA4C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB3C0INT_Pos (7UL) /*!< CTIMER INTSTAT: CTMRB3C0INT (Bit 7) */ +#define CTIMER_INTSTAT_CTMRB3C0INT_Msk (0x80UL) /*!< CTIMER INTSTAT: CTMRB3C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA3C0INT_Pos (6UL) /*!< CTIMER INTSTAT: CTMRA3C0INT (Bit 6) */ +#define CTIMER_INTSTAT_CTMRA3C0INT_Msk (0x40UL) /*!< CTIMER INTSTAT: CTMRA3C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB2C0INT_Pos (5UL) /*!< CTIMER INTSTAT: CTMRB2C0INT (Bit 5) */ +#define CTIMER_INTSTAT_CTMRB2C0INT_Msk (0x20UL) /*!< CTIMER INTSTAT: CTMRB2C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA2C0INT_Pos (4UL) /*!< CTIMER INTSTAT: CTMRA2C0INT (Bit 4) */ +#define CTIMER_INTSTAT_CTMRA2C0INT_Msk (0x10UL) /*!< CTIMER INTSTAT: CTMRA2C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB1C0INT_Pos (3UL) /*!< CTIMER INTSTAT: CTMRB1C0INT (Bit 3) */ +#define CTIMER_INTSTAT_CTMRB1C0INT_Msk (0x8UL) /*!< CTIMER INTSTAT: CTMRB1C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA1C0INT_Pos (2UL) /*!< CTIMER INTSTAT: CTMRA1C0INT (Bit 2) */ +#define CTIMER_INTSTAT_CTMRA1C0INT_Msk (0x4UL) /*!< CTIMER INTSTAT: CTMRA1C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRB0C0INT_Pos (1UL) /*!< CTIMER INTSTAT: CTMRB0C0INT (Bit 1) */ +#define CTIMER_INTSTAT_CTMRB0C0INT_Msk (0x2UL) /*!< CTIMER INTSTAT: CTMRB0C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSTAT_CTMRA0C0INT_Pos (0UL) /*!< CTIMER INTSTAT: CTMRA0C0INT (Bit 0) */ +#define CTIMER_INTSTAT_CTMRA0C0INT_Msk (0x1UL) /*!< CTIMER INTSTAT: CTMRA0C0INT (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define CTIMER_INTCLR_CTMRB7C1INT_Pos (31UL) /*!< CTIMER INTCLR: CTMRB7C1INT (Bit 31) */ +#define CTIMER_INTCLR_CTMRB7C1INT_Msk (0x80000000UL) /*!< CTIMER INTCLR: CTMRB7C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA7C1INT_Pos (30UL) /*!< CTIMER INTCLR: CTMRA7C1INT (Bit 30) */ +#define CTIMER_INTCLR_CTMRA7C1INT_Msk (0x40000000UL) /*!< CTIMER INTCLR: CTMRA7C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB6C1INT_Pos (29UL) /*!< CTIMER INTCLR: CTMRB6C1INT (Bit 29) */ +#define CTIMER_INTCLR_CTMRB6C1INT_Msk (0x20000000UL) /*!< CTIMER INTCLR: CTMRB6C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA6C1INT_Pos (28UL) /*!< CTIMER INTCLR: CTMRA6C1INT (Bit 28) */ +#define CTIMER_INTCLR_CTMRA6C1INT_Msk (0x10000000UL) /*!< CTIMER INTCLR: CTMRA6C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB5C1INT_Pos (27UL) /*!< CTIMER INTCLR: CTMRB5C1INT (Bit 27) */ +#define CTIMER_INTCLR_CTMRB5C1INT_Msk (0x8000000UL) /*!< CTIMER INTCLR: CTMRB5C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA5C1INT_Pos (26UL) /*!< CTIMER INTCLR: CTMRA5C1INT (Bit 26) */ +#define CTIMER_INTCLR_CTMRA5C1INT_Msk (0x4000000UL) /*!< CTIMER INTCLR: CTMRA5C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB4C1INT_Pos (25UL) /*!< CTIMER INTCLR: CTMRB4C1INT (Bit 25) */ +#define CTIMER_INTCLR_CTMRB4C1INT_Msk (0x2000000UL) /*!< CTIMER INTCLR: CTMRB4C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA4C1INT_Pos (24UL) /*!< CTIMER INTCLR: CTMRA4C1INT (Bit 24) */ +#define CTIMER_INTCLR_CTMRA4C1INT_Msk (0x1000000UL) /*!< CTIMER INTCLR: CTMRA4C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB3C1INT_Pos (23UL) /*!< CTIMER INTCLR: CTMRB3C1INT (Bit 23) */ +#define CTIMER_INTCLR_CTMRB3C1INT_Msk (0x800000UL) /*!< CTIMER INTCLR: CTMRB3C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA3C1INT_Pos (22UL) /*!< CTIMER INTCLR: CTMRA3C1INT (Bit 22) */ +#define CTIMER_INTCLR_CTMRA3C1INT_Msk (0x400000UL) /*!< CTIMER INTCLR: CTMRA3C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB2C1INT_Pos (21UL) /*!< CTIMER INTCLR: CTMRB2C1INT (Bit 21) */ +#define CTIMER_INTCLR_CTMRB2C1INT_Msk (0x200000UL) /*!< CTIMER INTCLR: CTMRB2C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA2C1INT_Pos (20UL) /*!< CTIMER INTCLR: CTMRA2C1INT (Bit 20) */ +#define CTIMER_INTCLR_CTMRA2C1INT_Msk (0x100000UL) /*!< CTIMER INTCLR: CTMRA2C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB1C1INT_Pos (19UL) /*!< CTIMER INTCLR: CTMRB1C1INT (Bit 19) */ +#define CTIMER_INTCLR_CTMRB1C1INT_Msk (0x80000UL) /*!< CTIMER INTCLR: CTMRB1C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA1C1INT_Pos (18UL) /*!< CTIMER INTCLR: CTMRA1C1INT (Bit 18) */ +#define CTIMER_INTCLR_CTMRA1C1INT_Msk (0x40000UL) /*!< CTIMER INTCLR: CTMRA1C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB0C1INT_Pos (17UL) /*!< CTIMER INTCLR: CTMRB0C1INT (Bit 17) */ +#define CTIMER_INTCLR_CTMRB0C1INT_Msk (0x20000UL) /*!< CTIMER INTCLR: CTMRB0C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA0C1INT_Pos (16UL) /*!< CTIMER INTCLR: CTMRA0C1INT (Bit 16) */ +#define CTIMER_INTCLR_CTMRA0C1INT_Msk (0x10000UL) /*!< CTIMER INTCLR: CTMRA0C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB7C0INT_Pos (15UL) /*!< CTIMER INTCLR: CTMRB7C0INT (Bit 15) */ +#define CTIMER_INTCLR_CTMRB7C0INT_Msk (0x8000UL) /*!< CTIMER INTCLR: CTMRB7C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA7C0INT_Pos (14UL) /*!< CTIMER INTCLR: CTMRA7C0INT (Bit 14) */ +#define CTIMER_INTCLR_CTMRA7C0INT_Msk (0x4000UL) /*!< CTIMER INTCLR: CTMRA7C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB6C0INT_Pos (13UL) /*!< CTIMER INTCLR: CTMRB6C0INT (Bit 13) */ +#define CTIMER_INTCLR_CTMRB6C0INT_Msk (0x2000UL) /*!< CTIMER INTCLR: CTMRB6C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA6C0INT_Pos (12UL) /*!< CTIMER INTCLR: CTMRA6C0INT (Bit 12) */ +#define CTIMER_INTCLR_CTMRA6C0INT_Msk (0x1000UL) /*!< CTIMER INTCLR: CTMRA6C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB5C0INT_Pos (11UL) /*!< CTIMER INTCLR: CTMRB5C0INT (Bit 11) */ +#define CTIMER_INTCLR_CTMRB5C0INT_Msk (0x800UL) /*!< CTIMER INTCLR: CTMRB5C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA5C0INT_Pos (10UL) /*!< CTIMER INTCLR: CTMRA5C0INT (Bit 10) */ +#define CTIMER_INTCLR_CTMRA5C0INT_Msk (0x400UL) /*!< CTIMER INTCLR: CTMRA5C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB4C0INT_Pos (9UL) /*!< CTIMER INTCLR: CTMRB4C0INT (Bit 9) */ +#define CTIMER_INTCLR_CTMRB4C0INT_Msk (0x200UL) /*!< CTIMER INTCLR: CTMRB4C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA4C0INT_Pos (8UL) /*!< CTIMER INTCLR: CTMRA4C0INT (Bit 8) */ +#define CTIMER_INTCLR_CTMRA4C0INT_Msk (0x100UL) /*!< CTIMER INTCLR: CTMRA4C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB3C0INT_Pos (7UL) /*!< CTIMER INTCLR: CTMRB3C0INT (Bit 7) */ +#define CTIMER_INTCLR_CTMRB3C0INT_Msk (0x80UL) /*!< CTIMER INTCLR: CTMRB3C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA3C0INT_Pos (6UL) /*!< CTIMER INTCLR: CTMRA3C0INT (Bit 6) */ +#define CTIMER_INTCLR_CTMRA3C0INT_Msk (0x40UL) /*!< CTIMER INTCLR: CTMRA3C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB2C0INT_Pos (5UL) /*!< CTIMER INTCLR: CTMRB2C0INT (Bit 5) */ +#define CTIMER_INTCLR_CTMRB2C0INT_Msk (0x20UL) /*!< CTIMER INTCLR: CTMRB2C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA2C0INT_Pos (4UL) /*!< CTIMER INTCLR: CTMRA2C0INT (Bit 4) */ +#define CTIMER_INTCLR_CTMRA2C0INT_Msk (0x10UL) /*!< CTIMER INTCLR: CTMRA2C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB1C0INT_Pos (3UL) /*!< CTIMER INTCLR: CTMRB1C0INT (Bit 3) */ +#define CTIMER_INTCLR_CTMRB1C0INT_Msk (0x8UL) /*!< CTIMER INTCLR: CTMRB1C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA1C0INT_Pos (2UL) /*!< CTIMER INTCLR: CTMRA1C0INT (Bit 2) */ +#define CTIMER_INTCLR_CTMRA1C0INT_Msk (0x4UL) /*!< CTIMER INTCLR: CTMRA1C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRB0C0INT_Pos (1UL) /*!< CTIMER INTCLR: CTMRB0C0INT (Bit 1) */ +#define CTIMER_INTCLR_CTMRB0C0INT_Msk (0x2UL) /*!< CTIMER INTCLR: CTMRB0C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTCLR_CTMRA0C0INT_Pos (0UL) /*!< CTIMER INTCLR: CTMRA0C0INT (Bit 0) */ +#define CTIMER_INTCLR_CTMRA0C0INT_Msk (0x1UL) /*!< CTIMER INTCLR: CTMRA0C0INT (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define CTIMER_INTSET_CTMRB7C1INT_Pos (31UL) /*!< CTIMER INTSET: CTMRB7C1INT (Bit 31) */ +#define CTIMER_INTSET_CTMRB7C1INT_Msk (0x80000000UL) /*!< CTIMER INTSET: CTMRB7C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA7C1INT_Pos (30UL) /*!< CTIMER INTSET: CTMRA7C1INT (Bit 30) */ +#define CTIMER_INTSET_CTMRA7C1INT_Msk (0x40000000UL) /*!< CTIMER INTSET: CTMRA7C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB6C1INT_Pos (29UL) /*!< CTIMER INTSET: CTMRB6C1INT (Bit 29) */ +#define CTIMER_INTSET_CTMRB6C1INT_Msk (0x20000000UL) /*!< CTIMER INTSET: CTMRB6C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA6C1INT_Pos (28UL) /*!< CTIMER INTSET: CTMRA6C1INT (Bit 28) */ +#define CTIMER_INTSET_CTMRA6C1INT_Msk (0x10000000UL) /*!< CTIMER INTSET: CTMRA6C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB5C1INT_Pos (27UL) /*!< CTIMER INTSET: CTMRB5C1INT (Bit 27) */ +#define CTIMER_INTSET_CTMRB5C1INT_Msk (0x8000000UL) /*!< CTIMER INTSET: CTMRB5C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA5C1INT_Pos (26UL) /*!< CTIMER INTSET: CTMRA5C1INT (Bit 26) */ +#define CTIMER_INTSET_CTMRA5C1INT_Msk (0x4000000UL) /*!< CTIMER INTSET: CTMRA5C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB4C1INT_Pos (25UL) /*!< CTIMER INTSET: CTMRB4C1INT (Bit 25) */ +#define CTIMER_INTSET_CTMRB4C1INT_Msk (0x2000000UL) /*!< CTIMER INTSET: CTMRB4C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA4C1INT_Pos (24UL) /*!< CTIMER INTSET: CTMRA4C1INT (Bit 24) */ +#define CTIMER_INTSET_CTMRA4C1INT_Msk (0x1000000UL) /*!< CTIMER INTSET: CTMRA4C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB3C1INT_Pos (23UL) /*!< CTIMER INTSET: CTMRB3C1INT (Bit 23) */ +#define CTIMER_INTSET_CTMRB3C1INT_Msk (0x800000UL) /*!< CTIMER INTSET: CTMRB3C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA3C1INT_Pos (22UL) /*!< CTIMER INTSET: CTMRA3C1INT (Bit 22) */ +#define CTIMER_INTSET_CTMRA3C1INT_Msk (0x400000UL) /*!< CTIMER INTSET: CTMRA3C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB2C1INT_Pos (21UL) /*!< CTIMER INTSET: CTMRB2C1INT (Bit 21) */ +#define CTIMER_INTSET_CTMRB2C1INT_Msk (0x200000UL) /*!< CTIMER INTSET: CTMRB2C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA2C1INT_Pos (20UL) /*!< CTIMER INTSET: CTMRA2C1INT (Bit 20) */ +#define CTIMER_INTSET_CTMRA2C1INT_Msk (0x100000UL) /*!< CTIMER INTSET: CTMRA2C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB1C1INT_Pos (19UL) /*!< CTIMER INTSET: CTMRB1C1INT (Bit 19) */ +#define CTIMER_INTSET_CTMRB1C1INT_Msk (0x80000UL) /*!< CTIMER INTSET: CTMRB1C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA1C1INT_Pos (18UL) /*!< CTIMER INTSET: CTMRA1C1INT (Bit 18) */ +#define CTIMER_INTSET_CTMRA1C1INT_Msk (0x40000UL) /*!< CTIMER INTSET: CTMRA1C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB0C1INT_Pos (17UL) /*!< CTIMER INTSET: CTMRB0C1INT (Bit 17) */ +#define CTIMER_INTSET_CTMRB0C1INT_Msk (0x20000UL) /*!< CTIMER INTSET: CTMRB0C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA0C1INT_Pos (16UL) /*!< CTIMER INTSET: CTMRA0C1INT (Bit 16) */ +#define CTIMER_INTSET_CTMRA0C1INT_Msk (0x10000UL) /*!< CTIMER INTSET: CTMRA0C1INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB7C0INT_Pos (15UL) /*!< CTIMER INTSET: CTMRB7C0INT (Bit 15) */ +#define CTIMER_INTSET_CTMRB7C0INT_Msk (0x8000UL) /*!< CTIMER INTSET: CTMRB7C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA7C0INT_Pos (14UL) /*!< CTIMER INTSET: CTMRA7C0INT (Bit 14) */ +#define CTIMER_INTSET_CTMRA7C0INT_Msk (0x4000UL) /*!< CTIMER INTSET: CTMRA7C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB6C0INT_Pos (13UL) /*!< CTIMER INTSET: CTMRB6C0INT (Bit 13) */ +#define CTIMER_INTSET_CTMRB6C0INT_Msk (0x2000UL) /*!< CTIMER INTSET: CTMRB6C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA6C0INT_Pos (12UL) /*!< CTIMER INTSET: CTMRA6C0INT (Bit 12) */ +#define CTIMER_INTSET_CTMRA6C0INT_Msk (0x1000UL) /*!< CTIMER INTSET: CTMRA6C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB5C0INT_Pos (11UL) /*!< CTIMER INTSET: CTMRB5C0INT (Bit 11) */ +#define CTIMER_INTSET_CTMRB5C0INT_Msk (0x800UL) /*!< CTIMER INTSET: CTMRB5C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA5C0INT_Pos (10UL) /*!< CTIMER INTSET: CTMRA5C0INT (Bit 10) */ +#define CTIMER_INTSET_CTMRA5C0INT_Msk (0x400UL) /*!< CTIMER INTSET: CTMRA5C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB4C0INT_Pos (9UL) /*!< CTIMER INTSET: CTMRB4C0INT (Bit 9) */ +#define CTIMER_INTSET_CTMRB4C0INT_Msk (0x200UL) /*!< CTIMER INTSET: CTMRB4C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA4C0INT_Pos (8UL) /*!< CTIMER INTSET: CTMRA4C0INT (Bit 8) */ +#define CTIMER_INTSET_CTMRA4C0INT_Msk (0x100UL) /*!< CTIMER INTSET: CTMRA4C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB3C0INT_Pos (7UL) /*!< CTIMER INTSET: CTMRB3C0INT (Bit 7) */ +#define CTIMER_INTSET_CTMRB3C0INT_Msk (0x80UL) /*!< CTIMER INTSET: CTMRB3C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA3C0INT_Pos (6UL) /*!< CTIMER INTSET: CTMRA3C0INT (Bit 6) */ +#define CTIMER_INTSET_CTMRA3C0INT_Msk (0x40UL) /*!< CTIMER INTSET: CTMRA3C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB2C0INT_Pos (5UL) /*!< CTIMER INTSET: CTMRB2C0INT (Bit 5) */ +#define CTIMER_INTSET_CTMRB2C0INT_Msk (0x20UL) /*!< CTIMER INTSET: CTMRB2C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA2C0INT_Pos (4UL) /*!< CTIMER INTSET: CTMRA2C0INT (Bit 4) */ +#define CTIMER_INTSET_CTMRA2C0INT_Msk (0x10UL) /*!< CTIMER INTSET: CTMRA2C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB1C0INT_Pos (3UL) /*!< CTIMER INTSET: CTMRB1C0INT (Bit 3) */ +#define CTIMER_INTSET_CTMRB1C0INT_Msk (0x8UL) /*!< CTIMER INTSET: CTMRB1C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA1C0INT_Pos (2UL) /*!< CTIMER INTSET: CTMRA1C0INT (Bit 2) */ +#define CTIMER_INTSET_CTMRA1C0INT_Msk (0x4UL) /*!< CTIMER INTSET: CTMRA1C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRB0C0INT_Pos (1UL) /*!< CTIMER INTSET: CTMRB0C0INT (Bit 1) */ +#define CTIMER_INTSET_CTMRB0C0INT_Msk (0x2UL) /*!< CTIMER INTSET: CTMRB0C0INT (Bitfield-Mask: 0x01) */ +#define CTIMER_INTSET_CTMRA0C0INT_Pos (0UL) /*!< CTIMER INTSET: CTMRA0C0INT (Bit 0) */ +#define CTIMER_INTSET_CTMRA0C0INT_Msk (0x1UL) /*!< CTIMER INTSET: CTMRA0C0INT (Bitfield-Mask: 0x01) */ +/* ======================================================= STMINTEN ======================================================== */ +#define CTIMER_STMINTEN_CAPTURED_Pos (12UL) /*!< CTIMER STMINTEN: CAPTURED (Bit 12) */ +#define CTIMER_STMINTEN_CAPTURED_Msk (0x1000UL) /*!< CTIMER STMINTEN: CAPTURED (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_CAPTUREC_Pos (11UL) /*!< CTIMER STMINTEN: CAPTUREC (Bit 11) */ +#define CTIMER_STMINTEN_CAPTUREC_Msk (0x800UL) /*!< CTIMER STMINTEN: CAPTUREC (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_CAPTUREB_Pos (10UL) /*!< CTIMER STMINTEN: CAPTUREB (Bit 10) */ +#define CTIMER_STMINTEN_CAPTUREB_Msk (0x400UL) /*!< CTIMER STMINTEN: CAPTUREB (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_CAPTUREA_Pos (9UL) /*!< CTIMER STMINTEN: CAPTUREA (Bit 9) */ +#define CTIMER_STMINTEN_CAPTUREA_Msk (0x200UL) /*!< CTIMER STMINTEN: CAPTUREA (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_OVERFLOW_Pos (8UL) /*!< CTIMER STMINTEN: OVERFLOW (Bit 8) */ +#define CTIMER_STMINTEN_OVERFLOW_Msk (0x100UL) /*!< CTIMER STMINTEN: OVERFLOW (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_COMPAREH_Pos (7UL) /*!< CTIMER STMINTEN: COMPAREH (Bit 7) */ +#define CTIMER_STMINTEN_COMPAREH_Msk (0x80UL) /*!< CTIMER STMINTEN: COMPAREH (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_COMPAREG_Pos (6UL) /*!< CTIMER STMINTEN: COMPAREG (Bit 6) */ +#define CTIMER_STMINTEN_COMPAREG_Msk (0x40UL) /*!< CTIMER STMINTEN: COMPAREG (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_COMPAREF_Pos (5UL) /*!< CTIMER STMINTEN: COMPAREF (Bit 5) */ +#define CTIMER_STMINTEN_COMPAREF_Msk (0x20UL) /*!< CTIMER STMINTEN: COMPAREF (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_COMPAREE_Pos (4UL) /*!< CTIMER STMINTEN: COMPAREE (Bit 4) */ +#define CTIMER_STMINTEN_COMPAREE_Msk (0x10UL) /*!< CTIMER STMINTEN: COMPAREE (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_COMPARED_Pos (3UL) /*!< CTIMER STMINTEN: COMPARED (Bit 3) */ +#define CTIMER_STMINTEN_COMPARED_Msk (0x8UL) /*!< CTIMER STMINTEN: COMPARED (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_COMPAREC_Pos (2UL) /*!< CTIMER STMINTEN: COMPAREC (Bit 2) */ +#define CTIMER_STMINTEN_COMPAREC_Msk (0x4UL) /*!< CTIMER STMINTEN: COMPAREC (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_COMPAREB_Pos (1UL) /*!< CTIMER STMINTEN: COMPAREB (Bit 1) */ +#define CTIMER_STMINTEN_COMPAREB_Msk (0x2UL) /*!< CTIMER STMINTEN: COMPAREB (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTEN_COMPAREA_Pos (0UL) /*!< CTIMER STMINTEN: COMPAREA (Bit 0) */ +#define CTIMER_STMINTEN_COMPAREA_Msk (0x1UL) /*!< CTIMER STMINTEN: COMPAREA (Bitfield-Mask: 0x01) */ +/* ====================================================== STMINTSTAT ======================================================= */ +#define CTIMER_STMINTSTAT_CAPTURED_Pos (12UL) /*!< CTIMER STMINTSTAT: CAPTURED (Bit 12) */ +#define CTIMER_STMINTSTAT_CAPTURED_Msk (0x1000UL) /*!< CTIMER STMINTSTAT: CAPTURED (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_CAPTUREC_Pos (11UL) /*!< CTIMER STMINTSTAT: CAPTUREC (Bit 11) */ +#define CTIMER_STMINTSTAT_CAPTUREC_Msk (0x800UL) /*!< CTIMER STMINTSTAT: CAPTUREC (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_CAPTUREB_Pos (10UL) /*!< CTIMER STMINTSTAT: CAPTUREB (Bit 10) */ +#define CTIMER_STMINTSTAT_CAPTUREB_Msk (0x400UL) /*!< CTIMER STMINTSTAT: CAPTUREB (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_CAPTUREA_Pos (9UL) /*!< CTIMER STMINTSTAT: CAPTUREA (Bit 9) */ +#define CTIMER_STMINTSTAT_CAPTUREA_Msk (0x200UL) /*!< CTIMER STMINTSTAT: CAPTUREA (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_OVERFLOW_Pos (8UL) /*!< CTIMER STMINTSTAT: OVERFLOW (Bit 8) */ +#define CTIMER_STMINTSTAT_OVERFLOW_Msk (0x100UL) /*!< CTIMER STMINTSTAT: OVERFLOW (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_COMPAREH_Pos (7UL) /*!< CTIMER STMINTSTAT: COMPAREH (Bit 7) */ +#define CTIMER_STMINTSTAT_COMPAREH_Msk (0x80UL) /*!< CTIMER STMINTSTAT: COMPAREH (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_COMPAREG_Pos (6UL) /*!< CTIMER STMINTSTAT: COMPAREG (Bit 6) */ +#define CTIMER_STMINTSTAT_COMPAREG_Msk (0x40UL) /*!< CTIMER STMINTSTAT: COMPAREG (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_COMPAREF_Pos (5UL) /*!< CTIMER STMINTSTAT: COMPAREF (Bit 5) */ +#define CTIMER_STMINTSTAT_COMPAREF_Msk (0x20UL) /*!< CTIMER STMINTSTAT: COMPAREF (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_COMPAREE_Pos (4UL) /*!< CTIMER STMINTSTAT: COMPAREE (Bit 4) */ +#define CTIMER_STMINTSTAT_COMPAREE_Msk (0x10UL) /*!< CTIMER STMINTSTAT: COMPAREE (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_COMPARED_Pos (3UL) /*!< CTIMER STMINTSTAT: COMPARED (Bit 3) */ +#define CTIMER_STMINTSTAT_COMPARED_Msk (0x8UL) /*!< CTIMER STMINTSTAT: COMPARED (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_COMPAREC_Pos (2UL) /*!< CTIMER STMINTSTAT: COMPAREC (Bit 2) */ +#define CTIMER_STMINTSTAT_COMPAREC_Msk (0x4UL) /*!< CTIMER STMINTSTAT: COMPAREC (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_COMPAREB_Pos (1UL) /*!< CTIMER STMINTSTAT: COMPAREB (Bit 1) */ +#define CTIMER_STMINTSTAT_COMPAREB_Msk (0x2UL) /*!< CTIMER STMINTSTAT: COMPAREB (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSTAT_COMPAREA_Pos (0UL) /*!< CTIMER STMINTSTAT: COMPAREA (Bit 0) */ +#define CTIMER_STMINTSTAT_COMPAREA_Msk (0x1UL) /*!< CTIMER STMINTSTAT: COMPAREA (Bitfield-Mask: 0x01) */ +/* ======================================================= STMINTCLR ======================================================= */ +#define CTIMER_STMINTCLR_CAPTURED_Pos (12UL) /*!< CTIMER STMINTCLR: CAPTURED (Bit 12) */ +#define CTIMER_STMINTCLR_CAPTURED_Msk (0x1000UL) /*!< CTIMER STMINTCLR: CAPTURED (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_CAPTUREC_Pos (11UL) /*!< CTIMER STMINTCLR: CAPTUREC (Bit 11) */ +#define CTIMER_STMINTCLR_CAPTUREC_Msk (0x800UL) /*!< CTIMER STMINTCLR: CAPTUREC (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_CAPTUREB_Pos (10UL) /*!< CTIMER STMINTCLR: CAPTUREB (Bit 10) */ +#define CTIMER_STMINTCLR_CAPTUREB_Msk (0x400UL) /*!< CTIMER STMINTCLR: CAPTUREB (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_CAPTUREA_Pos (9UL) /*!< CTIMER STMINTCLR: CAPTUREA (Bit 9) */ +#define CTIMER_STMINTCLR_CAPTUREA_Msk (0x200UL) /*!< CTIMER STMINTCLR: CAPTUREA (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_OVERFLOW_Pos (8UL) /*!< CTIMER STMINTCLR: OVERFLOW (Bit 8) */ +#define CTIMER_STMINTCLR_OVERFLOW_Msk (0x100UL) /*!< CTIMER STMINTCLR: OVERFLOW (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_COMPAREH_Pos (7UL) /*!< CTIMER STMINTCLR: COMPAREH (Bit 7) */ +#define CTIMER_STMINTCLR_COMPAREH_Msk (0x80UL) /*!< CTIMER STMINTCLR: COMPAREH (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_COMPAREG_Pos (6UL) /*!< CTIMER STMINTCLR: COMPAREG (Bit 6) */ +#define CTIMER_STMINTCLR_COMPAREG_Msk (0x40UL) /*!< CTIMER STMINTCLR: COMPAREG (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_COMPAREF_Pos (5UL) /*!< CTIMER STMINTCLR: COMPAREF (Bit 5) */ +#define CTIMER_STMINTCLR_COMPAREF_Msk (0x20UL) /*!< CTIMER STMINTCLR: COMPAREF (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_COMPAREE_Pos (4UL) /*!< CTIMER STMINTCLR: COMPAREE (Bit 4) */ +#define CTIMER_STMINTCLR_COMPAREE_Msk (0x10UL) /*!< CTIMER STMINTCLR: COMPAREE (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_COMPARED_Pos (3UL) /*!< CTIMER STMINTCLR: COMPARED (Bit 3) */ +#define CTIMER_STMINTCLR_COMPARED_Msk (0x8UL) /*!< CTIMER STMINTCLR: COMPARED (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_COMPAREC_Pos (2UL) /*!< CTIMER STMINTCLR: COMPAREC (Bit 2) */ +#define CTIMER_STMINTCLR_COMPAREC_Msk (0x4UL) /*!< CTIMER STMINTCLR: COMPAREC (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_COMPAREB_Pos (1UL) /*!< CTIMER STMINTCLR: COMPAREB (Bit 1) */ +#define CTIMER_STMINTCLR_COMPAREB_Msk (0x2UL) /*!< CTIMER STMINTCLR: COMPAREB (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTCLR_COMPAREA_Pos (0UL) /*!< CTIMER STMINTCLR: COMPAREA (Bit 0) */ +#define CTIMER_STMINTCLR_COMPAREA_Msk (0x1UL) /*!< CTIMER STMINTCLR: COMPAREA (Bitfield-Mask: 0x01) */ +/* ======================================================= STMINTSET ======================================================= */ +#define CTIMER_STMINTSET_CAPTURED_Pos (12UL) /*!< CTIMER STMINTSET: CAPTURED (Bit 12) */ +#define CTIMER_STMINTSET_CAPTURED_Msk (0x1000UL) /*!< CTIMER STMINTSET: CAPTURED (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_CAPTUREC_Pos (11UL) /*!< CTIMER STMINTSET: CAPTUREC (Bit 11) */ +#define CTIMER_STMINTSET_CAPTUREC_Msk (0x800UL) /*!< CTIMER STMINTSET: CAPTUREC (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_CAPTUREB_Pos (10UL) /*!< CTIMER STMINTSET: CAPTUREB (Bit 10) */ +#define CTIMER_STMINTSET_CAPTUREB_Msk (0x400UL) /*!< CTIMER STMINTSET: CAPTUREB (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_CAPTUREA_Pos (9UL) /*!< CTIMER STMINTSET: CAPTUREA (Bit 9) */ +#define CTIMER_STMINTSET_CAPTUREA_Msk (0x200UL) /*!< CTIMER STMINTSET: CAPTUREA (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_OVERFLOW_Pos (8UL) /*!< CTIMER STMINTSET: OVERFLOW (Bit 8) */ +#define CTIMER_STMINTSET_OVERFLOW_Msk (0x100UL) /*!< CTIMER STMINTSET: OVERFLOW (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_COMPAREH_Pos (7UL) /*!< CTIMER STMINTSET: COMPAREH (Bit 7) */ +#define CTIMER_STMINTSET_COMPAREH_Msk (0x80UL) /*!< CTIMER STMINTSET: COMPAREH (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_COMPAREG_Pos (6UL) /*!< CTIMER STMINTSET: COMPAREG (Bit 6) */ +#define CTIMER_STMINTSET_COMPAREG_Msk (0x40UL) /*!< CTIMER STMINTSET: COMPAREG (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_COMPAREF_Pos (5UL) /*!< CTIMER STMINTSET: COMPAREF (Bit 5) */ +#define CTIMER_STMINTSET_COMPAREF_Msk (0x20UL) /*!< CTIMER STMINTSET: COMPAREF (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_COMPAREE_Pos (4UL) /*!< CTIMER STMINTSET: COMPAREE (Bit 4) */ +#define CTIMER_STMINTSET_COMPAREE_Msk (0x10UL) /*!< CTIMER STMINTSET: COMPAREE (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_COMPARED_Pos (3UL) /*!< CTIMER STMINTSET: COMPARED (Bit 3) */ +#define CTIMER_STMINTSET_COMPARED_Msk (0x8UL) /*!< CTIMER STMINTSET: COMPARED (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_COMPAREC_Pos (2UL) /*!< CTIMER STMINTSET: COMPAREC (Bit 2) */ +#define CTIMER_STMINTSET_COMPAREC_Msk (0x4UL) /*!< CTIMER STMINTSET: COMPAREC (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_COMPAREB_Pos (1UL) /*!< CTIMER STMINTSET: COMPAREB (Bit 1) */ +#define CTIMER_STMINTSET_COMPAREB_Msk (0x2UL) /*!< CTIMER STMINTSET: COMPAREB (Bitfield-Mask: 0x01) */ +#define CTIMER_STMINTSET_COMPAREA_Pos (0UL) /*!< CTIMER STMINTSET: COMPAREA (Bit 0) */ +#define CTIMER_STMINTSET_COMPAREA_Msk (0x1UL) /*!< CTIMER STMINTSET: COMPAREA (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ GPIO ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== PADREGA ======================================================== */ +#define GPIO_PADREGA_PAD3PWRUP_Pos (30UL) /*!< GPIO PADREGA: PAD3PWRUP (Bit 30) */ +#define GPIO_PADREGA_PAD3PWRUP_Msk (0x40000000UL) /*!< GPIO PADREGA: PAD3PWRUP (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD3FNCSEL_Pos (27UL) /*!< GPIO PADREGA: PAD3FNCSEL (Bit 27) */ +#define GPIO_PADREGA_PAD3FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGA: PAD3FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGA_PAD3STRNG_Pos (26UL) /*!< GPIO PADREGA: PAD3STRNG (Bit 26) */ +#define GPIO_PADREGA_PAD3STRNG_Msk (0x4000000UL) /*!< GPIO PADREGA: PAD3STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD3INPEN_Pos (25UL) /*!< GPIO PADREGA: PAD3INPEN (Bit 25) */ +#define GPIO_PADREGA_PAD3INPEN_Msk (0x2000000UL) /*!< GPIO PADREGA: PAD3INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD3PULL_Pos (24UL) /*!< GPIO PADREGA: PAD3PULL (Bit 24) */ +#define GPIO_PADREGA_PAD3PULL_Msk (0x1000000UL) /*!< GPIO PADREGA: PAD3PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD2FNCSEL_Pos (19UL) /*!< GPIO PADREGA: PAD2FNCSEL (Bit 19) */ +#define GPIO_PADREGA_PAD2FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGA: PAD2FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGA_PAD2STRNG_Pos (18UL) /*!< GPIO PADREGA: PAD2STRNG (Bit 18) */ +#define GPIO_PADREGA_PAD2STRNG_Msk (0x40000UL) /*!< GPIO PADREGA: PAD2STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD2INPEN_Pos (17UL) /*!< GPIO PADREGA: PAD2INPEN (Bit 17) */ +#define GPIO_PADREGA_PAD2INPEN_Msk (0x20000UL) /*!< GPIO PADREGA: PAD2INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD2PULL_Pos (16UL) /*!< GPIO PADREGA: PAD2PULL (Bit 16) */ +#define GPIO_PADREGA_PAD2PULL_Msk (0x10000UL) /*!< GPIO PADREGA: PAD2PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD1RSEL_Pos (14UL) /*!< GPIO PADREGA: PAD1RSEL (Bit 14) */ +#define GPIO_PADREGA_PAD1RSEL_Msk (0xc000UL) /*!< GPIO PADREGA: PAD1RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGA_PAD1FNCSEL_Pos (11UL) /*!< GPIO PADREGA: PAD1FNCSEL (Bit 11) */ +#define GPIO_PADREGA_PAD1FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGA: PAD1FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGA_PAD1STRNG_Pos (10UL) /*!< GPIO PADREGA: PAD1STRNG (Bit 10) */ +#define GPIO_PADREGA_PAD1STRNG_Msk (0x400UL) /*!< GPIO PADREGA: PAD1STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD1INPEN_Pos (9UL) /*!< GPIO PADREGA: PAD1INPEN (Bit 9) */ +#define GPIO_PADREGA_PAD1INPEN_Msk (0x200UL) /*!< GPIO PADREGA: PAD1INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD1PULL_Pos (8UL) /*!< GPIO PADREGA: PAD1PULL (Bit 8) */ +#define GPIO_PADREGA_PAD1PULL_Msk (0x100UL) /*!< GPIO PADREGA: PAD1PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD0RSEL_Pos (6UL) /*!< GPIO PADREGA: PAD0RSEL (Bit 6) */ +#define GPIO_PADREGA_PAD0RSEL_Msk (0xc0UL) /*!< GPIO PADREGA: PAD0RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGA_PAD0FNCSEL_Pos (3UL) /*!< GPIO PADREGA: PAD0FNCSEL (Bit 3) */ +#define GPIO_PADREGA_PAD0FNCSEL_Msk (0x38UL) /*!< GPIO PADREGA: PAD0FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGA_PAD0STRNG_Pos (2UL) /*!< GPIO PADREGA: PAD0STRNG (Bit 2) */ +#define GPIO_PADREGA_PAD0STRNG_Msk (0x4UL) /*!< GPIO PADREGA: PAD0STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD0INPEN_Pos (1UL) /*!< GPIO PADREGA: PAD0INPEN (Bit 1) */ +#define GPIO_PADREGA_PAD0INPEN_Msk (0x2UL) /*!< GPIO PADREGA: PAD0INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGA_PAD0PULL_Pos (0UL) /*!< GPIO PADREGA: PAD0PULL (Bit 0) */ +#define GPIO_PADREGA_PAD0PULL_Msk (0x1UL) /*!< GPIO PADREGA: PAD0PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGB ======================================================== */ +#define GPIO_PADREGB_PAD7FNCSEL_Pos (27UL) /*!< GPIO PADREGB: PAD7FNCSEL (Bit 27) */ +#define GPIO_PADREGB_PAD7FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGB: PAD7FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGB_PAD7STRNG_Pos (26UL) /*!< GPIO PADREGB: PAD7STRNG (Bit 26) */ +#define GPIO_PADREGB_PAD7STRNG_Msk (0x4000000UL) /*!< GPIO PADREGB: PAD7STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD7INPEN_Pos (25UL) /*!< GPIO PADREGB: PAD7INPEN (Bit 25) */ +#define GPIO_PADREGB_PAD7INPEN_Msk (0x2000000UL) /*!< GPIO PADREGB: PAD7INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD7PULL_Pos (24UL) /*!< GPIO PADREGB: PAD7PULL (Bit 24) */ +#define GPIO_PADREGB_PAD7PULL_Msk (0x1000000UL) /*!< GPIO PADREGB: PAD7PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD6RSEL_Pos (22UL) /*!< GPIO PADREGB: PAD6RSEL (Bit 22) */ +#define GPIO_PADREGB_PAD6RSEL_Msk (0xc00000UL) /*!< GPIO PADREGB: PAD6RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGB_PAD6FNCSEL_Pos (19UL) /*!< GPIO PADREGB: PAD6FNCSEL (Bit 19) */ +#define GPIO_PADREGB_PAD6FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGB: PAD6FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGB_PAD6STRNG_Pos (18UL) /*!< GPIO PADREGB: PAD6STRNG (Bit 18) */ +#define GPIO_PADREGB_PAD6STRNG_Msk (0x40000UL) /*!< GPIO PADREGB: PAD6STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD6INPEN_Pos (17UL) /*!< GPIO PADREGB: PAD6INPEN (Bit 17) */ +#define GPIO_PADREGB_PAD6INPEN_Msk (0x20000UL) /*!< GPIO PADREGB: PAD6INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD6PULL_Pos (16UL) /*!< GPIO PADREGB: PAD6PULL (Bit 16) */ +#define GPIO_PADREGB_PAD6PULL_Msk (0x10000UL) /*!< GPIO PADREGB: PAD6PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD5RSEL_Pos (14UL) /*!< GPIO PADREGB: PAD5RSEL (Bit 14) */ +#define GPIO_PADREGB_PAD5RSEL_Msk (0xc000UL) /*!< GPIO PADREGB: PAD5RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGB_PAD5FNCSEL_Pos (11UL) /*!< GPIO PADREGB: PAD5FNCSEL (Bit 11) */ +#define GPIO_PADREGB_PAD5FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGB: PAD5FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGB_PAD5STRNG_Pos (10UL) /*!< GPIO PADREGB: PAD5STRNG (Bit 10) */ +#define GPIO_PADREGB_PAD5STRNG_Msk (0x400UL) /*!< GPIO PADREGB: PAD5STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD5INPEN_Pos (9UL) /*!< GPIO PADREGB: PAD5INPEN (Bit 9) */ +#define GPIO_PADREGB_PAD5INPEN_Msk (0x200UL) /*!< GPIO PADREGB: PAD5INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD5PULL_Pos (8UL) /*!< GPIO PADREGB: PAD5PULL (Bit 8) */ +#define GPIO_PADREGB_PAD5PULL_Msk (0x100UL) /*!< GPIO PADREGB: PAD5PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD4FNCSEL_Pos (3UL) /*!< GPIO PADREGB: PAD4FNCSEL (Bit 3) */ +#define GPIO_PADREGB_PAD4FNCSEL_Msk (0x38UL) /*!< GPIO PADREGB: PAD4FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGB_PAD4STRNG_Pos (2UL) /*!< GPIO PADREGB: PAD4STRNG (Bit 2) */ +#define GPIO_PADREGB_PAD4STRNG_Msk (0x4UL) /*!< GPIO PADREGB: PAD4STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD4INPEN_Pos (1UL) /*!< GPIO PADREGB: PAD4INPEN (Bit 1) */ +#define GPIO_PADREGB_PAD4INPEN_Msk (0x2UL) /*!< GPIO PADREGB: PAD4INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGB_PAD4PULL_Pos (0UL) /*!< GPIO PADREGB: PAD4PULL (Bit 0) */ +#define GPIO_PADREGB_PAD4PULL_Msk (0x1UL) /*!< GPIO PADREGB: PAD4PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGC ======================================================== */ +#define GPIO_PADREGC_PAD11FNCSEL_Pos (27UL) /*!< GPIO PADREGC: PAD11FNCSEL (Bit 27) */ +#define GPIO_PADREGC_PAD11FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGC: PAD11FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGC_PAD11STRNG_Pos (26UL) /*!< GPIO PADREGC: PAD11STRNG (Bit 26) */ +#define GPIO_PADREGC_PAD11STRNG_Msk (0x4000000UL) /*!< GPIO PADREGC: PAD11STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD11INPEN_Pos (25UL) /*!< GPIO PADREGC: PAD11INPEN (Bit 25) */ +#define GPIO_PADREGC_PAD11INPEN_Msk (0x2000000UL) /*!< GPIO PADREGC: PAD11INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD11PULL_Pos (24UL) /*!< GPIO PADREGC: PAD11PULL (Bit 24) */ +#define GPIO_PADREGC_PAD11PULL_Msk (0x1000000UL) /*!< GPIO PADREGC: PAD11PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD10FNCSEL_Pos (19UL) /*!< GPIO PADREGC: PAD10FNCSEL (Bit 19) */ +#define GPIO_PADREGC_PAD10FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGC: PAD10FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGC_PAD10STRNG_Pos (18UL) /*!< GPIO PADREGC: PAD10STRNG (Bit 18) */ +#define GPIO_PADREGC_PAD10STRNG_Msk (0x40000UL) /*!< GPIO PADREGC: PAD10STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD10INPEN_Pos (17UL) /*!< GPIO PADREGC: PAD10INPEN (Bit 17) */ +#define GPIO_PADREGC_PAD10INPEN_Msk (0x20000UL) /*!< GPIO PADREGC: PAD10INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD10PULL_Pos (16UL) /*!< GPIO PADREGC: PAD10PULL (Bit 16) */ +#define GPIO_PADREGC_PAD10PULL_Msk (0x10000UL) /*!< GPIO PADREGC: PAD10PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD9RSEL_Pos (14UL) /*!< GPIO PADREGC: PAD9RSEL (Bit 14) */ +#define GPIO_PADREGC_PAD9RSEL_Msk (0xc000UL) /*!< GPIO PADREGC: PAD9RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGC_PAD9FNCSEL_Pos (11UL) /*!< GPIO PADREGC: PAD9FNCSEL (Bit 11) */ +#define GPIO_PADREGC_PAD9FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGC: PAD9FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGC_PAD9STRNG_Pos (10UL) /*!< GPIO PADREGC: PAD9STRNG (Bit 10) */ +#define GPIO_PADREGC_PAD9STRNG_Msk (0x400UL) /*!< GPIO PADREGC: PAD9STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD9INPEN_Pos (9UL) /*!< GPIO PADREGC: PAD9INPEN (Bit 9) */ +#define GPIO_PADREGC_PAD9INPEN_Msk (0x200UL) /*!< GPIO PADREGC: PAD9INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD9PULL_Pos (8UL) /*!< GPIO PADREGC: PAD9PULL (Bit 8) */ +#define GPIO_PADREGC_PAD9PULL_Msk (0x100UL) /*!< GPIO PADREGC: PAD9PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD8RSEL_Pos (6UL) /*!< GPIO PADREGC: PAD8RSEL (Bit 6) */ +#define GPIO_PADREGC_PAD8RSEL_Msk (0xc0UL) /*!< GPIO PADREGC: PAD8RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGC_PAD8FNCSEL_Pos (3UL) /*!< GPIO PADREGC: PAD8FNCSEL (Bit 3) */ +#define GPIO_PADREGC_PAD8FNCSEL_Msk (0x38UL) /*!< GPIO PADREGC: PAD8FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGC_PAD8STRNG_Pos (2UL) /*!< GPIO PADREGC: PAD8STRNG (Bit 2) */ +#define GPIO_PADREGC_PAD8STRNG_Msk (0x4UL) /*!< GPIO PADREGC: PAD8STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD8INPEN_Pos (1UL) /*!< GPIO PADREGC: PAD8INPEN (Bit 1) */ +#define GPIO_PADREGC_PAD8INPEN_Msk (0x2UL) /*!< GPIO PADREGC: PAD8INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGC_PAD8PULL_Pos (0UL) /*!< GPIO PADREGC: PAD8PULL (Bit 0) */ +#define GPIO_PADREGC_PAD8PULL_Msk (0x1UL) /*!< GPIO PADREGC: PAD8PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGD ======================================================== */ +#define GPIO_PADREGD_PAD15FNCSEL_Pos (27UL) /*!< GPIO PADREGD: PAD15FNCSEL (Bit 27) */ +#define GPIO_PADREGD_PAD15FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGD: PAD15FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGD_PAD15STRNG_Pos (26UL) /*!< GPIO PADREGD: PAD15STRNG (Bit 26) */ +#define GPIO_PADREGD_PAD15STRNG_Msk (0x4000000UL) /*!< GPIO PADREGD: PAD15STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD15INPEN_Pos (25UL) /*!< GPIO PADREGD: PAD15INPEN (Bit 25) */ +#define GPIO_PADREGD_PAD15INPEN_Msk (0x2000000UL) /*!< GPIO PADREGD: PAD15INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD15PULL_Pos (24UL) /*!< GPIO PADREGD: PAD15PULL (Bit 24) */ +#define GPIO_PADREGD_PAD15PULL_Msk (0x1000000UL) /*!< GPIO PADREGD: PAD15PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD14FNCSEL_Pos (19UL) /*!< GPIO PADREGD: PAD14FNCSEL (Bit 19) */ +#define GPIO_PADREGD_PAD14FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGD: PAD14FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGD_PAD14STRNG_Pos (18UL) /*!< GPIO PADREGD: PAD14STRNG (Bit 18) */ +#define GPIO_PADREGD_PAD14STRNG_Msk (0x40000UL) /*!< GPIO PADREGD: PAD14STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD14INPEN_Pos (17UL) /*!< GPIO PADREGD: PAD14INPEN (Bit 17) */ +#define GPIO_PADREGD_PAD14INPEN_Msk (0x20000UL) /*!< GPIO PADREGD: PAD14INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD14PULL_Pos (16UL) /*!< GPIO PADREGD: PAD14PULL (Bit 16) */ +#define GPIO_PADREGD_PAD14PULL_Msk (0x10000UL) /*!< GPIO PADREGD: PAD14PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD13FNCSEL_Pos (11UL) /*!< GPIO PADREGD: PAD13FNCSEL (Bit 11) */ +#define GPIO_PADREGD_PAD13FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGD: PAD13FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGD_PAD13STRNG_Pos (10UL) /*!< GPIO PADREGD: PAD13STRNG (Bit 10) */ +#define GPIO_PADREGD_PAD13STRNG_Msk (0x400UL) /*!< GPIO PADREGD: PAD13STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD13INPEN_Pos (9UL) /*!< GPIO PADREGD: PAD13INPEN (Bit 9) */ +#define GPIO_PADREGD_PAD13INPEN_Msk (0x200UL) /*!< GPIO PADREGD: PAD13INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD13PULL_Pos (8UL) /*!< GPIO PADREGD: PAD13PULL (Bit 8) */ +#define GPIO_PADREGD_PAD13PULL_Msk (0x100UL) /*!< GPIO PADREGD: PAD13PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD12FNCSEL_Pos (3UL) /*!< GPIO PADREGD: PAD12FNCSEL (Bit 3) */ +#define GPIO_PADREGD_PAD12FNCSEL_Msk (0x38UL) /*!< GPIO PADREGD: PAD12FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGD_PAD12STRNG_Pos (2UL) /*!< GPIO PADREGD: PAD12STRNG (Bit 2) */ +#define GPIO_PADREGD_PAD12STRNG_Msk (0x4UL) /*!< GPIO PADREGD: PAD12STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD12INPEN_Pos (1UL) /*!< GPIO PADREGD: PAD12INPEN (Bit 1) */ +#define GPIO_PADREGD_PAD12INPEN_Msk (0x2UL) /*!< GPIO PADREGD: PAD12INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGD_PAD12PULL_Pos (0UL) /*!< GPIO PADREGD: PAD12PULL (Bit 0) */ +#define GPIO_PADREGD_PAD12PULL_Msk (0x1UL) /*!< GPIO PADREGD: PAD12PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGE ======================================================== */ +#define GPIO_PADREGE_PAD19FNCSEL_Pos (27UL) /*!< GPIO PADREGE: PAD19FNCSEL (Bit 27) */ +#define GPIO_PADREGE_PAD19FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGE: PAD19FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGE_PAD19STRNG_Pos (26UL) /*!< GPIO PADREGE: PAD19STRNG (Bit 26) */ +#define GPIO_PADREGE_PAD19STRNG_Msk (0x4000000UL) /*!< GPIO PADREGE: PAD19STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD19INPEN_Pos (25UL) /*!< GPIO PADREGE: PAD19INPEN (Bit 25) */ +#define GPIO_PADREGE_PAD19INPEN_Msk (0x2000000UL) /*!< GPIO PADREGE: PAD19INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD19PULL_Pos (24UL) /*!< GPIO PADREGE: PAD19PULL (Bit 24) */ +#define GPIO_PADREGE_PAD19PULL_Msk (0x1000000UL) /*!< GPIO PADREGE: PAD19PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD18FNCSEL_Pos (19UL) /*!< GPIO PADREGE: PAD18FNCSEL (Bit 19) */ +#define GPIO_PADREGE_PAD18FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGE: PAD18FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGE_PAD18STRNG_Pos (18UL) /*!< GPIO PADREGE: PAD18STRNG (Bit 18) */ +#define GPIO_PADREGE_PAD18STRNG_Msk (0x40000UL) /*!< GPIO PADREGE: PAD18STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD18INPEN_Pos (17UL) /*!< GPIO PADREGE: PAD18INPEN (Bit 17) */ +#define GPIO_PADREGE_PAD18INPEN_Msk (0x20000UL) /*!< GPIO PADREGE: PAD18INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD18PULL_Pos (16UL) /*!< GPIO PADREGE: PAD18PULL (Bit 16) */ +#define GPIO_PADREGE_PAD18PULL_Msk (0x10000UL) /*!< GPIO PADREGE: PAD18PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD17FNCSEL_Pos (11UL) /*!< GPIO PADREGE: PAD17FNCSEL (Bit 11) */ +#define GPIO_PADREGE_PAD17FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGE: PAD17FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGE_PAD17STRNG_Pos (10UL) /*!< GPIO PADREGE: PAD17STRNG (Bit 10) */ +#define GPIO_PADREGE_PAD17STRNG_Msk (0x400UL) /*!< GPIO PADREGE: PAD17STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD17INPEN_Pos (9UL) /*!< GPIO PADREGE: PAD17INPEN (Bit 9) */ +#define GPIO_PADREGE_PAD17INPEN_Msk (0x200UL) /*!< GPIO PADREGE: PAD17INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD17PULL_Pos (8UL) /*!< GPIO PADREGE: PAD17PULL (Bit 8) */ +#define GPIO_PADREGE_PAD17PULL_Msk (0x100UL) /*!< GPIO PADREGE: PAD17PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD16FNCSEL_Pos (3UL) /*!< GPIO PADREGE: PAD16FNCSEL (Bit 3) */ +#define GPIO_PADREGE_PAD16FNCSEL_Msk (0x38UL) /*!< GPIO PADREGE: PAD16FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGE_PAD16STRNG_Pos (2UL) /*!< GPIO PADREGE: PAD16STRNG (Bit 2) */ +#define GPIO_PADREGE_PAD16STRNG_Msk (0x4UL) /*!< GPIO PADREGE: PAD16STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD16INPEN_Pos (1UL) /*!< GPIO PADREGE: PAD16INPEN (Bit 1) */ +#define GPIO_PADREGE_PAD16INPEN_Msk (0x2UL) /*!< GPIO PADREGE: PAD16INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGE_PAD16PULL_Pos (0UL) /*!< GPIO PADREGE: PAD16PULL (Bit 0) */ +#define GPIO_PADREGE_PAD16PULL_Msk (0x1UL) /*!< GPIO PADREGE: PAD16PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGF ======================================================== */ +#define GPIO_PADREGF_PAD23FNCSEL_Pos (27UL) /*!< GPIO PADREGF: PAD23FNCSEL (Bit 27) */ +#define GPIO_PADREGF_PAD23FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGF: PAD23FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGF_PAD23STRNG_Pos (26UL) /*!< GPIO PADREGF: PAD23STRNG (Bit 26) */ +#define GPIO_PADREGF_PAD23STRNG_Msk (0x4000000UL) /*!< GPIO PADREGF: PAD23STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD23INPEN_Pos (25UL) /*!< GPIO PADREGF: PAD23INPEN (Bit 25) */ +#define GPIO_PADREGF_PAD23INPEN_Msk (0x2000000UL) /*!< GPIO PADREGF: PAD23INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD23PULL_Pos (24UL) /*!< GPIO PADREGF: PAD23PULL (Bit 24) */ +#define GPIO_PADREGF_PAD23PULL_Msk (0x1000000UL) /*!< GPIO PADREGF: PAD23PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD22FNCSEL_Pos (19UL) /*!< GPIO PADREGF: PAD22FNCSEL (Bit 19) */ +#define GPIO_PADREGF_PAD22FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGF: PAD22FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGF_PAD22STRNG_Pos (18UL) /*!< GPIO PADREGF: PAD22STRNG (Bit 18) */ +#define GPIO_PADREGF_PAD22STRNG_Msk (0x40000UL) /*!< GPIO PADREGF: PAD22STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD22INPEN_Pos (17UL) /*!< GPIO PADREGF: PAD22INPEN (Bit 17) */ +#define GPIO_PADREGF_PAD22INPEN_Msk (0x20000UL) /*!< GPIO PADREGF: PAD22INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD22PULL_Pos (16UL) /*!< GPIO PADREGF: PAD22PULL (Bit 16) */ +#define GPIO_PADREGF_PAD22PULL_Msk (0x10000UL) /*!< GPIO PADREGF: PAD22PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD21FNCSEL_Pos (11UL) /*!< GPIO PADREGF: PAD21FNCSEL (Bit 11) */ +#define GPIO_PADREGF_PAD21FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGF: PAD21FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGF_PAD21STRNG_Pos (10UL) /*!< GPIO PADREGF: PAD21STRNG (Bit 10) */ +#define GPIO_PADREGF_PAD21STRNG_Msk (0x400UL) /*!< GPIO PADREGF: PAD21STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD21INPEN_Pos (9UL) /*!< GPIO PADREGF: PAD21INPEN (Bit 9) */ +#define GPIO_PADREGF_PAD21INPEN_Msk (0x200UL) /*!< GPIO PADREGF: PAD21INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD21PULL_Pos (8UL) /*!< GPIO PADREGF: PAD21PULL (Bit 8) */ +#define GPIO_PADREGF_PAD21PULL_Msk (0x100UL) /*!< GPIO PADREGF: PAD21PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD20FNCSEL_Pos (3UL) /*!< GPIO PADREGF: PAD20FNCSEL (Bit 3) */ +#define GPIO_PADREGF_PAD20FNCSEL_Msk (0x38UL) /*!< GPIO PADREGF: PAD20FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGF_PAD20STRNG_Pos (2UL) /*!< GPIO PADREGF: PAD20STRNG (Bit 2) */ +#define GPIO_PADREGF_PAD20STRNG_Msk (0x4UL) /*!< GPIO PADREGF: PAD20STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD20INPEN_Pos (1UL) /*!< GPIO PADREGF: PAD20INPEN (Bit 1) */ +#define GPIO_PADREGF_PAD20INPEN_Msk (0x2UL) /*!< GPIO PADREGF: PAD20INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGF_PAD20PULL_Pos (0UL) /*!< GPIO PADREGF: PAD20PULL (Bit 0) */ +#define GPIO_PADREGF_PAD20PULL_Msk (0x1UL) /*!< GPIO PADREGF: PAD20PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGG ======================================================== */ +#define GPIO_PADREGG_PAD27RSEL_Pos (30UL) /*!< GPIO PADREGG: PAD27RSEL (Bit 30) */ +#define GPIO_PADREGG_PAD27RSEL_Msk (0xc0000000UL) /*!< GPIO PADREGG: PAD27RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGG_PAD27FNCSEL_Pos (27UL) /*!< GPIO PADREGG: PAD27FNCSEL (Bit 27) */ +#define GPIO_PADREGG_PAD27FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGG: PAD27FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGG_PAD27STRNG_Pos (26UL) /*!< GPIO PADREGG: PAD27STRNG (Bit 26) */ +#define GPIO_PADREGG_PAD27STRNG_Msk (0x4000000UL) /*!< GPIO PADREGG: PAD27STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD27INPEN_Pos (25UL) /*!< GPIO PADREGG: PAD27INPEN (Bit 25) */ +#define GPIO_PADREGG_PAD27INPEN_Msk (0x2000000UL) /*!< GPIO PADREGG: PAD27INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD27PULL_Pos (24UL) /*!< GPIO PADREGG: PAD27PULL (Bit 24) */ +#define GPIO_PADREGG_PAD27PULL_Msk (0x1000000UL) /*!< GPIO PADREGG: PAD27PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD26FNCSEL_Pos (19UL) /*!< GPIO PADREGG: PAD26FNCSEL (Bit 19) */ +#define GPIO_PADREGG_PAD26FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGG: PAD26FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGG_PAD26STRNG_Pos (18UL) /*!< GPIO PADREGG: PAD26STRNG (Bit 18) */ +#define GPIO_PADREGG_PAD26STRNG_Msk (0x40000UL) /*!< GPIO PADREGG: PAD26STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD26INPEN_Pos (17UL) /*!< GPIO PADREGG: PAD26INPEN (Bit 17) */ +#define GPIO_PADREGG_PAD26INPEN_Msk (0x20000UL) /*!< GPIO PADREGG: PAD26INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD26PULL_Pos (16UL) /*!< GPIO PADREGG: PAD26PULL (Bit 16) */ +#define GPIO_PADREGG_PAD26PULL_Msk (0x10000UL) /*!< GPIO PADREGG: PAD26PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD25RSEL_Pos (14UL) /*!< GPIO PADREGG: PAD25RSEL (Bit 14) */ +#define GPIO_PADREGG_PAD25RSEL_Msk (0xc000UL) /*!< GPIO PADREGG: PAD25RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGG_PAD25FNCSEL_Pos (11UL) /*!< GPIO PADREGG: PAD25FNCSEL (Bit 11) */ +#define GPIO_PADREGG_PAD25FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGG: PAD25FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGG_PAD25STRNG_Pos (10UL) /*!< GPIO PADREGG: PAD25STRNG (Bit 10) */ +#define GPIO_PADREGG_PAD25STRNG_Msk (0x400UL) /*!< GPIO PADREGG: PAD25STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD25INPEN_Pos (9UL) /*!< GPIO PADREGG: PAD25INPEN (Bit 9) */ +#define GPIO_PADREGG_PAD25INPEN_Msk (0x200UL) /*!< GPIO PADREGG: PAD25INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD25PULL_Pos (8UL) /*!< GPIO PADREGG: PAD25PULL (Bit 8) */ +#define GPIO_PADREGG_PAD25PULL_Msk (0x100UL) /*!< GPIO PADREGG: PAD25PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD24FNCSEL_Pos (3UL) /*!< GPIO PADREGG: PAD24FNCSEL (Bit 3) */ +#define GPIO_PADREGG_PAD24FNCSEL_Msk (0x38UL) /*!< GPIO PADREGG: PAD24FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGG_PAD24STRNG_Pos (2UL) /*!< GPIO PADREGG: PAD24STRNG (Bit 2) */ +#define GPIO_PADREGG_PAD24STRNG_Msk (0x4UL) /*!< GPIO PADREGG: PAD24STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD24INPEN_Pos (1UL) /*!< GPIO PADREGG: PAD24INPEN (Bit 1) */ +#define GPIO_PADREGG_PAD24INPEN_Msk (0x2UL) /*!< GPIO PADREGG: PAD24INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGG_PAD24PULL_Pos (0UL) /*!< GPIO PADREGG: PAD24PULL (Bit 0) */ +#define GPIO_PADREGG_PAD24PULL_Msk (0x1UL) /*!< GPIO PADREGG: PAD24PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGH ======================================================== */ +#define GPIO_PADREGH_PAD31FNCSEL_Pos (27UL) /*!< GPIO PADREGH: PAD31FNCSEL (Bit 27) */ +#define GPIO_PADREGH_PAD31FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGH: PAD31FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGH_PAD31STRNG_Pos (26UL) /*!< GPIO PADREGH: PAD31STRNG (Bit 26) */ +#define GPIO_PADREGH_PAD31STRNG_Msk (0x4000000UL) /*!< GPIO PADREGH: PAD31STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD31INPEN_Pos (25UL) /*!< GPIO PADREGH: PAD31INPEN (Bit 25) */ +#define GPIO_PADREGH_PAD31INPEN_Msk (0x2000000UL) /*!< GPIO PADREGH: PAD31INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD31PULL_Pos (24UL) /*!< GPIO PADREGH: PAD31PULL (Bit 24) */ +#define GPIO_PADREGH_PAD31PULL_Msk (0x1000000UL) /*!< GPIO PADREGH: PAD31PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD30FNCSEL_Pos (19UL) /*!< GPIO PADREGH: PAD30FNCSEL (Bit 19) */ +#define GPIO_PADREGH_PAD30FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGH: PAD30FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGH_PAD30STRNG_Pos (18UL) /*!< GPIO PADREGH: PAD30STRNG (Bit 18) */ +#define GPIO_PADREGH_PAD30STRNG_Msk (0x40000UL) /*!< GPIO PADREGH: PAD30STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD30INPEN_Pos (17UL) /*!< GPIO PADREGH: PAD30INPEN (Bit 17) */ +#define GPIO_PADREGH_PAD30INPEN_Msk (0x20000UL) /*!< GPIO PADREGH: PAD30INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD30PULL_Pos (16UL) /*!< GPIO PADREGH: PAD30PULL (Bit 16) */ +#define GPIO_PADREGH_PAD30PULL_Msk (0x10000UL) /*!< GPIO PADREGH: PAD30PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD29FNCSEL_Pos (11UL) /*!< GPIO PADREGH: PAD29FNCSEL (Bit 11) */ +#define GPIO_PADREGH_PAD29FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGH: PAD29FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGH_PAD29STRNG_Pos (10UL) /*!< GPIO PADREGH: PAD29STRNG (Bit 10) */ +#define GPIO_PADREGH_PAD29STRNG_Msk (0x400UL) /*!< GPIO PADREGH: PAD29STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD29INPEN_Pos (9UL) /*!< GPIO PADREGH: PAD29INPEN (Bit 9) */ +#define GPIO_PADREGH_PAD29INPEN_Msk (0x200UL) /*!< GPIO PADREGH: PAD29INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD29PULL_Pos (8UL) /*!< GPIO PADREGH: PAD29PULL (Bit 8) */ +#define GPIO_PADREGH_PAD29PULL_Msk (0x100UL) /*!< GPIO PADREGH: PAD29PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD28FNCSEL_Pos (3UL) /*!< GPIO PADREGH: PAD28FNCSEL (Bit 3) */ +#define GPIO_PADREGH_PAD28FNCSEL_Msk (0x38UL) /*!< GPIO PADREGH: PAD28FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGH_PAD28STRNG_Pos (2UL) /*!< GPIO PADREGH: PAD28STRNG (Bit 2) */ +#define GPIO_PADREGH_PAD28STRNG_Msk (0x4UL) /*!< GPIO PADREGH: PAD28STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD28INPEN_Pos (1UL) /*!< GPIO PADREGH: PAD28INPEN (Bit 1) */ +#define GPIO_PADREGH_PAD28INPEN_Msk (0x2UL) /*!< GPIO PADREGH: PAD28INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGH_PAD28PULL_Pos (0UL) /*!< GPIO PADREGH: PAD28PULL (Bit 0) */ +#define GPIO_PADREGH_PAD28PULL_Msk (0x1UL) /*!< GPIO PADREGH: PAD28PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGI ======================================================== */ +#define GPIO_PADREGI_PAD35FNCSEL_Pos (27UL) /*!< GPIO PADREGI: PAD35FNCSEL (Bit 27) */ +#define GPIO_PADREGI_PAD35FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGI: PAD35FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGI_PAD35STRNG_Pos (26UL) /*!< GPIO PADREGI: PAD35STRNG (Bit 26) */ +#define GPIO_PADREGI_PAD35STRNG_Msk (0x4000000UL) /*!< GPIO PADREGI: PAD35STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD35INPEN_Pos (25UL) /*!< GPIO PADREGI: PAD35INPEN (Bit 25) */ +#define GPIO_PADREGI_PAD35INPEN_Msk (0x2000000UL) /*!< GPIO PADREGI: PAD35INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD35PULL_Pos (24UL) /*!< GPIO PADREGI: PAD35PULL (Bit 24) */ +#define GPIO_PADREGI_PAD35PULL_Msk (0x1000000UL) /*!< GPIO PADREGI: PAD35PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD34FNCSEL_Pos (19UL) /*!< GPIO PADREGI: PAD34FNCSEL (Bit 19) */ +#define GPIO_PADREGI_PAD34FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGI: PAD34FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGI_PAD34STRNG_Pos (18UL) /*!< GPIO PADREGI: PAD34STRNG (Bit 18) */ +#define GPIO_PADREGI_PAD34STRNG_Msk (0x40000UL) /*!< GPIO PADREGI: PAD34STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD34INPEN_Pos (17UL) /*!< GPIO PADREGI: PAD34INPEN (Bit 17) */ +#define GPIO_PADREGI_PAD34INPEN_Msk (0x20000UL) /*!< GPIO PADREGI: PAD34INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD34PULL_Pos (16UL) /*!< GPIO PADREGI: PAD34PULL (Bit 16) */ +#define GPIO_PADREGI_PAD34PULL_Msk (0x10000UL) /*!< GPIO PADREGI: PAD34PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD33FNCSEL_Pos (11UL) /*!< GPIO PADREGI: PAD33FNCSEL (Bit 11) */ +#define GPIO_PADREGI_PAD33FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGI: PAD33FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGI_PAD33STRNG_Pos (10UL) /*!< GPIO PADREGI: PAD33STRNG (Bit 10) */ +#define GPIO_PADREGI_PAD33STRNG_Msk (0x400UL) /*!< GPIO PADREGI: PAD33STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD33INPEN_Pos (9UL) /*!< GPIO PADREGI: PAD33INPEN (Bit 9) */ +#define GPIO_PADREGI_PAD33INPEN_Msk (0x200UL) /*!< GPIO PADREGI: PAD33INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD33PULL_Pos (8UL) /*!< GPIO PADREGI: PAD33PULL (Bit 8) */ +#define GPIO_PADREGI_PAD33PULL_Msk (0x100UL) /*!< GPIO PADREGI: PAD33PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD32FNCSEL_Pos (3UL) /*!< GPIO PADREGI: PAD32FNCSEL (Bit 3) */ +#define GPIO_PADREGI_PAD32FNCSEL_Msk (0x38UL) /*!< GPIO PADREGI: PAD32FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGI_PAD32STRNG_Pos (2UL) /*!< GPIO PADREGI: PAD32STRNG (Bit 2) */ +#define GPIO_PADREGI_PAD32STRNG_Msk (0x4UL) /*!< GPIO PADREGI: PAD32STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD32INPEN_Pos (1UL) /*!< GPIO PADREGI: PAD32INPEN (Bit 1) */ +#define GPIO_PADREGI_PAD32INPEN_Msk (0x2UL) /*!< GPIO PADREGI: PAD32INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGI_PAD32PULL_Pos (0UL) /*!< GPIO PADREGI: PAD32PULL (Bit 0) */ +#define GPIO_PADREGI_PAD32PULL_Msk (0x1UL) /*!< GPIO PADREGI: PAD32PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGJ ======================================================== */ +#define GPIO_PADREGJ_PAD39RSEL_Pos (30UL) /*!< GPIO PADREGJ: PAD39RSEL (Bit 30) */ +#define GPIO_PADREGJ_PAD39RSEL_Msk (0xc0000000UL) /*!< GPIO PADREGJ: PAD39RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGJ_PAD39FNCSEL_Pos (27UL) /*!< GPIO PADREGJ: PAD39FNCSEL (Bit 27) */ +#define GPIO_PADREGJ_PAD39FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGJ: PAD39FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGJ_PAD39STRNG_Pos (26UL) /*!< GPIO PADREGJ: PAD39STRNG (Bit 26) */ +#define GPIO_PADREGJ_PAD39STRNG_Msk (0x4000000UL) /*!< GPIO PADREGJ: PAD39STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD39INPEN_Pos (25UL) /*!< GPIO PADREGJ: PAD39INPEN (Bit 25) */ +#define GPIO_PADREGJ_PAD39INPEN_Msk (0x2000000UL) /*!< GPIO PADREGJ: PAD39INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD39PULL_Pos (24UL) /*!< GPIO PADREGJ: PAD39PULL (Bit 24) */ +#define GPIO_PADREGJ_PAD39PULL_Msk (0x1000000UL) /*!< GPIO PADREGJ: PAD39PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD38FNCSEL_Pos (19UL) /*!< GPIO PADREGJ: PAD38FNCSEL (Bit 19) */ +#define GPIO_PADREGJ_PAD38FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGJ: PAD38FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGJ_PAD38STRNG_Pos (18UL) /*!< GPIO PADREGJ: PAD38STRNG (Bit 18) */ +#define GPIO_PADREGJ_PAD38STRNG_Msk (0x40000UL) /*!< GPIO PADREGJ: PAD38STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD38INPEN_Pos (17UL) /*!< GPIO PADREGJ: PAD38INPEN (Bit 17) */ +#define GPIO_PADREGJ_PAD38INPEN_Msk (0x20000UL) /*!< GPIO PADREGJ: PAD38INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD38PULL_Pos (16UL) /*!< GPIO PADREGJ: PAD38PULL (Bit 16) */ +#define GPIO_PADREGJ_PAD38PULL_Msk (0x10000UL) /*!< GPIO PADREGJ: PAD38PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD37PWRDN_Pos (15UL) /*!< GPIO PADREGJ: PAD37PWRDN (Bit 15) */ +#define GPIO_PADREGJ_PAD37PWRDN_Msk (0x8000UL) /*!< GPIO PADREGJ: PAD37PWRDN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD37FNCSEL_Pos (11UL) /*!< GPIO PADREGJ: PAD37FNCSEL (Bit 11) */ +#define GPIO_PADREGJ_PAD37FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGJ: PAD37FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGJ_PAD37STRNG_Pos (10UL) /*!< GPIO PADREGJ: PAD37STRNG (Bit 10) */ +#define GPIO_PADREGJ_PAD37STRNG_Msk (0x400UL) /*!< GPIO PADREGJ: PAD37STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD37INPEN_Pos (9UL) /*!< GPIO PADREGJ: PAD37INPEN (Bit 9) */ +#define GPIO_PADREGJ_PAD37INPEN_Msk (0x200UL) /*!< GPIO PADREGJ: PAD37INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD37PULL_Pos (8UL) /*!< GPIO PADREGJ: PAD37PULL (Bit 8) */ +#define GPIO_PADREGJ_PAD37PULL_Msk (0x100UL) /*!< GPIO PADREGJ: PAD37PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD36PWRUP_Pos (6UL) /*!< GPIO PADREGJ: PAD36PWRUP (Bit 6) */ +#define GPIO_PADREGJ_PAD36PWRUP_Msk (0x40UL) /*!< GPIO PADREGJ: PAD36PWRUP (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD36FNCSEL_Pos (3UL) /*!< GPIO PADREGJ: PAD36FNCSEL (Bit 3) */ +#define GPIO_PADREGJ_PAD36FNCSEL_Msk (0x38UL) /*!< GPIO PADREGJ: PAD36FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGJ_PAD36STRNG_Pos (2UL) /*!< GPIO PADREGJ: PAD36STRNG (Bit 2) */ +#define GPIO_PADREGJ_PAD36STRNG_Msk (0x4UL) /*!< GPIO PADREGJ: PAD36STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD36INPEN_Pos (1UL) /*!< GPIO PADREGJ: PAD36INPEN (Bit 1) */ +#define GPIO_PADREGJ_PAD36INPEN_Msk (0x2UL) /*!< GPIO PADREGJ: PAD36INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGJ_PAD36PULL_Pos (0UL) /*!< GPIO PADREGJ: PAD36PULL (Bit 0) */ +#define GPIO_PADREGJ_PAD36PULL_Msk (0x1UL) /*!< GPIO PADREGJ: PAD36PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGK ======================================================== */ +#define GPIO_PADREGK_PAD43RSEL_Pos (30UL) /*!< GPIO PADREGK: PAD43RSEL (Bit 30) */ +#define GPIO_PADREGK_PAD43RSEL_Msk (0xc0000000UL) /*!< GPIO PADREGK: PAD43RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGK_PAD43FNCSEL_Pos (27UL) /*!< GPIO PADREGK: PAD43FNCSEL (Bit 27) */ +#define GPIO_PADREGK_PAD43FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGK: PAD43FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGK_PAD43STRNG_Pos (26UL) /*!< GPIO PADREGK: PAD43STRNG (Bit 26) */ +#define GPIO_PADREGK_PAD43STRNG_Msk (0x4000000UL) /*!< GPIO PADREGK: PAD43STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD43INPEN_Pos (25UL) /*!< GPIO PADREGK: PAD43INPEN (Bit 25) */ +#define GPIO_PADREGK_PAD43INPEN_Msk (0x2000000UL) /*!< GPIO PADREGK: PAD43INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD43PULL_Pos (24UL) /*!< GPIO PADREGK: PAD43PULL (Bit 24) */ +#define GPIO_PADREGK_PAD43PULL_Msk (0x1000000UL) /*!< GPIO PADREGK: PAD43PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD42RSEL_Pos (22UL) /*!< GPIO PADREGK: PAD42RSEL (Bit 22) */ +#define GPIO_PADREGK_PAD42RSEL_Msk (0xc00000UL) /*!< GPIO PADREGK: PAD42RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGK_PAD42FNCSEL_Pos (19UL) /*!< GPIO PADREGK: PAD42FNCSEL (Bit 19) */ +#define GPIO_PADREGK_PAD42FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGK: PAD42FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGK_PAD42STRNG_Pos (18UL) /*!< GPIO PADREGK: PAD42STRNG (Bit 18) */ +#define GPIO_PADREGK_PAD42STRNG_Msk (0x40000UL) /*!< GPIO PADREGK: PAD42STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD42INPEN_Pos (17UL) /*!< GPIO PADREGK: PAD42INPEN (Bit 17) */ +#define GPIO_PADREGK_PAD42INPEN_Msk (0x20000UL) /*!< GPIO PADREGK: PAD42INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD42PULL_Pos (16UL) /*!< GPIO PADREGK: PAD42PULL (Bit 16) */ +#define GPIO_PADREGK_PAD42PULL_Msk (0x10000UL) /*!< GPIO PADREGK: PAD42PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD41PWRDN_Pos (15UL) /*!< GPIO PADREGK: PAD41PWRDN (Bit 15) */ +#define GPIO_PADREGK_PAD41PWRDN_Msk (0x8000UL) /*!< GPIO PADREGK: PAD41PWRDN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD41FNCSEL_Pos (11UL) /*!< GPIO PADREGK: PAD41FNCSEL (Bit 11) */ +#define GPIO_PADREGK_PAD41FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGK: PAD41FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGK_PAD41STRNG_Pos (10UL) /*!< GPIO PADREGK: PAD41STRNG (Bit 10) */ +#define GPIO_PADREGK_PAD41STRNG_Msk (0x400UL) /*!< GPIO PADREGK: PAD41STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD41INPEN_Pos (9UL) /*!< GPIO PADREGK: PAD41INPEN (Bit 9) */ +#define GPIO_PADREGK_PAD41INPEN_Msk (0x200UL) /*!< GPIO PADREGK: PAD41INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD41PULL_Pos (8UL) /*!< GPIO PADREGK: PAD41PULL (Bit 8) */ +#define GPIO_PADREGK_PAD41PULL_Msk (0x100UL) /*!< GPIO PADREGK: PAD41PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD40RSEL_Pos (6UL) /*!< GPIO PADREGK: PAD40RSEL (Bit 6) */ +#define GPIO_PADREGK_PAD40RSEL_Msk (0xc0UL) /*!< GPIO PADREGK: PAD40RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGK_PAD40FNCSEL_Pos (3UL) /*!< GPIO PADREGK: PAD40FNCSEL (Bit 3) */ +#define GPIO_PADREGK_PAD40FNCSEL_Msk (0x38UL) /*!< GPIO PADREGK: PAD40FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGK_PAD40STRNG_Pos (2UL) /*!< GPIO PADREGK: PAD40STRNG (Bit 2) */ +#define GPIO_PADREGK_PAD40STRNG_Msk (0x4UL) /*!< GPIO PADREGK: PAD40STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD40INPEN_Pos (1UL) /*!< GPIO PADREGK: PAD40INPEN (Bit 1) */ +#define GPIO_PADREGK_PAD40INPEN_Msk (0x2UL) /*!< GPIO PADREGK: PAD40INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGK_PAD40PULL_Pos (0UL) /*!< GPIO PADREGK: PAD40PULL (Bit 0) */ +#define GPIO_PADREGK_PAD40PULL_Msk (0x1UL) /*!< GPIO PADREGK: PAD40PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGL ======================================================== */ +#define GPIO_PADREGL_PAD47FNCSEL_Pos (27UL) /*!< GPIO PADREGL: PAD47FNCSEL (Bit 27) */ +#define GPIO_PADREGL_PAD47FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGL: PAD47FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGL_PAD47STRNG_Pos (26UL) /*!< GPIO PADREGL: PAD47STRNG (Bit 26) */ +#define GPIO_PADREGL_PAD47STRNG_Msk (0x4000000UL) /*!< GPIO PADREGL: PAD47STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD47INPEN_Pos (25UL) /*!< GPIO PADREGL: PAD47INPEN (Bit 25) */ +#define GPIO_PADREGL_PAD47INPEN_Msk (0x2000000UL) /*!< GPIO PADREGL: PAD47INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD47PULL_Pos (24UL) /*!< GPIO PADREGL: PAD47PULL (Bit 24) */ +#define GPIO_PADREGL_PAD47PULL_Msk (0x1000000UL) /*!< GPIO PADREGL: PAD47PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD46FNCSEL_Pos (19UL) /*!< GPIO PADREGL: PAD46FNCSEL (Bit 19) */ +#define GPIO_PADREGL_PAD46FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGL: PAD46FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGL_PAD46STRNG_Pos (18UL) /*!< GPIO PADREGL: PAD46STRNG (Bit 18) */ +#define GPIO_PADREGL_PAD46STRNG_Msk (0x40000UL) /*!< GPIO PADREGL: PAD46STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD46INPEN_Pos (17UL) /*!< GPIO PADREGL: PAD46INPEN (Bit 17) */ +#define GPIO_PADREGL_PAD46INPEN_Msk (0x20000UL) /*!< GPIO PADREGL: PAD46INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD46PULL_Pos (16UL) /*!< GPIO PADREGL: PAD46PULL (Bit 16) */ +#define GPIO_PADREGL_PAD46PULL_Msk (0x10000UL) /*!< GPIO PADREGL: PAD46PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD45FNCSEL_Pos (11UL) /*!< GPIO PADREGL: PAD45FNCSEL (Bit 11) */ +#define GPIO_PADREGL_PAD45FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGL: PAD45FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGL_PAD45STRNG_Pos (10UL) /*!< GPIO PADREGL: PAD45STRNG (Bit 10) */ +#define GPIO_PADREGL_PAD45STRNG_Msk (0x400UL) /*!< GPIO PADREGL: PAD45STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD45INPEN_Pos (9UL) /*!< GPIO PADREGL: PAD45INPEN (Bit 9) */ +#define GPIO_PADREGL_PAD45INPEN_Msk (0x200UL) /*!< GPIO PADREGL: PAD45INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD45PULL_Pos (8UL) /*!< GPIO PADREGL: PAD45PULL (Bit 8) */ +#define GPIO_PADREGL_PAD45PULL_Msk (0x100UL) /*!< GPIO PADREGL: PAD45PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD44FNCSEL_Pos (3UL) /*!< GPIO PADREGL: PAD44FNCSEL (Bit 3) */ +#define GPIO_PADREGL_PAD44FNCSEL_Msk (0x38UL) /*!< GPIO PADREGL: PAD44FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGL_PAD44STRNG_Pos (2UL) /*!< GPIO PADREGL: PAD44STRNG (Bit 2) */ +#define GPIO_PADREGL_PAD44STRNG_Msk (0x4UL) /*!< GPIO PADREGL: PAD44STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD44INPEN_Pos (1UL) /*!< GPIO PADREGL: PAD44INPEN (Bit 1) */ +#define GPIO_PADREGL_PAD44INPEN_Msk (0x2UL) /*!< GPIO PADREGL: PAD44INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGL_PAD44PULL_Pos (0UL) /*!< GPIO PADREGL: PAD44PULL (Bit 0) */ +#define GPIO_PADREGL_PAD44PULL_Msk (0x1UL) /*!< GPIO PADREGL: PAD44PULL (Bitfield-Mask: 0x01) */ +/* ======================================================== PADREGM ======================================================== */ +#define GPIO_PADREGM_PAD49RSEL_Pos (14UL) /*!< GPIO PADREGM: PAD49RSEL (Bit 14) */ +#define GPIO_PADREGM_PAD49RSEL_Msk (0xc000UL) /*!< GPIO PADREGM: PAD49RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGM_PAD49FNCSEL_Pos (11UL) /*!< GPIO PADREGM: PAD49FNCSEL (Bit 11) */ +#define GPIO_PADREGM_PAD49FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGM: PAD49FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGM_PAD49STRNG_Pos (10UL) /*!< GPIO PADREGM: PAD49STRNG (Bit 10) */ +#define GPIO_PADREGM_PAD49STRNG_Msk (0x400UL) /*!< GPIO PADREGM: PAD49STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGM_PAD49INPEN_Pos (9UL) /*!< GPIO PADREGM: PAD49INPEN (Bit 9) */ +#define GPIO_PADREGM_PAD49INPEN_Msk (0x200UL) /*!< GPIO PADREGM: PAD49INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGM_PAD49PULL_Pos (8UL) /*!< GPIO PADREGM: PAD49PULL (Bit 8) */ +#define GPIO_PADREGM_PAD49PULL_Msk (0x100UL) /*!< GPIO PADREGM: PAD49PULL (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGM_PAD48RSEL_Pos (6UL) /*!< GPIO PADREGM: PAD48RSEL (Bit 6) */ +#define GPIO_PADREGM_PAD48RSEL_Msk (0xc0UL) /*!< GPIO PADREGM: PAD48RSEL (Bitfield-Mask: 0x03) */ +#define GPIO_PADREGM_PAD48FNCSEL_Pos (3UL) /*!< GPIO PADREGM: PAD48FNCSEL (Bit 3) */ +#define GPIO_PADREGM_PAD48FNCSEL_Msk (0x38UL) /*!< GPIO PADREGM: PAD48FNCSEL (Bitfield-Mask: 0x07) */ +#define GPIO_PADREGM_PAD48STRNG_Pos (2UL) /*!< GPIO PADREGM: PAD48STRNG (Bit 2) */ +#define GPIO_PADREGM_PAD48STRNG_Msk (0x4UL) /*!< GPIO PADREGM: PAD48STRNG (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGM_PAD48INPEN_Pos (1UL) /*!< GPIO PADREGM: PAD48INPEN (Bit 1) */ +#define GPIO_PADREGM_PAD48INPEN_Msk (0x2UL) /*!< GPIO PADREGM: PAD48INPEN (Bitfield-Mask: 0x01) */ +#define GPIO_PADREGM_PAD48PULL_Pos (0UL) /*!< GPIO PADREGM: PAD48PULL (Bit 0) */ +#define GPIO_PADREGM_PAD48PULL_Msk (0x1UL) /*!< GPIO PADREGM: PAD48PULL (Bitfield-Mask: 0x01) */ +/* ========================================================= CFGA ========================================================== */ +#define GPIO_CFGA_GPIO7INTD_Pos (31UL) /*!< GPIO CFGA: GPIO7INTD (Bit 31) */ +#define GPIO_CFGA_GPIO7INTD_Msk (0x80000000UL) /*!< GPIO CFGA: GPIO7INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO7OUTCFG_Pos (29UL) /*!< GPIO CFGA: GPIO7OUTCFG (Bit 29) */ +#define GPIO_CFGA_GPIO7OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGA: GPIO7OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGA_GPIO7INCFG_Pos (28UL) /*!< GPIO CFGA: GPIO7INCFG (Bit 28) */ +#define GPIO_CFGA_GPIO7INCFG_Msk (0x10000000UL) /*!< GPIO CFGA: GPIO7INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO6INTD_Pos (27UL) /*!< GPIO CFGA: GPIO6INTD (Bit 27) */ +#define GPIO_CFGA_GPIO6INTD_Msk (0x8000000UL) /*!< GPIO CFGA: GPIO6INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO6OUTCFG_Pos (25UL) /*!< GPIO CFGA: GPIO6OUTCFG (Bit 25) */ +#define GPIO_CFGA_GPIO6OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGA: GPIO6OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGA_GPIO6INCFG_Pos (24UL) /*!< GPIO CFGA: GPIO6INCFG (Bit 24) */ +#define GPIO_CFGA_GPIO6INCFG_Msk (0x1000000UL) /*!< GPIO CFGA: GPIO6INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO5INTD_Pos (23UL) /*!< GPIO CFGA: GPIO5INTD (Bit 23) */ +#define GPIO_CFGA_GPIO5INTD_Msk (0x800000UL) /*!< GPIO CFGA: GPIO5INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO5OUTCFG_Pos (21UL) /*!< GPIO CFGA: GPIO5OUTCFG (Bit 21) */ +#define GPIO_CFGA_GPIO5OUTCFG_Msk (0x600000UL) /*!< GPIO CFGA: GPIO5OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGA_GPIO5INCFG_Pos (20UL) /*!< GPIO CFGA: GPIO5INCFG (Bit 20) */ +#define GPIO_CFGA_GPIO5INCFG_Msk (0x100000UL) /*!< GPIO CFGA: GPIO5INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO4INTD_Pos (19UL) /*!< GPIO CFGA: GPIO4INTD (Bit 19) */ +#define GPIO_CFGA_GPIO4INTD_Msk (0x80000UL) /*!< GPIO CFGA: GPIO4INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO4OUTCFG_Pos (17UL) /*!< GPIO CFGA: GPIO4OUTCFG (Bit 17) */ +#define GPIO_CFGA_GPIO4OUTCFG_Msk (0x60000UL) /*!< GPIO CFGA: GPIO4OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGA_GPIO4INCFG_Pos (16UL) /*!< GPIO CFGA: GPIO4INCFG (Bit 16) */ +#define GPIO_CFGA_GPIO4INCFG_Msk (0x10000UL) /*!< GPIO CFGA: GPIO4INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO3INTD_Pos (15UL) /*!< GPIO CFGA: GPIO3INTD (Bit 15) */ +#define GPIO_CFGA_GPIO3INTD_Msk (0x8000UL) /*!< GPIO CFGA: GPIO3INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO3OUTCFG_Pos (13UL) /*!< GPIO CFGA: GPIO3OUTCFG (Bit 13) */ +#define GPIO_CFGA_GPIO3OUTCFG_Msk (0x6000UL) /*!< GPIO CFGA: GPIO3OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGA_GPIO3INCFG_Pos (12UL) /*!< GPIO CFGA: GPIO3INCFG (Bit 12) */ +#define GPIO_CFGA_GPIO3INCFG_Msk (0x1000UL) /*!< GPIO CFGA: GPIO3INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO2INTD_Pos (11UL) /*!< GPIO CFGA: GPIO2INTD (Bit 11) */ +#define GPIO_CFGA_GPIO2INTD_Msk (0x800UL) /*!< GPIO CFGA: GPIO2INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO2OUTCFG_Pos (9UL) /*!< GPIO CFGA: GPIO2OUTCFG (Bit 9) */ +#define GPIO_CFGA_GPIO2OUTCFG_Msk (0x600UL) /*!< GPIO CFGA: GPIO2OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGA_GPIO2INCFG_Pos (8UL) /*!< GPIO CFGA: GPIO2INCFG (Bit 8) */ +#define GPIO_CFGA_GPIO2INCFG_Msk (0x100UL) /*!< GPIO CFGA: GPIO2INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO1INTD_Pos (7UL) /*!< GPIO CFGA: GPIO1INTD (Bit 7) */ +#define GPIO_CFGA_GPIO1INTD_Msk (0x80UL) /*!< GPIO CFGA: GPIO1INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO1OUTCFG_Pos (5UL) /*!< GPIO CFGA: GPIO1OUTCFG (Bit 5) */ +#define GPIO_CFGA_GPIO1OUTCFG_Msk (0x60UL) /*!< GPIO CFGA: GPIO1OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGA_GPIO1INCFG_Pos (4UL) /*!< GPIO CFGA: GPIO1INCFG (Bit 4) */ +#define GPIO_CFGA_GPIO1INCFG_Msk (0x10UL) /*!< GPIO CFGA: GPIO1INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO0INTD_Pos (3UL) /*!< GPIO CFGA: GPIO0INTD (Bit 3) */ +#define GPIO_CFGA_GPIO0INTD_Msk (0x8UL) /*!< GPIO CFGA: GPIO0INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGA_GPIO0OUTCFG_Pos (1UL) /*!< GPIO CFGA: GPIO0OUTCFG (Bit 1) */ +#define GPIO_CFGA_GPIO0OUTCFG_Msk (0x6UL) /*!< GPIO CFGA: GPIO0OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGA_GPIO0INCFG_Pos (0UL) /*!< GPIO CFGA: GPIO0INCFG (Bit 0) */ +#define GPIO_CFGA_GPIO0INCFG_Msk (0x1UL) /*!< GPIO CFGA: GPIO0INCFG (Bitfield-Mask: 0x01) */ +/* ========================================================= CFGB ========================================================== */ +#define GPIO_CFGB_GPIO15INTD_Pos (31UL) /*!< GPIO CFGB: GPIO15INTD (Bit 31) */ +#define GPIO_CFGB_GPIO15INTD_Msk (0x80000000UL) /*!< GPIO CFGB: GPIO15INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO15OUTCFG_Pos (29UL) /*!< GPIO CFGB: GPIO15OUTCFG (Bit 29) */ +#define GPIO_CFGB_GPIO15OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGB: GPIO15OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGB_GPIO15INCFG_Pos (28UL) /*!< GPIO CFGB: GPIO15INCFG (Bit 28) */ +#define GPIO_CFGB_GPIO15INCFG_Msk (0x10000000UL) /*!< GPIO CFGB: GPIO15INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO14INTD_Pos (27UL) /*!< GPIO CFGB: GPIO14INTD (Bit 27) */ +#define GPIO_CFGB_GPIO14INTD_Msk (0x8000000UL) /*!< GPIO CFGB: GPIO14INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO14OUTCFG_Pos (25UL) /*!< GPIO CFGB: GPIO14OUTCFG (Bit 25) */ +#define GPIO_CFGB_GPIO14OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGB: GPIO14OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGB_GPIO14INCFG_Pos (24UL) /*!< GPIO CFGB: GPIO14INCFG (Bit 24) */ +#define GPIO_CFGB_GPIO14INCFG_Msk (0x1000000UL) /*!< GPIO CFGB: GPIO14INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO13INTD_Pos (23UL) /*!< GPIO CFGB: GPIO13INTD (Bit 23) */ +#define GPIO_CFGB_GPIO13INTD_Msk (0x800000UL) /*!< GPIO CFGB: GPIO13INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO13OUTCFG_Pos (21UL) /*!< GPIO CFGB: GPIO13OUTCFG (Bit 21) */ +#define GPIO_CFGB_GPIO13OUTCFG_Msk (0x600000UL) /*!< GPIO CFGB: GPIO13OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGB_GPIO13INCFG_Pos (20UL) /*!< GPIO CFGB: GPIO13INCFG (Bit 20) */ +#define GPIO_CFGB_GPIO13INCFG_Msk (0x100000UL) /*!< GPIO CFGB: GPIO13INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO12INTD_Pos (19UL) /*!< GPIO CFGB: GPIO12INTD (Bit 19) */ +#define GPIO_CFGB_GPIO12INTD_Msk (0x80000UL) /*!< GPIO CFGB: GPIO12INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO12OUTCFG_Pos (17UL) /*!< GPIO CFGB: GPIO12OUTCFG (Bit 17) */ +#define GPIO_CFGB_GPIO12OUTCFG_Msk (0x60000UL) /*!< GPIO CFGB: GPIO12OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGB_GPIO12INCFG_Pos (16UL) /*!< GPIO CFGB: GPIO12INCFG (Bit 16) */ +#define GPIO_CFGB_GPIO12INCFG_Msk (0x10000UL) /*!< GPIO CFGB: GPIO12INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO11INTD_Pos (15UL) /*!< GPIO CFGB: GPIO11INTD (Bit 15) */ +#define GPIO_CFGB_GPIO11INTD_Msk (0x8000UL) /*!< GPIO CFGB: GPIO11INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO11OUTCFG_Pos (13UL) /*!< GPIO CFGB: GPIO11OUTCFG (Bit 13) */ +#define GPIO_CFGB_GPIO11OUTCFG_Msk (0x6000UL) /*!< GPIO CFGB: GPIO11OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGB_GPIO11INCFG_Pos (12UL) /*!< GPIO CFGB: GPIO11INCFG (Bit 12) */ +#define GPIO_CFGB_GPIO11INCFG_Msk (0x1000UL) /*!< GPIO CFGB: GPIO11INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO10INTD_Pos (11UL) /*!< GPIO CFGB: GPIO10INTD (Bit 11) */ +#define GPIO_CFGB_GPIO10INTD_Msk (0x800UL) /*!< GPIO CFGB: GPIO10INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO10OUTCFG_Pos (9UL) /*!< GPIO CFGB: GPIO10OUTCFG (Bit 9) */ +#define GPIO_CFGB_GPIO10OUTCFG_Msk (0x600UL) /*!< GPIO CFGB: GPIO10OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGB_GPIO10INCFG_Pos (8UL) /*!< GPIO CFGB: GPIO10INCFG (Bit 8) */ +#define GPIO_CFGB_GPIO10INCFG_Msk (0x100UL) /*!< GPIO CFGB: GPIO10INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO9INTD_Pos (7UL) /*!< GPIO CFGB: GPIO9INTD (Bit 7) */ +#define GPIO_CFGB_GPIO9INTD_Msk (0x80UL) /*!< GPIO CFGB: GPIO9INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO9OUTCFG_Pos (5UL) /*!< GPIO CFGB: GPIO9OUTCFG (Bit 5) */ +#define GPIO_CFGB_GPIO9OUTCFG_Msk (0x60UL) /*!< GPIO CFGB: GPIO9OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGB_GPIO9INCFG_Pos (4UL) /*!< GPIO CFGB: GPIO9INCFG (Bit 4) */ +#define GPIO_CFGB_GPIO9INCFG_Msk (0x10UL) /*!< GPIO CFGB: GPIO9INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO8INTD_Pos (3UL) /*!< GPIO CFGB: GPIO8INTD (Bit 3) */ +#define GPIO_CFGB_GPIO8INTD_Msk (0x8UL) /*!< GPIO CFGB: GPIO8INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGB_GPIO8OUTCFG_Pos (1UL) /*!< GPIO CFGB: GPIO8OUTCFG (Bit 1) */ +#define GPIO_CFGB_GPIO8OUTCFG_Msk (0x6UL) /*!< GPIO CFGB: GPIO8OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGB_GPIO8INCFG_Pos (0UL) /*!< GPIO CFGB: GPIO8INCFG (Bit 0) */ +#define GPIO_CFGB_GPIO8INCFG_Msk (0x1UL) /*!< GPIO CFGB: GPIO8INCFG (Bitfield-Mask: 0x01) */ +/* ========================================================= CFGC ========================================================== */ +#define GPIO_CFGC_GPIO23INTD_Pos (31UL) /*!< GPIO CFGC: GPIO23INTD (Bit 31) */ +#define GPIO_CFGC_GPIO23INTD_Msk (0x80000000UL) /*!< GPIO CFGC: GPIO23INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO23OUTCFG_Pos (29UL) /*!< GPIO CFGC: GPIO23OUTCFG (Bit 29) */ +#define GPIO_CFGC_GPIO23OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGC: GPIO23OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGC_GPIO23INCFG_Pos (28UL) /*!< GPIO CFGC: GPIO23INCFG (Bit 28) */ +#define GPIO_CFGC_GPIO23INCFG_Msk (0x10000000UL) /*!< GPIO CFGC: GPIO23INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO22INTD_Pos (27UL) /*!< GPIO CFGC: GPIO22INTD (Bit 27) */ +#define GPIO_CFGC_GPIO22INTD_Msk (0x8000000UL) /*!< GPIO CFGC: GPIO22INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO22OUTCFG_Pos (25UL) /*!< GPIO CFGC: GPIO22OUTCFG (Bit 25) */ +#define GPIO_CFGC_GPIO22OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGC: GPIO22OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGC_GPIO22INCFG_Pos (24UL) /*!< GPIO CFGC: GPIO22INCFG (Bit 24) */ +#define GPIO_CFGC_GPIO22INCFG_Msk (0x1000000UL) /*!< GPIO CFGC: GPIO22INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO21INTD_Pos (23UL) /*!< GPIO CFGC: GPIO21INTD (Bit 23) */ +#define GPIO_CFGC_GPIO21INTD_Msk (0x800000UL) /*!< GPIO CFGC: GPIO21INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO21OUTCFG_Pos (21UL) /*!< GPIO CFGC: GPIO21OUTCFG (Bit 21) */ +#define GPIO_CFGC_GPIO21OUTCFG_Msk (0x600000UL) /*!< GPIO CFGC: GPIO21OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGC_GPIO21INCFG_Pos (20UL) /*!< GPIO CFGC: GPIO21INCFG (Bit 20) */ +#define GPIO_CFGC_GPIO21INCFG_Msk (0x100000UL) /*!< GPIO CFGC: GPIO21INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO20INTD_Pos (19UL) /*!< GPIO CFGC: GPIO20INTD (Bit 19) */ +#define GPIO_CFGC_GPIO20INTD_Msk (0x80000UL) /*!< GPIO CFGC: GPIO20INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO20OUTCFG_Pos (17UL) /*!< GPIO CFGC: GPIO20OUTCFG (Bit 17) */ +#define GPIO_CFGC_GPIO20OUTCFG_Msk (0x60000UL) /*!< GPIO CFGC: GPIO20OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGC_GPIO20INCFG_Pos (16UL) /*!< GPIO CFGC: GPIO20INCFG (Bit 16) */ +#define GPIO_CFGC_GPIO20INCFG_Msk (0x10000UL) /*!< GPIO CFGC: GPIO20INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO19INTD_Pos (15UL) /*!< GPIO CFGC: GPIO19INTD (Bit 15) */ +#define GPIO_CFGC_GPIO19INTD_Msk (0x8000UL) /*!< GPIO CFGC: GPIO19INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO19OUTCFG_Pos (13UL) /*!< GPIO CFGC: GPIO19OUTCFG (Bit 13) */ +#define GPIO_CFGC_GPIO19OUTCFG_Msk (0x6000UL) /*!< GPIO CFGC: GPIO19OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGC_GPIO19INCFG_Pos (12UL) /*!< GPIO CFGC: GPIO19INCFG (Bit 12) */ +#define GPIO_CFGC_GPIO19INCFG_Msk (0x1000UL) /*!< GPIO CFGC: GPIO19INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO18INTD_Pos (11UL) /*!< GPIO CFGC: GPIO18INTD (Bit 11) */ +#define GPIO_CFGC_GPIO18INTD_Msk (0x800UL) /*!< GPIO CFGC: GPIO18INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO18OUTCFG_Pos (9UL) /*!< GPIO CFGC: GPIO18OUTCFG (Bit 9) */ +#define GPIO_CFGC_GPIO18OUTCFG_Msk (0x600UL) /*!< GPIO CFGC: GPIO18OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGC_GPIO18INCFG_Pos (8UL) /*!< GPIO CFGC: GPIO18INCFG (Bit 8) */ +#define GPIO_CFGC_GPIO18INCFG_Msk (0x100UL) /*!< GPIO CFGC: GPIO18INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO17INTD_Pos (7UL) /*!< GPIO CFGC: GPIO17INTD (Bit 7) */ +#define GPIO_CFGC_GPIO17INTD_Msk (0x80UL) /*!< GPIO CFGC: GPIO17INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO17OUTCFG_Pos (5UL) /*!< GPIO CFGC: GPIO17OUTCFG (Bit 5) */ +#define GPIO_CFGC_GPIO17OUTCFG_Msk (0x60UL) /*!< GPIO CFGC: GPIO17OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGC_GPIO17INCFG_Pos (4UL) /*!< GPIO CFGC: GPIO17INCFG (Bit 4) */ +#define GPIO_CFGC_GPIO17INCFG_Msk (0x10UL) /*!< GPIO CFGC: GPIO17INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO16INTD_Pos (3UL) /*!< GPIO CFGC: GPIO16INTD (Bit 3) */ +#define GPIO_CFGC_GPIO16INTD_Msk (0x8UL) /*!< GPIO CFGC: GPIO16INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGC_GPIO16OUTCFG_Pos (1UL) /*!< GPIO CFGC: GPIO16OUTCFG (Bit 1) */ +#define GPIO_CFGC_GPIO16OUTCFG_Msk (0x6UL) /*!< GPIO CFGC: GPIO16OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGC_GPIO16INCFG_Pos (0UL) /*!< GPIO CFGC: GPIO16INCFG (Bit 0) */ +#define GPIO_CFGC_GPIO16INCFG_Msk (0x1UL) /*!< GPIO CFGC: GPIO16INCFG (Bitfield-Mask: 0x01) */ +/* ========================================================= CFGD ========================================================== */ +#define GPIO_CFGD_GPIO31INTD_Pos (31UL) /*!< GPIO CFGD: GPIO31INTD (Bit 31) */ +#define GPIO_CFGD_GPIO31INTD_Msk (0x80000000UL) /*!< GPIO CFGD: GPIO31INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO31OUTCFG_Pos (29UL) /*!< GPIO CFGD: GPIO31OUTCFG (Bit 29) */ +#define GPIO_CFGD_GPIO31OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGD: GPIO31OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGD_GPIO31INCFG_Pos (28UL) /*!< GPIO CFGD: GPIO31INCFG (Bit 28) */ +#define GPIO_CFGD_GPIO31INCFG_Msk (0x10000000UL) /*!< GPIO CFGD: GPIO31INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO30INTD_Pos (27UL) /*!< GPIO CFGD: GPIO30INTD (Bit 27) */ +#define GPIO_CFGD_GPIO30INTD_Msk (0x8000000UL) /*!< GPIO CFGD: GPIO30INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO30OUTCFG_Pos (25UL) /*!< GPIO CFGD: GPIO30OUTCFG (Bit 25) */ +#define GPIO_CFGD_GPIO30OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGD: GPIO30OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGD_GPIO30INCFG_Pos (24UL) /*!< GPIO CFGD: GPIO30INCFG (Bit 24) */ +#define GPIO_CFGD_GPIO30INCFG_Msk (0x1000000UL) /*!< GPIO CFGD: GPIO30INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO29INTD_Pos (23UL) /*!< GPIO CFGD: GPIO29INTD (Bit 23) */ +#define GPIO_CFGD_GPIO29INTD_Msk (0x800000UL) /*!< GPIO CFGD: GPIO29INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO29OUTCFG_Pos (21UL) /*!< GPIO CFGD: GPIO29OUTCFG (Bit 21) */ +#define GPIO_CFGD_GPIO29OUTCFG_Msk (0x600000UL) /*!< GPIO CFGD: GPIO29OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGD_GPIO29INCFG_Pos (20UL) /*!< GPIO CFGD: GPIO29INCFG (Bit 20) */ +#define GPIO_CFGD_GPIO29INCFG_Msk (0x100000UL) /*!< GPIO CFGD: GPIO29INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO28INTD_Pos (19UL) /*!< GPIO CFGD: GPIO28INTD (Bit 19) */ +#define GPIO_CFGD_GPIO28INTD_Msk (0x80000UL) /*!< GPIO CFGD: GPIO28INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO28OUTCFG_Pos (17UL) /*!< GPIO CFGD: GPIO28OUTCFG (Bit 17) */ +#define GPIO_CFGD_GPIO28OUTCFG_Msk (0x60000UL) /*!< GPIO CFGD: GPIO28OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGD_GPIO28INCFG_Pos (16UL) /*!< GPIO CFGD: GPIO28INCFG (Bit 16) */ +#define GPIO_CFGD_GPIO28INCFG_Msk (0x10000UL) /*!< GPIO CFGD: GPIO28INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO27INTD_Pos (15UL) /*!< GPIO CFGD: GPIO27INTD (Bit 15) */ +#define GPIO_CFGD_GPIO27INTD_Msk (0x8000UL) /*!< GPIO CFGD: GPIO27INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO27OUTCFG_Pos (13UL) /*!< GPIO CFGD: GPIO27OUTCFG (Bit 13) */ +#define GPIO_CFGD_GPIO27OUTCFG_Msk (0x6000UL) /*!< GPIO CFGD: GPIO27OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGD_GPIO27INCFG_Pos (12UL) /*!< GPIO CFGD: GPIO27INCFG (Bit 12) */ +#define GPIO_CFGD_GPIO27INCFG_Msk (0x1000UL) /*!< GPIO CFGD: GPIO27INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO26INTD_Pos (11UL) /*!< GPIO CFGD: GPIO26INTD (Bit 11) */ +#define GPIO_CFGD_GPIO26INTD_Msk (0x800UL) /*!< GPIO CFGD: GPIO26INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO26OUTCFG_Pos (9UL) /*!< GPIO CFGD: GPIO26OUTCFG (Bit 9) */ +#define GPIO_CFGD_GPIO26OUTCFG_Msk (0x600UL) /*!< GPIO CFGD: GPIO26OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGD_GPIO26INCFG_Pos (8UL) /*!< GPIO CFGD: GPIO26INCFG (Bit 8) */ +#define GPIO_CFGD_GPIO26INCFG_Msk (0x100UL) /*!< GPIO CFGD: GPIO26INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO25INTD_Pos (7UL) /*!< GPIO CFGD: GPIO25INTD (Bit 7) */ +#define GPIO_CFGD_GPIO25INTD_Msk (0x80UL) /*!< GPIO CFGD: GPIO25INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO25OUTCFG_Pos (5UL) /*!< GPIO CFGD: GPIO25OUTCFG (Bit 5) */ +#define GPIO_CFGD_GPIO25OUTCFG_Msk (0x60UL) /*!< GPIO CFGD: GPIO25OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGD_GPIO25INCFG_Pos (4UL) /*!< GPIO CFGD: GPIO25INCFG (Bit 4) */ +#define GPIO_CFGD_GPIO25INCFG_Msk (0x10UL) /*!< GPIO CFGD: GPIO25INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO24INTD_Pos (3UL) /*!< GPIO CFGD: GPIO24INTD (Bit 3) */ +#define GPIO_CFGD_GPIO24INTD_Msk (0x8UL) /*!< GPIO CFGD: GPIO24INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGD_GPIO24OUTCFG_Pos (1UL) /*!< GPIO CFGD: GPIO24OUTCFG (Bit 1) */ +#define GPIO_CFGD_GPIO24OUTCFG_Msk (0x6UL) /*!< GPIO CFGD: GPIO24OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGD_GPIO24INCFG_Pos (0UL) /*!< GPIO CFGD: GPIO24INCFG (Bit 0) */ +#define GPIO_CFGD_GPIO24INCFG_Msk (0x1UL) /*!< GPIO CFGD: GPIO24INCFG (Bitfield-Mask: 0x01) */ +/* ========================================================= CFGE ========================================================== */ +#define GPIO_CFGE_GPIO39INTD_Pos (31UL) /*!< GPIO CFGE: GPIO39INTD (Bit 31) */ +#define GPIO_CFGE_GPIO39INTD_Msk (0x80000000UL) /*!< GPIO CFGE: GPIO39INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO39OUTCFG_Pos (29UL) /*!< GPIO CFGE: GPIO39OUTCFG (Bit 29) */ +#define GPIO_CFGE_GPIO39OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGE: GPIO39OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGE_GPIO39INCFG_Pos (28UL) /*!< GPIO CFGE: GPIO39INCFG (Bit 28) */ +#define GPIO_CFGE_GPIO39INCFG_Msk (0x10000000UL) /*!< GPIO CFGE: GPIO39INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO38INTD_Pos (27UL) /*!< GPIO CFGE: GPIO38INTD (Bit 27) */ +#define GPIO_CFGE_GPIO38INTD_Msk (0x8000000UL) /*!< GPIO CFGE: GPIO38INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO38OUTCFG_Pos (25UL) /*!< GPIO CFGE: GPIO38OUTCFG (Bit 25) */ +#define GPIO_CFGE_GPIO38OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGE: GPIO38OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGE_GPIO38INCFG_Pos (24UL) /*!< GPIO CFGE: GPIO38INCFG (Bit 24) */ +#define GPIO_CFGE_GPIO38INCFG_Msk (0x1000000UL) /*!< GPIO CFGE: GPIO38INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO37INTD_Pos (23UL) /*!< GPIO CFGE: GPIO37INTD (Bit 23) */ +#define GPIO_CFGE_GPIO37INTD_Msk (0x800000UL) /*!< GPIO CFGE: GPIO37INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO37OUTCFG_Pos (21UL) /*!< GPIO CFGE: GPIO37OUTCFG (Bit 21) */ +#define GPIO_CFGE_GPIO37OUTCFG_Msk (0x600000UL) /*!< GPIO CFGE: GPIO37OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGE_GPIO37INCFG_Pos (20UL) /*!< GPIO CFGE: GPIO37INCFG (Bit 20) */ +#define GPIO_CFGE_GPIO37INCFG_Msk (0x100000UL) /*!< GPIO CFGE: GPIO37INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO36INTD_Pos (19UL) /*!< GPIO CFGE: GPIO36INTD (Bit 19) */ +#define GPIO_CFGE_GPIO36INTD_Msk (0x80000UL) /*!< GPIO CFGE: GPIO36INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO36OUTCFG_Pos (17UL) /*!< GPIO CFGE: GPIO36OUTCFG (Bit 17) */ +#define GPIO_CFGE_GPIO36OUTCFG_Msk (0x60000UL) /*!< GPIO CFGE: GPIO36OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGE_GPIO36INCFG_Pos (16UL) /*!< GPIO CFGE: GPIO36INCFG (Bit 16) */ +#define GPIO_CFGE_GPIO36INCFG_Msk (0x10000UL) /*!< GPIO CFGE: GPIO36INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO35INTD_Pos (15UL) /*!< GPIO CFGE: GPIO35INTD (Bit 15) */ +#define GPIO_CFGE_GPIO35INTD_Msk (0x8000UL) /*!< GPIO CFGE: GPIO35INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO35OUTCFG_Pos (13UL) /*!< GPIO CFGE: GPIO35OUTCFG (Bit 13) */ +#define GPIO_CFGE_GPIO35OUTCFG_Msk (0x6000UL) /*!< GPIO CFGE: GPIO35OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGE_GPIO35INCFG_Pos (12UL) /*!< GPIO CFGE: GPIO35INCFG (Bit 12) */ +#define GPIO_CFGE_GPIO35INCFG_Msk (0x1000UL) /*!< GPIO CFGE: GPIO35INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO34INTD_Pos (11UL) /*!< GPIO CFGE: GPIO34INTD (Bit 11) */ +#define GPIO_CFGE_GPIO34INTD_Msk (0x800UL) /*!< GPIO CFGE: GPIO34INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO34OUTCFG_Pos (9UL) /*!< GPIO CFGE: GPIO34OUTCFG (Bit 9) */ +#define GPIO_CFGE_GPIO34OUTCFG_Msk (0x600UL) /*!< GPIO CFGE: GPIO34OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGE_GPIO34INCFG_Pos (8UL) /*!< GPIO CFGE: GPIO34INCFG (Bit 8) */ +#define GPIO_CFGE_GPIO34INCFG_Msk (0x100UL) /*!< GPIO CFGE: GPIO34INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO33INTD_Pos (7UL) /*!< GPIO CFGE: GPIO33INTD (Bit 7) */ +#define GPIO_CFGE_GPIO33INTD_Msk (0x80UL) /*!< GPIO CFGE: GPIO33INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO33OUTCFG_Pos (5UL) /*!< GPIO CFGE: GPIO33OUTCFG (Bit 5) */ +#define GPIO_CFGE_GPIO33OUTCFG_Msk (0x60UL) /*!< GPIO CFGE: GPIO33OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGE_GPIO33INCFG_Pos (4UL) /*!< GPIO CFGE: GPIO33INCFG (Bit 4) */ +#define GPIO_CFGE_GPIO33INCFG_Msk (0x10UL) /*!< GPIO CFGE: GPIO33INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO32INTD_Pos (3UL) /*!< GPIO CFGE: GPIO32INTD (Bit 3) */ +#define GPIO_CFGE_GPIO32INTD_Msk (0x8UL) /*!< GPIO CFGE: GPIO32INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGE_GPIO32OUTCFG_Pos (1UL) /*!< GPIO CFGE: GPIO32OUTCFG (Bit 1) */ +#define GPIO_CFGE_GPIO32OUTCFG_Msk (0x6UL) /*!< GPIO CFGE: GPIO32OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGE_GPIO32INCFG_Pos (0UL) /*!< GPIO CFGE: GPIO32INCFG (Bit 0) */ +#define GPIO_CFGE_GPIO32INCFG_Msk (0x1UL) /*!< GPIO CFGE: GPIO32INCFG (Bitfield-Mask: 0x01) */ +/* ========================================================= CFGF ========================================================== */ +#define GPIO_CFGF_GPIO47INTD_Pos (31UL) /*!< GPIO CFGF: GPIO47INTD (Bit 31) */ +#define GPIO_CFGF_GPIO47INTD_Msk (0x80000000UL) /*!< GPIO CFGF: GPIO47INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO47OUTCFG_Pos (29UL) /*!< GPIO CFGF: GPIO47OUTCFG (Bit 29) */ +#define GPIO_CFGF_GPIO47OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGF: GPIO47OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGF_GPIO47INCFG_Pos (28UL) /*!< GPIO CFGF: GPIO47INCFG (Bit 28) */ +#define GPIO_CFGF_GPIO47INCFG_Msk (0x10000000UL) /*!< GPIO CFGF: GPIO47INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO46INTD_Pos (27UL) /*!< GPIO CFGF: GPIO46INTD (Bit 27) */ +#define GPIO_CFGF_GPIO46INTD_Msk (0x8000000UL) /*!< GPIO CFGF: GPIO46INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO46OUTCFG_Pos (25UL) /*!< GPIO CFGF: GPIO46OUTCFG (Bit 25) */ +#define GPIO_CFGF_GPIO46OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGF: GPIO46OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGF_GPIO46INCFG_Pos (24UL) /*!< GPIO CFGF: GPIO46INCFG (Bit 24) */ +#define GPIO_CFGF_GPIO46INCFG_Msk (0x1000000UL) /*!< GPIO CFGF: GPIO46INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO45INTD_Pos (23UL) /*!< GPIO CFGF: GPIO45INTD (Bit 23) */ +#define GPIO_CFGF_GPIO45INTD_Msk (0x800000UL) /*!< GPIO CFGF: GPIO45INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO45OUTCFG_Pos (21UL) /*!< GPIO CFGF: GPIO45OUTCFG (Bit 21) */ +#define GPIO_CFGF_GPIO45OUTCFG_Msk (0x600000UL) /*!< GPIO CFGF: GPIO45OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGF_GPIO45INCFG_Pos (20UL) /*!< GPIO CFGF: GPIO45INCFG (Bit 20) */ +#define GPIO_CFGF_GPIO45INCFG_Msk (0x100000UL) /*!< GPIO CFGF: GPIO45INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO44INTD_Pos (19UL) /*!< GPIO CFGF: GPIO44INTD (Bit 19) */ +#define GPIO_CFGF_GPIO44INTD_Msk (0x80000UL) /*!< GPIO CFGF: GPIO44INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO44OUTCFG_Pos (17UL) /*!< GPIO CFGF: GPIO44OUTCFG (Bit 17) */ +#define GPIO_CFGF_GPIO44OUTCFG_Msk (0x60000UL) /*!< GPIO CFGF: GPIO44OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGF_GPIO44INCFG_Pos (16UL) /*!< GPIO CFGF: GPIO44INCFG (Bit 16) */ +#define GPIO_CFGF_GPIO44INCFG_Msk (0x10000UL) /*!< GPIO CFGF: GPIO44INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO43INTD_Pos (15UL) /*!< GPIO CFGF: GPIO43INTD (Bit 15) */ +#define GPIO_CFGF_GPIO43INTD_Msk (0x8000UL) /*!< GPIO CFGF: GPIO43INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO43OUTCFG_Pos (13UL) /*!< GPIO CFGF: GPIO43OUTCFG (Bit 13) */ +#define GPIO_CFGF_GPIO43OUTCFG_Msk (0x6000UL) /*!< GPIO CFGF: GPIO43OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGF_GPIO43INCFG_Pos (12UL) /*!< GPIO CFGF: GPIO43INCFG (Bit 12) */ +#define GPIO_CFGF_GPIO43INCFG_Msk (0x1000UL) /*!< GPIO CFGF: GPIO43INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO42INTD_Pos (11UL) /*!< GPIO CFGF: GPIO42INTD (Bit 11) */ +#define GPIO_CFGF_GPIO42INTD_Msk (0x800UL) /*!< GPIO CFGF: GPIO42INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO42OUTCFG_Pos (9UL) /*!< GPIO CFGF: GPIO42OUTCFG (Bit 9) */ +#define GPIO_CFGF_GPIO42OUTCFG_Msk (0x600UL) /*!< GPIO CFGF: GPIO42OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGF_GPIO42INCFG_Pos (8UL) /*!< GPIO CFGF: GPIO42INCFG (Bit 8) */ +#define GPIO_CFGF_GPIO42INCFG_Msk (0x100UL) /*!< GPIO CFGF: GPIO42INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO41INTD_Pos (7UL) /*!< GPIO CFGF: GPIO41INTD (Bit 7) */ +#define GPIO_CFGF_GPIO41INTD_Msk (0x80UL) /*!< GPIO CFGF: GPIO41INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO41OUTCFG_Pos (5UL) /*!< GPIO CFGF: GPIO41OUTCFG (Bit 5) */ +#define GPIO_CFGF_GPIO41OUTCFG_Msk (0x60UL) /*!< GPIO CFGF: GPIO41OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGF_GPIO41INCFG_Pos (4UL) /*!< GPIO CFGF: GPIO41INCFG (Bit 4) */ +#define GPIO_CFGF_GPIO41INCFG_Msk (0x10UL) /*!< GPIO CFGF: GPIO41INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO40INTD_Pos (3UL) /*!< GPIO CFGF: GPIO40INTD (Bit 3) */ +#define GPIO_CFGF_GPIO40INTD_Msk (0x8UL) /*!< GPIO CFGF: GPIO40INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGF_GPIO40OUTCFG_Pos (1UL) /*!< GPIO CFGF: GPIO40OUTCFG (Bit 1) */ +#define GPIO_CFGF_GPIO40OUTCFG_Msk (0x6UL) /*!< GPIO CFGF: GPIO40OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGF_GPIO40INCFG_Pos (0UL) /*!< GPIO CFGF: GPIO40INCFG (Bit 0) */ +#define GPIO_CFGF_GPIO40INCFG_Msk (0x1UL) /*!< GPIO CFGF: GPIO40INCFG (Bitfield-Mask: 0x01) */ +/* ========================================================= CFGG ========================================================== */ +#define GPIO_CFGG_GPIO49INTD_Pos (7UL) /*!< GPIO CFGG: GPIO49INTD (Bit 7) */ +#define GPIO_CFGG_GPIO49INTD_Msk (0x80UL) /*!< GPIO CFGG: GPIO49INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGG_GPIO49OUTCFG_Pos (5UL) /*!< GPIO CFGG: GPIO49OUTCFG (Bit 5) */ +#define GPIO_CFGG_GPIO49OUTCFG_Msk (0x60UL) /*!< GPIO CFGG: GPIO49OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGG_GPIO49INCFG_Pos (4UL) /*!< GPIO CFGG: GPIO49INCFG (Bit 4) */ +#define GPIO_CFGG_GPIO49INCFG_Msk (0x10UL) /*!< GPIO CFGG: GPIO49INCFG (Bitfield-Mask: 0x01) */ +#define GPIO_CFGG_GPIO48INTD_Pos (3UL) /*!< GPIO CFGG: GPIO48INTD (Bit 3) */ +#define GPIO_CFGG_GPIO48INTD_Msk (0x8UL) /*!< GPIO CFGG: GPIO48INTD (Bitfield-Mask: 0x01) */ +#define GPIO_CFGG_GPIO48OUTCFG_Pos (1UL) /*!< GPIO CFGG: GPIO48OUTCFG (Bit 1) */ +#define GPIO_CFGG_GPIO48OUTCFG_Msk (0x6UL) /*!< GPIO CFGG: GPIO48OUTCFG (Bitfield-Mask: 0x03) */ +#define GPIO_CFGG_GPIO48INCFG_Pos (0UL) /*!< GPIO CFGG: GPIO48INCFG (Bit 0) */ +#define GPIO_CFGG_GPIO48INCFG_Msk (0x1UL) /*!< GPIO CFGG: GPIO48INCFG (Bitfield-Mask: 0x01) */ +/* ======================================================== PADKEY ========================================================= */ +#define GPIO_PADKEY_PADKEY_Pos (0UL) /*!< GPIO PADKEY: PADKEY (Bit 0) */ +#define GPIO_PADKEY_PADKEY_Msk (0xffffffffUL) /*!< GPIO PADKEY: PADKEY (Bitfield-Mask: 0xffffffff) */ +/* ========================================================== RDA ========================================================== */ +#define GPIO_RDA_RDA_Pos (0UL) /*!< GPIO RDA: RDA (Bit 0) */ +#define GPIO_RDA_RDA_Msk (0xffffffffUL) /*!< GPIO RDA: RDA (Bitfield-Mask: 0xffffffff) */ +/* ========================================================== RDB ========================================================== */ +#define GPIO_RDB_RDB_Pos (0UL) /*!< GPIO RDB: RDB (Bit 0) */ +#define GPIO_RDB_RDB_Msk (0x3ffffUL) /*!< GPIO RDB: RDB (Bitfield-Mask: 0x3ffff) */ +/* ========================================================== WTA ========================================================== */ +#define GPIO_WTA_WTA_Pos (0UL) /*!< GPIO WTA: WTA (Bit 0) */ +#define GPIO_WTA_WTA_Msk (0xffffffffUL) /*!< GPIO WTA: WTA (Bitfield-Mask: 0xffffffff) */ +/* ========================================================== WTB ========================================================== */ +#define GPIO_WTB_WTB_Pos (0UL) /*!< GPIO WTB: WTB (Bit 0) */ +#define GPIO_WTB_WTB_Msk (0x3ffffUL) /*!< GPIO WTB: WTB (Bitfield-Mask: 0x3ffff) */ +/* ========================================================= WTSA ========================================================== */ +#define GPIO_WTSA_WTSA_Pos (0UL) /*!< GPIO WTSA: WTSA (Bit 0) */ +#define GPIO_WTSA_WTSA_Msk (0xffffffffUL) /*!< GPIO WTSA: WTSA (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= WTSB ========================================================== */ +#define GPIO_WTSB_WTSB_Pos (0UL) /*!< GPIO WTSB: WTSB (Bit 0) */ +#define GPIO_WTSB_WTSB_Msk (0x3ffffUL) /*!< GPIO WTSB: WTSB (Bitfield-Mask: 0x3ffff) */ +/* ========================================================= WTCA ========================================================== */ +#define GPIO_WTCA_WTCA_Pos (0UL) /*!< GPIO WTCA: WTCA (Bit 0) */ +#define GPIO_WTCA_WTCA_Msk (0xffffffffUL) /*!< GPIO WTCA: WTCA (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= WTCB ========================================================== */ +#define GPIO_WTCB_WTCB_Pos (0UL) /*!< GPIO WTCB: WTCB (Bit 0) */ +#define GPIO_WTCB_WTCB_Msk (0x3ffffUL) /*!< GPIO WTCB: WTCB (Bitfield-Mask: 0x3ffff) */ +/* ========================================================== ENA ========================================================== */ +#define GPIO_ENA_ENA_Pos (0UL) /*!< GPIO ENA: ENA (Bit 0) */ +#define GPIO_ENA_ENA_Msk (0xffffffffUL) /*!< GPIO ENA: ENA (Bitfield-Mask: 0xffffffff) */ +/* ========================================================== ENB ========================================================== */ +#define GPIO_ENB_ENB_Pos (0UL) /*!< GPIO ENB: ENB (Bit 0) */ +#define GPIO_ENB_ENB_Msk (0x3ffffUL) /*!< GPIO ENB: ENB (Bitfield-Mask: 0x3ffff) */ +/* ========================================================= ENSA ========================================================== */ +#define GPIO_ENSA_ENSA_Pos (0UL) /*!< GPIO ENSA: ENSA (Bit 0) */ +#define GPIO_ENSA_ENSA_Msk (0xffffffffUL) /*!< GPIO ENSA: ENSA (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= ENSB ========================================================== */ +#define GPIO_ENSB_ENSB_Pos (0UL) /*!< GPIO ENSB: ENSB (Bit 0) */ +#define GPIO_ENSB_ENSB_Msk (0x3ffffUL) /*!< GPIO ENSB: ENSB (Bitfield-Mask: 0x3ffff) */ +/* ========================================================= ENCA ========================================================== */ +#define GPIO_ENCA_ENCA_Pos (0UL) /*!< GPIO ENCA: ENCA (Bit 0) */ +#define GPIO_ENCA_ENCA_Msk (0xffffffffUL) /*!< GPIO ENCA: ENCA (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= ENCB ========================================================== */ +#define GPIO_ENCB_ENCB_Pos (0UL) /*!< GPIO ENCB: ENCB (Bit 0) */ +#define GPIO_ENCB_ENCB_Msk (0x3ffffUL) /*!< GPIO ENCB: ENCB (Bitfield-Mask: 0x3ffff) */ +/* ======================================================== STMRCAP ======================================================== */ +#define GPIO_STMRCAP_STPOL3_Pos (30UL) /*!< GPIO STMRCAP: STPOL3 (Bit 30) */ +#define GPIO_STMRCAP_STPOL3_Msk (0x40000000UL) /*!< GPIO STMRCAP: STPOL3 (Bitfield-Mask: 0x01) */ +#define GPIO_STMRCAP_STSEL3_Pos (24UL) /*!< GPIO STMRCAP: STSEL3 (Bit 24) */ +#define GPIO_STMRCAP_STSEL3_Msk (0x3f000000UL) /*!< GPIO STMRCAP: STSEL3 (Bitfield-Mask: 0x3f) */ +#define GPIO_STMRCAP_STPOL2_Pos (22UL) /*!< GPIO STMRCAP: STPOL2 (Bit 22) */ +#define GPIO_STMRCAP_STPOL2_Msk (0x400000UL) /*!< GPIO STMRCAP: STPOL2 (Bitfield-Mask: 0x01) */ +#define GPIO_STMRCAP_STSEL2_Pos (16UL) /*!< GPIO STMRCAP: STSEL2 (Bit 16) */ +#define GPIO_STMRCAP_STSEL2_Msk (0x3f0000UL) /*!< GPIO STMRCAP: STSEL2 (Bitfield-Mask: 0x3f) */ +#define GPIO_STMRCAP_STPOL1_Pos (14UL) /*!< GPIO STMRCAP: STPOL1 (Bit 14) */ +#define GPIO_STMRCAP_STPOL1_Msk (0x4000UL) /*!< GPIO STMRCAP: STPOL1 (Bitfield-Mask: 0x01) */ +#define GPIO_STMRCAP_STSEL1_Pos (8UL) /*!< GPIO STMRCAP: STSEL1 (Bit 8) */ +#define GPIO_STMRCAP_STSEL1_Msk (0x3f00UL) /*!< GPIO STMRCAP: STSEL1 (Bitfield-Mask: 0x3f) */ +#define GPIO_STMRCAP_STPOL0_Pos (6UL) /*!< GPIO STMRCAP: STPOL0 (Bit 6) */ +#define GPIO_STMRCAP_STPOL0_Msk (0x40UL) /*!< GPIO STMRCAP: STPOL0 (Bitfield-Mask: 0x01) */ +#define GPIO_STMRCAP_STSEL0_Pos (0UL) /*!< GPIO STMRCAP: STSEL0 (Bit 0) */ +#define GPIO_STMRCAP_STSEL0_Msk (0x3fUL) /*!< GPIO STMRCAP: STSEL0 (Bitfield-Mask: 0x3f) */ +/* ======================================================== IOM0IRQ ======================================================== */ +#define GPIO_IOM0IRQ_IOM0IRQ_Pos (0UL) /*!< GPIO IOM0IRQ: IOM0IRQ (Bit 0) */ +#define GPIO_IOM0IRQ_IOM0IRQ_Msk (0x3fUL) /*!< GPIO IOM0IRQ: IOM0IRQ (Bitfield-Mask: 0x3f) */ +/* ======================================================== IOM1IRQ ======================================================== */ +#define GPIO_IOM1IRQ_IOM1IRQ_Pos (0UL) /*!< GPIO IOM1IRQ: IOM1IRQ (Bit 0) */ +#define GPIO_IOM1IRQ_IOM1IRQ_Msk (0x3fUL) /*!< GPIO IOM1IRQ: IOM1IRQ (Bitfield-Mask: 0x3f) */ +/* ======================================================== IOM2IRQ ======================================================== */ +#define GPIO_IOM2IRQ_IOM2IRQ_Pos (0UL) /*!< GPIO IOM2IRQ: IOM2IRQ (Bit 0) */ +#define GPIO_IOM2IRQ_IOM2IRQ_Msk (0x3fUL) /*!< GPIO IOM2IRQ: IOM2IRQ (Bitfield-Mask: 0x3f) */ +/* ======================================================== IOM3IRQ ======================================================== */ +#define GPIO_IOM3IRQ_IOM3IRQ_Pos (0UL) /*!< GPIO IOM3IRQ: IOM3IRQ (Bit 0) */ +#define GPIO_IOM3IRQ_IOM3IRQ_Msk (0x3fUL) /*!< GPIO IOM3IRQ: IOM3IRQ (Bitfield-Mask: 0x3f) */ +/* ======================================================== IOM4IRQ ======================================================== */ +#define GPIO_IOM4IRQ_IOM4IRQ_Pos (0UL) /*!< GPIO IOM4IRQ: IOM4IRQ (Bit 0) */ +#define GPIO_IOM4IRQ_IOM4IRQ_Msk (0x3fUL) /*!< GPIO IOM4IRQ: IOM4IRQ (Bitfield-Mask: 0x3f) */ +/* ======================================================== IOM5IRQ ======================================================== */ +#define GPIO_IOM5IRQ_IOM5IRQ_Pos (0UL) /*!< GPIO IOM5IRQ: IOM5IRQ (Bit 0) */ +#define GPIO_IOM5IRQ_IOM5IRQ_Msk (0x3fUL) /*!< GPIO IOM5IRQ: IOM5IRQ (Bitfield-Mask: 0x3f) */ +/* ======================================================= BLEIFIRQ ======================================================== */ +#define GPIO_BLEIFIRQ_BLEIFIRQ_Pos (0UL) /*!< GPIO BLEIFIRQ: BLEIFIRQ (Bit 0) */ +#define GPIO_BLEIFIRQ_BLEIFIRQ_Msk (0x3fUL) /*!< GPIO BLEIFIRQ: BLEIFIRQ (Bitfield-Mask: 0x3f) */ +/* ======================================================== GPIOOBS ======================================================== */ +#define GPIO_GPIOOBS_OBS_DATA_Pos (0UL) /*!< GPIO GPIOOBS: OBS_DATA (Bit 0) */ +#define GPIO_GPIOOBS_OBS_DATA_Msk (0xffffUL) /*!< GPIO GPIOOBS: OBS_DATA (Bitfield-Mask: 0xffff) */ +/* ====================================================== ALTPADCFGA ======================================================= */ +#define GPIO_ALTPADCFGA_PAD3_SR_Pos (28UL) /*!< GPIO ALTPADCFGA: PAD3_SR (Bit 28) */ +#define GPIO_ALTPADCFGA_PAD3_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGA: PAD3_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGA_PAD3_DS1_Pos (24UL) /*!< GPIO ALTPADCFGA: PAD3_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGA_PAD3_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGA: PAD3_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGA_PAD2_SR_Pos (20UL) /*!< GPIO ALTPADCFGA: PAD2_SR (Bit 20) */ +#define GPIO_ALTPADCFGA_PAD2_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGA: PAD2_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGA_PAD2_DS1_Pos (16UL) /*!< GPIO ALTPADCFGA: PAD2_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGA_PAD2_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGA: PAD2_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGA_PAD1_SR_Pos (12UL) /*!< GPIO ALTPADCFGA: PAD1_SR (Bit 12) */ +#define GPIO_ALTPADCFGA_PAD1_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGA: PAD1_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGA_PAD1_DS1_Pos (8UL) /*!< GPIO ALTPADCFGA: PAD1_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGA_PAD1_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGA: PAD1_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGA_PAD0_SR_Pos (4UL) /*!< GPIO ALTPADCFGA: PAD0_SR (Bit 4) */ +#define GPIO_ALTPADCFGA_PAD0_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGA: PAD0_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGA_PAD0_DS1_Pos (0UL) /*!< GPIO ALTPADCFGA: PAD0_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGA_PAD0_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGA: PAD0_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGB ======================================================= */ +#define GPIO_ALTPADCFGB_PAD7_SR_Pos (28UL) /*!< GPIO ALTPADCFGB: PAD7_SR (Bit 28) */ +#define GPIO_ALTPADCFGB_PAD7_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGB: PAD7_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGB_PAD7_DS1_Pos (24UL) /*!< GPIO ALTPADCFGB: PAD7_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGB_PAD7_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGB: PAD7_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGB_PAD6_SR_Pos (20UL) /*!< GPIO ALTPADCFGB: PAD6_SR (Bit 20) */ +#define GPIO_ALTPADCFGB_PAD6_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGB: PAD6_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGB_PAD6_DS1_Pos (16UL) /*!< GPIO ALTPADCFGB: PAD6_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGB_PAD6_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGB: PAD6_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGB_PAD5_SR_Pos (12UL) /*!< GPIO ALTPADCFGB: PAD5_SR (Bit 12) */ +#define GPIO_ALTPADCFGB_PAD5_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGB: PAD5_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGB_PAD5_DS1_Pos (8UL) /*!< GPIO ALTPADCFGB: PAD5_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGB_PAD5_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGB: PAD5_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGB_PAD4_SR_Pos (4UL) /*!< GPIO ALTPADCFGB: PAD4_SR (Bit 4) */ +#define GPIO_ALTPADCFGB_PAD4_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGB: PAD4_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGB_PAD4_DS1_Pos (0UL) /*!< GPIO ALTPADCFGB: PAD4_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGB_PAD4_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGB: PAD4_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGC ======================================================= */ +#define GPIO_ALTPADCFGC_PAD11_SR_Pos (28UL) /*!< GPIO ALTPADCFGC: PAD11_SR (Bit 28) */ +#define GPIO_ALTPADCFGC_PAD11_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGC: PAD11_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGC_PAD11_DS1_Pos (24UL) /*!< GPIO ALTPADCFGC: PAD11_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGC_PAD11_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGC: PAD11_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGC_PAD10_SR_Pos (20UL) /*!< GPIO ALTPADCFGC: PAD10_SR (Bit 20) */ +#define GPIO_ALTPADCFGC_PAD10_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGC: PAD10_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGC_PAD10_DS1_Pos (16UL) /*!< GPIO ALTPADCFGC: PAD10_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGC_PAD10_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGC: PAD10_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGC_PAD9_SR_Pos (12UL) /*!< GPIO ALTPADCFGC: PAD9_SR (Bit 12) */ +#define GPIO_ALTPADCFGC_PAD9_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGC: PAD9_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGC_PAD9_DS1_Pos (8UL) /*!< GPIO ALTPADCFGC: PAD9_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGC_PAD9_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGC: PAD9_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGC_PAD8_SR_Pos (4UL) /*!< GPIO ALTPADCFGC: PAD8_SR (Bit 4) */ +#define GPIO_ALTPADCFGC_PAD8_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGC: PAD8_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGC_PAD8_DS1_Pos (0UL) /*!< GPIO ALTPADCFGC: PAD8_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGC_PAD8_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGC: PAD8_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGD ======================================================= */ +#define GPIO_ALTPADCFGD_PAD15_SR_Pos (28UL) /*!< GPIO ALTPADCFGD: PAD15_SR (Bit 28) */ +#define GPIO_ALTPADCFGD_PAD15_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGD: PAD15_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGD_PAD15_DS1_Pos (24UL) /*!< GPIO ALTPADCFGD: PAD15_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGD_PAD15_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGD: PAD15_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGD_PAD14_SR_Pos (20UL) /*!< GPIO ALTPADCFGD: PAD14_SR (Bit 20) */ +#define GPIO_ALTPADCFGD_PAD14_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGD: PAD14_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGD_PAD14_DS1_Pos (16UL) /*!< GPIO ALTPADCFGD: PAD14_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGD_PAD14_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGD: PAD14_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGD_PAD13_SR_Pos (12UL) /*!< GPIO ALTPADCFGD: PAD13_SR (Bit 12) */ +#define GPIO_ALTPADCFGD_PAD13_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGD: PAD13_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGD_PAD13_DS1_Pos (8UL) /*!< GPIO ALTPADCFGD: PAD13_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGD_PAD13_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGD: PAD13_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGD_PAD12_SR_Pos (4UL) /*!< GPIO ALTPADCFGD: PAD12_SR (Bit 4) */ +#define GPIO_ALTPADCFGD_PAD12_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGD: PAD12_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGD_PAD12_DS1_Pos (0UL) /*!< GPIO ALTPADCFGD: PAD12_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGD_PAD12_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGD: PAD12_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGE ======================================================= */ +#define GPIO_ALTPADCFGE_PAD19_SR_Pos (28UL) /*!< GPIO ALTPADCFGE: PAD19_SR (Bit 28) */ +#define GPIO_ALTPADCFGE_PAD19_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGE: PAD19_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGE_PAD19_DS1_Pos (24UL) /*!< GPIO ALTPADCFGE: PAD19_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGE_PAD19_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGE: PAD19_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGE_PAD18_SR_Pos (20UL) /*!< GPIO ALTPADCFGE: PAD18_SR (Bit 20) */ +#define GPIO_ALTPADCFGE_PAD18_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGE: PAD18_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGE_PAD18_DS1_Pos (16UL) /*!< GPIO ALTPADCFGE: PAD18_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGE_PAD18_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGE: PAD18_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGE_PAD17_SR_Pos (12UL) /*!< GPIO ALTPADCFGE: PAD17_SR (Bit 12) */ +#define GPIO_ALTPADCFGE_PAD17_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGE: PAD17_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGE_PAD17_DS1_Pos (8UL) /*!< GPIO ALTPADCFGE: PAD17_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGE_PAD17_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGE: PAD17_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGE_PAD16_SR_Pos (4UL) /*!< GPIO ALTPADCFGE: PAD16_SR (Bit 4) */ +#define GPIO_ALTPADCFGE_PAD16_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGE: PAD16_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGE_PAD16_DS1_Pos (0UL) /*!< GPIO ALTPADCFGE: PAD16_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGE_PAD16_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGE: PAD16_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGF ======================================================= */ +#define GPIO_ALTPADCFGF_PAD23_SR_Pos (28UL) /*!< GPIO ALTPADCFGF: PAD23_SR (Bit 28) */ +#define GPIO_ALTPADCFGF_PAD23_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGF: PAD23_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGF_PAD23_DS1_Pos (24UL) /*!< GPIO ALTPADCFGF: PAD23_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGF_PAD23_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGF: PAD23_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGF_PAD22_SR_Pos (20UL) /*!< GPIO ALTPADCFGF: PAD22_SR (Bit 20) */ +#define GPIO_ALTPADCFGF_PAD22_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGF: PAD22_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGF_PAD22_DS1_Pos (16UL) /*!< GPIO ALTPADCFGF: PAD22_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGF_PAD22_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGF: PAD22_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGF_PAD21_SR_Pos (12UL) /*!< GPIO ALTPADCFGF: PAD21_SR (Bit 12) */ +#define GPIO_ALTPADCFGF_PAD21_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGF: PAD21_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGF_PAD21_DS1_Pos (8UL) /*!< GPIO ALTPADCFGF: PAD21_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGF_PAD21_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGF: PAD21_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGF_PAD20_SR_Pos (4UL) /*!< GPIO ALTPADCFGF: PAD20_SR (Bit 4) */ +#define GPIO_ALTPADCFGF_PAD20_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGF: PAD20_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGF_PAD20_DS1_Pos (0UL) /*!< GPIO ALTPADCFGF: PAD20_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGF_PAD20_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGF: PAD20_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGG ======================================================= */ +#define GPIO_ALTPADCFGG_PAD27_SR_Pos (28UL) /*!< GPIO ALTPADCFGG: PAD27_SR (Bit 28) */ +#define GPIO_ALTPADCFGG_PAD27_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGG: PAD27_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGG_PAD27_DS1_Pos (24UL) /*!< GPIO ALTPADCFGG: PAD27_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGG_PAD27_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGG: PAD27_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGG_PAD26_SR_Pos (20UL) /*!< GPIO ALTPADCFGG: PAD26_SR (Bit 20) */ +#define GPIO_ALTPADCFGG_PAD26_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGG: PAD26_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGG_PAD26_DS1_Pos (16UL) /*!< GPIO ALTPADCFGG: PAD26_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGG_PAD26_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGG: PAD26_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGG_PAD25_SR_Pos (12UL) /*!< GPIO ALTPADCFGG: PAD25_SR (Bit 12) */ +#define GPIO_ALTPADCFGG_PAD25_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGG: PAD25_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGG_PAD25_DS1_Pos (8UL) /*!< GPIO ALTPADCFGG: PAD25_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGG_PAD25_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGG: PAD25_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGG_PAD24_SR_Pos (4UL) /*!< GPIO ALTPADCFGG: PAD24_SR (Bit 4) */ +#define GPIO_ALTPADCFGG_PAD24_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGG: PAD24_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGG_PAD24_DS1_Pos (0UL) /*!< GPIO ALTPADCFGG: PAD24_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGG_PAD24_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGG: PAD24_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGH ======================================================= */ +#define GPIO_ALTPADCFGH_PAD31_SR_Pos (28UL) /*!< GPIO ALTPADCFGH: PAD31_SR (Bit 28) */ +#define GPIO_ALTPADCFGH_PAD31_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGH: PAD31_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGH_PAD31_DS1_Pos (24UL) /*!< GPIO ALTPADCFGH: PAD31_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGH_PAD31_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGH: PAD31_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGH_PAD30_SR_Pos (20UL) /*!< GPIO ALTPADCFGH: PAD30_SR (Bit 20) */ +#define GPIO_ALTPADCFGH_PAD30_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGH: PAD30_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGH_PAD30_DS1_Pos (16UL) /*!< GPIO ALTPADCFGH: PAD30_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGH_PAD30_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGH: PAD30_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGH_PAD29_SR_Pos (12UL) /*!< GPIO ALTPADCFGH: PAD29_SR (Bit 12) */ +#define GPIO_ALTPADCFGH_PAD29_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGH: PAD29_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGH_PAD29_DS1_Pos (8UL) /*!< GPIO ALTPADCFGH: PAD29_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGH_PAD29_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGH: PAD29_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGH_PAD28_SR_Pos (4UL) /*!< GPIO ALTPADCFGH: PAD28_SR (Bit 4) */ +#define GPIO_ALTPADCFGH_PAD28_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGH: PAD28_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGH_PAD28_DS1_Pos (0UL) /*!< GPIO ALTPADCFGH: PAD28_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGH_PAD28_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGH: PAD28_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGI ======================================================= */ +#define GPIO_ALTPADCFGI_PAD35_SR_Pos (28UL) /*!< GPIO ALTPADCFGI: PAD35_SR (Bit 28) */ +#define GPIO_ALTPADCFGI_PAD35_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGI: PAD35_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGI_PAD35_DS1_Pos (24UL) /*!< GPIO ALTPADCFGI: PAD35_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGI_PAD35_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGI: PAD35_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGI_PAD34_SR_Pos (20UL) /*!< GPIO ALTPADCFGI: PAD34_SR (Bit 20) */ +#define GPIO_ALTPADCFGI_PAD34_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGI: PAD34_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGI_PAD34_DS1_Pos (16UL) /*!< GPIO ALTPADCFGI: PAD34_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGI_PAD34_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGI: PAD34_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGI_PAD33_SR_Pos (12UL) /*!< GPIO ALTPADCFGI: PAD33_SR (Bit 12) */ +#define GPIO_ALTPADCFGI_PAD33_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGI: PAD33_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGI_PAD33_DS1_Pos (8UL) /*!< GPIO ALTPADCFGI: PAD33_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGI_PAD33_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGI: PAD33_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGI_PAD32_SR_Pos (4UL) /*!< GPIO ALTPADCFGI: PAD32_SR (Bit 4) */ +#define GPIO_ALTPADCFGI_PAD32_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGI: PAD32_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGI_PAD32_DS1_Pos (0UL) /*!< GPIO ALTPADCFGI: PAD32_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGI_PAD32_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGI: PAD32_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGJ ======================================================= */ +#define GPIO_ALTPADCFGJ_PAD39_SR_Pos (28UL) /*!< GPIO ALTPADCFGJ: PAD39_SR (Bit 28) */ +#define GPIO_ALTPADCFGJ_PAD39_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGJ: PAD39_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGJ_PAD39_DS1_Pos (24UL) /*!< GPIO ALTPADCFGJ: PAD39_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGJ_PAD39_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGJ: PAD39_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGJ_PAD38_SR_Pos (20UL) /*!< GPIO ALTPADCFGJ: PAD38_SR (Bit 20) */ +#define GPIO_ALTPADCFGJ_PAD38_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGJ: PAD38_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGJ_PAD38_DS1_Pos (16UL) /*!< GPIO ALTPADCFGJ: PAD38_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGJ_PAD38_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGJ: PAD38_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGJ_PAD37_SR_Pos (12UL) /*!< GPIO ALTPADCFGJ: PAD37_SR (Bit 12) */ +#define GPIO_ALTPADCFGJ_PAD37_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGJ: PAD37_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGJ_PAD37_DS1_Pos (8UL) /*!< GPIO ALTPADCFGJ: PAD37_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGJ_PAD37_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGJ: PAD37_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGJ_PAD36_SR_Pos (4UL) /*!< GPIO ALTPADCFGJ: PAD36_SR (Bit 4) */ +#define GPIO_ALTPADCFGJ_PAD36_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGJ: PAD36_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGJ_PAD36_DS1_Pos (0UL) /*!< GPIO ALTPADCFGJ: PAD36_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGJ_PAD36_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGJ: PAD36_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGK ======================================================= */ +#define GPIO_ALTPADCFGK_PAD43_SR_Pos (28UL) /*!< GPIO ALTPADCFGK: PAD43_SR (Bit 28) */ +#define GPIO_ALTPADCFGK_PAD43_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGK: PAD43_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGK_PAD43_DS1_Pos (24UL) /*!< GPIO ALTPADCFGK: PAD43_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGK_PAD43_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGK: PAD43_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGK_PAD42_SR_Pos (20UL) /*!< GPIO ALTPADCFGK: PAD42_SR (Bit 20) */ +#define GPIO_ALTPADCFGK_PAD42_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGK: PAD42_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGK_PAD42_DS1_Pos (16UL) /*!< GPIO ALTPADCFGK: PAD42_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGK_PAD42_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGK: PAD42_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGK_PAD41_SR_Pos (12UL) /*!< GPIO ALTPADCFGK: PAD41_SR (Bit 12) */ +#define GPIO_ALTPADCFGK_PAD41_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGK: PAD41_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGK_PAD41_DS1_Pos (8UL) /*!< GPIO ALTPADCFGK: PAD41_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGK_PAD41_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGK: PAD41_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGK_PAD40_SR_Pos (4UL) /*!< GPIO ALTPADCFGK: PAD40_SR (Bit 4) */ +#define GPIO_ALTPADCFGK_PAD40_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGK: PAD40_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGK_PAD40_DS1_Pos (0UL) /*!< GPIO ALTPADCFGK: PAD40_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGK_PAD40_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGK: PAD40_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGL ======================================================= */ +#define GPIO_ALTPADCFGL_PAD47_SR_Pos (28UL) /*!< GPIO ALTPADCFGL: PAD47_SR (Bit 28) */ +#define GPIO_ALTPADCFGL_PAD47_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGL: PAD47_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGL_PAD47_DS1_Pos (24UL) /*!< GPIO ALTPADCFGL: PAD47_DS1 (Bit 24) */ +#define GPIO_ALTPADCFGL_PAD47_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGL: PAD47_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGL_PAD46_SR_Pos (20UL) /*!< GPIO ALTPADCFGL: PAD46_SR (Bit 20) */ +#define GPIO_ALTPADCFGL_PAD46_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGL: PAD46_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGL_PAD46_DS1_Pos (16UL) /*!< GPIO ALTPADCFGL: PAD46_DS1 (Bit 16) */ +#define GPIO_ALTPADCFGL_PAD46_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGL: PAD46_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGL_PAD45_SR_Pos (12UL) /*!< GPIO ALTPADCFGL: PAD45_SR (Bit 12) */ +#define GPIO_ALTPADCFGL_PAD45_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGL: PAD45_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGL_PAD45_DS1_Pos (8UL) /*!< GPIO ALTPADCFGL: PAD45_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGL_PAD45_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGL: PAD45_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGL_PAD44_SR_Pos (4UL) /*!< GPIO ALTPADCFGL: PAD44_SR (Bit 4) */ +#define GPIO_ALTPADCFGL_PAD44_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGL: PAD44_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGL_PAD44_DS1_Pos (0UL) /*!< GPIO ALTPADCFGL: PAD44_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGL_PAD44_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGL: PAD44_DS1 (Bitfield-Mask: 0x01) */ +/* ====================================================== ALTPADCFGM ======================================================= */ +#define GPIO_ALTPADCFGM_PAD49_SR_Pos (12UL) /*!< GPIO ALTPADCFGM: PAD49_SR (Bit 12) */ +#define GPIO_ALTPADCFGM_PAD49_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGM: PAD49_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGM_PAD49_DS1_Pos (8UL) /*!< GPIO ALTPADCFGM: PAD49_DS1 (Bit 8) */ +#define GPIO_ALTPADCFGM_PAD49_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGM: PAD49_DS1 (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGM_PAD48_SR_Pos (4UL) /*!< GPIO ALTPADCFGM: PAD48_SR (Bit 4) */ +#define GPIO_ALTPADCFGM_PAD48_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGM: PAD48_SR (Bitfield-Mask: 0x01) */ +#define GPIO_ALTPADCFGM_PAD48_DS1_Pos (0UL) /*!< GPIO ALTPADCFGM: PAD48_DS1 (Bit 0) */ +#define GPIO_ALTPADCFGM_PAD48_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGM: PAD48_DS1 (Bitfield-Mask: 0x01) */ +/* ========================================================= SCDET ========================================================= */ +#define GPIO_SCDET_SCDET_Pos (0UL) /*!< GPIO SCDET: SCDET (Bit 0) */ +#define GPIO_SCDET_SCDET_Msk (0x3fUL) /*!< GPIO SCDET: SCDET (Bitfield-Mask: 0x3f) */ +/* ======================================================== CTENCFG ======================================================== */ +#define GPIO_CTENCFG_EN31_Pos (31UL) /*!< GPIO CTENCFG: EN31 (Bit 31) */ +#define GPIO_CTENCFG_EN31_Msk (0x80000000UL) /*!< GPIO CTENCFG: EN31 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN30_Pos (30UL) /*!< GPIO CTENCFG: EN30 (Bit 30) */ +#define GPIO_CTENCFG_EN30_Msk (0x40000000UL) /*!< GPIO CTENCFG: EN30 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN29_Pos (29UL) /*!< GPIO CTENCFG: EN29 (Bit 29) */ +#define GPIO_CTENCFG_EN29_Msk (0x20000000UL) /*!< GPIO CTENCFG: EN29 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN28_Pos (28UL) /*!< GPIO CTENCFG: EN28 (Bit 28) */ +#define GPIO_CTENCFG_EN28_Msk (0x10000000UL) /*!< GPIO CTENCFG: EN28 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN27_Pos (27UL) /*!< GPIO CTENCFG: EN27 (Bit 27) */ +#define GPIO_CTENCFG_EN27_Msk (0x8000000UL) /*!< GPIO CTENCFG: EN27 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN26_Pos (26UL) /*!< GPIO CTENCFG: EN26 (Bit 26) */ +#define GPIO_CTENCFG_EN26_Msk (0x4000000UL) /*!< GPIO CTENCFG: EN26 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN25_Pos (25UL) /*!< GPIO CTENCFG: EN25 (Bit 25) */ +#define GPIO_CTENCFG_EN25_Msk (0x2000000UL) /*!< GPIO CTENCFG: EN25 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN24_Pos (24UL) /*!< GPIO CTENCFG: EN24 (Bit 24) */ +#define GPIO_CTENCFG_EN24_Msk (0x1000000UL) /*!< GPIO CTENCFG: EN24 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN23_Pos (23UL) /*!< GPIO CTENCFG: EN23 (Bit 23) */ +#define GPIO_CTENCFG_EN23_Msk (0x800000UL) /*!< GPIO CTENCFG: EN23 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN22_Pos (22UL) /*!< GPIO CTENCFG: EN22 (Bit 22) */ +#define GPIO_CTENCFG_EN22_Msk (0x400000UL) /*!< GPIO CTENCFG: EN22 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN21_Pos (21UL) /*!< GPIO CTENCFG: EN21 (Bit 21) */ +#define GPIO_CTENCFG_EN21_Msk (0x200000UL) /*!< GPIO CTENCFG: EN21 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN20_Pos (20UL) /*!< GPIO CTENCFG: EN20 (Bit 20) */ +#define GPIO_CTENCFG_EN20_Msk (0x100000UL) /*!< GPIO CTENCFG: EN20 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN19_Pos (19UL) /*!< GPIO CTENCFG: EN19 (Bit 19) */ +#define GPIO_CTENCFG_EN19_Msk (0x80000UL) /*!< GPIO CTENCFG: EN19 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN18_Pos (18UL) /*!< GPIO CTENCFG: EN18 (Bit 18) */ +#define GPIO_CTENCFG_EN18_Msk (0x40000UL) /*!< GPIO CTENCFG: EN18 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN17_Pos (17UL) /*!< GPIO CTENCFG: EN17 (Bit 17) */ +#define GPIO_CTENCFG_EN17_Msk (0x20000UL) /*!< GPIO CTENCFG: EN17 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN16_Pos (16UL) /*!< GPIO CTENCFG: EN16 (Bit 16) */ +#define GPIO_CTENCFG_EN16_Msk (0x10000UL) /*!< GPIO CTENCFG: EN16 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN15_Pos (15UL) /*!< GPIO CTENCFG: EN15 (Bit 15) */ +#define GPIO_CTENCFG_EN15_Msk (0x8000UL) /*!< GPIO CTENCFG: EN15 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN14_Pos (14UL) /*!< GPIO CTENCFG: EN14 (Bit 14) */ +#define GPIO_CTENCFG_EN14_Msk (0x4000UL) /*!< GPIO CTENCFG: EN14 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN13_Pos (13UL) /*!< GPIO CTENCFG: EN13 (Bit 13) */ +#define GPIO_CTENCFG_EN13_Msk (0x2000UL) /*!< GPIO CTENCFG: EN13 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN12_Pos (12UL) /*!< GPIO CTENCFG: EN12 (Bit 12) */ +#define GPIO_CTENCFG_EN12_Msk (0x1000UL) /*!< GPIO CTENCFG: EN12 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN11_Pos (11UL) /*!< GPIO CTENCFG: EN11 (Bit 11) */ +#define GPIO_CTENCFG_EN11_Msk (0x800UL) /*!< GPIO CTENCFG: EN11 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN10_Pos (10UL) /*!< GPIO CTENCFG: EN10 (Bit 10) */ +#define GPIO_CTENCFG_EN10_Msk (0x400UL) /*!< GPIO CTENCFG: EN10 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN9_Pos (9UL) /*!< GPIO CTENCFG: EN9 (Bit 9) */ +#define GPIO_CTENCFG_EN9_Msk (0x200UL) /*!< GPIO CTENCFG: EN9 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN8_Pos (8UL) /*!< GPIO CTENCFG: EN8 (Bit 8) */ +#define GPIO_CTENCFG_EN8_Msk (0x100UL) /*!< GPIO CTENCFG: EN8 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN7_Pos (7UL) /*!< GPIO CTENCFG: EN7 (Bit 7) */ +#define GPIO_CTENCFG_EN7_Msk (0x80UL) /*!< GPIO CTENCFG: EN7 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN6_Pos (6UL) /*!< GPIO CTENCFG: EN6 (Bit 6) */ +#define GPIO_CTENCFG_EN6_Msk (0x40UL) /*!< GPIO CTENCFG: EN6 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN5_Pos (5UL) /*!< GPIO CTENCFG: EN5 (Bit 5) */ +#define GPIO_CTENCFG_EN5_Msk (0x20UL) /*!< GPIO CTENCFG: EN5 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN4_Pos (4UL) /*!< GPIO CTENCFG: EN4 (Bit 4) */ +#define GPIO_CTENCFG_EN4_Msk (0x10UL) /*!< GPIO CTENCFG: EN4 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN3_Pos (3UL) /*!< GPIO CTENCFG: EN3 (Bit 3) */ +#define GPIO_CTENCFG_EN3_Msk (0x8UL) /*!< GPIO CTENCFG: EN3 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN2_Pos (2UL) /*!< GPIO CTENCFG: EN2 (Bit 2) */ +#define GPIO_CTENCFG_EN2_Msk (0x4UL) /*!< GPIO CTENCFG: EN2 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN1_Pos (1UL) /*!< GPIO CTENCFG: EN1 (Bit 1) */ +#define GPIO_CTENCFG_EN1_Msk (0x2UL) /*!< GPIO CTENCFG: EN1 (Bitfield-Mask: 0x01) */ +#define GPIO_CTENCFG_EN0_Pos (0UL) /*!< GPIO CTENCFG: EN0 (Bit 0) */ +#define GPIO_CTENCFG_EN0_Msk (0x1UL) /*!< GPIO CTENCFG: EN0 (Bitfield-Mask: 0x01) */ +/* ======================================================== INT0EN ========================================================= */ +#define GPIO_INT0EN_GPIO31_Pos (31UL) /*!< GPIO INT0EN: GPIO31 (Bit 31) */ +#define GPIO_INT0EN_GPIO31_Msk (0x80000000UL) /*!< GPIO INT0EN: GPIO31 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO30_Pos (30UL) /*!< GPIO INT0EN: GPIO30 (Bit 30) */ +#define GPIO_INT0EN_GPIO30_Msk (0x40000000UL) /*!< GPIO INT0EN: GPIO30 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO29_Pos (29UL) /*!< GPIO INT0EN: GPIO29 (Bit 29) */ +#define GPIO_INT0EN_GPIO29_Msk (0x20000000UL) /*!< GPIO INT0EN: GPIO29 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO28_Pos (28UL) /*!< GPIO INT0EN: GPIO28 (Bit 28) */ +#define GPIO_INT0EN_GPIO28_Msk (0x10000000UL) /*!< GPIO INT0EN: GPIO28 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO27_Pos (27UL) /*!< GPIO INT0EN: GPIO27 (Bit 27) */ +#define GPIO_INT0EN_GPIO27_Msk (0x8000000UL) /*!< GPIO INT0EN: GPIO27 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO26_Pos (26UL) /*!< GPIO INT0EN: GPIO26 (Bit 26) */ +#define GPIO_INT0EN_GPIO26_Msk (0x4000000UL) /*!< GPIO INT0EN: GPIO26 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO25_Pos (25UL) /*!< GPIO INT0EN: GPIO25 (Bit 25) */ +#define GPIO_INT0EN_GPIO25_Msk (0x2000000UL) /*!< GPIO INT0EN: GPIO25 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO24_Pos (24UL) /*!< GPIO INT0EN: GPIO24 (Bit 24) */ +#define GPIO_INT0EN_GPIO24_Msk (0x1000000UL) /*!< GPIO INT0EN: GPIO24 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO23_Pos (23UL) /*!< GPIO INT0EN: GPIO23 (Bit 23) */ +#define GPIO_INT0EN_GPIO23_Msk (0x800000UL) /*!< GPIO INT0EN: GPIO23 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO22_Pos (22UL) /*!< GPIO INT0EN: GPIO22 (Bit 22) */ +#define GPIO_INT0EN_GPIO22_Msk (0x400000UL) /*!< GPIO INT0EN: GPIO22 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO21_Pos (21UL) /*!< GPIO INT0EN: GPIO21 (Bit 21) */ +#define GPIO_INT0EN_GPIO21_Msk (0x200000UL) /*!< GPIO INT0EN: GPIO21 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO20_Pos (20UL) /*!< GPIO INT0EN: GPIO20 (Bit 20) */ +#define GPIO_INT0EN_GPIO20_Msk (0x100000UL) /*!< GPIO INT0EN: GPIO20 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO19_Pos (19UL) /*!< GPIO INT0EN: GPIO19 (Bit 19) */ +#define GPIO_INT0EN_GPIO19_Msk (0x80000UL) /*!< GPIO INT0EN: GPIO19 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO18_Pos (18UL) /*!< GPIO INT0EN: GPIO18 (Bit 18) */ +#define GPIO_INT0EN_GPIO18_Msk (0x40000UL) /*!< GPIO INT0EN: GPIO18 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO17_Pos (17UL) /*!< GPIO INT0EN: GPIO17 (Bit 17) */ +#define GPIO_INT0EN_GPIO17_Msk (0x20000UL) /*!< GPIO INT0EN: GPIO17 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO16_Pos (16UL) /*!< GPIO INT0EN: GPIO16 (Bit 16) */ +#define GPIO_INT0EN_GPIO16_Msk (0x10000UL) /*!< GPIO INT0EN: GPIO16 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO15_Pos (15UL) /*!< GPIO INT0EN: GPIO15 (Bit 15) */ +#define GPIO_INT0EN_GPIO15_Msk (0x8000UL) /*!< GPIO INT0EN: GPIO15 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO14_Pos (14UL) /*!< GPIO INT0EN: GPIO14 (Bit 14) */ +#define GPIO_INT0EN_GPIO14_Msk (0x4000UL) /*!< GPIO INT0EN: GPIO14 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO13_Pos (13UL) /*!< GPIO INT0EN: GPIO13 (Bit 13) */ +#define GPIO_INT0EN_GPIO13_Msk (0x2000UL) /*!< GPIO INT0EN: GPIO13 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO12_Pos (12UL) /*!< GPIO INT0EN: GPIO12 (Bit 12) */ +#define GPIO_INT0EN_GPIO12_Msk (0x1000UL) /*!< GPIO INT0EN: GPIO12 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO11_Pos (11UL) /*!< GPIO INT0EN: GPIO11 (Bit 11) */ +#define GPIO_INT0EN_GPIO11_Msk (0x800UL) /*!< GPIO INT0EN: GPIO11 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO10_Pos (10UL) /*!< GPIO INT0EN: GPIO10 (Bit 10) */ +#define GPIO_INT0EN_GPIO10_Msk (0x400UL) /*!< GPIO INT0EN: GPIO10 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO9_Pos (9UL) /*!< GPIO INT0EN: GPIO9 (Bit 9) */ +#define GPIO_INT0EN_GPIO9_Msk (0x200UL) /*!< GPIO INT0EN: GPIO9 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO8_Pos (8UL) /*!< GPIO INT0EN: GPIO8 (Bit 8) */ +#define GPIO_INT0EN_GPIO8_Msk (0x100UL) /*!< GPIO INT0EN: GPIO8 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO7_Pos (7UL) /*!< GPIO INT0EN: GPIO7 (Bit 7) */ +#define GPIO_INT0EN_GPIO7_Msk (0x80UL) /*!< GPIO INT0EN: GPIO7 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO6_Pos (6UL) /*!< GPIO INT0EN: GPIO6 (Bit 6) */ +#define GPIO_INT0EN_GPIO6_Msk (0x40UL) /*!< GPIO INT0EN: GPIO6 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO5_Pos (5UL) /*!< GPIO INT0EN: GPIO5 (Bit 5) */ +#define GPIO_INT0EN_GPIO5_Msk (0x20UL) /*!< GPIO INT0EN: GPIO5 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO4_Pos (4UL) /*!< GPIO INT0EN: GPIO4 (Bit 4) */ +#define GPIO_INT0EN_GPIO4_Msk (0x10UL) /*!< GPIO INT0EN: GPIO4 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO3_Pos (3UL) /*!< GPIO INT0EN: GPIO3 (Bit 3) */ +#define GPIO_INT0EN_GPIO3_Msk (0x8UL) /*!< GPIO INT0EN: GPIO3 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO2_Pos (2UL) /*!< GPIO INT0EN: GPIO2 (Bit 2) */ +#define GPIO_INT0EN_GPIO2_Msk (0x4UL) /*!< GPIO INT0EN: GPIO2 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO1_Pos (1UL) /*!< GPIO INT0EN: GPIO1 (Bit 1) */ +#define GPIO_INT0EN_GPIO1_Msk (0x2UL) /*!< GPIO INT0EN: GPIO1 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0EN_GPIO0_Pos (0UL) /*!< GPIO INT0EN: GPIO0 (Bit 0) */ +#define GPIO_INT0EN_GPIO0_Msk (0x1UL) /*!< GPIO INT0EN: GPIO0 (Bitfield-Mask: 0x01) */ +/* ======================================================= INT0STAT ======================================================== */ +#define GPIO_INT0STAT_GPIO31_Pos (31UL) /*!< GPIO INT0STAT: GPIO31 (Bit 31) */ +#define GPIO_INT0STAT_GPIO31_Msk (0x80000000UL) /*!< GPIO INT0STAT: GPIO31 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO30_Pos (30UL) /*!< GPIO INT0STAT: GPIO30 (Bit 30) */ +#define GPIO_INT0STAT_GPIO30_Msk (0x40000000UL) /*!< GPIO INT0STAT: GPIO30 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO29_Pos (29UL) /*!< GPIO INT0STAT: GPIO29 (Bit 29) */ +#define GPIO_INT0STAT_GPIO29_Msk (0x20000000UL) /*!< GPIO INT0STAT: GPIO29 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO28_Pos (28UL) /*!< GPIO INT0STAT: GPIO28 (Bit 28) */ +#define GPIO_INT0STAT_GPIO28_Msk (0x10000000UL) /*!< GPIO INT0STAT: GPIO28 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO27_Pos (27UL) /*!< GPIO INT0STAT: GPIO27 (Bit 27) */ +#define GPIO_INT0STAT_GPIO27_Msk (0x8000000UL) /*!< GPIO INT0STAT: GPIO27 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO26_Pos (26UL) /*!< GPIO INT0STAT: GPIO26 (Bit 26) */ +#define GPIO_INT0STAT_GPIO26_Msk (0x4000000UL) /*!< GPIO INT0STAT: GPIO26 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO25_Pos (25UL) /*!< GPIO INT0STAT: GPIO25 (Bit 25) */ +#define GPIO_INT0STAT_GPIO25_Msk (0x2000000UL) /*!< GPIO INT0STAT: GPIO25 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO24_Pos (24UL) /*!< GPIO INT0STAT: GPIO24 (Bit 24) */ +#define GPIO_INT0STAT_GPIO24_Msk (0x1000000UL) /*!< GPIO INT0STAT: GPIO24 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO23_Pos (23UL) /*!< GPIO INT0STAT: GPIO23 (Bit 23) */ +#define GPIO_INT0STAT_GPIO23_Msk (0x800000UL) /*!< GPIO INT0STAT: GPIO23 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO22_Pos (22UL) /*!< GPIO INT0STAT: GPIO22 (Bit 22) */ +#define GPIO_INT0STAT_GPIO22_Msk (0x400000UL) /*!< GPIO INT0STAT: GPIO22 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO21_Pos (21UL) /*!< GPIO INT0STAT: GPIO21 (Bit 21) */ +#define GPIO_INT0STAT_GPIO21_Msk (0x200000UL) /*!< GPIO INT0STAT: GPIO21 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO20_Pos (20UL) /*!< GPIO INT0STAT: GPIO20 (Bit 20) */ +#define GPIO_INT0STAT_GPIO20_Msk (0x100000UL) /*!< GPIO INT0STAT: GPIO20 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO19_Pos (19UL) /*!< GPIO INT0STAT: GPIO19 (Bit 19) */ +#define GPIO_INT0STAT_GPIO19_Msk (0x80000UL) /*!< GPIO INT0STAT: GPIO19 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO18_Pos (18UL) /*!< GPIO INT0STAT: GPIO18 (Bit 18) */ +#define GPIO_INT0STAT_GPIO18_Msk (0x40000UL) /*!< GPIO INT0STAT: GPIO18 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO17_Pos (17UL) /*!< GPIO INT0STAT: GPIO17 (Bit 17) */ +#define GPIO_INT0STAT_GPIO17_Msk (0x20000UL) /*!< GPIO INT0STAT: GPIO17 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO16_Pos (16UL) /*!< GPIO INT0STAT: GPIO16 (Bit 16) */ +#define GPIO_INT0STAT_GPIO16_Msk (0x10000UL) /*!< GPIO INT0STAT: GPIO16 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO15_Pos (15UL) /*!< GPIO INT0STAT: GPIO15 (Bit 15) */ +#define GPIO_INT0STAT_GPIO15_Msk (0x8000UL) /*!< GPIO INT0STAT: GPIO15 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO14_Pos (14UL) /*!< GPIO INT0STAT: GPIO14 (Bit 14) */ +#define GPIO_INT0STAT_GPIO14_Msk (0x4000UL) /*!< GPIO INT0STAT: GPIO14 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO13_Pos (13UL) /*!< GPIO INT0STAT: GPIO13 (Bit 13) */ +#define GPIO_INT0STAT_GPIO13_Msk (0x2000UL) /*!< GPIO INT0STAT: GPIO13 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO12_Pos (12UL) /*!< GPIO INT0STAT: GPIO12 (Bit 12) */ +#define GPIO_INT0STAT_GPIO12_Msk (0x1000UL) /*!< GPIO INT0STAT: GPIO12 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO11_Pos (11UL) /*!< GPIO INT0STAT: GPIO11 (Bit 11) */ +#define GPIO_INT0STAT_GPIO11_Msk (0x800UL) /*!< GPIO INT0STAT: GPIO11 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO10_Pos (10UL) /*!< GPIO INT0STAT: GPIO10 (Bit 10) */ +#define GPIO_INT0STAT_GPIO10_Msk (0x400UL) /*!< GPIO INT0STAT: GPIO10 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO9_Pos (9UL) /*!< GPIO INT0STAT: GPIO9 (Bit 9) */ +#define GPIO_INT0STAT_GPIO9_Msk (0x200UL) /*!< GPIO INT0STAT: GPIO9 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO8_Pos (8UL) /*!< GPIO INT0STAT: GPIO8 (Bit 8) */ +#define GPIO_INT0STAT_GPIO8_Msk (0x100UL) /*!< GPIO INT0STAT: GPIO8 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO7_Pos (7UL) /*!< GPIO INT0STAT: GPIO7 (Bit 7) */ +#define GPIO_INT0STAT_GPIO7_Msk (0x80UL) /*!< GPIO INT0STAT: GPIO7 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO6_Pos (6UL) /*!< GPIO INT0STAT: GPIO6 (Bit 6) */ +#define GPIO_INT0STAT_GPIO6_Msk (0x40UL) /*!< GPIO INT0STAT: GPIO6 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO5_Pos (5UL) /*!< GPIO INT0STAT: GPIO5 (Bit 5) */ +#define GPIO_INT0STAT_GPIO5_Msk (0x20UL) /*!< GPIO INT0STAT: GPIO5 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO4_Pos (4UL) /*!< GPIO INT0STAT: GPIO4 (Bit 4) */ +#define GPIO_INT0STAT_GPIO4_Msk (0x10UL) /*!< GPIO INT0STAT: GPIO4 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO3_Pos (3UL) /*!< GPIO INT0STAT: GPIO3 (Bit 3) */ +#define GPIO_INT0STAT_GPIO3_Msk (0x8UL) /*!< GPIO INT0STAT: GPIO3 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO2_Pos (2UL) /*!< GPIO INT0STAT: GPIO2 (Bit 2) */ +#define GPIO_INT0STAT_GPIO2_Msk (0x4UL) /*!< GPIO INT0STAT: GPIO2 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO1_Pos (1UL) /*!< GPIO INT0STAT: GPIO1 (Bit 1) */ +#define GPIO_INT0STAT_GPIO1_Msk (0x2UL) /*!< GPIO INT0STAT: GPIO1 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0STAT_GPIO0_Pos (0UL) /*!< GPIO INT0STAT: GPIO0 (Bit 0) */ +#define GPIO_INT0STAT_GPIO0_Msk (0x1UL) /*!< GPIO INT0STAT: GPIO0 (Bitfield-Mask: 0x01) */ +/* ======================================================== INT0CLR ======================================================== */ +#define GPIO_INT0CLR_GPIO31_Pos (31UL) /*!< GPIO INT0CLR: GPIO31 (Bit 31) */ +#define GPIO_INT0CLR_GPIO31_Msk (0x80000000UL) /*!< GPIO INT0CLR: GPIO31 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO30_Pos (30UL) /*!< GPIO INT0CLR: GPIO30 (Bit 30) */ +#define GPIO_INT0CLR_GPIO30_Msk (0x40000000UL) /*!< GPIO INT0CLR: GPIO30 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO29_Pos (29UL) /*!< GPIO INT0CLR: GPIO29 (Bit 29) */ +#define GPIO_INT0CLR_GPIO29_Msk (0x20000000UL) /*!< GPIO INT0CLR: GPIO29 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO28_Pos (28UL) /*!< GPIO INT0CLR: GPIO28 (Bit 28) */ +#define GPIO_INT0CLR_GPIO28_Msk (0x10000000UL) /*!< GPIO INT0CLR: GPIO28 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO27_Pos (27UL) /*!< GPIO INT0CLR: GPIO27 (Bit 27) */ +#define GPIO_INT0CLR_GPIO27_Msk (0x8000000UL) /*!< GPIO INT0CLR: GPIO27 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO26_Pos (26UL) /*!< GPIO INT0CLR: GPIO26 (Bit 26) */ +#define GPIO_INT0CLR_GPIO26_Msk (0x4000000UL) /*!< GPIO INT0CLR: GPIO26 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO25_Pos (25UL) /*!< GPIO INT0CLR: GPIO25 (Bit 25) */ +#define GPIO_INT0CLR_GPIO25_Msk (0x2000000UL) /*!< GPIO INT0CLR: GPIO25 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO24_Pos (24UL) /*!< GPIO INT0CLR: GPIO24 (Bit 24) */ +#define GPIO_INT0CLR_GPIO24_Msk (0x1000000UL) /*!< GPIO INT0CLR: GPIO24 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO23_Pos (23UL) /*!< GPIO INT0CLR: GPIO23 (Bit 23) */ +#define GPIO_INT0CLR_GPIO23_Msk (0x800000UL) /*!< GPIO INT0CLR: GPIO23 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO22_Pos (22UL) /*!< GPIO INT0CLR: GPIO22 (Bit 22) */ +#define GPIO_INT0CLR_GPIO22_Msk (0x400000UL) /*!< GPIO INT0CLR: GPIO22 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO21_Pos (21UL) /*!< GPIO INT0CLR: GPIO21 (Bit 21) */ +#define GPIO_INT0CLR_GPIO21_Msk (0x200000UL) /*!< GPIO INT0CLR: GPIO21 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO20_Pos (20UL) /*!< GPIO INT0CLR: GPIO20 (Bit 20) */ +#define GPIO_INT0CLR_GPIO20_Msk (0x100000UL) /*!< GPIO INT0CLR: GPIO20 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO19_Pos (19UL) /*!< GPIO INT0CLR: GPIO19 (Bit 19) */ +#define GPIO_INT0CLR_GPIO19_Msk (0x80000UL) /*!< GPIO INT0CLR: GPIO19 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO18_Pos (18UL) /*!< GPIO INT0CLR: GPIO18 (Bit 18) */ +#define GPIO_INT0CLR_GPIO18_Msk (0x40000UL) /*!< GPIO INT0CLR: GPIO18 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO17_Pos (17UL) /*!< GPIO INT0CLR: GPIO17 (Bit 17) */ +#define GPIO_INT0CLR_GPIO17_Msk (0x20000UL) /*!< GPIO INT0CLR: GPIO17 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO16_Pos (16UL) /*!< GPIO INT0CLR: GPIO16 (Bit 16) */ +#define GPIO_INT0CLR_GPIO16_Msk (0x10000UL) /*!< GPIO INT0CLR: GPIO16 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO15_Pos (15UL) /*!< GPIO INT0CLR: GPIO15 (Bit 15) */ +#define GPIO_INT0CLR_GPIO15_Msk (0x8000UL) /*!< GPIO INT0CLR: GPIO15 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO14_Pos (14UL) /*!< GPIO INT0CLR: GPIO14 (Bit 14) */ +#define GPIO_INT0CLR_GPIO14_Msk (0x4000UL) /*!< GPIO INT0CLR: GPIO14 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO13_Pos (13UL) /*!< GPIO INT0CLR: GPIO13 (Bit 13) */ +#define GPIO_INT0CLR_GPIO13_Msk (0x2000UL) /*!< GPIO INT0CLR: GPIO13 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO12_Pos (12UL) /*!< GPIO INT0CLR: GPIO12 (Bit 12) */ +#define GPIO_INT0CLR_GPIO12_Msk (0x1000UL) /*!< GPIO INT0CLR: GPIO12 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO11_Pos (11UL) /*!< GPIO INT0CLR: GPIO11 (Bit 11) */ +#define GPIO_INT0CLR_GPIO11_Msk (0x800UL) /*!< GPIO INT0CLR: GPIO11 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO10_Pos (10UL) /*!< GPIO INT0CLR: GPIO10 (Bit 10) */ +#define GPIO_INT0CLR_GPIO10_Msk (0x400UL) /*!< GPIO INT0CLR: GPIO10 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO9_Pos (9UL) /*!< GPIO INT0CLR: GPIO9 (Bit 9) */ +#define GPIO_INT0CLR_GPIO9_Msk (0x200UL) /*!< GPIO INT0CLR: GPIO9 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO8_Pos (8UL) /*!< GPIO INT0CLR: GPIO8 (Bit 8) */ +#define GPIO_INT0CLR_GPIO8_Msk (0x100UL) /*!< GPIO INT0CLR: GPIO8 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO7_Pos (7UL) /*!< GPIO INT0CLR: GPIO7 (Bit 7) */ +#define GPIO_INT0CLR_GPIO7_Msk (0x80UL) /*!< GPIO INT0CLR: GPIO7 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO6_Pos (6UL) /*!< GPIO INT0CLR: GPIO6 (Bit 6) */ +#define GPIO_INT0CLR_GPIO6_Msk (0x40UL) /*!< GPIO INT0CLR: GPIO6 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO5_Pos (5UL) /*!< GPIO INT0CLR: GPIO5 (Bit 5) */ +#define GPIO_INT0CLR_GPIO5_Msk (0x20UL) /*!< GPIO INT0CLR: GPIO5 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO4_Pos (4UL) /*!< GPIO INT0CLR: GPIO4 (Bit 4) */ +#define GPIO_INT0CLR_GPIO4_Msk (0x10UL) /*!< GPIO INT0CLR: GPIO4 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO3_Pos (3UL) /*!< GPIO INT0CLR: GPIO3 (Bit 3) */ +#define GPIO_INT0CLR_GPIO3_Msk (0x8UL) /*!< GPIO INT0CLR: GPIO3 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO2_Pos (2UL) /*!< GPIO INT0CLR: GPIO2 (Bit 2) */ +#define GPIO_INT0CLR_GPIO2_Msk (0x4UL) /*!< GPIO INT0CLR: GPIO2 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO1_Pos (1UL) /*!< GPIO INT0CLR: GPIO1 (Bit 1) */ +#define GPIO_INT0CLR_GPIO1_Msk (0x2UL) /*!< GPIO INT0CLR: GPIO1 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0CLR_GPIO0_Pos (0UL) /*!< GPIO INT0CLR: GPIO0 (Bit 0) */ +#define GPIO_INT0CLR_GPIO0_Msk (0x1UL) /*!< GPIO INT0CLR: GPIO0 (Bitfield-Mask: 0x01) */ +/* ======================================================== INT0SET ======================================================== */ +#define GPIO_INT0SET_GPIO31_Pos (31UL) /*!< GPIO INT0SET: GPIO31 (Bit 31) */ +#define GPIO_INT0SET_GPIO31_Msk (0x80000000UL) /*!< GPIO INT0SET: GPIO31 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO30_Pos (30UL) /*!< GPIO INT0SET: GPIO30 (Bit 30) */ +#define GPIO_INT0SET_GPIO30_Msk (0x40000000UL) /*!< GPIO INT0SET: GPIO30 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO29_Pos (29UL) /*!< GPIO INT0SET: GPIO29 (Bit 29) */ +#define GPIO_INT0SET_GPIO29_Msk (0x20000000UL) /*!< GPIO INT0SET: GPIO29 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO28_Pos (28UL) /*!< GPIO INT0SET: GPIO28 (Bit 28) */ +#define GPIO_INT0SET_GPIO28_Msk (0x10000000UL) /*!< GPIO INT0SET: GPIO28 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO27_Pos (27UL) /*!< GPIO INT0SET: GPIO27 (Bit 27) */ +#define GPIO_INT0SET_GPIO27_Msk (0x8000000UL) /*!< GPIO INT0SET: GPIO27 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO26_Pos (26UL) /*!< GPIO INT0SET: GPIO26 (Bit 26) */ +#define GPIO_INT0SET_GPIO26_Msk (0x4000000UL) /*!< GPIO INT0SET: GPIO26 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO25_Pos (25UL) /*!< GPIO INT0SET: GPIO25 (Bit 25) */ +#define GPIO_INT0SET_GPIO25_Msk (0x2000000UL) /*!< GPIO INT0SET: GPIO25 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO24_Pos (24UL) /*!< GPIO INT0SET: GPIO24 (Bit 24) */ +#define GPIO_INT0SET_GPIO24_Msk (0x1000000UL) /*!< GPIO INT0SET: GPIO24 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO23_Pos (23UL) /*!< GPIO INT0SET: GPIO23 (Bit 23) */ +#define GPIO_INT0SET_GPIO23_Msk (0x800000UL) /*!< GPIO INT0SET: GPIO23 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO22_Pos (22UL) /*!< GPIO INT0SET: GPIO22 (Bit 22) */ +#define GPIO_INT0SET_GPIO22_Msk (0x400000UL) /*!< GPIO INT0SET: GPIO22 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO21_Pos (21UL) /*!< GPIO INT0SET: GPIO21 (Bit 21) */ +#define GPIO_INT0SET_GPIO21_Msk (0x200000UL) /*!< GPIO INT0SET: GPIO21 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO20_Pos (20UL) /*!< GPIO INT0SET: GPIO20 (Bit 20) */ +#define GPIO_INT0SET_GPIO20_Msk (0x100000UL) /*!< GPIO INT0SET: GPIO20 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO19_Pos (19UL) /*!< GPIO INT0SET: GPIO19 (Bit 19) */ +#define GPIO_INT0SET_GPIO19_Msk (0x80000UL) /*!< GPIO INT0SET: GPIO19 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO18_Pos (18UL) /*!< GPIO INT0SET: GPIO18 (Bit 18) */ +#define GPIO_INT0SET_GPIO18_Msk (0x40000UL) /*!< GPIO INT0SET: GPIO18 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO17_Pos (17UL) /*!< GPIO INT0SET: GPIO17 (Bit 17) */ +#define GPIO_INT0SET_GPIO17_Msk (0x20000UL) /*!< GPIO INT0SET: GPIO17 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO16_Pos (16UL) /*!< GPIO INT0SET: GPIO16 (Bit 16) */ +#define GPIO_INT0SET_GPIO16_Msk (0x10000UL) /*!< GPIO INT0SET: GPIO16 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO15_Pos (15UL) /*!< GPIO INT0SET: GPIO15 (Bit 15) */ +#define GPIO_INT0SET_GPIO15_Msk (0x8000UL) /*!< GPIO INT0SET: GPIO15 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO14_Pos (14UL) /*!< GPIO INT0SET: GPIO14 (Bit 14) */ +#define GPIO_INT0SET_GPIO14_Msk (0x4000UL) /*!< GPIO INT0SET: GPIO14 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO13_Pos (13UL) /*!< GPIO INT0SET: GPIO13 (Bit 13) */ +#define GPIO_INT0SET_GPIO13_Msk (0x2000UL) /*!< GPIO INT0SET: GPIO13 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO12_Pos (12UL) /*!< GPIO INT0SET: GPIO12 (Bit 12) */ +#define GPIO_INT0SET_GPIO12_Msk (0x1000UL) /*!< GPIO INT0SET: GPIO12 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO11_Pos (11UL) /*!< GPIO INT0SET: GPIO11 (Bit 11) */ +#define GPIO_INT0SET_GPIO11_Msk (0x800UL) /*!< GPIO INT0SET: GPIO11 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO10_Pos (10UL) /*!< GPIO INT0SET: GPIO10 (Bit 10) */ +#define GPIO_INT0SET_GPIO10_Msk (0x400UL) /*!< GPIO INT0SET: GPIO10 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO9_Pos (9UL) /*!< GPIO INT0SET: GPIO9 (Bit 9) */ +#define GPIO_INT0SET_GPIO9_Msk (0x200UL) /*!< GPIO INT0SET: GPIO9 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO8_Pos (8UL) /*!< GPIO INT0SET: GPIO8 (Bit 8) */ +#define GPIO_INT0SET_GPIO8_Msk (0x100UL) /*!< GPIO INT0SET: GPIO8 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO7_Pos (7UL) /*!< GPIO INT0SET: GPIO7 (Bit 7) */ +#define GPIO_INT0SET_GPIO7_Msk (0x80UL) /*!< GPIO INT0SET: GPIO7 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO6_Pos (6UL) /*!< GPIO INT0SET: GPIO6 (Bit 6) */ +#define GPIO_INT0SET_GPIO6_Msk (0x40UL) /*!< GPIO INT0SET: GPIO6 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO5_Pos (5UL) /*!< GPIO INT0SET: GPIO5 (Bit 5) */ +#define GPIO_INT0SET_GPIO5_Msk (0x20UL) /*!< GPIO INT0SET: GPIO5 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO4_Pos (4UL) /*!< GPIO INT0SET: GPIO4 (Bit 4) */ +#define GPIO_INT0SET_GPIO4_Msk (0x10UL) /*!< GPIO INT0SET: GPIO4 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO3_Pos (3UL) /*!< GPIO INT0SET: GPIO3 (Bit 3) */ +#define GPIO_INT0SET_GPIO3_Msk (0x8UL) /*!< GPIO INT0SET: GPIO3 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO2_Pos (2UL) /*!< GPIO INT0SET: GPIO2 (Bit 2) */ +#define GPIO_INT0SET_GPIO2_Msk (0x4UL) /*!< GPIO INT0SET: GPIO2 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO1_Pos (1UL) /*!< GPIO INT0SET: GPIO1 (Bit 1) */ +#define GPIO_INT0SET_GPIO1_Msk (0x2UL) /*!< GPIO INT0SET: GPIO1 (Bitfield-Mask: 0x01) */ +#define GPIO_INT0SET_GPIO0_Pos (0UL) /*!< GPIO INT0SET: GPIO0 (Bit 0) */ +#define GPIO_INT0SET_GPIO0_Msk (0x1UL) /*!< GPIO INT0SET: GPIO0 (Bitfield-Mask: 0x01) */ +/* ======================================================== INT1EN ========================================================= */ +#define GPIO_INT1EN_GPIO49_Pos (17UL) /*!< GPIO INT1EN: GPIO49 (Bit 17) */ +#define GPIO_INT1EN_GPIO49_Msk (0x20000UL) /*!< GPIO INT1EN: GPIO49 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO48_Pos (16UL) /*!< GPIO INT1EN: GPIO48 (Bit 16) */ +#define GPIO_INT1EN_GPIO48_Msk (0x10000UL) /*!< GPIO INT1EN: GPIO48 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO47_Pos (15UL) /*!< GPIO INT1EN: GPIO47 (Bit 15) */ +#define GPIO_INT1EN_GPIO47_Msk (0x8000UL) /*!< GPIO INT1EN: GPIO47 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO46_Pos (14UL) /*!< GPIO INT1EN: GPIO46 (Bit 14) */ +#define GPIO_INT1EN_GPIO46_Msk (0x4000UL) /*!< GPIO INT1EN: GPIO46 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO45_Pos (13UL) /*!< GPIO INT1EN: GPIO45 (Bit 13) */ +#define GPIO_INT1EN_GPIO45_Msk (0x2000UL) /*!< GPIO INT1EN: GPIO45 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO44_Pos (12UL) /*!< GPIO INT1EN: GPIO44 (Bit 12) */ +#define GPIO_INT1EN_GPIO44_Msk (0x1000UL) /*!< GPIO INT1EN: GPIO44 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO43_Pos (11UL) /*!< GPIO INT1EN: GPIO43 (Bit 11) */ +#define GPIO_INT1EN_GPIO43_Msk (0x800UL) /*!< GPIO INT1EN: GPIO43 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO42_Pos (10UL) /*!< GPIO INT1EN: GPIO42 (Bit 10) */ +#define GPIO_INT1EN_GPIO42_Msk (0x400UL) /*!< GPIO INT1EN: GPIO42 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO41_Pos (9UL) /*!< GPIO INT1EN: GPIO41 (Bit 9) */ +#define GPIO_INT1EN_GPIO41_Msk (0x200UL) /*!< GPIO INT1EN: GPIO41 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO40_Pos (8UL) /*!< GPIO INT1EN: GPIO40 (Bit 8) */ +#define GPIO_INT1EN_GPIO40_Msk (0x100UL) /*!< GPIO INT1EN: GPIO40 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO39_Pos (7UL) /*!< GPIO INT1EN: GPIO39 (Bit 7) */ +#define GPIO_INT1EN_GPIO39_Msk (0x80UL) /*!< GPIO INT1EN: GPIO39 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO38_Pos (6UL) /*!< GPIO INT1EN: GPIO38 (Bit 6) */ +#define GPIO_INT1EN_GPIO38_Msk (0x40UL) /*!< GPIO INT1EN: GPIO38 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO37_Pos (5UL) /*!< GPIO INT1EN: GPIO37 (Bit 5) */ +#define GPIO_INT1EN_GPIO37_Msk (0x20UL) /*!< GPIO INT1EN: GPIO37 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO36_Pos (4UL) /*!< GPIO INT1EN: GPIO36 (Bit 4) */ +#define GPIO_INT1EN_GPIO36_Msk (0x10UL) /*!< GPIO INT1EN: GPIO36 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO35_Pos (3UL) /*!< GPIO INT1EN: GPIO35 (Bit 3) */ +#define GPIO_INT1EN_GPIO35_Msk (0x8UL) /*!< GPIO INT1EN: GPIO35 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO34_Pos (2UL) /*!< GPIO INT1EN: GPIO34 (Bit 2) */ +#define GPIO_INT1EN_GPIO34_Msk (0x4UL) /*!< GPIO INT1EN: GPIO34 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO33_Pos (1UL) /*!< GPIO INT1EN: GPIO33 (Bit 1) */ +#define GPIO_INT1EN_GPIO33_Msk (0x2UL) /*!< GPIO INT1EN: GPIO33 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1EN_GPIO32_Pos (0UL) /*!< GPIO INT1EN: GPIO32 (Bit 0) */ +#define GPIO_INT1EN_GPIO32_Msk (0x1UL) /*!< GPIO INT1EN: GPIO32 (Bitfield-Mask: 0x01) */ +/* ======================================================= INT1STAT ======================================================== */ +#define GPIO_INT1STAT_GPIO49_Pos (17UL) /*!< GPIO INT1STAT: GPIO49 (Bit 17) */ +#define GPIO_INT1STAT_GPIO49_Msk (0x20000UL) /*!< GPIO INT1STAT: GPIO49 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO48_Pos (16UL) /*!< GPIO INT1STAT: GPIO48 (Bit 16) */ +#define GPIO_INT1STAT_GPIO48_Msk (0x10000UL) /*!< GPIO INT1STAT: GPIO48 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO47_Pos (15UL) /*!< GPIO INT1STAT: GPIO47 (Bit 15) */ +#define GPIO_INT1STAT_GPIO47_Msk (0x8000UL) /*!< GPIO INT1STAT: GPIO47 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO46_Pos (14UL) /*!< GPIO INT1STAT: GPIO46 (Bit 14) */ +#define GPIO_INT1STAT_GPIO46_Msk (0x4000UL) /*!< GPIO INT1STAT: GPIO46 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO45_Pos (13UL) /*!< GPIO INT1STAT: GPIO45 (Bit 13) */ +#define GPIO_INT1STAT_GPIO45_Msk (0x2000UL) /*!< GPIO INT1STAT: GPIO45 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO44_Pos (12UL) /*!< GPIO INT1STAT: GPIO44 (Bit 12) */ +#define GPIO_INT1STAT_GPIO44_Msk (0x1000UL) /*!< GPIO INT1STAT: GPIO44 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO43_Pos (11UL) /*!< GPIO INT1STAT: GPIO43 (Bit 11) */ +#define GPIO_INT1STAT_GPIO43_Msk (0x800UL) /*!< GPIO INT1STAT: GPIO43 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO42_Pos (10UL) /*!< GPIO INT1STAT: GPIO42 (Bit 10) */ +#define GPIO_INT1STAT_GPIO42_Msk (0x400UL) /*!< GPIO INT1STAT: GPIO42 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO41_Pos (9UL) /*!< GPIO INT1STAT: GPIO41 (Bit 9) */ +#define GPIO_INT1STAT_GPIO41_Msk (0x200UL) /*!< GPIO INT1STAT: GPIO41 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO40_Pos (8UL) /*!< GPIO INT1STAT: GPIO40 (Bit 8) */ +#define GPIO_INT1STAT_GPIO40_Msk (0x100UL) /*!< GPIO INT1STAT: GPIO40 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO39_Pos (7UL) /*!< GPIO INT1STAT: GPIO39 (Bit 7) */ +#define GPIO_INT1STAT_GPIO39_Msk (0x80UL) /*!< GPIO INT1STAT: GPIO39 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO38_Pos (6UL) /*!< GPIO INT1STAT: GPIO38 (Bit 6) */ +#define GPIO_INT1STAT_GPIO38_Msk (0x40UL) /*!< GPIO INT1STAT: GPIO38 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO37_Pos (5UL) /*!< GPIO INT1STAT: GPIO37 (Bit 5) */ +#define GPIO_INT1STAT_GPIO37_Msk (0x20UL) /*!< GPIO INT1STAT: GPIO37 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO36_Pos (4UL) /*!< GPIO INT1STAT: GPIO36 (Bit 4) */ +#define GPIO_INT1STAT_GPIO36_Msk (0x10UL) /*!< GPIO INT1STAT: GPIO36 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO35_Pos (3UL) /*!< GPIO INT1STAT: GPIO35 (Bit 3) */ +#define GPIO_INT1STAT_GPIO35_Msk (0x8UL) /*!< GPIO INT1STAT: GPIO35 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO34_Pos (2UL) /*!< GPIO INT1STAT: GPIO34 (Bit 2) */ +#define GPIO_INT1STAT_GPIO34_Msk (0x4UL) /*!< GPIO INT1STAT: GPIO34 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO33_Pos (1UL) /*!< GPIO INT1STAT: GPIO33 (Bit 1) */ +#define GPIO_INT1STAT_GPIO33_Msk (0x2UL) /*!< GPIO INT1STAT: GPIO33 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1STAT_GPIO32_Pos (0UL) /*!< GPIO INT1STAT: GPIO32 (Bit 0) */ +#define GPIO_INT1STAT_GPIO32_Msk (0x1UL) /*!< GPIO INT1STAT: GPIO32 (Bitfield-Mask: 0x01) */ +/* ======================================================== INT1CLR ======================================================== */ +#define GPIO_INT1CLR_GPIO49_Pos (17UL) /*!< GPIO INT1CLR: GPIO49 (Bit 17) */ +#define GPIO_INT1CLR_GPIO49_Msk (0x20000UL) /*!< GPIO INT1CLR: GPIO49 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO48_Pos (16UL) /*!< GPIO INT1CLR: GPIO48 (Bit 16) */ +#define GPIO_INT1CLR_GPIO48_Msk (0x10000UL) /*!< GPIO INT1CLR: GPIO48 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO47_Pos (15UL) /*!< GPIO INT1CLR: GPIO47 (Bit 15) */ +#define GPIO_INT1CLR_GPIO47_Msk (0x8000UL) /*!< GPIO INT1CLR: GPIO47 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO46_Pos (14UL) /*!< GPIO INT1CLR: GPIO46 (Bit 14) */ +#define GPIO_INT1CLR_GPIO46_Msk (0x4000UL) /*!< GPIO INT1CLR: GPIO46 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO45_Pos (13UL) /*!< GPIO INT1CLR: GPIO45 (Bit 13) */ +#define GPIO_INT1CLR_GPIO45_Msk (0x2000UL) /*!< GPIO INT1CLR: GPIO45 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO44_Pos (12UL) /*!< GPIO INT1CLR: GPIO44 (Bit 12) */ +#define GPIO_INT1CLR_GPIO44_Msk (0x1000UL) /*!< GPIO INT1CLR: GPIO44 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO43_Pos (11UL) /*!< GPIO INT1CLR: GPIO43 (Bit 11) */ +#define GPIO_INT1CLR_GPIO43_Msk (0x800UL) /*!< GPIO INT1CLR: GPIO43 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO42_Pos (10UL) /*!< GPIO INT1CLR: GPIO42 (Bit 10) */ +#define GPIO_INT1CLR_GPIO42_Msk (0x400UL) /*!< GPIO INT1CLR: GPIO42 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO41_Pos (9UL) /*!< GPIO INT1CLR: GPIO41 (Bit 9) */ +#define GPIO_INT1CLR_GPIO41_Msk (0x200UL) /*!< GPIO INT1CLR: GPIO41 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO40_Pos (8UL) /*!< GPIO INT1CLR: GPIO40 (Bit 8) */ +#define GPIO_INT1CLR_GPIO40_Msk (0x100UL) /*!< GPIO INT1CLR: GPIO40 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO39_Pos (7UL) /*!< GPIO INT1CLR: GPIO39 (Bit 7) */ +#define GPIO_INT1CLR_GPIO39_Msk (0x80UL) /*!< GPIO INT1CLR: GPIO39 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO38_Pos (6UL) /*!< GPIO INT1CLR: GPIO38 (Bit 6) */ +#define GPIO_INT1CLR_GPIO38_Msk (0x40UL) /*!< GPIO INT1CLR: GPIO38 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO37_Pos (5UL) /*!< GPIO INT1CLR: GPIO37 (Bit 5) */ +#define GPIO_INT1CLR_GPIO37_Msk (0x20UL) /*!< GPIO INT1CLR: GPIO37 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO36_Pos (4UL) /*!< GPIO INT1CLR: GPIO36 (Bit 4) */ +#define GPIO_INT1CLR_GPIO36_Msk (0x10UL) /*!< GPIO INT1CLR: GPIO36 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO35_Pos (3UL) /*!< GPIO INT1CLR: GPIO35 (Bit 3) */ +#define GPIO_INT1CLR_GPIO35_Msk (0x8UL) /*!< GPIO INT1CLR: GPIO35 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO34_Pos (2UL) /*!< GPIO INT1CLR: GPIO34 (Bit 2) */ +#define GPIO_INT1CLR_GPIO34_Msk (0x4UL) /*!< GPIO INT1CLR: GPIO34 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO33_Pos (1UL) /*!< GPIO INT1CLR: GPIO33 (Bit 1) */ +#define GPIO_INT1CLR_GPIO33_Msk (0x2UL) /*!< GPIO INT1CLR: GPIO33 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1CLR_GPIO32_Pos (0UL) /*!< GPIO INT1CLR: GPIO32 (Bit 0) */ +#define GPIO_INT1CLR_GPIO32_Msk (0x1UL) /*!< GPIO INT1CLR: GPIO32 (Bitfield-Mask: 0x01) */ +/* ======================================================== INT1SET ======================================================== */ +#define GPIO_INT1SET_GPIO49_Pos (17UL) /*!< GPIO INT1SET: GPIO49 (Bit 17) */ +#define GPIO_INT1SET_GPIO49_Msk (0x20000UL) /*!< GPIO INT1SET: GPIO49 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO48_Pos (16UL) /*!< GPIO INT1SET: GPIO48 (Bit 16) */ +#define GPIO_INT1SET_GPIO48_Msk (0x10000UL) /*!< GPIO INT1SET: GPIO48 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO47_Pos (15UL) /*!< GPIO INT1SET: GPIO47 (Bit 15) */ +#define GPIO_INT1SET_GPIO47_Msk (0x8000UL) /*!< GPIO INT1SET: GPIO47 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO46_Pos (14UL) /*!< GPIO INT1SET: GPIO46 (Bit 14) */ +#define GPIO_INT1SET_GPIO46_Msk (0x4000UL) /*!< GPIO INT1SET: GPIO46 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO45_Pos (13UL) /*!< GPIO INT1SET: GPIO45 (Bit 13) */ +#define GPIO_INT1SET_GPIO45_Msk (0x2000UL) /*!< GPIO INT1SET: GPIO45 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO44_Pos (12UL) /*!< GPIO INT1SET: GPIO44 (Bit 12) */ +#define GPIO_INT1SET_GPIO44_Msk (0x1000UL) /*!< GPIO INT1SET: GPIO44 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO43_Pos (11UL) /*!< GPIO INT1SET: GPIO43 (Bit 11) */ +#define GPIO_INT1SET_GPIO43_Msk (0x800UL) /*!< GPIO INT1SET: GPIO43 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO42_Pos (10UL) /*!< GPIO INT1SET: GPIO42 (Bit 10) */ +#define GPIO_INT1SET_GPIO42_Msk (0x400UL) /*!< GPIO INT1SET: GPIO42 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO41_Pos (9UL) /*!< GPIO INT1SET: GPIO41 (Bit 9) */ +#define GPIO_INT1SET_GPIO41_Msk (0x200UL) /*!< GPIO INT1SET: GPIO41 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO40_Pos (8UL) /*!< GPIO INT1SET: GPIO40 (Bit 8) */ +#define GPIO_INT1SET_GPIO40_Msk (0x100UL) /*!< GPIO INT1SET: GPIO40 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO39_Pos (7UL) /*!< GPIO INT1SET: GPIO39 (Bit 7) */ +#define GPIO_INT1SET_GPIO39_Msk (0x80UL) /*!< GPIO INT1SET: GPIO39 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO38_Pos (6UL) /*!< GPIO INT1SET: GPIO38 (Bit 6) */ +#define GPIO_INT1SET_GPIO38_Msk (0x40UL) /*!< GPIO INT1SET: GPIO38 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO37_Pos (5UL) /*!< GPIO INT1SET: GPIO37 (Bit 5) */ +#define GPIO_INT1SET_GPIO37_Msk (0x20UL) /*!< GPIO INT1SET: GPIO37 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO36_Pos (4UL) /*!< GPIO INT1SET: GPIO36 (Bit 4) */ +#define GPIO_INT1SET_GPIO36_Msk (0x10UL) /*!< GPIO INT1SET: GPIO36 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO35_Pos (3UL) /*!< GPIO INT1SET: GPIO35 (Bit 3) */ +#define GPIO_INT1SET_GPIO35_Msk (0x8UL) /*!< GPIO INT1SET: GPIO35 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO34_Pos (2UL) /*!< GPIO INT1SET: GPIO34 (Bit 2) */ +#define GPIO_INT1SET_GPIO34_Msk (0x4UL) /*!< GPIO INT1SET: GPIO34 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO33_Pos (1UL) /*!< GPIO INT1SET: GPIO33 (Bit 1) */ +#define GPIO_INT1SET_GPIO33_Msk (0x2UL) /*!< GPIO INT1SET: GPIO33 (Bitfield-Mask: 0x01) */ +#define GPIO_INT1SET_GPIO32_Pos (0UL) /*!< GPIO INT1SET: GPIO32 (Bit 0) */ +#define GPIO_INT1SET_GPIO32_Msk (0x1UL) /*!< GPIO INT1SET: GPIO32 (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ IOM0 ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= FIFO ========================================================== */ +#define IOM0_FIFO_FIFO_Pos (0UL) /*!< IOM0 FIFO: FIFO (Bit 0) */ +#define IOM0_FIFO_FIFO_Msk (0xffffffffUL) /*!< IOM0 FIFO: FIFO (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== FIFOPTR ======================================================== */ +#define IOM0_FIFOPTR_FIFO1REM_Pos (24UL) /*!< IOM0 FIFOPTR: FIFO1REM (Bit 24) */ +#define IOM0_FIFOPTR_FIFO1REM_Msk (0xff000000UL) /*!< IOM0 FIFOPTR: FIFO1REM (Bitfield-Mask: 0xff) */ +#define IOM0_FIFOPTR_FIFO1SIZ_Pos (16UL) /*!< IOM0 FIFOPTR: FIFO1SIZ (Bit 16) */ +#define IOM0_FIFOPTR_FIFO1SIZ_Msk (0xff0000UL) /*!< IOM0 FIFOPTR: FIFO1SIZ (Bitfield-Mask: 0xff) */ +#define IOM0_FIFOPTR_FIFO0REM_Pos (8UL) /*!< IOM0 FIFOPTR: FIFO0REM (Bit 8) */ +#define IOM0_FIFOPTR_FIFO0REM_Msk (0xff00UL) /*!< IOM0 FIFOPTR: FIFO0REM (Bitfield-Mask: 0xff) */ +#define IOM0_FIFOPTR_FIFO0SIZ_Pos (0UL) /*!< IOM0 FIFOPTR: FIFO0SIZ (Bit 0) */ +#define IOM0_FIFOPTR_FIFO0SIZ_Msk (0xffUL) /*!< IOM0 FIFOPTR: FIFO0SIZ (Bitfield-Mask: 0xff) */ +/* ======================================================== FIFOTHR ======================================================== */ +#define IOM0_FIFOTHR_FIFOWTHR_Pos (8UL) /*!< IOM0 FIFOTHR: FIFOWTHR (Bit 8) */ +#define IOM0_FIFOTHR_FIFOWTHR_Msk (0x3f00UL) /*!< IOM0 FIFOTHR: FIFOWTHR (Bitfield-Mask: 0x3f) */ +#define IOM0_FIFOTHR_FIFORTHR_Pos (0UL) /*!< IOM0 FIFOTHR: FIFORTHR (Bit 0) */ +#define IOM0_FIFOTHR_FIFORTHR_Msk (0x3fUL) /*!< IOM0 FIFOTHR: FIFORTHR (Bitfield-Mask: 0x3f) */ +/* ======================================================== FIFOPOP ======================================================== */ +#define IOM0_FIFOPOP_FIFODOUT_Pos (0UL) /*!< IOM0 FIFOPOP: FIFODOUT (Bit 0) */ +#define IOM0_FIFOPOP_FIFODOUT_Msk (0xffffffffUL) /*!< IOM0 FIFOPOP: FIFODOUT (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= FIFOPUSH ======================================================== */ +#define IOM0_FIFOPUSH_FIFODIN_Pos (0UL) /*!< IOM0 FIFOPUSH: FIFODIN (Bit 0) */ +#define IOM0_FIFOPUSH_FIFODIN_Msk (0xffffffffUL) /*!< IOM0 FIFOPUSH: FIFODIN (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= FIFOCTRL ======================================================== */ +#define IOM0_FIFOCTRL_FIFORSTN_Pos (1UL) /*!< IOM0 FIFOCTRL: FIFORSTN (Bit 1) */ +#define IOM0_FIFOCTRL_FIFORSTN_Msk (0x2UL) /*!< IOM0 FIFOCTRL: FIFORSTN (Bitfield-Mask: 0x01) */ +#define IOM0_FIFOCTRL_POPWR_Pos (0UL) /*!< IOM0 FIFOCTRL: POPWR (Bit 0) */ +#define IOM0_FIFOCTRL_POPWR_Msk (0x1UL) /*!< IOM0 FIFOCTRL: POPWR (Bitfield-Mask: 0x01) */ +/* ======================================================== FIFOLOC ======================================================== */ +#define IOM0_FIFOLOC_FIFORPTR_Pos (8UL) /*!< IOM0 FIFOLOC: FIFORPTR (Bit 8) */ +#define IOM0_FIFOLOC_FIFORPTR_Msk (0xf00UL) /*!< IOM0 FIFOLOC: FIFORPTR (Bitfield-Mask: 0x0f) */ +#define IOM0_FIFOLOC_FIFOWPTR_Pos (0UL) /*!< IOM0 FIFOLOC: FIFOWPTR (Bit 0) */ +#define IOM0_FIFOLOC_FIFOWPTR_Msk (0xfUL) /*!< IOM0 FIFOLOC: FIFOWPTR (Bitfield-Mask: 0x0f) */ +/* ========================================================= INTEN ========================================================= */ +#define IOM0_INTEN_CQERR_Pos (14UL) /*!< IOM0 INTEN: CQERR (Bit 14) */ +#define IOM0_INTEN_CQERR_Msk (0x4000UL) /*!< IOM0 INTEN: CQERR (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_CQUPD_Pos (13UL) /*!< IOM0 INTEN: CQUPD (Bit 13) */ +#define IOM0_INTEN_CQUPD_Msk (0x2000UL) /*!< IOM0 INTEN: CQUPD (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_CQPAUSED_Pos (12UL) /*!< IOM0 INTEN: CQPAUSED (Bit 12) */ +#define IOM0_INTEN_CQPAUSED_Msk (0x1000UL) /*!< IOM0 INTEN: CQPAUSED (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_DERR_Pos (11UL) /*!< IOM0 INTEN: DERR (Bit 11) */ +#define IOM0_INTEN_DERR_Msk (0x800UL) /*!< IOM0 INTEN: DERR (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_DCMP_Pos (10UL) /*!< IOM0 INTEN: DCMP (Bit 10) */ +#define IOM0_INTEN_DCMP_Msk (0x400UL) /*!< IOM0 INTEN: DCMP (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_ARB_Pos (9UL) /*!< IOM0 INTEN: ARB (Bit 9) */ +#define IOM0_INTEN_ARB_Msk (0x200UL) /*!< IOM0 INTEN: ARB (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_STOP_Pos (8UL) /*!< IOM0 INTEN: STOP (Bit 8) */ +#define IOM0_INTEN_STOP_Msk (0x100UL) /*!< IOM0 INTEN: STOP (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_START_Pos (7UL) /*!< IOM0 INTEN: START (Bit 7) */ +#define IOM0_INTEN_START_Msk (0x80UL) /*!< IOM0 INTEN: START (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_ICMD_Pos (6UL) /*!< IOM0 INTEN: ICMD (Bit 6) */ +#define IOM0_INTEN_ICMD_Msk (0x40UL) /*!< IOM0 INTEN: ICMD (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_IACC_Pos (5UL) /*!< IOM0 INTEN: IACC (Bit 5) */ +#define IOM0_INTEN_IACC_Msk (0x20UL) /*!< IOM0 INTEN: IACC (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_NAK_Pos (4UL) /*!< IOM0 INTEN: NAK (Bit 4) */ +#define IOM0_INTEN_NAK_Msk (0x10UL) /*!< IOM0 INTEN: NAK (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_FOVFL_Pos (3UL) /*!< IOM0 INTEN: FOVFL (Bit 3) */ +#define IOM0_INTEN_FOVFL_Msk (0x8UL) /*!< IOM0 INTEN: FOVFL (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_FUNDFL_Pos (2UL) /*!< IOM0 INTEN: FUNDFL (Bit 2) */ +#define IOM0_INTEN_FUNDFL_Msk (0x4UL) /*!< IOM0 INTEN: FUNDFL (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_THR_Pos (1UL) /*!< IOM0 INTEN: THR (Bit 1) */ +#define IOM0_INTEN_THR_Msk (0x2UL) /*!< IOM0 INTEN: THR (Bitfield-Mask: 0x01) */ +#define IOM0_INTEN_CMDCMP_Pos (0UL) /*!< IOM0 INTEN: CMDCMP (Bit 0) */ +#define IOM0_INTEN_CMDCMP_Msk (0x1UL) /*!< IOM0 INTEN: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define IOM0_INTSTAT_CQERR_Pos (14UL) /*!< IOM0 INTSTAT: CQERR (Bit 14) */ +#define IOM0_INTSTAT_CQERR_Msk (0x4000UL) /*!< IOM0 INTSTAT: CQERR (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_CQUPD_Pos (13UL) /*!< IOM0 INTSTAT: CQUPD (Bit 13) */ +#define IOM0_INTSTAT_CQUPD_Msk (0x2000UL) /*!< IOM0 INTSTAT: CQUPD (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_CQPAUSED_Pos (12UL) /*!< IOM0 INTSTAT: CQPAUSED (Bit 12) */ +#define IOM0_INTSTAT_CQPAUSED_Msk (0x1000UL) /*!< IOM0 INTSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_DERR_Pos (11UL) /*!< IOM0 INTSTAT: DERR (Bit 11) */ +#define IOM0_INTSTAT_DERR_Msk (0x800UL) /*!< IOM0 INTSTAT: DERR (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_DCMP_Pos (10UL) /*!< IOM0 INTSTAT: DCMP (Bit 10) */ +#define IOM0_INTSTAT_DCMP_Msk (0x400UL) /*!< IOM0 INTSTAT: DCMP (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_ARB_Pos (9UL) /*!< IOM0 INTSTAT: ARB (Bit 9) */ +#define IOM0_INTSTAT_ARB_Msk (0x200UL) /*!< IOM0 INTSTAT: ARB (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_STOP_Pos (8UL) /*!< IOM0 INTSTAT: STOP (Bit 8) */ +#define IOM0_INTSTAT_STOP_Msk (0x100UL) /*!< IOM0 INTSTAT: STOP (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_START_Pos (7UL) /*!< IOM0 INTSTAT: START (Bit 7) */ +#define IOM0_INTSTAT_START_Msk (0x80UL) /*!< IOM0 INTSTAT: START (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_ICMD_Pos (6UL) /*!< IOM0 INTSTAT: ICMD (Bit 6) */ +#define IOM0_INTSTAT_ICMD_Msk (0x40UL) /*!< IOM0 INTSTAT: ICMD (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_IACC_Pos (5UL) /*!< IOM0 INTSTAT: IACC (Bit 5) */ +#define IOM0_INTSTAT_IACC_Msk (0x20UL) /*!< IOM0 INTSTAT: IACC (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_NAK_Pos (4UL) /*!< IOM0 INTSTAT: NAK (Bit 4) */ +#define IOM0_INTSTAT_NAK_Msk (0x10UL) /*!< IOM0 INTSTAT: NAK (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_FOVFL_Pos (3UL) /*!< IOM0 INTSTAT: FOVFL (Bit 3) */ +#define IOM0_INTSTAT_FOVFL_Msk (0x8UL) /*!< IOM0 INTSTAT: FOVFL (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_FUNDFL_Pos (2UL) /*!< IOM0 INTSTAT: FUNDFL (Bit 2) */ +#define IOM0_INTSTAT_FUNDFL_Msk (0x4UL) /*!< IOM0 INTSTAT: FUNDFL (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_THR_Pos (1UL) /*!< IOM0 INTSTAT: THR (Bit 1) */ +#define IOM0_INTSTAT_THR_Msk (0x2UL) /*!< IOM0 INTSTAT: THR (Bitfield-Mask: 0x01) */ +#define IOM0_INTSTAT_CMDCMP_Pos (0UL) /*!< IOM0 INTSTAT: CMDCMP (Bit 0) */ +#define IOM0_INTSTAT_CMDCMP_Msk (0x1UL) /*!< IOM0 INTSTAT: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define IOM0_INTCLR_CQERR_Pos (14UL) /*!< IOM0 INTCLR: CQERR (Bit 14) */ +#define IOM0_INTCLR_CQERR_Msk (0x4000UL) /*!< IOM0 INTCLR: CQERR (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_CQUPD_Pos (13UL) /*!< IOM0 INTCLR: CQUPD (Bit 13) */ +#define IOM0_INTCLR_CQUPD_Msk (0x2000UL) /*!< IOM0 INTCLR: CQUPD (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_CQPAUSED_Pos (12UL) /*!< IOM0 INTCLR: CQPAUSED (Bit 12) */ +#define IOM0_INTCLR_CQPAUSED_Msk (0x1000UL) /*!< IOM0 INTCLR: CQPAUSED (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_DERR_Pos (11UL) /*!< IOM0 INTCLR: DERR (Bit 11) */ +#define IOM0_INTCLR_DERR_Msk (0x800UL) /*!< IOM0 INTCLR: DERR (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_DCMP_Pos (10UL) /*!< IOM0 INTCLR: DCMP (Bit 10) */ +#define IOM0_INTCLR_DCMP_Msk (0x400UL) /*!< IOM0 INTCLR: DCMP (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_ARB_Pos (9UL) /*!< IOM0 INTCLR: ARB (Bit 9) */ +#define IOM0_INTCLR_ARB_Msk (0x200UL) /*!< IOM0 INTCLR: ARB (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_STOP_Pos (8UL) /*!< IOM0 INTCLR: STOP (Bit 8) */ +#define IOM0_INTCLR_STOP_Msk (0x100UL) /*!< IOM0 INTCLR: STOP (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_START_Pos (7UL) /*!< IOM0 INTCLR: START (Bit 7) */ +#define IOM0_INTCLR_START_Msk (0x80UL) /*!< IOM0 INTCLR: START (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_ICMD_Pos (6UL) /*!< IOM0 INTCLR: ICMD (Bit 6) */ +#define IOM0_INTCLR_ICMD_Msk (0x40UL) /*!< IOM0 INTCLR: ICMD (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_IACC_Pos (5UL) /*!< IOM0 INTCLR: IACC (Bit 5) */ +#define IOM0_INTCLR_IACC_Msk (0x20UL) /*!< IOM0 INTCLR: IACC (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_NAK_Pos (4UL) /*!< IOM0 INTCLR: NAK (Bit 4) */ +#define IOM0_INTCLR_NAK_Msk (0x10UL) /*!< IOM0 INTCLR: NAK (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_FOVFL_Pos (3UL) /*!< IOM0 INTCLR: FOVFL (Bit 3) */ +#define IOM0_INTCLR_FOVFL_Msk (0x8UL) /*!< IOM0 INTCLR: FOVFL (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_FUNDFL_Pos (2UL) /*!< IOM0 INTCLR: FUNDFL (Bit 2) */ +#define IOM0_INTCLR_FUNDFL_Msk (0x4UL) /*!< IOM0 INTCLR: FUNDFL (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_THR_Pos (1UL) /*!< IOM0 INTCLR: THR (Bit 1) */ +#define IOM0_INTCLR_THR_Msk (0x2UL) /*!< IOM0 INTCLR: THR (Bitfield-Mask: 0x01) */ +#define IOM0_INTCLR_CMDCMP_Pos (0UL) /*!< IOM0 INTCLR: CMDCMP (Bit 0) */ +#define IOM0_INTCLR_CMDCMP_Msk (0x1UL) /*!< IOM0 INTCLR: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define IOM0_INTSET_CQERR_Pos (14UL) /*!< IOM0 INTSET: CQERR (Bit 14) */ +#define IOM0_INTSET_CQERR_Msk (0x4000UL) /*!< IOM0 INTSET: CQERR (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_CQUPD_Pos (13UL) /*!< IOM0 INTSET: CQUPD (Bit 13) */ +#define IOM0_INTSET_CQUPD_Msk (0x2000UL) /*!< IOM0 INTSET: CQUPD (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_CQPAUSED_Pos (12UL) /*!< IOM0 INTSET: CQPAUSED (Bit 12) */ +#define IOM0_INTSET_CQPAUSED_Msk (0x1000UL) /*!< IOM0 INTSET: CQPAUSED (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_DERR_Pos (11UL) /*!< IOM0 INTSET: DERR (Bit 11) */ +#define IOM0_INTSET_DERR_Msk (0x800UL) /*!< IOM0 INTSET: DERR (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_DCMP_Pos (10UL) /*!< IOM0 INTSET: DCMP (Bit 10) */ +#define IOM0_INTSET_DCMP_Msk (0x400UL) /*!< IOM0 INTSET: DCMP (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_ARB_Pos (9UL) /*!< IOM0 INTSET: ARB (Bit 9) */ +#define IOM0_INTSET_ARB_Msk (0x200UL) /*!< IOM0 INTSET: ARB (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_STOP_Pos (8UL) /*!< IOM0 INTSET: STOP (Bit 8) */ +#define IOM0_INTSET_STOP_Msk (0x100UL) /*!< IOM0 INTSET: STOP (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_START_Pos (7UL) /*!< IOM0 INTSET: START (Bit 7) */ +#define IOM0_INTSET_START_Msk (0x80UL) /*!< IOM0 INTSET: START (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_ICMD_Pos (6UL) /*!< IOM0 INTSET: ICMD (Bit 6) */ +#define IOM0_INTSET_ICMD_Msk (0x40UL) /*!< IOM0 INTSET: ICMD (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_IACC_Pos (5UL) /*!< IOM0 INTSET: IACC (Bit 5) */ +#define IOM0_INTSET_IACC_Msk (0x20UL) /*!< IOM0 INTSET: IACC (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_NAK_Pos (4UL) /*!< IOM0 INTSET: NAK (Bit 4) */ +#define IOM0_INTSET_NAK_Msk (0x10UL) /*!< IOM0 INTSET: NAK (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_FOVFL_Pos (3UL) /*!< IOM0 INTSET: FOVFL (Bit 3) */ +#define IOM0_INTSET_FOVFL_Msk (0x8UL) /*!< IOM0 INTSET: FOVFL (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_FUNDFL_Pos (2UL) /*!< IOM0 INTSET: FUNDFL (Bit 2) */ +#define IOM0_INTSET_FUNDFL_Msk (0x4UL) /*!< IOM0 INTSET: FUNDFL (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_THR_Pos (1UL) /*!< IOM0 INTSET: THR (Bit 1) */ +#define IOM0_INTSET_THR_Msk (0x2UL) /*!< IOM0 INTSET: THR (Bitfield-Mask: 0x01) */ +#define IOM0_INTSET_CMDCMP_Pos (0UL) /*!< IOM0 INTSET: CMDCMP (Bit 0) */ +#define IOM0_INTSET_CMDCMP_Msk (0x1UL) /*!< IOM0 INTSET: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== CLKCFG ========================================================= */ +#define IOM0_CLKCFG_TOTPER_Pos (24UL) /*!< IOM0 CLKCFG: TOTPER (Bit 24) */ +#define IOM0_CLKCFG_TOTPER_Msk (0xff000000UL) /*!< IOM0 CLKCFG: TOTPER (Bitfield-Mask: 0xff) */ +#define IOM0_CLKCFG_LOWPER_Pos (16UL) /*!< IOM0 CLKCFG: LOWPER (Bit 16) */ +#define IOM0_CLKCFG_LOWPER_Msk (0xff0000UL) /*!< IOM0 CLKCFG: LOWPER (Bitfield-Mask: 0xff) */ +#define IOM0_CLKCFG_DIVEN_Pos (12UL) /*!< IOM0 CLKCFG: DIVEN (Bit 12) */ +#define IOM0_CLKCFG_DIVEN_Msk (0x1000UL) /*!< IOM0 CLKCFG: DIVEN (Bitfield-Mask: 0x01) */ +#define IOM0_CLKCFG_DIV3_Pos (11UL) /*!< IOM0 CLKCFG: DIV3 (Bit 11) */ +#define IOM0_CLKCFG_DIV3_Msk (0x800UL) /*!< IOM0 CLKCFG: DIV3 (Bitfield-Mask: 0x01) */ +#define IOM0_CLKCFG_FSEL_Pos (8UL) /*!< IOM0 CLKCFG: FSEL (Bit 8) */ +#define IOM0_CLKCFG_FSEL_Msk (0x700UL) /*!< IOM0 CLKCFG: FSEL (Bitfield-Mask: 0x07) */ +#define IOM0_CLKCFG_IOCLKEN_Pos (0UL) /*!< IOM0 CLKCFG: IOCLKEN (Bit 0) */ +#define IOM0_CLKCFG_IOCLKEN_Msk (0x1UL) /*!< IOM0 CLKCFG: IOCLKEN (Bitfield-Mask: 0x01) */ +/* ====================================================== SUBMODCTRL ======================================================= */ +#define IOM0_SUBMODCTRL_SMOD1TYPE_Pos (5UL) /*!< IOM0 SUBMODCTRL: SMOD1TYPE (Bit 5) */ +#define IOM0_SUBMODCTRL_SMOD1TYPE_Msk (0xe0UL) /*!< IOM0 SUBMODCTRL: SMOD1TYPE (Bitfield-Mask: 0x07) */ +#define IOM0_SUBMODCTRL_SMOD1EN_Pos (4UL) /*!< IOM0 SUBMODCTRL: SMOD1EN (Bit 4) */ +#define IOM0_SUBMODCTRL_SMOD1EN_Msk (0x10UL) /*!< IOM0 SUBMODCTRL: SMOD1EN (Bitfield-Mask: 0x01) */ +#define IOM0_SUBMODCTRL_SMOD0TYPE_Pos (1UL) /*!< IOM0 SUBMODCTRL: SMOD0TYPE (Bit 1) */ +#define IOM0_SUBMODCTRL_SMOD0TYPE_Msk (0xeUL) /*!< IOM0 SUBMODCTRL: SMOD0TYPE (Bitfield-Mask: 0x07) */ +#define IOM0_SUBMODCTRL_SMOD0EN_Pos (0UL) /*!< IOM0 SUBMODCTRL: SMOD0EN (Bit 0) */ +#define IOM0_SUBMODCTRL_SMOD0EN_Msk (0x1UL) /*!< IOM0 SUBMODCTRL: SMOD0EN (Bitfield-Mask: 0x01) */ +/* ========================================================== CMD ========================================================== */ +#define IOM0_CMD_OFFSETLO_Pos (24UL) /*!< IOM0 CMD: OFFSETLO (Bit 24) */ +#define IOM0_CMD_OFFSETLO_Msk (0xff000000UL) /*!< IOM0 CMD: OFFSETLO (Bitfield-Mask: 0xff) */ +#define IOM0_CMD_CMDSEL_Pos (20UL) /*!< IOM0 CMD: CMDSEL (Bit 20) */ +#define IOM0_CMD_CMDSEL_Msk (0x300000UL) /*!< IOM0 CMD: CMDSEL (Bitfield-Mask: 0x03) */ +#define IOM0_CMD_TSIZE_Pos (8UL) /*!< IOM0 CMD: TSIZE (Bit 8) */ +#define IOM0_CMD_TSIZE_Msk (0xfff00UL) /*!< IOM0 CMD: TSIZE (Bitfield-Mask: 0xfff) */ +#define IOM0_CMD_CONT_Pos (7UL) /*!< IOM0 CMD: CONT (Bit 7) */ +#define IOM0_CMD_CONT_Msk (0x80UL) /*!< IOM0 CMD: CONT (Bitfield-Mask: 0x01) */ +#define IOM0_CMD_OFFSETCNT_Pos (5UL) /*!< IOM0 CMD: OFFSETCNT (Bit 5) */ +#define IOM0_CMD_OFFSETCNT_Msk (0x60UL) /*!< IOM0 CMD: OFFSETCNT (Bitfield-Mask: 0x03) */ +#define IOM0_CMD_CMD_Pos (0UL) /*!< IOM0 CMD: CMD (Bit 0) */ +#define IOM0_CMD_CMD_Msk (0x1fUL) /*!< IOM0 CMD: CMD (Bitfield-Mask: 0x1f) */ +/* ======================================================== CMDRPT ========================================================= */ +#define IOM0_CMDRPT_CMDRPT_Pos (0UL) /*!< IOM0 CMDRPT: CMDRPT (Bit 0) */ +#define IOM0_CMDRPT_CMDRPT_Msk (0x1fUL) /*!< IOM0 CMDRPT: CMDRPT (Bitfield-Mask: 0x1f) */ +/* ======================================================= OFFSETHI ======================================================== */ +#define IOM0_OFFSETHI_OFFSETHI_Pos (0UL) /*!< IOM0 OFFSETHI: OFFSETHI (Bit 0) */ +#define IOM0_OFFSETHI_OFFSETHI_Msk (0xffffUL) /*!< IOM0 OFFSETHI: OFFSETHI (Bitfield-Mask: 0xffff) */ +/* ======================================================== CMDSTAT ======================================================== */ +#define IOM0_CMDSTAT_CTSIZE_Pos (8UL) /*!< IOM0 CMDSTAT: CTSIZE (Bit 8) */ +#define IOM0_CMDSTAT_CTSIZE_Msk (0xfff00UL) /*!< IOM0 CMDSTAT: CTSIZE (Bitfield-Mask: 0xfff) */ +#define IOM0_CMDSTAT_CMDSTAT_Pos (5UL) /*!< IOM0 CMDSTAT: CMDSTAT (Bit 5) */ +#define IOM0_CMDSTAT_CMDSTAT_Msk (0xe0UL) /*!< IOM0 CMDSTAT: CMDSTAT (Bitfield-Mask: 0x07) */ +#define IOM0_CMDSTAT_CCMD_Pos (0UL) /*!< IOM0 CMDSTAT: CCMD (Bit 0) */ +#define IOM0_CMDSTAT_CCMD_Msk (0x1fUL) /*!< IOM0 CMDSTAT: CCMD (Bitfield-Mask: 0x1f) */ +/* ======================================================= DMATRIGEN ======================================================= */ +#define IOM0_DMATRIGEN_DTHREN_Pos (1UL) /*!< IOM0 DMATRIGEN: DTHREN (Bit 1) */ +#define IOM0_DMATRIGEN_DTHREN_Msk (0x2UL) /*!< IOM0 DMATRIGEN: DTHREN (Bitfield-Mask: 0x01) */ +#define IOM0_DMATRIGEN_DCMDCMPEN_Pos (0UL) /*!< IOM0 DMATRIGEN: DCMDCMPEN (Bit 0) */ +#define IOM0_DMATRIGEN_DCMDCMPEN_Msk (0x1UL) /*!< IOM0 DMATRIGEN: DCMDCMPEN (Bitfield-Mask: 0x01) */ +/* ====================================================== DMATRIGSTAT ====================================================== */ +#define IOM0_DMATRIGSTAT_DTOTCMP_Pos (2UL) /*!< IOM0 DMATRIGSTAT: DTOTCMP (Bit 2) */ +#define IOM0_DMATRIGSTAT_DTOTCMP_Msk (0x4UL) /*!< IOM0 DMATRIGSTAT: DTOTCMP (Bitfield-Mask: 0x01) */ +#define IOM0_DMATRIGSTAT_DTHR_Pos (1UL) /*!< IOM0 DMATRIGSTAT: DTHR (Bit 1) */ +#define IOM0_DMATRIGSTAT_DTHR_Msk (0x2UL) /*!< IOM0 DMATRIGSTAT: DTHR (Bitfield-Mask: 0x01) */ +#define IOM0_DMATRIGSTAT_DCMDCMP_Pos (0UL) /*!< IOM0 DMATRIGSTAT: DCMDCMP (Bit 0) */ +#define IOM0_DMATRIGSTAT_DCMDCMP_Msk (0x1UL) /*!< IOM0 DMATRIGSTAT: DCMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== DMACFG ========================================================= */ +#define IOM0_DMACFG_DPWROFF_Pos (9UL) /*!< IOM0 DMACFG: DPWROFF (Bit 9) */ +#define IOM0_DMACFG_DPWROFF_Msk (0x200UL) /*!< IOM0 DMACFG: DPWROFF (Bitfield-Mask: 0x01) */ +#define IOM0_DMACFG_DMAPRI_Pos (8UL) /*!< IOM0 DMACFG: DMAPRI (Bit 8) */ +#define IOM0_DMACFG_DMAPRI_Msk (0x100UL) /*!< IOM0 DMACFG: DMAPRI (Bitfield-Mask: 0x01) */ +#define IOM0_DMACFG_DMADIR_Pos (1UL) /*!< IOM0 DMACFG: DMADIR (Bit 1) */ +#define IOM0_DMACFG_DMADIR_Msk (0x2UL) /*!< IOM0 DMACFG: DMADIR (Bitfield-Mask: 0x01) */ +#define IOM0_DMACFG_DMAEN_Pos (0UL) /*!< IOM0 DMACFG: DMAEN (Bit 0) */ +#define IOM0_DMACFG_DMAEN_Msk (0x1UL) /*!< IOM0 DMACFG: DMAEN (Bitfield-Mask: 0x01) */ +/* ====================================================== DMATOTCOUNT ====================================================== */ +#define IOM0_DMATOTCOUNT_TOTCOUNT_Pos (0UL) /*!< IOM0 DMATOTCOUNT: TOTCOUNT (Bit 0) */ +#define IOM0_DMATOTCOUNT_TOTCOUNT_Msk (0xfffUL) /*!< IOM0 DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xfff) */ +/* ====================================================== DMATARGADDR ====================================================== */ +#define IOM0_DMATARGADDR_TARGADDR28_Pos (28UL) /*!< IOM0 DMATARGADDR: TARGADDR28 (Bit 28) */ +#define IOM0_DMATARGADDR_TARGADDR28_Msk (0x10000000UL) /*!< IOM0 DMATARGADDR: TARGADDR28 (Bitfield-Mask: 0x01) */ +#define IOM0_DMATARGADDR_TARGADDR_Pos (0UL) /*!< IOM0 DMATARGADDR: TARGADDR (Bit 0) */ +#define IOM0_DMATARGADDR_TARGADDR_Msk (0xfffffUL) /*!< IOM0 DMATARGADDR: TARGADDR (Bitfield-Mask: 0xfffff) */ +/* ======================================================== DMASTAT ======================================================== */ +#define IOM0_DMASTAT_DMAERR_Pos (2UL) /*!< IOM0 DMASTAT: DMAERR (Bit 2) */ +#define IOM0_DMASTAT_DMAERR_Msk (0x4UL) /*!< IOM0 DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ +#define IOM0_DMASTAT_DMACPL_Pos (1UL) /*!< IOM0 DMASTAT: DMACPL (Bit 1) */ +#define IOM0_DMASTAT_DMACPL_Msk (0x2UL) /*!< IOM0 DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ +#define IOM0_DMASTAT_DMATIP_Pos (0UL) /*!< IOM0 DMASTAT: DMATIP (Bit 0) */ +#define IOM0_DMASTAT_DMATIP_Msk (0x1UL) /*!< IOM0 DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ +/* ========================================================= CQCFG ========================================================= */ +#define IOM0_CQCFG_CQPRI_Pos (1UL) /*!< IOM0 CQCFG: CQPRI (Bit 1) */ +#define IOM0_CQCFG_CQPRI_Msk (0x2UL) /*!< IOM0 CQCFG: CQPRI (Bitfield-Mask: 0x01) */ +#define IOM0_CQCFG_CQEN_Pos (0UL) /*!< IOM0 CQCFG: CQEN (Bit 0) */ +#define IOM0_CQCFG_CQEN_Msk (0x1UL) /*!< IOM0 CQCFG: CQEN (Bitfield-Mask: 0x01) */ +/* ======================================================== CQADDR ========================================================= */ +#define IOM0_CQADDR_CQADDR28_Pos (28UL) /*!< IOM0 CQADDR: CQADDR28 (Bit 28) */ +#define IOM0_CQADDR_CQADDR28_Msk (0x10000000UL) /*!< IOM0 CQADDR: CQADDR28 (Bitfield-Mask: 0x01) */ +#define IOM0_CQADDR_CQADDR_Pos (2UL) /*!< IOM0 CQADDR: CQADDR (Bit 2) */ +#define IOM0_CQADDR_CQADDR_Msk (0xffffcUL) /*!< IOM0 CQADDR: CQADDR (Bitfield-Mask: 0x3ffff) */ +/* ======================================================== CQSTAT ========================================================= */ +#define IOM0_CQSTAT_CQERR_Pos (2UL) /*!< IOM0 CQSTAT: CQERR (Bit 2) */ +#define IOM0_CQSTAT_CQERR_Msk (0x4UL) /*!< IOM0 CQSTAT: CQERR (Bitfield-Mask: 0x01) */ +#define IOM0_CQSTAT_CQPAUSED_Pos (1UL) /*!< IOM0 CQSTAT: CQPAUSED (Bit 1) */ +#define IOM0_CQSTAT_CQPAUSED_Msk (0x2UL) /*!< IOM0 CQSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ +#define IOM0_CQSTAT_CQTIP_Pos (0UL) /*!< IOM0 CQSTAT: CQTIP (Bit 0) */ +#define IOM0_CQSTAT_CQTIP_Msk (0x1UL) /*!< IOM0 CQSTAT: CQTIP (Bitfield-Mask: 0x01) */ +/* ======================================================== CQFLAGS ======================================================== */ +#define IOM0_CQFLAGS_CQIRQMASK_Pos (16UL) /*!< IOM0 CQFLAGS: CQIRQMASK (Bit 16) */ +#define IOM0_CQFLAGS_CQIRQMASK_Msk (0xffff0000UL) /*!< IOM0 CQFLAGS: CQIRQMASK (Bitfield-Mask: 0xffff) */ +#define IOM0_CQFLAGS_CQFLAGS_Pos (0UL) /*!< IOM0 CQFLAGS: CQFLAGS (Bit 0) */ +#define IOM0_CQFLAGS_CQFLAGS_Msk (0xffffUL) /*!< IOM0 CQFLAGS: CQFLAGS (Bitfield-Mask: 0xffff) */ +/* ====================================================== CQSETCLEAR ======================================================= */ +#define IOM0_CQSETCLEAR_CQFCLR_Pos (16UL) /*!< IOM0 CQSETCLEAR: CQFCLR (Bit 16) */ +#define IOM0_CQSETCLEAR_CQFCLR_Msk (0xff0000UL) /*!< IOM0 CQSETCLEAR: CQFCLR (Bitfield-Mask: 0xff) */ +#define IOM0_CQSETCLEAR_CQFTGL_Pos (8UL) /*!< IOM0 CQSETCLEAR: CQFTGL (Bit 8) */ +#define IOM0_CQSETCLEAR_CQFTGL_Msk (0xff00UL) /*!< IOM0 CQSETCLEAR: CQFTGL (Bitfield-Mask: 0xff) */ +#define IOM0_CQSETCLEAR_CQFSET_Pos (0UL) /*!< IOM0 CQSETCLEAR: CQFSET (Bit 0) */ +#define IOM0_CQSETCLEAR_CQFSET_Msk (0xffUL) /*!< IOM0 CQSETCLEAR: CQFSET (Bitfield-Mask: 0xff) */ +/* ======================================================= CQPAUSEEN ======================================================= */ +#define IOM0_CQPAUSEEN_CQPEN_Pos (0UL) /*!< IOM0 CQPAUSEEN: CQPEN (Bit 0) */ +#define IOM0_CQPAUSEEN_CQPEN_Msk (0xffffUL) /*!< IOM0 CQPAUSEEN: CQPEN (Bitfield-Mask: 0xffff) */ +/* ======================================================= CQCURIDX ======================================================== */ +#define IOM0_CQCURIDX_CQCURIDX_Pos (0UL) /*!< IOM0 CQCURIDX: CQCURIDX (Bit 0) */ +#define IOM0_CQCURIDX_CQCURIDX_Msk (0xffUL) /*!< IOM0 CQCURIDX: CQCURIDX (Bitfield-Mask: 0xff) */ +/* ======================================================= CQENDIDX ======================================================== */ +#define IOM0_CQENDIDX_CQENDIDX_Pos (0UL) /*!< IOM0 CQENDIDX: CQENDIDX (Bit 0) */ +#define IOM0_CQENDIDX_CQENDIDX_Msk (0xffUL) /*!< IOM0 CQENDIDX: CQENDIDX (Bitfield-Mask: 0xff) */ +/* ======================================================== STATUS ========================================================= */ +#define IOM0_STATUS_IDLEST_Pos (2UL) /*!< IOM0 STATUS: IDLEST (Bit 2) */ +#define IOM0_STATUS_IDLEST_Msk (0x4UL) /*!< IOM0 STATUS: IDLEST (Bitfield-Mask: 0x01) */ +#define IOM0_STATUS_CMDACT_Pos (1UL) /*!< IOM0 STATUS: CMDACT (Bit 1) */ +#define IOM0_STATUS_CMDACT_Msk (0x2UL) /*!< IOM0 STATUS: CMDACT (Bitfield-Mask: 0x01) */ +#define IOM0_STATUS_ERR_Pos (0UL) /*!< IOM0 STATUS: ERR (Bit 0) */ +#define IOM0_STATUS_ERR_Msk (0x1UL) /*!< IOM0 STATUS: ERR (Bitfield-Mask: 0x01) */ +/* ======================================================== MSPICFG ======================================================== */ +#define IOM0_MSPICFG_MSPIRST_Pos (30UL) /*!< IOM0 MSPICFG: MSPIRST (Bit 30) */ +#define IOM0_MSPICFG_MSPIRST_Msk (0x40000000UL) /*!< IOM0 MSPICFG: MSPIRST (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_DOUTDLY_Pos (27UL) /*!< IOM0 MSPICFG: DOUTDLY (Bit 27) */ +#define IOM0_MSPICFG_DOUTDLY_Msk (0x38000000UL) /*!< IOM0 MSPICFG: DOUTDLY (Bitfield-Mask: 0x07) */ +#define IOM0_MSPICFG_DINDLY_Pos (24UL) /*!< IOM0 MSPICFG: DINDLY (Bit 24) */ +#define IOM0_MSPICFG_DINDLY_Msk (0x7000000UL) /*!< IOM0 MSPICFG: DINDLY (Bitfield-Mask: 0x07) */ +#define IOM0_MSPICFG_SPILSB_Pos (23UL) /*!< IOM0 MSPICFG: SPILSB (Bit 23) */ +#define IOM0_MSPICFG_SPILSB_Msk (0x800000UL) /*!< IOM0 MSPICFG: SPILSB (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_RDFCPOL_Pos (22UL) /*!< IOM0 MSPICFG: RDFCPOL (Bit 22) */ +#define IOM0_MSPICFG_RDFCPOL_Msk (0x400000UL) /*!< IOM0 MSPICFG: RDFCPOL (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_WTFCPOL_Pos (21UL) /*!< IOM0 MSPICFG: WTFCPOL (Bit 21) */ +#define IOM0_MSPICFG_WTFCPOL_Msk (0x200000UL) /*!< IOM0 MSPICFG: WTFCPOL (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_WTFCIRQ_Pos (20UL) /*!< IOM0 MSPICFG: WTFCIRQ (Bit 20) */ +#define IOM0_MSPICFG_WTFCIRQ_Msk (0x100000UL) /*!< IOM0 MSPICFG: WTFCIRQ (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_MOSIINV_Pos (18UL) /*!< IOM0 MSPICFG: MOSIINV (Bit 18) */ +#define IOM0_MSPICFG_MOSIINV_Msk (0x40000UL) /*!< IOM0 MSPICFG: MOSIINV (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_RDFC_Pos (17UL) /*!< IOM0 MSPICFG: RDFC (Bit 17) */ +#define IOM0_MSPICFG_RDFC_Msk (0x20000UL) /*!< IOM0 MSPICFG: RDFC (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_WTFC_Pos (16UL) /*!< IOM0 MSPICFG: WTFC (Bit 16) */ +#define IOM0_MSPICFG_WTFC_Msk (0x10000UL) /*!< IOM0 MSPICFG: WTFC (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_FULLDUP_Pos (2UL) /*!< IOM0 MSPICFG: FULLDUP (Bit 2) */ +#define IOM0_MSPICFG_FULLDUP_Msk (0x4UL) /*!< IOM0 MSPICFG: FULLDUP (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_SPHA_Pos (1UL) /*!< IOM0 MSPICFG: SPHA (Bit 1) */ +#define IOM0_MSPICFG_SPHA_Msk (0x2UL) /*!< IOM0 MSPICFG: SPHA (Bitfield-Mask: 0x01) */ +#define IOM0_MSPICFG_SPOL_Pos (0UL) /*!< IOM0 MSPICFG: SPOL (Bit 0) */ +#define IOM0_MSPICFG_SPOL_Msk (0x1UL) /*!< IOM0 MSPICFG: SPOL (Bitfield-Mask: 0x01) */ +/* ======================================================== MI2CCFG ======================================================== */ +#define IOM0_MI2CCFG_STRDIS_Pos (24UL) /*!< IOM0 MI2CCFG: STRDIS (Bit 24) */ +#define IOM0_MI2CCFG_STRDIS_Msk (0x1000000UL) /*!< IOM0 MI2CCFG: STRDIS (Bitfield-Mask: 0x01) */ +#define IOM0_MI2CCFG_SMPCNT_Pos (16UL) /*!< IOM0 MI2CCFG: SMPCNT (Bit 16) */ +#define IOM0_MI2CCFG_SMPCNT_Msk (0xff0000UL) /*!< IOM0 MI2CCFG: SMPCNT (Bitfield-Mask: 0xff) */ +#define IOM0_MI2CCFG_SDAENDLY_Pos (12UL) /*!< IOM0 MI2CCFG: SDAENDLY (Bit 12) */ +#define IOM0_MI2CCFG_SDAENDLY_Msk (0xf000UL) /*!< IOM0 MI2CCFG: SDAENDLY (Bitfield-Mask: 0x0f) */ +#define IOM0_MI2CCFG_SCLENDLY_Pos (8UL) /*!< IOM0 MI2CCFG: SCLENDLY (Bit 8) */ +#define IOM0_MI2CCFG_SCLENDLY_Msk (0xf00UL) /*!< IOM0 MI2CCFG: SCLENDLY (Bitfield-Mask: 0x0f) */ +#define IOM0_MI2CCFG_MI2CRST_Pos (6UL) /*!< IOM0 MI2CCFG: MI2CRST (Bit 6) */ +#define IOM0_MI2CCFG_MI2CRST_Msk (0x40UL) /*!< IOM0 MI2CCFG: MI2CRST (Bitfield-Mask: 0x01) */ +#define IOM0_MI2CCFG_SDADLY_Pos (4UL) /*!< IOM0 MI2CCFG: SDADLY (Bit 4) */ +#define IOM0_MI2CCFG_SDADLY_Msk (0x30UL) /*!< IOM0 MI2CCFG: SDADLY (Bitfield-Mask: 0x03) */ +#define IOM0_MI2CCFG_ARBEN_Pos (2UL) /*!< IOM0 MI2CCFG: ARBEN (Bit 2) */ +#define IOM0_MI2CCFG_ARBEN_Msk (0x4UL) /*!< IOM0 MI2CCFG: ARBEN (Bitfield-Mask: 0x01) */ +#define IOM0_MI2CCFG_I2CLSB_Pos (1UL) /*!< IOM0 MI2CCFG: I2CLSB (Bit 1) */ +#define IOM0_MI2CCFG_I2CLSB_Msk (0x2UL) /*!< IOM0 MI2CCFG: I2CLSB (Bitfield-Mask: 0x01) */ +#define IOM0_MI2CCFG_ADDRSZ_Pos (0UL) /*!< IOM0 MI2CCFG: ADDRSZ (Bit 0) */ +#define IOM0_MI2CCFG_ADDRSZ_Msk (0x1UL) /*!< IOM0 MI2CCFG: ADDRSZ (Bitfield-Mask: 0x01) */ +/* ======================================================== DEVCFG ========================================================= */ +#define IOM0_DEVCFG_DEVADDR_Pos (0UL) /*!< IOM0 DEVCFG: DEVADDR (Bit 0) */ +#define IOM0_DEVCFG_DEVADDR_Msk (0x3ffUL) /*!< IOM0 DEVCFG: DEVADDR (Bitfield-Mask: 0x3ff) */ +/* ======================================================== IOMDBG ========================================================= */ +#define IOM0_IOMDBG_DBGDATA_Pos (3UL) /*!< IOM0 IOMDBG: DBGDATA (Bit 3) */ +#define IOM0_IOMDBG_DBGDATA_Msk (0xfffffff8UL) /*!< IOM0 IOMDBG: DBGDATA (Bitfield-Mask: 0x1fffffff) */ +#define IOM0_IOMDBG_APBCLKON_Pos (2UL) /*!< IOM0 IOMDBG: APBCLKON (Bit 2) */ +#define IOM0_IOMDBG_APBCLKON_Msk (0x4UL) /*!< IOM0 IOMDBG: APBCLKON (Bitfield-Mask: 0x01) */ +#define IOM0_IOMDBG_IOCLKON_Pos (1UL) /*!< IOM0 IOMDBG: IOCLKON (Bit 1) */ +#define IOM0_IOMDBG_IOCLKON_Msk (0x2UL) /*!< IOM0 IOMDBG: IOCLKON (Bitfield-Mask: 0x01) */ +#define IOM0_IOMDBG_DBGEN_Pos (0UL) /*!< IOM0 IOMDBG: DBGEN (Bit 0) */ +#define IOM0_IOMDBG_DBGEN_Msk (0x1UL) /*!< IOM0 IOMDBG: DBGEN (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ IOSLAVE ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== FIFOPTR ======================================================== */ +#define IOSLAVE_FIFOPTR_FIFOSIZ_Pos (8UL) /*!< IOSLAVE FIFOPTR: FIFOSIZ (Bit 8) */ +#define IOSLAVE_FIFOPTR_FIFOSIZ_Msk (0xff00UL) /*!< IOSLAVE FIFOPTR: FIFOSIZ (Bitfield-Mask: 0xff) */ +#define IOSLAVE_FIFOPTR_FIFOPTR_Pos (0UL) /*!< IOSLAVE FIFOPTR: FIFOPTR (Bit 0) */ +#define IOSLAVE_FIFOPTR_FIFOPTR_Msk (0xffUL) /*!< IOSLAVE FIFOPTR: FIFOPTR (Bitfield-Mask: 0xff) */ +/* ======================================================== FIFOCFG ======================================================== */ +#define IOSLAVE_FIFOCFG_ROBASE_Pos (24UL) /*!< IOSLAVE FIFOCFG: ROBASE (Bit 24) */ +#define IOSLAVE_FIFOCFG_ROBASE_Msk (0x3f000000UL) /*!< IOSLAVE FIFOCFG: ROBASE (Bitfield-Mask: 0x3f) */ +#define IOSLAVE_FIFOCFG_FIFOMAX_Pos (8UL) /*!< IOSLAVE FIFOCFG: FIFOMAX (Bit 8) */ +#define IOSLAVE_FIFOCFG_FIFOMAX_Msk (0x3f00UL) /*!< IOSLAVE FIFOCFG: FIFOMAX (Bitfield-Mask: 0x3f) */ +#define IOSLAVE_FIFOCFG_FIFOBASE_Pos (0UL) /*!< IOSLAVE FIFOCFG: FIFOBASE (Bit 0) */ +#define IOSLAVE_FIFOCFG_FIFOBASE_Msk (0x1fUL) /*!< IOSLAVE FIFOCFG: FIFOBASE (Bitfield-Mask: 0x1f) */ +/* ======================================================== FIFOTHR ======================================================== */ +#define IOSLAVE_FIFOTHR_FIFOTHR_Pos (0UL) /*!< IOSLAVE FIFOTHR: FIFOTHR (Bit 0) */ +#define IOSLAVE_FIFOTHR_FIFOTHR_Msk (0xffUL) /*!< IOSLAVE FIFOTHR: FIFOTHR (Bitfield-Mask: 0xff) */ +/* ========================================================= FUPD ========================================================== */ +#define IOSLAVE_FUPD_IOREAD_Pos (1UL) /*!< IOSLAVE FUPD: IOREAD (Bit 1) */ +#define IOSLAVE_FUPD_IOREAD_Msk (0x2UL) /*!< IOSLAVE FUPD: IOREAD (Bitfield-Mask: 0x01) */ +#define IOSLAVE_FUPD_FIFOUPD_Pos (0UL) /*!< IOSLAVE FUPD: FIFOUPD (Bit 0) */ +#define IOSLAVE_FUPD_FIFOUPD_Msk (0x1UL) /*!< IOSLAVE FUPD: FIFOUPD (Bitfield-Mask: 0x01) */ +/* ======================================================== FIFOCTR ======================================================== */ +#define IOSLAVE_FIFOCTR_FIFOCTR_Pos (0UL) /*!< IOSLAVE FIFOCTR: FIFOCTR (Bit 0) */ +#define IOSLAVE_FIFOCTR_FIFOCTR_Msk (0x3ffUL) /*!< IOSLAVE FIFOCTR: FIFOCTR (Bitfield-Mask: 0x3ff) */ +/* ======================================================== FIFOINC ======================================================== */ +#define IOSLAVE_FIFOINC_FIFOINC_Pos (0UL) /*!< IOSLAVE FIFOINC: FIFOINC (Bit 0) */ +#define IOSLAVE_FIFOINC_FIFOINC_Msk (0x3ffUL) /*!< IOSLAVE FIFOINC: FIFOINC (Bitfield-Mask: 0x3ff) */ +/* ========================================================== CFG ========================================================== */ +#define IOSLAVE_CFG_IFCEN_Pos (31UL) /*!< IOSLAVE CFG: IFCEN (Bit 31) */ +#define IOSLAVE_CFG_IFCEN_Msk (0x80000000UL) /*!< IOSLAVE CFG: IFCEN (Bitfield-Mask: 0x01) */ +#define IOSLAVE_CFG_I2CADDR_Pos (8UL) /*!< IOSLAVE CFG: I2CADDR (Bit 8) */ +#define IOSLAVE_CFG_I2CADDR_Msk (0xfff00UL) /*!< IOSLAVE CFG: I2CADDR (Bitfield-Mask: 0xfff) */ +#define IOSLAVE_CFG_STARTRD_Pos (4UL) /*!< IOSLAVE CFG: STARTRD (Bit 4) */ +#define IOSLAVE_CFG_STARTRD_Msk (0x10UL) /*!< IOSLAVE CFG: STARTRD (Bitfield-Mask: 0x01) */ +#define IOSLAVE_CFG_LSB_Pos (2UL) /*!< IOSLAVE CFG: LSB (Bit 2) */ +#define IOSLAVE_CFG_LSB_Msk (0x4UL) /*!< IOSLAVE CFG: LSB (Bitfield-Mask: 0x01) */ +#define IOSLAVE_CFG_SPOL_Pos (1UL) /*!< IOSLAVE CFG: SPOL (Bit 1) */ +#define IOSLAVE_CFG_SPOL_Msk (0x2UL) /*!< IOSLAVE CFG: SPOL (Bitfield-Mask: 0x01) */ +#define IOSLAVE_CFG_IFCSEL_Pos (0UL) /*!< IOSLAVE CFG: IFCSEL (Bit 0) */ +#define IOSLAVE_CFG_IFCSEL_Msk (0x1UL) /*!< IOSLAVE CFG: IFCSEL (Bitfield-Mask: 0x01) */ +/* ========================================================= PRENC ========================================================= */ +#define IOSLAVE_PRENC_PRENC_Pos (0UL) /*!< IOSLAVE PRENC: PRENC (Bit 0) */ +#define IOSLAVE_PRENC_PRENC_Msk (0x1fUL) /*!< IOSLAVE PRENC: PRENC (Bitfield-Mask: 0x1f) */ +/* ======================================================= IOINTCTL ======================================================== */ +#define IOSLAVE_IOINTCTL_IOINTSET_Pos (24UL) /*!< IOSLAVE IOINTCTL: IOINTSET (Bit 24) */ +#define IOSLAVE_IOINTCTL_IOINTSET_Msk (0xff000000UL) /*!< IOSLAVE IOINTCTL: IOINTSET (Bitfield-Mask: 0xff) */ +#define IOSLAVE_IOINTCTL_IOINTCLR_Pos (16UL) /*!< IOSLAVE IOINTCTL: IOINTCLR (Bit 16) */ +#define IOSLAVE_IOINTCTL_IOINTCLR_Msk (0x10000UL) /*!< IOSLAVE IOINTCTL: IOINTCLR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_IOINTCTL_IOINT_Pos (8UL) /*!< IOSLAVE IOINTCTL: IOINT (Bit 8) */ +#define IOSLAVE_IOINTCTL_IOINT_Msk (0xff00UL) /*!< IOSLAVE IOINTCTL: IOINT (Bitfield-Mask: 0xff) */ +#define IOSLAVE_IOINTCTL_IOINTEN_Pos (0UL) /*!< IOSLAVE IOINTCTL: IOINTEN (Bit 0) */ +#define IOSLAVE_IOINTCTL_IOINTEN_Msk (0xffUL) /*!< IOSLAVE IOINTCTL: IOINTEN (Bitfield-Mask: 0xff) */ +/* ======================================================== GENADD ========================================================= */ +#define IOSLAVE_GENADD_GADATA_Pos (0UL) /*!< IOSLAVE GENADD: GADATA (Bit 0) */ +#define IOSLAVE_GENADD_GADATA_Msk (0xffUL) /*!< IOSLAVE GENADD: GADATA (Bitfield-Mask: 0xff) */ +/* ========================================================= INTEN ========================================================= */ +#define IOSLAVE_INTEN_XCMPWR_Pos (9UL) /*!< IOSLAVE INTEN: XCMPWR (Bit 9) */ +#define IOSLAVE_INTEN_XCMPWR_Msk (0x200UL) /*!< IOSLAVE INTEN: XCMPWR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTEN_XCMPWF_Pos (8UL) /*!< IOSLAVE INTEN: XCMPWF (Bit 8) */ +#define IOSLAVE_INTEN_XCMPWF_Msk (0x100UL) /*!< IOSLAVE INTEN: XCMPWF (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTEN_XCMPRR_Pos (7UL) /*!< IOSLAVE INTEN: XCMPRR (Bit 7) */ +#define IOSLAVE_INTEN_XCMPRR_Msk (0x80UL) /*!< IOSLAVE INTEN: XCMPRR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTEN_XCMPRF_Pos (6UL) /*!< IOSLAVE INTEN: XCMPRF (Bit 6) */ +#define IOSLAVE_INTEN_XCMPRF_Msk (0x40UL) /*!< IOSLAVE INTEN: XCMPRF (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTEN_IOINTW_Pos (5UL) /*!< IOSLAVE INTEN: IOINTW (Bit 5) */ +#define IOSLAVE_INTEN_IOINTW_Msk (0x20UL) /*!< IOSLAVE INTEN: IOINTW (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTEN_GENAD_Pos (4UL) /*!< IOSLAVE INTEN: GENAD (Bit 4) */ +#define IOSLAVE_INTEN_GENAD_Msk (0x10UL) /*!< IOSLAVE INTEN: GENAD (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTEN_FRDERR_Pos (3UL) /*!< IOSLAVE INTEN: FRDERR (Bit 3) */ +#define IOSLAVE_INTEN_FRDERR_Msk (0x8UL) /*!< IOSLAVE INTEN: FRDERR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTEN_FUNDFL_Pos (2UL) /*!< IOSLAVE INTEN: FUNDFL (Bit 2) */ +#define IOSLAVE_INTEN_FUNDFL_Msk (0x4UL) /*!< IOSLAVE INTEN: FUNDFL (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTEN_FOVFL_Pos (1UL) /*!< IOSLAVE INTEN: FOVFL (Bit 1) */ +#define IOSLAVE_INTEN_FOVFL_Msk (0x2UL) /*!< IOSLAVE INTEN: FOVFL (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTEN_FSIZE_Pos (0UL) /*!< IOSLAVE INTEN: FSIZE (Bit 0) */ +#define IOSLAVE_INTEN_FSIZE_Msk (0x1UL) /*!< IOSLAVE INTEN: FSIZE (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define IOSLAVE_INTSTAT_XCMPWR_Pos (9UL) /*!< IOSLAVE INTSTAT: XCMPWR (Bit 9) */ +#define IOSLAVE_INTSTAT_XCMPWR_Msk (0x200UL) /*!< IOSLAVE INTSTAT: XCMPWR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSTAT_XCMPWF_Pos (8UL) /*!< IOSLAVE INTSTAT: XCMPWF (Bit 8) */ +#define IOSLAVE_INTSTAT_XCMPWF_Msk (0x100UL) /*!< IOSLAVE INTSTAT: XCMPWF (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSTAT_XCMPRR_Pos (7UL) /*!< IOSLAVE INTSTAT: XCMPRR (Bit 7) */ +#define IOSLAVE_INTSTAT_XCMPRR_Msk (0x80UL) /*!< IOSLAVE INTSTAT: XCMPRR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSTAT_XCMPRF_Pos (6UL) /*!< IOSLAVE INTSTAT: XCMPRF (Bit 6) */ +#define IOSLAVE_INTSTAT_XCMPRF_Msk (0x40UL) /*!< IOSLAVE INTSTAT: XCMPRF (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSTAT_IOINTW_Pos (5UL) /*!< IOSLAVE INTSTAT: IOINTW (Bit 5) */ +#define IOSLAVE_INTSTAT_IOINTW_Msk (0x20UL) /*!< IOSLAVE INTSTAT: IOINTW (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSTAT_GENAD_Pos (4UL) /*!< IOSLAVE INTSTAT: GENAD (Bit 4) */ +#define IOSLAVE_INTSTAT_GENAD_Msk (0x10UL) /*!< IOSLAVE INTSTAT: GENAD (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSTAT_FRDERR_Pos (3UL) /*!< IOSLAVE INTSTAT: FRDERR (Bit 3) */ +#define IOSLAVE_INTSTAT_FRDERR_Msk (0x8UL) /*!< IOSLAVE INTSTAT: FRDERR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSTAT_FUNDFL_Pos (2UL) /*!< IOSLAVE INTSTAT: FUNDFL (Bit 2) */ +#define IOSLAVE_INTSTAT_FUNDFL_Msk (0x4UL) /*!< IOSLAVE INTSTAT: FUNDFL (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSTAT_FOVFL_Pos (1UL) /*!< IOSLAVE INTSTAT: FOVFL (Bit 1) */ +#define IOSLAVE_INTSTAT_FOVFL_Msk (0x2UL) /*!< IOSLAVE INTSTAT: FOVFL (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSTAT_FSIZE_Pos (0UL) /*!< IOSLAVE INTSTAT: FSIZE (Bit 0) */ +#define IOSLAVE_INTSTAT_FSIZE_Msk (0x1UL) /*!< IOSLAVE INTSTAT: FSIZE (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define IOSLAVE_INTCLR_XCMPWR_Pos (9UL) /*!< IOSLAVE INTCLR: XCMPWR (Bit 9) */ +#define IOSLAVE_INTCLR_XCMPWR_Msk (0x200UL) /*!< IOSLAVE INTCLR: XCMPWR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTCLR_XCMPWF_Pos (8UL) /*!< IOSLAVE INTCLR: XCMPWF (Bit 8) */ +#define IOSLAVE_INTCLR_XCMPWF_Msk (0x100UL) /*!< IOSLAVE INTCLR: XCMPWF (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTCLR_XCMPRR_Pos (7UL) /*!< IOSLAVE INTCLR: XCMPRR (Bit 7) */ +#define IOSLAVE_INTCLR_XCMPRR_Msk (0x80UL) /*!< IOSLAVE INTCLR: XCMPRR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTCLR_XCMPRF_Pos (6UL) /*!< IOSLAVE INTCLR: XCMPRF (Bit 6) */ +#define IOSLAVE_INTCLR_XCMPRF_Msk (0x40UL) /*!< IOSLAVE INTCLR: XCMPRF (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTCLR_IOINTW_Pos (5UL) /*!< IOSLAVE INTCLR: IOINTW (Bit 5) */ +#define IOSLAVE_INTCLR_IOINTW_Msk (0x20UL) /*!< IOSLAVE INTCLR: IOINTW (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTCLR_GENAD_Pos (4UL) /*!< IOSLAVE INTCLR: GENAD (Bit 4) */ +#define IOSLAVE_INTCLR_GENAD_Msk (0x10UL) /*!< IOSLAVE INTCLR: GENAD (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTCLR_FRDERR_Pos (3UL) /*!< IOSLAVE INTCLR: FRDERR (Bit 3) */ +#define IOSLAVE_INTCLR_FRDERR_Msk (0x8UL) /*!< IOSLAVE INTCLR: FRDERR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTCLR_FUNDFL_Pos (2UL) /*!< IOSLAVE INTCLR: FUNDFL (Bit 2) */ +#define IOSLAVE_INTCLR_FUNDFL_Msk (0x4UL) /*!< IOSLAVE INTCLR: FUNDFL (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTCLR_FOVFL_Pos (1UL) /*!< IOSLAVE INTCLR: FOVFL (Bit 1) */ +#define IOSLAVE_INTCLR_FOVFL_Msk (0x2UL) /*!< IOSLAVE INTCLR: FOVFL (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTCLR_FSIZE_Pos (0UL) /*!< IOSLAVE INTCLR: FSIZE (Bit 0) */ +#define IOSLAVE_INTCLR_FSIZE_Msk (0x1UL) /*!< IOSLAVE INTCLR: FSIZE (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define IOSLAVE_INTSET_XCMPWR_Pos (9UL) /*!< IOSLAVE INTSET: XCMPWR (Bit 9) */ +#define IOSLAVE_INTSET_XCMPWR_Msk (0x200UL) /*!< IOSLAVE INTSET: XCMPWR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSET_XCMPWF_Pos (8UL) /*!< IOSLAVE INTSET: XCMPWF (Bit 8) */ +#define IOSLAVE_INTSET_XCMPWF_Msk (0x100UL) /*!< IOSLAVE INTSET: XCMPWF (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSET_XCMPRR_Pos (7UL) /*!< IOSLAVE INTSET: XCMPRR (Bit 7) */ +#define IOSLAVE_INTSET_XCMPRR_Msk (0x80UL) /*!< IOSLAVE INTSET: XCMPRR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSET_XCMPRF_Pos (6UL) /*!< IOSLAVE INTSET: XCMPRF (Bit 6) */ +#define IOSLAVE_INTSET_XCMPRF_Msk (0x40UL) /*!< IOSLAVE INTSET: XCMPRF (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSET_IOINTW_Pos (5UL) /*!< IOSLAVE INTSET: IOINTW (Bit 5) */ +#define IOSLAVE_INTSET_IOINTW_Msk (0x20UL) /*!< IOSLAVE INTSET: IOINTW (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSET_GENAD_Pos (4UL) /*!< IOSLAVE INTSET: GENAD (Bit 4) */ +#define IOSLAVE_INTSET_GENAD_Msk (0x10UL) /*!< IOSLAVE INTSET: GENAD (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSET_FRDERR_Pos (3UL) /*!< IOSLAVE INTSET: FRDERR (Bit 3) */ +#define IOSLAVE_INTSET_FRDERR_Msk (0x8UL) /*!< IOSLAVE INTSET: FRDERR (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSET_FUNDFL_Pos (2UL) /*!< IOSLAVE INTSET: FUNDFL (Bit 2) */ +#define IOSLAVE_INTSET_FUNDFL_Msk (0x4UL) /*!< IOSLAVE INTSET: FUNDFL (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSET_FOVFL_Pos (1UL) /*!< IOSLAVE INTSET: FOVFL (Bit 1) */ +#define IOSLAVE_INTSET_FOVFL_Msk (0x2UL) /*!< IOSLAVE INTSET: FOVFL (Bitfield-Mask: 0x01) */ +#define IOSLAVE_INTSET_FSIZE_Pos (0UL) /*!< IOSLAVE INTSET: FSIZE (Bit 0) */ +#define IOSLAVE_INTSET_FSIZE_Msk (0x1UL) /*!< IOSLAVE INTSET: FSIZE (Bitfield-Mask: 0x01) */ +/* ====================================================== REGACCINTEN ====================================================== */ +#define IOSLAVE_REGACCINTEN_REGACC_Pos (0UL) /*!< IOSLAVE REGACCINTEN: REGACC (Bit 0) */ +#define IOSLAVE_REGACCINTEN_REGACC_Msk (0xffffffffUL) /*!< IOSLAVE REGACCINTEN: REGACC (Bitfield-Mask: 0xffffffff) */ +/* ===================================================== REGACCINTSTAT ===================================================== */ +#define IOSLAVE_REGACCINTSTAT_REGACC_Pos (0UL) /*!< IOSLAVE REGACCINTSTAT: REGACC (Bit 0) */ +#define IOSLAVE_REGACCINTSTAT_REGACC_Msk (0xffffffffUL) /*!< IOSLAVE REGACCINTSTAT: REGACC (Bitfield-Mask: 0xffffffff) */ +/* ===================================================== REGACCINTCLR ====================================================== */ +#define IOSLAVE_REGACCINTCLR_REGACC_Pos (0UL) /*!< IOSLAVE REGACCINTCLR: REGACC (Bit 0) */ +#define IOSLAVE_REGACCINTCLR_REGACC_Msk (0xffffffffUL) /*!< IOSLAVE REGACCINTCLR: REGACC (Bitfield-Mask: 0xffffffff) */ +/* ===================================================== REGACCINTSET ====================================================== */ +#define IOSLAVE_REGACCINTSET_REGACC_Pos (0UL) /*!< IOSLAVE REGACCINTSET: REGACC (Bit 0) */ +#define IOSLAVE_REGACCINTSET_REGACC_Msk (0xffffffffUL) /*!< IOSLAVE REGACCINTSET: REGACC (Bitfield-Mask: 0xffffffff) */ + + +/* =========================================================================================================================== */ +/* ================ MCUCTRL ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== CHIPPN ========================================================= */ +#define MCUCTRL_CHIPPN_PARTNUM_Pos (0UL) /*!< MCUCTRL CHIPPN: PARTNUM (Bit 0) */ +#define MCUCTRL_CHIPPN_PARTNUM_Msk (0xffffffffUL) /*!< MCUCTRL CHIPPN: PARTNUM (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== CHIPID0 ======================================================== */ +#define MCUCTRL_CHIPID0_CHIPID0_Pos (0UL) /*!< MCUCTRL CHIPID0: CHIPID0 (Bit 0) */ +#define MCUCTRL_CHIPID0_CHIPID0_Msk (0xffffffffUL) /*!< MCUCTRL CHIPID0: CHIPID0 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== CHIPID1 ======================================================== */ +#define MCUCTRL_CHIPID1_CHIPID1_Pos (0UL) /*!< MCUCTRL CHIPID1: CHIPID1 (Bit 0) */ +#define MCUCTRL_CHIPID1_CHIPID1_Msk (0xffffffffUL) /*!< MCUCTRL CHIPID1: CHIPID1 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== CHIPREV ======================================================== */ +#define MCUCTRL_CHIPREV_SIPART_Pos (8UL) /*!< MCUCTRL CHIPREV: SIPART (Bit 8) */ +#define MCUCTRL_CHIPREV_SIPART_Msk (0xfff00UL) /*!< MCUCTRL CHIPREV: SIPART (Bitfield-Mask: 0xfff) */ +#define MCUCTRL_CHIPREV_REVMAJ_Pos (4UL) /*!< MCUCTRL CHIPREV: REVMAJ (Bit 4) */ +#define MCUCTRL_CHIPREV_REVMAJ_Msk (0xf0UL) /*!< MCUCTRL CHIPREV: REVMAJ (Bitfield-Mask: 0x0f) */ +#define MCUCTRL_CHIPREV_REVMIN_Pos (0UL) /*!< MCUCTRL CHIPREV: REVMIN (Bit 0) */ +#define MCUCTRL_CHIPREV_REVMIN_Msk (0xfUL) /*!< MCUCTRL CHIPREV: REVMIN (Bitfield-Mask: 0x0f) */ +/* ======================================================= VENDORID ======================================================== */ +#define MCUCTRL_VENDORID_VENDORID_Pos (0UL) /*!< MCUCTRL VENDORID: VENDORID (Bit 0) */ +#define MCUCTRL_VENDORID_VENDORID_Msk (0xffffffffUL) /*!< MCUCTRL VENDORID: VENDORID (Bitfield-Mask: 0xffffffff) */ +/* ========================================================== SKU ========================================================== */ +#define MCUCTRL_SKU_SECBOOT_Pos (2UL) /*!< MCUCTRL SKU: SECBOOT (Bit 2) */ +#define MCUCTRL_SKU_SECBOOT_Msk (0x4UL) /*!< MCUCTRL SKU: SECBOOT (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SKU_ALLOWBLE_Pos (1UL) /*!< MCUCTRL SKU: ALLOWBLE (Bit 1) */ +#define MCUCTRL_SKU_ALLOWBLE_Msk (0x2UL) /*!< MCUCTRL SKU: ALLOWBLE (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SKU_ALLOWBURST_Pos (0UL) /*!< MCUCTRL SKU: ALLOWBURST (Bit 0) */ +#define MCUCTRL_SKU_ALLOWBURST_Msk (0x1UL) /*!< MCUCTRL SKU: ALLOWBURST (Bitfield-Mask: 0x01) */ +/* ===================================================== FEATUREENABLE ===================================================== */ +#define MCUCTRL_FEATUREENABLE_BURSTAVAIL_Pos (6UL) /*!< MCUCTRL FEATUREENABLE: BURSTAVAIL (Bit 6) */ +#define MCUCTRL_FEATUREENABLE_BURSTAVAIL_Msk (0x40UL) /*!< MCUCTRL FEATUREENABLE: BURSTAVAIL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_FEATUREENABLE_BURSTACK_Pos (5UL) /*!< MCUCTRL FEATUREENABLE: BURSTACK (Bit 5) */ +#define MCUCTRL_FEATUREENABLE_BURSTACK_Msk (0x20UL) /*!< MCUCTRL FEATUREENABLE: BURSTACK (Bitfield-Mask: 0x01) */ +#define MCUCTRL_FEATUREENABLE_BURSTREQ_Pos (4UL) /*!< MCUCTRL FEATUREENABLE: BURSTREQ (Bit 4) */ +#define MCUCTRL_FEATUREENABLE_BURSTREQ_Msk (0x10UL) /*!< MCUCTRL FEATUREENABLE: BURSTREQ (Bitfield-Mask: 0x01) */ +#define MCUCTRL_FEATUREENABLE_BLEAVAIL_Pos (2UL) /*!< MCUCTRL FEATUREENABLE: BLEAVAIL (Bit 2) */ +#define MCUCTRL_FEATUREENABLE_BLEAVAIL_Msk (0x4UL) /*!< MCUCTRL FEATUREENABLE: BLEAVAIL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_FEATUREENABLE_BLEACK_Pos (1UL) /*!< MCUCTRL FEATUREENABLE: BLEACK (Bit 1) */ +#define MCUCTRL_FEATUREENABLE_BLEACK_Msk (0x2UL) /*!< MCUCTRL FEATUREENABLE: BLEACK (Bitfield-Mask: 0x01) */ +#define MCUCTRL_FEATUREENABLE_BLEREQ_Pos (0UL) /*!< MCUCTRL FEATUREENABLE: BLEREQ (Bit 0) */ +#define MCUCTRL_FEATUREENABLE_BLEREQ_Msk (0x1UL) /*!< MCUCTRL FEATUREENABLE: BLEREQ (Bitfield-Mask: 0x01) */ +/* ======================================================= DEBUGGER ======================================================== */ +#define MCUCTRL_DEBUGGER_LOCKOUT_Pos (0UL) /*!< MCUCTRL DEBUGGER: LOCKOUT (Bit 0) */ +#define MCUCTRL_DEBUGGER_LOCKOUT_Msk (0x1UL) /*!< MCUCTRL DEBUGGER: LOCKOUT (Bitfield-Mask: 0x01) */ +/* ======================================================== BODCTRL ======================================================== */ +#define MCUCTRL_BODCTRL_BODHVREFSEL_Pos (5UL) /*!< MCUCTRL BODCTRL: BODHVREFSEL (Bit 5) */ +#define MCUCTRL_BODCTRL_BODHVREFSEL_Msk (0x20UL) /*!< MCUCTRL BODCTRL: BODHVREFSEL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_BODCTRL_BODLVREFSEL_Pos (4UL) /*!< MCUCTRL BODCTRL: BODLVREFSEL (Bit 4) */ +#define MCUCTRL_BODCTRL_BODLVREFSEL_Msk (0x10UL) /*!< MCUCTRL BODCTRL: BODLVREFSEL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_BODCTRL_BODFPWD_Pos (3UL) /*!< MCUCTRL BODCTRL: BODFPWD (Bit 3) */ +#define MCUCTRL_BODCTRL_BODFPWD_Msk (0x8UL) /*!< MCUCTRL BODCTRL: BODFPWD (Bitfield-Mask: 0x01) */ +#define MCUCTRL_BODCTRL_BODCPWD_Pos (2UL) /*!< MCUCTRL BODCTRL: BODCPWD (Bit 2) */ +#define MCUCTRL_BODCTRL_BODCPWD_Msk (0x4UL) /*!< MCUCTRL BODCTRL: BODCPWD (Bitfield-Mask: 0x01) */ +#define MCUCTRL_BODCTRL_BODHPWD_Pos (1UL) /*!< MCUCTRL BODCTRL: BODHPWD (Bit 1) */ +#define MCUCTRL_BODCTRL_BODHPWD_Msk (0x2UL) /*!< MCUCTRL BODCTRL: BODHPWD (Bitfield-Mask: 0x01) */ +#define MCUCTRL_BODCTRL_BODLPWD_Pos (0UL) /*!< MCUCTRL BODCTRL: BODLPWD (Bit 0) */ +#define MCUCTRL_BODCTRL_BODLPWD_Msk (0x1UL) /*!< MCUCTRL BODCTRL: BODLPWD (Bitfield-Mask: 0x01) */ +/* ======================================================= ADCPWRDLY ======================================================= */ +#define MCUCTRL_ADCPWRDLY_ADCPWR1_Pos (8UL) /*!< MCUCTRL ADCPWRDLY: ADCPWR1 (Bit 8) */ +#define MCUCTRL_ADCPWRDLY_ADCPWR1_Msk (0xff00UL) /*!< MCUCTRL ADCPWRDLY: ADCPWR1 (Bitfield-Mask: 0xff) */ +#define MCUCTRL_ADCPWRDLY_ADCPWR0_Pos (0UL) /*!< MCUCTRL ADCPWRDLY: ADCPWR0 (Bit 0) */ +#define MCUCTRL_ADCPWRDLY_ADCPWR0_Msk (0xffUL) /*!< MCUCTRL ADCPWRDLY: ADCPWR0 (Bitfield-Mask: 0xff) */ +/* ======================================================== ADCCAL ========================================================= */ +#define MCUCTRL_ADCCAL_ADCCALIBRATED_Pos (1UL) /*!< MCUCTRL ADCCAL: ADCCALIBRATED (Bit 1) */ +#define MCUCTRL_ADCCAL_ADCCALIBRATED_Msk (0x2UL) /*!< MCUCTRL ADCCAL: ADCCALIBRATED (Bitfield-Mask: 0x01) */ +#define MCUCTRL_ADCCAL_CALONPWRUP_Pos (0UL) /*!< MCUCTRL ADCCAL: CALONPWRUP (Bit 0) */ +#define MCUCTRL_ADCCAL_CALONPWRUP_Msk (0x1UL) /*!< MCUCTRL ADCCAL: CALONPWRUP (Bitfield-Mask: 0x01) */ +/* ====================================================== ADCBATTLOAD ====================================================== */ +#define MCUCTRL_ADCBATTLOAD_BATTLOAD_Pos (0UL) /*!< MCUCTRL ADCBATTLOAD: BATTLOAD (Bit 0) */ +#define MCUCTRL_ADCBATTLOAD_BATTLOAD_Msk (0x1UL) /*!< MCUCTRL ADCBATTLOAD: BATTLOAD (Bitfield-Mask: 0x01) */ +/* ======================================================== ADCTRIM ======================================================== */ +#define MCUCTRL_ADCTRIM_ADCRFBUFIBTRIM_Pos (11UL) /*!< MCUCTRL ADCTRIM: ADCRFBUFIBTRIM (Bit 11) */ +#define MCUCTRL_ADCTRIM_ADCRFBUFIBTRIM_Msk (0x1800UL) /*!< MCUCTRL ADCTRIM: ADCRFBUFIBTRIM (Bitfield-Mask: 0x03) */ +#define MCUCTRL_ADCTRIM_ADCREFBUFTRIM_Pos (6UL) /*!< MCUCTRL ADCTRIM: ADCREFBUFTRIM (Bit 6) */ +#define MCUCTRL_ADCTRIM_ADCREFBUFTRIM_Msk (0x7c0UL) /*!< MCUCTRL ADCTRIM: ADCREFBUFTRIM (Bitfield-Mask: 0x1f) */ +#define MCUCTRL_ADCTRIM_ADCREFKEEPIBTRIM_Pos (0UL) /*!< MCUCTRL ADCTRIM: ADCREFKEEPIBTRIM (Bit 0) */ +#define MCUCTRL_ADCTRIM_ADCREFKEEPIBTRIM_Msk (0x3UL) /*!< MCUCTRL ADCTRIM: ADCREFKEEPIBTRIM (Bitfield-Mask: 0x03) */ +/* ====================================================== ADCREFCOMP ======================================================= */ +#define MCUCTRL_ADCREFCOMP_ADCRFCMPEN_Pos (16UL) /*!< MCUCTRL ADCREFCOMP: ADCRFCMPEN (Bit 16) */ +#define MCUCTRL_ADCREFCOMP_ADCRFCMPEN_Msk (0x10000UL) /*!< MCUCTRL ADCREFCOMP: ADCRFCMPEN (Bitfield-Mask: 0x01) */ +#define MCUCTRL_ADCREFCOMP_ADCREFKEEPTRIM_Pos (8UL) /*!< MCUCTRL ADCREFCOMP: ADCREFKEEPTRIM (Bit 8) */ +#define MCUCTRL_ADCREFCOMP_ADCREFKEEPTRIM_Msk (0x1f00UL) /*!< MCUCTRL ADCREFCOMP: ADCREFKEEPTRIM (Bitfield-Mask: 0x1f) */ +#define MCUCTRL_ADCREFCOMP_ADC_REFCOMP_OUT_Pos (0UL) /*!< MCUCTRL ADCREFCOMP: ADC_REFCOMP_OUT (Bit 0) */ +#define MCUCTRL_ADCREFCOMP_ADC_REFCOMP_OUT_Msk (0x1UL) /*!< MCUCTRL ADCREFCOMP: ADC_REFCOMP_OUT (Bitfield-Mask: 0x01) */ +/* ======================================================= XTALCTRL ======================================================== */ +#define MCUCTRL_XTALCTRL_XTALICOMPTRIM_Pos (8UL) /*!< MCUCTRL XTALCTRL: XTALICOMPTRIM (Bit 8) */ +#define MCUCTRL_XTALCTRL_XTALICOMPTRIM_Msk (0x300UL) /*!< MCUCTRL XTALCTRL: XTALICOMPTRIM (Bitfield-Mask: 0x03) */ +#define MCUCTRL_XTALCTRL_XTALIBUFTRIM_Pos (6UL) /*!< MCUCTRL XTALCTRL: XTALIBUFTRIM (Bit 6) */ +#define MCUCTRL_XTALCTRL_XTALIBUFTRIM_Msk (0xc0UL) /*!< MCUCTRL XTALCTRL: XTALIBUFTRIM (Bitfield-Mask: 0x03) */ +#define MCUCTRL_XTALCTRL_PWDBODXTAL_Pos (5UL) /*!< MCUCTRL XTALCTRL: PWDBODXTAL (Bit 5) */ +#define MCUCTRL_XTALCTRL_PWDBODXTAL_Msk (0x20UL) /*!< MCUCTRL XTALCTRL: PWDBODXTAL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_XTALCTRL_PDNBCMPRXTAL_Pos (4UL) /*!< MCUCTRL XTALCTRL: PDNBCMPRXTAL (Bit 4) */ +#define MCUCTRL_XTALCTRL_PDNBCMPRXTAL_Msk (0x10UL) /*!< MCUCTRL XTALCTRL: PDNBCMPRXTAL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_XTALCTRL_PDNBCOREXTAL_Pos (3UL) /*!< MCUCTRL XTALCTRL: PDNBCOREXTAL (Bit 3) */ +#define MCUCTRL_XTALCTRL_PDNBCOREXTAL_Msk (0x8UL) /*!< MCUCTRL XTALCTRL: PDNBCOREXTAL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_XTALCTRL_BYPCMPRXTAL_Pos (2UL) /*!< MCUCTRL XTALCTRL: BYPCMPRXTAL (Bit 2) */ +#define MCUCTRL_XTALCTRL_BYPCMPRXTAL_Msk (0x4UL) /*!< MCUCTRL XTALCTRL: BYPCMPRXTAL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_XTALCTRL_FDBKDSBLXTAL_Pos (1UL) /*!< MCUCTRL XTALCTRL: FDBKDSBLXTAL (Bit 1) */ +#define MCUCTRL_XTALCTRL_FDBKDSBLXTAL_Msk (0x2UL) /*!< MCUCTRL XTALCTRL: FDBKDSBLXTAL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_XTALCTRL_XTALSWE_Pos (0UL) /*!< MCUCTRL XTALCTRL: XTALSWE (Bit 0) */ +#define MCUCTRL_XTALCTRL_XTALSWE_Msk (0x1UL) /*!< MCUCTRL XTALCTRL: XTALSWE (Bitfield-Mask: 0x01) */ +/* ====================================================== XTALGENCTRL ====================================================== */ +#define MCUCTRL_XTALGENCTRL_XTALKSBIASTRIM_Pos (8UL) /*!< MCUCTRL XTALGENCTRL: XTALKSBIASTRIM (Bit 8) */ +#define MCUCTRL_XTALGENCTRL_XTALKSBIASTRIM_Msk (0x3f00UL) /*!< MCUCTRL XTALGENCTRL: XTALKSBIASTRIM (Bitfield-Mask: 0x3f) */ +#define MCUCTRL_XTALGENCTRL_XTALBIASTRIM_Pos (2UL) /*!< MCUCTRL XTALGENCTRL: XTALBIASTRIM (Bit 2) */ +#define MCUCTRL_XTALGENCTRL_XTALBIASTRIM_Msk (0xfcUL) /*!< MCUCTRL XTALGENCTRL: XTALBIASTRIM (Bitfield-Mask: 0x3f) */ +#define MCUCTRL_XTALGENCTRL_ACWARMUP_Pos (0UL) /*!< MCUCTRL XTALGENCTRL: ACWARMUP (Bit 0) */ +#define MCUCTRL_XTALGENCTRL_ACWARMUP_Msk (0x3UL) /*!< MCUCTRL XTALGENCTRL: ACWARMUP (Bitfield-Mask: 0x03) */ +/* ======================================================= MISCCTRL ======================================================== */ +#define MCUCTRL_MISCCTRL_BLE_RESETN_Pos (5UL) /*!< MCUCTRL MISCCTRL: BLE_RESETN (Bit 5) */ +#define MCUCTRL_MISCCTRL_BLE_RESETN_Msk (0x20UL) /*!< MCUCTRL MISCCTRL: BLE_RESETN (Bitfield-Mask: 0x01) */ +#define MCUCTRL_MISCCTRL_RESERVED_RW_0_Pos (0UL) /*!< MCUCTRL MISCCTRL: RESERVED_RW_0 (Bit 0) */ +#define MCUCTRL_MISCCTRL_RESERVED_RW_0_Msk (0x1fUL) /*!< MCUCTRL MISCCTRL: RESERVED_RW_0 (Bitfield-Mask: 0x1f) */ +/* ====================================================== BOOTLOADER ======================================================= */ +#define MCUCTRL_BOOTLOADER_SECBOOTONRST_Pos (30UL) /*!< MCUCTRL BOOTLOADER: SECBOOTONRST (Bit 30) */ +#define MCUCTRL_BOOTLOADER_SECBOOTONRST_Msk (0xc0000000UL) /*!< MCUCTRL BOOTLOADER: SECBOOTONRST (Bitfield-Mask: 0x03) */ +#define MCUCTRL_BOOTLOADER_SECBOOT_Pos (28UL) /*!< MCUCTRL BOOTLOADER: SECBOOT (Bit 28) */ +#define MCUCTRL_BOOTLOADER_SECBOOT_Msk (0x30000000UL) /*!< MCUCTRL BOOTLOADER: SECBOOT (Bitfield-Mask: 0x03) */ +#define MCUCTRL_BOOTLOADER_SECBOOTFEATURE_Pos (26UL) /*!< MCUCTRL BOOTLOADER: SECBOOTFEATURE (Bit 26) */ +#define MCUCTRL_BOOTLOADER_SECBOOTFEATURE_Msk (0xc000000UL) /*!< MCUCTRL BOOTLOADER: SECBOOTFEATURE (Bitfield-Mask: 0x03) */ +#define MCUCTRL_BOOTLOADER_PROTLOCK_Pos (2UL) /*!< MCUCTRL BOOTLOADER: PROTLOCK (Bit 2) */ +#define MCUCTRL_BOOTLOADER_PROTLOCK_Msk (0x4UL) /*!< MCUCTRL BOOTLOADER: PROTLOCK (Bitfield-Mask: 0x01) */ +#define MCUCTRL_BOOTLOADER_SBLOCK_Pos (1UL) /*!< MCUCTRL BOOTLOADER: SBLOCK (Bit 1) */ +#define MCUCTRL_BOOTLOADER_SBLOCK_Msk (0x2UL) /*!< MCUCTRL BOOTLOADER: SBLOCK (Bitfield-Mask: 0x01) */ +#define MCUCTRL_BOOTLOADER_BOOTLOADERLOW_Pos (0UL) /*!< MCUCTRL BOOTLOADER: BOOTLOADERLOW (Bit 0) */ +#define MCUCTRL_BOOTLOADER_BOOTLOADERLOW_Msk (0x1UL) /*!< MCUCTRL BOOTLOADER: BOOTLOADERLOW (Bitfield-Mask: 0x01) */ +/* ====================================================== SHADOWVALID ====================================================== */ +#define MCUCTRL_SHADOWVALID_INFO0_VALID_Pos (2UL) /*!< MCUCTRL SHADOWVALID: INFO0_VALID (Bit 2) */ +#define MCUCTRL_SHADOWVALID_INFO0_VALID_Msk (0x4UL) /*!< MCUCTRL SHADOWVALID: INFO0_VALID (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SHADOWVALID_BLDSLEEP_Pos (1UL) /*!< MCUCTRL SHADOWVALID: BLDSLEEP (Bit 1) */ +#define MCUCTRL_SHADOWVALID_BLDSLEEP_Msk (0x2UL) /*!< MCUCTRL SHADOWVALID: BLDSLEEP (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SHADOWVALID_VALID_Pos (0UL) /*!< MCUCTRL SHADOWVALID: VALID (Bit 0) */ +#define MCUCTRL_SHADOWVALID_VALID_Msk (0x1UL) /*!< MCUCTRL SHADOWVALID: VALID (Bitfield-Mask: 0x01) */ +/* ======================================================= SCRATCH0 ======================================================== */ +#define MCUCTRL_SCRATCH0_SCRATCH0_Pos (0UL) /*!< MCUCTRL SCRATCH0: SCRATCH0 (Bit 0) */ +#define MCUCTRL_SCRATCH0_SCRATCH0_Msk (0xffffffffUL) /*!< MCUCTRL SCRATCH0: SCRATCH0 (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= SCRATCH1 ======================================================== */ +#define MCUCTRL_SCRATCH1_SCRATCH1_Pos (0UL) /*!< MCUCTRL SCRATCH1: SCRATCH1 (Bit 0) */ +#define MCUCTRL_SCRATCH1_SCRATCH1_Msk (0xffffffffUL) /*!< MCUCTRL SCRATCH1: SCRATCH1 (Bitfield-Mask: 0xffffffff) */ +/* ==================================================== ICODEFAULTADDR ===================================================== */ +#define MCUCTRL_ICODEFAULTADDR_ICODEFAULTADDR_Pos (0UL) /*!< MCUCTRL ICODEFAULTADDR: ICODEFAULTADDR (Bit 0) */ +#define MCUCTRL_ICODEFAULTADDR_ICODEFAULTADDR_Msk (0xffffffffUL) /*!< MCUCTRL ICODEFAULTADDR: ICODEFAULTADDR (Bitfield-Mask: 0xffffffff) */ +/* ==================================================== DCODEFAULTADDR ===================================================== */ +#define MCUCTRL_DCODEFAULTADDR_DCODEFAULTADDR_Pos (0UL) /*!< MCUCTRL DCODEFAULTADDR: DCODEFAULTADDR (Bit 0) */ +#define MCUCTRL_DCODEFAULTADDR_DCODEFAULTADDR_Msk (0xffffffffUL) /*!< MCUCTRL DCODEFAULTADDR: DCODEFAULTADDR (Bitfield-Mask: 0xffffffff) */ +/* ===================================================== SYSFAULTADDR ====================================================== */ +#define MCUCTRL_SYSFAULTADDR_SYSFAULTADDR_Pos (0UL) /*!< MCUCTRL SYSFAULTADDR: SYSFAULTADDR (Bit 0) */ +#define MCUCTRL_SYSFAULTADDR_SYSFAULTADDR_Msk (0xffffffffUL) /*!< MCUCTRL SYSFAULTADDR: SYSFAULTADDR (Bitfield-Mask: 0xffffffff) */ +/* ====================================================== FAULTSTATUS ====================================================== */ +#define MCUCTRL_FAULTSTATUS_SYSFAULT_Pos (2UL) /*!< MCUCTRL FAULTSTATUS: SYSFAULT (Bit 2) */ +#define MCUCTRL_FAULTSTATUS_SYSFAULT_Msk (0x4UL) /*!< MCUCTRL FAULTSTATUS: SYSFAULT (Bitfield-Mask: 0x01) */ +#define MCUCTRL_FAULTSTATUS_DCODEFAULT_Pos (1UL) /*!< MCUCTRL FAULTSTATUS: DCODEFAULT (Bit 1) */ +#define MCUCTRL_FAULTSTATUS_DCODEFAULT_Msk (0x2UL) /*!< MCUCTRL FAULTSTATUS: DCODEFAULT (Bitfield-Mask: 0x01) */ +#define MCUCTRL_FAULTSTATUS_ICODEFAULT_Pos (0UL) /*!< MCUCTRL FAULTSTATUS: ICODEFAULT (Bit 0) */ +#define MCUCTRL_FAULTSTATUS_ICODEFAULT_Msk (0x1UL) /*!< MCUCTRL FAULTSTATUS: ICODEFAULT (Bitfield-Mask: 0x01) */ +/* ==================================================== FAULTCAPTUREEN ===================================================== */ +#define MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_Pos (0UL) /*!< MCUCTRL FAULTCAPTUREEN: FAULTCAPTUREEN (Bit 0) */ +#define MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_Msk (0x1UL) /*!< MCUCTRL FAULTCAPTUREEN: FAULTCAPTUREEN (Bitfield-Mask: 0x01) */ +/* ========================================================= DBGR1 ========================================================= */ +#define MCUCTRL_DBGR1_ONETO8_Pos (0UL) /*!< MCUCTRL DBGR1: ONETO8 (Bit 0) */ +#define MCUCTRL_DBGR1_ONETO8_Msk (0xffffffffUL) /*!< MCUCTRL DBGR1: ONETO8 (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= DBGR2 ========================================================= */ +#define MCUCTRL_DBGR2_COOLCODE_Pos (0UL) /*!< MCUCTRL DBGR2: COOLCODE (Bit 0) */ +#define MCUCTRL_DBGR2_COOLCODE_Msk (0xffffffffUL) /*!< MCUCTRL DBGR2: COOLCODE (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= PMUENABLE ======================================================= */ +#define MCUCTRL_PMUENABLE_ENABLE_Pos (0UL) /*!< MCUCTRL PMUENABLE: ENABLE (Bit 0) */ +#define MCUCTRL_PMUENABLE_ENABLE_Msk (0x1UL) /*!< MCUCTRL PMUENABLE: ENABLE (Bitfield-Mask: 0x01) */ +/* ======================================================= TPIUCTRL ======================================================== */ +#define MCUCTRL_TPIUCTRL_CLKSEL_Pos (8UL) /*!< MCUCTRL TPIUCTRL: CLKSEL (Bit 8) */ +#define MCUCTRL_TPIUCTRL_CLKSEL_Msk (0x700UL) /*!< MCUCTRL TPIUCTRL: CLKSEL (Bitfield-Mask: 0x07) */ +#define MCUCTRL_TPIUCTRL_ENABLE_Pos (0UL) /*!< MCUCTRL TPIUCTRL: ENABLE (Bit 0) */ +#define MCUCTRL_TPIUCTRL_ENABLE_Msk (0x1UL) /*!< MCUCTRL TPIUCTRL: ENABLE (Bitfield-Mask: 0x01) */ +/* ====================================================== OTAPOINTER ======================================================= */ +#define MCUCTRL_OTAPOINTER_OTAPOINTER_Pos (2UL) /*!< MCUCTRL OTAPOINTER: OTAPOINTER (Bit 2) */ +#define MCUCTRL_OTAPOINTER_OTAPOINTER_Msk (0xfffffffcUL) /*!< MCUCTRL OTAPOINTER: OTAPOINTER (Bitfield-Mask: 0x3fffffff) */ +#define MCUCTRL_OTAPOINTER_OTASBLUPDATE_Pos (1UL) /*!< MCUCTRL OTAPOINTER: OTASBLUPDATE (Bit 1) */ +#define MCUCTRL_OTAPOINTER_OTASBLUPDATE_Msk (0x2UL) /*!< MCUCTRL OTAPOINTER: OTASBLUPDATE (Bitfield-Mask: 0x01) */ +#define MCUCTRL_OTAPOINTER_OTAVALID_Pos (0UL) /*!< MCUCTRL OTAPOINTER: OTAVALID (Bit 0) */ +#define MCUCTRL_OTAPOINTER_OTAVALID_Msk (0x1UL) /*!< MCUCTRL OTAPOINTER: OTAVALID (Bitfield-Mask: 0x01) */ +/* ====================================================== APBDMACTRL ======================================================= */ +#define MCUCTRL_APBDMACTRL_HYSTERESIS_Pos (8UL) /*!< MCUCTRL APBDMACTRL: HYSTERESIS (Bit 8) */ +#define MCUCTRL_APBDMACTRL_HYSTERESIS_Msk (0xff00UL) /*!< MCUCTRL APBDMACTRL: HYSTERESIS (Bitfield-Mask: 0xff) */ +#define MCUCTRL_APBDMACTRL_DECODEABORT_Pos (1UL) /*!< MCUCTRL APBDMACTRL: DECODEABORT (Bit 1) */ +#define MCUCTRL_APBDMACTRL_DECODEABORT_Msk (0x2UL) /*!< MCUCTRL APBDMACTRL: DECODEABORT (Bitfield-Mask: 0x01) */ +#define MCUCTRL_APBDMACTRL_DMA_ENABLE_Pos (0UL) /*!< MCUCTRL APBDMACTRL: DMA_ENABLE (Bit 0) */ +#define MCUCTRL_APBDMACTRL_DMA_ENABLE_Msk (0x1UL) /*!< MCUCTRL APBDMACTRL: DMA_ENABLE (Bitfield-Mask: 0x01) */ +/* ======================================================= SRAMMODE ======================================================== */ +#define MCUCTRL_SRAMMODE_DPREFETCH_CACHE_Pos (5UL) /*!< MCUCTRL SRAMMODE: DPREFETCH_CACHE (Bit 5) */ +#define MCUCTRL_SRAMMODE_DPREFETCH_CACHE_Msk (0x20UL) /*!< MCUCTRL SRAMMODE: DPREFETCH_CACHE (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SRAMMODE_DPREFETCH_Pos (4UL) /*!< MCUCTRL SRAMMODE: DPREFETCH (Bit 4) */ +#define MCUCTRL_SRAMMODE_DPREFETCH_Msk (0x10UL) /*!< MCUCTRL SRAMMODE: DPREFETCH (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SRAMMODE_IPREFETCH_CACHE_Pos (1UL) /*!< MCUCTRL SRAMMODE: IPREFETCH_CACHE (Bit 1) */ +#define MCUCTRL_SRAMMODE_IPREFETCH_CACHE_Msk (0x2UL) /*!< MCUCTRL SRAMMODE: IPREFETCH_CACHE (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SRAMMODE_IPREFETCH_Pos (0UL) /*!< MCUCTRL SRAMMODE: IPREFETCH (Bit 0) */ +#define MCUCTRL_SRAMMODE_IPREFETCH_Msk (0x1UL) /*!< MCUCTRL SRAMMODE: IPREFETCH (Bitfield-Mask: 0x01) */ +/* ====================================================== KEXTCLKSEL ======================================================= */ +#define MCUCTRL_KEXTCLKSEL_KEXTCLKSEL_Pos (0UL) /*!< MCUCTRL KEXTCLKSEL: KEXTCLKSEL (Bit 0) */ +#define MCUCTRL_KEXTCLKSEL_KEXTCLKSEL_Msk (0xffffffffUL) /*!< MCUCTRL KEXTCLKSEL: KEXTCLKSEL (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= SIMOBUCK4 ======================================================= */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKIBIASTRIM_Pos (28UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKIBIASTRIM (Bit 28) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKIBIASTRIM_Msk (0xf0000000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKIBIASTRIM (Bitfield-Mask: 0x0f) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLOMODE_Pos (26UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLOMODE (Bit 26) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLOMODE_Msk (0xc000000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLOMODE (Bitfield-Mask: 0x03) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKPRIORITYSEL_Pos (25UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKPRIORITYSEL (Bit 25) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKPRIORITYSEL_Msk (0x2000000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKPRIORITYSEL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKCOMP2TIMEOUTEN_Pos (24UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCOMP2TIMEOUTEN (Bit 24) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKCOMP2TIMEOUTEN_Msk (0x1000000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCOMP2TIMEOUTEN (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKCOMP2LPEN_Pos (23UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCOMP2LPEN (Bit 23) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKCOMP2LPEN_Msk (0x800000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCOMP2LPEN (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKCLKDIVSEL_Pos (21UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCLKDIVSEL (Bit 21) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKCLKDIVSEL_Msk (0x600000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCLKDIVSEL (Bitfield-Mask: 0x03) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKEXTCLKSEL_Pos (20UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKEXTCLKSEL (Bit 20) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKEXTCLKSEL_Msk (0x100000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKEXTCLKSEL (Bitfield-Mask: 0x01) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLODRVSTRTRIM_Pos (17UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLODRVSTRTRIM (Bit 17) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLODRVSTRTRIM_Msk (0xe0000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLODRVSTRTRIM (Bitfield-Mask: 0x07) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLOCNTRTRIM_Pos (14UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLOCNTRTRIM (Bit 14) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLOCNTRTRIM_Msk (0x1c000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLOCNTRTRIM (Bitfield-Mask: 0x07) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKZXTRIM_Pos (10UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKZXTRIM (Bit 10) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKZXTRIM_Msk (0x3c00UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKZXTRIM (Bitfield-Mask: 0x0f) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLEAKAGETRIM_Pos (8UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLEAKAGETRIM (Bit 8) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLEAKAGETRIM_Msk (0x300UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLEAKAGETRIM (Bitfield-Mask: 0x03) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLPDRVSTRTRIM_Pos (6UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLPDRVSTRTRIM (Bit 6) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLPDRVSTRTRIM_Msk (0xc0UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLPDRVSTRTRIM (Bitfield-Mask: 0x03) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMACTDRVSTRTRIM_Pos (4UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMACTDRVSTRTRIM (Bit 4) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMACTDRVSTRTRIM_Msk (0x30UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMACTDRVSTRTRIM (Bitfield-Mask: 0x03) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLPLOWTONTRIM_Pos (0UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLPLOWTONTRIM (Bit 0) */ +#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLPLOWTONTRIM_Msk (0xfUL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLPLOWTONTRIM (Bitfield-Mask: 0x0f) */ +/* ======================================================= BLEBUCK2 ======================================================== */ +#define MCUCTRL_BLEBUCK2_BLEBUCKTOND2ATRIM_Pos (12UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTOND2ATRIM (Bit 12) */ +#define MCUCTRL_BLEBUCK2_BLEBUCKTOND2ATRIM_Msk (0x3f000UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTOND2ATRIM (Bitfield-Mask: 0x3f) */ +#define MCUCTRL_BLEBUCK2_BLEBUCKTONHITRIM_Pos (6UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTONHITRIM (Bit 6) */ +#define MCUCTRL_BLEBUCK2_BLEBUCKTONHITRIM_Msk (0xfc0UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTONHITRIM (Bitfield-Mask: 0x3f) */ +#define MCUCTRL_BLEBUCK2_BLEBUCKTONLOWTRIM_Pos (0UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTONLOWTRIM (Bit 0) */ +#define MCUCTRL_BLEBUCK2_BLEBUCKTONLOWTRIM_Msk (0x3fUL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTONLOWTRIM (Bitfield-Mask: 0x3f) */ +/* ====================================================== FLASHWPROT0 ====================================================== */ +#define MCUCTRL_FLASHWPROT0_FW0BITS_Pos (0UL) /*!< MCUCTRL FLASHWPROT0: FW0BITS (Bit 0) */ +#define MCUCTRL_FLASHWPROT0_FW0BITS_Msk (0xffffffffUL) /*!< MCUCTRL FLASHWPROT0: FW0BITS (Bitfield-Mask: 0xffffffff) */ +/* ====================================================== FLASHWPROT1 ====================================================== */ +#define MCUCTRL_FLASHWPROT1_FW1BITS_Pos (0UL) /*!< MCUCTRL FLASHWPROT1: FW1BITS (Bit 0) */ +#define MCUCTRL_FLASHWPROT1_FW1BITS_Msk (0xffffffffUL) /*!< MCUCTRL FLASHWPROT1: FW1BITS (Bitfield-Mask: 0xffffffff) */ +/* ====================================================== FLASHRPROT0 ====================================================== */ +#define MCUCTRL_FLASHRPROT0_FR0BITS_Pos (0UL) /*!< MCUCTRL FLASHRPROT0: FR0BITS (Bit 0) */ +#define MCUCTRL_FLASHRPROT0_FR0BITS_Msk (0xffffffffUL) /*!< MCUCTRL FLASHRPROT0: FR0BITS (Bitfield-Mask: 0xffffffff) */ +/* ====================================================== FLASHRPROT1 ====================================================== */ +#define MCUCTRL_FLASHRPROT1_FR1BITS_Pos (0UL) /*!< MCUCTRL FLASHRPROT1: FR1BITS (Bit 0) */ +#define MCUCTRL_FLASHRPROT1_FR1BITS_Msk (0xffffffffUL) /*!< MCUCTRL FLASHRPROT1: FR1BITS (Bitfield-Mask: 0xffffffff) */ +/* ================================================= DMASRAMWRITEPROTECT0 ================================================== */ +#define MCUCTRL_DMASRAMWRITEPROTECT0_DMA_WPROT0_Pos (0UL) /*!< MCUCTRL DMASRAMWRITEPROTECT0: DMA_WPROT0 (Bit 0) */ +#define MCUCTRL_DMASRAMWRITEPROTECT0_DMA_WPROT0_Msk (0xffffffffUL) /*!< MCUCTRL DMASRAMWRITEPROTECT0: DMA_WPROT0 (Bitfield-Mask: 0xffffffff) */ +/* ================================================= DMASRAMWRITEPROTECT1 ================================================== */ +#define MCUCTRL_DMASRAMWRITEPROTECT1_DMA_WPROT1_Pos (0UL) /*!< MCUCTRL DMASRAMWRITEPROTECT1: DMA_WPROT1 (Bit 0) */ +#define MCUCTRL_DMASRAMWRITEPROTECT1_DMA_WPROT1_Msk (0xffffUL) /*!< MCUCTRL DMASRAMWRITEPROTECT1: DMA_WPROT1 (Bitfield-Mask: 0xffff) */ +/* ================================================== DMASRAMREADPROTECT0 ================================================== */ +#define MCUCTRL_DMASRAMREADPROTECT0_DMA_RPROT0_Pos (0UL) /*!< MCUCTRL DMASRAMREADPROTECT0: DMA_RPROT0 (Bit 0) */ +#define MCUCTRL_DMASRAMREADPROTECT0_DMA_RPROT0_Msk (0xffffffffUL) /*!< MCUCTRL DMASRAMREADPROTECT0: DMA_RPROT0 (Bitfield-Mask: 0xffffffff) */ +/* ================================================== DMASRAMREADPROTECT1 ================================================== */ +#define MCUCTRL_DMASRAMREADPROTECT1_DMA_RPROT1_Pos (0UL) /*!< MCUCTRL DMASRAMREADPROTECT1: DMA_RPROT1 (Bit 0) */ +#define MCUCTRL_DMASRAMREADPROTECT1_DMA_RPROT1_Msk (0xffffUL) /*!< MCUCTRL DMASRAMREADPROTECT1: DMA_RPROT1 (Bitfield-Mask: 0xffff) */ + + +/* =========================================================================================================================== */ +/* ================ MSPI ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= CTRL ========================================================== */ +#define MSPI_CTRL_XFERBYTES_Pos (16UL) /*!< MSPI CTRL: XFERBYTES (Bit 16) */ +#define MSPI_CTRL_XFERBYTES_Msk (0xffff0000UL) /*!< MSPI CTRL: XFERBYTES (Bitfield-Mask: 0xffff) */ +#define MSPI_CTRL_PIOSCRAMBLE_Pos (11UL) /*!< MSPI CTRL: PIOSCRAMBLE (Bit 11) */ +#define MSPI_CTRL_PIOSCRAMBLE_Msk (0x800UL) /*!< MSPI CTRL: PIOSCRAMBLE (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_TXRX_Pos (10UL) /*!< MSPI CTRL: TXRX (Bit 10) */ +#define MSPI_CTRL_TXRX_Msk (0x400UL) /*!< MSPI CTRL: TXRX (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_SENDI_Pos (9UL) /*!< MSPI CTRL: SENDI (Bit 9) */ +#define MSPI_CTRL_SENDI_Msk (0x200UL) /*!< MSPI CTRL: SENDI (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_SENDA_Pos (8UL) /*!< MSPI CTRL: SENDA (Bit 8) */ +#define MSPI_CTRL_SENDA_Msk (0x100UL) /*!< MSPI CTRL: SENDA (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_ENTURN_Pos (7UL) /*!< MSPI CTRL: ENTURN (Bit 7) */ +#define MSPI_CTRL_ENTURN_Msk (0x80UL) /*!< MSPI CTRL: ENTURN (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_BIGENDIAN_Pos (6UL) /*!< MSPI CTRL: BIGENDIAN (Bit 6) */ +#define MSPI_CTRL_BIGENDIAN_Msk (0x40UL) /*!< MSPI CTRL: BIGENDIAN (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_CONT_Pos (5UL) /*!< MSPI CTRL: CONT (Bit 5) */ +#define MSPI_CTRL_CONT_Msk (0x20UL) /*!< MSPI CTRL: CONT (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_QUADCMD_Pos (3UL) /*!< MSPI CTRL: QUADCMD (Bit 3) */ +#define MSPI_CTRL_QUADCMD_Msk (0x8UL) /*!< MSPI CTRL: QUADCMD (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_BUSY_Pos (2UL) /*!< MSPI CTRL: BUSY (Bit 2) */ +#define MSPI_CTRL_BUSY_Msk (0x4UL) /*!< MSPI CTRL: BUSY (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_STATUS_Pos (1UL) /*!< MSPI CTRL: STATUS (Bit 1) */ +#define MSPI_CTRL_STATUS_Msk (0x2UL) /*!< MSPI CTRL: STATUS (Bitfield-Mask: 0x01) */ +#define MSPI_CTRL_START_Pos (0UL) /*!< MSPI CTRL: START (Bit 0) */ +#define MSPI_CTRL_START_Msk (0x1UL) /*!< MSPI CTRL: START (Bitfield-Mask: 0x01) */ +/* ========================================================== CFG ========================================================== */ +#define MSPI_CFG_CPOL_Pos (17UL) /*!< MSPI CFG: CPOL (Bit 17) */ +#define MSPI_CFG_CPOL_Msk (0x20000UL) /*!< MSPI CFG: CPOL (Bitfield-Mask: 0x01) */ +#define MSPI_CFG_CPHA_Pos (16UL) /*!< MSPI CFG: CPHA (Bit 16) */ +#define MSPI_CFG_CPHA_Msk (0x10000UL) /*!< MSPI CFG: CPHA (Bitfield-Mask: 0x01) */ +#define MSPI_CFG_TURNAROUND_Pos (8UL) /*!< MSPI CFG: TURNAROUND (Bit 8) */ +#define MSPI_CFG_TURNAROUND_Msk (0x3f00UL) /*!< MSPI CFG: TURNAROUND (Bitfield-Mask: 0x3f) */ +#define MSPI_CFG_SEPIO_Pos (7UL) /*!< MSPI CFG: SEPIO (Bit 7) */ +#define MSPI_CFG_SEPIO_Msk (0x80UL) /*!< MSPI CFG: SEPIO (Bitfield-Mask: 0x01) */ +#define MSPI_CFG_ISIZE_Pos (6UL) /*!< MSPI CFG: ISIZE (Bit 6) */ +#define MSPI_CFG_ISIZE_Msk (0x40UL) /*!< MSPI CFG: ISIZE (Bitfield-Mask: 0x01) */ +#define MSPI_CFG_ASIZE_Pos (4UL) /*!< MSPI CFG: ASIZE (Bit 4) */ +#define MSPI_CFG_ASIZE_Msk (0x30UL) /*!< MSPI CFG: ASIZE (Bitfield-Mask: 0x03) */ +#define MSPI_CFG_DEVCFG_Pos (0UL) /*!< MSPI CFG: DEVCFG (Bit 0) */ +#define MSPI_CFG_DEVCFG_Msk (0xfUL) /*!< MSPI CFG: DEVCFG (Bitfield-Mask: 0x0f) */ +/* ========================================================= ADDR ========================================================== */ +#define MSPI_ADDR_ADDR_Pos (0UL) /*!< MSPI ADDR: ADDR (Bit 0) */ +#define MSPI_ADDR_ADDR_Msk (0xffffffffUL) /*!< MSPI ADDR: ADDR (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= INSTR ========================================================= */ +#define MSPI_INSTR_INSTR_Pos (0UL) /*!< MSPI INSTR: INSTR (Bit 0) */ +#define MSPI_INSTR_INSTR_Msk (0xffffUL) /*!< MSPI INSTR: INSTR (Bitfield-Mask: 0xffff) */ +/* ======================================================== TXFIFO ========================================================= */ +#define MSPI_TXFIFO_TXFIFO_Pos (0UL) /*!< MSPI TXFIFO: TXFIFO (Bit 0) */ +#define MSPI_TXFIFO_TXFIFO_Msk (0xffffffffUL) /*!< MSPI TXFIFO: TXFIFO (Bitfield-Mask: 0xffffffff) */ +/* ======================================================== RXFIFO ========================================================= */ +#define MSPI_RXFIFO_RXFIFO_Pos (0UL) /*!< MSPI RXFIFO: RXFIFO (Bit 0) */ +#define MSPI_RXFIFO_RXFIFO_Msk (0xffffffffUL) /*!< MSPI RXFIFO: RXFIFO (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= TXENTRIES ======================================================= */ +#define MSPI_TXENTRIES_TXENTRIES_Pos (0UL) /*!< MSPI TXENTRIES: TXENTRIES (Bit 0) */ +#define MSPI_TXENTRIES_TXENTRIES_Msk (0x1fUL) /*!< MSPI TXENTRIES: TXENTRIES (Bitfield-Mask: 0x1f) */ +/* ======================================================= RXENTRIES ======================================================= */ +#define MSPI_RXENTRIES_RXENTRIES_Pos (0UL) /*!< MSPI RXENTRIES: RXENTRIES (Bit 0) */ +#define MSPI_RXENTRIES_RXENTRIES_Msk (0x1fUL) /*!< MSPI RXENTRIES: RXENTRIES (Bitfield-Mask: 0x1f) */ +/* ======================================================= THRESHOLD ======================================================= */ +#define MSPI_THRESHOLD_RXTHRESH_Pos (8UL) /*!< MSPI THRESHOLD: RXTHRESH (Bit 8) */ +#define MSPI_THRESHOLD_RXTHRESH_Msk (0x1f00UL) /*!< MSPI THRESHOLD: RXTHRESH (Bitfield-Mask: 0x1f) */ +#define MSPI_THRESHOLD_TXTHRESH_Pos (0UL) /*!< MSPI THRESHOLD: TXTHRESH (Bit 0) */ +#define MSPI_THRESHOLD_TXTHRESH_Msk (0x1fUL) /*!< MSPI THRESHOLD: TXTHRESH (Bitfield-Mask: 0x1f) */ +/* ======================================================== MSPICFG ======================================================== */ +#define MSPI_MSPICFG_PRSTN_Pos (31UL) /*!< MSPI MSPICFG: PRSTN (Bit 31) */ +#define MSPI_MSPICFG_PRSTN_Msk (0x80000000UL) /*!< MSPI MSPICFG: PRSTN (Bitfield-Mask: 0x01) */ +#define MSPI_MSPICFG_IPRSTN_Pos (30UL) /*!< MSPI MSPICFG: IPRSTN (Bit 30) */ +#define MSPI_MSPICFG_IPRSTN_Msk (0x40000000UL) /*!< MSPI MSPICFG: IPRSTN (Bitfield-Mask: 0x01) */ +#define MSPI_MSPICFG_FIFORESET_Pos (29UL) /*!< MSPI MSPICFG: FIFORESET (Bit 29) */ +#define MSPI_MSPICFG_FIFORESET_Msk (0x20000000UL) /*!< MSPI MSPICFG: FIFORESET (Bitfield-Mask: 0x01) */ +#define MSPI_MSPICFG_CLKDIV_Pos (8UL) /*!< MSPI MSPICFG: CLKDIV (Bit 8) */ +#define MSPI_MSPICFG_CLKDIV_Msk (0x3f00UL) /*!< MSPI MSPICFG: CLKDIV (Bitfield-Mask: 0x3f) */ +#define MSPI_MSPICFG_IOMSEL_Pos (4UL) /*!< MSPI MSPICFG: IOMSEL (Bit 4) */ +#define MSPI_MSPICFG_IOMSEL_Msk (0x70UL) /*!< MSPI MSPICFG: IOMSEL (Bitfield-Mask: 0x07) */ +#define MSPI_MSPICFG_TXNEG_Pos (3UL) /*!< MSPI MSPICFG: TXNEG (Bit 3) */ +#define MSPI_MSPICFG_TXNEG_Msk (0x8UL) /*!< MSPI MSPICFG: TXNEG (Bitfield-Mask: 0x01) */ +#define MSPI_MSPICFG_RXNEG_Pos (2UL) /*!< MSPI MSPICFG: RXNEG (Bit 2) */ +#define MSPI_MSPICFG_RXNEG_Msk (0x4UL) /*!< MSPI MSPICFG: RXNEG (Bitfield-Mask: 0x01) */ +#define MSPI_MSPICFG_RXCAP_Pos (1UL) /*!< MSPI MSPICFG: RXCAP (Bit 1) */ +#define MSPI_MSPICFG_RXCAP_Msk (0x2UL) /*!< MSPI MSPICFG: RXCAP (Bitfield-Mask: 0x01) */ +#define MSPI_MSPICFG_APBCLK_Pos (0UL) /*!< MSPI MSPICFG: APBCLK (Bit 0) */ +#define MSPI_MSPICFG_APBCLK_Msk (0x1UL) /*!< MSPI MSPICFG: APBCLK (Bitfield-Mask: 0x01) */ +/* ======================================================== PADCFG ========================================================= */ +#define MSPI_PADCFG_REVCS_Pos (21UL) /*!< MSPI PADCFG: REVCS (Bit 21) */ +#define MSPI_PADCFG_REVCS_Msk (0x200000UL) /*!< MSPI PADCFG: REVCS (Bitfield-Mask: 0x01) */ +#define MSPI_PADCFG_IN3_Pos (20UL) /*!< MSPI PADCFG: IN3 (Bit 20) */ +#define MSPI_PADCFG_IN3_Msk (0x100000UL) /*!< MSPI PADCFG: IN3 (Bitfield-Mask: 0x01) */ +#define MSPI_PADCFG_IN2_Pos (19UL) /*!< MSPI PADCFG: IN2 (Bit 19) */ +#define MSPI_PADCFG_IN2_Msk (0x80000UL) /*!< MSPI PADCFG: IN2 (Bitfield-Mask: 0x01) */ +#define MSPI_PADCFG_IN1_Pos (18UL) /*!< MSPI PADCFG: IN1 (Bit 18) */ +#define MSPI_PADCFG_IN1_Msk (0x40000UL) /*!< MSPI PADCFG: IN1 (Bitfield-Mask: 0x01) */ +#define MSPI_PADCFG_IN0_Pos (16UL) /*!< MSPI PADCFG: IN0 (Bit 16) */ +#define MSPI_PADCFG_IN0_Msk (0x30000UL) /*!< MSPI PADCFG: IN0 (Bitfield-Mask: 0x03) */ +#define MSPI_PADCFG_OUT7_Pos (4UL) /*!< MSPI PADCFG: OUT7 (Bit 4) */ +#define MSPI_PADCFG_OUT7_Msk (0x10UL) /*!< MSPI PADCFG: OUT7 (Bitfield-Mask: 0x01) */ +#define MSPI_PADCFG_OUT6_Pos (3UL) /*!< MSPI PADCFG: OUT6 (Bit 3) */ +#define MSPI_PADCFG_OUT6_Msk (0x8UL) /*!< MSPI PADCFG: OUT6 (Bitfield-Mask: 0x01) */ +#define MSPI_PADCFG_OUT5_Pos (2UL) /*!< MSPI PADCFG: OUT5 (Bit 2) */ +#define MSPI_PADCFG_OUT5_Msk (0x4UL) /*!< MSPI PADCFG: OUT5 (Bitfield-Mask: 0x01) */ +#define MSPI_PADCFG_OUT4_Pos (1UL) /*!< MSPI PADCFG: OUT4 (Bit 1) */ +#define MSPI_PADCFG_OUT4_Msk (0x2UL) /*!< MSPI PADCFG: OUT4 (Bitfield-Mask: 0x01) */ +#define MSPI_PADCFG_OUT3_Pos (0UL) /*!< MSPI PADCFG: OUT3 (Bit 0) */ +#define MSPI_PADCFG_OUT3_Msk (0x1UL) /*!< MSPI PADCFG: OUT3 (Bitfield-Mask: 0x01) */ +/* ======================================================= PADOUTEN ======================================================== */ +#define MSPI_PADOUTEN_OUTEN_Pos (0UL) /*!< MSPI PADOUTEN: OUTEN (Bit 0) */ +#define MSPI_PADOUTEN_OUTEN_Msk (0x1ffUL) /*!< MSPI PADOUTEN: OUTEN (Bitfield-Mask: 0x1ff) */ +/* ========================================================= FLASH ========================================================= */ +#define MSPI_FLASH_READINSTR_Pos (24UL) /*!< MSPI FLASH: READINSTR (Bit 24) */ +#define MSPI_FLASH_READINSTR_Msk (0xff000000UL) /*!< MSPI FLASH: READINSTR (Bitfield-Mask: 0xff) */ +#define MSPI_FLASH_WRITEINSTR_Pos (16UL) /*!< MSPI FLASH: WRITEINSTR (Bit 16) */ +#define MSPI_FLASH_WRITEINSTR_Msk (0xff0000UL) /*!< MSPI FLASH: WRITEINSTR (Bitfield-Mask: 0xff) */ +#define MSPI_FLASH_XIPMIXED_Pos (8UL) /*!< MSPI FLASH: XIPMIXED (Bit 8) */ +#define MSPI_FLASH_XIPMIXED_Msk (0x700UL) /*!< MSPI FLASH: XIPMIXED (Bitfield-Mask: 0x07) */ +#define MSPI_FLASH_XIPSENDI_Pos (7UL) /*!< MSPI FLASH: XIPSENDI (Bit 7) */ +#define MSPI_FLASH_XIPSENDI_Msk (0x80UL) /*!< MSPI FLASH: XIPSENDI (Bitfield-Mask: 0x01) */ +#define MSPI_FLASH_XIPSENDA_Pos (6UL) /*!< MSPI FLASH: XIPSENDA (Bit 6) */ +#define MSPI_FLASH_XIPSENDA_Msk (0x40UL) /*!< MSPI FLASH: XIPSENDA (Bitfield-Mask: 0x01) */ +#define MSPI_FLASH_XIPENTURN_Pos (5UL) /*!< MSPI FLASH: XIPENTURN (Bit 5) */ +#define MSPI_FLASH_XIPENTURN_Msk (0x20UL) /*!< MSPI FLASH: XIPENTURN (Bitfield-Mask: 0x01) */ +#define MSPI_FLASH_XIPBIGENDIAN_Pos (4UL) /*!< MSPI FLASH: XIPBIGENDIAN (Bit 4) */ +#define MSPI_FLASH_XIPBIGENDIAN_Msk (0x10UL) /*!< MSPI FLASH: XIPBIGENDIAN (Bitfield-Mask: 0x01) */ +#define MSPI_FLASH_XIPACK_Pos (2UL) /*!< MSPI FLASH: XIPACK (Bit 2) */ +#define MSPI_FLASH_XIPACK_Msk (0xcUL) /*!< MSPI FLASH: XIPACK (Bitfield-Mask: 0x03) */ +#define MSPI_FLASH_XIPEN_Pos (0UL) /*!< MSPI FLASH: XIPEN (Bit 0) */ +#define MSPI_FLASH_XIPEN_Msk (0x1UL) /*!< MSPI FLASH: XIPEN (Bitfield-Mask: 0x01) */ +/* ====================================================== SCRAMBLING ======================================================= */ +#define MSPI_SCRAMBLING_SCRENABLE_Pos (31UL) /*!< MSPI SCRAMBLING: SCRENABLE (Bit 31) */ +#define MSPI_SCRAMBLING_SCRENABLE_Msk (0x80000000UL) /*!< MSPI SCRAMBLING: SCRENABLE (Bitfield-Mask: 0x01) */ +#define MSPI_SCRAMBLING_SCREND_Pos (16UL) /*!< MSPI SCRAMBLING: SCREND (Bit 16) */ +#define MSPI_SCRAMBLING_SCREND_Msk (0x3ff0000UL) /*!< MSPI SCRAMBLING: SCREND (Bitfield-Mask: 0x3ff) */ +#define MSPI_SCRAMBLING_SCRSTART_Pos (0UL) /*!< MSPI SCRAMBLING: SCRSTART (Bit 0) */ +#define MSPI_SCRAMBLING_SCRSTART_Msk (0x3ffUL) /*!< MSPI SCRAMBLING: SCRSTART (Bitfield-Mask: 0x3ff) */ +/* ========================================================= INTEN ========================================================= */ +#define MSPI_INTEN_SCRERR_Pos (12UL) /*!< MSPI INTEN: SCRERR (Bit 12) */ +#define MSPI_INTEN_SCRERR_Msk (0x1000UL) /*!< MSPI INTEN: SCRERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_CQERR_Pos (11UL) /*!< MSPI INTEN: CQERR (Bit 11) */ +#define MSPI_INTEN_CQERR_Msk (0x800UL) /*!< MSPI INTEN: CQERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_CQPAUSED_Pos (10UL) /*!< MSPI INTEN: CQPAUSED (Bit 10) */ +#define MSPI_INTEN_CQPAUSED_Msk (0x400UL) /*!< MSPI INTEN: CQPAUSED (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_CQUPD_Pos (9UL) /*!< MSPI INTEN: CQUPD (Bit 9) */ +#define MSPI_INTEN_CQUPD_Msk (0x200UL) /*!< MSPI INTEN: CQUPD (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_CQCMP_Pos (8UL) /*!< MSPI INTEN: CQCMP (Bit 8) */ +#define MSPI_INTEN_CQCMP_Msk (0x100UL) /*!< MSPI INTEN: CQCMP (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_DERR_Pos (7UL) /*!< MSPI INTEN: DERR (Bit 7) */ +#define MSPI_INTEN_DERR_Msk (0x80UL) /*!< MSPI INTEN: DERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_DCMP_Pos (6UL) /*!< MSPI INTEN: DCMP (Bit 6) */ +#define MSPI_INTEN_DCMP_Msk (0x40UL) /*!< MSPI INTEN: DCMP (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_RXF_Pos (5UL) /*!< MSPI INTEN: RXF (Bit 5) */ +#define MSPI_INTEN_RXF_Msk (0x20UL) /*!< MSPI INTEN: RXF (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_RXO_Pos (4UL) /*!< MSPI INTEN: RXO (Bit 4) */ +#define MSPI_INTEN_RXO_Msk (0x10UL) /*!< MSPI INTEN: RXO (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_RXU_Pos (3UL) /*!< MSPI INTEN: RXU (Bit 3) */ +#define MSPI_INTEN_RXU_Msk (0x8UL) /*!< MSPI INTEN: RXU (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_TXO_Pos (2UL) /*!< MSPI INTEN: TXO (Bit 2) */ +#define MSPI_INTEN_TXO_Msk (0x4UL) /*!< MSPI INTEN: TXO (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_TXE_Pos (1UL) /*!< MSPI INTEN: TXE (Bit 1) */ +#define MSPI_INTEN_TXE_Msk (0x2UL) /*!< MSPI INTEN: TXE (Bitfield-Mask: 0x01) */ +#define MSPI_INTEN_CMDCMP_Pos (0UL) /*!< MSPI INTEN: CMDCMP (Bit 0) */ +#define MSPI_INTEN_CMDCMP_Msk (0x1UL) /*!< MSPI INTEN: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define MSPI_INTSTAT_SCRERR_Pos (12UL) /*!< MSPI INTSTAT: SCRERR (Bit 12) */ +#define MSPI_INTSTAT_SCRERR_Msk (0x1000UL) /*!< MSPI INTSTAT: SCRERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_CQERR_Pos (11UL) /*!< MSPI INTSTAT: CQERR (Bit 11) */ +#define MSPI_INTSTAT_CQERR_Msk (0x800UL) /*!< MSPI INTSTAT: CQERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_CQPAUSED_Pos (10UL) /*!< MSPI INTSTAT: CQPAUSED (Bit 10) */ +#define MSPI_INTSTAT_CQPAUSED_Msk (0x400UL) /*!< MSPI INTSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_CQUPD_Pos (9UL) /*!< MSPI INTSTAT: CQUPD (Bit 9) */ +#define MSPI_INTSTAT_CQUPD_Msk (0x200UL) /*!< MSPI INTSTAT: CQUPD (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_CQCMP_Pos (8UL) /*!< MSPI INTSTAT: CQCMP (Bit 8) */ +#define MSPI_INTSTAT_CQCMP_Msk (0x100UL) /*!< MSPI INTSTAT: CQCMP (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_DERR_Pos (7UL) /*!< MSPI INTSTAT: DERR (Bit 7) */ +#define MSPI_INTSTAT_DERR_Msk (0x80UL) /*!< MSPI INTSTAT: DERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_DCMP_Pos (6UL) /*!< MSPI INTSTAT: DCMP (Bit 6) */ +#define MSPI_INTSTAT_DCMP_Msk (0x40UL) /*!< MSPI INTSTAT: DCMP (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_RXF_Pos (5UL) /*!< MSPI INTSTAT: RXF (Bit 5) */ +#define MSPI_INTSTAT_RXF_Msk (0x20UL) /*!< MSPI INTSTAT: RXF (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_RXO_Pos (4UL) /*!< MSPI INTSTAT: RXO (Bit 4) */ +#define MSPI_INTSTAT_RXO_Msk (0x10UL) /*!< MSPI INTSTAT: RXO (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_RXU_Pos (3UL) /*!< MSPI INTSTAT: RXU (Bit 3) */ +#define MSPI_INTSTAT_RXU_Msk (0x8UL) /*!< MSPI INTSTAT: RXU (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_TXO_Pos (2UL) /*!< MSPI INTSTAT: TXO (Bit 2) */ +#define MSPI_INTSTAT_TXO_Msk (0x4UL) /*!< MSPI INTSTAT: TXO (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_TXE_Pos (1UL) /*!< MSPI INTSTAT: TXE (Bit 1) */ +#define MSPI_INTSTAT_TXE_Msk (0x2UL) /*!< MSPI INTSTAT: TXE (Bitfield-Mask: 0x01) */ +#define MSPI_INTSTAT_CMDCMP_Pos (0UL) /*!< MSPI INTSTAT: CMDCMP (Bit 0) */ +#define MSPI_INTSTAT_CMDCMP_Msk (0x1UL) /*!< MSPI INTSTAT: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define MSPI_INTCLR_SCRERR_Pos (12UL) /*!< MSPI INTCLR: SCRERR (Bit 12) */ +#define MSPI_INTCLR_SCRERR_Msk (0x1000UL) /*!< MSPI INTCLR: SCRERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_CQERR_Pos (11UL) /*!< MSPI INTCLR: CQERR (Bit 11) */ +#define MSPI_INTCLR_CQERR_Msk (0x800UL) /*!< MSPI INTCLR: CQERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_CQPAUSED_Pos (10UL) /*!< MSPI INTCLR: CQPAUSED (Bit 10) */ +#define MSPI_INTCLR_CQPAUSED_Msk (0x400UL) /*!< MSPI INTCLR: CQPAUSED (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_CQUPD_Pos (9UL) /*!< MSPI INTCLR: CQUPD (Bit 9) */ +#define MSPI_INTCLR_CQUPD_Msk (0x200UL) /*!< MSPI INTCLR: CQUPD (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_CQCMP_Pos (8UL) /*!< MSPI INTCLR: CQCMP (Bit 8) */ +#define MSPI_INTCLR_CQCMP_Msk (0x100UL) /*!< MSPI INTCLR: CQCMP (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_DERR_Pos (7UL) /*!< MSPI INTCLR: DERR (Bit 7) */ +#define MSPI_INTCLR_DERR_Msk (0x80UL) /*!< MSPI INTCLR: DERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_DCMP_Pos (6UL) /*!< MSPI INTCLR: DCMP (Bit 6) */ +#define MSPI_INTCLR_DCMP_Msk (0x40UL) /*!< MSPI INTCLR: DCMP (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_RXF_Pos (5UL) /*!< MSPI INTCLR: RXF (Bit 5) */ +#define MSPI_INTCLR_RXF_Msk (0x20UL) /*!< MSPI INTCLR: RXF (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_RXO_Pos (4UL) /*!< MSPI INTCLR: RXO (Bit 4) */ +#define MSPI_INTCLR_RXO_Msk (0x10UL) /*!< MSPI INTCLR: RXO (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_RXU_Pos (3UL) /*!< MSPI INTCLR: RXU (Bit 3) */ +#define MSPI_INTCLR_RXU_Msk (0x8UL) /*!< MSPI INTCLR: RXU (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_TXO_Pos (2UL) /*!< MSPI INTCLR: TXO (Bit 2) */ +#define MSPI_INTCLR_TXO_Msk (0x4UL) /*!< MSPI INTCLR: TXO (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_TXE_Pos (1UL) /*!< MSPI INTCLR: TXE (Bit 1) */ +#define MSPI_INTCLR_TXE_Msk (0x2UL) /*!< MSPI INTCLR: TXE (Bitfield-Mask: 0x01) */ +#define MSPI_INTCLR_CMDCMP_Pos (0UL) /*!< MSPI INTCLR: CMDCMP (Bit 0) */ +#define MSPI_INTCLR_CMDCMP_Msk (0x1UL) /*!< MSPI INTCLR: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define MSPI_INTSET_SCRERR_Pos (12UL) /*!< MSPI INTSET: SCRERR (Bit 12) */ +#define MSPI_INTSET_SCRERR_Msk (0x1000UL) /*!< MSPI INTSET: SCRERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_CQERR_Pos (11UL) /*!< MSPI INTSET: CQERR (Bit 11) */ +#define MSPI_INTSET_CQERR_Msk (0x800UL) /*!< MSPI INTSET: CQERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_CQPAUSED_Pos (10UL) /*!< MSPI INTSET: CQPAUSED (Bit 10) */ +#define MSPI_INTSET_CQPAUSED_Msk (0x400UL) /*!< MSPI INTSET: CQPAUSED (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_CQUPD_Pos (9UL) /*!< MSPI INTSET: CQUPD (Bit 9) */ +#define MSPI_INTSET_CQUPD_Msk (0x200UL) /*!< MSPI INTSET: CQUPD (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_CQCMP_Pos (8UL) /*!< MSPI INTSET: CQCMP (Bit 8) */ +#define MSPI_INTSET_CQCMP_Msk (0x100UL) /*!< MSPI INTSET: CQCMP (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_DERR_Pos (7UL) /*!< MSPI INTSET: DERR (Bit 7) */ +#define MSPI_INTSET_DERR_Msk (0x80UL) /*!< MSPI INTSET: DERR (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_DCMP_Pos (6UL) /*!< MSPI INTSET: DCMP (Bit 6) */ +#define MSPI_INTSET_DCMP_Msk (0x40UL) /*!< MSPI INTSET: DCMP (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_RXF_Pos (5UL) /*!< MSPI INTSET: RXF (Bit 5) */ +#define MSPI_INTSET_RXF_Msk (0x20UL) /*!< MSPI INTSET: RXF (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_RXO_Pos (4UL) /*!< MSPI INTSET: RXO (Bit 4) */ +#define MSPI_INTSET_RXO_Msk (0x10UL) /*!< MSPI INTSET: RXO (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_RXU_Pos (3UL) /*!< MSPI INTSET: RXU (Bit 3) */ +#define MSPI_INTSET_RXU_Msk (0x8UL) /*!< MSPI INTSET: RXU (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_TXO_Pos (2UL) /*!< MSPI INTSET: TXO (Bit 2) */ +#define MSPI_INTSET_TXO_Msk (0x4UL) /*!< MSPI INTSET: TXO (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_TXE_Pos (1UL) /*!< MSPI INTSET: TXE (Bit 1) */ +#define MSPI_INTSET_TXE_Msk (0x2UL) /*!< MSPI INTSET: TXE (Bitfield-Mask: 0x01) */ +#define MSPI_INTSET_CMDCMP_Pos (0UL) /*!< MSPI INTSET: CMDCMP (Bit 0) */ +#define MSPI_INTSET_CMDCMP_Msk (0x1UL) /*!< MSPI INTSET: CMDCMP (Bitfield-Mask: 0x01) */ +/* ======================================================== DMACFG ========================================================= */ +#define MSPI_DMACFG_DMAPWROFF_Pos (18UL) /*!< MSPI DMACFG: DMAPWROFF (Bit 18) */ +#define MSPI_DMACFG_DMAPWROFF_Msk (0x40000UL) /*!< MSPI DMACFG: DMAPWROFF (Bitfield-Mask: 0x01) */ +#define MSPI_DMACFG_DMAPRI_Pos (3UL) /*!< MSPI DMACFG: DMAPRI (Bit 3) */ +#define MSPI_DMACFG_DMAPRI_Msk (0x18UL) /*!< MSPI DMACFG: DMAPRI (Bitfield-Mask: 0x03) */ +#define MSPI_DMACFG_DMADIR_Pos (2UL) /*!< MSPI DMACFG: DMADIR (Bit 2) */ +#define MSPI_DMACFG_DMADIR_Msk (0x4UL) /*!< MSPI DMACFG: DMADIR (Bitfield-Mask: 0x01) */ +#define MSPI_DMACFG_DMAEN_Pos (0UL) /*!< MSPI DMACFG: DMAEN (Bit 0) */ +#define MSPI_DMACFG_DMAEN_Msk (0x3UL) /*!< MSPI DMACFG: DMAEN (Bitfield-Mask: 0x03) */ +/* ======================================================== DMASTAT ======================================================== */ +#define MSPI_DMASTAT_SCRERR_Pos (3UL) /*!< MSPI DMASTAT: SCRERR (Bit 3) */ +#define MSPI_DMASTAT_SCRERR_Msk (0x8UL) /*!< MSPI DMASTAT: SCRERR (Bitfield-Mask: 0x01) */ +#define MSPI_DMASTAT_DMAERR_Pos (2UL) /*!< MSPI DMASTAT: DMAERR (Bit 2) */ +#define MSPI_DMASTAT_DMAERR_Msk (0x4UL) /*!< MSPI DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ +#define MSPI_DMASTAT_DMACPL_Pos (1UL) /*!< MSPI DMASTAT: DMACPL (Bit 1) */ +#define MSPI_DMASTAT_DMACPL_Msk (0x2UL) /*!< MSPI DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ +#define MSPI_DMASTAT_DMATIP_Pos (0UL) /*!< MSPI DMASTAT: DMATIP (Bit 0) */ +#define MSPI_DMASTAT_DMATIP_Msk (0x1UL) /*!< MSPI DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ +/* ====================================================== DMATARGADDR ====================================================== */ +#define MSPI_DMATARGADDR_TARGADDR_Pos (0UL) /*!< MSPI DMATARGADDR: TARGADDR (Bit 0) */ +#define MSPI_DMATARGADDR_TARGADDR_Msk (0xffffffffUL) /*!< MSPI DMATARGADDR: TARGADDR (Bitfield-Mask: 0xffffffff) */ +/* ====================================================== DMADEVADDR ======================================================= */ +#define MSPI_DMADEVADDR_DEVADDR_Pos (0UL) /*!< MSPI DMADEVADDR: DEVADDR (Bit 0) */ +#define MSPI_DMADEVADDR_DEVADDR_Msk (0xffffffffUL) /*!< MSPI DMADEVADDR: DEVADDR (Bitfield-Mask: 0xffffffff) */ +/* ====================================================== DMATOTCOUNT ====================================================== */ +#define MSPI_DMATOTCOUNT_TOTCOUNT_Pos (0UL) /*!< MSPI DMATOTCOUNT: TOTCOUNT (Bit 0) */ +#define MSPI_DMATOTCOUNT_TOTCOUNT_Msk (0xffffUL) /*!< MSPI DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xffff) */ +/* ======================================================= DMABCOUNT ======================================================= */ +#define MSPI_DMABCOUNT_BCOUNT_Pos (0UL) /*!< MSPI DMABCOUNT: BCOUNT (Bit 0) */ +#define MSPI_DMABCOUNT_BCOUNT_Msk (0xffUL) /*!< MSPI DMABCOUNT: BCOUNT (Bitfield-Mask: 0xff) */ +/* ======================================================= DMATHRESH ======================================================= */ +#define MSPI_DMATHRESH_DMATHRESH_Pos (0UL) /*!< MSPI DMATHRESH: DMATHRESH (Bit 0) */ +#define MSPI_DMATHRESH_DMATHRESH_Msk (0xfUL) /*!< MSPI DMATHRESH: DMATHRESH (Bitfield-Mask: 0x0f) */ +/* ========================================================= CQCFG ========================================================= */ +#define MSPI_CQCFG_CQAUTOCLEARMASK_Pos (3UL) /*!< MSPI CQCFG: CQAUTOCLEARMASK (Bit 3) */ +#define MSPI_CQCFG_CQAUTOCLEARMASK_Msk (0x8UL) /*!< MSPI CQCFG: CQAUTOCLEARMASK (Bitfield-Mask: 0x01) */ +#define MSPI_CQCFG_CQPWROFF_Pos (2UL) /*!< MSPI CQCFG: CQPWROFF (Bit 2) */ +#define MSPI_CQCFG_CQPWROFF_Msk (0x4UL) /*!< MSPI CQCFG: CQPWROFF (Bitfield-Mask: 0x01) */ +#define MSPI_CQCFG_CQPRI_Pos (1UL) /*!< MSPI CQCFG: CQPRI (Bit 1) */ +#define MSPI_CQCFG_CQPRI_Msk (0x2UL) /*!< MSPI CQCFG: CQPRI (Bitfield-Mask: 0x01) */ +#define MSPI_CQCFG_CQEN_Pos (0UL) /*!< MSPI CQCFG: CQEN (Bit 0) */ +#define MSPI_CQCFG_CQEN_Msk (0x1UL) /*!< MSPI CQCFG: CQEN (Bitfield-Mask: 0x01) */ +/* ======================================================== CQADDR ========================================================= */ +#define MSPI_CQADDR_CQADDR_Pos (0UL) /*!< MSPI CQADDR: CQADDR (Bit 0) */ +#define MSPI_CQADDR_CQADDR_Msk (0x1fffffffUL) /*!< MSPI CQADDR: CQADDR (Bitfield-Mask: 0x1fffffff) */ +/* ======================================================== CQSTAT ========================================================= */ +#define MSPI_CQSTAT_CQPAUSED_Pos (3UL) /*!< MSPI CQSTAT: CQPAUSED (Bit 3) */ +#define MSPI_CQSTAT_CQPAUSED_Msk (0x8UL) /*!< MSPI CQSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ +#define MSPI_CQSTAT_CQERR_Pos (2UL) /*!< MSPI CQSTAT: CQERR (Bit 2) */ +#define MSPI_CQSTAT_CQERR_Msk (0x4UL) /*!< MSPI CQSTAT: CQERR (Bitfield-Mask: 0x01) */ +#define MSPI_CQSTAT_CQCPL_Pos (1UL) /*!< MSPI CQSTAT: CQCPL (Bit 1) */ +#define MSPI_CQSTAT_CQCPL_Msk (0x2UL) /*!< MSPI CQSTAT: CQCPL (Bitfield-Mask: 0x01) */ +#define MSPI_CQSTAT_CQTIP_Pos (0UL) /*!< MSPI CQSTAT: CQTIP (Bit 0) */ +#define MSPI_CQSTAT_CQTIP_Msk (0x1UL) /*!< MSPI CQSTAT: CQTIP (Bitfield-Mask: 0x01) */ +/* ======================================================== CQFLAGS ======================================================== */ +#define MSPI_CQFLAGS_CQFLAGS_Pos (0UL) /*!< MSPI CQFLAGS: CQFLAGS (Bit 0) */ +#define MSPI_CQFLAGS_CQFLAGS_Msk (0xffffUL) /*!< MSPI CQFLAGS: CQFLAGS (Bitfield-Mask: 0xffff) */ +/* ====================================================== CQSETCLEAR ======================================================= */ +#define MSPI_CQSETCLEAR_CQFCLR_Pos (16UL) /*!< MSPI CQSETCLEAR: CQFCLR (Bit 16) */ +#define MSPI_CQSETCLEAR_CQFCLR_Msk (0xff0000UL) /*!< MSPI CQSETCLEAR: CQFCLR (Bitfield-Mask: 0xff) */ +#define MSPI_CQSETCLEAR_CQFTOGGLE_Pos (8UL) /*!< MSPI CQSETCLEAR: CQFTOGGLE (Bit 8) */ +#define MSPI_CQSETCLEAR_CQFTOGGLE_Msk (0xff00UL) /*!< MSPI CQSETCLEAR: CQFTOGGLE (Bitfield-Mask: 0xff) */ +#define MSPI_CQSETCLEAR_CQFSET_Pos (0UL) /*!< MSPI CQSETCLEAR: CQFSET (Bit 0) */ +#define MSPI_CQSETCLEAR_CQFSET_Msk (0xffUL) /*!< MSPI CQSETCLEAR: CQFSET (Bitfield-Mask: 0xff) */ +/* ======================================================== CQPAUSE ======================================================== */ +#define MSPI_CQPAUSE_CQMASK_Pos (0UL) /*!< MSPI CQPAUSE: CQMASK (Bit 0) */ +#define MSPI_CQPAUSE_CQMASK_Msk (0xffffUL) /*!< MSPI CQPAUSE: CQMASK (Bitfield-Mask: 0xffff) */ +/* ======================================================= CQCURIDX ======================================================== */ +#define MSPI_CQCURIDX_CQCURIDX_Pos (0UL) /*!< MSPI CQCURIDX: CQCURIDX (Bit 0) */ +#define MSPI_CQCURIDX_CQCURIDX_Msk (0xffUL) /*!< MSPI CQCURIDX: CQCURIDX (Bitfield-Mask: 0xff) */ +/* ======================================================= CQENDIDX ======================================================== */ +#define MSPI_CQENDIDX_CQENDIDX_Pos (0UL) /*!< MSPI CQENDIDX: CQENDIDX (Bit 0) */ +#define MSPI_CQENDIDX_CQENDIDX_Msk (0xffUL) /*!< MSPI CQENDIDX: CQENDIDX (Bitfield-Mask: 0xff) */ + + +/* =========================================================================================================================== */ +/* ================ PDM ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= PCFG ========================================================== */ +#define PDM_PCFG_LRSWAP_Pos (31UL) /*!< PDM PCFG: LRSWAP (Bit 31) */ +#define PDM_PCFG_LRSWAP_Msk (0x80000000UL) /*!< PDM PCFG: LRSWAP (Bitfield-Mask: 0x01) */ +#define PDM_PCFG_PGARIGHT_Pos (26UL) /*!< PDM PCFG: PGARIGHT (Bit 26) */ +#define PDM_PCFG_PGARIGHT_Msk (0x7c000000UL) /*!< PDM PCFG: PGARIGHT (Bitfield-Mask: 0x1f) */ +#define PDM_PCFG_PGALEFT_Pos (21UL) /*!< PDM PCFG: PGALEFT (Bit 21) */ +#define PDM_PCFG_PGALEFT_Msk (0x3e00000UL) /*!< PDM PCFG: PGALEFT (Bitfield-Mask: 0x1f) */ +#define PDM_PCFG_MCLKDIV_Pos (17UL) /*!< PDM PCFG: MCLKDIV (Bit 17) */ +#define PDM_PCFG_MCLKDIV_Msk (0x60000UL) /*!< PDM PCFG: MCLKDIV (Bitfield-Mask: 0x03) */ +#define PDM_PCFG_SINCRATE_Pos (10UL) /*!< PDM PCFG: SINCRATE (Bit 10) */ +#define PDM_PCFG_SINCRATE_Msk (0x1fc00UL) /*!< PDM PCFG: SINCRATE (Bitfield-Mask: 0x7f) */ +#define PDM_PCFG_ADCHPD_Pos (9UL) /*!< PDM PCFG: ADCHPD (Bit 9) */ +#define PDM_PCFG_ADCHPD_Msk (0x200UL) /*!< PDM PCFG: ADCHPD (Bitfield-Mask: 0x01) */ +#define PDM_PCFG_HPCUTOFF_Pos (5UL) /*!< PDM PCFG: HPCUTOFF (Bit 5) */ +#define PDM_PCFG_HPCUTOFF_Msk (0x1e0UL) /*!< PDM PCFG: HPCUTOFF (Bitfield-Mask: 0x0f) */ +#define PDM_PCFG_CYCLES_Pos (2UL) /*!< PDM PCFG: CYCLES (Bit 2) */ +#define PDM_PCFG_CYCLES_Msk (0x1cUL) /*!< PDM PCFG: CYCLES (Bitfield-Mask: 0x07) */ +#define PDM_PCFG_SOFTMUTE_Pos (1UL) /*!< PDM PCFG: SOFTMUTE (Bit 1) */ +#define PDM_PCFG_SOFTMUTE_Msk (0x2UL) /*!< PDM PCFG: SOFTMUTE (Bitfield-Mask: 0x01) */ +#define PDM_PCFG_PDMCOREEN_Pos (0UL) /*!< PDM PCFG: PDMCOREEN (Bit 0) */ +#define PDM_PCFG_PDMCOREEN_Msk (0x1UL) /*!< PDM PCFG: PDMCOREEN (Bitfield-Mask: 0x01) */ +/* ========================================================= VCFG ========================================================== */ +#define PDM_VCFG_IOCLKEN_Pos (31UL) /*!< PDM VCFG: IOCLKEN (Bit 31) */ +#define PDM_VCFG_IOCLKEN_Msk (0x80000000UL) /*!< PDM VCFG: IOCLKEN (Bitfield-Mask: 0x01) */ +#define PDM_VCFG_RSTB_Pos (30UL) /*!< PDM VCFG: RSTB (Bit 30) */ +#define PDM_VCFG_RSTB_Msk (0x40000000UL) /*!< PDM VCFG: RSTB (Bitfield-Mask: 0x01) */ +#define PDM_VCFG_PDMCLKSEL_Pos (27UL) /*!< PDM VCFG: PDMCLKSEL (Bit 27) */ +#define PDM_VCFG_PDMCLKSEL_Msk (0x38000000UL) /*!< PDM VCFG: PDMCLKSEL (Bitfield-Mask: 0x07) */ +#define PDM_VCFG_PDMCLKEN_Pos (26UL) /*!< PDM VCFG: PDMCLKEN (Bit 26) */ +#define PDM_VCFG_PDMCLKEN_Msk (0x4000000UL) /*!< PDM VCFG: PDMCLKEN (Bitfield-Mask: 0x01) */ +#define PDM_VCFG_I2SEN_Pos (20UL) /*!< PDM VCFG: I2SEN (Bit 20) */ +#define PDM_VCFG_I2SEN_Msk (0x100000UL) /*!< PDM VCFG: I2SEN (Bitfield-Mask: 0x01) */ +#define PDM_VCFG_BCLKINV_Pos (19UL) /*!< PDM VCFG: BCLKINV (Bit 19) */ +#define PDM_VCFG_BCLKINV_Msk (0x80000UL) /*!< PDM VCFG: BCLKINV (Bitfield-Mask: 0x01) */ +#define PDM_VCFG_DMICKDEL_Pos (17UL) /*!< PDM VCFG: DMICKDEL (Bit 17) */ +#define PDM_VCFG_DMICKDEL_Msk (0x20000UL) /*!< PDM VCFG: DMICKDEL (Bitfield-Mask: 0x01) */ +#define PDM_VCFG_SELAP_Pos (16UL) /*!< PDM VCFG: SELAP (Bit 16) */ +#define PDM_VCFG_SELAP_Msk (0x10000UL) /*!< PDM VCFG: SELAP (Bitfield-Mask: 0x01) */ +#define PDM_VCFG_PCMPACK_Pos (8UL) /*!< PDM VCFG: PCMPACK (Bit 8) */ +#define PDM_VCFG_PCMPACK_Msk (0x100UL) /*!< PDM VCFG: PCMPACK (Bitfield-Mask: 0x01) */ +#define PDM_VCFG_CHSET_Pos (3UL) /*!< PDM VCFG: CHSET (Bit 3) */ +#define PDM_VCFG_CHSET_Msk (0x18UL) /*!< PDM VCFG: CHSET (Bitfield-Mask: 0x03) */ +/* ======================================================= VOICESTAT ======================================================= */ +#define PDM_VOICESTAT_FIFOCNT_Pos (0UL) /*!< PDM VOICESTAT: FIFOCNT (Bit 0) */ +#define PDM_VOICESTAT_FIFOCNT_Msk (0x3fUL) /*!< PDM VOICESTAT: FIFOCNT (Bitfield-Mask: 0x3f) */ +/* ======================================================= FIFOREAD ======================================================== */ +#define PDM_FIFOREAD_FIFOREAD_Pos (0UL) /*!< PDM FIFOREAD: FIFOREAD (Bit 0) */ +#define PDM_FIFOREAD_FIFOREAD_Msk (0xffffffffUL) /*!< PDM FIFOREAD: FIFOREAD (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= FIFOFLUSH ======================================================= */ +#define PDM_FIFOFLUSH_FIFOFLUSH_Pos (0UL) /*!< PDM FIFOFLUSH: FIFOFLUSH (Bit 0) */ +#define PDM_FIFOFLUSH_FIFOFLUSH_Msk (0x1UL) /*!< PDM FIFOFLUSH: FIFOFLUSH (Bitfield-Mask: 0x01) */ +/* ======================================================== FIFOTHR ======================================================== */ +#define PDM_FIFOTHR_FIFOTHR_Pos (0UL) /*!< PDM FIFOTHR: FIFOTHR (Bit 0) */ +#define PDM_FIFOTHR_FIFOTHR_Msk (0x1fUL) /*!< PDM FIFOTHR: FIFOTHR (Bitfield-Mask: 0x1f) */ +/* ========================================================= INTEN ========================================================= */ +#define PDM_INTEN_DERR_Pos (4UL) /*!< PDM INTEN: DERR (Bit 4) */ +#define PDM_INTEN_DERR_Msk (0x10UL) /*!< PDM INTEN: DERR (Bitfield-Mask: 0x01) */ +#define PDM_INTEN_DCMP_Pos (3UL) /*!< PDM INTEN: DCMP (Bit 3) */ +#define PDM_INTEN_DCMP_Msk (0x8UL) /*!< PDM INTEN: DCMP (Bitfield-Mask: 0x01) */ +#define PDM_INTEN_UNDFL_Pos (2UL) /*!< PDM INTEN: UNDFL (Bit 2) */ +#define PDM_INTEN_UNDFL_Msk (0x4UL) /*!< PDM INTEN: UNDFL (Bitfield-Mask: 0x01) */ +#define PDM_INTEN_OVF_Pos (1UL) /*!< PDM INTEN: OVF (Bit 1) */ +#define PDM_INTEN_OVF_Msk (0x2UL) /*!< PDM INTEN: OVF (Bitfield-Mask: 0x01) */ +#define PDM_INTEN_THR_Pos (0UL) /*!< PDM INTEN: THR (Bit 0) */ +#define PDM_INTEN_THR_Msk (0x1UL) /*!< PDM INTEN: THR (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define PDM_INTSTAT_DERR_Pos (4UL) /*!< PDM INTSTAT: DERR (Bit 4) */ +#define PDM_INTSTAT_DERR_Msk (0x10UL) /*!< PDM INTSTAT: DERR (Bitfield-Mask: 0x01) */ +#define PDM_INTSTAT_DCMP_Pos (3UL) /*!< PDM INTSTAT: DCMP (Bit 3) */ +#define PDM_INTSTAT_DCMP_Msk (0x8UL) /*!< PDM INTSTAT: DCMP (Bitfield-Mask: 0x01) */ +#define PDM_INTSTAT_UNDFL_Pos (2UL) /*!< PDM INTSTAT: UNDFL (Bit 2) */ +#define PDM_INTSTAT_UNDFL_Msk (0x4UL) /*!< PDM INTSTAT: UNDFL (Bitfield-Mask: 0x01) */ +#define PDM_INTSTAT_OVF_Pos (1UL) /*!< PDM INTSTAT: OVF (Bit 1) */ +#define PDM_INTSTAT_OVF_Msk (0x2UL) /*!< PDM INTSTAT: OVF (Bitfield-Mask: 0x01) */ +#define PDM_INTSTAT_THR_Pos (0UL) /*!< PDM INTSTAT: THR (Bit 0) */ +#define PDM_INTSTAT_THR_Msk (0x1UL) /*!< PDM INTSTAT: THR (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define PDM_INTCLR_DERR_Pos (4UL) /*!< PDM INTCLR: DERR (Bit 4) */ +#define PDM_INTCLR_DERR_Msk (0x10UL) /*!< PDM INTCLR: DERR (Bitfield-Mask: 0x01) */ +#define PDM_INTCLR_DCMP_Pos (3UL) /*!< PDM INTCLR: DCMP (Bit 3) */ +#define PDM_INTCLR_DCMP_Msk (0x8UL) /*!< PDM INTCLR: DCMP (Bitfield-Mask: 0x01) */ +#define PDM_INTCLR_UNDFL_Pos (2UL) /*!< PDM INTCLR: UNDFL (Bit 2) */ +#define PDM_INTCLR_UNDFL_Msk (0x4UL) /*!< PDM INTCLR: UNDFL (Bitfield-Mask: 0x01) */ +#define PDM_INTCLR_OVF_Pos (1UL) /*!< PDM INTCLR: OVF (Bit 1) */ +#define PDM_INTCLR_OVF_Msk (0x2UL) /*!< PDM INTCLR: OVF (Bitfield-Mask: 0x01) */ +#define PDM_INTCLR_THR_Pos (0UL) /*!< PDM INTCLR: THR (Bit 0) */ +#define PDM_INTCLR_THR_Msk (0x1UL) /*!< PDM INTCLR: THR (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define PDM_INTSET_DERR_Pos (4UL) /*!< PDM INTSET: DERR (Bit 4) */ +#define PDM_INTSET_DERR_Msk (0x10UL) /*!< PDM INTSET: DERR (Bitfield-Mask: 0x01) */ +#define PDM_INTSET_DCMP_Pos (3UL) /*!< PDM INTSET: DCMP (Bit 3) */ +#define PDM_INTSET_DCMP_Msk (0x8UL) /*!< PDM INTSET: DCMP (Bitfield-Mask: 0x01) */ +#define PDM_INTSET_UNDFL_Pos (2UL) /*!< PDM INTSET: UNDFL (Bit 2) */ +#define PDM_INTSET_UNDFL_Msk (0x4UL) /*!< PDM INTSET: UNDFL (Bitfield-Mask: 0x01) */ +#define PDM_INTSET_OVF_Pos (1UL) /*!< PDM INTSET: OVF (Bit 1) */ +#define PDM_INTSET_OVF_Msk (0x2UL) /*!< PDM INTSET: OVF (Bitfield-Mask: 0x01) */ +#define PDM_INTSET_THR_Pos (0UL) /*!< PDM INTSET: THR (Bit 0) */ +#define PDM_INTSET_THR_Msk (0x1UL) /*!< PDM INTSET: THR (Bitfield-Mask: 0x01) */ +/* ======================================================= DMATRIGEN ======================================================= */ +#define PDM_DMATRIGEN_DTHR90_Pos (1UL) /*!< PDM DMATRIGEN: DTHR90 (Bit 1) */ +#define PDM_DMATRIGEN_DTHR90_Msk (0x2UL) /*!< PDM DMATRIGEN: DTHR90 (Bitfield-Mask: 0x01) */ +#define PDM_DMATRIGEN_DTHR_Pos (0UL) /*!< PDM DMATRIGEN: DTHR (Bit 0) */ +#define PDM_DMATRIGEN_DTHR_Msk (0x1UL) /*!< PDM DMATRIGEN: DTHR (Bitfield-Mask: 0x01) */ +/* ====================================================== DMATRIGSTAT ====================================================== */ +#define PDM_DMATRIGSTAT_DTHR90STAT_Pos (1UL) /*!< PDM DMATRIGSTAT: DTHR90STAT (Bit 1) */ +#define PDM_DMATRIGSTAT_DTHR90STAT_Msk (0x2UL) /*!< PDM DMATRIGSTAT: DTHR90STAT (Bitfield-Mask: 0x01) */ +#define PDM_DMATRIGSTAT_DTHRSTAT_Pos (0UL) /*!< PDM DMATRIGSTAT: DTHRSTAT (Bit 0) */ +#define PDM_DMATRIGSTAT_DTHRSTAT_Msk (0x1UL) /*!< PDM DMATRIGSTAT: DTHRSTAT (Bitfield-Mask: 0x01) */ +/* ======================================================== DMACFG ========================================================= */ +#define PDM_DMACFG_DPWROFF_Pos (10UL) /*!< PDM DMACFG: DPWROFF (Bit 10) */ +#define PDM_DMACFG_DPWROFF_Msk (0x400UL) /*!< PDM DMACFG: DPWROFF (Bitfield-Mask: 0x01) */ +#define PDM_DMACFG_DAUTOHIP_Pos (9UL) /*!< PDM DMACFG: DAUTOHIP (Bit 9) */ +#define PDM_DMACFG_DAUTOHIP_Msk (0x200UL) /*!< PDM DMACFG: DAUTOHIP (Bitfield-Mask: 0x01) */ +#define PDM_DMACFG_DMAPRI_Pos (8UL) /*!< PDM DMACFG: DMAPRI (Bit 8) */ +#define PDM_DMACFG_DMAPRI_Msk (0x100UL) /*!< PDM DMACFG: DMAPRI (Bitfield-Mask: 0x01) */ +#define PDM_DMACFG_DMADIR_Pos (2UL) /*!< PDM DMACFG: DMADIR (Bit 2) */ +#define PDM_DMACFG_DMADIR_Msk (0x4UL) /*!< PDM DMACFG: DMADIR (Bitfield-Mask: 0x01) */ +#define PDM_DMACFG_DMAEN_Pos (0UL) /*!< PDM DMACFG: DMAEN (Bit 0) */ +#define PDM_DMACFG_DMAEN_Msk (0x1UL) /*!< PDM DMACFG: DMAEN (Bitfield-Mask: 0x01) */ +/* ====================================================== DMATOTCOUNT ====================================================== */ +#define PDM_DMATOTCOUNT_TOTCOUNT_Pos (0UL) /*!< PDM DMATOTCOUNT: TOTCOUNT (Bit 0) */ +#define PDM_DMATOTCOUNT_TOTCOUNT_Msk (0xfffffUL) /*!< PDM DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xfffff) */ +/* ====================================================== DMATARGADDR ====================================================== */ +#define PDM_DMATARGADDR_UTARGADDR_Pos (20UL) /*!< PDM DMATARGADDR: UTARGADDR (Bit 20) */ +#define PDM_DMATARGADDR_UTARGADDR_Msk (0xfff00000UL) /*!< PDM DMATARGADDR: UTARGADDR (Bitfield-Mask: 0xfff) */ +#define PDM_DMATARGADDR_LTARGADDR_Pos (0UL) /*!< PDM DMATARGADDR: LTARGADDR (Bit 0) */ +#define PDM_DMATARGADDR_LTARGADDR_Msk (0xfffffUL) /*!< PDM DMATARGADDR: LTARGADDR (Bitfield-Mask: 0xfffff) */ +/* ======================================================== DMASTAT ======================================================== */ +#define PDM_DMASTAT_DMAERR_Pos (2UL) /*!< PDM DMASTAT: DMAERR (Bit 2) */ +#define PDM_DMASTAT_DMAERR_Msk (0x4UL) /*!< PDM DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ +#define PDM_DMASTAT_DMACPL_Pos (1UL) /*!< PDM DMASTAT: DMACPL (Bit 1) */ +#define PDM_DMASTAT_DMACPL_Msk (0x2UL) /*!< PDM DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ +#define PDM_DMASTAT_DMATIP_Pos (0UL) /*!< PDM DMASTAT: DMATIP (Bit 0) */ +#define PDM_DMASTAT_DMATIP_Msk (0x1UL) /*!< PDM DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ PWRCTRL ================ */ +/* =========================================================================================================================== */ + +/* ======================================================= SUPPLYSRC ======================================================= */ +#define PWRCTRL_SUPPLYSRC_BLEBUCKEN_Pos (0UL) /*!< PWRCTRL SUPPLYSRC: BLEBUCKEN (Bit 0) */ +#define PWRCTRL_SUPPLYSRC_BLEBUCKEN_Msk (0x1UL) /*!< PWRCTRL SUPPLYSRC: BLEBUCKEN (Bitfield-Mask: 0x01) */ +/* ===================================================== SUPPLYSTATUS ====================================================== */ +#define PWRCTRL_SUPPLYSTATUS_BLEBUCKON_Pos (1UL) /*!< PWRCTRL SUPPLYSTATUS: BLEBUCKON (Bit 1) */ +#define PWRCTRL_SUPPLYSTATUS_BLEBUCKON_Msk (0x2UL) /*!< PWRCTRL SUPPLYSTATUS: BLEBUCKON (Bitfield-Mask: 0x01) */ +#define PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_Pos (0UL) /*!< PWRCTRL SUPPLYSTATUS: SIMOBUCKON (Bit 0) */ +#define PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_Msk (0x1UL) /*!< PWRCTRL SUPPLYSTATUS: SIMOBUCKON (Bitfield-Mask: 0x01) */ +/* ======================================================= DEVPWREN ======================================================== */ +#define PWRCTRL_DEVPWREN_PWRBLEL_Pos (13UL) /*!< PWRCTRL DEVPWREN: PWRBLEL (Bit 13) */ +#define PWRCTRL_DEVPWREN_PWRBLEL_Msk (0x2000UL) /*!< PWRCTRL DEVPWREN: PWRBLEL (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRPDM_Pos (12UL) /*!< PWRCTRL DEVPWREN: PWRPDM (Bit 12) */ +#define PWRCTRL_DEVPWREN_PWRPDM_Msk (0x1000UL) /*!< PWRCTRL DEVPWREN: PWRPDM (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRMSPI_Pos (11UL) /*!< PWRCTRL DEVPWREN: PWRMSPI (Bit 11) */ +#define PWRCTRL_DEVPWREN_PWRMSPI_Msk (0x800UL) /*!< PWRCTRL DEVPWREN: PWRMSPI (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRSCARD_Pos (10UL) /*!< PWRCTRL DEVPWREN: PWRSCARD (Bit 10) */ +#define PWRCTRL_DEVPWREN_PWRSCARD_Msk (0x400UL) /*!< PWRCTRL DEVPWREN: PWRSCARD (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRADC_Pos (9UL) /*!< PWRCTRL DEVPWREN: PWRADC (Bit 9) */ +#define PWRCTRL_DEVPWREN_PWRADC_Msk (0x200UL) /*!< PWRCTRL DEVPWREN: PWRADC (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRUART1_Pos (8UL) /*!< PWRCTRL DEVPWREN: PWRUART1 (Bit 8) */ +#define PWRCTRL_DEVPWREN_PWRUART1_Msk (0x100UL) /*!< PWRCTRL DEVPWREN: PWRUART1 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRUART0_Pos (7UL) /*!< PWRCTRL DEVPWREN: PWRUART0 (Bit 7) */ +#define PWRCTRL_DEVPWREN_PWRUART0_Msk (0x80UL) /*!< PWRCTRL DEVPWREN: PWRUART0 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRIOM5_Pos (6UL) /*!< PWRCTRL DEVPWREN: PWRIOM5 (Bit 6) */ +#define PWRCTRL_DEVPWREN_PWRIOM5_Msk (0x40UL) /*!< PWRCTRL DEVPWREN: PWRIOM5 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRIOM4_Pos (5UL) /*!< PWRCTRL DEVPWREN: PWRIOM4 (Bit 5) */ +#define PWRCTRL_DEVPWREN_PWRIOM4_Msk (0x20UL) /*!< PWRCTRL DEVPWREN: PWRIOM4 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRIOM3_Pos (4UL) /*!< PWRCTRL DEVPWREN: PWRIOM3 (Bit 4) */ +#define PWRCTRL_DEVPWREN_PWRIOM3_Msk (0x10UL) /*!< PWRCTRL DEVPWREN: PWRIOM3 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRIOM2_Pos (3UL) /*!< PWRCTRL DEVPWREN: PWRIOM2 (Bit 3) */ +#define PWRCTRL_DEVPWREN_PWRIOM2_Msk (0x8UL) /*!< PWRCTRL DEVPWREN: PWRIOM2 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRIOM1_Pos (2UL) /*!< PWRCTRL DEVPWREN: PWRIOM1 (Bit 2) */ +#define PWRCTRL_DEVPWREN_PWRIOM1_Msk (0x4UL) /*!< PWRCTRL DEVPWREN: PWRIOM1 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRIOM0_Pos (1UL) /*!< PWRCTRL DEVPWREN: PWRIOM0 (Bit 1) */ +#define PWRCTRL_DEVPWREN_PWRIOM0_Msk (0x2UL) /*!< PWRCTRL DEVPWREN: PWRIOM0 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREN_PWRIOS_Pos (0UL) /*!< PWRCTRL DEVPWREN: PWRIOS (Bit 0) */ +#define PWRCTRL_DEVPWREN_PWRIOS_Msk (0x1UL) /*!< PWRCTRL DEVPWREN: PWRIOS (Bitfield-Mask: 0x01) */ +/* ===================================================== MEMPWDINSLEEP ===================================================== */ +#define PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_Pos (31UL) /*!< PWRCTRL MEMPWDINSLEEP: CACHEPWDSLP (Bit 31) */ +#define PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_Msk (0x80000000UL) /*!< PWRCTRL MEMPWDINSLEEP: CACHEPWDSLP (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_Pos (14UL) /*!< PWRCTRL MEMPWDINSLEEP: FLASH1PWDSLP (Bit 14) */ +#define PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_Msk (0x4000UL) /*!< PWRCTRL MEMPWDINSLEEP: FLASH1PWDSLP (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_Pos (13UL) /*!< PWRCTRL MEMPWDINSLEEP: FLASH0PWDSLP (Bit 13) */ +#define PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_Msk (0x2000UL) /*!< PWRCTRL MEMPWDINSLEEP: FLASH0PWDSLP (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_Pos (3UL) /*!< PWRCTRL MEMPWDINSLEEP: SRAMPWDSLP (Bit 3) */ +#define PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_Msk (0x1ff8UL) /*!< PWRCTRL MEMPWDINSLEEP: SRAMPWDSLP (Bitfield-Mask: 0x3ff) */ +#define PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_Pos (0UL) /*!< PWRCTRL MEMPWDINSLEEP: DTCMPWDSLP (Bit 0) */ +#define PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_Msk (0x7UL) /*!< PWRCTRL MEMPWDINSLEEP: DTCMPWDSLP (Bitfield-Mask: 0x07) */ +/* ======================================================= MEMPWREN ======================================================== */ +#define PWRCTRL_MEMPWREN_CACHEB2_Pos (31UL) /*!< PWRCTRL MEMPWREN: CACHEB2 (Bit 31) */ +#define PWRCTRL_MEMPWREN_CACHEB2_Msk (0x80000000UL) /*!< PWRCTRL MEMPWREN: CACHEB2 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWREN_CACHEB0_Pos (30UL) /*!< PWRCTRL MEMPWREN: CACHEB0 (Bit 30) */ +#define PWRCTRL_MEMPWREN_CACHEB0_Msk (0x40000000UL) /*!< PWRCTRL MEMPWREN: CACHEB0 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWREN_FLASH1_Pos (14UL) /*!< PWRCTRL MEMPWREN: FLASH1 (Bit 14) */ +#define PWRCTRL_MEMPWREN_FLASH1_Msk (0x4000UL) /*!< PWRCTRL MEMPWREN: FLASH1 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWREN_FLASH0_Pos (13UL) /*!< PWRCTRL MEMPWREN: FLASH0 (Bit 13) */ +#define PWRCTRL_MEMPWREN_FLASH0_Msk (0x2000UL) /*!< PWRCTRL MEMPWREN: FLASH0 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWREN_SRAM_Pos (3UL) /*!< PWRCTRL MEMPWREN: SRAM (Bit 3) */ +#define PWRCTRL_MEMPWREN_SRAM_Msk (0x1ff8UL) /*!< PWRCTRL MEMPWREN: SRAM (Bitfield-Mask: 0x3ff) */ +#define PWRCTRL_MEMPWREN_DTCM_Pos (0UL) /*!< PWRCTRL MEMPWREN: DTCM (Bit 0) */ +#define PWRCTRL_MEMPWREN_DTCM_Msk (0x7UL) /*!< PWRCTRL MEMPWREN: DTCM (Bitfield-Mask: 0x07) */ +/* ===================================================== MEMPWRSTATUS ====================================================== */ +#define PWRCTRL_MEMPWRSTATUS_CACHEB2_Pos (16UL) /*!< PWRCTRL MEMPWRSTATUS: CACHEB2 (Bit 16) */ +#define PWRCTRL_MEMPWRSTATUS_CACHEB2_Msk (0x10000UL) /*!< PWRCTRL MEMPWRSTATUS: CACHEB2 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_CACHEB0_Pos (15UL) /*!< PWRCTRL MEMPWRSTATUS: CACHEB0 (Bit 15) */ +#define PWRCTRL_MEMPWRSTATUS_CACHEB0_Msk (0x8000UL) /*!< PWRCTRL MEMPWRSTATUS: CACHEB0 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_FLASH1_Pos (14UL) /*!< PWRCTRL MEMPWRSTATUS: FLASH1 (Bit 14) */ +#define PWRCTRL_MEMPWRSTATUS_FLASH1_Msk (0x4000UL) /*!< PWRCTRL MEMPWRSTATUS: FLASH1 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_FLASH0_Pos (13UL) /*!< PWRCTRL MEMPWRSTATUS: FLASH0 (Bit 13) */ +#define PWRCTRL_MEMPWRSTATUS_FLASH0_Msk (0x2000UL) /*!< PWRCTRL MEMPWRSTATUS: FLASH0 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM9_Pos (12UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM9 (Bit 12) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM9_Msk (0x1000UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM9 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM8_Pos (11UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM8 (Bit 11) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM8_Msk (0x800UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM8 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM7_Pos (10UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM7 (Bit 10) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM7_Msk (0x400UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM7 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM6_Pos (9UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM6 (Bit 9) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM6_Msk (0x200UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM6 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM5_Pos (8UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM5 (Bit 8) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM5_Msk (0x100UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM5 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM4_Pos (7UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM4 (Bit 7) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM4_Msk (0x80UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM4 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM3_Pos (6UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM3 (Bit 6) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM3_Msk (0x40UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM3 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM2_Pos (5UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM2 (Bit 5) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM2_Msk (0x20UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM2 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM1_Pos (4UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM1 (Bit 4) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM1_Msk (0x10UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM1 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM0_Pos (3UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM0 (Bit 3) */ +#define PWRCTRL_MEMPWRSTATUS_SRAM0_Msk (0x8UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM0 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_DTCM1_Pos (2UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM1 (Bit 2) */ +#define PWRCTRL_MEMPWRSTATUS_DTCM1_Msk (0x4UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM1 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_DTCM01_Pos (1UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM01 (Bit 1) */ +#define PWRCTRL_MEMPWRSTATUS_DTCM01_Msk (0x2UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM01 (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWRSTATUS_DTCM00_Pos (0UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM00 (Bit 0) */ +#define PWRCTRL_MEMPWRSTATUS_DTCM00_Msk (0x1UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM00 (Bitfield-Mask: 0x01) */ +/* ===================================================== DEVPWRSTATUS ====================================================== */ +#define PWRCTRL_DEVPWRSTATUS_SYSDEEPSLEEP_Pos (31UL) /*!< PWRCTRL DEVPWRSTATUS: SYSDEEPSLEEP (Bit 31) */ +#define PWRCTRL_DEVPWRSTATUS_SYSDEEPSLEEP_Msk (0x80000000UL) /*!< PWRCTRL DEVPWRSTATUS: SYSDEEPSLEEP (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_COREDEEPSLEEP_Pos (30UL) /*!< PWRCTRL DEVPWRSTATUS: COREDEEPSLEEP (Bit 30) */ +#define PWRCTRL_DEVPWRSTATUS_COREDEEPSLEEP_Msk (0x40000000UL) /*!< PWRCTRL DEVPWRSTATUS: COREDEEPSLEEP (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_CORESLEEP_Pos (29UL) /*!< PWRCTRL DEVPWRSTATUS: CORESLEEP (Bit 29) */ +#define PWRCTRL_DEVPWRSTATUS_CORESLEEP_Msk (0x20000000UL) /*!< PWRCTRL DEVPWRSTATUS: CORESLEEP (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_BLEH_Pos (9UL) /*!< PWRCTRL DEVPWRSTATUS: BLEH (Bit 9) */ +#define PWRCTRL_DEVPWRSTATUS_BLEH_Msk (0x200UL) /*!< PWRCTRL DEVPWRSTATUS: BLEH (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_BLEL_Pos (8UL) /*!< PWRCTRL DEVPWRSTATUS: BLEL (Bit 8) */ +#define PWRCTRL_DEVPWRSTATUS_BLEL_Msk (0x100UL) /*!< PWRCTRL DEVPWRSTATUS: BLEL (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_PWRPDM_Pos (7UL) /*!< PWRCTRL DEVPWRSTATUS: PWRPDM (Bit 7) */ +#define PWRCTRL_DEVPWRSTATUS_PWRPDM_Msk (0x80UL) /*!< PWRCTRL DEVPWRSTATUS: PWRPDM (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_PWRMSPI_Pos (6UL) /*!< PWRCTRL DEVPWRSTATUS: PWRMSPI (Bit 6) */ +#define PWRCTRL_DEVPWRSTATUS_PWRMSPI_Msk (0x40UL) /*!< PWRCTRL DEVPWRSTATUS: PWRMSPI (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_PWRADC_Pos (5UL) /*!< PWRCTRL DEVPWRSTATUS: PWRADC (Bit 5) */ +#define PWRCTRL_DEVPWRSTATUS_PWRADC_Msk (0x20UL) /*!< PWRCTRL DEVPWRSTATUS: PWRADC (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_HCPC_Pos (4UL) /*!< PWRCTRL DEVPWRSTATUS: HCPC (Bit 4) */ +#define PWRCTRL_DEVPWRSTATUS_HCPC_Msk (0x10UL) /*!< PWRCTRL DEVPWRSTATUS: HCPC (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_HCPB_Pos (3UL) /*!< PWRCTRL DEVPWRSTATUS: HCPB (Bit 3) */ +#define PWRCTRL_DEVPWRSTATUS_HCPB_Msk (0x8UL) /*!< PWRCTRL DEVPWRSTATUS: HCPB (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_HCPA_Pos (2UL) /*!< PWRCTRL DEVPWRSTATUS: HCPA (Bit 2) */ +#define PWRCTRL_DEVPWRSTATUS_HCPA_Msk (0x4UL) /*!< PWRCTRL DEVPWRSTATUS: HCPA (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_MCUH_Pos (1UL) /*!< PWRCTRL DEVPWRSTATUS: MCUH (Bit 1) */ +#define PWRCTRL_DEVPWRSTATUS_MCUH_Msk (0x2UL) /*!< PWRCTRL DEVPWRSTATUS: MCUH (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWRSTATUS_MCUL_Pos (0UL) /*!< PWRCTRL DEVPWRSTATUS: MCUL (Bit 0) */ +#define PWRCTRL_DEVPWRSTATUS_MCUL_Msk (0x1UL) /*!< PWRCTRL DEVPWRSTATUS: MCUL (Bitfield-Mask: 0x01) */ +/* ======================================================= SRAMCTRL ======================================================== */ +#define PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_Pos (8UL) /*!< PWRCTRL SRAMCTRL: SRAMLIGHTSLEEP (Bit 8) */ +#define PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_Msk (0xfff00UL) /*!< PWRCTRL SRAMCTRL: SRAMLIGHTSLEEP (Bitfield-Mask: 0xfff) */ +#define PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_Pos (2UL) /*!< PWRCTRL SRAMCTRL: SRAMMASTERCLKGATE (Bit 2) */ +#define PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_Msk (0x4UL) /*!< PWRCTRL SRAMCTRL: SRAMMASTERCLKGATE (Bitfield-Mask: 0x01) */ +#define PWRCTRL_SRAMCTRL_SRAMCLKGATE_Pos (1UL) /*!< PWRCTRL SRAMCTRL: SRAMCLKGATE (Bit 1) */ +#define PWRCTRL_SRAMCTRL_SRAMCLKGATE_Msk (0x2UL) /*!< PWRCTRL SRAMCTRL: SRAMCLKGATE (Bitfield-Mask: 0x01) */ +/* ======================================================= ADCSTATUS ======================================================= */ +#define PWRCTRL_ADCSTATUS_REFBUFPWD_Pos (5UL) /*!< PWRCTRL ADCSTATUS: REFBUFPWD (Bit 5) */ +#define PWRCTRL_ADCSTATUS_REFBUFPWD_Msk (0x20UL) /*!< PWRCTRL ADCSTATUS: REFBUFPWD (Bitfield-Mask: 0x01) */ +#define PWRCTRL_ADCSTATUS_REFKEEPPWD_Pos (4UL) /*!< PWRCTRL ADCSTATUS: REFKEEPPWD (Bit 4) */ +#define PWRCTRL_ADCSTATUS_REFKEEPPWD_Msk (0x10UL) /*!< PWRCTRL ADCSTATUS: REFKEEPPWD (Bitfield-Mask: 0x01) */ +#define PWRCTRL_ADCSTATUS_VBATPWD_Pos (3UL) /*!< PWRCTRL ADCSTATUS: VBATPWD (Bit 3) */ +#define PWRCTRL_ADCSTATUS_VBATPWD_Msk (0x8UL) /*!< PWRCTRL ADCSTATUS: VBATPWD (Bitfield-Mask: 0x01) */ +#define PWRCTRL_ADCSTATUS_VPTATPWD_Pos (2UL) /*!< PWRCTRL ADCSTATUS: VPTATPWD (Bit 2) */ +#define PWRCTRL_ADCSTATUS_VPTATPWD_Msk (0x4UL) /*!< PWRCTRL ADCSTATUS: VPTATPWD (Bitfield-Mask: 0x01) */ +#define PWRCTRL_ADCSTATUS_BGTPWD_Pos (1UL) /*!< PWRCTRL ADCSTATUS: BGTPWD (Bit 1) */ +#define PWRCTRL_ADCSTATUS_BGTPWD_Msk (0x2UL) /*!< PWRCTRL ADCSTATUS: BGTPWD (Bitfield-Mask: 0x01) */ +#define PWRCTRL_ADCSTATUS_ADCPWD_Pos (0UL) /*!< PWRCTRL ADCSTATUS: ADCPWD (Bit 0) */ +#define PWRCTRL_ADCSTATUS_ADCPWD_Msk (0x1UL) /*!< PWRCTRL ADCSTATUS: ADCPWD (Bitfield-Mask: 0x01) */ +/* ========================================================= MISC ========================================================== */ +#define PWRCTRL_MISC_FORCEBLEBUCKACT_Pos (7UL) /*!< PWRCTRL MISC: FORCEBLEBUCKACT (Bit 7) */ +#define PWRCTRL_MISC_FORCEBLEBUCKACT_Msk (0x80UL) /*!< PWRCTRL MISC: FORCEBLEBUCKACT (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MISC_MEMVRLPBLE_Pos (6UL) /*!< PWRCTRL MISC: MEMVRLPBLE (Bit 6) */ +#define PWRCTRL_MISC_MEMVRLPBLE_Msk (0x40UL) /*!< PWRCTRL MISC: MEMVRLPBLE (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MISC_FORCEMEMVRADC_Pos (4UL) /*!< PWRCTRL MISC: FORCEMEMVRADC (Bit 4) */ +#define PWRCTRL_MISC_FORCEMEMVRADC_Msk (0x30UL) /*!< PWRCTRL MISC: FORCEMEMVRADC (Bitfield-Mask: 0x03) */ +#define PWRCTRL_MISC_FORCEMEMVRLPTIMERS_Pos (3UL) /*!< PWRCTRL MISC: FORCEMEMVRLPTIMERS (Bit 3) */ +#define PWRCTRL_MISC_FORCEMEMVRLPTIMERS_Msk (0x8UL) /*!< PWRCTRL MISC: FORCEMEMVRLPTIMERS (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MISC_FORCECOREVRLPTIMERS_Pos (2UL) /*!< PWRCTRL MISC: FORCECOREVRLPTIMERS (Bit 2) */ +#define PWRCTRL_MISC_FORCECOREVRLPTIMERS_Msk (0x4UL) /*!< PWRCTRL MISC: FORCECOREVRLPTIMERS (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MISC_FORCECOREVRLPPDM_Pos (1UL) /*!< PWRCTRL MISC: FORCECOREVRLPPDM (Bit 1) */ +#define PWRCTRL_MISC_FORCECOREVRLPPDM_Msk (0x2UL) /*!< PWRCTRL MISC: FORCECOREVRLPPDM (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MISC_SIMOBUCKEN_Pos (0UL) /*!< PWRCTRL MISC: SIMOBUCKEN (Bit 0) */ +#define PWRCTRL_MISC_SIMOBUCKEN_Msk (0x1UL) /*!< PWRCTRL MISC: SIMOBUCKEN (Bitfield-Mask: 0x01) */ +/* ===================================================== DEVPWREVENTEN ===================================================== */ +#define PWRCTRL_DEVPWREVENTEN_BURSTEVEN_Pos (31UL) /*!< PWRCTRL DEVPWREVENTEN: BURSTEVEN (Bit 31) */ +#define PWRCTRL_DEVPWREVENTEN_BURSTEVEN_Msk (0x80000000UL) /*!< PWRCTRL DEVPWREVENTEN: BURSTEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_Pos (30UL) /*!< PWRCTRL DEVPWREVENTEN: BURSTFEATUREEVEN (Bit 30) */ +#define PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_Msk (0x40000000UL) /*!< PWRCTRL DEVPWREVENTEN: BURSTFEATUREEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_Pos (29UL) /*!< PWRCTRL DEVPWREVENTEN: BLEFEATUREEVEN (Bit 29) */ +#define PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_Msk (0x20000000UL) /*!< PWRCTRL DEVPWREVENTEN: BLEFEATUREEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_BLELEVEN_Pos (8UL) /*!< PWRCTRL DEVPWREVENTEN: BLELEVEN (Bit 8) */ +#define PWRCTRL_DEVPWREVENTEN_BLELEVEN_Msk (0x100UL) /*!< PWRCTRL DEVPWREVENTEN: BLELEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_PDMEVEN_Pos (7UL) /*!< PWRCTRL DEVPWREVENTEN: PDMEVEN (Bit 7) */ +#define PWRCTRL_DEVPWREVENTEN_PDMEVEN_Msk (0x80UL) /*!< PWRCTRL DEVPWREVENTEN: PDMEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_MSPIEVEN_Pos (6UL) /*!< PWRCTRL DEVPWREVENTEN: MSPIEVEN (Bit 6) */ +#define PWRCTRL_DEVPWREVENTEN_MSPIEVEN_Msk (0x40UL) /*!< PWRCTRL DEVPWREVENTEN: MSPIEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_ADCEVEN_Pos (5UL) /*!< PWRCTRL DEVPWREVENTEN: ADCEVEN (Bit 5) */ +#define PWRCTRL_DEVPWREVENTEN_ADCEVEN_Msk (0x20UL) /*!< PWRCTRL DEVPWREVENTEN: ADCEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_HCPCEVEN_Pos (4UL) /*!< PWRCTRL DEVPWREVENTEN: HCPCEVEN (Bit 4) */ +#define PWRCTRL_DEVPWREVENTEN_HCPCEVEN_Msk (0x10UL) /*!< PWRCTRL DEVPWREVENTEN: HCPCEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_HCPBEVEN_Pos (3UL) /*!< PWRCTRL DEVPWREVENTEN: HCPBEVEN (Bit 3) */ +#define PWRCTRL_DEVPWREVENTEN_HCPBEVEN_Msk (0x8UL) /*!< PWRCTRL DEVPWREVENTEN: HCPBEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_HCPAEVEN_Pos (2UL) /*!< PWRCTRL DEVPWREVENTEN: HCPAEVEN (Bit 2) */ +#define PWRCTRL_DEVPWREVENTEN_HCPAEVEN_Msk (0x4UL) /*!< PWRCTRL DEVPWREVENTEN: HCPAEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_MCUHEVEN_Pos (1UL) /*!< PWRCTRL DEVPWREVENTEN: MCUHEVEN (Bit 1) */ +#define PWRCTRL_DEVPWREVENTEN_MCUHEVEN_Msk (0x2UL) /*!< PWRCTRL DEVPWREVENTEN: MCUHEVEN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_DEVPWREVENTEN_MCULEVEN_Pos (0UL) /*!< PWRCTRL DEVPWREVENTEN: MCULEVEN (Bit 0) */ +#define PWRCTRL_DEVPWREVENTEN_MCULEVEN_Msk (0x1UL) /*!< PWRCTRL DEVPWREVENTEN: MCULEVEN (Bitfield-Mask: 0x01) */ +/* ===================================================== MEMPWREVENTEN ===================================================== */ +#define PWRCTRL_MEMPWREVENTEN_CACHEB2EN_Pos (31UL) /*!< PWRCTRL MEMPWREVENTEN: CACHEB2EN (Bit 31) */ +#define PWRCTRL_MEMPWREVENTEN_CACHEB2EN_Msk (0x80000000UL) /*!< PWRCTRL MEMPWREVENTEN: CACHEB2EN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWREVENTEN_CACHEB0EN_Pos (30UL) /*!< PWRCTRL MEMPWREVENTEN: CACHEB0EN (Bit 30) */ +#define PWRCTRL_MEMPWREVENTEN_CACHEB0EN_Msk (0x40000000UL) /*!< PWRCTRL MEMPWREVENTEN: CACHEB0EN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWREVENTEN_FLASH1EN_Pos (14UL) /*!< PWRCTRL MEMPWREVENTEN: FLASH1EN (Bit 14) */ +#define PWRCTRL_MEMPWREVENTEN_FLASH1EN_Msk (0x4000UL) /*!< PWRCTRL MEMPWREVENTEN: FLASH1EN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWREVENTEN_FLASH0EN_Pos (13UL) /*!< PWRCTRL MEMPWREVENTEN: FLASH0EN (Bit 13) */ +#define PWRCTRL_MEMPWREVENTEN_FLASH0EN_Msk (0x2000UL) /*!< PWRCTRL MEMPWREVENTEN: FLASH0EN (Bitfield-Mask: 0x01) */ +#define PWRCTRL_MEMPWREVENTEN_SRAMEN_Pos (3UL) /*!< PWRCTRL MEMPWREVENTEN: SRAMEN (Bit 3) */ +#define PWRCTRL_MEMPWREVENTEN_SRAMEN_Msk (0x1ff8UL) /*!< PWRCTRL MEMPWREVENTEN: SRAMEN (Bitfield-Mask: 0x3ff) */ +#define PWRCTRL_MEMPWREVENTEN_DTCMEN_Pos (0UL) /*!< PWRCTRL MEMPWREVENTEN: DTCMEN (Bit 0) */ +#define PWRCTRL_MEMPWREVENTEN_DTCMEN_Msk (0x7UL) /*!< PWRCTRL MEMPWREVENTEN: DTCMEN (Bitfield-Mask: 0x07) */ + + +/* =========================================================================================================================== */ +/* ================ RSTGEN ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== CFG ========================================================== */ +#define RSTGEN_CFG_WDREN_Pos (1UL) /*!< RSTGEN CFG: WDREN (Bit 1) */ +#define RSTGEN_CFG_WDREN_Msk (0x2UL) /*!< RSTGEN CFG: WDREN (Bitfield-Mask: 0x01) */ +#define RSTGEN_CFG_BODHREN_Pos (0UL) /*!< RSTGEN CFG: BODHREN (Bit 0) */ +#define RSTGEN_CFG_BODHREN_Msk (0x1UL) /*!< RSTGEN CFG: BODHREN (Bitfield-Mask: 0x01) */ +/* ========================================================= SWPOI ========================================================= */ +#define RSTGEN_SWPOI_SWPOIKEY_Pos (0UL) /*!< RSTGEN SWPOI: SWPOIKEY (Bit 0) */ +#define RSTGEN_SWPOI_SWPOIKEY_Msk (0xffUL) /*!< RSTGEN SWPOI: SWPOIKEY (Bitfield-Mask: 0xff) */ +/* ========================================================= SWPOR ========================================================= */ +#define RSTGEN_SWPOR_SWPORKEY_Pos (0UL) /*!< RSTGEN SWPOR: SWPORKEY (Bit 0) */ +#define RSTGEN_SWPOR_SWPORKEY_Msk (0xffUL) /*!< RSTGEN SWPOR: SWPORKEY (Bitfield-Mask: 0xff) */ +/* ======================================================== TPIURST ======================================================== */ +#define RSTGEN_TPIURST_TPIURST_Pos (0UL) /*!< RSTGEN TPIURST: TPIURST (Bit 0) */ +#define RSTGEN_TPIURST_TPIURST_Msk (0x1UL) /*!< RSTGEN TPIURST: TPIURST (Bitfield-Mask: 0x01) */ +/* ========================================================= INTEN ========================================================= */ +#define RSTGEN_INTEN_BODH_Pos (0UL) /*!< RSTGEN INTEN: BODH (Bit 0) */ +#define RSTGEN_INTEN_BODH_Msk (0x1UL) /*!< RSTGEN INTEN: BODH (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define RSTGEN_INTSTAT_BODH_Pos (0UL) /*!< RSTGEN INTSTAT: BODH (Bit 0) */ +#define RSTGEN_INTSTAT_BODH_Msk (0x1UL) /*!< RSTGEN INTSTAT: BODH (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define RSTGEN_INTCLR_BODH_Pos (0UL) /*!< RSTGEN INTCLR: BODH (Bit 0) */ +#define RSTGEN_INTCLR_BODH_Msk (0x1UL) /*!< RSTGEN INTCLR: BODH (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define RSTGEN_INTSET_BODH_Pos (0UL) /*!< RSTGEN INTSET: BODH (Bit 0) */ +#define RSTGEN_INTSET_BODH_Msk (0x1UL) /*!< RSTGEN INTSET: BODH (Bitfield-Mask: 0x01) */ +/* ========================================================= STAT ========================================================== */ +#define RSTGEN_STAT_SBOOT_Pos (31UL) /*!< RSTGEN STAT: SBOOT (Bit 31) */ +#define RSTGEN_STAT_SBOOT_Msk (0x80000000UL) /*!< RSTGEN STAT: SBOOT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_FBOOT_Pos (30UL) /*!< RSTGEN STAT: FBOOT (Bit 30) */ +#define RSTGEN_STAT_FBOOT_Msk (0x40000000UL) /*!< RSTGEN STAT: FBOOT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_BOBSTAT_Pos (10UL) /*!< RSTGEN STAT: BOBSTAT (Bit 10) */ +#define RSTGEN_STAT_BOBSTAT_Msk (0x400UL) /*!< RSTGEN STAT: BOBSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_BOFSTAT_Pos (9UL) /*!< RSTGEN STAT: BOFSTAT (Bit 9) */ +#define RSTGEN_STAT_BOFSTAT_Msk (0x200UL) /*!< RSTGEN STAT: BOFSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_BOCSTAT_Pos (8UL) /*!< RSTGEN STAT: BOCSTAT (Bit 8) */ +#define RSTGEN_STAT_BOCSTAT_Msk (0x100UL) /*!< RSTGEN STAT: BOCSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_BOUSTAT_Pos (7UL) /*!< RSTGEN STAT: BOUSTAT (Bit 7) */ +#define RSTGEN_STAT_BOUSTAT_Msk (0x80UL) /*!< RSTGEN STAT: BOUSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_WDRSTAT_Pos (6UL) /*!< RSTGEN STAT: WDRSTAT (Bit 6) */ +#define RSTGEN_STAT_WDRSTAT_Msk (0x40UL) /*!< RSTGEN STAT: WDRSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_DBGRSTAT_Pos (5UL) /*!< RSTGEN STAT: DBGRSTAT (Bit 5) */ +#define RSTGEN_STAT_DBGRSTAT_Msk (0x20UL) /*!< RSTGEN STAT: DBGRSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_POIRSTAT_Pos (4UL) /*!< RSTGEN STAT: POIRSTAT (Bit 4) */ +#define RSTGEN_STAT_POIRSTAT_Msk (0x10UL) /*!< RSTGEN STAT: POIRSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_SWRSTAT_Pos (3UL) /*!< RSTGEN STAT: SWRSTAT (Bit 3) */ +#define RSTGEN_STAT_SWRSTAT_Msk (0x8UL) /*!< RSTGEN STAT: SWRSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_BORSTAT_Pos (2UL) /*!< RSTGEN STAT: BORSTAT (Bit 2) */ +#define RSTGEN_STAT_BORSTAT_Msk (0x4UL) /*!< RSTGEN STAT: BORSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_PORSTAT_Pos (1UL) /*!< RSTGEN STAT: PORSTAT (Bit 1) */ +#define RSTGEN_STAT_PORSTAT_Msk (0x2UL) /*!< RSTGEN STAT: PORSTAT (Bitfield-Mask: 0x01) */ +#define RSTGEN_STAT_EXRSTAT_Pos (0UL) /*!< RSTGEN STAT: EXRSTAT (Bit 0) */ +#define RSTGEN_STAT_EXRSTAT_Msk (0x1UL) /*!< RSTGEN STAT: EXRSTAT (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ RTC ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== CTRLOW ========================================================= */ +#define RTC_CTRLOW_CTRHR_Pos (24UL) /*!< RTC CTRLOW: CTRHR (Bit 24) */ +#define RTC_CTRLOW_CTRHR_Msk (0x3f000000UL) /*!< RTC CTRLOW: CTRHR (Bitfield-Mask: 0x3f) */ +#define RTC_CTRLOW_CTRMIN_Pos (16UL) /*!< RTC CTRLOW: CTRMIN (Bit 16) */ +#define RTC_CTRLOW_CTRMIN_Msk (0x7f0000UL) /*!< RTC CTRLOW: CTRMIN (Bitfield-Mask: 0x7f) */ +#define RTC_CTRLOW_CTRSEC_Pos (8UL) /*!< RTC CTRLOW: CTRSEC (Bit 8) */ +#define RTC_CTRLOW_CTRSEC_Msk (0x7f00UL) /*!< RTC CTRLOW: CTRSEC (Bitfield-Mask: 0x7f) */ +#define RTC_CTRLOW_CTR100_Pos (0UL) /*!< RTC CTRLOW: CTR100 (Bit 0) */ +#define RTC_CTRLOW_CTR100_Msk (0xffUL) /*!< RTC CTRLOW: CTR100 (Bitfield-Mask: 0xff) */ +/* ========================================================= CTRUP ========================================================= */ +#define RTC_CTRUP_CTERR_Pos (31UL) /*!< RTC CTRUP: CTERR (Bit 31) */ +#define RTC_CTRUP_CTERR_Msk (0x80000000UL) /*!< RTC CTRUP: CTERR (Bitfield-Mask: 0x01) */ +#define RTC_CTRUP_CEB_Pos (28UL) /*!< RTC CTRUP: CEB (Bit 28) */ +#define RTC_CTRUP_CEB_Msk (0x10000000UL) /*!< RTC CTRUP: CEB (Bitfield-Mask: 0x01) */ +#define RTC_CTRUP_CB_Pos (27UL) /*!< RTC CTRUP: CB (Bit 27) */ +#define RTC_CTRUP_CB_Msk (0x8000000UL) /*!< RTC CTRUP: CB (Bitfield-Mask: 0x01) */ +#define RTC_CTRUP_CTRWKDY_Pos (24UL) /*!< RTC CTRUP: CTRWKDY (Bit 24) */ +#define RTC_CTRUP_CTRWKDY_Msk (0x7000000UL) /*!< RTC CTRUP: CTRWKDY (Bitfield-Mask: 0x07) */ +#define RTC_CTRUP_CTRYR_Pos (16UL) /*!< RTC CTRUP: CTRYR (Bit 16) */ +#define RTC_CTRUP_CTRYR_Msk (0xff0000UL) /*!< RTC CTRUP: CTRYR (Bitfield-Mask: 0xff) */ +#define RTC_CTRUP_CTRMO_Pos (8UL) /*!< RTC CTRUP: CTRMO (Bit 8) */ +#define RTC_CTRUP_CTRMO_Msk (0x1f00UL) /*!< RTC CTRUP: CTRMO (Bitfield-Mask: 0x1f) */ +#define RTC_CTRUP_CTRDATE_Pos (0UL) /*!< RTC CTRUP: CTRDATE (Bit 0) */ +#define RTC_CTRUP_CTRDATE_Msk (0x3fUL) /*!< RTC CTRUP: CTRDATE (Bitfield-Mask: 0x3f) */ +/* ======================================================== ALMLOW ========================================================= */ +#define RTC_ALMLOW_ALMHR_Pos (24UL) /*!< RTC ALMLOW: ALMHR (Bit 24) */ +#define RTC_ALMLOW_ALMHR_Msk (0x3f000000UL) /*!< RTC ALMLOW: ALMHR (Bitfield-Mask: 0x3f) */ +#define RTC_ALMLOW_ALMMIN_Pos (16UL) /*!< RTC ALMLOW: ALMMIN (Bit 16) */ +#define RTC_ALMLOW_ALMMIN_Msk (0x7f0000UL) /*!< RTC ALMLOW: ALMMIN (Bitfield-Mask: 0x7f) */ +#define RTC_ALMLOW_ALMSEC_Pos (8UL) /*!< RTC ALMLOW: ALMSEC (Bit 8) */ +#define RTC_ALMLOW_ALMSEC_Msk (0x7f00UL) /*!< RTC ALMLOW: ALMSEC (Bitfield-Mask: 0x7f) */ +#define RTC_ALMLOW_ALM100_Pos (0UL) /*!< RTC ALMLOW: ALM100 (Bit 0) */ +#define RTC_ALMLOW_ALM100_Msk (0xffUL) /*!< RTC ALMLOW: ALM100 (Bitfield-Mask: 0xff) */ +/* ========================================================= ALMUP ========================================================= */ +#define RTC_ALMUP_ALMWKDY_Pos (16UL) /*!< RTC ALMUP: ALMWKDY (Bit 16) */ +#define RTC_ALMUP_ALMWKDY_Msk (0x70000UL) /*!< RTC ALMUP: ALMWKDY (Bitfield-Mask: 0x07) */ +#define RTC_ALMUP_ALMMO_Pos (8UL) /*!< RTC ALMUP: ALMMO (Bit 8) */ +#define RTC_ALMUP_ALMMO_Msk (0x1f00UL) /*!< RTC ALMUP: ALMMO (Bitfield-Mask: 0x1f) */ +#define RTC_ALMUP_ALMDATE_Pos (0UL) /*!< RTC ALMUP: ALMDATE (Bit 0) */ +#define RTC_ALMUP_ALMDATE_Msk (0x3fUL) /*!< RTC ALMUP: ALMDATE (Bitfield-Mask: 0x3f) */ +/* ======================================================== RTCCTL ========================================================= */ +#define RTC_RTCCTL_HR1224_Pos (5UL) /*!< RTC RTCCTL: HR1224 (Bit 5) */ +#define RTC_RTCCTL_HR1224_Msk (0x20UL) /*!< RTC RTCCTL: HR1224 (Bitfield-Mask: 0x01) */ +#define RTC_RTCCTL_RSTOP_Pos (4UL) /*!< RTC RTCCTL: RSTOP (Bit 4) */ +#define RTC_RTCCTL_RSTOP_Msk (0x10UL) /*!< RTC RTCCTL: RSTOP (Bitfield-Mask: 0x01) */ +#define RTC_RTCCTL_RPT_Pos (1UL) /*!< RTC RTCCTL: RPT (Bit 1) */ +#define RTC_RTCCTL_RPT_Msk (0xeUL) /*!< RTC RTCCTL: RPT (Bitfield-Mask: 0x07) */ +#define RTC_RTCCTL_WRTC_Pos (0UL) /*!< RTC RTCCTL: WRTC (Bit 0) */ +#define RTC_RTCCTL_WRTC_Msk (0x1UL) /*!< RTC RTCCTL: WRTC (Bitfield-Mask: 0x01) */ +/* ========================================================= INTEN ========================================================= */ +#define RTC_INTEN_ALM_Pos (0UL) /*!< RTC INTEN: ALM (Bit 0) */ +#define RTC_INTEN_ALM_Msk (0x1UL) /*!< RTC INTEN: ALM (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define RTC_INTSTAT_ALM_Pos (0UL) /*!< RTC INTSTAT: ALM (Bit 0) */ +#define RTC_INTSTAT_ALM_Msk (0x1UL) /*!< RTC INTSTAT: ALM (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define RTC_INTCLR_ALM_Pos (0UL) /*!< RTC INTCLR: ALM (Bit 0) */ +#define RTC_INTCLR_ALM_Msk (0x1UL) /*!< RTC INTCLR: ALM (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define RTC_INTSET_ALM_Pos (0UL) /*!< RTC INTSET: ALM (Bit 0) */ +#define RTC_INTSET_ALM_Msk (0x1UL) /*!< RTC INTSET: ALM (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ SCARD ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== SR =========================================================== */ +#define SCARD_SR_FHF_Pos (6UL) /*!< SCARD SR: FHF (Bit 6) */ +#define SCARD_SR_FHF_Msk (0x40UL) /*!< SCARD SR: FHF (Bitfield-Mask: 0x01) */ +#define SCARD_SR_FT2REND_Pos (5UL) /*!< SCARD SR: FT2REND (Bit 5) */ +#define SCARD_SR_FT2REND_Msk (0x20UL) /*!< SCARD SR: FT2REND (Bitfield-Mask: 0x01) */ +#define SCARD_SR_PE_Pos (4UL) /*!< SCARD SR: PE (Bit 4) */ +#define SCARD_SR_PE_Msk (0x10UL) /*!< SCARD SR: PE (Bitfield-Mask: 0x01) */ +#define SCARD_SR_OVR_Pos (3UL) /*!< SCARD SR: OVR (Bit 3) */ +#define SCARD_SR_OVR_Msk (0x8UL) /*!< SCARD SR: OVR (Bitfield-Mask: 0x01) */ +#define SCARD_SR_FER_Pos (2UL) /*!< SCARD SR: FER (Bit 2) */ +#define SCARD_SR_FER_Msk (0x4UL) /*!< SCARD SR: FER (Bitfield-Mask: 0x01) */ +#define SCARD_SR_TBERBF_Pos (1UL) /*!< SCARD SR: TBERBF (Bit 1) */ +#define SCARD_SR_TBERBF_Msk (0x2UL) /*!< SCARD SR: TBERBF (Bitfield-Mask: 0x01) */ +#define SCARD_SR_FNE_Pos (0UL) /*!< SCARD SR: FNE (Bit 0) */ +#define SCARD_SR_FNE_Msk (0x1UL) /*!< SCARD SR: FNE (Bitfield-Mask: 0x01) */ +/* ========================================================== DR =========================================================== */ +#define SCARD_DR_DR_Pos (0UL) /*!< SCARD DR: DR (Bit 0) */ +#define SCARD_DR_DR_Msk (0xffUL) /*!< SCARD DR: DR (Bitfield-Mask: 0xff) */ +/* ========================================================== SR1 ========================================================== */ +#define SCARD_SR1_IDLE_Pos (3UL) /*!< SCARD SR1: IDLE (Bit 3) */ +#define SCARD_SR1_IDLE_Msk (0x8UL) /*!< SCARD SR1: IDLE (Bitfield-Mask: 0x01) */ +#define SCARD_SR1_SYNCEND_Pos (2UL) /*!< SCARD SR1: SYNCEND (Bit 2) */ +#define SCARD_SR1_SYNCEND_Msk (0x4UL) /*!< SCARD SR1: SYNCEND (Bitfield-Mask: 0x01) */ +#define SCARD_SR1_PRL_Pos (1UL) /*!< SCARD SR1: PRL (Bit 1) */ +#define SCARD_SR1_PRL_Msk (0x2UL) /*!< SCARD SR1: PRL (Bitfield-Mask: 0x01) */ +#define SCARD_SR1_ECNTOVER_Pos (0UL) /*!< SCARD SR1: ECNTOVER (Bit 0) */ +#define SCARD_SR1_ECNTOVER_Msk (0x1UL) /*!< SCARD SR1: ECNTOVER (Bitfield-Mask: 0x01) */ +/* ====================================================== RETXCNTRMI ======================================================= */ +#define SCARD_RETXCNTRMI_RETXCNTRMI_Pos (0UL) /*!< SCARD RETXCNTRMI: RETXCNTRMI (Bit 0) */ +#define SCARD_RETXCNTRMI_RETXCNTRMI_Msk (0xfUL) /*!< SCARD RETXCNTRMI: RETXCNTRMI (Bitfield-Mask: 0x0f) */ +/* ======================================================== CLKCTRL ======================================================== */ +#define SCARD_CLKCTRL_APBCLKEN_Pos (1UL) /*!< SCARD CLKCTRL: APBCLKEN (Bit 1) */ +#define SCARD_CLKCTRL_APBCLKEN_Msk (0x2UL) /*!< SCARD CLKCTRL: APBCLKEN (Bitfield-Mask: 0x01) */ +#define SCARD_CLKCTRL_CLKEN_Pos (0UL) /*!< SCARD CLKCTRL: CLKEN (Bit 0) */ +#define SCARD_CLKCTRL_CLKEN_Msk (0x1UL) /*!< SCARD CLKCTRL: CLKEN (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ SECURITY ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= CTRL ========================================================== */ +#define SECURITY_CTRL_CRCERROR_Pos (31UL) /*!< SECURITY CTRL: CRCERROR (Bit 31) */ +#define SECURITY_CTRL_CRCERROR_Msk (0x80000000UL) /*!< SECURITY CTRL: CRCERROR (Bitfield-Mask: 0x01) */ +#define SECURITY_CTRL_FUNCTION_Pos (4UL) /*!< SECURITY CTRL: FUNCTION (Bit 4) */ +#define SECURITY_CTRL_FUNCTION_Msk (0xf0UL) /*!< SECURITY CTRL: FUNCTION (Bitfield-Mask: 0x0f) */ +#define SECURITY_CTRL_ENABLE_Pos (0UL) /*!< SECURITY CTRL: ENABLE (Bit 0) */ +#define SECURITY_CTRL_ENABLE_Msk (0x1UL) /*!< SECURITY CTRL: ENABLE (Bitfield-Mask: 0x01) */ +/* ======================================================== SRCADDR ======================================================== */ +#define SECURITY_SRCADDR_ADDR_Pos (0UL) /*!< SECURITY SRCADDR: ADDR (Bit 0) */ +#define SECURITY_SRCADDR_ADDR_Msk (0xffffffffUL) /*!< SECURITY SRCADDR: ADDR (Bitfield-Mask: 0xffffffff) */ +/* ========================================================== LEN ========================================================== */ +#define SECURITY_LEN_LEN_Pos (2UL) /*!< SECURITY LEN: LEN (Bit 2) */ +#define SECURITY_LEN_LEN_Msk (0xffffcUL) /*!< SECURITY LEN: LEN (Bitfield-Mask: 0x3ffff) */ +/* ======================================================== RESULT ========================================================= */ +#define SECURITY_RESULT_CRC_Pos (0UL) /*!< SECURITY RESULT: CRC (Bit 0) */ +#define SECURITY_RESULT_CRC_Msk (0xffffffffUL) /*!< SECURITY RESULT: CRC (Bitfield-Mask: 0xffffffff) */ +/* ======================================================= LOCKCTRL ======================================================== */ +#define SECURITY_LOCKCTRL_SELECT_Pos (0UL) /*!< SECURITY LOCKCTRL: SELECT (Bit 0) */ +#define SECURITY_LOCKCTRL_SELECT_Msk (0xffUL) /*!< SECURITY LOCKCTRL: SELECT (Bitfield-Mask: 0xff) */ +/* ======================================================= LOCKSTAT ======================================================== */ +#define SECURITY_LOCKSTAT_STATUS_Pos (0UL) /*!< SECURITY LOCKSTAT: STATUS (Bit 0) */ +#define SECURITY_LOCKSTAT_STATUS_Msk (0xffffffffUL) /*!< SECURITY LOCKSTAT: STATUS (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= KEY0 ========================================================== */ +#define SECURITY_KEY0_KEY0_Pos (0UL) /*!< SECURITY KEY0: KEY0 (Bit 0) */ +#define SECURITY_KEY0_KEY0_Msk (0xffffffffUL) /*!< SECURITY KEY0: KEY0 (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= KEY1 ========================================================== */ +#define SECURITY_KEY1_KEY1_Pos (0UL) /*!< SECURITY KEY1: KEY1 (Bit 0) */ +#define SECURITY_KEY1_KEY1_Msk (0xffffffffUL) /*!< SECURITY KEY1: KEY1 (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= KEY2 ========================================================== */ +#define SECURITY_KEY2_KEY2_Pos (0UL) /*!< SECURITY KEY2: KEY2 (Bit 0) */ +#define SECURITY_KEY2_KEY2_Msk (0xffffffffUL) /*!< SECURITY KEY2: KEY2 (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= KEY3 ========================================================== */ +#define SECURITY_KEY3_KEY3_Pos (0UL) /*!< SECURITY KEY3: KEY3 (Bit 0) */ +#define SECURITY_KEY3_KEY3_Msk (0xffffffffUL) /*!< SECURITY KEY3: KEY3 (Bitfield-Mask: 0xffffffff) */ + + +/* =========================================================================================================================== */ +/* ================ UART0 ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== DR =========================================================== */ +#define UART0_DR_OEDATA_Pos (11UL) /*!< UART0 DR: OEDATA (Bit 11) */ +#define UART0_DR_OEDATA_Msk (0x800UL) /*!< UART0 DR: OEDATA (Bitfield-Mask: 0x01) */ +#define UART0_DR_BEDATA_Pos (10UL) /*!< UART0 DR: BEDATA (Bit 10) */ +#define UART0_DR_BEDATA_Msk (0x400UL) /*!< UART0 DR: BEDATA (Bitfield-Mask: 0x01) */ +#define UART0_DR_PEDATA_Pos (9UL) /*!< UART0 DR: PEDATA (Bit 9) */ +#define UART0_DR_PEDATA_Msk (0x200UL) /*!< UART0 DR: PEDATA (Bitfield-Mask: 0x01) */ +#define UART0_DR_FEDATA_Pos (8UL) /*!< UART0 DR: FEDATA (Bit 8) */ +#define UART0_DR_FEDATA_Msk (0x100UL) /*!< UART0 DR: FEDATA (Bitfield-Mask: 0x01) */ +#define UART0_DR_DATA_Pos (0UL) /*!< UART0 DR: DATA (Bit 0) */ +#define UART0_DR_DATA_Msk (0xffUL) /*!< UART0 DR: DATA (Bitfield-Mask: 0xff) */ +/* ========================================================== RSR ========================================================== */ +#define UART0_RSR_OESTAT_Pos (3UL) /*!< UART0 RSR: OESTAT (Bit 3) */ +#define UART0_RSR_OESTAT_Msk (0x8UL) /*!< UART0 RSR: OESTAT (Bitfield-Mask: 0x01) */ +#define UART0_RSR_BESTAT_Pos (2UL) /*!< UART0 RSR: BESTAT (Bit 2) */ +#define UART0_RSR_BESTAT_Msk (0x4UL) /*!< UART0 RSR: BESTAT (Bitfield-Mask: 0x01) */ +#define UART0_RSR_PESTAT_Pos (1UL) /*!< UART0 RSR: PESTAT (Bit 1) */ +#define UART0_RSR_PESTAT_Msk (0x2UL) /*!< UART0 RSR: PESTAT (Bitfield-Mask: 0x01) */ +#define UART0_RSR_FESTAT_Pos (0UL) /*!< UART0 RSR: FESTAT (Bit 0) */ +#define UART0_RSR_FESTAT_Msk (0x1UL) /*!< UART0 RSR: FESTAT (Bitfield-Mask: 0x01) */ +/* ========================================================== FR =========================================================== */ +#define UART0_FR_TXBUSY_Pos (8UL) /*!< UART0 FR: TXBUSY (Bit 8) */ +#define UART0_FR_TXBUSY_Msk (0x100UL) /*!< UART0 FR: TXBUSY (Bitfield-Mask: 0x01) */ +#define UART0_FR_TXFE_Pos (7UL) /*!< UART0 FR: TXFE (Bit 7) */ +#define UART0_FR_TXFE_Msk (0x80UL) /*!< UART0 FR: TXFE (Bitfield-Mask: 0x01) */ +#define UART0_FR_RXFF_Pos (6UL) /*!< UART0 FR: RXFF (Bit 6) */ +#define UART0_FR_RXFF_Msk (0x40UL) /*!< UART0 FR: RXFF (Bitfield-Mask: 0x01) */ +#define UART0_FR_TXFF_Pos (5UL) /*!< UART0 FR: TXFF (Bit 5) */ +#define UART0_FR_TXFF_Msk (0x20UL) /*!< UART0 FR: TXFF (Bitfield-Mask: 0x01) */ +#define UART0_FR_RXFE_Pos (4UL) /*!< UART0 FR: RXFE (Bit 4) */ +#define UART0_FR_RXFE_Msk (0x10UL) /*!< UART0 FR: RXFE (Bitfield-Mask: 0x01) */ +#define UART0_FR_BUSY_Pos (3UL) /*!< UART0 FR: BUSY (Bit 3) */ +#define UART0_FR_BUSY_Msk (0x8UL) /*!< UART0 FR: BUSY (Bitfield-Mask: 0x01) */ +#define UART0_FR_DCD_Pos (2UL) /*!< UART0 FR: DCD (Bit 2) */ +#define UART0_FR_DCD_Msk (0x4UL) /*!< UART0 FR: DCD (Bitfield-Mask: 0x01) */ +#define UART0_FR_DSR_Pos (1UL) /*!< UART0 FR: DSR (Bit 1) */ +#define UART0_FR_DSR_Msk (0x2UL) /*!< UART0 FR: DSR (Bitfield-Mask: 0x01) */ +#define UART0_FR_CTS_Pos (0UL) /*!< UART0 FR: CTS (Bit 0) */ +#define UART0_FR_CTS_Msk (0x1UL) /*!< UART0 FR: CTS (Bitfield-Mask: 0x01) */ +/* ========================================================= ILPR ========================================================== */ +#define UART0_ILPR_ILPDVSR_Pos (0UL) /*!< UART0 ILPR: ILPDVSR (Bit 0) */ +#define UART0_ILPR_ILPDVSR_Msk (0xffUL) /*!< UART0 ILPR: ILPDVSR (Bitfield-Mask: 0xff) */ +/* ========================================================= IBRD ========================================================== */ +#define UART0_IBRD_DIVINT_Pos (0UL) /*!< UART0 IBRD: DIVINT (Bit 0) */ +#define UART0_IBRD_DIVINT_Msk (0xffffUL) /*!< UART0 IBRD: DIVINT (Bitfield-Mask: 0xffff) */ +/* ========================================================= FBRD ========================================================== */ +#define UART0_FBRD_DIVFRAC_Pos (0UL) /*!< UART0 FBRD: DIVFRAC (Bit 0) */ +#define UART0_FBRD_DIVFRAC_Msk (0x3fUL) /*!< UART0 FBRD: DIVFRAC (Bitfield-Mask: 0x3f) */ +/* ========================================================= LCRH ========================================================== */ +#define UART0_LCRH_SPS_Pos (7UL) /*!< UART0 LCRH: SPS (Bit 7) */ +#define UART0_LCRH_SPS_Msk (0x80UL) /*!< UART0 LCRH: SPS (Bitfield-Mask: 0x01) */ +#define UART0_LCRH_WLEN_Pos (5UL) /*!< UART0 LCRH: WLEN (Bit 5) */ +#define UART0_LCRH_WLEN_Msk (0x60UL) /*!< UART0 LCRH: WLEN (Bitfield-Mask: 0x03) */ +#define UART0_LCRH_FEN_Pos (4UL) /*!< UART0 LCRH: FEN (Bit 4) */ +#define UART0_LCRH_FEN_Msk (0x10UL) /*!< UART0 LCRH: FEN (Bitfield-Mask: 0x01) */ +#define UART0_LCRH_STP2_Pos (3UL) /*!< UART0 LCRH: STP2 (Bit 3) */ +#define UART0_LCRH_STP2_Msk (0x8UL) /*!< UART0 LCRH: STP2 (Bitfield-Mask: 0x01) */ +#define UART0_LCRH_EPS_Pos (2UL) /*!< UART0 LCRH: EPS (Bit 2) */ +#define UART0_LCRH_EPS_Msk (0x4UL) /*!< UART0 LCRH: EPS (Bitfield-Mask: 0x01) */ +#define UART0_LCRH_PEN_Pos (1UL) /*!< UART0 LCRH: PEN (Bit 1) */ +#define UART0_LCRH_PEN_Msk (0x2UL) /*!< UART0 LCRH: PEN (Bitfield-Mask: 0x01) */ +#define UART0_LCRH_BRK_Pos (0UL) /*!< UART0 LCRH: BRK (Bit 0) */ +#define UART0_LCRH_BRK_Msk (0x1UL) /*!< UART0 LCRH: BRK (Bitfield-Mask: 0x01) */ +/* ========================================================== CR =========================================================== */ +#define UART0_CR_CTSEN_Pos (15UL) /*!< UART0 CR: CTSEN (Bit 15) */ +#define UART0_CR_CTSEN_Msk (0x8000UL) /*!< UART0 CR: CTSEN (Bitfield-Mask: 0x01) */ +#define UART0_CR_RTSEN_Pos (14UL) /*!< UART0 CR: RTSEN (Bit 14) */ +#define UART0_CR_RTSEN_Msk (0x4000UL) /*!< UART0 CR: RTSEN (Bitfield-Mask: 0x01) */ +#define UART0_CR_OUT2_Pos (13UL) /*!< UART0 CR: OUT2 (Bit 13) */ +#define UART0_CR_OUT2_Msk (0x2000UL) /*!< UART0 CR: OUT2 (Bitfield-Mask: 0x01) */ +#define UART0_CR_OUT1_Pos (12UL) /*!< UART0 CR: OUT1 (Bit 12) */ +#define UART0_CR_OUT1_Msk (0x1000UL) /*!< UART0 CR: OUT1 (Bitfield-Mask: 0x01) */ +#define UART0_CR_RTS_Pos (11UL) /*!< UART0 CR: RTS (Bit 11) */ +#define UART0_CR_RTS_Msk (0x800UL) /*!< UART0 CR: RTS (Bitfield-Mask: 0x01) */ +#define UART0_CR_DTR_Pos (10UL) /*!< UART0 CR: DTR (Bit 10) */ +#define UART0_CR_DTR_Msk (0x400UL) /*!< UART0 CR: DTR (Bitfield-Mask: 0x01) */ +#define UART0_CR_RXE_Pos (9UL) /*!< UART0 CR: RXE (Bit 9) */ +#define UART0_CR_RXE_Msk (0x200UL) /*!< UART0 CR: RXE (Bitfield-Mask: 0x01) */ +#define UART0_CR_TXE_Pos (8UL) /*!< UART0 CR: TXE (Bit 8) */ +#define UART0_CR_TXE_Msk (0x100UL) /*!< UART0 CR: TXE (Bitfield-Mask: 0x01) */ +#define UART0_CR_LBE_Pos (7UL) /*!< UART0 CR: LBE (Bit 7) */ +#define UART0_CR_LBE_Msk (0x80UL) /*!< UART0 CR: LBE (Bitfield-Mask: 0x01) */ +#define UART0_CR_CLKSEL_Pos (4UL) /*!< UART0 CR: CLKSEL (Bit 4) */ +#define UART0_CR_CLKSEL_Msk (0x70UL) /*!< UART0 CR: CLKSEL (Bitfield-Mask: 0x07) */ +#define UART0_CR_CLKEN_Pos (3UL) /*!< UART0 CR: CLKEN (Bit 3) */ +#define UART0_CR_CLKEN_Msk (0x8UL) /*!< UART0 CR: CLKEN (Bitfield-Mask: 0x01) */ +#define UART0_CR_SIRLP_Pos (2UL) /*!< UART0 CR: SIRLP (Bit 2) */ +#define UART0_CR_SIRLP_Msk (0x4UL) /*!< UART0 CR: SIRLP (Bitfield-Mask: 0x01) */ +#define UART0_CR_SIREN_Pos (1UL) /*!< UART0 CR: SIREN (Bit 1) */ +#define UART0_CR_SIREN_Msk (0x2UL) /*!< UART0 CR: SIREN (Bitfield-Mask: 0x01) */ +#define UART0_CR_UARTEN_Pos (0UL) /*!< UART0 CR: UARTEN (Bit 0) */ +#define UART0_CR_UARTEN_Msk (0x1UL) /*!< UART0 CR: UARTEN (Bitfield-Mask: 0x01) */ +/* ========================================================= IFLS ========================================================== */ +#define UART0_IFLS_RXIFLSEL_Pos (3UL) /*!< UART0 IFLS: RXIFLSEL (Bit 3) */ +#define UART0_IFLS_RXIFLSEL_Msk (0x38UL) /*!< UART0 IFLS: RXIFLSEL (Bitfield-Mask: 0x07) */ +#define UART0_IFLS_TXIFLSEL_Pos (0UL) /*!< UART0 IFLS: TXIFLSEL (Bit 0) */ +#define UART0_IFLS_TXIFLSEL_Msk (0x7UL) /*!< UART0 IFLS: TXIFLSEL (Bitfield-Mask: 0x07) */ +/* ========================================================== IER ========================================================== */ +#define UART0_IER_OEIM_Pos (10UL) /*!< UART0 IER: OEIM (Bit 10) */ +#define UART0_IER_OEIM_Msk (0x400UL) /*!< UART0 IER: OEIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_BEIM_Pos (9UL) /*!< UART0 IER: BEIM (Bit 9) */ +#define UART0_IER_BEIM_Msk (0x200UL) /*!< UART0 IER: BEIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_PEIM_Pos (8UL) /*!< UART0 IER: PEIM (Bit 8) */ +#define UART0_IER_PEIM_Msk (0x100UL) /*!< UART0 IER: PEIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_FEIM_Pos (7UL) /*!< UART0 IER: FEIM (Bit 7) */ +#define UART0_IER_FEIM_Msk (0x80UL) /*!< UART0 IER: FEIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_RTIM_Pos (6UL) /*!< UART0 IER: RTIM (Bit 6) */ +#define UART0_IER_RTIM_Msk (0x40UL) /*!< UART0 IER: RTIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_TXIM_Pos (5UL) /*!< UART0 IER: TXIM (Bit 5) */ +#define UART0_IER_TXIM_Msk (0x20UL) /*!< UART0 IER: TXIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_RXIM_Pos (4UL) /*!< UART0 IER: RXIM (Bit 4) */ +#define UART0_IER_RXIM_Msk (0x10UL) /*!< UART0 IER: RXIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_DSRMIM_Pos (3UL) /*!< UART0 IER: DSRMIM (Bit 3) */ +#define UART0_IER_DSRMIM_Msk (0x8UL) /*!< UART0 IER: DSRMIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_DCDMIM_Pos (2UL) /*!< UART0 IER: DCDMIM (Bit 2) */ +#define UART0_IER_DCDMIM_Msk (0x4UL) /*!< UART0 IER: DCDMIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_CTSMIM_Pos (1UL) /*!< UART0 IER: CTSMIM (Bit 1) */ +#define UART0_IER_CTSMIM_Msk (0x2UL) /*!< UART0 IER: CTSMIM (Bitfield-Mask: 0x01) */ +#define UART0_IER_TXCMPMIM_Pos (0UL) /*!< UART0 IER: TXCMPMIM (Bit 0) */ +#define UART0_IER_TXCMPMIM_Msk (0x1UL) /*!< UART0 IER: TXCMPMIM (Bitfield-Mask: 0x01) */ +/* ========================================================== IES ========================================================== */ +#define UART0_IES_OERIS_Pos (10UL) /*!< UART0 IES: OERIS (Bit 10) */ +#define UART0_IES_OERIS_Msk (0x400UL) /*!< UART0 IES: OERIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_BERIS_Pos (9UL) /*!< UART0 IES: BERIS (Bit 9) */ +#define UART0_IES_BERIS_Msk (0x200UL) /*!< UART0 IES: BERIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_PERIS_Pos (8UL) /*!< UART0 IES: PERIS (Bit 8) */ +#define UART0_IES_PERIS_Msk (0x100UL) /*!< UART0 IES: PERIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_FERIS_Pos (7UL) /*!< UART0 IES: FERIS (Bit 7) */ +#define UART0_IES_FERIS_Msk (0x80UL) /*!< UART0 IES: FERIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_RTRIS_Pos (6UL) /*!< UART0 IES: RTRIS (Bit 6) */ +#define UART0_IES_RTRIS_Msk (0x40UL) /*!< UART0 IES: RTRIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_TXRIS_Pos (5UL) /*!< UART0 IES: TXRIS (Bit 5) */ +#define UART0_IES_TXRIS_Msk (0x20UL) /*!< UART0 IES: TXRIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_RXRIS_Pos (4UL) /*!< UART0 IES: RXRIS (Bit 4) */ +#define UART0_IES_RXRIS_Msk (0x10UL) /*!< UART0 IES: RXRIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_DSRMRIS_Pos (3UL) /*!< UART0 IES: DSRMRIS (Bit 3) */ +#define UART0_IES_DSRMRIS_Msk (0x8UL) /*!< UART0 IES: DSRMRIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_DCDMRIS_Pos (2UL) /*!< UART0 IES: DCDMRIS (Bit 2) */ +#define UART0_IES_DCDMRIS_Msk (0x4UL) /*!< UART0 IES: DCDMRIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_CTSMRIS_Pos (1UL) /*!< UART0 IES: CTSMRIS (Bit 1) */ +#define UART0_IES_CTSMRIS_Msk (0x2UL) /*!< UART0 IES: CTSMRIS (Bitfield-Mask: 0x01) */ +#define UART0_IES_TXCMPMRIS_Pos (0UL) /*!< UART0 IES: TXCMPMRIS (Bit 0) */ +#define UART0_IES_TXCMPMRIS_Msk (0x1UL) /*!< UART0 IES: TXCMPMRIS (Bitfield-Mask: 0x01) */ +/* ========================================================== MIS ========================================================== */ +#define UART0_MIS_OEMIS_Pos (10UL) /*!< UART0 MIS: OEMIS (Bit 10) */ +#define UART0_MIS_OEMIS_Msk (0x400UL) /*!< UART0 MIS: OEMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_BEMIS_Pos (9UL) /*!< UART0 MIS: BEMIS (Bit 9) */ +#define UART0_MIS_BEMIS_Msk (0x200UL) /*!< UART0 MIS: BEMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_PEMIS_Pos (8UL) /*!< UART0 MIS: PEMIS (Bit 8) */ +#define UART0_MIS_PEMIS_Msk (0x100UL) /*!< UART0 MIS: PEMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_FEMIS_Pos (7UL) /*!< UART0 MIS: FEMIS (Bit 7) */ +#define UART0_MIS_FEMIS_Msk (0x80UL) /*!< UART0 MIS: FEMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_RTMIS_Pos (6UL) /*!< UART0 MIS: RTMIS (Bit 6) */ +#define UART0_MIS_RTMIS_Msk (0x40UL) /*!< UART0 MIS: RTMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_TXMIS_Pos (5UL) /*!< UART0 MIS: TXMIS (Bit 5) */ +#define UART0_MIS_TXMIS_Msk (0x20UL) /*!< UART0 MIS: TXMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_RXMIS_Pos (4UL) /*!< UART0 MIS: RXMIS (Bit 4) */ +#define UART0_MIS_RXMIS_Msk (0x10UL) /*!< UART0 MIS: RXMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_DSRMMIS_Pos (3UL) /*!< UART0 MIS: DSRMMIS (Bit 3) */ +#define UART0_MIS_DSRMMIS_Msk (0x8UL) /*!< UART0 MIS: DSRMMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_DCDMMIS_Pos (2UL) /*!< UART0 MIS: DCDMMIS (Bit 2) */ +#define UART0_MIS_DCDMMIS_Msk (0x4UL) /*!< UART0 MIS: DCDMMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_CTSMMIS_Pos (1UL) /*!< UART0 MIS: CTSMMIS (Bit 1) */ +#define UART0_MIS_CTSMMIS_Msk (0x2UL) /*!< UART0 MIS: CTSMMIS (Bitfield-Mask: 0x01) */ +#define UART0_MIS_TXCMPMMIS_Pos (0UL) /*!< UART0 MIS: TXCMPMMIS (Bit 0) */ +#define UART0_MIS_TXCMPMMIS_Msk (0x1UL) /*!< UART0 MIS: TXCMPMMIS (Bitfield-Mask: 0x01) */ +/* ========================================================== IEC ========================================================== */ +#define UART0_IEC_OEIC_Pos (10UL) /*!< UART0 IEC: OEIC (Bit 10) */ +#define UART0_IEC_OEIC_Msk (0x400UL) /*!< UART0 IEC: OEIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_BEIC_Pos (9UL) /*!< UART0 IEC: BEIC (Bit 9) */ +#define UART0_IEC_BEIC_Msk (0x200UL) /*!< UART0 IEC: BEIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_PEIC_Pos (8UL) /*!< UART0 IEC: PEIC (Bit 8) */ +#define UART0_IEC_PEIC_Msk (0x100UL) /*!< UART0 IEC: PEIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_FEIC_Pos (7UL) /*!< UART0 IEC: FEIC (Bit 7) */ +#define UART0_IEC_FEIC_Msk (0x80UL) /*!< UART0 IEC: FEIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_RTIC_Pos (6UL) /*!< UART0 IEC: RTIC (Bit 6) */ +#define UART0_IEC_RTIC_Msk (0x40UL) /*!< UART0 IEC: RTIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_TXIC_Pos (5UL) /*!< UART0 IEC: TXIC (Bit 5) */ +#define UART0_IEC_TXIC_Msk (0x20UL) /*!< UART0 IEC: TXIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_RXIC_Pos (4UL) /*!< UART0 IEC: RXIC (Bit 4) */ +#define UART0_IEC_RXIC_Msk (0x10UL) /*!< UART0 IEC: RXIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_DSRMIC_Pos (3UL) /*!< UART0 IEC: DSRMIC (Bit 3) */ +#define UART0_IEC_DSRMIC_Msk (0x8UL) /*!< UART0 IEC: DSRMIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_DCDMIC_Pos (2UL) /*!< UART0 IEC: DCDMIC (Bit 2) */ +#define UART0_IEC_DCDMIC_Msk (0x4UL) /*!< UART0 IEC: DCDMIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_CTSMIC_Pos (1UL) /*!< UART0 IEC: CTSMIC (Bit 1) */ +#define UART0_IEC_CTSMIC_Msk (0x2UL) /*!< UART0 IEC: CTSMIC (Bitfield-Mask: 0x01) */ +#define UART0_IEC_TXCMPMIC_Pos (0UL) /*!< UART0 IEC: TXCMPMIC (Bit 0) */ +#define UART0_IEC_TXCMPMIC_Msk (0x1UL) /*!< UART0 IEC: TXCMPMIC (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ VCOMP ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== CFG ========================================================== */ +#define VCOMP_CFG_LVLSEL_Pos (16UL) /*!< VCOMP CFG: LVLSEL (Bit 16) */ +#define VCOMP_CFG_LVLSEL_Msk (0xf0000UL) /*!< VCOMP CFG: LVLSEL (Bitfield-Mask: 0x0f) */ +#define VCOMP_CFG_NSEL_Pos (8UL) /*!< VCOMP CFG: NSEL (Bit 8) */ +#define VCOMP_CFG_NSEL_Msk (0x300UL) /*!< VCOMP CFG: NSEL (Bitfield-Mask: 0x03) */ +#define VCOMP_CFG_PSEL_Pos (0UL) /*!< VCOMP CFG: PSEL (Bit 0) */ +#define VCOMP_CFG_PSEL_Msk (0x3UL) /*!< VCOMP CFG: PSEL (Bitfield-Mask: 0x03) */ +/* ========================================================= STAT ========================================================== */ +#define VCOMP_STAT_PWDSTAT_Pos (1UL) /*!< VCOMP STAT: PWDSTAT (Bit 1) */ +#define VCOMP_STAT_PWDSTAT_Msk (0x2UL) /*!< VCOMP STAT: PWDSTAT (Bitfield-Mask: 0x01) */ +#define VCOMP_STAT_CMPOUT_Pos (0UL) /*!< VCOMP STAT: CMPOUT (Bit 0) */ +#define VCOMP_STAT_CMPOUT_Msk (0x1UL) /*!< VCOMP STAT: CMPOUT (Bitfield-Mask: 0x01) */ +/* ======================================================== PWDKEY ========================================================= */ +#define VCOMP_PWDKEY_PWDKEY_Pos (0UL) /*!< VCOMP PWDKEY: PWDKEY (Bit 0) */ +#define VCOMP_PWDKEY_PWDKEY_Msk (0xffffffffUL) /*!< VCOMP PWDKEY: PWDKEY (Bitfield-Mask: 0xffffffff) */ +/* ========================================================= INTEN ========================================================= */ +#define VCOMP_INTEN_OUTHI_Pos (1UL) /*!< VCOMP INTEN: OUTHI (Bit 1) */ +#define VCOMP_INTEN_OUTHI_Msk (0x2UL) /*!< VCOMP INTEN: OUTHI (Bitfield-Mask: 0x01) */ +#define VCOMP_INTEN_OUTLOW_Pos (0UL) /*!< VCOMP INTEN: OUTLOW (Bit 0) */ +#define VCOMP_INTEN_OUTLOW_Msk (0x1UL) /*!< VCOMP INTEN: OUTLOW (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define VCOMP_INTSTAT_OUTHI_Pos (1UL) /*!< VCOMP INTSTAT: OUTHI (Bit 1) */ +#define VCOMP_INTSTAT_OUTHI_Msk (0x2UL) /*!< VCOMP INTSTAT: OUTHI (Bitfield-Mask: 0x01) */ +#define VCOMP_INTSTAT_OUTLOW_Pos (0UL) /*!< VCOMP INTSTAT: OUTLOW (Bit 0) */ +#define VCOMP_INTSTAT_OUTLOW_Msk (0x1UL) /*!< VCOMP INTSTAT: OUTLOW (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define VCOMP_INTCLR_OUTHI_Pos (1UL) /*!< VCOMP INTCLR: OUTHI (Bit 1) */ +#define VCOMP_INTCLR_OUTHI_Msk (0x2UL) /*!< VCOMP INTCLR: OUTHI (Bitfield-Mask: 0x01) */ +#define VCOMP_INTCLR_OUTLOW_Pos (0UL) /*!< VCOMP INTCLR: OUTLOW (Bit 0) */ +#define VCOMP_INTCLR_OUTLOW_Msk (0x1UL) /*!< VCOMP INTCLR: OUTLOW (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define VCOMP_INTSET_OUTHI_Pos (1UL) /*!< VCOMP INTSET: OUTHI (Bit 1) */ +#define VCOMP_INTSET_OUTHI_Msk (0x2UL) /*!< VCOMP INTSET: OUTHI (Bitfield-Mask: 0x01) */ +#define VCOMP_INTSET_OUTLOW_Pos (0UL) /*!< VCOMP INTSET: OUTLOW (Bit 0) */ +#define VCOMP_INTSET_OUTLOW_Msk (0x1UL) /*!< VCOMP INTSET: OUTLOW (Bitfield-Mask: 0x01) */ + + +/* =========================================================================================================================== */ +/* ================ WDT ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== CFG ========================================================== */ +#define WDT_CFG_CLKSEL_Pos (24UL) /*!< WDT CFG: CLKSEL (Bit 24) */ +#define WDT_CFG_CLKSEL_Msk (0x7000000UL) /*!< WDT CFG: CLKSEL (Bitfield-Mask: 0x07) */ +#define WDT_CFG_INTVAL_Pos (16UL) /*!< WDT CFG: INTVAL (Bit 16) */ +#define WDT_CFG_INTVAL_Msk (0xff0000UL) /*!< WDT CFG: INTVAL (Bitfield-Mask: 0xff) */ +#define WDT_CFG_RESVAL_Pos (8UL) /*!< WDT CFG: RESVAL (Bit 8) */ +#define WDT_CFG_RESVAL_Msk (0xff00UL) /*!< WDT CFG: RESVAL (Bitfield-Mask: 0xff) */ +#define WDT_CFG_RESEN_Pos (2UL) /*!< WDT CFG: RESEN (Bit 2) */ +#define WDT_CFG_RESEN_Msk (0x4UL) /*!< WDT CFG: RESEN (Bitfield-Mask: 0x01) */ +#define WDT_CFG_INTEN_Pos (1UL) /*!< WDT CFG: INTEN (Bit 1) */ +#define WDT_CFG_INTEN_Msk (0x2UL) /*!< WDT CFG: INTEN (Bitfield-Mask: 0x01) */ +#define WDT_CFG_WDTEN_Pos (0UL) /*!< WDT CFG: WDTEN (Bit 0) */ +#define WDT_CFG_WDTEN_Msk (0x1UL) /*!< WDT CFG: WDTEN (Bitfield-Mask: 0x01) */ +/* ========================================================= RSTRT ========================================================= */ +#define WDT_RSTRT_RSTRT_Pos (0UL) /*!< WDT RSTRT: RSTRT (Bit 0) */ +#define WDT_RSTRT_RSTRT_Msk (0xffUL) /*!< WDT RSTRT: RSTRT (Bitfield-Mask: 0xff) */ +/* ========================================================= LOCK ========================================================== */ +#define WDT_LOCK_LOCK_Pos (0UL) /*!< WDT LOCK: LOCK (Bit 0) */ +#define WDT_LOCK_LOCK_Msk (0xffUL) /*!< WDT LOCK: LOCK (Bitfield-Mask: 0xff) */ +/* ========================================================= COUNT ========================================================= */ +#define WDT_COUNT_COUNT_Pos (0UL) /*!< WDT COUNT: COUNT (Bit 0) */ +#define WDT_COUNT_COUNT_Msk (0xffUL) /*!< WDT COUNT: COUNT (Bitfield-Mask: 0xff) */ +/* ========================================================= INTEN ========================================================= */ +#define WDT_INTEN_WDTINT_Pos (0UL) /*!< WDT INTEN: WDTINT (Bit 0) */ +#define WDT_INTEN_WDTINT_Msk (0x1UL) /*!< WDT INTEN: WDTINT (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSTAT ======================================================== */ +#define WDT_INTSTAT_WDTINT_Pos (0UL) /*!< WDT INTSTAT: WDTINT (Bit 0) */ +#define WDT_INTSTAT_WDTINT_Msk (0x1UL) /*!< WDT INTSTAT: WDTINT (Bitfield-Mask: 0x01) */ +/* ======================================================== INTCLR ========================================================= */ +#define WDT_INTCLR_WDTINT_Pos (0UL) /*!< WDT INTCLR: WDTINT (Bit 0) */ +#define WDT_INTCLR_WDTINT_Msk (0x1UL) /*!< WDT INTCLR: WDTINT (Bitfield-Mask: 0x01) */ +/* ======================================================== INTSET ========================================================= */ +#define WDT_INTSET_WDTINT_Pos (0UL) /*!< WDT INTSET: WDTINT (Bit 0) */ +#define WDT_INTSET_WDTINT_Msk (0x1UL) /*!< WDT INTSET: WDTINT (Bitfield-Mask: 0x01) */ + +/** @} */ /* End of group PosMask_peripherals */ + + +/* =========================================================================================================================== */ +/* ================ Enumerated Values Peripheral Section ================ */ +/* =========================================================================================================================== */ + + +/** @addtogroup EnumValue_peripherals + * @{ + */ + + + +/* =========================================================================================================================== */ +/* ================ ADC ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== CFG ========================================================== */ +/* ================================================ ADC CFG CLKSEL [24..25] ================================================ */ +typedef enum { /*!< ADC_CFG_CLKSEL */ + ADC_CFG_CLKSEL_OFF = 0, /*!< OFF : Off mode. The HFRC or HFRC_DIV2 clock must be selected + for the ADC to function. The ADC controller + automatically shuts off the clock in it's + low power modes. When setting ADCEN to '0', + the CLKSEL should remain set to one of the + two clock selects for proper power down + sequencing. value. */ + ADC_CFG_CLKSEL_HFRC = 1, /*!< HFRC : HFRC Core Clock divided by (CORESEL+1) value. */ + ADC_CFG_CLKSEL_HFRC_DIV2 = 2, /*!< HFRC_DIV2 : HFRC Core Clock / 2 further divided by (CORESEL+1) + value. */ +} ADC_CFG_CLKSEL_Enum; + +/* =============================================== ADC CFG TRIGPOL [19..19] ================================================ */ +typedef enum { /*!< ADC_CFG_TRIGPOL */ + ADC_CFG_TRIGPOL_RISING_EDGE = 0, /*!< RISING_EDGE : Trigger on rising edge. value. */ + ADC_CFG_TRIGPOL_FALLING_EDGE = 1, /*!< FALLING_EDGE : Trigger on falling edge. value. */ +} ADC_CFG_TRIGPOL_Enum; + +/* =============================================== ADC CFG TRIGSEL [16..18] ================================================ */ +typedef enum { /*!< ADC_CFG_TRIGSEL */ + ADC_CFG_TRIGSEL_EXT0 = 0, /*!< EXT0 : Off chip External Trigger0 (ADC_ET0) value. */ + ADC_CFG_TRIGSEL_EXT1 = 1, /*!< EXT1 : Off chip External Trigger1 (ADC_ET1) value. */ + ADC_CFG_TRIGSEL_EXT2 = 2, /*!< EXT2 : Off chip External Trigger2 (ADC_ET2) value. */ + ADC_CFG_TRIGSEL_EXT3 = 3, /*!< EXT3 : Off chip External Trigger3 (ADC_ET3) value. */ + ADC_CFG_TRIGSEL_VCOMP = 4, /*!< VCOMP : Voltage Comparator Output value. */ + ADC_CFG_TRIGSEL_SWT = 7, /*!< SWT : Software Trigger value. */ +} ADC_CFG_TRIGSEL_Enum; + +/* ============================================== ADC CFG DFIFORDEN [12..12] =============================================== */ +typedef enum { /*!< ADC_CFG_DFIFORDEN */ + ADC_CFG_DFIFORDEN_DIS = 0, /*!< DIS : Destructive Reads are prevented. Reads to the FIFOPR register + will not POP an entry off the FIFO. value. */ + ADC_CFG_DFIFORDEN_EN = 1, /*!< EN : Reads to the FIFOPR registger will automatically pop an + entry off the FIFO. value. */ +} ADC_CFG_DFIFORDEN_Enum; + +/* ================================================= ADC CFG REFSEL [8..9] ================================================= */ +typedef enum { /*!< ADC_CFG_REFSEL */ + ADC_CFG_REFSEL_INT2P0 = 0, /*!< INT2P0 : Internal 2.0V Bandgap Reference Voltage value. */ + ADC_CFG_REFSEL_INT1P5 = 1, /*!< INT1P5 : Internal 1.5V Bandgap Reference Voltage value. */ + ADC_CFG_REFSEL_EXT2P0 = 2, /*!< EXT2P0 : Off Chip 2.0V Reference value. */ + ADC_CFG_REFSEL_EXT1P5 = 3, /*!< EXT1P5 : Off Chip 1.5V Reference value. */ +} ADC_CFG_REFSEL_Enum; + +/* ================================================= ADC CFG CKMODE [4..4] ================================================= */ +typedef enum { /*!< ADC_CFG_CKMODE */ + ADC_CFG_CKMODE_LPCKMODE = 0, /*!< LPCKMODE : Disable the clock between scans for LPMODE0. Set + LPCKMODE to 0x1 while configuring the ADC. value. */ + ADC_CFG_CKMODE_LLCKMODE = 1, /*!< LLCKMODE : Low Latency Clock Mode. When set, HFRC and the adc_clk + will remain on while in functioning in LPMODE0. value. */ +} ADC_CFG_CKMODE_Enum; + +/* ================================================= ADC CFG LPMODE [3..3] ================================================= */ +typedef enum { /*!< ADC_CFG_LPMODE */ + ADC_CFG_LPMODE_MODE0 = 0, /*!< MODE0 : Low Power Mode 0. Leaves the ADC fully powered between + scans with minimum latency between a trigger event and + sample data collection. value. */ + ADC_CFG_LPMODE_MODE1 = 1, /*!< MODE1 : Low Power Mode 1. Powers down all circuity and clocks + associated with the ADC until the next trigger event. Between + scans, the reference buffer requires up to 50us of delay + from a scan trigger event before the conversion will commence + while operating in this mode. value. */ +} ADC_CFG_LPMODE_Enum; + +/* ================================================= ADC CFG RPTEN [2..2] ================================================== */ +typedef enum { /*!< ADC_CFG_RPTEN */ + ADC_CFG_RPTEN_SINGLE_SCAN = 0, /*!< SINGLE_SCAN : In Single Scan Mode, the ADC will complete a single + scan upon each trigger event. value. */ + ADC_CFG_RPTEN_REPEATING_SCAN = 1, /*!< REPEATING_SCAN : In Repeating Scan Mode, the ADC will complete + it's first scan upon the initial trigger event and all + subsequent scans will occur at regular intervals defined + by the configuration programmed for the CTTMRA3 internal + timer until the timer is disabled or the ADC is disabled. + When disabling the ADC (setting ADCEN to '0'), the RPTEN + bit should be cleared. value. */ +} ADC_CFG_RPTEN_Enum; + +/* ================================================= ADC CFG ADCEN [0..0] ================================================== */ +typedef enum { /*!< ADC_CFG_ADCEN */ + ADC_CFG_ADCEN_DIS = 0, /*!< DIS : Disable the ADC module. value. */ + ADC_CFG_ADCEN_EN = 1, /*!< EN : Enable the ADC module. value. */ +} ADC_CFG_ADCEN_Enum; + +/* ========================================================= STAT ========================================================== */ +/* ================================================ ADC STAT PWDSTAT [0..0] ================================================ */ +typedef enum { /*!< ADC_STAT_PWDSTAT */ + ADC_STAT_PWDSTAT_ON = 0, /*!< ON : Powered on. value. */ + ADC_STAT_PWDSTAT_POWERED_DOWN = 1, /*!< POWERED_DOWN : ADC Low Power Mode 1. value. */ +} ADC_STAT_PWDSTAT_Enum; + +/* ========================================================== SWT ========================================================== */ +/* ================================================== ADC SWT SWT [0..7] =================================================== */ +typedef enum { /*!< ADC_SWT_SWT */ + ADC_SWT_SWT_GEN_SW_TRIGGER = 55, /*!< GEN_SW_TRIGGER : Writing this value generates a software trigger. + value. */ +} ADC_SWT_SWT_Enum; + +/* ======================================================== SL0CFG ========================================================= */ +/* ============================================== ADC SL0CFG ADSEL0 [24..26] =============================================== */ +typedef enum { /*!< ADC_SL0CFG_ADSEL0 */ + ADC_SL0CFG_ADSEL0_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide + module for this slot. value. */ + ADC_SL0CFG_ADSEL0_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL0CFG_ADSEL0_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL0CFG_ADSEL0_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL0CFG_ADSEL0_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL0CFG_ADSEL0_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL0CFG_ADSEL0_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL0CFG_ADSEL0_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate + divide module for this slot. value. */ +} ADC_SL0CFG_ADSEL0_Enum; + +/* ============================================== ADC SL0CFG PRMODE0 [16..17] ============================================== */ +typedef enum { /*!< ADC_SL0CFG_PRMODE0 */ + ADC_SL0CFG_PRMODE0_P14B = 0, /*!< P14B : 14-bit precision mode value. */ + ADC_SL0CFG_PRMODE0_P12B = 1, /*!< P12B : 12-bit precision mode value. */ + ADC_SL0CFG_PRMODE0_P10B = 2, /*!< P10B : 10-bit precision mode value. */ + ADC_SL0CFG_PRMODE0_P8B = 3, /*!< P8B : 8-bit precision mode value. */ +} ADC_SL0CFG_PRMODE0_Enum; + +/* =============================================== ADC SL0CFG CHSEL0 [8..11] =============================================== */ +typedef enum { /*!< ADC_SL0CFG_CHSEL0 */ + ADC_SL0CFG_CHSEL0_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ + ADC_SL0CFG_CHSEL0_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ + ADC_SL0CFG_CHSEL0_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ + ADC_SL0CFG_CHSEL0_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ + ADC_SL0CFG_CHSEL0_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ + ADC_SL0CFG_CHSEL0_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ + ADC_SL0CFG_CHSEL0_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ + ADC_SL0CFG_CHSEL0_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ + ADC_SL0CFG_CHSEL0_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ + ADC_SL0CFG_CHSEL0_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ + ADC_SL0CFG_CHSEL0_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and + pad13(P). value. */ + ADC_SL0CFG_CHSEL0_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and + pad14(P). value. */ + ADC_SL0CFG_CHSEL0_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ + ADC_SL0CFG_CHSEL0_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ + ADC_SL0CFG_CHSEL0_VSS = 14, /*!< VSS : Input VSS value. */ +} ADC_SL0CFG_CHSEL0_Enum; + +/* ================================================ ADC SL0CFG WCEN0 [1..1] ================================================ */ +typedef enum { /*!< ADC_SL0CFG_WCEN0 */ + ADC_SL0CFG_WCEN0_WCEN = 1, /*!< WCEN : Enable the window compare for slot 0. value. */ +} ADC_SL0CFG_WCEN0_Enum; + +/* ================================================ ADC SL0CFG SLEN0 [0..0] ================================================ */ +typedef enum { /*!< ADC_SL0CFG_SLEN0 */ + ADC_SL0CFG_SLEN0_SLEN = 1, /*!< SLEN : Enable slot 0 for ADC conversions. value. */ +} ADC_SL0CFG_SLEN0_Enum; + +/* ======================================================== SL1CFG ========================================================= */ +/* ============================================== ADC SL1CFG ADSEL1 [24..26] =============================================== */ +typedef enum { /*!< ADC_SL1CFG_ADSEL1 */ + ADC_SL1CFG_ADSEL1_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide + module for this slot. value. */ + ADC_SL1CFG_ADSEL1_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL1CFG_ADSEL1_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL1CFG_ADSEL1_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL1CFG_ADSEL1_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL1CFG_ADSEL1_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL1CFG_ADSEL1_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL1CFG_ADSEL1_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate + divide module for this slot. value. */ +} ADC_SL1CFG_ADSEL1_Enum; + +/* ============================================== ADC SL1CFG PRMODE1 [16..17] ============================================== */ +typedef enum { /*!< ADC_SL1CFG_PRMODE1 */ + ADC_SL1CFG_PRMODE1_P14B = 0, /*!< P14B : 14-bit precision mode value. */ + ADC_SL1CFG_PRMODE1_P12B = 1, /*!< P12B : 12-bit precision mode value. */ + ADC_SL1CFG_PRMODE1_P10B = 2, /*!< P10B : 10-bit precision mode value. */ + ADC_SL1CFG_PRMODE1_P8B = 3, /*!< P8B : 8-bit precision mode value. */ +} ADC_SL1CFG_PRMODE1_Enum; + +/* =============================================== ADC SL1CFG CHSEL1 [8..11] =============================================== */ +typedef enum { /*!< ADC_SL1CFG_CHSEL1 */ + ADC_SL1CFG_CHSEL1_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ + ADC_SL1CFG_CHSEL1_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ + ADC_SL1CFG_CHSEL1_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ + ADC_SL1CFG_CHSEL1_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ + ADC_SL1CFG_CHSEL1_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ + ADC_SL1CFG_CHSEL1_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ + ADC_SL1CFG_CHSEL1_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ + ADC_SL1CFG_CHSEL1_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ + ADC_SL1CFG_CHSEL1_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ + ADC_SL1CFG_CHSEL1_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ + ADC_SL1CFG_CHSEL1_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and + pad13(P). value. */ + ADC_SL1CFG_CHSEL1_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and + pad14(P). value. */ + ADC_SL1CFG_CHSEL1_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ + ADC_SL1CFG_CHSEL1_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ + ADC_SL1CFG_CHSEL1_VSS = 14, /*!< VSS : Input VSS value. */ +} ADC_SL1CFG_CHSEL1_Enum; + +/* ================================================ ADC SL1CFG WCEN1 [1..1] ================================================ */ +typedef enum { /*!< ADC_SL1CFG_WCEN1 */ + ADC_SL1CFG_WCEN1_WCEN = 1, /*!< WCEN : Enable the window compare for slot 1. value. */ +} ADC_SL1CFG_WCEN1_Enum; + +/* ================================================ ADC SL1CFG SLEN1 [0..0] ================================================ */ +typedef enum { /*!< ADC_SL1CFG_SLEN1 */ + ADC_SL1CFG_SLEN1_SLEN = 1, /*!< SLEN : Enable slot 1 for ADC conversions. value. */ +} ADC_SL1CFG_SLEN1_Enum; + +/* ======================================================== SL2CFG ========================================================= */ +/* ============================================== ADC SL2CFG ADSEL2 [24..26] =============================================== */ +typedef enum { /*!< ADC_SL2CFG_ADSEL2 */ + ADC_SL2CFG_ADSEL2_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide + module for this slot. value. */ + ADC_SL2CFG_ADSEL2_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL2CFG_ADSEL2_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL2CFG_ADSEL2_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL2CFG_ADSEL2_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL2CFG_ADSEL2_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL2CFG_ADSEL2_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL2CFG_ADSEL2_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate + divide module for this slot. value. */ +} ADC_SL2CFG_ADSEL2_Enum; + +/* ============================================== ADC SL2CFG PRMODE2 [16..17] ============================================== */ +typedef enum { /*!< ADC_SL2CFG_PRMODE2 */ + ADC_SL2CFG_PRMODE2_P14B = 0, /*!< P14B : 14-bit precision mode value. */ + ADC_SL2CFG_PRMODE2_P12B = 1, /*!< P12B : 12-bit precision mode value. */ + ADC_SL2CFG_PRMODE2_P10B = 2, /*!< P10B : 10-bit precision mode value. */ + ADC_SL2CFG_PRMODE2_P8B = 3, /*!< P8B : 8-bit precision mode value. */ +} ADC_SL2CFG_PRMODE2_Enum; + +/* =============================================== ADC SL2CFG CHSEL2 [8..11] =============================================== */ +typedef enum { /*!< ADC_SL2CFG_CHSEL2 */ + ADC_SL2CFG_CHSEL2_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ + ADC_SL2CFG_CHSEL2_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ + ADC_SL2CFG_CHSEL2_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ + ADC_SL2CFG_CHSEL2_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ + ADC_SL2CFG_CHSEL2_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ + ADC_SL2CFG_CHSEL2_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ + ADC_SL2CFG_CHSEL2_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ + ADC_SL2CFG_CHSEL2_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ + ADC_SL2CFG_CHSEL2_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ + ADC_SL2CFG_CHSEL2_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ + ADC_SL2CFG_CHSEL2_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and + pad13(P). value. */ + ADC_SL2CFG_CHSEL2_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and + pad14(P). value. */ + ADC_SL2CFG_CHSEL2_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ + ADC_SL2CFG_CHSEL2_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ + ADC_SL2CFG_CHSEL2_VSS = 14, /*!< VSS : Input VSS value. */ +} ADC_SL2CFG_CHSEL2_Enum; + +/* ================================================ ADC SL2CFG WCEN2 [1..1] ================================================ */ +typedef enum { /*!< ADC_SL2CFG_WCEN2 */ + ADC_SL2CFG_WCEN2_WCEN = 1, /*!< WCEN : Enable the window compare for slot 2. value. */ +} ADC_SL2CFG_WCEN2_Enum; + +/* ================================================ ADC SL2CFG SLEN2 [0..0] ================================================ */ +typedef enum { /*!< ADC_SL2CFG_SLEN2 */ + ADC_SL2CFG_SLEN2_SLEN = 1, /*!< SLEN : Enable slot 2 for ADC conversions. value. */ +} ADC_SL2CFG_SLEN2_Enum; + +/* ======================================================== SL3CFG ========================================================= */ +/* ============================================== ADC SL3CFG ADSEL3 [24..26] =============================================== */ +typedef enum { /*!< ADC_SL3CFG_ADSEL3 */ + ADC_SL3CFG_ADSEL3_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide + module for this slot. value. */ + ADC_SL3CFG_ADSEL3_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL3CFG_ADSEL3_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL3CFG_ADSEL3_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL3CFG_ADSEL3_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL3CFG_ADSEL3_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL3CFG_ADSEL3_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL3CFG_ADSEL3_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate + divide module for this slot. value. */ +} ADC_SL3CFG_ADSEL3_Enum; + +/* ============================================== ADC SL3CFG PRMODE3 [16..17] ============================================== */ +typedef enum { /*!< ADC_SL3CFG_PRMODE3 */ + ADC_SL3CFG_PRMODE3_P14B = 0, /*!< P14B : 14-bit precision mode value. */ + ADC_SL3CFG_PRMODE3_P12B = 1, /*!< P12B : 12-bit precision mode value. */ + ADC_SL3CFG_PRMODE3_P10B = 2, /*!< P10B : 10-bit precision mode value. */ + ADC_SL3CFG_PRMODE3_P8B = 3, /*!< P8B : 8-bit precision mode value. */ +} ADC_SL3CFG_PRMODE3_Enum; + +/* =============================================== ADC SL3CFG CHSEL3 [8..11] =============================================== */ +typedef enum { /*!< ADC_SL3CFG_CHSEL3 */ + ADC_SL3CFG_CHSEL3_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ + ADC_SL3CFG_CHSEL3_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ + ADC_SL3CFG_CHSEL3_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ + ADC_SL3CFG_CHSEL3_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ + ADC_SL3CFG_CHSEL3_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ + ADC_SL3CFG_CHSEL3_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ + ADC_SL3CFG_CHSEL3_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ + ADC_SL3CFG_CHSEL3_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ + ADC_SL3CFG_CHSEL3_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ + ADC_SL3CFG_CHSEL3_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ + ADC_SL3CFG_CHSEL3_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and + pad13(P). value. */ + ADC_SL3CFG_CHSEL3_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and + pad14(P). value. */ + ADC_SL3CFG_CHSEL3_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ + ADC_SL3CFG_CHSEL3_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ + ADC_SL3CFG_CHSEL3_VSS = 14, /*!< VSS : Input VSS value. */ +} ADC_SL3CFG_CHSEL3_Enum; + +/* ================================================ ADC SL3CFG WCEN3 [1..1] ================================================ */ +typedef enum { /*!< ADC_SL3CFG_WCEN3 */ + ADC_SL3CFG_WCEN3_WCEN = 1, /*!< WCEN : Enable the window compare for slot 3. value. */ +} ADC_SL3CFG_WCEN3_Enum; + +/* ================================================ ADC SL3CFG SLEN3 [0..0] ================================================ */ +typedef enum { /*!< ADC_SL3CFG_SLEN3 */ + ADC_SL3CFG_SLEN3_SLEN = 1, /*!< SLEN : Enable slot 3 for ADC conversions. value. */ +} ADC_SL3CFG_SLEN3_Enum; + +/* ======================================================== SL4CFG ========================================================= */ +/* ============================================== ADC SL4CFG ADSEL4 [24..26] =============================================== */ +typedef enum { /*!< ADC_SL4CFG_ADSEL4 */ + ADC_SL4CFG_ADSEL4_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide + module for this slot. value. */ + ADC_SL4CFG_ADSEL4_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL4CFG_ADSEL4_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL4CFG_ADSEL4_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL4CFG_ADSEL4_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL4CFG_ADSEL4_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL4CFG_ADSEL4_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL4CFG_ADSEL4_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate + divide module for this slot. value. */ +} ADC_SL4CFG_ADSEL4_Enum; + +/* ============================================== ADC SL4CFG PRMODE4 [16..17] ============================================== */ +typedef enum { /*!< ADC_SL4CFG_PRMODE4 */ + ADC_SL4CFG_PRMODE4_P14B = 0, /*!< P14B : 14-bit precision mode value. */ + ADC_SL4CFG_PRMODE4_P12B = 1, /*!< P12B : 12-bit precision mode value. */ + ADC_SL4CFG_PRMODE4_P10B = 2, /*!< P10B : 10-bit precision mode value. */ + ADC_SL4CFG_PRMODE4_P8B = 3, /*!< P8B : 8-bit precision mode value. */ +} ADC_SL4CFG_PRMODE4_Enum; + +/* =============================================== ADC SL4CFG CHSEL4 [8..11] =============================================== */ +typedef enum { /*!< ADC_SL4CFG_CHSEL4 */ + ADC_SL4CFG_CHSEL4_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ + ADC_SL4CFG_CHSEL4_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ + ADC_SL4CFG_CHSEL4_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ + ADC_SL4CFG_CHSEL4_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ + ADC_SL4CFG_CHSEL4_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ + ADC_SL4CFG_CHSEL4_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ + ADC_SL4CFG_CHSEL4_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ + ADC_SL4CFG_CHSEL4_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ + ADC_SL4CFG_CHSEL4_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ + ADC_SL4CFG_CHSEL4_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ + ADC_SL4CFG_CHSEL4_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and + pad13(P). value. */ + ADC_SL4CFG_CHSEL4_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and + pad14(P). value. */ + ADC_SL4CFG_CHSEL4_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ + ADC_SL4CFG_CHSEL4_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ + ADC_SL4CFG_CHSEL4_VSS = 14, /*!< VSS : Input VSS value. */ +} ADC_SL4CFG_CHSEL4_Enum; + +/* ================================================ ADC SL4CFG WCEN4 [1..1] ================================================ */ +typedef enum { /*!< ADC_SL4CFG_WCEN4 */ + ADC_SL4CFG_WCEN4_WCEN = 1, /*!< WCEN : Enable the window compare for slot 4. value. */ +} ADC_SL4CFG_WCEN4_Enum; + +/* ================================================ ADC SL4CFG SLEN4 [0..0] ================================================ */ +typedef enum { /*!< ADC_SL4CFG_SLEN4 */ + ADC_SL4CFG_SLEN4_SLEN = 1, /*!< SLEN : Enable slot 4 for ADC conversions. value. */ +} ADC_SL4CFG_SLEN4_Enum; + +/* ======================================================== SL5CFG ========================================================= */ +/* ============================================== ADC SL5CFG ADSEL5 [24..26] =============================================== */ +typedef enum { /*!< ADC_SL5CFG_ADSEL5 */ + ADC_SL5CFG_ADSEL5_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide + module for this slot. value. */ + ADC_SL5CFG_ADSEL5_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL5CFG_ADSEL5_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL5CFG_ADSEL5_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL5CFG_ADSEL5_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL5CFG_ADSEL5_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL5CFG_ADSEL5_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL5CFG_ADSEL5_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate + divide module for this slot. value. */ +} ADC_SL5CFG_ADSEL5_Enum; + +/* ============================================== ADC SL5CFG PRMODE5 [16..17] ============================================== */ +typedef enum { /*!< ADC_SL5CFG_PRMODE5 */ + ADC_SL5CFG_PRMODE5_P14B = 0, /*!< P14B : 14-bit precision mode value. */ + ADC_SL5CFG_PRMODE5_P12B = 1, /*!< P12B : 12-bit precision mode value. */ + ADC_SL5CFG_PRMODE5_P10B = 2, /*!< P10B : 10-bit precision mode value. */ + ADC_SL5CFG_PRMODE5_P8B = 3, /*!< P8B : 8-bit precision mode value. */ +} ADC_SL5CFG_PRMODE5_Enum; + +/* =============================================== ADC SL5CFG CHSEL5 [8..11] =============================================== */ +typedef enum { /*!< ADC_SL5CFG_CHSEL5 */ + ADC_SL5CFG_CHSEL5_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ + ADC_SL5CFG_CHSEL5_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ + ADC_SL5CFG_CHSEL5_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ + ADC_SL5CFG_CHSEL5_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ + ADC_SL5CFG_CHSEL5_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ + ADC_SL5CFG_CHSEL5_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ + ADC_SL5CFG_CHSEL5_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ + ADC_SL5CFG_CHSEL5_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ + ADC_SL5CFG_CHSEL5_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ + ADC_SL5CFG_CHSEL5_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ + ADC_SL5CFG_CHSEL5_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and + pad13(P). value. */ + ADC_SL5CFG_CHSEL5_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and + pad14(P). value. */ + ADC_SL5CFG_CHSEL5_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ + ADC_SL5CFG_CHSEL5_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ + ADC_SL5CFG_CHSEL5_VSS = 14, /*!< VSS : Input VSS value. */ +} ADC_SL5CFG_CHSEL5_Enum; + +/* ================================================ ADC SL5CFG WCEN5 [1..1] ================================================ */ +typedef enum { /*!< ADC_SL5CFG_WCEN5 */ + ADC_SL5CFG_WCEN5_WCEN = 1, /*!< WCEN : Enable the window compare for slot 5. value. */ +} ADC_SL5CFG_WCEN5_Enum; + +/* ================================================ ADC SL5CFG SLEN5 [0..0] ================================================ */ +typedef enum { /*!< ADC_SL5CFG_SLEN5 */ + ADC_SL5CFG_SLEN5_SLEN = 1, /*!< SLEN : Enable slot 5 for ADC conversions. value. */ +} ADC_SL5CFG_SLEN5_Enum; + +/* ======================================================== SL6CFG ========================================================= */ +/* ============================================== ADC SL6CFG ADSEL6 [24..26] =============================================== */ +typedef enum { /*!< ADC_SL6CFG_ADSEL6 */ + ADC_SL6CFG_ADSEL6_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide + module for this slot. value. */ + ADC_SL6CFG_ADSEL6_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL6CFG_ADSEL6_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL6CFG_ADSEL6_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL6CFG_ADSEL6_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL6CFG_ADSEL6_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL6CFG_ADSEL6_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL6CFG_ADSEL6_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate + divide module for this slot. value. */ +} ADC_SL6CFG_ADSEL6_Enum; + +/* ============================================== ADC SL6CFG PRMODE6 [16..17] ============================================== */ +typedef enum { /*!< ADC_SL6CFG_PRMODE6 */ + ADC_SL6CFG_PRMODE6_P14B = 0, /*!< P14B : 14-bit precision mode value. */ + ADC_SL6CFG_PRMODE6_P12B = 1, /*!< P12B : 12-bit precision mode value. */ + ADC_SL6CFG_PRMODE6_P10B = 2, /*!< P10B : 10-bit precision mode value. */ + ADC_SL6CFG_PRMODE6_P8B = 3, /*!< P8B : 8-bit precision mode value. */ +} ADC_SL6CFG_PRMODE6_Enum; + +/* =============================================== ADC SL6CFG CHSEL6 [8..11] =============================================== */ +typedef enum { /*!< ADC_SL6CFG_CHSEL6 */ + ADC_SL6CFG_CHSEL6_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ + ADC_SL6CFG_CHSEL6_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ + ADC_SL6CFG_CHSEL6_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ + ADC_SL6CFG_CHSEL6_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ + ADC_SL6CFG_CHSEL6_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ + ADC_SL6CFG_CHSEL6_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ + ADC_SL6CFG_CHSEL6_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ + ADC_SL6CFG_CHSEL6_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ + ADC_SL6CFG_CHSEL6_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ + ADC_SL6CFG_CHSEL6_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ + ADC_SL6CFG_CHSEL6_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and + pad13(P). value. */ + ADC_SL6CFG_CHSEL6_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and + pad14(P). value. */ + ADC_SL6CFG_CHSEL6_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ + ADC_SL6CFG_CHSEL6_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ + ADC_SL6CFG_CHSEL6_VSS = 14, /*!< VSS : Input VSS value. */ +} ADC_SL6CFG_CHSEL6_Enum; + +/* ================================================ ADC SL6CFG WCEN6 [1..1] ================================================ */ +typedef enum { /*!< ADC_SL6CFG_WCEN6 */ + ADC_SL6CFG_WCEN6_WCEN = 1, /*!< WCEN : Enable the window compare for slot 6. value. */ +} ADC_SL6CFG_WCEN6_Enum; + +/* ================================================ ADC SL6CFG SLEN6 [0..0] ================================================ */ +typedef enum { /*!< ADC_SL6CFG_SLEN6 */ + ADC_SL6CFG_SLEN6_SLEN = 1, /*!< SLEN : Enable slot 6 for ADC conversions. value. */ +} ADC_SL6CFG_SLEN6_Enum; + +/* ======================================================== SL7CFG ========================================================= */ +/* ============================================== ADC SL7CFG ADSEL7 [24..26] =============================================== */ +typedef enum { /*!< ADC_SL7CFG_ADSEL7 */ + ADC_SL7CFG_ADSEL7_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide + module for this slot. value. */ + ADC_SL7CFG_ADSEL7_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL7CFG_ADSEL7_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL7CFG_ADSEL7_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide + module for this slot. value. */ + ADC_SL7CFG_ADSEL7_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL7CFG_ADSEL7_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL7CFG_ADSEL7_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate + divide module for this slot. value. */ + ADC_SL7CFG_ADSEL7_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate + divide module for this slot. value. */ +} ADC_SL7CFG_ADSEL7_Enum; + +/* ============================================== ADC SL7CFG PRMODE7 [16..17] ============================================== */ +typedef enum { /*!< ADC_SL7CFG_PRMODE7 */ + ADC_SL7CFG_PRMODE7_P14B = 0, /*!< P14B : 14-bit precision mode value. */ + ADC_SL7CFG_PRMODE7_P12B = 1, /*!< P12B : 12-bit precision mode value. */ + ADC_SL7CFG_PRMODE7_P10B = 2, /*!< P10B : 10-bit precision mode value. */ + ADC_SL7CFG_PRMODE7_P8B = 3, /*!< P8B : 8-bit precision mode value. */ +} ADC_SL7CFG_PRMODE7_Enum; + +/* =============================================== ADC SL7CFG CHSEL7 [8..11] =============================================== */ +typedef enum { /*!< ADC_SL7CFG_CHSEL7 */ + ADC_SL7CFG_CHSEL7_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ + ADC_SL7CFG_CHSEL7_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ + ADC_SL7CFG_CHSEL7_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ + ADC_SL7CFG_CHSEL7_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ + ADC_SL7CFG_CHSEL7_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ + ADC_SL7CFG_CHSEL7_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ + ADC_SL7CFG_CHSEL7_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ + ADC_SL7CFG_CHSEL7_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ + ADC_SL7CFG_CHSEL7_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ + ADC_SL7CFG_CHSEL7_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ + ADC_SL7CFG_CHSEL7_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and + pad13(P). value. */ + ADC_SL7CFG_CHSEL7_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and + pad14(P). value. */ + ADC_SL7CFG_CHSEL7_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ + ADC_SL7CFG_CHSEL7_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ + ADC_SL7CFG_CHSEL7_VSS = 14, /*!< VSS : Input VSS value. */ +} ADC_SL7CFG_CHSEL7_Enum; + +/* ================================================ ADC SL7CFG WCEN7 [1..1] ================================================ */ +typedef enum { /*!< ADC_SL7CFG_WCEN7 */ + ADC_SL7CFG_WCEN7_WCEN = 1, /*!< WCEN : Enable the window compare for slot 7. value. */ +} ADC_SL7CFG_WCEN7_Enum; + +/* ================================================ ADC SL7CFG SLEN7 [0..0] ================================================ */ +typedef enum { /*!< ADC_SL7CFG_SLEN7 */ + ADC_SL7CFG_SLEN7_SLEN = 1, /*!< SLEN : Enable slot 7 for ADC conversions. value. */ +} ADC_SL7CFG_SLEN7_Enum; + +/* ========================================================= WULIM ========================================================= */ +/* ========================================================= WLLIM ========================================================= */ +/* ======================================================== SCWLIM ========================================================= */ +/* ========================================================= FIFO ========================================================== */ +/* ======================================================== FIFOPR ========================================================= */ +/* ========================================================= INTEN ========================================================= */ +/* ================================================= ADC INTEN DERR [7..7] ================================================= */ +typedef enum { /*!< ADC_INTEN_DERR */ + ADC_INTEN_DERR_DMAERROR = 1, /*!< DMAERROR : DMA Error Condition Occurred value. */ +} ADC_INTEN_DERR_Enum; + +/* ================================================= ADC INTEN DCMP [6..6] ================================================= */ +typedef enum { /*!< ADC_INTEN_DCMP */ + ADC_INTEN_DCMP_DMACOMPLETE = 1, /*!< DMACOMPLETE : DMA Completed a transfer value. */ +} ADC_INTEN_DCMP_Enum; + +/* ================================================ ADC INTEN WCINC [5..5] ================================================= */ +typedef enum { /*!< ADC_INTEN_WCINC */ + ADC_INTEN_WCINC_WCINCINT = 1, /*!< WCINCINT : Window comparitor voltage incursion interrupt. value. */ +} ADC_INTEN_WCINC_Enum; + +/* ================================================ ADC INTEN WCEXC [4..4] ================================================= */ +typedef enum { /*!< ADC_INTEN_WCEXC */ + ADC_INTEN_WCEXC_WCEXCINT = 1, /*!< WCEXCINT : Window comparitor voltage excursion interrupt. value. */ +} ADC_INTEN_WCEXC_Enum; + +/* =============================================== ADC INTEN FIFOOVR2 [3..3] =============================================== */ +typedef enum { /*!< ADC_INTEN_FIFOOVR2 */ + ADC_INTEN_FIFOOVR2_FIFOFULLINT = 1, /*!< FIFOFULLINT : FIFO 100 percent full interrupt. value. */ +} ADC_INTEN_FIFOOVR2_Enum; + +/* =============================================== ADC INTEN FIFOOVR1 [2..2] =============================================== */ +typedef enum { /*!< ADC_INTEN_FIFOOVR1 */ + ADC_INTEN_FIFOOVR1_FIFO75INT = 1, /*!< FIFO75INT : FIFO 75 percent full interrupt. value. */ +} ADC_INTEN_FIFOOVR1_Enum; + +/* ================================================ ADC INTEN SCNCMP [1..1] ================================================ */ +typedef enum { /*!< ADC_INTEN_SCNCMP */ + ADC_INTEN_SCNCMP_SCNCMPINT = 1, /*!< SCNCMPINT : ADC scan complete interrupt. value. */ +} ADC_INTEN_SCNCMP_Enum; + +/* ================================================ ADC INTEN CNVCMP [0..0] ================================================ */ +typedef enum { /*!< ADC_INTEN_CNVCMP */ + ADC_INTEN_CNVCMP_CNVCMPINT = 1, /*!< CNVCMPINT : ADC conversion complete interrupt. value. */ +} ADC_INTEN_CNVCMP_Enum; + +/* ======================================================== INTSTAT ======================================================== */ +/* ================================================ ADC INTSTAT DERR [7..7] ================================================ */ +typedef enum { /*!< ADC_INTSTAT_DERR */ + ADC_INTSTAT_DERR_DMAERROR = 1, /*!< DMAERROR : DMA Error Condition Occurred value. */ +} ADC_INTSTAT_DERR_Enum; + +/* ================================================ ADC INTSTAT DCMP [6..6] ================================================ */ +typedef enum { /*!< ADC_INTSTAT_DCMP */ + ADC_INTSTAT_DCMP_DMACOMPLETE = 1, /*!< DMACOMPLETE : DMA Completed a transfer value. */ +} ADC_INTSTAT_DCMP_Enum; + +/* =============================================== ADC INTSTAT WCINC [5..5] ================================================ */ +typedef enum { /*!< ADC_INTSTAT_WCINC */ + ADC_INTSTAT_WCINC_WCINCINT = 1, /*!< WCINCINT : Window comparitor voltage incursion interrupt. value. */ +} ADC_INTSTAT_WCINC_Enum; + +/* =============================================== ADC INTSTAT WCEXC [4..4] ================================================ */ +typedef enum { /*!< ADC_INTSTAT_WCEXC */ + ADC_INTSTAT_WCEXC_WCEXCINT = 1, /*!< WCEXCINT : Window comparitor voltage excursion interrupt. value. */ +} ADC_INTSTAT_WCEXC_Enum; + +/* ============================================== ADC INTSTAT FIFOOVR2 [3..3] ============================================== */ +typedef enum { /*!< ADC_INTSTAT_FIFOOVR2 */ + ADC_INTSTAT_FIFOOVR2_FIFOFULLINT = 1, /*!< FIFOFULLINT : FIFO 100 percent full interrupt. value. */ +} ADC_INTSTAT_FIFOOVR2_Enum; + +/* ============================================== ADC INTSTAT FIFOOVR1 [2..2] ============================================== */ +typedef enum { /*!< ADC_INTSTAT_FIFOOVR1 */ + ADC_INTSTAT_FIFOOVR1_FIFO75INT = 1, /*!< FIFO75INT : FIFO 75 percent full interrupt. value. */ +} ADC_INTSTAT_FIFOOVR1_Enum; + +/* =============================================== ADC INTSTAT SCNCMP [1..1] =============================================== */ +typedef enum { /*!< ADC_INTSTAT_SCNCMP */ + ADC_INTSTAT_SCNCMP_SCNCMPINT = 1, /*!< SCNCMPINT : ADC scan complete interrupt. value. */ +} ADC_INTSTAT_SCNCMP_Enum; + +/* =============================================== ADC INTSTAT CNVCMP [0..0] =============================================== */ +typedef enum { /*!< ADC_INTSTAT_CNVCMP */ + ADC_INTSTAT_CNVCMP_CNVCMPINT = 1, /*!< CNVCMPINT : ADC conversion complete interrupt. value. */ +} ADC_INTSTAT_CNVCMP_Enum; + +/* ======================================================== INTCLR ========================================================= */ +/* ================================================ ADC INTCLR DERR [7..7] ================================================= */ +typedef enum { /*!< ADC_INTCLR_DERR */ + ADC_INTCLR_DERR_DMAERROR = 1, /*!< DMAERROR : DMA Error Condition Occurred value. */ +} ADC_INTCLR_DERR_Enum; + +/* ================================================ ADC INTCLR DCMP [6..6] ================================================= */ +typedef enum { /*!< ADC_INTCLR_DCMP */ + ADC_INTCLR_DCMP_DMACOMPLETE = 1, /*!< DMACOMPLETE : DMA Completed a transfer value. */ +} ADC_INTCLR_DCMP_Enum; + +/* ================================================ ADC INTCLR WCINC [5..5] ================================================ */ +typedef enum { /*!< ADC_INTCLR_WCINC */ + ADC_INTCLR_WCINC_WCINCINT = 1, /*!< WCINCINT : Window comparitor voltage incursion interrupt. value. */ +} ADC_INTCLR_WCINC_Enum; + +/* ================================================ ADC INTCLR WCEXC [4..4] ================================================ */ +typedef enum { /*!< ADC_INTCLR_WCEXC */ + ADC_INTCLR_WCEXC_WCEXCINT = 1, /*!< WCEXCINT : Window comparitor voltage excursion interrupt. value. */ +} ADC_INTCLR_WCEXC_Enum; + +/* ============================================== ADC INTCLR FIFOOVR2 [3..3] =============================================== */ +typedef enum { /*!< ADC_INTCLR_FIFOOVR2 */ + ADC_INTCLR_FIFOOVR2_FIFOFULLINT = 1, /*!< FIFOFULLINT : FIFO 100 percent full interrupt. value. */ +} ADC_INTCLR_FIFOOVR2_Enum; + +/* ============================================== ADC INTCLR FIFOOVR1 [2..2] =============================================== */ +typedef enum { /*!< ADC_INTCLR_FIFOOVR1 */ + ADC_INTCLR_FIFOOVR1_FIFO75INT = 1, /*!< FIFO75INT : FIFO 75 percent full interrupt. value. */ +} ADC_INTCLR_FIFOOVR1_Enum; + +/* =============================================== ADC INTCLR SCNCMP [1..1] ================================================ */ +typedef enum { /*!< ADC_INTCLR_SCNCMP */ + ADC_INTCLR_SCNCMP_SCNCMPINT = 1, /*!< SCNCMPINT : ADC scan complete interrupt. value. */ +} ADC_INTCLR_SCNCMP_Enum; + +/* =============================================== ADC INTCLR CNVCMP [0..0] ================================================ */ +typedef enum { /*!< ADC_INTCLR_CNVCMP */ + ADC_INTCLR_CNVCMP_CNVCMPINT = 1, /*!< CNVCMPINT : ADC conversion complete interrupt. value. */ +} ADC_INTCLR_CNVCMP_Enum; + +/* ======================================================== INTSET ========================================================= */ +/* ================================================ ADC INTSET DERR [7..7] ================================================= */ +typedef enum { /*!< ADC_INTSET_DERR */ + ADC_INTSET_DERR_DMAERROR = 1, /*!< DMAERROR : DMA Error Condition Occurred value. */ +} ADC_INTSET_DERR_Enum; + +/* ================================================ ADC INTSET DCMP [6..6] ================================================= */ +typedef enum { /*!< ADC_INTSET_DCMP */ + ADC_INTSET_DCMP_DMACOMPLETE = 1, /*!< DMACOMPLETE : DMA Completed a transfer value. */ +} ADC_INTSET_DCMP_Enum; + +/* ================================================ ADC INTSET WCINC [5..5] ================================================ */ +typedef enum { /*!< ADC_INTSET_WCINC */ + ADC_INTSET_WCINC_WCINCINT = 1, /*!< WCINCINT : Window comparitor voltage incursion interrupt. value. */ +} ADC_INTSET_WCINC_Enum; + +/* ================================================ ADC INTSET WCEXC [4..4] ================================================ */ +typedef enum { /*!< ADC_INTSET_WCEXC */ + ADC_INTSET_WCEXC_WCEXCINT = 1, /*!< WCEXCINT : Window comparitor voltage excursion interrupt. value. */ +} ADC_INTSET_WCEXC_Enum; + +/* ============================================== ADC INTSET FIFOOVR2 [3..3] =============================================== */ +typedef enum { /*!< ADC_INTSET_FIFOOVR2 */ + ADC_INTSET_FIFOOVR2_FIFOFULLINT = 1, /*!< FIFOFULLINT : FIFO 100 percent full interrupt. value. */ +} ADC_INTSET_FIFOOVR2_Enum; + +/* ============================================== ADC INTSET FIFOOVR1 [2..2] =============================================== */ +typedef enum { /*!< ADC_INTSET_FIFOOVR1 */ + ADC_INTSET_FIFOOVR1_FIFO75INT = 1, /*!< FIFO75INT : FIFO 75 percent full interrupt. value. */ +} ADC_INTSET_FIFOOVR1_Enum; + +/* =============================================== ADC INTSET SCNCMP [1..1] ================================================ */ +typedef enum { /*!< ADC_INTSET_SCNCMP */ + ADC_INTSET_SCNCMP_SCNCMPINT = 1, /*!< SCNCMPINT : ADC scan complete interrupt. value. */ +} ADC_INTSET_SCNCMP_Enum; + +/* =============================================== ADC INTSET CNVCMP [0..0] ================================================ */ +typedef enum { /*!< ADC_INTSET_CNVCMP */ + ADC_INTSET_CNVCMP_CNVCMPINT = 1, /*!< CNVCMPINT : ADC conversion complete interrupt. value. */ +} ADC_INTSET_CNVCMP_Enum; + +/* ======================================================= DMATRIGEN ======================================================= */ +/* ====================================================== DMATRIGSTAT ====================================================== */ +/* ======================================================== DMACFG ========================================================= */ +/* ============================================== ADC DMACFG DMAMSK [17..17] =============================================== */ +typedef enum { /*!< ADC_DMACFG_DMAMSK */ + ADC_DMACFG_DMAMSK_DIS = 0, /*!< DIS : FIFO Contents are copied directly to memory without modification. + value. */ + ADC_DMACFG_DMAMSK_EN = 1, /*!< EN : Only the FIFODATA contents are copied to memory on DMA + transfers. The SLOTNUM and FIFOCNT contents are cleared + to zero. value. */ +} ADC_DMACFG_DMAMSK_Enum; + +/* ============================================ ADC DMACFG DMAHONSTAT [16..16] ============================================= */ +typedef enum { /*!< ADC_DMACFG_DMAHONSTAT */ + ADC_DMACFG_DMAHONSTAT_DIS = 0, /*!< DIS : ADC conversions will continue regardless of DMA status + register value. */ + ADC_DMACFG_DMAHONSTAT_EN = 1, /*!< EN : ADC conversions will not progress if DMAERR or DMACPL bits + in DMA status register are set. value. */ +} ADC_DMACFG_DMAHONSTAT_Enum; + +/* ============================================== ADC DMACFG DMADYNPRI [9..9] ============================================== */ +typedef enum { /*!< ADC_DMACFG_DMADYNPRI */ + ADC_DMACFG_DMADYNPRI_DIS = 0, /*!< DIS : Disable dynamic priority (use DMAPRI setting only) value. */ + ADC_DMACFG_DMADYNPRI_EN = 1, /*!< EN : Enable dynamic priority value. */ +} ADC_DMACFG_DMADYNPRI_Enum; + +/* =============================================== ADC DMACFG DMAPRI [8..8] ================================================ */ +typedef enum { /*!< ADC_DMACFG_DMAPRI */ + ADC_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ + ADC_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ +} ADC_DMACFG_DMAPRI_Enum; + +/* =============================================== ADC DMACFG DMADIR [2..2] ================================================ */ +typedef enum { /*!< ADC_DMACFG_DMADIR */ + ADC_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction value. */ + ADC_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction value. */ +} ADC_DMACFG_DMADIR_Enum; + +/* ================================================ ADC DMACFG DMAEN [0..0] ================================================ */ +typedef enum { /*!< ADC_DMACFG_DMAEN */ + ADC_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ + ADC_DMACFG_DMAEN_EN = 1, /*!< EN : Enable DMA Function value. */ +} ADC_DMACFG_DMAEN_Enum; + +/* ====================================================== DMATOTCOUNT ====================================================== */ +/* ====================================================== DMATARGADDR ====================================================== */ +/* ======================================================== DMASTAT ======================================================== */ + + +/* =========================================================================================================================== */ +/* ================ APBDMA ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== BBVALUE ======================================================== */ +/* ====================================================== BBSETCLEAR ======================================================= */ +/* ======================================================== BBINPUT ======================================================== */ +/* ======================================================= DEBUGDATA ======================================================= */ +/* ========================================================= DEBUG ========================================================= */ +/* ============================================== APBDMA DEBUG DEBUGEN [0..3] ============================================== */ +typedef enum { /*!< APBDMA_DEBUG_DEBUGEN */ + APBDMA_DEBUG_DEBUGEN_OFF = 0, /*!< OFF : Debug Disabled value. */ + APBDMA_DEBUG_DEBUGEN_ARB = 1, /*!< ARB : Debug Arb values value. */ +} APBDMA_DEBUG_DEBUGEN_Enum; + + + +/* =========================================================================================================================== */ +/* ================ BLEIF ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= FIFO ========================================================== */ +/* ======================================================== FIFOPTR ======================================================== */ +/* ======================================================== FIFOTHR ======================================================== */ +/* ======================================================== FIFOPOP ======================================================== */ +/* ======================================================= FIFOPUSH ======================================================== */ +/* ======================================================= FIFOCTRL ======================================================== */ +/* ======================================================== FIFOLOC ======================================================== */ +/* ======================================================== CLKCFG ========================================================= */ +/* =============================================== BLEIF CLKCFG FSEL [8..10] =============================================== */ +typedef enum { /*!< BLEIF_CLKCFG_FSEL */ + BLEIF_CLKCFG_FSEL_MIN_PWR = 0, /*!< MIN_PWR : Selects the minimum power clock. This setting should + be used whenever the IOM is not active. value. */ + BLEIF_CLKCFG_FSEL_HFRC = 1, /*!< HFRC : Selects the HFRC as the input clock. value. */ + BLEIF_CLKCFG_FSEL_HFRC_DIV2 = 2, /*!< HFRC_DIV2 : Selects the HFRC / 2 as the input clock. value. */ + BLEIF_CLKCFG_FSEL_HFRC_DIV4 = 3, /*!< HFRC_DIV4 : Selects the HFRC / 4 as the input clock. value. */ + BLEIF_CLKCFG_FSEL_HFRC_DIV8 = 4, /*!< HFRC_DIV8 : Selects the HFRC / 8 as the input clock. value. */ + BLEIF_CLKCFG_FSEL_HFRC_DIV16 = 5, /*!< HFRC_DIV16 : Selects the HFRC / 16 as the input clock. value. */ + BLEIF_CLKCFG_FSEL_HFRC_DIV32 = 6, /*!< HFRC_DIV32 : Selects the HFRC / 32 as the input clock. value. */ + BLEIF_CLKCFG_FSEL_HFRC_DIV64 = 7, /*!< HFRC_DIV64 : Selects the HFRC / 64 as the input clock. value. */ +} BLEIF_CLKCFG_FSEL_Enum; + +/* ========================================================== CMD ========================================================== */ +/* ================================================= BLEIF CMD CMD [0..4] ================================================== */ +typedef enum { /*!< BLEIF_CMD_CMD */ + BLEIF_CMD_CMD_WRITE = 1, /*!< WRITE : Write command using count of offset bytes specified + in the OFFSETCNT field value. */ + BLEIF_CMD_CMD_READ = 2, /*!< READ : Read command using count of offset bytes specified in + the OFFSETCNT field value. */ +} BLEIF_CMD_CMD_Enum; + +/* ======================================================== CMDRPT ========================================================= */ +/* ======================================================= OFFSETHI ======================================================== */ +/* ======================================================== CMDSTAT ======================================================== */ +/* ============================================= BLEIF CMDSTAT CMDSTAT [5..7] ============================================== */ +typedef enum { /*!< BLEIF_CMDSTAT_CMDSTAT */ + BLEIF_CMDSTAT_CMDSTAT_ERR = 1, /*!< ERR : Error encountered with command value. */ + BLEIF_CMDSTAT_CMDSTAT_ACTIVE = 2, /*!< ACTIVE : Actively processing command value. */ + BLEIF_CMDSTAT_CMDSTAT_IDLE = 4, /*!< IDLE : Idle state, no active command, no error value. */ + BLEIF_CMDSTAT_CMDSTAT_WAIT = 6, /*!< WAIT : Command in progress, but waiting on data from host value. */ +} BLEIF_CMDSTAT_CMDSTAT_Enum; + +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ +/* ======================================================= DMATRIGEN ======================================================= */ +/* ====================================================== DMATRIGSTAT ====================================================== */ +/* ======================================================== DMACFG ========================================================= */ +/* ============================================== BLEIF DMACFG DPWROFF [9..9] ============================================== */ +typedef enum { /*!< BLEIF_DMACFG_DPWROFF */ + BLEIF_DMACFG_DPWROFF_DIS = 0, /*!< DIS : Power off disabled value. */ + BLEIF_DMACFG_DPWROFF_EN = 1, /*!< EN : Power off enabled value. */ +} BLEIF_DMACFG_DPWROFF_Enum; + +/* ============================================== BLEIF DMACFG DMAPRI [8..8] =============================================== */ +typedef enum { /*!< BLEIF_DMACFG_DMAPRI */ + BLEIF_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ + BLEIF_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ +} BLEIF_DMACFG_DMAPRI_Enum; + +/* ============================================== BLEIF DMACFG DMADIR [1..1] =============================================== */ +typedef enum { /*!< BLEIF_DMACFG_DMADIR */ + BLEIF_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction. To be set when + doing IOM read operations, ie reading data from external + devices. value. */ + BLEIF_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction. To be set when doing + IOM write operations, ie writing data to external devices. + value. */ +} BLEIF_DMACFG_DMADIR_Enum; + +/* =============================================== BLEIF DMACFG DMAEN [0..0] =============================================== */ +typedef enum { /*!< BLEIF_DMACFG_DMAEN */ + BLEIF_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ + BLEIF_DMACFG_DMAEN_EN = 1, /*!< EN : Enable DMA Function value. */ +} BLEIF_DMACFG_DMAEN_Enum; + +/* ====================================================== DMATOTCOUNT ====================================================== */ +/* ====================================================== DMATARGADDR ====================================================== */ +/* ======================================================== DMASTAT ======================================================== */ +/* ========================================================= CQCFG ========================================================= */ +/* =============================================== BLEIF CQCFG CQPRI [1..1] ================================================ */ +typedef enum { /*!< BLEIF_CQCFG_CQPRI */ + BLEIF_CQCFG_CQPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ + BLEIF_CQCFG_CQPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ +} BLEIF_CQCFG_CQPRI_Enum; + +/* ================================================ BLEIF CQCFG CQEN [0..0] ================================================ */ +typedef enum { /*!< BLEIF_CQCFG_CQEN */ + BLEIF_CQCFG_CQEN_DIS = 0, /*!< DIS : Disable CQ Function value. */ + BLEIF_CQCFG_CQEN_EN = 1, /*!< EN : Enable CQ Function value. */ +} BLEIF_CQCFG_CQEN_Enum; + +/* ======================================================== CQADDR ========================================================= */ +/* ======================================================== CQSTAT ========================================================= */ +/* ======================================================== CQFLAGS ======================================================== */ +/* ====================================================== CQSETCLEAR ======================================================= */ +/* ======================================================= CQPAUSEEN ======================================================= */ +/* ============================================= BLEIF CQPAUSEEN CQPEN [0..15] ============================================= */ +typedef enum { /*!< BLEIF_CQPAUSEEN_CQPEN */ + BLEIF_CQPAUSEEN_CQPEN_CNTEQ = 32768, /*!< CNTEQ : Pauses command queue processing when HWCNT matches SWCNT + value. */ + BLEIF_CQPAUSEEN_CQPEN_BLEXOREN = 16384, /*!< BLEXOREN : Pause command queue when input BLE bit XORed with + SWFLAG4 is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_IOMXOREN = 8192, /*!< IOMXOREN : Pause command queue when input IOM bit XORed with + SWFLAG3 is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_GPIOXOREN = 4096, /*!< GPIOXOREN : Pause command queue when input GPIO irq_bit XORed + with SWFLAG2 is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_MSPI1XNOREN = 2048, /*!< MSPI1XNOREN : Pause command queue when input MSPI1 bit XNORed + with SWFLAG1 is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_MSPI0XNOREN = 1024, /*!< MSPI0XNOREN : Pause command queue when input MSPI0 bit XNORed + with SWFLAG0 is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_MSPI1XOREN = 512, /*!< MSPI1XOREN : Pause command queue when input MSPI1 bit XORed + with SWFLAG1 is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_MSPI0XOREN = 256, /*!< MSPI0XOREN : Pause command queue when input MSPI0 bit XORed + with SWFLAG0 is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN7 = 128, /*!< SWFLAGEN7 : Pause the command queue when software flag bit 7 + is '1'. value. */ + BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN6 = 64, /*!< SWFLAGEN6 : Pause the command queue when software flag bit 7 + is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN5 = 32, /*!< SWFLAGEN5 : Pause the command queue when software flag bit 7 + is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN4 = 16, /*!< SWFLAGEN4 : Pause the command queue when software flag bit 7 + is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN3 = 8, /*!< SWFLAGEN3 : Pause the command queue when software flag bit 7 + is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN2 = 4, /*!< SWFLAGEN2 : Pause the command queue when software flag bit 7 + is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN1 = 2, /*!< SWFLAGEN1 : Pause the command queue when software flag bit 7 + is '1' value. */ + BLEIF_CQPAUSEEN_CQPEN_SWFLGEN0 = 1, /*!< SWFLGEN0 : Pause the command queue when software flag bit 7 + is '1' value. */ +} BLEIF_CQPAUSEEN_CQPEN_Enum; + +/* ======================================================= CQCURIDX ======================================================== */ +/* ======================================================= CQENDIDX ======================================================== */ +/* ======================================================== STATUS ========================================================= */ +/* ============================================== BLEIF STATUS IDLEST [2..2] =============================================== */ +typedef enum { /*!< BLEIF_STATUS_IDLEST */ + BLEIF_STATUS_IDLEST_IDLE = 1, /*!< IDLE : The I/O state machine is in the idle state. value. */ +} BLEIF_STATUS_IDLEST_Enum; + +/* ============================================== BLEIF STATUS CMDACT [1..1] =============================================== */ +typedef enum { /*!< BLEIF_STATUS_CMDACT */ + BLEIF_STATUS_CMDACT_ACTIVE = 1, /*!< ACTIVE : An I/O command is active. Indicates the active module + has an active command and is processing this. De-asserted + when the command is completed. value. */ +} BLEIF_STATUS_CMDACT_Enum; + +/* ================================================ BLEIF STATUS ERR [0..0] ================================================ */ +typedef enum { /*!< BLEIF_STATUS_ERR */ + BLEIF_STATUS_ERR_ERROR = 1, /*!< ERROR : Bit has been deprecated and will always return 0. value. */ +} BLEIF_STATUS_ERR_Enum; + +/* ======================================================== MSPICFG ======================================================== */ +/* ============================================= BLEIF MSPICFG SPILSB [23..23] ============================================= */ +typedef enum { /*!< BLEIF_MSPICFG_SPILSB */ + BLEIF_MSPICFG_SPILSB_MSB = 0, /*!< MSB : Send and receive MSB bit first value. */ + BLEIF_MSPICFG_SPILSB_LSB = 1, /*!< LSB : Send and receive LSB bit first value. */ +} BLEIF_MSPICFG_SPILSB_Enum; + +/* ============================================ BLEIF MSPICFG RDFCPOL [22..22] ============================================= */ +typedef enum { /*!< BLEIF_MSPICFG_RDFCPOL */ + BLEIF_MSPICFG_RDFCPOL_NORMAL = 0, /*!< NORMAL : SPI_STATUS signal from BLE Core high(1) creates flow + control and new read spi transactions will not be started + until the signal goes low.(default) value. */ + BLEIF_MSPICFG_RDFCPOL_INVERTED = 1, /*!< INVERTED : SPI_STATUS signal from BLE Core low(0) creates flow + control and new read spi transactions will not be started + until the signal goes high. value. */ +} BLEIF_MSPICFG_RDFCPOL_Enum; + +/* ============================================ BLEIF MSPICFG WTFCPOL [21..21] ============================================= */ +typedef enum { /*!< BLEIF_MSPICFG_WTFCPOL */ + BLEIF_MSPICFG_WTFCPOL_NORMAL = 0, /*!< NORMAL : SPI_STATUS signal from BLE Core high(1) creates flow + control and new write spi transactions will not be started + until the signal goes low.(default) value. */ + BLEIF_MSPICFG_WTFCPOL_INVERTED = 1, /*!< INVERTED : SPI_STATUS signal from BLE Core high(1) creates low(0) + control and new write spi transactions will not be started + until the signal goes high. value. */ +} BLEIF_MSPICFG_WTFCPOL_Enum; + +/* ============================================== BLEIF MSPICFG RDFC [17..17] ============================================== */ +typedef enum { /*!< BLEIF_MSPICFG_RDFC */ + BLEIF_MSPICFG_RDFC_DIS = 0, /*!< DIS : Read mode flow control disabled. value. */ + BLEIF_MSPICFG_RDFC_EN = 1, /*!< EN : Read mode flow control enabled. value. */ +} BLEIF_MSPICFG_RDFC_Enum; + +/* ============================================== BLEIF MSPICFG WTFC [16..16] ============================================== */ +typedef enum { /*!< BLEIF_MSPICFG_WTFC */ + BLEIF_MSPICFG_WTFC_DIS = 0, /*!< DIS : Write mode flow control disabled. value. */ + BLEIF_MSPICFG_WTFC_EN = 1, /*!< EN : Write mode flow control enabled. value. */ +} BLEIF_MSPICFG_WTFC_Enum; + +/* =============================================== BLEIF MSPICFG SPHA [1..1] =============================================== */ +typedef enum { /*!< BLEIF_MSPICFG_SPHA */ + BLEIF_MSPICFG_SPHA_SAMPLE_LEADING_EDGE = 0, /*!< SAMPLE_LEADING_EDGE : Sample on the leading (first) clock edge, + rising or falling dependant on the value of SPOL value. */ + BLEIF_MSPICFG_SPHA_SAMPLE_TRAILING_EDGE = 1, /*!< SAMPLE_TRAILING_EDGE : Sample on the trailing (second) clock + edge, rising of falling dependant on the value of SPOL + value. */ +} BLEIF_MSPICFG_SPHA_Enum; + +/* =============================================== BLEIF MSPICFG SPOL [0..0] =============================================== */ +typedef enum { /*!< BLEIF_MSPICFG_SPOL */ + BLEIF_MSPICFG_SPOL_CLK_BASE_0 = 0, /*!< CLK_BASE_0 : The initial value of the clock is 0. value. */ + BLEIF_MSPICFG_SPOL_CLK_BASE_1 = 1, /*!< CLK_BASE_1 : The initial value of the clock is 1. value. */ +} BLEIF_MSPICFG_SPOL_Enum; + +/* ======================================================== BLECFG ========================================================= */ +/* ============================================ BLEIF BLECFG SPIISOCTL [14..15] ============================================ */ +typedef enum { /*!< BLEIF_BLECFG_SPIISOCTL */ + BLEIF_BLECFG_SPIISOCTL_ON = 3, /*!< ON : SPI signals from BLE Core to/from MCU Core are isolated. + value. */ + BLEIF_BLECFG_SPIISOCTL_OFF = 2, /*!< OFF : SPI signals from BLE Core to/from MCU Core are not isolated. + value. */ + BLEIF_BLECFG_SPIISOCTL_AUTO = 0, /*!< AUTO : SPI signals from BLE Core to/from MCU Core are automatically + isolated by the logic value. */ +} BLEIF_BLECFG_SPIISOCTL_Enum; + +/* ============================================ BLEIF BLECFG PWRISOCTL [12..13] ============================================ */ +typedef enum { /*!< BLEIF_BLECFG_PWRISOCTL */ + BLEIF_BLECFG_PWRISOCTL_ON = 3, /*!< ON : BLEH power signal isolation to on (isolated). value. */ + BLEIF_BLECFG_PWRISOCTL_OFF = 2, /*!< OFF : BLEH power signal isolation to off (not isolated). value. */ + BLEIF_BLECFG_PWRISOCTL_AUTO = 0, /*!< AUTO : BLEH Power signal isolation is controlled automatically + through the interface logic value. */ +} BLEIF_BLECFG_PWRISOCTL_Enum; + +/* ============================================ BLEIF BLECFG BLEHREQCTL [6..7] ============================================= */ +typedef enum { /*!< BLEIF_BLECFG_BLEHREQCTL */ + BLEIF_BLECFG_BLEHREQCTL_ON = 3, /*!< ON : BLEH Power-on reg signal is set to on (1). value. */ + BLEIF_BLECFG_BLEHREQCTL_OFF = 2, /*!< OFF : BLEH Power-on signal is set to off (0). value. */ + BLEIF_BLECFG_BLEHREQCTL_AUTO = 0, /*!< AUTO : BLEH Power-on signal is controlled by the PWRSM logic + and automatically controlled value. */ +} BLEIF_BLECFG_BLEHREQCTL_Enum; + +/* ============================================ BLEIF BLECFG DCDCFLGCTL [4..5] ============================================= */ +typedef enum { /*!< BLEIF_BLECFG_DCDCFLGCTL */ + BLEIF_BLECFG_DCDCFLGCTL_ON = 3, /*!< ON : DCDC Flag signal is set to on (1). value. */ + BLEIF_BLECFG_DCDCFLGCTL_OFF = 2, /*!< OFF : DCDC Flag signal is set to off (0). value. */ + BLEIF_BLECFG_DCDCFLGCTL_AUTO = 0, /*!< AUTO : DCDC Flag signal is controlled by the PWRSM logic and + automatically controlled value. */ +} BLEIF_BLECFG_DCDCFLGCTL_Enum; + +/* ============================================= BLEIF BLECFG WAKEUPCTL [2..3] ============================================= */ +typedef enum { /*!< BLEIF_BLECFG_WAKEUPCTL */ + BLEIF_BLECFG_WAKEUPCTL_ON = 3, /*!< ON : Wake signal is set to on (1). value. */ + BLEIF_BLECFG_WAKEUPCTL_OFF = 2, /*!< OFF : Wake signal is set to off (0). value. */ + BLEIF_BLECFG_WAKEUPCTL_AUTO = 0, /*!< AUTO : Wake signal is controlled by the PWRSM logic and automatically + controlled value. */ +} BLEIF_BLECFG_WAKEUPCTL_Enum; + +/* ============================================== BLEIF BLECFG BLERSTN [1..1] ============================================== */ +typedef enum { /*!< BLEIF_BLECFG_BLERSTN */ + BLEIF_BLECFG_BLERSTN_ACTIVE = 1, /*!< ACTIVE : The reset signal is active (0) value. */ + BLEIF_BLECFG_BLERSTN_INACTIVE = 0, /*!< INACTIVE : The reset signal is inactive (1) value. */ +} BLEIF_BLECFG_BLERSTN_Enum; + +/* ============================================== BLEIF BLECFG PWRSMEN [0..0] ============================================== */ +typedef enum { /*!< BLEIF_BLECFG_PWRSMEN */ + BLEIF_BLECFG_PWRSMEN_ON = 1, /*!< ON : Internal power state machine is enabled and will sequence + the BLEH power domain as indicated in the design document. + Overrides for the power signals are not enabled. value. */ + BLEIF_BLECFG_PWRSMEN_OFF = 0, /*!< OFF : Internal power state machine is disabled and will not + sequence the BLEH power domain. The values of the overrides + will be used to drive the output sequencing signals value. */ +} BLEIF_BLECFG_PWRSMEN_Enum; + +/* ======================================================== PWRCMD ========================================================= */ +/* ======================================================== BSTATUS ======================================================== */ +/* ============================================== BLEIF BSTATUS PWRST [8..10] ============================================== */ +typedef enum { /*!< BLEIF_BSTATUS_PWRST */ + BLEIF_BSTATUS_PWRST_OFF = 0, /*!< OFF : Internal power state machine is disabled and will not + sequence the BLEH power domain. The values of the overrides + will be used to drive the output sequencing signals value. */ + BLEIF_BSTATUS_PWRST_INIT = 1, /*!< INIT : Initialization state. BLEH not powered value. */ + BLEIF_BSTATUS_PWRST_PWRON = 2, /*!< PWRON : Waiting for the powerup of the BLEH value. */ + BLEIF_BSTATUS_PWRST_ACTIVE = 3, /*!< ACTIVE : The BLE Core is powered and active value. */ + BLEIF_BSTATUS_PWRST_SLEEP = 6, /*!< SLEEP : The BLE Core has entered sleep mode and the power request + is inactive value. */ + BLEIF_BSTATUS_PWRST_SHUTDOWN = 4, /*!< SHUTDOWN : The BLE Core is in shutdown mode value. */ +} BLEIF_BSTATUS_PWRST_Enum; + +/* ============================================= BLEIF BSTATUS B2MSTATE [0..2] ============================================= */ +typedef enum { /*!< BLEIF_BSTATUS_B2MSTATE */ + BLEIF_BSTATUS_B2MSTATE_RESET = 0, /*!< RESET : Reset State value. */ + BLEIF_BSTATUS_B2MSTATE_Sleep = 1, /*!< Sleep : Sleep state. value. */ + BLEIF_BSTATUS_B2MSTATE_Standby = 2, /*!< Standby : Standby State value. */ + BLEIF_BSTATUS_B2MSTATE_Idle = 3, /*!< Idle : Idle state value. */ + BLEIF_BSTATUS_B2MSTATE_Active = 4, /*!< Active : Active state. value. */ +} BLEIF_BSTATUS_B2MSTATE_Enum; + +/* ======================================================== BLEDBG ========================================================= */ + + +/* =========================================================================================================================== */ +/* ================ CACHECTRL ================ */ +/* =========================================================================================================================== */ + +/* ======================================================= CACHECFG ======================================================== */ +/* =========================================== CACHECTRL CACHECFG CONFIG [4..7] ============================================ */ +typedef enum { /*!< CACHECTRL_CACHECFG_CONFIG */ + CACHECTRL_CACHECFG_CONFIG_W1_128B_512E = 4, /*!< W1_128B_512E : Direct mapped, 128-bit linesize, 512 entries + (4 SRAMs active) value. */ + CACHECTRL_CACHECFG_CONFIG_W2_128B_512E = 5, /*!< W2_128B_512E : Two-way set associative, 128-bit linesize, 512 + entries (8 SRAMs active) value. */ + CACHECTRL_CACHECFG_CONFIG_W1_128B_1024E = 8, /*!< W1_128B_1024E : Direct mapped, 128-bit linesize, 1024 entries + (8 SRAMs active) value. */ +} CACHECTRL_CACHECFG_CONFIG_Enum; + +/* ======================================================= FLASHCFG ======================================================== */ +/* ========================================== CACHECTRL FLASHCFG LPMMODE [12..13] ========================================== */ +typedef enum { /*!< CACHECTRL_FLASHCFG_LPMMODE */ + CACHECTRL_FLASHCFG_LPMMODE_NEVER = 0, /*!< NEVER : High power mode (LPM not used). value. */ + CACHECTRL_FLASHCFG_LPMMODE_STANDBY = 1, /*!< STANDBY : Fast Standby mode. LPM deasserted for read operations, + but asserted while flash IDLE. value. */ + CACHECTRL_FLASHCFG_LPMMODE_ALWAYS = 2, /*!< ALWAYS : Low Power mode. LPM always asserted for reads. LPM_RD_WAIT + must be programmed to accomodate longer read access times. + value. */ +} CACHECTRL_FLASHCFG_LPMMODE_Enum; + +/* ========================================================= CTRL ========================================================== */ +/* =========================================== CACHECTRL CTRL RESET_STAT [1..1] ============================================ */ +typedef enum { /*!< CACHECTRL_CTRL_RESET_STAT */ + CACHECTRL_CTRL_RESET_STAT_CLEAR = 1, /*!< CLEAR : Clear Cache Stats value. */ +} CACHECTRL_CTRL_RESET_STAT_Enum; + +/* ======================================================= NCR0START ======================================================= */ +/* ======================================================== NCR0END ======================================================== */ +/* ======================================================= NCR1START ======================================================= */ +/* ======================================================== NCR1END ======================================================== */ +/* ========================================================= DMON0 ========================================================= */ +/* ========================================================= DMON1 ========================================================= */ +/* ========================================================= DMON2 ========================================================= */ +/* ========================================================= DMON3 ========================================================= */ +/* ========================================================= IMON0 ========================================================= */ +/* ========================================================= IMON1 ========================================================= */ +/* ========================================================= IMON2 ========================================================= */ +/* ========================================================= IMON3 ========================================================= */ + + +/* =========================================================================================================================== */ +/* ================ CLKGEN ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= CALXT ========================================================= */ +/* ========================================================= CALRC ========================================================= */ +/* ======================================================== ACALCTR ======================================================== */ +/* ========================================================= OCTRL ========================================================= */ +/* =============================================== CLKGEN OCTRL ACAL [8..10] =============================================== */ +typedef enum { /*!< CLKGEN_OCTRL_ACAL */ + CLKGEN_OCTRL_ACAL_DIS = 0, /*!< DIS : Disable Autocalibration value. */ + CLKGEN_OCTRL_ACAL_1024SEC = 2, /*!< 1024SEC : Autocalibrate every 1024 seconds. Once autocalibration + is done, an interrupt will be triggered at the end of 1024 + seconds. value. */ + CLKGEN_OCTRL_ACAL_512SEC = 3, /*!< 512SEC : Autocalibrate every 512 seconds. Once autocalibration + is done, an interrupt will be trigged at the end of 512 + seconds. value. */ + CLKGEN_OCTRL_ACAL_XTFREQ = 6, /*!< XTFREQ : Frequency measurement using XT. The XT clock is normally + considered much more accurate than the LFRC clock source. + value. */ + CLKGEN_OCTRL_ACAL_EXTFREQ = 7, /*!< EXTFREQ : Frequency measurement using external clock. value. */ +} CLKGEN_OCTRL_ACAL_Enum; + +/* =============================================== CLKGEN OCTRL OSEL [7..7] ================================================ */ +typedef enum { /*!< CLKGEN_OCTRL_OSEL */ + CLKGEN_OCTRL_OSEL_RTC_XT = 0, /*!< RTC_XT : RTC uses the XT value. */ + CLKGEN_OCTRL_OSEL_RTC_LFRC = 1, /*!< RTC_LFRC : RTC uses the LFRC value. */ +} CLKGEN_OCTRL_OSEL_Enum; + +/* ================================================ CLKGEN OCTRL FOS [6..6] ================================================ */ +typedef enum { /*!< CLKGEN_OCTRL_FOS */ + CLKGEN_OCTRL_FOS_DIS = 0, /*!< DIS : Disable the oscillator switch on failure function. value. */ + CLKGEN_OCTRL_FOS_EN = 1, /*!< EN : Enable the oscillator switch on failure function. value. */ +} CLKGEN_OCTRL_FOS_Enum; + +/* ============================================== CLKGEN OCTRL STOPRC [1..1] =============================================== */ +typedef enum { /*!< CLKGEN_OCTRL_STOPRC */ + CLKGEN_OCTRL_STOPRC_EN = 0, /*!< EN : Enable the LFRC Oscillator to drive the RTC value. */ + CLKGEN_OCTRL_STOPRC_STOP = 1, /*!< STOP : Stop the LFRC Oscillator when driving the RTC value. */ +} CLKGEN_OCTRL_STOPRC_Enum; + +/* ============================================== CLKGEN OCTRL STOPXT [0..0] =============================================== */ +typedef enum { /*!< CLKGEN_OCTRL_STOPXT */ + CLKGEN_OCTRL_STOPXT_EN = 0, /*!< EN : Enable the XT Oscillator to drive the RTC value. */ + CLKGEN_OCTRL_STOPXT_STOP = 1, /*!< STOP : Stop the XT Oscillator when driving the RTC value. */ +} CLKGEN_OCTRL_STOPXT_Enum; + +/* ======================================================== CLKOUT ========================================================= */ +/* =============================================== CLKGEN CLKOUT CKEN [7..7] =============================================== */ +typedef enum { /*!< CLKGEN_CLKOUT_CKEN */ + CLKGEN_CLKOUT_CKEN_DIS = 0, /*!< DIS : Disable CLKOUT value. */ + CLKGEN_CLKOUT_CKEN_EN = 1, /*!< EN : Enable CLKOUT value. */ +} CLKGEN_CLKOUT_CKEN_Enum; + +/* ============================================== CLKGEN CLKOUT CKSEL [0..5] =============================================== */ +typedef enum { /*!< CLKGEN_CLKOUT_CKSEL */ + CLKGEN_CLKOUT_CKSEL_LFRC = 0, /*!< LFRC : LFRC value. */ + CLKGEN_CLKOUT_CKSEL_XT_DIV2 = 1, /*!< XT_DIV2 : XT / 2 value. */ + CLKGEN_CLKOUT_CKSEL_XT_DIV4 = 2, /*!< XT_DIV4 : XT / 4 value. */ + CLKGEN_CLKOUT_CKSEL_XT_DIV8 = 3, /*!< XT_DIV8 : XT / 8 value. */ + CLKGEN_CLKOUT_CKSEL_XT_DIV16 = 4, /*!< XT_DIV16 : XT / 16 value. */ + CLKGEN_CLKOUT_CKSEL_XT_DIV32 = 5, /*!< XT_DIV32 : XT / 32 value. */ + CLKGEN_CLKOUT_CKSEL_RTC_1Hz = 16, /*!< RTC_1Hz : 1 Hz as selected in RTC value. */ + CLKGEN_CLKOUT_CKSEL_XT_DIV2M = 22, /*!< XT_DIV2M : XT / 2^21 value. */ + CLKGEN_CLKOUT_CKSEL_XT = 23, /*!< XT : XT value. */ + CLKGEN_CLKOUT_CKSEL_CG_100Hz = 24, /*!< CG_100Hz : 100 Hz as selected in CLKGEN value. */ + CLKGEN_CLKOUT_CKSEL_HFRC = 25, /*!< HFRC : HFRC value. */ + CLKGEN_CLKOUT_CKSEL_HFRC_DIV4 = 26, /*!< HFRC_DIV4 : HFRC / 4 value. */ + CLKGEN_CLKOUT_CKSEL_HFRC_DIV8 = 27, /*!< HFRC_DIV8 : HFRC / 8 value. */ + CLKGEN_CLKOUT_CKSEL_HFRC_DIV16 = 28, /*!< HFRC_DIV16 : HFRC / 16 value. */ + CLKGEN_CLKOUT_CKSEL_HFRC_DIV64 = 29, /*!< HFRC_DIV64 : HFRC / 64 value. */ + CLKGEN_CLKOUT_CKSEL_HFRC_DIV128 = 30, /*!< HFRC_DIV128 : HFRC / 128 value. */ + CLKGEN_CLKOUT_CKSEL_HFRC_DIV256 = 31, /*!< HFRC_DIV256 : HFRC / 256 value. */ + CLKGEN_CLKOUT_CKSEL_HFRC_DIV512 = 32, /*!< HFRC_DIV512 : HFRC / 512 value. */ + CLKGEN_CLKOUT_CKSEL_FLASH_CLK = 34, /*!< FLASH_CLK : Flash Clock value. */ + CLKGEN_CLKOUT_CKSEL_LFRC_DIV2 = 35, /*!< LFRC_DIV2 : LFRC / 2 value. */ + CLKGEN_CLKOUT_CKSEL_LFRC_DIV32 = 36, /*!< LFRC_DIV32 : LFRC / 32 value. */ + CLKGEN_CLKOUT_CKSEL_LFRC_DIV512 = 37, /*!< LFRC_DIV512 : LFRC / 512 value. */ + CLKGEN_CLKOUT_CKSEL_LFRC_DIV32K = 38, /*!< LFRC_DIV32K : LFRC / 32768 value. */ + CLKGEN_CLKOUT_CKSEL_XT_DIV256 = 39, /*!< XT_DIV256 : XT / 256 value. */ + CLKGEN_CLKOUT_CKSEL_XT_DIV8K = 40, /*!< XT_DIV8K : XT / 8192 value. */ + CLKGEN_CLKOUT_CKSEL_XT_DIV64K = 41, /*!< XT_DIV64K : XT / 2^16 value. */ + CLKGEN_CLKOUT_CKSEL_ULFRC_DIV16 = 42, /*!< ULFRC_DIV16 : Uncal LFRC / 16 value. */ + CLKGEN_CLKOUT_CKSEL_ULFRC_DIV128 = 43, /*!< ULFRC_DIV128 : Uncal LFRC / 128 value. */ + CLKGEN_CLKOUT_CKSEL_ULFRC_1Hz = 44, /*!< ULFRC_1Hz : Uncal LFRC / 1024 value. */ + CLKGEN_CLKOUT_CKSEL_ULFRC_DIV4K = 45, /*!< ULFRC_DIV4K : Uncal LFRC / 4096 value. */ + CLKGEN_CLKOUT_CKSEL_ULFRC_DIV1M = 46, /*!< ULFRC_DIV1M : Uncal LFRC / 2^20 value. */ + CLKGEN_CLKOUT_CKSEL_HFRC_DIV64K = 47, /*!< HFRC_DIV64K : HFRC / 2^16 value. */ + CLKGEN_CLKOUT_CKSEL_HFRC_DIV16M = 48, /*!< HFRC_DIV16M : HFRC / 2^24 value. */ + CLKGEN_CLKOUT_CKSEL_LFRC_DIV1M = 49, /*!< LFRC_DIV1M : LFRC / 2^20 value. */ + CLKGEN_CLKOUT_CKSEL_HFRCNE = 50, /*!< HFRCNE : HFRC (not autoenabled) value. */ + CLKGEN_CLKOUT_CKSEL_HFRCNE_DIV8 = 51, /*!< HFRCNE_DIV8 : HFRC / 8 (not autoenabled) value. */ + CLKGEN_CLKOUT_CKSEL_XTNE = 53, /*!< XTNE : XT (not autoenabled) value. */ + CLKGEN_CLKOUT_CKSEL_XTNE_DIV16 = 54, /*!< XTNE_DIV16 : XT / 16 (not autoenabled) value. */ + CLKGEN_CLKOUT_CKSEL_LFRCNE_DIV32 = 55, /*!< LFRCNE_DIV32 : LFRC / 32 (not autoenabled) value. */ + CLKGEN_CLKOUT_CKSEL_LFRCNE = 57, /*!< LFRCNE : LFRC (not autoenabled) - Default for undefined values + value. */ +} CLKGEN_CLKOUT_CKSEL_Enum; + +/* ======================================================== CLKKEY ========================================================= */ +/* ============================================= CLKGEN CLKKEY CLKKEY [0..31] ============================================== */ +typedef enum { /*!< CLKGEN_CLKKEY_CLKKEY */ + CLKGEN_CLKKEY_CLKKEY_Key = 71, /*!< Key : Key value. */ +} CLKGEN_CLKKEY_CLKKEY_Enum; + +/* ========================================================= CCTRL ========================================================= */ +/* ============================================== CLKGEN CCTRL CORESEL [0..0] ============================================== */ +typedef enum { /*!< CLKGEN_CCTRL_CORESEL */ + CLKGEN_CCTRL_CORESEL_HFRC = 0, /*!< HFRC : Core Clock is HFRC value. */ + CLKGEN_CCTRL_CORESEL_HFRC_DIV2 = 1, /*!< HFRC_DIV2 : Core Clock is HFRC / 2 value. */ +} CLKGEN_CCTRL_CORESEL_Enum; + +/* ======================================================== STATUS ========================================================= */ +/* ========================================================= HFADJ ========================================================= */ +/* ============================================ CLKGEN HFADJ HFADJGAIN [21..23] ============================================ */ +typedef enum { /*!< CLKGEN_HFADJ_HFADJGAIN */ + CLKGEN_HFADJ_HFADJGAIN_Gain_of_1 = 0, /*!< Gain_of_1 : HF Adjust with Gain of 1 value. */ + CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_2 = 1, /*!< Gain_of_1_in_2 : HF Adjust with Gain of 0.5 value. */ + CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_4 = 2, /*!< Gain_of_1_in_4 : HF Adjust with Gain of 0.25 value. */ + CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_8 = 3, /*!< Gain_of_1_in_8 : HF Adjust with Gain of 0.125 value. */ + CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_16 = 4, /*!< Gain_of_1_in_16 : HF Adjust with Gain of 0.0625 value. */ + CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_32 = 5, /*!< Gain_of_1_in_32 : HF Adjust with Gain of 0.03125 value. */ +} CLKGEN_HFADJ_HFADJGAIN_Enum; + +/* ============================================ CLKGEN HFADJ HFWARMUP [20..20] ============================================= */ +typedef enum { /*!< CLKGEN_HFADJ_HFWARMUP */ + CLKGEN_HFADJ_HFWARMUP_1SEC = 0, /*!< 1SEC : Autoadjust XT warmup period = 1-2 seconds value. */ + CLKGEN_HFADJ_HFWARMUP_2SEC = 1, /*!< 2SEC : Autoadjust XT warmup period = 2-4 seconds value. */ +} CLKGEN_HFADJ_HFWARMUP_Enum; + +/* ============================================== CLKGEN HFADJ HFADJCK [1..3] ============================================== */ +typedef enum { /*!< CLKGEN_HFADJ_HFADJCK */ + CLKGEN_HFADJ_HFADJCK_4SEC = 0, /*!< 4SEC : Autoadjust repeat period = 4 seconds value. */ + CLKGEN_HFADJ_HFADJCK_16SEC = 1, /*!< 16SEC : Autoadjust repeat period = 16 seconds value. */ + CLKGEN_HFADJ_HFADJCK_32SEC = 2, /*!< 32SEC : Autoadjust repeat period = 32 seconds value. */ + CLKGEN_HFADJ_HFADJCK_64SEC = 3, /*!< 64SEC : Autoadjust repeat period = 64 seconds value. */ + CLKGEN_HFADJ_HFADJCK_128SEC = 4, /*!< 128SEC : Autoadjust repeat period = 128 seconds value. */ + CLKGEN_HFADJ_HFADJCK_256SEC = 5, /*!< 256SEC : Autoadjust repeat period = 256 seconds value. */ + CLKGEN_HFADJ_HFADJCK_512SEC = 6, /*!< 512SEC : Autoadjust repeat period = 512 seconds value. */ + CLKGEN_HFADJ_HFADJCK_1024SEC = 7, /*!< 1024SEC : Autoadjust repeat period = 1024 seconds value. */ +} CLKGEN_HFADJ_HFADJCK_Enum; + +/* ============================================== CLKGEN HFADJ HFADJEN [0..0] ============================================== */ +typedef enum { /*!< CLKGEN_HFADJ_HFADJEN */ + CLKGEN_HFADJ_HFADJEN_DIS = 0, /*!< DIS : Disable the HFRC adjustment value. */ + CLKGEN_HFADJ_HFADJEN_EN = 1, /*!< EN : Enable the HFRC adjustment value. */ +} CLKGEN_HFADJ_HFADJEN_Enum; + +/* ====================================================== CLOCKENSTAT ====================================================== */ +/* ======================================== CLKGEN CLOCKENSTAT CLOCKENSTAT [0..31] ========================================= */ +typedef enum { /*!< CLKGEN_CLOCKENSTAT_CLOCKENSTAT */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_ADC_CLKEN = 1, /*!< ADC_CLKEN : Clock enable for the ADC. value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_ACTIVITY_CLKEN = 2,/*!< APBDMA_ACTIVITY_CLKEN : Clock enable for the APBDMA ACTIVITY + value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_AOH_CLKEN = 4,/*!< APBDMA_AOH_CLKEN : Clock enable for the APBDMA AOH DOMAIN value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_AOL_CLKEN = 8,/*!< APBDMA_AOL_CLKEN : Clock enable for the APBDMA AOL DOMAIN value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_APB_CLKEN = 16,/*!< APBDMA_APB_CLKEN : Clock enable for the APBDMA_APB value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_BLEL_CLKEN = 32,/*!< APBDMA_BLEL_CLKEN : Clock enable for the APBDMA_BLEL value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_HCPA_CLKEN = 64,/*!< APBDMA_HCPA_CLKEN : Clock enable for the APBDMA_HCPA value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_HCPB_CLKEN = 128,/*!< APBDMA_HCPB_CLKEN : Clock enable for the APBDMA_HCPB value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_HCPC_CLKEN = 256,/*!< APBDMA_HCPC_CLKEN : Clock enable for the APBDMA_HCPC value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_MSPI_CLKEN = 512,/*!< APBDMA_MSPI_CLKEN : Clock enable for the APBDMA_MSPI value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_PDM_CLKEN = 1024,/*!< APBDMA_PDM_CLKEN : Clock enable for the APBDMA_PDM value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_BLEIF_CLK_CLKEN = 2048,/*!< BLEIF_CLK_CLKEN : Clock enable for the BLEIF value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_BLEIF_CLK32K_CLKEN = 4096,/*!< BLEIF_CLK32K_CLKEN : Clock enable for the BLEIF 32khZ CLOCK + value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER_CLKEN = 8192,/*!< CTIMER_CLKEN : Clock enable for the CTIMER BLOCK value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER0A_CLKEN = 16384,/*!< CTIMER0A_CLKEN : Clock enable for the CTIMER0A value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER0B_CLKEN = 32768,/*!< CTIMER0B_CLKEN : Clock enable for the CTIMER0B value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER1A_CLKEN = 65536,/*!< CTIMER1A_CLKEN : Clock enable for the CTIMER1A value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER1B_CLKEN = 131072,/*!< CTIMER1B_CLKEN : Clock enable for the CTIMER1B value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER2A_CLKEN = 262144,/*!< CTIMER2A_CLKEN : Clock enable for the CTIMER2A value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER2B_CLKEN = 524288,/*!< CTIMER2B_CLKEN : Clock enable for the CTIMER2B value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER3A_CLKEN = 1048576,/*!< CTIMER3A_CLKEN : Clock enable for the CTIMER3A value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER3B_CLKEN = 2097152,/*!< CTIMER3B_CLKEN : Clock enable for the CTIMER3B value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER4A_CLKEN = 4194304,/*!< CTIMER4A_CLKEN : Clock enable for the CTIMER4A value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER4B_CLKEN = 8388608,/*!< CTIMER4B_CLKEN : Clock enable for the CTIMER4B value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER5A_CLKEN = 16777216,/*!< CTIMER5A_CLKEN : Clock enable for the CTIMER5A value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER5B_CLKEN = 33554432,/*!< CTIMER5B_CLKEN : Clock enable for the CTIMER5B value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER6A_CLKEN = 67108864,/*!< CTIMER6A_CLKEN : Clock enable for the CTIMER6A value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER6B_CLKEN = 134217728,/*!< CTIMER6B_CLKEN : Clock enable for the CTIMER6B value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER7A_CLKEN = 268435456,/*!< CTIMER7A_CLKEN : Clock enable for the CTIMER7A value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER7B_CLKEN = 536870912,/*!< CTIMER7B_CLKEN : Clock enable for the CTIMER7B value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_DAP_CLKEN = 1073741824,/*!< DAP_CLKEN : Clock enable for the DAP value. */ + CLKGEN_CLOCKENSTAT_CLOCKENSTAT_IOMSTRIFC0_CLKEN = -2147483648,/*!< IOMSTRIFC0_CLKEN : Clock enable for the IOMSTRIFC0 value. */ +} CLKGEN_CLOCKENSTAT_CLOCKENSTAT_Enum; + +/* ===================================================== CLOCKEN2STAT ====================================================== */ +/* ======================================= CLKGEN CLOCKEN2STAT CLOCKEN2STAT [0..31] ======================================== */ +typedef enum { /*!< CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC1_CLKEN = 1,/*!< IOMSTRIFC1_CLKEN : Clock enable for the IO MASTER 1 IFC INTERFACE + value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC2_CLKEN = 2,/*!< IOMSTRIFC2_CLKEN : Clock enable for the IO MASTER 2 IFC INTERFACE + value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC3_CLKEN = 4,/*!< IOMSTRIFC3_CLKEN : Clock enable for the IO MASTER 3 IFC INTERFACE + value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC4_CLKEN = 8,/*!< IOMSTRIFC4_CLKEN : Clock enable for the IO MASTER 4 IFC INTERFACE + value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC5_CLKEN = 16,/*!< IOMSTRIFC5_CLKEN : Clock enable for the IO MASTER 5 IFC INTERFACE + value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_PDM_CLKEN = 32,/*!< PDM_CLKEN : Clock enable for the PDM value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_PDMIFC_CLKEN = 64,/*!< PDMIFC_CLKEN : Clock enable for the PDM INTERFACE value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_PWRCTRL_CLKEN = 128,/*!< PWRCTRL_CLKEN : Clock enable for the PWRCTRL value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_RSTGEN_CLKEN = 256,/*!< RSTGEN_CLKEN : Clock enable for the RSTGEN value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_SCARD_CLKEN = 512,/*!< SCARD_CLKEN : Clock enable for the SCARD value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_SCARD_ALTAPB_CLKEN = 1024,/*!< SCARD_ALTAPB_CLKEN : Clock enable for the SCARD ALTAPB value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_STIMER_CNT_CLKEN = 2048,/*!< STIMER_CNT_CLKEN : Clock enable for the STIMER_CNT_CLKEN value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_TPIU_CLKEN = 4096,/*!< TPIU_CLKEN : Clock enable for the TPIU_CLKEN value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_UART0HF_CLKEN = 8192,/*!< UART0HF_CLKEN : Clock enable for the UART0 HF value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_UART1HF_CLKEN = 16384,/*!< UART1HF_CLKEN : Clock enable for the UART1 HF value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_XT_32KHZ_EN = 1073741824,/*!< XT_32KHZ_EN : Clock enable for the XT 32KHZ value. */ + CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_FORCEHFRC = -2147483648,/*!< FORCEHFRC : HFRC is forced on Status. value. */ +} CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_Enum; + +/* ===================================================== CLOCKEN3STAT ====================================================== */ +/* ======================================= CLKGEN CLOCKEN3STAT CLOCKEN3STAT [0..31] ======================================== */ +typedef enum { /*!< CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT */ + CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_XTAL_enabled = 16777216,/*!< XTAL_enabled : XTAL is enabled value. */ + CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_HFRC_enabled = 33554432,/*!< HFRC_enabled : HFRC is enabled value. */ + CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_HFADJEN = 67108864,/*!< HFADJEN : HFRC Adjust enabled value. */ + CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_HFRC_en_out = 134217728,/*!< HFRC_en_out : HFRC Enabled out value. */ + CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_RTC_XT = 268435456,/*!< RTC_XT : RTC use XT value. */ + CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_clkout_xtal_en = 536870912,/*!< clkout_xtal_en : XTAL clkout enabled value. */ + CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_clkout_hfrc_en = 1073741824,/*!< clkout_hfrc_en : HFRC clkout enabled value. */ + CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_flashclk_en = -2147483648,/*!< flashclk_en : Flash clk is enabled value. */ +} CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_Enum; + +/* ======================================================= FREQCTRL ======================================================== */ +/* ============================================ CLKGEN FREQCTRL BURSTREQ [0..0] ============================================ */ +typedef enum { /*!< CLKGEN_FREQCTRL_BURSTREQ */ + CLKGEN_FREQCTRL_BURSTREQ_DIS = 0, /*!< DIS : Frequency for ARM core stays at 48MHz value. */ + CLKGEN_FREQCTRL_BURSTREQ_EN = 1, /*!< EN : Frequency for ARM core is increased to 96MHz value. */ +} CLKGEN_FREQCTRL_BURSTREQ_Enum; + +/* ===================================================== BLEBUCKTONADJ ===================================================== */ +/* ===================================== CLKGEN BLEBUCKTONADJ ZEROLENDETECTEN [27..27] ===================================== */ +typedef enum { /*!< CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_DIS = 0, /*!< DIS : Disable Zero Length Detect value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_EN = 1, /*!< EN : Enable Zero Length Detect value. */ +} CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_Enum; + +/* ==================================== CLKGEN BLEBUCKTONADJ ZEROLENDETECTTRIM [23..26] ==================================== */ +typedef enum { /*!< CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetF = 15,/*!< SetF : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 81us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetE = 14,/*!< SetE : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 75.6us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetD = 13,/*!< SetD : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 70.2us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetC = 12,/*!< SetC : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 64.8us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetB = 11,/*!< SetB : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 59.4us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetA = 10,/*!< SetA : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 54.0us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set9 = 9,/*!< Set9 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 48.6us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set8 = 8,/*!< Set8 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 43.2us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set7 = 7,/*!< Set7 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 37.8us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set6 = 6,/*!< Set6 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 32.4us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set5 = 5,/*!< Set5 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 27.0us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set4 = 4,/*!< Set4 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 21.6us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set3 = 3,/*!< Set3 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 16.2us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set2 = 2,/*!< Set2 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 10.8us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set1 = 1,/*!< Set1 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 5.4us (10 percent margin of error) or more value. */ + CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set0 = 0,/*!< Set0 : Indicator send when the BLE BUCK asserts blebuck_comp1 + for about 2.0us (10 percent margin of error) or more value. */ +} CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Enum; + +/* ======================================= CLKGEN BLEBUCKTONADJ TONADJUSTEN [22..22] ======================================= */ +typedef enum { /*!< CLKGEN_BLEBUCKTONADJ_TONADJUSTEN */ + CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_DIS = 0, /*!< DIS : Disable Adjust for BLE BUCK TON trim value. */ + CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_EN = 1, /*!< EN : Enable Adjust for BLE BUCK TON trim value. */ +} CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_Enum; + +/* ===================================== CLKGEN BLEBUCKTONADJ TONADJUSTPERIOD [20..21] ===================================== */ +typedef enum { /*!< CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD */ + CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_HFRC_3KHz = 3,/*!< HFRC_3KHz : Adjust done for every 1 3KHz period value. */ + CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_HFRC_12KHz = 2,/*!< HFRC_12KHz : Adjust done for every 1 12KHz period value. */ + CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_HFRC_47KHz = 1,/*!< HFRC_47KHz : Adjust done for every 1 47KHz period value. */ + CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_HFRC_94KHz = 0,/*!< HFRC_94KHz : Adjust done for every 1 94KHz period value. */ +} CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_Enum; + +/* ======================================================= INTRPTEN ======================================================== */ +/* ====================================================== INTRPTSTAT ======================================================= */ +/* ======================================================= INTRPTCLR ======================================================= */ +/* ======================================================= INTRPTSET ======================================================= */ + + +/* =========================================================================================================================== */ +/* ================ CTIMER ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= TMR0 ========================================================== */ +/* ======================================================== CMPRA0 ========================================================= */ +/* ======================================================== CMPRB0 ========================================================= */ +/* ========================================================= CTRL0 ========================================================= */ +/* ============================================= CTIMER CTRL0 CTLINK0 [31..31] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_CTLINK0 */ + CTIMER_CTRL0_CTLINK0_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A0/B0 timers as two independent 16-bit + timers (default). value. */ + CTIMER_CTRL0_CTLINK0_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A0/B0 timers into a single 32-bit timer. + value. */ +} CTIMER_CTRL0_CTLINK0_Enum; + +/* ============================================ CTIMER CTRL0 TMRB0POL [28..28] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRB0POL */ + CTIMER_CTRL0_TMRB0POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB0 pin is the same as the + timer output. value. */ + CTIMER_CTRL0_TMRB0POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB0 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL0_TMRB0POL_Enum; + +/* ============================================ CTIMER CTRL0 TMRB0CLR [27..27] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRB0CLR */ + CTIMER_CTRL0_TMRB0CLR_RUN = 0, /*!< RUN : Allow counter/timer B0 to run value. */ + CTIMER_CTRL0_TMRB0CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B0 at 0x0000. value. */ +} CTIMER_CTRL0_TMRB0CLR_Enum; + +/* ============================================ CTIMER CTRL0 TMRB0IE1 [26..26] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRB0IE1 */ + CTIMER_CTRL0_TMRB0IE1_DIS = 0, /*!< DIS : Disable counter/timer B0 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL0_TMRB0IE1_EN = 1, /*!< EN : Enable counter/timer B0 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL0_TMRB0IE1_Enum; + +/* ============================================ CTIMER CTRL0 TMRB0IE0 [25..25] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRB0IE0 */ + CTIMER_CTRL0_TMRB0IE0_DIS = 0, /*!< DIS : Disable counter/timer B0 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL0_TMRB0IE0_EN = 1, /*!< EN : Enable counter/timer B0 to generate an interrupt based + on COMPR0 value. */ +} CTIMER_CTRL0_TMRB0IE0_Enum; + +/* ============================================= CTIMER CTRL0 TMRB0FN [22..24] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRB0FN */ + CTIMER_CTRL0_TMRB0FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0B0, stop. value. */ + CTIMER_CTRL0_TMRB0FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0B0, restart. value. */ + CTIMER_CTRL0_TMRB0FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B0, assert, + count to CMPR1B0, deassert, stop. value. */ + CTIMER_CTRL0_TMRB0FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B0, assert, count + to CMPR1B0, deassert, restart. value. */ + CTIMER_CTRL0_TMRB0FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL0_TMRB0FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL0_TMRB0FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL0_TMRB0FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL0_TMRB0FN_Enum; + +/* ============================================ CTIMER CTRL0 TMRB0CLK [17..21] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRB0CLK */ + CTIMER_CTRL0_TMRB0CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ + CTIMER_CTRL0_TMRB0CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL0_TMRB0CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL0_TMRB0CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL0_TMRB0CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL0_TMRB0CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL0_TMRB0CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL0_TMRB0CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL0_TMRB0CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL0_TMRB0CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL0_TMRB0CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL0_TMRB0CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL0_TMRB0CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL0_TMRB0CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL0_TMRB0CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL0_TMRB0CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL0_TMRB0CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL0_TMRB0CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL0_TMRB0CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL0_TMRB0CLK_CTMRA0 = 20, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ + CTIMER_CTRL0_TMRB0CLK_CTMRB1 = 21, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL0_TMRB0CLK_CTMRA1 = 22, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ + CTIMER_CTRL0_TMRB0CLK_CTMRA2 = 23, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ + CTIMER_CTRL0_TMRB0CLK_CTMRB2 = 24, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL0_TMRB0CLK_CTMRB3 = 25, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL0_TMRB0CLK_CTMRB4 = 26, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL0_TMRB0CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL0_TMRB0CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL0_TMRB0CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL0_TMRB0CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL0_TMRB0CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL0_TMRB0CLK_Enum; + +/* ============================================= CTIMER CTRL0 TMRB0EN [16..16] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRB0EN */ + CTIMER_CTRL0_TMRB0EN_DIS = 0, /*!< DIS : Counter/Timer B0 Disable. value. */ + CTIMER_CTRL0_TMRB0EN_EN = 1, /*!< EN : Counter/Timer B0 Enable. value. */ +} CTIMER_CTRL0_TMRB0EN_Enum; + +/* ============================================ CTIMER CTRL0 TMRA0POL [12..12] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRA0POL */ + CTIMER_CTRL0_TMRA0POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA0 pin is the same as the + timer output. value. */ + CTIMER_CTRL0_TMRA0POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA0 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL0_TMRA0POL_Enum; + +/* ============================================ CTIMER CTRL0 TMRA0CLR [11..11] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRA0CLR */ + CTIMER_CTRL0_TMRA0CLR_RUN = 0, /*!< RUN : Allow counter/timer A0 to run value. */ + CTIMER_CTRL0_TMRA0CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A0 at 0x0000. value. */ +} CTIMER_CTRL0_TMRA0CLR_Enum; + +/* ============================================ CTIMER CTRL0 TMRA0IE1 [10..10] ============================================= */ +typedef enum { /*!< CTIMER_CTRL0_TMRA0IE1 */ + CTIMER_CTRL0_TMRA0IE1_DIS = 0, /*!< DIS : Disable counter/timer A0 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL0_TMRA0IE1_EN = 1, /*!< EN : Enable counter/timer A0 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL0_TMRA0IE1_Enum; + +/* ============================================= CTIMER CTRL0 TMRA0IE0 [9..9] ============================================== */ +typedef enum { /*!< CTIMER_CTRL0_TMRA0IE0 */ + CTIMER_CTRL0_TMRA0IE0_DIS = 0, /*!< DIS : Disable counter/timer A0 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL0_TMRA0IE0_EN = 1, /*!< EN : Enable counter/timer A0 to generate an interrupt based + on COMPR0. value. */ +} CTIMER_CTRL0_TMRA0IE0_Enum; + +/* ============================================== CTIMER CTRL0 TMRA0FN [6..8] ============================================== */ +typedef enum { /*!< CTIMER_CTRL0_TMRA0FN */ + CTIMER_CTRL0_TMRA0FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0A0, stop. value. */ + CTIMER_CTRL0_TMRA0FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0A0, restart. value. */ + CTIMER_CTRL0_TMRA0FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A0, assert, + count to CMPR1A0, deassert, stop. value. */ + CTIMER_CTRL0_TMRA0FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A0, assert, count + to CMPR1A0, deassert, restart. value. */ + CTIMER_CTRL0_TMRA0FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL0_TMRA0FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL0_TMRA0FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL0_TMRA0FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL0_TMRA0FN_Enum; + +/* ============================================= CTIMER CTRL0 TMRA0CLK [1..5] ============================================== */ +typedef enum { /*!< CTIMER_CTRL0_TMRA0CLK */ + CTIMER_CTRL0_TMRA0CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ + CTIMER_CTRL0_TMRA0CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL0_TMRA0CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL0_TMRA0CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL0_TMRA0CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL0_TMRA0CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL0_TMRA0CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL0_TMRA0CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL0_TMRA0CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL0_TMRA0CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL0_TMRA0CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL0_TMRA0CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL0_TMRA0CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL0_TMRA0CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL0_TMRA0CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL0_TMRA0CLK_HCLK_DIV4 = 15, /*!< HCLK_DIV4 : Clock source is HCLK / 4. value. */ + CTIMER_CTRL0_TMRA0CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL0_TMRA0CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL0_TMRA0CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL0_TMRA0CLK_CTMRB0 = 20, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL0_TMRA0CLK_CTMRA1 = 21, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ + CTIMER_CTRL0_TMRA0CLK_CTMRB1 = 22, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL0_TMRA0CLK_CTMRA2 = 23, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ + CTIMER_CTRL0_TMRA0CLK_CTMRB2 = 24, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL0_TMRA0CLK_CTMRB3 = 25, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL0_TMRA0CLK_CTMRB4 = 26, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL0_TMRA0CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL0_TMRA0CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL0_TMRA0CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL0_TMRA0CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL0_TMRA0CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL0_TMRA0CLK_Enum; + +/* ============================================== CTIMER CTRL0 TMRA0EN [0..0] ============================================== */ +typedef enum { /*!< CTIMER_CTRL0_TMRA0EN */ + CTIMER_CTRL0_TMRA0EN_DIS = 0, /*!< DIS : Counter/Timer A0 Disable. value. */ + CTIMER_CTRL0_TMRA0EN_EN = 1, /*!< EN : Counter/Timer A0 Enable. value. */ +} CTIMER_CTRL0_TMRA0EN_Enum; + +/* ======================================================= CMPRAUXA0 ======================================================= */ +/* ======================================================= CMPRAUXB0 ======================================================= */ +/* ========================================================= AUX0 ========================================================== */ +/* ============================================ CTIMER AUX0 TMRB0EN23 [30..30] ============================================= */ +typedef enum { /*!< CTIMER_AUX0_TMRB0EN23 */ + CTIMER_AUX0_TMRB0EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX0_TMRB0EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX0_TMRB0EN23_Enum; + +/* ============================================ CTIMER AUX0 TMRB0POL23 [29..29] ============================================ */ +typedef enum { /*!< CTIMER_AUX0_TMRB0POL23 */ + CTIMER_AUX0_TMRB0POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX0_TMRB0POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX0_TMRB0POL23_Enum; + +/* ============================================ CTIMER AUX0 TMRB0TINV [28..28] ============================================= */ +typedef enum { /*!< CTIMER_AUX0_TMRB0TINV */ + CTIMER_AUX0_TMRB0TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX0_TMRB0TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX0_TMRB0TINV_Enum; + +/* =========================================== CTIMER AUX0 TMRB0NOSYNC [27..27] ============================================ */ +typedef enum { /*!< CTIMER_AUX0_TMRB0NOSYNC */ + CTIMER_AUX0_TMRB0NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX0_TMRB0NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX0_TMRB0NOSYNC_Enum; + +/* ============================================ CTIMER AUX0 TMRB0TRIG [23..26] ============================================= */ +typedef enum { /*!< CTIMER_AUX0_TMRB0TRIG */ + CTIMER_AUX0_TMRB0TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX0_TMRB0TRIG_A0OUT = 1, /*!< A0OUT : Trigger source is CTIMERA0 OUT. value. */ + CTIMER_AUX0_TMRB0TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX0_TMRB0TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX0_TMRB0TRIG_B2OUT = 4, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ + CTIMER_AUX0_TMRB0TRIG_B5OUT = 5, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ + CTIMER_AUX0_TMRB0TRIG_A4OUT = 6, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ + CTIMER_AUX0_TMRB0TRIG_B4OUT = 7, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ + CTIMER_AUX0_TMRB0TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX0_TMRB0TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX0_TMRB0TRIG_B7OUT2 = 10, /*!< B7OUT2 : Trigger source is CTIMERB7 OUT2. value. */ + CTIMER_AUX0_TMRB0TRIG_A2OUT2 = 11, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ + CTIMER_AUX0_TMRB0TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX0_TMRB0TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX0_TMRB0TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ + CTIMER_AUX0_TMRB0TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ +} CTIMER_AUX0_TMRB0TRIG_Enum; + +/* ============================================ CTIMER AUX0 TMRA0EN23 [14..14] ============================================= */ +typedef enum { /*!< CTIMER_AUX0_TMRA0EN23 */ + CTIMER_AUX0_TMRA0EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX0_TMRA0EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX0_TMRA0EN23_Enum; + +/* ============================================ CTIMER AUX0 TMRA0POL23 [13..13] ============================================ */ +typedef enum { /*!< CTIMER_AUX0_TMRA0POL23 */ + CTIMER_AUX0_TMRA0POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX0_TMRA0POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX0_TMRA0POL23_Enum; + +/* ============================================ CTIMER AUX0 TMRA0TINV [12..12] ============================================= */ +typedef enum { /*!< CTIMER_AUX0_TMRA0TINV */ + CTIMER_AUX0_TMRA0TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX0_TMRA0TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX0_TMRA0TINV_Enum; + +/* =========================================== CTIMER AUX0 TMRA0NOSYNC [11..11] ============================================ */ +typedef enum { /*!< CTIMER_AUX0_TMRA0NOSYNC */ + CTIMER_AUX0_TMRA0NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX0_TMRA0NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX0_TMRA0NOSYNC_Enum; + +/* ============================================= CTIMER AUX0 TMRA0TRIG [7..10] ============================================= */ +typedef enum { /*!< CTIMER_AUX0_TMRA0TRIG */ + CTIMER_AUX0_TMRA0TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX0_TMRA0TRIG_B0OUT = 1, /*!< B0OUT : Trigger source is CTIMERB0 OUT. value. */ + CTIMER_AUX0_TMRA0TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX0_TMRA0TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX0_TMRA0TRIG_A1OUT = 4, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ + CTIMER_AUX0_TMRA0TRIG_B1OUT = 5, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ + CTIMER_AUX0_TMRA0TRIG_A5OUT = 6, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ + CTIMER_AUX0_TMRA0TRIG_B5OUT = 7, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ + CTIMER_AUX0_TMRA0TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX0_TMRA0TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX0_TMRA0TRIG_B6OUT2 = 10, /*!< B6OUT2 : Trigger source is CTIMERB6 OUT2. value. */ + CTIMER_AUX0_TMRA0TRIG_A2OUT2 = 11, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ + CTIMER_AUX0_TMRA0TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX0_TMRA0TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX0_TMRA0TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ + CTIMER_AUX0_TMRA0TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ +} CTIMER_AUX0_TMRA0TRIG_Enum; + +/* ========================================================= TMR1 ========================================================== */ +/* ======================================================== CMPRA1 ========================================================= */ +/* ======================================================== CMPRB1 ========================================================= */ +/* ========================================================= CTRL1 ========================================================= */ +/* ============================================= CTIMER CTRL1 CTLINK1 [31..31] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_CTLINK1 */ + CTIMER_CTRL1_CTLINK1_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A1/B1 timers as two independent 16-bit + timers (default). value. */ + CTIMER_CTRL1_CTLINK1_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A1/B1 timers into a single 32-bit timer. + value. */ +} CTIMER_CTRL1_CTLINK1_Enum; + +/* ============================================ CTIMER CTRL1 TMRB1POL [28..28] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRB1POL */ + CTIMER_CTRL1_TMRB1POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB1 pin is the same as the + timer output. value. */ + CTIMER_CTRL1_TMRB1POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB1 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL1_TMRB1POL_Enum; + +/* ============================================ CTIMER CTRL1 TMRB1CLR [27..27] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRB1CLR */ + CTIMER_CTRL1_TMRB1CLR_RUN = 0, /*!< RUN : Allow counter/timer B1 to run value. */ + CTIMER_CTRL1_TMRB1CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B1 at 0x0000. value. */ +} CTIMER_CTRL1_TMRB1CLR_Enum; + +/* ============================================ CTIMER CTRL1 TMRB1IE1 [26..26] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRB1IE1 */ + CTIMER_CTRL1_TMRB1IE1_DIS = 0, /*!< DIS : Disable counter/timer B1 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL1_TMRB1IE1_EN = 1, /*!< EN : Enable counter/timer B1 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL1_TMRB1IE1_Enum; + +/* ============================================ CTIMER CTRL1 TMRB1IE0 [25..25] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRB1IE0 */ + CTIMER_CTRL1_TMRB1IE0_DIS = 0, /*!< DIS : Disable counter/timer B1 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL1_TMRB1IE0_EN = 1, /*!< EN : Enable counter/timer B1 to generate an interrupt based + on COMPR0 value. */ +} CTIMER_CTRL1_TMRB1IE0_Enum; + +/* ============================================= CTIMER CTRL1 TMRB1FN [22..24] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRB1FN */ + CTIMER_CTRL1_TMRB1FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0B1, stop. value. */ + CTIMER_CTRL1_TMRB1FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0B1, restart. value. */ + CTIMER_CTRL1_TMRB1FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B1, assert, + count to CMPR1B1, deassert, stop. value. */ + CTIMER_CTRL1_TMRB1FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B1, assert, count + to CMPR1B1, deassert, restart. value. */ + CTIMER_CTRL1_TMRB1FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL1_TMRB1FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL1_TMRB1FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL1_TMRB1FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL1_TMRB1FN_Enum; + +/* ============================================ CTIMER CTRL1 TMRB1CLK [17..21] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRB1CLK */ + CTIMER_CTRL1_TMRB1CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ + CTIMER_CTRL1_TMRB1CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL1_TMRB1CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL1_TMRB1CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL1_TMRB1CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL1_TMRB1CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL1_TMRB1CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL1_TMRB1CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL1_TMRB1CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL1_TMRB1CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL1_TMRB1CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL1_TMRB1CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL1_TMRB1CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL1_TMRB1CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL1_TMRB1CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL1_TMRB1CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL1_TMRB1CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL1_TMRB1CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL1_TMRB1CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL1_TMRB1CLK_CTMRA1 = 20, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ + CTIMER_CTRL1_TMRB1CLK_CTMRA0 = 21, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ + CTIMER_CTRL1_TMRB1CLK_CTMRB0 = 22, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL1_TMRB1CLK_CTMRA2 = 23, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ + CTIMER_CTRL1_TMRB1CLK_CTMRB2 = 24, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL1_TMRB1CLK_CTMRB3 = 25, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL1_TMRB1CLK_CTMRB4 = 26, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL1_TMRB1CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL1_TMRB1CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL1_TMRB1CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL1_TMRB1CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL1_TMRB1CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL1_TMRB1CLK_Enum; + +/* ============================================= CTIMER CTRL1 TMRB1EN [16..16] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRB1EN */ + CTIMER_CTRL1_TMRB1EN_DIS = 0, /*!< DIS : Counter/Timer B1 Disable. value. */ + CTIMER_CTRL1_TMRB1EN_EN = 1, /*!< EN : Counter/Timer B1 Enable. value. */ +} CTIMER_CTRL1_TMRB1EN_Enum; + +/* ============================================ CTIMER CTRL1 TMRA1POL [12..12] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRA1POL */ + CTIMER_CTRL1_TMRA1POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA1 pin is the same as the + timer output. value. */ + CTIMER_CTRL1_TMRA1POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA1 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL1_TMRA1POL_Enum; + +/* ============================================ CTIMER CTRL1 TMRA1CLR [11..11] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRA1CLR */ + CTIMER_CTRL1_TMRA1CLR_RUN = 0, /*!< RUN : Allow counter/timer A1 to run value. */ + CTIMER_CTRL1_TMRA1CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A1 at 0x0000. value. */ +} CTIMER_CTRL1_TMRA1CLR_Enum; + +/* ============================================ CTIMER CTRL1 TMRA1IE1 [10..10] ============================================= */ +typedef enum { /*!< CTIMER_CTRL1_TMRA1IE1 */ + CTIMER_CTRL1_TMRA1IE1_DIS = 0, /*!< DIS : Disable counter/timer A1 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL1_TMRA1IE1_EN = 1, /*!< EN : Enable counter/timer A1 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL1_TMRA1IE1_Enum; + +/* ============================================= CTIMER CTRL1 TMRA1IE0 [9..9] ============================================== */ +typedef enum { /*!< CTIMER_CTRL1_TMRA1IE0 */ + CTIMER_CTRL1_TMRA1IE0_DIS = 0, /*!< DIS : Disable counter/timer A1 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL1_TMRA1IE0_EN = 1, /*!< EN : Enable counter/timer A1 to generate an interrupt based + on COMPR0. value. */ +} CTIMER_CTRL1_TMRA1IE0_Enum; + +/* ============================================== CTIMER CTRL1 TMRA1FN [6..8] ============================================== */ +typedef enum { /*!< CTIMER_CTRL1_TMRA1FN */ + CTIMER_CTRL1_TMRA1FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0A1, stop. value. */ + CTIMER_CTRL1_TMRA1FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0A1, restart. value. */ + CTIMER_CTRL1_TMRA1FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A1, assert, + count to CMPR1A1, deassert, stop. value. */ + CTIMER_CTRL1_TMRA1FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A1, assert, count + to CMPR1A1, deassert, restart. value. */ + CTIMER_CTRL1_TMRA1FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL1_TMRA1FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL1_TMRA1FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL1_TMRA1FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL1_TMRA1FN_Enum; + +/* ============================================= CTIMER CTRL1 TMRA1CLK [1..5] ============================================== */ +typedef enum { /*!< CTIMER_CTRL1_TMRA1CLK */ + CTIMER_CTRL1_TMRA1CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ + CTIMER_CTRL1_TMRA1CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL1_TMRA1CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL1_TMRA1CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL1_TMRA1CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL1_TMRA1CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL1_TMRA1CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL1_TMRA1CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL1_TMRA1CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL1_TMRA1CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL1_TMRA1CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL1_TMRA1CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL1_TMRA1CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL1_TMRA1CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL1_TMRA1CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL1_TMRA1CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL1_TMRA1CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL1_TMRA1CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL1_TMRA1CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL1_TMRA1CLK_CTMRB1 = 20, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL1_TMRA1CLK_CTMRA0 = 21, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ + CTIMER_CTRL1_TMRA1CLK_CTMRB0 = 22, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL1_TMRA1CLK_CTMRA2 = 23, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ + CTIMER_CTRL1_TMRA1CLK_CTMRB2 = 24, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL1_TMRA1CLK_CTMRB3 = 25, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL1_TMRA1CLK_CTMRB4 = 26, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL1_TMRA1CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL1_TMRA1CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL1_TMRA1CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL1_TMRA1CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL1_TMRA1CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL1_TMRA1CLK_Enum; + +/* ============================================== CTIMER CTRL1 TMRA1EN [0..0] ============================================== */ +typedef enum { /*!< CTIMER_CTRL1_TMRA1EN */ + CTIMER_CTRL1_TMRA1EN_DIS = 0, /*!< DIS : Counter/Timer A1 Disable. value. */ + CTIMER_CTRL1_TMRA1EN_EN = 1, /*!< EN : Counter/Timer A1 Enable. value. */ +} CTIMER_CTRL1_TMRA1EN_Enum; + +/* ======================================================= CMPRAUXA1 ======================================================= */ +/* ======================================================= CMPRAUXB1 ======================================================= */ +/* ========================================================= AUX1 ========================================================== */ +/* ============================================ CTIMER AUX1 TMRB1EN23 [30..30] ============================================= */ +typedef enum { /*!< CTIMER_AUX1_TMRB1EN23 */ + CTIMER_AUX1_TMRB1EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX1_TMRB1EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX1_TMRB1EN23_Enum; + +/* ============================================ CTIMER AUX1 TMRB1POL23 [29..29] ============================================ */ +typedef enum { /*!< CTIMER_AUX1_TMRB1POL23 */ + CTIMER_AUX1_TMRB1POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX1_TMRB1POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX1_TMRB1POL23_Enum; + +/* ============================================ CTIMER AUX1 TMRB1TINV [28..28] ============================================= */ +typedef enum { /*!< CTIMER_AUX1_TMRB1TINV */ + CTIMER_AUX1_TMRB1TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX1_TMRB1TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX1_TMRB1TINV_Enum; + +/* =========================================== CTIMER AUX1 TMRB1NOSYNC [27..27] ============================================ */ +typedef enum { /*!< CTIMER_AUX1_TMRB1NOSYNC */ + CTIMER_AUX1_TMRB1NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX1_TMRB1NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX1_TMRB1NOSYNC_Enum; + +/* ============================================ CTIMER AUX1 TMRB1TRIG [23..26] ============================================= */ +typedef enum { /*!< CTIMER_AUX1_TMRB1TRIG */ + CTIMER_AUX1_TMRB1TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX1_TMRB1TRIG_A1OUT = 1, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ + CTIMER_AUX1_TMRB1TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX1_TMRB1TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX1_TMRB1TRIG_A6OUT = 4, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ + CTIMER_AUX1_TMRB1TRIG_B6OUT = 5, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ + CTIMER_AUX1_TMRB1TRIG_A0OUT = 6, /*!< A0OUT : Trigger source is CTIMERA0 OUT. value. */ + CTIMER_AUX1_TMRB1TRIG_B0OUT = 7, /*!< B0OUT : Trigger source is CTIMERB0 OUT. value. */ + CTIMER_AUX1_TMRB1TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX1_TMRB1TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX1_TMRB1TRIG_A4OUT2 = 10, /*!< A4OUT2 : Trigger source is CTIMERA4 OUT2. value. */ + CTIMER_AUX1_TMRB1TRIG_B4OUT2 = 11, /*!< B4OUT2 : Trigger source is CTIMERB4 OUT2. value. */ + CTIMER_AUX1_TMRB1TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX1_TMRB1TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX1_TMRB1TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ + CTIMER_AUX1_TMRB1TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ +} CTIMER_AUX1_TMRB1TRIG_Enum; + +/* ============================================ CTIMER AUX1 TMRA1EN23 [14..14] ============================================= */ +typedef enum { /*!< CTIMER_AUX1_TMRA1EN23 */ + CTIMER_AUX1_TMRA1EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX1_TMRA1EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX1_TMRA1EN23_Enum; + +/* ============================================ CTIMER AUX1 TMRA1POL23 [13..13] ============================================ */ +typedef enum { /*!< CTIMER_AUX1_TMRA1POL23 */ + CTIMER_AUX1_TMRA1POL23_NORMAL = 0, /*!< NORMAL : Upper output normal polarity value. */ + CTIMER_AUX1_TMRA1POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX1_TMRA1POL23_Enum; + +/* ============================================ CTIMER AUX1 TMRA1TINV [12..12] ============================================= */ +typedef enum { /*!< CTIMER_AUX1_TMRA1TINV */ + CTIMER_AUX1_TMRA1TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX1_TMRA1TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX1_TMRA1TINV_Enum; + +/* =========================================== CTIMER AUX1 TMRA1NOSYNC [11..11] ============================================ */ +typedef enum { /*!< CTIMER_AUX1_TMRA1NOSYNC */ + CTIMER_AUX1_TMRA1NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX1_TMRA1NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX1_TMRA1NOSYNC_Enum; + +/* ============================================= CTIMER AUX1 TMRA1TRIG [7..10] ============================================= */ +typedef enum { /*!< CTIMER_AUX1_TMRA1TRIG */ + CTIMER_AUX1_TMRA1TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX1_TMRA1TRIG_B1OUT = 1, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ + CTIMER_AUX1_TMRA1TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX1_TMRA1TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX1_TMRA1TRIG_A0OUT = 4, /*!< A0OUT : Trigger source is CTIMERA0 OUT. value. */ + CTIMER_AUX1_TMRA1TRIG_B0OUT = 5, /*!< B0OUT : Trigger source is CTIMERB0 OUT. value. */ + CTIMER_AUX1_TMRA1TRIG_A5OUT = 6, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ + CTIMER_AUX1_TMRA1TRIG_B5OUT = 7, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ + CTIMER_AUX1_TMRA1TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX1_TMRA1TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX1_TMRA1TRIG_A4OUT2 = 10, /*!< A4OUT2 : Trigger source is CTIMERA4 OUT2. value. */ + CTIMER_AUX1_TMRA1TRIG_B4OUT2 = 11, /*!< B4OUT2 : Trigger source is CTIMERB4 OUT2. value. */ + CTIMER_AUX1_TMRA1TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX1_TMRA1TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX1_TMRA1TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ + CTIMER_AUX1_TMRA1TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ +} CTIMER_AUX1_TMRA1TRIG_Enum; + +/* ========================================================= TMR2 ========================================================== */ +/* ======================================================== CMPRA2 ========================================================= */ +/* ======================================================== CMPRB2 ========================================================= */ +/* ========================================================= CTRL2 ========================================================= */ +/* ============================================= CTIMER CTRL2 CTLINK2 [31..31] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_CTLINK2 */ + CTIMER_CTRL2_CTLINK2_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A2/B2 timers as two independent 16-bit + timers (default). value. */ + CTIMER_CTRL2_CTLINK2_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A2/B2 timers into a single 32-bit timer. + value. */ +} CTIMER_CTRL2_CTLINK2_Enum; + +/* ============================================ CTIMER CTRL2 TMRB2POL [28..28] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRB2POL */ + CTIMER_CTRL2_TMRB2POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB2 pin is the same as the + timer output. value. */ + CTIMER_CTRL2_TMRB2POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB2 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL2_TMRB2POL_Enum; + +/* ============================================ CTIMER CTRL2 TMRB2CLR [27..27] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRB2CLR */ + CTIMER_CTRL2_TMRB2CLR_RUN = 0, /*!< RUN : Allow counter/timer B2 to run value. */ + CTIMER_CTRL2_TMRB2CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B2 at 0x0000. value. */ +} CTIMER_CTRL2_TMRB2CLR_Enum; + +/* ============================================ CTIMER CTRL2 TMRB2IE1 [26..26] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRB2IE1 */ + CTIMER_CTRL2_TMRB2IE1_DIS = 0, /*!< DIS : Disable counter/timer B2 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL2_TMRB2IE1_EN = 1, /*!< EN : Enable counter/timer B2 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL2_TMRB2IE1_Enum; + +/* ============================================ CTIMER CTRL2 TMRB2IE0 [25..25] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRB2IE0 */ + CTIMER_CTRL2_TMRB2IE0_DIS = 0, /*!< DIS : Disable counter/timer B2 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL2_TMRB2IE0_EN = 1, /*!< EN : Enable counter/timer B2 to generate an interrupt based + on COMPR0 value. */ +} CTIMER_CTRL2_TMRB2IE0_Enum; + +/* ============================================= CTIMER CTRL2 TMRB2FN [22..24] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRB2FN */ + CTIMER_CTRL2_TMRB2FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0B2, stop. value. */ + CTIMER_CTRL2_TMRB2FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0B2, restart. value. */ + CTIMER_CTRL2_TMRB2FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B2, assert, + count to CMPR1B2, deassert, stop. value. */ + CTIMER_CTRL2_TMRB2FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B2, assert, count + to CMPR1B2, deassert, restart. value. */ + CTIMER_CTRL2_TMRB2FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL2_TMRB2FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL2_TMRB2FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL2_TMRB2FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL2_TMRB2FN_Enum; + +/* ============================================ CTIMER CTRL2 TMRB2CLK [17..21] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRB2CLK */ + CTIMER_CTRL2_TMRB2CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ + CTIMER_CTRL2_TMRB2CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL2_TMRB2CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL2_TMRB2CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL2_TMRB2CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL2_TMRB2CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL2_TMRB2CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL2_TMRB2CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL2_TMRB2CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL2_TMRB2CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL2_TMRB2CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL2_TMRB2CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL2_TMRB2CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL2_TMRB2CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL2_TMRB2CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL2_TMRB2CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL2_TMRB2CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL2_TMRB2CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL2_TMRB2CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL2_TMRB2CLK_CTMRA2 = 20, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ + CTIMER_CTRL2_TMRB2CLK_CTMRB3 = 21, /*!< CTMRB3 : Clock source is CTIMERA3 OUT. value. */ + CTIMER_CTRL2_TMRB2CLK_CTMRA3 = 22, /*!< CTMRA3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL2_TMRB2CLK_CTMRA4 = 23, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ + CTIMER_CTRL2_TMRB2CLK_CTMRB4 = 24, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL2_TMRB2CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL2_TMRB2CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL2_TMRB2CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL2_TMRB2CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL2_TMRB2CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL2_TMRB2CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL2_TMRB2CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL2_TMRB2CLK_Enum; + +/* ============================================= CTIMER CTRL2 TMRB2EN [16..16] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRB2EN */ + CTIMER_CTRL2_TMRB2EN_DIS = 0, /*!< DIS : Counter/Timer B2 Disable. value. */ + CTIMER_CTRL2_TMRB2EN_EN = 1, /*!< EN : Counter/Timer B2 Enable. value. */ +} CTIMER_CTRL2_TMRB2EN_Enum; + +/* ============================================ CTIMER CTRL2 TMRA2POL [12..12] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRA2POL */ + CTIMER_CTRL2_TMRA2POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA2 pin is the same as the + timer output. value. */ + CTIMER_CTRL2_TMRA2POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA2 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL2_TMRA2POL_Enum; + +/* ============================================ CTIMER CTRL2 TMRA2CLR [11..11] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRA2CLR */ + CTIMER_CTRL2_TMRA2CLR_RUN = 0, /*!< RUN : Allow counter/timer A2 to run value. */ + CTIMER_CTRL2_TMRA2CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A2 at 0x0000. value. */ +} CTIMER_CTRL2_TMRA2CLR_Enum; + +/* ============================================ CTIMER CTRL2 TMRA2IE1 [10..10] ============================================= */ +typedef enum { /*!< CTIMER_CTRL2_TMRA2IE1 */ + CTIMER_CTRL2_TMRA2IE1_DIS = 0, /*!< DIS : Disable counter/timer A2 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL2_TMRA2IE1_EN = 1, /*!< EN : Enable counter/timer A2 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL2_TMRA2IE1_Enum; + +/* ============================================= CTIMER CTRL2 TMRA2IE0 [9..9] ============================================== */ +typedef enum { /*!< CTIMER_CTRL2_TMRA2IE0 */ + CTIMER_CTRL2_TMRA2IE0_DIS = 0, /*!< DIS : Disable counter/timer A2 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL2_TMRA2IE0_EN = 1, /*!< EN : Enable counter/timer A2 to generate an interrupt based + on COMPR0. value. */ +} CTIMER_CTRL2_TMRA2IE0_Enum; + +/* ============================================== CTIMER CTRL2 TMRA2FN [6..8] ============================================== */ +typedef enum { /*!< CTIMER_CTRL2_TMRA2FN */ + CTIMER_CTRL2_TMRA2FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0A2, stop. value. */ + CTIMER_CTRL2_TMRA2FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0A2, restart. value. */ + CTIMER_CTRL2_TMRA2FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A2, assert, + count to CMPR1A2, deassert, stop. value. */ + CTIMER_CTRL2_TMRA2FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A2, assert, count + to CMPR1A2, deassert, restart. value. */ + CTIMER_CTRL2_TMRA2FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL2_TMRA2FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL2_TMRA2FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL2_TMRA2FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL2_TMRA2FN_Enum; + +/* ============================================= CTIMER CTRL2 TMRA2CLK [1..5] ============================================== */ +typedef enum { /*!< CTIMER_CTRL2_TMRA2CLK */ + CTIMER_CTRL2_TMRA2CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ + CTIMER_CTRL2_TMRA2CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL2_TMRA2CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL2_TMRA2CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL2_TMRA2CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL2_TMRA2CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL2_TMRA2CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL2_TMRA2CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL2_TMRA2CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL2_TMRA2CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL2_TMRA2CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL2_TMRA2CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL2_TMRA2CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL2_TMRA2CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL2_TMRA2CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL2_TMRA2CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL2_TMRA2CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL2_TMRA2CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL2_TMRA2CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL2_TMRA2CLK_CTMRB2 = 20, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL2_TMRA2CLK_CTMRB3 = 21, /*!< CTMRB3 : Clock source is CTIMERA3 OUT. value. */ + CTIMER_CTRL2_TMRA2CLK_CTMRA3 = 22, /*!< CTMRA3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL2_TMRA2CLK_CTMRA4 = 23, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ + CTIMER_CTRL2_TMRA2CLK_CTMRB4 = 24, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL2_TMRA2CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL2_TMRA2CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL2_TMRA2CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL2_TMRA2CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL2_TMRA2CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL2_TMRA2CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL2_TMRA2CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL2_TMRA2CLK_Enum; + +/* ============================================== CTIMER CTRL2 TMRA2EN [0..0] ============================================== */ +typedef enum { /*!< CTIMER_CTRL2_TMRA2EN */ + CTIMER_CTRL2_TMRA2EN_DIS = 0, /*!< DIS : Counter/Timer A2 Disable. value. */ + CTIMER_CTRL2_TMRA2EN_EN = 1, /*!< EN : Counter/Timer A2 Enable. value. */ +} CTIMER_CTRL2_TMRA2EN_Enum; + +/* ======================================================= CMPRAUXA2 ======================================================= */ +/* ======================================================= CMPRAUXB2 ======================================================= */ +/* ========================================================= AUX2 ========================================================== */ +/* ============================================ CTIMER AUX2 TMRB2EN23 [30..30] ============================================= */ +typedef enum { /*!< CTIMER_AUX2_TMRB2EN23 */ + CTIMER_AUX2_TMRB2EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX2_TMRB2EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX2_TMRB2EN23_Enum; + +/* ============================================ CTIMER AUX2 TMRB2POL23 [29..29] ============================================ */ +typedef enum { /*!< CTIMER_AUX2_TMRB2POL23 */ + CTIMER_AUX2_TMRB2POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX2_TMRB2POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX2_TMRB2POL23_Enum; + +/* ============================================ CTIMER AUX2 TMRB2TINV [28..28] ============================================= */ +typedef enum { /*!< CTIMER_AUX2_TMRB2TINV */ + CTIMER_AUX2_TMRB2TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX2_TMRB2TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX2_TMRB2TINV_Enum; + +/* =========================================== CTIMER AUX2 TMRB2NOSYNC [27..27] ============================================ */ +typedef enum { /*!< CTIMER_AUX2_TMRB2NOSYNC */ + CTIMER_AUX2_TMRB2NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX2_TMRB2NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX2_TMRB2NOSYNC_Enum; + +/* ============================================ CTIMER AUX2 TMRB2TRIG [23..26] ============================================= */ +typedef enum { /*!< CTIMER_AUX2_TMRB2TRIG */ + CTIMER_AUX2_TMRB2TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX2_TMRB2TRIG_A2OUT = 1, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ + CTIMER_AUX2_TMRB2TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX2_TMRB2TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX2_TMRB2TRIG_A1OUT = 4, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ + CTIMER_AUX2_TMRB2TRIG_B1OUT = 5, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ + CTIMER_AUX2_TMRB2TRIG_A4OUT = 6, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ + CTIMER_AUX2_TMRB2TRIG_B4OUT = 7, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ + CTIMER_AUX2_TMRB2TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX2_TMRB2TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX2_TMRB2TRIG_A5OUT2 = 10, /*!< A5OUT2 : Trigger source is CTIMERA5 OUT2. value. */ + CTIMER_AUX2_TMRB2TRIG_B5OUT2 = 11, /*!< B5OUT2 : Trigger source is CTIMERB5 OUT2. value. */ + CTIMER_AUX2_TMRB2TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX2_TMRB2TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX2_TMRB2TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ + CTIMER_AUX2_TMRB2TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ +} CTIMER_AUX2_TMRB2TRIG_Enum; + +/* ============================================ CTIMER AUX2 TMRA2EN23 [14..14] ============================================= */ +typedef enum { /*!< CTIMER_AUX2_TMRA2EN23 */ + CTIMER_AUX2_TMRA2EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX2_TMRA2EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX2_TMRA2EN23_Enum; + +/* ============================================ CTIMER AUX2 TMRA2POL23 [13..13] ============================================ */ +typedef enum { /*!< CTIMER_AUX2_TMRA2POL23 */ + CTIMER_AUX2_TMRA2POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX2_TMRA2POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX2_TMRA2POL23_Enum; + +/* ============================================ CTIMER AUX2 TMRA2TINV [12..12] ============================================= */ +typedef enum { /*!< CTIMER_AUX2_TMRA2TINV */ + CTIMER_AUX2_TMRA2TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX2_TMRA2TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX2_TMRA2TINV_Enum; + +/* =========================================== CTIMER AUX2 TMRA2NOSYNC [11..11] ============================================ */ +typedef enum { /*!< CTIMER_AUX2_TMRA2NOSYNC */ + CTIMER_AUX2_TMRA2NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX2_TMRA2NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX2_TMRA2NOSYNC_Enum; + +/* ============================================= CTIMER AUX2 TMRA2TRIG [7..10] ============================================= */ +typedef enum { /*!< CTIMER_AUX2_TMRA2TRIG */ + CTIMER_AUX2_TMRA2TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX2_TMRA2TRIG_B2OUT = 1, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ + CTIMER_AUX2_TMRA2TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX2_TMRA2TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX2_TMRA2TRIG_A0OUT = 4, /*!< A0OUT : Trigger source is CTIMERA0 OUT. value. */ + CTIMER_AUX2_TMRA2TRIG_B0OUT = 5, /*!< B0OUT : Trigger source is CTIMERB0 OUT. value. */ + CTIMER_AUX2_TMRA2TRIG_A4OUT = 6, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ + CTIMER_AUX2_TMRA2TRIG_B4OUT = 7, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ + CTIMER_AUX2_TMRA2TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX2_TMRA2TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX2_TMRA2TRIG_A5OUT2 = 10, /*!< A5OUT2 : Trigger source is CTIMERA5 OUT2. value. */ + CTIMER_AUX2_TMRA2TRIG_B5OUT2 = 11, /*!< B5OUT2 : Trigger source is CTIMERB5 OUT2. value. */ + CTIMER_AUX2_TMRA2TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX2_TMRA2TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX2_TMRA2TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ + CTIMER_AUX2_TMRA2TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ +} CTIMER_AUX2_TMRA2TRIG_Enum; + +/* ========================================================= TMR3 ========================================================== */ +/* ======================================================== CMPRA3 ========================================================= */ +/* ======================================================== CMPRB3 ========================================================= */ +/* ========================================================= CTRL3 ========================================================= */ +/* ============================================= CTIMER CTRL3 CTLINK3 [31..31] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_CTLINK3 */ + CTIMER_CTRL3_CTLINK3_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A3/B3 timers as two independent 16-bit + timers (default). value. */ + CTIMER_CTRL3_CTLINK3_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A3/B3 timers into a single 32-bit timer. + value. */ +} CTIMER_CTRL3_CTLINK3_Enum; + +/* ============================================ CTIMER CTRL3 TMRB3POL [28..28] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRB3POL */ + CTIMER_CTRL3_TMRB3POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB3 pin is the same as the + timer output. value. */ + CTIMER_CTRL3_TMRB3POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB3 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL3_TMRB3POL_Enum; + +/* ============================================ CTIMER CTRL3 TMRB3CLR [27..27] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRB3CLR */ + CTIMER_CTRL3_TMRB3CLR_RUN = 0, /*!< RUN : Allow counter/timer B3 to run value. */ + CTIMER_CTRL3_TMRB3CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B3 at 0x0000. value. */ +} CTIMER_CTRL3_TMRB3CLR_Enum; + +/* ============================================ CTIMER CTRL3 TMRB3IE1 [26..26] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRB3IE1 */ + CTIMER_CTRL3_TMRB3IE1_DIS = 0, /*!< DIS : Disable counter/timer B3 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL3_TMRB3IE1_EN = 1, /*!< EN : Enable counter/timer B3 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL3_TMRB3IE1_Enum; + +/* ============================================ CTIMER CTRL3 TMRB3IE0 [25..25] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRB3IE0 */ + CTIMER_CTRL3_TMRB3IE0_DIS = 0, /*!< DIS : Disable counter/timer B3 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL3_TMRB3IE0_EN = 1, /*!< EN : Enable counter/timer B3 to generate an interrupt based + on COMPR0 value. */ +} CTIMER_CTRL3_TMRB3IE0_Enum; + +/* ============================================= CTIMER CTRL3 TMRB3FN [22..24] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRB3FN */ + CTIMER_CTRL3_TMRB3FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0B3, stop. value. */ + CTIMER_CTRL3_TMRB3FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0B3, restart. value. */ + CTIMER_CTRL3_TMRB3FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B3, assert, + count to CMPR1B3, deassert, stop. value. */ + CTIMER_CTRL3_TMRB3FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B3, assert, count + to CMPR1B3, deassert, restart. value. */ + CTIMER_CTRL3_TMRB3FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL3_TMRB3FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL3_TMRB3FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL3_TMRB3FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL3_TMRB3FN_Enum; + +/* ============================================ CTIMER CTRL3 TMRB3CLK [17..21] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRB3CLK */ + CTIMER_CTRL3_TMRB3CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ + CTIMER_CTRL3_TMRB3CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL3_TMRB3CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL3_TMRB3CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL3_TMRB3CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL3_TMRB3CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL3_TMRB3CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL3_TMRB3CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL3_TMRB3CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL3_TMRB3CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL3_TMRB3CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL3_TMRB3CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL3_TMRB3CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL3_TMRB3CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL3_TMRB3CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL3_TMRB3CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL3_TMRB3CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL3_TMRB3CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL3_TMRB3CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL3_TMRB3CLK_CTMRA3 = 20, /*!< CTMRA3 : Clock source is CTIMERA3 OUT. value. */ + CTIMER_CTRL3_TMRB3CLK_CTMRA2 = 21, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ + CTIMER_CTRL3_TMRB3CLK_CTMRB2 = 22, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL3_TMRB3CLK_CTMRA4 = 23, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ + CTIMER_CTRL3_TMRB3CLK_CTMRB4 = 24, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL3_TMRB3CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL3_TMRB3CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL3_TMRB3CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL3_TMRB3CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL3_TMRB3CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL3_TMRB3CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL3_TMRB3CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL3_TMRB3CLK_Enum; + +/* ============================================= CTIMER CTRL3 TMRB3EN [16..16] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRB3EN */ + CTIMER_CTRL3_TMRB3EN_DIS = 0, /*!< DIS : Counter/Timer B3 Disable. value. */ + CTIMER_CTRL3_TMRB3EN_EN = 1, /*!< EN : Counter/Timer B3 Enable. value. */ +} CTIMER_CTRL3_TMRB3EN_Enum; + +/* ============================================ CTIMER CTRL3 TMRA3POL [12..12] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRA3POL */ + CTIMER_CTRL3_TMRA3POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA3 pin is the same as the + timer output. value. */ + CTIMER_CTRL3_TMRA3POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA3 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL3_TMRA3POL_Enum; + +/* ============================================ CTIMER CTRL3 TMRA3CLR [11..11] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRA3CLR */ + CTIMER_CTRL3_TMRA3CLR_RUN = 0, /*!< RUN : Allow counter/timer A3 to run value. */ + CTIMER_CTRL3_TMRA3CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A3 at 0x0000. value. */ +} CTIMER_CTRL3_TMRA3CLR_Enum; + +/* ============================================ CTIMER CTRL3 TMRA3IE1 [10..10] ============================================= */ +typedef enum { /*!< CTIMER_CTRL3_TMRA3IE1 */ + CTIMER_CTRL3_TMRA3IE1_DIS = 0, /*!< DIS : Disable counter/timer A3 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL3_TMRA3IE1_EN = 1, /*!< EN : Enable counter/timer A3 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL3_TMRA3IE1_Enum; + +/* ============================================= CTIMER CTRL3 TMRA3IE0 [9..9] ============================================== */ +typedef enum { /*!< CTIMER_CTRL3_TMRA3IE0 */ + CTIMER_CTRL3_TMRA3IE0_DIS = 0, /*!< DIS : Disable counter/timer A3 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL3_TMRA3IE0_EN = 1, /*!< EN : Enable counter/timer A3 to generate an interrupt based + on COMPR0. value. */ +} CTIMER_CTRL3_TMRA3IE0_Enum; + +/* ============================================== CTIMER CTRL3 TMRA3FN [6..8] ============================================== */ +typedef enum { /*!< CTIMER_CTRL3_TMRA3FN */ + CTIMER_CTRL3_TMRA3FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0A3, stop. value. */ + CTIMER_CTRL3_TMRA3FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0A3, restart. value. */ + CTIMER_CTRL3_TMRA3FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A3, assert, + count to CMPR1A3, deassert, stop. value. */ + CTIMER_CTRL3_TMRA3FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A3, assert, count + to CMPR1A3, deassert, restart. value. */ + CTIMER_CTRL3_TMRA3FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL3_TMRA3FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL3_TMRA3FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL3_TMRA3FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL3_TMRA3FN_Enum; + +/* ============================================= CTIMER CTRL3 TMRA3CLK [1..5] ============================================== */ +typedef enum { /*!< CTIMER_CTRL3_TMRA3CLK */ + CTIMER_CTRL3_TMRA3CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ + CTIMER_CTRL3_TMRA3CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL3_TMRA3CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL3_TMRA3CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL3_TMRA3CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL3_TMRA3CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL3_TMRA3CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL3_TMRA3CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL3_TMRA3CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL3_TMRA3CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL3_TMRA3CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL3_TMRA3CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL3_TMRA3CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL3_TMRA3CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL3_TMRA3CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL3_TMRA3CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL3_TMRA3CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL3_TMRA3CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL3_TMRA3CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL3_TMRA3CLK_CTMRB3 = 20, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL3_TMRA3CLK_CTMRA2 = 21, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ + CTIMER_CTRL3_TMRA3CLK_CTMRB2 = 22, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL3_TMRA3CLK_CTMRA4 = 23, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ + CTIMER_CTRL3_TMRA3CLK_CTMRB4 = 24, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL3_TMRA3CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL3_TMRA3CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL3_TMRA3CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL3_TMRA3CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL3_TMRA3CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL3_TMRA3CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL3_TMRA3CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL3_TMRA3CLK_Enum; + +/* ============================================== CTIMER CTRL3 TMRA3EN [0..0] ============================================== */ +typedef enum { /*!< CTIMER_CTRL3_TMRA3EN */ + CTIMER_CTRL3_TMRA3EN_DIS = 0, /*!< DIS : Counter/Timer A3 Disable. value. */ + CTIMER_CTRL3_TMRA3EN_EN = 1, /*!< EN : Counter/Timer A3 Enable. value. */ +} CTIMER_CTRL3_TMRA3EN_Enum; + +/* ======================================================= CMPRAUXA3 ======================================================= */ +/* ======================================================= CMPRAUXB3 ======================================================= */ +/* ========================================================= AUX3 ========================================================== */ +/* ============================================ CTIMER AUX3 TMRB3EN23 [30..30] ============================================= */ +typedef enum { /*!< CTIMER_AUX3_TMRB3EN23 */ + CTIMER_AUX3_TMRB3EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX3_TMRB3EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX3_TMRB3EN23_Enum; + +/* ============================================ CTIMER AUX3 TMRB3POL23 [29..29] ============================================ */ +typedef enum { /*!< CTIMER_AUX3_TMRB3POL23 */ + CTIMER_AUX3_TMRB3POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX3_TMRB3POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX3_TMRB3POL23_Enum; + +/* ============================================ CTIMER AUX3 TMRB3TINV [28..28] ============================================= */ +typedef enum { /*!< CTIMER_AUX3_TMRB3TINV */ + CTIMER_AUX3_TMRB3TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX3_TMRB3TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX3_TMRB3TINV_Enum; + +/* =========================================== CTIMER AUX3 TMRB3NOSYNC [27..27] ============================================ */ +typedef enum { /*!< CTIMER_AUX3_TMRB3NOSYNC */ + CTIMER_AUX3_TMRB3NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX3_TMRB3NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX3_TMRB3NOSYNC_Enum; + +/* ============================================ CTIMER AUX3 TMRB3TRIG [23..26] ============================================= */ +typedef enum { /*!< CTIMER_AUX3_TMRB3TRIG */ + CTIMER_AUX3_TMRB3TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX3_TMRB3TRIG_A3OUT = 1, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX3_TMRB3TRIG_B2OUT = 2, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ + CTIMER_AUX3_TMRB3TRIG_A2OUT = 3, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ + CTIMER_AUX3_TMRB3TRIG_A4OUT = 4, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ + CTIMER_AUX3_TMRB3TRIG_B4OUT = 5, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ + CTIMER_AUX3_TMRB3TRIG_A6OUT = 6, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ + CTIMER_AUX3_TMRB3TRIG_B6OUT = 7, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ + CTIMER_AUX3_TMRB3TRIG_B5OUT2 = 8, /*!< B5OUT2 : Trigger source is CTIMERB5 OUT2. value. */ + CTIMER_AUX3_TMRB3TRIG_A5OUT2 = 9, /*!< A5OUT2 : Trigger source is CTIMERA5 OUT2. value. */ + CTIMER_AUX3_TMRB3TRIG_A1OUT2 = 10, /*!< A1OUT2 : Trigger source is CTIMERA1 OUT2. value. */ + CTIMER_AUX3_TMRB3TRIG_B1OUT2 = 11, /*!< B1OUT2 : Trigger source is CTIMERB1 OUT2. value. */ + CTIMER_AUX3_TMRB3TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX3_TMRB3TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX3_TMRB3TRIG_B2OUT2DUAL = 14, /*!< B2OUT2DUAL : Trigger source is CTIMERB2 OUT2, dual edge. value. */ + CTIMER_AUX3_TMRB3TRIG_A2OUT2DUAL = 15, /*!< A2OUT2DUAL : Trigger source is CTIMERA2 OUT2, dual edge. value. */ +} CTIMER_AUX3_TMRB3TRIG_Enum; + +/* ============================================ CTIMER AUX3 TMRA3EN23 [14..14] ============================================= */ +typedef enum { /*!< CTIMER_AUX3_TMRA3EN23 */ + CTIMER_AUX3_TMRA3EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX3_TMRA3EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX3_TMRA3EN23_Enum; + +/* ============================================ CTIMER AUX3 TMRA3POL23 [13..13] ============================================ */ +typedef enum { /*!< CTIMER_AUX3_TMRA3POL23 */ + CTIMER_AUX3_TMRA3POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX3_TMRA3POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX3_TMRA3POL23_Enum; + +/* ============================================ CTIMER AUX3 TMRA3TINV [12..12] ============================================= */ +typedef enum { /*!< CTIMER_AUX3_TMRA3TINV */ + CTIMER_AUX3_TMRA3TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX3_TMRA3TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX3_TMRA3TINV_Enum; + +/* =========================================== CTIMER AUX3 TMRA3NOSYNC [11..11] ============================================ */ +typedef enum { /*!< CTIMER_AUX3_TMRA3NOSYNC */ + CTIMER_AUX3_TMRA3NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX3_TMRA3NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX3_TMRA3NOSYNC_Enum; + +/* ============================================= CTIMER AUX3 TMRA3TRIG [7..10] ============================================= */ +typedef enum { /*!< CTIMER_AUX3_TMRA3TRIG */ + CTIMER_AUX3_TMRA3TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX3_TMRA3TRIG_B3OUT = 1, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX3_TMRA3TRIG_B2OUT = 2, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ + CTIMER_AUX3_TMRA3TRIG_A2OUT = 3, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ + CTIMER_AUX3_TMRA3TRIG_A4OUT = 4, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ + CTIMER_AUX3_TMRA3TRIG_B4OUT = 5, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ + CTIMER_AUX3_TMRA3TRIG_A7OUT = 6, /*!< A7OUT : Trigger source is CTIMERA7 OUT. value. */ + CTIMER_AUX3_TMRA3TRIG_B7OUT = 7, /*!< B7OUT : Trigger source is CTIMERB7 OUT. value. */ + CTIMER_AUX3_TMRA3TRIG_B5OUT2 = 8, /*!< B5OUT2 : Trigger source is CTIMERB5 OUT2. value. */ + CTIMER_AUX3_TMRA3TRIG_A5OUT2 = 9, /*!< A5OUT2 : Trigger source is CTIMERA5 OUT2. value. */ + CTIMER_AUX3_TMRA3TRIG_A1OUT2 = 10, /*!< A1OUT2 : Trigger source is CTIMERA1 OUT2. value. */ + CTIMER_AUX3_TMRA3TRIG_B1OUT2 = 11, /*!< B1OUT2 : Trigger source is CTIMERB1 OUT2. value. */ + CTIMER_AUX3_TMRA3TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX3_TMRA3TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX3_TMRA3TRIG_B2OUT2DUAL = 14, /*!< B2OUT2DUAL : Trigger source is CTIMERB2 OUT2, dual edge. value. */ + CTIMER_AUX3_TMRA3TRIG_A2OUT2DUAL = 15, /*!< A2OUT2DUAL : Trigger source is CTIMERA2 OUT2, dual edge. value. */ +} CTIMER_AUX3_TMRA3TRIG_Enum; + +/* ========================================================= TMR4 ========================================================== */ +/* ======================================================== CMPRA4 ========================================================= */ +/* ======================================================== CMPRB4 ========================================================= */ +/* ========================================================= CTRL4 ========================================================= */ +/* ============================================= CTIMER CTRL4 CTLINK4 [31..31] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_CTLINK4 */ + CTIMER_CTRL4_CTLINK4_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A4/B4 timers as two independent 16-bit + timers (default). value. */ + CTIMER_CTRL4_CTLINK4_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A4/B4 timers into a single 32-bit timer. + value. */ +} CTIMER_CTRL4_CTLINK4_Enum; + +/* ============================================ CTIMER CTRL4 TMRB4POL [28..28] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRB4POL */ + CTIMER_CTRL4_TMRB4POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB4 pin is the same as the + timer output. value. */ + CTIMER_CTRL4_TMRB4POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB4 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL4_TMRB4POL_Enum; + +/* ============================================ CTIMER CTRL4 TMRB4CLR [27..27] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRB4CLR */ + CTIMER_CTRL4_TMRB4CLR_RUN = 0, /*!< RUN : Allow counter/timer B4 to run value. */ + CTIMER_CTRL4_TMRB4CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B4 at 0x0000. value. */ +} CTIMER_CTRL4_TMRB4CLR_Enum; + +/* ============================================ CTIMER CTRL4 TMRB4IE1 [26..26] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRB4IE1 */ + CTIMER_CTRL4_TMRB4IE1_DIS = 0, /*!< DIS : Disable counter/timer B4 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL4_TMRB4IE1_EN = 1, /*!< EN : Enable counter/timer B4 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL4_TMRB4IE1_Enum; + +/* ============================================ CTIMER CTRL4 TMRB4IE0 [25..25] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRB4IE0 */ + CTIMER_CTRL4_TMRB4IE0_DIS = 0, /*!< DIS : Disable counter/timer B4 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL4_TMRB4IE0_EN = 1, /*!< EN : Enable counter/timer B4 to generate an interrupt based + on COMPR0 value. */ +} CTIMER_CTRL4_TMRB4IE0_Enum; + +/* ============================================= CTIMER CTRL4 TMRB4FN [22..24] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRB4FN */ + CTIMER_CTRL4_TMRB4FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0B4, stop. value. */ + CTIMER_CTRL4_TMRB4FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0B4, restart. value. */ + CTIMER_CTRL4_TMRB4FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B4, assert, + count to CMPR1B4, deassert, stop. value. */ + CTIMER_CTRL4_TMRB4FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B4, assert, count + to CMPR1B4, deassert, restart. value. */ + CTIMER_CTRL4_TMRB4FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL4_TMRB4FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL4_TMRB4FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL4_TMRB4FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL4_TMRB4FN_Enum; + +/* ============================================ CTIMER CTRL4 TMRB4CLK [17..21] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRB4CLK */ + CTIMER_CTRL4_TMRB4CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ + CTIMER_CTRL4_TMRB4CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL4_TMRB4CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL4_TMRB4CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL4_TMRB4CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL4_TMRB4CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL4_TMRB4CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL4_TMRB4CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL4_TMRB4CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL4_TMRB4CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL4_TMRB4CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL4_TMRB4CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL4_TMRB4CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL4_TMRB4CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL4_TMRB4CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL4_TMRB4CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL4_TMRB4CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL4_TMRB4CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL4_TMRB4CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL4_TMRB4CLK_CTMRA4 = 20, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ + CTIMER_CTRL4_TMRB4CLK_CTMRA1 = 21, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ + CTIMER_CTRL4_TMRB4CLK_CTMRB1 = 22, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL4_TMRB4CLK_CTMRA5 = 23, /*!< CTMRA5 : Clock source is CTIMERA5 OUT. value. */ + CTIMER_CTRL4_TMRB4CLK_CTMRB5 = 24, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL4_TMRB4CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL4_TMRB4CLK_CTMRB2 = 26, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL4_TMRB4CLK_CTMRB3 = 27, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL4_TMRB4CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL4_TMRB4CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL4_TMRB4CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL4_TMRB4CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL4_TMRB4CLK_Enum; + +/* ============================================= CTIMER CTRL4 TMRB4EN [16..16] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRB4EN */ + CTIMER_CTRL4_TMRB4EN_DIS = 0, /*!< DIS : Counter/Timer B4 Disable. value. */ + CTIMER_CTRL4_TMRB4EN_EN = 1, /*!< EN : Counter/Timer B4 Enable. value. */ +} CTIMER_CTRL4_TMRB4EN_Enum; + +/* ============================================ CTIMER CTRL4 TMRA4POL [12..12] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRA4POL */ + CTIMER_CTRL4_TMRA4POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA4 pin is the same as the + timer output. value. */ + CTIMER_CTRL4_TMRA4POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA4 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL4_TMRA4POL_Enum; + +/* ============================================ CTIMER CTRL4 TMRA4CLR [11..11] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRA4CLR */ + CTIMER_CTRL4_TMRA4CLR_RUN = 0, /*!< RUN : Allow counter/timer A4 to run value. */ + CTIMER_CTRL4_TMRA4CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A4 at 0x0000. value. */ +} CTIMER_CTRL4_TMRA4CLR_Enum; + +/* ============================================ CTIMER CTRL4 TMRA4IE1 [10..10] ============================================= */ +typedef enum { /*!< CTIMER_CTRL4_TMRA4IE1 */ + CTIMER_CTRL4_TMRA4IE1_DIS = 0, /*!< DIS : Disable counter/timer A4 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL4_TMRA4IE1_EN = 1, /*!< EN : Enable counter/timer A4 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL4_TMRA4IE1_Enum; + +/* ============================================= CTIMER CTRL4 TMRA4IE0 [9..9] ============================================== */ +typedef enum { /*!< CTIMER_CTRL4_TMRA4IE0 */ + CTIMER_CTRL4_TMRA4IE0_DIS = 0, /*!< DIS : Disable counter/timer A4 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL4_TMRA4IE0_EN = 1, /*!< EN : Enable counter/timer A4 to generate an interrupt based + on COMPR0. value. */ +} CTIMER_CTRL4_TMRA4IE0_Enum; + +/* ============================================== CTIMER CTRL4 TMRA4FN [6..8] ============================================== */ +typedef enum { /*!< CTIMER_CTRL4_TMRA4FN */ + CTIMER_CTRL4_TMRA4FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0A4, stop. value. */ + CTIMER_CTRL4_TMRA4FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0A4, restart. value. */ + CTIMER_CTRL4_TMRA4FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A4, assert, + count to CMPR1A4, deassert, stop. value. */ + CTIMER_CTRL4_TMRA4FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A4, assert, count + to CMPR1A4, deassert, restart. value. */ + CTIMER_CTRL4_TMRA4FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL4_TMRA4FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL4_TMRA4FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL4_TMRA4FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL4_TMRA4FN_Enum; + +/* ============================================= CTIMER CTRL4 TMRA4CLK [1..5] ============================================== */ +typedef enum { /*!< CTIMER_CTRL4_TMRA4CLK */ + CTIMER_CTRL4_TMRA4CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ + CTIMER_CTRL4_TMRA4CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL4_TMRA4CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL4_TMRA4CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL4_TMRA4CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL4_TMRA4CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL4_TMRA4CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL4_TMRA4CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL4_TMRA4CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL4_TMRA4CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL4_TMRA4CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL4_TMRA4CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL4_TMRA4CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL4_TMRA4CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL4_TMRA4CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL4_TMRA4CLK_HCLK_DIV4 = 15, /*!< HCLK_DIV4 : Clock source is HCLK / 4. value. */ + CTIMER_CTRL4_TMRA4CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL4_TMRA4CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL4_TMRA4CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL4_TMRA4CLK_CTMRB4 = 20, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL4_TMRA4CLK_CTMRA1 = 21, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ + CTIMER_CTRL4_TMRA4CLK_CTMRB1 = 22, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL4_TMRA4CLK_CTMRA5 = 23, /*!< CTMRA5 : Clock source is CTIMERA5 OUT. value. */ + CTIMER_CTRL4_TMRA4CLK_CTMRB5 = 24, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL4_TMRA4CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL4_TMRA4CLK_CTMRB2 = 26, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL4_TMRA4CLK_CTMRB3 = 27, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL4_TMRA4CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL4_TMRA4CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL4_TMRA4CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL4_TMRA4CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL4_TMRA4CLK_Enum; + +/* ============================================== CTIMER CTRL4 TMRA4EN [0..0] ============================================== */ +typedef enum { /*!< CTIMER_CTRL4_TMRA4EN */ + CTIMER_CTRL4_TMRA4EN_DIS = 0, /*!< DIS : Counter/Timer A4 Disable. value. */ + CTIMER_CTRL4_TMRA4EN_EN = 1, /*!< EN : Counter/Timer A4 Enable. value. */ +} CTIMER_CTRL4_TMRA4EN_Enum; + +/* ======================================================= CMPRAUXA4 ======================================================= */ +/* ======================================================= CMPRAUXB4 ======================================================= */ +/* ========================================================= AUX4 ========================================================== */ +/* ============================================ CTIMER AUX4 TMRB4EN23 [30..30] ============================================= */ +typedef enum { /*!< CTIMER_AUX4_TMRB4EN23 */ + CTIMER_AUX4_TMRB4EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX4_TMRB4EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX4_TMRB4EN23_Enum; + +/* ============================================ CTIMER AUX4 TMRB4POL23 [29..29] ============================================ */ +typedef enum { /*!< CTIMER_AUX4_TMRB4POL23 */ + CTIMER_AUX4_TMRB4POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX4_TMRB4POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX4_TMRB4POL23_Enum; + +/* ============================================ CTIMER AUX4 TMRB4TINV [28..28] ============================================= */ +typedef enum { /*!< CTIMER_AUX4_TMRB4TINV */ + CTIMER_AUX4_TMRB4TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX4_TMRB4TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX4_TMRB4TINV_Enum; + +/* =========================================== CTIMER AUX4 TMRB4NOSYNC [27..27] ============================================ */ +typedef enum { /*!< CTIMER_AUX4_TMRB4NOSYNC */ + CTIMER_AUX4_TMRB4NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX4_TMRB4NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX4_TMRB4NOSYNC_Enum; + +/* ============================================ CTIMER AUX4 TMRB4TRIG [23..26] ============================================= */ +typedef enum { /*!< CTIMER_AUX4_TMRB4TRIG */ + CTIMER_AUX4_TMRB4TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX4_TMRB4TRIG_A4OUT = 1, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ + CTIMER_AUX4_TMRB4TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX4_TMRB4TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX4_TMRB4TRIG_A7OUT = 4, /*!< A7OUT : Trigger source is CTIMERA7 OUT. value. */ + CTIMER_AUX4_TMRB4TRIG_B7OUT = 5, /*!< B7OUT : Trigger source is CTIMERB7 OUT. value. */ + CTIMER_AUX4_TMRB4TRIG_A1OUT = 6, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ + CTIMER_AUX4_TMRB4TRIG_B1OUT = 7, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ + CTIMER_AUX4_TMRB4TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX4_TMRB4TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX4_TMRB4TRIG_A1OUT2 = 10, /*!< A1OUT2 : Trigger source is CTIMERA1 OUT2. value. */ + CTIMER_AUX4_TMRB4TRIG_B1OUT2 = 11, /*!< B1OUT2 : Trigger source is CTIMERB1 OUT2. value. */ + CTIMER_AUX4_TMRB4TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX4_TMRB4TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX4_TMRB4TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ + CTIMER_AUX4_TMRB4TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ +} CTIMER_AUX4_TMRB4TRIG_Enum; + +/* ============================================ CTIMER AUX4 TMRA4EN23 [14..14] ============================================= */ +typedef enum { /*!< CTIMER_AUX4_TMRA4EN23 */ + CTIMER_AUX4_TMRA4EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX4_TMRA4EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX4_TMRA4EN23_Enum; + +/* ============================================ CTIMER AUX4 TMRA4POL23 [13..13] ============================================ */ +typedef enum { /*!< CTIMER_AUX4_TMRA4POL23 */ + CTIMER_AUX4_TMRA4POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX4_TMRA4POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX4_TMRA4POL23_Enum; + +/* ============================================ CTIMER AUX4 TMRA4TINV [12..12] ============================================= */ +typedef enum { /*!< CTIMER_AUX4_TMRA4TINV */ + CTIMER_AUX4_TMRA4TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX4_TMRA4TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX4_TMRA4TINV_Enum; + +/* =========================================== CTIMER AUX4 TMRA4NOSYNC [11..11] ============================================ */ +typedef enum { /*!< CTIMER_AUX4_TMRA4NOSYNC */ + CTIMER_AUX4_TMRA4NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX4_TMRA4NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX4_TMRA4NOSYNC_Enum; + +/* ============================================= CTIMER AUX4 TMRA4TRIG [7..10] ============================================= */ +typedef enum { /*!< CTIMER_AUX4_TMRA4TRIG */ + CTIMER_AUX4_TMRA4TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX4_TMRA4TRIG_B4OUT = 1, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ + CTIMER_AUX4_TMRA4TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX4_TMRA4TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX4_TMRA4TRIG_A6OUT = 4, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ + CTIMER_AUX4_TMRA4TRIG_B6OUT = 5, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ + CTIMER_AUX4_TMRA4TRIG_A2OUT = 6, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ + CTIMER_AUX4_TMRA4TRIG_B2OUT = 7, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ + CTIMER_AUX4_TMRA4TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX4_TMRA4TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX4_TMRA4TRIG_A1OUT2 = 10, /*!< A1OUT2 : Trigger source is CTIMERA1 OUT2. value. */ + CTIMER_AUX4_TMRA4TRIG_B1OUT2 = 11, /*!< B1OUT2 : Trigger source is CTIMERB1 OUT2. value. */ + CTIMER_AUX4_TMRA4TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX4_TMRA4TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX4_TMRA4TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ + CTIMER_AUX4_TMRA4TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ +} CTIMER_AUX4_TMRA4TRIG_Enum; + +/* ========================================================= TMR5 ========================================================== */ +/* ======================================================== CMPRA5 ========================================================= */ +/* ======================================================== CMPRB5 ========================================================= */ +/* ========================================================= CTRL5 ========================================================= */ +/* ============================================= CTIMER CTRL5 CTLINK5 [31..31] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_CTLINK5 */ + CTIMER_CTRL5_CTLINK5_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A5/B5 timers as two independent 16-bit + timers (default). value. */ + CTIMER_CTRL5_CTLINK5_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A5/B5 timers into a single 32-bit timer. + value. */ +} CTIMER_CTRL5_CTLINK5_Enum; + +/* ============================================ CTIMER CTRL5 TMRB5POL [28..28] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRB5POL */ + CTIMER_CTRL5_TMRB5POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB5 pin is the same as the + timer output. value. */ + CTIMER_CTRL5_TMRB5POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB5 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL5_TMRB5POL_Enum; + +/* ============================================ CTIMER CTRL5 TMRB5CLR [27..27] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRB5CLR */ + CTIMER_CTRL5_TMRB5CLR_RUN = 0, /*!< RUN : Allow counter/timer B5 to run value. */ + CTIMER_CTRL5_TMRB5CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B5 at 0x0000. value. */ +} CTIMER_CTRL5_TMRB5CLR_Enum; + +/* ============================================ CTIMER CTRL5 TMRB5IE1 [26..26] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRB5IE1 */ + CTIMER_CTRL5_TMRB5IE1_DIS = 0, /*!< DIS : Disable counter/timer B5 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL5_TMRB5IE1_EN = 1, /*!< EN : Enable counter/timer B5 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL5_TMRB5IE1_Enum; + +/* ============================================ CTIMER CTRL5 TMRB5IE0 [25..25] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRB5IE0 */ + CTIMER_CTRL5_TMRB5IE0_DIS = 0, /*!< DIS : Disable counter/timer B5 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL5_TMRB5IE0_EN = 1, /*!< EN : Enable counter/timer B5 to generate an interrupt based + on COMPR0 value. */ +} CTIMER_CTRL5_TMRB5IE0_Enum; + +/* ============================================= CTIMER CTRL5 TMRB5FN [22..24] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRB5FN */ + CTIMER_CTRL5_TMRB5FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0B5, stop. value. */ + CTIMER_CTRL5_TMRB5FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0B5, restart. value. */ + CTIMER_CTRL5_TMRB5FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B5, assert, + count to CMPR1B5, deassert, stop. value. */ + CTIMER_CTRL5_TMRB5FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B5, assert, count + to CMPR1B5, deassert, restart. value. */ + CTIMER_CTRL5_TMRB5FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL5_TMRB5FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL5_TMRB5FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL5_TMRB5FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL5_TMRB5FN_Enum; + +/* ============================================ CTIMER CTRL5 TMRB5CLK [17..21] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRB5CLK */ + CTIMER_CTRL5_TMRB5CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ + CTIMER_CTRL5_TMRB5CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL5_TMRB5CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL5_TMRB5CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL5_TMRB5CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL5_TMRB5CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL5_TMRB5CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL5_TMRB5CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL5_TMRB5CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL5_TMRB5CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL5_TMRB5CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL5_TMRB5CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL5_TMRB5CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL5_TMRB5CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL5_TMRB5CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL5_TMRB5CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL5_TMRB5CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL5_TMRB5CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL5_TMRB5CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL5_TMRB5CLK_CTMRA5 = 20, /*!< CTMRA5 : Clock source is CTIMERA5 OUT. value. */ + CTIMER_CTRL5_TMRB5CLK_CTMRA0 = 21, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ + CTIMER_CTRL5_TMRB5CLK_CTMRB0 = 22, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL5_TMRB5CLK_CTMRA6 = 23, /*!< CTMRA6 : Clock source is CTIMERA6 OUT. value. */ + CTIMER_CTRL5_TMRB5CLK_CTMRB6 = 24, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL5_TMRB5CLK_CTMRB1 = 25, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL5_TMRB5CLK_CTMRB2 = 26, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL5_TMRB5CLK_CTMRB3 = 27, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL5_TMRB5CLK_CTMRB4 = 28, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL5_TMRB5CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL5_TMRB5CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL5_TMRB5CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL5_TMRB5CLK_Enum; + +/* ============================================= CTIMER CTRL5 TMRB5EN [16..16] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRB5EN */ + CTIMER_CTRL5_TMRB5EN_DIS = 0, /*!< DIS : Counter/Timer B5 Disable. value. */ + CTIMER_CTRL5_TMRB5EN_EN = 1, /*!< EN : Counter/Timer B5 Enable. value. */ +} CTIMER_CTRL5_TMRB5EN_Enum; + +/* ============================================ CTIMER CTRL5 TMRA5POL [12..12] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRA5POL */ + CTIMER_CTRL5_TMRA5POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA5 pin is the same as the + timer output. value. */ + CTIMER_CTRL5_TMRA5POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA5 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL5_TMRA5POL_Enum; + +/* ============================================ CTIMER CTRL5 TMRA5CLR [11..11] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRA5CLR */ + CTIMER_CTRL5_TMRA5CLR_RUN = 0, /*!< RUN : Allow counter/timer A5 to run value. */ + CTIMER_CTRL5_TMRA5CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A5 at 0x0000. value. */ +} CTIMER_CTRL5_TMRA5CLR_Enum; + +/* ============================================ CTIMER CTRL5 TMRA5IE1 [10..10] ============================================= */ +typedef enum { /*!< CTIMER_CTRL5_TMRA5IE1 */ + CTIMER_CTRL5_TMRA5IE1_DIS = 0, /*!< DIS : Disable counter/timer A5 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL5_TMRA5IE1_EN = 1, /*!< EN : Enable counter/timer A5 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL5_TMRA5IE1_Enum; + +/* ============================================= CTIMER CTRL5 TMRA5IE0 [9..9] ============================================== */ +typedef enum { /*!< CTIMER_CTRL5_TMRA5IE0 */ + CTIMER_CTRL5_TMRA5IE0_DIS = 0, /*!< DIS : Disable counter/timer A5 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL5_TMRA5IE0_EN = 1, /*!< EN : Enable counter/timer A5 to generate an interrupt based + on COMPR0. value. */ +} CTIMER_CTRL5_TMRA5IE0_Enum; + +/* ============================================== CTIMER CTRL5 TMRA5FN [6..8] ============================================== */ +typedef enum { /*!< CTIMER_CTRL5_TMRA5FN */ + CTIMER_CTRL5_TMRA5FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0A5, stop. value. */ + CTIMER_CTRL5_TMRA5FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0A5, restart. value. */ + CTIMER_CTRL5_TMRA5FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A5, assert, + count to CMPR1A5, deassert, stop. value. */ + CTIMER_CTRL5_TMRA5FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A5, assert, count + to CMPR1A5, deassert, restart. value. */ + CTIMER_CTRL5_TMRA5FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL5_TMRA5FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL5_TMRA5FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL5_TMRA5FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL5_TMRA5FN_Enum; + +/* ============================================= CTIMER CTRL5 TMRA5CLK [1..5] ============================================== */ +typedef enum { /*!< CTIMER_CTRL5_TMRA5CLK */ + CTIMER_CTRL5_TMRA5CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ + CTIMER_CTRL5_TMRA5CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL5_TMRA5CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL5_TMRA5CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL5_TMRA5CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL5_TMRA5CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL5_TMRA5CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL5_TMRA5CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL5_TMRA5CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL5_TMRA5CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL5_TMRA5CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL5_TMRA5CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL5_TMRA5CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL5_TMRA5CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL5_TMRA5CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL5_TMRA5CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL5_TMRA5CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL5_TMRA5CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL5_TMRA5CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL5_TMRA5CLK_CTMRB5 = 20, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL5_TMRA5CLK_CTMRA0 = 21, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ + CTIMER_CTRL5_TMRA5CLK_CTMRB0 = 22, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL5_TMRA5CLK_CTMRA6 = 23, /*!< CTMRA6 : Clock source is CTIMERA6 OUT. value. */ + CTIMER_CTRL5_TMRA5CLK_CTMRB6 = 24, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL5_TMRA5CLK_CTMRB1 = 25, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL5_TMRA5CLK_CTMRB2 = 26, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL5_TMRA5CLK_CTMRB3 = 27, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL5_TMRA5CLK_CTMRB4 = 28, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL5_TMRA5CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL5_TMRA5CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL5_TMRA5CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL5_TMRA5CLK_Enum; + +/* ============================================== CTIMER CTRL5 TMRA5EN [0..0] ============================================== */ +typedef enum { /*!< CTIMER_CTRL5_TMRA5EN */ + CTIMER_CTRL5_TMRA5EN_DIS = 0, /*!< DIS : Counter/Timer A5 Disable. value. */ + CTIMER_CTRL5_TMRA5EN_EN = 1, /*!< EN : Counter/Timer A5 Enable. value. */ +} CTIMER_CTRL5_TMRA5EN_Enum; + +/* ======================================================= CMPRAUXA5 ======================================================= */ +/* ======================================================= CMPRAUXB5 ======================================================= */ +/* ========================================================= AUX5 ========================================================== */ +/* ============================================ CTIMER AUX5 TMRB5EN23 [30..30] ============================================= */ +typedef enum { /*!< CTIMER_AUX5_TMRB5EN23 */ + CTIMER_AUX5_TMRB5EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX5_TMRB5EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX5_TMRB5EN23_Enum; + +/* ============================================ CTIMER AUX5 TMRB5POL23 [29..29] ============================================ */ +typedef enum { /*!< CTIMER_AUX5_TMRB5POL23 */ + CTIMER_AUX5_TMRB5POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX5_TMRB5POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX5_TMRB5POL23_Enum; + +/* ============================================ CTIMER AUX5 TMRB5TINV [28..28] ============================================= */ +typedef enum { /*!< CTIMER_AUX5_TMRB5TINV */ + CTIMER_AUX5_TMRB5TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX5_TMRB5TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX5_TMRB5TINV_Enum; + +/* =========================================== CTIMER AUX5 TMRB5NOSYNC [27..27] ============================================ */ +typedef enum { /*!< CTIMER_AUX5_TMRB5NOSYNC */ + CTIMER_AUX5_TMRB5NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX5_TMRB5NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX5_TMRB5NOSYNC_Enum; + +/* ============================================ CTIMER AUX5 TMRB5TRIG [23..26] ============================================= */ +typedef enum { /*!< CTIMER_AUX5_TMRB5TRIG */ + CTIMER_AUX5_TMRB5TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX5_TMRB5TRIG_A5OUT = 1, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ + CTIMER_AUX5_TMRB5TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX5_TMRB5TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX5_TMRB5TRIG_A6OUT = 4, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ + CTIMER_AUX5_TMRB5TRIG_B6OUT = 5, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ + CTIMER_AUX5_TMRB5TRIG_A1OUT = 6, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ + CTIMER_AUX5_TMRB5TRIG_B1OUT = 7, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ + CTIMER_AUX5_TMRB5TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX5_TMRB5TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX5_TMRB5TRIG_A0OUT2 = 10, /*!< A0OUT2 : Trigger source is CTIMERA0 OUT2. value. */ + CTIMER_AUX5_TMRB5TRIG_B0OUT2 = 11, /*!< B0OUT2 : Trigger source is CTIMERB0 OUT2. value. */ + CTIMER_AUX5_TMRB5TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX5_TMRB5TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX5_TMRB5TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ + CTIMER_AUX5_TMRB5TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ +} CTIMER_AUX5_TMRB5TRIG_Enum; + +/* ============================================ CTIMER AUX5 TMRA5EN23 [14..14] ============================================= */ +typedef enum { /*!< CTIMER_AUX5_TMRA5EN23 */ + CTIMER_AUX5_TMRA5EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX5_TMRA5EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX5_TMRA5EN23_Enum; + +/* ============================================ CTIMER AUX5 TMRA5POL23 [13..13] ============================================ */ +typedef enum { /*!< CTIMER_AUX5_TMRA5POL23 */ + CTIMER_AUX5_TMRA5POL23_NORMAL = 0, /*!< NORMAL : Upper output normal polarity value. */ + CTIMER_AUX5_TMRA5POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX5_TMRA5POL23_Enum; + +/* ============================================ CTIMER AUX5 TMRA5TINV [12..12] ============================================= */ +typedef enum { /*!< CTIMER_AUX5_TMRA5TINV */ + CTIMER_AUX5_TMRA5TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX5_TMRA5TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX5_TMRA5TINV_Enum; + +/* =========================================== CTIMER AUX5 TMRA5NOSYNC [11..11] ============================================ */ +typedef enum { /*!< CTIMER_AUX5_TMRA5NOSYNC */ + CTIMER_AUX5_TMRA5NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX5_TMRA5NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX5_TMRA5NOSYNC_Enum; + +/* ============================================= CTIMER AUX5 TMRA5TRIG [7..10] ============================================= */ +typedef enum { /*!< CTIMER_AUX5_TMRA5TRIG */ + CTIMER_AUX5_TMRA5TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX5_TMRA5TRIG_B5OUT = 1, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ + CTIMER_AUX5_TMRA5TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX5_TMRA5TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX5_TMRA5TRIG_A4OUT = 4, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ + CTIMER_AUX5_TMRA5TRIG_B4OUT = 5, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ + CTIMER_AUX5_TMRA5TRIG_A2OUT = 6, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ + CTIMER_AUX5_TMRA5TRIG_B2OUT = 7, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ + CTIMER_AUX5_TMRA5TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX5_TMRA5TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX5_TMRA5TRIG_A0OUT2 = 10, /*!< A0OUT2 : Trigger source is CTIMERA0 OUT2. value. */ + CTIMER_AUX5_TMRA5TRIG_B0OUT2 = 11, /*!< B0OUT2 : Trigger source is CTIMERB0 OUT2. value. */ + CTIMER_AUX5_TMRA5TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX5_TMRA5TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX5_TMRA5TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ + CTIMER_AUX5_TMRA5TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ +} CTIMER_AUX5_TMRA5TRIG_Enum; + +/* ========================================================= TMR6 ========================================================== */ +/* ======================================================== CMPRA6 ========================================================= */ +/* ======================================================== CMPRB6 ========================================================= */ +/* ========================================================= CTRL6 ========================================================= */ +/* ============================================= CTIMER CTRL6 CTLINK6 [31..31] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_CTLINK6 */ + CTIMER_CTRL6_CTLINK6_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A6/B6 timers as two independent 16-bit + timers (default). value. */ + CTIMER_CTRL6_CTLINK6_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A6/B6 timers into a single 32-bit timer. + value. */ +} CTIMER_CTRL6_CTLINK6_Enum; + +/* ============================================ CTIMER CTRL6 TMRB6POL [28..28] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRB6POL */ + CTIMER_CTRL6_TMRB6POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB6 pin is the same as the + timer output. value. */ + CTIMER_CTRL6_TMRB6POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB6 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL6_TMRB6POL_Enum; + +/* ============================================ CTIMER CTRL6 TMRB6CLR [27..27] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRB6CLR */ + CTIMER_CTRL6_TMRB6CLR_RUN = 0, /*!< RUN : Allow counter/timer B6 to run value. */ + CTIMER_CTRL6_TMRB6CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B6 at 0x0000. value. */ +} CTIMER_CTRL6_TMRB6CLR_Enum; + +/* ============================================ CTIMER CTRL6 TMRB6IE1 [26..26] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRB6IE1 */ + CTIMER_CTRL6_TMRB6IE1_DIS = 0, /*!< DIS : Disable counter/timer B6 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL6_TMRB6IE1_EN = 1, /*!< EN : Enable counter/timer B6 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL6_TMRB6IE1_Enum; + +/* ============================================ CTIMER CTRL6 TMRB6IE0 [25..25] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRB6IE0 */ + CTIMER_CTRL6_TMRB6IE0_DIS = 0, /*!< DIS : Disable counter/timer B6 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL6_TMRB6IE0_EN = 1, /*!< EN : Enable counter/timer B6 to generate an interrupt based + on COMPR0 value. */ +} CTIMER_CTRL6_TMRB6IE0_Enum; + +/* ============================================= CTIMER CTRL6 TMRB6FN [22..24] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRB6FN */ + CTIMER_CTRL6_TMRB6FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0B6, stop. value. */ + CTIMER_CTRL6_TMRB6FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0B6, restart. value. */ + CTIMER_CTRL6_TMRB6FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B6, assert, + count to CMPR1B6, deassert, stop. value. */ + CTIMER_CTRL6_TMRB6FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B6, assert, count + to CMPR1B6, deassert, restart. value. */ + CTIMER_CTRL6_TMRB6FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL6_TMRB6FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL6_TMRB6FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL6_TMRB6FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL6_TMRB6FN_Enum; + +/* ============================================ CTIMER CTRL6 TMRB6CLK [17..21] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRB6CLK */ + CTIMER_CTRL6_TMRB6CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ + CTIMER_CTRL6_TMRB6CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL6_TMRB6CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL6_TMRB6CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL6_TMRB6CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL6_TMRB6CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL6_TMRB6CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL6_TMRB6CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL6_TMRB6CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL6_TMRB6CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL6_TMRB6CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL6_TMRB6CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL6_TMRB6CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL6_TMRB6CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL6_TMRB6CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL6_TMRB6CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL6_TMRB6CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL6_TMRB6CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL6_TMRB6CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL6_TMRB6CLK_CTMRA6 = 20, /*!< CTMRA6 : Clock source is CTIMERA6 OUT. value. */ + CTIMER_CTRL6_TMRB6CLK_CTMRA3 = 21, /*!< CTMRA3 : Clock source is CTIMERA3 OUT. value. */ + CTIMER_CTRL6_TMRB6CLK_CTMRB3 = 22, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL6_TMRB6CLK_CTMRA7 = 23, /*!< CTMRA7 : Clock source is CTIMERA7 OUT. value. */ + CTIMER_CTRL6_TMRB6CLK_CTMRB7 = 24, /*!< CTMRB7 : Clock source is CTIMERB7 OUT. value. */ + CTIMER_CTRL6_TMRB6CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL6_TMRB6CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL6_TMRB6CLK_CTMRB2 = 27, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL6_TMRB6CLK_CTMRB4 = 28, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL6_TMRB6CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL6_TMRB6CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL6_TMRB6CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL6_TMRB6CLK_Enum; + +/* ============================================= CTIMER CTRL6 TMRB6EN [16..16] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRB6EN */ + CTIMER_CTRL6_TMRB6EN_DIS = 0, /*!< DIS : Counter/Timer B6 Disable. value. */ + CTIMER_CTRL6_TMRB6EN_EN = 1, /*!< EN : Counter/Timer B6 Enable. value. */ +} CTIMER_CTRL6_TMRB6EN_Enum; + +/* ============================================ CTIMER CTRL6 TMRA6POL [12..12] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRA6POL */ + CTIMER_CTRL6_TMRA6POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA6 pin is the same as the + timer output. value. */ + CTIMER_CTRL6_TMRA6POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA6 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL6_TMRA6POL_Enum; + +/* ============================================ CTIMER CTRL6 TMRA6CLR [11..11] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRA6CLR */ + CTIMER_CTRL6_TMRA6CLR_RUN = 0, /*!< RUN : Allow counter/timer A6 to run value. */ + CTIMER_CTRL6_TMRA6CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A6 at 0x0000. value. */ +} CTIMER_CTRL6_TMRA6CLR_Enum; + +/* ============================================ CTIMER CTRL6 TMRA6IE1 [10..10] ============================================= */ +typedef enum { /*!< CTIMER_CTRL6_TMRA6IE1 */ + CTIMER_CTRL6_TMRA6IE1_DIS = 0, /*!< DIS : Disable counter/timer A6 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL6_TMRA6IE1_EN = 1, /*!< EN : Enable counter/timer A6 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL6_TMRA6IE1_Enum; + +/* ============================================= CTIMER CTRL6 TMRA6IE0 [9..9] ============================================== */ +typedef enum { /*!< CTIMER_CTRL6_TMRA6IE0 */ + CTIMER_CTRL6_TMRA6IE0_DIS = 0, /*!< DIS : Disable counter/timer A6 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL6_TMRA6IE0_EN = 1, /*!< EN : Enable counter/timer A6 to generate an interrupt based + on COMPR0. value. */ +} CTIMER_CTRL6_TMRA6IE0_Enum; + +/* ============================================== CTIMER CTRL6 TMRA6FN [6..8] ============================================== */ +typedef enum { /*!< CTIMER_CTRL6_TMRA6FN */ + CTIMER_CTRL6_TMRA6FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0A6, stop. value. */ + CTIMER_CTRL6_TMRA6FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0A6, restart. value. */ + CTIMER_CTRL6_TMRA6FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A6, assert, + count to CMPR1A6, deassert, stop. value. */ + CTIMER_CTRL6_TMRA6FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A6, assert, count + to CMPR1A6, deassert, restart. value. */ + CTIMER_CTRL6_TMRA6FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL6_TMRA6FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL6_TMRA6FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL6_TMRA6FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL6_TMRA6FN_Enum; + +/* ============================================= CTIMER CTRL6 TMRA6CLK [1..5] ============================================== */ +typedef enum { /*!< CTIMER_CTRL6_TMRA6CLK */ + CTIMER_CTRL6_TMRA6CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ + CTIMER_CTRL6_TMRA6CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL6_TMRA6CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL6_TMRA6CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL6_TMRA6CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL6_TMRA6CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL6_TMRA6CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL6_TMRA6CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL6_TMRA6CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL6_TMRA6CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL6_TMRA6CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL6_TMRA6CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL6_TMRA6CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL6_TMRA6CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL6_TMRA6CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL6_TMRA6CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL6_TMRA6CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL6_TMRA6CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL6_TMRA6CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL6_TMRA6CLK_CTMRB6 = 20, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ + CTIMER_CTRL6_TMRA6CLK_CTMRA3 = 21, /*!< CTMRA3 : Clock source is CTIMERA3 OUT. value. */ + CTIMER_CTRL6_TMRA6CLK_CTMRB3 = 22, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL6_TMRA6CLK_CTMRA7 = 23, /*!< CTMRA7 : Clock source is CTIMERA7 OUT. value. */ + CTIMER_CTRL6_TMRA6CLK_CTMRB7 = 24, /*!< CTMRB7 : Clock source is CTIMERB7 OUT. value. */ + CTIMER_CTRL6_TMRA6CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL6_TMRA6CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL6_TMRA6CLK_CTMRB2 = 27, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL6_TMRA6CLK_CTMRB4 = 28, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL6_TMRA6CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL6_TMRA6CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL6_TMRA6CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL6_TMRA6CLK_Enum; + +/* ============================================== CTIMER CTRL6 TMRA6EN [0..0] ============================================== */ +typedef enum { /*!< CTIMER_CTRL6_TMRA6EN */ + CTIMER_CTRL6_TMRA6EN_DIS = 0, /*!< DIS : Counter/Timer A6 Disable. value. */ + CTIMER_CTRL6_TMRA6EN_EN = 1, /*!< EN : Counter/Timer A6 Enable. value. */ +} CTIMER_CTRL6_TMRA6EN_Enum; + +/* ======================================================= CMPRAUXA6 ======================================================= */ +/* ======================================================= CMPRAUXB6 ======================================================= */ +/* ========================================================= AUX6 ========================================================== */ +/* ============================================ CTIMER AUX6 TMRB6EN23 [30..30] ============================================= */ +typedef enum { /*!< CTIMER_AUX6_TMRB6EN23 */ + CTIMER_AUX6_TMRB6EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX6_TMRB6EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX6_TMRB6EN23_Enum; + +/* ============================================ CTIMER AUX6 TMRB6POL23 [29..29] ============================================ */ +typedef enum { /*!< CTIMER_AUX6_TMRB6POL23 */ + CTIMER_AUX6_TMRB6POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX6_TMRB6POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX6_TMRB6POL23_Enum; + +/* ============================================ CTIMER AUX6 TMRB6TINV [28..28] ============================================= */ +typedef enum { /*!< CTIMER_AUX6_TMRB6TINV */ + CTIMER_AUX6_TMRB6TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX6_TMRB6TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX6_TMRB6TINV_Enum; + +/* =========================================== CTIMER AUX6 TMRB6NOSYNC [27..27] ============================================ */ +typedef enum { /*!< CTIMER_AUX6_TMRB6NOSYNC */ + CTIMER_AUX6_TMRB6NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX6_TMRB6NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX6_TMRB6NOSYNC_Enum; + +/* ============================================ CTIMER AUX6 TMRB6TRIG [23..26] ============================================= */ +typedef enum { /*!< CTIMER_AUX6_TMRB6TRIG */ + CTIMER_AUX6_TMRB6TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX6_TMRB6TRIG_A6OUT = 1, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ + CTIMER_AUX6_TMRB6TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX6_TMRB6TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX6_TMRB6TRIG_A4OUT = 4, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ + CTIMER_AUX6_TMRB6TRIG_B4OUT = 5, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ + CTIMER_AUX6_TMRB6TRIG_A1OUT = 6, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ + CTIMER_AUX6_TMRB6TRIG_B1OUT = 7, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ + CTIMER_AUX6_TMRB6TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX6_TMRB6TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX6_TMRB6TRIG_A2OUT2 = 10, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ + CTIMER_AUX6_TMRB6TRIG_B2OUT2 = 11, /*!< B2OUT2 : Trigger source is CTIMERB2 OUT2. value. */ + CTIMER_AUX6_TMRB6TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX6_TMRB6TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX6_TMRB6TRIG_B0OUT2DUAL = 14, /*!< B0OUT2DUAL : Trigger source is CTIMERB0 OUT2, dual edge. value. */ + CTIMER_AUX6_TMRB6TRIG_A0OUT2DUAL = 15, /*!< A0OUT2DUAL : Trigger source is CTIMERA0 OUT2, dual edge. value. */ +} CTIMER_AUX6_TMRB6TRIG_Enum; + +/* ============================================ CTIMER AUX6 TMRA6EN23 [14..14] ============================================= */ +typedef enum { /*!< CTIMER_AUX6_TMRA6EN23 */ + CTIMER_AUX6_TMRA6EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX6_TMRA6EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX6_TMRA6EN23_Enum; + +/* ============================================ CTIMER AUX6 TMRA6POL23 [13..13] ============================================ */ +typedef enum { /*!< CTIMER_AUX6_TMRA6POL23 */ + CTIMER_AUX6_TMRA6POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX6_TMRA6POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX6_TMRA6POL23_Enum; + +/* ============================================ CTIMER AUX6 TMRA6TINV [12..12] ============================================= */ +typedef enum { /*!< CTIMER_AUX6_TMRA6TINV */ + CTIMER_AUX6_TMRA6TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX6_TMRA6TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX6_TMRA6TINV_Enum; + +/* =========================================== CTIMER AUX6 TMRA6NOSYNC [11..11] ============================================ */ +typedef enum { /*!< CTIMER_AUX6_TMRA6NOSYNC */ + CTIMER_AUX6_TMRA6NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX6_TMRA6NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX6_TMRA6NOSYNC_Enum; + +/* ============================================= CTIMER AUX6 TMRA6TRIG [7..10] ============================================= */ +typedef enum { /*!< CTIMER_AUX6_TMRA6TRIG */ + CTIMER_AUX6_TMRA6TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX6_TMRA6TRIG_B6OUT = 1, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ + CTIMER_AUX6_TMRA6TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX6_TMRA6TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX6_TMRA6TRIG_A5OUT = 4, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ + CTIMER_AUX6_TMRA6TRIG_B5OUT = 5, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ + CTIMER_AUX6_TMRA6TRIG_A1OUT = 6, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ + CTIMER_AUX6_TMRA6TRIG_B1OUT = 7, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ + CTIMER_AUX6_TMRA6TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX6_TMRA6TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX6_TMRA6TRIG_A2OUT2 = 10, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ + CTIMER_AUX6_TMRA6TRIG_B2OUT2 = 11, /*!< B2OUT2 : Trigger source is CTIMERBb OUT2. value. */ + CTIMER_AUX6_TMRA6TRIG_A5OUT2DUAL = 12, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ + CTIMER_AUX6_TMRA6TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX6_TMRA6TRIG_B0OUT2DUAL = 14, /*!< B0OUT2DUAL : Trigger source is CTIMERB0 OUT2, dual edge. value. */ + CTIMER_AUX6_TMRA6TRIG_A0OUT2DUAL = 15, /*!< A0OUT2DUAL : Trigger source is CTIMERA0 OUT2, dual edge. value. */ +} CTIMER_AUX6_TMRA6TRIG_Enum; + +/* ========================================================= TMR7 ========================================================== */ +/* ======================================================== CMPRA7 ========================================================= */ +/* ======================================================== CMPRB7 ========================================================= */ +/* ========================================================= CTRL7 ========================================================= */ +/* ============================================= CTIMER CTRL7 CTLINK7 [31..31] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_CTLINK7 */ + CTIMER_CTRL7_CTLINK7_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A7/B7 timers as two independent 16-bit + timers (default). value. */ + CTIMER_CTRL7_CTLINK7_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A7/B7 timers into a single 32-bit timer. + value. */ +} CTIMER_CTRL7_CTLINK7_Enum; + +/* ============================================ CTIMER CTRL7 TMRB7POL [28..28] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRB7POL */ + CTIMER_CTRL7_TMRB7POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB7 pin is the same as the + timer output. value. */ + CTIMER_CTRL7_TMRB7POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB7 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL7_TMRB7POL_Enum; + +/* ============================================ CTIMER CTRL7 TMRB7CLR [27..27] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRB7CLR */ + CTIMER_CTRL7_TMRB7CLR_RUN = 0, /*!< RUN : Allow counter/timer B7 to run value. */ + CTIMER_CTRL7_TMRB7CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B7 at 0x0000. value. */ +} CTIMER_CTRL7_TMRB7CLR_Enum; + +/* ============================================ CTIMER CTRL7 TMRB7IE1 [26..26] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRB7IE1 */ + CTIMER_CTRL7_TMRB7IE1_DIS = 0, /*!< DIS : Disable counter/timer B7 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL7_TMRB7IE1_EN = 1, /*!< EN : Enable counter/timer B7 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL7_TMRB7IE1_Enum; + +/* ============================================ CTIMER CTRL7 TMRB7IE0 [25..25] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRB7IE0 */ + CTIMER_CTRL7_TMRB7IE0_DIS = 0, /*!< DIS : Disable counter/timer B7 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL7_TMRB7IE0_EN = 1, /*!< EN : Enable counter/timer B7 to generate an interrupt based + on COMPR0 value. */ +} CTIMER_CTRL7_TMRB7IE0_Enum; + +/* ============================================= CTIMER CTRL7 TMRB7FN [22..24] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRB7FN */ + CTIMER_CTRL7_TMRB7FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0B7, stop. value. */ + CTIMER_CTRL7_TMRB7FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0B7, restart. value. */ + CTIMER_CTRL7_TMRB7FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B7, assert, + count to CMPR1B7, deassert, stop. value. */ + CTIMER_CTRL7_TMRB7FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B7, assert, count + to CMPR1B7, deassert, restart. value. */ + CTIMER_CTRL7_TMRB7FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL7_TMRB7FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL7_TMRB7FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL7_TMRB7FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL7_TMRB7FN_Enum; + +/* ============================================ CTIMER CTRL7 TMRB7CLK [17..21] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRB7CLK */ + CTIMER_CTRL7_TMRB7CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ + CTIMER_CTRL7_TMRB7CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL7_TMRB7CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL7_TMRB7CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL7_TMRB7CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL7_TMRB7CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL7_TMRB7CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL7_TMRB7CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL7_TMRB7CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL7_TMRB7CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL7_TMRB7CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL7_TMRB7CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL7_TMRB7CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL7_TMRB7CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL7_TMRB7CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL7_TMRB7CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL7_TMRB7CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL7_TMRB7CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL7_TMRB7CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL7_TMRB7CLK_CTMRA7 = 20, /*!< CTMRA7 : Clock source is CTIMERA7 OUT. value. */ + CTIMER_CTRL7_TMRB7CLK_CTMRA2 = 21, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ + CTIMER_CTRL7_TMRB7CLK_CTMRB2 = 22, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL7_TMRB7CLK_CTMRA0 = 23, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ + CTIMER_CTRL7_TMRB7CLK_CTMRB0 = 24, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL7_TMRB7CLK_CTMRB1 = 25, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL7_TMRB7CLK_CTMRB3 = 26, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL7_TMRB7CLK_CTMRB4 = 27, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL7_TMRB7CLK_CTMRB5 = 28, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL7_TMRB7CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL7_TMRB7CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL7_TMRB7CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL7_TMRB7CLK_Enum; + +/* ============================================= CTIMER CTRL7 TMRB7EN [16..16] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRB7EN */ + CTIMER_CTRL7_TMRB7EN_DIS = 0, /*!< DIS : Counter/Timer B7 Disable. value. */ + CTIMER_CTRL7_TMRB7EN_EN = 1, /*!< EN : Counter/Timer B7 Enable. value. */ +} CTIMER_CTRL7_TMRB7EN_Enum; + +/* ============================================ CTIMER CTRL7 TMRA7POL [12..12] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRA7POL */ + CTIMER_CTRL7_TMRA7POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA7 pin is the same as the + timer output. value. */ + CTIMER_CTRL7_TMRA7POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA7 pin is the inverse of + the timer output. value. */ +} CTIMER_CTRL7_TMRA7POL_Enum; + +/* ============================================ CTIMER CTRL7 TMRA7CLR [11..11] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRA7CLR */ + CTIMER_CTRL7_TMRA7CLR_RUN = 0, /*!< RUN : Allow counter/timer A7 to run value. */ + CTIMER_CTRL7_TMRA7CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A7 at 0x0000. value. */ +} CTIMER_CTRL7_TMRA7CLR_Enum; + +/* ============================================ CTIMER CTRL7 TMRA7IE1 [10..10] ============================================= */ +typedef enum { /*!< CTIMER_CTRL7_TMRA7IE1 */ + CTIMER_CTRL7_TMRA7IE1_DIS = 0, /*!< DIS : Disable counter/timer A7 from generating an interrupt + based on COMPR1. value. */ + CTIMER_CTRL7_TMRA7IE1_EN = 1, /*!< EN : Enable counter/timer A7 to generate an interrupt based + on COMPR1. value. */ +} CTIMER_CTRL7_TMRA7IE1_Enum; + +/* ============================================= CTIMER CTRL7 TMRA7IE0 [9..9] ============================================== */ +typedef enum { /*!< CTIMER_CTRL7_TMRA7IE0 */ + CTIMER_CTRL7_TMRA7IE0_DIS = 0, /*!< DIS : Disable counter/timer A7 from generating an interrupt + based on COMPR0. value. */ + CTIMER_CTRL7_TMRA7IE0_EN = 1, /*!< EN : Enable counter/timer A7 to generate an interrupt based + on COMPR0. value. */ +} CTIMER_CTRL7_TMRA7IE0_Enum; + +/* ============================================== CTIMER CTRL7 TMRA7FN [6..8] ============================================== */ +typedef enum { /*!< CTIMER_CTRL7_TMRA7FN */ + CTIMER_CTRL7_TMRA7FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count + to CMPR0A7, stop. value. */ + CTIMER_CTRL7_TMRA7FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide + pulses). Count to CMPR0A7, restart. value. */ + CTIMER_CTRL7_TMRA7FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A7, assert, + count to CMPR1A7, deassert, stop. value. */ + CTIMER_CTRL7_TMRA7FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A7, assert, count + to CMPR1A7, deassert, restart. value. */ + CTIMER_CTRL7_TMRA7FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ + CTIMER_CTRL7_TMRA7FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ + CTIMER_CTRL7_TMRA7FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. + value. */ + CTIMER_CTRL7_TMRA7FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ +} CTIMER_CTRL7_TMRA7FN_Enum; + +/* ============================================= CTIMER CTRL7 TMRA7CLK [1..5] ============================================== */ +typedef enum { /*!< CTIMER_CTRL7_TMRA7CLK */ + CTIMER_CTRL7_TMRA7CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ + CTIMER_CTRL7_TMRA7CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ + CTIMER_CTRL7_TMRA7CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ + CTIMER_CTRL7_TMRA7CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ + CTIMER_CTRL7_TMRA7CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ + CTIMER_CTRL7_TMRA7CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ + CTIMER_CTRL7_TMRA7CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ + CTIMER_CTRL7_TMRA7CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ + CTIMER_CTRL7_TMRA7CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ + CTIMER_CTRL7_TMRA7CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ + CTIMER_CTRL7_TMRA7CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ + CTIMER_CTRL7_TMRA7CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ + CTIMER_CTRL7_TMRA7CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ + CTIMER_CTRL7_TMRA7CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ + CTIMER_CTRL7_TMRA7CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. + value. */ + CTIMER_CTRL7_TMRA7CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ + CTIMER_CTRL7_TMRA7CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ + CTIMER_CTRL7_TMRA7CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ + CTIMER_CTRL7_TMRA7CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ + CTIMER_CTRL7_TMRA7CLK_CTMRB7 = 20, /*!< CTMRB7 : Clock source is CTIMERB7 OUT. value. */ + CTIMER_CTRL7_TMRA7CLK_CTMRA2 = 21, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ + CTIMER_CTRL7_TMRA7CLK_CTMRB2 = 22, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ + CTIMER_CTRL7_TMRA7CLK_CTMRA0 = 23, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ + CTIMER_CTRL7_TMRA7CLK_CTMRB0 = 24, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ + CTIMER_CTRL7_TMRA7CLK_CTMRB1 = 25, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ + CTIMER_CTRL7_TMRA7CLK_CTMRB3 = 26, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ + CTIMER_CTRL7_TMRA7CLK_CTMRB4 = 27, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ + CTIMER_CTRL7_TMRA7CLK_CTMRB5 = 28, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ + CTIMER_CTRL7_TMRA7CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ + CTIMER_CTRL7_TMRA7CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ + CTIMER_CTRL7_TMRA7CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ +} CTIMER_CTRL7_TMRA7CLK_Enum; + +/* ============================================== CTIMER CTRL7 TMRA7EN [0..0] ============================================== */ +typedef enum { /*!< CTIMER_CTRL7_TMRA7EN */ + CTIMER_CTRL7_TMRA7EN_DIS = 0, /*!< DIS : Counter/Timer A7 Disable. value. */ + CTIMER_CTRL7_TMRA7EN_EN = 1, /*!< EN : Counter/Timer A7 Enable. value. */ +} CTIMER_CTRL7_TMRA7EN_Enum; + +/* ======================================================= CMPRAUXA7 ======================================================= */ +/* ======================================================= CMPRAUXB7 ======================================================= */ +/* ========================================================= AUX7 ========================================================== */ +/* ============================================ CTIMER AUX7 TMRB7EN23 [30..30] ============================================= */ +typedef enum { /*!< CTIMER_AUX7_TMRB7EN23 */ + CTIMER_AUX7_TMRB7EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX7_TMRB7EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX7_TMRB7EN23_Enum; + +/* ============================================ CTIMER AUX7 TMRB7POL23 [29..29] ============================================ */ +typedef enum { /*!< CTIMER_AUX7_TMRB7POL23 */ + CTIMER_AUX7_TMRB7POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX7_TMRB7POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX7_TMRB7POL23_Enum; + +/* ============================================ CTIMER AUX7 TMRB7TINV [28..28] ============================================= */ +typedef enum { /*!< CTIMER_AUX7_TMRB7TINV */ + CTIMER_AUX7_TMRB7TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX7_TMRB7TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX7_TMRB7TINV_Enum; + +/* =========================================== CTIMER AUX7 TMRB7NOSYNC [27..27] ============================================ */ +typedef enum { /*!< CTIMER_AUX7_TMRB7NOSYNC */ + CTIMER_AUX7_TMRB7NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX7_TMRB7NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX7_TMRB7NOSYNC_Enum; + +/* ============================================ CTIMER AUX7 TMRB7TRIG [23..26] ============================================= */ +typedef enum { /*!< CTIMER_AUX7_TMRB7TRIG */ + CTIMER_AUX7_TMRB7TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX7_TMRB7TRIG_A7OUT = 1, /*!< A7OUT : Trigger source is CTIMERA7 OUT. value. */ + CTIMER_AUX7_TMRB7TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX7_TMRB7TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX7_TMRB7TRIG_A5OUT = 4, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ + CTIMER_AUX7_TMRB7TRIG_B5OUT = 5, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ + CTIMER_AUX7_TMRB7TRIG_A2OUT = 6, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ + CTIMER_AUX7_TMRB7TRIG_B2OUT = 7, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ + CTIMER_AUX7_TMRB7TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX7_TMRB7TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX7_TMRB7TRIG_A2OUT2 = 10, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ + CTIMER_AUX7_TMRB7TRIG_B2OUT2 = 11, /*!< B2OUT2 : Trigger source is CTIMERB2 OUT2. value. */ + CTIMER_AUX7_TMRB7TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX7_TMRB7TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ + CTIMER_AUX7_TMRB7TRIG_B1OUT2DUAL = 14, /*!< B1OUT2DUAL : Trigger source is CTIMERB1 OUT2, dual edge. value. */ + CTIMER_AUX7_TMRB7TRIG_A1OUT2DUAL = 15, /*!< A1OUT2DUAL : Trigger source is CTIMERA1 OUT2, dual edge. value. */ +} CTIMER_AUX7_TMRB7TRIG_Enum; + +/* ============================================ CTIMER AUX7 TMRA7EN23 [14..14] ============================================= */ +typedef enum { /*!< CTIMER_AUX7_TMRA7EN23 */ + CTIMER_AUX7_TMRA7EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ + CTIMER_AUX7_TMRA7EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ +} CTIMER_AUX7_TMRA7EN23_Enum; + +/* ============================================ CTIMER AUX7 TMRA7POL23 [13..13] ============================================ */ +typedef enum { /*!< CTIMER_AUX7_TMRA7POL23 */ + CTIMER_AUX7_TMRA7POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ + CTIMER_AUX7_TMRA7POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ +} CTIMER_AUX7_TMRA7POL23_Enum; + +/* ============================================ CTIMER AUX7 TMRA7TINV [12..12] ============================================= */ +typedef enum { /*!< CTIMER_AUX7_TMRA7TINV */ + CTIMER_AUX7_TMRA7TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ + CTIMER_AUX7_TMRA7TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ +} CTIMER_AUX7_TMRA7TINV_Enum; + +/* =========================================== CTIMER AUX7 TMRA7NOSYNC [11..11] ============================================ */ +typedef enum { /*!< CTIMER_AUX7_TMRA7NOSYNC */ + CTIMER_AUX7_TMRA7NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ + CTIMER_AUX7_TMRA7NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ +} CTIMER_AUX7_TMRA7NOSYNC_Enum; + +/* ============================================= CTIMER AUX7 TMRA7TRIG [7..10] ============================================= */ +typedef enum { /*!< CTIMER_AUX7_TMRA7TRIG */ + CTIMER_AUX7_TMRA7TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ + CTIMER_AUX7_TMRA7TRIG_B7OUT = 1, /*!< B7OUT : Trigger source is CTIMERB7 OUT. value. */ + CTIMER_AUX7_TMRA7TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ + CTIMER_AUX7_TMRA7TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ + CTIMER_AUX7_TMRA7TRIG_A1OUT = 4, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ + CTIMER_AUX7_TMRA7TRIG_B1OUT = 5, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ + CTIMER_AUX7_TMRA7TRIG_A4OUT = 6, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ + CTIMER_AUX7_TMRA7TRIG_B4OUT = 7, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ + CTIMER_AUX7_TMRA7TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ + CTIMER_AUX7_TMRA7TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ + CTIMER_AUX7_TMRA7TRIG_A2OUT2 = 10, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ + CTIMER_AUX7_TMRA7TRIG_B2OUT2 = 11, /*!< B2OUT2 : Trigger source is CTIMERB2 OUT2. value. */ + CTIMER_AUX7_TMRA7TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ + CTIMER_AUX7_TMRA7TRIG_A5OUT2DUAL = 13, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ + CTIMER_AUX7_TMRA7TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ + CTIMER_AUX7_TMRA7TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ +} CTIMER_AUX7_TMRA7TRIG_Enum; + +/* ======================================================== GLOBEN ========================================================= */ +/* ============================================== CTIMER GLOBEN ENB7 [15..15] ============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENB7 */ + CTIMER_GLOBEN_ENB7_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENB7_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENB7_Enum; + +/* ============================================== CTIMER GLOBEN ENA7 [14..14] ============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENA7 */ + CTIMER_GLOBEN_ENA7_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENA7_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENA7_Enum; + +/* ============================================== CTIMER GLOBEN ENB6 [13..13] ============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENB6 */ + CTIMER_GLOBEN_ENB6_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENB6_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENB6_Enum; + +/* ============================================== CTIMER GLOBEN ENA6 [12..12] ============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENA6 */ + CTIMER_GLOBEN_ENA6_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENA6_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENA6_Enum; + +/* ============================================== CTIMER GLOBEN ENB5 [11..11] ============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENB5 */ + CTIMER_GLOBEN_ENB5_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENB5_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENB5_Enum; + +/* ============================================== CTIMER GLOBEN ENA5 [10..10] ============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENA5 */ + CTIMER_GLOBEN_ENA5_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENA5_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENA5_Enum; + +/* =============================================== CTIMER GLOBEN ENB4 [9..9] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENB4 */ + CTIMER_GLOBEN_ENB4_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENB4_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENB4_Enum; + +/* =============================================== CTIMER GLOBEN ENA4 [8..8] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENA4 */ + CTIMER_GLOBEN_ENA4_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENA4_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENA4_Enum; + +/* =============================================== CTIMER GLOBEN ENB3 [7..7] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENB3 */ + CTIMER_GLOBEN_ENB3_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENB3_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENB3_Enum; + +/* =============================================== CTIMER GLOBEN ENA3 [6..6] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENA3 */ + CTIMER_GLOBEN_ENA3_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENA3_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENA3_Enum; + +/* =============================================== CTIMER GLOBEN ENB2 [5..5] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENB2 */ + CTIMER_GLOBEN_ENB2_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENB2_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENB2_Enum; + +/* =============================================== CTIMER GLOBEN ENA2 [4..4] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENA2 */ + CTIMER_GLOBEN_ENA2_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENA2_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENA2_Enum; + +/* =============================================== CTIMER GLOBEN ENB1 [3..3] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENB1 */ + CTIMER_GLOBEN_ENB1_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENB1_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENB1_Enum; + +/* =============================================== CTIMER GLOBEN ENA1 [2..2] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENA1 */ + CTIMER_GLOBEN_ENA1_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENA1_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENA1_Enum; + +/* =============================================== CTIMER GLOBEN ENB0 [1..1] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENB0 */ + CTIMER_GLOBEN_ENB0_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENB0_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENB0_Enum; + +/* =============================================== CTIMER GLOBEN ENA0 [0..0] =============================================== */ +typedef enum { /*!< CTIMER_GLOBEN_ENA0 */ + CTIMER_GLOBEN_ENA0_LCO = 1, /*!< LCO : Use local enable. value. */ + CTIMER_GLOBEN_ENA0_DIS = 0, /*!< DIS : Disable CTIMER. value. */ +} CTIMER_GLOBEN_ENA0_Enum; + +/* ======================================================== OUTCFG0 ======================================================== */ +/* ============================================= CTIMER OUTCFG0 CFG9 [28..30] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG9 */ + CTIMER_OUTCFG0_CFG9_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG9_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG9_B0OUT = 5, /*!< B0OUT : Output is B0OUT. value. */ + CTIMER_OUTCFG0_CFG9_A4OUT = 4, /*!< A4OUT : Output is A4OUT. value. */ + CTIMER_OUTCFG0_CFG9_A2OUT = 3, /*!< A2OUT : Output is A2OUT. value. */ + CTIMER_OUTCFG0_CFG9_A2OUT2 = 2, /*!< A2OUT2 : Output is A2OUT2 value. */ + CTIMER_OUTCFG0_CFG9_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG9_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG9_Enum; + +/* ============================================= CTIMER OUTCFG0 CFG8 [25..27] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG8 */ + CTIMER_OUTCFG0_CFG8_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG8_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG8_B6OUT = 5, /*!< B6OUT : Output is B6OUT. value. */ + CTIMER_OUTCFG0_CFG8_A4OUT2 = 4, /*!< A4OUT2 : Output is A4OUT2. value. */ + CTIMER_OUTCFG0_CFG8_A3OUT2 = 3, /*!< A3OUT2 : Output is A3OUT. value. */ + CTIMER_OUTCFG0_CFG8_A2OUT = 2, /*!< A2OUT : Output is A2OUT value. */ + CTIMER_OUTCFG0_CFG8_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG8_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG8_Enum; + +/* ============================================= CTIMER OUTCFG0 CFG7 [22..24] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG7 */ + CTIMER_OUTCFG0_CFG7_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG7_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG7_A7OUT = 5, /*!< A7OUT : Output is A7OUT. value. */ + CTIMER_OUTCFG0_CFG7_B5OUT = 4, /*!< B5OUT : Output is B5OUT. value. */ + CTIMER_OUTCFG0_CFG7_B1OUT = 3, /*!< B1OUT : Output is B1OUT. value. */ + CTIMER_OUTCFG0_CFG7_B1OUT2 = 2, /*!< B1OUT2 : Output is B1OUT2 value. */ + CTIMER_OUTCFG0_CFG7_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG7_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG7_Enum; + +/* ============================================= CTIMER OUTCFG0 CFG6 [19..21] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG6 */ + CTIMER_OUTCFG0_CFG6_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG6_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG6_B7OUT = 5, /*!< B7OUT : Output is B7OUT. value. */ + CTIMER_OUTCFG0_CFG6_B5OUT2 = 4, /*!< B5OUT2 : Output is B5OUT2. value. */ + CTIMER_OUTCFG0_CFG6_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ + CTIMER_OUTCFG0_CFG6_B1OUT = 2, /*!< B1OUT : Output is B1OUT value. */ + CTIMER_OUTCFG0_CFG6_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG6_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG6_Enum; + +/* ============================================= CTIMER OUTCFG0 CFG5 [16..18] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG5 */ + CTIMER_OUTCFG0_CFG5_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG5_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG5_A7OUT = 5, /*!< A7OUT : Output is A7OUT. value. */ + CTIMER_OUTCFG0_CFG5_B6OUT = 4, /*!< B6OUT : Output is A5OUT. value. */ + CTIMER_OUTCFG0_CFG5_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ + CTIMER_OUTCFG0_CFG5_A1OUT2 = 2, /*!< A1OUT2 : Output is A1OUT2 value. */ + CTIMER_OUTCFG0_CFG5_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG5_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG5_Enum; + +/* ============================================= CTIMER OUTCFG0 CFG4 [12..14] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG4 */ + CTIMER_OUTCFG0_CFG4_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG4_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG4_B5OUT = 5, /*!< B5OUT : Output is B5OUT. value. */ + CTIMER_OUTCFG0_CFG4_A5OUT2 = 4, /*!< A5OUT2 : Output is A5OUT2. value. */ + CTIMER_OUTCFG0_CFG4_A2OUT2 = 3, /*!< A2OUT2 : Output is A2OUT2. value. */ + CTIMER_OUTCFG0_CFG4_A1OUT = 2, /*!< A1OUT : Output is A1OUT value. */ + CTIMER_OUTCFG0_CFG4_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG4_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG4_Enum; + +/* ============================================== CTIMER OUTCFG0 CFG3 [9..11] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG3 */ + CTIMER_OUTCFG0_CFG3_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG3_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG3_A6OUT = 5, /*!< A6OUT : Output is A6OUT. value. */ + CTIMER_OUTCFG0_CFG3_A1OUT = 4, /*!< A1OUT : Output is A1OUT. value. */ + CTIMER_OUTCFG0_CFG3_B0OUT = 3, /*!< B0OUT : Output is B0OUT. value. */ + CTIMER_OUTCFG0_CFG3_B0OUT2 = 2, /*!< B0OUT2 : Output is B0OUT2 value. */ + CTIMER_OUTCFG0_CFG3_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG3_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG3_Enum; + +/* ============================================== CTIMER OUTCFG0 CFG2 [6..8] =============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG2 */ + CTIMER_OUTCFG0_CFG2_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG2_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG2_A7OUT = 5, /*!< A7OUT : Output is A7OUT. value. */ + CTIMER_OUTCFG0_CFG2_B6OUT2 = 4, /*!< B6OUT2 : Output is B6OUT2. value. */ + CTIMER_OUTCFG0_CFG2_B1OUT2 = 3, /*!< B1OUT2 : Output is B1OUT2. value. */ + CTIMER_OUTCFG0_CFG2_B0OUT = 2, /*!< B0OUT : Output is B0OUT value. */ + CTIMER_OUTCFG0_CFG2_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG2_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG2_Enum; + +/* ============================================== CTIMER OUTCFG0 CFG1 [3..5] =============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG1 */ + CTIMER_OUTCFG0_CFG1_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG1_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG1_B7OUT2 = 5, /*!< B7OUT2 : Output is B7OUT2. value. */ + CTIMER_OUTCFG0_CFG1_A5OUT = 4, /*!< A5OUT : Output is A5OUT. value. */ + CTIMER_OUTCFG0_CFG1_A0OUT = 3, /*!< A0OUT : Output is A0OUT. value. */ + CTIMER_OUTCFG0_CFG1_A0OUT2 = 2, /*!< A0OUT2 : Output is A0OUT2 value. */ + CTIMER_OUTCFG0_CFG1_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG1_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG1_Enum; + +/* ============================================== CTIMER OUTCFG0 CFG0 [0..2] =============================================== */ +typedef enum { /*!< CTIMER_OUTCFG0_CFG0 */ + CTIMER_OUTCFG0_CFG0_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG0_CFG0_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG0_CFG0_A6OUT = 5, /*!< A6OUT : Output is A6OUT. value. */ + CTIMER_OUTCFG0_CFG0_A5OUT2 = 4, /*!< A5OUT2 : Output is A5OUT2. value. */ + CTIMER_OUTCFG0_CFG0_B2OUT2 = 3, /*!< B2OUT2 : Output is B2OUT2. value. */ + CTIMER_OUTCFG0_CFG0_A0OUT = 2, /*!< A0OUT : Output is A0OUT value. */ + CTIMER_OUTCFG0_CFG0_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG0_CFG0_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG0_CFG0_Enum; + +/* ======================================================== OUTCFG1 ======================================================== */ +/* ============================================= CTIMER OUTCFG1 CFG19 [28..30] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG19 */ + CTIMER_OUTCFG1_CFG19_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG19_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG19_B1OUT2 = 5, /*!< B1OUT2 : Output is B1OUT2. value. */ + CTIMER_OUTCFG1_CFG19_B4OUT = 4, /*!< B4OUT : Output is B4OUT. value. */ + CTIMER_OUTCFG1_CFG19_A2OUT = 3, /*!< A2OUT : Output is A2OUT. value. */ + CTIMER_OUTCFG1_CFG19_B4OUT2 = 2, /*!< B4OUT2 : Output is B4OUT2 value. */ + CTIMER_OUTCFG1_CFG19_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG19_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG19_Enum; + +/* ============================================= CTIMER OUTCFG1 CFG18 [25..27] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG18 */ + CTIMER_OUTCFG1_CFG18_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG18_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG18_A3OUT2 = 5, /*!< A3OUT2 : Output is A3OUT2. value. */ + CTIMER_OUTCFG1_CFG18_A0OUT = 4, /*!< A0OUT : Output is A0OUT. value. */ + CTIMER_OUTCFG1_CFG18_B0OUT = 3, /*!< B0OUT : Output is B0OUT. value. */ + CTIMER_OUTCFG1_CFG18_B4OUT = 2, /*!< B4OUT : Output is B4OUT value. */ + CTIMER_OUTCFG1_CFG18_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG18_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG18_Enum; + +/* ============================================= CTIMER OUTCFG1 CFG17 [22..24] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG17 */ + CTIMER_OUTCFG1_CFG17_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG17_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG17_A1OUT2 = 5, /*!< A1OUT2 : Output is A1OUT2. value. */ + CTIMER_OUTCFG1_CFG17_A4OUT = 4, /*!< A4OUT : Output is A4OUT. value. */ + CTIMER_OUTCFG1_CFG17_B7OUT = 3, /*!< B7OUT : Output is B7OUT. value. */ + CTIMER_OUTCFG1_CFG17_A4OUT2 = 2, /*!< A4OUT2 : Output is A4OUT2 value. */ + CTIMER_OUTCFG1_CFG17_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG17_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG17_Enum; + +/* ============================================= CTIMER OUTCFG1 CFG16 [19..21] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG16 */ + CTIMER_OUTCFG1_CFG16_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG16_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG16_B3OUT2 = 5, /*!< B3OUT2 : Output is B3OUT2. value. */ + CTIMER_OUTCFG1_CFG16_A0OUT2 = 4, /*!< A0OUT2 : Output is A0OUT2. value. */ + CTIMER_OUTCFG1_CFG16_A0OUT = 3, /*!< A0OUT : Output is A0OUT. value. */ + CTIMER_OUTCFG1_CFG16_A4OUT = 2, /*!< A4OUT : Output is A4OUT value. */ + CTIMER_OUTCFG1_CFG16_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG16_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG16_Enum; + +/* ============================================= CTIMER OUTCFG1 CFG15 [16..18] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG15 */ + CTIMER_OUTCFG1_CFG15_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG15_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG15_A4OUT2 = 5, /*!< A4OUT2 : Output is A4OUT2. value. */ + CTIMER_OUTCFG1_CFG15_A7OUT = 4, /*!< A7OUT : Output is B1OUT. value. */ + CTIMER_OUTCFG1_CFG15_B3OUT = 3, /*!< B3OUT : Output is B3OUT. value. */ + CTIMER_OUTCFG1_CFG15_B3OUT2 = 2, /*!< B3OUT2 : Output is B3OUT2 value. */ + CTIMER_OUTCFG1_CFG15_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG15_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG15_Enum; + +/* ============================================= CTIMER OUTCFG1 CFG14 [12..14] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG14 */ + CTIMER_OUTCFG1_CFG14_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG14_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG14_A7OUT = 5, /*!< A7OUT : Output is A7OUT. value. */ + CTIMER_OUTCFG1_CFG14_B7OUT2 = 4, /*!< B7OUT2 : Output is B7OUT2. value. */ + CTIMER_OUTCFG1_CFG14_B1OUT = 3, /*!< B1OUT : Output is B1OUT. value. */ + CTIMER_OUTCFG1_CFG14_B3OUT = 2, /*!< B3OUT : Output is B3OUT value. */ + CTIMER_OUTCFG1_CFG14_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG14_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG14_Enum; + +/* ============================================= CTIMER OUTCFG1 CFG13 [9..11] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG13 */ + CTIMER_OUTCFG1_CFG13_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG13_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG13_B4OUT2 = 5, /*!< B4OUT2 : Output is B4OUT2. value. */ + CTIMER_OUTCFG1_CFG13_A6OUT = 4, /*!< A6OUT : Output is B1OUT. value. */ + CTIMER_OUTCFG1_CFG13_A3OUT = 3, /*!< A3OUT : Output is A3OUT. value. */ + CTIMER_OUTCFG1_CFG13_A3OUT2 = 2, /*!< A3OUT2 : Output is A3OUT2 value. */ + CTIMER_OUTCFG1_CFG13_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG13_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG13_Enum; + +/* ============================================== CTIMER OUTCFG1 CFG12 [6..8] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG12 */ + CTIMER_OUTCFG1_CFG12_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG12_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG12_B6OUT2 = 5, /*!< B6OUT2 : Output is B6OUT2. value. */ + CTIMER_OUTCFG1_CFG12_B0OUT2 = 4, /*!< B0OUT2 : Output is B0OUT2. value. */ + CTIMER_OUTCFG1_CFG12_B1OUT = 3, /*!< B1OUT : Output is B1OUT. value. */ + CTIMER_OUTCFG1_CFG12_A3OUT = 2, /*!< A3OUT : Output is A3OUT value. */ + CTIMER_OUTCFG1_CFG12_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG12_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG12_Enum; + +/* ============================================== CTIMER OUTCFG1 CFG11 [3..5] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG11 */ + CTIMER_OUTCFG1_CFG11_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG11_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG11_B5OUT2 = 5, /*!< B5OUT2 : Output is B5OUT2. value. */ + CTIMER_OUTCFG1_CFG11_B4OUT = 4, /*!< B4OUT : Output is B4OUT. value. */ + CTIMER_OUTCFG1_CFG11_B2OUT = 3, /*!< B2OUT : Output is B2OUT. value. */ + CTIMER_OUTCFG1_CFG11_B2OUT2 = 2, /*!< B2OUT2 : Output is B2OUT2 value. */ + CTIMER_OUTCFG1_CFG11_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG11_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG11_Enum; + +/* ============================================== CTIMER OUTCFG1 CFG10 [0..2] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG1_CFG10 */ + CTIMER_OUTCFG1_CFG10_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG1_CFG10_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG1_CFG10_A6OUT = 5, /*!< A6OUT : Output is A6OUT. value. */ + CTIMER_OUTCFG1_CFG10_B4OUT2 = 4, /*!< B4OUT2 : Output is B4OUT2. value. */ + CTIMER_OUTCFG1_CFG10_B3OUT2 = 3, /*!< B3OUT2 : Output is B3OUT2. value. */ + CTIMER_OUTCFG1_CFG10_B2OUT = 2, /*!< B2OUT : Output is B2OUT value. */ + CTIMER_OUTCFG1_CFG10_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG1_CFG10_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG1_CFG10_Enum; + +/* ======================================================== OUTCFG2 ======================================================== */ +/* ============================================= CTIMER OUTCFG2 CFG29 [28..30] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG29 */ + CTIMER_OUTCFG2_CFG29_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG29_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG29_A3OUT2 = 5, /*!< A3OUT2 : Output is A3OUT2. value. */ + CTIMER_OUTCFG2_CFG29_A7OUT = 4, /*!< A7OUT : Output is A7OUT. value. */ + CTIMER_OUTCFG2_CFG29_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ + CTIMER_OUTCFG2_CFG29_B5OUT2 = 2, /*!< B5OUT2 : Output is B5OUT2 value. */ + CTIMER_OUTCFG2_CFG29_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG29_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG29_Enum; + +/* ============================================= CTIMER OUTCFG2 CFG28 [25..27] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG28 */ + CTIMER_OUTCFG2_CFG28_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG28_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG28_B0OUT2 = 5, /*!< B0OUT2 : Output is B0OUT2. value. */ + CTIMER_OUTCFG2_CFG28_A5OUT2 = 4, /*!< A5OUT2 : Output is A5OUT2. value. */ + CTIMER_OUTCFG2_CFG28_A3OUT = 3, /*!< A3OUT : Output is A3OUT. value. */ + CTIMER_OUTCFG2_CFG28_A7OUT = 2, /*!< A7OUT : Output is A7OUT value. */ + CTIMER_OUTCFG2_CFG28_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG28_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG28_Enum; + +/* ============================================= CTIMER OUTCFG2 CFG27 [22..24] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG27 */ + CTIMER_OUTCFG2_CFG27_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG27_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG27_B2OUT2 = 5, /*!< B2OUT2 : Output is B2OUT2. value. */ + CTIMER_OUTCFG2_CFG27_B6OUT = 4, /*!< B6OUT : Output is B6OUT. value. */ + CTIMER_OUTCFG2_CFG27_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ + CTIMER_OUTCFG2_CFG27_B6OUT2 = 2, /*!< B6OUT2 : Output is B6OUT2 value. */ + CTIMER_OUTCFG2_CFG27_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG27_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG27_Enum; + +/* ============================================= CTIMER OUTCFG2 CFG26 [19..21] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG26 */ + CTIMER_OUTCFG2_CFG26_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG26_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG26_A1OUT2 = 5, /*!< A1OUT2 : Output is A1OUT2. value. */ + CTIMER_OUTCFG2_CFG26_A5OUT = 4, /*!< A5OUT : Output is A5OUT. value. */ + CTIMER_OUTCFG2_CFG26_B2OUT = 3, /*!< B2OUT : Output is B2OUT. value. */ + CTIMER_OUTCFG2_CFG26_B6OUT = 2, /*!< B6OUT : Output is B6OUT value. */ + CTIMER_OUTCFG2_CFG26_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG26_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG26_Enum; + +/* ============================================= CTIMER OUTCFG2 CFG25 [16..18] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG25 */ + CTIMER_OUTCFG2_CFG25_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG25_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG25_A2OUT2 = 5, /*!< A2OUT2 : Output is A2OUT2. value. */ + CTIMER_OUTCFG2_CFG25_A6OUT = 4, /*!< A6OUT : Output is A6OUT. value. */ + CTIMER_OUTCFG2_CFG25_B2OUT = 3, /*!< B2OUT : Output is B2OUT. value. */ + CTIMER_OUTCFG2_CFG25_B4OUT2 = 2, /*!< B4OUT2 : Output is B4OUT2 value. */ + CTIMER_OUTCFG2_CFG25_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG25_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG25_Enum; + +/* ============================================= CTIMER OUTCFG2 CFG24 [12..14] ============================================= */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG24 */ + CTIMER_OUTCFG2_CFG24_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG24_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG24_B1OUT2 = 5, /*!< B1OUT2 : Output is B1OUT2. value. */ + CTIMER_OUTCFG2_CFG24_A1OUT = 4, /*!< A1OUT : Output is A1OUT. value. */ + CTIMER_OUTCFG2_CFG24_A2OUT = 3, /*!< A2OUT : Output is A2OUT. value. */ + CTIMER_OUTCFG2_CFG24_A6OUT = 2, /*!< A6OUT : Output is A6OUT value. */ + CTIMER_OUTCFG2_CFG24_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG24_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG24_Enum; + +/* ============================================= CTIMER OUTCFG2 CFG23 [9..11] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG23 */ + CTIMER_OUTCFG2_CFG23_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG23_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG23_B0OUT2 = 5, /*!< B0OUT2 : Output is B0OUT2. value. */ + CTIMER_OUTCFG2_CFG23_A5OUT = 4, /*!< A5OUT : Output is A5OUT. value. */ + CTIMER_OUTCFG2_CFG23_A7OUT = 3, /*!< A7OUT : Output is B1OUT. value. */ + CTIMER_OUTCFG2_CFG23_B5OUT2 = 2, /*!< B5OUT2 : Output is B5OUT2 value. */ + CTIMER_OUTCFG2_CFG23_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG23_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG23_Enum; + +/* ============================================== CTIMER OUTCFG2 CFG22 [6..8] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG22 */ + CTIMER_OUTCFG2_CFG22_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG22_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG22_A2OUT2 = 5, /*!< A2OUT2 : Output is A2OUT2. value. */ + CTIMER_OUTCFG2_CFG22_A1OUT = 4, /*!< A1OUT : Output is A1OUT. value. */ + CTIMER_OUTCFG2_CFG22_A6OUT = 3, /*!< A6OUT : Output is B1OUT. value. */ + CTIMER_OUTCFG2_CFG22_B5OUT = 2, /*!< B5OUT : Output is B5OUT value. */ + CTIMER_OUTCFG2_CFG22_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG22_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG22_Enum; + +/* ============================================== CTIMER OUTCFG2 CFG21 [3..5] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG21 */ + CTIMER_OUTCFG2_CFG21_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG21_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG21_A0OUT2 = 5, /*!< A0OUT2 : Output is A0OUT2. value. */ + CTIMER_OUTCFG2_CFG21_B5OUT = 4, /*!< B5OUT : Output is B5OUT. value. */ + CTIMER_OUTCFG2_CFG21_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ + CTIMER_OUTCFG2_CFG21_A5OUT2 = 2, /*!< A5OUT2 : Output is A5OUT2 value. */ + CTIMER_OUTCFG2_CFG21_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG21_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG21_Enum; + +/* ============================================== CTIMER OUTCFG2 CFG20 [0..2] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG2_CFG20 */ + CTIMER_OUTCFG2_CFG20_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG2_CFG20_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG2_CFG20_B2OUT2 = 5, /*!< B2OUT2 : Output is B2OUT2. value. */ + CTIMER_OUTCFG2_CFG20_A1OUT2 = 4, /*!< A1OUT2 : Output is A1OUT2. value. */ + CTIMER_OUTCFG2_CFG20_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ + CTIMER_OUTCFG2_CFG20_A5OUT = 2, /*!< A5OUT : Output is A5OUT value. */ + CTIMER_OUTCFG2_CFG20_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG2_CFG20_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG2_CFG20_Enum; + +/* ======================================================== OUTCFG3 ======================================================== */ +/* ============================================== CTIMER OUTCFG3 CFG31 [3..5] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG3_CFG31 */ + CTIMER_OUTCFG3_CFG31_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG3_CFG31_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG3_CFG31_B3OUT2 = 5, /*!< B3OUT2 : Output is B3OUT2. value. */ + CTIMER_OUTCFG3_CFG31_B7OUT = 4, /*!< B7OUT : Output is B7OUT. value. */ + CTIMER_OUTCFG3_CFG31_A6OUT = 3, /*!< A6OUT : Output is A6OUT. value. */ + CTIMER_OUTCFG3_CFG31_B7OUT2 = 2, /*!< B7OUT2 : Output is B7OUT2 value. */ + CTIMER_OUTCFG3_CFG31_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG3_CFG31_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG3_CFG31_Enum; + +/* ============================================== CTIMER OUTCFG3 CFG30 [0..2] ============================================== */ +typedef enum { /*!< CTIMER_OUTCFG3_CFG30 */ + CTIMER_OUTCFG3_CFG30_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ + CTIMER_OUTCFG3_CFG30_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ + CTIMER_OUTCFG3_CFG30_A0OUT2 = 5, /*!< A0OUT2 : Output is A0OUT2. value. */ + CTIMER_OUTCFG3_CFG30_A4OUT2 = 4, /*!< A4OUT2 : Output is A4OUT2. value. */ + CTIMER_OUTCFG3_CFG30_B3OUT = 3, /*!< B3OUT : Output is B3OUT. value. */ + CTIMER_OUTCFG3_CFG30_B7OUT = 2, /*!< B7OUT : Output is B7OUT value. */ + CTIMER_OUTCFG3_CFG30_ONE = 1, /*!< ONE : Force output to 1. value. */ + CTIMER_OUTCFG3_CFG30_ZERO = 0, /*!< ZERO : Force output to 0 value. */ +} CTIMER_OUTCFG3_CFG30_Enum; + +/* ========================================================= INCFG ========================================================= */ +/* ============================================== CTIMER INCFG CFGB7 [15..15] ============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGB7 */ + CTIMER_INCFG_CFGB7_CT31 = 1, /*!< CT31 : Input is CT31 value. */ + CTIMER_INCFG_CFGB7_CT30 = 0, /*!< CT30 : Input is CT30 value. */ +} CTIMER_INCFG_CFGB7_Enum; + +/* ============================================== CTIMER INCFG CFGA7 [14..14] ============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGA7 */ + CTIMER_INCFG_CFGA7_CT29 = 1, /*!< CT29 : Input is CT29 value. */ + CTIMER_INCFG_CFGA7_CT28 = 0, /*!< CT28 : Input is CT28 value. */ +} CTIMER_INCFG_CFGA7_Enum; + +/* ============================================== CTIMER INCFG CFGB6 [13..13] ============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGB6 */ + CTIMER_INCFG_CFGB6_CT27 = 1, /*!< CT27 : Input is CT27 value. */ + CTIMER_INCFG_CFGB6_CT26 = 0, /*!< CT26 : Input is CT26 value. */ +} CTIMER_INCFG_CFGB6_Enum; + +/* ============================================== CTIMER INCFG CFGA6 [12..12] ============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGA6 */ + CTIMER_INCFG_CFGA6_CT25 = 1, /*!< CT25 : Input is CT25 value. */ + CTIMER_INCFG_CFGA6_CT24 = 0, /*!< CT24 : Input is CT24 value. */ +} CTIMER_INCFG_CFGA6_Enum; + +/* ============================================== CTIMER INCFG CFGB5 [11..11] ============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGB5 */ + CTIMER_INCFG_CFGB5_CT23 = 1, /*!< CT23 : Input is CT23 value. */ + CTIMER_INCFG_CFGB5_CT22 = 0, /*!< CT22 : Input is CT22 value. */ +} CTIMER_INCFG_CFGB5_Enum; + +/* ============================================== CTIMER INCFG CFGA5 [10..10] ============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGA5 */ + CTIMER_INCFG_CFGA5_CT21 = 1, /*!< CT21 : Input is CT21 value. */ + CTIMER_INCFG_CFGA5_CT20 = 0, /*!< CT20 : Input is CT20 value. */ +} CTIMER_INCFG_CFGA5_Enum; + +/* =============================================== CTIMER INCFG CFGB4 [9..9] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGB4 */ + CTIMER_INCFG_CFGB4_CT19 = 1, /*!< CT19 : Input is CT19 value. */ + CTIMER_INCFG_CFGB4_CT18 = 0, /*!< CT18 : Input is CT18 value. */ +} CTIMER_INCFG_CFGB4_Enum; + +/* =============================================== CTIMER INCFG CFGA4 [8..8] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGA4 */ + CTIMER_INCFG_CFGA4_CT17 = 1, /*!< CT17 : Input is CT17 value. */ + CTIMER_INCFG_CFGA4_CT16 = 0, /*!< CT16 : Input is CT16 value. */ +} CTIMER_INCFG_CFGA4_Enum; + +/* =============================================== CTIMER INCFG CFGB3 [7..7] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGB3 */ + CTIMER_INCFG_CFGB3_CT15 = 1, /*!< CT15 : Input is CT15 value. */ + CTIMER_INCFG_CFGB3_CT14 = 0, /*!< CT14 : Input is CT14 value. */ +} CTIMER_INCFG_CFGB3_Enum; + +/* =============================================== CTIMER INCFG CFGA3 [6..6] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGA3 */ + CTIMER_INCFG_CFGA3_CT13 = 1, /*!< CT13 : Input is CT13 value. */ + CTIMER_INCFG_CFGA3_CT12 = 0, /*!< CT12 : Input is CT12 value. */ +} CTIMER_INCFG_CFGA3_Enum; + +/* =============================================== CTIMER INCFG CFGB2 [5..5] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGB2 */ + CTIMER_INCFG_CFGB2_CT11 = 1, /*!< CT11 : Input is CT11 value. */ + CTIMER_INCFG_CFGB2_CT10 = 0, /*!< CT10 : Input is CT10 value. */ +} CTIMER_INCFG_CFGB2_Enum; + +/* =============================================== CTIMER INCFG CFGA2 [4..4] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGA2 */ + CTIMER_INCFG_CFGA2_CT9 = 1, /*!< CT9 : Input is CT9 value. */ + CTIMER_INCFG_CFGA2_CT8 = 0, /*!< CT8 : Input is CT8 value. */ +} CTIMER_INCFG_CFGA2_Enum; + +/* =============================================== CTIMER INCFG CFGB1 [3..3] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGB1 */ + CTIMER_INCFG_CFGB1_CT7 = 1, /*!< CT7 : Input is CT7 value. */ + CTIMER_INCFG_CFGB1_CT6 = 0, /*!< CT6 : Input is CT6 value. */ +} CTIMER_INCFG_CFGB1_Enum; + +/* =============================================== CTIMER INCFG CFGA1 [2..2] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGA1 */ + CTIMER_INCFG_CFGA1_CT5 = 1, /*!< CT5 : Input is CT5 value. */ + CTIMER_INCFG_CFGA1_CT4 = 0, /*!< CT4 : Input is CT4 value. */ +} CTIMER_INCFG_CFGA1_Enum; + +/* =============================================== CTIMER INCFG CFGB0 [1..1] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGB0 */ + CTIMER_INCFG_CFGB0_CT3 = 1, /*!< CT3 : Input is CT3 value. */ + CTIMER_INCFG_CFGB0_CT2 = 0, /*!< CT2 : Input is CT2 value. */ +} CTIMER_INCFG_CFGB0_Enum; + +/* =============================================== CTIMER INCFG CFGA0 [0..0] =============================================== */ +typedef enum { /*!< CTIMER_INCFG_CFGA0 */ + CTIMER_INCFG_CFGA0_CT1 = 1, /*!< CT1 : Input is CT1 value. */ + CTIMER_INCFG_CFGA0_CT0 = 0, /*!< CT0 : Input is CT0 value. */ +} CTIMER_INCFG_CFGA0_Enum; + +/* ========================================================= STCFG ========================================================= */ +/* ============================================= CTIMER STCFG FREEZE [31..31] ============================================== */ +typedef enum { /*!< CTIMER_STCFG_FREEZE */ + CTIMER_STCFG_FREEZE_THAW = 0, /*!< THAW : Let the COUNTER register run on its input clock. value. */ + CTIMER_STCFG_FREEZE_FREEZE = 1, /*!< FREEZE : Stop the COUNTER register for loading. value. */ +} CTIMER_STCFG_FREEZE_Enum; + +/* ============================================== CTIMER STCFG CLEAR [30..30] ============================================== */ +typedef enum { /*!< CTIMER_STCFG_CLEAR */ + CTIMER_STCFG_CLEAR_RUN = 0, /*!< RUN : Let the COUNTER register run on its input clock. value. */ + CTIMER_STCFG_CLEAR_CLEAR = 1, /*!< CLEAR : Stop the COUNTER register for loading. value. */ +} CTIMER_STCFG_CLEAR_Enum; + +/* ========================================== CTIMER STCFG COMPARE_H_EN [15..15] =========================================== */ +typedef enum { /*!< CTIMER_STCFG_COMPARE_H_EN */ + CTIMER_STCFG_COMPARE_H_EN_DISABLE = 0, /*!< DISABLE : Compare H disabled. value. */ + CTIMER_STCFG_COMPARE_H_EN_ENABLE = 1, /*!< ENABLE : Compare H enabled. value. */ +} CTIMER_STCFG_COMPARE_H_EN_Enum; + +/* ========================================== CTIMER STCFG COMPARE_G_EN [14..14] =========================================== */ +typedef enum { /*!< CTIMER_STCFG_COMPARE_G_EN */ + CTIMER_STCFG_COMPARE_G_EN_DISABLE = 0, /*!< DISABLE : Compare G disabled. value. */ + CTIMER_STCFG_COMPARE_G_EN_ENABLE = 1, /*!< ENABLE : Compare G enabled. value. */ +} CTIMER_STCFG_COMPARE_G_EN_Enum; + +/* ========================================== CTIMER STCFG COMPARE_F_EN [13..13] =========================================== */ +typedef enum { /*!< CTIMER_STCFG_COMPARE_F_EN */ + CTIMER_STCFG_COMPARE_F_EN_DISABLE = 0, /*!< DISABLE : Compare F disabled. value. */ + CTIMER_STCFG_COMPARE_F_EN_ENABLE = 1, /*!< ENABLE : Compare F enabled. value. */ +} CTIMER_STCFG_COMPARE_F_EN_Enum; + +/* ========================================== CTIMER STCFG COMPARE_E_EN [12..12] =========================================== */ +typedef enum { /*!< CTIMER_STCFG_COMPARE_E_EN */ + CTIMER_STCFG_COMPARE_E_EN_DISABLE = 0, /*!< DISABLE : Compare E disabled. value. */ + CTIMER_STCFG_COMPARE_E_EN_ENABLE = 1, /*!< ENABLE : Compare E enabled. value. */ +} CTIMER_STCFG_COMPARE_E_EN_Enum; + +/* ========================================== CTIMER STCFG COMPARE_D_EN [11..11] =========================================== */ +typedef enum { /*!< CTIMER_STCFG_COMPARE_D_EN */ + CTIMER_STCFG_COMPARE_D_EN_DISABLE = 0, /*!< DISABLE : Compare D disabled. value. */ + CTIMER_STCFG_COMPARE_D_EN_ENABLE = 1, /*!< ENABLE : Compare D enabled. value. */ +} CTIMER_STCFG_COMPARE_D_EN_Enum; + +/* ========================================== CTIMER STCFG COMPARE_C_EN [10..10] =========================================== */ +typedef enum { /*!< CTIMER_STCFG_COMPARE_C_EN */ + CTIMER_STCFG_COMPARE_C_EN_DISABLE = 0, /*!< DISABLE : Compare C disabled. value. */ + CTIMER_STCFG_COMPARE_C_EN_ENABLE = 1, /*!< ENABLE : Compare C enabled. value. */ +} CTIMER_STCFG_COMPARE_C_EN_Enum; + +/* =========================================== CTIMER STCFG COMPARE_B_EN [9..9] ============================================ */ +typedef enum { /*!< CTIMER_STCFG_COMPARE_B_EN */ + CTIMER_STCFG_COMPARE_B_EN_DISABLE = 0, /*!< DISABLE : Compare B disabled. value. */ + CTIMER_STCFG_COMPARE_B_EN_ENABLE = 1, /*!< ENABLE : Compare B enabled. value. */ +} CTIMER_STCFG_COMPARE_B_EN_Enum; + +/* =========================================== CTIMER STCFG COMPARE_A_EN [8..8] ============================================ */ +typedef enum { /*!< CTIMER_STCFG_COMPARE_A_EN */ + CTIMER_STCFG_COMPARE_A_EN_DISABLE = 0, /*!< DISABLE : Compare A disabled. value. */ + CTIMER_STCFG_COMPARE_A_EN_ENABLE = 1, /*!< ENABLE : Compare A enabled. value. */ +} CTIMER_STCFG_COMPARE_A_EN_Enum; + +/* ============================================== CTIMER STCFG CLKSEL [0..3] =============================================== */ +typedef enum { /*!< CTIMER_STCFG_CLKSEL */ + CTIMER_STCFG_CLKSEL_NOCLK = 0, /*!< NOCLK : No clock enabled. value. */ + CTIMER_STCFG_CLKSEL_HFRC_DIV16 = 1, /*!< HFRC_DIV16 : 3MHz from the HFRC clock divider. value. */ + CTIMER_STCFG_CLKSEL_HFRC_DIV256 = 2, /*!< HFRC_DIV256 : 187.5KHz from the HFRC clock divider. value. */ + CTIMER_STCFG_CLKSEL_XTAL_DIV1 = 3, /*!< XTAL_DIV1 : 32768Hz from the crystal oscillator. value. */ + CTIMER_STCFG_CLKSEL_XTAL_DIV2 = 4, /*!< XTAL_DIV2 : 16384Hz from the crystal oscillator. value. */ + CTIMER_STCFG_CLKSEL_XTAL_DIV32 = 5, /*!< XTAL_DIV32 : 1024Hz from the crystal oscillator. value. */ + CTIMER_STCFG_CLKSEL_LFRC_DIV1 = 6, /*!< LFRC_DIV1 : Approximately 1KHz from the LFRC oscillator (uncalibrated). + value. */ + CTIMER_STCFG_CLKSEL_CTIMER0A = 7, /*!< CTIMER0A : Use CTIMER 0 section A as a prescaler for the clock + source. value. */ + CTIMER_STCFG_CLKSEL_CTIMER0B = 8, /*!< CTIMER0B : Use CTIMER 0 section B (or A and B linked together) + as a prescaler for the clock source. value. */ +} CTIMER_STCFG_CLKSEL_Enum; + +/* ========================================================= STTMR ========================================================= */ +/* ==================================================== CAPTURECONTROL ===================================================== */ +/* ========================================= CTIMER CAPTURECONTROL CAPTURE3 [3..3] ========================================= */ +typedef enum { /*!< CTIMER_CAPTURECONTROL_CAPTURE3 */ + CTIMER_CAPTURECONTROL_CAPTURE3_DISABLE = 0, /*!< DISABLE : Capture function disabled. value. */ + CTIMER_CAPTURECONTROL_CAPTURE3_ENABLE = 1, /*!< ENABLE : Capture function enabled. value. */ +} CTIMER_CAPTURECONTROL_CAPTURE3_Enum; + +/* ========================================= CTIMER CAPTURECONTROL CAPTURE2 [2..2] ========================================= */ +typedef enum { /*!< CTIMER_CAPTURECONTROL_CAPTURE2 */ + CTIMER_CAPTURECONTROL_CAPTURE2_DISABLE = 0, /*!< DISABLE : Capture function disabled. value. */ + CTIMER_CAPTURECONTROL_CAPTURE2_ENABLE = 1, /*!< ENABLE : Capture function enabled. value. */ +} CTIMER_CAPTURECONTROL_CAPTURE2_Enum; + +/* ========================================= CTIMER CAPTURECONTROL CAPTURE1 [1..1] ========================================= */ +typedef enum { /*!< CTIMER_CAPTURECONTROL_CAPTURE1 */ + CTIMER_CAPTURECONTROL_CAPTURE1_DISABLE = 0, /*!< DISABLE : Capture function disabled. value. */ + CTIMER_CAPTURECONTROL_CAPTURE1_ENABLE = 1, /*!< ENABLE : Capture function enabled. value. */ +} CTIMER_CAPTURECONTROL_CAPTURE1_Enum; + +/* ========================================= CTIMER CAPTURECONTROL CAPTURE0 [0..0] ========================================= */ +typedef enum { /*!< CTIMER_CAPTURECONTROL_CAPTURE0 */ + CTIMER_CAPTURECONTROL_CAPTURE0_DISABLE = 0, /*!< DISABLE : Capture function disabled. value. */ + CTIMER_CAPTURECONTROL_CAPTURE0_ENABLE = 1, /*!< ENABLE : Capture function enabled. value. */ +} CTIMER_CAPTURECONTROL_CAPTURE0_Enum; + +/* ======================================================== SCMPR0 ========================================================= */ +/* ======================================================== SCMPR1 ========================================================= */ +/* ======================================================== SCMPR2 ========================================================= */ +/* ======================================================== SCMPR3 ========================================================= */ +/* ======================================================== SCMPR4 ========================================================= */ +/* ======================================================== SCMPR5 ========================================================= */ +/* ======================================================== SCMPR6 ========================================================= */ +/* ======================================================== SCMPR7 ========================================================= */ +/* ======================================================== SCAPT0 ========================================================= */ +/* ======================================================== SCAPT1 ========================================================= */ +/* ======================================================== SCAPT2 ========================================================= */ +/* ======================================================== SCAPT3 ========================================================= */ +/* ========================================================= SNVR0 ========================================================= */ +/* ========================================================= SNVR1 ========================================================= */ +/* ========================================================= SNVR2 ========================================================= */ +/* ========================================================= SNVR3 ========================================================= */ +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ +/* ======================================================= STMINTEN ======================================================== */ +/* =========================================== CTIMER STMINTEN CAPTURED [12..12] =========================================== */ +typedef enum { /*!< CTIMER_STMINTEN_CAPTURED */ + CTIMER_STMINTEN_CAPTURED_CAPD_INT = 1, /*!< CAPD_INT : Capture D interrupt status bit was set. value. */ +} CTIMER_STMINTEN_CAPTURED_Enum; + +/* =========================================== CTIMER STMINTEN CAPTUREC [11..11] =========================================== */ +typedef enum { /*!< CTIMER_STMINTEN_CAPTUREC */ + CTIMER_STMINTEN_CAPTUREC_CAPC_INT = 1, /*!< CAPC_INT : CAPTURE C interrupt status bit was set. value. */ +} CTIMER_STMINTEN_CAPTUREC_Enum; + +/* =========================================== CTIMER STMINTEN CAPTUREB [10..10] =========================================== */ +typedef enum { /*!< CTIMER_STMINTEN_CAPTUREB */ + CTIMER_STMINTEN_CAPTUREB_CAPB_INT = 1, /*!< CAPB_INT : CAPTURE B interrupt status bit was set. value. */ +} CTIMER_STMINTEN_CAPTUREB_Enum; + +/* ============================================ CTIMER STMINTEN CAPTUREA [9..9] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_CAPTUREA */ + CTIMER_STMINTEN_CAPTUREA_CAPA_INT = 1, /*!< CAPA_INT : CAPTURE A interrupt status bit was set. value. */ +} CTIMER_STMINTEN_CAPTUREA_Enum; + +/* ============================================ CTIMER STMINTEN OVERFLOW [8..8] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_OVERFLOW */ + CTIMER_STMINTEN_OVERFLOW_OFLOW_INT = 1, /*!< OFLOW_INT : Overflow interrupt status bit was set. value. */ +} CTIMER_STMINTEN_OVERFLOW_Enum; + +/* ============================================ CTIMER STMINTEN COMPAREH [7..7] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_COMPAREH */ + CTIMER_STMINTEN_COMPAREH_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTEN_COMPAREH_Enum; + +/* ============================================ CTIMER STMINTEN COMPAREG [6..6] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_COMPAREG */ + CTIMER_STMINTEN_COMPAREG_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTEN_COMPAREG_Enum; + +/* ============================================ CTIMER STMINTEN COMPAREF [5..5] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_COMPAREF */ + CTIMER_STMINTEN_COMPAREF_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTEN_COMPAREF_Enum; + +/* ============================================ CTIMER STMINTEN COMPAREE [4..4] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_COMPAREE */ + CTIMER_STMINTEN_COMPAREE_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTEN_COMPAREE_Enum; + +/* ============================================ CTIMER STMINTEN COMPARED [3..3] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_COMPARED */ + CTIMER_STMINTEN_COMPARED_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTEN_COMPARED_Enum; + +/* ============================================ CTIMER STMINTEN COMPAREC [2..2] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_COMPAREC */ + CTIMER_STMINTEN_COMPAREC_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTEN_COMPAREC_Enum; + +/* ============================================ CTIMER STMINTEN COMPAREB [1..1] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_COMPAREB */ + CTIMER_STMINTEN_COMPAREB_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTEN_COMPAREB_Enum; + +/* ============================================ CTIMER STMINTEN COMPAREA [0..0] ============================================ */ +typedef enum { /*!< CTIMER_STMINTEN_COMPAREA */ + CTIMER_STMINTEN_COMPAREA_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTEN_COMPAREA_Enum; + +/* ====================================================== STMINTSTAT ======================================================= */ +/* ========================================== CTIMER STMINTSTAT CAPTURED [12..12] ========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_CAPTURED */ + CTIMER_STMINTSTAT_CAPTURED_CAPD_INT = 1, /*!< CAPD_INT : Capture D interrupt status bit was set. value. */ +} CTIMER_STMINTSTAT_CAPTURED_Enum; + +/* ========================================== CTIMER STMINTSTAT CAPTUREC [11..11] ========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_CAPTUREC */ + CTIMER_STMINTSTAT_CAPTUREC_CAPC_INT = 1, /*!< CAPC_INT : CAPTURE C interrupt status bit was set. value. */ +} CTIMER_STMINTSTAT_CAPTUREC_Enum; + +/* ========================================== CTIMER STMINTSTAT CAPTUREB [10..10] ========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_CAPTUREB */ + CTIMER_STMINTSTAT_CAPTUREB_CAPB_INT = 1, /*!< CAPB_INT : CAPTURE B interrupt status bit was set. value. */ +} CTIMER_STMINTSTAT_CAPTUREB_Enum; + +/* =========================================== CTIMER STMINTSTAT CAPTUREA [9..9] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_CAPTUREA */ + CTIMER_STMINTSTAT_CAPTUREA_CAPA_INT = 1, /*!< CAPA_INT : CAPTURE A interrupt status bit was set. value. */ +} CTIMER_STMINTSTAT_CAPTUREA_Enum; + +/* =========================================== CTIMER STMINTSTAT OVERFLOW [8..8] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_OVERFLOW */ + CTIMER_STMINTSTAT_OVERFLOW_OFLOW_INT = 1, /*!< OFLOW_INT : Overflow interrupt status bit was set. value. */ +} CTIMER_STMINTSTAT_OVERFLOW_Enum; + +/* =========================================== CTIMER STMINTSTAT COMPAREH [7..7] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREH */ + CTIMER_STMINTSTAT_COMPAREH_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSTAT_COMPAREH_Enum; + +/* =========================================== CTIMER STMINTSTAT COMPAREG [6..6] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREG */ + CTIMER_STMINTSTAT_COMPAREG_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSTAT_COMPAREG_Enum; + +/* =========================================== CTIMER STMINTSTAT COMPAREF [5..5] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREF */ + CTIMER_STMINTSTAT_COMPAREF_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSTAT_COMPAREF_Enum; + +/* =========================================== CTIMER STMINTSTAT COMPAREE [4..4] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREE */ + CTIMER_STMINTSTAT_COMPAREE_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSTAT_COMPAREE_Enum; + +/* =========================================== CTIMER STMINTSTAT COMPARED [3..3] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_COMPARED */ + CTIMER_STMINTSTAT_COMPARED_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSTAT_COMPARED_Enum; + +/* =========================================== CTIMER STMINTSTAT COMPAREC [2..2] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREC */ + CTIMER_STMINTSTAT_COMPAREC_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSTAT_COMPAREC_Enum; + +/* =========================================== CTIMER STMINTSTAT COMPAREB [1..1] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREB */ + CTIMER_STMINTSTAT_COMPAREB_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSTAT_COMPAREB_Enum; + +/* =========================================== CTIMER STMINTSTAT COMPAREA [0..0] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREA */ + CTIMER_STMINTSTAT_COMPAREA_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSTAT_COMPAREA_Enum; + +/* ======================================================= STMINTCLR ======================================================= */ +/* ========================================== CTIMER STMINTCLR CAPTURED [12..12] =========================================== */ +typedef enum { /*!< CTIMER_STMINTCLR_CAPTURED */ + CTIMER_STMINTCLR_CAPTURED_CAPD_INT = 1, /*!< CAPD_INT : Capture D interrupt status bit was set. value. */ +} CTIMER_STMINTCLR_CAPTURED_Enum; + +/* ========================================== CTIMER STMINTCLR CAPTUREC [11..11] =========================================== */ +typedef enum { /*!< CTIMER_STMINTCLR_CAPTUREC */ + CTIMER_STMINTCLR_CAPTUREC_CAPC_INT = 1, /*!< CAPC_INT : CAPTURE C interrupt status bit was set. value. */ +} CTIMER_STMINTCLR_CAPTUREC_Enum; + +/* ========================================== CTIMER STMINTCLR CAPTUREB [10..10] =========================================== */ +typedef enum { /*!< CTIMER_STMINTCLR_CAPTUREB */ + CTIMER_STMINTCLR_CAPTUREB_CAPB_INT = 1, /*!< CAPB_INT : CAPTURE B interrupt status bit was set. value. */ +} CTIMER_STMINTCLR_CAPTUREB_Enum; + +/* =========================================== CTIMER STMINTCLR CAPTUREA [9..9] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_CAPTUREA */ + CTIMER_STMINTCLR_CAPTUREA_CAPA_INT = 1, /*!< CAPA_INT : CAPTURE A interrupt status bit was set. value. */ +} CTIMER_STMINTCLR_CAPTUREA_Enum; + +/* =========================================== CTIMER STMINTCLR OVERFLOW [8..8] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_OVERFLOW */ + CTIMER_STMINTCLR_OVERFLOW_OFLOW_INT = 1, /*!< OFLOW_INT : Overflow interrupt status bit was set. value. */ +} CTIMER_STMINTCLR_OVERFLOW_Enum; + +/* =========================================== CTIMER STMINTCLR COMPAREH [7..7] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_COMPAREH */ + CTIMER_STMINTCLR_COMPAREH_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTCLR_COMPAREH_Enum; + +/* =========================================== CTIMER STMINTCLR COMPAREG [6..6] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_COMPAREG */ + CTIMER_STMINTCLR_COMPAREG_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTCLR_COMPAREG_Enum; + +/* =========================================== CTIMER STMINTCLR COMPAREF [5..5] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_COMPAREF */ + CTIMER_STMINTCLR_COMPAREF_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTCLR_COMPAREF_Enum; + +/* =========================================== CTIMER STMINTCLR COMPAREE [4..4] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_COMPAREE */ + CTIMER_STMINTCLR_COMPAREE_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTCLR_COMPAREE_Enum; + +/* =========================================== CTIMER STMINTCLR COMPARED [3..3] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_COMPARED */ + CTIMER_STMINTCLR_COMPARED_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTCLR_COMPARED_Enum; + +/* =========================================== CTIMER STMINTCLR COMPAREC [2..2] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_COMPAREC */ + CTIMER_STMINTCLR_COMPAREC_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTCLR_COMPAREC_Enum; + +/* =========================================== CTIMER STMINTCLR COMPAREB [1..1] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_COMPAREB */ + CTIMER_STMINTCLR_COMPAREB_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTCLR_COMPAREB_Enum; + +/* =========================================== CTIMER STMINTCLR COMPAREA [0..0] ============================================ */ +typedef enum { /*!< CTIMER_STMINTCLR_COMPAREA */ + CTIMER_STMINTCLR_COMPAREA_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTCLR_COMPAREA_Enum; + +/* ======================================================= STMINTSET ======================================================= */ +/* ========================================== CTIMER STMINTSET CAPTURED [12..12] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSET_CAPTURED */ + CTIMER_STMINTSET_CAPTURED_CAPD_INT = 1, /*!< CAPD_INT : Capture D interrupt status bit was set. value. */ +} CTIMER_STMINTSET_CAPTURED_Enum; + +/* ========================================== CTIMER STMINTSET CAPTUREC [11..11] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSET_CAPTUREC */ + CTIMER_STMINTSET_CAPTUREC_CAPC_INT = 1, /*!< CAPC_INT : CAPTURE C interrupt status bit was set. value. */ +} CTIMER_STMINTSET_CAPTUREC_Enum; + +/* ========================================== CTIMER STMINTSET CAPTUREB [10..10] =========================================== */ +typedef enum { /*!< CTIMER_STMINTSET_CAPTUREB */ + CTIMER_STMINTSET_CAPTUREB_CAPB_INT = 1, /*!< CAPB_INT : CAPTURE B interrupt status bit was set. value. */ +} CTIMER_STMINTSET_CAPTUREB_Enum; + +/* =========================================== CTIMER STMINTSET CAPTUREA [9..9] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_CAPTUREA */ + CTIMER_STMINTSET_CAPTUREA_CAPA_INT = 1, /*!< CAPA_INT : CAPTURE A interrupt status bit was set. value. */ +} CTIMER_STMINTSET_CAPTUREA_Enum; + +/* =========================================== CTIMER STMINTSET OVERFLOW [8..8] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_OVERFLOW */ + CTIMER_STMINTSET_OVERFLOW_OFLOW_INT = 1, /*!< OFLOW_INT : Overflow interrupt status bit was set. value. */ +} CTIMER_STMINTSET_OVERFLOW_Enum; + +/* =========================================== CTIMER STMINTSET COMPAREH [7..7] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_COMPAREH */ + CTIMER_STMINTSET_COMPAREH_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSET_COMPAREH_Enum; + +/* =========================================== CTIMER STMINTSET COMPAREG [6..6] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_COMPAREG */ + CTIMER_STMINTSET_COMPAREG_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSET_COMPAREG_Enum; + +/* =========================================== CTIMER STMINTSET COMPAREF [5..5] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_COMPAREF */ + CTIMER_STMINTSET_COMPAREF_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSET_COMPAREF_Enum; + +/* =========================================== CTIMER STMINTSET COMPAREE [4..4] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_COMPAREE */ + CTIMER_STMINTSET_COMPAREE_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSET_COMPAREE_Enum; + +/* =========================================== CTIMER STMINTSET COMPARED [3..3] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_COMPARED */ + CTIMER_STMINTSET_COMPARED_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSET_COMPARED_Enum; + +/* =========================================== CTIMER STMINTSET COMPAREC [2..2] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_COMPAREC */ + CTIMER_STMINTSET_COMPAREC_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSET_COMPAREC_Enum; + +/* =========================================== CTIMER STMINTSET COMPAREB [1..1] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_COMPAREB */ + CTIMER_STMINTSET_COMPAREB_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSET_COMPAREB_Enum; + +/* =========================================== CTIMER STMINTSET COMPAREA [0..0] ============================================ */ +typedef enum { /*!< CTIMER_STMINTSET_COMPAREA */ + CTIMER_STMINTSET_COMPAREA_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. + value. */ +} CTIMER_STMINTSET_COMPAREA_Enum; + + + +/* =========================================================================================================================== */ +/* ================ GPIO ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== PADREGA ======================================================== */ +/* ============================================ GPIO PADREGA PAD3PWRUP [30..30] ============================================ */ +typedef enum { /*!< GPIO_PADREGA_PAD3PWRUP */ + GPIO_PADREGA_PAD3PWRUP_DIS = 0, /*!< DIS : Power switch disabled value. */ + GPIO_PADREGA_PAD3PWRUP_EN = 1, /*!< EN : Power switch enabled (switched to VDD) value. */ +} GPIO_PADREGA_PAD3PWRUP_Enum; + +/* =========================================== GPIO PADREGA PAD3FNCSEL [27..29] ============================================ */ +typedef enum { /*!< GPIO_PADREGA_PAD3FNCSEL */ + GPIO_PADREGA_PAD3FNCSEL_UA0RTS = 0, /*!< UA0RTS : Configure as the UART0 RTS output value. */ + GPIO_PADREGA_PAD3FNCSEL_SLnCE = 1, /*!< SLnCE : Configure as the IOSLAVE SPI nCE signal value. */ + GPIO_PADREGA_PAD3FNCSEL_NCE3 = 2, /*!< NCE3 : IOM/MSPI nCE group 3 value. */ + GPIO_PADREGA_PAD3FNCSEL_GPIO3 = 3, /*!< GPIO3 : Configure as GPIO3 value. */ + GPIO_PADREGA_PAD3FNCSEL_MSPI7 = 5, /*!< MSPI7 : MSPI data connection 7 value. */ + GPIO_PADREGA_PAD3FNCSEL_TRIG1 = 6, /*!< TRIG1 : Configure as the ADC Trigger 1 signal value. */ + GPIO_PADREGA_PAD3FNCSEL_I2S_WCLK = 7, /*!< I2S_WCLK : Configure as the PDM I2S Word Clock input value. */ +} GPIO_PADREGA_PAD3FNCSEL_Enum; + +/* ============================================ GPIO PADREGA PAD3STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGA_PAD3STRNG */ + GPIO_PADREGA_PAD3STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGA_PAD3STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGA_PAD3STRNG_Enum; + +/* ============================================ GPIO PADREGA PAD3INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGA_PAD3INPEN */ + GPIO_PADREGA_PAD3INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGA_PAD3INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGA_PAD3INPEN_Enum; + +/* ============================================ GPIO PADREGA PAD3PULL [24..24] ============================================= */ +typedef enum { /*!< GPIO_PADREGA_PAD3PULL */ + GPIO_PADREGA_PAD3PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGA_PAD3PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGA_PAD3PULL_Enum; + +/* =========================================== GPIO PADREGA PAD2FNCSEL [19..21] ============================================ */ +typedef enum { /*!< GPIO_PADREGA_PAD2FNCSEL */ + GPIO_PADREGA_PAD2FNCSEL_SLMISO = 1, /*!< SLMISO : Configure as the IOSLAVE SPI MISO signal value. */ + GPIO_PADREGA_PAD2FNCSEL_UART0RX = 2, /*!< UART0RX : Configure as the UART0 RX input value. */ + GPIO_PADREGA_PAD2FNCSEL_GPIO2 = 3, /*!< GPIO2 : Configure as GPIO2 value. */ + GPIO_PADREGA_PAD2FNCSEL_MSPI6 = 5, /*!< MSPI6 : CMSPI data connection 6 value. */ + GPIO_PADREGA_PAD2FNCSEL_NCE2 = 7, /*!< NCE2 : IOM/MSPI nCE group 2 value. */ +} GPIO_PADREGA_PAD2FNCSEL_Enum; + +/* ============================================ GPIO PADREGA PAD2STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGA_PAD2STRNG */ + GPIO_PADREGA_PAD2STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGA_PAD2STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGA_PAD2STRNG_Enum; + +/* ============================================ GPIO PADREGA PAD2INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGA_PAD2INPEN */ + GPIO_PADREGA_PAD2INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGA_PAD2INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGA_PAD2INPEN_Enum; + +/* ============================================ GPIO PADREGA PAD2PULL [16..16] ============================================= */ +typedef enum { /*!< GPIO_PADREGA_PAD2PULL */ + GPIO_PADREGA_PAD2PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGA_PAD2PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGA_PAD2PULL_Enum; + +/* ============================================ GPIO PADREGA PAD1RSEL [14..15] ============================================= */ +typedef enum { /*!< GPIO_PADREGA_PAD1RSEL */ + GPIO_PADREGA_PAD1RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGA_PAD1RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGA_PAD1RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGA_PAD1RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGA_PAD1RSEL_Enum; + +/* =========================================== GPIO PADREGA PAD1FNCSEL [11..13] ============================================ */ +typedef enum { /*!< GPIO_PADREGA_PAD1FNCSEL */ + GPIO_PADREGA_PAD1FNCSEL_SLSDAWIR3 = 0, /*!< SLSDAWIR3 : Configure as the IOSLAVE I2C SDA or SPI WIR3 signal + value. */ + GPIO_PADREGA_PAD1FNCSEL_SLMOSI = 1, /*!< SLMOSI : Configure as the IOSLAVE SPI MOSI signal value. */ + GPIO_PADREGA_PAD1FNCSEL_UART0TX = 2, /*!< UART0TX : Configure as the UART0 TX output signal value. */ + GPIO_PADREGA_PAD1FNCSEL_GPIO1 = 3, /*!< GPIO1 : Configure as GPIO1 value. */ + GPIO_PADREGA_PAD1FNCSEL_MSPI5 = 5, /*!< MSPI5 : MSPI data connection 5 value. */ + GPIO_PADREGA_PAD1FNCSEL_NCE1 = 7, /*!< NCE1 : IOM/MSPI nCE group 1 value. */ +} GPIO_PADREGA_PAD1FNCSEL_Enum; + +/* ============================================ GPIO PADREGA PAD1STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGA_PAD1STRNG */ + GPIO_PADREGA_PAD1STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGA_PAD1STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGA_PAD1STRNG_Enum; + +/* ============================================= GPIO PADREGA PAD1INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGA_PAD1INPEN */ + GPIO_PADREGA_PAD1INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGA_PAD1INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGA_PAD1INPEN_Enum; + +/* ============================================= GPIO PADREGA PAD1PULL [8..8] ============================================== */ +typedef enum { /*!< GPIO_PADREGA_PAD1PULL */ + GPIO_PADREGA_PAD1PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGA_PAD1PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGA_PAD1PULL_Enum; + +/* ============================================= GPIO PADREGA PAD0RSEL [6..7] ============================================== */ +typedef enum { /*!< GPIO_PADREGA_PAD0RSEL */ + GPIO_PADREGA_PAD0RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGA_PAD0RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGA_PAD0RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGA_PAD0RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGA_PAD0RSEL_Enum; + +/* ============================================ GPIO PADREGA PAD0FNCSEL [3..5] ============================================= */ +typedef enum { /*!< GPIO_PADREGA_PAD0FNCSEL */ + GPIO_PADREGA_PAD0FNCSEL_SLSCL = 0, /*!< SLSCL : Configure as the IOSLAVE I2C SCL signal value. */ + GPIO_PADREGA_PAD0FNCSEL_SLSCK = 1, /*!< SLSCK : Configure as the IOSLAVE SPI SCK signal value. */ + GPIO_PADREGA_PAD0FNCSEL_CLKOUT = 2, /*!< CLKOUT : Configure as the CLKOUT signal value. */ + GPIO_PADREGA_PAD0FNCSEL_GPIO0 = 3, /*!< GPIO0 : Configure as GPIO0 value. */ + GPIO_PADREGA_PAD0FNCSEL_MSPI4 = 5, /*!< MSPI4 : MSPI data connection 4 value. */ + GPIO_PADREGA_PAD0FNCSEL_NCE0 = 7, /*!< NCE0 : IOM/MSPI nCE group 0 value. */ +} GPIO_PADREGA_PAD0FNCSEL_Enum; + +/* ============================================= GPIO PADREGA PAD0STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGA_PAD0STRNG */ + GPIO_PADREGA_PAD0STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGA_PAD0STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGA_PAD0STRNG_Enum; + +/* ============================================= GPIO PADREGA PAD0INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGA_PAD0INPEN */ + GPIO_PADREGA_PAD0INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGA_PAD0INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGA_PAD0INPEN_Enum; + +/* ============================================= GPIO PADREGA PAD0PULL [0..0] ============================================== */ +typedef enum { /*!< GPIO_PADREGA_PAD0PULL */ + GPIO_PADREGA_PAD0PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGA_PAD0PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGA_PAD0PULL_Enum; + +/* ======================================================== PADREGB ======================================================== */ +/* =========================================== GPIO PADREGB PAD7FNCSEL [27..29] ============================================ */ +typedef enum { /*!< GPIO_PADREGB_PAD7FNCSEL */ + GPIO_PADREGB_PAD7FNCSEL_NCE7 = 0, /*!< NCE7 : IOM/MSPI nCE group 7 value. */ + GPIO_PADREGB_PAD7FNCSEL_M0MOSI = 1, /*!< M0MOSI : Configure as the IOMSTR0 SPI MOSI signal value. */ + GPIO_PADREGB_PAD7FNCSEL_CLKOUT = 2, /*!< CLKOUT : Configure as the CLKOUT signal value. */ + GPIO_PADREGB_PAD7FNCSEL_GPIO7 = 3, /*!< GPIO7 : Configure as GPIO7 value. */ + GPIO_PADREGB_PAD7FNCSEL_TRIG0 = 4, /*!< TRIG0 : Configure as the ADC Trigger 0 signal value. */ + GPIO_PADREGB_PAD7FNCSEL_UART0TX = 5, /*!< UART0TX : Configure as the UART0 TX output signal value. */ + GPIO_PADREGB_PAD7FNCSEL_CT19 = 7, /*!< CT19 : CTIMER connection 19 value. */ +} GPIO_PADREGB_PAD7FNCSEL_Enum; + +/* ============================================ GPIO PADREGB PAD7STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGB_PAD7STRNG */ + GPIO_PADREGB_PAD7STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGB_PAD7STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGB_PAD7STRNG_Enum; + +/* ============================================ GPIO PADREGB PAD7INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGB_PAD7INPEN */ + GPIO_PADREGB_PAD7INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGB_PAD7INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGB_PAD7INPEN_Enum; + +/* ============================================ GPIO PADREGB PAD7PULL [24..24] ============================================= */ +typedef enum { /*!< GPIO_PADREGB_PAD7PULL */ + GPIO_PADREGB_PAD7PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGB_PAD7PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGB_PAD7PULL_Enum; + +/* ============================================ GPIO PADREGB PAD6RSEL [22..23] ============================================= */ +typedef enum { /*!< GPIO_PADREGB_PAD6RSEL */ + GPIO_PADREGB_PAD6RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGB_PAD6RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGB_PAD6RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGB_PAD6RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGB_PAD6RSEL_Enum; + +/* =========================================== GPIO PADREGB PAD6FNCSEL [19..21] ============================================ */ +typedef enum { /*!< GPIO_PADREGB_PAD6FNCSEL */ + GPIO_PADREGB_PAD6FNCSEL_M0SDAWIR3 = 0, /*!< M0SDAWIR3 : Configure as the IOMSTR0 I2C SDA or SPI WIR3 signal + value. */ + GPIO_PADREGB_PAD6FNCSEL_M0MISO = 1, /*!< M0MISO : Configure as the IOMSTR0 SPI MISO signal value. */ + GPIO_PADREGB_PAD6FNCSEL_UA0CTS = 2, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ + GPIO_PADREGB_PAD6FNCSEL_GPIO6 = 3, /*!< GPIO6 : Configure as GPIO6 value. */ + GPIO_PADREGB_PAD6FNCSEL_CT10 = 5, /*!< CT10 : CTIMER connection 10 value. */ + GPIO_PADREGB_PAD6FNCSEL_I2S_DAT = 7, /*!< I2S_DAT : Configure as the PDM I2S Data output signal value. */ +} GPIO_PADREGB_PAD6FNCSEL_Enum; + +/* ============================================ GPIO PADREGB PAD6STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGB_PAD6STRNG */ + GPIO_PADREGB_PAD6STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGB_PAD6STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGB_PAD6STRNG_Enum; + +/* ============================================ GPIO PADREGB PAD6INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGB_PAD6INPEN */ + GPIO_PADREGB_PAD6INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGB_PAD6INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGB_PAD6INPEN_Enum; + +/* ============================================ GPIO PADREGB PAD6PULL [16..16] ============================================= */ +typedef enum { /*!< GPIO_PADREGB_PAD6PULL */ + GPIO_PADREGB_PAD6PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGB_PAD6PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGB_PAD6PULL_Enum; + +/* ============================================ GPIO PADREGB PAD5RSEL [14..15] ============================================= */ +typedef enum { /*!< GPIO_PADREGB_PAD5RSEL */ + GPIO_PADREGB_PAD5RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGB_PAD5RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGB_PAD5RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGB_PAD5RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGB_PAD5RSEL_Enum; + +/* =========================================== GPIO PADREGB PAD5FNCSEL [11..13] ============================================ */ +typedef enum { /*!< GPIO_PADREGB_PAD5FNCSEL */ + GPIO_PADREGB_PAD5FNCSEL_M0SCL = 0, /*!< M0SCL : Configure as the IOMSTR0 I2C SCL signal value. */ + GPIO_PADREGB_PAD5FNCSEL_M0SCK = 1, /*!< M0SCK : Configure as the IOMSTR0 SPI SCK signal value. */ + GPIO_PADREGB_PAD5FNCSEL_UA0RTS = 2, /*!< UA0RTS : Configure as the UART0 RTS signal output value. */ + GPIO_PADREGB_PAD5FNCSEL_GPIO5 = 3, /*!< GPIO5 : Configure as GPIO5 value. */ + GPIO_PADREGB_PAD5FNCSEL_EXTHFA = 5, /*!< EXTHFA : Configure as the External HFA input clock value. */ + GPIO_PADREGB_PAD5FNCSEL_CT8 = 7, /*!< CT8 : CTIMER connection 8 value. */ +} GPIO_PADREGB_PAD5FNCSEL_Enum; + +/* ============================================ GPIO PADREGB PAD5STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGB_PAD5STRNG */ + GPIO_PADREGB_PAD5STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGB_PAD5STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGB_PAD5STRNG_Enum; + +/* ============================================= GPIO PADREGB PAD5INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGB_PAD5INPEN */ + GPIO_PADREGB_PAD5INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGB_PAD5INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGB_PAD5INPEN_Enum; + +/* ============================================= GPIO PADREGB PAD5PULL [8..8] ============================================== */ +typedef enum { /*!< GPIO_PADREGB_PAD5PULL */ + GPIO_PADREGB_PAD5PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGB_PAD5PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGB_PAD5PULL_Enum; + +/* ============================================ GPIO PADREGB PAD4FNCSEL [3..5] ============================================= */ +typedef enum { /*!< GPIO_PADREGB_PAD4FNCSEL */ + GPIO_PADREGB_PAD4FNCSEL_UA0CTS = 0, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ + GPIO_PADREGB_PAD4FNCSEL_SLINT = 1, /*!< SLINT : Configure as the IOSLAVE interrupt out signal value. */ + GPIO_PADREGB_PAD4FNCSEL_NCE4 = 2, /*!< NCE4 : IOM/SPI nCE group 4 value. */ + GPIO_PADREGB_PAD4FNCSEL_GPIO4 = 3, /*!< GPIO4 : Configure as GPIO4 value. */ + GPIO_PADREGB_PAD4FNCSEL_UART0RX = 5, /*!< UART0RX : Configure as the UART0 RX input value. */ + GPIO_PADREGB_PAD4FNCSEL_CT17 = 6, /*!< CT17 : CTIMER connection 17 value. */ + GPIO_PADREGB_PAD4FNCSEL_MSPI2 = 7, /*!< MSPI2 : MSPI data connection 2 value. */ +} GPIO_PADREGB_PAD4FNCSEL_Enum; + +/* ============================================= GPIO PADREGB PAD4STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGB_PAD4STRNG */ + GPIO_PADREGB_PAD4STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGB_PAD4STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGB_PAD4STRNG_Enum; + +/* ============================================= GPIO PADREGB PAD4INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGB_PAD4INPEN */ + GPIO_PADREGB_PAD4INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGB_PAD4INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGB_PAD4INPEN_Enum; + +/* ============================================= GPIO PADREGB PAD4PULL [0..0] ============================================== */ +typedef enum { /*!< GPIO_PADREGB_PAD4PULL */ + GPIO_PADREGB_PAD4PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGB_PAD4PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGB_PAD4PULL_Enum; + +/* ======================================================== PADREGC ======================================================== */ +/* =========================================== GPIO PADREGC PAD11FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGC_PAD11FNCSEL */ + GPIO_PADREGC_PAD11FNCSEL_ADCSE2 = 0, /*!< ADCSE2 : Configure as the analog input for ADC single ended + input 2 value. */ + GPIO_PADREGC_PAD11FNCSEL_NCE11 = 1, /*!< NCE11 : IOM/MSPI nCE group 11 value. */ + GPIO_PADREGC_PAD11FNCSEL_CT31 = 2, /*!< CT31 : CTIMER connection 31 value. */ + GPIO_PADREGC_PAD11FNCSEL_GPIO11 = 3, /*!< GPIO11 : Configure as GPIO11 value. */ + GPIO_PADREGC_PAD11FNCSEL_SLINT = 4, /*!< SLINT : Configure as the IOSLAVE interrupt out signal value. */ + GPIO_PADREGC_PAD11FNCSEL_UA1CTS = 5, /*!< UA1CTS : Configure as the UART1 CTS input signal value. */ + GPIO_PADREGC_PAD11FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as the UART0 RX input signal value. */ + GPIO_PADREGC_PAD11FNCSEL_PDM_DATA = 7, /*!< PDM_DATA : Configure as the PDM Data input signal value. */ +} GPIO_PADREGC_PAD11FNCSEL_Enum; + +/* =========================================== GPIO PADREGC PAD11STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGC_PAD11STRNG */ + GPIO_PADREGC_PAD11STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGC_PAD11STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGC_PAD11STRNG_Enum; + +/* =========================================== GPIO PADREGC PAD11INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGC_PAD11INPEN */ + GPIO_PADREGC_PAD11INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGC_PAD11INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGC_PAD11INPEN_Enum; + +/* ============================================ GPIO PADREGC PAD11PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGC_PAD11PULL */ + GPIO_PADREGC_PAD11PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGC_PAD11PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGC_PAD11PULL_Enum; + +/* =========================================== GPIO PADREGC PAD10FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGC_PAD10FNCSEL */ + GPIO_PADREGC_PAD10FNCSEL_M1MOSI = 1, /*!< M1MOSI : Configure as the IOMSTR1 SPI MOSI signal value. */ + GPIO_PADREGC_PAD10FNCSEL_NCE10 = 2, /*!< NCE10 : IOM/MSPI nCE group 10 value. */ + GPIO_PADREGC_PAD10FNCSEL_GPIO10 = 3, /*!< GPIO10 : Configure as GPIO10 value. */ + GPIO_PADREGC_PAD10FNCSEL_PDMCLK = 4, /*!< PDMCLK : PDM serial clock out value. */ + GPIO_PADREGC_PAD10FNCSEL_UA1RTS = 5, /*!< UA1RTS : Configure as the UART1 RTS output signal value. */ +} GPIO_PADREGC_PAD10FNCSEL_Enum; + +/* =========================================== GPIO PADREGC PAD10STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGC_PAD10STRNG */ + GPIO_PADREGC_PAD10STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGC_PAD10STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGC_PAD10STRNG_Enum; + +/* =========================================== GPIO PADREGC PAD10INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGC_PAD10INPEN */ + GPIO_PADREGC_PAD10INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGC_PAD10INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGC_PAD10INPEN_Enum; + +/* ============================================ GPIO PADREGC PAD10PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGC_PAD10PULL */ + GPIO_PADREGC_PAD10PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGC_PAD10PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGC_PAD10PULL_Enum; + +/* ============================================ GPIO PADREGC PAD9RSEL [14..15] ============================================= */ +typedef enum { /*!< GPIO_PADREGC_PAD9RSEL */ + GPIO_PADREGC_PAD9RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGC_PAD9RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGC_PAD9RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGC_PAD9RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGC_PAD9RSEL_Enum; + +/* =========================================== GPIO PADREGC PAD9FNCSEL [11..13] ============================================ */ +typedef enum { /*!< GPIO_PADREGC_PAD9FNCSEL */ + GPIO_PADREGC_PAD9FNCSEL_M1SDAWIR3 = 0, /*!< M1SDAWIR3 : Configure as the IOMSTR1 I2C SDA or SPI WIR3 signal + value. */ + GPIO_PADREGC_PAD9FNCSEL_M1MISO = 1, /*!< M1MISO : Configure as the IOMSTR1 SPI MISO signal value. */ + GPIO_PADREGC_PAD9FNCSEL_NCE9 = 2, /*!< NCE9 : IOM/MSPI nCE group 9 value. */ + GPIO_PADREGC_PAD9FNCSEL_GPIO9 = 3, /*!< GPIO9 : Configure as GPIO9 value. */ + GPIO_PADREGC_PAD9FNCSEL_SCCIO = 4, /*!< SCCIO : SCARD data I/O connection value. */ + GPIO_PADREGC_PAD9FNCSEL_UART1RX = 6, /*!< UART1RX : Configure as UART1 RX input signal value. */ +} GPIO_PADREGC_PAD9FNCSEL_Enum; + +/* ============================================ GPIO PADREGC PAD9STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGC_PAD9STRNG */ + GPIO_PADREGC_PAD9STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGC_PAD9STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGC_PAD9STRNG_Enum; + +/* ============================================= GPIO PADREGC PAD9INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGC_PAD9INPEN */ + GPIO_PADREGC_PAD9INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGC_PAD9INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGC_PAD9INPEN_Enum; + +/* ============================================= GPIO PADREGC PAD9PULL [8..8] ============================================== */ +typedef enum { /*!< GPIO_PADREGC_PAD9PULL */ + GPIO_PADREGC_PAD9PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGC_PAD9PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGC_PAD9PULL_Enum; + +/* ============================================= GPIO PADREGC PAD8RSEL [6..7] ============================================== */ +typedef enum { /*!< GPIO_PADREGC_PAD8RSEL */ + GPIO_PADREGC_PAD8RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGC_PAD8RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGC_PAD8RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGC_PAD8RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGC_PAD8RSEL_Enum; + +/* ============================================ GPIO PADREGC PAD8FNCSEL [3..5] ============================================= */ +typedef enum { /*!< GPIO_PADREGC_PAD8FNCSEL */ + GPIO_PADREGC_PAD8FNCSEL_M1SCL = 0, /*!< M1SCL : Configure as the IOMSTR1 I2C SCL signal value. */ + GPIO_PADREGC_PAD8FNCSEL_M1SCK = 1, /*!< M1SCK : Configure as the IOMSTR1 SPI SCK signal value. */ + GPIO_PADREGC_PAD8FNCSEL_NCE8 = 2, /*!< NCE8 : IOM/MSPI nCE group 8 value. */ + GPIO_PADREGC_PAD8FNCSEL_GPIO8 = 3, /*!< GPIO8 : Configure as GPIO8 value. */ + GPIO_PADREGC_PAD8FNCSEL_SCCLK = 4, /*!< SCCLK : SCARD serial clock output value. */ + GPIO_PADREGC_PAD8FNCSEL_UART1TX = 6, /*!< UART1TX : Configure as the UART1 TX output signal value. */ +} GPIO_PADREGC_PAD8FNCSEL_Enum; + +/* ============================================= GPIO PADREGC PAD8STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGC_PAD8STRNG */ + GPIO_PADREGC_PAD8STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGC_PAD8STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGC_PAD8STRNG_Enum; + +/* ============================================= GPIO PADREGC PAD8INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGC_PAD8INPEN */ + GPIO_PADREGC_PAD8INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGC_PAD8INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGC_PAD8INPEN_Enum; + +/* ============================================= GPIO PADREGC PAD8PULL [0..0] ============================================== */ +typedef enum { /*!< GPIO_PADREGC_PAD8PULL */ + GPIO_PADREGC_PAD8PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGC_PAD8PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGC_PAD8PULL_Enum; + +/* ======================================================== PADREGD ======================================================== */ +/* =========================================== GPIO PADREGD PAD15FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGD_PAD15FNCSEL */ + GPIO_PADREGD_PAD15FNCSEL_ADCD1N = 0, /*!< ADCD1N : Configure as the analog ADC differential pair 1 N input + signal value. */ + GPIO_PADREGD_PAD15FNCSEL_NCE15 = 1, /*!< NCE15 : IOM/MSPI nCE group 15 value. */ + GPIO_PADREGD_PAD15FNCSEL_UART1RX = 2, /*!< UART1RX : Configure as the UART1 RX signal value. */ + GPIO_PADREGD_PAD15FNCSEL_GPIO15 = 3, /*!< GPIO15 : Configure as GPIO15 value. */ + GPIO_PADREGD_PAD15FNCSEL_PDMDATA = 4, /*!< PDMDATA : PDM serial data input value. */ + GPIO_PADREGD_PAD15FNCSEL_EXTXT = 5, /*!< EXTXT : Configure as the external XTAL oscillator input value. */ + GPIO_PADREGD_PAD15FNCSEL_SWDIO = 6, /*!< SWDIO : Configure as an alternate port for the SWDIO I/O signal + value. */ + GPIO_PADREGD_PAD15FNCSEL_SWO = 7, /*!< SWO : Configure as an SWO (Serial Wire Trace output) value. */ +} GPIO_PADREGD_PAD15FNCSEL_Enum; + +/* =========================================== GPIO PADREGD PAD15STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGD_PAD15STRNG */ + GPIO_PADREGD_PAD15STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGD_PAD15STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGD_PAD15STRNG_Enum; + +/* =========================================== GPIO PADREGD PAD15INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGD_PAD15INPEN */ + GPIO_PADREGD_PAD15INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGD_PAD15INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGD_PAD15INPEN_Enum; + +/* ============================================ GPIO PADREGD PAD15PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGD_PAD15PULL */ + GPIO_PADREGD_PAD15PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGD_PAD15PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGD_PAD15PULL_Enum; + +/* =========================================== GPIO PADREGD PAD14FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGD_PAD14FNCSEL */ + GPIO_PADREGD_PAD14FNCSEL_ADCD1P = 0, /*!< ADCD1P : Configure as the analog ADC differential pair 1 P input + signal value. */ + GPIO_PADREGD_PAD14FNCSEL_NCE14 = 1, /*!< NCE14 : IOM/MSPI nCE group 14 value. */ + GPIO_PADREGD_PAD14FNCSEL_UART1TX = 2, /*!< UART1TX : Configure as the UART1 TX output signal value. */ + GPIO_PADREGD_PAD14FNCSEL_GPIO14 = 3, /*!< GPIO14 : Configure as GPIO14 value. */ + GPIO_PADREGD_PAD14FNCSEL_PDMCLK = 4, /*!< PDMCLK : PDM serial clock output value. */ + GPIO_PADREGD_PAD14FNCSEL_EXTHFS = 5, /*!< EXTHFS : Configure as the External HFRC oscillator input select + value. */ + GPIO_PADREGD_PAD14FNCSEL_SWDCK = 6, /*!< SWDCK : Configure as the alternate input for the SWDCK input + signal value. */ + GPIO_PADREGD_PAD14FNCSEL_32kHzXT = 7, /*!< 32kHzXT : Configure as the 32kHz crystal output signal value. */ +} GPIO_PADREGD_PAD14FNCSEL_Enum; + +/* =========================================== GPIO PADREGD PAD14STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGD_PAD14STRNG */ + GPIO_PADREGD_PAD14STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGD_PAD14STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGD_PAD14STRNG_Enum; + +/* =========================================== GPIO PADREGD PAD14INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGD_PAD14INPEN */ + GPIO_PADREGD_PAD14INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGD_PAD14INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGD_PAD14INPEN_Enum; + +/* ============================================ GPIO PADREGD PAD14PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGD_PAD14PULL */ + GPIO_PADREGD_PAD14PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGD_PAD14PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGD_PAD14PULL_Enum; + +/* =========================================== GPIO PADREGD PAD13FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGD_PAD13FNCSEL */ + GPIO_PADREGD_PAD13FNCSEL_ADCD0PSE8 = 0, /*!< ADCD0PSE8 : Configure as the ADC Differential pair 0 P, or Single + Ended input 8 analog input signal. Determination of the + D0P vs SE8 usage is done when the particular channel is + selected within the ADC module value. */ + GPIO_PADREGD_PAD13FNCSEL_NCE13 = 1, /*!< NCE13 : IOM/MSPI nCE group 13 value. */ + GPIO_PADREGD_PAD13FNCSEL_CT2 = 2, /*!< CT2 : CTIMER connection 2 value. */ + GPIO_PADREGD_PAD13FNCSEL_GPIO13 = 3, /*!< GPIO13 : Configure as GPIO13 value. */ + GPIO_PADREGD_PAD13FNCSEL_I2SBCLK = 4, /*!< I2SBCLK : I2C interface bit clock value. */ + GPIO_PADREGD_PAD13FNCSEL_EXTHFB = 5, /*!< EXTHFB : Configure as the external HFRC oscillator input value. */ + GPIO_PADREGD_PAD13FNCSEL_UA0RTS = 6, /*!< UA0RTS : Configure as the UART0 RTS signal output value. */ + GPIO_PADREGD_PAD13FNCSEL_UART1RX = 7, /*!< UART1RX : Configure as the UART1 RX input signal value. */ +} GPIO_PADREGD_PAD13FNCSEL_Enum; + +/* =========================================== GPIO PADREGD PAD13STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGD_PAD13STRNG */ + GPIO_PADREGD_PAD13STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGD_PAD13STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGD_PAD13STRNG_Enum; + +/* ============================================ GPIO PADREGD PAD13INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGD_PAD13INPEN */ + GPIO_PADREGD_PAD13INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGD_PAD13INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGD_PAD13INPEN_Enum; + +/* ============================================= GPIO PADREGD PAD13PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGD_PAD13PULL */ + GPIO_PADREGD_PAD13PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGD_PAD13PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGD_PAD13PULL_Enum; + +/* ============================================ GPIO PADREGD PAD12FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGD_PAD12FNCSEL */ + GPIO_PADREGD_PAD12FNCSEL_ADCD0NSE9 = 0, /*!< ADCD0NSE9 : Configure as the ADC Differential pair 0 N, or Single + Ended input 9 analog input signal. Determination of the + D0N vs SE9 usage is done when the particular channel is + selected within the ADC module value. */ + GPIO_PADREGD_PAD12FNCSEL_NCE12 = 1, /*!< NCE12 : IOM/MSPI nCE group 12 value. */ + GPIO_PADREGD_PAD12FNCSEL_CT0 = 2, /*!< CT0 : CTIMER connection 0 value. */ + GPIO_PADREGD_PAD12FNCSEL_GPIO12 = 3, /*!< GPIO12 : Configure as GPIO12 value. */ + GPIO_PADREGD_PAD12FNCSEL_SLnCE = 4, /*!< SLnCE : Configure as the IOSLAVE SPI nCE signal value. */ + GPIO_PADREGD_PAD12FNCSEL_PDMCLK = 5, /*!< PDMCLK : PDM serial clock output value. */ + GPIO_PADREGD_PAD12FNCSEL_UA0CTS = 6, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ + GPIO_PADREGD_PAD12FNCSEL_UART1TX = 7, /*!< UART1TX : Configure as the UART1 TX output signal value. */ +} GPIO_PADREGD_PAD12FNCSEL_Enum; + +/* ============================================ GPIO PADREGD PAD12STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGD_PAD12STRNG */ + GPIO_PADREGD_PAD12STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGD_PAD12STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGD_PAD12STRNG_Enum; + +/* ============================================ GPIO PADREGD PAD12INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGD_PAD12INPEN */ + GPIO_PADREGD_PAD12INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGD_PAD12INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGD_PAD12INPEN_Enum; + +/* ============================================= GPIO PADREGD PAD12PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGD_PAD12PULL */ + GPIO_PADREGD_PAD12PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGD_PAD12PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGD_PAD12PULL_Enum; + +/* ======================================================== PADREGE ======================================================== */ +/* =========================================== GPIO PADREGE PAD19FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGE_PAD19FNCSEL */ + GPIO_PADREGE_PAD19FNCSEL_CMPRF0 = 0, /*!< CMPRF0 : Configure as the analog comparator reference 0 signal + value. */ + GPIO_PADREGE_PAD19FNCSEL_NCE19 = 1, /*!< NCE19 : IOM/MSPI nCE group 19 value. */ + GPIO_PADREGE_PAD19FNCSEL_CT6 = 2, /*!< CT6 : CTIMER conenction 6 value. */ + GPIO_PADREGE_PAD19FNCSEL_GPIO19 = 3, /*!< GPIO19 : Configure as GPIO19 value. */ + GPIO_PADREGE_PAD19FNCSEL_SCCLK = 4, /*!< SCCLK : SCARD serial clock value. */ + GPIO_PADREGE_PAD19FNCSEL_ANATEST1 = 5, /*!< ANATEST1 : Configure as the ANATEST1 I/O signal value. */ + GPIO_PADREGE_PAD19FNCSEL_UART1RX = 6, /*!< UART1RX : Configure as the UART1 RX input signal value. */ + GPIO_PADREGE_PAD19FNCSEL_I2SBCLK = 7, /*!< I2SBCLK : Configure as the PDM I2S bit clock input signal value. */ +} GPIO_PADREGE_PAD19FNCSEL_Enum; + +/* =========================================== GPIO PADREGE PAD19STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGE_PAD19STRNG */ + GPIO_PADREGE_PAD19STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGE_PAD19STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGE_PAD19STRNG_Enum; + +/* =========================================== GPIO PADREGE PAD19INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGE_PAD19INPEN */ + GPIO_PADREGE_PAD19INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGE_PAD19INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGE_PAD19INPEN_Enum; + +/* ============================================ GPIO PADREGE PAD19PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGE_PAD19PULL */ + GPIO_PADREGE_PAD19PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGE_PAD19PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGE_PAD19PULL_Enum; + +/* =========================================== GPIO PADREGE PAD18FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGE_PAD18FNCSEL */ + GPIO_PADREGE_PAD18FNCSEL_CMPIN1 = 0, /*!< CMPIN1 : Configure as the analog comparator input 1 signal value. */ + GPIO_PADREGE_PAD18FNCSEL_NCE18 = 1, /*!< NCE18 : IOM/MSPI nCE group 18 value. */ + GPIO_PADREGE_PAD18FNCSEL_CT4 = 2, /*!< CT4 : CTIMER connection 4 value. */ + GPIO_PADREGE_PAD18FNCSEL_GPIO18 = 3, /*!< GPIO18 : Configure as GPIO18 value. */ + GPIO_PADREGE_PAD18FNCSEL_UA0RTS = 4, /*!< UA0RTS : Configure as UART0 RTS output signal value. */ + GPIO_PADREGE_PAD18FNCSEL_ANATEST2 = 5, /*!< ANATEST2 : Configure as ANATEST2 I/O signal value. */ + GPIO_PADREGE_PAD18FNCSEL_UART1TX = 6, /*!< UART1TX : Configure as UART1 TX output signal value. */ + GPIO_PADREGE_PAD18FNCSEL_SCCIO = 7, /*!< SCCIO : SCARD data input/output connectin value. */ +} GPIO_PADREGE_PAD18FNCSEL_Enum; + +/* =========================================== GPIO PADREGE PAD18STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGE_PAD18STRNG */ + GPIO_PADREGE_PAD18STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGE_PAD18STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGE_PAD18STRNG_Enum; + +/* =========================================== GPIO PADREGE PAD18INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGE_PAD18INPEN */ + GPIO_PADREGE_PAD18INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGE_PAD18INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGE_PAD18INPEN_Enum; + +/* ============================================ GPIO PADREGE PAD18PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGE_PAD18PULL */ + GPIO_PADREGE_PAD18PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGE_PAD18PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGE_PAD18PULL_Enum; + +/* =========================================== GPIO PADREGE PAD17FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGE_PAD17FNCSEL */ + GPIO_PADREGE_PAD17FNCSEL_CMPRF1 = 0, /*!< CMPRF1 : Configure as the analog comparator reference signal + 1 input signal value. */ + GPIO_PADREGE_PAD17FNCSEL_NCE17 = 1, /*!< NCE17 : IOM/MSPI nCE group 17 value. */ + GPIO_PADREGE_PAD17FNCSEL_TRIG1 = 2, /*!< TRIG1 : Configure as the ADC Trigger 1 signal value. */ + GPIO_PADREGE_PAD17FNCSEL_GPIO17 = 3, /*!< GPIO17 : Configure as GPIO17 value. */ + GPIO_PADREGE_PAD17FNCSEL_SCCCLK = 4, /*!< SCCCLK : SCARD serial clock output value. */ + GPIO_PADREGE_PAD17FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as UART0 RX input signal value. */ + GPIO_PADREGE_PAD17FNCSEL_UA1CTS = 7, /*!< UA1CTS : Configure as UART1 CTS input signal value. */ +} GPIO_PADREGE_PAD17FNCSEL_Enum; + +/* =========================================== GPIO PADREGE PAD17STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGE_PAD17STRNG */ + GPIO_PADREGE_PAD17STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGE_PAD17STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGE_PAD17STRNG_Enum; + +/* ============================================ GPIO PADREGE PAD17INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGE_PAD17INPEN */ + GPIO_PADREGE_PAD17INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGE_PAD17INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGE_PAD17INPEN_Enum; + +/* ============================================= GPIO PADREGE PAD17PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGE_PAD17PULL */ + GPIO_PADREGE_PAD17PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGE_PAD17PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGE_PAD17PULL_Enum; + +/* ============================================ GPIO PADREGE PAD16FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGE_PAD16FNCSEL */ + GPIO_PADREGE_PAD16FNCSEL_ADCSE0 = 0, /*!< ADCSE0 : Configure as the analog ADC single ended port 0 input + signal value. */ + GPIO_PADREGE_PAD16FNCSEL_NCE16 = 1, /*!< NCE16 : IOM/MSPI nCE group 16 value. */ + GPIO_PADREGE_PAD16FNCSEL_TRIG0 = 2, /*!< TRIG0 : Configure as the ADC Trigger 0 signal value. */ + GPIO_PADREGE_PAD16FNCSEL_GPIO16 = 3, /*!< GPIO16 : Configure as GPIO16 value. */ + GPIO_PADREGE_PAD16FNCSEL_SCCRST = 4, /*!< SCCRST : SCARD reset output value. */ + GPIO_PADREGE_PAD16FNCSEL_CMPIN0 = 5, /*!< CMPIN0 : Configure as comparator input 0 signal value. */ + GPIO_PADREGE_PAD16FNCSEL_UART0TX = 6, /*!< UART0TX : Configure as UART0 TX output signal value. */ + GPIO_PADREGE_PAD16FNCSEL_UA1RTS = 7, /*!< UA1RTS : Configure as UART1 RTS output signal value. */ +} GPIO_PADREGE_PAD16FNCSEL_Enum; + +/* ============================================ GPIO PADREGE PAD16STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGE_PAD16STRNG */ + GPIO_PADREGE_PAD16STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGE_PAD16STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGE_PAD16STRNG_Enum; + +/* ============================================ GPIO PADREGE PAD16INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGE_PAD16INPEN */ + GPIO_PADREGE_PAD16INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGE_PAD16INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGE_PAD16INPEN_Enum; + +/* ============================================= GPIO PADREGE PAD16PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGE_PAD16PULL */ + GPIO_PADREGE_PAD16PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGE_PAD16PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGE_PAD16PULL_Enum; + +/* ======================================================== PADREGF ======================================================== */ +/* =========================================== GPIO PADREGF PAD23FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGF_PAD23FNCSEL */ + GPIO_PADREGF_PAD23FNCSEL_UART0RX = 0, /*!< UART0RX : Configure as the UART0 RX signal value. */ + GPIO_PADREGF_PAD23FNCSEL_NCE23 = 1, /*!< NCE23 : IOM/MSPI nCE group 23 value. */ + GPIO_PADREGF_PAD23FNCSEL_CT14 = 2, /*!< CT14 : CTIMER connection 14 value. */ + GPIO_PADREGF_PAD23FNCSEL_GPIO23 = 3, /*!< GPIO23 : Configure as GPIO23 value. */ + GPIO_PADREGF_PAD23FNCSEL_I2SWCLK = 4, /*!< I2SWCLK : I2S word clock input value. */ + GPIO_PADREGF_PAD23FNCSEL_CMPOUT = 5, /*!< CMPOUT : Configure as voltage comparitor output value. */ + GPIO_PADREGF_PAD23FNCSEL_MSPI3 = 6, /*!< MSPI3 : MSPI data connection 3 value. */ + GPIO_PADREGF_PAD23FNCSEL_EXTXT = 7, /*!< EXTXT : External XTAL osacillatgor input value. */ +} GPIO_PADREGF_PAD23FNCSEL_Enum; + +/* =========================================== GPIO PADREGF PAD23STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGF_PAD23STRNG */ + GPIO_PADREGF_PAD23STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGF_PAD23STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGF_PAD23STRNG_Enum; + +/* =========================================== GPIO PADREGF PAD23INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGF_PAD23INPEN */ + GPIO_PADREGF_PAD23INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGF_PAD23INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGF_PAD23INPEN_Enum; + +/* ============================================ GPIO PADREGF PAD23PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGF_PAD23PULL */ + GPIO_PADREGF_PAD23PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGF_PAD23PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGF_PAD23PULL_Enum; + +/* =========================================== GPIO PADREGF PAD22FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGF_PAD22FNCSEL */ + GPIO_PADREGF_PAD22FNCSEL_UART0TX = 0, /*!< UART0TX : Configure as the UART0 TX signal value. */ + GPIO_PADREGF_PAD22FNCSEL_NCE22 = 1, /*!< NCE22 : IOM/MSPI nCE group 22 value. */ + GPIO_PADREGF_PAD22FNCSEL_CT12 = 2, /*!< CT12 : CTIMER connection 12 value. */ + GPIO_PADREGF_PAD22FNCSEL_GPIO22 = 3, /*!< GPIO22 : Configure as GPIO22 value. */ + GPIO_PADREGF_PAD22FNCSEL_PDM_CLK = 4, /*!< PDM_CLK : Configure as the PDM CLK output value. */ + GPIO_PADREGF_PAD22FNCSEL_EXTLF = 5, /*!< EXTLF : External LFRC input value. */ + GPIO_PADREGF_PAD22FNCSEL_MSPI0 = 6, /*!< MSPI0 : MSPI data connection 0 value. */ + GPIO_PADREGF_PAD22FNCSEL_SWO = 7, /*!< SWO : Configure as the serial trace data output signal value. */ +} GPIO_PADREGF_PAD22FNCSEL_Enum; + +/* =========================================== GPIO PADREGF PAD22STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGF_PAD22STRNG */ + GPIO_PADREGF_PAD22STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGF_PAD22STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGF_PAD22STRNG_Enum; + +/* =========================================== GPIO PADREGF PAD22INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGF_PAD22INPEN */ + GPIO_PADREGF_PAD22INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGF_PAD22INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGF_PAD22INPEN_Enum; + +/* ============================================ GPIO PADREGF PAD22PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGF_PAD22PULL */ + GPIO_PADREGF_PAD22PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGF_PAD22PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGF_PAD22PULL_Enum; + +/* =========================================== GPIO PADREGF PAD21FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGF_PAD21FNCSEL */ + GPIO_PADREGF_PAD21FNCSEL_SWDIO = 0, /*!< SWDIO : Configure as the serial wire debug data signal value. */ + GPIO_PADREGF_PAD21FNCSEL_NCE21 = 1, /*!< NCE21 : IOM/MSPI nCE group 21 value. */ + GPIO_PADREGF_PAD21FNCSEL_GPIO21 = 3, /*!< GPIO21 : Configure as GPIO21 value. */ + GPIO_PADREGF_PAD21FNCSEL_UART0RX = 4, /*!< UART0RX : Configure as UART0 RX input signal value. */ + GPIO_PADREGF_PAD21FNCSEL_UART1RX = 5, /*!< UART1RX : Configure as UART1 RX input signal value. */ + GPIO_PADREGF_PAD21FNCSEL_I2SBCLK = 6, /*!< I2SBCLK : I2S byte clock input value. */ + GPIO_PADREGF_PAD21FNCSEL_UA1CTS = 7, /*!< UA1CTS : Configure as UART1 CTS input signal value. */ +} GPIO_PADREGF_PAD21FNCSEL_Enum; + +/* =========================================== GPIO PADREGF PAD21STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGF_PAD21STRNG */ + GPIO_PADREGF_PAD21STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGF_PAD21STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGF_PAD21STRNG_Enum; + +/* ============================================ GPIO PADREGF PAD21INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGF_PAD21INPEN */ + GPIO_PADREGF_PAD21INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGF_PAD21INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGF_PAD21INPEN_Enum; + +/* ============================================= GPIO PADREGF PAD21PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGF_PAD21PULL */ + GPIO_PADREGF_PAD21PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGF_PAD21PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGF_PAD21PULL_Enum; + +/* ============================================ GPIO PADREGF PAD20FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGF_PAD20FNCSEL */ + GPIO_PADREGF_PAD20FNCSEL_SWDCK = 0, /*!< SWDCK : Configure as the serial wire debug clock signal value. */ + GPIO_PADREGF_PAD20FNCSEL_NCE20 = 1, /*!< NCE20 : IOM/MSPI nCE group 20 value. */ + GPIO_PADREGF_PAD20FNCSEL_GPIO20 = 3, /*!< GPIO20 : Configure as GPIO20 value. */ + GPIO_PADREGF_PAD20FNCSEL_UART0TX = 4, /*!< UART0TX : Configure as UART0 TX output signal value. */ + GPIO_PADREGF_PAD20FNCSEL_UART1TX = 5, /*!< UART1TX : Configure as UART1 TX output signal value. */ + GPIO_PADREGF_PAD20FNCSEL_I2SBCLK = 6, /*!< I2SBCLK : I2S byte clock input value. */ + GPIO_PADREGF_PAD20FNCSEL_UA1RTS = 7, /*!< UA1RTS : Configure as UART1 RTS output signal value. */ +} GPIO_PADREGF_PAD20FNCSEL_Enum; + +/* ============================================ GPIO PADREGF PAD20STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGF_PAD20STRNG */ + GPIO_PADREGF_PAD20STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGF_PAD20STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGF_PAD20STRNG_Enum; + +/* ============================================ GPIO PADREGF PAD20INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGF_PAD20INPEN */ + GPIO_PADREGF_PAD20INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGF_PAD20INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGF_PAD20INPEN_Enum; + +/* ============================================= GPIO PADREGF PAD20PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGF_PAD20PULL */ + GPIO_PADREGF_PAD20PULL_DIS = 0, /*!< DIS : Pulldown disabled value. */ + GPIO_PADREGF_PAD20PULL_EN = 1, /*!< EN : Pulldown enabled value. */ +} GPIO_PADREGF_PAD20PULL_Enum; + +/* ======================================================== PADREGG ======================================================== */ +/* ============================================ GPIO PADREGG PAD27RSEL [30..31] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD27RSEL */ + GPIO_PADREGG_PAD27RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGG_PAD27RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGG_PAD27RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGG_PAD27RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGG_PAD27RSEL_Enum; + +/* =========================================== GPIO PADREGG PAD27FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGG_PAD27FNCSEL */ + GPIO_PADREGG_PAD27FNCSEL_UART0RX = 0, /*!< UART0RX : Configure as UART0 RX input signal value. */ + GPIO_PADREGG_PAD27FNCSEL_NCE27 = 1, /*!< NCE27 : IOM/MSPI nCE group 27 value. */ + GPIO_PADREGG_PAD27FNCSEL_CT5 = 2, /*!< CT5 : CTIMER connection 5 value. */ + GPIO_PADREGG_PAD27FNCSEL_GPIO27 = 3, /*!< GPIO27 : Configure as GPIO27 value. */ + GPIO_PADREGG_PAD27FNCSEL_M2SCL = 4, /*!< M2SCL : Configure as I2C clock I/O signal from IOMSTR2 value. */ + GPIO_PADREGG_PAD27FNCSEL_M2SCK = 5, /*!< M2SCK : Configure as SPI clock output signal from IOMSTR2 value. */ +} GPIO_PADREGG_PAD27FNCSEL_Enum; + +/* =========================================== GPIO PADREGG PAD27STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD27STRNG */ + GPIO_PADREGG_PAD27STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGG_PAD27STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGG_PAD27STRNG_Enum; + +/* =========================================== GPIO PADREGG PAD27INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD27INPEN */ + GPIO_PADREGG_PAD27INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGG_PAD27INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGG_PAD27INPEN_Enum; + +/* ============================================ GPIO PADREGG PAD27PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD27PULL */ + GPIO_PADREGG_PAD27PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGG_PAD27PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGG_PAD27PULL_Enum; + +/* =========================================== GPIO PADREGG PAD26FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGG_PAD26FNCSEL */ + GPIO_PADREGG_PAD26FNCSEL_EXTHF = 0, /*!< EXTHF : Configure as the external HFRC oscillator input value. */ + GPIO_PADREGG_PAD26FNCSEL_NCE26 = 1, /*!< NCE26 : IOM/MSPI nCE group 26 value. */ + GPIO_PADREGG_PAD26FNCSEL_CT3 = 2, /*!< CT3 : CTIMER connection 3 value. */ + GPIO_PADREGG_PAD26FNCSEL_GPIO26 = 3, /*!< GPIO26 : Configure as GPIO26 value. */ + GPIO_PADREGG_PAD26FNCSEL_SCCRST = 4, /*!< SCCRST : SCARD reset output value. */ + GPIO_PADREGG_PAD26FNCSEL_MSPI1 = 5, /*!< MSPI1 : MSPI data connection 1 value. */ + GPIO_PADREGG_PAD26FNCSEL_UART0TX = 6, /*!< UART0TX : Configure as UART0 TX output signal value. */ + GPIO_PADREGG_PAD26FNCSEL_UA1CTS = 7, /*!< UA1CTS : Configure as UART1 CTS input signal value. */ +} GPIO_PADREGG_PAD26FNCSEL_Enum; + +/* =========================================== GPIO PADREGG PAD26STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD26STRNG */ + GPIO_PADREGG_PAD26STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGG_PAD26STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGG_PAD26STRNG_Enum; + +/* =========================================== GPIO PADREGG PAD26INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD26INPEN */ + GPIO_PADREGG_PAD26INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGG_PAD26INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGG_PAD26INPEN_Enum; + +/* ============================================ GPIO PADREGG PAD26PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD26PULL */ + GPIO_PADREGG_PAD26PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGG_PAD26PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGG_PAD26PULL_Enum; + +/* ============================================ GPIO PADREGG PAD25RSEL [14..15] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD25RSEL */ + GPIO_PADREGG_PAD25RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGG_PAD25RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGG_PAD25RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGG_PAD25RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGG_PAD25RSEL_Enum; + +/* =========================================== GPIO PADREGG PAD25FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGG_PAD25FNCSEL */ + GPIO_PADREGG_PAD25FNCSEL_UART1RX = 0, /*!< UART1RX : Configure as UART1 RX input signal value. */ + GPIO_PADREGG_PAD25FNCSEL_NCE25 = 1, /*!< NCE25 : IOM/MSPI nCE group 25 value. */ + GPIO_PADREGG_PAD25FNCSEL_CT1 = 2, /*!< CT1 : CTIMER connection 1 value. */ + GPIO_PADREGG_PAD25FNCSEL_GPIO25 = 3, /*!< GPIO25 : Configure as GPIO25 value. */ + GPIO_PADREGG_PAD25FNCSEL_M2SDAWIR3 = 4, /*!< M2SDAWIR3 : Configure as the IOMSTR2 I2C SDA or SPI WIR3 signal + value. */ + GPIO_PADREGG_PAD25FNCSEL_M2MISO = 5, /*!< M2MISO : Configure as the IOMSTR2 SPI MISO input signal value. */ +} GPIO_PADREGG_PAD25FNCSEL_Enum; + +/* =========================================== GPIO PADREGG PAD25STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD25STRNG */ + GPIO_PADREGG_PAD25STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGG_PAD25STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGG_PAD25STRNG_Enum; + +/* ============================================ GPIO PADREGG PAD25INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGG_PAD25INPEN */ + GPIO_PADREGG_PAD25INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGG_PAD25INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGG_PAD25INPEN_Enum; + +/* ============================================= GPIO PADREGG PAD25PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGG_PAD25PULL */ + GPIO_PADREGG_PAD25PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGG_PAD25PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGG_PAD25PULL_Enum; + +/* ============================================ GPIO PADREGG PAD24FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGG_PAD24FNCSEL */ + GPIO_PADREGG_PAD24FNCSEL_UART1TX = 0, /*!< UART1TX : Configure as UART1 TX output signal value. */ + GPIO_PADREGG_PAD24FNCSEL_NCE24 = 1, /*!< NCE24 : IOM/MSPI nCE group 24 value. */ + GPIO_PADREGG_PAD24FNCSEL_MSPI8 = 2, /*!< MSPI8 : MSPI data connection 8 value. */ + GPIO_PADREGG_PAD24FNCSEL_GPIO24 = 3, /*!< GPIO24 : Configure as GPIO24 value. */ + GPIO_PADREGG_PAD24FNCSEL_UA0CTS = 4, /*!< UA0CTS : Configure as UART0 CTS input signal value. */ + GPIO_PADREGG_PAD24FNCSEL_CT21 = 5, /*!< CT21 : CTIMER connection 21 value. */ + GPIO_PADREGG_PAD24FNCSEL_32kHzXT = 6, /*!< 32kHzXT : Configure as the 32kHz crystal output signal value. */ + GPIO_PADREGG_PAD24FNCSEL_SWO = 7, /*!< SWO : Configure as the serial trace data output signal value. */ +} GPIO_PADREGG_PAD24FNCSEL_Enum; + +/* ============================================ GPIO PADREGG PAD24STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGG_PAD24STRNG */ + GPIO_PADREGG_PAD24STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGG_PAD24STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGG_PAD24STRNG_Enum; + +/* ============================================ GPIO PADREGG PAD24INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGG_PAD24INPEN */ + GPIO_PADREGG_PAD24INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGG_PAD24INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGG_PAD24INPEN_Enum; + +/* ============================================= GPIO PADREGG PAD24PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGG_PAD24PULL */ + GPIO_PADREGG_PAD24PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGG_PAD24PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGG_PAD24PULL_Enum; + +/* ======================================================== PADREGH ======================================================== */ +/* =========================================== GPIO PADREGH PAD31FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGH_PAD31FNCSEL */ + GPIO_PADREGH_PAD31FNCSEL_ADCSE3 = 0, /*!< ADCSE3 : Configure as the analog input for ADC single ended + input 3 value. */ + GPIO_PADREGH_PAD31FNCSEL_NCE31 = 1, /*!< NCE31 : IOM/MSPI nCE group 31 value. */ + GPIO_PADREGH_PAD31FNCSEL_CT13 = 2, /*!< CT13 : CTIMER connection 13 value. */ + GPIO_PADREGH_PAD31FNCSEL_GPIO31 = 3, /*!< GPIO31 : Configure as GPIO31 value. */ + GPIO_PADREGH_PAD31FNCSEL_UART0RX = 4, /*!< UART0RX : Configure as the UART0 RX input signal value. */ + GPIO_PADREGH_PAD31FNCSEL_SCCCLK = 5, /*!< SCCCLK : SCARD serial clock output value. */ + GPIO_PADREGH_PAD31FNCSEL_UA1RTS = 7, /*!< UA1RTS : Configure as UART1 RTS output signal value. */ +} GPIO_PADREGH_PAD31FNCSEL_Enum; + +/* =========================================== GPIO PADREGH PAD31STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGH_PAD31STRNG */ + GPIO_PADREGH_PAD31STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGH_PAD31STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGH_PAD31STRNG_Enum; + +/* =========================================== GPIO PADREGH PAD31INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGH_PAD31INPEN */ + GPIO_PADREGH_PAD31INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGH_PAD31INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGH_PAD31INPEN_Enum; + +/* ============================================ GPIO PADREGH PAD31PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGH_PAD31PULL */ + GPIO_PADREGH_PAD31PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGH_PAD31PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGH_PAD31PULL_Enum; + +/* =========================================== GPIO PADREGH PAD30FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGH_PAD30FNCSEL */ + GPIO_PADREGH_PAD30FNCSEL_ANATEST1 = 0, /*!< ANATEST1 : Configure as the ANATEST1 I/O signal value. */ + GPIO_PADREGH_PAD30FNCSEL_NCE30 = 1, /*!< NCE30 : IOM/MSPI nCE group 30 value. */ + GPIO_PADREGH_PAD30FNCSEL_CT11 = 2, /*!< CT11 : CTIMER connection 11 value. */ + GPIO_PADREGH_PAD30FNCSEL_GPIO30 = 3, /*!< GPIO30 : Configure as GPIO30 value. */ + GPIO_PADREGH_PAD30FNCSEL_UART0TX = 4, /*!< UART0TX : Configure as UART0 TX output signal value. */ + GPIO_PADREGH_PAD30FNCSEL_UA1RTS = 5, /*!< UA1RTS : Configure as UART1 RTS output signal value. */ + GPIO_PADREGH_PAD30FNCSEL_I2S_DAT = 7, /*!< I2S_DAT : Configure as the PDM I2S Data output signal value. */ +} GPIO_PADREGH_PAD30FNCSEL_Enum; + +/* =========================================== GPIO PADREGH PAD30STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGH_PAD30STRNG */ + GPIO_PADREGH_PAD30STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGH_PAD30STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGH_PAD30STRNG_Enum; + +/* =========================================== GPIO PADREGH PAD30INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGH_PAD30INPEN */ + GPIO_PADREGH_PAD30INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGH_PAD30INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGH_PAD30INPEN_Enum; + +/* ============================================ GPIO PADREGH PAD30PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGH_PAD30PULL */ + GPIO_PADREGH_PAD30PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGH_PAD30PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGH_PAD30PULL_Enum; + +/* =========================================== GPIO PADREGH PAD29FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGH_PAD29FNCSEL */ + GPIO_PADREGH_PAD29FNCSEL_ADCSE1 = 0, /*!< ADCSE1 : Configure as the analog input for ADC single ended + input 1 value. */ + GPIO_PADREGH_PAD29FNCSEL_NCE29 = 1, /*!< NCE29 : IOM/MSPI nCE group 29 value. */ + GPIO_PADREGH_PAD29FNCSEL_CT9 = 2, /*!< CT9 : CTIMER connection 9 value. */ + GPIO_PADREGH_PAD29FNCSEL_GPIO29 = 3, /*!< GPIO29 : Configure as GPIO29 value. */ + GPIO_PADREGH_PAD29FNCSEL_UA0CTS = 4, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ + GPIO_PADREGH_PAD29FNCSEL_UA1CTS = 5, /*!< UA1CTS : Configure as the UART1 CTS input signal value. */ + GPIO_PADREGH_PAD29FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as the UART0 RX input signal value. */ + GPIO_PADREGH_PAD29FNCSEL_PDM_DATA = 7, /*!< PDM_DATA : Configure as PDM DATA input value. */ +} GPIO_PADREGH_PAD29FNCSEL_Enum; + +/* =========================================== GPIO PADREGH PAD29STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGH_PAD29STRNG */ + GPIO_PADREGH_PAD29STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGH_PAD29STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGH_PAD29STRNG_Enum; + +/* ============================================ GPIO PADREGH PAD29INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGH_PAD29INPEN */ + GPIO_PADREGH_PAD29INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGH_PAD29INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGH_PAD29INPEN_Enum; + +/* ============================================= GPIO PADREGH PAD29PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGH_PAD29PULL */ + GPIO_PADREGH_PAD29PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGH_PAD29PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGH_PAD29PULL_Enum; + +/* ============================================ GPIO PADREGH PAD28FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGH_PAD28FNCSEL */ + GPIO_PADREGH_PAD28FNCSEL_I2S_WCLK = 0, /*!< I2S_WCLK : Configure as the PDM I2S Word Clock input value. */ + GPIO_PADREGH_PAD28FNCSEL_NCE28 = 1, /*!< NCE28 : IOM/MSPI nCE group 28 value. */ + GPIO_PADREGH_PAD28FNCSEL_CT7 = 2, /*!< CT7 : CTIMER connection 7 value. */ + GPIO_PADREGH_PAD28FNCSEL_GPIO28 = 3, /*!< GPIO28 : Configure as GPIO28 value. */ + GPIO_PADREGH_PAD28FNCSEL_M2MOSI = 5, /*!< M2MOSI : Configure as the IOMSTR2 SPI MOSI output signal value. */ + GPIO_PADREGH_PAD28FNCSEL_UART0TX = 6, /*!< UART0TX : Configure as the UART0 TX output signal value. */ +} GPIO_PADREGH_PAD28FNCSEL_Enum; + +/* ============================================ GPIO PADREGH PAD28STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGH_PAD28STRNG */ + GPIO_PADREGH_PAD28STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGH_PAD28STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGH_PAD28STRNG_Enum; + +/* ============================================ GPIO PADREGH PAD28INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGH_PAD28INPEN */ + GPIO_PADREGH_PAD28INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGH_PAD28INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGH_PAD28INPEN_Enum; + +/* ============================================= GPIO PADREGH PAD28PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGH_PAD28PULL */ + GPIO_PADREGH_PAD28PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGH_PAD28PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGH_PAD28PULL_Enum; + +/* ======================================================== PADREGI ======================================================== */ +/* =========================================== GPIO PADREGI PAD35FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGI_PAD35FNCSEL */ + GPIO_PADREGI_PAD35FNCSEL_ADCSE7 = 0, /*!< ADCSE7 : Configure as the analog input for ADC single ended + input 7 value. */ + GPIO_PADREGI_PAD35FNCSEL_NCE35 = 1, /*!< NCE35 : IOM/MSPI nCE group 35 value. */ + GPIO_PADREGI_PAD35FNCSEL_UART1TX = 2, /*!< UART1TX : Configure as the UART1 TX signal value. */ + GPIO_PADREGI_PAD35FNCSEL_GPIO35 = 3, /*!< GPIO35 : Configure as GPIO35 value. */ + GPIO_PADREGI_PAD35FNCSEL_I2SDAT = 4, /*!< I2SDAT : I2S serial data output value. */ + GPIO_PADREGI_PAD35FNCSEL_CT27 = 5, /*!< CT27 : CTIMER connection 27 value. */ + GPIO_PADREGI_PAD35FNCSEL_UA0RTS = 6, /*!< UA0RTS : Configure as the UART0 RTS output value. */ +} GPIO_PADREGI_PAD35FNCSEL_Enum; + +/* =========================================== GPIO PADREGI PAD35STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGI_PAD35STRNG */ + GPIO_PADREGI_PAD35STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGI_PAD35STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGI_PAD35STRNG_Enum; + +/* =========================================== GPIO PADREGI PAD35INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGI_PAD35INPEN */ + GPIO_PADREGI_PAD35INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGI_PAD35INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGI_PAD35INPEN_Enum; + +/* ============================================ GPIO PADREGI PAD35PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGI_PAD35PULL */ + GPIO_PADREGI_PAD35PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGI_PAD35PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGI_PAD35PULL_Enum; + +/* =========================================== GPIO PADREGI PAD34FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGI_PAD34FNCSEL */ + GPIO_PADREGI_PAD34FNCSEL_ADCSE6 = 0, /*!< ADCSE6 : Configure as the analog input for ADC single ended + input 6 value. */ + GPIO_PADREGI_PAD34FNCSEL_NCE34 = 1, /*!< NCE34 : IOM/MSPI nCE group 34 value. */ + GPIO_PADREGI_PAD34FNCSEL_UA1RTS = 2, /*!< UA1RTS : Configure as the UART1 RTS output value. */ + GPIO_PADREGI_PAD34FNCSEL_GPIO34 = 3, /*!< GPIO34 : Configure as GPIO34 value. */ + GPIO_PADREGI_PAD34FNCSEL_CMPRF2 = 4, /*!< CMPRF2 : Configure as the analog comparator reference 2 signal + value. */ + GPIO_PADREGI_PAD34FNCSEL_UA0RTS = 5, /*!< UA0RTS : Configure as the UART0 RTS output value. */ + GPIO_PADREGI_PAD34FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as the UART0 RX input value. */ + GPIO_PADREGI_PAD34FNCSEL_PDMDATA = 7, /*!< PDMDATA : PDM serial data input value. */ +} GPIO_PADREGI_PAD34FNCSEL_Enum; + +/* =========================================== GPIO PADREGI PAD34STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGI_PAD34STRNG */ + GPIO_PADREGI_PAD34STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGI_PAD34STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGI_PAD34STRNG_Enum; + +/* =========================================== GPIO PADREGI PAD34INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGI_PAD34INPEN */ + GPIO_PADREGI_PAD34INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGI_PAD34INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGI_PAD34INPEN_Enum; + +/* ============================================ GPIO PADREGI PAD34PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGI_PAD34PULL */ + GPIO_PADREGI_PAD34PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGI_PAD34PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGI_PAD34PULL_Enum; + +/* =========================================== GPIO PADREGI PAD33FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGI_PAD33FNCSEL */ + GPIO_PADREGI_PAD33FNCSEL_ADCSE5 = 0, /*!< ADCSE5 : Configure as the analog ADC single ended port 5 input + signal value. */ + GPIO_PADREGI_PAD33FNCSEL_NCE33 = 1, /*!< NCE33 : IOM/MSPI nCE group 33 value. */ + GPIO_PADREGI_PAD33FNCSEL_32kHzXT = 2, /*!< 32kHzXT : Configure as the 32kHz crystal output signal value. */ + GPIO_PADREGI_PAD33FNCSEL_GPIO33 = 3, /*!< GPIO33 : Configure as GPIO33 value. */ + GPIO_PADREGI_PAD33FNCSEL_UA0CTS = 5, /*!< UA0CTS : Configure as the UART0 CTS input value. */ + GPIO_PADREGI_PAD33FNCSEL_CT23 = 6, /*!< CT23 : CTIMER connection 23 value. */ + GPIO_PADREGI_PAD33FNCSEL_SWO = 7, /*!< SWO : Configure as the serial trace data output signal value. */ +} GPIO_PADREGI_PAD33FNCSEL_Enum; + +/* =========================================== GPIO PADREGI PAD33STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGI_PAD33STRNG */ + GPIO_PADREGI_PAD33STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGI_PAD33STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGI_PAD33STRNG_Enum; + +/* ============================================ GPIO PADREGI PAD33INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGI_PAD33INPEN */ + GPIO_PADREGI_PAD33INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGI_PAD33INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGI_PAD33INPEN_Enum; + +/* ============================================= GPIO PADREGI PAD33PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGI_PAD33PULL */ + GPIO_PADREGI_PAD33PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGI_PAD33PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGI_PAD33PULL_Enum; + +/* ============================================ GPIO PADREGI PAD32FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGI_PAD32FNCSEL */ + GPIO_PADREGI_PAD32FNCSEL_ADCSE4 = 0, /*!< ADCSE4 : Configure as the analog input for ADC single ended + input 4 value. */ + GPIO_PADREGI_PAD32FNCSEL_NCE32 = 1, /*!< NCE32 : IOM/MSPI nCE group 32 value. */ + GPIO_PADREGI_PAD32FNCSEL_CT15 = 2, /*!< CT15 : CTIMER connection 15 value. */ + GPIO_PADREGI_PAD32FNCSEL_GPIO32 = 3, /*!< GPIO32 : Configure as GPIO32 value. */ + GPIO_PADREGI_PAD32FNCSEL_SCCIO = 4, /*!< SCCIO : SCARD serial data input/output value. */ + GPIO_PADREGI_PAD32FNCSEL_EXTLF = 5, /*!< EXTLF : External input to the LFRC oscillator value. */ + GPIO_PADREGI_PAD32FNCSEL_UA1CTS = 7, /*!< UA1CTS : Configure as the UART1 CTS input value. */ +} GPIO_PADREGI_PAD32FNCSEL_Enum; + +/* ============================================ GPIO PADREGI PAD32STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGI_PAD32STRNG */ + GPIO_PADREGI_PAD32STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGI_PAD32STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGI_PAD32STRNG_Enum; + +/* ============================================ GPIO PADREGI PAD32INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGI_PAD32INPEN */ + GPIO_PADREGI_PAD32INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGI_PAD32INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGI_PAD32INPEN_Enum; + +/* ============================================= GPIO PADREGI PAD32PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGI_PAD32PULL */ + GPIO_PADREGI_PAD32PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGI_PAD32PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGI_PAD32PULL_Enum; + +/* ======================================================== PADREGJ ======================================================== */ +/* ============================================ GPIO PADREGJ PAD39RSEL [30..31] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD39RSEL */ + GPIO_PADREGJ_PAD39RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGJ_PAD39RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGJ_PAD39RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGJ_PAD39RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGJ_PAD39RSEL_Enum; + +/* =========================================== GPIO PADREGJ PAD39FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGJ_PAD39FNCSEL */ + GPIO_PADREGJ_PAD39FNCSEL_UART0TX = 0, /*!< UART0TX : Configure as the UART0 TX output signal value. */ + GPIO_PADREGJ_PAD39FNCSEL_UART1TX = 1, /*!< UART1TX : Configure as the UART1 TX output signal value. */ + GPIO_PADREGJ_PAD39FNCSEL_CT25 = 2, /*!< CT25 : CTIMER connection 25 value. */ + GPIO_PADREGJ_PAD39FNCSEL_GPIO39 = 3, /*!< GPIO39 : Configure as GPIO39 value. */ + GPIO_PADREGJ_PAD39FNCSEL_M4SCL = 4, /*!< M4SCL : Configure as the IOMSTR4 I2C SCL signal value. */ + GPIO_PADREGJ_PAD39FNCSEL_M4SCK = 5, /*!< M4SCK : Configure as the IOMSTR4 SPI SCK signal value. */ +} GPIO_PADREGJ_PAD39FNCSEL_Enum; + +/* =========================================== GPIO PADREGJ PAD39STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD39STRNG */ + GPIO_PADREGJ_PAD39STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGJ_PAD39STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGJ_PAD39STRNG_Enum; + +/* =========================================== GPIO PADREGJ PAD39INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD39INPEN */ + GPIO_PADREGJ_PAD39INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGJ_PAD39INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGJ_PAD39INPEN_Enum; + +/* ============================================ GPIO PADREGJ PAD39PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD39PULL */ + GPIO_PADREGJ_PAD39PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGJ_PAD39PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGJ_PAD39PULL_Enum; + +/* =========================================== GPIO PADREGJ PAD38FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGJ_PAD38FNCSEL */ + GPIO_PADREGJ_PAD38FNCSEL_TRIG3 = 0, /*!< TRIG3 : Configure as the ADC Trigger 3 signal value. */ + GPIO_PADREGJ_PAD38FNCSEL_NCE38 = 1, /*!< NCE38 : IOM/MSPI nCE group 38 value. */ + GPIO_PADREGJ_PAD38FNCSEL_UA0CTS = 2, /*!< UA0CTS : Configure as the UART0 CTS signal value. */ + GPIO_PADREGJ_PAD38FNCSEL_GPIO38 = 3, /*!< GPIO38 : Configure as GPIO38 value. */ + GPIO_PADREGJ_PAD38FNCSEL_M3MOSI = 5, /*!< M3MOSI : Configure as the IOMSTR3 SPI MOSI output signal value. */ + GPIO_PADREGJ_PAD38FNCSEL_UART1RX = 6, /*!< UART1RX : Configure as the UART1 RX input signal value. */ +} GPIO_PADREGJ_PAD38FNCSEL_Enum; + +/* =========================================== GPIO PADREGJ PAD38STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD38STRNG */ + GPIO_PADREGJ_PAD38STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGJ_PAD38STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGJ_PAD38STRNG_Enum; + +/* =========================================== GPIO PADREGJ PAD38INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD38INPEN */ + GPIO_PADREGJ_PAD38INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGJ_PAD38INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGJ_PAD38INPEN_Enum; + +/* ============================================ GPIO PADREGJ PAD38PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD38PULL */ + GPIO_PADREGJ_PAD38PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGJ_PAD38PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGJ_PAD38PULL_Enum; + +/* =========================================== GPIO PADREGJ PAD37PWRDN [15..15] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD37PWRDN */ + GPIO_PADREGJ_PAD37PWRDN_DIS = 0, /*!< DIS : Power switch disabled value. */ + GPIO_PADREGJ_PAD37PWRDN_EN = 1, /*!< EN : Power switch enabled (switch to GND) value. */ +} GPIO_PADREGJ_PAD37PWRDN_Enum; + +/* =========================================== GPIO PADREGJ PAD37FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGJ_PAD37FNCSEL */ + GPIO_PADREGJ_PAD37FNCSEL_TRIG2 = 0, /*!< TRIG2 : Configure as the ADC Trigger 2 signal value. */ + GPIO_PADREGJ_PAD37FNCSEL_NCE37 = 1, /*!< NCE37 : IOM/MSPI nCE group 37 value. */ + GPIO_PADREGJ_PAD37FNCSEL_UA0RTS = 2, /*!< UA0RTS : Configure as the UART0 RTS output signal value. */ + GPIO_PADREGJ_PAD37FNCSEL_GPIO37 = 3, /*!< GPIO37 : Configure as GPIO37 value. */ + GPIO_PADREGJ_PAD37FNCSEL_SCCIO = 4, /*!< SCCIO : SCARD serial data input/output value. */ + GPIO_PADREGJ_PAD37FNCSEL_UART1TX = 5, /*!< UART1TX : Configure as the UART1 TX output signal value. */ + GPIO_PADREGJ_PAD37FNCSEL_PDMCLK = 6, /*!< PDMCLK : Configure as the PDM CLK output signal value. */ + GPIO_PADREGJ_PAD37FNCSEL_CT29 = 7, /*!< CT29 : CTIMER connection 29 value. */ +} GPIO_PADREGJ_PAD37FNCSEL_Enum; + +/* =========================================== GPIO PADREGJ PAD37STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD37STRNG */ + GPIO_PADREGJ_PAD37STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGJ_PAD37STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGJ_PAD37STRNG_Enum; + +/* ============================================ GPIO PADREGJ PAD37INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGJ_PAD37INPEN */ + GPIO_PADREGJ_PAD37INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGJ_PAD37INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGJ_PAD37INPEN_Enum; + +/* ============================================= GPIO PADREGJ PAD37PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGJ_PAD37PULL */ + GPIO_PADREGJ_PAD37PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGJ_PAD37PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGJ_PAD37PULL_Enum; + +/* ============================================ GPIO PADREGJ PAD36PWRUP [6..6] ============================================= */ +typedef enum { /*!< GPIO_PADREGJ_PAD36PWRUP */ + GPIO_PADREGJ_PAD36PWRUP_DIS = 0, /*!< DIS : Power switch disabled value. */ + GPIO_PADREGJ_PAD36PWRUP_EN = 1, /*!< EN : Power switch enabled (switched to VDD) value. */ +} GPIO_PADREGJ_PAD36PWRUP_Enum; + +/* ============================================ GPIO PADREGJ PAD36FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGJ_PAD36FNCSEL */ + GPIO_PADREGJ_PAD36FNCSEL_TRIG1 = 0, /*!< TRIG1 : Configure as the ADC Trigger 1 signal value. */ + GPIO_PADREGJ_PAD36FNCSEL_NCE36 = 1, /*!< NCE36 : IOM/MSPI nCE group 36 value. */ + GPIO_PADREGJ_PAD36FNCSEL_UART1RX = 2, /*!< UART1RX : Configure as the UART1 RX input signal value. */ + GPIO_PADREGJ_PAD36FNCSEL_GPIO36 = 3, /*!< GPIO36 : Configure as GPIO36 value. */ + GPIO_PADREGJ_PAD36FNCSEL_32kHzXT = 4, /*!< 32kHzXT : Configure as the 32kHz output clock from the crystal + value. */ + GPIO_PADREGJ_PAD36FNCSEL_UA1CTS = 5, /*!< UA1CTS : Configure as the UART1 CTS input signal value. */ + GPIO_PADREGJ_PAD36FNCSEL_UA0CTS = 6, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ + GPIO_PADREGJ_PAD36FNCSEL_PDMDATA = 7, /*!< PDMDATA : PDM serial data input value. */ +} GPIO_PADREGJ_PAD36FNCSEL_Enum; + +/* ============================================ GPIO PADREGJ PAD36STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGJ_PAD36STRNG */ + GPIO_PADREGJ_PAD36STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGJ_PAD36STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGJ_PAD36STRNG_Enum; + +/* ============================================ GPIO PADREGJ PAD36INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGJ_PAD36INPEN */ + GPIO_PADREGJ_PAD36INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGJ_PAD36INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGJ_PAD36INPEN_Enum; + +/* ============================================= GPIO PADREGJ PAD36PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGJ_PAD36PULL */ + GPIO_PADREGJ_PAD36PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGJ_PAD36PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGJ_PAD36PULL_Enum; + +/* ======================================================== PADREGK ======================================================== */ +/* ============================================ GPIO PADREGK PAD43RSEL [30..31] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD43RSEL */ + GPIO_PADREGK_PAD43RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGK_PAD43RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGK_PAD43RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGK_PAD43RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGK_PAD43RSEL_Enum; + +/* =========================================== GPIO PADREGK PAD43FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGK_PAD43FNCSEL */ + GPIO_PADREGK_PAD43FNCSEL_UART1RX = 0, /*!< UART1RX : Configure as the UART1 RX input signal value. */ + GPIO_PADREGK_PAD43FNCSEL_NCE43 = 1, /*!< NCE43 : IOM/MSPI nCE group 43 value. */ + GPIO_PADREGK_PAD43FNCSEL_CT18 = 2, /*!< CT18 : CTIMER connection 18 value. */ + GPIO_PADREGK_PAD43FNCSEL_GPIO43 = 3, /*!< GPIO43 : Configure as GPIO43 value. */ + GPIO_PADREGK_PAD43FNCSEL_M3SDAWIR3 = 4, /*!< M3SDAWIR3 : Configure as the IOMSTR3 I2C SDA or SPI WIR3 signal + value. */ + GPIO_PADREGK_PAD43FNCSEL_M3MISO = 5, /*!< M3MISO : Configure as the IOMSTR3 SPI MISO signal value. */ +} GPIO_PADREGK_PAD43FNCSEL_Enum; + +/* =========================================== GPIO PADREGK PAD43STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD43STRNG */ + GPIO_PADREGK_PAD43STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGK_PAD43STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGK_PAD43STRNG_Enum; + +/* =========================================== GPIO PADREGK PAD43INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD43INPEN */ + GPIO_PADREGK_PAD43INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGK_PAD43INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGK_PAD43INPEN_Enum; + +/* ============================================ GPIO PADREGK PAD43PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD43PULL */ + GPIO_PADREGK_PAD43PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGK_PAD43PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGK_PAD43PULL_Enum; + +/* ============================================ GPIO PADREGK PAD42RSEL [22..23] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD42RSEL */ + GPIO_PADREGK_PAD42RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGK_PAD42RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGK_PAD42RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGK_PAD42RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGK_PAD42RSEL_Enum; + +/* =========================================== GPIO PADREGK PAD42FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGK_PAD42FNCSEL */ + GPIO_PADREGK_PAD42FNCSEL_UART1TX = 0, /*!< UART1TX : Configure as the UART1 TX output signal value. */ + GPIO_PADREGK_PAD42FNCSEL_NCE42 = 1, /*!< NCE42 : IOM/MSPI nCE group 42 value. */ + GPIO_PADREGK_PAD42FNCSEL_CT16 = 2, /*!< CT16 : CTIMER connection 16 value. */ + GPIO_PADREGK_PAD42FNCSEL_GPIO42 = 3, /*!< GPIO42 : Configure as GPIO42 value. */ + GPIO_PADREGK_PAD42FNCSEL_M3SCL = 4, /*!< M3SCL : Configure as the IOMSTR3 I2C SCL clock I/O signal value. */ + GPIO_PADREGK_PAD42FNCSEL_M3SCK = 5, /*!< M3SCK : Configure as the IOMSTR3 SPI SCK output value. */ +} GPIO_PADREGK_PAD42FNCSEL_Enum; + +/* =========================================== GPIO PADREGK PAD42STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD42STRNG */ + GPIO_PADREGK_PAD42STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGK_PAD42STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGK_PAD42STRNG_Enum; + +/* =========================================== GPIO PADREGK PAD42INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD42INPEN */ + GPIO_PADREGK_PAD42INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGK_PAD42INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGK_PAD42INPEN_Enum; + +/* ============================================ GPIO PADREGK PAD42PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD42PULL */ + GPIO_PADREGK_PAD42PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGK_PAD42PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGK_PAD42PULL_Enum; + +/* =========================================== GPIO PADREGK PAD41PWRDN [15..15] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD41PWRDN */ + GPIO_PADREGK_PAD41PWRDN_DIS = 0, /*!< DIS : Power switch disabled value. */ + GPIO_PADREGK_PAD41PWRDN_EN = 1, /*!< EN : Power switch enabled (Switch pad to VSS) value. */ +} GPIO_PADREGK_PAD41PWRDN_Enum; + +/* =========================================== GPIO PADREGK PAD41FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGK_PAD41FNCSEL */ + GPIO_PADREGK_PAD41FNCSEL_NCE41 = 0, /*!< NCE41 : IOM/MSPI nCE group 41 value. */ + GPIO_PADREGK_PAD41FNCSEL_SWO = 2, /*!< SWO : Configure as the serial wire debug SWO signal value. */ + GPIO_PADREGK_PAD41FNCSEL_GPIO41 = 3, /*!< GPIO41 : Configure as GPIO41 value. */ + GPIO_PADREGK_PAD41FNCSEL_I2SWCLK = 4, /*!< I2SWCLK : I2S word clock input value. */ + GPIO_PADREGK_PAD41FNCSEL_UA1RTS = 5, /*!< UA1RTS : Configure as the UART1 RTS output signal value. */ + GPIO_PADREGK_PAD41FNCSEL_UART0TX = 6, /*!< UART0TX : Configure as the UART0 TX output signal value. */ + GPIO_PADREGK_PAD41FNCSEL_UA0RTS = 7, /*!< UA0RTS : Configure as the UART0 RTS output signal value. */ +} GPIO_PADREGK_PAD41FNCSEL_Enum; + +/* =========================================== GPIO PADREGK PAD41STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD41STRNG */ + GPIO_PADREGK_PAD41STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGK_PAD41STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGK_PAD41STRNG_Enum; + +/* ============================================ GPIO PADREGK PAD41INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGK_PAD41INPEN */ + GPIO_PADREGK_PAD41INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGK_PAD41INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGK_PAD41INPEN_Enum; + +/* ============================================= GPIO PADREGK PAD41PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGK_PAD41PULL */ + GPIO_PADREGK_PAD41PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGK_PAD41PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGK_PAD41PULL_Enum; + +/* ============================================= GPIO PADREGK PAD40RSEL [6..7] ============================================= */ +typedef enum { /*!< GPIO_PADREGK_PAD40RSEL */ + GPIO_PADREGK_PAD40RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGK_PAD40RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGK_PAD40RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGK_PAD40RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGK_PAD40RSEL_Enum; + +/* ============================================ GPIO PADREGK PAD40FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGK_PAD40FNCSEL */ + GPIO_PADREGK_PAD40FNCSEL_UART0RX = 0, /*!< UART0RX : Configure as the UART0 RX input signal value. */ + GPIO_PADREGK_PAD40FNCSEL_UART1RX = 1, /*!< UART1RX : Configure as the UART1 RX input signal value. */ + GPIO_PADREGK_PAD40FNCSEL_TRIG0 = 2, /*!< TRIG0 : Configure as the ADC Trigger 0 signal value. */ + GPIO_PADREGK_PAD40FNCSEL_GPIO40 = 3, /*!< GPIO40 : Configure as GPIO40 value. */ + GPIO_PADREGK_PAD40FNCSEL_M4SDAWIR3 = 4, /*!< M4SDAWIR3 : Configure as the IOMSTR4 I2C SDA or SPI WIR3 signal + value. */ + GPIO_PADREGK_PAD40FNCSEL_M4MISO = 5, /*!< M4MISO : Configure as the IOMSTR4 SPI MISO input signal value. */ +} GPIO_PADREGK_PAD40FNCSEL_Enum; + +/* ============================================ GPIO PADREGK PAD40STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGK_PAD40STRNG */ + GPIO_PADREGK_PAD40STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGK_PAD40STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGK_PAD40STRNG_Enum; + +/* ============================================ GPIO PADREGK PAD40INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGK_PAD40INPEN */ + GPIO_PADREGK_PAD40INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGK_PAD40INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGK_PAD40INPEN_Enum; + +/* ============================================= GPIO PADREGK PAD40PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGK_PAD40PULL */ + GPIO_PADREGK_PAD40PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGK_PAD40PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGK_PAD40PULL_Enum; + +/* ======================================================== PADREGL ======================================================== */ +/* =========================================== GPIO PADREGL PAD47FNCSEL [27..29] =========================================== */ +typedef enum { /*!< GPIO_PADREGL_PAD47FNCSEL */ + GPIO_PADREGL_PAD47FNCSEL_32kHzXT = 0, /*!< 32kHzXT : Configure as the 32kHz output clock from the crystal + value. */ + GPIO_PADREGL_PAD47FNCSEL_NCE47 = 1, /*!< NCE47 : IOM/MSPI nCE group 47 value. */ + GPIO_PADREGL_PAD47FNCSEL_CT26 = 2, /*!< CT26 : CTIMER connection 26 value. */ + GPIO_PADREGL_PAD47FNCSEL_GPIO47 = 3, /*!< GPIO47 : Configure as GPIO47 value. */ + GPIO_PADREGL_PAD47FNCSEL_M5MOSI = 5, /*!< M5MOSI : Configure as the IOMSTR5 SPI MOSI output signal value. */ + GPIO_PADREGL_PAD47FNCSEL_UART1RX = 6, /*!< UART1RX : Configure as the UART1 RX input signal value. */ +} GPIO_PADREGL_PAD47FNCSEL_Enum; + +/* =========================================== GPIO PADREGL PAD47STRNG [26..26] ============================================ */ +typedef enum { /*!< GPIO_PADREGL_PAD47STRNG */ + GPIO_PADREGL_PAD47STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGL_PAD47STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGL_PAD47STRNG_Enum; + +/* =========================================== GPIO PADREGL PAD47INPEN [25..25] ============================================ */ +typedef enum { /*!< GPIO_PADREGL_PAD47INPEN */ + GPIO_PADREGL_PAD47INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGL_PAD47INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGL_PAD47INPEN_Enum; + +/* ============================================ GPIO PADREGL PAD47PULL [24..24] ============================================ */ +typedef enum { /*!< GPIO_PADREGL_PAD47PULL */ + GPIO_PADREGL_PAD47PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGL_PAD47PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGL_PAD47PULL_Enum; + +/* =========================================== GPIO PADREGL PAD46FNCSEL [19..21] =========================================== */ +typedef enum { /*!< GPIO_PADREGL_PAD46FNCSEL */ + GPIO_PADREGL_PAD46FNCSEL_32khz_XT = 0, /*!< 32khz_XT : Configure as the 32kHz output clock from the crystal + value. */ + GPIO_PADREGL_PAD46FNCSEL_NCE46 = 1, /*!< NCE46 : IOM/MSPI nCE group 46 value. */ + GPIO_PADREGL_PAD46FNCSEL_CT24 = 2, /*!< CT24 : CTIMER connection 24 value. */ + GPIO_PADREGL_PAD46FNCSEL_GPIO46 = 3, /*!< GPIO46 : Configure as GPIO46 value. */ + GPIO_PADREGL_PAD46FNCSEL_SCCRST = 4, /*!< SCCRST : SCARD reset output value. */ + GPIO_PADREGL_PAD46FNCSEL_PDMCLK = 5, /*!< PDMCLK : PDM serial clock output value. */ + GPIO_PADREGL_PAD46FNCSEL_UART1TX = 6, /*!< UART1TX : Configure as the UART1 TX output signal value. */ + GPIO_PADREGL_PAD46FNCSEL_SWO = 7, /*!< SWO : Configure as the serial wire debug SWO signal value. */ +} GPIO_PADREGL_PAD46FNCSEL_Enum; + +/* =========================================== GPIO PADREGL PAD46STRNG [18..18] ============================================ */ +typedef enum { /*!< GPIO_PADREGL_PAD46STRNG */ + GPIO_PADREGL_PAD46STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGL_PAD46STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGL_PAD46STRNG_Enum; + +/* =========================================== GPIO PADREGL PAD46INPEN [17..17] ============================================ */ +typedef enum { /*!< GPIO_PADREGL_PAD46INPEN */ + GPIO_PADREGL_PAD46INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGL_PAD46INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGL_PAD46INPEN_Enum; + +/* ============================================ GPIO PADREGL PAD46PULL [16..16] ============================================ */ +typedef enum { /*!< GPIO_PADREGL_PAD46PULL */ + GPIO_PADREGL_PAD46PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGL_PAD46PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGL_PAD46PULL_Enum; + +/* =========================================== GPIO PADREGL PAD45FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGL_PAD45FNCSEL */ + GPIO_PADREGL_PAD45FNCSEL_UA1CTS = 0, /*!< UA1CTS : Configure as the UART1 CTS input signal value. */ + GPIO_PADREGL_PAD45FNCSEL_NCE45 = 1, /*!< NCE45 : IOM/MSPI nCE group 45 value. */ + GPIO_PADREGL_PAD45FNCSEL_CT22 = 2, /*!< CT22 : CTIMER connection 22 value. */ + GPIO_PADREGL_PAD45FNCSEL_GPIO45 = 3, /*!< GPIO45 : Configure as GPIO45 value. */ + GPIO_PADREGL_PAD45FNCSEL_I2SDAT = 4, /*!< I2SDAT : I2S serial data output value. */ + GPIO_PADREGL_PAD45FNCSEL_PDMDATA = 5, /*!< PDMDATA : PDM serial data input value. */ + GPIO_PADREGL_PAD45FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as the SPI channel 5 nCE signal from IOMSTR5 + value. */ + GPIO_PADREGL_PAD45FNCSEL_SWO = 7, /*!< SWO : Configure as the serial wire debug SWO signal value. */ +} GPIO_PADREGL_PAD45FNCSEL_Enum; + +/* =========================================== GPIO PADREGL PAD45STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGL_PAD45STRNG */ + GPIO_PADREGL_PAD45STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGL_PAD45STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGL_PAD45STRNG_Enum; + +/* ============================================ GPIO PADREGL PAD45INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGL_PAD45INPEN */ + GPIO_PADREGL_PAD45INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGL_PAD45INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGL_PAD45INPEN_Enum; + +/* ============================================= GPIO PADREGL PAD45PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGL_PAD45PULL */ + GPIO_PADREGL_PAD45PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGL_PAD45PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGL_PAD45PULL_Enum; + +/* ============================================ GPIO PADREGL PAD44FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGL_PAD44FNCSEL */ + GPIO_PADREGL_PAD44FNCSEL_UA1RTS = 0, /*!< UA1RTS : Configure as the UART1 RTS output signal value. */ + GPIO_PADREGL_PAD44FNCSEL_NCE44 = 1, /*!< NCE44 : IOM/MSPI nCE group 44 value. */ + GPIO_PADREGL_PAD44FNCSEL_CT20 = 2, /*!< CT20 : CTIMER connection 20 value. */ + GPIO_PADREGL_PAD44FNCSEL_GPIO44 = 3, /*!< GPIO44 : Configure as GPIO44 value. */ + GPIO_PADREGL_PAD44FNCSEL_M4MOSI = 5, /*!< M4MOSI : Configure as the IOMSTR4 SPI MOSI signal value. */ + GPIO_PADREGL_PAD44FNCSEL_M5nCE6 = 6, /*!< M5nCE6 : Configure as the SPI channel 6 nCE signal from IOMSTR5 + value. */ +} GPIO_PADREGL_PAD44FNCSEL_Enum; + +/* ============================================ GPIO PADREGL PAD44STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGL_PAD44STRNG */ + GPIO_PADREGL_PAD44STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGL_PAD44STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGL_PAD44STRNG_Enum; + +/* ============================================ GPIO PADREGL PAD44INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGL_PAD44INPEN */ + GPIO_PADREGL_PAD44INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGL_PAD44INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGL_PAD44INPEN_Enum; + +/* ============================================= GPIO PADREGL PAD44PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGL_PAD44PULL */ + GPIO_PADREGL_PAD44PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGL_PAD44PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGL_PAD44PULL_Enum; + +/* ======================================================== PADREGM ======================================================== */ +/* ============================================ GPIO PADREGM PAD49RSEL [14..15] ============================================ */ +typedef enum { /*!< GPIO_PADREGM_PAD49RSEL */ + GPIO_PADREGM_PAD49RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGM_PAD49RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGM_PAD49RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGM_PAD49RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGM_PAD49RSEL_Enum; + +/* =========================================== GPIO PADREGM PAD49FNCSEL [11..13] =========================================== */ +typedef enum { /*!< GPIO_PADREGM_PAD49FNCSEL */ + GPIO_PADREGM_PAD49FNCSEL_UART0RX = 0, /*!< UART0RX : Configure as the UART0 RX input signal value. */ + GPIO_PADREGM_PAD49FNCSEL_NCE49 = 1, /*!< NCE49 : IOM/MSPPI nCE group 49 value. */ + GPIO_PADREGM_PAD49FNCSEL_CT30 = 2, /*!< CT30 : CTIMER connection 30 value. */ + GPIO_PADREGM_PAD49FNCSEL_GPIO49 = 3, /*!< GPIO49 : Configure as GPIO49 value. */ + GPIO_PADREGM_PAD49FNCSEL_M5SDAWIR3 = 4, /*!< M5SDAWIR3 : Configure as the IOMSTR5 I2C SDA or SPI WIR3 signal + value. */ + GPIO_PADREGM_PAD49FNCSEL_M5MISO = 5, /*!< M5MISO : Configure as the IOMSTR5 SPI MISO input signal value. */ +} GPIO_PADREGM_PAD49FNCSEL_Enum; + +/* =========================================== GPIO PADREGM PAD49STRNG [10..10] ============================================ */ +typedef enum { /*!< GPIO_PADREGM_PAD49STRNG */ + GPIO_PADREGM_PAD49STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGM_PAD49STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGM_PAD49STRNG_Enum; + +/* ============================================ GPIO PADREGM PAD49INPEN [9..9] ============================================= */ +typedef enum { /*!< GPIO_PADREGM_PAD49INPEN */ + GPIO_PADREGM_PAD49INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGM_PAD49INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGM_PAD49INPEN_Enum; + +/* ============================================= GPIO PADREGM PAD49PULL [8..8] ============================================= */ +typedef enum { /*!< GPIO_PADREGM_PAD49PULL */ + GPIO_PADREGM_PAD49PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGM_PAD49PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGM_PAD49PULL_Enum; + +/* ============================================= GPIO PADREGM PAD48RSEL [6..7] ============================================= */ +typedef enum { /*!< GPIO_PADREGM_PAD48RSEL */ + GPIO_PADREGM_PAD48RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ + GPIO_PADREGM_PAD48RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ + GPIO_PADREGM_PAD48RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ + GPIO_PADREGM_PAD48RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ +} GPIO_PADREGM_PAD48RSEL_Enum; + +/* ============================================ GPIO PADREGM PAD48FNCSEL [3..5] ============================================ */ +typedef enum { /*!< GPIO_PADREGM_PAD48FNCSEL */ + GPIO_PADREGM_PAD48FNCSEL_UART0TX = 0, /*!< UART0TX : Configure as the UART0 TX output signal value. */ + GPIO_PADREGM_PAD48FNCSEL_NCE48 = 1, /*!< NCE48 : IOM/MSPI nCE group 48 value. */ + GPIO_PADREGM_PAD48FNCSEL_CT28 = 2, /*!< CT28 : CTIMER conenction 28 value. */ + GPIO_PADREGM_PAD48FNCSEL_GPIO48 = 3, /*!< GPIO48 : Configure as GPIO48 value. */ + GPIO_PADREGM_PAD48FNCSEL_M5SCL = 4, /*!< M5SCL : Configure as the IOMSTR5 I2C SCL clock I/O signal value. */ + GPIO_PADREGM_PAD48FNCSEL_M5SCK = 5, /*!< M5SCK : Configure as the IOMSTR5 SPI SCK output value. */ +} GPIO_PADREGM_PAD48FNCSEL_Enum; + +/* ============================================ GPIO PADREGM PAD48STRNG [2..2] ============================================= */ +typedef enum { /*!< GPIO_PADREGM_PAD48STRNG */ + GPIO_PADREGM_PAD48STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ + GPIO_PADREGM_PAD48STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ +} GPIO_PADREGM_PAD48STRNG_Enum; + +/* ============================================ GPIO PADREGM PAD48INPEN [1..1] ============================================= */ +typedef enum { /*!< GPIO_PADREGM_PAD48INPEN */ + GPIO_PADREGM_PAD48INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ + GPIO_PADREGM_PAD48INPEN_EN = 1, /*!< EN : Pad input enabled value. */ +} GPIO_PADREGM_PAD48INPEN_Enum; + +/* ============================================= GPIO PADREGM PAD48PULL [0..0] ============================================= */ +typedef enum { /*!< GPIO_PADREGM_PAD48PULL */ + GPIO_PADREGM_PAD48PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ + GPIO_PADREGM_PAD48PULL_EN = 1, /*!< EN : Pullup enabled value. */ +} GPIO_PADREGM_PAD48PULL_Enum; + +/* ========================================================= CFGA ========================================================== */ +/* ============================================= GPIO CFGA GPIO7INTD [31..31] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO7INTD */ + GPIO_CFGA_GPIO7INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x0 - nCE polarity active low value. */ + GPIO_CFGA_GPIO7INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x0 - nCE polarity active high value. */ +} GPIO_CFGA_GPIO7INTD_Enum; + +/* ============================================ GPIO CFGA GPIO7OUTCFG [29..30] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO7OUTCFG */ + GPIO_CFGA_GPIO7OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGA_GPIO7OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGA_GPIO7OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGA_GPIO7OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGA_GPIO7OUTCFG_Enum; + +/* ============================================= GPIO CFGA GPIO7INCFG [28..28] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO7INCFG */ + GPIO_CFGA_GPIO7INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGA_GPIO7INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGA_GPIO7INCFG_Enum; + +/* ============================================= GPIO CFGA GPIO6INTD [27..27] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO6INTD */ + GPIO_CFGA_GPIO6INTD_INTDIS = 0, /*!< INTDIS : INCFG = 1 - No interrupt on GPIO transition value. */ + GPIO_CFGA_GPIO6INTD_INTBOTH = 1, /*!< INTBOTH : INCFG = 1 - Interrupt on either low to high or high + to low GPIO transition value. */ +} GPIO_CFGA_GPIO6INTD_Enum; + +/* ============================================ GPIO CFGA GPIO6OUTCFG [25..26] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO6OUTCFG */ + GPIO_CFGA_GPIO6OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGA_GPIO6OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGA_GPIO6OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGA_GPIO6OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGA_GPIO6OUTCFG_Enum; + +/* ============================================= GPIO CFGA GPIO6INCFG [24..24] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO6INCFG */ + GPIO_CFGA_GPIO6INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGA_GPIO6INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGA_GPIO6INCFG_Enum; + +/* ============================================= GPIO CFGA GPIO5INTD [23..23] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO5INTD */ + GPIO_CFGA_GPIO5INTD_INTDIS = 0, /*!< INTDIS : INCFG = 1 - No interrupt on GPIO transition value. */ + GPIO_CFGA_GPIO5INTD_INTBOTH = 1, /*!< INTBOTH : INCFG = 1 - Interrupt on either low to high or high + to low GPIO transition value. */ +} GPIO_CFGA_GPIO5INTD_Enum; + +/* ============================================ GPIO CFGA GPIO5OUTCFG [21..22] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO5OUTCFG */ + GPIO_CFGA_GPIO5OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGA_GPIO5OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGA_GPIO5OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGA_GPIO5OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGA_GPIO5OUTCFG_Enum; + +/* ============================================= GPIO CFGA GPIO5INCFG [20..20] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO5INCFG */ + GPIO_CFGA_GPIO5INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGA_GPIO5INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGA_GPIO5INCFG_Enum; + +/* ============================================= GPIO CFGA GPIO4INTD [19..19] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO4INTD */ + GPIO_CFGA_GPIO4INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ + GPIO_CFGA_GPIO4INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ +} GPIO_CFGA_GPIO4INTD_Enum; + +/* ============================================ GPIO CFGA GPIO4OUTCFG [17..18] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO4OUTCFG */ + GPIO_CFGA_GPIO4OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGA_GPIO4OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGA_GPIO4OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGA_GPIO4OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGA_GPIO4OUTCFG_Enum; + +/* ============================================= GPIO CFGA GPIO4INCFG [16..16] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO4INCFG */ + GPIO_CFGA_GPIO4INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGA_GPIO4INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGA_GPIO4INCFG_Enum; + +/* ============================================= GPIO CFGA GPIO3INTD [15..15] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO3INTD */ + GPIO_CFGA_GPIO3INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ + GPIO_CFGA_GPIO3INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ +} GPIO_CFGA_GPIO3INTD_Enum; + +/* ============================================ GPIO CFGA GPIO3OUTCFG [13..14] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO3OUTCFG */ + GPIO_CFGA_GPIO3OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGA_GPIO3OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGA_GPIO3OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGA_GPIO3OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGA_GPIO3OUTCFG_Enum; + +/* ============================================= GPIO CFGA GPIO3INCFG [12..12] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO3INCFG */ + GPIO_CFGA_GPIO3INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGA_GPIO3INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGA_GPIO3INCFG_Enum; + +/* ============================================= GPIO CFGA GPIO2INTD [11..11] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO2INTD */ + GPIO_CFGA_GPIO2INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x7 - nCE polarity active low value. */ + GPIO_CFGA_GPIO2INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x7 - nCE polarity active high value. */ +} GPIO_CFGA_GPIO2INTD_Enum; + +/* ============================================= GPIO CFGA GPIO2OUTCFG [9..10] ============================================= */ +typedef enum { /*!< GPIO_CFGA_GPIO2OUTCFG */ + GPIO_CFGA_GPIO2OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGA_GPIO2OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGA_GPIO2OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGA_GPIO2OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGA_GPIO2OUTCFG_Enum; + +/* ============================================== GPIO CFGA GPIO2INCFG [8..8] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO2INCFG */ + GPIO_CFGA_GPIO2INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGA_GPIO2INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGA_GPIO2INCFG_Enum; + +/* ============================================== GPIO CFGA GPIO1INTD [7..7] =============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO1INTD */ + GPIO_CFGA_GPIO1INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x7 - nCE polarity active low value. */ + GPIO_CFGA_GPIO1INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x7 - nCE polarity active high value. */ +} GPIO_CFGA_GPIO1INTD_Enum; + +/* ============================================= GPIO CFGA GPIO1OUTCFG [5..6] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO1OUTCFG */ + GPIO_CFGA_GPIO1OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGA_GPIO1OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGA_GPIO1OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGA_GPIO1OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGA_GPIO1OUTCFG_Enum; + +/* ============================================== GPIO CFGA GPIO1INCFG [4..4] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO1INCFG */ + GPIO_CFGA_GPIO1INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGA_GPIO1INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGA_GPIO1INCFG_Enum; + +/* ============================================== GPIO CFGA GPIO0INTD [3..3] =============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO0INTD */ + GPIO_CFGA_GPIO0INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x7 - nCE polarity active low value. */ + GPIO_CFGA_GPIO0INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x7 - nCE polarity active high value. */ +} GPIO_CFGA_GPIO0INTD_Enum; + +/* ============================================= GPIO CFGA GPIO0OUTCFG [1..2] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO0OUTCFG */ + GPIO_CFGA_GPIO0OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGA_GPIO0OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGA_GPIO0OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGA_GPIO0OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGA_GPIO0OUTCFG_Enum; + +/* ============================================== GPIO CFGA GPIO0INCFG [0..0] ============================================== */ +typedef enum { /*!< GPIO_CFGA_GPIO0INCFG */ + GPIO_CFGA_GPIO0INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGA_GPIO0INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGA_GPIO0INCFG_Enum; + +/* ========================================================= CFGB ========================================================== */ +/* ============================================= GPIO CFGB GPIO15INTD [31..31] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO15INTD */ + GPIO_CFGB_GPIO15INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGB_GPIO15INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGB_GPIO15INTD_Enum; + +/* ============================================ GPIO CFGB GPIO15OUTCFG [29..30] ============================================ */ +typedef enum { /*!< GPIO_CFGB_GPIO15OUTCFG */ + GPIO_CFGB_GPIO15OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGB_GPIO15OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGB_GPIO15OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGB_GPIO15OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGB_GPIO15OUTCFG_Enum; + +/* ============================================ GPIO CFGB GPIO15INCFG [28..28] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO15INCFG */ + GPIO_CFGB_GPIO15INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGB_GPIO15INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGB_GPIO15INCFG_Enum; + +/* ============================================= GPIO CFGB GPIO14INTD [27..27] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO14INTD */ + GPIO_CFGB_GPIO14INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGB_GPIO14INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGB_GPIO14INTD_Enum; + +/* ============================================ GPIO CFGB GPIO14OUTCFG [25..26] ============================================ */ +typedef enum { /*!< GPIO_CFGB_GPIO14OUTCFG */ + GPIO_CFGB_GPIO14OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGB_GPIO14OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGB_GPIO14OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGB_GPIO14OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGB_GPIO14OUTCFG_Enum; + +/* ============================================ GPIO CFGB GPIO14INCFG [24..24] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO14INCFG */ + GPIO_CFGB_GPIO14INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGB_GPIO14INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGB_GPIO14INCFG_Enum; + +/* ============================================= GPIO CFGB GPIO13INTD [23..23] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO13INTD */ + GPIO_CFGB_GPIO13INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGB_GPIO13INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGB_GPIO13INTD_Enum; + +/* ============================================ GPIO CFGB GPIO13OUTCFG [21..22] ============================================ */ +typedef enum { /*!< GPIO_CFGB_GPIO13OUTCFG */ + GPIO_CFGB_GPIO13OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGB_GPIO13OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGB_GPIO13OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGB_GPIO13OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGB_GPIO13OUTCFG_Enum; + +/* ============================================ GPIO CFGB GPIO13INCFG [20..20] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO13INCFG */ + GPIO_CFGB_GPIO13INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGB_GPIO13INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGB_GPIO13INCFG_Enum; + +/* ============================================= GPIO CFGB GPIO12INTD [19..19] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO12INTD */ + GPIO_CFGB_GPIO12INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGB_GPIO12INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGB_GPIO12INTD_Enum; + +/* ============================================ GPIO CFGB GPIO12OUTCFG [17..18] ============================================ */ +typedef enum { /*!< GPIO_CFGB_GPIO12OUTCFG */ + GPIO_CFGB_GPIO12OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGB_GPIO12OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGB_GPIO12OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGB_GPIO12OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGB_GPIO12OUTCFG_Enum; + +/* ============================================ GPIO CFGB GPIO12INCFG [16..16] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO12INCFG */ + GPIO_CFGB_GPIO12INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGB_GPIO12INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGB_GPIO12INCFG_Enum; + +/* ============================================= GPIO CFGB GPIO11INTD [15..15] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO11INTD */ + GPIO_CFGB_GPIO11INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGB_GPIO11INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGB_GPIO11INTD_Enum; + +/* ============================================ GPIO CFGB GPIO11OUTCFG [13..14] ============================================ */ +typedef enum { /*!< GPIO_CFGB_GPIO11OUTCFG */ + GPIO_CFGB_GPIO11OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGB_GPIO11OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGB_GPIO11OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGB_GPIO11OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGB_GPIO11OUTCFG_Enum; + +/* ============================================ GPIO CFGB GPIO11INCFG [12..12] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO11INCFG */ + GPIO_CFGB_GPIO11INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGB_GPIO11INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGB_GPIO11INCFG_Enum; + +/* ============================================= GPIO CFGB GPIO10INTD [11..11] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO10INTD */ + GPIO_CFGB_GPIO10INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ + GPIO_CFGB_GPIO10INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ +} GPIO_CFGB_GPIO10INTD_Enum; + +/* ============================================ GPIO CFGB GPIO10OUTCFG [9..10] ============================================= */ +typedef enum { /*!< GPIO_CFGB_GPIO10OUTCFG */ + GPIO_CFGB_GPIO10OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGB_GPIO10OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGB_GPIO10OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGB_GPIO10OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGB_GPIO10OUTCFG_Enum; + +/* ============================================= GPIO CFGB GPIO10INCFG [8..8] ============================================== */ +typedef enum { /*!< GPIO_CFGB_GPIO10INCFG */ + GPIO_CFGB_GPIO10INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGB_GPIO10INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGB_GPIO10INCFG_Enum; + +/* ============================================== GPIO CFGB GPIO9INTD [7..7] =============================================== */ +typedef enum { /*!< GPIO_CFGB_GPIO9INTD */ + GPIO_CFGB_GPIO9INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ + GPIO_CFGB_GPIO9INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ +} GPIO_CFGB_GPIO9INTD_Enum; + +/* ============================================= GPIO CFGB GPIO9OUTCFG [5..6] ============================================== */ +typedef enum { /*!< GPIO_CFGB_GPIO9OUTCFG */ + GPIO_CFGB_GPIO9OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGB_GPIO9OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGB_GPIO9OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGB_GPIO9OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGB_GPIO9OUTCFG_Enum; + +/* ============================================== GPIO CFGB GPIO9INCFG [4..4] ============================================== */ +typedef enum { /*!< GPIO_CFGB_GPIO9INCFG */ + GPIO_CFGB_GPIO9INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGB_GPIO9INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGB_GPIO9INCFG_Enum; + +/* ============================================== GPIO CFGB GPIO8INTD [3..3] =============================================== */ +typedef enum { /*!< GPIO_CFGB_GPIO8INTD */ + GPIO_CFGB_GPIO8INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ + GPIO_CFGB_GPIO8INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ +} GPIO_CFGB_GPIO8INTD_Enum; + +/* ============================================= GPIO CFGB GPIO8OUTCFG [1..2] ============================================== */ +typedef enum { /*!< GPIO_CFGB_GPIO8OUTCFG */ + GPIO_CFGB_GPIO8OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGB_GPIO8OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGB_GPIO8OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGB_GPIO8OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGB_GPIO8OUTCFG_Enum; + +/* ============================================== GPIO CFGB GPIO8INCFG [0..0] ============================================== */ +typedef enum { /*!< GPIO_CFGB_GPIO8INCFG */ + GPIO_CFGB_GPIO8INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGB_GPIO8INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGB_GPIO8INCFG_Enum; + +/* ========================================================= CFGC ========================================================== */ +/* ============================================= GPIO CFGC GPIO23INTD [31..31] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO23INTD */ + GPIO_CFGC_GPIO23INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGC_GPIO23INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGC_GPIO23INTD_Enum; + +/* ============================================ GPIO CFGC GPIO23OUTCFG [29..30] ============================================ */ +typedef enum { /*!< GPIO_CFGC_GPIO23OUTCFG */ + GPIO_CFGC_GPIO23OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGC_GPIO23OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGC_GPIO23OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGC_GPIO23OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGC_GPIO23OUTCFG_Enum; + +/* ============================================ GPIO CFGC GPIO23INCFG [28..28] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO23INCFG */ + GPIO_CFGC_GPIO23INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGC_GPIO23INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGC_GPIO23INCFG_Enum; + +/* ============================================= GPIO CFGC GPIO22INTD [27..27] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO22INTD */ + GPIO_CFGC_GPIO22INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGC_GPIO22INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGC_GPIO22INTD_Enum; + +/* ============================================ GPIO CFGC GPIO22OUTCFG [25..26] ============================================ */ +typedef enum { /*!< GPIO_CFGC_GPIO22OUTCFG */ + GPIO_CFGC_GPIO22OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGC_GPIO22OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGC_GPIO22OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGC_GPIO22OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGC_GPIO22OUTCFG_Enum; + +/* ============================================ GPIO CFGC GPIO22INCFG [24..24] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO22INCFG */ + GPIO_CFGC_GPIO22INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGC_GPIO22INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGC_GPIO22INCFG_Enum; + +/* ============================================= GPIO CFGC GPIO21INTD [23..23] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO21INTD */ + GPIO_CFGC_GPIO21INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGC_GPIO21INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGC_GPIO21INTD_Enum; + +/* ============================================ GPIO CFGC GPIO21OUTCFG [21..22] ============================================ */ +typedef enum { /*!< GPIO_CFGC_GPIO21OUTCFG */ + GPIO_CFGC_GPIO21OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGC_GPIO21OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGC_GPIO21OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGC_GPIO21OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGC_GPIO21OUTCFG_Enum; + +/* ============================================ GPIO CFGC GPIO21INCFG [20..20] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO21INCFG */ + GPIO_CFGC_GPIO21INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGC_GPIO21INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGC_GPIO21INCFG_Enum; + +/* ============================================= GPIO CFGC GPIO20INTD [19..19] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO20INTD */ + GPIO_CFGC_GPIO20INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGC_GPIO20INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGC_GPIO20INTD_Enum; + +/* ============================================ GPIO CFGC GPIO20OUTCFG [17..18] ============================================ */ +typedef enum { /*!< GPIO_CFGC_GPIO20OUTCFG */ + GPIO_CFGC_GPIO20OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGC_GPIO20OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGC_GPIO20OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGC_GPIO20OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGC_GPIO20OUTCFG_Enum; + +/* ============================================ GPIO CFGC GPIO20INCFG [16..16] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO20INCFG */ + GPIO_CFGC_GPIO20INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGC_GPIO20INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGC_GPIO20INCFG_Enum; + +/* ============================================= GPIO CFGC GPIO19INTD [15..15] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO19INTD */ + GPIO_CFGC_GPIO19INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGC_GPIO19INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGC_GPIO19INTD_Enum; + +/* ============================================ GPIO CFGC GPIO19OUTCFG [13..14] ============================================ */ +typedef enum { /*!< GPIO_CFGC_GPIO19OUTCFG */ + GPIO_CFGC_GPIO19OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGC_GPIO19OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGC_GPIO19OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGC_GPIO19OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGC_GPIO19OUTCFG_Enum; + +/* ============================================ GPIO CFGC GPIO19INCFG [12..12] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO19INCFG */ + GPIO_CFGC_GPIO19INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGC_GPIO19INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGC_GPIO19INCFG_Enum; + +/* ============================================= GPIO CFGC GPIO18INTD [11..11] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO18INTD */ + GPIO_CFGC_GPIO18INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGC_GPIO18INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGC_GPIO18INTD_Enum; + +/* ============================================ GPIO CFGC GPIO18OUTCFG [9..10] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO18OUTCFG */ + GPIO_CFGC_GPIO18OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGC_GPIO18OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGC_GPIO18OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGC_GPIO18OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGC_GPIO18OUTCFG_Enum; + +/* ============================================= GPIO CFGC GPIO18INCFG [8..8] ============================================== */ +typedef enum { /*!< GPIO_CFGC_GPIO18INCFG */ + GPIO_CFGC_GPIO18INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGC_GPIO18INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGC_GPIO18INCFG_Enum; + +/* ============================================== GPIO CFGC GPIO17INTD [7..7] ============================================== */ +typedef enum { /*!< GPIO_CFGC_GPIO17INTD */ + GPIO_CFGC_GPIO17INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGC_GPIO17INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGC_GPIO17INTD_Enum; + +/* ============================================= GPIO CFGC GPIO17OUTCFG [5..6] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO17OUTCFG */ + GPIO_CFGC_GPIO17OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGC_GPIO17OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGC_GPIO17OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGC_GPIO17OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGC_GPIO17OUTCFG_Enum; + +/* ============================================= GPIO CFGC GPIO17INCFG [4..4] ============================================== */ +typedef enum { /*!< GPIO_CFGC_GPIO17INCFG */ + GPIO_CFGC_GPIO17INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGC_GPIO17INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGC_GPIO17INCFG_Enum; + +/* ============================================== GPIO CFGC GPIO16INTD [3..3] ============================================== */ +typedef enum { /*!< GPIO_CFGC_GPIO16INTD */ + GPIO_CFGC_GPIO16INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGC_GPIO16INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGC_GPIO16INTD_Enum; + +/* ============================================= GPIO CFGC GPIO16OUTCFG [1..2] ============================================= */ +typedef enum { /*!< GPIO_CFGC_GPIO16OUTCFG */ + GPIO_CFGC_GPIO16OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGC_GPIO16OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGC_GPIO16OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGC_GPIO16OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGC_GPIO16OUTCFG_Enum; + +/* ============================================= GPIO CFGC GPIO16INCFG [0..0] ============================================== */ +typedef enum { /*!< GPIO_CFGC_GPIO16INCFG */ + GPIO_CFGC_GPIO16INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGC_GPIO16INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGC_GPIO16INCFG_Enum; + +/* ========================================================= CFGD ========================================================== */ +/* ============================================= GPIO CFGD GPIO31INTD [31..31] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO31INTD */ + GPIO_CFGD_GPIO31INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGD_GPIO31INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGD_GPIO31INTD_Enum; + +/* ============================================ GPIO CFGD GPIO31OUTCFG [29..30] ============================================ */ +typedef enum { /*!< GPIO_CFGD_GPIO31OUTCFG */ + GPIO_CFGD_GPIO31OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGD_GPIO31OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGD_GPIO31OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGD_GPIO31OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGD_GPIO31OUTCFG_Enum; + +/* ============================================ GPIO CFGD GPIO31INCFG [28..28] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO31INCFG */ + GPIO_CFGD_GPIO31INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGD_GPIO31INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGD_GPIO31INCFG_Enum; + +/* ============================================= GPIO CFGD GPIO30INTD [27..27] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO30INTD */ + GPIO_CFGD_GPIO30INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGD_GPIO30INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGD_GPIO30INTD_Enum; + +/* ============================================ GPIO CFGD GPIO30OUTCFG [25..26] ============================================ */ +typedef enum { /*!< GPIO_CFGD_GPIO30OUTCFG */ + GPIO_CFGD_GPIO30OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGD_GPIO30OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGD_GPIO30OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGD_GPIO30OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGD_GPIO30OUTCFG_Enum; + +/* ============================================ GPIO CFGD GPIO30INCFG [24..24] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO30INCFG */ + GPIO_CFGD_GPIO30INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGD_GPIO30INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGD_GPIO30INCFG_Enum; + +/* ============================================= GPIO CFGD GPIO29INTD [23..23] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO29INTD */ + GPIO_CFGD_GPIO29INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGD_GPIO29INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGD_GPIO29INTD_Enum; + +/* ============================================ GPIO CFGD GPIO29OUTCFG [21..22] ============================================ */ +typedef enum { /*!< GPIO_CFGD_GPIO29OUTCFG */ + GPIO_CFGD_GPIO29OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGD_GPIO29OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGD_GPIO29OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGD_GPIO29OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGD_GPIO29OUTCFG_Enum; + +/* ============================================ GPIO CFGD GPIO29INCFG [20..20] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO29INCFG */ + GPIO_CFGD_GPIO29INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGD_GPIO29INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGD_GPIO29INCFG_Enum; + +/* ============================================= GPIO CFGD GPIO28INTD [19..19] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO28INTD */ + GPIO_CFGD_GPIO28INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGD_GPIO28INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGD_GPIO28INTD_Enum; + +/* ============================================ GPIO CFGD GPIO28OUTCFG [17..18] ============================================ */ +typedef enum { /*!< GPIO_CFGD_GPIO28OUTCFG */ + GPIO_CFGD_GPIO28OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGD_GPIO28OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGD_GPIO28OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGD_GPIO28OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGD_GPIO28OUTCFG_Enum; + +/* ============================================ GPIO CFGD GPIO28INCFG [16..16] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO28INCFG */ + GPIO_CFGD_GPIO28INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGD_GPIO28INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGD_GPIO28INCFG_Enum; + +/* ============================================= GPIO CFGD GPIO27INTD [15..15] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO27INTD */ + GPIO_CFGD_GPIO27INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGD_GPIO27INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGD_GPIO27INTD_Enum; + +/* ============================================ GPIO CFGD GPIO27OUTCFG [13..14] ============================================ */ +typedef enum { /*!< GPIO_CFGD_GPIO27OUTCFG */ + GPIO_CFGD_GPIO27OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGD_GPIO27OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGD_GPIO27OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGD_GPIO27OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGD_GPIO27OUTCFG_Enum; + +/* ============================================ GPIO CFGD GPIO27INCFG [12..12] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO27INCFG */ + GPIO_CFGD_GPIO27INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGD_GPIO27INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGD_GPIO27INCFG_Enum; + +/* ============================================= GPIO CFGD GPIO26INTD [11..11] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO26INTD */ + GPIO_CFGD_GPIO26INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGD_GPIO26INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGD_GPIO26INTD_Enum; + +/* ============================================ GPIO CFGD GPIO26OUTCFG [9..10] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO26OUTCFG */ + GPIO_CFGD_GPIO26OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGD_GPIO26OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGD_GPIO26OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGD_GPIO26OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGD_GPIO26OUTCFG_Enum; + +/* ============================================= GPIO CFGD GPIO26INCFG [8..8] ============================================== */ +typedef enum { /*!< GPIO_CFGD_GPIO26INCFG */ + GPIO_CFGD_GPIO26INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGD_GPIO26INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGD_GPIO26INCFG_Enum; + +/* ============================================== GPIO CFGD GPIO25INTD [7..7] ============================================== */ +typedef enum { /*!< GPIO_CFGD_GPIO25INTD */ + GPIO_CFGD_GPIO25INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGD_GPIO25INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGD_GPIO25INTD_Enum; + +/* ============================================= GPIO CFGD GPIO25OUTCFG [5..6] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO25OUTCFG */ + GPIO_CFGD_GPIO25OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGD_GPIO25OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGD_GPIO25OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGD_GPIO25OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGD_GPIO25OUTCFG_Enum; + +/* ============================================= GPIO CFGD GPIO25INCFG [4..4] ============================================== */ +typedef enum { /*!< GPIO_CFGD_GPIO25INCFG */ + GPIO_CFGD_GPIO25INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGD_GPIO25INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGD_GPIO25INCFG_Enum; + +/* ============================================== GPIO CFGD GPIO24INTD [3..3] ============================================== */ +typedef enum { /*!< GPIO_CFGD_GPIO24INTD */ + GPIO_CFGD_GPIO24INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGD_GPIO24INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGD_GPIO24INTD_Enum; + +/* ============================================= GPIO CFGD GPIO24OUTCFG [1..2] ============================================= */ +typedef enum { /*!< GPIO_CFGD_GPIO24OUTCFG */ + GPIO_CFGD_GPIO24OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGD_GPIO24OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGD_GPIO24OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGD_GPIO24OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGD_GPIO24OUTCFG_Enum; + +/* ============================================= GPIO CFGD GPIO24INCFG [0..0] ============================================== */ +typedef enum { /*!< GPIO_CFGD_GPIO24INCFG */ + GPIO_CFGD_GPIO24INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGD_GPIO24INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGD_GPIO24INCFG_Enum; + +/* ========================================================= CFGE ========================================================== */ +/* ============================================= GPIO CFGE GPIO39INTD [31..31] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO39INTD */ + GPIO_CFGE_GPIO39INTD_INTDIS = 0, /*!< INTDIS : INCFG = 1 - No interrupt on GPIO transition value. */ + GPIO_CFGE_GPIO39INTD_INTBOTH = 1, /*!< INTBOTH : INCFG = 1 - Interrupt on either low to high or high + to low GPIO transition value. */ +} GPIO_CFGE_GPIO39INTD_Enum; + +/* ============================================ GPIO CFGE GPIO39OUTCFG [29..30] ============================================ */ +typedef enum { /*!< GPIO_CFGE_GPIO39OUTCFG */ + GPIO_CFGE_GPIO39OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGE_GPIO39OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGE_GPIO39OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGE_GPIO39OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGE_GPIO39OUTCFG_Enum; + +/* ============================================ GPIO CFGE GPIO39INCFG [28..28] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO39INCFG */ + GPIO_CFGE_GPIO39INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGE_GPIO39INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGE_GPIO39INCFG_Enum; + +/* ============================================= GPIO CFGE GPIO38INTD [27..27] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO38INTD */ + GPIO_CFGE_GPIO38INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGE_GPIO38INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGE_GPIO38INTD_Enum; + +/* ============================================ GPIO CFGE GPIO38OUTCFG [25..26] ============================================ */ +typedef enum { /*!< GPIO_CFGE_GPIO38OUTCFG */ + GPIO_CFGE_GPIO38OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGE_GPIO38OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGE_GPIO38OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGE_GPIO38OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGE_GPIO38OUTCFG_Enum; + +/* ============================================ GPIO CFGE GPIO38INCFG [24..24] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO38INCFG */ + GPIO_CFGE_GPIO38INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGE_GPIO38INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGE_GPIO38INCFG_Enum; + +/* ============================================= GPIO CFGE GPIO37INTD [23..23] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO37INTD */ + GPIO_CFGE_GPIO37INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGE_GPIO37INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGE_GPIO37INTD_Enum; + +/* ============================================ GPIO CFGE GPIO37OUTCFG [21..22] ============================================ */ +typedef enum { /*!< GPIO_CFGE_GPIO37OUTCFG */ + GPIO_CFGE_GPIO37OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGE_GPIO37OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGE_GPIO37OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGE_GPIO37OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGE_GPIO37OUTCFG_Enum; + +/* ============================================ GPIO CFGE GPIO37INCFG [20..20] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO37INCFG */ + GPIO_CFGE_GPIO37INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGE_GPIO37INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGE_GPIO37INCFG_Enum; + +/* ============================================= GPIO CFGE GPIO36INTD [19..19] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO36INTD */ + GPIO_CFGE_GPIO36INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGE_GPIO36INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGE_GPIO36INTD_Enum; + +/* ============================================ GPIO CFGE GPIO36OUTCFG [17..18] ============================================ */ +typedef enum { /*!< GPIO_CFGE_GPIO36OUTCFG */ + GPIO_CFGE_GPIO36OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGE_GPIO36OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGE_GPIO36OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGE_GPIO36OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGE_GPIO36OUTCFG_Enum; + +/* ============================================ GPIO CFGE GPIO36INCFG [16..16] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO36INCFG */ + GPIO_CFGE_GPIO36INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGE_GPIO36INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGE_GPIO36INCFG_Enum; + +/* ============================================= GPIO CFGE GPIO35INTD [15..15] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO35INTD */ + GPIO_CFGE_GPIO35INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGE_GPIO35INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGE_GPIO35INTD_Enum; + +/* ============================================ GPIO CFGE GPIO35OUTCFG [13..14] ============================================ */ +typedef enum { /*!< GPIO_CFGE_GPIO35OUTCFG */ + GPIO_CFGE_GPIO35OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGE_GPIO35OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGE_GPIO35OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGE_GPIO35OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGE_GPIO35OUTCFG_Enum; + +/* ============================================ GPIO CFGE GPIO35INCFG [12..12] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO35INCFG */ + GPIO_CFGE_GPIO35INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGE_GPIO35INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGE_GPIO35INCFG_Enum; + +/* ============================================= GPIO CFGE GPIO34INTD [11..11] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO34INTD */ + GPIO_CFGE_GPIO34INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGE_GPIO34INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGE_GPIO34INTD_Enum; + +/* ============================================ GPIO CFGE GPIO34OUTCFG [9..10] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO34OUTCFG */ + GPIO_CFGE_GPIO34OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGE_GPIO34OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGE_GPIO34OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGE_GPIO34OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGE_GPIO34OUTCFG_Enum; + +/* ============================================= GPIO CFGE GPIO34INCFG [8..8] ============================================== */ +typedef enum { /*!< GPIO_CFGE_GPIO34INCFG */ + GPIO_CFGE_GPIO34INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGE_GPIO34INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGE_GPIO34INCFG_Enum; + +/* ============================================== GPIO CFGE GPIO33INTD [7..7] ============================================== */ +typedef enum { /*!< GPIO_CFGE_GPIO33INTD */ + GPIO_CFGE_GPIO33INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGE_GPIO33INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGE_GPIO33INTD_Enum; + +/* ============================================= GPIO CFGE GPIO33OUTCFG [5..6] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO33OUTCFG */ + GPIO_CFGE_GPIO33OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGE_GPIO33OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGE_GPIO33OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGE_GPIO33OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGE_GPIO33OUTCFG_Enum; + +/* ============================================= GPIO CFGE GPIO33INCFG [4..4] ============================================== */ +typedef enum { /*!< GPIO_CFGE_GPIO33INCFG */ + GPIO_CFGE_GPIO33INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGE_GPIO33INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGE_GPIO33INCFG_Enum; + +/* ============================================== GPIO CFGE GPIO32INTD [3..3] ============================================== */ +typedef enum { /*!< GPIO_CFGE_GPIO32INTD */ + GPIO_CFGE_GPIO32INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGE_GPIO32INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGE_GPIO32INTD_Enum; + +/* ============================================= GPIO CFGE GPIO32OUTCFG [1..2] ============================================= */ +typedef enum { /*!< GPIO_CFGE_GPIO32OUTCFG */ + GPIO_CFGE_GPIO32OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGE_GPIO32OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGE_GPIO32OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGE_GPIO32OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGE_GPIO32OUTCFG_Enum; + +/* ============================================= GPIO CFGE GPIO32INCFG [0..0] ============================================== */ +typedef enum { /*!< GPIO_CFGE_GPIO32INCFG */ + GPIO_CFGE_GPIO32INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGE_GPIO32INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGE_GPIO32INCFG_Enum; + +/* ========================================================= CFGF ========================================================== */ +/* ============================================= GPIO CFGF GPIO47INTD [31..31] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO47INTD */ + GPIO_CFGF_GPIO47INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGF_GPIO47INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGF_GPIO47INTD_Enum; + +/* ============================================ GPIO CFGF GPIO47OUTCFG [29..30] ============================================ */ +typedef enum { /*!< GPIO_CFGF_GPIO47OUTCFG */ + GPIO_CFGF_GPIO47OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGF_GPIO47OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGF_GPIO47OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGF_GPIO47OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGF_GPIO47OUTCFG_Enum; + +/* ============================================ GPIO CFGF GPIO47INCFG [28..28] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO47INCFG */ + GPIO_CFGF_GPIO47INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGF_GPIO47INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGF_GPIO47INCFG_Enum; + +/* ============================================= GPIO CFGF GPIO46INTD [27..27] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO46INTD */ + GPIO_CFGF_GPIO46INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGF_GPIO46INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGF_GPIO46INTD_Enum; + +/* ============================================ GPIO CFGF GPIO46OUTCFG [25..26] ============================================ */ +typedef enum { /*!< GPIO_CFGF_GPIO46OUTCFG */ + GPIO_CFGF_GPIO46OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGF_GPIO46OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGF_GPIO46OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGF_GPIO46OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGF_GPIO46OUTCFG_Enum; + +/* ============================================ GPIO CFGF GPIO46INCFG [24..24] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO46INCFG */ + GPIO_CFGF_GPIO46INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGF_GPIO46INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGF_GPIO46INCFG_Enum; + +/* ============================================= GPIO CFGF GPIO45INTD [23..23] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO45INTD */ + GPIO_CFGF_GPIO45INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGF_GPIO45INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGF_GPIO45INTD_Enum; + +/* ============================================ GPIO CFGF GPIO45OUTCFG [21..22] ============================================ */ +typedef enum { /*!< GPIO_CFGF_GPIO45OUTCFG */ + GPIO_CFGF_GPIO45OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGF_GPIO45OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGF_GPIO45OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGF_GPIO45OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGF_GPIO45OUTCFG_Enum; + +/* ============================================ GPIO CFGF GPIO45INCFG [20..20] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO45INCFG */ + GPIO_CFGF_GPIO45INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGF_GPIO45INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGF_GPIO45INCFG_Enum; + +/* ============================================= GPIO CFGF GPIO44INTD [19..19] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO44INTD */ + GPIO_CFGF_GPIO44INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGF_GPIO44INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGF_GPIO44INTD_Enum; + +/* ============================================ GPIO CFGF GPIO44OUTCFG [17..18] ============================================ */ +typedef enum { /*!< GPIO_CFGF_GPIO44OUTCFG */ + GPIO_CFGF_GPIO44OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGF_GPIO44OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGF_GPIO44OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGF_GPIO44OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGF_GPIO44OUTCFG_Enum; + +/* ============================================ GPIO CFGF GPIO44INCFG [16..16] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO44INCFG */ + GPIO_CFGF_GPIO44INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGF_GPIO44INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGF_GPIO44INCFG_Enum; + +/* ============================================= GPIO CFGF GPIO43INTD [15..15] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO43INTD */ + GPIO_CFGF_GPIO43INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGF_GPIO43INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGF_GPIO43INTD_Enum; + +/* ============================================ GPIO CFGF GPIO43OUTCFG [13..14] ============================================ */ +typedef enum { /*!< GPIO_CFGF_GPIO43OUTCFG */ + GPIO_CFGF_GPIO43OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGF_GPIO43OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGF_GPIO43OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGF_GPIO43OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGF_GPIO43OUTCFG_Enum; + +/* ============================================ GPIO CFGF GPIO43INCFG [12..12] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO43INCFG */ + GPIO_CFGF_GPIO43INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGF_GPIO43INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGF_GPIO43INCFG_Enum; + +/* ============================================= GPIO CFGF GPIO42INTD [11..11] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO42INTD */ + GPIO_CFGF_GPIO42INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGF_GPIO42INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGF_GPIO42INTD_Enum; + +/* ============================================ GPIO CFGF GPIO42OUTCFG [9..10] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO42OUTCFG */ + GPIO_CFGF_GPIO42OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGF_GPIO42OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGF_GPIO42OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGF_GPIO42OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGF_GPIO42OUTCFG_Enum; + +/* ============================================= GPIO CFGF GPIO42INCFG [8..8] ============================================== */ +typedef enum { /*!< GPIO_CFGF_GPIO42INCFG */ + GPIO_CFGF_GPIO42INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGF_GPIO42INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGF_GPIO42INCFG_Enum; + +/* ============================================== GPIO CFGF GPIO41INTD [7..7] ============================================== */ +typedef enum { /*!< GPIO_CFGF_GPIO41INTD */ + GPIO_CFGF_GPIO41INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x0 - nCE polarity active low value. */ + GPIO_CFGF_GPIO41INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x0 - nCE polarity active high value. */ +} GPIO_CFGF_GPIO41INTD_Enum; + +/* ============================================= GPIO CFGF GPIO41OUTCFG [5..6] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO41OUTCFG */ + GPIO_CFGF_GPIO41OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGF_GPIO41OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGF_GPIO41OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGF_GPIO41OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGF_GPIO41OUTCFG_Enum; + +/* ============================================= GPIO CFGF GPIO41INCFG [4..4] ============================================== */ +typedef enum { /*!< GPIO_CFGF_GPIO41INCFG */ + GPIO_CFGF_GPIO41INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGF_GPIO41INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGF_GPIO41INCFG_Enum; + +/* ============================================== GPIO CFGF GPIO40INTD [3..3] ============================================== */ +typedef enum { /*!< GPIO_CFGF_GPIO40INTD */ + GPIO_CFGF_GPIO40INTD_INTDIS = 0, /*!< INTDIS : INCFG = 1 - No interrupt on GPIO transition value. */ + GPIO_CFGF_GPIO40INTD_INTBOTH = 1, /*!< INTBOTH : INCFG = 1 - Interrupt on either low to high or high + to low GPIO transition value. */ +} GPIO_CFGF_GPIO40INTD_Enum; + +/* ============================================= GPIO CFGF GPIO40OUTCFG [1..2] ============================================= */ +typedef enum { /*!< GPIO_CFGF_GPIO40OUTCFG */ + GPIO_CFGF_GPIO40OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGF_GPIO40OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGF_GPIO40OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGF_GPIO40OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGF_GPIO40OUTCFG_Enum; + +/* ============================================= GPIO CFGF GPIO40INCFG [0..0] ============================================== */ +typedef enum { /*!< GPIO_CFGF_GPIO40INCFG */ + GPIO_CFGF_GPIO40INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGF_GPIO40INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGF_GPIO40INCFG_Enum; + +/* ========================================================= CFGG ========================================================== */ +/* ============================================== GPIO CFGG GPIO49INTD [7..7] ============================================== */ +typedef enum { /*!< GPIO_CFGG_GPIO49INTD */ + GPIO_CFGG_GPIO49INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGG_GPIO49INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGG_GPIO49INTD_Enum; + +/* ============================================= GPIO CFGG GPIO49OUTCFG [5..6] ============================================= */ +typedef enum { /*!< GPIO_CFGG_GPIO49OUTCFG */ + GPIO_CFGG_GPIO49OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGG_GPIO49OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGG_GPIO49OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGG_GPIO49OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGG_GPIO49OUTCFG_Enum; + +/* ============================================= GPIO CFGG GPIO49INCFG [4..4] ============================================== */ +typedef enum { /*!< GPIO_CFGG_GPIO49INCFG */ + GPIO_CFGG_GPIO49INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGG_GPIO49INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGG_GPIO49INCFG_Enum; + +/* ============================================== GPIO CFGG GPIO48INTD [3..3] ============================================== */ +typedef enum { /*!< GPIO_CFGG_GPIO48INTD */ + GPIO_CFGG_GPIO48INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ + GPIO_CFGG_GPIO48INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ +} GPIO_CFGG_GPIO48INTD_Enum; + +/* ============================================= GPIO CFGG GPIO48OUTCFG [1..2] ============================================= */ +typedef enum { /*!< GPIO_CFGG_GPIO48OUTCFG */ + GPIO_CFGG_GPIO48OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ + GPIO_CFGG_GPIO48OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ + GPIO_CFGG_GPIO48OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ + GPIO_CFGG_GPIO48OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ +} GPIO_CFGG_GPIO48OUTCFG_Enum; + +/* ============================================= GPIO CFGG GPIO48INCFG [0..0] ============================================== */ +typedef enum { /*!< GPIO_CFGG_GPIO48INCFG */ + GPIO_CFGG_GPIO48INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ + GPIO_CFGG_GPIO48INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ +} GPIO_CFGG_GPIO48INCFG_Enum; + +/* ======================================================== PADKEY ========================================================= */ +/* ============================================== GPIO PADKEY PADKEY [0..31] =============================================== */ +typedef enum { /*!< GPIO_PADKEY_PADKEY */ + GPIO_PADKEY_PADKEY_Key = 115, /*!< Key : Key value. */ +} GPIO_PADKEY_PADKEY_Enum; + +/* ========================================================== RDA ========================================================== */ +/* ========================================================== RDB ========================================================== */ +/* ========================================================== WTA ========================================================== */ +/* ========================================================== WTB ========================================================== */ +/* ========================================================= WTSA ========================================================== */ +/* ========================================================= WTSB ========================================================== */ +/* ========================================================= WTCA ========================================================== */ +/* ========================================================= WTCB ========================================================== */ +/* ========================================================== ENA ========================================================== */ +/* ========================================================== ENB ========================================================== */ +/* ========================================================= ENSA ========================================================== */ +/* ========================================================= ENSB ========================================================== */ +/* ========================================================= ENCA ========================================================== */ +/* ========================================================= ENCB ========================================================== */ +/* ======================================================== STMRCAP ======================================================== */ +/* ============================================= GPIO STMRCAP STPOL3 [30..30] ============================================== */ +typedef enum { /*!< GPIO_STMRCAP_STPOL3 */ + GPIO_STMRCAP_STPOL3_CAPLH = 0, /*!< CAPLH : Capture on low to high GPIO transition value. */ + GPIO_STMRCAP_STPOL3_CAPHL = 1, /*!< CAPHL : Capture on high to low GPIO transition value. */ +} GPIO_STMRCAP_STPOL3_Enum; + +/* ============================================= GPIO STMRCAP STPOL2 [22..22] ============================================== */ +typedef enum { /*!< GPIO_STMRCAP_STPOL2 */ + GPIO_STMRCAP_STPOL2_CAPLH = 0, /*!< CAPLH : Capture on low to high GPIO transition value. */ + GPIO_STMRCAP_STPOL2_CAPHL = 1, /*!< CAPHL : Capture on high to low GPIO transition value. */ +} GPIO_STMRCAP_STPOL2_Enum; + +/* ============================================= GPIO STMRCAP STPOL1 [14..14] ============================================== */ +typedef enum { /*!< GPIO_STMRCAP_STPOL1 */ + GPIO_STMRCAP_STPOL1_CAPLH = 0, /*!< CAPLH : Capture on low to high GPIO transition value. */ + GPIO_STMRCAP_STPOL1_CAPHL = 1, /*!< CAPHL : Capture on high to low GPIO transition value. */ +} GPIO_STMRCAP_STPOL1_Enum; + +/* ============================================== GPIO STMRCAP STPOL0 [6..6] =============================================== */ +typedef enum { /*!< GPIO_STMRCAP_STPOL0 */ + GPIO_STMRCAP_STPOL0_CAPLH = 0, /*!< CAPLH : Capture on low to high GPIO transition value. */ + GPIO_STMRCAP_STPOL0_CAPHL = 1, /*!< CAPHL : Capture on high to low GPIO transition value. */ +} GPIO_STMRCAP_STPOL0_Enum; + +/* ======================================================== IOM0IRQ ======================================================== */ +/* ======================================================== IOM1IRQ ======================================================== */ +/* ======================================================== IOM2IRQ ======================================================== */ +/* ======================================================== IOM3IRQ ======================================================== */ +/* ======================================================== IOM4IRQ ======================================================== */ +/* ======================================================== IOM5IRQ ======================================================== */ +/* ======================================================= BLEIFIRQ ======================================================== */ +/* ======================================================== GPIOOBS ======================================================== */ +/* ====================================================== ALTPADCFGA ======================================================= */ +/* =========================================== GPIO ALTPADCFGA PAD3_SR [28..28] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGA_PAD3_SR */ + GPIO_ALTPADCFGA_PAD3_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGA_PAD3_SR_Enum; + +/* =========================================== GPIO ALTPADCFGA PAD2_SR [20..20] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGA_PAD2_SR */ + GPIO_ALTPADCFGA_PAD2_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGA_PAD2_SR_Enum; + +/* =========================================== GPIO ALTPADCFGA PAD1_SR [12..12] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGA_PAD1_SR */ + GPIO_ALTPADCFGA_PAD1_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGA_PAD1_SR_Enum; + +/* ============================================ GPIO ALTPADCFGA PAD0_SR [4..4] ============================================= */ +typedef enum { /*!< GPIO_ALTPADCFGA_PAD0_SR */ + GPIO_ALTPADCFGA_PAD0_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGA_PAD0_SR_Enum; + +/* ====================================================== ALTPADCFGB ======================================================= */ +/* =========================================== GPIO ALTPADCFGB PAD7_SR [28..28] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGB_PAD7_SR */ + GPIO_ALTPADCFGB_PAD7_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGB_PAD7_SR_Enum; + +/* =========================================== GPIO ALTPADCFGB PAD6_SR [20..20] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGB_PAD6_SR */ + GPIO_ALTPADCFGB_PAD6_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGB_PAD6_SR_Enum; + +/* =========================================== GPIO ALTPADCFGB PAD5_SR [12..12] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGB_PAD5_SR */ + GPIO_ALTPADCFGB_PAD5_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGB_PAD5_SR_Enum; + +/* ============================================ GPIO ALTPADCFGB PAD4_SR [4..4] ============================================= */ +typedef enum { /*!< GPIO_ALTPADCFGB_PAD4_SR */ + GPIO_ALTPADCFGB_PAD4_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGB_PAD4_SR_Enum; + +/* ====================================================== ALTPADCFGC ======================================================= */ +/* =========================================== GPIO ALTPADCFGC PAD11_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGC_PAD11_SR */ + GPIO_ALTPADCFGC_PAD11_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGC_PAD11_SR_Enum; + +/* =========================================== GPIO ALTPADCFGC PAD10_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGC_PAD10_SR */ + GPIO_ALTPADCFGC_PAD10_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGC_PAD10_SR_Enum; + +/* =========================================== GPIO ALTPADCFGC PAD9_SR [12..12] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGC_PAD9_SR */ + GPIO_ALTPADCFGC_PAD9_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGC_PAD9_SR_Enum; + +/* ============================================ GPIO ALTPADCFGC PAD8_SR [4..4] ============================================= */ +typedef enum { /*!< GPIO_ALTPADCFGC_PAD8_SR */ + GPIO_ALTPADCFGC_PAD8_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGC_PAD8_SR_Enum; + +/* ====================================================== ALTPADCFGD ======================================================= */ +/* =========================================== GPIO ALTPADCFGD PAD15_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGD_PAD15_SR */ + GPIO_ALTPADCFGD_PAD15_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGD_PAD15_SR_Enum; + +/* =========================================== GPIO ALTPADCFGD PAD14_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGD_PAD14_SR */ + GPIO_ALTPADCFGD_PAD14_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGD_PAD14_SR_Enum; + +/* =========================================== GPIO ALTPADCFGD PAD13_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGD_PAD13_SR */ + GPIO_ALTPADCFGD_PAD13_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGD_PAD13_SR_Enum; + +/* ============================================ GPIO ALTPADCFGD PAD12_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGD_PAD12_SR */ + GPIO_ALTPADCFGD_PAD12_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGD_PAD12_SR_Enum; + +/* ====================================================== ALTPADCFGE ======================================================= */ +/* =========================================== GPIO ALTPADCFGE PAD19_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGE_PAD19_SR */ + GPIO_ALTPADCFGE_PAD19_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGE_PAD19_SR_Enum; + +/* =========================================== GPIO ALTPADCFGE PAD18_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGE_PAD18_SR */ + GPIO_ALTPADCFGE_PAD18_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGE_PAD18_SR_Enum; + +/* =========================================== GPIO ALTPADCFGE PAD17_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGE_PAD17_SR */ + GPIO_ALTPADCFGE_PAD17_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGE_PAD17_SR_Enum; + +/* ============================================ GPIO ALTPADCFGE PAD16_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGE_PAD16_SR */ + GPIO_ALTPADCFGE_PAD16_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGE_PAD16_SR_Enum; + +/* ====================================================== ALTPADCFGF ======================================================= */ +/* =========================================== GPIO ALTPADCFGF PAD23_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGF_PAD23_SR */ + GPIO_ALTPADCFGF_PAD23_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGF_PAD23_SR_Enum; + +/* =========================================== GPIO ALTPADCFGF PAD22_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGF_PAD22_SR */ + GPIO_ALTPADCFGF_PAD22_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGF_PAD22_SR_Enum; + +/* =========================================== GPIO ALTPADCFGF PAD21_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGF_PAD21_SR */ + GPIO_ALTPADCFGF_PAD21_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGF_PAD21_SR_Enum; + +/* ============================================ GPIO ALTPADCFGF PAD20_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGF_PAD20_SR */ + GPIO_ALTPADCFGF_PAD20_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGF_PAD20_SR_Enum; + +/* ====================================================== ALTPADCFGG ======================================================= */ +/* =========================================== GPIO ALTPADCFGG PAD27_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGG_PAD27_SR */ + GPIO_ALTPADCFGG_PAD27_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGG_PAD27_SR_Enum; + +/* =========================================== GPIO ALTPADCFGG PAD26_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGG_PAD26_SR */ + GPIO_ALTPADCFGG_PAD26_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGG_PAD26_SR_Enum; + +/* =========================================== GPIO ALTPADCFGG PAD25_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGG_PAD25_SR */ + GPIO_ALTPADCFGG_PAD25_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGG_PAD25_SR_Enum; + +/* ============================================ GPIO ALTPADCFGG PAD24_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGG_PAD24_SR */ + GPIO_ALTPADCFGG_PAD24_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGG_PAD24_SR_Enum; + +/* ====================================================== ALTPADCFGH ======================================================= */ +/* =========================================== GPIO ALTPADCFGH PAD31_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGH_PAD31_SR */ + GPIO_ALTPADCFGH_PAD31_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGH_PAD31_SR_Enum; + +/* =========================================== GPIO ALTPADCFGH PAD30_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGH_PAD30_SR */ + GPIO_ALTPADCFGH_PAD30_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGH_PAD30_SR_Enum; + +/* =========================================== GPIO ALTPADCFGH PAD29_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGH_PAD29_SR */ + GPIO_ALTPADCFGH_PAD29_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGH_PAD29_SR_Enum; + +/* ============================================ GPIO ALTPADCFGH PAD28_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGH_PAD28_SR */ + GPIO_ALTPADCFGH_PAD28_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGH_PAD28_SR_Enum; + +/* ====================================================== ALTPADCFGI ======================================================= */ +/* =========================================== GPIO ALTPADCFGI PAD35_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGI_PAD35_SR */ + GPIO_ALTPADCFGI_PAD35_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGI_PAD35_SR_Enum; + +/* =========================================== GPIO ALTPADCFGI PAD34_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGI_PAD34_SR */ + GPIO_ALTPADCFGI_PAD34_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGI_PAD34_SR_Enum; + +/* =========================================== GPIO ALTPADCFGI PAD33_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGI_PAD33_SR */ + GPIO_ALTPADCFGI_PAD33_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGI_PAD33_SR_Enum; + +/* ============================================ GPIO ALTPADCFGI PAD32_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGI_PAD32_SR */ + GPIO_ALTPADCFGI_PAD32_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGI_PAD32_SR_Enum; + +/* ====================================================== ALTPADCFGJ ======================================================= */ +/* =========================================== GPIO ALTPADCFGJ PAD39_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGJ_PAD39_SR */ + GPIO_ALTPADCFGJ_PAD39_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGJ_PAD39_SR_Enum; + +/* =========================================== GPIO ALTPADCFGJ PAD38_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGJ_PAD38_SR */ + GPIO_ALTPADCFGJ_PAD38_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGJ_PAD38_SR_Enum; + +/* =========================================== GPIO ALTPADCFGJ PAD37_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGJ_PAD37_SR */ + GPIO_ALTPADCFGJ_PAD37_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGJ_PAD37_SR_Enum; + +/* ============================================ GPIO ALTPADCFGJ PAD36_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGJ_PAD36_SR */ + GPIO_ALTPADCFGJ_PAD36_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGJ_PAD36_SR_Enum; + +/* ====================================================== ALTPADCFGK ======================================================= */ +/* =========================================== GPIO ALTPADCFGK PAD43_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGK_PAD43_SR */ + GPIO_ALTPADCFGK_PAD43_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGK_PAD43_SR_Enum; + +/* =========================================== GPIO ALTPADCFGK PAD42_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGK_PAD42_SR */ + GPIO_ALTPADCFGK_PAD42_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGK_PAD42_SR_Enum; + +/* =========================================== GPIO ALTPADCFGK PAD41_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGK_PAD41_SR */ + GPIO_ALTPADCFGK_PAD41_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGK_PAD41_SR_Enum; + +/* ============================================ GPIO ALTPADCFGK PAD40_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGK_PAD40_SR */ + GPIO_ALTPADCFGK_PAD40_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGK_PAD40_SR_Enum; + +/* ====================================================== ALTPADCFGL ======================================================= */ +/* =========================================== GPIO ALTPADCFGL PAD47_SR [28..28] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGL_PAD47_SR */ + GPIO_ALTPADCFGL_PAD47_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGL_PAD47_SR_Enum; + +/* =========================================== GPIO ALTPADCFGL PAD46_SR [20..20] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGL_PAD46_SR */ + GPIO_ALTPADCFGL_PAD46_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGL_PAD46_SR_Enum; + +/* =========================================== GPIO ALTPADCFGL PAD45_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGL_PAD45_SR */ + GPIO_ALTPADCFGL_PAD45_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGL_PAD45_SR_Enum; + +/* ============================================ GPIO ALTPADCFGL PAD44_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGL_PAD44_SR */ + GPIO_ALTPADCFGL_PAD44_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGL_PAD44_SR_Enum; + +/* ====================================================== ALTPADCFGM ======================================================= */ +/* =========================================== GPIO ALTPADCFGM PAD49_SR [12..12] =========================================== */ +typedef enum { /*!< GPIO_ALTPADCFGM_PAD49_SR */ + GPIO_ALTPADCFGM_PAD49_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGM_PAD49_SR_Enum; + +/* ============================================ GPIO ALTPADCFGM PAD48_SR [4..4] ============================================ */ +typedef enum { /*!< GPIO_ALTPADCFGM_PAD48_SR */ + GPIO_ALTPADCFGM_PAD48_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ +} GPIO_ALTPADCFGM_PAD48_SR_Enum; + +/* ========================================================= SCDET ========================================================= */ +/* ======================================================== CTENCFG ======================================================== */ +/* ============================================== GPIO CTENCFG EN31 [31..31] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN31 */ + GPIO_CTENCFG_EN31_DIS = 1, /*!< DIS : Disable CT31 for output value. */ + GPIO_CTENCFG_EN31_EN = 0, /*!< EN : Enable CT31 for output value. */ +} GPIO_CTENCFG_EN31_Enum; + +/* ============================================== GPIO CTENCFG EN30 [30..30] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN30 */ + GPIO_CTENCFG_EN30_DIS = 1, /*!< DIS : Disable CT30 for output value. */ + GPIO_CTENCFG_EN30_EN = 0, /*!< EN : Enable CT30 for output value. */ +} GPIO_CTENCFG_EN30_Enum; + +/* ============================================== GPIO CTENCFG EN29 [29..29] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN29 */ + GPIO_CTENCFG_EN29_DIS = 1, /*!< DIS : Disable CT29 for output value. */ + GPIO_CTENCFG_EN29_EN = 0, /*!< EN : Enable CT29 for output value. */ +} GPIO_CTENCFG_EN29_Enum; + +/* ============================================== GPIO CTENCFG EN28 [28..28] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN28 */ + GPIO_CTENCFG_EN28_DIS = 1, /*!< DIS : Disable CT28 for output value. */ + GPIO_CTENCFG_EN28_EN = 0, /*!< EN : Enable CT28 for output value. */ +} GPIO_CTENCFG_EN28_Enum; + +/* ============================================== GPIO CTENCFG EN27 [27..27] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN27 */ + GPIO_CTENCFG_EN27_DIS = 1, /*!< DIS : Disable CT27 for output value. */ + GPIO_CTENCFG_EN27_EN = 0, /*!< EN : Enable CT27 for output value. */ +} GPIO_CTENCFG_EN27_Enum; + +/* ============================================== GPIO CTENCFG EN26 [26..26] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN26 */ + GPIO_CTENCFG_EN26_DIS = 1, /*!< DIS : Disable CT26 for output value. */ + GPIO_CTENCFG_EN26_EN = 0, /*!< EN : Enable CT26 for output value. */ +} GPIO_CTENCFG_EN26_Enum; + +/* ============================================== GPIO CTENCFG EN25 [25..25] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN25 */ + GPIO_CTENCFG_EN25_DIS = 1, /*!< DIS : Disable CT25 for output value. */ + GPIO_CTENCFG_EN25_EN = 0, /*!< EN : Enable CT25 for output value. */ +} GPIO_CTENCFG_EN25_Enum; + +/* ============================================== GPIO CTENCFG EN24 [24..24] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN24 */ + GPIO_CTENCFG_EN24_DIS = 1, /*!< DIS : Disable CT24 for output value. */ + GPIO_CTENCFG_EN24_EN = 0, /*!< EN : Enable CT24 for output value. */ +} GPIO_CTENCFG_EN24_Enum; + +/* ============================================== GPIO CTENCFG EN23 [23..23] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN23 */ + GPIO_CTENCFG_EN23_DIS = 1, /*!< DIS : Disable CT23 for output value. */ + GPIO_CTENCFG_EN23_EN = 0, /*!< EN : Enable CT23 for output value. */ +} GPIO_CTENCFG_EN23_Enum; + +/* ============================================== GPIO CTENCFG EN22 [22..22] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN22 */ + GPIO_CTENCFG_EN22_DIS = 1, /*!< DIS : Disable CT22 for output value. */ + GPIO_CTENCFG_EN22_EN = 0, /*!< EN : Enable CT22 for output value. */ +} GPIO_CTENCFG_EN22_Enum; + +/* ============================================== GPIO CTENCFG EN21 [21..21] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN21 */ + GPIO_CTENCFG_EN21_DIS = 1, /*!< DIS : Disable CT21 for output value. */ + GPIO_CTENCFG_EN21_EN = 0, /*!< EN : Enable CT21 for output value. */ +} GPIO_CTENCFG_EN21_Enum; + +/* ============================================== GPIO CTENCFG EN20 [20..20] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN20 */ + GPIO_CTENCFG_EN20_DIS = 1, /*!< DIS : Disable CT20 for output value. */ + GPIO_CTENCFG_EN20_EN = 0, /*!< EN : Enable CT20 for output value. */ +} GPIO_CTENCFG_EN20_Enum; + +/* ============================================== GPIO CTENCFG EN19 [19..19] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN19 */ + GPIO_CTENCFG_EN19_DIS = 1, /*!< DIS : Disable CT19 for output value. */ + GPIO_CTENCFG_EN19_EN = 0, /*!< EN : Enable CT19 for output value. */ +} GPIO_CTENCFG_EN19_Enum; + +/* ============================================== GPIO CTENCFG EN18 [18..18] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN18 */ + GPIO_CTENCFG_EN18_DIS = 1, /*!< DIS : Disable CT18 for output value. */ + GPIO_CTENCFG_EN18_EN = 0, /*!< EN : Enable CT18 for output value. */ +} GPIO_CTENCFG_EN18_Enum; + +/* ============================================== GPIO CTENCFG EN17 [17..17] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN17 */ + GPIO_CTENCFG_EN17_DIS = 1, /*!< DIS : Disable CT17 for output value. */ + GPIO_CTENCFG_EN17_EN = 0, /*!< EN : Enable CT17 for output value. */ +} GPIO_CTENCFG_EN17_Enum; + +/* ============================================== GPIO CTENCFG EN16 [16..16] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN16 */ + GPIO_CTENCFG_EN16_DIS = 1, /*!< DIS : Disable CT16 for output value. */ + GPIO_CTENCFG_EN16_EN = 0, /*!< EN : Enable CT16 for output value. */ +} GPIO_CTENCFG_EN16_Enum; + +/* ============================================== GPIO CTENCFG EN15 [15..15] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN15 */ + GPIO_CTENCFG_EN15_DIS = 1, /*!< DIS : Disable CT15 for output value. */ + GPIO_CTENCFG_EN15_EN = 0, /*!< EN : Enable CT15 for output value. */ +} GPIO_CTENCFG_EN15_Enum; + +/* ============================================== GPIO CTENCFG EN14 [14..14] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN14 */ + GPIO_CTENCFG_EN14_DIS = 1, /*!< DIS : Disable CT14 for output value. */ + GPIO_CTENCFG_EN14_EN = 0, /*!< EN : Enable CT14 for output value. */ +} GPIO_CTENCFG_EN14_Enum; + +/* ============================================== GPIO CTENCFG EN13 [13..13] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN13 */ + GPIO_CTENCFG_EN13_DIS = 1, /*!< DIS : Disable CT13 for output value. */ + GPIO_CTENCFG_EN13_EN = 0, /*!< EN : Enable CT13 for output value. */ +} GPIO_CTENCFG_EN13_Enum; + +/* ============================================== GPIO CTENCFG EN12 [12..12] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN12 */ + GPIO_CTENCFG_EN12_DIS = 1, /*!< DIS : Disable CT12 for output value. */ + GPIO_CTENCFG_EN12_EN = 0, /*!< EN : Enable CT12 for output value. */ +} GPIO_CTENCFG_EN12_Enum; + +/* ============================================== GPIO CTENCFG EN11 [11..11] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN11 */ + GPIO_CTENCFG_EN11_DIS = 1, /*!< DIS : Disable CT11 for output value. */ + GPIO_CTENCFG_EN11_EN = 0, /*!< EN : Enable CT11 for output value. */ +} GPIO_CTENCFG_EN11_Enum; + +/* ============================================== GPIO CTENCFG EN10 [10..10] =============================================== */ +typedef enum { /*!< GPIO_CTENCFG_EN10 */ + GPIO_CTENCFG_EN10_DIS = 1, /*!< DIS : Disable CT10 for output value. */ + GPIO_CTENCFG_EN10_EN = 0, /*!< EN : Enable CT10 for output value. */ +} GPIO_CTENCFG_EN10_Enum; + +/* ================================================ GPIO CTENCFG EN9 [9..9] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN9 */ + GPIO_CTENCFG_EN9_DIS = 0, /*!< DIS : Disable CT9 for output value. */ +} GPIO_CTENCFG_EN9_Enum; + +/* ================================================ GPIO CTENCFG EN8 [8..8] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN8 */ + GPIO_CTENCFG_EN8_DIS = 1, /*!< DIS : Disable CT8 for output value. */ + GPIO_CTENCFG_EN8_EN = 0, /*!< EN : Enable CT8 for output value. */ +} GPIO_CTENCFG_EN8_Enum; + +/* ================================================ GPIO CTENCFG EN7 [7..7] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN7 */ + GPIO_CTENCFG_EN7_DIS = 1, /*!< DIS : Disable CT7 for output value. */ + GPIO_CTENCFG_EN7_EN = 0, /*!< EN : Enable CT7 for output value. */ +} GPIO_CTENCFG_EN7_Enum; + +/* ================================================ GPIO CTENCFG EN6 [6..6] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN6 */ + GPIO_CTENCFG_EN6_DIS = 1, /*!< DIS : Disable CT6 for output value. */ + GPIO_CTENCFG_EN6_EN = 0, /*!< EN : Enable CT6 for output value. */ +} GPIO_CTENCFG_EN6_Enum; + +/* ================================================ GPIO CTENCFG EN5 [5..5] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN5 */ + GPIO_CTENCFG_EN5_DIS = 1, /*!< DIS : Disable CT5 for output value. */ + GPIO_CTENCFG_EN5_EN = 0, /*!< EN : Enable CT5 for output value. */ +} GPIO_CTENCFG_EN5_Enum; + +/* ================================================ GPIO CTENCFG EN4 [4..4] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN4 */ + GPIO_CTENCFG_EN4_DIS = 1, /*!< DIS : Disable CT4 for output value. */ + GPIO_CTENCFG_EN4_EN = 0, /*!< EN : Enable CT4 for output value. */ +} GPIO_CTENCFG_EN4_Enum; + +/* ================================================ GPIO CTENCFG EN3 [3..3] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN3 */ + GPIO_CTENCFG_EN3_DIS = 1, /*!< DIS : Disable CT3 for output value. */ + GPIO_CTENCFG_EN3_EN = 0, /*!< EN : Enable CT3 for output value. */ +} GPIO_CTENCFG_EN3_Enum; + +/* ================================================ GPIO CTENCFG EN2 [2..2] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN2 */ + GPIO_CTENCFG_EN2_DIS = 1, /*!< DIS : Disable CT2 for output value. */ + GPIO_CTENCFG_EN2_EN = 0, /*!< EN : Enable CT2 for output value. */ +} GPIO_CTENCFG_EN2_Enum; + +/* ================================================ GPIO CTENCFG EN1 [1..1] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN1 */ + GPIO_CTENCFG_EN1_DIS = 1, /*!< DIS : Disable CT1 for output value. */ + GPIO_CTENCFG_EN1_EN = 0, /*!< EN : Enable CT1 for output value. */ +} GPIO_CTENCFG_EN1_Enum; + +/* ================================================ GPIO CTENCFG EN0 [0..0] ================================================ */ +typedef enum { /*!< GPIO_CTENCFG_EN0 */ + GPIO_CTENCFG_EN0_DIS = 1, /*!< DIS : Disable CT0 for output value. */ + GPIO_CTENCFG_EN0_EN = 0, /*!< EN : Enable CT0 for output value. */ +} GPIO_CTENCFG_EN0_Enum; + +/* ======================================================== INT0EN ========================================================= */ +/* ======================================================= INT0STAT ======================================================== */ +/* ======================================================== INT0CLR ======================================================== */ +/* ======================================================== INT0SET ======================================================== */ +/* ======================================================== INT1EN ========================================================= */ +/* ======================================================= INT1STAT ======================================================== */ +/* ======================================================== INT1CLR ======================================================== */ +/* ======================================================== INT1SET ======================================================== */ + + +/* =========================================================================================================================== */ +/* ================ IOM0 ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= FIFO ========================================================== */ +/* ======================================================== FIFOPTR ======================================================== */ +/* ======================================================== FIFOTHR ======================================================== */ +/* ======================================================== FIFOPOP ======================================================== */ +/* ======================================================= FIFOPUSH ======================================================== */ +/* ======================================================= FIFOCTRL ======================================================== */ +/* ======================================================== FIFOLOC ======================================================== */ +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ +/* ======================================================== CLKCFG ========================================================= */ +/* ============================================== IOM0 CLKCFG DIVEN [12..12] =============================================== */ +typedef enum { /*!< IOM0_CLKCFG_DIVEN */ + IOM0_CLKCFG_DIVEN_DIS = 0, /*!< DIS : Disable TOTPER division. value. */ + IOM0_CLKCFG_DIVEN_EN = 1, /*!< EN : Enable TOTPER division. value. */ +} IOM0_CLKCFG_DIVEN_Enum; + +/* =============================================== IOM0 CLKCFG DIV3 [11..11] =============================================== */ +typedef enum { /*!< IOM0_CLKCFG_DIV3 */ + IOM0_CLKCFG_DIV3_DIS = 0, /*!< DIS : Select divide by 1. value. */ + IOM0_CLKCFG_DIV3_EN = 1, /*!< EN : Select divide by 3. value. */ +} IOM0_CLKCFG_DIV3_Enum; + +/* =============================================== IOM0 CLKCFG FSEL [8..10] ================================================ */ +typedef enum { /*!< IOM0_CLKCFG_FSEL */ + IOM0_CLKCFG_FSEL_MIN_PWR = 0, /*!< MIN_PWR : Selects the minimum power clock. This setting should + be used whenever the IOM is not active. value. */ + IOM0_CLKCFG_FSEL_HFRC = 1, /*!< HFRC : Selects the HFRC as the input clock. value. */ + IOM0_CLKCFG_FSEL_HFRC_DIV2 = 2, /*!< HFRC_DIV2 : Selects the HFRC / 2 as the input clock. value. */ + IOM0_CLKCFG_FSEL_HFRC_DIV4 = 3, /*!< HFRC_DIV4 : Selects the HFRC / 4 as the input clock. value. */ + IOM0_CLKCFG_FSEL_HFRC_DIV8 = 4, /*!< HFRC_DIV8 : Selects the HFRC / 8 as the input clock. value. */ + IOM0_CLKCFG_FSEL_HFRC_DIV16 = 5, /*!< HFRC_DIV16 : Selects the HFRC / 16 as the input clock. value. */ + IOM0_CLKCFG_FSEL_HFRC_DIV32 = 6, /*!< HFRC_DIV32 : Selects the HFRC / 32 as the input clock. value. */ + IOM0_CLKCFG_FSEL_HFRC_DIV64 = 7, /*!< HFRC_DIV64 : Selects the HFRC / 64 as the input clock. value. */ +} IOM0_CLKCFG_FSEL_Enum; + +/* ====================================================== SUBMODCTRL ======================================================= */ +/* =========================================== IOM0 SUBMODCTRL SMOD1TYPE [5..7] ============================================ */ +typedef enum { /*!< IOM0_SUBMODCTRL_SMOD1TYPE */ + IOM0_SUBMODCTRL_SMOD1TYPE_MSPI = 0, /*!< MSPI : SPI Master submodule value. */ + IOM0_SUBMODCTRL_SMOD1TYPE_I2C_MASTER = 1, /*!< I2C_MASTER : MI2C submodule value. */ + IOM0_SUBMODCTRL_SMOD1TYPE_SSPI = 2, /*!< SSPI : SPI Slave submodule value. */ + IOM0_SUBMODCTRL_SMOD1TYPE_SI2C = 3, /*!< SI2C : I2C Slave submodule value. */ + IOM0_SUBMODCTRL_SMOD1TYPE_NA = 7, /*!< NA : NOT INSTALLED value. */ +} IOM0_SUBMODCTRL_SMOD1TYPE_Enum; + +/* =========================================== IOM0 SUBMODCTRL SMOD0TYPE [1..3] ============================================ */ +typedef enum { /*!< IOM0_SUBMODCTRL_SMOD0TYPE */ + IOM0_SUBMODCTRL_SMOD0TYPE_SPI_MASTER = 0, /*!< SPI_MASTER : MSPI submodule value. */ + IOM0_SUBMODCTRL_SMOD0TYPE_I2C_MASTER = 1, /*!< I2C_MASTER : I2C Master submodule value. */ + IOM0_SUBMODCTRL_SMOD0TYPE_SSPI = 2, /*!< SSPI : SPI Slave submodule value. */ + IOM0_SUBMODCTRL_SMOD0TYPE_SI2C = 3, /*!< SI2C : I2C Slave submodule value. */ + IOM0_SUBMODCTRL_SMOD0TYPE_NA = 7, /*!< NA : NOT INSTALLED value. */ +} IOM0_SUBMODCTRL_SMOD0TYPE_Enum; + +/* ========================================================== CMD ========================================================== */ +/* ================================================== IOM0 CMD CMD [0..4] ================================================== */ +typedef enum { /*!< IOM0_CMD_CMD */ + IOM0_CMD_CMD_WRITE = 1, /*!< WRITE : Write command using count of offset bytes specified + in the OFFSETCNT field value. */ + IOM0_CMD_CMD_READ = 2, /*!< READ : Read command using count of offset bytes specified in + the OFFSETCNT field value. */ + IOM0_CMD_CMD_TMW = 3, /*!< TMW : SPI only. Test mode to do constant write operations. Useful + for debug and power measurements. Will continually send + data in OFFSET field value. */ + IOM0_CMD_CMD_TMR = 4, /*!< TMR : SPI Only. Test mode to do constant read operations. Useful + for debug and power measurements. Will continually read + data from external input value. */ +} IOM0_CMD_CMD_Enum; + +/* ======================================================== CMDRPT ========================================================= */ +/* ======================================================= OFFSETHI ======================================================== */ +/* ======================================================== CMDSTAT ======================================================== */ +/* ============================================== IOM0 CMDSTAT CMDSTAT [5..7] ============================================== */ +typedef enum { /*!< IOM0_CMDSTAT_CMDSTAT */ + IOM0_CMDSTAT_CMDSTAT_ERR = 1, /*!< ERR : Error encountered with command value. */ + IOM0_CMDSTAT_CMDSTAT_ACTIVE = 2, /*!< ACTIVE : Actively processing command value. */ + IOM0_CMDSTAT_CMDSTAT_IDLE = 4, /*!< IDLE : Idle state, no active command, no error value. */ + IOM0_CMDSTAT_CMDSTAT_WAIT = 6, /*!< WAIT : Command in progress, but waiting on data from host value. */ +} IOM0_CMDSTAT_CMDSTAT_Enum; + +/* ======================================================= DMATRIGEN ======================================================= */ +/* ====================================================== DMATRIGSTAT ====================================================== */ +/* ======================================================== DMACFG ========================================================= */ +/* ============================================== IOM0 DMACFG DPWROFF [9..9] =============================================== */ +typedef enum { /*!< IOM0_DMACFG_DPWROFF */ + IOM0_DMACFG_DPWROFF_DIS = 0, /*!< DIS : Power off disabled value. */ + IOM0_DMACFG_DPWROFF_EN = 1, /*!< EN : Power off enabled value. */ +} IOM0_DMACFG_DPWROFF_Enum; + +/* =============================================== IOM0 DMACFG DMAPRI [8..8] =============================================== */ +typedef enum { /*!< IOM0_DMACFG_DMAPRI */ + IOM0_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ + IOM0_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ +} IOM0_DMACFG_DMAPRI_Enum; + +/* =============================================== IOM0 DMACFG DMADIR [1..1] =============================================== */ +typedef enum { /*!< IOM0_DMACFG_DMADIR */ + IOM0_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction. To be set when + doing IOM read operations, ie reading data from external + devices. value. */ + IOM0_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction. To be set when doing + IOM write operations, ie writing data to external devices. + value. */ +} IOM0_DMACFG_DMADIR_Enum; + +/* =============================================== IOM0 DMACFG DMAEN [0..0] ================================================ */ +typedef enum { /*!< IOM0_DMACFG_DMAEN */ + IOM0_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ + IOM0_DMACFG_DMAEN_EN = 1, /*!< EN : Enable DMA Function value. */ +} IOM0_DMACFG_DMAEN_Enum; + +/* ====================================================== DMATOTCOUNT ====================================================== */ +/* ====================================================== DMATARGADDR ====================================================== */ +/* ======================================================== DMASTAT ======================================================== */ +/* ========================================================= CQCFG ========================================================= */ +/* ================================================ IOM0 CQCFG CQPRI [1..1] ================================================ */ +typedef enum { /*!< IOM0_CQCFG_CQPRI */ + IOM0_CQCFG_CQPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ + IOM0_CQCFG_CQPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ +} IOM0_CQCFG_CQPRI_Enum; + +/* ================================================ IOM0 CQCFG CQEN [0..0] ================================================= */ +typedef enum { /*!< IOM0_CQCFG_CQEN */ + IOM0_CQCFG_CQEN_DIS = 0, /*!< DIS : Disable CQ Function value. */ + IOM0_CQCFG_CQEN_EN = 1, /*!< EN : Enable CQ Function value. */ +} IOM0_CQCFG_CQEN_Enum; + +/* ======================================================== CQADDR ========================================================= */ +/* ======================================================== CQSTAT ========================================================= */ +/* ======================================================== CQFLAGS ======================================================== */ +/* ====================================================== CQSETCLEAR ======================================================= */ +/* ======================================================= CQPAUSEEN ======================================================= */ +/* ============================================= IOM0 CQPAUSEEN CQPEN [0..15] ============================================== */ +typedef enum { /*!< IOM0_CQPAUSEEN_CQPEN */ + IOM0_CQPAUSEEN_CQPEN_IDXEQ = 32768, /*!< IDXEQ : Pauses the command queue when the current index matches + the last index value. */ + IOM0_CQPAUSEEN_CQPEN_BLEXOREN = 16384, /*!< BLEXOREN : Pause command queue when input BLE bit XORed with + SWFLAG4 is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_IOMXOREN = 8192, /*!< IOMXOREN : Pause command queue when input IOM bit XORed with + SWFLAG3 is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_GPIOXOREN = 4096, /*!< GPIOXOREN : Pause command queue when input GPIO irq_bit XORed + with SWFLAG2 is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_MSPI1XNOREN = 2048, /*!< MSPI1XNOREN : Pause command queue when input MSPI1 bit XNORed + with SWFLAG1 is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_MSPI0XNOREN = 1024, /*!< MSPI0XNOREN : Pause command queue when input MSPI0 bit XNORed + with SWFLAG0 is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_MSPI1XOREN = 512, /*!< MSPI1XOREN : Pause command queue when input MSPI1 bit XORed + with SWFLAG1 is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_MSPI0XOREN = 256, /*!< MSPI0XOREN : Pause command queue when input MSPI0 bit XORed + with SWFLAG0 is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_SWFLAGEN7 = 128, /*!< SWFLAGEN7 : Pause the command queue when software flag bit 7 + is '1'. value. */ + IOM0_CQPAUSEEN_CQPEN_SWFLAGEN6 = 64, /*!< SWFLAGEN6 : Pause the command queue when software flag bit 6 + is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_SWFLAGEN5 = 32, /*!< SWFLAGEN5 : Pause the command queue when software flag bit 5 + is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_SWFLAGEN4 = 16, /*!< SWFLAGEN4 : Pause the command queue when software flag bit 4 + is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_SWFLAGEN3 = 8, /*!< SWFLAGEN3 : Pause the command queue when software flag bit 3 + is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_SWFLAGEN2 = 4, /*!< SWFLAGEN2 : Pause the command queue when software flag bit 2 + is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_SWFLAGEN1 = 2, /*!< SWFLAGEN1 : Pause the command queue when software flag bit 1 + is '1' value. */ + IOM0_CQPAUSEEN_CQPEN_SWFLAGEN0 = 1, /*!< SWFLAGEN0 : Pause the command queue when software flag bit 0 + is '1' value. */ +} IOM0_CQPAUSEEN_CQPEN_Enum; + +/* ======================================================= CQCURIDX ======================================================== */ +/* ======================================================= CQENDIDX ======================================================== */ +/* ======================================================== STATUS ========================================================= */ +/* =============================================== IOM0 STATUS IDLEST [2..2] =============================================== */ +typedef enum { /*!< IOM0_STATUS_IDLEST */ + IOM0_STATUS_IDLEST_IDLE = 1, /*!< IDLE : The I/O state machine is in the idle state. value. */ +} IOM0_STATUS_IDLEST_Enum; + +/* =============================================== IOM0 STATUS CMDACT [1..1] =============================================== */ +typedef enum { /*!< IOM0_STATUS_CMDACT */ + IOM0_STATUS_CMDACT_ACTIVE = 1, /*!< ACTIVE : An I/O command is active. Indicates the active module + has an active command and is processing this. De-asserted + when the command is completed. value. */ +} IOM0_STATUS_CMDACT_Enum; + +/* ================================================ IOM0 STATUS ERR [0..0] ================================================= */ +typedef enum { /*!< IOM0_STATUS_ERR */ + IOM0_STATUS_ERR_ERROR = 1, /*!< ERROR : Bit has been deprecated and will always return 0. value. */ +} IOM0_STATUS_ERR_Enum; + +/* ======================================================== MSPICFG ======================================================== */ +/* ============================================= IOM0 MSPICFG SPILSB [23..23] ============================================== */ +typedef enum { /*!< IOM0_MSPICFG_SPILSB */ + IOM0_MSPICFG_SPILSB_MSB = 0, /*!< MSB : Send and receive MSB bit first value. */ + IOM0_MSPICFG_SPILSB_LSB = 1, /*!< LSB : Send and receive LSB bit first value. */ +} IOM0_MSPICFG_SPILSB_Enum; + +/* ============================================= IOM0 MSPICFG RDFCPOL [22..22] ============================================= */ +typedef enum { /*!< IOM0_MSPICFG_RDFCPOL */ + IOM0_MSPICFG_RDFCPOL_HIGH = 0, /*!< HIGH : Flow control signal high creates flow control. value. */ + IOM0_MSPICFG_RDFCPOL_LOW = 1, /*!< LOW : Flow control signal low creates flow control. value. */ +} IOM0_MSPICFG_RDFCPOL_Enum; + +/* ============================================= IOM0 MSPICFG WTFCPOL [21..21] ============================================= */ +typedef enum { /*!< IOM0_MSPICFG_WTFCPOL */ + IOM0_MSPICFG_WTFCPOL_HIGH = 0, /*!< HIGH : Flow control signal high(1) creates flow control and + byte transfers will stop until the flow control signal + goes low. value. */ + IOM0_MSPICFG_WTFCPOL_LOW = 1, /*!< LOW : Flow control signal low(0) creates flow control and byte + transfers will stop until the flow control signal goes + high(1). value. */ +} IOM0_MSPICFG_WTFCPOL_Enum; + +/* ============================================= IOM0 MSPICFG WTFCIRQ [20..20] ============================================= */ +typedef enum { /*!< IOM0_MSPICFG_WTFCIRQ */ + IOM0_MSPICFG_WTFCIRQ_MISO = 0, /*!< MISO : MISO is used as the write mode flow control signal. value. */ + IOM0_MSPICFG_WTFCIRQ_IRQ = 1, /*!< IRQ : IRQ is used as the write mode flow control signal. value. */ +} IOM0_MSPICFG_WTFCIRQ_Enum; + +/* ============================================= IOM0 MSPICFG MOSIINV [18..18] ============================================= */ +typedef enum { /*!< IOM0_MSPICFG_MOSIINV */ + IOM0_MSPICFG_MOSIINV_NORMAL = 0, /*!< NORMAL : MOSI is set to 0 in read mode and 1 in write mode. + value. */ + IOM0_MSPICFG_MOSIINV_INVERT = 1, /*!< INVERT : MOSI is set to 1 in read mode and 0 in write mode. + value. */ +} IOM0_MSPICFG_MOSIINV_Enum; + +/* ============================================== IOM0 MSPICFG RDFC [17..17] =============================================== */ +typedef enum { /*!< IOM0_MSPICFG_RDFC */ + IOM0_MSPICFG_RDFC_DIS = 0, /*!< DIS : Read mode flow control disabled. value. */ + IOM0_MSPICFG_RDFC_EN = 1, /*!< EN : Read mode flow control enabled. value. */ +} IOM0_MSPICFG_RDFC_Enum; + +/* ============================================== IOM0 MSPICFG WTFC [16..16] =============================================== */ +typedef enum { /*!< IOM0_MSPICFG_WTFC */ + IOM0_MSPICFG_WTFC_DIS = 0, /*!< DIS : Write mode flow control disabled. value. */ + IOM0_MSPICFG_WTFC_EN = 1, /*!< EN : Write mode flow control enabled. value. */ +} IOM0_MSPICFG_WTFC_Enum; + +/* =============================================== IOM0 MSPICFG SPHA [1..1] ================================================ */ +typedef enum { /*!< IOM0_MSPICFG_SPHA */ + IOM0_MSPICFG_SPHA_SAMPLE_LEADING_EDGE = 0, /*!< SAMPLE_LEADING_EDGE : Sample on the leading (first) clock edge. + value. */ + IOM0_MSPICFG_SPHA_SAMPLE_TRAILING_EDGE = 1, /*!< SAMPLE_TRAILING_EDGE : Sample on the trailing (second) clock + edge. value. */ +} IOM0_MSPICFG_SPHA_Enum; + +/* =============================================== IOM0 MSPICFG SPOL [0..0] ================================================ */ +typedef enum { /*!< IOM0_MSPICFG_SPOL */ + IOM0_MSPICFG_SPOL_CLK_BASE_0 = 0, /*!< CLK_BASE_0 : The base value of the clock is 0. value. */ + IOM0_MSPICFG_SPOL_CLK_BASE_1 = 1, /*!< CLK_BASE_1 : The base value of the clock is 1. value. */ +} IOM0_MSPICFG_SPOL_Enum; + +/* ======================================================== MI2CCFG ======================================================== */ +/* =============================================== IOM0 MI2CCFG ARBEN [2..2] =============================================== */ +typedef enum { /*!< IOM0_MI2CCFG_ARBEN */ + IOM0_MI2CCFG_ARBEN_ARBEN = 1, /*!< ARBEN : Enable multi-master bus arbitration support for this + i2c master value. */ + IOM0_MI2CCFG_ARBEN_ARBDIS = 0, /*!< ARBDIS : Disable multi-master bus arbitration support for this + i2c master value. */ +} IOM0_MI2CCFG_ARBEN_Enum; + +/* ============================================== IOM0 MI2CCFG I2CLSB [1..1] =============================================== */ +typedef enum { /*!< IOM0_MI2CCFG_I2CLSB */ + IOM0_MI2CCFG_I2CLSB_MSBFIRST = 0, /*!< MSBFIRST : Byte data is transmitted MSB first onto the bus/read + from the bus value. */ + IOM0_MI2CCFG_I2CLSB_LSBFIRST = 1, /*!< LSBFIRST : Byte data is transmitted LSB first onto the bus/read + from the bus value. */ +} IOM0_MI2CCFG_I2CLSB_Enum; + +/* ============================================== IOM0 MI2CCFG ADDRSZ [0..0] =============================================== */ +typedef enum { /*!< IOM0_MI2CCFG_ADDRSZ */ + IOM0_MI2CCFG_ADDRSZ_ADDRSZ7 = 0, /*!< ADDRSZ7 : Use 7b addressing for I2C master transactions value. */ + IOM0_MI2CCFG_ADDRSZ_ADDRSZ10 = 1, /*!< ADDRSZ10 : Use 10b addressing for I2C master transactions value. */ +} IOM0_MI2CCFG_ADDRSZ_Enum; + +/* ======================================================== DEVCFG ========================================================= */ +/* ======================================================== IOMDBG ========================================================= */ + + +/* =========================================================================================================================== */ +/* ================ IOSLAVE ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== FIFOPTR ======================================================== */ +/* ======================================================== FIFOCFG ======================================================== */ +/* ======================================================== FIFOTHR ======================================================== */ +/* ========================================================= FUPD ========================================================== */ +/* ======================================================== FIFOCTR ======================================================== */ +/* ======================================================== FIFOINC ======================================================== */ +/* ========================================================== CFG ========================================================== */ +/* ============================================== IOSLAVE CFG IFCEN [31..31] =============================================== */ +typedef enum { /*!< IOSLAVE_CFG_IFCEN */ + IOSLAVE_CFG_IFCEN_DIS = 0, /*!< DIS : Disable the IOSLAVE value. */ + IOSLAVE_CFG_IFCEN_EN = 1, /*!< EN : Enable the IOSLAVE value. */ +} IOSLAVE_CFG_IFCEN_Enum; + +/* ============================================== IOSLAVE CFG STARTRD [4..4] =============================================== */ +typedef enum { /*!< IOSLAVE_CFG_STARTRD */ + IOSLAVE_CFG_STARTRD_LATE = 0, /*!< LATE : Initiate I/O RAM read late in each transferred byte. + value. */ + IOSLAVE_CFG_STARTRD_EARLY = 1, /*!< EARLY : Initiate I/O RAM read early in each transferred byte. + value. */ +} IOSLAVE_CFG_STARTRD_Enum; + +/* ================================================ IOSLAVE CFG LSB [2..2] ================================================= */ +typedef enum { /*!< IOSLAVE_CFG_LSB */ + IOSLAVE_CFG_LSB_MSB_FIRST = 0, /*!< MSB_FIRST : Data is assumed to be sent and received with MSB + first. value. */ + IOSLAVE_CFG_LSB_LSB_FIRST = 1, /*!< LSB_FIRST : Data is assumed to be sent and received with LSB + first. value. */ +} IOSLAVE_CFG_LSB_Enum; + +/* ================================================ IOSLAVE CFG SPOL [1..1] ================================================ */ +typedef enum { /*!< IOSLAVE_CFG_SPOL */ + IOSLAVE_CFG_SPOL_SPI_MODES_0_3 = 0, /*!< SPI_MODES_0_3 : Polarity 0, handles SPI modes 0 and 3. value. */ + IOSLAVE_CFG_SPOL_SPI_MODES_1_2 = 1, /*!< SPI_MODES_1_2 : Polarity 1, handles SPI modes 1 and 2. value. */ +} IOSLAVE_CFG_SPOL_Enum; + +/* =============================================== IOSLAVE CFG IFCSEL [0..0] =============================================== */ +typedef enum { /*!< IOSLAVE_CFG_IFCSEL */ + IOSLAVE_CFG_IFCSEL_I2C = 0, /*!< I2C : Selects I2C interface for the IO Slave. value. */ + IOSLAVE_CFG_IFCSEL_SPI = 1, /*!< SPI : Selects SPI interface for the IO Slave. value. */ +} IOSLAVE_CFG_IFCSEL_Enum; + +/* ========================================================= PRENC ========================================================= */ +/* ======================================================= IOINTCTL ======================================================== */ +/* ======================================================== GENADD ========================================================= */ +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ +/* ====================================================== REGACCINTEN ====================================================== */ +/* ===================================================== REGACCINTSTAT ===================================================== */ +/* ===================================================== REGACCINTCLR ====================================================== */ +/* ===================================================== REGACCINTSET ====================================================== */ + + +/* =========================================================================================================================== */ +/* ================ MCUCTRL ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== CHIPPN ========================================================= */ +/* ============================================ MCUCTRL CHIPPN PARTNUM [0..31] ============================================= */ +typedef enum { /*!< MCUCTRL_CHIPPN_PARTNUM */ + MCUCTRL_CHIPPN_PARTNUM_APOLLO3 = 100663296,/*!< APOLLO3 : Apollo3 part number is 0x06xxxxxx. value. */ + MCUCTRL_CHIPPN_PARTNUM_APOLLO2 = 50331648,/*!< APOLLO2 : Apollo2 part number is 0x03xxxxxx. value. */ + MCUCTRL_CHIPPN_PARTNUM_APOLLO = 16777216,/*!< APOLLO : Apollo part number is 0x01xxxxxx. value. */ + MCUCTRL_CHIPPN_PARTNUM_PN_M = -16777216,/*!< PN_M : Mask for the part number field. value. */ + MCUCTRL_CHIPPN_PARTNUM_PN_S = 24, /*!< PN_S : Bit position for the part number field. value. */ + MCUCTRL_CHIPPN_PARTNUM_FLASHSIZE_M = 15728640,/*!< FLASHSIZE_M : Mask for the FLASH_SIZE field.Values:0: 16KB1: + 32KB2: 64KB3: 128KB4: 256KB5: 512KB6: 1MB7: 2MB value. */ + MCUCTRL_CHIPPN_PARTNUM_FLASHSIZE_S = 20, /*!< FLASHSIZE_S : Bit position for the FLASH_SIZE field. value. */ + MCUCTRL_CHIPPN_PARTNUM_SRAMSIZE_M = 983040,/*!< SRAMSIZE_M : Mask for the SRAM_SIZE field.Values:0: 16KB1: 32KB2: + 64KB3: 128KB4: 256KB5: 512KB6: 1MB7: 384KB value. */ + MCUCTRL_CHIPPN_PARTNUM_SRAMSIZE_S = 16, /*!< SRAMSIZE_S : Bit position for the SRAM_SIZE field. value. */ + MCUCTRL_CHIPPN_PARTNUM_REV_M = 65280, /*!< REV_M : Mask for the revision field. Bits [15:12] are major + rev, [11:8] are minor rev.Values:0: Major Rev A, Minor + Rev 01: Major Rev B, Minor Rev 1 value. */ + MCUCTRL_CHIPPN_PARTNUM_REV_S = 8, /*!< REV_S : Bit position for the revision field. value. */ + MCUCTRL_CHIPPN_PARTNUM_PKG_M = 192, /*!< PKG_M : Mask for the package field.Values:0: SIP1: QFN2: BGA3: + CSP value. */ + MCUCTRL_CHIPPN_PARTNUM_PKG_S = 6, /*!< PKG_S : Bit position for the package field. value. */ + MCUCTRL_CHIPPN_PARTNUM_PINS_M = 56, /*!< PINS_M : Mask for the pins field.Values:0: 25 pins1: 49 pins2: + 64 pins3: 81 pins value. */ + MCUCTRL_CHIPPN_PARTNUM_PINS_S = 3, /*!< PINS_S : Bit position for the pins field. value. */ + MCUCTRL_CHIPPN_PARTNUM_TEMP_S = 1, /*!< TEMP_S : Bit position for the temperature field. value. */ + MCUCTRL_CHIPPN_PARTNUM_QUAL_S = 0, /*!< QUAL_S : Bit position for the qualified field. value. */ +} MCUCTRL_CHIPPN_PARTNUM_Enum; + +/* ======================================================== CHIPID0 ======================================================== */ +/* ============================================ MCUCTRL CHIPID0 CHIPID0 [0..31] ============================================ */ +typedef enum { /*!< MCUCTRL_CHIPID0_CHIPID0 */ + MCUCTRL_CHIPID0_CHIPID0_APOLLO3 = 0, /*!< APOLLO3 : Apollo3 CHIPID0. value. */ +} MCUCTRL_CHIPID0_CHIPID0_Enum; + +/* ======================================================== CHIPID1 ======================================================== */ +/* ============================================ MCUCTRL CHIPID1 CHIPID1 [0..31] ============================================ */ +typedef enum { /*!< MCUCTRL_CHIPID1_CHIPID1 */ + MCUCTRL_CHIPID1_CHIPID1_APOLLO3 = 0, /*!< APOLLO3 : Apollo3 CHIPID1. value. */ +} MCUCTRL_CHIPID1_CHIPID1_Enum; + +/* ======================================================== CHIPREV ======================================================== */ +/* ============================================= MCUCTRL CHIPREV REVMAJ [4..7] ============================================= */ +typedef enum { /*!< MCUCTRL_CHIPREV_REVMAJ */ + MCUCTRL_CHIPREV_REVMAJ_A = 1, /*!< A : Apollo3 revision A value. */ +} MCUCTRL_CHIPREV_REVMAJ_Enum; + +/* ============================================= MCUCTRL CHIPREV REVMIN [0..3] ============================================= */ +typedef enum { /*!< MCUCTRL_CHIPREV_REVMIN */ + MCUCTRL_CHIPREV_REVMIN_REV1 = 2, /*!< REV1 : Apollo3 minor rev 1. value. */ + MCUCTRL_CHIPREV_REVMIN_REV0 = 1, /*!< REV0 : Apollo3 minor rev 0. Minor revision value, succeeding + minor revisions will increment from this value. value. */ +} MCUCTRL_CHIPREV_REVMIN_Enum; + +/* ======================================================= VENDORID ======================================================== */ +/* =========================================== MCUCTRL VENDORID VENDORID [0..31] =========================================== */ +typedef enum { /*!< MCUCTRL_VENDORID_VENDORID */ + MCUCTRL_VENDORID_VENDORID_AMBIQ = 1095582289,/*!< AMBIQ : Ambiq Vendor ID value. */ +} MCUCTRL_VENDORID_VENDORID_Enum; + +/* ========================================================== SKU ========================================================== */ +/* ===================================================== FEATUREENABLE ===================================================== */ +/* ======================================== MCUCTRL FEATUREENABLE BURSTAVAIL [6..6] ======================================== */ +typedef enum { /*!< MCUCTRL_FEATUREENABLE_BURSTAVAIL */ + MCUCTRL_FEATUREENABLE_BURSTAVAIL_AVAIL = 1, /*!< AVAIL : Burst functionality available value. */ + MCUCTRL_FEATUREENABLE_BURSTAVAIL_NOTAVAIL = 0,/*!< NOTAVAIL : Burst functionality not available value. */ +} MCUCTRL_FEATUREENABLE_BURSTAVAIL_Enum; + +/* ========================================= MCUCTRL FEATUREENABLE BURSTREQ [4..4] ========================================= */ +typedef enum { /*!< MCUCTRL_FEATUREENABLE_BURSTREQ */ + MCUCTRL_FEATUREENABLE_BURSTREQ_EN = 1, /*!< EN : Enable the Burst functionality value. */ + MCUCTRL_FEATUREENABLE_BURSTREQ_DIS = 0, /*!< DIS : Disable the Burst functionality value. */ +} MCUCTRL_FEATUREENABLE_BURSTREQ_Enum; + +/* ========================================= MCUCTRL FEATUREENABLE BLEAVAIL [2..2] ========================================= */ +typedef enum { /*!< MCUCTRL_FEATUREENABLE_BLEAVAIL */ + MCUCTRL_FEATUREENABLE_BLEAVAIL_AVAIL = 1, /*!< AVAIL : BLE functionality available value. */ + MCUCTRL_FEATUREENABLE_BLEAVAIL_NOTAVAIL = 0, /*!< NOTAVAIL : BLE functionality not available value. */ +} MCUCTRL_FEATUREENABLE_BLEAVAIL_Enum; + +/* ========================================== MCUCTRL FEATUREENABLE BLEREQ [0..0] ========================================== */ +typedef enum { /*!< MCUCTRL_FEATUREENABLE_BLEREQ */ + MCUCTRL_FEATUREENABLE_BLEREQ_EN = 1, /*!< EN : Enable the BLE functionality value. */ + MCUCTRL_FEATUREENABLE_BLEREQ_DIS = 0, /*!< DIS : Disable the BLE functionality value. */ +} MCUCTRL_FEATUREENABLE_BLEREQ_Enum; + +/* ======================================================= DEBUGGER ======================================================== */ +/* ======================================================== BODCTRL ======================================================== */ +/* ======================================================= ADCPWRDLY ======================================================= */ +/* ======================================================== ADCCAL ========================================================= */ +/* ========================================== MCUCTRL ADCCAL ADCCALIBRATED [1..1] ========================================== */ +typedef enum { /*!< MCUCTRL_ADCCAL_ADCCALIBRATED */ + MCUCTRL_ADCCAL_ADCCALIBRATED_FALSE = 0, /*!< FALSE : ADC is not calibrated value. */ + MCUCTRL_ADCCAL_ADCCALIBRATED_TRUE = 1, /*!< TRUE : ADC is calibrated value. */ +} MCUCTRL_ADCCAL_ADCCALIBRATED_Enum; + +/* =========================================== MCUCTRL ADCCAL CALONPWRUP [0..0] ============================================ */ +typedef enum { /*!< MCUCTRL_ADCCAL_CALONPWRUP */ + MCUCTRL_ADCCAL_CALONPWRUP_DIS = 0, /*!< DIS : Disable automatic calibration on initial power up value. */ + MCUCTRL_ADCCAL_CALONPWRUP_EN = 1, /*!< EN : Enable automatic calibration on initial power up value. */ +} MCUCTRL_ADCCAL_CALONPWRUP_Enum; + +/* ====================================================== ADCBATTLOAD ====================================================== */ +/* ========================================== MCUCTRL ADCBATTLOAD BATTLOAD [0..0] ========================================== */ +typedef enum { /*!< MCUCTRL_ADCBATTLOAD_BATTLOAD */ + MCUCTRL_ADCBATTLOAD_BATTLOAD_DIS = 0, /*!< DIS : Battery load is disconnected value. */ + MCUCTRL_ADCBATTLOAD_BATTLOAD_EN = 1, /*!< EN : Battery load is enabled value. */ +} MCUCTRL_ADCBATTLOAD_BATTLOAD_Enum; + +/* ======================================================== ADCTRIM ======================================================== */ +/* ====================================================== ADCREFCOMP ======================================================= */ +/* ======================================================= XTALCTRL ======================================================== */ +/* ========================================== MCUCTRL XTALCTRL PWDBODXTAL [5..5] =========================================== */ +typedef enum { /*!< MCUCTRL_XTALCTRL_PWDBODXTAL */ + MCUCTRL_XTALCTRL_PWDBODXTAL_PWRUPBOD = 0, /*!< PWRUPBOD : Power up xtal on BOD value. */ + MCUCTRL_XTALCTRL_PWDBODXTAL_PWRDNBOD = 1, /*!< PWRDNBOD : Power down XTAL on BOD. value. */ +} MCUCTRL_XTALCTRL_PWDBODXTAL_Enum; + +/* ========================================= MCUCTRL XTALCTRL PDNBCMPRXTAL [4..4] ========================================== */ +typedef enum { /*!< MCUCTRL_XTALCTRL_PDNBCMPRXTAL */ + MCUCTRL_XTALCTRL_PDNBCMPRXTAL_PWRUPCOMP = 1, /*!< PWRUPCOMP : Power up XTAL oscillator comparator. value. */ + MCUCTRL_XTALCTRL_PDNBCMPRXTAL_PWRDNCOMP = 0, /*!< PWRDNCOMP : Power down XTAL oscillator comparator. value. */ +} MCUCTRL_XTALCTRL_PDNBCMPRXTAL_Enum; + +/* ========================================= MCUCTRL XTALCTRL PDNBCOREXTAL [3..3] ========================================== */ +typedef enum { /*!< MCUCTRL_XTALCTRL_PDNBCOREXTAL */ + MCUCTRL_XTALCTRL_PDNBCOREXTAL_PWRUPCORE = 1, /*!< PWRUPCORE : Power up XTAL oscillator core. value. */ + MCUCTRL_XTALCTRL_PDNBCOREXTAL_PWRDNCORE = 0, /*!< PWRDNCORE : Power down XTAL oscillator core. value. */ +} MCUCTRL_XTALCTRL_PDNBCOREXTAL_Enum; + +/* ========================================== MCUCTRL XTALCTRL BYPCMPRXTAL [2..2] ========================================== */ +typedef enum { /*!< MCUCTRL_XTALCTRL_BYPCMPRXTAL */ + MCUCTRL_XTALCTRL_BYPCMPRXTAL_USECOMP = 0, /*!< USECOMP : Use the XTAL oscillator comparator. value. */ + MCUCTRL_XTALCTRL_BYPCMPRXTAL_BYPCOMP = 1, /*!< BYPCOMP : Bypass the XTAL oscillator comparator. value. */ +} MCUCTRL_XTALCTRL_BYPCMPRXTAL_Enum; + +/* ========================================= MCUCTRL XTALCTRL FDBKDSBLXTAL [1..1] ========================================== */ +typedef enum { /*!< MCUCTRL_XTALCTRL_FDBKDSBLXTAL */ + MCUCTRL_XTALCTRL_FDBKDSBLXTAL_EN = 0, /*!< EN : Enable XTAL oscillator comparator. value. */ + MCUCTRL_XTALCTRL_FDBKDSBLXTAL_DIS = 1, /*!< DIS : Disable XTAL oscillator comparator. value. */ +} MCUCTRL_XTALCTRL_FDBKDSBLXTAL_Enum; + +/* ============================================ MCUCTRL XTALCTRL XTALSWE [0..0] ============================================ */ +typedef enum { /*!< MCUCTRL_XTALCTRL_XTALSWE */ + MCUCTRL_XTALCTRL_XTALSWE_OVERRIDE_DIS = 0, /*!< OVERRIDE_DIS : XTAL Software Override Disable. value. */ + MCUCTRL_XTALCTRL_XTALSWE_OVERRIDE_EN = 1, /*!< OVERRIDE_EN : XTAL Software Override Enable. value. */ +} MCUCTRL_XTALCTRL_XTALSWE_Enum; + +/* ====================================================== XTALGENCTRL ====================================================== */ +/* ========================================== MCUCTRL XTALGENCTRL ACWARMUP [0..1] ========================================== */ +typedef enum { /*!< MCUCTRL_XTALGENCTRL_ACWARMUP */ + MCUCTRL_XTALGENCTRL_ACWARMUP_SEC1 = 0, /*!< SEC1 : Warmup period of 1-2 seconds value. */ + MCUCTRL_XTALGENCTRL_ACWARMUP_SEC2 = 1, /*!< SEC2 : Warmup period of 2-4 seconds value. */ + MCUCTRL_XTALGENCTRL_ACWARMUP_SEC4 = 2, /*!< SEC4 : Warmup period of 4-8 seconds value. */ + MCUCTRL_XTALGENCTRL_ACWARMUP_SEC8 = 3, /*!< SEC8 : Warmup period of 8-16 seconds value. */ +} MCUCTRL_XTALGENCTRL_ACWARMUP_Enum; + +/* ======================================================= MISCCTRL ======================================================== */ +/* ====================================================== BOOTLOADER ======================================================= */ +/* ======================================= MCUCTRL BOOTLOADER SECBOOTONRST [30..31] ======================================== */ +typedef enum { /*!< MCUCTRL_BOOTLOADER_SECBOOTONRST */ + MCUCTRL_BOOTLOADER_SECBOOTONRST_DISABLED = 0, /*!< DISABLED : Secure boot disabled value. */ + MCUCTRL_BOOTLOADER_SECBOOTONRST_ENABLED = 1, /*!< ENABLED : Secure boot enabled value. */ + MCUCTRL_BOOTLOADER_SECBOOTONRST_ERROR = 2, /*!< ERROR : Error in secure boot configuration value. */ +} MCUCTRL_BOOTLOADER_SECBOOTONRST_Enum; + +/* ========================================== MCUCTRL BOOTLOADER SECBOOT [28..29] ========================================== */ +typedef enum { /*!< MCUCTRL_BOOTLOADER_SECBOOT */ + MCUCTRL_BOOTLOADER_SECBOOT_DISABLED = 0, /*!< DISABLED : Secure boot disabled value. */ + MCUCTRL_BOOTLOADER_SECBOOT_ENABLED = 1, /*!< ENABLED : Secure boot enabled value. */ + MCUCTRL_BOOTLOADER_SECBOOT_ERROR = 2, /*!< ERROR : Error in secure boot configuration value. */ +} MCUCTRL_BOOTLOADER_SECBOOT_Enum; + +/* ====================================== MCUCTRL BOOTLOADER SECBOOTFEATURE [26..27] ======================================= */ +typedef enum { /*!< MCUCTRL_BOOTLOADER_SECBOOTFEATURE */ + MCUCTRL_BOOTLOADER_SECBOOTFEATURE_DISABLED = 0,/*!< DISABLED : Secure boot disabled value. */ + MCUCTRL_BOOTLOADER_SECBOOTFEATURE_ENABLED = 1,/*!< ENABLED : Secure boot enabled value. */ + MCUCTRL_BOOTLOADER_SECBOOTFEATURE_ERROR = 2, /*!< ERROR : Error in secure boot configuration value. */ +} MCUCTRL_BOOTLOADER_SECBOOTFEATURE_Enum; + +/* ========================================== MCUCTRL BOOTLOADER PROTLOCK [2..2] =========================================== */ +typedef enum { /*!< MCUCTRL_BOOTLOADER_PROTLOCK */ + MCUCTRL_BOOTLOADER_PROTLOCK_LOCK = 1, /*!< LOCK : Enable the secure boot lock value. */ +} MCUCTRL_BOOTLOADER_PROTLOCK_Enum; + +/* =========================================== MCUCTRL BOOTLOADER SBLOCK [1..1] ============================================ */ +typedef enum { /*!< MCUCTRL_BOOTLOADER_SBLOCK */ + MCUCTRL_BOOTLOADER_SBLOCK_LOCK = 1, /*!< LOCK : Enable the secure boot lock value. */ +} MCUCTRL_BOOTLOADER_SBLOCK_Enum; + +/* ======================================== MCUCTRL BOOTLOADER BOOTLOADERLOW [0..0] ======================================== */ +typedef enum { /*!< MCUCTRL_BOOTLOADER_BOOTLOADERLOW */ + MCUCTRL_BOOTLOADER_BOOTLOADERLOW_ADDR0 = 1, /*!< ADDR0 : Bootloader code at 0x00000000. value. */ +} MCUCTRL_BOOTLOADER_BOOTLOADERLOW_Enum; + +/* ====================================================== SHADOWVALID ====================================================== */ +/* ======================================== MCUCTRL SHADOWVALID INFO0_VALID [2..2] ========================================= */ +typedef enum { /*!< MCUCTRL_SHADOWVALID_INFO0_VALID */ + MCUCTRL_SHADOWVALID_INFO0_VALID_VALID = 1, /*!< VALID : Flash info0 (customer) space contains valid data. value. */ +} MCUCTRL_SHADOWVALID_INFO0_VALID_Enum; + +/* ========================================== MCUCTRL SHADOWVALID BLDSLEEP [1..1] ========================================== */ +typedef enum { /*!< MCUCTRL_SHADOWVALID_BLDSLEEP */ + MCUCTRL_SHADOWVALID_BLDSLEEP_DEEPSLEEP = 1, /*!< DEEPSLEEP : Bootloader will go to deep sleep if no flash image + loaded value. */ +} MCUCTRL_SHADOWVALID_BLDSLEEP_Enum; + +/* =========================================== MCUCTRL SHADOWVALID VALID [0..0] ============================================ */ +typedef enum { /*!< MCUCTRL_SHADOWVALID_VALID */ + MCUCTRL_SHADOWVALID_VALID_VALID = 1, /*!< VALID : Flash information space contains valid data. value. */ +} MCUCTRL_SHADOWVALID_VALID_Enum; + +/* ======================================================= SCRATCH0 ======================================================== */ +/* ======================================================= SCRATCH1 ======================================================== */ +/* ==================================================== ICODEFAULTADDR ===================================================== */ +/* ==================================================== DCODEFAULTADDR ===================================================== */ +/* ===================================================== SYSFAULTADDR ====================================================== */ +/* ====================================================== FAULTSTATUS ====================================================== */ +/* ========================================== MCUCTRL FAULTSTATUS SYSFAULT [2..2] ========================================== */ +typedef enum { /*!< MCUCTRL_FAULTSTATUS_SYSFAULT */ + MCUCTRL_FAULTSTATUS_SYSFAULT_NOFAULT = 0, /*!< NOFAULT : No bus fault has been detected. value. */ + MCUCTRL_FAULTSTATUS_SYSFAULT_FAULT = 1, /*!< FAULT : Bus fault detected. value. */ +} MCUCTRL_FAULTSTATUS_SYSFAULT_Enum; + +/* ========================================= MCUCTRL FAULTSTATUS DCODEFAULT [1..1] ========================================= */ +typedef enum { /*!< MCUCTRL_FAULTSTATUS_DCODEFAULT */ + MCUCTRL_FAULTSTATUS_DCODEFAULT_NOFAULT = 0, /*!< NOFAULT : No DCODE fault has been detected. value. */ + MCUCTRL_FAULTSTATUS_DCODEFAULT_FAULT = 1, /*!< FAULT : DCODE fault detected. value. */ +} MCUCTRL_FAULTSTATUS_DCODEFAULT_Enum; + +/* ========================================= MCUCTRL FAULTSTATUS ICODEFAULT [0..0] ========================================= */ +typedef enum { /*!< MCUCTRL_FAULTSTATUS_ICODEFAULT */ + MCUCTRL_FAULTSTATUS_ICODEFAULT_NOFAULT = 0, /*!< NOFAULT : No ICODE fault has been detected. value. */ + MCUCTRL_FAULTSTATUS_ICODEFAULT_FAULT = 1, /*!< FAULT : ICODE fault detected. value. */ +} MCUCTRL_FAULTSTATUS_ICODEFAULT_Enum; + +/* ==================================================== FAULTCAPTUREEN ===================================================== */ +/* ===================================== MCUCTRL FAULTCAPTUREEN FAULTCAPTUREEN [0..0] ====================================== */ +typedef enum { /*!< MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN */ + MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_DIS = 0,/*!< DIS : Disable fault capture. value. */ + MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_EN = 1, /*!< EN : Enable fault capture. value. */ +} MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_Enum; + +/* ========================================================= DBGR1 ========================================================= */ +/* ========================================================= DBGR2 ========================================================= */ +/* ======================================================= PMUENABLE ======================================================= */ +/* ============================================ MCUCTRL PMUENABLE ENABLE [0..0] ============================================ */ +typedef enum { /*!< MCUCTRL_PMUENABLE_ENABLE */ + MCUCTRL_PMUENABLE_ENABLE_DIS = 0, /*!< DIS : Disable MCU power management. value. */ + MCUCTRL_PMUENABLE_ENABLE_EN = 1, /*!< EN : Enable MCU power management. value. */ +} MCUCTRL_PMUENABLE_ENABLE_Enum; + +/* ======================================================= TPIUCTRL ======================================================== */ +/* ============================================ MCUCTRL TPIUCTRL CLKSEL [8..10] ============================================ */ +typedef enum { /*!< MCUCTRL_TPIUCTRL_CLKSEL */ + MCUCTRL_TPIUCTRL_CLKSEL_LOWPWR = 0, /*!< LOWPWR : Low power state. value. */ + MCUCTRL_TPIUCTRL_CLKSEL_HFRCDIV2 = 1, /*!< HFRCDIV2 : Selects HFRC divided by 2 as the source TPIU clk + value. */ + MCUCTRL_TPIUCTRL_CLKSEL_HFRCDIV8 = 2, /*!< HFRCDIV8 : Selects HFRC divided by 8 as the source TPIU clk + value. */ + MCUCTRL_TPIUCTRL_CLKSEL_HFRCDIV16 = 3, /*!< HFRCDIV16 : Selects HFRC divided by 16 as the source TPIU clk + value. */ + MCUCTRL_TPIUCTRL_CLKSEL_HFRCDIV32 = 4, /*!< HFRCDIV32 : Selects HFRC divided by 32 as the source TPIU clk + value. */ +} MCUCTRL_TPIUCTRL_CLKSEL_Enum; + +/* ============================================ MCUCTRL TPIUCTRL ENABLE [0..0] ============================================= */ +typedef enum { /*!< MCUCTRL_TPIUCTRL_ENABLE */ + MCUCTRL_TPIUCTRL_ENABLE_DIS = 0, /*!< DIS : Disable the TPIU. value. */ + MCUCTRL_TPIUCTRL_ENABLE_EN = 1, /*!< EN : Enable the TPIU. value. */ +} MCUCTRL_TPIUCTRL_ENABLE_Enum; + +/* ====================================================== OTAPOINTER ======================================================= */ +/* ====================================================== APBDMACTRL ======================================================= */ +/* ========================================= MCUCTRL APBDMACTRL DECODEABORT [1..1] ========================================= */ +typedef enum { /*!< MCUCTRL_APBDMACTRL_DECODEABORT */ + MCUCTRL_APBDMACTRL_DECODEABORT_DISABLE = 0, /*!< DISABLE : Bus operations to powered down peripherals are quietly + discarded value. */ + MCUCTRL_APBDMACTRL_DECODEABORT_ENABLE = 1, /*!< ENABLE : Bus operations to powered down peripherals result in + a bus fault. value. */ +} MCUCTRL_APBDMACTRL_DECODEABORT_Enum; + +/* ========================================= MCUCTRL APBDMACTRL DMA_ENABLE [0..0] ========================================== */ +typedef enum { /*!< MCUCTRL_APBDMACTRL_DMA_ENABLE */ + MCUCTRL_APBDMACTRL_DMA_ENABLE_DISABLE = 0, /*!< DISABLE : DMA operations disabled value. */ + MCUCTRL_APBDMACTRL_DMA_ENABLE_ENABLE = 1, /*!< ENABLE : DMA operations enabled value. */ +} MCUCTRL_APBDMACTRL_DMA_ENABLE_Enum; + +/* ======================================================= SRAMMODE ======================================================== */ +/* ====================================================== KEXTCLKSEL ======================================================= */ +/* ========================================= MCUCTRL KEXTCLKSEL KEXTCLKSEL [0..31] ========================================= */ +typedef enum { /*!< MCUCTRL_KEXTCLKSEL_KEXTCLKSEL */ + MCUCTRL_KEXTCLKSEL_KEXTCLKSEL_Key = 83, /*!< Key : Key value. */ +} MCUCTRL_KEXTCLKSEL_KEXTCLKSEL_Enum; + +/* ======================================================= SIMOBUCK4 ======================================================= */ +/* ======================================================= BLEBUCK2 ======================================================== */ +/* ====================================================== FLASHWPROT0 ====================================================== */ +/* ====================================================== FLASHWPROT1 ====================================================== */ +/* ====================================================== FLASHRPROT0 ====================================================== */ +/* ====================================================== FLASHRPROT1 ====================================================== */ +/* ================================================= DMASRAMWRITEPROTECT0 ================================================== */ +/* ================================================= DMASRAMWRITEPROTECT1 ================================================== */ +/* ================================================== DMASRAMREADPROTECT0 ================================================== */ +/* ================================================== DMASRAMREADPROTECT1 ================================================== */ + + +/* =========================================================================================================================== */ +/* ================ MSPI ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= CTRL ========================================================== */ +/* ========================================================== CFG ========================================================== */ +/* ================================================ MSPI CFG CPOL [17..17] ================================================= */ +typedef enum { /*!< MSPI_CFG_CPOL */ + MSPI_CFG_CPOL_LOW = 0, /*!< LOW : Clock inactive state is low. value. */ + MSPI_CFG_CPOL_HIGH = 1, /*!< HIGH : Clock inactive state is high. value. */ +} MSPI_CFG_CPOL_Enum; + +/* ================================================ MSPI CFG CPHA [16..16] ================================================= */ +typedef enum { /*!< MSPI_CFG_CPHA */ + MSPI_CFG_CPHA_MIDDLE = 0, /*!< MIDDLE : Clock toggles in middle of data bit. value. */ + MSPI_CFG_CPHA_START = 1, /*!< START : Clock toggles at start of data bit. value. */ +} MSPI_CFG_CPHA_Enum; + +/* ================================================ MSPI CFG DEVCFG [0..3] ================================================= */ +typedef enum { /*!< MSPI_CFG_DEVCFG */ + MSPI_CFG_DEVCFG_SERIAL0 = 1, /*!< SERIAL0 : Single bit SPI flash on chip select 0 value. */ + MSPI_CFG_DEVCFG_SERIAL1 = 2, /*!< SERIAL1 : Single bit SPI flash on chip select 1 value. */ + MSPI_CFG_DEVCFG_DUAL0 = 5, /*!< DUAL0 : Dual SPI flash on chip select 0 value. */ + MSPI_CFG_DEVCFG_DUAL1 = 6, /*!< DUAL1 : Dual bit SPI flash on chip select 1 value. */ + MSPI_CFG_DEVCFG_QUAD0 = 9, /*!< QUAD0 : Quad SPI flash on chip select 0 value. */ + MSPI_CFG_DEVCFG_QUAD1 = 10, /*!< QUAD1 : Quad SPI flash on chip select 1 value. */ + MSPI_CFG_DEVCFG_OCTAL0 = 13, /*!< OCTAL0 : Octal SPI flash on chip select 0 value. */ + MSPI_CFG_DEVCFG_OCTAL1 = 14, /*!< OCTAL1 : Octal SPI flash on chip select 1 value. */ + MSPI_CFG_DEVCFG_QUADPAIRED = 15, /*!< QUADPAIRED : Dual Quad SPI flash on chip selects 0/1. value. */ + MSPI_CFG_DEVCFG_QUADPAIRED_SERIAL = 3, /*!< QUADPAIRED_SERIAL : Dual Quad SPI flash on chip selects 0/1, + but transmit in serial mode for initialization operations + value. */ +} MSPI_CFG_DEVCFG_Enum; + +/* ========================================================= ADDR ========================================================== */ +/* ========================================================= INSTR ========================================================= */ +/* ======================================================== TXFIFO ========================================================= */ +/* ======================================================== RXFIFO ========================================================= */ +/* ======================================================= TXENTRIES ======================================================= */ +/* ======================================================= RXENTRIES ======================================================= */ +/* ======================================================= THRESHOLD ======================================================= */ +/* ======================================================== MSPICFG ======================================================== */ +/* ============================================== MSPI MSPICFG CLKDIV [8..13] ============================================== */ +typedef enum { /*!< MSPI_MSPICFG_CLKDIV */ + MSPI_MSPICFG_CLKDIV_CLK24 = 2, /*!< CLK24 : 24 MHz MSPI clock value. */ + MSPI_MSPICFG_CLKDIV_CLK12 = 4, /*!< CLK12 : 12 MHz MSPI clock value. */ + MSPI_MSPICFG_CLKDIV_CLK6 = 8, /*!< CLK6 : 6 MHz MSPI clock value. */ + MSPI_MSPICFG_CLKDIV_CLK3 = 16, /*!< CLK3 : 3 MHz MSPI clock value. */ + MSPI_MSPICFG_CLKDIV_CLK1_5 = 32, /*!< CLK1_5 : 1.5 MHz MSPI clock value. */ +} MSPI_MSPICFG_CLKDIV_Enum; + +/* ============================================== MSPI MSPICFG IOMSEL [4..6] =============================================== */ +typedef enum { /*!< MSPI_MSPICFG_IOMSEL */ + MSPI_MSPICFG_IOMSEL_IOM0 = 0, /*!< IOM0 : ERROR: desc VALUE MISSING value. */ + MSPI_MSPICFG_IOMSEL_IOM1 = 1, /*!< IOM1 : ERROR: desc VALUE MISSING value. */ + MSPI_MSPICFG_IOMSEL_IOM2 = 2, /*!< IOM2 : ERROR: desc VALUE MISSING value. */ + MSPI_MSPICFG_IOMSEL_IOM3 = 3, /*!< IOM3 : ERROR: desc VALUE MISSING value. */ + MSPI_MSPICFG_IOMSEL_IOM4 = 4, /*!< IOM4 : ERROR: desc VALUE MISSING value. */ + MSPI_MSPICFG_IOMSEL_IOM5 = 5, /*!< IOM5 : ERROR: desc VALUE MISSING value. */ + MSPI_MSPICFG_IOMSEL_DISABLED = 7, /*!< DISABLED : No IOM selected. Signals always zero. value. */ +} MSPI_MSPICFG_IOMSEL_Enum; + +/* =============================================== MSPI MSPICFG TXNEG [3..3] =============================================== */ +typedef enum { /*!< MSPI_MSPICFG_TXNEG */ + MSPI_MSPICFG_TXNEG_NORMAL = 0, /*!< NORMAL : TX launched from posedge internal clock value. */ + MSPI_MSPICFG_TXNEG_NEGEDGE = 1, /*!< NEGEDGE : TX data launched from negedge of internal clock value. */ +} MSPI_MSPICFG_TXNEG_Enum; + +/* =============================================== MSPI MSPICFG RXNEG [2..2] =============================================== */ +typedef enum { /*!< MSPI_MSPICFG_RXNEG */ + MSPI_MSPICFG_RXNEG_NORMAL = 0, /*!< NORMAL : RX data sampled on posedge of internal clock value. */ + MSPI_MSPICFG_RXNEG_NEGEDGE = 1, /*!< NEGEDGE : RX data sampled on negedge of internal clock value. */ +} MSPI_MSPICFG_RXNEG_Enum; + +/* =============================================== MSPI MSPICFG RXCAP [1..1] =============================================== */ +typedef enum { /*!< MSPI_MSPICFG_RXCAP */ + MSPI_MSPICFG_RXCAP_NORMAL = 0, /*!< NORMAL : RX Capture phase aligns with CPHA setting value. */ + MSPI_MSPICFG_RXCAP_DELAY = 1, /*!< DELAY : RX Capture phase is delayed from CPHA setting by one + clock edge value. */ +} MSPI_MSPICFG_RXCAP_Enum; + +/* ============================================== MSPI MSPICFG APBCLK [0..0] =============================================== */ +typedef enum { /*!< MSPI_MSPICFG_APBCLK */ + MSPI_MSPICFG_APBCLK_DIS = 0, /*!< DIS : Disable continuous clock. value. */ + MSPI_MSPICFG_APBCLK_EN = 1, /*!< EN : Enable continuous clock. value. */ +} MSPI_MSPICFG_APBCLK_Enum; + +/* ======================================================== PADCFG ========================================================= */ +/* ======================================================= PADOUTEN ======================================================== */ +/* ============================================== MSPI PADOUTEN OUTEN [0..8] =============================================== */ +typedef enum { /*!< MSPI_PADOUTEN_OUTEN */ + MSPI_PADOUTEN_OUTEN_QUAD0 = 271, /*!< QUAD0 : Quad0 (4 data + 1 clock) value. */ + MSPI_PADOUTEN_OUTEN_QUAD1 = 496, /*!< QUAD1 : Quad1 (4 data + 1 clock) value. */ + MSPI_PADOUTEN_OUTEN_OCTAL = 511, /*!< OCTAL : Octal (8 data + 1 clock) value. */ + MSPI_PADOUTEN_OUTEN_SERIAL0 = 259, /*!< SERIAL0 : Serial (2 data + 1 clock) value. */ +} MSPI_PADOUTEN_OUTEN_Enum; + +/* ========================================================= FLASH ========================================================= */ +/* =============================================== MSPI FLASH XIPACK [2..3] ================================================ */ +typedef enum { /*!< MSPI_FLASH_XIPACK */ + MSPI_FLASH_XIPACK_NOACK = 0, /*!< NOACK : No acknowledege sent. Data IOs are tristated the first + turnaround cycle value. */ + MSPI_FLASH_XIPACK_ACK = 2, /*!< ACK : Positive acknowledege sent. Data IOs are driven to 0 the + first turnaround cycle to acknowledge XIP mode value. */ + MSPI_FLASH_XIPACK_TERMINATE = 3, /*!< TERMINATE : Negative acknowledege sent. Data IOs are driven + to 1 the first turnaround cycle to terminate XIP mode. + XIPSENDI should be reenabled for the next transfer value. */ +} MSPI_FLASH_XIPACK_Enum; + +/* ====================================================== SCRAMBLING ======================================================= */ +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ +/* ======================================================== DMACFG ========================================================= */ +/* =============================================== MSPI DMACFG DMAPRI [3..4] =============================================== */ +typedef enum { /*!< MSPI_DMACFG_DMAPRI */ + MSPI_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ + MSPI_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ + MSPI_DMACFG_DMAPRI_AUTO = 2, /*!< AUTO : Auto Priority (priority raised once TX FIFO empties or + RX FIFO fills) value. */ +} MSPI_DMACFG_DMAPRI_Enum; + +/* =============================================== MSPI DMACFG DMADIR [2..2] =============================================== */ +typedef enum { /*!< MSPI_DMACFG_DMADIR */ + MSPI_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction value. */ + MSPI_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction value. */ +} MSPI_DMACFG_DMADIR_Enum; + +/* =============================================== MSPI DMACFG DMAEN [0..1] ================================================ */ +typedef enum { /*!< MSPI_DMACFG_DMAEN */ + MSPI_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ + MSPI_DMACFG_DMAEN_EN = 3, /*!< EN : Enable HW controlled DMA Function to manage DMA to flash + devices. HW will automatically handle issuance of instruction/address + bytes based on settings in the FLASH register. value. */ +} MSPI_DMACFG_DMAEN_Enum; + +/* ======================================================== DMASTAT ======================================================== */ +/* ====================================================== DMATARGADDR ====================================================== */ +/* ====================================================== DMADEVADDR ======================================================= */ +/* ====================================================== DMATOTCOUNT ====================================================== */ +/* ======================================================= DMABCOUNT ======================================================= */ +/* ======================================================= DMATHRESH ======================================================= */ +/* ========================================================= CQCFG ========================================================= */ +/* ================================================ MSPI CQCFG CQPRI [1..1] ================================================ */ +typedef enum { /*!< MSPI_CQCFG_CQPRI */ + MSPI_CQCFG_CQPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ + MSPI_CQCFG_CQPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ +} MSPI_CQCFG_CQPRI_Enum; + +/* ================================================ MSPI CQCFG CQEN [0..0] ================================================= */ +typedef enum { /*!< MSPI_CQCFG_CQEN */ + MSPI_CQCFG_CQEN_DIS = 0, /*!< DIS : Disable CQ Function value. */ + MSPI_CQCFG_CQEN_EN = 1, /*!< EN : Enable CQ Function value. */ +} MSPI_CQCFG_CQEN_Enum; + +/* ======================================================== CQADDR ========================================================= */ +/* ======================================================== CQSTAT ========================================================= */ +/* ======================================================== CQFLAGS ======================================================== */ +/* ============================================= MSPI CQFLAGS CQFLAGS [0..15] ============================================== */ +typedef enum { /*!< MSPI_CQFLAGS_CQFLAGS */ + MSPI_CQFLAGS_CQFLAGS_STOP = 32768, /*!< STOP : CQ Stop Flag. When set, CQ processing will complete. + value. */ + MSPI_CQFLAGS_CQFLAGS_CQIDX = 16384, /*!< CQIDX : CQ Index Pointers (CURIDX/ENDIDX) match. value. */ + MSPI_CQFLAGS_CQFLAGS_DMACPL = 2048, /*!< DMACPL : DMA Complete Status (hardwired DMACPL bit in DMASTAT) + value. */ + MSPI_CQFLAGS_CQFLAGS_CMDCPL = 1024, /*!< CMDCPL : PIO Operation completed (STATUS bit in CTRL register) + value. */ + MSPI_CQFLAGS_CQFLAGS_IOM1READY = 512, /*!< IOM1READY : IOM Buffer 1 Ready Status (from selected IOM). This + status is the result of XOR'ing the IOM0START with the + incoming status from the IOM. When high, MSPI can send + to the buffer. value. */ + MSPI_CQFLAGS_CQFLAGS_IOM0READY = 256, /*!< IOM0READY : IOM Buffer 0 Ready Status (from selected IOM). This + status is the result of XOR'ing the IOM0START with the + incoming status from the IOM. When high, MSPI can send + to the buffer. value. */ + MSPI_CQFLAGS_CQFLAGS_SWFLAG7 = 128, /*!< SWFLAG7 : Software flag 7. Can be used by software to start/pause + operations value. */ + MSPI_CQFLAGS_CQFLAGS_SWFLAG6 = 64, /*!< SWFLAG6 : Software flag 6. Can be used by software to start/pause + operatoins value. */ + MSPI_CQFLAGS_CQFLAGS_SWFLAG5 = 32, /*!< SWFLAG5 : Software flag 5. Can be used by software to start/pause + operations value. */ + MSPI_CQFLAGS_CQFLAGS_SWFLAG4 = 16, /*!< SWFLAG4 : Software flag 4. Can be used by software to start/pause + operatoins value. */ + MSPI_CQFLAGS_CQFLAGS_SWFLAG3 = 8, /*!< SWFLAG3 : Software flag 3. Can be used by software to start/pause + operations value. */ + MSPI_CQFLAGS_CQFLAGS_SWFLAG2 = 4, /*!< SWFLAG2 : Software flag 2. Can be used by software to start/pause + operatoins value. */ + MSPI_CQFLAGS_CQFLAGS_SWFLAG1 = 2, /*!< SWFLAG1 : Software flag 1. Can be used by software to start/pause + operations value. */ + MSPI_CQFLAGS_CQFLAGS_SWFLAG0 = 1, /*!< SWFLAG0 : Software flag 0. Can be used by software to start/pause + operatoins value. */ +} MSPI_CQFLAGS_CQFLAGS_Enum; + +/* ====================================================== CQSETCLEAR ======================================================= */ +/* ======================================================== CQPAUSE ======================================================== */ +/* ============================================== MSPI CQPAUSE CQMASK [0..15] ============================================== */ +typedef enum { /*!< MSPI_CQPAUSE_CQMASK */ + MSPI_CQPAUSE_CQMASK_STOP = 32768, /*!< STOP : CQ Stop Flag. When set, CQ processing will complete. + value. */ + MSPI_CQPAUSE_CQMASK_CQIDX = 16384, /*!< CQIDX : CQ Index Pointers (CURIDX/ENDIDX) match. value. */ + MSPI_CQPAUSE_CQMASK_DMACPL = 2048, /*!< DMACPL : DMA Complete Status (hardwired DMACPL bit in DMASTAT) + value. */ + MSPI_CQPAUSE_CQMASK_CMDCPL = 1024, /*!< CMDCPL : PIO Operation completed (STATUS bit in CTRL register) + value. */ + MSPI_CQPAUSE_CQMASK_IOM1READY = 512, /*!< IOM1READY : IOM Buffer 1 Ready Status (from selected IOM). This + status is the result of XOR'ing the IOM0START with the + incoming status from the IOM. When high, MSPI can send + to the buffer. value. */ + MSPI_CQPAUSE_CQMASK_IOM0READY = 256, /*!< IOM0READY : IOM Buffer 0 Ready Status (from selected IOM). This + status is the result of XOR'ing the IOM0START with the + incoming status from the IOM. When high, MSPI can send + to the buffer. value. */ + MSPI_CQPAUSE_CQMASK_SWFLAG7 = 128, /*!< SWFLAG7 : Software flag 7. Can be used by software to start/pause + operations value. */ + MSPI_CQPAUSE_CQMASK_SWFLAG6 = 64, /*!< SWFLAG6 : Software flag 6. Can be used by software to start/pause + operatoins value. */ + MSPI_CQPAUSE_CQMASK_SWFLAG5 = 32, /*!< SWFLAG5 : Software flag 5. Can be used by software to start/pause + operations value. */ + MSPI_CQPAUSE_CQMASK_SWFLAG4 = 16, /*!< SWFLAG4 : Software flag 4. Can be used by software to start/pause + operatoins value. */ + MSPI_CQPAUSE_CQMASK_SWFLAG3 = 8, /*!< SWFLAG3 : Software flag 3. Can be used by software to start/pause + operations value. */ + MSPI_CQPAUSE_CQMASK_SWFLAG2 = 4, /*!< SWFLAG2 : Software flag 2. Can be used by software to start/pause + operatoins value. */ + MSPI_CQPAUSE_CQMASK_SWFLAG1 = 2, /*!< SWFLAG1 : Software flag 1. Can be used by software to start/pause + operations value. */ + MSPI_CQPAUSE_CQMASK_SWFLAG0 = 1, /*!< SWFLAG0 : Software flag 0. Can be used by software to start/pause + operatoins value. */ +} MSPI_CQPAUSE_CQMASK_Enum; + +/* ======================================================= CQCURIDX ======================================================== */ +/* ======================================================= CQENDIDX ======================================================== */ + + +/* =========================================================================================================================== */ +/* ================ PDM ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= PCFG ========================================================== */ +/* =============================================== PDM PCFG LRSWAP [31..31] ================================================ */ +typedef enum { /*!< PDM_PCFG_LRSWAP */ + PDM_PCFG_LRSWAP_EN = 1, /*!< EN : Swap left and right channels (FIFO Read RIGHT_LEFT). value. */ + PDM_PCFG_LRSWAP_NOSWAP = 0, /*!< NOSWAP : No channel swapping (IFO Read LEFT_RIGHT). value. */ +} PDM_PCFG_LRSWAP_Enum; + +/* ============================================== PDM PCFG PGARIGHT [26..30] =============================================== */ +typedef enum { /*!< PDM_PCFG_PGARIGHT */ + PDM_PCFG_PGARIGHT_P405DB = 31, /*!< P405DB : 40.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P390DB = 30, /*!< P390DB : 39.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P375DB = 29, /*!< P375DB : 37.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P360DB = 28, /*!< P360DB : 36.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P345DB = 27, /*!< P345DB : 34.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P330DB = 26, /*!< P330DB : 33.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P315DB = 25, /*!< P315DB : 31.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P300DB = 24, /*!< P300DB : 30.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P285DB = 23, /*!< P285DB : 28.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P270DB = 22, /*!< P270DB : 27.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P255DB = 21, /*!< P255DB : 25.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P240DB = 20, /*!< P240DB : 24.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P225DB = 19, /*!< P225DB : 22.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P210DB = 18, /*!< P210DB : 21.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P195DB = 17, /*!< P195DB : 19.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P180DB = 16, /*!< P180DB : 18.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P165DB = 15, /*!< P165DB : 16.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P150DB = 14, /*!< P150DB : 15.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P135DB = 13, /*!< P135DB : 13.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P120DB = 12, /*!< P120DB : 12.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P105DB = 11, /*!< P105DB : 10.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P90DB = 10, /*!< P90DB : 9.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P75DB = 9, /*!< P75DB : 7.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P60DB = 8, /*!< P60DB : 6.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P45DB = 7, /*!< P45DB : 4.5 db gain. value. */ + PDM_PCFG_PGARIGHT_P30DB = 6, /*!< P30DB : 3.0 db gain. value. */ + PDM_PCFG_PGARIGHT_P15DB = 5, /*!< P15DB : 1.5 db gain. value. */ + PDM_PCFG_PGARIGHT_0DB = 4, /*!< 0DB : 0.0 db gain. value. */ + PDM_PCFG_PGARIGHT_M15DB = 3, /*!< M15DB : -1.5 db gain. value. */ + PDM_PCFG_PGARIGHT_M300DB = 2, /*!< M300DB : -3.0 db gain. value. */ + PDM_PCFG_PGARIGHT_M45DB = 1, /*!< M45DB : -4.5 db gain. value. */ + PDM_PCFG_PGARIGHT_M60DB = 0, /*!< M60DB : -6.0 db gain. value. */ +} PDM_PCFG_PGARIGHT_Enum; + +/* =============================================== PDM PCFG PGALEFT [21..25] =============================================== */ +typedef enum { /*!< PDM_PCFG_PGALEFT */ + PDM_PCFG_PGALEFT_P405DB = 31, /*!< P405DB : 40.5 db gain. value. */ + PDM_PCFG_PGALEFT_P390DB = 30, /*!< P390DB : 39.0 db gain. value. */ + PDM_PCFG_PGALEFT_P375DB = 29, /*!< P375DB : 37.5 db gain. value. */ + PDM_PCFG_PGALEFT_P360DB = 28, /*!< P360DB : 36.0 db gain. value. */ + PDM_PCFG_PGALEFT_P345DB = 27, /*!< P345DB : 34.5 db gain. value. */ + PDM_PCFG_PGALEFT_P330DB = 26, /*!< P330DB : 33.0 db gain. value. */ + PDM_PCFG_PGALEFT_P315DB = 25, /*!< P315DB : 31.5 db gain. value. */ + PDM_PCFG_PGALEFT_P300DB = 24, /*!< P300DB : 30.0 db gain. value. */ + PDM_PCFG_PGALEFT_P285DB = 23, /*!< P285DB : 28.5 db gain. value. */ + PDM_PCFG_PGALEFT_P270DB = 22, /*!< P270DB : 27.0 db gain. value. */ + PDM_PCFG_PGALEFT_P255DB = 21, /*!< P255DB : 25.5 db gain. value. */ + PDM_PCFG_PGALEFT_P240DB = 20, /*!< P240DB : 24.0 db gain. value. */ + PDM_PCFG_PGALEFT_P225DB = 19, /*!< P225DB : 22.5 db gain. value. */ + PDM_PCFG_PGALEFT_P210DB = 18, /*!< P210DB : 21.0 db gain. value. */ + PDM_PCFG_PGALEFT_P195DB = 17, /*!< P195DB : 19.5 db gain. value. */ + PDM_PCFG_PGALEFT_P180DB = 16, /*!< P180DB : 18.0 db gain. value. */ + PDM_PCFG_PGALEFT_P165DB = 15, /*!< P165DB : 16.5 db gain. value. */ + PDM_PCFG_PGALEFT_P150DB = 14, /*!< P150DB : 15.0 db gain. value. */ + PDM_PCFG_PGALEFT_P135DB = 13, /*!< P135DB : 13.5 db gain. value. */ + PDM_PCFG_PGALEFT_P120DB = 12, /*!< P120DB : 12.0 db gain. value. */ + PDM_PCFG_PGALEFT_P105DB = 11, /*!< P105DB : 10.5 db gain. value. */ + PDM_PCFG_PGALEFT_P90DB = 10, /*!< P90DB : 9.0 db gain. value. */ + PDM_PCFG_PGALEFT_P75DB = 9, /*!< P75DB : 7.5 db gain. value. */ + PDM_PCFG_PGALEFT_P60DB = 8, /*!< P60DB : 6.0 db gain. value. */ + PDM_PCFG_PGALEFT_P45DB = 7, /*!< P45DB : 4.5 db gain. value. */ + PDM_PCFG_PGALEFT_P30DB = 6, /*!< P30DB : 3.0 db gain. value. */ + PDM_PCFG_PGALEFT_P15DB = 5, /*!< P15DB : 1.5 db gain. value. */ + PDM_PCFG_PGALEFT_0DB = 4, /*!< 0DB : 0.0 db gain. value. */ + PDM_PCFG_PGALEFT_M15DB = 3, /*!< M15DB : -1.5 db gain. value. */ + PDM_PCFG_PGALEFT_M300DB = 2, /*!< M300DB : -3.0 db gain. value. */ + PDM_PCFG_PGALEFT_M45DB = 1, /*!< M45DB : -4.5 db gain. value. */ + PDM_PCFG_PGALEFT_M60DB = 0, /*!< M60DB : -6.0 db gain. value. */ +} PDM_PCFG_PGALEFT_Enum; + +/* =============================================== PDM PCFG MCLKDIV [17..18] =============================================== */ +typedef enum { /*!< PDM_PCFG_MCLKDIV */ + PDM_PCFG_MCLKDIV_MCKDIV4 = 3, /*!< MCKDIV4 : Divide input clock by 4 value. */ + PDM_PCFG_MCLKDIV_MCKDIV3 = 2, /*!< MCKDIV3 : Divide input clock by 3 value. */ + PDM_PCFG_MCLKDIV_MCKDIV2 = 1, /*!< MCKDIV2 : Divide input clock by 2 value. */ + PDM_PCFG_MCLKDIV_MCKDIV1 = 0, /*!< MCKDIV1 : Divide input clock by 1 value. */ +} PDM_PCFG_MCLKDIV_Enum; + +/* ================================================ PDM PCFG ADCHPD [9..9] ================================================= */ +typedef enum { /*!< PDM_PCFG_ADCHPD */ + PDM_PCFG_ADCHPD_EN = 1, /*!< EN : Enable high pass filter. value. */ + PDM_PCFG_ADCHPD_DIS = 0, /*!< DIS : Disable high pass filter. value. */ +} PDM_PCFG_ADCHPD_Enum; + +/* =============================================== PDM PCFG SOFTMUTE [1..1] ================================================ */ +typedef enum { /*!< PDM_PCFG_SOFTMUTE */ + PDM_PCFG_SOFTMUTE_EN = 1, /*!< EN : Enable Soft Mute. value. */ + PDM_PCFG_SOFTMUTE_DIS = 0, /*!< DIS : Disable Soft Mute. value. */ +} PDM_PCFG_SOFTMUTE_Enum; + +/* =============================================== PDM PCFG PDMCOREEN [0..0] =============================================== */ +typedef enum { /*!< PDM_PCFG_PDMCOREEN */ + PDM_PCFG_PDMCOREEN_EN = 1, /*!< EN : Enable Data Streaming. value. */ + PDM_PCFG_PDMCOREEN_DIS = 0, /*!< DIS : Disable Data Streaming. value. */ +} PDM_PCFG_PDMCOREEN_Enum; + +/* ========================================================= VCFG ========================================================== */ +/* =============================================== PDM VCFG IOCLKEN [31..31] =============================================== */ +typedef enum { /*!< PDM_VCFG_IOCLKEN */ + PDM_VCFG_IOCLKEN_DIS = 0, /*!< DIS : Disable FIFO read. value. */ + PDM_VCFG_IOCLKEN_EN = 1, /*!< EN : Enable FIFO read. value. */ +} PDM_VCFG_IOCLKEN_Enum; + +/* ================================================ PDM VCFG RSTB [30..30] ================================================= */ +typedef enum { /*!< PDM_VCFG_RSTB */ + PDM_VCFG_RSTB_RESET = 0, /*!< RESET : Reset the core. value. */ + PDM_VCFG_RSTB_NORM = 1, /*!< NORM : Enable the core. value. */ +} PDM_VCFG_RSTB_Enum; + +/* ============================================== PDM VCFG PDMCLKSEL [27..29] ============================================== */ +typedef enum { /*!< PDM_VCFG_PDMCLKSEL */ + PDM_VCFG_PDMCLKSEL_DISABLE = 0, /*!< DISABLE : Static value. value. */ + PDM_VCFG_PDMCLKSEL_12MHz = 1, /*!< 12MHz : PDM clock is 12 MHz. value. */ + PDM_VCFG_PDMCLKSEL_6MHz = 2, /*!< 6MHz : PDM clock is 6 MHz. value. */ + PDM_VCFG_PDMCLKSEL_3MHz = 3, /*!< 3MHz : PDM clock is 3 MHz. value. */ + PDM_VCFG_PDMCLKSEL_1_5MHz = 4, /*!< 1_5MHz : PDM clock is 1.5 MHz. value. */ + PDM_VCFG_PDMCLKSEL_750KHz = 5, /*!< 750KHz : PDM clock is 750 KHz. value. */ + PDM_VCFG_PDMCLKSEL_375KHz = 6, /*!< 375KHz : PDM clock is 375 KHz. value. */ + PDM_VCFG_PDMCLKSEL_187KHz = 7, /*!< 187KHz : PDM clock is 187.5 KHz. value. */ +} PDM_VCFG_PDMCLKSEL_Enum; + +/* ============================================== PDM VCFG PDMCLKEN [26..26] =============================================== */ +typedef enum { /*!< PDM_VCFG_PDMCLKEN */ + PDM_VCFG_PDMCLKEN_DIS = 0, /*!< DIS : Disable serial clock. value. */ + PDM_VCFG_PDMCLKEN_EN = 1, /*!< EN : Enable serial clock. value. */ +} PDM_VCFG_PDMCLKEN_Enum; + +/* ================================================ PDM VCFG I2SEN [20..20] ================================================ */ +typedef enum { /*!< PDM_VCFG_I2SEN */ + PDM_VCFG_I2SEN_DIS = 0, /*!< DIS : Disable I2S interface. value. */ + PDM_VCFG_I2SEN_EN = 1, /*!< EN : Enable I2S interface. value. */ +} PDM_VCFG_I2SEN_Enum; + +/* =============================================== PDM VCFG BCLKINV [19..19] =============================================== */ +typedef enum { /*!< PDM_VCFG_BCLKINV */ + PDM_VCFG_BCLKINV_INV = 0, /*!< INV : BCLK inverted. value. */ + PDM_VCFG_BCLKINV_NORM = 1, /*!< NORM : BCLK not inverted. value. */ +} PDM_VCFG_BCLKINV_Enum; + +/* ============================================== PDM VCFG DMICKDEL [17..17] =============================================== */ +typedef enum { /*!< PDM_VCFG_DMICKDEL */ + PDM_VCFG_DMICKDEL_0CYC = 0, /*!< 0CYC : No delay. value. */ + PDM_VCFG_DMICKDEL_1CYC = 1, /*!< 1CYC : 1 cycle delay. value. */ +} PDM_VCFG_DMICKDEL_Enum; + +/* ================================================ PDM VCFG SELAP [16..16] ================================================ */ +typedef enum { /*!< PDM_VCFG_SELAP */ + PDM_VCFG_SELAP_I2S = 1, /*!< I2S : Clock source from I2S BCLK. value. */ + PDM_VCFG_SELAP_INTERNAL = 0, /*!< INTERNAL : Clock source from internal clock generator. value. */ +} PDM_VCFG_SELAP_Enum; + +/* ================================================ PDM VCFG PCMPACK [8..8] ================================================ */ +typedef enum { /*!< PDM_VCFG_PCMPACK */ + PDM_VCFG_PCMPACK_DIS = 0, /*!< DIS : Disable PCM packing. value. */ + PDM_VCFG_PCMPACK_EN = 1, /*!< EN : Enable PCM packing. value. */ +} PDM_VCFG_PCMPACK_Enum; + +/* ================================================= PDM VCFG CHSET [3..4] ================================================= */ +typedef enum { /*!< PDM_VCFG_CHSET */ + PDM_VCFG_CHSET_DIS = 0, /*!< DIS : Channel disabled. value. */ + PDM_VCFG_CHSET_LEFT = 1, /*!< LEFT : Mono left channel. value. */ + PDM_VCFG_CHSET_RIGHT = 2, /*!< RIGHT : Mono right channel. value. */ + PDM_VCFG_CHSET_STEREO = 3, /*!< STEREO : Stereo channels. value. */ +} PDM_VCFG_CHSET_Enum; + +/* ======================================================= VOICESTAT ======================================================= */ +/* ======================================================= FIFOREAD ======================================================== */ +/* ======================================================= FIFOFLUSH ======================================================= */ +/* ======================================================== FIFOTHR ======================================================== */ +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ +/* ======================================================= DMATRIGEN ======================================================= */ +/* ====================================================== DMATRIGSTAT ====================================================== */ +/* ======================================================== DMACFG ========================================================= */ +/* =============================================== PDM DMACFG DMAPRI [8..8] ================================================ */ +typedef enum { /*!< PDM_DMACFG_DMAPRI */ + PDM_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ + PDM_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ +} PDM_DMACFG_DMAPRI_Enum; + +/* =============================================== PDM DMACFG DMADIR [2..2] ================================================ */ +typedef enum { /*!< PDM_DMACFG_DMADIR */ + PDM_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction. THe PDM module + will only DMA to memory. value. */ + PDM_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction. Not available for PDM + module value. */ +} PDM_DMACFG_DMADIR_Enum; + +/* ================================================ PDM DMACFG DMAEN [0..0] ================================================ */ +typedef enum { /*!< PDM_DMACFG_DMAEN */ + PDM_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ + PDM_DMACFG_DMAEN_EN = 1, /*!< EN : Enable DMA Function value. */ +} PDM_DMACFG_DMAEN_Enum; + +/* ====================================================== DMATOTCOUNT ====================================================== */ +/* ====================================================== DMATARGADDR ====================================================== */ +/* ======================================================== DMASTAT ======================================================== */ + + +/* =========================================================================================================================== */ +/* ================ PWRCTRL ================ */ +/* =========================================================================================================================== */ + +/* ======================================================= SUPPLYSRC ======================================================= */ +/* ========================================== PWRCTRL SUPPLYSRC BLEBUCKEN [0..0] =========================================== */ +typedef enum { /*!< PWRCTRL_SUPPLYSRC_BLEBUCKEN */ + PWRCTRL_SUPPLYSRC_BLEBUCKEN_EN = 1, /*!< EN : Enable the BLE Buck. value. */ + PWRCTRL_SUPPLYSRC_BLEBUCKEN_DIS = 0, /*!< DIS : Disable the BLE Buck. value. */ +} PWRCTRL_SUPPLYSRC_BLEBUCKEN_Enum; + +/* ===================================================== SUPPLYSTATUS ====================================================== */ +/* ========================================= PWRCTRL SUPPLYSTATUS BLEBUCKON [1..1] ========================================= */ +typedef enum { /*!< PWRCTRL_SUPPLYSTATUS_BLEBUCKON */ + PWRCTRL_SUPPLYSTATUS_BLEBUCKON_LDO = 0, /*!< LDO : Indicates the the LDO is supplying the BLE/Burst power + domain value. */ + PWRCTRL_SUPPLYSTATUS_BLEBUCKON_BUCK = 1, /*!< BUCK : Indicates the the Buck is supplying the BLE/Burst power + domain value. */ +} PWRCTRL_SUPPLYSTATUS_BLEBUCKON_Enum; + +/* ======================================== PWRCTRL SUPPLYSTATUS SIMOBUCKON [0..0] ========================================= */ +typedef enum { /*!< PWRCTRL_SUPPLYSTATUS_SIMOBUCKON */ + PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_OFF = 0, /*!< OFF : Indicates the the SIMO Buck is OFF. value. */ + PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_ON = 1, /*!< ON : Indicates the the SIMO Buck is ON. value. */ +} PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_Enum; + +/* ======================================================= DEVPWREN ======================================================== */ +/* =========================================== PWRCTRL DEVPWREN PWRBLEL [13..13] =========================================== */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRBLEL */ + PWRCTRL_DEVPWREN_PWRBLEL_EN = 1, /*!< EN : Power up BLE controller value. */ + PWRCTRL_DEVPWREN_PWRBLEL_DIS = 0, /*!< DIS : Power down BLE controller value. */ +} PWRCTRL_DEVPWREN_PWRBLEL_Enum; + +/* =========================================== PWRCTRL DEVPWREN PWRPDM [12..12] ============================================ */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRPDM */ + PWRCTRL_DEVPWREN_PWRPDM_EN = 1, /*!< EN : Power up PDM value. */ + PWRCTRL_DEVPWREN_PWRPDM_DIS = 0, /*!< DIS : Power down PDM value. */ +} PWRCTRL_DEVPWREN_PWRPDM_Enum; + +/* =========================================== PWRCTRL DEVPWREN PWRMSPI [11..11] =========================================== */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRMSPI */ + PWRCTRL_DEVPWREN_PWRMSPI_EN = 1, /*!< EN : Power up MSPI value. */ + PWRCTRL_DEVPWREN_PWRMSPI_DIS = 0, /*!< DIS : Power down MSPI value. */ +} PWRCTRL_DEVPWREN_PWRMSPI_Enum; + +/* ========================================== PWRCTRL DEVPWREN PWRSCARD [10..10] =========================================== */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRSCARD */ + PWRCTRL_DEVPWREN_PWRSCARD_EN = 1, /*!< EN : Power up SCARD value. */ + PWRCTRL_DEVPWREN_PWRSCARD_DIS = 0, /*!< DIS : Power down SCARD value. */ +} PWRCTRL_DEVPWREN_PWRSCARD_Enum; + +/* ============================================ PWRCTRL DEVPWREN PWRADC [9..9] ============================================= */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRADC */ + PWRCTRL_DEVPWREN_PWRADC_EN = 1, /*!< EN : Power up ADC value. */ + PWRCTRL_DEVPWREN_PWRADC_DIS = 0, /*!< DIS : Power Down ADC value. */ +} PWRCTRL_DEVPWREN_PWRADC_Enum; + +/* =========================================== PWRCTRL DEVPWREN PWRUART1 [8..8] ============================================ */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRUART1 */ + PWRCTRL_DEVPWREN_PWRUART1_EN = 1, /*!< EN : Power up UART 1 value. */ + PWRCTRL_DEVPWREN_PWRUART1_DIS = 0, /*!< DIS : Power down UART 1 value. */ +} PWRCTRL_DEVPWREN_PWRUART1_Enum; + +/* =========================================== PWRCTRL DEVPWREN PWRUART0 [7..7] ============================================ */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRUART0 */ + PWRCTRL_DEVPWREN_PWRUART0_EN = 1, /*!< EN : Power up UART 0 value. */ + PWRCTRL_DEVPWREN_PWRUART0_DIS = 0, /*!< DIS : Power down UART 0 value. */ +} PWRCTRL_DEVPWREN_PWRUART0_Enum; + +/* ============================================ PWRCTRL DEVPWREN PWRIOM5 [6..6] ============================================ */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM5 */ + PWRCTRL_DEVPWREN_PWRIOM5_EN = 1, /*!< EN : Power up IO Master 5 value. */ + PWRCTRL_DEVPWREN_PWRIOM5_DIS = 0, /*!< DIS : Power down IO Master 5 value. */ +} PWRCTRL_DEVPWREN_PWRIOM5_Enum; + +/* ============================================ PWRCTRL DEVPWREN PWRIOM4 [5..5] ============================================ */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM4 */ + PWRCTRL_DEVPWREN_PWRIOM4_EN = 1, /*!< EN : Power up IO Master 4 value. */ + PWRCTRL_DEVPWREN_PWRIOM4_DIS = 0, /*!< DIS : Power down IO Master 4 value. */ +} PWRCTRL_DEVPWREN_PWRIOM4_Enum; + +/* ============================================ PWRCTRL DEVPWREN PWRIOM3 [4..4] ============================================ */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM3 */ + PWRCTRL_DEVPWREN_PWRIOM3_EN = 1, /*!< EN : Power up IO Master 3 value. */ + PWRCTRL_DEVPWREN_PWRIOM3_DIS = 0, /*!< DIS : Power down IO Master 3 value. */ +} PWRCTRL_DEVPWREN_PWRIOM3_Enum; + +/* ============================================ PWRCTRL DEVPWREN PWRIOM2 [3..3] ============================================ */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM2 */ + PWRCTRL_DEVPWREN_PWRIOM2_EN = 1, /*!< EN : Power up IO Master 2 value. */ + PWRCTRL_DEVPWREN_PWRIOM2_DIS = 0, /*!< DIS : Power down IO Master 2 value. */ +} PWRCTRL_DEVPWREN_PWRIOM2_Enum; + +/* ============================================ PWRCTRL DEVPWREN PWRIOM1 [2..2] ============================================ */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM1 */ + PWRCTRL_DEVPWREN_PWRIOM1_EN = 1, /*!< EN : Power up IO Master 1 value. */ + PWRCTRL_DEVPWREN_PWRIOM1_DIS = 0, /*!< DIS : Power down IO Master 1 value. */ +} PWRCTRL_DEVPWREN_PWRIOM1_Enum; + +/* ============================================ PWRCTRL DEVPWREN PWRIOM0 [1..1] ============================================ */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM0 */ + PWRCTRL_DEVPWREN_PWRIOM0_EN = 1, /*!< EN : Power up IO Master 0 value. */ + PWRCTRL_DEVPWREN_PWRIOM0_DIS = 0, /*!< DIS : Power down IO Master 0 value. */ +} PWRCTRL_DEVPWREN_PWRIOM0_Enum; + +/* ============================================ PWRCTRL DEVPWREN PWRIOS [0..0] ============================================= */ +typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOS */ + PWRCTRL_DEVPWREN_PWRIOS_EN = 1, /*!< EN : Power up IO slave value. */ + PWRCTRL_DEVPWREN_PWRIOS_DIS = 0, /*!< DIS : Power down IO slave value. */ +} PWRCTRL_DEVPWREN_PWRIOS_Enum; + +/* ===================================================== MEMPWDINSLEEP ===================================================== */ +/* ====================================== PWRCTRL MEMPWDINSLEEP CACHEPWDSLP [31..31] ======================================= */ +typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP */ + PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_EN = 1, /*!< EN : Power down cache in deep sleep value. */ + PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_DIS = 0, /*!< DIS : Retain cache in deep sleep value. */ +} PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_Enum; + +/* ====================================== PWRCTRL MEMPWDINSLEEP FLASH1PWDSLP [14..14] ====================================== */ +typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP */ + PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_EN = 1, /*!< EN : Flash1 is powered down during deepsleep value. */ + PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_DIS = 0, /*!< DIS : Flash1 is kept powered on during deepsleep value. */ +} PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_Enum; + +/* ====================================== PWRCTRL MEMPWDINSLEEP FLASH0PWDSLP [13..13] ====================================== */ +typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP */ + PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_EN = 1, /*!< EN : Flash0 is powered down during deepsleep value. */ + PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_DIS = 0, /*!< DIS : Flash0 is kept powered on during deepsleep value. */ +} PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_Enum; + +/* ======================================= PWRCTRL MEMPWDINSLEEP SRAMPWDSLP [3..12] ======================================== */ +typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_NONE = 0, /*!< NONE : All banks retained value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP0 = 1, /*!< GROUP0 : SRAM GROUP0 powered down (64KB-96KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP1 = 2, /*!< GROUP1 : SRAM GROUP1 powered down (96KB-128KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP2 = 4, /*!< GROUP2 : SRAM GROUP2 powered down (128KB-160KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP3 = 8, /*!< GROUP3 : SRAM GROUP3 powered down (160KB-192KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP4 = 16, /*!< GROUP4 : SRAM GROUP4 powered down (192KB-224KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP5 = 32, /*!< GROUP5 : SRAM GROUP5 powered down (224KB-256KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP6 = 64, /*!< GROUP6 : SRAM GROUP6 powered down (256KB-288KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP7 = 128,/*!< GROUP7 : SRAM GROUP7 powered down (288KB-320KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP8 = 256,/*!< GROUP8 : SRAM GROUP8 powered down (320KB-352KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP9 = 512,/*!< GROUP9 : SRAM GROUP9 powered down (352KB-384KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_SRAM64K = 3, /*!< SRAM64K : Powerdown lower 64k SRAM (64KB-128KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_SRAM128K = 15,/*!< SRAM128K : Powerdown lower 128k SRAM (64KB-192KB) value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER32K = 1022,/*!< ALLBUTLOWER32K : All SRAM banks but lower 32k powered down (96KB-384KB). + value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER64K = 1020,/*!< ALLBUTLOWER64K : All banks but lower 64k powered down. value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER128K = 1008,/*!< ALLBUTLOWER128K : All banks but lower 128k powered down. value. */ + PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALL = 1023, /*!< ALL : All banks powered down. value. */ +} PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_Enum; + +/* ======================================== PWRCTRL MEMPWDINSLEEP DTCMPWDSLP [0..2] ======================================== */ +typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP */ + PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_NONE = 0, /*!< NONE : All DTCM retained value. */ + PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_GROUP0DTCM0 = 1,/*!< GROUP0DTCM0 : Group0_DTCM0 powered down in deep sleep (0KB-8KB) + value. */ + PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_GROUP0DTCM1 = 2,/*!< GROUP0DTCM1 : Group0_DTCM1 powered down in deep sleep (8KB-32KB) + value. */ + PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_GROUP0 = 3, /*!< GROUP0 : Both DTCMs in group0 are powered down in deep sleep + (0KB-32KB) value. */ + PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_ALLBUTGROUP0DTCM0 = 6,/*!< ALLBUTGROUP0DTCM0 : Group1 and Group0_DTCM1 are powered down + in deep sleep (8KB-64KB) value. */ + PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_GROUP1 = 4, /*!< GROUP1 : Group1 DTCM powered down in deep sleep (32KB-64KB) + value. */ + PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_ALL = 7, /*!< ALL : All DTCMs powered down in deep sleep (0KB-64KB) value. */ +} PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_Enum; + +/* ======================================================= MEMPWREN ======================================================== */ +/* =========================================== PWRCTRL MEMPWREN CACHEB2 [31..31] =========================================== */ +typedef enum { /*!< PWRCTRL_MEMPWREN_CACHEB2 */ + PWRCTRL_MEMPWREN_CACHEB2_EN = 1, /*!< EN : Power up Cache Bank 2 value. */ + PWRCTRL_MEMPWREN_CACHEB2_DIS = 0, /*!< DIS : Power down Cache Bank 2 value. */ +} PWRCTRL_MEMPWREN_CACHEB2_Enum; + +/* =========================================== PWRCTRL MEMPWREN CACHEB0 [30..30] =========================================== */ +typedef enum { /*!< PWRCTRL_MEMPWREN_CACHEB0 */ + PWRCTRL_MEMPWREN_CACHEB0_EN = 1, /*!< EN : Power up Cache Bank 0 value. */ + PWRCTRL_MEMPWREN_CACHEB0_DIS = 0, /*!< DIS : Power down Cache Bank 0 value. */ +} PWRCTRL_MEMPWREN_CACHEB0_Enum; + +/* =========================================== PWRCTRL MEMPWREN FLASH1 [14..14] ============================================ */ +typedef enum { /*!< PWRCTRL_MEMPWREN_FLASH1 */ + PWRCTRL_MEMPWREN_FLASH1_EN = 1, /*!< EN : Power up Flash1 value. */ + PWRCTRL_MEMPWREN_FLASH1_DIS = 0, /*!< DIS : Power down Flash1 value. */ +} PWRCTRL_MEMPWREN_FLASH1_Enum; + +/* =========================================== PWRCTRL MEMPWREN FLASH0 [13..13] ============================================ */ +typedef enum { /*!< PWRCTRL_MEMPWREN_FLASH0 */ + PWRCTRL_MEMPWREN_FLASH0_EN = 1, /*!< EN : Power up Flash0 value. */ + PWRCTRL_MEMPWREN_FLASH0_DIS = 0, /*!< DIS : Power down Flash0 value. */ +} PWRCTRL_MEMPWREN_FLASH0_Enum; + +/* ============================================= PWRCTRL MEMPWREN SRAM [3..12] ============================================= */ +typedef enum { /*!< PWRCTRL_MEMPWREN_SRAM */ + PWRCTRL_MEMPWREN_SRAM_NONE = 0, /*!< NONE : Do not power ON any of the SRAM banks value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP0 = 1, /*!< GROUP0 : Power ON only SRAM group0 (0KB-32KB) value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP1 = 2, /*!< GROUP1 : Power ON only SRAM group1 (32KB-64KB) value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP2 = 4, /*!< GROUP2 : Power ON only SRAM group2 (64KB-96KB) value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP3 = 8, /*!< GROUP3 : Power ON only SRAM group3 (96KB-128KB) value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP4 = 16, /*!< GROUP4 : Power ON only SRAM group4 (128KB-160KB) value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP5 = 32, /*!< GROUP5 : Power ON only SRAM group5 (160KB-192KB) value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP6 = 64, /*!< GROUP6 : Power ON only SRAM group6 (192KB-224KB) value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP7 = 128, /*!< GROUP7 : Power ON only SRAM group7 (224KB-256KB) value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP8 = 256, /*!< GROUP8 : Power ON only SRAM group8 (256KB-288KB) value. */ + PWRCTRL_MEMPWREN_SRAM_GROUP9 = 512, /*!< GROUP9 : Power ON only SRAM group9 (288KB-320KB) value. */ + PWRCTRL_MEMPWREN_SRAM_SRAM64K = 3, /*!< SRAM64K : Power ON only lower 64k value. */ + PWRCTRL_MEMPWREN_SRAM_SRAM128K = 15, /*!< SRAM128K : Power ON only lower 128k value. */ + PWRCTRL_MEMPWREN_SRAM_SRAM256K = 255, /*!< SRAM256K : Power ON only lower 256k value. */ + PWRCTRL_MEMPWREN_SRAM_ALL = 1023, /*!< ALL : All SRAM banks (320K) powered ON value. */ +} PWRCTRL_MEMPWREN_SRAM_Enum; + +/* ============================================= PWRCTRL MEMPWREN DTCM [0..2] ============================================== */ +typedef enum { /*!< PWRCTRL_MEMPWREN_DTCM */ + PWRCTRL_MEMPWREN_DTCM_NONE = 0, /*!< NONE : Do not enable power to any DTCMs value. */ + PWRCTRL_MEMPWREN_DTCM_GROUP0DTCM0 = 1, /*!< GROUP0DTCM0 : Power ON only GROUP0_DTCM0 value. */ + PWRCTRL_MEMPWREN_DTCM_GROUP0DTCM1 = 2, /*!< GROUP0DTCM1 : Power ON only GROUP0_DTCM1 value. */ + PWRCTRL_MEMPWREN_DTCM_GROUP0 = 3, /*!< GROUP0 : Power ON only DTCMs in group0 value. */ + PWRCTRL_MEMPWREN_DTCM_GROUP1 = 4, /*!< GROUP1 : Power ON only DTCMs in group1 value. */ + PWRCTRL_MEMPWREN_DTCM_ALL = 7, /*!< ALL : Power ON all DTCMs value. */ +} PWRCTRL_MEMPWREN_DTCM_Enum; + +/* ===================================================== MEMPWRSTATUS ====================================================== */ +/* ===================================================== DEVPWRSTATUS ====================================================== */ +/* ======================================================= SRAMCTRL ======================================================== */ +/* ======================================== PWRCTRL SRAMCTRL SRAMLIGHTSLEEP [8..19] ======================================== */ +typedef enum { /*!< PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP */ + PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_ALL = 255, /*!< ALL : Enable LIGHT SLEEP for ALL SRAMs value. */ + PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_DIS = 0, /*!< DIS : Disables LIGHT SLEEP for ALL SRAMs value. */ +} PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_Enum; + +/* ======================================= PWRCTRL SRAMCTRL SRAMMASTERCLKGATE [2..2] ======================================= */ +typedef enum { /*!< PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE */ + PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_EN = 1, /*!< EN : Enable Master SRAM Clock Gate value. */ + PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_DIS = 0, /*!< DIS : Disables Master SRAM Clock Gating value. */ +} PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_Enum; + +/* ========================================== PWRCTRL SRAMCTRL SRAMCLKGATE [1..1] ========================================== */ +typedef enum { /*!< PWRCTRL_SRAMCTRL_SRAMCLKGATE */ + PWRCTRL_SRAMCTRL_SRAMCLKGATE_EN = 1, /*!< EN : Enable Individual SRAM Clock Gating value. */ + PWRCTRL_SRAMCTRL_SRAMCLKGATE_DIS = 0, /*!< DIS : Disables Individual SRAM Clock Gating value. */ +} PWRCTRL_SRAMCTRL_SRAMCLKGATE_Enum; + +/* ======================================================= ADCSTATUS ======================================================= */ +/* ========================================================= MISC ========================================================== */ +/* ============================================ PWRCTRL MISC MEMVRLPBLE [6..6] ============================================= */ +typedef enum { /*!< PWRCTRL_MISC_MEMVRLPBLE */ + PWRCTRL_MISC_MEMVRLPBLE_EN = 1, /*!< EN : Mem VR can go to lp mode even when BLE is powered on. value. */ + PWRCTRL_MISC_MEMVRLPBLE_DIS = 0, /*!< DIS : Mem VR will stay in active mode when BLE is powered on. + value. */ +} PWRCTRL_MISC_MEMVRLPBLE_Enum; + +/* =========================================== PWRCTRL MISC FORCEMEMVRADC [4..5] =========================================== */ +typedef enum { /*!< PWRCTRL_MISC_FORCEMEMVRADC */ + PWRCTRL_MISC_FORCEMEMVRADC_ACT = 2, /*!< ACT : In this mode if all the other domains but ADC are powered + down, mem VR will stay in ACT mode. value. */ + PWRCTRL_MISC_FORCEMEMVRADC_LP = 1, /*!< LP : In this mode if all the other domains but ADC are powered + down, mem VR will stay in LP mode. value. */ + PWRCTRL_MISC_FORCEMEMVRADC_DIS = 0, /*!< DIS : In this mode if all the other domains but ADC are powered + down, mem VR will duty cycle between active and LP modes + depending on ADC sampling. value. */ +} PWRCTRL_MISC_FORCEMEMVRADC_Enum; + +/* ============================================ PWRCTRL MISC SIMOBUCKEN [0..0] ============================================= */ +typedef enum { /*!< PWRCTRL_MISC_SIMOBUCKEN */ + PWRCTRL_MISC_SIMOBUCKEN_EN = 1, /*!< EN : Enable the SIMO Buck value. */ + PWRCTRL_MISC_SIMOBUCKEN_DIS = 0, /*!< DIS : Disable the SIMO Buck value. */ +} PWRCTRL_MISC_SIMOBUCKEN_Enum; + +/* ===================================================== DEVPWREVENTEN ===================================================== */ +/* ======================================= PWRCTRL DEVPWREVENTEN BURSTEVEN [31..31] ======================================== */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_BURSTEVEN */ + PWRCTRL_DEVPWREVENTEN_BURSTEVEN_EN = 1, /*!< EN : Enable BURST status event value. */ + PWRCTRL_DEVPWREVENTEN_BURSTEVEN_DIS = 0, /*!< DIS : Disable BURST status event value. */ +} PWRCTRL_DEVPWREVENTEN_BURSTEVEN_Enum; + +/* ==================================== PWRCTRL DEVPWREVENTEN BURSTFEATUREEVEN [30..30] ==================================== */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN */ + PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_EN = 1,/*!< EN : Enable BURSTFEATURE status event value. */ + PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_DIS = 0,/*!< DIS : Disable BURSTFEATURE status event value. */ +} PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_Enum; + +/* ===================================== PWRCTRL DEVPWREVENTEN BLEFEATUREEVEN [29..29] ===================================== */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN */ + PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_EN = 1, /*!< EN : Enable BLEFEATURE status event value. */ + PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_DIS = 0, /*!< DIS : Disable BLEFEATURE status event value. */ +} PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_Enum; + +/* ========================================= PWRCTRL DEVPWREVENTEN BLELEVEN [8..8] ========================================= */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_BLELEVEN */ + PWRCTRL_DEVPWREVENTEN_BLELEVEN_EN = 1, /*!< EN : Enable BLE power-on status event value. */ + PWRCTRL_DEVPWREVENTEN_BLELEVEN_DIS = 0, /*!< DIS : Disable BLE power-on status event value. */ +} PWRCTRL_DEVPWREVENTEN_BLELEVEN_Enum; + +/* ========================================= PWRCTRL DEVPWREVENTEN PDMEVEN [7..7] ========================================== */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_PDMEVEN */ + PWRCTRL_DEVPWREVENTEN_PDMEVEN_EN = 1, /*!< EN : Enable PDM power-on status event value. */ + PWRCTRL_DEVPWREVENTEN_PDMEVEN_DIS = 0, /*!< DIS : Disable PDM power-on status event value. */ +} PWRCTRL_DEVPWREVENTEN_PDMEVEN_Enum; + +/* ========================================= PWRCTRL DEVPWREVENTEN MSPIEVEN [6..6] ========================================= */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_MSPIEVEN */ + PWRCTRL_DEVPWREVENTEN_MSPIEVEN_EN = 1, /*!< EN : Enable MSPI power-on status event value. */ + PWRCTRL_DEVPWREVENTEN_MSPIEVEN_DIS = 0, /*!< DIS : Disable MSPI power-on status event value. */ +} PWRCTRL_DEVPWREVENTEN_MSPIEVEN_Enum; + +/* ========================================= PWRCTRL DEVPWREVENTEN ADCEVEN [5..5] ========================================== */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_ADCEVEN */ + PWRCTRL_DEVPWREVENTEN_ADCEVEN_EN = 1, /*!< EN : Enable ADC power-on status event value. */ + PWRCTRL_DEVPWREVENTEN_ADCEVEN_DIS = 0, /*!< DIS : Disable ADC power-on status event value. */ +} PWRCTRL_DEVPWREVENTEN_ADCEVEN_Enum; + +/* ========================================= PWRCTRL DEVPWREVENTEN HCPCEVEN [4..4] ========================================= */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_HCPCEVEN */ + PWRCTRL_DEVPWREVENTEN_HCPCEVEN_EN = 1, /*!< EN : Enable HCPC power-on status event value. */ + PWRCTRL_DEVPWREVENTEN_HCPCEVEN_DIS = 0, /*!< DIS : Disable HCPC power-on status event value. */ +} PWRCTRL_DEVPWREVENTEN_HCPCEVEN_Enum; + +/* ========================================= PWRCTRL DEVPWREVENTEN HCPBEVEN [3..3] ========================================= */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_HCPBEVEN */ + PWRCTRL_DEVPWREVENTEN_HCPBEVEN_EN = 1, /*!< EN : Enable HCPB power-on status event value. */ + PWRCTRL_DEVPWREVENTEN_HCPBEVEN_DIS = 0, /*!< DIS : Disable HCPB power-on status event value. */ +} PWRCTRL_DEVPWREVENTEN_HCPBEVEN_Enum; + +/* ========================================= PWRCTRL DEVPWREVENTEN HCPAEVEN [2..2] ========================================= */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_HCPAEVEN */ + PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN = 1, /*!< EN : Enable HCPA power-on status event value. */ + PWRCTRL_DEVPWREVENTEN_HCPAEVEN_DIS = 0, /*!< DIS : Disable HCPA power-on status event value. */ +} PWRCTRL_DEVPWREVENTEN_HCPAEVEN_Enum; + +/* ========================================= PWRCTRL DEVPWREVENTEN MCUHEVEN [1..1] ========================================= */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_MCUHEVEN */ + PWRCTRL_DEVPWREVENTEN_MCUHEVEN_EN = 1, /*!< EN : Enable MCHU power-on status event value. */ + PWRCTRL_DEVPWREVENTEN_MCUHEVEN_DIS = 0, /*!< DIS : Disable MCUH power-on status event value. */ +} PWRCTRL_DEVPWREVENTEN_MCUHEVEN_Enum; + +/* ========================================= PWRCTRL DEVPWREVENTEN MCULEVEN [0..0] ========================================= */ +typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_MCULEVEN */ + PWRCTRL_DEVPWREVENTEN_MCULEVEN_EN = 1, /*!< EN : Enable MCUL power-on status event value. */ + PWRCTRL_DEVPWREVENTEN_MCULEVEN_DIS = 0, /*!< DIS : Disable MCUL power-on status event value. */ +} PWRCTRL_DEVPWREVENTEN_MCULEVEN_Enum; + +/* ===================================================== MEMPWREVENTEN ===================================================== */ +/* ======================================= PWRCTRL MEMPWREVENTEN CACHEB2EN [31..31] ======================================== */ +typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_CACHEB2EN */ + PWRCTRL_MEMPWREVENTEN_CACHEB2EN_EN = 1, /*!< EN : Enable CACHE BANK 2 status event value. */ + PWRCTRL_MEMPWREVENTEN_CACHEB2EN_DIS = 0, /*!< DIS : Disable CACHE BANK 2 status event value. */ +} PWRCTRL_MEMPWREVENTEN_CACHEB2EN_Enum; + +/* ======================================= PWRCTRL MEMPWREVENTEN CACHEB0EN [30..30] ======================================== */ +typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_CACHEB0EN */ + PWRCTRL_MEMPWREVENTEN_CACHEB0EN_EN = 1, /*!< EN : Enable CACHE BANK 0 status event value. */ + PWRCTRL_MEMPWREVENTEN_CACHEB0EN_DIS = 0, /*!< DIS : Disable CACHE BANK 0 status event value. */ +} PWRCTRL_MEMPWREVENTEN_CACHEB0EN_Enum; + +/* ======================================== PWRCTRL MEMPWREVENTEN FLASH1EN [14..14] ======================================== */ +typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_FLASH1EN */ + PWRCTRL_MEMPWREVENTEN_FLASH1EN_EN = 1, /*!< EN : Enable FLASH status event value. */ + PWRCTRL_MEMPWREVENTEN_FLASH1EN_DIS = 0, /*!< DIS : Disables FLASH status event value. */ +} PWRCTRL_MEMPWREVENTEN_FLASH1EN_Enum; + +/* ======================================== PWRCTRL MEMPWREVENTEN FLASH0EN [13..13] ======================================== */ +typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_FLASH0EN */ + PWRCTRL_MEMPWREVENTEN_FLASH0EN_EN = 1, /*!< EN : Enable FLASH status event value. */ + PWRCTRL_MEMPWREVENTEN_FLASH0EN_DIS = 0, /*!< DIS : Disables FLASH status event value. */ +} PWRCTRL_MEMPWREVENTEN_FLASH0EN_Enum; + +/* ========================================= PWRCTRL MEMPWREVENTEN SRAMEN [3..12] ========================================== */ +typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_SRAMEN */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_NONE = 0, /*!< NONE : Disable SRAM power-on status event value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP0EN = 1, /*!< GROUP0EN : Enable SRAM group0 (0KB-32KB) power on status event + value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP1EN = 2, /*!< GROUP1EN : Enable SRAM group1 (32KB-64KB) power on status event + value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP2EN = 4, /*!< GROUP2EN : Enable SRAM group2 (64KB-96KB) power on status event + value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP3EN = 8, /*!< GROUP3EN : Enable SRAM group3 (96KB-128KB) power on status event + value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP4EN = 16, /*!< GROUP4EN : Enable SRAM group4 (128KB-160KB) power on status + event value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP5EN = 32, /*!< GROUP5EN : Enable SRAM group5 (160KB-192KB) power on status + event value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP6EN = 64, /*!< GROUP6EN : Enable SRAM group6 (192KB-224KB) power on status + event value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP7EN = 128, /*!< GROUP7EN : Enable SRAM group7 (224KB-256KB) power on status + event value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP8EN = 256, /*!< GROUP8EN : Enable SRAM group8 (256KB-288KB) power on status + event value. */ + PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP9EN = 512, /*!< GROUP9EN : Enable SRAM group9 (288KB-320KB) power on status + event value. */ +} PWRCTRL_MEMPWREVENTEN_SRAMEN_Enum; + +/* ========================================== PWRCTRL MEMPWREVENTEN DTCMEN [0..2] ========================================== */ +typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_DTCMEN */ + PWRCTRL_MEMPWREVENTEN_DTCMEN_NONE = 0, /*!< NONE : Do not enable DTCM power-on status event value. */ + PWRCTRL_MEMPWREVENTEN_DTCMEN_GROUP0DTCM0EN = 1,/*!< GROUP0DTCM0EN : Enable GROUP0_DTCM0 power on status event value. */ + PWRCTRL_MEMPWREVENTEN_DTCMEN_GROUP0DTCM1EN = 2,/*!< GROUP0DTCM1EN : Enable GROUP0_DTCM1 power on status event value. */ + PWRCTRL_MEMPWREVENTEN_DTCMEN_GROUP0EN = 3, /*!< GROUP0EN : Enable DTCMs in group0 power on status event value. */ + PWRCTRL_MEMPWREVENTEN_DTCMEN_GROUP1EN = 4, /*!< GROUP1EN : Enable DTCMs in group1 power on status event value. */ + PWRCTRL_MEMPWREVENTEN_DTCMEN_ALL = 7, /*!< ALL : Enable all DTCM power on status event value. */ +} PWRCTRL_MEMPWREVENTEN_DTCMEN_Enum; + + + +/* =========================================================================================================================== */ +/* ================ RSTGEN ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== CFG ========================================================== */ +/* ========================================================= SWPOI ========================================================= */ +/* ============================================= RSTGEN SWPOI SWPOIKEY [0..7] ============================================== */ +typedef enum { /*!< RSTGEN_SWPOI_SWPOIKEY */ + RSTGEN_SWPOI_SWPOIKEY_KEYVALUE = 27, /*!< KEYVALUE : Writing 0x1B key value generates a software POI reset. + value. */ +} RSTGEN_SWPOI_SWPOIKEY_Enum; + +/* ========================================================= SWPOR ========================================================= */ +/* ============================================= RSTGEN SWPOR SWPORKEY [0..7] ============================================== */ +typedef enum { /*!< RSTGEN_SWPOR_SWPORKEY */ + RSTGEN_SWPOR_SWPORKEY_KEYVALUE = 212, /*!< KEYVALUE : Writing 0xD4 key value generates a software POR reset. + value. */ +} RSTGEN_SWPOR_SWPORKEY_Enum; + +/* ======================================================== TPIURST ======================================================== */ +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ +/* ========================================================= STAT ========================================================== */ + + +/* =========================================================================================================================== */ +/* ================ RTC ================ */ +/* =========================================================================================================================== */ + +/* ======================================================== CTRLOW ========================================================= */ +/* ========================================================= CTRUP ========================================================= */ +/* =============================================== RTC CTRUP CTERR [31..31] ================================================ */ +typedef enum { /*!< RTC_CTRUP_CTERR */ + RTC_CTRUP_CTERR_NOERR = 0, /*!< NOERR : No read error occurred value. */ + RTC_CTRUP_CTERR_RDERR = 1, /*!< RDERR : Read error occurred value. */ +} RTC_CTRUP_CTERR_Enum; + +/* ================================================ RTC CTRUP CEB [28..28] ================================================= */ +typedef enum { /*!< RTC_CTRUP_CEB */ + RTC_CTRUP_CEB_DIS = 0, /*!< DIS : Disable the Century bit from changing value. */ + RTC_CTRUP_CEB_EN = 1, /*!< EN : Enable the Century bit to change value. */ +} RTC_CTRUP_CEB_Enum; + +/* ================================================= RTC CTRUP CB [27..27] ================================================= */ +typedef enum { /*!< RTC_CTRUP_CB */ + RTC_CTRUP_CB_2000 = 0, /*!< 2000 : Century is 2000s value. */ + RTC_CTRUP_CB_1900_2100 = 1, /*!< 1900_2100 : Century is 1900s/2100s value. */ +} RTC_CTRUP_CB_Enum; + +/* ======================================================== ALMLOW ========================================================= */ +/* ========================================================= ALMUP ========================================================= */ +/* ======================================================== RTCCTL ========================================================= */ +/* =============================================== RTC RTCCTL HR1224 [5..5] ================================================ */ +typedef enum { /*!< RTC_RTCCTL_HR1224 */ + RTC_RTCCTL_HR1224_24HR = 0, /*!< 24HR : Hours in 24 hour mode value. */ + RTC_RTCCTL_HR1224_12HR = 1, /*!< 12HR : Hours in 12 hour mode value. */ +} RTC_RTCCTL_HR1224_Enum; + +/* ================================================ RTC RTCCTL RSTOP [4..4] ================================================ */ +typedef enum { /*!< RTC_RTCCTL_RSTOP */ + RTC_RTCCTL_RSTOP_RUN = 0, /*!< RUN : Allow the RTC input clock to run value. */ + RTC_RTCCTL_RSTOP_STOP = 1, /*!< STOP : Stop the RTC input clock value. */ +} RTC_RTCCTL_RSTOP_Enum; + +/* ================================================= RTC RTCCTL RPT [1..3] ================================================= */ +typedef enum { /*!< RTC_RTCCTL_RPT */ + RTC_RTCCTL_RPT_DIS = 0, /*!< DIS : Alarm interrupt disabled value. */ + RTC_RTCCTL_RPT_YEAR = 1, /*!< YEAR : Interrupt every year value. */ + RTC_RTCCTL_RPT_MONTH = 2, /*!< MONTH : Interrupt every month value. */ + RTC_RTCCTL_RPT_WEEK = 3, /*!< WEEK : Interrupt every week value. */ + RTC_RTCCTL_RPT_DAY = 4, /*!< DAY : Interrupt every day value. */ + RTC_RTCCTL_RPT_HR = 5, /*!< HR : Interrupt every hour value. */ + RTC_RTCCTL_RPT_MIN = 6, /*!< MIN : Interrupt every minute value. */ + RTC_RTCCTL_RPT_SEC = 7, /*!< SEC : Interrupt every second/10th/100th value. */ +} RTC_RTCCTL_RPT_Enum; + +/* ================================================ RTC RTCCTL WRTC [0..0] ================================================= */ +typedef enum { /*!< RTC_RTCCTL_WRTC */ + RTC_RTCCTL_WRTC_DIS = 0, /*!< DIS : Counter writes are disabled value. */ + RTC_RTCCTL_WRTC_EN = 1, /*!< EN : Counter writes are enabled value. */ +} RTC_RTCCTL_WRTC_Enum; + +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ + + +/* =========================================================================================================================== */ +/* ================ SCARD ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== SR =========================================================== */ +/* ========================================================== DR =========================================================== */ +/* ========================================================== SR1 ========================================================== */ +/* ====================================================== RETXCNTRMI ======================================================= */ +/* ======================================================== CLKCTRL ======================================================== */ + + +/* =========================================================================================================================== */ +/* ================ SECURITY ================ */ +/* =========================================================================================================================== */ + +/* ========================================================= CTRL ========================================================== */ +/* ============================================= SECURITY CTRL FUNCTION [4..7] ============================================= */ +typedef enum { /*!< SECURITY_CTRL_FUNCTION */ + SECURITY_CTRL_FUNCTION_CRC32 = 0, /*!< CRC32 : Perform CRC32 operation value. */ +} SECURITY_CTRL_FUNCTION_Enum; + +/* ======================================================== SRCADDR ======================================================== */ +/* ========================================================== LEN ========================================================== */ +/* ======================================================== RESULT ========================================================= */ +/* ======================================================= LOCKCTRL ======================================================== */ +/* ============================================ SECURITY LOCKCTRL SELECT [0..7] ============================================ */ +typedef enum { /*!< SECURITY_LOCKCTRL_SELECT */ + SECURITY_LOCKCTRL_SELECT_CUSTOMER_KEY = 1, /*!< CUSTOMER_KEY : Unlock Customer Key (access to top half of info0) + value. */ + SECURITY_LOCKCTRL_SELECT_NONE = 0, /*!< NONE : Lock Control should be set to NONE when not in use. value. */ +} SECURITY_LOCKCTRL_SELECT_Enum; + +/* ======================================================= LOCKSTAT ======================================================== */ +/* =========================================== SECURITY LOCKSTAT STATUS [0..31] ============================================ */ +typedef enum { /*!< SECURITY_LOCKSTAT_STATUS */ + SECURITY_LOCKSTAT_STATUS_CUSTOMER_KEY = 1, /*!< CUSTOMER_KEY : Customer Key is unlocked (access is granted to + top half of info0) value. */ + SECURITY_LOCKSTAT_STATUS_NONE = 0, /*!< NONE : No resources are unlocked value. */ +} SECURITY_LOCKSTAT_STATUS_Enum; + +/* ========================================================= KEY0 ========================================================== */ +/* ========================================================= KEY1 ========================================================== */ +/* ========================================================= KEY2 ========================================================== */ +/* ========================================================= KEY3 ========================================================== */ + + +/* =========================================================================================================================== */ +/* ================ UART0 ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== DR =========================================================== */ +/* =============================================== UART0 DR OEDATA [11..11] ================================================ */ +typedef enum { /*!< UART0_DR_OEDATA */ + UART0_DR_OEDATA_NOERR = 0, /*!< NOERR : No error on UART OEDATA, overrun error indicator. value. */ + UART0_DR_OEDATA_ERR = 1, /*!< ERR : Error on UART OEDATA, overrun error indicator. value. */ +} UART0_DR_OEDATA_Enum; + +/* =============================================== UART0 DR BEDATA [10..10] ================================================ */ +typedef enum { /*!< UART0_DR_BEDATA */ + UART0_DR_BEDATA_NOERR = 0, /*!< NOERR : No error on UART BEDATA, break error indicator. value. */ + UART0_DR_BEDATA_ERR = 1, /*!< ERR : Error on UART BEDATA, break error indicator. value. */ +} UART0_DR_BEDATA_Enum; + +/* ================================================ UART0 DR PEDATA [9..9] ================================================= */ +typedef enum { /*!< UART0_DR_PEDATA */ + UART0_DR_PEDATA_NOERR = 0, /*!< NOERR : No error on UART PEDATA, parity error indicator. value. */ + UART0_DR_PEDATA_ERR = 1, /*!< ERR : Error on UART PEDATA, parity error indicator. value. */ +} UART0_DR_PEDATA_Enum; + +/* ================================================ UART0 DR FEDATA [8..8] ================================================= */ +typedef enum { /*!< UART0_DR_FEDATA */ + UART0_DR_FEDATA_NOERR = 0, /*!< NOERR : No error on UART FEDATA, framing error indicator. value. */ + UART0_DR_FEDATA_ERR = 1, /*!< ERR : Error on UART FEDATA, framing error indicator. value. */ +} UART0_DR_FEDATA_Enum; + +/* ========================================================== RSR ========================================================== */ +/* ================================================ UART0 RSR OESTAT [3..3] ================================================ */ +typedef enum { /*!< UART0_RSR_OESTAT */ + UART0_RSR_OESTAT_NOERR = 0, /*!< NOERR : No error on UART OESTAT, overrun error indicator. value. */ + UART0_RSR_OESTAT_ERR = 1, /*!< ERR : Error on UART OESTAT, overrun error indicator. value. */ +} UART0_RSR_OESTAT_Enum; + +/* ================================================ UART0 RSR BESTAT [2..2] ================================================ */ +typedef enum { /*!< UART0_RSR_BESTAT */ + UART0_RSR_BESTAT_NOERR = 0, /*!< NOERR : No error on UART BESTAT, break error indicator. value. */ + UART0_RSR_BESTAT_ERR = 1, /*!< ERR : Error on UART BESTAT, break error indicator. value. */ +} UART0_RSR_BESTAT_Enum; + +/* ================================================ UART0 RSR PESTAT [1..1] ================================================ */ +typedef enum { /*!< UART0_RSR_PESTAT */ + UART0_RSR_PESTAT_NOERR = 0, /*!< NOERR : No error on UART PESTAT, parity error indicator. value. */ + UART0_RSR_PESTAT_ERR = 1, /*!< ERR : Error on UART PESTAT, parity error indicator. value. */ +} UART0_RSR_PESTAT_Enum; + +/* ================================================ UART0 RSR FESTAT [0..0] ================================================ */ +typedef enum { /*!< UART0_RSR_FESTAT */ + UART0_RSR_FESTAT_NOERR = 0, /*!< NOERR : No error on UART FESTAT, framing error indicator. value. */ + UART0_RSR_FESTAT_ERR = 1, /*!< ERR : Error on UART FESTAT, framing error indicator. value. */ +} UART0_RSR_FESTAT_Enum; + +/* ========================================================== FR =========================================================== */ +/* ================================================= UART0 FR TXFE [7..7] ================================================== */ +typedef enum { /*!< UART0_FR_TXFE */ + UART0_FR_TXFE_XMTFIFO_EMPTY = 1, /*!< XMTFIFO_EMPTY : Transmit fifo is empty. value. */ +} UART0_FR_TXFE_Enum; + +/* ================================================= UART0 FR RXFF [6..6] ================================================== */ +typedef enum { /*!< UART0_FR_RXFF */ + UART0_FR_RXFF_RCVFIFO_FULL = 1, /*!< RCVFIFO_FULL : Receive fifo is full. value. */ +} UART0_FR_RXFF_Enum; + +/* ================================================= UART0 FR TXFF [5..5] ================================================== */ +typedef enum { /*!< UART0_FR_TXFF */ + UART0_FR_TXFF_XMTFIFO_FULL = 1, /*!< XMTFIFO_FULL : Transmit fifo is full. value. */ +} UART0_FR_TXFF_Enum; + +/* ================================================= UART0 FR RXFE [4..4] ================================================== */ +typedef enum { /*!< UART0_FR_RXFE */ + UART0_FR_RXFE_RCVFIFO_EMPTY = 1, /*!< RCVFIFO_EMPTY : Receive fifo is empty. value. */ +} UART0_FR_RXFE_Enum; + +/* ================================================= UART0 FR BUSY [3..3] ================================================== */ +typedef enum { /*!< UART0_FR_BUSY */ + UART0_FR_BUSY_BUSY = 1, /*!< BUSY : UART busy indicator. value. */ +} UART0_FR_BUSY_Enum; + +/* ================================================== UART0 FR DCD [2..2] ================================================== */ +typedef enum { /*!< UART0_FR_DCD */ + UART0_FR_DCD_DETECTED = 1, /*!< DETECTED : Data carrier detect detected. value. */ +} UART0_FR_DCD_Enum; + +/* ================================================== UART0 FR DSR [1..1] ================================================== */ +typedef enum { /*!< UART0_FR_DSR */ + UART0_FR_DSR_READY = 1, /*!< READY : Data set ready. value. */ +} UART0_FR_DSR_Enum; + +/* ================================================== UART0 FR CTS [0..0] ================================================== */ +typedef enum { /*!< UART0_FR_CTS */ + UART0_FR_CTS_CLEARTOSEND = 1, /*!< CLEARTOSEND : Clear to send is indicated. value. */ +} UART0_FR_CTS_Enum; + +/* ========================================================= ILPR ========================================================== */ +/* ========================================================= IBRD ========================================================== */ +/* ========================================================= FBRD ========================================================== */ +/* ========================================================= LCRH ========================================================== */ +/* ========================================================== CR =========================================================== */ +/* ================================================ UART0 CR CLKSEL [4..6] ================================================= */ +typedef enum { /*!< UART0_CR_CLKSEL */ + UART0_CR_CLKSEL_NOCLK = 0, /*!< NOCLK : No UART clock. This is the low power default. value. */ + UART0_CR_CLKSEL_24MHZ = 1, /*!< 24MHZ : 24 MHz clock. value. */ + UART0_CR_CLKSEL_12MHZ = 2, /*!< 12MHZ : 12 MHz clock. value. */ + UART0_CR_CLKSEL_6MHZ = 3, /*!< 6MHZ : 6 MHz clock. value. */ + UART0_CR_CLKSEL_3MHZ = 4, /*!< 3MHZ : 3 MHz clock. value. */ +} UART0_CR_CLKSEL_Enum; + +/* ========================================================= IFLS ========================================================== */ +/* ========================================================== IER ========================================================== */ +/* ========================================================== IES ========================================================== */ +/* ========================================================== MIS ========================================================== */ +/* ========================================================== IEC ========================================================== */ + + +/* =========================================================================================================================== */ +/* ================ VCOMP ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== CFG ========================================================== */ +/* =============================================== VCOMP CFG LVLSEL [16..19] =============================================== */ +typedef enum { /*!< VCOMP_CFG_LVLSEL */ + VCOMP_CFG_LVLSEL_0P58V = 0, /*!< 0P58V : Set Reference input to 0.58 Volts. value. */ + VCOMP_CFG_LVLSEL_0P77V = 1, /*!< 0P77V : Set Reference input to 0.77 Volts. value. */ + VCOMP_CFG_LVLSEL_0P97V = 2, /*!< 0P97V : Set Reference input to 0.97 Volts. value. */ + VCOMP_CFG_LVLSEL_1P16V = 3, /*!< 1P16V : Set Reference input to 1.16 Volts. value. */ + VCOMP_CFG_LVLSEL_1P35V = 4, /*!< 1P35V : Set Reference input to 1.35 Volts. value. */ + VCOMP_CFG_LVLSEL_1P55V = 5, /*!< 1P55V : Set Reference input to 1.55 Volts. value. */ + VCOMP_CFG_LVLSEL_1P74V = 6, /*!< 1P74V : Set Reference input to 1.74 Volts. value. */ + VCOMP_CFG_LVLSEL_1P93V = 7, /*!< 1P93V : Set Reference input to 1.93 Volts. value. */ + VCOMP_CFG_LVLSEL_2P13V = 8, /*!< 2P13V : Set Reference input to 2.13 Volts. value. */ + VCOMP_CFG_LVLSEL_2P32V = 9, /*!< 2P32V : Set Reference input to 2.32 Volts. value. */ + VCOMP_CFG_LVLSEL_2P51V = 10, /*!< 2P51V : Set Reference input to 2.51 Volts. value. */ + VCOMP_CFG_LVLSEL_2P71V = 11, /*!< 2P71V : Set Reference input to 2.71 Volts. value. */ + VCOMP_CFG_LVLSEL_2P90V = 12, /*!< 2P90V : Set Reference input to 2.90 Volts. value. */ + VCOMP_CFG_LVLSEL_3P09V = 13, /*!< 3P09V : Set Reference input to 3.09 Volts. value. */ + VCOMP_CFG_LVLSEL_3P29V = 14, /*!< 3P29V : Set Reference input to 3.29 Volts. value. */ + VCOMP_CFG_LVLSEL_3P48V = 15, /*!< 3P48V : Set Reference input to 3.48 Volts. value. */ +} VCOMP_CFG_LVLSEL_Enum; + +/* ================================================= VCOMP CFG NSEL [8..9] ================================================= */ +typedef enum { /*!< VCOMP_CFG_NSEL */ + VCOMP_CFG_NSEL_VREFEXT1 = 0, /*!< VREFEXT1 : Use external reference 1 for reference input. value. */ + VCOMP_CFG_NSEL_VREFEXT2 = 1, /*!< VREFEXT2 : Use external reference 2 for reference input. value. */ + VCOMP_CFG_NSEL_VREFEXT3 = 2, /*!< VREFEXT3 : Use external reference 3 for reference input. value. */ + VCOMP_CFG_NSEL_DAC = 3, /*!< DAC : Use DAC output selected by LVLSEL for reference input. + value. */ +} VCOMP_CFG_NSEL_Enum; + +/* ================================================= VCOMP CFG PSEL [0..1] ================================================= */ +typedef enum { /*!< VCOMP_CFG_PSEL */ + VCOMP_CFG_PSEL_VDDADJ = 0, /*!< VDDADJ : Use VDDADJ for the positive input. value. */ + VCOMP_CFG_PSEL_VTEMP = 1, /*!< VTEMP : Use the temperature sensor output for the positive input. + Note: If this channel is selected for PSEL, the bandap + circuit required for temperature comparisons will automatically + turn on. The bandgap circuit requires 11us to stabalize. + value. */ + VCOMP_CFG_PSEL_VEXT1 = 2, /*!< VEXT1 : Use external voltage 0 for positive input. value. */ + VCOMP_CFG_PSEL_VEXT2 = 3, /*!< VEXT2 : Use external voltage 1 for positive input. value. */ +} VCOMP_CFG_PSEL_Enum; + +/* ========================================================= STAT ========================================================== */ +/* =============================================== VCOMP STAT PWDSTAT [1..1] =============================================== */ +typedef enum { /*!< VCOMP_STAT_PWDSTAT */ + VCOMP_STAT_PWDSTAT_POWERED_DOWN = 1, /*!< POWERED_DOWN : The voltage comparator is powered down. value. */ +} VCOMP_STAT_PWDSTAT_Enum; + +/* =============================================== VCOMP STAT CMPOUT [0..0] ================================================ */ +typedef enum { /*!< VCOMP_STAT_CMPOUT */ + VCOMP_STAT_CMPOUT_VOUT_LOW = 0, /*!< VOUT_LOW : The negative input of the comparator is greater than + the positive input. value. */ + VCOMP_STAT_CMPOUT_VOUT_HIGH = 1, /*!< VOUT_HIGH : The positive input of the comparator is greater + than the negative input. value. */ +} VCOMP_STAT_CMPOUT_Enum; + +/* ======================================================== PWDKEY ========================================================= */ +/* ============================================== VCOMP PWDKEY PWDKEY [0..31] ============================================== */ +typedef enum { /*!< VCOMP_PWDKEY_PWDKEY */ + VCOMP_PWDKEY_PWDKEY_Key = 55, /*!< Key : Key value. */ +} VCOMP_PWDKEY_PWDKEY_Enum; + +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ + + +/* =========================================================================================================================== */ +/* ================ WDT ================ */ +/* =========================================================================================================================== */ + +/* ========================================================== CFG ========================================================== */ +/* ================================================ WDT CFG CLKSEL [24..26] ================================================ */ +typedef enum { /*!< WDT_CFG_CLKSEL */ + WDT_CFG_CLKSEL_OFF = 0, /*!< OFF : Low Power Mode. This setting disables the watch dog timer. + value. */ + WDT_CFG_CLKSEL_128HZ = 1, /*!< 128HZ : 128 Hz LFRC clock. value. */ + WDT_CFG_CLKSEL_16HZ = 2, /*!< 16HZ : 16 Hz LFRC clock. value. */ + WDT_CFG_CLKSEL_1HZ = 3, /*!< 1HZ : 1 Hz LFRC clock. value. */ + WDT_CFG_CLKSEL_1_16HZ = 4, /*!< 1_16HZ : 1/16th Hz LFRC clock. value. */ +} WDT_CFG_CLKSEL_Enum; + +/* ========================================================= RSTRT ========================================================= */ +/* ================================================ WDT RSTRT RSTRT [0..7] ================================================= */ +typedef enum { /*!< WDT_RSTRT_RSTRT */ + WDT_RSTRT_RSTRT_KEYVALUE = 178, /*!< KEYVALUE : This is the key value to write to WDTRSTRT to restart + the WDT. This is a write only register. value. */ +} WDT_RSTRT_RSTRT_Enum; + +/* ========================================================= LOCK ========================================================== */ +/* ================================================= WDT LOCK LOCK [0..7] ================================================== */ +typedef enum { /*!< WDT_LOCK_LOCK */ + WDT_LOCK_LOCK_KEYVALUE = 58, /*!< KEYVALUE : This is the key value to write to WDTLOCK to lock + the WDT. value. */ +} WDT_LOCK_LOCK_Enum; + +/* ========================================================= COUNT ========================================================= */ +/* ========================================================= INTEN ========================================================= */ +/* ======================================================== INTSTAT ======================================================== */ +/* ======================================================== INTCLR ========================================================= */ +/* ======================================================== INTSET ========================================================= */ + +/** @} */ /* End of group EnumValue_peripherals */ + + +#ifdef __cplusplus +} +#endif + +#endif /* APOLLO3_H */ + + +/** @} */ /* End of group apollo3 */ + +/** @} */ /* End of group Ambiq Micro */ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/captured_data_to_wav.py b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/captured_data_to_wav.py new file mode 100644 index 0000000000..84b6259452 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/captured_data_to_wav.py @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import re +import struct +import matplotlib.pyplot as plt +import soundfile as sf + +def new_data_to_array(fn): + vals = [] + with open(fn) as f: + for n, line in enumerate(f): + if n is not 0: + vals.extend([int(v, 16) for v in line.split()]) + b = ''.join(map(chr, vals)) + y = struct.unpack('<'+'h'*int(len(b)/2), b) + + return y + + +data = 'captured_data.txt' +vals = np.array(new_data_to_array(data)).astype(float) + +#plt.plot(vals, 'o-') +#plt.show(block=False) + +wav = vals/np.max(np.abs(vals)) +sf.write('captured_data.wav', wav, 16000) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/compare_1k.py b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/compare_1k.py new file mode 100644 index 0000000000..9c91560d50 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/compare_1k.py @@ -0,0 +1,153 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import re +import struct +import matplotlib.pyplot as plt +import soundfile as sf + +def new_data_to_array(fn, datatype='int16'): + vals = [] + with open(fn) as f: + for n, line in enumerate(f): + if n is not 0: + vals.extend([int(v, 16) for v in line.split()]) + b = ''.join(map(chr, vals)) + + if datatype == 'int8': + typestr = 'b' + arraylen = int(len(b)) + elif datatype == 'int16': + typestr = 'h' + arraylen = int(len(b)//2) + elif datatype == 'int32': + typestr = 'i' + arraylen = int(len(b)//4) + if datatype == 'uint8': + typestr = 'B' + arraylen = int(len(b)) + elif datatype == 'uint16': + typestr = 'H' + arraylen = int(len(b)//2) + elif datatype == 'uint32': + typestr = 'I' + arraylen = int(len(b)//4) + + y = np.array(struct.unpack('<'+typestr*arraylen, b)) + + return y + +# x is the fixed-point input in Qm.n format +def to_float(x, n): + return x.astype(float)*2**(-n) + +micro_windowed_input = new_data_to_array('micro_windowed_input.txt', datatype='int32') +cmsis_windowed_input = new_data_to_array('cmsis_windowed_input.txt', datatype='int16') + +micro_dft = new_data_to_array('micro_dft.txt', datatype='int32') +cmsis_dft = new_data_to_array('cmsis_dft.txt', datatype='int16') +py_dft = np.fft.rfft(to_float(cmsis_windowed_input,15), n=512) +py_result = np.empty((2*py_dft.size), dtype=np.float) +py_result[0::2] = np.real(py_dft) +py_result[1::2] = np.imag(py_dft) + +micro_power = new_data_to_array('micro_power.txt', datatype='int32') +cmsis_power = new_data_to_array('cmsis_power.txt', datatype='int16') +py_power = np.square(np.abs(py_dft)) + +micro_power_avg = new_data_to_array('micro_power_avg.txt', datatype='uint8') +cmsis_power_avg = new_data_to_array('cmsis_power_avg.txt', datatype='uint8') + +plt.figure(1) +plt.subplot(311) +plt.plot(micro_windowed_input, label='Micro fixed') +plt.legend() +plt.subplot(312) +plt.plot(cmsis_windowed_input, label='CMSIS fixed') +plt.legend() +plt.subplot(313) +plt.plot(to_float(micro_windowed_input, 30), label='Micro to float') +plt.plot(to_float(cmsis_windowed_input, 15), label='CMSIS to float') +plt.legend() + +plt.figure(2) +plt.subplot(311) +plt.plot(micro_dft, label='Micro fixed') +plt.legend() +plt.subplot(312) +plt.plot(cmsis_dft, label='CMSIS fixed') +plt.legend() +plt.subplot(313) +plt.plot(to_float(micro_dft, 22), label='Micro to float') +# CMSIS result has 6 fractionanl bits (not 7) due to documentation error (see README.md) +plt.plot(to_float(cmsis_dft, 6), label='CMSIS to float') +plt.plot(py_result, label='Python result') +plt.legend() + +plt.figure(3) +plt.subplot(311) +plt.plot(micro_power, label='Micro fixed') +plt.legend() +plt.subplot(312) +plt.plot(cmsis_power[0:256], label='CMSIS fixed') +plt.legend() +plt.subplot(313) +plt.plot(to_float(micro_power, 22), label='Micro to float') +plt.plot(to_float(cmsis_power[0:256], 6), label='CMSIS to float') +plt.plot(py_power, label='Python result') +plt.legend() + +plt.figure(4) +plt.plot(micro_power_avg, label='Micro fixed') +plt.plot(cmsis_power_avg, label='CMSIS fixed') +plt.legend() +plt.show() + +#t = np.arange(16000.*0.03)/16000. +#sin1k = 0.1*np.sin(2*np.pi*1000*t) # Factor of 10 because micro preprocessing overflows otherwise +# +#plt.figure(1) +#plt.subplot(511) +#plt.plot(sin1k) +#plt.title('Input sine') +# +#plt.subplot(512) +#plt.plot(to_float(micro_windowed_input, 30), label='Micro-Lite') +#plt.plot(to_float(cmsis_windowed_input, 15), label='CMSIS') +#plt.title('Windowed sine') +#plt.legend(loc='center right') +# +#plt.subplot(513) +#plt.plot(to_float(micro_dft, 22), label='Micro-Lite') +#plt.plot(to_float(cmsis_dft, 6), label='CMSIS') +#plt.title('FFT') +#plt.legend(loc='center') +# +#plt.subplot(514) +#plt.plot(to_float(micro_power, 22), label='Micro-Lite') +#plt.plot(to_float(cmsis_power[0:256], 6), label='CMSIS') +#plt.title('|FFT|^2') +#plt.legend(loc='center right') +# +#plt.subplot(515) +#plt.plot(micro_power_avg, label='Micro-Lite') +#plt.plot(cmsis_power_avg, label='CMSIS') +#plt.title('Averaged |FFT|^2') +#plt.legend(loc='center right') +# +#plt.tight_layout(pad=0, w_pad=0.2, h_pad=0.2) +# +#plt.show() +# diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc new file mode 100644 index 0000000000..31fae1f2dc --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc @@ -0,0 +1,57 @@ +/* This file is a modification of the Tensorflow Micro Lite file preprocessor.cc + * We have retained the original copyright and header information, in + * accordance with the Apache 2.0 license terms. + */ + +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +extern "C" { +#include "tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h" +} + +#define output_data_size 43 +int count; + +extern TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, + const int16_t* input, int input_size, int output_size, + uint8_t* output); + +TF_LITE_MICRO_TESTS_BEGIN +CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; +//DWT->LAR = 0xC5ACCE55; +DWT->CYCCNT = 0; +DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + +TF_LITE_MICRO_TEST(TestPreprocessor) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + uint8_t calculated_data[output_data_size]; + TfLiteStatus yes_status = Preprocess( + error_reporter, g_sin_1k, g_sin_1k_size, + output_data_size, calculated_data); + count = DWT->CYCCNT; + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, yes_status); + +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd new file mode 100644 index 0000000000..0f701660a8 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Needs to be compiled with -O0 +file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_1k_cmsis_test +target remote localhost:2331 +load ../../../tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_1k_cmsis_test +monitor reset +break preprocessor.cc:70 +commands +dump verilog value cmsis_windowed_input.txt bufB +c +end +break preprocessor.cc:77 +commands +dump verilog value cmsis_dft.txt bufA +c +end +break preprocessor.cc:82 +commands +dump verilog value cmsis_power.txt bufB +c +end +break preprocessor.cc:84 +commands +dump verilog memory cmsis_power_avg.txt output output+42 +c +end +break preprocessor_1k.cc:53 +commands +print count +end +c diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_micro_test.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_micro_test.cmd new file mode 100644 index 0000000000..35c602d78c --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_micro_test.cmd @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Needs to be run when compiled with -O0 +file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_1k_micro_test +target remote localhost:2331 +load ../../../tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_1k_micro_test +monitor reset +break preprocessor.cc:211 +commands +dump verilog value micro_windowed_input.txt fixed_input +dump verilog value micro_dft.txt fourier_values +dump verilog value micro_power.txt power_spectrum +dump verilog memory micro_power_avg.txt output output+42 +c +end +break preprocessor_1k.cc:53 +commands +print count +end +c diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_test.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_test.cmd new file mode 100644 index 0000000000..4458af17d6 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_test.cmd @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +file ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test +target remote localhost:2331 +load ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test +monitor reset diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd new file mode 100644 index 0000000000..db299f7277 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test +target remote localhost:2331 +load ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test +monitor reset +break pushbutton_main.c:325 +commands +printf "Silence score: %d\n", g_silence_score +printf "Unknown score: %d\n", g_unknown_score +printf "Yes score: %d\n", g_yes_score +printf "No score: %d\n", g_no_score +printf "g_scores[0]: %d\n", g_scores[0] +printf "g_scores[1]: %d\n", g_scores[1] +printf "g_scores[2]: %d\n", g_scores[2] +printf "g_scores[3]: %d\n", g_scores[3] +printf "max_score: %d\n", max_score +printf "max_score_index: %d\n", max_score_index +c +end +c diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd new file mode 100644 index 0000000000..8cd1a7e90e --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an AS IS BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test +target remote localhost:2331 +load ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test +monitor reset +break pushbutton_main.c:316 +commands +dump verilog value captured_data.txt captured_data +c +end +c diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c new file mode 100644 index 0000000000..82337e63da --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c @@ -0,0 +1,339 @@ +/* This file is a modification of the Tensorflow Micro Lite file _main.c + * We have retained the original copyright and header information, in + * accordance with the Apache 2.0 license terms. + */ + +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include "am_mcu_apollo.h" // Defines AM_CMSIS_REGS +#include "am_bsp.h" +#include "am_util.h" + +#define ARM_MATH_CM4 +#include + +//***************************************************************************** +// Parameters +// +// Total number of bytes transferred = 320*50*2 = 32000 +//***************************************************************************** + +#define FRAME_SIZE 320 // Capture one 320-sample (20-ms) frame at a time +#define NUM_FRAMES 50 // Number of frames in 1 second + +//***************************************************************************** +// GLOBALS +//***************************************************************************** + +volatile int16_t g_numFramesCaptured = 0; +volatile bool g_bPDMDataReady = false; +int16_t captured_data[FRAME_SIZE*NUM_FRAMES]; // Location of 1-second data buffer +extern uint8_t g_silence_score; +extern uint8_t g_unknown_score; +extern uint8_t g_yes_score; +extern uint8_t g_no_score; +q7_t g_scores[4] = {0}; + + +//***************************************************************************** +// The entry point for the application. +//***************************************************************************** +extern int main(int argc, char**argv); + +void DebugLog(const char* s) { am_util_stdio_printf( "%s", s); } +void DebugLogInt32(int32_t i) { am_util_stdio_printf( "%d", i); } +void DebugLogUInt32(uint32_t i) { am_util_stdio_printf( "%d", i); } +void DebugLogHex(uint32_t i) { am_util_stdio_printf( "0x%8x", i); } +void DebugLogFloat(float i) { am_util_stdio_printf( "%f", i); } + +//***************************************************************************** +// PDM configuration information. +//***************************************************************************** +void *PDMHandle; + +am_hal_pdm_config_t g_sPdmConfig = +{ + .eClkDivider = AM_HAL_PDM_MCLKDIV_1, + .eLeftGain = AM_HAL_PDM_GAIN_P225DB, + .eRightGain = AM_HAL_PDM_GAIN_P225DB, + .ui32DecimationRate = 48, // OSR = 1500/16 = 96 = 2*SINCRATE --> SINC_RATE = 48 + .bHighPassEnable = 0, + .ui32HighPassCutoff = 0xB, + .ePDMClkSpeed = AM_HAL_PDM_CLK_1_5MHZ, + .bInvertI2SBCLK = 0, + .ePDMClkSource = AM_HAL_PDM_INTERNAL_CLK, + .bPDMSampleDelay = 0, + .bDataPacking = 1, + .ePCMChannels = AM_HAL_PDM_CHANNEL_RIGHT, + .bLRSwap = 0, +}; + + +//***************************************************************************** +// BUTTON0 pin configuration settings. +//***************************************************************************** +const am_hal_gpio_pincfg_t g_deepsleep_button0 = +{ + .uFuncSel = 3, + .eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI, + .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, +}; + +//***************************************************************************** +// PDM initialization. +//***************************************************************************** +void pdm_init(void) +{ + // + // Initialize, power-up, and configure the PDM. + // + am_hal_pdm_initialize(0, &PDMHandle); + am_hal_pdm_power_control(PDMHandle, AM_HAL_PDM_POWER_ON, false); + am_hal_pdm_configure(PDMHandle, &g_sPdmConfig); + am_hal_pdm_enable(PDMHandle); + + // + // Configure the necessary pins. + // + am_hal_gpio_pincfg_t sPinCfg = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +// ARPIT 181019 + //sPinCfg.uFuncSel = AM_HAL_PIN_10_PDMCLK; + //am_hal_gpio_pinconfig(10, sPinCfg); + sPinCfg.uFuncSel = AM_HAL_PIN_12_PDMCLK; + am_hal_gpio_pinconfig(12, sPinCfg); + + sPinCfg.uFuncSel = AM_HAL_PIN_11_PDMDATA; + am_hal_gpio_pinconfig(11, sPinCfg); + + //am_hal_gpio_state_write(14, AM_HAL_GPIO_OUTPUT_CLEAR); + //am_hal_gpio_pinconfig(14, g_AM_HAL_GPIO_OUTPUT); + + // + // Configure and enable PDM interrupts (set up to trigger on DMA + // completion). + // + am_hal_pdm_interrupt_enable(PDMHandle, (AM_HAL_PDM_INT_DERR + | AM_HAL_PDM_INT_DCMP + | AM_HAL_PDM_INT_UNDFL + | AM_HAL_PDM_INT_OVF)); + +#if AM_CMSIS_REGS + NVIC_EnableIRQ(PDM_IRQn); +#else + am_hal_interrupt_enable(AM_HAL_INTERRUPT_PDM); +#endif +} + +//***************************************************************************** +// +// Start a transaction to get some number of bytes from the PDM interface. +// +//***************************************************************************** +void pdm_data_get(void) +{ + // + // Configure DMA and target address. + // + am_hal_pdm_transfer_t sTransfer; + sTransfer.ui32TargetAddr = (uint32_t ) (&captured_data[FRAME_SIZE*g_numFramesCaptured]); + sTransfer.ui32TotalCount = 2*FRAME_SIZE; // Each sample is 2 bytes + + // + // Start the data transfer. + // + am_hal_pdm_dma_start(PDMHandle, &sTransfer); +} + + +//***************************************************************************** +// +// PDM interrupt handler. +// +//***************************************************************************** +void am_pdm_isr(void) +{ + uint32_t ui32Status; + // + // Read the interrupt status. + // + am_hal_pdm_interrupt_status_get(PDMHandle, &ui32Status, true); + am_hal_pdm_interrupt_clear(PDMHandle, ui32Status); + + // + // Once our DMA transaction completes, send a flag to the main routine + // + if (ui32Status & AM_HAL_PDM_INT_DCMP) + g_bPDMDataReady = true; +} + + +//***************************************************************************** +// GPIO ISR +// Will enable the PDM, set number of frames transferred to 0, and turn on LED +//***************************************************************************** +void +am_gpio_isr(void) +{ + // + // Delay for debounce. + // + am_util_delay_ms(200); + + // + // Clear the GPIO Interrupt (write to clear). + // + am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); + + // Start audio transfer + am_hal_pdm_fifo_flush(PDMHandle); + pdm_data_get(); + am_hal_pdm_enable(PDMHandle); + + // + // Turn on LED 0 + // + am_devices_led_on(am_bsp_psLEDs, 0); +} + +int _main(void) +{ + am_util_id_t sIdDevice; + uint32_t ui32StrBuf; + + // + // Set the clock frequency. + // + am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0); + + // + // Set the default cache configuration + // + am_hal_cachectrl_config(&am_hal_cachectrl_defaults); + am_hal_cachectrl_enable(); + + // + // Configure the board for low power operation. + // + am_bsp_low_power_init(); + + +#if defined(AM_BSP_NUM_BUTTONS) && defined(AM_BSP_NUM_LEDS) + // + // Configure the button pin. + // + am_hal_gpio_pinconfig(AM_BSP_GPIO_BUTTON0, g_deepsleep_button0); + + // + // Clear the GPIO Interrupt (write to clear). + // + am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); + + // + // Enable the GPIO/button interrupt. + // + am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); + + // + // Configure the LEDs. + // + am_devices_led_array_init(am_bsp_psLEDs, AM_BSP_NUM_LEDS); + + // + // Turn the LEDs off + // + for (int ix = 0; ix < AM_BSP_NUM_LEDS; ix++) + { + am_devices_led_off(am_bsp_psLEDs, ix); + } + +// am_devices_led_on(am_bsp_psLEDs, 1); +#endif // defined(AM_BSP_NUM_BUTTONS) && defined(AM_BSP_NUM_LEDS) + +#if AM_CMSIS_REGS + NVIC_EnableIRQ(GPIO_IRQn); +#else // AM_CMSIS_REGS + am_hal_interrupt_enable(AM_HAL_INTERRUPT_GPIO); +#endif // AM_CMSIS_REGS + + // + // Enable interrupts to the core. + // + am_hal_interrupt_master_enable(); + + // Turn on PDM + pdm_init(); + + // + // Initialize the printf interface for UART output + // + am_bsp_uart_printf_enable(); + + // + // Print the banner. + // + am_util_stdio_terminal_clear(); + am_util_stdio_printf("Starting streaming test\n\n"); + + // Score variables + q7_t max_score = 0; + uint32_t max_score_index = 0; + + while(1) + { + + am_hal_interrupt_master_disable(); + + if (g_bPDMDataReady) + { + g_bPDMDataReady = false; + g_numFramesCaptured++; + + if (g_numFramesCaptured < NUM_FRAMES) { + pdm_data_get(); // Start converting the next set of PCM samples. + } + + else + { + g_numFramesCaptured = 0; + //am_hal_pdm_disable(PDMHandle); + am_devices_led_off(am_bsp_psLEDs, 0); + + main(0, NULL); + + g_scores[0] = (q7_t) g_silence_score - 128; + g_scores[1] = (q7_t) g_unknown_score - 128; + g_scores[2] = (q7_t) g_yes_score - 128; + g_scores[3] = (q7_t) g_no_score - 128; + + am_devices_led_off(am_bsp_psLEDs, max_score_index+1); // Turn off LED for previous max score + arm_max_q7(g_scores, 4, &max_score, &max_score_index); + am_devices_led_on(am_bsp_psLEDs, max_score_index+1); // Turn on LED for new max score + } + } + + // + // Go to Deep Sleep. + // + am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); + + am_hal_interrupt_master_enable(); + + } + + //main(0, NULL); +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc new file mode 100644 index 0000000000..ce4de4dbd8 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc @@ -0,0 +1,120 @@ +/* This file is a modification of the Tensorflow Micro Lite file micro_speech_test.cc + * We have retained the original copyright and header information, in + * accordance with the Apache 2.0 license terms. + */ + +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h" +#include "tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h" +#include "tensorflow/lite/experimental/micro/micro_interpreter.h" +#include "tensorflow/lite/schema/schema_generated.h" +#include "tensorflow/lite/version.h" + +extern int16_t captured_data[16000]; +uint8_t g_silence_score = 0; +uint8_t g_unknown_score = 0; +uint8_t g_yes_score = 0; +uint8_t g_no_score = 0; + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(TestPreprocessor) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + uint8_t preprocessed_data[43*49]; + TfLiteStatus preprocess_1sec_status = Preprocess_1sec( + error_reporter, captured_data, preprocessed_data); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, preprocess_1sec_status); + + + // Map the model into a usable data structure. This doesn't involve any + // copying or parsing, it's a very lightweight operation. + const tflite::Model* model = ::tflite::GetModel(g_tiny_conv_model_data); + if (model->version() != TFLITE_SCHEMA_VERSION) { + error_reporter->Report( + "Model provided is schema version %d not equal " + "to supported version %d.\n", + model->version(), TFLITE_SCHEMA_VERSION); + } + + // This pulls in all the operation implementations we need. + tflite::ops::micro::AllOpsResolver resolver; + + // Create an area of memory to use for input, output, and intermediate arrays. + const int tensor_arena_size = 10 * 1024; + uint8_t tensor_arena[tensor_arena_size]; + tflite::SimpleTensorAllocator tensor_allocator(tensor_arena, + tensor_arena_size); + + // Build an interpreter to run the model with. + tflite::MicroInterpreter interpreter(model, resolver, &tensor_allocator, + error_reporter); + + // Get information about the memory area to use for the model's input. + TfLiteTensor* input = interpreter.input(0); + + // Make sure the input has the properties we expect. + TF_LITE_MICRO_EXPECT_NE(nullptr, input); + TF_LITE_MICRO_EXPECT_EQ(4, input->dims->size); + TF_LITE_MICRO_EXPECT_EQ(1, input->dims->data[0]); + TF_LITE_MICRO_EXPECT_EQ(49, input->dims->data[1]); + TF_LITE_MICRO_EXPECT_EQ(43, input->dims->data[2]); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteUInt8, input->type); + + // Copy a spectrogram created from a .wav audio file of someone saying "Yes", + // into the memory area used for the input. + for (int i = 0; i < input->bytes; ++i) { + input->data.uint8[i] = preprocessed_data[i]; + } + + // Run the model on this input and make sure it succeeds. + TfLiteStatus invoke_status = interpreter.Invoke(); + if (invoke_status != kTfLiteOk) { + error_reporter->Report("Invoke failed\n"); + } + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, invoke_status); + + // Get the output from the model, and make sure it's the expected size and + // type. + TfLiteTensor* output = interpreter.output(0); + TF_LITE_MICRO_EXPECT_EQ(2, output->dims->size); + TF_LITE_MICRO_EXPECT_EQ(1, output->dims->data[0]); + TF_LITE_MICRO_EXPECT_EQ(4, output->dims->data[1]); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteUInt8, output->type); + + // There are four possible classes in the output, each with a score. + const int kSilenceIndex = 0; + const int kUnknownIndex = 1; + const int kYesIndex = 2; + const int kNoIndex = 3; + + // Make sure that the expected "Yes" score is higher than the other classes. + g_silence_score = output->data.uint8[kSilenceIndex]; + g_unknown_score = output->data.uint8[kUnknownIndex]; + g_yes_score = output->data.uint8[kYesIndex]; + g_no_score = output->data.uint8[kNoIndex]; + + error_reporter->Report("Ran successfully\n"); + +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c new file mode 100755 index 0000000000..c7f1573563 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c @@ -0,0 +1,116 @@ +//***************************************************************************** +// +//! @file system_apollo3.c +//! +//! @brief Ambiq Micro Apollo3 MCU specific functions. +// +//***************************************************************************** + +/* + * Copyright (C) 2015-2017, Ambiq Micro + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of itscontributors may be used to endorse + * or promote products derived from thissoftware without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file apollo3.h + * @brief CMSIS HeaderFile + * @version 1.0 + * @date 10. August 2018 + * @note Generated by SVDConv V3.3.18 on Friday, 10.08.2018 16:52:09 + * from File 'apollo3.svd', + * last modified on Friday, 10.08.2018 20:01:31 + */ + + +#include +#include "system_apollo3.h" +#include "apollo3.h" + +//***************************************************************************** +// +// Defines +// +//***************************************************************************** + +// +// Clocks +// +#define __HSI (6000000UL) +#define __XTAL (32768UL) // Crystal Oscillator frequency +#define __SYS_OSC_CLK (48000000) // Main oscillator frequency +#define __SYSTEM_CLOCK (1*__SYS_OSC_CLK) + +// +// Initialize SystemCoreClock with the system core clock frequency value +// achieved after system intitialization. +// This means system core clock frequency after call to SystemInit() +// +uint32_t SystemCoreClock = __SYSTEM_CLOCK; // System Clock Frequency (Core Clock) + +//***************************************************************************** +// +//! @brief Set the global clock frequncy. +//! +//! This function sets the global clock frequency. +//! +//! @return None. +// +//***************************************************************************** +void +SystemCoreClockUpdate(void) +{ + // + // Calculate the system frequency based upon the current register settings. + // This function can be used to retrieve the system core clock frequeny + // after user changed register sittings. + // + SystemCoreClock = __SYS_OSC_CLK / (CLKGEN->CCTRL_b.CORESEL + 1); +} + +//***************************************************************************** +// +//! @brief Initialize the system. +//! +//! This function sets up the microcontroller system. +//! +//! @return None. +// +//***************************************************************************** +void +SystemInit(void) +{ + // + // Initialize the system + // Do not use global variables because this function is called before + // reaching pre-main. RW section maybe overwritten afterwards. + // + SystemCoreClock = __SYSTEM_CLOCK; + + CLKGEN->CLKKEY = 0x47; // Enable write to CCTRL + CLKGEN->CCTRL_b.CORESEL = 0; // Div by 1 for 48MHz + CLKGEN->CLKKEY = 0; // Disable write to CCTRL +} + diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h new file mode 100755 index 0000000000..7fd9b51d5a --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h @@ -0,0 +1,72 @@ +//***************************************************************************** +// +//! @file system_Apollo3.h +//! +//! @brief Ambiq Micro Apollo3 MCU specific functions. +// +//***************************************************************************** + +/* + * Copyright (C) 2015-2017, Ambiq Micro + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of itscontributors may be used to endorse + * or promote products derived from thissoftware without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @file apollo3.h + * @brief CMSIS HeaderFile + * @version 1.0 + * @date 10. August 2018 + * @note Generated by SVDConv V3.3.18 on Friday, 10.08.2018 16:52:09 + * from File 'apollo3.svd', + * last modified on Friday, 10.08.2018 20:01:31 + */ + + +#ifndef SYSTEM_APOLLO3_H +#define SYSTEM_APOLLO3_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock) + +//***************************************************************************** +// +// External function definitions +// +//***************************************************************************** +extern void SystemInit (void); +extern void SystemCoreClockUpdate (void); + +#ifdef __cplusplus +} +#endif + +#endif // SYSTEM_APOLLO3_H + diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc new file mode 100644 index 0000000000..c0365d5690 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.cc @@ -0,0 +1,33 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" + +namespace { +int16_t g_dummy_audio_data[kMaxAudioSampleSize]; +} // namespace + +TfLiteStatus GetAudioSamples(tflite::ErrorReporter* error_reporter, + int start_ms, int duration_ms, + int* audio_samples_size, int16_t** audio_samples) { + for (int i = 0; i < kMaxAudioSampleSize; ++i) { + g_dummy_audio_data[i] = 0; + } + *audio_samples_size = kMaxAudioSampleSize; + *audio_samples = g_dummy_audio_data; + return kTfLiteOk; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h new file mode 100644 index 0000000000..7e2442a5e8 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h @@ -0,0 +1,36 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_AUDIO_PROVIDER_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_AUDIO_PROVIDER_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" + +// This is an abstraction around an audio source like a microphone, and is +// expected to return 16-bit PCM sample data for a given point in time. The +// sample data itself should be used as quickly as possible by the caller, since +// to allow memory optimizations there are no guarantees that the samples won't +// be overwritten by new data in the future. In practice, implementations should +// ensure that there's a reasonable time allowed for clients to access the data +// before any reuse. +// The reference implementation can have no platform-specific dependencies, so +// it just returns an array filled with zeros. For real applications, you should +// ensure there's a specialized implementation that accesses hardware APIs. +TfLiteStatus GetAudioSamples(tflite::ErrorReporter* error_reporter, + int start_ms, int duration_ms, + int* audio_samples_size, int16_t** audio_samples); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_AUDIO_PROVIDER_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_test.cc new file mode 100644 index 0000000000..5f7c7605f0 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider_test.cc @@ -0,0 +1,44 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(TestAudioProvider) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + int audio_samples_size = 0; + int16_t* audio_samples = nullptr; + TfLiteStatus get_status = + GetAudioSamples(error_reporter, 0, kFeatureSliceDurationMs, + &audio_samples_size, &audio_samples); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, get_status); + TF_LITE_MICRO_EXPECT_LE(audio_samples_size, kMaxAudioSampleSize); + TF_LITE_MICRO_EXPECT_NE(audio_samples, nullptr); + + // Make sure we can read all of the returned memory locations. + int total = 0; + for (int i = 0; i < audio_samples_size; ++i) { + total += audio_samples[i]; + } +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc new file mode 100644 index 0000000000..c4c52ac0ff --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.cc @@ -0,0 +1,121 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h" + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/audio_provider.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/timer.h" + +namespace { +// Stores the timestamp for the previous fetch of audio data, so that we can +// avoid recalculating all the features from scratch if some earlier timeslices +// are still present. +int32_t g_last_time_in_ms = 0; +// Make sure we don't try to use cached information if this is the first call +// into the provider. +bool g_is_first_run = true; +} // namespace + +FeatureProvider::FeatureProvider(int feature_size, uint8_t* feature_data) + : feature_size_(feature_size), feature_data_(feature_data) { + // Initialize the feature data to default values. + for (int n = 0; n < feature_size_; ++n) { + feature_data_[n] = 0; + } +} + +FeatureProvider::~FeatureProvider() {} + +TfLiteStatus FeatureProvider::PopulateFeatureData( + tflite::ErrorReporter* error_reporter, int* how_many_new_slices) { + if (feature_size_ != kFeatureElementCount) { + error_reporter->Report("Requested feature_data_ size %d doesn't match %d", + feature_size_, kFeatureElementCount); + return kTfLiteError; + } + + const int32_t time_in_ms = TimeInMilliseconds(); + // Quantize the time into steps as long as each window stride, so we can + // figure out which audio data we need to fetch. + const int last_step = (g_last_time_in_ms / kFeatureSliceStrideMs); + const int current_step = (time_in_ms / kFeatureSliceStrideMs); + g_last_time_in_ms = time_in_ms; + + int slices_needed = current_step - last_step; + // If this is the first call, make sure we don't use any cached information. + if (g_is_first_run) { + g_is_first_run = false; + slices_needed = kFeatureSliceCount; + } + if (slices_needed > kFeatureSliceCount) { + slices_needed = kFeatureSliceCount; + } + *how_many_new_slices = slices_needed; + + const int slices_to_keep = kFeatureSliceCount - slices_needed; + const int slices_to_drop = kFeatureSliceCount - slices_to_keep; + // If we can avoid recalculating some slices, just move the existing data + // up in the spectrogram, to perform something like this: + // last time = 80ms current time = 120ms + // +-----------+ +-----------+ + // | data@20ms | --> | data@60ms | + // +-----------+ -- +-----------+ + // | data@40ms | -- --> | data@80ms | + // +-----------+ -- -- +-----------+ + // | data@60ms | -- -- | | + // +-----------+ -- +-----------+ + // | data@80ms | -- | | + // +-----------+ +-----------+ + if (slices_to_keep > 0) { + for (int dest_slice = 0; dest_slice < slices_to_keep; ++dest_slice) { + uint8_t* dest_slice_data = + feature_data_ + (dest_slice * kFeatureSliceSize); + const int src_slice = dest_slice + slices_to_drop; + const uint8_t* src_slice_data = + feature_data_ + (src_slice * kFeatureSliceSize); + for (int i = 0; i < kFeatureSliceSize; ++i) { + dest_slice_data[i] = src_slice_data[i]; + } + } + } + // Any slices that need to be filled in with feature data have their + // appropriate audio data pulled, and features calculated for that slice. + if (slices_needed > 0) { + for (int new_slice = slices_to_keep; new_slice < kFeatureSliceCount; + ++new_slice) { + const int new_step = (current_step - kFeatureSliceCount + 1) + new_slice; + const int32_t slice_start_ms = (new_step * kFeatureSliceStrideMs); + int16_t* audio_samples = nullptr; + int audio_samples_size = 0; + GetAudioSamples(error_reporter, slice_start_ms, kFeatureSliceDurationMs, + &audio_samples_size, &audio_samples); + if (audio_samples_size < kMaxAudioSampleSize) { + error_reporter->Report("Audio data size %d too small, want %d", + audio_samples_size, kMaxAudioSampleSize); + return kTfLiteError; + } + uint8_t* new_slice_data = feature_data_ + (new_slice * kFeatureSliceSize); + TfLiteStatus preprocess_status = + Preprocess(error_reporter, audio_samples, audio_samples_size, + kFeatureSliceSize, new_slice_data); + if (preprocess_status != kTfLiteOk) { + return preprocess_status; + } + } + } + return kTfLiteOk; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h new file mode 100644 index 0000000000..a86c56ebf0 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h @@ -0,0 +1,48 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_FEATURE_PROVIDER_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_FEATURE_PROVIDER_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" + +// Binds itself to an area of memory intended to hold the input features for an +// audio-recognition neural network model, and fills that data area with the +// features representing the current audio input, for example from a microphone. +// The audio features themselves are a two-dimensional array, made up of +// horizontal slices representing the frequencies at one point in time, stacked +// on top of each other to form a spectrogram showing how those frequencies +// changed over time. +class FeatureProvider { + public: + // Create the provider, and bind it to an area of memory. This memory should + // remain accessible for the lifetime of the provider object, since subsequent + // calls will fill it with feature data. The provider does no memory + // management of this data. + FeatureProvider(int feature_size, uint8_t* feature_data); + ~FeatureProvider(); + + // Fills the feature data with information from audio inputs, and returns how + // many feature slices were updated. + TfLiteStatus PopulateFeatureData(tflite::ErrorReporter* error_reporter, + int* how_many_new_slices); + + private: + int feature_size_; + uint8_t* feature_data_; +}; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_FEATURE_PROVIDER_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc new file mode 100644 index 0000000000..1e52aec8d2 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider_test.cc @@ -0,0 +1,38 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(TestFeatureProvider) { + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + uint8_t feature_data[kFeatureElementCount]; + FeatureProvider feature_provider(kFeatureElementCount, feature_data); + + int how_many_new_slices = 0; + TfLiteStatus populate_status = feature_provider.PopulateFeatureData( + error_reporter, &how_many_new_slices); + TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, populate_status); + TF_LITE_MICRO_EXPECT_EQ(kFeatureSliceCount, how_many_new_slices); +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc index de60c982f3..b623d8d11b 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc @@ -31,6 +31,8 @@ limitations under the License. #include +#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" + namespace { // q format notation: qx.y => 1 sign bit, x-1 integer bits, y fraction bits. @@ -66,13 +68,6 @@ inline int32_t FloatToFixed_Q2_30(float input) { return static_cast(roundf(input * (1 << 30))); } -// These constants allow us to allocate fixed-sized arrays on the stack for our -// working memory. -constexpr int kInputSize = 512; -constexpr int kAverageWindowSize = 6; -constexpr int kOutputSize = - ((kInputSize / 2) + (kAverageWindowSize - 1)) / kAverageWindowSize; - // Performs a discrete Fourier transform on the real inputs. This corresponds to // rdft() in the FFT package at http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html, // and to kiss_fftr() in KISSFFT at https://github.com/mborgerding/kissfft. @@ -127,14 +122,14 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, const int16_t* input, int input_size, int output_size, uint8_t* output) { // Ensure our input and output data arrays are valid. - if (input_size > kInputSize) { + if (input_size > kMaxAudioSampleSize) { error_reporter->Report("Input size %d larger than %d", input_size, - kInputSize); + kMaxAudioSampleSize); return kTfLiteError; } - if (output_size != kOutputSize) { + if (output_size != kFeatureSliceSize) { error_reporter->Report("Requested output size %d doesn't match %d", - output_size, kOutputSize); + output_size, kFeatureSliceSize); return kTfLiteError; } @@ -142,18 +137,17 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, // In a real application, we'd calculate this table once in an initialization // function and store it for repeated reuse. // q1.15 format. - int16_t window_function[kInputSize]; + int16_t window_function[kMaxAudioSampleSize]; CalculatePeriodicHann(input_size, window_function); // Apply the window function to our time series input, and pad it with zeroes // to the next power of two. - int32_t fixed_input[kInputSize]; - for (int i = 0; i < kInputSize; ++i) { + int32_t fixed_input[kMaxAudioSampleSize]; + for (int i = 0; i < kMaxAudioSampleSize; ++i) { if (i < input_size) { // input is int16_t. Treat as q1.15 fixed point value in range [-1,1) // window_function is also q1.15 fixed point number - fixed_input[i] = - Q1_15_FixedMultiply_Q2_30(input[i], window_function[i]); + fixed_input[i] = Q1_15_FixedMultiply_Q2_30(input[i], window_function[i]); } else { fixed_input[i] = 0; } @@ -161,31 +155,31 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, // Pull the frequency data from the time series sample. // Calculated in q10.22 format from q2.30 inputs. - int32_t fourier_values[kInputSize]; - CalculateDiscreteFourierTransform(fixed_input, kInputSize, fourier_values); + int32_t fourier_values[kMaxAudioSampleSize]; + CalculateDiscreteFourierTransform(fixed_input, kMaxAudioSampleSize, + fourier_values); // We have the complex numbers giving us information about each frequency // band, but all we want to know is how strong each frequency is, so calculate // the squared magnitude by adding together the squares of each component. - int32_t power_spectrum[kInputSize / 2]; - for (int i = 0; i < (kInputSize / 2); ++i) { + int32_t power_spectrum[kMaxAudioSampleSize / 2]; + for (int i = 0; i < (kMaxAudioSampleSize / 2); ++i) { const int32_t real = fourier_values[(i * 2) + 0]; const int32_t imaginary = fourier_values[(i * 2) + 1]; // q10.22 results - power_spectrum[i] = - Q10_22_FixedMultiply_Q10_22(real, real) + - Q10_22_FixedMultiply_Q10_22(imaginary, imaginary); + power_spectrum[i] = Q10_22_FixedMultiply_Q10_22(real, real) + + Q10_22_FixedMultiply_Q10_22(imaginary, imaginary); } // Finally, reduce the size of the output by averaging together six adjacent // frequencies into each slot, producing an array of 43 values. // Power_spectrum numbers are q10.22. Divide by kAverageWindowSize inside // loop to prevent overflow. - for (int i = 0; i < kOutputSize; ++i) { + for (int i = 0; i < kFeatureSliceSize; ++i) { int32_t average = 0; for (int j = 0; j < kAverageWindowSize; ++j) { const int index = (i * kAverageWindowSize) + j; - if (index < (kInputSize / 2)) { + if (index < (kMaxAudioSampleSize / 2)) { average += power_spectrum[index] / kAverageWindowSize; } } diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/main.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/main.cc new file mode 100644 index 0000000000..1890c25cf2 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/main.cc @@ -0,0 +1,112 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/feature_provider.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h" +#include "tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/micro_interpreter.h" +#include "tensorflow/lite/schema/schema_generated.h" +#include "tensorflow/lite/version.h" + +int main(int argc, char* argv[]) { + // Set up logging. + tflite::MicroErrorReporter micro_error_reporter; + tflite::ErrorReporter* error_reporter = µ_error_reporter; + + // Map the model into a usable data structure. This doesn't involve any + // copying or parsing, it's a very lightweight operation. + const tflite::Model* model = ::tflite::GetModel(g_tiny_conv_model_data); + if (model->version() != TFLITE_SCHEMA_VERSION) { + error_reporter->Report( + "Model provided is schema version %d not equal " + "to supported version %d.\n", + model->version(), TFLITE_SCHEMA_VERSION); + return 1; + } + + // This pulls in all the operation implementations we need. + tflite::ops::micro::AllOpsResolver resolver; + + // Create an area of memory to use for input, output, and intermediate arrays. + // The size of this will depend on the model you're using, and may need to be + // determined by experimentation. + const int tensor_arena_size = 10 * 1024; + uint8_t tensor_arena[tensor_arena_size]; + tflite::SimpleTensorAllocator tensor_allocator(tensor_arena, + tensor_arena_size); + + // Build an interpreter to run the model with. + tflite::MicroInterpreter interpreter(model, resolver, &tensor_allocator, + error_reporter); + + // Get information about the memory area to use for the model's input. + TfLiteTensor* model_input = interpreter.input(0); + if ((model_input->dims->size != 4) || (model_input->dims->data[0] != 1) || + (model_input->dims->data[1] != kFeatureSliceCount) || + (model_input->dims->data[2] != kFeatureSliceSize) || + (model_input->type != kTfLiteUInt8)) { + error_reporter->Report("Bad input tensor parameters in model"); + return 1; + } + + // Prepare to access the audio spectrograms from a microphone or other source + // that will provide the inputs to the neural network. + FeatureProvider feature_provider(kFeatureElementCount, + model_input->data.uint8); + + // Keep reading and analysing audio data in an infinite loop. + while (true) { + // Fetch the spectrogram for the current time. + int how_many_new_slices = 0; + TfLiteStatus feature_status = feature_provider.PopulateFeatureData( + error_reporter, &how_many_new_slices); + if (feature_status != kTfLiteOk) { + error_reporter->Report("Feature generation failed"); + return 1; + } + // If no new audio samples have been received since last time, don't bother + // running the network model. + if (how_many_new_slices == 0) { + continue; + } + + // Run the model on the spectrogram input and make sure it succeeds. + TfLiteStatus invoke_status = interpreter.Invoke(); + if (invoke_status != kTfLiteOk) { + error_reporter->Report("Invoke failed"); + return 1; + } + + // The output from the model is a vector containing the scores for each + // kind of prediction, so figure out what the highest scoring category was. + TfLiteTensor* output = interpreter.output(0); + uint8_t top_category_score = 0; + int top_category_index = 0; + for (int category_index = 0; category_index < kCategoryCount; + ++category_index) { + const uint8_t category_score = output->data.uint8[category_index]; + if (category_score > top_category_score) { + top_category_score = category_score; + top_category_index = category_index; + } + } + + error_reporter->Report("Heard %s", kCategoryLabels[top_category_index]); + } + + return 0; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc similarity index 73% rename from tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc index a3e561a8b5..b9b8fb37b1 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.cc @@ -13,8 +13,11 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -// See the header for documentation on the meaning of this data. +#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.h" - -const uint8_t g_no_power_spectrum_data[g_no_power_spectrum_data_size] = {233,6,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,40}; +const char* kCategoryLabels[kCategoryCount] = { + "silence", + "unknown", + "yes", + "no", +}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h b/tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h new file mode 100644 index 0000000000..1d8f3123a5 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h @@ -0,0 +1,42 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MODEL_SETTINGS_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MODEL_SETTINGS_H_ + +// Keeping these as constant expressions allow us to allocate fixed-sized arrays +// on the stack for our working memory. + +// The size of the input time series data we pass to the FFT to produce the +// frequency information. This has to be a power of two, and since we're dealing +// with 30ms of 16KHz inputs, which means 480 samples, this is the next value. +constexpr int kMaxAudioSampleSize = 512; + +// All of these values are derived from the values used during model training, +// if you change your model you'll need to update these constants. +constexpr int kAverageWindowSize = 6; +constexpr int kFeatureSliceSize = + ((kMaxAudioSampleSize / 2) + (kAverageWindowSize - 1)) / kAverageWindowSize; +constexpr int kFeatureSliceCount = 49; +constexpr int kFeatureElementCount = (kFeatureSliceSize * kFeatureSliceCount); +constexpr int kFeatureSliceStrideMs = 20; +constexpr int kFeatureSliceDurationMs = 30; + +constexpr int kCategoryCount = 4; +constexpr int kSilenceIndex = 0; +constexpr int kUnknownIndex = 1; +extern const char* kCategoryLabels[kCategoryCount]; + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_MODEL_SETTINGS_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc index 12f9e22038..743d229224 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc @@ -28,14 +28,9 @@ limitations under the License. #include -namespace { +#include "tensorflow/lite/experimental/micro/examples/micro_speech/model_settings.h" -// These constants allow us to allocate fixed-sized arrays on the stack for our -// working memory. -constexpr int kInputSize = 512; -constexpr int kAverageWindowSize = 6; -constexpr int kOutputSize = - ((kInputSize / 2) + (kAverageWindowSize - 1)) / kAverageWindowSize; +namespace { // Performs a discrete Fourier transform on the real inputs. This corresponds to // rdft() in the FFT package at http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html, @@ -78,27 +73,27 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, const int16_t* input, int input_size, int output_size, uint8_t* output) { // Ensure our input and output data arrays are valid. - if (input_size > kInputSize) { + if (input_size > kMaxAudioSampleSize) { error_reporter->Report("Input size %d larger than %d", input_size, - kInputSize); + kMaxAudioSampleSize); return kTfLiteError; } - if (output_size != kOutputSize) { + if (output_size != kFeatureSliceSize) { error_reporter->Report("Requested output size %d doesn't match %d", - output_size, kOutputSize); + output_size, kFeatureSliceSize); return kTfLiteError; } // Pre-calculate the window function we'll be applying to the input data. // In a real application, we'd calculate this table once in an initialization // function and store it for repeated reuse. - float window_function[kInputSize]; + float window_function[kMaxAudioSampleSize]; CalculatePeriodicHann(input_size, window_function); // Apply the window function to our time series input, and pad it with zeroes // to the next power of two. - float float_input[kInputSize]; - for (int i = 0; i < kInputSize; ++i) { + float float_input[kMaxAudioSampleSize]; + for (int i = 0; i < kMaxAudioSampleSize; ++i) { if (i < input_size) { float_input[i] = (input[i] * window_function[i]) / static_cast(1 << 15); @@ -108,14 +103,15 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, } // Pull the frequency data from the time series sample. - float fourier_values[kInputSize]; - CalculateDiscreteFourierTransform(float_input, kInputSize, fourier_values); + float fourier_values[kMaxAudioSampleSize]; + CalculateDiscreteFourierTransform(float_input, kMaxAudioSampleSize, + fourier_values); // We have the complex numbers giving us information about each frequency // band, but all we want to know is how strong each frequency is, so calculate // the squared magnitude by adding together the squares of each component. - float power_spectrum[kInputSize / 2]; - for (int i = 0; i < (kInputSize / 2); ++i) { + float power_spectrum[kMaxAudioSampleSize / 2]; + for (int i = 0; i < (kMaxAudioSampleSize / 2); ++i) { const float real = fourier_values[(i * 2) + 0]; const float imaginary = fourier_values[(i * 2) + 1]; power_spectrum[i] = (real * real) + (imaginary * imaginary); @@ -123,11 +119,11 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, // Finally, reduce the size of the output by averaging together six adjacent // frequencies into each slot, producing an array of 43 values. - for (int i = 0; i < kOutputSize; ++i) { + for (int i = 0; i < kFeatureSliceSize; ++i) { float total = 0.0f; for (int j = 0; j < kAverageWindowSize; ++j) { const int index = (i * kAverageWindowSize) + j; - if (index < (kInputSize / 2)) { + if (index < (kMaxAudioSampleSize / 2)) { total += power_spectrum[index]; } } @@ -147,3 +143,13 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, } return kTfLiteOk; } + +TfLiteStatus Preprocess_1sec(tflite::ErrorReporter* error_reporter, + const int16_t* input, uint8_t* output) { + int i; + for(i=0; i<49; i++) { + Preprocess(error_reporter, input+i*320, 480, 43, output+i*43); + } + return kTfLiteOk; +} + diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h index dede2a8642..0057b4505f 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h @@ -19,8 +19,16 @@ limitations under the License. #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +// Converts audio sample data into a more compact form that's appropriate for +// feeding into a neural network. There are reference implementations that use +// both floating point and fixed point available, but because the calculations +// involved can be time-consuming, it's recommended that you use or write +// specialized versions for your platform. TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, const int16_t* input, int input_size, int output_size, uint8_t* output); +TfLiteStatus Preprocess_1sec(tflite::ErrorReporter* error_reporter, + const int16_t* input, uint8_t* output); + #endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc index e8b49f67e3..d9b0c48ba3 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc @@ -22,6 +22,7 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/testing/micro_test.h" + TF_LITE_MICRO_TESTS_BEGIN TF_LITE_MICRO_TEST(TestPreprocessor) { diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/timer.cc similarity index 73% rename from tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc rename to tensorflow/lite/experimental/micro/examples/micro_speech/timer.cc index 89edb51040..6c96a61ab5 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/timer.cc @@ -13,8 +13,10 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -// See the header for documentation on the meaning of this data. +#include "tensorflow/lite/experimental/micro/examples/micro_speech/timer.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.h" - -const uint8_t g_yes_power_spectrum_data[g_yes_power_spectrum_data_size] = {8,88,8,0,0,0,0,0,0,0,0,3,12,0,5,22,19,5,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,1}; +int32_t TimeInMilliseconds() { + static int current_time = 0; + current_time += 100; + return current_time; +} diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/timer.h b/tensorflow/lite/experimental/micro/examples/micro_speech/timer.h new file mode 100644 index 0000000000..162952844a --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/timer.h @@ -0,0 +1,31 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_TIMER_H_ +#define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_TIMER_H_ + +#include + +// Returns the time in milliseconds. There's no contract about what time zero +// represents, the accuracy, or the granularity of the result. Subsequent calls +// will generally not return a lower value, but even that's not guaranteed if +// there's an overflow wraparound. +// The reference implementation of this function just returns a constantly +// incrementing value for each call, since it would need a non-portable platform +// call to access time information. For real applications, you'll need to write +// your own platform-specific implementation. +int32_t TimeInMilliseconds(); + +#endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_TIMER_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/timer_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/timer_test.cc new file mode 100644 index 0000000000..0487a12b25 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/timer_test.cc @@ -0,0 +1,49 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/experimental/micro/examples/micro_speech/timer.h" + +#include + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" + +TF_LITE_MICRO_TESTS_BEGIN + +TF_LITE_MICRO_TEST(TestTimer) { + // Make sure that the technically-undefined overflow behavior we rely on below + // works on this platform. It's still not guaranteed, but at least this is a + // sanity check. Turn off when running with ASan, as it will complain about + // the following undefined behavior. +#ifndef ADDRESS_SANITIZER + int32_t overflow_value = std::numeric_limits::max(); + overflow_value += 1; + TF_LITE_MICRO_EXPECT_EQ(std::numeric_limits::min(), overflow_value); +#endif + + const int32_t first_time = TimeInMilliseconds(); + const int32_t second_time = TimeInMilliseconds(); + + // It's possible that the timer may have wrapped around from +BIG_NUM to + // -BIG_NUM between the first and second calls, since we're storing + // milliseconds in a 32-bit integer. It's not reasonable that the call itself + // would have taken more than 2^31 milliseconds though, so look at the + // difference and rely on integer overflow to ensure it's accurate. + const int32_t time_delta = (second_time - first_time); + TF_LITE_MICRO_EXPECT_LE(0, time_delta); +} + +TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/testing/micro_test.h b/tensorflow/lite/experimental/micro/testing/micro_test.h index 10bab05fae..2f20dd5ac7 100644 --- a/tensorflow/lite/experimental/micro/testing/micro_test.h +++ b/tensorflow/lite/experimental/micro/testing/micro_test.h @@ -153,4 +153,22 @@ extern tflite::ErrorReporter* reporter; } \ } while (false) +#define TF_LITE_MICRO_EXPECT_GE(x, y) \ + do { \ + if ((x) < (y)) { \ + micro_test::reporter->Report(#x " >= " #y " failed at %s:%d", __FILE__, \ + __LINE__); \ + micro_test::did_test_fail = true; \ + } \ + } while (false) + +#define TF_LITE_MICRO_EXPECT_LE(x, y) \ + do { \ + if ((x) > (y)) { \ + micro_test::reporter->Report(#x " <= " #y " failed at %s:%d", __FILE__, \ + __LINE__); \ + micro_test::did_test_fail = true; \ + } \ + } while (false) + #endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_TESTING_MICRO_TEST_H_ diff --git a/tensorflow/lite/experimental/micro/tools/make/Makefile b/tensorflow/lite/experimental/micro/tools/make/Makefile index 463709a6e5..3f6f927358 100644 --- a/tensorflow/lite/experimental/micro/tools/make/Makefile +++ b/tensorflow/lite/experimental/micro/tools/make/Makefile @@ -59,13 +59,27 @@ tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc +# Test binary for the streaming microcontroller speech model. +PUSHBUTTON_MICRO_SPEECH_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc + +# Test binary for the streaming microcontroller speech model. +PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc + # Test binary for the microcontroller speech model. PREPROCESSOR_TEST_SRCS := \ tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc +tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_waveform.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc PREPROCESSOR_REFERENCE_TEST_SRCS = \ $(PREPROCESSOR_TEST_SRCS) \ @@ -75,6 +89,11 @@ PREPROCESSOR_FIXED_TEST_SRCS += \ $(PREPROCESSOR_TEST_SRCS) \ tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc +PREPROCESSOR_1K_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc + + MICROLITE_TEST_SRCS := \ $(wildcard tensorflow/lite/experimental/micro/*test.cc) \ $(wildcard tensorflow/lite/experimental/micro/kernels/*test.cc) @@ -101,6 +120,8 @@ ALL_SRCS := \ $(PREPROCESSOR_REFERENCE_TEST_SRCS) \ $(PREPROCESSOR_FIXED_TEST_SRCS) \ $(MICROLITE_CC_SRCS) \ + $(PREPROCESSOR_1K_MICRO_TEST_SRCS) \ + $(PREPROCESSOR_1K_CMSIS_TEST_SRCS) \ $(MICROLITE_TEST_SRCS) # Where compiled objects are stored. @@ -112,8 +133,12 @@ LIBDIR := $(GENDIR)lib/ MICROLITE_LIB_PATH := $(LIBDIR)$(MICROLITE_LIB_NAME) MICRO_SPEECH_TEST_BINARY := $(BINDIR)micro_speech_test +PUSHBUTTON_MICRO_SPEECH_TEST_BINARY := $(BINDIR)pushbutton_micro_speech_test +PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY := $(BINDIR)pushbutton_cmsis_speech_test PREPROCESSOR_REFERENCE_TEST_BINARY := $(BINDIR)preprocessor_reference_test PREPROCESSOR_FIXED_TEST_BINARY := $(BINDIR)preprocessor_fixed_test +PREPROCESSOR_1K_MICRO_TEST_BINARY := $(BINDIR)preprocessor_1k_micro_test +PREPROCESSOR_1K_CMSIS_TEST_BINARY := $(BINDIR)preprocessor_1k_cmsis_test CXX := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}g++ CC := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}gcc @@ -128,6 +153,13 @@ $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_REFERENCE_TEST_SRCS)))) PREPROCESSOR_FIXED_TEST_OBJS := $(addprefix $(OBJDIR), \ $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_FIXED_TEST_SRCS)))) +PREPROCESSOR_1K_MICRO_TEST_OBJS := $(addprefix $(OBJDIR), \ +$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_1K_MICRO_TEST_SRCS)))) + +PREPROCESSOR_1K_CMSIS_TEST_OBJS := $(addprefix $(OBJDIR), \ +$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_1K_CMSIS_TEST_SRCS))) \ +arm_bitreversal2.o) + MICROLITE_LIB_OBJS := $(addprefix $(OBJDIR), \ $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(MICROLITE_CC_SRCS)))) @@ -194,6 +226,35 @@ preprocessor_fixed_test_bin: $(PREPROCESSOR_FIXED_TEST_BINARY).bin test_preprocessor_fixed: $(PREPROCESSOR_FIXED_TEST_BINARY) $(TEST_SCRIPT) $(PREPROCESSOR_FIXED_TEST_BINARY) '~~~ALL TESTS PASSED~~~' +$(PREPROCESSOR_1K_MICRO_TEST_BINARY): $(PREPROCESSOR_1K_MICRO_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PREPROCESSOR_1K_MICRO_TEST_BINARY) $(PREPROCESSOR_1K_MICRO_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + +preprocessor_1k_micro_test: $(PREPROCESSOR_1K_MICRO_TEST_BINARY) +preprocessor_1k_micro_test_bin: $(PREPROCESSOR_1K_MICRO_TEST_BINARY).bin + +test_preprocessor_1k_micro: $(PREPROCESSOR_1K_MICRO_TEST_BINARY) + $(TEST_SCRIPT) $(PREPROCESSOR_1K_MICRO_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + + +$(PREPROCESSOR_1K_CMSIS_TEST_BINARY): $(PREPROCESSOR_1K_CMSIS_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) $(PREPROCESSOR_1K_CMSIS_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + +preprocessor_1k_cmsis_test: $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) +preprocessor_1k_cmsis_test_bin: $(PREPROCESSOR_1K_CMSIS_TEST_BINARY).bin + +test_preprocessor_1k_cmsis: $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) + $(TEST_SCRIPT) $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + + +$(OBJDIR)arm_bitreversal2.o: + $(CXX) $(CXXFLAGS) $(INCLUDES) -c $(CMSIS_SRC_DIR)/TransformFunctions/arm_bitreversal2.S -o $(OBJDIR)arm_bitreversal2.o + $(BINDIR)%_test : $(OBJDIR)%_test.o $(MICROLITE_LIB_PATH) @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $(INCLUDES) \ diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md deleted file mode 100644 index fec4923e0e..0000000000 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/README.md +++ /dev/null @@ -1,13 +0,0 @@ -Follow these steps to get the preprocessor test working on Apollo 3: - -1. Download the SDK to the be at the same level as tensorflow.git -2. Copy and prepare files by running tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh -3. Recompile libarm_cortexM4lf_math.a with the softfp option, and call it libarm_cartexM4lf_math_softfp.a. The original version was compiled with the hard option, and this caused conflicts with existing software. We might be able to fix this in the future -4. Install Segger JLink tools from https://www.segger.com/downloads/jlink/ -5. Compile the preprocessor_test_bin project with the following command: make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=apollo3evb VENDORLIB=cmsis-dsp preprocessor_test_bin -6. Download to the target with JFlashLiteExe with the following settings: - 1. Device = AMA3B1KK-KBR - 2. Interface = SWD at 1000 kHz - 3. Data file = tensorflow/lite/experimental/micro/tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_test.bin - 4. Prog Addr = 0x0000C000 -7. Connect to device via serial port (115200 baud) and press reset button. Should see all tests passed. Seeing a discrepance between Windows and Linux testing --> need to debug diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/get_yesno_data.cmd b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/get_yesno_data.cmd deleted file mode 100644 index 71d5389ee3..0000000000 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/get_yesno_data.cmd +++ /dev/null @@ -1,10 +0,0 @@ -file ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test -target remote localhost:2331 -load ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test -monitor reset -break preprocessor_test.cc:35 -break preprocessor_test.cc:51 -c -dump verilog value yes_calculated_data.txt yes_calculated_data -c -dump verilog value no_calculated_data.txt no_calculated_data diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh index 79ce18f11f..7ef2309502 100755 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh @@ -14,19 +14,22 @@ # limitations under the License. # ============================================================================== -if [ ! -d "../Apollo3-SDK-2018.08.13" ]; then +AP3_DIR="tensorflow/lite/experimental/micro/tools/make/downloads/Apollo3-SDK-2018.08.13" +if [ ! -d $AP3_DIR ]; then echo "Apollo 3 SDK does not exist" - echo "Either the SDK has not been downloaded, or this script is not being done from the root of the repository" + echo "Either the SDK has not been downloaded, or this script is not being run from the root of the repository" else DEST_DIR="tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb" - AP3_DIR="../Apollo3-SDK-2018.08.13" cp "$AP3_DIR/boards/apollo3_evb/examples/hello_world/gcc/startup_gcc.c" "$DEST_DIR" - cp "$AP3_DIR/utils/am_util_delay.c" "$DEST_DIR" - cp "$AP3_DIR/utils/am_util_faultisr.c" "$DEST_DIR" - cp "$AP3_DIR/utils/am_util_id.c" "$DEST_DIR" - cp "$AP3_DIR/utils/am_util_stdio.c" "$DEST_DIR" - cp "$AP3_DIR/boards/apollo3_evb/bsp/gcc/bin/libam_bsp.a" "$DEST_DIR" - cp "$AP3_DIR/mcu/apollo3/hal/gcc/bin/libam_hal.a" "$DEST_DIR" + cp "$AP3_DIR/boards/apollo3_evb/examples/hello_world/gcc/hello_world.ld" "$DEST_DIR/apollo3evb.ld" sed -i -e '131s/1024/1024\*20/g' "$DEST_DIR/startup_gcc.c" sed -i -e 's/main/_main/g' "$DEST_DIR/startup_gcc.c" + sed -i -e '3s/hello_world.ld/apollo3evb.ld/g' "$DEST_DIR/apollo3evb.ld" + sed -i -e '3s/startup_gnu/startup_gcc/g' "$DEST_DIR/apollo3evb.ld" + sed -i -e '6s/am_reset_isr/Reset_Handler/g' "$DEST_DIR/apollo3evb.ld" + sed -i -e '22s/\*(.text\*)/\*(.text\*)\n\n\t\/\* These are the C++ global constructors. Stick them all here and\n\t \* then walk through the array in main() calling them all.\n\t \*\/\n\t_init_array_start = .;\n\tKEEP (\*(SORT(.init_array\*)))\n\t_init_array_end = .;\n\n\t\/\* XXX Currently not doing anything for global destructors. \*\/\n/g' "$DEST_DIR/apollo3evb.ld" + sed -i -e "70s/} > SRAM/} > SRAM\n \/\* Add this to satisfy reference to symbol 'end' from libnosys.a(sbrk.o)\n \* to denote the HEAP start.\n \*\/\n end = .;/g" "$DEST_DIR/apollo3evb.ld" + echo "Finished preparing Apollo3 files" + + fi diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/preprocessor_test.cmd b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/preprocessor_test.cmd deleted file mode 100644 index 1b1db457fe..0000000000 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/preprocessor_test.cmd +++ /dev/null @@ -1,4 +0,0 @@ -file ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test -target remote localhost:2331 -load ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test -monitor reset diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/replace_calculated_data.py b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/replace_calculated_data.py deleted file mode 100644 index 3c1b0110fc..0000000000 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/replace_calculated_data.py +++ /dev/null @@ -1,33 +0,0 @@ -import numpy as np -import re - -# This should be run from make/targets/apollo3evb - -def new_data_to_array(fn): - vals = [] - with open(fn) as f: - for n, line in enumerate(f): - if n is not 0: - vals.extend([str(int(v, 16)) for v in line.split()]) - - return ','.join(vals) - -def replace_data(fn_old, new_data): - patt = '(?<=\{).+?(?=\})' - with open(fn_old,'r') as f: - str_old = f.read() - str_new = re.sub(patt, new_data, str_old, flags=re.DOTALL) - with open(fn_old,'w') as f: - f.write(str_new) - - -yes_old = '../../../../examples/micro_speech/CMSIS/yes_power_spectrum_data.cc' -no_old = '../../../../examples/micro_speech/CMSIS/no_power_spectrum_data.cc' -yes_new = 'yes_calculated_data.txt' -no_new = 'no_calculated_data.txt' - -yes_new_vals = new_data_to_array(yes_new) -no_new_vals = new_data_to_array(no_new) - -replace_data(yes_old, yes_new_vals) -replace_data(no_old, no_new_vals) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc index 153a19fcd4..3db4367a17 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc @@ -4,10 +4,10 @@ ifeq ($(TARGET), apollo3evb) TARGET_TOOLCHAIN_PREFIX := arm-none-eabi- # Download the Ambiq Apollo3 SDK and set this variable to find the header # files: - APOLLO3_SDK := ../Apollo3-SDK-2018.08.13 + APOLLO3_SDK := $(MAKEFILE_DIR)/downloads/Apollo3-SDK-2018.08.13 # Need a pointer to the GNU ARM toolchain for crtbegin.o for the fp functions # with the softfp interfaces. - GCC_ARM := ../gcc-arm-none-eabi-7-2018-q2-update/ + GCC_ARM := $(MAKEFILE_DIR)/downloads/gcc-arm-none-eabi-7-2018-q2-update/ PLATFORM_FLAGS = \ -DPART_apollo3 \ @@ -17,6 +17,7 @@ ifeq ($(TARGET), apollo3evb) -DTF_LITE_STATIC_MEMORY \ -DTF_LITE_MCU_DEBUG_LOG \ -D __FPU_PRESENT=1 \ + -DARM_MATH_CM4 \ -fno-rtti \ -fmessage-length=0 \ -fno-exceptions \ @@ -42,7 +43,7 @@ ifeq ($(TARGET), apollo3evb) -fomit-frame-pointer \ -fpermissive \ -nostdlib \ - -g \ + -ggdb \ -O3 CXXFLAGS += $(PLATFORM_FLAGS) CCFLAGS += $(PLATFORM_FLAGS) @@ -56,11 +57,9 @@ ifeq ($(TARGET), apollo3evb) -Wl,-T,$(MAKEFILE_DIR)/targets/apollo3evb/apollo3evb.ld \ -Wl,-Map=$(MAKEFILE_DIR)/gen/$(TARGET).map,--cref BUILD_TYPE := micro - # The apollo3evb libs should be copied from the SDK after building them. MICROLITE_LIBS := \ - $(MAKEFILE_DIR)/targets/apollo3evb/libam_bsp.a \ - $(MAKEFILE_DIR)/targets/apollo3evb/libam_hal.a \ - $(MAKEFILE_DIR)/downloads/cmsis/CMSIS/Lib/GCC/libarm_cortexM4lf_math_softfp.a \ + $(APOLLO3_SDK)/boards/apollo3_evb/bsp/gcc/bin/libam_bsp.a \ + $(APOLLO3_SDK)/mcu/apollo3/hal/gcc/bin/libam_hal.a \ $(GCC_ARM)/lib/gcc/arm-none-eabi/7.3.1/thumb/v7e-m/fpv4-sp/softfp/crtbegin.o \ -lm INCLUDES += \ @@ -83,11 +82,63 @@ ifeq ($(TARGET), apollo3evb) # of the DebugLog interfaces. MICROLITE_CC_SRCS += \ $(MAKEFILE_DIR)/targets/apollo3evb/startup_gcc.c \ - $(MAKEFILE_DIR)/targets/apollo3evb/_main.c \ - $(MAKEFILE_DIR)/targets/apollo3evb/am_util_delay.c \ - $(MAKEFILE_DIR)/targets/apollo3evb/am_util_faultisr.c \ - $(MAKEFILE_DIR)/targets/apollo3evb/am_util_id.c \ - $(MAKEFILE_DIR)/targets/apollo3evb/am_util_stdio.c + $(APOLLO3_SDK)/utils/am_util_delay.c \ + $(APOLLO3_SDK)/utils/am_util_faultisr.c \ + $(APOLLO3_SDK)/utils/am_util_id.c \ + $(APOLLO3_SDK)/utils/am_util_stdio.c + + CMSIS_SRC_DIR := tensorflow/lite/experimental/micro/tools/make/downloads/cmsis/CMSIS/DSP/Source + CMSIS_SRCS := \ + $(CMSIS_SRC_DIR)/BasicMathFunctions/arm_mult_q15.c \ + $(CMSIS_SRC_DIR)/TransformFunctions/arm_rfft_init_q15.c \ + $(CMSIS_SRC_DIR)/TransformFunctions/arm_rfft_q15.c \ + $(CMSIS_SRC_DIR)/TransformFunctions/arm_cfft_q15.c \ + $(CMSIS_SRC_DIR)/TransformFunctions/arm_cfft_radix4_q15.c \ + $(CMSIS_SRC_DIR)/CommonTables/arm_const_structs.c \ + $(CMSIS_SRC_DIR)/CommonTables/arm_common_tables.c \ + $(CMSIS_SRC_DIR)/StatisticsFunctions/arm_mean_q15.c \ + $(CMSIS_SRC_DIR)/StatisticsFunctions/arm_max_q7.c + + AP3_MICRO_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/apollo3 + CMSIS_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS + + MICRO_SPEECH_TEST_SRCS += \ + $(AP3_MICRO_DIR)/_main.c + + PREPROCESSOR_1K_CMSIS_TEST_SRCS := \ + $(PREPROCESSOR_1K_SRCS) \ + $(CMSIS_DIR)/preprocessor.cc \ + $(CMSIS_DIR)/arm_cmplx_mag_squared_q10p6.c \ + $(CMSIS_DIR)/hanning.c \ + $(AP3_MICRO_DIR)/system_apollo3.c \ + $(AP3_MICRO_DIR)/_main.c \ + $(CMSIS_SRCS) + + PREPROCESSOR_1K_MICRO_TEST_SRCS := \ + $(PREPROCESSOR_1K_SRCS) \ + tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc \ + tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c \ + $(AP3_MICRO_DIR)/_main.c + + PUSHBUTTON_MICRO_SPEECH_TEST_SRCS := \ + $(AP3_MICRO_DIR)/../preprocessor.cc \ + $(AP3_MICRO_DIR)/pushbutton_main.c \ + $(AP3_MICRO_DIR)/pushbutton_test.cc \ + $(AP3_MICRO_DIR)/../tiny_conv_model_data.cc \ + $(APOLLO3_SDK)/devices/am_devices_led.c + + PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS := \ + $(AP3_MICRO_DIR)/pushbutton_main.c \ + $(AP3_MICRO_DIR)/pushbutton_test.cc \ + $(AP3_MICRO_DIR)/../tiny_conv_model_data.cc \ + $(CMSIS_DIR)/preprocessor.cc \ + $(CMSIS_DIR)/arm_cmplx_mag_squared_q10p6.c \ + $(CMSIS_DIR)/hanning.c \ + $(APOLLO3_SDK)/devices/am_devices_led.c \ + $(CMSIS_SRCS) + + PREPROCESSOR_TEST_SRCS += \ + $(AP3_MICRO_DIR)/_main.c TEST_SCRIPT := tensorflow/lite/experimental/log_test/test_apollo3evb_binary.sh # These are tests that don't currently work on the blue pill. @@ -96,4 +147,5 @@ ifeq ($(TARGET), apollo3evb) tensorflow/lite/experimental/micro/simple_tensor_allocator_test.cc MICROLITE_TEST_SRCS := $(filter-out $(EXCLUDED_TESTS), $(MICROLITE_TEST_SRCS)) + endif diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc deleted file mode 100644 index 54b3393229..0000000000 --- a/tensorflow/lite/experimental/micro/tools/make/targets/cmsis-dsp_makefile.inc +++ /dev/null @@ -1,9 +0,0 @@ -ifeq ($(VENDORLIB), cmsis-dsp) -PREPROCESSOR_TEST_SRCS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/no_power_spectrum_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/yes_power_spectrum_data.cc -endif diff --git a/tensorflow/lite/experimental/microfrontend/python/kernel_tests/audio_microfrontend_op_test.py b/tensorflow/lite/experimental/microfrontend/python/kernel_tests/audio_microfrontend_op_test.py index 020d40bc13..561f5f7a50 100644 --- a/tensorflow/lite/experimental/microfrontend/python/kernel_tests/audio_microfrontend_op_test.py +++ b/tensorflow/lite/experimental/microfrontend/python/kernel_tests/audio_microfrontend_op_test.py @@ -110,7 +110,7 @@ class AudioFeatureGenerationTest(tf.test.TestCase): left_context=1, right_context=1) self.assertAllEqual( - filterbanks.eval(), + self.evaluate(filterbanks), [[479, 425, 479, 425, 436, 378], [479, 425, 436, 378, 410, 350], [436, 378, 410, 350, 391, 325], [410, 350, 391, 325, 391, 325]]) @@ -153,7 +153,7 @@ class AudioFeatureGenerationTest(tf.test.TestCase): frame_stride=3, zero_padding=True) self.assertAllEqual( - filterbanks.eval(), + self.evaluate(filterbanks), [[0, 0, 0, 0, 479, 425], [436, 378, 410, 350, 391, 325], [374, 308, 362, 292, 352, 275]]) diff --git a/tensorflow/lite/experimental/writer/BUILD b/tensorflow/lite/experimental/writer/BUILD index 506c668cf2..57ce636367 100644 --- a/tensorflow/lite/experimental/writer/BUILD +++ b/tensorflow/lite/experimental/writer/BUILD @@ -1,6 +1,9 @@ -package(default_visibility = [ - "//visibility:public", -]) +package( + default_visibility = [ + "//visibility:public", + ], + features = ["-parse_headers"], +) licenses(["notice"]) # Apache 2.0 diff --git a/tensorflow/lite/experimental/writer/option_writer_generator.cc b/tensorflow/lite/experimental/writer/option_writer_generator.cc index 036809e94a..fa360a2f47 100644 --- a/tensorflow/lite/experimental/writer/option_writer_generator.cc +++ b/tensorflow/lite/experimental/writer/option_writer_generator.cc @@ -56,6 +56,7 @@ static const char* param_structs[] = {"TfLiteConvParams", "TfLiteTransposeParams", "TfLiteReducerParams", "TfLiteSplitParams", + "TfLiteSplitVParams", "TfLiteSqueezeParams", "TfLiteStridedSliceParams", "TfLiteArgMaxParams", @@ -66,6 +67,8 @@ static const char* param_structs[] = {"TfLiteConvParams", "TfLiteFakeQuantParams", "TfLitePackParams", "TfLiteOneHotParams", + "TfLiteLeakyReluParams", + "TfLiteMirrorPaddingParams", nullptr}; } // namespace @@ -152,6 +155,7 @@ class OpOptionData { op_to_option_["BIDIRECTIONAL_SEQUENCE_RNN"] = "SequenceRNNOptions"; op_to_option_["UNIDIRECTIONAL_SEQUENCE_RNN"] = "SequenceRNNOptions"; op_to_option_["UNIDIRECTIONAL_SEQUENCE_RNN"] = "SequenceRNNOptions"; + op_to_option_["MIRROR_PAD"] = ""; // TODO(karimnosseir): MirrorPadOptions. // Manually specified mappings between ops and options (none) op_to_option_["EMBEDDING_LOOKUP"] = ""; // TODO(aselle): maybe something else. diff --git a/tensorflow/lite/g3doc/_book.yaml b/tensorflow/lite/g3doc/_book.yaml index ab0d186848..a51c7a667f 100644 --- a/tensorflow/lite/g3doc/_book.yaml +++ b/tensorflow/lite/g3doc/_book.yaml @@ -3,11 +3,11 @@ upper_tabs: - include: /_upper_tabs_left.yaml - include: /api_docs/_upper_tabs_api.yaml # Dropdown menu -- name: Ecosystem - path: /ecosystem +- name: Resources + path: /resources is_default: true menu: - - include: /ecosystem/_menu_toc.yaml + - include: /resources/_menu_toc.yaml lower_tabs: # Subsite tabs other: diff --git a/tensorflow/lite/g3doc/_index.yaml b/tensorflow/lite/g3doc/_index.yaml index 093f86b542..1b3f1d616a 100644 --- a/tensorflow/lite/g3doc/_index.yaml +++ b/tensorflow/lite/g3doc/_index.yaml @@ -189,7 +189,7 @@ landing_page: - label: Read more path: https://cloud.google.com/blog/products/ai-machine-learning/ai-motion-designing-simple-system-see-understand-and-react-real-world-part-ii - heading: "Introducing the Model Optimization Toolkit" - image_path: /ecosystem/images/tf-logo-card-16x9.png + image_path: /resources/images/tf-logo-card-16x9.png path: https://medium.com/tensorflow/introducing-the-model-optimization-toolkit-for-tensorflow-254aca1ba0a3 buttons: - label: Read on TensorFlow blog @@ -205,7 +205,7 @@ landing_page: background: grey items: - heading: "Using TensorFlow Lite on Android" - image_path: /ecosystem/images/tf-logo-card-16x9.png + image_path: /resources/images/tf-logo-card-16x9.png path: https://medium.com/tensorflow/using-tensorflow-lite-on-android-9bbc9cb7d69d buttons: - label: Read on TensorFlow blog @@ -216,7 +216,7 @@ landing_page: - label: Watch the video path: https://www.youtube.com/watch?v=FAMfy7izB6A - heading: "TensorFlow Lite on GitHub" - image_path: /ecosystem/images/github-card-16x9.png + image_path: /resources/images/github-card-16x9.png path: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite buttons: - label: View on GitHub diff --git a/tensorflow/lite/g3doc/convert/index.md b/tensorflow/lite/g3doc/convert/index.md index bc92a1c1a1..60fa265c29 100644 --- a/tensorflow/lite/g3doc/convert/index.md +++ b/tensorflow/lite/g3doc/convert/index.md @@ -6,14 +6,20 @@ file used by the TensorFlow Lite interpreter. ## From model training to device deployment After a TensorFlow model is trained, the TensorFlow Lite converter uses that -model to generate a TensorFlow Lite [FlatBuffer](https://google.github.io/flatbuffers/) -file (`.tflite`). The converter supports as input: +model to generate a TensorFlow Lite +[FlatBuffer](https://google.github.io/flatbuffers/) file (`.tflite`). The +converter supports as input: [SavedModels](https://www.tensorflow.org/guide/saved_model#using_savedmodel_with_estimators), frozen graphs (models generated by [freeze_graph.py](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/tools/freeze_graph.py)), -and `tf.keras` models. The TensorFlow Lite `FlatBuffer` file is deployed to a -client device (generally a mobile or embedded device), and the TensorFlow Lite +and `tf.keras` HDF5 models. The TensorFlow Lite `FlatBuffer` file is deployed to +a client device (generally a mobile or embedded device), and the TensorFlow Lite interpreter uses the compressed model for on-device inference. This conversion process is shown in the diagram below: ![TFLite converter workflow](../images/convert/workflow.svg) + +The TensorFlow Lite Converter can be used either from [Python](python_api.md) or +from the [command line](cmdline_examples.md). This allows you to integrate the +conversion step into the model design workflow, ensuring the model is easy to +convert to a mobile inference graph. diff --git a/tensorflow/lite/g3doc/convert/python_api.md b/tensorflow/lite/g3doc/convert/python_api.md index 4bdf0d8cbe..b914a34fa8 100644 --- a/tensorflow/lite/g3doc/convert/python_api.md +++ b/tensorflow/lite/g3doc/convert/python_api.md @@ -3,10 +3,9 @@ This page provides examples on how to use the TensorFlow Lite Converter and the TensorFlow Lite interpreter using the Python API. -Note: TFLite recently moved from `tf.contrib.lite` to `tf.lite`. If you are -using tensorflow `r1.12` or earlier you will need to add `.contrib` to the -commands below. `tf.lite` works with newer builds, like the nightly build, -which can be installed with: `pip install tf-nightly` +Note: These docs describe the converter in the TensorFlow nightly release, +installed using `pip install tf-nightly`. For docs describing older versions +reference ["Converting models from TensorFlow 1.12"](#pre_tensorflow_1.12). [TOC] @@ -24,11 +23,6 @@ The API for converting TensorFlow models to TensorFlow Lite as of TensorFlow 1.9 is `tf.lite.TFLiteConverter`. The API for calling the Python intepreter is `tf.lite.Interpreter`. -Note: Reference "Additional Instructions" sections for converting TensorFlow -models to TensorFlow Lite -[in TensorFlow 1.9 to TensorFlow 1.11](#pre_tensorflow_1.11) and -[prior to TensorFlow 1.9](#pre_tensorflow_1.9) - `TFLiteConverter` provides class methods based on the original format of the model. `TFLiteConverter.from_session()` is available for GraphDefs. `TFLiteConverter.from_saved_model()` is available for SavedModels. @@ -250,14 +244,13 @@ either install the nightly build with [Docker](https://www.tensorflow.org/install/docker), or [build the pip package from source](https://www.tensorflow.org/install/source). -### Converting models in TensorFlow 1.9 to TensorFlow 1.11 - -To convert TensorFlow models to TensorFlow Lite in TensorFlow 1.9 through -TensorFlow 1.11, use `TocoConverter`. `TocoConverter` is semantically -identically to `TFLiteConverter`. +### Converting models from TensorFlow 1.12 -### Converting models prior to TensorFlow 1.9 +Reference the following table to convert TensorFlow models to TensorFlow Lite in +and before TensorFlow 1.12. Run `help()` to get details of each API. -To convert TensorFlow models to TensorFlow Lite in TensorFlow 1.7 and TensorFlow -1.8, use the `toco_convert` function. Run `help(tf.lite.toco_convert)` -to get details about accepted parameters. +TensorFlow Version | Python API +------------------ | --------------------------------- +1.12 | `tf.contrib.lite.TFLiteConverter` +1.9-1.11 | `tf.contrib.lite.TocoConverter` +1.7-1.8 | `tf.contrib.lite.toco_convert` diff --git a/tensorflow/lite/g3doc/devguide.md b/tensorflow/lite/g3doc/devguide.md index 270cb8ce37..fdd02638f9 100644 --- a/tensorflow/lite/g3doc/devguide.md +++ b/tensorflow/lite/g3doc/devguide.md @@ -35,7 +35,7 @@ by suggesting contextually relevant messages. The model is built specifically fo memory constrained devices, such as watches and phones, and has been successfully used in Smart Replies on Android Wear. Currently, this model is Android-specific. -These pre-trained models are [available for download](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/g3doc/models.md) +These pre-trained models are [available for download](models.md). ### Re-train Inception-V3 or MobileNet for a custom data set @@ -57,51 +57,59 @@ A developer may choose to train a custom model using Tensorflow (see the [TensorFlow tutorials](../tutorials/) for examples of building and training models). If you have already written a model, the first step is to export this to a `tf.GraphDef` file. This is required because some formats do not store the -model structure outside the code, and we must communicate with other parts of the -framework. See -[Exporting the Inference Graph](https://github.com/tensorflow/models/blob/master/research/slim/README.md) -to create .pb file for the custom model. +model structure outside the code, and we must communicate with other parts of +the framework. See +[Exporting the Inference Graph](https://www.tensorflow.org/tutorials/keras/save_and_restore_models#save_the_entire_model) +to create file for the custom model. -TensorFlow Lite currently supports a subset of TensorFlow operators. Refer to the -[TensorFlow Lite & TensorFlow Compatibility Guide](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/g3doc/tf_ops_compatibility.md) +TensorFlow Lite currently supports a subset of TensorFlow operators. Refer to +the [TensorFlow Lite & TensorFlow Compatibility Guide](tf_ops_compatibility.md) for supported operators and their usage. This set of operators will continue to grow in future Tensorflow Lite releases. - ## 2. Convert the model format -The model generated (or downloaded) in the previous step is a *standard* -Tensorflow model and you should now have a .pb or .pbtxt `tf.GraphDef` file. -Models generated with transfer learning (re-training) or custom models must be -converted—but, we must first freeze the graph to convert the model to the -Tensorflow Lite format. This process uses several model formats: - -* `tf.GraphDef` (.pb) —A protobuf that represents the TensorFlow training or - computation graph. It contains operators, tensors, and variables definitions. -* *CheckPoint* (.ckpt) —Serialized variables from a TensorFlow graph. Since this - does not contain a graph structure, it cannot be interpreted by itself. -* `FrozenGraphDef` —A subclass of `GraphDef` that does not contain - variables. A `GraphDef` can be converted to a `FrozenGraphDef` by taking a - CheckPoint and a `GraphDef`, and converting each variable into a constant - using the value retrieved from the CheckPoint. -* `SavedModel` —A `GraphDef` and CheckPoint with a signature that labels - input and output arguments to a model. A `GraphDef` and CheckPoint can be - extracted from a `SavedModel`. -* *TensorFlow Lite model* (.tflite) —A serialized - [FlatBuffer](https://google.github.io/flatbuffers/) that contains TensorFlow - Lite operators and tensors for the TensorFlow Lite interpreter, similar to a - `FrozenGraphDef`. - -### Freeze Graph - -To use the `GraphDef` .pb file with TensorFlow Lite, you must have checkpoints -that contain trained weight parameters. The .pb file only contains the structure -of the graph. The process of merging the checkpoint values with the graph -structure is called *freezing the graph*. - -You should have a checkpoints folder or download them for a pre-trained model -(for example, -[MobileNets](https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet_v1.md)). +The [TensorFlow Lite Converter](convert/index.md) accepts the following file +formats: + +* `SavedModel` — A `GraphDef` and checkpoint with a signature that labels + input and output arguments to a model. See the documentation for converting + SavedModels using [Python](convert/python_api.md#basic_savedmodel) or using + the [command line](convert/cmdline_examples.md#savedmodel). +* `tf.keras` - A HDF5 file containing a model with weights and input and + output arguments generated by `tf.Keras`. See the documentation for + converting HDF5 models using + [Python](convert/python_api.md#basic_keras_file) or using the + [command line](convert/cmdline_examples.md#keras). +* `frozen tf.GraphDef` — A subclass of `tf.GraphDef` that does not contain + variables. A `GraphDef` can be converted to a `frozen GraphDef` by taking a + checkpoint and a `GraphDef`, and converting each variable into a constant + using the value retrieved from the checkpoint. Instructions on converting a + `tf.GraphDef` to a TensorFlow Lite model are described in the next + subsection. + +### Converting a tf.GraphDef + +TensorFlow models may be saved as a .pb or .pbtxt `tf.GraphDef` file. In order +to convert the `tf.GraphDef` file to TensorFlow Lite, the model must first be +frozen. This process invovles several file formats including the `frozen +GraphDef`: + +* `tf.GraphDef` (.pb or .pbtxt) — A protobuf that represents the TensorFlow + training or computation graph. It contains operators, tensors, and variables + definitions. +* *checkpoint* (.ckpt) — Serialized variables from a TensorFlow graph. Since + this does not contain a graph structure, it cannot be interpreted by itself. +* *TensorFlow Lite model* (.tflite) — A serialized + [FlatBuffer](https://google.github.io/flatbuffers/) that contains TensorFlow + Lite operators and tensors for the TensorFlow Lite interpreter. + +You must have checkpoints that contain trained weights. The `tf.GraphDef` file +only contains the structure of the graph. The process of merging the checkpoint +values with the graph structure is called *freezing the graph*. + +`tf.GraphDef` and checkpoint files for MobileNet models are available +[here](https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet_v1.md). To freeze the graph, use the following command (changing the arguments): @@ -113,69 +121,53 @@ freeze_graph --input_graph=/tmp/mobilenet_v1_224.pb \ --output_node_names=MobileNetV1/Predictions/Reshape_1 ``` -The `input_binary` flag must be enabled so the protobuf is read and written in -a binary format. Set the `input_graph` and `input_checkpoint` files. +Set the `input_binary` flag to `True` when reading a binary protobuf, a `.pb` +file. Set to `False` for a `.pbtxt` file. -The `output_node_names` may not be obvious outside of the code that built the -model. The easiest way to find them is to visualize the graph, either with -[TensorBoard](https://codelabs.developers.google.com/codelabs/tensorflow-for-poets-2/#3) -or `graphviz`. +Set `input_graph` and `input_checkpoint` to the respective filenames. The +`output_node_names` may not be obvious outside of the code that built the model. +The easiest way to find them is to visualize the graph, either with +[TensorBoard](https://www.tensorflow.org/guide/summaries_and_tensorboard) or +`graphviz`. The frozen `GraphDef` is now ready for conversion to the `FlatBuffer` format -(.tflite) for use on Android or iOS devices. For Android, the Tensorflow -Optimizing Converter tool supports both float and quantized models. To convert -the frozen `GraphDef` to the .tflite format: +(.tflite) for use on Android or iOS devices. For Android, the TensorFlow Lite +Converter tool supports both float and quantized models. To convert the frozen +`GraphDef` to the .tflite format use a command similar to the following: ``` -toco --input_file=$(pwd)/mobilenet_v1_1.0_224/frozen_graph.pb \ - --input_format=TENSORFLOW_GRAPHDEF \ - --output_format=TFLITE \ +tflite_convert \ --output_file=/tmp/mobilenet_v1_1.0_224.tflite \ - --inference_type=FLOAT \ - --input_type=FLOAT \ + --graph_def_file=/tmp/mobilenet_v1_0.50_128/frozen_graph.pb \ --input_arrays=input \ - --output_arrays=MobilenetV1/Predictions/Reshape_1 \ - --input_shapes=1,224,224,3 + --output_arrays=MobilenetV1/Predictions/Reshape_1 ``` -The `input_file` argument should reference the frozen `GraphDef` file -containing the model architecture. The [frozen_graph.pb](https://storage.googleapis.com/download.tensorflow.org/models/mobilenet_v1_1.0_224_frozen.tgz) -file used here is available for download. `output_file` is where the TensorFlow -Lite model will get generated. The `input_type` and `inference_type` -arguments should be set to `FLOAT`, unless converting a -quantized model. -Setting the `input_array`, `output_array`, and `input_shape` arguments are not as -straightforward. The easiest way to find these values is to explore the graph -using Tensorboard. Reuse the arguments for specifying the output nodes for -inference in the `freeze_graph` step. - -It is also possible to use the Tensorflow Optimizing Converter with protobufs -from either Python or from the command line (see the -[toco_from_protos.py](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/toco/python/toco_from_protos.py) -example). This allows you to integrate the conversion step into the model design -workflow, ensuring the model is easily convertible to a mobile inference graph. -For example: - -```python -import tensorflow as tf - -img = tf.placeholder(name="img", dtype=tf.float32, shape=(1, 64, 64, 3)) -val = img + tf.constant([1., 2., 3.]) + tf.constant([1., 4., 4.]) -out = tf.identity(val, name="out") - -with tf.Session() as sess: - tflite_model = tf.lite.toco_convert(sess.graph_def, [img], [out]) - open("converteds_model.tflite", "wb").write(tflite_model) -``` +The +[frozen_graph.pb](https://storage.googleapis.com/download.tensorflow.org/models/mobilenet_v1_1.0_224_frozen.tgz) +file used here is available for download. Setting the `input_array` and +`output_array` arguments is not straightforward. The easiest way to find these +values is to explore the graph using +[TensorBoard](https://www.tensorflow.org/guide/summaries_and_tensorboard). Reuse +the arguments for specifying the output nodes for inference in the +`freeze_graph` step. + +### Full converter reference -For usage, see the Tensorflow Optimizing Converter -[command-line examples](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/toco/g3doc/cmdline_examples.md). +The [TensorFlow Lite Converter](convert/index.md) can be +[Python](convert/python_api.md) or from the +[command line](convert/cmdline_examples.md). This allows you to integrate the +conversion step into the model design workflow, ensuring the model is easy to +convert to a mobile inference graph. -Refer to the -[Ops compatibility guide](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/g3doc/tf_ops_compatibility.md) -for troubleshooting help, and if that doesn't help, please +### Ops compatibility + +Refer to the [ops compatibility guide](tf_ops_compatibility.md) for +troubleshooting help, and if that doesn't help, please [file an issue](https://github.com/tensorflow/tensorflow/issues). +### Graph vizualization tool + The [development repo](https://github.com/tensorflow/tensorflow) contains a tool to visualize TensorFlow Lite models after conversion. To build the [visualize.py](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/tools/visualize.py) @@ -212,8 +204,8 @@ installing TensorFlow on Android and setting up `bazel` and Android Studio. ### iOS To integrate a TensorFlow model in an iOS app, see the -[TensorFlow Lite for iOS](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/g3doc/ios.md) -guide and iOS demo guide. +[TensorFlow Lite for iOS](ios.md) guide and iOS demo +guide. #### Core ML support @@ -227,6 +219,5 @@ devices. To use the converter, refer to the ### Raspberry Pi Compile Tensorflow Lite for a Raspberry Pi by following the -[RPi build instructions](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/g3doc/rpi.md) -This compiles a static library file (`.a`) used to build your app. There are -plans for Python bindings and a demo app. +[RPi build instructions](rpi.md) This compiles a static library file (`.a`) used +to build your app. There are plans for Python bindings and a demo app. diff --git a/tensorflow/lite/g3doc/models.md b/tensorflow/lite/g3doc/models.md index 537e285490..62b3f17c79 100644 --- a/tensorflow/lite/g3doc/models.md +++ b/tensorflow/lite/g3doc/models.md @@ -76,8 +76,11 @@ Mobilenet_V1_1.0_128_quant | [paper](https://arxiv.org/pdf/1712.05877.pdf), [tf Mobilenet_V1_1.0_160_quant | [paper](https://arxiv.org/pdf/1712.05877.pdf), [tflite&pb](http://download.tensorflow.org/models/mobilenet_v1_2018_08_02/mobilenet_v1_1.0_160_quant.tgz) | 4.3 Mb | 66.9% | 86.7% | 37.4 ms Mobilenet_V1_1.0_192_quant | [paper](https://arxiv.org/pdf/1712.05877.pdf), [tflite&pb](http://download.tensorflow.org/models/mobilenet_v1_2018_08_02/mobilenet_v1_1.0_192_quant.tgz) | 4.3 Mb | 69.1% | 88.1% | 51.9 ms Mobilenet_V1_1.0_224_quant | [paper](https://arxiv.org/pdf/1712.05877.pdf), [tflite&pb](http://download.tensorflow.org/models/mobilenet_v1_2018_08_02/mobilenet_v1_1.0_224_quant.tgz) | 4.3 Mb | 70.0% | 89.0% | 70.2 ms -Mobilenet_v2_1.0_224_quant | [paper](https://arxiv.org/abs/1806.08342), [tflite&pb](http://download.tensorflow.org/models/tflite_11_05_08/mobilenet_v2_1.0_224_quant.tgz) | 3.4 Mb | 70.8% | 89.9% | 80.3 ms -Inception_v3_quant | [paper](https://arxiv.org/abs/1806.08342),[tflite&pb](http://download.tensorflow.org/models/tflite_11_05_08/inception_v3_quant.tgz) | 23 Mb | 77.5% | 93.7% | 637 ms +Mobilenet_V2_1.0_224_quant | [paper](https://arxiv.org/abs/1806.08342), [tflite&pb](http://download.tensorflow.org/models/tflite_11_05_08/mobilenet_v2_1.0_224_quant.tgz) | 3.4 Mb | 70.8% | 89.9% | 80.3 ms +Inception_V1_quant | [paper](https://arxiv.org/abs/1409.4842), [tflite&pb](http://download.tensorflow.org/models/inception_v1_224_quant_20181026.tgz) | 6.4 Mb | 70.1% | 89.8% | 154.5 ms +Inception_V2_quant | [paper](https://arxiv.org/abs/1512.00567), [tflite&pb](http://download.tensorflow.org/models/inception_v2_224_quant_20181026.tgz) | 11 Mb | 73.5% | 91.4% | 235.0 ms +Inception_V3_quant | [paper](https://arxiv.org/abs/1806.08342),[tflite&pb](http://download.tensorflow.org/models/tflite_11_05_08/inception_v3_quant.tgz) | 23 Mb | 77.5% | 93.7% | 637 ms +Inception_V4_quant | [paper](https://arxiv.org/abs/1602.07261), [tflite&pb](http://download.tensorflow.org/models/inception_v4_299_quant_20181026.tgz) | 41 Mb | 79.5% | 93.9% | 1250.8 ms ## Other models diff --git a/tensorflow/lite/g3doc/tf_ops_compatibility.md b/tensorflow/lite/g3doc/tf_ops_compatibility.md index b0dfb0fed1..dcfda72137 100644 --- a/tensorflow/lite/g3doc/tf_ops_compatibility.md +++ b/tensorflow/lite/g3doc/tf_ops_compatibility.md @@ -1,4 +1,3 @@ - # TensorFlow Lite & TensorFlow Compatibility Guide TensorFlow Lite supports a number of TensorFlow operations used in common @@ -75,6 +74,7 @@ counterparts: 0D tensor* * [tf.squeeze](https://www.tensorflow.org/api_docs/python/tf/squeeze) - *as long as axis is not provided* +* [tf.squared_difference](https://www.tensorflow.org/versions/master/api_docs/python/tf/squared_difference) * [tf.strided_slice](https://www.tensorflow.org/api_docs/python/tf/strided_slice) - *as long as ellipsis_mask and new_axis_mask are not used* * [tf.transpose](https://www.tensorflow.org/versions/master/api_docs/python/tf/transpose) - @@ -139,6 +139,17 @@ following common ops are not supported at the moment: The following TensorFlow Lite operations are fully supported and used in place of the TensorFlow operations listed above: +**ABS** + +``` +Inputs { + 0: a tensor +} +Outputs { + 0: elementwise abs of the input +} +``` + **ADD** ``` @@ -154,6 +165,30 @@ Options { } ``` +**ARG_MAX** + +``` +Inputs { + 0: a tensor + 1: a tensor +} +Outputs { + 0: A tensor of indices of maximum values. +} +``` + +**ARG_MIN** + +``` +Inputs { + 0: a tensor + 1: a tensor +} +Outputs { + 0: A tensor of indices of minium values. +} +``` + **AVERAGE_POOL_2D** ``` @@ -280,6 +315,18 @@ Outputs { } ``` +**FILL** + +``` +Inputs { + 0: a 1D tensor + 1: a 0D (scalar) tensor +} +Outputs { + 0: A tensor of shape `tensor 0` filled with the value in `tensor 1`. +} +``` + **FLOOR** ``` @@ -291,6 +338,30 @@ outputs: { } ``` +**FLOOR_DIV** + +``` +Inputs { + 0: a tensor + 1: a tensor +} +Outputs { + 0: result of computing element-wise floor of `tensor 0` divided by `tensor 1`. +} +``` + +**FLOOR_MOD** + +``` +Inputs { + 0: a tensor + 1: a tensor +} +Outputs { + 0: result of computing element-wise floor of `tensor 0` modulo `tensor 1`. +} +``` + **FULLY_CONNECTED** ``` @@ -378,6 +449,34 @@ Options { } ``` +**LEAKY_RELU** + +``` +Inputs { + 0: a tensor +} +Outputs { + 0: a tensor equivalent to max(input, input * alpha) +} +Options { + alpha: slope of the activation at x < 0 (provided alpha <= 1) +} +``` + +**LEAKY_RELU** + +``` +Inputs { + 0: a tensor +} +Outputs { + 0: a tensor equivalent to max(input, input * alpha) +} +Options { + alpha +} +``` + **LESS** ``` @@ -421,6 +520,18 @@ Options { } ``` +**LOGICAL_OR** + +``` +Inputs { + 0: a list of tensors. + 1: a list of tensors. +} +Outputs { + 0: A tensor of logical_or output tensors. +} +``` + **LOGISTIC** ``` @@ -498,6 +609,18 @@ Outputs { } ``` +**PACK** + +``` +Inputs { + 0: a list of tensors. + 1: an integer. +} +Outputs { + 0: A tensor of stacked tensors. +} +``` + **PAD** ``` @@ -539,6 +662,35 @@ Outputs { } ``` +**POW** + +``` +Inputs { + 0: a tensor + 1: a tensor +} +Outputs { + 0: elementwise pow of the input tensors +} +``` + +**RANGE** + +``` +Inputs { + 0: a 0D (scalar) tensor + 1: a 0D (scalar) tensor + 2: a 0D (scalar) tensor +} +Outputs { + 0: A 1D tensor of type `dtype` defined by a sequence where `tensor 0` is the + start, `tensor 1` is the limit, and `tensor 2` is the delta. +} +Options { + dtype +} +``` + **RELU** ``` @@ -587,6 +739,22 @@ Options { } ``` +**RESIZE_NEAREST_NEIGHBOR** + +``` +Inputs { + 0: a 4D tensor + 1: a 1D tensor with 2 elements +} +Outputs { + 0: A tensor of type `tensor 0` resized according to `tensor 1` heigh/width values + using nearest neighbors interpolation. +} +Options { + align_corners +} +``` + **RSQRT** ``` @@ -698,6 +866,22 @@ Options { } ``` +**SPLIT_V** + +``` +Inputs { + 0: tensor (input) + 1: 1-D tensor (size_splits) + 2: 0-D tensor (axis) +} +Outputs { + 0-N: subtensors built from the input tensors +} +Options { + num_splits: Specifies number of outputs +} +``` + **SQRT** ``` @@ -781,66 +965,6 @@ Outputs { } ``` -**POW** - -``` -Inputs { - 0: a tensor - 1: a tensor -} -Outputs { - 0: elementwise pow of the input tensors -} -``` - -**ARG_MAX** - -``` -Inputs { - 0: a tensor - 1: a tensor -} -Outputs { - 0: A tensor of indices of maximum values. -} -``` - -**ARG_MIN** - -``` -Inputs { - 0: a tensor - 1: a tensor -} -Outputs { - 0: A tensor of indices of minium values. -} -``` - -**PACK** - -``` -Inputs { - 0: a list of tensors. - 1: an integer. -} -Outputs { - 0: A tensor of stacked tensors. -} -``` - -**LOGICAL_OR** - -``` -Inputs { - 0: a list of tensors. - 1: a list of tensors. -} -Outputs { - 0: A tensor of logical_or output tensors. -} -``` - **UNPACK** ``` @@ -854,26 +978,26 @@ Outputs { } ``` -**FLOOR_DIV** +**ZEROS_LIKE** ``` Inputs { - 0: a list of tensors. - 1: a list of tensors. + 0: a tensor } Outputs { - 0: A tensor of floor_div output tensors. + 0: A tensor of the same shape and type as x but filled with zeros } ``` -**ZEROS_LIKE** +**FILL** ``` Inputs { - 0: a tensor + 0: A Tensor. Must be one of the following types: int32, int64. 1-D. Represents the shape of the output tensor. + 1: A Tensor. 0-D (scalar). Value to fill the returned tensor. } Outputs { - 0: A tensor of the same shape and type as x but filled with zeros + 0: A tensor of the same type as value (input1). } ``` diff --git a/tensorflow/lite/g3doc/using_select_tf_ops.md b/tensorflow/lite/g3doc/using_select_tf_ops.md new file mode 100644 index 0000000000..aa51f58baa --- /dev/null +++ b/tensorflow/lite/g3doc/using_select_tf_ops.md @@ -0,0 +1,249 @@ +# [Experimental] Using TensorFlow Lite with select TensorFlow ops + +The TensorFlow Lite builtin op library has grown rapidly, and will continue to +grow, but there remains a long tail of TensorFlow ops that are not yet natively +supported by TensorFlow Lite . These unsupported ops can be a point of friction +in the TensorFlow Lite model conversion process. To that end, the team has +recently been working on an experimental mechanism for reducing this friction. + +This document outlines how to use TensorFlow Lite with select TensorFlow ops. +*Note that this feature is experimental and is under active development.* As you +use this feature, keep in mind the [known limitations](#known-limitations), and +please send feedback about models that work and issues you are facing to +tflite@tensorflow.org. + +TensorFlow Lite will continue to have +[TensorFlow Lite builtin ops](tf_ops_compatibility.md) optimized for mobile and +embedded devices. However, TensorFlow Lite models can now use a subset of +TensorFlow ops when TFLite builtin ops are not sufficient. + +Models converted with TensorFlow ops will require a TensorFlow Lite interpreter +that has a larger binary size than the interpreter with only TFLite builtin ops. +Additionally, performance optimizations will not be available for any TensorFlow +ops in the TensorFlow Lite model. + +This document outlines how to [convert](#converting-the-model) and +[run](#running-the-model) a TFLite model with TensorFlow ops on your platform of +choice. It also discusses some [known limitations](#known-limitations), the +[future plans](#future-plans) for this feature, and basic +[performance and size metrics](#metrics). + +## Converting the model + +To convert a TensorFlow model to a TensorFlow Lite model with TensorFlow ops, +use the `target_ops` argument in the +[TensorFlow Lite converter](https://www.tensorflow.org/lite/convert/). The +following values are valid options for `target_ops`: + +* `TFLITE_BUILTINS` - Converts models using TensorFlow Lite builtin ops. +* `SELECT_TF_OPS` - Converts models using TensorFlow ops. The exact subset of + supported ops can be found in the whitelist at + `lite/toco/tflite/whitelisted_flex_ops.cc`. + +The recommended approach is to convert the model with `TFLITE_BUILTINS`, then +with both `TFLITE_BUILTINS,SELECT_TF_OPS`, and finally with only +`SELECT_TF_OPS`. Using both options (i.e. `TFLITE_BUILTINS,SELECT_TF_OPS`) +creates models with TensorFlow Lite ops where possible. Using only +`SELECT_TF_OPS` is useful when the model contains TensorFlow ops that are only +partially supported by TensorFlow Lite, and one would like to avoid those +limitations. + +The following example shows how to use `target_ops` in the +[`TFLiteConverter`](https://www.tensorflow.org/lite/convert/python_api) Python +API. + +``` +import tensorflow as tf + +converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) +converter.target_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, + tf.lite.OpsSet.SELECT_TF_OPS] +tflite_model = converter.convert() +open("converted_model.tflite", "wb").write(tflite_model) +``` + +The following example shows how to use `target_ops` in the +[`tflite_convert`](https://www.tensorflow.org/lite/convert/cmdline_examples) +command line tool. + +``` +tflite_convert \ + --output_file=/tmp/foo.tflite \ + --graph_def_file=/tmp/foo.pb \ + --input_arrays=input \ + --output_arrays=MobilenetV1/Predictions/Reshape_1 \ + --target_ops=TFLITE_BUILTINS,SELECT_TF_OPS +``` + +When building and running `tflite_convert` directly with `bazel`, please pass +`--define=with_select_tf_ops=true` as an additional argument. + +``` +bazel run --define=with_select_tf_ops=true tflite_convert -- \ + --output_file=/tmp/foo.tflite \ + --graph_def_file=/tmp/foo.pb \ + --input_arrays=input \ + --output_arrays=MobilenetV1/Predictions/Reshape_1 \ + --target_ops=TFLITE_BUILTINS,SELECT_TF_OPS +``` + +## Running the model + +When using a TensorFlow Lite model that has been converted with support for +select TensorFlow ops, the client must also use a TensorFlow Lite runtime that +includes the necessary library of TensorFlow ops. + +### Android AAR + +A new Android AAR target with select TensorFlow ops has been added for +convenience. Assuming a working TensorFlow Lite +build environment, build the Android AAR with select TensorFlow ops as +follows: + +```sh +bazel build --cxxopt='--std=c++11' -c opt \ + --config=android_arm --config=monolithic \ + //tensorflow/lite/java:tensorflow-lite-with-select-tf-ops +``` + +This will generate an AAR file in `bazel-genfiles/tensorflow/lite/java/`. From +there, you can either import the AAR directly into your project, or publish the +custom AAR to your local Maven repository: + +```sh +mvn install:install-file \ + -Dfile=bazel-genfiles/tensorflow/lite/java/tensorflow-lite-with-select-tf-ops.aar \ + -DgroupId=org.tensorflow \ + -DartifactId=tensorflow-lite-with-select-tf-ops -Dversion=0.1.100 -Dpackaging=aar +``` + +Finally, in your app's `build.gradle`, ensure you have the `mavenLocal()` +dependency and replace the standard TensorFlow Lite dependency with the one that +has support for select TensorFlow ops: + +``` +allprojects { + repositories { + jcenter() + mavenLocal() + } +} + +dependencies { + compile 'org.tensorflow:tensorflow-lite-with-select-tf-ops:0.1.100' +} +``` + +### iOS + +With XCode Command Line Tools installed, TensorFlow Lite with select TensorFlow +ops support can be built with the following command: + +```sh +tensorflow/contrib/makefile/build_all_ios_with_tflite.sh +``` + +This will generate the required static linking libraries in the +`tensorflow/contrib/makefile/gen/lib/` directory. + +The TensorFlow Lite camera example app can be used to test this. A new +TensorFlow Lite XCode project with support for select TensorFlow ops has been +added to +`tensorflow/lite/examples/ios/camera/tflite_camera_example_with_select_tf_ops.xcodeproj`. + +To use this feature in a your own project, either clone the example project or +set the project settings for a new or existing project to the following: + +* In Build Phases -> Link Binary With Libraries, add the static libraries + under `tensorflow/contrib/makefile/gen/lib/` directory: + * `libtensorflow-lite.a` + * `libprotobuf.a` + * `nsync.a` +* In Build Settings -> Header Search Paths, add the following directories: + * `tensorflow/lite/` + * `tensorflow/contrib/makefile/downloads/flatbuffer/include` + * `tensorflow/contrib/makefile/downloads/eigen` +* In Build Settings -> Other Linker Flags, add `-force_load + tensorflow/contrib/makefile/gen/lib/libtensorflow-lite.a`. + +A CocoaPod with support for select TensorFlow ops will also be released in the +future. + +### C++ + +When building TensorFlow Lite libraries using the bazel pipeline, the additional +TensorFlow ops library can be included and enabled as follows: + +* Enable monolithic builds if necessary by adding the `--config=monolithic` + build flag. +* Do one of the following: + * Include the `--define=with_select_tf_ops=true` build flag in the `bazel + build` invocation when building TensorFlow Lite. + * Add the TensorFlow ops delegate library dependency to the build + dependencies: `tensorflow/lite/delegates/flex:delegate`. + +Note that the necessary `TfLiteDelegate` will be installed automatically when +creating the interpreter at runtime as long as the delegate is linked into the +client library. It is not necessary to explicitly install the delegate instance +as is typically required with other delegate types. + +### Python pip Package + +Python support is actively under development. + +## Metrics + +### Performance + +When using a mixture of both builtin and select TensorFlow ops, all of the same +TensorFlow Lite optimizations and optimized builtin kernels will be be available +and usable with the converted model. For the TensorFlow ops, performance should +generally be comparable to that of +[TensorFlow Mobile](https://www.tensorflow.org/lite/tfmobile/). + +The following table describes the average time taken to run inference on +MobileNet on a Pixel 2. The listed times are an average of 100 runs. These +targets were built for Android using the flags: `--config=android_arm64 -c opt`. + +Build | Time (milliseconds) +------------------------------------ | ------------------- +Only built-in ops (`TFLITE_BUILTIN`) | 260.7 +Using only TF ops (`SELECT_TF_OPS`) | 264.5 + +### Binary Size + +The following table describes the binary size of TensorFlow Lite for each build. +These targets were built for Android using `--config=android_arm -c opt`. + +Build | C++ Binary Size | Android APK Size +--------------------- | --------------- | ---------------- +Only built-in ops | 796 KB | 561 KB +Built-in ops + TF ops | 23.0 MB | 8.0 MB + +## Known Limitations + +The following is a list of some of the known limitations: + +* Control flow ops are not yet supported. +* The + [`post_training_quantization`](https://www.tensorflow.org/performance/post_training_quantization) + flag is currently not supported for TensorFlow ops so it will not quantize + weights for any TensorFlow ops. In models with both TensorFlow Lite builtin + ops and TensorFlow ops, the weights for the builtin ops will be quantized. +* Ops that require explicit initialization from resources, like HashTableV2, + are not yet supported. +* Certain TensorFlow ops may not support the full set of input/output types + that are typically available on stock TensorFlow. + +## Future Plans + +The following is a list of improvements to this pipeline that are in progress: + +* *Selective registration* - There is work being done to make it simple to + generate TFLite interpreter binaries that only contain the TensorFlow ops + required for a particular set of models. +* *Improved usability* - The conversion process will be simplified to only + require a single pass through the converter. Additionally, pre-built Android + AAR and iOS CocoaPod binaries will be provided. +* *Improved performance* - There is work being done to ensure TensorFlow Lite + with TensorFlow ops has performance parity to TensorFlow Mobile. diff --git a/tensorflow/lite/interpreter.cc b/tensorflow/lite/interpreter.cc index c90fc3be87..e2129ed46d 100644 --- a/tensorflow/lite/interpreter.cc +++ b/tensorflow/lite/interpreter.cc @@ -20,7 +20,6 @@ limitations under the License. #include #include -#include "tensorflow/lite/arena_planner.h" #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/context_util.h" #include "tensorflow/lite/core/api/error_reporter.h" @@ -32,110 +31,15 @@ limitations under the License. #include "tensorflow/lite/util.h" namespace tflite { -namespace { - -TfLiteStatus ReportOpError(TfLiteContext* context, const TfLiteNode& node, - const TfLiteRegistration& registration, - int node_index, const char* message) { - context->ReportError( - context, "Node number %d (%s) %s.\n", node_index, - registration.custom_name - ? registration.custom_name - : EnumNameBuiltinOperator( - static_cast(registration.builtin_code)), - message); - return kTfLiteError; -} - -// Stub method which returns kTfLiteError when the function is forbidden. -// We're registrating this function to several different function to save -// compiled binary size. Please note the restrictions: -// * The type of first parameter have to be `TfLiteContext*`. -// * All paramteters must be trivailly destructible. (E.g. No C++ class) -TfLiteStatus ForbiddenContextFunction(TfLiteContext* context, ...) { - context->ReportError(context, - "The function is forbidden if not calling in delegate."); - return kTfLiteError; -} - -// Set the ForbiddenContextFunction to a compatible function pointer. -template -void SetForbiddenContextFunction(FunctionType* func) { - *func = reinterpret_cast(ForbiddenContextFunction); -} - -// Returns true if at least one tensor in the given list is kTfLiteDynamic. -template -bool HasDynamicTensorImpl(const TfLiteContext& context, - const TensorIntArray& int_array) { - for (int i : int_array) { - const TfLiteTensor& tensor = context.tensors[i]; - if (tensor.allocation_type == kTfLiteDynamic) { - return true; - } - } - return false; -} - -} // namespace - -// A trivial implementation of GraphInfo around the Interpreter. -// NOTE: this interpreter info represents the subset of the -// graph that is executed according to execution plan. Thus, -// the indices are execution plan indices rather than raw node -// indices. -class InterpreterInfo : public GraphInfo { - public: - explicit InterpreterInfo(Interpreter* interpreter) - : interpreter_(interpreter) {} - - size_t num_tensors() const override { return interpreter_->tensors_size(); } - TfLiteTensor* tensor(size_t index) override { - return interpreter_->tensor(index); - } - size_t num_nodes() const override { - return interpreter_->execution_plan().size(); - } - const TfLiteNode& node(size_t index) const override { - int node_index = interpreter_->execution_plan()[index]; - return interpreter_->node_and_registration(node_index)->first; - } - const std::vector& inputs() const override { - return interpreter_->inputs(); - } - const std::vector& outputs() const override { - return interpreter_->outputs(); - } - const std::vector& variables() const override { - return interpreter_->variables(); - } - - public: - Interpreter* interpreter_; -}; Interpreter::Interpreter(ErrorReporter* error_reporter) : error_reporter_(error_reporter ? error_reporter : DefaultErrorReporter()) { - context_.impl_ = static_cast(this); - context_.ResizeTensor = ResizeTensor; - context_.ReportError = ReportError; - context_.AddTensors = AddTensors; - context_.tensors = nullptr; - context_.tensors_size = 0; - context_.allow_fp32_relax_to_fp16 = false; - context_.recommended_num_threads = -1; - context_.GetExternalContext = GetExternalContext; - context_.SetExternalContext = SetExternalContext; - - // Invalid to call these these except from TfLiteDelegate - SwitchToKernelContext(); + // There's always at least 1 subgraph which is the primary subgraph. + AddSubgraphs(1); + context_ = primary_subgraph().context(); // Reserve some space for the tensors to avoid excessive resizing. - tensors_.reserve(kTensorsReservedCapacity); - nodes_and_registration_.reserve(kTensorsReservedCapacity); - next_execution_plan_index_to_prepare_ = 0; - for (int i = 0; i < kTfLiteMaxExternalContexts; ++i) { external_contexts_[i] = nullptr; } @@ -143,670 +47,88 @@ Interpreter::Interpreter(ErrorReporter* error_reporter) UseNNAPI(false); } -Interpreter::~Interpreter() { - for (auto& nodeAndReg : nodes_and_registration_) { - TfLiteNode& node = nodeAndReg.first; - TfLiteIntArrayFree(node.inputs); - TfLiteIntArrayFree(node.outputs); - TfLiteIntArrayFree(node.temporaries); - if (node.builtin_data) free(node.builtin_data); - OpFree(nodeAndReg.second, node.user_data); - node.builtin_data = nullptr; - } - - for (size_t i = 0; i < context_.tensors_size; i++) { - TfLiteTensor* tensor = &context_.tensors[i]; - if (tensor->buffer_handle != kTfLiteNullBufferHandle && - tensor->delegate->FreeBufferHandle != nullptr) { - tensor->delegate->FreeBufferHandle(&context_, tensor->delegate, - &tensor->buffer_handle); - } - TfLiteTensorFree(tensor); - } -} - -TfLiteStatus Interpreter::ReplaceNodeSubsetsWithDelegateKernels( - TfLiteContext* context, TfLiteRegistration registration, - const TfLiteIntArray* nodes_to_replace, TfLiteDelegate* delegate) { - return static_cast(context->impl_) - ->ReplaceNodeSubsetsWithDelegateKernels(registration, nodes_to_replace, - delegate); -} - -namespace { - -// Copy a std::vector to an existing TfLiteIntArray. -// This is a low-level data manipulation function, and it's caller's -// responsibility to ensure TfLiteIntArray has enough size. -void CopyVectorToTfLiteIntArray(const std::vector& vec, - TfLiteIntArray* arr) { - arr->size = vec.size(); - memcpy(arr->data, vec.data(), sizeof(int) * arr->size); -} - -// This function allocates a continuous memory space that contains a -// TfLiteDelegateParams followed by a several TfLiteIntArray. -// When calling `free` at TfLiteDelegateParams*, all the allocated space -// will be freed together. -// -// +-----------------------------------+ -// | TfLiteDelegateParams | -// | TfLiteDelegate* delegate; | -// | TfLiteIntArray* nodes_to_replace; |--\ -// | TfLiteIntArray* input_tensors; |--+--\ -// | TfLiteIntArray* output_tensors; |--+--+--\ -// +-----------------------------------+ | | | -// | TfLiteIntArray (variable size) |<-/ | | -// +-----------------------------------+ | | -// | TfLiteIntArray (variable size) |<----/ | -// +-----------------------------------+ | -// | TfLiteIntArray (variable size) |<-------/ -// +-----------------------------------+ -TfLiteDelegateParams* CreateDelegateParams(TfLiteDelegate* delegate, - const NodeSubset& node_subset) { - // Step 1: Calculate the allocation size. - int allocation_size = sizeof(TfLiteDelegateParams); - - int nodes_to_replace_size = - TfLiteIntArrayGetSizeInBytes(node_subset.nodes.size()); - allocation_size += nodes_to_replace_size; - - int input_tensors_size = - TfLiteIntArrayGetSizeInBytes(node_subset.input_tensors.size()); - allocation_size += input_tensors_size; - - int output_tensors_size = - TfLiteIntArrayGetSizeInBytes(node_subset.output_tensors.size()); - allocation_size += output_tensors_size; - - // Step 2: Allocate the memory. - // Use `char*` for conveniently step through the allocated space by bytes. - char* allocation = reinterpret_cast(malloc(allocation_size)); - - // Step 3: Fill all data structures structures. - TfLiteDelegateParams* params = - reinterpret_cast(allocation); - params->delegate = delegate; - allocation += sizeof(TfLiteDelegateParams); - - params->nodes_to_replace = reinterpret_cast(allocation); - CopyVectorToTfLiteIntArray(node_subset.nodes, params->nodes_to_replace); - allocation += nodes_to_replace_size; - - params->input_tensors = reinterpret_cast(allocation); - CopyVectorToTfLiteIntArray(node_subset.input_tensors, params->input_tensors); - allocation += input_tensors_size; - - params->output_tensors = reinterpret_cast(allocation); - CopyVectorToTfLiteIntArray(node_subset.output_tensors, - params->output_tensors); - allocation += output_tensors_size; - - return params; -} - -} // namespace - -TfLiteStatus Interpreter::ReplaceNodeSubsetsWithDelegateKernels( - TfLiteRegistration registration, const TfLiteIntArray* nodes_to_replace, - TfLiteDelegate* delegate) { - // Annotate the registration as DELEGATE op. - registration.builtin_code = BuiltinOperator_DELEGATE; - - // Analyze the graph to find all independent node_subsets that are either - // fully not-this-delegate or this-delegate computation. - InterpreterInfo info(this); - std::vector node_subsets; - PartitionGraphIntoIndependentNodeSubsets(&info, nodes_to_replace, - &node_subsets); - - execution_plan_.clear(); - for (auto& node_subset : node_subsets) { - // Subsets calimed by the delegate should have a "macro" op created, the - // other node_subsets (kTfNonPartition) just have their nodes added back to - // the execution plan. - switch (node_subset.type) { - case NodeSubset::kTfNonPartition: - for (auto it = node_subset.nodes.begin(); it != node_subset.nodes.end(); - ++it) { - execution_plan_.push_back(*it); - } - break; - case NodeSubset::kTfPartition: { - int node_index; - - TfLiteDelegateParams* params = - CreateDelegateParams(delegate, node_subset); - TF_LITE_ENSURE_STATUS(AddNodeWithParameters( - node_subset.input_tensors, node_subset.output_tensors, nullptr, 0, - params, ®istration, &node_index)); - - // Initialize the output tensors's delegate-related fields. - for (int tensor_index : node_subset.output_tensors) { - TfLiteTensor* tensor = &tensors_[tensor_index]; - TF_LITE_ENSURE(&context_, tensor->delegate == nullptr || - tensor->delegate == delegate); - tensor->delegate = delegate; - } - - // Associate the node with the delegate. - TfLiteNode* node = &nodes_and_registration_[node_index].first; - node->delegate = delegate; - } break; - case NodeSubset::kTfUnexplored: - return kTfLiteError; - break; - } - } - return kTfLiteOk; -} - -TfLiteExternalContext* Interpreter::GetExternalContext( - TfLiteExternalContextType type) { - if (type >= 0 && type < kTfLiteMaxExternalContexts) { - return external_contexts_[type]; - } - return nullptr; -} - -TfLiteExternalContext* Interpreter::GetExternalContext( - struct TfLiteContext* context, TfLiteExternalContextType type) { - return static_cast(context->impl_)->GetExternalContext(type); -} +Interpreter::~Interpreter() {} void Interpreter::SetExternalContext(TfLiteExternalContextType type, TfLiteExternalContext* ctx) { - if (type >= 0 && type < kTfLiteMaxExternalContexts) { - external_contexts_[type] = ctx; - } -} - -void Interpreter::SetExternalContext(struct TfLiteContext* context, - TfLiteExternalContextType type, - TfLiteExternalContext* ctx) { - return static_cast(context->impl_) - ->SetExternalContext(type, ctx); -} - -// Gets an TfLiteIntArray* representing the execution plan. The interpreter owns -// this memory and it is only guaranteed to exist during the invocation of the -// delegate prepare. -TfLiteStatus Interpreter::GetExecutionPlan(TfLiteIntArray** execution_plan) { - // TODO(aselle): Do not make a copy here - plan_cache_.reset(TfLiteIntArrayCreate(execution_plan_.size())); - *execution_plan = plan_cache_.get(); - static_assert(sizeof(plan_cache_->data[0]) == sizeof(execution_plan_[0]), - "TfLiteIntArray and execution_plan do not contain same type."); - std::memcpy(plan_cache_->data, execution_plan_.data(), - sizeof(plan_cache_->data[0]) * execution_plan_.size()); - return kTfLiteOk; -} - -// WARNING: This is an experimental interface that is subject to change. -// Entry point for C node plugin API to get the execution plan -TfLiteStatus Interpreter::GetExecutionPlan(struct TfLiteContext* context, - TfLiteIntArray** execution_plan) { - return static_cast(context->impl_) - ->GetExecutionPlan(execution_plan); + primary_subgraph().SetExternalContext(type, ctx); } TfLiteStatus Interpreter::SetInputs(std::vector inputs) { - TF_LITE_ENSURE_OK(&context_, - CheckTensorIndices("inputs", inputs.data(), inputs.size())); - inputs_ = std::move(inputs); - return kTfLiteOk; + return primary_subgraph().SetInputs(inputs); } TfLiteStatus Interpreter::SetOutputs(std::vector outputs) { - TF_LITE_ENSURE_OK( - &context_, CheckTensorIndices("outputs", outputs.data(), outputs.size())); - outputs_ = std::move(outputs); - return kTfLiteOk; + return primary_subgraph().SetOutputs(outputs); } TfLiteStatus Interpreter::SetVariables(std::vector variables) { - TF_LITE_ENSURE_OK(&context_, CheckTensorIndices("variables", variables.data(), - variables.size())); - variables_ = std::move(variables); - return kTfLiteOk; -} - -TfLiteStatus Interpreter::CheckTensorIndices(const char* label, - const int* indices, int length) { - // Making sure kOptionalTensor is not re-defined to something other than -1. - static_assert(kOptionalTensor == -1, "kOptionalTensor should be defined -1"); - - for (int i = 0; i < length; i++) { - int index = indices[i]; - // Continue if index == kOptionalTensor before additional comparisons below, - // size_t(-1) is always >= context_tensors_size. - if (index == kOptionalTensor) { - continue; - } - if (index < 0 || static_cast(index) >= context_.tensors_size) { - ReportError(&context_, "Invalid tensor index %d in %s\n", index, label); - consistent_ = false; - return kTfLiteError; - } - } - return kTfLiteOk; -} - -TfLiteStatus Interpreter::BytesRequired(TfLiteType type, const int* dims, - size_t dims_size, size_t* bytes) { - // TODO(aselle): Check for overflow here using overflow.h in TensorFlow - // MultiplyWithoutOverflow. - TF_LITE_ENSURE(&context_, bytes != nullptr); - size_t count = 1; - for (int k = 0; k < dims_size; k++) count *= dims[k]; - switch (type) { - case kTfLiteFloat32: - *bytes = sizeof(float) * count; - break; - case kTfLiteInt16: - *bytes = sizeof(int16_t) * count; - break; - case kTfLiteInt32: - *bytes = sizeof(int32_t) * count; - break; - case kTfLiteUInt8: - *bytes = sizeof(uint8_t) * count; - break; - case kTfLiteInt64: - *bytes = sizeof(int64_t) * count; - break; - case kTfLiteBool: - *bytes = sizeof(bool) * count; - break; - case kTfLiteComplex64: - *bytes = sizeof(std::complex) * count; - break; - default: - ReportError(&context_, - "Only float32, int16, int32, int64, uint8, bool, complex64 " - "supported currently."); - return kTfLiteError; - } - return kTfLiteOk; + return primary_subgraph().SetVariables(variables); } TfLiteStatus Interpreter::AllocateTensors() { - if (!consistent_) { - ReportError(&context_, "AllocateTensors() called on inconsistent model."); - return kTfLiteError; - } - - // Explicit (re)allocation is necessary if nodes have been changed or tensors - // have been resized. For inputs marked as dynamic, we can't short-circuit the - // allocation as the client may have done the resize manually. - if (state_ != kStateUninvokable && !HasDynamicTensorImpl(context_, inputs_)) { - return kTfLiteOk; - } - - next_execution_plan_index_to_prepare_ = 0; - if (memory_planner_) { - TF_LITE_ENSURE_STATUS(memory_planner_->ResetAllocations()); - } - - TF_LITE_ENSURE_STATUS(PrepareOpsAndTensors()); - - state_ = kStateInvokable; - - // Reset the variable tensors to zero after (re)allocating the tensors. - // Developers shouldn't rely on the side effect of this function to reset - // variable tesnsors. They should call `ResetVariableTensors` directly - // instead. - ResetVariableTensors(); - - return kTfLiteOk; + return primary_subgraph().AllocateTensors(); } -// TODO(ycling): Support non-zero default values. -TfLiteStatus Interpreter::ResetVariableTensors() { - for (auto& tensor : tensors_) { - if (!tensor.is_variable) { - continue; - } +void Interpreter::ReserveNodes(int count) { + primary_subgraph().nodes_and_registration().reserve(count); +} - // Variable tensors have to be `kTfLiteArenaRwPersistent`, and must be - // allocated after the initial `PrepareOpsAndTensors()` is called. - TF_LITE_ENSURE_EQ(&context_, tensor.allocation_type, - kTfLiteArenaRwPersistent); - TF_LITE_ENSURE(&context_, tensor.data.raw != nullptr); +void Interpreter::AddSubgraphs(int subgraphs_to_add, + int* first_new_subgraph_index) { + const size_t base_index = subgraphs_.size(); + if (first_new_subgraph_index) *first_new_subgraph_index = base_index; - memset(tensor.data.raw, 0, tensor.bytes); + subgraphs_.reserve(base_index + subgraphs_to_add); + for (int i = 0; i < subgraphs_to_add; ++i) { + Subgraph* subgraph = + new Subgraph(error_reporter_, external_contexts_, &subgraphs_); + subgraphs_.emplace_back(subgraph); } - return kTfLiteOk; -} - -void Interpreter::ReserveNodes(int count) { - nodes_and_registration_.reserve(count); } TfLiteStatus Interpreter::AddNodeWithParameters( const std::vector& inputs, const std::vector& outputs, const char* init_data, size_t init_data_size, void* builtin_data, const TfLiteRegistration* registration, int* node_index) { - if (state_ == kStateInvokableAndImmutable) { - ReportError(&context_, - "AddNodeWithParameters is disallowed when graph is immutable."); - return kTfLiteError; - } - state_ = kStateUninvokable; - - std::unique_ptr builtin_data_deleter(builtin_data, - free); - - TF_LITE_ENSURE_OK(&context_, CheckTensorIndices("node inputs", inputs.data(), - inputs.size())); - TF_LITE_ENSURE_OK( - &context_, - CheckTensorIndices("node outputs", outputs.data(), outputs.size())); - - int new_node_index = nodes_and_registration_.size(); - if (node_index) *node_index = new_node_index; - nodes_and_registration_.resize(nodes_and_registration_.size() + 1); - auto& node_and_reg = nodes_and_registration_.back(); - TfLiteNode& node = node_and_reg.first; - if (node.inputs) TfLiteIntArrayFree(node.inputs); - if (node.outputs) TfLiteIntArrayFree(node.outputs); - if (node.temporaries) TfLiteIntArrayFree(node.temporaries); - - // NOTE, here we are not using move semantics yet, since our internal - // representation isn't std::vector, but in the future we would like to avoid - // copies, so we want the interface to take r-value references now. - node.inputs = ConvertVectorToTfLiteIntArray(inputs); - node.outputs = ConvertVectorToTfLiteIntArray(outputs); - node.temporaries = TfLiteIntArrayCreate(0); - if (init_data) { - node.user_data = OpInit(*registration, init_data, init_data_size); - } else { - node.user_data = - OpInit(*registration, - reinterpret_cast(builtin_data_deleter.get()), 0); - } - - node.builtin_data = builtin_data_deleter.release(); - // TODO(ycling): Filling `custom_initial_data` and `custom_initial_data_size` - // properly for nodes generated by ReplaceNodeSubsetsWithDelegateKernels. - - if (registration->builtin_code == BuiltinOperator_CUSTOM) { - // When it's a CUSTOM op, the `custom_options` field in the Flatbuffer - // `Operator` table is passed in. - node.custom_initial_data = init_data; - node.custom_initial_data_size = init_data_size; - } else { - node.custom_initial_data = nullptr; - node.custom_initial_data_size = 0; - } - - node.delegate = nullptr; - node_and_reg.second = *registration; - execution_plan_.push_back(new_node_index); - return kTfLiteOk; + return primary_subgraph().AddNodeWithParameters(inputs, outputs, init_data, + init_data_size, builtin_data, + registration, node_index); } TfLiteStatus Interpreter::ResizeInputTensor(int tensor_index, const std::vector& dims) { - if (state_ == kStateInvokableAndImmutable) { - ReportError(&context_, - "ResizeInputTensor is disallowed when graph is immutable."); - return kTfLiteError; - } - - // TODO(aselle): All bounds checks can be implemented as one-sided bounds - // checks by casting to unsigned for efficiency. Profile before doing this. - TF_LITE_ENSURE(&context_, - tensor_index < context_.tensors_size && tensor_index >= 0); - TfLiteTensor* tensor = &context_.tensors[tensor_index]; - - // Short-circuit the state change if the dimensions don't change, avoiding - // unnecessary (re)allocations. - if (EqualArrayAndTfLiteIntArray(tensor->dims, dims.size(), dims.data())) { - return kTfLiteOk; - } - - state_ = kStateUninvokable; - return ResizeTensorImpl(tensor, ConvertVectorToTfLiteIntArray(dims)); -} - -bool HasDynamicTensor(const TfLiteContext& context, - const TfLiteIntArray* int_array) { - return HasDynamicTensorImpl(context, TfLiteIntArrayView{int_array}); -} - -TfLiteStatus Interpreter::PrepareOpsStartingAt( - int first_execution_plan_index, int* last_execution_plan_index_prepared) { - for (int execution_plan_index = first_execution_plan_index; - execution_plan_index < execution_plan_.size(); execution_plan_index++) { - int node_index = execution_plan_[execution_plan_index]; - TfLiteNode& node = nodes_and_registration_[node_index].first; - const TfLiteRegistration& registration = - nodes_and_registration_[node_index].second; - EnsureTensorsVectorCapacity(); - if (OpPrepare(registration, &node) == kTfLiteError) { - return ReportOpError(&context_, node, registration, node_index, - "failed to prepare"); - } - - *last_execution_plan_index_prepared = execution_plan_index; - - // Discontinue if the node has dynamic outputs. Note that we don't - // stop for dynamic temporary tensors since they won't affect the - // sizes of other tensors in the graph. - if (HasDynamicTensor(context_, node.outputs)) { - break; - } - } - return kTfLiteOk; -} - -TfLiteStatus Interpreter::PrepareOpsAndTensors() { - if (!memory_planner_) { - memory_planner_.reset(new ArenaPlanner( - &context_, std::unique_ptr(new InterpreterInfo(this)), - /*preserve_inputs=*/true, /*preserve_intermediates*/ false)); - memory_planner_->PlanAllocations(); - } - - int last_exec_plan_index_prepared = 0; - - TF_LITE_ENSURE_STATUS(PrepareOpsStartingAt( - next_execution_plan_index_to_prepare_, &last_exec_plan_index_prepared)); - TF_LITE_ENSURE_STATUS(memory_planner_->ExecuteAllocations( - next_execution_plan_index_to_prepare_, last_exec_plan_index_prepared)); - - next_execution_plan_index_to_prepare_ = last_exec_plan_index_prepared + 1; - return kTfLiteOk; + return primary_subgraph().ResizeInputTensor(tensor_index, dims); } TfLiteStatus Interpreter::Invoke() { - if (!consistent_) { - ReportError(&context_, "Invoke called on model that is not consistent."); - return kTfLiteError; - } - if (state_ == kStateUninvokable) { - ReportError(&context_, "Invoke called on model that is not ready."); - return kTfLiteError; - } - - TfLiteStatus status = kTfLiteOk; - if (nnapi_delegate_) { - if (next_execution_plan_index_to_prepare_ == execution_plan_.size()) { - TF_LITE_ENSURE_OK(&context_, nnapi_delegate_->Invoke(this)); - return kTfLiteOk; - } else { - // TODO(aselle): In the future, we would like this to be an - // automatic tflite CPU fallback. - ReportError(&context_, - "NNAPI was requested, but dependent sized tensors " - "being used.\n"); - return kTfLiteError; - } - } - - // Invocations are always done in node order. - // Note that calling Invoke repeatedly will cause the original memory plan to - // be reused, unless either ResizeInputTensor() or AllocateTensors() has been - // called. - for (int execution_plan_index = 0; - execution_plan_index < execution_plan_.size(); execution_plan_index++) { - if (execution_plan_index == next_execution_plan_index_to_prepare_) { - TF_LITE_ENSURE_STATUS(PrepareOpsAndTensors()); - TF_LITE_ENSURE(&context_, next_execution_plan_index_to_prepare_ >= - execution_plan_index); - } - int node_index = execution_plan_[execution_plan_index]; - TfLiteNode& node = nodes_and_registration_[node_index].first; - const TfLiteRegistration& registration = - nodes_and_registration_[node_index].second; - SCOPED_OPERATOR_PROFILE(profiler_, node_index); - - // TODO(ycling): This is an extra loop through inputs to check if the data - // need to be copied from Delegate buffer to raw memory, which is often not - // needed. We may want to cache this in prepare to know if this needs to be - // done for a node or not. - for (int i = 0; i < node.inputs->size; ++i) { - int tensor_index = node.inputs->data[i]; - if (tensor_index == kOptionalTensor) { - continue; - } - TfLiteTensor* tensor = &tensors_[tensor_index]; - if (tensor->delegate && tensor->delegate != node.delegate && - tensor->data_is_stale) { - EnsureTensorDataIsReadable(tensor_index); - } - } - - EnsureTensorsVectorCapacity(); - tensor_resized_since_op_invoke_ = false; - if (OpInvoke(registration, &node) == kTfLiteError) { - status = ReportOpError(&context_, node, registration, node_index, - "failed to invoke"); - } - - // Force execution prep for downstream ops if the latest op triggered the - // resize of a dynamic tensor. - if (tensor_resized_since_op_invoke_ && - HasDynamicTensor(context_, node.outputs)) { - next_execution_plan_index_to_prepare_ = execution_plan_index + 1; - } - } + TfLiteStatus status = primary_subgraph().Invoke(); if (!allow_buffer_handle_output_) { - for (int tensor_index : outputs_) { - EnsureTensorDataIsReadable(tensor_index); + for (int tensor_index : outputs()) { + primary_subgraph().EnsureTensorDataIsReadable(tensor_index); } } return status; } -TfLiteStatus Interpreter::ResizeTensor(TfLiteContext* context, - TfLiteTensor* tensor, - TfLiteIntArray* new_size) { - // Note here that context->impl_ is recovering the this pointer for an - // instance of Interpreter to call into the member function ResizeTensorImpl - // (this function is static). - return static_cast(context->impl_) - ->ResizeTensorImpl(tensor, new_size); -} - -void Interpreter::ReportErrorImpl(const char* format, va_list args) { - error_reporter_->Report(format, args); -} - -void Interpreter::ReportError(TfLiteContext* context, const char* format, ...) { - va_list args; - va_start(args, format); - auto* f = static_cast(context->impl_); - // Note here that context->impl_ is recovering the this pointer for an - // instance of Interpreter to call into the member function ReportErrorImpl - // (this function is static). - f->ReportErrorImpl(format, args); - va_end(args); -} - TfLiteStatus Interpreter::AddTensors(int tensors_to_add, int* first_new_tensor_index) { - const size_t base_index = tensors_.size(); - if (first_new_tensor_index) *first_new_tensor_index = base_index; - tensors_.resize(tensors_.size() + tensors_to_add); - for (size_t i = base_index; i < tensors_.size(); i++) { - memset(&tensors_[i], 0, sizeof(tensors_[i])); - tensors_[i].buffer_handle = kTfLiteNullBufferHandle; - } - context_.tensors = tensors_.data(); - context_.tensors_size = tensors_.size(); - return kTfLiteOk; -} - -TfLiteStatus Interpreter::AddTensors(TfLiteContext* context, int tensors_to_add, - int* first_new_tensor_index) { - // Note here that context->impl_ is recovering the this pointer for an - // instance of Interpreter to call into the member function AddTensors - // (this function is static). - return static_cast(context->impl_) - ->AddTensors(tensors_to_add, first_new_tensor_index); -} - -TfLiteStatus Interpreter::GetNodeAndRegistration( - int node_index, TfLiteNode** node, TfLiteRegistration** registration) { - TF_LITE_ENSURE(&context_, node_index >= 0); - TF_LITE_ENSURE(&context_, static_cast(node_index) < nodes_size()); - TF_LITE_ENSURE(&context_, node != nullptr && registration != nullptr); - *node = &nodes_and_registration_[node_index].first; - *registration = &nodes_and_registration_[node_index].second; - return kTfLiteOk; + return primary_subgraph().AddTensors(tensors_to_add, first_new_tensor_index); } -TfLiteStatus Interpreter::GetNodeAndRegistration( - struct TfLiteContext* context, int node_index, TfLiteNode** node, - TfLiteRegistration** registration) { - return static_cast(context->impl_) - ->GetNodeAndRegistration(node_index, node, registration); +TfLiteStatus Interpreter::ResetVariableTensors() { + return primary_subgraph().ResetVariableTensors(); } TfLiteStatus Interpreter::SetTensorParametersReadOnly( int tensor_index, TfLiteType type, const char* name, const size_t rank, const int* dims, TfLiteQuantizationParams quantization, const char* buffer, size_t bytes, const Allocation* allocation) { - if (state_ == kStateInvokableAndImmutable) { - ReportError( - &context_, - "SetTensorParametersReadOnly is disallowed when graph is immutable."); - return kTfLiteError; - } - - TF_LITE_ENSURE(&context_, - tensor_index < context_.tensors_size && tensor_index >= 0); - // For most tensors we know exactly how much memory is necessary so we can - // ensure the buffer is large enough. However, we need to skip string tensors - // because their sizes change with the contents of the individual strings. - if (type != kTfLiteString) { - size_t required_bytes; - TF_LITE_ENSURE_OK(&context_, - BytesRequired(type, dims, rank, &required_bytes)); - TF_LITE_ENSURE_EQ(&context_, required_bytes, bytes); - } - - TfLiteTensor& tensor = context_.tensors[tensor_index]; - if (type == tensor.type && - EqualArrayAndTfLiteIntArray(tensor.dims, rank, dims)) { - // Fast path which does not invalidate the invokable property. - TfLiteTensorDataFree(&tensor); - tensor.data.raw = const_cast(buffer); - if (!tensor.dims) tensor.dims = ConvertArrayToTfLiteIntArray(rank, dims); - tensor.params = quantization; - tensor.allocation_type = kTfLiteMmapRo; - tensor.allocation = allocation; - } else { - state_ = kStateUninvokable; - TfLiteTensorReset(type, name, ConvertArrayToTfLiteIntArray(rank, dims), - quantization, const_cast(buffer), bytes, - kTfLiteMmapRo, allocation, false, &tensor); - } - return kTfLiteOk; + return primary_subgraph().SetTensorParametersReadOnly( + tensor_index, type, name, rank, dims, quantization, buffer, bytes, + allocation); } // Set description of inputs/outputs/data/fptrs for node `node_index`. @@ -816,186 +138,52 @@ TfLiteStatus Interpreter::SetTensorParametersReadOnly( TfLiteStatus Interpreter::SetTensorParametersReadWrite( int tensor_index, TfLiteType type, const char* name, const size_t rank, const int* dims, TfLiteQuantizationParams quantization, bool is_variable) { - if (state_ == kStateInvokableAndImmutable) { - ReportError( - &context_, - "SetTensorParametersReadWrite is disallowed when graph is immutable."); - return kTfLiteError; - } - TF_LITE_ENSURE(&context_, - tensor_index < context_.tensors_size && tensor_index >= 0); - size_t required_bytes = 0; - if (type != kTfLiteString) { - // These types will be allocated in our arena so we need to record how - // many bytes we will need based on the dimensions. String tensors are - // allocated dynamically and we can't know ahead of time how much space - // they will require. - TF_LITE_ENSURE_OK(&context_, - BytesRequired(type, dims, rank, &required_bytes)); - } - - TfLiteAllocationType allocation_type = kTfLiteArenaRw; - if (type == kTfLiteString) { - if (is_variable) { - // We don't have a real use case for string variable tensor. - ReportError(&context_, "String variable tensor isn't supported."); - return kTfLiteError; - } - allocation_type = kTfLiteDynamic; - } else if (is_variable) { - allocation_type = kTfLiteArenaRwPersistent; - } - - TfLiteTensorReset(type, name, ConvertArrayToTfLiteIntArray(rank, dims), - quantization, - /*buffer=*/nullptr, required_bytes, allocation_type, - nullptr, is_variable, &context_.tensors[tensor_index]); - return kTfLiteOk; + return primary_subgraph().SetTensorParametersReadWrite( + tensor_index, type, name, rank, dims, quantization, is_variable); } TfLiteStatus Interpreter::SetExecutionPlan(const std::vector& new_plan) { - for (int node_index : new_plan) { - TF_LITE_ENSURE(&context_, node_index >= 0 && node_index < nodes_size()); - } - execution_plan_ = new_plan; - return kTfLiteOk; -} - -TfLiteStatus Interpreter::ResizeTensorImpl(TfLiteTensor* tensor, - TfLiteIntArray* new_size) { - // Note that in theory we could resize kTfLiteArenaRwPersistent tensors too. - if (tensor->allocation_type == kTfLiteArenaRw || - tensor->allocation_type == kTfLiteDynamic || - tensor->allocation_type == kTfLiteArenaRwPersistent) { - tensor_resized_since_op_invoke_ |= - TfLiteIntArrayEqual(tensor->dims, new_size) == 0; - if (tensor->type != kTfLiteString) { - size_t bytesRequired; - TfLiteStatus status = BytesRequired(tensor->type, new_size->data, - new_size->size, &bytesRequired); - if (status != kTfLiteOk) { - TfLiteIntArrayFree(new_size); - return kTfLiteError; - } - - // Realloc space for kTfLiteDynamic tensors. - TfLiteTensorRealloc(bytesRequired, tensor); - tensor->bytes = bytesRequired; - } - if (tensor->dims) TfLiteIntArrayFree(tensor->dims); - tensor->dims = new_size; - - if (tensor->allocation_type != kTfLiteDynamic) { - tensor->data.raw = nullptr; - } - } else { - // kTfLiteMmapRo tensors are stored in the flatbuffer and are therefore - // of fixed size. - TfLiteIntArrayFree(new_size); - ReportError(&context_, "Attempting to resize a fixed-size tensor."); - return kTfLiteError; - } - return kTfLiteOk; + return primary_subgraph().SetExecutionPlan(new_plan); } -void Interpreter::UseNNAPI(bool enable) { - // TODO(aselle): This is a workaround for finding if NNAPI exists. - // We also need to make sure getLibraryHandle() is renamed to be NNAPI - // prefixed. - if (!NNAPIDelegate::IsSupported()) enable = false; - if (!enable) { - nnapi_delegate_.reset(); - } else if (!nnapi_delegate_) { - nnapi_delegate_.reset(new NNAPIDelegate); - } -} +void Interpreter::UseNNAPI(bool enable) { primary_subgraph().UseNNAPI(enable); } void Interpreter::SetNumThreads(int num_threads) { - context_.recommended_num_threads = num_threads; + for (auto& subgraph : subgraphs_) { + subgraph->context()->recommended_num_threads = num_threads; + } for (int i = 0; i < kTfLiteMaxExternalContexts; ++i) { auto* c = external_contexts_[i]; if (c && c->Refresh) { - c->Refresh(&context_); + c->Refresh(context_); } } } -void Interpreter::SwitchToDelegateContext() { - context_.GetNodeAndRegistration = GetNodeAndRegistration; - context_.ReplaceNodeSubsetsWithDelegateKernels = - ReplaceNodeSubsetsWithDelegateKernels; - context_.GetExecutionPlan = GetExecutionPlan; -} - -void Interpreter::SwitchToKernelContext() { - SetForbiddenContextFunction(&context_.GetNodeAndRegistration); - SetForbiddenContextFunction(&context_.ReplaceNodeSubsetsWithDelegateKernels); - SetForbiddenContextFunction(&context_.GetExecutionPlan); +void Interpreter::SetAllowFp16PrecisionForFp32(bool allow) { + for (auto& subgraph : subgraphs_) { + subgraph->context()->allow_fp32_relax_to_fp16 = allow; + } } TfLiteStatus Interpreter::ModifyGraphWithDelegate(TfLiteDelegate* delegate) { - if (!(delegate->flags & kTfLiteDelegateFlagsAllowDynamicTensors)) { - int last_execution_plan_index_prepared; - TF_LITE_ENSURE_OK(&context_, PrepareOpsStartingAt( - 0, &last_execution_plan_index_prepared)); - - bool has_dynamic_tensors = true; - // Dynamic tensors exist if not all nodes can be prepared. - if (last_execution_plan_index_prepared + 1 == execution_plan_.size()) { - // If all the nodes can be prepared, check if the last node has dynamic - // tensors. - int node_index = execution_plan_[last_execution_plan_index_prepared]; - TfLiteNode& node = nodes_and_registration_[node_index].first; - if (!HasDynamicTensor(context_, node.outputs)) { - has_dynamic_tensors = false; - } - } - if (has_dynamic_tensors) { - ReportError( - &context_, - "Attempting to use a delegate that only supports static-sized " - "tensors with a graph that has dynamic-sized tensors."); - return kTfLiteError; - } - } - - // TODO(aselle): Consider if it is worth storing pointers to delegates. - // Setup additional context interface. - SwitchToDelegateContext(); - - TfLiteStatus status = delegate->Prepare(&context_, delegate); - - // Remove additional context info. - SwitchToKernelContext(); - - TF_LITE_ENSURE_OK(&context_, status); - - if (!(delegate->flags & kTfLiteDelegateFlagsAllowDynamicTensors)) { - // Reset the state to force tensor/op reallocation. - state_ = kStateUninvokable; - TF_LITE_ENSURE_OK(&context_, AllocateTensors()); - TF_LITE_ENSURE_EQ(&context_, state_, kStateInvokable); - // After using a delegate which doesn't support dynamic tensors, make the - // entire graph immutable. - state_ = kStateInvokableAndImmutable; - } - - return status; + return primary_subgraph().ModifyGraphWithDelegate(delegate); } TfLiteStatus Interpreter::SetBufferHandle(int tensor_index, TfLiteBufferHandle buffer_handle, TfLiteDelegate* delegate) { - TF_LITE_ENSURE(&context_, tensor_index < tensors_size()); - TfLiteTensor* tensor = &tensors_[tensor_index]; + TF_LITE_ENSURE(context_, tensor_index < tensors_size()); + std::vector& tensors = primary_subgraph().tensors(); + TfLiteTensor* tensor = &tensors[tensor_index]; - TF_LITE_ENSURE(&context_, + TF_LITE_ENSURE(context_, tensor->delegate == nullptr || tensor->delegate == delegate); tensor->delegate = delegate; if (tensor->buffer_handle != kTfLiteNullBufferHandle) { - TF_LITE_ENSURE(&context_, tensor->delegate->FreeBufferHandle != nullptr); - tensor->delegate->FreeBufferHandle(&context_, tensor->delegate, + TF_LITE_ENSURE(context_, tensor->delegate->FreeBufferHandle != nullptr); + tensor->delegate->FreeBufferHandle(context_, tensor->delegate, &tensor->buffer_handle); } tensor->buffer_handle = buffer_handle; @@ -1006,8 +194,9 @@ TfLiteStatus Interpreter::SetBufferHandle(int tensor_index, TfLiteStatus Interpreter::GetBufferHandle(int tensor_index, TfLiteBufferHandle* buffer_handle, TfLiteDelegate** delegate) { - TF_LITE_ENSURE(&context_, tensor_index < tensors_size()); - TfLiteTensor* tensor = &tensors_[tensor_index]; + TF_LITE_ENSURE(context_, tensor_index < tensors_size()); + std::vector& tensors = primary_subgraph().tensors(); + TfLiteTensor* tensor = &tensors[tensor_index]; *delegate = tensor->delegate; *buffer_handle = tensor->buffer_handle; @@ -1015,4 +204,12 @@ TfLiteStatus Interpreter::GetBufferHandle(int tensor_index, return kTfLiteOk; } +void Interpreter::SetProfiler(profiling::Profiler* profiler) { + for (auto& subgraph : subgraphs_) subgraph->SetProfiler(profiler); +} + +profiling::Profiler* Interpreter::GetProfiler() { + return primary_subgraph().GetProfiler(); +} + } // namespace tflite diff --git a/tensorflow/lite/interpreter.h b/tensorflow/lite/interpreter.h index 415c5f0979..6192d56ca2 100644 --- a/tensorflow/lite/interpreter.h +++ b/tensorflow/lite/interpreter.h @@ -25,6 +25,7 @@ limitations under the License. #include "tensorflow/lite/allocation.h" #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/core/subgraph.h" #include "tensorflow/lite/memory_planner.h" #include "tensorflow/lite/profiling/profiler.h" #include "tensorflow/lite/stderr_reporter.h" @@ -57,6 +58,10 @@ constexpr TfLiteType typeToTfLiteType() { return kTfLiteUInt8; } template <> +constexpr TfLiteType typeToTfLiteType() { + return kTfLiteInt8; +} +template <> constexpr TfLiteType typeToTfLiteType() { return kTfLiteBool; } @@ -69,9 +74,6 @@ constexpr TfLiteType typeToTfLiteType() { return kTfLiteString; } -// Forward declare since NNAPIDelegate uses Interpreter. -class NNAPIDelegate; - // An interpreter for a graph of nodes that input and output from tensors. // Each node of the graph processes a set of input tensors and produces a // set of output Tensors. All inputs/output tensors are referenced by index. @@ -100,12 +102,6 @@ class NNAPIDelegate; // foo.Invoke(); // -struct TfLiteIntArrayDeleter { - void operator()(TfLiteIntArray* a) { - if (a) TfLiteIntArrayFree(a); - } -}; - class Interpreter { public: // Instantiate an interpreter. All errors associated with reading and @@ -117,6 +113,7 @@ class Interpreter { ~Interpreter(); + // Interpreters are not copyable as they have non-trivial memory semantics. Interpreter(const Interpreter&) = delete; Interpreter& operator=(const Interpreter&) = delete; @@ -197,34 +194,40 @@ class Interpreter { // Functions to access tensor data // Read only access to list of inputs. - const std::vector& inputs() const { return inputs_; } + const std::vector& inputs() const { return primary_subgraph().inputs(); } // Return the name of a given input. The given index must be between 0 and // inputs().size(). const char* GetInputName(int index) const { - return context_.tensors[inputs_[index]].name; + return context_->tensors[inputs()[index]].name; } // Read only access to list of outputs. - const std::vector& outputs() const { return outputs_; } + const std::vector& outputs() const { + return primary_subgraph().outputs(); + } // Read only access to list of variable tensors. - const std::vector& variables() const { return variables_; } + const std::vector& variables() const { + return primary_subgraph().variables(); + } // Return the name of a given output. The given index must be between 0 and // outputs().size(). const char* GetOutputName(int index) const { - return context_.tensors[outputs_[index]].name; + return context_->tensors[outputs()[index]].name; } // Return the number of tensors in the model. - size_t tensors_size() const { return context_.tensors_size; } + size_t tensors_size() const { return context_->tensors_size; } // Return the number of ops in the model. - size_t nodes_size() const { return nodes_and_registration_.size(); } + size_t nodes_size() const { return primary_subgraph().nodes_size(); } // WARNING: Experimental interface, subject to change - const std::vector& execution_plan() const { return execution_plan_; } + const std::vector& execution_plan() const { + return primary_subgraph().execution_plan(); + } // WARNING: Experimental interface, subject to change // Overrides execution plan. This bounds checks indices sent in. @@ -234,27 +237,18 @@ class Interpreter { // TODO(aselle): Create a safe ArrayHandle interface to avoid exposing this // read/write access to structure TfLiteTensor* tensor(int tensor_index) { - if (tensor_index < 0 || - static_cast(tensor_index) >= context_.tensors_size) - return nullptr; - return &context_.tensors[tensor_index]; + return primary_subgraph().tensor(tensor_index); } // Get an immutable tensor data structure. const TfLiteTensor* tensor(int tensor_index) const { - if (tensor_index < 0 || - static_cast(tensor_index) >= context_.tensors_size) - return nullptr; - return &context_.tensors[tensor_index]; + return primary_subgraph().tensor(tensor_index); } // Get a pointer to an operation and registration data structure if in bounds. const std::pair* node_and_registration( int node_index) const { - if (node_index < 0 || - static_cast(node_index) >= nodes_and_registration_.size()) - return nullptr; - return &nodes_and_registration_[node_index]; + return primary_subgraph().node_and_registration(node_index); } // Perform a checked cast to the appropriate tensor type (mutable pointer @@ -285,28 +279,28 @@ class Interpreter { // index must be between 0 and inputs().size(). template T* typed_input_tensor(int index) { - return typed_tensor(inputs_[index]); + return typed_tensor(inputs()[index]); } // Return an immutable pointer into the data of a given input tensor. The // given index must be between 0 and inputs().size(). template const T* typed_input_tensor(int index) const { - return typed_tensor(inputs_[index]); + return typed_tensor(inputs()[index]); } // Return a mutable pointer into the data of a given output tensor. The given // index must be between 0 and outputs().size(). template T* typed_output_tensor(int index) { - return typed_tensor(outputs_[index]); + return typed_tensor(outputs()[index]); } // Return an immutable pointer into the data of a given output tensor. The // given index must be between 0 and outputs().size(). template const T* typed_output_tensor(int index) const { - return typed_tensor(outputs_[index]); + return typed_tensor(outputs()[index]); } // Change the dimensionality of a given tensor. Note, this is only acceptable @@ -321,7 +315,6 @@ class Interpreter { // Update allocations for all tensors. This will redim dependent tensors using // the input tensor dimensionality as given. This is relatively expensive. // If you know that your sizes are not changing, you need not call this. - // Returns status of success or failure. TfLiteStatus AllocateTensors(); @@ -342,14 +335,12 @@ class Interpreter { // Allow float16 precision for FP32 calculation when possible. // default: not allow. // WARNING: This is an experimental API and subject to change. - void SetAllowFp16PrecisionForFp32(bool allow) { - context_.allow_fp32_relax_to_fp16 = allow; - } + void SetAllowFp16PrecisionForFp32(bool allow); // Get the half precision flag. // WARNING: This is an experimental API and subject to change. bool GetAllowFp16PrecisionForFp32() const { - return context_.allow_fp32_relax_to_fp16; + return context_->allow_fp32_relax_to_fp16; } // Owning handle to a TfLiteDelegate instance. @@ -366,18 +357,7 @@ class Interpreter { // it might require to copy the data from delegate buffer to raw memory. // WARNING: This is an experimental API and subject to change. TfLiteStatus EnsureTensorDataIsReadable(int tensor_index) { - TfLiteTensor* t = tensor(tensor_index); - TF_LITE_ENSURE(&context_, t != nullptr); - if (t->data_is_stale) { - TF_LITE_ENSURE(&context_, t->delegate != nullptr); - TF_LITE_ENSURE(&context_, t->buffer_handle != kTfLiteNullBufferHandle); - // This can be null if the delegate doesn't use its own buffer. - TF_LITE_ENSURE(&context_, t->delegate->CopyFromBufferHandle != nullptr); - t->delegate->CopyFromBufferHandle( - &context_, t->delegate, t->buffer_handle, t->data.raw, t->bytes); - t->data_is_stale = false; - } - return kTfLiteOk; + return primary_subgraph().EnsureTensorDataIsReadable(tensor_index); } // Set the delegate buffer handle to a tensor. It can be called in the @@ -400,9 +380,9 @@ class Interpreter { TfLiteBufferHandle* buffer_handle, TfLiteDelegate** delegate); - void SetProfiler(profiling::Profiler* profiler) { profiler_ = profiler; } + void SetProfiler(profiling::Profiler* profiler); - profiling::Profiler* GetProfiler() { return profiler_; } + profiling::Profiler* GetProfiler(); // The default capacity of `tensors_` vector. static constexpr int kTensorsReservedCapacity = 128; @@ -435,142 +415,47 @@ class Interpreter { const char* OpProfilingString(const TfLiteRegistration& op_reg, const TfLiteNode* node) const { if (op_reg.profiling_string == nullptr) return nullptr; - return op_reg.profiling_string(&context_, node); + return op_reg.profiling_string(context_, node); } // Set the value of an external context. void SetExternalContext(TfLiteExternalContextType type, TfLiteExternalContext* ctx); - private: - friend class InterpreterBuilder; - friend class InterpreterTest; - - // Prevent 'context_' from accessing functions that are only available to - // delegated kernels. - void SwitchToKernelContext(); - - // Add delegate-only functions to 'context_'. - void SwitchToDelegateContext(); + // Adds `subgraphs_to_add` subgraphs, preserving pre-existing Subgraph + // entries. The value pointed to by `first_new_subgraph_index` will be set to + // the index of the first new subgraph if `first_new_subgraph_index` is + // non-null. + // WARNING: This is an experimental API and subject to change. + void AddSubgraphs(int subgraphs_to_add, + int* first_new_subgraph_index = nullptr); - // Give 'op_reg' a chance to initialize itself using the contents of - // 'buffer'. - void* OpInit(const TfLiteRegistration& op_reg, const char* buffer, - size_t length) { - if (op_reg.init == nullptr) return nullptr; - return op_reg.init(&context_, buffer, length); - } + // Return the number of subgraphs in the model. + // WARNING: This is an experimental API and subject to change. + size_t subgraphs_size() const { return subgraphs_.size(); } - // Let 'op_reg' release any memory it might have allocated via 'OpInit'. - void OpFree(const TfLiteRegistration& op_reg, void* buffer) { - if (op_reg.free == nullptr) return; - if (buffer) { - op_reg.free(&context_, buffer); - } + // Get a pointer to a subgraph if in bounds. + // WARNING: This is an experimental API and subject to change. + Subgraph* subgraph(int subgraph_index) { + if (subgraph_index < 0 || + static_cast(subgraph_index) >= subgraphs_size()) + return nullptr; + return &*subgraphs_[subgraph_index]; } - // Prepare the given 'node' for execution. - TfLiteStatus OpPrepare(const TfLiteRegistration& op_reg, TfLiteNode* node) { - if (op_reg.prepare == nullptr) return kTfLiteOk; - return op_reg.prepare(&context_, node); + // WARNING: Experimental interface, subject to change + Subgraph& primary_subgraph() { + return *subgraphs_.front(); // Safe as subgraphs_ always has 1 entry. } - // Invoke the operator represented by 'node'. - TfLiteStatus OpInvoke(const TfLiteRegistration& op_reg, TfLiteNode* node) { - if (op_reg.invoke == nullptr) return kTfLiteError; - return op_reg.invoke(&context_, node); + // WARNING: Experimental interface, subject to change + const Subgraph& primary_subgraph() const { + return *subgraphs_.front(); // Safe as subgraphs_ always has 1 entry. } - // Call OpPrepare() for as many ops as possible, allocating memory for their - // tensors. If an op containing dynamic tensors is found, preparation will be - // postponed until this function is called again. This allows the interpreter - // to wait until Invoke() to resolve the sizes of dynamic tensors. - TfLiteStatus PrepareOpsAndTensors(); - - // Call OpPrepare() for all ops starting at 'first_node'. Stop when a - // dynamic tensors is found or all ops have been prepared. Fill - // 'last_node_prepared' with the id of the op containing dynamic tensors, or - // the last in the graph. - TfLiteStatus PrepareOpsStartingAt(int first_execution_plan_index, - int* last_execution_plan_index_prepared); - - // Tensors needed by the interpreter. Use `AddTensors` to add more blank - // tensor entries. Note, `tensors_.data()` needs to be synchronized to the - // `context_` whenever this std::vector is reallocated. Currently this - // only happens in `AddTensors()`. - std::vector tensors_; - - // Check if an array of tensor indices are valid with respect to the Tensor - // array. - // NOTE: this changes consistent_ to be false if indices are out of bounds. - TfLiteStatus CheckTensorIndices(const char* label, const int* indices, - int length); - - // Compute the number of bytes required to represent a tensor with dimensions - // specified by the array dims (of length dims_size). Returns the status code - // and bytes. - TfLiteStatus BytesRequired(TfLiteType type, const int* dims, size_t dims_size, - size_t* bytes); - - // Request an tensor be resized implementation. If the given tensor is of - // type kTfLiteDynamic it will also be allocated new memory. - TfLiteStatus ResizeTensorImpl(TfLiteTensor* tensor, TfLiteIntArray* new_size); - - // Report a detailed error string (will be printed to stderr). - // TODO(aselle): allow user of class to provide alternative destinations. - void ReportErrorImpl(const char* format, va_list args); - - // Entry point for C node plugin API to request an tensor be resized. - static TfLiteStatus ResizeTensor(TfLiteContext* context, TfLiteTensor* tensor, - TfLiteIntArray* new_size); - // Entry point for C node plugin API to report an error. - static void ReportError(TfLiteContext* context, const char* format, ...); - - // Entry point for C node plugin API to add new tensors. - static TfLiteStatus AddTensors(TfLiteContext* context, int tensors_to_add, - int* first_new_tensor_index); - - // WARNING: This is an experimental API and subject to change. - // Entry point for C API ReplaceNodeSubsetsWithDelegateKernels - static TfLiteStatus ReplaceNodeSubsetsWithDelegateKernels( - TfLiteContext* context, TfLiteRegistration registration, - const TfLiteIntArray* nodes_to_replace, TfLiteDelegate* delegate); - - // Update the execution graph to replace some of the nodes with stub - // nodes. Specifically any node index that has `nodes[index]==1` will be - // slated for replacement with a delegate kernel specified by registration. - // Ownership of 'nodes_to_replace' and 'delegate' remains with the caller. - // WARNING: This is an experimental interface that is subject to change. - TfLiteStatus ReplaceNodeSubsetsWithDelegateKernels( - TfLiteRegistration registration, const TfLiteIntArray* nodes_to_replace, - TfLiteDelegate* delegate); - - // WARNING: This is an experimental interface that is subject to change. - // Gets the internal pointer to a TensorFlow lite node by node_index. - TfLiteStatus GetNodeAndRegistration(int node_index, TfLiteNode** node, - TfLiteRegistration** registration); - - // WARNING: This is an experimental interface that is subject to change. - // Entry point for C node plugin API to get a node by index. - static TfLiteStatus GetNodeAndRegistration(struct TfLiteContext*, - int node_index, TfLiteNode** node, - TfLiteRegistration** registration); - - // WARNING: This is an experimental interface that is subject to change. - // Gets an TfLiteIntArray* representing the execution plan. The interpreter - // owns this memory and it is only guaranteed to exist during the invocation - // of the delegate prepare. - TfLiteStatus GetExecutionPlan(TfLiteIntArray** execution_plan); - - // WARNING: This is an experimental interface that is subject to change. - // Entry point for C node plugin API to get the execution plan. - static TfLiteStatus GetExecutionPlan(struct TfLiteContext* context, - TfLiteIntArray** execution_plan); - - // Retrieve an existing external context by type. - TfLiteExternalContext* GetExternalContext(TfLiteExternalContextType type); - static TfLiteExternalContext* GetExternalContext( - struct TfLiteContext* context, TfLiteExternalContextType type); + private: + friend class InterpreterBuilder; + friend class InterpreterTest; // Set the value of an external context. static void SetExternalContext(struct TfLiteContext* context, @@ -587,105 +472,28 @@ class Interpreter { return ModifyGraphWithDelegate(owned_delegates_.back().get()); } - // Ensures that `tensors_` has at least `kTensorsCapacityHeadroom` extra - // capacity. Calling this function may invalidate existing pointers to - // tensors. After calling this function, adding `kTensorsCapacityHeadroom` - // more tensors won't invalidate the pointer to existing tensors. - void EnsureTensorsVectorCapacity() { - const size_t required_capacity = tensors_size() + kTensorsCapacityHeadroom; - if (required_capacity > tensors_.capacity()) { - tensors_.reserve(required_capacity); - context_.tensors = tensors_.data(); - } - } - - // The state of the Interpreter. - enum State { - // The interpreter isn't ready to be invoked. - // `AllocateTensor` need to be called to enter an invokable state. - kStateUninvokable = 0, - // The interpreter is ready to be invoked. - kStateInvokable, - // The interpreter is ready to be invoked, and graph can't be further - // modified. The interpreter will enter this state when calling - // `ModifyGraphWithDelegate` with `allow_dynamic_tensors=false`. - kStateInvokableAndImmutable, - }; - State state_ = kStateUninvokable; - // A pure C data structure used to communicate with the pure C plugin // interface. To avoid copying tensor metadata, this is also the definitive // structure to store tensors. - TfLiteContext context_; - - // Node inputs/outputs are stored in TfLiteNode and TfLiteRegistration stores - // function pointers to actual implementation. - std::vector> - nodes_and_registration_; - - // Whether the model is consistent. That is to say if the inputs and outputs - // of every node and the global inputs and outputs are valid indexes into - // the tensor array. - bool consistent_ = true; - - // Array of indices representing the tensors that are inputs to the - // interpreter. - std::vector inputs_; - - // Array of indices representing the tensors that are outputs to the - // interpreter. - std::vector outputs_; - - // Array of indices representing the tensors that are variable tensors. - std::vector variables_; + // This is the primary subgraph context. + TfLiteContext* context_; // The error reporter delegate that tflite will forward queries errors to. ErrorReporter* error_reporter_; - // Index of the next node to prepare. - // During Invoke(), Interpreter will allocate input tensors first, which are - // known to be fixed size. Then it will allocate outputs from nodes as many - // as possible. When there is a node that produces dynamic sized tensor. - // Interpreter will stop allocating tensors, set the value of next allocate - // node id, and execute the node to generate the output tensor before continue - // to allocate successors. This process repeats until all nodes are executed. - // NOTE: this relies on the order of nodes that is in topological order. - int next_execution_plan_index_to_prepare_; - - // WARNING: This is an experimental interface that is subject to change. - // This is a list of node indices (to index into nodes_and_registration). - // This represents a valid topological sort (dependency ordered) execution - // plan. In particular, it is valid for this ordering to contain only a - // subset of the node indices. - std::vector execution_plan_; - - // In the future, we'd like a TfLiteIntArray compatible representation. - // TODO(aselle): replace execution_plan_ with this. - std::unique_ptr plan_cache_; - - // Whether to delegate to NN API - std::unique_ptr nnapi_delegate_; - // List of delegates that have been installed and are owned by this // interpreter instance. Useful if client delegate ownership is burdensome. // WARNING: This is an experimental API and subject to change. // TODO(b/116667551): Use TfLiteExternalContext for storing state. std::vector owned_delegates_; - std::unique_ptr memory_planner_; - bool allow_buffer_handle_output_ = false; - // Tracking bit for whether a tensor was resized in the course of an op - // invocation. This is a useful hint to ensure that dynamic tensor outputs - // trigger downstream reallocation after op invocation. - bool tensor_resized_since_op_invoke_ = false; - - // Profiler for this interpreter instance. - profiling::Profiler* profiler_ = nullptr; - // List of active external contexts. TfLiteExternalContext* external_contexts_[kTfLiteMaxExternalContexts]; + + // Subgraphs + std::vector> subgraphs_; }; } // namespace tflite diff --git a/tensorflow/lite/interpreter_test.cc b/tensorflow/lite/interpreter_test.cc index 7f03c3ceba..78b5d1b887 100644 --- a/tensorflow/lite/interpreter_test.cc +++ b/tensorflow/lite/interpreter_test.cc @@ -38,7 +38,7 @@ class InterpreterTest : public ::testing::Test { } protected: - TfLiteContext* GetInterpreterContext() { return &interpreter_.context_; } + TfLiteContext* GetInterpreterContext() { return interpreter_.context_; } Interpreter interpreter_; }; @@ -566,7 +566,7 @@ TEST(BasicInterpreter, ThreeStepAllocate) { DynamicBuffer buf; StringRef str_ref = GetString(input, 0); buf.AddString(str_ref); - buf.WriteToTensor(output); + buf.WriteToTensorAsVector(output); return kTfLiteOk; }; @@ -1090,17 +1090,17 @@ class TestDelegate : public ::testing::Test { TfLiteIntArrayFree(nodes_to_separate); return kTfLiteOk; }; - delegate_.CopyToBufferHandle = - [](TfLiteContext* context, TfLiteDelegate* delegate, - TfLiteBufferHandle buffer_handle, void* data, - size_t size) -> TfLiteStatus { + delegate_.CopyToBufferHandle = [](TfLiteContext* context, + TfLiteDelegate* delegate, + TfLiteBufferHandle buffer_handle, + TfLiteTensor* tensor) -> TfLiteStatus { // TODO(ycling): Implement tests to test buffer copying logic. return kTfLiteOk; }; delegate_.CopyFromBufferHandle = [](TfLiteContext* context, TfLiteDelegate* delegate, - TfLiteBufferHandle buffer_handle, void* data, - size_t size) -> TfLiteStatus { + TfLiteBufferHandle buffer_handle, + TfLiteTensor* output) -> TfLiteStatus { // TODO(ycling): Implement tests to test buffer copying logic. return kTfLiteOk; }; diff --git a/tensorflow/lite/java/src/main/java/org/tensorflow/lite/DataType.java b/tensorflow/lite/java/src/main/java/org/tensorflow/lite/DataType.java index 41093e8ffe..bd47574f71 100644 --- a/tensorflow/lite/java/src/main/java/org/tensorflow/lite/DataType.java +++ b/tensorflow/lite/java/src/main/java/org/tensorflow/lite/DataType.java @@ -27,7 +27,10 @@ public enum DataType { UINT8(3), /** 64-bit signed integer. */ - INT64(4); + INT64(4), + + /** Strings. */ + STRING(5); private final int value; @@ -46,6 +49,8 @@ public enum DataType { return 1; case INT64: return 8; + case STRING: + return -1; } throw new IllegalArgumentException( "DataType error: DataType " + this + " is not supported yet"); @@ -82,6 +87,8 @@ public enum DataType { return "byte"; case INT64: return "long"; + case STRING: + return "string"; } throw new IllegalArgumentException( "DataType error: DataType " + this + " is not supported yet"); diff --git a/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Tensor.java b/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Tensor.java index 6ca47aa3ed..7aa24b4198 100644 --- a/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Tensor.java +++ b/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Tensor.java @@ -162,6 +162,8 @@ public final class Tensor { return DataType.UINT8; } else if (long.class.equals(c)) { return DataType.INT64; + } else if (String.class.equals(c)) { + return DataType.STRING; } } throw new IllegalArgumentException( diff --git a/tensorflow/lite/java/src/main/native/BUILD b/tensorflow/lite/java/src/main/native/BUILD index 2abba24345..8f95f14518 100644 --- a/tensorflow/lite/java/src/main/native/BUILD +++ b/tensorflow/lite/java/src/main/native/BUILD @@ -43,6 +43,7 @@ cc_library( "//tensorflow/lite:context", "//tensorflow/lite:framework", "//tensorflow/lite:schema_fbs_version", + "//tensorflow/lite:string_util", ], alwayslink = 1, ) diff --git a/tensorflow/lite/java/src/main/native/nativeinterpreterwrapper_jni.cc b/tensorflow/lite/java/src/main/native/nativeinterpreterwrapper_jni.cc index c7389c5811..1e98f94250 100644 --- a/tensorflow/lite/java/src/main/native/nativeinterpreterwrapper_jni.cc +++ b/tensorflow/lite/java/src/main/native/nativeinterpreterwrapper_jni.cc @@ -78,6 +78,8 @@ int getDataType(TfLiteType data_type) { return 3; case kTfLiteInt64: return 4; + case kTfLiteString: + return 5; default: return -1; } diff --git a/tensorflow/lite/java/src/main/native/tensor_jni.cc b/tensorflow/lite/java/src/main/native/tensor_jni.cc index 1d813d50da..82d2679de9 100644 --- a/tensorflow/lite/java/src/main/native/tensor_jni.cc +++ b/tensorflow/lite/java/src/main/native/tensor_jni.cc @@ -16,8 +16,10 @@ limitations under the License. #include "tensorflow/lite/java/src/main/native/tensor_jni.h" #include #include +#include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/interpreter.h" #include "tensorflow/lite/java/src/main/native/exception_jni.h" +#include "tensorflow/lite/string_util.h" namespace { @@ -48,7 +50,7 @@ TfLiteTensor* GetTensorFromHandle(JNIEnv* env, jlong handle) { return reinterpret_cast(handle)->tensor(); } -size_t elementByteSize(TfLiteType data_type) { +size_t ElementByteSize(TfLiteType data_type) { // The code in this file makes the assumption that the // TensorFlow TF_DataTypes and the Java primitive types // have the same byte sizes. Validate that: @@ -77,11 +79,11 @@ size_t elementByteSize(TfLiteType data_type) { } } -size_t writeOneDimensionalArray(JNIEnv* env, jobject object, TfLiteType type, +size_t WriteOneDimensionalArray(JNIEnv* env, jobject object, TfLiteType type, void* dst, size_t dst_size) { jarray array = static_cast(object); const int num_elements = env->GetArrayLength(array); - size_t to_copy = num_elements * elementByteSize(type); + size_t to_copy = num_elements * ElementByteSize(type); if (to_copy > dst_size) { throwException(env, kIllegalStateException, "Internal error: cannot write Java array of %d bytes to " @@ -126,10 +128,10 @@ size_t writeOneDimensionalArray(JNIEnv* env, jobject object, TfLiteType type, } } -size_t readOneDimensionalArray(JNIEnv* env, TfLiteType data_type, +size_t ReadOneDimensionalArray(JNIEnv* env, TfLiteType data_type, const void* src, size_t src_size, jarray dst) { const int len = env->GetArrayLength(dst); - const size_t size = len * elementByteSize(data_type); + const size_t size = len * ElementByteSize(data_type); if (size > src_size) { throwException( env, kIllegalStateException, @@ -170,17 +172,17 @@ size_t readOneDimensionalArray(JNIEnv* env, TfLiteType data_type, return 0; } -size_t readMultiDimensionalArray(JNIEnv* env, TfLiteType data_type, char* src, +size_t ReadMultiDimensionalArray(JNIEnv* env, TfLiteType data_type, char* src, size_t src_size, int dims_left, jarray dst) { if (dims_left == 1) { - return readOneDimensionalArray(env, data_type, src, src_size, dst); + return ReadOneDimensionalArray(env, data_type, src, src_size, dst); } else { jobjectArray ndarray = static_cast(dst); int len = env->GetArrayLength(ndarray); size_t size = 0; for (int i = 0; i < len; ++i) { jarray row = static_cast(env->GetObjectArrayElement(ndarray, i)); - size += readMultiDimensionalArray(env, data_type, src + size, + size += ReadMultiDimensionalArray(env, data_type, src + size, src_size - size, dims_left - 1, row); env->DeleteLocalRef(row); if (env->ExceptionCheck()) return size; @@ -189,10 +191,43 @@ size_t readMultiDimensionalArray(JNIEnv* env, TfLiteType data_type, char* src, } } -size_t writeMultiDimensionalArray(JNIEnv* env, jobject src, TfLiteType type, +// Returns the total number of strings read. +int ReadMultiDimensionalStringArray(JNIEnv* env, TfLiteTensor* tensor, + int dims_left, int start_str_index, + jarray dst) { + jobjectArray object_array = static_cast(dst); + int len = env->GetArrayLength(object_array); + int num_strings_read = 0; + + // If dst is a 1-dimensional array, copy the strings into it. Else + // recursively call ReadMultiDimensionalStringArray over sub-dimensions. + if (dims_left == 1) { + for (int i = 0; i < len; ++i) { + const tflite::StringRef strref = + tflite::GetString(tensor, start_str_index + num_strings_read); + jstring string_dest = env->NewStringUTF(strref.str); + env->SetObjectArrayElement(object_array, i, string_dest); + env->DeleteLocalRef(string_dest); + ++num_strings_read; + } + } else { + for (int i = 0; i < len; ++i) { + jarray row = + static_cast(env->GetObjectArrayElement(object_array, i)); + num_strings_read += ReadMultiDimensionalStringArray( + env, tensor, dims_left - 1, start_str_index + num_strings_read, row); + env->DeleteLocalRef(row); + if (env->ExceptionCheck()) return num_strings_read; + } + } + + return num_strings_read; +} + +size_t WriteMultiDimensionalArray(JNIEnv* env, jobject src, TfLiteType type, int dims_left, char** dst, int dst_size) { if (dims_left <= 1) { - return writeOneDimensionalArray(env, src, type, *dst, dst_size); + return WriteOneDimensionalArray(env, src, type, *dst, dst_size); } else { jobjectArray ndarray = static_cast(src); int len = env->GetArrayLength(ndarray); @@ -200,7 +235,7 @@ size_t writeMultiDimensionalArray(JNIEnv* env, jobject src, TfLiteType type, for (int i = 0; i < len; ++i) { jobject row = env->GetObjectArrayElement(ndarray, i); char* next_dst = *dst + sz; - sz += writeMultiDimensionalArray(env, row, type, dims_left - 1, &next_dst, + sz += WriteMultiDimensionalArray(env, row, type, dims_left - 1, &next_dst, dst_size - sz); env->DeleteLocalRef(row); if (env->ExceptionCheck()) return sz; @@ -209,6 +244,44 @@ size_t writeMultiDimensionalArray(JNIEnv* env, jobject src, TfLiteType type, } } +void PopulateStringDynamicBuffer(JNIEnv* env, jobject src, + tflite::DynamicBuffer* dst_buffer, + int dims_left) { + jobjectArray object_array = static_cast(src); + const int num_elements = env->GetArrayLength(object_array); + + // If src is a 1-dimensional array, add the strings into dst_buffer. Else + // recursively call populateStringDynamicBuffer over sub-dimensions. + if (dims_left <= 1) { + for (int i = 0; i < num_elements; ++i) { + jstring string_obj = + static_cast(env->GetObjectArrayElement(object_array, i)); + const char* chars = env->GetStringUTFChars(string_obj, nullptr); + // + 1 for terminating character. + const int byte_len = env->GetStringUTFLength(string_obj) + 1; + dst_buffer->AddString(chars, byte_len); + env->ReleaseStringUTFChars(string_obj, chars); + env->DeleteLocalRef(string_obj); + } + } else { + for (int i = 0; i < num_elements; ++i) { + jobject row = env->GetObjectArrayElement(object_array, i); + PopulateStringDynamicBuffer(env, row, dst_buffer, dims_left - 1); + env->DeleteLocalRef(row); + if (env->ExceptionCheck()) return; + } + } +} + +void WriteMultiDimensionalStringArray(JNIEnv* env, jobject src, + TfLiteTensor* tensor) { + tflite::DynamicBuffer dst_buffer; + PopulateStringDynamicBuffer(env, src, &dst_buffer, tensor->dims->size); + if (!env->ExceptionCheck()) { + dst_buffer.WriteToTensor(tensor, /*new_shape=*/nullptr); + } +} + } // namespace JNIEXPORT jlong JNICALL Java_org_tensorflow_lite_Tensor_create( @@ -266,8 +339,14 @@ Java_org_tensorflow_lite_Tensor_readMultiDimensionalArray(JNIEnv* env, "Internal error: Cannot copy empty/scalar Tensors."); return; } - readMultiDimensionalArray(env, tensor->type, tensor->data.raw, tensor->bytes, - num_dims, static_cast(value)); + if (tensor->type == kTfLiteString) { + ReadMultiDimensionalStringArray(env, tensor, num_dims, 0, + static_cast(value)); + } else { + ReadMultiDimensionalArray(env, tensor->type, tensor->data.raw, + tensor->bytes, num_dims, + static_cast(value)); + } } JNIEXPORT void JNICALL @@ -277,7 +356,7 @@ Java_org_tensorflow_lite_Tensor_writeMultiDimensionalArray(JNIEnv* env, jobject src) { TfLiteTensor* tensor = GetTensorFromHandle(env, handle); if (tensor == nullptr) return; - if (tensor->data.raw == nullptr) { + if (tensor->type != kTfLiteString && tensor->data.raw == nullptr) { throwException(env, kIllegalArgumentException, "Internal error: Target Tensor hasn't been allocated."); return; @@ -287,8 +366,12 @@ Java_org_tensorflow_lite_Tensor_writeMultiDimensionalArray(JNIEnv* env, "Internal error: Cannot copy empty/scalar Tensors."); return; } - writeMultiDimensionalArray(env, src, tensor->type, tensor->dims->size, - &tensor->data.raw, tensor->bytes); + if (tensor->type == kTfLiteString) { + WriteMultiDimensionalStringArray(env, src, tensor); + } else { + WriteMultiDimensionalArray(env, src, tensor->type, tensor->dims->size, + &tensor->data.raw, tensor->bytes); + } } JNIEXPORT jint JNICALL Java_org_tensorflow_lite_Tensor_dtype(JNIEnv* env, diff --git a/tensorflow/lite/java/src/test/java/org/tensorflow/lite/DataTypeTest.java b/tensorflow/lite/java/src/test/java/org/tensorflow/lite/DataTypeTest.java index 6d6417f895..8412ec0e9d 100644 --- a/tensorflow/lite/java/src/test/java/org/tensorflow/lite/DataTypeTest.java +++ b/tensorflow/lite/java/src/test/java/org/tensorflow/lite/DataTypeTest.java @@ -30,6 +30,7 @@ public final class DataTypeTest { assertThat(DataType.INT32.byteSize()).isEqualTo(4); assertThat(DataType.UINT8.byteSize()).isEqualTo(1); assertThat(DataType.INT64.byteSize()).isEqualTo(8); + assertThat(DataType.STRING.byteSize()).isEqualTo(-1); } @Test diff --git a/tensorflow/lite/java/src/test/java/org/tensorflow/lite/NativeInterpreterWrapperTest.java b/tensorflow/lite/java/src/test/java/org/tensorflow/lite/NativeInterpreterWrapperTest.java index 07d334c33b..b00efa77cb 100644 --- a/tensorflow/lite/java/src/test/java/org/tensorflow/lite/NativeInterpreterWrapperTest.java +++ b/tensorflow/lite/java/src/test/java/org/tensorflow/lite/NativeInterpreterWrapperTest.java @@ -43,6 +43,9 @@ public final class NativeInterpreterWrapperTest { private static final String BYTE_MODEL_PATH = "tensorflow/lite/java/src/testdata/uint8.bin"; + private static final String STRING_MODEL_PATH = + "tensorflow/lite/java/src/testdata/string.bin"; + private static final String QUANTIZED_MODEL_PATH = "tensorflow/lite/java/src/testdata/quantized.bin"; @@ -224,6 +227,50 @@ public final class NativeInterpreterWrapperTest { wrapper.close(); } + @Test + public void testRunWithString() { + NativeInterpreterWrapper wrapper = new NativeInterpreterWrapper(STRING_MODEL_PATH); + String[] oneD = {"s1", "s22", "s333"}; + String[][] twoD = {oneD, oneD, oneD, oneD, oneD, oneD, oneD, oneD}; + String[][][] threeD = {twoD, twoD, twoD, twoD, twoD, twoD, twoD, twoD}; + String[][][][] fourD = {threeD, threeD}; + Object[] inputs = {fourD}; + String[][][][] parsedOutputs = new String[2][4][4][12]; + Map outputs = new HashMap<>(); + outputs.put(0, parsedOutputs); + wrapper.run(inputs, outputs); + String[] outputOneD = parsedOutputs[0][0][0]; + String[] expected = { + "s1", "s22", "s333", "s1", "s22", "s333", "s1", "s22", "s333", "s1", "s22", "s333" + }; + assertThat(outputOneD).isEqualTo(expected); + wrapper.close(); + } + + @Test + public void testRunWithString_wrongShapeError() { + NativeInterpreterWrapper wrapper = new NativeInterpreterWrapper(STRING_MODEL_PATH); + String[] oneD = {"s1", "s22", "s333"}; + String[][] twoD = {oneD, oneD, oneD, oneD, oneD, oneD, oneD, oneD}; + String[][][] threeD = {twoD, twoD, twoD, twoD, twoD, twoD, twoD, twoD}; + String[][][][] fourD = {threeD, threeD}; + Object[] inputs = {fourD}; + String[][][][] parsedOutputs = new String[2][4][4][10]; + Map outputs = new HashMap<>(); + outputs.put(0, parsedOutputs); + try { + wrapper.run(inputs, outputs); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e) + .hasMessageThat() + .contains( + "Cannot copy between a TensorFlowLite tensor with shape [2, 4, 4, 12] and " + + "a Java object with shape [2, 4, 4, 10]"); + } + wrapper.close(); + } + @Test public void testRunWithByteBufferHavingBytes() { NativeInterpreterWrapper wrapper = new NativeInterpreterWrapper(BYTE_MODEL_PATH); diff --git a/tensorflow/lite/java/src/testdata/string.bin b/tensorflow/lite/java/src/testdata/string.bin new file mode 100644 index 0000000000000000000000000000000000000000..36a2509acdfa17841d0c128674e7b4e382ad00fc GIT binary patch literal 584 zcmb1OU|3JeSkj0_A6 z2@DJj{2+b)&i)F{`FUljMJ1^zdJHTK3=Ad=3=BF95IrFNihuwAhyDBiAH)`5U|?Wk zU;wKF@j>RE`1k++nScNP^Dv0OZ3l^i>=I#MVBlb2V31*i*bA~7gh6J2+*ZKAz_0^q zUflox{}~tAXYL2@ATi%W_!^U~up^9o8!7{K=Mfb9pV0hs~P z2eONSq23unGcX*2*ueyn2bl??RiI%4QqRl4zz~#LoRL_Nst+c?Zes)c7ZSc44D3kZ z3v(~Xe2{w$!0Iu>2xM-4X-Pq8Nqk9aUU7aASRD)4T##N+9Evc2NKovtGl1O1z#zf^ z3O@!020;)XB&)%|09FNZI|zgP4bl(7AT|R78v_Re3j-V2d`LWj)Pej4!k};isRhvx Mwd`QE3=9ln00k8^3;+NC literal 0 HcmV?d00001 diff --git a/tensorflow/lite/kernels/BUILD b/tensorflow/lite/kernels/BUILD index 010ba83466..00d9d1feae 100644 --- a/tensorflow/lite/kernels/BUILD +++ b/tensorflow/lite/kernels/BUILD @@ -183,6 +183,7 @@ cc_library( "exp.cc", "expand_dims.cc", "fake_quant.cc", + "fill.cc", "floor.cc", "floor_div.cc", "floor_mod.cc", @@ -197,6 +198,7 @@ cc_library( "lstm.cc", "maximum_minimum.cc", "mfcc.cc", + "mirror_pad.cc", "mul.cc", "neg.cc", "one_hot.cc", @@ -219,6 +221,8 @@ cc_library( "sparse_output_fully_connected.cc", "sparse_to_dense.cc", "split.cc", + "split_v.cc", + "squared_difference.cc", "squeeze.cc", "strided_slice.cc", "sub.cc", @@ -1064,6 +1068,22 @@ tf_cc_test( ], ) +tf_cc_test( + name = "split_v_test", + size = "small", + srcs = ["split_v_test.cc"], + tags = [ + "no_oss", + "tflite_not_portable_ios", + ], + deps = [ + ":builtin_ops", + "//tensorflow/lite:framework", + "//tensorflow/lite/kernels:test_util", + "@com_google_googletest//:gtest", + ], +) + tf_cc_test( name = "squeeze_test", size = "small", @@ -1379,6 +1399,32 @@ tf_cc_test( ], ) +tf_cc_test( + name = "squared_difference_test", + size = "small", + srcs = ["squared_difference_test.cc"], + tags = ["tflite_not_portable_ios"], + deps = [ + ":builtin_ops", + "//tensorflow/lite:framework", + "//tensorflow/lite/kernels:test_util", + "@com_google_googletest//:gtest", + ], +) + +tf_cc_test( + name = "fill_test", + size = "small", + srcs = ["fill_test.cc"], + tags = ["tflite_not_portable_ios"], + deps = [ + ":builtin_ops", + "//tensorflow/lite:framework", + "//tensorflow/lite/kernels:test_util", + "@com_google_googletest//:gtest", + ], +) + filegroup( name = "all_files", srcs = glob( @@ -1392,3 +1438,14 @@ filegroup( ) tflite_portable_test_suite() + +tf_cc_test( + name = "mirror_pad_test", + srcs = ["mirror_pad_test.cc"], + deps = [ + ":builtin_ops", + ":test_util", + "//tensorflow/lite:framework", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/tensorflow/lite/kernels/activations.cc b/tensorflow/lite/kernels/activations.cc index 9c525d9640..a766542560 100644 --- a/tensorflow/lite/kernels/activations.cc +++ b/tensorflow/lite/kernels/activations.cc @@ -45,6 +45,11 @@ struct LogSoftmaxOpData : public OpData { int32_t reverse_scaling_right_shift = 0; }; +struct PreluOpData : public OpData { + int32_t output_multiplier = 0; + int output_shift = 0; +}; + void* Init(TfLiteContext* context, const char* buffer, size_t length) { // This is a builtin op, so we don't use the contents in 'buffer', if any. // Instead, we allocate a new object to carry information from Prepare() to @@ -57,6 +62,10 @@ void* LogSoftmaxInit(TfLiteContext* context, const char* buffer, return new LogSoftmaxOpData; } +void* PreluInit(TfLiteContext* context, const char* buffer, size_t length) { + return new PreluOpData; +} + void Free(TfLiteContext* context, void* buffer) { delete reinterpret_cast(buffer); } @@ -65,6 +74,10 @@ void LogSoftmaxFree(TfLiteContext* context, void* buffer) { delete reinterpret_cast(buffer); } +void PreluFree(TfLiteContext* context, void* buffer) { + delete reinterpret_cast(buffer); +} + TfLiteStatus GenericPrepare(TfLiteContext* context, TfLiteNode* node) { TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); @@ -253,13 +266,18 @@ TfLiteStatus PreluPrepare(TfLiteContext* context, TfLiteNode* node) { const TfLiteTensor* input = GetInput(context, node, 0); TfLiteTensor* output = GetOutput(context, node, 0); const TfLiteTensor* alpha = GetInput(context, node, 1); + PreluOpData* data = reinterpret_cast(node->user_data); - // Currently only Float32 is supported - // TODO(ycling): Support other data types. - TF_LITE_ENSURE_EQ(context, input->type, kTfLiteFloat32); - TF_LITE_ENSURE_EQ(context, alpha->type, kTfLiteFloat32); + TF_LITE_ENSURE_EQ(context, input->type, alpha->type); output->type = input->type; + if (output->type == kTfLiteUInt8 || output->type == kTfLiteInt16) { + double real_multiplier = + input->params.scale * alpha->params.scale / output->params.scale; + QuantizeMultiplierSmallerThanOneExp( + real_multiplier, &data->output_multiplier, &data->output_shift); + } + // PRelu (parameteric Relu) shares the same alpha value on "shared axis". // This means it's always required to "broadcast" alpha values in PRelu. TfLiteIntArray* output_size = nullptr; @@ -288,8 +306,8 @@ TfLiteStatus ReluEval(TfLiteContext* context, TfLiteNode* node) { return kTfLiteOk; } break; default: - context->ReportError(context, "Only float32 supported currently, got %d.", - input->type); + context->ReportError(context, "Only float32 supported currently, got %s.", + TfLiteTypeGetName(input->type)); return kTfLiteError; } } @@ -309,8 +327,8 @@ TfLiteStatus Relu1Eval(TfLiteContext* context, TfLiteNode* node) { return kTfLiteOk; } break; default: - context->ReportError(context, "Only float32 supported currently, got %d.", - input->type); + context->ReportError(context, "Only float32 supported currently, got %s.", + TfLiteTypeGetName(input->type)); return kTfLiteError; } } @@ -327,9 +345,24 @@ TfLiteStatus Relu6Eval(TfLiteContext* context, TfLiteNode* node) { for (; in < in_end; in++, out++) *out = std::min(std::max(0.f, *in), 6.f); return kTfLiteOk; } break; + case kTfLiteUInt8: { + ActivationParams params; + params.activation_type = FusedActivationFunctionType::kRelu6; + params.quantized_activation_min = std::max( + 0, output->params.zero_point + + static_cast(roundf(0.f / output->params.scale))); + params.quantized_activation_max = std::min( + 255, output->params.zero_point + + static_cast(roundf(6.f / output->params.scale))); + optimized_ops::ReluX(params, GetTensorShape(input), + GetTensorData(input), GetTensorShape(output), + GetTensorData(output)); + return kTfLiteOk; + } break; default: - context->ReportError(context, "Only float32 supported currently, got %d.", - input->type); + context->ReportError( + context, "Only float32 and uint8 supported currently, got %s.", + TfLiteTypeGetName(input->type)); return kTfLiteError; } } @@ -367,8 +400,8 @@ TfLiteStatus TanhEval(TfLiteContext* context, TfLiteNode* node) { return kTfLiteOk; } break; default: - context->ReportError(context, "Only float32 supported currently, got %d.", - input->type); + context->ReportError(context, "Only float32 supported currently, got %s.", + TfLiteTypeGetName(input->type)); return kTfLiteError; } } @@ -407,9 +440,8 @@ TfLiteStatus SigmoidEval(TfLiteContext* context, TfLiteNode* node) { break; } default: - context->ReportError(context, "Only float32 supported currently, got %d.", - input->type); - return kTfLiteError; + context->ReportError(context, "Only float32 supported currently, got %s.", + TfLiteTypeGetName(input->type)); } return kTfLiteOk; } @@ -604,8 +636,8 @@ TfLiteStatus SoftmaxEval(TfLiteContext* context, TfLiteNode* node) { } default: context->ReportError( - context, "Only float32 and uint8_t supported currently, got %d.", - input->type); + context, "Only float32 and uint8_t supported currently, got %s.", + TfLiteTypeGetName(input->type)); return kTfLiteError; } } @@ -636,8 +668,8 @@ TfLiteStatus LogSoftmaxEval(TfLiteContext* context, TfLiteNode* node) { return kTfLiteOk; } default: - context->ReportError(context, "Only float32 supported currently., got %d", - input->type); + context->ReportError(context, "Only float32 supported currently., got %s", + TfLiteTypeGetName(input->type)); return kTfLiteError; } } @@ -651,16 +683,57 @@ TfLiteStatus PreluEval(TfLiteContext* context, TfLiteNode* node) { const TfLiteTensor* input = GetInput(context, node, 0); const TfLiteTensor* alpha = GetInput(context, node, 1); TfLiteTensor* output = GetOutput(context, node, 0); - if (input->type != kTfLiteFloat32) { - context->ReportError(context, "Only float32 supported currently, got %d.", - input->type); - return kTfLiteError; + const PreluOpData* data = reinterpret_cast(node->user_data); + switch (input->type) { + case kTfLiteFloat32: { + reference_ops::BroadcastBinaryFunction4DSlow( + GetTensorShape(input), GetTensorData(input), + GetTensorShape(alpha), GetTensorData(alpha), + GetTensorShape(output), GetTensorData(output), + ApplyPrelu); + return kTfLiteOk; + } break; + case kTfLiteUInt8: { + PreluParams op_params; + op_params.input_offset = -input->params.zero_point; + op_params.alpha_offset = -alpha->params.zero_point; + op_params.output_offset = output->params.zero_point; + op_params.output_multiplier = data->output_multiplier; + op_params.output_shift = data->output_shift; + reference_ops::BroadcastPrelu4DSlow( + op_params, GetTensorShape(input), GetTensorData(input), + GetTensorShape(alpha), GetTensorData(alpha), + GetTensorShape(output), GetTensorData(output)); + return kTfLiteOk; + } break; + default: + context->ReportError(context, + "Only float32, uint8 supported currently, got %d.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; + } +} + +TfLiteStatus LeakyReluEval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteTensor* input = GetInput(context, node, 0); + TfLiteTensor* output = GetOutput(context, node, 0); + const auto* params = + reinterpret_cast(node->builtin_data); + + LeakyReluParams op_params; + op_params.alpha = params->alpha; + switch (input->type) { + case kTfLiteFloat32: { + optimized_ops::LeakyRelu( + op_params, GetTensorShape(input), GetTensorData(input), + GetTensorShape(output), GetTensorData(output)); + return kTfLiteOk; + } break; + default: + context->ReportError(context, "Only float32 supported currently, got %s.", + TfLiteTypeGetName(input->type)); + return kTfLiteError; } - reference_ops::BroadcastBinaryFunction4DSlow( - GetTensorShape(input), GetTensorData(input), GetTensorShape(alpha), - GetTensorData(alpha), GetTensorShape(output), - GetTensorData(output), ApplyPrelu); - return kTfLiteOk; } } // namespace activations @@ -715,12 +788,19 @@ TfLiteRegistration* Register_LOG_SOFTMAX() { } TfLiteRegistration* Register_PRELU() { - static TfLiteRegistration r = {/*init=*/nullptr, /*free=*/nullptr, + static TfLiteRegistration r = {activations::PreluInit, activations::PreluFree, activations::PreluPrepare, activations::PreluEval}; return &r; } +TfLiteRegistration* Register_LEAKY_RELU() { + static TfLiteRegistration r = {/*init=*/nullptr, /*free=*/nullptr, + activations::GenericPrepare, + activations::LeakyReluEval}; + return &r; +} + } // namespace builtin } // namespace ops } // namespace tflite diff --git a/tensorflow/lite/kernels/activations_test.cc b/tensorflow/lite/kernels/activations_test.cc index fff4121dc0..67f137baff 100644 --- a/tensorflow/lite/kernels/activations_test.cc +++ b/tensorflow/lite/kernels/activations_test.cc @@ -170,6 +170,29 @@ TEST(FloatActivationsOpTest, Tanh) { }))); } +TEST(QuantizedActivationsOpTest, Relu6) { + const float kMin = -1; + const float kMax = 127.f / 128.f; + QuantizedActivationsOpModel m( + BuiltinOperator_RELU6, + /*input=*/{TensorType_UINT8, {1, 2, 4, 1}, 8 * kMin, 8 * kMax}, + /*output=*/{TensorType_UINT8, {1, 2, 4, 1}, 8 * kMin, 8 * kMax}); + m.SetInput({ + 0, -6, 2, 4, // + 3, -2, 10, 1, // + }); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear( + { + 0, 0, 2, 4, // + 3, 0, 6, 1, // + }, + kQuantizedTolerance))); + EXPECT_THAT(m.GetOutput(), + ElementsAreArray({128, 128, 160, 192, 176, 128, 224, 144})); +} + TEST(QuantizedActivationsOpTest, Tanh) { const float kMin = -1; const float kMax = 127.f / 128.f; @@ -563,15 +586,29 @@ TEST(QuantizedActivationsOpTest, LogSoftmax) { ElementsAreArray({189, 93, 221, 253, 142, 63, 255, 111})); } -class PReluOpModel : public SingleOpModel { +// A base class of PRelu op model. It provides the constructor for +// FloatPReluOpModel and QuantizedPReluOpModel. +class BasePReluOpModel : public SingleOpModel { public: - PReluOpModel(const TensorData& input, const TensorData& alpha) { + BasePReluOpModel(const TensorData& input, const TensorData& alpha) { input_ = AddInput(input); alpha_ = AddInput(alpha); - output_ = AddOutput(input); + output_ = AddOutput({input.type, input.shape, input.min, input.max}); SetBuiltinOp(BuiltinOperator_PRELU, BuiltinOptions_NONE, 0); BuildInterpreter({GetShape(input_), GetShape(alpha_)}); } + + protected: + int input_; + int alpha_; + int output_; +}; + +// The FloatPReluOpModel class handles float input and output. +class FloatPReluOpModel : public BasePReluOpModel { + public: + using BasePReluOpModel::BasePReluOpModel; + void SetInput(std::initializer_list data) { PopulateTensor(input_, data); } @@ -579,16 +616,35 @@ class PReluOpModel : public SingleOpModel { PopulateTensor(alpha_, data); } std::vector GetOutput() { return ExtractVector(output_); } +}; - protected: - int input_; - int alpha_; - int output_; +// The QuantizedPReluOpModel class handles quantized input and output. +class QuantizedPReluOpModel : public BasePReluOpModel { + public: + using BasePReluOpModel::BasePReluOpModel; + + template + void SetInput(std::initializer_list data) { + QuantizeAndPopulate(input_, data); + } + template + void SetAlpha(std::initializer_list data) { + QuantizeAndPopulate(alpha_, data); + } + template + std::vector GetOutput() { + return ExtractVector(output_); + } + template + std::vector GetDequantizedOutput() { + return Dequantize(ExtractVector(output_), GetScale(output_), + GetZeroPoint(output_)); + } }; TEST(FloatActivationsOpTest, PRelu) { - PReluOpModel m({TensorType_FLOAT32, {1, 2, 2, 3}}, - {TensorType_FLOAT32, {1, 1, 3}}); + FloatPReluOpModel m({TensorType_FLOAT32, {1, 2, 2, 3}}, + {TensorType_FLOAT32, {1, 1, 3}}); m.SetInput({ 0.0f, 0.0f, 0.0f, // Row 1, Column 1 @@ -606,6 +662,69 @@ TEST(FloatActivationsOpTest, PRelu) { })); } +TEST(QuantizedActivationsOpTest, PRelu) { + const float kMin = -1; + const float kMax = 127.f / 128.f; + QuantizedPReluOpModel m({TensorType_UINT8, {1, 2, 2, 3}, kMin, kMax}, + {TensorType_UINT8, {1, 1, 3}, kMin, kMax}); + m.SetInput({ + 0.0f, 0.0f, 0.0f, // Row 1, Column 1 + 0.5f, 0.5f, 0.5f, // Row 1, Column 2 + -1.0f, -1.0f, -1.0f, // Row 2, Column 1 + -0.25f, -0.25f, -0.25f, // Row 1, Column 2 + }); + m.SetAlpha({0.0f, 0.5f, -0.5f}); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear( + { + 0.0f, 0.0f, 0.0f, // Row 1, Column 1 + 0.5f, 0.5f, 0.5f, // Row 1, Column 2 + 0.0f, -0.5f, 0.5f, // Row 2, Column 1 + 0.0f, -0.125f, 0.125f, // Row 1, Column 2 + }, + kQuantizedTolerance))); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({ + 128, 128, 128, // Row 1, Column 1 + 192, 192, 192, // Row 1, Column 2 + 128, 64, 192, // Row 2, Column 1 + 128, 112, 144, // Row 1, Column 2 + })); +} + +class LeakyReluOpModel : public SingleOpModel { + public: + LeakyReluOpModel(const TensorData& input, float alpha) { + input_ = AddInput(input); + output_ = AddOutput(input); + SetBuiltinOp(BuiltinOperator_LEAKY_RELU, BuiltinOptions_LeakyReluOptions, + CreateLeakyReluOptions(builder_, alpha).Union()); + BuildInterpreter({GetShape(input_)}); + } + void SetInput(std::initializer_list data) { + PopulateTensor(input_, data); + } + std::vector GetOutput() { return ExtractVector(output_); } + + protected: + int input_; + int output_; +}; + +TEST(FloatActivationsOpTest, LeakyRelu) { + LeakyReluOpModel m({TensorType_FLOAT32, {2, 3}}, 0.5f); + + m.SetInput({ + 0.0f, 1.0f, 3.0f, // Row 1 + 1.0f, -1.0f, -2.0f, // Row 2 + }); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({ + 0.0f, 1.0f, 3.0f, // Row 1 + 1.0f, -0.5f, -1.0f, // Row 2 + })); +} + } // namespace } // namespace tflite diff --git a/tensorflow/lite/kernels/conv.cc b/tensorflow/lite/kernels/conv.cc index 0c14b9eb65..1fd870be93 100644 --- a/tensorflow/lite/kernels/conv.cc +++ b/tensorflow/lite/kernels/conv.cc @@ -24,7 +24,6 @@ limitations under the License. #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/kernels/eigen_support.h" #include "tensorflow/lite/kernels/gemm_support.h" -#include "tensorflow/lite/kernels/internal/optimized/cblas_conv.h" #include "tensorflow/lite/kernels/internal/optimized/multithreaded_conv.h" #include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" #include "tensorflow/lite/kernels/internal/quantization_util.h" @@ -491,11 +490,10 @@ void EvalFloat(TfLiteContext* context, TfLiteNode* node, CalculateActivationRange(params->activation, &output_activation_min, &output_activation_max); KernelType effective_kernel_type; - if ((kernel_type == kMultithreadOptimized || - kernel_type == kCblasOptimized) && + if ((kernel_type == kMultithreadOptimized) && (params->dilation_width_factor != 1 || params->dilation_height_factor != 1)) { - // kMultithreadOptimized and kCblasOptimized do not support dilation. + // kMultithreadOptimized does not support dilation. // Therefore, fallback to optimized. effective_kernel_type = kGenericOptimized; } else { @@ -521,6 +519,7 @@ void EvalFloat(TfLiteContext* context, TfLiteNode* node, GetTensorData(im2col)); break; } + case kCblasOptimized: case kGenericOptimized: { optimized_ops::Conv(op_params, GetTensorShape(input), GetTensorData(input), GetTensorShape(filter), @@ -546,15 +545,6 @@ void EvalFloat(TfLiteContext* context, TfLiteNode* node, GetTensorData(im2col)); break; } - case kCblasOptimized: { - cblas_ops::Conv(op_params, GetTensorShape(input), - GetTensorData(input), GetTensorShape(filter), - GetTensorData(filter), GetTensorShape(bias), - GetTensorData(bias), GetTensorShape(output), - GetTensorData(output), GetTensorShape(im2col), - GetTensorData(im2col)); - break; - } } } diff --git a/tensorflow/lite/kernels/eigen_support.cc b/tensorflow/lite/kernels/eigen_support.cc index 44e0086ad8..bad5975a7c 100644 --- a/tensorflow/lite/kernels/eigen_support.cc +++ b/tensorflow/lite/kernels/eigen_support.cc @@ -34,6 +34,15 @@ static_assert( "kDefaultArenaAlignment doesn't comply with Eigen alignment requirement."); #endif // EIGEN_DONT_ALIGN +// Helper routine for updating the global Eigen thread count used for OpenMP. +void SetEigenNbThreads(int threads) { +#if defined(EIGEN_HAS_OPENMP) + // The global Eigen thread count is only used when OpenMP is enabled. As this + // call causes problems with tsan, make it only when OpenMP is available. + Eigen::setNbThreads(context->recommended_num_threads); +#endif // defined(EIGEN_HAS_OPENMP) +} + // We have a single global threadpool for all convolution operations. This means // that inferences started from different threads may block each other, but // since the underlying resource of CPU cores should be consumed by the @@ -78,7 +87,7 @@ void InitDevice(TfLiteContext* context, RefCountedEigenContext* ptr) { } TfLiteStatus Refresh(TfLiteContext* context) { - Eigen::setNbThreads(context->recommended_num_threads); + SetEigenNbThreads(context->recommended_num_threads); auto* ptr = GetEigenContext(context); if (ptr != nullptr) { @@ -94,7 +103,7 @@ void IncrementUsageCounter(TfLiteContext* context) { auto* ptr = GetEigenContext(context); if (ptr == nullptr) { if (context->recommended_num_threads != -1) { - Eigen::setNbThreads(context->recommended_num_threads); + SetEigenNbThreads(context->recommended_num_threads); } ptr = new RefCountedEigenContext; ptr->type = kTfLiteEigenContext; diff --git a/tensorflow/lite/kernels/elementwise.cc b/tensorflow/lite/kernels/elementwise.cc index 416a69eb0e..a79388b900 100644 --- a/tensorflow/lite/kernels/elementwise.cc +++ b/tensorflow/lite/kernels/elementwise.cc @@ -15,6 +15,7 @@ limitations under the License. #include #include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/kernels/internal/reference/reference_ops.h" #include "tensorflow/lite/kernels/internal/tensor.h" #include "tensorflow/lite/kernels/kernel_util.h" @@ -74,6 +75,10 @@ inline TfLiteStatus EvalLogical(TfLiteContext* context, TfLiteNode* node, return EvalImpl(context, node, bool_func, kTfLiteBool); } +TfLiteStatus AbsEval(TfLiteContext* context, TfLiteNode* node) { + return EvalNumeric(context, node, std::abs); +} + TfLiteStatus SinEval(TfLiteContext* context, TfLiteNode* node) { return EvalNumeric(context, node, std::sin); } @@ -101,6 +106,14 @@ TfLiteStatus LogicalNotEval(TfLiteContext* context, TfLiteNode* node) { } // namespace } // namespace elementwise +TfLiteRegistration* Register_ABS() { + static TfLiteRegistration r = { + /*init=*/nullptr, /*free=*/nullptr, + elementwise::GenericPrepare, + elementwise::AbsEval}; + return &r; +} + TfLiteRegistration* Register_SIN() { static TfLiteRegistration r = { /*init=*/nullptr, /*free=*/nullptr, diff --git a/tensorflow/lite/kernels/elementwise_test.cc b/tensorflow/lite/kernels/elementwise_test.cc index 52df8dc3cc..7d24320081 100644 --- a/tensorflow/lite/kernels/elementwise_test.cc +++ b/tensorflow/lite/kernels/elementwise_test.cc @@ -74,6 +74,19 @@ TEST(ElementWise, Log) { EXPECT_THAT(m.GetTensorShape(m.output()), ElementsAreArray({1, 1, 4, 1})); } +TEST(FloatActivationsOpTest, Abs) { + ElementWiseOpFloatModel m(BuiltinOperator_ABS, {1, 2, 4, 1}); + m.PopulateTensor(m.input(), { + 0.f, -6.2f, 2.f, 4.f, // + 3.f, -2.f, 10.f, 1.f, // + }); + m.Invoke(); + EXPECT_THAT(m.ExtractVector(m.output()), ElementsAreArray({ + 0.f, 6.2f, 2.f, 4.f, // + 3.f, 2.f, 10.f, 1.f, // + })); +} + TEST(ElementWise, Sqrt) { ElementWiseOpFloatModel m(BuiltinOperator_SQRT, {1, 1, 4, 1}); m.PopulateTensor(m.input(), {0, 1, 2, 4}); diff --git a/tensorflow/lite/kernels/fill.cc b/tensorflow/lite/kernels/fill.cc new file mode 100644 index 0000000000..079ee44f37 --- /dev/null +++ b/tensorflow/lite/kernels/fill.cc @@ -0,0 +1,141 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/kernels/internal/reference/reference_ops.h" +#include "tensorflow/lite/kernels/internal/tensor.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/kernel_util.h" + +namespace tflite { +namespace ops { +namespace builtin { +namespace fill { + +namespace { + +constexpr int kDimsTensor = 0; +constexpr int kValueTensor = 1; +constexpr int kOutputTensor = 0; + +template +TfLiteStatus ResizeOutputImpl(TfLiteContext* context, const TfLiteTensor* dims, + TfLiteTensor* output) { + TfLiteIntArray* output_shape = TfLiteIntArrayCreate(dims->dims->data[0]); + for (int i = 0; i < output_shape->size; ++i) { + T data = GetTensorData(dims)[i]; + if (data < 0) { + context->ReportError(context, "Fill dimensions must be >= 0", dims->type); + return kTfLiteError; + } + output_shape->data[i] = data; + } + return context->ResizeTensor(context, output, output_shape); +} + +TfLiteStatus ResizeOutput(TfLiteContext* context, const TfLiteTensor* dims, + TfLiteTensor* output) { + switch (dims->type) { + case kTfLiteInt32: + return ResizeOutputImpl(context, dims, output); + case kTfLiteInt64: + return ResizeOutputImpl(context, dims, output); + default: + context->ReportError( + context, + "Fill only currently supports int32, int64 for input 0, " + "got %d.", + dims->type); + return kTfLiteError; + } +} + +} // namespace + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + const TfLiteTensor* dims = GetInput(context, node, kDimsTensor); + const TfLiteTensor* value = GetInput(context, node, kValueTensor); + + // Make sure the 1st input tensor is 1-D. + TF_LITE_ENSURE_EQ(context, NumDimensions(dims), 1); + + // Make sure the 1st input tensor is int32 or int64. + const auto dtype = dims->type; + TF_LITE_ENSURE(context, dtype == kTfLiteInt32 || dtype == kTfLiteInt64); + + // Make sure the 2nd input tensor is a scalar. + TF_LITE_ENSURE_EQ(context, NumDimensions(value), 0); + + TfLiteTensor* output = GetOutput(context, node, kOutputTensor); + output->type = value->type; + + if (IsConstantTensor(dims)) { + TF_LITE_ENSURE_OK(context, ResizeOutput(context, dims, output)); + } else { + SetTensorToDynamic(output); + } + return kTfLiteOk; +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteTensor* value = GetInput(context, node, kValueTensor); + + TfLiteTensor* output = GetOutput(context, node, kOutputTensor); + + if (IsDynamicTensor(output)) { + const TfLiteTensor* dims = GetInput(context, node, kDimsTensor); + TF_LITE_ENSURE_OK(context, ResizeOutput(context, dims, output)); + } +#define TF_LITE_FILL(data_type) \ + reference_ops::Fill(GetTensorShape(value), GetTensorData(value), \ + GetTensorShape(output), \ + GetTensorData(output)) + switch (output->type) { + case kTfLiteInt32: + TF_LITE_FILL(int32_t); + break; + case kTfLiteInt64: + TF_LITE_FILL(int64_t); + break; + case kTfLiteFloat32: + TF_LITE_FILL(float); + break; + default: + context->ReportError( + context, + "Fill only currently supports int32, int64, float32 for input 1," + "got %d.", + value->type); + return kTfLiteError; + } +#undef TF_LITE_FILL + return kTfLiteOk; +} + +} // namespace fill + +TfLiteRegistration* Register_FILL() { + static TfLiteRegistration r = {/*init=*/nullptr, /*free=*/nullptr, + fill::Prepare, fill::Eval}; + return &r; +} + +} // namespace builtin +} // namespace ops +} // namespace tflite diff --git a/tensorflow/lite/kernels/fill_test.cc b/tensorflow/lite/kernels/fill_test.cc new file mode 100644 index 0000000000..08044d76f9 --- /dev/null +++ b/tensorflow/lite/kernels/fill_test.cc @@ -0,0 +1,94 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include "tensorflow/lite/interpreter.h" +#include "tensorflow/lite/kernels/register.h" +#include "tensorflow/lite/kernels/test_util.h" +#include "tensorflow/lite/model.h" + +namespace tflite { +namespace { + +using ::testing::ElementsAreArray; +using ::testing::IsEmpty; + +class FillOpModel : public SingleOpModel { + public: + explicit FillOpModel(const TensorData& input1, const TensorData& input2) { + input1_ = AddInput(input1); + input2_ = AddInput(input2); + output_ = AddOutput(input1); + SetBuiltinOp(BuiltinOperator_FILL, BuiltinOptions_FillOptions, + CreateFillOptions(builder_).Union()); + BuildInterpreter({GetShape(input1_), GetShape(input2_)}); + } + + int input1() { return input1_; } + int input2() { return input2_; } + int output() { return output_; } + + protected: + int input1_; + int input2_; + int output_; +}; + +TEST(FillOpModel, FillInt32) { + FillOpModel m({TensorType_INT32, {2}}, {TensorType_INT32}); + m.PopulateTensor(m.input1(), {2, 3}); + m.PopulateTensor(m.input2(), {-11}); + m.Invoke(); + EXPECT_THAT(m.ExtractVector(m.output()), + ElementsAreArray({-11, -11, -11, -11, -11, -11})); + EXPECT_THAT(m.GetTensorShape(m.output()), ElementsAreArray({2, 3})); +} + +TEST(FillOpModel, FillInt64) { + FillOpModel m({TensorType_INT32, {2}}, {TensorType_INT64}); + m.PopulateTensor(m.input1(), {2, 4}); + m.PopulateTensor(m.input2(), {2 ^ 45}); + m.Invoke(); + EXPECT_THAT(m.ExtractVector(m.output()), + ElementsAreArray({2 ^ 45, 2 ^ 45, 2 ^ 45, 2 ^ 45, 2 ^ 45, 2 ^ 45, + 2 ^ 45, 2 ^ 45})); + EXPECT_THAT(m.GetTensorShape(m.output()), ElementsAreArray({2, 4})); +} + +TEST(FillOpModel, FillFloat) { + FillOpModel m({TensorType_INT64, {3}}, {TensorType_FLOAT32}); + m.PopulateTensor(m.input1(), {2, 2, 2}); + m.PopulateTensor(m.input2(), {4.0}); + m.Invoke(); + EXPECT_THAT(m.ExtractVector(m.output()), + ElementsAreArray({4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0})); + EXPECT_THAT(m.GetTensorShape(m.output()), ElementsAreArray({2, 2, 2})); +} + +TEST(FillOpModel, FillOutputScalar) { + FillOpModel m({TensorType_INT64, {0}}, {TensorType_FLOAT32}); + m.PopulateTensor(m.input2(), {4.0}); + m.Invoke(); + EXPECT_THAT(m.ExtractVector(m.output()), ElementsAreArray({4.0})); + EXPECT_THAT(m.GetTensorShape(m.output()), IsEmpty()); +} + +} // namespace +} // namespace tflite + +int main(int argc, char** argv) { + ::tflite::LogToStderr(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tensorflow/lite/kernels/fully_connected.cc b/tensorflow/lite/kernels/fully_connected.cc index 63cca1cf54..a1eecb284a 100644 --- a/tensorflow/lite/kernels/fully_connected.cc +++ b/tensorflow/lite/kernels/fully_connected.cc @@ -117,7 +117,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { // Note that quantized inference requires that all tensors have their // parameters set. This is usually done during quantized training. TfLiteType data_type = input->type; - if (data_type != kTfLiteFloat32) { + if (data_type != kTfLiteFloat32 && data_type != kTfLiteInt32) { double real_multiplier = 0.0; TF_LITE_ENSURE_STATUS(GetQuantizedConvolutionMultipler( context, input, filter, bias, output, &real_multiplier)); diff --git a/tensorflow/lite/kernels/gather.cc b/tensorflow/lite/kernels/gather.cc index 61884d6a12..f205daae13 100644 --- a/tensorflow/lite/kernels/gather.cc +++ b/tensorflow/lite/kernels/gather.cc @@ -118,7 +118,7 @@ TfLiteStatus GatherStrings(TfLiteContext* context, const TfLiteTensor* input, const auto string_ref = GetString(input, pos); buffer.AddString(string_ref.str, string_ref.len); } - buffer.WriteToTensor(output); + buffer.WriteToTensorAsVector(output); return kTfLiteOk; } diff --git a/tensorflow/lite/kernels/hashtable_lookup.cc b/tensorflow/lite/kernels/hashtable_lookup.cc index b6ae7a3d1a..da1116cf85 100644 --- a/tensorflow/lite/kernels/hashtable_lookup.cc +++ b/tensorflow/lite/kernels/hashtable_lookup.cc @@ -137,7 +137,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { } } if (output->type == kTfLiteString) { - buf.WriteToTensor(output); + buf.WriteToTensorAsVector(output); } return kTfLiteOk; diff --git a/tensorflow/lite/kernels/internal/BUILD b/tensorflow/lite/kernels/internal/BUILD index 6d9690ea46..7d2653f0a1 100644 --- a/tensorflow/lite/kernels/internal/BUILD +++ b/tensorflow/lite/kernels/internal/BUILD @@ -234,8 +234,6 @@ cc_library( cc_library( name = "optimized", hdrs = [ - "optimized/cblas_conv.h", - "optimized/cblas_reference.h", "optimized/eigen_spatial_convolutions.h", "optimized/eigen_tensor_reduced_instantiations_oss.h", "optimized/multithreaded_conv.h", diff --git a/tensorflow/lite/kernels/internal/optimized/cblas_conv.h b/tensorflow/lite/kernels/internal/optimized/cblas_conv.h deleted file mode 100644 index 5377205050..0000000000 --- a/tensorflow/lite/kernels/internal/optimized/cblas_conv.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_OPTIMIZED_CBLAS_CONV_H_ -#define TENSORFLOW_LITE_KERNELS_INTERNAL_OPTIMIZED_CBLAS_CONV_H_ - -// The Conv implementation based on CBLAS interface. This is only used on iOS -// for now, utilizing Apple's Accelerate framework. - -#if TFLITE_USE_APPLE_ACCELERATE_FOR_CONV -#include -#else -#include "tensorflow/lite/kernels/internal/optimized/cblas_reference.h" -#endif - -#include "tensorflow/lite/kernels/internal/optimized/multithreaded_conv.h" -#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" - -namespace tflite { -namespace cblas_ops { - -inline void Conv(const ConvParams& params, const RuntimeShape& input_shape, - const float* input_data, const RuntimeShape& filter_shape, - const float* filter_data, const RuntimeShape& bias_shape, - const float* bias_data, const RuntimeShape& output_shape, - float* output_data, const RuntimeShape& im2col_shape, - float* im2col_data) { - const int stride_width = params.stride_width; - const int stride_height = params.stride_height; - const int pad_width = params.padding_values.width; - const int pad_height = params.padding_values.height; - const int dilation_width_factor = params.dilation_width_factor; - const int dilation_height_factor = params.dilation_height_factor; - const float output_activation_min = params.float_activation_min; - const float output_activation_max = params.float_activation_max; - TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); - TFLITE_DCHECK_EQ(filter_shape.DimensionsCount(), 4); - TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); - gemmlowp::ScopedProfilingLabel label("Conv/cblas"); - - const float* gemm_input_data = nullptr; - const RuntimeShape* gemm_input_shape = nullptr; - const int filter_width = filter_shape.Dims(2); - const int filter_height = filter_shape.Dims(1); - const bool need_im2col = stride_width != 1 || stride_height != 1 || - filter_width != 1 || filter_height != 1; - if (need_im2col) { - TFLITE_DCHECK(im2col_data); - ConvParams op_params; - op_params.padding_type = PaddingType::kSame; - op_params.padding_values.width = pad_width; - op_params.padding_values.height = pad_height; - op_params.stride_width = stride_width; - op_params.stride_height = stride_height; - op_params.dilation_width_factor = dilation_width_factor; - op_params.dilation_height_factor = dilation_height_factor; - optimized_ops::Im2col(op_params, filter_height, filter_width, 0, - input_shape, input_data, im2col_shape, im2col_data); - - gemm_input_data = im2col_data; - gemm_input_shape = &im2col_shape; - } else { - TFLITE_DCHECK(!im2col_data); - gemm_input_data = input_data; - gemm_input_shape = &input_shape; - } - - // The following code computes matrix multiplication c = a * transponse(b) - // with CBLAS, where: - // * `a` is a matrix with dimensions (m, k). - // * `b` is a matrix with dimensions (n, k), so transpose(b) is (k, n). - // * `c` is a matrix with dimensions (m, n). - // The naming of variables are aligned with CBLAS specification here. - const float* a = gemm_input_data; - const float* b = filter_data; - float* c = output_data; - const int gemm_input_dims = gemm_input_shape->DimensionsCount(); - int m = FlatSizeSkipDim(*gemm_input_shape, gemm_input_dims - 1); - int n = output_shape.Dims(3); - int k = gemm_input_shape->Dims(gemm_input_dims - 1); - // The stride of matrix a, b and c respectively. - int stride_a = k; - int stride_b = k; - int stride_c = n; - - cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, m, n, k, 1.0f, a, - stride_a, b, stride_b, 0.0f, c, stride_c); - - optimized_ops::AddBiasAndEvalActivationFunction( - output_activation_min, output_activation_max, bias_shape, bias_data, - output_shape, output_data); -} - -} // namespace cblas_ops -} // namespace tflite - -#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_OPTIMIZED_CBLAS_CONV_H_ diff --git a/tensorflow/lite/kernels/internal/optimized/cblas_reference.h b/tensorflow/lite/kernels/internal/optimized/cblas_reference.h deleted file mode 100644 index fa07578612..0000000000 --- a/tensorflow/lite/kernels/internal/optimized/cblas_reference.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_OPTIMIZED_CBLAS_REFERENCE_H_ -#define TENSORFLOW_LITE_KERNELS_INTERNAL_OPTIMIZED_CBLAS_REFERENCE_H_ - -#include "tensorflow/lite/kernels/internal/compatibility.h" - -// The reference implementation for a small subset of CBLAS interface. -// This is only used for testing CBLAS implementation, and should never be used -// in production code. - -namespace tflite { -namespace cblas_ops { - -// The following code follows the original CBLAS specification, and it might -// conflict with the TensorFlow naming convention. -// TODO(ycling): Find another way to test CBLAS with bazel, without writing -// a reference implementation by ourselves. -enum CBLAS_ORDER { CblasRowMajor = 0, CblasColMajor = 1 }; - -enum CBLAS_TRANSPOSE { CblasNoTrans = 0, CblasTrans = 1, CblasConjTrans = 2 }; - -// A reference implementation for matrix multiplication. -// The following code computes, c = a * transponse(b) matrix multiplication -// with CBLAS, where: -// * `a` is a matrix with dimensions (m, k). -// * `b` is a matrix with dimensions (n, k), so transpose(b) is (k, n). -// * `c` is a matrix with dimensions (m, n). -// The naming of variables is aligned with CBLAS specification here. -void cblas_sgemm(const enum CBLAS_ORDER order, - const enum CBLAS_TRANSPOSE trans_a, - const enum CBLAS_TRANSPOSE trans_b, const int m, const int n, - const int k, const float alpha, const float *a, - const int stride_a, const float *b, const int stride_b, - const float beta, float *c, const int stride_c) { - TFLITE_DCHECK(order == CblasRowMajor); - TFLITE_DCHECK(trans_a == CblasNoTrans); - TFLITE_DCHECK(trans_b == CblasTrans); - TFLITE_DCHECK(beta == 0.0f); - for (int row = 0; row < m; ++row) { - for (int col = 0; col < n; ++col) { - // If `beta` non-zero, multiple it with the original values in output. - // Otherwise, ignore the original value in output completely. - float value = 0.0f; - for (int idx = 0; idx < k; ++idx) { - value += alpha * a[stride_a * row + idx] * b[stride_b * col + idx]; - } - c[stride_c * row + col] = value; - } - } -} - -} // namespace cblas_ops -} // namespace tflite - -#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_OPTIMIZED_CBLAS_REFERENCE_H_ diff --git a/tensorflow/lite/kernels/internal/optimized/depthwiseconv_float.h b/tensorflow/lite/kernels/internal/optimized/depthwiseconv_float.h index 25b66d4b55..c77715de57 100644 --- a/tensorflow/lite/kernels/internal/optimized/depthwiseconv_float.h +++ b/tensorflow/lite/kernels/internal/optimized/depthwiseconv_float.h @@ -793,22 +793,26 @@ void FloatDepthwiseConvAccumRow(int stride, int dilation_factor, int out_x_loop_end_unclampled = 0; if (kAllowStrided) { if (stride == 2) { - out_x_loop_start_unclampled = (pad_width - filter_x + 1) / 2; + out_x_loop_start_unclampled = + (pad_width - dilation_factor * filter_x + 1) / 2; out_x_loop_end_unclampled = - (pad_width + input_width - filter_x + 1) / 2; + (pad_width + input_width - dilation_factor * filter_x + 1) / 2; } else if (stride == 4) { - out_x_loop_start_unclampled = (pad_width - filter_x + 3) / 4; + out_x_loop_start_unclampled = + (pad_width - dilation_factor * filter_x + 3) / 4; out_x_loop_end_unclampled = - (pad_width + input_width - filter_x + 3) / 4; + (pad_width + input_width - dilation_factor * filter_x + 3) / 4; } else { out_x_loop_start_unclampled = - (pad_width - filter_x + stride - 1) / stride; - out_x_loop_end_unclampled = - (pad_width + input_width - filter_x + stride - 1) / stride; + (pad_width - dilation_factor * filter_x + stride - 1) / stride; + out_x_loop_end_unclampled = (pad_width + input_width - + dilation_factor * filter_x + stride - 1) / + stride; } } else { - out_x_loop_start_unclampled = pad_width - filter_x; - out_x_loop_end_unclampled = pad_width + input_width - filter_x; + out_x_loop_start_unclampled = pad_width - dilation_factor * filter_x; + out_x_loop_end_unclampled = + pad_width + input_width - dilation_factor * filter_x; } // The kernel will have to iterate on the segment of the // output row that starts at out_x_loop_start and out_x_loop_end. @@ -819,7 +823,8 @@ void FloatDepthwiseConvAccumRow(int stride, int dilation_factor, float* acc_buffer_ptr = acc_buffer + (out_x_loop_start - out_x_buffer_start) * output_depth; - const int in_x_origin = (out_x_loop_start * stride) - pad_width + filter_x; + const int in_x_origin = + (out_x_loop_start * stride) - pad_width + dilation_factor * filter_x; const float* input_ptr = input_data + in_x_origin * input_depth; const int num_output_pixels = out_x_loop_end - out_x_loop_start; FloatDepthwiseConvKernel; \ diff --git a/tensorflow/lite/kernels/internal/optimized/depthwiseconv_uint8.h b/tensorflow/lite/kernels/internal/optimized/depthwiseconv_uint8.h index 5317cea884..d3dca799a7 100644 --- a/tensorflow/lite/kernels/internal/optimized/depthwiseconv_uint8.h +++ b/tensorflow/lite/kernels/internal/optimized/depthwiseconv_uint8.h @@ -1499,22 +1499,26 @@ void QuantizedDepthwiseConvAccumRow(int stride, int dilation_factor, int out_x_loop_end_unclampled = 0; if (kAllowStrided) { if (stride == 2) { - out_x_loop_start_unclampled = (pad_width - filter_x + 1) / 2; + out_x_loop_start_unclampled = + (pad_width - dilation_factor * filter_x + 1) / 2; out_x_loop_end_unclampled = - (pad_width + input_width - filter_x + 1) / 2; + (pad_width + input_width - dilation_factor * filter_x + 1) / 2; } else if (stride == 4) { - out_x_loop_start_unclampled = (pad_width - filter_x + 3) / 4; + out_x_loop_start_unclampled = + (pad_width - dilation_factor * filter_x + 3) / 4; out_x_loop_end_unclampled = - (pad_width + input_width - filter_x + 3) / 4; + (pad_width + input_width - dilation_factor * filter_x + 3) / 4; } else { out_x_loop_start_unclampled = - (pad_width - filter_x + stride - 1) / stride; - out_x_loop_end_unclampled = - (pad_width + input_width - filter_x + stride - 1) / stride; + (pad_width - dilation_factor * filter_x + stride - 1) / stride; + out_x_loop_end_unclampled = (pad_width + input_width - + dilation_factor * filter_x + stride - 1) / + stride; } } else { - out_x_loop_start_unclampled = pad_width - filter_x; - out_x_loop_end_unclampled = pad_width + input_width - filter_x; + out_x_loop_start_unclampled = pad_width - dilation_factor * filter_x; + out_x_loop_end_unclampled = + pad_width + input_width - dilation_factor * filter_x; } // The kernel will have to iterate on the segment of the // output row that starts at out_x_loop_start and out_x_loop_end. @@ -1525,7 +1529,8 @@ void QuantizedDepthwiseConvAccumRow(int stride, int dilation_factor, int32* acc_buffer_ptr = acc_buffer + (out_x_loop_start - out_x_buffer_start) * output_depth; - const int in_x_origin = (out_x_loop_start * stride) - pad_width + filter_x; + const int in_x_origin = + (out_x_loop_start * stride) - pad_width + dilation_factor * filter_x; const uint8* input_ptr = input_data + in_x_origin * input_depth; const int num_output_pixels = out_x_loop_end - out_x_loop_start; QuantizedDepthwiseConvKernel< @@ -1703,8 +1708,7 @@ inline void DepthwiseConvGeneral( FIXED_DEPTH_MULTIPLIER) \ if (!row_accum_func && (stride_width == 1 || ALLOW_STRIDED) && \ (input_depth == FIXED_INPUT_DEPTH || FIXED_INPUT_DEPTH == 0) && \ - depth_multiplier == FIXED_DEPTH_MULTIPLIER && \ - dilation_width_factor == 1 && dilation_height_factor == 1) { \ + depth_multiplier == FIXED_DEPTH_MULTIPLIER) { \ row_accum_func = \ QuantizedDepthwiseConvAccumRow; \ diff --git a/tensorflow/lite/kernels/internal/optimized/depthwiseconv_uint8_3x3_filter.h b/tensorflow/lite/kernels/internal/optimized/depthwiseconv_uint8_3x3_filter.h index 3f2ed0b1f0..5859bcaed4 100644 --- a/tensorflow/lite/kernels/internal/optimized/depthwiseconv_uint8_3x3_filter.h +++ b/tensorflow/lite/kernels/internal/optimized/depthwiseconv_uint8_3x3_filter.h @@ -23,11 +23,6 @@ limitations under the License. namespace tflite { namespace optimized_ops { -// clang-format gets confused with this file and ends up formatting lines to -// be larger than 80 characters. Turn off here and back on at the end of the -// file. -// clang-format off - // See CategorizeDotProductKernel for definitive taxonomy. enum class DotProduct3x3KernelType { kNone = 0, // Parameter combination is not supported for dot product kernels. @@ -120,42 +115,58 @@ struct DepthwiseConvParams { #define OFFSET_OUTPUT_WIDTH 84 #define OFFSET_OUTPUT_HEIGHT 88 -static_assert(offsetof(DepthwiseConvParams, input_depth) == - OFFSET_INPUT_DEPTH, ""); +static_assert(offsetof(DepthwiseConvParams, input_depth) == OFFSET_INPUT_DEPTH, + ""); static_assert(offsetof(DepthwiseConvParams, input_row_size) == - OFFSET_INPUT_ROW_SIZE, ""); + OFFSET_INPUT_ROW_SIZE, + ""); static_assert(offsetof(DepthwiseConvParams, output_depth) == - OFFSET_OUTPUT_DEPTH, ""); + OFFSET_OUTPUT_DEPTH, + ""); static_assert(offsetof(DepthwiseConvParams, output_row_size) == - OFFSET_OUTPUT_ROW_SIZE, ""); + OFFSET_OUTPUT_ROW_SIZE, + ""); static_assert(offsetof(DepthwiseConvParams, filter_row_size) == - OFFSET_FILTER_ROW_SIZE, ""); + OFFSET_FILTER_ROW_SIZE, + ""); static_assert(offsetof(DepthwiseConvParams, input_offset) == - OFFSET_INPUT_OFFSET, ""); + OFFSET_INPUT_OFFSET, + ""); static_assert(offsetof(DepthwiseConvParams, output_offset) == - OFFSET_OUTPUT_OFFSET, ""); + OFFSET_OUTPUT_OFFSET, + ""); static_assert(offsetof(DepthwiseConvParams, filter_offset) == - OFFSET_FILTER_OFFSET, ""); + OFFSET_FILTER_OFFSET, + ""); static_assert(offsetof(DepthwiseConvParams, output_multiplier) == - OFFSET_OUTPUT_MULTIPLIER, ""); + OFFSET_OUTPUT_MULTIPLIER, + ""); static_assert(offsetof(DepthwiseConvParams, output_activation_min) == - OFFSET_OUTPUT_ACTIVATION_MIN, ""); + OFFSET_OUTPUT_ACTIVATION_MIN, + ""); static_assert(offsetof(DepthwiseConvParams, output_activation_max) == - OFFSET_OUTPUT_ACTIVATION_MAX, ""); + OFFSET_OUTPUT_ACTIVATION_MAX, + ""); static_assert(offsetof(DepthwiseConvParams, output_right_shift) == - OFFSET_OUTPUT_RIGHT_SHIFT, ""); -static_assert(offsetof(DepthwiseConvParams, input_width) == - OFFSET_INPUT_WIDTH, ""); + OFFSET_OUTPUT_RIGHT_SHIFT, + ""); +static_assert(offsetof(DepthwiseConvParams, input_width) == OFFSET_INPUT_WIDTH, + ""); static_assert(offsetof(DepthwiseConvParams, input_height) == - OFFSET_INPUT_HEIGHT, ""); + OFFSET_INPUT_HEIGHT, + ""); static_assert(offsetof(DepthwiseConvParams, stride_width) == - OFFSET_STRIDE_WIDTH, ""); + OFFSET_STRIDE_WIDTH, + ""); static_assert(offsetof(DepthwiseConvParams, stride_height) == - OFFSET_STRIDE_HEIGHT, ""); + OFFSET_STRIDE_HEIGHT, + ""); static_assert(offsetof(DepthwiseConvParams, output_width) == - OFFSET_OUTPUT_WIDTH, ""); + OFFSET_OUTPUT_WIDTH, + ""); static_assert(offsetof(DepthwiseConvParams, output_height) == - OFFSET_OUTPUT_HEIGHT, ""); + OFFSET_OUTPUT_HEIGHT, + ""); template struct DepthwiseConvWindow {}; @@ -164,10 +175,10 @@ template <> struct DepthwiseConvWindow<8, 1, 1> { public: static inline void Run(const uint8* input_ptr, const uint8* filter_ptr, - const int32* bias_ptr, uint8* output_ptr, int64_t input_depth, - int64_t input_row_size, int32 output_window_height, - int32 output_window_width, - const DepthwiseConvParams* params_ptr) { + const int32* bias_ptr, uint8* output_ptr, + int64_t input_depth, int64_t input_row_size, + int32 output_window_height, int32 output_window_width, + const DepthwiseConvParams* params_ptr) { const int64_t input_width_increment = 2 * input_depth; const int64_t input_height_increment = 2 * input_row_size; const int64_t output_height_increment = 2 * params_ptr->output_row_size; @@ -1147,10 +1158,10 @@ struct DepthwiseConvWindow<8, 1, 1> { template <> struct DepthwiseConvWindow<8, 2, 2> { static inline void Run(const uint8* input_ptr, const uint8* filter_ptr, - const int32* bias_ptr, uint8* output_ptr, int64_t input_depth, - int64_t input_row_size, int32 output_window_height, - int32 output_window_width, - const DepthwiseConvParams* params_ptr) { + const int32* bias_ptr, uint8* output_ptr, + int64_t input_depth, int64_t input_row_size, + int32 output_window_height, int32 output_window_width, + const DepthwiseConvParams* params_ptr) { const int64_t input_width_increment = 4 * input_depth; const int64_t input_height_increment = 4 * input_row_size; const int64_t output_height_increment = 2 * params_ptr->output_row_size; @@ -2990,11 +3001,10 @@ struct ShuffleParams { ShuffleParams() = default; ShuffleParams(int32 output_width, int32 output_height, int32 stride_width, int32 stride_height) - : output_width(output_width) - , output_height(output_height) - , input_width(get_shuffle_input_size(stride_width, output_width)) - , input_height(get_shuffle_input_size(stride_height, output_height)) { - } + : output_width(output_width), + output_height(output_height), + input_width(get_shuffle_input_size(stride_width, output_width)), + input_height(get_shuffle_input_size(stride_height, output_height)) {} }; template @@ -3003,10 +3013,10 @@ struct DepthwiseConvThroughDepth { // |start_depth| to |end_depth|. Keep this not inlined to maintain a small // binary size. We use a DepthwiseConvParams struct for read only params // to minimize call overhead. - static __attribute__((noinline)) void Run(const uint8* input_ptr, - const uint8* filter_ptr, const int32* bias_ptr, uint8* output_ptr, - int64_t start_depth, int64_t end_depth, int64_t input_depth, - int64_t input_row_size, int32 output_window_height, + static __attribute__((noinline)) void Run( + const uint8* input_ptr, const uint8* filter_ptr, const int32* bias_ptr, + uint8* output_ptr, int64_t start_depth, int64_t end_depth, + int64_t input_depth, int64_t input_row_size, int32 output_window_height, int32 output_window_width, const DepthwiseConvParams& params) { for (; start_depth <= end_depth - 8; start_depth += 8) { DepthwiseConvWindow<8, kStrideWidth, kStrideHeight>::Run( @@ -3029,12 +3039,15 @@ struct DepthwiseConvMultiRow { uint8* output_data, const DepthwiseConvParams& params, const ShuffleParams& shuffle_params, uint8* shuffle_workspace) { - TFLITE_DCHECK(shuffle_params.input_height == + TFLITE_DCHECK( + shuffle_params.input_height == get_shuffle_input_size(kStrideHeight, shuffle_params.output_height)); - TFLITE_DCHECK(shuffle_params.input_width == + TFLITE_DCHECK( + shuffle_params.input_width == get_shuffle_input_size(kStrideWidth, shuffle_params.output_width)); - TFLITE_DCHECK(64 * shuffle_params.input_width * shuffle_params.input_height - <= DEPTHWISECONV_SHUFFLE_WORKSPACE_SIZE); + TFLITE_DCHECK(64 * shuffle_params.input_width * + shuffle_params.input_height <= + DEPTHWISECONV_SHUFFLE_WORKSPACE_SIZE); int32 out_x = start_x; @@ -3045,7 +3058,7 @@ struct DepthwiseConvMultiRow { if (params.output_depth > 64 || (params.output_depth <= 64 && params.input_width > 150)) { for (; out_x <= (end_x - shuffle_params.output_width); - out_x += shuffle_params.output_width) { + out_x += shuffle_params.output_width) { const uint8* input_ptr = input_data; const int32* bias_ptr = bias_data; const uint8* filter_ptr = filter_data; @@ -3091,8 +3104,8 @@ struct DepthwiseConvMultiRow { } // Handle leftover depth. - ConvKernel::Run(input_ptr, filter_ptr, bias_ptr, output_ptr, - depth, params.output_depth, params.input_depth, + ConvKernel::Run(input_ptr, filter_ptr, bias_ptr, output_ptr, depth, + params.output_depth, params.input_depth, params.input_row_size, shuffle_params.output_height, shuffle_params.output_width, params); @@ -3119,13 +3132,15 @@ struct DepthwiseConvMultiRow { // * Horizontal edges. // * Vertical edges. inline void DepthwiseConvHandlePadding(const uint8* input_data, - const uint8* filter_data, const int32* bias_data, uint8* output_data, - const DepthwiseConvParams& params) { + const uint8* filter_data, + const int32* bias_data, + uint8* output_data, + const DepthwiseConvParams& params) { if (params.input_width == 1 && params.input_height == 1) { - const uint8* filter_ptr = filter_data + params.filter_row_size - + params.output_depth; - DepthwiseConvPartial::Run(input_data, filter_ptr, - bias_data, output_data, ¶ms); + const uint8* filter_ptr = + filter_data + params.filter_row_size + params.output_depth; + DepthwiseConvPartial::Run( + input_data, filter_ptr, bias_data, output_data, ¶ms); return; } @@ -3136,27 +3151,27 @@ inline void DepthwiseConvHandlePadding(const uint8* input_data, // Handle top row. const uint8* input_ptr = input_data; - const uint8* filter_ptr = filter_data + params.filter_row_size - + params.output_depth; + const uint8* filter_ptr = + filter_data + params.filter_row_size + params.output_depth; uint8* output_ptr = output_data; - DepthwiseConvPartial::Run(input_ptr, filter_ptr, - bias_data, output_ptr, ¶ms); + DepthwiseConvPartial::Run( + input_ptr, filter_ptr, bias_data, output_ptr, ¶ms); input_ptr += (params.stride_width - 1) * params.input_depth; filter_ptr = filter_data + params.filter_row_size; output_ptr += params.output_depth; for (int32 out_x = out_x_start_corner + 1; out_x < out_x_end_corner; - out_x++) { + out_x++) { DepthwiseConvPartial::Run( input_ptr, filter_ptr, bias_data, output_ptr, ¶ms); input_ptr += params.stride_width * params.input_depth; output_ptr += params.output_depth; } - DepthwiseConvPartial::Run(input_ptr, filter_ptr, - bias_data, output_ptr, ¶ms); + DepthwiseConvPartial::Run( + input_ptr, filter_ptr, bias_data, output_ptr, ¶ms); // Handle left side. input_ptr = input_data + (params.stride_width - 1) * params.input_row_size; @@ -3164,7 +3179,7 @@ inline void DepthwiseConvHandlePadding(const uint8* input_data, output_ptr = output_data + params.output_row_size; for (int32 out_y = out_y_start_corner + 1; out_y < out_y_end_corner; - out_y++) { + out_y++) { DepthwiseConvPartial::Run( input_ptr, filter_ptr, bias_data, output_ptr, ¶ms); input_ptr += params.stride_width * params.input_row_size; @@ -3172,14 +3187,14 @@ inline void DepthwiseConvHandlePadding(const uint8* input_data, } // Handle right side. - input_ptr = input_data + (params.input_width - 2) * params.input_depth - + (params.stride_width - 1) * params.input_row_size; + input_ptr = input_data + (params.input_width - 2) * params.input_depth + + (params.stride_width - 1) * params.input_row_size; filter_ptr = filter_data; output_ptr = output_data + params.output_row_size + - (params.output_width - 1) * params.output_depth; + (params.output_width - 1) * params.output_depth; for (int32 out_y = out_y_start_corner + 1; out_y < out_y_end_corner; - out_y++) { + out_y++) { DepthwiseConvPartial::Run( input_ptr, filter_ptr, bias_data, output_ptr, ¶ms); input_ptr += params.stride_width * params.input_row_size; @@ -3189,26 +3204,26 @@ inline void DepthwiseConvHandlePadding(const uint8* input_data, // Handle bottom row. input_ptr = input_data + (params.input_height - 2) * params.input_row_size; filter_ptr = filter_data + params.output_depth; - output_ptr = output_data + - (params.output_height - 1) * params.output_row_size; + output_ptr = + output_data + (params.output_height - 1) * params.output_row_size; - DepthwiseConvPartial::Run(input_ptr, filter_ptr, - bias_data, output_ptr, ¶ms); + DepthwiseConvPartial::Run( + input_ptr, filter_ptr, bias_data, output_ptr, ¶ms); input_ptr += (params.stride_width == 1) ? 0 : params.input_depth; filter_ptr = filter_data; output_ptr += params.output_depth; for (int32 out_x = out_x_start_corner + 1; out_x < out_x_end_corner; - out_x++) { + out_x++) { DepthwiseConvPartial::Run( input_ptr, filter_ptr, bias_data, output_ptr, ¶ms); input_ptr += params.stride_width * params.input_depth; output_ptr += params.output_depth; } - DepthwiseConvPartial::Run(input_ptr, filter_ptr, - bias_data, output_ptr, ¶ms); + DepthwiseConvPartial::Run( + input_ptr, filter_ptr, bias_data, output_ptr, ¶ms); } inline bool Fast3x3FilterKernelSupported( @@ -3383,8 +3398,8 @@ inline void DepthwiseConv3x3Filter( const int in_x = (out_x * stride_width) - pad_width; const int in_y = (out_y * stride_height) - pad_height; input_ptr += in_y * params.input_row_size + in_x * params.input_depth; - output_ptr += out_y * params.output_row_size - + out_x * params.output_depth; + output_ptr += + out_y * params.output_row_size + out_x * params.output_depth; } // Shuffling shapes that maximize width over the shuffle workspace size @@ -3439,7 +3454,6 @@ inline void DepthwiseConv3x3Filter( } } } -// clang-format on #endif // __aarch64__ diff --git a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h index 6f2cd4faab..c7691e2763 100644 --- a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h +++ b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h @@ -25,6 +25,10 @@ limitations under the License. #include #include +#if defined(TF_LITE_USE_CBLAS) && defined(__APPLE__) +#include +#endif + #include "third_party/eigen3/Eigen/Core" #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" #include "fixedpoint/fixedpoint.h" @@ -60,11 +64,13 @@ using reference_ops::DepthConcatenation; using reference_ops::Dequantize; using reference_ops::Div; using reference_ops::FakeQuant; +using reference_ops::Fill; using reference_ops::Gather; using reference_ops::Greater; using reference_ops::GreaterEqual; using reference_ops::GreaterEqualWithScaling; using reference_ops::GreaterWithScaling; +using reference_ops::LeakyRelu; using reference_ops::Less; using reference_ops::LessEqual; using reference_ops::LessEqualWithScaling; @@ -1867,18 +1873,45 @@ inline void Conv(const ConvParams& params, const RuntimeShape& input_shape, gemm_input_shape = &input_shape; } - const auto im2col_matrix_map = - MapAsMatrixWithLastDimAsRows(gemm_input_data, *gemm_input_shape); - const auto filter_matrix_map = - MapAsMatrixWithFirstDimAsCols(filter_data, filter_shape); - auto output_matrix_map = - MapAsMatrixWithLastDimAsRows(output_data, output_shape); - - Gemm(filter_matrix_map.transpose(), im2col_matrix_map, &output_matrix_map); - - AddBiasAndEvalActivationFunction(output_activation_min, output_activation_max, - bias_shape, bias_data, output_shape, - output_data); + // The following code computes matrix multiplication c = a * transponse(b) + // with CBLAS, where: + // * `a` is a matrix with dimensions (m, k). + // * `b` is a matrix with dimensions (n, k), so transpose(b) is (k, n). + // * `c` is a matrix with dimensions (m, n). + // The naming of variables are aligned with CBLAS specification here. + const float* a = gemm_input_data; + const float* b = filter_data; + float* c = output_data; + const int gemm_input_dims = gemm_input_shape->DimensionsCount(); + int m = FlatSizeSkipDim(*gemm_input_shape, gemm_input_dims - 1); + int n = output_shape.Dims(3); + int k = gemm_input_shape->Dims(gemm_input_dims - 1); + +#if defined(TF_LITE_USE_CBLAS) && defined(__APPLE__) + // The stride of matrix a, b and c respectively. + int stride_a = k; + int stride_b = k; + int stride_c = n; + + cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasTrans, m, n, k, 1.0f, a, + stride_a, b, stride_b, 0.0f, c, stride_c); +#else + // When an optimized CBLAS implementation is not available, fall back + // to using Eigen. + typedef Eigen::Matrix + Matrix; + typedef Eigen::Map MatrixRef; + typedef Eigen::Map ConstMatrixRef; + + MatrixRef matrix_c(c, m, n); + ConstMatrixRef matrix_a(a, m, k); + ConstMatrixRef matrix_b(b, n, k); + matrix_c.noalias() = matrix_a * matrix_b.transpose(); +#endif // defined(TF_LITE_USE_CBLAS) && defined(__APPLE__) + + optimized_ops::AddBiasAndEvalActivationFunction( + output_activation_min, output_activation_max, bias_shape, bias_data, + output_shape, output_data); } inline void HybridConv(const ConvParams& params, float* scaling_factors_ptr, @@ -4292,7 +4325,6 @@ inline void LogSoftmax(const SoftmaxParams& params, using FixedPointScaledDiff = gemmlowp::FixedPoint; using FixedPointAccum = gemmlowp::FixedPoint; - using FixedPoint0 = gemmlowp::FixedPoint; const int trailing_dim = input_shape.DimensionsCount() - 1; const int outer_size = diff --git a/tensorflow/lite/kernels/internal/reference/reference_ops.h b/tensorflow/lite/kernels/internal/reference/reference_ops.h index 1bd9129488..ea3ab06da1 100644 --- a/tensorflow/lite/kernels/internal/reference/reference_ops.h +++ b/tensorflow/lite/kernels/internal/reference/reference_ops.h @@ -558,6 +558,19 @@ inline void ReluX(const tflite::ActivationParams& params, } } +inline void LeakyRelu(const tflite::LeakyReluParams& params, + const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + gemmlowp::ScopedProfilingLabel label("LeakyRelu (not fused)"); + const int flat_size = MatchingFlatSize(input_shape, output_shape); + for (int i = 0; i < flat_size; ++i) { + const float val = input_data[i]; + // Note that this implementation matches that of TensorFlow, and corresponds + // to the traditional LeakyRelu equation only for alpha <= 1. + output_data[i] = std::max(val, val * params.alpha); + } +} + inline void L2Normalization(const tflite::L2NormalizationParams& op_params, const RuntimeShape& input_shape, const float* input_data, @@ -2723,7 +2736,6 @@ inline void LogSoftmax(const SoftmaxParams& params, using FixedPointScaledDiff = gemmlowp::FixedPoint; using FixedPointAccum = gemmlowp::FixedPoint; - using FixedPoint0 = gemmlowp::FixedPoint; const int trailing_dim = input_shape.DimensionsCount() - 1; const int outer_size = @@ -3651,8 +3663,10 @@ inline void Mean(const tflite::MeanParams& op_params, const RuntimeShape& unextended_output_shape, T* output_data) { gemmlowp::ScopedProfilingLabel label("Mean"); - TFLITE_DCHECK_LE(unextended_input_shape.DimensionsCount(), 4); - TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4); + // Current implementation only supports dimension equals 4 and simultaneous + // reduction over width and height. + TFLITE_CHECK_EQ(unextended_input_shape.DimensionsCount(), 4); + TFLITE_CHECK_LE(unextended_output_shape.DimensionsCount(), 4); const RuntimeShape input_shape = RuntimeShape::ExtendedShape(4, unextended_input_shape); const RuntimeShape output_shape = @@ -3666,8 +3680,6 @@ inline void Mean(const tflite::MeanParams& op_params, const int input_height = input_shape.Dims(1); const int input_width = input_shape.Dims(2); - // The current implementation only supports simultaneous reduction over - // width and height. TFLITE_DCHECK_EQ(op_params.axis_count, 2); TFLITE_DCHECK((op_params.axis[0] == 1 && op_params.axis[1] == 2) || (op_params.axis[0] == 2 && op_params.axis[1] == 1)); @@ -4554,6 +4566,63 @@ inline void ResizeNearestNeighbor( } } +inline void BroadcastPrelu4DSlow(const PreluParams& params, + const RuntimeShape& input_shape, + const uint8* input_data, + const RuntimeShape& alpha_shape, + const uint8* alpha_data, + const RuntimeShape& output_shape, + uint8* output_data) { + TFLITE_DCHECK_LE(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(alpha_shape.DimensionsCount(), 4); + TFLITE_DCHECK_LE(output_shape.DimensionsCount(), 4); + const RuntimeShape extended_output_shape = + RuntimeShape::ExtendedShape(4, output_shape); + NdArrayDesc<4> desc1; + NdArrayDesc<4> desc2; + NdArrayDescsForElementwiseBroadcast(input_shape, alpha_shape, &desc1, &desc2); + + for (int b = 0; b < extended_output_shape.Dims(0); ++b) { + for (int y = 0; y < extended_output_shape.Dims(1); ++y) { + for (int x = 0; x < extended_output_shape.Dims(2); ++x) { + for (int c = 0; c < extended_output_shape.Dims(3); ++c) { + int output_index = Offset(extended_output_shape, b, y, x, c); + int input_index = SubscriptToIndex(desc1, b, y, x, c); + const int32 input_value = + params.input_offset + input_data[input_index]; + if (input_value >= 0) { + output_data[output_index] = input_data[input_index]; + } else { + auto alpha_index = SubscriptToIndex(desc2, b, y, x, c); + const int32 alpha_value = + params.alpha_offset + alpha_data[alpha_index]; + const int32 unclamped_output = + params.output_offset + + MultiplyByQuantizedMultiplierSmallerThanOneExp( + input_value * alpha_value, params.output_multiplier, + params.output_shift); + const int32 quantized_min = std::numeric_limits::min(); + const int32 quantized_max = std::numeric_limits::max(); + const int32 clamped_output = std::min( + quantized_max, std::max(quantized_min, unclamped_output)); + output_data[output_index] = static_cast(clamped_output); + } + } + } + } + } +} + +template +void Fill(const RuntimeShape& value_shape, const T* value_data, + const RuntimeShape& output_shape, T* output_data) { + TFLITE_DCHECK_EQ(value_shape.DimensionsCount(), 0); + const int flat_size = output_shape.FlatSize(); + for (int i = 0; i < flat_size; ++i) { + output_data[i] = *value_data; + } +} + } // namespace reference_ops } // namespace tflite diff --git a/tensorflow/lite/kernels/internal/tensor_ctypes.h b/tensorflow/lite/kernels/internal/tensor_ctypes.h index d24dca9bfb..4a94b703f8 100644 --- a/tensorflow/lite/kernels/internal/tensor_ctypes.h +++ b/tensorflow/lite/kernels/internal/tensor_ctypes.h @@ -53,6 +53,11 @@ inline bool* GetTensorData(TfLiteTensor* tensor) { return tensor != nullptr ? tensor->data.b : nullptr; } +template <> +inline int8_t* GetTensorData(TfLiteTensor* tensor) { + return tensor != nullptr ? tensor->data.int8 : nullptr; +} + template inline const T* GetTensorData(const TfLiteTensor* tensor); @@ -66,6 +71,11 @@ inline const uint8_t* GetTensorData(const TfLiteTensor* tensor) { return tensor != nullptr ? tensor->data.uint8 : nullptr; } +template <> +inline const int8_t* GetTensorData(const TfLiteTensor* tensor) { + return tensor != nullptr ? tensor->data.int8 : nullptr; +} + template <> inline const int16_t* GetTensorData(const TfLiteTensor* tensor) { return tensor != nullptr ? tensor->data.i16 : nullptr; diff --git a/tensorflow/lite/kernels/internal/types.h b/tensorflow/lite/kernels/internal/types.h index a05bd5e003..859ec8c682 100644 --- a/tensorflow/lite/kernels/internal/types.h +++ b/tensorflow/lite/kernels/internal/types.h @@ -904,6 +904,14 @@ struct PadParams { ResizingCategory resizing_category; }; +struct PreluParams { + int32 input_offset; + int32 alpha_offset; + int32 output_offset; + int32 output_multiplier; + int output_shift; +}; + struct PoolParams { FusedActivationFunctionType activation; PaddingType padding_type; @@ -1006,6 +1014,10 @@ struct UnpackParams { int16 axis; }; +struct LeakyReluParams { + float alpha; +}; + template inline void SetActivationParams(float min, float max, P* params) { params->float_activation_min = min; diff --git a/tensorflow/lite/kernels/mirror_pad.cc b/tensorflow/lite/kernels/mirror_pad.cc new file mode 100644 index 0000000000..e74e47f7a3 --- /dev/null +++ b/tensorflow/lite/kernels/mirror_pad.cc @@ -0,0 +1,374 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/reference_ops.h" +#include "tensorflow/lite/kernels/internal/tensor.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" + +namespace tflite { +namespace ops { +namespace builtin { +namespace mirror_pad { +namespace { + +// Simple class that represents a mirror padded tensor - which is the output +// from the Op. +struct PaddedTensor { + // If not null that means this is a scalar value. + // Note: This is not owned by default. It will point to the value + // in the input tensor. + const void* value = nullptr; + // If this tensor is not one value, then this vector will have + // all the tensors that belongs to this tensor. + // Pointers are owned. + std::vector> values; + // Pointers to PaddedTensors that are padded on the left of the current + // tensor. + std::vector left_pad_ptrs; + // Pointers to PaddedTensors that are padded on the right of the current + // tensor. + std::vector right_pad_ptrs; + + // Returns mutable pointer to the tensor identified by 'indices'. + PaddedTensor* GetMutable(const std::vector& indices) { + auto* result = this; + for (int i = 0; i < indices.size(); ++i) { + if (indices[i] >= result->values.size()) { + return nullptr; + } + result = result->values[indices[i]].get(); + if (result == nullptr) break; + } + return result; + } +}; + +// Util method to initialize the memory of the padded tensor. +void InitializeTensorMemory(const TfLiteIntArray* const dims, int dim_index, + int dims_size, PaddedTensor* padded_tensor) { + if (dim_index >= dims_size) { + return; + } + padded_tensor->values.reserve(dims->data[dim_index]); + for (int i = 0; i < dims->data[dim_index]; ++i) { + padded_tensor->values.emplace_back(new PaddedTensor()); + InitializeTensorMemory(dims, dim_index + 1, dims_size, + padded_tensor->values.back().get()); + } +} + +// Returns pointer to the value at the specified index in 'data'. +inline const void* GetValuePointerAtIndex(const void* data, int index, + const TfLiteType data_type) { + switch (data_type) { + case kTfLiteFloat32: + return static_cast(data) + index; + case kTfLiteInt32: + return static_cast(data) + index; + case kTfLiteUInt8: + return static_cast(data) + index; + case kTfLiteInt64: + return static_cast(data) + index; + case kTfLiteBool: + return static_cast(data) + index; + case kTfLiteInt16: + return static_cast(data) + index; + case kTfLiteInt8: + return static_cast(data) + index; + // Unsupported types ? + default: + return nullptr; + } + return nullptr; +} + +// Util method that increment index in the N-d array. +void IncrementTensorIndex(const TfLiteIntArray* dims, + std::vector* tensor_index_ptr) { + int dimension_index = dims->size - 1; + auto& tensor_index = *tensor_index_ptr; + tensor_index[dimension_index]++; + while (dimension_index >= 0 && + tensor_index[dimension_index] == dims->data[dimension_index]) { + tensor_index[dimension_index] = 0; + dimension_index--; + if (dimension_index >= 0) tensor_index[dimension_index]++; + } +} + +// Fills the 'padded_tensor' with data from 'input_tensor'. +TfLiteStatus InitFromInputTensor(const TfLiteTensor* input_tensor, + PaddedTensor* padded_tensor) { + const auto* dims = input_tensor->dims; + const auto data_type = input_tensor->type; + const void* data = static_cast(input_tensor->data.raw_const); + // Either invalid input or unsupported type.+ + if (data == nullptr) { + return kTfLiteError; + } + // Index of current processing tensor. + std::vector tensor_index(dims->size, 0); + int flat_index = 0; + const int num_elements = NumElements(input_tensor); + while (flat_index < num_elements) { + auto* tensor = padded_tensor->GetMutable(tensor_index); + if (tensor == nullptr) { + return kTfLiteError; + } + tensor->value = GetValuePointerAtIndex(data, flat_index, data_type); + IncrementTensorIndex(dims, &tensor_index); + ++flat_index; + } + + return kTfLiteOk; +} + +template +inline void GetPadding(const T* data, int offset, int64_t* left_pad, + int64_t* right_pad) { + *left_pad = static_cast(*(data + offset * 2)); + *right_pad = static_cast(*(data + offset * 2 + 1)); +} + +inline TfLiteStatus GetPadding(const TfLiteTensor* padding_matrix, + int dimension, int64_t* left_pad, + int64_t* right_pad) { + switch (padding_matrix->type) { + case kTfLiteInt32: + GetPadding(padding_matrix->data.i32, dimension, left_pad, right_pad); + break; + case kTfLiteInt64: + GetPadding(padding_matrix->data.i64, dimension, left_pad, right_pad); + break; + default: + return kTfLiteError; + } + return kTfLiteOk; +} + +TfLiteStatus ValidateTensor(const TfLiteTensor* padding_matrix, int offset, + int dimension_index, PaddedTensor* padded_tensor, + TfLiteContext* context) { + if (dimension_index >= padding_matrix->dims->data[0]) { + return kTfLiteOk; + } + + int64_t left_pad = 0, right_pad = 0; + TF_LITE_ENSURE_STATUS( + GetPadding(padding_matrix, dimension_index, &left_pad, &right_pad)); + // If we are not going to include border we must have enough values + // to use. + if (left_pad + offset > padded_tensor->values.size()) { + context->ReportError( + context, "Not enough values for Mirror Pad, required %d, available %d.", + left_pad + offset, padded_tensor->values.size()); + return kTfLiteError; + } + if (right_pad + offset > padded_tensor->values.size()) { + context->ReportError( + context, "Not enough values for Mirror Pad, required %d, available %d.", + right_pad + offset, padded_tensor->values.size()); + return kTfLiteError; + } + if (!padded_tensor->values.empty()) { + ValidateTensor(padding_matrix, offset, dimension_index + 1, + padded_tensor->values[0].get(), context); + } + return kTfLiteOk; +} + +// Fills 'padded_tensor' with the padding information based on +// 'padding_matrix'. +// 'dimension_index' represents which dimension the function is operating on. +TfLiteStatus PadTensor(const TfLiteTensor* padding_matrix, int offset, + int dimension_index, PaddedTensor* padded_tensor, + TfLiteContext* context) { + if (dimension_index >= padding_matrix->dims->data[0]) return kTfLiteOk; + + int64_t left_pad = 0, right_pad = 0; + TF_LITE_ENSURE_STATUS( + GetPadding(padding_matrix, dimension_index, &left_pad, &right_pad)); + + for (int i = left_pad + offset - 1; i >= offset && left_pad > 0; + --i, --left_pad) { + padded_tensor->left_pad_ptrs.push_back(padded_tensor->values[i].get()); + } + for (int i = padded_tensor->values.size() - (1 + offset); + i >= 0 && right_pad > 0; --i, --right_pad) { + padded_tensor->right_pad_ptrs.push_back(padded_tensor->values[i].get()); + } + + for (auto& tensor : padded_tensor->values) { + TF_LITE_ENSURE_STATUS(PadTensor(padding_matrix, offset, dimension_index + 1, + tensor.get(), context)); + } + return kTfLiteOk; +} + +// Fills 'output_data' with data from 'padded_tensor'. +// The function does this recursively by setting left padding first then +// original data, followed by the right padding. +template +int FillOutput(const PaddedTensor* padded_tensor, T* output_data, + int index_in_output) { + if (padded_tensor == nullptr || output_data == nullptr) { + return -1; + } + if (padded_tensor->value != nullptr) { + output_data[index_in_output] = *static_cast(padded_tensor->value); + return index_in_output + 1; + } + for (const auto* tensor : padded_tensor->left_pad_ptrs) { + index_in_output = FillOutput(tensor, output_data, index_in_output); + } + for (const auto& tensor : padded_tensor->values) { + index_in_output = FillOutput(tensor.get(), output_data, index_in_output); + } + for (const auto* tensor : padded_tensor->right_pad_ptrs) { + index_in_output = FillOutput(tensor, output_data, index_in_output); + } + return index_in_output; +} + +// Returns the shape of the final output after padding. +std::unique_ptr GetPaddedOutputShape( + const TfLiteTensor* input, const TfLiteTensor* padding_matrix) { + const int input_dims = NumDimensions(input); + std::unique_ptr shape( + TfLiteIntArrayCreate(input_dims), TfLiteIntArrayFree); + + int64_t left_pad = 0, right_pad = 0; + for (int i = 0; i < input_dims; ++i) { + GetPadding(padding_matrix, i, &left_pad, &right_pad); + shape->data[i] = SizeOfDimension(input, i) + left_pad + right_pad; + } + return shape; +} + +} // namespace + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteTensor* input_tensor = GetInput(context, node, 0); + const TfLiteTensor* padding_matrix = GetInput(context, node, 1); + auto* params = + reinterpret_cast(node->builtin_data); + + if (params == nullptr) { + return kTfLiteError; + } + const int input_dims = NumDimensions(input_tensor); + + TfLiteTensor* output_tensor = GetOutput(context, node, 0); + if (IsDynamicTensor(output_tensor)) { + auto output_size = GetPaddedOutputShape(input_tensor, padding_matrix); + if (output_size == nullptr) { + return kTfLiteError; + } + TF_LITE_ENSURE_STATUS( + context->ResizeTensor(context, output_tensor, output_size.release())); + } + + PaddedTensor padded_tensor; + // Initialize memory. + InitializeTensorMemory(input_tensor->dims, 0, input_dims, &padded_tensor); + // Set the values from the input_tensor. + TF_LITE_ENSURE_STATUS(InitFromInputTensor(input_tensor, &padded_tensor)); + + const int offset = + params->mode != TfLiteMirrorPaddingMode::kTfLiteMirrorPaddingReflect ? 0 + : 1; + // Make sure padding values are sufficient and valid to use. + TF_LITE_ENSURE_STATUS( + ValidateTensor(padding_matrix, offset, 0, &padded_tensor, context)); + // Apply padding. + TF_LITE_ENSURE_STATUS( + PadTensor(padding_matrix, offset, 0, &padded_tensor, context)); + + // Fill the output tensor from the padded tensor. + TfLiteStatus status = kTfLiteOk; + +#define TF_LITE_MIRROR_PAD(type) \ + FillOutput(&padded_tensor, GetTensorData(output_tensor), 0); + + switch (output_tensor->type) { + case kTfLiteFloat32: { + TF_LITE_MIRROR_PAD(float); + break; + } + case kTfLiteInt32: { + TF_LITE_MIRROR_PAD(int32_t); + break; + } + case kTfLiteUInt8: { + TF_LITE_MIRROR_PAD(uint8_t); + break; + } + case kTfLiteInt64: { + TF_LITE_MIRROR_PAD(int64_t); + break; + } + default: + status = kTfLiteError; + break; + } +#undef TF_LITE_MIRROR_PAD + return status; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + return nullptr; +} + +void Free(TfLiteContext* context, void* buffer) {} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + const TfLiteTensor* input_tensor = GetInput(context, node, 0); + const TfLiteTensor* padding_matrix = GetInput(context, node, 1); + TfLiteTensor* output_tensor = GetOutput(context, node, 0); + + TF_LITE_ENSURE_EQ(context, NumDimensions(padding_matrix), 2); + TF_LITE_ENSURE_EQ(context, SizeOfDimension(padding_matrix, 0), + NumDimensions(input_tensor)); + + if (!IsConstantTensor(padding_matrix)) { + SetTensorToDynamic(output_tensor); + return kTfLiteOk; + } + // We have constant padding, so we can infer output size. + + auto output_size = GetPaddedOutputShape(input_tensor, padding_matrix); + if (output_size == nullptr) { + return kTfLiteError; + } + return context->ResizeTensor(context, output_tensor, output_size.release()); +} + +} // namespace mirror_pad +TfLiteRegistration* Register_MIRROR_PAD() { + static TfLiteRegistration r = {mirror_pad::Init, mirror_pad::Free, + mirror_pad::Prepare, mirror_pad::Eval}; + return &r; +} + +} // namespace builtin +} // namespace ops +} // namespace tflite diff --git a/tensorflow/lite/kernels/mirror_pad_test.cc b/tensorflow/lite/kernels/mirror_pad_test.cc new file mode 100644 index 0000000000..fd09e6e449 --- /dev/null +++ b/tensorflow/lite/kernels/mirror_pad_test.cc @@ -0,0 +1,189 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include "tensorflow/lite/interpreter.h" +#include "tensorflow/lite/kernels/register.h" +#include "tensorflow/lite/kernels/test_util.h" +#include "tensorflow/lite/model.h" + +namespace tflite { +namespace { + +using ::testing::ElementsAreArray; + +template +class BaseMirrorPadOpModel : public SingleOpModel { + public: + BaseMirrorPadOpModel(const TensorData& input, + const TensorData& padding_matrix, + const TensorData& output, + const tflite::MirrorPadMode mode) { + input_id_ = AddInput(input); + padding_matrix_id_ = AddInput(padding_matrix); + output_id_ = AddOutput(output); + SetBuiltinOp(BuiltinOperator_MIRROR_PAD, BuiltinOptions_MirrorPadOptions, + CreateMirrorPadOptions(builder_, mode).Union()); + BuildInterpreter({GetShape(input_id_), GetShape(padding_matrix_id_)}); + } + + int input_tensor_id() { return input_id_; } + int padding_matrix_tensor_id() { return padding_matrix_id_; } + + std::vector GetOutput() { return ExtractVector(output_id_); } + + protected: + int input_id_; + int padding_matrix_id_; + int output_id_; +}; + +TEST(MirrorPadTest, EmptyPad) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_REFLECT); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {0, 0, 0, 0}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), ElementsAreArray({1, 2, 3, 4, 5, 6})); +} + +TEST(MirrorPadTest, PadOneSide_right_Reflect) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_REFLECT); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {0, 1, 0, 1}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({1, 2, 3, 2, 4, 5, 6, 5, 1, 2, 3, 2})); +} + +TEST(MirrorPadTest, PadOneSide_left_Reflect) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_REFLECT); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {1, 0, 1, 0}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({5, 4, 5, 6, 2, 1, 2, 3, 5, 4, 5, 6})); +} + +TEST(MirrorPadTest, PadOneSide_right_Symmetric) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_SYMMETRIC); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {0, 1, 0, 1}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({1, 2, 3, 3, 4, 5, 6, 6, 4, 5, 6, 6})); +} + +TEST(MirrorPadTest, PadOneSide_left_Symmetric) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_SYMMETRIC); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {1, 0, 1, 0}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({1, 1, 2, 3, 1, 1, 2, 3, 4, 4, 5, 6})); +} + +TEST(MirrorPadTest, PadBothSides_Symmetric) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_SYMMETRIC); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {1, 1, 1, 1}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({1, 1, 2, 3, 3, 1, 1, 2, 3, 3, + 4, 4, 5, 6, 6, 4, 4, 5, 6, 6})); +} + +TEST(MirrorPadTest, PadBothSides_Reflect) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_REFLECT); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {1, 1, 1, 1}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({5, 4, 5, 6, 5, 2, 1, 2, 3, 2, + 5, 4, 5, 6, 5, 2, 1, 2, 3, 2})); +} + +TEST(MirrorPadTest, PadBothSides_Symmetric_Whole) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_SYMMETRIC); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {2, 2, 3, 3}); + model.Invoke(); + EXPECT_THAT( + model.GetOutput(), + ElementsAreArray({6, 5, 4, 4, 5, 6, 6, 5, 4, 3, 2, 1, 1, 2, 3, 3, 2, 1, + 3, 2, 1, 1, 2, 3, 3, 2, 1, 6, 5, 4, 4, 5, 6, 6, 5, 4, + 6, 5, 4, 4, 5, 6, 6, 5, 4, 3, 2, 1, 1, 2, 3, 3, 2, 1})); +} + +TEST(MirrorPadTest, PadBothSides_Reflect_Whole) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_REFLECT); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {1, 1, 2, 2}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({6, 5, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 2, 1, + 6, 5, 4, 5, 6, 5, 4, 3, 2, 1, 2, 3, 2, 1})); +} + +TEST(MirrorPadTest, Pad_Symmetric) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {2, 3}}, {TensorType_INT32, {2, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_SYMMETRIC); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3, 4, 5, 6}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {1, 1, 2, 2}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({2, 1, 1, 2, 3, 3, 2, 2, 1, 1, 2, 3, 3, 2, + 5, 4, 4, 5, 6, 6, 5, 5, 4, 4, 5, 6, 6, 5})); +} + +TEST(MirrorPadTest, Pad_1D_Reflect) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {3}}, {TensorType_INT32, {1, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_REFLECT); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {0, 2}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), ElementsAreArray({1, 2, 3, 2, 1})); +} + +TEST(MirrorPadTest, Pad_1D_Symmetric) { + BaseMirrorPadOpModel model( + {TensorType_INT32, {3}}, {TensorType_INT32, {1, 2}}, + {TensorType_INT32, {}}, tflite::MirrorPadMode_SYMMETRIC); + model.PopulateTensor(model.input_tensor_id(), {1, 2, 3}); + model.PopulateTensor(model.padding_matrix_tensor_id(), {0, 2}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), ElementsAreArray({1, 2, 3, 3, 2})); +} + +} // namespace +} // namespace tflite diff --git a/tensorflow/lite/kernels/pooling_test.cc b/tensorflow/lite/kernels/pooling_test.cc index 80eef02509..98777f1c13 100644 --- a/tensorflow/lite/kernels/pooling_test.cc +++ b/tensorflow/lite/kernels/pooling_test.cc @@ -67,6 +67,10 @@ class QuantizedPoolingOpModel : public BasePoolingOpModel { QuantizeAndPopulate(input_, data); } + void SetInput(const std::vector& data) { + QuantizeAndPopulate(input_, data); + } + std::vector GetOutput() { return ExtractVector(output_); } std::vector GetDequantizedOutput() { return Dequantize(ExtractVector(output_), @@ -106,6 +110,45 @@ TEST(QuantizedPoolingOpTest, AveragePool) { EXPECT_THAT(m.GetOutput(), ElementsAreArray({44, 92})); } +// Send in a white image, expect a white pixel. +TEST(QuantizedPoolingOpTest, AveragePoolImageSize16) { + int image_size = 16; + QuantizedPoolingOpModel m( + BuiltinOperator_AVERAGE_POOL_2D, + /*input=*/{TensorType_UINT8, {1, image_size, image_size, 1}, 0, 16}, + /*filter_width=*/image_size, + /*filter_height=*/image_size, + /*output=*/{TensorType_UINT8, {}, 0, 16}); + + std::vector input(image_size * image_size, 16.f); + m.SetInput(input); + m.Invoke(); + + EXPECT_THAT(m.GetOutput(), ::testing::ElementsAre(255)); + EXPECT_THAT(m.GetDequantizedOutput(), ElementsAreArray(ArrayFloatNear({16}))); +} + +// Send in a white image, expect something other than a white pixel, due to +// overflow. +TEST(QuantizedPoolingOpTest, AveragePoolImageSize17) { + int image_size = 17; + QuantizedPoolingOpModel m( + BuiltinOperator_AVERAGE_POOL_2D, + /*input=*/{TensorType_UINT8, {1, image_size, image_size, 1}, 0, 16}, + /*filter_width=*/image_size, + /*filter_height=*/image_size, + /*output=*/{TensorType_UINT8, {}, 0, 16}); + + std::vector input(image_size * image_size, 16.f); + m.SetInput(input); + m.Invoke(); + + // Ordinarily we would see '255' here. However, the optimized version of + // AveragePool uses a uint16 accumulator which causes it to overflow for + // images this large. + EXPECT_THAT(m.GetOutput(), ::testing::ElementsAre(28)); +} + TEST(FloatPoolingOpTest, MaxPool) { FloatPoolingOpModel m(BuiltinOperator_MAX_POOL_2D, /*input=*/{TensorType_FLOAT32, {1, 2, 4, 1}}, diff --git a/tensorflow/lite/kernels/reduce.cc b/tensorflow/lite/kernels/reduce.cc index ed2d475f6d..336e827ca4 100644 --- a/tensorflow/lite/kernels/reduce.cc +++ b/tensorflow/lite/kernels/reduce.cc @@ -20,6 +20,8 @@ limitations under the License. #include "tensorflow/lite/kernels/internal/quantization_util.h" #include "tensorflow/lite/kernels/internal/reference/reference_ops.h" #include "tensorflow/lite/kernels/internal/tensor.h" +#include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +#include "tensorflow/lite/kernels/internal/types.h" #include "tensorflow/lite/kernels/kernel_util.h" #include "tensorflow/lite/kernels/op_macros.h" @@ -229,6 +231,17 @@ TfLiteStatus PrepareMeanOrSum(TfLiteContext* context, TfLiteNode* node) { return ResizeTempSum(context, &op_context, temp_sum); } +void ResolveAxis(const int* axis_data, int axis_count, + tflite::MeanParams* op_params) { + int i = 0; + for (; i < axis_count; ++i) { + op_params->axis[i] = static_cast(axis_data[i]); + } + for (; i < 4; ++i) { + op_params->axis[i] = 1; + } +} + template TfLiteStatus EvalMean(TfLiteContext* context, TfLiteNode* node) { OpContext op_context(context, node); @@ -257,9 +270,23 @@ TfLiteStatus EvalMean(TfLiteContext* context, TfLiteNode* node) { if (kernel_type == kReference) { switch (op_context.input->type) { - case kTfLiteFloat32: - TF_LITE_ENSURE(context, TF_LITE_MEAN(reference_ops, float, float)); - break; + case kTfLiteFloat32: { + tflite::MeanParams op_params; + op_params.axis_count = num_axis; + ResolveAxis(GetTensorData(op_context.axis), num_axis, &op_params); + const TfLiteTensor* input = op_context.input; + if (op_context.params->keep_dims && NumDimensions(input) == 4 && + op_params.axis_count == 2 && + ((op_params.axis[0] == 1 && op_params.axis[1] == 2) || + (op_params.axis[0] == 2 && op_params.axis[1] == 1))) { + reference_ops::Mean(op_params, GetTensorShape(input), + GetTensorData(input), + GetTensorShape(op_context.output), + GetTensorData(op_context.output)); + } else { + TF_LITE_ENSURE(context, TF_LITE_MEAN(reference_ops, float, float)); + } + } break; case kTfLiteInt32: TF_LITE_ENSURE(context, TF_LITE_MEAN(reference_ops, int, int64_t)); break; @@ -286,7 +313,8 @@ TfLiteStatus EvalMean(TfLiteContext* context, TfLiteNode* node) { GetTensorData(op_context.axis), num_axis, op_context.params->keep_dims, GetTensorData(temp_index), GetTensorData(resolved_axis), - GetTensorData(temp_sum), /*compute_sum=*/false)); + GetTensorData(temp_sum), + /*compute_sum=*/false)); } break; default: diff --git a/tensorflow/lite/kernels/register.cc b/tensorflow/lite/kernels/register.cc index c683453767..3c60d281b3 100644 --- a/tensorflow/lite/kernels/register.cc +++ b/tensorflow/lite/kernels/register.cc @@ -31,6 +31,7 @@ TfLiteRegistration* Register_RELU_1(); namespace builtin { +TfLiteRegistration* Register_ABS(); TfLiteRegistration* Register_RELU(); TfLiteRegistration* Register_RELU_N1_TO_1(); TfLiteRegistration* Register_RELU6(); @@ -74,6 +75,7 @@ TfLiteRegistration* Register_GATHER(); TfLiteRegistration* Register_TRANSPOSE(); TfLiteRegistration* Register_MEAN(); TfLiteRegistration* Register_SPLIT(); +TfLiteRegistration* Register_SPLIT_V(); TfLiteRegistration* Register_SQUEEZE(); TfLiteRegistration* Register_STRIDED_SLICE(); TfLiteRegistration* Register_EXP(); @@ -123,6 +125,10 @@ TfLiteRegistration* Register_SQUARE(); TfLiteRegistration* Register_ZEROS_LIKE(); TfLiteRegistration* Register_FLOOR_MOD(); TfLiteRegistration* Register_RANGE(); +TfLiteRegistration* Register_LEAKY_RELU(); +TfLiteRegistration* Register_SQUARED_DIFFERENCE(); +TfLiteRegistration* Register_FILL(); +TfLiteRegistration* Register_MIRROR_PAD(); TfLiteStatus UnsupportedTensorFlowOp(TfLiteContext* context, TfLiteNode* node) { context->ReportError( @@ -152,6 +158,7 @@ const TfLiteRegistration* BuiltinOpResolver::FindOp(const char* op, } BuiltinOpResolver::BuiltinOpResolver() { + AddBuiltin(BuiltinOperator_ABS, Register_ABS()); AddBuiltin(BuiltinOperator_RELU, Register_RELU()); AddBuiltin(BuiltinOperator_RELU_N1_TO_1, Register_RELU_N1_TO_1()); AddBuiltin(BuiltinOperator_RELU6, Register_RELU6()); @@ -207,6 +214,7 @@ BuiltinOpResolver::BuiltinOpResolver() { AddBuiltin(BuiltinOperator_DIV, Register_DIV()); AddBuiltin(BuiltinOperator_SUB, Register_SUB()); AddBuiltin(BuiltinOperator_SPLIT, Register_SPLIT()); + AddBuiltin(BuiltinOperator_SPLIT_V, Register_SPLIT_V()); AddBuiltin(BuiltinOperator_SQUEEZE, Register_SQUEEZE()); AddBuiltin(BuiltinOperator_STRIDED_SLICE, Register_STRIDED_SLICE()); AddBuiltin(BuiltinOperator_EXP, Register_EXP()); @@ -256,6 +264,10 @@ BuiltinOpResolver::BuiltinOpResolver() { AddBuiltin(BuiltinOperator_ZEROS_LIKE, Register_ZEROS_LIKE()); AddBuiltin(BuiltinOperator_FLOOR_MOD, Register_FLOOR_MOD()); AddBuiltin(BuiltinOperator_RANGE, Register_RANGE()); + AddBuiltin(BuiltinOperator_LEAKY_RELU, Register_LEAKY_RELU()); + AddBuiltin(BuiltinOperator_SQUARED_DIFFERENCE, Register_SQUARED_DIFFERENCE()); + AddBuiltin(BuiltinOperator_FILL, Register_FILL()); + AddBuiltin(BuiltinOperator_MIRROR_PAD, Register_MIRROR_PAD()); // TODO(andrewharp, ahentz): Move these somewhere more appropriate so that // custom ops aren't always included by default. diff --git a/tensorflow/lite/kernels/register.h b/tensorflow/lite/kernels/register.h index eb5ce667d4..059c9d165e 100644 --- a/tensorflow/lite/kernels/register.h +++ b/tensorflow/lite/kernels/register.h @@ -15,7 +15,6 @@ limitations under the License. #ifndef TENSORFLOW_LITE_KERNELS_REGISTER_H_ #define TENSORFLOW_LITE_KERNELS_REGISTER_H_ -#include #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/model.h" #include "tensorflow/lite/mutable_op_resolver.h" diff --git a/tensorflow/lite/kernels/skip_gram.cc b/tensorflow/lite/kernels/skip_gram.cc index f20719ecaf..265ba18a3e 100644 --- a/tensorflow/lite/kernels/skip_gram.cc +++ b/tensorflow/lite/kernels/skip_gram.cc @@ -107,7 +107,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { // Generate n-grams recursively. tflite::DynamicBuffer buf; if (words.size() < params->ngram_size) { - buf.WriteToTensor(GetOutput(context, node, 0)); + buf.WriteToTensorAsVector(GetOutput(context, node, 0)); return kTfLiteOk; } @@ -145,7 +145,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { } } - buf.WriteToTensor(GetOutput(context, node, 0)); + buf.WriteToTensorAsVector(GetOutput(context, node, 0)); return kTfLiteOk; } } // namespace diff --git a/tensorflow/lite/kernels/split_v.cc b/tensorflow/lite/kernels/split_v.cc new file mode 100644 index 0000000000..060e3c5f79 --- /dev/null +++ b/tensorflow/lite/kernels/split_v.cc @@ -0,0 +1,207 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" +#include "tensorflow/lite/kernels/internal/reference/reference_ops.h" +#include "tensorflow/lite/kernels/internal/tensor.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" + +namespace tflite { +namespace ops { +namespace builtin { +namespace split_v { + +struct OpContext { + OpContext(TfLiteContext* context, TfLiteNode* node) { + params = reinterpret_cast(node->builtin_data); + input = GetInput(context, node, 0); + size_splits = GetInput(context, node, 1); + axis = GetInput(context, node, 2); + } + TfLiteSplitVParams* params; + const TfLiteTensor* input; + const TfLiteTensor* size_splits; + const TfLiteTensor* axis; +}; + +TfLiteStatus UseDynamicOutputTensors(TfLiteContext* context, TfLiteNode* node) { + for (int i = 0; i < NumOutputs(node); ++i) { + SetTensorToDynamic(GetOutput(context, node, i)); + } + return kTfLiteOk; +} + +template +void GetSizeSplitsVector(const TfLiteTensor* size_splits, + std::vector* size_splits_vector) { + const auto num_elements = NumElements(size_splits); + for (int i = 0; i < num_elements; ++i) { + size_splits_vector->push_back(GetTensorData(size_splits)[i]); + } +} + +TfLiteStatus ResizeOutputTensors(TfLiteContext* context, TfLiteNode* node, + const TfLiteTensor* input, + const TfLiteTensor* size_splits, + const TfLiteTensor* axis) { + int axis_value = GetTensorData(axis)[0]; + if (axis_value < 0) { + axis_value += NumDimensions(input); + } + + std::vector size_splits_vector; + if (size_splits->type == kTfLiteInt32) { + GetSizeSplitsVector(size_splits, &size_splits_vector); + } else if (size_splits->type == kTfLiteInt64) { + GetSizeSplitsVector(size_splits, &size_splits_vector); + } else { + context->ReportError(context, "size_splits only support type int32|int64."); + return kTfLiteError; + } + + int minus_one_index = -1; + int64_t size_splits_sum = 0; + + for (int i = 0; i < size_splits_vector.size(); ++i) { + if (size_splits_vector.at(i) == -1) { + if (minus_one_index == -1) { + minus_one_index = i; + } else { + context->ReportError(context, + "The size_splits contains more than one -1."); + } + } else { + size_splits_sum += size_splits_vector.at(i); + } + } + + const int input_size = SizeOfDimension(input, axis_value); + + if (minus_one_index != -1) { + if (size_splits_sum > input_size) { + context->ReportError( + context, + "The sum of size_splits must be less than the dimension of value."); + } else { + size_splits_vector[minus_one_index] = input_size - size_splits_sum; + } + } else if (size_splits_sum != input_size) { + context->ReportError( + context, + "The size_splits must sum to the dimension of value along axis."); + } + + for (int i = 0; i < NumOutputs(node); ++i) { + TfLiteIntArray* output_dims = TfLiteIntArrayCopy(input->dims); + output_dims->data[axis_value] = size_splits_vector.at(i); + TfLiteTensor* output = GetOutput(context, node, i); + TF_LITE_ENSURE_STATUS(context->ResizeTensor(context, output, output_dims)); + } + + return kTfLiteOk; +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + TF_LITE_ENSURE_EQ(context, NumInputs(node), 3); + + OpContext op_context(context, node); + + TF_LITE_ENSURE_EQ(context, NumOutputs(node), op_context.params->num_splits); + + auto input_type = op_context.input->type; + TF_LITE_ENSURE(context, input_type == kTfLiteFloat32 || + input_type == kTfLiteUInt8 || + input_type == kTfLiteInt16); + for (int i = 0; i < NumOutputs(node); ++i) { + GetOutput(context, node, i)->type = input_type; + } + + auto size_splits = op_context.size_splits; + TF_LITE_ENSURE_EQ(context, NumDimensions(size_splits), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), NumElements(size_splits)); + + // If we know the contents of the 'size_splits' tensor and the 'axis' tensor, + // resize all outputs. Otherwise, wait until Eval(). + if (IsConstantTensor(op_context.size_splits) && + IsConstantTensor(op_context.axis)) { + return ResizeOutputTensors(context, node, op_context.input, + op_context.size_splits, op_context.axis); + } else { + return UseDynamicOutputTensors(context, node); + } +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + OpContext op_context(context, node); + + // When the 'size_splits' and the 'axis' tensor is non-const we can't resize + // output tensors in Prepare(), and we have to do it now. + if (!IsConstantTensor(op_context.axis) || + !IsConstantTensor(op_context.size_splits)) { + TF_LITE_ENSURE_OK( + context, ResizeOutputTensors(context, node, op_context.input, + op_context.size_splits, op_context.axis)); + } + + int axis_value = GetTensorData(op_context.axis)[0]; + + // Use split function to build the outputs since they share the same logic. +#define TF_LITE_SPLIT_V(scalar) \ + VectorOfTensors all_outputs(*context, *node->outputs); \ + tflite::SplitParams op_params; \ + op_params.num_split = NumOutputs(node); \ + op_params.axis = axis_value; \ + reference_ops::Split(op_params, GetTensorShape(op_context.input), \ + GetTensorData(op_context.input), \ + all_outputs.shapes(), all_outputs.data()); + switch (op_context.input->type) { + case kTfLiteFloat32: { + TF_LITE_SPLIT_V(float); + break; + } + case kTfLiteUInt8: { + TF_LITE_SPLIT_V(uint8_t); + break; + } + case kTfLiteInt16: { + TF_LITE_SPLIT_V(int16_t); + break; + } + default: + context->ReportError( + context, + "Only float32, uint8 and int16 are currently supported, got %d.", + op_context.input->type); + return kTfLiteError; + } +#undef TF_LITE_SPLIT_V + + return kTfLiteOk; +} + +} // namespace split_v + +TfLiteRegistration* Register_SPLIT_V() { + static TfLiteRegistration r = {nullptr, nullptr, split_v::Prepare, + split_v::Eval}; + return &r; +} + +} // namespace builtin +} // namespace ops +} // namespace tflite diff --git a/tensorflow/lite/kernels/split_v_test.cc b/tensorflow/lite/kernels/split_v_test.cc new file mode 100644 index 0000000000..2d1d36d685 --- /dev/null +++ b/tensorflow/lite/kernels/split_v_test.cc @@ -0,0 +1,175 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include +#include "tensorflow/lite/interpreter.h" +#include "tensorflow/lite/kernels/register.h" +#include "tensorflow/lite/kernels/test_util.h" +#include "tensorflow/lite/model.h" + +namespace tflite { +namespace { + +using ::testing::ElementsAreArray; + +constexpr int kAxisIsATensor = -1000; + +class SplitVOpModel : public SingleOpModel { + public: + SplitVOpModel(const TensorData& input, const TensorData& size_splits, + int num_splits, int axis) { + input_ = AddInput(input); + size_splits_ = AddInput(size_splits); + if (axis == kAxisIsATensor) { + axis_ = AddInput({TensorType_INT32, {1}}); + } else { + axis_ = AddConstInput(TensorType_INT32, {axis}, {1}); + } + for (int i = 0; i < num_splits; ++i) { + outputs_.push_back(AddOutput(input.type)); + } + SetBuiltinOp(BuiltinOperator_SPLIT_V, BuiltinOptions_SplitVOptions, + CreateSplitVOptions(builder_, num_splits).Union()); + if (axis == kAxisIsATensor) { + BuildInterpreter( + {GetShape(input_), GetShape(size_splits_), GetShape(axis_)}); + } else { + BuildInterpreter({GetShape(input_), GetShape(size_splits_), {}}); + } + } + + void SetInput(std::initializer_list data) { + PopulateTensor(input_, data); + } + void SetSizeSplits(std::initializer_list data) { + PopulateTensor(size_splits_, data); + } + void SetAxis(int axis) { PopulateTensor(axis_, {axis}); } + + std::vector GetOutput(int i) { + return ExtractVector(outputs_[i]); + } + std::vector GetOutputShape(int i) { return GetTensorShape(outputs_[i]); } + + private: + int input_; + int size_splits_; + int axis_; + std::vector outputs_; +}; + +// TODO(ruic): Add tests to test quantized values. b/119638735 +using TensorValues = std::initializer_list; + +void Check(int axis, std::initializer_list input_shape, + std::initializer_list size_splits_shape, + std::vector> output_shapes, + const TensorValues& input_data, + const std::initializer_list& size_splits_data, + const std::vector& output_data) { + int num_splits = size_splits_data.size(); + SplitVOpModel m({TensorType_FLOAT32, input_shape}, + {TensorType_INT32, size_splits_shape}, num_splits, + kAxisIsATensor); + m.SetInput(input_data); + m.SetSizeSplits(size_splits_data); + m.SetAxis(axis); + m.Invoke(); + for (int i = 0; i < num_splits; ++i) { + EXPECT_THAT(m.GetOutput(i), ElementsAreArray(output_data[i])); + EXPECT_THAT(m.GetOutputShape(i), ElementsAreArray(output_shapes[i])); + } + + SplitVOpModel const_m({TensorType_FLOAT32, input_shape}, + {TensorType_INT32, size_splits_shape}, num_splits, + axis); + const_m.SetInput(input_data); + const_m.SetSizeSplits(size_splits_data); + const_m.Invoke(); + for (int i = 0; i < num_splits; ++i) { + EXPECT_THAT(const_m.GetOutput(i), ElementsAreArray(output_data[i])); + EXPECT_THAT(const_m.GetOutputShape(i), ElementsAreArray(output_shapes[i])); + } +} + +TEST(SplitVOpTest, TwoDimensional) { + // Input shape: {4, 3} + // size_splits: {1, 1, 3} + // axis: 0 + // We should have 3 outpus with shapes respectively: + // output 0 : {1, 3} + // output 1 : {1, 3} + // output 1 : {2, 3} + Check(/*axis=*/0, {4, 3}, {3}, {{1, 3}, {1, 3}, {2, 3}}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, {1, 1, 2}, + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9, 10, 11, 12}}); +} + +TEST(SplitVOpTest, FourDimensional) { + Check(/*axis=*/0, {2, 2, 2, 2}, {2}, {{1, 2, 2, 2}, {1, 2, 2, 2}}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {1, 1}, + { + {1, 2, 3, 4, 5, 6, 7, 8}, + {9, 10, 11, 12, 13, 14, 15, 16}, + }); + Check(/*axis=*/1, {2, 2, 2, 2}, {2}, {{2, 1, 2, 2}, {2, 1, 2, 2}}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {1, -1}, + { + {1, 2, 3, 4, 9, 10, 11, 12}, + {5, 6, 7, 8, 13, 14, 15, 16}, + }); + Check(/*axis=*/2, {2, 2, 2, 2}, {2}, {{2, 2, 1, 2}, {2, 2, 1, 2}}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {1, 1}, + { + {1, 2, 5, 6, 9, 10, 13, 14}, + {3, 4, 7, 8, 11, 12, 15, 16}, + }); + Check(/*axis=*/3, {2, 2, 2, 2}, {2}, {{2, 2, 2, 1}, {2, 2, 2, 1}}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {1, 1}, + { + {1, 3, 5, 7, 9, 11, 13, 15}, + {2, 4, 6, 8, 10, 12, 14, 16}, + }); +} + +TEST(SplitVOpTest, OneDimensional) { + Check(/*axis=*/0, {8}, {8}, {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}}, + {1, 2, 3, 4, 5, 6, 7, 8}, {1, 1, 1, 1, 1, 1, 1, 1}, + {{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}}); +} + +TEST(SplitVOpTest, OneDimensional2) { + Check(/*axis=*/0, {8}, {8}, {{1}, {1}, {1}, {1}, {1}, {1}, {2}, {0}}, + {1, 2, 3, 4, 5, 6, 7, 8}, {1, 1, 1, 1, 1, 1, 2, -1}, + {{1}, {2}, {3}, {4}, {5}, {6}, {7, 8}, {}}); +} + +TEST(SplitVOpTest, NegativeAxis) { + Check(/*axis=*/-4, {2, 2, 2, 2}, {2}, {{1, 2, 2, 2}, {1, 2, 2, 2}}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}, {1, 1}, + { + {1, 2, 3, 4, 5, 6, 7, 8}, + {9, 10, 11, 12, 13, 14, 15, 16}, + }); +} + +} // namespace +} // namespace tflite + +int main(int argc, char** argv) { + ::tflite::LogToStderr(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tensorflow/lite/kernels/squared_difference.cc b/tensorflow/lite/kernels/squared_difference.cc new file mode 100644 index 0000000000..59b53a6287 --- /dev/null +++ b/tensorflow/lite/kernels/squared_difference.cc @@ -0,0 +1,129 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/c/builtin_op_data.h" +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" +#include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/reference_ops.h" +#include "tensorflow/lite/kernels/internal/tensor.h" +#include "tensorflow/lite/kernels/kernel_util.h" +#include "tensorflow/lite/kernels/op_macros.h" + +namespace tflite { +namespace ops { +namespace builtin { +namespace squared_difference { + +constexpr int kInputTensor1 = 0; +constexpr int kInputTensor2 = 1; +constexpr int kOutputTensor = 0; + +struct OpData { + bool requires_broadcast; +}; + +template +T SquaredDifference(T input1, T input2) { + const T difference = input1 - input2; + return difference * difference; +} + +void* Init(TfLiteContext* context, const char* buffer, size_t length) { + auto* data = new OpData; + data->requires_broadcast = false; + return data; +} + +void Free(TfLiteContext* context, void* buffer) { + delete reinterpret_cast(buffer); +} + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + OpData* data = reinterpret_cast(node->user_data); + + TF_LITE_ENSURE_EQ(context, NumInputs(node), 2); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + + const TfLiteTensor* input1 = GetInput(context, node, kInputTensor1); + const TfLiteTensor* input2 = GetInput(context, node, kInputTensor2); + TfLiteTensor* output = GetOutput(context, node, kOutputTensor); + + TF_LITE_ENSURE_EQ(context, input1->type, input2->type); + output->type = input2->type; + + data->requires_broadcast = !HaveSameShapes(input1, input2); + + TfLiteIntArray* output_size = nullptr; + if (data->requires_broadcast) { + TF_LITE_ENSURE_OK(context, CalculateShapeForBroadcast( + context, input1, input2, &output_size)); + } else { + output_size = TfLiteIntArrayCopy(input1->dims); + } + + return context->ResizeTensor(context, output, output_size); +} + +template +void EvalSquaredDifference(TfLiteContext* context, TfLiteNode* node, + const OpData* data, const TfLiteTensor* input1, + const TfLiteTensor* input2, TfLiteTensor* output) { + if (data->requires_broadcast) { + reference_ops::BroadcastBinaryFunction4DSlow( + GetTensorShape(input1), GetTensorData(input1), + GetTensorShape(input2), GetTensorData(input2), + GetTensorShape(output), GetTensorData(output), SquaredDifference); + } else { + reference_ops::BinaryFunction( + GetTensorShape(input1), GetTensorData(input1), + GetTensorShape(input2), GetTensorData(input2), + GetTensorShape(output), GetTensorData(output), SquaredDifference); + } +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + OpData* data = reinterpret_cast(node->user_data); + + const TfLiteTensor* input1 = GetInput(context, node, kInputTensor1); + const TfLiteTensor* input2 = GetInput(context, node, kInputTensor2); + TfLiteTensor* output = GetOutput(context, node, kOutputTensor); + + if (output->type == kTfLiteFloat32) { + EvalSquaredDifference(context, node, data, input1, input2, output); + } else if (output->type == kTfLiteInt32) { + EvalSquaredDifference(context, node, data, input1, input2, output); + } else { + context->ReportError(context, + "SquaredDifference only supports FLOAT32, INT32 and " + "quantized UINT8 now, got %d.", + output->type); + return kTfLiteError; + } + + return kTfLiteOk; +} + +} // namespace squared_difference + +TfLiteRegistration* Register_SQUARED_DIFFERENCE() { + static TfLiteRegistration r = { + squared_difference::Init, squared_difference::Free, + squared_difference::Prepare, squared_difference::Eval}; + return &r; +} + +} // namespace builtin +} // namespace ops +} // namespace tflite diff --git a/tensorflow/lite/kernels/squared_difference_test.cc b/tensorflow/lite/kernels/squared_difference_test.cc new file mode 100644 index 0000000000..32bcab3b87 --- /dev/null +++ b/tensorflow/lite/kernels/squared_difference_test.cc @@ -0,0 +1,157 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include "tensorflow/lite/interpreter.h" +#include "tensorflow/lite/kernels/register.h" +#include "tensorflow/lite/kernels/test_util.h" +#include "tensorflow/lite/model.h" + +namespace tflite { +namespace { + +using ::testing::ElementsAreArray; + +class BaseSquaredDifferenceOpModel : public SingleOpModel { + public: + BaseSquaredDifferenceOpModel(const TensorData& input1, + const TensorData& input2, + const TensorData& output) { + input1_ = AddInput(input1); + input2_ = AddInput(input2); + output_ = AddOutput(output); + SetBuiltinOp(BuiltinOperator_SQUARED_DIFFERENCE, + BuiltinOptions_SquaredDifferenceOptions, + CreateSquaredDifferenceOptions(builder_).Union()); + BuildInterpreter({GetShape(input1_), GetShape(input2_)}); + } + + int input1() { return input1_; } + int input2() { return input2_; } + + protected: + int input1_; + int input2_; + int output_; +}; + +class FloatSquaredDifferenceOpModel : public BaseSquaredDifferenceOpModel { + public: + using BaseSquaredDifferenceOpModel::BaseSquaredDifferenceOpModel; + + std::vector GetOutput() { return ExtractVector(output_); } +}; + +class IntegerSquaredDifferenceOpModel : public BaseSquaredDifferenceOpModel { + public: + using BaseSquaredDifferenceOpModel::BaseSquaredDifferenceOpModel; + + std::vector GetOutput() { return ExtractVector(output_); } +}; + +TEST(FloatSquaredDifferenceOpTest, FloatType_SameShape) { + FloatSquaredDifferenceOpModel m({TensorType_FLOAT32, {1, 2, 2, 1}}, + {TensorType_FLOAT32, {1, 2, 2, 1}}, + {TensorType_FLOAT32, {}}); + m.PopulateTensor(m.input1(), {-0.2, 0.2, -1.2, 0.8}); + m.PopulateTensor(m.input2(), {0.5, 0.2, -1.5, 0.5}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), + ElementsAreArray(ArrayFloatNear({0.49, 0.0, 0.09, 0.09}))); +} + +TEST(FloatSquaredDifferenceOpTest, FloatType_VariousInputShapes) { + std::vector> test_shapes = { + {6}, {2, 3}, {2, 1, 3}, {1, 3, 1, 2}}; + for (int i = 0; i < test_shapes.size(); ++i) { + FloatSquaredDifferenceOpModel m({TensorType_FLOAT32, test_shapes[i]}, + {TensorType_FLOAT32, test_shapes[i]}, + {TensorType_FLOAT32, {}}); + m.PopulateTensor(m.input1(), {-2.0, 0.2, 0.3, 0.8, 1.1, -2.0}); + m.PopulateTensor(m.input2(), {1.0, 0.2, 0.6, 0.4, -1.0, -0.0}); + m.Invoke(); + EXPECT_THAT( + m.GetOutput(), + ElementsAreArray(ArrayFloatNear({9.0, 0.0, 0.09, 0.16, 4.41, 4.0}))) + << "With shape number " << i; + } +} + +TEST(FloatSquaredDifferenceOpTest, FloatType_WithBroadcast) { + std::vector> test_shapes = { + {6}, {2, 3}, {2, 1, 3}, {1, 3, 1, 2}}; + for (int i = 0; i < test_shapes.size(); ++i) { + FloatSquaredDifferenceOpModel m( + {TensorType_FLOAT32, test_shapes[i]}, + {TensorType_FLOAT32, {}}, // always a scalar + {TensorType_FLOAT32, {}}); + m.PopulateTensor(m.input1(), {-0.2, 0.2, 0.5, 0.8, 0.11, 1.1}); + m.PopulateTensor(m.input2(), {0.1}); + m.Invoke(); + EXPECT_THAT( + m.GetOutput(), + ElementsAreArray(ArrayFloatNear({0.09, 0.01, 0.16, 0.49, 0.0001, 1.0}))) + << "With shape number " << i; + } +} + +TEST(IntegerSquaredDifferenceOpTest, IntegerType_SameShape) { + IntegerSquaredDifferenceOpModel m({TensorType_INT32, {1, 2, 2, 1}}, + {TensorType_INT32, {1, 2, 2, 1}}, + {TensorType_INT32, {}}); + m.PopulateTensor(m.input1(), {-2, 2, -15, 8}); + m.PopulateTensor(m.input2(), {5, -2, -3, 5}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({49, 16, 144, 9})); +} + +TEST(IntegerSquaredDifferenceOpTest, IntegerType_VariousInputShapes) { + std::vector> test_shapes = { + {6}, {2, 3}, {2, 1, 3}, {1, 3, 1, 2}}; + for (int i = 0; i < test_shapes.size(); ++i) { + IntegerSquaredDifferenceOpModel m({TensorType_INT32, test_shapes[i]}, + {TensorType_INT32, test_shapes[i]}, + {TensorType_INT32, {}}); + m.PopulateTensor(m.input1(), {-20, 2, 3, 8, 11, -20}); + m.PopulateTensor(m.input2(), {1, 2, 6, 5, -5, -20}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({441, 0, 9, 9, 256, 0})) + << "With shape number " << i; + } +} + +TEST(IntegerSquaredDifferenceOpTest, IntegerType_WithBroadcast) { + std::vector> test_shapes = { + {6}, {2, 3}, {2, 1, 3}, {1, 3, 1, 2}}; + for (int i = 0; i < test_shapes.size(); ++i) { + IntegerSquaredDifferenceOpModel m( + {TensorType_INT32, test_shapes[i]}, + {TensorType_INT32, {}}, // always a scalar + {TensorType_INT32, {}}); + m.PopulateTensor(m.input1(), {-20, 10, 7, 3, 1, 13}); + m.PopulateTensor(m.input2(), {3}); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({529, 49, 16, 0, 4, 100})) + << "With shape number " << i; + } +} + +} // namespace +} // namespace tflite + +int main(int argc, char** argv) { + ::tflite::LogToStderr(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tensorflow/lite/kernels/test_util.h b/tensorflow/lite/kernels/test_util.h index 43a5137a94..dadabb86ab 100644 --- a/tensorflow/lite/kernels/test_util.h +++ b/tensorflow/lite/kernels/test_util.h @@ -199,7 +199,7 @@ class SingleOpModel { for (const string& s : content) { buf.AddString(s.data(), s.length()); } - buf.WriteToTensor(tensor); + buf.WriteToTensor(tensor, /*new_shape=*/nullptr); } // Populate the tensor given its index. @@ -307,6 +307,7 @@ class SingleOpModel { if (is_quantized) { if (t.min != 0 || t.max != 0) { + // TODO(b/119422369): Handle signed int8 here. if (t.type == TensorType_UINT8) { std::tie(t.scale, t.zero_point) = QuantizationParams(t.min, t.max); diff --git a/tensorflow/lite/lib_package/create_ios_frameworks.sh b/tensorflow/lite/lib_package/create_ios_frameworks.sh index fa466ed5bc..7901655b7c 100755 --- a/tensorflow/lite/lib_package/create_ios_frameworks.sh +++ b/tensorflow/lite/lib_package/create_ios_frameworks.sh @@ -30,7 +30,7 @@ echo "Creating target Headers directories" mkdir -p $FW_DIR_TFLITE_HDRS echo "Headers, populating: TensorFlow Lite" -cd $TFLITE_DIR/../../.. +cd $TFLITE_DIR/../.. find tensorflow/lite -name '*.h' \ -not -path 'tensorflow/lite/tools/*' \ @@ -51,10 +51,10 @@ cd $FW_DIR_TFLITE_HDRS tar xf tmp.tar rm -f tmp.tar -cd $TFLITE_DIR/../../.. +cd $TFLITE_DIR/../.. echo "Generate master LICENSE file and copy to target" bazel build //tensorflow/tools/lib_package:clicenses_generate -cp $TFLITE_DIR/../../../bazel-genfiles/tensorflow/tools/lib_package/include/tensorflow/c/LICENSE \ +cp $TFLITE_DIR/../../bazel-genfiles/tensorflow/tools/lib_package/include/tensorflow/c/LICENSE \ $FW_DIR_TFLITE echo "Copying static libraries" diff --git a/tensorflow/lite/models/smartreply/demo/app/src/main/java/com/example/android/smartreply/SmartReplyClient.java b/tensorflow/lite/models/smartreply/demo/app/src/main/java/com/example/android/smartreply/SmartReplyClient.java index d5b1ac0ffb..fbd75051e7 100644 --- a/tensorflow/lite/models/smartreply/demo/app/src/main/java/com/example/android/smartreply/SmartReplyClient.java +++ b/tensorflow/lite/models/smartreply/demo/app/src/main/java/com/example/android/smartreply/SmartReplyClient.java @@ -90,29 +90,26 @@ public class SmartReplyClient implements AutoCloseable { } private MappedByteBuffer loadModelFile() throws IOException { - AssetFileDescriptor fileDescriptor = context.getAssets().openFd(MODEL_PATH); - FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor()); - try { + try (AssetFileDescriptor fileDescriptor = context.getAssets().openFd(MODEL_PATH); + FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor())) { FileChannel fileChannel = inputStream.getChannel(); long startOffset = fileDescriptor.getStartOffset(); long declaredLength = fileDescriptor.getDeclaredLength(); return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength); - } finally { - inputStream.close(); } } private String[] loadBackoffList() throws IOException { List labelList = new ArrayList(); - BufferedReader reader = - new BufferedReader(new InputStreamReader(context.getAssets().open(BACKOFF_PATH))); - String line; - while ((line = reader.readLine()) != null) { - if (!line.isEmpty()) { - labelList.add(line); + try (BufferedReader reader = + new BufferedReader(new InputStreamReader(context.getAssets().open(BACKOFF_PATH)))) { + String line; + while ((line = reader.readLine()) != null) { + if (!line.isEmpty()) { + labelList.add(line); + } } } - reader.close(); String[] ans = new String[labelList.size()]; labelList.toArray(ans); return ans; diff --git a/tensorflow/lite/models/smartreply/ops/normalize.cc b/tensorflow/lite/models/smartreply/ops/normalize.cc index 8480260f27..3cb11cc055 100644 --- a/tensorflow/lite/models/smartreply/ops/normalize.cc +++ b/tensorflow/lite/models/smartreply/ops/normalize.cc @@ -92,7 +92,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { tflite::DynamicBuffer buf; buf.AddString(result.data(), result.length()); - buf.WriteToTensor(GetOutput(context, node, 0)); + buf.WriteToTensorAsVector(GetOutput(context, node, 0)); return kTfLiteOk; } diff --git a/tensorflow/lite/models/smartreply/predictor.cc b/tensorflow/lite/models/smartreply/predictor.cc index 7db2502977..59bf4a3cf1 100644 --- a/tensorflow/lite/models/smartreply/predictor.cc +++ b/tensorflow/lite/models/smartreply/predictor.cc @@ -49,7 +49,7 @@ void ExecuteTfLite(const std::string& sentence, TfLiteTensor* input = interpreter->tensor(interpreter->inputs()[0]); tflite::DynamicBuffer buf; buf.AddString(sentence.data(), sentence.length()); - buf.WriteToTensor(input); + buf.WriteToTensorAsVector(input); interpreter->AllocateTensors(); interpreter->Invoke(); diff --git a/tensorflow/lite/nnapi_delegate.cc b/tensorflow/lite/nnapi_delegate.cc index 950bdb3942..26d75696a1 100644 --- a/tensorflow/lite/nnapi_delegate.cc +++ b/tensorflow/lite/nnapi_delegate.cc @@ -140,13 +140,13 @@ NNAPIDelegate::~NNAPIDelegate() { // ANeuralNetworksShutdown(); } -// Adds the tensors of the interpreter to the NN API model. -TfLiteStatus addTensorOperands(tflite::Interpreter* interpreter, +// Adds the tensors of the subgraph to the NN API model. +TfLiteStatus addTensorOperands(tflite::Subgraph* subgraph, ANeuralNetworksModel* nn_model, uint32_t* no_of_operands_added, std::vector* nnapi_ids) { uint32_t next_id = 0; - for (size_t i = 0; i < interpreter->tensors_size(); i++) { + for (size_t i = 0; i < subgraph->tensors_size(); i++) { // Skip temporaries and RNN back-edges. if ((*nnapi_ids)[i] == kOperandNotNeeded) continue; @@ -156,7 +156,7 @@ TfLiteStatus addTensorOperands(tflite::Interpreter* interpreter, // NNAPI requires 32-bit float scale to be zero, tflite doesn't care float scale = 0.0f; int32_t zeroPoint = 0; - TfLiteTensor* tensor = interpreter->tensor(i); + TfLiteTensor* tensor = subgraph->tensor(i); switch (tensor->type) { case kTfLiteNoType: // Tensors added during initialization of Ops don't have a type yet and @@ -240,12 +240,12 @@ void MapAndAddTensorIds(const int* from_ids_buf, size_t from_ids_count, // Adds the operations and their parameters to the NN API model. // 'next-id' is the operand ID of the next operand of the model. TfLiteStatus AddOpsAndParams( - tflite::Interpreter* interpreter, ANeuralNetworksModel* nn_model, + tflite::Subgraph* subgraph, ANeuralNetworksModel* nn_model, uint32_t next_id, std::vector* model_state_inputs, std::vector* model_state_outputs, const std::vector& tensor_id_to_nnapi_id) { - for (size_t i = 0; i < interpreter->nodes_size(); i++) { - const auto* node_and_registration = interpreter->node_and_registration(i); + for (size_t i = 0; i < subgraph->nodes_size(); i++) { + const auto* node_and_registration = subgraph->node_and_registration(i); const TfLiteNode& node = node_and_registration->first; const TfLiteRegistration& registration = node_and_registration->second; tflite::BuiltinOperator builtin = @@ -291,9 +291,9 @@ TfLiteStatus AddOpsAndParams( // For each state_out tensor, a corresponding state_in operand needs to be // created for NNAPI. auto duplicate_state_tensor_float32 = - [interpreter, &nn_model, &next_id, &augmented_inputs, - &model_state_inputs, &model_state_outputs](int tensor_id) { - const TfLiteTensor* tensor = interpreter->tensor(tensor_id); + [subgraph, &nn_model, &next_id, &augmented_inputs, &model_state_inputs, + &model_state_outputs](int tensor_id) { + const TfLiteTensor* tensor = subgraph->tensor(tensor_id); ANeuralNetworksOperandType operand_type{ ANEURALNETWORKS_TENSOR_FLOAT32, static_cast(tensor->dims->size), @@ -388,11 +388,11 @@ TfLiteStatus AddOpsAndParams( }; // LSTM in NNAPI requires scratch tensor as an output operand. - auto add_lstm_scratch_tensor_float32 = [interpreter, &node, &nn_model, + auto add_lstm_scratch_tensor_float32 = [subgraph, &node, &nn_model, &next_id, &augmented_outputs]() { if (node.temporaries->size == 0) return; int scratch_buffer_index = node.temporaries->data[0]; - const TfLiteTensor* tensor = interpreter->tensor(scratch_buffer_index); + const TfLiteTensor* tensor = subgraph->tensor(scratch_buffer_index); ANeuralNetworksOperandType operand_type{ ANEURALNETWORKS_TENSOR_FLOAT32, static_cast(tensor->dims->size), @@ -584,7 +584,7 @@ TfLiteStatus AddOpsAndParams( // The permutation input tensor value dictates the output dimensions. // TODO(b/110888333): Support dynamically-sized tensors in delegates. if ((node.inputs->size > 1) && - (interpreter->tensor(node.inputs->data[1])->allocation_type != + (subgraph->tensor(node.inputs->data[1])->allocation_type != kTfLiteMmapRo)) { logError("NNAPI does not yet support dynamic tensors."); return kTfLiteError; @@ -601,14 +601,13 @@ TfLiteStatus AddOpsAndParams( return kTfLiteError; } if ((node.inputs->size > 0) && - (interpreter->tensor(node.inputs->data[0])->dims->size != 4)) { + (subgraph->tensor(node.inputs->data[0])->dims->size != 4)) { logError("NNAPI only supports input rank 4 for L2Normalization"); return kTfLiteError; } break; case tflite::BuiltinOperator_HASHTABLE_LOOKUP: - if (interpreter->tensor(node.outputs->data[0])->type != - kTfLiteFloat32) { + if (subgraph->tensor(node.outputs->data[0])->type != kTfLiteFloat32) { logError("NNAPI only support HASHTABLE_LOOKUP with float32 output", builtin); return kTfLiteError; @@ -682,6 +681,11 @@ TfLiteStatus AddOpsAndParams( case tflite::BuiltinOperator_FILL: case tflite::BuiltinOperator_FLOOR_MOD: case tflite::BuiltinOperator_RANGE: + case tflite::BuiltinOperator_LEAKY_RELU: + case tflite::BuiltinOperator_SQUARED_DIFFERENCE: + case tflite::BuiltinOperator_MIRROR_PAD: + case tflite::BuiltinOperator_ABS: + case tflite::BuiltinOperator_SPLIT_V: logError("Op code %d is currently not delegated to NNAPI", builtin); return kTfLiteError; break; @@ -706,7 +710,7 @@ TfLiteStatus AddOpsAndParams( return kTfLiteOk; } -TfLiteStatus NNAPIDelegate::BuildGraph(Interpreter* interpreter) { +TfLiteStatus NNAPIDelegate::BuildGraph(Subgraph* subgraph) { if (nn_model_ && nn_compiled_model_) return model_status_; // TODO(aselle): This is not correct. need to handle resize invalidation. @@ -718,7 +722,7 @@ TfLiteStatus NNAPIDelegate::BuildGraph(Interpreter* interpreter) { // inputs and outputs and mark the mapping in tensor_id_to_nnapi_id with // kOperandIdNotSet. addTensorOperands will replace those with the // corresponding NNAPI operand ids and skip kOperandNotNeeded entries. - std::vector tensor_id_to_nnapi_id(interpreter->tensors_size(), + std::vector tensor_id_to_nnapi_id(subgraph->tensors_size(), kOperandNotNeeded); auto set_ids_to_not_set = [&tensor_id_to_nnapi_id](const int* buf, size_t count) { @@ -729,35 +733,31 @@ TfLiteStatus NNAPIDelegate::BuildGraph(Interpreter* interpreter) { } } }; - for (size_t i = 0; i < interpreter->nodes_size(); i++) { - const auto* node_and_registration = interpreter->node_and_registration(i); + for (size_t i = 0; i < subgraph->nodes_size(); i++) { + const auto* node_and_registration = subgraph->node_and_registration(i); const TfLiteNode& node = node_and_registration->first; set_ids_to_not_set(node.inputs->data, node.inputs->size); set_ids_to_not_set(node.outputs->data, node.outputs->size); } - set_ids_to_not_set(interpreter->inputs().data(), - interpreter->inputs().size()); - set_ids_to_not_set(interpreter->outputs().data(), - interpreter->outputs().size()); + set_ids_to_not_set(subgraph->inputs().data(), subgraph->inputs().size()); + set_ids_to_not_set(subgraph->outputs().data(), subgraph->outputs().size()); uint32_t next_id = 0; RETURN_ERROR_IF_TFLITE_FAILED(addTensorOperands( - interpreter, nn_model_, &next_id, &tensor_id_to_nnapi_id)); + subgraph, nn_model_, &next_id, &tensor_id_to_nnapi_id)); RETURN_ERROR_IF_TFLITE_FAILED( - AddOpsAndParams(interpreter, nn_model_, next_id, &model_states_inputs_, + AddOpsAndParams(subgraph, nn_model_, next_id, &model_states_inputs_, &model_states_outputs_, tensor_id_to_nnapi_id)); std::vector augmented_inputs; - MapAndAddTensorIds(interpreter->inputs().data(), - interpreter->inputs().size(), &augmented_inputs, - tensor_id_to_nnapi_id); + MapAndAddTensorIds(subgraph->inputs().data(), subgraph->inputs().size(), + &augmented_inputs, tensor_id_to_nnapi_id); augmented_inputs.insert(augmented_inputs.end(), model_states_inputs_.begin(), model_states_inputs_.end()); std::vector augmented_outputs; - MapAndAddTensorIds(interpreter->outputs().data(), - interpreter->outputs().size(), &augmented_outputs, - tensor_id_to_nnapi_id); + MapAndAddTensorIds(subgraph->outputs().data(), subgraph->outputs().size(), + &augmented_outputs, tensor_id_to_nnapi_id); MapAndAddTensorIds(model_states_outputs_.data(), model_states_outputs_.size(), &augmented_outputs, tensor_id_to_nnapi_id); @@ -770,7 +770,7 @@ TfLiteStatus NNAPIDelegate::BuildGraph(Interpreter* interpreter) { if (GetAndroidSdkVersionCached() >= 28) { CHECK_NN(ANeuralNetworksModel_relaxComputationFloat32toFloat16( - nn_model_, interpreter->GetAllowFp16PrecisionForFp32())); + nn_model_, subgraph->GetAllowFp16PrecisionForFp32())); } CHECK_NN(ANeuralNetworksModel_finish(nn_model_)); } @@ -781,9 +781,9 @@ TfLiteStatus NNAPIDelegate::BuildGraph(Interpreter* interpreter) { return kTfLiteOk; } -TfLiteStatus NNAPIDelegate::Invoke(Interpreter* interpreter) { +TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { if (!nn_model_) { - model_status_ = BuildGraph(interpreter); + model_status_ = BuildGraph(subgraph); if (model_status_ != kTfLiteOk) { logError("Failed to build graph for NNAPI"); } @@ -796,19 +796,19 @@ TfLiteStatus NNAPIDelegate::Invoke(Interpreter* interpreter) { CHECK_NN(ANeuralNetworksExecution_create(nn_compiled_model_, &execution)); // Currently perform deep copy of input buffer - for (size_t i = 0; i < interpreter->inputs().size(); i++) { - int input = interpreter->inputs()[i]; + for (size_t i = 0; i < subgraph->inputs().size(); i++) { + int input = subgraph->inputs()[i]; // TODO(aselle): Is this what we want or do we want input instead? // TODO(aselle): This should be called setInputValue maybe to be cons. - TfLiteTensor* tensor = interpreter->tensor(input); + TfLiteTensor* tensor = subgraph->tensor(input); CHECK_NN(ANeuralNetworksExecution_setInput( execution, i, nullptr, tensor->data.raw, tensor->bytes)); } // Tell nn api where to place final data. - for (size_t i = 0; i < interpreter->outputs().size(); i++) { - int output = interpreter->outputs()[i]; - TfLiteTensor* tensor = interpreter->tensor(output); + for (size_t i = 0; i < subgraph->outputs().size(); i++) { + int output = subgraph->outputs()[i]; + TfLiteTensor* tensor = subgraph->tensor(output); CHECK_NN(ANeuralNetworksExecution_setOutput( execution, i, nullptr, tensor->data.raw, tensor->bytes)); } @@ -817,16 +817,16 @@ TfLiteStatus NNAPIDelegate::Invoke(Interpreter* interpreter) { // current invocation. for (size_t i = 0; i < model_states_outputs_.size(); i++) { int state_tensor_idx = model_states_outputs_[i]; - TfLiteTensor* tensor = interpreter->tensor(state_tensor_idx); + TfLiteTensor* tensor = subgraph->tensor(state_tensor_idx); // Here we are using a deep copy for state_in tensors so that we are not // reading and writing into the same buffer during a invocation. // TODO(miaowang): using double shared buffer to minimize the copies. CHECK_NN(ANeuralNetworksExecution_setInput( - execution, i + interpreter->inputs().size(), nullptr, tensor->data.raw, + execution, i + subgraph->inputs().size(), nullptr, tensor->data.raw, tensor->bytes)); // Tell NNAPI where to output the state_out. CHECK_NN(ANeuralNetworksExecution_setOutput( - execution, i + interpreter->outputs().size(), nullptr, tensor->data.raw, + execution, i + subgraph->outputs().size(), nullptr, tensor->data.raw, tensor->bytes)); } @@ -839,9 +839,9 @@ TfLiteStatus NNAPIDelegate::Invoke(Interpreter* interpreter) { #if 0 printf("From the NN API:\n"); - TfLiteTensor* tensor = interpreter->tensor(interpreter->outputs()[0]); + TfLiteTensor* tensor = subgraph->tensor(subgraph->outputs()[0]); if (float* data = - interpreter->typed_tensor(interpreter->outputs()[0])) { + subgraph->typed_tensor(subgraph->outputs()[0])) { size_t num = tensor->bytes / sizeof(float); for (float* p = data; p < data + num; p++) { printf(" %f", *p); diff --git a/tensorflow/lite/nnapi_delegate.h b/tensorflow/lite/nnapi_delegate.h index 63b408c141..b4f8e4ecf3 100644 --- a/tensorflow/lite/nnapi_delegate.h +++ b/tensorflow/lite/nnapi_delegate.h @@ -18,6 +18,7 @@ limitations under the License. #include "tensorflow/lite/allocation.h" #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/core/subgraph.h" #include "tensorflow/lite/interpreter.h" class ANeuralNetworksModel; @@ -50,10 +51,10 @@ class NNAPIDelegate { ~NNAPIDelegate(); // Convert a tflite graph to NNAPI - TfLiteStatus BuildGraph(Interpreter* interpreter); + TfLiteStatus BuildGraph(Subgraph* subgraph); // Run - TfLiteStatus Invoke(Interpreter* interpreter); + TfLiteStatus Invoke(Subgraph* subgraph); // Whether the current platform supports NNAPI delegation. static bool IsSupported(); diff --git a/tensorflow/lite/nnapi_delegate_disabled.cc b/tensorflow/lite/nnapi_delegate_disabled.cc index 44dc21f1b6..a8f2c0bfe3 100644 --- a/tensorflow/lite/nnapi_delegate_disabled.cc +++ b/tensorflow/lite/nnapi_delegate_disabled.cc @@ -35,13 +35,11 @@ NNAPIDelegate::~NNAPIDelegate() { #undef UNUSED_MEMBER } -TfLiteStatus NNAPIDelegate::BuildGraph(Interpreter* interpreter) { +TfLiteStatus NNAPIDelegate::BuildGraph(Subgraph* subgraph) { return kTfLiteError; } -TfLiteStatus NNAPIDelegate::Invoke(Interpreter* interpreter) { - return kTfLiteError; -} +TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { return kTfLiteError; } bool NNAPIDelegate::IsSupported() { return false; } diff --git a/tensorflow/lite/optional_debug_tools.cc b/tensorflow/lite/optional_debug_tools.cc index 5ee1cf6d33..1113bf01b1 100644 --- a/tensorflow/lite/optional_debug_tools.cc +++ b/tensorflow/lite/optional_debug_tools.cc @@ -44,6 +44,8 @@ const char* TensorTypeName(TfLiteType type) { return "kTfLiteInt32"; case kTfLiteUInt8: return "kTfLiteUInt8"; + case kTfLiteInt8: + return "kTfLiteInt8"; case kTfLiteInt64: return "kTfLiteInt64"; case kTfLiteString: diff --git a/tensorflow/lite/python/BUILD b/tensorflow/lite/python/BUILD index 017dd72f78..acf827892b 100644 --- a/tensorflow/lite/python/BUILD +++ b/tensorflow/lite/python/BUILD @@ -89,6 +89,7 @@ py_library( srcs_version = "PY2AND3", deps = [ "//tensorflow/lite/toco:toco_flags_proto_py", + "//tensorflow/python:dtypes", ], ) @@ -103,6 +104,7 @@ py_library( "//tensorflow/lite/toco:toco_flags_proto_py", "//tensorflow/lite/toco/python:tensorflow_wrap_toco", "//tensorflow/lite/toco/python:toco_from_protos", + "//tensorflow/python:dtypes", "//tensorflow/python:platform", ], ) diff --git a/tensorflow/lite/python/convert.py b/tensorflow/lite/python/convert.py index 9991fb2a73..563312e027 100644 --- a/tensorflow/lite/python/convert.py +++ b/tensorflow/lite/python/convert.py @@ -28,6 +28,8 @@ import tempfile as _tempfile from tensorflow.lite.python import lite_constants from tensorflow.lite.toco import model_flags_pb2 as _model_flags_pb2 from tensorflow.lite.toco import toco_flags_pb2 as _toco_flags_pb2 +from tensorflow.lite.toco import types_pb2 as _types_pb2 +from tensorflow.python.framework import dtypes from tensorflow.python.platform import resource_loader as _resource_loader from tensorflow.python.util import deprecation from tensorflow.python.util.lazy_loader import LazyLoader @@ -53,6 +55,18 @@ else: if _toco_from_proto_bin and not _os.path.exists(_toco_from_proto_bin): _toco_from_proto_bin = "toco_from_protos" + +# Map of tf.dtypes to TFLite types_flag_pb2. +_MAP_TF_TO_TFLITE_TYPES = { + dtypes.float32: _types_pb2.FLOAT, + dtypes.int32: _types_pb2.INT32, + dtypes.int64: _types_pb2.INT64, + dtypes.string: _types_pb2.STRING, + dtypes.uint8: _types_pb2.QUANTIZED_UINT8, + dtypes.complex64: _types_pb2.COMPLEX64 +} + + def _try_convert_to_unicode(output): if output is None: return u"" @@ -65,6 +79,24 @@ def _try_convert_to_unicode(output): return output +def convert_dtype_to_tflite_type(tf_dtype): + """Converts tf.dtype to TFLite proto type. + + Args: + tf_dtype: tf.dtype + + Raises: + ValueError: Unsupported tf.dtype. + + Returns: + types_flag_pb2. + """ + result = _MAP_TF_TO_TFLITE_TYPES.get(tf_dtype) + if result is None: + raise ValueError("Unsupported tf.dtype {0}".format(tf_dtype)) + return result + + class OpsSet(enum.Enum): """Enum class defining the sets of ops available to generate TFLite models. @@ -214,10 +246,10 @@ def build_toco_convert_protos(input_tensors, `foo.get_shape()` and `foo.dtype`. output_tensors: List of output tensors (only .name is used from this). inference_type: Target data type of real-number arrays in the output file. - Must be `{FLOAT, QUANTIZED_UINT8}`. (default FLOAT) + Must be `{tf.float32, tf.uint8}`. (default tf.float32) inference_input_type: Target data type of real-number input arrays. Allows for a different type for input arrays in the case of quantization. - Must be `{FLOAT, QUANTIZED_UINT8}`. (default `inference_type`) + Must be `{tf.float32, tf.uint8}`. (default `inference_type`) input_format: Type of data to read Currently must be `{TENSORFLOW_GRAPHDEF}`. (default TENSORFLOW_GRAPHDEF) input_shapes: Input array shape. It needs to be a list of the same length @@ -269,16 +301,19 @@ def build_toco_convert_protos(input_tensors, process. Raises: - ValueError: If the input tensor type is unknown + ValueError: + If the input tensor type is unknown + Missing mean_values or std_dev_values RuntimeError: If TOCO fails to convert (in which case the runtime error's error text will contain the TOCO error log) """ toco = _toco_flags_pb2.TocoFlags() toco.input_format = input_format toco.output_format = output_format - toco.inference_type = inference_type + toco.inference_type = convert_dtype_to_tflite_type(inference_type) if inference_input_type: - toco.inference_input_type = inference_input_type + toco.inference_input_type = convert_dtype_to_tflite_type( + inference_input_type) else: toco.inference_input_type = toco.inference_type toco.drop_control_dependency = drop_control_dependency @@ -302,9 +337,14 @@ def build_toco_convert_protos(input_tensors, model.change_concat_input_ranges = change_concat_input_ranges for idx, input_tensor in enumerate(input_tensors): input_array = model.input_arrays.add() - if toco.inference_input_type == lite_constants.QUANTIZED_UINT8: - input_array.mean_value, input_array.std_value = quantized_input_stats[idx] input_array.name = tensor_name(input_tensor) + input_array.data_type = convert_dtype_to_tflite_type(input_tensor.dtype) + + if toco.inference_input_type == _types_pb2.QUANTIZED_UINT8: + if not quantized_input_stats: + raise ValueError("std_dev and mean must be defined when " + "inference_input_type is QUANTIZED_UINT8.") + input_array.mean_value, input_array.std_value = quantized_input_stats[idx] if input_shapes is None: shape = input_tensor.get_shape() else: @@ -352,7 +392,11 @@ def toco_convert_graph_def(input_data, input_arrays_with_shape, output_arrays, for idx, (name, shape) in enumerate(input_arrays_with_shape): input_array = model_flags.input_arrays.add() - if kwargs["inference_type"] == lite_constants.QUANTIZED_UINT8: + if toco_flags.inference_input_type == _types_pb2.QUANTIZED_UINT8: + if (("quantized_input_stats" not in kwargs) or + (not kwargs["quantized_input_stats"])): + raise ValueError("std_dev and mean must be defined when " + "inference_input_type is QUANTIZED_UINT8.") input_array.mean_value, input_array.std_value = kwargs[ "quantized_input_stats"][idx] input_array.name = name diff --git a/tensorflow/lite/python/convert_saved_model.py b/tensorflow/lite/python/convert_saved_model.py index 3f54d2559c..f8d986b746 100644 --- a/tensorflow/lite/python/convert_saved_model.py +++ b/tensorflow/lite/python/convert_saved_model.py @@ -197,12 +197,27 @@ def set_tensor_shapes(tensors, shapes): tensors: TensorFlow ops.Tensor. shapes: Dict of strings representing input tensor names to list of integers representing input shapes (e.g., {"foo": : [1, 16, 16, 3]}). + + Raises: + ValueError: + `shapes` contains an invalid tensor. + `shapes` contains an invalid shape for a valid tensor. """ if shapes: - for tensor in tensors: - shape = shapes.get(tensor_name(tensor)) + tensor_names_to_tensor = {tensor_name(tensor): tensor for tensor in tensors} + for name, shape in shapes.items(): + if name not in tensor_names_to_tensor: + raise ValueError("Invalid tensor \'{}\' found in tensor shapes " + "map.".format(name)) if shape is not None: - tensor.set_shape(shape) + tensor = tensor_names_to_tensor[name] + try: + tensor.set_shape(shape) + except ValueError as error: + message = ("The shape of tensor '{0}' cannot be changed from {1} to " + "{2}. {3}".format(name, tensor.get_shape(), shape, + str(error))) + raise ValueError(message) def freeze_saved_model(saved_model_dir, input_arrays, input_shapes, diff --git a/tensorflow/lite/python/convert_saved_model_test.py b/tensorflow/lite/python/convert_saved_model_test.py index dff582f1a1..76113853ca 100644 --- a/tensorflow/lite/python/convert_saved_model_test.py +++ b/tensorflow/lite/python/convert_saved_model_test.py @@ -75,12 +75,30 @@ class TensorFunctionsTest(test_util.TensorFlowTestCase): convert_saved_model.set_tensor_shapes([tensor], {"Placeholder": [1, 3, 5]}) self.assertEqual([1, 3, 5], tensor.shape.as_list()) - def testSetTensorShapeInvalid(self): + def testSetTensorShapeArrayInvalid(self): + # Tests set_tensor_shape where the tensor name passed in doesn't exist. tensor = array_ops.placeholder(shape=[None, 3, 5], dtype=dtypes.float32) self.assertEqual([None, 3, 5], tensor.shape.as_list()) - convert_saved_model.set_tensor_shapes([tensor], - {"invalid-input": [5, 3, 5]}) + with self.assertRaises(ValueError) as error: + convert_saved_model.set_tensor_shapes([tensor], + {"invalid-input": [5, 3, 5]}) + self.assertEqual( + "Invalid tensor 'invalid-input' found in tensor shapes map.", + str(error.exception)) + self.assertEqual([None, 3, 5], tensor.shape.as_list()) + + def testSetTensorShapeDimensionInvalid(self): + # Tests set_tensor_shape where the shape passed in is incompatiable. + tensor = array_ops.placeholder(shape=[None, 3, 5], dtype=dtypes.float32) + self.assertEqual([None, 3, 5], tensor.shape.as_list()) + + with self.assertRaises(ValueError) as error: + convert_saved_model.set_tensor_shapes([tensor], + {"Placeholder": [1, 5, 5]}) + self.assertIn( + "The shape of tensor 'Placeholder' cannot be changed from " + "(?, 3, 5) to [1, 5, 5].", str(error.exception)) self.assertEqual([None, 3, 5], tensor.shape.as_list()) def testSetTensorShapeEmpty(self): diff --git a/tensorflow/lite/python/convert_test.py b/tensorflow/lite/python/convert_test.py index 7a0bce921b..2a6f1f634f 100644 --- a/tensorflow/lite/python/convert_test.py +++ b/tensorflow/lite/python/convert_test.py @@ -23,6 +23,7 @@ from tensorflow.lite.python import convert from tensorflow.lite.python import lite_constants from tensorflow.lite.python import op_hint from tensorflow.lite.python.interpreter import Interpreter +from tensorflow.lite.toco import types_pb2 as _types_pb2 from tensorflow.python.client import session from tensorflow.python.framework import dtypes from tensorflow.python.framework import test_util @@ -65,6 +66,21 @@ class ConvertTest(test_util.TensorFlowTestCase): quantized_input_stats=[(0., 1.)]) self.assertTrue(tflite_model) + def testQuantizationInvalid(self): + in_tensor = array_ops.placeholder( + shape=[1, 16, 16, 3], dtype=dtypes.float32) + out_tensor = array_ops.fake_quant_with_min_max_args( + in_tensor + in_tensor, min=0., max=1.) + sess = session.Session() + + with self.assertRaises(ValueError) as error: + convert.toco_convert( + sess.graph_def, [in_tensor], [out_tensor], + inference_type=lite_constants.QUANTIZED_UINT8) + self.assertEqual( + "std_dev and mean must be defined when inference_input_type is " + "QUANTIZED_UINT8.", str(error.exception)) + def testGraphDefBasic(self): in_tensor = array_ops.placeholder( shape=[1, 16, 16, 3], dtype=dtypes.float32, name="input") @@ -138,6 +154,27 @@ class ConvertTest(test_util.TensorFlowTestCase): self.assertTrue(([1, 16, 16, 3] == output_details[0]["shape"]).all()) self.assertTrue(output_details[0]["quantization"][0] > 0) # scale + def testGraphDefQuantizationInvalid(self): + in_tensor_1 = array_ops.placeholder( + shape=[1, 16, 16, 3], dtype=dtypes.float32, name="inputA") + in_tensor_2 = array_ops.placeholder( + shape=[1, 16, 16, 3], dtype=dtypes.float32, name="inputB") + _ = array_ops.fake_quant_with_min_max_args( + in_tensor_1 + in_tensor_2, min=0., max=1., name="output") + sess = session.Session() + + input_arrays_map = [("inputA", [1, 16, 16, 3]), ("inputB", [1, 16, 16, 3])] + output_arrays = ["output"] + with self.assertRaises(ValueError) as error: + convert.toco_convert_graph_def( + sess.graph_def, + input_arrays_map, + output_arrays, + inference_type=lite_constants.QUANTIZED_UINT8) + self.assertEqual( + "std_dev and mean must be defined when inference_input_type is " + "QUANTIZED_UINT8.", str(error.exception)) + class ConvertTestOpHint(test_util.TensorFlowTestCase): """Test the hint to stub functionality.""" @@ -329,6 +366,27 @@ class ConvertTestOpHint(test_util.TensorFlowTestCase): output_nodes=[op_hint._tensor_name_base(output.name)]), set(["agg", "Const", "Identity"])) + def testConvertDtype(self): + self.assertEqual( + convert.convert_dtype_to_tflite_type(lite_constants.FLOAT), + _types_pb2.FLOAT) + self.assertEqual( + convert.convert_dtype_to_tflite_type(dtypes.float32), _types_pb2.FLOAT) + self.assertEqual( + convert.convert_dtype_to_tflite_type(dtypes.int32), _types_pb2.INT32) + self.assertEqual( + convert.convert_dtype_to_tflite_type(dtypes.int64), _types_pb2.INT64) + self.assertEqual( + convert.convert_dtype_to_tflite_type(dtypes.string), _types_pb2.STRING) + self.assertEqual( + convert.convert_dtype_to_tflite_type(dtypes.uint8), + _types_pb2.QUANTIZED_UINT8) + self.assertEqual( + convert.convert_dtype_to_tflite_type(dtypes.complex64), + _types_pb2.COMPLEX64) + with self.assertRaises(ValueError): + convert.convert_dtype_to_tflite_type(dtypes.bool) + if __name__ == "__main__": test.main() diff --git a/tensorflow/lite/python/interpreter_wrapper/interpreter_wrapper.cc b/tensorflow/lite/python/interpreter_wrapper/interpreter_wrapper.cc index e71752fe63..d14af439ec 100644 --- a/tensorflow/lite/python/interpreter_wrapper/interpreter_wrapper.cc +++ b/tensorflow/lite/python/interpreter_wrapper/interpreter_wrapper.cc @@ -124,6 +124,8 @@ int TfLiteTypeToPyArrayType(TfLiteType tf_lite_type) { return NPY_INT16; case kTfLiteUInt8: return NPY_UINT8; + case kTfLiteInt8: + return NPY_INT8; case kTfLiteInt64: return NPY_INT64; case kTfLiteString: @@ -150,6 +152,8 @@ TfLiteType TfLiteTypeFromPyArray(PyArrayObject* array) { return kTfLiteInt16; case NPY_UINT8: return kTfLiteUInt8; + case NPY_INT8: + return kTfLiteInt8; case NPY_INT64: return kTfLiteInt64; case NPY_BOOL: diff --git a/tensorflow/lite/python/lite.py b/tensorflow/lite/python/lite.py index 5810553da2..1b20ff2f92 100644 --- a/tensorflow/lite/python/lite.py +++ b/tensorflow/lite/python/lite.py @@ -25,8 +25,6 @@ EXPERIMENTAL: APIs here are unstable and likely to change without notice. @@convert_op_hints_to_stubs @@build_toco_convert_protos -@@FLOAT -@@QUANTIZED_UINT8 @@TFLITE @@GRAPHVIZ_DOT @@ -78,10 +76,10 @@ class TFLiteConverter(object): Attributes: inference_type: Target data type of real-number arrays in the output file. - Must be `{FLOAT, QUANTIZED_UINT8}`. (default FLOAT) + Must be `{tf.float32, tf.uint8}`. (default tf.float32) inference_input_type: Target data type of real-number input arrays. Allows for a different type for input arrays in the case of quantization. - Must be `{FLOAT, QUANTIZED_UINT8}`. (default `inference_type`) + Must be `{tf.float32, tf.uint8}`. (default `inference_type`) output_format: Output file format. Currently must be `{TFLITE, GRAPHVIZ_DOT}`. (default TFLITE) quantized_input_stats: Dict of strings representing input tensor names @@ -402,15 +400,16 @@ class TFLiteConverter(object): # Checks dimensions in input tensor. if self._has_valid_tensors(): for tensor in self._input_tensors: - if not tensor.get_shape(): + shape = tensor.get_shape() + if not shape or not shape.as_list(): raise ValueError("Provide an input shape for input array " "'{0}'.".format(_tensor_name(tensor))) - shape = tensor.get_shape().as_list() - if None in shape[1:]: + shape_list = shape.as_list() + if None in shape_list[1:]: raise ValueError( "None is only supported in the 1st dimension. Tensor '{0}' has " - "invalid shape '{1}'.".format(_tensor_name(tensor), shape)) - elif shape[0] is None: + "invalid shape '{1}'.".format(_tensor_name(tensor), shape_list)) + elif shape_list[0] is None: self._set_batch_size(batch_size=1) # Get quantization stats. Ensures there is one stat per name if the stats diff --git a/tensorflow/lite/python/lite_constants.py b/tensorflow/lite/python/lite_constants.py index fdefc5e6cf..f5d6d10379 100644 --- a/tensorflow/lite/python/lite_constants.py +++ b/tensorflow/lite/python/lite_constants.py @@ -19,26 +19,25 @@ from __future__ import division from __future__ import print_function from tensorflow.lite.toco import toco_flags_pb2 as _toco_flags_pb2 -from tensorflow.lite.toco import types_pb2 as _types_pb2 +from tensorflow.python.framework import dtypes from tensorflow.python.util.all_util import remove_undocumented from tensorflow.python.util.tf_export import tf_export as _tf_export -# Enum types from the protobuf promoted to the API -FLOAT = _types_pb2.FLOAT -INT32 = _types_pb2.INT32 -INT64 = _types_pb2.INT64 -STRING = _types_pb2.STRING -QUANTIZED_UINT8 = _types_pb2.QUANTIZED_UINT8 -COMPLEX64 = _types_pb2.COMPLEX64 +FLOAT = dtypes.float32 +INT32 = dtypes.int32 +INT64 = dtypes.int64 +STRING = dtypes.string +QUANTIZED_UINT8 = dtypes.uint8 +COMPLEX64 = dtypes.complex64 TENSORFLOW_GRAPHDEF = _toco_flags_pb2.TENSORFLOW_GRAPHDEF TFLITE = _toco_flags_pb2.TFLITE GRAPHVIZ_DOT = _toco_flags_pb2.GRAPHVIZ_DOT -_tf_export("lite.constants.FLOAT").export_constant(__name__, "FLOAT") -_tf_export("lite.constants.INT32").export_constant(__name__, "INT32") -_tf_export("lite.constants.INT64").export_constant(__name__, "INT64") -_tf_export("lite.constants.STRING").export_constant(__name__, "STRING") -_tf_export("lite.constants.QUANTIZED_UINT8").export_constant( +_tf_export(v1=["lite.constants.FLOAT"]).export_constant(__name__, "FLOAT") +_tf_export(v1=["lite.constants.INT32"]).export_constant(__name__, "INT32") +_tf_export(v1=["lite.constants.INT64"]).export_constant(__name__, "INT64") +_tf_export(v1=["lite.constants.STRING"]).export_constant(__name__, "STRING") +_tf_export(v1=["lite.constants.QUANTIZED_UINT8"]).export_constant( __name__, "QUANTIZED_UINT8") _tf_export("lite.constants.TFLITE").export_constant(__name__, "TFLITE") _tf_export("lite.constants.GRAPHVIZ_DOT").export_constant( diff --git a/tensorflow/lite/python/lite_test.py b/tensorflow/lite/python/lite_test.py index 5a5697db92..1ae0d3c3ed 100644 --- a/tensorflow/lite/python/lite_test.py +++ b/tensorflow/lite/python/lite_test.py @@ -182,7 +182,7 @@ class FromSessionTest(test_util.TensorFlowTestCase): out_tensor = in_tensor + in_tensor sess = session.Session() - # Test invalid shape. None after 1st dimension. + # Test None as shape. converter = lite.TFLiteConverter.from_session(sess, [in_tensor], [out_tensor]) with self.assertRaises(ValueError) as error: @@ -190,7 +190,20 @@ class FromSessionTest(test_util.TensorFlowTestCase): self.assertEqual('Provide an input shape for input array \'Placeholder\'.', str(error.exception)) - def testBatchSizeInvalid(self): + def testSizeEmptyInvalid(self): + in_tensor = array_ops.placeholder(dtype=dtypes.float32, shape=[]) + out_tensor = in_tensor + in_tensor + sess = session.Session() + + # Test empty shape. + converter = lite.TFLiteConverter.from_session(sess, [in_tensor], + [out_tensor]) + with self.assertRaises(ValueError) as error: + converter.convert() + self.assertEqual('Provide an input shape for input array \'Placeholder\'.', + str(error.exception)) + + def testSizeInvalid(self): in_tensor = array_ops.placeholder( shape=[1, None, 16, 3], dtype=dtypes.float32) out_tensor = in_tensor + in_tensor @@ -931,12 +944,13 @@ class FromKerasFile(test_util.TensorFlowTestCase): """Test a Sequential tf.keras model testing input shapes argument.""" keras_file = self._getSequentialModel() - # Passing in shape of invalid input array has no impact as long as all input - # arrays have a shape. - converter = lite.TFLiteConverter.from_keras_model_file( - keras_file, input_shapes={'invalid-input': [2, 3]}) - tflite_model = converter.convert() - self.assertTrue(tflite_model) + # Passing in shape of invalid input array raises error. + with self.assertRaises(ValueError) as error: + converter = lite.TFLiteConverter.from_keras_model_file( + keras_file, input_shapes={'invalid-input': [2, 3]}) + self.assertEqual( + "Invalid tensor 'invalid-input' found in tensor shapes map.", + str(error.exception)) # Passing in shape of valid input array. converter = lite.TFLiteConverter.from_keras_model_file( diff --git a/tensorflow/lite/python/op_hint.py b/tensorflow/lite/python/op_hint.py index 3afce1baf2..8d7f9316bf 100644 --- a/tensorflow/lite/python/op_hint.py +++ b/tensorflow/lite/python/op_hint.py @@ -104,9 +104,9 @@ class OpHint(object): that make up the pseudo op. A similar process is done to any output that is to be exported from the current op. - TODO(aselle): When TensorFlow functions functionality works for arbitrary - constructs, this mechanism can be retired and changed to use python defun's. """ + # TODO(aselle): When TensorFlow functions functionality works for arbitrary + # constructs, this mechanism can be retired and changed to use python defun's. # Attr constants that are used for representation in the GraphDef. These # will be used on every Identity op that is involved in a total OpHint. @@ -403,7 +403,7 @@ class _LiteOperand(object): out_graphdef: A graphdef that is ready to have this input added. Returns: - The the output that the stub should use as an input for this operand. + The output that the stub should use as an input for this operand. Raises: RuntimeError: if the method is not implemented. diff --git a/tensorflow/lite/python/tflite_convert.py b/tensorflow/lite/python/tflite_convert.py index 00ea6d722e..341b539bea 100644 --- a/tensorflow/lite/python/tflite_convert.py +++ b/tensorflow/lite/python/tflite_convert.py @@ -25,7 +25,6 @@ import sys from tensorflow.lite.python import lite from tensorflow.lite.python import lite_constants from tensorflow.lite.toco import toco_flags_pb2 as _toco_flags_pb2 -from tensorflow.lite.toco import types_pb2 as _types_pb2 from tensorflow.python.platform import app @@ -41,6 +40,27 @@ def _parse_set(values): return None +def _parse_inference_type(value, flag): + """Converts the inference type to the value of the constant. + + Args: + value: str representing the inference type. + flag: str representing the flag name. + + Returns: + tf.dtype. + + Raises: + ValueError: Unsupported value. + """ + if value == "FLOAT": + return lite_constants.FLOAT + if value == "QUANTIZED_UINT8": + return lite_constants.QUANTIZED_UINT8 + raise ValueError("Unsupported value for --{0}. Only FLOAT and " + "QUANTIZED_UINT8 are supported.".format(flag)) + + def _get_toco_converter(flags): """Makes a TFLiteConverter object based on the flags provided. @@ -101,10 +121,11 @@ def _convert_model(flags): # Create converter. converter = _get_toco_converter(flags) if flags.inference_type: - converter.inference_type = _types_pb2.IODataType.Value(flags.inference_type) + converter.inference_type = _parse_inference_type(flags.inference_type, + "inference_type") if flags.inference_input_type: - converter.inference_input_type = _types_pb2.IODataType.Value( - flags.inference_input_type) + converter.inference_input_type = _parse_inference_type( + flags.inference_input_type, "inference_input_type") if flags.output_format: converter.output_format = _toco_flags_pb2.FileFormat.Value( flags.output_format) @@ -115,7 +136,7 @@ def _convert_model(flags): # In quantized inference, mean_value has to be integer so that the real # value 0.0 is exactly representable. - if flags.inference_type == lite_constants.QUANTIZED_UINT8: + if converter.inference_type == lite_constants.QUANTIZED_UINT8: mean_values = _parse_array(flags.mean_values, type_fn=int) else: mean_values = _parse_array(flags.mean_values, type_fn=float) @@ -156,7 +177,7 @@ def _convert_model(flags): if flags.post_training_quantize: converter.post_training_quantize = flags.post_training_quantize - if flags.inference_type == lite_constants.QUANTIZED_UINT8: + if converter.inference_type == lite_constants.QUANTIZED_UINT8: print("--post_training_quantize quantizes a graph of inference_type " "FLOAT. Overriding inference type QUANTIZED_UINT8 to FLOAT.") converter.inference_type = lite_constants.FLOAT diff --git a/tensorflow/lite/schema/schema.fbs b/tensorflow/lite/schema/schema.fbs index 9b0eae74c3..6436167303 100644 --- a/tensorflow/lite/schema/schema.fbs +++ b/tensorflow/lite/schema/schema.fbs @@ -200,6 +200,11 @@ enum BuiltinOperator : byte { FLOOR_MOD = 95, RANGE = 96, RESIZE_NEAREST_NEIGHBOR = 97, + LEAKY_RELU = 98, + SQUARED_DIFFERENCE = 99, + MIRROR_PAD = 100, + ABS = 101, + SPLIT_V = 102, } // Options for the builtin operators. @@ -278,6 +283,11 @@ union BuiltinOptions { FloorModOptions, RangeOptions, ResizeNearestNeighborOptions, + LeakyReluOptions, + SquaredDifferenceOptions, + MirrorPadOptions, + AbsOptions, + SplitVOptions, } enum Padding : byte { SAME, VALID } @@ -526,6 +536,10 @@ table SplitOptions { num_splits: int; } +table SplitVOptions { + num_splits: int; +} + table StridedSliceOptions { begin_mask: int; end_mask: int; @@ -629,6 +643,10 @@ table OneHotOptions { axis:int; } +table AbsOptions { +} + + table LogicalAndOptions { } @@ -658,6 +676,24 @@ table FloorModOptions { table RangeOptions { } +table LeakyReluOptions { + alpha:float; +} + +table SquaredDifferenceOptions { +} + +enum MirrorPadMode : byte { + // Doesn't include borders. + REFLECT = 0, + // Includes borders. + SYMMETRIC = 1, +} + +table MirrorPadOptions { + mode:MirrorPadMode; +} + // An OperatorCode can be an enum value (BuiltinOperator) if the operator is a // builtin, or a string if the operator is custom. table OperatorCode { diff --git a/tensorflow/lite/schema/schema_generated.h b/tensorflow/lite/schema/schema_generated.h index b7885cfcc5..af8b143364 100755 --- a/tensorflow/lite/schema/schema_generated.h +++ b/tensorflow/lite/schema/schema_generated.h @@ -148,6 +148,9 @@ struct SqueezeOptionsT; struct SplitOptions; struct SplitOptionsT; +struct SplitVOptions; +struct SplitVOptionsT; + struct StridedSliceOptions; struct StridedSliceOptionsT; @@ -226,6 +229,9 @@ struct LogicalOrOptionsT; struct OneHotOptions; struct OneHotOptionsT; +struct AbsOptions; +struct AbsOptionsT; + struct LogicalAndOptions; struct LogicalAndOptionsT; @@ -253,6 +259,15 @@ struct FloorModOptionsT; struct RangeOptions; struct RangeOptionsT; +struct LeakyReluOptions; +struct LeakyReluOptionsT; + +struct SquaredDifferenceOptions; +struct SquaredDifferenceOptionsT; + +struct MirrorPadOptions; +struct MirrorPadOptionsT; + struct OperatorCode; struct OperatorCodeT; @@ -500,11 +515,16 @@ enum BuiltinOperator { BuiltinOperator_FLOOR_MOD = 95, BuiltinOperator_RANGE = 96, BuiltinOperator_RESIZE_NEAREST_NEIGHBOR = 97, + BuiltinOperator_LEAKY_RELU = 98, + BuiltinOperator_SQUARED_DIFFERENCE = 99, + BuiltinOperator_MIRROR_PAD = 100, + BuiltinOperator_ABS = 101, + BuiltinOperator_SPLIT_V = 102, BuiltinOperator_MIN = BuiltinOperator_ADD, - BuiltinOperator_MAX = BuiltinOperator_RESIZE_NEAREST_NEIGHBOR + BuiltinOperator_MAX = BuiltinOperator_SPLIT_V }; -inline const BuiltinOperator (&EnumValuesBuiltinOperator())[97] { +inline const BuiltinOperator (&EnumValuesBuiltinOperator())[102] { static const BuiltinOperator values[] = { BuiltinOperator_ADD, BuiltinOperator_AVERAGE_POOL_2D, @@ -602,7 +622,12 @@ inline const BuiltinOperator (&EnumValuesBuiltinOperator())[97] { BuiltinOperator_FILL, BuiltinOperator_FLOOR_MOD, BuiltinOperator_RANGE, - BuiltinOperator_RESIZE_NEAREST_NEIGHBOR + BuiltinOperator_RESIZE_NEAREST_NEIGHBOR, + BuiltinOperator_LEAKY_RELU, + BuiltinOperator_SQUARED_DIFFERENCE, + BuiltinOperator_MIRROR_PAD, + BuiltinOperator_ABS, + BuiltinOperator_SPLIT_V }; return values; } @@ -707,6 +732,11 @@ inline const char * const *EnumNamesBuiltinOperator() { "FLOOR_MOD", "RANGE", "RESIZE_NEAREST_NEIGHBOR", + "LEAKY_RELU", + "SQUARED_DIFFERENCE", + "MIRROR_PAD", + "ABS", + "SPLIT_V", nullptr }; return names; @@ -793,11 +823,16 @@ enum BuiltinOptions { BuiltinOptions_FloorModOptions = 72, BuiltinOptions_RangeOptions = 73, BuiltinOptions_ResizeNearestNeighborOptions = 74, + BuiltinOptions_LeakyReluOptions = 75, + BuiltinOptions_SquaredDifferenceOptions = 76, + BuiltinOptions_MirrorPadOptions = 77, + BuiltinOptions_AbsOptions = 78, + BuiltinOptions_SplitVOptions = 79, BuiltinOptions_MIN = BuiltinOptions_NONE, - BuiltinOptions_MAX = BuiltinOptions_ResizeNearestNeighborOptions + BuiltinOptions_MAX = BuiltinOptions_SplitVOptions }; -inline const BuiltinOptions (&EnumValuesBuiltinOptions())[75] { +inline const BuiltinOptions (&EnumValuesBuiltinOptions())[80] { static const BuiltinOptions values[] = { BuiltinOptions_NONE, BuiltinOptions_Conv2DOptions, @@ -873,7 +908,12 @@ inline const BuiltinOptions (&EnumValuesBuiltinOptions())[75] { BuiltinOptions_UnidirectionalSequenceLSTMOptions, BuiltinOptions_FloorModOptions, BuiltinOptions_RangeOptions, - BuiltinOptions_ResizeNearestNeighborOptions + BuiltinOptions_ResizeNearestNeighborOptions, + BuiltinOptions_LeakyReluOptions, + BuiltinOptions_SquaredDifferenceOptions, + BuiltinOptions_MirrorPadOptions, + BuiltinOptions_AbsOptions, + BuiltinOptions_SplitVOptions }; return values; } @@ -955,6 +995,11 @@ inline const char * const *EnumNamesBuiltinOptions() { "FloorModOptions", "RangeOptions", "ResizeNearestNeighborOptions", + "LeakyReluOptions", + "SquaredDifferenceOptions", + "MirrorPadOptions", + "AbsOptions", + "SplitVOptions", nullptr }; return names; @@ -1265,6 +1310,26 @@ template<> struct BuiltinOptionsTraits { static const BuiltinOptions enum_value = BuiltinOptions_ResizeNearestNeighborOptions; }; +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_LeakyReluOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SquaredDifferenceOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_MirrorPadOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_AbsOptions; +}; + +template<> struct BuiltinOptionsTraits { + static const BuiltinOptions enum_value = BuiltinOptions_SplitVOptions; +}; + struct BuiltinOptionsUnion { BuiltinOptions type; void *value; @@ -1888,6 +1953,46 @@ struct BuiltinOptionsUnion { return type == BuiltinOptions_ResizeNearestNeighborOptions ? reinterpret_cast(value) : nullptr; } + LeakyReluOptionsT *AsLeakyReluOptions() { + return type == BuiltinOptions_LeakyReluOptions ? + reinterpret_cast(value) : nullptr; + } + const LeakyReluOptionsT *AsLeakyReluOptions() const { + return type == BuiltinOptions_LeakyReluOptions ? + reinterpret_cast(value) : nullptr; + } + SquaredDifferenceOptionsT *AsSquaredDifferenceOptions() { + return type == BuiltinOptions_SquaredDifferenceOptions ? + reinterpret_cast(value) : nullptr; + } + const SquaredDifferenceOptionsT *AsSquaredDifferenceOptions() const { + return type == BuiltinOptions_SquaredDifferenceOptions ? + reinterpret_cast(value) : nullptr; + } + MirrorPadOptionsT *AsMirrorPadOptions() { + return type == BuiltinOptions_MirrorPadOptions ? + reinterpret_cast(value) : nullptr; + } + const MirrorPadOptionsT *AsMirrorPadOptions() const { + return type == BuiltinOptions_MirrorPadOptions ? + reinterpret_cast(value) : nullptr; + } + AbsOptionsT *AsAbsOptions() { + return type == BuiltinOptions_AbsOptions ? + reinterpret_cast(value) : nullptr; + } + const AbsOptionsT *AsAbsOptions() const { + return type == BuiltinOptions_AbsOptions ? + reinterpret_cast(value) : nullptr; + } + SplitVOptionsT *AsSplitVOptions() { + return type == BuiltinOptions_SplitVOptions ? + reinterpret_cast(value) : nullptr; + } + const SplitVOptionsT *AsSplitVOptions() const { + return type == BuiltinOptions_SplitVOptions ? + reinterpret_cast(value) : nullptr; + } }; bool VerifyBuiltinOptions(flatbuffers::Verifier &verifier, const void *obj, BuiltinOptions type); @@ -2085,6 +2190,35 @@ inline const char *EnumNameCombinerType(CombinerType e) { return EnumNamesCombinerType()[index]; } +enum MirrorPadMode { + MirrorPadMode_REFLECT = 0, + MirrorPadMode_SYMMETRIC = 1, + MirrorPadMode_MIN = MirrorPadMode_REFLECT, + MirrorPadMode_MAX = MirrorPadMode_SYMMETRIC +}; + +inline const MirrorPadMode (&EnumValuesMirrorPadMode())[2] { + static const MirrorPadMode values[] = { + MirrorPadMode_REFLECT, + MirrorPadMode_SYMMETRIC + }; + return values; +} + +inline const char * const *EnumNamesMirrorPadMode() { + static const char * const names[] = { + "REFLECT", + "SYMMETRIC", + nullptr + }; + return names; +} + +inline const char *EnumNameMirrorPadMode(MirrorPadMode e) { + const size_t index = static_cast(e); + return EnumNamesMirrorPadMode()[index]; +} + enum CustomOptionsFormat { CustomOptionsFormat_FLEXBUFFERS = 0, CustomOptionsFormat_MIN = CustomOptionsFormat_FLEXBUFFERS, @@ -4935,6 +5069,60 @@ inline flatbuffers::Offset CreateSplitOptions( flatbuffers::Offset CreateSplitOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct SplitVOptionsT : public flatbuffers::NativeTable { + typedef SplitVOptions TableType; + int32_t num_splits; + SplitVOptionsT() + : num_splits(0) { + } +}; + +struct SplitVOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SplitVOptionsT NativeTableType; + enum { + VT_NUM_SPLITS = 4 + }; + int32_t num_splits() const { + return GetField(VT_NUM_SPLITS, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_NUM_SPLITS) && + verifier.EndTable(); + } + SplitVOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SplitVOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SplitVOptionsBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_num_splits(int32_t num_splits) { + fbb_.AddElement(SplitVOptions::VT_NUM_SPLITS, num_splits, 0); + } + explicit SplitVOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + SplitVOptionsBuilder &operator=(const SplitVOptionsBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSplitVOptions( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t num_splits = 0) { + SplitVOptionsBuilder builder_(_fbb); + builder_.add_num_splits(num_splits); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSplitVOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct StridedSliceOptionsT : public flatbuffers::NativeTable { typedef StridedSliceOptions TableType; int32_t begin_mask; @@ -6247,6 +6435,46 @@ inline flatbuffers::Offset CreateOneHotOptions( flatbuffers::Offset CreateOneHotOptions(flatbuffers::FlatBufferBuilder &_fbb, const OneHotOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct AbsOptionsT : public flatbuffers::NativeTable { + typedef AbsOptions TableType; + AbsOptionsT() { + } +}; + +struct AbsOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef AbsOptionsT NativeTableType; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + AbsOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(AbsOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct AbsOptionsBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit AbsOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + AbsOptionsBuilder &operator=(const AbsOptionsBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateAbsOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + AbsOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateAbsOptions(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct LogicalAndOptionsT : public flatbuffers::NativeTable { typedef LogicalAndOptions TableType; LogicalAndOptionsT() { @@ -6633,6 +6861,154 @@ inline flatbuffers::Offset CreateRangeOptions( flatbuffers::Offset CreateRangeOptions(flatbuffers::FlatBufferBuilder &_fbb, const RangeOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +struct LeakyReluOptionsT : public flatbuffers::NativeTable { + typedef LeakyReluOptions TableType; + float alpha; + LeakyReluOptionsT() + : alpha(0.0f) { + } +}; + +struct LeakyReluOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef LeakyReluOptionsT NativeTableType; + enum { + VT_ALPHA = 4 + }; + float alpha() const { + return GetField(VT_ALPHA, 0.0f); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_ALPHA) && + verifier.EndTable(); + } + LeakyReluOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(LeakyReluOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct LeakyReluOptionsBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_alpha(float alpha) { + fbb_.AddElement(LeakyReluOptions::VT_ALPHA, alpha, 0.0f); + } + explicit LeakyReluOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + LeakyReluOptionsBuilder &operator=(const LeakyReluOptionsBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateLeakyReluOptions( + flatbuffers::FlatBufferBuilder &_fbb, + float alpha = 0.0f) { + LeakyReluOptionsBuilder builder_(_fbb); + builder_.add_alpha(alpha); + return builder_.Finish(); +} + +flatbuffers::Offset CreateLeakyReluOptions(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct SquaredDifferenceOptionsT : public flatbuffers::NativeTable { + typedef SquaredDifferenceOptions TableType; + SquaredDifferenceOptionsT() { + } +}; + +struct SquaredDifferenceOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef SquaredDifferenceOptionsT NativeTableType; + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + SquaredDifferenceOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(SquaredDifferenceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquaredDifferenceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct SquaredDifferenceOptionsBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + explicit SquaredDifferenceOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + SquaredDifferenceOptionsBuilder &operator=(const SquaredDifferenceOptionsBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateSquaredDifferenceOptions( + flatbuffers::FlatBufferBuilder &_fbb) { + SquaredDifferenceOptionsBuilder builder_(_fbb); + return builder_.Finish(); +} + +flatbuffers::Offset CreateSquaredDifferenceOptions(flatbuffers::FlatBufferBuilder &_fbb, const SquaredDifferenceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct MirrorPadOptionsT : public flatbuffers::NativeTable { + typedef MirrorPadOptions TableType; + MirrorPadMode mode; + MirrorPadOptionsT() + : mode(MirrorPadMode_REFLECT) { + } +}; + +struct MirrorPadOptions FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef MirrorPadOptionsT NativeTableType; + enum { + VT_MODE = 4 + }; + MirrorPadMode mode() const { + return static_cast(GetField(VT_MODE, 0)); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_MODE) && + verifier.EndTable(); + } + MirrorPadOptionsT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(MirrorPadOptionsT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct MirrorPadOptionsBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_mode(MirrorPadMode mode) { + fbb_.AddElement(MirrorPadOptions::VT_MODE, static_cast(mode), 0); + } + explicit MirrorPadOptionsBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + MirrorPadOptionsBuilder &operator=(const MirrorPadOptionsBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateMirrorPadOptions( + flatbuffers::FlatBufferBuilder &_fbb, + MirrorPadMode mode = MirrorPadMode_REFLECT) { + MirrorPadOptionsBuilder builder_(_fbb); + builder_.add_mode(mode); + return builder_.Finish(); +} + +flatbuffers::Offset CreateMirrorPadOptions(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + struct OperatorCodeT : public flatbuffers::NativeTable { typedef OperatorCode TableType; BuiltinOperator builtin_code; @@ -6988,6 +7364,21 @@ struct Operator FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const ResizeNearestNeighborOptions *builtin_options_as_ResizeNearestNeighborOptions() const { return builtin_options_type() == BuiltinOptions_ResizeNearestNeighborOptions ? static_cast(builtin_options()) : nullptr; } + const LeakyReluOptions *builtin_options_as_LeakyReluOptions() const { + return builtin_options_type() == BuiltinOptions_LeakyReluOptions ? static_cast(builtin_options()) : nullptr; + } + const SquaredDifferenceOptions *builtin_options_as_SquaredDifferenceOptions() const { + return builtin_options_type() == BuiltinOptions_SquaredDifferenceOptions ? static_cast(builtin_options()) : nullptr; + } + const MirrorPadOptions *builtin_options_as_MirrorPadOptions() const { + return builtin_options_type() == BuiltinOptions_MirrorPadOptions ? static_cast(builtin_options()) : nullptr; + } + const AbsOptions *builtin_options_as_AbsOptions() const { + return builtin_options_type() == BuiltinOptions_AbsOptions ? static_cast(builtin_options()) : nullptr; + } + const SplitVOptions *builtin_options_as_SplitVOptions() const { + return builtin_options_type() == BuiltinOptions_SplitVOptions ? static_cast(builtin_options()) : nullptr; + } const flatbuffers::Vector *custom_options() const { return GetPointer *>(VT_CUSTOM_OPTIONS); } @@ -7315,6 +7706,26 @@ template<> inline const ResizeNearestNeighborOptions *Operator::builtin_options_ return builtin_options_as_ResizeNearestNeighborOptions(); } +template<> inline const LeakyReluOptions *Operator::builtin_options_as() const { + return builtin_options_as_LeakyReluOptions(); +} + +template<> inline const SquaredDifferenceOptions *Operator::builtin_options_as() const { + return builtin_options_as_SquaredDifferenceOptions(); +} + +template<> inline const MirrorPadOptions *Operator::builtin_options_as() const { + return builtin_options_as_MirrorPadOptions(); +} + +template<> inline const AbsOptions *Operator::builtin_options_as() const { + return builtin_options_as_AbsOptions(); +} + +template<> inline const SplitVOptions *Operator::builtin_options_as() const { + return builtin_options_as_SplitVOptions(); +} + struct OperatorBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; @@ -8932,6 +9343,32 @@ inline flatbuffers::Offset CreateSplitOptions(flatbuffers::FlatBuf _num_splits); } +inline SplitVOptionsT *SplitVOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = new SplitVOptionsT(); + UnPackTo(_o, _resolver); + return _o; +} + +inline void SplitVOptions::UnPackTo(SplitVOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = num_splits(); _o->num_splits = _e; }; +} + +inline flatbuffers::Offset SplitVOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSplitVOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSplitVOptions(flatbuffers::FlatBufferBuilder &_fbb, const SplitVOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SplitVOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _num_splits = _o->num_splits; + return tflite::CreateSplitVOptions( + _fbb, + _num_splits); +} + inline StridedSliceOptionsT *StridedSliceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { auto _o = new StridedSliceOptionsT(); UnPackTo(_o, _resolver); @@ -9593,6 +10030,29 @@ inline flatbuffers::Offset CreateOneHotOptions(flatbuffers::FlatB _axis); } +inline AbsOptionsT *AbsOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = new AbsOptionsT(); + UnPackTo(_o, _resolver); + return _o; +} + +inline void AbsOptions::UnPackTo(AbsOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset AbsOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateAbsOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateAbsOptions(flatbuffers::FlatBufferBuilder &_fbb, const AbsOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const AbsOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateAbsOptions( + _fbb); +} + inline LogicalAndOptionsT *LogicalAndOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { auto _o = new LogicalAndOptionsT(); UnPackTo(_o, _resolver); @@ -9806,6 +10266,81 @@ inline flatbuffers::Offset CreateRangeOptions(flatbuffers::FlatBuf _fbb); } +inline LeakyReluOptionsT *LeakyReluOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = new LeakyReluOptionsT(); + UnPackTo(_o, _resolver); + return _o; +} + +inline void LeakyReluOptions::UnPackTo(LeakyReluOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = alpha(); _o->alpha = _e; }; +} + +inline flatbuffers::Offset LeakyReluOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateLeakyReluOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateLeakyReluOptions(flatbuffers::FlatBufferBuilder &_fbb, const LeakyReluOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const LeakyReluOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _alpha = _o->alpha; + return tflite::CreateLeakyReluOptions( + _fbb, + _alpha); +} + +inline SquaredDifferenceOptionsT *SquaredDifferenceOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = new SquaredDifferenceOptionsT(); + UnPackTo(_o, _resolver); + return _o; +} + +inline void SquaredDifferenceOptions::UnPackTo(SquaredDifferenceOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; +} + +inline flatbuffers::Offset SquaredDifferenceOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const SquaredDifferenceOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateSquaredDifferenceOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateSquaredDifferenceOptions(flatbuffers::FlatBufferBuilder &_fbb, const SquaredDifferenceOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const SquaredDifferenceOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + return tflite::CreateSquaredDifferenceOptions( + _fbb); +} + +inline MirrorPadOptionsT *MirrorPadOptions::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = new MirrorPadOptionsT(); + UnPackTo(_o, _resolver); + return _o; +} + +inline void MirrorPadOptions::UnPackTo(MirrorPadOptionsT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = mode(); _o->mode = _e; }; +} + +inline flatbuffers::Offset MirrorPadOptions::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateMirrorPadOptions(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateMirrorPadOptions(flatbuffers::FlatBufferBuilder &_fbb, const MirrorPadOptionsT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MirrorPadOptionsT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _mode = _o->mode; + return tflite::CreateMirrorPadOptions( + _fbb, + _mode); +} + inline OperatorCodeT *OperatorCode::UnPack(const flatbuffers::resolver_function_t *_resolver) const { auto _o = new OperatorCodeT(); UnPackTo(_o, _resolver); @@ -10360,6 +10895,26 @@ inline bool VerifyBuiltinOptions(flatbuffers::Verifier &verifier, const void *ob auto ptr = reinterpret_cast(obj); return verifier.VerifyTable(ptr); } + case BuiltinOptions_LeakyReluOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SquaredDifferenceOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_MirrorPadOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_AbsOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case BuiltinOptions_SplitVOptions: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } default: return false; } } @@ -10674,6 +11229,26 @@ inline void *BuiltinOptionsUnion::UnPack(const void *obj, BuiltinOptions type, c auto ptr = reinterpret_cast(obj); return ptr->UnPack(resolver); } + case BuiltinOptions_LeakyReluOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SquaredDifferenceOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_MirrorPadOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_AbsOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case BuiltinOptions_SplitVOptions: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } default: return nullptr; } } @@ -10976,6 +11551,26 @@ inline flatbuffers::Offset BuiltinOptionsUnion::Pack(flatbuffers::FlatBuff auto ptr = reinterpret_cast(value); return CreateResizeNearestNeighborOptions(_fbb, ptr, _rehasher).Union(); } + case BuiltinOptions_LeakyReluOptions: { + auto ptr = reinterpret_cast(value); + return CreateLeakyReluOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SquaredDifferenceOptions: { + auto ptr = reinterpret_cast(value); + return CreateSquaredDifferenceOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_MirrorPadOptions: { + auto ptr = reinterpret_cast(value); + return CreateMirrorPadOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_AbsOptions: { + auto ptr = reinterpret_cast(value); + return CreateAbsOptions(_fbb, ptr, _rehasher).Union(); + } + case BuiltinOptions_SplitVOptions: { + auto ptr = reinterpret_cast(value); + return CreateSplitVOptions(_fbb, ptr, _rehasher).Union(); + } default: return 0; } } @@ -11278,6 +11873,26 @@ inline BuiltinOptionsUnion::BuiltinOptionsUnion(const BuiltinOptionsUnion &u) FL value = new ResizeNearestNeighborOptionsT(*reinterpret_cast(u.value)); break; } + case BuiltinOptions_LeakyReluOptions: { + value = new LeakyReluOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SquaredDifferenceOptions: { + value = new SquaredDifferenceOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_MirrorPadOptions: { + value = new MirrorPadOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_AbsOptions: { + value = new AbsOptionsT(*reinterpret_cast(u.value)); + break; + } + case BuiltinOptions_SplitVOptions: { + value = new SplitVOptionsT(*reinterpret_cast(u.value)); + break; + } default: break; } @@ -11655,6 +12270,31 @@ inline void BuiltinOptionsUnion::Reset() { delete ptr; break; } + case BuiltinOptions_LeakyReluOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SquaredDifferenceOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_MirrorPadOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_AbsOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case BuiltinOptions_SplitVOptions: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } default: break; } value = nullptr; diff --git a/tensorflow/lite/string_util.cc b/tensorflow/lite/string_util.cc index 1b33f5bcba..6efa11d60c 100644 --- a/tensorflow/lite/string_util.cc +++ b/tensorflow/lite/string_util.cc @@ -96,8 +96,7 @@ int DynamicBuffer::WriteToBuffer(char** buffer) { return bytes; } -void DynamicBuffer::WriteToTensor(TfLiteTensor* tensor) { - // Set tensor content pointer to tensor_buffer, and release original data. +void DynamicBuffer::WriteToTensorAsVector(TfLiteTensor* tensor) { auto dims = TfLiteIntArrayCreate(1); dims->data[0] = offset_.size() - 1; // Store number of strings. WriteToTensor(tensor, dims); @@ -108,6 +107,10 @@ void DynamicBuffer::WriteToTensor(TfLiteTensor* tensor, char* tensor_buffer; int bytes = WriteToBuffer(&tensor_buffer); + if (new_shape == nullptr) { + new_shape = TfLiteIntArrayCopy(tensor->dims); + } + // Set tensor content pointer to tensor_buffer, and release original data. TfLiteTensorReset(tensor->type, tensor->name, new_shape, tensor->params, tensor_buffer, bytes, kTfLiteDynamic, tensor->allocation, diff --git a/tensorflow/lite/string_util.h b/tensorflow/lite/string_util.h index c9b74482f7..f076db76f2 100644 --- a/tensorflow/lite/string_util.h +++ b/tensorflow/lite/string_util.h @@ -74,12 +74,18 @@ class DynamicBuffer { // The function allocates space for the buffer but does NOT take ownership. int WriteToBuffer(char** buffer); - // Fill content into a string tensor, with the given new_shape. The new - // shape must match the number of strings in this object. + // Fill content into a string tensor, with the given new_shape. The new shape + // must match the number of strings in this object. Caller relinquishes + // ownership of new_shape. If 'new_shape' is nullptr, keep the tensor's + // existing shape. void WriteToTensor(TfLiteTensor* tensor, TfLiteIntArray* new_shape); // Fill content into a string tensor. Set shape to {num_strings}. - void WriteToTensor(TfLiteTensor* tensor); + void WriteToTensorAsVector(TfLiteTensor* tensor); + + // Deprecated. Use WriteToTensorAsVector() or pass in the new shpe. + // TODO(b/120230709): remove when people migrate away. + void WriteToTensor(TfLiteTensor* tensor) { WriteToTensorAsVector(tensor); } private: // Data buffer to store contents of strings, not including headers. diff --git a/tensorflow/lite/string_util_test.cc b/tensorflow/lite/string_util_test.cc index 377cdd77eb..cbf1d7b226 100644 --- a/tensorflow/lite/string_util_test.cc +++ b/tensorflow/lite/string_util_test.cc @@ -55,7 +55,7 @@ TEST(StringUtil, TestStringUtil) { new_shape->data[0] = 2; new_shape->data[1] = 1; buf0.WriteToTensor(t0, new_shape); - buf1.WriteToTensor(t1); + buf1.WriteToTensorAsVector(t1); // Check tensor shapes. EXPECT_EQ(t0->dims->size, 2); @@ -99,7 +99,7 @@ TEST(StringUtil, TestAddJoinedString) { DynamicBuffer buf; buf.AddJoinedString({{s0, 3}, {s1, 4}, {s2, 0}, {s3, 3}}, ' '); - buf.WriteToTensor(t0); + buf.WriteToTensorAsVector(t0); ASSERT_EQ(GetStringCount(t0), 1); StringRef str_ref; @@ -115,12 +115,43 @@ TEST(StringUtil, TestEmptyList) { t0->type = kTfLiteString; t0->allocation_type = kTfLiteDynamic; DynamicBuffer buf; - buf.WriteToTensor(t0); + buf.WriteToTensorAsVector(t0); ASSERT_EQ(GetStringCount(t0), 0); ASSERT_EQ(t0->bytes, 8); } +TEST(StringUtil, TestShapes) { + Interpreter interpreter; + interpreter.AddTensors(1); + TfLiteTensor* t0 = interpreter.tensor(0); + t0->type = kTfLiteString; + t0->allocation_type = kTfLiteDynamic; + t0->dims = TfLiteIntArrayCreate(2); + t0->dims->data[0] = 2; + t0->dims->data[1] = 1; + + // Not setting a new shape: number of strings must match + DynamicBuffer buf; + buf.AddString("ABC", 3); + buf.AddString("X", 1); + buf.WriteToTensor(t0, nullptr); + + ASSERT_EQ(t0->dims->size, 2); + EXPECT_EQ(t0->dims->data[0], 2); + EXPECT_EQ(t0->dims->data[1], 1); + + auto new_shape = TfLiteIntArrayCreate(2); + new_shape->data[0] = 1; + new_shape->data[1] = 2; + + buf.WriteToTensor(t0, new_shape); + + ASSERT_EQ(t0->dims->size, 2); + EXPECT_EQ(t0->dims->data[0], 1); + EXPECT_EQ(t0->dims->data[1], 2); +} + } // namespace tflite int main(int argc, char** argv) { diff --git a/tensorflow/lite/testing/generate_examples.py b/tensorflow/lite/testing/generate_examples.py index 2b129df766..4c731a7d18 100644 --- a/tensorflow/lite/testing/generate_examples.py +++ b/tensorflow/lite/testing/generate_examples.py @@ -103,8 +103,8 @@ KNOWN_BUGS = { r"batch_to_space_nd.*input_shape=\[8,2,2,2,1,1\]": "70594733", # Div will use floordiv. r"div.*int32": "72051395", - # No support for SplitV - r"split.*num_or_size_splits=\[2,2\]": "73377559", + # Constant 1D gather crashes toco. + r"gather_buggy.*input_shape=\[3\].*": "120029508", } @@ -370,7 +370,8 @@ def make_zip_of_tests(zip_path, make_graph, make_test_inputs, extra_toco_options=ExtraTocoOptions(), - use_frozen_graph=False): + use_frozen_graph=False, + expected_tf_success=None): """Helper to make a zip file of a bunch of TensorFlow models. This does a cartestian product of the dictionary of test_parameters and @@ -390,6 +391,8 @@ def make_zip_of_tests(zip_path, `output_tensors` and returns tuple `(input_values, output_values)`. extra_toco_options: Additional toco options. use_frozen_graph: Whether or not freeze graph before toco converter. + expected_tf_success: Number of times tensorflow is supposed to succeed in + executing the input graphs. `None` means "unknown". Raises: RuntimeError: if there are toco errors that can't be ignored. @@ -550,6 +553,11 @@ def make_zip_of_tests(zip_path, " and %d TOCO converted graphs (%.1f%%"), zip_path, total_conversions, tf_success, toco_success, percent) + if expected_tf_success is not None and tf_success != expected_tf_success: + raise RuntimeError( + "Expected TF to succeed %d times, but that happened %d times" % + (expected_tf_success, tf_success)) + if not FLAGS.ignore_toco_errors and toco_errors > 0: raise RuntimeError( "Found %d errors while generating toco models" % toco_errors) @@ -616,6 +624,30 @@ def make_max_pool_tests(zip_path): make_pool_tests(tf.nn.max_pool)(zip_path) +def make_abs_tests(zip_path): + """Make a set of tests to do relu.""" + + # Chose a set of parameters + test_parameters = [{ + "input_shape": [[], [1], [2, 3], [1, 1, 1, 1], [1, 3, 4, 3], + [3, 15, 14, 3], [3, 1, 2, 4, 6], [2, 2, 3, 4, 5, 6]], + }] + + def build_graph(parameters): + input_tensor = tf.placeholder( + dtype=tf.float32, name="input", shape=parameters["input_shape"]) + out = tf.abs(input_tensor) + return [input_tensor], [out] + + def build_inputs(parameters, sess, inputs, outputs): + input_values = create_tensor_data( + np.float32, parameters["input_shape"], min_value=-10, max_value=10) + return [input_values], sess.run( + outputs, feed_dict=dict(zip(inputs, [input_values]))) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + + def make_relu_tests(zip_path): """Make a set of tests to do relu.""" @@ -747,6 +779,34 @@ def make_prelu_tests(zip_path): use_frozen_graph=True) +def make_leaky_relu_tests(zip_path): + """Make a set of tests to do LeakyRelu.""" + + test_parameters = [ + { + "input_shape": [[], [1], [5], [1, 10, 10, 3], [3, 3, 3, 3]], + "alpha": [0.1, 1.0, 2.0, -0.1, -1.0, -2.0], + }, + ] + + def build_graph(parameters): + """Build the graph for the test case.""" + + input_tensor = tf.placeholder( + dtype=tf.float32, name="input", shape=parameters["input_shape"]) + out = tf.nn.leaky_relu(input_tensor, alpha=parameters["alpha"]) + return [input_tensor], [out] + + def build_inputs(parameters, sess, inputs, outputs): + """Build the inputs for the test case.""" + input_values = create_tensor_data( + np.float32, parameters["input_shape"], min_value=-3, max_value=10) + return [input_values], sess.run( + outputs, feed_dict=dict(zip(inputs, [input_values]))) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + + # This function tests various TensorFLow functions that generates Const op, # including `tf.ones`, `tf.zeros` and random functions. def make_constant_tests(zip_path): @@ -755,6 +815,7 @@ def make_constant_tests(zip_path): test_parameters = [{ "dtype": [tf.float32, tf.int32], "input_shape": [[], [1], [2], [1, 1, 1, 1], [2, 2, 2, 2]], + "constant_is_also_output": [True, False], }] def build_graph(parameters): @@ -764,17 +825,19 @@ def make_constant_tests(zip_path): shape=parameters["input_shape"]) constant = tf.constant( create_tensor_data(parameters["dtype"], parameters["input_shape"])) - # This maximum node is here to avoid the situation where a graph output is - # a constant, which is an error in toco. - out = tf.maximum(dummy_input, constant) - return [dummy_input], [out] + out = [tf.maximum(dummy_input, constant)] + if parameters["constant_is_also_output"]: + out.append(constant) + + return [dummy_input], out def build_inputs(parameters, sess, inputs, outputs): dummy_input = np.zeros( parameters["input_shape"], dtype=_TF_TYPE_INFO[parameters["dtype"]][0]) return [dummy_input], sess.run(outputs, feed_dict={inputs[0]: dummy_input}) - make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs, + expected_tf_success=20) def make_binary_op_tests(zip_path, binary_operator): @@ -869,34 +932,46 @@ def make_reduce_tests(reduce_op, def f(zip_path): """Actual function that generates examples.""" - test_parameters = [{ - "input_dtype": [tf.float32, tf.int32, tf.int64], - "input_shape": [[3, 2, 4]], - "axis": [ - 0, 1, 2, [0, 1], [0, 2], [1, 2], [0, 1, 2], [1, 0], [2, 0], - [2, 1], [2, 1, 0], [2, 0, 1], -1, -2, -3, [1, -1], [0, -1], [-1, 0], - [-1, -2, -3], [0, 0, 0], [2, 2, 0], [1, 0, -3, -3] - ], - "const_axis": [True, False], - "keepdims": [True, False], - }, { - "input_dtype": [tf.float32], - "input_shape": [[1, 8, 8, 3]], - "axis": [ - 0, 1, 2, 3, [1, 2], [0, 3], [1, 2, 3], [0, 1, 2, 3], - [3, 2, 1, 0], [3, 1, 0, 2], [2, 0], [3, 0], [3, 1], [1, 0], -1, -2, - -3, -4, [0, -2], [2, 3, -1, 0], [3, 1, 2, -3], [3, -4], [2, 2, 2], - [2, 2, 3], [-3, -3, -4], [-3, 2, 1] - ], - "const_axis": [True, False], - "keepdims": [True, False], - }, { - "input_dtype": [tf.float32], - "input_shape": [[], [1, 8, 8, 3], [3, 2, 4]], - "axis": [None], - "const_axis": [True], - "keepdims": [True, False], - }] + test_parameters = [ + { + "input_dtype": [tf.float32, tf.int32, tf.int64], + "input_shape": [[3, 3, 2, 4]], + "axis": [ + 0, 1, 2, [0, 1], [0, 2], [1, 2], [0, 1, 2], [1, 0], [2, 0], + [2, 1], [2, 1, 0], [2, 0, 1], -1, -2, -3, [1, -1], [0, -1], + [-1, 0], [-1, -2, -3], [0, 0, 0], [2, 2, 0], [1, 0, -3, -3] + ], + "const_axis": [True, False], + "keepdims": [True, False], + }, + { + "input_dtype": [tf.float32], + "input_shape": [[1, 8, 8, 3]], + "axis": [ + 0, 1, 2, 3, [1, 2], [0, 3], [1, 2, 3], [0, 1, 2, + 3], [3, 2, 1, 0], + [3, 1, 0, 2], [2, 0], [3, 0], [3, 1], [1, 0], -1, -2, -3, -4, + [0, -2], [2, 3, -1, 0], [3, 1, 2, -3], [3, -4], [2, 2, 2], + [2, 2, 3], [-3, -3, -4], [-3, 2, 1] + ], + "const_axis": [True, False], + "keepdims": [True, False], + }, + { + "input_dtype": [tf.float32], + "input_shape": [[], [1, 8, 8, 3], [3, 2, 4]], + "axis": [[]], # shape is: [0] + "const_axis": [False], + "keepdims": [True, False], + }, + { + "input_dtype": [tf.float32], + "input_shape": [[], [1, 8, 8, 3], [3, 2, 4]], + "axis": [None], # shape is: [] + "const_axis": [True], + "keepdims": [True, False], + } + ] def build_graph(parameters): """Build the mean op testing graph.""" @@ -1135,6 +1210,10 @@ def make_floor_mod_tests(zip_path): make_binary_op_tests(zip_path, tf.floormod) +def make_squared_difference_tests(zip_path): + make_binary_op_tests(zip_path, tf.squared_difference) + + def make_gather_tests(zip_path): """Make a set of tests to do gather.""" @@ -1142,9 +1221,9 @@ def make_gather_tests(zip_path): # TODO(mgubin): add string tests when they are supported by Toco. # TODO(mgubin): add tests for Nd indices when they are supported by # TfLite. - "params_dtype": [tf.float32, tf.int32], + "params_dtype": [tf.float32, tf.int32, tf.int64], "params_shape": [[10], [1, 2, 20]], - "indices_dtype": [tf.int32], + "indices_dtype": [tf.int32, tf.int64], "indices_shape": [[3], [5]], "axis": [-1, 0, 1], }] @@ -1172,7 +1251,43 @@ def make_gather_tests(zip_path): return [params, indices], sess.run( outputs, feed_dict=dict(zip(inputs, [params, indices]))) - make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + # Note that TF can't execute with index=1 and params_shape=[10]. + make_zip_of_tests( + zip_path, + test_parameters, + build_graph, + build_inputs, + expected_tf_success=60) + + +def make_gather_buggy_tests(zip_path): + """Make a set of tests to show gather crashes toco.""" + + test_parameters = [{ + "input_shape": [[3]], + "reference_shape": [[2]], + }, { + "input_shape": [[2, 3]], + "reference_shape": [[2, 3]], + }] + + def build_graph(parameters): + """Build a graph where the inputs to Gather are constants.""" + reference = tf.placeholder( + dtype=tf.int32, shape=parameters["reference_shape"]) + gather_input = tf.constant( + create_tensor_data(tf.int32, parameters["input_shape"])) + gather_indices = tf.constant([0, 1], tf.int32) + out = tf.equal(reference, tf.gather(gather_input, gather_indices)) + return [reference], [out] + + def build_inputs(parameters, sess, inputs, outputs): + reference_values = np.zeros(parameters["reference_shape"], dtype=np.int32) + return [reference_values], sess.run( + outputs, feed_dict={inputs[0]: reference_values}) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs, + expected_tf_success=2) def make_global_batch_norm_tests(zip_path): @@ -1340,23 +1455,27 @@ def make_conv_with_shared_weights_tests(zip_path): input_shape, filter_shape = get_tensor_shapes(parameters) input_tensor = tf.placeholder( dtype=tf.float32, name="input", shape=input_shape) + input_tensors = [input_tensor] # Construct a constant weights tensor which will be used by both Conv2D. filter_tensor = tf.constant( create_tensor_data(np.float32, filter_shape), dtype=tf.float32) - input_tensors = [input_tensor] + + # Ensure that FuseBinaryIntoFollowingAffine works with an input which + # is shared by multiple affine ops. + conv_input = input_tensor + 0.1 # Construct 2 Conv2D operations which use exactly the same input and # weights. result1 = tf.nn.conv2d( - input_tensor, + conv_input, filter_tensor, strides=parameters["strides"], dilations=parameters["dilations"], padding=parameters["padding"], data_format=parameters["data_format"]) result2 = tf.nn.conv2d( - input_tensor, + conv_input, filter_tensor, strides=parameters["strides"], dilations=parameters["dilations"], @@ -1524,7 +1643,7 @@ def make_split_tests(zip_path): test_parameters = [{ "input_shape": [[1, 3, 4, 6], [2, 4, 1], [6, 4], [8]], - "num_or_size_splits": [1, 2, 3, 4, 5, [2, 2]], + "num_or_size_splits": [1, 2, 3, 4, 5], "axis": [0, 1, 2, 3, -4, -3, -2, -1], }] @@ -1542,6 +1661,29 @@ def make_split_tests(zip_path): make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) +def make_splitv_tests(zip_path): + """Make a set of tests to do tf.split_v.""" + + test_parameters = [{ + "input_shape": [[1, 3, 4, 6], [2, 4, 1], [6, 4], [8]], + "size_splits": [[2, 2], [1, 3], [4, 2], [5, 3], + [-1, 1], [-1, 2], [-1, 4]], + "axis": [0, 1, 2, 3, -4, -3, -2, -1], + }] + + def build_graph(parameters): + input_tensor = tf.placeholder( + dtype=tf.float32, name="input", shape=parameters["input_shape"]) + out = tf.split(input_tensor, parameters["size_splits"], parameters["axis"]) + return [input_tensor], [out[0]] + + def build_inputs(parameters, sess, inputs, outputs): + values = [create_tensor_data(np.float32, parameters["input_shape"])] + return values, sess.run(outputs, feed_dict=dict(zip(inputs, values))) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + + def make_concat_tests(zip_path): """Make a set of tests to do concatenation.""" @@ -2468,6 +2610,32 @@ def make_strided_slice_1d_exhaustive_tests(zip_path): _make_strided_slice_tests(zip_path, test_parameters) +def make_strided_slice_buggy_tests(zip_path): + """Make a set of tests to show strided_slice yields incorrect results.""" + + test_parameters = [{ + "unused_iteration_counter": [1], + }] + + def build_graph(parameters): + """Build the strided_slice op testing graph.""" + del parameters + input_values = tf.placeholder(dtype=tf.float32, shape=[4, 2]) + data = tf.constant([[0, 1, 2, 3], + [4, 5, 6, 7], + [8, 9, 10, 11], + [12, 13, 14, 15]], tf.float32) + return [input_values], [input_values + data[:, :2]] + + def build_inputs(parameters, sess, inputs, outputs): + del parameters + input_values = np.zeros([4, 2], dtype=np.float32) + return [input_values], sess.run( + outputs, feed_dict={inputs[0]: input_values}) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + + def make_lstm_tests(zip_path): """Make a set of tests to do basic Lstm cell.""" @@ -3121,7 +3289,7 @@ def make_transpose_conv_tests(zip_path): def make_tile_tests(zip_path): """Make a set of tests to do tile.""" test_parameters = [{ - "input_dtype": [tf.float32, tf.int32], + "input_dtype": [tf.float32, tf.int32, tf.bool], "input_shape": [[3, 2, 1], [2, 2, 2]], "multiplier_dtype": [tf.int32, tf.int64], "multiplier_shape": [[3]] @@ -3143,8 +3311,10 @@ def make_tile_tests(zip_path): def build_inputs(parameters, sess, inputs, outputs): input_value = create_tensor_data(parameters["input_dtype"], parameters["input_shape"]) - multipliers_value = create_tensor_data(parameters["multiplier_dtype"], - parameters["multiplier_shape"]) + multipliers_value = create_tensor_data( + parameters["multiplier_dtype"], + parameters["multiplier_shape"], + min_value=0) return [input_value, multipliers_value], sess.run( outputs, feed_dict={ @@ -3365,6 +3535,36 @@ def make_range_tests(zip_path): make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) +def make_fill_tests(zip_path): + """Make a set of tests to do fill.""" + + test_parameters = [{ + "dims_dtype": [tf.int32, tf.int64], + "dims_shape": [[], [1], [3], [3, 3]], + "value_dtype": [tf.int32, tf.int64, tf.float32], + }] + + def build_graph(parameters): + """Build the fill op testing graph.""" + input1 = tf.placeholder( + dtype=parameters["dims_dtype"], + name="dims", + shape=parameters["dims_shape"]) + input2 = tf.placeholder( + dtype=parameters["value_dtype"], name="value", shape=[]) + out = tf.fill(input1, input2) + return [input1, input2], [out] + + def build_inputs(parameters, sess, inputs, outputs): + input1 = create_tensor_data(parameters["dims_dtype"], + parameters["dims_shape"], 1) + input2 = create_scalar_data(parameters["value_dtype"]) + return [input1, input2], sess.run( + outputs, feed_dict=dict(zip(inputs, [input1, input2]))) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + + def _make_logical_tests(op): """Make a set of tests to do logical operations.""" @@ -3416,6 +3616,141 @@ def make_logical_xor_tests(zip_path): return _make_logical_tests(tf.logical_xor)(zip_path) +def make_mirror_pad_tests(zip_path): + """Make a set of tests to do mirror_pad.""" + + test_parameters = [ + { + "input_shape": [[2, 3]], + "padding_matrix": [[[1, 1], [2, 1]]], + "mode": ["REFLECT"], + "type": ["const"] + }, + { + "input_shape": [[2, 3]], + "padding_matrix": [[[1, 1], [1, 1]]], + "mode": ["REFLECT"], + "type": ["const"] + }, + { + "input_shape": [[2, 3]], + "padding_matrix": [[[1, 1], [2, 1]]], + "mode": ["SYMMETRIC"], + "type": ["placeholder"] + }, + { + "input_shape": [[2, 3]], + "padding_matrix": [[[1, 1], [2, 1]]], + "mode": ["REFLECT"], + "type": ["placeholder"] + }, + { + "input_shape": [[3]], + "padding_matrix": [[[0, 2]]], + "mode": ["SYMMETRIC"], + "type": ["placeholder"] + }, + { + "input_shape": [[3]], + "padding_matrix": [[[0, 2]]], + "mode": ["SYMMETRIC"], + "type": ["const"] + }, + { + "input_shape": [[3]], + "padding_matrix": [[[0, 2]]], + "mode": ["REFLECT"], + "type": ["const"] + }, + ] + + def build_graph(parameters): + """Build the graph for the test case.""" + + input_tensor = tf.placeholder( + dtype=tf.int32, name="input", shape=parameters["input_shape"]) + if parameters["type"] != "const": + padding_matrix = tf.placeholder( + dtype=tf.int32, + name="padding", + shape=[len(parameters["input_shape"]), 2]) + input_tensors = [input_tensor, padding_matrix] + else: + padding_matrix = tf.constant(np.array(parameters["padding_matrix"])) + input_tensors = [input_tensor] + output = tf.pad( + input_tensor, paddings=padding_matrix, mode=parameters["mode"]) + + return input_tensors, [output] + + def build_inputs(parameters, sess, inputs, outputs): + input_values = [create_tensor_data(tf.int32, parameters["input_shape"])] + if parameters["type"] != "const": + input_values.append(np.array(parameters["padding_matrix"])) + return input_values, sess.run( + outputs, feed_dict=dict(zip(inputs, input_values))) + + make_zip_of_tests( + zip_path, + test_parameters, + build_graph, + build_inputs, + expected_tf_success=7) + + +def make_unroll_batch_matmul_tests(zip_path): + """Make a set of tests to test unroll_batch_matmul.""" + + test_parameters = [{"dtype": [tf.float32], "shape": [[(2, 2, 3), (2, 3, 2)]]}] + + def build_graph(parameters): + """Build the batch_matmul op testing graph.""" + input_tensor1 = tf.placeholder( + dtype=parameters["dtype"], shape=parameters["shape"][0]) + input_tensor2 = tf.placeholder( + dtype=parameters["dtype"], shape=parameters["shape"][1]) + # Should be unrolled and replaced with fully_connected ops in the end. + out = tf.matmul(input_tensor1, input_tensor2) + return [input_tensor1, input_tensor2], [out] + + def build_inputs(parameters, sess, inputs, outputs): + input_value1 = create_tensor_data( + parameters["dtype"], shape=parameters["shape"][0]) + input_value2 = create_tensor_data( + parameters["dtype"], shape=parameters["shape"][1]) + return [input_value1, input_value2], sess.run( + outputs, feed_dict=dict(zip(inputs, [input_value1, input_value2]))) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + + +def make_placeholder_with_default_tests(zip_path): + """Make a set of tests to test placeholder_with_default.""" + + test_parameters = [{ + "dtype": [tf.float32, tf.int32, tf.int64], + }] + + def build_graph(parameters): + """Build the placeholder_with_default testing graph.""" + const_node = tf.constant( + [1, 2, 2, 0], shape=[2, 2], dtype=parameters["dtype"]) + input_tensor = tf.placeholder_with_default( + const_node, shape=[2, 2], name="input") + out = tf.equal(input_tensor, const_node, name="output") + + return [input_tensor], [out] + + def build_inputs(parameters, sess, inputs, outputs): + numpy_type = _TF_TYPE_INFO[parameters["dtype"]][0] + input_value = np.array([[1, 0], [2, 1]], numpy_type) + return [input_value], sess.run( + outputs, feed_dict=dict(zip(inputs, [input_value]))) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs, + expected_tf_success=3) + + # Toco binary path provided by the generate rule. bin_path = None diff --git a/tensorflow/lite/testing/generated_examples_zip_test.cc b/tensorflow/lite/testing/generated_examples_zip_test.cc index aedea52065..91a4851fb0 100644 --- a/tensorflow/lite/testing/generated_examples_zip_test.cc +++ b/tensorflow/lite/testing/generated_examples_zip_test.cc @@ -101,6 +101,10 @@ std::map kBrokenTests = { {R"(^\/mul.*dtype=tf\.int64)", "119126484"}, {R"(^\/add.*dtype=tf\.int64)", "119126484"}, {R"(^\/floor_div.*dtype=tf\.int64)", "119126484"}, + {R"(^\/squared_difference.*dtype=tf\.int64)", "119126484"}, + + // Strided Slice chooses the wrong dimension. + {R"(^\/strided_slice_buggy)", "119786029"}, }; // Allows test data to be unarchived into a temporary directory and makes diff --git a/tensorflow/lite/testing/tflite_driver.cc b/tensorflow/lite/testing/tflite_driver.cc index 3a0febb780..27e3a3770b 100644 --- a/tensorflow/lite/testing/tflite_driver.cc +++ b/tensorflow/lite/testing/tflite_driver.cc @@ -147,9 +147,10 @@ TfLiteDriver::TfLiteDriver(bool use_nnapi, const string& delegate_name) } TfLiteDriver::~TfLiteDriver() { - for (TfLiteTensor* t : tensors_to_deallocate_) { - free(t->data.raw); + for (auto t : tensors_to_deallocate_) { + DeallocateStringTensor(t.second); } + interpreter_.reset(); } void TfLiteDriver::AllocateTensors() { @@ -242,12 +243,10 @@ void TfLiteDriver::SetInput(int id, const string& csv_values) { case kTfLiteString: { string s = absl::HexStringToBytes(csv_values); - tensor->data.raw = reinterpret_cast(malloc(s.size())); - tensor->bytes = s.size(); + DeallocateStringTensor(tensors_to_deallocate_[id]); + AllocateStringTensor(id, s.size(), tensor); memcpy(tensor->data.raw, s.data(), s.size()); - // We must remember to free the memory we allocated above. - tensors_to_deallocate_.push_back(tensor); break; } default: diff --git a/tensorflow/lite/testing/tflite_driver.h b/tensorflow/lite/testing/tflite_driver.h index d8b40565ba..1da0533c57 100644 --- a/tensorflow/lite/testing/tflite_driver.h +++ b/tensorflow/lite/testing/tflite_driver.h @@ -49,6 +49,18 @@ class TfLiteDriver : public TestRunner { string ReadOutput(int id) override { return "no-op"; } private: + void DeallocateStringTensor(TfLiteTensor* t) { + if (t) { + free(t->data.raw); + t->data.raw = nullptr; + } + } + void AllocateStringTensor(int id, size_t num_bytes, TfLiteTensor* t) { + t->data.raw = reinterpret_cast(malloc(num_bytes)); + t->bytes = num_bytes; + tensors_to_deallocate_[id] = t; + } + void ResetLSTMStateTensors(); class Expectation; @@ -59,7 +71,7 @@ class TfLiteDriver : public TestRunner { std::unique_ptr interpreter_; std::map> expected_output_; bool must_allocate_tensors_ = true; - std::vector tensors_to_deallocate_; + std::map tensors_to_deallocate_; }; } // namespace testing diff --git a/tensorflow/lite/toco/BUILD b/tensorflow/lite/toco/BUILD index 1430287444..82aa1f557e 100644 --- a/tensorflow/lite/toco/BUILD +++ b/tensorflow/lite/toco/BUILD @@ -395,6 +395,28 @@ tf_cc_test( # :toco is the main public command-line tool exposing the functionality # of the :toco_tooling library. +cc_library( + name = "toco_convert", + srcs = ["toco_convert.cc"], + hdrs = ["toco_convert.h"], + visibility = ["//visibility:public"], + deps = [ + ":model", + ":model_cmdline_flags", + ":model_flags_proto_cc", + ":toco_cmdline_flags", + ":toco_flags_proto_cc", + ":toco_port", + ":toco_tooling", + ":types_proto_cc", + "@com_google_absl//absl/strings", + "//tensorflow/core:lib", + # We cannot embed the core:ops dependency directly into :toco_tooling as + # it can conflict with downstream deps when toco is used as a library. + "//tensorflow/core:ops", + ], +) + tf_cc_binary( name = "toco", srcs = ["toco.cc"], @@ -404,6 +426,7 @@ tf_cc_binary( ":model_cmdline_flags", ":model_flags_proto_cc", ":toco_cmdline_flags", + ":toco_convert", ":toco_flags_proto_cc", ":toco_port", ":toco_tooling", @@ -416,6 +439,29 @@ tf_cc_binary( ], ) +tf_cc_test( + name = "toco_convert_test", + srcs = ["toco_convert_test.cc"], + visibility = ["//visibility:public"], + deps = [ + ":model", + ":model_cmdline_flags", + ":model_flags_proto_cc", + ":toco_cmdline_flags", + ":toco_convert", + ":toco_flags_proto_cc", + ":toco_port", + ":toco_tooling", + ":types_proto_cc", + "@com_google_googletest//:gtest_main", + "@com_google_absl//absl/strings", + "//tensorflow/core:lib", + # We cannot embed the core:ops dependency directly into :toco_tooling as + # it can conflict with downstream deps when toco is used as a library. + "//tensorflow/core:ops", + ], +) + tf_cc_test( name = "toco_port_test", srcs = ["toco_port_test.cc"], diff --git a/tensorflow/lite/toco/README.md b/tensorflow/lite/toco/README.md index 91f6f618a3..fe98a90b38 100644 --- a/tensorflow/lite/toco/README.md +++ b/tensorflow/lite/toco/README.md @@ -8,9 +8,9 @@ the usage documentation. Usage information is given in these documents: -* [Command-line glossary](g3doc/cmdline_reference.md) -* [Command-line examples](g3doc/cmdline_examples.md) -* [Python API examples](g3doc/python_api.md) +* [Command-line glossary](../g3doc/convert/cmdline_reference.md) +* [Command-line examples](../g3doc/convert/cmdline_examples.md) +* [Python API examples](../g3doc/convert/python_api.md) ## Where the converter fits in the TensorFlow landscape @@ -26,4 +26,4 @@ to client devices, generally mobile devices, where the TensorFlow Lite interpreter handles them on-device. This flow is represented in the diagram below. -![drawing](g3doc/toco_landscape.svg) +![drawing](../g3doc/images/convert/workflow.svg) diff --git a/tensorflow/lite/toco/export_tensorflow.cc b/tensorflow/lite/toco/export_tensorflow.cc index 1752745aae..9fff001552 100644 --- a/tensorflow/lite/toco/export_tensorflow.cc +++ b/tensorflow/lite/toco/export_tensorflow.cc @@ -48,7 +48,8 @@ using tensorflow::TensorProto; namespace toco { namespace { -tensorflow::DataType GetTensorFlowDataType(ArrayDataType data_type) { +tensorflow::DataType GetTensorFlowDataType(ArrayDataType data_type, + const string& error_location) { switch (data_type) { case ArrayDataType::kBool: return tensorflow::DT_BOOL; @@ -66,14 +67,21 @@ tensorflow::DataType GetTensorFlowDataType(ArrayDataType data_type) { return tensorflow::DT_COMPLEX64; default: case ArrayDataType::kNone: - LOG(FATAL) << "Unsupported data type: " << static_cast(data_type); + LOG(FATAL) << "Unsupported data type '" << ArrayDataTypeName(data_type) + << "' in " << error_location; return tensorflow::DT_INVALID; } } +tensorflow::DataType GetTensorFlowDataTypeForOp(ArrayDataType data_type, + const string& op_name) { + return GetTensorFlowDataType(data_type, "op '" + op_name + "'"); +} + tensorflow::DataType GetTensorFlowDataType(const Model& model, const string& array_name) { - return GetTensorFlowDataType(model.GetArray(array_name).data_type); + return GetTensorFlowDataType(model.GetArray(array_name).data_type, + "array '" + array_name + "'"); } // TensorFlow sometimes forbids what it calls "legacy scalars", @@ -1150,6 +1158,29 @@ void ConvertSplitOperator(const Model& model, tensorflow_graph); } +void ConvertSplitVOperator(const Model& model, + const TensorFlowSplitVOperator& src_op, + GraphDef* tensorflow_graph) { + tensorflow::NodeDef* split_v_op = tensorflow_graph->add_node(); + split_v_op->set_op("SplitV"); + split_v_op->set_name(src_op.outputs[0]); + for (const auto& input : src_op.inputs) { + *split_v_op->add_input() = input; + } + (*split_v_op->mutable_attr())["T"].set_type( + GetTensorFlowDataType(model, src_op.inputs[0])); + (*split_v_op->mutable_attr())["num_split"].set_i(src_op.num_split); + const auto& split_dim_array = model.GetArray(src_op.inputs[1]); + CHECK(split_dim_array.buffer); + CHECK(split_dim_array.data_type == ArrayDataType::kInt32); + const auto& split_dim_data = + split_dim_array.GetBuffer().data; + CHECK_EQ(split_dim_data.size(), 1); + const int split_dim = split_dim_data[0]; + CreateDummyConcatDimTensorConst(src_op.inputs[0], split_dim, + tensorflow_graph); +} + void ConvertCastOperator(const Model& model, const CastOperator& src_op, GraphDef* tensorflow_graph) { tensorflow::NodeDef* cast_op = tensorflow_graph->add_node(); @@ -1285,7 +1316,7 @@ void ConvertRangeOperator(const Model& model, const RangeOperator& src_op, *range_op->add_input() = src_op.inputs[1]; *range_op->add_input() = src_op.inputs[2]; (*range_op->mutable_attr())["Tidx"].set_type( - GetTensorFlowDataType(src_op.dtype)); + GetTensorFlowDataTypeForOp(src_op.dtype, /*op_name=*/src_op.outputs[0])); } void ConvertPackOperator(const Model& model, const PackOperator& src_op, @@ -1298,7 +1329,8 @@ void ConvertPackOperator(const Model& model, const PackOperator& src_op, } (*pack_op->mutable_attr())["axis"].set_i(src_op.axis); (*pack_op->mutable_attr())["N"].set_i(src_op.inputs.size()); - (*pack_op->mutable_attr())["T"].set_type(GetTensorFlowDataType(src_op.dtype)); + (*pack_op->mutable_attr())["T"].set_type( + GetTensorFlowDataTypeForOp(src_op.dtype, src_op.outputs[0])); } void ConvertFillOperator(const Model& model, const FillOperator& src_op, @@ -1887,7 +1919,7 @@ void ConvertRandomUniformOperator(const Model& model, GetTensorFlowDataType(model, src_op.inputs[0]); (*new_op->mutable_attr())["T"].set_type(shape_type); (*new_op->mutable_attr())["dtype"].set_type( - GetTensorFlowDataType(src_op.dtype)); + GetTensorFlowDataTypeForOp(src_op.dtype, src_op.outputs[0])); (*new_op->mutable_attr())["seed"].set_i(src_op.seed); (*new_op->mutable_attr())["seed2"].set_i(src_op.seed2); } @@ -2124,6 +2156,10 @@ void ConvertOperator(const Model& model, const Operator& src_op, ConvertSplitOperator(model, static_cast(src_op), tensorflow_graph); + } else if (src_op.type == OperatorType::kSplitV) { + ConvertSplitVOperator(model, + static_cast(src_op), + tensorflow_graph); } else if (src_op.type == OperatorType::kFakeQuant) { ConvertFakeQuantOperator(static_cast(src_op), tensorflow_graph); diff --git a/tensorflow/lite/toco/graph_transformations/fuse_binary_into_following_affine.cc b/tensorflow/lite/toco/graph_transformations/fuse_binary_into_following_affine.cc index 6b4765b23c..436b639253 100644 --- a/tensorflow/lite/toco/graph_transformations/fuse_binary_into_following_affine.cc +++ b/tensorflow/lite/toco/graph_transformations/fuse_binary_into_following_affine.cc @@ -221,9 +221,8 @@ void FuseMulOrDivParamsIntoFollowingAffine(Model* model, Operator* following_op, Operator* following_op = GetOpWithInput(*model, binary_op->outputs[0]); if (!following_op) { - AddMessageF( - "Not fusing %s because it is not consumed by exactly one other op", - LogName(*binary_op)); + AddMessageF("Not fusing %s because it is not consumed by any op", + LogName(*binary_op)); return ::tensorflow::Status::OK(); } @@ -288,7 +287,10 @@ void FuseMulOrDivParamsIntoFollowingAffine(Model* model, Operator* following_op, AddMessageF("Fusing %s into the following %s", LogName(*binary_op), LogName(*following_op)); - model->EraseArray(binary_op->outputs[0]); + if (CountOpsWithInput(*model, binary_op->outputs[0]) == 1) { + model->EraseArray(binary_op->outputs[0]); + } + following_op->inputs[0] = binary_op->inputs[index_of_variable_input]; const auto& old_constant_param_name = binary_op->inputs[index_of_constant_input]; diff --git a/tensorflow/lite/toco/graph_transformations/propagate_array_data_types.cc b/tensorflow/lite/toco/graph_transformations/propagate_array_data_types.cc index 9a458dccb9..cbae6610d7 100644 --- a/tensorflow/lite/toco/graph_transformations/propagate_array_data_types.cc +++ b/tensorflow/lite/toco/graph_transformations/propagate_array_data_types.cc @@ -86,6 +86,13 @@ void SetDataTypeForAllOutputs(Model* model, Operator* op, SetDataTypeForAllOutputs(model, op, data_type); break; } + case OperatorType::kSplitV: { + // These operators produce output with the same type as its 1st input + CHECK_GE(op->inputs.size(), 3); + const ArrayDataType data_type = model->GetArray(op->inputs[0]).data_type; + SetDataTypeForAllOutputs(model, op, data_type); + break; + } case OperatorType::kTransposeConv: { // These operators produce an output with the same type as their 3rd input CHECK_GE(op->inputs.size(), 3); diff --git a/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc b/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc index 78ea54e452..0e653f08a0 100644 --- a/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc +++ b/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc @@ -15,6 +15,7 @@ limitations under the License. #include #include #include +#include #include #include #include @@ -786,6 +787,97 @@ void ProcessTensorFlowSplitOperator(Model* model, TensorFlowSplitOperator* op) { } } +void ProcessTensorFlowSplitVOperator(Model* model, + TensorFlowSplitVOperator* op) { + CHECK_EQ(op->inputs.size(), 3); + + const auto& input_array = model->GetArray(op->inputs[0]); + // Yield until input dims have been resolved. + if (!input_array.has_shape()) { + return; + } + const Shape& input_shape = input_array.shape(); + + // Yield until size_splits is constant. + if (!IsConstantParameterArray(*model, op->inputs[1])) { + return; + } + const auto& size_array = model->GetArray(op->inputs[1]); + // Yield until size_splits dims have been resolved. + if (!size_array.has_shape()) { + return; + } + const Shape& size_shape = size_array.shape(); + + CHECK(size_array.data_type == ArrayDataType::kInt32 || + size_array.data_type == ArrayDataType::kInt64) + << "size_splits must be int32, int64"; + CHECK_EQ(size_shape.dimensions_count(), 1) << "size_splits must be 1-D"; + + std::vector size_splits_vector; + if (size_array.data_type == ArrayDataType::kInt32) { + for (const auto each_size : + size_array.GetBuffer().data) { + size_splits_vector.push_back(each_size); + } + } else { + size_splits_vector = size_array.GetBuffer().data; + } + + // Yield until axis is constant. + if (!IsConstantParameterArray(*model, op->inputs[2])) { + return; + } + const auto& axis_array = model->GetArray(op->inputs[2]); + // Yield until axis dims have been resolved. + if (!axis_array.has_shape()) { + return; + } + + CHECK(axis_array.data_type == ArrayDataType::kInt32) + << "Axis array must be int32."; + CHECK_EQ(RequiredBufferSizeForShape(axis_array.shape()), 1) + << "Axis array must be scalar."; + + int axis = axis_array.GetBuffer().data[0]; + if (axis < 0) { + axis += input_shape.dimensions_count(); + } + + CHECK_EQ(op->num_split, size_splits_vector.size()); + + int64_t minus_one_count = 0, size_splits_sum = 0; + for (auto size : size_splits_vector) { + if (size == -1) { + ++minus_one_count; + } else { + size_splits_sum += size; + } + } + + const int input_size = input_shape.dims(axis); + + CHECK_LE(minus_one_count, 1) << "size_splits can contain at most one -1."; + + if (minus_one_count == 1) { + CHECK_LE(size_splits_sum, input_size); + auto iter = + std::find(size_splits_vector.begin(), size_splits_vector.end(), -1); + *iter = input_size - size_splits_sum; + } else { + CHECK_EQ(size_splits_sum, input_size); + } + + CHECK_EQ(op->outputs.size(), op->num_split); + + for (int i = 0; i < op->outputs.size(); ++i) { + const auto& output = op->outputs[i]; + Shape output_shape = input_shape; + (*output_shape.mutable_dims())[axis] = size_splits_vector.at(i); + model->GetArray(output).copy_shape(output_shape); + } +} + void ProcessAveragePoolOperator(Model* model, AveragePoolOperator* op) { const string& input_name = op->inputs[0]; const auto& input_array = model->GetArray(input_name); @@ -1691,6 +1783,51 @@ void ProcessUnpackOperator(Model* model, UnpackOperator* op) { } } +void ProcessMirrorPadOperator(Model* model, MirrorPadOperator* op) { + CHECK_EQ(op->inputs.size(), 2); + const auto& input_array = model->GetArray(op->inputs[0]); + const auto& padding_matrix = model->GetArray(op->inputs[1]); + + // Yield until input dims have been resolved. + if (!input_array.has_shape()) { + return; + } + + auto& output_array = model->GetArray(op->outputs[0]); + // If output already computed or padding matrix is non + // const then return. + if (output_array.has_shape() || + !IsConstantParameterArray(*model, op->inputs[1])) { + return; + } + Shape output_shape = input_array.shape(); + std::vector& dims = *output_shape.mutable_dims(); + + std::vector padding; + if (padding_matrix.data_type == ArrayDataType::kInt32) { + const auto& data = padding_matrix.GetBuffer().data; + for (auto elem : data) { + padding.push_back(static_cast(elem)); + } + } else if (padding_matrix.data_type == ArrayDataType::kInt64) { + const auto& data = padding_matrix.GetBuffer().data; + for (auto elem : data) { + padding.push_back(elem); + } + } else { + CHECK(padding_matrix.data_type == ArrayDataType::kInt64 || + padding_matrix.data_type == ArrayDataType::kInt32); + } + CHECK_EQ(padding_matrix.shape().dimensions_count(), 2); + CHECK_EQ(input_array.shape().dimensions_count(), + padding_matrix.shape().dims(0)); + for (int i = 0; i < input_array.shape().dimensions_count(); ++i) { + dims[i] += padding[i * 2] + padding[i * 2 + 1]; + } + + output_array.copy_shape(output_shape); +} + } // namespace ::tensorflow::Status PropagateFixedSizes::Run(Model* model, @@ -1707,6 +1844,7 @@ void ProcessUnpackOperator(Model* model, UnpackOperator* op) { } switch (op->type) { + case OperatorType::kAbs: case OperatorType::kBatchNormalization: case OperatorType::kL2Normalization: case OperatorType::kDequantize: @@ -1714,6 +1852,7 @@ void ProcessUnpackOperator(Model* model, UnpackOperator* op) { case OperatorType::kRelu1: case OperatorType::kRelu6: case OperatorType::kPRelu: + case OperatorType::kLeakyRelu: case OperatorType::kSoftmax: case OperatorType::kLogSoftmax: case OperatorType::kLog: @@ -1759,6 +1898,7 @@ void ProcessUnpackOperator(Model* model, UnpackOperator* op) { case OperatorType::kEqual: case OperatorType::kNotEqual: case OperatorType::kPow: + case OperatorType::kSquaredDifference: ProcessSimpleBinaryOperator(model, op); break; case OperatorType::kAddN: @@ -1834,6 +1974,10 @@ void ProcessUnpackOperator(Model* model, UnpackOperator* op) { ProcessTensorFlowSplitOperator(model, static_cast(op)); break; + case OperatorType::kSplitV: + ProcessTensorFlowSplitVOperator( + model, static_cast(op)); + break; case OperatorType::kSqueeze: ProcessSqueezeOperator(model, static_cast(op)); break; @@ -1956,6 +2100,9 @@ void ProcessUnpackOperator(Model* model, UnpackOperator* op) { case OperatorType::kUnpack: ProcessUnpackOperator(model, static_cast(op)); break; + case OperatorType::kMirrorPad: + ProcessMirrorPadOperator(model, static_cast(op)); + break; default: // Unimplemented, another graph transformation should drop it. LOG(FATAL) << "Unhandled operator type " << OperatorTypeName(op->type); diff --git a/tensorflow/lite/toco/graph_transformations/quantize.cc b/tensorflow/lite/toco/graph_transformations/quantize.cc index e28b7288f0..1146078c30 100644 --- a/tensorflow/lite/toco/graph_transformations/quantize.cc +++ b/tensorflow/lite/toco/graph_transformations/quantize.cc @@ -64,7 +64,8 @@ bool SupportsQuantization(const Operator& op) { type == OperatorType::kRelu1 || type == OperatorType::kRelu6 || type == OperatorType::kShape || type == OperatorType::kExpandDims || type == OperatorType::kPack || type == OperatorType::kTopK_V2 || - type == OperatorType::kResizeNearestNeighbor; + type == OperatorType::kResizeNearestNeighbor || + type == OperatorType::kPRelu; } // The quantized op allows output arrays of type float using @@ -360,7 +361,7 @@ bool ChooseQuantizationForOperatorOutput( op.type == OperatorType::kSpaceToDepth || op.type == OperatorType::kReshape || op.type == OperatorType::kSplit || op.type == OperatorType::kRelu || op.type == OperatorType::kRelu1 || - op.type == OperatorType::kRelu6) { + op.type == OperatorType::kRelu6 || op.type == OperatorType::kPRelu) { int data_input_index = 0; if (op.type == OperatorType::kSplit) { data_input_index = 1; diff --git a/tensorflow/lite/toco/graph_transformations/resolve_constant_gather.cc b/tensorflow/lite/toco/graph_transformations/resolve_constant_gather.cc index 1149930131..c72135923e 100644 --- a/tensorflow/lite/toco/graph_transformations/resolve_constant_gather.cc +++ b/tensorflow/lite/toco/graph_transformations/resolve_constant_gather.cc @@ -47,6 +47,10 @@ inline void Gather(const Array& input_array, int input_rank, stride *= input_shape.dims(i); } + // Let's make sure we have enough space for all element in the memcpy() + // below, which writes 'stride' elements startng at 'i * stride'. + CHECK_EQ(stride * coords_shape.dims(0), output_data.size()); + for (int i = 0; i < coords_shape.dims(0); ++i) { DCHECK_GE(coords_data[i], 0); DCHECK_LT(coords_data[i], input_shape.dims(rev_input_rank)); diff --git a/tensorflow/lite/toco/graph_transformations/resolve_reduce_attributes.cc b/tensorflow/lite/toco/graph_transformations/resolve_reduce_attributes.cc index ea5d33009b..9ceba45e93 100644 --- a/tensorflow/lite/toco/graph_transformations/resolve_reduce_attributes.cc +++ b/tensorflow/lite/toco/graph_transformations/resolve_reduce_attributes.cc @@ -35,6 +35,11 @@ bool ResolveAttributes(Model* model, T* op) { const Array& indices_array = model->GetArray(op->inputs[1]); if (!indices_array.has_shape()) return false; + + // It is ok for indices_array to have a shape for an empty tensor. In that + // case, we don't bother setting 'axis'. + if (indices_array.buffer->Length() == 0) return false; + op->axis = indices_array.GetBuffer().data; return true; } diff --git a/tensorflow/lite/toco/graph_transformations/unroll_batch_matmul.cc b/tensorflow/lite/toco/graph_transformations/unroll_batch_matmul.cc index d59954fc74..41a735394d 100644 --- a/tensorflow/lite/toco/graph_transformations/unroll_batch_matmul.cc +++ b/tensorflow/lite/toco/graph_transformations/unroll_batch_matmul.cc @@ -117,7 +117,8 @@ namespace toco { auto* slice_b_op = new SliceOperator; slice_b_op->inputs = { batch_op->inputs[1], - CreateInt32Array(model, batch_name + "/slice_b/slice/begin", {0, 0, 0}), + CreateInt32Array(model, batch_name + "/slice_b/slice/begin", + {batch, 0, 0}), CreateInt32Array( model, batch_name + "/slice_b/slice/size", {1, input_array_b.shape().dims(1), input_array_b.shape().dims(2)}), diff --git a/tensorflow/lite/toco/import_tensorflow.cc b/tensorflow/lite/toco/import_tensorflow.cc index 96f3c6a6ab..0b2f810394 100644 --- a/tensorflow/lite/toco/import_tensorflow.cc +++ b/tensorflow/lite/toco/import_tensorflow.cc @@ -935,6 +935,25 @@ tensorflow::Status ConvertSplitOperator( return tensorflow::Status::OK(); } +tensorflow::Status ConvertSplitVOperator( + const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, + Model* model) { + CHECK_EQ(node.op(), "SplitV"); + TF_QCHECK_OK(CheckInputsCount(node, tf_import_flags, 3)); + auto* op = new TensorFlowSplitVOperator; + op->inputs.push_back(node.input(0)); + op->inputs.push_back(node.input(1)); + op->inputs.push_back(node.input(2)); + const int num_split = GetIntAttr(node, "num_split"); + op->outputs.push_back(node.name()); + for (int i = 1; i < num_split; i++) { + op->outputs.push_back(absl::StrCat(node.name(), ":", i)); + } + op->num_split = num_split; + model->operators.emplace_back(op); + return tensorflow::Status::OK(); +} + tensorflow::Status ConvertSwitchOperator( const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, Model* model) { @@ -1134,6 +1153,31 @@ tensorflow::Status ConvertConcatOperator( return tensorflow::Status::OK(); } +tensorflow::Status ConvertMirrorPadOperator( + const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, + Model* model) { + if (node.op() != "MirrorPad") { + LOG(FATAL) << "Expected MirrorPad."; + } + const int num_inputs = GetInputsCount(node, tf_import_flags); + CHECK_EQ(num_inputs, 2); + auto* op = new MirrorPadOperator; + for (int i = 0; i < num_inputs; ++i) { + op->inputs.push_back(node.input(i)); + } + op->outputs.push_back(node.name()); + const auto mode = GetStringAttr(node, "mode"); + if (mode == "REFLECT") { + op->mode = toco::MirrorPadMode::kReflect; + } else if (mode == "SYMMETRIC") { + op->mode = toco::MirrorPadMode::kSymmetric; + } + + model->operators.emplace_back(op); + + return tensorflow::Status::OK(); +} + static constexpr int kAnyNumInputs = -1; enum FlexSupport { kFlexOk, kFlexNotOk }; @@ -1221,7 +1265,7 @@ void GetOutputNamesFromNodeDef(const NodeDef& node, void GetOutputTypesFromNodeDef(const NodeDef& node, const tensorflow::OpDef& op_def, TensorFlowUnsupportedOperator* op) { - // The the given type to the op, or clear the types if invalid. + // The given type to the op, or clear the types if invalid. auto add_type = [&node, op](tensorflow::DataType type) { if (type == tensorflow::DT_INVALID) { LOG(WARNING) << "Op node missing output type attribute: " << node.name(); @@ -2012,13 +2056,13 @@ bool InlineAllFunctions(GraphDef* graphdef) { tensorflow::SessionOptions options; auto* device_count = options.config.mutable_device_count(); device_count->insert({"CPU", 1}); - std::vector devices; + std::vector> devices; TF_CHECK_OK(tensorflow::DeviceFactory::AddDevices( options, "/job:localhost/replica:0/task:0", &devices)); tensorflow::FunctionLibraryDefinition fld(tensorflow::OpRegistry::Global(), graphdef_copy.library()); - tensorflow::DeviceMgr device_mgr(devices); + tensorflow::DeviceMgr device_mgr(std::move(devices)); tensorflow::OptimizerOptions o_opts; tensorflow::ProcessFunctionLibraryRuntime pflr( &device_mgr, tensorflow::Env::Default(), TF_GRAPH_DEF_VERSION, &fld, @@ -2220,6 +2264,21 @@ tensorflow::Status ConvertUnidirectionalSequenceLstm( return tensorflow::Status::OK(); } +tensorflow::Status ConvertLeakyReluOperator( + const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, + Model* model) { + CHECK_EQ(node.op(), "LeakyRelu"); + TF_QCHECK_OK(CheckInputsCount(node, tf_import_flags, 1)); + CHECK_EQ(GetDataTypeAttr(node, "T"), DT_FLOAT); + const auto& input_name = node.input(0); + auto* op = new LeakyReluOperator; + op->inputs.push_back(input_name); + op->outputs.push_back(node.name()); + op->alpha = GetFloatAttr(node, "alpha"); + model->operators.emplace_back(op); + return tensorflow::Status::OK(); +} + } // namespace namespace internal { @@ -2233,12 +2292,14 @@ ConverterMapType GetTensorFlowNodeConverterMapForFlex() { return std::unordered_map({ // We need to let TCO convert Placeholder information into // array data, so that the data types are correct. + {"LegacyFedInput", ConvertPlaceholderOperator}, {"Placeholder", ConvertPlaceholderOperator}, }); } ConverterMapType GetTensorFlowNodeConverterMap() { return std::unordered_map({ + {"Abs", ConvertSimpleOperator}, {"Add", ConvertSimpleOperator}, {"AddN", ConvertSimpleOperatorFlexOk}, {"All", ConvertSimpleOperator}, @@ -2282,6 +2343,7 @@ ConverterMapType GetTensorFlowNodeConverterMap() { ConvertSimpleOperator}, {"Identity", ConvertIdentityOperator}, {"LRN", ConvertLRNOperator}, + {"LeakyRelu", ConvertLeakyReluOperator}, {"LegacyFedInput", ConvertPlaceholderOperator}, {"Less", ConvertSimpleOperator}, {"LessEqual", ConvertSimpleOperator}, @@ -2332,8 +2394,11 @@ ConverterMapType GetTensorFlowNodeConverterMap() { {"SpaceToDepth", ConvertSpaceToDepthOperator}, {"SparseToDense", ConvertSparseToDenseOperator}, {"Split", ConvertSplitOperator}, + {"SplitV", ConvertSplitVOperator}, {"Sqrt", ConvertSimpleOperator}, {"Square", ConvertSimpleOperator}, + {"SquaredDifference", + ConvertSimpleOperator}, {"Squeeze", ConvertSqueezeOperator}, {"StopGradient", ConvertIdentityOperator}, {"StridedSlice", ConvertStridedSliceOperator}, @@ -2349,6 +2414,7 @@ ConverterMapType GetTensorFlowNodeConverterMap() { {"Unpack", ConvertUnpackOperator}, {"ZerosLike", ConvertSimpleOperator}, {"UnidirectionalSequenceLstm", ConvertUnidirectionalSequenceLstm}, + {"MirrorPad", ConvertMirrorPadOperator}, }); } diff --git a/tensorflow/lite/toco/model.h b/tensorflow/lite/toco/model.h index f85e1c2878..f19355968f 100644 --- a/tensorflow/lite/toco/model.h +++ b/tensorflow/lite/toco/model.h @@ -121,8 +121,10 @@ enum class OperatorType : uint8 { kRsqrt, kShape, kSplit, + kSplitV, kSqrt, kSquare, + kSquaredDifference, kSum, kSwitch, kTile, @@ -152,7 +154,10 @@ enum class OperatorType : uint8 { kCTCBeamSearchDecoder, kUnpack, kZerosLike, - kResizeNearestNeighbor + kResizeNearestNeighbor, + kLeakyRelu, + kAbs, + kMirrorPad }; // Helper to deal with TensorFlow arrays using a different ordering of @@ -653,6 +658,17 @@ struct MulOperator : Operator { MulOperator() : Operator(OperatorType::kMul) {} }; +// Element-wise Abs operator: +// x -> abs(x) +// +// Inputs: +// inputs[0]: required: the input array +// +// TensorFlow equivalent: Relu +struct AbsOperator : Operator { + AbsOperator() : Operator(OperatorType::kAbs) {} +}; + // Element-wise Relu operator: // x -> max(0, x) // @@ -699,6 +715,19 @@ struct PReluOperator : Operator { PReluOperator() : Operator(OperatorType::kPRelu) {} }; +// LeakyRelu +// x -> max(x, alpha * x) +// +// Inputs: +// inputs[0]: required: the input array +// +// TensorFlow equivalent: LeakyRelu +struct LeakyReluOperator : Operator { + LeakyReluOperator() : Operator(OperatorType::kLeakyRelu) {} + + float alpha = 0.2f; // 0.2 matches the default value for the TF op attribute. +}; + // Element-wise Logistic operator: // x -> Logistic(x) = 1 / (1 + exp(-x)) // @@ -1289,6 +1318,17 @@ struct TensorFlowSquareOperator : Operator { TensorFlowSquareOperator() : Operator(OperatorType::kSquare) {} }; +// Element-wise squared difference ((x-y)*(x-y)) operator. +// +// Inputs: +// inputs[0]: required: the left-hand side array +// inputs[1]: required: the right-hand side array +// +// TensorFlow equivalent: SquaredDifference +struct SquaredDifferenceOperator : Operator { + SquaredDifferenceOperator() : Operator(OperatorType::kSquaredDifference) {} +}; + // Transposes a tensor. // // By default, this operation performs a regular matrix transpose on 2-D input @@ -1363,6 +1403,12 @@ struct TensorFlowSplitOperator : Operator { int num_split = 0; }; +// TensorFlow SplitV equivalent. Refer to TensorFlow documentation for details. +struct TensorFlowSplitVOperator : Operator { + TensorFlowSplitVOperator() : Operator(OperatorType::kSplitV) {} + int num_split = 0; +}; + // TensorFlow Concat equivalent. Refer to TensorFlow documentation for details. // Not fully supported, just a placeholder to handle TensorFlow graphs and // support graph transformations to other operator types by matching sub-graphs. @@ -1887,6 +1933,23 @@ struct TensorFlowZerosLikeOperator : Operator { TensorFlowZerosLikeOperator() : Operator(OperatorType::kZerosLike) {} }; +enum class MirrorPadMode { kNone, kSymmetric, kReflect }; + +// MirrorPad Operator: +// +// Inputs: +// Inputs[0]: required: input tensor to be padded. +// Inputs[1]: required: 2 Column matrix specifying padding sizes. The number of +// rows must be the same as the rank of the input. +// Inputs[2]: required: REFLECT or SYMMETRIC. +// +// TensorFlow equivalent: MirrorPad. +struct MirrorPadOperator : Operator { + MirrorPadOperator() : Operator(OperatorType::kMirrorPad) {} + // mode is either SYMMETRIC or REFLECT. + MirrorPadMode mode; +}; + // Alloc's are used for transient arrays only. An Alloc specifies which interval // of the "transient_data" workspace buffer passed to inference functions, is to // be used for the transient array at hand. The 'start' and 'end' values are diff --git a/tensorflow/lite/toco/tflite/export.cc b/tensorflow/lite/toco/tflite/export.cc index 489c21295e..8b9448486d 100644 --- a/tensorflow/lite/toco/tflite/export.cc +++ b/tensorflow/lite/toco/tflite/export.cc @@ -126,7 +126,6 @@ OperatorKey::OperatorKey( type_ = builtin_ops.at(name); return; } - // The logic below is all for custom ops or Flex ops. is_custom_op_ = true; type_ = BuiltinOperator_CUSTOM; @@ -332,6 +331,11 @@ Offset>> ExportOperators( std::set* variable_tensor_indices, const ExportParams& params) { variable_tensor_indices->clear(); + auto is_tflite_builtin = [](const BaseOperator* op) { + const auto& tflite_builtins = GetBuiltinOpsMap(); + return (op && tflite_builtins.find(op->name()) != tflite_builtins.end()); + }; + // The operators are in execution order, so we just follow tf.mini order. std::vector> op_vector; for (const auto& op : model.operators) { @@ -360,7 +364,19 @@ Offset>> ExportOperators( auto options = Options::Custom(0); std::vector mutating_input_variables; - if (tflite_op) { + + // It is conceivable that an op is exportable via Serialize() but does not + // have a corresponding TFLITE builtin. In that case, when flex mode is + // enabled we should export it as a flex op, not as a native. + bool export_as_flex_op = !is_tflite_builtin(tflite_op) && + key.is_flex_op() && + !op->tensorflow_node_def.empty(); + if (export_as_flex_op) { + auto fbb = WriteFlexOpOptions(op->tensorflow_node_def); + if (fbb) { + options = Options::Custom(builder->CreateVector(fbb->GetBuffer())); + } + } else if (tflite_op) { options = tflite_op->Serialize(*op, builder); mutating_input_variables = tflite_op->GetMutatingInputVariables(*op); @@ -373,12 +389,13 @@ Offset>> ExportOperators( variable_tensor_indices->insert(variable_tensor_index); } } - } else if (key.is_flex_op() && !op->tensorflow_node_def.empty()) { - auto fbb = WriteFlexOpOptions(op->tensorflow_node_def); - if (fbb) { - options = Options::Custom(builder->CreateVector(fbb->GetBuffer())); - } + } else { + // We don't know much about this op. It doesn't have a serializer and + // it is not supposed to be exported as a flex op. We will treat it as + // a regular custom op: we will still create an operator for it, but it + // will not have any 'options'. } + // The only supported CustomOptionFormat is FLEXBUFFERS now. op_vector.push_back(CreateOperator( *builder, op_index, builder->CreateVector(inputs), diff --git a/tensorflow/lite/toco/tflite/export_test.cc b/tensorflow/lite/toco/tflite/export_test.cc index b6c67772ac..b371296784 100644 --- a/tensorflow/lite/toco/tflite/export_test.cc +++ b/tensorflow/lite/toco/tflite/export_test.cc @@ -46,6 +46,18 @@ class ExportTest : public ::testing::Test { input_model_.operators.emplace_back(new AddOperator); } else if (name == "Sub") { input_model_.operators.emplace_back(new SubOperator); + } else if (name == "Assert") { + auto* op = new TensorFlowAssertOperator; + + // Even though assert is known to TOCO, it doesn't have a tflite + // serializer, so it has to be exported as a custom op. If we attach a + // NodeDef to it, however, it will be exported as a flex op instead. + ::tensorflow::NodeDef node_def; + node_def.set_name("Assert"); + node_def.set_op("Assert"); + node_def.SerializeToString(&op->tensorflow_node_def); + + input_model_.operators.emplace_back(op); } else { auto* op = new TensorFlowUnsupportedOperator; op->tensorflow_op = name; @@ -232,37 +244,38 @@ class OpSetsTest : public ExportTest { TEST_F(OpSetsTest, BuiltinsOnly) { // --target_op_set=TFLITE_BUILTINS SetAllowedOpSets({kTfLiteBuiltins}); - EXPECT_THAT(ImportExport({"Add", "AdjustHue", "UnrollAndFold"}), + EXPECT_THAT(ImportExport({"Add", "AdjustHue", "UnrollAndFold", "Assert"}), ElementsAre()); EXPECT_THAT(ImportExport({"Add"}), ElementsAre("builtin:ADD")); // --target_op_set=TFLITE_BUILTINS --allow_custom_ops SetAllowedOpSets({kTfLiteBuiltins, kCustomOps}); - EXPECT_THAT( - ImportExport({"Add", "AdjustHue", "UnrollAndFold"}), - ElementsAre("builtin:ADD", "custom:AdjustHue", "custom:UnrollAndFold")); + EXPECT_THAT(ImportExport({"Add", "AdjustHue", "UnrollAndFold", "Assert"}), + ElementsAre("builtin:ADD", "custom:AdjustHue", "custom:Assert", + "custom:UnrollAndFold")); } TEST_F(OpSetsTest, TfSelectOnly) { // --target_op_set=SELECT_TF_OPS SetAllowedOpSets({kSelectTfOps}); - EXPECT_THAT( - ImportExport({"Add", "AdjustHue", "RandomUniform", "UnrollAndFold"}), - ElementsAre()); + EXPECT_THAT(ImportExport({"Add", "AdjustHue", "RandomUniform", + "UnrollAndFold", "Assert"}), + ElementsAre()); EXPECT_THAT(ImportExport({"Add"}), ElementsAre("custom:FlexAdd")); // --target_op_set=SELECT_TF_OPS --allow_custom_ops SetAllowedOpSets({kSelectTfOps, kCustomOps}); EXPECT_THAT( - ImportExport({"Add", "AdjustHue", "RandomUniform", "UnrollAndFold"}), - ElementsAre("custom:AdjustHue", "custom:FlexAdd", + ImportExport( + {"Add", "AdjustHue", "RandomUniform", "UnrollAndFold", "Assert"}), + ElementsAre("custom:AdjustHue", "custom:FlexAdd", "custom:FlexAssert", "custom:FlexRandomUniform", "custom:UnrollAndFold")); } TEST_F(OpSetsTest, BuiltinsAndTfSelect) { // --target_op_set=TFLITE_BUILTINS,SELECT_TF_OPS SetAllowedOpSets({kTfLiteBuiltins, kSelectTfOps}); - EXPECT_THAT(ImportExport({"Add", "AdjustHue", "UnrollAndFold"}), + EXPECT_THAT(ImportExport({"Add", "AdjustHue", "UnrollAndFold", "Assert"}), ElementsAre()); EXPECT_THAT(ImportExport({"Add", "RandomUniform"}), ElementsAre("builtin:ADD", "custom:FlexRandomUniform")); @@ -270,9 +283,10 @@ TEST_F(OpSetsTest, BuiltinsAndTfSelect) { // --target_op_set=TFLITE_BUILTINS,SELECT_TF_OPS --allow_custom_ops SetAllowedOpSets({kTfLiteBuiltins, kSelectTfOps, kCustomOps}); EXPECT_THAT( - ImportExport({"Add", "AdjustHue", "RandomUniform", "UnrollAndFold"}), - ElementsAre("builtin:ADD", "custom:AdjustHue", "custom:FlexRandomUniform", - "custom:UnrollAndFold")); + ImportExport( + {"Add", "AdjustHue", "RandomUniform", "UnrollAndFold", "Assert"}), + ElementsAre("builtin:ADD", "custom:AdjustHue", "custom:FlexAssert", + "custom:FlexRandomUniform", "custom:UnrollAndFold")); } // This test is based on a hypothetical scenario that dilation is supported diff --git a/tensorflow/lite/toco/tflite/operator.cc b/tensorflow/lite/toco/tflite/operator.cc index 84ae448246..e0faed4927 100644 --- a/tensorflow/lite/toco/tflite/operator.cc +++ b/tensorflow/lite/toco/tflite/operator.cc @@ -978,6 +978,26 @@ class Split int GetVersion(const Operator& op) const override { return 1; } }; +class SplitV + : public BuiltinOperator { + public: + using BuiltinOperator::BuiltinOperator; + + flatbuffers::Offset WriteOptions( + const TocoOperator& op, + flatbuffers::FlatBufferBuilder* builder) const override { + return ::tflite::CreateSplitVOptions(*builder, op.num_split); + } + + void ReadOptions(const TfLiteOptions& options, + TocoOperator* op) const override { + op->num_split = options.num_splits(); + } + + int GetVersion(const Operator& op) const override { return 1; } +}; + class StridedSlice : public BuiltinOperator { + public: + using BuiltinOperator::BuiltinOperator; + flatbuffers::Offset WriteOptions( + const TocoOperator& op, + flatbuffers::FlatBufferBuilder* builder) const override { + return ::tflite::CreateLeakyReluOptions(*builder, op.alpha); + } + void ReadOptions(const TfLiteOptions& options, + TocoOperator* op) const override { + op->alpha = options.alpha(); + } + + int GetVersion(const Operator& op) const override { return 1; } +}; + +class SquaredDifference + : public BuiltinOperator< + SquaredDifferenceOperator, ::tflite::SquaredDifferenceOptions, + ::tflite::BuiltinOptions_SquaredDifferenceOptions> { + public: + using BuiltinOperator::BuiltinOperator; + + flatbuffers::Offset WriteOptions( + const TocoOperator& op, + flatbuffers::FlatBufferBuilder* builder) const override { + return ::tflite::CreateSquaredDifferenceOptions(*builder); + } + + void ReadOptions(const TfLiteOptions& options, + TocoOperator* op) const override {} + + int GetVersion(const Operator& op) const override { return 1; } +}; + +class MirrorPad + : public BuiltinOperator { + public: + using BuiltinOperator::BuiltinOperator; + flatbuffers::Offset WriteOptions( + const TocoOperator& op, + flatbuffers::FlatBufferBuilder* builder) const override { + return ::tflite::CreateMirrorPadOptions( + *builder, op.mode == MirrorPadMode::kReflect + ? ::tflite::MirrorPadMode::MirrorPadMode_REFLECT + : ::tflite::MirrorPadMode::MirrorPadMode_SYMMETRIC); + } + void ReadOptions(const TfLiteOptions& options, + TocoOperator* op) const override { + op->mode = options.mode() == ::tflite::MirrorPadMode::MirrorPadMode_REFLECT + ? MirrorPadMode::kReflect + : MirrorPadMode::kSymmetric; + } + + int GetVersion(const Operator& op) const override { return 1; } +}; + std::unique_ptr WriteFlexOpOptions( const string& tensorflow_node_def) { auto fbb = absl::make_unique(); @@ -1447,6 +1527,7 @@ std::vector> BuildOperatorList( OperatorType::kMaxPool)); ops.push_back( MakeUnique(::tflite::BuiltinOperator_MUL, OperatorType::kMul)); + ops.push_back( MakeUnique(::tflite::BuiltinOperator_PAD, OperatorType::kPad)); ops.push_back( @@ -1483,6 +1564,8 @@ std::vector> BuildOperatorList( OperatorType::kSqueeze)); ops.push_back( MakeUnique(::tflite::BuiltinOperator_SPLIT, OperatorType::kSplit)); + ops.push_back(MakeUnique(::tflite::BuiltinOperator_SPLIT_V, + OperatorType::kSplitV)); ops.push_back(MakeUnique( ::tflite::BuiltinOperator_STRIDED_SLICE, OperatorType::kStridedSlice)); ops.push_back(MakeUnique(::tflite::BuiltinOperator_TOPK_V2, @@ -1516,6 +1599,13 @@ std::vector> BuildOperatorList( OperatorType::kOneHot)); ops.push_back(MakeUnique(::tflite::BuiltinOperator_UNPACK, OperatorType::kUnpack)); + ops.push_back(MakeUnique(::tflite::BuiltinOperator_LEAKY_RELU, + OperatorType::kLeakyRelu)); + ops.push_back(MakeUnique( + ::tflite::BuiltinOperator_SQUARED_DIFFERENCE, + OperatorType::kSquaredDifference)); + ops.push_back(MakeUnique(::tflite::BuiltinOperator_MIRROR_PAD, + OperatorType::kMirrorPad)); // Custom Operators. ops.push_back( @@ -1600,7 +1690,10 @@ std::vector> BuildOperatorList( "SQUARE", OperatorType::kSquare)); ops.push_back(MakeUnique>( "ZEROS_LIKE", OperatorType::kZerosLike)); - + ops.push_back( + MakeUnique>("ABS", OperatorType::kAbs)); + ops.push_back( + MakeUnique>("FILL", OperatorType::kFill)); return ops; } } // namespace diff --git a/tensorflow/lite/toco/tflite/operator_test.cc b/tensorflow/lite/toco/tflite/operator_test.cc index 8a776cbf0b..14ec89cd73 100644 --- a/tensorflow/lite/toco/tflite/operator_test.cc +++ b/tensorflow/lite/toco/tflite/operator_test.cc @@ -151,6 +151,7 @@ TEST_F(OperatorTest, SimpleOperators) { OperatorType::kZerosLike); CheckSimpleOperator("FLOOR_MOD", OperatorType::kFloorMod); CheckSimpleOperator("RANGE", OperatorType::kRange); + CheckSimpleOperator("FILL", OperatorType::kFill); } TEST_F(OperatorTest, BuiltinAdd) { @@ -310,6 +311,14 @@ TEST_F(OperatorTest, CustomSplit) { EXPECT_EQ(op.num_split, output_toco_op->num_split); } +TEST_F(OperatorTest, CustomSplitV) { + TensorFlowSplitVOperator op; + op.num_split = 123; + auto output_toco_op = SerializeAndDeserialize( + GetOperator("SPLIT_V", OperatorType::kSplitV), op); + EXPECT_EQ(op.num_split, output_toco_op->num_split); +} + TEST_F(OperatorTest, BuiltinAveragePool) { AveragePoolOperator op; op.fused_activation_function = FusedActivationFunctionType::kRelu6; @@ -517,6 +526,21 @@ TEST_F(OperatorTest, BuiltinUnpack) { EXPECT_EQ(op.axis, output_toco_op->axis); } +TEST_F(OperatorTest, BuiltinLeakyRelu) { + LeakyReluOperator op; + op.alpha = 3; + auto output_toco_op = SerializeAndDeserialize( + GetOperator("LEAKY_RELU", OperatorType::kLeakyRelu), op); + EXPECT_EQ(op.alpha, output_toco_op->alpha); +} + +TEST_F(OperatorTest, BuiltinSquaredDifference) { + SquaredDifferenceOperator op; + auto output_toco_op = SerializeAndDeserialize( + GetOperator("SQUARED_DIFFERENCE", OperatorType::kSquaredDifference), op); + ASSERT_NE(nullptr, output_toco_op.get()); +} + TEST_F(OperatorTest, CustomCTCBeamSearchDecoder) { CTCBeamSearchDecoderOperator op; op.beam_width = 3; @@ -592,6 +616,14 @@ TEST_F(OperatorTest, TestShouldExportAsFlexOp) { EXPECT_FALSE(ShouldExportAsFlexOp(true, "RFFT")); } +TEST_F(OperatorTest, BuiltinMirrorPad) { + MirrorPadOperator op; + op.mode = MirrorPadMode::kReflect; + auto output_toco_op = SerializeAndDeserialize( + GetOperator("MIRROR_PAD", OperatorType::kMirrorPad), op); + EXPECT_EQ(op.mode, output_toco_op->mode); +} + } // namespace } // namespace tflite diff --git a/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc b/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc index d251589b48..039a918af1 100644 --- a/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc +++ b/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc @@ -187,6 +187,7 @@ bool IsWhitelistedFlexOp(const std::string& tensorflow_op_name) { "MirrorPad", "MirrorPadGrad", "Mul", + "Multinomial", "Neg", "NextIteration", "NonMaxSuppression", diff --git a/tensorflow/lite/toco/toco.cc b/tensorflow/lite/toco/toco.cc index 9740015850..4a3d6a5848 100644 --- a/tensorflow/lite/toco/toco.cc +++ b/tensorflow/lite/toco/toco.cc @@ -16,87 +16,9 @@ limitations under the License. #include #include -#include "absl/strings/string_view.h" -#include "tensorflow/lite/toco/model.h" #include "tensorflow/lite/toco/model_cmdline_flags.h" -#include "tensorflow/lite/toco/model_flags.pb.h" #include "tensorflow/lite/toco/toco_cmdline_flags.h" -#include "tensorflow/lite/toco/toco_flags.pb.h" -#include "tensorflow/lite/toco/toco_port.h" -#include "tensorflow/lite/toco/toco_tooling.h" -#include "tensorflow/lite/toco/toco_types.h" -#include "tensorflow/core/lib/core/errors.h" -#include "tensorflow/core/platform/logging.h" - -namespace toco { -namespace { - -// Checks the permissions of the output file to ensure it is writeable. -void CheckOutputFilePermissions(const Arg& output_file) { - QCHECK(output_file.specified()) << "Missing required flag --output_file.\n"; - QCHECK(port::file::Writable(output_file.value()).ok()) - << "Specified output_file is not writable: " << output_file.value() - << ".\n"; -} - -// Checks the permissions of the frozen model file. -void CheckFrozenModelPermissions(const Arg& input_file) { - QCHECK(input_file.specified()) << "Missing required flag --input_file.\n"; - QCHECK(port::file::Exists(input_file.value(), port::file::Defaults()).ok()) - << "Specified input_file does not exist: " << input_file.value() << ".\n"; - QCHECK(port::file::Readable(input_file.value(), port::file::Defaults()).ok()) - << "Specified input_file exists, but is not readable: " - << input_file.value() << ".\n"; -} - -// Reads the contents of the GraphDef from either the frozen graph file or the -// SavedModel directory. If it reads the SavedModel directory, it updates the -// ModelFlags and TocoFlags accordingly. -void ReadInputData(const ParsedTocoFlags& parsed_toco_flags, - const ParsedModelFlags& parsed_model_flags, - TocoFlags* toco_flags, ModelFlags* model_flags, - string* graph_def_contents) { - port::CheckInitGoogleIsDone("InitGoogle is not done yet.\n"); - - // Ensure savedmodel_directory is not set. - QCHECK(!parsed_toco_flags.savedmodel_directory.specified()) - << "Use `tensorflow/lite/python/tflite_convert` script with " - << "SavedModel directories.\n"; - - // Checks the input file permissions and reads the contents. - CheckFrozenModelPermissions(parsed_toco_flags.input_file); - CHECK(port::file::GetContents(parsed_toco_flags.input_file.value(), - graph_def_contents, port::file::Defaults()) - .ok()); -} - -tensorflow::Status ToolMain(const ParsedTocoFlags& parsed_toco_flags, - const ParsedModelFlags& parsed_model_flags) { - ModelFlags model_flags; - ReadModelFlagsFromCommandLineFlags(parsed_model_flags, &model_flags); - - TocoFlags toco_flags; - ReadTocoFlagsFromCommandLineFlags(parsed_toco_flags, &toco_flags); - - string graph_def_contents; - ReadInputData(parsed_toco_flags, parsed_model_flags, &toco_flags, - &model_flags, &graph_def_contents); - CheckOutputFilePermissions(parsed_toco_flags.output_file); - - std::unique_ptr model = - Import(toco_flags, model_flags, graph_def_contents); - Transform(toco_flags, model.get()); - string output_file_contents; - TF_RETURN_IF_ERROR(Export(toco_flags, *model, toco_flags.allow_custom_ops(), - &output_file_contents)); - TF_RETURN_IF_ERROR( - port::file::SetContents(parsed_toco_flags.output_file.value(), - output_file_contents, port::file::Defaults())); - return tensorflow::Status(); -} - -} // namespace -} // namespace toco +#include "tensorflow/lite/toco/toco_convert.h" int main(int argc, char** argv) { toco::string msg; @@ -126,6 +48,6 @@ int main(int argc, char** argv) { return 1; } toco::port::InitGoogle(argv[0], effective_argc, &effective_argv, true); - auto status = toco::ToolMain(parsed_toco_flags, parsed_model_flags); + auto status = toco::Convert(parsed_toco_flags, parsed_model_flags); return status.ok() ? 0 : -1; } diff --git a/tensorflow/lite/toco/toco_convert.cc b/tensorflow/lite/toco/toco_convert.cc new file mode 100644 index 0000000000..28e7b10ecd --- /dev/null +++ b/tensorflow/lite/toco/toco_convert.cc @@ -0,0 +1,108 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "tensorflow/lite/toco/model.h" +#include "tensorflow/lite/toco/model_cmdline_flags.h" +#include "tensorflow/lite/toco/model_flags.pb.h" +#include "tensorflow/lite/toco/toco_cmdline_flags.h" +#include "tensorflow/lite/toco/toco_flags.pb.h" +#include "tensorflow/lite/toco/toco_port.h" +#include "tensorflow/lite/toco/toco_tooling.h" +#include "tensorflow/lite/toco/toco_types.h" +#include "tensorflow/core/lib/core/errors.h" +#include "tensorflow/core/platform/logging.h" + +namespace toco { +namespace { + +// Checks the permissions of the output file to ensure it is writeable. +void CheckOutputFilePermissions(const Arg& output_file) { + QCHECK(output_file.specified()) << "Missing required flag --output_file.\n"; + QCHECK(port::file::Writable(output_file.value()).ok()) + << "Specified output_file is not writable: " << output_file.value() + << ".\n"; +} + +// Checks the permissions of the frozen model file. +void CheckFrozenModelPermissions(const Arg& input_file) { + QCHECK(input_file.specified()) << "Missing required flag --input_file.\n"; + QCHECK(port::file::Exists(input_file.value(), port::file::Defaults()).ok()) + << "Specified input_file does not exist: " << input_file.value() << ".\n"; + QCHECK(port::file::Readable(input_file.value(), port::file::Defaults()).ok()) + << "Specified input_file exists, but is not readable: " + << input_file.value() << ".\n"; +} + +// Reads the contents of the GraphDef from either the frozen graph file or the +// SavedModel directory. If it reads the SavedModel directory, it updates the +// ModelFlags and TocoFlags accordingly. +void ReadInputData(const ParsedTocoFlags& parsed_toco_flags, + const ParsedModelFlags& parsed_model_flags, + TocoFlags* toco_flags, ModelFlags* model_flags, + string* graph_def_contents) { + port::CheckInitGoogleIsDone("InitGoogle is not done yet.\n"); + + // Ensure savedmodel_directory is not set. + QCHECK(!parsed_toco_flags.savedmodel_directory.specified()) + << "Use `tensorflow/lite/python/tflite_convert` script with " + << "SavedModel directories.\n"; + + // Checks the input file permissions and reads the contents. + CheckFrozenModelPermissions(parsed_toco_flags.input_file); + CHECK(port::file::GetContents(parsed_toco_flags.input_file.value(), + graph_def_contents, port::file::Defaults()) + .ok()); +} +} // namespace + +tensorflow::Status Convert(const string& graph_def_contents, + const TocoFlags& toco_flags, + const ModelFlags& model_flags, + string* output_file_contents) { + std::unique_ptr model = + Import(toco_flags, model_flags, graph_def_contents); + Transform(toco_flags, model.get()); + return Export(toco_flags, *model, toco_flags.allow_custom_ops(), + output_file_contents); +} + +tensorflow::Status Convert(const ParsedTocoFlags& parsed_toco_flags, + const ParsedModelFlags& parsed_model_flags) { + ModelFlags model_flags; + ReadModelFlagsFromCommandLineFlags(parsed_model_flags, &model_flags); + + TocoFlags toco_flags; + ReadTocoFlagsFromCommandLineFlags(parsed_toco_flags, &toco_flags); + + string graph_def_contents; + ReadInputData(parsed_toco_flags, parsed_model_flags, &toco_flags, + &model_flags, &graph_def_contents); + CheckOutputFilePermissions(parsed_toco_flags.output_file); + + string output_file_contents; + TF_RETURN_IF_ERROR(Convert(graph_def_contents, toco_flags, model_flags, + &output_file_contents)); + + TF_RETURN_IF_ERROR( + port::file::SetContents(parsed_toco_flags.output_file.value(), + output_file_contents, port::file::Defaults())); + return tensorflow::Status(); +} + +} // namespace toco diff --git a/tensorflow/lite/toco/toco_convert.h b/tensorflow/lite/toco/toco_convert.h new file mode 100644 index 0000000000..ebbd336d3f --- /dev/null +++ b/tensorflow/lite/toco/toco_convert.h @@ -0,0 +1,34 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_TOCO_TOCO_CONVERT_H_ +#define TENSORFLOW_LITE_TOCO_TOCO_CONVERT_H_ + +#include "tensorflow/core/lib/core/status.h" +#include "tensorflow/lite/toco/args.h" +#include "tensorflow/lite/toco/model_flags.pb.h" +#include "tensorflow/lite/toco/toco_flags.pb.h" + +namespace toco { + +tensorflow::Status Convert(const string& graph_def_contents, + const TocoFlags& toco_flags, + const ModelFlags& model_flags, + string* output_file_contents); + +tensorflow::Status Convert(const ParsedTocoFlags& parsed_toco_flags, + const ParsedModelFlags& parsed_model_flags); +} // namespace toco + +#endif // TENSORFLOW_LITE_TOCO_TOCO_CONVERT_H_ diff --git a/tensorflow/lite/toco/toco_convert_test.cc b/tensorflow/lite/toco/toco_convert_test.cc new file mode 100644 index 0000000000..c3c440db94 --- /dev/null +++ b/tensorflow/lite/toco/toco_convert_test.cc @@ -0,0 +1,173 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/toco/toco_convert.h" +#include +#include + +namespace toco { +namespace { + +TEST(TocoTest, MissingInputFile) { + ParsedTocoFlags toco_flags; + ParsedModelFlags model_flags; + EXPECT_DEATH(Convert(toco_flags, model_flags).ok(), + "Missing required flag --input_file"); +} + +TEST(TocoTest, BadInputFormat) { + TocoFlags toco_flags; + ModelFlags model_flags; + + string input; + string output; + + EXPECT_DEATH(Convert(input, toco_flags, model_flags, &output).ok(), + "Unhandled input_format='FILE_FORMAT_UNKNOWN'"); +} + +TEST(TocoTest, MissingOuputArrays) { + TocoFlags toco_flags; + ModelFlags model_flags; + + toco_flags.set_input_format(TENSORFLOW_GRAPHDEF); + string input; + string output; + + EXPECT_DEATH(Convert(input, toco_flags, model_flags, &output).ok(), + "This model does not define output arrays, so a --output_arrays " + "flag must be given on the command-line"); +} + +TEST(TocoTest, BadOutputArray) { + TocoFlags toco_flags; + ModelFlags model_flags; + + toco_flags.set_input_format(TENSORFLOW_GRAPHDEF); + model_flags.add_output_arrays("output1"); + string input; + string output; + + EXPECT_DEATH(Convert(input, toco_flags, model_flags, &output).ok(), + "Specified output array .output1. is not produced by any op " + "in this graph. Is it a typo. To silence this message, pass " + "this flag: allow_nonexistent_arrays"); +} + +TEST(TocoTest, BadOutputFormat) { + TocoFlags toco_flags; + ModelFlags model_flags; + + toco_flags.set_input_format(TENSORFLOW_GRAPHDEF); + model_flags.add_output_arrays("output1"); + string input = R"GraphDef( + node { + name: "output1" + input: "input1" + input: "input2" + op: "Sub" + attr { key: "T" value { type: DT_FLOAT } } + } + )GraphDef"; + + string output; + + EXPECT_DEATH(Convert(input, toco_flags, model_flags, &output).ok(), + "Unhandled output_format='FILE_FORMAT_UNKNOWN'"); +} + +TEST(TocoTest, SimpleFloatModel) { + TocoFlags toco_flags; + ModelFlags model_flags; + + toco_flags.set_input_format(TENSORFLOW_GRAPHDEF); + toco_flags.set_output_format(TENSORFLOW_GRAPHDEF); + + // Inputs are automatically selected (but that might not be a good idea). + model_flags.add_output_arrays("output1"); + string input = R"GraphDef( + node { + name: "input1" + op: "Placeholder" + attr { key: "dtype" value { type: DT_INT64 } } + } + node { + name: "input2" + op: "Placeholder" + attr { key: "dtype" value { type: DT_INT64 } } + } + node { + name: "output1" + input: "input1" + input: "input2" + op: "Sub" + attr { key: "T" value { type: DT_FLOAT } } + } + )GraphDef"; + + string output; + EXPECT_TRUE(Convert(input, toco_flags, model_flags, &output).ok()); + EXPECT_TRUE(!output.empty()); +} + +TEST(TocoTest, TransientStringTensors) { + TocoFlags toco_flags; + ModelFlags model_flags; + + toco_flags.set_input_format(TENSORFLOW_GRAPHDEF); + + // We need to do a couple of things to trigger the transient array + // initialization code: output format must support memory planning, and the + // input array must have a shape. + toco_flags.set_output_format(TFLITE); + + model_flags.add_output_arrays("output1"); + string input = R"GraphDef( + node { + name: "input1" + op: "Placeholder" + attr { key: "dtype" value { type: DT_STRING } } + attr { key: "shape" value { shape { dim { size:1 }}}} + } + node { + name: "indices1" + op: "Placeholder" + attr { key: "dtype" value { type: DT_INT64 } } + } + node { + name: "intermediate1" + op: "Gather" + input: "input1" + input: "indices1" + attr { key: "Tparams" value { type: DT_STRING } } + attr { key: "Tindices" value { type: DT_INT64 } } + } + node { + name: "output1" + op: "Gather" + input: "intermediate1" + input: "indices2" + attr { key: "Tparams" value { type: DT_STRING } } + attr { key: "Tindices" value { type: DT_INT64 } } + } + )GraphDef"; + + string output; + + EXPECT_TRUE(Convert(input, toco_flags, model_flags, &output).ok()); + EXPECT_TRUE(!output.empty()); +} + +} // namespace +} // namespace toco diff --git a/tensorflow/lite/toco/toco_tooling.cc b/tensorflow/lite/toco/toco_tooling.cc index 5f96e833fb..55a454e66d 100644 --- a/tensorflow/lite/toco/toco_tooling.cc +++ b/tensorflow/lite/toco/toco_tooling.cc @@ -210,7 +210,8 @@ std::unique_ptr Import(const TocoFlags& toco_flags, CheckInvariants(*model); break; default: - LOG(FATAL) << "Unhandled input_format"; + LOG(FATAL) << "Unhandled input_format='" + << FileFormat_Name(toco_flags.input_format()) << "'"; } LogDump(kLogLevelModelChanged, "AT IMPORT", *model); @@ -308,6 +309,7 @@ void Transform(const TocoFlags& toco_flags, Model* model) { // Fix any issues with IO edges. This must happen after any transform that // may modify the structure of the edges. FixEdgeArrays(model); + FixOperatorOrdering(model); if (quantize_output) { // If the user specified default min/max ranges we need to set all arrays @@ -424,7 +426,8 @@ tensorflow::Status Export(const TocoFlags& toco_flags, const Model& model, DumpGraphviz(model, output_file_contents); break; default: - LOG(FATAL) << "Unhandled output_format"; + LOG(FATAL) << "Unhandled output_format='" + << FileFormat_Name(toco_flags.output_format()) << "'"; } return tensorflow::Status(); } diff --git a/tensorflow/lite/toco/tooling_util.cc b/tensorflow/lite/toco/tooling_util.cc index e33f7c8452..af4cd386a2 100644 --- a/tensorflow/lite/toco/tooling_util.cc +++ b/tensorflow/lite/toco/tooling_util.cc @@ -308,6 +308,7 @@ const char* OperatorTypeName(OperatorType type) { #define HANDLE_OPERATORTYPENAME_CASE(c) \ case OperatorType::k##c: \ return #c; + HANDLE_OPERATORTYPENAME_CASE(Abs) HANDLE_OPERATORTYPENAME_CASE(Add) HANDLE_OPERATORTYPENAME_CASE(AddN) HANDLE_OPERATORTYPENAME_CASE(AveragePool) @@ -371,6 +372,7 @@ const char* OperatorTypeName(OperatorType type) { HANDLE_OPERATORTYPENAME_CASE(Shape) HANDLE_OPERATORTYPENAME_CASE(Slice) HANDLE_OPERATORTYPENAME_CASE(Split) + HANDLE_OPERATORTYPENAME_CASE(SplitV) HANDLE_OPERATORTYPENAME_CASE(Sqrt) HANDLE_OPERATORTYPENAME_CASE(Square) HANDLE_OPERATORTYPENAME_CASE(Switch) @@ -411,6 +413,9 @@ const char* OperatorTypeName(OperatorType type) { HANDLE_OPERATORTYPENAME_CASE(ZerosLike) HANDLE_OPERATORTYPENAME_CASE(UnidirectionalSequenceLstm) HANDLE_OPERATORTYPENAME_CASE(ResizeNearestNeighbor) + HANDLE_OPERATORTYPENAME_CASE(LeakyRelu) + HANDLE_OPERATORTYPENAME_CASE(SquaredDifference) + HANDLE_OPERATORTYPENAME_CASE(MirrorPad) default: LOG(FATAL) << "Unhandled op type"; #undef HANDLE_OPERATORTYPENAME_CASE @@ -439,6 +444,7 @@ bool OperatorSupportsFusedActivation(OperatorType type) { case OperatorType::kMaxPool: case OperatorType::kMul: case OperatorType::kSub: + case OperatorType::kSquaredDifference: return true; default: return false; @@ -531,12 +537,12 @@ void DumpGraphvizVideoFrame(const Model& model) { if (!dump_hashes.count(hash)) { LOG(INFO) << "DUMPING GRAPHVIZ VIDEO FRAME: " << dump_id; dump_hashes.insert(hash); - CHECK(port::file::SetContents( - port::file::JoinPath( - dump_options.dump_graphviz, - toco::port::StringF("toco_video_%05d.dot", dump_id)), - graphviz_dump, port::file::Defaults()) - .ok()); + const auto result = port::file::SetContents( + port::file::JoinPath( + dump_options.dump_graphviz, + toco::port::StringF("toco_video_%05d.dot", dump_id)), + graphviz_dump, port::file::Defaults()); + QCHECK(result.ok()) << result.error_message(); dump_id++; } } @@ -550,14 +556,13 @@ void LogDump(int log_level, const string& message, const Model& model) { string graphviz_dump; DumpGraphviz(model, &graphviz_dump); - CHECK(port::file::SetContents( - port::file::JoinPath( - dump_options.dump_graphviz, - absl::StrCat("toco_", - absl::StrReplaceAll(message, {{" ", "_"}}), - ".dot")), - graphviz_dump, port::file::Defaults()) - .ok()); + const auto result = port::file::SetContents( + port::file::JoinPath( + dump_options.dump_graphviz, + absl::StrCat("toco_", absl::StrReplaceAll(message, {{" ", "_"}}), + ".dot")), + graphviz_dump, port::file::Defaults()); + QCHECK(result.ok()) << result.error_message(); } if (!VLOG_IS_ON(log_level)) { @@ -894,6 +899,9 @@ void CheckNonExistentIOArrays(const Model& model) { << "\" is not consumed by any op in this graph. " << general_comment; } for (const string& output_array : model.flags.output_arrays()) { + if (IsConstantParameterArray(model, output_array)) { + continue; // It is OK to request that a constant be an output. + } QCHECK(GetOpWithOutput(model, output_array)) << "Specified output array \"" << output_array << "\" is not produced by any op in this graph. " << general_comment; @@ -1032,10 +1040,10 @@ void CheckEachArray(const Model& model) { if (colon_pos != string::npos) { CHECK_EQ(name.substr(colon_pos + 1).find_first_not_of("0123456789"), string::npos) - << "Array name must only have digits after colon"; + << "Array '" << name << "' has non-digit characters after colon."; } - CHECK_GT(colon_pos, 0) - << "First character of array name must not be a colon."; + CHECK_GT(colon_pos, 0) << "Array '" << name + << "' must not start with a colon."; } } @@ -1767,6 +1775,14 @@ bool IsAllocatableTransientArray(const Model& model, const string& array_name) { if (!array->has_shape()) { return false; } + + // The size of string tensors is rarely known ahead of time, so all transient + // tensors of this type will need to be dynamically allocated. + if (array->final_data_type == ArrayDataType::kString || + array->data_type == ArrayDataType::kString) { + return false; + } + return true; } @@ -2207,6 +2223,8 @@ ArrayDataType ConvertIODataTypeToArrayDataType(IODataType type) { return ArrayDataType::kFloat; case QUANTIZED_UINT8: return ArrayDataType::kUint8; + case INT8: + return ArrayDataType::kInt8; case QUANTIZED_INT16: return ArrayDataType::kInt16; case INT32: diff --git a/tensorflow/lite/toco/types.proto b/tensorflow/lite/toco/types.proto index 12f711fd8a..fa911b8a4c 100644 --- a/tensorflow/lite/toco/types.proto +++ b/tensorflow/lite/toco/types.proto @@ -43,4 +43,7 @@ enum IODataType { // Complex64, not quantized COMPLEX64 = 8; + + // Int8, quantized based on QuantizationParameters in schema. + INT8 = 9; } diff --git a/tensorflow/lite/tools/benchmark/benchmark_model.cc b/tensorflow/lite/tools/benchmark/benchmark_model.cc index 05148aea65..e9b485efca 100644 --- a/tensorflow/lite/tools/benchmark/benchmark_model.cc +++ b/tensorflow/lite/tools/benchmark/benchmark_model.cc @@ -51,11 +51,13 @@ using tensorflow::Stat; BenchmarkParams BenchmarkModel::DefaultParams() { BenchmarkParams params; params.AddParam("num_runs", BenchmarkParam::Create(50)); + params.AddParam("min_secs", BenchmarkParam::Create(1.0f)); params.AddParam("run_delay", BenchmarkParam::Create(-1.0f)); params.AddParam("num_threads", BenchmarkParam::Create(1)); params.AddParam("benchmark_name", BenchmarkParam::Create("")); params.AddParam("output_prefix", BenchmarkParam::Create("")); params.AddParam("warmup_runs", BenchmarkParam::Create(1)); + params.AddParam("warmup_min_secs", BenchmarkParam::Create(0.5f)); return params; } @@ -73,19 +75,34 @@ void BenchmarkLoggingListener::OnBenchmarkEnd(const BenchmarkResults &results) { std::vector BenchmarkModel::GetFlags() { return { - CreateFlag("num_runs", ¶ms_, "number of runs"), + CreateFlag("num_runs", ¶ms_, + "minimum number of runs, see also min_secs"), + CreateFlag( + "min_secs", ¶ms_, + "minimum number of seconds to rerun for, potentially making the " + "actual number of runs to be greater than num_runs"), CreateFlag("run_delay", ¶ms_, "delay between runs in seconds"), CreateFlag("num_threads", ¶ms_, "number of threads"), CreateFlag("benchmark_name", ¶ms_, "benchmark name"), CreateFlag("output_prefix", ¶ms_, "benchmark output prefix"), - CreateFlag("warmup_runs", ¶ms_, - "how many runs to initialize model"), + CreateFlag( + "warmup_runs", ¶ms_, + "minimum number of runs performed on initialization, to " + "allow performance characteristics to settle, see also " + "warmup_min_secs"), + CreateFlag( + "warmup_min_secs", ¶ms_, + "minimum number of seconds to rerun for, potentially making the " + "actual number of warm-up runs to be greater than warmup_runs"), }; } void BenchmarkModel::LogParams() { - TFLITE_LOG(INFO) << "Num runs: [" << params_.Get("num_runs") << "]"; + TFLITE_LOG(INFO) << "Min num runs: [" << params_.Get("num_runs") + << "]"; + TFLITE_LOG(INFO) << "Min runs duration (seconds): [" + << params_.Get("min_secs") << "]"; TFLITE_LOG(INFO) << "Inter-run delay (seconds): [" << params_.Get("run_delay") << "]"; TFLITE_LOG(INFO) << "Num threads: [" << params_.Get("num_threads") @@ -94,16 +111,24 @@ void BenchmarkModel::LogParams() { << params_.Get("benchmark_name") << "]"; TFLITE_LOG(INFO) << "Output prefix: [" << params_.Get("output_prefix") << "]"; - TFLITE_LOG(INFO) << "Warmup runs: [" << params_.Get("warmup_runs") - << "]"; + TFLITE_LOG(INFO) << "Min warmup runs: [" + << params_.Get("warmup_runs") << "]"; + TFLITE_LOG(INFO) << "Min warmup runs duration (seconds): [" + << params_.Get("warmup_min_secs") << "]"; } void BenchmarkModel::PrepareInputsAndOutputs() {} -Stat BenchmarkModel::Run(int num_times, RunType run_type) { +Stat BenchmarkModel::Run(int min_num_times, float min_secs, + RunType run_type) { Stat run_stats; - TFLITE_LOG(INFO) << "Running benchmark for " << num_times << " iterations "; - for (int run = 0; run < num_times; run++) { + TFLITE_LOG(INFO) << "Running benchmark for at least " << min_num_times + << " iterations and at least " << min_secs << " seconds"; + int64_t min_finish_us = + profiling::time::NowMicros() + static_cast(min_secs * 1.e6f); + for (int run = 0; + run < min_num_times || profiling::time::NowMicros() < min_finish_us; + run++) { PrepareInputsAndOutputs(); listeners_.OnSingleRunStart(run_type); int64_t start_us = profiling::time::NowMicros(); @@ -145,9 +170,11 @@ void BenchmarkModel::Run() { uint64_t input_bytes = ComputeInputBytes(); Stat warmup_time_us = - Run(params_.Get("warmup_runs"), WARMUP); + Run(params_.Get("warmup_runs"), + params_.Get("warmup_min_secs"), WARMUP); Stat inference_time_us = - Run(params_.Get("num_runs"), REGULAR); + Run(params_.Get("num_runs"), params_.Get("min_secs"), + REGULAR); listeners_.OnBenchmarkEnd( {startup_latency_us, input_bytes, warmup_time_us, inference_time_us}); } diff --git a/tensorflow/lite/tools/benchmark/benchmark_model.h b/tensorflow/lite/tools/benchmark/benchmark_model.h index d8a9b05010..31ee5c92aa 100644 --- a/tensorflow/lite/tools/benchmark/benchmark_model.h +++ b/tensorflow/lite/tools/benchmark/benchmark_model.h @@ -150,7 +150,8 @@ class BenchmarkModel { bool ParseFlags(int argc, char** argv); virtual std::vector GetFlags(); virtual uint64_t ComputeInputBytes() = 0; - virtual tensorflow::Stat Run(int num_times, RunType run_type); + virtual tensorflow::Stat Run(int min_num_times, float min_secs, + RunType run_type); virtual void PrepareInputsAndOutputs(); virtual void RunImpl() = 0; BenchmarkParams params_; diff --git a/tensorflow/lite/tools/benchmark/benchmark_test.cc b/tensorflow/lite/tools/benchmark/benchmark_test.cc index 59d23d9008..8191fbcd73 100644 --- a/tensorflow/lite/tools/benchmark/benchmark_test.cc +++ b/tensorflow/lite/tools/benchmark/benchmark_test.cc @@ -33,6 +33,7 @@ namespace { BenchmarkParams CreateParams() { BenchmarkParams params; params.AddParam("num_runs", BenchmarkParam::Create(2)); + params.AddParam("min_secs", BenchmarkParam::Create(1.0f)); params.AddParam("run_delay", BenchmarkParam::Create(-1.0f)); params.AddParam("num_threads", BenchmarkParam::Create(1)); params.AddParam("benchmark_name", BenchmarkParam::Create("")); @@ -42,6 +43,7 @@ BenchmarkParams CreateParams() { params.AddParam("input_layer", BenchmarkParam::Create("")); params.AddParam("input_layer_shape", BenchmarkParam::Create("")); params.AddParam("use_nnapi", BenchmarkParam::Create(false)); + params.AddParam("warmup_min_secs", BenchmarkParam::Create(0.5f)); return params; } diff --git a/tensorflow/lite/tools/benchmark/benchmark_tflite_model.cc b/tensorflow/lite/tools/benchmark/benchmark_tflite_model.cc index 777d9dde7d..16f70870b6 100644 --- a/tensorflow/lite/tools/benchmark/benchmark_tflite_model.cc +++ b/tensorflow/lite/tools/benchmark/benchmark_tflite_model.cc @@ -181,7 +181,9 @@ bool PopulateInputLayerInfo( return true; } -BenchmarkParams GetDefaultParams() { +} // namespace + +BenchmarkParams BenchmarkTfLiteModel::DefaultParams() { BenchmarkParams default_params = BenchmarkModel::DefaultParams(); default_params.AddParam("graph", BenchmarkParam::Create("")); default_params.AddParam("input_layer", @@ -192,10 +194,8 @@ BenchmarkParams GetDefaultParams() { return default_params; } -} // namespace - BenchmarkTfLiteModel::BenchmarkTfLiteModel() - : BenchmarkTfLiteModel(GetDefaultParams()) {} + : BenchmarkTfLiteModel(DefaultParams()) {} BenchmarkTfLiteModel::BenchmarkTfLiteModel(BenchmarkParams params) : BenchmarkModel(std::move(params)) { @@ -279,7 +279,7 @@ void BenchmarkTfLiteModel::PrepareInputsAndOutputs() { FillRandomString(&buffer, sizes, []() { return "we're have some friends over saturday to hang out in the yard"; }); - buffer.WriteToTensor(interpreter->tensor(i)); + buffer.WriteToTensor(interpreter->tensor(i), /*new_shape=*/nullptr); } else { TFLITE_LOG(FATAL) << "Don't know how to populate tensor " << t->name << " of type " << t->type; @@ -319,6 +319,7 @@ void BenchmarkTfLiteModel::Init() { bool use_nnapi = params_.Get("use_nnapi"); interpreter->UseNNAPI(use_nnapi); + ApplyDelegates(); auto interpreter_inputs = interpreter->inputs(); diff --git a/tensorflow/lite/tools/benchmark/benchmark_tflite_model.h b/tensorflow/lite/tools/benchmark/benchmark_tflite_model.h index 401ab5427d..83599e644d 100644 --- a/tensorflow/lite/tools/benchmark/benchmark_tflite_model.h +++ b/tensorflow/lite/tools/benchmark/benchmark_tflite_model.h @@ -77,11 +77,16 @@ class BenchmarkTfLiteModel : public BenchmarkModel { }; protected: + static BenchmarkParams DefaultParams(); void PrepareInputsAndOutputs() override; - private: + // Allows installation of custom delegates during initialization + virtual void ApplyDelegates() {} + std::unique_ptr model; std::unique_ptr interpreter; + + private: std::vector inputs; ProfilingListener profiling_listener_; GemmlowpProfilingListener gemmlowp_profiling_listener_; diff --git a/tensorflow/lite/tools/benchmark/ios/TFLiteBenchmark/TFLiteBenchmark.xcodeproj/project.pbxproj b/tensorflow/lite/tools/benchmark/ios/TFLiteBenchmark/TFLiteBenchmark.xcodeproj/project.pbxproj index 958936a660..a5f5bfbbda 100644 --- a/tensorflow/lite/tools/benchmark/ios/TFLiteBenchmark/TFLiteBenchmark.xcodeproj/project.pbxproj +++ b/tensorflow/lite/tools/benchmark/ios/TFLiteBenchmark/TFLiteBenchmark.xcodeproj/project.pbxproj @@ -20,7 +20,7 @@ /* Begin PBXFileReference section */ 6FE7579920D59CE500F01636 /* benchmark_params.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = benchmark_params.json; sourceTree = ""; }; - 6FE7579C20D5A5E000F01636 /* benchmark-lib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "benchmark-lib.a"; path = "$SRCROOT/../../../../../../../tensorflow/lite/tools/make/gen/lib/benchmark-lib.a"; sourceTree = ""; }; + 6FE7579C20D5A5E000F01636 /* benchmark-lib.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "benchmark-lib.a"; path = "$SRCROOT/../../../../../../tensorflow/lite/tools/make/gen/lib/benchmark-lib.a"; sourceTree = ""; }; 6FE7579E20D5A6A700F01636 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; 6FE757A020D5AB8000F01636 /* mobilenet_v1_1.0_224.tflite */ = {isa = PBXFileReference; lastKnownFileType = file; path = mobilenet_v1_1.0_224.tflite; sourceTree = ""; }; 6FE93FF820D592D8008C9FE4 /* TFLiteBenchmark.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TFLiteBenchmark.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -309,19 +309,19 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; "HEADER_SEARCH_PATHS[arch=*]" = ( - $SRCROOT/../../../../../../../, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/eigen, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/gemmlowp, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/neon_2_sse, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/farmhash/src, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/flatbuffers/include, + $SRCROOT/../../../../../../, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/eigen, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/gemmlowp, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/neon_2_sse, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/farmhash/src, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/flatbuffers/include, ); INFOPLIST_FILE = TFLiteBenchmark/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - "LIBRARY_SEARCH_PATHS[arch=*]" = $SRCROOT/../../../../../../../tensorflow/lite/tools/make/gen/lib; + "LIBRARY_SEARCH_PATHS[arch=*]" = $SRCROOT/../../../../../../tensorflow/lite/tools/make/gen/lib; PRODUCT_BUNDLE_IDENTIFIER = example.TFLiteBenchmark; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; @@ -335,19 +335,19 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; "HEADER_SEARCH_PATHS[arch=*]" = ( - $SRCROOT/../../../../../../../, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/eigen, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/gemmlowp, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/neon_2_sse, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/farmhash/src, - $SRCROOT/../../../../../../../tensorflow/lite/tools/make/downloads/flatbuffers/include, + $SRCROOT/../../../../../../, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/eigen, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/gemmlowp, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/neon_2_sse, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/farmhash/src, + $SRCROOT/../../../../../../tensorflow/lite/tools/make/downloads/flatbuffers/include, ); INFOPLIST_FILE = TFLiteBenchmark/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - "LIBRARY_SEARCH_PATHS[arch=*]" = $SRCROOT/../../../../../../../tensorflow/lite/tools/make/gen/lib; + "LIBRARY_SEARCH_PATHS[arch=*]" = $SRCROOT/../../../../../../tensorflow/lite/tools/make/gen/lib; PRODUCT_BUNDLE_IDENTIFIER = example.TFLiteBenchmark; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/tensorflow/lite/tools/make/Makefile b/tensorflow/lite/tools/make/Makefile index 8f12355854..363a069d5e 100644 --- a/tensorflow/lite/tools/make/Makefile +++ b/tensorflow/lite/tools/make/Makefile @@ -85,6 +85,7 @@ CORE_CC_ALL_SRCS := \ $(wildcard tensorflow/lite/*.cc) \ $(wildcard tensorflow/lite/*.c) \ $(wildcard tensorflow/lite/c/*.c) \ +$(wildcard tensorflow/lite/core/*.cc) \ $(wildcard tensorflow/lite/core/api/*.cc) ifneq ($(BUILD_TYPE),micro) CORE_CC_ALL_SRCS += \ @@ -113,6 +114,10 @@ ifeq ($(BUILD_TYPE),micro) CORE_CC_EXCLUDE_SRCS += \ tensorflow/lite/mmap_allocation.cc \ tensorflow/lite/nnapi_delegate.cc +else +CORE_CC_EXCLUDE_SRCS += \ +tensorflow/contrib/lite/mmap_allocation_disabled.cc \ +tensorflow/contrib/lite/nnapi_delegate_disabled.cc endif # Filter out all the excluded files. TF_LITE_CC_SRCS := $(filter-out $(CORE_CC_EXCLUDE_SRCS), $(CORE_CC_ALL_SRCS)) @@ -208,6 +213,9 @@ $(BENCHMARK_BINARY) : $(BENCHMARK_LIB) benchmark: $(BENCHMARK_BINARY) +libdir: + @echo $(LIBDIR) + # Gets rid of all generated files. clean: rm -rf $(MAKEFILE_DIR)/gen diff --git a/tensorflow/lite/tools/make/targets/ios_makefile.inc b/tensorflow/lite/tools/make/targets/ios_makefile.inc index 7f36b8ecef..ae9276f9a6 100644 --- a/tensorflow/lite/tools/make/targets/ios_makefile.inc +++ b/tensorflow/lite/tools/make/targets/ios_makefile.inc @@ -22,7 +22,7 @@ ifeq ($(TARGET), ios) TARGET_ARCH := x86_64 CXXFLAGS += -miphoneos-version-min=$(MIN_SDK_VERSION) \ -DGEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK \ - -DTFLITE_USE_APPLE_ACCELERATE_FOR_CONV \ + -DTF_LITE_USE_CBLAS \ -fembed-bitcode \ -Wno-c++11-narrowing \ -mno-thumb \ diff --git a/tensorflow/lite/tools/optimize/g3doc/quantize_weights.md b/tensorflow/lite/tools/optimize/g3doc/quantize_weights.md index 2517882c84..cea164c38f 100644 --- a/tensorflow/lite/tools/optimize/g3doc/quantize_weights.md +++ b/tensorflow/lite/tools/optimize/g3doc/quantize_weights.md @@ -3,7 +3,7 @@ ## Recommended usage The Quantize Weights transformation is integrated with -[tflite_convert](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/toco/g3doc/cmdline_reference.md#transformation-flags). +[tflite_convert](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/g3doc/convert/cmdline_reference.md#transformation-flags). The recommended way of invoking this tool is by simply adding the `--post_training_quantize` flag to your original tflite_convert invocation. For diff --git a/tensorflow/lite/tools/pip_package/MANIFEST.in b/tensorflow/lite/tools/pip_package/MANIFEST.in new file mode 100644 index 0000000000..bb574e63a3 --- /dev/null +++ b/tensorflow/lite/tools/pip_package/MANIFEST.in @@ -0,0 +1 @@ +recursive-include * *.py diff --git a/tensorflow/lite/tools/pip_package/README.md b/tensorflow/lite/tools/pip_package/README.md new file mode 100644 index 0000000000..8190782c39 --- /dev/null +++ b/tensorflow/lite/tools/pip_package/README.md @@ -0,0 +1,33 @@ +# Building TensorFlow Lite Standalone Pip + +Many users would like to deploy TensorFlow lite interpreter and use it from +Python without requiring the rest of TensorFlow. + +## Steps + +To build a binary wheel run this script: +``` +sudo apt install swig libjpeg-dev zlib1g-dev python3-dev python3-numpy +sh tensorflow/lite/tools/pip_package/build_pip_package.sh +``` +That will print out some output and a .whl file. You can then install that +``` +pip install --upgrade +``` + +Note, unlike tensorflow this will be installed to a tflite_runtime namespace. +You can then use the Tensorflow Lite interpreter as. +``` +import tflite_runtime as tflr +interpreter = tflr.lite.Interpreter(model_path="foo.tflite") +``` + +This currently works to build on Linux machines including Raspberry Pi. In +the future, cross compilation to smaller SOCs like Raspberry Pi from +bigger host will be supported. + +## Caveats + +* You cannot use TensorFlow Select ops, only TensorFlow Lite builtins. +* Currently custom ops and delegates cannot be registered. + diff --git a/tensorflow/lite/tools/pip_package/build_pip_package.sh b/tensorflow/lite/tools/pip_package/build_pip_package.sh new file mode 100644 index 0000000000..2887ce8471 --- /dev/null +++ b/tensorflow/lite/tools/pip_package/build_pip_package.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +set -e + +# Find where this script lives and then the Tensorflow root. +MY_DIRECTORY=`dirname $0` +export TENSORFLOW_SRC_ROOT=`realpath $MY_DIRECTORY/../../../..` + +export TENSORFLOW_VERSION=`grep "_VERSION = " $TENSORFLOW_SRC_ROOT/tensorflow/tools/pip_package/setup.py | cut -d'=' -f 2 | sed "s/[ '-]//g"`; + + +# Build a pip build tree. +BUILD_ROOT=/tmp/tflite_pip +rm -rf $BUILD_ROOT +mkdir -p $BUILD_ROOT/tflite_runtime/lite +mkdir -p $BUILD_ROOT/tflite_runtime/lite/python + +# Build an importable module tree +cat > $BUILD_ROOT/tflite_runtime/__init__.py < $BUILD_ROOT/tflite_runtime/lite/__init__.py < $BUILD_ROOT/tflite_runtime/lite/python/__init__.py < hashes); +struct TfLiteIntArrayDeleter { + void operator()(TfLiteIntArray* a) { + if (a) TfLiteIntArrayFree(a); + } +}; + } // namespace tflite #endif // TENSORFLOW_LITE_UTIL_H_ diff --git a/tensorflow/opensource_only.files b/tensorflow/opensource_only.files new file mode 100644 index 0000000000..8ff1645b98 --- /dev/null +++ b/tensorflow/opensource_only.files @@ -0,0 +1,17 @@ +tensorflow/third_party/toolchains/preconfig/ubuntu14.04/py3/BUILD +tensorflow/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/BUILD +tensorflow/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc/BUILD +tensorflow/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/build_defs.bzl +tensorflow/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/BUILD +tensorflow/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/BUILD +tensorflow/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/build_defs.bzl +tensorflow/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/BUILD +tensorflow/third_party/toolchains/preconfig/ubuntu14.04/nccl2/BUILD +tensorflow/third_party/toolchains/preconfig/generate/workspace.bzl +tensorflow/third_party/toolchains/preconfig/generate/containers.bzl +tensorflow/third_party/toolchains/preconfig/generate/generate.bzl +tensorflow/third_party/toolchains/preconfig/generate/BUILD +tensorflow/third_party/toolchains/preconfig/win_1803/bazel_018/BUILD +tensorflow/third_party/toolchains/preconfig/win_1803/bazel_018/dummy_toolchain.bzl +tensorflow/third_party/toolchains/preconfig/win_1803/py36/BUILD +tensorflow/third_party/toolchains/preconfig/win_1803/BUILD \ No newline at end of file diff --git a/tensorflow/python/BUILD b/tensorflow/python/BUILD index 4fe92262ba..a558045e4a 100644 --- a/tensorflow/python/BUILD +++ b/tensorflow/python/BUILD @@ -102,6 +102,7 @@ py_library( ":framework_for_generated_wrappers", ":functional_ops", ":gradient_checker", + ":gradient_checker_v2", ":graph_util", ":histogram_ops", ":image_ops", @@ -124,7 +125,6 @@ py_library( ":session_ops", ":sets", ":sparse_ops", - ":spectral_ops", ":spectral_ops_test_util", ":standard_ops", ":state_ops", @@ -132,6 +132,7 @@ py_library( ":subscribe", ":summary", ":tensor_array_ops", + ":tensor_forest_ops", ":test_ops", # TODO: Break testing code out into separate rule. ":tf_cluster", ":tf_item", @@ -524,6 +525,17 @@ py_test( ], ) +py_test( + name = "dispatch_test", + srcs = ["util/dispatch_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":client_testlib", + ":platform", + ":util", + ], +) + py_test( name = "keyword_args_test", srcs = ["util/keyword_args_test.py"], @@ -854,7 +866,6 @@ py_library( deps = [ ":c_api_util", ":control_flow_util", - ":cpp_shape_inference_proto_py", ":device", ":dtypes", ":error_interpolation", @@ -862,6 +873,7 @@ py_library( ":platform", ":registry", ":tensor_shape", + ":tf2", ":traceable_stack", ":util", ":versions", @@ -880,6 +892,8 @@ py_library( deps = [ ":auto_control_deps", ":framework_ops", + ":sparse_tensor", + ":tensor_array_ops", "//tensorflow/python/autograph", "//tensorflow/python/eager:context", "//tensorflow/python/eager:graph_only_ops", @@ -894,6 +908,8 @@ py_library( deps = [ ":control_flow_ops", ":framework_ops", + ":sparse_tensor", + ":tensor_array_ops", ":util", ], ) @@ -981,6 +997,7 @@ py_library( srcs_version = "PY2AND3", deps = [ ":dtypes", + ":tf2", ":util", "//tensorflow/core:protos_all_py", ], @@ -994,6 +1011,7 @@ py_library( ":common_shapes", ":dtypes", ":tensor_shape", + ":util", "//third_party/py/numpy", ], ) @@ -1052,6 +1070,7 @@ py_library( ":random_seed", ":resource_variable_ops", ":session", + ":tensor_array_ops", ":training", ":util", ":variables", @@ -1076,10 +1095,13 @@ py_library( srcs_version = "PY2AND3", deps = [ ":client", + ":cond_v2", ":framework_test_lib", ":gradient_checker", + ":gradient_checker_v2", ":platform_test", ":util", + ":while_v2", ], ) @@ -1384,6 +1406,7 @@ py_test( srcs_version = "PY2AND3", tags = ["no_pip"], # test_ops_2 is not available in pip. deps = [ + ":cond_v2", ":control_flow_ops", ":errors", ":framework", @@ -1398,6 +1421,7 @@ py_test( ":util", ":variable_scope", ":variables", + ":while_v2", "//tensorflow/core:protos_all_py", "//tensorflow/python/eager:context", "//tensorflow/python/eager:function", @@ -1618,6 +1642,14 @@ tf_gen_op_wrapper_private_py( ], ) +tf_gen_op_wrapper_private_py( + name = "tensor_forest_ops_gen", + visibility = ["//tensorflow:internal"], + deps = [ + "//tensorflow/core:tensor_forest_ops_op_lib", + ], +) + tf_gen_op_wrapper_private_py( name = "summary_ops_gen", visibility = ["//tensorflow:__subpackages__"], @@ -1837,6 +1869,7 @@ tf_gen_op_wrapper_private_py( tf_gen_op_wrapper_private_py( name = "spectral_ops_gen", + visibility = ["//tensorflow/python/ops/signal:__pkg__"], ) tf_gen_op_wrapper_private_py( @@ -1941,6 +1974,28 @@ py_library( ], ) +py_library( + name = "tensor_forest_ops", + srcs = ["ops/tensor_forest_ops.py"], + srcs_version = "PY2AND3", + deps = [ + ":framework", + ":ops", + ":tensor_forest_ops_gen", + ":training", + "//tensorflow/core/kernels/boosted_trees:boosted_trees_proto_py", + ], +) + +py_library( + name = "optional_grad", + srcs = ["ops/optional_grad.py"], + srcs_version = "PY2AND3", + deps = [ + ":framework_ops", + ], +) + py_library( name = "sets", srcs = [ @@ -2056,7 +2111,6 @@ py_library( srcs = ["ops/control_flow_ops.py"], srcs_version = "PY2AND3", deps = [ - "tensor_shape", ":array_ops", ":array_ops_gen", ":constant_op", @@ -2071,6 +2125,7 @@ py_library( ":resource_variable_ops_gen", ":sparse_tensor", ":tensor_array_ops", + ":tensor_shape", ":tf2", ":tf_should_use", ":util", @@ -2093,7 +2148,9 @@ py_library( srcs = ["ops/control_flow_util_v2.py"], srcs_version = "PY2AND3", deps = [ - "framework_ops", + ":control_flow_util", + ":framework_ops", + "//tensorflow/core:protos_all_py", "//tensorflow/python/eager:context", "//tensorflow/python/eager:function", ], @@ -2118,7 +2175,7 @@ py_library( ":graph_to_function_def", ":pywrap_tensorflow", ":util", - "//tensorflow/core:protos_all_py", + "//tensorflow/python/data/ops:dataset_ops", "//tensorflow/python/eager:function", ], ) @@ -2145,7 +2202,6 @@ py_library( ":tensor_shape", ":tensor_util", ":util", - "//tensorflow/core:protos_all_py", "//tensorflow/python/eager:function", ], ) @@ -2263,10 +2319,10 @@ py_library( ":manip_ops", ":math_grad", ":math_ops", + ":optional_grad", ":platform", ":random_grad", ":resource_variable_ops", - ":spectral_grad", ":tensor_array_ops", ":tensor_util", ":unconnected_gradients", @@ -2508,7 +2564,6 @@ py_library( ":nn_ops_gen", ":sparse_ops_gen", ":sparse_tensor", - ":spectral_ops_gen", ":state_ops", ":state_ops_gen", ":tensor_shape", @@ -2814,33 +2869,34 @@ py_test( ":framework_test_lib", ":sparse_ops", ":sparse_tensor", + "@absl_py//absl/testing:parameterized", ], ) py_library( - name = "spectral_grad", - srcs = ["ops/spectral_grad.py"], + name = "sort_ops", + srcs = ["ops/sort_ops.py"], srcs_version = "PY2AND3", deps = [ ":array_ops", ":framework", - ":framework_for_generated_wrappers", ":math_ops", - ":spectral_ops", + ":nn_ops", "//third_party/py/numpy", ], ) -py_library( - name = "spectral_ops", - srcs = ["ops/spectral_ops.py"], +py_test( + name = "sort_ops_test", + srcs = ["ops/sort_ops_test.py"], srcs_version = "PY2AND3", deps = [ ":array_ops", - ":dtypes", - ":framework_ops", - ":math_ops", - ":spectral_ops_gen", + ":client_testlib", + ":framework", + ":random_ops", + ":sort_ops", + "//third_party/py/numpy", ], ) @@ -2958,10 +3014,10 @@ py_library( ":random_ops", ":script_ops", ":session_ops", + ":sort_ops", ":sparse_grad", ":sparse_ops", ":special_math_ops", - ":spectral_grad", ":state_grad", ":state_ops", ":stateless_random_ops", @@ -2972,6 +3028,7 @@ py_library( ":util", ":variable_scope", ":variables", + "//tensorflow/python/eager:wrap_function", "//tensorflow/python/ops/distributions", "//tensorflow/python/ops/linalg", ], @@ -3066,13 +3123,16 @@ py_library( deps = [ ":array_ops", ":constant_op", + ":control_flow_ops_gen", ":data_flow_ops_gen", ":dtypes", ":errors", ":framework_ops", + ":list_ops", ":math_ops", ":tensor_shape", ":tensor_util", + ":tf2", ":tf_should_use", "//tensorflow/python/eager:context", ], @@ -3131,6 +3191,19 @@ py_library( ], ) +py_library( + name = "gradient_checker_v2", + srcs = ["ops/gradient_checker_v2.py"], + srcs_version = "PY2AND3", + deps = [ + ":array_ops", + ":framework_for_generated_wrappers", + ":gradients", + ":platform", + "//third_party/py/numpy", + ], +) + # This target is deprecated. py_library( name = "ops", @@ -3196,6 +3269,22 @@ cuda_py_test( ], ) +cuda_py_test( + name = "gradient_checker_v2_test", + size = "medium", + srcs = ["ops/gradient_checker_v2_test.py"], + additional_deps = [ + ":array_ops", + ":client_testlib", + ":framework_for_generated_wrappers", + ":math_ops", + ":nn_grad", + ":nn_ops", + ":platform", + "//third_party/py/numpy", + ], +) + cuda_py_test( name = "gradients_test", size = "medium", @@ -3304,6 +3393,9 @@ cuda_py_test( ":client_testlib", ":framework_for_generated_wrappers", ":math_ops", + "//tensorflow/python/eager:backprop", + "//tensorflow/python/eager:context", + "//tensorflow/python/eager:execution_callbacks", "//third_party/py/numpy", ], tags = ["no_windows_gpu"], @@ -3475,6 +3567,7 @@ py_library( "@six_archive//:six", "//tensorflow/core:protos_all_py", "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/distribute:reduce_util", "//tensorflow/python/distribute:distribute_coordinator_context", "//tensorflow/python/eager:backprop", "//tensorflow/python/eager:context", @@ -3486,6 +3579,19 @@ py_library( ], ) +# Dependency added and used by ClusterResolvers to avoid circular dependency between keras, distribute, and training. +py_library( + name = "training_server_lib", + srcs = ["training/server_lib.py"], + srcs_version = "PY2AND3", + deps = [ + ":framework", + ":pywrap_tensorflow", + ":util", + "//tensorflow/core:protos_all_py", + ], +) + py_library( name = "saveable_object", srcs = ["training/saveable_object.py"], @@ -3560,17 +3666,6 @@ py_library( ], ) -py_library( - name = "device_util", - srcs = ["training/device_util.py"], - srcs_version = "PY2AND3", - deps = [ - ":device", - ":framework_ops", - "//tensorflow/python/eager:context", - ], -) - py_library( name = "distribute", srcs = [ @@ -3579,29 +3674,7 @@ py_library( ], srcs_version = "PY2AND3", deps = [ - ":array_ops", - ":control_flow_ops", - ":device_util", - ":framework_ops", - ":platform", - ":resource_variable_ops", - ":state_ops", - ":util", - ":variable_scope", - "//tensorflow/python/data", - "//tensorflow/python/ops/losses", - ], -) - -py_test( - name = "distribute_test", - size = "small", - srcs = ["training/distribute_test.py"], - srcs_version = "PY2AND3", - deps = [ - ":client_testlib", - ":distribute", - ":variable_scope", + "//tensorflow/python/distribute:distribute_lib", ], ) @@ -4108,11 +4181,24 @@ genrule( # Get the import library of _pywrap_tensorflow_internal.dll filegroup( - name = "pywrap_tensorflow_import_lib_file", + name = "get_pywrap_tensorflow_import_lib_file", srcs = [":_pywrap_tensorflow_internal.so"], output_group = "interface_library", ) +# Rename the import library for _pywrap_tensorflow_internal.pyd to _pywrap_tensorflow_internal.lib +# (It was _pywrap_tensorflow_internal.so.if.lib). +genrule( + name = "pywrap_tensorflow_import_lib_file", + srcs = [":get_pywrap_tensorflow_import_lib_file"], + outs = ["_pywrap_tensorflow_internal.lib"], + cmd = select({ + "//tensorflow:windows": "cp -f $< $@", + "//conditions:default": "touch $@", # Just a placeholder for Unix platforms + }), + visibility = ["//visibility:public"], +) + # Create a cc_import rule for the import library of _pywrap_tensorflow_internal.dll # so that custom ops' dynamic libraries can link against it. cc_import( @@ -4590,7 +4676,6 @@ cuda_py_tests( "training/basic_loops_test.py", "training/coordinator_test.py", "training/device_setter_test.py", - "training/device_util_test.py", "training/ftrl_test.py", "training/gradient_descent_test.py", "training/learning_rate_decay_test.py", @@ -4901,7 +4986,7 @@ py_test( ":training", ":variable_scope", ":variables", - "//tensorflow/python/feature_column", + "//tensorflow/python/feature_column:feature_column_py", "//third_party/py/numpy", ], ) diff --git a/tensorflow/python/__init__.py b/tensorflow/python/__init__.py index 5da304e38c..547043030b 100644 --- a/tensorflow/python/__init__.py +++ b/tensorflow/python/__init__.py @@ -86,12 +86,12 @@ from tensorflow.python.ops import image_ops as image from tensorflow.python.ops import manip_ops as manip from tensorflow.python.ops import metrics from tensorflow.python.ops import nn +from tensorflow.python.ops import ragged from tensorflow.python.ops import sets -from tensorflow.python.ops import spectral_ops as spectral from tensorflow.python.ops.distributions import distributions from tensorflow.python.ops.linalg import linalg from tensorflow.python.ops.losses import losses -from tensorflow.python.ops import signal +from tensorflow.python.ops.signal import signal from tensorflow.python.profiler import profiler from tensorflow.python.saved_model import saved_model from tensorflow.python.summary import summary @@ -163,7 +163,7 @@ tf_export('Summary', 'summary.Summary')(Summary) tf_export('summary.SummaryDescription')(SummaryDescription) tf_export('SummaryMetadata')(SummaryMetadata) tf_export('summary.TaggedRunMetadata')(TaggedRunMetadata) -tf_export('TensorInfo')(TensorInfo) +tf_export(v1=['TensorInfo'])(TensorInfo) # pylint: enable=undefined-variable # Special dunders that we choose to export: diff --git a/tensorflow/python/autograph/converters/BUILD b/tensorflow/python/autograph/converters/BUILD index ced2e4796b..3ac446db02 100644 --- a/tensorflow/python/autograph/converters/BUILD +++ b/tensorflow/python/autograph/converters/BUILD @@ -63,7 +63,6 @@ py_test( name = "asserts_test", srcs = ["asserts_test.py"], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ ":converters", "//tensorflow/python:client_testlib", @@ -239,7 +238,6 @@ py_test( name = "error_handlers_test", srcs = ["error_handlers_test.py"], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ ":converters", "//tensorflow/python:client_testlib", diff --git a/tensorflow/python/autograph/converters/asserts_test.py b/tensorflow/python/autograph/converters/asserts_test.py index eef628aeb6..9ae448892a 100644 --- a/tensorflow/python/autograph/converters/asserts_test.py +++ b/tensorflow/python/autograph/converters/asserts_test.py @@ -23,12 +23,14 @@ from tensorflow.python.autograph.converters import side_effect_guards from tensorflow.python.autograph.core import converter_testing from tensorflow.python.framework import constant_op from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import gen_control_flow_ops from tensorflow.python.platform import test class AssertsTest(converter_testing.TestCase): + @test_util.run_deprecated_v1 def test_basic(self): def test_fn(a): @@ -41,7 +43,7 @@ class AssertsTest(converter_testing.TestCase): op = result.test_fn(constant_op.constant(False)) with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, 'test message'): - sess.run(op) + self.evaluate(op) if __name__ == '__main__': diff --git a/tensorflow/python/autograph/converters/builtin_functions_test.py b/tensorflow/python/autograph/converters/builtin_functions_test.py index 30cfb13233..2683be16ec 100644 --- a/tensorflow/python/autograph/converters/builtin_functions_test.py +++ b/tensorflow/python/autograph/converters/builtin_functions_test.py @@ -24,12 +24,14 @@ from tensorflow.python.autograph.converters import builtin_functions from tensorflow.python.autograph.core import converter_testing from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test class BuiltinFunctionsTest(converter_testing.TestCase): + @test_util.run_deprecated_v1 def test_len(self): def test_fn(a): @@ -41,6 +43,7 @@ class BuiltinFunctionsTest(converter_testing.TestCase): ops = result.test_fn(p) self.assertEqual(sess.run(ops, {p: [0, 0, 0]}), 3) + @test_util.run_deprecated_v1 def test_print(self): if six.PY2: @@ -54,6 +57,7 @@ class BuiltinFunctionsTest(converter_testing.TestCase): with self.assertPrints('a\n'): sess.run(result.test_fn('a')) + @test_util.run_deprecated_v1 def test_print_multiple_values(self): if six.PY2: diff --git a/tensorflow/python/autograph/converters/call_trees.py b/tensorflow/python/autograph/converters/call_trees.py index 55cea89126..9b85fc8367 100644 --- a/tensorflow/python/autograph/converters/call_trees.py +++ b/tensorflow/python/autograph/converters/call_trees.py @@ -22,7 +22,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from collections import namedtuple +import collections import gast @@ -35,7 +35,7 @@ from tensorflow.python.autograph.pyct import templates from tensorflow.python.util import tf_inspect -class FunctionInfo(namedtuple('FunctionInfo', ('dtype',))): +class FunctionInfo(collections.namedtuple('FunctionInfo', ('dtype',))): pass @@ -116,12 +116,19 @@ class CallTreeTransformer(converter.Base): def _function_is_compilable(self, target_entity): """Determines whether an entity can be compiled at all.""" # TODO(mdan): Expand. + if target_entity.__module__ is None: # Functions like builtins and NumPy don't expose a module. # Those in general should not be compiled. return False + if inspect_utils.isbuiltin(target_entity): return False + + if inspect_utils.isnamedtuple(target_entity): + # namedtuple doesn't expose its source code, making it uncompilable. + return False + return True def _should_compile(self, node, fqn): @@ -140,6 +147,11 @@ class CallTreeTransformer(converter.Base): if target_entity is not None: + # Currently, lambdas are always converted. + # TODO(mdan): Allow markers of the kind f = ag.do_not_convert(lambda: ...) + if inspect_utils.islambda(target_entity): + return True + # This may be reached when "calling" a callable attribute of an object. # For example: # @@ -296,7 +308,13 @@ class CallTreeTransformer(converter.Base): # safe for graph mode. return node + elif inspect_utils.isnamedtuple(target_entity): + # Although not compilable, we assume they are safe for graph mode. + node = self.generic_visit(node) + return node + else: + # TODO(mdan): Instert dynamic conversion here instead. raise NotImplementedError( 'py_func with return values (unknown function)') else: diff --git a/tensorflow/python/autograph/converters/call_trees_test.py b/tensorflow/python/autograph/converters/call_trees_test.py index 916c736fb4..454d75d755 100644 --- a/tensorflow/python/autograph/converters/call_trees_test.py +++ b/tensorflow/python/autograph/converters/call_trees_test.py @@ -18,6 +18,8 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import collections + import numpy as np from tensorflow.python.autograph.converters import call_trees @@ -85,6 +87,34 @@ class CallTreesTest(converter_testing.TestCase): tc = TestClass() self.assertEquals(3, result.test_fn_2(tc, 1)) + def test_known_called_lambda(self): + + l = lambda x: x + + def test_fn(a): + return l(a) + + ns = {'l': l} + node, ctx = self.prepare(test_fn, ns) + node = call_trees.transform(node, ctx) + + with self.compiled(node, ns) as result: + self.assertEquals(1, result.test_fn(1)) + + def test_known_called_namedtuple(self): + + nt = collections.namedtuple('TestNamedTuple', ['a']) + + def test_fn(a): + return nt(a) + + ns = {'nt': nt} + node, ctx = self.prepare(test_fn, ns) + node = call_trees.transform(node, ctx) + + with self.compiled(node, ns) as result: + self.assertEquals(nt(1), result.test_fn(1)) + def test_py_func_known_function(self): def test_fn(): @@ -94,7 +124,7 @@ class CallTreesTest(converter_testing.TestCase): dtypes.int64) as result: with self.cached_session() as sess: self.assertTrue(isinstance(result.test_fn(), ops.Tensor)) - self.assertIn(sess.run(result.test_fn()), (0, 1, 2)) + self.assertIn(self.evaluate(result.test_fn()), (0, 1, 2)) def test_uncompiled_modules(self): @@ -113,7 +143,7 @@ class CallTreesTest(converter_testing.TestCase): with self.compiled(node, ns) as result: with self.cached_session() as sess: result_tensor = result.test_fn(constant_op.constant(1)) - self.assertEquals(sess.run(result_tensor), 3) + self.assertEquals(self.evaluate(result_tensor), 3) def test_call_to_decorated_function(self): diff --git a/tensorflow/python/autograph/converters/continue_statements.py b/tensorflow/python/autograph/converters/continue_statements.py index 584cdc1efd..05e19e59fc 100644 --- a/tensorflow/python/autograph/converters/continue_statements.py +++ b/tensorflow/python/autograph/converters/continue_statements.py @@ -24,94 +24,93 @@ from tensorflow.python.autograph.pyct import templates from tensorflow.python.autograph.pyct.static_analysis.annos import NodeAnno -# Tags for local state. -CONTROL_VAR_NAME = 'control_var_name' -CONTINUE_USED = 'continue_used' -GUARD_CREATED = 'guard_created' -CREATE_GUARD_NEXT = 'create_guard_next' +class _Continue(object): + + def __init__(self): + self.used = False + self.control_var_name = None + self.create_guard = False + self.guard_created = False + + def __repr__(self): + return 'used: %s, var: %s' % (self.used, self.control_var_name) class ContinueCanonicalizationTransformer(converter.Base): """Canonicalizes continue statements into additional conditionals.""" def visit_Continue(self, node): - self.set_local(CONTINUE_USED, True) + self.state[_Continue].used = True template = """ - var_name = tf.constant(True) + var_name = True """ return templates.replace( - template, var_name=self.get_local(CONTROL_VAR_NAME)) + template, var_name=self.state[_Continue].control_var_name) def _postprocess_statement(self, node): # Example of how the state machine below works: # - # 1| stmt # State: CONTINUE_USED = False + # 1| stmt # State: Continue_.used = False # | # Action: none # 2| if cond: - # 3| continue # State: CONTINUE_USED = True, - # | # GUARD_CREATED = False, - # | # CREATE_GUARD_NEXT = False - # | # Action: set CREATE_GUARD_NEXT = True - # 4| stmt # State: CONTINUE_USED = True, - # | # GUARD_CREATED = False, - # | # CREATE_GUARD_NEXT = True + # 3| continue # State: Continue_.used = True, + # | # Continue_.guard_created = False, + # | # Continue_.create_guard = False + # | # Action: Continue_.create_guard = True + # 4| stmt # State: Continue_.used = True, + # | # Continue_.guard_created = False, + # | # Continue_.create_guard = True # | # Action: create `if not continue_used`, - # | # set GUARD_CREATED = True - # 5| stmt # State: CONTINUE_USED = True, GUARD_CREATED = True + # | # set Continue_.guard_created = True + # 5| stmt # State: Continue_.used = True, + # | # Continue_.guard_created = True # | # Action: none (will be wrapped under previously # | # created if node) - if self.get_local(CONTINUE_USED, False): - if self.get_local(GUARD_CREATED, False): + if self.state[_Continue].used: + if self.state[_Continue].guard_created: return node, None - elif not self.get_local(CREATE_GUARD_NEXT, False): - self.set_local(CREATE_GUARD_NEXT, True) + elif not self.state[_Continue].create_guard: + self.state[_Continue].create_guard = True return node, None else: - self.set_local(GUARD_CREATED, True) + self.state[_Continue].guard_created = True template = """ if not var_name: original_node """ cond, = templates.replace( template, - var_name=self.get_local(CONTROL_VAR_NAME), + var_name=self.state[_Continue].control_var_name, original_node=node) return cond, cond.body return node, None def _visit_loop_body(self, node, nodes): - self.enter_local_scope() + self.state[_Continue].enter() scope = anno.getanno(node, NodeAnno.BODY_SCOPE) continue_var = self.ctx.namer.new_symbol('continue_', scope.referenced) - self.set_local(CONTROL_VAR_NAME, continue_var) + self.state[_Continue].control_var_name = continue_var nodes = self.visit_block(nodes, after_visit=self._postprocess_statement) - if self.get_local(CONTINUE_USED, False): + if self.state[_Continue].used: template = """ - var_name = tf.constant(False) + var_name = False """ control_var_init = templates.replace(template, var_name=continue_var) nodes = control_var_init + nodes - self.exit_local_scope() + self.state[_Continue].exit() return nodes - def _visit_non_loop_body(self, nodes): - self.enter_local_scope(inherit=(CONTROL_VAR_NAME,)) - nodes = self.visit_block(nodes, after_visit=self._postprocess_statement) - continue_used = self.get_local(CONTINUE_USED, False) - self.exit_local_scope(keep=(CONTINUE_USED,)) - return nodes, continue_used - def visit_While(self, node): node.test = self.visit(node.test) node.body = self._visit_loop_body(node, node.body) # A continue in the else clause applies to the containing scope. - node.orelse, _ = self._visit_non_loop_body(node.orelse) + node.orelse = self.visit_block(node.orelse) return node def visit_For(self, node): @@ -119,21 +118,11 @@ class ContinueCanonicalizationTransformer(converter.Base): node.iter = self.generic_visit(node.iter) node.body = self._visit_loop_body(node, node.body) # A continue in the else clause applies to the containing scope. - node.orelse, _ = self._visit_non_loop_body(node.orelse) - return node - - def visit_If(self, node): - node.test = self.generic_visit(node.test) - node.body, continue_used_body = self._visit_non_loop_body(node.body) - node.orelse, continue_used_orelse = self._visit_non_loop_body(node.orelse) - self.set_local(CONTINUE_USED, continue_used_body or continue_used_orelse) - return node - - def visit_With(self, node): - node.items = self.visit_block(node.items) - node.body, _ = self._visit_non_loop_body(node.body) + node.orelse = self.visit_block(node.orelse) return node def transform(node, ctx): - return ContinueCanonicalizationTransformer(ctx).visit(node) + transformer = ContinueCanonicalizationTransformer(ctx) + node = transformer.visit(node) + return node diff --git a/tensorflow/python/autograph/converters/control_flow.py b/tensorflow/python/autograph/converters/control_flow.py index 5853e044c5..bef6cae1bb 100644 --- a/tensorflow/python/autograph/converters/control_flow.py +++ b/tensorflow/python/autograph/converters/control_flow.py @@ -106,14 +106,49 @@ class ControlFlowTransformer(converter.Base): return 'no variables' return ', '.join(map(str, symbol_set)) - def visit_If(self, node): - node = self.generic_visit(node) + def _determine_aliased_symbols(self, scope, node_defined_in, block): + if block: + block_live_in = set(anno.getanno(block[0], anno.Static.LIVE_VARS_IN)) + else: + block_live_in = set() + # For the purpose of aliasing, composite symbols with live owners are live + # as well. Otherwise this would leak tensors from the conditional's body. + # + # For example: + # + # obj = some_obj + # if cond: + # obj.a = val + # + # Thanslating to the code below would be incorrect: + # + # def true_fn(): + # obj.a = val() # Wrong! leaks ops owned by true_fn + # return obj.a + for s in scope.modified: + if s.is_composite(): + live_parents = block_live_in & s.owner_set + if live_parents: + block_live_in.add(s) + return scope.modified & node_defined_in & block_live_in + + def visit_If(self, node): body_scope = anno.getanno(node, annos.NodeAnno.BODY_SCOPE) orelse_scope = anno.getanno(node, annos.NodeAnno.ORELSE_SCOPE) defined_in = anno.getanno(node, anno.Static.DEFINED_VARS_IN) live_out = anno.getanno(node, anno.Static.LIVE_VARS_OUT) + # Note: this information needs to be extracted before the body conversion + # that happens in the call to generic_visit below, because the conversion + # generates nodes that lack static analysis annotations. + need_alias_in_body = self._determine_aliased_symbols( + body_scope, defined_in, node.body) + need_alias_in_orelse = self._determine_aliased_symbols( + orelse_scope, defined_in, node.orelse) + + node = self.generic_visit(node) + modified_in_cond = body_scope.modified | orelse_scope.modified returned_from_cond = set() for s in modified_in_cond: @@ -125,9 +160,6 @@ class ControlFlowTransformer(converter.Base): if live_out & s.owner_set: returned_from_cond.add(s) - need_alias_in_body = body_scope.modified & defined_in - need_alias_in_orelse = orelse_scope.modified & defined_in - created_in_body = body_scope.modified & returned_from_cond - defined_in created_in_orelse = orelse_scope.modified & returned_from_cond - defined_in diff --git a/tensorflow/python/autograph/converters/control_flow_test.py b/tensorflow/python/autograph/converters/control_flow_test.py index 03fdfc804e..034fcbe386 100644 --- a/tensorflow/python/autograph/converters/control_flow_test.py +++ b/tensorflow/python/autograph/converters/control_flow_test.py @@ -23,6 +23,7 @@ from tensorflow.python.autograph.core import converter_testing from tensorflow.python.autograph.pyct import transformer from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -36,6 +37,7 @@ class ControlFlowTest(converter_testing.TestCase): with self.cached_session() as sess: self.assertEqual(sess.run(result.test_fn(*inputs)), expected) + @test_util.run_deprecated_v1 def test_while_basic(self): def test_fn(n): @@ -48,6 +50,7 @@ class ControlFlowTest(converter_testing.TestCase): self.assertTransformedResult(test_fn, constant_op.constant(5), (10, 5, 5)) + @test_util.run_deprecated_v1 def test_while_nested(self): def test_fn(n): @@ -66,6 +69,7 @@ class ControlFlowTest(converter_testing.TestCase): self.assertTransformedResult(test_fn, constant_op.constant(5), (25, 5, 0, 5)) + @test_util.run_deprecated_v1 def test_while_single_output(self): def test_fn(n): @@ -86,6 +90,7 @@ class ControlFlowTest(converter_testing.TestCase): with self.assertRaises(NameError): control_flow.transform(node, ctx) + @test_util.run_deprecated_v1 def test_if_basic(self): def test_fn(n): @@ -100,6 +105,7 @@ class ControlFlowTest(converter_testing.TestCase): self.assertTransformedResult(test_fn, constant_op.constant(1), (-1, 0)) self.assertTransformedResult(test_fn, constant_op.constant(-1), (0, -2)) + @test_util.run_deprecated_v1 def test_if_complex_outputs(self): class TestClass(object): @@ -124,6 +130,7 @@ class ControlFlowTest(converter_testing.TestCase): res_obj = result.test_fn(constant_op.constant(-1), TestClass(0, 0)) self.assertEqual(sess.run((res_obj.a, res_obj.b)), (0, -2)) + @test_util.run_deprecated_v1 def test_if_single_output(self): def test_fn(n): @@ -133,6 +140,7 @@ class ControlFlowTest(converter_testing.TestCase): self.assertTransformedResult(test_fn, constant_op.constant(1), -1) + @test_util.run_deprecated_v1 def test_if_semi(self): def test_fn(n): @@ -143,6 +151,7 @@ class ControlFlowTest(converter_testing.TestCase): self.assertTransformedResult(test_fn, constant_op.constant(2), 3) self.assertTransformedResult(test_fn, constant_op.constant(-3), -3) + @test_util.run_deprecated_v1 def test_if_local_var(self): def test_fn(n): @@ -154,6 +163,7 @@ class ControlFlowTest(converter_testing.TestCase): self.assertTransformedResult(test_fn, constant_op.constant(1), 5) self.assertTransformedResult(test_fn, constant_op.constant(-1), -1) + @test_util.run_deprecated_v1 def test_if_no_outputs(self): def test_fn(n): @@ -177,6 +187,7 @@ class ControlFlowTest(converter_testing.TestCase): with self.assertRaises(transformer.AutographParseError): control_flow.transform(node, ctx) + @test_util.run_deprecated_v1 def test_simple_for(self): def test_fn(l): @@ -191,6 +202,7 @@ class ControlFlowTest(converter_testing.TestCase): empty_vector = constant_op.constant([], shape=(0,), dtype=dtypes.int32) self.assertTransformedResult(test_fn, empty_vector, (0, 0)) + @test_util.run_deprecated_v1 def test_for_single_output(self): def test_fn(l): @@ -235,6 +247,7 @@ class ControlFlowTest(converter_testing.TestCase): with self.assertRaises(NameError): control_flow.transform(node, ctx) + @test_util.run_deprecated_v1 def test_for_tuple_unpacking(self): def test_fn(x_list): z = tf.constant(0) # pylint:disable=undefined-variable diff --git a/tensorflow/python/autograph/converters/function_scopes_test.py b/tensorflow/python/autograph/converters/function_scopes_test.py index e5ce03a109..5a1248c801 100644 --- a/tensorflow/python/autograph/converters/function_scopes_test.py +++ b/tensorflow/python/autograph/converters/function_scopes_test.py @@ -22,11 +22,13 @@ from tensorflow.python.autograph.converters import function_scopes from tensorflow.python.autograph.core import converter_testing from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.platform import test class FunctionBodyTransformerTest(converter_testing.TestCase): + @test_util.run_deprecated_v1 def test_basic(self): def test_fn(l): @@ -40,6 +42,7 @@ class FunctionBodyTransformerTest(converter_testing.TestCase): self.assertIn('test_fn/', result_op.op.name) self.assertEqual('Docstring.', result.test_fn.__doc__) + @test_util.run_deprecated_v1 def test_multiline_docstring(self): tf = None @@ -58,6 +61,7 @@ class FunctionBodyTransformerTest(converter_testing.TestCase): self.assertIn('First sentence.', result.test_fn.__doc__) self.assertIn('Second sentence.', result.test_fn.__doc__) + @test_util.run_deprecated_v1 def test_nested_functions(self): def test_fn(l): @@ -74,6 +78,7 @@ class FunctionBodyTransformerTest(converter_testing.TestCase): self.assertNotIn('inner_fn', first.op.name) self.assertIn('test_fn/inner_fn/', second.op.name) + @test_util.run_deprecated_v1 def test_method(self): class TestClass(object): diff --git a/tensorflow/python/autograph/converters/lists_test.py b/tensorflow/python/autograph/converters/lists_test.py index f6da845fcc..39843c7d74 100644 --- a/tensorflow/python/autograph/converters/lists_test.py +++ b/tensorflow/python/autograph/converters/lists_test.py @@ -68,7 +68,7 @@ class ListTest(converter_testing.TestCase): with self.cached_session() as sess: tl = result.test_fn() r = list_ops.tensor_list_stack(tl, dtypes.int32) - self.assertAllEqual(sess.run(r), [1, 2, 3]) + self.assertAllEqual(self.evaluate(r), [1, 2, 3]) def test_list_pop(self): @@ -91,8 +91,8 @@ class ListTest(converter_testing.TestCase): with self.cached_session() as sess: ts, tl = result.test_fn() r = list_ops.tensor_list_stack(tl, dtypes.int32) - self.assertAllEqual(sess.run(r), [1, 2]) - self.assertAllEqual(sess.run(ts), 3) + self.assertAllEqual(self.evaluate(r), [1, 2]) + self.assertAllEqual(self.evaluate(ts), 3) def test_double_list_pop(self): @@ -123,7 +123,7 @@ class ListTest(converter_testing.TestCase): with self.compiled(node, {}, array_ops.stack, dtypes.int32) as result: with self.cached_session() as sess: - self.assertAllEqual(sess.run(result.test_fn()), [1, 2, 3]) + self.assertAllEqual(self.evaluate(result.test_fn()), [1, 2, 3]) # TODO(mdan): Add a test with tf.stack with axis kwarg. diff --git a/tensorflow/python/autograph/converters/logical_expressions_test.py b/tensorflow/python/autograph/converters/logical_expressions_test.py index 99db04a775..687412750e 100644 --- a/tensorflow/python/autograph/converters/logical_expressions_test.py +++ b/tensorflow/python/autograph/converters/logical_expressions_test.py @@ -21,11 +21,13 @@ from __future__ import print_function from tensorflow.python.autograph.converters import logical_expressions from tensorflow.python.autograph.core import converter_testing from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.platform import test class LogicalExpressionTest(converter_testing.TestCase): + @test_util.run_deprecated_v1 def test_equals(self): def test_fn(a, b): @@ -36,6 +38,7 @@ class LogicalExpressionTest(converter_testing.TestCase): self.assertTrue(sess.run(result.test_fn(constant_op.constant(1), 1))) self.assertFalse(sess.run(result.test_fn(constant_op.constant(1), 2))) + @test_util.run_deprecated_v1 def test_bool_ops(self): def test_fn(a, b, c): @@ -48,6 +51,7 @@ class LogicalExpressionTest(converter_testing.TestCase): self.assertFalse( sess.run(result.test_fn(constant_op.constant(True), False, True))) + @test_util.run_deprecated_v1 def test_comparison(self): def test_fn(a, b, c, d): diff --git a/tensorflow/python/autograph/converters/side_effect_guards_test.py b/tensorflow/python/autograph/converters/side_effect_guards_test.py index cef3199169..645267e560 100644 --- a/tensorflow/python/autograph/converters/side_effect_guards_test.py +++ b/tensorflow/python/autograph/converters/side_effect_guards_test.py @@ -23,6 +23,7 @@ from tensorflow.python.autograph.core import converter_testing from tensorflow.python.framework import constant_op from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import state_ops from tensorflow.python.ops import variable_scope @@ -34,6 +35,7 @@ tf = None # Will be replaced by a mock. class SideEffectGuardsTest(converter_testing.TestCase): + @test_util.run_deprecated_v1 def test_side_effect_on_return_only_variable(self): def test_fn(a): @@ -48,12 +50,12 @@ class SideEffectGuardsTest(converter_testing.TestCase): with self.compiled(node, {}, state_ops.assign) as result: with self.cached_session() as sess: v = variable_scope.get_variable('test', initializer=2) - sess.run(v.initializer) - sess.run(result.test_fn(v)) + self.evaluate(v.initializer) + self.evaluate(result.test_fn(v)) # TODO(mdan): Add support for this use case. # Right now the variable `a` is not conditioned on the `assign` because # there's no way to add control dependencies to a variable object. - self.assertEqual(2, sess.run(v)) + self.assertEqual(2, self.evaluate(v)) def test_side_effect_on_used_variable(self): @@ -69,12 +71,13 @@ class SideEffectGuardsTest(converter_testing.TestCase): with self.compiled(node, {}, state_ops.assign) as result: with self.cached_session() as sess: v = variable_scope.get_variable('test', initializer=2) - sess.run(v.initializer) - sess.run(result.test_fn(v)) + self.evaluate(v.initializer) + self.evaluate(result.test_fn(v)) # TODO(mdan): Ensure the result of test_fn(v) is also deterministic. # Right now it's 3 or 4 based on whether the read is synchronized. - self.assertEqual(3, sess.run(v)) + self.assertEqual(3, self.evaluate(v)) + @test_util.run_deprecated_v1 def test_side_effect_on_tensor(self): def test_fn(a): @@ -109,10 +112,10 @@ class SideEffectGuardsTest(converter_testing.TestCase): with self.compiled(node, {}, state_ops.assign_add) as result: with self.cached_session() as sess: v = variable_scope.get_variable('test', initializer=2) - sess.run(v.initializer) - sess.run(result.test_fn(v)) + self.evaluate(v.initializer) + self.evaluate(result.test_fn(v)) # TODO(mdan): Ensure the result of test_fn(v) is also deterministic. - self.assertEqual(4, sess.run(v)) + self.assertEqual(4, self.evaluate(v)) def test_multiline_nested_block(self): @@ -130,10 +133,10 @@ class SideEffectGuardsTest(converter_testing.TestCase): with self.compiled(node, {}, state_ops.assign, ops.name_scope) as result: with self.cached_session() as sess: v = variable_scope.get_variable('test', initializer=2) - sess.run(v.initializer) - sess.run(result.test_fn(v)) + self.evaluate(v.initializer) + self.evaluate(result.test_fn(v)) # TODO(mdan): Ensure the result of test_fn(v) is also deterministic. - self.assertEqual(3, sess.run(v)) + self.assertEqual(3, self.evaluate(v)) def test_multiline_block_unsafe(self): @@ -153,10 +156,10 @@ class SideEffectGuardsTest(converter_testing.TestCase): state_ops.assign_add) as result: with self.cached_session() as sess: v = variable_scope.get_variable('test', initializer=2) - sess.run(v.initializer) - sess.run(result.test_fn(v)) + self.evaluate(v.initializer) + self.evaluate(result.test_fn(v)) # TODO(mdan): Ensure the result of test_fn(v) is also deterministic. - self.assertEqual(4, sess.run(v)) + self.assertEqual(4, self.evaluate(v)) if __name__ == '__main__': diff --git a/tensorflow/python/autograph/converters/slices_test.py b/tensorflow/python/autograph/converters/slices_test.py index e190a7cfe8..bd049afdfc 100644 --- a/tensorflow/python/autograph/converters/slices_test.py +++ b/tensorflow/python/autograph/converters/slices_test.py @@ -49,7 +49,7 @@ class SliceTest(converter_testing.TestCase): tl = list_ops.tensor_list_from_tensor( [1, 2], element_shape=constant_op.constant([], dtype=dtypes.int32)) y = result.test_fn(tl) - self.assertEqual(2, sess.run(y)) + self.assertEqual(2, self.evaluate(y)) def test_index_access_multiple_definitions(self): diff --git a/tensorflow/python/autograph/core/converter.py b/tensorflow/python/autograph/core/converter.py index 49e24895a2..e88c4674ee 100644 --- a/tensorflow/python/autograph/core/converter.py +++ b/tensorflow/python/autograph/core/converter.py @@ -82,6 +82,7 @@ from tensorflow.python.autograph.pyct.static_analysis import live_values from tensorflow.python.autograph.pyct.static_analysis import liveness from tensorflow.python.autograph.pyct.static_analysis import reaching_definitions from tensorflow.python.autograph.pyct.static_analysis import type_info +from tensorflow.python.eager import function # TODO(mdan): These contexts can be refactored into first class objects. # For example, we could define Program and Entity abstractions that hold on @@ -96,7 +97,7 @@ class Verbosity(IntEnum): Attributes: * BRIEF: No logging, minimal error messages. * VERBOSE: Detailed logging of generated code, detailed error messages. - """ + """ BRIEF = 0 VERBOSE = 1 @@ -151,7 +152,7 @@ class ConversionOptions(object): optional_features=Feature.ALL): self.recursive = recursive self.verbose = verbose - self.strip_decorators = strip_decorators or () + self._strip_decorators = strip_decorators or () self.force_conversion = force_conversion # TODO(mdan): Rename to conversion_recursion_depth? self.internal_convert_user_code = internal_convert_user_code @@ -161,6 +162,12 @@ class ConversionOptions(object): optional_features = frozenset(optional_features) self.optional_features = optional_features + @property + def strip_decorators(self): + # A few decorators are included by default. + # TODO(mdan): Revert if function.defun becomes a public symbol. + return self._strip_decorators + (function.defun,) + def uses(self, feature): return (Feature.ALL in self.optional_features or feature in self.optional_features) @@ -216,7 +223,7 @@ class ConversionOptions(object): as_qualified_name(ConversionOptions)), recursive_val=parser.parse_expression(str(self.recursive)), verbose_val=parser.parse_expression(str(int(self.verbose))), - strip_decorators_val=list_of_names(self.strip_decorators), + strip_decorators_val=list_of_names(self._strip_decorators), force_conversion_val=parser.parse_expression( str(self.force_conversion)), internal_convert_user_code_val=parser.parse_expression( diff --git a/tensorflow/python/autograph/core/converter_testing.py b/tensorflow/python/autograph/core/converter_testing.py index 7b0608d03f..f1374081d3 100644 --- a/tensorflow/python/autograph/core/converter_testing.py +++ b/tensorflow/python/autograph/core/converter_testing.py @@ -32,6 +32,7 @@ from tensorflow.python.autograph.core import errors from tensorflow.python.autograph.core import function_wrapping from tensorflow.python.autograph.lang import special_functions from tensorflow.python.autograph.pyct import compiler +from tensorflow.python.autograph.pyct import inspect_utils from tensorflow.python.autograph.pyct import origin_info from tensorflow.python.autograph.pyct import parser from tensorflow.python.autograph.pyct import pretty_printer @@ -43,7 +44,7 @@ def imported_decorator(f): return lambda a: f(a) + 1 -# TODO(mdan): We might be able to use the real namer here. +# TODO(mdan): We should use the real namer here. class FakeNamer(object): """A fake namer that uses a global counter to generate unique names.""" @@ -61,7 +62,8 @@ class FakeNamer(object): original_fqn, live_entity=None, owner_type=None): - del live_entity + if inspect_utils.islambda(live_entity): + return None, False if owner_type is not None: return None, False return ('renamed_%s' % '_'.join(original_fqn)), True diff --git a/tensorflow/python/autograph/core/errors_test.py b/tensorflow/python/autograph/core/errors_test.py index aa6c293268..845a28a522 100644 --- a/tensorflow/python/autograph/core/errors_test.py +++ b/tensorflow/python/autograph/core/errors_test.py @@ -22,6 +22,7 @@ from tensorflow.python.autograph.core import errors from tensorflow.python.autograph.pyct import origin_info from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors as tf_errors +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test from tensorflow.python.util import tf_inspect @@ -47,6 +48,7 @@ class RuntimeErrorsTest(test.TestCase): 'test_comment') return loc, origin + @test_util.run_deprecated_v1 def test_improved_errors_basic(self): loc, origin = self.fake_origin(zero_div, 2) zero_div_caller.ag_source_map = {loc: origin} @@ -55,13 +57,14 @@ class RuntimeErrorsTest(test.TestCase): with self.assertRaises(errors.TfRuntimeError) as cm: with errors.improved_errors(zero_div_caller): with self.cached_session() as sess: - sess.run(ops) + self.evaluate(ops) for frame in cm.exception.custom_traceback: _, _, function_name, _ = frame self.assertNotEqual('zero_div', function_name) self.assertIn(origin.as_frame(), set(cm.exception.custom_traceback)) + @test_util.run_deprecated_v1 def test_improved_errors_no_matching_lineno(self): loc, origin = self.fake_origin(zero_div, -1) zero_div_caller.ag_source_map = {loc: origin} @@ -70,7 +73,7 @@ class RuntimeErrorsTest(test.TestCase): with self.assertRaises(errors.TfRuntimeError) as cm: with errors.improved_errors(zero_div_caller): with self.cached_session() as sess: - sess.run(ops) + self.evaluate(ops) all_function_names = set() for frame in cm.exception.custom_traceback: @@ -79,6 +82,7 @@ class RuntimeErrorsTest(test.TestCase): self.assertNotEqual('test_function_name', function_name) self.assertIn('zero_div', all_function_names) + @test_util.run_deprecated_v1 def test_improved_errors_failures(self): loc, _ = self.fake_origin(zero_div, 2) zero_div_caller.ag_source_map = {loc: 'bogus object'} @@ -87,7 +91,7 @@ class RuntimeErrorsTest(test.TestCase): with self.assertRaises(tf_errors.InvalidArgumentError): with errors.improved_errors(zero_div_caller): with self.cached_session() as sess: - sess.run(ops) + self.evaluate(ops) def test_improved_errors_validation(self): with self.assertRaisesRegexp( diff --git a/tensorflow/python/autograph/core/function_wrapping_test.py b/tensorflow/python/autograph/core/function_wrapping_test.py index 5e217055c7..7e21b979db 100644 --- a/tensorflow/python/autograph/core/function_wrapping_test.py +++ b/tensorflow/python/autograph/core/function_wrapping_test.py @@ -20,11 +20,13 @@ from __future__ import print_function from tensorflow.python.autograph.core import function_wrapping from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.platform import test class FunctionWrappingTest(test.TestCase): + @test_util.run_deprecated_v1 def test_function_scope_name(self): with function_wrapping.function_scope('test_name'): t = constant_op.constant(1) diff --git a/tensorflow/python/autograph/core/naming.py b/tensorflow/python/autograph/core/naming.py index 43fcbcfc03..b8d79daeba 100644 --- a/tensorflow/python/autograph/core/naming.py +++ b/tensorflow/python/autograph/core/naming.py @@ -18,8 +18,8 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.autograph.pyct import inspect_utils from tensorflow.python.autograph.pyct import qual_names -from tensorflow.python.util import tf_inspect class Namer(object): @@ -77,8 +77,7 @@ class Namer(object): if not self.recursive: return None, False - if (live_entity is not None and tf_inspect.isfunction(live_entity) and - live_entity.__name__ == ''): + if (live_entity is not None and inspect_utils.islambda(live_entity)): return None, False if owner_type is not None and owner_type not in self.partial_types: diff --git a/tensorflow/python/autograph/impl/BUILD b/tensorflow/python/autograph/impl/BUILD index 2f9037c43b..201a888754 100644 --- a/tensorflow/python/autograph/impl/BUILD +++ b/tensorflow/python/autograph/impl/BUILD @@ -41,7 +41,6 @@ py_test( name = "api_test", srcs = ["api_test.py"], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ ":impl", "//tensorflow/python:client_testlib", @@ -54,7 +53,6 @@ py_test( name = "conversion_test", srcs = ["conversion_test.py"], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ ":impl", "//tensorflow/python:client_testlib", diff --git a/tensorflow/python/autograph/impl/api.py b/tensorflow/python/autograph/impl/api.py index 69674b2be3..19a472064a 100644 --- a/tensorflow/python/autograph/impl/api.py +++ b/tensorflow/python/autograph/impl/api.py @@ -195,6 +195,17 @@ def converted_call(f, owner, options, *args, **kwargs): if not options.internal_convert_user_code: return f(*args, **kwargs) + # Unwrap functools.partial objects + # TODO(allenl, mdan): Consider sharing unwrapping logic with tf_inspect. + while isinstance(f, functools.partial): + args = f.args + args + new_kwargs = {} + if f.keywords is not None: + new_kwargs.update(f.keywords) + new_kwargs.update(kwargs) + kwargs = new_kwargs + f = f.func + if tf_inspect.isfunction(f) or tf_inspect.ismethod(f): # Regular functions target_entity = f diff --git a/tensorflow/python/autograph/impl/api_test.py b/tensorflow/python/autograph/impl/api_test.py index ef577568c4..66edda5119 100644 --- a/tensorflow/python/autograph/impl/api_test.py +++ b/tensorflow/python/autograph/impl/api_test.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import functools import gc import numpy as np @@ -28,6 +29,7 @@ from tensorflow.python.autograph.impl import api from tensorflow.python.autograph.pyct import parser from tensorflow.python.autograph.utils import py_func from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.keras.engine import sequential from tensorflow.python.keras.layers import core from tensorflow.python.ops import variables @@ -43,6 +45,7 @@ class TestResource(str): class ApiTest(test.TestCase): + @test_util.run_deprecated_v1 def test_decorator_recurses(self): class TestClass(object): @@ -63,8 +66,9 @@ class ApiTest(test.TestCase): x = tc.test_method( constant_op.constant([2, 4]), constant_op.constant(1), constant_op.constant(-2)) - self.assertListEqual([0, 1], sess.run(x).tolist()) + self.assertListEqual([0, 1], self.evaluate(x).tolist()) + @test_util.run_deprecated_v1 def test_decorator_does_not_recurse(self): class TestClass(object): @@ -83,8 +87,9 @@ class ApiTest(test.TestCase): x = tc.test_method( constant_op.constant([2, 4]), constant_op.constant(1), constant_op.constant(-2)) - self.assertListEqual([0, 1], sess.run(x).tolist()) + self.assertListEqual([0, 1], self.evaluate(x).tolist()) + @test_util.run_deprecated_v1 def test_decorator_calls_unconverted_graph(self): class TestClass(object): @@ -104,8 +109,9 @@ class ApiTest(test.TestCase): x = tc.test_method( constant_op.constant([2, 4]), constant_op.constant(1), constant_op.constant(-2)) - self.assertListEqual([0, 1], sess.run(x).tolist()) + self.assertListEqual([0, 1], self.evaluate(x).tolist()) + @test_util.run_deprecated_v1 def test_decorator_calls_unconverted_py_func(self): class TestClass(object): @@ -130,8 +136,9 @@ class ApiTest(test.TestCase): x = tc.test_method( constant_op.constant([2, 4]), constant_op.constant(1), constant_op.constant(-2)) - self.assertListEqual([0, 1], sess.run(x).tolist()) + self.assertListEqual([0, 1], self.evaluate(x).tolist()) + @test_util.run_deprecated_v1 def test_decorator_calls_decorated(self): class TestClass(object): @@ -153,7 +160,7 @@ class ApiTest(test.TestCase): x = tc.test_method( constant_op.constant([2, 4]), constant_op.constant(1), constant_op.constant(-2)) - self.assertListEqual([0, 1], sess.run(x).tolist()) + self.assertListEqual([0, 1], self.evaluate(x).tolist()) def test_decorator_preserves_argspec(self): @@ -171,6 +178,7 @@ class ApiTest(test.TestCase): list(tf_inspect.getfullargspec(tc.called_member)), list(tf_inspect.getfullargspec(tc.called_member_converted))) + @test_util.run_deprecated_v1 def test_convert_call_site_decorator(self): class TestClass(object): @@ -192,7 +200,7 @@ class ApiTest(test.TestCase): x = tc.test_method( constant_op.constant([2, 4]), constant_op.constant(1), constant_op.constant(-2)) - self.assertListEqual([0, 1], sess.run(x).tolist()) + self.assertListEqual([0, 1], self.evaluate(x).tolist()) def test_converted_call_builtin(self): x = api.converted_call(range, None, converter.ConversionOptions(), 3) @@ -208,7 +216,27 @@ class ApiTest(test.TestCase): with self.cached_session() as sess: x = api.converted_call(test_fn, None, converter.ConversionOptions(), constant_op.constant(-1)) - self.assertEqual(1, sess.run(x)) + self.assertEqual(1, self.evaluate(x)) + + def test_converted_call_functools_partial(self): + + def test_fn(x, y, z): + if x < 0: + return -x, -y, -z + return x, y, z + + x = api.converted_call( + functools.partial(test_fn, constant_op.constant(-1), z=-3), + None, converter.ConversionOptions(), + constant_op.constant(-2)) + self.assertEqual((1, 2, 3), self.evaluate(x)) + + x = api.converted_call( + functools.partial( + functools.partial(test_fn, constant_op.constant(-1)), z=-3), + None, converter.ConversionOptions(), + constant_op.constant(-2)) + self.assertEqual((1, 2, 3), self.evaluate(x)) def test_converted_call_method_explicit_owner(self): # TODO(mdan): Implement. @@ -234,7 +262,7 @@ class ApiTest(test.TestCase): tc = TestClass(constant_op.constant(-1)) x = api.converted_call(tc.test_method, None, converter.ConversionOptions(), tc) - self.assertEqual(1, sess.run(x)) + self.assertEqual(1, self.evaluate(x)) def test_converted_call_method_by_class(self): @@ -252,7 +280,7 @@ class ApiTest(test.TestCase): tc = TestClass(constant_op.constant(-1)) x = api.converted_call(TestClass.test_method, None, converter.ConversionOptions(), tc) - self.assertEqual(1, sess.run(x)) + self.assertEqual(1, self.evaluate(x)) def test_converted_call_callable_object(self): @@ -269,7 +297,7 @@ class ApiTest(test.TestCase): with self.cached_session() as sess: tc = TestClass(constant_op.constant(-1)) x = api.converted_call(tc, None, converter.ConversionOptions()) - self.assertEqual(1, sess.run(x)) + self.assertEqual(1, self.evaluate(x)) def test_converted_call_constructor(self): @@ -288,7 +316,7 @@ class ApiTest(test.TestCase): constant_op.constant(-1)) # tc is now a converted object. x = tc.test_method() - self.assertEqual(1, sess.run(x)) + self.assertEqual(1, self.evaluate(x)) def test_converted_call_already_converted(self): @@ -298,13 +326,14 @@ class ApiTest(test.TestCase): with self.cached_session() as sess: x = api.converted_call(f, None, converter.ConversionOptions(), constant_op.constant(0)) - self.assertTrue(sess.run(x)) + self.assertTrue(self.evaluate(x)) converted_f = api.to_graph(f) x = api.converted_call(converted_f, None, converter.ConversionOptions(), constant_op.constant(0)) - self.assertTrue(sess.run(x)) + self.assertTrue(self.evaluate(x)) + @test_util.run_deprecated_v1 def test_converted_call_no_user_code(self): def f(x): @@ -334,8 +363,8 @@ class ApiTest(test.TestCase): constant_op.constant([[0.0]]), training=True) with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - self.assertAllEqual([[0.0, 0.0]], sess.run(x)) + self.evaluate(variables.global_variables_initializer()) + self.assertAllEqual([[0.0, 0.0]], self.evaluate(x)) def test_converted_call_whitelisted_method_extra_self(self): @@ -349,8 +378,8 @@ class ApiTest(test.TestCase): model, constant_op.constant([[0.0]]), training=True) with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - self.assertAllEqual([[0.0, 0.0]], sess.run(x)) + self.evaluate(variables.global_variables_initializer()) + self.assertAllEqual([[0.0, 0.0]], self.evaluate(x)) def test_converted_call_whitelisted_method_via_owner(self): @@ -364,8 +393,8 @@ class ApiTest(test.TestCase): constant_op.constant([[0.0]]), training=True) with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - self.assertAllEqual([[0.0, 0.0]], sess.run(x)) + self.evaluate(variables.global_variables_initializer()) + self.assertAllEqual([[0.0, 0.0]], self.evaluate(x)) def test_converted_call_lambda(self): @@ -376,9 +405,10 @@ class ApiTest(test.TestCase): x = api.converted_call(l, None, opts, constant_op.constant(0)) with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - self.assertAllEqual(True, sess.run(x)) + self.evaluate(variables.global_variables_initializer()) + self.assertAllEqual(True, self.evaluate(x)) + @test_util.run_deprecated_v1 def test_to_graph_basic(self): def test_fn(x, s): @@ -390,8 +420,9 @@ class ApiTest(test.TestCase): with self.cached_session() as sess: x = compiled_fn(constant_op.constant([4, 8]), 4) - self.assertListEqual([1, 2], sess.run(x).tolist()) + self.assertListEqual([1, 2], self.evaluate(x).tolist()) + @test_util.run_deprecated_v1 def test_to_graph_with_defaults(self): foo = 4 @@ -405,7 +436,7 @@ class ApiTest(test.TestCase): with self.cached_session() as sess: x = compiled_fn(constant_op.constant([4, 8])) - self.assertListEqual([1, 2], sess.run(x).tolist()) + self.assertListEqual([1, 2], self.evaluate(x).tolist()) def test_to_code_basic(self): diff --git a/tensorflow/python/autograph/impl/conversion.py b/tensorflow/python/autograph/impl/conversion.py index 328a4b5fe4..f8decd24e8 100644 --- a/tensorflow/python/autograph/impl/conversion.py +++ b/tensorflow/python/autograph/impl/conversion.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import functools import imp import gast @@ -72,12 +73,31 @@ def is_whitelisted_for_graph(o): Returns: Boolean """ - m = tf_inspect.getmodule(o) + # TODO(b/120224672): Fix this. + if isinstance(o, functools.partial): + # tf_inspect.getmodule(functools.partial(...)) otherwise returns None since + # functools.partial objects do not have a __module__ attribute. + m = functools + else: + m = tf_inspect.getmodule(o) for prefix, in config.DEFAULT_UNCOMPILED_MODULES: if m.__name__.startswith(prefix): return True + if hasattr(o, 'autograph_info__'): return True + + if inspect_utils.isnamedtuple(o): + # Due to the way they're constructed, namedtuple types cannot be converted + # because they don't expose source code. But we assume they are safe for + # graph mode since they are just containers. + if tf_inspect.isclass(o) and len(o.__bases__) > 1: + logging.log_first_n( + logging.level_warning(), + 'Entity {} looks like a namedtuple subclass. If it has any custom' + ' methods, they will not be converted by AutoGraph.'.format(o), 1) + return True + return False @@ -281,11 +301,10 @@ def function_to_graph(f, node, source = parser.parse_entity(f) node = node.body[0] - # In general, the output of inspect.getsource is inexact because it uses crude - # regex matching methods to search the source file. This is particularly - # problematic for lambda functions, where the entire containing lines are - # returned. Certain distributions of CPython may also return the enclosing - # function for local functions. + # In general, the output of inspect.getsource is inexact because it uses + # regex matching to adjust the exact location around the line number that + # CPython records. This is particularly problematic for lambda functions, + # where the entire containing lines are returned. nodes = ast_util.find_matching_definitions(node, f) if len(nodes) != 1: if f.__name__ == '': @@ -298,8 +317,8 @@ def function_to_graph(f, raise ValueError( 'Unable to identify source code of function {}. The source code' ' reported by Python did not include exactly one matching signature:' - '\n{}\nTo avoid ambiguity, use a unique name for each' - ' function.'.format(f, source)) + '\n{}\n. This is an extremely rare occurrence. Please report it to' + ' the TensorFlow team.'.format(f, source)) node, = nodes # TODO(znado): Place inside standard_analysis. diff --git a/tensorflow/python/autograph/lang/special_functions_test.py b/tensorflow/python/autograph/lang/special_functions_test.py index 123ee65b32..8d40f4036c 100644 --- a/tensorflow/python/autograph/lang/special_functions_test.py +++ b/tensorflow/python/autograph/lang/special_functions_test.py @@ -36,7 +36,7 @@ class SpecialFunctionsTest(test.TestCase): python_one = special_functions.match_staging_level(1, 1) with self.cached_session() as sess: self.assertTrue(tensor_util.is_tensor(tensor_one)) - self.assertAllEqual(sess.run(tensor_one), 1) + self.assertAllEqual(self.evaluate(tensor_one), 1) self.assertEqual(python_one, 1) def test_tensor_list_empty_list(self): @@ -45,21 +45,21 @@ class SpecialFunctionsTest(test.TestCase): element_shape=()) sl = list_ops.tensor_list_stack(l, element_dtype=dtypes.int32) with self.cached_session() as sess: - self.assertAllEqual(sess.run(sl), []) + self.assertAllEqual(self.evaluate(sl), []) l = special_functions.tensor_list((), element_dtype=dtypes.int32, element_shape=()) sl = list_ops.tensor_list_stack(l, element_dtype=dtypes.int32) with self.cached_session() as sess: - self.assertAllEqual(sess.run(sl), []) + self.assertAllEqual(self.evaluate(sl), []) def test_tensor_list_tensor(self): l = special_functions.tensor_list( constant_op.constant([], dtype=dtypes.int32)) sl = list_ops.tensor_list_stack(l, element_dtype=dtypes.int32) with self.cached_session() as sess: - self.assertAllEqual(sess.run(sl), []) + self.assertAllEqual(self.evaluate(sl), []) def test_tensor_list_unsupported_initializer(self): with self.assertRaisesRegexp(ValueError, 'unknown type'): @@ -76,7 +76,7 @@ class SpecialFunctionsTest(test.TestCase): l = special_functions.tensor_list(elements) sl = list_ops.tensor_list_stack(l, element_dtype=dtypes.int32) with self.cached_session() as sess: - self.assertAllEqual(sess.run(sl), [[1, 2], [3, 4]]) + self.assertAllEqual(self.evaluate(sl), [[1, 2], [3, 4]]) def test_tensor_list_array_from_elements(self): elements = [constant_op.constant([1, 2]), constant_op.constant([3, 4])] @@ -84,7 +84,7 @@ class SpecialFunctionsTest(test.TestCase): l = special_functions.tensor_list(elements, use_tensor_array=True) sl = l.stack() with self.cached_session() as sess: - self.assertAllEqual(sess.run(sl), [[1, 2], [3, 4]]) + self.assertAllEqual(self.evaluate(sl), [[1, 2], [3, 4]]) def test_stack(self): self.assertEqual(special_functions.stack(1, strict=False), 1) diff --git a/tensorflow/python/autograph/operators/control_flow.py b/tensorflow/python/autograph/operators/control_flow.py index 6eedd695a7..670897744a 100644 --- a/tensorflow/python/autograph/operators/control_flow.py +++ b/tensorflow/python/autograph/operators/control_flow.py @@ -61,7 +61,7 @@ def for_stmt(iter_, extra_test, body, init_state): """ if tensor_util.is_tensor(iter_): return _known_len_for_stmt(iter_, extra_test, body, init_state) - elif isinstance(iter_, dataset_ops.Dataset): + elif isinstance(iter_, dataset_ops.DatasetV2): return _dataset_for_stmt(iter_, extra_test, body, init_state) else: return _py_for_stmt(iter_, extra_test, body, init_state) @@ -123,7 +123,7 @@ def _dataset_for_stmt(ds, extra_test, body, init_state): (dataset_ops.Dataset.from_tensors(tag).repeat(), ds)) ds_with_epoch = epoch_numbers.flat_map(lambda i: tag_with(ds, i)) - iterator = ds_with_epoch.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(ds_with_epoch) with ops.control_dependencies((iterator.initializer,)): epoch_number, iterate = iterator.get_next() diff --git a/tensorflow/python/autograph/operators/control_flow_test.py b/tensorflow/python/autograph/operators/control_flow_test.py index 2dea18dc5f..0a7d4b6402 100644 --- a/tensorflow/python/autograph/operators/control_flow_test.py +++ b/tensorflow/python/autograph/operators/control_flow_test.py @@ -22,12 +22,14 @@ from tensorflow.python.autograph.operators import control_flow from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.platform import test class ForLoopTest(test.TestCase): + @test_util.run_deprecated_v1 def test_tensor(self): s = control_flow.for_stmt( constant_op.constant([1, 2, 3, 4]), @@ -35,7 +37,7 @@ class ForLoopTest(test.TestCase): body=lambda i, s: (s + i,), init_state=(0,)) with self.cached_session() as sess: - self.assertEqual((10,), sess.run(s)) + self.assertEqual((10,), self.evaluate(s)) def test_python(self): s = control_flow.for_stmt( @@ -45,6 +47,7 @@ class ForLoopTest(test.TestCase): init_state=(0,)) self.assertEqual(10, s) + @test_util.run_deprecated_v1 def test_dataset(self): to_int32 = lambda i: math_ops.cast(i, dtypes.int32) s = control_flow.for_stmt( @@ -53,11 +56,12 @@ class ForLoopTest(test.TestCase): body=lambda i, s: (s + i,), init_state=(0,)) with self.cached_session() as sess: - self.assertEqual((10,), sess.run(s)) + self.assertEqual((10,), self.evaluate(s)) class WhileLoopTest(test.TestCase): + @test_util.run_deprecated_v1 def test_tensor(self): n = constant_op.constant(5) results = control_flow.while_stmt( @@ -66,7 +70,7 @@ class WhileLoopTest(test.TestCase): init_state=(0, 0), extra_deps=(n,)) with self.cached_session() as sess: - self.assertEqual((5, 10), sess.run(results)) + self.assertEqual((5, 10), self.evaluate(results)) def test_python(self): n = 5 @@ -87,23 +91,25 @@ class IfStmtTest(test.TestCase): return control_flow.if_stmt( cond=cond, body=lambda: (1, 2), orelse=lambda: (-1, -2)) + @test_util.run_deprecated_v1 def test_tensor(self): with self.cached_session() as sess: t = self.single_return_if_stmt(constant_op.constant(True)) - self.assertEqual(1, sess.run(t)) + self.assertEqual(1, self.evaluate(t)) t = self.single_return_if_stmt(constant_op.constant(False)) - self.assertEqual(-1, sess.run(t)) + self.assertEqual(-1, self.evaluate(t)) def test_python(self): self.assertEqual(1, self.single_return_if_stmt(True)) self.assertEqual(-1, self.single_return_if_stmt(False)) + @test_util.run_deprecated_v1 def test_tensor_multiple_returns(self): with self.cached_session() as sess: t = self.multi_return_if_stmt(constant_op.constant(True)) - self.assertAllEqual([1, 2], sess.run(t)) + self.assertAllEqual([1, 2], self.evaluate(t)) t = self.multi_return_if_stmt(constant_op.constant(False)) - self.assertAllEqual([-1, -2], sess.run(t)) + self.assertAllEqual([-1, -2], self.evaluate(t)) def test_python_multiple_returns(self): self.assertEqual((1, 2), self.multi_return_if_stmt(True)) diff --git a/tensorflow/python/autograph/operators/data_structures_test.py b/tensorflow/python/autograph/operators/data_structures_test.py index 6039b07982..c5a3a3d1ca 100644 --- a/tensorflow/python/autograph/operators/data_structures_test.py +++ b/tensorflow/python/autograph/operators/data_structures_test.py @@ -22,6 +22,7 @@ from tensorflow.python.autograph.operators import data_structures from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import list_ops from tensorflow.python.ops import tensor_array_ops from tensorflow.python.platform import test @@ -43,7 +44,7 @@ class ListTest(test.TestCase): l = data_structures.tf_tensor_list_new([3, 4, 5]) t = list_ops.tensor_list_stack(l, element_dtype=dtypes.int32) with self.cached_session() as sess: - self.assertAllEqual(sess.run(t), [3, 4, 5]) + self.assertAllEqual(self.evaluate(t), [3, 4, 5]) def test_tf_tensor_list_new_empty(self): l = data_structures.tf_tensor_list_new([], @@ -51,14 +52,15 @@ class ListTest(test.TestCase): element_shape=()) t = list_ops.tensor_list_stack(l, element_dtype=dtypes.int32) with self.cached_session() as sess: - self.assertAllEqual(sess.run(t), []) + self.assertAllEqual(self.evaluate(t), []) def test_tf_tensor_list_new_from_tensor(self): l = data_structures.tf_tensor_list_new(constant_op.constant([3, 4, 5])) t = list_ops.tensor_list_stack(l, element_dtype=dtypes.int32) with self.cached_session() as sess: - self.assertAllEqual(sess.run(t), [3, 4, 5]) + self.assertAllEqual(self.evaluate(t), [3, 4, 5]) + @test_util.run_deprecated_v1 def test_tf_tensor_list_new_illegal_input(self): with self.assertRaises(ValueError): data_structures.tf_tensor_list_new([3, 4.0]) @@ -77,7 +79,7 @@ class ListTest(test.TestCase): l = data_structures.tf_tensor_array_new([3, 4, 5]) t = l.stack() with self.cached_session() as sess: - self.assertAllEqual(sess.run(t), [3, 4, 5]) + self.assertAllEqual(self.evaluate(t), [3, 4, 5]) def test_tf_tensor_array_new_illegal_input(self): with self.assertRaises(ValueError): @@ -102,15 +104,16 @@ class ListTest(test.TestCase): t = list_ops.tensor_list_stack(l, element_dtype=x.dtype) with self.cached_session() as sess: - self.assertAllEqual(sess.run(t), [[1, 2, 3]]) + self.assertAllEqual(self.evaluate(t), [[1, 2, 3]]) + @test_util.run_v1_only("b/117943489") def test_append_tensorarray(self): l = tensor_array_ops.TensorArray(dtypes.int32, size=0, dynamic_size=True) l1 = data_structures.list_append(l, 1) l2 = data_structures.list_append(l1, 2) with self.cached_session() as sess: - self.assertAllEqual(sess.run(l1.stack()), [1]) - self.assertAllEqual(sess.run(l2.stack()), [1, 2]) + self.assertAllEqual(self.evaluate(l1.stack()), [1]) + self.assertAllEqual(self.evaluate(l2.stack()), [1, 2]) def test_append_python(self): l = [] @@ -131,10 +134,10 @@ class ListTest(test.TestCase): with self.cached_session() as sess: l, x = data_structures.list_pop(l, None, opts) - self.assertAllEqual(sess.run(x), [3, 4]) + self.assertAllEqual(self.evaluate(x), [3, 4]) t = list_ops.tensor_list_stack(l, element_dtype=initial_list.dtype) - self.assertAllEqual(sess.run(t), [[1, 2]]) + self.assertAllEqual(self.evaluate(t), [[1, 2]]) def test_pop_python(self): l = [1, 2, 3] @@ -152,12 +155,12 @@ class ListTest(test.TestCase): with self.cached_session() as sess: t = data_structures.list_stack(l, opts) - self.assertAllEqual(sess.run(t), sess.run(initial_list)) + self.assertAllEqual(self.evaluate(t), self.evaluate(initial_list)) + @test_util.run_deprecated_v1 def test_stack_tensor_list_empty(self): l = list_ops.empty_tensor_list( - element_shape=-1, - element_dtype=dtypes.variant) + element_shape=None, element_dtype=dtypes.variant) opts = data_structures.ListStackOpts( element_dtype=dtypes.int32, original_call=None) diff --git a/tensorflow/python/autograph/operators/exceptions_test.py b/tensorflow/python/autograph/operators/exceptions_test.py index 186535d05b..21ba76bb95 100644 --- a/tensorflow/python/autograph/operators/exceptions_test.py +++ b/tensorflow/python/autograph/operators/exceptions_test.py @@ -21,6 +21,7 @@ from __future__ import print_function from tensorflow.python.autograph.operators import exceptions from tensorflow.python.framework import constant_op from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -30,8 +31,9 @@ class ExceptionsTest(test.TestCase): with self.cached_session() as sess: t = exceptions.assert_stmt( constant_op.constant(True), lambda: constant_op.constant('ignored')) - sess.run(t) + self.evaluate(t) + @test_util.run_deprecated_v1 def test_assert_tf_triggered(self): with self.cached_session() as sess: t = exceptions.assert_stmt( @@ -40,8 +42,9 @@ class ExceptionsTest(test.TestCase): with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, 'test message'): - sess.run(t) + self.evaluate(t) + @test_util.run_deprecated_v1 def test_assert_tf_multiple_printed_values(self): two_tensors = [ constant_op.constant('test message'), @@ -53,7 +56,7 @@ class ExceptionsTest(test.TestCase): with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, 'test message.*another message'): - sess.run(t) + self.evaluate(t) def test_assert_python_untriggered(self): side_effect_trace = [] diff --git a/tensorflow/python/autograph/operators/logical_test.py b/tensorflow/python/autograph/operators/logical_test.py index d6649f7b2b..e22f39932d 100644 --- a/tensorflow/python/autograph/operators/logical_test.py +++ b/tensorflow/python/autograph/operators/logical_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python.autograph.operators import logical from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -42,14 +43,15 @@ class LogicalOperatorsTest(test.TestCase): self.assertFalse(logical.and_(lambda: False, lambda: True)) self.assertFalse(logical.and_(lambda: False, self.assertNotCalled)) + @test_util.run_deprecated_v1 def test_and_tf(self): with self.cached_session() as sess: t = logical.and_(self._tf_true, self._tf_true) - self.assertEqual(sess.run(t), True) + self.assertEqual(self.evaluate(t), True) t = logical.and_(self._tf_true, lambda: True) - self.assertEqual(sess.run(t), True) + self.assertEqual(self.evaluate(t), True) t = logical.and_(self._tf_false, lambda: True) - self.assertEqual(sess.run(t), False) + self.assertEqual(self.evaluate(t), False) # TODO(mdan): Add a test for ops with side effects. def test_or_python(self): @@ -60,14 +62,15 @@ class LogicalOperatorsTest(test.TestCase): self.assertTrue(logical.or_(lambda: False, lambda: True)) self.assertTrue(logical.or_(lambda: True, self.assertNotCalled)) + @test_util.run_deprecated_v1 def test_or_tf(self): with self.cached_session() as sess: t = logical.or_(self._tf_false, self._tf_true) - self.assertEqual(sess.run(t), True) + self.assertEqual(self.evaluate(t), True) t = logical.or_(self._tf_false, lambda: True) - self.assertEqual(sess.run(t), True) + self.assertEqual(self.evaluate(t), True) t = logical.or_(self._tf_true, lambda: True) - self.assertEqual(sess.run(t), True) + self.assertEqual(self.evaluate(t), True) # TODO(mdan): Add a test for ops with side effects. def test_not_python(self): @@ -78,7 +81,7 @@ class LogicalOperatorsTest(test.TestCase): def test_not_tf(self): with self.cached_session() as sess: t = logical.not_(self._tf_false()) - self.assertEqual(sess.run(t), True) + self.assertEqual(self.evaluate(t), True) if __name__ == '__main__': diff --git a/tensorflow/python/autograph/operators/py_builtins_test.py b/tensorflow/python/autograph/operators/py_builtins_test.py index 443e30a475..c856e39d14 100644 --- a/tensorflow/python/autograph/operators/py_builtins_test.py +++ b/tensorflow/python/autograph/operators/py_builtins_test.py @@ -27,6 +27,7 @@ from tensorflow.python.autograph.operators import py_builtins from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import tensor_array_ops from tensorflow.python.platform import test @@ -38,29 +39,29 @@ class PyBuiltinsTest(test.TestCase): self.assertEqual(py_builtins.abs_(-1), 1) with self.cached_session() as sess: t = py_builtins.abs_(constant_op.constant(-1)) - self.assertEqual(sess.run(t), 1) + self.assertEqual(self.evaluate(t), 1) t = py_builtins.abs_(constant_op.constant([-1, 2, -3])) - self.assertAllEqual(sess.run(t), [1, 2, 3]) + self.assertAllEqual(self.evaluate(t), [1, 2, 3]) def test_float(self): self.assertEqual(py_builtins.float_(10), 10.0) self.assertEqual(py_builtins.float_('10.0'), 10.0) with self.cached_session() as sess: t = py_builtins.float_(constant_op.constant(1, dtype=dtypes.int64)) - self.assertEqual(sess.run(t), 1.0) + self.assertEqual(self.evaluate(t), 1.0) st = py_builtins.float_(constant_op.constant('1.0')) - self.assertEqual(sess.run(st), 1.0) + self.assertEqual(self.evaluate(st), 1.0) def test_int(self): self.assertEqual(py_builtins.int_(10.0), 10) self.assertEqual(py_builtins.int_('11', 2), 3) with self.cached_session() as sess: t = py_builtins.int_(constant_op.constant(1, dtype=dtypes.float64)) - self.assertEqual(sess.run(t), 1) + self.assertEqual(self.evaluate(t), 1) st = py_builtins.int_(constant_op.constant('1')) - self.assertEqual(sess.run(st), 1) + self.assertEqual(self.evaluate(st), 1) st = py_builtins.int_(constant_op.constant('1'), 10) - self.assertEqual(sess.run(st), 1) + self.assertEqual(self.evaluate(st), 1) def test_int_unsupported_base(self): t = constant_op.constant(1, dtype=dtypes.float64) @@ -73,14 +74,15 @@ class PyBuiltinsTest(test.TestCase): t = py_builtins.len_(constant_op.constant([[1], [2], [3]])) self.assertEqual(t, 3) ta = py_builtins.len_(tensor_array_ops.TensorArray(dtypes.int32, size=5)) - self.assertEqual(sess.run(ta), 5) + self.assertEqual(self.evaluate(ta), 5) tl = py_builtins.len_(data_structures.tf_tensor_list_new([3, 4, 5])) - self.assertEqual(sess.run(tl), 3) + self.assertEqual(self.evaluate(tl), 3) def test_len_scalar(self): with self.assertRaises(ValueError): py_builtins.len_(constant_op.constant(1)) + @test_util.run_deprecated_v1 def test_len_dynamic_shape(self): with self.cached_session() as sess: p = array_ops.placeholder(dtype=dtypes.int32, shape=None) @@ -91,6 +93,7 @@ class PyBuiltinsTest(test.TestCase): t = py_builtins.len_(p) sess.run(t, {p: 1}) + @test_util.run_deprecated_v1 def test_print_tensors(self): try: out_capturer = six.StringIO() @@ -101,6 +104,7 @@ class PyBuiltinsTest(test.TestCase): finally: sys.stdout = sys.__stdout__ + @test_util.run_deprecated_v1 def test_print_complex(self): try: out_capturer = six.StringIO() @@ -120,18 +124,18 @@ class PyBuiltinsTest(test.TestCase): def test_range_tensor(self): with self.cached_session() as sess: r = py_builtins.range_(constant_op.constant(3)) - self.assertAllEqual(sess.run(r), [0, 1, 2]) + self.assertAllEqual(self.evaluate(r), [0, 1, 2]) r = py_builtins.range_(1, constant_op.constant(3)) - self.assertAllEqual(sess.run(r), [1, 2]) + self.assertAllEqual(self.evaluate(r), [1, 2]) r = py_builtins.range_(2, 0, constant_op.constant(-1)) - self.assertAllEqual(sess.run(r), [2, 1]) + self.assertAllEqual(self.evaluate(r), [2, 1]) def test_range_tensor_empty_range(self): with self.session() as sess: r = py_builtins.range_(constant_op.constant(-3)) - self.assertAllEqual(sess.run(r), []) + self.assertAllEqual(self.evaluate(r), []) r = py_builtins.range_(5, constant_op.constant(2)) - self.assertAllEqual(sess.run(r), []) + self.assertAllEqual(self.evaluate(r), []) if __name__ == '__main__': diff --git a/tensorflow/python/autograph/operators/slices_test.py b/tensorflow/python/autograph/operators/slices_test.py index 9e4865b3c6..d444054fd7 100644 --- a/tensorflow/python/autograph/operators/slices_test.py +++ b/tensorflow/python/autograph/operators/slices_test.py @@ -34,7 +34,7 @@ class SlicesTest(test.TestCase): with self.cached_session() as sess: t = list_ops.tensor_list_stack(l, element_dtype=initial_list.dtype) - self.assertAllEqual(sess.run(t), [[5, 6], [3, 4]]) + self.assertAllEqual(self.evaluate(t), [[5, 6], [3, 4]]) def test_get_item_tensor_list(self): initial_list = constant_op.constant([[1, 2], [3, 4]]) @@ -44,7 +44,7 @@ class SlicesTest(test.TestCase): l, 1, slices.GetItemOpts(element_dtype=initial_list.dtype)) with self.cached_session() as sess: - self.assertAllEqual(sess.run(t), [3, 4]) + self.assertAllEqual(self.evaluate(t), [3, 4]) def test_get_item_tensor_string(self): initial_str = constant_op.constant('abcd') @@ -52,14 +52,14 @@ class SlicesTest(test.TestCase): slices.GetItemOpts(element_dtype=initial_str.dtype)) with self.cached_session() as sess: - self.assertEqual(sess.run(t), b'b') + self.assertEqual(self.evaluate(t), b'b') initial_list_str = constant_op.constant(['abcd', 'bcde']) t = slices.get_item(initial_list_str, 1, slices.GetItemOpts(element_dtype=initial_str.dtype)) with self.cached_session() as sess: - self.assertEqual(sess.run(t), b'bcde') + self.assertEqual(self.evaluate(t), b'bcde') if __name__ == '__main__': diff --git a/tensorflow/python/autograph/pyct/BUILD b/tensorflow/python/autograph/pyct/BUILD index ddadc6b96e..ba8ec27139 100644 --- a/tensorflow/python/autograph/pyct/BUILD +++ b/tensorflow/python/autograph/pyct/BUILD @@ -80,7 +80,6 @@ py_test( name = "compiler_test", srcs = ["compiler_test.py"], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ ":pyct", "//tensorflow/python:client_testlib", @@ -154,7 +153,6 @@ py_test( name = "transformer_test", srcs = ["transformer_test.py"], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ ":pyct", "//tensorflow/python:client_testlib", diff --git a/tensorflow/python/autograph/pyct/inspect_utils.py b/tensorflow/python/autograph/pyct/inspect_utils.py index 4d56b93671..7c819f364f 100644 --- a/tensorflow/python/autograph/pyct/inspect_utils.py +++ b/tensorflow/python/autograph/pyct/inspect_utils.py @@ -46,6 +46,28 @@ if six.PY2: SPECIAL_BUILTINS['xrange'] = xrange +def islambda(f): + if not tf_inspect.isfunction(f): + return False + if not hasattr(f, '__name__'): + return False + return f.__name__ == '' + + +def isnamedtuple(f): + """Returns True if the argument is a namedtuple-like.""" + if not (tf_inspect.isclass(f) and issubclass(f, tuple)): + return False + if not hasattr(f, '_fields'): + return False + fields = getattr(f, '_fields') + if not isinstance(fields, tuple): + return False + if not all(isinstance(f, str) for f in fields): + return False + return True + + def isbuiltin(f): """Returns True if the argument is a built-in function.""" if f in SPECIAL_BUILTINS.values(): diff --git a/tensorflow/python/autograph/pyct/inspect_utils_test.py b/tensorflow/python/autograph/pyct/inspect_utils_test.py index 622e3bafc0..a2c39056d1 100644 --- a/tensorflow/python/autograph/pyct/inspect_utils_test.py +++ b/tensorflow/python/autograph/pyct/inspect_utils_test.py @@ -18,7 +18,8 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from functools import wraps +import collections +import functools import imp import types import weakref @@ -46,7 +47,7 @@ def wrapping_decorator(): def replacement(*_): return None - @wraps(f) + @functools.wraps(f) def wrapper(*args, **kwargs): return replacement(*args, **kwargs) return wrapper @@ -95,6 +96,38 @@ def free_factory(): class InspectUtilsTest(test.TestCase): + def test_islambda(self): + def test_fn(): + pass + + self.assertTrue(inspect_utils.islambda(lambda x: x)) + self.assertFalse(inspect_utils.islambda(test_fn)) + + def test_isnamedtuple(self): + nt = collections.namedtuple('TestNamedTuple', ['a', 'b']) + + class NotANamedTuple(tuple): + pass + + self.assertTrue(inspect_utils.isnamedtuple(nt)) + self.assertFalse(inspect_utils.isnamedtuple(NotANamedTuple)) + + def test_isnamedtuple_confounder(self): + """This test highlights false positives when detecting named tuples.""" + + class NamedTupleLike(tuple): + _fields = ('a', 'b') + + self.assertTrue(inspect_utils.isnamedtuple(NamedTupleLike)) + + def test_isnamedtuple_subclass(self): + """This test highlights false positives when detecting named tuples.""" + + class NamedTupleSubclass(collections.namedtuple('Test', ['a', 'b'])): + pass + + self.assertTrue(inspect_utils.isnamedtuple(NamedTupleSubclass)) + def test_getnamespace_globals(self): ns = inspect_utils.getnamespace(factory) self.assertEqual(ns['free_function'], free_function) diff --git a/tensorflow/python/autograph/pyct/static_analysis/BUILD b/tensorflow/python/autograph/pyct/static_analysis/BUILD index 4a4ccdcbd1..5e260c5730 100644 --- a/tensorflow/python/autograph/pyct/static_analysis/BUILD +++ b/tensorflow/python/autograph/pyct/static_analysis/BUILD @@ -38,7 +38,6 @@ py_test( name = "activity_test", srcs = ["activity_test.py"], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ ":static_analysis", "//tensorflow/python:client_testlib", @@ -51,7 +50,6 @@ py_test( name = "live_values_test", srcs = ["live_values_test.py"], srcs_version = "PY2AND3", - tags = ["no_windows"], deps = [ ":static_analysis", "//tensorflow/python:client_testlib", diff --git a/tensorflow/python/autograph/pyct/static_analysis/liveness.py b/tensorflow/python/autograph/pyct/static_analysis/liveness.py index 451398f1b7..f8b8d7fa77 100644 --- a/tensorflow/python/autograph/pyct/static_analysis/liveness.py +++ b/tensorflow/python/autograph/pyct/static_analysis/liveness.py @@ -161,6 +161,16 @@ class Annotator(transformer.Base): self.cross_function_analyzer = cross_function_analyzer self.current_analyzer = None + def visit(self, node): + node = super(Annotator, self).visit(node) + if (self.current_analyzer is not None and + isinstance(node, gast.stmt) and + node in self.current_analyzer.graph.index): + cfg_node = self.current_analyzer.graph.index[node] + anno.setanno(node, anno.Static.LIVE_VARS_IN, + frozenset(self.current_analyzer.in_[cfg_node])) + return node + def visit_FunctionDef(self, node): parent_analyzer = self.current_analyzer self.current_analyzer = self.cross_function_analyzer.analyzers[node] @@ -198,6 +208,10 @@ class Annotator(transformer.Base): node = self._block_statement_live_out(node) return self._block_statement_live_in(node, node.test) + def visit_With(self, node): + node = self.generic_visit(node) + return self._block_statement_live_in(node, node.items[0]) + def visit_Expr(self, node): node = self.generic_visit(node) cfg_node = self.current_analyzer.graph.index[node] diff --git a/tensorflow/python/autograph/utils/misc_test.py b/tensorflow/python/autograph/utils/misc_test.py index 8d2b0d6e13..c78df48d62 100644 --- a/tensorflow/python/autograph/utils/misc_test.py +++ b/tensorflow/python/autograph/utils/misc_test.py @@ -19,6 +19,7 @@ from __future__ import division from __future__ import print_function from tensorflow.python.autograph.utils.misc import alias_tensors +from tensorflow.python.framework import test_util from tensorflow.python.framework.constant_op import constant from tensorflow.python.ops.variables import Variable from tensorflow.python.platform import test @@ -26,14 +27,16 @@ from tensorflow.python.platform import test class MiscTest(test.TestCase): + @test_util.run_deprecated_v1 def test_alias_single_tensor(self): a = constant(1) new_a = alias_tensors(a) self.assertFalse(new_a is a) with self.cached_session() as sess: - self.assertEqual(1, sess.run(new_a)) + self.assertEqual(1, self.evaluate(new_a)) + @test_util.run_deprecated_v1 def test_alias_tensors(self): a = constant(1) v = Variable(2) @@ -47,7 +50,7 @@ class MiscTest(test.TestCase): self.assertTrue(new_s is s) self.assertTrue(new_l is l) with self.cached_session() as sess: - self.assertEqual(1, sess.run(new_a)) + self.assertEqual(1, self.evaluate(new_a)) if __name__ == '__main__': diff --git a/tensorflow/python/autograph/utils/py_func_test.py b/tensorflow/python/autograph/utils/py_func_test.py index 1c220d9492..28cefd8c3e 100644 --- a/tensorflow/python/autograph/utils/py_func_test.py +++ b/tensorflow/python/autograph/utils/py_func_test.py @@ -34,13 +34,13 @@ class PyFuncTest(test.TestCase): with self.cached_session() as sess: result = py_func.wrap_py_func(test_fn, dtypes.int64, (1, constant_op.constant(1), 1)) - self.assertEqual(3, sess.run(result)) + self.assertEqual(3, self.evaluate(result)) result = py_func.wrap_py_func(test_fn, dtypes.int64, (1, 1, 1)) - self.assertEqual(3, sess.run(result)) + self.assertEqual(3, self.evaluate(result)) result = py_func.wrap_py_func( test_fn, dtypes.int64, (constant_op.constant(1), 1, constant_op.constant(1))) - self.assertEqual(3, sess.run(result)) + self.assertEqual(3, self.evaluate(result)) def test_wrap_py_func_complex_args(self): @@ -54,10 +54,10 @@ class PyFuncTest(test.TestCase): with self.cached_session() as sess: result = py_func.wrap_py_func(test_fn, dtypes.int64, (7, TestClass())) - self.assertEqual(35, sess.run(result)) + self.assertEqual(35, self.evaluate(result)) result = py_func.wrap_py_func(test_fn, dtypes.int64, (constant_op.constant(7), TestClass())) - self.assertEqual(35, sess.run(result)) + self.assertEqual(35, self.evaluate(result)) def test_wrap_py_func_kwargs(self): @@ -74,13 +74,13 @@ class PyFuncTest(test.TestCase): 'c': 11, 'd': TestClass(13) }) - self.assertEqual(178, sess.run(result)) + self.assertEqual(178, self.evaluate(result)) result = py_func.wrap_py_func(test_fn, dtypes.int64, (constant_op.constant(7), TestClass(5)), { 'c': constant_op.constant(11), 'd': TestClass(13) }) - self.assertEqual(178, sess.run(result)) + self.assertEqual(178, self.evaluate(result)) def test_wrap_py_func_dummy_return(self): @@ -91,11 +91,11 @@ class PyFuncTest(test.TestCase): with self.cached_session() as sess: result = py_func.wrap_py_func(test_fn, None, (5,), use_dummy_return=True) - self.assertEqual(1, sess.run(result)) + self.assertEqual(1, self.evaluate(result)) self.assertEqual([1], side_counter) result = py_func.wrap_py_func( test_fn, None, (constant_op.constant(5),), use_dummy_return=True) - self.assertEqual(1, sess.run(result)) + self.assertEqual(1, self.evaluate(result)) self.assertEqual([2], side_counter) diff --git a/tensorflow/python/autograph/utils/tensor_list_test.py b/tensorflow/python/autograph/utils/tensor_list_test.py index 697c166eb1..bbbc3bf691 100644 --- a/tensorflow/python/autograph/utils/tensor_list_test.py +++ b/tensorflow/python/autograph/utils/tensor_list_test.py @@ -19,10 +19,10 @@ from __future__ import division from __future__ import print_function from tensorflow.python.autograph.utils import tensor_list as tl -from tensorflow.python.client.session import Session from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.framework.constant_op import constant from tensorflow.python.ops import list_ops from tensorflow.python.ops import tensor_array_ops @@ -34,6 +34,7 @@ class TensorListTest(test.TestCase): def _shape(self, shape_tuple): return constant(shape_tuple, dtypes.int32) + @test_util.run_v1_only("b/117943489") def test_dynamic_list_append(self): l = [] l = tl.dynamic_list_append(l, 1) @@ -42,19 +43,16 @@ class TensorListTest(test.TestCase): l = list_ops.empty_tensor_list(self._shape(()), dtypes.int32) l = tl.dynamic_list_append(l, 1) s = list_ops.tensor_list_stack(l, element_dtype=dtypes.int32) - with self.cached_session() as sess: - self.assertAllEqual(sess.run(s), [1]) + self.assertAllEqual(s, [1]) l = tensor_array_ops.TensorArray(dtypes.int32, size=0, dynamic_size=True) l = tl.dynamic_list_append(l, 1) s = l.stack() - with self.cached_session() as sess: - self.assertAllEqual(sess.run(s), [1]) + self.assertAllEqual(s, [1]) l = tl.TensorList(self._shape(()), dtypes.int32) l = tl.dynamic_list_append(l, 1) - with self.cached_session() as sess: - self.assertAllEqual(sess.run(l[0]), 1) + self.assertAllEqual(l[0], 1) def test_list_append_python(self): with context.eager_mode(): @@ -80,6 +78,7 @@ class TensorListTest(test.TestCase): l[0] = ops.convert_to_tensor(b) self.assertEqual(l[0].numpy(), b.numpy()) + @test_util.run_deprecated_v1 def test_list_append_tf(self): a = constant(3.0) l = tl.TensorList(a.shape, a.dtype) @@ -91,13 +90,12 @@ class TensorListTest(test.TestCase): c3 = l.count() a2 = l.pop() c4 = l.count() - with Session() as sess: - c1, c2, c3, c4, a, a2 = sess.run([c1, c2, c3, c4, a, a2]) - self.assertEqual(c1, 1) - self.assertEqual(c2, 2) - self.assertEqual(c3, 1) - self.assertEqual(c4, 0) - self.assertEqual(a, a2) + c1, c2, c3, c4, a, a2 = self.evaluate([c1, c2, c3, c4, a, a2]) + self.assertEqual(c1, 1) + self.assertEqual(c2, 2) + self.assertEqual(c3, 1) + self.assertEqual(c4, 0) + self.assertEqual(a, a2) def test_list_index_tf(self): a = constant(3.0) @@ -107,10 +105,9 @@ class TensorListTest(test.TestCase): l0 = l[0] l[0] = b l1 = l[0] - with self.cached_session() as sess: - l0, l1, a, b = sess.run([l0, l1, a, b]) - self.assertEqual(l0, a) - self.assertEqual(l1, b) + l0, l1, a, b = self.evaluate([l0, l1, a, b]) + self.assertEqual(l0, a) + self.assertEqual(l1, b) if __name__ == '__main__': diff --git a/tensorflow/python/autograph/utils/type_check.py b/tensorflow/python/autograph/utils/type_check.py index 8748abc47b..ccef7dee03 100644 --- a/tensorflow/python/autograph/utils/type_check.py +++ b/tensorflow/python/autograph/utils/type_check.py @@ -30,4 +30,4 @@ def is_tensor(*args): Returns: True if any *args are TensorFlow types, False if none are. """ - return any([tensor_util.is_tensor(a) for a in args]) + return any(tensor_util.is_tensor(a) for a in args) diff --git a/tensorflow/python/autograph/utils/type_check_test.py b/tensorflow/python/autograph/utils/type_check_test.py index b3d1304e16..2521dc9f92 100644 --- a/tensorflow/python/autograph/utils/type_check_test.py +++ b/tensorflow/python/autograph/utils/type_check_test.py @@ -28,6 +28,7 @@ from tensorflow.python.platform import test class TypeCheckTest(test.TestCase): + @test_util.run_deprecated_v1 def test_checks(self): self.assertTrue(type_check.is_tensor(constant_op.constant([1, 2, 3]))) self.assertTrue( diff --git a/tensorflow/python/client/device_lib.i b/tensorflow/python/client/device_lib.i index 944e855cee..3e579152d5 100644 --- a/tensorflow/python/client/device_lib.i +++ b/tensorflow/python/client/device_lib.i @@ -48,17 +48,14 @@ static std::vector ListDevicesWithSessionConfig( std::vector output; SessionOptions options; options.config = config; - std::vector devices; + std::vector> devices; Status status = DeviceFactory::AddDevices( options, "" /* name_prefix */, &devices); if (!status.ok()) { Set_TF_Status_from_Status(out_status, status); } - std::vector> device_holder(devices.begin(), - devices.end()); - - for (const Device* device : devices) { + for (const std::unique_ptr& device : devices) { const DeviceAttributes& attr = device->attributes(); string attr_serialized; if (!attr.SerializeToString(&attr_serialized)) { diff --git a/tensorflow/python/client/session.py b/tensorflow/python/client/session.py index 06c66dda9f..87a200ed33 100644 --- a/tensorflow/python/client/session.py +++ b/tensorflow/python/client/session.py @@ -828,7 +828,7 @@ class BaseSession(SessionInterface): nested list, tuple, namedtuple, dict, or OrderedDict containing graph elements at its leaves. A graph element can be one of the following types: - * An `tf.Operation`. + * A `tf.Operation`. The corresponding fetched value will be `None`. * A `tf.Tensor`. The corresponding fetched value will be a numpy ndarray containing the @@ -1097,7 +1097,7 @@ class BaseSession(SessionInterface): if isinstance(subfeed_val, ops.Tensor): raise TypeError('The value of a feed cannot be a tf.Tensor object. ' 'Acceptable feed values include Python scalars, ' - 'strings, lists, numpy ndarrays, or TensorHandles.' + 'strings, lists, numpy ndarrays, or TensorHandles. ' 'For reference, the tensor object was ' + str(feed_val) + ' which was passed to the ' 'feed with key ' + str(feed) + '.') diff --git a/tensorflow/python/client/session_clusterspec_prop_test.py b/tensorflow/python/client/session_clusterspec_prop_test.py index df020f88a8..224f880ed1 100644 --- a/tensorflow/python/client/session_clusterspec_prop_test.py +++ b/tensorflow/python/client/session_clusterspec_prop_test.py @@ -62,7 +62,7 @@ class SessionClusterSpecPropagationTest(test_util.TensorFlowTestCase): const = constant_op.constant(17) sess = session.Session(server1.target, config=config) - output = sess.run(const) + output = self.evaluate(const) self.assertEqual(17, output) def testClusterSpecPropagationWorker2Placement(self): @@ -106,7 +106,7 @@ class SessionClusterSpecPropagationTest(test_util.TensorFlowTestCase): with ops.Graph().as_default() as g, ops.device('/job:worker/task:0'): const = constant_op.constant(17) sess = session.Session(server1.target, config=config, graph=g) - output = sess.run(const) + output = self.evaluate(const) self.assertEqual(17, output) def testCanonicalDeviceNames(self): @@ -208,7 +208,7 @@ class SessionClusterSpecPropagationTest(test_util.TensorFlowTestCase): with ops.device('/job:worker/task:0/cpu:0'): sum3 = sum1 + sum2 sess = session.Session(server1.target, config=config, graph=g) - output = sess.run(sum3) + output = self.evaluate(sum3) self.assertEqual(40, output) def testLegacyDeviceNames(self): diff --git a/tensorflow/python/client/session_partial_run_test.py b/tensorflow/python/client/session_partial_run_test.py index 92ca47efa9..a97930635a 100644 --- a/tensorflow/python/client/session_partial_run_test.py +++ b/tensorflow/python/client/session_partial_run_test.py @@ -117,7 +117,7 @@ class PartialRunTest(test_util.TensorFlowTestCase): a = constant_op.constant(2.0, dtypes.float32) b = a * 2 c = b * 3 - r1 = sess.run([b, c]) + r1 = self.evaluate([b, c]) h = sess.partial_run_setup([b, c], []) r2 = sess.partial_run(h, [b, c]) self.assertEqual(r1, r2) @@ -188,6 +188,7 @@ class PartialRunTest(test_util.TensorFlowTestCase): r = sess.partial_run(h, [b], {}) self.assertEqual([6.0], r) + @test_util.run_deprecated_v1 def testInvalidPartialRunSetup(self): sess = session.Session() x = array_ops.placeholder(dtypes.float32, shape=[]) @@ -196,6 +197,7 @@ class PartialRunTest(test_util.TensorFlowTestCase): 'specify at least one target to fetch or execute.'): sess.partial_run_setup(fetches=[], feeds=[x]) + @test_util.run_deprecated_v1 def testPartialRunSetupNoFeedsPassed(self): sess = session.Session() r1 = constant_op.constant([6.0]) @@ -204,80 +206,102 @@ class PartialRunTest(test_util.TensorFlowTestCase): result1 = sess.partial_run(h, r1) self.assertEqual([6.0], result1) + @test_util.run_deprecated_v1 def testPartialRunDirect(self): self.RunTestPartialRun(session.Session()) + @test_util.run_deprecated_v1 def testPartialRunIncompleteDirect(self): self.RunTestPartialRunIncomplete(session.Session()) + @test_util.run_deprecated_v1 def testConcurrentPartialRunDirect(self): self.RunTestConcurrentPartialRun(session.Session()) + @test_util.run_deprecated_v1 def testManyPartialRunDirect(self): self.RunTestManyPartialRun(session.Session()) + @test_util.run_deprecated_v1 def testRunAndPartialRunDirect(self): self.RunTestRunAndPartialRun(session.Session()) + @test_util.run_deprecated_v1 def testPartialRunMissingPlaceholderFeedExceptionDirect(self): self.RunTestPartialRunMissingPlaceholderFeedException(session.Session()) + @test_util.run_deprecated_v1 def testPartialRunUnspecifiedFeedDirect(self): self.RunTestPartialRunUnspecifiedFeed(session.Session()) + @test_util.run_deprecated_v1 def testPartialRunUnspecifiedFetchDirect(self): self.RunTestPartialRunUnspecifiedFetch(session.Session()) + @test_util.run_deprecated_v1 def testPartialRunAlreadyFedDirect(self): self.RunTestPartialRunAlreadyFed(session.Session()) + @test_util.run_deprecated_v1 def testPartialRunAlreadyFetchedDirect(self): self.RunTestPartialRunAlreadyFetched(session.Session()) + @test_util.run_deprecated_v1 def testPartialRunEmptyFetchesDirect(self): self.RunTestPartialRunEmptyFetches(session.Session()) + @test_util.run_deprecated_v1 def testPartialRunDist(self): server = server_lib.Server.create_local_server() self.RunTestPartialRun(session.Session(server.target)) + @test_util.run_deprecated_v1 def testPartialRunIncompleteDist(self): server = server_lib.Server.create_local_server() self.RunTestPartialRunIncomplete(session.Session(server.target)) + @test_util.run_deprecated_v1 def testConcurrentPartialRunDist(self): server = server_lib.Server.create_local_server() self.RunTestConcurrentPartialRun(session.Session(server.target)) + @test_util.run_deprecated_v1 def testManyPartialRunDist(self): server = server_lib.Server.create_local_server() self.RunTestManyPartialRun(session.Session(server.target)) + @test_util.run_deprecated_v1 def testRunAndPartialRunDist(self): server = server_lib.Server.create_local_server() self.RunTestRunAndPartialRun(session.Session(server.target)) + @test_util.run_deprecated_v1 def testPartialRunMissingPlaceholderFeedExceptionDist(self): server = server_lib.Server.create_local_server() self.RunTestPartialRunMissingPlaceholderFeedException( session.Session(server.target)) + @test_util.run_deprecated_v1 def testPartialRunUnspecifiedFeedDist(self): server = server_lib.Server.create_local_server() self.RunTestPartialRunUnspecifiedFeed(session.Session(server.target)) + @test_util.run_deprecated_v1 def testPartialRunUnspecifiedFetchDist(self): server = server_lib.Server.create_local_server() self.RunTestPartialRunUnspecifiedFetch(session.Session(server.target)) + @test_util.run_deprecated_v1 def testPartialRunAlreadyFedDist(self): server = server_lib.Server.create_local_server() self.RunTestPartialRunAlreadyFed(session.Session(server.target)) + @test_util.run_deprecated_v1 def testPartialRunAlreadyFetchedDist(self): server = server_lib.Server.create_local_server() self.RunTestPartialRunAlreadyFetched(session.Session(server.target)) + @test_util.run_deprecated_v1 def testPartialRunEmptyFetchesDist(self): server = server_lib.Server.create_local_server() self.RunTestPartialRunEmptyFetches(session.Session(server.target)) diff --git a/tensorflow/python/client/timeline_test.py b/tensorflow/python/client/timeline_test.py index dfd0147643..61c0da01b8 100644 --- a/tensorflow/python/client/timeline_test.py +++ b/tensorflow/python/client/timeline_test.py @@ -57,6 +57,7 @@ class TimelineTest(test.TestCase): ctf = tl.generate_chrome_trace_format() self._validateTrace(ctf) + @test_util.run_deprecated_v1 def testTimelineCpu(self): run_options = config_pb2.RunOptions( trace_level=config_pb2.RunOptions.FULL_TRACE) @@ -147,7 +148,7 @@ class TimelineTest(test.TestCase): num2 = variables.Variable(2.0, name='num2') with ops.device('/cpu:2'): result = num1 + num2 + num1 * num2 - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) sess.run(result, options=run_options, run_metadata=run_metadata) self.assertTrue(run_metadata.HasField('step_stats')) @@ -176,7 +177,7 @@ class TimelineTest(test.TestCase): num2 = variables.Variable(2.0, name='num2') with ops.device('/cpu:2'): result = num1 + num2 + num1 * num2 - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) sess.run(result, options=run_options, run_metadata=run_metadata) self.assertTrue(run_metadata.HasField('step_stats')) step_stats = run_metadata.step_stats diff --git a/tensorflow/python/client/virtual_gpu_test.py b/tensorflow/python/client/virtual_gpu_test.py index 5892e0fc84..e82ee0666c 100644 --- a/tensorflow/python/client/virtual_gpu_test.py +++ b/tensorflow/python/client/virtual_gpu_test.py @@ -216,7 +216,7 @@ class VirtualGpuTest(test_util.TensorFlowTestCase): for d in self._util.devices: with ops.device(d): var = variables.Variable(random_ops.random_uniform(mat_shape)) - sess.run(var.initializer) + self.evaluate(var.initializer) data.append(var) s = data[0] for i in range(1, len(data)): diff --git a/tensorflow/python/compat/BUILD b/tensorflow/python/compat/BUILD index e0a1c8e057..9f2ce8c676 100644 --- a/tensorflow/python/compat/BUILD +++ b/tensorflow/python/compat/BUILD @@ -9,7 +9,10 @@ py_library( srcs = ["compat.py"], srcs_version = "PY2AND3", visibility = ["//tensorflow:internal"], - deps = ["//tensorflow/python:util"], + deps = [ + "//tensorflow/python:tf2", + "//tensorflow/python:util", + ], ) tf_py_test( diff --git a/tensorflow/python/compat/compat.py b/tensorflow/python/compat/compat.py index 385fd431f4..0b6ff30488 100644 --- a/tensorflow/python/compat/compat.py +++ b/tensorflow/python/compat/compat.py @@ -23,10 +23,16 @@ from __future__ import division from __future__ import print_function import datetime + +from tensorflow.python import tf2 +from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_shape +from tensorflow.python.ops import variable_scope + from tensorflow.python.util import tf_contextlib from tensorflow.python.util.tf_export import tf_export -_FORWARD_COMPATIBILITY_HORIZON = datetime.date(2018, 11, 13) +_FORWARD_COMPATIBILITY_HORIZON = datetime.date(2018, 12, 4) @tf_export("compat.forward_compatible") @@ -132,3 +138,40 @@ def forward_compatibility_horizon(year, month, day): yield finally: _FORWARD_COMPATIBILITY_HORIZON = old_compat_date + + +@tf_export(v1=["enable_v2_behavior"]) +def enable_v2_behavior(): + """Enables TensorFlow 2.x behaviors. + + This function can be called at the beginning of the program (before `Tensors`, + `Graphs` or other structures have been created, and before devices have been + initialized. It switches all global behaviors that are different between + TensorFlow 1.x and 2.x to behave as intended for 2.x. + + This function is called in the main TensorFlow `__init__.py` file, user should + not need to call it, except during complex migrations. + """ + tf2.enable() # Switches TensorArrayV2 and control flow V2 + ops.enable_eager_execution() + tensor_shape.enable_v2_tensorshape() # Also switched by tf2 + variable_scope.enable_resource_variables() + + +@tf_export(v1=["disable_v2_behavior"]) +def disable_v2_behavior(): + """Enables TensorFlow 2.x behaviors. + + This function can be called at the beginning of the program (before `Tensors`, + `Graphs` or other structures have been created, and before devices have been + initialized. It switches all global behaviors that are different between + TensorFlow 1.x and 2.x to behave as intended for 1.x. + + User can call this function to disable 2.x behavior during complex migrations. + """ + tf2.disable() # Switches TensorArrayV2 and control flow V2 + ops.disable_eager_execution() + tensor_shape.disable_v2_tensorshape() # Also switched by tf2 + variable_scope.disable_resource_variables() + + diff --git a/tensorflow/python/data/__init__.py b/tensorflow/python/data/__init__.py index 7536ba668a..75ba88f303 100644 --- a/tensorflow/python/data/__init__.py +++ b/tensorflow/python/data/__init__.py @@ -24,6 +24,8 @@ from __future__ import print_function # pylint: disable=unused-import from tensorflow.python.data import experimental from tensorflow.python.data.ops.dataset_ops import Dataset +from tensorflow.python.data.ops.dataset_ops import make_initializable_iterator +from tensorflow.python.data.ops.dataset_ops import make_one_shot_iterator from tensorflow.python.data.ops.iterator_ops import Iterator from tensorflow.python.data.ops.readers import FixedLengthRecordDataset from tensorflow.python.data.ops.readers import TextLineDataset diff --git a/tensorflow/python/data/benchmarks/BUILD b/tensorflow/python/data/benchmarks/BUILD index fd723e0d71..5b0500eae1 100644 --- a/tensorflow/python/data/benchmarks/BUILD +++ b/tensorflow/python/data/benchmarks/BUILD @@ -6,6 +6,61 @@ exports_files(["LICENSE"]) load("//tensorflow:tensorflow.bzl", "py_test") +py_test( + name = "batch_benchmark", + srcs = ["batch_benchmark.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", + "//tensorflow/python:session", + "//tensorflow/python:sparse_tensor", + "//tensorflow/python/data/ops:dataset_ops", + "//third_party/py/numpy", + ], +) + +py_test( + name = "filter_benchmark", + srcs = ["filter_benchmark.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_ops", + "//tensorflow/python:session", + "//tensorflow/python/data/ops:dataset_ops", + "//third_party/py/numpy", + ], +) + +py_test( + name = "from_tensor_slices_benchmark", + srcs = ["from_tensor_slices_benchmark.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:client_testlib", + "//tensorflow/python:errors", + "//tensorflow/python:session", + "//tensorflow/python/data/ops:dataset_ops", + "//third_party/py/numpy", + ], +) + +py_test( + name = "map_benchmark", + srcs = ["map_benchmark.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_ops", + "//tensorflow/python:session", + "//tensorflow/python/data/ops:dataset_ops", + "//third_party/py/numpy", + ], +) + py_test( name = "range_benchmark", srcs = ["range_benchmark.py"], diff --git a/tensorflow/python/data/benchmarks/batch_benchmark.py b/tensorflow/python/data/benchmarks/batch_benchmark.py new file mode 100644 index 0000000000..e063849f70 --- /dev/null +++ b/tensorflow/python/data/benchmarks/batch_benchmark.py @@ -0,0 +1,85 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Benchmarks for `tf.data.Dataset.batch()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +import numpy as np + +from tensorflow.python.client import session +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import sparse_tensor +from tensorflow.python.ops import array_ops +from tensorflow.python.platform import test + + +# TODO(b/119837791): Add eager benchmarks. +class BatchBenchmark(test.Benchmark): + """Benchmarks for `tf.data.Dataset.batch()`.""" + + def benchmarkBatchSparse(self): + non_zeros_per_row_values = [0, 1, 5, 10, 100] + batch_size_values = [1, 32, 64, 128, 1024] + + sparse_placeholder = array_ops.sparse_placeholder(dtype=dtypes.int64) + batch_size_placeholder = array_ops.placeholder(dtype=dtypes.int64, shape=[]) + + dataset = dataset_ops.Dataset.from_tensors(sparse_placeholder).repeat( + ).batch(batch_size_placeholder) + iterator = dataset_ops.make_initializable_iterator(dataset) + next_element = iterator.get_next() + + for non_zeros_per_row in non_zeros_per_row_values: + + sparse_value = sparse_tensor.SparseTensorValue( + indices=np.arange(non_zeros_per_row, dtype=np.int64)[:, np.newaxis], + values=np.arange(non_zeros_per_row, dtype=np.int64), + dense_shape=[1000]) + + for batch_size in batch_size_values: + + with session.Session() as sess: + sess.run(iterator.initializer, feed_dict={ + sparse_placeholder: sparse_value, + batch_size_placeholder: batch_size}) + # Run five steps to warm up the session caches before taking the + # first measurement. + for _ in range(5): + sess.run(next_element.indices.op) + deltas = [] + for _ in range(100): + start = time.time() + for _ in range(100): + sess.run(next_element.indices.op) + end = time.time() + deltas.append(end - start) + + median_wall_time = np.median(deltas) / 100.0 + + print("Batch sparse dataset non-zeros per row: %d batch_size: %d " + "wall time: %f" + % (non_zeros_per_row, batch_size, median_wall_time)) + self.report_benchmark( + iters=10000, wall_time=median_wall_time, + name="batch_sparse_dataset_nnz_%d_batch_size_%d" % ( + non_zeros_per_row, batch_size)) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/benchmarks/filter_benchmark.py b/tensorflow/python/data/benchmarks/filter_benchmark.py new file mode 100644 index 0000000000..a6d86fe221 --- /dev/null +++ b/tensorflow/python/data/benchmarks/filter_benchmark.py @@ -0,0 +1,69 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Benchmarks for `tf.data.Dataset.filter()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +import numpy as np + +from tensorflow.python.client import session +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import ops +from tensorflow.python.ops import array_ops +from tensorflow.python.platform import test + + +# TODO(b/119837791): Add eager benchmarks. +class FilterBenchmark(test.Benchmark): + """Benchmarks for `tf.data.Dataset.filter()`.""" + + def _benchmark(self, predicate, name): + with ops.Graph().as_default(): + dataset = ( + dataset_ops.Dataset.from_tensors(True).repeat(None).filter(predicate)) + iterator = dataset_ops.make_one_shot_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + for _ in range(5): + sess.run(next_element.op) + deltas = [] + for _ in range(100): + start = time.time() + for _ in range(100): + sess.run(next_element.op) + end = time.time() + deltas.append(end - start) + + median_wall_time = np.median(deltas) / 100 + print("Filter dataset using %s. Median wall time: %f" % + (name, median_wall_time)) + self.report_benchmark( + iters=100, + wall_time=median_wall_time, + name=name) + + def benchmarkSimpleFunction(self): + self._benchmark(array_ops.identity, "simple_function") + + def benchmarkReturnComponentOptimization(self): + self._benchmark(lambda x: x, "return_component") + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/benchmarks/from_tensor_slices_benchmark.py b/tensorflow/python/data/benchmarks/from_tensor_slices_benchmark.py new file mode 100644 index 0000000000..d7f1a4e7af --- /dev/null +++ b/tensorflow/python/data/benchmarks/from_tensor_slices_benchmark.py @@ -0,0 +1,188 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Benchmarks for `tf.data.Dataset.from_tensor_slices()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +import numpy as np + +from tensorflow.python.client import session +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import errors +from tensorflow.python.platform import test + + +# TODO(b/119837791): Add eager benchmarks. +class FromTensorSlicesBenchmark(test.Benchmark): + """Benchmarks for `tf.data.Dataset.from_tensor_slices()`.""" + + def benchmarkSliceRepeatBatch(self): + input_size = 10000 + batch_size = 100 + num_epochs = 100 + + input_data = np.random.randn(input_size) + + dataset = ( + dataset_ops.Dataset.from_tensor_slices(input_data) + .repeat(num_epochs + 1).batch(batch_size)) + iterator = dataset_ops.make_initializable_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + sess.run(iterator.initializer) + # Run one whole epoch to burn in the computation. + for _ in range(input_size // batch_size): + sess.run(next_element) + deltas = [] + try: + while True: + start = time.time() + sess.run(next_element) + deltas.append(time.time() - start) + except errors.OutOfRangeError: + pass + + median_wall_time = np.median(deltas) + print("Slice/repeat/batch with sess.run() input size: %d batch size: %d " + "Median wall time per element: %f" % (input_size, batch_size, + median_wall_time)) + self.report_benchmark( + iters=len(deltas), + wall_time=median_wall_time, + name="slice_repeat_batch_input_%d_batch_%d" % (input_size, batch_size)) + + def benchmarkSliceRepeatBatchCallable(self): + input_size = 10000 + batch_size = 100 + num_epochs = 100 + + input_data = np.random.randn(input_size) + + dataset = ( + dataset_ops.Dataset.from_tensor_slices(input_data) + .repeat(num_epochs + 1).batch(batch_size)) + iterator = dataset_ops.make_initializable_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + sess.run(iterator.initializer) + get_next_element = sess.make_callable(next_element) + # Run one whole epoch to burn in the computation. + for _ in range(input_size // batch_size): + get_next_element() + deltas = [] + try: + while True: + start = time.time() + get_next_element() + deltas.append(time.time() - start) + except errors.OutOfRangeError: + pass + + median_wall_time = np.median(deltas) + print( + "Slice/repeat/batch with callable input size: %d batch size: %d Median" + " wall time per element: %f" % (input_size, batch_size, + median_wall_time)) + self.report_benchmark( + iters=len(deltas), + wall_time=median_wall_time, + name="slice_repeat_batch_callable_input_%d_batch_%d" % + (input_size, batch_size)) + + def benchmarkReshapeSliceRepeatCallable(self): + input_size = 10000 + batch_size = 100 + num_epochs = 100 + + input_data = np.random.randn(input_size) + + dataset = ( + dataset_ops.Dataset.from_tensor_slices(input_data.reshape(100, 100)) + .repeat(num_epochs + 1)) + iterator = dataset_ops.make_initializable_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + sess.run(iterator.initializer) + get_next_element = sess.make_callable(next_element) + # Run one whole epoch to burn in the computation. + for _ in range(input_size // batch_size): + get_next_element() + deltas = [] + try: + while True: + start = time.time() + get_next_element() + deltas.append(time.time() - start) + except errors.OutOfRangeError: + pass + + median_wall_time = np.median(deltas) + print("Reshape/slice/repeat with callable input size: %d batch size: %d " + "Median wall time per element: %f" % (input_size, batch_size, + median_wall_time)) + self.report_benchmark( + iters=len(deltas), + wall_time=median_wall_time, + name="reshape_slice_repeat_callable_input_%d_batch_%d" % + (input_size, batch_size)) + + def benchmarkSliceBatchCacheRepeatCallable(self): + input_size = 10000 + batch_size = 100 + num_epochs = 100 + + input_data = np.random.randn(input_size) + + dataset = ( + dataset_ops.Dataset.from_tensor_slices(input_data).batch(batch_size) + .cache().repeat(num_epochs + 1)) + iterator = dataset_ops.make_initializable_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + sess.run(iterator.initializer) + get_next_element = sess.make_callable(next_element) + # Run one whole epoch to burn in the computation. + for _ in range(input_size // batch_size): + get_next_element() + deltas = [] + try: + while True: + start = time.time() + get_next_element() + deltas.append(time.time() - start) + except errors.OutOfRangeError: + pass + + median_wall_time = np.median(deltas) + print( + "Slice/batch/cache/repeat with callable input size: %d batch size: %d " + "Median wall time per element: %f" + % (input_size, batch_size, median_wall_time)) + self.report_benchmark( + iters=len(deltas), + wall_time=median_wall_time, + name="slice_batch_cache_repeat_callable_input_%d_batch_%d" % + (input_size, batch_size)) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/benchmarks/map_benchmark.py b/tensorflow/python/data/benchmarks/map_benchmark.py new file mode 100644 index 0000000000..65d945cdae --- /dev/null +++ b/tensorflow/python/data/benchmarks/map_benchmark.py @@ -0,0 +1,135 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Bechmarks for `tf.data.Dataset.map()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +import numpy as np + +from tensorflow.python.client import session +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import ops +from tensorflow.python.platform import test + + +# TODO(b/119837791): Add eager benchmarks. +class MapBenchmark(test.Benchmark): + """Bechmarks for `tf.data.Dataset.map()`.""" + + def benchmarkChainOfMaps(self): + chain_lengths = [0, 1, 2, 5, 10, 20, 50] + for chain_length in chain_lengths: + for mode in ["general", "single-threaded", "short-circuit"]: + if mode == "general": + map_fn = lambda x: x + 1 + use_inter_op_parallelism = True + print_label = "" + benchmark_label = "" + if mode == "single-threaded": + map_fn = lambda x: x + 1 + use_inter_op_parallelism = False + print_label = " (single threaded mode)" + benchmark_label = "_single_threaded" + if mode == "short-circuit": + map_fn = lambda x: x + use_inter_op_parallelism = True # should not have any significance + print_label = " (short circuit mode)" + benchmark_label = "_short_circuit" + + with ops.Graph().as_default(): + dataset = dataset_ops.Dataset.from_tensors(0).repeat(None) + for _ in range(chain_length): + dataset = dataset_ops.MapDataset( + dataset, + map_fn, + use_inter_op_parallelism=use_inter_op_parallelism) + iterator = dataset_ops.make_one_shot_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + for _ in range(5): + sess.run(next_element.op) + deltas = [] + for _ in range(100): + start = time.time() + for _ in range(100): + sess.run(next_element.op) + end = time.time() + deltas.append(end - start) + + median_wall_time = np.median(deltas) / 100 + print("Map dataset chain length%s: %d Median wall time: %f" % + (print_label, chain_length, median_wall_time)) + self.report_benchmark( + iters=1000, + wall_time=median_wall_time, + name="map_dataset_chain_length_%d%s" % (chain_length, + benchmark_label)) + + def benchmarkMapFanOut(self): + fan_outs = [1, 2, 5, 10, 20, 50, 100] + for fan_out in fan_outs: + for mode in ["general", "single-threaded", "short-circuit"]: + if mode == "general": + map_fn = lambda *xs: [x + 1 for x in xs] + use_inter_op_parallelism = True + print_label = "" + benchmark_label = "" + if mode == "single-threaded": + map_fn = lambda *xs: [x + 1 for x in xs] + use_inter_op_parallelism = False + print_label = " (single threaded mode)" + benchmark_label = "_single_threaded" + if mode == "short-circuit": + map_fn = lambda *xs: xs + use_inter_op_parallelism = True # should not have any significance + print_label = " (short circuit mode)" + benchmark_label = "_short_circuit" + + with ops.Graph().as_default(): + dataset = dataset_ops.Dataset.from_tensors( + tuple(0 for _ in range(fan_out))).repeat(None) + dataset = dataset_ops.MapDataset( + dataset, + map_fn, + use_inter_op_parallelism=use_inter_op_parallelism) + iterator = dataset_ops.make_one_shot_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + for _ in range(5): + sess.run(next_element[0].op) + deltas = [] + for _ in range(100): + start = time.time() + for _ in range(100): + sess.run(next_element[0].op) + end = time.time() + deltas.append(end - start) + + median_wall_time = np.median(deltas) / 100 + print("Map dataset fan out%s: %d Median wall time: %f" % + (print_label, fan_out, median_wall_time)) + self.report_benchmark( + iters=1000, + wall_time=median_wall_time, + name="map_dataset_fan_out_%d%s" % (fan_out, benchmark_label)) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/benchmarks/range_benchmark.py b/tensorflow/python/data/benchmarks/range_benchmark.py index 25f63b79a2..a5020e2873 100644 --- a/tensorflow/python/data/benchmarks/range_benchmark.py +++ b/tensorflow/python/data/benchmarks/range_benchmark.py @@ -39,7 +39,7 @@ class RangeBenchmark(test.Benchmark): # costs). dataset = dataset_ops.Dataset.range(num_elements).skip( num_elements - 1).take(1).with_options(options) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() with session.Session() as sess: diff --git a/tensorflow/python/data/experimental/__init__.py b/tensorflow/python/data/experimental/__init__.py index 126c2be442..14dfec37cd 100644 --- a/tensorflow/python/data/experimental/__init__.py +++ b/tensorflow/python/data/experimental/__init__.py @@ -25,6 +25,7 @@ See [Importing Data](https://tensorflow.org/guide/datasets) for an overview. @@Counter @@CheckpointInputPipelineHook @@CsvDataset +@@OptimizationOptions @@Optional @@RandomDataset @@Reducer @@ -32,12 +33,15 @@ See [Importing Data](https://tensorflow.org/guide/datasets) for an overview. @@StatsAggregator @@StatsOptions @@TFRecordWriter +@@ThreadingOptions @@bucket_by_sequence_length +@@cardinality @@choose_from_datasets @@copy_to_device @@dense_to_sparse_batch @@enumerate_dataset +@@filter_for_shard @@get_next_as_optional @@get_single_element @@group_by_reducer @@ -59,6 +63,8 @@ See [Importing Data](https://tensorflow.org/guide/datasets) for an overview. @@unique @@AUTOTUNE +@@INFINITE_CARDINALITY +@@UNKNOWN_CARDINALITY """ from __future__ import absolute_import @@ -70,9 +76,13 @@ from __future__ import print_function from tensorflow.python.data.experimental.ops.batching import dense_to_sparse_batch from tensorflow.python.data.experimental.ops.batching import map_and_batch from tensorflow.python.data.experimental.ops.batching import unbatch +from tensorflow.python.data.experimental.ops.cardinality import cardinality +from tensorflow.python.data.experimental.ops.cardinality import INFINITE as INFINITE_CARDINALITY +from tensorflow.python.data.experimental.ops.cardinality import UNKNOWN as UNKNOWN_CARDINALITY from tensorflow.python.data.experimental.ops.counter import Counter from tensorflow.python.data.experimental.ops.enumerate_ops import enumerate_dataset from tensorflow.python.data.experimental.ops.error_ops import ignore_errors +from tensorflow.python.data.experimental.ops.filter_for_shard_ops import filter_for_shard from tensorflow.python.data.experimental.ops.get_single_element import get_single_element from tensorflow.python.data.experimental.ops.grouping import bucket_by_sequence_length from tensorflow.python.data.experimental.ops.grouping import group_by_reducer @@ -83,10 +93,8 @@ from tensorflow.python.data.experimental.ops.interleave_ops import parallel_inte from tensorflow.python.data.experimental.ops.interleave_ops import sample_from_datasets from tensorflow.python.data.experimental.ops.iterator_ops import CheckpointInputPipelineHook from tensorflow.python.data.experimental.ops.iterator_ops import make_saveable_from_iterator - -# Optimization constant that can be used to enable auto-tuning. from tensorflow.python.data.experimental.ops.optimization import AUTOTUNE - +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.experimental.ops.parsing_ops import parse_example_dataset from tensorflow.python.data.experimental.ops.prefetching_ops import copy_to_device from tensorflow.python.data.experimental.ops.prefetching_ops import prefetch_to_device @@ -101,6 +109,7 @@ from tensorflow.python.data.experimental.ops.shuffle_ops import shuffle_and_repe from tensorflow.python.data.experimental.ops.stats_aggregator import StatsAggregator from tensorflow.python.data.experimental.ops.stats_ops import latency_stats from tensorflow.python.data.experimental.ops.stats_options import StatsOptions +from tensorflow.python.data.experimental.ops.threading_options import ThreadingOptions from tensorflow.python.data.experimental.ops.unique import unique from tensorflow.python.data.experimental.ops.writers import TFRecordWriter from tensorflow.python.data.ops.iterator_ops import get_next_as_optional diff --git a/tensorflow/python/data/experimental/benchmarks/BUILD b/tensorflow/python/data/experimental/benchmarks/BUILD index b89fbe7757..8175116c6e 100644 --- a/tensorflow/python/data/experimental/benchmarks/BUILD +++ b/tensorflow/python/data/experimental/benchmarks/BUILD @@ -7,36 +7,118 @@ exports_files(["LICENSE"]) load("//tensorflow:tensorflow.bzl", "cuda_py_test") load("//tensorflow:tensorflow.bzl", "py_test") +py_test( + name = "autotune_benchmark", + srcs = ["autotune_benchmark.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:client_testlib", + "//tensorflow/python:math_ops", + "//tensorflow/python:session", + "//tensorflow/python/data/experimental/ops:batching", + "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/ops:dataset_ops", + "//third_party/py/numpy", + ], +) + +py_test( + name = "csv_dataset_benchmark", + srcs = ["csv_dataset_benchmark.py"], + srcs_version = "PY2AND3", + tags = ["no_pip"], + deps = [ + "//tensorflow/python:client_testlib", + "//tensorflow/python:parsing_ops", + "//tensorflow/python:platform", + "//tensorflow/python:platform_test", + "//tensorflow/python:session", + "//tensorflow/python/data/experimental/ops:readers", + "//tensorflow/python/data/ops:readers", + "//third_party/py/numpy", + ], +) + py_test( name = "map_and_batch_benchmark", - size = "medium", srcs = ["map_and_batch_benchmark.py"], srcs_version = "PY2AND3", deps = [ + "//tensorflow/core:protos_all_py", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_ops", + "//tensorflow/python:constant_op", + "//tensorflow/python:dtypes", + "//tensorflow/python:math_ops", "//tensorflow/python:random_ops", "//tensorflow/python:session", "//tensorflow/python/data/experimental/ops:batching", - "//tensorflow/python/data/experimental/ops:optimization", "//tensorflow/python/data/ops:dataset_ops", "//third_party/py/numpy", ], ) py_test( - name = "map_benchmark", - size = "medium", - srcs = ["map_benchmark.py"], + name = "map_vectorization_benchmark", + srcs = ["map_vectorization_benchmark.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/core:protos_all_py", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:constant_op", + "//tensorflow/python:dtypes", + "//tensorflow/python:math_ops", + "//tensorflow/python:parsing_ops", + "//tensorflow/python:session", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/data/util:nest", + "//third_party/py/numpy", + ], +) + +py_test( + name = "matching_files_benchmark", + size = "small", + srcs = ["matching_files_benchmark.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", + "//tensorflow/python:errors", + "//tensorflow/python:util", + "//tensorflow/python/data/experimental/ops:matching_files", + "//tensorflow/python/data/ops:dataset_ops", + "//third_party/py/numpy", + ], +) + +py_test( + name = "optimize_benchmark", + srcs = ["optimize_benchmark.py"], srcs_version = "PY2AND3", deps = [ "//tensorflow/python:client_testlib", "//tensorflow/python:framework_ops", "//tensorflow/python:math_ops", "//tensorflow/python:session", + "//tensorflow/python/data/ops:dataset_ops", + "//third_party/py/numpy", + ], +) + +py_test( + name = "unbatch_benchmark", + srcs = ["unbatch_benchmark.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", + "//tensorflow/python:framework_ops", + "//tensorflow/python:session", "//tensorflow/python/data/experimental/ops:batching", - "//tensorflow/python/data/experimental/ops:optimization", "//tensorflow/python/data/ops:dataset_ops", "//third_party/py/numpy", ], diff --git a/tensorflow/python/data/experimental/benchmarks/autotune_benchmark.py b/tensorflow/python/data/experimental/benchmarks/autotune_benchmark.py new file mode 100644 index 0000000000..b48ef95666 --- /dev/null +++ b/tensorflow/python/data/experimental/benchmarks/autotune_benchmark.py @@ -0,0 +1,187 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Benchmarks for autotuning performance knobs.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +import numpy as np + +from tensorflow.python.client import session +from tensorflow.python.data.experimental.ops import batching +from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import test + + +class AutotuneBenchmark(test.Benchmark): + """Benchmarks for autotuning performance knobs.""" + + def benchmarkMap(self): + k = 1024 * 1024 + dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), + np.random.rand(4 * k, + 1))).repeat() + dataset = dataset.map( + math_ops.matmul, num_parallel_calls=optimization.AUTOTUNE) + iterator = dataset_ops.make_one_shot_iterator(dataset) + get_next = iterator.get_next() + + deltas = [] + with session.Session() as sess: + for _ in range(5): + sess.run(get_next.op) + for _ in range(1000): + start = time.time() + sess.run(get_next.op) + end = time.time() + deltas.append(end - start) + + print("%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n" % + (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), + np.max(deltas))) + self.report_benchmark( + iters=1000, wall_time=np.median(deltas), name="map_autotune") + + def benchmarkMapAndBatch(self): + self._benchmarkMapAndBatch(numa_aware=False) + self._benchmarkMapAndBatch(numa_aware=True) + + def _benchmarkMapAndBatch(self, numa_aware): + batch_size = 16 + k = 1024 * 1024 + dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), + np.random.rand(4 * k, + 1))).repeat() + dataset = dataset.apply( + batching.map_and_batch( + math_ops.matmul, + num_parallel_calls=optimization.AUTOTUNE, + batch_size=batch_size)) + options = dataset_ops.Options() + options.experimental_numa_aware = numa_aware + dataset = dataset.with_options(options) + iterator = dataset_ops.make_one_shot_iterator(dataset) + get_next = iterator.get_next() + + deltas = [] + with session.Session() as sess: + for _ in range(5): + sess.run(get_next.op) + for _ in range(100): + start = time.time() + sess.run(get_next.op) + end = time.time() + deltas.append(end - start) + + print("%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n" % + (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), + np.max(deltas))) + + self.report_benchmark( + iters=100, + wall_time=np.median(deltas), + name=("numa_" if numa_aware else "") + "map_and_batch_autotune") + + def benchmarkInterleave(self): + k = 1024 * 1024 + dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), + np.random.rand(4 * k, + 1))).repeat() + dataset = dataset.map(math_ops.matmul) + dataset = dataset_ops.Dataset.range(1).repeat().interleave( + lambda _: dataset, + cycle_length=10, + num_parallel_calls=optimization.AUTOTUNE) + iterator = dataset_ops.make_one_shot_iterator(dataset) + get_next = iterator.get_next() + + deltas = [] + with session.Session() as sess: + for _ in range(5): + sess.run(get_next.op) + for _ in range(1000): + start = time.time() + sess.run(get_next.op) + end = time.time() + deltas.append(end - start) + + print("%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n" % + (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), + np.max(deltas))) + self.report_benchmark( + iters=1000, + wall_time=np.median(deltas), + name="interleave_autotune") + + def benchmarkMapAndInterleave(self): + k = 1024 * 1024 + a = (np.random.rand(1, 8 * k), np.random.rand(8 * k, 1)) + b = (np.random.rand(1, 4 * k), np.random.rand(4 * k, 1)) + c = (np.random.rand(1, 2 * k), np.random.rand(2 * k, 1)) + dataset = dataset_ops.Dataset.from_tensors((a, b, c)).repeat() + + def f1(a, b, c): + x, y = a + return math_ops.matmul(x, y), b, c + + def f2(a, b, c): + x, y = b + return a, math_ops.matmul(x, y), c + + def f3(a, b, c): + x, y = c + return a, b, math_ops.matmul(x, y) + + dataset = dataset.map(f1, num_parallel_calls=optimization.AUTOTUNE) + dataset = dataset_ops.Dataset.range(1).repeat().interleave( + lambda _: dataset, + num_parallel_calls=optimization.AUTOTUNE, + cycle_length=2) + + dataset = dataset.map(f2, num_parallel_calls=optimization.AUTOTUNE) + dataset = dataset_ops.Dataset.range(1).repeat().interleave( + lambda _: dataset, + num_parallel_calls=optimization.AUTOTUNE, + cycle_length=2) + + dataset = dataset.map(f3, num_parallel_calls=optimization.AUTOTUNE) + iterator = dataset_ops.make_one_shot_iterator(dataset) + get_next = iterator.get_next() + + deltas = [] + with session.Session() as sess: + for _ in range(5): + sess.run(get_next) + for _ in range(100): + start = time.time() + sess.run(get_next) + end = time.time() + deltas.append(end - start) + + print("%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n" % + (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), + np.max(deltas))) + self.report_benchmark( + iters=100, + wall_time=np.median(deltas), + name="map_and_interleave_autotune") + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/experimental/benchmarks/csv_dataset_benchmark.py b/tensorflow/python/data/experimental/benchmarks/csv_dataset_benchmark.py new file mode 100644 index 0000000000..03345ce4e6 --- /dev/null +++ b/tensorflow/python/data/experimental/benchmarks/csv_dataset_benchmark.py @@ -0,0 +1,130 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Benchmarks for `tf.data.experimental.CsvDataset`.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os +import string +import tempfile +import time + +import numpy as np + +from tensorflow.python.client import session +from tensorflow.python.data.experimental.ops import readers +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.ops import readers as core_readers +from tensorflow.python.ops import parsing_ops +from tensorflow.python.platform import gfile +from tensorflow.python.platform import googletest +from tensorflow.python.platform import test + + +class CsvDatasetBenchmark(test.Benchmark): + """Benchmarks for `tf.data.experimental.CsvDataset`.""" + + FLOAT_VAL = '1.23456E12' + STR_VAL = string.ascii_letters * 10 + + def _setUp(self, str_val): + # Since this isn't test.TestCase, have to manually create a test dir + gfile.MakeDirs(googletest.GetTempDir()) + self._temp_dir = tempfile.mkdtemp(dir=googletest.GetTempDir()) + + self._num_cols = [4, 64, 256] + self._num_per_iter = 5000 + self._filenames = [] + for n in self._num_cols: + fn = os.path.join(self._temp_dir, 'file%d.csv' % n) + with open(fn, 'wb') as f: + # Just write 100 rows and use `repeat`... Assumes the cost + # of creating an iterator is not significant + row = ','.join([str_val for _ in range(n)]) + f.write('\n'.join([row for _ in range(100)])) + self._filenames.append(fn) + + def _tearDown(self): + gfile.DeleteRecursively(self._temp_dir) + + def _runBenchmark(self, dataset, num_cols, prefix): + dataset = dataset.skip(self._num_per_iter - 1) + deltas = [] + for _ in range(10): + next_element = dataset_ops.make_one_shot_iterator(dataset).get_next() + with session.Session() as sess: + start = time.time() + # NOTE: This depends on the underlying implementation of skip, to have + # the net effect of calling `GetNext` num_per_iter times on the + # input dataset. We do it this way (instead of a python for loop, or + # batching N inputs in one iter) so that the overhead from session.run + # or batch doesn't dominate. If we eventually optimize skip, this has + # to change. + sess.run(next_element) + end = time.time() + deltas.append(end - start) + # Median wall time per CSV record read and decoded + median_wall_time = np.median(deltas) / self._num_per_iter + print('%s num_cols: %d Median wall time: %f' % (prefix, num_cols, + median_wall_time)) + self.report_benchmark( + iters=self._num_per_iter, + wall_time=median_wall_time, + name='%s_with_cols_%d' % (prefix, num_cols)) + + def benchmarkMapWithFloats(self): + self._setUp(self.FLOAT_VAL) + for i in range(len(self._filenames)): + num_cols = self._num_cols[i] + kwargs = {'record_defaults': [[0.0]] * num_cols} + dataset = core_readers.TextLineDataset(self._filenames[i]).repeat() + dataset = dataset.map(lambda l: parsing_ops.decode_csv(l, **kwargs)) # pylint: disable=cell-var-from-loop + self._runBenchmark(dataset, num_cols, 'csv_float_map_decode_csv') + self._tearDown() + + def benchmarkMapWithStrings(self): + self._setUp(self.STR_VAL) + for i in range(len(self._filenames)): + num_cols = self._num_cols[i] + kwargs = {'record_defaults': [['']] * num_cols} + dataset = core_readers.TextLineDataset(self._filenames[i]).repeat() + dataset = dataset.map(lambda l: parsing_ops.decode_csv(l, **kwargs)) # pylint: disable=cell-var-from-loop + self._runBenchmark(dataset, num_cols, 'csv_strings_map_decode_csv') + self._tearDown() + + def benchmarkCsvDatasetWithFloats(self): + self._setUp(self.FLOAT_VAL) + for i in range(len(self._filenames)): + num_cols = self._num_cols[i] + kwargs = {'record_defaults': [[0.0]] * num_cols} + dataset = core_readers.TextLineDataset(self._filenames[i]).repeat() + dataset = readers.CsvDataset(self._filenames[i], **kwargs).repeat() # pylint: disable=cell-var-from-loop + self._runBenchmark(dataset, num_cols, 'csv_float_fused_dataset') + self._tearDown() + + def benchmarkCsvDatasetWithStrings(self): + self._setUp(self.STR_VAL) + for i in range(len(self._filenames)): + num_cols = self._num_cols[i] + kwargs = {'record_defaults': [['']] * num_cols} + dataset = core_readers.TextLineDataset(self._filenames[i]).repeat() + dataset = readers.CsvDataset(self._filenames[i], **kwargs).repeat() # pylint: disable=cell-var-from-loop + self._runBenchmark(dataset, num_cols, 'csv_strings_fused_dataset') + self._tearDown() + +if __name__ == '__main__': + test.main() diff --git a/tensorflow/python/data/experimental/benchmarks/map_and_batch_benchmark.py b/tensorflow/python/data/experimental/benchmarks/map_and_batch_benchmark.py index a90156cd33..fbd06a5a78 100644 --- a/tensorflow/python/data/experimental/benchmarks/map_and_batch_benchmark.py +++ b/tensorflow/python/data/experimental/benchmarks/map_and_batch_benchmark.py @@ -17,6 +17,8 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import hashlib +import itertools import time import numpy as np @@ -25,11 +27,15 @@ from tensorflow.core.protobuf import config_pb2 from tensorflow.python.client import session from tensorflow.python.data.experimental.ops import batching from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops from tensorflow.python.platform import test +_NUMPY_RANDOM_SEED = 42 + class MapAndBatchBenchmark(test.Benchmark): """Benchmarks for `tf.data.experimental.map_and_batch()`.""" @@ -48,7 +54,7 @@ class MapAndBatchBenchmark(test.Benchmark): dataset = dataset.apply(batching.map_and_batch( lambda _: dense_value, batch_size_placeholder)) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() for shape in shapes: @@ -89,6 +95,129 @@ class MapAndBatchBenchmark(test.Benchmark): name="benchmark_batch_dense_dataset_nnz_%d_batch_size_%d" % ( np.prod(shape), batch_size)) + def benchmarkMapAndBatchChainingVersusFusing(self): + """Compares the performance of chaining and fusing map and batch. + + NOTE: It is recommended to build the benchmark with + `-c opt --copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-gmlt` + and execute it on a machine with at least 32 CPU cores. + """ + + # Sequential pipeline configurations. + seq_elem_size_series = itertools.product([1], [1], [1, 2, 4, 8], [16]) + seq_batch_size_series = itertools.product([1], [1], [1], [8, 16, 32, 64]) + + # Parallel pipeline configuration. + par_elem_size_series = itertools.product([32], [32], [1, 2, 4, 8], [256]) + par_batch_size_series = itertools.product([32], [32], [1], + [128, 256, 512, 1024]) + par_num_calls_series = itertools.product([8, 16, 32, 64], [32], [1], [512]) + par_inter_op_series = itertools.product([32], [8, 16, 32, 64], [1], [512]) + + def name(method, label, num_calls, inter_op, element_size, batch_size): + return ("%s_id_%s_num_calls_%d_inter_op_%d_elem_size_%d_batch_size_%d" % ( + method, + hashlib.sha1(label).hexdigest()[:8], + num_calls, + inter_op, + element_size, + batch_size, + )) + + def benchmark(label, series): + """Runs benchmark the given series.""" + + print("%s:" % label) + + def make_base_dataset(element_size): + k = 1024 * 1024 + x = constant_op.constant(np.random.rand(element_size, 4 * k)) + y = constant_op.constant(np.random.rand(4 * k, 1)) + return dataset_ops.Dataset.range(1000000000000).map(lambda _: (x, y)) + + for num_calls, inter_op, element_size, batch_size in series: + + num_iters = 1024 // ( + (element_size * batch_size) // min(num_calls, inter_op)) + dataset = make_base_dataset(element_size) + chained_dataset = dataset.map( + math_ops.matmul, + num_parallel_calls=num_calls).batch(batch_size=batch_size) + chained_iterator = dataset_ops.make_one_shot_iterator(chained_dataset) + chained_get_next = chained_iterator.get_next() + + chained_deltas = [] + with session.Session( + config=config_pb2.ConfigProto( + inter_op_parallelism_threads=inter_op, + use_per_session_threads=True)) as sess: + for _ in range(5): + sess.run(chained_get_next.op) + for _ in range(num_iters): + start = time.time() + sess.run(chained_get_next.op) + end = time.time() + chained_deltas.append(end - start) + + fused_dataset = dataset.apply( + batching.map_and_batch( + math_ops.matmul, + num_parallel_calls=num_calls, + batch_size=batch_size)) + fused_iterator = dataset_ops.make_one_shot_iterator(fused_dataset) + fused_get_next = fused_iterator.get_next() + + fused_deltas = [] + with session.Session( + config=config_pb2.ConfigProto( + inter_op_parallelism_threads=inter_op, + use_per_session_threads=True)) as sess: + + for _ in range(5): + sess.run(fused_get_next.op) + for _ in range(num_iters): + start = time.time() + sess.run(fused_get_next.op) + end = time.time() + fused_deltas.append(end - start) + + print( + "batch size: %d, num parallel calls: %d, inter-op parallelism: %d, " + "element size: %d, num iters: %d\nchained wall time: %f (median), " + "%f (mean), %f (stddev), %f (min), %f (max)\n fused wall time: " + "%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n " + "chained/fused: %.2fx (median), %.2fx (mean)" % + (batch_size, num_calls, inter_op, element_size, num_iters, + np.median(chained_deltas), np.mean(chained_deltas), + np.std(chained_deltas), np.min(chained_deltas), + np.max(chained_deltas), np.median(fused_deltas), + np.mean(fused_deltas), np.std(fused_deltas), np.min(fused_deltas), + np.max(fused_deltas), + np.median(chained_deltas) / np.median(fused_deltas), + np.mean(chained_deltas) / np.mean(fused_deltas))) + + self.report_benchmark( + iters=num_iters, + wall_time=np.median(chained_deltas), + name=name("chained", label, num_calls, inter_op, element_size, + batch_size)) + + self.report_benchmark( + iters=num_iters, + wall_time=np.median(fused_deltas), + name=name("fused", label, num_calls, inter_op, element_size, + batch_size)) + + print() + + np.random.seed(_NUMPY_RANDOM_SEED) + benchmark("Sequential element size evaluation", seq_elem_size_series) + benchmark("Sequential batch size evaluation", seq_batch_size_series) + benchmark("Parallel element size evaluation", par_elem_size_series) + benchmark("Parallel batch size evaluation", par_batch_size_series) + benchmark("Transformation parallelism evaluation", par_num_calls_series) + benchmark("Threadpool size evaluation", par_inter_op_series) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/experimental/benchmarks/map_benchmark.py b/tensorflow/python/data/experimental/benchmarks/map_benchmark.py deleted file mode 100644 index ad253cffa5..0000000000 --- a/tensorflow/python/data/experimental/benchmarks/map_benchmark.py +++ /dev/null @@ -1,245 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import hashlib -import itertools -import time - -import numpy as np - -from tensorflow.core.protobuf import config_pb2 -from tensorflow.python.client import session -from tensorflow.python.data.experimental.ops import batching -from tensorflow.python.data.experimental.ops import optimization -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import ops -from tensorflow.python.ops import math_ops -from tensorflow.python.platform import test - -_NUMPY_RANDOM_SEED = 42 - - -class MapDatasetBenchmark(test.Benchmark): - - # The purpose of this benchmark is to compare the performance of chaining vs - # fusing of the map and batch transformations across various configurations. - # - # NOTE: It is recommended to build the benchmark with - # `-c opt --copt=-mavx --copt=-mavx2 --copt=-mfma --copt=-gmlt` - # and execute it on a machine with at least 32 CPU cores. - def benchmarkMapAndBatch(self): - - # Sequential pipeline configurations. - seq_elem_size_series = itertools.product([1], [1], [1, 2, 4, 8], [16]) - seq_batch_size_series = itertools.product([1], [1], [1], [8, 16, 32, 64]) - - # Parallel pipeline configuration. - par_elem_size_series = itertools.product([32], [32], [1, 2, 4, 8], [256]) - par_batch_size_series = itertools.product([32], [32], [1], - [128, 256, 512, 1024]) - par_num_calls_series = itertools.product([8, 16, 32, 64], [32], [1], [512]) - par_inter_op_series = itertools.product([32], [8, 16, 32, 64], [1], [512]) - - def name(method, label, num_calls, inter_op, element_size, batch_size): - return ("%s_id_%s_num_calls_%d_inter_op_%d_elem_size_%d_batch_size_%d" % ( - method, - hashlib.sha1(label).hexdigest(), - num_calls, - inter_op, - element_size, - batch_size, - )) - - def benchmark(label, series): - - print("%s:" % label) - for num_calls, inter_op, element_size, batch_size in series: - - num_iters = 1024 // ( - (element_size * batch_size) // min(num_calls, inter_op)) - k = 1024 * 1024 - dataset = dataset_ops.Dataset.from_tensors((np.random.rand( - element_size, 4 * k), np.random.rand(4 * k, 1))).repeat() - - chained_dataset = dataset.map( - math_ops.matmul, - num_parallel_calls=num_calls).batch(batch_size=batch_size) - chained_iterator = chained_dataset.make_one_shot_iterator() - chained_get_next = chained_iterator.get_next() - - chained_deltas = [] - with session.Session( - config=config_pb2.ConfigProto( - inter_op_parallelism_threads=inter_op, - use_per_session_threads=True)) as sess: - for _ in range(5): - sess.run(chained_get_next.op) - for _ in range(num_iters): - start = time.time() - sess.run(chained_get_next.op) - end = time.time() - chained_deltas.append(end - start) - - fused_dataset = dataset.apply( - batching.map_and_batch( - math_ops.matmul, - num_parallel_calls=num_calls, - batch_size=batch_size)) - fused_iterator = fused_dataset.make_one_shot_iterator() - fused_get_next = fused_iterator.get_next() - - fused_deltas = [] - with session.Session( - config=config_pb2.ConfigProto( - inter_op_parallelism_threads=inter_op, - use_per_session_threads=True)) as sess: - - for _ in range(5): - sess.run(fused_get_next.op) - for _ in range(num_iters): - start = time.time() - sess.run(fused_get_next.op) - end = time.time() - fused_deltas.append(end - start) - - print( - "batch size: %d, num parallel calls: %d, inter-op parallelism: %d, " - "element size: %d, num iters: %d\nchained wall time: %f (median), " - "%f (mean), %f (stddev), %f (min), %f (max)\n fused wall time: " - "%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n " - "chained/fused: %.2fx (median), %.2fx (mean)" % - (batch_size, num_calls, inter_op, element_size, num_iters, - np.median(chained_deltas), np.mean(chained_deltas), - np.std(chained_deltas), np.min(chained_deltas), - np.max(chained_deltas), np.median(fused_deltas), - np.mean(fused_deltas), np.std(fused_deltas), np.min(fused_deltas), - np.max(fused_deltas), - np.median(chained_deltas) / np.median(fused_deltas), - np.mean(chained_deltas) / np.mean(fused_deltas))) - - self.report_benchmark( - iters=num_iters, - wall_time=np.median(chained_deltas), - name=name("chained", label, num_calls, inter_op, element_size, - batch_size)) - - self.report_benchmark( - iters=num_iters, - wall_time=np.median(fused_deltas), - name=name("fused", label, num_calls, inter_op, element_size, - batch_size)) - - print("") - - np.random.seed(_NUMPY_RANDOM_SEED) - benchmark("Sequential element size evaluation", seq_elem_size_series) - benchmark("Sequential batch size evaluation", seq_batch_size_series) - benchmark("Parallel element size evaluation", par_elem_size_series) - benchmark("Parallel batch size evaluation", par_batch_size_series) - benchmark("Transformation parallelism evaluation", par_num_calls_series) - benchmark("Threadpool size evaluation", par_inter_op_series) - - # This benchmark compares the performance of pipeline with multiple chained - # maps with and without map fusion. - def benchmarkChainOfMaps(self): - chain_lengths = [0, 1, 2, 5, 10, 20, 50] - for chain_length in chain_lengths: - self._benchmarkChainOfMaps(chain_length, False) - self._benchmarkChainOfMaps(chain_length, True) - - def _benchmarkChainOfMaps(self, chain_length, optimize_dataset): - with ops.Graph().as_default(): - dataset = dataset_ops.Dataset.from_tensors(0).repeat(None) - for _ in range(chain_length): - dataset = dataset.map(lambda x: x) - if optimize_dataset: - dataset = dataset.apply(optimization.optimize(["map_fusion"])) - - iterator = dataset.make_one_shot_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - for _ in range(5): - sess.run(next_element.op) - deltas = [] - for _ in range(100): - start = time.time() - for _ in range(100): - sess.run(next_element.op) - end = time.time() - deltas.append(end - start) - - median_wall_time = np.median(deltas) / 100 - opt_mark = "opt" if optimize_dataset else "no-opt" - print("Map dataset {} chain length: {} Median wall time: {}".format( - opt_mark, chain_length, median_wall_time)) - self.report_benchmark( - iters=1000, - wall_time=median_wall_time, - name="benchmark_map_dataset_chain_latency_{}_{}".format( - opt_mark, chain_length)) - - -class MapAndFilterBenchmark(test.Benchmark): - - # This benchmark compares the performance of pipeline with multiple chained - # map + filter with and without map fusion. - def benchmarkMapAndFilter(self): - chain_lengths = [0, 1, 2, 5, 10, 20, 50] - for chain_length in chain_lengths: - self._benchmarkMapAndFilter(chain_length, False) - self._benchmarkMapAndFilter(chain_length, True) - - def _benchmarkMapAndFilter(self, chain_length, optimize_dataset): - with ops.Graph().as_default(): - dataset = dataset_ops.Dataset.from_tensors(0).repeat(None) - for _ in range(chain_length): - dataset = dataset.map(lambda x: x + 5).filter( - lambda x: math_ops.greater_equal(x - 5, 0)) - if optimize_dataset: - dataset = dataset.apply( - optimization.optimize(["map_and_filter_fusion"])) - - iterator = dataset.make_one_shot_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - for _ in range(10): - sess.run(next_element.op) - deltas = [] - for _ in range(100): - start = time.time() - for _ in range(100): - sess.run(next_element.op) - end = time.time() - deltas.append(end - start) - - median_wall_time = np.median(deltas) / 100 - opt_mark = "opt" if optimize_dataset else "no-opt" - print("Map and filter dataset {} chain length: {} Median wall time: {}". - format(opt_mark, chain_length, median_wall_time)) - self.report_benchmark( - iters=1000, - wall_time=median_wall_time, - name="benchmark_map_and_filter_dataset_chain_latency_{}_{}".format( - opt_mark, chain_length)) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/experimental/benchmarks/map_vectorization_benchmark.py b/tensorflow/python/data/experimental/benchmarks/map_vectorization_benchmark.py new file mode 100644 index 0000000000..47ec6391f7 --- /dev/null +++ b/tensorflow/python/data/experimental/benchmarks/map_vectorization_benchmark.py @@ -0,0 +1,194 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Benchmarks for the `MapVectorization` optimization.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +import numpy as np + +from tensorflow.core.example import example_pb2 +from tensorflow.core.example import feature_pb2 +from tensorflow.python.client import session +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.util import nest +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import parsing_ops +from tensorflow.python.platform import test + + +def _generate_csv_test_case(): + """Generates a `decode_csv()` test case.""" + + def csv_factory(): + return dataset_ops.Dataset.from_tensor_slices(["1.0:2:a", + "2.4:5:c"]).repeat(5) + + def decode_csv_fn(x): + return parsing_ops.decode_csv( + x, + record_defaults=[ + constant_op.constant([], dtypes.float32), + constant_op.constant([], dtypes.int32), + constant_op.constant([], dtypes.string) + ], + field_delim=":") + + return decode_csv_fn, csv_factory + + +def _generate_parse_single_example_test_case(): + """Generates a `parse_single_example()` test case.""" + + def parse_example_factory(): + """Parse example factory.""" + + def _int64_feature(*values): + return feature_pb2.Feature(int64_list=feature_pb2.Int64List(value=values)) + + def _bytes_feature(*values): + return feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[v.encode("utf-8") for v in values])) + + return dataset_ops.Dataset.from_tensor_slices( + constant_op.constant([ + example_pb2.Example( + features=feature_pb2.Features( + feature={ + "dense_int": _int64_feature(i), + "dense_str": _bytes_feature(str(i)), + "sparse_int": _int64_feature(i, i * 2, i * 4, i * 8), + "sparse_str": _bytes_feature(*["abc"] * i) + })).SerializeToString() for i in range(10) + ])) + + def parse_single_example_fn(x): + features = { + "dense_int": parsing_ops.FixedLenFeature((), dtypes.int64, 0), + "dense_str": parsing_ops.FixedLenFeature((), dtypes.string, ""), + "sparse_int": parsing_ops.VarLenFeature(dtypes.int64), + "sparse_str": parsing_ops.VarLenFeature(dtypes.string), + } + return parsing_ops.parse_single_example(x, features) + + return parse_single_example_fn, parse_example_factory + + +# TODO(rachelim): Add a benchmark for more expensive transformations, such as +# vgg_preprocessing. +class MapVectorizationBenchmark(test.Benchmark): + """Benchmarks for the `MapVectorization` optimization.""" + + def _run(self, x, num_iters=100, name=None): + deltas = [] + with session.Session() as sess: + for _ in range(5): + # Warm up session... + sess.run(x) + for _ in range(num_iters): + start = time.time() + sess.run(x) + end = time.time() + deltas.append(end - start) + median_time = np.median(deltas) + self.report_benchmark(iters=num_iters, wall_time=median_time, name=name) + return median_time + + def _compare(self, input_dataset, map_fn, batch_size, input_size, str_id): + num_elems = int(np.sum([np.prod(x) for x in input_size])) + name_template = "{}__batch_size_{}_input_element_size_{}_{}" + unoptimized = input_dataset.map(map_fn).batch(batch_size) + unoptimized_op = dataset_ops.make_one_shot_iterator(unoptimized).get_next() + + optimized = input_dataset.map(map_fn).batch(batch_size) + options = dataset_ops.Options() + options.experimental_map_vectorization = True + optimized = optimized.with_options(options) + optimized_op = dataset_ops.make_one_shot_iterator(optimized).get_next() + + unoptimized_time = self._run( + unoptimized_op, + name=name_template.format(str_id, batch_size, num_elems, "unoptimized")) + optimized_time = self._run( + optimized_op, + name=name_template.format(str_id, batch_size, num_elems, "optimized")) + + print("Batch size: {}\n" + "Input element size: {}\n" + "Transformation: {}\n" + "Speedup: {}\n".format(batch_size, input_size, str_id, + (unoptimized_time / optimized_time))) + + # Known cheap functions + def benchmarkIdentity(self): + self._benchmark_helper(lambda *args: [array_ops.identity(x) for x in args], + "identity") + + def benchmarkAddConst(self): + self._benchmark_helper(lambda *args: [x + 1 for x in args], "add_const") + + def benchmarkReturnConst(self): + self._benchmark_helper(lambda *args: [constant_op.constant(2)], "ret_const") + + def benchmarkSelect(self): + self._benchmark_helper(lambda *args: args[0], "select") + + def benchmarkCast(self): + self._benchmark_helper( + lambda *args: [math_ops.cast(x, dtypes.float64) for x in args], "cast") + + def benchmarkReshape(self): + self._benchmark_helper( + lambda *args: [array_ops.reshape(x, (-1, 30)) for x in args], "reshape") + + def benchmarkDecodeCSV(self): + csv_fn, csv_factory = _generate_csv_test_case() + self._benchmark_helper(csv_fn, "decode_csv", lambda: [csv_factory()]) + + def benchmarkParseSingleExample(self): + # NOTE: Since we haven't implemented a vectorizer for "SerializeSparse", + # this function is only naively vectorized. + parse_fn, parse_factory = _generate_parse_single_example_test_case() + + self._benchmark_helper(parse_fn, "parse_single_example", + lambda: [parse_factory()]) + + def _default_dataset_factory(self): + input_sizes = [(10, 10, 3), (10, 100, 300)] + for sz in input_sizes: + yield dataset_ops.Dataset.from_tensor_slices(np.random.rand(*sz)) + + def _benchmark_helper(self, map_fn, str_id, base_dataset_factory=None): + if base_dataset_factory is None: + base_dataset_factory = self._default_dataset_factory + + batch_size = 1000 + for base_dataset in base_dataset_factory(): + base_dataset = base_dataset.repeat() + input_size = [ + tuple(shape.as_list()) + for shape in nest.flatten(base_dataset.output_shapes) + ] + self._compare(base_dataset, map_fn, batch_size, input_size, str_id) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/experimental/benchmarks/matching_files_benchmark.py b/tensorflow/python/data/experimental/benchmarks/matching_files_benchmark.py new file mode 100644 index 0000000000..c53f8dd7c5 --- /dev/null +++ b/tensorflow/python/data/experimental/benchmarks/matching_files_benchmark.py @@ -0,0 +1,102 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Benchmark for the experimental `MatchingFilesDataset`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os +import shutil +import tempfile +import time + +import numpy as np + +from tensorflow.python.client import session +from tensorflow.python.data.experimental.ops import matching_files +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import errors +from tensorflow.python.framework import ops +from tensorflow.python.platform import test + + +class MatchingFilesBenchmark(test.Benchmark): + """Benchmark for the experimental `MatchingFilesDataset`.""" + + def benchmarkNestedDirectories(self): + tmp_dir = tempfile.mkdtemp() + width = 500 + depth = 10 + for i in range(width): + for j in range(depth): + new_base = os.path.join(tmp_dir, str(i), + *[str(dir_name) for dir_name in range(j)]) + os.makedirs(new_base) + child_files = ['a.py', 'b.pyc'] if j < depth - 1 else ['c.txt', 'd.log'] + for f in child_files: + filename = os.path.join(new_base, f) + open(filename, 'w').close() + + patterns = [ + os.path.join(tmp_dir, os.path.join(*['**' + for _ in range(depth)]), suffix) + for suffix in ['*.txt', '*.log'] + ] + + deltas = [] + iters = 3 + for _ in range(iters): + with ops.Graph().as_default(): + dataset = matching_files.MatchingFilesDataset(patterns) + next_element = dataset_ops.make_one_shot_iterator(dataset).get_next() + + with session.Session() as sess: + sub_deltas = [] + while True: + try: + start = time.time() + sess.run(next_element) + end = time.time() + sub_deltas.append(end - start) + except errors.OutOfRangeError: + break + deltas.append(sub_deltas) + + median_deltas = np.median(deltas, axis=0) + print('Nested directory size (width*depth): %d*%d Median wall time: ' + '%fs (read first filename), %fs (read second filename), avg %fs' + ' (read %d more filenames)' % + (width, depth, median_deltas[0], median_deltas[1], + np.average(median_deltas[2:]), len(median_deltas) - 2)) + self.report_benchmark( + iters=iters, + wall_time=np.sum(median_deltas), + extras={ + 'read first file:': + median_deltas[0], + 'read second file:': + median_deltas[1], + 'avg time for reading %d more filenames:' % + (len(median_deltas) - 2): + np.average(median_deltas[2:]) + }, + name='dataset_nested_directory(%d*%d)' % + (width, depth)) + + shutil.rmtree(tmp_dir, ignore_errors=True) + + +if __name__ == '__main__': + test.main() diff --git a/tensorflow/python/data/experimental/benchmarks/optimize_benchmark.py b/tensorflow/python/data/experimental/benchmarks/optimize_benchmark.py new file mode 100644 index 0000000000..2f9b89111f --- /dev/null +++ b/tensorflow/python/data/experimental/benchmarks/optimize_benchmark.py @@ -0,0 +1,120 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Benchmarks for static optimizations.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +import numpy as np + +from tensorflow.python.client import session +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import ops +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import test + + +class OptimizationBenchmark(test.Benchmark): + """Benchmarks for static optimizations.""" + + def benchmarkMapFusion(self): + """Evaluates performance map of fusion.""" + + chain_lengths = [0, 1, 2, 5, 10, 20, 50] + for chain_length in chain_lengths: + self._benchmarkMapFusion(chain_length, False) + self._benchmarkMapFusion(chain_length, True) + + def _benchmarkMapFusion(self, chain_length, optimize_dataset): + with ops.Graph().as_default(): + dataset = dataset_ops.Dataset.from_tensors(0).repeat(None) + for _ in range(chain_length): + dataset = dataset.map(lambda x: x) + if optimize_dataset: + options = dataset_ops.Options() + options.experimental_map_fusion = True + dataset = dataset.with_options(options) + + iterator = dataset_ops.make_one_shot_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + for _ in range(5): + sess.run(next_element.op) + deltas = [] + for _ in range(100): + start = time.time() + for _ in range(100): + sess.run(next_element.op) + end = time.time() + deltas.append(end - start) + + median_wall_time = np.median(deltas) / 100 + opt_mark = "opt" if optimize_dataset else "noopt" + print("Map dataset {} chain length: {} Median wall time: {}".format( + opt_mark, chain_length, median_wall_time)) + self.report_benchmark( + iters=100, + wall_time=median_wall_time, + name="map_fusion_{}_chain_length_{}".format( + opt_mark, chain_length)) + + def benchmarkMapAndFilterFusion(self): + """Evaluates performance map of fusion.""" + + chain_lengths = [0, 1, 2, 5, 10, 20, 50] + for chain_length in chain_lengths: + self._benchmarkMapAndFilterFusion(chain_length, False) + self._benchmarkMapAndFilterFusion(chain_length, True) + + def _benchmarkMapAndFilterFusion(self, chain_length, optimize_dataset): + with ops.Graph().as_default(): + dataset = dataset_ops.Dataset.from_tensors(0).repeat(None) + for _ in range(chain_length): + dataset = dataset.map(lambda x: x + 5).filter( + lambda x: math_ops.greater_equal(x - 5, 0)) + if optimize_dataset: + options = dataset_ops.Options() + options.experimental_map_and_filter_fusion = True + dataset = dataset.with_options(options) + iterator = dataset_ops.make_one_shot_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + for _ in range(10): + sess.run(next_element.op) + deltas = [] + for _ in range(100): + start = time.time() + for _ in range(100): + sess.run(next_element.op) + end = time.time() + deltas.append(end - start) + + median_wall_time = np.median(deltas) / 100 + opt_mark = "opt" if optimize_dataset else "noopt" + print("Map and filter dataset {} chain length: {} Median wall time: {}" + .format(opt_mark, chain_length, median_wall_time)) + self.report_benchmark( + iters=100, + wall_time=median_wall_time, + name="map_and_filter_fusion_{}_chain_length_{}".format( + opt_mark, chain_length)) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/experimental/benchmarks/unbatch_benchmark.py b/tensorflow/python/data/experimental/benchmarks/unbatch_benchmark.py new file mode 100644 index 0000000000..c36a32534d --- /dev/null +++ b/tensorflow/python/data/experimental/benchmarks/unbatch_benchmark.py @@ -0,0 +1,107 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.experimental.unbatch()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +import numpy as np + +from tensorflow.python.client import session +from tensorflow.python.data.experimental.ops import batching +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.ops import array_ops +from tensorflow.python.platform import test + + +class UnbatchBenchmark(test.Benchmark): + """Benchmarks for `tf.data.experimental.unbatch()`.""" + + def benchmarkNativeUnbatch(self): + batch_sizes = [1, 2, 5, 10, 20, 50] + elems_per_trial = 10000 + with ops.Graph().as_default(): + dataset = dataset_ops.Dataset.from_tensors("element").repeat(None) + batch_size_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) + dataset = dataset.batch(batch_size_placeholder) + dataset = dataset.apply(batching.unbatch()) + dataset = dataset.skip(elems_per_trial) + iterator = dataset_ops.make_initializable_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + for batch_size in batch_sizes: + deltas = [] + for _ in range(5): + sess.run( + iterator.initializer, + feed_dict={batch_size_placeholder: batch_size}) + start = time.time() + sess.run(next_element.op) + end = time.time() + deltas.append((end - start) / elems_per_trial) + + median_wall_time = np.median(deltas) + print("Unbatch (native) batch size: %d Median wall time per element:" + " %f microseconds" % (batch_size, median_wall_time * 1e6)) + self.report_benchmark( + iters=10000, + wall_time=median_wall_time, + name="native_batch_size_%d" % + batch_size) + + # Include a benchmark of the previous `unbatch()` implementation that uses + # a composition of more primitive ops. Eventually we'd hope to generate code + # that is as good in both cases. + def benchmarkOldUnbatchImplementation(self): + batch_sizes = [1, 2, 5, 10, 20, 50] + elems_per_trial = 10000 + with ops.Graph().as_default(): + dataset = dataset_ops.Dataset.from_tensors("element").repeat(None) + batch_size_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) + dataset = dataset.batch(batch_size_placeholder) + dataset = dataset.flat_map(dataset_ops.Dataset.from_tensor_slices) + dataset = dataset.skip(elems_per_trial) + iterator = dataset_ops.make_initializable_iterator(dataset) + next_element = iterator.get_next() + + with session.Session() as sess: + for batch_size in batch_sizes: + deltas = [] + for _ in range(5): + sess.run( + iterator.initializer, + feed_dict={batch_size_placeholder: batch_size}) + start = time.time() + sess.run(next_element.op) + end = time.time() + deltas.append((end - start) / elems_per_trial) + + median_wall_time = np.median(deltas) + print("Unbatch (unfused) batch size: %d Median wall time per element:" + " %f microseconds" % (batch_size, median_wall_time * 1e6)) + self.report_benchmark( + iters=10000, + wall_time=median_wall_time, + name="unfused_batch_size_%d" % + batch_size) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/BUILD b/tensorflow/python/data/experimental/kernel_tests/BUILD index c9b11a2c38..c76e576b5b 100644 --- a/tensorflow/python/data/experimental/kernel_tests/BUILD +++ b/tensorflow/python/data/experimental/kernel_tests/BUILD @@ -72,15 +72,11 @@ py_test( "//tensorflow/python:errors", "//tensorflow/python:framework_test_lib", "//tensorflow/python:parsing_ops", - "//tensorflow/python:platform", - "//tensorflow/python:platform_test", - "//tensorflow/python:session", "//tensorflow/python/data/experimental/ops:error_ops", "//tensorflow/python/data/experimental/ops:readers", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:readers", "//tensorflow/python/eager:context", - "//third_party/py/numpy", ], ) @@ -153,27 +149,6 @@ py_test( ], ) -cuda_py_test( - name = "function_buffering_resource_test", - size = "small", - srcs = ["function_buffering_resource_test.py"], - additional_deps = [ - "//tensorflow/python/data/experimental/ops:prefetching_ops", - "//tensorflow/core:protos_all_py", - "//tensorflow/python:client_testlib", - "//tensorflow/python:constant_op", - "//tensorflow/python/data/kernel_tests:test_base", - "//tensorflow/python/eager:function", - "//tensorflow/python:dtypes", - "//tensorflow/python:framework_ops", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:resource_variable_ops", - "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/data/ops:iterator_ops", - ], - tags = ["no_windows_gpu"], -) - py_test( name = "get_single_element_test", size = "small", @@ -371,6 +346,37 @@ py_test( ], ) +py_test( + name = "matching_files_test", + size = "small", + srcs = ["matching_files_test.py"], + srcs_version = "PY2AND3", + tags = ["no_pip"], + deps = [ + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", + "//tensorflow/python:errors", + "//tensorflow/python:util", + "//tensorflow/python/data/experimental/ops:matching_files", + "//tensorflow/python/data/kernel_tests:test_base", + "//tensorflow/python/data/ops:dataset_ops", + "//third_party/py/numpy", + ], +) + +py_test( + name = "cardinality_test", + srcs = ["cardinality_test.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python/data/experimental/ops:cardinality", + "//tensorflow/python/data/kernel_tests:test_base", + "//tensorflow/python/data/ops:dataset_ops", + "@absl_py//absl/testing:parameterized", + ], +) + py_test( name = "override_threadpool_test", size = "small", @@ -618,7 +624,9 @@ py_test( size = "medium", srcs = ["stats_dataset_ops_test.py"], srcs_version = "PY2AND3", - tags = ["no_pip"], + tags = [ + "no_pip", + ], deps = [ ":reader_dataset_ops_test_base", ":stats_dataset_test_base", diff --git a/tensorflow/python/data/experimental/kernel_tests/batch_dataset_op_test.py b/tensorflow/python/data/experimental/kernel_tests/batch_dataset_op_test.py deleted file mode 100644 index e896752a26..0000000000 --- a/tensorflow/python/data/experimental/kernel_tests/batch_dataset_op_test.py +++ /dev/null @@ -1,688 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import math -import time - -from absl.testing import parameterized -import numpy as np - -from tensorflow.python.client import session -from tensorflow.python.data.experimental.ops import batching -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import ops -from tensorflow.python.framework import sparse_tensor -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import script_ops -from tensorflow.python.ops import string_ops -from tensorflow.python.platform import test -from tensorflow.python.util import compat - - -class BatchDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): - - def testDenseToSparseBatchDataset(self): - components = np.random.randint(12, size=(100,)).astype(np.int32) - iterator = ( - dataset_ops.Dataset.from_tensor_slices(components) - .map(lambda x: array_ops.fill([x], x)).apply( - batching.dense_to_sparse_batch(4, - [12])).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - - for start in range(0, len(components), 4): - results = sess.run(get_next) - self.assertAllEqual([[i, j] - for i, c in enumerate(components[start:start + 4]) - for j in range(c)], results.indices) - self.assertAllEqual( - [c for c in components[start:start + 4] for _ in range(c)], - results.values) - self.assertAllEqual([min(4, - len(components) - start), 12], - results.dense_shape) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testDenseToSparseBatchDatasetWithUnknownShape(self): - components = np.random.randint(5, size=(40,)).astype(np.int32) - iterator = ( - dataset_ops.Dataset.from_tensor_slices(components).map( - lambda x: array_ops.fill([x, x], x)).apply( - batching.dense_to_sparse_batch( - 4, [5, None])).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - - for start in range(0, len(components), 4): - results = sess.run(get_next) - self.assertAllEqual([[i, j, z] - for i, c in enumerate(components[start:start + 4]) - for j in range(c) - for z in range(c)], results.indices) - self.assertAllEqual([ - c for c in components[start:start + 4] for _ in range(c) - for _ in range(c) - ], results.values) - self.assertAllEqual([ - min(4, - len(components) - start), 5, - np.max(components[start:start + 4]) - ], results.dense_shape) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testDenseToSparseBatchDatasetWithInvalidShape(self): - input_tensor = array_ops.constant([[1]]) - with self.assertRaisesRegexp(ValueError, "Dimension -2 must be >= 0"): - dataset_ops.Dataset.from_tensors(input_tensor).apply( - batching.dense_to_sparse_batch(4, - [-2])).make_initializable_iterator() - - def testDenseToSparseBatchDatasetShapeErrors(self): - input_tensor = array_ops.placeholder(dtypes.int32) - iterator = ( - dataset_ops.Dataset.from_tensors(input_tensor).apply( - batching.dense_to_sparse_batch(4, - [12])).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - # Initialize with an input tensor of incompatible rank. - sess.run(init_op, feed_dict={input_tensor: [[1]]}) - with self.assertRaisesRegexp(errors.InvalidArgumentError, - "incompatible with the row shape"): - sess.run(get_next) - - # Initialize with an input tensor that is larger than `row_shape`. - sess.run(init_op, feed_dict={input_tensor: range(13)}) - with self.assertRaisesRegexp(errors.DataLossError, - "larger than the row shape"): - sess.run(get_next) - - def testUnbatchWithUnknownRankInput(self): - placeholder = array_ops.placeholder(dtypes.int32) - dataset = dataset_ops.Dataset.from_tensors(placeholder).apply( - batching.unbatch()) - iterator = dataset.make_initializable_iterator() - next_elem = iterator.get_next() - - with self.cached_session() as sess: - sess.run(iterator.initializer, feed_dict={placeholder: [0, 1, 2, 3]}) - for i in range(4): - self.assertEqual(i, sess.run(next_elem)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_elem) - - def testUnbatchScalarDataset(self): - data = tuple([math_ops.range(10) for _ in range(3)]) - data = dataset_ops.Dataset.from_tensor_slices(data) - expected_types = (dtypes.int32,) * 3 - data = data.batch(2) - self.assertEqual(expected_types, data.output_types) - data = data.apply(batching.unbatch()) - self.assertEqual(expected_types, data.output_types) - - iterator = data.make_one_shot_iterator() - op = iterator.get_next() - - with self.cached_session() as sess: - for i in range(10): - self.assertEqual((i,) * 3, sess.run(op)) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(op) - - def testUnbatchDatasetWithStrings(self): - data = tuple([math_ops.range(10) for _ in range(3)]) - data = dataset_ops.Dataset.from_tensor_slices(data) - data = data.map(lambda x, y, z: (x, string_ops.as_string(y), z)) - expected_types = (dtypes.int32, dtypes.string, dtypes.int32) - data = data.batch(2) - self.assertEqual(expected_types, data.output_types) - data = data.apply(batching.unbatch()) - self.assertEqual(expected_types, data.output_types) - - iterator = data.make_one_shot_iterator() - op = iterator.get_next() - - with self.cached_session() as sess: - for i in range(10): - self.assertEqual((i, compat.as_bytes(str(i)), i), sess.run(op)) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(op) - - def testUnbatchDatasetWithSparseTensor(self): - st = sparse_tensor.SparseTensorValue( - indices=[[i, i] for i in range(10)], - values=list(range(10)), - dense_shape=[10, 10]) - data = dataset_ops.Dataset.from_tensors(st) - data = data.apply(batching.unbatch()) - data = data.batch(5) - data = data.apply(batching.unbatch()) - iterator = data.make_one_shot_iterator() - next_element = iterator.get_next() - - with self.cached_session() as sess: - for i in range(10): - st_row = sess.run(next_element) - self.assertEqual([i], st_row.indices) - self.assertEqual([i], st_row.values) - self.assertEqual([10], st_row.dense_shape) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - def testUnbatchDatasetWithDenseAndSparseTensor(self): - st = sparse_tensor.SparseTensorValue( - indices=[[i, i] for i in range(10)], - values=list(range(10)), - dense_shape=[10, 10]) - data = dataset_ops.Dataset.from_tensors((list(range(10)), st)) - data = data.apply(batching.unbatch()) - data = data.batch(5) - data = data.apply(batching.unbatch()) - iterator = data.make_one_shot_iterator() - next_element = iterator.get_next() - - with self.cached_session() as sess: - for i in range(10): - dense_elem, st_row = sess.run(next_element) - self.assertEqual(i, dense_elem) - self.assertEqual([i], st_row.indices) - self.assertEqual([i], st_row.values) - self.assertEqual([10], st_row.dense_shape) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - def testUnbatchSingleElementTupleDataset(self): - data = tuple([(math_ops.range(10),) for _ in range(3)]) - data = dataset_ops.Dataset.from_tensor_slices(data) - expected_types = ((dtypes.int32,),) * 3 - data = data.batch(2) - self.assertEqual(expected_types, data.output_types) - data = data.apply(batching.unbatch()) - self.assertEqual(expected_types, data.output_types) - - iterator = data.make_one_shot_iterator() - op = iterator.get_next() - - with self.cached_session() as sess: - for i in range(10): - self.assertEqual(((i,),) * 3, sess.run(op)) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(op) - - def testUnbatchMultiElementTupleDataset(self): - data = tuple([(math_ops.range(10 * i, 10 * i + 10), - array_ops.fill([10], "hi")) for i in range(3)]) - data = dataset_ops.Dataset.from_tensor_slices(data) - expected_types = ((dtypes.int32, dtypes.string),) * 3 - data = data.batch(2) - self.assertAllEqual(expected_types, data.output_types) - data = data.apply(batching.unbatch()) - self.assertAllEqual(expected_types, data.output_types) - - iterator = data.make_one_shot_iterator() - op = iterator.get_next() - - with self.cached_session() as sess: - for i in range(10): - self.assertEqual(((i, b"hi"), (10 + i, b"hi"), (20 + i, b"hi")), - sess.run(op)) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(op) - - def testUnbatchEmpty(self): - data = dataset_ops.Dataset.from_tensors( - (constant_op.constant([]), constant_op.constant([], shape=[0, 4]), - constant_op.constant([], shape=[0, 4, 0]))) - data = data.apply(batching.unbatch()) - iterator = data.make_one_shot_iterator() - next_element = iterator.get_next() - - with self.cached_session() as sess: - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - def testUnbatchStaticShapeMismatch(self): - data = dataset_ops.Dataset.from_tensors((np.arange(7), np.arange(8), - np.arange(9))) - with self.assertRaises(ValueError): - data.apply(batching.unbatch()) - - def testUnbatchDynamicShapeMismatch(self): - ph1 = array_ops.placeholder(dtypes.int32, shape=[None]) - ph2 = array_ops.placeholder(dtypes.int32, shape=None) - data = dataset_ops.Dataset.from_tensors((ph1, ph2)) - data = data.apply(batching.unbatch()) - iterator = data.make_initializable_iterator() - next_element = iterator.get_next() - - with self.cached_session() as sess: - # Mismatch in the 0th dimension. - sess.run( - iterator.initializer, - feed_dict={ - ph1: np.arange(7).astype(np.int32), - ph2: np.arange(8).astype(np.int32) - }) - with self.assertRaises(errors.InvalidArgumentError): - sess.run(next_element) - - # No 0th dimension (i.e. scalar value) for one component. - sess.run( - iterator.initializer, - feed_dict={ - ph1: np.arange(7).astype(np.int32), - ph2: 7 - }) - with self.assertRaises(errors.InvalidArgumentError): - sess.run(next_element) - - @parameterized.named_parameters( - ("Default", None, None), - ("SequentialCalls", 1, None), - ("ParallelCalls", 2, None), - ("ParallelBatches", None, 10), - ) - def testMapAndBatch(self, num_parallel_calls, num_parallel_batches): - """Test a dataset that maps a TF function across its input elements.""" - # The pipeline is TensorSliceDataset -> - # RepeatDataset(count) -> MapAndBatchDataset(square_3, batch_size). - components = (np.arange(7), - np.array([[1, 2, 3]]) * np.arange(7)[:, np.newaxis], - np.array(37.0) * np.arange(7)) - - count = array_ops.placeholder(dtypes.int64, shape=[]) - batch_size = array_ops.placeholder(dtypes.int64, shape=[]) - - def _map_fn(x, y, z): - return math_ops.square(x), math_ops.square(y), math_ops.square(z) - - iterator = ( - dataset_ops.Dataset.from_tensor_slices(components).repeat(count).apply( - batching.map_and_batch( - map_func=_map_fn, - batch_size=batch_size, - num_parallel_calls=num_parallel_calls, - num_parallel_batches=num_parallel_batches)) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([[None] + list(c.shape[1:]) for c in components], - [t.shape.as_list() for t in get_next]) - - with self.cached_session() as sess: - # Batch of a finite input, where the batch_size divides the - # total number of elements. - sess.run(init_op, feed_dict={count: 28, batch_size: 14}) - num_batches = (28 * 7) // 14 - for i in range(num_batches): - result = sess.run(get_next) - for component, result_component in zip(components, result): - for j in range(14): - self.assertAllEqual(component[(i * 14 + j) % 7]**2, - result_component[j]) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Batch of a finite input, where the batch_size does not - # divide the total number of elements. - sess.run(init_op, feed_dict={count: 14, batch_size: 8}) - - # We expect (num_batches - 1) full-sized batches. - num_batches = int(math.ceil((14 * 7) / 8)) - for i in range(num_batches - 1): - result = sess.run(get_next) - for component, result_component in zip(components, result): - for j in range(8): - self.assertAllEqual(component[(i * 8 + j) % 7]**2, - result_component[j]) - result = sess.run(get_next) - for component, result_component in zip(components, result): - for j in range((14 * 7) % 8): - self.assertAllEqual(component[((num_batches - 1) * 8 + j) % 7]**2, - result_component[j]) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Batch of an empty input should fail straight away. - sess.run(init_op, feed_dict={count: 0, batch_size: 8}) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Empty batch should be an initialization time error. - with self.assertRaises(errors.InvalidArgumentError): - sess.run(init_op, feed_dict={count: 14, batch_size: 0}) - - @parameterized.named_parameters( - ("Even", False), - ("Uneven", True), - ) - def testMapAndBatchPartialBatch(self, drop_remainder): - iterator = ( - dataset_ops.Dataset.range(10).apply( - batching.map_and_batch( - lambda x: array_ops.reshape(x * x, [1]), - batch_size=4, - drop_remainder=drop_remainder)).make_one_shot_iterator()) - if drop_remainder: - self.assertEqual([4, 1], iterator.output_shapes.as_list()) - else: - self.assertEqual([None, 1], iterator.output_shapes.as_list()) - next_element = iterator.get_next() - with self.cached_session() as sess: - self.assertAllEqual([[0], [1], [4], [9]], sess.run(next_element)) - self.assertAllEqual([[16], [25], [36], [49]], sess.run(next_element)) - if not drop_remainder: - self.assertAllEqual([[64], [81]], sess.run(next_element)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - def testMapAndBatchYieldsPartialBatch(self): - iterator = ( - dataset_ops.Dataset.range(10).apply( - batching.map_and_batch(lambda x: array_ops.reshape(x * x, [1]), - 4)).make_one_shot_iterator()) - self.assertEqual([None, 1], iterator.output_shapes.as_list()) - next_element = iterator.get_next() - with self.cached_session() as sess: - self.assertAllEqual([[0], [1], [4], [9]], sess.run(next_element)) - self.assertAllEqual([[16], [25], [36], [49]], sess.run(next_element)) - self.assertAllEqual([[64], [81]], sess.run(next_element)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - def testMapAndBatchParallelGetNext(self): - iterator = ( - dataset_ops.Dataset.range(50000).apply( - batching.map_and_batch(lambda x: x, - batch_size=100)).make_one_shot_iterator()) - elements = [] - for _ in range(100): - elements.append(iterator.get_next()) - with self.cached_session() as sess: - for i in range(5): - got = sess.run(elements) - got.sort(key=lambda x: x[0]) - expected = [] - for j in range(100): - expected.append(range(i * 10000 + j * 100, i * 10000 + (j + 1) * 100)) - self.assertAllEqual(got, expected) - with self.assertRaises(errors.OutOfRangeError): - sess.run(elements) - - def testMapAndBatchParallelGetNextDropRemainder(self): - iterator = ( - dataset_ops.Dataset.range(49999).apply( - batching.map_and_batch( - lambda x: x, batch_size=100, - drop_remainder=True)).make_one_shot_iterator()) - elements = [] - for _ in range(100): - elements.append(iterator.get_next()) - with self.cached_session() as sess: - for i in range(4): - got = sess.run(elements) - got.sort(key=lambda x: x[0]) - expected = [] - for j in range(100): - expected.append(range(i * 10000 + j * 100, i * 10000 + (j + 1) * 100)) - self.assertAllEqual(got, expected) - with self.assertRaises(errors.OutOfRangeError): - sess.run(elements) - - def testMapAndBatchSparse(self): - - def _sparse(i): - return sparse_tensor.SparseTensorValue( - indices=[[0]], values=(i * [1]), dense_shape=[1]) - - iterator = dataset_ops.Dataset.range(10).apply( - batching.map_and_batch(_sparse, 5)).make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(2): - actual = sess.run(get_next) - expected = sparse_tensor.SparseTensorValue( - indices=[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], - values=[i * 5, i * 5 + 1, i * 5 + 2, i * 5 + 3, i * 5 + 4], - dense_shape=[5, 1]) - self.assertTrue(sparse_tensor.is_sparse(actual)) - self.assertSparseValuesEqual(actual, expected) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testMapAndBatchFails(self): - """Test a dataset that maps a TF function across its input elements.""" - dataset = dataset_ops.Dataset.from_tensors( - array_ops.check_numerics( - constant_op.constant(1.0) / constant_op.constant(0.0), "oops")) - batch_size = array_ops.placeholder(dtypes.int64, shape=[]) - iterator = ( - dataset.apply(batching.map_and_batch( - lambda x: x, batch_size)).make_initializable_iterator()) - init_op = iterator.initializer - with self.cached_session() as sess: - with self.assertRaisesRegexp(errors.InvalidArgumentError, "oops"): - sess.run(init_op, feed_dict={batch_size: 14}) - - def testMapAndBatchShapeMismatch(self): - """Test a dataset that maps a TF function across its input elements.""" - - def generator(): - yield [1] - yield [2] - yield [3] - yield [[4, 5, 6]] - - dataset = dataset_ops.Dataset.from_generator( - generator, output_types=dtypes.int32) - batch_size = 4 - iterator = ( - dataset.apply(batching.map_and_batch( - lambda x: x, batch_size)).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - with self.cached_session() as sess: - sess.run(init_op) - with self.assertRaisesRegexp(errors.InvalidArgumentError, - "number of elements does not match"): - sess.run(get_next) - - def testMapAndBatchImplicitDispose(self): - # Tests whether a map and batch dataset will be cleaned up correctly when - # the pipeline does not run it until exhaustion. - # The pipeline is TensorSliceDataset -> RepeatDataset(1000) -> - # MapAndBatchDataset(f=square_3, batch_size=100). - components = (np.arange(1000), - np.array([[1, 2, 3]]) * np.arange(1000)[:, np.newaxis], - np.array(37.0) * np.arange(1000)) - - def _map_fn(x, y, z): - return math_ops.square(x), math_ops.square(y), math_ops.square(z) - - dataset = dataset_ops.Dataset.from_tensor_slices(components).repeat( - 1000).apply(batching.map_and_batch(_map_fn, batch_size=100)) - dataset = dataset.prefetch(5) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - for _ in range(3): - sess.run(get_next) - - @parameterized.named_parameters( - ("1", 0), - ("2", 5), - ("3", 10), - ("4", 90), - ("5", 95), - ("6", 99), - ) - def testMapAndBatchOutOfRangeError(self, threshold): - - def raising_py_fn(i): - if i >= threshold: - raise StopIteration() - else: - return i - - iterator = ( - dataset_ops.Dataset.range(100).apply( - batching.map_and_batch( - lambda x: script_ops.py_func(raising_py_fn, [x], dtypes.int64), - batch_size=10)).make_one_shot_iterator()) - get_next = iterator.get_next() - - with self.cached_session() as sess: - for i in range(threshold // 10): - self.assertAllEqual([i * 10 + j for j in range(10)], sess.run(get_next)) - if threshold % 10 != 0: - self.assertAllEqual( - [threshold // 10 * 10 + j for j in range(threshold % 10)], - sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - @parameterized.named_parameters( - ("1", False, dtypes.bool), - ("2", -42, dtypes.int8), - ("3", -42, dtypes.int16), - ("4", -42, dtypes.int32), - ("5", -42, dtypes.int64), - ("6", 42, dtypes.uint8), - ("7", 42, dtypes.uint16), - ("8", 42.0, dtypes.float16), - ("9", 42.0, dtypes.float32), - ("10", 42.0, dtypes.float64), - ("11", b"hello", dtypes.string), - ) - def testMapAndBatchTypes(self, element, dtype): - - def gen(): - yield element - - dataset = dataset_ops.Dataset.from_generator(gen, dtype).repeat(100).apply( - batching.map_and_batch(lambda x: x, batch_size=10)) - - get_next = dataset.make_one_shot_iterator().get_next() - - with self.cached_session() as sess: - for _ in range(10): - self.assertAllEqual([element for _ in range(10)], sess.run(get_next)) - - -class UnbatchDatasetBenchmark(test.Benchmark): - - def benchmarkNativeUnbatch(self): - batch_sizes = [1, 2, 5, 10, 20, 50] - elems_per_trial = 10000 - with ops.Graph().as_default(): - dataset = dataset_ops.Dataset.from_tensors("element").repeat(None) - batch_size_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - dataset = dataset.batch(batch_size_placeholder) - dataset = dataset.apply(batching.unbatch()) - dataset = dataset.skip(elems_per_trial) - iterator = dataset.make_initializable_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - for batch_size in batch_sizes: - deltas = [] - for _ in range(5): - sess.run( - iterator.initializer, - feed_dict={batch_size_placeholder: batch_size}) - start = time.time() - sess.run(next_element.op) - end = time.time() - deltas.append((end - start) / elems_per_trial) - - median_wall_time = np.median(deltas) - print("Unbatch (native) batch size: %d Median wall time per element:" - " %f microseconds" % (batch_size, median_wall_time * 1e6)) - self.report_benchmark( - iters=10000, - wall_time=median_wall_time, - name="benchmark_unbatch_dataset_native_batch_size_%d" % - batch_size) - - # Include a benchmark of the previous `unbatch()` implementation that uses - # a composition of more primitive ops. Eventually we'd hope to generate code - # that is as good in both cases. - def benchmarkOldUnbatchImplementation(self): - batch_sizes = [1, 2, 5, 10, 20, 50] - elems_per_trial = 10000 - with ops.Graph().as_default(): - dataset = dataset_ops.Dataset.from_tensors("element").repeat(None) - batch_size_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - dataset = dataset.batch(batch_size_placeholder) - dataset = dataset.flat_map(dataset_ops.Dataset.from_tensor_slices) - dataset = dataset.skip(elems_per_trial) - iterator = dataset.make_initializable_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - for batch_size in batch_sizes: - deltas = [] - for _ in range(5): - sess.run( - iterator.initializer, - feed_dict={batch_size_placeholder: batch_size}) - start = time.time() - sess.run(next_element.op) - end = time.time() - deltas.append((end - start) / elems_per_trial) - - median_wall_time = np.median(deltas) - print("Unbatch (unfused) batch size: %d Median wall time per element:" - " %f microseconds" % (batch_size, median_wall_time * 1e6)) - self.report_benchmark( - iters=10000, - wall_time=median_wall_time, - name="benchmark_unbatch_dataset_unfused_batch_size_%d" % - batch_size) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py index 3903ec49b9..8264dee3c1 100644 --- a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py @@ -105,14 +105,14 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): boundaries, batch_sizes, no_padding=no_padding)) - batch, = dataset.make_one_shot_iterator().get_next() + batch, = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: batches = [] for _ in range(4): - batches.append(sess.run(batch)) + batches.append(self.evaluate(batch)) with self.assertRaises(errors.OutOfRangeError): - sess.run(batch) + self.evaluate(batch) batch_sizes_val = [] lengths_val = [] for batch in batches: @@ -155,14 +155,14 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): grouping.bucket_by_sequence_length( element_len, boundaries, batch_sizes, pad_to_bucket_boundary=True)) - batch, = dataset.make_one_shot_iterator().get_next() + batch, = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: batches = [] for _ in range(3): - batches.append(sess.run(batch)) + batches.append(self.evaluate(batch)) with self.assertRaisesOpError("bucket_boundaries"): - sess.run(batch) + self.evaluate(batch) batch_sizes_val = [] lengths_val = [] for batch in batches: @@ -192,14 +192,14 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): grouping.bucket_by_sequence_length( element_len, boundaries, batch_sizes, pad_to_bucket_boundary=True)) - batch, = dataset.make_one_shot_iterator().get_next() + batch, = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: batches = [] for _ in range(5): - batches.append(sess.run(batch)) + batches.append(self.evaluate(batch)) with self.assertRaises(errors.OutOfRangeError): - sess.run(batch) + self.evaluate(batch) self.assertAllEqual(batches[0], [[1, 0], [1, 1]]) @@ -295,12 +295,12 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): def _compute_batches(dataset): """Computes actual batch outputs of dataset and stores in a set.""" - batch = dataset.make_one_shot_iterator().get_next() + batch = dataset_ops.make_one_shot_iterator(dataset).get_next() all_sparse_tensors = set() with self.cached_session() as sess: with self.assertRaises(errors.OutOfRangeError): while True: - output = sess.run(batch) + output = self.evaluate(batch) sprs_tensor = (tuple([tuple(idx) for idx in output.indices]), tuple(output.values)) all_sparse_tensors.add(sprs_tensor) diff --git a/tensorflow/python/data/experimental/kernel_tests/cardinality_test.py b/tensorflow/python/data/experimental/kernel_tests/cardinality_test.py new file mode 100644 index 0000000000..943f0f1f81 --- /dev/null +++ b/tensorflow/python/data/experimental/kernel_tests/cardinality_test.py @@ -0,0 +1,158 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.experimental.cardinality()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from absl.testing import parameterized + +from tensorflow.python.data.experimental.ops import cardinality +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.platform import test + + +class NumElementsTest(test_base.DatasetTestBase, parameterized.TestCase): + """Tests for `tf.data.experimental.cardinality()`.""" + + @parameterized.named_parameters( + # pylint: disable=g-long-lambda + ("Batch1", + lambda: dataset_ops.Dataset.range(5).batch(2, drop_remainder=True), 2), + ("Batch2", + lambda: dataset_ops.Dataset.range(5).batch(2, drop_remainder=False), 3), + ("Batch3", + lambda: dataset_ops.Dataset.range(5).filter(lambda _: True).batch(2), + cardinality.UNKNOWN), + ("Batch4", lambda: dataset_ops.Dataset.range(5).repeat().batch(2), + cardinality.INFINITE), + ("Cache1", lambda: dataset_ops.Dataset.range(5).cache(), 5), + ("Cache2", lambda: dataset_ops.Dataset.range(5).cache("foo"), 5), + ("Concatenate1", lambda: dataset_ops.Dataset.range(5).concatenate( + dataset_ops.Dataset.range(5)), 10), + ("Concatenate2", + lambda: dataset_ops.Dataset.range(5).filter(lambda _: True).concatenate( + dataset_ops.Dataset.range(5)), cardinality.UNKNOWN), + ("Concatenate3", lambda: dataset_ops.Dataset.range(5).repeat(). + concatenate(dataset_ops.Dataset.range(5)), + cardinality.INFINITE), + ("Concatenate4", lambda: dataset_ops.Dataset.range(5).concatenate( + dataset_ops.Dataset.range(5).filter(lambda _: True)), + cardinality.UNKNOWN), + ("Concatenate5", + lambda: dataset_ops.Dataset.range(5).filter(lambda _: True).concatenate( + dataset_ops.Dataset.range(5).filter(lambda _: True)), + cardinality.UNKNOWN), + ("Concatenate6", lambda: dataset_ops.Dataset.range(5).repeat(). + concatenate(dataset_ops.Dataset.range(5).filter(lambda _: True)), + cardinality.INFINITE), + ("Concatenate7", lambda: dataset_ops.Dataset.range(5).concatenate( + dataset_ops.Dataset.range(5).repeat()), cardinality.INFINITE), + ("Concatenate8", + lambda: dataset_ops.Dataset.range(5).filter(lambda _: True).concatenate( + dataset_ops.Dataset.range(5).repeat()), cardinality.INFINITE), + ("Concatenate9", + lambda: dataset_ops.Dataset.range(5).repeat().concatenate( + dataset_ops.Dataset.range(5).repeat()), cardinality.INFINITE), + ("FlatMap", lambda: dataset_ops.Dataset.range(5).flat_map( + lambda _: dataset_ops.Dataset.from_tensors(0)), + cardinality.UNKNOWN), + ("Filter", lambda: dataset_ops.Dataset.range(5).filter(lambda _: True), + cardinality.UNKNOWN), + ("FromTensors1", lambda: dataset_ops.Dataset.from_tensors(0), 1), + ("FromTensors2", lambda: dataset_ops.Dataset.from_tensors((0, 1)), 1), + ("FromTensorSlices1", + lambda: dataset_ops.Dataset.from_tensor_slices([0, 0, 0]), 3), + ("FromTensorSlices2", + lambda: dataset_ops.Dataset.from_tensor_slices(([0, 0, 0], [1, 1, 1])), + 3), + ("Interleave1", lambda: dataset_ops.Dataset.range(5).interleave( + lambda _: dataset_ops.Dataset.from_tensors(0), cycle_length=1), + cardinality.UNKNOWN), + ("Interleave2", lambda: dataset_ops.Dataset.range(5).interleave( + lambda _: dataset_ops.Dataset.from_tensors(0), + cycle_length=1, + num_parallel_calls=1), cardinality.UNKNOWN), + ("Map1", lambda: dataset_ops.Dataset.range(5).map(lambda x: x), 5), + ("Map2", lambda: dataset_ops.Dataset.range(5).map( + lambda x: x, num_parallel_calls=1), 5), + ("PaddedBatch1", lambda: dataset_ops.Dataset.range(5).padded_batch( + 2, [], drop_remainder=True), 2), + ("PaddedBatch2", lambda: dataset_ops.Dataset.range(5).padded_batch( + 2, [], drop_remainder=False), 3), + ("PaddedBatch3", lambda: dataset_ops.Dataset.range(5).filter( + lambda _: True).padded_batch(2, []), cardinality.UNKNOWN), + ("PaddedBatch4", + lambda: dataset_ops.Dataset.range(5).repeat().padded_batch(2, []), + cardinality.INFINITE), + ("Prefetch", lambda: dataset_ops.Dataset.range(5).prefetch(buffer_size=1), + 5), + ("Range1", lambda: dataset_ops.Dataset.range(0), 0), + ("Range2", lambda: dataset_ops.Dataset.range(5), 5), + ("Range3", lambda: dataset_ops.Dataset.range(5, 10), 5), + ("Range4", lambda: dataset_ops.Dataset.range(10, 5), 0), + ("Range5", lambda: dataset_ops.Dataset.range(5, 10, 2), 3), + ("Range6", lambda: dataset_ops.Dataset.range(10, 5, -2), 3), + ("Repeat1", lambda: dataset_ops.Dataset.range(0).repeat(0), 0), + ("Repeat2", lambda: dataset_ops.Dataset.range(1).repeat(0), 0), + ("Repeat3", lambda: dataset_ops.Dataset.range(0).repeat(5), 0), + ("Repeat4", lambda: dataset_ops.Dataset.range(1).repeat(5), 5), + ("Repeat5", lambda: dataset_ops.Dataset.range(0).repeat(), 0), + ("Repeat6", lambda: dataset_ops.Dataset.range(1).repeat(), + cardinality.INFINITE), + ("Shuffle", lambda: dataset_ops.Dataset.range(5).shuffle(buffer_size=1), + 5), + ("Skip1", lambda: dataset_ops.Dataset.range(5).skip(2), 3), + ("Skip2", lambda: dataset_ops.Dataset.range(5).skip(8), 0), + ("Skip3", + lambda: dataset_ops.Dataset.range(5).filter(lambda _: True).skip(2), + cardinality.UNKNOWN), + ("Skip4", lambda: dataset_ops.Dataset.range(5).repeat().skip(2), + cardinality.INFINITE), + ("Take1", lambda: dataset_ops.Dataset.range(5).take(2), 2), + ("Take2", lambda: dataset_ops.Dataset.range(5).take(8), 5), + ("Take3", + lambda: dataset_ops.Dataset.range(5).filter(lambda _: True).take(2), + cardinality.UNKNOWN), + ("Take4", lambda: dataset_ops.Dataset.range(5).repeat().take(2), 2), + ("Window1", lambda: dataset_ops.Dataset.range(5).window( + size=2, shift=2, drop_remainder=True), 2), + ("Window2", lambda: dataset_ops.Dataset.range(5).window( + size=2, shift=2, drop_remainder=False), 3), + ("Zip1", lambda: dataset_ops.Dataset.zip(dataset_ops.Dataset.range(5)), + 5), + ("Zip2", lambda: dataset_ops.Dataset.zip( + (dataset_ops.Dataset.range(5), dataset_ops.Dataset.range(3))), 3), + ("Zip3", lambda: dataset_ops.Dataset.zip( + (dataset_ops.Dataset.range(5), + dataset_ops.Dataset.range(3).repeat())), 5), + ("Zip4", lambda: dataset_ops.Dataset.zip( + (dataset_ops.Dataset.range(5).repeat(), + dataset_ops.Dataset.range(3).repeat())), cardinality.INFINITE), + ("Zip5", lambda: dataset_ops.Dataset.zip( + (dataset_ops.Dataset.range(5), + dataset_ops.Dataset.range(3).filter(lambda _: True))), + cardinality.UNKNOWN), + # pylint: enable=g-long-lambda + ) + def testNumElements(self, dataset_fn, expected_result): + with self.cached_session() as sess: + self.assertEqual( + sess.run(cardinality.cardinality(dataset_fn())), expected_result) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/copy_to_device_test.py b/tensorflow/python/data/experimental/kernel_tests/copy_to_device_test.py index cea8bd6f0b..b8166fe833 100644 --- a/tensorflow/python/data/experimental/kernel_tests/copy_to_device_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/copy_to_device_test.py @@ -35,13 +35,14 @@ from tensorflow.python.util import compat as util_compat class CopyToDeviceTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testCopyToDevice(self): host_dataset = dataset_ops.Dataset.range(10) device_dataset = host_dataset.apply( prefetching_ops.copy_to_device("/cpu:1")) with ops.device("/cpu:1"): - iterator = device_dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -55,19 +56,20 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual([], next_element.shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testCopyToDeviceInt32(self): host_dataset = dataset_ops.Dataset.from_tensors([0, 1, 2, 3]) device_dataset = host_dataset.apply( prefetching_ops.copy_to_device("/cpu:1")) with ops.device("/cpu:1"): - iterator = device_dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -81,18 +83,19 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual((4,), next_element.shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: - self.assertAllEqual([0, 1, 2, 3], sess.run(next_element)) + with self.test_session(config=worker_config): + self.assertAllEqual([0, 1, 2, 3], self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testCopyToSameDevice(self): host_dataset = dataset_ops.Dataset.range(10) device_dataset = host_dataset.apply( prefetching_ops.copy_to_device("/cpu:0")) with ops.device("/cpu:0"): - iterator = device_dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -106,19 +109,20 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual([], next_element.shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testCopyToDeviceWithPrefetch(self): host_dataset = dataset_ops.Dataset.range(10) device_dataset = host_dataset.apply( prefetching_ops.copy_to_device("/cpu:1")).prefetch(1) with ops.device("/cpu:1"): - iterator = device_dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -132,19 +136,20 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual([], next_element.shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testCopyDictToDevice(self): host_dataset = dataset_ops.Dataset.range(10).map(lambda x: {"a": x}) device_dataset = host_dataset.apply( prefetching_ops.copy_to_device("/cpu:1")) with ops.device("/cpu:1"): - iterator = device_dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -158,19 +163,20 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual([], next_element["a"].shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - self.assertEqual({"a": i}, sess.run(next_element)) + self.assertEqual({"a": i}, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testCopyDictToDeviceWithPrefetch(self): host_dataset = dataset_ops.Dataset.range(10).map(lambda x: {"a": x}) device_dataset = host_dataset.apply( prefetching_ops.copy_to_device("/cpu:1")).prefetch(1) with ops.device("/cpu:1"): - iterator = device_dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -184,12 +190,13 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual([], next_element["a"].shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - self.assertEqual({"a": i}, sess.run(next_element)) + self.assertEqual({"a": i}, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testCopySparseTensorsToDevice(self): def make_tensor(i): @@ -202,7 +209,7 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/cpu:1")) with ops.device("/cpu:1"): - iterator = device_dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -215,15 +222,16 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual(dtypes.int64, next_element.dtype) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - actual = sess.run(next_element) + actual = self.evaluate(next_element) self.assertAllEqual([i], actual.values) self.assertAllEqual([[0, 0]], actual.indices) self.assertAllEqual([2, 2], actual.dense_shape) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testCopySparseTensorsToDeviceWithPrefetch(self): def make_tensor(i): @@ -236,7 +244,7 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/cpu:1")).prefetch(1) with ops.device("/cpu:1"): - iterator = device_dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -249,14 +257,14 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual(dtypes.int64, next_element.dtype) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - actual = sess.run(next_element) + actual = self.evaluate(next_element) self.assertAllEqual([i], actual.values) self.assertAllEqual([[0, 0]], actual.indices) self.assertAllEqual([2, 2], actual.dense_shape) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDeviceGpu(self): if not test_util.is_gpu_available(): @@ -267,15 +275,16 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/gpu:0")) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDeviceGpuWithPrefetch(self): if not test_util.is_gpu_available(): @@ -286,15 +295,16 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/gpu:0")).prefetch(1) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDeviceGpuWithMap(self): if not test_util.is_gpu_available(): @@ -319,18 +329,19 @@ class CopyToDeviceTest(test_base.DatasetTestBase): device_dataset = device_dataset.with_options(options) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) for i in range(10): - x, y, z = sess.run(next_element) + x, y, z = self.evaluate(next_element) self.assertEqual(i**2, x) self.assertEqual(float(i**2), y) self.assertEqual(util_compat.as_bytes(str(i)), z) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDeviceGpuInt32(self): if not test_util.is_gpu_available(): @@ -341,14 +352,15 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/gpu:0")) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) - self.assertAllEqual([0, 1, 2, 3], sess.run(next_element)) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) + self.assertAllEqual([0, 1, 2, 3], self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDeviceGpuInt32AndPrefetch(self): if not test_util.is_gpu_available(): @@ -359,14 +371,15 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/gpu:0")).prefetch(1) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) - self.assertAllEqual([0, 1, 2, 3], sess.run(next_element)) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) + self.assertAllEqual([0, 1, 2, 3], self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDeviceGpuStrings(self): if not test_util.is_gpu_available(): @@ -377,14 +390,15 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/gpu:0")) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) - self.assertAllEqual([b"a", b"b", b"c"], sess.run(next_element)) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) + self.assertAllEqual([b"a", b"b", b"c"], self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDeviceGpuStringsAndPrefetch(self): if not test_util.is_gpu_available(): @@ -395,14 +409,15 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/gpu:0")) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) - self.assertAllEqual([b"a", b"b", b"c"], sess.run(next_element)) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) + self.assertAllEqual([b"a", b"b", b"c"], self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDevicePingPongCPUGPU(self): if not test_util.is_gpu_available(): @@ -416,23 +431,25 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/cpu:0", source_device="/gpu:0")) with ops.device("/cpu:0"): - iterator = back_to_cpu_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(back_to_cpu_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testCopyToDeviceWithReInit(self): host_dataset = dataset_ops.Dataset.range(10) device_dataset = host_dataset.apply( prefetching_ops.copy_to_device("/cpu:1")) with ops.device("/cpu:1"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -446,23 +463,24 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual([], next_element.shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: - sess.run(iterator.initializer) + with self.test_session(config=worker_config): + self.evaluate(iterator.initializer) for i in range(5): - self.assertEqual(i, sess.run(next_element)) - sess.run(iterator.initializer) + self.assertEqual(i, self.evaluate(next_element)) + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testCopyToDeviceWithReInitAndPrefetch(self): host_dataset = dataset_ops.Dataset.range(10) device_dataset = host_dataset.apply( prefetching_ops.copy_to_device("/cpu:1")).prefetch(1) with ops.device("/cpu:1"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) @@ -476,15 +494,15 @@ class CopyToDeviceTest(test_base.DatasetTestBase): self.assertEqual([], next_element.shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: - sess.run(iterator.initializer) + with self.test_session(config=worker_config): + self.evaluate(iterator.initializer) for i in range(5): - self.assertEqual(i, sess.run(next_element)) - sess.run(iterator.initializer) + self.assertEqual(i, self.evaluate(next_element)) + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDeviceGpuWithReInit(self): if not test_util.is_gpu_available(): @@ -495,18 +513,19 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/gpu:0")) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) for i in range(5): - self.assertEqual(i, sess.run(next_element)) - sess.run(iterator.initializer) + self.assertEqual(i, self.evaluate(next_element)) + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testCopyToDeviceGpuWithReInitAndPrefetch(self): if not test_util.is_gpu_available(): @@ -517,18 +536,19 @@ class CopyToDeviceTest(test_base.DatasetTestBase): prefetching_ops.copy_to_device("/gpu:0")).prefetch(1) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) for i in range(5): - self.assertEqual(i, sess.run(next_element)) - sess.run(iterator.initializer) + self.assertEqual(i, self.evaluate(next_element)) + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testIteratorGetNextAsOptionalOnGPU(self): if not test_util.is_gpu_available(): @@ -538,33 +558,35 @@ class CopyToDeviceTest(test_base.DatasetTestBase): device_dataset = host_dataset.apply( prefetching_ops.copy_to_device("/gpu:0")) with ops.device("/gpu:0"): - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_elem = iterator_ops.get_next_as_optional(iterator) elem_has_value_t = next_elem.has_value() elem_value_t = next_elem.get_value() - with self.cached_session() as sess: + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): # Before initializing the iterator, evaluating the optional fails with # a FailedPreconditionError. with self.assertRaises(errors.FailedPreconditionError): - sess.run(elem_has_value_t) + self.evaluate(elem_has_value_t) with self.assertRaises(errors.FailedPreconditionError): - sess.run(elem_value_t) + self.evaluate(elem_value_t) # For each element of the dataset, assert that the optional evaluates to # the expected value. - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for i in range(3): - elem_has_value, elem_value = sess.run([elem_has_value_t, elem_value_t]) + elem_has_value, elem_value = self.evaluate( + [elem_has_value_t, elem_value_t]) self.assertTrue(elem_has_value) self.assertEqual(i, elem_value) # After exhausting the iterator, `next_elem.has_value()` will evaluate to # false, and attempting to get the value will fail. for _ in range(2): - self.assertFalse(sess.run(elem_has_value_t)) + self.assertFalse(self.evaluate(elem_has_value_t)) with self.assertRaises(errors.InvalidArgumentError): - sess.run(elem_value_t) + self.evaluate(elem_value_t) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/counter_test.py b/tensorflow/python/data/experimental/kernel_tests/counter_test.py index 4e114ac479..49e1f2272b 100644 --- a/tensorflow/python/data/experimental/kernel_tests/counter_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/counter_test.py @@ -19,32 +19,35 @@ from __future__ import print_function from tensorflow.python.data.experimental.ops import counter from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.platform import test class CounterTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testCounter(self): """Test dataset construction using `count`.""" - iterator = (counter.Counter(start=3, step=4) - .make_one_shot_iterator()) + iterator = dataset_ops.make_one_shot_iterator( + counter.Counter(start=3, step=4)) get_next = iterator.get_next() self.assertEqual([], get_next.shape.as_list()) self.assertEqual(dtypes.int64, get_next.dtype) - negative_iterator = (counter.Counter(start=0, step=-1) - .make_one_shot_iterator()) + negative_iterator = dataset_ops.make_one_shot_iterator( + counter.Counter(start=0, step=-1)) negative_get_next = negative_iterator.get_next() with self.cached_session() as sess: - self.assertEqual(3, sess.run(get_next)) - self.assertEqual(3 + 4, sess.run(get_next)) - self.assertEqual(3 + 2 * 4, sess.run(get_next)) + self.assertEqual(3, self.evaluate(get_next)) + self.assertEqual(3 + 4, self.evaluate(get_next)) + self.assertEqual(3 + 2 * 4, self.evaluate(get_next)) - self.assertEqual(0, sess.run(negative_get_next)) - self.assertEqual(-1, sess.run(negative_get_next)) - self.assertEqual(-2, sess.run(negative_get_next)) + self.assertEqual(0, self.evaluate(negative_get_next)) + self.assertEqual(-1, self.evaluate(negative_get_next)) + self.assertEqual(-2, self.evaluate(negative_get_next)) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/csv_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/csv_dataset_test.py index fb75be1fbc..b2f1b43ecf 100644 --- a/tensorflow/python/data/experimental/kernel_tests/csv_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/csv_dataset_test.py @@ -20,14 +20,8 @@ from __future__ import print_function import gzip import os -import string -import tempfile -import time import zlib -import numpy as np - -from tensorflow.python.client import session from tensorflow.python.data.experimental.ops import error_ops from tensorflow.python.data.experimental.ops import readers from tensorflow.python.data.kernel_tests import test_base @@ -38,8 +32,6 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import test_util from tensorflow.python.ops import parsing_ops -from tensorflow.python.platform import gfile -from tensorflow.python.platform import googletest from tensorflow.python.platform import test @@ -537,96 +529,5 @@ class CsvDatasetTest(test_base.DatasetTestBase): record_defaults=record_defaults) -class CsvDatasetBenchmark(test.Benchmark): - """Benchmarks for the various ways of creating a dataset from CSV files. - """ - FLOAT_VAL = '1.23456E12' - STR_VAL = string.ascii_letters * 10 - - def _setUp(self, str_val): - # Since this isn't test.TestCase, have to manually create a test dir - gfile.MakeDirs(googletest.GetTempDir()) - self._temp_dir = tempfile.mkdtemp(dir=googletest.GetTempDir()) - - self._num_cols = [4, 64, 256] - self._num_per_iter = 5000 - self._filenames = [] - for n in self._num_cols: - fn = os.path.join(self._temp_dir, 'file%d.csv' % n) - with open(fn, 'wb') as f: - # Just write 100 rows and use `repeat`... Assumes the cost - # of creating an iterator is not significant - row = ','.join([str_val for _ in range(n)]) - f.write('\n'.join([row for _ in range(100)])) - self._filenames.append(fn) - - def _tearDown(self): - gfile.DeleteRecursively(self._temp_dir) - - def _runBenchmark(self, dataset, num_cols, prefix): - dataset = dataset.skip(self._num_per_iter - 1) - deltas = [] - for _ in range(10): - next_element = dataset.make_one_shot_iterator().get_next() - with session.Session() as sess: - start = time.time() - # NOTE: This depends on the underlying implementation of skip, to have - # the net effect of calling `GetNext` num_per_iter times on the - # input dataset. We do it this way (instead of a python for loop, or - # batching N inputs in one iter) so that the overhead from session.run - # or batch doesn't dominate. If we eventually optimize skip, this has - # to change. - sess.run(next_element) - end = time.time() - deltas.append(end - start) - # Median wall time per CSV record read and decoded - median_wall_time = np.median(deltas) / self._num_per_iter - print('%s num_cols: %d Median wall time: %f' % (prefix, num_cols, - median_wall_time)) - self.report_benchmark( - iters=self._num_per_iter, - wall_time=median_wall_time, - name='%s_with_cols_%d' % (prefix, num_cols)) - - def benchmarkMapWithFloats(self): - self._setUp(self.FLOAT_VAL) - for i in range(len(self._filenames)): - num_cols = self._num_cols[i] - kwargs = {'record_defaults': [[0.0]] * num_cols} - dataset = core_readers.TextLineDataset(self._filenames[i]).repeat() - dataset = dataset.map(lambda l: parsing_ops.decode_csv(l, **kwargs)) # pylint: disable=cell-var-from-loop - self._runBenchmark(dataset, num_cols, 'csv_float_map_decode_csv') - self._tearDown() - - def benchmarkMapWithStrings(self): - self._setUp(self.STR_VAL) - for i in range(len(self._filenames)): - num_cols = self._num_cols[i] - kwargs = {'record_defaults': [['']] * num_cols} - dataset = core_readers.TextLineDataset(self._filenames[i]).repeat() - dataset = dataset.map(lambda l: parsing_ops.decode_csv(l, **kwargs)) # pylint: disable=cell-var-from-loop - self._runBenchmark(dataset, num_cols, 'csv_strings_map_decode_csv') - self._tearDown() - - def benchmarkCsvDatasetWithFloats(self): - self._setUp(self.FLOAT_VAL) - for i in range(len(self._filenames)): - num_cols = self._num_cols[i] - kwargs = {'record_defaults': [[0.0]] * num_cols} - dataset = core_readers.TextLineDataset(self._filenames[i]).repeat() - dataset = readers.CsvDataset(self._filenames[i], **kwargs).repeat() # pylint: disable=cell-var-from-loop - self._runBenchmark(dataset, num_cols, 'csv_float_fused_dataset') - self._tearDown() - - def benchmarkCsvDatasetWithStrings(self): - self._setUp(self.STR_VAL) - for i in range(len(self._filenames)): - num_cols = self._num_cols[i] - kwargs = {'record_defaults': [['']] * num_cols} - dataset = core_readers.TextLineDataset(self._filenames[i]).repeat() - dataset = readers.CsvDataset(self._filenames[i], **kwargs).repeat() # pylint: disable=cell-var-from-loop - self._runBenchmark(dataset, num_cols, 'csv_strings_fused_dataset') - self._tearDown() - if __name__ == '__main__': test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/dense_to_sparse_batch_test.py b/tensorflow/python/data/experimental/kernel_tests/dense_to_sparse_batch_test.py index 73be6cbcca..22e057a284 100644 --- a/tensorflow/python/data/experimental/kernel_tests/dense_to_sparse_batch_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/dense_to_sparse_batch_test.py @@ -24,27 +24,28 @@ from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test class DenseToSparseBatchTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testDenseToSparseBatchDataset(self): components = np.random.randint(12, size=(100,)).astype(np.int32) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(components) .map(lambda x: array_ops.fill([x], x)).apply( - batching.dense_to_sparse_batch(4, [12])) - .make_initializable_iterator()) + batching.dense_to_sparse_batch(4, [12]))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) for start in range(0, len(components), 4): - results = sess.run(get_next) + results = self.evaluate(get_next) self.assertAllEqual([[i, j] for i, c in enumerate(components[start:start + 4]) for j in range(c)], results.indices) @@ -56,23 +57,23 @@ class DenseToSparseBatchTest(test_base.DatasetTestBase): results.dense_shape) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) + @test_util.run_deprecated_v1 def testDenseToSparseBatchDatasetWithUnknownShape(self): components = np.random.randint(5, size=(40,)).astype(np.int32) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(components) .map(lambda x: array_ops.fill([x, x], x)).apply( - batching.dense_to_sparse_batch( - 4, [5, None])).make_initializable_iterator()) + batching.dense_to_sparse_batch(4, [5, None]))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) for start in range(0, len(components), 4): - results = sess.run(get_next) + results = self.evaluate(get_next) self.assertAllEqual([[i, j, z] for i, c in enumerate(components[start:start + 4]) for j in range(c) @@ -89,20 +90,22 @@ class DenseToSparseBatchTest(test_base.DatasetTestBase): ], results.dense_shape) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) + @test_util.run_deprecated_v1 def testDenseToSparseBatchDatasetWithInvalidShape(self): input_tensor = array_ops.constant([[1]]) with self.assertRaisesRegexp(ValueError, "Dimension -2 must be >= 0"): - dataset_ops.Dataset.from_tensors(input_tensor).apply( - batching.dense_to_sparse_batch(4, [-2])).make_initializable_iterator() + dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_tensors(input_tensor).apply( + batching.dense_to_sparse_batch(4, [-2]))) + @test_util.run_deprecated_v1 def testDenseToSparseBatchDatasetShapeErrors(self): input_tensor = array_ops.placeholder(dtypes.int32) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensors(input_tensor).apply( - batching.dense_to_sparse_batch(4, [12])) - .make_initializable_iterator()) + batching.dense_to_sparse_batch(4, [12]))) init_op = iterator.initializer get_next = iterator.get_next() @@ -111,13 +114,13 @@ class DenseToSparseBatchTest(test_base.DatasetTestBase): sess.run(init_op, feed_dict={input_tensor: [[1]]}) with self.assertRaisesRegexp(errors.InvalidArgumentError, "incompatible with the row shape"): - sess.run(get_next) + self.evaluate(get_next) # Initialize with an input tensor that is larger than `row_shape`. sess.run(init_op, feed_dict={input_tensor: range(13)}) with self.assertRaisesRegexp(errors.DataLossError, "larger than the row shape"): - sess.run(get_next) + self.evaluate(get_next) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/directed_interleave_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/directed_interleave_dataset_test.py index 796a692c56..2144342066 100644 --- a/tensorflow/python/data/experimental/kernel_tests/directed_interleave_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/directed_interleave_dataset_test.py @@ -24,11 +24,13 @@ from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util from tensorflow.python.platform import test class DirectedInterleaveDatasetTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testBasic(self): selector_dataset = dataset_ops.Dataset.range(10).repeat(100) input_datasets = [ @@ -36,16 +38,16 @@ class DirectedInterleaveDatasetTest(test_base.DatasetTestBase): ] dataset = interleave_ops._DirectedInterleaveDataset(selector_dataset, input_datasets) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() with self.cached_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for _ in range(100): for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def _normalize(self, vec): return vec / vec.sum() @@ -65,18 +67,19 @@ class DirectedInterleaveDatasetTest(test_base.DatasetTestBase): for i in range(num_datasets) ], weights) dataset = dataset.take(num_samples) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) next_element = iterator.get_next() with self.cached_session() as sess: freqs = np.zeros([num_datasets]) for _ in range(num_samples): - freqs[sess.run(next_element)] += 1 + freqs[self.evaluate(next_element)] += 1 with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) return freqs + @test_util.run_deprecated_v1 def testSampleFromDatasets(self): random_seed.set_random_seed(1619) num_samples = 5000 @@ -96,20 +99,21 @@ class DirectedInterleaveDatasetTest(test_base.DatasetTestBase): freqs = self._testSampleFromDatasetsHelper(probs_ds, classes, num_samples) self.assertLess(self._chi2(probs, freqs / num_samples), 1e-2) + @test_util.run_deprecated_v1 def testSelectFromDatasets(self): words = [b"foo", b"bar", b"baz"] datasets = [dataset_ops.Dataset.from_tensors(w).repeat() for w in words] choice_array = np.random.randint(3, size=(15,), dtype=np.int64) choice_dataset = dataset_ops.Dataset.from_tensor_slices(choice_array) dataset = interleave_ops.choose_from_datasets(datasets, choice_dataset) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) next_element = iterator.get_next() with self.cached_session() as sess: for i in choice_array: - self.assertEqual(words[i], sess.run(next_element)) + self.assertEqual(words[i], self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testErrors(self): with self.assertRaisesRegexp(ValueError, diff --git a/tensorflow/python/data/experimental/kernel_tests/enumerate_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/enumerate_dataset_test.py index e54235d9f8..25742098f1 100644 --- a/tensorflow/python/data/experimental/kernel_tests/enumerate_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/enumerate_dataset_test.py @@ -24,17 +24,20 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.platform import test class EnumerateDatasetTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testEnumerateDataset(self): components = (["a", "b"], [1, 2], [37.0, 38]) start = constant_op.constant(20, dtype=dtypes.int64) - iterator = (dataset_ops.Dataset.from_tensor_slices(components).apply( - enumerate_ops.enumerate_dataset(start)).make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_tensor_slices(components).apply( + enumerate_ops.enumerate_dataset(start))) init_op = iterator.initializer get_next = iterator.get_next() @@ -44,12 +47,12 @@ class EnumerateDatasetTest(test_base.DatasetTestBase): [t.shape for t in get_next[1]]) with self.cached_session() as sess: - sess.run(init_op) - self.assertEqual((20, (b"a", 1, 37.0)), sess.run(get_next)) - self.assertEqual((21, (b"b", 2, 38.0)), sess.run(get_next)) + self.evaluate(init_op) + self.assertEqual((20, (b"a", 1, 37.0)), self.evaluate(get_next)) + self.assertEqual((21, (b"b", 2, 38.0)), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/filter_dataset_op_test.py b/tensorflow/python/data/experimental/kernel_tests/filter_dataset_op_test.py index c6ee88c676..357b5f1b49 100644 --- a/tensorflow/python/data/experimental/kernel_tests/filter_dataset_op_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/filter_dataset_op_test.py @@ -47,17 +47,17 @@ class FilterBenchmark(test.Benchmark): if optimize_dataset: dataset = dataset.apply(optimization.optimize(["filter_fusion"])) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) next_element = iterator.get_next() with session.Session() as sess: for _ in range(10): - sess.run(next_element.op) + self.evaluate(next_element.op) deltas = [] for _ in range(100): start = time.time() for _ in range(100): - sess.run(next_element.op) + self.evaluate(next_element.op) end = time.time() deltas.append(end - start) diff --git a/tensorflow/python/data/experimental/kernel_tests/function_buffering_resource_test.py b/tensorflow/python/data/experimental/kernel_tests/function_buffering_resource_test.py deleted file mode 100644 index d38452e265..0000000000 --- a/tensorflow/python/data/experimental/kernel_tests/function_buffering_resource_test.py +++ /dev/null @@ -1,248 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the private `FunctionBufferingResource` used in prefetching.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import threading - -from tensorflow.core.protobuf import config_pb2 -from tensorflow.python.data.experimental.ops import prefetching_ops -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.data.ops import iterator_ops -from tensorflow.python.eager import function -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import ops -from tensorflow.python.framework import tensor_spec -from tensorflow.python.framework import test_util -from tensorflow.python.ops import resource_variable_ops -from tensorflow.python.platform import test - - -class FunctionBufferingResourceTest(test_base.DatasetTestBase): - - def setUp(self): - self._event = threading.Event() - - def _create_ds_and_iterator(self, device0, initializable=False): - - def gen(): - for i in range(1, 10): - yield [float(i)] - if i == 6: - self._event.set() - - with ops.device(device0): - ds = dataset_ops.Dataset.from_generator(gen, (dtypes.float32)) - if initializable: - ds_iterator = ds.make_initializable_iterator() - else: - ds_iterator = ds.make_one_shot_iterator() - return (ds, ds_iterator) - - def _create_ops(self, ds, ds_iterator, buffer_name, device0, device1): - ds_iterator_handle = ds_iterator.string_handle() - - @function.defun(input_signature=[tensor_spec.TensorSpec([], dtypes.string)]) - def _remote_fn(h): - remote_iterator = iterator_ops.Iterator.from_string_handle( - h, ds.output_types, ds.output_shapes) - return remote_iterator.get_next() - - target = constant_op.constant(device0) - with ops.device(device1): - buffer_resource_handle = prefetching_ops.function_buffering_resource( - f=_remote_fn.get_concrete_function(), - output_types=[dtypes.float32], - target_device=target, - string_arg=ds_iterator_handle, - buffer_size=3, - shared_name=buffer_name) - - with ops.device(device1): - prefetch_op = prefetching_ops.function_buffering_resource_get_next( - function_buffer_resource=buffer_resource_handle, - output_types=[dtypes.float32]) - reset_op = prefetching_ops.function_buffering_resource_reset( - function_buffer_resource=buffer_resource_handle) - destroy_op = resource_variable_ops.destroy_resource_op( - buffer_resource_handle, ignore_lookup_error=True) - - return (prefetch_op, reset_op, destroy_op) - - def _prefetch_fn_helper_one_shot(self, buffer_name, device0, device1): - worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - - ds, ds_iterator = self._create_ds_and_iterator(device0, initializable=False) - prefetch_op, _, destroy_op = self._create_ops(ds, ds_iterator, buffer_name, - device0, device1) - - with self.test_session(config=worker_config) as sess: - elem = sess.run(prefetch_op) - self.assertEqual(elem, [1.0]) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [2.0]) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [3.0]) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [4.0]) - self._event.wait() - elem = sess.run(prefetch_op) - self.assertEqual(elem, [5.0]) - sess.run(destroy_op) - - def testSameDeviceCPU(self): - self._prefetch_fn_helper_one_shot("same_device_cpu", - "/job:localhost/replica:0/task:0/cpu:0", - "/job:localhost/replica:0/task:0/cpu:0") - - def testDifferentDeviceCPU(self): - self._prefetch_fn_helper_one_shot("diff_device_cpu", - "/job:localhost/replica:0/task:0/cpu:0", - "/job:localhost/replica:0/task:0/cpu:1") - - def testDifferentDeviceCPUGPU(self): - if not test_util.is_gpu_available(): - self.skipTest("No GPU available") - - self._prefetch_fn_helper_one_shot("cpu_gpu", - "/job:localhost/replica:0/task:0/cpu:0", - "/job:localhost/replica:0/task:0/gpu:0") - - def testReinitialization(self): - worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - - device0 = "/job:localhost/replica:0/task:0/cpu:0" - device1 = "/job:localhost/replica:0/task:0/cpu:1" - ds, ds_iterator = self._create_ds_and_iterator(device0, initializable=True) - prefetch_op, reset_op, destroy_op = self._create_ops( - ds, ds_iterator, "reinit", device0, device1) - - with self.test_session(config=worker_config) as sess: - sess.run(ds_iterator.initializer) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [1.0]) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [2.0]) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [3.0]) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [4.0]) - self._event.wait() - elem = sess.run(prefetch_op) - self.assertEqual(elem, [5.0]) - # Lets reset the function buffering resource and reinitialize the - # iterator. Should be able to go through this again. - self._event.clear() - sess.run(reset_op) - sess.run(ds_iterator.initializer) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [1.0]) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [2.0]) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [3.0]) - elem = sess.run(prefetch_op) - self.assertEqual(elem, [4.0]) - self._event.wait() - elem = sess.run(prefetch_op) - self.assertEqual(elem, [5.0]) - sess.run(destroy_op) - - def testReinitializationOutOfRange(self): - worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - - device0 = "/job:localhost/replica:0/task:0/cpu:0" - device1 = "/job:localhost/replica:0/task:0/cpu:1" - ds, ds_iterator = self._create_ds_and_iterator(device0, initializable=True) - prefetch_op, reset_op, destroy_op = self._create_ops( - ds, ds_iterator, "reinit", device0, device1) - - with self.test_session(config=worker_config) as sess: - sess.run(ds_iterator.initializer) - for i in range(1, 10): - elem = sess.run(prefetch_op) - self.assertEqual(elem, [float(i)]) - # Try fetching after its over twice to test out end of sequence. - with self.assertRaises(errors.OutOfRangeError): - sess.run(prefetch_op) - with self.assertRaises(errors.OutOfRangeError): - sess.run(prefetch_op) - - # Now reset everything and try it out again. - self._event.clear() - sess.run(reset_op) - sess.run(ds_iterator.initializer) - for i in range(1, 10): - elem = sess.run(prefetch_op) - self.assertEqual(elem, [float(i)]) - # Try fetching after its over twice to test out end of sequence. - with self.assertRaises(errors.OutOfRangeError): - sess.run(prefetch_op) - with self.assertRaises(errors.OutOfRangeError): - sess.run(prefetch_op) - - sess.run(destroy_op) - - def testStringsGPU(self): - if not test_util.is_gpu_available(): - self.skipTest("No GPU available") - - device0 = "/job:localhost/replica:0/task:0/cpu:0" - device1 = "/job:localhost/replica:0/task:0/gpu:0" - - ds = dataset_ops.Dataset.from_tensor_slices(["a", "b", "c"]) - ds_iterator = ds.make_one_shot_iterator() - ds_iterator_handle = ds_iterator.string_handle() - - @function.defun(input_signature=[tensor_spec.TensorSpec([], dtypes.string)]) - def _remote_fn(h): - remote_iterator = iterator_ops.Iterator.from_string_handle( - h, ds.output_types, ds.output_shapes) - return remote_iterator.get_next() - - target = constant_op.constant(device0) - with ops.device(device1): - buffer_resource_handle = prefetching_ops.function_buffering_resource( - f=_remote_fn.get_concrete_function(), - output_types=[dtypes.string], - target_device=target, - string_arg=ds_iterator_handle, - buffer_size=3, - shared_name="strings") - - with ops.device(device1): - prefetch_op = prefetching_ops.function_buffering_resource_get_next( - function_buffer_resource=buffer_resource_handle, - output_types=[dtypes.string]) - destroy_op = resource_variable_ops.destroy_resource_op( - buffer_resource_handle, ignore_lookup_error=True) - - with self.cached_session() as sess: - self.assertEqual([b"a"], sess.run(prefetch_op)) - self.assertEqual([b"b"], sess.run(prefetch_op)) - self.assertEqual([b"c"], sess.run(prefetch_op)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(prefetch_op) - - sess.run(destroy_op) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/get_single_element_test.py b/tensorflow/python/data/experimental/kernel_tests/get_single_element_test.py index 8c07afbac5..ef576563a1 100644 --- a/tensorflow/python/data/experimental/kernel_tests/get_single_element_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/get_single_element_test.py @@ -25,6 +25,7 @@ from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test @@ -39,6 +40,7 @@ class GetSingleElementTest(test_base.DatasetTestBase, parameterized.TestCase): ("MoreThanOne", 0, 2, errors.InvalidArgumentError, "Dataset had more than one element."), ) + @test_util.run_deprecated_v1 def testGetSingleElement(self, skip, take, error=None, error_msg=None): skip_t = array_ops.placeholder(dtypes.int64, shape=[]) take_t = array_ops.placeholder(dtypes.int64, shape=[]) @@ -67,6 +69,17 @@ class GetSingleElementTest(test_base.DatasetTestBase, parameterized.TestCase): with self.assertRaisesRegexp(error, error_msg): sess.run(element, feed_dict={skip_t: skip, take_t: take}) + def testWindow(self): + """Test that `get_single_element()` can consume a nested dataset.""" + def flat_map_func(ds): + batched = ds.batch(2) + element = get_single_element.get_single_element(batched) + return dataset_ops.Dataset.from_tensors(element) + + dataset = dataset_ops.Dataset.range(10).window(2).flat_map(flat_map_func) + self.assertDatasetProduces( + dataset, [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/group_by_reducer_test.py b/tensorflow/python/data/experimental/kernel_tests/group_by_reducer_test.py index 9030328593..8507df3d3a 100644 --- a/tensorflow/python/data/experimental/kernel_tests/group_by_reducer_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/group_by_reducer_test.py @@ -27,6 +27,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -36,14 +37,15 @@ class GroupByReducerTest(test_base.DatasetTestBase): def checkResults(self, dataset, shapes, values): self.assertEqual(shapes, dataset.output_shapes) - get_next = dataset.make_one_shot_iterator().get_next() + get_next = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: for expected in values: - got = sess.run(get_next) + got = self.evaluate(get_next) self.assertEqual(got, expected) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) + @test_util.run_deprecated_v1 def testSum(self): reducer = grouping.Reducer( init_func=lambda _: np.int64(0), @@ -55,6 +57,7 @@ class GroupByReducerTest(test_base.DatasetTestBase): self.checkResults( dataset, shapes=tensor_shape.scalar(), values=[(i - 1) * i, i * i]) + @test_util.run_deprecated_v1 def testAverage(self): def reduce_fn(x, y): @@ -72,6 +75,7 @@ class GroupByReducerTest(test_base.DatasetTestBase): self.checkResults( dataset, shapes=tensor_shape.scalar(), values=[i - 1, i]) + @test_util.run_deprecated_v1 def testConcat(self): components = np.array(list("abcdefghijklmnopqrst")).view(np.chararray) reducer = grouping.Reducer( @@ -88,6 +92,7 @@ class GroupByReducerTest(test_base.DatasetTestBase): shapes=tensor_shape.scalar(), values=[b"acegikmoqs" [:i], b"bdfhjlnprt" [:i]]) + @test_util.run_deprecated_v1 def testSparseSum(self): def _sparse(i): return sparse_tensor.SparseTensorValue( @@ -105,6 +110,7 @@ class GroupByReducerTest(test_base.DatasetTestBase): self.checkResults( dataset, shapes=tensor_shape.scalar(), values=[(i - 1) * i, i * i]) + @test_util.run_deprecated_v1 def testChangingStateShape(self): def reduce_fn(x, _): @@ -124,14 +130,14 @@ class GroupByReducerTest(test_base.DatasetTestBase): grouping.group_by_reducer(lambda x: x, reducer)) self.assertEqual([None], dataset.output_shapes[0].as_list()) self.assertIs(None, dataset.output_shapes[1].ndims) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() with self.cached_session() as sess: - x, y = sess.run(get_next) + x, y = self.evaluate(get_next) self.assertAllEqual([0] * (2**i), x) self.assertAllEqual(np.array(1, ndmin=i), y) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) def testTypeMismatch(self): reducer = grouping.Reducer( @@ -188,9 +194,9 @@ class GroupByReducerTest(test_base.DatasetTestBase): dataset = dataset_ops.Dataset.zip( (dataset_ops.Dataset.range(10), dataset_ops.Dataset.range(10))).apply( grouping.group_by_reducer(lambda x, y: np.int64(0), reducer)) - get_next = dataset.make_one_shot_iterator().get_next() + get_next = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: - x, y = sess.run(get_next) + x, y = self.evaluate(get_next) self.assertAllEqual(x, np.asarray([x for x in range(10)])) self.assertEqual(y, 45) diff --git a/tensorflow/python/data/experimental/kernel_tests/group_by_window_test.py b/tensorflow/python/data/experimental/kernel_tests/group_by_window_test.py index 557d56e8b9..cbb79e55f5 100644 --- a/tensorflow/python/data/experimental/kernel_tests/group_by_window_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/group_by_window_test.py @@ -27,6 +27,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import string_ops @@ -49,6 +50,7 @@ class GroupByWindowTest(test_base.DatasetTestBase): 32, (tensor_shape.TensorShape([]), tensor_shape.TensorShape( [None]), tensor_shape.TensorShape([3]))))) + @test_util.run_deprecated_v1 def testSingleBucket(self): def _map_fn(v): @@ -63,14 +65,14 @@ class GroupByWindowTest(test_base.DatasetTestBase): lambda x, y, z: 0, lambda k, bucket: self._dynamicPad(k, bucket, 32), 32)) - iterator = bucketed_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(bucketed_dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) - which_bucket, bucketed_values = sess.run(get_next) + which_bucket, bucketed_values = self.evaluate(get_next) self.assertEqual(0, which_bucket) @@ -84,6 +86,7 @@ class GroupByWindowTest(test_base.DatasetTestBase): self.assertAllEqual(expected_unk_int64, bucketed_values[1]) self.assertAllEqual(expected_vec3_str, bucketed_values[2]) + @test_util.run_deprecated_v1 def testEvenOddBuckets(self): def _map_fn(v): @@ -98,16 +101,16 @@ class GroupByWindowTest(test_base.DatasetTestBase): lambda x, y, z: math_ops.cast(x % 2, dtypes.int64), lambda k, bucket: self._dynamicPad(k, bucket, 32), 32)) - iterator = bucketed_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(bucketed_dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) # Get two minibatches (one containing even values, one containing odds) - which_bucket_even, bucketed_values_even = sess.run(get_next) - which_bucket_odd, bucketed_values_odd = sess.run(get_next) + which_bucket_even, bucketed_values_even = self.evaluate(get_next) + which_bucket_odd, bucketed_values_odd = self.evaluate(get_next) # Count number of bucket_tensors. self.assertEqual(3, len(bucketed_values_even)) @@ -141,6 +144,7 @@ class GroupByWindowTest(test_base.DatasetTestBase): self.assertAllEqual(expected_unk_int64, bucketed_values_odd[1]) self.assertAllEqual(expected_vec3_str, bucketed_values_odd[2]) + @test_util.run_deprecated_v1 def testEvenOddBucketsFilterOutAllOdd(self): def _map_fn(v): @@ -169,16 +173,16 @@ class GroupByWindowTest(test_base.DatasetTestBase): lambda d: math_ops.cast(d["x"] % 2, dtypes.int64), lambda k, bucket: _dynamic_pad_fn(k, bucket, 32), 32)) - iterator = bucketed_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(bucketed_dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) # Get two minibatches ([0, 2, ...] and [64, 66, ...]) - which_bucket0, bucketed_values_even0 = sess.run(get_next) - which_bucket1, bucketed_values_even1 = sess.run(get_next) + which_bucket0, bucketed_values_even0 = self.evaluate(get_next) + which_bucket1, bucketed_values_even1 = self.evaluate(get_next) # Ensure that bucket 1 was completely filtered out self.assertAllEqual(0, which_bucket0) @@ -188,6 +192,7 @@ class GroupByWindowTest(test_base.DatasetTestBase): self.assertAllEqual( np.arange(64, 128, 2, dtype=np.int64), bucketed_values_even1["x"]) + @test_util.run_deprecated_v1 def testDynamicWindowSize(self): components = np.arange(100).astype(np.int64) @@ -202,16 +207,16 @@ class GroupByWindowTest(test_base.DatasetTestBase): dataset = dataset_ops.Dataset.from_tensor_slices(components).apply( grouping.group_by_window(lambda x: x % 2, lambda _, xs: xs.batch(20), None, window_size_func)) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) with self.assertRaises(errors.OutOfRangeError): batches = 0 while True: - result = sess.run(get_next) + result = self.evaluate(get_next) is_even = all(x % 2 == 0 for x in result) is_odd = all(x % 2 == 1 for x in result) self.assertTrue(is_even or is_odd) @@ -221,22 +226,23 @@ class GroupByWindowTest(test_base.DatasetTestBase): self.assertEqual(batches, 15) + @test_util.run_deprecated_v1 def testSimple(self): components = np.random.randint(100, size=(200,)).astype(np.int64) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(components).map(lambda x: x * x) .apply( grouping.group_by_window(lambda x: x % 2, lambda _, xs: xs.batch(4), - 4)).make_initializable_iterator()) + 4))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) counts = [] with self.assertRaises(errors.OutOfRangeError): while True: - result = sess.run(get_next) + result = self.evaluate(get_next) self.assertTrue( all(x % 2 == 0 for x in result) or all(x % 2 == 1) @@ -248,61 +254,64 @@ class GroupByWindowTest(test_base.DatasetTestBase): self.assertGreaterEqual(num_full_batches, 24) self.assertTrue(all(c == 4 for c in counts[:num_full_batches])) + @test_util.run_deprecated_v1 def testImmediateOutput(self): components = np.array( [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 0, 0, 2, 2, 0, 0], dtype=np.int64) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(components).repeat(-1).apply( grouping.group_by_window(lambda x: x % 3, lambda _, xs: xs.batch(4), - 4)).make_initializable_iterator()) + 4))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) # The input is infinite, so this test demonstrates that: # 1. We produce output without having to consume the entire input, # 2. Different buckets can produce output at different rates, and # 3. For deterministic input, the output is deterministic. for _ in range(3): - self.assertAllEqual([0, 0, 0, 0], sess.run(get_next)) - self.assertAllEqual([1, 1, 1, 1], sess.run(get_next)) - self.assertAllEqual([2, 2, 2, 2], sess.run(get_next)) - self.assertAllEqual([0, 0, 0, 0], sess.run(get_next)) + self.assertAllEqual([0, 0, 0, 0], self.evaluate(get_next)) + self.assertAllEqual([1, 1, 1, 1], self.evaluate(get_next)) + self.assertAllEqual([2, 2, 2, 2], self.evaluate(get_next)) + self.assertAllEqual([0, 0, 0, 0], self.evaluate(get_next)) + @test_util.run_deprecated_v1 def testSmallGroups(self): components = np.array([0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0], dtype=np.int64) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(components).apply( grouping.group_by_window(lambda x: x % 2, lambda _, xs: xs.batch(4), - 4)).make_initializable_iterator()) + 4))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) - self.assertAllEqual([0, 0, 0, 0], sess.run(get_next)) - self.assertAllEqual([1, 1, 1, 1], sess.run(get_next)) + self.evaluate(init_op) + self.assertAllEqual([0, 0, 0, 0], self.evaluate(get_next)) + self.assertAllEqual([1, 1, 1, 1], self.evaluate(get_next)) # The small outputs at the end are deterministically produced in key # order. - self.assertAllEqual([0, 0, 0], sess.run(get_next)) - self.assertAllEqual([1], sess.run(get_next)) + self.assertAllEqual([0, 0, 0], self.evaluate(get_next)) + self.assertAllEqual([1], self.evaluate(get_next)) + @test_util.run_deprecated_v1 def testEmpty(self): - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.range(4).apply( - grouping.group_by_window(lambda _: 0, lambda _, xs: xs, 0)) - .make_initializable_iterator()) + grouping.group_by_window(lambda _: 0, lambda _, xs: xs, 0))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) with self.assertRaisesRegexp( errors.InvalidArgumentError, "Window size must be greater than zero, but got 0."): - print(sess.run(get_next)) + print(self.evaluate(get_next)) + @test_util.run_deprecated_v1 def testReduceFuncError(self): components = np.random.randint(100, size=(200,)).astype(np.int64) @@ -314,19 +323,19 @@ class GroupByWindowTest(test_base.DatasetTestBase): padded_shapes=(tensor_shape.TensorShape([]), constant_op.constant([5], dtype=dtypes.int64) * -1)) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(components) .map(lambda x: (x, ops.convert_to_tensor([x * x]))).apply( - grouping.group_by_window(lambda x, _: x % 2, reduce_func, - 32)).make_initializable_iterator()) + grouping.group_by_window(lambda x, _: x % 2, reduce_func, 32))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) with self.assertRaises(errors.InvalidArgumentError): - sess.run(get_next) + self.evaluate(get_next) + @test_util.run_deprecated_v1 def testConsumeWindowDatasetMoreThanOnce(self): components = np.random.randint(50, size=(200,)).astype(np.int64) @@ -340,22 +349,21 @@ class GroupByWindowTest(test_base.DatasetTestBase): 4, padded_shapes=ops.convert_to_tensor([(key + 1) * 10])), )) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(components) .map(lambda x: array_ops.fill([math_ops.cast(x, dtypes.int32)], x)) .apply(grouping.group_by_window( lambda x: math_ops.cast(array_ops.shape(x)[0] // 10, dtypes.int64), - reduce_func, 4)) - .make_initializable_iterator()) + reduce_func, 4))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) counts = [] with self.assertRaises(errors.OutOfRangeError): while True: - tight_result, multiple_of_10_result = sess.run(get_next) + tight_result, multiple_of_10_result = self.evaluate(get_next) self.assertEqual(0, multiple_of_10_result.shape[1] % 10) self.assertAllEqual(tight_result, multiple_of_10_result[:, :tight_result.shape[1]]) diff --git a/tensorflow/python/data/experimental/kernel_tests/ignore_errors_test.py b/tensorflow/python/data/experimental/kernel_tests/ignore_errors_test.py index c0ec1486ab..81f580fccb 100644 --- a/tensorflow/python/data/experimental/kernel_tests/ignore_errors_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/ignore_errors_test.py @@ -25,6 +25,7 @@ from tensorflow.python.data.experimental.ops import error_ops from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import io_ops from tensorflow.python.platform import test @@ -35,6 +36,7 @@ _NUMPY_RANDOM_SEED = 42 class IgnoreErrorsTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testMapIgnoreError(self): components = np.array([1., 2., 3., np.nan, 5.]).astype(np.float32) @@ -42,17 +44,18 @@ class IgnoreErrorsTest(test_base.DatasetTestBase): dataset_ops.Dataset.from_tensor_slices(components) .map(lambda x: array_ops.check_numerics(x, "message")).apply( error_ops.ignore_errors())) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) for x in [1., 2., 3., 5.]: - self.assertEqual(x, sess.run(get_next)) + self.assertEqual(x, self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) + @test_util.run_deprecated_v1 def testParallelMapIgnoreError(self): components = np.array([1., 2., 3., np.nan, 5.]).astype(np.float32) @@ -60,17 +63,18 @@ class IgnoreErrorsTest(test_base.DatasetTestBase): dataset_ops.Dataset.from_tensor_slices(components).map( lambda x: array_ops.check_numerics(x, "message"), num_parallel_calls=2).prefetch(2).apply(error_ops.ignore_errors())) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) for x in [1., 2., 3., 5.]: - self.assertEqual(x, sess.run(get_next)) + self.assertEqual(x, self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) + @test_util.run_deprecated_v1 def testReadFileIgnoreError(self): def write_string_to_file(value, filename): @@ -87,28 +91,28 @@ class IgnoreErrorsTest(test_base.DatasetTestBase): dataset_ops.Dataset.from_tensor_slices(filenames).map( io_ops.read_file, num_parallel_calls=2).prefetch(2).apply(error_ops.ignore_errors())) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: # All of the files are present. - sess.run(init_op) + self.evaluate(init_op) for filename in filenames: - self.assertEqual(compat.as_bytes(filename), sess.run(get_next)) + self.assertEqual(compat.as_bytes(filename), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Delete one of the files. os.remove(filenames[0]) # Attempting to read filenames[0] will fail, but ignore_errors() # will catch the error. - sess.run(init_op) + self.evaluate(init_op) for filename in filenames[1:]: - self.assertEqual(compat.as_bytes(filename), sess.run(get_next)) + self.assertEqual(compat.as_bytes(filename), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/indexed_dataset_ops_test.py b/tensorflow/python/data/experimental/kernel_tests/indexed_dataset_ops_test.py index c93a8353ce..c3c4ccd077 100644 --- a/tensorflow/python/data/experimental/kernel_tests/indexed_dataset_ops_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/indexed_dataset_ops_test.py @@ -24,6 +24,7 @@ from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops from tensorflow.python.platform import test @@ -31,6 +32,7 @@ from tensorflow.python.platform import test class IndexedDatasetOpsTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testLowLevelIndexedDatasetOps(self): identity = ged_ops.experimental_identity_indexed_dataset( ops.convert_to_tensor(16, dtype=dtypes.uint64)) @@ -46,14 +48,15 @@ class IndexedDatasetOpsTest(test_base.DatasetTestBase): handle, index, output_types=[dtypes.uint64], output_shapes=[[]]) with self.cached_session() as sess: - sess.run(materialize) + self.evaluate(materialize) self.assertEqual([3], sess.run(get_op, feed_dict={index: 3})) + @test_util.run_deprecated_v1 def testIdentityIndexedDataset(self): ds = indexed_dataset_ops.IdentityIndexedDataset(16) materialized = ds.materialize() with self.cached_session() as sess: - sess.run(materialized.initializer) + self.evaluate(materialized.initializer) placeholder = array_ops.placeholder(dtypes.uint64, shape=[]) for i in range(16): output = sess.run( @@ -68,12 +71,13 @@ class IndexedDatasetOpsTest(test_base.DatasetTestBase): itr = ds.make_initializable_iterator() n = itr.get_next() with self.cached_session() as sess: - sess.run(itr.initializer) + self.evaluate(itr.initializer) for i in range(16): - output = sess.run(n) + output = self.evaluate(n) self.assertEqual(i, output) with self.assertRaises(errors.OutOfRangeError): - sess.run(n) + self.evaluate(n) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/make_batched_features_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/make_batched_features_dataset_test.py index 91ae8cb1bd..7c78810494 100644 --- a/tensorflow/python/data/experimental/kernel_tests/make_batched_features_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/make_batched_features_dataset_test.py @@ -21,11 +21,13 @@ import numpy as np from tensorflow.python.data.experimental.kernel_tests import reader_dataset_ops_test_base from tensorflow.python.data.experimental.ops import readers +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import readers as core_readers from tensorflow.python.data.util import nest from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import io_ops from tensorflow.python.ops import parsing_ops from tensorflow.python.platform import test @@ -40,11 +42,12 @@ class MakeBatchedFeaturesDatasetTest( with ops.Graph().as_default() as g: with self.session(graph=g) as sess: # Basic test: read from file 0. - self.outputs = self.make_batch_feature( - filenames=self.test_filenames[0], - label_key="label", - num_epochs=num_epochs, - batch_size=batch_size).make_one_shot_iterator().get_next() + self.outputs = dataset_ops.make_one_shot_iterator( + self.make_batch_feature( + filenames=self.test_filenames[0], + label_key="label", + num_epochs=num_epochs, + batch_size=batch_size)).get_next() self.verify_records( sess, batch_size, @@ -57,11 +60,12 @@ class MakeBatchedFeaturesDatasetTest( with ops.Graph().as_default() as g: with self.session(graph=g) as sess: # Basic test: read from file 1. - self.outputs = self.make_batch_feature( - filenames=self.test_filenames[1], - label_key="label", - num_epochs=num_epochs, - batch_size=batch_size).make_one_shot_iterator().get_next() + self.outputs = dataset_ops.make_one_shot_iterator( + self.make_batch_feature( + filenames=self.test_filenames[1], + label_key="label", + num_epochs=num_epochs, + batch_size=batch_size)).get_next() self.verify_records( sess, batch_size, @@ -74,11 +78,12 @@ class MakeBatchedFeaturesDatasetTest( with ops.Graph().as_default() as g: with self.session(graph=g) as sess: # Basic test: read from both files. - self.outputs = self.make_batch_feature( - filenames=self.test_filenames, - label_key="label", - num_epochs=num_epochs, - batch_size=batch_size).make_one_shot_iterator().get_next() + self.outputs = dataset_ops.make_one_shot_iterator( + self.make_batch_feature( + filenames=self.test_filenames, + label_key="label", + num_epochs=num_epochs, + batch_size=batch_size)).get_next() self.verify_records( sess, batch_size, @@ -90,14 +95,16 @@ class MakeBatchedFeaturesDatasetTest( with ops.Graph().as_default() as g: with self.session(graph=g) as sess: # Basic test: read from both files. - self.outputs = self.make_batch_feature( - filenames=self.test_filenames, - num_epochs=num_epochs, - batch_size=batch_size).make_one_shot_iterator().get_next() + self.outputs = dataset_ops.make_one_shot_iterator( + self.make_batch_feature( + filenames=self.test_filenames, + num_epochs=num_epochs, + batch_size=batch_size)).get_next() self.verify_records(sess, batch_size, num_epochs=num_epochs) with self.assertRaises(errors.OutOfRangeError): self._next_actual_batch(sess) + @test_util.run_deprecated_v1 def testReadWithEquivalentDataset(self): features = { "file": parsing_ops.FixedLenFeature([], dtypes.int64), @@ -107,19 +114,19 @@ class MakeBatchedFeaturesDatasetTest( core_readers.TFRecordDataset(self.test_filenames) .map(lambda x: parsing_ops.parse_single_example(x, features)) .repeat(10).batch(2)) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer next_element = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) for file_batch, _, _, _, record_batch, _ in self._next_expected_batch( range(self._num_files), 2, 10): - actual_batch = sess.run(next_element) + actual_batch = self.evaluate(next_element) self.assertAllEqual(file_batch, actual_batch["file"]) self.assertAllEqual(record_batch, actual_batch["record"]) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testReadWithFusedShuffleRepeatDataset(self): num_epochs = 5 @@ -128,18 +135,18 @@ class MakeBatchedFeaturesDatasetTest( # Test that shuffling with same seed produces the same result. with ops.Graph().as_default() as g: with self.session(graph=g) as sess: - outputs1 = self.make_batch_feature( + outputs1 = dataset_ops.make_one_shot_iterator(self.make_batch_feature( filenames=self.test_filenames[0], num_epochs=num_epochs, batch_size=batch_size, shuffle=True, - shuffle_seed=5).make_one_shot_iterator().get_next() - outputs2 = self.make_batch_feature( + shuffle_seed=5)).get_next() + outputs2 = dataset_ops.make_one_shot_iterator(self.make_batch_feature( filenames=self.test_filenames[0], num_epochs=num_epochs, batch_size=batch_size, shuffle=True, - shuffle_seed=5).make_one_shot_iterator().get_next() + shuffle_seed=5)).get_next() for _ in range(total_records // batch_size): batch1 = self._run_actual_batch(outputs1, sess) batch2 = self._run_actual_batch(outputs2, sess) @@ -149,18 +156,18 @@ class MakeBatchedFeaturesDatasetTest( # Test that shuffling with different seeds produces a different order. with ops.Graph().as_default() as g: with self.session(graph=g) as sess: - outputs1 = self.make_batch_feature( + outputs1 = dataset_ops.make_one_shot_iterator(self.make_batch_feature( filenames=self.test_filenames[0], num_epochs=num_epochs, batch_size=batch_size, shuffle=True, - shuffle_seed=5).make_one_shot_iterator().get_next() - outputs2 = self.make_batch_feature( + shuffle_seed=5)).get_next() + outputs2 = dataset_ops.make_one_shot_iterator(self.make_batch_feature( filenames=self.test_filenames[0], num_epochs=num_epochs, batch_size=batch_size, shuffle=True, - shuffle_seed=15).make_one_shot_iterator().get_next() + shuffle_seed=15)).get_next() all_equal = True for _ in range(total_records // batch_size): batch1 = self._run_actual_batch(outputs1, sess) @@ -176,14 +183,14 @@ class MakeBatchedFeaturesDatasetTest( for parser_num_threads in [2, 4]: with ops.Graph().as_default() as g: with self.session(graph=g) as sess: - self.outputs = self.make_batch_feature( - filenames=self.test_filenames, - label_key="label", - num_epochs=num_epochs, - batch_size=batch_size, - reader_num_threads=reader_num_threads, - parser_num_threads=parser_num_threads).make_one_shot_iterator( - ).get_next() + self.outputs = dataset_ops.make_one_shot_iterator( + self.make_batch_feature( + filenames=self.test_filenames, + label_key="label", + num_epochs=num_epochs, + batch_size=batch_size, + reader_num_threads=reader_num_threads, + parser_num_threads=parser_num_threads)).get_next() self.verify_records( sess, batch_size, @@ -195,13 +202,13 @@ class MakeBatchedFeaturesDatasetTest( with ops.Graph().as_default() as g: with self.session(graph=g) as sess: - self.outputs = self.make_batch_feature( - filenames=self.test_filenames, - num_epochs=num_epochs, - batch_size=batch_size, - reader_num_threads=reader_num_threads, - parser_num_threads=parser_num_threads).make_one_shot_iterator( - ).get_next() + self.outputs = dataset_ops.make_one_shot_iterator( + self.make_batch_feature( + filenames=self.test_filenames, + num_epochs=num_epochs, + batch_size=batch_size, + reader_num_threads=reader_num_threads, + parser_num_threads=parser_num_threads)).get_next() self.verify_records( sess, batch_size, @@ -215,12 +222,12 @@ class MakeBatchedFeaturesDatasetTest( for num_epochs in [1, 10]: with ops.Graph().as_default(): # Basic test: read from file 0. - outputs = self.make_batch_feature( + outputs = dataset_ops.make_one_shot_iterator(self.make_batch_feature( filenames=self.test_filenames[0], label_key="label", num_epochs=num_epochs, batch_size=batch_size, - drop_final_batch=True).make_one_shot_iterator().get_next() + drop_final_batch=True)).get_next() for tensor in nest.flatten(outputs): if isinstance(tensor, ops.Tensor): # Guard against SparseTensor. self.assertEqual(tensor.shape[0], batch_size) diff --git a/tensorflow/python/data/experimental/kernel_tests/make_csv_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/make_csv_dataset_test.py index e4bf089184..e80accee33 100644 --- a/tensorflow/python/data/experimental/kernel_tests/make_csv_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/make_csv_dataset_test.py @@ -25,11 +25,13 @@ import numpy as np from tensorflow.python.data.experimental.ops import readers from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.util import nest from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -82,7 +84,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): expected_output, expected_keys, ): - nxt = dataset.make_one_shot_iterator().get_next() + nxt = dataset_ops.make_one_shot_iterator(dataset).get_next() for expected_features in self._next_expected_batch( expected_output, @@ -90,7 +92,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): batch_size, num_epochs, ): - actual_features = sess.run(nxt) + actual_features = self.evaluate(nxt) if label_name is not None: expected_labels = expected_features.pop(label_name) @@ -102,7 +104,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): self.assertAllEqual(expected_features[k], actual_features[k]) with self.assertRaises(errors.OutOfRangeError): - sess.run(nxt) + self.evaluate(nxt) def _test_dataset(self, inputs, @@ -127,6 +129,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): self._verify_output(sess, dataset, batch_size, num_epochs, label_name, expected_output, expected_keys) + @test_util.run_deprecated_v1 def testMakeCSVDataset(self): """Tests making a CSV dataset with keys and defaults provided.""" record_defaults = [ @@ -158,6 +161,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): column_defaults=record_defaults, ) + @test_util.run_deprecated_v1 def testMakeCSVDataset_withBatchSizeAndEpochs(self): """Tests making a CSV dataset with keys and defaults provided.""" record_defaults = [ @@ -189,6 +193,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): column_defaults=record_defaults, ) + @test_util.run_deprecated_v1 def testMakeCSVDataset_withCompressionType(self): """Tests `compression_type` argument.""" record_defaults = [ @@ -257,6 +262,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): label_name="not_a_real_label", column_names=column_names) + @test_util.run_deprecated_v1 def testMakeCSVDataset_withNoLabel(self): """Tests making a CSV dataset with no label provided.""" record_defaults = [ @@ -286,6 +292,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): column_defaults=record_defaults, ) + @test_util.run_deprecated_v1 def testMakeCSVDataset_withNoHeader(self): """Tests that datasets can be created from CSV files with no header line. """ @@ -347,6 +354,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): column_defaults=record_defaults, ) + @test_util.run_deprecated_v1 def testMakeCSVDataset_withNoColNames(self): """Tests that datasets can be created when column names are not specified. @@ -451,6 +459,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): header=True, ) + @test_util.run_deprecated_v1 def testMakeCSVDataset_withSelectCols(self): record_defaults = [ constant_op.constant([], dtypes.int32), @@ -557,6 +566,7 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): label_name=None, select_columns=["invalid_col_name"]) + @test_util.run_deprecated_v1 def testMakeCSVDataset_withShuffle(self): record_defaults = [ constant_op.constant([], dtypes.int32), @@ -604,11 +614,11 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): shuffle_seed=5, num_epochs=2, ) - outputs1 = dataset1.make_one_shot_iterator().get_next() - outputs2 = dataset2.make_one_shot_iterator().get_next() + outputs1 = dataset_ops.make_one_shot_iterator(dataset1).get_next() + outputs2 = dataset_ops.make_one_shot_iterator(dataset2).get_next() for _ in range(total_records // batch_size): - batch1 = nest.flatten(sess.run(outputs1)) - batch2 = nest.flatten(sess.run(outputs2)) + batch1 = nest.flatten(self.evaluate(outputs1)) + batch2 = nest.flatten(self.evaluate(outputs2)) for i in range(len(batch1)): self.assertAllEqual(batch1[i], batch2[i]) @@ -635,12 +645,12 @@ class MakeCsvDatasetTest(test_base.DatasetTestBase): shuffle_seed=6, num_epochs=2, ) - outputs1 = dataset1.make_one_shot_iterator().get_next() - outputs2 = dataset2.make_one_shot_iterator().get_next() + outputs1 = dataset_ops.make_one_shot_iterator(dataset1).get_next() + outputs2 = dataset_ops.make_one_shot_iterator(dataset2).get_next() all_equal = False for _ in range(total_records // batch_size): - batch1 = nest.flatten(sess.run(outputs1)) - batch2 = nest.flatten(sess.run(outputs2)) + batch1 = nest.flatten(self.evaluate(outputs1)) + batch2 = nest.flatten(self.evaluate(outputs2)) for i in range(len(batch1)): all_equal = all_equal and np.array_equal(batch1[i], batch2[i]) self.assertFalse(all_equal) diff --git a/tensorflow/python/data/experimental/kernel_tests/make_tf_record_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/make_tf_record_dataset_test.py index 657cf3c00e..ab2feb6426 100644 --- a/tensorflow/python/data/experimental/kernel_tests/make_tf_record_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/make_tf_record_dataset_test.py @@ -19,6 +19,7 @@ from __future__ import print_function from tensorflow.python.data.experimental.kernel_tests import reader_dataset_ops_test_base from tensorflow.python.data.experimental.ops import readers +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.util import nest from tensorflow.python.framework import errors from tensorflow.python.framework import ops @@ -105,7 +106,7 @@ class MakeTFRecordDatasetTest( for expected_batch in self._next_expected_batch( file_indices, batch_size, num_epochs, interleave_cycle_length, drop_final_batch, use_parser_fn): - actual_batch = sess.run(outputs) + actual_batch = self.evaluate(outputs) self.assertAllEqual(expected_batch, actual_batch) def _read_test(self, batch_size, num_epochs, file_index=None, @@ -122,20 +123,21 @@ class MakeTFRecordDatasetTest( with ops.Graph().as_default() as g: with self.session(graph=g) as sess: - outputs = readers.make_tf_record_dataset( - file_pattern=file_pattern, - num_epochs=num_epochs, - batch_size=batch_size, - parser_fn=fn, - num_parallel_reads=num_parallel_reads, - drop_final_batch=drop_final_batch, - shuffle=False).make_one_shot_iterator().get_next() + outputs = dataset_ops.make_one_shot_iterator( + readers.make_tf_record_dataset( + file_pattern=file_pattern, + num_epochs=num_epochs, + batch_size=batch_size, + parser_fn=fn, + num_parallel_reads=num_parallel_reads, + drop_final_batch=drop_final_batch, + shuffle=False)).get_next() self._verify_records( sess, outputs, batch_size, file_index, num_epochs=num_epochs, interleave_cycle_length=num_parallel_reads, drop_final_batch=drop_final_batch, use_parser_fn=parser_fn) with self.assertRaises(errors.OutOfRangeError): - sess.run(outputs) + self.evaluate(outputs) def testRead(self): for batch_size in [1, 2]: @@ -185,22 +187,22 @@ class MakeTFRecordDatasetTest( num_parallel_reads=num_parallel_reads, shuffle=True, shuffle_seed=seed) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) first_batches = [] try: while True: - first_batches.append(sess.run(next_element)) + first_batches.append(self.evaluate(next_element)) except errors.OutOfRangeError: pass - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) second_batches = [] try: while True: - second_batches.append(sess.run(next_element)) + second_batches.append(self.evaluate(next_element)) except errors.OutOfRangeError: pass diff --git a/tensorflow/python/data/experimental/kernel_tests/map_and_batch_test.py b/tensorflow/python/data/experimental/kernel_tests/map_and_batch_test.py index 5ead6d1c75..e6e24c3db1 100644 --- a/tensorflow/python/data/experimental/kernel_tests/map_and_batch_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/map_and_batch_test.py @@ -29,6 +29,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops @@ -48,6 +49,7 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): ("ParallelCallsNUMA", 2, None, True), ("ParallelBatchesNUMA", None, 10, True), ) + @test_util.run_deprecated_v1 def testMapAndBatch(self, num_parallel_calls, num_parallel_batches, numa_aware): """Test a dataset that maps a TF function across its input elements.""" @@ -76,7 +78,7 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() @@ -89,13 +91,13 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): sess.run(init_op, feed_dict={count: 28, batch_size: 14}) num_batches = (28 * 7) // 14 for i in range(num_batches): - result = sess.run(get_next) + result = self.evaluate(get_next) for component, result_component in zip(components, result): for j in range(14): self.assertAllEqual(component[(i * 14 + j) % 7]**2, result_component[j]) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Batch of a finite input, where the batch_size does not # divide the total number of elements. @@ -104,23 +106,23 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): # We expect (num_batches - 1) full-sized batches. num_batches = int(math.ceil((14 * 7) / 8)) for i in range(num_batches - 1): - result = sess.run(get_next) + result = self.evaluate(get_next) for component, result_component in zip(components, result): for j in range(8): self.assertAllEqual(component[(i * 8 + j) % 7]**2, result_component[j]) - result = sess.run(get_next) + result = self.evaluate(get_next) for component, result_component in zip(components, result): for j in range((14 * 7) % 8): self.assertAllEqual(component[((num_batches - 1) * 8 + j) % 7]**2, result_component[j]) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Batch of an empty input should fail straight away. sess.run(init_op, feed_dict={count: 0, batch_size: 8}) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Empty batch should be an initialization time error. with self.assertRaises(errors.InvalidArgumentError): @@ -132,6 +134,7 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): ("EvenNUMA", False, True), ("UnevenNUMA", True, True), ) + @test_util.run_deprecated_v1 def testMapAndBatchPartialBatch(self, drop_remainder, numa_aware): dataset = ( dataset_ops.Dataset.range(10).apply( @@ -144,7 +147,7 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) if drop_remainder: self.assertEqual([4, 1], iterator.output_shapes.as_list()) @@ -152,17 +155,18 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): self.assertEqual([None, 1], iterator.output_shapes.as_list()) next_element = iterator.get_next() with self.cached_session() as sess: - self.assertAllEqual([[0], [1], [4], [9]], sess.run(next_element)) - self.assertAllEqual([[16], [25], [36], [49]], sess.run(next_element)) + self.assertAllEqual([[0], [1], [4], [9]], self.evaluate(next_element)) + self.assertAllEqual([[16], [25], [36], [49]], self.evaluate(next_element)) if not drop_remainder: - self.assertAllEqual([[64], [81]], sess.run(next_element)) + self.assertAllEqual([[64], [81]], self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) @parameterized.named_parameters( ("Normal", False), ("NUMA", True), ) + @test_util.run_deprecated_v1 def testMapAndBatchYieldsPartialBatch(self, numa_aware): dataset = ( dataset_ops.Dataset.range(10).apply( @@ -173,20 +177,21 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) self.assertEqual([None, 1], iterator.output_shapes.as_list()) next_element = iterator.get_next() with self.cached_session() as sess: - self.assertAllEqual([[0], [1], [4], [9]], sess.run(next_element)) - self.assertAllEqual([[16], [25], [36], [49]], sess.run(next_element)) - self.assertAllEqual([[64], [81]], sess.run(next_element)) + self.assertAllEqual([[0], [1], [4], [9]], self.evaluate(next_element)) + self.assertAllEqual([[16], [25], [36], [49]], self.evaluate(next_element)) + self.assertAllEqual([[64], [81]], self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) @parameterized.named_parameters( ("Normal", False), ("NUMA", True), ) + @test_util.run_deprecated_v1 def testMapAndBatchParallelGetNext(self, numa_aware): dataset = dataset_ops.Dataset.range(50000).apply( batching.map_and_batch(lambda x: x, batch_size=100)) @@ -194,26 +199,27 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) elements = [] for _ in range(100): elements.append(iterator.get_next()) with self.cached_session() as sess: for i in range(5): - got = sess.run(elements) + got = self.evaluate(elements) got.sort(key=lambda x: x[0]) expected = [] for j in range(100): expected.append(range(i * 10000 + j * 100, i * 10000 + (j + 1) * 100)) self.assertAllEqual(got, expected) with self.assertRaises(errors.OutOfRangeError): - sess.run(elements) + self.evaluate(elements) @parameterized.named_parameters( ("Normal", False), ("NUMA", True), ) + @test_util.run_deprecated_v1 def testMapAndBatchParallelGetNextDropRemainder(self, numa_aware): dataset = dataset_ops.Dataset.range(49999).apply( batching.map_and_batch( @@ -223,26 +229,27 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) elements = [] for _ in range(100): elements.append(iterator.get_next()) with self.cached_session() as sess: for i in range(4): - got = sess.run(elements) + got = self.evaluate(elements) got.sort(key=lambda x: x[0]) expected = [] for j in range(100): expected.append(range(i * 10000 + j * 100, i * 10000 + (j + 1) * 100)) self.assertAllEqual(got, expected) with self.assertRaises(errors.OutOfRangeError): - sess.run(elements) + self.evaluate(elements) @parameterized.named_parameters( ("Normal", False), ("NUMA", True), ) + @test_util.run_deprecated_v1 def testMapAndBatchSparse(self, numa_aware): def _sparse(i): @@ -255,15 +262,15 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) for i in range(2): - actual = sess.run(get_next) + actual = self.evaluate(get_next) expected = sparse_tensor.SparseTensorValue( indices=[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], values=[i * 5, i * 5 + 1, i * 5 + 2, i * 5 + 3, i * 5 + 4], @@ -271,12 +278,13 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): self.assertTrue(sparse_tensor.is_sparse(actual)) self.assertSparseValuesEqual(actual, expected) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) @parameterized.named_parameters( ("Normal", False), ("NUMA", True), ) + @test_util.run_deprecated_v1 def testMapAndBatchFails(self, numa_aware): """Test a dataset that maps a TF function across its input elements.""" dataset = dataset_ops.Dataset.from_tensors( @@ -288,7 +296,7 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer with self.cached_session() as sess: @@ -299,6 +307,7 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): ("Normal", False), ("NUMA", True), ) + @test_util.run_deprecated_v1 def testMapAndBatchShapeMismatch(self, numa_aware): """Test a dataset that maps a TF function across its input elements.""" @@ -316,15 +325,15 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) with self.assertRaisesRegexp(errors.InvalidArgumentError, "number of elements does not match"): - sess.run(get_next) + self.evaluate(get_next) @parameterized.named_parameters( ("Normal", False), @@ -349,12 +358,12 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() with self.cached_session() as sess: for _ in range(3): - sess.run(get_next) + self.evaluate(get_next) @parameterized.named_parameters( ("1", 0, False), @@ -370,6 +379,7 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): ("5NUMA", 95, True), ("6NUMA", 99, True), ) + @test_util.run_deprecated_v1 def testMapAndBatchOutOfRangeError(self, threshold, numa_aware): def raising_py_fn(i): @@ -388,18 +398,19 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() with self.cached_session() as sess: for i in range(threshold // 10): - self.assertAllEqual([i * 10 + j for j in range(10)], sess.run(get_next)) + self.assertAllEqual([i * 10 + j for j in range(10)], + self.evaluate(get_next)) if threshold % 10 != 0: self.assertAllEqual( [threshold // 10 * 10 + j for j in range(threshold % 10)], - sess.run(get_next)) + self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) @parameterized.named_parameters( ("1", False, dtypes.bool, False), @@ -438,11 +449,12 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options.experimental_numa_aware = True dataset = dataset.with_options(options) - get_next = dataset.make_one_shot_iterator().get_next() + get_next = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: for _ in range(10): - self.assertAllEqual([element for _ in range(10)], sess.run(get_next)) + self.assertAllEqual([element for _ in range(10)], + self.evaluate(get_next)) @parameterized.named_parameters( ("Identity", None, lambda x: x, None), @@ -450,10 +462,11 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): ("Swap", (None, None), lambda x, y: (y, x), None), ("Project", (None, None), lambda x, y: x, None), ) + @test_util.run_deprecated_v1 def testShortCircuit(self, structure, map_fn, num_parallel_calls): dataset = self.structuredDataset(structure).repeat().apply( batching.map_and_batch(map_fn, batch_size=10)) - get_next = dataset.make_one_shot_iterator().get_next() + get_next = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: if isinstance(structure, tuple): @@ -462,23 +475,25 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): else: expected = map_fn( sess.run(self.structuredElement(structure, shape=[10]))) - self.assertAllEqual(expected, sess.run(get_next)) + self.assertAllEqual(expected, self.evaluate(get_next)) + @test_util.run_deprecated_v1 def testShortCircuitCapturedInput(self): captured_t = array_ops.placeholder(dtypes.int64, shape=[]) dataset = self.structuredDataset(None).repeat().apply( batching.map_and_batch(lambda x: captured_t, batch_size=10)) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) get_next = iterator.get_next() with self.cached_session() as sess: sess.run(iterator.initializer, feed_dict={captured_t: 42}) - self.assertAllEqual([42] * 10, sess.run(get_next)) + self.assertAllEqual([42] * 10, self.evaluate(get_next)) @parameterized.named_parameters( ("Normal", False), ("NUMA", True), ) + @test_util.run_deprecated_v1 def testMapAndBatchControlFlow(self, numa_aware): def map_fn(x): @@ -494,20 +509,20 @@ class MapAndBatchTest(test_base.DatasetTestBase, parameterized.TestCase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() with self.cached_session() as sess: for i in range(10): print("Case %d" % i) if i < 5: self.assertAllEqual([i * 10 + j + 1 for j in range(10)], - sess.run(get_next)) + self.evaluate(get_next)) else: self.assertAllEqual( [((i * 10) + j) * ((i * 10) + j) for j in range(10)], - sess.run(get_next)) + self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/map_defun_op_test.py b/tensorflow/python/data/experimental/kernel_tests/map_defun_op_test.py index 11694540fa..6042ca1c63 100644 --- a/tensorflow/python/data/experimental/kernel_tests/map_defun_op_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/map_defun_op_test.py @@ -218,7 +218,7 @@ class MapDefunTest(test_base.DatasetTestBase): def _assert_op_cancelled(self, sess, map_defun_op): with self.assertRaisesRegexp(errors.CancelledError, "was cancelled"): - sess.run(map_defun_op) + self.evaluate(map_defun_op) def testMapDefunWithParentCancellation(self): # Checks that a cancellation of the parent graph is threaded through to @@ -260,10 +260,10 @@ class MapDefunBenchmark(test.Benchmark): with session.Session() as sess: # Warm up the session for _ in range(5): - sess.run(op) + self.evaluate(op) start = time.time() for _ in range(num_iters): - sess.run(op) + self.evaluate(op) end = time.time() mean_us = (end - start) * 1e6 / num_iters self.report_benchmark( diff --git a/tensorflow/python/data/kernel_tests/matching_files_dataset_op_test.py b/tensorflow/python/data/experimental/kernel_tests/matching_files_test.py similarity index 57% rename from tensorflow/python/data/kernel_tests/matching_files_dataset_op_test.py rename to tensorflow/python/data/experimental/kernel_tests/matching_files_test.py index 4d86ec4228..0ee7616d35 100644 --- a/tensorflow/python/data/kernel_tests/matching_files_dataset_op_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/matching_files_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the experimental input pipeline ops.""" +"""Tests for the private `MatchingFilesDataset`.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -20,20 +20,17 @@ from __future__ import print_function import os import shutil import tempfile -import time -import numpy as np - -from tensorflow.python.client import session +from tensorflow.python.data.experimental.ops import matching_files from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops.dataset_ops import MatchingFilesDataset +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors -from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.platform import test from tensorflow.python.util import compat -class MatchingFilesDatasetTest(test_base.DatasetTestBase): +class MatchingFilesTest(test_base.DatasetTestBase): def setUp(self): self.tmp_dir = tempfile.mkdtemp() @@ -45,34 +42,40 @@ class MatchingFilesDatasetTest(test_base.DatasetTestBase): for filename in filenames: open(os.path.join(self.tmp_dir, filename), 'a').close() + @test_util.run_deprecated_v1 def testNonExistingDirectory(self): - """Test the MatchingFiles dataset with a non-existing directory""" + """Test the MatchingFiles dataset with a non-existing directory.""" self.tmp_dir = os.path.join(self.tmp_dir, 'nonexistingdir') - dataset = MatchingFilesDataset(os.path.join(self.tmp_dir, '*')) + dataset = matching_files.MatchingFilesDataset( + os.path.join(self.tmp_dir, '*')) with self.cached_session() as sess: - next_element = dataset.make_one_shot_iterator().get_next() + next_element = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.assertRaises(errors.NotFoundError): sess.run(next_element) + @test_util.run_deprecated_v1 def testEmptyDirectory(self): - """Test the MatchingFiles dataset with an empty directory""" + """Test the MatchingFiles dataset with an empty directory.""" - dataset = MatchingFilesDataset(os.path.join(self.tmp_dir, '*')) + dataset = matching_files.MatchingFilesDataset( + os.path.join(self.tmp_dir, '*')) with self.cached_session() as sess: - next_element = dataset.make_one_shot_iterator().get_next() + next_element = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.assertRaises(errors.NotFoundError): sess.run(next_element) + @test_util.run_deprecated_v1 def testSimpleDirectory(self): - """Test the MatchingFiles dataset with a simple directory""" + """Test the MatchingFiles dataset with a simple directory.""" filenames = ['a', 'b', 'c'] self._touchTempFiles(filenames) - dataset = MatchingFilesDataset(os.path.join(self.tmp_dir, '*')) + dataset = matching_files.MatchingFilesDataset( + os.path.join(self.tmp_dir, '*')) with self.cached_session() as sess: - next_element = dataset.make_one_shot_iterator().get_next() + next_element = dataset_ops.make_one_shot_iterator(dataset).get_next() expected_filenames = [] actual_filenames = [] @@ -85,15 +88,17 @@ class MatchingFilesDatasetTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(next_element) + @test_util.run_deprecated_v1 def testFileSuffixes(self): - """Test the MatchingFiles dataset using the suffixes of filename""" + """Test the MatchingFiles dataset using the suffixes of filename.""" filenames = ['a.txt', 'b.py', 'c.py', 'd.pyc'] self._touchTempFiles(filenames) - dataset = MatchingFilesDataset(os.path.join(self.tmp_dir, '*.py')) + dataset = matching_files.MatchingFilesDataset( + os.path.join(self.tmp_dir, '*.py')) with self.cached_session() as sess: - next_element = dataset.make_one_shot_iterator().get_next() + next_element = dataset_ops.make_one_shot_iterator(dataset).get_next() expected_filenames = [] actual_filenames = [] for filename in filenames[1:-1]: @@ -105,15 +110,17 @@ class MatchingFilesDatasetTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(next_element) + @test_util.run_deprecated_v1 def testFileMiddles(self): - """Test the MatchingFiles dataset using the middles of filename""" + """Test the MatchingFiles dataset using the middles of filename.""" filenames = ['aa.txt', 'bb.py', 'bbc.pyc', 'cc.pyc'] self._touchTempFiles(filenames) - dataset = MatchingFilesDataset(os.path.join(self.tmp_dir, 'b*.py*')) + dataset = matching_files.MatchingFilesDataset( + os.path.join(self.tmp_dir, 'b*.py*')) with self.cached_session() as sess: - next_element = dataset.make_one_shot_iterator().get_next() + next_element = dataset_ops.make_one_shot_iterator(dataset).get_next() expected_filenames = [] actual_filenames = [] for filename in filenames[1:3]: @@ -125,8 +132,9 @@ class MatchingFilesDatasetTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(next_element) + @test_util.run_deprecated_v1 def testNestedDirectories(self): - """Test the MatchingFiles dataset with nested directories""" + """Test the MatchingFiles dataset with nested directories.""" filenames = [] width = 8 @@ -147,9 +155,9 @@ class MatchingFilesDatasetTest(test_base.DatasetTestBase): suffix) for suffix in ['*.txt', '*.log'] ] - dataset = MatchingFilesDataset(patterns) + dataset = matching_files.MatchingFilesDataset(patterns) with self.cached_session() as sess: - next_element = dataset.make_one_shot_iterator().get_next() + next_element = dataset_ops.make_one_shot_iterator(dataset).get_next() expected_filenames = [ compat.as_bytes(filename) for filename in filenames @@ -165,70 +173,5 @@ class MatchingFilesDatasetTest(test_base.DatasetTestBase): self.assertItemsEqual(expected_filenames, actual_filenames) -class MatchingFilesDatasetBenchmark(test.Benchmark): - - def benchmarkNestedDirectories(self): - tmp_dir = tempfile.mkdtemp() - width = 500 - depth = 10 - for i in range(width): - for j in range(depth): - new_base = os.path.join(tmp_dir, str(i), - *[str(dir_name) for dir_name in range(j)]) - os.makedirs(new_base) - child_files = ['a.py', 'b.pyc'] if j < depth - 1 else ['c.txt', 'd.log'] - for f in child_files: - filename = os.path.join(new_base, f) - open(filename, 'w').close() - - patterns = [ - os.path.join(tmp_dir, os.path.join(*['**' - for _ in range(depth)]), suffix) - for suffix in ['*.txt', '*.log'] - ] - - deltas = [] - iters = 3 - for _ in range(iters): - with ops.Graph().as_default(): - dataset = MatchingFilesDataset(patterns) - next_element = dataset.make_one_shot_iterator().get_next() - - with session.Session() as sess: - sub_deltas = [] - while True: - try: - start = time.time() - sess.run(next_element) - end = time.time() - sub_deltas.append(end - start) - except errors.OutOfRangeError: - break - deltas.append(sub_deltas) - - median_deltas = np.median(deltas, axis=0) - print('Nested directory size (width*depth): %d*%d Median wall time: ' - '%fs (read first filename), %fs (read second filename), avg %fs' - ' (read %d more filenames)' % - (width, depth, median_deltas[0], median_deltas[1], - np.average(median_deltas[2:]), len(median_deltas) - 2)) - self.report_benchmark( - iters=iters, - wall_time=np.sum(median_deltas), - extras={ - 'read first file:': - median_deltas[0], - 'read second file:': - median_deltas[1], - 'avg time for reading %d more filenames:' % - (len(median_deltas) - 2): - np.average(median_deltas[2:]) - }, - name='benchmark_matching_files_dataset_nesteddirectory(%d*%d)' % - (width, depth)) - - shutil.rmtree(tmp_dir, ignore_errors=True) - - if __name__ == '__main__': test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/BUILD b/tensorflow/python/data/experimental/kernel_tests/optimization/BUILD index 9946ef5a42..f214944254 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/BUILD +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/BUILD @@ -42,6 +42,7 @@ py_test( "//tensorflow/python:errors", "//tensorflow/python:math_ops", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", "@absl_py//absl/testing:parameterized", @@ -68,6 +69,7 @@ py_test( "//tensorflow/python:math_ops", "//tensorflow/python:random_ops", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", "@absl_py//absl/testing:parameterized", @@ -127,6 +129,7 @@ py_test( "//tensorflow/python:client_testlib", "//tensorflow/python:errors", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", ], @@ -148,6 +151,7 @@ py_test( "//tensorflow/python:errors", "//tensorflow/python:math_ops", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", "@absl_py//absl/testing:parameterized", @@ -167,6 +171,7 @@ py_test( "//tensorflow/python:client_testlib", "//tensorflow/python:errors", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", "@absl_py//absl/testing:parameterized", @@ -192,6 +197,7 @@ py_test( "//tensorflow/python:math_ops", "//tensorflow/python:random_ops", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", "@absl_py//absl/testing:parameterized", @@ -202,6 +208,7 @@ py_test( name = "map_vectorization_test", size = "medium", srcs = ["map_vectorization_test.py"], + shard_count = 8, srcs_version = "PY2AND3", tags = [ "no_oss", @@ -220,15 +227,15 @@ py_test( "//tensorflow/python:dtypes", "//tensorflow/python:errors", "//tensorflow/python:framework_ops", + "//tensorflow/python:framework_test_lib", "//tensorflow/python:math_ops", - "//tensorflow/python:nn_ops", + "//tensorflow/python:nn", "//tensorflow/python:parsing_ops", - "//tensorflow/python:session", "//tensorflow/python:sparse_tensor", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/data/util:nest", "//third_party/py/numpy", "@absl_py//absl/testing:parameterized", ], @@ -248,12 +255,9 @@ py_test( deps = [ "//tensorflow/python:client_testlib", "//tensorflow/python:errors", - "//tensorflow/python:math_ops", - "//tensorflow/python/data/experimental/ops:batching", "//tensorflow/python/data/experimental/ops:optimization", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", - "//third_party/py/numpy", "@absl_py//absl/testing:parameterized", ], ) @@ -275,6 +279,7 @@ py_test( "//tensorflow/python:errors", "//tensorflow/python:math_ops", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", ], @@ -296,10 +301,17 @@ py_test( "//tensorflow/python:dtypes", "//tensorflow/python:errors", "//tensorflow/python:random_ops", + "//tensorflow/python:variable_scope", + "//tensorflow/python/data/experimental/ops:batching", + "//tensorflow/python/data/experimental/ops:grouping", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", + "//tensorflow/python/data/experimental/ops:scan_ops", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/eager:context", "//third_party/py/numpy", + "@absl_py//absl/testing:parameterized", ], ) @@ -316,6 +328,7 @@ py_test( "//tensorflow/python:client_testlib", "//tensorflow/python:errors", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", ], diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/assert_next_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/assert_next_dataset_test.py index ed719a0ce9..9b8248a78d 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/assert_next_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/assert_next_dataset_test.py @@ -21,32 +21,27 @@ from tensorflow.python.data.experimental.ops import optimization from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.platform import test +@test_util.run_all_in_graph_and_eager_modes class AssertNextDatasetTest(test_base.DatasetTestBase): def testAssertNext(self): dataset = dataset_ops.Dataset.from_tensors(0).apply( optimization.assert_next(["Map"])).map(lambda x: x) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - self.assertEqual(0, sess.run(get_next)) + self.assertDatasetProduces(dataset, expected_output=[0]) def testAssertNextInvalid(self): dataset = dataset_ops.Dataset.from_tensors(0).apply( optimization.assert_next(["Whoops"])).map(lambda x: x) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - with self.assertRaisesRegexp( - errors.InvalidArgumentError, - "Asserted Whoops transformation at offset 0 but encountered " - "Map transformation instead."): - sess.run(get_next) + self.assertDatasetProduces( + dataset, + expected_error=( + errors.InvalidArgumentError, + "Asserted Whoops transformation at offset 0 but encountered " + "Map transformation instead.")) def testAssertNextShort(self): dataset = dataset_ops.Dataset.from_tensors(0).apply( @@ -54,14 +49,11 @@ class AssertNextDatasetTest(test_base.DatasetTestBase): options = dataset_ops.Options() options.experimental_autotune = False dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - with self.assertRaisesRegexp( - errors.InvalidArgumentError, - "Asserted next 2 transformations but encountered only 1."): - sess.run(get_next) + self.assertDatasetProduces( + dataset, + expected_error=( + errors.InvalidArgumentError, + "Asserted next 2 transformations but encountered only 1.")) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/filter_fusion_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/filter_fusion_test.py index 80a0d879dc..7371cf31df 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/filter_fusion_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/filter_fusion_test.py @@ -20,11 +20,12 @@ from __future__ import print_function from absl.testing import parameterized from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -58,6 +59,7 @@ def _filter_fusion_test_cases(): return tuple(tests) +@test_util.run_all_in_graph_and_eager_modes class FilterFusionTest(test_base.DatasetTestBase, parameterized.TestCase): @parameterized.named_parameters(*_filter_fusion_test_cases()) @@ -70,28 +72,25 @@ class FilterFusionTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = dataset.cache() options = dataset_ops.Options() - options.experimental_filter_fusion = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.filter_fusion = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - with self.cached_session() as sess: - for x in range(5): - r = map_function(x) - filtered = False - for predicate in predicates: - if isinstance(r, tuple): - b = predicate(*r) # Pass tuple as multiple arguments. - else: - b = predicate(r) - if not sess.run(b): - filtered = True - break + expected_output = [] + for x in range(5): + r = map_function(x) + filtered = False + for predicate in predicates: + if isinstance(r, tuple): + b = predicate(*r) # Pass tuple as multiple arguments. + else: + b = predicate(r) + if not self.evaluate(b): + filtered = True + break - if not filtered: - result = sess.run(get_next) - self.assertAllEqual(r, result) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + if not filtered: + expected_output.append(r) + self.assertDatasetProduces(dataset, expected_output=expected_output) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/hoist_random_uniform_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/hoist_random_uniform_test.py index 9f7fbfeba0..5f3a8683fb 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/hoist_random_uniform_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/hoist_random_uniform_test.py @@ -20,12 +20,15 @@ from __future__ import print_function from absl.testing import parameterized from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops @@ -58,23 +61,29 @@ def _hoist_random_uniform_test_cases(): return tuple(tests) +@test_util.run_all_in_graph_and_eager_modes class HoistRandomUniformTest(test_base.DatasetTestBase, parameterized.TestCase): def _testDataset(self, dataset): - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() previous_result = 0 - with self.cached_session() as sess: - for _ in range(5): - result = sess.run(get_next) - self.assertLessEqual(1, result) - self.assertLessEqual(result, 10) - # This checks if the result is somehow random by checking if we are not - # generating the same values. - self.assertNotEqual(previous_result, result) - previous_result = result - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + if context.executing_eagerly(): + iterator = dataset.__iter__() + get_next = iterator._next_internal # pylint: disable=protected-access + else: + iterator = dataset_ops.make_one_shot_iterator(dataset) + get_next = iterator.get_next + for _ in range(5): + result = self.evaluate(get_next()) + self.assertLessEqual(1, result) + self.assertLessEqual(result, 10) + # This checks if the result is somehow random by checking if we are not + # generating the same values. + self.assertNotEqual(previous_result, result) + previous_result = result + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) @parameterized.named_parameters(*_hoist_random_uniform_test_cases()) def testHoisting(self, function, will_optimize): @@ -83,7 +92,8 @@ class HoistRandomUniformTest(test_base.DatasetTestBase, parameterized.TestCase): ["Zip[0]", "Map"] if will_optimize else ["Map"])).map(function) options = dataset_ops.Options() - options.experimental_hoist_random_uniform = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.hoist_random_uniform = True dataset = dataset.with_options(options) self._testDataset(dataset) @@ -99,7 +109,8 @@ class HoistRandomUniformTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = dataset_ops.Dataset.range(5).apply( optimization.assert_next(["Zip[0]", "Map"])).map(random_with_capture) options = dataset_ops.Options() - options.experimental_hoist_random_uniform = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.hoist_random_uniform = True dataset = dataset.with_options(options) self._testDataset(dataset) diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/latency_all_edges_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/latency_all_edges_test.py index 7144d834f9..fc65f52704 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/latency_all_edges_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/latency_all_edges_test.py @@ -22,10 +22,11 @@ from tensorflow.python.data.experimental.ops import optimization from tensorflow.python.data.experimental.ops import stats_aggregator from tensorflow.python.data.experimental.ops import stats_options from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.platform import test +@test_util.run_all_in_graph_and_eager_modes class LatencyAllEdgesTest(stats_dataset_test_base.StatsDatasetTestBase): def testLatencyStatsOptimization(self): @@ -39,22 +40,18 @@ class LatencyAllEdgesTest(stats_dataset_test_base.StatsDatasetTestBase): options.experimental_stats.latency_all_edges = True options.experimental_stats.aggregator = aggregator dataset = dataset.with_options(options) - iterator = dataset.make_initializable_iterator() - get_next = iterator.get_next() + self.assertDatasetProduces( + dataset, + expected_output=[1], + requires_initialization=True, + num_test_iterations=1) summary_t = aggregator.get_summary() - - with self.cached_session() as sess: - sess.run(iterator.initializer) - self.assertEqual(1 * 1, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - summary_str = sess.run(summary_t) - self._assertSummaryHasCount(summary_str, - "record_latency_TensorDataset/_1", 1) - self._assertSummaryHasCount(summary_str, "record_latency_MapDataset/_4", - 1) - self._assertSummaryHasCount(summary_str, - "record_latency_PrefetchDataset/_6", 1) + summary_str = self.evaluate(summary_t) + self._assertSummaryHasCount(summary_str, "record_latency_TensorDataset/_1", + 1) + self._assertSummaryHasCount(summary_str, "record_latency_MapDataset/_4", 1) + self._assertSummaryHasCount(summary_str, + "record_latency_PrefetchDataset/_6", 1) def testLatencyStatsOptimizationV2(self): aggregator = stats_aggregator.StatsAggregator() @@ -63,24 +60,21 @@ class LatencyAllEdgesTest(stats_dataset_test_base.StatsDatasetTestBase): ["LatencyStats", "Map", "LatencyStats", "Prefetch", "LatencyStats"])).map(lambda x: x * x).prefetch(1) options = dataset_ops.Options() - options.experimental_stats = stats_options.StatsOptions(aggregator) + options.experimental_stats = stats_options.StatsOptions() + options.experimental_stats.aggregator = aggregator dataset = dataset.with_options(options) - iterator = dataset.make_initializable_iterator() - get_next = iterator.get_next() + self.assertDatasetProduces( + dataset, + expected_output=[1], + requires_initialization=True, + num_test_iterations=1) summary_t = aggregator.get_summary() - - with self.cached_session() as sess: - sess.run(iterator.initializer) - self.assertEqual(1, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - summary_str = sess.run(summary_t) - self._assertSummaryHasCount(summary_str, - "record_latency_TensorDataset/_1", 1) - self._assertSummaryHasCount(summary_str, "record_latency_MapDataset/_4", - 1) - self._assertSummaryHasCount(summary_str, - "record_latency_PrefetchDataset/_6", 1) + summary_str = self.evaluate(summary_t) + self._assertSummaryHasCount(summary_str, "record_latency_TensorDataset/_1", + 1) + self._assertSummaryHasCount(summary_str, "record_latency_MapDataset/_4", 1) + self._assertSummaryHasCount(summary_str, + "record_latency_PrefetchDataset/_6", 1) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/make_numa_aware_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/make_numa_aware_test.py index 6191a7db08..2386dd5f11 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/make_numa_aware_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/make_numa_aware_test.py @@ -21,10 +21,11 @@ from tensorflow.python.data.experimental.ops import batching from tensorflow.python.data.experimental.ops import optimization from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.platform import test +@test_util.run_all_in_graph_and_eager_modes class MakeNumaAwareTest(test_base.DatasetTestBase): def testMakeNumaAware(self): @@ -34,13 +35,8 @@ class MakeNumaAwareTest(test_base.DatasetTestBase): options = dataset_ops.Options() options.experimental_numa_aware = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - self.assertAllEqual([x * x for x in range(10)], sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.assertDatasetProduces( + dataset, expected_output=[[x * x for x in range(10)]]) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/map_and_batch_fusion_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/map_and_batch_fusion_test.py index ddf3cbbcc3..801f664f09 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/map_and_batch_fusion_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/map_and_batch_fusion_test.py @@ -18,12 +18,14 @@ from __future__ import division from __future__ import print_function from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.platform import test +@test_util.run_all_in_graph_and_eager_modes class MapAndBatchFusionTest(test_base.DatasetTestBase): def testMapAndBatchFusion(self): @@ -31,15 +33,11 @@ class MapAndBatchFusionTest(test_base.DatasetTestBase): optimization.assert_next( ["MapAndBatch"])).map(lambda x: x * x).batch(10) options = dataset_ops.Options() - options.experimental_map_and_batch_fusion = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.map_and_batch_fusion = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - self.assertAllEqual([x * x for x in range(10)], sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.assertDatasetProduces( + dataset, expected_output=[[x * x for x in range(10)]]) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/map_and_filter_fusion_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/map_and_filter_fusion_test.py index 3b4ca62340..db8f214fbf 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/map_and_filter_fusion_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/map_and_filter_fusion_test.py @@ -20,11 +20,12 @@ from __future__ import print_function from absl.testing import parameterized from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -62,23 +63,20 @@ def _map_and_filter_fusion_test_cases(): return tuple(tests) +@test_util.run_all_in_graph_and_eager_modes class MapAndFilterFusionTest(test_base.DatasetTestBase, parameterized.TestCase): def _testMapAndFilter(self, dataset, function, predicate): - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - with self.cached_session() as sess: - for x in range(10): - r = function(x) - if isinstance(r, tuple): - b = predicate(*r) # Pass tuple as multiple arguments. - else: - b = predicate(r) - if sess.run(b): - result = sess.run(get_next) - self.assertAllEqual(r, result) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + expected_output = [] + for x in range(10): + r = function(x) + if isinstance(r, tuple): + b = predicate(*r) # Pass tuple as multiple arguments. + else: + b = predicate(r) + if self.evaluate(b): + expected_output.append(r) + self.assertDatasetProduces(dataset, expected_output=expected_output) @parameterized.named_parameters(*_map_and_filter_fusion_test_cases()) def testMapFilterFusion(self, function, predicate): @@ -86,7 +84,8 @@ class MapAndFilterFusionTest(test_base.DatasetTestBase, parameterized.TestCase): optimization.assert_next( ["Map", "FilterByLastComponent"])).map(function).filter(predicate) options = dataset_ops.Options() - options.experimental_map_and_filter_fusion = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.map_and_filter_fusion = True dataset = dataset.with_options(options) self._testMapAndFilter(dataset, function, predicate) @@ -104,7 +103,8 @@ class MapAndFilterFusionTest(test_base.DatasetTestBase, parameterized.TestCase): optimization.assert_next(["Map", "Filter"])).map(function).filter(predicate) options = dataset_ops.Options() - options.experimental_map_and_filter_fusion = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.map_and_filter_fusion = True dataset = dataset.with_options(options) self._testMapAndFilter(dataset, function, predicate) diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/map_fusion_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/map_fusion_test.py index ec63ad7200..d8d6390374 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/map_fusion_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/map_fusion_test.py @@ -20,9 +20,10 @@ from __future__ import print_function from absl.testing import parameterized from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -62,6 +63,7 @@ def _map_fusion_test_cases(): return tuple(tests) +@test_util.run_all_in_graph_and_eager_modes class MapFusionTest(test_base.DatasetTestBase, parameterized.TestCase): @parameterized.named_parameters(*_map_fusion_test_cases()) @@ -73,23 +75,19 @@ class MapFusionTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = dataset.cache() options = dataset_ops.Options() - options.experimental_map_fusion = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.map_fusion = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - with self.cached_session() as sess: - for x in range(5): - result = sess.run(get_next) - r = x - for function in functions: - if isinstance(r, tuple): - r = function(*r) # Pass tuple as multiple arguments. - else: - r = function(r) - self.assertAllEqual(r, result) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + expected_output = [] + for x in range(5): + r = x + for function in functions: + if isinstance(r, tuple): + r = function(*r) # Pass tuple as multiple arguments. + else: + r = function(r) + expected_output.append(r) + self.assertDatasetProduces(dataset, expected_output=expected_output) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/map_parallelization_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/map_parallelization_test.py index c95f7b2eb1..0ff3fff4f8 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/map_parallelization_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/map_parallelization_test.py @@ -20,11 +20,12 @@ from __future__ import print_function from absl.testing import parameterized from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops @@ -58,6 +59,7 @@ def _map_parallelization_test_cases(): ("AssertWithRandom", assert_with_random, False)) +@test_util.run_all_in_graph_and_eager_modes class MapParallelizationTest(test_base.DatasetTestBase, parameterized.TestCase): @parameterized.named_parameters(*_map_parallelization_test_cases()) @@ -66,23 +68,12 @@ class MapParallelizationTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = dataset_ops.Dataset.range(5).apply( optimization.assert_next(next_nodes)).map(function) options = dataset_ops.Options() - options.experimental_map_parallelization = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.map_parallelization = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.test_session() as sess: - for x in range(5): - result = sess.run(get_next) - # No need to run the pipeline if it was not optimized. Also the results - # might be hard to check because of random. - if not should_optimize: - return - r = function(x) - self.assertAllEqual(r, result) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + if should_optimize: + self.assertDatasetProduces( + dataset, expected_output=[function(x) for x in range(5)]) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/map_vectorization_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/map_vectorization_test.py index f10b66ff69..c2e08e2cd8 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/map_vectorization_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/map_vectorization_test.py @@ -17,23 +17,21 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import time - from absl.testing import parameterized import numpy as np from tensorflow.core.example import example_pb2 from tensorflow.core.example import feature_pb2 -from tensorflow.python.client import session from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.data.util import nest from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import bitwise_ops from tensorflow.python.ops import check_ops @@ -319,6 +317,7 @@ def _generate_optimization_test_cases(): } for x in test_cases for num_parallel_calls in (None, 12)] +@test_util.run_all_in_graph_and_eager_modes class MapVectorizationTest(test_base.DatasetTestBase, parameterized.TestCase): def _get_test_datasets(self, @@ -355,7 +354,8 @@ class MapVectorizationTest(test_base.DatasetTestBase, parameterized.TestCase): optimized = _make_dataset(["Batch", map_node_name] if expect_optimized else [map_node_name, "Batch"]) options = dataset_ops.Options() - options.experimental_map_vectorization = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.map_vectorization = True optimized = optimized.with_options(options) return unoptimized, optimized @@ -366,7 +366,8 @@ class MapVectorizationTest(test_base.DatasetTestBase, parameterized.TestCase): num_parallel_calls) self.assertDatasetsEqual(unoptimized, optimized) - def testOptimizationBadMapFn(self): + # TODO(b/117581999): Add eager coverage for the following tests. + def testSkipEagerOptimizationBadMapFn(self): # Test map functions that give an error def map_fn(x): # x has leading dimension 5, this will raise an error @@ -375,7 +376,7 @@ class MapVectorizationTest(test_base.DatasetTestBase, parameterized.TestCase): base_dataset = dataset_ops.Dataset.range(5).repeat(5).batch( 5, drop_remainder=True) _, optimized = self._get_test_datasets(base_dataset, map_fn) - nxt = optimized.make_one_shot_iterator().get_next() + nxt = dataset_ops.make_one_shot_iterator(optimized).get_next() with self.assertRaisesRegexp(errors.InvalidArgumentError, r"indices = 10 is not in \[0, 5\)"): self.evaluate(nxt) @@ -394,7 +395,8 @@ class MapVectorizationTest(test_base.DatasetTestBase, parameterized.TestCase): base_dataset, map_fn, expect_optimized=True) self.assertDatasetsEqual(optimized, unoptimized) - def testOptimizationIgnoreStateful(self): + # TODO(b/117581999): Add eager coverage for the following tests. + def testSkipEagerOptimizationIgnoreStateful(self): def map_fn(x): with ops.control_dependencies([check_ops.assert_equal(x, 0)]): @@ -420,7 +422,8 @@ class MapVectorizationTest(test_base.DatasetTestBase, parameterized.TestCase): base_dataset, map_fn, expect_optimized=False) self.assertDatasetsEqual(unoptimized, optimized) - def testOptimizationIgnoreRaggedMap(self): + # TODO(b/117581999): Add eager coverage for the following tests. + def testSkipEagerOptimizationIgnoreRaggedMap(self): # Don't optimize when the output of the map fn shapes are unknown. def map_fn(x): return array_ops.tile(x, x) @@ -434,102 +437,5 @@ class MapVectorizationTest(test_base.DatasetTestBase, parameterized.TestCase): ("IteratorGetNext", "IteratorGetNext_1", 1)]) -class MapVectorizationBenchmark(test.Benchmark): - # TODO(rachelim): Add a benchmark for more expensive transformations, such as - # vgg_preprocessing. - - def _run(self, x, num_iters=100, name=None): - deltas = [] - with session.Session() as sess: - for _ in range(5): - # Warm up session... - sess.run(x) - for _ in range(num_iters): - start = time.time() - sess.run(x) - end = time.time() - deltas.append(end - start) - median_time = np.median(deltas) - self.report_benchmark(iters=num_iters, wall_time=median_time, name=name) - return median_time - - def _compare(self, input_dataset, map_fn, batch_size, input_size, str_id): - num_elems = int(np.sum([np.prod(x) for x in input_size])) - name_template = "{}__batch_size_{}_input_element_size_{}_{}" - unoptimized = input_dataset.map(map_fn).batch(batch_size) - unoptimized_op = unoptimized.make_one_shot_iterator().get_next() - - optimized = input_dataset.map(map_fn).batch(batch_size) - options = dataset_ops.Options() - options.experimental_map_vectorization = True - optimized = optimized.with_options(options) - optimized_op = optimized.make_one_shot_iterator().get_next() - - unoptimized_time = self._run( - unoptimized_op, - name=name_template.format(str_id, batch_size, num_elems, "unoptimized")) - optimized_time = self._run( - optimized_op, - name=name_template.format(str_id, batch_size, num_elems, "optimized")) - - print("Batch size: {}\n" - "Input element size: {}\n" - "Transformation: {}\n" - "Speedup: {}\n".format(batch_size, input_size, str_id, - (unoptimized_time / optimized_time))) - - # Known cheap functions - def benchmarkIdentity(self): - self._benchmark_helper(lambda *args: [array_ops.identity(x) for x in args], - "identity") - - def benchmarkAddConst(self): - self._benchmark_helper(lambda *args: [x + 1 for x in args], "add_const") - - def benchmarkReturnConst(self): - self._benchmark_helper(lambda *args: [constant_op.constant(2)], "ret_const") - - def benchmarkSelect(self): - self._benchmark_helper(lambda *args: args[0], "select") - - def benchmarkCast(self): - self._benchmark_helper( - lambda *args: [math_ops.cast(x, dtypes.float64) for x in args], "cast") - - def benchmarkReshape(self): - self._benchmark_helper( - lambda *args: [array_ops.reshape(x, (-1, 30)) for x in args], "reshape") - - def benchmarkDecodeCSV(self): - csv_fn, csv_factory = _generate_csv_test_case() - self._benchmark_helper(csv_fn, "decode_csv", lambda: [csv_factory()]) - - def benchmarkParseSingleExample(self): - # NOTE: Since we haven't implemented a vectorizer for "SerializeSparse", - # this function is only naively vectorized. - parse_fn, parse_factory = _generate_parse_single_example_test_case() - - self._benchmark_helper(parse_fn, "parse_single_example", - lambda: [parse_factory()]) - - def _default_dataset_factory(self): - input_sizes = [(10, 10, 3), (10, 100, 300)] - for sz in input_sizes: - yield dataset_ops.Dataset.from_tensor_slices(np.random.rand(*sz)) - - def _benchmark_helper(self, map_fn, str_id, base_dataset_factory=None): - if base_dataset_factory is None: - base_dataset_factory = self._default_dataset_factory - - batch_size = 1000 - for base_dataset in base_dataset_factory(): - base_dataset = base_dataset.repeat() - input_size = [ - tuple(shape.as_list()) - for shape in nest.flatten(base_dataset.output_shapes) - ] - self._compare(base_dataset, map_fn, batch_size, input_size, str_id) - - if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/model_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/model_dataset_test.py index 5b49bdf453..0f0274b41f 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/model_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/model_dataset_test.py @@ -17,181 +17,18 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import time - from absl.testing import parameterized -import numpy as np -from tensorflow.python.data.experimental.ops import batching from tensorflow.python.data.experimental.ops import optimization from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors -from tensorflow.python.ops import math_ops from tensorflow.python.platform import test +# TODO(b/117581999): Add eager coverage for the following tests. class ModelDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): - def testModelMap(self): - k = 1024 * 1024 - dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), - np.random.rand(4 * k, - 1))).repeat() - dataset = dataset.map(math_ops.matmul) - dataset = dataset_ops._ModelDataset(dataset) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - deltas = [] - with self.cached_session() as sess: - for _ in range(5): - sess.run(get_next.op) - for _ in range(100): - start = time.time() - sess.run(get_next.op) - end = time.time() - deltas.append(end - start) - - print("%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n" % - (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), - np.max(deltas))) - - def testModelParallelMap(self): - k = 1024 * 1024 - dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), - np.random.rand(4 * k, - 1))).repeat() - dataset = dataset.map( - math_ops.matmul, num_parallel_calls=optimization.AUTOTUNE) - dataset = dataset_ops._ModelDataset(dataset) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - deltas = [] - with self.cached_session() as sess: - for _ in range(5): - sess.run(get_next.op) - for _ in range(1000): - start = time.time() - sess.run(get_next.op) - end = time.time() - deltas.append(end - start) - - print("%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n" % - (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), - np.max(deltas))) - - @parameterized.named_parameters( - ("Default", False), - ("NUMA", True), - ) - def testModelMapAndBatch(self, numa_aware): - batch_size = 16 - k = 1024 * 1024 - dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), - np.random.rand(4 * k, - 1))).repeat() - dataset = dataset.apply( - batching.map_and_batch( - math_ops.matmul, - num_parallel_calls=optimization.AUTOTUNE, - batch_size=batch_size)) - dataset = dataset_ops._ModelDataset(dataset) - options = dataset_ops.Options() - options.experimental_numa_aware = numa_aware - dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - deltas = [] - with self.cached_session() as sess: - for _ in range(5): - sess.run(get_next.op) - for _ in range(10): - start = time.time() - sess.run(get_next.op) - end = time.time() - deltas.append(end - start) - - print("%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n" % - (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), - np.max(deltas))) - - def testModelParallelInterleave(self): - k = 1024 * 1024 - dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), - np.random.rand(4 * k, - 1))).repeat() - dataset = dataset.map(math_ops.matmul) - dataset = dataset_ops.Dataset.range(1).repeat().interleave( - lambda _: dataset, - cycle_length=10, - num_parallel_calls=optimization.AUTOTUNE) - dataset = dataset_ops._ModelDataset(dataset) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - deltas = [] - with self.cached_session() as sess: - for _ in range(5): - sess.run(get_next.op) - for _ in range(1000): - start = time.time() - sess.run(get_next.op) - end = time.time() - deltas.append(end - start) - - print("%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n" % - (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), - np.max(deltas))) - - def testModelNested(self): - k = 1024 * 1024 - a = (np.random.rand(1, 8 * k), np.random.rand(8 * k, 1)) - b = (np.random.rand(1, 4 * k), np.random.rand(4 * k, 1)) - c = (np.random.rand(1, 2 * k), np.random.rand(2 * k, 1)) - dataset = dataset_ops.Dataset.from_tensors((a, b, c)).repeat() - - def f1(a, b, c): - x, y = a - return math_ops.matmul(x, y), b, c - - def f2(a, b, c): - x, y = b - return a, math_ops.matmul(x, y), c - - def f3(a, b, c): - x, y = c - return a, b, math_ops.matmul(x, y) - - dataset = dataset.map(f1, num_parallel_calls=optimization.AUTOTUNE) - dataset = dataset_ops.Dataset.range(1).repeat().interleave( - lambda _: dataset, cycle_length=2) - - dataset = dataset.map(f2, num_parallel_calls=optimization.AUTOTUNE) - dataset = dataset_ops.Dataset.range(1).repeat().interleave( - lambda _: dataset, cycle_length=2) - - dataset = dataset.map(f3, num_parallel_calls=optimization.AUTOTUNE) - dataset = dataset_ops._ModelDataset(dataset) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - deltas = [] - with self.cached_session() as sess: - for _ in range(5): - sess.run(get_next) - for _ in range(100): - start = time.time() - sess.run(get_next) - end = time.time() - deltas.append(end - start) - - print("%f (median), %f (mean), %f (stddev), %f (min), %f (max)\n" % - (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), - np.max(deltas))) - def testAutotuneOption(self): dataset = dataset_ops.Dataset.from_tensors(0) dataset = dataset.map(lambda x: x).apply( @@ -200,13 +37,13 @@ class ModelDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): options.experimental_autotune = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() with self.cached_session() as sess: - self.assertEqual(0, sess.run(get_next)) + self.assertEqual(0, self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/noop_elimination_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/noop_elimination_test.py index ddcd7f4da4..ce86bfa4e0 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/noop_elimination_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/noop_elimination_test.py @@ -18,15 +18,17 @@ from __future__ import division from __future__ import print_function from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.platform import test +@test_util.run_all_in_graph_and_eager_modes class NoopEliminationTest(test_base.DatasetTestBase): def testNoopElimination(self): @@ -41,18 +43,10 @@ class NoopEliminationTest(test_base.DatasetTestBase): dataset = dataset.repeat(some_tensor).skip(5).take(-1).skip(0).repeat( 1).prefetch(0).prefetch(1).cache() options = dataset_ops.Options() - options.experimental_noop_elimination = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.noop_elimination = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.test_session() as sess: - for x in range(5): - result = sess.run(get_next) - self.assertAllEqual(result, x) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.assertDatasetProduces(dataset, expected_output=range(5)) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/optimize_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/optimize_dataset_test.py index 739b6a9bf4..751be83326 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/optimize_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/optimize_dataset_test.py @@ -17,54 +17,125 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import warnings + +from absl.testing import parameterized import numpy as np +from tensorflow.python.data.experimental.ops import batching +from tensorflow.python.data.experimental.ops import grouping from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops import optimization_options +from tensorflow.python.data.experimental.ops import scan_ops from tensorflow.python.data.experimental.ops import threadpool from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops +from tensorflow.python.ops import variable_scope from tensorflow.python.platform import test -class OptimizeDatasetTest(test_base.DatasetTestBase): +def _generate_captured_refvar_test_cases(): + """Generates testcases. + + Returns: + A list of tuples of (testcase_name, make_dataset_fn). make_dataset_fn takes + a tf.Variable as input and creates a test dataset that uses that variable. + """ + + def make_map_dataset(var): + return dataset_ops.Dataset.from_tensors(0).map(lambda x: x + var) + + def make_flat_map_dataset(var): + return dataset_ops.Dataset.from_tensors( + 0).flat_map(lambda _: dataset_ops.Dataset.from_tensors(var)) + + def make_filter_dataset(var): + return dataset_ops.Dataset.from_tensors(0).filter(lambda x: x < var) + + def make_map_and_batch_dataset(var): + + def map_fn(x): + return x + var + + return dataset_ops.Dataset.from_tensors(0).apply( + batching.map_and_batch(map_fn, 1)) + + def make_group_by_reducer_dataset(var): + reducer = grouping.Reducer( + init_func=lambda _: 0, + reduce_func=lambda x, y: x, + finalize_func=lambda _: var) + return dataset_ops.Dataset.range(5).apply( + grouping.group_by_reducer(lambda x: x % 2, reducer)) + + def make_group_by_window_dataset(var): + + def reduce_fn(key, bucket): + del key, bucket + return dataset_ops.Dataset.from_tensors(var) + + return dataset_ops.Dataset.from_tensors(0).repeat(10).apply( + grouping.group_by_window(lambda _: 0, reduce_fn, 10)) + + def make_scan_dataset(var): + return dataset_ops.Dataset.from_tensors(0).apply( + scan_ops.scan( + 0, lambda old_state, elem: (old_state + 1, elem + old_state + var))) + + return [ + # Core datasets + ("Map", make_map_dataset), + ("FlatMap", make_flat_map_dataset), + ("Filter", make_filter_dataset), + # Experimental datasets + ("MapAndBatch", make_map_and_batch_dataset), + ("GroupByReducer", make_group_by_reducer_dataset), + ("GroupByWindow", make_group_by_window_dataset), + ("Scan", make_scan_dataset) + ] + + +@test_util.run_all_in_graph_and_eager_modes +class OptimizeDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): def testOptimizationStatefulFunction(self): - dataset = dataset_ops.Dataset.range(10).map( - lambda _: random_ops.random_uniform([])).batch(10) + dataset = dataset_ops.Dataset.range( + 10).map(lambda _: random_ops.random_uniform([])).batch(10) dataset = dataset_ops._OptimizeDataset(dataset, []) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(get_next) + get_next = self.getNext(dataset) + self.evaluate(get_next()) - def testOptimizationLargeInputFromTensor(self): + # TODO(b/117581999): Add eager coverage for the following tests. + def testSkipEagerOptimizationLargeInputFromTensor(self): input_t = array_ops.placeholder(dtypes.int32, (None, None, None)) dataset = dataset_ops.Dataset.from_tensors(input_t) dataset = dataset_ops._OptimizeDataset(dataset, []) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: sess.run(init_op, {input_t: np.ones([512, 1024, 1025], np.int32)}) - sess.run(get_next) + self.evaluate(get_next) - def testOptimizationLargeInputFromTensorSlices(self): + # TODO(b/117581999): Add eager coverage for the following tests. + def testSkipEagerOptimizationLargeInputFromTensorSlices(self): input_t = array_ops.placeholder(dtypes.int32, (None, None, None, None)) dataset = dataset_ops.Dataset.from_tensor_slices(input_t) dataset = dataset_ops._OptimizeDataset(dataset, []) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: sess.run(init_op, {input_t: np.ones([1, 512, 1024, 1025], np.int32)}) - sess.run(get_next) + self.evaluate(get_next) def testOptimizationNestedDataset(self): @@ -78,13 +149,22 @@ class OptimizeDatasetTest(test_base.DatasetTestBase): dataset = dataset_ops.Dataset.range(1) dataset = dataset.flat_map(flat_map_fn) dataset = dataset_ops._OptimizeDataset(dataset, ["noop_elimination"]) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() + self.assertDatasetProduces(dataset, expected_output=[0]) - with self.cached_session() as sess: - self.assertEquals(0, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + def testOptimizationNestedDatasetWithModifiedRetval(self): + + def flat_map_fn(_): + dataset = dataset_ops.Dataset.from_tensors(0) + dataset = dataset.apply(optimization.assert_next(["MapAndBatch"])) + # Should be fused by map and batch fusion + dataset = dataset.map(lambda x: x) + dataset = dataset.batch(1) + return dataset + + dataset = dataset_ops.Dataset.range(1) + dataset = dataset.flat_map(flat_map_fn) + dataset = dataset_ops._OptimizeDataset(dataset, ["map_and_batch_fusion"]) + self.assertDatasetProduces(dataset, expected_output=[[0]]) def testOptimizationThreadPoolDataset(self): dataset = dataset_ops.Dataset.range(10).batch(10) @@ -95,14 +175,10 @@ class OptimizeDatasetTest(test_base.DatasetTestBase): 2, display_name="private_thread_pool_%d" % 2)) dataset = dataset_ops._OptimizeDataset(dataset, []) - iterator = dataset.make_initializable_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(iterator.initializer) - self.assertAllEqual(list(range(10)), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.assertDatasetProduces( + dataset, + expected_output=[list(range(10))], + requires_initialization=True) def testOptimizationNonSerializable(self): dataset = dataset_ops.Dataset.from_tensors(0) @@ -113,26 +189,61 @@ class OptimizeDatasetTest(test_base.DatasetTestBase): dataset = dataset.skip(0) # Should be removed by noop elimination dataset = dataset.cache() dataset = dataset_ops._OptimizeDataset(dataset, ["noop_elimination"]) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - self.assertEquals(0, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.assertDatasetProduces(dataset, expected_output=[0]) def testOptimizationNonSerializableAsDirectInput(self): - """Tests that non-serializable dataset can be OptimizeDataset's input. - """ + """Tests that non-serializable dataset can be OptimizeDataset's input.""" dataset = dataset_ops.Dataset.from_tensors(0) dataset = dataset.apply(optimization.non_serializable()) dataset = dataset_ops._OptimizeDataset(dataset, ["noop_elimination"]) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - with self.cached_session() as sess: - self.assertEquals(0, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.assertDatasetProduces(dataset, expected_output=[0]) + + @parameterized.named_parameters(_generate_captured_refvar_test_cases()) + # Skip eager because RefVariables are not supported in eager mode. + def testSkipEagerOptimizationWithCapturedRefVar(self, dataset_fn): + """Tests that default optimizations are disabled with ref variables.""" + variable = variable_scope.get_variable( + "v", initializer=0, use_resource=False) + assign_op = variable.assign_add(1) + + unoptimized_dataset = dataset_fn(variable) + + options = dataset_ops.Options() + opt_options = optimization_options.OptimizationOptions() + opt_options.noop_elimination = True + opt_options.map_and_batch_fusion = True + options.experimental_optimization = opt_options + optimized_dataset = unoptimized_dataset.with_options(options) + + # Check that warning is logged. + warnings.simplefilter("always") + with warnings.catch_warnings(record=True) as w: + optimized_it = optimized_dataset.make_initializable_iterator() + + self.assertGreaterEqual(len(w), 1) + expected = ("tf.data static optimizations are not compatible with " + "tf.Variable. The following optimizations will be disabled: " + "map_and_batch_fusion, noop_elimination. To enable " + "optimizations, use resource variables instead by calling " + "`tf.enable_resource_variables()` at the start of the program.") + self.assertTrue(any([expected in str(warning) for warning in w])) + + # Check that outputs are the same in the optimized and unoptimized cases, + # when the variable value is changing. + unoptimized_it = unoptimized_dataset.make_initializable_iterator() + with ops.control_dependencies([assign_op]): + unoptimized_output = unoptimized_it.get_next() + optimized_output = optimized_it.get_next() + + self.evaluate(variable.initializer) + self.evaluate((unoptimized_it.initializer, optimized_it.initializer)) + while True: + try: + unoptimized, optimized = self.evaluate((unoptimized_output, + optimized_output)) + self.assertEqual(unoptimized, optimized) + except errors.OutOfRangeError: + break if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/optimization/shuffle_and_repeat_fusion_test.py b/tensorflow/python/data/experimental/kernel_tests/optimization/shuffle_and_repeat_fusion_test.py index 36582f449f..5f746ec63a 100644 --- a/tensorflow/python/data/experimental/kernel_tests/optimization/shuffle_and_repeat_fusion_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/optimization/shuffle_and_repeat_fusion_test.py @@ -18,31 +18,35 @@ from __future__ import division from __future__ import print_function from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.platform import test +@test_util.run_all_in_graph_and_eager_modes class ShuffleAndRepeatFusionTest(test_base.DatasetTestBase): def testShuffleAndRepeatFusion(self): dataset = dataset_ops.Dataset.range(10).apply( optimization.assert_next(["ShuffleAndRepeat"])).shuffle(10).repeat(2) options = dataset_ops.Options() - options.experimental_shuffle_and_repeat_fusion = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.shuffle_and_repeat_fusion = True dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() + get_next = self.getNext(dataset) - with self.cached_session() as sess: - for _ in range(2): - results = [] - for _ in range(10): - results.append(sess.run(get_next)) - self.assertAllEqual([x for x in range(10)], sorted(results)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + for _ in range(2): + results = [] + for _ in range(10): + results.append(self.evaluate(get_next())) + self.assertAllEqual([x for x in range(10)], sorted(results)) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/override_threadpool_test.py b/tensorflow/python/data/experimental/kernel_tests/override_threadpool_test.py index 5e419a9b2f..aa81663a18 100644 --- a/tensorflow/python/data/experimental/kernel_tests/override_threadpool_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/override_threadpool_test.py @@ -22,12 +22,15 @@ import threading from absl.testing import parameterized import numpy as np +from tensorflow.core.framework import graph_pb2 +from tensorflow.python.data.experimental.ops import threading_options from tensorflow.python.data.experimental.ops import threadpool from tensorflow.python.data.experimental.ops import unique from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.ops import script_ops from tensorflow.python.platform import test @@ -35,18 +38,7 @@ from tensorflow.python.platform import test class OverrideThreadpoolTest(test_base.DatasetTestBase, parameterized.TestCase): - @parameterized.named_parameters( - ("1", 1, None), - ("2", 2, None), - ("3", 4, None), - ("4", 8, None), - ("5", 16, None), - ("6", 4, -1), - ("7", 4, 0), - ("8", 4, 1), - ("9", 4, 4), - ) - def testNumThreads(self, num_threads, max_intra_op_parallelism): + def _testNumThreadsHelper(self, num_threads, override_threadpool_fn): def get_thread_id(_): # Python creates a dummy thread object to represent the current @@ -60,32 +52,86 @@ class OverrideThreadpoolTest(test_base.DatasetTestBase, dataset_ops.Dataset.range(1000).map( lambda x: script_ops.py_func(get_thread_id, [x], dtypes.int64), num_parallel_calls=32).apply(unique.unique())) - - dataset = threadpool.override_threadpool( - dataset, - threadpool.PrivateThreadPool( - num_threads, - max_intra_op_parallelism=max_intra_op_parallelism, - display_name="private_thread_pool_%d" % num_threads)) - - iterator = dataset.make_initializable_iterator() + dataset = override_threadpool_fn(dataset) + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) - thread_ids = [] - try: - while True: - thread_ids.append(sess.run(next_element)) - except errors.OutOfRangeError: - pass - self.assertEqual(len(thread_ids), len(set(thread_ids))) - self.assertGreater(len(thread_ids), 0) + self.evaluate(iterator.initializer) + thread_ids = [] + try: + while True: + thread_ids.append(self.evaluate(next_element)) + except errors.OutOfRangeError: + pass + self.assertLen(thread_ids, len(set(thread_ids))) + self.assertNotEmpty(thread_ids) + if num_threads: # NOTE(mrry): We don't control the thread pool scheduling, and # so cannot guarantee that all of the threads in the pool will # perform work. self.assertLessEqual(len(thread_ids), num_threads) + @parameterized.named_parameters( + ("1", 1, None), + ("2", 2, None), + ("3", 4, None), + ("4", 8, None), + ("5", 16, None), + ("6", 4, -1), + ("7", 4, 0), + ("8", 4, 1), + ("9", 4, 4), + ) + @test_util.run_deprecated_v1 + def testNumThreadsDeprecated(self, num_threads, max_intra_op_parallelism): + + def override_threadpool_fn(dataset): + return threadpool.override_threadpool( + dataset, + threadpool.PrivateThreadPool( + num_threads, + max_intra_op_parallelism=max_intra_op_parallelism, + display_name="private_thread_pool_%d" % num_threads)) + + self._testNumThreadsHelper(num_threads, override_threadpool_fn) + + @parameterized.named_parameters( + ("1", 1, None), + ("2", 2, None), + ("3", 4, None), + ("4", 8, None), + ("5", 16, None), + ("6", None, 0), + ("7", None, 1), + ("8", None, 4), + ("9", 4, 0), + ("10", 4, 1), + ("11", 4, 4), + ("12", None, None), + ) + @test_util.run_deprecated_v1 + def testNumThreads(self, num_threads, max_intra_op_parallelism): + + def override_threadpool_fn(dataset): + t_options = threading_options.ThreadingOptions() + if max_intra_op_parallelism is not None: + t_options.max_intra_op_parallelism = max_intra_op_parallelism + if num_threads is not None: + t_options.private_threadpool_size = num_threads + options = dataset_ops.Options() + options.experimental_threading = t_options + return dataset.with_options(options) + + self._testNumThreadsHelper(num_threads, override_threadpool_fn) + + def testMaxIntraOpParallelismAsGraphDefInternal(self): + dataset = dataset_ops.Dataset.from_tensors(0) + dataset = dataset_ops._MaxIntraOpParallelismDataset(dataset, 1) + graph = graph_pb2.GraphDef().FromString( + self.evaluate(dataset._as_serialized_graph())) + self.assertTrue( + any([node.op != "MaxIntraOpParallelismDataset" for node in graph.node])) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/experimental/kernel_tests/parallel_interleave_test.py b/tensorflow/python/data/experimental/kernel_tests/parallel_interleave_test.py index 90ac250df7..113326c028 100644 --- a/tensorflow/python/data/experimental/kernel_tests/parallel_interleave_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/parallel_interleave_test.py @@ -86,7 +86,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self.block_length, self.sloppy, self.buffer_output_elements, self.prefetch_input_elements))) - self.iterator = self.dataset.make_initializable_iterator() + self.iterator = dataset_ops.make_initializable_iterator(self.dataset) self.init_op = self.iterator.initializer self.next_element = self.iterator.get_next() @@ -195,9 +195,9 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): [[4] * 4, [5] * 5, [6] * 6] * self.repeat_count, 1, 1): self.write_coordination_events[expected_element].set() self.assertEqual(expected_element * expected_element, - sess.run(self.next_element)) + self.evaluate(self.next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testSingleThreaded(self): self._testSingleThreaded() @@ -235,10 +235,10 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): for expected_element in self._interleave( [[3] * 3, [7] * 7, [4] * 4] * self.repeat_count, 2, 1): self.write_coordination_events[expected_element].set() - output = sess.run(self.next_element) + output = self.evaluate(self.next_element) self.assertEqual(expected_element * expected_element, output) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def _testTwoThreadsNoContention(self, sloppy=False): # num_threads > 1. @@ -262,7 +262,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self.write_coordination_events[expected_element].set() if done_first_event: # First event starts the worker threads. self.read_coordination_events[expected_element].acquire() - actual_element = sess.run(self.next_element) + actual_element = self.evaluate(self.next_element) if not done_first_event: self.read_coordination_events[expected_element].acquire() done_first_event = True @@ -270,7 +270,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): "At index %s: %s expected, got: %s" % (i, expected_element, actual_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testTwoThreadsNoContention(self): self._testTwoThreadsNoContention() @@ -309,7 +309,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): else: self.write_coordination_events[expected_element].set() time.sleep(0.5) # Sleep to consistently "avoid" the race condition. - actual_element = sess.run(self.next_element) + actual_element = self.evaluate(self.next_element) if not done_first_event: done_first_event = True self.assertTrue( @@ -318,7 +318,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): "At index %s: %s expected, got: %s" % (i, expected_element, actual_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testTwoThreadsNoContentionWithRaces(self): self._testTwoThreadsNoContentionWithRaces() @@ -348,7 +348,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self.write_coordination_events[expected_element].set() if done_first_event: # First event starts the worker threads. self.read_coordination_events[expected_element].acquire() - actual_element = sess.run(self.next_element) + actual_element = self.evaluate(self.next_element) if not done_first_event: done_first_event = True self.read_coordination_events[expected_element].acquire() @@ -356,7 +356,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): "At index %s: %s expected, got: %s" % (i, expected_element, actual_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testTwoThreadsNoContentionBlockLength(self): self._testTwoThreadsNoContentionBlockLength() @@ -396,7 +396,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): else: self.write_coordination_events[expected_element].set() time.sleep(0.5) # Sleep to consistently "avoid" the race condition. - actual_element = sess.run(self.next_element) + actual_element = self.evaluate(self.next_element) if not done_first_event: done_first_event = True self.assertTrue( @@ -405,7 +405,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): "At index %s: %s expected, got: %s" % (i, expected_element, actual_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testTwoThreadsNoContentionWithRacesAndBlocking(self): self._testTwoThreadsNoContentionWithRacesAndBlocking() @@ -428,7 +428,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self.prefetch_input_elements: 0, }) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testEmptyInput(self): self._testEmptyInput() @@ -451,7 +451,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self.prefetch_input_elements: 0, }) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testNonEmptyInputIntoEmptyOutputs(self): self._testNonEmptyInputIntoEmptyOutputs() @@ -484,7 +484,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): # presence of finishing iterators. if done_first_event and not (sloppy and (i in race_indices)): self.read_coordination_events[expected_element].acquire() - actual_element = sess.run(self.next_element) + actual_element = self.evaluate(self.next_element) if not done_first_event or (sloppy and (i in race_indices)): done_first_event = True self.read_coordination_events[expected_element].acquire() @@ -520,10 +520,10 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): ] for element in mis_ordering: self.write_coordination_events[element].set() - self.assertEqual(element * element, sess.run(self.next_element)) + self.assertEqual(element * element, self.evaluate(self.next_element)) self.assertTrue(self.read_coordination_events[element].acquire(False)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testBlockLengthWithContentionSloppy(self): with self.cached_session() as sess: @@ -549,7 +549,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self.write_coordination_events[expected_element].set() if done_first_event: # First event starts the worker threads. self.read_coordination_events[expected_element].acquire() - actual_element = sess.run(self.next_element) + actual_element = self.evaluate(self.next_element) if not done_first_event: self.read_coordination_events[expected_element].acquire() done_first_event = True @@ -557,7 +557,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): "At index %s: %s expected, got: %s" % (i, expected_element, actual_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def _testEarlyExit(self, sloppy=False): # Exiting without consuming all input should not block @@ -575,7 +575,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): }) for i in range(4, 7): self.write_coordination_events[i].set() - elem = sess.run(self.next_element) # Start all workers + elem = self.evaluate(self.next_element) # Start all workers # Allow the one successful worker to progress beyond the py_func again. elem = int(math.sqrt(elem)) self.write_coordination_events[elem].set() @@ -603,12 +603,12 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): dataset = dataset.apply( interleave_ops.parallel_interleave( interleave_fn, cycle_length=16, block_length=2, sloppy=sloppy)) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) with self.cached_session() as sess: output_values = [] for _ in range(30): - output_values.append(sess.run(iterator.get_next())) + output_values.append(self.evaluate(iterator.get_next())) expected_values = self._interleave( [[4] * 4, [5] * 5, [6] * 6] * self.repeat_count, 1, 2) @@ -630,20 +630,19 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): sparse_ops.sparse_to_dense(x.indices, x.dense_shape, x.values)) dataset = dataset_ops.Dataset.range(10).map(_map_fn) - iterator = dataset.apply( - interleave_ops.parallel_interleave( - _interleave_fn, cycle_length=1)).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset.apply( + interleave_ops.parallel_interleave(_interleave_fn, cycle_length=1))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) for i in range(10): for j in range(2): expected = [i, 0] if j % 2 == 0 else [0, -i] - self.assertAllEqual(expected, sess.run(get_next)) + self.assertAllEqual(expected, self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) def testErrorsInOutputFn(self): with self.cached_session() as sess: @@ -668,15 +667,15 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self.error = ValueError() self.write_coordination_events[expected_element].set() with self.assertRaises(errors.InvalidArgumentError): - sess.run(self.next_element) + self.evaluate(self.next_element) else: self.write_coordination_events[expected_element].set() - actual_element = sess.run(self.next_element) + actual_element = self.evaluate(self.next_element) self.assertEqual(expected_element * expected_element, actual_element, "At index %s: %s expected, got: %s" % (i, expected_element, actual_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testErrorsInInputFn(self): @@ -701,7 +700,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self.buffer_output_elements, self.prefetch_input_elements))) - self.iterator = self.dataset.make_initializable_iterator() + self.iterator = dataset_ops.make_initializable_iterator(self.dataset) self.init_op = self.iterator.initializer self.next_element = self.iterator.get_next() @@ -720,14 +719,14 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self._interleave([[4] * 4, [5], [6] * 6] * self.repeat_count, 2, 1)): if expected_element == 5: with self.assertRaises(errors.InvalidArgumentError): - sess.run(self.next_element) + self.evaluate(self.next_element) else: - actual_element = sess.run(self.next_element) + actual_element = self.evaluate(self.next_element) self.assertEqual(expected_element, actual_element, "At index %s: %s expected, got: %s" % (i, expected_element, actual_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testErrorsInInterleaveFn(self): @@ -750,7 +749,7 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self.buffer_output_elements, self.prefetch_input_elements))) - self.iterator = self.dataset.make_initializable_iterator() + self.iterator = dataset_ops.make_initializable_iterator(self.dataset) self.init_op = self.iterator.initializer self.next_element = self.iterator.get_next() @@ -769,14 +768,14 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): self._interleave([[4] * 4, [5], [6] * 6] * self.repeat_count, 2, 1)): if expected_element == 5: with self.assertRaises(errors.InvalidArgumentError): - sess.run(self.next_element) + self.evaluate(self.next_element) else: - actual_element = sess.run(self.next_element) + actual_element = self.evaluate(self.next_element) self.assertEqual(expected_element, actual_element, "At index %s: %s expected, got: %s" % (i, expected_element, actual_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(self.next_element) + self.evaluate(self.next_element) def testShutdownRace(self): dataset = dataset_ops.Dataset.range(20) @@ -789,17 +788,17 @@ class ParallelInterleaveTest(test_base.DatasetTestBase): buffer_output_elements=1, prefetch_input_elements=0)) dataset = dataset.batch(32) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() results = [] with self.cached_session() as sess: for _ in range(2): elements = [] - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) try: while True: - elements.extend(sess.run(next_element)) + elements.extend(self.evaluate(next_element)) except errors.OutOfRangeError: pass results.append(elements) diff --git a/tensorflow/python/data/experimental/kernel_tests/parse_example_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/parse_example_dataset_test.py index c74f754fef..76e0d4d72a 100644 --- a/tensorflow/python/data/experimental/kernel_tests/parse_example_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/parse_example_dataset_test.py @@ -144,6 +144,7 @@ class ParseExampleDatasetTest(test_base.DatasetTestBase): expected_values=expected_output, create_iterator_twice=True) + @test_util.run_deprecated_v1 def testEmptySerializedWithoutDefaultsShouldFail(self): input_features = { "st_a": @@ -177,6 +178,7 @@ class ParseExampleDatasetTest(test_base.DatasetTestBase): expected_err=(errors_impl.InvalidArgumentError, "Feature: c \\(data type: float\\) is required")) + @test_util.run_deprecated_v1 def testDenseNotMatchingShapeShouldFail(self): original = [ example(features=features({ @@ -669,6 +671,7 @@ class ParseExampleDatasetTest(test_base.DatasetTestBase): for batch_size in (1, 10, 20, 100, 256): self._testSerializedContainingVarLenDenseLargerBatch(batch_size) + @test_util.run_deprecated_v1 def testSkipEagerSerializedShapeMismatch(self): aname = "a" bname = "b" @@ -706,6 +709,7 @@ class ParseExampleDatasetTest(test_base.DatasetTestBase): expected_err=(ValueError, "Cannot reshape a tensor with 0 elements to shape")) + @test_util.run_deprecated_v1 def testSerializedContainingVarLenDense(self): aname = "a" bname = "b" diff --git a/tensorflow/python/data/experimental/kernel_tests/prefetch_to_device_test.py b/tensorflow/python/data/experimental/kernel_tests/prefetch_to_device_test.py index f73725366c..80bd43e9ad 100644 --- a/tensorflow/python/data/experimental/kernel_tests/prefetch_to_device_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/prefetch_to_device_test.py @@ -31,17 +31,15 @@ from tensorflow.python.platform import test class PrefetchToDeviceTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testPrefetchToDevice(self): host_dataset = dataset_ops.Dataset.range(10) device_dataset = host_dataset.apply( prefetching_ops.prefetch_to_device("/cpu:1")) - # NOTE(mrry): This device block creates the "host" dataset and iterator on - # /cpu:0, and ensures that the prefetching is across devices. In typical use - # this would not be necessary, because the GPU device would not support any - # of the dataset-related ops. - with ops.device("/cpu:0"): - iterator = device_dataset.make_one_shot_iterator() + with ops.device("/cpu:1"): + iterator = dataset_ops.make_one_shot_iterator(device_dataset) + next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) self.assertEqual(host_dataset.output_types, iterator.output_types) @@ -50,29 +48,26 @@ class PrefetchToDeviceTest(test_base.DatasetTestBase): self.assertEqual(host_dataset.output_classes, device_dataset.output_classes) self.assertEqual(host_dataset.output_classes, iterator.output_classes) - next_element = iterator.get_next() self.assertEqual(dtypes.int64, next_element.dtype) self.assertEqual([], next_element.shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testPrefetchToSameDevice(self): host_dataset = dataset_ops.Dataset.range(10) device_dataset = host_dataset.apply( prefetching_ops.prefetch_to_device( "/job:localhost/replica:0/task:0/device:CPU:0")) - # NOTE(mrry): This device block creates the "host" dataset and iterator on - # /cpu:0, and ensures that the prefetching is across devices. In typical use - # this would not be necessary, because the GPU device would not support any - # of the dataset-related ops. - with ops.device("/cpu:0"): - iterator = device_dataset.make_one_shot_iterator() + with ops.device("/cpu:1"): + iterator = dataset_ops.make_one_shot_iterator(device_dataset) + next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) self.assertEqual(host_dataset.output_types, iterator.output_types) @@ -81,27 +76,24 @@ class PrefetchToDeviceTest(test_base.DatasetTestBase): self.assertEqual(host_dataset.output_classes, device_dataset.output_classes) self.assertEqual(host_dataset.output_classes, iterator.output_classes) - next_element = iterator.get_next() self.assertEqual(dtypes.int64, next_element.dtype) self.assertEqual([], next_element.shape) - with self.cached_session() as sess: + with self.cached_session(): for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testPrefetchDictToDevice(self): host_dataset = dataset_ops.Dataset.range(10).map(lambda x: {"a": x}) device_dataset = host_dataset.apply( prefetching_ops.prefetch_to_device("/cpu:1")) - # NOTE(mrry): This device block creates the "host" dataset and iterator on - # /cpu:0, and ensures that the prefetching is across devices. In typical use - # this would not be necessary, because the GPU device would not support any - # of the dataset-related ops. - with ops.device("/cpu:0"): - iterator = device_dataset.make_one_shot_iterator() + with ops.device("/cpu:1"): + iterator = dataset_ops.make_one_shot_iterator(device_dataset) + next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) self.assertEqual(host_dataset.output_types, iterator.output_types) @@ -110,17 +102,17 @@ class PrefetchToDeviceTest(test_base.DatasetTestBase): self.assertEqual(host_dataset.output_classes, device_dataset.output_classes) self.assertEqual(host_dataset.output_classes, iterator.output_classes) - next_element = iterator.get_next() self.assertEqual(dtypes.int64, next_element["a"].dtype) self.assertEqual([], next_element["a"].shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - self.assertEqual({"a": i}, sess.run(next_element)) + self.assertEqual({"a": i}, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testPrefetchSparseTensorsToDevice(self): def make_tensor(i): return sparse_tensor.SparseTensorValue( @@ -130,12 +122,9 @@ class PrefetchToDeviceTest(test_base.DatasetTestBase): device_dataset = host_dataset.apply( prefetching_ops.prefetch_to_device("/cpu:1")) - # NOTE(mrry): This device block creates the "host" dataset and iterator on - # /cpu:0, and ensures that the prefetching is across devices. In typical use - # this would not be necessary, because the GPU device would not support any - # of the dataset-related ops. - with ops.device("/cpu:0"): - iterator = device_dataset.make_one_shot_iterator() + with ops.device("/cpu:1"): + iterator = dataset_ops.make_one_shot_iterator(device_dataset) + next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) self.assertEqual(host_dataset.output_types, iterator.output_types) @@ -144,18 +133,17 @@ class PrefetchToDeviceTest(test_base.DatasetTestBase): self.assertEqual(host_dataset.output_classes, device_dataset.output_classes) self.assertEqual(host_dataset.output_classes, iterator.output_classes) - next_element = iterator.get_next() self.assertEqual(dtypes.int64, next_element.dtype) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: + with self.test_session(config=worker_config): for i in range(10): - actual = sess.run(next_element) + actual = self.evaluate(next_element) self.assertAllEqual([i], actual.values) self.assertAllEqual([[0, 0]], actual.indices) self.assertAllEqual([2, 2], actual.dense_shape) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testPrefetchToDeviceGpu(self): if not test_util.is_gpu_available(): @@ -165,26 +153,26 @@ class PrefetchToDeviceTest(test_base.DatasetTestBase): device_dataset = host_dataset.apply( prefetching_ops.prefetch_to_device("/gpu:0")) - iterator = device_dataset.make_one_shot_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testPrefetchToDeviceWithReInit(self): host_dataset = dataset_ops.Dataset.range(10) device_dataset = host_dataset.apply( prefetching_ops.prefetch_to_device("/cpu:1")) - # NOTE(mrry): This device block creates the "host" dataset and iterator on - # /cpu:0, and ensures that the prefetching is across devices. In typical use - # this would not be necessary, because the GPU device would not support any - # of the dataset-related ops. - with ops.device("/cpu:0"): - iterator = device_dataset.make_initializable_iterator() + with ops.device("/cpu:1"): + iterator = dataset_ops.make_initializable_iterator(device_dataset) + next_element = iterator.get_next() self.assertEqual(host_dataset.output_types, device_dataset.output_types) self.assertEqual(host_dataset.output_types, iterator.output_types) @@ -193,20 +181,19 @@ class PrefetchToDeviceTest(test_base.DatasetTestBase): self.assertEqual(host_dataset.output_classes, device_dataset.output_classes) self.assertEqual(host_dataset.output_classes, iterator.output_classes) - next_element = iterator.get_next() self.assertEqual(dtypes.int64, next_element.dtype) self.assertEqual([], next_element.shape) worker_config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=worker_config) as sess: - sess.run(iterator.initializer) + with self.test_session(config=worker_config): + self.evaluate(iterator.initializer) for i in range(5): - self.assertEqual(i, sess.run(next_element)) - sess.run(iterator.initializer) + self.assertEqual(i, self.evaluate(next_element)) + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testPrefetchToDeviceGpuWithReInit(self): if not test_util.is_gpu_available(): @@ -216,18 +203,19 @@ class PrefetchToDeviceTest(test_base.DatasetTestBase): device_dataset = host_dataset.apply( prefetching_ops.prefetch_to_device("/gpu:0")) - iterator = device_dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(device_dataset) next_element = iterator.get_next() - with self.cached_session() as sess: - sess.run(iterator.initializer) + with self.cached_session( + config=config_pb2.ConfigProto(allow_soft_placement=False)): + self.evaluate(iterator.initializer) for i in range(5): - self.assertEqual(i, sess.run(next_element)) - sess.run(iterator.initializer) + self.assertEqual(i, self.evaluate(next_element)) + self.evaluate(iterator.initializer) for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/rejection_resample_test.py b/tensorflow/python/data/experimental/kernel_tests/rejection_resample_test.py index 4c879dbae6..76f68f50c8 100644 --- a/tensorflow/python/data/experimental/kernel_tests/rejection_resample_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/rejection_resample_test.py @@ -28,6 +28,7 @@ from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import string_ops @@ -47,7 +48,7 @@ def _time_resampling( initial_dist=init_dist, seed=142)) - get_next = dataset.make_one_shot_iterator().get_next() + get_next = dataset_ops.make_one_shot_iterator(dataset).get_next() with test_obj.test_session() as sess: start_time = time.time() @@ -63,6 +64,7 @@ class RejectionResampleTest(test_base.DatasetTestBase, parameterized.TestCase): @parameterized.named_parameters( ("InitialDistributionKnown", True), ("InitialDistributionUnknown", False)) + @test_util.run_deprecated_v1 def testDistribution(self, initial_known): classes = np.random.randint(5, size=(20000,)) # Uniformly sampled target_dist = [0.9, 0.05, 0.05, 0.0, 0.0] @@ -71,12 +73,12 @@ class RejectionResampleTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = dataset_ops.Dataset.from_tensor_slices(classes).shuffle( 200, seed=21).map(lambda c: (c, string_ops.as_string(c))).repeat() - get_next = dataset.apply( + get_next = dataset_ops.make_one_shot_iterator(dataset.apply( resampling.rejection_resample( target_dist=target_dist, initial_dist=initial_dist, class_func=lambda c, _: c, - seed=27)).make_one_shot_iterator().get_next() + seed=27))).get_next() with self.cached_session() as sess: returned = [] @@ -97,6 +99,7 @@ class RejectionResampleTest(test_base.DatasetTestBase, parameterized.TestCase): @parameterized.named_parameters( ("OnlyInitial", True), ("NotInitial", False)) + @test_util.run_deprecated_v1 def testEdgeCasesSampleFromInitialDataset(self, only_initial_dist): init_dist = [0.5, 0.5] target_dist = [0.5, 0.5] if only_initial_dist else [0.0, 1.0] @@ -114,7 +117,7 @@ class RejectionResampleTest(test_base.DatasetTestBase, parameterized.TestCase): target_dist=target_dist, initial_dist=init_dist)) - get_next = dataset.make_one_shot_iterator().get_next() + get_next = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: returned = [] @@ -122,6 +125,7 @@ class RejectionResampleTest(test_base.DatasetTestBase, parameterized.TestCase): while True: returned.append(sess.run(get_next)) + @test_util.run_deprecated_v1 def testRandomClasses(self): init_dist = [0.25, 0.25, 0.25, 0.25] target_dist = [0.0, 0.0, 0.0, 1.0] @@ -145,7 +149,7 @@ class RejectionResampleTest(test_base.DatasetTestBase, parameterized.TestCase): target_dist=target_dist, initial_dist=init_dist)) - get_next = dataset.make_one_shot_iterator().get_next() + get_next = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: returned = [] diff --git a/tensorflow/python/data/experimental/kernel_tests/restructured_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/restructured_dataset_test.py index 516e489d04..658e6120cf 100644 --- a/tensorflow/python/data/experimental/kernel_tests/restructured_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/restructured_dataset_test.py @@ -22,12 +22,14 @@ from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.util import nest from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test class RestructuredDatasetTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testRestructureDataset(self): components = (array_ops.placeholder(dtypes.int32), (array_ops.placeholder(dtypes.int32, shape=[None]), diff --git a/tensorflow/python/data/experimental/kernel_tests/scan_test.py b/tensorflow/python/data/experimental/kernel_tests/scan_test.py index 0730455431..03af7ecd2f 100644 --- a/tensorflow/python/data/experimental/kernel_tests/scan_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/scan_test.py @@ -40,6 +40,7 @@ class ScanTest(test_base.DatasetTestBase): return dataset_ops.Dataset.from_tensors(0).repeat().apply( scan_ops.scan(start, scan_fn)) + @test_util.run_deprecated_v1 def testCount(self): def make_scan_fn(step): return lambda state, _: (state + step, state) @@ -47,8 +48,8 @@ class ScanTest(test_base.DatasetTestBase): start = array_ops.placeholder(dtypes.int32, shape=[]) step = array_ops.placeholder(dtypes.int32, shape=[]) take = array_ops.placeholder(dtypes.int64, shape=[]) - iterator = self._counting_dataset( - start, make_scan_fn(step)).take(take).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(self._counting_dataset( + start, make_scan_fn(step)).take(take)) next_element = iterator.get_next() with self.cached_session() as sess: @@ -60,15 +61,15 @@ class ScanTest(test_base.DatasetTestBase): feed_dict={start: start_val, step: step_val, take: take_val}) for expected, _ in zip( itertools.count(start_val, step_val), range(take_val)): - self.assertEqual(expected, sess.run(next_element)) + self.assertEqual(expected, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) @test_util.run_in_graph_and_eager_modes def testFibonacci(self): - iterator = dataset_ops.Dataset.from_tensors(1).repeat(None).apply( - scan_ops.scan([0, 1], lambda a, _: ([a[1], a[0] + a[1]], a[1])) - ).make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator( + dataset_ops.Dataset.from_tensors(1).repeat(None).apply( + scan_ops.scan([0, 1], lambda a, _: ([a[1], a[0] + a[1]], a[1])))) if context.executing_eagerly(): next_element = iterator.get_next @@ -83,6 +84,7 @@ class ScanTest(test_base.DatasetTestBase): self.assertEqual(5, self.evaluate(next_element())) self.assertEqual(8, self.evaluate(next_element())) + @test_util.run_deprecated_v1 def testSparseCount(self): def _sparse(i): return sparse_tensor.SparseTensorValue( @@ -96,9 +98,8 @@ class ScanTest(test_base.DatasetTestBase): start = array_ops.placeholder(dtypes.int32, shape=[]) step = array_ops.placeholder(dtypes.int32, shape=[]) take = array_ops.placeholder(dtypes.int64, shape=[]) - iterator = self._counting_dataset( - _sparse(start), - make_scan_fn(step)).take(take).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(self._counting_dataset( + _sparse(start), make_scan_fn(step)).take(take)) next_element = iterator.get_next() with self.cached_session() as sess: @@ -110,10 +111,11 @@ class ScanTest(test_base.DatasetTestBase): feed_dict={start: start_val, step: step_val, take: take_val}) for expected, _ in zip( itertools.count(start_val, step_val), range(take_val)): - self.assertEqual(expected, sess.run(next_element).values[0]) + self.assertEqual(expected, self.evaluate(next_element).values[0]) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testChangingStateShape(self): # Test the fixed-point shape invariant calculations: start with # initial values with known shapes, and use a scan function that @@ -131,16 +133,16 @@ class ScanTest(test_base.DatasetTestBase): self.assertIs(None, dataset.output_shapes[0][1].ndims) self.assertEqual([], dataset.output_shapes[1].as_list()) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) next_element = iterator.get_next() with self.cached_session() as sess: for i in range(5): - (longer_vector_val, larger_rank_val), _ = sess.run(next_element) + (longer_vector_val, larger_rank_val), _ = self.evaluate(next_element) self.assertAllEqual([0] * (2**i), longer_vector_val) self.assertAllEqual(np.array(1, ndmin=i), larger_rank_val) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testIncorrectStateType(self): diff --git a/tensorflow/python/data/experimental/kernel_tests/serialization/BUILD b/tensorflow/python/data/experimental/kernel_tests/serialization/BUILD index 2cfb575903..4a2e28f496 100644 --- a/tensorflow/python/data/experimental/kernel_tests/serialization/BUILD +++ b/tensorflow/python/data/experimental/kernel_tests/serialization/BUILD @@ -74,7 +74,11 @@ py_test( size = "small", srcs = ["checkpoint_input_pipeline_hook_test.py"], srcs_version = "PY2AND3", - tags = ["no_pip"], + tags = [ + "no_pip", + "no_windows", + "notsan", + ], deps = [ "//tensorflow/python:client_testlib", "//tensorflow/python:constant_op", @@ -313,6 +317,7 @@ py_test( srcs_version = "PY2AND3", tags = [ "no_pip", + "no_windows", "notap", ], deps = [ @@ -355,9 +360,13 @@ py_test( size = "small", srcs = ["matching_files_dataset_serialization_test.py"], srcs_version = "PY2AND3", + tags = [ + "no_windows", + ], deps = [ ":dataset_serialization_test_base", "//tensorflow/python:client_testlib", + "//tensorflow/python/data/experimental/ops:matching_files", "//tensorflow/python/data/ops:dataset_ops", "//third_party/py/numpy", ], diff --git a/tensorflow/python/data/experimental/kernel_tests/serialization/checkpoint_input_pipeline_hook_test.py b/tensorflow/python/data/experimental/kernel_tests/serialization/checkpoint_input_pipeline_hook_test.py index 94393d6d4b..8cc66d0c29 100644 --- a/tensorflow/python/data/experimental/kernel_tests/serialization/checkpoint_input_pipeline_hook_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/serialization/checkpoint_input_pipeline_hook_test.py @@ -21,17 +21,18 @@ from __future__ import print_function from tensorflow.python.data.experimental.ops import iterator_ops from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.estimator import estimator -from tensorflow.python.estimator import model_fn from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test from tensorflow.python.training import checkpoint_management from tensorflow.python.training import saver as saver_lib from tensorflow.python.training import training_util +from tensorflow_estimator.python.estimator import estimator +from tensorflow_estimator.python.estimator import model_fn class CheckpointInputPipelineHookTest(test_base.DatasetTestBase): @@ -68,6 +69,7 @@ class CheckpointInputPipelineHookTest(test_base.DatasetTestBase): def _build_iterator_saver_hook(self, est): return iterator_ops.CheckpointInputPipelineHook(est) + @test_util.run_deprecated_v1 def testReturnDatasetFromInputFn(self): def _input_fn(): @@ -80,6 +82,7 @@ class CheckpointInputPipelineHookTest(test_base.DatasetTestBase): est.train(_input_fn, steps=2, hooks=[self._build_iterator_saver_hook(est)]) self.assertSequenceEqual(self._read_vars(est.model_dir), (4, 3)) + @test_util.run_deprecated_v1 def testBuildIteratorInInputFn(self): def _input_fn(): @@ -94,6 +97,7 @@ class CheckpointInputPipelineHookTest(test_base.DatasetTestBase): est.train(_input_fn, steps=2, hooks=[self._build_iterator_saver_hook(est)]) self.assertSequenceEqual(self._read_vars(est.model_dir), (4, 3)) + @test_util.run_deprecated_v1 def testDoNotRestore(self): def _input_fn(): diff --git a/tensorflow/python/data/experimental/kernel_tests/serialization/dataset_serialization_test_base.py b/tensorflow/python/data/experimental/kernel_tests/serialization/dataset_serialization_test_base.py index 7f435b8239..e65aa44d06 100644 --- a/tensorflow/python/data/experimental/kernel_tests/serialization/dataset_serialization_test_base.py +++ b/tensorflow/python/data/experimental/kernel_tests/serialization/dataset_serialization_test_base.py @@ -23,6 +23,7 @@ import os import numpy as np from tensorflow.python.data.experimental.ops import iterator_ops as contrib_iterator_ops +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import iterator_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors @@ -578,7 +579,7 @@ class DatasetSerializationTestBase(test.TestCase): return np.linspace(0, num_outputs, num_samples, dtype=int) def _build_graph(self, ds_fn, sparse_tensors=False): - iterator = ds_fn().make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(ds_fn()) saveable = contrib_iterator_ops.make_saveable_from_iterator(iterator) ops.add_to_collection(ops.GraphKeys.SAVEABLE_OBJECTS, saveable) diff --git a/tensorflow/python/data/experimental/kernel_tests/serialization/filter_dataset_serialization_test.py b/tensorflow/python/data/experimental/kernel_tests/serialization/filter_dataset_serialization_test.py index 225f6cbac0..e3ba8ad231 100644 --- a/tensorflow/python/data/experimental/kernel_tests/serialization/filter_dataset_serialization_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/serialization/filter_dataset_serialization_test.py @@ -17,8 +17,6 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import numpy as np - from tensorflow.python.data.experimental.kernel_tests.serialization import dataset_serialization_test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import sparse_tensor @@ -35,7 +33,7 @@ class FilterDatasetSerializationTest( def testFilterCore(self): div = 3 - num_outputs = np.sum([x % 3 != 2 for x in range(100)]) + num_outputs = sum(x % 3 != 2 for x in range(100)) self.run_core_tests(lambda: self._build_filter_range_graph(div), lambda: self._build_filter_range_graph(div * 2), num_outputs) @@ -47,7 +45,7 @@ class FilterDatasetSerializationTest( lambda d: d["foo"] + d["bar"]) def testFilterDictCore(self): - num_outputs = np.sum([(x**2) % 2 == 0 for x in range(10)]) + num_outputs = sum((x**2) % 2 == 0 for x in range(10)) self.run_core_tests(self._build_filter_dict_graph, None, num_outputs) def _build_sparse_filter(self): diff --git a/tensorflow/python/data/experimental/kernel_tests/serialization/matching_files_dataset_serialization_test.py b/tensorflow/python/data/experimental/kernel_tests/serialization/matching_files_dataset_serialization_test.py index 7edb200d2e..c026e97835 100644 --- a/tensorflow/python/data/experimental/kernel_tests/serialization/matching_files_dataset_serialization_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/serialization/matching_files_dataset_serialization_test.py @@ -22,7 +22,7 @@ import shutil import tempfile from tensorflow.python.data.experimental.kernel_tests.serialization import dataset_serialization_test_base -from tensorflow.python.data.ops.dataset_ops import MatchingFilesDataset +from tensorflow.python.data.experimental.ops import matching_files from tensorflow.python.platform import test @@ -30,7 +30,7 @@ class MatchingFilesDatasetSerializationTest( dataset_serialization_test_base.DatasetSerializationTestBase): def _build_iterator_graph(self, test_patterns): - return MatchingFilesDataset(test_patterns) + return matching_files.MatchingFilesDataset(test_patterns) def testMatchingFilesCore(self): tmp_dir = tempfile.mkdtemp() diff --git a/tensorflow/python/data/experimental/kernel_tests/serialization/range_dataset_serialization_test.py b/tensorflow/python/data/experimental/kernel_tests/serialization/range_dataset_serialization_test.py index ef99d01c73..34419a3149 100644 --- a/tensorflow/python/data/experimental/kernel_tests/serialization/range_dataset_serialization_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/serialization/range_dataset_serialization_test.py @@ -56,8 +56,8 @@ class RangeDatasetSerializationTest( def testSaveRestore(self): def _build_graph(start, stop): - iterator = dataset_ops.Dataset.range(start, - stop).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(start, stop)) init_op = iterator.initializer get_next = iterator.get_next() save_op = self._save_op(iterator._iterator_resource) @@ -71,36 +71,36 @@ class RangeDatasetSerializationTest( with ops.Graph().as_default() as g: init_op, get_next, save_op, _ = _build_graph(start, stop) with self.session(graph=g) as sess: - sess.run(variables.global_variables_initializer()) - sess.run(init_op) + self.evaluate(variables.global_variables_initializer()) + self.evaluate(init_op) for i in range(start, break_point): - self.assertEqual(i, sess.run(get_next)) - sess.run(save_op) + self.assertEqual(i, self.evaluate(get_next)) + self.evaluate(save_op) with ops.Graph().as_default() as g: init_op, get_next, _, restore_op = _build_graph(start, stop) with self.session(graph=g) as sess: - sess.run(init_op) - sess.run(restore_op) + self.evaluate(init_op) + self.evaluate(restore_op) for i in range(break_point, stop): - self.assertEqual(i, sess.run(get_next)) + self.assertEqual(i, self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Saving and restoring in same session. with ops.Graph().as_default() as g: init_op, get_next, save_op, restore_op = _build_graph(start, stop) with self.session(graph=g) as sess: - sess.run(variables.global_variables_initializer()) - sess.run(init_op) + self.evaluate(variables.global_variables_initializer()) + self.evaluate(init_op) for i in range(start, break_point): - self.assertEqual(i, sess.run(get_next)) - sess.run(save_op) - sess.run(restore_op) + self.assertEqual(i, self.evaluate(get_next)) + self.evaluate(save_op) + self.evaluate(restore_op) for i in range(break_point, stop): - self.assertEqual(i, sess.run(get_next)) + self.assertEqual(i, self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) def _build_range_dataset(self, start, stop): return dataset_ops.Dataset.range(start, stop) diff --git a/tensorflow/python/data/experimental/kernel_tests/serialization/serialization_integration_test.py b/tensorflow/python/data/experimental/kernel_tests/serialization/serialization_integration_test.py index 88d5c896c9..12fa0989d0 100644 --- a/tensorflow/python/data/experimental/kernel_tests/serialization/serialization_integration_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/serialization/serialization_integration_test.py @@ -60,9 +60,9 @@ class SerializationIntegrationTest(test.TestCase): init_ops, get_next_ops, saver = self._build_graph(num_pipelines, num_outputs) with self.session(graph=g) as sess: - sess.run(init_ops) + self.evaluate(init_ops) for _ in range(break_point): - output = sess.run(get_next_ops) + output = self.evaluate(get_next_ops) for i in range(num_pipelines): all_outputs[i].append(output[i]) saver.save(sess, self._ckpt_path()) @@ -73,7 +73,7 @@ class SerializationIntegrationTest(test.TestCase): with self.session(graph=g) as sess: saver.restore(sess, self._ckpt_path()) for _ in range(num_outputs - break_point): - output = sess.run(get_next_ops) + output = self.evaluate(get_next_ops) for i in range(num_pipelines): all_outputs[i].append(output[i]) diff --git a/tensorflow/python/data/experimental/kernel_tests/serialization/shuffle_dataset_serialization_test.py b/tensorflow/python/data/experimental/kernel_tests/serialization/shuffle_dataset_serialization_test.py index a04f1ddafc..e753a7a15b 100644 --- a/tensorflow/python/data/experimental/kernel_tests/serialization/shuffle_dataset_serialization_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/serialization/shuffle_dataset_serialization_test.py @@ -138,9 +138,9 @@ class ShuffleDatasetSerializationTest( saver = saver_lib.Saver(allow_empty=True) with self.session(graph=g) as sess: self._save(sess, saver) - expected = [sess.run(get_next_ops) for _ in range(num_outputs)] + expected = [self.evaluate(get_next_ops) for _ in range(num_outputs)] self._restore(saver, sess) - actual = [sess.run(get_next_ops) for _ in range(num_outputs)] + actual = [self.evaluate(get_next_ops) for _ in range(num_outputs)] self.match(expected, actual) diff --git a/tensorflow/python/data/experimental/kernel_tests/shuffle_and_repeat_test.py b/tensorflow/python/data/experimental/kernel_tests/shuffle_and_repeat_test.py index c208963a86..9528f83291 100644 --- a/tensorflow/python/data/experimental/kernel_tests/shuffle_and_repeat_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/shuffle_and_repeat_test.py @@ -24,6 +24,7 @@ from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -34,16 +35,17 @@ class ShuffleAndRepeatTest(test_base.DatasetTestBase): shuffle_ops.shuffle_and_repeat(buffer_size=5, count=count, seed=seed)) def _gen_outputs(self, ds_fn, num_outputs, verify_exhausted=True): - get_next = ds_fn().make_one_shot_iterator().get_next() + get_next = dataset_ops.make_one_shot_iterator(ds_fn()).get_next() outputs = [] with self.cached_session() as sess: for _ in range(num_outputs): - outputs.append(sess.run(get_next)) + outputs.append(self.evaluate(get_next)) if verify_exhausted: with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) return outputs + @test_util.run_deprecated_v1 def testCorrectOutput(self): output = self._gen_outputs(lambda: self._build_ds(10), 100) self.assertSequenceEqual( @@ -52,6 +54,7 @@ class ShuffleAndRepeatTest(test_base.DatasetTestBase): for i in range(5): self.assertSequenceEqual(sorted(output[i * 20:(i + 1) * 20]), range(20)) + @test_util.run_deprecated_v1 def testReshuffling(self): # Check that the output orders of different epochs are indeed different. output = self._gen_outputs(lambda: self._build_ds(10), 100) @@ -60,17 +63,20 @@ class ShuffleAndRepeatTest(test_base.DatasetTestBase): epoch2 = output[(i + 1) * 20:(i + 2) * 20] self.assertNotEqual(epoch1, epoch2) + @test_util.run_deprecated_v1 def testSameOrderForSameSeeds(self): output1 = self._gen_outputs(lambda: self._build_ds(10), 100) output2 = self._gen_outputs(lambda: self._build_ds(10), 100) self.assertEqual(output1, output2) + @test_util.run_deprecated_v1 def testDifferentOrderForDifferentSeeds(self): output1 = self._gen_outputs(lambda: self._build_ds(10), 100) output2 = self._gen_outputs(lambda: self._build_ds(20), 100) self.assertNotEqual(output1, output2) self.assertEqual(sorted(output1), sorted(output2)) + @test_util.run_deprecated_v1 def testCountNone(self): output1 = self._gen_outputs( lambda: self._build_ds(10, count=None), 100, verify_exhausted=False) @@ -79,6 +85,7 @@ class ShuffleAndRepeatTest(test_base.DatasetTestBase): self.assertNotEqual(output1, output2) self.assertEqual(sorted(output1), sorted(output2)) + @test_util.run_deprecated_v1 def testCountMinusOne(self): output1 = self._gen_outputs( lambda: self._build_ds(10, count=-1), 100, verify_exhausted=False) @@ -108,7 +115,7 @@ class ShuffleAndRepeatTest(test_base.DatasetTestBase): shuffle_ops.shuffle_and_repeat(buffer_size=21)) get_next_op = ds.make_one_shot_iterator().get_next() with self.session(graph=g) as sess: - sess.run(get_next_op) + self.evaluate(get_next_op) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/sleep_test.py b/tensorflow/python/data/experimental/kernel_tests/sleep_test.py index bf53acc82a..46b22f80b6 100644 --- a/tensorflow/python/data/experimental/kernel_tests/sleep_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/sleep_test.py @@ -23,6 +23,7 @@ from tensorflow.python.data.experimental.ops import sleep from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.platform import test _NUMPY_RANDOM_SEED = 42 @@ -30,22 +31,23 @@ _NUMPY_RANDOM_SEED = 42 class SleepTest(test_base.DatasetTestBase): + @test_util.run_deprecated_v1 def testSleep(self): sleep_microseconds = 100 dataset = dataset_ops.Dataset.range(10).apply( sleep.sleep(sleep_microseconds)) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() with self.cached_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) start_time = time.time() for i in range(10): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) end_time = time.time() self.assertGreater(end_time - start_time, (10 * sleep_microseconds) / 1e6) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/sql_dataset_test.py b/tensorflow/python/data/experimental/kernel_tests/sql_dataset_test.py index a2c1169638..eb66927ee5 100644 --- a/tensorflow/python/data/experimental/kernel_tests/sql_dataset_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/sql_dataset_test.py @@ -39,10 +39,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ORDER BY first_name DESC" }) for _ in range(2): # Dataset is repeated. See setUp. - self.assertEqual((b"John", b"Doe", b"Hi!"), sess.run(get_next)) - self.assertEqual((b"Jane", b"Moe", b"Hi again!"), sess.run(get_next)) + self.assertEqual((b"John", b"Doe", b"Hi!"), self.evaluate(get_next)) + self.assertEqual((b"Jane", b"Moe", b"Hi again!"), + self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that SqlDataset works on a join query. def testReadResultSetJoinQuery(self): @@ -58,9 +59,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ON students.first_name = people.first_name " "AND students.last_name = people.last_name" }) - self.assertEqual((b"John", b"California", b"Hi!"), sess.run(get_next)) + self.assertEqual((b"John", b"California", b"Hi!"), + self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that SqlDataset can read a database entry with a null-terminator # in the middle of the text and place the entry in a `string` tensor. @@ -75,10 +77,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "SELECT first_name, last_name, favorite_nonsense_word " "FROM students ORDER BY first_name DESC" }) - self.assertEqual((b"John", b"Doe", b"n\0nsense"), sess.run(get_next)) - self.assertEqual((b"Jane", b"Moe", b"nonsense\0"), sess.run(get_next)) + self.assertEqual((b"John", b"Doe", b"n\0nsense"), self.evaluate(get_next)) + self.assertEqual((b"Jane", b"Moe", b"nonsense\0"), + self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that SqlDataset works when used on two different queries. # Because the output types of the dataset must be determined at graph-creation @@ -93,21 +96,22 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, last_name, motto FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", b"Doe", b"Hi!"), sess.run(get_next)) - self.assertEqual((b"Jane", b"Moe", b"Hi again!"), sess.run(get_next)) + self.assertEqual((b"John", b"Doe", b"Hi!"), self.evaluate(get_next)) + self.assertEqual((b"Jane", b"Moe", b"Hi again!"), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) sess.run( init_op, feed_dict={ self.query: "SELECT first_name, last_name, state FROM people " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", b"Doe", b"California"), sess.run(get_next)) + self.assertEqual((b"John", b"Doe", b"California"), + self.evaluate(get_next)) self.assertEqual((b"Benjamin", b"Franklin", b"Pennsylvania"), - sess.run(get_next)) + self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that an `OutOfRangeError` is raised on the first call to # `get_next_str_only` if result set is empty. @@ -122,7 +126,7 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "WHERE first_name = 'Nonexistent'" }) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that an error is raised when `driver_name` is invalid. def testReadResultSetWithInvalidDriverName(self): @@ -151,7 +155,7 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ORDER BY first_name DESC" }) with self.assertRaises(errors.UnknownError): - sess.run(get_next) + self.evaluate(get_next) # Test that an error is raised when there is a syntax error in `query`. def testReadResultSetOfQueryWithSyntaxError(self): @@ -166,7 +170,7 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ORDER BY first_name DESC" }) with self.assertRaises(errors.UnknownError): - sess.run(get_next) + self.evaluate(get_next) # Test that an error is raised when the number of columns in `query` # does not match the length of `output_types`. @@ -181,7 +185,7 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ORDER BY first_name DESC" }) with self.assertRaises(errors.InvalidArgumentError): - sess.run(get_next) + self.evaluate(get_next) # Test that no results are returned when `query` is an insert query rather # than a select query. In particular, the error refers to the number of @@ -199,7 +203,7 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "VALUES ('Foo', 'Bar', 'Baz'), ('Fizz', 'Buzz', 'Fizzbuzz')" }) with self.assertRaises(errors.InvalidArgumentError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read an integer from a SQLite database table and # place it in an `int8` tensor. @@ -212,10 +216,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, desk_number FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", 9), sess.run(get_next)) - self.assertEqual((b"Jane", 127), sess.run(get_next)) + self.assertEqual((b"John", 9), self.evaluate(get_next)) + self.assertEqual((b"Jane", 127), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a negative or 0-valued integer from a # SQLite database table and place it in an `int8` tensor. @@ -230,9 +234,9 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "FROM students " "WHERE first_name = 'John' ORDER BY first_name DESC" }) - self.assertEqual((b"John", 0, -2), sess.run(get_next)) + self.assertEqual((b"John", 0, -2), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a large (positive or negative) integer from # a SQLite database table and place it in an `int8` tensor. @@ -246,11 +250,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "SELECT desk_number, favorite_negative_number FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((9, -2), sess.run(get_next)) + self.assertEqual((9, -2), self.evaluate(get_next)) # Max and min values of int8 - self.assertEqual((127, -128), sess.run(get_next)) + self.assertEqual((127, -128), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read an integer from a SQLite database table and # place it in an `int16` tensor. @@ -263,10 +267,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, desk_number FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", 9), sess.run(get_next)) - self.assertEqual((b"Jane", 127), sess.run(get_next)) + self.assertEqual((b"John", 9), self.evaluate(get_next)) + self.assertEqual((b"Jane", 127), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a negative or 0-valued integer from a # SQLite database table and place it in an `int16` tensor. @@ -281,9 +285,9 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "FROM students " "WHERE first_name = 'John' ORDER BY first_name DESC" }) - self.assertEqual((b"John", 0, -2), sess.run(get_next)) + self.assertEqual((b"John", 0, -2), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a large (positive or negative) integer from # a SQLite database table and place it in an `int16` tensor. @@ -297,11 +301,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "FROM students ORDER BY first_name DESC" }) # Max value of int16 - self.assertEqual((b"John", 32767), sess.run(get_next)) + self.assertEqual((b"John", 32767), self.evaluate(get_next)) # Min value of int16 - self.assertEqual((b"Jane", -32768), sess.run(get_next)) + self.assertEqual((b"Jane", -32768), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read an integer from a SQLite database table and # place it in an `int32` tensor. @@ -314,8 +318,8 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, desk_number FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", 9), sess.run(get_next)) - self.assertEqual((b"Jane", 127), sess.run(get_next)) + self.assertEqual((b"John", 9), self.evaluate(get_next)) + self.assertEqual((b"Jane", 127), self.evaluate(get_next)) # Test that `SqlDataset` can read a negative or 0-valued integer from a # SQLite database table and place it in an `int32` tensor. @@ -328,10 +332,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, income FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", 0), sess.run(get_next)) - self.assertEqual((b"Jane", -20000), sess.run(get_next)) + self.assertEqual((b"John", 0), self.evaluate(get_next)) + self.assertEqual((b"Jane", -20000), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a large (positive or negative) integer from # a SQLite database table and place it in an `int32` tensor. @@ -345,11 +349,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ORDER BY first_name DESC" }) # Max value of int32 - self.assertEqual((b"John", 2147483647), sess.run(get_next)) + self.assertEqual((b"John", 2147483647), self.evaluate(get_next)) # Min value of int32 - self.assertEqual((b"Jane", -2147483648), sess.run(get_next)) + self.assertEqual((b"Jane", -2147483648), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a numeric `varchar` from a SQLite database # table and place it in an `int32` tensor. @@ -362,10 +366,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, school_id FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", 123), sess.run(get_next)) - self.assertEqual((b"Jane", 1000), sess.run(get_next)) + self.assertEqual((b"John", 123), self.evaluate(get_next)) + self.assertEqual((b"Jane", 1000), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read an integer from a SQLite database table # and place it in an `int64` tensor. @@ -378,10 +382,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, desk_number FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", 9), sess.run(get_next)) - self.assertEqual((b"Jane", 127), sess.run(get_next)) + self.assertEqual((b"John", 9), self.evaluate(get_next)) + self.assertEqual((b"Jane", 127), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a negative or 0-valued integer from a # SQLite database table and place it in an `int64` tensor. @@ -394,10 +398,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, income FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", 0), sess.run(get_next)) - self.assertEqual((b"Jane", -20000), sess.run(get_next)) + self.assertEqual((b"John", 0), self.evaluate(get_next)) + self.assertEqual((b"Jane", -20000), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a large (positive or negative) integer from # a SQLite database table and place it in an `int64` tensor. @@ -412,11 +416,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ORDER BY first_name DESC" }) # Max value of int64 - self.assertEqual((b"John", 9223372036854775807), sess.run(get_next)) + self.assertEqual((b"John", 9223372036854775807), self.evaluate(get_next)) # Min value of int64 - self.assertEqual((b"Jane", -9223372036854775808), sess.run(get_next)) + self.assertEqual((b"Jane", -9223372036854775808), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read an integer from a SQLite database table and # place it in a `uint8` tensor. @@ -429,10 +433,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, desk_number FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", 9), sess.run(get_next)) - self.assertEqual((b"Jane", 127), sess.run(get_next)) + self.assertEqual((b"John", 9), self.evaluate(get_next)) + self.assertEqual((b"Jane", 127), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read the minimum and maximum uint8 values from a # SQLite database table and place them in `uint8` tensors. @@ -446,11 +450,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ORDER BY first_name DESC" }) # Min value of uint8 - self.assertEqual((b"John", 0), sess.run(get_next)) + self.assertEqual((b"John", 0), self.evaluate(get_next)) # Max value of uint8 - self.assertEqual((b"Jane", 255), sess.run(get_next)) + self.assertEqual((b"Jane", 255), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read an integer from a SQLite database table # and place it in a `uint16` tensor. @@ -463,10 +467,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, desk_number FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", 9), sess.run(get_next)) - self.assertEqual((b"Jane", 127), sess.run(get_next)) + self.assertEqual((b"John", 9), self.evaluate(get_next)) + self.assertEqual((b"Jane", 127), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read the minimum and maximum uint16 values from a # SQLite database table and place them in `uint16` tensors. @@ -480,11 +484,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ORDER BY first_name DESC" }) # Min value of uint16 - self.assertEqual((b"John", 0), sess.run(get_next)) + self.assertEqual((b"John", 0), self.evaluate(get_next)) # Max value of uint16 - self.assertEqual((b"Jane", 65535), sess.run(get_next)) + self.assertEqual((b"Jane", 65535), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a 0-valued and 1-valued integer from a # SQLite database table and place them as `True` and `False` respectively @@ -499,10 +503,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "SELECT first_name, registration_complete FROM students " "ORDER BY first_name DESC" }) - self.assertEqual((b"John", True), sess.run(get_next)) - self.assertEqual((b"Jane", False), sess.run(get_next)) + self.assertEqual((b"John", True), self.evaluate(get_next)) + self.assertEqual((b"Jane", False), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read an integer that is not 0-valued or 1-valued # from a SQLite database table and place it as `True` in a `bool` tensor. @@ -515,10 +519,10 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.query: "SELECT first_name, favorite_medium_sized_number " "FROM students ORDER BY first_name DESC" }) - self.assertEqual((b"John", True), sess.run(get_next)) - self.assertEqual((b"Jane", True), sess.run(get_next)) + self.assertEqual((b"John", True), self.evaluate(get_next)) + self.assertEqual((b"Jane", True), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a float from a SQLite database table # and place it in a `float64` tensor. @@ -533,10 +537,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "SELECT first_name, last_name, victories FROM townspeople " "ORDER BY first_name" }) - self.assertEqual((b"George", b"Washington", 20.0), sess.run(get_next)) - self.assertEqual((b"John", b"Adams", -19.95), sess.run(get_next)) + self.assertEqual((b"George", b"Washington", 20.0), + self.evaluate(get_next)) + self.assertEqual((b"John", b"Adams", -19.95), self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a float from a SQLite database table beyond # the precision of 64-bit IEEE, without throwing an error. Test that @@ -555,13 +560,13 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): self.assertEqual( (b"George", b"Washington", 1331241.321342132321324589798264627463827647382647382643874), - sess.run(get_next)) + self.evaluate(get_next)) self.assertEqual( (b"John", b"Adams", 1331241321342132321324589798264627463827647382647382643874.0), - sess.run(get_next)) + self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) # Test that `SqlDataset` can read a float from a SQLite database table, # representing the largest integer representable as a 64-bit IEEE float @@ -579,11 +584,11 @@ class SqlDatasetTest(sql_dataset_test_base.SqlDatasetTestBase): "ORDER BY first_name" }) self.assertNotEqual((b"George", b"Washington", 9007199254740992.0), - sess.run(get_next)) + self.evaluate(get_next)) self.assertNotEqual((b"John", b"Adams", 9007199254740991.0), - sess.run(get_next)) + self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + self.evaluate(get_next) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/sql_dataset_test_base.py b/tensorflow/python/data/experimental/kernel_tests/sql_dataset_test_base.py index 6aaaa90c65..809e09c804 100644 --- a/tensorflow/python/data/experimental/kernel_tests/sql_dataset_test_base.py +++ b/tensorflow/python/data/experimental/kernel_tests/sql_dataset_test_base.py @@ -24,6 +24,7 @@ import sqlite3 from tensorflow.python.data.experimental.ops import readers from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes from tensorflow.python.ops import array_ops from tensorflow.python.platform import test @@ -35,7 +36,7 @@ class SqlDatasetTestBase(test_base.DatasetTestBase): def _createSqlDataset(self, output_types, num_repeats=1): dataset = readers.SqlDataset(self.driver_name, self.data_source_name, self.query, output_types).repeat(num_repeats) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() return init_op, get_next diff --git a/tensorflow/python/data/experimental/kernel_tests/stats_dataset_ops_test.py b/tensorflow/python/data/experimental/kernel_tests/stats_dataset_ops_test.py index 83028937d3..8a300364f9 100644 --- a/tensorflow/python/data/experimental/kernel_tests/stats_dataset_ops_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/stats_dataset_ops_test.py @@ -30,6 +30,7 @@ from tensorflow.python.data.experimental.ops import stats_options from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -45,84 +46,84 @@ def function_set_stats_aggregator(dataset, def function_apply_options(dataset, aggregator, prefix="", counter_prefix=""): options = dataset_ops.Options() - options.experimental_stats = stats_options.StatsOptions(aggregator) + options.experimental_stats = stats_options.StatsOptions() + options.experimental_stats.aggregator = aggregator + options.experimental_stats.prefix = prefix + options.experimental_stats.counter_prefix = counter_prefix options.experimental_stats.latency_all_edges = False - if prefix: - options.experimental_stats.prefix = prefix - if counter_prefix: - options.experimental_stats.counter_prefix = counter_prefix return dataset.with_options(options) @parameterized.named_parameters( - dict( - testcase_name="SetStatsAggregator", - dataset_transformation=function_set_stats_aggregator), - dict( - testcase_name="StatsOptions", - dataset_transformation=function_apply_options)) + ("SetStatsAggregator", function_set_stats_aggregator), + ("StatsOptions", function_apply_options), +) class StatsDatasetTest(stats_dataset_test_base.StatsDatasetTestBase): + @test_util.run_deprecated_v1 def testBytesProduced(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(100).map( lambda x: array_ops.tile([x], ops.convert_to_tensor([x]))).apply( stats_ops.bytes_produced_stats("bytes_produced")) dataset = dataset_transformation(dataset, aggregator) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() with self.cached_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) expected_sum = 0.0 for i in range(100): self.assertAllEqual( - np.array([i] * i, dtype=np.int64), sess.run(next_element)) - summary_str = sess.run(summary_t) + np.array([i] * i, dtype=np.int64), self.evaluate(next_element)) + summary_str = self.evaluate(summary_t) self._assertSummaryHasCount(summary_str, "bytes_produced", float(i + 1)) expected_sum += i * 8.0 self._assertSummaryHasSum(summary_str, "bytes_produced", expected_sum) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - summary_str = sess.run(summary_t) + self.evaluate(next_element) + summary_str = self.evaluate(summary_t) self._assertSummaryHasCount(summary_str, "bytes_produced", 100.0) self._assertSummaryHasSum(summary_str, "bytes_produced", expected_sum) + @test_util.run_deprecated_v1 def testLatencyStats(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(100).apply( stats_ops.latency_stats("record_latency")) dataset = dataset_transformation(dataset, aggregator) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() with self.cached_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for i in range(100): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) self._assertSummaryHasCount( - sess.run(summary_t), "record_latency", float(i + 1)) + self.evaluate(summary_t), "record_latency", float(i + 1)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - self._assertSummaryHasCount(sess.run(summary_t), "record_latency", 100.0) + self.evaluate(next_element) + self._assertSummaryHasCount( + self.evaluate(summary_t), "record_latency", 100.0) + @test_util.run_deprecated_v1 def testPrefetchBufferUtilization(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(100).map( lambda x: array_ops.tile([x], ops.convert_to_tensor([x]))).prefetch(-1) dataset = dataset_transformation(dataset, aggregator) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() with self.cached_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for i in range(100): self.assertAllEqual( - np.array([i] * i, dtype=np.int64), sess.run(next_element)) - summary_str = sess.run(summary_t) + np.array([i] * i, dtype=np.int64), self.evaluate(next_element)) + summary_str = self.evaluate(summary_t) self._assertSummaryHasCount(summary_str, "Prefetch::buffer_utilization", float(i + 1)) self._assertSummaryContains(summary_str, "Prefetch::buffer_capacity") @@ -130,58 +131,62 @@ class StatsDatasetTest(stats_dataset_test_base.StatsDatasetTestBase): self._assertSummaryHasRange(summary_str, "Prefetch::buffer_utilization", 0, 1) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - summary_str = sess.run(summary_t) + self.evaluate(next_element) + summary_str = self.evaluate(summary_t) self._assertSummaryHasCount(summary_str, "Prefetch::buffer_utilization", 100) + @test_util.run_deprecated_v1 def testPrefetchBufferScalars(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(10).map( lambda x: array_ops.tile([x], ops.convert_to_tensor([x]))).prefetch(0) dataset = dataset_transformation(dataset, aggregator) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() with self.cached_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for i in range(10): self.assertAllEqual( - np.array([i] * i, dtype=np.int64), sess.run(next_element)) - summary_str = sess.run(summary_t) + np.array([i] * i, dtype=np.int64), self.evaluate(next_element)) + summary_str = self.evaluate(summary_t) self._assertSummaryHasScalarValue(summary_str, "Prefetch::buffer_capacity", 0) self._assertSummaryHasScalarValue(summary_str, "Prefetch::buffer_size", 0) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testFilteredElementsStats(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(101).filter( lambda x: math_ops.equal(math_ops.mod(x, 3), 0)) dataset = dataset_transformation(dataset, aggregator) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() with self.test_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for i in range(34): - self.assertEqual(i * 3, sess.run(next_element)) + self.assertEqual(i * 3, self.evaluate(next_element)) if i is not 0: self._assertSummaryHasScalarValue( - sess.run(summary_t), "Filter::dropped_elements", float(i * 2)) + self.evaluate(summary_t), "Filter::dropped_elements", + float(i * 2)) self._assertSummaryHasScalarValue( - sess.run(summary_t), "Filter::filtered_elements", float(i + 1)) + self.evaluate(summary_t), "Filter::filtered_elements", float(i + 1)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) self._assertSummaryHasScalarValue( - sess.run(summary_t), "Filter::dropped_elements", 67.0) + self.evaluate(summary_t), "Filter::dropped_elements", 67.0) self._assertSummaryHasScalarValue( - sess.run(summary_t), "Filter::filtered_elements", 34.0) + self.evaluate(summary_t), "Filter::filtered_elements", 34.0) + @test_util.run_deprecated_v1 def testMapBufferUtilization(self, dataset_transformation): def dataset_fn(): @@ -196,6 +201,7 @@ class StatsDatasetTest(stats_dataset_test_base.StatsDatasetTestBase): dataset_transformation, function_processing_time=True) + @test_util.run_deprecated_v1 def testMapAutoTuneBufferUtilization(self, dataset_transformation): def dataset_fn(): @@ -213,6 +219,7 @@ class StatsDatasetTest(stats_dataset_test_base.StatsDatasetTestBase): dataset_transformation, function_processing_time=True) + @test_util.run_deprecated_v1 def testInterleaveAutoTuneBufferUtilization(self, dataset_transformation): def dataset_fn(): @@ -229,6 +236,7 @@ class StatsDatasetTest(stats_dataset_test_base.StatsDatasetTestBase): self._testParallelCallsStats(dataset_fn, "ParallelInterleaveV2", 10, dataset_transformation) + @test_util.run_deprecated_v1 def testMapAndBatchAutoTuneBufferUtilization(self, dataset_transformation): def dataset_fn(): @@ -250,104 +258,114 @@ class StatsDatasetTest(stats_dataset_test_base.StatsDatasetTestBase): check_elements=False, function_processing_time=True) + @test_util.run_deprecated_v1 def testReinitialize(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(100).apply( stats_ops.latency_stats("record_latency")) dataset = dataset_transformation(dataset, aggregator) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() with self.cached_session() as sess: for j in range(5): - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for i in range(100): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) self._assertSummaryHasCount( - sess.run(summary_t), "record_latency", float((j * 100) + i + 1)) + self.evaluate(summary_t), "record_latency", + float((j * 100) + i + 1)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) self._assertSummaryHasCount( - sess.run(summary_t), "record_latency", (j + 1) * 100.0) + self.evaluate(summary_t), "record_latency", (j + 1) * 100.0) + @test_util.run_deprecated_v1 def testNoAggregatorRegistered(self, dataset_transformation): dataset = dataset_ops.Dataset.range(100).apply( stats_ops.latency_stats("record_latency")) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() with self.cached_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for i in range(100): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testMultipleTags(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(100).apply( stats_ops.latency_stats("record_latency")).apply( stats_ops.latency_stats("record_latency_2")) dataset = dataset_transformation(dataset, aggregator) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() with self.cached_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for i in range(100): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) self._assertSummaryHasCount( - sess.run(summary_t), "record_latency", float(i + 1)) + self.evaluate(summary_t), "record_latency", float(i + 1)) self._assertSummaryHasCount( - sess.run(summary_t), "record_latency_2", float(i + 1)) + self.evaluate(summary_t), "record_latency_2", float(i + 1)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - self._assertSummaryHasCount(sess.run(summary_t), "record_latency", 100.0) + self.evaluate(next_element) + self._assertSummaryHasCount( + self.evaluate(summary_t), "record_latency", 100.0) self._assertSummaryHasCount( - sess.run(summary_t), "record_latency_2", 100.0) + self.evaluate(summary_t), "record_latency_2", 100.0) + @test_util.run_deprecated_v1 def testRepeatedTags(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(100).apply( stats_ops.latency_stats("record_latency")).apply( stats_ops.latency_stats("record_latency")) dataset = dataset_transformation(dataset, aggregator) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() with self.cached_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for i in range(100): - self.assertEqual(i, sess.run(next_element)) + self.assertEqual(i, self.evaluate(next_element)) self._assertSummaryHasCount( - sess.run(summary_t), "record_latency", float(2 * (i + 1))) + self.evaluate(summary_t), "record_latency", float(2 * (i + 1))) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - self._assertSummaryHasCount(sess.run(summary_t), "record_latency", 200.0) + self.evaluate(next_element) + self._assertSummaryHasCount( + self.evaluate(summary_t), "record_latency", 200.0) + @test_util.run_deprecated_v1 def testMultipleIteratorsSameAggregator(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(100).apply( stats_ops.latency_stats("record_latency")) dataset = dataset_transformation(dataset, aggregator) - iterator_0 = dataset.make_initializable_iterator() - iterator_1 = dataset.make_initializable_iterator() + iterator_0 = dataset_ops.make_initializable_iterator(dataset) + iterator_1 = dataset_ops.make_initializable_iterator(dataset) next_element = iterator_0.get_next() + iterator_1.get_next() summary_t = aggregator.get_summary() with self.cached_session() as sess: - sess.run([iterator_0.initializer, iterator_1.initializer]) + self.evaluate([iterator_0.initializer, iterator_1.initializer]) for i in range(100): - self.assertEqual(i * 2, sess.run(next_element)) + self.assertEqual(i * 2, self.evaluate(next_element)) self._assertSummaryHasCount( - sess.run(summary_t), "record_latency", float(2 * (i + 1))) + self.evaluate(summary_t), "record_latency", float(2 * (i + 1))) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - self._assertSummaryHasCount(sess.run(summary_t), "record_latency", 200.0) + self.evaluate(next_element) + self._assertSummaryHasCount( + self.evaluate(summary_t), "record_latency", 200.0) + @test_util.run_deprecated_v1 def testMultipleDatasetWithPrefixes(self, dataset_transformation): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_ops.Dataset.range(100).apply( @@ -356,25 +374,25 @@ class StatsDatasetTest(stats_dataset_test_base.StatsDatasetTestBase): dataset2 = dataset_ops.Dataset.range(100).apply( stats_ops.latency_stats("record_latency")) dataset2 = dataset_transformation(dataset2, aggregator, prefix="dataset2") - iterator_0 = dataset.make_initializable_iterator() - iterator_1 = dataset2.make_initializable_iterator() + iterator_0 = dataset_ops.make_initializable_iterator(dataset) + iterator_1 = dataset_ops.make_initializable_iterator(dataset2) next_element = iterator_0.get_next() + iterator_1.get_next() summary_t = aggregator.get_summary() with self.test_session() as sess: - sess.run([iterator_0.initializer, iterator_1.initializer]) + self.evaluate([iterator_0.initializer, iterator_1.initializer]) for i in range(100): - self.assertEqual(i * 2, sess.run(next_element)) + self.assertEqual(i * 2, self.evaluate(next_element)) self._assertSummaryHasCount( - sess.run(summary_t), "dataset1_record_latency", float(i + 1)) + self.evaluate(summary_t), "dataset1_record_latency", float(i + 1)) self._assertSummaryHasCount( - sess.run(summary_t), "dataset2_record_latency", float(i + 1)) + self.evaluate(summary_t), "dataset2_record_latency", float(i + 1)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) self._assertSummaryHasCount( - sess.run(summary_t), "dataset1_record_latency", 100.0) + self.evaluate(summary_t), "dataset1_record_latency", 100.0) self._assertSummaryHasCount( - sess.run(summary_t), "dataset2_record_latency", 100.0) + self.evaluate(summary_t), "dataset2_record_latency", 100.0) @parameterized.named_parameters( @@ -388,6 +406,7 @@ class FeatureStatsDatasetTest( stats_dataset_test_base.StatsDatasetTestBase, reader_dataset_ops_test_base.MakeBatchedFeaturesDatasetTestBase): + @test_util.run_deprecated_v1 def testFeaturesStats(self, dataset_transformation): num_epochs = 5 total_records = num_epochs * self._num_records @@ -416,25 +435,26 @@ class FeatureStatsDatasetTest( dataset = dataset_transformation( dataset_fn(), aggregator, prefix="record_stats") - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() with self.test_session() as sess: - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for _ in range(num_output): - sess.run(next_element) + self.evaluate(next_element) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) self._assertSummaryHasCount( - sess.run(summary_t), "record_stats_features", total_records) + self.evaluate(summary_t), "record_stats_features", total_records) self._assertSummaryHasCount( - sess.run(summary_t), "record_stats_feature-values", total_records) + self.evaluate(summary_t), "record_stats_feature-values", + total_records) self._assertSummaryHasSum( - sess.run(summary_t), "record_stats_features", total_records * 4) + self.evaluate(summary_t), "record_stats_features", total_records * 4) self._assertSummaryHasSum( - sess.run(summary_t), "record_stats_feature-values", + self.evaluate(summary_t), "record_stats_feature-values", self._sum_keywords(1) * num_epochs + 3 * total_records) diff --git a/tensorflow/python/data/experimental/kernel_tests/stats_dataset_test_base.py b/tensorflow/python/data/experimental/kernel_tests/stats_dataset_test_base.py index c5bf926759..ab1d1c3028 100644 --- a/tensorflow/python/data/experimental/kernel_tests/stats_dataset_test_base.py +++ b/tensorflow/python/data/experimental/kernel_tests/stats_dataset_test_base.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.core.framework import summary_pb2 from tensorflow.python.data.experimental.ops import stats_aggregator from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors @@ -93,7 +94,7 @@ class StatsDatasetTestBase(test_base.DatasetTestBase): aggregator = stats_aggregator.StatsAggregator() dataset = dataset_fn() dataset = dataset_transformation(dataset, aggregator) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() summary_t = aggregator.get_summary() diff --git a/tensorflow/python/data/experimental/kernel_tests/unbatch_test.py b/tensorflow/python/data/experimental/kernel_tests/unbatch_test.py index 0278a208cb..cef5e8d269 100644 --- a/tensorflow/python/data/experimental/kernel_tests/unbatch_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/unbatch_test.py @@ -17,20 +17,18 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import time from absl.testing import parameterized import numpy as np -from tensorflow.python.client import session from tensorflow.python.data.experimental.ops import batching from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors -from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import string_ops @@ -40,20 +38,22 @@ from tensorflow.python.util import compat class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): + @test_util.run_deprecated_v1 def testUnbatchWithUnknownRankInput(self): placeholder = array_ops.placeholder(dtypes.int32) dataset = dataset_ops.Dataset.from_tensors(placeholder).apply( batching.unbatch()) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_elem = iterator.get_next() with self.cached_session() as sess: sess.run(iterator.initializer, feed_dict={placeholder: [0, 1, 2, 3]}) for i in range(4): - self.assertEqual(i, sess.run(next_elem)) + self.assertEqual(i, self.evaluate(next_elem)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_elem) + self.evaluate(next_elem) + @test_util.run_deprecated_v1 def testUnbatchScalarDataset(self): data = tuple([math_ops.range(10) for _ in range(3)]) data = dataset_ops.Dataset.from_tensor_slices(data) @@ -63,16 +63,17 @@ class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): data = data.apply(batching.unbatch()) self.assertEqual(expected_types, data.output_types) - iterator = data.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(data) op = iterator.get_next() with self.cached_session() as sess: for i in range(10): - self.assertEqual((i,) * 3, sess.run(op)) + self.assertEqual((i,) * 3, self.evaluate(op)) with self.assertRaises(errors.OutOfRangeError): - sess.run(op) + self.evaluate(op) + @test_util.run_deprecated_v1 def testUnbatchDatasetWithStrings(self): data = tuple([math_ops.range(10) for _ in range(3)]) data = dataset_ops.Dataset.from_tensor_slices(data) @@ -83,16 +84,17 @@ class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): data = data.apply(batching.unbatch()) self.assertEqual(expected_types, data.output_types) - iterator = data.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(data) op = iterator.get_next() with self.cached_session() as sess: for i in range(10): - self.assertEqual((i, compat.as_bytes(str(i)), i), sess.run(op)) + self.assertEqual((i, compat.as_bytes(str(i)), i), self.evaluate(op)) with self.assertRaises(errors.OutOfRangeError): - sess.run(op) + self.evaluate(op) + @test_util.run_deprecated_v1 def testUnbatchDatasetWithSparseTensor(self): st = sparse_tensor.SparseTensorValue( indices=[[i, i] for i in range(10)], @@ -102,18 +104,19 @@ class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): data = data.apply(batching.unbatch()) data = data.batch(5) data = data.apply(batching.unbatch()) - iterator = data.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(data) next_element = iterator.get_next() with self.cached_session() as sess: for i in range(10): - st_row = sess.run(next_element) + st_row = self.evaluate(next_element) self.assertEqual([i], st_row.indices) self.assertEqual([i], st_row.values) self.assertEqual([10], st_row.dense_shape) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testUnbatchDatasetWithDenseAndSparseTensor(self): st = sparse_tensor.SparseTensorValue( indices=[[i, i] for i in range(10)], @@ -123,19 +126,20 @@ class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): data = data.apply(batching.unbatch()) data = data.batch(5) data = data.apply(batching.unbatch()) - iterator = data.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(data) next_element = iterator.get_next() with self.cached_session() as sess: for i in range(10): - dense_elem, st_row = sess.run(next_element) + dense_elem, st_row = self.evaluate(next_element) self.assertEqual(i, dense_elem) self.assertEqual([i], st_row.indices) self.assertEqual([i], st_row.values) self.assertEqual([10], st_row.dense_shape) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testUnbatchSingleElementTupleDataset(self): data = tuple([(math_ops.range(10),) for _ in range(3)]) data = dataset_ops.Dataset.from_tensor_slices(data) @@ -145,16 +149,17 @@ class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): data = data.apply(batching.unbatch()) self.assertEqual(expected_types, data.output_types) - iterator = data.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(data) op = iterator.get_next() with self.cached_session() as sess: for i in range(10): - self.assertEqual(((i,),) * 3, sess.run(op)) + self.assertEqual(((i,),) * 3, self.evaluate(op)) with self.assertRaises(errors.OutOfRangeError): - sess.run(op) + self.evaluate(op) + @test_util.run_deprecated_v1 def testUnbatchMultiElementTupleDataset(self): data = tuple([(math_ops.range(10 * i, 10 * i + 10), array_ops.fill([10], "hi")) for i in range(3)]) @@ -165,28 +170,29 @@ class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): data = data.apply(batching.unbatch()) self.assertAllEqual(expected_types, data.output_types) - iterator = data.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(data) op = iterator.get_next() with self.cached_session() as sess: for i in range(10): self.assertEqual(((i, b"hi"), (10 + i, b"hi"), (20 + i, b"hi")), - sess.run(op)) + self.evaluate(op)) with self.assertRaises(errors.OutOfRangeError): - sess.run(op) + self.evaluate(op) + @test_util.run_deprecated_v1 def testUnbatchEmpty(self): data = dataset_ops.Dataset.from_tensors( (constant_op.constant([]), constant_op.constant([], shape=[0, 4]), constant_op.constant([], shape=[0, 4, 0]))) data = data.apply(batching.unbatch()) - iterator = data.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(data) next_element = iterator.get_next() with self.cached_session() as sess: with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) def testUnbatchStaticShapeMismatch(self): data = dataset_ops.Dataset.from_tensors((np.arange(7), np.arange(8), @@ -194,12 +200,13 @@ class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): with self.assertRaises(ValueError): data.apply(batching.unbatch()) + @test_util.run_deprecated_v1 def testUnbatchDynamicShapeMismatch(self): ph1 = array_ops.placeholder(dtypes.int32, shape=[None]) ph2 = array_ops.placeholder(dtypes.int32, shape=None) data = dataset_ops.Dataset.from_tensors((ph1, ph2)) data = data.apply(batching.unbatch()) - iterator = data.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(data) next_element = iterator.get_next() with self.cached_session() as sess: @@ -211,7 +218,7 @@ class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): ph2: np.arange(8).astype(np.int32) }) with self.assertRaises(errors.InvalidArgumentError): - sess.run(next_element) + self.evaluate(next_element) # No 0th dimension (i.e. scalar value) for one component. sess.run( @@ -221,79 +228,7 @@ class UnbatchTest(test_base.DatasetTestBase, parameterized.TestCase): ph2: 7 }) with self.assertRaises(errors.InvalidArgumentError): - sess.run(next_element) - - -class UnbatchBenchmark(test.Benchmark): - - def benchmarkNativeUnbatch(self): - batch_sizes = [1, 2, 5, 10, 20, 50] - elems_per_trial = 10000 - with ops.Graph().as_default(): - dataset = dataset_ops.Dataset.from_tensors("element").repeat(None) - batch_size_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - dataset = dataset.batch(batch_size_placeholder) - dataset = dataset.apply(batching.unbatch()) - dataset = dataset.skip(elems_per_trial) - iterator = dataset.make_initializable_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - for batch_size in batch_sizes: - deltas = [] - for _ in range(5): - sess.run( - iterator.initializer, - feed_dict={batch_size_placeholder: batch_size}) - start = time.time() - sess.run(next_element.op) - end = time.time() - deltas.append((end - start) / elems_per_trial) - - median_wall_time = np.median(deltas) - print("Unbatch (native) batch size: %d Median wall time per element:" - " %f microseconds" % (batch_size, median_wall_time * 1e6)) - self.report_benchmark( - iters=10000, - wall_time=median_wall_time, - name="benchmark_unbatch_dataset_native_batch_size_%d" % - batch_size) - - # Include a benchmark of the previous `unbatch()` implementation that uses - # a composition of more primitive ops. Eventually we'd hope to generate code - # that is as good in both cases. - def benchmarkOldUnbatchImplementation(self): - batch_sizes = [1, 2, 5, 10, 20, 50] - elems_per_trial = 10000 - with ops.Graph().as_default(): - dataset = dataset_ops.Dataset.from_tensors("element").repeat(None) - batch_size_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - dataset = dataset.batch(batch_size_placeholder) - dataset = dataset.flat_map(dataset_ops.Dataset.from_tensor_slices) - dataset = dataset.skip(elems_per_trial) - iterator = dataset.make_initializable_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - for batch_size in batch_sizes: - deltas = [] - for _ in range(5): - sess.run( - iterator.initializer, - feed_dict={batch_size_placeholder: batch_size}) - start = time.time() - sess.run(next_element.op) - end = time.time() - deltas.append((end - start) / elems_per_trial) - - median_wall_time = np.median(deltas) - print("Unbatch (unfused) batch size: %d Median wall time per element:" - " %f microseconds" % (batch_size, median_wall_time * 1e6)) - self.report_benchmark( - iters=10000, - wall_time=median_wall_time, - name="benchmark_unbatch_dataset_unfused_batch_size_%d" % - batch_size) + self.evaluate(next_element) if __name__ == "__main__": diff --git a/tensorflow/python/data/experimental/kernel_tests/unique_test.py b/tensorflow/python/data/experimental/kernel_tests/unique_test.py index 847cff26b0..1d9941d7f4 100644 --- a/tensorflow/python/data/experimental/kernel_tests/unique_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/unique_test.py @@ -22,6 +22,7 @@ from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.platform import test from tensorflow.python.util import compat @@ -43,20 +44,21 @@ class UniqueTest(test_base.DatasetTestBase): current_test_case = [] dataset = dataset_ops.Dataset.from_generator(lambda: current_test_case, dtype).apply(unique.unique()) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) next_element = iterator.get_next() with self.cached_session() as sess: for test_case, expected in test_cases: current_test_case = test_case - sess.run(iterator.initializer) + self.evaluate(iterator.initializer) for element in expected: if dtype == dtypes.string: element = compat.as_bytes(element) - self.assertAllEqual(element, sess.run(next_element)) + self.assertAllEqual(element, self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testSimpleInt(self): for dtype in [dtypes.int32, dtypes.int64]: self._testSimpleHelper(dtype, [ @@ -69,6 +71,7 @@ class UniqueTest(test_base.DatasetTestBase): ([[1, 1], [1, 1], [2, 2], [3, 3], [1, 1]], [[1, 1], [2, 2], [3, 3]]), ]) + @test_util.run_deprecated_v1 def testSimpleString(self): self._testSimpleHelper(dtypes.string, [ ([], []), diff --git a/tensorflow/python/data/experimental/ops/BUILD b/tensorflow/python/data/experimental/ops/BUILD index 170fda90b6..43f43182f6 100644 --- a/tensorflow/python/data/experimental/ops/BUILD +++ b/tensorflow/python/data/experimental/ops/BUILD @@ -4,6 +4,16 @@ licenses(["notice"]) # Apache 2.0 exports_files(["LICENSE"]) +py_library( + name = "cardinality", + srcs = ["cardinality.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:experimental_dataset_ops_gen", + "//tensorflow/python:tensor_util", + ], +) + py_library( name = "counter", srcs = ["counter.py"], @@ -54,8 +64,8 @@ py_library( srcs_version = "PY2AND3", deps = [ "//tensorflow/python:constant_op", - "//tensorflow/python:dataset_ops_gen", "//tensorflow/python:dtypes", + "//tensorflow/python:experimental_dataset_ops_gen", "//tensorflow/python:framework_ops", "//tensorflow/python:random_seed", "//tensorflow/python:tensor_shape", @@ -125,6 +135,7 @@ py_library( "//tensorflow/python/data/util:convert", "//tensorflow/python/data/util:nest", "//tensorflow/python/data/util:sparse", + "//tensorflow/python/data/util:structure", "//third_party/py/numpy", ], ) @@ -139,6 +150,18 @@ py_library( ], ) +py_library( + name = "filter_for_shard_ops", + srcs = ["filter_for_shard_ops.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:dtypes", + "//tensorflow/python:math_ops", + "//tensorflow/python:ops", + "//tensorflow/python:tensor_util", + ], +) + py_library( name = "error_ops", srcs = ["error_ops.py"], @@ -165,7 +188,7 @@ py_library( "//tensorflow/python:tensor_shape", "//tensorflow/python/data/ops:dataset_ops", "//tensorflow/python/data/util:nest", - "//tensorflow/python/data/util:sparse", + "//tensorflow/python/data/util:structure", ], ) @@ -188,6 +211,28 @@ py_library( ], ) +py_library( + name = "map_defun", + srcs = ["map_defun.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:dataset_ops_gen", + "//tensorflow/python:framework_ops", + "//tensorflow/python:tensor_shape", + ], +) + +py_library( + name = "matching_files", + srcs = ["matching_files.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:dataset_ops_gen", + "//tensorflow/python:framework_ops", + "//tensorflow/python:tensor_shape", + ], +) + py_library( name = "optimization", srcs = ["optimization.py"], @@ -201,6 +246,16 @@ py_library( ], ) +py_library( + name = "optimization_options", + srcs = ["optimization_options.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:util", + "//tensorflow/python/data/util:options", + ], +) + py_library( name = "parsing_ops", srcs = ["parsing_ops.py"], @@ -217,17 +272,6 @@ py_library( ], ) -py_library( - name = "map_defun", - srcs = ["map_defun.py"], - srcs_version = "PY2AND3", - deps = [ - "//tensorflow/python:dataset_ops_gen", - "//tensorflow/python:framework_ops", - "//tensorflow/python:tensor_shape", - ], -) - py_library( name = "resampling", srcs = ["resampling.py"], @@ -253,7 +297,7 @@ py_library( srcs = ["scan_ops.py"], srcs_version = "PY2AND3", deps = [ - "//tensorflow/python:dataset_ops_gen", + "//tensorflow/python:experimental_dataset_ops_gen", "//tensorflow/python:framework_ops", "//tensorflow/python:function", "//tensorflow/python/data/ops:dataset_ops", @@ -303,6 +347,18 @@ py_library( srcs_version = "PY2AND3", deps = [ ":stats_aggregator", + "//tensorflow/python:util", + "//tensorflow/python/data/util:options", + ], +) + +py_library( + name = "threading_options", + srcs = ["threading_options.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:util", + "//tensorflow/python/data/util:options", ], ) @@ -313,9 +369,8 @@ py_library( deps = [ "//tensorflow/python:experimental_dataset_ops_gen", "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:util", "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/data/util:nest", - "//tensorflow/python/data/util:sparse", "//tensorflow/python/eager:context", ], ) @@ -378,14 +433,17 @@ py_library( name = "dataset_ops", deps = [ ":batching", + ":cardinality", ":counter", ":enumerate_ops", ":error_ops", + ":filter_for_shard_ops", ":get_single_element", ":grouping", ":indexed_dataset_ops", ":interleave_ops", ":map_defun", + ":matching_files", ":optimization", ":prefetching_ops", ":readers", diff --git a/tensorflow/python/data/experimental/ops/batching.py b/tensorflow/python/data/experimental/ops/batching.py index d8985fd13b..668bf3e800 100644 --- a/tensorflow/python/data/experimental/ops/batching.py +++ b/tensorflow/python/data/experimental/ops/batching.py @@ -30,11 +30,12 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import check_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_array_ops -from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.util.tf_export import tf_export @@ -365,7 +366,7 @@ class _UnbatchDataset(dataset_ops.UnaryDataset): self._input_dataset = input_dataset def _as_variant_tensor(self): - return gen_dataset_ops.unbatch_dataset( + return ged_ops.experimental_unbatch_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access **dataset_ops.flat_structure(self)) @@ -455,7 +456,7 @@ class _DenseToSparseBatchDataset(dataset_ops.UnaryDataset): self._row_shape = row_shape def _as_variant_tensor(self): - return gen_dataset_ops.dense_to_sparse_batch_dataset( + return ged_ops.experimental_dense_to_sparse_batch_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access self._batch_size, row_shape=convert.partial_shape_to_tensor(self._row_shape), @@ -569,13 +570,16 @@ class _RestructuredDataset(dataset_ops.UnaryDataset): return self._output_shapes -class _MapAndBatchDataset(dataset_ops.MapDataset): +class _MapAndBatchDataset(dataset_ops.UnaryDataset): """A `Dataset` that maps a function over a batch of elements.""" def __init__(self, input_dataset, map_func, batch_size, num_parallel_calls, drop_remainder): """See `Dataset.map()` for details.""" - super(_MapAndBatchDataset, self).__init__(input_dataset, map_func) + super(_MapAndBatchDataset, self).__init__(input_dataset) + self._input_dataset = input_dataset + self._map_func = dataset_ops.StructuredFunctionWrapper( + map_func, "tf.data.experimental.map_and_batch()", dataset=input_dataset) self._batch_size_t = ops.convert_to_tensor( batch_size, dtype=dtypes.int64, name="batch_size") self._num_parallel_calls_t = ops.convert_to_tensor( @@ -583,36 +587,40 @@ class _MapAndBatchDataset(dataset_ops.MapDataset): self._drop_remainder_t = ops.convert_to_tensor( drop_remainder, dtype=dtypes.bool, name="drop_remainder") - self._batch_size = batch_size - self._drop_remainder = drop_remainder + constant_drop_remainder = tensor_util.constant_value(self._drop_remainder_t) + if constant_drop_remainder: + # NOTE(mrry): `constant_drop_remainder` may be `None` (unknown statically) + # or `False` (explicitly retaining the remainder). + self._output_structure = self._map_func.output_structure._batch( # pylint: disable=protected-access + tensor_util.constant_value(self._batch_size_t)) + else: + self._output_structure = self._map_func.output_structure._batch(None) # pylint: disable=protected-access + + def _functions(self): + return [self._map_func] def _as_variant_tensor(self): # pylint: disable=protected-access - input_resource = self._input_dataset._as_variant_tensor() - return gen_dataset_ops.map_and_batch_dataset_v2( - input_resource, - self._map_func.captured_inputs, - f=self._map_func, + return ged_ops.experimental_map_and_batch_dataset( + self._input_dataset._as_variant_tensor(), + self._map_func.function.captured_inputs, + f=self._map_func.function, batch_size=self._batch_size_t, num_parallel_calls=self._num_parallel_calls_t, drop_remainder=self._drop_remainder_t, - **dataset_ops.flat_structure(self)) - # pylint: enable=protected-access + **dataset_ops.flat_structure(structure=self._output_structure)) + + @property + def output_classes(self): + return self._output_structure._to_legacy_output_classes() # pylint: disable=protected-access @property def output_shapes(self): - dim = self._batch_size if self._drop_remainder else None - return nest.pack_sequence_as(self._output_shapes, [ - tensor_shape.vector(dim).concatenate(s) - for s in nest.flatten(self._output_shapes) - ]) + return self._output_structure._to_legacy_output_shapes() # pylint: disable=protected-access @property def output_types(self): - return self._output_types - - def _transformation_name(self): - return "tf.data.experimental.map_and_batch()" + return self._output_structure._to_legacy_output_types() # pylint: disable=protected-access @tf_export("data.experimental.map_and_batch") diff --git a/tensorflow/python/data/experimental/ops/cardinality.py b/tensorflow/python/data/experimental/ops/cardinality.py new file mode 100644 index 0000000000..9cf0a8801e --- /dev/null +++ b/tensorflow/python/data/experimental/ops/cardinality.py @@ -0,0 +1,50 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Cardinality analysis of `Dataset` objects.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops +from tensorflow.python.util.tf_export import tf_export + + +INFINITE = -1 +UNKNOWN = -2 +tf_export("data.experimental.INFINITE_CARDINALITY").export_constant( + __name__, "INFINITE") +tf_export("data.experimental.UNKNOWN_CARDINALITY").export_constant( + __name__, "UNKNOWN") + + +@tf_export("data.experimental.cardinality") +def cardinality(dataset): + """Returns the cardinality of `dataset`, if known. + + The operation returns the cardinality of `dataset`. The operation may return + `tf.data.experimental.INFINITE_CARDINALITY` if `dataset` contains an infinite + number of elements or `tf.data.experimental.UNKNOWN_CARDINALITY` if the + analysis fails to determine the number of elements in `dataset` (e.g. when the + dataset source is a file). + + Args: + dataset: A `tf.data.Dataset` for which to determine cardinality. + + Returns: + A scalar `tf.int64` `Tensor` representing the cardinality of `dataset`. If + the cardinality is infinite or unknown, the operation returns the named + constant `INFINITE_CARDINALITY` and `UNKNOWN_CARDINALITY` respectively. + """ + return ged_ops.experimental_dataset_cardinality(dataset._as_variant_tensor()) # pylint: disable=protected-access diff --git a/tensorflow/python/data/experimental/ops/counter.py b/tensorflow/python/data/experimental/ops/counter.py index 42200eaef9..652eb9d002 100644 --- a/tensorflow/python/data/experimental/ops/counter.py +++ b/tensorflow/python/data/experimental/ops/counter.py @@ -25,8 +25,8 @@ from tensorflow.python.framework import ops from tensorflow.python.util.tf_export import tf_export -@tf_export("data.experimental.Counter") -def Counter(start=0, step=1, dtype=dtypes.int64): +@tf_export("data.experimental.Counter", v1=[]) +def CounterV2(start=0, step=1, dtype=dtypes.int64): """Creates a `Dataset` that counts from `start` in steps of size `step`. For example: @@ -53,3 +53,13 @@ def Counter(start=0, step=1, dtype=dtypes.int64): step = ops.convert_to_tensor(step, dtype=dtype, name="step") return dataset_ops.Dataset.from_tensors(0).repeat(None).apply( scan_ops.scan(start, lambda state, _: (state + step, state))) + + +@tf_export(v1=["data.experimental.Counter"]) +def CounterV1(start=0, step=1, dtype=dtypes.int64): + return dataset_ops.DatasetV1Adapter(CounterV2(start, step, dtype)) +CounterV1.__doc__ = CounterV2.__doc__ + +# TODO(b/119044825): Until all `tf.data` unit tests are converted to V2, keep +# this alias in place. +Counter = CounterV1 # pylint: disable=invalid-name diff --git a/tensorflow/python/data/experimental/ops/enumerate_ops.py b/tensorflow/python/data/experimental/ops/enumerate_ops.py index a1af98f552..f38cab12a7 100644 --- a/tensorflow/python/data/experimental/ops/enumerate_ops.py +++ b/tensorflow/python/data/experimental/ops/enumerate_ops.py @@ -26,9 +26,9 @@ from tensorflow.python.util.tf_export import tf_export @tf_export("data.experimental.enumerate_dataset") def enumerate_dataset(start=0): - """A transformation that enumerate the elements of a dataset. + """A transformation that enumerates the elements of a dataset. - It is Similar to python's `enumerate`. + It is similar to python's `enumerate`. For example: ```python diff --git a/tensorflow/python/data/experimental/ops/error_ops.py b/tensorflow/python/data/experimental/ops/error_ops.py index 82e274b70c..879b13ce09 100644 --- a/tensorflow/python/data/experimental/ops/error_ops.py +++ b/tensorflow/python/data/experimental/ops/error_ops.py @@ -52,7 +52,7 @@ def ignore_errors(): return _apply_fn -class _IgnoreErrorsDataset(dataset_ops.UnaryDataset): +class _IgnoreErrorsDataset(dataset_ops.UnaryUnchangedStructureDataset): """A `Dataset` that silently ignores errors when computing its input.""" def __init__(self, input_dataset): @@ -64,15 +64,3 @@ class _IgnoreErrorsDataset(dataset_ops.UnaryDataset): return gen_experimental_dataset_ops.experimental_ignore_errors_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access **dataset_ops.flat_structure(self)) - - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types diff --git a/tensorflow/python/data/experimental/ops/filter_for_shard_ops.py b/tensorflow/python/data/experimental/ops/filter_for_shard_ops.py new file mode 100644 index 0000000000..91d3dca3e9 --- /dev/null +++ b/tensorflow/python/data/experimental/ops/filter_for_shard_ops.py @@ -0,0 +1,106 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Naive shard dataset transformation.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_util +from tensorflow.python.ops import math_ops +from tensorflow.python.util.tf_export import tf_export + + +@tf_export("data.experimental.filter_for_shard") +def filter_for_shard(num_shards, shard_index): + """Creates a `Dataset` that includes only 1/`num_shards` of this dataset. + + This dataset operator is very useful when running distributed training, as + it allows each worker to read a unique subset. + + When reading a single input file, you can skip elements as follows: + + ```python + d = tf.data.TFRecordDataset(FLAGS.input_file) + d = d.apply(tf.data.experimental.naive_shard(FLAGS.num_workers, + FLAGS.worker_index)) + d = d.repeat(FLAGS.num_epochs) + d = d.shuffle(FLAGS.shuffle_buffer_size) + d = d.map(parser_fn, num_parallel_calls=FLAGS.num_map_threads) + ``` + + Important caveats: + + - Be sure to shard before you use any randomizing operator (such as + shuffle). + - Generally it is best if the shard operator is used early in the dataset + pipeline. For example, when reading from a set of TFRecord files, shard + before converting the dataset to input samples. This avoids reading every + file on every worker. The following is an example of an efficient + sharding strategy within a complete pipeline: + + ```python + d = Dataset.list_files(FLAGS.pattern) + d = d.apply(tf.data.experimental.naive_shard(FLAGS.num_workers, + FLAGS.worker_index)) + d = d.repeat(FLAGS.num_epochs) + d = d.shuffle(FLAGS.shuffle_buffer_size) + d = d.interleave(tf.data.TFRecordDataset, + cycle_length=FLAGS.num_readers, block_length=1) + d = d.map(parser_fn, num_parallel_calls=FLAGS.num_map_threads) + ``` + + Args: + num_shards: A `tf.int64` scalar `tf.Tensor`, representing the number of + shards operating in parallel. + shard_index: A `tf.int64` scalar `tf.Tensor`, representing the worker index. + + Returns: + A `Dataset` transformation function, which can be passed to + `tf.data.Dataset.apply`. + + Raises: + ValueError: if `num_shards` or `shard_index` are illegal values. Note: error + checking is done on a best-effort basis, and errors aren't guaranteed to + be caught upon dataset creation. (e.g. providing in a placeholder tensor + bypasses the early checking, and will instead result in an error during + a session.run call.) + """ + num_shards = ops.convert_to_tensor( + num_shards, name="num_shards", dtype=dtypes.int64) + num_shards_static = tensor_util.constant_value(num_shards) + shard_index = ops.convert_to_tensor(shard_index, name="shard_index", + dtype=dtypes.int64) + shard_index_static = tensor_util.constant_value(shard_index) + + if num_shards_static is not None and num_shards_static < 1: + raise ValueError("num_shards must be >= 1; got: %s" % num_shards_static) + if shard_index_static is not None and shard_index_static < 0: + raise ValueError("shard_index must be >= 0; got: %s" % shard_index_static) + if (shard_index_static is not None and num_shards_static is not None and + shard_index_static >= num_shards_static): + raise ValueError("shard_index must be < num_shards; %s is not < %s" % + (shard_index_static, num_shards_static)) + + def filter_fn(elem_index, _): + mod_result = math_ops.mod(elem_index, num_shards) + return math_ops.equal(mod_result, shard_index) + + def _apply_fn(dataset): + # pylint: disable=protected-access + return dataset._enumerate().filter(filter_fn).map(lambda _, elem: elem) + + return _apply_fn diff --git a/tensorflow/python/data/experimental/ops/get_single_element.py b/tensorflow/python/data/experimental/ops/get_single_element.py index 132526166c..73116edf12 100644 --- a/tensorflow/python/data/experimental/ops/get_single_element.py +++ b/tensorflow/python/data/experimental/ops/get_single_element.py @@ -60,7 +60,7 @@ def get_single_element(dataset): InvalidArgumentError (at runtime): if `dataset` does not contain exactly one element. """ - if not isinstance(dataset, dataset_ops.Dataset): + if not isinstance(dataset, dataset_ops.DatasetV2): raise TypeError("`dataset` must be a `tf.data.Dataset` object.") nested_ret = nest.pack_sequence_as( diff --git a/tensorflow/python/data/experimental/ops/grouping.py b/tensorflow/python/data/experimental/ops/grouping.py index 026867d405..ad9fe9a4e8 100644 --- a/tensorflow/python/data/experimental/ops/grouping.py +++ b/tensorflow/python/data/experimental/ops/grouping.py @@ -21,13 +21,14 @@ import numpy as np from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.util import nest +from tensorflow.python.data.util import structure from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.ops import array_ops from tensorflow.python.ops import check_ops -from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops from tensorflow.python.ops import math_ops from tensorflow.python.util.tf_export import tf_export @@ -236,29 +237,6 @@ def bucket_by_sequence_length(element_length_func, return _apply_fn -def _map_x_dataset(map_func): - """A transformation that maps `map_func` across its input. - - This transformation is similar to `tf.data.Dataset.map`, but in addition to - supporting dense and sparse tensor inputs, it also supports dataset inputs. - - Args: - map_func: A function mapping a nested structure of tensors and/or datasets - (having shapes and types defined by `self.output_shapes` and - `self.output_types`) to another nested structure of tensors and/or - datasets. - - Returns: - Dataset: A `Dataset`. - """ - - def _apply_fn(dataset): - """Function from `Dataset` to `Dataset` that applies the transformation.""" - return _MapXDataset(dataset, map_func) - - return _apply_fn - - class _GroupByReducerDataset(dataset_ops.UnaryDataset): """A `Dataset` that groups its input and performs a reduction.""" @@ -284,7 +262,7 @@ class _GroupByReducerDataset(dataset_ops.UnaryDataset): "`key_func` must return a single tf.int64 tensor. " "Got type=%s and shape=%s" % (wrapped_func.output_types, wrapped_func.output_shapes)) - self._key_func = wrapped_func.function + self._key_func = wrapped_func def _make_init_func(self, init_func): """Make wrapping defun for init_func.""" @@ -294,7 +272,7 @@ class _GroupByReducerDataset(dataset_ops.UnaryDataset): input_classes=ops.Tensor, input_shapes=tensor_shape.scalar(), input_types=dtypes.int64) - self._init_func = wrapped_func.function + self._init_func = wrapped_func self._state_classes = wrapped_func.output_classes self._state_shapes = wrapped_func.output_shapes self._state_types = wrapped_func.output_types @@ -356,8 +334,8 @@ class _GroupByReducerDataset(dataset_ops.UnaryDataset): self._state_shapes = nest.pack_sequence_as(self._state_shapes, weakened_state_shapes) - self._reduce_func = wrapped_func.function - self._reduce_func.add_to_graph(ops.get_default_graph()) + self._reduce_func = wrapped_func + self._reduce_func.function.add_to_graph(ops.get_default_graph()) def _make_finalize_func(self, finalize_func): """Make wrapping defun for finalize_func.""" @@ -367,7 +345,7 @@ class _GroupByReducerDataset(dataset_ops.UnaryDataset): input_classes=self._state_classes, input_shapes=self._state_shapes, input_types=self._state_types) - self._finalize_func = wrapped_func.function + self._finalize_func = wrapped_func self._output_classes = wrapped_func.output_classes self._output_shapes = wrapped_func.output_shapes self._output_types = wrapped_func.output_types @@ -384,17 +362,22 @@ class _GroupByReducerDataset(dataset_ops.UnaryDataset): def output_types(self): return self._output_types + def _functions(self): + return [ + self._key_func, self._init_func, self._reduce_func, self._finalize_func + ] + def _as_variant_tensor(self): - return gen_dataset_ops.group_by_reducer_dataset( + return ged_ops.experimental_group_by_reducer_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access - self._key_func.captured_inputs, - self._init_func.captured_inputs, - self._reduce_func.captured_inputs, - self._finalize_func.captured_inputs, - key_func=self._key_func, - init_func=self._init_func, - reduce_func=self._reduce_func, - finalize_func=self._finalize_func, + self._key_func.function.captured_inputs, + self._init_func.function.captured_inputs, + self._reduce_func.function.captured_inputs, + self._finalize_func.function.captured_inputs, + key_func=self._key_func.function, + init_func=self._init_func.function, + reduce_func=self._reduce_func.function, + finalize_func=self._finalize_func.function, **dataset_ops.flat_structure(self)) def _transformation_name(self): @@ -430,7 +413,7 @@ class _GroupByWindowDataset(dataset_ops.UnaryDataset): wrapped_func.output_shapes.is_compatible_with(tensor_shape.scalar())): raise ValueError( "`window_size_func` must return a single tf.int64 scalar tensor.") - self._window_size_func = wrapped_func.function + self._window_size_func = wrapped_func def _make_key_func(self, key_func, input_dataset): """Make wrapping defun for key_func.""" @@ -444,25 +427,29 @@ class _GroupByWindowDataset(dataset_ops.UnaryDataset): wrapped_func.output_shapes.is_compatible_with(tensor_shape.scalar())): raise ValueError( "`key_func` must return a single tf.int64 scalar tensor.") - self._key_func = wrapped_func.function + self._key_func = wrapped_func def _make_reduce_func(self, reduce_func, input_dataset): """Make wrapping defun for reduce_func.""" - nested_dataset = dataset_ops._NestedDatasetComponent(input_dataset) # pylint: disable=protected-access + nested_dataset = dataset_ops.DatasetStructure( + structure.Structure._from_legacy_structure( # pylint: disable=protected-access + input_dataset.output_types, input_dataset.output_shapes, + input_dataset.output_classes)) wrapped_func = dataset_ops.StructuredFunctionWrapper( reduce_func, self._transformation_name(), input_classes=(ops.Tensor, nested_dataset), input_shapes=(tensor_shape.scalar(), nested_dataset), - input_types=(dtypes.int64, nested_dataset), - experimental_nested_dataset_support=True) + input_types=(dtypes.int64, nested_dataset)) if not isinstance( - wrapped_func.output_classes, dataset_ops._NestedDatasetComponent): # pylint: disable=protected-access + wrapped_func.output_structure, dataset_ops.DatasetStructure): raise TypeError("`reduce_func` must return a `Dataset` object.") - self._output_classes = wrapped_func.output_classes.output_classes - self._output_types = wrapped_func.output_types.output_types - self._output_shapes = wrapped_func.output_shapes.output_shapes - self._reduce_func = wrapped_func.function + # pylint: disable=protected-access + element_structure = wrapped_func.output_structure._element_structure + self._output_classes = element_structure._to_legacy_output_classes() + self._output_types = element_structure._to_legacy_output_types() + self._output_shapes = element_structure._to_legacy_output_shapes() + self._reduce_func = wrapped_func @property def output_classes(self): @@ -476,15 +463,18 @@ class _GroupByWindowDataset(dataset_ops.UnaryDataset): def output_types(self): return self._output_types + def _functions(self): + return [self._key_func, self._reduce_func, self._window_size_func] + def _as_variant_tensor(self): - return gen_dataset_ops.group_by_window_dataset( + return ged_ops.experimental_group_by_window_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access - self._key_func.captured_inputs, - self._reduce_func.captured_inputs, - self._window_size_func.captured_inputs, - key_func=self._key_func, - reduce_func=self._reduce_func, - window_size_func=self._window_size_func, + self._key_func.function.captured_inputs, + self._reduce_func.function.captured_inputs, + self._window_size_func.function.captured_inputs, + key_func=self._key_func.function, + reduce_func=self._reduce_func.function, + window_size_func=self._window_size_func.function, **dataset_ops.flat_structure(self)) def _transformation_name(self): @@ -517,45 +507,3 @@ class Reducer(object): @property def finalize_func(self): return self._finalize_func - - -class _MapXDataset(dataset_ops.UnaryDataset): - """A `Dataset` that maps a function over elements in its input.""" - - def __init__(self, input_dataset, map_func): - """See `map_x_dataset()` for details.""" - super(_MapXDataset, self).__init__(input_dataset) - self._input_dataset = input_dataset - - wrapped_func = dataset_ops.StructuredFunctionWrapper( - map_func, - self._transformation_name(), - dataset=input_dataset, - experimental_nested_dataset_support=True) - self._output_classes = wrapped_func.output_classes - self._output_shapes = wrapped_func.output_shapes - self._output_types = wrapped_func.output_types - self._map_func = wrapped_func.function - - def _as_variant_tensor(self): - input_t = self._input_dataset._as_variant_tensor() # pylint: disable=protected-access - return gen_dataset_ops.map_dataset( - input_t, - self._map_func.captured_inputs, - f=self._map_func, - **dataset_ops.flat_structure(self)) - - @property - def output_classes(self): - return self._output_classes - - @property - def output_shapes(self): - return self._output_shapes - - @property - def output_types(self): - return self._output_types - - def _transformation_name(self): - return "tf.data.experimental.map_x_dataset()" diff --git a/tensorflow/python/data/experimental/ops/indexed_dataset_ops.py b/tensorflow/python/data/experimental/ops/indexed_dataset_ops.py index 9c06474a2f..570f0116f7 100644 --- a/tensorflow/python/data/experimental/ops/indexed_dataset_ops.py +++ b/tensorflow/python/data/experimental/ops/indexed_dataset_ops.py @@ -65,6 +65,7 @@ class MaterializedIndexedDataset(object): sparse.as_dense_types(self._output_shapes, self._output_classes))) +# TODO(saeta): Add a `DatasetV1` wrapper if this is exposed via the public API. class IndexedDataset(dataset_ops.Dataset): """IndexedDataset is highly experimental! """ @@ -149,6 +150,7 @@ class IndexedDataset(dataset_ops.Dataset): raise NotImplementedError("IndexedDataset._as_variant_tensor") +# TODO(saeta): Add a `DatasetV1` wrapper if this is exposed via the public API. class IdentityIndexedDataset(IndexedDataset): """IdentityIndexedDataset is a trivial indexed dataset used for testing. """ diff --git a/tensorflow/python/data/experimental/ops/interleave_ops.py b/tensorflow/python/data/experimental/ops/interleave_ops.py index a3c094859e..8b0fdfce11 100644 --- a/tensorflow/python/data/experimental/ops/interleave_ops.py +++ b/tensorflow/python/data/experimental/ops/interleave_ops.py @@ -133,8 +133,8 @@ class _DirectedInterleaveDataset(dataset_ops.Dataset): return self._data_inputs[0].output_types -@tf_export("data.experimental.sample_from_datasets") -def sample_from_datasets(datasets, weights=None, seed=None): +@tf_export("data.experimental.sample_from_datasets", v1=[]) +def sample_from_datasets_v2(datasets, weights=None, seed=None): """Samples elements at random from the datasets in `datasets`. Args: @@ -158,7 +158,7 @@ def sample_from_datasets(datasets, weights=None, seed=None): length of the `datasets` element. """ num_datasets = len(datasets) - if not isinstance(weights, dataset_ops.Dataset): + if not isinstance(weights, dataset_ops.DatasetV2): if weights is None: # Select inputs with uniform probability. logits = [[1.0] * num_datasets] @@ -217,8 +217,15 @@ def sample_from_datasets(datasets, weights=None, seed=None): return _DirectedInterleaveDataset(selector_input, datasets) -@tf_export("data.experimental.choose_from_datasets") -def choose_from_datasets(datasets, choice_dataset): +@tf_export(v1=["data.experimental.sample_from_datasets"]) +def sample_from_datasets_v1(datasets, weights=None, seed=None): + return dataset_ops.DatasetV1Adapter( + sample_from_datasets_v2(datasets, weights, seed)) +sample_from_datasets_v1.__doc__ = sample_from_datasets_v2.__doc__ + + +@tf_export("data.experimental.choose_from_datasets", v1=[]) +def choose_from_datasets_v2(datasets, choice_dataset): """Creates a dataset that deterministically chooses elements from `datasets`. For example, given the following datasets: @@ -260,3 +267,16 @@ def choose_from_datasets(datasets, choice_dataset): raise TypeError("`choice_dataset` must be a dataset of scalar " "`tf.int64` tensors.") return _DirectedInterleaveDataset(choice_dataset, datasets) + + +@tf_export(v1=["data.experimental.choose_from_datasets"]) +def choose_from_datasets_v1(datasets, choice_dataset): + return dataset_ops.DatasetV1Adapter( + choose_from_datasets_v2(datasets, choice_dataset)) +choose_from_datasets_v1.__doc__ = choose_from_datasets_v2.__doc__ + + +# TODO(b/119044825): Until all `tf.data` unit tests are converted to V2, keep +# these aliases in place. +choose_from_datasets = choose_from_datasets_v1 +sample_from_datasets = sample_from_datasets_v1 diff --git a/tensorflow/python/data/experimental/ops/matching_files.py b/tensorflow/python/data/experimental/ops/matching_files.py new file mode 100644 index 0000000000..8398f86e31 --- /dev/null +++ b/tensorflow/python/data/experimental/ops/matching_files.py @@ -0,0 +1,51 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Experimental API for matching input filenames.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_shape +from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops + + +class MatchingFilesDataset(dataset_ops.DatasetSource): + """A `Dataset` that list the files according to the input patterns.""" + + def __init__(self, patterns): + super(MatchingFilesDataset, self).__init__() + self._patterns = ops.convert_to_tensor( + patterns, dtype=dtypes.string, name="patterns") + + def _as_variant_tensor(self): + return ged_ops.experimental_matching_files_dataset(self._patterns) + + @property + def output_classes(self): + return ops.Tensor + + @property + def output_shapes(self): + return tensor_shape.scalar() + + @property + def output_types(self): + return dtypes.string + + diff --git a/tensorflow/python/data/experimental/ops/optimization.py b/tensorflow/python/data/experimental/ops/optimization.py index b744db7f1e..c6c7de9265 100644 --- a/tensorflow/python/data/experimental/ops/optimization.py +++ b/tensorflow/python/data/experimental/ops/optimization.py @@ -100,7 +100,7 @@ def optimize(optimizations=None): return _apply_fn -class _AssertNextDataset(dataset_ops.UnaryDataset): +class _AssertNextDataset(dataset_ops.UnaryUnchangedStructureDataset): """A `Dataset` that asserts which transformations happen next.""" def __init__(self, input_dataset, transformations): @@ -118,20 +118,8 @@ class _AssertNextDataset(dataset_ops.UnaryDataset): self._transformations, **dataset_ops.flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - - -class _NonSerializableDataset(dataset_ops.UnaryDataset): +class _NonSerializableDataset(dataset_ops.UnaryUnchangedStructureDataset): """A `Dataset` that performs non-serializable identity transformation.""" def __init__(self, input_dataset): @@ -143,15 +131,3 @@ class _NonSerializableDataset(dataset_ops.UnaryDataset): return gen_experimental_dataset_ops.experimental_non_serializable_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access **dataset_ops.flat_structure(self)) - - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types diff --git a/tensorflow/python/data/experimental/ops/optimization_options.py b/tensorflow/python/data/experimental/ops/optimization_options.py new file mode 100644 index 0000000000..dc9d319374 --- /dev/null +++ b/tensorflow/python/data/experimental/ops/optimization_options.py @@ -0,0 +1,83 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Experimental API for controlling optimizations in `tf.data` pipelines.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + + +from tensorflow.python.data.util import options +from tensorflow.python.util.tf_export import tf_export + + +@tf_export("data.experimental.OptimizationOptions") +class OptimizationOptions(options.OptionsBase): + """Represents options for dataset optimizations. + + You can apply `OptimizationOptions` to a `dataset` object, as follows: + + ```python + options = tf.data.Options() + options.optimization = tf.data.experimental.OptimizationOptions() + options.optimization.map_and_batch_fusion = True + dataset = dataset.with_options(options) + ``` + """ + + filter_fusion = options.create_option( + name="filter_fusion", + ty=bool, + docstring="Whether to fuse filter transformations.") + + hoist_random_uniform = options.create_option( + name="hoist_random_uniform", + ty=bool, + docstring= + "Whether to hoist `tf.random_uniform()` ops out of map transformations.") + + map_and_batch_fusion = options.create_option( + name="map_and_batch_fusion", + ty=bool, + docstring="Whether to fuse map and batch transformations.") + + map_and_filter_fusion = options.create_option( + name="map_and_filter_fusion", + ty=bool, + docstring="Whether to fuse map and filter transformations.") + + map_fusion = options.create_option( + name="map_and_filter_fusion", + ty=bool, + docstring="Whether to fuse map transformations.") + + map_parallelization = options.create_option( + name="map_parallelization", + ty=bool, + docstring="Whether to parallelize stateless map transformations.") + + map_vectorization = options.create_option( + name="map_vectorization", + ty=bool, + docstring="Whether to vectorize map transformations.") + + noop_elimination = options.create_option( + name="noop_elimination", + ty=bool, + docstring="Whether to eliminate no-op transformations.") + + shuffle_and_repeat_fusion = options.create_option( + name="shuffle_and_repeat_fusion", + ty=bool, + docstring="Whether to fuse shuffle and repeat transformations.") diff --git a/tensorflow/python/data/experimental/ops/parsing_ops.py b/tensorflow/python/data/experimental/ops/parsing_ops.py index 6615b9022a..44cb0b8a2c 100644 --- a/tensorflow/python/data/experimental/ops/parsing_ops.py +++ b/tensorflow/python/data/experimental/ops/parsing_ops.py @@ -22,7 +22,7 @@ from tensorflow.python.data.util import nest from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor -from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops from tensorflow.python.ops import parsing_ops from tensorflow.python.util.tf_export import tf_export @@ -80,7 +80,7 @@ class _ParseExampleDataset(dataset_ops.UnaryDataset): ])) def _as_variant_tensor(self): - return gen_dataset_ops.parse_example_dataset( + return gen_experimental_dataset_ops.experimental_parse_example_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access self._num_parallel_calls, self._dense_defaults, @@ -138,10 +138,10 @@ def parse_example_dataset(features, num_parallel_calls=1): def _apply_fn(dataset): """Function from `Dataset` to `Dataset` that applies the transformation.""" out_dataset = _ParseExampleDataset(dataset, features, num_parallel_calls) - if any([ + if any( isinstance(feature, parsing_ops.SparseFeature) for _, feature in features.items() - ]): + ): # pylint: disable=protected-access # pylint: disable=g-long-lambda out_dataset = out_dataset.map( diff --git a/tensorflow/python/data/experimental/ops/prefetching_ops.py b/tensorflow/python/data/experimental/ops/prefetching_ops.py index d34f9f25bd..0894dd5f70 100644 --- a/tensorflow/python/data/experimental/ops/prefetching_ops.py +++ b/tensorflow/python/data/experimental/ops/prefetching_ops.py @@ -17,13 +17,10 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import warnings - from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import iterator_ops from tensorflow.python.data.util import nest from tensorflow.python.data.util import sparse -from tensorflow.python.eager import context from tensorflow.python.eager import function from tensorflow.python.framework import device as framework_device from tensorflow.python.framework import dtypes @@ -37,304 +34,6 @@ from tensorflow.python.ops import resource_variable_ops from tensorflow.python.util.tf_export import tf_export -def function_buffering_resource(string_arg, - target_device, - f, - buffer_size, - output_types, - container="", - shared_name=None, - name=None): - """Creates a FunctionBufferingResource. - - A FunctionBufferingResource fills up a buffer by calling a function `f` on - `target_device`. `f` should take in only a single string argument as input. - - Args: - string_arg: The single string argument to the function. - target_device: The device to run `f` on. - f: The function to be executed. - buffer_size: Size of the buffer to be populated. - output_types: The output types generated by the function. - container: (Optional) string. Defaults to "". - shared_name: (Optional) string. - name: (Optional) string to name the op. - - Returns: - Handle to a FunctionBufferingResource. - """ - if shared_name is None: - shared_name = "" - return ged_ops.experimental_function_buffering_resource( - string_arg=string_arg, - target_device=target_device, - shared_name=shared_name, - f=f, - buffer_size=buffer_size, - container=container, - name=name, - output_types=output_types) - - -def function_buffering_resource_get_next(function_buffer_resource, - output_types, - name=None): - return ged_ops.experimental_function_buffering_resource_get_next( - function_buffer_resource=function_buffer_resource, - output_types=output_types, - name=name) - - -def function_buffering_resource_reset(function_buffer_resource, name=None): - return ged_ops.experimental_function_buffering_resource_reset( - function_buffer_resource=function_buffer_resource, name=name) - - -# pylint: disable=protected-access -class _PrefetchToDeviceIterator(object): - """A replacement for `tf.data.Iterator` that prefetches to another device. - - Args: - input_dataset: The input dataset - one_shot: If true, we make a one shot iterator that's already initialized. - device: A fully specified device string where we want to prefetch to - buffer_size: Size of the prefetching buffer. - shared_name: (Optional.) If non-empty, the returned iterator will be - shared under the given name across multiple sessions that share the - same devices (e.g. when using a remote server). - - Returns: - An Iterator type object. - """ - - def __init__(self, - input_dataset, - one_shot, - device, - buffer_size, - shared_name=None): - self._input_dataset = input_dataset - self._get_next_call_count = 0 - self._one_shot = one_shot - if shared_name is None: - shared_name = "" - - if self._one_shot: - self._input_iterator = input_dataset.make_one_shot_iterator() - else: - self._input_iterator = iterator_ops.Iterator.from_structure( - self._input_dataset.output_types, self._input_dataset.output_shapes, - shared_name, self._input_dataset.output_classes) - input_iterator_handle = self._input_iterator.string_handle() - - @function.defun(input_signature=[tensor_spec.TensorSpec([], dtypes.string)]) - # handle is a scalar `tf.Tensor` of type `tf.string` - def _prefetch_fn(handle): - """Prefetches one element from `input_iterator`.""" - remote_iterator = iterator_ops.Iterator.from_string_handle( - handle, self._input_iterator.output_types, - self._input_iterator.output_shapes, - self._input_iterator.output_classes) - ret = remote_iterator.get_next() - return nest.flatten(sparse.serialize_sparse_tensors(ret)) - - self._prefetch_fn = _prefetch_fn._get_concrete_function_internal() # pylint: disable=protected-access - - iterator_device = ged_ops.experimental_iterator_get_device( - self._input_iterator._iterator_resource) - - with ops.device(device): - self._buffering_resource = function_buffering_resource( - f=self._prefetch_fn, - target_device=iterator_device, - string_arg=input_iterator_handle, - buffer_size=buffer_size, - shared_name=shared_name, - output_types=nest.flatten( - sparse.as_dense_types(self._input_dataset.output_types, - self._input_dataset.output_classes))) - - if not self._one_shot: - reset_op = function_buffering_resource_reset(self._buffering_resource) - with ops.control_dependencies([reset_op]): - self._initializer = self._input_iterator.make_initializer( - self._input_dataset) - - def get_next(self, name=None): - """See `tf.data.Iterator.get_next`.""" - self._get_next_call_count += 1 - if self._get_next_call_count > iterator_ops.GET_NEXT_CALL_WARNING_THRESHOLD: - warnings.warn(iterator_ops.GET_NEXT_CALL_WARNING_MESSAGE) - - flat_ret = ged_ops.experimental_function_buffering_resource_get_next( - self._buffering_resource, - output_types=nest.flatten( - sparse.as_dense_types(self.output_types, self.output_classes)), - name=name) - - ret = sparse.deserialize_sparse_tensors( - nest.pack_sequence_as(self.output_types, flat_ret), - self.output_types, self.output_shapes, self.output_classes) - - for tensor, shape in zip( - nest.flatten(ret), nest.flatten(self.output_shapes)): - if isinstance(tensor, ops.Tensor): - tensor.set_shape(shape) - - return ret - - @property - def initializer(self): - if self._one_shot: - raise NotImplementedError("Can't initialize a one_shot_iterator") - return self._initializer - - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - - -class _PrefetchToDeviceEagerIterator(iterator_ops.EagerIterator): - """A replacement for `tf.data.Iterator` that prefetches to another device. - - Args: - input_dataset: The input dataset - one_shot: If true, we make a one shot iterator that's already initialized. - device: A fully specified device string where we want to prefetch to - buffer_size: Size of the prefetching buffer. - shared_name: (Optional.) If non-empty, the returned iterator will be - shared under the given name across multiple sessions that share the - same devices (e.g. when using a remote server). - - Returns: - An Iterator type object. - """ - - def __init__(self, - input_dataset, - device, - buffer_size): - with ops.device("/device:CPU:0"): - super(_PrefetchToDeviceEagerIterator, self).__init__(input_dataset) - input_iterator_handle = gen_dataset_ops.iterator_to_string_handle( - self._resource) - - self._device = device - - @function.defun(input_signature=[tensor_spec.TensorSpec([], dtypes.string)]) - def _prefetch_fn(handle): - """Prefetches one element from `input_iterator`.""" - remote_iterator = iterator_ops.Iterator.from_string_handle( - handle, self.output_types, self.output_shapes, self.output_classes) - ret = remote_iterator.get_next() - return nest.flatten(sparse.serialize_sparse_tensors(ret)) - - self._prefetch_fn = _prefetch_fn._get_concrete_function_internal() # pylint: disable=protected-access - - with ops.device(device): - self._buffering_resource = function_buffering_resource( - f=self._prefetch_fn, - output_types=self._flat_output_types, - target_device=ged_ops.experimental_iterator_get_device( - self._resource), - string_arg=input_iterator_handle, - buffer_size=buffer_size, - shared_name=iterator_ops._generate_shared_name( - "function_buffer_resource")) - - def _next_internal(self): - """Returns a nested structure of `tf.Tensor`s containing the next element. - """ - # This runs in sync mode as iterators use an error status to communicate - # that there is no more data to iterate over. - # TODO(b/77291417): Fix - with context.execution_mode(context.SYNC): - with ops.device(self._device): - flat_ret = ged_ops.experimental_function_buffering_resource_get_next( - function_buffer_resource=self._buffering_resource, - output_types=self._flat_output_types) - return self._element_structure._from_tensor_list(flat_ret) -# pylint: enable=protected-access - - -class _PrefetchToDeviceDataset(dataset_ops.UnaryDataset): - """A `Dataset` whose iterator prefetches elements to another device.""" - - def __init__(self, input_dataset, device, buffer_size): - super(_PrefetchToDeviceDataset, self).__init__(input_dataset) - self._input_dataset = input_dataset - self._device = device - self._buffer_size = buffer_size if buffer_size is not None else 1 - - # The static analysis cannot tell that the eager iterator's superclass has - # a `next()` method. - # pylint: disable=non-iterator-returned - def __iter__(self): - """Creates an `Iterator` for enumerating the elements of this dataset. - - The returned iterator implements the Python iterator protocol and therefore - can only be used in eager mode. - - Returns: - An `Iterator` over the elements of this dataset. - - Raises: - RuntimeError: If eager execution is enabled. - """ - if context.executing_eagerly(): - return _PrefetchToDeviceEagerIterator(self._input_dataset, self._device, - self._buffer_size) - else: - raise RuntimeError("dataset.__iter__() is only supported when eager " - "execution is enabled.") - # pylint: enable=non-iterator-returned - - def make_one_shot_iterator(self): - if context.executing_eagerly(): - return _PrefetchToDeviceEagerIterator(self._input_dataset, self._device, - self._buffer_size) - else: - return _PrefetchToDeviceIterator(self._input_dataset, one_shot=True, - device=self._device, - buffer_size=self._buffer_size) - - def make_initializable_iterator(self, shared_name=None): - return _PrefetchToDeviceIterator( - self._input_dataset, - one_shot=False, - device=self._device, - buffer_size=self._buffer_size, - shared_name=shared_name) - - def _as_variant_tensor(self): - # TODO(mrry): Raise this error earlier (e.g. when one of the Dataset - # transformation methods is called. - # TODO(mrry): Investigate support for chaining further transformations after - # the prefetch, including GPU support. - raise NotImplementedError("`prefetch_to_device()` must be the last " - "transformation in a dataset pipeline.") - - @property - def output_types(self): - return self._input_dataset.output_types - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_classes(self): - return self._input_dataset.output_classes - - @tf_export("data.experimental.prefetch_to_device") def prefetch_to_device(device, buffer_size=None): """A transformation that prefetches dataset values to the given `device`. @@ -352,7 +51,8 @@ def prefetch_to_device(device, buffer_size=None): `tf.data.Dataset.apply`. """ def _apply_fn(dataset): - return _PrefetchToDeviceDataset(dataset, device, buffer_size) + return dataset.apply( + copy_to_device(target_device=device)).prefetch(buffer_size) return _apply_fn @@ -371,8 +71,11 @@ def copy_to_device(target_device, source_device="/cpu:0"): """ def _apply_fn(dataset): + options = dataset_ops.Options() + options.experimental_autotune = False return _CopyToDeviceDataset( - dataset, target_device=target_device, source_device=source_device) + dataset, target_device=target_device, + source_device=source_device).with_options(options) return _apply_fn @@ -380,7 +83,7 @@ def copy_to_device(target_device, source_device="/cpu:0"): # TODO(rohanj): Use the _input_hostmem attr on the RemoteCall ops to indicate # all inputs to the Op are in host memory, thereby avoiding some unnecessary # Sends and Recvs. -class _CopyToDeviceDataset(dataset_ops.UnaryDataset): +class _CopyToDeviceDataset(dataset_ops.UnaryUnchangedStructureDataset): """A `Dataset` that copies elements to another device.""" def __init__(self, input_dataset, target_device, source_device="/cpu:0"): @@ -529,18 +232,6 @@ class _CopyToDeviceDataset(dataset_ops.UnaryDataset): output_types=self._flat_output_types, output_shapes=self._flat_output_shapes) - @property - def output_types(self): - return self._input_dataset.output_types - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_classes(self): - return self._input_dataset.output_classes - class _MapOnGpuDataset(dataset_ops.UnaryDataset): """A `Dataset` that maps a function over elements in its using a GPU.""" @@ -551,36 +242,35 @@ class _MapOnGpuDataset(dataset_ops.UnaryDataset): self._input_dataset = input_dataset self._use_inter_op_parallelism = use_inter_op_parallelism - wrapped_func = dataset_ops.StructuredFunctionWrapper( + self._map_func = dataset_ops.StructuredFunctionWrapper( map_func, self._transformation_name(), dataset=input_dataset, defun_kwargs={"experimental_ints_on_device": True}) - self._output_classes = wrapped_func.output_classes - self._output_shapes = wrapped_func.output_shapes - self._output_types = wrapped_func.output_types - self._map_func = wrapped_func.function + + def _functions(self): + return [self._map_func] def _as_variant_tensor(self): input_t = self._input_dataset._as_variant_tensor() # pylint: disable=protected-access return ged_ops.experimental_map_dataset( input_t, - self._map_func.captured_inputs, - f=self._map_func, + self._map_func.function.captured_inputs, + f=self._map_func.function, use_inter_op_parallelism=self._use_inter_op_parallelism, **dataset_ops.flat_structure(self)) @property def output_classes(self): - return self._output_classes + return self._map_func.output_classes @property def output_shapes(self): - return self._output_shapes + return self._map_func.output_shapes @property def output_types(self): - return self._output_types + return self._map_func.output_types def _transformation_name(self): return "map_on_gpu()" diff --git a/tensorflow/python/data/experimental/ops/random_ops.py b/tensorflow/python/data/experimental/ops/random_ops.py index e3a2aeab31..a4359f356b 100644 --- a/tensorflow/python/data/experimental/ops/random_ops.py +++ b/tensorflow/python/data/experimental/ops/random_ops.py @@ -17,26 +17,28 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import functools + from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.util import random_seed from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape -from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops from tensorflow.python.util.tf_export import tf_export -@tf_export("data.experimental.RandomDataset") -class RandomDataset(dataset_ops.DatasetSource): +@tf_export("data.experimental.RandomDataset", v1=[]) +class RandomDatasetV2(dataset_ops.DatasetSource): """A `Dataset` of pseudorandom values.""" def __init__(self, seed=None): """A `Dataset` of pseudorandom values.""" - super(RandomDataset, self).__init__() + super(RandomDatasetV2, self).__init__() self._seed, self._seed2 = random_seed.get_seed(seed) def _as_variant_tensor(self): - return gen_dataset_ops.random_dataset( + return gen_experimental_dataset_ops.experimental_random_dataset( seed=self._seed, seed2=self._seed2, **dataset_ops.flat_structure(self)) @@ -52,3 +54,18 @@ class RandomDataset(dataset_ops.DatasetSource): @property def output_types(self): return dtypes.int64 + + +@tf_export(v1=["data.experimental.RandomDataset"]) +class RandomDatasetV1(dataset_ops.DatasetV1Adapter): + """A `Dataset` of pseudorandom values.""" + + @functools.wraps(RandomDatasetV2.__init__) + def __init__(self, seed=None): + wrapped = RandomDatasetV2(seed) + super(RandomDatasetV1, self).__init__(wrapped) + + +# TODO(b/119044825): Until all `tf.data` unit tests are converted to V2, keep +# this alias in place. +RandomDataset = RandomDatasetV1 diff --git a/tensorflow/python/data/experimental/ops/readers.py b/tensorflow/python/data/experimental/ops/readers.py index fe60192586..a4c260dde7 100644 --- a/tensorflow/python/data/experimental/ops/readers.py +++ b/tensorflow/python/data/experimental/ops/readers.py @@ -19,6 +19,7 @@ from __future__ import print_function import collections import csv +import functools import numpy as np @@ -36,7 +37,6 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.lib.io import file_io -from tensorflow.python.ops import gen_dataset_ops from tensorflow.python.ops import gen_experimental_dataset_ops from tensorflow.python.ops import io_ops from tensorflow.python.platform import gfile @@ -307,8 +307,8 @@ def make_tf_record_dataset(file_pattern, return dataset.prefetch(buffer_size=prefetch_buffer_size) -@tf_export("data.experimental.make_csv_dataset") -def make_csv_dataset( +@tf_export("data.experimental.make_csv_dataset", v1=[]) +def make_csv_dataset_v2( file_pattern, batch_size, column_names=None, @@ -507,11 +507,42 @@ def make_csv_dataset( return dataset +@tf_export(v1=["data.experimental.make_csv_dataset"]) +def make_csv_dataset_v1( + file_pattern, + batch_size, + column_names=None, + column_defaults=None, + label_name=None, + select_columns=None, + field_delim=",", + use_quote_delim=True, + na_value="", + header=True, + num_epochs=None, + shuffle=True, + shuffle_buffer_size=10000, + shuffle_seed=None, + prefetch_buffer_size=optimization.AUTOTUNE, + num_parallel_reads=1, + sloppy=False, + num_rows_for_inference=100, + compression_type=None, +): # pylint: disable=missing-docstring + return dataset_ops.DatasetV1Adapter(make_csv_dataset_v2( + file_pattern, batch_size, column_names, column_defaults, label_name, + select_columns, field_delim, use_quote_delim, na_value, header, + num_epochs, shuffle, shuffle_buffer_size, shuffle_seed, + prefetch_buffer_size, num_parallel_reads, sloppy, num_rows_for_inference, + compression_type)) +make_csv_dataset_v1.__doc__ = make_csv_dataset_v2.__doc__ + + _DEFAULT_READER_BUFFER_SIZE_BYTES = 4 * 1024 * 1024 # 4 MB -@tf_export("data.experimental.CsvDataset") -class CsvDataset(dataset_ops.DatasetSource): +@tf_export("data.experimental.CsvDataset", v1=[]) +class CsvDatasetV2(dataset_ops.DatasetSource): """A Dataset comprising lines from one or more CSV files.""" def __init__(self, @@ -541,7 +572,9 @@ class CsvDataset(dataset_ops.DatasetSource): We can construct a CsvDataset from it as follows: ```python - dataset = tf.data.experimental.CsvDataset( + tf.enable_eager_execution() + + dataset = tf.data.experimental.CsvDataset( "my_file*.csv", [tf.float32, # Required field, use dtype or empty tensor tf.constant([0.0], dtype=tf.float32), # Optional field, default to 0.0 @@ -553,13 +586,8 @@ class CsvDataset(dataset_ops.DatasetSource): The expected output of its iterations is: ```python - next_element = dataset.make_one_shot_iterator().get_next() - with tf.Session() as sess: - while True: - try: - print(sess.run(next_element)) - except tf.errors.OutOfRangeError: - break + for element in dataset: + print(element) >> (4.28e10, 5.55e6, 12) >> (-5.3e14, 0.0, 2) @@ -594,7 +622,7 @@ class CsvDataset(dataset_ops.DatasetSource): the input data. If specified, only this subset of columns will be parsed. Defaults to parsing all columns. """ - super(CsvDataset, self).__init__() + super(CsvDatasetV2, self).__init__() self._filenames = ops.convert_to_tensor( filenames, dtype=dtypes.string, name="filenames") self._compression_type = convert.optional_param_to_tensor( @@ -658,22 +686,43 @@ class CsvDataset(dataset_ops.DatasetSource): return self._output_classes -@tf_export("data.experimental.make_batched_features_dataset") -def make_batched_features_dataset(file_pattern, - batch_size, - features, - reader=core_readers.TFRecordDataset, - label_key=None, - reader_args=None, - num_epochs=None, - shuffle=True, - shuffle_buffer_size=10000, - shuffle_seed=None, - prefetch_buffer_size=optimization.AUTOTUNE, - reader_num_threads=1, - parser_num_threads=2, - sloppy_ordering=False, - drop_final_batch=False): +@tf_export(v1=["data.experimental.CsvDataset"]) +class CsvDatasetV1(dataset_ops.DatasetV1Adapter): + """A Dataset comprising lines from one or more CSV files.""" + + @functools.wraps(CsvDatasetV2.__init__) + def __init__(self, + filenames, + record_defaults, + compression_type=None, + buffer_size=None, + header=False, + field_delim=",", + use_quote_delim=True, + na_value="", + select_cols=None): + wrapped = CsvDatasetV2(filenames, record_defaults, compression_type, + buffer_size, header, field_delim, use_quote_delim, + na_value, select_cols) + super(CsvDatasetV1, self).__init__(wrapped) + + +@tf_export("data.experimental.make_batched_features_dataset", v1=[]) +def make_batched_features_dataset_v2(file_pattern, + batch_size, + features, + reader=core_readers.TFRecordDataset, + label_key=None, + reader_args=None, + num_epochs=None, + shuffle=True, + shuffle_buffer_size=10000, + shuffle_seed=None, + prefetch_buffer_size=optimization.AUTOTUNE, + reader_num_threads=1, + parser_num_threads=2, + sloppy_ordering=False, + drop_final_batch=False): """Returns a `Dataset` of feature dictionaries from `Example` protos. If label_key argument is provided, returns a `Dataset` of tuple @@ -819,6 +868,31 @@ def make_batched_features_dataset(file_pattern, return dataset +@tf_export(v1=["data.experimental.make_batched_features_dataset"]) +def make_batched_features_dataset_v1(file_pattern, # pylint: disable=missing-docstring + batch_size, + features, + reader=core_readers.TFRecordDataset, + label_key=None, + reader_args=None, + num_epochs=None, + shuffle=True, + shuffle_buffer_size=10000, + shuffle_seed=None, + prefetch_buffer_size=optimization.AUTOTUNE, + reader_num_threads=1, + parser_num_threads=2, + sloppy_ordering=False, + drop_final_batch=False): + return dataset_ops.DatasetV1Adapter(make_batched_features_dataset_v2( + file_pattern, batch_size, features, reader, label_key, reader_args, + num_epochs, shuffle, shuffle_buffer_size, shuffle_seed, + prefetch_buffer_size, reader_num_threads, parser_num_threads, + sloppy_ordering, drop_final_batch)) +make_batched_features_dataset_v2.__doc__ = ( + make_batched_features_dataset_v1.__doc__) + + def _get_file_names(file_pattern, shuffle): """Parse list of file names from pattern, optionally shuffled. @@ -850,8 +924,8 @@ def _get_file_names(file_pattern, shuffle): return file_names -@tf_export("data.experimental.SqlDataset") -class SqlDataset(dataset_ops.DatasetSource): +@tf_export("data.experimental.SqlDataset", v1=[]) +class SqlDatasetV2(dataset_ops.DatasetSource): """A `Dataset` consisting of the results from a SQL query.""" def __init__(self, driver_name, data_source_name, query, output_types): @@ -861,17 +935,14 @@ class SqlDataset(dataset_ops.DatasetSource): For example: ```python + tf.enable_eager_execution() + dataset = tf.data.experimental.SqlDataset("sqlite", "/foo/bar.sqlite3", "SELECT name, age FROM people", (tf.string, tf.int32)) - iterator = dataset.make_one_shot_iterator() - next_element = iterator.get_next() # Prints the rows of the result set of the above query. - while True: - try: - print(sess.run(next_element)) - except tf.errors.OutOfRangeError: - break + for element in dataset: + print(element) ``` Args: @@ -883,7 +954,7 @@ class SqlDataset(dataset_ops.DatasetSource): output_types: A tuple of `tf.DType` objects representing the types of the columns returned by `query`. """ - super(SqlDataset, self).__init__() + super(SqlDatasetV2, self).__init__() self._driver_name = ops.convert_to_tensor( driver_name, dtype=dtypes.string, name="driver_name") self._data_source_name = ops.convert_to_tensor( @@ -893,10 +964,9 @@ class SqlDataset(dataset_ops.DatasetSource): self._output_types = output_types def _as_variant_tensor(self): - return gen_dataset_ops.sql_dataset(self._driver_name, - self._data_source_name, self._query, - nest.flatten(self.output_types), - nest.flatten(self.output_shapes)) + return gen_experimental_dataset_ops.experimental_sql_dataset( + self._driver_name, self._data_source_name, self._query, + nest.flatten(self.output_types), nest.flatten(self.output_shapes)) @property def output_classes(self): @@ -910,3 +980,21 @@ class SqlDataset(dataset_ops.DatasetSource): @property def output_types(self): return self._output_types + + +@tf_export(v1=["data.experimental.SqlDataset"]) +class SqlDatasetV1(dataset_ops.DatasetV1Adapter): + """A `Dataset` consisting of the results from a SQL query.""" + + @functools.wraps(SqlDatasetV2.__init__) + def __init__(self, driver_name, data_source_name, query, output_types): + wrapped = SqlDatasetV2(driver_name, data_source_name, query, output_types) + super(SqlDatasetV1, self).__init__(wrapped) + + +# TODO(b/119044825): Until all `tf.data` unit tests are converted to V2, keep +# these aliases in place. +CsvDataset = CsvDatasetV1 +SqlDataset = SqlDatasetV1 +make_batched_features_dataset = make_batched_features_dataset_v1 +make_csv_dataset = make_csv_dataset_v1 diff --git a/tensorflow/python/data/experimental/ops/scan_ops.py b/tensorflow/python/data/experimental/ops/scan_ops.py index 1194238e2f..c768373cf4 100644 --- a/tensorflow/python/data/experimental/ops/scan_ops.py +++ b/tensorflow/python/data/experimental/ops/scan_ops.py @@ -24,7 +24,7 @@ from tensorflow.python.data.util import nest from tensorflow.python.data.util import sparse from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor -from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops from tensorflow.python.util.tf_export import tf_export @@ -125,16 +125,19 @@ class _ScanDataset(dataset_ops.UnaryDataset): self._state_shapes = nest.pack_sequence_as(self._state_shapes, weakened_state_shapes) - self._scan_func = wrapped_func.function - self._scan_func.add_to_graph(ops.get_default_graph()) + self._scan_func = wrapped_func + self._scan_func.function.add_to_graph(ops.get_default_graph()) + + def _functions(self): + return [self._scan_func] def _as_variant_tensor(self): input_t = self._input_dataset._as_variant_tensor() # pylint: disable=protected-access - return gen_dataset_ops.scan_dataset( + return gen_experimental_dataset_ops.experimental_scan_dataset( input_t, nest.flatten(sparse.serialize_sparse_tensors(self._initial_state)), - self._scan_func.captured_inputs, - f=self._scan_func, + self._scan_func.function.captured_inputs, + f=self._scan_func.function, **dataset_ops.flat_structure(self)) @property diff --git a/tensorflow/python/data/experimental/ops/shuffle_ops.py b/tensorflow/python/data/experimental/ops/shuffle_ops.py index a4307212da..d12328a714 100644 --- a/tensorflow/python/data/experimental/ops/shuffle_ops.py +++ b/tensorflow/python/data/experimental/ops/shuffle_ops.py @@ -26,7 +26,7 @@ from tensorflow.python.ops import gen_dataset_ops from tensorflow.python.util.tf_export import tf_export -class _ShuffleAndRepeatDataset(dataset_ops.UnaryDataset): +class _ShuffleAndRepeatDataset(dataset_ops.UnaryUnchangedStructureDataset): """A `Dataset` that fuses `shuffle` and `repeat`.""" def __init__(self, input_dataset, buffer_size, count=None, seed=None): @@ -53,18 +53,6 @@ class _ShuffleAndRepeatDataset(dataset_ops.UnaryDataset): **dataset_ops.flat_structure(self)) # pylint: enable=protected-access - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - @tf_export("data.experimental.shuffle_and_repeat") def shuffle_and_repeat(buffer_size, count=None, seed=None): diff --git a/tensorflow/python/data/experimental/ops/sleep.py b/tensorflow/python/data/experimental/ops/sleep.py index 7e7d370f70..5e9d021ada 100644 --- a/tensorflow/python/data/experimental/ops/sleep.py +++ b/tensorflow/python/data/experimental/ops/sleep.py @@ -21,7 +21,7 @@ from tensorflow.python.data.ops import dataset_ops from tensorflow.python.ops import gen_experimental_dataset_ops -class _SleepDataset(dataset_ops.UnaryDataset): +class _SleepDataset(dataset_ops.UnaryUnchangedStructureDataset): """A `Dataset` that sleeps before producing each upstream element.""" def __init__(self, input_dataset, sleep_microseconds): diff --git a/tensorflow/python/data/experimental/ops/stats_aggregator.py b/tensorflow/python/data/experimental/ops/stats_aggregator.py index 5274c816a4..d5fcc033ab 100644 --- a/tensorflow/python/data/experimental/ops/stats_aggregator.py +++ b/tensorflow/python/data/experimental/ops/stats_aggregator.py @@ -17,7 +17,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops from tensorflow.python.util.tf_export import tf_export @@ -47,7 +47,6 @@ class StatsAggregator(object): options = dataset_ops.Options() options.experimental_stats = tf.data.experimental.StatsOptions(aggregator) dataset = dataset.with_options(options) - iterator = dataset.make_one_shot_iterator() ``` To get a protocol buffer summary of the currently aggregated statistics, @@ -69,7 +68,7 @@ class StatsAggregator(object): def __init__(self): """Creates a `StatsAggregator`.""" - self._resource = gen_dataset_ops.stats_aggregator_handle() + self._resource = ged_ops.experimental_stats_aggregator_handle() # TODO(b/116314787): Update this/add support for V2 summary API. def get_summary(self): @@ -81,4 +80,4 @@ class StatsAggregator(object): Returns: A scalar string `tf.Tensor` that summarizes the aggregated statistics. """ - return gen_dataset_ops.stats_aggregator_summary(self._resource) + return ged_ops.experimental_stats_aggregator_summary(self._resource) diff --git a/tensorflow/python/data/experimental/ops/stats_ops.py b/tensorflow/python/data/experimental/ops/stats_ops.py index ca2f5f2a88..15a9d24546 100644 --- a/tensorflow/python/data/experimental/ops/stats_ops.py +++ b/tensorflow/python/data/experimental/ops/stats_ops.py @@ -20,7 +20,7 @@ from __future__ import print_function from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops -from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops from tensorflow.python.util import deprecation from tensorflow.python.util.tf_export import tf_export @@ -66,8 +66,10 @@ def bytes_produced_stats(tag): """ def _apply_fn(dataset): - return _StatsDataset(dataset, gen_dataset_ops.bytes_produced_stats_dataset, - tag) + return _StatsDataset( + dataset, + gen_experimental_dataset_ops.experimental_bytes_produced_stats_dataset, + tag) return _apply_fn @@ -89,12 +91,14 @@ def latency_stats(tag): """ def _apply_fn(dataset): - return _StatsDataset(dataset, gen_dataset_ops.latency_stats_dataset, tag) + return _StatsDataset( + dataset, + gen_experimental_dataset_ops.experimental_latency_stats_dataset, tag) return _apply_fn -class _StatsDataset(dataset_ops.UnaryDataset): +class _StatsDataset(dataset_ops.UnaryUnchangedStructureDataset): """A `Dataset` that acts as an identity, and also records statistics.""" def __init__(self, input_dataset, op_function, tag): @@ -108,15 +112,3 @@ class _StatsDataset(dataset_ops.UnaryDataset): self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access self._tag, **dataset_ops.flat_structure(self)) - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - - @property - def output_classes(self): - return self._input_dataset.output_classes diff --git a/tensorflow/python/data/experimental/ops/stats_options.py b/tensorflow/python/data/experimental/ops/stats_options.py index c088d3d888..6e884aa08a 100644 --- a/tensorflow/python/data/experimental/ops/stats_options.py +++ b/tensorflow/python/data/experimental/ops/stats_options.py @@ -20,25 +20,24 @@ from __future__ import division from __future__ import print_function from tensorflow.python.data.experimental.ops import stats_aggregator +from tensorflow.python.data.util import options from tensorflow.python.util.tf_export import tf_export @tf_export("data.experimental.StatsOptions") -class StatsOptions(object): +class StatsOptions(options.OptionsBase): """Represents options for collecting dataset stats using `StatsAggregator`. To apply `StatsOptions` with a `tf.data.Dataset` object, use the following pattern: ```python - aggretator = tf.data.experimental.StatsAggregator() + aggregator = tf.data.experimental.StatsAggregator() - options = dataset_ops.Options() + options = tf.data.Options() options.experimental_stats = tf.data.experimental.StatsOptions() options.experimental_stats.aggregator = aggregator dataset = dataset.with_options(options) - - iterator = dataset.make_one_shot_iterator() ``` Note: a `StatsAggregator` object can be attached either duing construction or @@ -52,52 +51,29 @@ class StatsOptions(object): ``` """ - for _name, _ty, _default, _docstring in [ - ("aggregator", stats_aggregator.StatsAggregator, None, - "Associate the given statistics options with the dataset pipeline."), - ("prefix", str, "", - "Prefix to prepend all statistics recorded for the input `dataset` with." - ), - ("counter_prefix", str, "", - "Prefix for the statistics recorded as counter."), - ("latency_all_edges", bool, True, - "Whether to add latency measurements on all edges."), - ]: - - def _make_getter(name): # pylint: disable=no-self-argument - - def getter(self): - return getattr(self, "_" + name) - - return getter - - def _make_setter(name, ty): # pylint: disable=no-self-argument - - def setter(self, value): - if not isinstance(value, ty): - raise TypeError( - "Attempting to set the option %s to incompatible value: %r when " - "it expects %r" % (name, value, ty)) - setattr(self, "_" + name, value) - - return setter - - vars()["_" + _name] = _default - vars()[_name] = property( - _make_getter(_name), _make_setter(_name, _ty), _default, _docstring) - - def __init__(self, aggregator=None): - if aggregator: - self.aggregator = aggregator - - def __eq__(self, other): - if isinstance(other, self.__class__): - return self.__dict__ == other.__dict__ - else: - return False - - def __ne__(self, other): - return not self.__eq__(other) - - def __str__(self): - return str(self.__dict__) + aggregator = options.create_option( + name="aggregator", + ty=stats_aggregator.StatsAggregator, + docstring= + "Associates the given statistics aggregator with the dataset pipeline.") + + prefix = options.create_option( + name="prefix", + ty=str, + docstring= + "Prefix to prepend all statistics recorded for the input `dataset` with.", + default="") + + counter_prefix = options.create_option( + name="counter_prefix", + ty=str, + docstring= + "Prefix for the statistics recorded as counter.", + default="") + + latency_all_edges = options.create_option( + name="latency_all_edges", + ty=bool, + docstring= + "Whether to add latency measurements on all edges.", + default=True) diff --git a/tensorflow/python/data/experimental/ops/threading_options.py b/tensorflow/python/data/experimental/ops/threading_options.py new file mode 100644 index 0000000000..dbf662186f --- /dev/null +++ b/tensorflow/python/data/experimental/ops/threading_options.py @@ -0,0 +1,50 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Experimental API for controlling threading in `tf.data` pipelines.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + + +from tensorflow.python.data.util import options +from tensorflow.python.util.tf_export import tf_export + + +@tf_export("data.experimental.ThreadingOptions") +class ThreadingOptions(options.OptionsBase): + """Represents options for dataset threading. + + To apply `ThreadingOptions` to a `dataset` object, use the following pattern: + + ```python + options = tf.data.Options() + options.experimental_threading = tf.data.experimental.ThreadingOptions() + options.experimental_threading.private_threadpool_size = 10 + dataset = dataset.with_options(options) + ``` + """ + + max_intra_op_parallelism = options.create_option( + name="max_intra_op_parallelism", + ty=int, + docstring= + "If set, it overrides the maximum degree of intra-op parallelism.") + + private_threadpool_size = options.create_option( + name="private_threadpool_size", + ty=int, + docstring= + "If set, the dataset will use a private threadpool of the given size.", + default=None) diff --git a/tensorflow/python/data/experimental/ops/threadpool.py b/tensorflow/python/data/experimental/ops/threadpool.py index 3ea017c6e8..69e8829d68 100644 --- a/tensorflow/python/data/experimental/ops/threadpool.py +++ b/tensorflow/python/data/experimental/ops/threadpool.py @@ -60,7 +60,7 @@ class PrivateThreadPool(object): display_name=display_name) -class _ThreadPoolDataset(dataset_ops.UnaryDataset): +class _ThreadPoolDataset(dataset_ops.UnaryUnchangedStructureDataset): """A `Dataset` that acts as an identity, and sets a custom threadpool.""" def __init__(self, input_dataset, thread_pool): @@ -74,18 +74,6 @@ class _ThreadPoolDataset(dataset_ops.UnaryDataset): self._thread_pool._resource, # pylint: disable=protected-access **dataset_ops.flat_structure(self)) - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - - @property - def output_classes(self): - return self._input_dataset.output_classes - # TODO(b/73383364): Properly export in the `tf.data.experimental` API when # stable or make private / remove. diff --git a/tensorflow/python/data/experimental/ops/unique.py b/tensorflow/python/data/experimental/ops/unique.py index 2a7775c456..55ed98d854 100644 --- a/tensorflow/python/data/experimental/ops/unique.py +++ b/tensorflow/python/data/experimental/ops/unique.py @@ -48,7 +48,7 @@ def unique(): return _apply_fn -class _UniqueDataset(dataset_ops.UnaryDataset): +class _UniqueDataset(dataset_ops.UnaryUnchangedStructureDataset): """A `Dataset` contains the unique elements from its input.""" def __init__(self, input_dataset): @@ -65,15 +65,3 @@ class _UniqueDataset(dataset_ops.UnaryDataset): return gen_experimental_dataset_ops.experimental_unique_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access **dataset_ops.flat_structure(self)) - - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types diff --git a/tensorflow/python/data/experimental/ops/writers.py b/tensorflow/python/data/experimental/ops/writers.py index 994447cb4d..aef6da5140 100644 --- a/tensorflow/python/data/experimental/ops/writers.py +++ b/tensorflow/python/data/experimental/ops/writers.py @@ -22,7 +22,7 @@ from tensorflow.python.data.util import convert from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape -from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops from tensorflow.python.util.tf_export import tf_export @@ -48,7 +48,7 @@ class TFRecordWriter(object): Returns: A `tf.Operation` that, when run, writes contents of `dataset` to a file. """ - if not isinstance(dataset, dataset_ops.Dataset): + if not isinstance(dataset, dataset_ops.DatasetV2): raise TypeError("`dataset` must be a `tf.data.Dataset` object.") if (dataset.output_types != dtypes.string or dataset.output_shapes != tensor_shape.scalar()): @@ -56,5 +56,5 @@ class TFRecordWriter(object): "`dataset` must produce scalar `DT_STRING` tensors whereas it " "produces shape {0} and types {1}".format(dataset.output_shapes, dataset.output_types)) - return gen_dataset_ops.dataset_to_tf_record( + return gen_experimental_dataset_ops.experimental_dataset_to_tf_record( dataset._as_variant_tensor(), self._filename, self._compression_type) # pylint: disable=protected-access diff --git a/tensorflow/python/data/kernel_tests/BUILD b/tensorflow/python/data/kernel_tests/BUILD index 21eed2b070..9f7ce99cbc 100644 --- a/tensorflow/python/data/kernel_tests/BUILD +++ b/tensorflow/python/data/kernel_tests/BUILD @@ -10,48 +10,46 @@ load("//tensorflow:tensorflow.bzl", "tf_py_test") load("//tensorflow:tensorflow.bzl", "cuda_py_test") tf_py_test( - name = "batch_dataset_op_test", + name = "batch_test", size = "small", - srcs = ["batch_dataset_op_test.py"], + srcs = ["batch_test.py"], additional_deps = [ ":test_base", "@absl_py//absl/testing:parameterized", "//third_party/py/numpy", + "//tensorflow/python/data/ops:dataset_ops", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", - "//tensorflow/python:constant_op", "//tensorflow/python:dtypes", "//tensorflow/python:errors", "//tensorflow/python:math_ops", - "//tensorflow/python:string_ops", - "//tensorflow/python:tensor_shape", - "//tensorflow/python:util", - "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python:sparse_tensor", ], ) tf_py_test( - name = "cache_dataset_op_test", + name = "cache_test", size = "small", - srcs = ["cache_dataset_op_test.py"], + srcs = ["cache_test.py"], additional_deps = [ ":test_base", "//third_party/py/numpy", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/data/ops:iterator_ops", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", "//tensorflow/python:constant_op", "//tensorflow/python:dtypes", "//tensorflow/python:errors", + "//tensorflow/python:framework_ops", "//tensorflow/python:variables", - "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/data/ops:iterator_ops", ], ) tf_py_test( - name = "concatenate_dataset_op_test", + name = "concatenate_test", size = "small", - srcs = ["concatenate_dataset_op_test.py"], + srcs = ["concatenate_test.py"], additional_deps = [ ":test_base", "//third_party/py/numpy", @@ -64,153 +62,257 @@ tf_py_test( ) tf_py_test( - name = "dataset_constructor_op_test", + name = "dataset_checkpoint_test", size = "small", - srcs = ["dataset_constructor_op_test.py"], + srcs = ["dataset_checkpoint_test.py"], additional_deps = [ ":test_base", - "//third_party/py/numpy", - "//tensorflow/core:protos_all_py", - "//tensorflow/python:array_ops", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/data/ops:iterator_ops", "//tensorflow/python:client_testlib", + "//tensorflow/python:dataset_ops_gen", "//tensorflow/python:dtypes", "//tensorflow/python:errors", "//tensorflow/python:framework_ops", - "//tensorflow/python:math_ops", - "//tensorflow/python:random_ops", - "//tensorflow/python:resource_variable_ops", - "//tensorflow/python:session", - "//tensorflow/python:sparse_tensor", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:io_ops", + "//tensorflow/python:parsing_ops", + "//tensorflow/python:platform", "//tensorflow/python:tensor_shape", + "//tensorflow/python:variables", + ], +) + +tf_py_test( + name = "dataset_test", + size = "small", + srcs = ["dataset_test.py"], + additional_deps = [ + ":test_base", + "@absl_py//absl/testing:parameterized", + "//third_party/py/numpy", + "//tensorflow/core:protos_all_py", "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/data/ops:readers", "//tensorflow/python/data/util:nest", - "//tensorflow/python/data/util:sparse", - ], - tags = [ - "manual", - "nomac", # b/62040583 + "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", + "//tensorflow/python:sparse_tensor", ], ) tf_py_test( - name = "dataset_from_generator_op_test", - size = "medium", - srcs = ["dataset_from_generator_op_test.py"], + name = "filter_test", + size = "small", + srcs = ["filter_test.py"], additional_deps = [ ":test_base", "//third_party/py/numpy", + "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", "//tensorflow/python:dtypes", "//tensorflow/python:errors", - "//tensorflow/python:tensor_shape", + "//tensorflow/python:functional_ops", + "//tensorflow/python:math_ops", + "//tensorflow/python:sparse_tensor", "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/data/util:sparse", ], ) tf_py_test( - name = "dataset_ops_test", + name = "fixed_length_record_dataset_test", size = "small", - srcs = ["dataset_ops_test.py"], + srcs = ["fixed_length_record_dataset_test.py"], + additional_deps = [ + ":test_base", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:dataset_ops_gen", + "//tensorflow/python:dtypes", + "//tensorflow/python:errors", + "//tensorflow/python:framework_ops", + "//tensorflow/python:io_ops", + "//tensorflow/python:parsing_ops", + "//tensorflow/python:tensor_shape", + "//tensorflow/python:util", + "//tensorflow/python/data/ops:iterator_ops", + "//tensorflow/python/data/ops:readers", + ], +) + +tf_py_test( + name = "flat_map_test", + size = "medium", + srcs = ["flat_map_test.py"], additional_deps = [ ":test_base", - "@absl_py//absl/testing:parameterized", "//third_party/py/numpy", + "//tensorflow/core:protos_all_py", + "//tensorflow/python/data/ops:readers", + "//tensorflow/python/data/util:nest", "//tensorflow/python:client_testlib", + "//tensorflow/python:errors", + "//tensorflow/python:session", + "//tensorflow/python:sparse_ops", "//tensorflow/python:sparse_tensor", + "//tensorflow/python:training", "//tensorflow/python/data/ops:dataset_ops", ], + grpc_enabled = True, +) + +tf_py_test( + name = "from_generator_test", + size = "medium", + srcs = ["from_generator_test.py"], + additional_deps = [ + ":test_base", + "//third_party/py/numpy", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:constant_op", + "//tensorflow/python:dtypes", + "//tensorflow/python:errors", + "//tensorflow/python:script_ops", + "//tensorflow/python:session", + ], ) tf_py_test( - name = "filter_dataset_op_test", + name = "from_sparse_tensor_slices_test", size = "small", - srcs = ["filter_dataset_op_test.py"], + srcs = ["from_sparse_tensor_slices_test.py"], additional_deps = [ ":test_base", "//third_party/py/numpy", + "//tensorflow/core:protos_all_py", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", "//tensorflow/python:dtypes", "//tensorflow/python:errors", - "//tensorflow/python:functional_ops", + "//tensorflow/python:framework_ops", "//tensorflow/python:math_ops", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:session", "//tensorflow/python:sparse_tensor", + "//tensorflow/python:tensor_shape", "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/data/util:nest", ], ) tf_py_test( - name = "flat_map_dataset_op_test", + name = "from_tensors_test", size = "small", - srcs = ["flat_map_dataset_op_test.py"], + srcs = ["from_tensors_test.py"], additional_deps = [ ":test_base", "//third_party/py/numpy", + "//tensorflow/core:protos_all_py", + "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", "//tensorflow/python:errors", + "//tensorflow/python:framework_ops", + "//tensorflow/python:math_ops", + "//tensorflow/python:resource_variable_ops", "//tensorflow/python:session", - "//tensorflow/python:sparse_ops", "//tensorflow/python:sparse_tensor", - "//tensorflow/python:training", + "//tensorflow/python:tensor_shape", "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/data/util:nest", + ], + tags = [ + "nomac", # b/62040583 ], - grpc_enabled = True, ) tf_py_test( - name = "list_files_dataset_op_test", + name = "from_tensor_slices_test", size = "small", - srcs = ["list_files_dataset_op_test.py"], + srcs = ["from_tensor_slices_test.py"], additional_deps = [ ":test_base", - "//tensorflow/python:array_ops", + "//third_party/py/numpy", "//tensorflow/python:client_testlib", "//tensorflow/python:dtypes", "//tensorflow/python:errors", - "//tensorflow/python:util", + "//tensorflow/python:sparse_tensor", + "//tensorflow/python:tensor_shape", "//tensorflow/python/data/ops:dataset_ops", ], ) tf_py_test( - name = "inputs_test", - size = "small", - srcs = ["inputs_test.py"], + name = "interleave_test", + size = "medium", + srcs = ["interleave_test.py"], additional_deps = [ ":test_base", "@absl_py//absl/testing:parameterized", "//third_party/py/numpy", + "//tensorflow/core:protos_all_py", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", + "//tensorflow/python:errors", + "//tensorflow/python:script_ops", + "//tensorflow/python:sparse_ops", "//tensorflow/python:sparse_tensor", + ], +) + +tf_py_test( + name = "iterator_checkpoint_test", + size = "medium", + srcs = ["iterator_checkpoint_test.py"], + additional_deps = [ + ":test_base", "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/eager:context", + "//tensorflow/python/training/checkpointable:util", + "//tensorflow/python:checkpoint_management", + "//tensorflow/python:client_testlib", + "//tensorflow/python:errors", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:math_ops", ], + grpc_enabled = True, ) tf_py_test( - name = "interleave_dataset_op_test", + name = "iterator_cluster_test", size = "small", - srcs = ["interleave_dataset_op_test.py"], + srcs = ["iterator_cluster_test.py"], additional_deps = [ - ":test_base", - "@absl_py//absl/testing:parameterized", - "//third_party/py/numpy", + "//tensorflow/core:protos_all_py", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/data/ops:iterator_ops", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", + "//tensorflow/python:constant_op", "//tensorflow/python:dtypes", "//tensorflow/python:errors", + "//tensorflow/python:framework_ops", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:function", + "//tensorflow/python:functional_ops", + "//tensorflow/python:lookup_ops", + "//tensorflow/python:math_ops", "//tensorflow/python:session", - "//tensorflow/python:sparse_ops", - "//tensorflow/python:sparse_tensor", - "//tensorflow/python:training", - "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python:string_ops", + ], + grpc_enabled = True, + tags = [ + "no_oss", # Test flaky due to port collisions. + "no_windows", ], ) cuda_py_test( - name = "iterator_ops_test", - size = "small", - srcs = ["iterator_ops_test.py"], + name = "iterator_test", + size = "medium", + srcs = ["iterator_test.py"], additional_deps = [ "@absl_py//absl/testing:parameterized", "//third_party/py/numpy", @@ -249,41 +351,30 @@ cuda_py_test( ) tf_py_test( - name = "iterator_ops_cluster_test", + name = "list_files_test", size = "small", - srcs = ["iterator_ops_cluster_test.py"], + srcs = ["list_files_test.py"], additional_deps = [ - "//tensorflow/core:protos_all_py", + ":test_base", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", "//tensorflow/python:dtypes", "//tensorflow/python:errors", - "//tensorflow/python:framework_ops", - "//tensorflow/python:framework_test_lib", - "//tensorflow/python:function", - "//tensorflow/python:functional_ops", - "//tensorflow/python:session", + "//tensorflow/python:util", "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/data/ops:iterator_ops", - "//tensorflow/python:constant_op", - "//tensorflow/python:string_ops", - "//tensorflow/python:lookup_ops", - ], - grpc_enabled = True, - tags = [ - "no_oss", # Test flaky due to port collisions. - "no_windows", ], ) tf_py_test( - name = "map_dataset_op_test", - size = "small", - srcs = ["map_dataset_op_test.py"], + name = "map_test", + size = "medium", + srcs = ["map_test.py"], additional_deps = [ ":test_base", "@absl_py//absl/testing:parameterized", "//third_party/py/numpy", + "//tensorflow/core:protos_all_py", + "//tensorflow/python/data/ops:dataset_ops", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", "//tensorflow/python:constant_op", @@ -297,27 +388,12 @@ tf_py_test( "//tensorflow/python:math_ops", "//tensorflow/python:random_ops", "//tensorflow/python:script_ops", + "//tensorflow/python:session", "//tensorflow/python:sparse_ops", "//tensorflow/python:sparse_tensor", "//tensorflow/python:string_ops", + "//tensorflow/python:tensor_util", "//tensorflow/python:variable_scope", - "//tensorflow/python/data/ops:dataset_ops", - ], -) - -tf_py_test( - name = "matching_files_dataset_op_test", - size = "small", - srcs = ["matching_files_dataset_op_test.py"], - additional_deps = [ - ":test_base", - "//third_party/py/numpy", - "//tensorflow/python:array_ops", - "//tensorflow/python:client_testlib", - "//tensorflow/python:dtypes", - "//tensorflow/python:errors", - "//tensorflow/python:util", - "//tensorflow/python/data/ops:dataset_ops", ], ) @@ -332,6 +408,7 @@ cuda_py_test( "//tensorflow/python/data/ops:multi_device_iterator_ops", "//tensorflow/python/data/ops:iterator_ops", "//tensorflow/python/data/experimental/ops:optimization", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", "//tensorflow/python:dtypes", @@ -345,9 +422,9 @@ cuda_py_test( ) cuda_py_test( - name = "optional_ops_test", + name = "optional_test", size = "small", - srcs = ["optional_ops_test.py"], + srcs = ["optional_test.py"], additional_deps = [ ":test_base", "@absl_py//absl/testing:parameterized", @@ -366,70 +443,58 @@ cuda_py_test( ) tf_py_test( - name = "prefetch_dataset_op_test", + name = "padded_batch_test", size = "small", - srcs = ["prefetch_dataset_op_test.py"], + srcs = ["padded_batch_test.py"], additional_deps = [ ":test_base", "@absl_py//absl/testing:parameterized", + "//third_party/py/numpy", + "//tensorflow/python/data/ops:dataset_ops", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", - "//tensorflow/python:dataset_ops_gen", + "//tensorflow/python:constant_op", "//tensorflow/python:dtypes", "//tensorflow/python:errors", - "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python:sparse_tensor", + "//tensorflow/python:string_ops", + "//tensorflow/python:tensor_shape", + "//tensorflow/python:util", ], ) tf_py_test( - name = "range_dataset_op_test", + name = "prefetch_test", size = "small", - srcs = ["range_dataset_op_test.py"], + srcs = ["prefetch_test.py"], additional_deps = [ ":test_base", + "@absl_py//absl/testing:parameterized", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", "//tensorflow/python:dataset_ops_gen", "//tensorflow/python:dtypes", "//tensorflow/python:errors", - "//tensorflow/python:io_ops", - "//tensorflow/python:framework_ops", - "//tensorflow/python:parsing_ops", - "//tensorflow/python:platform", - "//tensorflow/python:tensor_shape", - "//tensorflow/python:variables", - "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/data/ops:iterator_ops", ], ) tf_py_test( - name = "reader_dataset_ops_test", + name = "range_test", size = "small", - srcs = ["reader_dataset_ops_test.py"], + srcs = ["range_test.py"], additional_deps = [ ":test_base", - "//tensorflow/python:array_ops", + "//tensorflow/python/data/ops:dataset_ops", "//tensorflow/python:client_testlib", - "//tensorflow/python:constant_op", - "//tensorflow/python:dataset_ops_gen", - "//tensorflow/python:dtypes", "//tensorflow/python:errors", - "//tensorflow/python:framework_ops", - "//tensorflow/python:io_ops", - "//tensorflow/python:lib", - "//tensorflow/python:parsing_ops", - "//tensorflow/python:tensor_shape", - "//tensorflow/python:util", - "//tensorflow/python/data/ops:iterator_ops", - "//tensorflow/python/data/ops:readers", + "//tensorflow/python:framework_test_lib", ], ) tf_py_test( - name = "reduce_dataset_op_test", + name = "reduce_test", size = "small", - srcs = ["reduce_dataset_op_test.py"], + srcs = ["reduce_test.py"], additional_deps = [ ":test_base", "@absl_py//absl/testing:parameterized", @@ -437,7 +502,6 @@ tf_py_test( "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", "//tensorflow/python:dtypes", - "//tensorflow/python:errors", "//tensorflow/python:math_ops", "//tensorflow/python:sparse_tensor", "//tensorflow/python/data/ops:dataset_ops", @@ -445,9 +509,9 @@ tf_py_test( ) tf_py_test( - name = "sequence_dataset_op_test", + name = "repeat_test", size = "small", - srcs = ["sequence_dataset_op_test.py"], + srcs = ["repeat_test.py"], additional_deps = [ ":test_base", "//third_party/py/numpy", @@ -460,9 +524,9 @@ tf_py_test( ) tf_py_test( - name = "shard_dataset_op_test", + name = "shard_test", size = "small", - srcs = ["shard_dataset_op_test.py"], + srcs = ["shard_test.py"], additional_deps = [ ":test_base", "//tensorflow/python:client_testlib", @@ -472,9 +536,9 @@ tf_py_test( ) tf_py_test( - name = "shuffle_dataset_op_test", + name = "shuffle_test", size = "small", - srcs = ["shuffle_dataset_op_test.py"], + srcs = ["shuffle_test.py"], additional_deps = [ ":test_base", "@absl_py//absl/testing:parameterized", @@ -491,21 +555,91 @@ tf_py_test( ], ) +tf_py_test( + name = "skip_test", + size = "small", + srcs = ["skip_test.py"], + additional_deps = [ + ":test_base", + "//third_party/py/numpy", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", + "//tensorflow/python:errors", + "//tensorflow/python/data/ops:dataset_ops", + ], +) + +tf_py_test( + name = "take_test", + size = "small", + srcs = ["take_test.py"], + additional_deps = [ + ":test_base", + "//third_party/py/numpy", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", + "//tensorflow/python:errors", + "//tensorflow/python/data/ops:dataset_ops", + ], +) + +tf_py_test( + name = "text_line_dataset_test", + size = "small", + srcs = ["text_line_dataset_test.py"], + additional_deps = [ + ":test_base", + "//tensorflow/python/data/ops:iterator_ops", + "//tensorflow/python/data/ops:readers", + "//tensorflow/python/eager:context", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", + "//tensorflow/python:errors", + "//tensorflow/python:util", + ], +) + +tf_py_test( + name = "tf_record_dataset_test", + size = "small", + srcs = ["tf_record_dataset_test.py"], + additional_deps = [ + ":test_base", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/data/ops:iterator_ops", + "//tensorflow/python/data/ops:readers", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:constant_op", + "//tensorflow/python:dtypes", + "//tensorflow/python:errors", + "//tensorflow/python:lib", + "//tensorflow/python:util", + ], +) + py_library( name = "test_base", srcs = ["test_base.py"], deps = [ + "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", + "//tensorflow/python:dtypes", "//tensorflow/python:errors", "//tensorflow/python:sparse_tensor", + "//tensorflow/python/data/ops:dataset_ops", "//tensorflow/python/data/util:nest", + "//tensorflow/python/eager:context", ], ) tf_py_test( - name = "window_dataset_op_test", - size = "small", - srcs = ["window_dataset_op_test.py"], + name = "window_test", + size = "medium", + srcs = ["window_test.py"], additional_deps = [ ":test_base", "@absl_py//absl/testing:parameterized", @@ -521,9 +655,9 @@ tf_py_test( ) tf_py_test( - name = "zip_dataset_op_test", + name = "zip_test", size = "small", - srcs = ["zip_dataset_op_test.py"], + srcs = ["zip_test.py"], additional_deps = [ ":test_base", "//third_party/py/numpy", diff --git a/tensorflow/python/data/kernel_tests/batch_dataset_op_test.py b/tensorflow/python/data/kernel_tests/batch_dataset_op_test.py deleted file mode 100644 index e8decb9ad0..0000000000 --- a/tensorflow/python/data/kernel_tests/batch_dataset_op_test.py +++ /dev/null @@ -1,515 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import time - -from absl.testing import parameterized -import numpy as np - -from tensorflow.python.client import session -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import sparse_tensor -from tensorflow.python.framework import tensor_shape -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import string_ops -from tensorflow.python.platform import test -from tensorflow.python.util import compat - - -class BatchDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): - - @parameterized.named_parameters( - ('even', 28, 14, False), - ('uneven_with_remainder', 28, 15, False), - ('uneven_without_remainder', 28, 15, True), - ('empty', 0, 14, False), - ) - def testBatchDataset(self, count, batch_size, drop_remainder): - """Tests the batch dataset logic for various input configurations. - - Args: - count: the number of input elements - batch_size: the batch size - drop_remainder: whether a smaller batch size should be produced if batch - size does not divide number of inputs evenly - """ - - # The pipeline is TensorSliceDataset -> MapDataset(square_3) -> - # RepeatDataset(count) -> BatchDataset(batch_size). - components = (np.arange(7), - np.array([[1, 2, 3]]) * np.arange(7)[:, np.newaxis], - np.array(37.0) * np.arange(7)) - - count_t = array_ops.placeholder(dtypes.int64, shape=[]) - batch_size_t = array_ops.placeholder(dtypes.int64, shape=[]) - drop_remainder_t = array_ops.placeholder(dtypes.bool, shape=[]) - - def _map_fn(x, y, z): - return math_ops.square(x), math_ops.square(y), math_ops.square(z) - - iterator = ( - dataset_ops.Dataset.from_tensor_slices(components).map(_map_fn) - .repeat(count).batch(batch_size, - drop_remainder).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - if drop_remainder: - dim0 = batch_size - else: - dim0 = None - self.assertEqual([[dim0] + list(c.shape[1:]) for c in components], - [t.shape.as_list() for t in get_next]) - - with self.cached_session() as sess: - sess.run( - init_op, - feed_dict={ - count_t: count, - batch_size_t: batch_size, - drop_remainder_t: drop_remainder - }) - num_full_batches = (count * 7) // batch_size - for i in range(num_full_batches): - result = sess.run(get_next) - for component, result_component in zip(components, result): - for j in range(batch_size): - self.assertAllEqual(component[(i * batch_size + j) % 7]**2, - result_component[j]) - if not drop_remainder and (count * 7) % batch_size > 0: - result = sess.run(get_next) - for component, result_component in zip(components, result): - for j in range((count * 7) % batch_size): - self.assertAllEqual( - component[(num_full_batches * batch_size + j) % 7]**2, - result_component[j]) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testBatchDatasetInvalidBatchSize(self): - iterator = (dataset_ops.Dataset.range(10).batch(0).make_one_shot_iterator()) - get_next = iterator.get_next() - - with self.cached_session() as sess: - with self.assertRaises(errors.InvalidArgumentError): - sess.run(get_next) - - def testBatchSparse(self): - - def _sparse(i): - return sparse_tensor.SparseTensorValue( - indices=[[0]], values=(i * [1]), dense_shape=[1]) - - iterator = dataset_ops.Dataset.range(10).map(_sparse).batch( - 5).make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(2): - actual = sess.run(get_next) - expected = sparse_tensor.SparseTensorValue( - indices=[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], - values=[i * 5, i * 5 + 1, i * 5 + 2, i * 5 + 3, i * 5 + 4], - dense_shape=[5, 1]) - self.assertTrue(sparse_tensor.is_sparse(actual)) - self.assertSparseValuesEqual(actual, expected) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testBatchSparseWithDifferentDenseShapes(self): - - def _sparse(i): - return sparse_tensor.SparseTensorValue( - indices=array_ops.expand_dims( - math_ops.range(i, dtype=dtypes.int64), 1), - values=array_ops.fill([math_ops.to_int32(i)], i), - dense_shape=[i]) - - iterator = dataset_ops.Dataset.range(10).map(_sparse).batch( - 5).make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(2): - actual = sess.run(get_next) - expected_indices = [] - expected_values = [] - for j in range(5): - for k in range(i * 5 + j): - expected_indices.append([j, k]) - expected_values.append(i * 5 + j) - expected = sparse_tensor.SparseTensorValue( - indices=expected_indices, - values=expected_values, - dense_shape=[5, (i + 1) * 5 - 1]) - self.assertTrue(sparse_tensor.is_sparse(actual)) - self.assertSparseValuesEqual(actual, expected) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testNestedBatchSparse(self): - - def _sparse(i): - return sparse_tensor.SparseTensorValue( - indices=[[0]], values=(i * [1]), dense_shape=[1]) - - iterator = dataset_ops.Dataset.range(10).map(_sparse).batch(5).batch( - 2).make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - actual = sess.run(get_next) - expected = sparse_tensor.SparseTensorValue( - indices=[[0, 0, 0], [0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 4, 0], - [1, 0, 0], [1, 1, 0], [1, 2, 0], [1, 3, 0], [1, 4, 0]], - values=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], - dense_shape=[2, 5, 1]) - self.assertTrue(sparse_tensor.is_sparse(actual)) - self.assertSparseValuesEqual(actual, expected) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testBatchShapeError(self): - - def generator(): - yield [1.0, 2.0, 3.0] - yield [4.0, 5.0, 6.0] - yield [7.0, 8.0, 9.0, 10.0] - - iterator = ( - dataset_ops.Dataset.from_generator( - generator, dtypes.float32, output_shapes=[None]).batch(3) - .make_initializable_iterator()) - next_element = iterator.get_next() - - with self.cached_session() as sess: - sess.run(iterator.initializer) - with self.assertRaisesRegexp( - errors.InvalidArgumentError, - r'Cannot batch tensors with different shapes in component 0. ' - r'First element had shape \[3\] and element 2 had shape \[4\].'): - sess.run(next_element) - - -def _random_seq_lens(count): - return np.random.randint(20, size=(count,)).astype(np.int32) - - -class PaddedBatchDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): - - @parameterized.named_parameters( - ('default_padding', _random_seq_lens(32), 4, [-1], False), - ('constant_padding', _random_seq_lens(32), 4, [25], False), - ('uneven_with_remainder', _random_seq_lens(34), 4, [-1], False), - ('uneven_without_remainder', _random_seq_lens(34), 4, [-1], True), - ) - def testPaddedBatchDataset(self, seq_lens, batch_size, padded_shapes, - drop_remainder): - """Tests the padded batch dataset logic for various input configurations. - - Args: - seq_lens: the input sequence lengths - batch_size: the batch size - padded_shapes: the padded shapes to use - drop_remainder: whether a smaller batch size should be produced if batch - size does not divide number of inputs evenly - """ - - seq_lens_t = array_ops.placeholder(dtypes.int32, shape=[None]) - batch_size_t = array_ops.placeholder(dtypes.int64, shape=[]) - padded_shapes_t = array_ops.placeholder(dtypes.int64, shape=[1]) - drop_remainder_t = array_ops.placeholder(dtypes.bool, shape=[]) - - iterator = ( - dataset_ops.Dataset.from_tensor_slices(seq_lens_t) - .map(lambda x: array_ops.fill([x], x)).padded_batch( - batch_size=batch_size_t, - drop_remainder=drop_remainder_t, - padded_shapes=padded_shapes_t).make_initializable_iterator()) - - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run( - init_op, - feed_dict={ - seq_lens_t: seq_lens, - batch_size_t: batch_size, - padded_shapes_t: padded_shapes, - drop_remainder_t: drop_remainder, - }) - - num_full_batches = len(seq_lens) // batch_size - - for i in range(num_full_batches): - result = sess.run(get_next) - padded_len = padded_shapes[0] - if padded_len is None or padded_len == -1: - padded_len = np.max(result) if result.size > 0 else 0 - self.assertEqual((batch_size, padded_len), result.shape) - for j in range(batch_size): - seq_len = seq_lens[(i * batch_size) + j] - self.assertAllEqual(result[j, :seq_len], [seq_len] * seq_len) - self.assertAllEqual(result[j, seq_len:], - [0] * (padded_len - seq_len)) - - if not drop_remainder and len(seq_lens) % batch_size > 0: - result = sess.run(get_next) - padded_len = np.max(result) if result.size > 0 else 0 - self.assertEqual((len(seq_lens) % batch_size, padded_len), - result.shape) - for j in range(len(seq_lens) % batch_size): - seq_len = seq_lens[num_full_batches * batch_size + j] - self.assertAllEqual(result[j, :seq_len], [seq_len] * seq_len) - self.assertAllEqual(result[j, seq_len:], - [0] * (padded_len - seq_len)) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testPaddedBatchShortPadding(self): - iterator = ( - dataset_ops.Dataset.from_tensor_slices([6, 5, 5, 5, 5]) - .map(lambda x: array_ops.fill([x], x)).padded_batch( - batch_size=4, padded_shapes=[5]).make_one_shot_iterator()) - get_next = iterator.get_next() - - with self.cached_session() as sess: - with self.assertRaises(errors.DataLossError): - sess.run(get_next) - - def testPaddedBatchEmptyTensors(self): - iterator = ( - dataset_ops.Dataset.from_tensor_slices([0, 0, 0, 0]) - .map(lambda x: array_ops.fill([x], x)).padded_batch( - batch_size=4, padded_shapes=[-1]).make_one_shot_iterator()) - get_next = iterator.get_next() - - with self.cached_session() as sess: - result = sess.run(get_next) - self.assertAllEqual([[], [], [], []], result) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testPaddedBatchDatasetNonDefaultPadding(self): - seq_lens = array_ops.placeholder(dtypes.int32, shape=[None]) - padded_shape = array_ops.placeholder(dtypes.int64, shape=[1]) - - def fill_tuple(x): - filled = array_ops.fill([x], x) - return (filled, string_ops.as_string(filled)) - - iterator = ( - dataset_ops.Dataset.from_tensor_slices(seq_lens).map(fill_tuple) - .padded_batch( - 4, - padded_shapes=(padded_shape, padded_shape), - padding_values=(-1, '')).make_initializable_iterator()) - - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - # Test with random sequence lengths, and max padding. - random_seq_lens = np.random.randint(20, size=(32,)).astype(np.int32) - sess.run( - init_op, feed_dict={ - padded_shape: [-1], - seq_lens: random_seq_lens - }) - for i in range(8): - result = sess.run(get_next) - padded_len = np.max(result[0]) - self.assertEqual((4, padded_len), result[0].shape) - self.assertEqual((4, padded_len), result[1].shape) - for j in range(4): - seq_len = random_seq_lens[(i * 4) + j] - self.assertAllEqual(result[0][j, :seq_len], [seq_len] * seq_len) - self.assertAllEqual(result[0][j, seq_len:], - [-1] * (padded_len - seq_len)) - self.assertAllEqual(result[1][j, :seq_len], - [compat.as_bytes(str(seq_len))] * seq_len) - self.assertAllEqual(result[1][j, seq_len:], - [b''] * (padded_len - seq_len)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testPaddedBatchDatasetUnicode(self): - # See GitHub issue 16149 - def generator(): - data = [[u'Простой', u'тест', u'юникода'], - [u'никогда', u'не', u'бывает', u'простым']] - - for seq in data: - yield seq, [0, 1, 2, 3] - - dataset = dataset_ops.Dataset.from_generator( - generator, (dtypes.string, dtypes.int32), - (tensor_shape.TensorShape([None]), tensor_shape.TensorShape([None]))) - padded_dataset = dataset.padded_batch( - 2, padded_shapes=([None], [None]), padding_values=('', 0)) - with self.cached_session() as sess: - next_element = padded_dataset.make_one_shot_iterator().get_next() - sess.run(next_element) - - def testPaddedBatchDatasetShapeSpecifications(self): - int_placeholder = array_ops.placeholder(dtypes.int32) - float_placeholder = array_ops.placeholder(dtypes.float32) - string_placeholder = array_ops.placeholder(dtypes.string) - input_dataset = dataset_ops.Dataset.from_tensors( - (int_placeholder, float_placeholder, string_placeholder)) - - # Test different ways of specifying the `padded_shapes` argument. - dynamic_padding_from_tensor_shapes = input_dataset.padded_batch( - 32, - padded_shapes=(tensor_shape.TensorShape([None]), - tensor_shape.TensorShape([None, None]), - tensor_shape.TensorShape([37]))) - dynamic_padding_from_lists = input_dataset.padded_batch( - 32, padded_shapes=([None], [None, None], [37])) - dynamic_padding_from_lists_with_minus_one = input_dataset.padded_batch( - 32, padded_shapes=([-1], [-1, -1], [37])) - dynamic_padding_from_tensors = input_dataset.padded_batch( - 32, - padded_shapes=(constant_op.constant([-1], dtype=dtypes.int64), - constant_op.constant([-1, -1], dtype=dtypes.int64), - constant_op.constant([37], dtype=dtypes.int64))) - - for dataset in [ - dynamic_padding_from_tensor_shapes, dynamic_padding_from_lists, - dynamic_padding_from_lists_with_minus_one, dynamic_padding_from_tensors - ]: - self.assertEqual([None, None], dataset.output_shapes[0].as_list()) - self.assertEqual([None, None, None], dataset.output_shapes[1].as_list()) - self.assertEqual([None, 37], dataset.output_shapes[2].as_list()) - - def testPaddedBatchSparseError(self): - - def _map_fn(i): - return sparse_tensor.SparseTensorValue( - indices=[[0, 0]], values=(i * [1]), dense_shape=[1, 1]), i - - with self.assertRaises(TypeError): - _ = dataset_ops.Dataset.range(10).map(_map_fn).padded_batch(10) - - def testPaddedBatchShapeError(self): - with self.assertRaisesRegexp( - ValueError, r'The padded shape \(1,\) is not compatible with the ' - r'corresponding input component shape \(\).'): - _ = dataset_ops.Dataset.range(10).padded_batch(5, padded_shapes=[1]) - - with self.assertRaisesRegexp( - ValueError, r'The padded shape \(1,\) is not compatible with the ' - r'corresponding input component shape \(3,\).'): - _ = dataset_ops.Dataset.from_tensors([1, 2, 3]).padded_batch( - 5, padded_shapes=[1]) - - with self.assertRaisesRegexp( - ValueError, r'Padded shape .* must be a 1-D tensor ' - r'of tf.int64 values, but its shape was \(2, 2\).'): - _ = dataset_ops.Dataset.from_tensors([1, 2, 3]).padded_batch( - 5, padded_shapes=[[1, 1], [1, 1]]) - - with self.assertRaisesRegexp( - TypeError, r'Padded shape .* must be a 1-D tensor ' - r'of tf.int64 values, but its element type was float32.'): - _ = dataset_ops.Dataset.from_tensors([1, 2, 3]).padded_batch( - 5, padded_shapes=constant_op.constant([1., 2., 3.])) - - with self.assertRaisesRegexp( - ValueError, r'The padded shape \(1,\) is not compatible with the ' - r'corresponding input component shape \(\).'): - shape_as_tensor = constant_op.constant([1], dtype=dtypes.int64) - _ = dataset_ops.Dataset.range(10).padded_batch( - 5, padded_shapes=shape_as_tensor) - - with self.assertRaisesRegexp( - ValueError, - r'The padded shape \((\?|None), (\?|None)\) is not compatible with the ' - r'corresponding input component shape \(\).'): - shape_as_tensor = array_ops.placeholder(dtypes.int64, shape=[2]) - _ = dataset_ops.Dataset.range(10).padded_batch( - 5, padded_shapes=shape_as_tensor) - - -class BatchDatasetBenchmark(test.Benchmark): - - def benchmarkBatchSparse(self): - non_zeros_per_row_values = [0, 1, 5, 10, 100] - batch_size_values = [1, 32, 64, 128, 1024] - - sparse_placeholder = array_ops.sparse_placeholder(dtype=dtypes.int64) - batch_size_placeholder = array_ops.placeholder(dtype=dtypes.int64, shape=[]) - - dataset = dataset_ops.Dataset.from_tensors(sparse_placeholder).repeat( - ).batch(batch_size_placeholder) - iterator = dataset.make_initializable_iterator() - next_element = iterator.get_next() - - for non_zeros_per_row in non_zeros_per_row_values: - - sparse_value = sparse_tensor.SparseTensorValue( - indices=np.arange(non_zeros_per_row, dtype=np.int64)[:, np.newaxis], - values=np.arange(non_zeros_per_row, dtype=np.int64), - dense_shape=[1000]) - - for batch_size in batch_size_values: - - with session.Session() as sess: - sess.run(iterator.initializer, feed_dict={ - sparse_placeholder: sparse_value, - batch_size_placeholder: batch_size}) - # Run five steps to warm up the session caches before taking the - # first measurement. - for _ in range(5): - sess.run(next_element.indices.op) - deltas = [] - for _ in range(100): - start = time.time() - for _ in range(100): - sess.run(next_element.indices.op) - end = time.time() - deltas.append(end - start) - - median_wall_time = np.median(deltas) / 100.0 - - print('Batch sparse dataset non-zeros per row: %d batch_size: %d ' - 'wall time: %f' - % (non_zeros_per_row, batch_size, median_wall_time)) - self.report_benchmark( - iters=10000, wall_time=median_wall_time, - name='benchmark_batch_sparse_dataset_nnz_%d_batch_size_%d' % ( - non_zeros_per_row, batch_size)) - - -if __name__ == '__main__': - test.main() diff --git a/tensorflow/python/data/kernel_tests/batch_test.py b/tensorflow/python/data/kernel_tests/batch_test.py new file mode 100644 index 0000000000..5b035e5917 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/batch_test.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.batch()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from absl.testing import parameterized +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.util import nest +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors +from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class BatchTest(test_base.DatasetTestBase, parameterized.TestCase): + + @parameterized.named_parameters( + ('even', 28, 14, False), + ('uneven_with_remainder', 28, 15, False), + ('uneven_without_remainder', 28, 15, True), + ('empty', 0, 14, False), + ) + def testBatchDataset(self, count, batch_size, drop_remainder): + """Tests the batch dataset logic for various input configurations. + + Args: + count: the number of input elements + batch_size: the batch size + drop_remainder: whether a smaller batch size should be produced if batch + size does not divide number of inputs evenly + """ + + # The pipeline is TensorSliceDataset -> MapDataset(square_3) -> + # RepeatDataset(count) -> BatchDataset(batch_size). + components = (np.arange(7), + np.array([[1, 2, 3]]) * np.arange(7)[:, np.newaxis], + np.array(37.0) * np.arange(7)) + + def _map_fn(x, y, z): + return math_ops.square(x), math_ops.square(y), math_ops.square(z) + + dataset = dataset_ops.Dataset.from_tensor_slices(components).map( + _map_fn).repeat(count).batch(batch_size, drop_remainder) + get_next = self.getNext(dataset) + + if drop_remainder: + dim0 = batch_size + else: + dim0 = None + self.assertEqual( + [ts.as_list() for ts in nest.flatten(dataset.output_shapes)], + [[dim0] + list(c.shape[1:]) for c in components]) + + num_full_batches = (count * 7) // batch_size + for i in range(num_full_batches): + result = self.evaluate(get_next()) + for component, result_component in zip(components, result): + for j in range(batch_size): + self.assertAllEqual(component[(i * batch_size + j) % 7]**2, + result_component[j]) + if not drop_remainder and (count * 7) % batch_size > 0: + result = self.evaluate(get_next()) + for component, result_component in zip(components, result): + for j in range((count * 7) % batch_size): + self.assertAllEqual( + component[(num_full_batches * batch_size + j) % 7]**2, + result_component[j]) + with self.assertRaises(errors.OutOfRangeError): + result = self.evaluate(get_next()) + + def testBatchDatasetInvalidBatchSize(self): + dataset = (dataset_ops.Dataset.range(10).batch(0)) + self.assertDatasetProduces( + dataset, expected_error=(errors.InvalidArgumentError, '')) + + def testBatchSparse(self): + + def _sparse(i): + return sparse_tensor.SparseTensorValue( + indices=[[0]], values=(i * [1]), dense_shape=[1]) + + dataset = dataset_ops.Dataset.range(10).map(_sparse).batch(5) + expected_output = [ + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], + values=[i * 5, i * 5 + 1, i * 5 + 2, i * 5 + 3, i * 5 + 4], + dense_shape=[5, 1]) for i in range(2) + ] + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testBatchSparseWithDifferentDenseShapes(self): + + def _sparse(i): + return sparse_tensor.SparseTensorValue( + indices=array_ops.expand_dims( + math_ops.range(i, dtype=dtypes.int64), 1), + values=array_ops.fill([math_ops.to_int32(i)], i), + dense_shape=[i]) + + dataset = dataset_ops.Dataset.range(10).map(_sparse).batch(5) + expected_output = [] + for i in range(2): + expected_indices = [] + expected_outputs = [] + for j in range(5): + for k in range(i * 5 + j): + expected_indices.append([j, k]) + expected_outputs.append(i * 5 + j) + expected_output.append( + sparse_tensor.SparseTensorValue( + indices=expected_indices, + values=expected_outputs, + dense_shape=[5, (i + 1) * 5 - 1])) + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testNestedBatchSparse(self): + + def _sparse(i): + return sparse_tensor.SparseTensorValue( + indices=[[0]], values=(i * [1]), dense_shape=[1]) + + dataset = dataset_ops.Dataset.range(10).map(_sparse).batch(5).batch(2) + expected_output = [ + sparse_tensor.SparseTensorValue( + indices=[[0, 0, 0], [0, 1, 0], [0, 2, 0], [0, 3, 0], [0, 4, 0], + [1, 0, 0], [1, 1, 0], [1, 2, 0], [1, 3, 0], [1, 4, 0]], + values=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], + dense_shape=[2, 5, 1]) + ] + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testBatchShapeError(self): + + def generator(): + yield [1.0, 2.0, 3.0] + yield [4.0, 5.0, 6.0] + yield [7.0, 8.0, 9.0, 10.0] + + dataset = ( + dataset_ops.Dataset.from_generator( + generator, dtypes.float32, output_shapes=[None]).batch(3)) + self.assertDatasetProduces( + dataset, + expected_error=( + errors.InvalidArgumentError, + r'Cannot batch tensors with different shapes in component 0. First ' + r'element had shape \[3\] and element 2 had shape \[4\].')) + + +if __name__ == '__main__': + test.main() diff --git a/tensorflow/python/data/kernel_tests/cache_dataset_op_test.py b/tensorflow/python/data/kernel_tests/cache_dataset_op_test.py deleted file mode 100644 index 63625fac03..0000000000 --- a/tensorflow/python/data/kernel_tests/cache_dataset_op_test.py +++ /dev/null @@ -1,318 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -from os import path -import shutil -import tempfile - -import numpy as np - -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.data.ops import iterator_ops -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import ops -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import variables -from tensorflow.python.platform import test - - -class FileCacheDatasetTest(test_base.DatasetTestBase): - - def setUp(self): - self.tmp_dir = tempfile.mkdtemp() - self.cache_prefix = path.join(self.tmp_dir, "cache") - - def tearDown(self): - if self.tmp_dir: - shutil.rmtree(self.tmp_dir, ignore_errors=True) - - def testCacheDatasetPassthrough(self): - components = (np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), - np.array([9.0, 10.0, 11.0, 12.0])) - count_placeholder = array_ops.placeholder_with_default( - constant_op.constant(5, dtypes.int64), shape=[]) - filename_placeholder = array_ops.placeholder(dtypes.string, shape=[]) - - repeat_dataset = (dataset_ops.Dataset.from_tensor_slices(components) - .repeat(count_placeholder)) - - cache_dataset = repeat_dataset.cache(filename_placeholder) - - self.assertEqual( - tuple([c.shape[1:] for c in components]), cache_dataset.output_shapes) - - # Create initialization ops for iterators without and with - # caching, respectively. - iterator = iterator_ops.Iterator.from_structure(cache_dataset.output_types, - cache_dataset.output_shapes) - init_fifo_op = iterator.make_initializer(repeat_dataset) - init_cache_op = iterator.make_initializer(cache_dataset) - - get_next = iterator.get_next() - - with self.cached_session() as sess: - # First run without caching to collect the "ground truth". - sess.run(init_fifo_op) - elements = [] - for _ in range(20): - elements.append(sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Assert that the cached dataset has the same elements as the - # "ground truth". - sess.run( - init_cache_op, feed_dict={filename_placeholder: self.cache_prefix}) - cached_elements = [] - for _ in range(20): - cached_elements.append(sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - self.assertAllEqual(elements, cached_elements) - - # Re-initialize with an empty upstream (to throw errors.OutOfRangeError - # if we didn't use the cache). - sess.run( - init_cache_op, - feed_dict={ - count_placeholder: 0, - filename_placeholder: self.cache_prefix - }) - replayed_elements = [] - for _ in range(20): - replayed_elements.append(sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - self.assertEqual(cached_elements, replayed_elements) - - # Re-initialize with an empty upstream and a missing cache file (should - # throw errors.OutOfRangeError immediately). - sess.run( - init_cache_op, - feed_dict={ - count_placeholder: 0, - filename_placeholder: self.cache_prefix + "nonsense" - }) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testConcurrentWriters(self): - components = (np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), - np.array([9.0, 10.0, 11.0, 12.0])) - filename_placeholder = array_ops.placeholder(dtypes.string, shape=[]) - - cache_dataset1 = (dataset_ops.Dataset.from_tensor_slices(components) - .cache(filename_placeholder)) - cache_dataset2 = (dataset_ops.Dataset.from_tensor_slices(components) - .cache(filename_placeholder)) - - iterator1 = cache_dataset1.make_initializable_iterator() - iterator2 = cache_dataset2.make_initializable_iterator() - init_cache_op1 = iterator1.initializer - init_cache_op2 = iterator2.initializer - - get_next1 = iterator1.get_next() - get_next2 = iterator2.get_next() - - with self.cached_session() as sess: - sess.run( - init_cache_op1, feed_dict={filename_placeholder: self.cache_prefix}) - sess.run(get_next1) # this should succeed - - sess.run( - init_cache_op2, feed_dict={filename_placeholder: self.cache_prefix}) - with self.assertRaises(errors.AlreadyExistsError): - sess.run(get_next2) - - sess.run(get_next1) # this should continue to succeed - - def testConcurrentReaders(self): - components = (np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), - np.array([9.0, 10.0, 11.0, 12.0])) - filename_placeholder = array_ops.placeholder(dtypes.string, shape=[]) - - cache_dataset1 = (dataset_ops.Dataset.from_tensor_slices(components) - .cache(filename_placeholder)) - cache_dataset2 = (dataset_ops.Dataset.from_tensor_slices(components) - .cache(filename_placeholder)) - - iterator1 = cache_dataset1.make_initializable_iterator() - iterator2 = cache_dataset2.make_initializable_iterator() - init_cache_op1 = iterator1.initializer - init_cache_op2 = iterator2.initializer - - get_next1 = iterator1.get_next() - get_next2 = iterator2.get_next() - - with self.cached_session() as sess: - sess.run( - init_cache_op1, feed_dict={filename_placeholder: self.cache_prefix}) - elements = [] - for _ in range(4): - elements.append(sess.run(get_next1)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next1) - - # Re-initialize - sess.run( - init_cache_op1, feed_dict={filename_placeholder: self.cache_prefix}) - sess.run( - init_cache_op2, feed_dict={filename_placeholder: self.cache_prefix}) - - # Reading concurrently should succeed. - elements_itr1 = [] - elements_itr2 = [] - elements_itr2.append(sess.run(get_next2)) - elements_itr1.append(sess.run(get_next1)) - elements_itr2.append(sess.run(get_next2)) - elements_itr1.append(sess.run(get_next1)) - # Intentionally reversing the order - elements_itr1.append(sess.run(get_next1)) - elements_itr2.append(sess.run(get_next2)) - elements_itr1.append(sess.run(get_next1)) - elements_itr2.append(sess.run(get_next2)) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next2) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next1) - - self.assertAllEqual(elements, elements_itr1) - self.assertAllEqual(elements, elements_itr2) - - -class MemoryCacheDatasetTest(test_base.DatasetTestBase): - - def testCacheDatasetPassthrough(self): - with ops.device("cpu:0"): - repeat_count = variables.Variable(constant_op.constant(10, dtypes.int64)) - dataset = dataset_ops.Dataset.range(3).flat_map( - lambda x: dataset_ops.Dataset.from_tensors(x).repeat(repeat_count)) - - cached_dataset = dataset.cache().repeat(2) - uncached_dataset = dataset.repeat(2) - - # Needs to be initializable to capture the variable. - cached_iterator = cached_dataset.make_initializable_iterator() - cached_next = cached_iterator.get_next() - uncached_iterator = uncached_dataset.make_initializable_iterator() - uncached_next = uncached_iterator.get_next() - - with self.cached_session() as sess: - - sess.run(repeat_count.initializer) - sess.run(cached_iterator.initializer) - sess.run(uncached_iterator.initializer) - - for i in range(3): - for _ in range(10): - self.assertEqual(sess.run(cached_next), i) - self.assertEqual(sess.run(uncached_next), i) - - sess.run(repeat_count.assign(0)) - - # The uncached iterator should now be empty. - with self.assertRaises(errors.OutOfRangeError): - sess.run(uncached_next) - - # The cached iterator replays from cache. - for i in range(3): - for _ in range(10): - self.assertEqual(sess.run(cached_next), i) - - # The cached iterator should now be empty. - with self.assertRaises(errors.OutOfRangeError): - sess.run(cached_next) - - def testEmptyCacheReading(self): - components = (np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), - np.array([9.0, 10.0, 11.0, 12.0])) - count_placeholder = array_ops.placeholder_with_default( - constant_op.constant(5, dtypes.int64), shape=[]) - - repeat_dataset = (dataset_ops.Dataset.from_tensor_slices(components) - .repeat(count_placeholder)) - - cache_dataset = repeat_dataset.cache() - - # Create initialization ops for iterators without and with - # caching, respectively. - iterator = cache_dataset.make_initializable_iterator() - init_cache_op = iterator.initializer - - get_next = iterator.get_next() - - with self.cached_session() as sess: - # Initialize with an empty upstream and a missing cache file (should - # throw errors.OutOfRangeError immediately). - sess.run(init_cache_op, feed_dict={count_placeholder: 0}) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testConcurrentReaders(self): - count_placeholder = array_ops.placeholder_with_default( - constant_op.constant(5, dtypes.int64), shape=[]) - dataset = dataset_ops.Dataset.range(count_placeholder).cache() - d1 = dataset.map(lambda x: x + 1) - d2 = dataset.map(lambda x: x + 6) - - i1 = d1.make_initializable_iterator() - i2 = d2.make_initializable_iterator() - - with self.cached_session() as sess: - sess.run(i1.initializer) - - self.assertEqual(1, sess.run(i1.get_next())) - self.assertEqual(2, sess.run(i1.get_next())) - self.assertEqual(3, sess.run(i1.get_next())) - - sess.run(i2.initializer, feed_dict={count_placeholder: 3}) - - self.assertEqual(6, sess.run(i2.get_next())) - self.assertEqual(7, sess.run(i2.get_next())) - self.assertEqual(4, sess.run(i1.get_next())) # interleave execution - self.assertEqual([8, 5], sess.run([i2.get_next(), i1.get_next()])) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(i1.get_next()) - with self.assertRaises(errors.OutOfRangeError): - sess.run(i2.get_next()) - - def testCacheTakeRepeat(self): - dataset = dataset_ops.Dataset.range(10).cache().take(5).repeat(2) - itr = dataset.make_one_shot_iterator() - n = itr.get_next() - - expected_values = [0, 1, 2, 3, 4, 0, 1, 2, 3, 4] - - with self.cached_session() as sess: - for i, expected in enumerate(expected_values): - self.assertEqual(expected, sess.run(n), - "Unexpected value at index %s" % i) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(itr.get_next()) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/kernel_tests/cache_test.py b/tensorflow/python/data/kernel_tests/cache_test.py new file mode 100644 index 0000000000..b561cd58ba --- /dev/null +++ b/tensorflow/python/data/kernel_tests/cache_test.py @@ -0,0 +1,253 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.cache()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from os import path +import shutil +import tempfile + +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util +from tensorflow.python.ops import variables +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class FileCacheTest(test_base.DatasetTestBase): + + def setUp(self): + self.tmp_dir = tempfile.mkdtemp() + self.cache_prefix = path.join(self.tmp_dir, "cache") + + def tearDown(self): + if self.tmp_dir: + shutil.rmtree(self.tmp_dir, ignore_errors=True) + + def testCacheDatasetPassthrough(self): + components = (np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), + np.array([9.0, 10.0, 11.0, 12.0])) + + def dataset_fn(count=5, filename=None): + repeat_dataset = ( + dataset_ops.Dataset.from_tensor_slices(components).repeat(count)) + if filename: + return repeat_dataset.cache(filename) + else: + return repeat_dataset + + self.assertEqual( + tuple([c.shape[1:] for c in components]), + dataset_fn().output_shapes) + + get_next = self.getNext(dataset_fn()) + + # First run without caching to collect the "ground truth". + elements = [] + for _ in range(20): + elements.append(self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + # Assert that the cached dataset has the same elements as the + # "ground truth". + get_next = self.getNext(dataset_fn(filename=self.cache_prefix)) + cached_elements = [] + for _ in range(20): + cached_elements.append(self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + self.assertAllEqual(elements, cached_elements) + + # Re-initialize with an empty upstream (to throw errors.OutOfRangeError + # if we didn't use the cache). + get_next = self.getNext(dataset_fn(count=0, filename=self.cache_prefix)) + replayed_elements = [] + for _ in range(20): + replayed_elements.append(self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + self.assertEqual(cached_elements, replayed_elements) + + # Re-initialize with an empty upstream and a missing cache file (should + # throw errors.OutOfRangeError immediately). + get_next = self.getNext( + dataset_fn(count=0, filename=self.cache_prefix + "nonsense")) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + def testConcurrentWriters(self): + components = (np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), + np.array([9.0, 10.0, 11.0, 12.0])) + + cache_dataset1 = ( + dataset_ops.Dataset.from_tensor_slices(components).cache( + self.cache_prefix)) + cache_dataset2 = ( + dataset_ops.Dataset.from_tensor_slices(components).cache( + self.cache_prefix)) + + get_next1 = self.getNext(cache_dataset1) + get_next2 = self.getNext(cache_dataset2) + + self.evaluate(get_next1()) # this should succeed + + with self.assertRaises(errors.AlreadyExistsError): + self.evaluate(get_next2()) + + self.evaluate(get_next1()) # this should continue to succeed + + def testConcurrentReaders(self): + components = (np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), + np.array([9.0, 10.0, 11.0, 12.0])) + + cache_dataset1 = ( + dataset_ops.Dataset.from_tensor_slices(components).cache( + self.cache_prefix)) + cache_dataset2 = ( + dataset_ops.Dataset.from_tensor_slices(components).cache( + self.cache_prefix)) + + get_next1 = self.getNext(cache_dataset1) + get_next2 = self.getNext(cache_dataset2) + + elements = [] + for _ in range(4): + elements.append(self.evaluate(get_next1())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next1()) + + # Re-initialize + get_next1 = self.getNext(cache_dataset1) + get_next2 = self.getNext(cache_dataset2) + + # Reading concurrently should succeed. + elements_itr1 = [] + elements_itr2 = [] + elements_itr2.append(self.evaluate(get_next2())) + elements_itr1.append(self.evaluate(get_next1())) + elements_itr2.append(self.evaluate(get_next2())) + elements_itr1.append(self.evaluate(get_next1())) + # Intentionally reversing the order + elements_itr1.append(self.evaluate(get_next1())) + elements_itr2.append(self.evaluate(get_next2())) + elements_itr1.append(self.evaluate(get_next1())) + elements_itr2.append(self.evaluate(get_next2())) + + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next2()) + + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next1()) + + self.assertAllEqual(elements, elements_itr1) + self.assertAllEqual(elements, elements_itr2) + + +@test_util.run_all_in_graph_and_eager_modes +class MemoryCacheTest(test_base.DatasetTestBase): + + def testCacheDatasetPassthrough(self): + with ops.device("cpu:0"): + repeat_count = variables.Variable(constant_op.constant(10, dtypes.int64)) + dataset = dataset_ops.Dataset.range(3).flat_map( + lambda x: dataset_ops.Dataset.from_tensors(x).repeat(repeat_count)) + + cached_dataset = dataset.cache().repeat(2) + uncached_dataset = dataset.repeat(2) + + self.evaluate(repeat_count.initializer) + # Needs to be initializable to capture the variable. + cached_next = self.getNext(cached_dataset, requires_initialization=True) + uncached_next = self.getNext( + uncached_dataset, requires_initialization=True) + for i in range(3): + for _ in range(10): + self.assertEqual(self.evaluate(cached_next()), i) + self.assertEqual(self.evaluate(uncached_next()), i) + + self.evaluate(repeat_count.assign(0)) + + # The uncached iterator should now be empty. + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(uncached_next()) + + # The cached iterator replays from cache. + for i in range(3): + for _ in range(10): + self.assertEqual(self.evaluate(cached_next()), i) + + # The cached iterator should now be empty. + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(cached_next()) + + def testEmptyCacheReading(self): + components = (np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), + np.array([9.0, 10.0, 11.0, 12.0])) + + repeat_dataset = ( + dataset_ops.Dataset.from_tensor_slices(components).repeat(0)) + cache_dataset = repeat_dataset.cache() + + # Create initialization ops for iterators without and with + # caching, respectively. + self.assertDatasetProduces(cache_dataset, expected_output=[]) + + def testConcurrentReaders(self): + + dataset = dataset_ops.Dataset.range(5).cache() + d1 = dataset.map(lambda x: x + 1) + d2 = dataset.map(lambda x: x + 6) + + get_next1 = self.getNext(d1) + + self.assertEqual(1, self.evaluate(get_next1())) + self.assertEqual(2, self.evaluate(get_next1())) + self.assertEqual(3, self.evaluate(get_next1())) + + get_next2 = self.getNext(d2) + + self.assertEqual(6, self.evaluate(get_next2())) + self.assertEqual(7, self.evaluate(get_next2())) + self.assertEqual(4, self.evaluate(get_next1())) # interleave execution + self.assertEqual([8, 5], + [self.evaluate(get_next2()), + self.evaluate(get_next1())]) + self.assertEqual(9, self.evaluate(get_next2())) + self.assertEqual(10, self.evaluate(get_next2())) + + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next2()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next1()) + + def testCacheTakeRepeat(self): + dataset = dataset_ops.Dataset.range(10).cache().take(5).repeat(2) + + expected_output = [0, 1, 2, 3, 4, 0, 1, 2, 3, 4] + self.assertDatasetProduces(dataset, expected_output=expected_output) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/concatenate_dataset_op_test.py b/tensorflow/python/data/kernel_tests/concatenate_test.py similarity index 75% rename from tensorflow/python/data/kernel_tests/concatenate_dataset_op_test.py rename to tensorflow/python/data/kernel_tests/concatenate_test.py index 83af31f380..5d8bfdc8f3 100644 --- a/tensorflow/python/data/kernel_tests/concatenate_dataset_op_test.py +++ b/tensorflow/python/data/kernel_tests/concatenate_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the experimental input pipeline ops.""" +"""Tests for `tf.data.Dataset.concatenate().""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -24,10 +24,12 @@ from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.util import nest from tensorflow.python.framework import errors from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.platform import test -class ConcatenateDatasetTest(test_base.DatasetTestBase): +@test_util.run_all_in_graph_and_eager_modes +class ConcatenateTest(test_base.DatasetTestBase): def testConcatenateDataset(self): input_components = ( @@ -46,23 +48,19 @@ class ConcatenateDatasetTest(test_base.DatasetTestBase): self.assertEqual(concatenated.output_shapes, (tensor_shape.TensorShape( [20]), tensor_shape.TensorShape([15]), tensor_shape.TensorShape([]))) - iterator = concatenated.make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(9): - result = sess.run(get_next) - if i < 4: - for component, result_component in zip(input_components, result): - self.assertAllEqual(component[i], result_component) - else: - for component, result_component in zip(to_concatenate_components, - result): - self.assertAllEqual(component[i - 4], result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + get_next = self.getNext(concatenated) + + for i in range(9): + result = self.evaluate(get_next()) + if i < 4: + for component, result_component in zip(input_components, result): + self.assertAllEqual(component[i], result_component) + else: + for component, result_component in zip(to_concatenate_components, + result): + self.assertAllEqual(component[i - 4], result_component) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) def testConcatenateDatasetDifferentShape(self): input_components = ( @@ -79,24 +77,18 @@ class ConcatenateDatasetTest(test_base.DatasetTestBase): self.assertEqual( [ts.as_list() for ts in nest.flatten(concatenated.output_shapes)], [[20], [None]]) - - iterator = concatenated.make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(9): - result = sess.run(get_next) - if i < 4: - for component, result_component in zip(input_components, result): - self.assertAllEqual(component[i], result_component) - else: - for component, result_component in zip(to_concatenate_components, - result): - self.assertAllEqual(component[i - 4], result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + get_next = self.getNext(concatenated) + for i in range(9): + result = self.evaluate(get_next()) + if i < 4: + for component, result_component in zip(input_components, result): + self.assertAllEqual(component[i], result_component) + else: + for component, result_component in zip(to_concatenate_components, + result): + self.assertAllEqual(component[i - 4], result_component) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) def testConcatenateDatasetDifferentStructure(self): input_components = ( diff --git a/tensorflow/python/data/kernel_tests/range_dataset_op_test.py b/tensorflow/python/data/kernel_tests/dataset_checkpoint_test.py similarity index 84% rename from tensorflow/python/data/kernel_tests/range_dataset_op_test.py rename to tensorflow/python/data/kernel_tests/dataset_checkpoint_test.py index b71e6b2ea4..6dcd94ea02 100644 --- a/tensorflow/python/data/kernel_tests/range_dataset_op_test.py +++ b/tensorflow/python/data/kernel_tests/dataset_checkpoint_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Test RangeDataset.""" +"""Checkpoint tests for `tf.data.Dataset`.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -26,7 +26,6 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape -from tensorflow.python.framework import test_util from tensorflow.python.ops import gen_dataset_ops from tensorflow.python.ops import io_ops from tensorflow.python.ops import parsing_ops @@ -35,51 +34,7 @@ from tensorflow.python.platform import gfile from tensorflow.python.platform import test -@test_util.run_all_in_graph_and_eager_modes -class RangeDatasetTest(test_base.DatasetTestBase): - - def testStop(self): - dataset = dataset_ops.Dataset.range(5) - self.assertDatasetProduces(dataset, expected_output=range(5)) - - def testStartStop(self): - start, stop = 2, 5 - dataset = dataset_ops.Dataset.range(start, stop) - self.assertDatasetProduces(dataset, expected_output=range(2, 5)) - - def testStartStopStep(self): - start, stop, step = 2, 10, 2 - dataset = dataset_ops.Dataset.range(start, stop, step) - self.assertDatasetProduces(dataset, expected_output=range(2, 10, 2)) - - def testZeroStep(self): - start, stop, step = 2, 10, 0 - dataset = dataset_ops.Dataset.range(start, stop, step) - self.assertDatasetProduces( - dataset, expected_err=(errors.InvalidArgumentError, "")) - - def testNegativeStep(self): - start, stop, step = 2, 10, -1 - dataset = dataset_ops.Dataset.range(start, stop, step) - self.assertDatasetProduces(dataset, expected_output=range(2, 10, -1)) - - def testStopLessThanStart(self): - start, stop = 10, 2 - dataset = dataset_ops.Dataset.range(start, stop) - self.assertDatasetProduces(dataset, expected_output=range(10, 2)) - - def testStopLessThanStartWithPositiveStep(self): - start, stop, step = 10, 2, 2 - dataset = dataset_ops.Dataset.range(start, stop, step) - self.assertDatasetProduces(dataset, expected_output=range(10, 2, 2)) - - def testStopLessThanStartWithNegativeStep(self): - start, stop, step = 10, 2, -1 - dataset = dataset_ops.Dataset.range(start, stop, step) - self.assertDatasetProduces(dataset, expected_output=range(10, 2, -1)) - - -class ExperimentalCheckpointDatasetTest(test_base.DatasetTestBase): +class DatasetCheckpointTest(test_base.DatasetTestBase): def tearDown(self): # Remove all checkpoint files. @@ -109,8 +64,8 @@ class ExperimentalCheckpointDatasetTest(test_base.DatasetTestBase): def testSaveRestore(self): def _build_graph(start, stop): - iterator = dataset_ops.Dataset.range(start, - stop).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(start, stop)) init_op = iterator.initializer get_next = iterator.get_next() save_op = self._save_op(iterator._iterator_resource) @@ -159,7 +114,7 @@ class ExperimentalCheckpointDatasetTest(test_base.DatasetTestBase): def _build_graph(start, stop, num_epochs): dataset = dataset_ops.Dataset.range(start, stop).repeat(num_epochs) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() save_op = self._save_op(iterator._iterator_resource) @@ -206,7 +161,7 @@ class ExperimentalCheckpointDatasetTest(test_base.DatasetTestBase): def _build_graph(start, stop): dataset = dataset_ops.Dataset.range(start, stop) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() save_op = self._save_op(iterator._iterator_resource) @@ -245,7 +200,7 @@ class ExperimentalCheckpointDatasetTest(test_base.DatasetTestBase): def _build_graph(start, stop): dataset = dataset_ops.Dataset.range(start, stop) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() save_op = self._save_op(iterator._iterator_resource) @@ -278,8 +233,8 @@ class ExperimentalCheckpointDatasetTest(test_base.DatasetTestBase): def testMultipleSaves(self): def _build_graph(start, stop): - iterator = dataset_ops.Dataset.range(start, - stop).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(start, stop)) init_op = iterator.initializer get_next = iterator.get_next() save_op = self._save_op(iterator._iterator_resource) @@ -321,8 +276,8 @@ class ExperimentalCheckpointDatasetTest(test_base.DatasetTestBase): def testSaveRestoreWithRepeat(self): def _build_graph(start, stop, num_epochs): - iterator = dataset_ops.Dataset.range( - start, stop).repeat(num_epochs).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(start, stop).repeat(num_epochs)) init_op = iterator.initializer get_next = iterator.get_next() save_op = self._save_op(iterator._iterator_resource) @@ -366,8 +321,8 @@ class ExperimentalCheckpointDatasetTest(test_base.DatasetTestBase): def testSaveRestoreExhaustedIterator(self): def _build_graph(start, stop, num_epochs): - iterator = dataset_ops.Dataset.range( - start, stop).repeat(num_epochs).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(start, stop).repeat(num_epochs)) init_op = iterator.initializer get_next = iterator.get_next() save_op = self._save_op(iterator._iterator_resource) diff --git a/tensorflow/python/data/kernel_tests/dataset_constructor_op_test.py b/tensorflow/python/data/kernel_tests/dataset_constructor_op_test.py deleted file mode 100644 index bc6b36285a..0000000000 --- a/tensorflow/python/data/kernel_tests/dataset_constructor_op_test.py +++ /dev/null @@ -1,650 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import time - -import numpy as np - -from tensorflow.core.protobuf import config_pb2 -from tensorflow.python.client import session -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.data.util import nest -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import ops -from tensorflow.python.framework import sparse_tensor -from tensorflow.python.framework import tensor_shape -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import resource_variable_ops -from tensorflow.python.platform import test - - -class DatasetConstructorTest(test_base.DatasetTestBase): - - def testFromTensors(self): - """Test a dataset that represents a single tuple of tensors.""" - components = (np.array(1), np.array([1, 2, 3]), np.array(37.0)) - - iterator = (dataset_ops.Dataset.from_tensors(components) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([c.shape for c in components], - [t.shape for t in get_next]) - - with self.cached_session() as sess: - sess.run(init_op) - results = sess.run(get_next) - for component, result_component in zip(components, results): - self.assertAllEqual(component, result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testFromTensorsSparse(self): - """Test a dataset that represents a single tuple of tensors.""" - components = (sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([0]), - dense_shape=np.array([1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[0, 0], [1, 1]]), - values=np.array([-1, 1]), - dense_shape=np.array([2, 2]))) - - iterator = ( - dataset_ops.Dataset.from_tensors(components) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual( - [tensor_shape.TensorShape(c.dense_shape) for c in components], - [shape for shape in iterator.output_shapes]) - - with self.cached_session() as sess: - sess.run(init_op) - results = sess.run(get_next) - for component, result_component in zip(components, results): - self.assertSparseValuesEqual(component, result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testFromTensorsMixed(self): - """Test an dataset that represents a single tuple of tensors.""" - components = (np.array(1), np.array([1, 2, 3]), np.array(37.0), - sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([0]), - dense_shape=np.array([1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[0, 0], [1, 1]]), - values=np.array([-1, 1]), - dense_shape=np.array([2, 2]))) - - iterator = ( - dataset_ops.Dataset.from_tensors(components) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([ - tensor_shape.TensorShape(c.dense_shape) - if sparse_tensor.is_sparse(c) else c.shape for c in components - ], [shape for shape in iterator.output_shapes]) - - with self.cached_session() as sess: - sess.run(init_op) - results = sess.run(get_next) - for component, result_component in zip(components, results): - if sparse_tensor.is_sparse(component): - self.assertSparseValuesEqual(component, result_component) - else: - self.assertAllEqual(component, result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testFromTensorSlices(self): - """Test a dataset that represents the slices from a tuple of tensors.""" - components = ( - np.tile(np.array([[1], [2], [3], [4]]), 20), np.tile( - np.array([[12], [13], [14], [15]]), 22), - np.array([37.0, 38.0, 39.0, 40.0]) - ) - - iterator = (dataset_ops.Dataset.from_tensor_slices(components) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([c.shape[1:] for c in components], - [t.shape for t in get_next]) - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(4): - results = sess.run(get_next) - for component, result_component in zip(components, results): - self.assertAllEqual(component[i], result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testFromTensorSlicesSparse(self): - """Test a dataset that represents the slices from a tuple of tensors.""" - components = (sparse_tensor.SparseTensorValue( - indices=np.array([[0, 0], [1, 0], [2, 0]]), - values=np.array([0, 0, 0]), - dense_shape=np.array([3, 1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[0, 0], [1, 1], [2, 2]]), - values=np.array([1, 2, 3]), - dense_shape=np.array([3, 3]))) - - iterator = ( - dataset_ops.Dataset.from_tensor_slices(components) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual( - [tensor_shape.TensorShape(c.dense_shape[1:]) for c in components], - [shape for shape in iterator.output_shapes]) - - with self.cached_session() as sess: - sess.run(init_op) - expected = [ - (sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([0]), - dense_shape=np.array([1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([1]), - dense_shape=np.array([3]))), - (sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([0]), - dense_shape=np.array([1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[1]]), - values=np.array([2]), - dense_shape=np.array([3]))), - (sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([0]), - dense_shape=np.array([1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[2]]), - values=np.array([3]), - dense_shape=np.array([3]))), - ] - for i in range(3): - results = sess.run(get_next) - for component, result_component in zip(expected[i], results): - self.assertSparseValuesEqual(component, result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testFromTensorSlicesMixed(self): - """Test a dataset that represents the slices from a tuple of tensors.""" - components = (np.tile(np.array([[1], [2], [3]]), 20), - np.tile(np.array([[12], [13], [14]]), 22), - np.array([37.0, 38.0, 39.0]), - sparse_tensor.SparseTensorValue( - indices=np.array([[0, 0], [1, 0], [2, 0]]), - values=np.array([0, 0, 0]), - dense_shape=np.array([3, 1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[0, 0], [1, 1], [2, 2]]), - values=np.array([1, 2, 3]), - dense_shape=np.array([3, 3]))) - - iterator = ( - dataset_ops.Dataset.from_tensor_slices(components) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([ - tensor_shape.TensorShape(c.dense_shape[1:]) - if sparse_tensor.is_sparse(c) else c.shape[1:] for c in components - ], [shape for shape in iterator.output_shapes]) - - with self.cached_session() as sess: - sess.run(init_op) - expected = [ - (sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([0]), - dense_shape=np.array([1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([1]), - dense_shape=np.array([3]))), - (sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([0]), - dense_shape=np.array([1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[1]]), - values=np.array([2]), - dense_shape=np.array([3]))), - (sparse_tensor.SparseTensorValue( - indices=np.array([[0]]), - values=np.array([0]), - dense_shape=np.array([1])), - sparse_tensor.SparseTensorValue( - indices=np.array([[2]]), - values=np.array([3]), - dense_shape=np.array([3]))), - ] - for i in range(3): - results = sess.run(get_next) - for component, result_component in zip( - (list(zip(*components[:3]))[i] + expected[i]), results): - if sparse_tensor.is_sparse(component): - self.assertSparseValuesEqual(component, result_component) - else: - self.assertAllEqual(component, result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testFromTensorSlicesWithDict(self): - components = {"foo": [1, 2, 3], "bar": [[4.0], [5.0], [6.0]]} - iterator = (dataset_ops.Dataset.from_tensor_slices(components) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual(dtypes.int32, iterator.output_types["foo"]) - self.assertEqual(dtypes.float32, iterator.output_types["bar"]) - self.assertEqual((), iterator.output_shapes["foo"]) - self.assertEqual((1,), iterator.output_shapes["bar"]) - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(3): - results = sess.run(get_next) - self.assertEqual(components["foo"][i], results["foo"]) - self.assertEqual(components["bar"][i], results["bar"]) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testFromSparseTensorSlices(self): - """Test a dataset based on slices of a `tf.SparseTensor`.""" - st = array_ops.sparse_placeholder(dtypes.float64) - iterator = (dataset_ops.Dataset.from_sparse_tensor_slices(st) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = sparse_tensor.SparseTensor(*iterator.get_next()) - - with self.cached_session() as sess: - slices = [[1., 2., 3.], [1.], [1.], [1., 2.], [], [1., 2.], [], [], []] - - # Test with sparse tensor in the appropriate order. - indices = np.array( - [[i, j] for i in range(len(slices)) for j in range(len(slices[i]))]) - values = np.array([val for s in slices for val in s]) - dense_shape = np.array([len(slices), max(len(s) for s in slices) + 1]) - sparse_feed = sparse_tensor.SparseTensorValue(indices, values, - dense_shape) - sess.run(init_op, feed_dict={st: sparse_feed}) - for i, s in enumerate(slices): - results = sess.run(get_next) - self.assertAllEqual(s, results.values) - expected_indices = np.array( - [[j] for j in range(len(slices[i]))]).reshape([-1, 1]) - self.assertAllEqual(expected_indices, results.indices) - self.assertAllEqual(dense_shape[1:], results.dense_shape) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Test with sparse tensor in the reverse order, which is not - # currently supported. - reverse_order_indices = indices[::-1, :] - reverse_order_values = values[::-1] - sparse_feed = sparse_tensor.SparseTensorValue( - reverse_order_indices, reverse_order_values, dense_shape) - with self.assertRaises(errors.UnimplementedError): - sess.run(init_op, feed_dict={st: sparse_feed}) - - # Test with an empty sparse tensor. - empty_indices = np.empty((0, 4), dtype=np.int64) - empty_values = np.empty((0,), dtype=np.float64) - empty_dense_shape = [0, 4, 37, 9] - sparse_feed = sparse_tensor.SparseTensorValue(empty_indices, empty_values, - empty_dense_shape) - sess.run(init_op, feed_dict={st: sparse_feed}) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # pylint: disable=g-long-lambda,unnecessary-lambda - def testNestedStructure(self): - components = (np.array([1, 2, 3], dtype=np.int64), - (np.array([4., 5.]), np.array([6., 7.])), - np.array([8, 9, 10], dtype=np.int64)) - - dataset = dataset_ops.Dataset.from_tensors(components) - self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), - dtypes.int64), dataset.output_types) - self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) - - dataset = dataset.shuffle(10, 10) - self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), - dtypes.int64), dataset.output_types) - self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) - - dataset = dataset.repeat(-1) - self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), - dtypes.int64), dataset.output_types) - self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) - - dataset = dataset.filter(lambda x, y, z: True) - self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), - dtypes.int64), dataset.output_types) - self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) - - dataset = dataset.take(5) - self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), - dtypes.int64), dataset.output_types) - self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) - - dataset = dataset.map(lambda x, y, z: ((x, z), (y[0], y[1]))) - self.assertEquals(((dtypes.int64, dtypes.int64), - (dtypes.float64, dtypes.float64)), dataset.output_types) - self.assertEquals((([3], [3]), ([2], [2])), dataset.output_shapes) - - dataset = dataset.flat_map( - lambda x, y: dataset_ops.Dataset.from_tensors(((x[0], x[1]), - (y[0], y[1]))) - ) - self.assertEquals(((dtypes.int64, dtypes.int64), - (dtypes.float64, dtypes.float64)), dataset.output_types) - self.assertEquals((([3], [3]), ([2], [2])), dataset.output_shapes) - - dataset = dataset.batch(32) - self.assertEquals(((dtypes.int64, dtypes.int64), - (dtypes.float64, dtypes.float64)), dataset.output_types) - self.assertEquals((([None, 3], [None, 3]), ([None, 2], [None, 2])), - nest.pack_sequence_as(dataset.output_shapes, [ - s.as_list() - for s in nest.flatten(dataset.output_shapes) - ])) - - iterator = dataset.make_one_shot_iterator() - (w, x), (y, z) = iterator.get_next() - self.assertEquals(dtypes.int64, w.dtype) - self.assertEquals(dtypes.int64, x.dtype) - self.assertEquals(dtypes.float64, y.dtype) - self.assertEquals(dtypes.float64, z.dtype) - self.assertEquals([None, 3], w.shape.as_list()) - self.assertEquals([None, 3], x.shape.as_list()) - self.assertEquals([None, 2], y.shape.as_list()) - self.assertEquals([None, 2], z.shape.as_list()) - - iterator = dataset.make_initializable_iterator() - (w, x), (y, z) = iterator.get_next() - self.assertEquals(dtypes.int64, w.dtype) - self.assertEquals(dtypes.int64, x.dtype) - self.assertEquals(dtypes.float64, y.dtype) - self.assertEquals(dtypes.float64, z.dtype) - self.assertEquals([None, 3], w.shape.as_list()) - self.assertEquals([None, 3], x.shape.as_list()) - self.assertEquals([None, 2], y.shape.as_list()) - self.assertEquals([None, 2], z.shape.as_list()) - - # Define a separate set of components with matching leading - # dimension for the from-slices constructor. - components_for_slices = (np.array([1, 2, 3], dtype=np.int64), - (np.array([4., 5., 6.]), - np.array([7., 8., 9.])), - np.array([10, 11, 12], dtype=np.int64)) - - dataset = dataset_ops.Dataset.from_tensor_slices(components_for_slices) - self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), - dtypes.int64), dataset.output_types) - self.assertEquals(([], ([], []), []), dataset.output_shapes) - - def testNestedDict(self): - components = {"a": {"aa": 1, "ab": [2.0, 2.0]}, "b": [3, 3, 3]} - dataset = dataset_ops.Dataset.from_tensors(components) - self.assertEquals(dtypes.int32, dataset.output_types["a"]["aa"]) - self.assertEquals(dtypes.float32, dataset.output_types["a"]["ab"]) - self.assertEquals(dtypes.int32, dataset.output_types["b"]) - self.assertEquals([], dataset.output_shapes["a"]["aa"]) - self.assertEquals([2], dataset.output_shapes["a"]["ab"]) - self.assertEquals([3], dataset.output_shapes["b"]) - - def testNonSequenceNestedStructure(self): - components = np.array([1, 2, 3], dtype=np.int64) - - dataset = dataset_ops.Dataset.from_tensors(components) - self.assertEquals(dtypes.int64, dataset.output_types) - self.assertEquals([3], dataset.output_shapes) - - dataset = dataset.filter( - lambda x: math_ops.reduce_all(math_ops.equal(x, components))) - self.assertEquals(dtypes.int64, dataset.output_types) - self.assertEquals([3], dataset.output_shapes) - - dataset = dataset.map(lambda x: array_ops.stack([x, x])) - self.assertEquals(dtypes.int64, dataset.output_types) - self.assertEquals([2, 3], dataset.output_shapes) - - dataset = dataset.flat_map( - lambda x: dataset_ops.Dataset.from_tensor_slices(x)) - self.assertEquals(dtypes.int64, dataset.output_types) - self.assertEquals([3], dataset.output_shapes) - - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - self.assertEquals(dtypes.int64, get_next.dtype) - self.assertEquals([3], get_next.shape) - - def testSplitPipelineFailsWithPlacementError(self): - with session.Session( - target="", - config=config_pb2.ConfigProto(device_count={"CPU": 2})) as sess: - - dataset = dataset_ops.Dataset.from_tensors(0) - - # Define a pipeline that attempts to use variables on two - # different devices. - # - # Initialize the variables before creating to iterator, to avoid the - # placement algorithm overriding the DT_RESOURCE colocation constraints. - with ops.device("/cpu:0"): - var_0 = resource_variable_ops.ResourceVariable(initial_value=0) - dataset = dataset.map(lambda x: x + var_0.read_value()) - sess.run(var_0.initializer) - - with ops.device("/cpu:1"): - var_1 = resource_variable_ops.ResourceVariable(initial_value=0) - dataset = dataset.map(lambda x: x + var_1.read_value()) - sess.run(var_1.initializer) - - iterator = dataset.make_initializable_iterator() - sess.run(iterator.initializer) - - with self.assertRaisesRegexp( - errors.FailedPreconditionError, - "Error while reading resource variable Variable"): - sess.run(iterator.get_next()) - - -class DatasetConstructorBenchmark(test.Benchmark): - - def benchmarkSliceRepeatBatch(self): - input_size = 10000 - batch_size = 100 - num_epochs = 100 - - input_data = np.random.randn(input_size) - - dataset = ( - dataset_ops.Dataset.from_tensor_slices(input_data) - .repeat(num_epochs + 1).batch(batch_size)) - iterator = dataset.make_initializable_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - sess.run(iterator.initializer) - # Run one whole epoch to burn in the computation. - for _ in range(input_size // batch_size): - sess.run(next_element) - deltas = [] - try: - while True: - start = time.time() - sess.run(next_element) - deltas.append(time.time() - start) - except errors.OutOfRangeError: - pass - - median_wall_time = np.median(deltas) - print("Slice/repeat/batch with sess.run() input size: %d batch size: %d " - "Median wall time per element: %f" % (input_size, batch_size, - median_wall_time)) - self.report_benchmark( - iters=len(deltas), - wall_time=median_wall_time, - name="benchmark_slice_repeat_batch_input_%d_batch_%d" % (input_size, - batch_size)) - - def benchmarkSliceRepeatBatchCallable(self): - input_size = 10000 - batch_size = 100 - num_epochs = 100 - - input_data = np.random.randn(input_size) - - dataset = ( - dataset_ops.Dataset.from_tensor_slices(input_data) - .repeat(num_epochs + 1).batch(batch_size)) - iterator = dataset.make_initializable_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - sess.run(iterator.initializer) - get_next_element = sess.make_callable(next_element) - # Run one whole epoch to burn in the computation. - for _ in range(input_size // batch_size): - get_next_element() - deltas = [] - try: - while True: - start = time.time() - get_next_element() - deltas.append(time.time() - start) - except errors.OutOfRangeError: - pass - - median_wall_time = np.median(deltas) - print( - "Slice/repeat/batch with callable input size: %d batch size: %d Median" - " wall time per element: %f" % (input_size, batch_size, - median_wall_time)) - self.report_benchmark( - iters=len(deltas), - wall_time=median_wall_time, - name="benchmark_slice_repeat_batch_callable_input_%d_batch_%d" % - (input_size, batch_size)) - - def benchmarkReshapeSliceRepeatCallable(self): - input_size = 10000 - batch_size = 100 - num_epochs = 100 - - input_data = np.random.randn(input_size) - - dataset = ( - dataset_ops.Dataset.from_tensor_slices(input_data.reshape(100, 100)) - .repeat(num_epochs + 1)) - iterator = dataset.make_initializable_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - sess.run(iterator.initializer) - get_next_element = sess.make_callable(next_element) - # Run one whole epoch to burn in the computation. - for _ in range(input_size // batch_size): - get_next_element() - deltas = [] - try: - while True: - start = time.time() - get_next_element() - deltas.append(time.time() - start) - except errors.OutOfRangeError: - pass - - median_wall_time = np.median(deltas) - print("Reshape/slice/repeat with callable input size: %d batch size: %d " - "Median wall time per element: %f" % (input_size, batch_size, - median_wall_time)) - self.report_benchmark( - iters=len(deltas), - wall_time=median_wall_time, - name="benchmark_reshape_slice_repeat_callable_input_%d_batch_%d" % - (input_size, batch_size)) - - def benchmarkSliceBatchCacheRepeatCallable(self): - input_size = 10000 - batch_size = 100 - num_epochs = 100 - - input_data = np.random.randn(input_size) - - dataset = ( - dataset_ops.Dataset.from_tensor_slices(input_data).batch(batch_size) - .cache().repeat(num_epochs + 1)) - iterator = dataset.make_initializable_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - sess.run(iterator.initializer) - get_next_element = sess.make_callable(next_element) - # Run one whole epoch to burn in the computation. - for _ in range(input_size // batch_size): - get_next_element() - deltas = [] - try: - while True: - start = time.time() - get_next_element() - deltas.append(time.time() - start) - except errors.OutOfRangeError: - pass - - median_wall_time = np.median(deltas) - print( - "Slice/batch/cache/repeat with callable input size: %d batch size: %d " - "Median wall time per element: %f" - % (input_size, batch_size, median_wall_time)) - self.report_benchmark( - iters=len(deltas), - wall_time=median_wall_time, - name="benchmark_slice_batch_cache_repeat_callable_input_%d_batch_%d" % - (input_size, batch_size)) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/kernel_tests/dataset_ops_test.py b/tensorflow/python/data/kernel_tests/dataset_test.py similarity index 69% rename from tensorflow/python/data/kernel_tests/dataset_ops_test.py rename to tensorflow/python/data/kernel_tests/dataset_test.py index a5324af4d0..2952c08be0 100644 --- a/tensorflow/python/data/kernel_tests/dataset_ops_test.py +++ b/tensorflow/python/data/kernel_tests/dataset_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the input pipeline ops.""" +"""Tests for `tf.data.Dataset`.""" from __future__ import absolute_import from __future__ import division @@ -24,21 +24,26 @@ import numpy as np from tensorflow.core.framework import graph_pb2 from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.ops import optional_ops from tensorflow.python.data.ops import readers from tensorflow.python.data.util import nest +from tensorflow.python.data.util import structure +from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.platform import test -class DatasetOpsTest(test_base.DatasetTestBase, parameterized.TestCase): +@test_util.run_all_in_graph_and_eager_modes +class DatasetTest(test_base.DatasetTestBase, parameterized.TestCase): def testAsSerializedGraph(self): dataset = dataset_ops.Dataset.range(10) - with self.cached_session() as sess: - graph = graph_pb2.GraphDef().FromString( - sess.run(dataset._as_serialized_graph())) - self.assertTrue(any([node.op != "RangeDataset" for node in graph.node])) + graph = graph_pb2.GraphDef().FromString( + self.evaluate(dataset._as_serialized_graph())) + self.assertTrue(any([node.op != "RangeDataset" for node in graph.node])) @staticmethod def make_apply_fn(dataset): @@ -76,7 +81,7 @@ class DatasetOpsTest(test_base.DatasetTestBase, parameterized.TestCase): lambda: readers.FixedLengthRecordDataset("", 42)), ("FromGenerator", lambda: dataset_ops.Dataset.from_generator( - DatasetOpsTest.make_gen(), dtypes.int32), + DatasetTest.make_gen(), dtypes.int32), 1), ("FromTensors", lambda: dataset_ops.Dataset.from_tensors([42])), ("FromTensorSlices", lambda: dataset_ops.Dataset.from_tensors([42])), @@ -222,12 +227,12 @@ class DatasetOpsTest(test_base.DatasetTestBase, parameterized.TestCase): options1 = dataset_ops.Options() options1.experimental_autotune = True options2 = dataset_ops.Options() - options2.experimental_filter_fusion = False + options2.experimental_deterministic = False ds = dataset_ops.Dataset.range(0).with_options(options1).with_options( options2) self.assertTrue(ds.options().experimental_autotune) # Explicitly check that flag is False since assertFalse allows None - self.assertIs(ds.options().experimental_filter_fusion, False) + self.assertIs(ds.options().experimental_deterministic, False) def testOptionsTwiceDifferentError(self): options1 = dataset_ops.Options() @@ -235,20 +240,78 @@ class DatasetOpsTest(test_base.DatasetTestBase, parameterized.TestCase): options2 = dataset_ops.Options() options2.experimental_autotune = False with self.assertRaisesRegexp(ValueError, - "Cannot merge incompatible values of option"): + "Cannot merge incompatible values"): dataset_ops.Dataset.range(0).with_options(options1).with_options(options2) def testOptionsMergeOptionsFromMultipleInputs(self): options1 = dataset_ops.Options() options1.experimental_autotune = True options2 = dataset_ops.Options() - options2.experimental_filter_fusion = True + options2.experimental_deterministic = True ds = dataset_ops.Dataset.zip( (dataset_ops.Dataset.range(0).with_options(options1), dataset_ops.Dataset.range(0).with_options(options2))) self.assertTrue(ds.options().experimental_autotune) - self.assertTrue(ds.options().experimental_filter_fusion) + self.assertTrue(ds.options().experimental_deterministic) + # TODO(b/119882922): use-after-free bug in eager mode. + # pylint: disable=g-long-lambda + @parameterized.named_parameters( + ("Tensor", lambda: constant_op.constant(37.0), + structure.TensorStructure(dtypes.float32, [])), + ("SparseTensor", lambda: sparse_tensor.SparseTensor( + indices=[[0]], values=constant_op.constant([0], dtype=dtypes.int32), + dense_shape=[1]), + structure.SparseTensorStructure(dtypes.int32, [1])), + ("Nest", lambda: { + "a": constant_op.constant(37.0), + "b": (constant_op.constant(["Foo"]), constant_op.constant("Bar"))}, + structure.NestedStructure({ + "a": structure.TensorStructure(dtypes.float32, []), + "b": (structure.TensorStructure(dtypes.string, [1]), + structure.TensorStructure(dtypes.string, []))})), + ("Dataset", lambda: dataset_ops.Dataset.from_tensor_slices( + constant_op.constant([1, 2, 3])), + dataset_ops.DatasetStructure( + structure.TensorStructure(dtypes.int32, []))), + ("Optional", lambda: optional_ops.Optional.from_value(37.0), + optional_ops.OptionalStructure( + structure.TensorStructure(dtypes.float32, []))), + ) + def testSkipEagerDatasetStructure(self, tf_value_fn, + expected_element_structure): + dataset = dataset_ops.Dataset.from_tensors(0).map(lambda _: tf_value_fn()) + dataset_structure = structure.Structure.from_value(dataset) + self.assertIsInstance(dataset_structure, dataset_ops.DatasetStructure) + + # TODO(b/110122868): Add a public API to `tf.data.Dataset` for accessing + # the element structure. + self.assertTrue(expected_element_structure.is_compatible_with( + dataset_structure._element_structure)) + self.assertTrue(dataset_structure._element_structure.is_compatible_with( + expected_element_structure)) + + self.assertEqual([dtypes.variant], dataset_structure._flat_types) + self.assertEqual([tensor_shape.scalar()], dataset_structure._flat_shapes) + + # Assert that the `Dataset` survives a round-trip via _from_tensor_list() + # and _to_tensor_list(). + round_trip_dataset = dataset_structure._from_tensor_list( + dataset_structure._to_tensor_list(dataset)) + + value = tf_value_fn() + + if isinstance(value, dataset_ops.Dataset): + self.assertDatasetsEqual(value, dataset.flat_map(lambda x: x)) + elif isinstance(value, optional_ops.Optional): + self.assertDatasetProduces( + round_trip_dataset.map(lambda opt: opt.get_value()), + [self.evaluate(value.get_value())], + requires_initialization=True) + else: + self.assertDatasetProduces( + round_trip_dataset, [self.evaluate(tf_value_fn())], + requires_initialization=True) if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/kernel_tests/filter_dataset_op_test.py b/tensorflow/python/data/kernel_tests/filter_dataset_op_test.py deleted file mode 100644 index a0c6b37a6d..0000000000 --- a/tensorflow/python/data/kernel_tests/filter_dataset_op_test.py +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import time - -import numpy as np - -from tensorflow.python.client import session -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import ops -from tensorflow.python.framework import sparse_tensor -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import functional_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.platform import test - - -class FilterDatasetTest(test_base.DatasetTestBase): - - def testFilterDataset(self): - components = ( - np.arange(7, dtype=np.int64), - np.array([[1, 2, 3]], dtype=np.int64) * np.arange( - 7, dtype=np.int64)[:, np.newaxis], - np.array(37.0, dtype=np.float64) * np.arange(7) - ) - count = array_ops.placeholder(dtypes.int64, shape=[]) - modulus = array_ops.placeholder(dtypes.int64) - - def _map_fn(x, y, z): - return math_ops.square(x), math_ops.square(y), math_ops.square(z) - - iterator = ( - dataset_ops.Dataset.from_tensor_slices(components).map(_map_fn) - .repeat(count) - .filter(lambda x, _y, _z: math_ops.equal(math_ops.mod(x, modulus), 0)) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([c.shape[1:] for c in components], - [t.shape for t in get_next]) - - with self.cached_session() as sess: - # Test that we can dynamically feed a different modulus value for each - # iterator. - def do_test(count_val, modulus_val): - sess.run(init_op, feed_dict={count: count_val, modulus: modulus_val}) - for _ in range(count_val): - for i in [x for x in range(7) if x**2 % modulus_val == 0]: - result = sess.run(get_next) - for component, result_component in zip(components, result): - self.assertAllEqual(component[i]**2, result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - do_test(14, 2) - do_test(4, 18) - - # Test an empty dataset. - do_test(0, 1) - - def testFilterRange(self): - dataset = dataset_ops.Dataset.range(100).filter( - lambda x: math_ops.not_equal(math_ops.mod(x, 3), 2)) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next() - - with self.cached_session() as sess: - self.assertEqual(0, sess.run(get_next)) - self.assertEqual(1, sess.run(get_next)) - self.assertEqual(3, sess.run(get_next)) - - def testFilterDict(self): - iterator = (dataset_ops.Dataset.range(10) - .map(lambda x: {"foo": x * 2, "bar": x ** 2}) - .filter(lambda d: math_ops.equal(d["bar"] % 2, 0)) - .map(lambda d: d["foo"] + d["bar"]) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(10): - if (i ** 2) % 2 == 0: - self.assertEqual(i * 2 + i ** 2, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testUseStepContainerInFilter(self): - input_data = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int64) - - # Define a predicate that returns true for the first element of - # the sequence and not the second, and uses `tf.map_fn()`. - def _predicate(xs): - squared_xs = functional_ops.map_fn(lambda x: x * x, xs) - summed = math_ops.reduce_sum(squared_xs) - return math_ops.equal(summed, 1 + 4 + 9) - - iterator = ( - dataset_ops.Dataset.from_tensor_slices([[1, 2, 3], [4, 5, 6]]) - .filter(_predicate) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - self.assertAllEqual(input_data[0], sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testSparse(self): - - def _map_fn(i): - return sparse_tensor.SparseTensorValue( - indices=np.array([[0, 0]]), - values=(i * np.array([1])), - dense_shape=np.array([1, 1])), i - - def _filter_fn(_, i): - return math_ops.equal(i % 2, 0) - - iterator = ( - dataset_ops.Dataset.range(10).map(_map_fn).filter(_filter_fn).map( - lambda x, i: x).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(5): - actual = sess.run(get_next) - self.assertTrue(isinstance(actual, sparse_tensor.SparseTensorValue)) - self.assertSparseValuesEqual(actual, _map_fn(i * 2)[0]) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testShortCircuit(self): - iterator = ( - dataset_ops.Dataset.zip( - (dataset_ops.Dataset.range(10), - dataset_ops.Dataset.from_tensors(True).repeat(None))) - .filter(lambda x, y: y).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(10): - self.assertEqual((i, True), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testParallelFilters(self): - dataset = dataset_ops.Dataset.range(10).filter( - lambda x: math_ops.equal(x % 2, 0)) - iterators = [dataset.make_one_shot_iterator() for _ in range(10)] - next_elements = [iterator.get_next() for iterator in iterators] - with self.cached_session() as sess: - self.assertEqual([0 for _ in range(10)], sess.run(next_elements)) - - -class FilterDatasetBenchmark(test.Benchmark): - - def _benchmark(self, predicate, name): - with ops.Graph().as_default(): - dataset = ( - dataset_ops.Dataset.from_tensors(True).repeat(None).filter(predicate)) - iterator = dataset.make_one_shot_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - for _ in range(5): - sess.run(next_element.op) - deltas = [] - for _ in range(100): - start = time.time() - for _ in range(100): - sess.run(next_element.op) - end = time.time() - deltas.append(end - start) - - median_wall_time = np.median(deltas) / 100 - print("Filter dataset using %s. Median wall time: %f" % - (name, median_wall_time)) - self.report_benchmark( - iters=100, - wall_time=median_wall_time, - name="benchmark_filter_dataset_%s" % name) - - def benchmarkSimpleFunction(self): - self._benchmark(array_ops.identity, "simple_function") - - def benchmarkReturnComponentOptimization(self): - self._benchmark(lambda x: x, "return_component") - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/kernel_tests/filter_test.py b/tensorflow/python/data/kernel_tests/filter_test.py new file mode 100644 index 0000000000..afaf954cbc --- /dev/null +++ b/tensorflow/python/data/kernel_tests/filter_test.py @@ -0,0 +1,128 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.filter()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import errors +from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util +from tensorflow.python.ops import functional_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class FilterTest(test_base.DatasetTestBase): + + def testFilterDataset(self): + components = ( + np.arange(7, dtype=np.int64), + np.array([[1, 2, 3]], dtype=np.int64) * np.arange( + 7, dtype=np.int64)[:, np.newaxis], + np.array(37.0, dtype=np.float64) * np.arange(7) + ) + def _map_fn(x, y, z): + return math_ops.square(x), math_ops.square(y), math_ops.square(z) + + def do_test(count, modulus): + dataset = dataset_ops.Dataset.from_tensor_slices(components).map( + _map_fn).repeat(count).filter( + lambda x, _y, _z: math_ops.equal(math_ops.mod(x, modulus), 0)) + self.assertEqual([c.shape[1:] for c in components], + [shape for shape in dataset.output_shapes]) + get_next = self.getNext(dataset) + for _ in range(count): + for i in [x for x in range(7) if x**2 % modulus == 0]: + result = self.evaluate(get_next()) + for component, result_component in zip(components, result): + self.assertAllEqual(component[i]**2, result_component) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + do_test(14, 2) + do_test(4, 18) + + # Test an empty dataset. + do_test(0, 1) + + def testFilterRange(self): + dataset = dataset_ops.Dataset.range(4).filter( + lambda x: math_ops.not_equal(math_ops.mod(x, 3), 2)) + self.assertDatasetProduces(dataset, expected_output=[0, 1, 3]) + + def testFilterDict(self): + dataset = dataset_ops.Dataset.range(10).map( + lambda x: {"foo": x * 2, "bar": x ** 2}).filter( + lambda d: math_ops.equal(d["bar"] % 2, 0)).map( + lambda d: d["foo"] + d["bar"]) + self.assertDatasetProduces( + dataset, + expected_output=[(i * 2 + i**2) for i in range(10) if not (i**2) % 2]) + + def testUseStepContainerInFilter(self): + input_data = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int64) + + # Define a predicate that returns true for the first element of + # the sequence and not the second, and uses `tf.map_fn()`. + def _predicate(xs): + squared_xs = functional_ops.map_fn(lambda x: x * x, xs) + summed = math_ops.reduce_sum(squared_xs) + return math_ops.equal(summed, 1 + 4 + 9) + + dataset = dataset_ops.Dataset.from_tensor_slices( + [[1, 2, 3], [4, 5, 6]]).filter(_predicate) + self.assertDatasetProduces(dataset, expected_output=[input_data[0]]) + + def testSparse(self): + + def _map_fn(i): + return sparse_tensor.SparseTensorValue( + indices=np.array([[0, 0]]), + values=(i * np.array([1])), + dense_shape=np.array([1, 1])), i + + def _filter_fn(_, i): + return math_ops.equal(i % 2, 0) + + dataset = dataset_ops.Dataset.range(10).map(_map_fn).filter(_filter_fn).map( + lambda x, i: x) + self.assertDatasetProduces( + dataset, expected_output=[_map_fn(i * 2)[0] for i in range(5)]) + + def testShortCircuit(self): + dataset = dataset_ops.Dataset.zip( + (dataset_ops.Dataset.range(10), + dataset_ops.Dataset.from_tensors(True).repeat(None) + )).filter(lambda x, y: y) + self.assertDatasetProduces( + dataset, expected_output=[(i, True) for i in range(10)]) + + def testParallelFilters(self): + dataset = dataset_ops.Dataset.range(10).filter( + lambda x: math_ops.equal(x % 2, 0)) + next_elements = [self.getNext(dataset) for _ in range(10)] + self.assertEqual([0 for _ in range(10)], + self.evaluate( + [next_element() for next_element in next_elements])) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/fixed_length_record_dataset_test.py b/tensorflow/python/data/kernel_tests/fixed_length_record_dataset_test.py new file mode 100644 index 0000000000..9503e57ca7 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/fixed_length_record_dataset_test.py @@ -0,0 +1,171 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.FixedLengthRecordDataset`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import gzip +import os +import zlib + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import readers +from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test +from tensorflow.python.util import compat + + +@test_util.run_all_in_graph_and_eager_modes +class FixedLengthRecordDatasetTest(test_base.DatasetTestBase): + + def setUp(self): + super(FixedLengthRecordDatasetTest, self).setUp() + self._num_files = 2 + self._num_records = 7 + self._header_bytes = 5 + self._record_bytes = 3 + self._footer_bytes = 2 + + def _record(self, f, r): + return compat.as_bytes(str(f * 2 + r) * self._record_bytes) + + def _createFiles(self, compression_type=None): + filenames = [] + for i in range(self._num_files): + fn = os.path.join(self.get_temp_dir(), "fixed_length_record.%d.txt" % i) + filenames.append(fn) + + contents = [] + contents.append(b"H" * self._header_bytes) + for j in range(self._num_records): + contents.append(self._record(i, j)) + contents.append(b"F" * self._footer_bytes) + contents = b"".join(contents) + + if not compression_type: + with open(fn, "wb") as f: + f.write(contents) + elif compression_type == "GZIP": + with gzip.GzipFile(fn, "wb") as f: + f.write(contents) + elif compression_type == "ZLIB": + contents = zlib.compress(contents) + with open(fn, "wb") as f: + f.write(contents) + else: + raise ValueError("Unsupported compression_type", compression_type) + + return filenames + + def _testFixedLengthRecordDataset(self, compression_type=None): + test_filenames = self._createFiles(compression_type=compression_type) + + def dataset_fn(filenames, num_epochs, batch_size=None): + repeat_dataset = readers.FixedLengthRecordDataset( + filenames, + self._record_bytes, + self._header_bytes, + self._footer_bytes, + compression_type=compression_type).repeat(num_epochs) + if batch_size: + return repeat_dataset.batch(batch_size) + return repeat_dataset + + # Basic test: read from file 0. + self.assertDatasetProduces( + dataset_fn([test_filenames[0]], 1), + expected_output=[ + self._record(0, i) for i in range(self._num_records) + ]) + + # Basic test: read from file 1. + self.assertDatasetProduces( + dataset_fn([test_filenames[1]], 1), + expected_output=[ + self._record(1, i) for i in range(self._num_records) + ]) + + # Basic test: read from both files. + expected_output = [] + for j in range(self._num_files): + expected_output.extend( + [self._record(j, i) for i in range(self._num_records)]) + self.assertDatasetProduces( + dataset_fn(test_filenames, 1), expected_output=expected_output) + + # Test repeated iteration through both files. + get_next = self.getNext(dataset_fn(test_filenames, 10)) + for _ in range(10): + for j in range(self._num_files): + for i in range(self._num_records): + self.assertEqual(self._record(j, i), self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + # Test batched and repeated iteration through both files. + get_next = self.getNext(dataset_fn(test_filenames, 10, self._num_records)) + for _ in range(10): + for j in range(self._num_files): + self.assertAllEqual( + [self._record(j, i) for i in range(self._num_records)], + self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + def testFixedLengthRecordDatasetNoCompression(self): + self._testFixedLengthRecordDataset() + + def testFixedLengthRecordDatasetGzipCompression(self): + self._testFixedLengthRecordDataset(compression_type="GZIP") + + def testFixedLengthRecordDatasetZlibCompression(self): + self._testFixedLengthRecordDataset(compression_type="ZLIB") + + def testFixedLengthRecordDatasetBuffering(self): + test_filenames = self._createFiles() + dataset = readers.FixedLengthRecordDataset( + test_filenames, + self._record_bytes, + self._header_bytes, + self._footer_bytes, + buffer_size=10) + expected_output = [] + for j in range(self._num_files): + expected_output.extend( + [self._record(j, i) for i in range(self._num_records)]) + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testFixedLengthRecordDatasetWrongSize(self): + test_filenames = self._createFiles() + dataset = readers.FixedLengthRecordDataset( + test_filenames, + self._record_bytes + 1, # Incorrect record length. + self._header_bytes, + self._footer_bytes, + buffer_size=10) + self.assertDatasetProduces( + dataset, + expected_error=( + errors.InvalidArgumentError, + r"Excluding the header \(5 bytes\) and footer \(2 bytes\), input " + r"file \".*fixed_length_record.0.txt\" has body length 21 bytes, " + r"which is not an exact multiple of the record length \(4 bytes\).") + ) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/flat_map_dataset_op_test.py b/tensorflow/python/data/kernel_tests/flat_map_test.py similarity index 57% rename from tensorflow/python/data/kernel_tests/flat_map_dataset_op_test.py rename to tensorflow/python/data/kernel_tests/flat_map_test.py index 68038f9cfc..ff52821b10 100644 --- a/tensorflow/python/data/kernel_tests/flat_map_dataset_op_test.py +++ b/tensorflow/python/data/kernel_tests/flat_map_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the experimental input pipeline ops.""" +"""Tests for `tf.data.Dataset.flat_map()`.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -26,54 +26,42 @@ from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import sparse_ops from tensorflow.python.platform import test from tensorflow.python.training import server_lib -class FlatMapDatasetTest(test_base.DatasetTestBase): +@test_util.run_all_in_graph_and_eager_modes +class FlatMapTest(test_base.DatasetTestBase): # pylint: disable=g-long-lambda def testFlatMapDataset(self): repeats = [1, 2, 3, 4, 5, 0, 1] components = np.array(repeats, dtype=np.int64) - iterator = ( - dataset_ops.Dataset.from_tensor_slices(components) - .flat_map(lambda x: dataset_ops.Dataset.from_tensors([x]).repeat(x)) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in repeats: - for _ in range(i): - self.assertEqual(i, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + dataset = dataset_ops.Dataset.from_tensor_slices(components).flat_map( + lambda x: dataset_ops.Dataset.from_tensors([x]).repeat(x)) + expected_output = [] + for i in repeats: + expected_output.extend([[i]] * i) + self.assertDatasetProduces(dataset, expected_output=expected_output) def testNestedFlatMapDataset(self): repeats = [[1, 2], [3, 4], [5, 0], [1, 7]] components = np.array(repeats, dtype=np.int64) - iterator = ( - dataset_ops.Dataset.from_tensor_slices(components) - .flat_map(lambda x: dataset_ops.Dataset.from_tensor_slices(x) - .flat_map(lambda y: dataset_ops.Dataset.from_tensors(y) - .repeat(y))).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for row in repeats: - for i in row: - for _ in range(i): - self.assertEqual(i, sess.run(get_next)) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testSharedResourceNestedFlatMapDataset(self): + dataset = dataset_ops.Dataset.from_tensor_slices(components).flat_map( + lambda x: dataset_ops.Dataset.from_tensor_slices(x).flat_map( + lambda y: dataset_ops.Dataset.from_tensors(y).repeat(y)) + ) + expected_output = [] + for row in repeats: + for i in row: + expected_output.extend([i] * i) + self.assertDatasetProduces(dataset, expected_output=expected_output) + + # Note: no eager mode coverage, session specific test. + @test_util.run_deprecated_v1 + def testSkipEagerSharedResourceNestedFlatMapDataset(self): repeats = [[1, 2], [3, 4], [5, 0], [1, 7]] components = np.array(repeats, dtype=np.int64) iterator = ( @@ -106,22 +94,16 @@ class FlatMapDatasetTest(test_base.DatasetTestBase): sess.run(get_next) def testMapDict(self): - iterator = (dataset_ops.Dataset.range(10) - .map(lambda x: {"foo": x * 2, "bar": x ** 2}) - .flat_map(lambda d: dataset_ops.Dataset.from_tensors(d["foo"]) - .repeat(d["bar"])) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(10): - for _ in range(i ** 2): - self.assertEqual(i * 2, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - # pylint: enable=g-long-lambda + dataset = dataset_ops.Dataset.range(10).map( + lambda x: {"foo": x * 2, "bar": x ** 2}).flat_map( + lambda d: dataset_ops.Dataset.from_tensors( + d["foo"]).repeat(d["bar"])) + get_next = self.getNext(dataset) + for i in range(10): + for _ in range(i**2): + self.assertEqual(i * 2, self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) def testSparse(self): def _map_fn(i): @@ -132,20 +114,12 @@ class FlatMapDatasetTest(test_base.DatasetTestBase): return dataset_ops.Dataset.from_tensor_slices( sparse_ops.sparse_to_dense(x.indices, x.dense_shape, x.values)) - iterator = ( - dataset_ops.Dataset.range(10).map(_map_fn).flat_map(_flat_map_fn) - .make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - for i in range(10): - for j in range(2): - expected = [i, 0] if j % 2 == 0 else [0, -i] - self.assertAllEqual(expected, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + dataset = dataset_ops.Dataset.range(10).map(_map_fn).flat_map(_flat_map_fn) + expected_output = [] + for i in range(10): + for j in range(2): + expected_output.append([i, 0] if j % 2 == 0 else [0, -i]) + self.assertDatasetProduces(dataset, expected_output=expected_output) if __name__ == "__main__": diff --git a/tensorflow/python/data/kernel_tests/dataset_from_generator_op_test.py b/tensorflow/python/data/kernel_tests/from_generator_test.py similarity index 85% rename from tensorflow/python/data/kernel_tests/dataset_from_generator_op_test.py rename to tensorflow/python/data/kernel_tests/from_generator_test.py index cb8cb9a77d..a6625534e7 100644 --- a/tensorflow/python/data/kernel_tests/dataset_from_generator_op_test.py +++ b/tensorflow/python/data/kernel_tests/from_generator_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the experimental input pipeline ops.""" +"""Tests for tf.data.Dataset.from_generator().""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -27,21 +27,21 @@ from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.ops import script_ops from tensorflow.python.platform import test -class DatasetConstructorTest(test_base.DatasetTestBase): +class FromGeneratorTest(test_base.DatasetTestBase): def _testFromGenerator(self, generator, elem_sequence, num_repeats, output_types=None): if output_types is None: output_types = dtypes.int64 - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_generator(generator, output_types=output_types) .repeat(num_repeats) - .prefetch(5) - .make_initializable_iterator()) + .prefetch(5)) init_op = iterator.initializer get_next = iterator.get_next() @@ -55,11 +55,10 @@ class DatasetConstructorTest(test_base.DatasetTestBase): sess.run(get_next) def _testFromGeneratorOneShot(self, generator, elem_sequence, num_repeats): - iterator = ( + iterator = dataset_ops.make_one_shot_iterator( dataset_ops.Dataset.from_generator(generator, output_types=dtypes.int64) .repeat(num_repeats) - .prefetch(5) - .make_one_shot_iterator()) + .prefetch(5)) get_next = iterator.get_next() with self.cached_session() as sess: @@ -69,6 +68,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testFromGeneratorUsingFunction(self): def generator(): for i in range(1, 100): @@ -79,18 +79,21 @@ class DatasetConstructorTest(test_base.DatasetTestBase): self._testFromGeneratorOneShot(generator, elem_sequence, 1) self._testFromGeneratorOneShot(generator, elem_sequence, 5) + @test_util.run_deprecated_v1 def testFromGeneratorUsingList(self): generator = lambda: [[i] * i for i in range(1, 100)] elem_sequence = list(generator()) self._testFromGenerator(generator, elem_sequence, 1) self._testFromGenerator(generator, elem_sequence, 5) + @test_util.run_deprecated_v1 def testFromGeneratorUsingNdarray(self): generator = lambda: np.arange(100, dtype=np.int64) elem_sequence = list(generator()) self._testFromGenerator(generator, elem_sequence, 1, output_types=np.int64) self._testFromGenerator(generator, elem_sequence, 5, output_types=np.int64) + @test_util.run_deprecated_v1 def testFromGeneratorUsingGeneratorExpression(self): # NOTE(mrry): Generator *expressions* are not repeatable (or in # general reusable), because they eagerly evaluate the `for` @@ -102,6 +105,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): self._testFromGenerator(generator, elem_sequence, 1) self._testFromGenerator(generator, elem_sequence, 5) + @test_util.run_deprecated_v1 def testFromMultipleConcurrentGenerators(self): num_inner_repeats = 5 num_outer_repeats = 100 @@ -124,11 +128,10 @@ class DatasetConstructorTest(test_base.DatasetTestBase): output_shapes=([None], [3])) .repeat(num_inner_repeats).prefetch(5)) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.range(num_outer_repeats) .interleave(interleave_fn, cycle_length=10, - block_length=len(input_list)) - .make_initializable_iterator()) + block_length=len(input_list))) init_op = iterator.initializer get_next = iterator.get_next() @@ -183,11 +186,10 @@ class DatasetConstructorTest(test_base.DatasetTestBase): return dataset_ops.Dataset.from_generator( generator, output_types=dtypes.int64, output_shapes=[]).prefetch(2) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.range(num_parallel_iterators) .interleave( - interleave_fn, cycle_length=num_parallel_iterators, block_length=1) - .make_initializable_iterator()) + interleave_fn, cycle_length=num_parallel_iterators, block_length=1)) init_op = iterator.initializer get_next = iterator.get_next() @@ -199,6 +201,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testFromGeneratorImplicitConversion(self): def generator(): yield [1] @@ -206,9 +209,9 @@ class DatasetConstructorTest(test_base.DatasetTestBase): yield [3] for dtype in [dtypes.int8, dtypes.int32, dtypes.int64]: - iterator = (dataset_ops.Dataset.from_generator( - generator, output_types=dtype, output_shapes=[1]) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_generator( + generator, output_types=dtype, output_shapes=[1])) init_op = iterator.initializer get_next = iterator.get_next() @@ -223,15 +226,16 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testFromGeneratorString(self): def generator(): yield "foo" yield b"bar" yield u"baz" - iterator = (dataset_ops.Dataset.from_generator( - generator, output_types=dtypes.string, output_shapes=[]) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_generator( + generator, output_types=dtypes.string, output_shapes=[])) init_op = iterator.initializer get_next = iterator.get_next() @@ -243,6 +247,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testFromGeneratorTypeError(self): def generator(): yield np.array([1, 2, 3], dtype=np.int64) @@ -250,9 +255,9 @@ class DatasetConstructorTest(test_base.DatasetTestBase): yield "ERROR" yield np.array([7, 8, 9], dtype=np.int64) - iterator = (dataset_ops.Dataset.from_generator( - generator, output_types=dtypes.int64, output_shapes=[3]) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_generator( + generator, output_types=dtypes.int64, output_shapes=[3])) init_op = iterator.initializer get_next = iterator.get_next() @@ -266,6 +271,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testFromGeneratorShapeError(self): def generator(): yield np.array([1, 2, 3], dtype=np.int64) @@ -273,9 +279,9 @@ class DatasetConstructorTest(test_base.DatasetTestBase): yield np.array([7, 8, 9, 10], dtype=np.int64) yield np.array([11, 12, 13], dtype=np.int64) - iterator = (dataset_ops.Dataset.from_generator( - generator, output_types=dtypes.int64, output_shapes=[3]) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_generator( + generator, output_types=dtypes.int64, output_shapes=[3])) init_op = iterator.initializer get_next = iterator.get_next() @@ -289,6 +295,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testFromGeneratorStructureError(self): def generator(): yield 1, 2 @@ -297,9 +304,9 @@ class DatasetConstructorTest(test_base.DatasetTestBase): yield 6, 7, 8 yield 9, 10 - iterator = (dataset_ops.Dataset.from_generator( - generator, output_types=(dtypes.int64, dtypes.int64)) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_generator( + generator, output_types=(dtypes.int64, dtypes.int64))) init_op = iterator.initializer get_next = iterator.get_next() @@ -317,14 +324,15 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testFromGeneratorHeterogeneous(self): def generator(): yield 1 yield [2, 3] - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_generator( - generator, output_types=dtypes.int64).make_initializable_iterator()) + generator, output_types=dtypes.int64)) init_op = iterator.initializer get_next = iterator.get_next() @@ -335,6 +343,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testFromGeneratorStopShort(self): def generator(): @@ -342,9 +351,9 @@ class DatasetConstructorTest(test_base.DatasetTestBase): yield 1 yield 2 - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_generator( - generator, output_types=dtypes.int64).make_initializable_iterator()) + generator, output_types=dtypes.int64)) init_op = iterator.initializer get_next = iterator.get_next() @@ -353,6 +362,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): self.assertAllEqual(0, sess.run(get_next)) self.assertAllEqual(1, sess.run(get_next)) + @test_util.run_deprecated_v1 def testFromGeneratorDestructorCalled(self): # Use an `Event` to signal that the generator has been deleted. event = threading.Event() @@ -371,9 +381,9 @@ class DatasetConstructorTest(test_base.DatasetTestBase): def __del__(self): event.set() - iterator = dataset_ops.Dataset.from_generator( - GeneratorWrapper, - output_types=dtypes.int64).take(2).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_generator( + GeneratorWrapper, output_types=dtypes.int64).take(2)) init_op = iterator.initializer get_next = iterator.get_next() @@ -387,6 +397,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): # iterator terminates (and the generator iterator is deleted). self.assertTrue(event.is_set()) + @test_util.run_deprecated_v1 def testFromGeneratorWithArgs(self): def flat_map_fn(elem): @@ -399,10 +410,8 @@ class DatasetConstructorTest(test_base.DatasetTestBase): generator_with_arg, output_types=dtypes.int64, output_shapes=(), args=(elem,)) - iterator = (dataset_ops.Dataset - .range(5) - .flat_map(flat_map_fn) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(5).flat_map(flat_map_fn)) init_op = iterator.initializer get_next = iterator.get_next() @@ -414,6 +423,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testFromGeneratorWithTwoArgs(self): def flat_map_fn(elem, message): @@ -426,12 +436,11 @@ class DatasetConstructorTest(test_base.DatasetTestBase): generator_with_arg, output_types=(dtypes.int64, dtypes.string), output_shapes=((), ()), args=(elem, message)) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.zip( (dataset_ops.Dataset.range(5), dataset_ops.Dataset.from_tensors("Hi!").repeat(None))) - .flat_map(flat_map_fn) - .make_initializable_iterator()) + .flat_map(flat_map_fn)) init_op = iterator.initializer get_next = iterator.get_next() @@ -446,6 +455,7 @@ class DatasetConstructorTest(test_base.DatasetTestBase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testGeneratorDatasetFinalizeFunctionCalled(self): # NOTE(mrry): This test tests the internal `_GeneratorDataset`, # which affords more control over what the finalize function can do than @@ -462,10 +472,9 @@ class DatasetConstructorTest(test_base.DatasetTestBase): stateful=True) dummy = constant_op.constant(37) - iterator = (dataset_ops._GeneratorDataset(dummy, lambda x: x, - lambda x: x, finalize_fn) - .take(2) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops._GeneratorDataset( + dummy, lambda x: x, lambda x: x, finalize_fn).take(2)) init_op = iterator.initializer get_next = iterator.get_next() diff --git a/tensorflow/python/data/kernel_tests/from_sparse_tensor_slices_test.py b/tensorflow/python/data/kernel_tests/from_sparse_tensor_slices_test.py new file mode 100644 index 0000000000..ef608ebb67 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/from_sparse_tensor_slices_test.py @@ -0,0 +1,86 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.from_sparse_tensor_slices()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors +from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class FromSparseTensorSlicesTest(test_base.DatasetTestBase): + + @test_util.run_deprecated_v1 + def testSkipEagerFromSparseTensorSlices(self): + """Test a dataset based on slices of a `tf.SparseTensor`.""" + st = array_ops.sparse_placeholder(dtypes.float64) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_sparse_tensor_slices(st)) + init_op = iterator.initializer + get_next = sparse_tensor.SparseTensor(*iterator.get_next()) + + with self.cached_session() as sess: + slices = [[1., 2., 3.], [1.], [1.], [1., 2.], [], [1., 2.], [], [], []] + + # Test with sparse tensor in the appropriate order. + indices = np.array( + [[i, j] for i in range(len(slices)) for j in range(len(slices[i]))]) + values = np.array([val for s in slices for val in s]) + dense_shape = np.array([len(slices), max(len(s) for s in slices) + 1]) + sparse_feed = sparse_tensor.SparseTensorValue(indices, values, + dense_shape) + sess.run(init_op, feed_dict={st: sparse_feed}) + for i, s in enumerate(slices): + results = sess.run(get_next) + self.assertAllEqual(s, results.values) + expected_indices = np.array( + [[j] for j in range(len(slices[i]))]).reshape([-1, 1]) + self.assertAllEqual(expected_indices, results.indices) + self.assertAllEqual(dense_shape[1:], results.dense_shape) + with self.assertRaises(errors.OutOfRangeError): + sess.run(get_next) + + # Test with sparse tensor in the reverse order, which is not + # currently supported. + reverse_order_indices = indices[::-1, :] + reverse_order_values = values[::-1] + sparse_feed = sparse_tensor.SparseTensorValue( + reverse_order_indices, reverse_order_values, dense_shape) + with self.assertRaises(errors.UnimplementedError): + sess.run(init_op, feed_dict={st: sparse_feed}) + + # Test with an empty sparse tensor. + empty_indices = np.empty((0, 4), dtype=np.int64) + empty_values = np.empty((0,), dtype=np.float64) + empty_dense_shape = [0, 4, 37, 9] + sparse_feed = sparse_tensor.SparseTensorValue(empty_indices, empty_values, + empty_dense_shape) + sess.run(init_op, feed_dict={st: sparse_feed}) + with self.assertRaises(errors.OutOfRangeError): + sess.run(get_next) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/from_tensor_slices_test.py b/tensorflow/python/data/kernel_tests/from_tensor_slices_test.py new file mode 100644 index 0000000000..9a480e5678 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/from_tensor_slices_test.py @@ -0,0 +1,177 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.from_tensor_slices().""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors +from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class FromTensorSlicesTest(test_base.DatasetTestBase): + + def testFromTensorSlices(self): + """Test a dataset that represents the slices from a tuple of tensors.""" + components = ( + np.tile(np.array([[1], [2], [3], [4]]), 20), np.tile( + np.array([[12], [13], [14], [15]]), 22), + np.array([37.0, 38.0, 39.0, 40.0]) + ) + + dataset = dataset_ops.Dataset.from_tensor_slices(components) + get_next = self.getNext(dataset) + + self.assertEqual([c.shape[1:] for c in components], + [shape for shape in dataset.output_shapes]) + + for i in range(4): + results = self.evaluate(get_next()) + for component, result_component in zip(components, results): + self.assertAllEqual(component[i], result_component) + with self.assertRaises(errors.OutOfRangeError): + results = self.evaluate(get_next()) + + def testSkipEagerFromTensorSlicesSparse(self): + """Test a dataset that represents the slices from a tuple of tensors.""" + components = (sparse_tensor.SparseTensorValue( + indices=np.array([[0, 0], [1, 0], [2, 0]]), + values=np.array([0, 0, 0]), + dense_shape=np.array([3, 1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[0, 0], [1, 1], [2, 2]]), + values=np.array([1, 2, 3]), + dense_shape=np.array([3, 3]))) + + dataset = dataset_ops.Dataset.from_tensor_slices(components) + + self.assertEqual( + [tensor_shape.TensorShape(c.dense_shape[1:]) for c in components], + [shape for shape in dataset.output_shapes]) + + expected = [ + (sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([0]), + dense_shape=np.array([1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([1]), + dense_shape=np.array([3]))), + (sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([0]), + dense_shape=np.array([1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[1]]), + values=np.array([2]), + dense_shape=np.array([3]))), + (sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([0]), + dense_shape=np.array([1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[2]]), + values=np.array([3]), + dense_shape=np.array([3]))), + ] + self.assertDatasetProduces(dataset, expected_output=expected) + + def testFromTensorSlicesMixed(self): + """Test a dataset that represents the slices from a tuple of tensors.""" + components = (np.tile(np.array([[1], [2], [3]]), 20), + np.tile(np.array([[12], [13], [14]]), 22), + np.array([37.0, 38.0, 39.0]), + sparse_tensor.SparseTensorValue( + indices=np.array([[0, 0], [1, 0], [2, 0]]), + values=np.array([0, 0, 0]), + dense_shape=np.array([3, 1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[0, 0], [1, 1], [2, 2]]), + values=np.array([1, 2, 3]), + dense_shape=np.array([3, 3]))) + + dataset = dataset_ops.Dataset.from_tensor_slices(components) + get_next = self.getNext(dataset) + self.assertEqual([ + tensor_shape.TensorShape(c.dense_shape[1:]) + if sparse_tensor.is_sparse(c) else c.shape[1:] for c in components + ], [shape for shape in dataset.output_shapes]) + + expected = [ + (sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([0]), + dense_shape=np.array([1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([1]), + dense_shape=np.array([3]))), + (sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([0]), + dense_shape=np.array([1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[1]]), + values=np.array([2]), + dense_shape=np.array([3]))), + (sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([0]), + dense_shape=np.array([1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[2]]), + values=np.array([3]), + dense_shape=np.array([3]))), + ] + for i in range(3): + results = self.evaluate(get_next()) + for component, result_component in zip( + (list(zip(*components[:3]))[i] + expected[i]), results): + if sparse_tensor.is_sparse(component): + self.assertSparseValuesEqual(component, result_component) + else: + self.assertAllEqual(component, result_component) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + def testFromTensorSlicesWithDict(self): + components = {"foo": [1, 2, 3], "bar": [[4.0], [5.0], [6.0]]} + dataset = dataset_ops.Dataset.from_tensor_slices(components) + get_next = self.getNext(dataset) + + self.assertEqual(dtypes.int32, dataset.output_types["foo"]) + self.assertEqual(dtypes.float32, dataset.output_types["bar"]) + self.assertEqual((), dataset.output_shapes["foo"]) + self.assertEqual((1,), dataset.output_shapes["bar"]) + + for i in range(3): + results = self.evaluate(get_next()) + self.assertEqual(components["foo"][i], results["foo"]) + self.assertEqual(components["bar"][i], results["bar"]) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/from_tensors_test.py b/tensorflow/python/data/kernel_tests/from_tensors_test.py new file mode 100644 index 0000000000..ab3c15263f --- /dev/null +++ b/tensorflow/python/data/kernel_tests/from_tensors_test.py @@ -0,0 +1,259 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.from_tensors().""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.core.protobuf import config_pb2 +from tensorflow.python.client import session +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.util import nest +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors +from tensorflow.python.framework import ops +from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class FromTensorsTest(test_base.DatasetTestBase): + + def testFromTensors(self): + """Test a dataset that represents a single tuple of tensors.""" + components = (np.array(1), np.array([1, 2, 3]), np.array(37.0)) + + dataset = dataset_ops.Dataset.from_tensors(components) + + self.assertEqual([c.shape for c in components], + nest.flatten(dataset.output_shapes)) + + self.assertDatasetProduces(dataset, expected_output=[components]) + + def testSkipEagerFromTensorsSparse(self): + """Test a dataset that represents a single tuple of tensors.""" + components = (sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([0]), + dense_shape=np.array([1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[0, 0], [1, 1]]), + values=np.array([-1, 1]), + dense_shape=np.array([2, 2]))) + + dataset = dataset_ops.Dataset.from_tensors(components) + + self.assertEqual( + [tensor_shape.TensorShape(c.dense_shape) for c in components], + [shape for shape in dataset.output_shapes]) + self.assertDatasetProduces(dataset, expected_output=[components]) + + def testFromTensorsMixed(self): + """Test an dataset that represents a single tuple of tensors.""" + components = (np.array(1), np.array([1, 2, 3]), np.array(37.0), + sparse_tensor.SparseTensorValue( + indices=np.array([[0]]), + values=np.array([0]), + dense_shape=np.array([1])), + sparse_tensor.SparseTensorValue( + indices=np.array([[0, 0], [1, 1]]), + values=np.array([-1, 1]), + dense_shape=np.array([2, 2]))) + + dataset = dataset_ops.Dataset.from_tensors(components) + self.assertEqual([ + tensor_shape.TensorShape(c.dense_shape) + if sparse_tensor.is_sparse(c) else c.shape for c in components + ], [shape for shape in dataset.output_shapes]) + + self.assertDatasetProduces(dataset, expected_output=[components]) + + # pylint: disable=g-long-lambda,unnecessary-lambda + def testNestedStructure(self): + components = (np.array([1, 2, 3], dtype=np.int64), + (np.array([4., 5.]), np.array([6., 7.])), + np.array([8, 9, 10], dtype=np.int64)) + + dataset = dataset_ops.Dataset.from_tensors(components) + self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), + dtypes.int64), dataset.output_types) + self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) + + dataset = dataset.shuffle(10, 10) + self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), + dtypes.int64), dataset.output_types) + self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) + + dataset = dataset.repeat(-1) + self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), + dtypes.int64), dataset.output_types) + self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) + + dataset = dataset.filter(lambda x, y, z: True) + self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), + dtypes.int64), dataset.output_types) + self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) + + dataset = dataset.take(5) + self.assertEquals((dtypes.int64, (dtypes.float64, dtypes.float64), + dtypes.int64), dataset.output_types) + self.assertEquals(([3], ([2], [2]), [3]), dataset.output_shapes) + + dataset = dataset.map(lambda x, y, z: ((x, z), (y[0], y[1]))) + self.assertEquals(((dtypes.int64, dtypes.int64), + (dtypes.float64, dtypes.float64)), dataset.output_types) + self.assertEquals((([3], [3]), ([2], [2])), dataset.output_shapes) + + dataset = dataset.flat_map( + lambda x, y: dataset_ops.Dataset.from_tensors(((x[0], x[1]), + (y[0], y[1]))) + ) + self.assertEquals(((dtypes.int64, dtypes.int64), + (dtypes.float64, dtypes.float64)), dataset.output_types) + self.assertEquals((([3], [3]), ([2], [2])), dataset.output_shapes) + + dataset = dataset.batch(32) + self.assertEquals(((dtypes.int64, dtypes.int64), + (dtypes.float64, dtypes.float64)), dataset.output_types) + self.assertEquals((([None, 3], [None, 3]), ([None, 2], [None, 2])), + nest.pack_sequence_as(dataset.output_shapes, [ + s.as_list() + for s in nest.flatten(dataset.output_shapes) + ])) + + # Define a separate set of components with matching leading + # dimension for the from-slices constructor. + components_for_slices = (np.array([1, 2, 3], dtype=np.int64), + (np.array([4., 5., 6.]), np.array([7., 8., 9.])), + np.array([10, 11, 12], dtype=np.int64)) + + dataset = dataset_ops.Dataset.from_tensor_slices(components_for_slices) + self.assertEquals((dtypes.int64, + (dtypes.float64, dtypes.float64), dtypes.int64), + dataset.output_types) + self.assertEquals(([], ([], []), []), dataset.output_shapes) + + # TODO(b/117581999): more specific shapes in eager mode. + @test_util.run_deprecated_v1 + def testSkipEagerNestedStructure(self): + components = (np.array([1, 2, 3], dtype=np.int64), (np.array([4., 5.]), + np.array([6., 7.])), + np.array([8, 9, 10], dtype=np.int64)) + + dataset = dataset_ops.Dataset.from_tensors(components) + dataset = dataset.map(lambda x, y, z: ((x, z), (y[0], y[1]))) + + dataset = dataset.flat_map( + lambda x, y: dataset_ops.Dataset.from_tensors( + ((x[0], x[1]), (y[0], y[1])))).batch(32) + + get_next = self.getNext(dataset) + (w, x), (y, z) = get_next() + self.assertEquals(dtypes.int64, w.dtype) + self.assertEquals(dtypes.int64, x.dtype) + self.assertEquals(dtypes.float64, y.dtype) + self.assertEquals(dtypes.float64, z.dtype) + self.assertEquals([None, 3], w.shape.as_list()) + self.assertEquals([None, 3], x.shape.as_list()) + self.assertEquals([None, 2], y.shape.as_list()) + self.assertEquals([None, 2], z.shape.as_list()) + + get_next = self.getNext(dataset) + (w, x), (y, z) = get_next() + self.assertEquals(dtypes.int64, w.dtype) + self.assertEquals(dtypes.int64, x.dtype) + self.assertEquals(dtypes.float64, y.dtype) + self.assertEquals(dtypes.float64, z.dtype) + self.assertEquals([None, 3], w.shape.as_list()) + self.assertEquals([None, 3], x.shape.as_list()) + self.assertEquals([None, 2], y.shape.as_list()) + self.assertEquals([None, 2], z.shape.as_list()) + + def testNestedDict(self): + components = {"a": {"aa": 1, "ab": [2.0, 2.0]}, "b": [3, 3, 3]} + dataset = dataset_ops.Dataset.from_tensors(components) + self.assertEquals(dtypes.int32, dataset.output_types["a"]["aa"]) + self.assertEquals(dtypes.float32, dataset.output_types["a"]["ab"]) + self.assertEquals(dtypes.int32, dataset.output_types["b"]) + self.assertEquals([], dataset.output_shapes["a"]["aa"]) + self.assertEquals([2], dataset.output_shapes["a"]["ab"]) + self.assertEquals([3], dataset.output_shapes["b"]) + + def testNonSequenceNestedStructure(self): + components = np.array([1, 2, 3], dtype=np.int64) + + dataset = dataset_ops.Dataset.from_tensors(components) + self.assertEquals(dtypes.int64, dataset.output_types) + self.assertEquals([3], dataset.output_shapes) + + dataset = dataset.filter( + lambda x: math_ops.reduce_all(math_ops.equal(x, components))) + self.assertEquals(dtypes.int64, dataset.output_types) + self.assertEquals([3], dataset.output_shapes) + + dataset = dataset.map(lambda x: array_ops.stack([x, x])) + self.assertEquals(dtypes.int64, dataset.output_types) + self.assertEquals([2, 3], dataset.output_shapes) + + dataset = dataset.flat_map( + lambda x: dataset_ops.Dataset.from_tensor_slices(x)) + self.assertEquals(dtypes.int64, dataset.output_types) + self.assertEquals([3], dataset.output_shapes) + + get_next = self.getNext(dataset) + self.assertEquals(dtypes.int64, get_next().dtype) + self.assertEquals([3], get_next().shape) + + def testSkipEagerSplitPipelineFailsWithPlacementError(self): + with session.Session( + target="", + config=config_pb2.ConfigProto(device_count={"CPU": 2})) as sess: + + dataset = dataset_ops.Dataset.from_tensors(0) + + # Define a pipeline that attempts to use variables on two + # different devices. + # + # Initialize the variables before creating to iterator, to avoid the + # placement algorithm overriding the DT_RESOURCE colocation constraints. + with ops.device("/cpu:0"): + var_0 = resource_variable_ops.ResourceVariable(initial_value=0) + dataset = dataset.map(lambda x: x + var_0.read_value()) + sess.run(var_0.initializer) + + with ops.device("/cpu:1"): + var_1 = resource_variable_ops.ResourceVariable(initial_value=0) + dataset = dataset.map(lambda x: x + var_1.read_value()) + sess.run(var_1.initializer) + + iterator = dataset_ops.make_initializable_iterator(dataset) + sess.run(iterator.initializer) + + with self.assertRaisesRegexp( + errors.FailedPreconditionError, + "Error while reading resource variable Variable"): + sess.run(iterator.get_next()) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/inputs_test.py b/tensorflow/python/data/kernel_tests/inputs_test.py deleted file mode 100644 index d089b49bcc..0000000000 --- a/tensorflow/python/data/kernel_tests/inputs_test.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright 2018 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -from absl.testing import parameterized -import numpy as np - -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.data.ops import readers -from tensorflow.python.data.util import nest -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import sparse_tensor -from tensorflow.python.platform import test - - -class InputsTest(test_base.DatasetTestBase, parameterized.TestCase): - - @staticmethod - def make_apply_fn(dataset): - - def apply_fn(dataset): - - def _apply_fn(dataset): - return dataset.cache() - - return dataset.apply(_apply_fn) - - return apply_fn - - @staticmethod - def make_gen(): - - def gen(): - yield 42 - - return gen - - @staticmethod - def make_interleave_fn(dataset, num_parallel_calls=None): - - def interleave_fn(dataset): - return dataset.interleave( - lambda x: dataset_ops.Dataset.range(0), - cycle_length=2, - num_parallel_calls=num_parallel_calls) - - return interleave_fn - - @parameterized.named_parameters( - ("FixedLengthRecord", readers.FixedLengthRecordDataset("", 42)), - ("FromGenerator", - dataset_ops.Dataset.from_generator(make_gen.__func__(), dtypes.int32), - 1), - ("FromSparseTensorSlices", - dataset_ops.Dataset.from_sparse_tensor_slices( - sparse_tensor.SparseTensor( - indices=np.array([[0, 0], [1, 0], [2, 0]]), - values=np.array([0, 0, 0]), - dense_shape=np.array([3, 1])))), - ("FromTensors", dataset_ops.Dataset.from_tensors([42])), - ("FromTensorSlices", dataset_ops.Dataset.from_tensors([42])), - ("Range", dataset_ops.Dataset.range(10)), - ("TextLine", readers.TextLineDataset("")), - ("TFRecord", readers.TFRecordDataset(""), 1), - ) - def testDatasetSourceInputs(self, dataset, num_inputs=0): - self.assertEqual(num_inputs, len(dataset._inputs())) - - @parameterized.named_parameters( - ("Apply", make_apply_fn.__func__(dataset_ops.Dataset.range(0)), - dataset_ops.Dataset.range(0)), - ("Batch", lambda x: x.batch(10), dataset_ops.Dataset.range(0)), - ("Cache", lambda x: x.cache(), dataset_ops.Dataset.range(0)), - ("Filter", lambda x: x.filter(lambda x: True), - dataset_ops.Dataset.range(0)), - ("FlatMap", lambda x: x.flat_map(lambda x: dataset_ops.Dataset.range(0)), - dataset_ops.Dataset.range(0)), - ("Interleave", make_interleave_fn.__func__(dataset_ops.Dataset.range(0)), - dataset_ops.Dataset.range(0)), - ("Map", lambda x: x.map(lambda x: x), dataset_ops.Dataset.range(0)), - ("PaddedBatch", lambda x: x.padded_batch(10, []), - dataset_ops.Dataset.range(0)), - ("ParallelInterleave", - make_interleave_fn.__func__(dataset_ops.Dataset.range(0), 2), - dataset_ops.Dataset.range(0)), - ("ParallelMap", lambda x: x.map(lambda x: x, num_parallel_calls=2), - dataset_ops.Dataset.range(0)), - ("Repeat", lambda x: x.repeat(), dataset_ops.Dataset.range(0)), - ("Shuffle", lambda x: x.shuffle(10), dataset_ops.Dataset.range(0)), - ("Skip", lambda x: x.skip(1), dataset_ops.Dataset.range(0)), - ("Take", lambda x: x.take(1), dataset_ops.Dataset.range(0)), - ("Window", lambda x: x.window(10), dataset_ops.Dataset.range(0)), - ) - def testUnaryTransformationInputs(self, dataset_fn, input_dataset): - self.assertEqual([input_dataset], dataset_fn(input_dataset)._inputs()) - - @parameterized.named_parameters( - ("Concatenate", lambda x, y: x.concatenate(y), - dataset_ops.Dataset.range(0), dataset_ops.Dataset.range(1))) - def testBinaryTransformationInputs(self, dataset_fn, input1, input2): - self.assertEqual([input1, input2], dataset_fn(input1, input2)._inputs()) - - @parameterized.named_parameters( - ("ZipOne", dataset_ops.Dataset.zip, (dataset_ops.Dataset.range(0))), - ("ZipNest", dataset_ops.Dataset.zip, - (dataset_ops.Dataset.range(0), - (dataset_ops.Dataset.range(1), dataset_ops.Dataset.range(2)))), - ("ZipTuple", dataset_ops.Dataset.zip, - (dataset_ops.Dataset.range(0), dataset_ops.Dataset.range(1)))) - def testVariadicTransformationInputs(self, dataset_fn, input_datasets): - self.assertEqual( - nest.flatten(input_datasets), - dataset_fn(input_datasets)._inputs()) - - def testCollectInputs(self): - ds1 = dataset_ops.Dataset.range(0) - ds2 = ds1.concatenate(ds1) - ds3 = dataset_ops.Dataset.zip((ds2, ds1, ds2)) - - inputs = [] - queue = [ds3] - while queue: - ds = queue[0] - queue = queue[1:] - queue.extend(ds._inputs()) - inputs.append(ds) - - self.assertEqual(5, inputs.count(ds1)) - self.assertEqual(2, inputs.count(ds2)) - self.assertEqual(1, inputs.count(ds3)) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/kernel_tests/interleave_dataset_op_test.py b/tensorflow/python/data/kernel_tests/interleave_test.py similarity index 85% rename from tensorflow/python/data/kernel_tests/interleave_dataset_op_test.py rename to tensorflow/python/data/kernel_tests/interleave_test.py index b911c249ce..c3450e6525 100644 --- a/tensorflow/python/data/kernel_tests/interleave_dataset_op_test.py +++ b/tensorflow/python/data/kernel_tests/interleave_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the experimental input pipeline ops.""" +"""Tests for `tf.data.Dataset.interleave()`.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -27,6 +27,7 @@ from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import errors from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import script_ops from tensorflow.python.ops import sparse_ops @@ -115,7 +116,7 @@ def _make_coordinated_sloppy_dataset(input_values, cycle_length, block_length, dataset = dataset_ops.Dataset.from_tensor_slices(input_values).repeat( 2).interleave(interleave_fn, cycle_length, block_length, num_parallel_calls).with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() return get_next, coordination_events @@ -133,7 +134,8 @@ def _repeat(values, count): return [[value] * value for value in np.tile(values, count)] -class InterleaveDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): +@test_util.run_all_in_graph_and_eager_modes +class InterleaveTest(test_base.DatasetTestBase, parameterized.TestCase): @parameterized.named_parameters( ("1", [4, 5, 6], 1, 1, [ @@ -191,16 +193,11 @@ class InterleaveDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): count).interleave( lambda x: dataset_ops.Dataset.from_tensors(x).repeat(x), cycle_length, block_length, num_parallel_calls) - get_next = dataset.make_one_shot_iterator().get_next() - - with self.cached_session() as sess: - for expected_element in _interleave( - _repeat(input_values, count), cycle_length, block_length): - self.assertEqual(expected_element, sess.run(get_next)) - - for _ in range(2): - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + expected_output = [ + element for element in _interleave( + _repeat(input_values, count), cycle_length, block_length) + ] + self.assertDatasetProduces(dataset, expected_output) @parameterized.named_parameters( ("1", np.float32([1., np.nan, 2., np.nan, 3.]), 1, 3, None), @@ -223,17 +220,16 @@ class InterleaveDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): lambda x: array_ops.check_numerics(x, "message")).interleave( dataset_ops.Dataset.from_tensors, cycle_length, block_length, num_parallel_calls) - get_next = dataset.make_one_shot_iterator().get_next() + get_next = self.getNext(dataset) - with self.cached_session() as sess: - for value in input_values: - if np.isnan(value): - with self.assertRaises(errors.InvalidArgumentError): - sess.run(get_next) - else: - self.assertEqual(value, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + for value in input_values: + if np.isnan(value): + with self.assertRaises(errors.InvalidArgumentError): + self.evaluate(get_next()) + else: + self.assertEqual(value, self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) def testInterleaveSparse(self): @@ -245,18 +241,17 @@ class InterleaveDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): return dataset_ops.Dataset.from_tensor_slices( sparse_ops.sparse_to_dense(x.indices, x.dense_shape, x.values)) - iterator = ( - dataset_ops.Dataset.range(10).map(_map_fn).interleave( - _interleave_fn, cycle_length=1).make_one_shot_iterator()) - get_next = iterator.get_next() - - with self.cached_session() as sess: - for i in range(10): - for j in range(2): - expected = [i, 0] if j % 2 == 0 else [0, -i] - self.assertAllEqual(expected, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + dataset = dataset_ops.Dataset.range(10).map(_map_fn).interleave( + _interleave_fn, cycle_length=1) + get_next = self.getNext(dataset) + for i in range(10): + for j in range(2): + expected = [i, 0] if j % 2 == 0 else [0, -i] + self.assertAllEqual(expected, self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) @parameterized.named_parameters( ("1", np.int64([4, 5, 6]), 2, 1, 1), @@ -269,8 +264,8 @@ class InterleaveDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): ("8", np.int64([4, 0, 6]), 2, 3, 1), ("9", np.int64([4, 0, 6]), 2, 3, 2), ) - def testSloppyInterleaveInOrder(self, input_values, cycle_length, - block_length, num_parallel_calls): + def testSkipEagerSloppyInterleaveInOrder(self, input_values, cycle_length, + block_length, num_parallel_calls): get_next, coordination_events = _make_coordinated_sloppy_dataset( input_values, cycle_length, block_length, num_parallel_calls) config = config_pb2.ConfigProto( @@ -281,7 +276,7 @@ class InterleaveDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): _repeat(input_values, 2), cycle_length, block_length): coordination_events[expected_element].set() self.assertEqual(expected_element * expected_element, - sess.run(get_next)) + self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) @@ -291,8 +286,8 @@ class InterleaveDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): ("3", np.int64([4, 5, 6]), 3, 2, 3), ("4", np.int64([4, 0, 6]), 2, 3, 2), ) - def testSloppyInterleaveOutOfOrder(self, input_values, cycle_length, - block_length, num_parallel_calls): + def testSkipEagerSloppyInterleaveOutOfOrder(self, input_values, cycle_length, + block_length, num_parallel_calls): get_next, coordination_events = _make_coordinated_sloppy_dataset( input_values, cycle_length, block_length, num_parallel_calls) config = config_pb2.ConfigProto( @@ -308,7 +303,7 @@ class InterleaveDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): for element in elements: coordination_events[element].set() - self.assertEqual(element * element, sess.run(get_next)) + self.assertEqual(element * element, self.evaluate(get_next)) with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) diff --git a/tensorflow/python/data/kernel_tests/iterator_checkpoint_test.py b/tensorflow/python/data/kernel_tests/iterator_checkpoint_test.py new file mode 100644 index 0000000000..91b356691b --- /dev/null +++ b/tensorflow/python/data/kernel_tests/iterator_checkpoint_test.py @@ -0,0 +1,129 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Checkpoint tests for `tf.data.Iterator`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import functools +import os + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.eager import context +from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import test +from tensorflow.python.training import checkpoint_management +from tensorflow.python.training.checkpointable import util as checkpointable_utils + + +@test_util.run_all_in_graph_and_eager_modes +class IteratorCheckpointingTest(test_base.DatasetTestBase): + + def testSaveRestoreOneShotIterator(self): + checkpoint_directory = self.get_temp_dir() + checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") + dataset = dataset_ops.Dataset.from_tensor_slices([1, 2, 3, 4, 5, 6]).map( + math_ops.square).batch(2) + iterator = iter(dataset) if context.executing_eagerly( + ) else dataset_ops.make_one_shot_iterator(dataset) + get_next = iterator.get_next if context.executing_eagerly( + ) else functools.partial(self.evaluate, iterator.get_next()) + checkpoint = checkpointable_utils.Checkpoint(iterator=iterator) + self.assertAllEqual([1, 4], get_next()) + save_path = checkpoint.save(checkpoint_prefix) + self.assertAllEqual([9, 16], get_next()) + self.assertAllEqual([25, 36], get_next()) + checkpoint.restore(save_path).run_restore_ops() + self.assertAllEqual([9, 16], get_next()) + self.assertAllEqual([25, 36], get_next()) + with self.assertRaises(errors.OutOfRangeError): + get_next() + + def testSaveRestoreMultipleIterator(self): + checkpoint_directory = self.get_temp_dir() + checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") + dataset = dataset_ops.Dataset.from_tensor_slices( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) + dataset = dataset.map(math_ops.square).batch(2) + iterator_1 = iter(dataset) if context.executing_eagerly( + ) else dataset_ops.make_one_shot_iterator(dataset) + get_next_1 = iterator_1.get_next if context.executing_eagerly( + ) else functools.partial(self.evaluate, iterator_1.get_next()) + iterator_2 = iter(dataset) if context.executing_eagerly( + ) else dataset_ops.make_one_shot_iterator(dataset) + get_next_2 = iterator_2.get_next if context.executing_eagerly( + ) else functools.partial(self.evaluate, iterator_2.get_next()) + dataset_2 = dataset_ops.Dataset.range(10) + iterator_3 = iter(dataset_2) if context.executing_eagerly( + ) else dataset_ops.make_one_shot_iterator(dataset_2) + get_next_3 = iterator_3.get_next if context.executing_eagerly( + ) else functools.partial(self.evaluate, iterator_3.get_next()) + checkpoint = checkpointable_utils.Checkpoint( + iterator_1=iterator_1, iterator_2=iterator_2, iterator_3=iterator_3) + self.assertAllEqual([1, 4], get_next_1()) + self.assertAllEqual(0, get_next_3()) + self.assertAllEqual(1, get_next_3()) + self.assertAllEqual(2, get_next_3()) + save_path = checkpoint.save(checkpoint_prefix) + self.assertAllEqual([1, 4], get_next_2()) + self.assertAllEqual([9, 16], get_next_2()) + self.assertAllEqual(3, get_next_3()) + checkpoint.restore(save_path).run_restore_ops() + self.assertAllEqual([9, 16], get_next_1()) + self.assertAllEqual([1, 4], get_next_2()) + self.assertAllEqual(3, get_next_3()) + + def testRestoreExhaustedIterator(self): + checkpoint_directory = self.get_temp_dir() + checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") + dataset = dataset_ops.Dataset.range(3) + iterator = iter(dataset) if context.executing_eagerly( + ) else dataset_ops.make_one_shot_iterator(dataset) + get_next = iterator.get_next if context.executing_eagerly( + ) else functools.partial(self.evaluate, iterator.get_next()) + checkpoint = checkpointable_utils.Checkpoint(iterator=iterator) + self.assertAllEqual(0, get_next()) + self.assertAllEqual(1, get_next()) + save_path = checkpoint.save(checkpoint_prefix) + self.assertAllEqual(2, get_next()) + checkpoint.restore(save_path).run_restore_ops() + self.assertAllEqual(2, get_next()) + save_path = checkpoint.save(checkpoint_prefix) + checkpoint.restore(save_path).run_restore_ops() + with self.assertRaises(errors.OutOfRangeError): + get_next() + + def testRestoreInReconstructedIteratorInitializable(self): + checkpoint_directory = self.get_temp_dir() + checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") + dataset = dataset_ops.Dataset.range(10) + iterator = iter(dataset) if context.executing_eagerly( + ) else dataset_ops.make_initializable_iterator(dataset) + get_next = iterator.get_next + checkpoint = checkpointable_utils.Checkpoint(iterator=iterator) + for i in range(5): + checkpoint.restore( + checkpoint_management.latest_checkpoint( + checkpoint_directory)).initialize_or_restore() + for j in range(2): + self.assertEqual(i * 2 + j, self.evaluate(get_next())) + checkpoint.save(file_prefix=checkpoint_prefix) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/iterator_ops_cluster_test.py b/tensorflow/python/data/kernel_tests/iterator_cluster_test.py similarity index 96% rename from tensorflow/python/data/kernel_tests/iterator_ops_cluster_test.py rename to tensorflow/python/data/kernel_tests/iterator_cluster_test.py index bf5fd781d6..728bed20a1 100644 --- a/tensorflow/python/data/kernel_tests/iterator_ops_cluster_test.py +++ b/tensorflow/python/data/kernel_tests/iterator_cluster_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the experimental input pipeline ops that need test_util.""" +"""Tests for `tf.data.Iterator` using distributed sessions.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -47,7 +47,7 @@ class IteratorClusterTest(test.TestCase): with ops.device("/job:worker/replica:0/task:0/cpu:1"): dataset_3 = dataset_ops.Dataset.from_tensor_slices([1, 2, 3]) - iterator_3 = dataset_3.make_one_shot_iterator() + iterator_3 = dataset_ops.make_one_shot_iterator(dataset_3) iterator_3_handle = iterator_3.string_handle() with ops.device("/job:worker/replica:0/task:0/cpu:0"): @@ -62,7 +62,7 @@ class IteratorClusterTest(test.TestCase): def _testRemoteIteratorHelper(self, device0, device1, target): with ops.device(device1): dataset_3 = dataset_ops.Dataset.from_tensor_slices([1, 2, 3]) - iterator_3 = dataset_3.make_one_shot_iterator() + iterator_3 = dataset_ops.make_one_shot_iterator(dataset_3) iterator_3_handle = iterator_3.string_handle() @function.Defun(dtypes.string) @@ -161,7 +161,7 @@ class IteratorClusterTest(test.TestCase): dataset_ops.Dataset.from_tensor_slices(components).map(_map_fn) .repeat(None).prefetch(10000)) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() diff --git a/tensorflow/python/data/kernel_tests/iterator_ops_test.py b/tensorflow/python/data/kernel_tests/iterator_test.py similarity index 83% rename from tensorflow/python/data/kernel_tests/iterator_ops_test.py rename to tensorflow/python/data/kernel_tests/iterator_test.py index a2a3528cc6..916cf8bb45 100644 --- a/tensorflow/python/data/kernel_tests/iterator_ops_test.py +++ b/tensorflow/python/data/kernel_tests/iterator_test.py @@ -12,12 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the experimental input pipeline ops.""" +"""Tests for `tf.data.Iterator`.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import functools import os import warnings @@ -50,24 +49,24 @@ from tensorflow.python.ops import parsing_ops from tensorflow.python.ops import script_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test -from tensorflow.python.training import checkpoint_management from tensorflow.python.training import server_lib -from tensorflow.python.training.checkpointable import util as checkpointable_utils from tensorflow.python.util import compat class IteratorTest(test.TestCase, parameterized.TestCase): + @test_util.run_deprecated_v1 def testNoGradients(self): component = constant_op.constant([1.]) side = constant_op.constant(0.) add = lambda x: x + side dataset = dataset_ops.Dataset.from_tensor_slices(component).map(add) - value = dataset.make_one_shot_iterator().get_next() + value = dataset_ops.make_one_shot_iterator(dataset).get_next() self.assertIsNone(gradients_impl.gradients(value, component)[0]) self.assertIsNone(gradients_impl.gradients(value, side)[0]) self.assertIsNone(gradients_impl.gradients(value, [component, side])[0]) + @test_util.run_deprecated_v1 def testCapturingStateInOneShotRaisesException(self): var = variables.Variable(37.0, name="myvar") dataset = ( @@ -76,8 +75,9 @@ class IteratorTest(test.TestCase, parameterized.TestCase): with self.assertRaisesRegexp( ValueError, r"`Dataset.make_one_shot_iterator\(\)` does not support " "datasets that capture stateful objects.+myvar"): - dataset.make_one_shot_iterator() + dataset_ops.make_one_shot_iterator(dataset) + @test_util.run_deprecated_v1 def testOneShotIterator(self): components = (np.arange(7), np.array([[1, 2, 3]]) * np.arange(7)[:, np.newaxis], @@ -86,9 +86,9 @@ class IteratorTest(test.TestCase, parameterized.TestCase): def _map_fn(x, y, z): return math_ops.square(x), math_ops.square(y), math_ops.square(z) - iterator = ( + iterator = dataset_ops.make_one_shot_iterator( dataset_ops.Dataset.from_tensor_slices(components).map(_map_fn) - .repeat(14).make_one_shot_iterator()) + .repeat(14)) get_next = iterator.get_next() self.assertEqual([c.shape[1:] for c in components], @@ -103,6 +103,7 @@ class IteratorTest(test.TestCase, parameterized.TestCase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testOneShotIteratorCaptureByValue(self): components = (np.arange(7), np.array([[1, 2, 3]]) * np.arange(7)[:, np.newaxis], @@ -112,9 +113,9 @@ class IteratorTest(test.TestCase, parameterized.TestCase): def _map_fn(x, y, z): return math_ops.square(x), math_ops.square(y), math_ops.square(z) - iterator = ( + iterator = dataset_ops.make_one_shot_iterator( dataset_ops.Dataset.from_tensor_slices(tensor_components) - .map(_map_fn).repeat(14).make_one_shot_iterator()) + .map(_map_fn).repeat(14)) get_next = iterator.get_next() self.assertEqual([c.shape[1:] for c in components], @@ -139,9 +140,9 @@ class IteratorTest(test.TestCase, parameterized.TestCase): def _map_fn(x, y, z): return math_ops.square(x), math_ops.square(y), math_ops.square(z) - iterator = ( + iterator = dataset_ops.make_one_shot_iterator( dataset_ops.Dataset.from_tensor_slices(components) - .map(_map_fn).repeat(14).make_one_shot_iterator()) + .map(_map_fn).repeat(14)) return iterator.get_next() server = server_lib.Server.create_local_server() @@ -165,9 +166,10 @@ class IteratorTest(test.TestCase, parameterized.TestCase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testOneShotIteratorNonBlocking(self): dataset = dataset_ops.Dataset.from_tensors([1, 2, 3]).map(lambda x: x * x) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) next_element = iterator.get_next() # Create a session with a single thread to ensure that the @@ -203,12 +205,13 @@ class IteratorTest(test.TestCase, parameterized.TestCase): len([None for r in results if r is None])) self.assertAllEqual([[1, 4, 9]], [r for r in results if r is not None]) + @test_util.run_deprecated_v1 def testOneShotIteratorInitializerFails(self): # Define a dataset whose initialization will always fail. dataset = dataset_ops.Dataset.from_tensors( array_ops.check_numerics( constant_op.constant(1.0) / constant_op.constant(0.0), "oops")) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) next_element = iterator.get_next() with self.cached_session() as sess: @@ -283,11 +286,11 @@ class IteratorTest(test.TestCase, parameterized.TestCase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 def testNotInitializedError(self): components = (np.array(1), np.array([1, 2, 3]), np.array(37.0)) - iterator = ( - dataset_ops.Dataset.from_tensors(components) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_tensors(components)) get_next = iterator.get_next() with self.cached_session() as sess: @@ -295,6 +298,7 @@ class IteratorTest(test.TestCase, parameterized.TestCase): "iterator has not been initialized"): sess.run(get_next) + @test_util.run_deprecated_v1 def testReinitializableIterator(self): dataset_3 = dataset_ops.Dataset.from_tensors( constant_op.constant([1, 2, 3])) @@ -334,6 +338,33 @@ class IteratorTest(test.TestCase, parameterized.TestCase): with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) + @test_util.run_deprecated_v1 + def testReinitializableIteratorWithFunctions(self): + + def g(): + for i in range(10): + yield i + + iterator = iterator_ops.Iterator.from_structure(dtypes.int64, []) + next_element = iterator.get_next() + + with self.cached_session() as sess: + dataset_1 = dataset_ops.Dataset.from_generator( + g, output_types=dtypes.int64) + sess.run(iterator.make_initializer(dataset_1)) + for expected in range(10): + self.assertEqual(expected, sess.run(next_element)) + with self.assertRaises(errors.OutOfRangeError): + sess.run(next_element) + + dataset_2 = dataset_ops.Dataset.from_generator( + g, output_types=dtypes.int64) + sess.run(iterator.make_initializer(dataset_2)) + for expected in range(10): + self.assertEqual(expected, sess.run(next_element)) + with self.assertRaises(errors.OutOfRangeError): + sess.run(next_element) + def testReinitializableIteratorStaticErrors(self): # Non-matching structure for types and shapes. with self.assertRaises(TypeError): @@ -367,12 +398,13 @@ class IteratorTest(test.TestCase, parameterized.TestCase): (constant_op.constant([1, 2, 3], dtype=dtypes.int64), constant_op.constant([4., 5., 6., 7.], dtype=dtypes.float64)))) + @test_util.run_deprecated_v1 def testIteratorStringHandle(self): dataset_3 = dataset_ops.Dataset.from_tensor_slices([1, 2, 3]) dataset_4 = dataset_ops.Dataset.from_tensor_slices([10, 20, 30, 40]) - iterator_3 = dataset_3.make_one_shot_iterator() - iterator_4 = dataset_4.make_one_shot_iterator() + iterator_3 = dataset_ops.make_one_shot_iterator(dataset_3) + iterator_4 = dataset_ops.make_one_shot_iterator(dataset_4) handle_placeholder = array_ops.placeholder(dtypes.string, shape=[]) feedable_iterator = iterator_ops.Iterator.from_string_handle( @@ -422,13 +454,14 @@ class IteratorTest(test.TestCase, parameterized.TestCase): sess.run( next_element, feed_dict={handle_placeholder: iterator_4_handle}) + @test_util.run_deprecated_v1 def testIteratorStringHandleFuture(self): with forward_compat.forward_compatibility_horizon(2018, 8, 4): dataset_3 = dataset_ops.Dataset.from_tensor_slices([1, 2, 3]) dataset_4 = dataset_ops.Dataset.from_tensor_slices([10, 20, 30, 40]) - iterator_3 = dataset_3.make_one_shot_iterator() - iterator_4 = dataset_4.make_one_shot_iterator() + iterator_3 = dataset_ops.make_one_shot_iterator(dataset_3) + iterator_4 = dataset_ops.make_one_shot_iterator(dataset_4) handle_placeholder = array_ops.placeholder(dtypes.string, shape=[]) feedable_iterator = iterator_ops.Iterator.from_string_handle( @@ -485,10 +518,11 @@ class IteratorTest(test.TestCase, parameterized.TestCase): sess.run( next_element, feed_dict={handle_placeholder: iterator_4_handle}) + @test_util.run_deprecated_v1 def testIteratorStringHandleReuseTensorObject(self): dataset = dataset_ops.Dataset.from_tensor_slices([1, 2, 3]) - one_shot_iterator = dataset.make_one_shot_iterator() - initializable_iterator = dataset.make_initializable_iterator() + one_shot_iterator = dataset_ops.make_one_shot_iterator(dataset) + initializable_iterator = dataset_ops.make_initializable_iterator(dataset) structure_iterator = iterator_ops.Iterator.from_structure( dataset.output_types) @@ -513,6 +547,7 @@ class IteratorTest(test.TestCase, parameterized.TestCase): self.assertEqual("foo_1", handle_with_same_name.op.name) self.assertIsNot(handle_with_name, handle_with_same_name) + @test_util.run_deprecated_v1 def testIteratorStringHandleError(self): dataset_int_scalar = ( dataset_ops.Dataset.from_tensor_slices([1, 2, 3]).repeat()) @@ -528,10 +563,10 @@ class IteratorTest(test.TestCase, parameterized.TestCase): handle_placeholder, dtypes.int32) with self.cached_session() as sess: - handle_int_scalar = sess.run( - dataset_int_scalar.make_one_shot_iterator().string_handle()) - handle_float_vector = sess.run( - dataset_float_vector.make_one_shot_iterator().string_handle()) + handle_int_scalar = sess.run(dataset_ops.make_one_shot_iterator( + dataset_int_scalar).string_handle()) + handle_float_vector = sess.run(dataset_ops.make_one_shot_iterator( + dataset_float_vector).string_handle()) self.assertEqual(1, sess.run( @@ -553,13 +588,14 @@ class IteratorTest(test.TestCase, parameterized.TestCase): feedable_int_vector.get_next(), feed_dict={handle_placeholder: handle_float_vector})) + @test_util.run_deprecated_v1 def testRemoteIteratorUsingRemoteCallOpDirectSession(self): worker_config = config_pb2.ConfigProto() worker_config.device_count["CPU"] = 3 with ops.device("/job:localhost/replica:0/task:0/cpu:1"): dataset_3 = dataset_ops.Dataset.from_tensor_slices([1, 2, 3]) - iterator_3 = dataset_3.make_one_shot_iterator() + iterator_3 = dataset_ops.make_one_shot_iterator(dataset_3) iterator_3_handle = iterator_3.string_handle() @function.Defun(dtypes.string) @@ -609,6 +645,7 @@ class IteratorTest(test.TestCase, parameterized.TestCase): target_placeholder: "/job:localhost/replica:0/task:0/cpu:1" }) + @test_util.run_deprecated_v1 def testRemoteIteratorUsingRemoteCallOpMultiWorkers(self): s1 = server_lib.Server.create_local_server() s2 = server_lib.Server.create_local_server() @@ -631,7 +668,7 @@ class IteratorTest(test.TestCase, parameterized.TestCase): for device in worker_devices: with ops.device(device): src = dataset_ops.Dataset.from_tensor_slices([device]) - itr = src.make_one_shot_iterator() + itr = dataset_ops.make_one_shot_iterator(src) itr_handles.append(itr.string_handle()) targets = dataset_ops.Dataset.from_tensor_slices(worker_devices) @@ -649,7 +686,7 @@ class IteratorTest(test.TestCase, parameterized.TestCase): with ops.device("/job:client"): client_dataset = dataset_ops.Dataset.zip((targets, handles)).map(map_fn) - itr = client_dataset.make_initializable_iterator() + itr = dataset_ops.make_initializable_iterator(client_dataset) n = itr.get_next() with session.Session(s3.target, config=config) as sess: @@ -667,7 +704,7 @@ class IteratorTest(test.TestCase, parameterized.TestCase): with ops.device("/job:localhost/replica:0/task:0/cpu:0"): dataset_3 = dataset_ops.Dataset.from_tensor_slices([1, 2, 3]) - iterator_3 = dataset_3.make_one_shot_iterator() + iterator_3 = dataset_ops.make_one_shot_iterator(dataset_3) iterator_3_handle = iterator_3.string_handle() def _encode_raw(byte_array): @@ -716,6 +753,7 @@ class IteratorTest(test.TestCase, parameterized.TestCase): target_placeholder: "/job:localhost/replica:0/task:0/cpu:0" }) + @test_util.run_deprecated_v1 def testIncorrectIteratorRestore(self): def _path(): @@ -738,8 +776,8 @@ class IteratorTest(test.TestCase, parameterized.TestCase): def _build_range_dataset_graph(): start = 1 stop = 10 - iterator = dataset_ops.Dataset.range(start, - stop).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(start, stop)) init_op = iterator.initializer get_next = iterator.get_next() save_op = _save_op(iterator._iterator_resource) @@ -748,8 +786,8 @@ class IteratorTest(test.TestCase, parameterized.TestCase): def _build_reader_dataset_graph(): filenames = ["test"] # Does not exist but we don't care in this test. - iterator = readers.FixedLengthRecordDataset( - filenames, 1, 0, 0).make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator( + readers.FixedLengthRecordDataset(filenames, 1, 0, 0)) init_op = iterator.initializer get_next_op = iterator.get_next() save_op = _save_op(iterator._iterator_resource) @@ -774,8 +812,9 @@ class IteratorTest(test.TestCase, parameterized.TestCase): with self.assertRaises(errors.InvalidArgumentError): sess.run(restore_op) + @test_util.run_deprecated_v1 def testRepeatedGetNextWarning(self): - iterator = dataset_ops.Dataset.range(10).make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset_ops.Dataset.range(10)) warnings.simplefilter("always") with warnings.catch_warnings(record=True) as w: for _ in range(100): @@ -818,8 +857,8 @@ class IteratorTest(test.TestCase, parameterized.TestCase): expected_output_classes, expected_output_types, expected_output_shapes): tf_value = tf_value_fn() - iterator = dataset_ops.Dataset.from_tensors( - tf_value).make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator( + dataset_ops.Dataset.from_tensors(tf_value)) self.assertTrue(expected_element_structure.is_compatible_with( iterator._element_structure)) @@ -832,100 +871,11 @@ class IteratorTest(test.TestCase, parameterized.TestCase): def testIteratorGetNextName(self): with ops.Graph().as_default(): - iterator = dataset_ops.Dataset.from_tensors(37.0).make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator( + dataset_ops.Dataset.from_tensors(37.0)) next_element = iterator.get_next(name="overridden_name") self.assertEqual("overridden_name", next_element.op.name) -class IteratorCheckpointingTest(test.TestCase): - - @test_util.run_in_graph_and_eager_modes - def testSaveRestoreOneShotIterator(self): - checkpoint_directory = self.get_temp_dir() - checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") - dataset = dataset_ops.Dataset.from_tensor_slices([1, 2, 3, 4, 5, 6]).map( - math_ops.square).batch(2) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next if context.executing_eagerly( - ) else functools.partial(self.evaluate, iterator.get_next()) - checkpoint = checkpointable_utils.Checkpoint(iterator=iterator) - self.assertAllEqual([1, 4], get_next()) - save_path = checkpoint.save(checkpoint_prefix) - self.assertAllEqual([9, 16], get_next()) - self.assertAllEqual([25, 36], get_next()) - checkpoint.restore(save_path).run_restore_ops() - self.assertAllEqual([9, 16], get_next()) - self.assertAllEqual([25, 36], get_next()) - with self.assertRaises(errors.OutOfRangeError): - get_next() - - @test_util.run_in_graph_and_eager_modes - def testSaveRestoreMultipleIterator(self): - checkpoint_directory = self.get_temp_dir() - checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") - dataset = dataset_ops.Dataset.from_tensor_slices( - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) - dataset = dataset.map(math_ops.square).batch(2) - iterator_1 = dataset.make_one_shot_iterator() - get_next_1 = iterator_1.get_next if context.executing_eagerly( - ) else functools.partial(self.evaluate, iterator_1.get_next()) - iterator_2 = dataset.make_one_shot_iterator() - get_next_2 = iterator_2.get_next if context.executing_eagerly( - ) else functools.partial(self.evaluate, iterator_2.get_next()) - dataset_2 = dataset_ops.Dataset.range(10) - iterator_3 = dataset_2.make_one_shot_iterator() - get_next_3 = iterator_3.get_next if context.executing_eagerly( - ) else functools.partial(self.evaluate, iterator_3.get_next()) - checkpoint = checkpointable_utils.Checkpoint( - iterator_1=iterator_1, iterator_2=iterator_2, iterator_3=iterator_3) - self.assertAllEqual([1, 4], get_next_1()) - self.assertAllEqual(0, get_next_3()) - self.assertAllEqual(1, get_next_3()) - self.assertAllEqual(2, get_next_3()) - save_path = checkpoint.save(checkpoint_prefix) - self.assertAllEqual([1, 4], get_next_2()) - self.assertAllEqual([9, 16], get_next_2()) - self.assertAllEqual(3, get_next_3()) - checkpoint.restore(save_path).run_restore_ops() - self.assertAllEqual([9, 16], get_next_1()) - self.assertAllEqual([1, 4], get_next_2()) - self.assertAllEqual(3, get_next_3()) - - @test_util.run_in_graph_and_eager_modes - def testRestoreExhaustedIterator(self): - checkpoint_directory = self.get_temp_dir() - checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") - dataset = dataset_ops.Dataset.range(3) - iterator = dataset.make_one_shot_iterator() - get_next = iterator.get_next if context.executing_eagerly( - ) else functools.partial(self.evaluate, iterator.get_next()) - checkpoint = checkpointable_utils.Checkpoint(iterator=iterator) - self.assertAllEqual(0, get_next()) - self.assertAllEqual(1, get_next()) - save_path = checkpoint.save(checkpoint_prefix) - self.assertAllEqual(2, get_next()) - checkpoint.restore(save_path).run_restore_ops() - self.assertAllEqual(2, get_next()) - save_path = checkpoint.save(checkpoint_prefix) - checkpoint.restore(save_path).run_restore_ops() - with self.assertRaises(errors.OutOfRangeError): - get_next() - - def testRestoreInReconstructedIteratorInitializable(self): - checkpoint_directory = self.get_temp_dir() - checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") - dataset = dataset_ops.Dataset.range(10) - iterator = dataset.make_initializable_iterator() - get_next = iterator.get_next() - checkpoint = checkpointable_utils.Checkpoint(iterator=iterator) - for i in range(5): - with self.cached_session() as sess: - checkpoint.restore(checkpoint_management.latest_checkpoint( - checkpoint_directory)).initialize_or_restore(sess) - for j in range(2): - self.assertEqual(i * 2 + j, sess.run(get_next)) - checkpoint.save(file_prefix=checkpoint_prefix) - - if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/kernel_tests/list_files_dataset_op_test.py b/tensorflow/python/data/kernel_tests/list_files_dataset_op_test.py deleted file mode 100644 index b58c1444da..0000000000 --- a/tensorflow/python/data/kernel_tests/list_files_dataset_op_test.py +++ /dev/null @@ -1,291 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -from os import path -import shutil -import tempfile - -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.ops import array_ops -from tensorflow.python.platform import test -from tensorflow.python.util import compat - - -class ListFilesDatasetOpTest(test_base.DatasetTestBase): - - def setUp(self): - self.tmp_dir = tempfile.mkdtemp() - - def tearDown(self): - shutil.rmtree(self.tmp_dir, ignore_errors=True) - - def _touchTempFiles(self, filenames): - for filename in filenames: - open(path.join(self.tmp_dir, filename), 'a').close() - - def testEmptyDirectory(self): - dataset = dataset_ops.Dataset.list_files(path.join(self.tmp_dir, '*')) - with self.cached_session() as sess: - itr = dataset.make_one_shot_iterator() - next_element = itr.get_next() - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - def testSimpleDirectory(self): - filenames = ['a', 'b', 'c'] - self._touchTempFiles(filenames) - - dataset = dataset_ops.Dataset.list_files(path.join(self.tmp_dir, '*')) - with self.cached_session() as sess: - itr = dataset.make_one_shot_iterator() - next_element = itr.get_next() - - full_filenames = [] - produced_filenames = [] - for filename in filenames: - full_filenames.append( - compat.as_bytes(path.join(self.tmp_dir, filename))) - produced_filenames.append(compat.as_bytes(sess.run(next_element))) - self.assertItemsEqual(full_filenames, produced_filenames) - with self.assertRaises(errors.OutOfRangeError): - sess.run(itr.get_next()) - - def testSimpleDirectoryNotShuffled(self): - filenames = ['b', 'c', 'a'] - self._touchTempFiles(filenames) - - dataset = dataset_ops.Dataset.list_files( - path.join(self.tmp_dir, '*'), shuffle=False) - with self.cached_session() as sess: - itr = dataset.make_one_shot_iterator() - next_element = itr.get_next() - - for filename in sorted(filenames): - self.assertEqual(compat.as_bytes(path.join(self.tmp_dir, filename)), - sess.run(next_element)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(itr.get_next()) - - def testFixedSeedResultsInRepeatableOrder(self): - filenames = ['a', 'b', 'c'] - self._touchTempFiles(filenames) - - dataset = dataset_ops.Dataset.list_files( - path.join(self.tmp_dir, '*'), shuffle=True, seed=37) - with self.cached_session() as sess: - itr = dataset.make_initializable_iterator() - next_element = itr.get_next() - - full_filenames = [compat.as_bytes(path.join(self.tmp_dir, filename)) - for filename in filenames] - - all_produced_filenames = [] - for _ in range(3): - produced_filenames = [] - sess.run(itr.initializer) - try: - while True: - produced_filenames.append(sess.run(next_element)) - except errors.OutOfRangeError: - pass - all_produced_filenames.append(produced_filenames) - - # Each run should produce the same set of filenames, which may be - # different from the order of `full_filenames`. - self.assertItemsEqual(full_filenames, all_produced_filenames[0]) - # However, the different runs should produce filenames in the same order - # as each other. - self.assertEqual(all_produced_filenames[0], all_produced_filenames[1]) - self.assertEqual(all_produced_filenames[0], all_produced_filenames[2]) - - def testEmptyDirectoryInitializer(self): - filename_placeholder = array_ops.placeholder(dtypes.string, shape=[]) - dataset = dataset_ops.Dataset.list_files(filename_placeholder) - - with self.cached_session() as sess: - itr = dataset.make_initializable_iterator() - with self.assertRaisesRegexp( - errors.InvalidArgumentError, 'No files matched pattern: '): - sess.run( - itr.initializer, - feed_dict={filename_placeholder: path.join(self.tmp_dir, '*')}) - - def testSimpleDirectoryInitializer(self): - filenames = ['a', 'b', 'c'] - self._touchTempFiles(filenames) - - filename_placeholder = array_ops.placeholder(dtypes.string, shape=[]) - dataset = dataset_ops.Dataset.list_files(filename_placeholder) - - with self.cached_session() as sess: - itr = dataset.make_initializable_iterator() - next_element = itr.get_next() - sess.run( - itr.initializer, - feed_dict={filename_placeholder: path.join(self.tmp_dir, '*')}) - - full_filenames = [] - produced_filenames = [] - for filename in filenames: - full_filenames.append( - compat.as_bytes(path.join(self.tmp_dir, filename))) - produced_filenames.append(compat.as_bytes(sess.run(next_element))) - - self.assertItemsEqual(full_filenames, produced_filenames) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(itr.get_next()) - - def testFileSuffixes(self): - filenames = ['a.txt', 'b.py', 'c.py', 'd.pyc'] - self._touchTempFiles(filenames) - - filename_placeholder = array_ops.placeholder(dtypes.string, shape=[]) - dataset = dataset_ops.Dataset.list_files(filename_placeholder) - - with self.cached_session() as sess: - itr = dataset.make_initializable_iterator() - next_element = itr.get_next() - sess.run( - itr.initializer, - feed_dict={filename_placeholder: path.join(self.tmp_dir, '*.py')}) - - full_filenames = [] - produced_filenames = [] - for filename in filenames[1:-1]: - full_filenames.append( - compat.as_bytes(path.join(self.tmp_dir, filename))) - produced_filenames.append(compat.as_bytes(sess.run(next_element))) - self.assertItemsEqual(full_filenames, produced_filenames) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(itr.get_next()) - - def testFileMiddles(self): - filenames = ['a.txt', 'b.py', 'c.pyc'] - self._touchTempFiles(filenames) - - filename_placeholder = array_ops.placeholder(dtypes.string, shape=[]) - dataset = dataset_ops.Dataset.list_files(filename_placeholder) - - with self.cached_session() as sess: - itr = dataset.make_initializable_iterator() - next_element = itr.get_next() - sess.run( - itr.initializer, - feed_dict={filename_placeholder: path.join(self.tmp_dir, '*.py*')}) - - full_filenames = [] - produced_filenames = [] - for filename in filenames[1:]: - full_filenames.append( - compat.as_bytes(path.join(self.tmp_dir, filename))) - produced_filenames.append(compat.as_bytes(sess.run(next_element))) - - self.assertItemsEqual(full_filenames, produced_filenames) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(itr.get_next()) - - def testNoShuffle(self): - filenames = ['a', 'b', 'c'] - self._touchTempFiles(filenames) - - # Repeat the list twice and ensure that the order is the same each time. - # NOTE(mrry): This depends on an implementation detail of `list_files()`, - # which is that the list of files is captured when the iterator is - # initialized. Otherwise, or if e.g. the iterator were initialized more than - # once, it's possible that the non-determinism of `tf.matching_files()` - # would cause this test to fail. However, it serves as a useful confirmation - # that the `shuffle=False` argument is working as intended. - # TODO(b/73959787): Provide some ordering guarantees so that this test is - # more meaningful. - dataset = dataset_ops.Dataset.list_files( - path.join(self.tmp_dir, '*'), shuffle=False).repeat(2) - with self.cached_session() as sess: - itr = dataset.make_one_shot_iterator() - next_element = itr.get_next() - - full_filenames = [] - produced_filenames = [] - for filename in filenames * 2: - full_filenames.append( - compat.as_bytes(path.join(self.tmp_dir, filename))) - produced_filenames.append(compat.as_bytes(sess.run(next_element))) - with self.assertRaises(errors.OutOfRangeError): - sess.run(itr.get_next()) - self.assertItemsEqual(full_filenames, produced_filenames) - self.assertEqual(produced_filenames[:len(filenames)], - produced_filenames[len(filenames):]) - - def testMultiplePatternsAsList(self): - filenames = ['a.txt', 'b.py', 'c.py', 'd.pyc'] - self._touchTempFiles(filenames) - - patterns = [path.join(self.tmp_dir, pat) for pat in ['*.py', '*.txt']] - dataset = dataset_ops.Dataset.list_files(patterns) - with self.cached_session() as sess: - itr = dataset.make_one_shot_iterator() - next_element = itr.get_next() - - full_filenames = [] - produced_filenames = [] - for filename in filenames[:-1]: - full_filenames.append( - compat.as_bytes(path.join(self.tmp_dir, filename))) - produced_filenames.append(compat.as_bytes(sess.run(next_element))) - self.assertItemsEqual(full_filenames, produced_filenames) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(itr.get_next()) - - def testMultiplePatternsAsTensor(self): - filenames = ['a.txt', 'b.py', 'c.py', 'd.pyc'] - self._touchTempFiles(filenames) - - filename_placeholder = array_ops.placeholder( - dtypes.string, shape=[ - 2, - ]) - dataset = dataset_ops.Dataset.list_files(filename_placeholder) - - with self.cached_session() as sess: - itr = dataset.make_initializable_iterator() - next_element = itr.get_next() - patterns = [path.join(self.tmp_dir, pat) for pat in ['*.py', '*.txt']] - sess.run(itr.initializer, feed_dict={filename_placeholder: patterns}) - - full_filenames = [] - produced_filenames = [] - for filename in filenames[:-1]: - full_filenames.append( - compat.as_bytes(path.join(self.tmp_dir, filename))) - produced_filenames.append(compat.as_bytes(sess.run(next_element))) - self.assertItemsEqual(full_filenames, produced_filenames) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(itr.get_next()) - - -if __name__ == '__main__': - test.main() diff --git a/tensorflow/python/data/kernel_tests/list_files_test.py b/tensorflow/python/data/kernel_tests/list_files_test.py new file mode 100644 index 0000000000..789f1ab6de --- /dev/null +++ b/tensorflow/python/data/kernel_tests/list_files_test.py @@ -0,0 +1,214 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.list_files()`.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from os import path +import shutil +import tempfile + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test +from tensorflow.python.util import compat + + +@test_util.run_all_in_graph_and_eager_modes +class ListFilesTest(test_base.DatasetTestBase): + + def setUp(self): + self.tmp_dir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.tmp_dir, ignore_errors=True) + + def _touchTempFiles(self, filenames): + for filename in filenames: + open(path.join(self.tmp_dir, filename), 'a').close() + + # Note: eager mode fails in assertion error same as initializer in graph mode. + @test_util.run_deprecated_v1 + def testSkipEagerEmptyDirectory(self): + dataset = dataset_ops.Dataset.list_files(path.join(self.tmp_dir, '*')) + self.assertDatasetProduces(dataset, expected_output=[]) + + def testSimpleDirectory(self): + filenames = ['a', 'b', 'c'] + self._touchTempFiles(filenames) + + dataset = dataset_ops.Dataset.list_files(path.join(self.tmp_dir, '*')) + self.assertDatasetProduces( + dataset, + expected_output=[ + compat.as_bytes(path.join(self.tmp_dir, filename)) + for filename in filenames + ], + assert_items_equal=True) + + def testSimpleDirectoryNotShuffled(self): + filenames = ['b', 'c', 'a'] + self._touchTempFiles(filenames) + + dataset = dataset_ops.Dataset.list_files( + path.join(self.tmp_dir, '*'), shuffle=False) + self.assertDatasetProduces( + dataset, + expected_output=[ + compat.as_bytes(path.join(self.tmp_dir, filename)) + for filename in sorted(filenames) + ]) + + def testFixedSeedResultsInRepeatableOrder(self): + filenames = ['a', 'b', 'c'] + self._touchTempFiles(filenames) + + dataset = dataset_ops.Dataset.list_files( + path.join(self.tmp_dir, '*'), shuffle=True, seed=37) + + full_filenames = [compat.as_bytes(path.join(self.tmp_dir, filename)) + for filename in filenames] + + all_produced_filenames = [] + for _ in range(3): + produced_filenames = [] + next_element = self.getNext(dataset, requires_initialization=True) + try: + while True: + produced_filenames.append(self.evaluate(next_element())) + except errors.OutOfRangeError: + pass + all_produced_filenames.append(produced_filenames) + + # Each run should produce the same set of filenames, which may be + # different from the order of `full_filenames`. + self.assertItemsEqual(full_filenames, all_produced_filenames[0]) + # However, the different runs should produce filenames in the same order + # as each other. + self.assertEqual(all_produced_filenames[0], all_produced_filenames[1]) + self.assertEqual(all_produced_filenames[0], all_produced_filenames[2]) + + # TODO(b/117581999): eager mode assertion fail wrapped, debug. + def tesSkipEagerEmptyDirectoryInitializer(self): + dataset = dataset_ops.Dataset.list_files(path.join(self.tmp_dir, '*')) + self.assertDatasetProduces( + dataset, + expected_error=(errors.InvalidArgumentError, + 'No files matched pattern'), + requires_initialization=True) + + def testSimpleDirectoryInitializer(self): + filenames = ['a', 'b', 'c'] + self._touchTempFiles(filenames) + + dataset = dataset_ops.Dataset.list_files(path.join(self.tmp_dir, '*')) + self.assertDatasetProduces( + dataset, + expected_output=[ + compat.as_bytes(path.join(self.tmp_dir, filename)) + for filename in filenames + ], + assert_items_equal=True) + + def testFileSuffixes(self): + filenames = ['a.txt', 'b.py', 'c.py', 'd.pyc'] + self._touchTempFiles(filenames) + + dataset = dataset_ops.Dataset.list_files(path.join(self.tmp_dir, '*.py')) + self.assertDatasetProduces( + dataset, + expected_output=[ + compat.as_bytes(path.join(self.tmp_dir, filename)) + for filename in filenames[1:-1] + ], + assert_items_equal=True) + + def testFileMiddles(self): + filenames = ['a.txt', 'b.py', 'c.pyc'] + self._touchTempFiles(filenames) + + dataset = dataset_ops.Dataset.list_files(path.join(self.tmp_dir, '*.py*')) + self.assertDatasetProduces( + dataset, + expected_output=[ + compat.as_bytes(path.join(self.tmp_dir, filename)) + for filename in filenames[1:] + ], + assert_items_equal=True) + + def testNoShuffle(self): + filenames = ['a', 'b', 'c'] + self._touchTempFiles(filenames) + + # Repeat the list twice and ensure that the order is the same each time. + # NOTE(mrry): This depends on an implementation detail of `list_files()`, + # which is that the list of files is captured when the iterator is + # initialized. Otherwise, or if e.g. the iterator were initialized more than + # once, it's possible that the non-determinism of `tf.matching_files()` + # would cause this test to fail. However, it serves as a useful confirmation + # that the `shuffle=False` argument is working as intended. + # TODO(b/73959787): Provide some ordering guarantees so that this test is + # more meaningful. + dataset = dataset_ops.Dataset.list_files( + path.join(self.tmp_dir, '*'), shuffle=False).repeat(2) + next_element = self.getNext(dataset) + + full_filenames = [] + produced_filenames = [] + for filename in filenames * 2: + full_filenames.append(compat.as_bytes(path.join(self.tmp_dir, filename))) + produced_filenames.append(compat.as_bytes(self.evaluate(next_element()))) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(next_element()) + self.assertItemsEqual(full_filenames, produced_filenames) + self.assertEqual(produced_filenames[:len(filenames)], + produced_filenames[len(filenames):]) + + def testMultiplePatternsAsList(self): + filenames = ['a.txt', 'b.py', 'c.py', 'd.pyc'] + self._touchTempFiles(filenames) + + patterns = [path.join(self.tmp_dir, pat) for pat in ['*.py', '*.txt']] + dataset = dataset_ops.Dataset.list_files(patterns) + self.assertDatasetProduces( + dataset, + expected_output=[ + compat.as_bytes(path.join(self.tmp_dir, filename)) + for filename in filenames[:-1] + ], + assert_items_equal=True) + + def testMultiplePatternsAsTensor(self): + filenames = ['a.txt', 'b.py', 'c.py', 'd.pyc'] + self._touchTempFiles(filenames) + + dataset = dataset_ops.Dataset.list_files( + [path.join(self.tmp_dir, pat) for pat in ['*.py', '*.txt']]) + self.assertDatasetProduces( + dataset, + expected_output=[ + compat.as_bytes(path.join(self.tmp_dir, filename)) + for filename in filenames[:-1] + ], + assert_items_equal=True) + + + +if __name__ == '__main__': + test.main() diff --git a/tensorflow/python/data/kernel_tests/map_dataset_op_test.py b/tensorflow/python/data/kernel_tests/map_test.py similarity index 80% rename from tensorflow/python/data/kernel_tests/map_dataset_op_test.py rename to tensorflow/python/data/kernel_tests/map_test.py index 81ef7d16be..fdce791447 100644 --- a/tensorflow/python/data/kernel_tests/map_dataset_op_test.py +++ b/tensorflow/python/data/kernel_tests/map_test.py @@ -19,7 +19,6 @@ from __future__ import print_function from collections import namedtuple import threading -import time import warnings from absl.testing import parameterized @@ -27,7 +26,6 @@ import numpy as np from tensorflow.core.framework import attr_value_pb2 from tensorflow.core.protobuf import config_pb2 -from tensorflow.python.client import session from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.framework import constant_op @@ -79,7 +77,7 @@ def _make_coordinated_sloppy_dataset(num_elements, num_parallel_calls): options.experimental_deterministic = False dataset = dataset_ops.Dataset.range(num_elements).map( map_fn, num_parallel_calls).with_options(options) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) next_element = iterator.get_next() return next_element, coordination_events @@ -102,7 +100,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): count = array_ops.placeholder(dtypes.int64, shape=[]) dataset = self._buildMapDataset(components, count) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() @@ -168,7 +166,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = self._buildParallelMapDataset( components, count, num_parallel_calls, output_buffer_size) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() @@ -237,7 +235,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = self._buildParallelMapDataset(components, 1000, 100, 100) # NOTE(mrry): Also test that the prefetching thread is cancelled correctly. dataset = dataset.prefetch(100) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() @@ -252,7 +250,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = (dataset_ops.Dataset.from_tensor_slices(components) .map(lambda x: array_ops.check_numerics(x, "message"), num_parallel_calls=2)) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() @@ -267,7 +265,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = (dataset_ops.Dataset.from_tensor_slices(components) .map(lambda x: array_ops.check_numerics(x, "message"), num_parallel_calls=2)) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() @@ -288,7 +286,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): dataset = (dataset_ops.Dataset.from_tensor_slices(components) .map(lambda x: array_ops.check_numerics(x, "message")) .prefetch(2)) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) init_op = iterator.initializer get_next = iterator.get_next() @@ -314,8 +312,8 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): return dataset_ops.Dataset.range(10).map(_map_fn) def _build_graph(): - captured_iterator = dataset_ops.Dataset.range( - 10).make_initializable_iterator() + captured_iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10)) ds = _build_ds(captured_iterator) iterator = ds.make_initializable_iterator() init_op = iterator.initializer @@ -345,10 +343,9 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): input_sentences = dataset_ops.Dataset.from_tensor_slices( ["brain brain tank salad surgery", "surgery brain"]) - iterator = (input_sentences - .map(lambda x: string_ops.string_split([x]).values) - .map(table.lookup) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + input_sentences + .map(lambda x: string_ops.string_split([x]).values).map(table.lookup)) init_op = iterator.initializer get_next = iterator.get_next() @@ -365,8 +362,9 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): queue = data_flow_ops.FIFOQueue(200, dtypes.int64, shapes=[]) enqueue_op = queue.enqueue_many(elements) close_op = queue.close() - iterator = (dataset_ops.Dataset.from_tensors(0).repeat(-1) - .map(lambda _: queue.dequeue()).make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_tensors(0).repeat(-1) + .map(lambda _: queue.dequeue())) init_op = iterator.initializer get_next = iterator.get_next() @@ -389,9 +387,9 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): enqueue_op = queue.enqueue_many(elements) close_op = queue.close() - iterator = (dataset_ops.Dataset.from_tensors(0).repeat(-1) - .map(lambda _: (queue.dequeue(), queue_2.dequeue())) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_tensors(0).repeat(-1) + .map(lambda _: (queue.dequeue(), queue_2.dequeue()))) init_op = iterator.initializer get_next = iterator.get_next() @@ -408,9 +406,9 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): def testCaptureVariable(self): counter_var = variable_scope.get_variable( "counter", (), dtypes.int32, use_resource=True) - iterator = (dataset_ops.Dataset.from_tensors(0).repeat(10) - .map(lambda _: counter_var.assign_add(1)) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_tensors(0).repeat(10) + .map(lambda _: counter_var.assign_add(1))) init_op = iterator.initializer get_next = iterator.get_next() @@ -428,9 +426,9 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): def testCaptureUninitializedVariableError(self): counter_var = variable_scope.get_variable( "counter", (), dtypes.int32, use_resource=True) - iterator = (dataset_ops.Dataset.from_tensors(0).repeat(10) - .map(lambda _: counter_var.assign_add(1)) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_tensors(0).repeat(10) + .map(lambda _: counter_var.assign_add(1))) init_op = iterator.initializer get_next = iterator.get_next() @@ -440,9 +438,9 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): sess.run(get_next) def testSeededStatefulOperatorIsProperlyStateful(self): - iterator = (dataset_ops.Dataset.from_tensors(0).repeat(10) - .map(lambda _: random_ops.random_uniform((), seed=11)).batch(2) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_tensors(0).repeat(10) + .map(lambda _: random_ops.random_uniform((), seed=11)).batch(2)) init_op = iterator.initializer get_next = iterator.get_next() @@ -464,11 +462,11 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): self.assertAllClose(random_values, random_values_2) def testStatefulMapKeepsStateAcrossIterators(self): - iterator = (dataset_ops.Dataset.from_tensors(0).repeat(10) - .map(lambda _: random_ops.random_uniform((), seed=11)) - .repeat(1000) - .batch(10) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.from_tensors(0).repeat(10) + .map(lambda _: random_ops.random_uniform((), seed=11)) + .repeat(1000) + .batch(10)) init_op = iterator.initializer get_next = iterator.get_next() @@ -493,9 +491,8 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): counter_var.assign_add(1) return x - iterator = (dataset_ops.Dataset.range(10) - .map(increment_fn) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10).map(increment_fn)) init_op = iterator.initializer get_next = iterator.get_next() @@ -511,17 +508,17 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): self.assertEqual(10, sess.run(counter_var)) def testMapDict(self): - iterator = (dataset_ops.Dataset.range(10) - .map(lambda x: {"foo": x * 2, "bar": x ** 2}) - .map(lambda d: d["foo"] + d["bar"]) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10) + .map(lambda x: {"foo": x * 2, "bar": x ** 2}) + .map(lambda d: d["foo"] + d["bar"])) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: sess.run(init_op) for i in range(10): - self.assertEqual(i * 2 + i ** 2, sess.run(get_next)) + self.assertEqual(i * 2 + i**2, sess.run(get_next)) with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) @@ -546,8 +543,9 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): dataset_tuple = dataset_tuple.map(preprocess_tuple) dataset_namedtuple = dataset_namedtuple.map(preprocess_namedtuple) - next_tuple = dataset_tuple.make_one_shot_iterator().get_next() - next_namedtuple = dataset_namedtuple.make_one_shot_iterator().get_next() + next_tuple = dataset_ops.make_one_shot_iterator(dataset_tuple).get_next() + next_namedtuple = dataset_ops.make_one_shot_iterator( + dataset_namedtuple).get_next() # make sure both datasets contain the same data with self.cached_session() as sess: @@ -561,16 +559,15 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): def testUseStepContainerInMap(self): row = np.arange(6) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensors(row) - .map(lambda elems: functional_ops.map_fn(lambda x: x * x, elems)) - .make_initializable_iterator()) + .map(lambda elems: functional_ops.map_fn(lambda x: x * x, elems))) init_op = iterator.initializer get_next = iterator.get_next() with self.cached_session() as sess: sess.run(init_op) - self.assertAllEqual(row ** 2, sess.run(get_next)) + self.assertAllEqual(row**2, sess.run(get_next)) with self.assertRaises(errors.OutOfRangeError): sess.run(get_next) @@ -600,9 +597,9 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): pred_fn_pairs, default=multiply, exclusive=True) def build_dataset(row, num): - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensor_slices(row).map( - lambda x: control_map_fn(x, num)).make_initializable_iterator()) + lambda x: control_map_fn(x, num))) init_op = iterator.initializer get_next = iterator.get_next() return init_op, get_next @@ -639,11 +636,10 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): def build_dataset(row, num): # pylint: disable=g-long-lambda - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensors(row).map( - lambda elems: functional_ops.map_fn(lambda x: - control_map_fn(x, num), elems) - ).make_initializable_iterator()) + lambda elems: functional_ops.map_fn( + lambda x: control_map_fn(x, num), elems))) init_op = iterator.initializer get_next = iterator.get_next() return init_op, get_next @@ -687,11 +683,10 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): row = np.arange(6) num = 2 # pylint: disable=g-long-lambda - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.from_tensors(row).map( - lambda elems: functional_ops.map_fn(lambda x: - control_map_fn(x, num), elems) - ).make_initializable_iterator()) + lambda elems: functional_ops.map_fn( + lambda x: control_map_fn(x, num), elems))) # pylint: enable=g-long-lambda init_op = iterator.initializer get_next = iterator.get_next() @@ -721,11 +716,10 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): return script_ops.py_func(_map_py_func, [x], x.dtype) buffer_size_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.range(100) .map(_map_fn) - .prefetch(buffer_size_placeholder) - .make_initializable_iterator()) + .prefetch(buffer_size_placeholder)) init_op = iterator.initializer get_next = iterator.get_next() @@ -761,9 +755,9 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): sess.run(get_next) def testReturnList(self): - iterator = (dataset_ops.Dataset.range(10) - .map(lambda x: [x, constant_op.constant(37.0)]) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10) + .map(lambda x: [x, constant_op.constant(37.0)])) init_op = iterator.initializer get_next = iterator.get_next() @@ -782,9 +776,8 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): return script_ops.py_func( _map_py_func, [x_tensor], [dtypes.int64, dtypes.float64]) - iterator = (dataset_ops.Dataset.range(10) - .map(_map_fn) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10).map(_map_fn)) init_op = iterator.initializer get_next = iterator.get_next() @@ -803,9 +796,8 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): values=(i * np.array([1])), dense_shape=np.array([1, 1])) - iterator = (dataset_ops.Dataset.range(10) - .map(_sparse) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10).map(_sparse)) init_op = iterator.initializer get_next = iterator.get_next() @@ -830,9 +822,8 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): self.assertTrue(sparse_tensor.is_sparse(i)) return sparse_ops.sparse_concat(0, [i, i]) - iterator = ( - dataset_ops.Dataset.range(10).map(_sparse).map(_check) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10).map(_sparse).map(_check)) init_op = iterator.initializer get_next = iterator.get_next() @@ -852,11 +843,10 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): else: return i - iterator = ( + iterator = dataset_ops.make_initializable_iterator( dataset_ops.Dataset.range(105) .map(lambda x: script_ops.py_func(raising_py_func, [x], dtypes.int64), - num_parallel_calls=2) - .make_initializable_iterator()) + num_parallel_calls=2)) init_op = iterator.initializer get_next = iterator.get_next() @@ -868,9 +858,8 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): sess.run(get_next) def testConstantOutput(self): - iterator = ( - dataset_ops.Dataset.range(10).map(lambda x: [x, "hello", 10]) - .make_initializable_iterator()) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10).map(lambda x: [x, "hello", 10])) init_op = iterator.initializer get_next = iterator.get_next() @@ -901,12 +890,14 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): break self.assertTrue(found_warning) - def testNestedDatasetError(self): - dataset = dataset_ops.Dataset.from_tensors([1.0, 2.0, 3.0]) - with self.assertRaisesRegexp( - NotImplementedError, r"The Dataset.map\(\) transformation does not " - "currently support nested datasets as outputs."): - _ = dataset.map(dataset_ops.Dataset.from_tensor_slices) + def testNestedDatasetMap(self): + # TODO(b/110122868): When iterators can yield a `tf.data.Dataset`, remove + # the `get_single_element()` call. + dataset = dataset_ops.Dataset.from_tensors([1.0, 2.0, 3.0]).map( + dataset_ops.Dataset.from_tensor_slices).map( + lambda ds: ds.batch(3)).flat_map(lambda x: x) + + self.assertDatasetProduces(dataset, [[1.0, 2.0, 3.0]]) def testReturnValueError(self): dataset = dataset_ops.Dataset.from_tensors([1.0, 2.0, 3.0]) @@ -939,7 +930,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): return const_tensor dataset = dataset.map(broken_function) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) with self.cached_session() as sess: with self.assertRaisesRegexp(errors.InvalidArgumentError, "BrokenConst"): @@ -966,7 +957,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): return tids dataset = make_dataset_fn(dataset, _map_fn) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() with self.cached_session() as sess: @@ -987,7 +978,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): def testShortCircuit(self, structure, map_fn, num_parallel_calls): dataset = self.structuredDataset(structure).repeat().map( map_fn, num_parallel_calls=num_parallel_calls) - get_next = dataset.make_one_shot_iterator().get_next() + get_next = dataset_ops.make_one_shot_iterator(dataset).get_next() with self.cached_session() as sess: if isinstance(structure, tuple): @@ -1004,7 +995,7 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): captured_t = array_ops.placeholder(dtypes.int64, shape=[]) dataset = self.structuredDataset(None).repeat().map( lambda x: captured_t, num_parallel_calls=num_parallel_calls) - iterator = dataset.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(dataset) get_next = iterator.get_next() with self.cached_session() as sess: @@ -1055,108 +1046,5 @@ class MapDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): sess.run(get_next) -class MapDatasetBenchmark(test.Benchmark): - - def benchmarkChainOfMaps(self): - chain_lengths = [0, 1, 2, 5, 10, 20, 50] - for chain_length in chain_lengths: - for mode in ["general", "single-threaded", "short-circuit"]: - if mode == "general": - map_fn = lambda x: x + 1 - use_inter_op_parallelism = True - print_label = "" - benchmark_label = "" - if mode == "single-threaded": - map_fn = lambda x: x + 1 - use_inter_op_parallelism = False - print_label = " (single threaded mode)" - benchmark_label = "_single_threaded" - if mode == "short-circuit": - map_fn = lambda x: x - use_inter_op_parallelism = True # should not have any significance - print_label = " (short circuit mode)" - benchmark_label = "_short_circuit" - - with ops.Graph().as_default(): - dataset = dataset_ops.Dataset.from_tensors(0).repeat(None) - for _ in range(chain_length): - dataset = dataset_ops.MapDataset( - dataset, - map_fn, - use_inter_op_parallelism=use_inter_op_parallelism) - iterator = dataset.make_one_shot_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - for _ in range(5): - sess.run(next_element.op) - deltas = [] - for _ in range(100): - start = time.time() - for _ in range(100): - sess.run(next_element.op) - end = time.time() - deltas.append(end - start) - - median_wall_time = np.median(deltas) / 100 - print("Map dataset chain length%s: %d Median wall time: %f" % - (print_label, chain_length, median_wall_time)) - self.report_benchmark( - iters=1000, - wall_time=median_wall_time, - name="benchmark_map_dataset_chain_latency_%d%s" % - (chain_length, benchmark_label)) - - def benchmarkMapFanOut(self): - fan_outs = [1, 2, 5, 10, 20, 50, 100] - for fan_out in fan_outs: - for mode in ["general", "single-threaded", "short-circuit"]: - if mode == "general": - map_fn = lambda *xs: [x + 1 for x in xs] - use_inter_op_parallelism = True - print_label = "" - benchmark_label = "" - if mode == "single-threaded": - map_fn = lambda *xs: [x + 1 for x in xs] - use_inter_op_parallelism = False - print_label = " (single threaded mode)" - benchmark_label = "_single_threaded" - if mode == "short-circuit": - map_fn = lambda *xs: xs - use_inter_op_parallelism = True # should not have any significance - print_label = " (short circuit mode)" - benchmark_label = "_short_circuit" - - with ops.Graph().as_default(): - dataset = dataset_ops.Dataset.from_tensors( - tuple(0 for _ in range(fan_out))).repeat(None) - dataset = dataset_ops.MapDataset( - dataset, - map_fn, - use_inter_op_parallelism=use_inter_op_parallelism) - iterator = dataset.make_one_shot_iterator() - next_element = iterator.get_next() - - with session.Session() as sess: - for _ in range(5): - sess.run(next_element[0].op) - deltas = [] - for _ in range(100): - start = time.time() - for _ in range(100): - sess.run(next_element[0].op) - end = time.time() - deltas.append(end - start) - - median_wall_time = np.median(deltas) / 100 - print("Map dataset fan out%s: %d Median wall time: %f" % - (print_label, fan_out, median_wall_time)) - self.report_benchmark( - iters=1000, - wall_time=median_wall_time, - name="benchmark_map_dataset_fan_out_%d%s" % (fan_out, - benchmark_label)) - - if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/kernel_tests/multi_device_iterator_test.py b/tensorflow/python/data/kernel_tests/multi_device_iterator_test.py index 42ee1e2186..622ebb55de 100644 --- a/tensorflow/python/data/kernel_tests/multi_device_iterator_test.py +++ b/tensorflow/python/data/kernel_tests/multi_device_iterator_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""MultiDeviceIterator tests.""" +"""Tests for `tf.data.MultiDeviceIterator`.""" from __future__ import absolute_import from __future__ import division @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.core.protobuf import config_pb2 from tensorflow.python.data.experimental.ops import optimization +from tensorflow.python.data.experimental.ops.optimization_options import OptimizationOptions from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import multi_device_iterator_ops @@ -31,6 +32,7 @@ from tensorflow.python.ops import array_ops from tensorflow.python.platform import test +# TODO(b/117581999): Add eager coverage. class MultiDeviceIteratorTest(test_base.DatasetTestBase): def testNoGetNext(self): @@ -40,7 +42,7 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 3}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) def testBasic(self): dataset = dataset_ops.Dataset.range(10) @@ -50,13 +52,13 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 3}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): - self.assertEqual(i, sess.run(elem_on_1)) - self.assertEqual(i + 1, sess.run(elem_on_2)) + self.assertEqual(i, self.evaluate(elem_on_1)) + self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): - sess.run(elem_on_1) - sess.run(elem_on_2) + self.evaluate(elem_on_1) + self.evaluate(elem_on_2) def testOneOnSameDevice(self): with ops.device("/cpu:0"): @@ -67,13 +69,13 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 2}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): - self.assertEqual(i, sess.run(elem_on_1)) - self.assertEqual(i + 1, sess.run(elem_on_2)) + self.assertEqual(i, self.evaluate(elem_on_1)) + self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): - sess.run(elem_on_1) - sess.run(elem_on_2) + self.evaluate(elem_on_1) + self.evaluate(elem_on_2) def testRepeatDevices(self): with ops.device("/cpu:0"): @@ -85,17 +87,17 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 3}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 20, 4): - self.assertEqual(i, sess.run(elem_on_1)) - self.assertEqual(i + 1, sess.run(elem_on_2)) - self.assertEqual(i + 2, sess.run(elem_on_3)) - self.assertEqual(i + 3, sess.run(elem_on_4)) + self.assertEqual(i, self.evaluate(elem_on_1)) + self.assertEqual(i + 1, self.evaluate(elem_on_2)) + self.assertEqual(i + 2, self.evaluate(elem_on_3)) + self.assertEqual(i + 3, self.evaluate(elem_on_4)) with self.assertRaises(errors.OutOfRangeError): - sess.run(elem_on_1) - sess.run(elem_on_2) - sess.run(elem_on_3) - sess.run(elem_on_4) + self.evaluate(elem_on_1) + self.evaluate(elem_on_2) + self.evaluate(elem_on_3) + self.evaluate(elem_on_4) def testNotFullyDivisible(self): dataset = dataset_ops.Dataset.range(9) @@ -105,14 +107,14 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 3}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 8, 2): - self.assertEqual(i, sess.run(elem_on_1)) - self.assertEqual(i + 1, sess.run(elem_on_2)) - self.assertEqual(8, sess.run(elem_on_1)) + self.assertEqual(i, self.evaluate(elem_on_1)) + self.assertEqual(i + 1, self.evaluate(elem_on_2)) + self.assertEqual(8, self.evaluate(elem_on_1)) with self.assertRaises(errors.OutOfRangeError): - sess.run(elem_on_1) - sess.run(elem_on_2) + self.evaluate(elem_on_1) + self.evaluate(elem_on_2) def testGetNextAsOptional(self): dataset = dataset_ops.Dataset.range(9) @@ -126,7 +128,7 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 3}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 8, 2): elem_on_1_has_value, elem_on_1_value = sess.run( [elem_on_1_has_value_t, elem_on_1_t]) @@ -140,12 +142,12 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): [elem_on_1_has_value_t, elem_on_1_t]) self.assertTrue(elem_on_1_has_value) self.assertEqual(8, elem_on_1_value) - self.assertFalse(sess.run(elem_on_1_has_value_t)) - self.assertFalse(sess.run(elem_on_2_has_value_t)) + self.assertFalse(self.evaluate(elem_on_1_has_value_t)) + self.assertFalse(self.evaluate(elem_on_2_has_value_t)) with self.assertRaises(errors.InvalidArgumentError): - sess.run(elem_on_1_t) + self.evaluate(elem_on_1_t) with self.assertRaises(errors.InvalidArgumentError): - sess.run(elem_on_2_t) + self.evaluate(elem_on_2_t) def testUneven(self): dataset = dataset_ops.Dataset.range(10) @@ -155,14 +157,14 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 3}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): - self.assertEqual(i, sess.run(elem_on_1)) + self.assertEqual(i, self.evaluate(elem_on_1)) for i in range(0, 10, 2): - self.assertEqual(i + 1, sess.run(elem_on_2)) + self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): - sess.run(elem_on_1) - sess.run(elem_on_2) + self.evaluate(elem_on_1) + self.evaluate(elem_on_2) def testMultipleInitializations(self): with ops.device("/cpu:0"): @@ -179,7 +181,8 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): with self.test_session(config=config) as sess: for i in range(1000): sess.run(init_op, feed_dict={epoch: i}) - self.assertEqual([(i, 0), (i, 1)], sess.run([elem_on_1, elem_on_2])) + self.assertEqual([(i, 0), (i, 1)], self.evaluate([elem_on_1, + elem_on_2])) def testBasicGpu(self): if not test_util.is_gpu_available(): @@ -192,13 +195,13 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 2, "GPU": 1}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): - self.assertEqual(i, sess.run(elem_on_1)) - self.assertEqual(i + 1, sess.run(elem_on_2)) + self.assertEqual(i, self.evaluate(elem_on_1)) + self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): - sess.run(elem_on_1) - sess.run(elem_on_2) + self.evaluate(elem_on_1) + self.evaluate(elem_on_2) def testUnevenGpu(self): if not test_util.is_gpu_available(): @@ -211,14 +214,14 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 2, "GPU": 1}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): - self.assertEqual(i, sess.run(elem_on_1)) + self.assertEqual(i, self.evaluate(elem_on_1)) for i in range(0, 10, 2): - self.assertEqual(i + 1, sess.run(elem_on_2)) + self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): - sess.run(elem_on_1) - sess.run(elem_on_2) + self.evaluate(elem_on_1) + self.evaluate(elem_on_2) def testGetNextAsOptionalGpu(self): if not test_util.is_gpu_available(): @@ -235,7 +238,7 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 2, "GPU": 1}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 8, 2): elem_on_1_has_value, elem_on_1_value = sess.run( [elem_on_1_has_value_t, elem_on_1_t]) @@ -249,12 +252,12 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): [elem_on_1_has_value_t, elem_on_1_t]) self.assertTrue(elem_on_1_has_value) self.assertEqual(8, elem_on_1_value) - self.assertFalse(sess.run(elem_on_1_has_value_t)) - self.assertFalse(sess.run(elem_on_2_has_value_t)) + self.assertFalse(self.evaluate(elem_on_1_has_value_t)) + self.assertFalse(self.evaluate(elem_on_2_has_value_t)) with self.assertRaises(errors.InvalidArgumentError): - sess.run(elem_on_1_t) + self.evaluate(elem_on_1_t) with self.assertRaises(errors.InvalidArgumentError): - sess.run(elem_on_2_t) + self.evaluate(elem_on_2_t) def testOptimization(self): dataset = dataset_ops.Dataset.range(10) @@ -263,7 +266,8 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): dataset = dataset.cache() options = dataset_ops.Options() - options.experimental_noop_elimination = True + options.experimental_optimization = OptimizationOptions() + options.experimental_optimization.noop_elimination = True dataset = dataset.with_options(options) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( @@ -272,13 +276,13 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): config = config_pb2.ConfigProto(device_count={"CPU": 3}) with self.test_session(config=config) as sess: - sess.run(multi_device_iterator.initializer) + self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): - self.assertEqual(i, sess.run(elem_on_1)) - self.assertEqual(i + 1, sess.run(elem_on_2)) + self.assertEqual(i, self.evaluate(elem_on_1)) + self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): - sess.run(elem_on_1) - sess.run(elem_on_2) + self.evaluate(elem_on_1) + self.evaluate(elem_on_2) if __name__ == "__main__": diff --git a/tensorflow/python/data/kernel_tests/optional_ops_test.py b/tensorflow/python/data/kernel_tests/optional_test.py similarity index 64% rename from tensorflow/python/data/kernel_tests/optional_ops_test.py rename to tensorflow/python/data/kernel_tests/optional_test.py index 604e3ad88e..c2c62e9423 100644 --- a/tensorflow/python/data/kernel_tests/optional_ops_test.py +++ b/tensorflow/python/data/kernel_tests/optional_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the Optional data type wrapper.""" +"""Tests for `tf.data.Optional`.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -33,18 +33,18 @@ from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops from tensorflow.python.platform import test +@test_util.run_all_in_graph_and_eager_modes class OptionalTest(test_base.DatasetTestBase, parameterized.TestCase): - @test_util.run_in_graph_and_eager_modes def testFromValue(self): opt = optional_ops.Optional.from_value(constant_op.constant(37.0)) self.assertTrue(self.evaluate(opt.has_value())) self.assertEqual(37.0, self.evaluate(opt.get_value())) - @test_util.run_in_graph_and_eager_modes def testFromStructuredValue(self): opt = optional_ops.Optional.from_value({ "a": constant_op.constant(37.0), @@ -56,7 +56,6 @@ class OptionalTest(test_base.DatasetTestBase, parameterized.TestCase): "b": ([b"Foo"], b"Bar") }, self.evaluate(opt.get_value())) - @test_util.run_in_graph_and_eager_modes def testFromSparseTensor(self): st_0 = sparse_tensor.SparseTensorValue( indices=np.array([[0]]), @@ -75,7 +74,7 @@ class OptionalTest(test_base.DatasetTestBase, parameterized.TestCase): self.assertAllEqual(expected.dense_shape, self.evaluate(actual.dense_shape)) - @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testFromNone(self): value_structure = structure.TensorStructure(dtypes.float32, []) opt = optional_ops.Optional.none_from_structure(value_structure) @@ -90,7 +89,90 @@ class OptionalTest(test_base.DatasetTestBase, parameterized.TestCase): with self.assertRaises(errors.InvalidArgumentError): self.evaluate(opt.get_value()) - @test_util.run_in_graph_and_eager_modes + def testAddN(self): + devices = ["/cpu:0"] + if test_util.is_gpu_available(): + devices.append("/gpu:0") + for device in devices: + with ops.device(device): + # With value + opt1 = optional_ops.Optional.from_value((1.0, 2.0)) + opt2 = optional_ops.Optional.from_value((3.0, 4.0)) + + add_tensor = math_ops.add_n([opt1._variant_tensor, + opt2._variant_tensor]) + add_opt = optional_ops._OptionalImpl(add_tensor, opt1.value_structure) + self.assertAllEqual(self.evaluate(add_opt.get_value()), (4.0, 6.0)) + + # Without value + opt_none1 = optional_ops.Optional.none_from_structure( + opt1.value_structure) + opt_none2 = optional_ops.Optional.none_from_structure( + opt2.value_structure) + add_tensor = math_ops.add_n([opt_none1._variant_tensor, + opt_none2._variant_tensor]) + add_opt = optional_ops._OptionalImpl(add_tensor, + opt_none1.value_structure) + self.assertFalse(self.evaluate(add_opt.has_value())) + + def testNestedAddN(self): + devices = ["/cpu:0"] + if test_util.is_gpu_available(): + devices.append("/gpu:0") + for device in devices: + with ops.device(device): + opt1 = optional_ops.Optional.from_value([1, 2.0]) + opt2 = optional_ops.Optional.from_value([3, 4.0]) + opt3 = optional_ops.Optional.from_value((5.0, opt1._variant_tensor)) + opt4 = optional_ops.Optional.from_value((6.0, opt2._variant_tensor)) + + add_tensor = math_ops.add_n([opt3._variant_tensor, + opt4._variant_tensor]) + add_opt = optional_ops._OptionalImpl(add_tensor, opt3.value_structure) + self.assertEqual(self.evaluate(add_opt.get_value()[0]), 11.0) + + inner_add_opt = optional_ops._OptionalImpl(add_opt.get_value()[1], + opt1.value_structure) + self.assertAllEqual(inner_add_opt.get_value(), [4, 6.0]) + + def testZerosLike(self): + devices = ["/cpu:0"] + if test_util.is_gpu_available(): + devices.append("/gpu:0") + for device in devices: + with ops.device(device): + # With value + opt = optional_ops.Optional.from_value((1.0, 2.0)) + zeros_tensor = array_ops.zeros_like(opt._variant_tensor) + zeros_opt = optional_ops._OptionalImpl(zeros_tensor, + opt.value_structure) + self.assertAllEqual(self.evaluate(zeros_opt.get_value()), + (0.0, 0.0)) + + # Without value + opt_none = optional_ops.Optional.none_from_structure( + opt.value_structure) + zeros_tensor = array_ops.zeros_like(opt_none._variant_tensor) + zeros_opt = optional_ops._OptionalImpl(zeros_tensor, + opt_none.value_structure) + self.assertFalse(self.evaluate(zeros_opt.has_value())) + + def testNestedZerosLike(self): + devices = ["/cpu:0"] + if test_util.is_gpu_available(): + devices.append("/gpu:0") + for device in devices: + with ops.device(device): + opt1 = optional_ops.Optional.from_value(1.0) + opt2 = optional_ops.Optional.from_value(opt1._variant_tensor) + + zeros_tensor = array_ops.zeros_like(opt2._variant_tensor) + zeros_opt = optional_ops._OptionalImpl(zeros_tensor, + opt2.value_structure) + inner_zeros_opt = optional_ops._OptionalImpl(zeros_opt.get_value(), + opt1.value_structure) + self.assertEqual(self.evaluate(inner_zeros_opt.get_value()), 0.0) + def testCopyToGPU(self): if not test_util.is_gpu_available(): self.skipTest("No GPU available") @@ -120,6 +202,41 @@ class OptionalTest(test_base.DatasetTestBase, parameterized.TestCase): self.evaluate(gpu_optional_with_value_values)) self.assertFalse(self.evaluate(gpu_optional_none_has_value)) + def testNestedCopyToGPU(self): + if not test_util.is_gpu_available(): + self.skipTest("No GPU available") + + with ops.device("/cpu:0"): + optional_with_value = optional_ops.Optional.from_value( + (constant_op.constant(37.0), constant_op.constant("Foo"), + constant_op.constant(42))) + optional_none = optional_ops.Optional.none_from_structure( + structure.TensorStructure(dtypes.float32, [])) + nested_optional = optional_ops.Optional.from_value( + (optional_with_value._variant_tensor, optional_none._variant_tensor, + 1.0)) + + with ops.device("/gpu:0"): + gpu_nested_optional = optional_ops._OptionalImpl( + array_ops.identity(nested_optional._variant_tensor), + nested_optional.value_structure) + + gpu_nested_optional_has_value = gpu_nested_optional.has_value() + gpu_nested_optional_values = gpu_nested_optional.get_value() + + self.assertTrue(self.evaluate(gpu_nested_optional_has_value)) + + inner_with_value = optional_ops._OptionalImpl( + gpu_nested_optional_values[0], optional_with_value.value_structure) + + inner_none = optional_ops._OptionalImpl( + gpu_nested_optional_values[1], optional_none.value_structure) + + self.assertEqual((37.0, b"Foo", 42), + self.evaluate(inner_with_value.get_value())) + self.assertFalse(self.evaluate(inner_none.has_value())) + self.assertEqual(1.0, self.evaluate(gpu_nested_optional_values[2])) + def _assertElementValueEqual(self, expected, actual): if isinstance(expected, dict): self.assertItemsEqual(list(expected.keys()), list(actual.keys())) @@ -151,7 +268,9 @@ class OptionalTest(test_base.DatasetTestBase, parameterized.TestCase): optional_ops.OptionalStructure( structure.TensorStructure(dtypes.float32, []))), ) - def testOptionalStructure(self, tf_value_fn, expected_value_structure): + @test_util.run_deprecated_v1 + def testSkipEagerOptionalStructure(self, tf_value_fn, + expected_value_structure): tf_value = tf_value_fn() opt = optional_ops.Optional.from_value(tf_value) @@ -205,7 +324,9 @@ class OptionalTest(test_base.DatasetTestBase, parameterized.TestCase): indices=[[0, 1], [1, 0]], values=[37.0, 42.0], dense_shape=[2, 2])}, False), ) - def testIteratorGetNextAsOptional(self, np_value, tf_value_fn, works_on_gpu): + @test_util.run_deprecated_v1 + def testSkipEagerIteratorGetNextAsOptional(self, np_value, tf_value_fn, + works_on_gpu): if not works_on_gpu and test.is_gpu_available(): self.skipTest("Test case not yet supported on GPU.") ds = dataset_ops.Dataset.from_tensors(np_value).repeat(3) diff --git a/tensorflow/python/data/kernel_tests/padded_batch_test.py b/tensorflow/python/data/kernel_tests/padded_batch_test.py new file mode 100644 index 0000000000..dcfb2f507b --- /dev/null +++ b/tensorflow/python/data/kernel_tests/padded_batch_test.py @@ -0,0 +1,243 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.padded_batch()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from absl.testing import parameterized +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors +from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import string_ops +from tensorflow.python.platform import test +from tensorflow.python.util import compat + + +def _random_seq_lens(count): + return np.random.randint(20, size=(count,)).astype(np.int32) + + +@test_util.run_all_in_graph_and_eager_modes +class PaddedBatchTest(test_base.DatasetTestBase, parameterized.TestCase): + + @parameterized.named_parameters( + ('default_padding', _random_seq_lens(32), 4, [-1], False), + ('constant_padding', _random_seq_lens(32), 4, [25], False), + ('uneven_with_remainder', _random_seq_lens(34), 4, [-1], False), + ('uneven_without_remainder', _random_seq_lens(34), 4, [-1], True), + ) + def testPaddedBatchDataset(self, seq_lens, batch_size, padded_shapes, + drop_remainder): + """Tests the padded batch dataset logic for various input configurations. + + Args: + seq_lens: the input sequence lengths + batch_size: the batch size + padded_shapes: the padded shapes to use + drop_remainder: whether a smaller batch size should be produced if batch + size does not divide number of inputs evenly + """ + + dataset = dataset_ops.Dataset.from_tensor_slices(seq_lens).map( + lambda x: array_ops.fill([x], x)).padded_batch( + batch_size=batch_size, + drop_remainder=drop_remainder, + padded_shapes=padded_shapes) + + num_full_batches = len(seq_lens) // batch_size + get_next = self.getNext(dataset) + for i in range(num_full_batches): + result = self.evaluate(get_next()) + padded_len = padded_shapes[0] + if padded_len is None or padded_len == -1: + padded_len = np.max(result) if result.size > 0 else 0 + self.assertEqual((batch_size, padded_len), result.shape) + for j in range(batch_size): + seq_len = seq_lens[(i * batch_size) + j] + self.assertAllEqual(result[j, :seq_len], [seq_len] * seq_len) + self.assertAllEqual(result[j, seq_len:], [0] * (padded_len - seq_len)) + + if not drop_remainder and len(seq_lens) % batch_size > 0: + result = self.evaluate(get_next()) + padded_len = np.max(result) if result.size > 0 else 0 + self.assertEqual((len(seq_lens) % batch_size, padded_len), result.shape) + for j in range(len(seq_lens) % batch_size): + seq_len = seq_lens[num_full_batches * batch_size + j] + self.assertAllEqual(result[j, :seq_len], [seq_len] * seq_len) + self.assertAllEqual(result[j, seq_len:], [0] * (padded_len - seq_len)) + + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + @test_util.run_deprecated_v1 + def testPaddedBatchShortPadding(self): + dataset = ( + dataset_ops.Dataset.from_tensor_slices( + [6, 5, 5, 5, 5]).map(lambda x: array_ops.fill([x], x)).padded_batch( + batch_size=4, padded_shapes=[5])) + self.assertDatasetProduces( + dataset, expected_error=(errors.DataLossError, '')) + + def testPaddedBatchEmptyTensors(self): + dataset = ( + dataset_ops.Dataset.from_tensor_slices( + [0, 0, 0, 0]).map(lambda x: array_ops.fill([x], x)).padded_batch( + batch_size=4, padded_shapes=[-1])) + self.assertDatasetProduces(dataset, expected_output=[[[], [], [], []]]) + + def testPaddedBatchDatasetNonDefaultPadding(self): + + def fill_tuple(x): + filled = array_ops.fill([x], x) + return (filled, string_ops.as_string(filled)) + + random_seq_lens = np.random.randint(20, size=(32,)).astype(np.int32) + dataset = ( + dataset_ops.Dataset.from_tensor_slices(random_seq_lens).map(fill_tuple) + .padded_batch( + 4, padded_shapes=([-1], [-1]), padding_values=(-1, ''))) + + get_next = self.getNext(dataset) + for i in range(8): + result = self.evaluate(get_next()) + padded_len = np.max(result[0]) + self.assertEqual((4, padded_len), result[0].shape) + self.assertEqual((4, padded_len), result[1].shape) + for j in range(4): + seq_len = random_seq_lens[(i * 4) + j] + self.assertAllEqual(result[0][j, :seq_len], [seq_len] * seq_len) + self.assertAllEqual(result[0][j, seq_len:], + [-1] * (padded_len - seq_len)) + self.assertAllEqual(result[1][j, :seq_len], + [compat.as_bytes(str(seq_len))] * seq_len) + self.assertAllEqual(result[1][j, seq_len:], + [b''] * (padded_len - seq_len)) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + def testPaddedBatchDatasetUnicode(self): + # See GitHub issue 16149 + def generator(): + data = [[u'Простой', u'тест', u'юникода'], + [u'никогда', u'не', u'бывает', u'простым']] + + for seq in data: + yield seq, [0, 1, 2, 3] + + dataset = dataset_ops.Dataset.from_generator( + generator, (dtypes.string, dtypes.int32), + (tensor_shape.TensorShape([None]), tensor_shape.TensorShape([None]))) + padded_dataset = dataset.padded_batch( + 2, padded_shapes=([None], [None]), padding_values=('', 0)) + next_element = self.getNext(padded_dataset) + self.evaluate(next_element()) + + @test_util.run_deprecated_v1 + def testSkipEagerPaddedBatchDatasetShapeSpecifications(self): + int_placeholder = array_ops.placeholder(dtypes.int32) + float_placeholder = array_ops.placeholder(dtypes.float32) + string_placeholder = array_ops.placeholder(dtypes.string) + input_dataset = dataset_ops.Dataset.from_tensors( + (int_placeholder, float_placeholder, string_placeholder)) + + # Test different ways of specifying the `padded_shapes` argument. + dynamic_padding_from_tensor_shapes = input_dataset.padded_batch( + 32, + padded_shapes=(tensor_shape.TensorShape([None]), + tensor_shape.TensorShape([None, None]), + tensor_shape.TensorShape([37]))) + dynamic_padding_from_lists = input_dataset.padded_batch( + 32, padded_shapes=([None], [None, None], [37])) + dynamic_padding_from_lists_with_minus_one = input_dataset.padded_batch( + 32, padded_shapes=([-1], [-1, -1], [37])) + dynamic_padding_from_tensors = input_dataset.padded_batch( + 32, + padded_shapes=(constant_op.constant([-1], dtype=dtypes.int64), + constant_op.constant([-1, -1], dtype=dtypes.int64), + constant_op.constant([37], dtype=dtypes.int64))) + + for dataset in [ + dynamic_padding_from_tensor_shapes, dynamic_padding_from_lists, + dynamic_padding_from_lists_with_minus_one, dynamic_padding_from_tensors + ]: + self.assertEqual([None, None], dataset.output_shapes[0].as_list()) + self.assertEqual([None, None, None], dataset.output_shapes[1].as_list()) + self.assertEqual([None, 37], dataset.output_shapes[2].as_list()) + + def testPaddedBatchSparseError(self): + + def _map_fn(i): + return sparse_tensor.SparseTensorValue( + indices=[[0, 0]], values=(i * [1]), dense_shape=[1, 1]), i + + with self.assertRaises(TypeError): + _ = dataset_ops.Dataset.range(10).map(_map_fn).padded_batch(10) + + def testPaddedBatchShapeError(self): + with self.assertRaisesRegexp( + ValueError, r'The padded shape \(1,\) is not compatible with the ' + r'corresponding input component shape \(\).'): + _ = dataset_ops.Dataset.range(10).padded_batch(5, padded_shapes=[1]) + + with self.assertRaisesRegexp( + ValueError, r'The padded shape \(1,\) is not compatible with the ' + r'corresponding input component shape \(3,\).'): + _ = dataset_ops.Dataset.from_tensors([1, 2, 3]).padded_batch( + 5, padded_shapes=[1]) + + with self.assertRaisesRegexp( + ValueError, r'Padded shape .* must be a 1-D tensor ' + r'of tf.int64 values, but its shape was \(2, 2\).'): + _ = dataset_ops.Dataset.from_tensors([1, 2, 3]).padded_batch( + 5, padded_shapes=[[1, 1], [1, 1]]) + + with self.assertRaisesRegexp( + TypeError, r'Padded shape .* must be a 1-D tensor ' + r'of tf.int64 values, but its element type was float32.'): + _ = dataset_ops.Dataset.from_tensors([1, 2, 3]).padded_batch( + 5, padded_shapes=constant_op.constant([1., 2., 3.])) + + with self.assertRaisesRegexp( + ValueError, r'The padded shape \(1,\) is not compatible with the ' + r'corresponding input component shape \(\).'): + shape_as_tensor = constant_op.constant([1], dtype=dtypes.int64) + _ = dataset_ops.Dataset.range(10).padded_batch( + 5, padded_shapes=shape_as_tensor) + + @test_util.run_deprecated_v1 + def testSkipEagerPaddedBatchShapeError(self): + with self.assertRaisesRegexp( + ValueError, + r'The padded shape \((\?|None), (\?|None)\) is not compatible with the ' + r'corresponding input component shape \(\).'): + shape_as_tensor = array_ops.placeholder(dtypes.int64, shape=[2]) + _ = dataset_ops.Dataset.range(10).padded_batch( + 5, padded_shapes=shape_as_tensor) + + +if __name__ == '__main__': + test.main() diff --git a/tensorflow/python/data/kernel_tests/prefetch_dataset_op_test.py b/tensorflow/python/data/kernel_tests/prefetch_test.py similarity index 52% rename from tensorflow/python/data/kernel_tests/prefetch_dataset_op_test.py rename to tensorflow/python/data/kernel_tests/prefetch_test.py index 76e2697b29..a143ba0ac6 100644 --- a/tensorflow/python/data/kernel_tests/prefetch_dataset_op_test.py +++ b/tensorflow/python/data/kernel_tests/prefetch_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Test PrefetchDataset.""" +"""Tests for `tf.data.Dataset.prefetch()`.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -21,40 +21,24 @@ from absl.testing import parameterized from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors -from tensorflow.python.ops import array_ops +from tensorflow.python.framework import test_util from tensorflow.python.platform import test -class PrefetchDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): +@test_util.run_all_in_graph_and_eager_modes +class PrefetchTest(test_base.DatasetTestBase, parameterized.TestCase): @parameterized.parameters((-1), (0), (5)) def testBufferSize(self, buffer_size): - buffer_size_t = array_ops.placeholder(dtypes.int64, shape=[]) - iterator = dataset_ops.Dataset.range(10).prefetch( - buffer_size=buffer_size_t).make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op, feed_dict={buffer_size_t: buffer_size}) - for m in range(10): - self.assertEqual(m, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) + dataset = dataset_ops.Dataset.range(10).prefetch(buffer_size=buffer_size) + self.assertDatasetProduces(dataset, expected_output=range(10)) @parameterized.parameters((-2), (-42)) def testInvalidBufferSize(self, buffer_size): - buffer_size_t = array_ops.placeholder(dtypes.int64, shape=[]) - iterator = dataset_ops.Dataset.range(10).prefetch( - buffer_size=buffer_size_t).make_initializable_iterator() - init_op = iterator.initializer - - with self.assertRaisesRegexp(errors.InvalidArgumentError, "buffer_size"): - with self.cached_session() as sess: - sess.run(init_op, feed_dict={buffer_size_t: buffer_size}) - + dataset = dataset_ops.Dataset.range(10).prefetch(buffer_size=buffer_size) + self.assertDatasetProduces( + dataset, expected_error=(errors.InvalidArgumentError, "buffer_size")) if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/kernel_tests/range_test.py b/tensorflow/python/data/kernel_tests/range_test.py new file mode 100644 index 0000000000..3f5d25e7f3 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/range_test.py @@ -0,0 +1,72 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.range()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class RangeTest(test_base.DatasetTestBase): + + def testStop(self): + dataset = dataset_ops.Dataset.range(5) + self.assertDatasetProduces(dataset, expected_output=range(5)) + + def testStartStop(self): + start, stop = 2, 5 + dataset = dataset_ops.Dataset.range(start, stop) + self.assertDatasetProduces(dataset, expected_output=range(2, 5)) + + def testStartStopStep(self): + start, stop, step = 2, 10, 2 + dataset = dataset_ops.Dataset.range(start, stop, step) + self.assertDatasetProduces(dataset, expected_output=range(2, 10, 2)) + + def testZeroStep(self): + start, stop, step = 2, 10, 0 + dataset = dataset_ops.Dataset.range(start, stop, step) + self.assertDatasetProduces( + dataset, expected_error=(errors.InvalidArgumentError, "")) + + def testNegativeStep(self): + start, stop, step = 2, 10, -1 + dataset = dataset_ops.Dataset.range(start, stop, step) + self.assertDatasetProduces(dataset, expected_output=range(2, 10, -1)) + + def testStopLessThanStart(self): + start, stop = 10, 2 + dataset = dataset_ops.Dataset.range(start, stop) + self.assertDatasetProduces(dataset, expected_output=range(10, 2)) + + def testStopLessThanStartWithPositiveStep(self): + start, stop, step = 10, 2, 2 + dataset = dataset_ops.Dataset.range(start, stop, step) + self.assertDatasetProduces(dataset, expected_output=range(10, 2, 2)) + + def testStopLessThanStartWithNegativeStep(self): + start, stop, step = 10, 2, -1 + dataset = dataset_ops.Dataset.range(start, stop, step) + self.assertDatasetProduces(dataset, expected_output=range(10, 2, -1)) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/reader_dataset_ops_test.py b/tensorflow/python/data/kernel_tests/reader_dataset_ops_test.py deleted file mode 100644 index 4fef4f30bf..0000000000 --- a/tensorflow/python/data/kernel_tests/reader_dataset_ops_test.py +++ /dev/null @@ -1,846 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import gzip -import os -import zlib - -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.data.ops import iterator_ops -from tensorflow.python.data.ops import readers -from tensorflow.python.eager import context -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import ops -from tensorflow.python.framework import tensor_shape -from tensorflow.python.lib.io import python_io -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import gen_dataset_ops -from tensorflow.python.ops import io_ops -from tensorflow.python.ops import parsing_ops -from tensorflow.python.platform import test -from tensorflow.python.util import compat - - -try: - import psutil # pylint: disable=g-import-not-at-top - psutil_import_succeeded = True -except ImportError: - psutil_import_succeeded = False - - -class TextLineDatasetTest(test_base.DatasetTestBase): - - def _lineText(self, f, l): - return compat.as_bytes("%d: %d" % (f, l)) - - def _createFiles(self, - num_files, - num_lines, - crlf=False, - compression_type=None): - filenames = [] - for i in range(num_files): - fn = os.path.join(self.get_temp_dir(), "text_line.%d.txt" % i) - filenames.append(fn) - contents = [] - for j in range(num_lines): - contents.append(self._lineText(i, j)) - # Always include a newline after the record unless it is - # at the end of the file, in which case we include it - if j + 1 != num_lines or i == 0: - contents.append(b"\r\n" if crlf else b"\n") - contents = b"".join(contents) - - if not compression_type: - with open(fn, "wb") as f: - f.write(contents) - elif compression_type == "GZIP": - with gzip.GzipFile(fn, "wb") as f: - f.write(contents) - elif compression_type == "ZLIB": - contents = zlib.compress(contents) - with open(fn, "wb") as f: - f.write(contents) - else: - raise ValueError("Unsupported compression_type", compression_type) - - return filenames - - def _testTextLineDataset(self, compression_type=None): - test_filenames = self._createFiles( - 2, 5, crlf=True, compression_type=compression_type) - filenames = array_ops.placeholder(dtypes.string, shape=[None]) - num_epochs = array_ops.placeholder(dtypes.int64, shape=[]) - batch_size = array_ops.placeholder(dtypes.int64, shape=[]) - - repeat_dataset = readers.TextLineDataset( - filenames, compression_type=compression_type).repeat(num_epochs) - batch_dataset = repeat_dataset.batch(batch_size) - - iterator = iterator_ops.Iterator.from_structure(batch_dataset.output_types) - init_op = iterator.make_initializer(repeat_dataset) - init_batch_op = iterator.make_initializer(batch_dataset) - get_next = iterator.get_next() - - with self.cached_session() as sess: - # Basic test: read from file 0. - sess.run( - init_op, feed_dict={filenames: [test_filenames[0]], - num_epochs: 1}) - for i in range(5): - self.assertEqual(self._lineText(0, i), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Basic test: read from file 1. - sess.run( - init_op, feed_dict={filenames: [test_filenames[1]], - num_epochs: 1}) - for i in range(5): - self.assertEqual(self._lineText(1, i), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Basic test: read from both files. - sess.run(init_op, feed_dict={filenames: test_filenames, num_epochs: 1}) - for j in range(2): - for i in range(5): - self.assertEqual(self._lineText(j, i), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Test repeated iteration through both files. - sess.run(init_op, feed_dict={filenames: test_filenames, num_epochs: 10}) - for _ in range(10): - for j in range(2): - for i in range(5): - self.assertEqual(self._lineText(j, i), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Test batched and repeated iteration through both files. - sess.run( - init_batch_op, - feed_dict={filenames: test_filenames, - num_epochs: 10, - batch_size: 5}) - for _ in range(10): - self.assertAllEqual([self._lineText(0, i) for i in range(5)], - sess.run(get_next)) - self.assertAllEqual([self._lineText(1, i) for i in range(5)], - sess.run(get_next)) - - def testTextLineDatasetNoCompression(self): - self._testTextLineDataset() - - def testTextLineDatasetGzipCompression(self): - self._testTextLineDataset(compression_type="GZIP") - - def testTextLineDatasetZlibCompression(self): - self._testTextLineDataset(compression_type="ZLIB") - - def testTextLineDatasetBuffering(self): - test_filenames = self._createFiles(2, 5, crlf=True) - - repeat_dataset = readers.TextLineDataset(test_filenames, buffer_size=10) - iterator = repeat_dataset.make_one_shot_iterator() - - with self.cached_session() as sess: - for j in range(2): - for i in range(5): - self.assertEqual(self._lineText(j, i), sess.run(iterator.get_next())) - with self.assertRaises(errors.OutOfRangeError): - sess.run(iterator.get_next()) - - def testIteratorResourceCleanup(self): - filename = os.path.join(self.get_temp_dir(), "text.txt") - with open(filename, "wt") as f: - for i in range(3): - f.write("%d\n" % (i,)) - with context.eager_mode(): - first_iterator = iter(readers.TextLineDataset(filename)) - self.assertEqual(b"0", next(first_iterator).numpy()) - second_iterator = iter(readers.TextLineDataset(filename)) - self.assertEqual(b"0", next(second_iterator).numpy()) - # Eager kernel caching is based on op attributes, which includes the - # Dataset's output shape. Create a different kernel to test that they - # don't create resources with the same names. - different_kernel_iterator = iter( - readers.TextLineDataset(filename).repeat().batch(16)) - self.assertEqual([16], next(different_kernel_iterator).shape) - # Remove our references to the Python Iterator objects, which (assuming no - # reference cycles) is enough to trigger DestroyResourceOp and close the - # partially-read files. - del first_iterator - del second_iterator - del different_kernel_iterator - if not psutil_import_succeeded: - self.skipTest( - "psutil is required to check that we've closed our files.") - open_files = psutil.Process().open_files() - self.assertNotIn(filename, [open_file.path for open_file in open_files]) - - -class FixedLengthRecordReaderTest(test_base.DatasetTestBase): - - def setUp(self): - super(FixedLengthRecordReaderTest, self).setUp() - self._num_files = 2 - self._num_records = 7 - self._header_bytes = 5 - self._record_bytes = 3 - self._footer_bytes = 2 - - def _record(self, f, r): - return compat.as_bytes(str(f * 2 + r) * self._record_bytes) - - def _createFiles(self, compression_type=None): - filenames = [] - for i in range(self._num_files): - fn = os.path.join(self.get_temp_dir(), "fixed_length_record.%d.txt" % i) - filenames.append(fn) - - contents = [] - contents.append(b"H" * self._header_bytes) - for j in range(self._num_records): - contents.append(self._record(i, j)) - contents.append(b"F" * self._footer_bytes) - contents = b"".join(contents) - - if not compression_type: - with open(fn, "wb") as f: - f.write(contents) - elif compression_type == "GZIP": - with gzip.GzipFile(fn, "wb") as f: - f.write(contents) - elif compression_type == "ZLIB": - contents = zlib.compress(contents) - with open(fn, "wb") as f: - f.write(contents) - else: - raise ValueError("Unsupported compression_type", compression_type) - - return filenames - - def _testFixedLengthRecordDataset(self, compression_type=None): - test_filenames = self._createFiles(compression_type=compression_type) - filenames = array_ops.placeholder(dtypes.string, shape=[None]) - num_epochs = array_ops.placeholder(dtypes.int64, shape=[]) - batch_size = array_ops.placeholder(dtypes.int64, shape=[]) - - repeat_dataset = ( - readers.FixedLengthRecordDataset( - filenames, - self._record_bytes, - self._header_bytes, - self._footer_bytes, - compression_type=compression_type).repeat(num_epochs)) - batch_dataset = repeat_dataset.batch(batch_size) - - iterator = iterator_ops.Iterator.from_structure(batch_dataset.output_types) - init_op = iterator.make_initializer(repeat_dataset) - init_batch_op = iterator.make_initializer(batch_dataset) - get_next = iterator.get_next() - - with self.cached_session() as sess: - # Basic test: read from file 0. - sess.run( - init_op, feed_dict={filenames: [test_filenames[0]], - num_epochs: 1}) - for i in range(self._num_records): - self.assertEqual(self._record(0, i), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Basic test: read from file 1. - sess.run( - init_op, feed_dict={filenames: [test_filenames[1]], - num_epochs: 1}) - for i in range(self._num_records): - self.assertEqual(self._record(1, i), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Basic test: read from both files. - sess.run(init_op, feed_dict={filenames: test_filenames, num_epochs: 1}) - for j in range(self._num_files): - for i in range(self._num_records): - self.assertEqual(self._record(j, i), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Test repeated iteration through both files. - sess.run(init_op, feed_dict={filenames: test_filenames, num_epochs: 10}) - for _ in range(10): - for j in range(self._num_files): - for i in range(self._num_records): - self.assertEqual(self._record(j, i), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Test batched and repeated iteration through both files. - sess.run( - init_batch_op, - feed_dict={ - filenames: test_filenames, - num_epochs: 10, - batch_size: self._num_records - }) - for _ in range(10): - for j in range(self._num_files): - self.assertAllEqual( - [self._record(j, i) for i in range(self._num_records)], - sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testFixedLengthRecordDatasetNoCompression(self): - self._testFixedLengthRecordDataset() - - def testFixedLengthRecordDatasetGzipCompression(self): - self._testFixedLengthRecordDataset(compression_type="GZIP") - - def testFixedLengthRecordDatasetZlibCompression(self): - self._testFixedLengthRecordDataset(compression_type="ZLIB") - - def testFixedLengthRecordDatasetBuffering(self): - test_filenames = self._createFiles() - dataset = readers.FixedLengthRecordDataset( - test_filenames, - self._record_bytes, - self._header_bytes, - self._footer_bytes, - buffer_size=10) - iterator = dataset.make_one_shot_iterator() - - with self.cached_session() as sess: - for j in range(self._num_files): - for i in range(self._num_records): - self.assertEqual(self._record(j, i), sess.run(iterator.get_next())) - with self.assertRaises(errors.OutOfRangeError): - sess.run(iterator.get_next()) - - def testFixedLengthRecordDatasetWrongSize(self): - test_filenames = self._createFiles() - dataset = readers.FixedLengthRecordDataset( - test_filenames, - self._record_bytes + 1, # Incorrect record length. - self._header_bytes, - self._footer_bytes, - buffer_size=10) - iterator = dataset.make_one_shot_iterator() - - with self.cached_session() as sess: - with self.assertRaisesRegexp( - errors.InvalidArgumentError, - r"Excluding the header \(5 bytes\) and footer \(2 bytes\), input " - r"file \".*fixed_length_record.0.txt\" has body length 21 bytes, " - r"which is not an exact multiple of the record length \(4 bytes\)."): - sess.run(iterator.get_next()) - - def _iterator_checkpoint_path(self): - return os.path.join(self.get_temp_dir(), "iterator") - - def _save_op(self, iterator_resource): - iterator_state_variant = gen_dataset_ops.serialize_iterator( - iterator_resource) - save_op = io_ops.write_file( - self._iterator_checkpoint_path(), - parsing_ops.serialize_tensor(iterator_state_variant)) - return save_op - - def _restore_op(self, iterator_resource): - iterator_state_variant = parsing_ops.parse_tensor( - io_ops.read_file(self._iterator_checkpoint_path()), dtypes.variant) - restore_op = gen_dataset_ops.deserialize_iterator(iterator_resource, - iterator_state_variant) - return restore_op - - def _build_iterator_graph(self, num_epochs): - filenames = self._createFiles() - dataset = (readers.FixedLengthRecordDataset( - filenames, self._record_bytes, self._header_bytes, self._footer_bytes) - .repeat(num_epochs)) - iterator = dataset.make_initializable_iterator() - init_op = iterator.initializer - get_next_op = iterator.get_next() - save_op = self._save_op(iterator._iterator_resource) - restore_op = self._restore_op(iterator._iterator_resource) - return init_op, get_next_op, save_op, restore_op - - def _restore_iterator(self): - output_types = dtypes.string - output_shapes = tensor_shape.scalar() - iterator = iterator_ops.Iterator.from_structure(output_types, output_shapes) - get_next = iterator.get_next() - restore_op = self._restore_op(iterator._iterator_resource) - return restore_op, get_next - - def testSaveRestore(self): - num_epochs = 10 - epoch_break = 5 - file_break = self._num_files // 2 - record_break = self._num_records // 2 - - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(init_op) - # Note: There is no checkpoint saved currently so a NotFoundError is - # raised. - with self.assertRaises(errors.NotFoundError): - sess.run(restore_op) - for epoch in range(num_epochs): - for f in range(self._num_files): - for r in range(self._num_records): - if (epoch == epoch_break and f == file_break and - r == record_break): - sess.run(save_op) - break - self.assertEqual(self._record(f, r), sess.run(get_next_op)) - else: - continue - break - else: - continue - break - else: - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(restore_op) - for epoch in range(num_epochs): - for f in range(self._num_files): - for r in range(self._num_records): - if (epoch < epoch_break or - (epoch == epoch_break and f < file_break) or - (epoch == epoch_break and f == file_break and - r < record_break)): - continue - self.assertEqual(self._record(f, r), sess.run(get_next_op)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - def testInitThenRestore(self): - # Note: Calling init_op before restore_op is redundant. This test just makes - # sure we do not fail if restore is called on an already initialized - # iterator resource. - num_epochs = 10 - epoch_break = 5 - file_break = self._num_files // 2 - record_break = self._num_records // 2 - - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(init_op) - # Note: There is no checkpoint saved currently so a NotFoundError is - # raised. - with self.assertRaises(errors.NotFoundError): - sess.run(restore_op) - for epoch in range(num_epochs): - for f in range(self._num_files): - for r in range(self._num_records): - if (epoch == epoch_break and f == file_break and - r == record_break): - sess.run(save_op) - break - self.assertEqual(self._record(f, r), sess.run(get_next_op)) - else: - continue - break - else: - continue - break - else: - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(init_op) - sess.run(restore_op) - for epoch in range(num_epochs): - for f in range(self._num_files): - for r in range(self._num_records): - if (epoch < epoch_break or - (epoch == epoch_break and f < file_break) or - (epoch == epoch_break and f == file_break and - r < record_break)): - continue - self.assertEqual(self._record(f, r), sess.run(get_next_op)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - def testRestoreInModifiedGraph(self): - num_epochs = 10 - num_epochs_1 = 20 - epoch_break = 5 - file_break = self._num_files // 2 - record_break = self._num_records // 2 - - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(init_op) - # Note: There is no checkpoint saved currently so a NotFoundError is - # raised. - with self.assertRaises(errors.NotFoundError): - sess.run(restore_op) - for epoch in range(num_epochs): - for f in range(self._num_files): - for r in range(self._num_records): - if (epoch == epoch_break and f == file_break and - r == record_break): - sess.run(save_op) - break - self.assertEqual(self._record(f, r), sess.run(get_next_op)) - else: - continue - break - else: - continue - break - else: - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs_1) - with self.session(graph=g) as sess: - sess.run(restore_op) - for epoch in range(num_epochs): - for f in range(self._num_files): - for r in range(self._num_records): - if (epoch < epoch_break or - (epoch == epoch_break and f < file_break) or - (epoch == epoch_break and f == file_break and - r < record_break)): - continue - self.assertEqual(self._record(f, r), sess.run(get_next_op)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - def testRestoreWithoutBuildingDatasetGraph(self): - num_epochs = 10 - epoch_break = 5 - file_break = self._num_files // 2 - record_break = self._num_records // 2 - - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(init_op) - # Note: There is no checkpoint saved currently so a NotFoundError is - # raised. - with self.assertRaises(errors.NotFoundError): - sess.run(restore_op) - for epoch in range(num_epochs): - for f in range(self._num_files): - for r in range(self._num_records): - if (epoch == epoch_break and f == file_break and - r == record_break): - sess.run(save_op) - break - self.assertEqual(self._record(f, r), sess.run(get_next_op)) - else: - continue - break - else: - continue - break - else: - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - with ops.Graph().as_default() as g: - restore_op, get_next_op = self._restore_iterator() - with self.session(graph=g) as sess: - sess.run(restore_op) - for epoch in range(num_epochs): - for f in range(self._num_files): - for r in range(self._num_records): - if (epoch < epoch_break or - (epoch == epoch_break and f < file_break) or - (epoch == epoch_break and f == file_break and - r < record_break)): - continue - self.assertEqual(self._record(f, r), sess.run(get_next_op)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - def testRestoreUnusedIterator(self): - num_epochs = 10 - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(init_op) - # Note: There is no checkpoint saved currently so a NotFoundError is - # raised. - with self.assertRaises(errors.NotFoundError): - sess.run(restore_op) - # Save unused iterator. - sess.run(save_op) - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(restore_op) - for _ in range(num_epochs * self._num_files * self._num_records): - sess.run(get_next_op) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - def testRestoreExhaustedIterator(self): - num_epochs = 10 - - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(init_op) - # Note: There is no checkpoint saved currently so a NotFoundError is - # raised. - with self.assertRaises(errors.NotFoundError): - sess.run(restore_op) - for _ in range(num_epochs): - for f in range(self._num_files): - for r in range(self._num_records): - self.assertEqual(self._record(f, r), sess.run(get_next_op)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - sess.run(save_op) - - with ops.Graph().as_default() as g: - init_op, get_next_op, save_op, restore_op = self._build_iterator_graph( - num_epochs=num_epochs) - with self.session(graph=g) as sess: - sess.run(restore_op) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next_op) - - -class TFRecordDatasetTest(test_base.DatasetTestBase): - - def setUp(self): - super(TFRecordDatasetTest, self).setUp() - self._num_files = 2 - self._num_records = 7 - - self.test_filenames = self._createFiles() - - self.filenames = array_ops.placeholder(dtypes.string, shape=[None]) - self.num_epochs = array_ops.placeholder_with_default( - constant_op.constant(1, dtypes.int64), shape=[]) - self.compression_type = array_ops.placeholder_with_default("", shape=[]) - self.batch_size = array_ops.placeholder(dtypes.int64, shape=[]) - - repeat_dataset = readers.TFRecordDataset(self.filenames, - self.compression_type).repeat( - self.num_epochs) - batch_dataset = repeat_dataset.batch(self.batch_size) - - iterator = iterator_ops.Iterator.from_structure(batch_dataset.output_types) - self.init_op = iterator.make_initializer(repeat_dataset) - self.init_batch_op = iterator.make_initializer(batch_dataset) - self.get_next = iterator.get_next() - - def _record(self, f, r): - return compat.as_bytes("Record %d of file %d" % (r, f)) - - def _createFiles(self): - filenames = [] - for i in range(self._num_files): - fn = os.path.join(self.get_temp_dir(), "tf_record.%d.txt" % i) - filenames.append(fn) - writer = python_io.TFRecordWriter(fn) - for j in range(self._num_records): - writer.write(self._record(i, j)) - writer.close() - return filenames - - def testReadOneEpoch(self): - with self.cached_session() as sess: - # Basic test: read from file 0. - sess.run( - self.init_op, - feed_dict={ - self.filenames: [self.test_filenames[0]], - self.num_epochs: 1 - }) - for i in range(self._num_records): - self.assertAllEqual(self._record(0, i), sess.run(self.get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(self.get_next) - - # Basic test: read from file 1. - sess.run( - self.init_op, - feed_dict={ - self.filenames: [self.test_filenames[1]], - self.num_epochs: 1 - }) - for i in range(self._num_records): - self.assertAllEqual(self._record(1, i), sess.run(self.get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(self.get_next) - - # Basic test: read from both files. - sess.run( - self.init_op, - feed_dict={self.filenames: self.test_filenames, - self.num_epochs: 1}) - for j in range(self._num_files): - for i in range(self._num_records): - self.assertAllEqual(self._record(j, i), sess.run(self.get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(self.get_next) - - def testReadTenEpochs(self): - with self.cached_session() as sess: - sess.run( - self.init_op, - feed_dict={self.filenames: self.test_filenames, - self.num_epochs: 10}) - for _ in range(10): - for j in range(self._num_files): - for i in range(self._num_records): - self.assertAllEqual(self._record(j, i), sess.run(self.get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(self.get_next) - - def testReadTenEpochsOfBatches(self): - with self.cached_session() as sess: - sess.run( - self.init_batch_op, - feed_dict={ - self.filenames: self.test_filenames, - self.num_epochs: 10, - self.batch_size: self._num_records - }) - for _ in range(10): - for j in range(self._num_files): - values = sess.run(self.get_next) - self.assertAllEqual( - [self._record(j, i) for i in range(self._num_records)], values) - with self.assertRaises(errors.OutOfRangeError): - sess.run(self.get_next) - - def testReadZlibFiles(self): - zlib_files = [] - for i, fn in enumerate(self.test_filenames): - with open(fn, "rb") as f: - cdata = zlib.compress(f.read()) - - zfn = os.path.join(self.get_temp_dir(), "tfrecord_%s.z" % i) - with open(zfn, "wb") as f: - f.write(cdata) - zlib_files.append(zfn) - - with self.cached_session() as sess: - sess.run( - self.init_op, - feed_dict={self.filenames: zlib_files, - self.compression_type: "ZLIB"}) - for j in range(self._num_files): - for i in range(self._num_records): - self.assertAllEqual(self._record(j, i), sess.run(self.get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(self.get_next) - - def testReadGzipFiles(self): - gzip_files = [] - for i, fn in enumerate(self.test_filenames): - with open(fn, "rb") as f: - gzfn = os.path.join(self.get_temp_dir(), "tfrecord_%s.gz" % i) - with gzip.GzipFile(gzfn, "wb") as gzf: - gzf.write(f.read()) - gzip_files.append(gzfn) - - with self.cached_session() as sess: - sess.run( - self.init_op, - feed_dict={self.filenames: gzip_files, - self.compression_type: "GZIP"}) - for j in range(self._num_files): - for i in range(self._num_records): - self.assertAllEqual(self._record(j, i), sess.run(self.get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(self.get_next) - - def testReadWithBuffer(self): - one_mebibyte = 2**20 - d = readers.TFRecordDataset(self.test_filenames, buffer_size=one_mebibyte) - iterator = d.make_one_shot_iterator() - next_element = iterator.get_next() - with self.cached_session() as sess: - for j in range(self._num_files): - for i in range(self._num_records): - self.assertAllEqual(self._record(j, i), sess.run(next_element)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - def testReadFromDatasetOfFiles(self): - files = dataset_ops.Dataset.from_tensor_slices(self.test_filenames) - d = readers.TFRecordDataset(files) - iterator = d.make_one_shot_iterator() - next_element = iterator.get_next() - with self.cached_session() as sess: - for j in range(self._num_files): - for i in range(self._num_records): - self.assertAllEqual(self._record(j, i), sess.run(next_element)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - def testReadTenEpochsFromDatasetOfFilesInParallel(self): - files = dataset_ops.Dataset.from_tensor_slices( - self.test_filenames).repeat(10) - d = readers.TFRecordDataset(files, num_parallel_reads=4) - iterator = d.make_one_shot_iterator() - next_element = iterator.get_next() - expected = [] - actual = [] - with self.cached_session() as sess: - for _ in range(10): - for j in range(self._num_files): - for i in range(self._num_records): - expected.append(self._record(j, i)) - actual.append(sess.run(next_element)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - self.assertEqual(sorted(expected), sorted(actual)) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/kernel_tests/reduce_dataset_op_test.py b/tensorflow/python/data/kernel_tests/reduce_test.py similarity index 72% rename from tensorflow/python/data/kernel_tests/reduce_dataset_op_test.py rename to tensorflow/python/data/kernel_tests/reduce_test.py index 11e07300b9..14bbc0bf72 100644 --- a/tensorflow/python/data/kernel_tests/reduce_dataset_op_test.py +++ b/tensorflow/python/data/kernel_tests/reduce_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the experimental input pipeline ops.""" +"""Tests for `tf.data.Dataset.reduce()`.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -22,21 +22,24 @@ import numpy as np from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.platform import test -class ReduceDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): +@test_util.run_all_in_graph_and_eager_modes +class ReduceTest(test_base.DatasetTestBase, parameterized.TestCase): def testSum(self): for i in range(10): ds = dataset_ops.Dataset.range(1, i + 1) - result = ds.reduce(np.int64(0), lambda x, y: x + y) - with self.cached_session() as sess: - self.assertEqual(((i + 1) * i) // 2, sess.run(result)) + result = ds.reduce( + constant_op.constant(0, dtype=dtypes.int64), lambda x, y: x + y) + self.assertEqual(((i + 1) * i) // 2, self.evaluate(result)) def testSumTuple(self): @@ -47,9 +50,8 @@ class ReduceDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): for i in range(10): ds = dataset_ops.Dataset.range(1, i + 1) ds = dataset_ops.Dataset.zip((ds, ds)) - result = ds.reduce(np.int64(0), reduce_fn) - with self.cached_session() as sess: - self.assertEqual(((i + 1) * i), sess.run(result)) + result = ds.reduce(constant_op.constant(0, dtype=dtypes.int64), reduce_fn) + self.assertEqual(((i + 1) * i), self.evaluate(result)) def testSumAndCount(self): @@ -59,13 +61,15 @@ class ReduceDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): for i in range(10): ds = dataset_ops.Dataset.range(1, i + 1) - result = ds.reduce((np.int64(0), np.int64(0)), reduce_fn) - with self.cached_session() as sess: - s, c = sess.run(result) - self.assertEqual(((i + 1) * i) // 2, s) - self.assertEqual(i, c) - - def testSquareUsingPlaceholder(self): + result = ds.reduce((constant_op.constant(0, dtype=dtypes.int64), + constant_op.constant(0, dtype=dtypes.int64)), + reduce_fn) + s, c = self.evaluate(result) + self.assertEqual(((i + 1) * i) // 2, s) + self.assertEqual(i, c) + + @test_util.run_deprecated_v1 + def testSkipEagerSquareUsingPlaceholder(self): delta = array_ops.placeholder(dtype=dtypes.int64) def reduce_fn(state, _): @@ -92,8 +96,7 @@ class ReduceDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): for i in range(10): ds = dataset_ops.Dataset.from_tensors(make_sparse_fn(i+1)) result = ds.reduce(make_sparse_fn(0), reduce_fn) - with self.cached_session() as sess: - self.assertSparseValuesEqual(make_sparse_fn(i+1), sess.run(result)) + self.assertSparseValuesEqual(make_sparse_fn(i + 1), self.evaluate(result)) def testNested(self): @@ -115,10 +118,10 @@ class ReduceDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): for i in range(10): ds = dataset_ops.Dataset.range(1, i + 1).map(map_fn) result = ds.reduce(map_fn(0), reduce_fn) - with self.cached_session() as sess: - result = sess.run(result) - self.assertEqual(((i + 1) * i) // 2, result["dense"]) - self.assertSparseValuesEqual(make_sparse_fn(i), result["sparse"]) + result = self.evaluate(result) + self.assertEqual(((i + 1) * i) // 2, result["dense"]) + self.assertSparseValuesEqual(make_sparse_fn(i), result["sparse"]) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/kernel_tests/repeat_test.py b/tensorflow/python/data/kernel_tests/repeat_test.py new file mode 100644 index 0000000000..4ef2fc1bfc --- /dev/null +++ b/tensorflow/python/data/kernel_tests/repeat_test.py @@ -0,0 +1,84 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.repeat()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class RepeatTest(test_base.DatasetTestBase): + + def testRepeatTensorDataset(self): + """Test a dataset that repeats its input multiple times.""" + components = (np.array(1), np.array([1, 2, 3]), np.array(37.0)) + # This placeholder can be fed when dataset-definition subgraph + # runs (i.e. `init_op` below) to configure the number of + # repetitions used in a particular iterator. + + def do_test(count): + dataset = dataset_ops.Dataset.from_tensors(components).repeat(count) + self.assertEqual([c.shape for c in components], + [shape for shape in dataset.output_shapes]) + self.assertDatasetProduces(dataset, [components] * count) + + # Test a finite repetition. + do_test(3) + + # test a different finite repetition. + do_test(7) + + # Test an empty repetition. + do_test(0) + + # Test an infinite repetition. + # NOTE(mrry): There's not a good way to test that the sequence + # actually is infinite. + dataset = dataset_ops.Dataset.from_tensors(components).repeat(-1) + self.assertEqual([c.shape for c in components], + [shape for shape in dataset.output_shapes]) + get_next = self.getNext(dataset) + for _ in range(17): + results = self.evaluate(get_next()) + for component, result_component in zip(components, results): + self.assertAllEqual(component, result_component) + + def testRepeatRepeatTensorDataset(self): + """Test the composition of repeat datasets.""" + components = (np.array(1), np.array([1, 2, 3]), np.array(37.0)) + inner_count, outer_count = 7, 14 + + dataset = dataset_ops.Dataset.from_tensors(components).repeat( + inner_count).repeat(outer_count) + self.assertEqual([c.shape for c in components], + [shape for shape in dataset.output_shapes]) + self.assertDatasetProduces(dataset, + [components] * (inner_count * outer_count)) + + def testRepeatEmptyDataset(self): + """Test that repeating an empty dataset does not hang.""" + dataset = dataset_ops.Dataset.from_tensors(0).repeat(10).skip(10).repeat(-1) + self.assertDatasetProduces(dataset, []) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/sequence_dataset_op_test.py b/tensorflow/python/data/kernel_tests/sequence_dataset_op_test.py deleted file mode 100644 index e86356dee7..0000000000 --- a/tensorflow/python/data/kernel_tests/sequence_dataset_op_test.py +++ /dev/null @@ -1,210 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import numpy as np - -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.ops import array_ops -from tensorflow.python.platform import test - - -class SequenceDatasetTest(test_base.DatasetTestBase): - - def testRepeatTensorDataset(self): - """Test a dataset that repeats its input multiple times.""" - components = (np.array(1), np.array([1, 2, 3]), np.array(37.0)) - # This placeholder can be fed when dataset-definition subgraph - # runs (i.e. `init_op` below) to configure the number of - # repetitions used in a particular iterator. - count_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - - iterator = (dataset_ops.Dataset.from_tensors(components) - .repeat(count_placeholder).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([c.shape for c in components], - [t.shape for t in get_next]) - - with self.cached_session() as sess: - # Test a finite repetition. - sess.run(init_op, feed_dict={count_placeholder: 3}) - for _ in range(3): - results = sess.run(get_next) - for component, result_component in zip(components, results): - self.assertAllEqual(component, result_component) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Test a different finite repetition. - sess.run(init_op, feed_dict={count_placeholder: 7}) - for _ in range(7): - results = sess.run(get_next) - for component, result_component in zip(components, results): - self.assertAllEqual(component, result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Test an empty repetition. - sess.run(init_op, feed_dict={count_placeholder: 0}) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Test an infinite repetition. - # NOTE(mrry): There's not a good way to test that the sequence - # actually is infinite. - sess.run(init_op, feed_dict={count_placeholder: -1}) - for _ in range(17): - results = sess.run(get_next) - for component, result_component in zip(components, results): - self.assertAllEqual(component, result_component) - - def testTakeTensorDataset(self): - components = (np.arange(10),) - count_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - - iterator = (dataset_ops.Dataset.from_tensor_slices(components) - .take(count_placeholder).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([c.shape[1:] for c in components], - [t.shape for t in get_next]) - - with self.cached_session() as sess: - # Take fewer than input size - sess.run(init_op, feed_dict={count_placeholder: 4}) - for i in range(4): - results = sess.run(get_next) - self.assertAllEqual(results, components[0][i:i+1]) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Take more than input size - sess.run(init_op, feed_dict={count_placeholder: 25}) - for i in range(10): - results = sess.run(get_next) - self.assertAllEqual(results, components[0][i:i+1]) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Take all of input - sess.run(init_op, feed_dict={count_placeholder: -1}) - for i in range(10): - results = sess.run(get_next) - self.assertAllEqual(results, components[0][i:i+1]) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Take nothing - sess.run(init_op, feed_dict={count_placeholder: 0}) - - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testSkipTensorDataset(self): - components = (np.arange(10),) - count_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - - iterator = (dataset_ops.Dataset.from_tensor_slices(components) - .skip(count_placeholder).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([c.shape[1:] for c in components], - [t.shape for t in get_next]) - - with self.cached_session() as sess: - # Skip fewer than input size, we should skip - # the first 4 elements and then read the rest. - sess.run(init_op, feed_dict={count_placeholder: 4}) - for i in range(4, 10): - results = sess.run(get_next) - self.assertAllEqual(results, components[0][i:i+1]) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Skip more than input size: get nothing. - sess.run(init_op, feed_dict={count_placeholder: 25}) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Skip exactly input size. - sess.run(init_op, feed_dict={count_placeholder: 10}) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Set -1 for 'count': skip the entire dataset. - sess.run(init_op, feed_dict={count_placeholder: -1}) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Skip nothing - sess.run(init_op, feed_dict={count_placeholder: 0}) - for i in range(0, 10): - results = sess.run(get_next) - self.assertAllEqual(results, components[0][i:i+1]) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testRepeatRepeatTensorDataset(self): - """Test the composition of repeat datasets.""" - components = (np.array(1), np.array([1, 2, 3]), np.array(37.0)) - inner_count = array_ops.placeholder(dtypes.int64, shape=[]) - outer_count = array_ops.placeholder(dtypes.int64, shape=[]) - - iterator = (dataset_ops.Dataset.from_tensors(components).repeat(inner_count) - .repeat(outer_count).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([c.shape for c in components], - [t.shape for t in get_next]) - - with self.cached_session() as sess: - sess.run(init_op, feed_dict={inner_count: 7, outer_count: 14}) - for _ in range(7 * 14): - results = sess.run(get_next) - for component, result_component in zip(components, results): - self.assertAllEqual(component, result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testRepeatEmptyDataset(self): - """Test that repeating an empty dataset does not hang.""" - iterator = (dataset_ops.Dataset.from_tensors(0).repeat(10).skip(10) - .repeat(-1).make_initializable_iterator()) - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/kernel_tests/shard_dataset_op_test.py b/tensorflow/python/data/kernel_tests/shard_test.py similarity index 52% rename from tensorflow/python/data/kernel_tests/shard_dataset_op_test.py rename to tensorflow/python/data/kernel_tests/shard_test.py index b9f3c79da5..928550676d 100644 --- a/tensorflow/python/data/kernel_tests/shard_dataset_op_test.py +++ b/tensorflow/python/data/kernel_tests/shard_test.py @@ -12,50 +12,33 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for the experimental input pipeline ops.""" +"""Tests for `tf.data.Dataset.shard()`.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.platform import test -class ShardDatasetOpTest(test_base.DatasetTestBase): +@test_util.run_all_in_graph_and_eager_modes +class ShardTest(test_base.DatasetTestBase): def testSimpleCase(self): dataset = dataset_ops.Dataset.range(10).shard(5, 2) - iterator = dataset.make_one_shot_iterator() - - with self.cached_session() as sess: - self.assertEqual(2, sess.run(iterator.get_next())) - self.assertEqual(7, sess.run(iterator.get_next())) - with self.assertRaises(errors.OutOfRangeError): - sess.run(iterator.get_next()) + self.assertDatasetProduces(dataset, expected_output=[2, 7]) def testNestedData(self): dataset_a = dataset_ops.Dataset.range(10) dataset_b = dataset_ops.Dataset.range(10, 0, -1) dataset = dataset_ops.Dataset.zip((dataset_a, dataset_b)).shard(5, 2) - iterator = dataset.make_one_shot_iterator() - - with self.cached_session() as sess: - self.assertEqual((2, 8), sess.run(iterator.get_next())) - self.assertEqual((7, 3), sess.run(iterator.get_next())) - with self.assertRaises(errors.OutOfRangeError): - sess.run(iterator.get_next()) + self.assertDatasetProduces(dataset, expected_output=[(2, 8), (7, 3)]) def testOffsetZero(self): dataset = dataset_ops.Dataset.range(10).shard(5, 0) - iterator = dataset.make_one_shot_iterator() - - with self.cached_session() as sess: - self.assertEqual(0, sess.run(iterator.get_next())) - self.assertEqual(5, sess.run(iterator.get_next())) - with self.assertRaises(errors.OutOfRangeError): - sess.run(iterator.get_next()) + self.assertDatasetProduces(dataset, expected_output=[0, 5]) def testOffsetGreaterNumShards(self): with self.assertRaises(ValueError): @@ -75,38 +58,19 @@ class ShardDatasetOpTest(test_base.DatasetTestBase): def testIteratorEndsBeforeFirstElem(self): dataset = dataset_ops.Dataset.range(1).shard(5, 2) - iterator = dataset.make_one_shot_iterator() - - with self.cached_session() as sess: - with self.assertRaises(errors.OutOfRangeError): - sess.run(iterator.get_next()) + self.assertDatasetProduces(dataset, expected_output=[]) def testLargerWorkerPool(self): dataset = dataset_ops.Dataset.range(10).shard(7, 5) - iterator = dataset.make_one_shot_iterator() - with self.cached_session() as sess: - self.assertEqual(5, sess.run(iterator.get_next())) - with self.assertRaises(errors.OutOfRangeError): - sess.run(iterator.get_next()) + self.assertDatasetProduces(dataset, expected_output=[5]) def testIndexEqualsNumShards(self): dataset = dataset_ops.Dataset.range(10).shard(5, 4) - iterator = dataset.make_one_shot_iterator() - with self.cached_session() as sess: - self.assertEqual(4, sess.run(iterator.get_next())) - self.assertEqual(9, sess.run(iterator.get_next())) - with self.assertRaises(errors.OutOfRangeError): - sess.run(iterator.get_next()) + self.assertDatasetProduces(dataset, expected_output=[4, 9]) def testIndexEqualsNumShards2(self): dataset = dataset_ops.Dataset.range(10).shard(4, 3) - iterator = dataset.make_one_shot_iterator() - with self.cached_session() as sess: - self.assertEqual(3, sess.run(iterator.get_next())) - self.assertEqual(7, sess.run(iterator.get_next())) - with self.assertRaises(errors.OutOfRangeError): - sess.run(iterator.get_next()) - + self.assertDatasetProduces(dataset, expected_output=[3, 7]) if __name__ == "__main__": test.main() diff --git a/tensorflow/python/data/kernel_tests/shuffle_dataset_op_test.py b/tensorflow/python/data/kernel_tests/shuffle_dataset_op_test.py deleted file mode 100644 index cad28f860e..0000000000 --- a/tensorflow/python/data/kernel_tests/shuffle_dataset_op_test.py +++ /dev/null @@ -1,278 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import collections - -from absl.testing import parameterized -import numpy as np - -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.data.ops import iterator_ops -from tensorflow.python.framework import constant_op -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import ops -from tensorflow.python.framework import random_seed -from tensorflow.python.ops import array_ops -from tensorflow.python.platform import test - - -class ShuffleDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): - - def testShuffleDataset(self): - components = ( - np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), - np.array([9.0, 10.0, 11.0, 12.0]) - ) - count_placeholder = array_ops.placeholder_with_default( - constant_op.constant(5, dtypes.int64), shape=[]) - buffer_size_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - seed_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - - repeat_dataset = (dataset_ops.Dataset.from_tensor_slices(components) - .repeat(count_placeholder)) - - shuffle_dataset = repeat_dataset.shuffle(buffer_size_placeholder, - seed_placeholder) - - self.assertEqual(tuple([c.shape[1:] for c in components]), - shuffle_dataset.output_shapes) - - # Create initialization ops for iterators without and with - # shuffling, respectively. - iterator = iterator_ops.Iterator.from_structure( - shuffle_dataset.output_types, shuffle_dataset.output_shapes) - init_fifo_op = iterator.make_initializer(repeat_dataset) - init_shuffle_op = iterator.make_initializer(shuffle_dataset) - - get_next = iterator.get_next() - - with self.cached_session() as sess: - # First run without shuffling to collect the "ground truth". - sess.run(init_fifo_op) - unshuffled_elements = [] - for _ in range(20): - unshuffled_elements.append(sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - # Assert that the shuffled dataset has the same elements as the - # "ground truth". - sess.run( - init_shuffle_op, - feed_dict={buffer_size_placeholder: 100, - seed_placeholder: 37}) - shuffled_elements = [] - for _ in range(20): - shuffled_elements.append(sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - self.assertAllEqual( - sorted(unshuffled_elements), sorted(shuffled_elements)) - - # Assert that shuffling twice with the same seeds gives the same sequence. - sess.run( - init_shuffle_op, - feed_dict={buffer_size_placeholder: 100, - seed_placeholder: 37}) - reshuffled_elements_same_seed = [] - for _ in range(20): - reshuffled_elements_same_seed.append(sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - self.assertEqual(shuffled_elements, reshuffled_elements_same_seed) - - # Assert that shuffling twice with a different seed gives a different - # permutation of the same elements. - sess.run( - init_shuffle_op, - feed_dict={buffer_size_placeholder: 100, - seed_placeholder: 1037}) - reshuffled_elements_different_seed = [] - for _ in range(20): - reshuffled_elements_different_seed.append(sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - self.assertNotEqual(shuffled_elements, reshuffled_elements_different_seed) - self.assertAllEqual( - sorted(shuffled_elements), sorted(reshuffled_elements_different_seed)) - - # Assert that the shuffled dataset has the same elements as the - # "ground truth" when the buffer size is smaller than the input - # dataset. - sess.run( - init_shuffle_op, - feed_dict={buffer_size_placeholder: 2, - seed_placeholder: 37}) - reshuffled_elements_small_buffer = [] - for _ in range(20): - reshuffled_elements_small_buffer.append(sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - self.assertAllEqual( - sorted(unshuffled_elements), sorted(reshuffled_elements_small_buffer)) - - # Test the case of shuffling an empty dataset. - sess.run(init_shuffle_op, feed_dict={buffer_size_placeholder: 2, - seed_placeholder: 37, - count_placeholder: 0}) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testSeedZero(self): - """Test for same behavior when the seed is a Python or Tensor zero.""" - iterator = ( - dataset_ops.Dataset.range(10).shuffle(10, seed=0) - .make_one_shot_iterator()) - get_next = iterator.get_next() - - elems = [] - with self.cached_session() as sess: - for _ in range(10): - elems.append(sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - seed_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) - iterator = ( - dataset_ops.Dataset.range(10).shuffle(10, seed=seed_placeholder) - .make_initializable_iterator()) - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(iterator.initializer, feed_dict={seed_placeholder: 0}) - for elem in elems: - self.assertEqual(elem, sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testDefaultArguments(self): - components = [0, 1, 2, 3, 4] - iterator = (dataset_ops.Dataset.from_tensor_slices(components).shuffle(5) - .repeat().make_one_shot_iterator()) - - get_next = iterator.get_next() - - with self.cached_session() as sess: - counts = collections.defaultdict(lambda: 0) - for _ in range(10): - for _ in range(5): - counts[sess.run(get_next)] += 1 - - for i in range(5): - self.assertEqual(10, counts[i]) - - def testShuffleNoReshuffleEachIteration(self): - iterator = (dataset_ops.Dataset.range(10) - .shuffle(10, reshuffle_each_iteration=False) - .batch(10) - .repeat(3) - .make_one_shot_iterator()) - next_element = iterator.get_next() - - with self.cached_session() as sess: - initial_permutation = sess.run(next_element) - self.assertAllEqual(initial_permutation, sess.run(next_element)) - self.assertAllEqual(initial_permutation, sess.run(next_element)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - def testShuffleReshuffleEachIteration(self): - iterator = (dataset_ops.Dataset.range(10) - .shuffle(10, seed=3, reshuffle_each_iteration=True) - .batch(10) - .repeat(3) - .make_one_shot_iterator()) - next_element = iterator.get_next() - - with self.cached_session() as sess: - initial_permutation = list(sess.run(next_element)) - for _ in range(2): - next_permutation = list(sess.run(next_element)) - self.assertNotEqual(initial_permutation, next_permutation) - self.assertAllEqual( - sorted(initial_permutation), sorted(next_permutation)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - @parameterized.named_parameters( - ("ReshuffleGraphLevelSeed", True, 38, None), - ("ReshuffleOpLevelSeed", True, None, 42), - ("ReshuffleGraphAndOpLevelSeed", True, 38, 42), - ("NoReshuffleGraphLevelSeed", False, 38, None), - ("NoReshuffleOpLevelSeed", False, None, 42), - ("NoReshuffleGraphAndOpLevelSeed", False, 38, 42), - ) - def testShuffleSeed(self, reshuffle, graph_level_seed, op_level_seed): - results = [] - for _ in range(2): - with ops.Graph().as_default() as g: - random_seed.set_random_seed(graph_level_seed) - dataset = dataset_ops.Dataset.range(10).shuffle( - 10, seed=op_level_seed, reshuffle_each_iteration=reshuffle).repeat( - 3) - iterator = dataset.make_one_shot_iterator() - next_element = iterator.get_next() - - run_results = [] - with self.session(graph=g) as sess: - for _ in range(30): - run_results.append(sess.run(next_element)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - results.append(run_results) - - self.assertAllEqual(results[0], results[1]) - - @parameterized.named_parameters( - ("ReshuffleOneShot", True, False), - ("ReshuffleInitializable", True, True), - ("NoReshuffleOneShot", False, False), - ("NoReshuffleInitializable", False, True), - ) - def testMultipleIterators(self, reshuffle, initializable): - with ops.Graph().as_default() as g: - dataset = dataset_ops.Dataset.range(100).shuffle( - 10, reshuffle_each_iteration=reshuffle).repeat(3) - - if initializable: - iterators = [dataset.make_initializable_iterator() for _ in range(2)] - else: - iterators = [dataset.make_one_shot_iterator() for _ in range(2)] - - results = [] - with self.session(graph=g) as sess: - for iterator in iterators: - if initializable: - sess.run(iterator.initializer) - next_element = iterator.get_next() - run_results = [] - for _ in range(300): - run_results.append(sess.run(next_element)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) - - results.append(run_results) - - self.assertNotEqual(results[0], results[1]) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/kernel_tests/shuffle_test.py b/tensorflow/python/data/kernel_tests/shuffle_test.py new file mode 100644 index 0000000000..13df870938 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/shuffle_test.py @@ -0,0 +1,249 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.shuffle()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import collections + +from absl.testing import parameterized +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops + +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors +from tensorflow.python.framework import ops +from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class ShuffleTest(test_base.DatasetTestBase, parameterized.TestCase): + + def testShuffleDataset(self): + components = ( + np.array([1, 2, 3, 4]), np.array([5, 6, 7, 8]), + np.array([9.0, 10.0, 11.0, 12.0]) + ) + + def dataset_fn(count=5, buffer_size=None, seed=0): + repeat_dataset = ( + dataset_ops.Dataset.from_tensor_slices(components).repeat(count)) + if buffer_size: + shuffle_dataset = repeat_dataset.shuffle(buffer_size, seed) + + self.assertEqual( + tuple([c.shape[1:] for c in components]), + shuffle_dataset.output_shapes) + return shuffle_dataset + else: + return repeat_dataset + + # First run without shuffling to collect the "ground truth". + get_next = self.getNext(dataset_fn()) + unshuffled_elements = [] + for _ in range(20): + unshuffled_elements.append(self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + # Assert that the shuffled dataset has the same elements as the + # "ground truth". + get_next = self.getNext(dataset_fn(buffer_size=100, seed=37)) + shuffled_elements = [] + for _ in range(20): + shuffled_elements.append(self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + self.assertAllEqual(sorted(unshuffled_elements), sorted(shuffled_elements)) + + # Assert that shuffling twice with the same seeds gives the same sequence. + get_next = self.getNext(dataset_fn(buffer_size=100, seed=37)) + reshuffled_elements_same_seed = [] + for _ in range(20): + reshuffled_elements_same_seed.append(self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + self.assertEqual(shuffled_elements, reshuffled_elements_same_seed) + + # Assert that shuffling twice with a different seed gives a different + # permutation of the same elements. + get_next = self.getNext(dataset_fn(buffer_size=100, seed=137)) + reshuffled_elements_different_seed = [] + for _ in range(20): + reshuffled_elements_different_seed.append(self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + self.assertNotEqual(shuffled_elements, reshuffled_elements_different_seed) + self.assertAllEqual( + sorted(shuffled_elements), sorted(reshuffled_elements_different_seed)) + + # Assert that the shuffled dataset has the same elements as the + # "ground truth" when the buffer size is smaller than the input + # dataset. + get_next = self.getNext(dataset_fn(buffer_size=2, seed=37)) + reshuffled_elements_small_buffer = [] + for _ in range(20): + reshuffled_elements_small_buffer.append(self.evaluate(get_next())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + self.assertAllEqual( + sorted(unshuffled_elements), sorted(reshuffled_elements_small_buffer)) + + # Test the case of shuffling an empty dataset. + get_next = self.getNext(dataset_fn(count=0, buffer_size=100, seed=37)) + + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + @test_util.run_deprecated_v1 + def testSkipEagerSeedZero(self): + """Test for same behavior when the seed is a Python or Tensor zero.""" + iterator = dataset_ops.make_one_shot_iterator( + dataset_ops.Dataset.range(10).shuffle(10, seed=0)) + get_next = iterator.get_next() + + elems = [] + with self.cached_session() as sess: + for _ in range(10): + elems.append(sess.run(get_next)) + with self.assertRaises(errors.OutOfRangeError): + sess.run(get_next) + + seed_placeholder = array_ops.placeholder(dtypes.int64, shape=[]) + iterator = dataset_ops.make_initializable_iterator( + dataset_ops.Dataset.range(10).shuffle(10, seed=seed_placeholder)) + get_next = iterator.get_next() + + with self.cached_session() as sess: + sess.run(iterator.initializer, feed_dict={seed_placeholder: 0}) + for elem in elems: + self.assertEqual(elem, sess.run(get_next)) + with self.assertRaises(errors.OutOfRangeError): + sess.run(get_next) + + def testDefaultArguments(self): + components = [0, 1, 2, 3, 4] + dataset = dataset_ops.Dataset.from_tensor_slices(components).shuffle( + 5).repeat() + get_next = self.getNext(dataset) + counts = collections.defaultdict(lambda: 0) + for _ in range(10): + for _ in range(5): + counts[self.evaluate(get_next())] += 1 + + for i in range(5): + self.assertEqual(10, counts[i]) + + def testShuffleNoReshuffleEachIteration(self): + dataset = dataset_ops.Dataset.range(10).shuffle( + 10, reshuffle_each_iteration=False).batch(10).repeat(3) + next_element = self.getNext(dataset) + + initial_permutation = self.evaluate(next_element()) + self.assertAllEqual(initial_permutation, self.evaluate(next_element())) + self.assertAllEqual(initial_permutation, self.evaluate(next_element())) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(next_element()) + + def testShuffleReshuffleEachIteration(self): + dataset = dataset_ops.Dataset.range(10).shuffle( + 10, seed=3, reshuffle_each_iteration=True).batch(10).repeat(3) + next_element = self.getNext(dataset) + + initial_permutation = list(self.evaluate(next_element())) + for _ in range(2): + next_permutation = list(self.evaluate(next_element())) + self.assertNotEqual(initial_permutation, next_permutation) + self.assertAllEqual(sorted(initial_permutation), sorted(next_permutation)) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(next_element()) + + @parameterized.named_parameters( + ("ReshuffleGraphLevelSeed", True, 38, None), + ("ReshuffleOpLevelSeed", True, None, 42), + ("ReshuffleGraphAndOpLevelSeed", True, 38, 42), + ("NoReshuffleGraphLevelSeed", False, 38, None), + ("NoReshuffleOpLevelSeed", False, None, 42), + ("NoReshuffleGraphAndOpLevelSeed", False, 38, 42), + ) + def testSkipEagerShuffleSeed(self, reshuffle, graph_level_seed, + op_level_seed): + results = [] + for _ in range(2): + with ops.Graph().as_default() as g: + random_seed.set_random_seed(graph_level_seed) + dataset = dataset_ops.Dataset.range(10).shuffle( + 10, seed=op_level_seed, reshuffle_each_iteration=reshuffle).repeat( + 3) + iterator = dataset_ops.make_one_shot_iterator(dataset) + next_element = iterator.get_next() + + run_results = [] + with self.session(graph=g) as sess: + for _ in range(30): + run_results.append(sess.run(next_element)) + with self.assertRaises(errors.OutOfRangeError): + sess.run(next_element) + results.append(run_results) + + self.assertAllEqual(results[0], results[1]) + + # TODO(b/117581999): fails for eager mode with result[0] equal to result[1], + # debug. + @parameterized.named_parameters( + ("ReshuffleOneShot", True, False), + ("ReshuffleInitializable", True, True), + ("NoReshuffleOneShot", False, False), + ("NoReshuffleInitializable", False, True), + ) + def testSkipEagerMultipleIterators(self, reshuffle, initializable): + with ops.Graph().as_default() as g: + dataset = dataset_ops.Dataset.range(100).shuffle( + 10, reshuffle_each_iteration=reshuffle).repeat(3) + + if initializable: + iterators = [dataset_ops.make_initializable_iterator(dataset) + for _ in range(2)] + else: + iterators = [dataset_ops.make_one_shot_iterator(dataset) + for _ in range(2)] + + results = [] + with self.session(graph=g) as sess: + for iterator in iterators: + if initializable: + sess.run(iterator.initializer) + next_element = iterator.get_next() + run_results = [] + for _ in range(300): + run_results.append(sess.run(next_element)) + with self.assertRaises(errors.OutOfRangeError): + sess.run(next_element) + + results.append(run_results) + + self.assertNotEqual(results[0], results[1]) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/skip_test.py b/tensorflow/python/data/kernel_tests/skip_test.py new file mode 100644 index 0000000000..c22be57692 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/skip_test.py @@ -0,0 +1,62 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.skip()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class SkipTest(test_base.DatasetTestBase): + + def testSkipTensorDataset(self): + components = (np.arange(10),) + + def do_test(count): + dataset = dataset_ops.Dataset.from_tensor_slices(components).skip(count) + self.assertEqual([c.shape[1:] for c in components], + [shape for shape in dataset.output_shapes]) + start_range = min(count, 10) if count != -1 else 10 + self.assertDatasetProduces( + dataset, + [tuple(components[0][i:i + 1]) for i in range(start_range, 10)]) + + # Skip fewer than input size, we should skip + # the first 4 elements and then read the rest. + do_test(4) + + # Skip more than input size: get nothing. + do_test(25) + + # Skip exactly input size. + do_test(10) + + # Set -1 for 'count': skip the entire dataset. + do_test(-1) + + # Skip nothing + do_test(0) + + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/take_test.py b/tensorflow/python/data/kernel_tests/take_test.py new file mode 100644 index 0000000000..03a7ece2d8 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/take_test.py @@ -0,0 +1,55 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.take()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class TakeTest(test_base.DatasetTestBase): + + def testTakeTensorDataset(self): + components = (np.arange(10),) + + def do_test(count): + dataset = dataset_ops.Dataset.from_tensor_slices(components).take(count) + self.assertEqual([c.shape[1:] for c in components], + [shape for shape in dataset.output_shapes]) + num_output = min(count, 10) if count != -1 else 10 + self.assertDatasetProduces( + dataset, [tuple(components[0][i:i + 1]) for i in range(num_output)]) + + # Take fewer than input size + do_test(4) + + # Take more than input size + do_test(25) + + # Take all of input + do_test(-1) + + # Take nothing + do_test(0) + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/test_base.py b/tensorflow/python/data/kernel_tests/test_base.py index edb3eff3c1..85f6c9de23 100644 --- a/tensorflow/python/data/kernel_tests/test_base.py +++ b/tensorflow/python/data/kernel_tests/test_base.py @@ -38,56 +38,102 @@ class DatasetTestBase(test.TestCase): self.assertAllEqual(a.values, b.values) self.assertAllEqual(a.dense_shape, b.dense_shape) - def getNext(self, dataset): + def getNext(self, dataset, requires_initialization=False): """Returns a callable that returns the next element of the dataset. Example use: ```python # In both graph and eager modes dataset = ... - nxt = self.getNext(dataset) - result = self.evaluate(nxt()) + get_next = self.getNext(dataset) + result = self.evaluate(get_next()) ``` Args: - dataset: A dataset whose next element is returned - + dataset: A dataset whose elements will be returned. + requires_initialization: Indicates that when the test is executed in graph + mode, it should use an initializable iterator to iterate through the + dataset (e.g. when it contains stateful nodes). Defaults to False. Returns: - A callable that returns the next element of `dataset` + A callable that returns the next element of `dataset`. """ - it = dataset.make_one_shot_iterator() if context.executing_eagerly(): - return it.get_next + iterator = dataset.__iter__() + return iterator._next_internal # pylint: disable=protected-access else: - nxt = it.get_next() - return lambda: nxt - - def _compare_output_to_expected(self, result_values, expected_values): - for i in range(len(result_values)): - if sparse_tensor.is_sparse(result_values[i]): - self.assertSparseValuesEqual(result_values[i], expected_values[i]) + if requires_initialization: + iterator = dataset_ops.make_initializable_iterator(dataset) + self.evaluate(iterator.initializer) else: - self.assertAllEqual(result_values[i], expected_values[i]) + iterator = dataset_ops.make_one_shot_iterator(dataset) + get_next = iterator.get_next() + return lambda: get_next + + def _compareOutputToExpected(self, result_values, expected_values, + assert_items_equal): + if assert_items_equal: + # TODO(shivaniagrawal): add support for nested elements containing sparse + # tensors when needed. + self.assertItemsEqual(result_values, expected_values) + return + for i in range(len(result_values)): + nest.assert_same_structure(result_values[i], expected_values[i]) + for result_value, expected_value in zip( + nest.flatten(result_values[i]), nest.flatten(expected_values[i])): + if sparse_tensor.is_sparse(result_value): + self.assertSparseValuesEqual(result_value, expected_value) + else: + self.assertAllEqual(result_value, expected_value) def assertDatasetProduces(self, - input_dataset, + dataset, expected_output=None, - expected_err=None, - create_iterator_twice=True): + expected_error=None, + requires_initialization=False, + num_test_iterations=1, + assert_items_equal=False): + """Asserts that a dataset produces the expected output / error. - if expected_err: - with self.assertRaisesWithPredicateMatch(expected_err[0], - expected_err[1]): - get_next = self.getNext(input_dataset) + Args: + dataset: A dataset to check for the expected output / error. + expected_output: A list of elements that the dataset is expected to + produce. + expected_error: A tuple `(type, predicate)` identifying the expected error + `dataset` should raise. The `type` should match the expected exception + type, while `predicate` should either be 1) a unary function that inputs + the raised exception and returns a boolean indicator of success or 2) a + regular expression that is expected to match the error message + partially. + requires_initialization: Indicates that when the test is executed in graph + mode, it should use an initializable iterator to iterate through the + dataset (e.g. when it contains stateful nodes). Defaults to False. + num_test_iterations: Number of times `dataset` will be iterated. Defaults + to 2. + assert_items_equal: Tests expected_output has (only) the same elements + regardless of order. + """ + self.assertTrue( + expected_error is not None or expected_output is not None, + "Exactly one of expected_output or expected error should be provided.") + if expected_error: + self.assertTrue( + expected_output is None, + "Exactly one of expected_output or expected error should be provided." + ) + with self.assertRaisesWithPredicateMatch(expected_error[0], + expected_error[1]): + get_next = self.getNext( + dataset, requires_initialization=requires_initialization) self.evaluate(get_next()) return - repeated = 2 if create_iterator_twice else 1 - for _ in range(repeated): - get_next = self.getNext(input_dataset) + self.assertGreater(num_test_iterations, 0) + for _ in range(num_test_iterations): + get_next = self.getNext( + dataset, requires_initialization=requires_initialization) result = [] for _ in range(len(expected_output)): result.append(self.evaluate(get_next())) - self._compare_output_to_expected(result, expected_output) + self._compareOutputToExpected(result, expected_output, assert_items_equal) with self.assertRaises(errors.OutOfRangeError): self.evaluate(get_next()) with self.assertRaises(errors.OutOfRangeError): @@ -132,7 +178,7 @@ class DatasetTestBase(test.TestCase): try: self.evaluate(next1()) raise ValueError( - 'Expected dataset to raise an error of type %s, but it did not.' % + "Expected dataset to raise an error of type %s, but it did not." % repr(exception_class)) except exception_class as e: expected_message = e.message diff --git a/tensorflow/python/data/kernel_tests/text_line_dataset_test.py b/tensorflow/python/data/kernel_tests/text_line_dataset_test.py new file mode 100644 index 0000000000..4db09a9808 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/text_line_dataset_test.py @@ -0,0 +1,165 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.TextLineDataset`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import gzip +import os +import zlib + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import readers +from tensorflow.python.eager import context +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test +from tensorflow.python.util import compat + + +try: + import psutil # pylint: disable=g-import-not-at-top + psutil_import_succeeded = True +except ImportError: + psutil_import_succeeded = False + + +@test_util.run_all_in_graph_and_eager_modes +class TextLineDatasetTest(test_base.DatasetTestBase): + + def _lineText(self, f, l): + return compat.as_bytes("%d: %d" % (f, l)) + + def _createFiles(self, + num_files, + num_lines, + crlf=False, + compression_type=None): + filenames = [] + for i in range(num_files): + fn = os.path.join(self.get_temp_dir(), "text_line.%d.txt" % i) + filenames.append(fn) + contents = [] + for j in range(num_lines): + contents.append(self._lineText(i, j)) + # Always include a newline after the record unless it is + # at the end of the file, in which case we include it + if j + 1 != num_lines or i == 0: + contents.append(b"\r\n" if crlf else b"\n") + contents = b"".join(contents) + + if not compression_type: + with open(fn, "wb") as f: + f.write(contents) + elif compression_type == "GZIP": + with gzip.GzipFile(fn, "wb") as f: + f.write(contents) + elif compression_type == "ZLIB": + contents = zlib.compress(contents) + with open(fn, "wb") as f: + f.write(contents) + else: + raise ValueError("Unsupported compression_type", compression_type) + + return filenames + + def _testTextLineDataset(self, compression_type=None): + test_filenames = self._createFiles( + 2, 5, crlf=True, compression_type=compression_type) + + def dataset_fn(filenames, num_epochs, batch_size=None): + repeat_dataset = readers.TextLineDataset( + filenames, compression_type=compression_type).repeat(num_epochs) + if batch_size: + return repeat_dataset.batch(batch_size) + return repeat_dataset + + # Basic test: read from file 0. + expected_output = [self._lineText(0, i) for i in range(5)] + self.assertDatasetProduces( + dataset_fn([test_filenames[0]], 1), expected_output=expected_output) + + # Basic test: read from file 1. + self.assertDatasetProduces( + dataset_fn([test_filenames[1]], 1), + expected_output=[self._lineText(1, i) for i in range(5)]) + + # Basic test: read from both files. + expected_output = [self._lineText(0, i) for i in range(5)] + expected_output.extend([self._lineText(1, i) for i in range(5)]) + self.assertDatasetProduces( + dataset_fn(test_filenames, 1), expected_output=expected_output) + + # Test repeated iteration through both files. + expected_output = [self._lineText(0, i) for i in range(5)] + expected_output.extend([self._lineText(1, i) for i in range(5)]) + self.assertDatasetProduces( + dataset_fn(test_filenames, 10), expected_output=expected_output * 10) + + # Test batched and repeated iteration through both files. + self.assertDatasetProduces( + dataset_fn(test_filenames, 10, 5), + expected_output=[[self._lineText(0, i) for i in range(5)], + [self._lineText(1, i) for i in range(5)]] * 10) + + def testTextLineDatasetNoCompression(self): + self._testTextLineDataset() + + def testTextLineDatasetGzipCompression(self): + self._testTextLineDataset(compression_type="GZIP") + + def testTextLineDatasetZlibCompression(self): + self._testTextLineDataset(compression_type="ZLIB") + + def testTextLineDatasetBuffering(self): + test_filenames = self._createFiles(2, 5, crlf=True) + + repeat_dataset = readers.TextLineDataset(test_filenames, buffer_size=10) + expected_output = [] + for j in range(2): + expected_output.extend([self._lineText(j, i) for i in range(5)]) + self.assertDatasetProduces(repeat_dataset, expected_output=expected_output) + + def testIteratorResourceCleanup(self): + filename = os.path.join(self.get_temp_dir(), "text.txt") + with open(filename, "wt") as f: + for i in range(3): + f.write("%d\n" % (i,)) + with context.eager_mode(): + first_iterator = iter(readers.TextLineDataset(filename)) + self.assertEqual(b"0", next(first_iterator).numpy()) + second_iterator = iter(readers.TextLineDataset(filename)) + self.assertEqual(b"0", next(second_iterator).numpy()) + # Eager kernel caching is based on op attributes, which includes the + # Dataset's output shape. Create a different kernel to test that they + # don't create resources with the same names. + different_kernel_iterator = iter( + readers.TextLineDataset(filename).repeat().batch(16)) + self.assertEqual([16], next(different_kernel_iterator).shape) + # Remove our references to the Python Iterator objects, which (assuming no + # reference cycles) is enough to trigger DestroyResourceOp and close the + # partially-read files. + del first_iterator + del second_iterator + del different_kernel_iterator + if not psutil_import_succeeded: + self.skipTest( + "psutil is required to check that we've closed our files.") + open_files = psutil.Process().open_files() + self.assertNotIn(filename, [open_file.path for open_file in open_files]) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/tf_record_dataset_test.py b/tensorflow/python/data/kernel_tests/tf_record_dataset_test.py new file mode 100644 index 0000000000..13a70aa88d --- /dev/null +++ b/tensorflow/python/data/kernel_tests/tf_record_dataset_test.py @@ -0,0 +1,170 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.TFRecordDataset`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import gzip +import os +import zlib + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.ops import readers +from tensorflow.python.framework import test_util +from tensorflow.python.lib.io import python_io +from tensorflow.python.platform import test +from tensorflow.python.util import compat + + +@test_util.run_all_in_graph_and_eager_modes +class TFRecordDatasetTest(test_base.DatasetTestBase): + + def setUp(self): + super(TFRecordDatasetTest, self).setUp() + self._num_files = 2 + self._num_records = 7 + + self.test_filenames = self._createFiles() + + def dataset_fn(self, + filenames, + compression_type="", + num_epochs=1, + batch_size=None): + + repeat_dataset = readers.TFRecordDataset( + filenames, compression_type).repeat(num_epochs) + if batch_size: + return repeat_dataset.batch(batch_size) + return repeat_dataset + + def _record(self, f, r): + return compat.as_bytes("Record %d of file %d" % (r, f)) + + def _createFiles(self): + filenames = [] + for i in range(self._num_files): + fn = os.path.join(self.get_temp_dir(), "tf_record.%d.txt" % i) + filenames.append(fn) + writer = python_io.TFRecordWriter(fn) + for j in range(self._num_records): + writer.write(self._record(i, j)) + writer.close() + return filenames + + def testReadOneEpoch(self): + # Basic test: read from file 0. + dataset = self.dataset_fn(self.test_filenames[0]) + self.assertDatasetProduces( + dataset, + expected_output=[self._record(0, i) for i in range(self._num_records)]) + + # Basic test: read from file 1. + dataset = self.dataset_fn(self.test_filenames[1]) + self.assertDatasetProduces( + dataset, + expected_output=[self._record(1, i) for i in range(self._num_records)]) + + # Basic test: read from both files. + dataset = self.dataset_fn(self.test_filenames) + expected_output = [] + for j in range(self._num_files): + expected_output.extend( + [self._record(j, i) for i in range(self._num_records)]) + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testReadTenEpochs(self): + dataset = self.dataset_fn(self.test_filenames, num_epochs=10) + expected_output = [] + for j in range(self._num_files): + expected_output.extend( + [self._record(j, i) for i in range(self._num_records)]) + self.assertDatasetProduces(dataset, expected_output=expected_output * 10) + + def testReadTenEpochsOfBatches(self): + dataset = self.dataset_fn( + self.test_filenames, num_epochs=10, batch_size=self._num_records) + expected_output = [] + for j in range(self._num_files): + expected_output.append( + [self._record(j, i) for i in range(self._num_records)]) + self.assertDatasetProduces(dataset, expected_output=expected_output * 10) + + def testReadZlibFiles(self): + zlib_files = [] + for i, fn in enumerate(self.test_filenames): + with open(fn, "rb") as f: + cdata = zlib.compress(f.read()) + + zfn = os.path.join(self.get_temp_dir(), "tfrecord_%s.z" % i) + with open(zfn, "wb") as f: + f.write(cdata) + zlib_files.append(zfn) + expected_output = [] + for j in range(self._num_files): + expected_output.extend( + [self._record(j, i) for i in range(self._num_records)]) + dataset = self.dataset_fn(zlib_files, compression_type="ZLIB") + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testReadGzipFiles(self): + gzip_files = [] + for i, fn in enumerate(self.test_filenames): + with open(fn, "rb") as f: + gzfn = os.path.join(self.get_temp_dir(), "tfrecord_%s.gz" % i) + with gzip.GzipFile(gzfn, "wb") as gzf: + gzf.write(f.read()) + gzip_files.append(gzfn) + expected_output = [] + for j in range(self._num_files): + expected_output.extend( + [self._record(j, i) for i in range(self._num_records)]) + dataset = self.dataset_fn(gzip_files, compression_type="GZIP") + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testReadWithBuffer(self): + one_mebibyte = 2**20 + dataset = readers.TFRecordDataset( + self.test_filenames, buffer_size=one_mebibyte) + expected_output = [] + for j in range(self._num_files): + expected_output.extend( + [self._record(j, i) for i in range(self._num_records)]) + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testReadFromDatasetOfFiles(self): + files = dataset_ops.Dataset.from_tensor_slices(self.test_filenames) + expected_output = [] + for j in range(self._num_files): + expected_output.extend( + [self._record(j, i) for i in range(self._num_records)]) + dataset = readers.TFRecordDataset(files) + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testReadTenEpochsFromDatasetOfFilesInParallel(self): + files = dataset_ops.Dataset.from_tensor_slices( + self.test_filenames).repeat(10) + expected_output = [] + for j in range(self._num_files): + expected_output.extend( + [self._record(j, i) for i in range(self._num_records)]) + dataset = readers.TFRecordDataset(files, num_parallel_reads=4) + self.assertDatasetProduces( + dataset, expected_output=expected_output * 10, assert_items_equal=True) + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/window_dataset_op_test.py b/tensorflow/python/data/kernel_tests/window_dataset_op_test.py deleted file mode 100644 index 9d06781094..0000000000 --- a/tensorflow/python/data/kernel_tests/window_dataset_op_test.py +++ /dev/null @@ -1,291 +0,0 @@ -# Copyright 2018 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -from absl.testing import parameterized -import numpy as np - -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.framework import sparse_tensor -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.platform import test - - -class WindowDatasetTest(test_base.DatasetTestBase, parameterized.TestCase): - - @parameterized.named_parameters( - ("1", 20, 14, 7, 1), - ("2", 20, 17, 9, 1), - ("3", 20, 14, 14, 1), - ("4", 20, 10, 14, 1), - ("5", 20, 14, 19, 1), - ("6", 20, 4, 1, 2), - ("7", 20, 2, 1, 6), - ("8", 20, 4, 7, 2), - ("9", 20, 2, 7, 6), - ("10", 1, 10, 4, 1), - ("11", 0, 10, 4, 1), - ("12", 20, 14, 7, 1, False), - ("13", 20, 17, 9, 1, False), - ("14", 20, 14, 14, 1, False), - ("15", 20, 10, 14, 1, False), - ("16", 20, 14, 19, 1, False), - ("17", 20, 4, 1, 2, False), - ("18", 20, 2, 1, 6, False), - ("19", 20, 4, 7, 2, False), - ("20", 20, 2, 7, 6, False), - ("21", 1, 10, 4, 1, False), - ("22", 0, 10, 4, 1, False), - ) - def testWindowDataset(self, count, size, shift, stride, drop_remainder=True): - """Tests a dataset that slides a window its input elements.""" - components = (np.arange(7), - np.array([[1, 2, 3]]) * np.arange(7)[:, np.newaxis], - np.array(37.0) * np.arange(7)) - - count_t = array_ops.placeholder(dtypes.int64, shape=[]) - size_t = array_ops.placeholder(dtypes.int64, shape=[]) - shift_t = array_ops.placeholder(dtypes.int64, shape=[]) - stride_t = array_ops.placeholder(dtypes.int64, shape=[]) - drop_remainder_t = array_ops.placeholder(dtypes.bool, shape=[]) - - def _map_fn(x, y, z): - return math_ops.square(x), math_ops.square(y), math_ops.square(z) - - def _flat_map_fn(x, y, z): - return dataset_ops.Dataset.zip((x.batch(batch_size=size_t), - y.batch(batch_size=size_t), - z.batch(batch_size=size_t))) - - iterator = dataset_ops.Dataset.from_tensor_slices(components).map( - _map_fn).repeat(count).window( - size=size_t, - shift=shift_t, - stride=stride_t, - drop_remainder=drop_remainder_t).flat_map( - _flat_map_fn).make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([[None] + list(c.shape[1:]) for c in components], - [t.shape.as_list() for t in get_next]) - - with self.cached_session() as sess: - sess.run( - init_op, - feed_dict={ - count_t: count, - size_t: size, - shift_t: shift, - stride_t: stride, - drop_remainder_t: drop_remainder - }) - num_full_batches = max( - 0, (count * 7 - ((size - 1) * stride + 1)) // shift + 1) - for i in range(num_full_batches): - result = sess.run(get_next) - for component, result_component in zip(components, result): - for j in range(size): - self.assertAllEqual(component[(i * shift + j * stride) % 7]**2, - result_component[j]) - if not drop_remainder: - num_partial_batches = (count * 7) // shift + ( - (count * 7) % shift > 0) - num_full_batches - for i in range(num_partial_batches): - result = sess.run(get_next) - for component, result_component in zip(components, result): - remaining = (count * 7) - ((num_full_batches + i) * shift) - num_elements = remaining // stride + ((remaining % stride) > 0) - for j in range(num_elements): - self.assertAllEqual( - component[((num_full_batches + i) * shift + j * stride) % 7] - **2, result_component[j]) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - @parameterized.named_parameters( - ("1", 14, 0, 3, 1), - ("2", 14, 3, 0, 1), - ("3", 14, 3, 3, 0), - ) - def testWindowDatasetInvalid(self, count, size, shift, stride): - count_t = array_ops.placeholder(dtypes.int64, shape=[]) - size_t = array_ops.placeholder(dtypes.int64, shape=[]) - shift_t = array_ops.placeholder(dtypes.int64, shape=[]) - stride_t = array_ops.placeholder(dtypes.int64, shape=[]) - - iterator = dataset_ops.Dataset.range(10).map(lambda x: x).repeat( - count_t).window( - size=size_t, shift=shift_t, - stride=stride_t).flat_map(lambda x: x.batch(batch_size=size_t) - ).make_initializable_iterator() - init_op = iterator.initializer - - with self.cached_session() as sess: - with self.assertRaises(errors.InvalidArgumentError): - sess.run( - init_op, - feed_dict={ - count_t: count, - size_t: size, - shift_t: shift, - stride_t: stride - }) - - def testWindowSparse(self): - - def _sparse(i): - return sparse_tensor.SparseTensorValue( - indices=[[0]], values=(i * [1]), dense_shape=[1]) - - iterator = dataset_ops.Dataset.range(10).map(_sparse).window( - size=5, shift=3, drop_remainder=True).flat_map( - lambda x: x.batch(batch_size=5)).make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - num_batches = (10 - 5) // 3 + 1 - for i in range(num_batches): - actual = sess.run(get_next) - expected = sparse_tensor.SparseTensorValue( - indices=[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], - values=[i * 3, i * 3 + 1, i * 3 + 2, i * 3 + 3, i * 3 + 4], - dense_shape=[5, 1]) - self.assertTrue(sparse_tensor.is_sparse(actual)) - self.assertSparseValuesEqual(actual, expected) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testWindowSparseWithDifferentDenseShapes(self): - - def _sparse(i): - return sparse_tensor.SparseTensorValue( - indices=array_ops.expand_dims( - math_ops.range(i, dtype=dtypes.int64), 1), - values=array_ops.fill([math_ops.to_int32(i)], i), - dense_shape=[i]) - - iterator = dataset_ops.Dataset.range(10).map(_sparse).window( - size=5, shift=3, drop_remainder=True).flat_map( - lambda x: x.batch(batch_size=5)).make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - num_batches = (10 - 5) // 3 + 1 - for i in range(num_batches): - actual = sess.run(get_next) - expected_indices = [] - expected_values = [] - for j in range(5): - for k in range(i * 3 + j): - expected_indices.append([j, k]) - expected_values.append(i * 3 + j) - expected = sparse_tensor.SparseTensorValue( - indices=expected_indices, - values=expected_values, - dense_shape=[5, i * 3 + 5 - 1]) - self.assertTrue(sparse_tensor.is_sparse(actual)) - self.assertSparseValuesEqual(actual, expected) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testNestedWindowSparse(self): - - def _sparse(i): - return sparse_tensor.SparseTensorValue( - indices=[[0]], values=(i * [1]), dense_shape=[1]) - - iterator = dataset_ops.Dataset.range(10).map(_sparse).window( - size=4, shift=2, - drop_remainder=True).flat_map(lambda x: x.batch(batch_size=4)).window( - size=3, shift=1, drop_remainder=True).flat_map( - lambda x: x.batch(batch_size=3)).make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - sess.run(init_op) - # Slide: 1st batch. - actual = sess.run(get_next) - expected = sparse_tensor.SparseTensorValue( - indices=[[0, 0, 0], [0, 1, 0], [0, 2, 0], [0, 3, 0], [1, 0, 0], - [1, 1, 0], [1, 2, 0], [1, 3, 0], [2, 0, 0], [2, 1, 0], - [2, 2, 0], [2, 3, 0]], - values=[0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7], - dense_shape=[3, 4, 1]) - self.assertTrue(sparse_tensor.is_sparse(actual)) - self.assertSparseValuesEqual(actual, expected) - # Slide: 2nd batch. - actual = sess.run(get_next) - expected = sparse_tensor.SparseTensorValue( - indices=[[0, 0, 0], [0, 1, 0], [0, 2, 0], [0, 3, 0], [1, 0, 0], - [1, 1, 0], [1, 2, 0], [1, 3, 0], [2, 0, 0], [2, 1, 0], - [2, 2, 0], [2, 3, 0]], - values=[2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9], - dense_shape=[3, 4, 1]) - self.assertTrue(sparse_tensor.is_sparse(actual)) - self.assertSparseValuesEqual(actual, expected) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testWindowShapeError(self): - - def generator(): - yield [1.0, 2.0, 3.0] - yield [4.0, 5.0, 6.0] - yield [7.0, 8.0, 9.0, 10.0] - - iterator = dataset_ops.Dataset.from_generator( - generator, dtypes.float32, output_shapes=[None]).window( - size=3, shift=1).flat_map( - lambda x: x.batch(batch_size=3)).make_initializable_iterator() - next_element = iterator.get_next() - - with self.cached_session() as sess: - sess.run(iterator.initializer) - with self.assertRaisesRegexp( - errors.InvalidArgumentError, - r"Cannot batch tensors with different shapes in component 0. " - r"First element had shape \[3\] and element 2 had shape \[4\]."): - sess.run(next_element) - - def testWindowIgnoreErrors(self): - input_values = np.float32([1., np.nan, 2., np.nan, 3.]) - dataset = dataset_ops.Dataset.from_tensor_slices(input_values).map( - lambda x: array_ops.check_numerics(x, "message")).window( - size=2, shift=2, stride=2, - drop_remainder=True).flat_map(lambda x: x.batch(batch_size=2)) - get_next = dataset.make_one_shot_iterator().get_next() - - with self.cached_session() as sess: - self.assertAllEqual(np.float32([1., 2.]), sess.run(get_next)) - self.assertAllEqual(np.float32([2., 3.]), sess.run(get_next)) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/kernel_tests/window_test.py b/tensorflow/python/data/kernel_tests/window_test.py new file mode 100644 index 0000000000..d083142ab6 --- /dev/null +++ b/tensorflow/python/data/kernel_tests/window_test.py @@ -0,0 +1,231 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.window()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from absl.testing import parameterized +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.util import nest +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import errors +from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class WindowTest(test_base.DatasetTestBase, parameterized.TestCase): + + @parameterized.named_parameters( + ("1", 20, 14, 7, 1), + ("2", 20, 17, 9, 1), + ("3", 20, 14, 14, 1), + ("4", 20, 10, 14, 1), + ("5", 20, 14, 19, 1), + ("6", 20, 4, 1, 2), + ("7", 20, 2, 1, 6), + ("8", 20, 4, 7, 2), + ("9", 20, 2, 7, 6), + ("10", 1, 10, 4, 1), + ("11", 0, 10, 4, 1), + ("12", 20, 14, 7, 1, False), + ("13", 20, 17, 9, 1, False), + ("14", 20, 14, 14, 1, False), + ("15", 20, 10, 14, 1, False), + ("16", 20, 14, 19, 1, False), + ("17", 20, 4, 1, 2, False), + ("18", 20, 2, 1, 6, False), + ("19", 20, 4, 7, 2, False), + ("20", 20, 2, 7, 6, False), + ("21", 1, 10, 4, 1, False), + ("22", 0, 10, 4, 1, False), + ) + def testWindowDataset(self, count, size, shift, stride, drop_remainder=True): + """Tests a dataset that slides a window its input elements.""" + components = (np.arange(7), + np.array([[1, 2, 3]]) * np.arange(7)[:, np.newaxis], + np.array(37.0) * np.arange(7)) + + def _map_fn(x, y, z): + return math_ops.square(x), math_ops.square(y), math_ops.square(z) + + def _flat_map_fn(x, y, z): + return dataset_ops.Dataset.zip((x.batch(batch_size=size), + y.batch(batch_size=size), + z.batch(batch_size=size))) + + dataset = dataset_ops.Dataset.from_tensor_slices(components).map( + _map_fn).repeat(count).window( + size=size, + shift=shift, + stride=stride, + drop_remainder=drop_remainder).flat_map(_flat_map_fn) + get_next = self.getNext(dataset) + + self.assertEqual( + [[None] + list(c.shape[1:]) for c in components], + [ts.as_list() for ts in nest.flatten(dataset.output_shapes)]) + + num_full_batches = max(0, + (count * 7 - ((size - 1) * stride + 1)) // shift + 1) + for i in range(num_full_batches): + result = self.evaluate(get_next()) + for component, result_component in zip(components, result): + for j in range(size): + self.assertAllEqual(component[(i * shift + j * stride) % 7]**2, + result_component[j]) + if not drop_remainder: + num_partial_batches = (count * 7) // shift + ( + (count * 7) % shift > 0) - num_full_batches + for i in range(num_partial_batches): + result = self.evaluate(get_next()) + for component, result_component in zip(components, result): + remaining = (count * 7) - ((num_full_batches + i) * shift) + num_elements = remaining // stride + ((remaining % stride) > 0) + for j in range(num_elements): + self.assertAllEqual( + component[((num_full_batches + i) * shift + j * stride) % 7]**2, + result_component[j]) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + @parameterized.named_parameters( + ("1", 14, 0, 3, 1), + ("2", 14, 3, 0, 1), + ("3", 14, 3, 3, 0), + ) + def testWindowDatasetInvalid(self, count, size, shift, stride): + dataset = dataset_ops.Dataset.range(10).map(lambda x: x).repeat( + count).window( + size=size, shift=shift, + stride=stride).flat_map(lambda x: x.batch(batch_size=size)) + self.assertDatasetProduces( + dataset, expected_error=(errors.InvalidArgumentError, "")) + + def testWindowSparse(self): + + def _sparse(i): + return sparse_tensor.SparseTensorValue( + indices=[[0]], values=(i * [1]), dense_shape=[1]) + + dataset = dataset_ops.Dataset.range(10).map(_sparse).window( + size=5, shift=3, + drop_remainder=True).flat_map(lambda x: x.batch(batch_size=5)) + + num_batches = (10 - 5) // 3 + 1 + expected_output = [ + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]], + values=[i * 3, i * 3 + 1, i * 3 + 2, i * 3 + 3, i * 3 + 4], + dense_shape=[5, 1]) for i in range(num_batches) + ] + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testWindowSparseWithDifferentDenseShapes(self): + + def _sparse(i): + return sparse_tensor.SparseTensorValue( + indices=array_ops.expand_dims( + math_ops.range(i, dtype=dtypes.int64), 1), + values=array_ops.fill([math_ops.to_int32(i)], i), + dense_shape=[i]) + + dataset = dataset_ops.Dataset.range(10).map(_sparse).window( + size=5, shift=3, + drop_remainder=True).flat_map(lambda x: x.batch(batch_size=5)) + + expected_output = [] + num_batches = (10 - 5) // 3 + 1 + for i in range(num_batches): + expected_indices = [] + expected_values = [] + for j in range(5): + for k in range(i * 3 + j): + expected_indices.append([j, k]) + expected_values.append(i * 3 + j) + expected_output.append( + sparse_tensor.SparseTensorValue( + indices=expected_indices, + values=expected_values, + dense_shape=[5, i * 3 + 5 - 1])) + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testNestedWindowSparse(self): + + def _sparse(i): + return sparse_tensor.SparseTensorValue( + indices=[[0]], values=(i * [1]), dense_shape=[1]) + + dataset = dataset_ops.Dataset.range(10).map(_sparse).window( + size=4, shift=2, + drop_remainder=True).flat_map(lambda x: x.batch(batch_size=4)).window( + size=3, shift=1, + drop_remainder=True).flat_map(lambda x: x.batch(batch_size=3)) + + expected_output = [ + sparse_tensor.SparseTensorValue( + indices=[[0, 0, 0], [0, 1, 0], [0, 2, 0], [0, 3, 0], [1, 0, 0], + [1, 1, 0], [1, 2, 0], [1, 3, 0], [2, 0, 0], [2, 1, 0], + [2, 2, 0], [2, 3, 0]], + values=[0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7], + dense_shape=[3, 4, 1]), + sparse_tensor.SparseTensorValue( + indices=[[0, 0, 0], [0, 1, 0], [0, 2, 0], [0, 3, 0], [1, 0, 0], + [1, 1, 0], [1, 2, 0], [1, 3, 0], [2, 0, 0], [2, 1, 0], + [2, 2, 0], [2, 3, 0]], + values=[2, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9], + dense_shape=[3, 4, 1]) + ] + self.assertDatasetProduces(dataset, expected_output=expected_output) + + def testWindowShapeError(self): + + def generator(): + yield [1.0, 2.0, 3.0] + yield [4.0, 5.0, 6.0] + yield [7.0, 8.0, 9.0, 10.0] + + dataset = dataset_ops.Dataset.from_generator( + generator, dtypes.float32, output_shapes=[None]).window( + size=3, shift=1).flat_map(lambda x: x.batch(batch_size=3)) + self.assertDatasetProduces( + dataset, + expected_error=( + errors.InvalidArgumentError, + r"Cannot batch tensors with different shapes in component 0. " + r"First element had shape \[3\] and element 2 had shape \[4\].")) + + def testWindowIgnoreErrors(self): + input_values = np.float32([1., np.nan, 2., np.nan, 3.]) + dataset = dataset_ops.Dataset.from_tensor_slices(input_values).map( + lambda x: array_ops.check_numerics(x, "message")).window( + size=2, shift=2, stride=2, + drop_remainder=True).flat_map(lambda x: x.batch(batch_size=2)) + self.assertDatasetProduces( + dataset, expected_output=[np.float32([1., 2.]), + np.float32([2., 3.])]) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/kernel_tests/zip_dataset_op_test.py b/tensorflow/python/data/kernel_tests/zip_dataset_op_test.py deleted file mode 100644 index 9d76387a34..0000000000 --- a/tensorflow/python/data/kernel_tests/zip_dataset_op_test.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Tests for the experimental input pipeline ops.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import numpy as np - -from tensorflow.python.data.kernel_tests import test_base -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import errors -from tensorflow.python.ops import array_ops -from tensorflow.python.platform import test - - -class ZipDatasetTest(test_base.DatasetTestBase): - - def testZipDataset(self): - component_placeholders = [ - array_ops.placeholder(dtypes.int64), - array_ops.placeholder(dtypes.int64), - array_ops.placeholder(dtypes.float64) - ] - - datasets = tuple([ - dataset_ops.Dataset.from_tensor_slices(component_placeholder) - for component_placeholder in component_placeholders - ]) - zipped = dataset_ops.Dataset.zip(datasets) - - iterator = zipped.make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - with self.cached_session() as sess: - equal_length_components = [ - np.tile(np.array([[1], [2], [3], [4]]), 20), - np.tile(np.array([[12], [13], [14], [15]]), 22), - np.array([37.0, 38.0, 39.0, 40.0]) - ] - sess.run(init_op, feed_dict={ph: value for ph, value in zip( - component_placeholders, equal_length_components)}) - for i in range(4): - results = sess.run(get_next) - for component, result_component in zip( - equal_length_components, results): - self.assertAllEqual(component[i], result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - variable_length_components = [[1, 2, 3, 4], [1, 2, 3, 4, 5], [1.0, 2.0]] - sess.run(init_op, feed_dict={ph: value for ph, value in zip( - component_placeholders, variable_length_components)}) - for i in range(2): - results = sess.run(get_next) - for component, result_component in zip( - variable_length_components, results): - self.assertAllEqual(component[i], result_component) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - def testNestedZipDataset(self): - component_placeholders = [ - array_ops.placeholder(dtypes.int64, shape=[4, 20]), - array_ops.placeholder(dtypes.int64, shape=[4, 22]), - array_ops.placeholder(dtypes.float64, shape=[4]) - ] - - datasets = [ - dataset_ops.Dataset.from_tensor_slices(component_placeholder) - for component_placeholder in component_placeholders - ] - zipped = dataset_ops.Dataset.zip((datasets[0], (datasets[1], datasets[2]))) - - iterator = zipped.make_initializable_iterator() - init_op = iterator.initializer - get_next = iterator.get_next() - - self.assertEqual([20], get_next[0].shape) - self.assertEqual([22], get_next[1][0].shape) - self.assertEqual([], get_next[1][1].shape) - - with self.cached_session() as sess: - equal_length_components = [ - np.tile(np.array([[1], [2], [3], [4]]), 20), - np.tile(np.array([[12], [13], [14], [15]]), 22), - np.array([37.0, 38.0, 39.0, 40.0]) - ] - sess.run(init_op, feed_dict={ph: value for ph, value in zip( - component_placeholders, equal_length_components)}) - for i in range(4): - result1, (result2, result3) = sess.run(get_next) - self.assertAllEqual(equal_length_components[0][i], result1) - self.assertAllEqual(equal_length_components[1][i], result2) - self.assertAllEqual(equal_length_components[2][i], result3) - with self.assertRaises(errors.OutOfRangeError): - sess.run(get_next) - - -if __name__ == "__main__": - test.main() diff --git a/tensorflow/python/data/kernel_tests/zip_test.py b/tensorflow/python/data/kernel_tests/zip_test.py new file mode 100644 index 0000000000..477c9fa7da --- /dev/null +++ b/tensorflow/python/data/kernel_tests/zip_test.py @@ -0,0 +1,101 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for `tf.data.Dataset.zip()`.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.data.kernel_tests import test_base +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import errors +from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class ZipTest(test_base.DatasetTestBase): + + def testZipDataset(self): + + def dataset_fn(components): + datasets = tuple([ + dataset_ops.Dataset.from_tensor_slices(component) + for component in components + ]) + return dataset_ops.Dataset.zip(datasets) + + equal_length_components = [ + np.tile(np.array([[1], [2], [3], [4]]), 20), + np.tile(np.array([[12], [13], [14], [15]]), 22), + np.array([37.0, 38.0, 39.0, 40.0]) + ] + + get_next = self.getNext(dataset_fn(equal_length_components)) + for i in range(4): + results = self.evaluate(get_next()) + for component, result_component in zip(equal_length_components, results): + self.assertAllEqual(component[i], result_component) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + variable_length_components = [[1, 2, 3, 4], [1, 2, 3, 4, 5], [1.0, 2.0]] + get_next = self.getNext(dataset_fn(variable_length_components)) + for i in range(2): + results = self.evaluate(get_next()) + for component, result_component in zip(variable_length_components, + results): + self.assertAllEqual(component[i], result_component) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + def testNestedZipDataset(self): + + equal_length_components = [ + np.tile(np.array([[1], [2], [3], [4]]), 20), + np.tile(np.array([[12], [13], [14], [15]]), 22), + np.array([37.0, 38.0, 39.0, 40.0]) + ] + datasets = [ + dataset_ops.Dataset.from_tensor_slices(component) + for component in equal_length_components + ] + dataset = dataset_ops.Dataset.zip((datasets[0], (datasets[1], datasets[2]))) + + self.assertEqual( + dataset.output_shapes, + (tensor_shape.TensorShape([20]), + (tensor_shape.TensorShape([22]), tensor_shape.TensorShape([])))) + + get_next = self.getNext(dataset) + for i in range(4): + result1, (result2, result3) = self.evaluate(get_next()) + self.assertAllEqual(equal_length_components[0][i], result1) + self.assertAllEqual(equal_length_components[1][i], result2) + self.assertAllEqual(equal_length_components[2][i], result3) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/ops/BUILD b/tensorflow/python/data/ops/BUILD index 18edc0872d..0c5acda180 100644 --- a/tensorflow/python/data/ops/BUILD +++ b/tensorflow/python/data/ops/BUILD @@ -14,6 +14,7 @@ py_library( "//tensorflow/python:control_flow_ops", "//tensorflow/python:dataset_ops_gen", "//tensorflow/python:dtypes", + "//tensorflow/python:experimental_dataset_ops_gen", "//tensorflow/python:framework_ops", "//tensorflow/python:function", "//tensorflow/python:math_ops", @@ -25,8 +26,12 @@ py_library( "//tensorflow/python:tensor_shape", "//tensorflow/python:tensor_util", "//tensorflow/python:util", + "//tensorflow/python/data/experimental/ops:filter_for_shard_ops", + "//tensorflow/python/data/experimental/ops:optimization_options", "//tensorflow/python/data/experimental/ops:stats_options", + "//tensorflow/python/data/experimental/ops:threading_options", "//tensorflow/python/data/util:nest", + "//tensorflow/python/data/util:options", "//tensorflow/python/data/util:random_seed", "//tensorflow/python/data/util:sparse", "//tensorflow/python/data/util:structure", diff --git a/tensorflow/python/data/ops/dataset_ops.py b/tensorflow/python/data/ops/dataset_ops.py index 3836a68e7d..ba6d20373e 100644 --- a/tensorflow/python/data/ops/dataset_ops.py +++ b/tensorflow/python/data/ops/dataset_ops.py @@ -18,6 +18,7 @@ from __future__ import division from __future__ import print_function import abc +import functools import threading import warnings @@ -25,11 +26,16 @@ import numpy as np import six from tensorflow.python.compat import compat +from tensorflow.python.data.experimental.ops import filter_for_shard_ops +from tensorflow.python.data.experimental.ops import optimization_options from tensorflow.python.data.experimental.ops import stats_options +from tensorflow.python.data.experimental.ops import threading_options from tensorflow.python.data.ops import iterator_ops from tensorflow.python.data.util import nest +from tensorflow.python.data.util import options as options_lib from tensorflow.python.data.util import random_seed from tensorflow.python.data.util import sparse +from tensorflow.python.data.util import structure as structure_lib from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes @@ -43,6 +49,7 @@ from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops from tensorflow.python.ops import gen_io_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import script_ops @@ -52,9 +59,12 @@ from tensorflow.python.util import function_utils from tensorflow.python.util.tf_export import tf_export -@tf_export("data.Dataset") +ops.NotDifferentiable("ReduceDataset") + + +@tf_export("data.Dataset", v1=[]) @six.add_metaclass(abc.ABCMeta) -class Dataset(object): +class DatasetV2(object): """Represents a potentially large set of elements. A `Dataset` can be used to represent an input pipeline as a @@ -62,9 +72,6 @@ class Dataset(object): plan" of transformations that act on those elements. """ - def __init__(self): - pass - def _as_serialized_graph(self): """Produces serialized graph representation of the dataset. @@ -89,6 +96,37 @@ class Dataset(object): raise NotImplementedError("Dataset._inputs") + def _has_captured_ref(self): + """Whether this dataset uses a function that captures ref variables. + + Returns: + A boolean, which if true indicates that the dataset or one of its inputs + uses a function that captures ref variables. + """ + if context.executing_eagerly(): + # RefVariables are not supported in eager mode + return False + + def is_tensor_or_parent_ref(tensor): + if tensor.dtype._is_ref_dtype: # pylint: disable=protected-access + return True + return any([is_tensor_or_parent_ref(x) for x in tensor.op.inputs]) + + for fn in self._functions(): + if any([is_tensor_or_parent_ref(t) for t in fn.function.captured_inputs]): + return True + + return any( + [input_dataset._has_captured_ref() for input_dataset in self._inputs()]) # pylint: disable=protected-access + + def _functions(self): + """Returns a list of functions associated with this dataset. + + Returns: + A list of `StructuredFunctionWrapper` objects. + """ + return [] + def options(self): """Returns the options for this dataset and its inputs. @@ -107,9 +145,26 @@ class Dataset(object): dataset = self options = self.options() + if options.experimental_threading is not None: + t_options = options.experimental_threading + if t_options.private_threadpool_size is not None: + dataset = _PrivateThreadPoolDataset(dataset, + t_options.private_threadpool_size) + if t_options.max_intra_op_parallelism is not None: + dataset = _MaxIntraOpParallelismDataset( + dataset, t_options.max_intra_op_parallelism) static_optimizations = options._static_optimizations() # pylint: disable=protected-access if static_optimizations: - dataset = _OptimizeDataset(dataset, static_optimizations) + if self._has_captured_ref(): + warnings.warn( + "tf.data static optimizations are not compatible with tf.Variable. " + "The following optimizations will be disabled: %s. To enable " + "optimizations, use resource variables instead by calling " + "`tf.enable_resource_variables()` at the start of the program." % + ", ".join(static_optimizations)) + else: + dataset = _OptimizeDataset(dataset, static_optimizations) + if options.experimental_autotune is not False: dataset = _ModelDataset(dataset) if options.experimental_stats and options.experimental_stats.aggregator: # pylint: disable=line-too-long @@ -119,51 +174,6 @@ class Dataset(object): options.experimental_stats.counter_prefix) return dataset - def make_initializable_iterator(self, shared_name=None): - """Creates an `Iterator` for enumerating the elements of this dataset. - - Note: The returned iterator will be in an uninitialized state, - and you must run the `iterator.initializer` operation before using it: - - ```python - dataset = ... - iterator = dataset.make_initializable_iterator() - # ... - sess.run(iterator.initializer) - ``` - - Args: - shared_name: (Optional.) If non-empty, the returned iterator will be - shared under the given name across multiple sessions that share the - same devices (e.g. when using a remote server). - - Returns: - An `Iterator` over the elements of this dataset. - - Raises: - RuntimeError: If eager execution is enabled. - """ - if context.executing_eagerly(): - raise RuntimeError( - "dataset.make_initializable_iterator is not supported when eager " - "execution is enabled.") - dataset = self._apply_options() - if shared_name is None: - shared_name = "" - if compat.forward_compatible(2018, 8, 3): - iterator_resource = gen_dataset_ops.iterator_v2( - container="", shared_name=shared_name, **flat_structure(self)) - else: - iterator_resource = gen_dataset_ops.iterator( - container="", shared_name=shared_name, **flat_structure(self)) - with ops.colocate_with(iterator_resource): - initializer = gen_dataset_ops.make_iterator( - dataset._as_variant_tensor(), # pylint: disable=protected-access - iterator_resource) - return iterator_ops.Iterator(iterator_resource, initializer, - dataset.output_types, dataset.output_shapes, - dataset.output_classes) - def __iter__(self): """Creates an `Iterator` for enumerating the elements of this dataset. @@ -183,55 +193,6 @@ class Dataset(object): raise RuntimeError("dataset.__iter__() is only supported when eager " "execution is enabled.") - def make_one_shot_iterator(self): - """Creates an `Iterator` for enumerating the elements of this dataset. - - Note: The returned iterator will be initialized automatically. - A "one-shot" iterator does not currently support re-initialization. - - Returns: - An `Iterator` over the elements of this dataset. - """ - if context.executing_eagerly(): - dataset = self._apply_options() - return iterator_ops.EagerIterator(dataset) - - graph_level_seed, op_level_seed = core_random_seed.get_seed(None) - - # NOTE(mrry): We capture by value here to ensure that `_make_dataset()` is - # a 0-argument function. - @function.Defun(capture_by_value=True) - def _make_dataset(): - """Factory function for a dataset.""" - # NOTE(mrry): `Defun` does not capture the graph-level seed from the - # enclosing graph, so if a graph-level seed is present we set the local - # graph seed based on a combination of the graph- and op-level seeds. - if graph_level_seed is not None: - assert op_level_seed is not None - core_random_seed.set_random_seed( - (graph_level_seed + 87654321 * op_level_seed) % (2 ** 63 - 1)) - - dataset = self._apply_options() - return dataset._as_variant_tensor() # pylint: disable=protected-access - - try: - _make_dataset.add_to_graph(ops.get_default_graph()) - except ValueError as err: - if "Cannot capture a stateful node" in str(err): - raise ValueError( - "Failed to create a one-shot iterator for a dataset. " - "`Dataset.make_one_shot_iterator()` does not support datasets that " - "capture stateful objects, such as a `Variable` or `LookupTable`. " - "In these cases, use `Dataset.make_initializable_iterator()`. " - "(Original error: %s)" % err) - else: - six.reraise(ValueError, err) - - return iterator_ops.Iterator( - gen_dataset_ops.one_shot_iterator( - dataset_factory=_make_dataset, **flat_structure(self)), - None, self.output_types, self.output_shapes, self.output_classes) - @abc.abstractproperty def output_classes(self): """Returns the class of each component of an element of this dataset. @@ -279,9 +240,10 @@ class Dataset(object): Note that if `tensors` contains a NumPy array, and eager execution is not enabled, the values will be embedded in the graph as one or more `tf.constant` operations. For large datasets (> 1 GB), this can waste - memory and run into byte limits of graph serialization. If tensors contains - one or more large NumPy arrays, consider the alternative described in - [this guide](https://tensorflow.org/guide/datasets#consuming_numpy_arrays). + memory and run into byte limits of graph serialization. If `tensors` + contains one or more large NumPy arrays, consider the alternative described + in [this + guide](https://tensorflow.org/guide/datasets#consuming_numpy_arrays). Args: tensors: A nested structure of tensors. @@ -298,9 +260,10 @@ class Dataset(object): Note that if `tensors` contains a NumPy array, and eager execution is not enabled, the values will be embedded in the graph as one or more `tf.constant` operations. For large datasets (> 1 GB), this can waste - memory and run into byte limits of graph serialization. If tensors contains - one or more large NumPy arrays, consider the alternative described in - [this guide](https://tensorflow.org/guide/datasets#consuming_numpy_arrays). + memory and run into byte limits of graph serialization. If `tensors` + contains one or more large NumPy arrays, consider the alternative described + in [this guide]( + https://tensorflow.org/guide/datasets#consuming_numpy_arrays). Args: tensors: A nested structure of tensors, each having the same size in the @@ -311,19 +274,6 @@ class Dataset(object): """ return TensorSliceDataset(tensors) - @staticmethod - @deprecation.deprecated(None, "Use `tf.data.Dataset.from_tensor_slices()`.") - def from_sparse_tensor_slices(sparse_tensor): - """Splits each rank-N `tf.SparseTensor` in this dataset row-wise. - - Args: - sparse_tensor: A `tf.SparseTensor`. - - Returns: - Dataset: A `Dataset` of rank-(N-1) sparse tensors. - """ - return SparseTensorSliceDataset(sparse_tensor) - class _GeneratorState(object): """Stores outstanding iterators created from a Python generator. @@ -373,17 +323,19 @@ class Dataset(object): ```python import itertools + tf.enable_eager_execution() def gen(): for i in itertools.count(1): yield (i, [1] * i) - ds = Dataset.from_generator( + ds = tf.data.Dataset.from_generator( gen, (tf.int64, tf.int64), (tf.TensorShape([]), tf.TensorShape([None]))) - value = ds.make_one_shot_iterator().get_next() - sess.run(value) # (1, array([1])) - sess.run(value) # (2, array([1, 1])) + for value in ds.take(2): + print value + # (1, array([1])) + # (2, array([1, 1])) ``` NOTE: The current implementation of `Dataset.from_generator()` uses @@ -435,7 +387,7 @@ class Dataset(object): flattened_types = [dtypes.as_dtype(dt) for dt in nest.flatten(output_types)] flattened_shapes = nest.flatten(output_shapes) - generator_state = Dataset._GeneratorState(generator) + generator_state = DatasetV2._GeneratorState(generator) def get_iterator_id_fn(unused_dummy): """Creates a unique `iterator_id` for each pass over the dataset. @@ -580,7 +532,7 @@ class Dataset(object): ``` Args: - *args: follow same semantics as python's xrange. + *args: follows the same semantics as python's xrange. len(args) == 1 -> start = 0, stop = args[0], step = 1 len(args) == 2 -> start = args[0], stop = args[1], step = 1 len(args) == 3 -> start = args[0], stop = args[1, stop = args[2] @@ -820,78 +772,6 @@ class Dataset(object): """ return SkipDataset(self, count) - def shard(self, num_shards, index): - """Creates a `Dataset` that includes only 1/`num_shards` of this dataset. - - This dataset operator is very useful when running distributed training, as - it allows each worker to read a unique subset. - - When reading a single input file, you can skip elements as follows: - - ```python - d = tf.data.TFRecordDataset(FLAGS.input_file) - d = d.shard(FLAGS.num_workers, FLAGS.worker_index) - d = d.repeat(FLAGS.num_epochs) - d = d.shuffle(FLAGS.shuffle_buffer_size) - d = d.map(parser_fn, num_parallel_calls=FLAGS.num_map_threads) - ``` - - Important caveats: - - - Be sure to shard before you use any randomizing operator (such as - shuffle). - - Generally it is best if the shard operator is used early in the dataset - pipeline. For example, when reading from a set of TFRecord files, shard - before converting the dataset to input samples. This avoids reading every - file on every worker. The following is an example of an efficient - sharding strategy within a complete pipeline: - - ```python - d = Dataset.list_files(FLAGS.pattern) - d = d.shard(FLAGS.num_workers, FLAGS.worker_index) - d = d.repeat(FLAGS.num_epochs) - d = d.shuffle(FLAGS.shuffle_buffer_size) - d = d.interleave(tf.data.TFRecordDataset, - cycle_length=FLAGS.num_readers, block_length=1) - d = d.map(parser_fn, num_parallel_calls=FLAGS.num_map_threads) - ``` - - Args: - num_shards: A `tf.int64` scalar `tf.Tensor`, representing the number of - shards operating in parallel. - index: A `tf.int64` scalar `tf.Tensor`, representing the worker index. - - Returns: - Dataset: A `Dataset`. - - Raises: - ValueError: if `num_shards` or `index` are illegal values. Note: error - checking is done on a best-effort basis, and aren't guaranteed to be - caught upon dataset creation. (e.g. providing in a placeholder tensor - bypasses the early checking, and will instead result in an error during - a session.run call.) - """ - num_shards = ops.convert_to_tensor( - num_shards, name="num_shards", dtype=dtypes.int64) - num_shards_static = tensor_util.constant_value(num_shards) - index = ops.convert_to_tensor(index, name="index", dtype=dtypes.int64) - index_static = tensor_util.constant_value(index) - - if num_shards_static is not None and num_shards_static < 1: - raise ValueError("num_shards must be >= 1; got: %s" % num_shards_static) - if index_static is not None and index_static < 0: - raise ValueError("index must be >= 0; got: %s" % index_static) - if (index_static is not None and num_shards_static is not None and - index_static >= num_shards_static): - raise ValueError("index must be <= num_shards; %s is not < %s" % - (index_static, num_shards_static)) - - def filter_fn(elem_index, _): - mod_result = math_ops.mod(elem_index, num_shards) - return math_ops.equal(mod_result, index) - - return self._enumerate().filter(filter_fn).map(lambda _, elem: elem) - def batch(self, batch_size, drop_remainder=False): """Combines consecutive elements of this dataset into batches. @@ -906,7 +786,7 @@ class Dataset(object): batch_size: A `tf.int64` scalar `tf.Tensor`, representing the number of consecutive elements of this dataset to combine in a single batch. drop_remainder: (Optional.) A `tf.bool` scalar `tf.Tensor`, representing - whether the last batch should be dropped in the case its has fewer than + whether the last batch should be dropped in the case it has fewer than `batch_size` elements; the default behavior is not to drop the smaller batch. @@ -963,7 +843,7 @@ class Dataset(object): respective components. Defaults are `0` for numeric types and the empty string for string types. drop_remainder: (Optional.) A `tf.bool` scalar `tf.Tensor`, representing - whether the last batch should be dropped in the case its has fewer than + whether the last batch should be dropped in the case it has fewer than `batch_size` elements; the default behavior is not to drop the smaller batch. @@ -1217,7 +1097,7 @@ class Dataset(object): dataset. """ dataset = transformation_func(self) - if not isinstance(dataset, Dataset): + if not isinstance(dataset, DatasetV2): raise TypeError("`transformation_func` must return a Dataset.") dataset._input_datasets = [self] # pylint: disable=protected-access return dataset @@ -1384,10 +1264,9 @@ class Dataset(object): def with_options(self, options): """Returns a new `tf.data.Dataset` with the given options set. - The options are "global" in the sense they apply to the entire input - pipeline in which the `with_options` transformation is used. If options are - set multiple times, they are merged if possible (see - `tf.data.Options.merge()` for details). + The options are "global" in the sense they apply to the entire dataset. + If options are set multiple times, they are merged as long as different + options do not use different non-default values. Args: options: A `tf.data.Options` that identifies the options the use. @@ -1396,164 +1275,497 @@ class Dataset(object): Dataset: A `Dataset` with the given options. Raises: - ValueError: if options are set more than once + ValueError: when an option is set more than once to a non-default value """ return _OptionsDataset(self, options) -@tf_export("data.Options") -class Options(object): - """Represents options for tf.data.Dataset. +@tf_export(v1=["data.Dataset"]) +class DatasetV1(DatasetV2): + """Represents a potentially large set of elements. - An `Options` object can be for instance used to control which static - optimizations to apply or whether to use performance modeling to dynamically - tune the parallelism of operations such as `tf.data.Dataset.map` or - `tf.data.Dataset.interleave`. + A `Dataset` can be used to represent an input pipeline as a + collection of elements (nested structures of tensors) and a "logical + plan" of transformations that act on those elements. """ - for _name, _ty, _docstring in [ - ("experimental_autotune", bool, - "Whether to dynamically adjust the values of tunable parameters (e.g. " - "degrees of parallelism)."), - ("experimental_deterministic", bool, - "Whether the outputs need to be produced in deterministic order."), - ("experimental_filter_fusion", bool, - "Whether to fuse filter transformations."), - ("experimental_hoist_random_uniform", bool, - "Whether to hoist `tf.random_uniform()` ops out of map transformations." - ), - ("experimental_stats", stats_options.StatsOptions, - "Associate the given statistics options with the dataset pipeline."), - ("experimental_map_and_batch_fusion", bool, - "Whether to fuse map and batch transformations."), - ("experimental_map_and_filter_fusion", bool, - "Whether to fuse map and filter transformations."), - ("experimental_map_fusion", bool, "Whether to fuse map transformations."), - ("experimental_map_parallelization", bool, - "Whether to parallelize stateless map transformations."), - ("experimental_map_vectorization", bool, - "Whether to vectorize map transformations."), - ("experimental_noop_elimination", bool, - "Whether to eliminate no-op transformations."), - ("experimental_shuffle_and_repeat_fusion", bool, - "Whether to fuse shuffle and repeat transformations."), - ("experimental_numa_aware", bool, - "Whether to use NUMA-aware operations."), - ]: - - def _make_getter(name): # pylint: disable=no-self-argument - - def getter(self): - return getattr(self, "_" + name) - - return getter - - def _make_setter(name, ty): # pylint: disable=no-self-argument - - def setter(self, value): - if not isinstance(value, ty): - raise TypeError( - "Attempting to set the option %s to incompatible value: %r when " - "it expects %r" % (name, value, ty)) - setattr(self, "_" + name, value) - - return setter - - vars()["_" + _name] = None - vars()[_name] = property( - _make_getter(_name), _make_setter(_name, _ty), None, _docstring) def __init__(self): pass - def __eq__(self, other): - if isinstance(other, self.__class__): - return self.__dict__ == other.__dict__ - else: - return False + @deprecation.deprecated( + None, "Use `for ... in dataset:` to iterate over a dataset. If using " + "`tf.estimator`, return the `Dataset` object directly from your input " + "function. As a last resort, you can use " + "`tf.compat.v1.data.make_one_shot_iterator(dataset)`.") + def make_one_shot_iterator(self): + """Creates an `Iterator` for enumerating the elements of this dataset. - def __ne__(self, other): - return not self.__eq__(other) + Note: The returned iterator will be initialized automatically. + A "one-shot" iterator does not currently support re-initialization. - def _static_optimizations(self): - """Produces the list of enabled static optimizations.""" - experimental_optimizations = [ - "filter_fusion", - "hoist_random_uniform", - "map_and_batch_fusion", - "map_and_filter_fusion", - "map_fusion", - "map_parallelization", - "map_vectorization", - "noop_elimination", - "shuffle_and_repeat_fusion", - ] - result = [] - for exp_opt in experimental_optimizations: - if getattr(self, "experimental_" + exp_opt): - result.append(exp_opt) + Returns: + An `Iterator` over the elements of this dataset. + """ + if context.executing_eagerly(): + dataset = self._apply_options() + return iterator_ops.EagerIterator(dataset) - if getattr(self, "experimental_numa_aware"): - result.append("make_numa_aware") - if getattr(self, "experimental_deterministic") is False: - result.append("make_sloppy") - experimental_stats_options = getattr(self, "experimental_stats") - if experimental_stats_options and getattr(experimental_stats_options, - "latency_all_edges"): - result.append("latency_all_edges") - return result + graph_level_seed, op_level_seed = core_random_seed.get_seed(None) - def merge(self, options): - """Merges itself with the given `tf.data.Options`. + # NOTE(mrry): We capture by value here to ensure that `_make_dataset()` is + # a 0-argument function. + @function.Defun(capture_by_value=True) + def _make_dataset(): + """Factory function for a dataset.""" + # NOTE(mrry): `Defun` does not capture the graph-level seed from the + # enclosing graph, so if a graph-level seed is present we set the local + # graph seed based on a combination of the graph- and op-level seeds. + if graph_level_seed is not None: + assert op_level_seed is not None + core_random_seed.set_random_seed( + (graph_level_seed + 87654321 * op_level_seed) % (2 ** 63 - 1)) - The given `tf.data.Options` can be merged as long as there does not exist an - attribute that is set to different values in `self` and `options`. + dataset = self._apply_options() + return dataset._as_variant_tensor() # pylint: disable=protected-access - Args: - options: a `tf.data.Options` to merge with + try: + _make_dataset.add_to_graph(ops.get_default_graph()) + except ValueError as err: + if "Cannot capture a stateful node" in str(err): + raise ValueError( + "Failed to create a one-shot iterator for a dataset. " + "`Dataset.make_one_shot_iterator()` does not support datasets that " + "capture stateful objects, such as a `Variable` or `LookupTable`. " + "In these cases, use `Dataset.make_initializable_iterator()`. " + "(Original error: %s)" % err) + else: + six.reraise(ValueError, err) - Raises: - ValueError: if the given `tf.data.Options` cannot be merged + return iterator_ops.Iterator( + gen_dataset_ops.one_shot_iterator( + dataset_factory=_make_dataset, **flat_structure(self)), + None, self.output_types, self.output_shapes, self.output_classes) - Returns: - New `tf.data.Options()` object which is the result of merging self with - the input `tf.data.Options`. - """ - result = Options() - for other in [self, options]: - for name in [ - "experimental_autotune", - "experimental_deterministic", - "experimental_filter_fusion", - "experimental_hoist_random_uniform", - "experimental_map_and_batch_fusion", - "experimental_map_and_filter_fusion", - "experimental_map_fusion", - "experimental_map_parallelization", - "experimental_map_vectorization", - "experimental_noop_elimination", - "experimental_numa_aware", - "experimental_shuffle_and_repeat_fusion", - "experimental_stats", - ]: - this = getattr(result, name) - that = getattr(other, name) - if that is not None: - if this is None: - setattr(result, name, that) - elif this != that: - raise ValueError( - "Cannot merge incompatible values of option: %s" % (name)) - return result + @deprecation.deprecated( + None, "Use `for ... in dataset:` to iterate over a dataset. If using " + "`tf.estimator`, return the `Dataset` object directly from your input " + "function. As a last resort, you can use " + "`tf.compat.v1.data.make_initializable_iterator(dataset)`.") + def make_initializable_iterator(self, shared_name=None): + """Creates an `Iterator` for enumerating the elements of this dataset. + Note: The returned iterator will be in an uninitialized state, + and you must run the `iterator.initializer` operation before using it: -class DatasetSource(Dataset): - """Abstract class representing a dataset with no inputs.""" + ```python + dataset = ... + iterator = dataset.make_initializable_iterator() + # ... + sess.run(iterator.initializer) + ``` + + Args: + shared_name: (Optional.) If non-empty, the returned iterator will be + shared under the given name across multiple sessions that share the + same devices (e.g. when using a remote server). + + Returns: + An `Iterator` over the elements of this dataset. + + Raises: + RuntimeError: If eager execution is enabled. + """ + if context.executing_eagerly(): + raise RuntimeError( + "dataset.make_initializable_iterator is not supported when eager " + "execution is enabled.") + dataset = self._apply_options() + if shared_name is None: + shared_name = "" + if compat.forward_compatible(2018, 8, 3): + iterator_resource = gen_dataset_ops.iterator_v2( + container="", shared_name=shared_name, **flat_structure(self)) + else: + iterator_resource = gen_dataset_ops.iterator( + container="", shared_name=shared_name, **flat_structure(self)) + with ops.colocate_with(iterator_resource): + initializer = gen_dataset_ops.make_iterator( + dataset._as_variant_tensor(), # pylint: disable=protected-access + iterator_resource) + return iterator_ops.Iterator(iterator_resource, initializer, + dataset.output_types, dataset.output_shapes, + dataset.output_classes) + + @staticmethod + @functools.wraps(DatasetV2.from_tensors) + def from_tensors(tensors): + return DatasetV1Adapter(DatasetV2.from_tensors(tensors)) + + @staticmethod + @functools.wraps(DatasetV2.from_tensor_slices) + def from_tensor_slices(tensors): + return DatasetV1Adapter(DatasetV2.from_tensor_slices(tensors)) + + @staticmethod + @deprecation.deprecated(None, "Use `tf.data.Dataset.from_tensor_slices()`.") + def from_sparse_tensor_slices(sparse_tensor): + """Splits each rank-N `tf.SparseTensor` in this dataset row-wise. + + Args: + sparse_tensor: A `tf.SparseTensor`. + + Returns: + Dataset: A `Dataset` of rank-(N-1) sparse tensors. + """ + return DatasetV1Adapter(SparseTensorSliceDataset(sparse_tensor)) + + @staticmethod + @functools.wraps(DatasetV2.from_generator) + def from_generator(generator, output_types, output_shapes=None, args=None): + return DatasetV1Adapter(DatasetV2.from_generator( + generator, output_types, output_shapes, args)) + + @staticmethod + @functools.wraps(DatasetV2.range) + def range(*args): + return DatasetV1Adapter(DatasetV2.range(*args)) + + @staticmethod + @functools.wraps(DatasetV2.zip) + def zip(datasets): + return DatasetV1Adapter(DatasetV2.zip(datasets)) + + @functools.wraps(DatasetV2.concatenate) + def concatenate(self, dataset): + return DatasetV1Adapter(super(DatasetV1, self).concatenate(dataset)) + + @functools.wraps(DatasetV2.prefetch) + def prefetch(self, buffer_size): + return DatasetV1Adapter(super(DatasetV1, self).prefetch(buffer_size)) + + @staticmethod + @functools.wraps(DatasetV2.list_files) + def list_files(file_pattern, shuffle=None, seed=None): + return DatasetV1Adapter(DatasetV2.list_files(file_pattern, shuffle, seed)) + + @functools.wraps(DatasetV2.repeat) + def repeat(self, count=None): + return DatasetV1Adapter(super(DatasetV1, self).repeat(count)) + + @functools.wraps(DatasetV2.shuffle) + def shuffle(self, buffer_size, seed=None, reshuffle_each_iteration=None): + return DatasetV1Adapter(super(DatasetV1, self).shuffle( + buffer_size, seed, reshuffle_each_iteration)) + + @functools.wraps(DatasetV2.cache) + def cache(self, filename=""): + return DatasetV1Adapter(super(DatasetV1, self).cache(filename)) + + @functools.wraps(DatasetV2.take) + def take(self, count): + return DatasetV1Adapter(super(DatasetV1, self).take(count)) + + @functools.wraps(DatasetV2.skip) + def skip(self, count): + return DatasetV1Adapter(super(DatasetV1, self).skip(count)) + + @deprecation.deprecated( + None, "Use `dataset.apply(tf.data.experimental.filter_for_shard(...))`.") + def shard(self, num_shards, index): + """Creates a `Dataset` that includes only 1/`num_shards` of this dataset. + + This dataset operator is very useful when running distributed training, as + it allows each worker to read a unique subset. + + When reading a single input file, you can skip elements as follows: + + ```python + d = tf.data.TFRecordDataset(FLAGS.input_file) + d = d.shard(FLAGS.num_workers, FLAGS.worker_index) + d = d.repeat(FLAGS.num_epochs) + d = d.shuffle(FLAGS.shuffle_buffer_size) + d = d.map(parser_fn, num_parallel_calls=FLAGS.num_map_threads) + ``` + + Important caveats: + + - Be sure to shard before you use any randomizing operator (such as + shuffle). + - Generally it is best if the shard operator is used early in the dataset + pipeline. For example, when reading from a set of TFRecord files, shard + before converting the dataset to input samples. This avoids reading every + file on every worker. The following is an example of an efficient + sharding strategy within a complete pipeline: + + ```python + d = Dataset.list_files(FLAGS.pattern) + d = d.shard(FLAGS.num_workers, FLAGS.worker_index) + d = d.repeat(FLAGS.num_epochs) + d = d.shuffle(FLAGS.shuffle_buffer_size) + d = d.interleave(tf.data.TFRecordDataset, + cycle_length=FLAGS.num_readers, block_length=1) + d = d.map(parser_fn, num_parallel_calls=FLAGS.num_map_threads) + ``` + + Args: + num_shards: A `tf.int64` scalar `tf.Tensor`, representing the number of + shards operating in parallel. + index: A `tf.int64` scalar `tf.Tensor`, representing the worker index. + + Returns: + Dataset: A `Dataset`. + + Raises: + ValueError: if `num_shards` or `index` are illegal values. Note: error + checking is done on a best-effort basis, and errors aren't guaranteed + to be caught upon dataset creation. (e.g. providing in a placeholder + tensor bypasses the early checking, and will instead result in an error + during a session.run call.) + """ + return self.apply(filter_for_shard_ops.filter_for_shard(num_shards, index)) + + @functools.wraps(DatasetV2.batch) + def batch(self, batch_size, drop_remainder=False): + return DatasetV1Adapter(super(DatasetV1, self).batch( + batch_size, drop_remainder)) + + @functools.wraps(DatasetV2.padded_batch) + def padded_batch(self, + batch_size, + padded_shapes, + padding_values=None, + drop_remainder=False): + return DatasetV1Adapter(super(DatasetV1, self).padded_batch( + batch_size, padded_shapes, padding_values, drop_remainder)) + + @functools.wraps(DatasetV2.map) + def map(self, map_func, num_parallel_calls=None): + return DatasetV1Adapter(super(DatasetV1, self).map( + map_func, num_parallel_calls)) + + @functools.wraps(DatasetV2.flat_map) + def flat_map(self, map_func): + return DatasetV1Adapter(super(DatasetV1, self).flat_map(map_func)) + + @functools.wraps(DatasetV2.interleave) + def interleave(self, + map_func, + cycle_length, + block_length=1, + num_parallel_calls=None): + return DatasetV1Adapter(super(DatasetV1, self).interleave( + map_func, cycle_length, block_length, num_parallel_calls)) + + @functools.wraps(DatasetV2.filter) + def filter(self, predicate): + return DatasetV1Adapter(super(DatasetV1, self).filter(predicate)) + + @functools.wraps(DatasetV2.apply) + def apply(self, transformation_func): + return DatasetV1Adapter(super(DatasetV1, self).apply(transformation_func)) + + @functools.wraps(DatasetV2.window) + def window(self, size, shift=None, stride=1, drop_remainder=False): + return DatasetV1Adapter(super(DatasetV1, self).window( + size, shift, stride, drop_remainder)) + + @functools.wraps(DatasetV2.with_options) + def with_options(self, options): + return DatasetV1Adapter(super(DatasetV1, self).with_options(options)) + + +# TODO(b/119044825): Until all `tf.data` unit tests are converted to V2, keep +# this alias in place. +Dataset = DatasetV1 + + +class DatasetV1Adapter(DatasetV1): + """Wraps a V2 `Dataset` object in the `tf.compat.v1.data.Dataset` API.""" + + def __init__(self, dataset): + super(DatasetV1Adapter, self).__init__() + self._dataset = dataset + + def _as_variant_tensor(self): + return self._dataset._as_variant_tensor() # pylint: disable=protected-access + + def _has_captured_ref(self): + return self._dataset._has_captured_ref() # pylint: disable=protected-access + + def _inputs(self): + return self._dataset._inputs() # pylint: disable=protected-access + + def options(self): + return self._dataset.options() + + @property + def output_classes(self): + return self._dataset.output_classes + + @property + def output_shapes(self): + return self._dataset.output_shapes + + @property + def output_types(self): + return self._dataset.output_types + + def __iter__(self): + return iter(self._dataset) + + +@tf_export(v1=["data.make_one_shot_iterator"]) +def make_one_shot_iterator(dataset): + """Creates a `tf.data.Iterator` for enumerating the elements of a dataset. + + Note: The returned iterator will be initialized automatically. + A "one-shot" iterator does not support re-initialization. + + Args: + dataset: A `tf.data.Dataset`. + + Returns: + A `tf.data.Iterator` over the elements of this dataset. + """ + try: + # Call the defined `make_one_shot_iterator()` if there is one, because some + # datasets (e.g. for prefetching) override its behavior. + return dataset.make_one_shot_iterator() + except AttributeError: + return DatasetV1Adapter(dataset).make_one_shot_iterator() + + +@tf_export(v1=["data.make_initializable_iterator"]) +def make_initializable_iterator(dataset): + """Creates a `tf.data.Iterator` for enumerating the elements of a dataset. + + Note: The returned iterator will be in an uninitialized state, + and you must run the `iterator.initializer` operation before using it: + + ```python + dataset = ... + iterator = dataset.make_initializable_iterator() + # ... + sess.run(iterator.initializer) + ``` + + Args: + dataset: A `tf.data.Dataset`. + + Returns: + A `tf.data.Iterator` over the elements of `dataset`. + + Raises: + RuntimeError: If eager execution is enabled. + """ + try: + # Call the defined `make_one_shot_iterator()` if there is one, because some + # datasets (e.g. for prefetching) override its behavior. + return dataset.make_initializable_iterator() + except AttributeError: + return DatasetV1Adapter(dataset).make_initializable_iterator() + + +@tf_export("data.Options") +class Options(options_lib.OptionsBase): + """Represents options for tf.data.Dataset. + + An `Options` object can be, for instance, used to control which static + optimizations to apply or whether to use performance modeling to dynamically + tune the parallelism of operations such as `tf.data.Dataset.map` or + `tf.data.Dataset.interleave`. + """ + + experimental_autotune = options_lib.create_option( + name="experimental_autotune", + ty=bool, + docstring= + "Whether to dynamically adjust the values of tunable parameters (e.g. " + "degrees of parallelism).") + + experimental_deterministic = options_lib.create_option( + name="experimental_deterministic", + ty=bool, + docstring= + "Whether to dynamically adjust the values of tunable parameters (e.g. " + "degrees of parallelism).") + + experimental_numa_aware = options_lib.create_option( + name="experimental_numa_aware", + ty=bool, + docstring="Whether to use NUMA-aware operations.") + + experimental_optimization = options_lib.create_option( + name="experimental_optimization", + ty=optimization_options.OptimizationOptions, + docstring="Associates the given optimization options with the dataset.") + + experimental_stats = options_lib.create_option( + name="experimental_stats", + ty=stats_options.StatsOptions, + docstring="Associates the given statistics options with the dataset.") + + experimental_threading = options_lib.create_option( + name="experimental_threading", + ty=threading_options.ThreadingOptions, + docstring="Associates the given threading options with the dataset.") + + def _static_optimizations(self): + """Produces the list of enabled static optimizations.""" + + result = [] + exp_optimization_options = self.experimental_optimization + if exp_optimization_options: + optimizations = [ + "filter_fusion", + "hoist_random_uniform", + "map_and_batch_fusion", + "map_and_filter_fusion", + "map_fusion", + "map_parallelization", + "map_vectorization", + "noop_elimination", + "shuffle_and_repeat_fusion", + ] + for optimization in optimizations: + if getattr(exp_optimization_options, optimization): + result.append(optimization) + if self.experimental_numa_aware: + result.append("make_numa_aware") + if self.experimental_deterministic is False: + result.append("make_sloppy") + exp_stats_options = self.experimental_stats + if exp_stats_options and exp_stats_options.latency_all_edges: + result.append("latency_all_edges") + return result + + def merge(self, options): + """Merges itself with the given `tf.data.Options`. + + The given `tf.data.Options` can be merged as long as there does not exist an + attribute that is set to different values in `self` and `options`. + + Args: + options: a `tf.data.Options` to merge with + + Raises: + ValueError: if the given `tf.data.Options` cannot be merged + + Returns: + New `tf.data.Options()` object which is the result of merging self with + the input `tf.data.Options`. + """ + return options_lib.merge_options(self, options) + + +class DatasetSource(DatasetV2): + """Abstract class representing a dataset with no inputs.""" def _inputs(self): return [] -class UnaryDataset(Dataset): +class UnaryDataset(DatasetV2): """Abstract class representing a dataset with one input.""" def __init__(self, input_dataset): @@ -1564,6 +1776,22 @@ class UnaryDataset(Dataset): return [self._input_dataset] +class UnaryUnchangedStructureDataset(UnaryDataset): + """Represents a unary dataset with the same input and output structure.""" + + @property + def output_classes(self): + return self._input_dataset.output_classes # pylint: disable=protected-access + + @property + def output_shapes(self): + return self._input_dataset.output_shapes # pylint: disable=protected-access + + @property + def output_types(self): + return self._input_dataset.output_types # pylint: disable=protected-access + + class TensorDataset(DatasetSource): """A `Dataset` with a single element, viz. a nested structure of tensors.""" @@ -1655,92 +1883,36 @@ class SparseTensorSliceDataset(DatasetSource): def __init__(self, sparse_tensor): """See `Dataset.from_sparse_tensor_slices()` for details.""" - super(SparseTensorSliceDataset, self).__init__() - if not isinstance(sparse_tensor, sparse_tensor_lib.SparseTensor): - raise TypeError("`sparse_tensor` must be a `tf.SparseTensor` object.") - self._sparse_tensor = sparse_tensor - - def _as_variant_tensor(self): - return gen_dataset_ops.sparse_tensor_slice_dataset( - self._sparse_tensor.indices, self._sparse_tensor.values, - self._sparse_tensor.dense_shape) - - @property - def output_classes(self): - return (ops.Tensor, ops.Tensor, ops.Tensor) - - @property - def output_shapes(self): - indices_shape = self._sparse_tensor.indices.get_shape() - shape_shape = self._sparse_tensor.dense_shape.get_shape() - rank = (indices_shape.dims[1] - 1).merge_with(shape_shape.dims[0] - 1) - num_values = tensor_shape.Dimension(None) - return (tensor_shape.TensorShape([num_values, rank]), - tensor_shape.TensorShape([num_values]), - tensor_shape.TensorShape([rank])) - - @property - def output_types(self): - return (dtypes.int64, self._sparse_tensor.dtype, dtypes.int64) - - -class _NestedDatasetComponent(object): - """The structure of a `Dataset` nested in a component of another `Dataset`. - - A `StructuredFunctionWrapper` around a function that returns a `Dataset` as - one of its components will have a `NestedDatasetComponent` in the - corresponding position in the `output_classes`, `output_shapes`, and - `output_types` properties. - - NOTE(mrry): This class is not currently exposed via the public API. Support - for nested datasets can be enabled on a function-by-function basis by setting - `experimental_nested_dataset_support=True` in the `StructuredFunctionWrapper` - initializer. - - TODO(b/110122868): Add this class, or something equivalent, to the public API. - We are considering revising the public API for accessing Dataset structure - (`output_classes` etc.) based on experience with nested datasets and other - custom component types. - """ - - def __init__(self, - dataset=None, - output_shapes=None, - output_types=None, - output_classes=None): - if dataset is None: - if (output_classes is None or output_shapes is None or - output_types is None): - raise ValueError( - "Either `dataset`, or all of `output_classes`, " - "`output_shapes`, and `output_types` must be specified.") - self._output_classes = output_classes - self._output_shapes = output_shapes - self._output_types = output_types - else: - if not (output_classes is None and output_shapes is None and - output_types is None): - raise ValueError( - "Either `dataset`, or all of `output_classes`, " - "`output_shapes`, and `output_types` must be specified.") - self._output_classes = dataset.output_classes - self._output_shapes = dataset.output_shapes - self._output_types = dataset.output_types + super(SparseTensorSliceDataset, self).__init__() + if not isinstance(sparse_tensor, sparse_tensor_lib.SparseTensor): + raise TypeError("`sparse_tensor` must be a `tf.SparseTensor` object.") + self._sparse_tensor = sparse_tensor + + def _as_variant_tensor(self): + return gen_dataset_ops.sparse_tensor_slice_dataset( + self._sparse_tensor.indices, self._sparse_tensor.values, + self._sparse_tensor.dense_shape) @property def output_classes(self): - return self._output_classes + return (ops.Tensor, ops.Tensor, ops.Tensor) @property def output_shapes(self): - return self._output_shapes + indices_shape = self._sparse_tensor.indices.get_shape() + shape_shape = self._sparse_tensor.dense_shape.get_shape() + rank = (indices_shape.dims[1] - 1).merge_with(shape_shape.dims[0] - 1) + num_values = tensor_shape.Dimension(None) + return (tensor_shape.TensorShape([num_values, rank]), + tensor_shape.TensorShape([num_values]), + tensor_shape.TensorShape([rank])) @property def output_types(self): - return self._output_types + return (dtypes.int64, self._sparse_tensor.dtype, dtypes.int64) -class _VariantDataset(Dataset): +class _VariantDataset(DatasetV2): """A Dataset wrapper around a `tf.variant`-typed function argument.""" def __init__(self, dataset_variant, structure): @@ -1756,15 +1928,76 @@ class _VariantDataset(Dataset): @property def output_classes(self): - return self._structure.output_classes + return self._structure._to_legacy_output_classes() # pylint: disable=protected-access @property def output_shapes(self): - return self._structure.output_shapes + return self._structure._to_legacy_output_shapes() # pylint: disable=protected-access @property def output_types(self): - return self._structure.output_types + return self._structure._to_legacy_output_types() # pylint: disable=protected-access + + +class DatasetStructure(structure_lib.Structure): + """Represents a `Dataset` of structured values.""" + + def __init__(self, element_structure): + self._element_structure = element_structure + + @property + def _flat_shapes(self): + return [tensor_shape.scalar()] + + @property + def _flat_types(self): + return [dtypes.variant] + + def is_compatible_with(self, other): + # pylint: disable=protected-access + return (isinstance(other, DatasetStructure) and + self._element_structure.is_compatible_with( + other._element_structure)) + + def _to_tensor_list(self, value): + return [value._as_variant_tensor()] # pylint: disable=protected-access + + def _from_tensor_list(self, flat_value): + if (len(flat_value) != 1 or flat_value[0].dtype != dtypes.variant or + not flat_value[0].shape.is_compatible_with(tensor_shape.scalar())): + raise ValueError( + "DatasetStructure corresponds to a single tf.variant scalar.") + return self._from_compatible_tensor_list(flat_value) + + def _from_compatible_tensor_list(self, flat_value): + # pylint: disable=protected-access + return _VariantDataset(flat_value[0], self._element_structure) + + @staticmethod + def from_value(value): + # TODO(b/110122868): We can simplify this when a `Dataset` object has a + # `Structure`-valued property. + element_structure = structure_lib.Structure._from_legacy_structure( + value.output_types, value.output_shapes, value.output_classes) + return DatasetStructure(element_structure) + + def _to_legacy_output_types(self): + return self + + def _to_legacy_output_shapes(self): + return self + + def _to_legacy_output_classes(self): + return self + + def _batch(self, batch_size): + raise NotImplementedError("Batching for `tf.data.Dataset` objects.") + + +# pylint: disable=protected-access +structure_lib.Structure._register_custom_converter(DatasetV2, + DatasetStructure.from_value) +# pylint: enable=protected-access class StructuredFunctionWrapper(object): @@ -1779,7 +2012,6 @@ class StructuredFunctionWrapper(object): input_shapes=None, input_types=None, add_to_graph=True, - experimental_nested_dataset_support=False, defun_kwargs=None): """Creates a new `StructuredFunctionWrapper` for the given function. @@ -1799,8 +2031,6 @@ class StructuredFunctionWrapper(object): argument defines the element types and structure for `func` arguments. add_to_graph: (Optional.) If `True`, the function will be added to the default graph. - experimental_nested_dataset_support: (Optional.) If `True`, the function - will support `tf.data.Dataset` objects as arguments and return values. defun_kwargs: (Optional.) A dictionary mapping string argument names to values. If supplied, will be passed to `function.Defun()` as keyword arguments. @@ -1825,6 +2055,9 @@ class StructuredFunctionWrapper(object): self._input_types = dataset.output_types self._input_classes = dataset.output_classes + self._input_structure = structure_lib.Structure._from_legacy_structure( # pylint: disable=protected-access + self._input_types, self._input_shapes, self._input_classes) + self._transformation_name = transformation_name readable_transformation_name = transformation_name.replace( ".", "_")[:-2] if len(transformation_name) > 2 else "" @@ -1832,39 +2065,18 @@ class StructuredFunctionWrapper(object): readable_transformation_name, function_utils.get_func_name(func), str(ops.uid()) - ]) - # TODO(b/110122868): Enable this support for all `tf.data` functions. - self._nested_dataset_support = experimental_nested_dataset_support - if defun_kwargs is None: defun_kwargs = {} @function.Defun( - *self._defun_args(), func_name=self._func_name, **defun_kwargs) + *self._input_structure._flat_types, func_name=self._func_name, # pylint: disable=protected-access + **defun_kwargs) def tf_data_structured_function_wrapper(*args): """Wrapper for passing nested structures to and from tf.data functions.""" - flat_args = [] - for arg, arg_class, arg_shape, arg_type in zip( - args, - nest.flatten(self._input_classes), - nest.flatten(self._input_shapes), - nest.flatten(self._input_types)): - # TODO(b/110122868): Add a registration mechanism for new component - # types. - if arg_class is sparse_tensor_lib.SparseTensor: - arg = sparse.deserialize_sparse_tensors( - arg, arg_type, arg_shape, arg_class) - arg.indices.set_shape([None, arg_shape.ndims]) - arg.dense_shape.set_shape([arg_shape.ndims]) - elif isinstance(arg_class, _NestedDatasetComponent): - assert self._nested_dataset_support - arg = _VariantDataset(arg, arg_class) - else: - arg.set_shape(arg_shape) - flat_args.append(arg) - nested_args = nest.pack_sequence_as(self._input_classes, flat_args) + # pylint: disable=protected-access + nested_args = self._input_structure._from_compatible_tensor_list(args) if not _should_unpack_args(nested_args): nested_args = (nested_args,) @@ -1882,55 +2094,14 @@ class StructuredFunctionWrapper(object): if isinstance(ret, list): ret = tuple(ret) - # Convert any `SparseTensorValue`s to `SparseTensor`s and all other - # values to tensors. - flat_ret = [] - flat_classes = [] - flat_shapes = [] - flat_types = [] - for t in nest.flatten(ret): - # TODO(b/110122868): Add a registration mechanism for new component - # types. - if sparse_tensor_lib.is_sparse(t): - t = sparse_tensor_lib.SparseTensor.from_value(t) - flat_ret.append(sparse.serialize_sparse_tensors(t)) - flat_classes.append(sparse_tensor_lib.SparseTensor) - flat_shapes.append(t.get_shape()) - flat_types.append(t.dtype) - elif isinstance(t, Dataset): - if not self._nested_dataset_support: - raise NotImplementedError( - "The %s transformation does not currently support nested " - "datasets as outputs." % self._transformation_name) - - flat_ret.append(t._as_variant_tensor()) # pylint: disable=protected-access - component = _NestedDatasetComponent(t) - flat_classes.append(component) - flat_shapes.append(component) - flat_types.append(component) - if t.options() != Options(): - warnings.warn("Encountered a nested dataset with non-default " - "options. These options will not be propagated to " - "the outer dataset.") - else: - try: - t = ops.convert_to_tensor(t) - except (ValueError, TypeError): - raise TypeError("Unsupported return value from function passed to " - "%s: %s." % (transformation_name, t)) - flat_ret.append(t) - flat_classes.append(ops.Tensor) - flat_shapes.append(t.get_shape()) - flat_types.append(t.dtype) - - ret = nest.pack_sequence_as(ret, flat_ret) - self._output_classes = nest.pack_sequence_as(ret, flat_classes) - self._output_shapes = nest.pack_sequence_as(ret, flat_shapes) - self._output_types = nest.pack_sequence_as(ret, flat_types) + try: + self._output_structure = structure_lib.Structure.from_value(ret) + except (ValueError, TypeError): + raise TypeError("Unsupported return value from function passed to " + "%s: %s." % (transformation_name, ret)) _warn_if_collections(transformation_name) - - return flat_ret + return self._output_structure._to_tensor_list(ret) self._function = tf_data_structured_function_wrapper if add_to_graph: @@ -1941,45 +2112,32 @@ class StructuredFunctionWrapper(object): # in case (e.g.) we need to rerun the function. self._function._create_definition_if_needed() # pylint: disable=protected-access - def _defun_args(self): - """Returns a flat list of `tf.DType` for the input element structure.""" - ret = [] - for input_type, input_class in zip(nest.flatten(self._input_types), - nest.flatten(self._input_classes)): - # TODO(b/110122868): Add a registration mechanism for new component types. - if input_class is sparse_tensor_lib.SparseTensor: - ret.append(dtypes.variant) - elif isinstance(input_class, _NestedDatasetComponent): - if not self._nested_dataset_support: - raise NotImplementedError( - "The %s transformation does not currently support nested " - "datasets as inputs." % self._transformation_name) - ret.append(dtypes.variant) - else: - assert isinstance(input_type, dtypes.DType) - ret.append(input_type) - return ret + @property + def output_structure(self): + return self._output_structure @property def output_classes(self): - return self._output_classes + return self._output_structure._to_legacy_output_classes() # pylint: disable=protected-access @property def output_shapes(self): - return self._output_shapes + return self._output_structure._to_legacy_output_shapes() # pylint: disable=protected-access @property def output_types(self): - return self._output_types + return self._output_structure._to_legacy_output_types() # pylint: disable=protected-access @property def function(self): return self._function -def flat_structure(dataset): +def flat_structure(dataset=None, structure=None): """Helper for setting `output_shapes` and `output_types` attrs of Dataset ops. + Either `dataset` or `structure` must be passed to this function. + Most Dataset op constructors expect `output_shapes` and `output_types` arguments that represent the flattened structure of an element. This helper function generates these attrs as a keyword argument dictionary, allowing @@ -1987,36 +2145,20 @@ def flat_structure(dataset): `**flat_structure(self)` to the op constructor. Args: - dataset: A `tf.data.Dataset`. + dataset: (Optional.) A `tf.data.Dataset`. + structure: (Optional.) A `Structure`. Returns: A dictionary of keyword arguments that can be passed to many Dataset op constructors. """ - output_classes = [] - output_shapes = [] - output_types = [] - for output_class, output_shape, output_type in zip( - nest.flatten(dataset.output_classes), nest.flatten(dataset.output_shapes), - nest.flatten(dataset.output_types)): - if isinstance(output_class, _NestedDatasetComponent): - output_classes.append(output_class.output_classes) - output_shapes.append(output_shape.output_shapes) - output_types.append(output_type.output_types) - else: - output_classes.append(output_class) - output_shapes.append(output_shape) - output_types.append(output_type) - - output_classes = nest.pack_sequence_as(dataset.output_classes, output_classes) - output_shapes = nest.pack_sequence_as(dataset.output_shapes, output_shapes) - output_types = nest.pack_sequence_as(dataset.output_types, output_types) - + # pylint: disable=protected-access + if structure is None: + structure = structure_lib.Structure._from_legacy_structure( + dataset.output_types, dataset.output_shapes, dataset.output_classes) return { - "output_shapes": - nest.flatten(sparse.as_dense_shapes(output_shapes, output_classes)), - "output_types": - nest.flatten(sparse.as_dense_types(output_types, output_classes)), + "output_shapes": structure._flat_shapes, + "output_types": structure._flat_types, } @@ -2108,14 +2250,14 @@ class _GeneratorDataset(DatasetSource): return "Dataset.from_generator()" -class ZipDataset(Dataset): +class ZipDataset(DatasetV2): """A `Dataset` that zips its inputs together.""" def __init__(self, datasets): """See `Dataset.zip()` for details.""" super(ZipDataset, self).__init__() for ds in nest.flatten(datasets): - if not isinstance(ds, Dataset): + if not isinstance(ds, DatasetV2): if isinstance(ds, list): message = ("The argument to `Dataset.zip()` must be a nested " "structure of `Dataset` objects. Nested structures do not " @@ -2155,7 +2297,7 @@ class ZipDataset(Dataset): [ds.output_types for ds in nest.flatten(self._datasets)]) -class ConcatenateDataset(Dataset): +class ConcatenateDataset(DatasetV2): """A `Dataset` that concatenates its input with given dataset.""" def __init__(self, input_dataset, dataset_to_concatenate): @@ -2210,7 +2352,7 @@ class ConcatenateDataset(Dataset): return self._output_types -class RepeatDataset(UnaryDataset): +class RepeatDataset(UnaryUnchangedStructureDataset): """A `Dataset` that repeats its input several times.""" def __init__(self, input_dataset, count): @@ -2229,18 +2371,6 @@ class RepeatDataset(UnaryDataset): count=self._count, **flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - class RangeDataset(DatasetSource): """A `Dataset` of a step separated range of values.""" @@ -2290,7 +2420,7 @@ class RangeDataset(DatasetSource): return dtypes.int64 -class CacheDataset(UnaryDataset): +class CacheDataset(UnaryUnchangedStructureDataset): """A `Dataset` that caches elements of its input.""" def __init__(self, input_dataset, filename): @@ -2306,20 +2436,8 @@ class CacheDataset(UnaryDataset): filename=self._filename, **flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - -class ShuffleDataset(UnaryDataset): +class ShuffleDataset(UnaryUnchangedStructureDataset): """A `Dataset` that randomly shuffles the elements of its input.""" def __init__(self, @@ -2367,20 +2485,8 @@ class ShuffleDataset(UnaryDataset): reshuffle_each_iteration=self._reshuffle_each_iteration, **flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - -class TakeDataset(UnaryDataset): +class TakeDataset(UnaryUnchangedStructureDataset): """A `Dataset` containing the first `count` elements from its input.""" def __init__(self, input_dataset, count): @@ -2395,20 +2501,8 @@ class TakeDataset(UnaryDataset): count=self._count, **flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - -class SkipDataset(UnaryDataset): +class SkipDataset(UnaryUnchangedStructureDataset): """A `Dataset` skipping the first `count` elements from its input.""" def __init__(self, input_dataset, count): @@ -2423,18 +2517,6 @@ class SkipDataset(UnaryDataset): count=self._count, **flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - class BatchDataset(UnaryDataset): """A `Dataset` that batches contiguous elements from its input.""" @@ -2448,37 +2530,37 @@ class BatchDataset(UnaryDataset): self._drop_remainder = ops.convert_to_tensor( drop_remainder, dtype=dtypes.bool, name="drop_remainder") - def _as_variant_tensor(self): - # TODO(jsimsa): Switch to using v2 only any time after 6/30/2018. - if smart_cond.smart_constant_value(self._drop_remainder) is False: - return gen_dataset_ops.batch_dataset( - self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access - batch_size=self._batch_size, - **flat_structure(self)) + # pylint: disable=protected-access + input_structure = structure_lib.Structure._from_legacy_structure( + input_dataset.output_types, input_dataset.output_shapes, + input_dataset.output_classes) + constant_drop_remainder = tensor_util.constant_value(self._drop_remainder) + if constant_drop_remainder: + # NOTE(mrry): `constant_drop_remainder` may be `None` (unknown statically) + # or `False` (explicitly retaining the remainder). + self._output_structure = input_structure._batch( + tensor_util.constant_value(self._batch_size)) else: - return gen_dataset_ops.batch_dataset_v2( - self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access - batch_size=self._batch_size, - drop_remainder=self._drop_remainder, - **flat_structure(self)) + self._output_structure = input_structure._batch(None) + + def _as_variant_tensor(self): + return gen_dataset_ops.batch_dataset_v2( + self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access + batch_size=self._batch_size, + drop_remainder=self._drop_remainder, + **flat_structure(structure=self._output_structure)) @property def output_classes(self): - return self._input_dataset.output_classes + return self._output_structure._to_legacy_output_classes() # pylint: disable=protected-access @property def output_shapes(self): - input_shapes = self._input_dataset.output_shapes - return nest.pack_sequence_as(input_shapes, [ - tensor_shape.vector( - tensor_util.constant_value(self._batch_size) if smart_cond. - smart_constant_value(self._drop_remainder) else None).concatenate(s) - for s in nest.flatten(self._input_dataset.output_shapes) - ]) + return self._output_structure._to_legacy_output_shapes() # pylint: disable=protected-access @property def output_types(self): - return self._input_dataset.output_types + return self._output_structure._to_legacy_output_types() # pylint: disable=protected-access def _is_padded_shape_compatible_with(padded_shape, input_component_shape): @@ -2704,66 +2786,37 @@ class MapDataset(UnaryDataset): super(MapDataset, self).__init__(input_dataset) self._input_dataset = input_dataset self._use_inter_op_parallelism = use_inter_op_parallelism - - wrapped_func = StructuredFunctionWrapper( + self._map_func = StructuredFunctionWrapper( map_func, self._transformation_name(), dataset=input_dataset) - self._output_classes = wrapped_func.output_classes - self._output_shapes = wrapped_func.output_shapes - self._output_types = wrapped_func.output_types - self._map_func = wrapped_func.function def _as_variant_tensor(self): input_t = self._input_dataset._as_variant_tensor() # pylint: disable=protected-access return gen_dataset_ops.map_dataset( input_t, - self._map_func.captured_inputs, - f=self._map_func, + self._map_func.function.captured_inputs, + f=self._map_func.function, use_inter_op_parallelism=self._use_inter_op_parallelism, - **flat_structure(self)) + **flat_structure(structure=self._map_func.output_structure)) + + def _functions(self): + return [self._map_func] @property def output_classes(self): - return self._output_classes + return self._map_func.output_classes @property def output_shapes(self): - return self._output_shapes + return self._map_func.output_shapes @property def output_types(self): - return self._output_types + return self._map_func.output_types def _transformation_name(self): return "Dataset.map()" -class MatchingFilesDataset(Dataset): - """A `Dataset` that list the files according to the input patterns.""" - - def __init__(self, patterns): - super(MatchingFilesDataset, self).__init__() - self._patterns = ops.convert_to_tensor( - patterns, dtype=dtypes.string, name="patterns") - - def _as_variant_tensor(self): - return gen_dataset_ops.matching_files_dataset(self._patterns) - - def _inputs(self): - return [] - - @property - def output_classes(self): - return ops.Tensor - - @property - def output_shapes(self): - return tensor_shape.scalar() - - @property - def output_types(self): - return dtypes.string - - class ParallelMapDataset(MapDataset): """A `Dataset` that maps a function over elements in its input in parallel.""" @@ -2780,16 +2833,15 @@ class ParallelMapDataset(MapDataset): num_parallel_calls, dtype=dtypes.int32, name="num_parallel_calls") def _as_variant_tensor(self): - input_t = self._input_dataset._as_variant_tensor() # pylint: disable=protected-access # pylint: disable=protected-access + input_t = self._input_dataset._as_variant_tensor() return gen_dataset_ops.parallel_map_dataset( input_t, - self._map_func.captured_inputs, - f=self._map_func, + self._map_func.function.captured_inputs, + f=self._map_func.function, num_parallel_calls=self._num_parallel_calls, use_inter_op_parallelism=self._use_inter_op_parallelism, - **flat_structure(self)) - # pylint: enable=protected-access + **flat_structure(structure=self._map_func.output_structure)) class FlatMapDataset(UnaryDataset): @@ -2800,36 +2852,33 @@ class FlatMapDataset(UnaryDataset): super(FlatMapDataset, self).__init__(input_dataset) self._input_dataset = input_dataset - wrapped_func = StructuredFunctionWrapper( - map_func, - self._transformation_name(), - dataset=input_dataset, - experimental_nested_dataset_support=True) - if not isinstance(wrapped_func.output_classes, _NestedDatasetComponent): + self._map_func = StructuredFunctionWrapper( + map_func, self._transformation_name(), dataset=input_dataset) + if not isinstance(self._map_func.output_structure, DatasetStructure): raise TypeError("`map_func` must return a `Dataset` object.") - self._output_classes = wrapped_func.output_classes.output_classes - self._output_types = wrapped_func.output_types.output_types - self._output_shapes = wrapped_func.output_shapes.output_shapes - self._map_func = wrapped_func.function + self._output_structure = self._map_func.output_structure._element_structure # pylint: disable=protected-access + + def _functions(self): + return [self._map_func] def _as_variant_tensor(self): return gen_dataset_ops.flat_map_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access - self._map_func.captured_inputs, - f=self._map_func, - **flat_structure(self)) + self._map_func.function.captured_inputs, + f=self._map_func.function, + **flat_structure(structure=self._output_structure)) @property def output_classes(self): - return self._output_classes + return self._output_structure._to_legacy_output_classes() # pylint: disable=protected-access @property def output_shapes(self): - return self._output_shapes + return self._output_structure._to_legacy_output_shapes() # pylint: disable=protected-access @property def output_types(self): - return self._output_types + return self._output_structure._to_legacy_output_types() # pylint: disable=protected-access def _transformation_name(self): return "Dataset.flat_map()" @@ -2848,13 +2897,14 @@ class InterleaveDataset(FlatMapDataset): block_length, dtype=dtypes.int64, name="block_length") def _as_variant_tensor(self): + # pylint: disable=protected-access return gen_dataset_ops.interleave_dataset( - self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access - self._map_func.captured_inputs, # pylint: disable=protected-access + self._input_dataset._as_variant_tensor(), + self._map_func.function.captured_inputs, self._cycle_length, self._block_length, - f=self._map_func, # pylint: disable=protected-access - **flat_structure(self)) + f=self._map_func.function, + **flat_structure(structure=self._output_structure)) def _transformation_name(self): return "Dataset.interleave()" @@ -2877,20 +2927,21 @@ class ParallelInterleaveDataset(FlatMapDataset): num_parallel_calls, dtype=dtypes.int64, name="num_parallel_calls") def _as_variant_tensor(self): + # pylint: disable=protected-access return gen_dataset_ops.parallel_interleave_dataset_v2( - self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access - self._map_func.captured_inputs, # pylint: disable=protected-access + self._input_dataset._as_variant_tensor(), + self._map_func.function.captured_inputs, self._cycle_length, self._block_length, self._num_parallel_calls, - f=self._map_func, # pylint: disable=protected-access - **flat_structure(self)) + f=self._map_func.function, + **flat_structure(structure=self._output_structure)) def _transformation_name(self): return "Dataset.interleave()" -class FilterDataset(UnaryDataset): +class FilterDataset(UnaryUnchangedStructureDataset): """A `Dataset` that filters its input according to a predicate function.""" def __init__(self, input_dataset, predicate): @@ -2903,32 +2954,23 @@ class FilterDataset(UnaryDataset): wrapped_func.output_types == dtypes.bool and wrapped_func.output_shapes.is_compatible_with(tensor_shape.scalar())): raise ValueError("`predicate` must return a scalar boolean tensor.") - self._predicate = wrapped_func.function + self._predicate = wrapped_func + + def _functions(self): + return [self._predicate] def _as_variant_tensor(self): return gen_dataset_ops.filter_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access - other_arguments=self._predicate.captured_inputs, - predicate=self._predicate, + other_arguments=self._predicate.function.captured_inputs, + predicate=self._predicate.function, **flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - def _transformation_name(self): return "Dataset.filter()" -class PrefetchDataset(UnaryDataset): +class PrefetchDataset(UnaryUnchangedStructureDataset): """A `Dataset` that asynchronously prefetches its input.""" def __init__(self, input_dataset, buffer_size): @@ -2946,18 +2988,6 @@ class PrefetchDataset(UnaryDataset): buffer_size=self._buffer_size, **flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - class WindowDataset(UnaryDataset): """A dataset that creates window datasets from the input elements.""" @@ -2975,10 +3005,9 @@ class WindowDataset(UnaryDataset): self._output_classes = nest.pack_sequence_as( input_dataset.output_classes, [ - _NestedDatasetComponent( # pylint: disable=protected-access - output_classes=output_class, - output_shapes=output_shape, - output_types=output_type) + DatasetStructure( + structure_lib.Structure._from_legacy_structure( # pylint: disable=protected-access + output_type, output_shape, output_class)) for output_class, output_shape, output_type in zip( nest.flatten(input_dataset.output_classes), nest.flatten(input_dataset.output_shapes), @@ -3009,7 +3038,7 @@ class WindowDataset(UnaryDataset): return self._output_types -class _OptionsDataset(UnaryDataset): +class _OptionsDataset(UnaryUnchangedStructureDataset): """An identity `Dataset` that stores options.""" def __init__(self, input_dataset, options): @@ -3027,20 +3056,8 @@ class _OptionsDataset(UnaryDataset): def options(self): return self._options - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - -class _ModelDataset(UnaryDataset): +class _ModelDataset(UnaryUnchangedStructureDataset): """A `Dataset` that acts as an identity, and models performance.""" def __init__(self, input_dataset): @@ -3053,20 +3070,8 @@ class _ModelDataset(UnaryDataset): self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access **flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - -class _OptimizeDataset(UnaryDataset): +class _OptimizeDataset(UnaryUnchangedStructureDataset): """A `Dataset` that acts as an identity, and applies optimizations.""" def __init__(self, input_dataset, optimizations): @@ -3084,21 +3089,9 @@ class _OptimizeDataset(UnaryDataset): self._optimizations, **flat_structure(self)) - @property - def output_classes(self): - return self._input_dataset.output_classes - - @property - def output_shapes(self): - return self._input_dataset.output_shapes - - @property - def output_types(self): - return self._input_dataset.output_types - -class _SetStatsAggregatorDataset(UnaryDataset): - """A `Dataset` that acts as an identity, and sets stats aggregator.""" +class _SetStatsAggregatorDataset(UnaryUnchangedStructureDataset): + """A `Dataset` that acts as an identity, and sets a stats aggregator.""" def __init__(self, input_dataset, aggregator, prefix, counter_prefix): super(_SetStatsAggregatorDataset, self).__init__(input_dataset) @@ -3108,21 +3101,43 @@ class _SetStatsAggregatorDataset(UnaryDataset): self._counter_prefix = counter_prefix def _as_variant_tensor(self): - return gen_dataset_ops.set_stats_aggregator_dataset( + return ged_ops.experimental_set_stats_aggregator_dataset( self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access self._stats_aggregator._resource, # pylint: disable=protected-access self._prefix, self._counter_prefix, **flat_structure(self)) - @property - def output_shapes(self): - return self._input_dataset.output_shapes - @property - def output_types(self): - return self._input_dataset.output_types +class _MaxIntraOpParallelismDataset(UnaryUnchangedStructureDataset): + """A `Dataset` that acts as an identity, overriding intra-op parallelism.""" - @property - def output_classes(self): - return self._input_dataset.output_classes + def __init__(self, input_dataset, max_intra_op_parallelism): + super(_MaxIntraOpParallelismDataset, self).__init__(input_dataset) + self._input_dataset = input_dataset + self._max_intra_op_parallelism = ops.convert_to_tensor( + max_intra_op_parallelism, + dtype=dtypes.int64, + name="max_intra_op_parallelism") + + def _as_variant_tensor(self): + return ged_ops.experimental_max_intra_op_parallelism_dataset( + self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access + self._max_intra_op_parallelism, + **flat_structure(self)) + + +class _PrivateThreadPoolDataset(UnaryUnchangedStructureDataset): + """A `Dataset` that acts as an identity, setting a private threadpool.""" + + def __init__(self, input_dataset, num_threads): + super(_PrivateThreadPoolDataset, self).__init__(input_dataset) + self._input_dataset = input_dataset + self._num_threads = ops.convert_to_tensor( + num_threads, dtype=dtypes.int64, name="num_threads") + + def _as_variant_tensor(self): + return ged_ops.experimental_private_thread_pool_dataset( + self._input_dataset._as_variant_tensor(), # pylint: disable=protected-access + self._num_threads, + **flat_structure(self)) diff --git a/tensorflow/python/data/ops/iterator_ops.py b/tensorflow/python/data/ops/iterator_ops.py index 68b03ba93b..e2ca64c802 100644 --- a/tensorflow/python/data/ops/iterator_ops.py +++ b/tensorflow/python/data/ops/iterator_ops.py @@ -68,7 +68,7 @@ def _device_stack_is_empty(): return not bool(device_stack) -@tf_export("data.Iterator") +@tf_export(v1=["data.Iterator"]) class Iterator(checkpointable.CheckpointableBase): """Represents the state of iterating through a `Dataset`.""" diff --git a/tensorflow/python/data/ops/optional_ops.py b/tensorflow/python/data/ops/optional_ops.py index 91cf883ce9..15ec755c67 100644 --- a/tensorflow/python/data/ops/optional_ops.py +++ b/tensorflow/python/data/ops/optional_ops.py @@ -183,19 +183,17 @@ class OptionalStructure(structure.Structure): return OptionalStructure(value.value_structure) def _to_legacy_output_types(self): - raise NotImplementedError("The `output_types` property is not supported on " - "structured objects containing an `Optional`. " - "Use the corresponding `structure` property.") + return self def _to_legacy_output_shapes(self): - raise NotImplementedError("The `output_shapes` property is not supported on" - " structured objects containing an `Optional`. " - "Use the corresponding `structure` property.") + return self def _to_legacy_output_classes(self): - raise NotImplementedError("The `output_classes` property is not supported " - "on structured objects containing an `Optional`. " - "Use the corresponding `structure` property.") + return self + + def _batch(self, batch_size): + raise NotImplementedError( + "Batching for `tf.data.experimental.Optional` objects.") # pylint: disable=protected-access diff --git a/tensorflow/python/data/ops/readers.py b/tensorflow/python/data/ops/readers.py index 7e165a052d..70a3b1b1cb 100644 --- a/tensorflow/python/data/ops/readers.py +++ b/tensorflow/python/data/ops/readers.py @@ -25,6 +25,7 @@ from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_dataset_ops +from tensorflow.python.ops import gen_experimental_dataset_ops as ged_ops from tensorflow.python.util.tf_export import tf_export @@ -32,8 +33,8 @@ from tensorflow.python.util.tf_export import tf_export _DEFAULT_READER_BUFFER_SIZE_BYTES = 256 * 1024 # 256 KB -@tf_export("data.TextLineDataset") -class TextLineDataset(dataset_ops.DatasetSource): +@tf_export("data.TextLineDataset", v1=[]) +class TextLineDatasetV2(dataset_ops.DatasetSource): """A `Dataset` comprising lines from one or more text files.""" def __init__(self, filenames, compression_type=None, buffer_size=None): @@ -47,7 +48,7 @@ class TextLineDataset(dataset_ops.DatasetSource): to buffer. A value of 0 results in the default buffering values chosen based on the compression type. """ - super(TextLineDataset, self).__init__() + super(TextLineDatasetV2, self).__init__() self._filenames = ops.convert_to_tensor( filenames, dtype=dtypes.string, name="filenames") self._compression_type = convert.optional_param_to_tensor( @@ -75,6 +76,24 @@ class TextLineDataset(dataset_ops.DatasetSource): return dtypes.string +@tf_export(v1=["data.TextLineDataset"]) +class TextLineDatasetV1(dataset_ops.DatasetV1Adapter): + """A `Dataset` comprising lines from one or more text files.""" + + def __init__(self, filenames, compression_type=None, buffer_size=None): + wrapped = TextLineDatasetV2(filenames, compression_type, buffer_size) + super(TextLineDatasetV1, self).__init__(wrapped) + __init__.__doc__ = TextLineDatasetV2.__init__.__doc__ + + @property + def _filenames(self): + return self._dataset._filenames # pylint: disable=protected-access + + @_filenames.setter + def _filenames(self, value): + self._dataset._filenames = value # pylint: disable=protected-access + + class _TFRecordDataset(dataset_ops.DatasetSource): """A `Dataset` comprising records from one or more TFRecord files.""" @@ -140,29 +159,28 @@ class ParallelInterleaveDataset(dataset_ops.InterleaveDataset): def _as_variant_tensor(self): # pylint: disable=protected-access - return gen_dataset_ops.parallel_interleave_dataset( + return ged_ops.experimental_parallel_interleave_dataset( self._input_dataset._as_variant_tensor(), - self._map_func.captured_inputs, + self._map_func.function.captured_inputs, self._cycle_length, self._block_length, self._sloppy, self._buffer_output_elements, self._prefetch_input_elements, - f=self._map_func, - **dataset_ops.flat_structure(self)) - # pylint: enable=protected-access + f=self._map_func.function, + **dataset_ops.flat_structure(structure=self._output_structure)) def _transformation_name(self): return "tf.data.experimental.parallel_interleave()" -@tf_export("data.TFRecordDataset") -class TFRecordDataset(dataset_ops.Dataset): +@tf_export("data.TFRecordDataset", v1=[]) +class TFRecordDatasetV2(dataset_ops.DatasetV2): """A `Dataset` comprising records from one or more TFRecord files.""" def __init__(self, filenames, compression_type=None, buffer_size=None, num_parallel_reads=None): - """Creates a `TFRecordDataset` to read for one or more TFRecord files. + """Creates a `TFRecordDataset` to read one or more TFRecord files. NOTE: The `num_parallel_reads` argument can be used to improve performance when reading from a remote filesystem. @@ -182,8 +200,8 @@ class TFRecordDataset(dataset_ops.Dataset): TypeError: If any argument does not have the expected type. ValueError: If any argument does not have the expected shape. """ - super(TFRecordDataset, self).__init__() - if isinstance(filenames, dataset_ops.Dataset): + super(TFRecordDatasetV2, self).__init__() + if isinstance(filenames, dataset_ops.DatasetV2): if filenames.output_types != dtypes.string: raise TypeError( "`filenames` must be a `tf.data.Dataset` of `tf.string` elements.") @@ -194,7 +212,7 @@ class TFRecordDataset(dataset_ops.Dataset): else: filenames = ops.convert_to_tensor(filenames, dtype=dtypes.string) filenames = array_ops.reshape(filenames, [-1], name="flat_filenames") - filenames = dataset_ops.Dataset.from_tensor_slices(filenames) + filenames = dataset_ops.DatasetV2.from_tensor_slices(filenames) self._filenames = filenames self._compression_type = compression_type @@ -217,10 +235,10 @@ class TFRecordDataset(dataset_ops.Dataset): compression_type=None, buffer_size=None, num_parallel_reads=None): - return TFRecordDataset(filenames or self._filenames, - compression_type or self._compression_type, - buffer_size or self._buffer_size, - num_parallel_reads or self._num_parallel_reads) + return TFRecordDatasetV2(filenames or self._filenames, + compression_type or self._compression_type, + buffer_size or self._buffer_size, + num_parallel_reads or self._num_parallel_reads) def _as_variant_tensor(self): return self._impl._as_variant_tensor() # pylint: disable=protected-access @@ -241,8 +259,40 @@ class TFRecordDataset(dataset_ops.Dataset): return self._impl.output_types -@tf_export("data.FixedLengthRecordDataset") -class FixedLengthRecordDataset(dataset_ops.DatasetSource): +@tf_export(v1=["data.TFRecordDataset"]) +class TFRecordDatasetV1(dataset_ops.DatasetV1Adapter): + """A `Dataset` comprising records from one or more TFRecord files.""" + + def __init__(self, filenames, compression_type=None, buffer_size=None, + num_parallel_reads=None): + wrapped = TFRecordDatasetV2( + filenames, compression_type, buffer_size, num_parallel_reads) + super(TFRecordDatasetV1, self).__init__(wrapped) + __init__.__doc__ = TFRecordDatasetV2.__init__.__doc__ + + def _clone(self, + filenames=None, + compression_type=None, + buffer_size=None, + num_parallel_reads=None): + # pylint: disable=protected-access + return TFRecordDatasetV1( + filenames or self._dataset._filenames, + compression_type or self._dataset._compression_type, + buffer_size or self._dataset._buffer_size, + num_parallel_reads or self._dataset._num_parallel_reads) + + @property + def _filenames(self): + return self._dataset._filenames # pylint: disable=protected-access + + @_filenames.setter + def _filenames(self, value): + self._dataset._filenames = value # pylint: disable=protected-access + + +@tf_export("data.FixedLengthRecordDataset", v1=[]) +class FixedLengthRecordDatasetV2(dataset_ops.DatasetSource): """A `Dataset` of fixed-length records from one or more binary files.""" def __init__(self, @@ -267,7 +317,7 @@ class FixedLengthRecordDataset(dataset_ops.DatasetSource): compression_type: (Optional.) A `tf.string` scalar evaluating to one of `""` (no compression), `"ZLIB"`, or `"GZIP"`. """ - super(FixedLengthRecordDataset, self).__init__() + super(FixedLengthRecordDatasetV2, self).__init__() self._filenames = ops.convert_to_tensor( filenames, dtype=dtypes.string, name="filenames") self._record_bytes = ops.convert_to_tensor( @@ -296,7 +346,6 @@ class FixedLengthRecordDataset(dataset_ops.DatasetSource): self._filenames, self._header_bytes, self._record_bytes, self._footer_bytes, self._buffer_size) - @property def output_classes(self): return ops.Tensor @@ -308,3 +357,36 @@ class FixedLengthRecordDataset(dataset_ops.DatasetSource): @property def output_types(self): return dtypes.string + + +@tf_export(v1=["data.FixedLengthRecordDataset"]) +class FixedLengthRecordDatasetV1(dataset_ops.DatasetV1Adapter): + """A `Dataset` of fixed-length records from one or more binary files.""" + + def __init__(self, + filenames, + record_bytes, + header_bytes=None, + footer_bytes=None, + buffer_size=None, + compression_type=None): + wrapped = FixedLengthRecordDatasetV2( + filenames, record_bytes, header_bytes, footer_bytes, buffer_size, + compression_type) + super(FixedLengthRecordDatasetV1, self).__init__(wrapped) + __init__.__doc__ = FixedLengthRecordDatasetV2.__init__.__doc__ + + @property + def _filenames(self): + return self._dataset._filenames # pylint: disable=protected-access + + @_filenames.setter + def _filenames(self, value): + self._dataset._filenames = value # pylint: disable=protected-access + + +# TODO(b/119044825): Until all `tf.data` unit tests are converted to V2, keep +# these aliases in place. +FixedLengthRecordDataset = FixedLengthRecordDatasetV1 +TFRecordDataset = TFRecordDatasetV1 +TextLineDataset = TextLineDatasetV1 diff --git a/tensorflow/python/data/util/BUILD b/tensorflow/python/data/util/BUILD index 39082ce370..f15ebc32a8 100644 --- a/tensorflow/python/data/util/BUILD +++ b/tensorflow/python/data/util/BUILD @@ -97,6 +97,23 @@ py_test( ], ) +py_library( + name = "options", + srcs = ["options.py"], + srcs_version = "PY2AND3", +) + +py_test( + name = "options_test", + size = "small", + srcs = ["options_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":options", + "//tensorflow/python:client_testlib", + ], +) + py_library( name = "convert", srcs = ["convert.py"], diff --git a/tensorflow/python/data/util/convert_test.py b/tensorflow/python/data/util/convert_test.py index 89c3afb296..78ca6e9513 100644 --- a/tensorflow/python/data/util/convert_test.py +++ b/tensorflow/python/data/util/convert_test.py @@ -22,6 +22,7 @@ from tensorflow.python.data.util import convert from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.platform import test from tensorflow.python.util import compat @@ -30,47 +31,53 @@ class ConvertTest(test.TestCase): def testInteger(self): resp = convert.optional_param_to_tensor("foo", 3) - with self.cached_session() as sess: - self.assertEqual(3, sess.run(resp)) + self.assertEqual(3, self.evaluate(resp)) def testIntegerDefault(self): resp = convert.optional_param_to_tensor("foo", None) - with self.cached_session() as sess: - self.assertEqual(0, sess.run(resp)) + self.assertEqual(0, self.evaluate(resp)) def testStringDefault(self): resp = convert.optional_param_to_tensor("bar", None, "default", dtypes.string) - with self.cached_session() as sess: - self.assertEqual(compat.as_bytes("default"), sess.run(resp)) + self.assertEqual(compat.as_bytes("default"), self.evaluate(resp)) def testString(self): resp = convert.optional_param_to_tensor("bar", "value", "default", dtypes.string) - with self.cached_session() as sess: - self.assertEqual(compat.as_bytes("value"), sess.run(resp)) + self.assertEqual(compat.as_bytes("value"), self.evaluate(resp)) def testPartialShapeToTensorKnownDimension(self): - with self.cached_session() as sess: - self.assertAllEqual([1], sess.run(convert.partial_shape_to_tensor( - tensor_shape.TensorShape([1])))) - self.assertAllEqual([1], sess.run(convert.partial_shape_to_tensor((1,)))) - self.assertAllEqual([1], sess.run(convert.partial_shape_to_tensor([1]))) - self.assertAllEqual([1], sess.run(convert.partial_shape_to_tensor( - constant_op.constant([1], dtype=dtypes.int64)))) - + self.assertAllEqual([1], + self.evaluate( + convert.partial_shape_to_tensor( + tensor_shape.TensorShape([1])))) + self.assertAllEqual([1], self.evaluate( + convert.partial_shape_to_tensor((1,)))) + self.assertAllEqual([1], self.evaluate( + convert.partial_shape_to_tensor([1]))) + self.assertAllEqual([1], + self.evaluate( + convert.partial_shape_to_tensor( + constant_op.constant([1], dtype=dtypes.int64)))) + + @test_util.run_deprecated_v1 def testPartialShapeToTensorUnknownDimension(self): - with self.cached_session() as sess: - self.assertAllEqual([-1], sess.run(convert.partial_shape_to_tensor( - tensor_shape.TensorShape([None])))) - self.assertAllEqual([-1], sess.run(convert.partial_shape_to_tensor( - (None,)))) - self.assertAllEqual([-1], sess.run(convert.partial_shape_to_tensor( - [None]))) - self.assertAllEqual([-1], sess.run(convert.partial_shape_to_tensor( - [-1]))) - self.assertAllEqual([-1], sess.run(convert.partial_shape_to_tensor( - constant_op.constant([-1], dtype=dtypes.int64)))) + self.assertAllEqual([-1], + self.evaluate( + convert.partial_shape_to_tensor( + tensor_shape.TensorShape([None])))) + self.assertAllEqual([-1], + self.evaluate(convert.partial_shape_to_tensor((None,)))) + self.assertAllEqual([-1], + self.evaluate(convert.partial_shape_to_tensor([None]))) + self.assertAllEqual([-1], + self.evaluate(convert.partial_shape_to_tensor([-1]))) + self.assertAllEqual([-1], + self.evaluate( + convert.partial_shape_to_tensor( + constant_op.constant([-1], + dtype=dtypes.int64)))) with self.assertRaisesRegexp( ValueError, r"The given shape .* must be a 1-D tensor of tf.int64 " @@ -84,42 +91,63 @@ class ConvertTest(test.TestCase): convert.partial_shape_to_tensor(constant_op.constant([1., 1.])) def testPartialShapeToTensorMultipleDimensions(self): - with self.cached_session() as sess: - self.assertAllEqual([3, 6], sess.run(convert.partial_shape_to_tensor( - tensor_shape.TensorShape([3, 6])))) - self.assertAllEqual([3, 6], sess.run(convert.partial_shape_to_tensor( - (3, 6)))) - self.assertAllEqual([3, 6], sess.run(convert.partial_shape_to_tensor( - [3, 6]))) - self.assertAllEqual([3, 6], sess.run(convert.partial_shape_to_tensor( - constant_op.constant([3, 6], dtype=dtypes.int64)))) - - self.assertAllEqual([3, -1], sess.run(convert.partial_shape_to_tensor( - tensor_shape.TensorShape([3, None])))) - self.assertAllEqual([3, -1], sess.run(convert.partial_shape_to_tensor( - (3, None)))) - self.assertAllEqual([3, -1], sess.run(convert.partial_shape_to_tensor( - [3, None]))) - self.assertAllEqual([3, -1], sess.run(convert.partial_shape_to_tensor( - constant_op.constant([3, -1], dtype=dtypes.int64)))) - - self.assertAllEqual([-1, -1], sess.run(convert.partial_shape_to_tensor( - tensor_shape.TensorShape([None, None])))) - self.assertAllEqual([-1, -1], sess.run(convert.partial_shape_to_tensor( - (None, None)))) - self.assertAllEqual([-1, -1], sess.run(convert.partial_shape_to_tensor( - [None, None]))) - self.assertAllEqual([-1, -1], sess.run(convert.partial_shape_to_tensor( - constant_op.constant([-1, -1], dtype=dtypes.int64)))) + self.assertAllEqual([3, 6], + self.evaluate( + convert.partial_shape_to_tensor( + tensor_shape.TensorShape([3, 6])))) + self.assertAllEqual([3, 6], + self.evaluate(convert.partial_shape_to_tensor((3, 6)))) + self.assertAllEqual([3, 6], + self.evaluate(convert.partial_shape_to_tensor([3, 6]))) + self.assertAllEqual([3, 6], + self.evaluate( + convert.partial_shape_to_tensor( + constant_op.constant([3, 6], + dtype=dtypes.int64)))) + + self.assertAllEqual([3, -1], + self.evaluate( + convert.partial_shape_to_tensor( + tensor_shape.TensorShape([3, None])))) + self.assertAllEqual([3, -1], + self.evaluate( + convert.partial_shape_to_tensor((3, None)))) + self.assertAllEqual([3, -1], + self.evaluate( + convert.partial_shape_to_tensor([3, None]))) + self.assertAllEqual([3, -1], + self.evaluate( + convert.partial_shape_to_tensor( + constant_op.constant([3, -1], + dtype=dtypes.int64)))) + + self.assertAllEqual([-1, -1], + self.evaluate( + convert.partial_shape_to_tensor( + tensor_shape.TensorShape([None, None])))) + self.assertAllEqual([-1, -1], + self.evaluate( + convert.partial_shape_to_tensor((None, None)))) + self.assertAllEqual([-1, -1], + self.evaluate( + convert.partial_shape_to_tensor([None, None]))) + self.assertAllEqual([-1, -1], + self.evaluate( + convert.partial_shape_to_tensor( + constant_op.constant([-1, -1], + dtype=dtypes.int64)))) def testPartialShapeToTensorScalar(self): - with self.cached_session() as sess: - self.assertAllEqual([], sess.run(convert.partial_shape_to_tensor( - tensor_shape.TensorShape([])))) - self.assertAllEqual([], sess.run(convert.partial_shape_to_tensor(()))) - self.assertAllEqual([], sess.run(convert.partial_shape_to_tensor([]))) - self.assertAllEqual([], sess.run(convert.partial_shape_to_tensor( - constant_op.constant([], dtype=dtypes.int64)))) + self.assertAllEqual([], + self.evaluate( + convert.partial_shape_to_tensor( + tensor_shape.TensorShape([])))) + self.assertAllEqual([], self.evaluate(convert.partial_shape_to_tensor(()))) + self.assertAllEqual([], self.evaluate(convert.partial_shape_to_tensor([]))) + self.assertAllEqual([], + self.evaluate( + convert.partial_shape_to_tensor( + constant_op.constant([], dtype=dtypes.int64)))) if __name__ == "__main__": diff --git a/tensorflow/python/data/util/options.py b/tensorflow/python/data/util/options.py new file mode 100644 index 0000000000..9badba8e56 --- /dev/null +++ b/tensorflow/python/data/util/options.py @@ -0,0 +1,131 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Utilities for tf.data options.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + + +def _internal_attr_name(name): + return "_" + name + + +class OptionsBase(object): + """Base class for representing a set of tf.data options. + + Attributes: + _options: Stores the option values. + """ + + def __init__(self): + self._options = {} + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + for name in set(self._options) | set(other._options): # pylint: disable=protected-access + if getattr(self, name) != getattr(other, name): + return False + return True + + def __ne__(self, other): + if isinstance(other, self.__class__): + return not self.__eq__(other) + else: + return NotImplemented + + +def create_option(name, ty, docstring, default=None): + """Creates a type-checked property. + + Args: + name: the name to use + ty: the type to use + docstring: the docstring to use + default: the default value to use + + Returns: + A type-checked property. + """ + + def get_fn(self): + return self._options.get(name, default) # pylint: disable=protected-access + + def set_fn(self, value): + if not isinstance(value, ty): + raise TypeError("Property \"%s\" must be of type %s, got: %r (type: %r)" % + (name, ty, value, type(value))) + self._options[name] = value # pylint: disable=protected-access + + return property(get_fn, set_fn, None, docstring) + + +def merge_options(*options_list): + """Merges the given options, returning the result as a new options object. + + The input arguments are expected to have a matching type that derives from + `OptionsBase` (and thus each represent a set of options). The method outputs + an object of the same type created by merging the sets of options represented + by the input arguments. + + The sets of options can be merged as long as there does not exist an option + with different non-default values. + + If an option is an instance of `OptionsBase` itself, then this method is + applied recursively to the set of options represented by this option. + + Args: + *options_list: options to merge + + Raises: + TypeError: if the input arguments are incompatible or not derived from + `OptionsBase` + ValueError: if the given options cannot be merged + + Returns: + A new options object which is the result of merging the given options. + """ + if len(options_list) < 1: + raise ValueError("At least one options should be provided") + result_type = type(options_list[0]) + + for options in options_list: + if not isinstance(options, result_type): + raise TypeError("Incompatible options type: %r vs %r" % (type(options), + result_type)) + + if not isinstance(options_list[0], OptionsBase): + raise TypeError("The inputs should inherit from `OptionsBase`") + + default_options = result_type() + result = result_type() + for options in options_list: + # Iterate over all set options and merge the into the result. + for name in options._options: # pylint: disable=protected-access + this = getattr(result, name) + that = getattr(options, name) + default = getattr(default_options, name) + if that == default: + continue + elif this == default: + setattr(result, name, that) + elif isinstance(this, OptionsBase): + setattr(result, name, merge_options(this, that)) + elif this != that: + raise ValueError( + "Cannot merge incompatible values (%r and %r) of option: %s" % + (this, that, name)) + return result diff --git a/tensorflow/python/data/util/options_test.py b/tensorflow/python/data/util/options_test.py new file mode 100644 index 0000000000..c5169835a3 --- /dev/null +++ b/tensorflow/python/data/util/options_test.py @@ -0,0 +1,96 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for dataset options utilities.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.data.util import options +from tensorflow.python.platform import test + + +class _TestOptions(options.OptionsBase): + x = options.create_option( + name="x", ty=int, docstring="the answer to everything", default=42) + y = options.create_option( + name="y", ty=float, docstring="a tasty pie", default=3.14) + + +class _NestedTestOptions(options.OptionsBase): + opts = options.create_option( + name="opts", ty=_TestOptions, docstring="nested options") + + +class OptionsTest(test.TestCase): + + def testDocumentation(self): + self.assertEqual(_TestOptions.x.__doc__, "the answer to everything") + self.assertEqual(_TestOptions.y.__doc__, "a tasty pie") + + def testCreateOption(self): + opts = _TestOptions() + self.assertEqual(opts.x, 42) + self.assertEqual(opts.y, 3.14) + self.assertIsInstance(opts.x, int) + self.assertIsInstance(opts.y, float) + opts.x = 0 + self.assertEqual(opts.x, 0) + with self.assertRaises(TypeError): + opts.x = 3.14 + opts.y = 0.0 + self.assertEqual(opts.y, 0.0) + with self.assertRaises(TypeError): + opts.y = 42 + + def testMergeOptions(self): + options1, options2 = _TestOptions(), _TestOptions() + with self.assertRaises(ValueError): + options.merge_options() + merged_options = options.merge_options(options1, options2) + self.assertEqual(merged_options.x, 42) + self.assertEqual(merged_options.y, 3.14) + options1.x = 0 + options2.y = 0.0 + merged_options = options.merge_options(options1, options2) + self.assertEqual(merged_options.x, 0) + self.assertEqual(merged_options.y, 0.0) + + def testMergeNestedOptions(self): + options1, options2 = _NestedTestOptions(), _NestedTestOptions() + merged_options = options.merge_options(options1, options2) + self.assertEqual(merged_options.opts, None) + options1.opts = _TestOptions() + merged_options = options.merge_options(options1, options2) + self.assertEqual(merged_options.opts, _TestOptions()) + options2.opts = _TestOptions() + merged_options = options.merge_options(options1, options2) + self.assertEqual(merged_options.opts, _TestOptions()) + options1.opts.x = 0 + options2.opts.y = 0.0 + merged_options = options.merge_options(options1, options2) + self.assertEqual(merged_options.opts.x, 0) + self.assertEqual(merged_options.opts.y, 0.0) + + def testMergeOptionsInvalid(self): + with self.assertRaises(TypeError): + options.merge_options(0) + options1, options2 = _TestOptions(), _NestedTestOptions() + with self.assertRaises(TypeError): + options.merge_options(options1, options2) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/data/util/sparse.py b/tensorflow/python/data/util/sparse.py index 5e6d224709..f2e22fefd3 100644 --- a/tensorflow/python/data/util/sparse.py +++ b/tensorflow/python/data/util/sparse.py @@ -34,7 +34,7 @@ def any_sparse(classes): Returns: `True` if `classes` contains a sparse tensor type and `False` otherwise. """ - return any([c is sparse_tensor.SparseTensor for c in nest.flatten(classes)]) + return any(c is sparse_tensor.SparseTensor for c in nest.flatten(classes)) def as_dense_shapes(shapes, classes): diff --git a/tensorflow/python/data/util/sparse_test.py b/tensorflow/python/data/util/sparse_test.py index 056b32480f..06acf55ab9 100644 --- a/tensorflow/python/data/util/sparse_test.py +++ b/tensorflow/python/data/util/sparse_test.py @@ -25,6 +25,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -292,10 +293,11 @@ class SparseTest(test.TestCase): return self.assertTrue(isinstance(b, sparse_tensor.SparseTensor)) with self.cached_session(): - self.assertAllEqual(a.eval().indices, b.eval().indices) - self.assertAllEqual(a.eval().values, b.eval().values) - self.assertAllEqual(a.eval().dense_shape, b.eval().dense_shape) + self.assertAllEqual(a.eval().indices, self.evaluate(b).indices) + self.assertAllEqual(a.eval().values, self.evaluate(b).values) + self.assertAllEqual(a.eval().dense_shape, self.evaluate(b).dense_shape) + @test_util.run_deprecated_v1 def testSerializeDeserialize(self): test_cases = ( (), @@ -325,6 +327,7 @@ class SparseTest(test.TestCase): for a, e in zip(nest.flatten(actual), nest.flatten(expected)): self.assertSparseValuesEqual(a, e) + @test_util.run_deprecated_v1 def testSerializeManyDeserialize(self): test_cases = ( (), diff --git a/tensorflow/python/data/util/structure.py b/tensorflow/python/data/util/structure.py index 9a3118297d..874e8abc6d 100644 --- a/tensorflow/python/data/util/structure.py +++ b/tensorflow/python/data/util/structure.py @@ -144,6 +144,19 @@ class Structure(object): """ return self._from_tensor_list(flat_value) + @abc.abstractmethod + def _batch(self, batch_size): + """Returns a structure representing a batch of objects with this structure. + + Args: + batch_size: An `int` representing the number of elements in a batch, + or `None` if the batch size may vary. + + Returns: + A `Structure` representing a batch of objects with this structure. + """ + raise NotImplementedError("Structure._batch()") + @staticmethod def from_value(value): """Returns a `Structure` that represents the given `value`. @@ -208,14 +221,16 @@ class Structure(object): flat_ret = [] for flat_type, flat_shape, flat_class in zip(flat_types, flat_shapes, flat_classes): - if issubclass(flat_class, sparse_tensor_lib.SparseTensor): + if isinstance(flat_class, Structure): + flat_ret.append(flat_class) + elif issubclass(flat_class, sparse_tensor_lib.SparseTensor): flat_ret.append(SparseTensorStructure(flat_type, flat_shape)) elif issubclass(flat_class, ops.Tensor): flat_ret.append(TensorStructure(flat_type, flat_shape)) else: # NOTE(mrry): Since legacy structures produced by iterators only - # comprise Tensors, SparseTensors, and nests, we do not need to support - # all structure types here. + # comprise Tensors, SparseTensors, and nests, we do not need to + # support all structure types here. raise TypeError( "Could not build a structure for output class %r" % flat_type) @@ -314,15 +329,23 @@ class NestedStructure(Structure): % (len(self._flat_types), len(flat_value))) flat_ret = [] - for sub_value, structure in zip(flat_value, self._flat_nested_structure): - flat_ret.append(structure._from_tensor_list([sub_value])) + i = 0 + for structure in self._flat_nested_structure: + num_flat_values = len(structure._flat_types) + sub_value = flat_value[i:i + num_flat_values] + flat_ret.append(structure._from_tensor_list(sub_value)) + i += num_flat_values return nest.pack_sequence_as(self._nested_structure, flat_ret) def _from_compatible_tensor_list(self, flat_value): flat_ret = [] - for sub_value, structure in zip(flat_value, self._flat_nested_structure): - flat_ret.append(structure._from_compatible_tensor_list([sub_value])) + i = 0 + for structure in self._flat_nested_structure: + num_flat_values = len(structure._flat_types) + sub_value = flat_value[i:i + num_flat_values] + flat_ret.append(structure._from_compatible_tensor_list(sub_value)) + i += num_flat_values return nest.pack_sequence_as(self._nested_structure, flat_ret) @@ -345,6 +368,10 @@ class NestedStructure(Structure): return nest.map_structure( lambda s: s._to_legacy_output_classes(), self._nested_structure) + def _batch(self, batch_size): + return NestedStructure(nest.map_structure( + lambda s: s._batch(batch_size), self._nested_structure)) + class TensorStructure(Structure): """Represents structural information about a `tf.Tensor`.""" @@ -381,6 +408,13 @@ class TensorStructure(Structure): return self._from_compatible_tensor_list(flat_value) def _from_compatible_tensor_list(self, flat_value): + # TODO(b/112266545): It would be cleaner to create a new `ensure_shape()` + # op here and return that, instead of mutating the input's shape using + # `Tensor.set_shape()`. However, that would add extra ops on the arguments + # of each `tf.data` function, which could impact performance. When this + # bug is resolved, we should be able to add the `ensure_shape()` ops and + # optimize them away using contextual shape information. + flat_value[0].set_shape(self._shape) return flat_value[0] @staticmethod @@ -396,6 +430,11 @@ class TensorStructure(Structure): def _to_legacy_output_classes(self): return ops.Tensor + def _batch(self, batch_size): + return TensorStructure( + self._dtype, + tensor_shape.TensorShape([batch_size]).concatenate(self._shape)) + class SparseTensorStructure(Structure): """Represents structural information about a `tf.SparseTensor`.""" @@ -406,7 +445,11 @@ class SparseTensorStructure(Structure): @property def _flat_shapes(self): - return [tensor_shape.vector(3)] + # NOTE(mrry): The default flat shape of a boxed `SparseTensor` is `(3,)`, + # but a `SparseTensorStructure` can also represent a batch of boxed + # `SparseTensor` objects with shape `(?, 3)` (and batches of batches, etc.), + # so the flat shape must be unknown. + return [tensor_shape.unknown_shape(None)] @property def _flat_types(self): @@ -428,8 +471,11 @@ class SparseTensorStructure(Structure): return self._from_compatible_tensor_list(flat_value) def _from_compatible_tensor_list(self, flat_value): - return sparse_ops.deserialize_sparse( + ret = sparse_ops.deserialize_sparse( flat_value[0], dtype=self._dtype, rank=self._dense_shape.ndims) + ret.indices.set_shape([None, self._dense_shape.ndims]) + ret.dense_shape.set_shape([self._dense_shape.ndims]) + return ret @staticmethod def from_value(value): @@ -446,3 +492,8 @@ class SparseTensorStructure(Structure): def _to_legacy_output_classes(self): return sparse_tensor_lib.SparseTensor + + def _batch(self, batch_size): + return SparseTensorStructure( + self._dtype, + tensor_shape.TensorShape([batch_size]).concatenate(self._dense_shape)) diff --git a/tensorflow/python/data/util/structure_test.py b/tensorflow/python/data/util/structure_test.py index 630a0c912b..314a459eff 100644 --- a/tensorflow/python/data/util/structure_test.py +++ b/tensorflow/python/data/util/structure_test.py @@ -28,6 +28,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test @@ -44,7 +45,7 @@ class StructureTest(test.TestCase, parameterized.TestCase): [dtypes.float32], [[]]), (lambda: sparse_tensor.SparseTensor( indices=[[3, 4]], values=[-1], dense_shape=[4, 5]), - structure.SparseTensorStructure, [dtypes.variant], [[3]]), + structure.SparseTensorStructure, [dtypes.variant], [None]), (lambda: (constant_op.constant(37.0), constant_op.constant([1, 2, 3])), structure.NestedStructure, [dtypes.float32, dtypes.int32], [[], [3]]), (lambda: { @@ -58,14 +59,17 @@ class StructureTest(test.TestCase, parameterized.TestCase): sparse_tensor.SparseTensor( indices=[[3, 4]], values=[-1], dense_shape=[4, 5])) }, structure.NestedStructure, - [dtypes.float32, dtypes.variant, dtypes.variant], [[], [3], [3]])) + [dtypes.float32, dtypes.variant, dtypes.variant], [[], None, None])) def testFlatStructure(self, value_fn, expected_structure, expected_types, expected_shapes): value = value_fn() s = structure.Structure.from_value(value) self.assertIsInstance(s, expected_structure) self.assertEqual(expected_types, s._flat_types) - self.assertEqual(expected_shapes, s._flat_shapes) + for expected, actual in zip(expected_shapes, s._flat_shapes): + self.assertTrue(actual.is_compatible_with(expected)) + self.assertTrue( + tensor_shape.as_shape(expected).is_compatible_with(actual)) @parameterized.parameters( (lambda: constant_op.constant(37.0), lambda: [ @@ -112,6 +116,7 @@ class StructureTest(test.TestCase, parameterized.TestCase): indices=[[0], [1], [2]], values=[4, 5, 6], dense_shape=[3]) }, (constant_op.constant(15.0), constant_op.constant([4, 5, 6]))]), ) + @test_util.run_deprecated_v1 def testIsCompatibleWithStructure( self, original_value_fn, compatible_values_fn, incompatible_values_fn): original_value = original_value_fn() @@ -354,5 +359,65 @@ class StructureTest(test.TestCase, parameterized.TestCase): self.assertTrue(expected_structure.is_compatible_with(actual_structure)) self.assertTrue(actual_structure.is_compatible_with(expected_structure)) + def testNestedNestedStructure(self): + # Although `Structure.from_value()` will not construct one, a nested + # structure containing nested `NestedStructure` objects can occur if a + # structure is constructed manually. + s = structure.NestedStructure( + (structure.TensorStructure(dtypes.int64, []), + structure.NestedStructure( + (structure.TensorStructure(dtypes.float32, []), + structure.TensorStructure(dtypes.string, []))))) + + int64_t = constant_op.constant(37, dtype=dtypes.int64) + float32_t = constant_op.constant(42.0) + string_t = constant_op.constant("Foo") + + nested_tensors = (int64_t, (float32_t, string_t)) + + tensor_list = s._to_tensor_list(nested_tensors) + for expected, actual in zip([int64_t, float32_t, string_t], tensor_list): + self.assertIs(expected, actual) + + (actual_int64_t, (actual_float32_t, actual_string_t)) = s._from_tensor_list( + tensor_list) + self.assertIs(int64_t, actual_int64_t) + self.assertIs(float32_t, actual_float32_t) + self.assertIs(string_t, actual_string_t) + + (actual_int64_t, (actual_float32_t, actual_string_t)) = ( + s._from_compatible_tensor_list(tensor_list)) + self.assertIs(int64_t, actual_int64_t) + self.assertIs(float32_t, actual_float32_t) + self.assertIs(string_t, actual_string_t) + + @parameterized.named_parameters( + ("Tensor", structure.TensorStructure(dtypes.float32, []), 32, + structure.TensorStructure(dtypes.float32, [32])), + ("TensorUnknown", structure.TensorStructure(dtypes.float32, []), None, + structure.TensorStructure(dtypes.float32, [None])), + ("SparseTensor", structure.SparseTensorStructure(dtypes.float32, [None]), + 32, structure.SparseTensorStructure(dtypes.float32, [32, None])), + ("SparseTensorUnknown", + structure.SparseTensorStructure(dtypes.float32, [4]), None, + structure.SparseTensorStructure(dtypes.float32, [None, 4])), + ("Nest", structure.NestedStructure({ + "a": structure.TensorStructure(dtypes.float32, []), + "b": (structure.SparseTensorStructure(dtypes.int32, [2, 2]), + structure.TensorStructure(dtypes.string, []))}), 128, + structure.NestedStructure({ + "a": structure.TensorStructure(dtypes.float32, [128]), + "b": (structure.SparseTensorStructure(dtypes.int32, [128, 2, 2]), + structure.TensorStructure(dtypes.string, [128]))})), + ) + def testBatch(self, element_structure, batch_size, + expected_batched_structure): + batched_structure = element_structure._batch(batch_size) + self.assertTrue( + batched_structure.is_compatible_with(expected_batched_structure)) + self.assertTrue( + expected_batched_structure.is_compatible_with(batched_structure)) + + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/debug/BUILD b/tensorflow/python/debug/BUILD index 7995123209..c6abd476d9 100644 --- a/tensorflow/python/debug/BUILD +++ b/tensorflow/python/debug/BUILD @@ -557,6 +557,7 @@ py_test( ":source_utils", "//tensorflow/core:protos_all_py", "//tensorflow/python:client", + "//tensorflow/python:cond_v2", "//tensorflow/python:constant_op", "//tensorflow/python:control_flow_ops", "//tensorflow/python:framework_ops", @@ -566,6 +567,7 @@ py_test( "//tensorflow/python:resource_variable_ops", "//tensorflow/python:util", "//tensorflow/python:variables", + "//tensorflow/python:while_v2", "//third_party/py/numpy", ], ) diff --git a/tensorflow/python/debug/cli/analyzer_cli_test.py b/tensorflow/python/debug/cli/analyzer_cli_test.py index f197a9e4dc..322ecf9466 100644 --- a/tensorflow/python/debug/cli/analyzer_cli_test.py +++ b/tensorflow/python/debug/cli/analyzer_cli_test.py @@ -645,6 +645,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): self.assertEqual(len("Size (B)") + 1, dump_size_col_width) self.assertEqual(len("Op type") + 1, op_type_col_width) + @test_util.run_deprecated_v1 def testMeasureTensorListColumnWidthsGivesRightAnswerForData(self): dump = self._debug_dump.dumped_tensor_data[0] self.assertLess(dump.dump_size_bytes, 1000) @@ -660,6 +661,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): # column should be determined by the length of "VariableV2". self.assertEqual(len("VariableV2") + 1, op_type_col_width) + @test_util.run_deprecated_v1 def testListTensors(self): # Use shorthand alias for the command prefix. out = self._registry.dispatch_command("lt", []) @@ -673,6 +675,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): # Check the main menu. check_main_menu(self, out, list_tensors_enabled=False) + @test_util.run_deprecated_v1 def testListTensorsInReverseTimeOrderWorks(self): # Use shorthand alias for the command prefix. out = self._registry.dispatch_command("lt", ["-s", "timestamp", "-r"]) @@ -688,6 +691,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): reverse=True) check_main_menu(self, out, list_tensors_enabled=False) + @test_util.run_deprecated_v1 def testListTensorsInDumpSizeOrderWorks(self): out = self._registry.dispatch_command("lt", ["-s", "dump_size"]) assert_listed_tensors( @@ -701,6 +705,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): sort_by="dump_size") check_main_menu(self, out, list_tensors_enabled=False) + @test_util.run_deprecated_v1 def testListTensorsInReverseDumpSizeOrderWorks(self): out = self._registry.dispatch_command("lt", ["-s", "dump_size", "-r"]) assert_listed_tensors( @@ -720,6 +725,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): self.assertIn("ValueError: Unsupported key to sort tensors by: foobar", out.lines) + @test_util.run_deprecated_v1 def testListTensorsInOpTypeOrderWorks(self): # Use shorthand alias for the command prefix. out = self._registry.dispatch_command("lt", ["-s", "op_type"]) @@ -735,6 +741,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): reverse=False) check_main_menu(self, out, list_tensors_enabled=False) + @test_util.run_deprecated_v1 def testListTensorsInReverseOpTypeOrderWorks(self): # Use shorthand alias for the command prefix. out = self._registry.dispatch_command("lt", ["-s", "op_type", "-r"]) @@ -750,6 +757,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): reverse=True) check_main_menu(self, out, list_tensors_enabled=False) + @test_util.run_deprecated_v1 def testListTensorsInTensorNameOrderWorks(self): # Use shorthand alias for the command prefix. out = self._registry.dispatch_command("lt", ["-s", "tensor_name"]) @@ -765,6 +773,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): reverse=False) check_main_menu(self, out, list_tensors_enabled=False) + @test_util.run_deprecated_v1 def testListTensorsInReverseTensorNameOrderWorks(self): # Use shorthand alias for the command prefix. out = self._registry.dispatch_command("lt", ["-s", "tensor_name", "-r"]) @@ -780,6 +789,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): reverse=True) check_main_menu(self, out, list_tensors_enabled=False) + @test_util.run_deprecated_v1 def testListTensorsFilterByNodeNameRegex(self): out = self._registry.dispatch_command("list_tensors", ["--node_name_filter", ".*read.*"]) @@ -793,6 +803,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): assert_listed_tensors(self, out, [], [], node_name_regex="^read") check_main_menu(self, out, list_tensors_enabled=False) + @test_util.run_deprecated_v1 def testListTensorFilterByOpTypeRegex(self): out = self._registry.dispatch_command("list_tensors", ["--op_type_filter", "Identity"]) @@ -821,6 +832,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): op_type_regex="(Add|MatMul)") check_main_menu(self, out, list_tensors_enabled=False) + @test_util.run_deprecated_v1 def testListTensorWithFilterAndNodeNameExclusionWorks(self): # First, create and register the filter. def is_2x1_vector(datum, tensor): @@ -877,6 +889,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): out = self._registry.dispatch_command("list_tensors", ["--bar"]) check_syntax_error_output(self, out, "list_tensors") + @test_util.run_deprecated_v1 def testNodeInfoByNodeName(self): node_name = "simple_mul_add/matmul" out = self._registry.dispatch_command("node_info", [node_name]) @@ -901,6 +914,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): [(len(out.lines[0]) - len(node_name), len(out.lines[0]), "bold")], out.font_attr_segs[0]) + @test_util.run_deprecated_v1 def testNodeInfoShowAttributes(self): node_name = "simple_mul_add/matmul" out = self._registry.dispatch_command("node_info", ["-a", node_name]) @@ -924,6 +938,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): print_tensor_node_name=node_name, list_outputs_node_name=node_name) + @test_util.run_deprecated_v1 def testNodeInfoShowDumps(self): node_name = "simple_mul_add/matmul" out = self._registry.dispatch_command("node_info", ["-d", node_name]) @@ -948,6 +963,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): len(out.lines[16]) - len(out.lines[16].strip()), len(out.lines[16]), "pt %s:0 -n 0" % node_name) + @test_util.run_deprecated_v1 def testNodeInfoShowStackTraceUnavailableIsIndicated(self): self._debug_dump.set_python_graph(None) @@ -971,6 +987,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): print_tensor_node_name=node_name, list_outputs_node_name=node_name) + @test_util.run_deprecated_v1 def testNodeInfoShowStackTraceAvailableWorks(self): self._debug_dump.set_python_graph(self._sess.graph) @@ -994,6 +1011,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): print_tensor_node_name=node_name, list_outputs_node_name=node_name) + @test_util.run_deprecated_v1 def testNodeInfoByTensorName(self): node_name = "simple_mul_add/u/read" tensor_name = node_name + ":0" @@ -1363,6 +1381,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): break return index + @test_util.run_deprecated_v1 def testPrintSourceForOpNamesWholeFileWorks(self): self._debug_dump.set_python_graph(self._sess.graph) out = self._registry.dispatch_command( @@ -1415,6 +1434,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): self.assertEqual("pt simple_mul_add/add", out.font_attr_segs[index + 1][0][2].content) + @test_util.run_deprecated_v1 def testPrintSourceForTensorNamesWholeFileWorks(self): self._debug_dump.set_python_graph(self._sess.graph) out = self._registry.dispatch_command( @@ -1435,6 +1455,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): self.assertEqual("pt simple_mul_add/u:0", out.font_attr_segs[index + 2][0][2].content) + @test_util.run_deprecated_v1 def testPrintSourceForOpNamesStartingAtSpecifiedLineWorks(self): self._debug_dump.set_python_graph(self._sess.graph) out = self._registry.dispatch_command( @@ -1461,6 +1482,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): self.assertEqual("pt simple_mul_add/u/read", out.font_attr_segs[index + 3][0][2].content) + @test_util.run_deprecated_v1 def testPrintSourceForOpNameSettingMaximumElementCountWorks(self): self._debug_dump.set_python_graph(self._sess.graph) out = self._registry.dispatch_command( @@ -1505,6 +1527,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): self.assertTrue(cli_shared.COLOR_GRAY in attr_seg[2] or attr_seg[2] == cli_shared.COLOR_GRAY) + @test_util.run_deprecated_v1 def testListSourceWithNodeNameFilterWithMatchesWorks(self): self._debug_dump.set_python_graph(self._sess.graph) out = self._registry.dispatch_command("list_source", ["-n", ".*/read"]) @@ -1583,7 +1606,7 @@ class AnalyzerCLISimpleMulAddTest(test_util.TensorFlowTestCase): x = variables.VariableV1([1, 3, 3, 7], name="x") _, idx = array_ops.unique(x, name="x_unique") idx_times_two = math_ops.multiply(idx, 2, name="idx_times_two") - sess.run(x.initializer) + self.evaluate(x.initializer) run_options = config_pb2.RunOptions(output_partition_graphs=True) debug_utils.watch_graph( @@ -1719,6 +1742,7 @@ class AnalyzerCLIControlDepTest(test_util.TensorFlowTestCase): # Tear down temporary dump directory. shutil.rmtree(cls._dump_root) + @test_util.run_deprecated_v1 def testNodeInfoWithControlDependencies(self): # Call node_info on a node with control inputs. out = self._registry.dispatch_command("node_info", @@ -1759,6 +1783,7 @@ class AnalyzerCLIControlDepTest(test_util.TensorFlowTestCase): len(out.lines[z_line]), "ni -a -d -t control_deps/ctrl_dep_z") + @test_util.run_deprecated_v1 def testListInputsNonRecursiveNoControl(self): """List inputs non-recursively, without any control inputs.""" @@ -1801,6 +1826,7 @@ class AnalyzerCLIControlDepTest(test_util.TensorFlowTestCase): len(out.lines[3]) - len("control_deps/ctrl_dep_y"), len(out.lines[3]), "li -c -r control_deps/ctrl_dep_y") + @test_util.run_deprecated_v1 def testListInputsNonRecursiveNoControlUsingTensorName(self): """List inputs using the name of an output tensor of the node.""" @@ -1829,6 +1855,7 @@ class AnalyzerCLIControlDepTest(test_util.TensorFlowTestCase): len(out.lines[3]) - len("control_deps/ctrl_dep_y"), len(out.lines[3]), "li -c -r control_deps/ctrl_dep_y") + @test_util.run_deprecated_v1 def testListInputsNonRecursiveWithControls(self): """List inputs non-recursively, with control inputs.""" node_name = "control_deps/ctrl_dep_z" @@ -1859,6 +1886,7 @@ class AnalyzerCLIControlDepTest(test_util.TensorFlowTestCase): len(out.lines[5]) - len("control_deps/x"), len(out.lines[5]), "li -c -r control_deps/x") + @test_util.run_deprecated_v1 def testListInputsRecursiveWithControls(self): """List inputs recursively, with control inputs.""" node_name = "control_deps/ctrl_dep_z" @@ -1904,6 +1932,7 @@ class AnalyzerCLIControlDepTest(test_util.TensorFlowTestCase): len(out.lines[18]) - len("control_deps/x"), len(out.lines[18]), "li -c -r control_deps/x") + @test_util.run_deprecated_v1 def testListInputsRecursiveWithControlsWithDepthLimit(self): """List inputs recursively, with control inputs and a depth limit.""" node_name = "control_deps/ctrl_dep_z" @@ -1963,6 +1992,7 @@ class AnalyzerCLIControlDepTest(test_util.TensorFlowTestCase): "ERROR: There is no node named \"control_deps/z/foo\" in the " "partition graphs"], out.lines) + @test_util.run_deprecated_v1 def testListRecipientsRecursiveWithControlsWithDepthLimit(self): """List recipients recursively, with control inputs and a depth limit.""" @@ -2034,6 +2064,7 @@ class AnalyzerCLIWhileLoopTest(test_util.TensorFlowTestCase): # Tear down temporary dump directory. shutil.rmtree(cls._dump_root) + @test_util.run_deprecated_v1 def testMultipleDumpsPrintTensorNoNumber(self): output = self._registry.dispatch_command("pt", ["while/Identity:0"]) @@ -2051,6 +2082,7 @@ class AnalyzerCLIWhileLoopTest(test_util.TensorFlowTestCase): self.assertEqual("For example:", output.lines[-2]) self.assertEqual(" print_tensor while/Identity:0 -n 0", output.lines[-1]) + @test_util.run_deprecated_v1 def testMultipleDumpsPrintTensorWithNumber(self): for i in xrange(5): output = self._registry.dispatch_command( @@ -2064,6 +2096,7 @@ class AnalyzerCLIWhileLoopTest(test_util.TensorFlowTestCase): self.assertTrue(output.lines[4].startswith("array(%d" % i)) self.assertTrue(output.lines[4].endswith(")")) + @test_util.run_deprecated_v1 def testMultipleDumpsPrintTensorInvalidNumber(self): output = self._registry.dispatch_command("pt", ["while/Identity:0", "-n", "10"]) diff --git a/tensorflow/python/debug/cli/cli_shared_test.py b/tensorflow/python/debug/cli/cli_shared_test.py index 07b364db9f..d191a234fd 100644 --- a/tensorflow/python/debug/cli/cli_shared_test.py +++ b/tensorflow/python/debug/cli/cli_shared_test.py @@ -118,6 +118,7 @@ class GetRunStartIntroAndDescriptionTest(test_util.TensorFlowTestCase): def tearDown(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testSingleFetchNoFeeds(self): run_start_intro = cli_shared.get_run_start_intro(12, self.const_a, None, {}) @@ -181,6 +182,7 @@ class GetRunStartIntroAndDescriptionTest(test_util.TensorFlowTestCase): run_start_intro = cli_shared.get_run_start_intro(1, self.sparse_d, None, {}) self.assertEqual(str(self.sparse_d), run_start_intro.lines[4].strip()) + @test_util.run_deprecated_v1 def testTwoFetchesListNoFeeds(self): fetches = [self.const_a, self.const_b] run_start_intro = cli_shared.get_run_start_intro(1, fetches, None, {}) @@ -197,6 +199,7 @@ class GetRunStartIntroAndDescriptionTest(test_util.TensorFlowTestCase): description = cli_shared.get_run_short_description(1, fetches, None) self.assertEqual("run #1: 2 fetches; 0 feeds", description) + @test_util.run_deprecated_v1 def testNestedListAsFetches(self): fetches = [self.const_c, [self.const_a, self.const_b]] run_start_intro = cli_shared.get_run_start_intro(1, fetches, None, {}) @@ -210,6 +213,7 @@ class GetRunStartIntroAndDescriptionTest(test_util.TensorFlowTestCase): description = cli_shared.get_run_short_description(1, fetches, None) self.assertEqual("run #1: 3 fetches; 0 feeds", description) + @test_util.run_deprecated_v1 def testNestedDictAsFetches(self): fetches = {"c": self.const_c, "ab": {"a": self.const_a, "b": self.const_b}} run_start_intro = cli_shared.get_run_start_intro(1, fetches, None, {}) @@ -227,6 +231,7 @@ class GetRunStartIntroAndDescriptionTest(test_util.TensorFlowTestCase): description = cli_shared.get_run_short_description(1, fetches, None) self.assertEqual("run #1: 3 fetches; 0 feeds", description) + @test_util.run_deprecated_v1 def testTwoFetchesAsTupleNoFeeds(self): fetches = (self.const_a, self.const_b) run_start_intro = cli_shared.get_run_start_intro(1, fetches, None, {}) @@ -243,6 +248,7 @@ class GetRunStartIntroAndDescriptionTest(test_util.TensorFlowTestCase): description = cli_shared.get_run_short_description(1, fetches, None) self.assertEqual("run #1: 2 fetches; 0 feeds", description) + @test_util.run_deprecated_v1 def testTwoFetchesAsNamedTupleNoFeeds(self): fetches_namedtuple = namedtuple("fetches", "x y") fetches = fetches_namedtuple(self.const_b, self.const_c) @@ -260,6 +266,7 @@ class GetRunStartIntroAndDescriptionTest(test_util.TensorFlowTestCase): description = cli_shared.get_run_short_description(1, fetches, None) self.assertEqual("run #1: 2 fetches; 0 feeds", description) + @test_util.run_deprecated_v1 def testWithFeedDict(self): feed_dict = { self.const_a: 10.0, @@ -283,6 +290,7 @@ class GetRunStartIntroAndDescriptionTest(test_util.TensorFlowTestCase): feed_dict) self.assertEqual("run #1: 1 fetch (c:0); 2 feeds", description) + @test_util.run_deprecated_v1 def testTensorFilters(self): feed_dict = {self.const_a: 10.0} tensor_filters = { @@ -313,11 +321,13 @@ class GetRunStartIntroAndDescriptionTest(test_util.TensorFlowTestCase): command_set.add(annot[2].content) self.assertEqual({"run -f filter_a", "run -f filter_b"}, command_set) + @test_util.run_deprecated_v1 def testGetRunShortDescriptionWorksForTensorFeedKey(self): short_description = cli_shared.get_run_short_description( 1, self.const_a, {self.const_a: 42.0}) self.assertEqual("run #1: 1 fetch (a:0); 1 feed (a:0)", short_description) + @test_util.run_deprecated_v1 def testGetRunShortDescriptionWorksForUnicodeFeedKey(self): short_description = cli_shared.get_run_short_description( 1, self.const_a, {u"foo": 42.0}) @@ -332,6 +342,7 @@ class GetErrorIntroTest(test_util.TensorFlowTestCase): def tearDown(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testShapeError(self): tf_error = errors.OpError(None, self.var_a.initializer, "foo description", None) diff --git a/tensorflow/python/debug/cli/profile_analyzer_cli_test.py b/tensorflow/python/debug/cli/profile_analyzer_cli_test.py index 60b6047970..effcd500c7 100644 --- a/tensorflow/python/debug/cli/profile_analyzer_cli_test.py +++ b/tensorflow/python/debug/cli/profile_analyzer_cli_test.py @@ -348,6 +348,7 @@ class ProfileAnalyzerPrintSourceTest(test_util.TensorFlowTestCase): ops.reset_default_graph() super(ProfileAnalyzerPrintSourceTest, self).tearDown() + @test_util.run_deprecated_v1 def testPrintSourceForWhileLoop(self): prof_output = self.prof_analyzer.print_source([__file__]) @@ -361,6 +362,7 @@ class ProfileAnalyzerPrintSourceTest(test_util.TensorFlowTestCase): r"\[(\|)+(\s)*\] .*us .*7\(55\) .*L%d.*(\S)+" % self.loop_lineno, prof_output.lines) + @test_util.run_deprecated_v1 def testPrintSourceOutputContainsClickableLinks(self): prof_output = self.prof_analyzer.print_source([__file__]) any_match, line_index = _at_least_one_line_matches( @@ -377,6 +379,7 @@ class ProfileAnalyzerPrintSourceTest(test_util.TensorFlowTestCase): break self.assertTrue(any_menu_item_match) + @test_util.run_deprecated_v1 def testPrintSourceWithNonDefaultTimeUnit(self): prof_output = self.prof_analyzer.print_source([ __file__, "--time_unit", "ms"]) @@ -391,6 +394,7 @@ class ProfileAnalyzerPrintSourceTest(test_util.TensorFlowTestCase): r"\[(\|)+(\s)*\] .*ms .*7\(55\) .*L%d.*(\S)+" % self.loop_lineno, prof_output.lines) + @test_util.run_deprecated_v1 def testPrintSourceWithNodeNameFilter(self): prof_output = self.prof_analyzer.print_source([ __file__, "--node_name_filter", "x$"]) @@ -423,6 +427,7 @@ class ProfileAnalyzerPrintSourceTest(test_util.TensorFlowTestCase): break self.assertTrue(any_menu_item_match) + @test_util.run_deprecated_v1 def testPrintSourceWithOpTypeFilter(self): prof_output = self.prof_analyzer.print_source([ __file__, "--op_type_filter", "Less"]) diff --git a/tensorflow/python/debug/lib/common_test.py b/tensorflow/python/debug/lib/common_test.py index 5af0dafcf9..f6413f6b7b 100644 --- a/tensorflow/python/debug/lib/common_test.py +++ b/tensorflow/python/debug/lib/common_test.py @@ -27,6 +27,7 @@ from tensorflow.python.platform import googletest class CommonTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testOnFeedOneFetch(self): a = constant_op.constant(10.0, name="a") b = constant_op.constant(20.0, name="b") @@ -35,6 +36,7 @@ class CommonTest(test_util.TensorFlowTestCase): self.assertItemsEqual(["a:0"], loaded[0]) self.assertItemsEqual(["b:0"], loaded[1]) + @test_util.run_deprecated_v1 def testGetRunKeyFlat(self): a = constant_op.constant(10.0, name="a") b = constant_op.constant(20.0, name="b") @@ -43,6 +45,7 @@ class CommonTest(test_util.TensorFlowTestCase): self.assertItemsEqual(["a:0"], loaded[0]) self.assertItemsEqual(["a:0", "b:0"], loaded[1]) + @test_util.run_deprecated_v1 def testGetRunKeyNestedFetches(self): a = constant_op.constant(10.0, name="a") b = constant_op.constant(20.0, name="b") diff --git a/tensorflow/python/debug/lib/debug_gradients_test.py b/tensorflow/python/debug/lib/debug_gradients_test.py index 01867fc69d..1c53147863 100644 --- a/tensorflow/python/debug/lib/debug_gradients_test.py +++ b/tensorflow/python/debug/lib/debug_gradients_test.py @@ -54,6 +54,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): ops.reset_default_graph() debug_gradients.clear_gradient_debuggers() + @test_util.run_deprecated_v1 def testIdentifyGradientGivesCorrectTensorObjectWithoutContextManager(self): grad_debugger = debug_gradients.GradientsDebugger() id_grad_w = grad_debugger.identify_gradient(self.w) @@ -84,6 +85,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertIsInstance(w_grad, ops.Tensor) self.assertAllClose(1.0, self.sess.run(w_grad)) + @test_util.run_deprecated_v1 def testIdentifyGradientGivesCorrectTensorObjectWithTfGradients(self): grad_debugger = debug_gradients.GradientsDebugger() id_grad_w = grad_debugger.identify_gradient(self.w) @@ -115,6 +117,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertIsInstance(w_grad, ops.Tensor) self.assertAllClose(1.0, self.sess.run(w_grad)) + @test_util.run_deprecated_v1 def testCallingIdentifyGradientTwiceWithTheSameGradientsDebuggerErrors(self): grad_debugger = debug_gradients.GradientsDebugger() grad_debugger.identify_gradient(self.w) @@ -122,6 +125,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): "The graph already contains an op named .*"): grad_debugger.identify_gradient(self.w) + @test_util.run_deprecated_v1 def testIdentifyGradientWorksOnMultipleLosses(self): grad_debugger_1 = debug_gradients.GradientsDebugger() grad_debugger_2 = debug_gradients.GradientsDebugger() @@ -150,6 +154,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertAllClose(2.0 * 5.0, self.sess.run(dz1_dy)) self.assertAllClose(0.5 * (5.0**-0.5), self.sess.run(dz2_dy)) + @test_util.run_deprecated_v1 def testIdentifyGradientRaisesLookupErrorForUnknownXTensor(self): grad_debugger_1 = debug_gradients.GradientsDebugger() grad_debugger_2 = debug_gradients.GradientsDebugger() @@ -170,6 +175,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): r"This GradientsDebugger has not received any gradient tensor for "): grad_debugger_2.gradient_tensor(self.w) + @test_util.run_deprecated_v1 def testIdentifyGradientRaisesTypeErrorForNonTensorOrTensorNameInput(self): grad_debugger = debug_gradients.GradientsDebugger() with self.assertRaisesRegexp( @@ -178,6 +184,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): r"has type .*Operation.*"): grad_debugger.gradient_tensor(variables.global_variables_initializer()) + @test_util.run_deprecated_v1 def testIdentifyGradientTensorWorksWithGradientDescentOptimizer(self): grad_debugger = debug_gradients.GradientsDebugger() id_grad_w = grad_debugger.identify_gradient(self.w) @@ -193,6 +200,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertIsInstance(w_grad, ops.Tensor) self.assertAllClose(1.0, self.sess.run(w_grad)) + @test_util.run_deprecated_v1 def testWatchGradientsByXTensorNamesWorks(self): y = math_ops.add(self.w, -1.0, name="y") @@ -219,6 +227,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertIsInstance(w_grad, ops.Tensor) self.assertAllClose(1.0, self.sess.run(w_grad)) + @test_util.run_deprecated_v1 def testWatchGradientsByXTensorNamesWorksWithoutContextManager(self): y = math_ops.add(self.w, -1.0, name="y") @@ -245,6 +254,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertIsInstance(w_grad, ops.Tensor) self.assertAllClose(1.0, self.sess.run(w_grad)) + @test_util.run_deprecated_v1 def testWatchGradientsWorksOnRefTensor(self): y = math_ops.add(self.w, -1.0, name="y") @@ -263,6 +273,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertAllClose(3.0, self.sess.run( grad_debugger.gradient_tensor("u:0"))) + @test_util.run_deprecated_v1 def testWatchGradientsWorksOnMultipleTensors(self): y = math_ops.add(self.w, -1.0, name="y") @@ -283,6 +294,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertAllClose(3.0, self.sess.run( grad_debugger.gradient_tensor("u:0"))) + @test_util.run_deprecated_v1 def testWatchGradientsByXTensorsWorks(self): y = math_ops.add(self.w, -1.0, name="foo/y") z = math_ops.square(y, name="foo/z") @@ -305,6 +317,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertAllClose(10.0, self.sess.run(w_grad)) self.assertAllClose(30.0, self.sess.run(u_grad)) + @test_util.run_deprecated_v1 def testWatchGradientsByTensorCanWorkOnMultipleLosses(self): y = math_ops.add(self.w, -1.0, name="y") z1 = math_ops.square(y, name="z1") @@ -330,6 +343,7 @@ class IdentifyGradientTest(test_util.TensorFlowTestCase): self.assertAllClose(2.0 * 5.0, self.sess.run(dz1_dy)) self.assertAllClose(0.5 * (5.0**-0.5), self.sess.run(dz2_dy)) + @test_util.run_deprecated_v1 def testGradientsValuesFromDumpWorks(self): y = math_ops.add(self.w, -1.0, name="y") z = math_ops.square(y, name="z") diff --git a/tensorflow/python/debug/lib/debug_graph_reconstruction_test.py b/tensorflow/python/debug/lib/debug_graph_reconstruction_test.py index 1f67f8a0d4..34030c0adc 100644 --- a/tensorflow/python/debug/lib/debug_graph_reconstruction_test.py +++ b/tensorflow/python/debug/lib/debug_graph_reconstruction_test.py @@ -126,8 +126,8 @@ class ReconstructNonDebugGraphTest(test_util.TensorFlowTestCase): u = variables.Variable([12.0], name="u") v = variables.Variable([30.0], name="v") w = math_ops.add(u, v, name="w") - sess.run(u.initializer) - sess.run(v.initializer) + self.evaluate(u.initializer) + self.evaluate(v.initializer) self._compareOriginalAndReconstructedGraphDefs( sess, w, expected_output=[42.0]) @@ -139,7 +139,7 @@ class ReconstructNonDebugGraphTest(test_util.TensorFlowTestCase): b = math_ops.add(a, a, name="b") with ops.control_dependencies([a, b]): c = math_ops.multiply(b, b, name="c") - sess.run(a.initializer) + self.evaluate(a.initializer) self._compareOriginalAndReconstructedGraphDefs( sess, c, expected_output=400.0) @@ -150,8 +150,8 @@ class ReconstructNonDebugGraphTest(test_util.TensorFlowTestCase): y = variables.Variable(20.0, name="y") cond = control_flow_ops.cond( x > y, lambda: math_ops.add(x, 1), lambda: math_ops.add(y, 1)) - sess.run(x.initializer) - sess.run(y.initializer) + self.evaluate(x.initializer) + self.evaluate(y.initializer) self._compareOriginalAndReconstructedGraphDefs( sess, cond, expected_output=21.0) @@ -173,8 +173,8 @@ class ReconstructNonDebugGraphTest(test_util.TensorFlowTestCase): toy_loss = x * (u - v) train_op = gradient_descent.GradientDescentOptimizer( learning_rate=0.1).minimize(toy_loss, name="train_op") - sess.run(u.initializer) - sess.run(v.initializer) + self.evaluate(u.initializer) + self.evaluate(v.initializer) self._compareOriginalAndReconstructedGraphDefs(sess, train_op) diff --git a/tensorflow/python/debug/lib/debug_utils_test.py b/tensorflow/python/debug/lib/debug_utils_test.py index 23ab98444c..cf59b30e3d 100644 --- a/tensorflow/python/debug/lib/debug_utils_test.py +++ b/tensorflow/python/debug/lib/debug_utils_test.py @@ -185,6 +185,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): self.assertEqual(["file:///tmp/tfdbg_1", "file:///tmp/tfdbg_2"], watch_0.debug_urls) + @test_util.run_deprecated_v1 def testWatchGraph_allNodes(self): debug_utils.watch_graph( self._run_options, @@ -216,6 +217,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): self.assertTrue("p1" in node_names) self.assertTrue("s" in node_names) + @test_util.run_deprecated_v1 def testWatchGraph_nodeNameWhitelist(self): debug_utils.watch_graph( self._run_options, @@ -230,6 +232,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): sorted(["a1_init", "a1", "a1/Assign", "a1/read", "p1"]), sorted(node_names)) + @test_util.run_deprecated_v1 def testWatchGraph_opTypeWhitelist(self): debug_utils.watch_graph( self._run_options, @@ -255,6 +258,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): ["DebugIdentity"], ["file:///tmp/tfdbg_1"]) self.assertEqual(["p1"], node_names) + @test_util.run_deprecated_v1 def testWatchGraph_tensorDTypeWhitelist(self): debug_utils.watch_graph( self._run_options, @@ -267,6 +271,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): ["DebugIdentity"], ["file:///tmp/tfdbg_1"]) self.assertItemsEqual(["a1", "a1/Assign", "b", "b/Assign"], node_names) + @test_util.run_deprecated_v1 def testWatchGraph_nodeNameAndTensorDTypeWhitelists(self): debug_utils.watch_graph( self._run_options, @@ -280,6 +285,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): ["DebugIdentity"], ["file:///tmp/tfdbg_1"]) self.assertItemsEqual(["a1", "a1/Assign"], node_names) + @test_util.run_deprecated_v1 def testWatchGraph_nodeNameBlacklist(self): debug_utils.watch_graph_with_blacklists( self._run_options, @@ -294,6 +300,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): sorted(["b_init", "b", "b/Assign", "b/read", "c", "s"]), sorted(node_names)) + @test_util.run_deprecated_v1 def testWatchGraph_opTypeBlacklist(self): debug_utils.watch_graph_with_blacklists( self._run_options, @@ -306,6 +313,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): ["DebugIdentity"], ["file:///tmp/tfdbg_1"]) self.assertEqual(sorted(["p1", "s"]), sorted(node_names)) + @test_util.run_deprecated_v1 def testWatchGraph_nodeNameAndOpTypeBlacklists(self): debug_utils.watch_graph_with_blacklists( self._run_options, @@ -319,6 +327,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): ["DebugIdentity"], ["file:///tmp/tfdbg_1"]) self.assertEqual(["s"], node_names) + @test_util.run_deprecated_v1 def testWatchGraph_tensorDTypeBlacklists(self): debug_utils.watch_graph_with_blacklists( self._run_options, @@ -335,6 +344,7 @@ class DebugUtilsTest(test_util.TensorFlowTestCase): self.assertNotIn("b/Assign", node_names) self.assertIn("s", node_names) + @test_util.run_deprecated_v1 def testWatchGraph_nodeNameAndTensorDTypeBlacklists(self): debug_utils.watch_graph_with_blacklists( self._run_options, diff --git a/tensorflow/python/debug/lib/session_debug_file_test.py b/tensorflow/python/debug/lib/session_debug_file_test.py index 1874160dd6..f5f9ba29ab 100644 --- a/tensorflow/python/debug/lib/session_debug_file_test.py +++ b/tensorflow/python/debug/lib/session_debug_file_test.py @@ -28,6 +28,7 @@ from tensorflow.python.debug.lib import debug_utils from tensorflow.python.debug.lib import session_debug_testlib from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables from tensorflow.python.platform import googletest @@ -44,6 +45,7 @@ class SessionDebugFileTest(session_debug_testlib.SessionDebugTestBase): else: return os.path.join(self._dump_root, "run_%d" % run_number) + @test_util.run_deprecated_v1 def testAllowsDifferentWatchesOnDifferentRuns(self): """Test watching different tensors on different runs of the same graph.""" diff --git a/tensorflow/python/debug/lib/session_debug_multi_gpu_test.py b/tensorflow/python/debug/lib/session_debug_multi_gpu_test.py index b0dc25851c..8eef45392f 100644 --- a/tensorflow/python/debug/lib/session_debug_multi_gpu_test.py +++ b/tensorflow/python/debug/lib/session_debug_multi_gpu_test.py @@ -67,7 +67,7 @@ class SessionDebugMultiGPUTest(test_util.TensorFlowTestCase): u1 = math_ops.multiply(v, v, name="u1") w = math_ops.subtract(u1, u0, name="w") - sess.run(v.initializer) + self.evaluate(v.initializer) run_options = config_pb2.RunOptions(output_partition_graphs=True) debug_utils.watch_graph(run_options, sess.graph, diff --git a/tensorflow/python/debug/lib/source_utils_test.py b/tensorflow/python/debug/lib/source_utils_test.py index 4a8d4eaa99..9083297fdb 100644 --- a/tensorflow/python/debug/lib/source_utils_test.py +++ b/tensorflow/python/debug/lib/source_utils_test.py @@ -65,6 +65,7 @@ class GuessIsTensorFlowLibraryTest(test_util.TensorFlowTestCase): self.assertTrue( source_utils.guess_is_tensorflow_py_library(source_utils.__file__)) + @test_util.run_deprecated_v1 def testFileInPythonKernelsPathReturnsTrue(self): x = constant_op.constant(42.0, name="x") self.assertTrue( @@ -109,8 +110,8 @@ class SourceHelperTest(test_util.TensorFlowTestCase): self.w = math_ops.matmul(self.u, self.v, name="w") self.w_line_number = line_number_above() - sess.run(self.u.initializer) - sess.run(self.v.initializer) + self.evaluate(self.u.initializer) + self.evaluate(self.v.initializer) run_options = config_pb2.RunOptions(output_partition_graphs=True) debug_utils.watch_graph( diff --git a/tensorflow/python/debug/wrappers/framework_test.py b/tensorflow/python/debug/wrappers/framework_test.py index 73e08ce7d5..68584b4ede 100644 --- a/tensorflow/python/debug/wrappers/framework_test.py +++ b/tensorflow/python/debug/wrappers/framework_test.py @@ -339,7 +339,7 @@ class DebugWrapperSessionTest(test_util.TensorFlowTestCase): with wrapper.as_default(): foo = constant_op.constant(42, name="foo") - self.assertEqual(42, foo.eval()) + self.assertEqual(42, self.evaluate(foo)) self.assertEqual(foo, self._observer["run_fetches"]) def testWrapperShouldSupportSessionClose(self): diff --git a/tensorflow/python/distribute/BUILD b/tensorflow/python/distribute/BUILD index 1c3d8ea67e..2d9a1764db 100644 --- a/tensorflow/python/distribute/BUILD +++ b/tensorflow/python/distribute/BUILD @@ -7,15 +7,140 @@ licenses(["notice"]) # Apache 2.0 exports_files(["LICENSE"]) load("//tensorflow:tensorflow.bzl", "py_test") +load("//tensorflow:tensorflow.bzl", "tf_py_test") +load("//tensorflow:tensorflow.bzl", "cuda_py_test") py_library( - name = "distribute", + name = "all_reduce", + srcs = [ + "all_reduce.py", + ], srcs_version = "PY2AND3", - visibility = ["//visibility:public"], deps = [ - ":distribute_config", - ":distribute_coordinator", - ":distribute_coordinator_context", + "//tensorflow/python:array_ops", + "//tensorflow/python:framework_ops", + "//tensorflow/python:math_ops", + "//tensorflow/python:nccl_ops", + ], +) + +tf_py_test( + name = "all_reduce_test", + srcs = ["all_reduce_test.py"], + additional_deps = [ + ":all_reduce", + "//third_party/py/numpy", + "//tensorflow/core:protos_all_py", + "//tensorflow/python:array_ops", + "//tensorflow/python:client", + "//tensorflow/python:framework_ops", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:math_ops", + "//tensorflow/python:constant_op", + "//tensorflow/python:client_testlib", + "//tensorflow/python:platform", + "//tensorflow/python:platform_test", + "//tensorflow/python:state_ops", + ], +) + +py_library( + name = "cross_device_ops", + srcs = ["cross_device_ops.py"], + srcs_version = "PY2AND3", + deps = [ + ":cross_device_utils", + ":device_util", + ":reduce_util", + ":values", + "//tensorflow/python:array_ops", + "//tensorflow/python:device_lib", + "//tensorflow/python:framework_ops", + "//tensorflow/python:math_ops", + "//tensorflow/python:platform", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python/eager:context", + "@six_archive//:six", + ], +) + +py_library( + name = "cross_device_utils", + srcs = ["cross_device_utils.py"], + srcs_version = "PY2AND3", + deps = [ + ":all_reduce", + ":values", + "//tensorflow/python:array_ops", + "//tensorflow/python:collective_ops", + "//tensorflow/python:device", + "//tensorflow/python:dtypes", + "//tensorflow/python:framework_ops", + "//tensorflow/python:gradients", + "//tensorflow/python:math_ops", + "//tensorflow/python:nccl_ops", + ], +) + +py_library( + name = "device_util", + srcs = ["device_util.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:device", + "//tensorflow/python:framework_ops", + "//tensorflow/python/eager:context", + ], +) + +cuda_py_test( + name = "device_util_test", + srcs = ["device_util_test.py"], + additional_deps = [ + ":device_util", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_ops", + ], +) + +py_library( + name = "distribute_lib", + srcs = [ + "distribute_lib.py", + "distribution_strategy_context.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":device_util", + ":reduce_util", + "//tensorflow/python:array_ops", + "//tensorflow/python:constant_op", + "//tensorflow/python:control_flow_ops", + "//tensorflow/python:dtypes", + "//tensorflow/python:framework_ops", + "//tensorflow/python:platform", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:state_ops", + "//tensorflow/python:util", + "//tensorflow/python:variable_scope", + "//tensorflow/python/data", + "//tensorflow/python/distribute/cluster_resolver:cluster_resolver_lib", + "//tensorflow/python/ops/losses", + "//tensorflow/tools/docs:doc_controls", + ], +) + +py_test( + name = "distribute_lib_test", + size = "small", + srcs = ["distribute_lib_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":distribute_lib", + "//tensorflow/python:client_testlib", + "//tensorflow/python:constant_op", + "//tensorflow/python:dtypes", + "//tensorflow/python:variable_scope", ], ) @@ -45,7 +170,6 @@ py_library( py_test( name = "distribute_coordinator_test", - size = "large", srcs = ["distribute_coordinator_test.py"], srcs_version = "PY2AND3", tags = [ @@ -76,6 +200,35 @@ py_library( deps = [], ) +py_library( + name = "mirrored_strategy", + srcs = ["mirrored_strategy.py"], + deps = [ + ":cross_device_ops", + ":device_util", + ":distribute_lib", + ":multi_worker_util", + ":reduce_util", + ":shared_variable_creator", + ":values", + "//tensorflow/core:protos_all_py", + "//tensorflow/python:array_ops", + "//tensorflow/python:constant_op", + "//tensorflow/python:control_flow_ops", + "//tensorflow/python:device", + "//tensorflow/python:dtypes", + "//tensorflow/python:framework_ops", + "//tensorflow/python:pywrap_tensorflow", + "//tensorflow/python:tensor_util", + "//tensorflow/python:training", + "//tensorflow/python:util", + "//tensorflow/python:variable_scope", + "//tensorflow/python:variables", + "//tensorflow/python/eager:context", + "//tensorflow/python/eager:tape", + ], +) + py_library( name = "multi_worker_util", srcs = [ @@ -88,6 +241,35 @@ py_library( ], ) +py_library( + name = "input_ops", + srcs = ["input_ops.py"], + deps = [ + "//tensorflow/python:framework_ops", + "//tensorflow/python/data/experimental/ops:filter_for_shard_ops", + "//tensorflow/python/data/util:nest", + ], +) + +cuda_py_test( + name = "input_ops_test", + srcs = ["input_ops_test.py"], + additional_deps = [ + ":input_ops", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/data/ops:readers", + "//tensorflow/python:errors", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_ops", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:io_ops", + "//tensorflow/python:util", + ], + tags = [ + "no_pip", + ], +) + py_test( name = "multi_worker_util_test", srcs = ["multi_worker_util_test.py"], @@ -120,3 +302,49 @@ py_library( "//tensorflow/python:training", ], ) + +py_library( + name = "reduce_util", + srcs = ["reduce_util.py"], + deps = [ + "//tensorflow/python:util", + "//tensorflow/python:variable_scope", + ], +) + +py_library( + name = "shared_variable_creator", + srcs = ["shared_variable_creator.py"], +) + +py_test( + name = "shared_variable_creator_test", + srcs = ["shared_variable_creator_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":shared_variable_creator", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:variable_scope", + "//tensorflow/python/eager:test", + ], +) + +py_library( + name = "values", + srcs = ["values.py"], + deps = [ + ":device_util", + ":distribute_lib", + ":input_ops", + "//tensorflow/python:array_ops", + "//tensorflow/python:control_flow_ops", + "//tensorflow/python:framework_ops", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:training", + "//tensorflow/python:util", + "//tensorflow/python/data/ops:multi_device_iterator_ops", + "//tensorflow/python/eager:context", + "//tensorflow/python/training/checkpointable:base", + "@six_archive//:six", + ], +) diff --git a/tensorflow/python/distribute/all_reduce.py b/tensorflow/python/distribute/all_reduce.py new file mode 100644 index 0000000000..bd7c45ae27 --- /dev/null +++ b/tensorflow/python/distribute/all_reduce.py @@ -0,0 +1,860 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Utilities to construct a TF subgraph implementing distributed All-Reduce.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import collections +import math + +from tensorflow.python.framework import device as device_lib +from tensorflow.python.framework import ops +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import nccl_ops + + +def _flatten_tensors(tensors): + """Check tensors for isomorphism and flatten. + + Args: + tensors: list of T `tf.Tensor` which must all have the same shape. + + Returns: + tensors: a list of T `tf.Tensor` which are flattened (1D) views of tensors + shape: the original shape of each element of input tensors + + Raises: + ValueError: tensors are empty or non-isomorphic or have unknown shape. + """ + if not tensors: + raise ValueError("tensors cannot be empty") + shape = tensors[0].shape + for tensor in tensors: + shape = shape.merge_with(tensor.shape) + if not shape.is_fully_defined(): + raise ValueError("Tensors must have statically known shape.") + if len(shape) != 1: + reshaped = [] + for t in tensors: + with ops.colocate_with(t): + reshaped.append(array_ops.reshape(t, [-1])) + tensors = reshaped + return tensors, shape + + +def _reshape_tensors(tensors, shape): + """Reshape tensors flattened by _flatten_tensors. + + Args: + tensors: list of T `tf.Tensor` of identical length 1D tensors. + shape: list of integers describing the desired shape. Product of + the elements must equal the length of each tensor. + + Returns: + list of T `tf.Tensor` which are the reshaped inputs. + """ + reshaped = [] + for t in tensors: + with ops.colocate_with(t): + reshaped.append(array_ops.reshape(t, shape)) + return reshaped + + +def _padded_split(tensor, pieces): + """Like split for 1D tensors but pads-out case where len % pieces != 0. + + Args: + tensor: T `tf.Tensor` that must be 1D. + pieces: a positive integer specifying the number of pieces into which + tensor should be split. + + Returns: + list of T `tf.Tensor` of length pieces, which hold the values of + thin input tensor, in order. The final tensor may + be zero-padded on the end to make its size equal to those of all + of the other tensors. + + Raises: + ValueError: The input tensor is not 1D. + """ + shape = tensor.shape + if 1 != len(shape): + raise ValueError("input tensor must be 1D") + tensor_len = shape.dims[0].value + with ops.colocate_with(tensor): + if tensor_len % pieces != 0: + # pad to an even length + chunk_size = 1 + tensor_len // pieces + if pieces > tensor_len: + # This is an edge case that should not come up in practice, + # i.e. a different reduction algorithm would be better, + # but we'll make it work just for completeness. + pad_len = pieces - tensor_len + extended_whole = array_ops.concat( + [tensor, array_ops.zeros([pad_len], dtype=tensor.dtype)], 0) + parts = array_ops.split(extended_whole, pieces) + return parts, pad_len + elif (pieces - 1) * chunk_size >= tensor_len: + # Another edge case of limited real interest. + pad_len = (pieces * chunk_size) % tensor_len + extended_whole = array_ops.concat( + [tensor, array_ops.zeros([pad_len], dtype=tensor.dtype)], 0) + parts = array_ops.split(extended_whole, pieces) + return parts, pad_len + else: + last_chunk_size = tensor_len - (pieces - 1) * chunk_size + pad_len = chunk_size - last_chunk_size + piece_lens = [chunk_size for _ in range(pieces - 1)] + [last_chunk_size] + parts = array_ops.split(tensor, piece_lens) + parts[-1] = array_ops.concat( + [parts[-1], array_ops.zeros([pad_len], dtype=tensor.dtype)], 0) + return parts, pad_len + else: + return array_ops.split(tensor, pieces), 0 + + +def _strip_padding(tensors, pad_len): + """Strip the suffix padding added by _padded_split. + + Args: + tensors: list of T `tf.Tensor` of identical length 1D tensors. + pad_len: number of elements to be stripped from the end of each tensor. + + Returns: + list of T `tf.Tensor` which are the stripped inputs. + + Raises: + ValueError: tensors must be a non-empty list of 1D tensors, and + each must be longer than pad_len. + """ + if not tensors: + raise ValueError("tensors cannot be empty") + shape = tensors[0].shape + if len(shape) > 1: + raise ValueError("tensors must be 1D") + prefix_len = int(shape[0] - pad_len) + if prefix_len < 0: + raise ValueError("pad_len longer than tensor") + stripped = [] + for t in tensors: + with ops.colocate_with(t): + stripped.append(array_ops.slice(t, [0], [prefix_len])) + return stripped + + +def _ragged_split(tensor, pieces): + """Like split for 1D tensors but allows case where len % pieces != 0. + + Args: + tensor: T `tf.Tensor` that must be 1D. + pieces: a positive integer specifying the number of pieces into which + tensor should be split. + + Returns: + list of T `tf.Tensor` of length pieces, which hold the values of + the input tensor, in order. The final tensor may be shorter + than the others, which will all be of equal length. + + Raises: + ValueError: input tensor must be 1D. + """ + shape = tensor.shape + if 1 != len(shape): + raise ValueError("input tensor must be 1D") + tensor_len = shape.dims[0].value + chunk_size = tensor_len // pieces + with ops.colocate_with(tensor): + if tensor_len != (pieces * chunk_size): + # last piece will be short + assert pieces > 1 + last_chunk_size = tensor_len - ((pieces - 1) * chunk_size) + assert last_chunk_size > 0 + piece_lens = [chunk_size for _ in range(pieces - 1)] + [last_chunk_size] + return array_ops.split(tensor, piece_lens) + else: + return array_ops.split(tensor, pieces) + + +def _ring_permutations(num_workers, num_subchunks, gpu_perm): + """"Generate an array of device index arrays, one for each subchunk. + + In the basic ring reduction algorithm there are size(T)/num_devices + data chunks and each device process one chunk per tick, i.e. sending + one chunk and receiving one chunk. The idea of subchunking is that + each device processes num_subchunks smaller data regions per tick, + and the ring rank permutation is different for each subchunk index + so that a device is potentially sending to and receiving from + num_subchunks different other devices at each tick. Where multiple + independent data channels exist between devices, this strategy + supplies a method of using them in parallel. + + Args: + num_workers: number of worker tasks + num_subchunks: number of subchunks into which to divide each per-GPU chunk. + gpu_perm: an array of integers in [0, num_gpus-1] giving the default + ring order of GPUs at each worker. Other permutations will be generated + by rotating this array and splicing together per-worker instances. + + Raises: + ValueError: the number of subchunks may not exceed the number of GPUs. + + Returns: + pred_by_s_d: list of lists that maps (by index) from (subchunk, dev) to + preceding device in the permutation for that subchunk. The + device index of GPU i at worker j is i + (j * num_gpus). + rank_by_s_d: list of lists that maps (by index) from (subchunk, dev) to + local rank of device d in the permutation for that subchunk. + """ + num_gpus = len(gpu_perm) + devices = num_workers * num_gpus + if devices == 0: + return [], [] + if num_subchunks > num_gpus: + raise ValueError( + "num_subchunks %d must be <= num_gpus %d" % (num_subchunks, num_gpus)) + rotation_interval = max(1, int(num_gpus / num_subchunks)) + perms_by_s = [] + for s in range(0, num_subchunks): + full_order = [] + offset = s * rotation_interval + for w in range(0, num_workers): + default_order = [(w * num_gpus) + i for i in gpu_perm] + dev_order = default_order[offset:] + default_order[:offset] + full_order += dev_order + perms_by_s.append(full_order) + pred_by_s_d = [[-1 for d in range(0, devices)] + for s in range(0, num_subchunks)] + rank_by_s_d = [[-1 for d in range(0, devices)] + for s in range(0, num_subchunks)] + for s in range(0, num_subchunks): + for d in range(0, devices): + for t in range(0, devices): + if d == perms_by_s[s][t]: + rank_by_s_d[s][d] = t + pred_by_s_d[s][d] = perms_by_s[s][(t + devices - 1) % devices] + break + return (pred_by_s_d, rank_by_s_d) + + +def build_ring_all_reduce(input_tensors, num_workers, num_subchunks, + gpu_perm, red_op, un_op=None): + """Construct a subgraph performing a ring-style all-reduce of input_tensors. + + Args: + input_tensors: a list of T `tf.Tensor` objects, which must all + have the same shape and type. + num_workers: number of worker tasks spanned by input_tensors. + num_subchunks: number of subchunks each device should process in one tick. + gpu_perm: a list of ints giving a ring-wise rank ordering of GPUs at + each worker. All workers must have the same number of + GPUs with the same rank ordering. If NVLINK is available, this should + be a ring order supported by NVLINK edges. + red_op: a binary operator for elementwise reduction. + un_op: an optional unary operator to apply to fully reduced values. + + Raises: + ValueError: empty input_tensors or they don't all have same + size. + + Returns: + a list of T `tf.Tensor` identical sum-reductions of input_tensors. + """ + if len(input_tensors) < 2: + raise ValueError("input_tensors must be length 2 or longer") + input_tensors, shape = _flatten_tensors(input_tensors) + devices = [t.device for t in input_tensors] + (pred_by_s_d, rank_by_s_d) = _ring_permutations( + num_workers, num_subchunks, gpu_perm) + chunks_by_dev, pad_len = _build_ring_gather( + input_tensors, devices, + num_subchunks, pred_by_s_d, rank_by_s_d, red_op) + if un_op: + chunks_by_dev = _apply_unary_to_chunks(un_op, chunks_by_dev) + output_tensors = _build_ring_scatter(pred_by_s_d, rank_by_s_d, + chunks_by_dev) + if pad_len > 0: + output_tensors = _strip_padding(output_tensors, pad_len) + if len(shape) != 1: + output_tensors = _reshape_tensors(output_tensors, shape) + return output_tensors + + +def _build_ring_gather(input_tensors, devices, num_subchunks, + pred_by_s_d, rank_by_s_d, red_op): + """Construct a subgraph for the first (reduction) pass of ring all-reduce. + + Args: + input_tensors: a list of T `tf.Tensor` 1D input tensors of same + shape and type. + devices: array of device name strings + num_subchunks: number of subchunks each device should process in one tick. + pred_by_s_d: as produced by _ring_permutations + rank_by_s_d: as produced by _ring_permutations + red_op: a binary operator for elementwise reduction + + Raises: + ValueError: tensors must all be one dimensional. + + Returns: + list of list of T `tf.Tensor` of (partially) reduced values where + exactly num_subchunks chunks at each device are fully reduced. + """ + num_devices = len(input_tensors) + if num_devices == 0: + return [] + if num_devices == 1: + return input_tensors + shape = input_tensors[0].shape + if 1 != len(shape): + raise ValueError("input tensors must be 1D") + num_chunks = num_devices * num_subchunks + num_ticks = num_devices - 1 + # Initialize chunks_by_dev with splits of the input tensors. + chunks_by_dev = [] + split_pad_len = 0 + for d in range(0, num_devices): + with ops.device(devices[d]): + splits, split_pad_len = _padded_split(input_tensors[d], num_chunks) + chunks_by_dev.append(splits) + # Reduction phase + for tick in range(0, num_ticks): + # One new partial reduction for every chunk + new_partial_reductions = [None for _ in range(0, num_chunks)] + # Compute reductions with respect to last tick's values + for d in range(0, num_devices): + with ops.device(devices[d]): + for s in range(0, num_subchunks): + rank = rank_by_s_d[s][d] + seg_index = (rank + num_devices - (2 + tick)) % num_devices + pred_dev = pred_by_s_d[s][d] + chunk_index = (seg_index * num_subchunks) + s + new_partial_reductions[chunk_index] = red_op( + chunks_by_dev[pred_dev][chunk_index], + chunks_by_dev[d][chunk_index]) + # Update chunks_by_dev with the new values at the end of the tick. + for d in range(0, num_devices): + for s in range(0, num_subchunks): + rank = rank_by_s_d[s][d] + seg_index = (rank + num_devices - (2 + tick)) % num_devices + chunk_index = (seg_index * num_subchunks) + s + chunks_by_dev[d][chunk_index] = new_partial_reductions[chunk_index] + return chunks_by_dev, split_pad_len + + +def _apply_unary_to_chunks(f, chunks_by_dev): + """Apply a unary op to each tensor in chunks_by_dev, on same device. + + Args: + f: a unary function over T `tf.Tensor`. + chunks_by_dev: list of lists of T `tf.Tensor`. + + Returns: + new list of lists of T `tf.Tensor` with the same structure as + chunks_by_dev containing the derived tensors. + """ + output = [] + for x in chunks_by_dev: + with ops.colocate_with(x[0]): + output.append([f(t) for t in x]) + return output + + +def _build_ring_scatter(pred_by_s_d, rank_by_s_d, + chunks_by_dev): + """Construct subgraph for second (scatter) pass of ring all-reduce. + + Args: + pred_by_s_d: as produced by _ring_permutations + rank_by_s_d: as produced by _ring_permutations + chunks_by_dev: list of list of T `tf.Tensor` indexed by ints + (device, chunk) + + Raises: + ValueError: chunks_by_dev is not well-formed + + Returns: + list of T `tf.Tensor` which are the fully reduced tensors, one + at each device corresponding to the outer dimension of chunks_by_dev. + """ + num_devices = len(chunks_by_dev) + num_chunks = len(chunks_by_dev[0]) + if 0 != num_chunks % num_devices: + raise ValueError( + "Expect number of chunks per device to be divisible by num_devices") + num_subchunks = int(num_chunks / num_devices) + num_ticks = num_devices - 1 + for tick in range(0, num_ticks): + passed_values = [None for _ in range(0, num_chunks)] + for d in range(0, num_devices): + with ops.colocate_with(chunks_by_dev[d][0]): + for s in range(0, num_subchunks): + rank = rank_by_s_d[s][d] + seg_index = (rank + num_devices - (1 + tick)) % num_devices + pred_dev = pred_by_s_d[s][d] + chunk_index = (seg_index * num_subchunks) + s + passed_values[chunk_index] = array_ops.identity( + chunks_by_dev[pred_dev][chunk_index]) + for d in range(0, num_devices): + for s in range(0, num_subchunks): + rank = rank_by_s_d[s][d] + seg_index = (rank + num_devices - (1 + tick)) % num_devices + chunk_index = (seg_index * num_subchunks) + s + chunks_by_dev[d][chunk_index] = passed_values[chunk_index] + # Join chunks at each device. + output = [] + for x in chunks_by_dev: + with ops.colocate_with(x[0]): + output.append(array_ops.concat(x, 0)) + return output + + +def build_recursive_hd_all_reduce(input_tensors, red_op, un_op=None): + """Construct a subgraph for recursive halving-doubling all-reduce. + + The recursive halving-doubling algorithm is described in + http://www.mcs.anl.gov/~thakur/papers/ijhpca-coll.pdf + + The concept is to arrange the participating n devices in + a linear sequence where devices exchange data pairwise + with one other device in each round. During the gather + phase there are lg(n) rounds where devices exchange + increasingly smaller sub-tensors with another device + at increasingly greater distances, until at the top + each device has 1/n of the fully reduced values. During the + scatter phase each device exchanges its fully reduced + sub-tensor (which doubles in length at each round) + with one other device at increasingly smaller distances + until each device has all of the fully reduced values. + + Note: this preliminary version requires that len(input_tensors) be a + power of 2. TODO(tucker): relax this restriction. Also, the + number of elements in each tensor must be divisible by 2^h where h + is the number of hops in each phase. This will also be relaxed in + the future with edge-case specific logic. + + Args: + input_tensors: list of T `tf.Tensor` to be elementwise reduced. + red_op: a binary elementwise reduction Op. + un_op: an optional unary elementwise Op to apply to reduced values. + + Returns: + list of T `tf.Tensor` which are the fully reduced tensors, one + at each device of input_tensors. + + Raises: + ValueError: num_devices not a power of 2, or tensor len not divisible + by 2 the proper number of times. + """ + devices = [t.device for t in input_tensors] + input_tensors, shape = _flatten_tensors(input_tensors) + reduced_shards = _build_recursive_hd_gather(input_tensors, devices, red_op) + if un_op: + reduced_shards = [un_op(t) for t in reduced_shards] + output_tensors = _build_recursive_hd_scatter(reduced_shards, devices) + if len(shape) != 1: + output_tensors = _reshape_tensors(output_tensors, shape) + return output_tensors + + +def _build_recursive_hd_gather(input_tensors, devices, red_op): + """Construct the gather phase of recursive halving-doubling all-reduce. + + Args: + input_tensors: list of T `tf.Tensor` to be elementwise reduced. + devices: a list of strings naming the devices hosting input_tensors, + which will also be used to host the (partial) reduction values. + red_op: a binary elementwise reduction Op. + + Returns: + list of T `tf.Tensor` which are the fully reduced tensor shards. + + Raises: + ValueError: num_devices not a power of 2, or tensor len not divisible + by 2 the proper number of times. + """ + num_devices = len(devices) + num_hops = int(math.log(num_devices, 2)) + if num_devices != (2 ** num_hops): + raise ValueError("num_devices must be a power of 2") + chunks = input_tensors + for h in range(0, num_hops): + span = 2 ** h + group_size = span * 2 + new_chunks = [[] for _ in devices] + for d in range(0, num_devices): + if (d % group_size) >= (group_size / 2): + # skip right half of a pair + continue + left_dev = devices[d] + right_dev = devices[d + span] + left_split = array_ops.split(chunks[d], 2) + right_split = array_ops.split(chunks[d+span], 2) + with ops.device(left_dev): + new_chunks[d] = red_op(left_split[0], right_split[0]) + with ops.device(right_dev): + new_chunks[d + span] = red_op(left_split[1], right_split[1]) + chunks = new_chunks + return chunks + + +def _build_recursive_hd_scatter(input_tensors, devices): + """Construct the scatter phase of recursive halving-doublng all-reduce. + + Args: + input_tensors: list of T `tf.Tensor` that are fully-reduced shards. + devices: a list of strings naming the devices on which the reconstituted + full tensors should be placed. + + Returns: + list of T `tf.Tensor` which are the fully reduced tensors. + """ + num_devices = len(devices) + num_hops = int(math.log(num_devices, 2)) + assert num_devices == (2 ** num_hops), "num_devices must be a power of 2" + chunks = input_tensors + for h in reversed(range(0, num_hops)): + span = 2 ** h + group_size = span * 2 + new_chunks = [[] for _ in devices] + for d in range(0, num_devices): + if (d % group_size) >= (group_size / 2): + # skip right half of a pair + continue + left_idx = d + right_idx = d + span + left_dev = devices[left_idx] + right_dev = devices[right_idx] + with ops.device(left_dev): + new_chunks[left_idx] = array_ops.concat([chunks[left_idx], + chunks[right_idx]], 0) + with ops.device(right_dev): + new_chunks[right_idx] = array_ops.concat([chunks[left_idx], + chunks[right_idx]], 0) + chunks = new_chunks + return chunks + + +def build_shuffle_all_reduce(input_tensors, gather_devices, red_op, un_op=None): + """Construct a subgraph for shuffle all-reduce. + + Shuffle reduce is essentially the algorithm implemented when using + parameter servers. Suppose tensor length is n, there are d devices + and g gather shards. Each device sends a n/g length sub-tensor to + each gather shard. The gather shards perform a reduction across d + fragments, then broadcast the result back to each device. The + devices then join the g fully reduced fragments they receive from + the shards. The gather shards could perform d-1 pairwise + reductions, or one d-way reduction. The first is better where + reduction Op time is low compared to transmission time, the second + better in the other case. + + Args: + input_tensors: list of T @(tf.Tensor} values to be reduced. + gather_devices: list of names of devices on which reduction shards + should be placed. + red_op: an n-array elementwise reduction Op + un_op: optional elementwise unary Op to be applied to fully-reduced values. + + Returns: + list of T `tf.Tensor` which are the fully reduced tensors. + """ + input_tensors, shape = _flatten_tensors(input_tensors) + dst_devices = [t.device for t in input_tensors] + reduced_shards = _build_shuffle_gather(input_tensors, gather_devices, + red_op, un_op) + output_tensors = _build_shuffle_scatter(reduced_shards, dst_devices) + if len(shape) != 1: + output_tensors = _reshape_tensors(output_tensors, shape) + return output_tensors + + +def _build_shuffle_gather(input_tensors, gather_devices, red_op, un_op=None): + """Construct the gather (concentrate and reduce) phase of shuffle all-reduce. + + Args: + input_tensors: list of T @(tf.Tensor} values to be reduced. + gather_devices: list of names of devices on which reduction shards + should be placed. + red_op: the binary reduction Op + un_op: optional elementwise unary Op to be applied to fully-reduced values. + + Returns: + list of T `tf.Tensor` which are the fully reduced shards. + + Raises: + ValueError: inputs not well-formed. + """ + num_source_devices = len(input_tensors) + num_gather_devices = len(gather_devices) + shape = input_tensors[0].shape + if len(shape) != 1: + raise ValueError("input_tensors must be 1D") + shards_by_source = [] + for d in range(0, num_source_devices): + with ops.colocate_with(input_tensors[d]): + shards_by_source.append( + _ragged_split(input_tensors[d], num_gather_devices)) + reduced_shards = [] + for d in range(0, num_gather_devices): + with ops.device(gather_devices[d]): + values = [s[d] for s in shards_by_source] + red_shard = red_op(values) + if un_op: + red_shard = un_op(red_shard) + reduced_shards.append(red_shard) + return reduced_shards + + +def _build_shuffle_scatter(reduced_shards, dst_devices): + """Build the scatter phase of shuffle all-reduce. + + Args: + reduced_shards: list of T @(tf.Tensor} fully reduced shards + dst_devices: list of names of devices at which the fully-reduced value + should be reconstituted. + + Returns: + list of T `tf.Tensor` scattered tensors. + """ + num_devices = len(dst_devices) + out_tensors = [] + for d in range(0, num_devices): + with ops.device(dst_devices[d]): + out_tensors.append(array_ops.concat(reduced_shards, 0)) + return out_tensors + + +def _split_by_task(devices, values): + """Partition devices and values by common task. + + Args: + devices: list of device name strings + values: list of T `tf.tensor` of same length as devices. + + Returns: + (per_task_devices, per_task_values) where both values are + lists of lists with isomorphic structure: the outer list is + indexed by task, and the inner list has length of the number + of values belonging to that task. per_task_devices contains + the specific devices to which the values are local, and + per_task_values contains the corresponding values. + + Raises: + ValueError: devices must be same length as values. + """ + num_devices = len(devices) + if num_devices != len(values): + raise ValueError("len(devices) must equal len(values)") + per_task_devices = collections.OrderedDict() + per_task_values = collections.OrderedDict() + for d in range(num_devices): + d_spec = device_lib.DeviceSpec.from_string(devices[d]) + if not hasattr(d_spec, "task") or d_spec.task is None: + assert False, "failed to parse device %s" % devices[d] + index = (d_spec.job or "localhost", d_spec.replica or 0, d_spec.task) + if index not in per_task_devices: + per_task_devices[index] = [] + per_task_values[index] = [] + per_task_devices[index].append(devices[d]) + per_task_values[index].append(values[d]) + + return (list(per_task_devices.values()), list(per_task_values.values())) + + +def build_nccl_all_reduce(input_tensors, red_op, un_op=None): + """Build a subgraph that does one full all-reduce, using NCCL. + + Args: + input_tensors: list of T `tf.Tensor` of same-shape and type values to + be reduced. + red_op: binary elementwise reduction operator. Must be one of + {tf.add} + un_op: optional unary elementwise Op to apply to fully-reduce values. + + Returns: + list of T `tf.Tensor` of reduced values. + + Raises: + ValueError: red_op not supported. + """ + if red_op == math_ops.add: + output_tensors = nccl_ops.all_sum(input_tensors) + else: + raise ValueError("red_op not supported by NCCL all-reduce: ", red_op) + if un_op: + un_op_wrapped = [] + for t in output_tensors: + with ops.colocate_with(t): + un_op_wrapped.append(un_op(t)) + output_tensors = un_op_wrapped + return output_tensors + + +def _build_nccl_hybrid(input_tensors, red_op, upper_level_f): + """Construct a subgraph for NCCL hybrid all-reduce. + + Args: + input_tensors: list of T `tf.Tensor` of same-shape and type values to + be reduced. + red_op: binary elementwise reduction operator. + upper_level_f: function for reducing one value per worker, across + workers. + + Returns: + list of T `tf.Tensor` of reduced values. + + Raises: + ValueError: inputs not well-formed. + """ + input_tensors, shape = _flatten_tensors(input_tensors) + devices = [t.device for t in input_tensors] + per_worker_devices, per_worker_values = _split_by_task(devices, input_tensors) + num_workers = len(per_worker_devices) + up_values = [None for w in range(0, num_workers)] + up_devices = up_values[:] + down_values = up_values[:] + # First stage: reduce within each worker using NCCL + for w in range(0, num_workers): + worker_values = build_nccl_all_reduce(per_worker_values[w], red_op) + # NOTE: these reductions will not run to completion unless + # every output value is used. Since we only need one, we + # need to put control dependencies on the rest. + with ops.control_dependencies(worker_values): + with ops.device(worker_values[0].device): + up_values[w] = array_ops.identity(worker_values[0]) + up_devices[w] = per_worker_devices[w][0] + # Second stage: Apply upper_level_f to reduce across first device at + # each worker + level_2_output = upper_level_f(up_values) + # Third stage: propagate within each worker using NCCL Broadcast + for w in range(0, num_workers): + dst_tensors = [] + with ops.device(per_worker_devices[w][0]): + broadcast_src = nccl_ops.broadcast(array_ops.identity(level_2_output[w])) + for d in per_worker_devices[w]: + with ops.device(d): + dst_tensors.append(array_ops.identity(broadcast_src)) + down_values[w] = dst_tensors + output_tensors = [v for sublist in down_values for v in sublist] + if len(shape) != 1: + output_tensors = _reshape_tensors(output_tensors, shape) + return output_tensors + + +def _reduce_non_singleton(input_tensors, red_f, un_op): + """If len(input_tensors) > 1, apply red_f, else apply un_op.""" + if len(input_tensors) > 1: + return red_f(input_tensors) + else: + if not un_op: + return input_tensors + output_tensors = [] + for t in input_tensors: + with ops.colocate_with(t): + output_tensors.append(un_op(t)) + return output_tensors + + +def build_nccl_then_ring(input_tensors, subdiv, red_op, un_op=None): + """Construct hybrid of NCCL within workers, Ring across workers.""" + def upper_builder(y): + return build_ring_all_reduce(y, len(y), subdiv, [0], red_op, un_op) + def upper_level_f(x): + return _reduce_non_singleton(x, upper_builder, un_op) + return _build_nccl_hybrid(input_tensors, red_op, upper_level_f) + + +def build_nccl_then_recursive_hd(input_tensors, red_op, un_op=None): + """Construct hybrid of NCCL within workers, Recursive-HD across workers.""" + upper_level_f = lambda x: build_recursive_hd_all_reduce(x, red_op, un_op) + return _build_nccl_hybrid(input_tensors, red_op, upper_level_f) + + +def build_nccl_then_shuffle(input_tensors, gather_devices, nccl_red_op, + shuffle_red_op, un_op=None): + """Construct hybrid of NCCL within workers, Shuffle across workers.""" + def upper_level_f(x): + return build_shuffle_all_reduce(x, gather_devices, shuffle_red_op, un_op) + + return _build_nccl_hybrid(input_tensors, nccl_red_op, upper_level_f) + + +def _build_shuffle_hybrid(input_tensors, gather_devices, red_op, upper_level_f): + """Construct a subgraph for Shuffle hybrid all-reduce. + + Args: + input_tensors: list of T `tf.Tensor` of same-shape and type values to + be reduced. + gather_devices: list of device names on which to host gather shards. + red_op: binary elementwise reduction operator. + upper_level_f: function for reducing one value per worker, across + workers. + + Returns: + list of T `tf.Tensor` of reduced values. + + Raises: + ValueError: inputs not well-formed. + """ + input_tensors, shape = _flatten_tensors(input_tensors) + # First stage, reduce across each worker using gather_devices. + devices = [t.device for t in input_tensors] + per_worker_devices, per_worker_values = _split_by_task(devices, input_tensors) + num_workers = len(per_worker_devices) + up_values = [] + if len(gather_devices) != num_workers: + raise ValueError("For shuffle hybrid, gather_devices must contain one " + "device per worker. ") + for w in range(0, num_workers): + reduced_shards = _build_shuffle_gather( + per_worker_values[w], [gather_devices[w]], red_op) + up_values.append(reduced_shards[0]) + # Second stage, apply upper_level_f. + level_2_output = upper_level_f(up_values) + # Third stage, apply shuffle scatter at each worker. + output_tensors = [] + for w in range(0, num_workers): + output_tensors += _build_shuffle_scatter( + [level_2_output[w]], per_worker_devices[w]) + if len(shape) != 1: + output_tensors = _reshape_tensors(output_tensors, shape) + return output_tensors + + +def build_shuffle_then_ring(input_tensors, gather_devices, subdiv, + red_n_op, red_op, un_op=None): + """Construct hybrid of Shuffle within workers, Ring across workers.""" + def upper_builder(tensors): + return build_ring_all_reduce(tensors, len(tensors), subdiv, [0], + red_op, un_op) + def upper_level_f(tensors): + return _reduce_non_singleton(tensors, upper_builder, un_op) + return _build_shuffle_hybrid( + input_tensors, gather_devices, red_n_op, upper_level_f) + + +def build_shuffle_then_shuffle(input_tensors, first_gather_devices, + second_gather_devices, red_op, un_op=None): + """Construct hybrid of Shuffle within workers, Shuffle across workers.""" + def upper_builder(tensors): + return build_shuffle_all_reduce(tensors, second_gather_devices, + red_op, un_op) + def upper_level_f(tensors): + return _reduce_non_singleton(tensors, upper_builder, un_op) + return _build_shuffle_hybrid( + input_tensors, first_gather_devices, red_op, upper_level_f) diff --git a/tensorflow/contrib/all_reduce/python/all_reduce_test.py b/tensorflow/python/distribute/all_reduce_test.py similarity index 97% rename from tensorflow/contrib/all_reduce/python/all_reduce_test.py rename to tensorflow/python/distribute/all_reduce_test.py index 304fd7fb8a..2c6b853124 100644 --- a/tensorflow/contrib/all_reduce/python/all_reduce_test.py +++ b/tensorflow/python/distribute/all_reduce_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for tensorflow.contrib.all_reduce.python..all_reduce.""" +"""Tests for all_reduce.""" from __future__ import absolute_import from __future__ import division @@ -22,8 +22,8 @@ import time import numpy as np -from tensorflow.contrib.all_reduce.python import all_reduce as ar from tensorflow.core.framework import types_pb2 +from tensorflow.python.distribute import all_reduce as ar from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape @@ -37,6 +37,7 @@ from tensorflow.python.platform import tf_logging class AllReduceTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testFlattenTensorsShapesDefined(self): x = array_ops.placeholder(types_pb2.DT_FLOAT, [None]) with self.assertRaisesRegexp(ValueError, @@ -100,6 +101,7 @@ class AllReduceTest(test_util.TensorFlowTestCase): input_tensors.append(array_ops.identity(t8)) return input_tensors, device_names + @test_util.run_deprecated_v1 def testBuildRingGatherPassStructure(self): # 1 worker, 1 device input_tensors, device_names = self._buildInput(1, 1) @@ -159,7 +161,7 @@ class AllReduceTest(test_util.TensorFlowTestCase): output_tensors = build_f(input_tensors, un_op) sum_reduced = math_ops.add_n(output_tensors) sum_reduced.op.run() - self.assertAllClose(sum_reduced.eval(), simple_sum.eval()) + self.assertAllClose(sum_reduced.eval(), self.evaluate(simple_sum)) def _testRingAllReduce(self, num_workers, num_gpus, shape, subdiv): start_time = time.time() @@ -170,6 +172,7 @@ class AllReduceTest(test_util.TensorFlowTestCase): "subdiv=%d elapsed=%f" % (num_workers, num_gpus, shape, subdiv, elapsed)) + @test_util.run_deprecated_v1 def testRingAllReduce(self): self._testRingAllReduce(1, 2, [], 1) self._testRingAllReduce(1, 2, [8], 1) @@ -199,6 +202,7 @@ class AllReduceTest(test_util.TensorFlowTestCase): tf_logging.info("ShuffleAllReduce num_workers=%d num_gpus=%d shape=%s " "elapsed=%f" % (num_workers, num_gpus, shape, elapsed)) + @test_util.run_deprecated_v1 def testShuffleAllReduce(self): self._testShuffleAllReduce(1, 2, [], 1) self._testShuffleAllReduce(1, 2, [8], 1) @@ -225,6 +229,7 @@ class AllReduceTest(test_util.TensorFlowTestCase): "shape=%s elapsed=%f" % (num_workers, num_gpus, shape, elapsed)) + @test_util.run_deprecated_v1 def testRecursiveHDAllReduce(self): self._testRecursiveHDAllReduce(1, 2, [8]) self._testRecursiveHDAllReduce(1, 2, [4, 4]) diff --git a/tensorflow/python/distribute/cluster_resolver/BUILD b/tensorflow/python/distribute/cluster_resolver/BUILD new file mode 100644 index 0000000000..360a2993cd --- /dev/null +++ b/tensorflow/python/distribute/cluster_resolver/BUILD @@ -0,0 +1,180 @@ +# Description: Operations defined for Cluster Resolvers + +load("//tensorflow:tensorflow.bzl", "tf_py_test") + +package( + default_visibility = [ + "//tensorflow:__subpackages__", + ], +) + +licenses(["notice"]) # Apache 2.0 + +py_library( + name = "cluster_resolver_lib", + srcs = [ + "__init__.py", + ], + srcs_version = "PY2AND3", + visibility = ["//visibility:public"], + deps = [ + ":base_cluster_resolver_py", + ":gce_cluster_resolver_py", + ":kubernetes_cluster_resolver_py", + ":slurm_cluster_resolver_py", + ":tfconfig_cluster_resolver_py", + ":tpu_cluster_resolver_py", + "//tensorflow/python:util", + ], +) + +py_library( + name = "base_cluster_resolver_py", + srcs = ["cluster_resolver.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:training_server_lib", + ], +) + +py_library( + name = "gce_cluster_resolver_py", + srcs = ["gce_cluster_resolver.py"], + srcs_version = "PY2AND3", + deps = [ + ":base_cluster_resolver_py", + "//tensorflow/python:training_server_lib", + ], +) + +py_library( + name = "tfconfig_cluster_resolver_py", + srcs = ["tfconfig_cluster_resolver.py"], + srcs_version = "PY2AND3", + deps = [ + ":base_cluster_resolver_py", + "//tensorflow/python:training_server_lib", + ], +) + +py_library( + name = "tpu_cluster_resolver_py", + srcs = ["tpu_cluster_resolver.py"], + srcs_version = "PY2AND3", + deps = [ + ":base_cluster_resolver_py", + "//tensorflow/python:training_server_lib", + ], +) + +py_library( + name = "slurm_cluster_resolver_py", + srcs = ["slurm_cluster_resolver.py"], + srcs_version = "PY2AND3", + deps = [ + ":base_cluster_resolver_py", + "//tensorflow/python:training_server_lib", + ], +) + +py_library( + name = "kubernetes_cluster_resolver_py", + srcs = ["kubernetes_cluster_resolver.py"], + srcs_version = "PY2AND3", + deps = [ + ":base_cluster_resolver_py", + "//tensorflow/python:training_server_lib", + ], +) + +tf_py_test( + name = "base_cluster_resolver_py_test", + srcs = ["cluster_resolver_test.py"], + additional_deps = [ + ":base_cluster_resolver_py", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:platform_test", + "//tensorflow/python:training_server_lib", + ], + main = "cluster_resolver_test.py", +) + +tf_py_test( + name = "gce_cluster_resolver_py_test", + size = "small", + srcs = ["gce_cluster_resolver_test.py"], + additional_deps = [ + ":gce_cluster_resolver_py", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:platform_test", + "//tensorflow/python:training_server_lib", + ], + main = "gce_cluster_resolver_test.py", +) + +tf_py_test( + name = "tfconfig_cluster_resolver_py_test", + size = "small", + srcs = ["tfconfig_cluster_resolver_test.py"], + additional_deps = [ + ":tfconfig_cluster_resolver_py", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:platform_test", + "//tensorflow/python:training_server_lib", + ], + grpc_enabled = True, + main = "tfconfig_cluster_resolver_test.py", +) + +tf_py_test( + name = "tpu_cluster_resolver_py_test", + size = "small", + srcs = ["tpu_cluster_resolver_test.py"], + additional_deps = [ + ":tpu_cluster_resolver_py", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:platform_test", + "//tensorflow/python:training_server_lib", + ], + grpc_enabled = True, + main = "tpu_cluster_resolver_test.py", +) + +tf_py_test( + name = "slurm_cluster_resolver_py_test", + size = "small", + srcs = ["slurm_cluster_resolver_test.py"], + additional_deps = [ + ":slurm_cluster_resolver_py", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:platform_test", + "//tensorflow/python:training_server_lib", + ], + main = "slurm_cluster_resolver_test.py", + tags = [], +) + +tf_py_test( + name = "kubernetes_cluster_resolver_py_test", + size = "small", + srcs = ["kubernetes_cluster_resolver_test.py"], + additional_deps = [ + ":kubernetes_cluster_resolver_py", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:platform_test", + "//tensorflow/python:training_server_lib", + ], + main = "kubernetes_cluster_resolver_test.py", +) diff --git a/tensorflow/contrib/cluster_resolver/README.md b/tensorflow/python/distribute/cluster_resolver/README.md similarity index 100% rename from tensorflow/contrib/cluster_resolver/README.md rename to tensorflow/python/distribute/cluster_resolver/README.md diff --git a/tensorflow/contrib/cluster_resolver/python/training/README.slurm b/tensorflow/python/distribute/cluster_resolver/README.slurm similarity index 100% rename from tensorflow/contrib/cluster_resolver/python/training/README.slurm rename to tensorflow/python/distribute/cluster_resolver/README.slurm diff --git a/tensorflow/python/distribute/cluster_resolver/__init__.py b/tensorflow/python/distribute/cluster_resolver/__init__.py new file mode 100644 index 0000000000..ef87f59b7f --- /dev/null +++ b/tensorflow/python/distribute/cluster_resolver/__init__.py @@ -0,0 +1,57 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Library Imports for Cluster Resolvers.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.distribute.cluster_resolver import cluster_resolver +from tensorflow.python.distribute.cluster_resolver import gce_cluster_resolver +from tensorflow.python.distribute.cluster_resolver import kubernetes_cluster_resolver +from tensorflow.python.distribute.cluster_resolver import slurm_cluster_resolver +from tensorflow.python.distribute.cluster_resolver import tfconfig_cluster_resolver +from tensorflow.python.distribute.cluster_resolver import tpu_cluster_resolver + +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import ClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import SimpleClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import UnionClusterResolver +from tensorflow.python.distribute.cluster_resolver.gce_cluster_resolver import GceClusterResolver +from tensorflow.python.distribute.cluster_resolver.kubernetes_cluster_resolver import KubernetesClusterResolver +from tensorflow.python.distribute.cluster_resolver.slurm_cluster_resolver import SlurmClusterResolver +from tensorflow.python.distribute.cluster_resolver.tfconfig_cluster_resolver import TFConfigClusterResolver +from tensorflow.python.distribute.cluster_resolver.tpu_cluster_resolver import TPUClusterResolver + +from tensorflow.python.util.all_util import remove_undocumented + +_allowed_symbols = [ + 'cluster_resolver', + 'gce_cluster_resolver', + 'kubernetes_cluster_resolver', + 'slurm_cluster_resolver', + 'tfconfig_cluster_resolver', + 'tpu_cluster_resolver', + 'ClusterResolver', + 'SimpleClusterResolver', + 'UnionClusterResolver', + 'GceClusterResolver', + 'KubernetesClusterResolver', + 'TFConfigClusterResolver', + 'TPUClusterResolver', + 'SlurmClusterResolver', +] + +remove_undocumented(__name__, _allowed_symbols) + diff --git a/tensorflow/python/distribute/cluster_resolver/cluster_resolver.py b/tensorflow/python/distribute/cluster_resolver/cluster_resolver.py new file mode 100644 index 0000000000..7774ac0e12 --- /dev/null +++ b/tensorflow/python/distribute/cluster_resolver/cluster_resolver.py @@ -0,0 +1,374 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Cluster Resolvers are used for dynamic cluster IP/hostname resolution.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import abc + +import six + +from tensorflow.python.training.server_lib import ClusterSpec + + +def format_master_url(master, rpc_layer=None): + if rpc_layer: + return '%s://%s' % (rpc_layer, master) + else: + return master + + +@six.add_metaclass(abc.ABCMeta) +class ClusterResolver(object): + """Abstract class for all implementations of ClusterResolvers. + + This defines the skeleton for all implementations of ClusterResolvers. + ClusterResolvers are a way for TensorFlow to communicate with various cluster + management systems (e.g. GCE, AWS, etc...). + + By letting TensorFlow communicate with these systems, we will be able to + automatically discover and resolve IP addresses for various TensorFlow + workers. This will eventually allow us to automatically recover from + underlying machine failures and scale TensorFlow worker clusters up and down. + + Note to Implementors: In addition to these abstract methods, you must also + implement the task_type, task_index, and rpc_layer attributes. You may choose + to implement them either as properties with getters or setters or directly + set the attributes. + + - task_type is the name of the server's current named job (e.g. 'worker', + 'ps' in a distributed parameterized training job). + - task_index is the ordinal index of the server within the task type. + - rpc_layer is the protocol used by TensorFlow to communicate with other + TensorFlow servers in a distributed environment. + """ + + @abc.abstractmethod + def cluster_spec(self): + """Retrieve the current state of the cluster and returns a ClusterSpec. + + Returns: + A ClusterSpec representing the state of the cluster at the moment this + function is called. + + Implementors of this function must take care in ensuring that the + ClusterSpec returned is up-to-date at the time of calling this function. + This usually means retrieving the information from the underlying cluster + management system every time this function is invoked and reconstructing + a cluster_spec, rather than attempting to cache anything. + """ + raise NotImplementedError() + + @abc.abstractmethod + def master(self, task_type=None, task_index=None, rpc_layer=None): + """Retrieves the name or URL of the session master. + + Args: + task_type: (Optional) The type of the TensorFlow task of the master. + task_index: (Optional) The index of the TensorFlow task of the master. + rpc_layer: (Optional) The RPC protocol for the given cluster. + + Returns: + The name or URL of the session master. + + Implementors of this function must take care in ensuring that the master + returned is up-to-date at the time to calling this function. This usually + means retrieving the master every time this function is invoked. + """ + raise NotImplementedError() + + @abc.abstractmethod + def num_accelerators_per_worker(self, session_config=None): + """Returns the number of accelerator cores per worker. + + This returns the number of accelerator cores (such as GPUs and TPUs) + available per worker. If workers only has CPU cores available, then this + should return 0. This method will query the master for this information + if it is not otherwise known. + + Args: + session_config: (Optional) Configuration for starting a new session to + query how many accelerator cores it has. + """ + raise NotImplementedError() + + @abc.abstractproperty + def environment(self): + """Returns the current environment which TensorFlow is running in.""" + raise NotImplementedError() + + +class SimpleClusterResolver(ClusterResolver): + """Simple implementation of ClusterResolver that accepts a ClusterSpec.""" + + def __init__(self, cluster_spec, master='', task_type=None, task_index=None, + environment='', num_accelerators_per_worker=0, + rpc_layer=None): + """Creates a SimpleClusterResolver from a ClusterSpec.""" + super(SimpleClusterResolver, self).__init__() + + self._task_type = task_type + self._task_index = task_index + self._environment = environment + self._num_accelerators_per_worker = num_accelerators_per_worker + self._rpc_layer = rpc_layer + + if not isinstance(cluster_spec, ClusterSpec): + raise TypeError('cluster_spec must be a ClusterSpec.') + self._cluster_spec = cluster_spec + + if not isinstance(master, str): + raise TypeError('master must be a string.') + self._master = master + + def cluster_spec(self): + """Returns the ClusterSpec passed into the constructor.""" + return self._cluster_spec + + def master(self, task_type=None, task_index=None, rpc_layer=None): + """Returns the master address to use when creating a session. + + Args: + task_type: (Optional) The type of the TensorFlow task of the master. + task_index: (Optional) The index of the TensorFlow task of the master. + rpc_layer: (Optional) The RPC used by distributed TensorFlow. + + Returns: + The name or URL of the session master. + + If a task_type and task_index is given, this will override the `master` + string passed into the initialization function. + """ + if task_type is not None and task_index is not None: + master = self.cluster_spec().task_address(task_type, task_index) + else: + master = self._master + + return format_master_url(master, rpc_layer=rpc_layer or self._rpc_layer) + + @property + def task_type(self): + return self._task_type + + @property + def task_index(self): + return self._task_index + + @task_type.setter + def task_type(self, task_type): + self._task_type = task_type + + @task_index.setter + def task_index(self, task_index): + self._task_index = task_index + + @property + def environment(self): + return self._environment + + def num_accelerators_per_worker(self, session_config=None): + """Returns the number of accelerator cores per worker. + + Args: + session_config: Unused. The SimpleClusterResolver does not do automatic + detection of accelerators, so a TensorFlow session will never be + created, and thus a `session_config` is never necessary here, and will + be ignored. + """ + del session_config + return self._num_accelerators_per_worker + + @property + def rpc_layer(self): + return self._rpc_layer + + @rpc_layer.setter + def rpc_layer(self, rpc_layer): + self._rpc_layer = rpc_layer + + +class UnionClusterResolver(ClusterResolver): + """Performs a union on underlying ClusterResolvers. + + This class performs a union given two or more existing ClusterResolvers. It + merges the underlying ClusterResolvers, and returns one unified ClusterSpec + when cluster_spec is called. The details of the merge function is + documented in the cluster_spec function. + + For additional Cluster Resolver properties such as task type, task index, + rpc layer, environment, etc..., we will return the value from the first + ClusterResolver in the union. + """ + + def __init__(self, *args, **kwargs): + """Initializes a UnionClusterResolver with other ClusterResolvers. + + Args: + *args: `ClusterResolver` objects to be unionized. + **kwargs: + rpc_layer - (Optional) Override value for the RPC layer used by + TensorFlow. + task_type - (Optional) Override value for the current task type. + task_index - (Optional) Override value for the current task index. + + Raises: + TypeError: If any argument is not a subclass of `ClusterResolvers`. + ValueError: If there are no arguments passed. + """ + super(UnionClusterResolver, self).__init__() + + self._rpc_layer = kwargs.pop('rpc_layer', None) + self._task_type = kwargs.pop('task_type', None) + self._task_index = kwargs.pop('task_index', None) + + if kwargs: + raise ValueError('Unexpected kwargs provided {!r}'.format(kwargs)) + + if not args: + raise ValueError('At least one ClusterResolver is required.') + + for cluster_resolver in args: + if not isinstance(cluster_resolver, ClusterResolver): + raise TypeError('All arguments must be a sub-class of ' + '`ClusterResolver.`') + self._cluster_resolvers = args + + def cluster_spec(self): + """Returns a union of all the ClusterSpecs from the ClusterResolvers. + + Returns: + A ClusterSpec containing host information merged from all the underlying + ClusterResolvers. + + Raises: + KeyError: If there are conflicting keys detected when merging two or + more dictionaries, this exception is raised. + + Note: If there are multiple ClusterResolvers exposing ClusterSpecs with the + same job name, we will merge the list/dict of workers. + + If *all* underlying ClusterSpecs expose the set of workers as lists, we will + concatenate the lists of workers, starting with the list of workers from + the first ClusterResolver passed into the constructor. + + If *any* of the ClusterSpecs expose the set of workers as a dict, we will + treat all the sets of workers as dicts (even if they are returned as lists) + and will only merge them into a dict if there is no conflicting keys. If + there is a conflicting key, we will raise a `KeyError`. + """ + + merged_cluster = {} + + # We figure out whether it is all lists for a particular job, or whether + # there are dicts inside. + for cluster_resolver in self._cluster_resolvers: + cluster_spec = cluster_resolver.cluster_spec() + cluster_dict = cluster_spec.as_dict() + + for job_name, tasks in cluster_dict.items(): + if job_name in merged_cluster: + # If we see a dict, then we write a dict out regardless. + if isinstance(tasks, dict): + merged_cluster[job_name] = {} + else: + # We take whichever type is present. + if isinstance(tasks, list): + merged_cluster[job_name] = [] + else: + merged_cluster[job_name] = {} + + # We then do the merge as appropriate in merged_cluster[job]. + for cluster_resolver in self._cluster_resolvers: + cluster_spec = cluster_resolver.cluster_spec() + cluster_dict = cluster_spec.as_dict() + + for job_name, tasks in cluster_dict.items(): + if isinstance(merged_cluster[job_name], list): + # We all have lists, we can just concatenate and be done. + merged_cluster[job_name].extend(tasks) + else: + if isinstance(tasks, list): + # We convert to a dictionary if the type is a list. + task_dict = dict(zip(range(0, len(tasks)), tasks)) + else: + # We can simply make a copy (for update) and be done. + task_dict = tasks.copy() + + # We detect if there are duplicates, and raise an error if so. + task_keys = set(task_dict) + merged_keys = set(merged_cluster[job_name].keys()) + intersected_keys = task_keys.intersection(merged_keys) + if intersected_keys: + raise KeyError('Duplicate keys detected when merging two ' + 'ClusterSpecs: %s' % repr(intersected_keys)) + + # We do the merge after all the processing. + merged_cluster[job_name].update(task_dict) + + return ClusterSpec(merged_cluster) + + def master(self, task_type=None, task_index=None, rpc_layer=None): + """Returns the master address to use when creating a session. + + This usually returns the master from the first ClusterResolver passed in, + but you can override this by specifying the task_type and task_index. + + Args: + task_type: (Optional) The type of the TensorFlow task of the master. + task_index: (Optional) The index of the TensorFlow task of the master. + rpc_layer: (Optional) The RPC protocol for the given cluster. + + Returns: + The name or URL of the session master. + """ + if task_type is not None and task_index is not None: + master = self.cluster_spec().task_address(task_type, task_index) + return format_master_url(master, rpc_layer or self._rpc_layer) + + return self._cluster_resolvers[0].master(rpc_layer=rpc_layer) + + @property + def task_type(self): + return self._task_type or self._cluster_resolvers[0].task_type + + @property + def task_index(self): + return self._task_index or self._cluster_resolvers[0].task_index + + @task_type.setter + def task_type(self, task_type): + self._task_type = task_type + + @task_index.setter + def task_index(self, task_index): + self._task_index = task_index + + @property + def environment(self): + return self._cluster_resolvers[0].environment + + def num_accelerators_per_worker(self, session_config=None): + return self._cluster_resolvers[0].num_accelerators_per_worker( + session_config) + + @property + def rpc_layer(self): + return self._rpc_layer or self._cluster_resolvers[0].rpc_layer + + @rpc_layer.setter + def rpc_layer(self, rpc_layer): + self._rpc_layer = rpc_layer diff --git a/tensorflow/contrib/cluster_resolver/python/training/cluster_resolver_test.py b/tensorflow/python/distribute/cluster_resolver/cluster_resolver_test.py similarity index 98% rename from tensorflow/contrib/cluster_resolver/python/training/cluster_resolver_test.py rename to tensorflow/python/distribute/cluster_resolver/cluster_resolver_test.py index b94c9612b5..b5448faec6 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/cluster_resolver_test.py +++ b/tensorflow/python/distribute/cluster_resolver/cluster_resolver_test.py @@ -18,8 +18,8 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import SimpleClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import UnionClusterResolver +from tensorflow.python.distribute.cluster_resolver import SimpleClusterResolver +from tensorflow.python.distribute.cluster_resolver import UnionClusterResolver from tensorflow.python.platform import test from tensorflow.python.training import server_lib diff --git a/tensorflow/python/distribute/cluster_resolver/gce_cluster_resolver.py b/tensorflow/python/distribute/cluster_resolver/gce_cluster_resolver.py new file mode 100644 index 0000000000..b167bc8fc8 --- /dev/null +++ b/tensorflow/python/distribute/cluster_resolver/gce_cluster_resolver.py @@ -0,0 +1,206 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Implementation of Cluster Resolvers for GCE Instance Groups.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import ClusterResolver +from tensorflow.python.training.server_lib import ClusterSpec + +_GOOGLE_API_CLIENT_INSTALLED = True +try: + from googleapiclient import discovery # pylint: disable=g-import-not-at-top + from oauth2client.client import GoogleCredentials # pylint: disable=g-import-not-at-top +except ImportError: + _GOOGLE_API_CLIENT_INSTALLED = False + + +def _format_master_url(master, rpc_layer=None): + return '%s://%s' % (rpc_layer, master) if rpc_layer else master + + +class GceClusterResolver(ClusterResolver): + """Cluster Resolver for Google Compute Engine. + + This is an implementation of cluster resolvers for the Google Compute Engine + instance group platform. By specifying a project, zone, and instance group, + this will retrieve the IP address of all the instances within the instance + group and return a Cluster Resolver object suitable for use for distributed + TensorFlow. + """ + + def __init__(self, + project, + zone, + instance_group, + port, + task_type='worker', + task_index=0, + rpc_layer='grpc', + num_accelerators_per_worker=0, + credentials='default', + service=None): + """Creates a new GceClusterResolver object. + + This takes in a few parameters and creates a GceClusterResolver project. It + will then use these parameters to query the GCE API for the IP addresses of + each instance in the instance group. + + Args: + project: Name of the GCE project. + zone: Zone of the GCE instance group. + instance_group: Name of the GCE instance group. + port: Port of the listening TensorFlow server (default: 8470) + task_type: Name of the TensorFlow job this GCE instance group of VM + instances belong to. + task_index: The task index for this particular VM, within the GCE + instance group. In particular, every single instance should be assigned + a unique ordinal index within an instance group manually so that they + can be distinguished from each other. + rpc_layer: The RPC layer TensorFlow should use to communicate across + instances. + num_accelerators_per_worker: Number of accelerators (GPUs) present per + instance. + credentials: GCE Credentials. If nothing is specified, this defaults to + GoogleCredentials.get_application_default(). + service: The GCE API object returned by the googleapiclient.discovery + function. (Default: discovery.build('compute', 'v1')). If you specify a + custom service object, then the credentials parameter will be ignored. + + Raises: + ImportError: If the googleapiclient is not installed. + """ + self._project = project + self._zone = zone + self._instance_group = instance_group + self._task_type = task_type + self._task_index = task_index + self._rpc_layer = rpc_layer + self._port = port + self._credentials = credentials + + if credentials == 'default': + if _GOOGLE_API_CLIENT_INSTALLED: + self._credentials = GoogleCredentials.get_application_default() + + if service is None: + if not _GOOGLE_API_CLIENT_INSTALLED: + raise ImportError('googleapiclient must be installed before using the ' + 'GCE cluster resolver') + self._service = discovery.build( + 'compute', 'v1', + credentials=self._credentials) + else: + self._service = service + + def cluster_spec(self): + """Returns a ClusterSpec object based on the latest instance group info. + + This returns a ClusterSpec object for use based on information from the + specified instance group. We will retrieve the information from the GCE APIs + every time this method is called. + + Returns: + A ClusterSpec containing host information retrieved from GCE. + """ + request_body = {'instanceState': 'RUNNING'} + request = self._service.instanceGroups().listInstances( + project=self._project, + zone=self._zone, + instanceGroups=self._instance_group, + body=request_body, + orderBy='name') + + worker_list = [] + + while request is not None: + response = request.execute() + + items = response['items'] + for instance in items: + instance_name = instance['instance'].split('/')[-1] + + instance_request = self._service.instances().get( + project=self._project, + zone=self._zone, + instance=instance_name) + + if instance_request is not None: + instance_details = instance_request.execute() + ip_address = instance_details['networkInterfaces'][0]['networkIP'] + instance_url = '%s:%s' % (ip_address, self._port) + worker_list.append(instance_url) + + request = self._service.instanceGroups().listInstances_next( + previous_request=request, + previous_response=response) + + worker_list.sort() + return ClusterSpec({self._task_type: worker_list}) + + def master(self, task_type=None, task_index=None, rpc_layer=None): + task_type = task_type if task_type is not None else self._task_type + task_index = task_index if task_index is not None else self._task_index + + if task_type is not None and task_index is not None: + master = self.cluster_spec().task_address(task_type, task_index) + if rpc_layer or self._rpc_layer: + return '%s://%s' % (rpc_layer or self._rpc_layer, master) + else: + return master + + return '' + + @property + def task_type(self): + return self._task_type + + @property + def task_index(self): + return self._task_index + + @task_type.setter + def task_type(self, task_type): + raise RuntimeError( + 'You cannot reset the task_type of the GceClusterResolver after it has ' + 'been created.') + + @task_index.setter + def task_index(self, task_index): + self._task_index = task_index + + @property + def environment(self): + """Returns the current environment which TensorFlow is running in. + + For users in the GCE environment, the environment property is always an + empty string, and Google users will not use this ClusterResolver for running + on internal systems. + """ + return '' + + @property + def rpc_layer(self): + return self._rpc_layer + + @rpc_layer.setter + def rpc_layer(self, rpc_layer): + self._rpc_layer = rpc_layer + + def num_accelerators_per_worker(self, session_config=None): + del session_config # Unused, since this is set manually in __init__. + return self._num_accelerators_per_worker diff --git a/tensorflow/contrib/cluster_resolver/python/training/gce_cluster_resolver_test.py b/tensorflow/python/distribute/cluster_resolver/gce_cluster_resolver_test.py similarity index 98% rename from tensorflow/contrib/cluster_resolver/python/training/gce_cluster_resolver_test.py rename to tensorflow/python/distribute/cluster_resolver/gce_cluster_resolver_test.py index c691552e86..d4f0660c92 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/gce_cluster_resolver_test.py +++ b/tensorflow/python/distribute/cluster_resolver/gce_cluster_resolver_test.py @@ -18,8 +18,8 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.contrib.cluster_resolver.python.training.cluster_resolver import UnionClusterResolver -from tensorflow.contrib.cluster_resolver.python.training.gce_cluster_resolver import GceClusterResolver +from tensorflow.python.distribute.cluster_resolver import GceClusterResolver +from tensorflow.python.distribute.cluster_resolver import UnionClusterResolver from tensorflow.python.platform import test from tensorflow.python.training import server_lib diff --git a/tensorflow/python/distribute/cluster_resolver/kubernetes_cluster_resolver.py b/tensorflow/python/distribute/cluster_resolver/kubernetes_cluster_resolver.py new file mode 100644 index 0000000000..041c081540 --- /dev/null +++ b/tensorflow/python/distribute/cluster_resolver/kubernetes_cluster_resolver.py @@ -0,0 +1,173 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Implementation of Cluster Resolvers for Kubernetes.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.client import device_lib +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import ClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import format_master_url +from tensorflow.python.training import server_lib + +_KUBERNETES_API_CLIENT_INSTALLED = True +try: + from kubernetes import client as k8sclient # pylint: disable=g-import-not-at-top + from kubernetes import config as k8sconfig # pylint: disable=g-import-not-at-top +except ImportError: + _KUBERNETES_API_CLIENT_INSTALLED = False + + +class KubernetesClusterResolver(ClusterResolver): + """Cluster Resolver for Kubernetes. + + This is an implementation of cluster resolvers for Kubernetes. When given the + the Kubernetes namespace and label selector for pods, we will retrieve the + pod IP addresses of all running pods matching the selector, and return a + ClusterSpec based on that information. + """ + + def __init__(self, + job_to_label_mapping=None, + tf_server_port=8470, + rpc_layer='grpc', + override_client=None): + """Initializes a new KubernetesClusterResolver. + + This initializes a new Kubernetes Cluster Resolver. The Cluster Resolver + will attempt to talk to the Kubernetes master to retrieve all the instances + of pods matching a label selector. + + Args: + job_to_label_mapping: A mapping of TensorFlow jobs to label selectors. + This allows users to specify many TensorFlow jobs in one Cluster + Resolver, and each job can have pods belong with different label + selectors. For example, a sample mapping might be + ``` + {'worker': ['job-name=worker-cluster-a', 'job-name=worker-cluster-b'], + 'ps': ['job-name=ps-1', 'job-name=ps-2']} + ``` + tf_server_port: The port the TensorFlow server is listening on. + rpc_layer: (Optional) The RPC layer TensorFlow should use to communicate + between tasks in Kubernetes. Defaults to 'grpc'. + override_client: The Kubernetes client (usually automatically retrieved + using `from kubernetes import client as k8sclient`). If you pass this + in, you are responsible for setting Kubernetes credentials manually. + + Raises: + ImportError: If the Kubernetes Python client is not installed and no + `override_client` is passed in. + RuntimeError: If autoresolve_task is not a boolean or a callable. + """ + if _KUBERNETES_API_CLIENT_INSTALLED: + k8sconfig.load_kube_config() + + if not job_to_label_mapping: + job_to_label_mapping = {'worker': ['job-name=tensorflow']} + + if not override_client and not _KUBERNETES_API_CLIENT_INSTALLED: + raise ImportError('The Kubernetes Python client must be installed before' + 'using the Kubernetes Cluster Resolver. To install the' + 'Kubernetes Python client, run `pip install ' + 'kubernetes` on your command line.') + + self._job_to_label_mapping = job_to_label_mapping + self._tf_server_port = tf_server_port + self._override_client = override_client + + self.task_type = None + self.task_index = None + self.rpc_layer = rpc_layer + + def master(self, task_type=None, task_index=None, rpc_layer=None): + """Returns the master address to use when creating a session. + + You must have set the task_type and task_index object properties before + calling this function, or pass in the `task_type` and `task_index` + parameters when using this function. If you do both, the function parameters + will override the object properties. + + Args: + task_type: (Optional) The type of the TensorFlow task of the master. + task_index: (Optional) The index of the TensorFlow task of the master. + rpc_layer: (Optional) The RPC protocol for the given cluster. + + Returns: + The name or URL of the session master. + """ + if task_type is not None and task_index is not None: + return format_master_url( + self.cluster_spec().task_address(task_type, task_index), + rpc_layer or self.rpc_layer) + + if self.task_type is not None and self.task_index is not None: + return format_master_url( + self.cluster_spec().task_address(self.task_type, self.task_index), + rpc_layer or self.rpc_layer) + + return '' + + def cluster_spec(self): + """Returns a ClusterSpec object based on the latest info from Kubernetes. + + We retrieve the information from the Kubernetes master every time this + method is called. + + Returns: + A ClusterSpec containing host information returned from Kubernetes. + + Raises: + RuntimeError: If any of the pods returned by the master is not in the + `Running` phase. + """ + if not self._override_client: + k8sconfig.load_kube_config() + + client = self._override_client or k8sclient.CoreV1Api() + cluster_map = {} + + for tf_job in self._job_to_label_mapping: + all_pods = [] + for selector in self._job_to_label_mapping[tf_job]: + ret = client.list_pod_for_all_namespaces(label_selector=selector) + selected_pods = [] + + # Sort the list by the name to make sure it doesn't change call to call. + for pod in sorted(ret.items, key=lambda x: x.metadata.name): + if pod.status.phase == 'Running': + selected_pods.append( + '%s:%s' % (pod.status.host_ip, self._tf_server_port)) + else: + raise RuntimeError('Pod "%s" is not running; phase: "%s"' % + (pod.metadata.name, pod.status.phase)) + all_pods.extend(selected_pods) + cluster_map[tf_job] = all_pods + + return server_lib.ClusterSpec(cluster_map) + + @property + def environment(self): + """Returns the current environment which TensorFlow is running in. + + For users in the Cloud environment, the environment property is always an + empty string, and Google users will not use this ClusterResolver for running + on internal systems. + """ + return '' + + def num_accelerators_per_worker(self, session_config=None): + local_devices = device_lib.list_local_devices(session_config) + return len([d for d in local_devices if d.device_type == 'GPU']) diff --git a/tensorflow/contrib/cluster_resolver/python/training/kubernetes_cluster_resolver_test.py b/tensorflow/python/distribute/cluster_resolver/kubernetes_cluster_resolver_test.py similarity index 87% rename from tensorflow/contrib/cluster_resolver/python/training/kubernetes_cluster_resolver_test.py rename to tensorflow/python/distribute/cluster_resolver/kubernetes_cluster_resolver_test.py index fbb26e803d..a9750fa60b 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/kubernetes_cluster_resolver_test.py +++ b/tensorflow/python/distribute/cluster_resolver/kubernetes_cluster_resolver_test.py @@ -18,7 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.contrib.cluster_resolver.python.training import KubernetesClusterResolver +from tensorflow.python.distribute.cluster_resolver import KubernetesClusterResolver from tensorflow.python.platform import test from tensorflow.python.training import server_lib @@ -109,6 +109,23 @@ class KubernetesClusterResolverTest(test.TestCase): """ self._verifyClusterSpecEquality(actual_cluster_spec, str(expected_proto)) + def testGetMasterWithOverrideParameters(self): + ret = _create_pod_list( + ('worker-0', 'Running', '10.1.2.3'), + ('worker-1', 'Running', '10.1.2.4'), + ('worker-2', 'Running', '10.1.2.5')) + + cluster_resolver = KubernetesClusterResolver( + override_client=_mock_kubernetes_client( + {'job-name=tensorflow': ret})) + cluster_resolver.task_type = 'worker' + cluster_resolver.task_index = 0 + self.assertEqual(cluster_resolver.task_type, 'worker') + self.assertEqual(cluster_resolver.task_index, 0) + self.assertEqual(cluster_resolver.master(), 'grpc://10.1.2.3:8470') + self.assertEqual(cluster_resolver.master('worker', 2), + 'grpc://10.1.2.5:8470') + def testNonRunningPod(self): ret = _create_pod_list(('tensorflow-abc123', 'Failed', '10.1.2.3'),) diff --git a/tensorflow/python/distribute/cluster_resolver/slurm_cluster_resolver.py b/tensorflow/python/distribute/cluster_resolver/slurm_cluster_resolver.py new file mode 100644 index 0000000000..fd3c6d6a18 --- /dev/null +++ b/tensorflow/python/distribute/cluster_resolver/slurm_cluster_resolver.py @@ -0,0 +1,226 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Implementation of Cluster Resolvers for Slurm workload manager.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import collections +import os +import subprocess + +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import ClusterResolver +from tensorflow.python.training.server_lib import ClusterSpec + + +class SlurmClusterResolver(ClusterResolver): + """Cluster Resolver for system with Slurm workload manager. + + This is an implementation of cluster resolvers for Slurm clusters. This allows + the specification of jobs and task counts, number of tasks per node, number of + GPUs on each node and number of GPUs for each task, It retrieves system + attributes by Slurm environment variables, resolves allocated computing node + names, construct a cluster and return a Cluster Resolver object which an be + use for distributed TensorFlow. + """ + + def _resolve_hostnames(self): + """Resolve host names of nodes allocated in current jobs. + + Returns: + A list of node names as strings. + """ + hostlist = (subprocess.check_output(['scontrol', 'show', 'hostname']). + decode('utf-8').strip().split('\n')) + return hostlist + + def __init__(self, + jobs, + port_base=8888, + gpus_per_node=1, + gpus_per_task=1, + tasks_per_node=None, + auto_set_gpu=True, + rpc_layer='grpc'): + """Creates a new SlurmClusterResolver object. + + This takes in parameters and creates a SlurmClusterResolver object. It uses + those parameters to check which nodes will processes reside and resolves + their hostnames. With the number of the GPUs on each node and number of GPUs + for each task it offsets the port number for each processes and allocate + GPUs to tasks by setting environment variables. The resolver currently + supports homogeneous tasks and default Slurm process allocation. + + Args: + jobs: Dictionary with job names as key and number of tasks in the job as + value + port_base: The first port number to start with for processes on a node. + gpus_per_node: Number of GPUs available on each node. + gpus_per_task: Number of GPUs to be used for each task. + tasks_per_node: Number of tasks to run on each node, if not set defaults + to Slurm's output environment variable SLURM_NTASKS_PER_NODE. + auto_set_gpu: Set the visible CUDA devices automatically while resolving + the cluster by setting CUDA_VISIBLE_DEVICES environment variable. + Defaults to True. + rpc_layer: (Optional) The protocol TensorFlow uses to communicate between + nodes. Defaults to 'grpc'. + + Returns: + A ClusterResolver object which can be used with distributed TensorFlow. + + Raises: + RuntimeError: If requested more GPUs per node then available or requested + more tasks then assigned tasks. + """ + + # check if launched by mpirun + if 'OMPI_COMM_WORLD_RANK' in os.environ: + self._rank = int(os.environ['OMPI_COMM_WORLD_RANK']) + num_tasks = int(os.environ['OMPI_COMM_WORLD_SIZE']) + else: + self._rank = int(os.environ['SLURM_PROCID']) + num_tasks = int(os.environ['SLURM_NTASKS']) + + self._jobs = collections.OrderedDict(sorted(jobs.items())) + self._port_base = port_base + + # user specification overrides SLURM specification + if tasks_per_node is not None: + self._tasks_per_node = tasks_per_node + elif tasks_per_node is None and 'SLURM_NTASKS_PER_NODE' in os.environ: + self._tasks_per_node = int(os.environ['SLURM_NTASKS_PER_NODE']) + else: + raise RuntimeError('Neither `tasks_per_node` or ' + 'SLURM_NTASKS_PER_NODE is set.') + + self._gpus_per_node = gpus_per_node + self._gpus_per_task = gpus_per_task + + self._auto_set_gpu = auto_set_gpu + self.task_type = None + self.task_index = None + self.rpc_layer = rpc_layer + + self._gpu_allocation = [] + self._cluster_allocation = {} + + if self._tasks_per_node * self._gpus_per_task > self._gpus_per_node: + raise RuntimeError('Requested more GPUs per node then available.') + + if sum(self._jobs.values()) != num_tasks: + raise RuntimeError('Requested more tasks then assigned tasks.') + + def cluster_spec(self): + """Returns a ClusterSpec object based on the latest instance group info. + + This returns a ClusterSpec object for use based on information from the + specified initialization parameters and Slurm environment variables. The + cluster specification is resolved each time this function is called. The + resolver extract hostnames of nodes by scontrol and pack tasks in that + order until a node a has number of tasks that is equal to specification. + GPUs on nodes are allocated to tasks by specification through setting + CUDA_VISIBLE_DEVICES environment variable. + + Returns: + A ClusterSpec containing host information retrieved from Slurm's + environment variables. + """ + hostlist = self._resolve_hostnames() + + task_list = [] + self._gpu_allocation = [] + self._cluster_allocation = {} + + for host in hostlist: + for port_offset, gpu_offset in zip( + range(self._tasks_per_node), + range(0, self._gpus_per_node, self._gpus_per_task)): + + host_addr = '%s:%d' % (host, self._port_base + port_offset) + task_list.append(host_addr) + gpu_id_list = [] + + for gpu_id in range(gpu_offset, gpu_offset + self._gpus_per_task): + gpu_id_list.append(str(gpu_id)) + + self._gpu_allocation.append(','.join(gpu_id_list)) + + cluster_rank_offset_start = 0 + cluster_rank_offset_end = 0 + + for task_type, num_tasks in self._jobs.items(): + cluster_rank_offset_end = cluster_rank_offset_start + num_tasks + + self._cluster_allocation[task_type] = ( + task_list[cluster_rank_offset_start:cluster_rank_offset_end]) + + if cluster_rank_offset_start <= self._rank < cluster_rank_offset_end: + self.task_type = task_type + self.task_index = self._rank - cluster_rank_offset_start + + cluster_rank_offset_start = cluster_rank_offset_end + + if self._auto_set_gpu is True: + os.environ['CUDA_VISIBLE_DEVICES'] = self._gpu_allocation[self._rank] + + return ClusterSpec(self._cluster_allocation) + + def get_task_info(self): + """Returns job name and task_index for the process which calls this. + + This returns the job name and task index for the process which calls this + function according to its rank and cluster specification. The job name and + task index are set after a cluster is constructed by cluster_spec otherwise + defaults to None. + + Returns: + A string specifying job name the process belongs to and an integner + specifying the task index the process belongs to in that job. + """ + return self.task_type, self.task_index + + def master(self, task_type=None, task_index=None, rpc_layer=None): + """Returns the master string for connecting to a TensorFlow master. + + Args: + task_type: (Optional) Overrides the default auto-selected task type. + task_index: (Optional) Overrides the default auto-slected task index. + rpc_layer: (Optional) Overrides the default RPC protocol TensorFlow uses + to communicate across nodes. + + Returns: + A connection string for connecting to a TensorFlow master. + """ + task_type = task_type if task_type is not None else self.task_type + task_index = task_index if task_index is not None else self.task_index + rpc_layer = rpc_layer or self.rpc_layer + master = self.cluster_spec().task_address(task_type, task_index) + + return '%s://%s' % (rpc_layer, master) if rpc_layer else master + + @property + def environment(self): + """Returns the current environment which TensorFlow is running in. + + For users in the Slurm environment, the environment property is always an + empty string, and Google users will not use this ClusterResolver for running + on internal systems. + """ + return '' + + def num_accelerators_per_worker(self, session_config=None): + del session_config # Unused, since this is set in __init__ manually. + return self._gpus_per_node diff --git a/tensorflow/contrib/cluster_resolver/python/training/slurm_cluster_resolver_test.py b/tensorflow/python/distribute/cluster_resolver/slurm_cluster_resolver_test.py similarity index 85% rename from tensorflow/contrib/cluster_resolver/python/training/slurm_cluster_resolver_test.py rename to tensorflow/python/distribute/cluster_resolver/slurm_cluster_resolver_test.py index 9aa7df745e..076539d16f 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/slurm_cluster_resolver_test.py +++ b/tensorflow/python/distribute/cluster_resolver/slurm_cluster_resolver_test.py @@ -20,7 +20,7 @@ from __future__ import print_function import os -from tensorflow.contrib.cluster_resolver.python.training.slurm_cluster_resolver import SlurmClusterResolver +from tensorflow.python.distribute.cluster_resolver import SlurmClusterResolver from tensorflow.python.platform import test from tensorflow.python.training import server_lib @@ -67,6 +67,31 @@ class SlurmClusterResolverTest(test.TestCase): """ self._verifyClusterSpecEquality(actual_cluster_spec, expected_proto) + @mock.patch.dict(os.environ, {'SLURM_PROCID': '0', 'SLURM_NTASKS': '3'}) + @mock.patch.object(SlurmClusterResolver, '_resolve_hostnames', + mock_resolve_hostnames_output) + def testSimpleMasterRetrieval(self): + slurm_cluster_resolver = SlurmClusterResolver( + jobs={ + 'ps': 1, + 'worker': 2 + }, + port_base=8888, + tasks_per_node=1, + gpus_per_node=1, + gpus_per_task=1, + auto_set_gpu=False) + + slurm_cluster_resolver.task_type = 'worker' + slurm_cluster_resolver.task_index = 1 + self.assertEqual(slurm_cluster_resolver.master(), 'grpc://t02n43:8888') + + slurm_cluster_resolver.rpc_layer = 'ab' + self.assertEqual(slurm_cluster_resolver.master('ps', 0), 'ab://t02n13:8888') + self.assertEqual( + slurm_cluster_resolver.master('ps', 0, rpc_layer='test'), + 'test://t02n13:8888') + @mock.patch.dict(os.environ, { 'SLURM_PROCID': '0', 'SLURM_NTASKS': '3', diff --git a/tensorflow/python/distribute/cluster_resolver/tfconfig_cluster_resolver.py b/tensorflow/python/distribute/cluster_resolver/tfconfig_cluster_resolver.py new file mode 100644 index 0000000000..a3246e77f4 --- /dev/null +++ b/tensorflow/python/distribute/cluster_resolver/tfconfig_cluster_resolver.py @@ -0,0 +1,171 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Implementation of Cluster Resolvers for TF_CONFIG Environment Variables.""" + + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import json +import os + +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import ClusterResolver +from tensorflow.python.training.server_lib import ClusterSpec + +_TF_CONFIG_ENV = 'TF_CONFIG' +_SESSION_MASTER_KEY = 'session_master' +_RPC_LAYER_KEY = 'rpc_layer' +_TASK_KEY = 'task' + + +def format_master_url(master, rpc_layer=None): + if rpc_layer: + return '%s://%s' % (rpc_layer, master) + else: + return master + + +def _load_tf_config(): + return json.loads(os.environ.get(_TF_CONFIG_ENV, '{}')) + + +def _get_value_in_tfconfig(key, default=None): + tf_config = _load_tf_config() + return tf_config[key] if key in tf_config else default + + +class TFConfigClusterResolver(ClusterResolver): + """Implementation of a ClusterResolver which reads the TF_CONFIG EnvVar.""" + + def __init__(self, + task_type=None, + task_index=None, + rpc_layer=None, + environment=None, + num_accelerators_per_worker=0): + """Creates a new TFConfigClusterResolver. + + Args: + task_type: (String, optional) Overrides the task type specified in the + TF_CONFIG environment variable. + task_index: (Integer, optional) Overrides the task index specified in the + TF_CONFIG environment variable. + rpc_layer: (String, optional) Overrides the rpc layer TensorFlow uses. + environment: (String, optional) Overrides the environment TensorFlow + operates in. + num_accelerators_per_worker: (Integer, optional) Specifies the number of + accelerators (e.g. GPUs, TPUs, others) that each node has. + """ + + self._task_type = task_type + self._task_index = task_index + self._rpc_layer = rpc_layer + self._environment = environment + self._num_accelerators_per_worker = num_accelerators_per_worker + + @property + def task_type(self): + if self._task_type is None: + task_info = _get_value_in_tfconfig(_TASK_KEY, {}) + return task_info['type'] if 'type' in task_info else None + else: + return self._task_type + + @property + def task_index(self): + if self._task_type is None: + task_info = _get_value_in_tfconfig(_TASK_KEY, {}) + return task_info['index'] if 'index' in task_info else None + else: + return self._task_index + + @task_type.setter + def task_type(self, task_type): + self._task_type = task_type + + @task_index.setter + def task_index(self, task_index): + self._task_index = task_index + + @property + def environment(self): + return self._environment + + @property + def rpc_layer(self): + if self._rpc_layer is None: + return _get_value_in_tfconfig(_RPC_LAYER_KEY) + else: + return self._rpc_layer + + @rpc_layer.setter + def rpc_layer(self, rpc_layer): + self._rpc_layer = rpc_layer + + def num_accelerators_per_worker(self, session_config=None): + # TODO(frankchn): Connect to server (w/ session_config) in the future. + del session_config # Unused, we do not connect to another server here. + return self._num_accelerators_per_worker + + def cluster_spec(self): + """Returns a ClusterSpec based on the TF_CONFIG environment variable. + + Returns: + A ClusterSpec with information from the TF_CONFIG environment variable. + """ + tf_config = _load_tf_config() + if 'cluster' not in tf_config: + return ClusterSpec({}) + return ClusterSpec(tf_config['cluster']) + + def master(self, task_type=None, task_index=None, rpc_layer=None): + """Returns the master address to use when creating a TensorFlow session. + + Args: + task_type: (String, optional) Overrides and sets the task_type of the + master. + task_index: (Integer, optional) Overrides and sets the task id of the + master. + rpc_layer: (String, optional) Overrides and sets the protocol over which + TensorFlow nodes communicate with each other. + + Returns: + The address of the master. + + Raises: + RuntimeError: If the task_type or task_id is not specified and the + `TF_CONFIG` environment variable does not contain a task section. + """ + + # If `session_master` is set, just use that. + session_master = _get_value_in_tfconfig(_SESSION_MASTER_KEY) + if session_master is not None: + return session_master + + # Return an empty string if we are the only job in the ClusterSpec. + cluster_spec = self.cluster_spec() + if (not cluster_spec.jobs or + (len(cluster_spec.jobs) == 1 and + len(cluster_spec.job_tasks(cluster_spec.jobs[0])) == 1)): + return '' + + # We try to auto-detect the task type and id, but uses the user-supplied one + # where available + task_type = task_type if task_type is not None else self.task_type + task_index = task_index if task_index is not None else self.task_index + + return format_master_url(cluster_spec.task_address(task_type, task_index), + self.rpc_layer) diff --git a/tensorflow/contrib/cluster_resolver/python/training/tfconfig_cluster_resolver_test.py b/tensorflow/python/distribute/cluster_resolver/tfconfig_cluster_resolver_test.py similarity index 72% rename from tensorflow/contrib/cluster_resolver/python/training/tfconfig_cluster_resolver_test.py rename to tensorflow/python/distribute/cluster_resolver/tfconfig_cluster_resolver_test.py index 468161d2aa..c20e51bc0b 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/tfconfig_cluster_resolver_test.py +++ b/tensorflow/python/distribute/cluster_resolver/tfconfig_cluster_resolver_test.py @@ -20,7 +20,7 @@ from __future__ import print_function import os -from tensorflow.contrib.cluster_resolver.python.training.tfconfig_cluster_resolver import TFConfigClusterResolver +from tensorflow.python.distribute.cluster_resolver import TFConfigClusterResolver from tensorflow.python.platform import test from tensorflow.python.training import server_lib @@ -133,6 +133,58 @@ class TFConfigClusterResolverTest(test.TestCase): cluster_resolver = TFConfigClusterResolver() self.assertEqual('grpc://ps0:2222', cluster_resolver.master()) + def testTaskTypeIndexRpcRead(self): + os.environ['TF_CONFIG'] = """ + { + "cluster": { + "ps": ["ps0:2222", "ps1:2222"], + "worker": ["worker0:2222", "worker1:2222", "worker2:2222"] + }, + "rpc_layer": "grpc", + "task": { + "type": "ps", + "index": 0 + } + } + """ + + cluster_resolver = TFConfigClusterResolver() + self.assertEqual('ps', cluster_resolver.task_type) + self.assertEqual(0, cluster_resolver.task_index) + self.assertEqual('grpc', cluster_resolver.rpc_layer) + + def testParameterOverrides(self): + os.environ['TF_CONFIG'] = """ + { + "cluster": { + "ps": ["ps0:2222", "ps1:2222"], + "worker": ["worker0:2222", "worker1:2222", "worker2:2222"] + }, + "rpc_layer": "grpc", + "task": { + "type": "ps", + "index": 1 + } + } + """ + + cluster_resolver = TFConfigClusterResolver(task_type='ps', task_index=0, + num_accelerators_per_worker=8) + + self.assertEqual('grpc://ps0:2222', cluster_resolver.master()) + self.assertEqual('ps', cluster_resolver.task_type) + self.assertEqual(0, cluster_resolver.task_index) + self.assertEqual(8, cluster_resolver.num_accelerators_per_worker()) + + cluster_resolver.task_type = 'worker' + cluster_resolver.task_index = 1 + cluster_resolver.rpc_layer = 'test' + + self.assertEqual('test://worker1:2222', cluster_resolver.master()) + self.assertEqual('worker', cluster_resolver.task_type) + self.assertEqual(1, cluster_resolver.task_index) + self.assertEqual('test', cluster_resolver.rpc_layer) + def testZeroItemsInClusterSpecMasterRead(self): os.environ['TF_CONFIG'] = """ {} diff --git a/tensorflow/python/distribute/cluster_resolver/tpu_cluster_resolver.py b/tensorflow/python/distribute/cluster_resolver/tpu_cluster_resolver.py new file mode 100644 index 0000000000..1956bd75a8 --- /dev/null +++ b/tensorflow/python/distribute/cluster_resolver/tpu_cluster_resolver.py @@ -0,0 +1,423 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Implementation of Cluster Resolvers for Cloud TPUs.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os + +from six.moves.urllib.request import Request +from six.moves.urllib.request import urlopen + +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import ClusterResolver +from tensorflow.python.distribute.cluster_resolver.cluster_resolver import format_master_url +from tensorflow.python.training import server_lib +from tensorflow.python.util import compat + +_GOOGLE_API_CLIENT_INSTALLED = True +try: + from googleapiclient import discovery # pylint: disable=g-import-not-at-top + from oauth2client.client import GoogleCredentials # pylint: disable=g-import-not-at-top +except ImportError: + _GOOGLE_API_CLIENT_INSTALLED = False + + +_GKE_ENV_VARIABLE = 'KUBE_GOOGLE_CLOUD_TPU_ENDPOINTS' +_ENDPOINTS_SEPARATOR = ',' +_DEFAULT_ENV_VARIABLE = 'TPU_NAME' +_DISCOVERY_SERVICE_URL_ENV_VARIABLE = 'TPU_API_DISCOVERY_URL' + + +class TPUClusterResolver(ClusterResolver): + """Cluster Resolver for Google Cloud TPUs. + + This is an implementation of cluster resolvers for the Google Cloud TPU + service. As Cloud TPUs are in alpha, you will need to specify a API definition + file for this to consume, in addition to a list of Cloud TPUs in your Google + Cloud Platform project. + """ + + def _tpuService(self): + """Creates a new Cloud TPU API object. + + This works around an issue where the underlying HTTP connection sometimes + times out when the script has been running for too long. Other methods in + this object calls this method to get a new API object whenever they need + to communicate with the Cloud API. + + Returns: + A Google Cloud TPU API object. + """ + if self._service: + return self._service + + credentials = self._credentials + if credentials is None or credentials == 'default': + credentials = GoogleCredentials.get_application_default() + + if self._discovery_url: + return discovery.build( + 'tpu', 'v1alpha1', + credentials=credentials, + discoveryServiceUrl=self._discovery_url) + else: + return discovery.build( + 'tpu', 'v1alpha1', + credentials=credentials) + + def _requestComputeMetadata(self, path): + req = Request('http://metadata/computeMetadata/v1/%s' % path, + headers={'Metadata-Flavor': 'Google'}) + resp = urlopen(req) + return compat.as_bytes(resp.read()) + + def _shouldResolve(self): + if isinstance(self._should_resolve_override, bool): + return self._should_resolve_override + if (self._tpu == compat.as_bytes('') or + self._tpu == compat.as_bytes('local') or + self._tpu.startswith(compat.as_bytes('/bns')) or + self._tpu.startswith(compat.as_bytes('localhost:')) or + self._tpu.startswith(compat.as_bytes('grpc://'))): + return False + return True + + @staticmethod + def _inGke(): + """When running in GKE, the environment variable will be set.""" + return _GKE_ENV_VARIABLE in os.environ + + @staticmethod + def _gkeEndpoints(): + return os.environ[_GKE_ENV_VARIABLE] + + @staticmethod + def _envVarFallback(): + if _DEFAULT_ENV_VARIABLE in os.environ: + return os.environ[_DEFAULT_ENV_VARIABLE] + return None + + @staticmethod + def _environmentDiscoveryUrl(): + return os.environ.get(_DISCOVERY_SERVICE_URL_ENV_VARIABLE) + + def __init__(self, + tpu=None, + zone=None, + project=None, + job_name='worker', + coordinator_name=None, + coordinator_address=None, + credentials='default', + service=None, + discovery_url=None): + """Creates a new TPUClusterResolver object. + + The ClusterResolver will then use the parameters to query the Cloud TPU APIs + for the IP addresses and ports of each Cloud TPU listed. + + Args: + tpu: Either a string, or a list of strings corresponding to the TPUs to + use. If the single string is the empty string, the string 'local', or a + string that begins with 'grpc://' or '/bns', then it is assumed to not + correspond with a Cloud TPU and will instead be passed as the session + master and no ClusterSpec propagation will be done. + zone: Zone where the TPUs are located. If omitted or empty, we will assume + that the zone of the TPU is the same as the zone of the GCE VM, which we + will try to discover from the GCE metadata service. + project: Name of the GCP project containing Cloud TPUs. If omitted or + empty, we will try to discover the project name of the GCE VM from the + GCE metadata service. + job_name: Name of the TensorFlow job the TPUs belong to. + coordinator_name: The name to use for the coordinator. Set to None if the + coordinator should not be included in the computed ClusterSpec. + coordinator_address: The address of the coordinator (typically an ip:port + pair). If set to None, a TF server will be started. If coordinator_name + is None, a TF server will not be started even if coordinator_address is + None. + credentials: GCE Credentials. If None, then we use default credentials + from the oauth2client + service: The GCE API object returned by the googleapiclient.discovery + function. If you specify a custom service object, then the credentials + parameter will be ignored. + discovery_url: A URL template that points to the location of + the discovery service. It should have two parameters {api} and + {apiVersion} that when filled in produce an absolute URL to the + discovery document for that service. The environment variable + 'TPU_API_DISCOVERY_URL' will override this. + + Raises: + ImportError: If the googleapiclient is not installed. + ValueError: If no TPUs are specified. + """ + if isinstance(tpu, list): + if not tpu: + raise ValueError('At least one TPU must be specified.') + if len(tpu) != 1: + raise NotImplementedError( + 'Using multiple TPUs in a single session is not yet implemented') + tpu = tpu[0] + + in_gke = self._inGke() + # When using GKE with Cloud TPUs, the env variable will be set. + if tpu is None: + if in_gke: + tpu = self._gkeEndpoints() + else: + tpu = self._envVarFallback() + + if tpu is None: + raise ValueError('Please provide a TPU Name to connect to.') + + self._tpu = compat.as_bytes(tpu) # self._tpu is always bytes + + # By default the task_type is 'worker` and the task_index is 0 (which is the + # first worker in the task). + self.task_type = job_name + self.task_index = 0 + + if tpu.startswith('grpc://'): + # Cloud environment, where we are using GRPC to communicate to TPUs. + self._environment = '' + elif tpu == 'local' or not tpu: + # Google environment, where the TPU is attached to the host. + self._environment = 'google' + elif tpu.startswith('/bns'): + # Google environment, where we reach the TPU through BNS. + self._environment = 'google' + + # If TPU is in the Google environment or exists locally, we don't use any + # RPC layer. + if tpu.startswith('/bns') or tpu == 'local' or not tpu: + self.rpc_layer = None + else: + self.rpc_layer = 'grpc' + + # Setting this overrides the return value of self._shouldResolve() + self._should_resolve_override = None + + # We strip out the protocol if it is included, and override the + # shouldResolve function to never resolve. We are adding the protocol back + # in later in self.master(). + if self.rpc_layer is not None and tpu.startswith(self.rpc_layer + '://'): + tpu = tpu[len(self.rpc_layer + '://'):] + self._tpu = tpu + self._should_resolve_override = False + + # Whether we should actually attempt to contact Cloud APIs + should_resolve = self._shouldResolve() + + # We error out if we are in a non-Cloud environment which cannot talk to the + # Cloud APIs using the standard class and a special object is not passed in. + self._service = service + if (self._service is None and should_resolve and + not _GOOGLE_API_CLIENT_INSTALLED): + raise ImportError('googleapiclient and oauth2client must be installed ' + 'before using the TPU cluster resolver. Execute: ' + '`pip install --upgrade google-api-python-client` ' + 'and `pip install --upgrade oauth2client` to ' + 'install with pip.') + + # We save user-passed credentials, unless the user didn't pass in anything. + self._credentials = credentials + if (credentials == 'default' and should_resolve and + _GOOGLE_API_CLIENT_INSTALLED): + self._credentials = None + + # Automatically detect project and zone if unspecified. + if not project and should_resolve: + project = compat.as_str( + self._requestComputeMetadata('project/project-id')) + if not zone and should_resolve: + zone_path = compat.as_str(self._requestComputeMetadata('instance/zone')) + zone = zone_path.split('/')[-1] + self._project = project + self._zone = zone + + self._discovery_url = self._environmentDiscoveryUrl() or discovery_url + + self._coordinator_name = coordinator_name + if (coordinator_name and not coordinator_address and + (should_resolve or in_gke)): + self._start_local_server() + else: + self._coordinator_address = coordinator_address + + def master(self, task_type=None, task_index=None, rpc_layer=None): + """Get the Master string to be used for the session. + + In the normal case, this returns the grpc path (grpc://1.2.3.4:8470) of + first instance in the ClusterSpec returned by the cluster_spec function. + + If a non-TPU name is used when constructing a TPUClusterResolver, that will + be returned instead (e.g. If the tpus argument's value when constructing + this TPUClusterResolver was 'grpc://10.240.1.2:8470', + 'grpc://10.240.1.2:8470' will be returned). + + Args: + task_type: (Optional, string) The type of the TensorFlow task of the + master. + task_index: (Optional, integer) The index of the TensorFlow task of the + master. + rpc_layer: (Optional, string) The RPC protocol TensorFlow should use to + communicate with TPUs. + + Returns: + string, the connection string to use when creating a session. + + Raises: + ValueError: If none of the TPUs specified exists. + """ + if self._shouldResolve(): + # We are going to communicate with the Cloud TPU APIs to get a Cluster. + cluster_spec = self.cluster_spec() + if task_type is not None and task_index is not None: + # task_type and task_index is from the function parameter + master = cluster_spec.task_address(task_type, task_index) + elif self.task_type is not None and self.task_index is not None: + # task_type and task_index is from the object + master = cluster_spec.task_address(self.task_type, self.task_index) + else: + # by default we take the first item in the cluster with the right name + job_tasks = cluster_spec.job_tasks(self.task_type) + if not job_tasks: + raise ValueError('No TPUs with the specified names exist.') + master = job_tasks[0] + else: + if isinstance(self._tpu, (bytes, bytearray)): + master = self._tpu.split(compat.as_bytes(_ENDPOINTS_SEPARATOR))[0] + else: + master = self._tpu.split(_ENDPOINTS_SEPARATOR)[0] + return format_master_url(master, rpc_layer or self.rpc_layer) + + def get_master(self): + return self.master() + + def get_job_name(self): + if self._shouldResolve(): + return self.task_type + + def cluster_spec(self): + """Returns a ClusterSpec object based on the latest TPU information. + + We retrieve the information from the GCE APIs every time this method is + called. + + Returns: + A ClusterSpec containing host information returned from Cloud TPUs. + + Raises: + RuntimeError: If the provided TPU is not healthy. + """ + ############################################################################ + # There are 5 potential cases this code must handle: + # 1. [Normal case.] We should resolve the TPU name to a set of tasks, and + # a. Create a ClusterSpec that includes the coordinator job + # b. Create a ClusterSpec without the coordinator job. + # 2. [GKE / No API Access.] We should not resolve the TPU name to a set of + # tasks and + # a. Create a ClusterSpec with the coordinator + # b. Create a ClusterSpec without the coordinator + # 3. [Other (legacy non-gRPC).] We should return an empty ClusterSpec. + ############################################################################ + + if self._shouldResolve(): + # Case 1. + full_name = 'projects/%s/locations/%s/nodes/%s' % ( + self._project, self._zone, compat.as_text(self._tpu)) + service = self._tpuService() + request = service.projects().locations().nodes().get(name=full_name) + response = request.execute() + + if 'state' in response and response['state'] != 'READY': + raise RuntimeError('TPU "%s" is not yet ready; state: "%s"' % + (compat.as_text(self._tpu), response['state'])) + + if 'health' in response and response['health'] != 'HEALTHY': + raise RuntimeError('TPU "%s" is unhealthy: "%s"' % + (compat.as_text(self._tpu), response['health'])) + + if 'networkEndpoints' in response: + worker_list = [ + '%s:%s' % (endpoint['ipAddress'], endpoint['port']) + for endpoint in response['networkEndpoints'] + ] + else: + # Fall back to the deprecated response format + instance_url = '%s:%s' % (response['ipAddress'], response['port']) + worker_list = [instance_url] + + cluster_spec = {self.task_type: worker_list} + else: + if self.rpc_layer is None: + # Case 3. + return None + # Case 2. + tpus = [] + for tpu in self._tpu.split(_ENDPOINTS_SEPARATOR): + # We are working around the fact that GKE environment variable that is + # supplied to us has the protocol string embedded in it, but we want + # to strip it out for the ClusterSpec. + if (self.rpc_layer is not None and + tpu.startswith(self.rpc_layer + '://')): + tpus.append(tpu[len(self.rpc_layer + '://'):]) + else: + tpus.append(tpu) + cluster_spec = {self.task_type: tpus} + + if self._coordinator_address: + # {1, 2}.a + cluster_spec[self._coordinator_name] = [self._coordinator_address] + + return server_lib.ClusterSpec(cluster_spec) + + def num_accelerators_per_worker(self, session_config=None): + """Returns the number of TPU cores per worker. + + This defaults to 8 for all current TPU configurations, and we do not need + to query any remote systems for this. + + Args: + session_config: Unused. Not currently necessary to query anything as this + number is 8 for all TPU configurations. + """ + del session_config # Unused. Not necessary to query anything. + return 8 + + @property + def environment(self): + """Returns the current environment which TensorFlow is running in.""" + return self._environment + + def _start_local_server(self): + address = self._requestComputeMetadata('instance/network-interfaces/0/ip') + self._server = server_lib.Server( + { + 'local': ['0.0.0.0:0'] + }, protocol='grpc', config=None, start=True) + # self._server.target is of the form: grpc://ipaddress:port + target = compat.as_bytes(self._server.target) + splits = target.split(compat.as_bytes(':')) + assert len(splits) == 3, self._server.target + assert splits[0] == compat.as_bytes('grpc'), self._server.target + self._coordinator_port = compat.as_text(splits[2]) + self._coordinator_address = '%s:%s' % ( + address, compat.as_text(self._coordinator_port)) + + def __deepcopy__(self, memo): + # TODO(b/73668574): Remove this once RunConfig avoids performing deepcopy. + return self diff --git a/tensorflow/contrib/cluster_resolver/python/training/tpu_cluster_resolver_test.py b/tensorflow/python/distribute/cluster_resolver/tpu_cluster_resolver_test.py similarity index 86% rename from tensorflow/contrib/cluster_resolver/python/training/tpu_cluster_resolver_test.py rename to tensorflow/python/distribute/cluster_resolver/tpu_cluster_resolver_test.py index 478c82967b..0f22ede3d9 100644 --- a/tensorflow/contrib/cluster_resolver/python/training/tpu_cluster_resolver_test.py +++ b/tensorflow/python/distribute/cluster_resolver/tpu_cluster_resolver_test.py @@ -20,7 +20,7 @@ from __future__ import print_function import os -from tensorflow.contrib.cluster_resolver.python.training.tpu_cluster_resolver import TPUClusterResolver +from tensorflow.python.distribute.cluster_resolver import TPUClusterResolver from tensorflow.python.platform import test from tensorflow.python.training import server_lib from tensorflow.python.util import compat @@ -132,6 +132,7 @@ class TPUClusterResolverTest(test.TestCase): } """ % tpu_cluster_resolver._coordinator_port self._verifyClusterSpecEquality(actual_cluster_spec, str(expected_proto)) + self.assertEqual(tpu_cluster_resolver.master(), 'grpc://10.1.2.3:8470') @mock.patch.object(TPUClusterResolver, '_requestComputeMetadata', mock_request_compute_metadata) @@ -157,6 +158,7 @@ class TPUClusterResolverTest(test.TestCase): job { name: 'worker' tasks { key: 0 value: '10.1.2.3:8470' } } """ self._verifyClusterSpecEquality(actual_cluster_spec, expected_proto) + self.assertEqual(tpu_cluster_resolver.master(), 'grpc://10.1.2.3:8470') @mock.patch.object(TPUClusterResolver, '_requestComputeMetadata', mock_request_compute_metadata) @@ -226,6 +228,7 @@ class TPUClusterResolverTest(test.TestCase): job { name: 'worker' tasks { key: 0 value: '10.1.2.3:8470' } } """ self._verifyClusterSpecEquality(actual_cluster_spec, expected_proto) + self.assertEqual(tpu_cluster_resolver.master(), 'grpc://10.1.2.3:8470') def testNewNetworkEndpointFormat(self): tpu_map = { @@ -304,6 +307,7 @@ class TPUClusterResolverTest(test.TestCase): } """ % tpu_cluster_resolver._coordinator_port self._verifyClusterSpecEquality(actual_cluster_spec, str(expected_proto)) + self.assertEqual(tpu_cluster_resolver.master(), 'grpc://10.2.3.4:8470') def testPodResolutionNoCoordinator(self): tpu_map = { @@ -350,6 +354,7 @@ class TPUClusterResolverTest(test.TestCase): } """ self._verifyClusterSpecEquality(actual_cluster_spec, expected_proto) + self.assertEqual(tpu_cluster_resolver.master(), 'grpc://10.2.3.4:8470') def testGetMasterNoEntries(self): tpu_map = {} @@ -464,5 +469,62 @@ class TPUClusterResolverTest(test.TestCase): self.assertEqual('https://{api}.internal/{apiVersion}', TPUClusterResolver._environmentDiscoveryUrl()) + def testEnvironmentAndRpcDetectionForGoogle(self): + tpu_cluster_resolver = TPUClusterResolver(tpu='/bns/ab/cd/ef') + self.assertEqual(tpu_cluster_resolver.environment, 'google') + self.assertEqual(tpu_cluster_resolver.rpc_layer, None) + + def testEnvironmentAndRpcDetectionForGrpcString(self): + tpu_cluster_resolver = TPUClusterResolver(tpu='grpc://10.1.2.3:8470') + self.assertEqual(tpu_cluster_resolver.environment, '') + self.assertEqual(tpu_cluster_resolver.rpc_layer, 'grpc') + self.assertEqual(tpu_cluster_resolver.master(), 'grpc://10.1.2.3:8470') + + def testOverrideTaskTypeAndIndexAndGetMaster(self): + tpu_map = { + 'projects/test-project/locations/us-central1-c/nodes/test-tpu-1': { + 'health': + 'HEALTHY', + 'networkEndpoints': [ + { + 'ipAddress': '10.2.3.4', + 'port': 8470, + }, + { + 'ipAddress': '10.2.3.5', + 'port': 8470, + }, + { + 'ipAddress': '10.2.3.6', + 'port': 8470, + }, + { + 'ipAddress': '10.2.3.7', + 'port': 8470, + }, + ] + } + } + + tpu_cluster_resolver = TPUClusterResolver( + project='test-project', + zone='us-central1-c', + tpu='test-tpu-1', + coordinator_name=None, + credentials=None, + service=self.mock_service_client(tpu_map=tpu_map)) + + self.assertEqual(tpu_cluster_resolver.master(), 'grpc://10.2.3.4:8470') + + tpu_cluster_resolver.task_type = 'worker' + tpu_cluster_resolver.task_index = 3 + self.assertEqual(tpu_cluster_resolver.master(), 'grpc://10.2.3.7:8470') + + self.assertEqual( + tpu_cluster_resolver.master( + task_type='worker', task_index=2, rpc_layer='test'), + 'test://10.2.3.6:8470') + + if __name__ == '__main__': test.main() diff --git a/tensorflow/contrib/distribute/python/cross_tower_ops.py b/tensorflow/python/distribute/cross_device_ops.py similarity index 86% rename from tensorflow/contrib/distribute/python/cross_tower_ops.py rename to tensorflow/python/distribute/cross_device_ops.py index b5b349aa64..a88ed62533 100644 --- a/tensorflow/contrib/distribute/python/cross_tower_ops.py +++ b/tensorflow/python/distribute/cross_device_ops.py @@ -21,17 +21,17 @@ from __future__ import print_function import collections import six -from tensorflow.contrib.distribute.python import cross_tower_utils -from tensorflow.contrib.distribute.python import values as value_lib from tensorflow.python.client import device_lib +from tensorflow.python.distribute import cross_device_utils +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import reduce_util +from tensorflow.python.distribute import values as value_lib from tensorflow.python.eager import context from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import resource_variable_ops -from tensorflow.python.ops import variable_scope as vs from tensorflow.python.platform import tf_logging as logging -from tensorflow.python.training import device_util def check_destinations(destinations): @@ -103,10 +103,10 @@ def _validate_value_destination_pairs(value_destination_pairs): # pylint: disable=g-missing-docstring if not value_destination_pairs: return False if not isinstance(value_destination_pairs, (list, tuple)): return False - if not all([isinstance(pair, tuple) for pair in value_destination_pairs]): + if not all(isinstance(pair, tuple) for pair in value_destination_pairs): return False - if not all([isinstance(v[0], value_lib.PerReplica) - for v in value_destination_pairs]): + if not all(isinstance(v[0], value_lib.PerReplica) + for v in value_destination_pairs): return False return True @@ -132,10 +132,10 @@ def _devices_match(left, right): def _all_devices_match(value_destination_pairs): - if not all([_devices_match(v, d) for v, d in value_destination_pairs]): + if not all(_devices_match(v, d) for v, d in value_destination_pairs): return False - if not all([_devices_match(v, value_destination_pairs[0][0]) - for v, _ in value_destination_pairs[1:]]): + if not all(_devices_match(v, value_destination_pairs[0][0]) + for v, _ in value_destination_pairs[1:]): return False return True @@ -144,13 +144,13 @@ def _simple_broadcast(value, destinations): index = {} devices = get_devices_from(destinations) for d in devices: - index[d] = cross_tower_utils.copy_tensor_or_indexed_slices_to_device( + index[d] = cross_device_utils.copy_tensor_or_indexed_slices_to_device( value, d) return value_lib.Mirrored(index) def _simple_reduce(per_replica_value, reduce_to_device, accumulation_fn, - aggregation): + reduce_op): # pylint: disable=g-missing-docstring all_values = [] count = 0 @@ -162,14 +162,13 @@ def _simple_reduce(per_replica_value, reduce_to_device, accumulation_fn, with ops.device(reduce_to_device): with context.context().device_policy(context.DEVICE_PLACEMENT_SILENT): - reduced = cross_tower_utils.aggregate_tensors_or_indexed_slices( + reduced = cross_device_utils.aggregate_tensors_or_indexed_slices( all_values, accumulation_fn) - if aggregation == vs.VariableAggregation.MEAN: - reduced = cross_tower_utils.divide_by_n_tensors_or_indexed_slices( + if reduce_op == reduce_util.ReduceOp.MEAN: + reduced = cross_device_utils.divide_by_n_tensors_or_indexed_slices( reduced, count) - elif aggregation != vs.VariableAggregation.SUM: - raise ValueError("`aggregation` must be VariableAggregation.SUM " - "or VariableAggregation.MEAN.") + elif reduce_op != reduce_util.ReduceOp.SUM: + raise ValueError("`reduce_op` must be Reduce.SUM or Reduce.MEAN.") return reduced @@ -179,15 +178,15 @@ class CrossDeviceOps(object): def __init__(self): pass - def reduce(self, aggregation, per_replica_value, destinations): + def reduce(self, reduce_op, per_replica_value, destinations): """Reduce `per_replica_value` to `destinations`. - It runs the reduction operation defined by `aggregation` and put the + It runs the reduction operation defined by `reduce_op` and put the result on `destinations`. Args: - aggregation: Indicates how a variable will be aggregated. Accepted values - are `tf.VariableAggregation.SUM`, `tf.VariableAggregation.MEAN`. + reduce_op: Indicates how per_replica_value will be reduced. Accepted + values are `tf.distribute.ReduceOp.SUM`, `tf.distribute.ReduceOp.MEAN`. per_replica_value: a PerReplica object or a tensor with device set. destinations: the reduction destinations. @@ -201,17 +200,17 @@ class CrossDeviceOps(object): per_replica_value = _make_tensor_into_per_replica(per_replica_value) validate_destinations(destinations) - return self._reduce(aggregation, per_replica_value, destinations) + return self._reduce(reduce_op, per_replica_value, destinations) - def batch_reduce(self, aggregation, value_destination_pairs): + def batch_reduce(self, reduce_op, value_destination_pairs): """Reduce PerReplica objects in a batch. Reduce each first element in `value_destination_pairs` to each second element which indicates the destinations. Args: - aggregation: Indicates how a variable will be aggregated. Accepted values - are `tf.VariableAggregation.SUM`, `tf.VariableAggregation.MEAN`. + reduce_op: Indicates how per_replica_value will be reduced. Accepted + values are `tf.distribute.ReduceOp.SUM`, `tf.distribute.ReduceOp.MEAN`. value_destination_pairs: a list or a tuple of tuples of PerReplica objects (or tensors with device set if there is one device) and destinations. @@ -231,7 +230,7 @@ class CrossDeviceOps(object): for _, d in value_destination_pairs: validate_destinations(d) - return self._batch_reduce(aggregation, value_destination_pairs) + return self._batch_reduce(reduce_op, value_destination_pairs) def broadcast(self, tensor, destinations): """Broadcast the `tensor` to destinations. @@ -246,11 +245,11 @@ class CrossDeviceOps(object): validate_destinations(destinations) return self._broadcast(tensor, destinations) - def _reduce(self, aggregation, per_replica_value, destinations): + def _reduce(self, reduce_op, per_replica_value, destinations): raise NotImplementedError( "_reduce method must be implemented in descendants.") - def _batch_reduce(self, aggregation, value_destination_pairs): + def _batch_reduce(self, reduce_op, value_destination_pairs): raise NotImplementedError( "_batch_reduce method must be implemented in descendants.") @@ -276,19 +275,19 @@ class ReductionToOneDeviceCrossDeviceOps(CrossDeviceOps): self.accumulation_fn = accumulation_fn super(ReductionToOneDeviceCrossDeviceOps, self).__init__() - def _reduce(self, aggregation, per_replica_value, destinations): + def _reduce(self, reduce_op, per_replica_value, destinations): if check_destinations(destinations): devices = get_devices_from(destinations) else: devices = get_devices_from(per_replica_value) reduce_to_device = self.reduce_to_device or devices[0] reduced = _simple_reduce(per_replica_value, reduce_to_device, - self.accumulation_fn, aggregation) + self.accumulation_fn, reduce_op) return self.broadcast(reduced, devices) - def _batch_reduce(self, aggregation, value_destination_pairs): + def _batch_reduce(self, reduce_op, value_destination_pairs): return [ - self._reduce(aggregation, t, destinations=v) + self._reduce(reduce_op, t, destinations=v) for t, v in value_destination_pairs ] @@ -323,20 +322,20 @@ def _group_value_by_device(per_replica_values): def _ungroup_and_make_mirrored(grouped_reduced, destinations, - aggregation, + reduce_op, num_between_graph_workers=1): """Ungroup results from all-reduce and make Mirrored objects. Each all-reduce result will be divided by the number of destinations before - Mirrored objects are created if aggregation is "mean". + Mirrored objects are created if reduce_op is "mean". Args: grouped_reduced: a list of lists, each sublist has components for each device, paired with a None. It is the result from - cross_tower_utils.aggregate_gradients_using*. + cross_device_utils.aggregate_gradients_using*. destinations: a list of device strings for returned Mirrored objects. - aggregation: Indicates how a variable will be aggregated. Accepted values - are `tf.VariableAggregation.SUM`, `tf.VariableAggregation.MEAN`. + reduce_op: Indicates how values will be aggregated. Accepted values + are `tf.distribute.ReduceOp.SUM`, `tf.distribute.ReduceOp.MEAN`. num_between_graph_workers: number of workers in the between-graph replication. @@ -346,7 +345,7 @@ def _ungroup_and_make_mirrored(grouped_reduced, index = [{} for _ in range(len(grouped_reduced[0]))] for d, per_replica_reduced in enumerate(grouped_reduced): for i, (v, _) in enumerate(per_replica_reduced): - if aggregation == vs.VariableAggregation.MEAN: + if reduce_op == reduce_util.ReduceOp.MEAN: index[i][destinations[d]] = v / ( len(destinations) * num_between_graph_workers) else: @@ -402,7 +401,7 @@ class ConcatAndSplitPacker(object): # all gradient shapes are defined, we use another method to get the # total size. # TODO(yuefengz): move this logic to array_ops.size. - if all([g.shape.is_fully_defined() for g, _ in device_grads_and_vars]): + if all(g.shape.is_fully_defined() for g, _ in device_grads_and_vars): total_grad_size = sum( [g.shape.num_elements() for g, _ in device_grads_and_vars]) else: @@ -486,7 +485,7 @@ class AggregateSmallTensorPacker(object): """Aggregate small tensors.""" if (self.agg_small_grads_max_bytes > 0 and self.agg_small_grads_max_group > 0): - device_grads, self.packing = cross_tower_utils.pack_small_tensors( + device_grads, self.packing = cross_device_utils.pack_small_tensors( grouped_grads_and_vars, max_bytes=self.agg_small_grads_max_bytes, max_group=self.agg_small_grads_max_group) @@ -494,8 +493,8 @@ class AggregateSmallTensorPacker(object): def unpack(self, summed_device_grad_packs): """Reverse the aggregation process.""" - return cross_tower_utils.unpack_small_tensors(summed_device_grad_packs, - self.packing) + return cross_device_utils.unpack_small_tensors(summed_device_grad_packs, + self.packing) def _pack_tensors(device_grads, @@ -557,13 +556,13 @@ class AllReduceCrossDeviceOps(CrossDeviceOps): self._agg_small_grads_max_group = agg_small_grads_max_group super(AllReduceCrossDeviceOps, self).__init__() - def _reduce(self, aggregation, per_replica_value, destinations): - contains_indexed_slices = cross_tower_utils.contains_indexed_slices( + def _reduce(self, reduce_op, per_replica_value, destinations): + contains_indexed_slices = cross_device_utils.contains_indexed_slices( per_replica_value) if (_devices_match(per_replica_value, destinations) and not context.executing_eagerly() and not contains_indexed_slices): - return self._batch_all_reduce(aggregation, [per_replica_value])[0] + return self._batch_all_reduce(reduce_op, [per_replica_value])[0] else: if contains_indexed_slices: logging.log_first_n( @@ -576,16 +575,16 @@ class AllReduceCrossDeviceOps(CrossDeviceOps): devices = get_devices_from(per_replica_value) reduce_to_device = devices[0] reduced = _simple_reduce(per_replica_value, reduce_to_device, - math_ops.add_n, aggregation) + math_ops.add_n, reduce_op) return self.broadcast(reduced, devices) - def _batch_reduce(self, aggregation, value_destination_pairs): + def _batch_reduce(self, reduce_op, value_destination_pairs): all_devices_match = _all_devices_match(value_destination_pairs) - contains_indexed_slices = cross_tower_utils.contains_indexed_slices( + contains_indexed_slices = cross_device_utils.contains_indexed_slices( value_destination_pairs) if (all_devices_match and not context.executing_eagerly() and not contains_indexed_slices): - return self._batch_all_reduce(aggregation, + return self._batch_all_reduce(reduce_op, [v[0] for v in value_destination_pairs]) else: if not all_devices_match: @@ -595,11 +594,11 @@ class AllReduceCrossDeviceOps(CrossDeviceOps): 10) return [ - self._reduce(aggregation, t, destinations=v) + self._reduce(reduce_op, t, destinations=v) for t, v in value_destination_pairs ] - def _batch_all_reduce(self, aggregation, per_replica_values): + def _batch_all_reduce(self, reduce_op, per_replica_values): """All reduce algorithm in a batch.""" logging.log_first_n( logging.INFO, "batch_all_reduce invoked for batches size = %d with " @@ -619,18 +618,18 @@ class AllReduceCrossDeviceOps(CrossDeviceOps): # the balance on num_splits. if self._all_reduce_alg == "nccl": # TODO(yuefengz): merge this into the all-reduce library. - reduced = cross_tower_utils.aggregate_gradients_using_nccl( + reduced = cross_device_utils.aggregate_gradients_using_nccl( device_grad_packs) else: # TODO(yuefengz): check that gpu ids in `destinations` are in ascending # order. reduced = ( - cross_tower_utils.aggregate_gradients_using_hierarchical_copy( + cross_device_utils.aggregate_gradients_using_hierarchical_copy( destinations, device_grad_packs)) reduced = _unpack_tensors(reduced, tensor_packer) return _ungroup_and_make_mirrored(reduced, per_replica_values[0].devices, - aggregation) + reduce_op) # For compatibility with code using the old name of `AllReduceCrossDeviceOps`. @@ -713,7 +712,7 @@ class MultiWorkerAllReduce(AllReduceCrossDeviceOps): validate_and_complete_spec(spec) for spec in all_reduce_spec ] - def _batch_all_reduce(self, aggregation, per_replica_values): + def _batch_all_reduce(self, reduce_op, per_replica_values): """All reduce algorithm in a batch.""" logging.log_first_n( logging.INFO, @@ -741,13 +740,13 @@ class MultiWorkerAllReduce(AllReduceCrossDeviceOps): this_grads = remaining_grads remaining_grads = [] else: - (this_grads, remaining_grads) = cross_tower_utils.split_grads_by_size( + (this_grads, remaining_grads) = cross_device_utils.split_grads_by_size( spec_tuple.limit, remaining_grads) if this_grads: device_grad_packs, tensor_packer = _pack_tensors( this_grads, self._num_packs, self._agg_small_grads_max_bytes, self._agg_small_grads_max_group) - range_agg_grads = cross_tower_utils.sum_gradients_all_reduce( + range_agg_grads = cross_device_utils.sum_gradients_all_reduce( self._worker_devices, device_grad_packs, len(self._worker_devices), spec_tuple.alg, spec_tuple.shards, range(self._num_gpus_per_worker)) range_agg_grads = _unpack_tensors(range_agg_grads, tensor_packer) @@ -761,7 +760,7 @@ class MultiWorkerAllReduce(AllReduceCrossDeviceOps): assert not remaining_grads return _ungroup_and_make_mirrored(aggregated_grads, destinations, - aggregation) + reduce_op) # TODO(yuefengz): support in-graph collective all-reduce. @@ -790,20 +789,20 @@ class CollectiveAllReduce(CrossDeviceOps): self._num_workers = num_workers self._num_gpus_per_worker = num_gpus_per_worker self._all_reduce_merge_scope = all_reduce_merge_scope - self._collective_keys = collective_keys or cross_tower_utils.CollectiveKeys( - ) + self._collective_keys = (collective_keys or + cross_device_utils.CollectiveKeys()) super(CollectiveAllReduce, self).__init__() # TODO(yuefengz, tucker): is indexed slices supported by collective ops? - def _reduce(self, aggregation, per_replica_value, destinations): - if cross_tower_utils.contains_indexed_slices(per_replica_value): + def _reduce(self, reduce_op, per_replica_value, destinations): + if cross_device_utils.contains_indexed_slices(per_replica_value): raise ValueError( "`IndexSlices` is not supported for Collective All-Reduce.") if context.executing_eagerly(): raise ValueError( "Eager execution is not supported for Collective All-Reduce") - all_reduced = self._batch_all_reduce(aggregation, [per_replica_value])[0] + all_reduced = self._batch_all_reduce(reduce_op, [per_replica_value])[0] if _devices_match(per_replica_value, destinations): return all_reduced else: @@ -819,8 +818,8 @@ class CollectiveAllReduce(CrossDeviceOps): return value_lib.Mirrored(index) - def _batch_reduce(self, aggregation, value_destination_pairs): - if cross_tower_utils.contains_indexed_slices(value_destination_pairs): + def _batch_reduce(self, reduce_op, value_destination_pairs): + if cross_device_utils.contains_indexed_slices(value_destination_pairs): raise ValueError( "`IndexSlices` is not supported for Collective All-Reduce.") if context.executing_eagerly(): @@ -829,7 +828,7 @@ class CollectiveAllReduce(CrossDeviceOps): all_devices_match = _all_devices_match(value_destination_pairs) if all_devices_match: - return self._batch_all_reduce(aggregation, + return self._batch_all_reduce(reduce_op, [v[0] for v in value_destination_pairs]) else: if not all_devices_match: @@ -838,11 +837,11 @@ class CollectiveAllReduce(CrossDeviceOps): "destinations are different.", 10) return [ - self._reduce(aggregation, t, destinations=v) + self._reduce(reduce_op, t, destinations=v) for t, v in value_destination_pairs ] - def _batch_all_reduce(self, aggregation, per_replica_values): + def _batch_all_reduce(self, reduce_op, per_replica_values): """All-reduce across all workers in a batch.""" if context.executing_eagerly(): raise ValueError( @@ -871,7 +870,7 @@ class CollectiveAllReduce(CrossDeviceOps): with ops.name_scope("allreduce"): for grad_and_vars in chunk: scaled_grads = [g for g, _ in grad_and_vars] - collective_reduced = cross_tower_utils.build_collective_reduce( + collective_reduced = cross_device_utils.build_collective_reduce( scaled_grads, self._num_workers, self._collective_keys, "Add", "Id") result = [] @@ -883,7 +882,7 @@ class CollectiveAllReduce(CrossDeviceOps): return _ungroup_and_make_mirrored( new_device_grads, per_replica_values[0].devices, - aggregation, + reduce_op, num_between_graph_workers=self._num_workers) @@ -917,15 +916,15 @@ def _choose_all_reduce_algorithm(device_links): def choose_the_best(devices, session_config=None): - """Find the best subclass of CrossDeviceOps given a tensorflow session. + """Find the best subclass of CrossDeviceOps given a session config. Args: - devices: a list of devices passed for distribute strategy. - session_config: a tensorflow session config or None. If None, it will make - deciesion based on all local devices. + devices: a list of devices passed to `tf.distribute.Strategy`. + session_config: a `tf.ConfigProto` or `None`. If `None`, it will make + decision based on all local devices. Returns: - a subclass of CrossDeviceOps. + A subclass of `CrossDeviceOps`. """ requested_devices = set([device_util.canonicalize(d) for d in devices]) machine_devices = device_lib.list_local_devices(session_config=session_config) @@ -938,13 +937,13 @@ def choose_the_best(devices, session_config=None): "Device is available but not used by distribute strategy: %s", d.name) if len(using_devices) != len(requested_devices): - logging.warning("Not all devices in distribute strategy are visible by " - "TensorFlow sessions.") + logging.warning("Not all devices in `tf.distribute.Strategy` are visible " + "to TensorFlow.") return ReductionToOneDeviceCrossDeviceOps() - if any([d.device_type.lower() != "gpu" for d in using_devices]): - logging.warning("Not all devices in DistributionStrategy are visible to " - "TensorFlow session.") + if any(d.device_type.lower() != "gpu" for d in using_devices): + logging.warning("Not all devices in `tf.distribute.Strategy` are visible " + "to TensorFlow.") return ReductionToOneDeviceCrossDeviceOps() device_links = [[] for _ in range(len(using_devices))] diff --git a/tensorflow/contrib/distribute/python/cross_tower_utils.py b/tensorflow/python/distribute/cross_device_utils.py similarity index 99% rename from tensorflow/contrib/distribute/python/cross_tower_utils.py rename to tensorflow/python/distribute/cross_device_utils.py index 50b3cf31e5..0faadd7e0c 100644 --- a/tensorflow/contrib/distribute/python/cross_tower_utils.py +++ b/tensorflow/python/distribute/cross_device_utils.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Utilities for cross_tower_ops.""" +"""Utilities for cross_device_ops.""" from __future__ import absolute_import from __future__ import division @@ -21,8 +21,8 @@ from __future__ import print_function import collections as pycoll import threading -from tensorflow.contrib.all_reduce.python import all_reduce -from tensorflow.contrib.distribute.python import values as value_lib +from tensorflow.python.distribute import all_reduce +from tensorflow.python.distribute import values as value_lib from tensorflow.python.framework import device as pydev from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops @@ -420,7 +420,7 @@ def sum_gradients_all_reduce(dev_prefixes, replica_grads, num_workers, alg, Returns: list of reduced tensors """ - alg_contains_shuffle = any([n in alg for n in ['pscpu', 'psgpu']]) + alg_contains_shuffle = any(n in alg for n in ['pscpu', 'psgpu']) is_hierarchical = '/' in alg if 'pscpu' in alg: aux_devices = [prefix + '/cpu:0' for prefix in dev_prefixes] diff --git a/tensorflow/python/training/device_util.py b/tensorflow/python/distribute/device_util.py similarity index 98% rename from tensorflow/python/training/device_util.py rename to tensorflow/python/distribute/device_util.py index 70e1ca4b5d..34474582ad 100644 --- a/tensorflow/python/training/device_util.py +++ b/tensorflow/python/distribute/device_util.py @@ -50,7 +50,7 @@ def canonicalize(d, default=None): # Fill in missing device fields using defaults. result = tf_device.DeviceSpec( replica=0, task=0, device_type="CPU", device_index=0) - if context.executing_eagerly(): + if ops.executing_eagerly_outside_functions(): result.job = "localhost" if default: result.merge_from(tf_device.DeviceSpec.from_string(default)) diff --git a/tensorflow/python/training/device_util_test.py b/tensorflow/python/distribute/device_util_test.py similarity index 95% rename from tensorflow/python/training/device_util_test.py rename to tensorflow/python/distribute/device_util_test.py index cdbb08229d..2f0d7ed3b3 100644 --- a/tensorflow/python/training/device_util_test.py +++ b/tensorflow/python/distribute/device_util_test.py @@ -18,14 +18,16 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.distribute import device_util from tensorflow.python.eager import context from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.platform import test -from tensorflow.python.training import device_util class DeviceUtilTest(test.TestCase): + @test_util.run_deprecated_v1 def testCurrentDeviceWithGlobalGraph(self): with ops.device("/cpu:0"): self.assertEqual(device_util.current(), "/device:CPU:0") @@ -49,6 +51,7 @@ class DeviceUtilTest(test.TestCase): self.assertEqual(device_util.current(), "/job:localhost/replica:0/task:0/device:CPU:0") + @test_util.run_deprecated_v1 def testCanonicalizeWithoutDefaultDevice(self): self.assertEqual( device_util.canonicalize("/cpu:0"), diff --git a/tensorflow/python/distribute/distribute_coordinator.py b/tensorflow/python/distribute/distribute_coordinator.py index 520413102b..c0f9b8a1fd 100644 --- a/tensorflow/python/distribute/distribute_coordinator.py +++ b/tensorflow/python/distribute/distribute_coordinator.py @@ -245,7 +245,7 @@ class _WorkerContext(object): else: session_config = self._session_config - if not self._strategy or self._strategy.should_init: + if not self._strategy or self._strategy.extended.experimental_should_init: logging.info("Creating chief session creator with config: %r", config) return monitored_session.ChiefSessionCreator( scaffold, @@ -261,6 +261,10 @@ class _WorkerContext(object): config=session_config, max_wait_secs=max_wait_secs) + @property + def session_config(self): + return copy.deepcopy(self._session_config) + @property def has_barrier(self): """Whether the barrier is set or not.""" @@ -301,15 +305,20 @@ class _WorkerContext(object): """Returns number of workers in the cluster, including chief.""" return self._num_workers + @property + def experimental_should_init(self): + """Whether to run init ops.""" + return self._strategy.extended.experimental_should_init + @property def should_checkpoint(self): """Whether to save checkpoint.""" - return self._strategy.should_checkpoint + return self._strategy.extended.should_checkpoint @property def should_save_summary(self): """Whether to save summaries.""" - return self._strategy.should_save_summary + return self._strategy.extended.should_save_summary def _run_single_worker(worker_fn, @@ -623,10 +632,10 @@ def run_distribute_coordinator(worker_fn, The `strategy` object is expected to be a DistributionStrategy object which has implemented methods needed by distributed coordinator such as `configure(session_config, cluster_spec, task_type, task_id)` which configures - the strategy object for a specific task and `should_init` property which - instructs the distribute coordinator whether to run init ops for a task. The - distribute coordinator will make a copy of the `strategy` object, call its - `configure` method and pass it to `worker_fn` as an argument. + the strategy object for a specific task and `experimental_should_init` + property which instructs the distribute coordinator whether to run init ops + for a task. The distribute coordinator will make a copy of the `strategy` + object, call its `configure` method and pass it to `worker_fn` as an argument. The `worker_fn` defines the training logic and is called under a its own worker context which can be accessed to via `get_current_worker_context`. A @@ -749,7 +758,7 @@ def run_distribute_coordinator(worker_fn, # The client must know the cluster but servers in the cluster don't have to # know the client. if task_type in [_TaskType.CLIENT, None]: - if strategy.between_graph: + if strategy.extended.experimental_between_graph: return _run_between_graph_client(worker_fn, strategy, eval_fn, eval_strategy, cluster_spec, session_config, rpc_layer) @@ -795,7 +804,7 @@ def run_distribute_coordinator(worker_fn, environment=environment) if task_type in [_TaskType.CHIEF, _TaskType.WORKER]: - if strategy.between_graph: + if strategy.extended.experimental_between_graph: # All jobs run `worker_fn` if between-graph. _run_single_worker(worker_fn, strategy, cluster_spec, task_type, task_id, session_config, rpc_layer) diff --git a/tensorflow/python/distribute/distribute_coordinator_test.py b/tensorflow/python/distribute/distribute_coordinator_test.py index 5d336648ce..f2cb950aad 100644 --- a/tensorflow/python/distribute/distribute_coordinator_test.py +++ b/tensorflow/python/distribute/distribute_coordinator_test.py @@ -47,6 +47,7 @@ from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables from tensorflow.python.platform import test from tensorflow.python.training import monitored_session +from tensorflow.python.training import session_manager CHIEF = distribute_coordinator._TaskType.CHIEF @@ -78,46 +79,53 @@ def _strip_protocol(target): return target -class MockStrategy(object): +class MockExtended(object): def __init__(self, between_graph=False, should_init=None, should_checkpoint=None, should_save_summary=None): - self._between_graph = between_graph - self._should_init = should_init - self._should_checkpoint = should_checkpoint - self._should_save_summary = should_save_summary + self.experimental_between_graph = between_graph + self.experimental_should_init = should_init + self.should_checkpoint = should_checkpoint + self.should_save_summary = should_save_summary - @property - def between_graph(self): - return self._between_graph + +class MockStrategy(object): + + def __init__(self, + between_graph=False, + should_init=None, + should_checkpoint=None, + should_save_summary=None): + self.extended = MockExtended(between_graph, should_init, should_checkpoint, + should_save_summary) def configure(self, session_config=None, cluster_spec=None, task_type=None, task_id=None): - if self._should_init is None: + if self.extended.experimental_should_init is None: if task_id == 0: - self._should_init = True + self.extended.experimental_should_init = True else: - self._should_init = False - if self._should_checkpoint is None: + self.extended.experimental_should_init = False + if self.extended.should_checkpoint is None: if task_id == 0: - self._should_checkpoint = True + self.extended.should_checkpoint = True else: - self._should_checkpoint = False - if self._should_save_summary is None: + self.extended.should_checkpoint = False + if self.extended.should_save_summary is None: if task_id == 0: - self._should_save_summary = True + self.extended.should_save_summary = True else: - self._should_save_summary = False + self.extended.should_save_summary = False if session_config: if (cluster_spec and task_type and task_id is not None and - self._between_graph): + self.extended.experimental_between_graph): session_config.intra_op_parallelism_threads += 1 if task_type in ["chief", "worker"]: session_config.device_filters.extend( @@ -126,18 +134,6 @@ class MockStrategy(object): session_config.inter_op_parallelism_threads += 1 session_config.device_filters.append("/job:somejob") - @property - def should_init(self): - return self._should_init - - @property - def should_checkpoint(self): - return self._should_checkpoint - - @property - def should_save_summary(self): - return self._should_save_summary - class MockServer(object): @@ -372,9 +368,12 @@ class DistributeCoordinatorTestBase(test.TestCase): context = distribute_coordinator_context.get_current_worker_context() self.assertTrue(context is not None) - self.assertEqual(context._strategy.should_init, strategy.should_init) - self.assertEqual(context.should_checkpoint, strategy.should_checkpoint) - self.assertEqual(context.should_save_summary, strategy.should_save_summary) + self.assertEqual(context._strategy.extended.experimental_should_init, + strategy.extended.experimental_should_init) + self.assertEqual(context.should_checkpoint, + strategy.extended.should_checkpoint) + self.assertEqual(context.should_save_summary, + strategy.extended.should_save_summary) task_type = str(context.task_type) task_id = context.task_id or 0 @@ -384,7 +383,8 @@ class DistributeCoordinatorTestBase(test.TestCase): while len(self._strategy_property[task_type]) <= task_id: self._strategy_property[task_type].append(None) self._strategy_property[task_type][task_id] = ( - context._strategy.should_init, context.should_checkpoint, + context._strategy.extended.experimental_should_init, + context.should_checkpoint, context.should_save_summary) def _run_mock_std_server(self, @@ -930,4 +930,14 @@ class RunStandardTensorflowServerTest(test.TestCase): if __name__ == "__main__": # TODO(yuefengz): find a smart way to terminite std server threads. with test.mock.patch.object(sys, "exit", os._exit): + # Reduce `recovery_wait_secs` from 30 seconds so the test completes quickly. + orig_init = session_manager.SessionManager.__init__ + + def new_init(*args, **kwargs): + kwargs.pop("recovery_wait_secs", None) + kwargs["recovery_wait_secs"] = 0.5 + orig_init(*args, **kwargs) + + session_manager.SessionManager.__init__ = new_init + test.main() diff --git a/tensorflow/python/distribute/distribute_lib.py b/tensorflow/python/distribute/distribute_lib.py new file mode 100644 index 0000000000..eddd6ff8b1 --- /dev/null +++ b/tensorflow/python/distribute/distribute_lib.py @@ -0,0 +1,1682 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Library for running a computation across multiple devices.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import copy +import threading +import weakref +import enum + +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribution_strategy_context +from tensorflow.python.distribute import reduce_util +from tensorflow.python.eager import context as eager_context +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import variable_scope +from tensorflow.python.ops.losses import losses_impl +from tensorflow.python.platform import tf_logging +from tensorflow.python.util import nest +from tensorflow.python.util.tf_export import tf_export +from tensorflow.tools.docs import doc_controls + + +# ------------------------------------------------------------------------------ +# Context tracking whether in a strategy.update() or .update_non_slot() call. + + +_update_device = threading.local() + + +def get_update_device(): + """Get the current device if in a `tf.distribute.Strategy.update()` call.""" + try: + return _update_device.current + except AttributeError: + return None + + +class UpdateContext(object): + """Context manager when you are in `update()` or `update_non_slot()`.""" + + def __init__(self, device): + self._device = device + self._old_device = None + + def __enter__(self): + self._old_device = get_update_device() + _update_device.current = self._device + + def __exit__(self, exception_type, exception_value, traceback): + del exception_type, exception_value, traceback + _update_device.current = self._old_device + + +# ------------------------------------------------------------------------------ +# Public utility functions. + + +@tf_export("distribute.get_loss_reduction") +def get_loss_reduction(): + """`tf.distribute.ReduceOp` corresponding to the last loss reduction.""" + loss_reduction = ops.get_default_graph()._last_loss_reduction # pylint: disable=protected-access + if (loss_reduction == losses_impl.Reduction.SUM or + loss_reduction == losses_impl.ReductionV2.SUM): + return reduce_util.ReduceOp.SUM + return reduce_util.ReduceOp.MEAN + + +# ------------------------------------------------------------------------------ +# Internal API for validating the current thread mode + + +def _require_cross_replica_context_extended(extended): + """Verify in cross-replica context.""" + context = _get_per_thread_mode() + cross_replica = context.cross_replica_context + if cross_replica is not None and cross_replica.extended is extended: + return + strategy = extended._container_strategy() # pylint: disable=protected-access + # We have an error to report, figure out the right message. + if context.distribution_strategy is not strategy: + _wrong_strategy_scope(strategy, context) + assert cross_replica is None + raise RuntimeError("Method requires being in cross-replica context, use " + "get_replica_context().merge_call()") + + +def _wrong_strategy_scope(strategy, context): + # Figure out the right error message. + if not distribution_strategy_context.has_distribution_strategy(): + raise RuntimeError( + 'Need to be inside "with strategy.scope()" for %s' % + (strategy,)) + else: + raise RuntimeError( + "Mixing different tf.distribute.Strategy objects: %s is not %s" % + (context.distribution_strategy, strategy)) + + +def require_replica_context(replica_ctx): + """Verify in `replica_ctx` replica context.""" + context = _get_per_thread_mode() + if context.replica_context is replica_ctx: return + # We have an error to report, figure out the right message. + if context.replica_context is None: + raise RuntimeError("Need to be inside `call_for_each_replica()`") + if context.distribution_strategy is replica_ctx.distribution_strategy: + # Two different ReplicaContexts with the same tf.distribute.Strategy. + raise RuntimeError("Mismatching ReplicaContext.") + raise RuntimeError( + "Mismatching tf.distribute.Strategy objects: %s is not %s." % + (context.distribution_strategy, replica_ctx.distribution_strategy)) + + +def _require_distribution_strategy_scope_strategy(strategy): + """Verify in a `strategy.scope()` in this thread.""" + context = _get_per_thread_mode() + if context.distribution_strategy is strategy: return + _wrong_strategy_scope(strategy, context) + + +def _require_distribution_strategy_scope_extended(extended): + """Verify in a `distribution_strategy.scope()` in this thread.""" + context = _get_per_thread_mode() + if context.distribution_strategy.extended is extended: return + # Report error. + strategy = extended._container_strategy() # pylint: disable=protected-access + _wrong_strategy_scope(strategy, context) + + +# ------------------------------------------------------------------------------ +# Internal context managers used to implement the DistributionStrategy +# base class + + +class _CurrentDistributionContext(object): + """Context manager setting the current `tf.distribute.Strategy`. + + Also: overrides the variable creator and optionally the current device. + """ + + def __init__(self, + strategy, + var_creator_scope, + var_scope=None, + default_device=None): + self._context = distribution_strategy_context._CrossReplicaThreadMode( # pylint: disable=protected-access + strategy) + self._var_creator_scope = var_creator_scope + self._var_scope = var_scope + if default_device: + self._device_scope = ops.device(default_device) + else: + self._device_scope = None + + def __enter__(self): + _push_per_thread_mode(self._context) + if self._var_scope: + self._var_scope.__enter__() + self._var_creator_scope.__enter__() + if self._device_scope: + self._device_scope.__enter__() + return self._context.distribution_strategy + + def __exit__(self, exception_type, exception_value, traceback): + if self._device_scope: + self._device_scope.__exit__(exception_type, exception_value, traceback) + self._var_creator_scope.__exit__(exception_type, exception_value, traceback) + if self._var_scope: + self._var_scope.__exit__(exception_type, exception_value, traceback) + _pop_per_thread_mode() + + +class _SameScopeAgainContext(object): + """Trivial context manager when you are already in `scope()`.""" + + def __init__(self, strategy): + self._distribution_strategy = strategy + + def __enter__(self): + return self._distribution_strategy + + def __exit__(self, exception_type, exception_value, traceback): + del exception_type, exception_value, traceback + + +# TODO(yuefengz): add more replication modes. +@tf_export("distribute.InputReplicationMode") +class InputReplicationMode(enum.Enum): + """Replication mode for input function.""" + + # The input function will be called on each worker independently, creating as + # many input pipelines as number of workers. Replicas will dequeue from the + # local Dataset on their worker. Distribution Strategy doesn't manage any + # state sharing between such separate input pipelines. + PER_WORKER = "PER_WORKER" + + +@tf_export("distribute.InputContext") +class InputContext(object): + """A class wrapping information needed by an input function. + + This is a context class that is passed to the user's input fn and contains + information about the compute replicas and input pipelines. The number of + compute replicas (in sync training) helps compute per input pipeline batch + size from the desired global batch size. Input pipeline information can be + used to return a different subset of the input in each input pipeline (for + e.g. shard the input pipeline, use a different input source etc). + """ + + def __init__(self, + num_input_pipelines=1, + input_pipeline_id=0, + num_replicas_in_sync=1): + """Initializes an InputContext object. + + Args: + num_input_pipelines: the number of input pipelines in a cluster. + input_pipeline_id: the current input pipeline id, should be an int in + [0,`num_input_pipelines`). + num_replicas_in_sync: the number of replicas that are in sync. + """ + self._num_input_pipelines = num_input_pipelines + self._input_pipeline_id = input_pipeline_id + self._num_replicas_in_sync = num_replicas_in_sync + + @property + def num_replicas_in_sync(self): + """Returns the number of compute replicas in sync.""" + return self._num_replicas_in_sync + + @property + def input_pipeline_id(self): + """Returns the input pipeline ID.""" + return self._input_pipeline_id + + @property + def num_input_pipelines(self): + """Returns the number of input pipelines.""" + return self._num_input_pipelines + + def get_per_replica_batch_size(self, global_batch_size): + """Returns the per-replica batch size. + + Args: + global_batch_size: the global batch size which should be divisible by + `num_replicas_in_sync`. + + Returns: + the per-replica batch size. + + Raises: + ValueError: if `global_batch_size` not divisible by + `num_replicas_in_sync`. + """ + if global_batch_size % self._num_replicas_in_sync != 0: + raise ValueError("The `global_batch_size` %r is not divisible by " + "`num_replicas_in_sync` %r " % + (global_batch_size, self._num_replicas_in_sync)) + return global_batch_size // self._num_replicas_in_sync + + +# ------------------------------------------------------------------------------ +# Base classes for all distribution strategies. + + +@tf_export("distribute.Strategy") +class DistributionStrategy(object): + """A list of devices with a state & compute distribution policy. + + See [tensorflow/contrib/distribute/README.md]( + https://www.tensorflow.org/code/tensorflow/contrib/distribute/README.md) + for overview and examples. + """ + + # TODO(josh11b): Raise an exception if variable partitioning requested before + # we add support. + # TODO(josh11b): Also `parameter_device_index` property? + # TODO(josh11b): `map()` + # TODO(josh11b): ClusterSpec/ClusterResolver + # TODO(josh11b): Partitioned computations, state; sharding + # TODO(josh11b): Model parallelism: "replicas" with multiple devices; shuffling + # TODO(josh11b): List of replicas with their worker and parameter devices + # (where the parameter devices may overlap in the ps case). + + def __init__(self, extended): + self._extended = extended + + @property + def extended(self): + """`tf.distribute.StrategyExtended` with additional methods.""" + return self._extended + + def scope(self): + """Returns a context manager selecting this Strategy as current. + + Inside a `with strategy.scope():` code block, this thread + will use a variable creator set by `strategy`, and will + enter its "cross-replica context". + + Returns: + A context manager. + """ + return self._extended._scope(self) # pylint: disable=protected-access + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def read_var(self, v): + """DEPRECATED: use extended.read_var() instead.""" + return self._extended.read_var(v) + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def colocate_vars_with(self, colocate_with_variable): + """DEPRECATED: use extended.colocate_vars_with() instead.""" + return self._extended.colocate_vars_with(colocate_with_variable) + + @doc_controls.do_not_generate_docs # DEPRECATED + def distribute_dataset(self, dataset_fn): + """Return a `dataset` split across all replicas. DEPRECATED. + + DEPRECATED: Please use `make_dataset_iterator` or + `make_input_fn_iterator` instead. + + Suitable for providing input to `extended.call_for_each_replica()` by + creating an iterator: + + ``` + def dataset_fn(): + return tf.data.Dataset.from_tensors([[1.]]).repeat() + + with strategy.scope(): + distributed_dataset = strategy.distribute_dataset(dataset_fn) + iterator = distributed_dataset.make_initializable_iterator() + replica_results = strategy.extended.call_for_each_replica( + replica_fn, args=(iterator.get_next(),)) + ``` + + Args: + dataset_fn: A function that returns a `tf.data.Dataset`. + + Returns: + A `PerReplicaDataset` that will produce data for each replica. + """ + return self._extended._distribute_dataset(dataset_fn) # pylint: disable=protected-access + + def make_dataset_iterator(self, dataset): + """Makes an iterator for input provided via input_dataset. + + Data from the given dataset will be distributed evenly across all the + compute replicas. We will assume that the input dataset is batched by the + global batch size. With this assumption, we will make a best effort to + divide each batch across all the replicas (one or more workers). + If this effort fails, an error will be thrown, and the user should instead + use `make_input_fn_iterator` which provides more control to the user, and + does not try to divide a batch across replicas. + + The user could also use `make_input_fn_iterator` if they want to + customize which input is fed to which replica/worker etc. + + Args: + dataset: `tf.data.Dataset` that will be distributed evenly across all + replicas. + + Returns: + An `tf.distribute.InputIterator` which returns inputs for each step of the + computation. User should call `initialize` on the returned iterator. + """ + return self._extended._make_dataset_iterator(dataset) # pylint: disable=protected-access + + def make_input_fn_iterator(self, + input_fn, + replication_mode=InputReplicationMode.PER_WORKER): + """Returns an iterator split across replicas created from an input function. + + The `input_fn` should take an `tf.distribute.InputContext` object where + information about input sharding can be accessed: + + ``` + def input_fn(input_context): + d = tf.data.Dataset.from_tensors([[1.]]).repeat() + return d.shard(input_context.num_input_pipelines, + input_context.input_pipeline_id) + with strategy.scope(): + iterator = strategy.make_input_fn_iterator( + input_fn) + replica_results = strategy.extended.call_for_each_replica( + replica_fn, iterator.get_next()) + ``` + + Args: + input_fn: A function that returns a `tf.data.Dataset`. This function is + expected to take an `tf.distribute.InputContext` object. + replication_mode: an enum value of `tf.distribute.InputReplicationMode`. + Only `PER_WORKER` is supported currently. + + Returns: + An iterator object that can be initialized and fetched next element. + """ + if replication_mode != InputReplicationMode.PER_WORKER: + raise ValueError( + "Input replication mode not supported: %r" % replication_mode) + return self.extended._make_input_fn_iterator( # pylint: disable=protected-access + input_fn, replication_mode=replication_mode) + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def broadcast(self, tensor, destinations=None): + """DEPRECATED: use extended.broadcast_to() instead.""" + return self._extended.broadcast_to(tensor, destinations) + + @doc_controls.do_not_generate_docs # Use experimental_initialize() instead. + def initialize(self): + """DEPRECATED: Use `experimental_initialize()` instead.""" + return self._extended._initialize() # pylint: disable=protected-access + + def experimental_initialize(self): + """Any initialization to be done before running any computations. + + In eager mode, it executes any initialization as a side effect. + In graph mode, it creates the initialization ops and returns them. + + For example, TPU initialize_system ops. + + Returns: + A list of ops to execute. + """ + return self._extended._initialize() # pylint: disable=protected-access + + @doc_controls.do_not_generate_docs # Use experimental_finalize() instead. + def finalize(self): + """DEPRECATED: Use `experimental_finalize()` instead.""" + return self._extended._finalize() # pylint: disable=protected-access + + def experimental_finalize(self): + """Any final actions to be done at the end of all computations. + + In eager mode, it executes any finalize actions as a side effect. + In graph mode, it creates the finalize ops and returns them. + + For example, TPU shutdown ops. + + Returns: + A list of ops to execute. + """ + return self._extended._finalize() # pylint: disable=protected-access + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def run_steps_on_dataset(self, fn, iterator, iterations=1, + initial_loop_values=None): + """DEPRECATED: use extended.experimental_run_steps_on_iterator() instead.""" + return self._extended.experimental_run_steps_on_iterator( + fn, iterator, iterations, initial_loop_values) + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def call_for_each_replica(self, fn, *args, **kwargs): + """DEPRECATED: use extended.call_for_each_replica() instead.""" + # Handle old *args, **kwargs, and new args=(...), kwargs={...}, to + # allow transition. + a = kwargs.pop("args", None) + if a is not None: + if args: + raise ValueError( + "Can't pass *args and args=... to call_for_each_replica") + args = a + k = kwargs.pop("kwargs", None) + if k is not None: + if kwargs: + raise ValueError( + "Can't pass **kwargs and kwargs=... to call_for_each_replica") + kwargs = k + kwargs.pop("run_concurrently", None) # Ignore old option. + return self._extended.call_for_each_replica(fn, args, kwargs) + + def reduce(self, reduce_op, value): + """Reduce `value` across replicas. + + Args: + reduce_op: A `tf.distribute.ReduceOp` value specifying how values should + be combined. + value: A "per replica" value to be combined into a single tensor. + + Returns: + A `Tensor`. + """ + _require_cross_replica_context_extended(self._extended) + return self._extended._reduce(reduce_op, value) # pylint: disable=protected-access + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def batch_reduce(self, aggregation, value_destination_pairs): + """DEPRECATED: use extended.batch_reduce_to() instead.""" + return self._extended.batch_reduce_to(aggregation, value_destination_pairs) + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def update(self, var, fn, *args, **kwargs): + """DEPRECATED: use extended.update() instead.""" + group = kwargs.pop("group", True) + # We temporarily support "grouped" in addition to "group" for backward- + # compatibility. + group = kwargs.pop("grouped", True) and group + # Handle old *args, **kwargs, and new args=(...), kwargs={...}, to + # allow transition. + a = kwargs.pop("args", None) + if a is not None: + if args: + raise ValueError( + "Can't pass *args and args=... to update") + args = a + k = kwargs.pop("kwargs", None) + if k is not None: + if kwargs: + raise ValueError( + "Can't pass **kwargs and kwargs=... to update") + kwargs = k + return self._extended.update(var, fn, args, kwargs, group) + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def update_non_slot(self, colocate_with, fn, *args, **kwargs): + """DEPRECATED: use extended.update_non_slot() instead.""" + group = kwargs.pop("group", True) + # We temporarily support "grouped" in addition to "group" for backward- + # compatibility. + group = kwargs.pop("grouped", True) and group + # Handle old *args, **kwargs, and new args=(...), kwargs={...}, to + # allow transition. + a = kwargs.pop("args", None) + if a is not None: + if args: + raise ValueError( + "Can't pass *args and args=... to update_non_slot") + args = a + k = kwargs.pop("kwargs", None) + if k is not None: + if kwargs: + raise ValueError( + "Can't pass **kwargs and kwargs=... to update_non_slot") + kwargs = k + return self._extended.update_non_slot( + colocate_with, fn, args, kwargs, group) + + @doc_controls.do_not_generate_docs # DEPRECATED, -> `DistributedValues` + def unwrap(self, value): + """Returns the list of all per-replica values contained in `value`. + + Args: + value: A value returned by `extended.call_for_each_replica()` or a + variable created in `scope`. + + Returns: + A list of values contained in `value`. If `value` represents a single + value, this returns `[value].` + """ + return self._extended._unwrap(value) # pylint: disable=protected-access + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def value_container(self, value): + """DEPRECATED: use extended.value_container() instead.""" + return self._extended.value_container(value) + + @doc_controls.do_not_generate_docs # DEPRECATED, -> `DistributedValues` + def group(self, value, name=None): + """Shortcut for `tf.group(self.unwrap(value))`.""" + return self._extended._group(value, name) # pylint: disable=protected-access + + @property + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def require_static_shapes(self): + """DEPRECATED: use extended.require_static_shapes instead.""" + return self._extended.experimental_require_static_shapes + + @property + def num_replicas_in_sync(self): + """Returns number of replicas over which gradients are aggregated.""" + return self._extended._num_replicas_in_sync # pylint: disable=protected-access + + @property + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def worker_devices(self): + """DEPRECATED: use extended.worker_devices instead.""" + return self._extended.worker_devices + + @property + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def parameter_devices(self): + """DEPRECATED: use extended.parameter_devices instead.""" + return self._extended.parameter_devices + + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def non_slot_devices(self, var_list): + """DEPRECATED: use extended.non_slot_devices instead.""" + return self._extended.non_slot_devices(var_list) + + @property + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def between_graph(self): + """DEPRECATED: use extended.experimental_between_graph instead.""" + return self._extended.experimental_between_graph + + @doc_controls.do_not_generate_docs # DEPRECATED, being replaced by a new API. + def configure(self, + session_config=None, + cluster_spec=None, + task_type=None, + task_id=None): + # pylint: disable=g-doc-return-or-yield,g-doc-args + """DEPRECATED: use `update_config_proto` instead. + + Configures the strategy class. + + DEPRECATED: This method's functionality has been split into the strategy + constructor and `update_config_proto`. In the future, we will allow passing + cluster and config_proto to the constructor to configure the strategy. And + `update_config_proto` can be used to update the config_proto based on the + specific strategy. + """ + return self._extended._configure( # pylint: disable=protected-access + session_config, cluster_spec, task_type, task_id) + + def update_config_proto(self, config_proto): + """Returns a copy of `config_proto` modified for use with this strategy. + + The updated config has something needed to run a strategy, e.g. + configuration to run collective ops, or device filters to improve + distributed training performance. + + Args: + config_proto: a `tf.ConfigProto` object. + + Returns: + The updated copy of the `config_proto`. + """ + return self._extended._update_config_proto(config_proto) # pylint: disable=protected-access + + @property + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def should_init(self): + """DEPRECATED: use extended.should_init instead.""" + return self._extended.experimental_should_init + + @property + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def should_checkpoint(self): + """DEPRECATED: use extended.should_checkpoint instead.""" + return self._extended.should_checkpoint + + @property + @doc_controls.do_not_generate_docs # DEPRECATED, moving to `extended` + def should_save_summary(self): + """DEPRECATED: use extended.should_save_summary instead.""" + return self._extended.should_save_summary + + def __deepcopy__(self, memo): + # First do a regular deepcopy of `self`. + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + setattr(result, k, copy.deepcopy(v, memo)) + # One little fix-up: we want `result._extended` to reference `result` + # instead of `self`. + result._extended._container_strategy_weakref = weakref.ref(result) # pylint: disable=protected-access + return result + + def __copy__(self): + raise RuntimeError("Must only deepcopy DistributionStrategy.") + + +@tf_export("distribute.StrategyExtended") +class DistributionStrategyExtended(object): + """Additional APIs for algorithms that need to be distribution-aware. + + The intent is that you can write an algorithm in a stylized way and + it will be usable with a variety of different + `tf.distribute.Strategy` + implementations. Each descendant will implement a different strategy + for distributing the algorithm across multiple devices/machines. + Furthermore, these changes can be hidden inside the specific layers + and other library classes that need special treatment to run in a + distributed setting, so that most users' model definition code can + run unchanged. The `tf.distribute.Strategy` API works the same way + with eager and graph execution. + + First let's introduce a few high-level concepts: + + * _Data parallelism_ is where we run multiple copies of the model + on different slices of the input data. This is in contrast to + _model parallelism_ where we divide up a single copy of a model + across multiple devices. + Note: we only support data parallelism for now, but + hope to add support for model parallelism in the future. + * A _replica_ is one copy of the model, running on one slice of the + input data. + * _Synchronous_, or more commonly _sync_, training is where the + updates from each replica are aggregated together before updating + the model variables. This is in contrast to _asynchronous_, or + _async_ training, where each replica updates the model variables + independently. + * Furthermore you might run your computation on multiple devices + on one machine (or "host"), or on multiple machines/hosts. + If you are running on multiple machines, you might have a + single master host that drives computation across all of them, + or you might have multiple clients driving the computation + asynchronously. + + To distribute an algorithm, we might use some of these ingredients: + + * Parameter servers: These are hosts that hold a single copy of + parameters/variables. All replicas that want to operate on a variable + retrieve it at the beginning of a step and send an update to be + applied at the end of the step. Can support either sync or async + training. + * Mirrored variables: These are variables that are copied to multiple + devices, where we keep the copies in sync by applying the same + updates to every copy. Normally would only be used with sync training. + * Reductions and Allreduce: A _reduction_ is some method of + aggregating multiple values into one value, like "sum" or + "mean". If doing sync training, we will perform a reduction on the + gradients to a parameter from all replicas before applying the + update. Allreduce is an algorithm for performing a reduction on + values from multiple devices and making the result available on + all of those devices. + * In the future we will have support for TensorFlow's partitioned + variables, where a single variable is split across multiple + devices. + + We have then a few approaches we want to support: + + * Code written (as if) with no knowledge of class `tf.distribute.Strategy`. + This code should work as before, even if some of the layers, etc. + used by that code are written to be distribution-aware. This is done + by having a default `tf.distribute.Strategy` that gives ordinary behavior, + and by default being in a single replica context. + * Ordinary model code that you want to run using a specific + `tf.distribute.Strategy`. This can be as simple as: + + ``` + with my_strategy.scope(): + iterator = my_strategy.make_dataset_iterator(dataset) + session.run(iterator.initialize()) + replica_train_ops = my_strategy.extended.call_for_each_replica( + replica_fn, args=(iterator.get_next(),)) + train_op = my_strategy.group(replica_train_ops) + ``` + + This takes an ordinary `dataset` and `replica_fn` and runs it + distributed using a particular `tf.distribute.Strategy` in + `my_strategy`. Any variables created in `replica_fn` are created + using `my_strategy`'s policy, and library functions called by + `replica_fn` can use the `get_replica_context()` API to get enhanced + behavior in this case. + + * If you want to write a distributed algorithm, you may use any of + the `tf.distribute.Strategy` APIs inside a + `with my_strategy.scope():` block of code. + + Lower-level concepts: + + * Wrapped values: In order to represent values parallel across devices + (either replicas or the devices associated with a particular value), we + wrap them in a "PerReplica" or "Mirrored" object that contains a map + from device to values. "PerReplica" is used when the value may be + different across replicas, and "Mirrored" when the value are the same. + * Unwrapping and merging: Consider calling a function `fn` on multiple + replicas, like `extended.call_for_each_replica(fn, args=[w])` with an + argument `w` that is a wrapped value. This means `w` will have a map taking + replica device `d0` to `w0`, replica device `d1` to `w1`, + etc. `extended.call_for_each_replica()` unwraps `w` before calling `fn`, so + it calls `fn(w0)` on `d0`, `fn(w1)` on `d1`, etc. It then merges the return + values from `fn()`, which can possibly result in wrapped values. For + example, let's say `fn()` returns a tuple with three components: `(x, a, + v0)` from replica 0, `(x, b, v1)` on replica 1, etc. If the first component + is the same object `x` from every replica, then the first component of the + merged result will also be `x`. If the second component is different (`a`, + `b`, ...) from each replica, then the merged value will have a wrapped map + from replica device to the different values. If the third component is the + members of a mirrored variable (`v` maps `d0` to `v0`, `d1` to `v1`, etc.), + then the merged result will be that mirrored variable (`v`). + * Replica context vs. Cross-replica context: _replica context_ is when we + are in some function that is being called once for each replica. + Otherwise we are in cross-replica context, which is useful for + calling `tf.distribute.Strategy` methods which operate across the + replicas (like `reduce_to()`). By default you start in a replica context + (the default "single replica context") and then some methods can + switch you back and forth, as described below. + * Worker devices vs. parameter devices: Most replica computations will + happen on worker devices. Since we don't yet support model + parallelism, there will be one worker device per replica. When using + parameter servers (see above), the set of devices holding + variables may be different, otherwise the parameter devices might + match the worker devices. + * Non-slot devices are some subset of the parameter devices where we + put all the non-slot variables. We need to ensure that all + non-slot variables are allocated on the same device, or mirrored + across the same set of devices. If you have some variable you want + to colocate all the non-slot variables with, you can use + `colocate_vars_with()` to get the remaining non-slot variables on + the same device. Otherwise you can use `non_slot_devices()` to + pick a consistent set of devices to pass to both + `colocate_vars_with()` and `update_non_slot()`. + + When using a `tf.distribute.Strategy`, we have a new type dimension + called _locality_ that says what values are compatible with which + APIs: + + * T: different value for each replica (e.g. a PerReplica-wrapped value). + * M: value is "mirrored" across replicas, i.e. there are copies with the + same value on each replica (e.g. a Mirrored-wrapped value). + * V(`v`): value is "mirrored" across all the devices which have a + copy of variable `v` (also a Mirrored-wrapped value, but over + parameter devices instead of worker devices). + * N: value is "mirrored" across all the "non-slot" devices + + Rules for methods with respect to locality and single-replica vs. + cross-replica context: + + * `with d.scope()`: default single-replica context -> cross-replica context + for `d` + * `with d.extended.colocate_vars_with(v)`: in replica/cross-replica context, + variables will be created with locality V(`v`). That is, if we write + `with d.extended.colocate_vars_with(v1): v2 = tf.get_variable(...)`, + then `v2` will have locality V(`v1`), i.e. locality V(`v2`) will equal + V(`v1`). + * `with d.extended.colocate_vars_with(d.extended.non_slot_devices(...))`: in + replica/cross-replica context, variables will be created with locality N + * `v = tf.get_variable(...)`: in replica/cross-replica context, creates + a variable (which by definition will have locality V(`v`), though + will match another locality if inside a `colocate_vars_with` + scope). + * `d.make_dataset_iterator(dataset)` (or the deprecated + `d.distribute_dataset(dataset).make_one_shot_iterator()`): in cross-replica + context, produces an iterator with locality T + * `d.extended.broadcast_to(t)`: in cross-replica context, produces a value + with locality M + * `d.extended.broadcast_to(t, v)`: in cross-replica context, produces a value + with locality V(`v`) + * `d.extended.call_for_each_replica(fn, ...)`: in cross-replica context, runs + `fn()` in a replica context (and so may call `get_replica_context()` and + use its API, including `merge_call()` to get back to cross-replica + context), once for each replica. May use values with locality T or + M, and any variable. + * `d.extended.reduce_to(m, t, t)`: in cross-replica context, accepts t with + locality T and produces a value with locality M. + * `d.extended.reduce_to(m, t, v)`: in cross-replica context, accepts t with + locality T and produces a value with locality V(`v`). + * `d.extended.batch_reduce_to(m, [(t, v)]): see `d.extended.reduce_to()` + * `d.extended.update(v, fn, ...)`: in cross-replica context, runs `fn()` once + for each device `v` is copied to, all inputs should have locality + V(`v`), output will have locality V(`v`) as well. + * `d.extended.update_non_slot(d.extended.non_slot_devices(), fn)`: in + cross-replica context, like `d.extended.update()` except with locality N. + * `d.extended.read_var(v)`: Gets the (read-only) value of the variable `v` (on + the device determined by the current device scope), aggregating + across replicas for replica-local variables. Frequently, this will be + done automatically when using `v` in an expression or fetching it in + a cross-replica context, but this function can be used to force that + conversion happens at a particular point in time (for example, to + add the result of the conversion to a graph collection). + + The standard pattern for updating variables is to: + + 1. Create an input iterator with `d.make_dataset_iterator()`. + 2. Define each replica `d.extended.call_for_each_replica()` up to the point of + getting a list of gradient, variable pairs. + 3. Call `d.extended.reduce_to(VariableAggregation.SUM, t, v)` or + `d.extended.batch_reduce_to()` to sum the gradients (with locality T) + into values with locality V(`v`). + 4. Call `d.extended.update(v)` for each variable to update its value. + + Steps 3 and 4 are done automatically by class `Optimizer` if you call + its `apply_gradients` method in a replica context. Otherwise you can + manually call its `_distributed_apply` method in a cross-replica context. + + Another thing you might want to do in the middle of your replica function is + an all-reduce of some intermediate value, using `d.extended.reduce_to()` or + `d.extended.batch_reduce_to()`. You simply provide the same tensor as the + input and destination. + + Layers should expect to be called in a replica context, and can use + the `tf.distribute.get_replica_context` function to get a + `tf.distribute.ReplicaContext` object. The + `ReplicaContext` object has a `merge_call()` method for entering + cross-replica context where you can use `reduce_to()` (or + `batch_reduce_to()`) and then optionally `update()` to update state. + + You may use this API whether or not a `tf.distribute.Strategy` is + being used, since there is a default implementation of + `ReplicaContext` and `tf.distribute.Strategy`. + + NOTE for new `tf.distribute.Strategy` implementations: Please put all logic + in a subclass of `tf.distribute.StrategyExtended`. The only code needed for + the `tf.distribute.Strategy` subclass is for instantiating your subclass of + `tf.distribute.StrategyExtended` in the `__init__` method. + """ + + def __init__(self, container_strategy): + self._container_strategy_weakref = weakref.ref(container_strategy) + self._default_device = None + # This property is used to determine if we should set drop_remainder=True + # when creating Datasets from numpy array inputs. + self._require_static_shapes = False + + def _container_strategy(self): + """Get the containing `DistributionStrategy`. + + This should not generally be needed except when creating a new + `ReplicaContext` and to validate that the caller is in the correct + `scope()`. + + Returns: + The `DistributionStrategy` such that `strategy.extended` is `self`. + """ + container_strategy = self._container_strategy_weakref() + assert container_strategy is not None + return container_strategy + + def _scope(self, strategy): + """Implementation of DistributionStrategy.scope().""" + if distribution_strategy_context.has_distribution_strategy(): + _require_cross_replica_context_extended(self) + return _SameScopeAgainContext(strategy) + + def creator_with_resource_vars(*args, **kwargs): + _require_distribution_strategy_scope_extended(self) + kwargs["use_resource"] = True + return self._create_variable(*args, **kwargs) + + def distributed_getter(getter, *args, **kwargs): + if not self._allow_variable_partition(): + if kwargs.pop("partitioner", None) is not None: + tf_logging.log_first_n( + tf_logging.WARN, "Partitioned variables are disabled when using " + "current tf.distribute.Strategy.", 1) + return getter(*args, **kwargs) + + return _CurrentDistributionContext( + strategy, + variable_scope.variable_creator_scope(creator_with_resource_vars), + variable_scope.variable_scope( + variable_scope.get_variable_scope(), + custom_getter=distributed_getter), self._default_device) + + def _allow_variable_partition(self): + return False + + def _create_variable(self, next_creator, *args, **kwargs): + # Note: should support "colocate_with" argument. + raise NotImplementedError("must be implemented in descendants") + + def read_var(self, v): + """Reads the value of a variable. + + Returns the aggregate value of a replica-local variable, or the + (read-only) value of any other variable. + + Args: + v: A variable allocated within the scope of this `tf.distribute.Strategy`. + + Returns: + A tensor representing the value of `v`, aggregated across replicas if + necessary. + """ + raise NotImplementedError("must be implemented in descendants") + + def colocate_vars_with(self, colocate_with_variable): + """Scope that controls which devices variables will be created on. + + No operations should be added to the graph inside this scope, it + should only be used when creating variables (some implementations + work by changing variable creation, others work by using a + tf.colocate_with() scope). + + This may only be used inside `self.scope()`. + + Example usage: + + ``` + with strategy.scope(): + var1 = tf.get_variable(...) + with strategy.extended.colocate_vars_with(v1): + # var2 and var3 will be created on the same device(s) as var1 + var2 = tf.get_variable(...) + var3 = tf.get_variable(...) + + def fn(v1, v2, v3): + # operates on v1 from var1, v2 from var2, and v3 from var3 + + # `fn` runs on every device `v1` is on, `v2` and `v3` will be there too. + strategy.extended.update(v1, fn, args=(v2, v3)) + ``` + + Args: + colocate_with_variable: A created in `self.scope()`. Variables created + while in the returned context manager will be on the same set of + devices as `colocate_with_variable`. + + Returns: + A context manager. + """ + def create_colocated_variable(next_creator, *args, **kwargs): + _require_distribution_strategy_scope_extended(self) + kwargs["use_resource"] = True + kwargs["colocate_with"] = colocate_with_variable + return next_creator(*args, **kwargs) + + _require_distribution_strategy_scope_extended(self) + return variable_scope.variable_creator_scope(create_colocated_variable) + + def _call_dataset_fn(self, dataset_fn): + """Call the `dataset_fn` with `input_context` as argument.""" + result = dataset_fn() + if not isinstance(result, dataset_ops.DatasetV2): + raise ValueError( + "dataset_fn() must return a tf.data.Dataset when using a " + "tf.distribute.Strategy.") + return result + + # TODO(josh11b): `PerReplicaDataset` currently only implements a few methods of + # Dataset API such as make_one_shot_iterator and make_initializable_iterator. + # Extend to implement more functionality of datasets. + def _distribute_dataset(self, dataset_fn): + raise NotImplementedError("must be implemented in descendants") + + def _make_dataset_iterator(self, dataset): + raise NotImplementedError("must be implemented in descendants") + + def _make_input_fn_iterator(self, input_fn, replication_mode): + raise NotImplementedError("must be implemented in descendants") + + def broadcast_to(self, tensor, destinations): + """Mirror a tensor on one device to all worker devices. + + Args: + tensor: A Tensor value to broadcast. + destinations: A mirrored variable or device string specifying the + destination devices to copy `tensor` to. + + Returns: + A value mirrored to `destinations` devices. + """ + # TODO(josh11b): More docstring + _require_cross_replica_context_extended(self) + assert not isinstance(destinations, (list, tuple)) + return self._broadcast_to(tensor, destinations) + + def _broadcast_to(self, tensor, destinations): + raise NotImplementedError("must be implemented in descendants") + + def _initialize(self): + return [] + + def _finalize(self): + return [] + + def experimental_run_steps_on_iterator(self, fn, iterator, iterations=1, + initial_loop_values=None): + """Run `fn` with input from `iterator` for `iterations` times. + + This method can be used to run a step function for training a number of + times using input from a dataset. + + Args: + fn: function to run using this distribution strategy. The function must + have the following signature: `def fn(context, inputs)`. + `context` is an instance of `MultiStepContext` that will be passed when + `fn` is run. `context` can be used to specify the outputs to be returned + from `fn` by calling `context.set_last_step_output`. It can also be used + to capture non tensor outputs by `context.set_non_tensor_output`. + See `MultiStepContext` documentation for more information. + `inputs` will have same type/structure as `iterator.get_next()`. + Typically, `fn` will use `call_for_each_replica` method of the strategy + to distribute the computation over multiple replicas. + iterator: Iterator of a dataset that represents the input for `fn`. The + caller is responsible for initializing the iterator as needed. + iterations: (Optional) Number of iterations that `fn` should be run. + Defaults to 1. + initial_loop_values: (Optional) Initial values to be passed into the + loop that runs `fn`. Defaults to `None`. # TODO(priyag): Remove + initial_loop_values argument when we have a mechanism to infer the + outputs of `fn`. + + Returns: + Returns the `MultiStepContext` object which has the following properties, + among other things: + - run_op: An op that runs `fn` `iterations` times. + - last_step_outputs: A dictionary containing tensors set using + `context.set_last_step_output`. Evaluating this returns the value of + the tensors after the last iteration. + - non_tensor_outputs: A dictionatry containing anything that was set by + `fn` by calling `context.set_non_tensor_output`. + """ + _require_cross_replica_context_extended(self) + return self._experimental_run_steps_on_iterator( + fn, iterator, iterations, initial_loop_values) + + def _experimental_run_steps_on_iterator(self, fn, iterator, iterations, + initial_loop_values): + raise NotImplementedError("must be implemented in descendants") + + def call_for_each_replica(self, fn, args=(), kwargs=None): + """Run `fn` once per replica. + + `fn` may call `tf.get_replica_context()` to access methods such as + `replica_id_in_sync_group` and `merge_call()`. + + `merge_call()` is used to communicate between the replicas and + re-enter the cross-replica context. All replicas pause their execution + having encountered a `merge_call()` call. After that the + `merge_fn`-function is executed. Its results are then unwrapped and + given back to each replica call. After that execution resumes until + `fn` is complete or encounters another `merge_call()`. Example: + + ```python + # Called once in "cross-replica" context. + def merge_fn(distribution, three_plus_replica_id): + # sum the values across replicas + return sum(distribution.unwrap(three_plus_replica_id)) + + # Called once per replica in `distribution`, in a "replica" context. + def fn(three): + replica_ctx = tf.get_replica_context() + v = three + replica_ctx.replica_id_in_sync_group + # Computes the sum of the `v` values across all replicas. + s = replica_ctx.merge_call(merge_fn, args=(v,)) + return s + v + + with distribution.scope(): + # in "cross-replica" context + ... + merged_results = distribution.call_for_each_replica(fn, args=[3]) + # merged_results has the values from every replica execution of `fn`. + print(distribution.unwrap(merged_results)) # Prints a list + ``` + + Args: + fn: function to run (will be run once per replica). + args: Tuple or list with positional arguments for `fn`. + kwargs: Dict with keyword arguments for `fn`. + + Returns: + Merged return value of `fn` across all replicas. + """ + _require_cross_replica_context_extended(self) + if kwargs is None: + kwargs = {} + return self._call_for_each_replica(fn, args, kwargs) + + def _call_for_each_replica(self, fn, args, kwargs): + raise NotImplementedError("must be implemented in descendants") + + def _reduce(self, reduce_op, value): + # Default implementation until we have an implementation for each strategy. + return self._unwrap(self._reduce_to( + reduce_op, value, device_util.current() or "/device:CPU:0"))[0] + + def reduce_to(self, reduce_op, value, destinations): + """Combine (via e.g. sum or mean) values across replicas. + + Args: + reduce_op: Reduction type, an instance of `tf.distribute.ReduceOp` enum. + DEPRECATED but still accepted values: + `tf.VariableAggregation.SUM`, + `tf.VariableAggregation.MEAN`, + value: A per-replica value with one value per replica. + destinations: A mirrored variable, a per-replica tensor, or a device + string. The return value will be copied to all destination devices (or + all the devices where the `destinations` value resides). To perform an + all-reduction, pass `value` to `destinations`. + + Returns: + A value mirrored to `destinations`. + """ + # TODO(josh11b): More docstring + _require_cross_replica_context_extended(self) + assert not isinstance(destinations, (list, tuple)) + + # TODO(priyag): Remove this when all callers have been updated. + if isinstance(reduce_op, variable_scope.VariableAggregation): + assert reduce_op in ( + variable_scope.VariableAggregation.SUM, + variable_scope.VariableAggregation.MEAN, + ) + reduce_op = reduce_util.ReduceOp.from_variable_aggregation(reduce_op) + assert (reduce_op == reduce_util.ReduceOp.SUM or + reduce_op == reduce_util.ReduceOp.MEAN) + return self._reduce_to(reduce_op, value, destinations) + + def _reduce_to(self, reduce_op, value, destinations): + raise NotImplementedError("must be implemented in descendants") + + def batch_reduce_to(self, reduce_op, value_destination_pairs): + """Combine multiple `reduce_to` calls into one for faster execution. + + Args: + reduce_op: Reduction type, an instance of `tf.distribute.ReduceOp` enum. + DEPRECATED but still accepted values: + `tf.VariableAggregation.SUM`, + `tf.VariableAggregation.MEAN`, + value_destination_pairs: A sequence of (value, destinations) + pairs. See `reduce_to()` for a description. + + Returns: + A list of mirrored values, one per pair in `value_destination_pairs`. + """ + # TODO(josh11b): More docstring + _require_cross_replica_context_extended(self) + + # TODO(priyag): Remove this when all callers have been updated. + if isinstance(reduce_op, variable_scope.VariableAggregation): + assert reduce_op in [ + variable_scope.VariableAggregation.SUM, + variable_scope.VariableAggregation.MEAN, + ] + reduce_op = reduce_util.ReduceOp.from_variable_aggregation(reduce_op) + return self._batch_reduce_to(reduce_op, value_destination_pairs) + + def _batch_reduce_to(self, reduce_op, value_destination_pairs): + return [ + self.reduce_to(reduce_op, t, destinations=v) + for t, v in value_destination_pairs + ] + + def update(self, var, fn, args=(), kwargs=None, group=True): + """Run `fn` to update `var` using inputs mirrored to the same devices. + + If `var` is mirrored across multiple devices, then this implements + logic like: + + ``` + results = {} + for device, v in var: + with tf.device(device): + # args and kwargs will be unwrapped if they are mirrored. + results[device] = fn(v, *args, **kwargs) + return merged(results) + ``` + + Otherwise this returns `fn(var, *args, **kwargs)` colocated with `var`. + + Neither `args` nor `kwargs` may contain per-replica values. + If they contain mirrored values, they will be unwrapped before + calling `fn`. + + Args: + var: Variable, possibly mirrored to multiple devices, to operate on. + fn: Function to call. Should take the variable as the first argument. + args: Tuple or list. Additional positional arguments to pass to `fn()`. + kwargs: Dict with keyword arguments to pass to `fn()`. + group: Boolean. Defaults to True. If False, the return value will be + unwrapped. + + Returns: + By default, the merged return value of `fn` across all replicas. The + merged result has dependencies to make sure that if it is evaluated at + all, the side effects (updates) will happen on every replica. If instead + "group=False" is specified, this function will return a nest of lists + where each list has an element per replica, and the caller is responsible + for ensuring all elements are executed. + """ + _require_cross_replica_context_extended(self) + if kwargs is None: + kwargs = {} + return self._update(var, fn, args, kwargs, group) + + def _update(self, var, fn, args, kwargs, group): + raise NotImplementedError("must be implemented in descendants") + + def update_non_slot( + self, colocate_with, fn, args=(), kwargs=None, group=True): + """Runs `fn(*args, **kwargs)` on `colocate_with` devices. + + Args: + colocate_with: The return value of `non_slot_devices()`. + fn: Function to execute. + args: Tuple or list. Positional arguments to pass to `fn()`. + kwargs: Dict with keyword arguments to pass to `fn()`. + group: Boolean. Defaults to True. If False, the return value will be + unwrapped. + + Returns: + Return value of `fn`, possibly merged across devices. + """ + _require_cross_replica_context_extended(self) + if kwargs is None: + kwargs = {} + return self._update_non_slot(colocate_with, fn, args, kwargs, group) + + def _update_non_slot(self, colocate_with, fn, args, kwargs, group): + raise NotImplementedError("must be implemented in descendants") + + def _unwrap(self, distributed_value): + raise NotImplementedError("must be implemented in descendants") + + def value_container(self, value): + """Returns the container that this per-replica `value` belongs to. + + Args: + value: A value returned by `call_for_each_replica()` or a variable + created in `scope()`. + + Returns: + A container that `value` belongs to. + If value does not belong to any container (including the case of + container having been destroyed), returns the value itself. + `value in unwrap(value_container(value))` will always be true. + """ + raise NotImplementedError("must be implemented in descendants") + + def _group(self, value, name=None): + """Shortcut for `tf.group(distribution.unwrap(value))`.""" + value = nest.flatten(self._unwrap(value)) + + if len(value) != 1 or name is not None: + return control_flow_ops.group(value, name=name) + # Special handling for the common case of one op. + v, = value + if hasattr(v, "op"): + v = v.op + return v + + @property + def experimental_require_static_shapes(self): + return self._require_static_shapes + + @property + def _num_replicas_in_sync(self): + """Returns number of replicas over which gradients are aggregated.""" + raise NotImplementedError("must be implemented in descendants") + + @property + def worker_devices(self): + """Returns the list of devices used to run `call_for_each_replica()` calls. + """ + # TODO(josh11b): More docstring + raise NotImplementedError("must be implemented in descendants") + + @property + def parameter_devices(self): + """Returns the list of devices used for variable and `update` placement.""" + # TODO(josh11b): More docstring + raise NotImplementedError("must be implemented in descendants") + + def non_slot_devices(self, var_list): + """Device(s) for non-slot variables. + + Create variables on these devices in a + `with colocate_vars_with(non_slot_devices(...)):` block. + Update those using `update_non_slot()`. + + Args: + var_list: The list of variables being optimized, needed with the + default `tf.distribute.Strategy`. + """ + raise NotImplementedError("must be implemented in descendants") + + @property + def experimental_between_graph(self): + """Whether the strategy uses between-graph replication or not. + + This is expected to return a constant value that will not be changed + throughout its life cycle. + """ + raise NotImplementedError("must be implemented in descendants") + + def _configure(self, + session_config=None, + cluster_spec=None, + task_type=None, + task_id=None): + """Configures the strategy class.""" + del session_config, cluster_spec, task_type, task_id + + def _update_config_proto(self, config_proto): + return copy.deepcopy(config_proto) + + @property + def experimental_should_init(self): + """Whether initialization is needed.""" + raise NotImplementedError("must be implemented in descendants") + + @property + def should_checkpoint(self): + """Whether checkpointing is needed.""" + raise NotImplementedError("must be implemented in descendants") + + @property + def should_save_summary(self): + """Whether saving summaries is needed.""" + raise NotImplementedError("must be implemented in descendants") + + +# A note about the difference between the context managers +# `ReplicaContext` (defined here) and `_CurrentDistributionContext` +# (defined above) used by `DistributionStrategy.scope()`: +# +# * a ReplicaContext is only present during a `call_for_each_replica()` +# call (except during a `merge_run` call) and in such a scope it +# will be returned by calls to `get_replica_context()`. Implementers of new +# DistributionStrategy descendants will frequently also need to +# define a descendant of ReplicaContext, and are responsible for +# entering and exiting this context. +# +# * DistributionStrategy.scope() sets up a variable_creator scope that +# changes variable creation calls (e.g. to make mirrored +# variables). This is intended as an outer scope that users enter once +# around their model creation and graph definition. There is no +# anticipated need to define descendants of _CurrentDistributionContext. +# It sets the current DistributionStrategy for purposes of +# `get_strategy()` and `has_strategy()` +# and switches the thread mode to a "cross-replica context". +@tf_export("distribute.ReplicaContext") +class ReplicaContext(object): + """`tf.distribute.Strategy` API when in a replica context. + + To be used inside your replicated step function, such as in a + `tf.distribute.StrategyExtended.call_for_each_replica` call. + """ + + def __init__(self, strategy, replica_id_in_sync_group): + self._distribution_strategy = strategy + self._thread_context = distribution_strategy_context._InReplicaThreadMode( # pylint: disable=protected-access + self) + self._replica_id_in_sync_group = replica_id_in_sync_group + + def __enter__(self): + _push_per_thread_mode(self._thread_context) + + def __exit__(self, exception_type, exception_value, traceback): + _pop_per_thread_mode() + + def merge_call(self, merge_fn, args=(), kwargs=None): + """Merge args across replicas and run `merge_fn` in a cross-replica context. + + This allows communication and coordination when there are multiple calls + to a model function triggered by a call to + `strategy.extended.call_for_each_replica(model_fn, ...)`. + + See `tf.distribute.StrategyExtended.call_for_each_replica` for an + explanation. + + If not inside a distributed scope, this is equivalent to: + + ``` + strategy = tf.distribute.get_strategy() + with cross-replica-context(strategy): + return merge_fn(strategy, *args, **kwargs) + ``` + + Args: + merge_fn: function that joins arguments from threads that are given as + PerReplica. It accepts `tf.distribute.Strategy` object as + the first argument. + args: List or tuple with positional per-thread arguments for `merge_fn`. + kwargs: Dict with keyword per-thread arguments for `merge_fn`. + + Returns: + The return value of `merge_fn`, except for `PerReplica` values which are + unpacked. + """ + require_replica_context(self) + if kwargs is None: + kwargs = {} + return self._merge_call(merge_fn, args, kwargs) + + def _merge_call(self, merge_fn, args, kwargs): + """Default implementation for single replica.""" + _push_per_thread_mode( # thread-local, so not needed with multiple threads + distribution_strategy_context._CrossReplicaThreadMode( # pylint: disable=protected-access + self._distribution_strategy)) + try: + return merge_fn(self._distribution_strategy, *args, **kwargs) + finally: + _pop_per_thread_mode() + + @property + def num_replicas_in_sync(self): + """Returns number of replicas over which gradients are aggregated.""" + return self._distribution_strategy.num_replicas_in_sync + + @property + def replica_id_in_sync_group(self): + """Which replica is being defined, from 0 to `num_replicas_in_sync - 1`.""" + require_replica_context(self) + return self._replica_id_in_sync_group + + @property + @doc_controls.do_not_generate_docs # DEPRECATED, use `strategy` + def distribution_strategy(self): + """DEPRECATED: use `self.stratgey` instead.""" + return self._distribution_strategy + + @property + def strategy(self): + """The current `tf.distribute.Strategy` object.""" + return self._distribution_strategy + + @property + def devices(self): + """The devices this replica is to be executed on, as a list of strings.""" + require_replica_context(self) + return [device_util.current()] + + # TODO(josh11b): Implement `start_all_reduce(method, t)` for efficient + # all-reduce. It would return a function returning the result of reducing `t` + # across all replicas. The caller would wait to call this function until they + # needed the reduce result, allowing an efficient implementation: + # * With eager execution, the reduction could be performed asynchronously + # in the background, not blocking until the result was needed. + # * When constructing a graph, it could batch up all reduction requests up + # to that point that the first result is needed. Most likely this can be + # implemented in terms of `merge_call()` and `batch_reduce_to()`. + +# ------------------------------------------------------------------------------ + + +class _DefaultDistributionStrategy(DistributionStrategy): + """Default `tf.distribute.Strategy` if none is explicitly selected.""" + + def __init__(self): + super(_DefaultDistributionStrategy, self).__init__( + _DefaultDistributionExtended(self)) + + +class _DefaultDistributionExtended(DistributionStrategyExtended): + """Implementation of _DefaultDistributionStrategy.""" + + def _scope(self, strategy): + """Context manager setting a variable creator and `self` as current.""" + if distribution_strategy_context.has_distribution_strategy(): + raise RuntimeError("Must not nest tf.distribute.Strategy scopes.") + + def creator(next_creator, *args, **kwargs): + _require_distribution_strategy_scope_strategy(strategy) + return next_creator(*args, **kwargs) + + return _CurrentDistributionContext( + strategy, variable_scope.variable_creator_scope(creator)) + + def colocate_vars_with(self, colocate_with_variable): + """Does not require `self.scope`.""" + _require_distribution_strategy_scope_extended(self) + return ops.colocate_with(colocate_with_variable) + + def _distribute_dataset(self, dataset_fn): + return self._call_dataset_fn(dataset_fn) + + def _make_dataset_iterator(self, dataset): + return _DefaultDistributionExtended.DefaultInputIterator(dataset) + + def _make_input_fn_iterator(self, + input_fn, + replication_mode=InputReplicationMode.PER_WORKER): + return input_fn(InputContext()).make_initializable_iterator() + + def _broadcast_to(self, tensor, destinations): + if destinations is None: + return tensor + else: + raise NotImplementedError("TODO") + + def _call_for_each_replica(self, fn, args, kwargs): + with ReplicaContext( + self._container_strategy(), + replica_id_in_sync_group=constant_op.constant(0, dtypes.int32)): + return fn(*args, **kwargs) + + def _reduce_to(self, reduce_op, value, destinations): + # TODO(josh11b): Use destinations? + del reduce_op, destinations + return value + + def _update(self, var, fn, args, kwargs, group): + # The implementations of _update() and _update_non_slot() are identical + # except _update() passes `var` as the first argument to `fn()`. + return self._update_non_slot(var, fn, (var,) + tuple(args), kwargs, group) + + def _update_non_slot(self, colocate_with, fn, args, kwargs, should_group): + # TODO(josh11b): Figure out what we should be passing to UpdateContext() + # once that value is used for something. + with ops.colocate_with(colocate_with), UpdateContext(colocate_with): + result = fn(*args, **kwargs) + if should_group: + return result + else: + return nest.map_structure(self._unwrap, result) + + def read_var(self, replica_local_var): + return array_ops.identity(replica_local_var) + + def _unwrap(self, distributed_value): + return [distributed_value] + + def value_container(self, value): + return value + + @property + def _num_replicas_in_sync(self): + return 1 + + @property + def worker_devices(self): + raise RuntimeError("worker_devices() method unsupported by default " + "tf.distribute.Strategy.") + + @property + def parameter_devices(self): + raise RuntimeError("parameter_devices() method unsupported by default " + "tf.distribute.Strategy.") + + def non_slot_devices(self, var_list): + return min(var_list, key=lambda x: x.name) + + # TODO(priyag): This should inherit from `InputIterator`, once dependency + # issues have been resolved. + class DefaultInputIterator(object): + """Default implementation of `InputIterator` for default strategy.""" + + def __init__(self, dataset): + self._dataset = dataset + if eager_context.executing_eagerly(): + self._iterator = dataset.make_one_shot_iterator() + else: + self._iterator = dataset.make_initializable_iterator() + + def get_next(self): + return self._iterator.get_next() + + def initialize(self): + if eager_context.executing_eagerly(): + self._iterator = self._dataset.make_one_shot_iterator() + return [] + else: + return [self._iterator.initializer] + + # TODO(priyag): Delete this once all strategies use global batch size. + @property + def _global_batch_size(self): + return True + + +# ------------------------------------------------------------------------------ +# We haven't yet implemented deserialization for DistributedVariables. +# So here we catch any attempts to deserialize variables +# when using distribution strategies. +# pylint: disable=protected-access +_original_from_proto = resource_variable_ops._from_proto_fn + + +def _from_proto_fn(v, import_scope=None): + if distribution_strategy_context.has_distribution_strategy(): + raise NotImplementedError( + "Deserialization of variables is not yet supported when using a " + "tf.distribute.Strategy.") + else: + return _original_from_proto(v, import_scope=import_scope) + +resource_variable_ops._from_proto_fn = _from_proto_fn +# pylint: enable=protected-access + + +#------------------------------------------------------------------------------- +# Shorthand for some methods from distribution_strategy_context. +_push_per_thread_mode = distribution_strategy_context._push_per_thread_mode # pylint: disable=protected-access +_get_per_thread_mode = distribution_strategy_context._get_per_thread_mode # pylint: disable=protected-access +_pop_per_thread_mode = distribution_strategy_context._pop_per_thread_mode # pylint: disable=protected-access diff --git a/tensorflow/python/training/distribute_test.py b/tensorflow/python/distribute/distribute_lib_test.py similarity index 75% rename from tensorflow/python/training/distribute_test.py rename to tensorflow/python/distribute/distribute_lib_test.py index 0a7bbd5687..d63d1fe3c3 100644 --- a/tensorflow/python/training/distribute_test.py +++ b/tensorflow/python/distribute/distribute_lib_test.py @@ -18,13 +18,15 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import distribution_strategy_context +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes from tensorflow.python.ops import variable_scope from tensorflow.python.platform import test -from tensorflow.python.training import distribute -from tensorflow.python.training import distribution_strategy_context -class _TestReplicaContext(distribute.ReplicaContext): +class _TestReplicaContext(distribute_lib.ReplicaContext): def merge_call(self, fn, *args, **kwargs): return kwargs["test_arg"] @@ -38,10 +40,18 @@ def _get_test_variable(name, synchronization, aggregation): } -class _TestStrategy(distribute.DistributionStrategy): +class _TestStrategy(distribute_lib.DistributionStrategy): + + def __init__(self): + super(_TestStrategy, self).__init__(_TestExtended(self)) + + +class _TestExtended(distribute_lib.DistributionStrategyExtended): def _call_for_each_replica(self, fn, args, kwargs): - with _TestReplicaContext(self, replica_id=0): + with _TestReplicaContext( + self._container_strategy(), + replica_id_in_sync_group=constant_op.constant(0, dtypes.int32)): return fn(*args, **kwargs) def _create_variable(self, next_creator, *args, **kwargs): @@ -53,6 +63,7 @@ def _assert_in_default_state(t): t.assertIs(distribution_strategy_context._get_default_replica_context(), distribution_strategy_context.get_replica_context()) t.assertIs(None, distribution_strategy_context.get_cross_replica_context()) + t.assertFalse(distribution_strategy_context.in_cross_replica_context()) t.assertIs(distribution_strategy_context._get_default_distribution_strategy(), distribution_strategy_context.get_distribution_strategy()) t.assertFalse(distribution_strategy_context.has_distribution_strategy()) @@ -69,6 +80,7 @@ class TestStrategyTest(test.TestCase): self.assertTrue(replica_context is not None) self.assertIs(None, distribution_strategy_context.get_cross_replica_context()) + self.assertFalse(distribution_strategy_context.in_cross_replica_context()) self.assertTrue(distribution_strategy_context.has_distribution_strategy()) self.assertIs(dist, distribution_strategy_context.get_distribution_strategy()) @@ -80,9 +92,9 @@ class TestStrategyTest(test.TestCase): variable_scope.variable(1.0, name="bar")) with self.assertRaises(RuntimeError): - dist.call_for_each_replica(run_fn) + dist.extended.call_for_each_replica(run_fn) with dist.scope(): - dist.call_for_each_replica(run_fn) + dist.extended.call_for_each_replica(run_fn) _assert_in_default_state(self) def testScope(self): @@ -92,6 +104,7 @@ class TestStrategyTest(test.TestCase): self.assertIs(None, distribution_strategy_context.get_replica_context()) self.assertIs(dist, distribution_strategy_context.get_cross_replica_context()) + self.assertTrue(distribution_strategy_context.in_cross_replica_context()) self.assertTrue(distribution_strategy_context.has_distribution_strategy()) self.assertIs(dist, distribution_strategy_context.get_distribution_strategy()) @@ -131,6 +144,7 @@ class DefaultDistributionStrategyTest(test.TestCase): self.assertIs(None, distribution_strategy_context.get_replica_context()) self.assertIs(dist, distribution_strategy_context.get_cross_replica_context()) + self.assertTrue(distribution_strategy_context.in_cross_replica_context()) self.assertIs(dist, distribution_strategy_context.get_distribution_strategy()) self.assertFalse( @@ -140,9 +154,26 @@ class DefaultDistributionStrategyTest(test.TestCase): replica_ctx = distribution_strategy_context.get_replica_context() self.assertIs(distribution_strategy_context._get_default_replica_context(), replica_ctx) - self.assertEqual("foo_bar", replica_ctx.merge_call(merge_fn, "bar")) + self.assertEqual("foo_bar", replica_ctx.merge_call(merge_fn, args=("bar",))) _assert_in_default_state(self) +class InputContextTest(test.TestCase): + + def testProperties(self): + input_context = distribute_lib.InputContext( + num_input_pipelines=2, input_pipeline_id=1, num_replicas_in_sync=6) + self.assertEqual(6, input_context.num_replicas_in_sync) + self.assertEqual(1, input_context.input_pipeline_id) + self.assertEqual(2, input_context.num_input_pipelines) + + def testPerReplicaBatchSize(self): + input_context = distribute_lib.InputContext( + num_input_pipelines=2, input_pipeline_id=1, num_replicas_in_sync=6) + self.assertEqual(2, input_context.get_per_replica_batch_size(12)) + with self.assertRaises(ValueError): + input_context.get_per_replica_batch_size(13) + + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/distribute/distribution_strategy_context.py b/tensorflow/python/distribute/distribution_strategy_context.py new file mode 100644 index 0000000000..78e096e286 --- /dev/null +++ b/tensorflow/python/distribute/distribution_strategy_context.py @@ -0,0 +1,236 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Utility to get distribution strategy related contexts.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import ops +from tensorflow.python.util.lazy_loader import LazyLoader +from tensorflow.python.util.tf_export import tf_export + + +# There is a circular dependency between this and `distribute` module. So we +# load it lazily to workaround this. +distribute_lib = LazyLoader( + "distribute_lib", globals(), + "tensorflow.python.distribute.distribute_lib") + +# ------------------------------------------------------------------------------ +# Internal API for setting the current thread mode as being either in a +# replica or cross-replica context for a particular distribution strategy. + + +class _ThreadMode(object): + + def __init__(self, dist, cross, replica): + self.distribution_strategy = dist + self.cross_replica_context = cross + self.replica_context = replica + + +class _CrossReplicaThreadMode(_ThreadMode): + + def __init__(self, distribution_strategy): + _ThreadMode.__init__( + self, distribution_strategy, distribution_strategy, None) + + +class _InReplicaThreadMode(_ThreadMode): + + def __init__(self, replica_ctx): + _ThreadMode.__init__( + self, replica_ctx.distribution_strategy, None, replica_ctx) + + +def _push_per_thread_mode(context): + ops.get_default_graph()._distribution_strategy_stack.append(context) # pylint: disable=protected-access + + +def _pop_per_thread_mode(): + ops.get_default_graph()._distribution_strategy_stack.pop(-1) # pylint: disable=protected-access + + +class _DefaultReplicaThreadMode(_ThreadMode): + """Type of default value returned by `_get_per_thread_mode()`. + + Used when the thread-local stack is empty. + """ + + def __init__(self): + _ThreadMode.__init__(self, _get_default_distribution_strategy(), None, + _get_default_replica_context()) + + +def _get_per_thread_mode(): + try: + return ops.get_default_graph()._distribution_strategy_stack[-1] # pylint: disable=protected-access + except (AttributeError, IndexError): + return _get_default_replica_mode() + + +# ------------------------------------------------------------------------------ +# Public API for accessing the current thread mode + + +@tf_export("distribute.get_replica_context") +def get_replica_context(): + """Returns the current `tf.distribute.ReplicaContext` or `None`. + + Returns `None` if in a cross-replica context. + + Note that execution: + + 1. starts in the default (single-replica) replica context (this function + will return the default `ReplicaContext` object); + 2. switches to cross-replica context (in which case this will return + `None`) when entering a `with tf.distribute.Strategy.scope():` block; + 3. switches to a (non-default) replica context inside + `extended.call_for_each_replica(fn, ...)`; + 4. if `fn` calls `get_replica_context().merge_call(merge_fn, ...)`, then + inside `merge_fn` you are back in the cross-replica context (and again + this function will return `None`). + + Note that you can also go directly from step 1 to 4 to switch to a + cross-replica context for the default `tf.distribute.Strategy`. You may + also switch from the cross-replica context of 4 to a replica context by + calling `extended.call_for_each_replica()`, jumping back to step 3. + + Most `tf.distribute.Strategy` methods may only be executed in + a cross-replica context, in a replica context you should use the + `ReplicaContext` API instead. + + Returns: + The current `ReplicaContext` object when in a replica context scope, + else `None`. + + Within a particular block, exactly one of these two things will be true: + + * `get_replica_context()` returns non-`None`, or + * `tf.distribute.is_cross_replica_context()` returns True. + """ + return _get_per_thread_mode().replica_context + + +def get_cross_replica_context(): + """Returns the current tf.distribute.Strategy if in a cross-replica context. + + DEPRECATED: Please use `in_cross_replica_context()` and + `get_distribution_strategy()` instead. + + Note that execution: + + 1. starts in the default (single-replica) replica context; + 2. switches to cross-replica context when entering a + `with tf.distribute.Strategy.scope():` block; + 3. switches to a (non-default) replica context inside + `call_for_each_replica(fn, ...)`; + 4. if `fn` calls `get_replica_context()->merge_call(merge_fn, ...)`, then + inside `merge_fn` you are back in the cross-replica context. + + Note that you can also go directly from step 1 to 4 to switch to a + cross-replica context for the default `tf.distribute.Strategy`. You may + also switch from the cross-replica context of 4 to a replica context by + calling `call_for_each_replica()`, jumping back to step 3. + + Most `tf.distribute.Strategy` methods may only be executed in + a cross-replica context. + + Returns: + Returns the current `tf.distribute.Strategy` object in a cross-replica + context, or `None`. + + Exactly one of `get_replica_context()` and `get_cross_replica_context()` + will return `None` in a particular block. + """ + return _get_per_thread_mode().cross_replica_context + + +@tf_export("distribute.in_cross_replica_context") +def in_cross_replica_context(): + """Returns True if in a cross-replica context. + + See `tf.distribute.get_replica_context` for details. + + Returns: + True if in a cross-replica context (`get_replica_context()` returns + `None`), or False if in a replica context (`get_replica_context()` returns + non-`None`). + """ + return _get_per_thread_mode().cross_replica_context is not None + + +@tf_export("distribute.get_strategy") +def get_distribution_strategy(): + """Returns the current `tf.distribute.Strategy` object. + + Typically only used in a cross-replica context: + + ``` + if tf.distribute.in_cross_replica_context(): + strategy = tf.distribute.get_strategy() + ... + ``` + + Returns: + A `tf.distribute.Strategy` object. Inside a + `with distribution_strategy.scope()` block, it returns + `distribution_strategy`, otherwise it returns the default + (single-replica) `tf.distribute.Strategy` object. + """ + return _get_per_thread_mode().distribution_strategy + + +@tf_export("distribute.has_strategy") +def has_distribution_strategy(): + """Return if there is a current non-default `tf.distribute.Strategy`. + + Returns: + True if inside a `with strategy.scope():`. + """ + return get_distribution_strategy() is not _get_default_distribution_strategy() + + +# ------------------------------------------------------------------------------ +# Defaults that are used when no distribution strategy is explicitly created. +# We create them lazily in a function so that we can workaround the circular +# dependency on distribute_lib. See lazy loader at the top of this file. + +_defaults = { + "distribution_strategy": None, + "replica_context": None, + "replica_mode": None +} + + +def _get_default_distribution_strategy(): + if _defaults["distribution_strategy"] is None: + _defaults["distribution_strategy"] = ( + distribute_lib._DefaultDistributionStrategy()) # pylint: disable=protected-access + return _defaults["distribution_strategy"] + + +def _get_default_replica_context(): + if _defaults["replica_context"] is None: + _defaults["replica_context"] = distribute_lib.ReplicaContext( + _get_default_distribution_strategy(), replica_id_in_sync_group=0) + return _defaults["replica_context"] + + +def _get_default_replica_mode(): + if _defaults["replica_mode"] is None: + _defaults["replica_mode"] = _DefaultReplicaThreadMode() + return _defaults["replica_mode"] diff --git a/tensorflow/python/distribute/estimator_training.py b/tensorflow/python/distribute/estimator_training.py index 227b00fb3e..549fa8fb8a 100644 --- a/tensorflow/python/distribute/estimator_training.py +++ b/tensorflow/python/distribute/estimator_training.py @@ -308,7 +308,7 @@ def estimator_train(estimator, train_distributed_fn, hooks): raise ValueError('Only `STANDALONE_CLIENT` mode is supported when you call ' '`estimator.train`') - if estimator._config._train_distribute.between_graph: + if estimator._config._train_distribute.extended.experimental_between_graph: # TODO(yuefengz): remove this limitation once we figure out how to merge # return values from `_worker_fn`s. raise ValueError('`Estimator.train` API is not supported for %s with ' @@ -356,7 +356,7 @@ def estimator_evaluate(estimator, evaluate_distributed_fn, hooks): raise ValueError('Only `STANDALONE_CLIENT` mode is supported when you call ' '`Estimator.train`') - if estimator._config._eval_distribute.between_graph: + if estimator._config._eval_distribute.extended.experimental_between_graph: # TODO(yuefengz): remove this limitation once we figure out how to merge # return values from `_worker_fn`s. raise ValueError('`Estimator.evaluate` API is not supported for %s with ' diff --git a/tensorflow/contrib/distribute/python/input_ops.py b/tensorflow/python/distribute/input_ops.py similarity index 89% rename from tensorflow/contrib/distribute/python/input_ops.py rename to tensorflow/python/distribute/input_ops.py index ac1ccd64b3..2ded209701 100644 --- a/tensorflow/contrib/distribute/python/input_ops.py +++ b/tensorflow/python/distribute/input_ops.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.data.experimental.ops import filter_for_shard_ops from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import readers from tensorflow.python.data.util import nest @@ -41,7 +42,8 @@ def auto_shard_dataset(dataset, num_shards, index): dataset: A `tf.data.Dataset` instance, typically the result of a bunch of dataset transformations. num_shards: A `tf.int64` scalar `tf.Tensor`, representing the number of - shards operating in parallel. Same usage as in `Dataset.shard`. + shards operating in parallel. Same usage as in + `tf.data.experimental.filter_for_shard`. index: A `tf.int64` scalar `tf.Tensor`, representing the worker index. Same usage as in `Dataset.shard`. @@ -74,13 +76,15 @@ def auto_shard_dataset(dataset, num_shards, index): # constructor. Eventually we will change all cases to clone datasets # instead of updating in-place. return dataset._clone( - filenames=dataset._filenames.shard(num_shards, index)) + filenames=dataset._filenames.apply( + filter_for_shard_ops.filter_for_shard(num_shards, index))) elif isinstance(dataset, dataset_ops.RangeDataset): - return dataset.shard(num_shards, index) + return dataset.apply( + filter_for_shard_ops.filter_for_shard(num_shards, index)) elif hasattr(dataset, "_map_func"): # TODO(priyag): Make this check more robust by enforcing some common # property on all map/flatmap/interleave datasets. - map_func_def = dataset._map_func.definition + map_func_def = dataset._map_func.function.definition for node in map_func_def.node_def: if node.op in _READER_DATASET_OPS: found_reader_op = True @@ -102,6 +106,11 @@ def auto_shard_dataset(dataset, num_shards, index): dataset._input_dataset, found_reader_op) return dataset + if isinstance(dataset, dataset_ops.DatasetV1Adapter): + dataset._dataset = _auto_shard_impl( + dataset._dataset, found_reader_op) + return dataset + # TODO(priyag): Make _input_dataset(s) a common property of all datasets to # make this check more robust. if hasattr(dataset, "_input_dataset"): @@ -137,6 +146,7 @@ def auto_shard_dataset(dataset, num_shards, index): # TODO(priyag): This will shard the filenames before any shuffling of the # filename dataset. It might be desirable to shard after shuffling # filenames? If so, how do we achieve that? - return dataset.shard(num_shards, index) + return dataset.apply( + filter_for_shard_ops.filter_for_shard(num_shards, index)) return _auto_shard_impl(dataset=dataset, found_reader_op=False) diff --git a/tensorflow/contrib/distribute/python/input_ops_test.py b/tensorflow/python/distribute/input_ops_test.py similarity index 89% rename from tensorflow/contrib/distribute/python/input_ops_test.py rename to tensorflow/python/distribute/input_ops_test.py index 559de97bb1..dcf946ba47 100644 --- a/tensorflow/contrib/distribute/python/input_ops_test.py +++ b/tensorflow/python/distribute/input_ops_test.py @@ -20,10 +20,11 @@ from __future__ import print_function import os -from tensorflow.contrib.distribute.python import input_ops from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import readers +from tensorflow.python.distribute import input_ops from tensorflow.python.framework import errors +from tensorflow.python.framework import test_util from tensorflow.python.lib.io import python_io from tensorflow.python.platform import test from tensorflow.python.util import compat @@ -92,10 +93,11 @@ class AutoShardDatasetTest(test.TestCase): with self.cached_session() as sess: for f in range(self._shard_index, self._num_files, self._num_shards): for r in range(self._num_records): - self.assertAllEqual(record_fn(r, f), sess.run(next_element)) + self.assertAllEqual(record_fn(r, f), self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testTFRecordDataset(self): dataset = readers.TFRecordDataset(self._createTFRecordFiles()) dataset = input_ops.auto_shard_dataset( @@ -103,6 +105,7 @@ class AutoShardDatasetTest(test.TestCase): self._verifySimpleShardingOutput(dataset, self._record) + @test_util.run_deprecated_v1 def testFlatMap(self): dataset = dataset_ops.Dataset.from_tensor_slices( self._createTFRecordFiles()) @@ -112,6 +115,7 @@ class AutoShardDatasetTest(test.TestCase): self._verifySimpleShardingOutput(dataset, self._record) + @test_util.run_deprecated_v1 def testInterleave(self): dataset = dataset_ops.Dataset.from_tensor_slices( self._createTFRecordFiles()) @@ -124,9 +128,10 @@ class AutoShardDatasetTest(test.TestCase): # contain records in order of files. self._verifySimpleShardingOutput(dataset, self._record) + @test_util.run_deprecated_v1 def testListfiles(self): filenames = self._createTFRecordFiles() - file_pattern = filenames[0].rsplit("/", 1)[0] + "/tf_record.*.txt" + file_pattern = filenames[0].rsplit(os.sep, 1)[0] + "/tf_record.*.txt" dataset = dataset_ops.Dataset.list_files(file_pattern, shuffle=False) dataset = dataset.flat_map(readers.TFRecordDataset) dataset = input_ops.auto_shard_dataset( @@ -138,12 +143,13 @@ class AutoShardDatasetTest(test.TestCase): actual, expected = [], [] for f in range(self._shard_index, self._num_files, self._num_shards): for r in range(self._num_records): - actual.append(sess.run(next_element)) + actual.append(self.evaluate(next_element)) expected.append(self._record(r, f)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) self.assertAllEqual(expected, actual) + @test_util.run_deprecated_v1 def testComplexPipeline(self): # Setup a complex input pipeline. batch_size = 2 @@ -171,9 +177,9 @@ class AutoShardDatasetTest(test.TestCase): num_iterations = (self._num_files * self._num_records * num_epochs) // ( self._num_shards * batch_size) for _ in range(num_iterations): - actual.extend(sess.run(next_element)) + actual.extend(self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) expected = [] for f in range(0, self._num_files, self._num_shards): @@ -183,6 +189,7 @@ class AutoShardDatasetTest(test.TestCase): self.assertAllEqual(sorted(expected), sorted(actual)) + @test_util.run_deprecated_v1 def testZip(self): dataset1 = readers.TFRecordDataset(self._createTFRecordFiles()) dataset2 = readers.TextLineDataset(self._createTextFiles()) @@ -193,6 +200,7 @@ class AutoShardDatasetTest(test.TestCase): record_fn = lambda r, f: (self._record(r, f), self._text_line(r, f)) self._verifySimpleShardingOutput(dataset, record_fn) + @test_util.run_deprecated_v1 def testConcat(self): dataset1 = readers.TFRecordDataset(self._createTFRecordFiles()) dataset2 = readers.TextLineDataset(self._createTextFiles()) @@ -205,13 +213,15 @@ class AutoShardDatasetTest(test.TestCase): with self.cached_session() as sess: for f in range(self._shard_index, self._num_files, self._num_shards): for r in range(self._num_records): - self.assertAllEqual(self._record(r, f), sess.run(next_element)) + self.assertAllEqual(self._record(r, f), self.evaluate(next_element)) for f in range(self._shard_index, self._num_files, self._num_shards): for r in range(self._num_records): - self.assertAllEqual(self._text_line(r, f), sess.run(next_element)) + self.assertAllEqual( + self._text_line(r, f), self.evaluate(next_element)) with self.assertRaises(errors.OutOfRangeError): - sess.run(next_element) + self.evaluate(next_element) + @test_util.run_deprecated_v1 def testTextLineReader(self): dataset = readers.TextLineDataset(self._createTextFiles()) dataset = input_ops.auto_shard_dataset( @@ -219,6 +229,7 @@ class AutoShardDatasetTest(test.TestCase): self._verifySimpleShardingOutput(dataset, self._text_line) + @test_util.run_deprecated_v1 def testTextLineReaderWithFlatMap(self): dataset = dataset_ops.Dataset.from_tensor_slices(self._createTextFiles()) dataset = dataset.flat_map(readers.TextLineDataset) @@ -227,6 +238,7 @@ class AutoShardDatasetTest(test.TestCase): self._verifySimpleShardingOutput(dataset, self._text_line) + @test_util.run_deprecated_v1 def testFixedLengthReader(self): dataset = readers.FixedLengthRecordDataset( self._createFixedLengthRecordFiles(), self._record_bytes) @@ -235,6 +247,7 @@ class AutoShardDatasetTest(test.TestCase): self._verifySimpleShardingOutput(dataset, self._fixed_length_record) + @test_util.run_deprecated_v1 def testFixedLengthReaderWithFlatMap(self): dataset = dataset_ops.Dataset.from_tensor_slices( self._createFixedLengthRecordFiles()) diff --git a/tensorflow/python/distribute/mirrored_strategy.py b/tensorflow/python/distribute/mirrored_strategy.py new file mode 100644 index 0000000000..0775920a7d --- /dev/null +++ b/tensorflow/python/distribute/mirrored_strategy.py @@ -0,0 +1,908 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Class MirroredStrategy implementing DistributionStrategy.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import contextlib +import copy +import functools +import threading + +from tensorflow.python import pywrap_tensorflow +from tensorflow.python.distribute import cross_device_ops as cross_device_ops_lib +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import multi_worker_util +from tensorflow.python.distribute import reduce_util +from tensorflow.python.distribute import shared_variable_creator +from tensorflow.python.distribute import values +from tensorflow.python.eager import context +from tensorflow.python.eager import tape +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import device as tf_device +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import variable_scope +from tensorflow.python.training import coordinator +from tensorflow.python.util import nest + + +# TODO(josh11b): Replace asserts in this file with if ...: raise ... + + +@contextlib.contextmanager +def _enter_graph(g): + if context.executing_eagerly(): + with g.as_default(), context.eager_mode(): + yield + else: + with g.as_default(): + yield + + +def _cpu_device(device): + cpu_device = tf_device.DeviceSpec.from_string(device) + cpu_device.merge_from(tf_device.DeviceSpec(device_type="CPU", device_index=0)) + return cpu_device.to_string() + + +class _RequestedStop(Exception): # pylint: disable=g-bad-exception-name + pass + + +# _call_for_each_replica and _reduce_non_distributed_value are not members of +# MirroredStrategy so that they are generally not allowed to use anything +# specific to MirroredStrategy and thus can be shared with other distribution +# strategies. + + +# TODO(yuefengz): maybe create a common class for those who need to call this +# _call_for_each_replica. +def _call_for_each_replica(distribution, fn, args, kwargs): + """Run `fn` in separate threads, once per replica/worker device. + + Args: + distribution: the DistributionStrategy object. + fn: function to run (will be run once per device, each in its own thread). + args: positional arguments for `fn` + kwargs: keyword arguments for `fn`. + + Returns: + Merged return value of `fn` across all replicas. + + Raises: + RuntimeError: If fn() calls get_replica_context().merge_call() a different + number of times from the available devices. + """ + # TODO(josh11b): Add this option once we add synchronization to variable + # creation. Until then, this is pretty unsafe to use. + run_concurrently = False + if not context.executing_eagerly(): + # Needed for per-thread device, etc. contexts in graph mode. + ops.get_default_graph().switch_to_thread_local() + + coord = coordinator.Coordinator(clean_stop_exception_types=(_RequestedStop,)) + + shared_variable_store = {} + + # TODO(isaprykin): Create these threads once instead of during every run() + # call. + threads = [] + for index, d in enumerate(distribution.extended.worker_devices): + variable_creator_fn = shared_variable_creator.make_fn( + shared_variable_store, index) + t = MirroredExtended._MirroredReplicaThread( # pylint: disable=protected-access + distribution, coord, d, variable_creator_fn, fn, + *values.select_device(d, args), **values.select_device(d, kwargs)) + threads.append(t) + + for t in threads: + t.start() + + # When `fn` starts `should_run` event is set on _MirroredReplicaThread + # (`MRT`) threads. The execution waits until + # `MRT.has_paused` is set, which indicates that either `fn` is + # complete or a `get_replica_context().merge_call()` is called. If `fn` is + # complete, then `MRT.done` is set to True. Otherwise, arguments + # of `get_replica_context().merge_call` from all paused threads are grouped + # and the `merge_fn` is performed. Results of the + # `get_replica_context().merge_call` are then set to `MRT.merge_result`. + # Each such `get_replica_context().merge_call` call returns the + # `MRT.merge_result` for that thread when `MRT.should_run` event + # is reset again. Execution of `fn` resumes. + + try: + with coord.stop_on_exception(): + all_done = False + while not all_done and not coord.should_stop(): + done = [] + if run_concurrently: + for t in threads: + t.should_run.set() + for t in threads: + t.has_paused.wait() + t.has_paused.clear() + if coord.should_stop(): + return None + done.append(t.done) + else: + for t in threads: + t.should_run.set() + t.has_paused.wait() + t.has_paused.clear() + if coord.should_stop(): + return None + done.append(t.done) + if coord.should_stop(): + return None + all_done = all(done) + if not all_done: + if any(done): + raise RuntimeError("Some replicas made a different number of " + "replica_context().merge_call() calls.") + # get_replica_context().merge_call() case + merge_args = values.regroup({t.device: t.merge_args for t in threads}) + merge_kwargs = values.regroup( + {t.device: t.merge_kwargs for t in threads}) + # We capture the name_scope of the MRT when we call merge_fn + # to ensure that if we have opened a name scope in the MRT, + # it will be respected when executing the merge function. We only + # capture the name_scope from the first MRT and assume it is + # the same for all other MRTs. + mtt_captured_name_scope = threads[0].captured_name_scope + with ops.name_scope(mtt_captured_name_scope): + merge_result = threads[0].merge_fn(distribution, *merge_args, + **merge_kwargs) + for t in threads: + t.merge_result = values.select_device(t.device, merge_result) + finally: + for t in threads: + t.should_run.set() + coord.join(threads) + + return values.regroup({t.device: t.main_result for t in threads}) + + +def _reduce_non_distributed_value(extended, reduce_op, value, destinations): + """Reduce a non-DistributedValue `value` to `destinations`.""" + if isinstance(value, values.DistributedValues): + raise ValueError("You are passing a `DistributedValue` to " + "`_reduce_non_distributed_value`, which is not allowed.") + + # If the same value is present on all replicas then the PerReplica value will + # be a single value. We also handle the case when `value` is a single value + # and equal to 0. + if value == 0: + return 0 + # If there is only a single value and the reduce op is MEAN, + # that value should be on all destinations. + if reduce_op == reduce_util.ReduceOp.MEAN: + return value + + cross_device_ops_lib.validate_destinations(destinations) + # We do not support a reduce op of SUM if the value is the same across + # all replicas. We call this as part of assign functions for MirroredVariables + # and summing up identical values across replicas is not clearly defined. + if (len(extended.worker_devices) != 1 or + not cross_device_ops_lib.check_destinations(destinations)): + raise ValueError("A non-DistributedValues value %s cannot be reduced with " + "the given reduce op %s." % (value, reduce_op)) + # TODO(anjalisridhar): Moves these methods to a device utility file? + devices = cross_device_ops_lib.get_devices_from(destinations) + if len(devices) == 1: + with ops.device(devices[0]): + return array_ops.identity(value) + else: + value_updates = {} + for d in devices: + with ops.device(d): + value_updates[d] = array_ops.identity(value) + return values.Mirrored(value_updates) + + +def _create_mirrored_variable(devices, real_mirrored_creator, *args, **kwargs): # pylint: disable=g-missing-docstring + # Figure out what collections this variable should be added to. + # We'll add the MirroredVariable to those collections instead. + collections = kwargs.pop("collections", None) + if collections is None: + collections = [ops.GraphKeys.GLOBAL_VARIABLES] + kwargs["collections"] = [] + + # Get synchronization value + synchronization = kwargs.get("synchronization", + variable_scope.VariableSynchronization.ON_WRITE) + if synchronization == variable_scope.VariableSynchronization.NONE: + raise ValueError("`NONE` variable synchronization mode is not " + "supported with `Mirrored` distribution strategy. Please" + " change the `synchronization` for variable: " + + kwargs["name"]) + elif synchronization == variable_scope.VariableSynchronization.ON_READ: + # Variables that are to be synced on read are replica local. + is_replica_local = True + kwargs["trainable"] = False + elif (synchronization == variable_scope.VariableSynchronization.ON_WRITE or + synchronization == variable_scope.VariableSynchronization.AUTO): + # `AUTO` synchronization for `MirroredStrategy` is `ON_WRITE`. + is_replica_local = False + else: + raise ValueError("Invalid variable synchronization mode: " + + synchronization + " for variable: " + kwargs["name"]) + + # Get aggregation value + aggregation = kwargs.pop("aggregation", + variable_scope.VariableAggregation.NONE) + if aggregation not in ( + variable_scope.VariableAggregation.NONE, + variable_scope.VariableAggregation.SUM, + variable_scope.VariableAggregation.MEAN, + variable_scope.VariableAggregation.ONLY_FIRST_REPLICA + ): + raise ValueError("Invalid variable aggregation mode: " + aggregation + + " for variable: " + kwargs["name"]) + + # Ignore user-specified caching device, not needed for mirrored variables. + kwargs.pop("caching_device", None) + + # TODO(josh11b,apassos): It would be better if variable initialization + # was never recorded on the tape instead of having to do this manually + # here. + with tape.stop_recording(): + index = real_mirrored_creator(devices, *args, **kwargs) + + if is_replica_local: + result = values.ReplicaLocalVariable( + index, index[devices[0]], aggregation) + else: + result = values.MirroredVariable(index, index[devices[0]], aggregation) + + # Add the wrapped variable to the requested collections. + # The handling of eager mode and the global step matches + # ResourceVariable._init_from_args(). + if not context.executing_eagerly(): + g = ops.get_default_graph() + # If "trainable" is True, next_creator() will add the member variables + # to the TRAINABLE_VARIABLES collection, so we manually remove + # them and replace with the MirroredVariable. We can't set + # "trainable" to False for next_creator() since that causes functions + # like implicit_gradients to skip those variables. + if kwargs.get("trainable", True): + collections.append(ops.GraphKeys.TRAINABLE_VARIABLES) + l = g.get_collection_ref(ops.GraphKeys.TRAINABLE_VARIABLES) + for v in index.values(): + if v in l: + l.remove(v) + g.add_to_collections(collections, result) + elif ops.GraphKeys.GLOBAL_STEP in collections: + ops.add_to_collections(ops.GraphKeys.GLOBAL_STEP, result) + + return result + + +def _is_device_list_local(devices): + """Checks whether the devices list is for local or multi-worker. + + Args: + devices: a list of device strings, either local for remote devices. + + Returns: + a boolean indicating whether these device strings are for local or for + remote. + + Raises: + ValueError: if device strings are not consistent. + """ + all_local = None + for d in devices: + d_spec = tf_device.DeviceSpec().parse_from_string(d) + is_local = d_spec.job in (None, "localhost") + + if all_local is None: # Determine all_local from first device. + all_local = is_local + + if all_local: + if not is_local: + raise ValueError("Local device string cannot have job specified other " + "than 'localhost'") + else: + if is_local: + raise ValueError("Remote device string must have job specified.") + if d_spec.task is None: + raise ValueError("Remote device string must have task specified.") + return all_local + + +def _cluster_spec_to_device_list(cluster_spec, num_gpus_per_worker): + """Returns a device list given a cluster spec.""" + cluster_spec = multi_worker_util.normalize_cluster_spec(cluster_spec) + devices = [] + for task_type in ("chief", "worker"): + for task_id in range(len(cluster_spec.as_dict().get(task_type, []))): + if num_gpus_per_worker is 0: + devices.append("/job:%s/task:%d" % (task_type, task_id)) + else: + devices.extend([ + "/job:%s/task:%d/device:GPU:%i" % (task_type, task_id, gpu_id) + for gpu_id in range(num_gpus_per_worker) + ]) + return devices + + +def _group_device_list(devices): + """Groups the devices list by task_type and task_id. + + Args: + devices: a list of device strings for remote devices. + + Returns: + a dict of list of device strings mapping from task_type to a list of devices + for the task_type in the asceding order of task_id. + """ + assert not _is_device_list_local(devices) + device_dict = {} + + for d in devices: + d_spec = tf_device.DeviceSpec().parse_from_string(d) + + # Create an entry for the task_type. + if d_spec.job not in device_dict: + device_dict[d_spec.job] = [] + + # Fill the device list for task_type until it covers the task_id. + while len(device_dict[d_spec.job]) <= d_spec.task: + device_dict[d_spec.job].append([]) + + device_dict[d_spec.job][d_spec.task].append(d) + + return device_dict + + +def _infer_num_gpus_per_worker(devices): + """Infers the number of GPUs on each worker. + + Currently to make multi-worker cross device ops work, we need all workers to + have the same number of GPUs. + + Args: + devices: a list of device strings, can be either local devices or remote + devices. + + Returns: + number of GPUs per worker. + + Raises: + ValueError if workers have different number of GPUs or GPU indices are not + consecutive and starting from 0. + """ + if _is_device_list_local(devices): + return len([d for d in devices if "GPU" in d.upper()]) + else: + device_dict = _group_device_list(devices) + num_gpus = None + for _, devices_in_task in device_dict.items(): + for device_in_task in devices_in_task: + if num_gpus is None: + num_gpus = len([d for d in device_in_task if "GPU" in d.upper()]) + + # Verify other workers have the same number of GPUs. + elif ( + num_gpus != len([d for d in device_in_task if "GPU" in d.upper()])): + raise ValueError("All workers should have the same number of GPUs.") + + for d in device_in_task: + d_spec = tf_device.DeviceSpec().parse_from_string(d) + if (d_spec.device_type.upper() == "GPU" and + d_spec.device_index >= num_gpus): + raise ValueError("Device_index on a worker should be consecutive " + "and start from 0.") + return num_gpus + + +def all_local_devices(num_gpus=None): + if num_gpus is None: + num_gpus = context.num_gpus() + return (tuple("/device:GPU:%d" % i for i in range(num_gpus)) or + ("/device:CPU:0",)) + + +class MirroredStrategy(distribute_lib.DistributionStrategy): + """Mirrors vars to distribute across multiple devices and machines. + + This strategy uses one replica per device and sync replication for its + multi-GPU version. + + The multi-worker version will be added in the fture. + + Args: + devices: a list of device strings. + cross_device_ops: optional, a descedant of `CrossDeviceOps`. If this is not + set, nccl will be use by default. + """ + + def __init__(self, devices=None, cross_device_ops=None): + extended = MirroredExtended( + self, devices=devices, cross_device_ops=cross_device_ops) + super(MirroredStrategy, self).__init__(extended) + + +class MirroredExtended(distribute_lib.DistributionStrategyExtended): + """Implementation of MirroredStrategy.""" + + def __init__(self, container_strategy, devices=None, cross_device_ops=None): + super(MirroredExtended, self).__init__(container_strategy) + if devices is None: + devices = all_local_devices() + if not devices: + raise ValueError("Got an empty `devices` list. Please make sure the " + "`devices` you pass in is not empty.") + self._cross_device_ops = cross_device_ops + self._initialize_strategy(devices) + + def _initialize_strategy(self, devices): + # The _initialize_strategy method is intended to be used by distribute + # coordinator as well. + if _is_device_list_local(devices): + self._initialize_local(devices) + else: + self._initialize_multi_worker(devices) + + def _initialize_local(self, devices): + """Initializes the object for local training.""" + self._local_mode = True + assert devices, "Must specify at least one device." + assert len(set(devices)) == len(devices), ( + "No duplicates allowed in `devices` argument.") + # TODO(josh11b): Require at least 2 devices? + self._devices = [device_util.resolve(d) for d in devices] + self._canonical_device_set = set(self._devices) + self._device_index = values.PerReplica( + {d: i for i, d in enumerate(devices)}) + + self._inferred_cross_device_ops = cross_device_ops_lib.choose_the_best( + devices) + + def _initialize_multi_worker(self, devices): + """Initializes the object for multi-worker training.""" + self._local_mode = False + + assert devices, "Must specify at least one device." + assert len(set(devices)) == len(devices), ( + "No duplicates allowed in `devices` argument.") + # TODO(josh11b): Require at least 2 devices? + self._devices = [device_util.resolve(d) for d in devices] + self._canonical_device_set = set(self._devices) + self._device_index = values.PerReplica( + {d: i for i, d in enumerate(devices)}) + + device_dict = _group_device_list(devices) + self._workers = [] + self._worker_devices = [] + for job in ["chief", "worker"]: + for task in range(len(device_dict.get(job, []))): + worker = "/job:%s/task:%d" % (job, task) + self._workers.append(worker) + self._worker_devices.append((worker, device_dict[job][task])) + + # Setting `_default_device` will add a device scope in the + # distribution.scope. We set the default device to the first worker. When + # users specify device under distribution.scope by + # with tf.device("/cpu:0"): + # ... + # their ops will end up on the cpu device of its first worker, e.g. + # "/job:worker/task:0/device:CPU:0". Note this is not used in replica mode. + self._default_device = self._workers[0] + + self._inferred_cross_device_ops = cross_device_ops_lib.MultiWorkerAllReduce( + self._workers, _infer_num_gpus_per_worker(self._devices)) + + def _create_variable(self, next_creator, *args, **kwargs): + """Create a mirrored variable. See `DistributionStrategy.scope`.""" + colocate_with = kwargs.pop("colocate_with", None) + devices = self._get_devices_from(colocate_with) + + def _real_mirrored_creator(devices, *args, **kwargs): # pylint: disable=g-missing-docstring + index = {} + for i, d in enumerate(devices): + with ops.init_scope(), ops.device(d): + if i > 0: + # Give replicas meaningful distinct names: + var0name = index[devices[0]].name.split(":")[0] + # We append a / to variable names created on replicas with id > 0 to + # ensure that we ignore the name scope and instead use the given + # name as the absolute name of the variable. + kwargs["name"] = "%s/replica_%d/" % (var0name, i) + # Initialize replicas with the same value: + def initial_value_fn(device=d): + if context.executing_eagerly(): + init_value = index[devices[0]].value() + return array_ops.identity(init_value) + else: + with ops.device(device): + init_value = index[devices[0]].initial_value + return array_ops.identity(init_value) + kwargs["initial_value"] = initial_value_fn + with context.context().device_policy(context.DEVICE_PLACEMENT_SILENT): + # Don't record operations (e.g. other variable reads) during + # variable creation. + with tape.stop_recording(): + v = next_creator(*args, **kwargs) + assert not isinstance(v, values.DistributedVariable) + index[d] = v + return index + + return _create_mirrored_variable(devices, _real_mirrored_creator, *args, + **kwargs) + + def _distribute_dataset(self, dataset_fn): + if self._local_mode: + return values.PerReplicaDataset( + self._call_dataset_fn(dataset_fn), self._devices) + else: + return values.MultiWorkerDataset( + functools.partial(self._call_dataset_fn, dataset_fn), + self._worker_devices, + auto_shard=False) + + def _make_dataset_iterator(self, dataset): + if self._local_mode: + worker = device_util.canonicalize("/device:CPU:0") + worker_device_pairs = [(worker, self._devices)] + else: + worker_device_pairs = self._worker_devices + + return values.DatasetIterator(dataset, worker_device_pairs, + self._num_replicas_in_sync) + + def _make_input_fn_iterator( + self, + input_fn, + replication_mode=distribute_lib.InputReplicationMode.PER_WORKER): + input_contexts = [] + if self._local_mode: + num_workers = 1 + worker = device_util.canonicalize("/device:CPU:0") + worker_device_pairs = [(worker, self._devices)] + else: + num_workers = len(self._worker_devices) + worker_device_pairs = self._worker_devices + + for i in range(num_workers): + input_contexts.append(distribute_lib.InputContext( + num_input_pipelines=num_workers, + input_pipeline_id=i, + num_replicas_in_sync=self._num_replicas_in_sync)) + return values.InputFunctionIterator( + input_fn, worker_device_pairs, input_contexts) + + # TODO(priyag): Deal with OutOfRange errors once b/111349762 is fixed. + def _experimental_run_steps_on_iterator(self, fn, iterator, iterations, + initial_loop_values=None): + if initial_loop_values is None: + initial_loop_values = {} + initial_loop_values = nest.flatten(initial_loop_values) + + ctx = values.MultiStepContext() + def body(i, *args): + """A wrapper around `fn` to create the while loop body.""" + del args + fn_inputs = iterator.get_next() + if not isinstance(fn_inputs, tuple): + fn_inputs = (fn_inputs,) + fn_result = fn(ctx, fn_inputs) + for (name, output) in ctx.last_step_outputs.items(): + # Convert all outputs to tensors, potentially from `DistributedValues`. + ctx.last_step_outputs[name] = self._unwrap(output) + flat_last_step_outputs = nest.flatten(ctx.last_step_outputs) + with ops.control_dependencies([fn_result]): + return [i + 1] + flat_last_step_outputs + + # We capture the control_flow_context at this point, before we run `fn` + # inside a while_loop. This is useful in cases where we might need to exit + # these contexts and get back to the outer context to do some things, for + # e.g. create an op which should be evaluated only once at the end of the + # loop on the host. One such usage is in creating metrics' value op. + self._outer_control_flow_context = ( + ops.get_default_graph()._get_control_flow_context()) # pylint: disable=protected-access + + cond = lambda i, *args: i < iterations + i = constant_op.constant(0) + loop_result = control_flow_ops.while_loop( + cond, body, [i] + initial_loop_values, name="", + parallel_iterations=1, back_prop=False, swap_memory=False, + return_same_structure=True) + del self._outer_control_flow_context + + ctx.run_op = control_flow_ops.group(loop_result) + + # Convert the last_step_outputs from a list to the original dict structure + # of last_step_outputs. + last_step_tensor_outputs = loop_result[1:] + last_step_tensor_outputs_dict = nest.pack_sequence_as( + ctx.last_step_outputs, last_step_tensor_outputs) + + for name, reduce_op in ctx._last_step_outputs_reduce_ops.items(): # pylint: disable=protected-access + output = last_step_tensor_outputs_dict[name] + # For outputs that have already been reduced, wrap them in a Mirrored + # container, else in a PerReplica container. + if reduce_op is None: + last_step_tensor_outputs_dict[name] = values.regroup( + {d: t for d, t in zip(self._devices, output)}, values.PerReplica) + else: + assert len(output) == 1 + last_step_tensor_outputs_dict[name] = output[0] + + ctx._set_last_step_outputs(last_step_tensor_outputs_dict) # pylint: disable=protected-access + return ctx + + def _broadcast_to(self, tensor, destinations): + # This is both a fast path for Python constants, and a way to delay + # converting Python values to a tensor until we know what type it + # should be converted to. Otherwise we have trouble with: + # global_step.assign_add(1) + # since the `1` gets broadcast as an int32 but global_step is int64. + if isinstance(tensor, (float, int)): + return tensor + # TODO(josh11b): In eager mode, use one thread per device, or async mode. + return self._get_cross_device_ops().broadcast( + tensor, destinations or self._devices) + + def _call_for_each_replica(self, fn, args, kwargs): + return _call_for_each_replica(self._container_strategy(), fn, args, kwargs) + + def _configure(self, + session_config=None, + cluster_spec=None, + task_type=None, + task_id=None): + del task_type, task_id + + if session_config: + session_config.CopyFrom(self._update_config_proto(session_config)) + + if cluster_spec: + # TODO(yuefengz): remove the following code once cluster_resolver is + # added. + num_gpus_per_worker = _infer_num_gpus_per_worker(self._devices) + multi_worker_devices = _cluster_spec_to_device_list( + cluster_spec, num_gpus_per_worker) + self._initialize_multi_worker(multi_worker_devices) + + def _update_config_proto(self, config_proto): + updated_config = copy.deepcopy(config_proto) + updated_config.isolate_session_state = True + return updated_config + + def _get_cross_device_ops(self): + return self._cross_device_ops or self._inferred_cross_device_ops + + def _reduce_to(self, reduce_op, value, destinations): + assert not isinstance(value, values.Mirrored) + if not isinstance(value, values.DistributedValues): + # This function handles reducing values that are not PerReplica or + # Mirrored values. For example, the same value could be present on all + # replicas in which case `value` would be a single value or value could + # be 0. + return _reduce_non_distributed_value(self, reduce_op, value, + destinations) + return self._get_cross_device_ops().reduce( + reduce_op, value, destinations=destinations) + + def _batch_reduce_to(self, reduce_op, value_destination_pairs): + return self._get_cross_device_ops().batch_reduce(reduce_op, + value_destination_pairs) + + def _update(self, var, fn, args, kwargs, group): + # TODO(josh11b): In eager mode, use one thread per device. + assert isinstance(var, values.DistributedVariable) + updates = {} + for d, v in var._index.items(): # pylint: disable=protected-access + name = "update_%d" % self._device_index.get(d) + with ops.device(d), distribute_lib.UpdateContext(d), ops.name_scope(name): + # If args and kwargs are not mirrored, the value is returned as is. + updates[d] = fn(v, + *values.select_device_mirrored(d, args), + **values.select_device_mirrored(d, kwargs)) + return values.update_regroup(self, updates, group) + + def _update_non_slot(self, colocate_with, fn, args, kwargs, group): + assert isinstance(colocate_with, list) + # TODO(josh11b): In eager mode, use one thread per device. + updates = {} + for d in colocate_with: + name = "update_%d" % self._device_index.get(d) + with ops.device(d), distribute_lib.UpdateContext(d), ops.name_scope(name): + updates[d] = fn(*values.select_device_mirrored(d, args), + **values.select_device_mirrored(d, kwargs)) + return values.update_regroup(self, updates, group) + + def read_var(self, replica_local_var): + """Read the aggregate value of a replica-local variable.""" + if isinstance(replica_local_var, values.ReplicaLocalVariable): + return replica_local_var._get_cross_replica() # pylint: disable=protected-access + assert isinstance(replica_local_var, values.Mirrored) + return array_ops.identity(replica_local_var.get()) + + def _unwrap(self, val): + if isinstance(val, values.DistributedValues): + # Return in a deterministic order. + if set(val.devices) == self._canonical_device_set: + return [val.get(device=d) for d in self._devices] + return [val.get(device=d) for d in sorted(val.devices)] + return [val] + + def value_container(self, val): + return values.value_container(val) + + @property + def _num_replicas_in_sync(self): + return len(self._devices) + + @property + def worker_devices(self): + # Make a copy to prevent users from accidentally mutating our copy. + return list(self._devices) + + @property + def parameter_devices(self): + return list(self._devices) + + @property + def experimental_between_graph(self): + return False + + @property + def experimental_should_init(self): + return True + + @property + def should_checkpoint(self): + return True + + @property + def should_save_summary(self): + return True + + def non_slot_devices(self, var_list): + del var_list + return list(self._devices) + + def _get_devices_from(self, colocate_with=None): + if colocate_with is None: + return self._devices + else: + return cross_device_ops_lib.get_devices_from(colocate_with) + + # TODO(priyag): Delete this once all strategies use global batch size. + @property + def _global_batch_size(self): + return True + + class _MirroredReplicaThread(threading.Thread): + """A thread that runs() a function on a device.""" + + def __init__(self, dist, coord, device, variable_creator_fn, fn, *args, + **kwargs): + super(MirroredExtended._MirroredReplicaThread, self).__init__() # pylint: disable=protected-access + self.coord = coord + self.distribution = dist + self.device = device + self.replica_id = dist.extended.worker_devices.index(device) + self.variable_creator_fn = variable_creator_fn + # State needed to run and return the results of `fn`. + self.main_fn = fn + self.main_args = args + self.main_kwargs = kwargs + self.main_result = None + self.done = False + # State needed to run the next merge_call() (if any) requested via + # ReplicaContext. + self.merge_fn = None + self.merge_args = None + self.merge_kwargs = None + self.merge_result = None + self.captured_name_scope = None + # We use a thread.Event for the main thread to signal when this + # thread should start running (`should_run`), and another for + # this thread to transfer control back to the main thread + # (`has_paused`, either when it gets to a + # `get_replica_context().merge_call` or when `fn` returns). In + # either case the event starts cleared, is signaled by calling + # set(). The receiving thread waits for the signal by calling + # wait() and then immediately clearing the event using clear(). + self.should_run = threading.Event() + self.has_paused = threading.Event() + # These fields have to do with inheriting various contexts from the + # parent thread: + # pylint: disable=protected-access + self.context_mode = context.context()._eager_context.mode + if not context.context()._context_handle: + context.context()._initialize_handle_and_devices() + self.context_device_policy = ( + pywrap_tensorflow.TFE_ContextGetDevicePlacementPolicy( + context.context()._context_handle)) + self.graph = ops.get_default_graph() + self._variable_creator_stack = self.graph._variable_creator_stack[:] + self._captured_var_scope = variable_scope.get_variable_scope() + # Adding a "/" at end lets us re-enter this scope later. + self._name_scope = self.graph.get_name_scope() + if self._name_scope: + self._name_scope += "/" + if self.replica_id > 0: + if not self._name_scope: + self._name_scope = "" + self._name_scope += "replica_%d/" % self.replica_id + + def run(self): + # pylint: disable=protected-access + self.graph._variable_creator_stack = self._variable_creator_stack + self.should_run.wait() + self.should_run.clear() + try: + if self.coord.should_stop(): + return + with self.coord.stop_on_exception(), \ + context.context()._mode(self.context_mode), \ + context.context().device_policy(self.context_device_policy), \ + _enter_graph(self.graph), \ + MirroredReplicaContext(self.distribution, constant_op.constant( + self.replica_id, dtypes.int32)), \ + ops.device(self.device), \ + ops.name_scope(self._name_scope), \ + variable_scope.variable_scope( + self._captured_var_scope, reuse=self.replica_id > 0), \ + variable_scope.variable_creator_scope(self.variable_creator_fn): + self.main_result = self.main_fn(*self.main_args, **self.main_kwargs) + self.done = True + finally: + self.has_paused.set() + + +class MirroredReplicaContext(distribute_lib.ReplicaContext): + """ReplicaContext used in MirroredStrategy.call_for_each_replica(). + + Opened in `_MirroredReplicaThread`, to allow the user to invoke + `MirroredStrategy`'s specific implementation of `merge_call()`, + which works by delegating the function and its arguments to + the main thread (the one that invoked + `MirroredStrategy.call_for_each_replica()`). + """ + + def _merge_call(self, fn, args, kwargs): + """Delegate to the main thread to actually perform merge_call().""" + t = threading.current_thread() # a _MirroredReplicaThread + t.merge_fn = fn + t.merge_args = args + t.merge_kwargs = kwargs + t.captured_name_scope = t.graph.get_name_scope() + # Adding a "/" at end lets us re-enter this scope later. + if t.captured_name_scope: + t.captured_name_scope += "/" + t.has_paused.set() + t.should_run.wait() + t.should_run.clear() + if t.coord.should_stop(): + raise _RequestedStop() + return t.merge_result + + @property + def devices(self): + distribute_lib.require_replica_context(self) + replica_id = tensor_util.constant_value(self._replica_id_in_sync_group) + return [self._distribution_strategy.extended.worker_devices[replica_id]] diff --git a/tensorflow/python/distribute/multi_worker_util.py b/tensorflow/python/distribute/multi_worker_util.py index 360733eff6..2986a6726a 100644 --- a/tensorflow/python/distribute/multi_worker_util.py +++ b/tensorflow/python/distribute/multi_worker_util.py @@ -45,6 +45,33 @@ def normalize_cluster_spec(cluster_spec): return cluster_spec +# TODO(yuefengz): add more validations. +def _validate_cluster_spec(cluster_spec, task_type, task_id): + """Validates `cluster_spec`. + + It checks + 1) whether there is such a task type as `task_type` in the + `cluster_spec`. + 2) whether there is at most one "chief" job. + 3) whether the `task_id` is smaller than the number of `task_type`. + + Args: + cluster_spec: a dict, `ClusterDef` or `ClusterSpec` object to be validated. + task_type: string indicating the type of the task. + task_id: task_id: the id of the `task_type` in this cluster. + Throws: + ValueError: if `cluster_spec` fails any check. + """ + cluster_spec = normalize_cluster_spec(cluster_spec).as_dict() + if task_type and task_type not in cluster_spec: + raise ValueError("`task_type` %r not found in cluster_spec." % task_type) + if len(cluster_spec.get("chief", [])) > 1: + raise ValueError("There must be at most one 'chief' job.") + if task_id >= len(cluster_spec[task_type]): + raise ValueError( + "The `task_id` %d exceeds the maximum id of %s." % (task_id, task_type)) + + def is_chief(cluster_spec, task_type, task_id): """Returns whether the given task is chief in the cluster. @@ -61,20 +88,73 @@ def is_chief(cluster_spec, task_type, task_id): ValueError: if `task_type` is not in the `cluster_spec` or `task_id` exceeds the maximum id of the `task_type`. """ - cluster_spec = normalize_cluster_spec(cluster_spec) - if task_type not in cluster_spec.jobs: - raise ValueError( - "The task_type \"%s\" is not in the `cluster_spec`." % task_type) - if task_id >= cluster_spec.num_tasks(task_type): - raise ValueError("The `task_id` %d exceeds the maximum id of %s." % ( - task_id, task_type)) + _validate_cluster_spec(cluster_spec, task_type, task_id) + cluster_spec = normalize_cluster_spec(cluster_spec).as_dict() if task_type == "chief": return True # If chief not in the cluster_spec, use the first worker as chief. This is # common in CollectiveAllReduceStrategy. - if ("chief" not in cluster_spec.jobs and task_type == "worker" and - task_id == 0): + if ("chief" not in cluster_spec and task_type == "worker" and task_id == 0): return True return False + + +def worker_count(cluster_spec, task_type): + """Returns the number of workers in the cluster.""" + _validate_cluster_spec(cluster_spec, task_type, task_id=0) + cluster_spec = normalize_cluster_spec(cluster_spec).as_dict() + + # Other jobs such as "ps" shouldn't call this function. + if task_type not in ["chief", "worker", "evaluator"]: + raise ValueError("Unexpected `task_type` %r" % task_type) + + if task_type == "evaluator": + # The "evaluator" is in its own cluster or its own partition of a cluster. + # So we don't have to count "chief" or "worker" if the current task is an + # "evaluator". + return len(cluster_spec["evaluator"]) + else: + # In the non-evaluator case, we return the total number of "chief" and + # "worker" tasks as the "chief" is also a worker. + return (len(cluster_spec.get("chief", [])) + len( + cluster_spec.get("worker", []))) + + +def id_in_cluster(cluster_spec, task_type, task_id): + """Returns a unique id for the task in the `task_type`'s cluster. + + It returns an id ranging from [0, `worker_count(task_type, task_id)`). + + Note: this function assumes that "evaluate" job is in its own cluster or its + own partition of a cluster. + + Args: + cluster_spec: a dict, `ClusterDef` or `ClusterSpec` object to be validated. + task_type: string indicating the type of the task. + task_id: the id of the `task_type` in this cluster. + + Returns: + an int indicating the unique id. + + Throws: + ValueError: if `task_type` is not "chief", "worker" or "evaluator". + """ + _validate_cluster_spec(cluster_spec, task_type, task_id) + cluster_spec = normalize_cluster_spec(cluster_spec).as_dict() + + # The "chief" job has always id 0 and there is at most one and "worker" jobs + # come after it. + if task_type == "chief": + return 0 + + if task_type == "worker": + return task_id + len(cluster_spec.get("chief", [])) + + # The "evaluator" is in its own cluster or its own partition of a cluster. + if task_type == "evaluator": + return task_id + + # We currently don't assign ids to other tasks. + raise ValueError("There is no id for task_type %r" % task_type) diff --git a/tensorflow/python/distribute/multi_worker_util_test.py b/tensorflow/python/distribute/multi_worker_util_test.py index bdc49725c7..9e1596eefd 100644 --- a/tensorflow/python/distribute/multi_worker_util_test.py +++ b/tensorflow/python/distribute/multi_worker_util_test.py @@ -95,7 +95,7 @@ class IsChiefTest(test.TestCase): self.assertFalse(multi_worker_util.is_chief(cluster_spec, "worker", 1)) with self.assertRaisesRegexp( - ValueError, "The task_type \"chief\" is not in the `cluster_spec`."): + ValueError, "`task_type` 'chief' not found in cluster_spec."): multi_worker_util.is_chief(cluster_spec, "chief", 0) with self.assertRaisesRegexp( @@ -103,5 +103,94 @@ class IsChiefTest(test.TestCase): multi_worker_util.is_chief(cluster_spec, "worker", 2) +class NumWorkersTest(test.TestCase): + + def testCountWorker(self): + cluster_spec = { + "chief": ["127.0.0.1:1234"], + "worker": ["127.0.0.1:8964", "127.0.0.1:2333"], + "ps": ["127.0.0.1:1926", "127.0.0.1:3141"] + } + self.assertEqual( + multi_worker_util.worker_count(cluster_spec, task_type="chief"), 3) + self.assertEqual( + multi_worker_util.worker_count(cluster_spec, task_type="worker"), 3) + + def testCountEvaluator(self): + cluster_spec = { + "chief": ["127.0.0.1:1234"], + "worker": ["127.0.0.1:8964", "127.0.0.1:2333"], + "evaluator": ["127.0.0.1:7566"] + } + self.assertEqual( + multi_worker_util.worker_count(cluster_spec, task_type="evaluator"), 1) + + def testTaskTypeNotFound(self): + cluster_spec = {} + with self.assertRaisesRegexp( + ValueError, "`task_type` 'worker' not found in cluster_spec."): + multi_worker_util.worker_count(cluster_spec, task_type="worker") + + def testCountPs(self): + cluster_spec = { + "chief": ["127.0.0.1:1234"], + "ps": ["127.0.0.1:1926", "127.0.0.1:3141"] + } + # A "ps" job shouldn't call this method. + with self.assertRaisesRegexp(ValueError, "Unexpected `task_type` 'ps'"): + multi_worker_util.worker_count(cluster_spec, task_type="ps") + + +class IdInClusterTest(test.TestCase): + + def testChiefId(self): + cluster_spec = { + "chief": ["127.0.0.1:1234"], + "worker": ["127.0.0.1:8964", "127.0.0.1:2333"], + "ps": ["127.0.0.1:1926", "127.0.0.1:3141"] + } + self.assertEqual( + multi_worker_util.id_in_cluster(cluster_spec, "chief", 0), 0) + + def testWorkerId(self): + cluster_spec = { + "chief": ["127.0.0.1:1234"], + "worker": ["127.0.0.1:8964", "127.0.0.1:2333"], + "ps": ["127.0.0.1:1926", "127.0.0.1:3141"] + } + self.assertEqual( + multi_worker_util.id_in_cluster(cluster_spec, "worker", 1), 2) + + cluster_spec = { + "worker": ["127.0.0.1:8964", "127.0.0.1:2333"], + "ps": ["127.0.0.1:1926", "127.0.0.1:3141"] + } + self.assertEqual( + multi_worker_util.id_in_cluster(cluster_spec, "worker", 1), 1) + + def testEvaluatorId(self): + cluster_spec = { + "chief": ["127.0.0.1:1234"], + "worker": ["127.0.0.1:8964", "127.0.0.1:2333"], + "evaluator": ["127.0.0.1:7566"] + } + self.assertEqual( + multi_worker_util.id_in_cluster(cluster_spec, "evaluator", 0), 0) + + def testPsId(self): + cluster_spec = {"chief": ["127.0.0.1:1234"], "ps": ["127.0.0.1:7566"]} + with self.assertRaisesRegexp(ValueError, + "There is no id for task_type 'ps'"): + multi_worker_util.id_in_cluster(cluster_spec, "ps", 0) + + def testMultipleChiefs(self): + cluster_spec = { + "chief": ["127.0.0.1:8258", "127.0.0.1:7566"], + } + with self.assertRaisesRegexp(ValueError, + "There must be at most one 'chief' job."): + multi_worker_util.id_in_cluster(cluster_spec, "chief", 0) + + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/distribute/reduce_util.py b/tensorflow/python/distribute/reduce_util.py new file mode 100644 index 0000000000..2b2a4e9dba --- /dev/null +++ b/tensorflow/python/distribute/reduce_util.py @@ -0,0 +1,53 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Utilites for reduce operations.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import enum + +from tensorflow.python.ops import variable_scope +from tensorflow.python.util.tf_export import tf_export + + +@tf_export("distribute.ReduceOp") +class ReduceOp(enum.Enum): + """Indicates how a set of values should be reduced. + + * `SUM`: Add all the values. + * `MEAN`: Take the arithmetic mean ("average") of the values. + + TODO(priyag): Add the following types: + * `MIN`: Return the minimum of all values. + * `MAX`: Return the maximum of all values. + """ + + SUM = "SUM" + MEAN = "MEAN" + + @staticmethod + def from_variable_aggregation(aggregation): + mapping = { + variable_scope.VariableAggregation.SUM: ReduceOp.SUM, + variable_scope.VariableAggregation.MEAN: ReduceOp.MEAN, + } + + reduce_op = mapping.get(aggregation) + if not reduce_op: + raise ValueError("Could not convert from `tf.VariableAggregation` %s to" + "`tf.distribute.ReduceOp` type" % aggregation) + return reduce_op diff --git a/tensorflow/contrib/distribute/python/shared_variable_creator.py b/tensorflow/python/distribute/shared_variable_creator.py similarity index 100% rename from tensorflow/contrib/distribute/python/shared_variable_creator.py rename to tensorflow/python/distribute/shared_variable_creator.py diff --git a/tensorflow/contrib/distribute/python/shared_variable_creator_test.py b/tensorflow/python/distribute/shared_variable_creator_test.py similarity index 97% rename from tensorflow/contrib/distribute/python/shared_variable_creator_test.py rename to tensorflow/python/distribute/shared_variable_creator_test.py index 2a9ab51fcf..4ddc29f256 100644 --- a/tensorflow/contrib/distribute/python/shared_variable_creator_test.py +++ b/tensorflow/python/distribute/shared_variable_creator_test.py @@ -18,7 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.contrib.distribute.python import shared_variable_creator +from tensorflow.python.distribute import shared_variable_creator from tensorflow.python.eager import test from tensorflow.python.framework import test_util from tensorflow.python.ops import variable_scope diff --git a/tensorflow/contrib/distribute/python/values.py b/tensorflow/python/distribute/values.py similarity index 77% rename from tensorflow/contrib/distribute/python/values.py rename to tensorflow/python/distribute/values.py index a162973535..01a1680a24 100644 --- a/tensorflow/contrib/distribute/python/values.py +++ b/tensorflow/python/distribute/values.py @@ -23,11 +23,18 @@ from __future__ import print_function import collections import contextlib +import operator import weakref import six -from tensorflow.contrib.distribute.python import input_ops +from tensorflow.python.data.experimental.ops import batching +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import multi_device_iterator_ops +from tensorflow.python.distribute import device_util +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import distribution_strategy_context +from tensorflow.python.distribute import input_ops +from tensorflow.python.distribute import reduce_util from tensorflow.python.eager import context from tensorflow.python.eager import tape from tensorflow.python.framework import device as tf_device @@ -38,10 +45,6 @@ from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_resource_variable_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import variable_scope as vs -from tensorflow.python.ops import variables as variables_lib -from tensorflow.python.training import device_util -from tensorflow.python.training import distribute as distribute_lib -from tensorflow.python.training import distribution_strategy_context from tensorflow.python.training import saver from tensorflow.python.training.checkpointable import base as checkpointable from tensorflow.python.util import nest @@ -97,10 +100,21 @@ class DistributedValues(object): # DistributionStrategy implementations. +# NOTE(josh11b,apassos): It would be great if we could inspect the values this was +# initialized with and use that to generate the overloaded operators here. +# Unfortunately, Python's rules for special methods don't allow this, see +# https://docs.python.org/3/reference/datamodel.html#special-method-names +# "if a class defines a method named __getitem__(), and x is an instance of +# this class, then x[i] is roughly equivalent to type(x).__getitem__(x, i)." +# In particular, these special methods don't go through __getattr__, and +# it will only use those methods if they are defined in the class, not the +# object. class DistributedDelegate(DistributedValues): """A map from device to values; acts as the same type as the values.""" def __getattr__(self, name): + # TODO(priyag): This needs to be made robust against pitfalls from mix use + # __getattr__ and @property. See b/120402273. return getattr(self.get(), name) # pylint: disable=multiple-statements @@ -316,6 +330,14 @@ class DistributedVariable(DistributedDelegate): ops.register_dense_tensor_like_type(DistributedVariable) +def _apply_aggregation(strategy, value, aggregation, destinations): + if aggregation == vs.VariableAggregation.ONLY_FIRST_REPLICA: + return strategy.broadcast(strategy.unwrap(value)[0], + destinations=destinations) + reduce_op = reduce_util.ReduceOp.from_variable_aggregation(aggregation) + return strategy.extended.reduce_to(reduce_op, value, destinations) + + class _MirroredSaveable(saver.BaseSaverBuilder.ResourceVariableSaveable): """Class for defining how to restore a MirroredVariable.""" @@ -373,14 +395,11 @@ class MirroredVariable(DistributedVariable, Mirrored, "MirroredVariable in Replica Context.") def merge_fn(strategy, value, *other_args, **other_kwargs): - return strategy.update( - self, f, - strategy.reduce( - aggregation=self._aggregation, value=value, destinations=self), - *other_args, **other_kwargs) + v = _apply_aggregation(strategy, value, self._aggregation, self) + return strategy.update(self, f, v, *other_args, **other_kwargs) return distribution_strategy_context.get_replica_context().merge_call( - merge_fn, *args, **kwargs) + merge_fn, args=args, kwargs=kwargs) def assign_sub(self, *args, **kwargs): assign_sub_fn = lambda var, *a, **kw: var.assign_sub(*a, **kw) @@ -614,14 +633,11 @@ class TPUMirroredVariable(checkpointable.CheckpointableBase): "TPUMirroredVariable in Replica Context.") def merge_fn(strategy, value, *other_args, **other_kwargs): - return strategy.update( - self, f, - strategy.reduce( - aggregation=self._aggregation, value=value, destinations=self), - *other_args, **other_kwargs) + v = _apply_aggregation(strategy, value, self._aggregation, self) + return strategy.update(self, f, v, *other_args, **other_kwargs) return distribution_strategy_context.get_replica_context().merge_call( - merge_fn, *args, **kwargs) + merge_fn, args=args, kwargs=kwargs) @contextlib.contextmanager def _handle_graph(self, handle): @@ -1058,18 +1074,18 @@ def select_device_mirrored(device, structured): return nest.map_structure(_get_mirrored, structured) -def update_regroup(strategy, updates, should_group): +def update_regroup(extended, updates, group): """Regroup for an update, with dependencies to ensure all updates execute.""" regrouped = regroup(updates, Mirrored) - if not should_group: - return nest.map_structure(strategy.unwrap, regrouped) + if not group: + return nest.map_structure(extended._unwrap, regrouped) # pylint: disable=protected-access grouped_flat = [] for u in nest.flatten(regrouped): if isinstance(u, DistributedValues): - g = strategy.group(u) + g = extended._group(u) # pylint: disable=protected-access if u.is_tensor_like: # Make sure we run all updates. Without this, something like - # session.run(strategy.update(...)) may only update one replica. + # session.run(extended.update(...)) may only update one replica. index = {} for d in u.devices: with ops.device(d), ops.control_dependencies([g]): @@ -1155,7 +1171,7 @@ class PerReplicaDataset(object): # Eager mode prefetching would error out in constructor. Only remaining # case is non-prefetching in eager mode. We delegate to # PerReplicaDataIterator to handle that case. - dataset_iterator = self._dataset.make_one_shot_iterator() + dataset_iterator = dataset_ops.make_one_shot_iterator(self._dataset) return PerReplicaDataIterator( dataset_iterator, self._devices, prefetch_on_device=False) @@ -1170,7 +1186,7 @@ class PerReplicaDataset(object): dataset_iterator = multi_device_iterator_ops.MultiDeviceIterator( self._dataset, self._devices) else: - dataset_iterator = self._dataset.make_initializable_iterator() + dataset_iterator = dataset_ops.make_initializable_iterator(self._dataset) return PerReplicaDataIterator( dataset_iterator, self._devices, @@ -1252,22 +1268,34 @@ class MultiWorkerDataset(object): """Initialize the MultiWorkerDataset object. Args: - dataset_fn: a function that returns a `tf.data.Dataset`. + dataset_fn: a function or a list of functions that returns a + `tf.data.Dataset`. worker_device_pairs: a list of (worker, list of devices on that worker) - pairs. + pairs; it must have same length with `dataset_fn` if `dataset_fn` is a + list. prefetch_on_device: whether to prefetch to devices. auto_shard: whether to auto-shard the dataset. """ + if isinstance(dataset_fn, list): + if len(dataset_fn) != len(worker_device_pairs): + raise ValueError("If `dataset_fn` is a list, it must have same length " + "as `worker_device_pairs`") + if auto_shard: + raise ValueError( + "If `dataset_fn` is a list, `auto_shard` is not supported.") self._worker_device_pairs = worker_device_pairs self._datasets = [] # TODO(yuefengz, priyag): support different set of jobs for input # processing. for i, (worker, worker_devices) in enumerate(worker_device_pairs): with ops.device(worker): - worker_input = dataset_fn() - if auto_shard: - worker_input = input_ops.auto_shard_dataset( - worker_input, len(worker_device_pairs), i) + if isinstance(dataset_fn, list): + worker_input = dataset_fn[i]() + else: + worker_input = dataset_fn() + if auto_shard: + worker_input = input_ops.auto_shard_dataset( + worker_input, len(worker_device_pairs), i) dataset = PerReplicaDataset( worker_input, worker_devices, prefetch_on_device=prefetch_on_device) self._datasets.append((worker, dataset)) @@ -1276,36 +1304,337 @@ class MultiWorkerDataset(object): iterators = [] for worker, dataset in self._datasets: with ops.device(worker): - iterators.append((worker, dataset.make_one_shot_iterator())) + iterators.append((worker, dataset_ops.make_one_shot_iterator(dataset))) return MultiWorkerDataIterator(iterators, self._worker_device_pairs) def make_initializable_iterator(self): iterators = [] for worker, dataset in self._datasets: with ops.device(worker): - iterators.append((worker, dataset.make_initializable_iterator())) + iterators.append( + (worker, dataset_ops.make_initializable_iterator(dataset))) return MultiWorkerDataIterator(iterators, self._worker_device_pairs) +class InputIterator(object): + """An input iterator, intended to be passed to `DistributionStrategy.run`.""" + + def get_next(self): + """Returns the next inputs for all replicas.""" + raise NotImplementedError("must be implemented in descendants") + + def initialize(self): + """Initialize the underlying input dataset, when applicable. + + In eager mode, this will create a new iterator and return it. + In graph mode, this will initialize the same underlying iterator(s). + + Users are required to call this if + - This iterator was returned from a call to `make_input_fn_iterator` with an + input function that returns a dataset. + - Or this iterator was returned from a call to `make_dataset_iterator`. + + Returns: + A list of initialization ops to be executed. + """ + raise NotImplementedError("must be implemented in descendants") + + +class InputIteratorImpl(InputIterator): + """Common implementation for all input iterators.""" + + def __init__(self, worker_device_pairs, iterators): + if not worker_device_pairs: + raise ValueError("Should have at least one worker for input iterator.") + + self._iterators = iterators + self._worker_device_pairs = worker_device_pairs + self._is_eager = context.executing_eagerly() + + def get_next(self, name=None): + """Returns the next input from the iterator for all replicas.""" + assert self._is_eager == context.executing_eagerly(), ( + "Iterator should be created and used in same execution mode.") + + index = {} + for i, (worker, worker_devices) in enumerate(self._worker_device_pairs): + if name is not None: + d = tf_device.DeviceSpec.from_string(worker) + new_name = "%s_%s_%d" % (name, d.job, d.task) + else: + new_name = None + with ops.device(worker): + data_per_worker = self._iterators[i].get_next(new_name) + + # Ungroup these per-replica value so as to get a flat map from devices to + # values. + for d in worker_devices: + v = select_device(d, data_per_worker) + if d in index: + raise ValueError("Duplicated devices in worker_device_pairs: %r" % v) + index[d] = v + + return regroup(index) + + def initialize(self): + """Initialze underlying iterators. + + Returns: + A list of any initializer ops that should be run. + """ + assert self._is_eager == context.executing_eagerly(), ( + "Iterator should be created and used in same execution mode.") + + init_ops = [] + for it in self._iterators: + init_ops.extend(it.initialize()) + return init_ops + + # TODO(priyag): Remove when we switch to using `MultiDeviceIterator` for TPUs. + @property + def output_classes(self): + return self._iterators[0].output_classes + + # TODO(priyag): Remove when we switch to using `MultiDeviceIterator` for TPUs. + @property + def output_shapes(self): + return self._iterators[0].output_shapes + + # TODO(priyag): Remove when we switch to using `MultiDeviceIterator` for TPUs. + @property + def output_types(self): + return self._iterators[0].output_types + + # TODO(priyag): Remove when we switch to using `MultiDeviceIterator` for TPUs. + def get_iterator(self, worker): + for i, (w, _) in enumerate(self._worker_device_pairs): + if worker == w: + return self._iterators[i] + return None + + +class InputFunctionIterator(InputIteratorImpl): + """Iterator created from input function.""" + + def __init__(self, input_fn, worker_device_pairs, input_contexts): + """Make an iterator for input provided via an input function. + + Currently implements PER_WORKER mode, in which the `input_fn` is called + once on each worker. + + TODO(priyag): Add other replication modes. + TODO(priyag): Allow taking input function that returns a callable that + returns nest of tensors. + + Args: + input_fn: Input function that returns a `tf.data.Dataset` object. + worker_device_pairs: A list of (worker, list of devices on that worker) + pairs. + input_contexts: A list of `InputContext` instances to be passed to call(s) + to `input_fn`. Length and order should match worker order in + `worker_device_pairs`. + """ + if len(worker_device_pairs) != len(input_contexts): + raise ValueError( + "Number of worker_device_pairs (%d) is not same as number of" + "input_contexts (%d)" % ( + len(worker_device_pairs), len(input_contexts))) + + iterators = [] + for (worker, devices), ctx in zip(worker_device_pairs, input_contexts): + # TODO(priyag): We should probably explicitly specify CPU device on worker. + with ops.device(worker): + result = input_fn(ctx) + if not isinstance(result, dataset_ops.DatasetV2): + raise ValueError("input_fn must return a tf.data.Dataset.") + iterator = _SingleWorkerDatasetIterator(result, worker, devices) + iterators.append(iterator) + + super(InputFunctionIterator, self).__init__( + worker_device_pairs, iterators) + + +class DatasetIterator(InputIteratorImpl): + """Iterator created from input dataset.""" + + def __init__(self, dataset, worker_device_pairs, split_batch_by=None): + """Make an iterator for the dataset on given devices. + + If `split_batch_by` is not None, we "split" each batch of the + dataset by `split_batch_by` value. To achieve this, we first unbatch the + input dataset and then rebatch it with the per replica batch size that is + calculated using `global_batch_size // split_batch_by`. + The currently supported datasets are as follows: + `dataset.batch()` is the last operation on the dataset OR + `dataset.apply(map_and_batch)` is the last operation on the dataset OR + `dataset.batch().prefetch()` are the last 2 operations on the dataset OR + `dataset.apply(map_and_batch).prefetch()` are the last 2 operations. + + TODO(priyag): Support multi worker / host cases properly by cloning + and sharding the dataset on each worker. Current setup will only work in + some cases, such as in-graph multi worker GPU case. If the input pipeline + has random shuffling (with a different seed on each worker), each worker + will see random input from the same overall dataset in each step. Otherwise, + each worker will see the same input in each step. + + Args: + dataset: `tf.data.Dataset` that will be used as the input source. + worker_device_pairs: A list of (worker, list of devices on that worker) + pairs. + split_batch_by: Optional integer. If present, we "split" each batch of the + dataset by `split_batch_by` value. + """ + if split_batch_by: + dataset = _split_dataset_batch(dataset, split_batch_by) + + iterators = [] + for worker, worker_devices in worker_device_pairs: + with ops.device(worker): + iterator = _SingleWorkerDatasetIterator(dataset, worker, worker_devices) + iterators.append(iterator) + + super(DatasetIterator, self).__init__(worker_device_pairs, iterators) + + +class _SingleWorkerDatasetIterator(object): + """Iterator for a single `tf.data.Dataset`.""" + + def __init__(self, dataset, worker, devices): + """Create iterator for the `dataset` to fetch data to worker's `devices` . + + `MultiDeviceIterator` is used to prefetch input to the devices on the + given worker. `MultiDeviceIterator` doesn't work in eager mode yet. + + Args: + dataset: A `tf.data.Dataset` instance. + worker: Worker on which ops should be created. + devices: Distribute data from `dataset` to these devices. + """ + self._dataset = dataset + self._worker = worker + self._devices = devices + self._is_eager = context.executing_eagerly() + self._make_iterator() + + def _make_iterator(self): + """Make appropriate iterator on the dataset.""" + with ops.device(self._worker): + if self._is_eager: + # TODO(rohanj): Enable prefetching in eager mode. + # TODO(priyag): Measure the performance of this approach vs calling + # get_next on the original dataset N times. + dataset = self._dataset.batch(len(self._devices), drop_remainder=True) + iterator = dataset_ops.make_one_shot_iterator(dataset) + else: + iterator = multi_device_iterator_ops.MultiDeviceIterator( + self._dataset, self._devices) + self._iterator = iterator + + def get_next(self, name=None): + """Get next element from the underlying iterator.""" + with ops.device(self._worker): + if self._is_eager: + # Batched dataset case. + batch = self._iterator.get_next(name=name) + index = {} + for i, d in enumerate(self._devices): + index[d] = nest.map_structure(operator.itemgetter(i), batch) + with ops.device(d): + index[d] = nest.map_structure(array_ops.identity, index[d]) + else: + # MultiDeviceIterator case. + data_list = self._iterator.get_next() + index = dict(zip(self._devices, data_list)) + + return regroup(index) + + def initialize(self): + """Initialze underlying iterator. + + In eager execution, this simply recreates the underlying iterator. + In graph execution, it returns the initializer ops for the underlying + iterator. + + Returns: + A list of any initializer ops that should be run. + """ + if self._is_eager: + self._make_iterator() + return [] + else: + return [self._iterator.initializer] + + @property + def output_classes(self): + return self._iterator.output_classes + + @property + def output_shapes(self): + return self._iterator.output_shapes + + @property + def output_types(self): + return self._iterator.output_types + + +def _split_dataset_batch(dataset, split_batch_by): + """Divide a batch-ed dataset's batches into smaller batches.""" + # TODO(sourabhbajaj): Remove this in lieu of distributed datasets + # pylint: disable=protected-access + def _get_batch_dataset(d): + """Get the underlying batch dataset from the dataset object.""" + if isinstance(d, dataset_ops.DatasetV1Adapter): + d = d._dataset + + if isinstance(d, (dataset_ops.BatchDataset, batching._MapAndBatchDataset)): + return d + elif isinstance(d, dataset_ops.PrefetchDataset): + return _get_batch_dataset(d._input_dataset) + raise ValueError( + "Unable to get batched dataset from the input dataset. `batch` " + "`map_and_batch` need to be the last operations on the dataset. " + "The batch operations can be followed by a prefetch.") + + batched_dataset = _get_batch_dataset(dataset) + batch_size = batched_dataset._batch_size + drop_remainder = batched_dataset._drop_remainder + # pylint: enable=protected-access + + if tensor_util.is_tensor(batch_size): + batch_size = tensor_util.constant_value(batch_size) + + if tensor_util.is_tensor(drop_remainder): + drop_remainder = tensor_util.constant_value(drop_remainder) + + if batch_size % split_batch_by: + raise ValueError( + "Batch size %s cannot be sharded evenly across replicas %s" % ( + batch_size, split_batch_by)) + new_batch_size = batch_size // split_batch_by + + dataset = dataset.apply(batching.unbatch()) + return dataset.batch(new_batch_size, drop_remainder=drop_remainder) + + class MultiStepContext(object): """A context object that can be used to capture things when running steps. This context object is useful when running multiple steps at a time using the - `run_steps_on_dataset` API. For e.g. it allows the user's step function to - specify which outputs to emit at what frequency. Currently it supports - capturing output from the last step, as well as capturing non tensor outputs. - In the future it will be augmented to support other use cases such as output - each N steps. + `experimental_run_steps_on_iterator` API. For e.g. it allows the user's step + function to specify which outputs to emit at what frequency. Currently it + supports capturing output from the last step, as well as capturing non tensor + outputs. In the future it will be augmented to support other use cases such + as output each N steps. """ def __init__(self): - """Initializes an output context. + """Initialize an output context. Returns: A context object. """ self._last_step_outputs = {} - self._last_step_outputs_aggregations = {} + self._last_step_outputs_reduce_ops = {} self._non_tensor_outputs = {} @property @@ -1315,8 +1644,8 @@ class MultiStepContext(object): Keys in the dictionary are names of tensors to be captured, as specified when `set_last_step_output` is called. Values in the dictionary are the tensors themselves. If - `set_last_step_output` was called with an `aggregation` for this output, - then the value is the aggregated value. + `set_last_step_output` was called with a `reduce_op` for this output, + then the value is the reduced value. Returns: A dictionary with last step outputs. @@ -1329,8 +1658,7 @@ class MultiStepContext(object): raise ValueError("Need a dictionary to set last_step_outputs.") self._last_step_outputs = outputs - def set_last_step_output(self, name, output, - aggregation=variables_lib.VariableAggregation.NONE): + def set_last_step_output(self, name, output, reduce_op=None): """Set `output` with `name` to be outputted from the last step. Args: @@ -1338,39 +1666,36 @@ class MultiStepContext(object): name. output: The tensors that should be outputted with `name`. See below for actual types supported. - aggregation: Aggregation method to use to aggregate outputs from multiple + reduce_op: Reduction method to use to reduce outputs from multiple replicas. Required if `set_last_step_output` is called in a replica context. Optional in cross_replica_context. - When present, the outputs from all the replicas are aggregated using the + When present, the outputs from all the replicas are reduced using the current distribution strategy's `reduce` method. Hence, the type of `output` must be what's supported by the corresponding `reduce` method. - For e.g. if using MirroredStrategy and aggregation is set, output + For e.g. if using MirroredStrategy and reduction is set, output must be a `PerReplica` value. - The aggregation method is also recorded in a dictionary - `_last_step_outputs_aggregations` for later interpreting of the + The reduce method is also recorded in a dictionary + `_last_step_outputs_reduce_ops` for later interpreting of the outputs as already reduced or not. - """ if distribution_strategy_context.get_cross_replica_context(): - self._last_step_outputs_aggregations[name] = aggregation - if aggregation is variables_lib.VariableAggregation.NONE: + self._last_step_outputs_reduce_ops[name] = reduce_op + if reduce_op is None: self._last_step_outputs[name] = output else: distribution = distribution_strategy_context.get_distribution_strategy() - self._last_step_outputs[name] = distribution.reduce( - aggregation, output, destinations="/device:CPU:0") + self._last_step_outputs[name] = distribution.reduce(reduce_op, output) else: - assert aggregation is not variables_lib.VariableAggregation.NONE + assert reduce_op is not None def merge_fn(distribution, value): - self._last_step_outputs[name] = distribution.reduce( - aggregation, value, destinations="/device:CPU:0") + self._last_step_outputs[name] = distribution.reduce(reduce_op, value) # Setting this inside the `merge_fn` because all replicas share the same # context object, so it's more robust to set it only once (even if all # the replicas are trying to set the same value). - self._last_step_outputs_aggregations[name] = aggregation + self._last_step_outputs_reduce_ops[name] = reduce_op distribution_strategy_context.get_replica_context().merge_call( - merge_fn, output) + merge_fn, args=(output,)) @property def non_tensor_outputs(self): @@ -1384,10 +1709,10 @@ class MultiStepContext(object): else: def merge_fn(distribution, value): # NOTE(priyag): For non tensor outputs, we simply return all the values - # in a list as aggregation doesn't make sense on non tensors. + # in a list as reduction doesn't make sense on non tensors. self._non_tensor_outputs[name] = distribution.unwrap(value) distribution_strategy_context.get_replica_context().merge_call( - merge_fn, output) + merge_fn, args=(output,)) def value_container(val): @@ -1452,14 +1777,11 @@ class AggregatingVariable(checkpointable.CheckpointableBase): "a variable in Replica Context.") def merge_fn(strategy, value, *other_args, **other_kwargs): - return strategy.update( - self, f, - strategy.reduce( - aggregation=self._aggregation, value=value, destinations=self), - *other_args, **other_kwargs) + v = _apply_aggregation(strategy, value, self._aggregation, self) + return strategy.update(self, f, v, *other_args, **other_kwargs) return distribution_strategy_context.get_replica_context().merge_call( - merge_fn, *args, **kwargs) + merge_fn, args=args, kwargs=kwargs) def assign_sub(self, *args, **kwargs): assign_sub_fn = lambda var, *a, **kw: var.assign_sub(*a, **kw) diff --git a/tensorflow/python/eager/BUILD b/tensorflow/python/eager/BUILD index 362e8e3b83..f43cf9327a 100644 --- a/tensorflow/python/eager/BUILD +++ b/tensorflow/python/eager/BUILD @@ -174,6 +174,23 @@ cuda_py_test( ], ) +cuda_py_test( + name = "function_gradients_test", + size = "medium", + srcs = ["function_gradients_test.py"], + additional_deps = [ + ":backprop", + ":context", + ":def_function", + ":function", + ":test", + "@absl_py//absl/testing:parameterized", + "//tensorflow/python:math_ops", + "//tensorflow/python:resource_variable_ops", + ], + shard_count = 5, +) + cuda_py_test( name = "function_test", size = "medium", @@ -193,7 +210,7 @@ cuda_py_test( "//tensorflow/python:math_ops", "//tensorflow/python:resource_variable_ops", ], - shard_count = 20, + shard_count = 15, ) py_library( @@ -238,6 +255,18 @@ py_library( ], ) +py_test( + name = "execution_callbacks_test", + srcs = ["execution_callbacks_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":execution_callbacks", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_ops", + "//tensorflow/python:math_ops", + ], +) + py_library( name = "graph_only_ops", srcs = ["graph_only_ops.py"], @@ -318,6 +347,7 @@ py_library( "//tensorflow/python/eager:context", "//tensorflow/python/eager:execute", "//tensorflow/python/eager:tape", + "//tensorflow/python/ops/parallel_for:control_flow_ops", "@six_archive//:six", ], ) diff --git a/tensorflow/python/eager/backprop.py b/tensorflow/python/eager/backprop.py index 844c9b52e7..29f9b2cda3 100644 --- a/tensorflow/python/eager/backprop.py +++ b/tensorflow/python/eager/backprop.py @@ -20,6 +20,7 @@ from __future__ import print_function import functools import operator +import sys import six @@ -33,6 +34,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.ops import array_ops +from tensorflow.python.ops import check_ops from tensorflow.python.ops import gen_array_ops from tensorflow.python.ops import gen_math_ops from tensorflow.python.ops import math_ops @@ -42,9 +44,20 @@ from tensorflow.python.platform import tf_logging as logging from tensorflow.python.util import nest from tensorflow.python.util import tf_contextlib from tensorflow.python.util import tf_inspect +from tensorflow.python.util.lazy_loader import LazyLoader from tensorflow.python.util.tf_export import tf_export +# Note that we need to lazy load the following two modules to avoid creating +# circular dependencies. +# TODO(b/119775953): fix the circular dependencies. +pfor_ops = LazyLoader( + "pfor_ops", globals(), + "tensorflow.python.ops.parallel_for.control_flow_ops") + +function = LazyLoader("function", globals(), + "tensorflow.python.eager.function") + _op_attr_type_cache = {} @@ -536,11 +549,11 @@ def _aggregate_grads(gradients): if len(gradients) == 1: return gradients[0] - if all([isinstance(g, ops.Tensor) for g in gradients]): + if all(isinstance(g, ops.Tensor) for g in gradients): return gen_math_ops.add_n(gradients) else: - assert all([isinstance(g, (ops.Tensor, ops.IndexedSlices)) - for g in gradients]) + assert all(isinstance(g, (ops.Tensor, ops.IndexedSlices)) + for g in gradients) indexed_slices_list = [] for grad in gradients: # TODO(xpan): Support nested IndexedSlices and core IndexedSlices @@ -776,6 +789,8 @@ class GradientTape(object): context.context().end_step() except AttributeError: pass + except TypeError: + pass def watch(self, tensor): """Ensures that `tensor` is being traced by this tape. @@ -935,3 +950,213 @@ class GradientTape(object): grad = nest.pack_sequence_as(sources, flat_grad) return grad + + def jacobian(self, + target, + sources, + unconnected_gradients=UnconnectedGradients.NONE, + parallel_iterations=None, + experimental_use_pfor=True): + """Computes the jacobian using operations recorded in context of this tape. + + See http://en.wikipedia.org/wiki/jacobian_matrix_and_determinant for the + definition of a Jacobian. + + Example usage: + + with tf.GradientTape() as g: + x = tf.constant([1.0, 2.0]) + g.watch(x) + y = x * x + jacobian = g.jacobian(y, x) + # jacobian value is [[2., 0.], [0., 4.]] + + Args: + target: Tensor to be differentiated. + sources: a list or nested structure of Tensors or Variables. `target` + will be differentiated against elements in `sources`. + unconnected_gradients: a value which can either hold 'none' or 'zero' and + alters the value which will be returned if the target and sources are + unconnected. The possible values and effects are detailed in + 'UnconnectedGradients' and it defaults to 'none'. + parallel_iterations: A knob to control how many iterations are dispatched + in parallel. This knob can be used to control the total memory usage. + experimental_use_pfor: If true, vectorizes the jacobian computation. Else + falls back to a sequential while_loop. Vectorization can sometimes fail + or lead to excessive memory usage. This option can be used to disable + vectorization in such cases. + + Returns: + a list or nested structure of Tensors (or IndexedSlices, or None), + one for each element in `sources`. Returned structure is the same as + the structure of `sources`. + + Raises: + RuntimeError: If called on a non-persistent tape with eager execution + enabled and without enabling experimental_use_pfor. + ValueError: If vectorization of jacobian computation fails. + """ + flat_sources = nest.flatten(sources) + target_static_shape = target.shape + target_shape = array_ops.shape(target) + # Note that we push and pop the tape here and below. This is needed since we + # need gradients through the enclosed operations. + self._push_tape() + target = array_ops.reshape(target, [-1]) + self._pop_tape() + + def loop_fn(i): + self._push_tape() + y = array_ops.gather(target, i) + self._pop_tape() + return self.gradient(y, flat_sources, + unconnected_gradients=unconnected_gradients) + + try: + target_size = int(target.shape[0]) + except TypeError: + target_size = array_ops.shape(target)[0] + + if experimental_use_pfor: + try: + output = pfor_ops.pfor(loop_fn, target_size, + parallel_iterations=parallel_iterations) + except ValueError as err: + six.reraise( + ValueError, + ValueError( + str(err) + "\nEncountered an exception while vectorizing the " + "jacobian computation. Vectorization can be disabled by setting" + " experimental_use_pfor to False."), + sys.exc_info()[2]) + else: + if context.executing_eagerly() and not self._persistent: + raise RuntimeError( + "GradientTape must be created with persistent=True" + " to compute the jacobian with eager execution enabled and with " + " experimental_use_pfor set to False.") + output = pfor_ops.for_loop( + loop_fn, [target.dtype] * len(flat_sources), target_size, + parallel_iterations=parallel_iterations) + + for i, out in enumerate(output): + if out is not None: + new_shape = array_ops.concat( + [target_shape, array_ops.shape(out)[1:]], axis=0) + out = array_ops.reshape(out, new_shape) + if context.executing_eagerly(): + out.set_shape(target_static_shape.concatenate(flat_sources[i].shape)) + output[i] = out + + return nest.pack_sequence_as(sources, output) + + def batch_jacobian(self, + target, + source, + unconnected_gradients=UnconnectedGradients.NONE, + parallel_iterations=None, + experimental_use_pfor=True): + """Computes and stacks per-example jacobians. + + See http://en.wikipedia.org/wiki/jacobian_matrix_and_determinant for the + definition of a Jacobian. This function is essentially an efficient + implementation of the following: + `tf.stack([self.jacobian(y[i], x[i]) for i in range(x.shape[0])])`. + + Note that compared to `GradientTape.jacobian` which computes gradient of + each output value w.r.t each input value, this function is useful when + `target[i,...] is independent of `source[j,...]` for `j != i`. This + independence assumption allows more efficient computation as compared to + `GradientTape.jacobian`. The output, as well as intermediate activations, + are lower dimensional and avoid a bunch of redundant zeros which would + result in the jacobian computation given the independence assumption. + + Example usage: + with tf.GradientTape() as g: + x = tf.constant([[1, 2], [3, 4]], dtype=tf.float32) + g.watch(x) + y = x * x + batch_jacobian = g.batch_jacobian(y, x) + # batch_jacobian is [[[2, 0], [0, 4]], [[6, 0], [0, 8]]] + + Args: + target: A tensor with rank 2 or higher and with shape [b, y1, ..., y_n]. + `target[i,...]` should only depend on `source[i,...]`. + source: A tensor with rank 2 or higher and with shape [b, x1, ..., x_m]. + unconnected_gradients: a value which can either hold 'none' or 'zero' and + alters the value which will be returned if the target and sources are + unconnected. The possible values and effects are detailed in + 'UnconnectedGradients' and it defaults to 'none'. + parallel_iterations: A knob to control how many iterations are dispatched + in parallel. This knob can be used to control the total memory usage. + experimental_use_pfor: If true, uses pfor for computing the Jacobian. Else + uses a tf.while_loop. + + Returns: + A tensor `t` with shape [b, y_1, ..., y_n, x1, ..., x_m] where `t[i, ...]` + is the jacobian of `target[i, ...]` w.r.t. `source[i, ...]`, i.e. stacked + per-example jacobians. + + Raises: + RuntimeError: If called on a non-persistent tape with eager execution + enabled and without enabling experimental_use_pfor. + ValueError: If vectorization of jacobian computation fails or if first + dimension of `target` and `source` do not match. + """ + target_shape = target.shape + if not target_shape.with_rank_at_least(2)[0].is_compatible_with( + source.shape.with_rank_at_least(2)[0]): + raise ValueError( + "Need first dimension of target shape (%s) and " + "source shape (%s) to match." % (target.shape, source.shape)) + if target_shape.is_fully_defined(): + batch_size = int(target_shape[0]) + target_row_size = target_shape.num_elements() // batch_size + else: + target_shape = array_ops.shape(target) + batch_size = target_shape[0] + target_row_size = array_ops.size(target) // batch_size + source_shape = array_ops.shape(source) + # Flatten target to 2-D. + # Note that we push and pop the tape here and below. This is needed since we + # need gradients through the enclosed operations. + self._push_tape() + with ops.control_dependencies( + [check_ops.assert_equal(batch_size, source_shape[0])]): + target = array_ops.reshape(target, [batch_size, target_row_size]) + self._pop_tape() + + def loop_fn(i): + self._push_tape() + y = array_ops.gather(target, i, axis=1) + self._pop_tape() + return self.gradient(y, source, + unconnected_gradients=unconnected_gradients) + + if experimental_use_pfor: + try: + output = pfor_ops.pfor(loop_fn, target_row_size, + parallel_iterations=parallel_iterations) + except ValueError as err: + six.reraise( + ValueError, + ValueError( + str(err) + "\nEncountered an exception while vectorizing the " + "batch_jacobian computation. Vectorization can be disabled by " + "setting experimental_use_pfor to False."), + sys.exc_info()[2]) + else: + if context.executing_eagerly() and not self._persistent: + raise RuntimeError( + "GradientTape must be created with persistent=True" + " to compute the batch_jacobian with eager execution enabled and " + " with experimental_use_pfor set to False.") + output = pfor_ops.for_loop(loop_fn, target.dtype, target_row_size, + parallel_iterations=parallel_iterations) + if output is None: + return None + output = array_ops.reshape(output, + [target_row_size, batch_size, -1]) + output = array_ops.transpose(output, [1, 0, 2]) + new_shape = array_ops.concat([target_shape, source_shape[1:]], axis=0) + return array_ops.reshape(output, new_shape) diff --git a/tensorflow/python/eager/backprop_test.py b/tensorflow/python/eager/backprop_test.py index 274d5320df..3cec40a48f 100644 --- a/tensorflow/python/eager/backprop_test.py +++ b/tensorflow/python/eager/backprop_test.py @@ -74,7 +74,7 @@ class BackpropTest(test.TestCase): tf_g1 = embedding_ops.embedding_lookup(tf_var, tf_ind1) tf_g2 = embedding_ops.embedding_lookup(tf_var, tf_ind2) tf_g3 = embedding_ops.embedding_lookup(tf_var, tf_ind3) - tf_g4 = math_ops.reduce_sum(tf_var * 2.0, reduction_indices=(0, 1)) + tf_g4 = math_ops.reduce_sum(tf_var * 2.0, axis=(0, 1)) tf_y = tf_g1 * tf_g2 * tf_g3 * tf_g4 tf_grad = gradients.gradients(tf_y, [tf_var])[0] @@ -215,7 +215,7 @@ class BackpropTest(test.TestCase): self.assertAllClose(tf_grad.values.eval(), grad.values) tf_opt.apply_gradients([(tf_grad, tf_embedding)]).run() - expected = tf_embedding.eval() + expected = self.evaluate(tf_embedding) opt.apply_gradients([(grad, embedding)]) self.assertAllClose(expected, embedding.read_value()) @@ -233,6 +233,68 @@ class BackpropTest(test.TestCase): self.assertTrue(ordered_variables[0] is v0) self.assertTrue(ordered_variables[1] is v1) + def testTapeNoOpGradient(self): + x = constant_op.constant(3.0) + with backprop.GradientTape() as t: + t.watch(x) + y = x + self.assertEqual(t.gradient(y, x).numpy(), 1.0) + + def testTapeIdentityGradientIsIdentity(self): + x = constant_op.constant(3.0) + with backprop.GradientTape() as t: + t.watch(x) + y = array_ops.identity(x) + self.assertEqual(t.gradient(y, x).numpy(), 1.0) + + def testTapeGradientMultiTargetOneIsSource(self): + x = constant_op.constant(2.0) + with backprop.GradientTape() as t: + t.watch(x) + y = x*x + self.assertEqual(t.gradient([x, y], x).numpy(), 5.0) + + def testTapeNoOpGradientWithMultiTargetAllSource(self): + x = constant_op.constant(3.0) + with backprop.GradientTape() as t: + t.watch(x) + y = x + self.assertEqual(t.gradient([y, y], x).numpy(), 2.0) + + def testTapeNoOpGradientWithMultiTargetMultiSource(self): + x = constant_op.constant(3.0) + y = constant_op.constant(5.0) + with backprop.GradientTape() as t: + t.watch(x) + t.watch(y) + z = y * y + self.assertAllEqual(t.gradient([x, y, z], [x, y]), [1.0, 11.0]) + + def testTapeNoOpOnVariableIsIdentity(self): + v0 = resource_variable_ops.ResourceVariable(1.0) + with backprop.GradientTape() as t: + y = v0.read_value() + self.assertEqual(t.gradient(y, v0).numpy(), 1.0) + + @test_util.assert_no_new_tensors + @test_util.assert_no_garbage_created + def testTapeNoOpGradient2By2(self): + a_2_by_2 = constant_op.constant(2.0, shape=[2, 2]) + with backprop.GradientTape(persistent=True) as tape: + tape.watch(a_2_by_2) + dy_dy = tape.gradient(a_2_by_2, [a_2_by_2])[0] + self.assertAllEqual(dy_dy.numpy(), + constant_op.constant(1.0, shape=[2, 2]).numpy()) + + @test_util.assert_no_new_pyobjects_executing_eagerly + def testTapeNoOpGradientMultiTarget2By2(self): + a_2_by_2 = constant_op.constant(2.0, shape=[2, 2]) + with backprop.GradientTape(persistent=True) as tape: + tape.watch(a_2_by_2) + dy_dy = tape.gradient([a_2_by_2, a_2_by_2], [a_2_by_2])[0] + self.assertAllEqual(dy_dy.numpy(), + constant_op.constant(2.0, shape=[2, 2]).numpy()) + def testTapeStopRecording(self): with backprop.GradientTape() as t: x = resource_variable_ops.ResourceVariable(1.0) @@ -1165,5 +1227,192 @@ class BackpropTest(test.TestCase): self.assertAllEqual(da[0], tf_da[0].eval()) +@test_util.run_all_in_graph_and_eager_modes +class JacobianTest(test.TestCase): + + def _jacobian(self, experimental_use_pfor): + persistent = context.executing_eagerly and not experimental_use_pfor + with backprop.GradientTape(persistent=persistent) as g: + x = constant_op.constant([1., 2.]) + y = constant_op.constant([3., 4.]) + g.watch(x) + g.watch(y) + z = x * x * y + jacobian = g.jacobian(z, [x, y], + experimental_use_pfor=experimental_use_pfor) + answer = [array_ops.diag(2 * x * y), array_ops.diag(x * x)] + return jacobian, answer + + def testPfor(self): + jacobian, answer = self._jacobian(experimental_use_pfor=True) + for j, a in zip(jacobian, answer): + self.assertAllEqual(a, j) + + def testWhileLoop(self): + jacobian, answer = self._jacobian(experimental_use_pfor=False) + for j, a in zip(jacobian, answer): + self.assertAllEqual(a, j) + + def testPforDefun(self): + + @function.defun + def _f(): + return self._jacobian(experimental_use_pfor=True) + + jacobian, answer = _f() + for j, a in zip(jacobian, answer): + self.assertAllEqual(a, j) + + def testWhileLoopDefun(self): + + @function.defun + def _f(): + return self._jacobian(experimental_use_pfor=False) + + jacobian, answer = _f() + for j, a in zip(jacobian, answer): + self.assertAllEqual(a, j) + + def testPersistentTape(self): + if not context.executing_eagerly(): + return + with backprop.GradientTape() as g: + x = constant_op.constant([1.0, 2.0]) + g.watch(x) + y = x * x + with self.assertRaisesRegexp(RuntimeError, 'persistent'): + g.jacobian(y, x, experimental_use_pfor=False) + + def testPforException(self): + var = variables.Variable([1.]) + + @custom_gradient.custom_gradient + def op(x): + def grad(_): + # Note that we perform a stateful operation here that will not be + # compatible with parallel for construct. + with ops.control_dependencies( + [var.assign(random_ops.random_uniform([1]))]): + return constant_op.constant(1.) + return x, grad + + with backprop.GradientTape() as g: + x = constant_op.constant([1., 2.]) + g.watch(x) + y = op(x) + with self.assertRaisesRegexp(ValueError, 'No converter'): + g.jacobian(y, x, experimental_use_pfor=True) + + def test_parallel_iterations(self): + with backprop.GradientTape(persistent=True) as g: + x = constant_op.constant([[1., 2], [3, 4]]) + g.watch(x) + y = math_ops.matmul(x, x) + self.assertAllClose(g.jacobian(y, x, parallel_iterations=2), + g.jacobian(y, x, parallel_iterations=3)) + + +@test_util.run_all_in_graph_and_eager_modes +class BatchJacobianTest(test.TestCase): + + def _batch_jacobian(self, experimental_use_pfor): + persistent = context.executing_eagerly and not experimental_use_pfor + with backprop.GradientTape(persistent=persistent) as g: + x = constant_op.constant([[1., 2.], [3., 4.]]) + y = constant_op.constant([[3., 4.], [5., 6.]]) + g.watch(x) + z = x * x * y + batch_jacobian = g.batch_jacobian( + z, x, experimental_use_pfor=experimental_use_pfor) + answer = array_ops.stack([array_ops.diag(2 * x[0] * y[0]), + array_ops.diag(2 * x[1] * y[1])]) + return batch_jacobian, answer + + def testPfor(self): + batch_jacobian, answer = self._batch_jacobian(experimental_use_pfor=True) + self.assertAllEqual(answer, batch_jacobian) + + def testWhileLoop(self): + batch_jacobian, answer = self._batch_jacobian(experimental_use_pfor=False) + self.assertAllEqual(answer, batch_jacobian) + + def testPforDefun(self): + + @function.defun + def _f(): + return self._batch_jacobian(experimental_use_pfor=True) + + batch_jacobian, answer = _f() + self.assertAllEqual(answer, batch_jacobian) + + def testWhileLoopDefun(self): + + @function.defun + def _f(): + return self._batch_jacobian(experimental_use_pfor=False) + + batch_jacobian, answer = _f() + self.assertAllEqual(answer, batch_jacobian) + + def testPersistentTape(self): + if not context.executing_eagerly(): + return + with backprop.GradientTape() as g: + x = constant_op.constant([[1.0, 2.0]]) + g.watch(x) + y = x * x + with self.assertRaisesRegexp(RuntimeError, 'persistent'): + g.batch_jacobian(y, x, experimental_use_pfor=False) + + def testBadShape(self): + x = random_ops.random_uniform([2, 3]) + with backprop.GradientTape() as g: + y = array_ops.concat([x, x], axis=0) + with self.assertRaisesRegexp(ValueError, 'Need first dimension'): + g.batch_jacobian(y, x) + + def testBadInputRank(self): + x = random_ops.random_uniform([2]) + with backprop.GradientTape() as g: + y = random_ops.random_uniform([2, 2]) + with self.assertRaisesRegexp(ValueError, 'must have rank at least 2'): + g.batch_jacobian(y, x) + + def testBadOutputRank(self): + x = random_ops.random_uniform([2, 2]) + with backprop.GradientTape() as g: + y = random_ops.random_uniform([2]) + with self.assertRaisesRegexp(ValueError, 'must have rank at least 2'): + g.batch_jacobian(y, x) + + def testPforException(self): + var = variables.Variable([1.]) + + @custom_gradient.custom_gradient + def op(x): + def grad(_): + # Note that we perform a stateful operation here that will not be + # compatible with parallel for construct. + with ops.control_dependencies( + [var.assign(random_ops.random_uniform([1]))]): + return constant_op.constant(1.) + return x, grad + + with backprop.GradientTape() as g: + x = constant_op.constant([[1.], [2.]]) + g.watch(x) + y = op(x) + with self.assertRaisesRegexp(ValueError, 'No converter'): + g.batch_jacobian(y, x, experimental_use_pfor=True) + + def test_parallel_iterations(self): + with backprop.GradientTape(persistent=True) as g: + x = constant_op.constant([[1., 2], [3, 4]]) + g.watch(x) + w = constant_op.constant([[1., 2, 3, 4], [5, 6, 7, 8]]) + y = math_ops.matmul(x, w) + self.assertAllClose(g.batch_jacobian(y, x, parallel_iterations=2), + g.batch_jacobian(y, x, parallel_iterations=3)) + if __name__ == '__main__': test.main() diff --git a/tensorflow/python/eager/benchmarks_test.py b/tensorflow/python/eager/benchmarks_test.py index 886715867c..31a7efca82 100644 --- a/tensorflow/python/eager/benchmarks_test.py +++ b/tensorflow/python/eager/benchmarks_test.py @@ -80,7 +80,6 @@ class SubclassedKerasModel(keras.Model): def __init__(self, initializer="ones"): super(SubclassedKerasModel, self).__init__() - self._can_use_graph_functions = True self.layer_a = keras.layers.Dense( 64, kernel_initializer=initializer, bias_initializer="zeros") self.layer_b = keras.layers.Dense( @@ -733,38 +732,38 @@ class MicroBenchmarks(test.Benchmark): assert np.equal(func(), make_keras_model()(data)).all() self._run(func, 30000) - def _benchmark_keras_model_fit(self, model): + def _benchmark_keras_model_fit(self, model, run_eagerly=False): data = random_ops.random_uniform((10, 10), minval=-1, maxval=1) labels = random_ops.random_uniform((10, 10), minval=-1, maxval=1) dataset = dataset_ops.Dataset.from_tensors((data, labels)).repeat() model.compile( gradient_descent.GradientDescentOptimizer(learning_rate=0.001), - loss="mse") + loss="mse", run_eagerly=run_eagerly) func = lambda: model.fit(dataset, epochs=1, steps_per_epoch=1000, verbose=0) # First call is more expensive (creates variables etc.), discount that. model.fit(dataset, epochs=1, steps_per_epoch=1, verbose=0) self._run(func, 1) - def _benchmark_keras_model_evaluate(self, model): + def _benchmark_keras_model_evaluate(self, model, run_eagerly=False): data = random_ops.random_uniform((10, 10), minval=-1, maxval=1) labels = random_ops.random_uniform((10, 10), minval=-1, maxval=1) dataset = dataset_ops.Dataset.from_tensors((data, labels)).repeat() model.compile( gradient_descent.GradientDescentOptimizer(learning_rate=0.001), - loss="mse") + loss="mse", run_eagerly=run_eagerly) func = lambda: model.evaluate(dataset, steps=1000, verbose=0) # First call is more expensive (creates variables etc.), discount that. model.evaluate(dataset, steps=1, verbose=0) self._run(func, 1) - def _benchmark_keras_model_predict(self, model): + def _benchmark_keras_model_predict(self, model, run_eagerly=False): data = random_ops.random_uniform((10, 10), minval=-1, maxval=1) dataset = dataset_ops.Dataset.from_tensors(tuple([data])).repeat() model.compile( gradient_descent.GradientDescentOptimizer(learning_rate=0.001), - loss="mse") + loss="mse", run_eagerly=run_eagerly) func = lambda: model.predict(dataset, steps=1000, verbose=0) # First call is more expensive (creates variables etc.), discount that. model.predict(dataset, steps=1, verbose=0) @@ -780,10 +779,9 @@ class MicroBenchmarks(test.Benchmark): model = SubclassedKerasModel(initializer="glorot_uniform") self._benchmark_keras_model_fit(model) - def benchmark_keras_model_subclassed_fit_disable_defun(self): + def benchmark_keras_model_subclassed_fit_run_model_eagerly(self): model = SubclassedKerasModel(initializer="glorot_uniform") - model._can_use_graph_functions = False - self._benchmark_keras_model_fit(model) + self._benchmark_keras_model_fit(model, run_eagerly=True) def benchmark_keras_model_functional_fit(self): model = make_keras_model(initializer="glorot_uniform") @@ -794,10 +792,9 @@ class MicroBenchmarks(test.Benchmark): model = make_keras_model(initializer="glorot_uniform") self._benchmark_keras_model_fit(model) - def benchmark_keras_model_functional_fit_disable_defun(self): + def benchmark_keras_model_functional_fit_run_model_eagerly(self): model = make_keras_model(initializer="glorot_uniform") - model._can_use_graph_functions = False - self._benchmark_keras_model_fit(model) + self._benchmark_keras_model_fit(model, run_eagerly=True) def benchmark_keras_model_sequential_fit(self): model = make_sequential_keras_model(initializer="glorot_uniform") @@ -808,64 +805,57 @@ class MicroBenchmarks(test.Benchmark): model = make_sequential_keras_model(initializer="glorot_uniform") self._benchmark_keras_model_fit(model) - def benchmark_keras_model_sequential_fit_disable_defun(self): + def benchmark_keras_model_sequential_fit_run_model_eagerly(self): model = make_sequential_keras_model(initializer="glorot_uniform") - model._can_use_graph_functions = False - self._benchmark_keras_model_fit(model) + self._benchmark_keras_model_fit(model, run_eagerly=True) def benchmark_keras_model_subclassed_evaluate(self): model = SubclassedKerasModel(initializer="glorot_uniform") self._benchmark_keras_model_evaluate(model) - def benchmark_keras_model_subclassed_evaluate_disable_defun(self): + def benchmark_keras_model_subclassed_evaluate_run_model_eagerly(self): model = SubclassedKerasModel(initializer="glorot_uniform") - model._can_use_graph_functions = False - self._benchmark_keras_model_evaluate(model) + self._benchmark_keras_model_evaluate(model, run_eagerly=True) def benchmark_keras_model_functional_evaluate(self): model = make_keras_model(initializer="glorot_uniform") self._benchmark_keras_model_evaluate(model) - def benchmark_keras_model_functional_evaluate_disable_defun(self): + def benchmark_keras_model_functional_evaluate_run_model_eagerly(self): model = make_keras_model(initializer="glorot_uniform") - model._can_use_graph_functions = False - self._benchmark_keras_model_evaluate(model) + self._benchmark_keras_model_evaluate(model, run_eagerly=True) def benchmark_keras_model_sequential_evaluate(self): model = make_sequential_keras_model(initializer="glorot_uniform") self._benchmark_keras_model_evaluate(model) - def benchmark_keras_model_sequential_evaluate_disable_defun(self): + def benchmark_keras_model_sequential_evaluate_run_model_eagerly(self): model = make_sequential_keras_model(initializer="glorot_uniform") - model._can_use_graph_functions = False - self._benchmark_keras_model_evaluate(model) + self._benchmark_keras_model_evaluate(model, run_eagerly=True) def benchmark_keras_model_subclassed_predict(self): model = SubclassedKerasModel(initializer="glorot_uniform") self._benchmark_keras_model_predict(model) - def benchmark_keras_model_subclassed_predict_disable_defun(self): + def benchmark_keras_model_subclassed_predict_run_model_eagerly(self): model = SubclassedKerasModel(initializer="glorot_uniform") - model._can_use_graph_functions = False - self._benchmark_keras_model_predict(model) + self._benchmark_keras_model_predict(model, run_eagerly=True) def benchmark_keras_model_functional_predict(self): model = make_keras_model(initializer="glorot_uniform") self._benchmark_keras_model_predict(model) - def benchmark_keras_model_functional_predict_disable_defun(self): + def benchmark_keras_model_functional_predict_run_model_eagerly(self): model = make_keras_model(initializer="glorot_uniform") - model._can_use_graph_functions = False - self._benchmark_keras_model_predict(model) + self._benchmark_keras_model_predict(model, run_eagerly=True) def benchmark_keras_model_sequential_predict(self): model = make_sequential_keras_model(initializer="glorot_uniform") self._benchmark_keras_model_predict(model) - def benchmark_keras_model_sequential_predict_disable_defun(self): + def benchmark_keras_model_sequential_predict_run_model_eagerly(self): model = make_sequential_keras_model(initializer="glorot_uniform") - model._can_use_graph_functions = False - self._benchmark_keras_model_predict(model) + self._benchmark_keras_model_predict(model, run_eagerly=True) def benchmarkScan(self): elems = math_ops.range(1600) diff --git a/tensorflow/python/eager/context.py b/tensorflow/python/eager/context.py index e3fef524bf..2f6b038dda 100644 --- a/tensorflow/python/eager/context.py +++ b/tensorflow/python/eager/context.py @@ -25,7 +25,6 @@ import random import threading from tensorflow.core.protobuf import config_pb2 -from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.python import pywrap_tensorflow from tensorflow.python import tf2 from tensorflow.python.framework import c_api_util @@ -86,21 +85,21 @@ class FunctionCallOptions(object): Eager functions are functions decorated with tf.contrib.eager.defun. """ - def __init__(self, executor_type=None, rewriter_config=None): + def __init__(self, executor_type=None, config_proto=None): """Constructor. Args: executor_type: (optional) name of the executor to be used to execute the eager function. If None or an empty string, the default Tensorflow executor will be used. - rewriter_config: (optional) a rewriter_config_pb2.RewriterConfig proto or + config_proto: (optional) a `config_pb2.ConfigProto` proto or a serialized string of that proto. The config used by Grappler when optimizing the function graph. Each concrete function is optimized the first time is called. Changing - rewriter_config after the first call has no effect. - If rewriter_config is None, an empty RewriterConfig will be used. + config_proto after the first call has no effect. + If config_proto is None, an empty RewriterConfig will be used. """ - self.rewriter_config_serialized = rewriter_config + self.config_proto_serialized = config_proto self.executor_type = executor_type @property @@ -112,24 +111,22 @@ class FunctionCallOptions(object): self._executor_type = executor_type @property - def rewriter_config_serialized(self): - return self._rewriter_config_serialized + def config_proto_serialized(self): + return self._config_proto_serialized - @rewriter_config_serialized.setter - def rewriter_config_serialized(self, config): - if isinstance(config, rewriter_config_pb2.RewriterConfig): - self._rewriter_config_serialized = config.SerializeToString() + @config_proto_serialized.setter + def config_proto_serialized(self, config): + if isinstance(config, config_pb2.ConfigProto): + self._config_proto_serialized = config.SerializeToString() elif isinstance(config, str): - self._rewriter_config_serialized = config + self._config_proto_serialized = config elif config is None: - self._rewriter_config_serialized = rewriter_config_pb2.RewriterConfig( - ).SerializeToString() + self._config_proto_serialized = ( + config_pb2.ConfigProto().SerializeToString()) else: - raise ValueError( - "the rewriter config must be either a " - "rewriter_config_pb2.RewriterConfig, or a serialized string of that " - "proto or None. got: {}" - .format(type(config))) + raise ValueError("the rewriter config must be either a " + "config_pb2.ConfigProto, or a serialized string of that " + "proto or None. got: {}".format(type(config))) # TODO(agarwal): better name ? @@ -152,14 +149,12 @@ class _EagerContext(threading.local): # Default rewriter config corresponds to turning all default grappler # optimizations on. - base_config = rewriter_config_pb2.RewriterConfig() + base_config = config_pb2.ConfigProto() - if config is not None and config.HasField( - "graph_options") and config.graph_options.HasField("rewrite_options"): - base_config.Merge(config.graph_options.rewrite_options) + if config is not None: + base_config.MergeFrom(config) - self.function_call_options = FunctionCallOptions( - rewriter_config=base_config) + self.function_call_options = FunctionCallOptions(config_proto=base_config) ContextSwitch = collections.namedtuple( @@ -897,21 +892,21 @@ def export_run_metadata(): return context().export_run_metadata() -def function_rewriter_config(rewriter_config): +def function_config_proto(config_proto): """Context manager for setting the grappler rewrite config. This config is used by Grappler when optimizing the function graph. Args: - rewriter_config: a rewriter_config_pb2.RewriterConfig proto or + config_proto: a `config_pb2.ConfigProto` proto or a serialized string of that proto or None. If None, the default instance - of rewriter_config_pb2.RewriterConfig will be used. + of `config_pb2.ConfigProto` will be used. Returns: A context manager. """ def _set_options_func(options): - options.rewriter_config_serialized = rewriter_config + options.config_proto_serialized = config_proto return context().function_call_options(_set_options_func) diff --git a/tensorflow/python/eager/def_function.py b/tensorflow/python/eager/def_function.py index cad6721c70..6bacd7a962 100644 --- a/tensorflow/python/eager/def_function.py +++ b/tensorflow/python/eager/def_function.py @@ -214,7 +214,7 @@ class PolymorphicFunction(object): python_function, name, input_signature=None, - autograph=False, + autograph=True, experimental_autograph_options=None): """Initializes a polymorphic function. @@ -503,7 +503,7 @@ class PolymorphicFunction(object): @tf_export("function", v1=[]) def function(func=None, input_signature=None, - autograph=False, + autograph=True, experimental_autograph_options=None): """Creates a callable TensorFlow graph from a Python function. @@ -552,9 +552,9 @@ def function(func=None, return x + tf.to_float(c) assert int(c) == 0 - assert f(1.0) == 3.0 + assert f(1.0) == 2.0 assert int(c) == 1 - assert f(1.0) == 4.0 + assert f(1.0) == 3.0 assert int(c) == 2 ``` diff --git a/tensorflow/python/eager/def_function_test.py b/tensorflow/python/eager/def_function_test.py index f0f71a219e..4100a10044 100644 --- a/tensorflow/python/eager/def_function_test.py +++ b/tensorflow/python/eager/def_function_test.py @@ -17,6 +17,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import functools from tensorflow.python.eager import backprop from tensorflow.python.eager import def_function @@ -149,9 +150,9 @@ class DefFunctionTest(test.TestCase): result = fn(3.0) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertAllEqual(sess.run(state[0]), 2.0) - self.assertAllEqual(sess.run(result), 6.0) + self.assertAllEqual(self.evaluate(result), 6.0) def testLegacyGraphModeVariablesNonTrivialInitializer(self): with ops.Graph().as_default(), self.test_session() as sess: @@ -168,9 +169,9 @@ class DefFunctionTest(test.TestCase): result = fn(3.0) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertAllEqual(sess.run(state[0]), 6.0) - self.assertAllEqual(sess.run(result), 18.0) + self.assertAllEqual(self.evaluate(result), 18.0) def testLegacyGraphModeInputDependentInitializerFails(self): with ops.Graph().as_default(): @@ -207,6 +208,18 @@ class DefFunctionTest(test.TestCase): m1 = MyModel() self.assertAllEqual(m1.apply(3.0), 6.0) + def test_functools_partial(self): + self.assertAllClose( + 3., + def_function.function(functools.partial(lambda x, y: x + y, 1.))( + constant_op.constant(2.))) + + def test_unspecified_default_argument(self): + wrapped = def_function.function( + lambda x, y=2: x + y, + input_signature=[tensor_spec.TensorSpec((), dtypes.int32)]) + self.assertEqual(3, wrapped(constant_op.constant(1)).numpy()) + def test_optimizer(self): x = constant_op.constant([[3., 4.]]) y = constant_op.constant([2.]) diff --git a/tensorflow/python/eager/execution_callbacks.py b/tensorflow/python/eager/execution_callbacks.py index 80ff4459d6..28b6b84a82 100644 --- a/tensorflow/python/eager/execution_callbacks.py +++ b/tensorflow/python/eager/execution_callbacks.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import contextlib import functools import numpy as np @@ -28,8 +29,13 @@ from tensorflow.python.eager import core from tensorflow.python.eager import execute from tensorflow.python.platform import tf_logging as logging -_DEFAULT_CALLBACK_ACTION = "raise" -_VALID_CALLBACK_ACTIONS = (None, "ignore", "print", "raise", "warn") +IGNORE = "ignore" +PRINT = "print" +RAISE = "raise" +WARN = "warn" + +_DEFAULT_CALLBACK_ACTION = RAISE +_VALID_CALLBACK_ACTIONS = (None, IGNORE, PRINT, RAISE, WARN) # TODO(cais): Consider moving this exception class to errors_impl.py. @@ -335,3 +341,38 @@ def seterr(inf_or_nan=None): functools.partial(inf_nan_callback, action=inf_or_nan)) return old_settings + + +@contextlib.contextmanager +def errstate(inf_or_nan=None): + """Context manager setting error state. + + Example: + ``` + c = tf.log(0.) # -inf + + with errstate(inf_or_nan="raise"): + tf.log(0.) # <-- Raises InfOrNanError. + ``` + + Args: + inf_or_nan: Set action for infinity (`inf`) and NaN (`nan`) values. + Possible values: `{IGNORE, PRINT, RAISE, WARN}`. + `IGNORE`: take no action when `inf` values appear. + `PRINT`: print a warning to `stdout`. + `RAISE`: raise an `InfOrNanError`. + `WARN`: print a warning using `tf.logging.warn`. + A value of `None` leads to no change in the action of the condition. + + Yields: + None. + + Raises: + ValueError: If the value of any keyword arguments is invalid. + """ + if not context.executing_eagerly(): + yield + else: + old_settings = seterr(inf_or_nan=inf_or_nan) + yield + seterr(**old_settings) diff --git a/tensorflow/python/eager/execution_callbacks_test.py b/tensorflow/python/eager/execution_callbacks_test.py new file mode 100644 index 0000000000..5594ab5f12 --- /dev/null +++ b/tensorflow/python/eager/execution_callbacks_test.py @@ -0,0 +1,55 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for eager execution_callbacks.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.eager import execution_callbacks +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import ops +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import test + + +def log_zero(): + """Computes `log(0.0)`.""" + return math_ops.log(constant_op.constant(0.)) + + +class ExecutionCallbacksTest(test.TestCase): + + def test_errstate_inf_raise(self): + with execution_callbacks.errstate(inf_or_nan=execution_callbacks.RAISE): + with self.assertRaises(execution_callbacks.InfOrNanError): + log_zero() + + def test_errstate_inf_ignore(self): + with execution_callbacks.errstate(inf_or_nan=execution_callbacks.IGNORE): + self.assertEqual(-float("inf"), log_zero().numpy()) + + def test_errstate_nesting(self): + with execution_callbacks.errstate(inf_or_nan=execution_callbacks.RAISE): + with execution_callbacks.errstate(inf_or_nan=execution_callbacks.IGNORE): + self.assertEqual(-float("inf"), log_zero().numpy()) + + with self.assertRaises(execution_callbacks.InfOrNanError): + log_zero() + + +if __name__ == "__main__": + ops.enable_eager_execution() + test.main() diff --git a/tensorflow/python/eager/function.py b/tensorflow/python/eager/function.py index c429dd359b..9d05a660b1 100644 --- a/tensorflow/python/eager/function.py +++ b/tensorflow/python/eager/function.py @@ -48,6 +48,7 @@ from tensorflow.python.ops import custom_gradient from tensorflow.python.ops import functional_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.platform import tf_logging as logging from tensorflow.python.util import compat from tensorflow.python.util import nest from tensorflow.python.util import tf_decorator @@ -66,6 +67,11 @@ WHITELIST_FUNCTION_ATTRIBUTE_REGEX = [ BACKWARD_FUNCTION_ATTRIBUTE_NAME ] +CacheKey = collections.namedtuple("CacheKey", [ + "input_signature", "parent_graph", "device_functions", "colocation_stack", + "uses_xla" +]) + def _parse_func_attrs(attributes): """Convert the keyword arguments into function_def attributes. @@ -83,8 +89,8 @@ def _parse_func_attrs(attributes): """ attrs = {} for key, value in attributes.items(): - if not any([re.match(reg, key) - for reg in WHITELIST_FUNCTION_ATTRIBUTE_REGEX]): + if not any(re.match(reg, key) + for reg in WHITELIST_FUNCTION_ATTRIBUTE_REGEX): raise ValueError("Attribute name is not whitelisted. " "Whitelisted: prefix %s, got: %s" % (WHITELIST_FUNCTION_ATTRIBUTE_REGEX, key)) @@ -260,7 +266,7 @@ class _EagerDefinedFunction(object): f=self, tout=self._output_types, executing_eagerly=executing_eagerly, - config=function_call_options.rewriter_config_serialized, + config=function_call_options.config_proto_serialized, executor_type=function_call_options.executor_type) if executing_eagerly: @@ -418,7 +424,10 @@ class Function(object): if (tape.should_record(tensor_inputs) or tape.should_record(self._captured_inputs)): - return self._backprop_call(args) + if context.executing_eagerly(): + return self._eager_backprop_call(args) + else: + return self._backprop_call_with_delayed_rewrite(args) # Only need to override the gradient in graph mode and when we have outputs. if context.executing_eagerly() or not self.outputs: @@ -444,37 +453,34 @@ class Function(object): name: The name to register the gradient as. """ @ops.RegisterGradient(name) - def grad_fn(op, *doutputs): # pylint: disable=unused-variable - """Gradients of this function.""" - if self._backward_graph_function is None: - self._construct_backprop_function() + def _registered_grad_fn(op, *doutputs): # pylint: disable=unused-variable + return self._grad_fn(op, *doutputs) - # pylint: disable=protected-access - self._forward_function.add_to_graph(op.graph) - num_inference_outputs = self._inference_function._num_outputs - - # Rewrite an inference call op to be a forward call op - if op.get_attr("f").name.encode() == self._inference_function.name: - func = attr_value_pb2.AttrValue( - func=attr_value_pb2.NameAttrList( - name=self._forward_function.name)) - op._set_attr("f", func) - types = attr_value_pb2.AttrValue.ListValue( - type=self._forward_function._output_types) - op._set_attr("Tout", attr_value_pb2.AttrValue(list=types)) - for i in range( - num_inference_outputs, len(self._forward_function._output_types)): - t = ops.Tensor(op, i, self._forward_function._output_types[i]) - t.set_shape(self._forward_function._output_shapes[i]) - func_graph_output = self._forward_function._func_graph_outputs[i] - custom_gradient.copy_handle_data(func_graph_output, t) - op._outputs.append(t) - # pylint: enable=protected-access - # Compute the gradients using the side outputs - side_outputs = op.outputs[num_inference_outputs:] - args = list(doutputs[:num_inference_outputs]) + list(side_outputs) - return self._backward_graph_function._call_flat( # pylint: disable=protected-access - (a for a in args if a is not None)) + def _grad_fn(self, op, *doutputs): + """Gradients of this function.""" + if self._backward_graph_function is None: + self._construct_backprop_function() + + # pylint: disable=protected-access + self._forward_function.add_to_graph(op.graph) + num_inference_outputs = self._inference_function._num_outputs + + # Rewrite an inference call op to be a forward call op + if op.get_attr("f").name.encode() == self._inference_function.name: + op._set_func_attr("f", self._forward_function.name) + op._set_type_list_attr("Tout", self._forward_function._output_types) + op._add_outputs( + self._forward_function._output_types[num_inference_outputs:], + self._forward_function._output_shapes[num_inference_outputs:]) + for i in range(num_inference_outputs, len(op.outputs)): + func_graph_output = self._forward_function._func_graph_outputs[i] + custom_gradient.copy_handle_data(func_graph_output, op.outputs[i]) + # pylint: enable=protected-access + # Compute the gradients using the side outputs + side_outputs = op.outputs[num_inference_outputs:] + args = list(doutputs[:num_inference_outputs]) + list(side_outputs) + return self._backward_graph_function._call_flat( # pylint: disable=protected-access + (a for a in args if a is not None)) @property def name(self): @@ -617,10 +623,13 @@ class Function(object): self._func_graph.outputs + backwards_graph_captures, forward_function_attr) - def _backprop_call(self, args): + def _eager_backprop_call(self, args): """Calls the forward function and records the result on a tape. - (Only records results on a tape if the function has outputs) + This method fully constructs the forward and backward functions before + calling the function and recording them on the tape. + + (Only records results on a tape if the function has outputs). Args: args: All inputs to the function, including resolved captured inputs @@ -662,6 +671,46 @@ class Function(object): args, backward_function) return self._build_call_outputs(real_outputs) + def _backprop_call_with_delayed_rewrite(self, args): + """Calls the inference function and records the result on a tape. + + The recorded backwards function will construct the backwards graph and + rewrite the inference function to the forward function. This only happens + if the recorded backwards function ends up being used to compute gradients. + + This approach avoids constructing unnecessary graphs, but it only works if + we are calling this function when not executing eagerly. + + (Only records results on a tape if the function has outputs) + + Args: + args: All inputs to the function, including resolved captured inputs + + Returns: + The call output. + """ + ctx = context.context() + + if not self._gradient_name: + self._gradient_name = "PartitionedCall-%s" % ops.uid() + self._register_gradient(self._gradient_name) + with ops.get_default_graph().gradient_override_map( + {"PartitionedCall": self._gradient_name, + "StatefulPartitionedCall": self._gradient_name}): + outputs = self._inference_function.call(ctx, args) + + if isinstance(outputs, ops.Operation) or outputs is None: + return outputs + + call_op = outputs[0].op + + def backward_function(*args): + return self._grad_fn(call_op, *args) + + tape.record_operation(self._inference_function.signature.name, outputs, + args, backward_function) + return self._build_call_outputs(outputs) + def _build_call_outputs(self, result): """Maps the fdef output list to actual output structure. @@ -724,7 +773,7 @@ class PolymorphicFunction(object): name, input_signature=None, attributes=None, - autograph=False): + autograph=True): """Initializes a polymorphic function. Args: @@ -927,17 +976,17 @@ class PolymorphicFunction(object): """Computes the cache key given inputs and execution context.""" if self._input_signature is None: inputs = (args, kwargs) if kwargs else args - cache_key = pywrap_tensorflow.TFE_Py_EncodeArg(inputs) + input_signature = pywrap_tensorflow.TFE_Py_EncodeArg(inputs) else: del args, kwargs - cache_key = self._flat_input_signature + input_signature = self._flat_input_signature ctx = context.context() with ops.init_scope(): # The graph, or whether we're executing eagerly, should be a part of the # cache key so we don't improperly capture tensors such as variables. executing_eagerly = ctx.executing_eagerly() - execution_context = executing_eagerly or ops.get_default_graph() + parent_graph = None if executing_eagerly else ops.get_default_graph() # pylint: disable=protected-access default_graph = ops.get_default_graph() @@ -966,8 +1015,8 @@ class PolymorphicFunction(object): else: device_functions = () # pylint: enable=protected-access - return (cache_key, execution_context, device_functions, colocation_stack, - uses_xla) + return CacheKey(input_signature, parent_graph, device_functions, + colocation_stack, uses_xla) def _canonicalize_function_inputs(self, *args, **kwargs): """Canonicalizes `args` and `kwargs`. @@ -1039,16 +1088,21 @@ class PolymorphicFunction(object): return inputs, kwargs else: assert not kwargs + signature_relevant_inputs = inputs[:len(self._input_signature)] try: - nest.assert_same_structure(self._input_signature, inputs) + nest.assert_same_structure(self._input_signature, + signature_relevant_inputs) except (ValueError, TypeError): raise ValueError("Structure of Python function inputs does not match " "input_signature.") - if any(not pywrap_tensorflow.IsTensor(arg) for arg in flat_inputs): + signature_inputs_flat = nest.flatten(signature_relevant_inputs) + if any(not pywrap_tensorflow.IsTensor(arg) + for arg in signature_inputs_flat): raise ValueError("When input_signature is provided, all inputs to " "the Python function must be Tensors.") if any(not spec.is_compatible_with(other) - for spec, other in zip(self._flat_input_signature, flat_inputs)): + for spec, other in zip(self._flat_input_signature, + signature_inputs_flat)): raise ValueError("Python inputs incompatible with input_signature: " "inputs (%s), input_signature (%s)" % (str(inputs), str(self._input_signature))) @@ -1083,6 +1137,9 @@ class PolymorphicFunction(object): "must be hashable.") if graph_function is None: + logging.vlog(1, + "Creating new FuncGraph for Python function %r (key: %r)", + self._python_function, cache_key) if self._input_signature is None: arglen = len(args) else: @@ -1137,7 +1194,7 @@ def validate_signature(signature): "a possibly nested sequence of TensorSpec objects.") -def defun(func=None, input_signature=None, autograph=False): +def defun(func=None, input_signature=None, autograph=True): """Compiles a Python function into a callable TensorFlow graph. `defun` (short for "define function") trace-compiles a Python function @@ -1470,7 +1527,7 @@ def defun(func=None, input_signature=None, autograph=False): def defun_with_attributes(func=None, input_signature=None, attributes=None, - autograph=False): + autograph=True): """Compiles a Python function into a callable TensorFlow graph. This function supports adding extra function attributes. See detailed diff --git a/tensorflow/python/eager/function_gradients_test.py b/tensorflow/python/eager/function_gradients_test.py new file mode 100644 index 0000000000..9b83f57089 --- /dev/null +++ b/tensorflow/python/eager/function_gradients_test.py @@ -0,0 +1,756 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from absl.testing import parameterized + +from tensorflow.core.protobuf import config_pb2 +from tensorflow.python.eager import backprop +from tensorflow.python.eager import context +from tensorflow.python.eager import def_function +from tensorflow.python.eager import function +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import gradients_impl +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import variable_scope +from tensorflow.python.ops import variables +from tensorflow.python.platform import test +from tensorflow.python.util import nest + + +class FunctionGradientsTest(test.TestCase, parameterized.TestCase): + + def testGraphModeWithGradients(self): + v = resource_variable_ops.ResourceVariable(1.0, name='v') + + @def_function.function + def step(): + def inner(): + return v * v + + return backprop.implicit_grad(inner)()[0][0] + + self.assertAllEqual(step(), 2.0) + + def testGraphGradientVariable(self): + with ops.Graph().as_default(), self.cached_session(): + v = variables.Variable(1.0) + + @def_function.function + def f(): + return 2.0 * v + + node = f() + grads, = gradients_impl.gradients(node, v) + v.initializer.run() + self.assertAllEqual(grads.eval(), 2.0) + self.assertEqual(grads.shape, v.shape) + + def testSymGradGatherNd(self): + with ops.Graph().as_default(), self.cached_session() as sess: + + @def_function.function + def f(x): + return array_ops.gather_nd(x, [[0]]) + + c = constant_op.constant([[2.]]) + f_c = f(c) + g, = gradients_impl.gradients(f_c, c) + self.assertAllEqual(self.evaluate(g).values, [[1.0]]) + + def testNoSymGradNestedDefun(self): + + @def_function.function + def outer(): + + @def_function.function + def f(x): + return array_ops.gather_nd(x, [[0]]) + + c = constant_op.constant([[2.]]) + f_c = f(c) + g, = gradients_impl.gradients(f_c, c) + self.assertIsInstance(g, ops.IndexedSlices) + + outer() + + def testGraphFunctionWithGradients(self): + v = resource_variable_ops.ResourceVariable(1.0, name='v') + + @def_function.function + def step(): + def inner(): + return v * v + + return backprop.implicit_grad(inner)()[0][0] + + step_op = step.get_concrete_function() + self.assertEqual(step_op.output_dtypes, dtypes.float32) + self.assertEqual(step_op.output_shapes, tensor_shape.TensorShape([])) + self.assertAllEqual(step_op(), 2.0) + + @test_util.run_in_graph_and_eager_modes() + def testDefunCondGradient(self): + + @def_function.function + def f(x): + return control_flow_ops.cond(x > 0.5, lambda: 2 * x, lambda: 3 * x) + + with backprop.GradientTape() as t: + x = constant_op.constant(1.0) + t.watch(x) + y = f(x) + self.assertAllEqual(self.evaluate(t.gradient(y, x)), 2.0) + + @test_util.run_in_graph_and_eager_modes() + def testGraphLoopGradient(self): + + @def_function.function + def f(x): + return control_flow_ops.while_loop(lambda _, i: i < 2, + lambda x, i: (2*x, i + 1), + [x, 0])[0] + + with backprop.GradientTape() as t: + x = constant_op.constant(1.0) + t.watch(x) + y = f(x) + self.assertAllEqual(self.evaluate(t.gradient(y, x)), 4.0) + + def testDefunDifferentiable(self): + v = resource_variable_ops.ResourceVariable(1.0) + + @def_function.function + def f(): + return v * v + + self.assertAllEqual(backprop.implicit_grad(f)()[0][0], 2.0) + + def testDefunCanBeDifferentiatedTwice(self): + v = resource_variable_ops.ResourceVariable(1.0) + + @def_function.function + def f(): + return v * v + + self.assertAllEqual(backprop.implicit_grad(f)()[0][0], 2.0) + # Ensure that v is watched again. + self.assertAllEqual(backprop.implicit_grad(f)()[0][0], 2.0) + + def testSymbolicGradientVariableNoneNotZerosLike(self): + with ops.Graph().as_default(): + v = variables.Variable(1.0) + + @def_function.function + def f(x, v): + v.read_value() + return x * x + + x = constant_op.constant(1.0) + l = f(x, v) + _, dv = gradients_impl.gradients(l, [x, v]) + with self.cached_session(): + v.initializer.run() + self.assertEqual(dv, None) + + def testDefunCallBackprop(self): + + @def_function.function + def f(x): + return math_ops.add(x, x) + + @def_function.function + def g(x): + return backprop.gradients_function(f, [0])(x)[0] + + self.assertAllEqual(2, g(constant_op.constant(2.))) + + @test_util.run_deprecated_v1 + def testGraphModeEagerGradError(self): + with context.graph_mode(): + def f(): + x = variable_scope.get_variable( + 'v', initializer=constant_op.constant(1.0)) + return x * constant_op.constant(2.0) + + with self.assertRaisesRegexp(ValueError, + 'No trainable variables were accessed'): + backprop.implicit_val_and_grad(f)() + + def testDefunCallBackpropUsingSameObjectForMultipleArguments(self): + + @def_function.function + def g(x): + return backprop.gradients_function(math_ops.multiply, [0, 1])(x, x) + + def np_g(x): + return [d.numpy() for d in g(x)] + + x = constant_op.constant(1.) + self.assertAllEqual([1., 1.], np_g(x)) + self.assertAllEqual([1., 1.], np_g(1.)) + + def testGradientTensorConversionWithDefun(self): + three = resource_variable_ops.ResourceVariable(3.0, name='v') + + @def_function.function + def f(x): + return math_ops.add(x, three) + + def g(x): + return f(x) + + g = backprop.implicit_grad(g)(constant_op.constant(1.0))[0][0] + self.assertAllEqual(g, 1.0) + + def testGradient(self): + matmul = def_function.function(math_ops.matmul) + + def sq(x): + return matmul(x, x, transpose_a=True) + + t = constant_op.constant([[1.0, 2.0], [3.0, 4.0]]) + grad_t, = backprop.gradients_function(sq, [0])(t) + self.assertAllEqual(grad_t, [[6, 6], [14, 14]]) + + def testGradientInFunction(self): + + @def_function.function + def f(x): + return backprop.gradients_function(lambda y: y * y, [0])(x)[0] + + self.assertAllEqual(f(constant_op.constant(1.0)), 2.0) + + def testGradientOfGatherWithDefun(self): + v = resource_variable_ops.ResourceVariable([0.0, 1.0, 2.0]) + + def sum_gather(): + return math_ops.reduce_sum(array_ops.gather(v, [1, 2])) + + grad_fn = backprop.implicit_grad(sum_gather) + gradient = grad_fn() + defun_grad_fn = backprop.implicit_grad(def_function.function(sum_gather)) + defun_gradient = defun_grad_fn() + self.assertEqual(len(gradient), len(defun_gradient)) + + gradient = gradient[0][0] + defun_gradient = defun_gradient[0][0] + self.assertAllEqual(gradient.values, defun_gradient.values) + self.assertAllEqual(gradient.indices, defun_gradient.indices) + self.assertAllEqual(gradient.dense_shape, defun_gradient.dense_shape) + + def testDifferentiableFunctionNoneOutputs(self): + + @def_function.function + def my_function(x): + return x, None + + def wrapper(x): + return my_function(x)[0] + + g = backprop.gradients_function(wrapper, [0])(constant_op.constant(0.0)) + self.assertAllEqual(g[0], 1.) + + @def_function.function + def foo(a): + return None, a * a + + x = constant_op.constant(5.0) + with backprop.GradientTape() as tp: + tp.watch(x) + none, r = foo(x) + g = tp.gradient(r, x) + + self.assertIs(none, None) + self.assertAllEqual(r, 25.0) + self.assertAllEqual(g, 2 * 5.0) + + @test_util.run_in_graph_and_eager_modes + def testNestedDifferentiableFunction(self): + @def_function.function + def inner_fn(a, b): + return a * math_ops.add(a, b) + + @def_function.function + def outer_fn(x): + return inner_fn(x, 1.0) + + x = constant_op.constant(5.0) + with backprop.GradientTape() as tp: + tp.watch(x) + result = outer_fn(x) + grad = tp.gradient(result, x) + + self.assertAllEqual(grad, 2 * 5.0 + 1.0) + + @test_util.run_in_graph_and_eager_modes + def testDeeplyNestedDifferentiableFunction(self): + @def_function.function + def inner_inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def inner_fn(a, b): + return inner_inner_fn(a, b) + + @def_function.function + def middle_fn(a, b): + return a * inner_fn(a, b) + + @def_function.function + def outer_fn(x): + return middle_fn(x, 1.0) + + x = constant_op.constant(5.0) + with backprop.GradientTape() as tp: + tp.watch(x) + result = outer_fn(x) + grad = tp.gradient(result, x) + + self.assertAllEqual(grad, 2 * 5.0 + 1.0) + + @test_util.run_in_graph_and_eager_modes + def testDeeplyNestedDifferentiableFunctionWithMultipleGradCalls(self): + @def_function.function + def inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def middle_fn(a, b): + return math_ops.mul(a, inner_fn(a, b)) + + @def_function.function + def outer_fn(x): + return middle_fn(x, 3.0) + + x = constant_op.constant(5.0) + self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) + + with backprop.GradientTape() as tp: + tp.watch(x) + result = outer_fn(x) + grad = tp.gradient(result, x) + + self.assertAllEqual(grad, 2 * 5.0 + 3.0) + self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) + self.assertAllEqual(middle_fn(3.0, x), 3.0 * (3.0 + 5.0)) + + with backprop.GradientTape() as tp: + tp.watch(x) + result = outer_fn(x) + grad = tp.gradient(result, x) + + self.assertAllEqual(grad, 2 * 5.0 + 3.0) + + y = constant_op.constant(4.0) + with backprop.GradientTape() as tp: + tp.watch(y) + result = outer_fn(y) + grad = tp.gradient(result, y) + + self.assertAllEqual(grad, 2 * 4.0 + 3.0) + + with backprop.GradientTape() as tp: + tp.watch(y) + result = inner_fn(y, y) + grad = tp.gradient(result, y) + + self.assertAllEqual(grad, 2.0) + + @test_util.run_in_graph_and_eager_modes + def testDeeplyNestedDifferentiableFunctionGradientTapeInDefun(self): + @def_function.function + def inner_inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def inner_fn(a, b): + return inner_inner_fn(a, b) + + @def_function.function + def middle_fn(a, b): + return a * inner_fn(a, b) + + @def_function.function + def outer_fn(x): + with backprop.GradientTape() as tp: + tp.watch(x) + result = middle_fn(x, 1.0) + grad = tp.gradient(result, x) + return grad + + x = constant_op.constant(5.0) + grad = outer_fn(x) + self.assertAllEqual(grad, 2 * 5.0 + 1.0) + + @test_util.run_in_graph_and_eager_modes + def testDeeplyNestedDifferentiableFunctionGradientTapeInNestedDefun(self): + @def_function.function + def inner_inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def inner_fn(a, b): + return inner_inner_fn(a, b) + + @def_function.function + def middle_fn(a, b): + return a * inner_fn(a, b) + + @def_function.function + def almost_outer_fn(x): + with backprop.GradientTape() as tp: + tp.watch(x) + result = middle_fn(x, 1.0) + grad = tp.gradient(result, x) + return grad + + @def_function.function + def outer_fn(x): + return almost_outer_fn(x) + + x = constant_op.constant(5.0) + grad = outer_fn(x) + self.assertAllEqual(grad, 2 * 5.0 + 1.0) + + @test_util.run_in_graph_and_eager_modes + def testDeeplyNestedDifferentiableFunctionGradientTapeInMultNestedDefun(self): + @def_function.function + def inner_inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def inner_fn(a, b): + return inner_inner_fn(a, b) + + @def_function.function + def middle_fn(a, b): + return a * inner_fn(a, b) + + @def_function.function + def almost_outer_fn(x): + with backprop.GradientTape() as tp: + tp.watch(x) + result = middle_fn(x, 1.0) + grad = tp.gradient(result, x) + return grad + + @def_function.function + def outer_fn(x): + return almost_outer_fn(x) + + @def_function.function + def outer_outer_fn(x): + return outer_fn(x) + + x = constant_op.constant(5.0) + grad = outer_outer_fn(x) + self.assertAllEqual(grad, 2 * 5.0 + 1.0) + + @test_util.run_in_graph_and_eager_modes + def testDeeplyNestedDifferentiableFunctionTFGradientInDefun(self): + @def_function.function + def inner_inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def inner_fn(a, b): + return inner_inner_fn(a, b) + + @def_function.function + def middle_fn(a, b): + return a * inner_fn(a, b) + + @def_function.function + def outer_fn(x): + result = middle_fn(x, 1.0) + return gradients_impl.gradients(result, [x])[0] + + x = constant_op.constant(5.0) + grad = outer_fn(x) + self.assertAllEqual(grad, 2 * 5.0 + 1.0) + + @test_util.run_in_graph_and_eager_modes + def testDeeplyNestedDifferentiableFunctionTFGradientInNestedDefun(self): + @def_function.function + def inner_inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def inner_fn(a, b): + return inner_inner_fn(a, b) + + @def_function.function + def middle_fn(a, b): + return a * inner_fn(a, b) + + @def_function.function + def almost_outer_fn(x): + result = middle_fn(x, 1.0) + return gradients_impl.gradients(result, [x])[0] + + @def_function.function + def outer_fn(x): + return almost_outer_fn(x) + + x = constant_op.constant(5.0) + grad = outer_fn(x) + self.assertAllEqual(grad, 2 * 5.0 + 1.0) + + @test_util.run_in_graph_and_eager_modes + def testDeeplyNestedDifferentiableFunctionTFGradientInMultNestedDefun(self): + @def_function.function + def inner_inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def inner_fn(a, b): + return inner_inner_fn(a, b) + + @def_function.function + def middle_fn(a, b): + return a * inner_fn(a, b) + + @def_function.function + def almost_outer_fn(x): + result = middle_fn(x, 1.0) + return gradients_impl.gradients(result, [x])[0] + + @def_function.function + def outer_fn(x): + return almost_outer_fn(x) + + @def_function.function + def outer_outer_fn(x): + return outer_fn(x) + + x = constant_op.constant(5.0) + grad = outer_outer_fn(x) + self.assertAllEqual(grad, 2 * 5.0 + 1.0) + + def testDeeplyNestedDifferentiableFunctionWithVariable(self): + var = variables.Variable(constant_op.constant(1.0)) + + @def_function.function + def inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def middle_fn(a, b): + return a * inner_fn(a, b) + + @def_function.function + def outer_fn(x): + return middle_fn(x, var) + + x = constant_op.constant(5.0) + with backprop.GradientTape() as tp: + tp.watch(x) + result = outer_fn(x) + grad = tp.gradient(result, x) + + self.assertAllEqual(grad, 2 * 5.0 + 1.0) + + def testDeeplyNestedDifferentiableFunctionWithVariableMultipleGradCalls(self): + v = variables.Variable(constant_op.constant(3.0)) + + @def_function.function + def inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def middle_fn(a, b): + return math_ops.mul(a, inner_fn(a, b)) + + @def_function.function + def outer_fn(x): + return middle_fn(x, v) + + x = constant_op.constant(5.0) + self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) + + with backprop.GradientTape() as tp: + tp.watch(x) + result = outer_fn(x) + grad = tp.gradient(result, x) + + self.assertAllEqual(grad, 2 * 5.0 + 3.0) + self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) + self.assertAllEqual(middle_fn(v, x), 3.0 * (3.0 + 5.0)) + + with backprop.GradientTape() as tp: + tp.watch(x) + result = outer_fn(x) + grad = tp.gradient(result, x) + + self.assertAllEqual(grad, 2 * 5.0 + 3.0) + + y = constant_op.constant(4.0) + with backprop.GradientTape() as tp: + tp.watch(y) + result = outer_fn(y) + grad = tp.gradient(result, y) + + self.assertAllEqual(grad, 2 * 4.0 + 3.0) + + v.assign(constant_op.constant(1.5)) + with backprop.GradientTape() as tp: + tp.watch(y) + result = outer_fn(y) + grad = tp.gradient(result, y) + + self.assertAllEqual(grad, 2 * 4.0 + 1.5) + + with backprop.GradientTape() as tp: + tp.watch(y) + result = inner_fn(y, v) + grad = tp.gradient(result, y) + + self.assertAllEqual(grad, 1.0) + + def testDeeplyNestedDifferentiableFunctionWithVariableMultipleTFGrads(self): + with context.graph_mode(), self.cached_session(): + v = resource_variable_ops.ResourceVariable(3.0) + v.initializer.run() + + @def_function.function + def inner_fn(a, b): + return math_ops.add(a, b) + + @def_function.function + def middle_fn(a, b): + return math_ops.mul(a, inner_fn(a, b)) + + @def_function.function + def outer_fn(x): + return middle_fn(x, v) + + x = constant_op.constant(5.0) + self.assertAllEqual(outer_fn(x).eval(), 5.0 * (5.0 + 3.0)) + + grad, = gradients_impl.gradients(outer_fn(x), x) + + self.assertAllEqual(grad, 2 * 5.0 + 3.0) + self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) + self.assertAllEqual(middle_fn(v, x), 3.0 * (3.0 + 5.0)) + + grad, = gradients_impl.gradients(outer_fn(x), x) + + self.assertAllEqual(grad, 2 * 5.0 + 3.0) + + y = constant_op.constant(4.0) + grad, = gradients_impl.gradients(outer_fn(y), y) + self.assertAllEqual(grad, 2 * 4.0 + 3.0) + + self.evaluate(v.assign(constant_op.constant(1.5))) + grad, = gradients_impl.gradients(outer_fn(y), y) + + self.assertAllEqual(grad, 2 * 4.0 + 1.5) + + grad, = gradients_impl.gradients(inner_fn(y, v), y) + self.assertAllEqual(grad, 1.0) + + def testNestedDifferentiableFunctionNoneOutputs(self): + @def_function.function + def foo(a, b): + return None, a * math_ops.add(a, b), None, 2*a + + @def_function.function + def bar(x): + return foo(x, 1.0) + + x = constant_op.constant(5.0) + with backprop.GradientTape(persistent=True) as tp: + tp.watch(x) + none1, r1, none2, r2 = bar(x) + g1 = tp.gradient(r1, x) + g2 = tp.gradient(r2, x) + + self.assertAllEqual(r1, 30.0) + self.assertAllEqual(r2, 10.0) + self.assertIs(none1, None) + self.assertIs(none2, None) + self.assertAllEqual(g1, 2 * 5.0 + 1.0) + self.assertAllEqual(g2, 2.0) + + def testGradientWithKeywordArguments(self): + matmul = def_function.function(math_ops.matmul) + + def sq(x): + return matmul(a=x, b=x, transpose_a=True) + + t = constant_op.constant([[1.0, 2.0], [3.0, 4.0]]) + grad_t, = backprop.gradients_function(sq, [0])(t) + self.assertAllEqual(grad_t, [[6, 6], [14, 14]]) + + with backprop.GradientTape(persistent=True) as tape: + tape.watch(t) + one = matmul(t, b=t, transpose_a=True) + two = matmul(b=t, a=t, transpose_a=True) + three = matmul(a=t, b=t, transpose_a=True) + + for output in [one, two, three]: + self.assertAllEqual(tape.gradient(output, t), [[6, 6], [14, 14]]) + + def testGradientInFunctionWithKeywordArguments(self): + + @def_function.function + def f(x): + return backprop.gradients_function(lambda y: y * y, [0])(x)[0] + + self.assertAllEqual(f(x=constant_op.constant(1.0)), 2.0) + + @test_util.run_in_graph_and_eager_modes + def testBackwardNone(self): + model = variables.Variable(1.0, name='model') + count = variables.Variable(0) + + @function.defun + def forward_pass(value): + count.assign_add(1) + residuals = value - model + loss = 0.5 * math_ops.reduce_mean(math_ops.pow(residuals, 2)) + # Note: count is an integer, so its doutput will be None + return loss, count + + def reduce_fn(x): + if context.executing_eagerly(): + with backprop.GradientTape() as t: + loss, count = forward_pass(x) + return t.gradient(loss, model), count + loss, count = forward_pass(x) + grad_only = gradients_impl.gradients(loss, model) + return grad_only, count + + g, _ = reduce_fn(constant_op.constant([7.0])) + + self.evaluate(variables.global_variables_initializer()) + self.assertAllEqual(nest.flatten(self.evaluate(g)), [-6.0]) + + +if __name__ == '__main__': + ops.enable_eager_execution( + config=config_pb2.ConfigProto(device_count={'CPU': 4})) + test.main() diff --git a/tensorflow/python/eager/function_test.py b/tensorflow/python/eager/function_test.py index 2af08689f8..71afbd24d8 100644 --- a/tensorflow/python/eager/function_test.py +++ b/tensorflow/python/eager/function_test.py @@ -29,7 +29,6 @@ import numpy from tensorflow.core.protobuf import config_pb2 from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.python import keras -from tensorflow.python.eager import backprop from tensorflow.python.eager import context from tensorflow.python.eager import def_function from tensorflow.python.eager import function @@ -48,7 +47,6 @@ from tensorflow.python.layers import convolutional from tensorflow.python.ops import array_ops from tensorflow.python.ops import clip_ops from tensorflow.python.ops import control_flow_ops -from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import init_ops from tensorflow.python.ops import list_ops from tensorflow.python.ops import math_ops @@ -102,10 +100,10 @@ class FunctionTest(test.TestCase, parameterized.TestCase): _ = x * y return x + y - # The default config allows everything. - rewrites = rewriter_config_pb2.RewriterConfig() + # The default config allows all rewrites. + config_proto = config_pb2.ConfigProto() - with context.function_rewriter_config(rewrites): + with context.function_config_proto(config_proto): t = constant_op.constant(1.0) self.assertAllEqual(add(t, t).numpy(), 2.0) @@ -149,31 +147,22 @@ class FunctionTest(test.TestCase, parameterized.TestCase): out = a_times_b(pair({'a': t}, {'b': t})) self.assertAllEqual(out, math_ops.matmul(t, t).numpy()) - def testGraphModeWithGradients(self): - v = resource_variable_ops.ResourceVariable(1.0, name='v') - - @def_function.function - def step(): - def inner(): - return v * v - - return backprop.implicit_grad(inner)()[0][0] + def testNestedOutputsGraphMode(self): + matmul = def_function.function(math_ops.matmul) - self.assertAllEqual(step(), 2.0) + pair = collections.namedtuple('pair', ['a', 'b']) - def testGraphGradientVariable(self): - with ops.Graph().as_default(), self.cached_session(): - v = variables.Variable(1.0) + @def_function.function() + def pairs_mul(pair_a, pair_b): + return pair(matmul(pair_a.a, pair_b.a), matmul(pair_a.b, pair_b.b)) - @def_function.function - def f(): - return 2.0 * v + a = constant_op.constant([[1.0, 2.0], [1.0, 2.0]]) + b = constant_op.constant([[3.0, 4.0], [3.0, 4.0]]) - node = f() - grads, = gradients_impl.gradients(node, v) - v.initializer.run() - self.assertAllEqual(grads.eval(), 2.0) - self.assertEqual(grads.shape, v.shape) + out = pairs_mul(pair(a, b), pair(b, a)) + expected = pair(math_ops.matmul(a, b).numpy(), + math_ops.matmul(b, a).numpy()) + self.assertAllClose(out, expected) def testGraphEagerIsolation(self): @@ -314,34 +303,6 @@ class FunctionTest(test.TestCase, parameterized.TestCase): random_seed.set_random_seed(1) self.assertAllEqual(f(), x) - def testSymGradGatherNd(self): - with ops.Graph().as_default(), self.cached_session() as sess: - - @def_function.function - def f(x): - return array_ops.gather_nd(x, [[0]]) - - c = constant_op.constant([[2.]]) - f_c = f(c) - g, = gradients_impl.gradients(f_c, c) - self.assertAllEqual(sess.run(g).values, [[1.0]]) - - def testNoSymGradNestedDefun(self): - - @def_function.function - def outer(): - - @def_function.function - def f(x): - return array_ops.gather_nd(x, [[0]]) - - c = constant_op.constant([[2.]]) - f_c = f(c) - g, = gradients_impl.gradients(f_c, c) - self.assertIsInstance(g, ops.IndexedSlices) - - outer() - def testNestedInputsGraphFunction(self): matmul = def_function.function(math_ops.matmul) @@ -378,21 +339,6 @@ class FunctionTest(test.TestCase, parameterized.TestCase): self.assertAllEqual(a, math_ops.matmul(t, t).numpy()) self.assertAllEqual(b['b'].numpy(), 1.0) - def testGraphFunctionWithGradients(self): - v = resource_variable_ops.ResourceVariable(1.0, name='v') - - @def_function.function - def step(): - def inner(): - return v * v - - return backprop.implicit_grad(inner)()[0][0] - - step_op = step.get_concrete_function() - self.assertEqual(step_op.output_dtypes, dtypes.float32) - self.assertEqual(step_op.output_shapes, tensor_shape.TensorShape([])) - self.assertAllEqual(step_op(), 2.0) - def testGraphFunctionNoneOutput(self): @def_function.function def fn(unused_a, unused_b): @@ -404,34 +350,6 @@ class FunctionTest(test.TestCase, parameterized.TestCase): self.assertEqual(fn_op.output_shapes, None) self.assertAllEqual(fn_op(x, x), None) - @test_util.run_in_graph_and_eager_modes() - def testDefunCondGradient(self): - - @def_function.function - def f(x): - return control_flow_ops.cond(x > 0.5, lambda: 2 * x, lambda: 3 * x) - - with backprop.GradientTape() as t: - x = constant_op.constant(1.0) - t.watch(x) - y = f(x) - self.assertAllEqual(self.evaluate(t.gradient(y, x)), 2.0) - - @test_util.run_in_graph_and_eager_modes() - def testGraphLoopGradient(self): - - @def_function.function - def f(x): - return control_flow_ops.while_loop(lambda _, i: i < 2, - lambda x, i: (2*x, i + 1), - [x, 0])[0] - - with backprop.GradientTape() as t: - x = constant_op.constant(1.0) - t.watch(x) - y = f(x) - self.assertAllEqual(self.evaluate(t.gradient(y, x)), 4.0) - def testDefunNumpyArraysConvertedToTensors(self): def f(x): @@ -625,27 +543,7 @@ class FunctionTest(test.TestCase, parameterized.TestCase): self.assertIsInstance( self.v, resource_variable_ops.ResourceVariable) - def testDefunDifferentiable(self): - v = resource_variable_ops.ResourceVariable(1.0) - - @def_function.function - def f(): - return v * v - - self.assertAllEqual(backprop.implicit_grad(f)()[0][0], 2.0) - - def testDefunCanBeDifferentiatedTwice(self): - v = resource_variable_ops.ResourceVariable(1.0) - - @def_function.function - def f(): - return v * v - - self.assertAllEqual(backprop.implicit_grad(f)()[0][0], 2.0) - # Ensure that v is watched again. - self.assertAllEqual(backprop.implicit_grad(f)()[0][0], 2.0) - - def testRunMetadata(self): + def disabled_testRunMetadata(self): @def_function.function def f(x): @@ -683,23 +581,7 @@ class FunctionTest(test.TestCase, parameterized.TestCase): variables.global_variables_initializer().run() call = def_function.function(o.call) op = call() - self.assertAllEqual(sess.run(op), 2.0) - - def testSymbolicGradientVariableNoneNotZerosLike(self): - with ops.Graph().as_default(): - v = variables.Variable(1.0) - - @def_function.function - def f(x, v): - v.read_value() - return x * x - - x = constant_op.constant(1.0) - l = f(x, v) - _, dv = gradients_impl.gradients(l, [x, v]) - with self.cached_session(): - v.initializer.run() - self.assertEqual(dv, None) + self.assertAllEqual(self.evaluate(op), 2.0) def testGraphModeManyFunctions(self): with ops.Graph().as_default(), self.cached_session(): @@ -742,42 +624,6 @@ class FunctionTest(test.TestCase, parameterized.TestCase): self.assertAllEqual(8, g(constant_op.constant(2))) - def testDefunCallBackprop(self): - - @def_function.function - def f(x): - return math_ops.add(x, x) - - @def_function.function - def g(x): - return backprop.gradients_function(f, [0])(x)[0] - - self.assertAllEqual(2, g(constant_op.constant(2.))) - - def testGraphModeEagerGradError(self): - with context.graph_mode(): - def f(): - x = variable_scope.get_variable( - 'v', initializer=constant_op.constant(1.0)) - return x * constant_op.constant(2.0) - - with self.assertRaisesRegexp(ValueError, - 'No trainable variables were accessed'): - backprop.implicit_val_and_grad(f)() - - def testDefunCallBackpropUsingSameObjectForMultipleArguments(self): - - @def_function.function - def g(x): - return backprop.gradients_function(math_ops.multiply, [0, 1])(x, x) - - def np_g(x): - return [d.numpy() for d in g(x)] - - x = constant_op.constant(1.) - self.assertAllEqual([1., 1.], np_g(x)) - self.assertAllEqual([1., 1.], np_g(1.)) - def testCallShape(self): @def_function.function @@ -808,37 +654,6 @@ class FunctionTest(test.TestCase, parameterized.TestCase): g(three) - def testGradientTensorConversionWithDefun(self): - three = resource_variable_ops.ResourceVariable(3.0, name='v') - - @def_function.function - def f(x): - return math_ops.add(x, three) - - def g(x): - return f(x) - - g = backprop.implicit_grad(g)(constant_op.constant(1.0))[0][0] - self.assertAllEqual(g, 1.0) - - def testGradient(self): - matmul = def_function.function(math_ops.matmul) - - def sq(x): - return matmul(x, x, transpose_a=True) - - t = constant_op.constant([[1.0, 2.0], [3.0, 4.0]]) - grad_t, = backprop.gradients_function(sq, [0])(t) - self.assertAllEqual(grad_t, [[6, 6], [14, 14]]) - - def testGradientInFunction(self): - - @def_function.function - def f(x): - return backprop.gradients_function(lambda y: y * y, [0])(x)[0] - - self.assertAllEqual(f(constant_op.constant(1.0)), 2.0) - def testGatherResourceWithDefun(self): with ops.device('cpu:0'): v = resource_variable_ops.ResourceVariable([0.0, 1.0, 2.0]) @@ -849,24 +664,6 @@ class FunctionTest(test.TestCase, parameterized.TestCase): defined = def_function.function(sum_gather) self.assertAllEqual(sum_gather(), defined()) - def testGradientOfGatherWithDefun(self): - v = resource_variable_ops.ResourceVariable([0.0, 1.0, 2.0]) - - def sum_gather(): - return math_ops.reduce_sum(array_ops.gather(v, [1, 2])) - - grad_fn = backprop.implicit_grad(sum_gather) - gradient = grad_fn() - defun_grad_fn = backprop.implicit_grad(def_function.function(sum_gather)) - defun_gradient = defun_grad_fn() - self.assertEqual(len(gradient), len(defun_gradient)) - - gradient = gradient[0][0] - defun_gradient = defun_gradient[0][0] - self.assertAllEqual(gradient.values, defun_gradient.values) - self.assertAllEqual(gradient.indices, defun_gradient.indices) - self.assertAllEqual(gradient.dense_shape, defun_gradient.dense_shape) - def testReturningIndexedSlicesWithDefun(self): def validate(indexed_slice): @@ -1012,440 +809,6 @@ class FunctionTest(test.TestCase, parameterized.TestCase): shape = constant_op.constant([2, 1]).gpu() reshape(value, shape) # No error is raised - def testDifferentiableFunctionNoneOutputs(self): - - @def_function.function - def my_function(x): - return x, None - - def wrapper(x): - return my_function(x)[0] - - g = backprop.gradients_function(wrapper, [0])(constant_op.constant(0.0)) - self.assertAllEqual(g[0], 1.) - - @def_function.function - def foo(a): - return None, a * a - - x = constant_op.constant(5.0) - with backprop.GradientTape() as tp: - tp.watch(x) - none, r = foo(x) - g = tp.gradient(r, x) - - self.assertIs(none, None) - self.assertAllEqual(r, 25.0) - self.assertAllEqual(g, 2 * 5.0) - - @test_util.run_in_graph_and_eager_modes - def testNestedDifferentiableFunction(self): - @def_function.function - def inner_fn(a, b): - return a * math_ops.add(a, b) - - @def_function.function - def outer_fn(x): - return inner_fn(x, 1.0) - - x = constant_op.constant(5.0) - with backprop.GradientTape() as tp: - tp.watch(x) - result = outer_fn(x) - grad = tp.gradient(result, x) - - self.assertAllEqual(grad, 2 * 5.0 + 1.0) - - @test_util.run_in_graph_and_eager_modes - def testDeeplyNestedDifferentiableFunction(self): - @def_function.function - def inner_inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def inner_fn(a, b): - return inner_inner_fn(a, b) - - @def_function.function - def middle_fn(a, b): - return a * inner_fn(a, b) - - @def_function.function - def outer_fn(x): - return middle_fn(x, 1.0) - - x = constant_op.constant(5.0) - with backprop.GradientTape() as tp: - tp.watch(x) - result = outer_fn(x) - grad = tp.gradient(result, x) - - self.assertAllEqual(grad, 2 * 5.0 + 1.0) - - @test_util.run_in_graph_and_eager_modes - def testDeeplyNestedDifferentiableFunctionWithMultipleGradCalls(self): - @def_function.function - def inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def middle_fn(a, b): - return math_ops.mul(a, inner_fn(a, b)) - - @def_function.function - def outer_fn(x): - return middle_fn(x, 3.0) - - x = constant_op.constant(5.0) - self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) - - with backprop.GradientTape() as tp: - tp.watch(x) - result = outer_fn(x) - grad = tp.gradient(result, x) - - self.assertAllEqual(grad, 2 * 5.0 + 3.0) - self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) - self.assertAllEqual(middle_fn(3.0, x), 3.0 * (3.0 + 5.0)) - - with backprop.GradientTape() as tp: - tp.watch(x) - result = outer_fn(x) - grad = tp.gradient(result, x) - - self.assertAllEqual(grad, 2 * 5.0 + 3.0) - - y = constant_op.constant(4.0) - with backprop.GradientTape() as tp: - tp.watch(y) - result = outer_fn(y) - grad = tp.gradient(result, y) - - self.assertAllEqual(grad, 2 * 4.0 + 3.0) - - with backprop.GradientTape() as tp: - tp.watch(y) - result = inner_fn(y, y) - grad = tp.gradient(result, y) - - self.assertAllEqual(grad, 2.0) - - @test_util.run_in_graph_and_eager_modes - def testDeeplyNestedDifferentiableFunctionGradientTapeInDefun(self): - @def_function.function - def inner_inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def inner_fn(a, b): - return inner_inner_fn(a, b) - - @def_function.function - def middle_fn(a, b): - return a * inner_fn(a, b) - - @def_function.function - def outer_fn(x): - with backprop.GradientTape() as tp: - tp.watch(x) - result = middle_fn(x, 1.0) - grad = tp.gradient(result, x) - return grad - - x = constant_op.constant(5.0) - grad = outer_fn(x) - self.assertAllEqual(grad, 2 * 5.0 + 1.0) - - @test_util.run_in_graph_and_eager_modes - def testDeeplyNestedDifferentiableFunctionGradientTapeInNestedDefun(self): - @def_function.function - def inner_inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def inner_fn(a, b): - return inner_inner_fn(a, b) - - @def_function.function - def middle_fn(a, b): - return a * inner_fn(a, b) - - @def_function.function - def almost_outer_fn(x): - with backprop.GradientTape() as tp: - tp.watch(x) - result = middle_fn(x, 1.0) - grad = tp.gradient(result, x) - return grad - - @def_function.function - def outer_fn(x): - return almost_outer_fn(x) - - x = constant_op.constant(5.0) - grad = outer_fn(x) - self.assertAllEqual(grad, 2 * 5.0 + 1.0) - - @test_util.run_in_graph_and_eager_modes - def testDeeplyNestedDifferentiableFunctionGradientTapeInMultNestedDefun(self): - @def_function.function - def inner_inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def inner_fn(a, b): - return inner_inner_fn(a, b) - - @def_function.function - def middle_fn(a, b): - return a * inner_fn(a, b) - - @def_function.function - def almost_outer_fn(x): - with backprop.GradientTape() as tp: - tp.watch(x) - result = middle_fn(x, 1.0) - grad = tp.gradient(result, x) - return grad - - @def_function.function - def outer_fn(x): - return almost_outer_fn(x) - - @def_function.function - def outer_outer_fn(x): - return outer_fn(x) - - x = constant_op.constant(5.0) - grad = outer_outer_fn(x) - self.assertAllEqual(grad, 2 * 5.0 + 1.0) - - @test_util.run_in_graph_and_eager_modes - def testDeeplyNestedDifferentiableFunctionTFGradientInDefun(self): - @def_function.function - def inner_inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def inner_fn(a, b): - return inner_inner_fn(a, b) - - @def_function.function - def middle_fn(a, b): - return a * inner_fn(a, b) - - @def_function.function - def outer_fn(x): - result = middle_fn(x, 1.0) - return gradients_impl.gradients(result, [x])[0] - - x = constant_op.constant(5.0) - grad = outer_fn(x) - self.assertAllEqual(grad, 2 * 5.0 + 1.0) - - @test_util.run_in_graph_and_eager_modes - def testDeeplyNestedDifferentiableFunctionTFGradientInNestedDefun(self): - @def_function.function - def inner_inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def inner_fn(a, b): - return inner_inner_fn(a, b) - - @def_function.function - def middle_fn(a, b): - return a * inner_fn(a, b) - - @def_function.function - def almost_outer_fn(x): - result = middle_fn(x, 1.0) - return gradients_impl.gradients(result, [x])[0] - - @def_function.function - def outer_fn(x): - return almost_outer_fn(x) - - x = constant_op.constant(5.0) - grad = outer_fn(x) - self.assertAllEqual(grad, 2 * 5.0 + 1.0) - - @test_util.run_in_graph_and_eager_modes - def testDeeplyNestedDifferentiableFunctionTFGradientInMultNestedDefun(self): - @def_function.function - def inner_inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def inner_fn(a, b): - return inner_inner_fn(a, b) - - @def_function.function - def middle_fn(a, b): - return a * inner_fn(a, b) - - @def_function.function - def almost_outer_fn(x): - result = middle_fn(x, 1.0) - return gradients_impl.gradients(result, [x])[0] - - @def_function.function - def outer_fn(x): - return almost_outer_fn(x) - - @def_function.function - def outer_outer_fn(x): - return outer_fn(x) - - x = constant_op.constant(5.0) - grad = outer_outer_fn(x) - self.assertAllEqual(grad, 2 * 5.0 + 1.0) - - def testDeeplyNestedDifferentiableFunctionWithVariable(self): - var = variables.Variable(constant_op.constant(1.0)) - - @def_function.function - def inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def middle_fn(a, b): - return a * inner_fn(a, b) - - @def_function.function - def outer_fn(x): - return middle_fn(x, var) - - x = constant_op.constant(5.0) - with backprop.GradientTape() as tp: - tp.watch(x) - result = outer_fn(x) - grad = tp.gradient(result, x) - - self.assertAllEqual(grad, 2 * 5.0 + 1.0) - - def testDeeplyNestedDifferentiableFunctionWithVariableMultipleGradCalls(self): - v = variables.Variable(constant_op.constant(3.0)) - - @def_function.function - def inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def middle_fn(a, b): - return math_ops.mul(a, inner_fn(a, b)) - - @def_function.function - def outer_fn(x): - return middle_fn(x, v) - - x = constant_op.constant(5.0) - self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) - - with backprop.GradientTape() as tp: - tp.watch(x) - result = outer_fn(x) - grad = tp.gradient(result, x) - - self.assertAllEqual(grad, 2 * 5.0 + 3.0) - self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) - self.assertAllEqual(middle_fn(v, x), 3.0 * (3.0 + 5.0)) - - with backprop.GradientTape() as tp: - tp.watch(x) - result = outer_fn(x) - grad = tp.gradient(result, x) - - self.assertAllEqual(grad, 2 * 5.0 + 3.0) - - y = constant_op.constant(4.0) - with backprop.GradientTape() as tp: - tp.watch(y) - result = outer_fn(y) - grad = tp.gradient(result, y) - - self.assertAllEqual(grad, 2 * 4.0 + 3.0) - - v.assign(constant_op.constant(1.5)) - with backprop.GradientTape() as tp: - tp.watch(y) - result = outer_fn(y) - grad = tp.gradient(result, y) - - self.assertAllEqual(grad, 2 * 4.0 + 1.5) - - with backprop.GradientTape() as tp: - tp.watch(y) - result = inner_fn(y, v) - grad = tp.gradient(result, y) - - self.assertAllEqual(grad, 1.0) - - def testDeeplyNestedDifferentiableFunctionWithVariableMultipleTFGrads(self): - with context.graph_mode(), self.cached_session(): - v = resource_variable_ops.ResourceVariable(3.0) - v.initializer.run() - - @def_function.function - def inner_fn(a, b): - return math_ops.add(a, b) - - @def_function.function - def middle_fn(a, b): - return math_ops.mul(a, inner_fn(a, b)) - - @def_function.function - def outer_fn(x): - return middle_fn(x, v) - - x = constant_op.constant(5.0) - self.assertAllEqual(outer_fn(x).eval(), 5.0 * (5.0 + 3.0)) - - grad, = gradients_impl.gradients(outer_fn(x), x) - - self.assertAllEqual(grad, 2 * 5.0 + 3.0) - self.assertAllEqual(outer_fn(x), 5.0 * (5.0 + 3.0)) - self.assertAllEqual(middle_fn(v, x), 3.0 * (3.0 + 5.0)) - - grad, = gradients_impl.gradients(outer_fn(x), x) - - self.assertAllEqual(grad, 2 * 5.0 + 3.0) - - y = constant_op.constant(4.0) - grad, = gradients_impl.gradients(outer_fn(y), y) - self.assertAllEqual(grad, 2 * 4.0 + 3.0) - - self.evaluate(v.assign(constant_op.constant(1.5))) - grad, = gradients_impl.gradients(outer_fn(y), y) - - self.assertAllEqual(grad, 2 * 4.0 + 1.5) - - grad, = gradients_impl.gradients(inner_fn(y, v), y) - self.assertAllEqual(grad, 1.0) - - def testNestedDifferentiableFunctionNoneOutputs(self): - @def_function.function - def foo(a, b): - return None, a * math_ops.add(a, b), None, 2*a - - @def_function.function - def bar(x): - return foo(x, 1.0) - - x = constant_op.constant(5.0) - with backprop.GradientTape(persistent=True) as tp: - tp.watch(x) - none1, r1, none2, r2 = bar(x) - g1 = tp.gradient(r1, x) - g2 = tp.gradient(r2, x) - - self.assertAllEqual(r1, 30.0) - self.assertAllEqual(r2, 10.0) - self.assertIs(none1, None) - self.assertIs(none2, None) - self.assertAllEqual(g1, 2 * 5.0 + 1.0) - self.assertAllEqual(g2, 2.0) - def testNoneOutput(self): @def_function.function @@ -1925,8 +1288,9 @@ class FunctionTest(test.TestCase, parameterized.TestCase): defined(array_ops.ones([2, 1])) # Wrong number of arguments. - with self.assertRaisesRegexp(ValueError, - 'Structure of Python function inputs.*'): + with self.assertRaisesRegexp( + ValueError, + 'Arguments and signature arguments do not match.*'): defined(array_ops.ones([2]), array_ops.ones([2])) with self.assertRaisesRegexp(ValueError, 'Structure of Python function inputs.*'): @@ -1945,10 +1309,16 @@ class FunctionTest(test.TestCase, parameterized.TestCase): else: return -1.0 * a - signature = [tensor_spec.TensorSpec([], dtypes.float32)] * 2 + signature = [ + tensor_spec.TensorSpec([], dtypes.float32), + tensor_spec.TensorSpec([], dtypes.bool), + ] defined = def_function.function(foo, input_signature=signature) a = constant_op.constant(1.0) - with self.assertRaises(TypeError): + with self.assertRaisesRegexp( + ValueError, + 'When input_signature is provided, all inputs to ' + 'the Python function must be Tensors.'): defined(a, training=True) def testInputSignatureWithKeywordPositionalArgs(self): @@ -2039,33 +1409,6 @@ class FunctionTest(test.TestCase, parameterized.TestCase): self.assertAllEqual(six, 2.0) self.assertAllEqual(seven, 2.0) - def testGradientWithKeywordArguments(self): - matmul = def_function.function(math_ops.matmul) - - def sq(x): - return matmul(a=x, b=x, transpose_a=True) - - t = constant_op.constant([[1.0, 2.0], [3.0, 4.0]]) - grad_t, = backprop.gradients_function(sq, [0])(t) - self.assertAllEqual(grad_t, [[6, 6], [14, 14]]) - - with backprop.GradientTape(persistent=True) as tape: - tape.watch(t) - one = matmul(t, b=t, transpose_a=True) - two = matmul(b=t, a=t, transpose_a=True) - three = matmul(a=t, b=t, transpose_a=True) - - for output in [one, two, three]: - self.assertAllEqual(tape.gradient(output, t), [[6, 6], [14, 14]]) - - def testGradientInFunctionWithKeywordArguments(self): - - @def_function.function - def f(x): - return backprop.gradients_function(lambda y: y * y, [0])(x)[0] - - self.assertAllEqual(f(x=constant_op.constant(1.0)), 2.0) - def testDefuningInstanceMethod(self): integer = constant_op.constant(2, dtypes.int64) @@ -2339,33 +1682,6 @@ class FunctionTest(test.TestCase, parameterized.TestCase): # pylint: disable=protected-access self.assertEqual(len(graph._functions), 3) - @test_util.run_in_graph_and_eager_modes - def testBackwardNone(self): - model = variables.Variable(1.0, name='model') - count = variables.Variable(0) - - @function.defun - def forward_pass(value): - count.assign_add(1) - residuals = value - model - loss = 0.5 * math_ops.reduce_mean(math_ops.pow(residuals, 2)) - # Note: count is an integer, so its doutput will be None - return loss, count - - def reduce_fn(x): - if context.executing_eagerly(): - with backprop.GradientTape() as t: - loss, count = forward_pass(x) - return t.gradient(loss, model), count - loss, count = forward_pass(x) - grad_only = gradients_impl.gradients(loss, model) - return grad_only, count - - g, _ = reduce_fn(constant_op.constant([7.0])) - - self.evaluate(variables.global_variables_initializer()) - self.assertAllEqual(nest.flatten(self.evaluate(g)), [-6.0]) - def testCallingFunctionWithDifferentVariables(self): @function.defun @@ -2403,8 +1719,7 @@ class FunctionTest(test.TestCase, parameterized.TestCase): 'be Tensors;.*'): graph_function('Not a Tensor.') - # TODO(scottzhu): Revive the test once the grappler plugin is updated. - def disabled_testSwapImplementationWithGrapplerPlugin(self): + def testSwapImplementationWithGrapplerPlugin(self): rewrites = rewriter_config_pb2.RewriterConfig() # function_optimizer has to be turn off, otherwise it will delete the # registered function if it does not get called. @@ -2441,7 +1756,7 @@ class FunctionTest(test.TestCase, parameterized.TestCase): function.register(cpu_boost, x) y = gpu_boost(x) - y_value = sess.run(y) + y_value = self.evaluate(y) if test.is_gpu_available(): self.assertEqual(y_value, 5.0) diff --git a/tensorflow/python/eager/graph_only_ops_test.py b/tensorflow/python/eager/graph_only_ops_test.py index 3cf3a61a62..914b4d9a95 100644 --- a/tensorflow/python/eager/graph_only_ops_test.py +++ b/tensorflow/python/eager/graph_only_ops_test.py @@ -29,12 +29,14 @@ from tensorflow.python.platform import test class GraphOnlyOpsTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testGraphZerosLike(self): x = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.int32) z_tf = graph_only_ops.graph_zeros_like(x) with self.cached_session(): - self.assertAllClose(np.zeros((2, 3)), z_tf.eval()) + self.assertAllClose(np.zeros((2, 3)), self.evaluate(z_tf)) + @test_util.run_deprecated_v1 def testGraphPlaceholder(self): x_tf = graph_only_ops.graph_placeholder(dtypes.int32, shape=(1,)) y_tf = math_ops.square(x_tf) diff --git a/tensorflow/python/eager/pywrap_tensor.cc b/tensorflow/python/eager/pywrap_tensor.cc index 55f0896e3b..206b96eef6 100644 --- a/tensorflow/python/eager/pywrap_tensor.cc +++ b/tensorflow/python/eager/pywrap_tensor.cc @@ -220,6 +220,14 @@ TFE_TensorHandle* ConvertToEagerTensor(PyObject* value, PyObject* dtype) { return nullptr; } } + tensorflow::Safe_PyObjectPtr value_decrefer; + if (PyArray_CheckAnyScalarExact(value)) { + // Convert numpy scalars to numpy arrays. + value = PyArray_FromScalar(value, nullptr); + // The returned value needs to be DECREF'd, but the original value was + // created in python code, and doesn't need to be DECREF'd. + value_decrefer.reset(value); + } if (PyArray_Check(value)) { int desired_np_dtype = -1; if (desired_dtype >= 0) { @@ -439,8 +447,8 @@ int EagerTensor_init(EagerTensor* self, PyObject* args, PyObject* kwds) { PyErr_SetString( PyExc_TypeError, tensorflow::strings::StrCat( - "Cannot convert value ", TFE_GetPythonString(value_str.get()), - " to EagerTensor with requested dtype: ", + "Cannot convert provided value to EagerTensor. Provided value: ", + TFE_GetPythonString(value_str.get()), " Requested dtype: ", tensorflow::DataTypeString( static_cast(desired_dtype))) .c_str()); @@ -672,11 +680,29 @@ static PyObject* EagerTensor_device(EagerTensor* self) { #endif } +// Getter `backing_device`. +static PyObject* EagerTensor_backing_device(EagerTensor* self) { + const char* device = + TFE_TensorHandleBackingDeviceName(self->handle, self->status); + if (MaybeRaiseExceptionFromTFStatus(self->status, PyExc_ValueError)) { + // Cleanup self->status before returning. + TF_SetStatus(self->status, TF_OK, ""); + return nullptr; + } +#if PY_MAJOR_VERSION >= 3 + return PyUnicode_FromString(device); +#else + return PyBytes_FromString(device); +#endif +} + static PyGetSetDef EagerTensor_getseters[] = { {const_cast("_id"), (getter)EagerTensor_getid, nullptr, const_cast("_id"), nullptr}, {const_cast("device"), (getter)EagerTensor_device, nullptr, const_cast("device"), nullptr}, + {const_cast("backing_device"), (getter)EagerTensor_backing_device, + nullptr, const_cast("backing_device"), nullptr}, {const_cast("_handle_data"), (getter)EagerTensor_tensor_handle, (setter)EagerTensor_settensor_handle, const_cast("_tensor_handle"), nullptr}, diff --git a/tensorflow/python/eager/pywrap_tfe_src.cc b/tensorflow/python/eager/pywrap_tfe_src.cc index 6ca8eadbde..9ce500bc08 100644 --- a/tensorflow/python/eager/pywrap_tfe_src.cc +++ b/tensorflow/python/eager/pywrap_tfe_src.cc @@ -1645,6 +1645,29 @@ PyObject* TFE_Py_TapeGradient(PyObject* tape, PyObject* target, if (PyErr_Occurred()) { return nullptr; } + tensorflow::gtl::FlatSet sources_set(sources_vec.begin(), + sources_vec.end()); + + tensorflow::Safe_PyObjectPtr seq = + tensorflow::make_safe(PySequence_Fast(target, "expected a sequence")); + int len = PySequence_Fast_GET_SIZE(seq.get()); + tensorflow::gtl::FlatMap + source_tensors_that_are_targets; + for (int i = 0; i < len; ++i) { + tensorflow::int64 target_id = target_vec[i]; + if (sources_set.find(target_id) != sources_set.end()) { + auto tensor = PySequence_Fast_GET_ITEM(seq.get(), i); + source_tensors_that_are_targets.insert( + std::make_pair(target_id, TapeTensorFromTensor(tensor))); + } + if (PyErr_Occurred()) { + return nullptr; + } + } + if (PyErr_Occurred()) { + return nullptr; + } + std::vector outgrad_vec; if (output_gradients != Py_None) { outgrad_vec = MakeTensorList(output_gradients); @@ -1659,7 +1682,8 @@ PyObject* TFE_Py_TapeGradient(PyObject* tape, PyObject* target, } std::vector result; status->status = tape_obj->tape->ComputeGradient( - *py_vspace, target_vec, sources_vec, outgrad_vec, &result); + *py_vspace, target_vec, sources_vec, source_tensors_that_are_targets, + outgrad_vec, &result); if (!status->status.ok()) { if (PyErr_Occurred()) { // Do not propagate the erroneous status as that would swallow the @@ -2279,8 +2303,10 @@ bool ConvertToTensor( PyErr_SetString( PyExc_TypeError, tensorflow::strings::StrCat( - "Cannot convert value ", TFE_GetPythonString(input_str.get()), - " to EagerTensor with requested dtype: ", desired_dtype) + "Cannot convert provided value to EagerTensor. Provided value: ", + TFE_GetPythonString(input_str.get()), " Requested dtype: ", + tensorflow::DataTypeString( + static_cast(desired_dtype))) .c_str()); return false; } diff --git a/tensorflow/python/eager/tape.py b/tensorflow/python/eager/tape.py index 1326f09713..e501b403a3 100644 --- a/tensorflow/python/eager/tape.py +++ b/tensorflow/python/eager/tape.py @@ -63,7 +63,7 @@ def watch_variable(tape, variable): """Marks this variable to be watched by the given tape.""" strategy = distribution_strategy_context.get_distribution_strategy() if distribution_strategy_context.get_replica_context(): - variables = [strategy.value_container(variable)] + variables = [strategy.extended.value_container(variable)] else: variables = strategy.unwrap(variable) for var in variables: @@ -78,7 +78,7 @@ def variable_accessed(variable): """ strategy = distribution_strategy_context.get_distribution_strategy() if distribution_strategy_context.get_replica_context(): - variables = [strategy.value_container(variable)] + variables = [strategy.extended.value_container(variable)] else: variables = strategy.unwrap(variable) for var in variables: diff --git a/tensorflow/python/eager/tape_test.py b/tensorflow/python/eager/tape_test.py index acd0e569f1..48d3b8ac6e 100644 --- a/tensorflow/python/eager/tape_test.py +++ b/tensorflow/python/eager/tape_test.py @@ -80,8 +80,8 @@ class TapeTest(test.TestCase): tf_e = tf_d + tf_f tf_da, tf_db = gradients_impl.gradients(tf_e, [tf_a, tf_b]) - self.assertAllEqual(da, tf_da.eval()) - self.assertAllEqual(db, tf_db.eval()) + self.assertAllEqual(da, self.evaluate(tf_da)) + self.assertAllEqual(db, self.evaluate(tf_db)) def testBasicFunctional(self): @@ -142,8 +142,8 @@ class TapeTest(test.TestCase): tf_rr = 2 * math_ops.reduce_sum(tf_mm) tf_da, tf_db = gradients_impl.gradients(tf_rr, [tf_a, tf_b]) - self.assertAllEqual(da, tf_da.eval()) - self.assertAllEqual(db, tf_db.eval()) + self.assertAllEqual(da, self.evaluate(tf_da)) + self.assertAllEqual(db, self.evaluate(tf_db)) def testGcTwoOutputs(self): diff --git a/tensorflow/python/eager/tensor_test.py b/tensorflow/python/eager/tensor_test.py index f61d847817..0ee2ff68c2 100644 --- a/tensorflow/python/eager/tensor_test.py +++ b/tensorflow/python/eager/tensor_test.py @@ -95,6 +95,18 @@ class TFETensorTest(test_util.TensorFlowTestCase): t = _create_tensor(values) self.assertAllEqual(values, t) + @test_util.assert_no_new_pyobjects_executing_eagerly + def testNumpyDtypeSurvivesThroughTensorConversion(self): + scalar_creators = [np.int32, np.int64, np.float32, np.float64] + conversion_functions = [ops.convert_to_tensor, constant_op.constant] + + for scalar_creator in scalar_creators: + for conversion_function in conversion_functions: + np_val = scalar_creator(3) + tensor_val = conversion_function(np_val) + self.assertEqual(tensor_val.numpy().dtype, np_val.dtype) + self.assertEqual(tensor_val.numpy(), np_val) + def testNumpyValueWithCast(self): values = np.array([3.0], dtype=np.float32) t = _create_tensor(values, dtype=dtypes.float64) @@ -128,6 +140,23 @@ class TFETensorTest(test_util.TensorFlowTestCase): tensor = constant_op.constant(numpy_tensor) self.assertAllEqual(numpy_tensor.ndim, tensor.ndim) + def testLenAgreesWithNumpy(self): + numpy_tensor = np.asarray(1.0) + tensor = constant_op.constant(numpy_tensor) + with self.assertRaises(TypeError): + len(numpy_tensor) + with self.assertRaisesRegexp( + TypeError, r"Scalar tensor has no `len[(][)]`"): + len(tensor) + + numpy_tensor = np.asarray([1.0, 2.0, 3.0]) + tensor = constant_op.constant(numpy_tensor) + self.assertAllEqual(len(numpy_tensor), len(tensor)) + + numpy_tensor = np.asarray([[1.0, 2.0, 3.0], [1.0, 2.0, 3.0]]) + tensor = constant_op.constant(numpy_tensor) + self.assertAllEqual(len(numpy_tensor), len(tensor)) + def testCopy(self): t = constant_op.constant(1.0) tt = copy.copy(t) @@ -158,9 +187,13 @@ class TFETensorTest(test_util.TensorFlowTestCase): self.assertEqual(dtypes.float64, t.dtype) def testBool(self): - t = _create_tensor(False) - if t: - self.assertFalse(True) + self.assertFalse(bool(_create_tensor(False))) + self.assertFalse(bool(_create_tensor([False]))) + self.assertFalse(bool(_create_tensor([[False]]))) + self.assertFalse(bool(_create_tensor([0]))) + self.assertFalse(bool(_create_tensor([0.]))) + self.assertTrue(bool(_create_tensor([1]))) + self.assertTrue(bool(_create_tensor([1.]))) def testIntDowncast(self): t = _create_tensor(3) @@ -306,6 +339,14 @@ class TFETensorTest(test_util.TensorFlowTestCase): def testConvertToTensorAllowsOverflow(self): _ = ops.convert_to_tensor(123456789, dtype=dtypes.uint8) + def testEagerTensorError(self): + with self.assertRaisesRegexp( + TypeError, + "Cannot convert provided value to EagerTensor. " + "Provided value.*Requested dtype.*"): + _ = ops.convert_to_tensor(1., dtype=dtypes.int32) + + class TFETensorUtilTest(test_util.TensorFlowTestCase): diff --git a/tensorflow/python/eager/test.py b/tensorflow/python/eager/test.py index 33ee797678..a45deac962 100644 --- a/tensorflow/python/eager/test.py +++ b/tensorflow/python/eager/test.py @@ -24,6 +24,6 @@ from tensorflow.python.platform.test import * # pylint: disable=wildcard-import # TODO(akshayka): Do away with this file. -def main(argv=None): +def main(argv=None): # pylint: disable=function-redefined _ops.enable_eager_execution() _test.main(argv) diff --git a/tensorflow/python/eager/wrap_function.py b/tensorflow/python/eager/wrap_function.py index 48266437ef..2b39e99a4e 100644 --- a/tensorflow/python/eager/wrap_function.py +++ b/tensorflow/python/eager/wrap_function.py @@ -26,6 +26,7 @@ from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import variable_scope from tensorflow.python.util import nest +from tensorflow.python.util.tf_export import tf_export class VariableHolder(object): @@ -45,6 +46,7 @@ class VariableHolder(object): return self._fn(*args, **kwargs) +# TODO(allenl): make this checkpointable class WrappedFunction(function.Function): """Wraps a tf V1 piece of code in a function.""" @@ -77,6 +79,7 @@ class WrappedFunction(function.Function): return pruned_fn +@tf_export(v1=["wrap_function"]) def wrap_function(fn, signature, name=None): """Wraps the TF 1.x function fn into a graph function. @@ -109,6 +112,21 @@ def wrap_function(fn, signature, name=None): assert float(f_sub(1.0)) == 3.0 ``` + Both `tf.compat.v1.wrap_function` and `tf.function` create a callable + TensorFlow graph. But while `tf.function` runs all stateful operations + (e.g. `tf.print`) and sequences operations to provide the same semantics as + eager execution, `wrap_function` is closer to the behavior of `session.run` in + TensorFlow 1.x. It will not run any operations unless they are required to + compute the function's outputs, either through a data dependency or a control + dependency. Nor will it sequence operations. + + Unlike `tf.function`, `wrap_function` will only trace the Python function + once. As with placeholders in TF 1.x, shapes and dtypes must be provided to + `wrap_function`'s `signature` argument. + + Since it is only traced once, variables and state may be created inside the + function and owned by the function wrapper object. + Args: fn: python function to be wrapped signature: the placeholder and python arguments to be passed to the diff --git a/tensorflow/python/feature_column/feature_column.py b/tensorflow/python/feature_column/feature_column.py index b7a6a88535..a858d92608 100644 --- a/tensorflow/python/feature_column/feature_column.py +++ b/tensorflow/python/feature_column/feature_column.py @@ -230,7 +230,7 @@ def _internal_input_layer(features, return _get_logits() -@tf_export('feature_column.input_layer') +@tf_export(v1=['feature_column.input_layer']) def input_layer(features, feature_columns, weight_collections=None, @@ -365,7 +365,7 @@ class InputLayer(object): return self._input_layer_template.weights -@tf_export('feature_column.linear_model') +@tf_export(v1=['feature_column.linear_model']) def linear_model(features, feature_columns, units=1, @@ -746,7 +746,7 @@ def _transform_features(features, feature_columns): return outputs -@tf_export('feature_column.make_parse_example_spec') +@tf_export(v1=['feature_column.make_parse_example_spec']) def make_parse_example_spec(feature_columns): """Creates parsing spec dictionary from input feature_columns. @@ -807,11 +807,14 @@ def make_parse_example_spec(feature_columns): return result -@tf_export('feature_column.embedding_column') -def embedding_column( - categorical_column, dimension, combiner='mean', initializer=None, - ckpt_to_load_from=None, tensor_name_in_ckpt=None, max_norm=None, - trainable=True): +def _embedding_column(categorical_column, + dimension, + combiner='mean', + initializer=None, + ckpt_to_load_from=None, + tensor_name_in_ckpt=None, + max_norm=None, + trainable=True): """`_DenseColumn` that converts from sparse, categorical input. Use this when your inputs are sparse, but you want to convert them to a dense @@ -919,178 +922,11 @@ def embedding_column( trainable=trainable) -@tf_export('feature_column.shared_embedding_columns') -def shared_embedding_columns( - categorical_columns, dimension, combiner='mean', initializer=None, - shared_embedding_collection_name=None, ckpt_to_load_from=None, - tensor_name_in_ckpt=None, max_norm=None, trainable=True): - """List of dense columns that convert from sparse, categorical input. - - This is similar to `embedding_column`, except that it produces a list of - embedding columns that share the same embedding weights. - - Use this when your inputs are sparse and of the same type (e.g. watched and - impression video IDs that share the same vocabulary), and you want to convert - them to a dense representation (e.g., to feed to a DNN). - - Inputs must be a list of categorical columns created by any of the - `categorical_column_*` function. They must all be of the same type and have - the same arguments except `key`. E.g. they can be - categorical_column_with_vocabulary_file with the same vocabulary_file. Some or - all columns could also be weighted_categorical_column. - - Here is an example embedding of two features for a DNNClassifier model: - - ```python - watched_video_id = categorical_column_with_vocabulary_file( - 'watched_video_id', video_vocabulary_file, video_vocabulary_size) - impression_video_id = categorical_column_with_vocabulary_file( - 'impression_video_id', video_vocabulary_file, video_vocabulary_size) - columns = shared_embedding_columns( - [watched_video_id, impression_video_id], dimension=10) - - estimator = tf.estimator.DNNClassifier(feature_columns=columns, ...) - - label_column = ... - def input_fn(): - features = tf.parse_example( - ..., features=make_parse_example_spec(columns + [label_column])) - labels = features.pop(label_column.name) - return features, labels - - estimator.train(input_fn=input_fn, steps=100) - ``` - - Here is an example using `shared_embedding_columns` with model_fn: - - ```python - def model_fn(features, ...): - watched_video_id = categorical_column_with_vocabulary_file( - 'watched_video_id', video_vocabulary_file, video_vocabulary_size) - impression_video_id = categorical_column_with_vocabulary_file( - 'impression_video_id', video_vocabulary_file, video_vocabulary_size) - columns = shared_embedding_columns( - [watched_video_id, impression_video_id], dimension=10) - dense_tensor = input_layer(features, columns) - # Form DNN layers, calculate loss, and return EstimatorSpec. - ... - ``` - - Args: - categorical_columns: List of categorical columns created by a - `categorical_column_with_*` function. These columns produce the sparse IDs - that are inputs to the embedding lookup. All columns must be of the same - type and have the same arguments except `key`. E.g. they can be - categorical_column_with_vocabulary_file with the same vocabulary_file. - Some or all columns could also be weighted_categorical_column. - dimension: An integer specifying dimension of the embedding, must be > 0. - combiner: A string specifying how to reduce if there are multiple entries - in a single row. Currently 'mean', 'sqrtn' and 'sum' are supported, with - 'mean' the default. 'sqrtn' often achieves good accuracy, in particular - with bag-of-words columns. Each of this can be thought as example level - normalizations on the column. For more information, see - `tf.embedding_lookup_sparse`. - initializer: A variable initializer function to be used in embedding - variable initialization. If not specified, defaults to - `tf.truncated_normal_initializer` with mean `0.0` and standard deviation - `1/sqrt(dimension)`. - shared_embedding_collection_name: Optional name of the collection where - shared embedding weights are added. If not given, a reasonable name will - be chosen based on the names of `categorical_columns`. This is also used - in `variable_scope` when creating shared embedding weights. - ckpt_to_load_from: String representing checkpoint name/pattern from which to - restore column weights. Required if `tensor_name_in_ckpt` is not `None`. - tensor_name_in_ckpt: Name of the `Tensor` in `ckpt_to_load_from` from - which to restore the column weights. Required if `ckpt_to_load_from` is - not `None`. - max_norm: If not `None`, each embedding is clipped if its l2-norm is - larger than this value, before combining. - trainable: Whether or not the embedding is trainable. Default is True. - - Returns: - A list of dense columns that converts from sparse input. The order of - results follows the ordering of `categorical_columns`. - - Raises: - ValueError: if `dimension` not > 0. - ValueError: if any of the given `categorical_columns` is of different type - or has different arguments than the others. - ValueError: if exactly one of `ckpt_to_load_from` and `tensor_name_in_ckpt` - is specified. - ValueError: if `initializer` is specified and is not callable. - RuntimeError: if eager execution is enabled. - """ - if context.executing_eagerly(): - raise RuntimeError('shared_embedding_columns are not supported when eager ' - 'execution is enabled.') - - if (dimension is None) or (dimension < 1): - raise ValueError('Invalid dimension {}.'.format(dimension)) - if (ckpt_to_load_from is None) != (tensor_name_in_ckpt is None): - raise ValueError('Must specify both `ckpt_to_load_from` and ' - '`tensor_name_in_ckpt` or none of them.') - - if (initializer is not None) and (not callable(initializer)): - raise ValueError('initializer must be callable if specified.') - if initializer is None: - initializer = init_ops.truncated_normal_initializer( - mean=0.0, stddev=1. / math.sqrt(dimension)) - - # Sort the columns so the default collection name is deterministic even if the - # user passes columns from an unsorted collection, such as dict.values(). - sorted_columns = sorted(categorical_columns, key=lambda x: x.name) - - c0 = sorted_columns[0] - num_buckets = c0._num_buckets # pylint: disable=protected-access - if not isinstance(c0, _CategoricalColumn): - raise ValueError( - 'All categorical_columns must be subclasses of _CategoricalColumn. ' - 'Given: {}, of type: {}'.format(c0, type(c0))) - if isinstance(c0, _WeightedCategoricalColumn): - c0 = c0.categorical_column - for c in sorted_columns[1:]: - if isinstance(c, _WeightedCategoricalColumn): - c = c.categorical_column - if not isinstance(c, type(c0)): - raise ValueError( - 'To use shared_embedding_column, all categorical_columns must have ' - 'the same type, or be weighted_categorical_column of the same type. ' - 'Given column: {} of type: {} does not match given column: {} of ' - 'type: {}'.format(c0, type(c0), c, type(c))) - if num_buckets != c._num_buckets: # pylint: disable=protected-access - raise ValueError( - 'To use shared_embedding_column, all categorical_columns must have ' - 'the same number of buckets. Given column: {} with buckets: {} does ' - 'not match column: {} with buckets: {}'.format( - c0, num_buckets, c, c._num_buckets)) # pylint: disable=protected-access - - if not shared_embedding_collection_name: - shared_embedding_collection_name = '_'.join(c.name for c in sorted_columns) - shared_embedding_collection_name += '_shared_embedding' - - result = [] - for column in categorical_columns: - result.append( - _SharedEmbeddingColumn( - categorical_column=column, - initializer=initializer, - dimension=dimension, - combiner=combiner, - shared_embedding_collection_name=shared_embedding_collection_name, - ckpt_to_load_from=ckpt_to_load_from, - tensor_name_in_ckpt=tensor_name_in_ckpt, - max_norm=max_norm, - trainable=trainable)) - - return result - - -@tf_export('feature_column.numeric_column') -def numeric_column(key, - shape=(1,), - default_value=None, - dtype=dtypes.float32, - normalizer_fn=None): +def _numeric_column(key, + shape=(1,), + default_value=None, + dtype=dtypes.float32, + normalizer_fn=None): """Represents real valued or numerical features. Example: @@ -1161,8 +997,7 @@ def numeric_column(key, normalizer_fn=normalizer_fn) -@tf_export('feature_column.bucketized_column') -def bucketized_column(source_column, boundaries): +def _bucketized_column(source_column, boundaries): """Represents discretized dense input. Buckets include the left boundary, and exclude the right boundary. Namely, @@ -1258,10 +1093,9 @@ def _assert_key_is_string(key): type(key), key)) -@tf_export('feature_column.categorical_column_with_hash_bucket') -def categorical_column_with_hash_bucket(key, - hash_bucket_size, - dtype=dtypes.string): +def _categorical_column_with_hash_bucket(key, + hash_bucket_size, + dtype=dtypes.string): """Represents sparse feature where ids are set by hashing. Use this when your sparse features are in string or integer format, and you @@ -1317,13 +1151,12 @@ def categorical_column_with_hash_bucket(key, return _HashedCategoricalColumn(key, hash_bucket_size, dtype) -@tf_export('feature_column.categorical_column_with_vocabulary_file') -def categorical_column_with_vocabulary_file(key, - vocabulary_file, - vocabulary_size=None, - num_oov_buckets=0, - default_value=None, - dtype=dtypes.string): +def _categorical_column_with_vocabulary_file(key, + vocabulary_file, + vocabulary_size=None, + num_oov_buckets=0, + default_value=None, + dtype=dtypes.string): """A `_CategoricalColumn` with a vocabulary file. Use this when your inputs are in string or integer format, and you have a @@ -1437,9 +1270,11 @@ def categorical_column_with_vocabulary_file(key, dtype=dtype) -@tf_export('feature_column.categorical_column_with_vocabulary_list') -def categorical_column_with_vocabulary_list( - key, vocabulary_list, dtype=None, default_value=-1, num_oov_buckets=0): +def _categorical_column_with_vocabulary_list(key, + vocabulary_list, + dtype=None, + default_value=-1, + num_oov_buckets=0): """A `_CategoricalColumn` with in-memory vocabulary. Use this when your inputs are in string or integer format, and you have an @@ -1548,8 +1383,7 @@ def categorical_column_with_vocabulary_list( default_value=default_value, num_oov_buckets=num_oov_buckets) -@tf_export('feature_column.categorical_column_with_identity') -def categorical_column_with_identity(key, num_buckets, default_value=None): +def _categorical_column_with_identity(key, num_buckets, default_value=None): """A `_CategoricalColumn` that returns identity values. Use this when your inputs are integers in the range `[0, num_buckets)`, and @@ -1616,8 +1450,7 @@ def categorical_column_with_identity(key, num_buckets, default_value=None): key=key, num_buckets=num_buckets, default_value=default_value) -@tf_export('feature_column.indicator_column') -def indicator_column(categorical_column): +def _indicator_column(categorical_column): """Represents multi-hot representation of given categorical column. - For DNN model, `indicator_column` can be used to wrap any @@ -1651,9 +1484,9 @@ def indicator_column(categorical_column): return _IndicatorColumn(categorical_column) -@tf_export('feature_column.weighted_categorical_column') -def weighted_categorical_column( - categorical_column, weight_feature_key, dtype=dtypes.float32): +def _weighted_categorical_column(categorical_column, + weight_feature_key, + dtype=dtypes.float32): """Applies weight values to a `_CategoricalColumn`. Use this when each of your sparse inputs has both an ID and a value. For @@ -1726,8 +1559,7 @@ def weighted_categorical_column( dtype=dtype) -@tf_export('feature_column.crossed_column') -def crossed_column(keys, hash_bucket_size, hash_key=None): +def _crossed_column(keys, hash_bucket_size, hash_key=None): """Returns a column for performing crosses of categorical features. Crossed features will be hashed according to `hash_bucket_size`. Conceptually, diff --git a/tensorflow/python/feature_column/feature_column_lib.py b/tensorflow/python/feature_column/feature_column_lib.py index 3b818f18b5..68a2712425 100644 --- a/tensorflow/python/feature_column/feature_column_lib.py +++ b/tensorflow/python/feature_column/feature_column_lib.py @@ -20,4 +20,5 @@ from __future__ import print_function # pylint: disable=unused-import,line-too-long,wildcard-import from tensorflow.python.feature_column.feature_column import * +from tensorflow.python.feature_column.feature_column_v2 import * # pylint: enable=unused-import,line-too-long diff --git a/tensorflow/python/feature_column/feature_column_test.py b/tensorflow/python/feature_column/feature_column_test.py index 1ae510250c..daa0a3b3a4 100644 --- a/tensorflow/python/feature_column/feature_column_test.py +++ b/tensorflow/python/feature_column/feature_column_test.py @@ -30,7 +30,8 @@ from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.python.client import session from tensorflow.python.eager import backprop from tensorflow.python.eager import context -from tensorflow.python.feature_column import feature_column_lib as fc +from tensorflow.python.feature_column import feature_column as fc +from tensorflow.python.feature_column import feature_column_v2 as fc_new from tensorflow.python.feature_column.feature_column import _CategoricalColumn from tensorflow.python.feature_column.feature_column import _DenseColumn from tensorflow.python.feature_column.feature_column import _FeatureColumn @@ -169,6 +170,7 @@ class LazyColumnTest(test.TestCase): TypeError, '"key" must be either a "str" or "_FeatureColumn".'): builder.get(NotAFeatureColumn()) + @test_util.run_deprecated_v1 def test_expand_dim_rank_1_sparse_tensor_empty_batch(self): # empty 1-D sparse tensor: builder = _LazyBuilder(features={'a': sparse_tensor.SparseTensor( @@ -184,8 +186,9 @@ class LazyColumnTest(test.TestCase): class NumericColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): - a = fc.numeric_column('aaa') + a = fc._numeric_column('aaa') self.assertEqual('aaa', a.key) self.assertEqual('aaa', a.name) self.assertEqual('aaa', a._var_scope_name) @@ -196,53 +199,53 @@ class NumericColumnTest(test.TestCase): def test_key_should_be_string(self): with self.assertRaisesRegexp(ValueError, 'key must be a string.'): - fc.numeric_column(key=('aaa',)) + fc._numeric_column(key=('aaa',)) def test_shape_saved_as_tuple(self): - a = fc.numeric_column('aaa', shape=[1, 2], default_value=[[3, 2.]]) + a = fc._numeric_column('aaa', shape=[1, 2], default_value=[[3, 2.]]) self.assertEqual((1, 2), a.shape) def test_default_value_saved_as_tuple(self): - a = fc.numeric_column('aaa', default_value=4.) + a = fc._numeric_column('aaa', default_value=4.) self.assertEqual((4.,), a.default_value) - a = fc.numeric_column('aaa', shape=[1, 2], default_value=[[3, 2.]]) + a = fc._numeric_column('aaa', shape=[1, 2], default_value=[[3, 2.]]) self.assertEqual(((3., 2.),), a.default_value) def test_shape_and_default_value_compatibility(self): - fc.numeric_column('aaa', shape=[2], default_value=[1, 2.]) + fc._numeric_column('aaa', shape=[2], default_value=[1, 2.]) with self.assertRaisesRegexp(ValueError, 'The shape of default_value'): - fc.numeric_column('aaa', shape=[2], default_value=[1, 2, 3.]) - fc.numeric_column( + fc._numeric_column('aaa', shape=[2], default_value=[1, 2, 3.]) + fc._numeric_column( 'aaa', shape=[3, 2], default_value=[[2, 3], [1, 2], [2, 3.]]) with self.assertRaisesRegexp(ValueError, 'The shape of default_value'): - fc.numeric_column( + fc._numeric_column( 'aaa', shape=[3, 1], default_value=[[2, 3], [1, 2], [2, 3.]]) with self.assertRaisesRegexp(ValueError, 'The shape of default_value'): - fc.numeric_column( + fc._numeric_column( 'aaa', shape=[3, 3], default_value=[[2, 3], [1, 2], [2, 3.]]) def test_default_value_type_check(self): - fc.numeric_column( + fc._numeric_column( 'aaa', shape=[2], default_value=[1, 2.], dtype=dtypes.float32) - fc.numeric_column( + fc._numeric_column( 'aaa', shape=[2], default_value=[1, 2], dtype=dtypes.int32) with self.assertRaisesRegexp(TypeError, 'must be compatible with dtype'): - fc.numeric_column( + fc._numeric_column( 'aaa', shape=[2], default_value=[1, 2.], dtype=dtypes.int32) with self.assertRaisesRegexp(TypeError, 'default_value must be compatible with dtype'): - fc.numeric_column('aaa', default_value=['string']) + fc._numeric_column('aaa', default_value=['string']) def test_shape_must_be_positive_integer(self): with self.assertRaisesRegexp(TypeError, 'shape dimensions must be integer'): - fc.numeric_column( + fc._numeric_column( 'aaa', shape=[ 1.0, ]) with self.assertRaisesRegexp(ValueError, 'shape dimensions must be greater than 0'): - fc.numeric_column( + fc._numeric_column( 'aaa', shape=[ 0, ]) @@ -250,20 +253,21 @@ class NumericColumnTest(test.TestCase): def test_dtype_is_convertible_to_float(self): with self.assertRaisesRegexp(ValueError, 'dtype must be convertible to float'): - fc.numeric_column('aaa', dtype=dtypes.string) + fc._numeric_column('aaa', dtype=dtypes.string) def test_scalar_default_value_fills_the_shape(self): - a = fc.numeric_column('aaa', shape=[2, 3], default_value=2.) + a = fc._numeric_column('aaa', shape=[2, 3], default_value=2.) self.assertEqual(((2., 2., 2.), (2., 2., 2.)), a.default_value) def test_parse_spec(self): - a = fc.numeric_column('aaa', shape=[2, 3], dtype=dtypes.int32) + a = fc._numeric_column('aaa', shape=[2, 3], dtype=dtypes.int32) self.assertEqual({ 'aaa': parsing_ops.FixedLenFeature((2, 3), dtype=dtypes.int32) }, a._parse_example_spec) + @test_util.run_deprecated_v1 def test_parse_example_no_default_value(self): - price = fc.numeric_column('price', shape=[2]) + price = fc._numeric_column('price', shape=[2]) data = example_pb2.Example(features=feature_pb2.Features( feature={ 'price': @@ -277,8 +281,9 @@ class NumericColumnTest(test.TestCase): with self.cached_session(): self.assertAllEqual([[20., 110.]], features['price'].eval()) + @test_util.run_deprecated_v1 def test_parse_example_with_default_value(self): - price = fc.numeric_column('price', shape=[2], default_value=11.) + price = fc._numeric_column('price', shape=[2], default_value=11.) data = example_pb2.Example(features=feature_pb2.Features( feature={ 'price': @@ -301,29 +306,31 @@ class NumericColumnTest(test.TestCase): def test_normalizer_fn_must_be_callable(self): with self.assertRaisesRegexp(TypeError, 'must be a callable'): - fc.numeric_column('price', normalizer_fn='NotACallable') + fc._numeric_column('price', normalizer_fn='NotACallable') + @test_util.run_deprecated_v1 def test_normalizer_fn_transform_feature(self): def _increment_two(input_tensor): return input_tensor + 2. - price = fc.numeric_column('price', shape=[2], normalizer_fn=_increment_two) + price = fc._numeric_column('price', shape=[2], normalizer_fn=_increment_two) output = _transform_features({'price': [[1., 2.], [5., 6.]]}, [price]) with self.cached_session(): self.assertAllEqual([[3., 4.], [7., 8.]], output[price].eval()) + @test_util.run_deprecated_v1 def test_get_dense_tensor(self): def _increment_two(input_tensor): return input_tensor + 2. - price = fc.numeric_column('price', shape=[2], normalizer_fn=_increment_two) + price = fc._numeric_column('price', shape=[2], normalizer_fn=_increment_two) builder = _LazyBuilder({'price': [[1., 2.], [5., 6.]]}) self.assertEqual(builder.get(price), price._get_dense_tensor(builder)) def test_sparse_tensor_not_supported(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') builder = _LazyBuilder({ 'price': sparse_tensor.SparseTensor( @@ -332,109 +339,113 @@ class NumericColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'must be a Tensor'): price._transform_feature(builder) + @test_util.run_deprecated_v1 def test_deep_copy(self): - a = fc.numeric_column('aaa', shape=[1, 2], default_value=[[3., 2.]]) + a = fc._numeric_column('aaa', shape=[1, 2], default_value=[[3., 2.]]) a_copy = copy.deepcopy(a) self.assertEqual(a_copy.name, 'aaa') self.assertEqual(a_copy.shape, (1, 2)) self.assertEqual(a_copy.default_value, ((3., 2.),)) def test_numpy_default_value(self): - a = fc.numeric_column( + a = fc._numeric_column( 'aaa', shape=[1, 2], default_value=np.array([[3., 2.]])) self.assertEqual(a.default_value, ((3., 2.),)) + @test_util.run_deprecated_v1 def test_linear_model(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} predictions = fc.linear_model(features, [price]) bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.]], price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.]], self.evaluate(price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price_var.assign([[10.]])) - self.assertAllClose([[10.], [50.]], predictions.eval()) + self.assertAllClose([[10.], [50.]], self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} predictions = get_keras_linear_model_predictions(features, [price]) bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.]], price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.]], self.evaluate(price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price_var.assign([[10.]])) - self.assertAllClose([[10.], [50.]], predictions.eval()) + self.assertAllClose([[10.], [50.]], self.evaluate(predictions)) class BucketizedColumnTest(test.TestCase): def test_invalid_source_column_type(self): - a = fc.categorical_column_with_hash_bucket('aaa', hash_bucket_size=10) + a = fc._categorical_column_with_hash_bucket('aaa', hash_bucket_size=10) with self.assertRaisesRegexp( ValueError, 'source_column must be a column generated with numeric_column'): - fc.bucketized_column(a, boundaries=[0, 1]) + fc._bucketized_column(a, boundaries=[0, 1]) def test_invalid_source_column_shape(self): - a = fc.numeric_column('aaa', shape=[2, 3]) + a = fc._numeric_column('aaa', shape=[2, 3]) with self.assertRaisesRegexp( ValueError, 'source_column must be one-dimensional column'): - fc.bucketized_column(a, boundaries=[0, 1]) + fc._bucketized_column(a, boundaries=[0, 1]) def test_invalid_boundaries(self): - a = fc.numeric_column('aaa') + a = fc._numeric_column('aaa') with self.assertRaisesRegexp( ValueError, 'boundaries must be a sorted list'): - fc.bucketized_column(a, boundaries=None) + fc._bucketized_column(a, boundaries=None) with self.assertRaisesRegexp( ValueError, 'boundaries must be a sorted list'): - fc.bucketized_column(a, boundaries=1.) + fc._bucketized_column(a, boundaries=1.) with self.assertRaisesRegexp( ValueError, 'boundaries must be a sorted list'): - fc.bucketized_column(a, boundaries=[1, 0]) + fc._bucketized_column(a, boundaries=[1, 0]) with self.assertRaisesRegexp( ValueError, 'boundaries must be a sorted list'): - fc.bucketized_column(a, boundaries=[1, 1]) + fc._bucketized_column(a, boundaries=[1, 1]) def test_name(self): - a = fc.numeric_column('aaa', dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) + a = fc._numeric_column('aaa', dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) self.assertEqual('aaa_bucketized', b.name) def test_var_scope_name(self): - a = fc.numeric_column('aaa', dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) + a = fc._numeric_column('aaa', dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) self.assertEqual('aaa_bucketized', b._var_scope_name) def test_parse_spec(self): - a = fc.numeric_column('aaa', shape=[2], dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) + a = fc._numeric_column('aaa', shape=[2], dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) self.assertEqual({ 'aaa': parsing_ops.FixedLenFeature((2,), dtype=dtypes.int32) }, b._parse_example_spec) def test_variable_shape(self): - a = fc.numeric_column('aaa', shape=[2], dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) + a = fc._numeric_column('aaa', shape=[2], dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) # Column 'aaa` has shape [2] times three buckets -> variable_shape=[2, 3]. self.assertAllEqual((2, 3), b._variable_shape) def test_num_buckets(self): - a = fc.numeric_column('aaa', shape=[2], dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) + a = fc._numeric_column('aaa', shape=[2], dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) # Column 'aaa` has shape [2] times three buckets -> num_buckets=6. self.assertEqual(6, b._num_buckets) + @test_util.run_deprecated_v1 def test_parse_example(self): - price = fc.numeric_column('price', shape=[2]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 50]) + price = fc._numeric_column('price', shape=[2]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 50]) data = example_pb2.Example(features=feature_pb2.Features( feature={ 'price': @@ -448,9 +459,10 @@ class BucketizedColumnTest(test.TestCase): with self.cached_session(): self.assertAllEqual([[20., 110.]], features['price'].eval()) + @test_util.run_deprecated_v1 def test_transform_feature(self): - price = fc.numeric_column('price', shape=[2]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) + price = fc._numeric_column('price', shape=[2]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): transformed_tensor = _transform_features({ 'price': [[-1., 1.], [5., 6.]] @@ -461,24 +473,22 @@ class BucketizedColumnTest(test.TestCase): def test_get_dense_tensor_one_input_value(self): """Tests _get_dense_tensor() for input with shape=[1].""" - price = fc.numeric_column('price', shape=[1]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) + price = fc._numeric_column('price', shape=[1]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): builder = _LazyBuilder({'price': [[-1.], [1.], [5.], [6.]]}) with _initialized_session(): bucketized_price_tensor = bucketized_price._get_dense_tensor(builder) self.assertAllClose( # One-hot tensor. - [[[1., 0., 0., 0., 0.]], - [[0., 1., 0., 0., 0.]], - [[0., 0., 0., 1., 0.]], - [[0., 0., 0., 0., 1.]]], - bucketized_price_tensor.eval()) + [[[1., 0., 0., 0., 0.]], [[0., 1., 0., 0., 0.]], + [[0., 0., 0., 1., 0.]], [[0., 0., 0., 0., 1.]]], + self.evaluate(bucketized_price_tensor)) def test_get_dense_tensor_two_input_values(self): """Tests _get_dense_tensor() for input with shape=[2].""" - price = fc.numeric_column('price', shape=[2]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) + price = fc._numeric_column('price', shape=[2]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): builder = _LazyBuilder({'price': [[-1., 1.], [5., 6.]]}) with _initialized_session(): @@ -487,12 +497,12 @@ class BucketizedColumnTest(test.TestCase): # One-hot tensor. [[[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.]], [[0., 0., 0., 1., 0.], [0., 0., 0., 0., 1.]]], - bucketized_price_tensor.eval()) + self.evaluate(bucketized_price_tensor)) def test_get_sparse_tensors_one_input_value(self): """Tests _get_sparse_tensors() for input with shape=[1].""" - price = fc.numeric_column('price', shape=[1]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) + price = fc._numeric_column('price', shape=[1]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): builder = _LazyBuilder({'price': [[-1.], [1.], [5.], [6.]]}) with _initialized_session() as sess: @@ -506,8 +516,8 @@ class BucketizedColumnTest(test.TestCase): def test_get_sparse_tensors_two_input_values(self): """Tests _get_sparse_tensors() for input with shape=[2].""" - price = fc.numeric_column('price', shape=[2]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) + price = fc._numeric_column('price', shape=[2]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): builder = _LazyBuilder({'price': [[-1., 1.], [5., 6.]]}) with _initialized_session() as sess: @@ -522,8 +532,8 @@ class BucketizedColumnTest(test.TestCase): self.assertAllEqual([2, 2], id_tensor_value.dense_shape) def test_sparse_tensor_input_not_supported(self): - price = fc.numeric_column('price') - bucketized_price = fc.bucketized_column(price, boundaries=[0, 1]) + price = fc._numeric_column('price') + bucketized_price = fc._bucketized_column(price, boundaries=[0, 1]) builder = _LazyBuilder({ 'price': sparse_tensor.SparseTensor( @@ -532,9 +542,10 @@ class BucketizedColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'must be a Tensor'): bucketized_price._transform_feature(builder) + @test_util.run_deprecated_v1 def test_deep_copy(self): - a = fc.numeric_column('aaa', shape=[2]) - a_bucketized = fc.bucketized_column(a, boundaries=[0, 1]) + a = fc._numeric_column('aaa', shape=[2]) + a_bucketized = fc._bucketized_column(a, boundaries=[0, 1]) a_bucketized_copy = copy.deepcopy(a_bucketized) self.assertEqual(a_bucketized_copy.name, 'aaa_bucketized') self.assertAllEqual(a_bucketized_copy._variable_shape, (2, 3)) @@ -542,45 +553,48 @@ class BucketizedColumnTest(test.TestCase): def test_linear_model_one_input_value(self): """Tests linear_model() for input with shape=[1].""" - price = fc.numeric_column('price', shape=[1]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) + price = fc._numeric_column('price', shape=[1]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): features = {'price': [[-1.], [1.], [5.], [6.]]} predictions = fc.linear_model(features, [bucketized_price]) bias = get_linear_model_bias() bucketized_price_var = get_linear_model_column_var(bucketized_price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) # One weight variable per bucket, all initialized to zero. - self.assertAllClose( - [[0.], [0.], [0.], [0.], [0.]], bucketized_price_var.eval()) - self.assertAllClose([[0.], [0.], [0.], [0.]], predictions.eval()) + self.assertAllClose([[0.], [0.], [0.], [0.], [0.]], + self.evaluate(bucketized_price_var)) + self.assertAllClose([[0.], [0.], [0.], [0.]], + self.evaluate(predictions)) sess.run(bucketized_price_var.assign( [[10.], [20.], [30.], [40.], [50.]])) # price -1. is in the 0th bucket, whose weight is 10. # price 1. is in the 1st bucket, whose weight is 20. # price 5. is in the 3rd bucket, whose weight is 40. # price 6. is in the 4th bucket, whose weight is 50. - self.assertAllClose([[10.], [20.], [40.], [50.]], predictions.eval()) + self.assertAllClose([[10.], [20.], [40.], [50.]], + self.evaluate(predictions)) sess.run(bias.assign([1.])) - self.assertAllClose([[11.], [21.], [41.], [51.]], predictions.eval()) + self.assertAllClose([[11.], [21.], [41.], [51.]], + self.evaluate(predictions)) def test_linear_model_two_input_values(self): """Tests linear_model() for input with shape=[2].""" - price = fc.numeric_column('price', shape=[2]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) + price = fc._numeric_column('price', shape=[2]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): features = {'price': [[-1., 1.], [5., 6.]]} predictions = fc.linear_model(features, [bucketized_price]) bias = get_linear_model_bias() bucketized_price_var = get_linear_model_column_var(bucketized_price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) # One weight per bucket per input column, all initialized to zero. self.assertAllClose( [[0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.]], - bucketized_price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.evaluate(bucketized_price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(bucketized_price_var.assign( [[10.], [20.], [30.], [40.], [50.], [60.], [70.], [80.], [90.], [100.]])) @@ -590,14 +604,14 @@ class BucketizedColumnTest(test.TestCase): # 2nd example: # price 5. is in the 3rd bucket, whose weight is 40. # price 6. is in the 9th bucket, whose weight is 100. - self.assertAllClose([[80.], [140.]], predictions.eval()) + self.assertAllClose([[80.], [140.]], self.evaluate(predictions)) sess.run(bias.assign([1.])) - self.assertAllClose([[81.], [141.]], predictions.eval()) + self.assertAllClose([[81.], [141.]], self.evaluate(predictions)) def test_keras_linear_model_one_input_value(self): """Tests _LinearModel for input with shape=[1].""" - price = fc.numeric_column('price', shape=[1]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) + price = fc._numeric_column('price', shape=[1]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): features = {'price': [[-1.], [1.], [5.], [6.]]} predictions = get_keras_linear_model_predictions(features, @@ -605,25 +619,28 @@ class BucketizedColumnTest(test.TestCase): bias = get_linear_model_bias() bucketized_price_var = get_linear_model_column_var(bucketized_price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) # One weight variable per bucket, all initialized to zero. self.assertAllClose([[0.], [0.], [0.], [0.], [0.]], - bucketized_price_var.eval()) - self.assertAllClose([[0.], [0.], [0.], [0.]], predictions.eval()) + self.evaluate(bucketized_price_var)) + self.assertAllClose([[0.], [0.], [0.], [0.]], + self.evaluate(predictions)) sess.run( bucketized_price_var.assign([[10.], [20.], [30.], [40.], [50.]])) # price -1. is in the 0th bucket, whose weight is 10. # price 1. is in the 1st bucket, whose weight is 20. # price 5. is in the 3rd bucket, whose weight is 40. # price 6. is in the 4th bucket, whose weight is 50. - self.assertAllClose([[10.], [20.], [40.], [50.]], predictions.eval()) + self.assertAllClose([[10.], [20.], [40.], [50.]], + self.evaluate(predictions)) sess.run(bias.assign([1.])) - self.assertAllClose([[11.], [21.], [41.], [51.]], predictions.eval()) + self.assertAllClose([[11.], [21.], [41.], [51.]], + self.evaluate(predictions)) def test_keras_linear_model_two_input_values(self): """Tests _LinearModel for input with shape=[2].""" - price = fc.numeric_column('price', shape=[2]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) + price = fc._numeric_column('price', shape=[2]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): features = {'price': [[-1., 1.], [5., 6.]]} predictions = get_keras_linear_model_predictions(features, @@ -631,12 +648,12 @@ class BucketizedColumnTest(test.TestCase): bias = get_linear_model_bias() bucketized_price_var = get_linear_model_column_var(bucketized_price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) # One weight per bucket per input column, all initialized to zero. self.assertAllClose( [[0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.]], - bucketized_price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.evaluate(bucketized_price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run( bucketized_price_var.assign([[10.], [20.], [30.], [40.], [50.], [60.], [70.], [80.], [90.], [100.]])) @@ -646,15 +663,16 @@ class BucketizedColumnTest(test.TestCase): # 2nd example: # price 5. is in the 3rd bucket, whose weight is 40. # price 6. is in the 9th bucket, whose weight is 100. - self.assertAllClose([[80.], [140.]], predictions.eval()) + self.assertAllClose([[80.], [140.]], self.evaluate(predictions)) sess.run(bias.assign([1.])) - self.assertAllClose([[81.], [141.]], predictions.eval()) + self.assertAllClose([[81.], [141.]], self.evaluate(predictions)) class HashedCategoricalColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): - a = fc.categorical_column_with_hash_bucket('aaa', 10) + a = fc._categorical_column_with_hash_bucket('aaa', 10) self.assertEqual('aaa', a.name) self.assertEqual('aaa', a._var_scope_name) self.assertEqual('aaa', a.key) @@ -663,25 +681,26 @@ class HashedCategoricalColumnTest(test.TestCase): def test_key_should_be_string(self): with self.assertRaisesRegexp(ValueError, 'key must be a string.'): - fc.categorical_column_with_hash_bucket(('key',), 10) + fc._categorical_column_with_hash_bucket(('key',), 10) def test_bucket_size_should_be_given(self): with self.assertRaisesRegexp(ValueError, 'hash_bucket_size must be set.'): - fc.categorical_column_with_hash_bucket('aaa', None) + fc._categorical_column_with_hash_bucket('aaa', None) def test_bucket_size_should_be_positive(self): with self.assertRaisesRegexp(ValueError, 'hash_bucket_size must be at least 1'): - fc.categorical_column_with_hash_bucket('aaa', 0) + fc._categorical_column_with_hash_bucket('aaa', 0) def test_dtype_should_be_string_or_integer(self): - fc.categorical_column_with_hash_bucket('aaa', 10, dtype=dtypes.string) - fc.categorical_column_with_hash_bucket('aaa', 10, dtype=dtypes.int32) + fc._categorical_column_with_hash_bucket('aaa', 10, dtype=dtypes.string) + fc._categorical_column_with_hash_bucket('aaa', 10, dtype=dtypes.int32) with self.assertRaisesRegexp(ValueError, 'dtype must be string or integer'): - fc.categorical_column_with_hash_bucket('aaa', 10, dtype=dtypes.float32) + fc._categorical_column_with_hash_bucket('aaa', 10, dtype=dtypes.float32) + @test_util.run_deprecated_v1 def test_deep_copy(self): - original = fc.categorical_column_with_hash_bucket('aaa', 10) + original = fc._categorical_column_with_hash_bucket('aaa', 10) for column in (original, copy.deepcopy(original)): self.assertEqual('aaa', column.name) self.assertEqual(10, column.hash_bucket_size) @@ -689,19 +708,20 @@ class HashedCategoricalColumnTest(test.TestCase): self.assertEqual(dtypes.string, column.dtype) def test_parse_spec_string(self): - a = fc.categorical_column_with_hash_bucket('aaa', 10) + a = fc._categorical_column_with_hash_bucket('aaa', 10) self.assertEqual({ 'aaa': parsing_ops.VarLenFeature(dtypes.string) }, a._parse_example_spec) def test_parse_spec_int(self): - a = fc.categorical_column_with_hash_bucket('aaa', 10, dtype=dtypes.int32) + a = fc._categorical_column_with_hash_bucket('aaa', 10, dtype=dtypes.int32) self.assertEqual({ 'aaa': parsing_ops.VarLenFeature(dtypes.int32) }, a._parse_example_spec) + @test_util.run_deprecated_v1 def test_parse_example(self): - a = fc.categorical_column_with_hash_bucket('aaa', 10) + a = fc._categorical_column_with_hash_bucket('aaa', 10) data = example_pb2.Example(features=feature_pb2.Features( feature={ 'aaa': @@ -721,8 +741,9 @@ class HashedCategoricalColumnTest(test.TestCase): dense_shape=[1, 2]), features['aaa'].eval()) + @test_util.run_deprecated_v1 def test_strings_should_be_hashed(self): - hashed_sparse = fc.categorical_column_with_hash_bucket('wire', 10) + hashed_sparse = fc._categorical_column_with_hash_bucket('wire', 10) wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], indices=[[0, 0], [1, 0], [1, 1]], @@ -739,11 +760,11 @@ class HashedCategoricalColumnTest(test.TestCase): output.dense_shape.eval()) def test_tensor_dtype_should_be_string_or_integer(self): - string_fc = fc.categorical_column_with_hash_bucket( + string_fc = fc._categorical_column_with_hash_bucket( 'a_string', 10, dtype=dtypes.string) - int_fc = fc.categorical_column_with_hash_bucket( + int_fc = fc._categorical_column_with_hash_bucket( 'a_int', 10, dtype=dtypes.int32) - float_fc = fc.categorical_column_with_hash_bucket( + float_fc = fc._categorical_column_with_hash_bucket( 'a_float', 10, dtype=dtypes.string) int_tensor = sparse_tensor.SparseTensor( values=[101], @@ -768,7 +789,7 @@ class HashedCategoricalColumnTest(test.TestCase): builder.get(float_fc) def test_dtype_should_match_with_tensor(self): - hashed_sparse = fc.categorical_column_with_hash_bucket( + hashed_sparse = fc._categorical_column_with_hash_bucket( 'wire', 10, dtype=dtypes.int64) wire_tensor = sparse_tensor.SparseTensor( values=['omar'], indices=[[0, 0]], dense_shape=[1, 1]) @@ -776,8 +797,9 @@ class HashedCategoricalColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'dtype must be compatible'): builder.get(hashed_sparse) + @test_util.run_deprecated_v1 def test_ints_should_be_hashed(self): - hashed_sparse = fc.categorical_column_with_hash_bucket( + hashed_sparse = fc._categorical_column_with_hash_bucket( 'wire', 10, dtype=dtypes.int64) wire_tensor = sparse_tensor.SparseTensor( values=[101, 201, 301], @@ -790,8 +812,9 @@ class HashedCategoricalColumnTest(test.TestCase): with self.cached_session(): self.assertAllEqual(expected_values, output.values.eval()) + @test_util.run_deprecated_v1 def test_int32_64_is_compatible(self): - hashed_sparse = fc.categorical_column_with_hash_bucket( + hashed_sparse = fc._categorical_column_with_hash_bucket( 'wire', 10, dtype=dtypes.int64) wire_tensor = sparse_tensor.SparseTensor( values=constant_op.constant([101, 201, 301], dtype=dtypes.int32), @@ -804,8 +827,9 @@ class HashedCategoricalColumnTest(test.TestCase): with self.cached_session(): self.assertAllEqual(expected_values, output.values.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): - hashed_sparse = fc.categorical_column_with_hash_bucket('wire', 10) + hashed_sparse = fc._categorical_column_with_hash_bucket('wire', 10) builder = _LazyBuilder({ 'wire': sparse_tensor.SparseTensor( @@ -818,7 +842,7 @@ class HashedCategoricalColumnTest(test.TestCase): self.assertEqual(builder.get(hashed_sparse), id_weight_pair.id_tensor) def test_get_sparse_tensors_weight_collections(self): - column = fc.categorical_column_with_hash_bucket('aaa', 10) + column = fc._categorical_column_with_hash_bucket('aaa', 10) inputs = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], indices=[[0, 0], [1, 0], [1, 1]], @@ -832,15 +856,17 @@ class HashedCategoricalColumnTest(test.TestCase): [], ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)) self.assertItemsEqual([], ops.get_collection('my_weights')) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_dense_input(self): - hashed_sparse = fc.categorical_column_with_hash_bucket('wire', 10) + hashed_sparse = fc._categorical_column_with_hash_bucket('wire', 10) builder = _LazyBuilder({'wire': (('omar', ''), ('stringer', 'marlo'))}) id_weight_pair = hashed_sparse._get_sparse_tensors(builder) self.assertIsNone(id_weight_pair.weight_tensor) self.assertEqual(builder.get(hashed_sparse), id_weight_pair.id_tensor) + @test_util.run_deprecated_v1 def test_linear_model(self): - wire_column = fc.categorical_column_with_hash_bucket('wire', 4) + wire_column = fc._categorical_column_with_hash_bucket('wire', 4) self.assertEqual(4, wire_column._num_buckets) with ops.Graph().as_default(): predictions = fc.linear_model({ @@ -852,16 +878,18 @@ class HashedCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() wire_var = get_linear_model_column_var(wire_column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), + self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() # 'marlo' -> 3: wire_var[3] = 4 # 'skywalker' -> 2, 'omar' -> 2: wire_var[2] + wire_var[2] = 3+3 = 6 - self.assertAllClose(((4.,), (6.,)), predictions.eval()) + self.assertAllClose(((4.,), (6.,)), self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): - wire_column = fc.categorical_column_with_hash_bucket('wire', 4) + wire_column = fc._categorical_column_with_hash_bucket('wire', 4) self.assertEqual(4, wire_column._num_buckets) with ops.Graph().as_default(): predictions = get_keras_linear_model_predictions({ @@ -874,13 +902,14 @@ class HashedCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() wire_var = get_linear_model_column_var(wire_column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), + self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() # 'marlo' -> 3: wire_var[3] = 4 # 'skywalker' -> 2, 'omar' -> 2: wire_var[2] + wire_var[2] = 3+3 = 6 - self.assertAllClose(((4.,), (6.,)), predictions.eval()) + self.assertAllClose(((4.,), (6.,)), self.evaluate(predictions)) class CrossedColumnTest(test.TestCase): @@ -888,100 +917,102 @@ class CrossedColumnTest(test.TestCase): def test_keys_empty(self): with self.assertRaisesRegexp( ValueError, 'keys must be a list with length > 1'): - fc.crossed_column([], 10) + fc._crossed_column([], 10) def test_keys_length_one(self): with self.assertRaisesRegexp( ValueError, 'keys must be a list with length > 1'): - fc.crossed_column(['a'], 10) + fc._crossed_column(['a'], 10) def test_key_type_unsupported(self): with self.assertRaisesRegexp(ValueError, 'Unsupported key type'): - fc.crossed_column(['a', fc.numeric_column('c')], 10) + fc._crossed_column(['a', fc._numeric_column('c')], 10) with self.assertRaisesRegexp( ValueError, 'categorical_column_with_hash_bucket is not supported'): - fc.crossed_column( - ['a', fc.categorical_column_with_hash_bucket('c', 10)], 10) + fc._crossed_column( + ['a', fc._categorical_column_with_hash_bucket('c', 10)], 10) def test_hash_bucket_size_negative(self): with self.assertRaisesRegexp( ValueError, 'hash_bucket_size must be > 1'): - fc.crossed_column(['a', 'c'], -1) + fc._crossed_column(['a', 'c'], -1) def test_hash_bucket_size_zero(self): with self.assertRaisesRegexp( ValueError, 'hash_bucket_size must be > 1'): - fc.crossed_column(['a', 'c'], 0) + fc._crossed_column(['a', 'c'], 0) def test_hash_bucket_size_none(self): with self.assertRaisesRegexp( ValueError, 'hash_bucket_size must be > 1'): - fc.crossed_column(['a', 'c'], None) + fc._crossed_column(['a', 'c'], None) def test_name(self): - a = fc.numeric_column('a', dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) - crossed1 = fc.crossed_column(['d1', 'd2'], 10) + a = fc._numeric_column('a', dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) + crossed1 = fc._crossed_column(['d1', 'd2'], 10) - crossed2 = fc.crossed_column([b, 'c', crossed1], 10) + crossed2 = fc._crossed_column([b, 'c', crossed1], 10) self.assertEqual('a_bucketized_X_c_X_d1_X_d2', crossed2.name) def test_name_ordered_alphabetically(self): """Tests that the name does not depend on the order of given columns.""" - a = fc.numeric_column('a', dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) - crossed1 = fc.crossed_column(['d1', 'd2'], 10) + a = fc._numeric_column('a', dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) + crossed1 = fc._crossed_column(['d1', 'd2'], 10) - crossed2 = fc.crossed_column([crossed1, 'c', b], 10) + crossed2 = fc._crossed_column([crossed1, 'c', b], 10) self.assertEqual('a_bucketized_X_c_X_d1_X_d2', crossed2.name) def test_name_leaf_keys_ordered_alphabetically(self): """Tests that the name does not depend on the order of given columns.""" - a = fc.numeric_column('a', dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) - crossed1 = fc.crossed_column(['d2', 'c'], 10) + a = fc._numeric_column('a', dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) + crossed1 = fc._crossed_column(['d2', 'c'], 10) - crossed2 = fc.crossed_column([crossed1, 'd1', b], 10) + crossed2 = fc._crossed_column([crossed1, 'd1', b], 10) self.assertEqual('a_bucketized_X_c_X_d1_X_d2', crossed2.name) def test_var_scope_name(self): - a = fc.numeric_column('a', dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) - crossed1 = fc.crossed_column(['d1', 'd2'], 10) + a = fc._numeric_column('a', dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) + crossed1 = fc._crossed_column(['d1', 'd2'], 10) - crossed2 = fc.crossed_column([b, 'c', crossed1], 10) + crossed2 = fc._crossed_column([b, 'c', crossed1], 10) self.assertEqual('a_bucketized_X_c_X_d1_X_d2', crossed2._var_scope_name) def test_parse_spec(self): - a = fc.numeric_column('a', shape=[2], dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) - crossed = fc.crossed_column([b, 'c'], 10) + a = fc._numeric_column('a', shape=[2], dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) + crossed = fc._crossed_column([b, 'c'], 10) self.assertEqual({ 'a': parsing_ops.FixedLenFeature((2,), dtype=dtypes.int32), 'c': parsing_ops.VarLenFeature(dtypes.string), }, crossed._parse_example_spec) def test_num_buckets(self): - a = fc.numeric_column('a', shape=[2], dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) - crossed = fc.crossed_column([b, 'c'], 15) + a = fc._numeric_column('a', shape=[2], dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) + crossed = fc._crossed_column([b, 'c'], 15) self.assertEqual(15, crossed._num_buckets) + @test_util.run_deprecated_v1 def test_deep_copy(self): - a = fc.numeric_column('a', dtype=dtypes.int32) - b = fc.bucketized_column(a, boundaries=[0, 1]) - crossed1 = fc.crossed_column(['d1', 'd2'], 10) - crossed2 = fc.crossed_column([b, 'c', crossed1], 15, hash_key=5) + a = fc._numeric_column('a', dtype=dtypes.int32) + b = fc._bucketized_column(a, boundaries=[0, 1]) + crossed1 = fc._crossed_column(['d1', 'd2'], 10) + crossed2 = fc._crossed_column([b, 'c', crossed1], 15, hash_key=5) crossed2_copy = copy.deepcopy(crossed2) self.assertEqual('a_bucketized_X_c_X_d1_X_d2', crossed2_copy.name,) self.assertEqual(15, crossed2_copy.hash_bucket_size) self.assertEqual(5, crossed2_copy.hash_key) + @test_util.run_deprecated_v1 def test_parse_example(self): - price = fc.numeric_column('price', shape=[2]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 50]) - price_cross_wire = fc.crossed_column([bucketized_price, 'wire'], 10) + price = fc._numeric_column('price', shape=[2]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 50]) + price_cross_wire = fc._crossed_column([bucketized_price, 'wire'], 10) data = example_pb2.Example(features=feature_pb2.Features( feature={ 'price': @@ -1004,12 +1035,13 @@ class CrossedColumnTest(test.TestCase): self.assertAllEqual([b'omar', b'stringer'], wire_sparse.values.eval()) self.assertAllEqual([1, 2], wire_sparse.dense_shape.eval()) + @test_util.run_deprecated_v1 def test_transform_feature(self): - price = fc.numeric_column('price', shape=[2]) - bucketized_price = fc.bucketized_column(price, boundaries=[0, 50]) + price = fc._numeric_column('price', shape=[2]) + bucketized_price = fc._bucketized_column(price, boundaries=[0, 50]) hash_bucket_size = 10 - price_cross_wire = fc.crossed_column( - [bucketized_price, 'wire'], hash_bucket_size) + price_cross_wire = fc._crossed_column([bucketized_price, 'wire'], + hash_bucket_size) features = { 'price': constant_op.constant([[1., 2.], [5., 6.]]), 'wire': sparse_tensor.SparseTensor( @@ -1020,18 +1052,19 @@ class CrossedColumnTest(test.TestCase): outputs = _transform_features(features, [price_cross_wire]) output = outputs[price_cross_wire] with self.cached_session() as sess: - output_val = sess.run(output) + output_val = self.evaluate(output) self.assertAllEqual( [[0, 0], [0, 1], [1, 0], [1, 1], [1, 2], [1, 3]], output_val.indices) for val in output_val.values: self.assertIn(val, list(range(hash_bucket_size))) self.assertAllEqual([2, 4], output_val.dense_shape) + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): - a = fc.numeric_column('a', dtype=dtypes.int32, shape=(2,)) - b = fc.bucketized_column(a, boundaries=(0, 1)) - crossed1 = fc.crossed_column(['d1', 'd2'], 10) - crossed2 = fc.crossed_column([b, 'c', crossed1], 15, hash_key=5) + a = fc._numeric_column('a', dtype=dtypes.int32, shape=(2,)) + b = fc._bucketized_column(a, boundaries=(0, 1)) + crossed1 = fc._crossed_column(['d1', 'd2'], 10) + crossed2 = fc._crossed_column([b, 'c', crossed1], 15, hash_key=5) with ops.Graph().as_default(): builder = _LazyBuilder({ 'a': @@ -1069,9 +1102,9 @@ class CrossedColumnTest(test.TestCase): def test_get_sparse_tensors_simple(self): """Same as test_get_sparse_tensors, but with simpler values.""" - a = fc.numeric_column('a', dtype=dtypes.int32, shape=(2,)) - b = fc.bucketized_column(a, boundaries=(0, 1)) - crossed = fc.crossed_column([b, 'c'], hash_bucket_size=5, hash_key=5) + a = fc._numeric_column('a', dtype=dtypes.int32, shape=(2,)) + b = fc._bucketized_column(a, boundaries=(0, 1)) + crossed = fc._crossed_column([b, 'c'], hash_bucket_size=5, hash_key=5) with ops.Graph().as_default(): builder = _LazyBuilder({ 'a': @@ -1094,14 +1127,15 @@ class CrossedColumnTest(test.TestCase): self.assertAllEqual(expected_values, id_tensor_eval.values) self.assertAllEqual((2, 4), id_tensor_eval.dense_shape) + @test_util.run_deprecated_v1 def test_linear_model(self): """Tests linear_model. Uses data from test_get_sparse_tesnsors_simple. """ - a = fc.numeric_column('a', dtype=dtypes.int32, shape=(2,)) - b = fc.bucketized_column(a, boundaries=(0, 1)) - crossed = fc.crossed_column([b, 'c'], hash_bucket_size=5, hash_key=5) + a = fc._numeric_column('a', dtype=dtypes.int32, shape=(2,)) + b = fc._bucketized_column(a, boundaries=(0, 1)) + crossed = fc._crossed_column([b, 'c'], hash_bucket_size=5, hash_key=5) with ops.Graph().as_default(): predictions = fc.linear_model({ 'a': constant_op.constant(((-1., .5), (.5, 1.))), @@ -1113,15 +1147,15 @@ class CrossedColumnTest(test.TestCase): bias = get_linear_model_bias() crossed_var = get_linear_model_column_var(crossed) with _initialized_session() as sess: - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose( - ((0.,), (0.,), (0.,), (0.,), (0.,)), crossed_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,), (0.,)), + self.evaluate(crossed_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) sess.run(crossed_var.assign(((1.,), (2.,), (3.,), (4.,), (5.,)))) # Expected ids after cross = (1, 0, 1, 3, 4, 2) - self.assertAllClose(((3.,), (14.,)), predictions.eval()) + self.assertAllClose(((3.,), (14.,)), self.evaluate(predictions)) sess.run(bias.assign((.1,))) - self.assertAllClose(((3.1,), (14.1,)), predictions.eval()) + self.assertAllClose(((3.1,), (14.1,)), self.evaluate(predictions)) def test_linear_model_with_weights(self): class _TestColumnWithWeights(_CategoricalColumn): @@ -1155,7 +1189,7 @@ class CrossedColumnTest(test.TestCase): id_tensor=ids_and_weights[0], weight_tensor=ids_and_weights[1]) t = _TestColumnWithWeights() - crossed = fc.crossed_column([t, 'c'], hash_bucket_size=5, hash_key=5) + crossed = fc._crossed_column([t, 'c'], hash_bucket_size=5, hash_key=5) with ops.Graph().as_default(): with self.assertRaisesRegexp( ValueError, @@ -1175,14 +1209,15 @@ class CrossedColumnTest(test.TestCase): dense_shape=(2, 2)), }, (crossed,)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): """Tests _LinearModel. Uses data from test_get_sparse_tesnsors_simple. """ - a = fc.numeric_column('a', dtype=dtypes.int32, shape=(2,)) - b = fc.bucketized_column(a, boundaries=(0, 1)) - crossed = fc.crossed_column([b, 'c'], hash_bucket_size=5, hash_key=5) + a = fc._numeric_column('a', dtype=dtypes.int32, shape=(2,)) + b = fc._bucketized_column(a, boundaries=(0, 1)) + crossed = fc._crossed_column([b, 'c'], hash_bucket_size=5, hash_key=5) with ops.Graph().as_default(): predictions = get_keras_linear_model_predictions({ 'a': @@ -1196,15 +1231,15 @@ class CrossedColumnTest(test.TestCase): bias = get_linear_model_bias() crossed_var = get_linear_model_column_var(crossed) with _initialized_session() as sess: - self.assertAllClose((0.,), bias.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) self.assertAllClose(((0.,), (0.,), (0.,), (0.,), (0.,)), - crossed_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.evaluate(crossed_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) sess.run(crossed_var.assign(((1.,), (2.,), (3.,), (4.,), (5.,)))) # Expected ids after cross = (1, 0, 1, 3, 4, 2) - self.assertAllClose(((3.,), (14.,)), predictions.eval()) + self.assertAllClose(((3.,), (14.,)), self.evaluate(predictions)) sess.run(bias.assign((.1,))) - self.assertAllClose(((3.1,), (14.1,)), predictions.eval()) + self.assertAllClose(((3.1,), (14.1,)), self.evaluate(predictions)) def test_keras_linear_model_with_weights(self): @@ -1242,7 +1277,7 @@ class CrossedColumnTest(test.TestCase): id_tensor=ids_and_weights[0], weight_tensor=ids_and_weights[1]) t = _TestColumnWithWeights() - crossed = fc.crossed_column([t, 'c'], hash_bucket_size=5, hash_key=5) + crossed = fc._crossed_column([t, 'c'], hash_bucket_size=5, hash_key=5) with ops.Graph().as_default(): with self.assertRaisesRegexp( ValueError, @@ -1331,31 +1366,31 @@ class LinearModelTest(test.TestCase): with self.assertRaisesRegexp( ValueError, 'Expected feature_columns to be iterable, found dict.'): fc.linear_model( - features={'a': [[0]]}, feature_columns={'a': fc.numeric_column('a')}) + features={'a': [[0]]}, feature_columns={'a': fc._numeric_column('a')}) def test_raises_if_duplicate_name(self): with self.assertRaisesRegexp( ValueError, 'Duplicate feature column name found for columns'): fc.linear_model( features={'a': [[0]]}, - feature_columns=[fc.numeric_column('a'), - fc.numeric_column('a')]) + feature_columns=[fc._numeric_column('a'), + fc._numeric_column('a')]) def test_dense_bias(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} predictions = fc.linear_model(features, [price]) bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) sess.run(price_var.assign([[10.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[15.], [55.]], predictions.eval()) + self.assertAllClose([[15.], [55.]], self.evaluate(predictions)) def test_sparse_bias(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default(): wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], # hashed to = [2, 0, 3] @@ -1366,15 +1401,16 @@ class LinearModelTest(test.TestCase): bias = get_linear_model_bias() wire_cast_var = get_linear_model_column_var(wire_cast) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.], [0.], [0.]], wire_cast_var.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.], [0.], [0.]], + self.evaluate(wire_cast_var)) sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [10015.]], predictions.eval()) + self.assertAllClose([[1005.], [10015.]], self.evaluate(predictions)) def test_dense_and_sparse_bias(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) - price = fc.numeric_column('price') + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) + price = fc._numeric_column('price') with ops.Graph().as_default(): wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], # hashed to = [2, 0, 3] @@ -1389,7 +1425,7 @@ class LinearModelTest(test.TestCase): sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) sess.run(price_var.assign([[10.]])) - self.assertAllClose([[1015.], [10065.]], predictions.eval()) + self.assertAllClose([[1015.], [10065.]], self.evaluate(predictions)) def test_dense_and_sparse_column(self): """When the column is both dense and sparse, uses sparse tensors.""" @@ -1442,25 +1478,25 @@ class LinearModelTest(test.TestCase): sess.run(dense_and_sparse_column_var.assign( [[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [10015.]], predictions.eval()) + self.assertAllClose([[1005.], [10015.]], self.evaluate(predictions)) def test_dense_multi_output(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} predictions = fc.linear_model(features, [price], units=3) bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((1, 3)), price_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((1, 3)), self.evaluate(price_var)) sess.run(price_var.assign([[10., 100., 1000.]])) sess.run(bias.assign([5., 6., 7.])) self.assertAllClose([[15., 106., 1007.], [55., 506., 5007.]], - predictions.eval()) + self.evaluate(predictions)) def test_sparse_multi_output(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default(): wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], # hashed to = [2, 0, 3] @@ -1471,29 +1507,29 @@ class LinearModelTest(test.TestCase): bias = get_linear_model_bias() wire_cast_var = get_linear_model_column_var(wire_cast) with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((4, 3)), wire_cast_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((4, 3)), self.evaluate(wire_cast_var)) sess.run( wire_cast_var.assign([[10., 11., 12.], [100., 110., 120.], [ 1000., 1100., 1200. ], [10000., 11000., 12000.]])) sess.run(bias.assign([5., 6., 7.])) self.assertAllClose([[1005., 1106., 1207.], [10015., 11017., 12019.]], - predictions.eval()) + self.evaluate(predictions)) def test_dense_multi_dimension(self): - price = fc.numeric_column('price', shape=2) + price = fc._numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1., 2.], [5., 6.]]} predictions = fc.linear_model(features, [price]) price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([[0.], [0.]], price_var.eval()) + self.assertAllClose([[0.], [0.]], self.evaluate(price_var)) sess.run(price_var.assign([[10.], [100.]])) - self.assertAllClose([[210.], [650.]], predictions.eval()) + self.assertAllClose([[210.], [650.]], self.evaluate(predictions)) def test_sparse_multi_rank(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default(): wire_tensor = array_ops.sparse_placeholder(dtypes.string) wire_value = sparse_tensor.SparseTensorValue( @@ -1504,7 +1540,7 @@ class LinearModelTest(test.TestCase): predictions = fc.linear_model(features, [wire_cast]) wire_cast_var = get_linear_model_column_var(wire_cast) with _initialized_session() as sess: - self.assertAllClose(np.zeros((4, 1)), wire_cast_var.eval()) + self.assertAllClose(np.zeros((4, 1)), self.evaluate(wire_cast_var)) self.assertAllClose( np.zeros((2, 1)), predictions.eval(feed_dict={wire_tensor: wire_value})) @@ -1514,7 +1550,7 @@ class LinearModelTest(test.TestCase): predictions.eval(feed_dict={wire_tensor: wire_value})) def test_sparse_combiner(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default(): wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], # hashed to = [2, 0, 3] @@ -1528,11 +1564,11 @@ class LinearModelTest(test.TestCase): with _initialized_session() as sess: sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [5010.]], predictions.eval()) + self.assertAllClose([[1005.], [5010.]], self.evaluate(predictions)) def test_sparse_combiner_with_negative_weights(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) - wire_cast_weights = fc.weighted_categorical_column(wire_cast, 'weights') + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast_weights = fc._weighted_categorical_column(wire_cast, 'weights') with ops.Graph().as_default(): wire_tensor = sparse_tensor.SparseTensor( @@ -1550,25 +1586,25 @@ class LinearModelTest(test.TestCase): with _initialized_session() as sess: sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [-9985.]], predictions.eval()) + self.assertAllClose([[1005.], [-9985.]], self.evaluate(predictions)) def test_dense_multi_dimension_multi_output(self): - price = fc.numeric_column('price', shape=2) + price = fc._numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1., 2.], [5., 6.]]} predictions = fc.linear_model(features, [price], units=3) bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((2, 3)), price_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((2, 3)), self.evaluate(price_var)) sess.run(price_var.assign([[1., 2., 3.], [10., 100., 1000.]])) sess.run(bias.assign([2., 3., 4.])) self.assertAllClose([[23., 205., 2007.], [67., 613., 6019.]], - predictions.eval()) + self.evaluate(predictions)) def test_raises_if_shape_mismatch(self): - price = fc.numeric_column('price', shape=2) + price = fc._numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} with self.assertRaisesRegexp( @@ -1577,22 +1613,22 @@ class LinearModelTest(test.TestCase): fc.linear_model(features, [price]) def test_dense_reshaping(self): - price = fc.numeric_column('price', shape=[1, 2]) + price = fc._numeric_column('price', shape=[1, 2]) with ops.Graph().as_default(): features = {'price': [[[1., 2.]], [[5., 6.]]]} predictions = fc.linear_model(features, [price]) bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.]], price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.]], self.evaluate(price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price_var.assign([[10.], [100.]])) - self.assertAllClose([[210.], [650.]], predictions.eval()) + self.assertAllClose([[210.], [650.]], self.evaluate(predictions)) def test_dense_multi_column(self): - price1 = fc.numeric_column('price1', shape=2) - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1', shape=2) + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': [[1., 2.], [5., 6.]], @@ -1603,18 +1639,18 @@ class LinearModelTest(test.TestCase): price1_var = get_linear_model_column_var(price1) price2_var = get_linear_model_column_var(price2) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.]], price1_var.eval()) - self.assertAllClose([[0.]], price2_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.]], self.evaluate(price1_var)) + self.assertAllClose([[0.]], self.evaluate(price2_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price1_var.assign([[10.], [100.]])) sess.run(price2_var.assign([[1000.]])) sess.run(bias.assign([7.])) - self.assertAllClose([[3217.], [4657.]], predictions.eval()) + self.assertAllClose([[3217.], [4657.]], self.evaluate(predictions)) def test_fills_cols_to_vars(self): - price1 = fc.numeric_column('price1', shape=2) - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1', shape=2) + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = {'price1': [[1., 2.], [5., 6.]], 'price2': [[3.], [4.]]} cols_to_vars = {} @@ -1627,8 +1663,8 @@ class LinearModelTest(test.TestCase): self.assertAllEqual(cols_to_vars[price2], [price2_var]) def test_fills_cols_to_vars_partitioned_variables(self): - price1 = fc.numeric_column('price1', shape=2) - price2 = fc.numeric_column('price2', shape=3) + price1 = fc._numeric_column('price1', shape=2) + price2 = fc._numeric_column('price2', shape=3) with ops.Graph().as_default(): features = { 'price1': [[1., 2.], [6., 7.]], @@ -1653,13 +1689,13 @@ class LinearModelTest(test.TestCase): # Provide three _DenseColumn's to input_layer: a _NumericColumn, a # _BucketizedColumn, and an _EmbeddingColumn. Only the _EmbeddingColumn # creates a Variable. - apple_numeric_column = fc.numeric_column('apple_numeric_column') - banana_dense_feature = fc.numeric_column('banana_dense_feature') - banana_dense_feature_bucketized = fc.bucketized_column( + apple_numeric_column = fc._numeric_column('apple_numeric_column') + banana_dense_feature = fc._numeric_column('banana_dense_feature') + banana_dense_feature_bucketized = fc._bucketized_column( banana_dense_feature, boundaries=[0.]) - cherry_sparse_column = fc.categorical_column_with_hash_bucket( + cherry_sparse_column = fc._categorical_column_with_hash_bucket( 'cherry_sparse_feature', hash_bucket_size=5) - dragonfruit_embedding_column = fc.embedding_column( + dragonfruit_embedding_column = fc._embedding_column( cherry_sparse_column, dimension=10) with ops.Graph().as_default(): features = { @@ -1684,7 +1720,7 @@ class LinearModelTest(test.TestCase): self.assertItemsEqual(input_layer_inputs, output_tensors) def test_dense_collection(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default() as g: features = {'price': [[1.], [5.]]} fc.linear_model(features, [price], weight_collections=['my-vars']) @@ -1695,7 +1731,7 @@ class LinearModelTest(test.TestCase): self.assertIn(price_var, my_vars) def test_sparse_collection(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default() as g: wire_tensor = sparse_tensor.SparseTensor( values=['omar'], indices=[[0, 0]], dense_shape=[1, 1]) @@ -1709,7 +1745,7 @@ class LinearModelTest(test.TestCase): self.assertIn(wire_cast_var, my_vars) def test_dense_trainable_default(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default() as g: features = {'price': [[1.], [5.]]} fc.linear_model(features, [price]) @@ -1720,7 +1756,7 @@ class LinearModelTest(test.TestCase): self.assertIn(price_var, trainable_vars) def test_sparse_trainable_default(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default() as g: wire_tensor = sparse_tensor.SparseTensor( values=['omar'], indices=[[0, 0]], dense_shape=[1, 1]) @@ -1733,7 +1769,7 @@ class LinearModelTest(test.TestCase): self.assertIn(wire_cast_var, trainable_vars) def test_dense_trainable_false(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default() as g: features = {'price': [[1.], [5.]]} fc.linear_model(features, [price], trainable=False) @@ -1741,7 +1777,7 @@ class LinearModelTest(test.TestCase): self.assertEqual([], trainable_vars) def test_sparse_trainable_false(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default() as g: wire_tensor = sparse_tensor.SparseTensor( values=['omar'], indices=[[0, 0]], dense_shape=[1, 1]) @@ -1751,9 +1787,9 @@ class LinearModelTest(test.TestCase): self.assertEqual([], trainable_vars) def test_column_order(self): - price_a = fc.numeric_column('price_a') - price_b = fc.numeric_column('price_b') - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + price_a = fc._numeric_column('price_a') + price_b = fc._numeric_column('price_b') + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default() as g: features = { 'price_a': [[1.]], @@ -1787,8 +1823,8 @@ class LinearModelTest(test.TestCase): self.assertIn('wire_cast', my_vars[2].name) def test_static_batch_size_mismatch(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': [[1.], [5.], [7.]], # batchsize = 3 @@ -1800,9 +1836,9 @@ class LinearModelTest(test.TestCase): fc.linear_model(features, [price1, price2]) def test_subset_of_static_batch_size_mismatch(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') - price3 = fc.numeric_column('price3') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') + price3 = fc._numeric_column('price3') with ops.Graph().as_default(): features = { 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 3 @@ -1815,8 +1851,8 @@ class LinearModelTest(test.TestCase): fc.linear_model(features, [price1, price2, price3]) def test_runtime_batch_size_mismatch(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 3 @@ -1830,8 +1866,8 @@ class LinearModelTest(test.TestCase): predictions, feed_dict={features['price1']: [[1.], [5.], [7.]]}) def test_runtime_batch_size_matches(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 2 @@ -1846,10 +1882,16 @@ class LinearModelTest(test.TestCase): features['price2']: [[1.], [5.]], }) + @test_util.run_deprecated_v1 def test_with_1d_sparse_tensor(self): - price = fc.numeric_column('price') - price_buckets = fc.bucketized_column(price, boundaries=[0., 10., 100.,]) - body_style = fc.categorical_column_with_vocabulary_list( + price = fc._numeric_column('price') + price_buckets = fc._bucketized_column( + price, boundaries=[ + 0., + 10., + 100., + ]) + body_style = fc._categorical_column_with_vocabulary_list( 'body-style', vocabulary_list=['hardtop', 'wagon', 'sedan']) # Provides 1-dim tensor and dense tensor. @@ -1873,14 +1915,21 @@ class LinearModelTest(test.TestCase): sess.run(body_style_var.assign([[-10.], [-100.], [-1000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[10 - 1000 + 5.], [1000 - 10 + 5.]], sess.run(net)) + self.assertAllClose([[10 - 1000 + 5.], [1000 - 10 + 5.]], + self.evaluate(net)) + @test_util.run_deprecated_v1 def test_with_1d_unknown_shape_sparse_tensor(self): - price = fc.numeric_column('price') - price_buckets = fc.bucketized_column(price, boundaries=[0., 10., 100.,]) - body_style = fc.categorical_column_with_vocabulary_list( + price = fc._numeric_column('price') + price_buckets = fc._bucketized_column( + price, boundaries=[ + 0., + 10., + 100., + ]) + body_style = fc._categorical_column_with_vocabulary_list( 'body-style', vocabulary_list=['hardtop', 'wagon', 'sedan']) - country = fc.categorical_column_with_vocabulary_list( + country = fc._categorical_column_with_vocabulary_list( 'country', vocabulary_list=['US', 'JP', 'CA']) # Provides 1-dim tensor and dense tensor. @@ -1917,8 +1966,9 @@ class LinearModelTest(test.TestCase): features['country']: country_data })) + @test_util.run_deprecated_v1 def test_with_rank_0_feature(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') features = { 'price': constant_op.constant(0), } @@ -1939,7 +1989,7 @@ class LinearModelTest(test.TestCase): sess.run(net, feed_dict={features['price']: np.array(1)}) def test_multiple_linear_models(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default(): features1 = {'price': [[1.], [5.]]} features2 = {'price': [[2.], [10.]]} @@ -1950,14 +2000,14 @@ class LinearModelTest(test.TestCase): price_var1 = get_linear_model_column_var(price, name='linear_model') price_var2 = get_linear_model_column_var(price, name='linear_model_1') with _initialized_session() as sess: - self.assertAllClose([0.], bias1.eval()) + self.assertAllClose([0.], self.evaluate(bias1)) sess.run(price_var1.assign([[10.]])) sess.run(bias1.assign([5.])) - self.assertAllClose([[15.], [55.]], predictions1.eval()) - self.assertAllClose([0.], bias2.eval()) + self.assertAllClose([[15.], [55.]], self.evaluate(predictions1)) + self.assertAllClose([0.], self.evaluate(bias2)) sess.run(price_var2.assign([[10.]])) sess.run(bias2.assign([5.])) - self.assertAllClose([[25.], [105.]], predictions2.eval()) + self.assertAllClose([[25.], [105.]], self.evaluate(predictions2)) class _LinearModelTest(test.TestCase): @@ -1996,31 +2046,31 @@ class _LinearModelTest(test.TestCase): with self.assertRaisesRegexp( ValueError, 'Expected feature_columns to be iterable, found dict.'): fc.linear_model( - features={'a': [[0]]}, feature_columns={'a': fc.numeric_column('a')}) + features={'a': [[0]]}, feature_columns={'a': fc._numeric_column('a')}) def test_raises_if_duplicate_name(self): with self.assertRaisesRegexp( ValueError, 'Duplicate feature column name found for columns'): get_keras_linear_model_predictions( features={'a': [[0]]}, - feature_columns=[fc.numeric_column('a'), - fc.numeric_column('a')]) + feature_columns=[fc._numeric_column('a'), + fc._numeric_column('a')]) def test_dense_bias(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} predictions = get_keras_linear_model_predictions(features, [price]) bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) sess.run(price_var.assign([[10.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[15.], [55.]], predictions.eval()) + self.assertAllClose([[15.], [55.]], self.evaluate(predictions)) def test_sparse_bias(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default(): wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], # hashed to = [2, 0, 3] @@ -2031,15 +2081,16 @@ class _LinearModelTest(test.TestCase): bias = get_linear_model_bias() wire_cast_var = get_linear_model_column_var(wire_cast) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.], [0.], [0.]], wire_cast_var.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.], [0.], [0.]], + self.evaluate(wire_cast_var)) sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [10015.]], predictions.eval()) + self.assertAllClose([[1005.], [10015.]], self.evaluate(predictions)) def test_dense_and_sparse_bias(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) - price = fc.numeric_column('price') + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) + price = fc._numeric_column('price') with ops.Graph().as_default(): wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], # hashed to = [2, 0, 3] @@ -2055,7 +2106,7 @@ class _LinearModelTest(test.TestCase): sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) sess.run(price_var.assign([[10.]])) - self.assertAllClose([[1015.], [10065.]], predictions.eval()) + self.assertAllClose([[1015.], [10065.]], self.evaluate(predictions)) def test_dense_and_sparse_column(self): """When the column is both dense and sparse, uses sparse tensors.""" @@ -2114,10 +2165,10 @@ class _LinearModelTest(test.TestCase): dense_and_sparse_column_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [10015.]], predictions.eval()) + self.assertAllClose([[1005.], [10015.]], self.evaluate(predictions)) def test_dense_multi_output(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} predictions = get_keras_linear_model_predictions( @@ -2125,15 +2176,15 @@ class _LinearModelTest(test.TestCase): bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((1, 3)), price_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((1, 3)), self.evaluate(price_var)) sess.run(price_var.assign([[10., 100., 1000.]])) sess.run(bias.assign([5., 6., 7.])) self.assertAllClose([[15., 106., 1007.], [55., 506., 5007.]], - predictions.eval()) + self.evaluate(predictions)) def test_sparse_multi_output(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default(): wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], # hashed to = [2, 0, 3] @@ -2145,29 +2196,29 @@ class _LinearModelTest(test.TestCase): bias = get_linear_model_bias() wire_cast_var = get_linear_model_column_var(wire_cast) with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((4, 3)), wire_cast_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((4, 3)), self.evaluate(wire_cast_var)) sess.run( wire_cast_var.assign([[10., 11., 12.], [100., 110., 120.], [1000., 1100., 1200.], [10000., 11000., 12000.]])) sess.run(bias.assign([5., 6., 7.])) self.assertAllClose([[1005., 1106., 1207.], [10015., 11017., 12019.]], - predictions.eval()) + self.evaluate(predictions)) def test_dense_multi_dimension(self): - price = fc.numeric_column('price', shape=2) + price = fc._numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1., 2.], [5., 6.]]} predictions = get_keras_linear_model_predictions(features, [price]) price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([[0.], [0.]], price_var.eval()) + self.assertAllClose([[0.], [0.]], self.evaluate(price_var)) sess.run(price_var.assign([[10.], [100.]])) - self.assertAllClose([[210.], [650.]], predictions.eval()) + self.assertAllClose([[210.], [650.]], self.evaluate(predictions)) def test_sparse_multi_rank(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default(): wire_tensor = array_ops.sparse_placeholder(dtypes.string) wire_value = sparse_tensor.SparseTensorValue( @@ -2178,7 +2229,7 @@ class _LinearModelTest(test.TestCase): predictions = get_keras_linear_model_predictions(features, [wire_cast]) wire_cast_var = get_linear_model_column_var(wire_cast) with _initialized_session() as sess: - self.assertAllClose(np.zeros((4, 1)), wire_cast_var.eval()) + self.assertAllClose(np.zeros((4, 1)), self.evaluate(wire_cast_var)) self.assertAllClose( np.zeros((2, 1)), predictions.eval(feed_dict={wire_tensor: wire_value})) @@ -2188,7 +2239,7 @@ class _LinearModelTest(test.TestCase): predictions.eval(feed_dict={wire_tensor: wire_value})) def test_sparse_combiner(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default(): wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], # hashed to = [2, 0, 3] @@ -2202,10 +2253,10 @@ class _LinearModelTest(test.TestCase): with _initialized_session() as sess: sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [5010.]], predictions.eval()) + self.assertAllClose([[1005.], [5010.]], self.evaluate(predictions)) def test_dense_multi_dimension_multi_output(self): - price = fc.numeric_column('price', shape=2) + price = fc._numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1., 2.], [5., 6.]]} predictions = get_keras_linear_model_predictions( @@ -2213,15 +2264,15 @@ class _LinearModelTest(test.TestCase): bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((2, 3)), price_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((2, 3)), self.evaluate(price_var)) sess.run(price_var.assign([[1., 2., 3.], [10., 100., 1000.]])) sess.run(bias.assign([2., 3., 4.])) self.assertAllClose([[23., 205., 2007.], [67., 613., 6019.]], - predictions.eval()) + self.evaluate(predictions)) def test_raises_if_shape_mismatch(self): - price = fc.numeric_column('price', shape=2) + price = fc._numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} with self.assertRaisesRegexp( @@ -2230,22 +2281,22 @@ class _LinearModelTest(test.TestCase): get_keras_linear_model_predictions(features, [price]) def test_dense_reshaping(self): - price = fc.numeric_column('price', shape=[1, 2]) + price = fc._numeric_column('price', shape=[1, 2]) with ops.Graph().as_default(): features = {'price': [[[1., 2.]], [[5., 6.]]]} predictions = get_keras_linear_model_predictions(features, [price]) bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.]], price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.]], self.evaluate(price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price_var.assign([[10.], [100.]])) - self.assertAllClose([[210.], [650.]], predictions.eval()) + self.assertAllClose([[210.], [650.]], self.evaluate(predictions)) def test_dense_multi_column(self): - price1 = fc.numeric_column('price1', shape=2) - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1', shape=2) + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = {'price1': [[1., 2.], [5., 6.]], 'price2': [[3.], [4.]]} predictions = get_keras_linear_model_predictions(features, @@ -2254,18 +2305,18 @@ class _LinearModelTest(test.TestCase): price1_var = get_linear_model_column_var(price1) price2_var = get_linear_model_column_var(price2) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.]], price1_var.eval()) - self.assertAllClose([[0.]], price2_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.]], self.evaluate(price1_var)) + self.assertAllClose([[0.]], self.evaluate(price2_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price1_var.assign([[10.], [100.]])) sess.run(price2_var.assign([[1000.]])) sess.run(bias.assign([7.])) - self.assertAllClose([[3217.], [4657.]], predictions.eval()) + self.assertAllClose([[3217.], [4657.]], self.evaluate(predictions)) def test_fills_cols_to_vars(self): - price1 = fc.numeric_column('price1', shape=2) - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1', shape=2) + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = {'price1': [[1., 2.], [5., 6.]], 'price2': [[3.], [4.]]} cols_to_vars = {} @@ -2279,8 +2330,8 @@ class _LinearModelTest(test.TestCase): self.assertAllEqual(cols_to_vars[price2], [price2_var]) def test_fills_cols_to_vars_partitioned_variables(self): - price1 = fc.numeric_column('price1', shape=2) - price2 = fc.numeric_column('price2', shape=3) + price1 = fc._numeric_column('price1', shape=2) + price2 = fc._numeric_column('price2', shape=3) with ops.Graph().as_default(): features = { 'price1': [[1., 2.], [6., 7.]], @@ -2303,7 +2354,7 @@ class _LinearModelTest(test.TestCase): self.assertAllEqual([[0.]], cols_to_vars[price2][1].eval()) def test_dense_collection(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default() as g: features = {'price': [[1.], [5.]]} get_keras_linear_model_predictions( @@ -2315,7 +2366,7 @@ class _LinearModelTest(test.TestCase): self.assertIn(price_var, my_vars) def test_sparse_collection(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default() as g: wire_tensor = sparse_tensor.SparseTensor( values=['omar'], indices=[[0, 0]], dense_shape=[1, 1]) @@ -2329,7 +2380,7 @@ class _LinearModelTest(test.TestCase): self.assertIn(wire_cast_var, my_vars) def test_dense_trainable_default(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default() as g: features = {'price': [[1.], [5.]]} get_keras_linear_model_predictions(features, [price]) @@ -2340,7 +2391,7 @@ class _LinearModelTest(test.TestCase): self.assertIn(price_var, trainable_vars) def test_sparse_trainable_default(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default() as g: wire_tensor = sparse_tensor.SparseTensor( values=['omar'], indices=[[0, 0]], dense_shape=[1, 1]) @@ -2353,7 +2404,7 @@ class _LinearModelTest(test.TestCase): self.assertIn(wire_cast_var, trainable_vars) def test_dense_trainable_false(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default() as g: features = {'price': [[1.], [5.]]} get_keras_linear_model_predictions(features, [price], trainable=False) @@ -2361,7 +2412,7 @@ class _LinearModelTest(test.TestCase): self.assertEqual([], trainable_vars) def test_sparse_trainable_false(self): - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default() as g: wire_tensor = sparse_tensor.SparseTensor( values=['omar'], indices=[[0, 0]], dense_shape=[1, 1]) @@ -2371,9 +2422,9 @@ class _LinearModelTest(test.TestCase): self.assertEqual([], trainable_vars) def test_column_order(self): - price_a = fc.numeric_column('price_a') - price_b = fc.numeric_column('price_b') - wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) + price_a = fc._numeric_column('price_a') + price_b = fc._numeric_column('price_b') + wire_cast = fc._categorical_column_with_hash_bucket('wire_cast', 4) with ops.Graph().as_default() as g: features = { 'price_a': [[1.]], @@ -2407,8 +2458,8 @@ class _LinearModelTest(test.TestCase): self.assertIn('wire_cast', my_vars[2].name) def test_static_batch_size_mismatch(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': [[1.], [5.], [7.]], # batchsize = 3 @@ -2420,9 +2471,9 @@ class _LinearModelTest(test.TestCase): get_keras_linear_model_predictions(features, [price1, price2]) def test_subset_of_static_batch_size_mismatch(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') - price3 = fc.numeric_column('price3') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') + price3 = fc._numeric_column('price3') with ops.Graph().as_default(): features = { 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 3 @@ -2435,8 +2486,8 @@ class _LinearModelTest(test.TestCase): get_keras_linear_model_predictions(features, [price1, price2, price3]) def test_runtime_batch_size_mismatch(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 3 @@ -2451,8 +2502,8 @@ class _LinearModelTest(test.TestCase): predictions, feed_dict={features['price1']: [[1.], [5.], [7.]]}) def test_runtime_batch_size_matches(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 2 @@ -2468,15 +2519,16 @@ class _LinearModelTest(test.TestCase): features['price2']: [[1.], [5.]], }) + @test_util.run_deprecated_v1 def test_with_1d_sparse_tensor(self): - price = fc.numeric_column('price') - price_buckets = fc.bucketized_column( + price = fc._numeric_column('price') + price_buckets = fc._bucketized_column( price, boundaries=[ 0., 10., 100., ]) - body_style = fc.categorical_column_with_vocabulary_list( + body_style = fc._categorical_column_with_vocabulary_list( 'body-style', vocabulary_list=['hardtop', 'wagon', 'sedan']) # Provides 1-dim tensor and dense tensor. @@ -2506,19 +2558,21 @@ class _LinearModelTest(test.TestCase): sess.run(body_style_var.assign([[-10.], [-100.], [-1000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[10 - 1000 + 5.], [1000 - 10 + 5.]], sess.run(net)) + self.assertAllClose([[10 - 1000 + 5.], [1000 - 10 + 5.]], + self.evaluate(net)) + @test_util.run_deprecated_v1 def test_with_1d_unknown_shape_sparse_tensor(self): - price = fc.numeric_column('price') - price_buckets = fc.bucketized_column( + price = fc._numeric_column('price') + price_buckets = fc._bucketized_column( price, boundaries=[ 0., 10., 100., ]) - body_style = fc.categorical_column_with_vocabulary_list( + body_style = fc._categorical_column_with_vocabulary_list( 'body-style', vocabulary_list=['hardtop', 'wagon', 'sedan']) - country = fc.categorical_column_with_vocabulary_list( + country = fc._categorical_column_with_vocabulary_list( 'country', vocabulary_list=['US', 'JP', 'CA']) # Provides 1-dim tensor and dense tensor. @@ -2554,8 +2608,9 @@ class _LinearModelTest(test.TestCase): features['country']: country_data })) + @test_util.run_deprecated_v1 def test_with_rank_0_feature(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') features = { 'price': constant_op.constant(0), } @@ -2581,7 +2636,7 @@ class InputLayerTest(test.TestCase): @test_util.run_in_graph_and_eager_modes def test_retrieving_input(self): features = {'a': [0.]} - input_layer = InputLayer(fc.numeric_column('a')) + input_layer = InputLayer(fc._numeric_column('a')) inputs = self.evaluate(input_layer(features)) self.assertAllClose([[0.]], inputs) @@ -2593,8 +2648,8 @@ class InputLayerTest(test.TestCase): dense_shape=(3, 3)) # Create feature columns (categorical and embedding). - categorical_column = fc.categorical_column_with_identity(key='a', - num_buckets=3) + categorical_column = fc._categorical_column_with_identity( + key='a', num_buckets=3) embedding_dimension = 2 def _embedding_column_initializer(shape, dtype, partition_info): del shape # unused @@ -2605,7 +2660,8 @@ class InputLayerTest(test.TestCase): (0, 1), # id 1 (1, 1)) # id 2 return embedding_values - embedding_column = fc.embedding_column( + + embedding_column = fc._embedding_column( categorical_column, dimension=embedding_dimension, initializer=_embedding_column_initializer) @@ -2636,8 +2692,8 @@ class InputLayerTest(test.TestCase): dense_shape=(3, 3)) # Create feature columns (categorical and embedding). - categorical_column = fc.categorical_column_with_identity(key='a', - num_buckets=3) + categorical_column = fc._categorical_column_with_identity( + key='a', num_buckets=3) embedding_dimension = 2 def _embedding_column_initializer(shape, dtype, partition_info): @@ -2650,7 +2706,7 @@ class InputLayerTest(test.TestCase): (1, 1)) # id 2 return embedding_values - embedding_column = fc.embedding_column( + embedding_column = fc._embedding_column( categorical_column, dimension=embedding_dimension, initializer=_embedding_column_initializer) @@ -2687,56 +2743,56 @@ class FunctionalInputLayerTest(test.TestCase): fc.input_layer( features={'a': [[0]]}, feature_columns=[ - fc.categorical_column_with_hash_bucket('wire_cast', 4) + fc._categorical_column_with_hash_bucket('wire_cast', 4) ]) def test_does_not_support_dict_columns(self): with self.assertRaisesRegexp( ValueError, 'Expected feature_columns to be iterable, found dict.'): fc.input_layer( - features={'a': [[0]]}, feature_columns={'a': fc.numeric_column('a')}) + features={'a': [[0]]}, feature_columns={'a': fc._numeric_column('a')}) def test_bare_column(self): with ops.Graph().as_default(): features = features = {'a': [0.]} - net = fc.input_layer(features, fc.numeric_column('a')) + net = fc.input_layer(features, fc._numeric_column('a')) with _initialized_session(): - self.assertAllClose([[0.]], net.eval()) + self.assertAllClose([[0.]], self.evaluate(net)) def test_column_generator(self): with ops.Graph().as_default(): features = features = {'a': [0.], 'b': [1.]} - columns = (fc.numeric_column(key) for key in features) + columns = (fc._numeric_column(key) for key in features) net = fc.input_layer(features, columns) with _initialized_session(): - self.assertAllClose([[0., 1.]], net.eval()) + self.assertAllClose([[0., 1.]], self.evaluate(net)) def test_raises_if_duplicate_name(self): with self.assertRaisesRegexp( ValueError, 'Duplicate feature column name found for columns'): fc.input_layer( features={'a': [[0]]}, - feature_columns=[fc.numeric_column('a'), - fc.numeric_column('a')]) + feature_columns=[fc._numeric_column('a'), + fc._numeric_column('a')]) def test_one_column(self): - price = fc.numeric_column('price') + price = fc._numeric_column('price') with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} net = fc.input_layer(features, [price]) with _initialized_session(): - self.assertAllClose([[1.], [5.]], net.eval()) + self.assertAllClose([[1.], [5.]], self.evaluate(net)) def test_multi_dimension(self): - price = fc.numeric_column('price', shape=2) + price = fc._numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1., 2.], [5., 6.]]} net = fc.input_layer(features, [price]) with _initialized_session(): - self.assertAllClose([[1., 2.], [5., 6.]], net.eval()) + self.assertAllClose([[1., 2.], [5., 6.]], self.evaluate(net)) def test_raises_if_shape_mismatch(self): - price = fc.numeric_column('price', shape=2) + price = fc._numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} with self.assertRaisesRegexp( @@ -2745,16 +2801,16 @@ class FunctionalInputLayerTest(test.TestCase): fc.input_layer(features, [price]) def test_reshaping(self): - price = fc.numeric_column('price', shape=[1, 2]) + price = fc._numeric_column('price', shape=[1, 2]) with ops.Graph().as_default(): features = {'price': [[[1., 2.]], [[5., 6.]]]} net = fc.input_layer(features, [price]) with _initialized_session(): - self.assertAllClose([[1., 2.], [5., 6.]], net.eval()) + self.assertAllClose([[1., 2.], [5., 6.]], self.evaluate(net)) def test_multi_column(self): - price1 = fc.numeric_column('price1', shape=2) - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1', shape=2) + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': [[1., 2.], [5., 6.]], @@ -2762,19 +2818,19 @@ class FunctionalInputLayerTest(test.TestCase): } net = fc.input_layer(features, [price1, price2]) with _initialized_session(): - self.assertAllClose([[1., 2., 3.], [5., 6., 4.]], net.eval()) + self.assertAllClose([[1., 2., 3.], [5., 6., 4.]], self.evaluate(net)) def test_fills_cols_to_vars(self): # Provide three _DenseColumn's to input_layer: a _NumericColumn, a # _BucketizedColumn, and an _EmbeddingColumn. Only the _EmbeddingColumn # creates a Variable. - price1 = fc.numeric_column('price1') - dense_feature = fc.numeric_column('dense_feature') - dense_feature_bucketized = fc.bucketized_column( + price1 = fc._numeric_column('price1') + dense_feature = fc._numeric_column('dense_feature') + dense_feature_bucketized = fc._bucketized_column( dense_feature, boundaries=[0.]) - some_sparse_column = fc.categorical_column_with_hash_bucket( + some_sparse_column = fc._categorical_column_with_hash_bucket( 'sparse_feature', hash_bucket_size=5) - some_embedding_column = fc.embedding_column( + some_embedding_column = fc._embedding_column( some_sparse_column, dimension=10) with ops.Graph().as_default(): features = { @@ -2793,24 +2849,25 @@ class FunctionalInputLayerTest(test.TestCase): variables_lib.Variable) self.assertAllEqual(cols_to_vars[some_embedding_column][0].shape, [5, 10]) + @test_util.run_deprecated_v1 def test_fills_cols_to_vars_shared_embedding(self): # Provide 5 DenseColumn's to input_layer: a NumericColumn, a # BucketizedColumn, an EmbeddingColumn, two SharedEmbeddingColumns. The # EmbeddingColumn creates a Variable and the two SharedEmbeddingColumns # shared one variable. - price1 = fc.numeric_column('price1') - dense_feature = fc.numeric_column('dense_feature') - dense_feature_bucketized = fc.bucketized_column( + price1 = fc._numeric_column('price1') + dense_feature = fc._numeric_column('dense_feature') + dense_feature_bucketized = fc._bucketized_column( dense_feature, boundaries=[0.]) - some_sparse_column = fc.categorical_column_with_hash_bucket( + some_sparse_column = fc._categorical_column_with_hash_bucket( 'sparse_feature', hash_bucket_size=5) - some_embedding_column = fc.embedding_column( + some_embedding_column = fc._embedding_column( some_sparse_column, dimension=10) - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=3) - shared_embedding_a, shared_embedding_b = fc.shared_embedding_columns( + shared_embedding_a, shared_embedding_b = fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) with ops.Graph().as_default(): features = { @@ -2850,13 +2907,13 @@ class FunctionalInputLayerTest(test.TestCase): self.assertAllEqual(cols_to_vars[shared_embedding_a][0].shape, [3, 2]) def test_fills_cols_to_vars_partitioned_variables(self): - price1 = fc.numeric_column('price1') - dense_feature = fc.numeric_column('dense_feature') - dense_feature_bucketized = fc.bucketized_column( + price1 = fc._numeric_column('price1') + dense_feature = fc._numeric_column('dense_feature') + dense_feature_bucketized = fc._bucketized_column( dense_feature, boundaries=[0.]) - some_sparse_column = fc.categorical_column_with_hash_bucket( + some_sparse_column = fc._categorical_column_with_hash_bucket( 'sparse_feature', hash_bucket_size=5) - some_embedding_column = fc.embedding_column( + some_embedding_column = fc._embedding_column( some_sparse_column, dimension=10) with ops.Graph().as_default(): features = { @@ -2883,8 +2940,8 @@ class FunctionalInputLayerTest(test.TestCase): self.assertAllEqual(cols_to_vars[some_embedding_column][2].shape, [1, 10]) def test_column_order(self): - price_a = fc.numeric_column('price_a') - price_b = fc.numeric_column('price_b') + price_a = fc._numeric_column('price_a') + price_b = fc._numeric_column('price_b') with ops.Graph().as_default(): features = { 'price_a': [[1.]], @@ -2893,11 +2950,11 @@ class FunctionalInputLayerTest(test.TestCase): net1 = fc.input_layer(features, [price_a, price_b]) net2 = fc.input_layer(features, [price_b, price_a]) with _initialized_session(): - self.assertAllClose([[1., 3.]], net1.eval()) - self.assertAllClose([[1., 3.]], net2.eval()) + self.assertAllClose([[1., 3.]], self.evaluate(net1)) + self.assertAllClose([[1., 3.]], self.evaluate(net2)) def test_fails_for_categorical_column(self): - animal = fc.categorical_column_with_identity('animal', num_buckets=4) + animal = fc._categorical_column_with_identity('animal', num_buckets=4) with ops.Graph().as_default(): features = { 'animal': @@ -2908,8 +2965,8 @@ class FunctionalInputLayerTest(test.TestCase): fc.input_layer(features, [animal]) def test_static_batch_size_mismatch(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': [[1.], [5.], [7.]], # batchsize = 3 @@ -2921,9 +2978,9 @@ class FunctionalInputLayerTest(test.TestCase): fc.input_layer(features, [price1, price2]) def test_subset_of_static_batch_size_mismatch(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') - price3 = fc.numeric_column('price3') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') + price3 = fc._numeric_column('price3') with ops.Graph().as_default(): features = { 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 3 @@ -2936,8 +2993,8 @@ class FunctionalInputLayerTest(test.TestCase): fc.input_layer(features, [price1, price2, price3]) def test_runtime_batch_size_mismatch(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 3 @@ -2950,8 +3007,8 @@ class FunctionalInputLayerTest(test.TestCase): sess.run(net, feed_dict={features['price1']: [[1.], [5.], [7.]]}) def test_runtime_batch_size_matches(self): - price1 = fc.numeric_column('price1') - price2 = fc.numeric_column('price2') + price1 = fc._numeric_column('price1') + price2 = fc._numeric_column('price2') with ops.Graph().as_default(): features = { 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 2 @@ -2967,9 +3024,9 @@ class FunctionalInputLayerTest(test.TestCase): }) def test_multiple_layers_with_same_embedding_column(self): - some_sparse_column = fc.categorical_column_with_hash_bucket( + some_sparse_column = fc._categorical_column_with_hash_bucket( 'sparse_feature', hash_bucket_size=5) - some_embedding_column = fc.embedding_column( + some_embedding_column = fc._embedding_column( some_sparse_column, dimension=10) with ops.Graph().as_default(): @@ -2990,13 +3047,14 @@ class FunctionalInputLayerTest(test.TestCase): expected_var_names, [v.name for v in ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)]) + @test_util.run_deprecated_v1 def test_multiple_layers_with_same_shared_embedding_column(self): - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=3) embedding_dimension = 2 - embedding_column_b, embedding_column_a = fc.shared_embedding_columns( + embedding_column_b, embedding_column_a = fc_new.shared_embedding_columns( [categorical_column_b, categorical_column_a], dimension=embedding_dimension) @@ -3023,13 +3081,14 @@ class FunctionalInputLayerTest(test.TestCase): ['input_layer/aaa_bbb_shared_embedding/embedding_weights:0'], [v.name for v in ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)]) + @test_util.run_deprecated_v1 def test_multiple_layers_with_same_shared_embedding_column_diff_graphs(self): - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=3) embedding_dimension = 2 - embedding_column_b, embedding_column_a = fc.shared_embedding_columns( + embedding_column_b, embedding_column_a = fc_new.shared_embedding_columns( [categorical_column_b, categorical_column_a], dimension=embedding_dimension) all_cols = [embedding_column_a, embedding_column_b] @@ -3074,6 +3133,7 @@ class FunctionalInputLayerTest(test.TestCase): ['input_layer/aaa_bbb_shared_embedding/embedding_weights:0'], [v.name for v in ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)]) + @test_util.run_deprecated_v1 def test_with_1d_sparse_tensor(self): embedding_values = ( (1., 2., 3., 4., 5.), # id 0 @@ -3085,18 +3145,18 @@ class FunctionalInputLayerTest(test.TestCase): return embedding_values # price has 1 dimension in input_layer - price = fc.numeric_column('price') + price = fc._numeric_column('price') # one_hot_body_style has 3 dims in input_layer. - body_style = fc.categorical_column_with_vocabulary_list( + body_style = fc._categorical_column_with_vocabulary_list( 'body-style', vocabulary_list=['hardtop', 'wagon', 'sedan']) - one_hot_body_style = fc.indicator_column(body_style) + one_hot_body_style = fc._indicator_column(body_style) # embedded_body_style has 5 dims in input_layer. - country = fc.categorical_column_with_vocabulary_list( + country = fc._categorical_column_with_vocabulary_list( 'country', vocabulary_list=['US', 'JP', 'CA']) - embedded_country = fc.embedding_column(country, dimension=5, - initializer=_initializer) + embedded_country = fc._embedding_column( + country, dimension=5, initializer=_initializer) # Provides 1-dim tensor and dense tensor. features = { @@ -3124,6 +3184,7 @@ class FunctionalInputLayerTest(test.TestCase): [1., 0., 0., 1., 2., 3., 4., 5., 12.]], sess.run(net)) + @test_util.run_deprecated_v1 def test_with_1d_unknown_shape_sparse_tensor(self): embedding_values = ( (1., 2.), # id 0 @@ -3135,17 +3196,17 @@ class FunctionalInputLayerTest(test.TestCase): return embedding_values # price has 1 dimension in input_layer - price = fc.numeric_column('price') + price = fc._numeric_column('price') # one_hot_body_style has 3 dims in input_layer. - body_style = fc.categorical_column_with_vocabulary_list( + body_style = fc._categorical_column_with_vocabulary_list( 'body-style', vocabulary_list=['hardtop', 'wagon', 'sedan']) - one_hot_body_style = fc.indicator_column(body_style) + one_hot_body_style = fc._indicator_column(body_style) # embedded_body_style has 5 dims in input_layer. - country = fc.categorical_column_with_vocabulary_list( + country = fc._categorical_column_with_vocabulary_list( 'country', vocabulary_list=['US', 'JP', 'CA']) - embedded_country = fc.embedding_column( + embedded_country = fc._embedding_column( country, dimension=2, initializer=_initializer) # Provides 1-dim tensor and dense tensor. @@ -3183,9 +3244,10 @@ class FunctionalInputLayerTest(test.TestCase): features['country']: country_data })) + @test_util.run_deprecated_v1 def test_with_rank_0_feature(self): # price has 1 dimension in input_layer - price = fc.numeric_column('price') + price = fc._numeric_column('price') features = { 'price': constant_op.constant(0), } @@ -3313,8 +3375,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'python/feature_column/testdata/wire_vocabulary.txt') self._wire_vocabulary_size = 3 + @test_util.run_deprecated_v1 def test_defaults(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file='path_to_file', vocabulary_size=3) self.assertEqual('aaa', column.name) self.assertEqual('aaa', column._var_scope_name) @@ -3326,22 +3389,30 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): def test_key_should_be_string(self): with self.assertRaisesRegexp(ValueError, 'key must be a string.'): - fc.categorical_column_with_vocabulary_file( + fc._categorical_column_with_vocabulary_file( key=('aaa',), vocabulary_file='path_to_file', vocabulary_size=3) + @test_util.run_deprecated_v1 def test_all_constructor_args(self): - column = fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file='path_to_file', vocabulary_size=3, - num_oov_buckets=4, dtype=dtypes.int32) + column = fc._categorical_column_with_vocabulary_file( + key='aaa', + vocabulary_file='path_to_file', + vocabulary_size=3, + num_oov_buckets=4, + dtype=dtypes.int32) self.assertEqual(7, column._num_buckets) self.assertEqual({ 'aaa': parsing_ops.VarLenFeature(dtypes.int32) }, column._parse_example_spec) + @test_util.run_deprecated_v1 def test_deep_copy(self): - original = fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file='path_to_file', vocabulary_size=3, - num_oov_buckets=4, dtype=dtypes.int32) + original = fc._categorical_column_with_vocabulary_file( + key='aaa', + vocabulary_file='path_to_file', + vocabulary_size=3, + num_oov_buckets=4, + dtype=dtypes.int32) for column in (original, copy.deepcopy(original)): self.assertEqual('aaa', column.name) self.assertEqual(7, column._num_buckets) @@ -3351,16 +3422,17 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): def test_vocabulary_file_none(self): with self.assertRaisesRegexp(ValueError, 'Missing vocabulary_file'): - fc.categorical_column_with_vocabulary_file( + fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=None, vocabulary_size=3) def test_vocabulary_file_empty_string(self): with self.assertRaisesRegexp(ValueError, 'Missing vocabulary_file'): - fc.categorical_column_with_vocabulary_file( + fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file='', vocabulary_size=3) + @test_util.run_deprecated_v1 def test_invalid_vocabulary_file(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file='file_does_not_exist', vocabulary_size=10) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), @@ -3373,16 +3445,19 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): def test_invalid_vocabulary_size(self): with self.assertRaisesRegexp(ValueError, 'Invalid vocabulary_size'): - fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file=self._wire_vocabulary_file_name, + fc._categorical_column_with_vocabulary_file( + key='aaa', + vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=-1) with self.assertRaisesRegexp(ValueError, 'Invalid vocabulary_size'): - fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file=self._wire_vocabulary_file_name, + fc._categorical_column_with_vocabulary_file( + key='aaa', + vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=0) + @test_util.run_deprecated_v1 def test_too_large_vocabulary_size(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size + 1) @@ -3397,20 +3472,24 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): def test_invalid_num_oov_buckets(self): with self.assertRaisesRegexp(ValueError, 'Invalid num_oov_buckets'): - fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file='path', vocabulary_size=3, + fc._categorical_column_with_vocabulary_file( + key='aaa', + vocabulary_file='path', + vocabulary_size=3, num_oov_buckets=-1) def test_invalid_dtype(self): with self.assertRaisesRegexp(ValueError, 'dtype must be string or integer'): - fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file='path', vocabulary_size=3, + fc._categorical_column_with_vocabulary_file( + key='aaa', + vocabulary_file='path', + vocabulary_size=3, dtype=dtypes.float64) def test_invalid_buckets_and_default_value(self): with self.assertRaisesRegexp( ValueError, 'both num_oov_buckets and default_value'): - fc.categorical_column_with_vocabulary_file( + fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size, @@ -3418,7 +3497,7 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): default_value=2) def test_invalid_input_dtype_int32(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size, @@ -3431,7 +3510,7 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): column._get_sparse_tensors(_LazyBuilder({'aaa': inputs})) def test_invalid_input_dtype_string(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._warriors_vocabulary_file_name, vocabulary_size=self._warriors_vocabulary_size, @@ -3443,8 +3522,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'dtype must be compatible'): column._get_sparse_tensors(_LazyBuilder({'aaa': inputs})) + @test_util.run_deprecated_v1 def test_parse_example(self): - a = fc.categorical_column_with_vocabulary_file( + a = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file='path_to_file', vocabulary_size=3) data = example_pb2.Example(features=feature_pb2.Features( feature={ @@ -3465,8 +3545,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=[1, 2]), features['aaa'].eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size) @@ -3485,8 +3566,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_none_vocabulary_size(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), @@ -3503,8 +3585,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_transform_feature(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size) @@ -3514,16 +3597,15 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=(2, 2)) id_tensor = _transform_features({'aaa': inputs}, [column])[column] with _initialized_session(): - _assert_sparse_tensor_value(self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array( - (2, -1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, -1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) def test_get_sparse_tensors_weight_collections(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size) @@ -3540,8 +3622,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): [], ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)) self.assertItemsEqual([], ops.get_collection('my_weights')) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_dense_input(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size) @@ -3559,8 +3642,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=(2, 2)), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_default_value_in_vocabulary(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size, @@ -3580,8 +3664,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_oov_buckets(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size, @@ -3601,11 +3686,12 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_small_vocabulary_size(self): # 'marlo' is the last entry in our vocabulary file, so be setting # `vocabulary_size` to 1 less than number of entries in file, we take # 'marlo' out of the vocabulary. - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size - 1) @@ -3624,8 +3710,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._warriors_vocabulary_file_name, vocabulary_size=self._warriors_vocabulary_size, @@ -3645,9 +3732,10 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32_dense_input(self): default_value = -100 - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._warriors_vocabulary_file_name, vocabulary_size=self._warriors_vocabulary_size, @@ -3667,8 +3755,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=(3, 3)), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32_with_oov_buckets(self): - column = fc.categorical_column_with_vocabulary_file( + column = fc._categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._warriors_vocabulary_file_name, vocabulary_size=self._warriors_vocabulary_size, @@ -3689,8 +3778,9 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_linear_model(self): - wire_column = fc.categorical_column_with_vocabulary_file( + wire_column = fc._categorical_column_with_vocabulary_file( key='wire', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size, @@ -3706,16 +3796,18 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() wire_var = get_linear_model_column_var(wire_column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), + self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() # 'marlo' -> 2: wire_var[2] = 3 # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 - self.assertAllClose(((3.,), (5.,)), predictions.eval()) + self.assertAllClose(((3.,), (5.,)), self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): - wire_column = fc.categorical_column_with_vocabulary_file( + wire_column = fc._categorical_column_with_vocabulary_file( key='wire', vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=self._wire_vocabulary_size, @@ -3732,19 +3824,20 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() wire_var = get_linear_model_column_var(wire_column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), + self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() # 'marlo' -> 2: wire_var[2] = 3 # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 - self.assertAllClose(((3.,), (5.,)), predictions.eval()) + self.assertAllClose(((3.,), (5.,)), self.evaluate(predictions)) class VocabularyListCategoricalColumnTest(test.TestCase): def test_defaults_string(self): - column = fc.categorical_column_with_vocabulary_list( + column = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) self.assertEqual('aaa', column.name) self.assertEqual('aaa', column.key) @@ -3756,11 +3849,11 @@ class VocabularyListCategoricalColumnTest(test.TestCase): def test_key_should_be_string(self): with self.assertRaisesRegexp(ValueError, 'key must be a string.'): - fc.categorical_column_with_vocabulary_list( + fc._categorical_column_with_vocabulary_list( key=('aaa',), vocabulary_list=('omar', 'stringer', 'marlo')) def test_defaults_int(self): - column = fc.categorical_column_with_vocabulary_list( + column = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12, 24, 36)) self.assertEqual('aaa', column.name) self.assertEqual('aaa', column.key) @@ -3770,17 +3863,21 @@ class VocabularyListCategoricalColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int64) }, column._parse_example_spec) + @test_util.run_deprecated_v1 def test_all_constructor_args(self): - column = fc.categorical_column_with_vocabulary_list( - key='aaa', vocabulary_list=(12, 24, 36), dtype=dtypes.int32, + column = fc._categorical_column_with_vocabulary_list( + key='aaa', + vocabulary_list=(12, 24, 36), + dtype=dtypes.int32, default_value=-99) self.assertEqual(3, column._num_buckets) self.assertEqual({ 'aaa': parsing_ops.VarLenFeature(dtypes.int32) }, column._parse_example_spec) + @test_util.run_deprecated_v1 def test_deep_copy(self): - original = fc.categorical_column_with_vocabulary_list( + original = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12, 24, 36), dtype=dtypes.int32) for column in (original, copy.deepcopy(original)): self.assertEqual('aaa', column.name) @@ -3791,65 +3888,65 @@ class VocabularyListCategoricalColumnTest(test.TestCase): def test_invalid_dtype(self): with self.assertRaisesRegexp(ValueError, 'dtype must be string or integer'): - fc.categorical_column_with_vocabulary_list( - key='aaa', vocabulary_list=('omar', 'stringer', 'marlo'), + fc._categorical_column_with_vocabulary_list( + key='aaa', + vocabulary_list=('omar', 'stringer', 'marlo'), dtype=dtypes.float32) def test_invalid_mapping_dtype(self): with self.assertRaisesRegexp( ValueError, r'vocabulary dtype must be string or integer'): - fc.categorical_column_with_vocabulary_list( + fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12., 24., 36.)) def test_mismatched_int_dtype(self): with self.assertRaisesRegexp( ValueError, r'dtype.*and vocabulary dtype.*do not match'): - fc.categorical_column_with_vocabulary_list( - key='aaa', vocabulary_list=('omar', 'stringer', 'marlo'), + fc._categorical_column_with_vocabulary_list( + key='aaa', + vocabulary_list=('omar', 'stringer', 'marlo'), dtype=dtypes.int32) def test_mismatched_string_dtype(self): with self.assertRaisesRegexp( ValueError, r'dtype.*and vocabulary dtype.*do not match'): - fc.categorical_column_with_vocabulary_list( + fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12, 24, 36), dtype=dtypes.string) def test_none_mapping(self): with self.assertRaisesRegexp( ValueError, r'vocabulary_list.*must be non-empty'): - fc.categorical_column_with_vocabulary_list( + fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=None) def test_empty_mapping(self): with self.assertRaisesRegexp( ValueError, r'vocabulary_list.*must be non-empty'): - fc.categorical_column_with_vocabulary_list( + fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=tuple([])) def test_duplicate_mapping(self): with self.assertRaisesRegexp(ValueError, 'Duplicate keys'): - fc.categorical_column_with_vocabulary_list( + fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12, 24, 12)) def test_invalid_num_oov_buckets(self): with self.assertRaisesRegexp(ValueError, 'Invalid num_oov_buckets'): - fc.categorical_column_with_vocabulary_list( - key='aaa', vocabulary_list=(12, 24, 36), - num_oov_buckets=-1) + fc._categorical_column_with_vocabulary_list( + key='aaa', vocabulary_list=(12, 24, 36), num_oov_buckets=-1) def test_invalid_buckets_and_default_value(self): with self.assertRaisesRegexp( ValueError, 'both num_oov_buckets and default_value'): - fc.categorical_column_with_vocabulary_list( + fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12, 24, 36), num_oov_buckets=100, default_value=2) def test_invalid_input_dtype_int32(self): - column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=('omar', 'stringer', 'marlo')) + column = fc._categorical_column_with_vocabulary_list( + key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=(12, 24, 36), @@ -3858,9 +3955,8 @@ class VocabularyListCategoricalColumnTest(test.TestCase): column._get_sparse_tensors(_LazyBuilder({'aaa': inputs})) def test_invalid_input_dtype_string(self): - column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=(12, 24, 36)) + column = fc._categorical_column_with_vocabulary_list( + key='aaa', vocabulary_list=(12, 24, 36)) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=('omar', 'stringer', 'marlo'), @@ -3868,8 +3964,9 @@ class VocabularyListCategoricalColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'dtype must be compatible'): column._get_sparse_tensors(_LazyBuilder({'aaa': inputs})) + @test_util.run_deprecated_v1 def test_parse_example_string(self): - a = fc.categorical_column_with_vocabulary_list( + a = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) data = example_pb2.Example(features=feature_pb2.Features( feature={ @@ -3890,8 +3987,9 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=[1, 2]), features['aaa'].eval()) + @test_util.run_deprecated_v1 def test_parse_example_int(self): - a = fc.categorical_column_with_vocabulary_list( + a = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(11, 21, 31)) data = example_pb2.Example(features=feature_pb2.Features( feature={ @@ -3912,10 +4010,10 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=[1, 2]), features['aaa'].eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): - column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=('omar', 'stringer', 'marlo')) + column = fc._categorical_column_with_vocabulary_list( + key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=('marlo', 'skywalker', 'omar'), @@ -3931,10 +4029,10 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_transform_feature(self): - column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=('omar', 'stringer', 'marlo')) + column = fc._categorical_column_with_vocabulary_list( + key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=('marlo', 'skywalker', 'omar'), @@ -3946,13 +4044,11 @@ class VocabularyListCategoricalColumnTest(test.TestCase): sparse_tensor.SparseTensorValue( indices=inputs.indices, values=np.array((2, -1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) def test_get_sparse_tensors_weight_collections(self): - column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=('omar', 'stringer', 'marlo')) + column = fc._categorical_column_with_vocabulary_list( + key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) inputs = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], indices=[[0, 0], [1, 0], [1, 1]], @@ -3966,10 +4062,10 @@ class VocabularyListCategoricalColumnTest(test.TestCase): [], ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)) self.assertItemsEqual([], ops.get_collection('my_weights')) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_dense_input(self): - column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=('omar', 'stringer', 'marlo')) + column = fc._categorical_column_with_vocabulary_list( + key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) id_weight_pair = column._get_sparse_tensors( _LazyBuilder({ 'aaa': (('marlo', ''), ('skywalker', 'omar')) @@ -3984,8 +4080,9 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=(2, 2)), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_default_value_in_vocabulary(self): - column = fc.categorical_column_with_vocabulary_list( + column = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo'), default_value=2) @@ -4004,8 +4101,9 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_oov_buckets(self): - column = fc.categorical_column_with_vocabulary_list( + column = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo'), num_oov_buckets=100) @@ -4024,8 +4122,9 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32(self): - column = fc.categorical_column_with_vocabulary_list( + column = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=np.array((30, 35, 11, 23, 22), dtype=np.int32), dtype=dtypes.int32) @@ -4044,9 +4143,10 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32_dense_input(self): default_value = -100 - column = fc.categorical_column_with_vocabulary_list( + column = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=np.array((30, 35, 11, 23, 22), dtype=np.int32), dtype=dtypes.int32, @@ -4067,8 +4167,9 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=(3, 3)), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32_with_oov_buckets(self): - column = fc.categorical_column_with_vocabulary_list( + column = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=np.array((30, 35, 11, 23, 22), dtype=np.int32), dtype=dtypes.int32, @@ -4088,8 +4189,9 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_linear_model(self): - wire_column = fc.categorical_column_with_vocabulary_list( + wire_column = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo'), num_oov_buckets=1) @@ -4104,16 +4206,18 @@ class VocabularyListCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() wire_var = get_linear_model_column_var(wire_column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), + self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() # 'marlo' -> 2: wire_var[2] = 3 # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 - self.assertAllClose(((3.,), (5.,)), predictions.eval()) + self.assertAllClose(((3.,), (5.,)), self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): - wire_column = fc.categorical_column_with_vocabulary_list( + wire_column = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo'), num_oov_buckets=1) @@ -4129,19 +4233,20 @@ class VocabularyListCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() wire_var = get_linear_model_column_var(wire_column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), + self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() # 'marlo' -> 2: wire_var[2] = 3 # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 - self.assertAllClose(((3.,), (5.,)), predictions.eval()) + self.assertAllClose(((3.,), (5.,)), self.evaluate(predictions)) class IdentityCategoricalColumnTest(test.TestCase): def test_constructor(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) self.assertEqual('aaa', column.name) self.assertEqual('aaa', column.key) self.assertEqual('aaa', column._var_scope_name) @@ -4152,10 +4257,11 @@ class IdentityCategoricalColumnTest(test.TestCase): def test_key_should_be_string(self): with self.assertRaisesRegexp(ValueError, 'key must be a string.'): - fc.categorical_column_with_identity(key=('aaa',), num_buckets=3) + fc._categorical_column_with_identity(key=('aaa',), num_buckets=3) + @test_util.run_deprecated_v1 def test_deep_copy(self): - original = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + original = fc._categorical_column_with_identity(key='aaa', num_buckets=3) for column in (original, copy.deepcopy(original)): self.assertEqual('aaa', column.name) self.assertEqual(3, column._num_buckets) @@ -4165,24 +4271,24 @@ class IdentityCategoricalColumnTest(test.TestCase): def test_invalid_num_buckets_zero(self): with self.assertRaisesRegexp(ValueError, 'num_buckets 0 < 1'): - fc.categorical_column_with_identity(key='aaa', num_buckets=0) + fc._categorical_column_with_identity(key='aaa', num_buckets=0) def test_invalid_num_buckets_negative(self): with self.assertRaisesRegexp(ValueError, 'num_buckets -1 < 1'): - fc.categorical_column_with_identity(key='aaa', num_buckets=-1) + fc._categorical_column_with_identity(key='aaa', num_buckets=-1) def test_invalid_default_value_too_small(self): with self.assertRaisesRegexp(ValueError, 'default_value -1 not in range'): - fc.categorical_column_with_identity( + fc._categorical_column_with_identity( key='aaa', num_buckets=3, default_value=-1) def test_invalid_default_value_too_big(self): with self.assertRaisesRegexp(ValueError, 'default_value 3 not in range'): - fc.categorical_column_with_identity( + fc._categorical_column_with_identity( key='aaa', num_buckets=3, default_value=3) def test_invalid_input_dtype(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=('omar', 'stringer', 'marlo'), @@ -4190,8 +4296,9 @@ class IdentityCategoricalColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'Invalid input, not integer'): column._get_sparse_tensors(_LazyBuilder({'aaa': inputs})) + @test_util.run_deprecated_v1 def test_parse_example(self): - a = fc.categorical_column_with_identity(key='aaa', num_buckets=30) + a = fc._categorical_column_with_identity(key='aaa', num_buckets=30) data = example_pb2.Example(features=feature_pb2.Features( feature={ 'aaa': @@ -4211,8 +4318,9 @@ class IdentityCategoricalColumnTest(test.TestCase): dense_shape=[1, 2]), features['aaa'].eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=(0, 1, 0), @@ -4228,8 +4336,9 @@ class IdentityCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_transform_feature(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=(0, 1, 0), @@ -4241,11 +4350,10 @@ class IdentityCategoricalColumnTest(test.TestCase): sparse_tensor.SparseTensorValue( indices=inputs.indices, values=np.array((0, 1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) def test_get_sparse_tensors_weight_collections(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=(0, 1, 0), @@ -4259,8 +4367,9 @@ class IdentityCategoricalColumnTest(test.TestCase): [], ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)) self.assertItemsEqual([], ops.get_collection('my_weights')) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_dense_input(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) id_weight_pair = column._get_sparse_tensors( _LazyBuilder({ 'aaa': ((0, -1), (1, 0)) @@ -4275,8 +4384,9 @@ class IdentityCategoricalColumnTest(test.TestCase): dense_shape=(2, 2)), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_inputs_too_small(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=(1, -1, 0), @@ -4288,8 +4398,9 @@ class IdentityCategoricalColumnTest(test.TestCase): errors.OpError, 'assert_greater_or_equal_0'): id_weight_pair.id_tensor.eval() + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_inputs_too_big(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=(1, 99, 0), @@ -4301,8 +4412,9 @@ class IdentityCategoricalColumnTest(test.TestCase): errors.OpError, 'assert_less_than_num_buckets'): id_weight_pair.id_tensor.eval() + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_default_value(self): - column = fc.categorical_column_with_identity( + column = fc._categorical_column_with_identity( key='aaa', num_buckets=4, default_value=3) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), @@ -4319,8 +4431,9 @@ class IdentityCategoricalColumnTest(test.TestCase): dense_shape=inputs.dense_shape), id_weight_pair.id_tensor.eval()) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_default_value_and_placeholder_inputs(self): - column = fc.categorical_column_with_identity( + column = fc._categorical_column_with_identity( key='aaa', num_buckets=4, default_value=3) input_indices = array_ops.placeholder(dtype=dtypes.int64) input_values = array_ops.placeholder(dtype=dtypes.int32) @@ -4344,8 +4457,9 @@ class IdentityCategoricalColumnTest(test.TestCase): input_shape: (2, 2), })) + @test_util.run_deprecated_v1 def test_linear_model(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) self.assertEqual(3, column._num_buckets) with ops.Graph().as_default(): predictions = fc.linear_model({ @@ -4357,16 +4471,17 @@ class IdentityCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) weight_var.assign(((1.,), (2.,), (3.,))).eval() # weight_var[0] = 1 # weight_var[2] + weight_var[1] = 3+2 = 5 - self.assertAllClose(((1.,), (5.,)), predictions.eval()) + self.assertAllClose(((1.,), (5.,)), self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): - column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) + column = fc._categorical_column_with_identity(key='aaa', num_buckets=3) self.assertEqual(3, column._num_buckets) with ops.Graph().as_default(): predictions = get_keras_linear_model_predictions({ @@ -4379,13 +4494,13 @@ class IdentityCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) weight_var.assign(((1.,), (2.,), (3.,))).eval() # weight_var[0] = 1 # weight_var[2] + weight_var[1] = 3+2 = 5 - self.assertAllClose(((1.,), (5.,)), predictions.eval()) + self.assertAllClose(((1.,), (5.,)), self.evaluate(predictions)) class TransformFeaturesTest(test.TestCase): @@ -4393,9 +4508,9 @@ class TransformFeaturesTest(test.TestCase): # All transform tests are distributed in column test. # Here we only test multi column case and naming def transform_multi_column(self): - bucketized_price = fc.bucketized_column( - fc.numeric_column('price'), boundaries=[0, 2, 4, 6]) - hashed_sparse = fc.categorical_column_with_hash_bucket('wire', 10) + bucketized_price = fc._bucketized_column( + fc._numeric_column('price'), boundaries=[0, 2, 4, 6]) + hashed_sparse = fc._categorical_column_with_hash_bucket('wire', 10) with ops.Graph().as_default(): features = { 'price': [[-1.], [5.]], @@ -4452,32 +4567,33 @@ class TransformFeaturesTest(test.TestCase): class IndicatorColumnTest(test.TestCase): def test_indicator_column(self): - a = fc.categorical_column_with_hash_bucket('a', 4) - indicator_a = fc.indicator_column(a) + a = fc._categorical_column_with_hash_bucket('a', 4) + indicator_a = fc._indicator_column(a) self.assertEqual(indicator_a.categorical_column.name, 'a') self.assertEqual(indicator_a.name, 'a_indicator') self.assertEqual(indicator_a._var_scope_name, 'a_indicator') self.assertEqual(indicator_a._variable_shape, [1, 4]) - b = fc.categorical_column_with_hash_bucket('b', hash_bucket_size=100) - indicator_b = fc.indicator_column(b) + b = fc._categorical_column_with_hash_bucket('b', hash_bucket_size=100) + indicator_b = fc._indicator_column(b) self.assertEqual(indicator_b.categorical_column.name, 'b') self.assertEqual(indicator_b.name, 'b_indicator') self.assertEqual(indicator_b._var_scope_name, 'b_indicator') self.assertEqual(indicator_b._variable_shape, [1, 100]) def test_1D_shape_succeeds(self): - animal = fc.indicator_column( - fc.categorical_column_with_hash_bucket('animal', 4)) + animal = fc._indicator_column( + fc._categorical_column_with_hash_bucket('animal', 4)) builder = _LazyBuilder({'animal': ['fox', 'fox']}) output = builder.get(animal) with self.cached_session(): - self.assertAllEqual([[0., 0., 1., 0.], [0., 0., 1., 0.]], output.eval()) + self.assertAllEqual([[0., 0., 1., 0.], [0., 0., 1., 0.]], + self.evaluate(output)) def test_2D_shape_succeeds(self): # TODO(ispir/cassandrax): Swith to categorical_column_with_keys when ready. - animal = fc.indicator_column( - fc.categorical_column_with_hash_bucket('animal', 4)) + animal = fc._indicator_column( + fc._categorical_column_with_hash_bucket('animal', 4)) builder = _LazyBuilder({ 'animal': sparse_tensor.SparseTensor( @@ -4487,11 +4603,12 @@ class IndicatorColumnTest(test.TestCase): }) output = builder.get(animal) with self.cached_session(): - self.assertAllEqual([[0., 0., 1., 0.], [0., 0., 1., 0.]], output.eval()) + self.assertAllEqual([[0., 0., 1., 0.], [0., 0., 1., 0.]], + self.evaluate(output)) def test_multi_hot(self): - animal = fc.indicator_column( - fc.categorical_column_with_identity('animal', num_buckets=4)) + animal = fc._indicator_column( + fc._categorical_column_with_identity('animal', num_buckets=4)) builder = _LazyBuilder({ 'animal': @@ -4500,11 +4617,11 @@ class IndicatorColumnTest(test.TestCase): }) output = builder.get(animal) with self.cached_session(): - self.assertAllEqual([[0., 2., 0., 0.]], output.eval()) + self.assertAllEqual([[0., 2., 0., 0.]], self.evaluate(output)) def test_multi_hot2(self): - animal = fc.indicator_column( - fc.categorical_column_with_identity('animal', num_buckets=4)) + animal = fc._indicator_column( + fc._categorical_column_with_identity('animal', num_buckets=4)) builder = _LazyBuilder({ 'animal': sparse_tensor.SparseTensor( @@ -4512,20 +4629,22 @@ class IndicatorColumnTest(test.TestCase): }) output = builder.get(animal) with self.cached_session(): - self.assertAllEqual([[0., 1., 1., 0.]], output.eval()) + self.assertAllEqual([[0., 1., 1., 0.]], self.evaluate(output)) + @test_util.run_deprecated_v1 def test_deep_copy(self): - a = fc.categorical_column_with_hash_bucket('a', 4) - column = fc.indicator_column(a) + a = fc._categorical_column_with_hash_bucket('a', 4) + column = fc._indicator_column(a) column_copy = copy.deepcopy(column) self.assertEqual(column_copy.categorical_column.name, 'a') self.assertEqual(column.name, 'a_indicator') self.assertEqual(column._variable_shape, [1, 4]) + @test_util.run_deprecated_v1 def test_parse_example(self): - a = fc.categorical_column_with_vocabulary_list( + a = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) - a_indicator = fc.indicator_column(a) + a_indicator = fc._indicator_column(a) data = example_pb2.Example(features=feature_pb2.Features( feature={ 'aaa': @@ -4545,10 +4664,11 @@ class IndicatorColumnTest(test.TestCase): dense_shape=[1, 2]), features['aaa'].eval()) + @test_util.run_deprecated_v1 def test_transform(self): - a = fc.categorical_column_with_vocabulary_list( + a = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) - a_indicator = fc.indicator_column(a) + a_indicator = fc._indicator_column(a) features = { 'aaa': sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), @@ -4557,51 +4677,56 @@ class IndicatorColumnTest(test.TestCase): } indicator_tensor = _transform_features(features, [a_indicator])[a_indicator] with _initialized_session(): - self.assertAllEqual([[0, 0, 1], [1, 0, 0]], indicator_tensor.eval()) + self.assertAllEqual([[0, 0, 1], [1, 0, 0]], + self.evaluate(indicator_tensor)) + @test_util.run_deprecated_v1 def test_transform_with_weighted_column(self): # Github issue 12557 - ids = fc.categorical_column_with_vocabulary_list( + ids = fc._categorical_column_with_vocabulary_list( key='ids', vocabulary_list=('a', 'b', 'c')) - weights = fc.weighted_categorical_column(ids, 'weights') - indicator = fc.indicator_column(weights) + weights = fc._weighted_categorical_column(ids, 'weights') + indicator = fc._indicator_column(weights) features = { 'ids': constant_op.constant([['c', 'b', 'a', 'c']]), 'weights': constant_op.constant([[2., 4., 6., 1.]]) } indicator_tensor = _transform_features(features, [indicator])[indicator] with _initialized_session(): - self.assertAllEqual([[6., 4., 3.]], indicator_tensor.eval()) + self.assertAllEqual([[6., 4., 3.]], self.evaluate(indicator_tensor)) + @test_util.run_deprecated_v1 def test_transform_with_missing_value_in_weighted_column(self): # Github issue 12583 - ids = fc.categorical_column_with_vocabulary_list( + ids = fc._categorical_column_with_vocabulary_list( key='ids', vocabulary_list=('a', 'b', 'c')) - weights = fc.weighted_categorical_column(ids, 'weights') - indicator = fc.indicator_column(weights) + weights = fc._weighted_categorical_column(ids, 'weights') + indicator = fc._indicator_column(weights) features = { 'ids': constant_op.constant([['c', 'b', 'unknown']]), 'weights': constant_op.constant([[2., 4., 6.]]) } indicator_tensor = _transform_features(features, [indicator])[indicator] with _initialized_session(): - self.assertAllEqual([[0., 4., 2.]], indicator_tensor.eval()) + self.assertAllEqual([[0., 4., 2.]], self.evaluate(indicator_tensor)) + @test_util.run_deprecated_v1 def test_transform_with_missing_value_in_categorical_column(self): # Github issue 12583 - ids = fc.categorical_column_with_vocabulary_list( + ids = fc._categorical_column_with_vocabulary_list( key='ids', vocabulary_list=('a', 'b', 'c')) - indicator = fc.indicator_column(ids) + indicator = fc._indicator_column(ids) features = { 'ids': constant_op.constant([['c', 'b', 'unknown']]), } indicator_tensor = _transform_features(features, [indicator])[indicator] with _initialized_session(): - self.assertAllEqual([[0., 1., 1.]], indicator_tensor.eval()) + self.assertAllEqual([[0., 1., 1.]], self.evaluate(indicator_tensor)) + @test_util.run_deprecated_v1 def test_linear_model(self): - animal = fc.indicator_column( - fc.categorical_column_with_identity('animal', num_buckets=4)) + animal = fc._indicator_column( + fc._categorical_column_with_identity('animal', num_buckets=4)) with ops.Graph().as_default(): features = { 'animal': @@ -4613,14 +4738,15 @@ class IndicatorColumnTest(test.TestCase): weight_var = get_linear_model_column_var(animal) with _initialized_session(): # All should be zero-initialized. - self.assertAllClose([[0.], [0.], [0.], [0.]], weight_var.eval()) - self.assertAllClose([[0.]], predictions.eval()) + self.assertAllClose([[0.], [0.], [0.], [0.]], self.evaluate(weight_var)) + self.assertAllClose([[0.]], self.evaluate(predictions)) weight_var.assign([[1.], [2.], [3.], [4.]]).eval() - self.assertAllClose([[2. + 3.]], predictions.eval()) + self.assertAllClose([[2. + 3.]], self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): - animal = fc.indicator_column( - fc.categorical_column_with_identity('animal', num_buckets=4)) + animal = fc._indicator_column( + fc._categorical_column_with_identity('animal', num_buckets=4)) with ops.Graph().as_default(): features = { 'animal': @@ -4632,14 +4758,15 @@ class IndicatorColumnTest(test.TestCase): weight_var = get_linear_model_column_var(animal) with _initialized_session(): # All should be zero-initialized. - self.assertAllClose([[0.], [0.], [0.], [0.]], weight_var.eval()) - self.assertAllClose([[0.]], predictions.eval()) + self.assertAllClose([[0.], [0.], [0.], [0.]], self.evaluate(weight_var)) + self.assertAllClose([[0.]], self.evaluate(predictions)) weight_var.assign([[1.], [2.], [3.], [4.]]).eval() - self.assertAllClose([[2. + 3.]], predictions.eval()) + self.assertAllClose([[2. + 3.]], self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_input_layer(self): - animal = fc.indicator_column( - fc.categorical_column_with_identity('animal', num_buckets=4)) + animal = fc._indicator_column( + fc._categorical_column_with_identity('animal', num_buckets=4)) with ops.Graph().as_default(): features = { 'animal': @@ -4648,16 +4775,17 @@ class IndicatorColumnTest(test.TestCase): } net = fc.input_layer(features, [animal]) with _initialized_session(): - self.assertAllClose([[0., 1., 1., 0.]], net.eval()) + self.assertAllClose([[0., 1., 1., 0.]], self.evaluate(net)) class EmbeddingColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=3) embedding_dimension = 2 - embedding_column = fc.embedding_column( + embedding_column = fc._embedding_column( categorical_column, dimension=embedding_dimension) self.assertIs(categorical_column, embedding_column.categorical_column) self.assertEqual(embedding_dimension, embedding_column.dimension) @@ -4674,15 +4802,20 @@ class EmbeddingColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column._parse_example_spec) + @test_util.run_deprecated_v1 def test_all_constructor_args(self): - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=3) embedding_dimension = 2 - embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, - combiner='my_combiner', initializer=lambda: 'my_initializer', - ckpt_to_load_from='my_ckpt', tensor_name_in_ckpt='my_ckpt_tensor', - max_norm=42., trainable=False) + embedding_column = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, + combiner='my_combiner', + initializer=lambda: 'my_initializer', + ckpt_to_load_from='my_ckpt', + tensor_name_in_ckpt='my_ckpt_tensor', + max_norm=42., + trainable=False) self.assertIs(categorical_column, embedding_column.categorical_column) self.assertEqual(embedding_dimension, embedding_column.dimension) self.assertEqual('my_combiner', embedding_column.combiner) @@ -4698,15 +4831,20 @@ class EmbeddingColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column._parse_example_spec) + @test_util.run_deprecated_v1 def test_deep_copy(self): - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=3) embedding_dimension = 2 - original = fc.embedding_column( - categorical_column, dimension=embedding_dimension, - combiner='my_combiner', initializer=lambda: 'my_initializer', - ckpt_to_load_from='my_ckpt', tensor_name_in_ckpt='my_ckpt_tensor', - max_norm=42., trainable=False) + original = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, + combiner='my_combiner', + initializer=lambda: 'my_initializer', + ckpt_to_load_from='my_ckpt', + tensor_name_in_ckpt='my_ckpt_tensor', + max_norm=42., + trainable=False) for embedding_column in (original, copy.deepcopy(original)): self.assertEqual('aaa', embedding_column.categorical_column.name) self.assertEqual(3, embedding_column.categorical_column._num_buckets) @@ -4727,16 +4865,19 @@ class EmbeddingColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column._parse_example_spec) + @test_util.run_deprecated_v1 def test_invalid_initializer(self): - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=3) with self.assertRaisesRegexp(ValueError, 'initializer must be callable'): - fc.embedding_column(categorical_column, dimension=2, initializer='not_fn') + fc._embedding_column( + categorical_column, dimension=2, initializer='not_fn') + @test_util.run_deprecated_v1 def test_parse_example(self): - a = fc.categorical_column_with_vocabulary_list( + a = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) - a_embedded = fc.embedding_column(a, dimension=2) + a_embedded = fc._embedding_column(a, dimension=2) data = example_pb2.Example(features=feature_pb2.Features( feature={ 'aaa': @@ -4756,9 +4897,10 @@ class EmbeddingColumnTest(test.TestCase): dense_shape=[1, 2]), features['aaa'].eval()) + @test_util.run_deprecated_v1 def test_transform_feature(self): - a = fc.categorical_column_with_identity(key='aaa', num_buckets=3) - a_embedded = fc.embedding_column(a, dimension=2) + a = fc._categorical_column_with_identity(key='aaa', num_buckets=3) + a_embedded = fc._embedding_column(a, dimension=2) features = { 'aaa': sparse_tensor.SparseTensor( indices=((0, 0), (1, 0), (1, 1)), @@ -4769,9 +4911,10 @@ class EmbeddingColumnTest(test.TestCase): output_a = outputs[a] output_embedded = outputs[a_embedded] with _initialized_session(): - _assert_sparse_tensor_value( - self, output_a.eval(), output_embedded.eval()) + _assert_sparse_tensor_value(self, self.evaluate(output_a), + self.evaluate(output_embedded)) + @test_util.run_deprecated_v1 def test_get_dense_tensor(self): # Inputs. vocabulary_size = 3 @@ -4810,10 +4953,11 @@ class EmbeddingColumnTest(test.TestCase): ) # Build columns. - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + embedding_column = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, initializer=_initializer) # Provide sparse input and get dense result. @@ -4828,8 +4972,9 @@ class EmbeddingColumnTest(test.TestCase): tuple([v.name for v in global_vars])) with _initialized_session(): self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, embedding_lookup.eval()) + self.assertAllEqual(expected_lookups, self.evaluate(embedding_lookup)) + @test_util.run_deprecated_v1 def test_get_dense_tensor_3d(self): # Inputs. vocabulary_size = 4 @@ -4870,10 +5015,11 @@ class EmbeddingColumnTest(test.TestCase): ) # Build columns. - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + embedding_column = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, initializer=_initializer) # Provide sparse input and get dense result. @@ -4888,8 +5034,9 @@ class EmbeddingColumnTest(test.TestCase): tuple([v.name for v in global_vars])) with _initialized_session(): self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, embedding_lookup.eval()) + self.assertAllEqual(expected_lookups, self.evaluate(embedding_lookup)) + @test_util.run_deprecated_v1 def test_get_dense_tensor_weight_collections(self): sparse_input = sparse_tensor.SparseTensorValue( # example 0, ids [2] @@ -4901,9 +5048,9 @@ class EmbeddingColumnTest(test.TestCase): dense_shape=(4, 5)) # Build columns. - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - embedding_column = fc.embedding_column(categorical_column, dimension=2) + embedding_column = fc._embedding_column(categorical_column, dimension=2) # Provide sparse input and get dense result. embedding_column._get_dense_tensor( @@ -4919,6 +5066,7 @@ class EmbeddingColumnTest(test.TestCase): self.assertItemsEqual( ('embedding_weights:0',), tuple([v.name for v in my_vars])) + @test_util.run_deprecated_v1 def test_get_dense_tensor_placeholder_inputs(self): # Inputs. vocabulary_size = 3 @@ -4957,10 +5105,11 @@ class EmbeddingColumnTest(test.TestCase): ) # Build columns. - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + embedding_column = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, initializer=_initializer) # Provide sparse input and get dense result. @@ -4989,6 +5138,7 @@ class EmbeddingColumnTest(test.TestCase): input_shape: sparse_input.dense_shape, })) + @test_util.run_deprecated_v1 def test_get_dense_tensor_restore_from_ckpt(self): # Inputs. vocabulary_size = 3 @@ -5025,10 +5175,11 @@ class EmbeddingColumnTest(test.TestCase): ) # Build columns. - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + embedding_column = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, ckpt_to_load_from=ckpt_path, tensor_name_in_ckpt=ckpt_tensor) @@ -5044,8 +5195,9 @@ class EmbeddingColumnTest(test.TestCase): ('embedding_weights:0',), tuple([v.name for v in global_vars])) with _initialized_session(): self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, embedding_lookup.eval()) + self.assertAllEqual(expected_lookups, self.evaluate(embedding_lookup)) + @test_util.run_deprecated_v1 def test_linear_model(self): # Inputs. batch_size = 4 @@ -5070,10 +5222,11 @@ class EmbeddingColumnTest(test.TestCase): return zeros_embedding_values # Build columns. - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + embedding_column = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, initializer=_initializer) with ops.Graph().as_default(): @@ -5100,11 +5253,13 @@ class EmbeddingColumnTest(test.TestCase): 'linear_model/aaa_embedding/weights:0'] with _initialized_session(): # Predictions with all zero weights. - self.assertAllClose(np.zeros((1,)), bias.eval()) - self.assertAllClose(zeros_embedding_values, embedding_weights.eval()) + self.assertAllClose(np.zeros((1,)), self.evaluate(bias)) + self.assertAllClose(zeros_embedding_values, + self.evaluate(embedding_weights)) + self.assertAllClose( + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights)) self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights.eval()) - self.assertAllClose(np.zeros((batch_size, 1)), predictions.eval()) + np.zeros((batch_size, 1)), self.evaluate(predictions)) # Predictions with all non-zero weights. embedding_weights.assign(( @@ -5119,8 +5274,10 @@ class EmbeddingColumnTest(test.TestCase): # example 3, ids [1], embedding[3] = [3, 5] # sum(embeddings * linear_weights) # = [4*7 + 6*11, 4*2 + 6*3.5, 4*0 + 6*0, 4*3 + 6*5] = [94, 29, 0, 42] - self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), predictions.eval()) + self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), + self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): # Inputs. batch_size = 4 @@ -5146,9 +5303,9 @@ class EmbeddingColumnTest(test.TestCase): return zeros_embedding_values # Build columns. - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( + embedding_column = fc._embedding_column( categorical_column, dimension=embedding_dimension, initializer=_initializer) @@ -5176,11 +5333,13 @@ class EmbeddingColumnTest(test.TestCase): linear_weights = trainable_vars['linear_model/aaa_embedding/weights:0'] with _initialized_session(): # Predictions with all zero weights. - self.assertAllClose(np.zeros((1,)), bias.eval()) - self.assertAllClose(zeros_embedding_values, embedding_weights.eval()) + self.assertAllClose(np.zeros((1,)), self.evaluate(bias)) + self.assertAllClose(zeros_embedding_values, + self.evaluate(embedding_weights)) self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights.eval()) - self.assertAllClose(np.zeros((batch_size, 1)), predictions.eval()) + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights)) + self.assertAllClose( + np.zeros((batch_size, 1)), self.evaluate(predictions)) # Predictions with all non-zero weights. embedding_weights.assign(( @@ -5195,8 +5354,10 @@ class EmbeddingColumnTest(test.TestCase): # example 3, ids [1], embedding[3] = [3, 5] # sum(embeddings * linear_weights) # = [4*7 + 6*11, 4*2 + 6*3.5, 4*0 + 6*0, 4*3 + 6*5] = [94, 29, 0, 42] - self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), predictions.eval()) + self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), + self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_input_layer(self): # Inputs. vocabulary_size = 3 @@ -5235,10 +5396,11 @@ class EmbeddingColumnTest(test.TestCase): ) # Build columns. - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + embedding_column = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, initializer=_initializer) # Provide sparse input and get dense result. @@ -5255,8 +5417,9 @@ class EmbeddingColumnTest(test.TestCase): tuple([v.name for v in trainable_vars])) with _initialized_session(): self.assertAllEqual(embedding_values, trainable_vars[0].eval()) - self.assertAllEqual(expected_lookups, input_layer.eval()) + self.assertAllEqual(expected_lookups, self.evaluate(input_layer)) + @test_util.run_deprecated_v1 def test_input_layer_not_trainable(self): # Inputs. vocabulary_size = 3 @@ -5295,11 +5458,13 @@ class EmbeddingColumnTest(test.TestCase): ) # Build columns. - categorical_column = fc.categorical_column_with_identity( + categorical_column = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, - initializer=_initializer, trainable=False) + embedding_column = fc._embedding_column( + categorical_column, + dimension=embedding_dimension, + initializer=_initializer, + trainable=False) # Provide sparse input and get dense result. input_layer = fc.input_layer({'aaa': sparse_input}, (embedding_column,)) @@ -5313,18 +5478,19 @@ class EmbeddingColumnTest(test.TestCase): [], ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES)) with _initialized_session(): self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, input_layer.eval()) + self.assertAllEqual(expected_lookups, self.evaluate(input_layer)) class SharedEmbeddingColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=3) embedding_dimension = 2 - embedding_column_b, embedding_column_a = fc.shared_embedding_columns( + embedding_column_b, embedding_column_a = fc_new.shared_embedding_columns( [categorical_column_b, categorical_column_a], dimension=embedding_dimension) self.assertIs(categorical_column_a, embedding_column_a.categorical_column) @@ -5362,13 +5528,14 @@ class SharedEmbeddingColumnTest(test.TestCase): 'bbb': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column_b._parse_example_spec) + @test_util.run_deprecated_v1 def test_all_constructor_args(self): - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=3) embedding_dimension = 2 - embedding_column_a, embedding_column_b = fc.shared_embedding_columns( + embedding_column_a, embedding_column_b = fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=embedding_dimension, combiner='my_combiner', @@ -5413,13 +5580,14 @@ class SharedEmbeddingColumnTest(test.TestCase): 'bbb': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column_b._parse_example_spec) + @test_util.run_deprecated_v1 def test_deep_copy(self): - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=3) embedding_dimension = 2 - original_a, _ = fc.shared_embedding_columns( + original_a, _ = fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=embedding_dimension, combiner='my_combiner', @@ -5427,7 +5595,8 @@ class SharedEmbeddingColumnTest(test.TestCase): shared_embedding_collection_name='shared_embedding_collection_name', ckpt_to_load_from='my_ckpt', tensor_name_in_ckpt='my_ckpt_tensor', - max_norm=42., trainable=False) + max_norm=42., + trainable=False) for embedding_column_a in (original_a, copy.deepcopy(original_a)): self.assertEqual('aaa', embedding_column_a.categorical_column.name) self.assertEqual(3, embedding_column_a.categorical_column._num_buckets) @@ -5450,55 +5619,60 @@ class SharedEmbeddingColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column_a._parse_example_spec) + @test_util.run_deprecated_v1 def test_invalid_initializer(self): - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=3) with self.assertRaisesRegexp(ValueError, 'initializer must be callable'): - fc.shared_embedding_columns( - [categorical_column_a, categorical_column_b], dimension=2, + fc_new.shared_embedding_columns( + [categorical_column_a, categorical_column_b], + dimension=2, initializer='not_fn') + @test_util.run_deprecated_v1 def test_incompatible_column_type(self): - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=3) - categorical_column_c = fc.categorical_column_with_hash_bucket( + categorical_column_c = fc._categorical_column_with_hash_bucket( key='ccc', hash_bucket_size=3) with self.assertRaisesRegexp( ValueError, 'all categorical_columns must have the same type.*' '_IdentityCategoricalColumn.*_HashedCategoricalColumn'): - fc.shared_embedding_columns( + fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b, categorical_column_c], dimension=2) + @test_util.run_deprecated_v1 def test_weighted_categorical_column_ok(self): - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=3) - weighted_categorical_column_a = fc.weighted_categorical_column( + weighted_categorical_column_a = fc._weighted_categorical_column( categorical_column_a, weight_feature_key='aaa_weights') - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=3) - weighted_categorical_column_b = fc.weighted_categorical_column( + weighted_categorical_column_b = fc._weighted_categorical_column( categorical_column_b, weight_feature_key='bbb_weights') - fc.shared_embedding_columns( + fc_new.shared_embedding_columns( [weighted_categorical_column_a, categorical_column_b], dimension=2) - fc.shared_embedding_columns( + fc_new.shared_embedding_columns( [categorical_column_a, weighted_categorical_column_b], dimension=2) - fc.shared_embedding_columns( + fc_new.shared_embedding_columns( [weighted_categorical_column_a, weighted_categorical_column_b], dimension=2) + @test_util.run_deprecated_v1 def test_parse_example(self): - a = fc.categorical_column_with_vocabulary_list( + a = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) - b = fc.categorical_column_with_vocabulary_list( + b = fc._categorical_column_with_vocabulary_list( key='bbb', vocabulary_list=('omar', 'stringer', 'marlo')) - a_embedded, b_embedded = fc.shared_embedding_columns( - [a, b], dimension=2) + a_embedded, b_embedded = fc_new.shared_embedding_columns([a, b], + dimension=2) data = example_pb2.Example(features=feature_pb2.Features( feature={ 'aaa': @@ -5529,11 +5703,12 @@ class SharedEmbeddingColumnTest(test.TestCase): dense_shape=[1, 2]), features['bbb'].eval()) + @test_util.run_deprecated_v1 def test_transform_feature(self): - a = fc.categorical_column_with_identity(key='aaa', num_buckets=3) - b = fc.categorical_column_with_identity(key='bbb', num_buckets=3) - a_embedded, b_embedded = fc.shared_embedding_columns( - [a, b], dimension=2) + a = fc._categorical_column_with_identity(key='aaa', num_buckets=3) + b = fc._categorical_column_with_identity(key='bbb', num_buckets=3) + a_embedded, b_embedded = fc_new.shared_embedding_columns([a, b], + dimension=2) features = { 'aaa': sparse_tensor.SparseTensor( indices=((0, 0), (1, 0), (1, 1)), @@ -5550,11 +5725,12 @@ class SharedEmbeddingColumnTest(test.TestCase): output_b = outputs[b] output_b_embedded = outputs[b_embedded] with _initialized_session(): - _assert_sparse_tensor_value( - self, output_a.eval(), output_a_embedded.eval()) - _assert_sparse_tensor_value( - self, output_b.eval(), output_b_embedded.eval()) + _assert_sparse_tensor_value(self, self.evaluate(output_a), + self.evaluate(output_a_embedded)) + _assert_sparse_tensor_value(self, self.evaluate(output_b), + self.evaluate(output_b_embedded)) + @test_util.run_deprecated_v1 def test_get_dense_tensor(self): # Inputs. vocabulary_size = 3 @@ -5598,13 +5774,14 @@ class SharedEmbeddingColumnTest(test.TestCase): ) # Build columns. - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - embedding_column_a, embedding_column_b = fc.shared_embedding_columns( + embedding_column_a, embedding_column_b = fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b], - dimension=embedding_dimension, initializer=_initializer) + dimension=embedding_dimension, + initializer=_initializer) # Provide sparse input and get dense result. embedding_lookup_a = embedding_column_a._get_dense_tensor( @@ -5618,10 +5795,11 @@ class SharedEmbeddingColumnTest(test.TestCase): tuple([v.name for v in global_vars])) embedding_var = global_vars[0] with _initialized_session(): - self.assertAllEqual(embedding_values, embedding_var.eval()) - self.assertAllEqual(expected_lookups_a, embedding_lookup_a.eval()) - self.assertAllEqual(expected_lookups_b, embedding_lookup_b.eval()) + self.assertAllEqual(embedding_values, self.evaluate(embedding_var)) + self.assertAllEqual(expected_lookups_a, self.evaluate(embedding_lookup_a)) + self.assertAllEqual(expected_lookups_b, self.evaluate(embedding_lookup_b)) + @test_util.run_deprecated_v1 def test_get_dense_tensor_weight_collections(self): # Inputs. vocabulary_size = 3 @@ -5651,11 +5829,11 @@ class SharedEmbeddingColumnTest(test.TestCase): return embedding_values # Build columns. - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - embedding_column_a, embedding_column_b = fc.shared_embedding_columns( + embedding_column_a, embedding_column_b = fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=embedding_dimension, initializer=_initializer) @@ -5674,6 +5852,7 @@ class SharedEmbeddingColumnTest(test.TestCase): ('input_layer/aaa_bbb_shared_embedding/embedding_weights:0',), tuple(v.name for v in my_vars)) + @test_util.run_deprecated_v1 def test_get_dense_tensor_placeholder_inputs(self): # Inputs. vocabulary_size = 3 @@ -5712,13 +5891,14 @@ class SharedEmbeddingColumnTest(test.TestCase): return embedding_values # Build columns. - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - embedding_column_a, embedding_column_b = fc.shared_embedding_columns( + embedding_column_a, embedding_column_b = fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b], - dimension=embedding_dimension, initializer=_initializer) + dimension=embedding_dimension, + initializer=_initializer) # Provide sparse input and get dense result. embedding_lookup_a = embedding_column_a._get_dense_tensor( @@ -5729,6 +5909,7 @@ class SharedEmbeddingColumnTest(test.TestCase): with _initialized_session() as sess: sess.run([embedding_lookup_a, embedding_lookup_b], feed_dict=feed_dict) + @test_util.run_deprecated_v1 def test_linear_model(self): # Inputs. batch_size = 2 @@ -5752,13 +5933,14 @@ class SharedEmbeddingColumnTest(test.TestCase): return zeros_embedding_values # Build columns. - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - embedding_column_a, embedding_column_b = fc.shared_embedding_columns( + embedding_column_a, embedding_column_b = fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b], - dimension=embedding_dimension, initializer=_initializer) + dimension=embedding_dimension, + initializer=_initializer) with ops.Graph().as_default(): predictions = fc.linear_model({ @@ -5790,13 +5972,15 @@ class SharedEmbeddingColumnTest(test.TestCase): 'linear_model/aaa_bbb_shared_embedding_1/weights:0'] with _initialized_session(): # Predictions with all zero weights. - self.assertAllClose(np.zeros((1,)), bias.eval()) - self.assertAllClose(zeros_embedding_values, embedding_weights.eval()) + self.assertAllClose(np.zeros((1,)), self.evaluate(bias)) + self.assertAllClose(zeros_embedding_values, + self.evaluate(embedding_weights)) + self.assertAllClose( + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights_a)) self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights_a.eval()) + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights_b)) self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights_b.eval()) - self.assertAllClose(np.zeros((batch_size, 1)), predictions.eval()) + np.zeros((batch_size, 1)), self.evaluate(predictions)) # Predictions with all non-zero weights. embedding_weights.assign(( @@ -5814,8 +5998,9 @@ class SharedEmbeddingColumnTest(test.TestCase): # example 1, ids [], embedding[1] = 0, 0] # sum(embeddings * linear_weights) # = [3*1 + 5*2, 3*0 +5*0] = [13, 0] - self.assertAllClose([[94. + 13.], [29.]], predictions.eval()) + self.assertAllClose([[94. + 13.], [29.]], self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): # Inputs. batch_size = 2 @@ -5842,11 +6027,11 @@ class SharedEmbeddingColumnTest(test.TestCase): return zeros_embedding_values # Build columns. - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - embedding_column_a, embedding_column_b = fc.shared_embedding_columns( + embedding_column_a, embedding_column_b = fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=embedding_dimension, initializer=_initializer) @@ -5881,13 +6066,15 @@ class SharedEmbeddingColumnTest(test.TestCase): 'linear_model/aaa_bbb_shared_embedding_1/weights:0'] with _initialized_session(): # Predictions with all zero weights. - self.assertAllClose(np.zeros((1,)), bias.eval()) - self.assertAllClose(zeros_embedding_values, embedding_weights.eval()) + self.assertAllClose(np.zeros((1,)), self.evaluate(bias)) + self.assertAllClose(zeros_embedding_values, + self.evaluate(embedding_weights)) self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights_a.eval()) + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights_a)) self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights_b.eval()) - self.assertAllClose(np.zeros((batch_size, 1)), predictions.eval()) + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights_b)) + self.assertAllClose( + np.zeros((batch_size, 1)), self.evaluate(predictions)) # Predictions with all non-zero weights. embedding_weights.assign(( @@ -5905,7 +6092,7 @@ class SharedEmbeddingColumnTest(test.TestCase): # example 1, ids [], embedding[1] = 0, 0] # sum(embeddings * linear_weights) # = [3*1 + 5*2, 3*0 +5*0] = [13, 0] - self.assertAllClose([[94. + 13.], [29.]], predictions.eval()) + self.assertAllClose([[94. + 13.], [29.]], self.evaluate(predictions)) def _test_input_layer(self, trainable=True): # Inputs. @@ -5949,13 +6136,14 @@ class SharedEmbeddingColumnTest(test.TestCase): ) # Build columns. - categorical_column_a = fc.categorical_column_with_identity( + categorical_column_a = fc._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) - categorical_column_b = fc.categorical_column_with_identity( + categorical_column_b = fc._categorical_column_with_identity( key='bbb', num_buckets=vocabulary_size) - embedding_column_a, embedding_column_b = fc.shared_embedding_columns( + embedding_column_a, embedding_column_b = fc_new.shared_embedding_columns( [categorical_column_a, categorical_column_b], - dimension=embedding_dimension, initializer=_initializer, + dimension=embedding_dimension, + initializer=_initializer, trainable=trainable) # Provide sparse input and get dense result. @@ -5978,20 +6166,23 @@ class SharedEmbeddingColumnTest(test.TestCase): shared_embedding_vars = global_vars with _initialized_session(): self.assertAllEqual(embedding_values, shared_embedding_vars[0].eval()) - self.assertAllEqual(expected_lookups, input_layer.eval()) + self.assertAllEqual(expected_lookups, self.evaluate(input_layer)) + @test_util.run_deprecated_v1 def test_input_layer(self): self._test_input_layer() + @test_util.run_deprecated_v1 def test_input_layer_no_trainable(self): self._test_input_layer(trainable=False) class WeightedCategoricalColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') self.assertEqual('ids_weighted_by_values', column.name) @@ -6002,10 +6193,11 @@ class WeightedCategoricalColumnTest(test.TestCase): 'values': parsing_ops.VarLenFeature(dtypes.float32) }, column._parse_example_spec) + @test_util.run_deprecated_v1 def test_deep_copy(self): """Tests deepcopy of categorical_column_with_hash_bucket.""" - original = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + original = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') for column in (original, copy.deepcopy(original)): @@ -6018,23 +6210,23 @@ class WeightedCategoricalColumnTest(test.TestCase): def test_invalid_dtype_none(self): with self.assertRaisesRegexp(ValueError, 'is not convertible to float'): - fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values', dtype=None) def test_invalid_dtype_string(self): with self.assertRaisesRegexp(ValueError, 'is not convertible to float'): - fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values', dtype=dtypes.string) def test_invalid_input_dtype(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') strings = sparse_tensor.SparseTensorValue( @@ -6046,14 +6238,14 @@ class WeightedCategoricalColumnTest(test.TestCase): def test_column_name_collision(self): with self.assertRaisesRegexp(ValueError, r'Parse config.*already exists'): - fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='aaa', num_buckets=3), weight_feature_key='aaa')._parse_example_spec() def test_missing_weights(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') inputs = sparse_tensor.SparseTensorValue( @@ -6064,10 +6256,12 @@ class WeightedCategoricalColumnTest(test.TestCase): ValueError, 'values is not in features dictionary'): _transform_features({'ids': inputs}, (column,)) + @test_util.run_deprecated_v1 def test_parse_example(self): - a = fc.categorical_column_with_vocabulary_list( + a = fc._categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) - a_weighted = fc.weighted_categorical_column(a, weight_feature_key='weights') + a_weighted = fc._weighted_categorical_column( + a, weight_feature_key='weights') data = example_pb2.Example(features=feature_pb2.Features( feature={ 'aaa': @@ -6098,9 +6292,10 @@ class WeightedCategoricalColumnTest(test.TestCase): dense_shape=[1, 2]), features['weights'].eval()) + @test_util.run_deprecated_v1 def test_transform_features(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') inputs = sparse_tensor.SparseTensorValue( @@ -6121,19 +6316,18 @@ class WeightedCategoricalColumnTest(test.TestCase): sparse_tensor.SparseTensorValue( indices=inputs.indices, values=np.array(inputs.values, dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) _assert_sparse_tensor_value( self, sparse_tensor.SparseTensorValue( indices=weights.indices, values=np.array(weights.values, dtype=np.float32), - dense_shape=weights.dense_shape), - weight_tensor.eval()) + dense_shape=weights.dense_shape), self.evaluate(weight_tensor)) + @test_util.run_deprecated_v1 def test_transform_features_dense_input(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') weights = sparse_tensor.SparseTensorValue( @@ -6150,19 +6344,18 @@ class WeightedCategoricalColumnTest(test.TestCase): sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=np.array((0, 1, 0), dtype=np.int64), - dense_shape=(2, 2)), - id_tensor.eval()) + dense_shape=(2, 2)), self.evaluate(id_tensor)) _assert_sparse_tensor_value( self, sparse_tensor.SparseTensorValue( indices=weights.indices, values=np.array(weights.values, dtype=np.float32), - dense_shape=weights.dense_shape), - weight_tensor.eval()) + dense_shape=weights.dense_shape), self.evaluate(weight_tensor)) + @test_util.run_deprecated_v1 def test_transform_features_dense_weights(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') inputs = sparse_tensor.SparseTensorValue( @@ -6179,19 +6372,18 @@ class WeightedCategoricalColumnTest(test.TestCase): sparse_tensor.SparseTensorValue( indices=inputs.indices, values=np.array(inputs.values, dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) _assert_sparse_tensor_value( self, sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=np.array((.5, 1., .1), dtype=np.float32), - dense_shape=(2, 2)), - weight_tensor.eval()) + dense_shape=(2, 2)), self.evaluate(weight_tensor)) + @test_util.run_deprecated_v1 def test_keras_linear_model(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') with ops.Graph().as_default(): @@ -6210,18 +6402,18 @@ class WeightedCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) weight_var.assign(((1.,), (2.,), (3.,))).eval() # weight_var[0] * weights[0, 0] = 1 * .5 = .5 # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] # = 3*1 + 2*.1 = 3+.2 = 3.2 - self.assertAllClose(((.5,), (3.2,)), predictions.eval()) + self.assertAllClose(((.5,), (3.2,)), self.evaluate(predictions)) def test_keras_linear_model_mismatched_shape(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') with ops.Graph().as_default(): @@ -6241,8 +6433,8 @@ class WeightedCategoricalColumnTest(test.TestCase): }, (column,)) def test_keras_linear_model_mismatched_dense_values(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') with ops.Graph().as_default(): @@ -6263,11 +6455,11 @@ class WeightedCategoricalColumnTest(test.TestCase): rewriter_config_pb2.RewriterConfig.OFF) with _initialized_session(config): with self.assertRaisesRegexp(errors.OpError, 'Incompatible shapes'): - predictions.eval() + self.evaluate(predictions) def test_keras_linear_model_mismatched_dense_shape(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') with ops.Graph().as_default(): @@ -6282,18 +6474,19 @@ class WeightedCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) weight_var.assign(((1.,), (2.,), (3.,))).eval() # weight_var[0] * weights[0, 0] = 1 * .5 = .5 # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] # = 3*1 + 2*.1 = 3+.2 = 3.2 - self.assertAllClose(((.5,), (3.2,)), predictions.eval()) + self.assertAllClose(((.5,), (3.2,)), self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_linear_model(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') with ops.Graph().as_default(): @@ -6310,18 +6503,18 @@ class WeightedCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) weight_var.assign(((1.,), (2.,), (3.,))).eval() # weight_var[0] * weights[0, 0] = 1 * .5 = .5 # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] # = 3*1 + 2*.1 = 3+.2 = 3.2 - self.assertAllClose(((.5,), (3.2,)), predictions.eval()) + self.assertAllClose(((.5,), (3.2,)), self.evaluate(predictions)) def test_linear_model_mismatched_shape(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') with ops.Graph().as_default(): @@ -6339,8 +6532,8 @@ class WeightedCategoricalColumnTest(test.TestCase): }, (column,)) def test_linear_model_mismatched_dense_values(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') with ops.Graph().as_default(): @@ -6361,11 +6554,11 @@ class WeightedCategoricalColumnTest(test.TestCase): rewriter_config_pb2.RewriterConfig.OFF) with _initialized_session(config): with self.assertRaisesRegexp(errors.OpError, 'Incompatible shapes'): - predictions.eval() + self.evaluate(predictions) def test_linear_model_mismatched_dense_shape(self): - column = fc.weighted_categorical_column( - categorical_column=fc.categorical_column_with_identity( + column = fc._weighted_categorical_column( + categorical_column=fc._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') with ops.Graph().as_default(): @@ -6379,14 +6572,14 @@ class WeightedCategoricalColumnTest(test.TestCase): bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) weight_var.assign(((1.,), (2.,), (3.,))).eval() # weight_var[0] * weights[0, 0] = 1 * .5 = .5 # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] # = 3*1 + 2*.1 = 3+.2 = 3.2 - self.assertAllClose(((.5,), (3.2,)), predictions.eval()) + self.assertAllClose(((.5,), (3.2,)), self.evaluate(predictions)) # TODO(ptucker): Add test with embedding of weighted categorical. diff --git a/tensorflow/python/feature_column/feature_column_v2.py b/tensorflow/python/feature_column/feature_column_v2.py index 9b4a7e882f..6308926494 100644 --- a/tensorflow/python/feature_column/feature_column_v2.py +++ b/tensorflow/python/feature_column/feature_column_v2.py @@ -165,6 +165,7 @@ from tensorflow.python.training import checkpoint_utils from tensorflow.python.training.checkpointable import tracking from tensorflow.python.util import deprecation from tensorflow.python.util import nest +from tensorflow.python.util.tf_export import tf_export _FEATURE_COLUMN_DEPRECATION_DATE = '2018-11-30' @@ -258,7 +259,7 @@ class StateManager(object): class _StateManagerImpl(StateManager): - """Manages the state of FeatureLayer and LinearModel.""" + """Manages the state of DenseFeatures and LinearLayer.""" def __init__(self, layer, trainable): """Creates an _StateManagerImpl object. @@ -302,7 +303,8 @@ class _StateManagerImpl(StateManager): raise ValueError('Variable does not exist.') -class FeatureLayer(Layer): +@tf_export('keras.layers.DenseFeatures', v1=[]) +class DenseFeatures(Layer): """A layer that produces a dense `Tensor` based on given `feature_columns`. Generally a single example in training data is described with FeatureColumns. @@ -318,7 +320,7 @@ class FeatureLayer(Layer): keywords_embedded = embedding_column( categorical_column_with_hash_bucket("keywords", 10K), dimensions=16) columns = [price, keywords_embedded, ...] - feature_layer = FeatureLayer(columns) + feature_layer = DenseFeatures(columns) features = tf.parse_example(..., features=make_parse_example_spec(columns)) dense_tensor = feature_layer(features) @@ -333,7 +335,7 @@ class FeatureLayer(Layer): trainable=True, name=None, **kwargs): - """Constructs a FeatureLayer. + """Constructs a DenseFeatures. Args: feature_columns: An iterable containing the FeatureColumns to use as @@ -344,13 +346,14 @@ class FeatureLayer(Layer): `indicator_column`. trainable: If `True` also add the variable to the graph collection `GraphKeys.TRAINABLE_VARIABLES` (see `tf.Variable`). - name: Name to give to the FeatureLayer. + name: Name to give to the DenseFeatures. **kwargs: Keyword arguments to construct a layer. Raises: ValueError: if an item in `feature_columns` is not a `DenseColumn`. """ - super(FeatureLayer, self).__init__(name=name, trainable=trainable, **kwargs) + super(DenseFeatures, self).__init__( + name=name, trainable=trainable, **kwargs) self._feature_columns = _normalize_feature_columns(feature_columns) self._feature_columns = sorted(self._feature_columns, key=lambda x: x.name) @@ -371,7 +374,7 @@ class FeatureLayer(Layer): with variable_scope._pure_variable_scope(self.name): # pylint: disable=protected-access with variable_scope._pure_variable_scope(column.name): # pylint: disable=protected-access column.create_state(self._state_manager) - super(FeatureLayer, self).build(None) + super(DenseFeatures, self).build(None) def call(self, features, cols_to_output_tensors=None): """Returns a dense tensor corresponding to the `feature_columns`. @@ -515,6 +518,7 @@ class _LinearModelLayer(Layer): return predictions +@tf_export('keras.layers.LinearModel', v1=[]) class LinearModel(training.Model): """Produces a linear prediction `Tensor` based on given `feature_columns`. @@ -522,7 +526,7 @@ class LinearModel(training.Model): Weighted sum refers to logits in classification problems. It refers to the prediction itself for linear regression problems. - Note on supported columns: `LinearModel` treats categorical columns as + Note on supported columns: `LinearLayer` treats categorical columns as `indicator_column`s. To be specific, assume the input as `SparseTensor` looks like: @@ -547,7 +551,7 @@ class LinearModel(training.Model): keywords = categorical_column_with_hash_bucket("keywords", 10K) keywords_price = crossed_column('keywords', price_buckets, ...) columns = [price_buckets, keywords, keywords_price ...] - linear_model = LinearModel(columns) + linear_model = LinearLayer(columns) features = tf.parse_example(..., features=make_parse_example_spec(columns)) prediction = linear_model(features) @@ -561,7 +565,7 @@ class LinearModel(training.Model): trainable=True, name=None, **kwargs): - """Constructs a LinearModel. + """Constructs a LinearLayer. Args: feature_columns: An iterable containing the FeatureColumns to use as @@ -650,7 +654,7 @@ class LinearModel(training.Model): return self.layer.bias -def _transform_features(features, feature_columns, state_manager): +def _transform_features_v2(features, feature_columns, state_manager): """Returns transformed features based on features columns passed in. Please note that most probably you would not need to use this function. Please @@ -695,7 +699,8 @@ def _transform_features(features, feature_columns, state_manager): return outputs -def make_parse_example_spec(feature_columns): +@tf_export('feature_column.make_parse_example_spec', v1=[]) +def make_parse_example_spec_v2(feature_columns): """Creates parsing spec dictionary from input feature_columns. The returned dictionary can be used as arg 'features' in `tf.parse_example`. @@ -754,10 +759,15 @@ def make_parse_example_spec(feature_columns): return result -def embedding_column( - categorical_column, dimension, combiner='mean', initializer=None, - ckpt_to_load_from=None, tensor_name_in_ckpt=None, max_norm=None, - trainable=True): +@tf_export('feature_column.embedding_column') +def embedding_column(categorical_column, + dimension, + combiner='mean', + initializer=None, + ckpt_to_load_from=None, + tensor_name_in_ckpt=None, + max_norm=None, + trainable=True): """`DenseColumn` that converts from sparse, categorical input. Use this when your inputs are sparse, but you want to convert them to a dense @@ -854,6 +864,180 @@ def embedding_column( trainable=trainable) +@tf_export(v1=['feature_column.shared_embedding_columns']) +def shared_embedding_columns(categorical_columns, + dimension, + combiner='mean', + initializer=None, + shared_embedding_collection_name=None, + ckpt_to_load_from=None, + tensor_name_in_ckpt=None, + max_norm=None, + trainable=True): + """List of dense columns that convert from sparse, categorical input. + + This is similar to `embedding_column`, except that it produces a list of + embedding columns that share the same embedding weights. + + Use this when your inputs are sparse and of the same type (e.g. watched and + impression video IDs that share the same vocabulary), and you want to convert + them to a dense representation (e.g., to feed to a DNN). + + Inputs must be a list of categorical columns created by any of the + `categorical_column_*` function. They must all be of the same type and have + the same arguments except `key`. E.g. they can be + categorical_column_with_vocabulary_file with the same vocabulary_file. Some or + all columns could also be weighted_categorical_column. + + Here is an example embedding of two features for a DNNClassifier model: + + ```python + watched_video_id = categorical_column_with_vocabulary_file( + 'watched_video_id', video_vocabulary_file, video_vocabulary_size) + impression_video_id = categorical_column_with_vocabulary_file( + 'impression_video_id', video_vocabulary_file, video_vocabulary_size) + columns = shared_embedding_columns( + [watched_video_id, impression_video_id], dimension=10) + + estimator = tf.estimator.DNNClassifier(feature_columns=columns, ...) + + label_column = ... + def input_fn(): + features = tf.parse_example( + ..., features=make_parse_example_spec(columns + [label_column])) + labels = features.pop(label_column.name) + return features, labels + + estimator.train(input_fn=input_fn, steps=100) + ``` + + Here is an example using `shared_embedding_columns` with model_fn: + + ```python + def model_fn(features, ...): + watched_video_id = categorical_column_with_vocabulary_file( + 'watched_video_id', video_vocabulary_file, video_vocabulary_size) + impression_video_id = categorical_column_with_vocabulary_file( + 'impression_video_id', video_vocabulary_file, video_vocabulary_size) + columns = shared_embedding_columns( + [watched_video_id, impression_video_id], dimension=10) + dense_tensor = input_layer(features, columns) + # Form DNN layers, calculate loss, and return EstimatorSpec. + ... + ``` + + Args: + categorical_columns: List of categorical columns created by a + `categorical_column_with_*` function. These columns produce the sparse IDs + that are inputs to the embedding lookup. All columns must be of the same + type and have the same arguments except `key`. E.g. they can be + categorical_column_with_vocabulary_file with the same vocabulary_file. + Some or all columns could also be weighted_categorical_column. + dimension: An integer specifying dimension of the embedding, must be > 0. + combiner: A string specifying how to reduce if there are multiple entries in + a single row. Currently 'mean', 'sqrtn' and 'sum' are supported, with + 'mean' the default. 'sqrtn' often achieves good accuracy, in particular + with bag-of-words columns. Each of this can be thought as example level + normalizations on the column. For more information, see + `tf.embedding_lookup_sparse`. + initializer: A variable initializer function to be used in embedding + variable initialization. If not specified, defaults to + `tf.truncated_normal_initializer` with mean `0.0` and standard deviation + `1/sqrt(dimension)`. + shared_embedding_collection_name: Optional name of the collection where + shared embedding weights are added. If not given, a reasonable name will + be chosen based on the names of `categorical_columns`. This is also used + in `variable_scope` when creating shared embedding weights. + ckpt_to_load_from: String representing checkpoint name/pattern from which to + restore column weights. Required if `tensor_name_in_ckpt` is not `None`. + tensor_name_in_ckpt: Name of the `Tensor` in `ckpt_to_load_from` from which + to restore the column weights. Required if `ckpt_to_load_from` is not + `None`. + max_norm: If not `None`, each embedding is clipped if its l2-norm is larger + than this value, before combining. + trainable: Whether or not the embedding is trainable. Default is True. + + Returns: + A list of dense columns that converts from sparse input. The order of + results follows the ordering of `categorical_columns`. + + Raises: + ValueError: if `dimension` not > 0. + ValueError: if any of the given `categorical_columns` is of different type + or has different arguments than the others. + ValueError: if exactly one of `ckpt_to_load_from` and `tensor_name_in_ckpt` + is specified. + ValueError: if `initializer` is specified and is not callable. + RuntimeError: if eager execution is enabled. + """ + if context.executing_eagerly(): + raise RuntimeError('shared_embedding_columns are not supported when eager ' + 'execution is enabled.') + + if (dimension is None) or (dimension < 1): + raise ValueError('Invalid dimension {}.'.format(dimension)) + if (ckpt_to_load_from is None) != (tensor_name_in_ckpt is None): + raise ValueError('Must specify both `ckpt_to_load_from` and ' + '`tensor_name_in_ckpt` or none of them.') + + if (initializer is not None) and (not callable(initializer)): + raise ValueError('initializer must be callable if specified.') + if initializer is None: + initializer = init_ops.truncated_normal_initializer( + mean=0.0, stddev=1. / math.sqrt(dimension)) + + # Sort the columns so the default collection name is deterministic even if the + # user passes columns from an unsorted collection, such as dict.values(). + sorted_columns = sorted(categorical_columns, key=lambda x: x.name) + + c0 = sorted_columns[0] + num_buckets = c0._num_buckets # pylint: disable=protected-access + if not isinstance(c0, fc_old._CategoricalColumn): # pylint: disable=protected-access + raise ValueError( + 'All categorical_columns must be subclasses of _CategoricalColumn. ' + 'Given: {}, of type: {}'.format(c0, type(c0))) + if isinstance(c0, + (fc_old._WeightedCategoricalColumn, WeightedCategoricalColumn)): # pylint: disable=protected-access + c0 = c0.categorical_column + for c in sorted_columns[1:]: + if isinstance( + c, (fc_old._WeightedCategoricalColumn, WeightedCategoricalColumn)): # pylint: disable=protected-access + c = c.categorical_column + if not isinstance(c, type(c0)): + raise ValueError( + 'To use shared_embedding_column, all categorical_columns must have ' + 'the same type, or be weighted_categorical_column of the same type. ' + 'Given column: {} of type: {} does not match given column: {} of ' + 'type: {}'.format(c0, type(c0), c, type(c))) + if num_buckets != c._num_buckets: # pylint: disable=protected-access + raise ValueError( + 'To use shared_embedding_column, all categorical_columns must have ' + 'the same number of buckets. Given column: {} with buckets: {} does ' + 'not match column: {} with buckets: {}'.format( + c0, num_buckets, c, c._num_buckets)) # pylint: disable=protected-access + + if not shared_embedding_collection_name: + shared_embedding_collection_name = '_'.join(c.name for c in sorted_columns) + shared_embedding_collection_name += '_shared_embedding' + + result = [] + for column in categorical_columns: + result.append( + fc_old._SharedEmbeddingColumn( # pylint: disable=protected-access + categorical_column=column, + initializer=initializer, + dimension=dimension, + combiner=combiner, + shared_embedding_collection_name=shared_embedding_collection_name, + ckpt_to_load_from=ckpt_to_load_from, + tensor_name_in_ckpt=tensor_name_in_ckpt, + max_norm=max_norm, + trainable=trainable)) + + return result + + +@tf_export('feature_column.shared_embedding_columns', v1=[]) def shared_embedding_columns_v2(categorical_columns, dimension, combiner='mean', @@ -1019,6 +1203,7 @@ def shared_embedding_columns_v2(categorical_columns, return result +@tf_export('feature_column.numeric_column') def numeric_column(key, shape=(1,), default_value=None, @@ -1094,6 +1279,7 @@ def numeric_column(key, normalizer_fn=normalizer_fn) +@tf_export('feature_column.bucketized_column') def bucketized_column(source_column, boundaries): """Represents discretized dense input. @@ -1190,6 +1376,7 @@ def _assert_key_is_string(key): type(key), key)) +@tf_export('feature_column.categorical_column_with_hash_bucket') def categorical_column_with_hash_bucket(key, hash_bucket_size, dtype=dtypes.string): @@ -1248,6 +1435,7 @@ def categorical_column_with_hash_bucket(key, return HashedCategoricalColumn(key, hash_bucket_size, dtype) +@tf_export(v1=['feature_column.categorical_column_with_vocabulary_file']) def categorical_column_with_vocabulary_file(key, vocabulary_file, vocabulary_size=None, @@ -1325,6 +1513,97 @@ def categorical_column_with_vocabulary_file(key, Returns: A `CategoricalColumn` with a vocabulary file. + Raises: + ValueError: `vocabulary_file` is missing or cannot be opened. + ValueError: `vocabulary_size` is missing or < 1. + ValueError: `num_oov_buckets` is a negative integer. + ValueError: `num_oov_buckets` and `default_value` are both specified. + ValueError: `dtype` is neither string nor integer. + """ + return categorical_column_with_vocabulary_file_v2( + key, vocabulary_file, vocabulary_size, + dtype, default_value, + num_oov_buckets) + + +@tf_export('feature_column.categorical_column_with_vocabulary_file', v1=[]) +def categorical_column_with_vocabulary_file_v2(key, + vocabulary_file, + vocabulary_size=None, + dtype=dtypes.string, + default_value=None, + num_oov_buckets=0): + """A `CategoricalColumn` with a vocabulary file. + + Use this when your inputs are in string or integer format, and you have a + vocabulary file that maps each value to an integer ID. By default, + out-of-vocabulary values are ignored. Use either (but not both) of + `num_oov_buckets` and `default_value` to specify how to include + out-of-vocabulary values. + + For input dictionary `features`, `features[key]` is either `Tensor` or + `SparseTensor`. If `Tensor`, missing values can be represented by `-1` for int + and `''` for string, which will be dropped by this feature column. + + Example with `num_oov_buckets`: + File '/us/states.txt' contains 50 lines, each with a 2-character U.S. state + abbreviation. All inputs with values in that file are assigned an ID 0-49, + corresponding to its line number. All other values are hashed and assigned an + ID 50-54. + + ```python + states = categorical_column_with_vocabulary_file( + key='states', vocabulary_file='/us/states.txt', vocabulary_size=50, + num_oov_buckets=5) + columns = [states, ...] + features = tf.parse_example(..., features=make_parse_example_spec(columns)) + linear_prediction = linear_model(features, columns) + ``` + + Example with `default_value`: + File '/us/states.txt' contains 51 lines - the first line is 'XX', and the + other 50 each have a 2-character U.S. state abbreviation. Both a literal 'XX' + in input, and other values missing from the file, will be assigned ID 0. All + others are assigned the corresponding line number 1-50. + + ```python + states = categorical_column_with_vocabulary_file( + key='states', vocabulary_file='/us/states.txt', vocabulary_size=51, + default_value=0) + columns = [states, ...] + features = tf.parse_example(..., features=make_parse_example_spec(columns)) + linear_prediction, _, _ = linear_model(features, columns) + ``` + + And to make an embedding with either: + + ```python + columns = [embedding_column(states, 3),...] + features = tf.parse_example(..., features=make_parse_example_spec(columns)) + dense_tensor = input_layer(features, columns) + ``` + + Args: + key: A unique string identifying the input feature. It is used as the + column name and the dictionary key for feature parsing configs, feature + `Tensor` objects, and feature columns. + vocabulary_file: The vocabulary file name. + vocabulary_size: Number of the elements in the vocabulary. This must be no + greater than length of `vocabulary_file`, if less than length, later + values are ignored. If None, it is set to the length of `vocabulary_file`. + dtype: The type of features. Only string and integer types are supported. + default_value: The integer ID value to return for out-of-vocabulary feature + values, defaults to `-1`. This can not be specified with a positive + `num_oov_buckets`. + num_oov_buckets: Non-negative integer, the number of out-of-vocabulary + buckets. All out-of-vocabulary inputs will be assigned IDs in the range + `[vocabulary_size, vocabulary_size+num_oov_buckets)` based on a hash of + the input value. A positive `num_oov_buckets` can not be specified with + `default_value`. + + Returns: + A `CategoricalColumn` with a vocabulary file. + Raises: ValueError: `vocabulary_file` is missing or cannot be opened. ValueError: `vocabulary_size` is missing or < 1. @@ -1367,8 +1646,12 @@ def categorical_column_with_vocabulary_file(key, dtype=dtype) -def categorical_column_with_vocabulary_list( - key, vocabulary_list, dtype=None, default_value=-1, num_oov_buckets=0): +@tf_export('feature_column.categorical_column_with_vocabulary_list') +def categorical_column_with_vocabulary_list(key, + vocabulary_list, + dtype=None, + default_value=-1, + num_oov_buckets=0): """A `CategoricalColumn` with in-memory vocabulary. Use this when your inputs are in string or integer format, and you have an @@ -1480,6 +1763,7 @@ def categorical_column_with_vocabulary_list( num_oov_buckets=num_oov_buckets) +@tf_export('feature_column.categorical_column_with_identity') def categorical_column_with_identity(key, num_buckets, default_value=None): """A `CategoricalColumn` that returns identity values. @@ -1547,6 +1831,7 @@ def categorical_column_with_identity(key, num_buckets, default_value=None): key=key, number_buckets=num_buckets, default_value=default_value) +@tf_export('feature_column.indicator_column') def indicator_column(categorical_column): """Represents multi-hot representation of given categorical column. @@ -1581,8 +1866,10 @@ def indicator_column(categorical_column): return IndicatorColumn(categorical_column) -def weighted_categorical_column( - categorical_column, weight_feature_key, dtype=dtypes.float32): +@tf_export('feature_column.weighted_categorical_column') +def weighted_categorical_column(categorical_column, + weight_feature_key, + dtype=dtypes.float32): """Applies weight values to a `CategoricalColumn`. Use this when each of your sparse inputs has both an ID and a value. For @@ -1655,6 +1942,7 @@ def weighted_categorical_column( dtype=dtype) +@tf_export('feature_column.crossed_column') def crossed_column(keys, hash_bucket_size, hash_key=None): """Returns a column for performing crosses of categorical features. @@ -2120,7 +2408,7 @@ def _create_categorical_column_weighted_sum( weight_tensor = sparse_ops.sparse_reshape( weight_tensor, [array_ops.shape(weight_tensor)[0], -1]) - return _safe_embedding_lookup_sparse( + return embedding_ops.safe_embedding_lookup_sparse( weight_var, id_tensor, sparse_weights=weight_tensor, @@ -2731,7 +3019,7 @@ class EmbeddingColumn( }) # Return embedding lookup result. - return _safe_embedding_lookup_sparse( + return embedding_ops.safe_embedding_lookup_sparse( embedding_weights=embedding_weights, sparse_ids=sparse_ids, sparse_weights=sparse_weights, @@ -2890,7 +3178,7 @@ class EmbeddingColumn( def _raise_shared_embedding_column_error(): raise ValueError('SharedEmbeddingColumns are not supported in ' '`linear_model` or `input_layer`. Please use ' - '`FeatureLayer` or `LinearModel` instead.') + '`DenseFeatures` or `LinearModel` instead.') class SharedEmbeddingColumnCreator(tracking.Checkpointable): @@ -3002,7 +3290,7 @@ class SharedEmbeddingColumn( embedding_weights = self.shared_embedding_column_creator.embedding_weights # Return embedding lookup result. - return _safe_embedding_lookup_sparse( + return embedding_ops.safe_embedding_lookup_sparse( embedding_weights=embedding_weights, sparse_ids=sparse_ids, sparse_weights=sparse_weights, @@ -3687,9 +3975,13 @@ class WeightedCategoricalColumn( def transform_feature(self, transformation_cache, state_manager): """Applies weights to tensor generated from `categorical_column`'.""" + print('WeightedCategoricalColumn.transform_feature: ', self.name) + print('Weight feature key: ', self.weight_feature_key) weight_tensor = transformation_cache.get(self.weight_feature_key, state_manager) + print('Weight tensor before: ', weight_tensor) weight_tensor = self._transform_weight_tensor(weight_tensor) + print('Weight tensor after: ', weight_tensor) return (transformation_cache.get(self.categorical_column, state_manager), weight_tensor) @@ -3703,7 +3995,9 @@ class WeightedCategoricalColumn( def get_sparse_tensors(self, transformation_cache, state_manager): """See `CategoricalColumn` base class.""" + print('WeightedCategoricalColumn.get_sparse_tensors: ', self.name) tensors = transformation_cache.get(self, state_manager) + print('tensors[1]: ', tensors[1]) return CategoricalColumn.IdWeightPair(tensors[0], tensors[1]) @deprecation.deprecated(_FEATURE_COLUMN_DEPRECATION_DATE, @@ -3898,142 +4192,6 @@ def _collect_leaf_level_keys(cross): return leaf_level_keys -# TODO(zakaria): Move this to embedding_ops and make it public. -def _safe_embedding_lookup_sparse(embedding_weights, - sparse_ids, - sparse_weights=None, - combiner='mean', - default_id=None, - name=None, - partition_strategy='div', - max_norm=None): - """Lookup embedding results, accounting for invalid IDs and empty features. - - The partitioned embedding in `embedding_weights` must all be the same shape - except for the first dimension. The first dimension is allowed to vary as the - vocabulary size is not necessarily a multiple of `P`. `embedding_weights` - may be a `PartitionedVariable` as returned by using `tf.get_variable()` with a - partitioner. - - Invalid IDs (< 0) are pruned from input IDs and weights, as well as any IDs - with non-positive weight. For an entry with no features, the embedding vector - for `default_id` is returned, or the 0-vector if `default_id` is not supplied. - - The ids and weights may be multi-dimensional. Embeddings are always aggregated - along the last dimension. - - Args: - embedding_weights: A list of `P` float `Tensor`s or values representing - partitioned embedding `Tensor`s. Alternatively, a `PartitionedVariable` - created by partitioning along dimension 0. The total unpartitioned - shape should be `[e_0, e_1, ..., e_m]`, where `e_0` represents the - vocab size and `e_1, ..., e_m` are the embedding dimensions. - sparse_ids: `SparseTensor` of shape `[d_0, d_1, ..., d_n]` containing the - ids. `d_0` is typically batch size. - sparse_weights: `SparseTensor` of same shape as `sparse_ids`, containing - float weights corresponding to `sparse_ids`, or `None` if all weights - are be assumed to be 1.0. - combiner: A string specifying how to combine embedding results for each - entry. Currently "mean", "sqrtn" and "sum" are supported, with "mean" - the default. - default_id: The id to use for an entry with no features. - name: A name for this operation (optional). - partition_strategy: A string specifying the partitioning strategy. - Currently `"div"` and `"mod"` are supported. Default is `"div"`. - max_norm: If not `None`, all embeddings are l2-normalized to max_norm before - combining. - - - Returns: - Dense `Tensor` of shape `[d_0, d_1, ..., d_{n-1}, e_1, ..., e_m]`. - - Raises: - ValueError: if `embedding_weights` is empty. - """ - if embedding_weights is None: - raise ValueError('Missing embedding_weights %s.' % embedding_weights) - if isinstance(embedding_weights, variables.PartitionedVariable): - embedding_weights = list(embedding_weights) # get underlying Variables. - if not isinstance(embedding_weights, list): - embedding_weights = [embedding_weights] - if len(embedding_weights) < 1: - raise ValueError('Missing embedding_weights %s.' % embedding_weights) - - dtype = sparse_weights.dtype if sparse_weights is not None else None - # TODO(rohanj): Look into removing this convert_to_tensor call. - embedding_weights = [ - ops.convert_to_tensor(w, dtype=dtype) for w in embedding_weights - ] - - with ops.name_scope(name, 'embedding_lookup', - embedding_weights + [sparse_ids, - sparse_weights]) as scope: - # Reshape higher-rank sparse ids and weights to linear segment ids. - original_shape = sparse_ids.dense_shape - original_rank_dim = tensor_shape.dimension_value( - sparse_ids.dense_shape.get_shape()[0]) - original_rank = ( - array_ops.size(original_shape) - if original_rank_dim is None - else original_rank_dim) - sparse_ids = sparse_ops.sparse_reshape(sparse_ids, [ - math_ops.reduce_prod( - array_ops.slice(original_shape, [0], [original_rank - 1])), - array_ops.gather(original_shape, original_rank - 1)]) - if sparse_weights is not None: - sparse_weights = sparse_tensor_lib.SparseTensor( - sparse_ids.indices, - sparse_weights.values, sparse_ids.dense_shape) - - # Prune invalid ids and weights. - sparse_ids, sparse_weights = _prune_invalid_ids(sparse_ids, sparse_weights) - if combiner != 'sum': - sparse_ids, sparse_weights = _prune_invalid_weights( - sparse_ids, sparse_weights) - - # Fill in dummy values for empty features, if necessary. - sparse_ids, is_row_empty = sparse_ops.sparse_fill_empty_rows(sparse_ids, - default_id or - 0) - if sparse_weights is not None: - sparse_weights, _ = sparse_ops.sparse_fill_empty_rows(sparse_weights, 1.0) - - result = embedding_ops.embedding_lookup_sparse( - embedding_weights, - sparse_ids, - sparse_weights, - combiner=combiner, - partition_strategy=partition_strategy, - name=None if default_id is None else scope, - max_norm=max_norm) - - if default_id is None: - # Broadcast is_row_empty to the same shape as embedding_lookup_result, - # for use in Select. - is_row_empty = array_ops.tile( - array_ops.reshape(is_row_empty, [-1, 1]), - array_ops.stack([1, array_ops.shape(result)[1]])) - - result = array_ops.where(is_row_empty, - array_ops.zeros_like(result), - result, - name=scope) - - # Reshape back from linear ids back into higher-dimensional dense result. - final_result = array_ops.reshape( - result, - array_ops.concat([ - array_ops.slice( - math_ops.cast(original_shape, dtypes.int32), [0], - [original_rank - 1]), - array_ops.slice(array_ops.shape(result), [1], [-1]) - ], 0)) - final_result.set_shape(tensor_shape.unknown_shape( - (tensor_shape.Dimension(original_rank_dim) - 1).value).concatenate( - result.get_shape()[1:])) - return final_result - - def _prune_invalid_ids(sparse_ids, sparse_weights): """Prune invalid IDs (< 0) from the input ids and weights.""" is_id_valid = math_ops.greater_equal(sparse_ids.values, 0) @@ -4089,10 +4247,14 @@ class IndicatorColumn( sp_ids=id_tensor, sp_values=weight_tensor, vocab_size=int(self._variable_shape[-1])) - # Remove (?, -1) index + # Remove (?, -1) index. weighted_column = sparse_ops.sparse_slice(weighted_column, [0, 0], weighted_column.dense_shape) - return sparse_ops.sparse_tensor_to_dense(weighted_column) + # Use scatter_nd to merge duplicated indices if existed, + # instead of sparse_tensor_to_dense. + return array_ops.scatter_nd(weighted_column.indices, + weighted_column.values, + weighted_column.dense_shape) dense_id_tensor = sparse_ops.sparse_tensor_to_dense( id_tensor, default_value=-1) @@ -4534,7 +4696,10 @@ def deserialize_feature_column(config, 'Expected FeatureColumn class, instead found: {}'.format(cls)) # Always deserialize the FeatureColumn, in order to get the name. - new_instance = cls._from_config(cls_config, columns_by_name=columns_by_name) # pylint: disable=protected-access + new_instance = cls._from_config( # pylint: disable=protected-access + cls_config, + custom_objects=custom_objects, + columns_by_name=columns_by_name) # If the name already exists, re-use the column from columns_by_name, # (new_instance remains unused). diff --git a/tensorflow/python/feature_column/feature_column_v2_test.py b/tensorflow/python/feature_column/feature_column_v2_test.py index a26b860056..0755c0b6ac 100644 --- a/tensorflow/python/feature_column/feature_column_v2_test.py +++ b/tensorflow/python/feature_column/feature_column_v2_test.py @@ -31,7 +31,6 @@ from tensorflow.python import keras from tensorflow.python.client import session from tensorflow.python.eager import backprop from tensorflow.python.eager import context -from tensorflow.python.estimator.inputs import numpy_io from tensorflow.python.feature_column import feature_column as fc_old from tensorflow.python.feature_column import feature_column_v2 as fc from tensorflow.python.framework import constant_op @@ -50,6 +49,7 @@ from tensorflow.python.platform import test from tensorflow.python.training import coordinator from tensorflow.python.training import queue_runner_impl from tensorflow.python.training import rmsprop +from tensorflow_estimator.python.estimator.inputs import numpy_io def _initialized_session(config=None): @@ -218,6 +218,7 @@ class LazyColumnTest(test.TestCase): TypeError, '"key" must be either a "str" or "FeatureColumn".'): transformation_cache.get(NotAFeatureColumn(), None) + @test_util.run_deprecated_v1 def test_expand_dim_rank_1_sparse_tensor_empty_batch(self): # empty 1-D sparse tensor: transformation_cache = fc.FeatureTransformationCache( @@ -228,15 +229,16 @@ class LazyColumnTest(test.TestCase): dense_shape=[0], values=np.array([])) }) - with self.cached_session(): - spv = transformation_cache.get('a', None).eval() - self.assertAllEqual(np.array([0, 1], dtype=np.int64), spv.dense_shape) - self.assertAllEqual( - np.reshape(np.array([], dtype=np.int64), (0, 2)), spv.indices) + + spv = self.evaluate(transformation_cache.get('a', None)) + self.assertAllEqual(np.array([0, 1], dtype=np.int64), spv.dense_shape) + self.assertAllEqual( + np.reshape(np.array([], dtype=np.int64), (0, 2)), spv.indices) class NumericColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): a = fc.numeric_column('aaa') self.assertEqual('aaa', a.key) @@ -315,59 +317,67 @@ class NumericColumnTest(test.TestCase): 'aaa': parsing_ops.FixedLenFeature((2, 3), dtype=dtypes.int32) }, a.parse_example_spec) + @test_util.run_deprecated_v1 def test_parse_example_no_default_value(self): price = fc.numeric_column('price', shape=[2]) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'price': - feature_pb2.Feature(float_list=feature_pb2.FloatList( - value=[20., 110.])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'price': + feature_pb2.Feature( + float_list=feature_pb2.FloatList(value=[20., 110.])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([price])) + features=fc.make_parse_example_spec_v2([price])) self.assertIn('price', features) - with self.cached_session(): - self.assertAllEqual([[20., 110.]], features['price'].eval()) + self.assertAllEqual([[20., 110.]], self.evaluate(features['price'])) + + @test_util.run_deprecated_v1 def test_parse_example_with_default_value(self): price = fc.numeric_column('price', shape=[2], default_value=11.) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'price': - feature_pb2.Feature(float_list=feature_pb2.FloatList( - value=[20., 110.])) - })) - no_data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'something_else': - feature_pb2.Feature(float_list=feature_pb2.FloatList( - value=[20., 110.])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'price': + feature_pb2.Feature( + float_list=feature_pb2.FloatList(value=[20., 110.])) + })) + no_data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'something_else': + feature_pb2.Feature( + float_list=feature_pb2.FloatList(value=[20., 110.])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString(), no_data.SerializeToString()], - features=fc.make_parse_example_spec([price])) + features=fc.make_parse_example_spec_v2([price])) self.assertIn('price', features) - with self.cached_session(): - self.assertAllEqual([[20., 110.], [11., 11.]], features['price'].eval()) + + self.assertAllEqual([[20., 110.], [11., 11.]], + self.evaluate(features['price'])) def test_normalizer_fn_must_be_callable(self): with self.assertRaisesRegexp(TypeError, 'must be a callable'): fc.numeric_column('price', normalizer_fn='NotACallable') + @test_util.run_deprecated_v1 def test_normalizer_fn_transform_feature(self): def _increment_two(input_tensor): return input_tensor + 2. price = fc.numeric_column('price', shape=[2], normalizer_fn=_increment_two) - output = fc._transform_features({ + output = fc._transform_features_v2({ 'price': [[1., 2.], [5., 6.]] }, [price], None) - with self.cached_session(): - self.assertAllEqual([[3., 4.], [7., 8.]], output[price].eval()) + self.assertAllEqual([[3., 4.], [7., 8.]], self.evaluate(output[price])) + + @test_util.run_deprecated_v1 def test_get_dense_tensor(self): def _increment_two(input_tensor): @@ -391,6 +401,7 @@ class NumericColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'must be a Tensor'): price.transform_feature(transformation_cache, None) + @test_util.run_deprecated_v1 def test_deep_copy(self): a = fc.numeric_column('aaa', shape=[1, 2], default_value=[[3., 2.]]) a_copy = copy.deepcopy(a) @@ -403,6 +414,7 @@ class NumericColumnTest(test.TestCase): 'aaa', shape=[1, 2], default_value=np.array([[3., 2.]])) self.assertEqual(a.default_value, ((3., 2.),)) + @test_util.run_deprecated_v1 def test_linear_model(self): price = fc.numeric_column('price') with ops.Graph().as_default(): @@ -411,11 +423,11 @@ class NumericColumnTest(test.TestCase): predictions = model(features) price_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.]], price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.]], self.evaluate(price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price_var.assign([[10.]])) - self.assertAllClose([[10.], [50.]], predictions.eval()) + self.assertAllClose([[10.], [50.]], self.evaluate(predictions)) def test_old_linear_model(self): price = fc.numeric_column('price') @@ -425,12 +437,13 @@ class NumericColumnTest(test.TestCase): bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.]], price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.]], self.evaluate(price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price_var.assign([[10.]])) - self.assertAllClose([[10.], [50.]], predictions.eval()) + self.assertAllClose([[10.], [50.]], self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_serialization(self): def _increment_two(input_tensor): @@ -471,17 +484,17 @@ class BucketizedColumnTest(test.TestCase): def test_invalid_boundaries(self): a = fc.numeric_column('aaa') - with self.assertRaisesRegexp( - ValueError, 'boundaries must be a sorted list'): + with self.assertRaisesRegexp(ValueError, + 'boundaries must be a sorted list'): fc.bucketized_column(a, boundaries=None) - with self.assertRaisesRegexp( - ValueError, 'boundaries must be a sorted list'): + with self.assertRaisesRegexp(ValueError, + 'boundaries must be a sorted list'): fc.bucketized_column(a, boundaries=1.) - with self.assertRaisesRegexp( - ValueError, 'boundaries must be a sorted list'): + with self.assertRaisesRegexp(ValueError, + 'boundaries must be a sorted list'): fc.bucketized_column(a, boundaries=[1, 0]) - with self.assertRaisesRegexp( - ValueError, 'boundaries must be a sorted list'): + with self.assertRaisesRegexp(ValueError, + 'boundaries must be a sorted list'): fc.bucketized_column(a, boundaries=[1, 1]) def test_name(self): @@ -491,7 +504,7 @@ class BucketizedColumnTest(test.TestCase): self.assertEqual('aaa_bucketized', b.name) def test_is_v2_column_old_numeric(self): - a = fc_old.numeric_column('aaa', dtype=dtypes.int32) + a = fc_old._numeric_column('aaa', dtype=dtypes.int32) b = fc.bucketized_column(a, boundaries=[0, 1]) self.assertFalse(b._is_v2_column) self.assertEqual('aaa_bucketized', b.name) @@ -515,32 +528,38 @@ class BucketizedColumnTest(test.TestCase): # Column 'aaa` has shape [2] times three buckets -> num_buckets=6. self.assertEqual(6, b.num_buckets) + @test_util.run_deprecated_v1 def test_parse_example(self): price = fc.numeric_column('price', shape=[2]) bucketized_price = fc.bucketized_column(price, boundaries=[0, 50]) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'price': - feature_pb2.Feature(float_list=feature_pb2.FloatList( - value=[20., 110.])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'price': + feature_pb2.Feature( + float_list=feature_pb2.FloatList(value=[20., 110.])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([bucketized_price])) + features=fc.make_parse_example_spec_v2([bucketized_price])) self.assertIn('price', features) - with self.cached_session(): - self.assertAllEqual([[20., 110.]], features['price'].eval()) + self.assertAllEqual([[20., 110.]], self.evaluate(features['price'])) + + @test_util.run_deprecated_v1 def test_transform_feature(self): price = fc.numeric_column('price', shape=[2]) bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): - transformed_tensor = fc._transform_features({ + transformed_tensor = fc._transform_features_v2({ 'price': [[-1., 1.], [5., 6.]] }, [bucketized_price], None) - with _initialized_session(): - self.assertAllEqual([[0, 1], [3, 4]], - transformed_tensor[bucketized_price].eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual([[0, 1], [3, 4]], + self.evaluate(transformed_tensor[bucketized_price])) def test_get_dense_tensor_one_input_value(self): """Tests _get_dense_tensor() for input with shape=[1].""" @@ -550,16 +569,17 @@ class BucketizedColumnTest(test.TestCase): transformation_cache = fc.FeatureTransformationCache({ 'price': [[-1.], [1.], [5.], [6.]] }) - with _initialized_session(): - bucketized_price_tensor = bucketized_price.get_dense_tensor( - transformation_cache, None) - self.assertAllClose( - # One-hot tensor. - [[[1., 0., 0., 0., 0.]], - [[0., 1., 0., 0., 0.]], - [[0., 0., 0., 1., 0.]], - [[0., 0., 0., 0., 1.]]], - bucketized_price_tensor.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + bucketized_price_tensor = bucketized_price.get_dense_tensor( + transformation_cache, None) + self.assertAllClose( + # One-hot tensor. + [[[1., 0., 0., 0., 0.]], [[0., 1., 0., 0., 0.]], + [[0., 0., 0., 1., 0.]], [[0., 0., 0., 0., 1.]]], + self.evaluate(bucketized_price_tensor)) def test_get_dense_tensor_two_input_values(self): """Tests _get_dense_tensor() for input with shape=[2].""" @@ -569,14 +589,17 @@ class BucketizedColumnTest(test.TestCase): transformation_cache = fc.FeatureTransformationCache({ 'price': [[-1., 1.], [5., 6.]] }) - with _initialized_session(): - bucketized_price_tensor = bucketized_price.get_dense_tensor( - transformation_cache, None) - self.assertAllClose( - # One-hot tensor. - [[[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.]], - [[0., 0., 0., 1., 0.], [0., 0., 0., 0., 1.]]], - bucketized_price_tensor.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + bucketized_price_tensor = bucketized_price.get_dense_tensor( + transformation_cache, None) + self.assertAllClose( + # One-hot tensor. + [[[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.]], + [[0., 0., 0., 1., 0.], [0., 0., 0., 0., 1.]]], + self.evaluate(bucketized_price_tensor)) def test_get_sparse_tensors_one_input_value(self): """Tests _get_sparse_tensors() for input with shape=[1].""" @@ -591,8 +614,8 @@ class BucketizedColumnTest(test.TestCase): transformation_cache, None) self.assertIsNone(id_weight_pair.weight_tensor) id_tensor_value = sess.run(id_weight_pair.id_tensor) - self.assertAllEqual( - [[0, 0], [1, 0], [2, 0], [3, 0]], id_tensor_value.indices) + self.assertAllEqual([[0, 0], [1, 0], [2, 0], [3, 0]], + id_tensor_value.indices) self.assertAllEqual([0, 1, 3, 4], id_tensor_value.values) self.assertAllEqual([4, 1], id_tensor_value.dense_shape) @@ -609,8 +632,8 @@ class BucketizedColumnTest(test.TestCase): transformation_cache, None) self.assertIsNone(id_weight_pair.weight_tensor) id_tensor_value = sess.run(id_weight_pair.id_tensor) - self.assertAllEqual( - [[0, 0], [0, 1], [1, 0], [1, 1]], id_tensor_value.indices) + self.assertAllEqual([[0, 0], [0, 1], [1, 0], [1, 1]], + id_tensor_value.indices) # Values 0-4 correspond to the first column of the input price. # Values 5-9 correspond to the second column of the input price. self.assertAllEqual([0, 6, 3, 9], id_tensor_value.values) @@ -627,6 +650,7 @@ class BucketizedColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'must be a Tensor'): bucketized_price.transform_feature(transformation_cache, None) + @test_util.run_deprecated_v1 def test_deep_copy(self): a = fc.numeric_column('aaa', shape=[2]) a_bucketized = fc.bucketized_column(a, boundaries=[0, 1]) @@ -645,20 +669,23 @@ class BucketizedColumnTest(test.TestCase): predictions = model(features) bucketized_price_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) # One weight variable per bucket, all initialized to zero. - self.assertAllClose( - [[0.], [0.], [0.], [0.], [0.]], bucketized_price_var.eval()) - self.assertAllClose([[0.], [0.], [0.], [0.]], predictions.eval()) - sess.run(bucketized_price_var.assign( - [[10.], [20.], [30.], [40.], [50.]])) + self.assertAllClose([[0.], [0.], [0.], [0.], [0.]], + self.evaluate(bucketized_price_var)) + self.assertAllClose([[0.], [0.], [0.], [0.]], + self.evaluate(predictions)) + sess.run( + bucketized_price_var.assign([[10.], [20.], [30.], [40.], [50.]])) # price -1. is in the 0th bucket, whose weight is 10. # price 1. is in the 1st bucket, whose weight is 20. # price 5. is in the 3rd bucket, whose weight is 40. # price 6. is in the 4th bucket, whose weight is 50. - self.assertAllClose([[10.], [20.], [40.], [50.]], predictions.eval()) + self.assertAllClose([[10.], [20.], [40.], [50.]], + self.evaluate(predictions)) sess.run(bias.assign([1.])) - self.assertAllClose([[11.], [21.], [41.], [51.]], predictions.eval()) + self.assertAllClose([[11.], [21.], [41.], [51.]], + self.evaluate(predictions)) def test_linear_model_two_input_values(self): """Tests linear_model() for input with shape=[2].""" @@ -670,24 +697,24 @@ class BucketizedColumnTest(test.TestCase): predictions = model(features) bucketized_price_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) # One weight per bucket per input column, all initialized to zero. self.assertAllClose( [[0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.]], - bucketized_price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) - sess.run(bucketized_price_var.assign( - [[10.], [20.], [30.], [40.], [50.], - [60.], [70.], [80.], [90.], [100.]])) + self.evaluate(bucketized_price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) + sess.run( + bucketized_price_var.assign([[10.], [20.], [30.], [40.], [50.], + [60.], [70.], [80.], [90.], [100.]])) # 1st example: # price -1. is in the 0th bucket, whose weight is 10. # price 1. is in the 6th bucket, whose weight is 70. # 2nd example: # price 5. is in the 3rd bucket, whose weight is 40. # price 6. is in the 9th bucket, whose weight is 100. - self.assertAllClose([[80.], [140.]], predictions.eval()) + self.assertAllClose([[80.], [140.]], self.evaluate(predictions)) sess.run(bias.assign([1.])) - self.assertAllClose([[81.], [141.]], predictions.eval()) + self.assertAllClose([[81.], [141.]], self.evaluate(predictions)) def test_old_linear_model_one_input_value(self): """Tests linear_model() for input with shape=[1].""" @@ -699,20 +726,23 @@ class BucketizedColumnTest(test.TestCase): bias = get_linear_model_bias() bucketized_price_var = get_linear_model_column_var(bucketized_price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) # One weight variable per bucket, all initialized to zero. self.assertAllClose([[0.], [0.], [0.], [0.], [0.]], - bucketized_price_var.eval()) - self.assertAllClose([[0.], [0.], [0.], [0.]], predictions.eval()) + self.evaluate(bucketized_price_var)) + self.assertAllClose([[0.], [0.], [0.], [0.]], + self.evaluate(predictions)) sess.run( bucketized_price_var.assign([[10.], [20.], [30.], [40.], [50.]])) # price -1. is in the 0th bucket, whose weight is 10. # price 1. is in the 1st bucket, whose weight is 20. # price 5. is in the 3rd bucket, whose weight is 40. # price 6. is in the 4th bucket, whose weight is 50. - self.assertAllClose([[10.], [20.], [40.], [50.]], predictions.eval()) + self.assertAllClose([[10.], [20.], [40.], [50.]], + self.evaluate(predictions)) sess.run(bias.assign([1.])) - self.assertAllClose([[11.], [21.], [41.], [51.]], predictions.eval()) + self.assertAllClose([[11.], [21.], [41.], [51.]], + self.evaluate(predictions)) def test_old_linear_model_two_input_values(self): """Tests linear_model() for input with shape=[2].""" @@ -724,12 +754,12 @@ class BucketizedColumnTest(test.TestCase): bias = get_linear_model_bias() bucketized_price_var = get_linear_model_column_var(bucketized_price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) # One weight per bucket per input column, all initialized to zero. self.assertAllClose( [[0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.], [0.]], - bucketized_price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.evaluate(bucketized_price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run( bucketized_price_var.assign([[10.], [20.], [30.], [40.], [50.], [60.], [70.], [80.], [90.], [100.]])) @@ -739,13 +769,13 @@ class BucketizedColumnTest(test.TestCase): # 2nd example: # price 5. is in the 3rd bucket, whose weight is 40. # price 6. is in the 9th bucket, whose weight is 100. - self.assertAllClose([[80.], [140.]], predictions.eval()) + self.assertAllClose([[80.], [140.]], self.evaluate(predictions)) sess.run(bias.assign([1.])) - self.assertAllClose([[81.], [141.]], predictions.eval()) + self.assertAllClose([[81.], [141.]], self.evaluate(predictions)) def test_old_linear_model_one_input_value_old_numeric(self): """Tests linear_model() for input with shape=[1].""" - price = fc_old.numeric_column('price', shape=[1]) + price = fc_old._numeric_column('price', shape=[1]) bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) with ops.Graph().as_default(): features = {'price': [[-1.], [1.], [5.], [6.]]} @@ -753,21 +783,25 @@ class BucketizedColumnTest(test.TestCase): bias = get_linear_model_bias() bucketized_price_var = get_linear_model_column_var(bucketized_price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) # One weight variable per bucket, all initialized to zero. self.assertAllClose([[0.], [0.], [0.], [0.], [0.]], - bucketized_price_var.eval()) - self.assertAllClose([[0.], [0.], [0.], [0.]], predictions.eval()) + self.evaluate(bucketized_price_var)) + self.assertAllClose([[0.], [0.], [0.], [0.]], + self.evaluate(predictions)) sess.run( bucketized_price_var.assign([[10.], [20.], [30.], [40.], [50.]])) # price -1. is in the 0th bucket, whose weight is 10. # price 1. is in the 1st bucket, whose weight is 20. # price 5. is in the 3rd bucket, whose weight is 40. # price 6. is in the 4th bucket, whose weight is 50. - self.assertAllClose([[10.], [20.], [40.], [50.]], predictions.eval()) + self.assertAllClose([[10.], [20.], [40.], [50.]], + self.evaluate(predictions)) sess.run(bias.assign([1.])) - self.assertAllClose([[11.], [21.], [41.], [51.]], predictions.eval()) + self.assertAllClose([[11.], [21.], [41.], [51.]], + self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_serialization(self): price = fc.numeric_column('price', shape=[2]) bucketized_price = fc.bucketized_column(price, boundaries=[0, 2, 4, 6]) @@ -800,6 +834,7 @@ class BucketizedColumnTest(test.TestCase): class HashedCategoricalColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): a = fc.categorical_column_with_hash_bucket('aaa', 10) self.assertEqual('aaa', a.name) @@ -827,6 +862,7 @@ class HashedCategoricalColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'dtype must be string or integer'): fc.categorical_column_with_hash_bucket('aaa', 10, dtype=dtypes.float32) + @test_util.run_deprecated_v1 def test_deep_copy(self): original = fc.categorical_column_with_hash_bucket('aaa', 10) for column in (original, copy.deepcopy(original)): @@ -847,45 +883,50 @@ class HashedCategoricalColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int32) }, a.parse_example_spec) + @test_util.run_deprecated_v1 def test_parse_example(self): a = fc.categorical_column_with_hash_bucket('aaa', 10) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'aaa': - feature_pb2.Feature(bytes_list=feature_pb2.BytesList( - value=[b'omar', b'stringer'])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'aaa': + feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[b'omar', b'stringer'])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([a])) + features=fc.make_parse_example_spec_v2([a])) self.assertIn('aaa', features) - with self.cached_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([b'omar', b'stringer'], dtype=np.object_), - dense_shape=[1, 2]), - features['aaa'].eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([b'omar', b'stringer'], dtype=np.object_), + dense_shape=[1, 2]), self.evaluate(features['aaa'])) + + @test_util.run_deprecated_v1 def test_strings_should_be_hashed(self): hashed_sparse = fc.categorical_column_with_hash_bucket('wire', 10) wire_tensor = sparse_tensor.SparseTensor( values=['omar', 'stringer', 'marlo'], indices=[[0, 0], [1, 0], [1, 1]], dense_shape=[2, 2]) - outputs = fc._transform_features({ + outputs = fc._transform_features_v2({ 'wire': wire_tensor }, [hashed_sparse], None) output = outputs[hashed_sparse] # Check exact hashed output. If hashing changes this test will break. expected_values = [6, 4, 1] - with self.cached_session(): - self.assertEqual(dtypes.int64, output.values.dtype) - self.assertAllEqual(expected_values, output.values.eval()) - self.assertAllEqual(wire_tensor.indices.eval(), output.indices.eval()) - self.assertAllEqual(wire_tensor.dense_shape.eval(), - output.dense_shape.eval()) + + self.assertEqual(dtypes.int64, output.values.dtype) + self.assertAllEqual(expected_values, self.evaluate(output.values)) + self.assertAllEqual( + self.evaluate(wire_tensor.indices), self.evaluate(output.indices)) + self.assertAllEqual( + self.evaluate(wire_tensor.dense_shape), + self.evaluate(output.dense_shape)) def test_tensor_dtype_should_be_string_or_integer(self): string_fc = fc.categorical_column_with_hash_bucket( @@ -895,17 +936,11 @@ class HashedCategoricalColumnTest(test.TestCase): float_fc = fc.categorical_column_with_hash_bucket( 'a_float', 10, dtype=dtypes.string) int_tensor = sparse_tensor.SparseTensor( - values=[101], - indices=[[0, 0]], - dense_shape=[1, 1]) + values=[101], indices=[[0, 0]], dense_shape=[1, 1]) string_tensor = sparse_tensor.SparseTensor( - values=['101'], - indices=[[0, 0]], - dense_shape=[1, 1]) + values=['101'], indices=[[0, 0]], dense_shape=[1, 1]) float_tensor = sparse_tensor.SparseTensor( - values=[101.], - indices=[[0, 0]], - dense_shape=[1, 1]) + values=[101.], indices=[[0, 0]], dense_shape=[1, 1]) transformation_cache = fc.FeatureTransformationCache({ 'a_int': int_tensor, 'a_string': string_tensor, @@ -925,6 +960,7 @@ class HashedCategoricalColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'dtype must be compatible'): transformation_cache.get(hashed_sparse, None) + @test_util.run_deprecated_v1 def test_ints_should_be_hashed(self): hashed_sparse = fc.categorical_column_with_hash_bucket( 'wire', 10, dtype=dtypes.int64) @@ -936,9 +972,10 @@ class HashedCategoricalColumnTest(test.TestCase): output = transformation_cache.get(hashed_sparse, None) # Check exact hashed output. If hashing changes this test will break. expected_values = [3, 7, 5] - with self.cached_session(): - self.assertAllEqual(expected_values, output.values.eval()) + self.assertAllEqual(expected_values, self.evaluate(output.values)) + + @test_util.run_deprecated_v1 def test_int32_64_is_compatible(self): hashed_sparse = fc.categorical_column_with_hash_bucket( 'wire', 10, dtype=dtypes.int64) @@ -950,9 +987,10 @@ class HashedCategoricalColumnTest(test.TestCase): output = transformation_cache.get(hashed_sparse, None) # Check exact hashed output. If hashing changes this test will break. expected_values = [3, 7, 5] - with self.cached_session(): - self.assertAllEqual(expected_values, output.values.eval()) + self.assertAllEqual(expected_values, self.evaluate(output.values)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): hashed_sparse = fc.categorical_column_with_hash_bucket('wire', 10) transformation_cache = fc.FeatureTransformationCache({ @@ -968,6 +1006,7 @@ class HashedCategoricalColumnTest(test.TestCase): self.assertEqual( transformation_cache.get(hashed_sparse, None), id_weight_pair.id_tensor) + @test_util.run_deprecated_v1 def test_get_sparse_tensors_dense_input(self): hashed_sparse = fc.categorical_column_with_hash_bucket('wire', 10) transformation_cache = fc.FeatureTransformationCache({ @@ -979,6 +1018,7 @@ class HashedCategoricalColumnTest(test.TestCase): self.assertEqual( transformation_cache.get(hashed_sparse, None), id_weight_pair.id_tensor) + @test_util.run_deprecated_v1 def test_linear_model(self): wire_column = fc.categorical_column_with_hash_bucket('wire', 4) self.assertEqual(4, wire_column.num_buckets) @@ -992,14 +1032,17 @@ class HashedCategoricalColumnTest(test.TestCase): dense_shape=(2, 2)) }) wire_var, bias = model.variables - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() - # 'marlo' -> 3: wire_var[3] = 4 - # 'skywalker' -> 2, 'omar' -> 2: wire_var[2] + wire_var[2] = 3+3 = 6 - self.assertAllClose(((4.,), (6.,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(wire_var.assign(((1.,), (2.,), (3.,), (4.,)))) + # 'marlo' -> 3: wire_var[3] = 4 + # 'skywalker' -> 2, 'omar' -> 2: wire_var[2] + wire_var[2] = 3+3 = 6 + self.assertAllClose(((4.,), (6.,)), self.evaluate(predictions)) def test_old_linear_model(self): wire_column = fc.categorical_column_with_hash_bucket('wire', 4) @@ -1014,15 +1057,19 @@ class HashedCategoricalColumnTest(test.TestCase): }, (wire_column,)) bias = get_linear_model_bias() wire_var = get_linear_model_column_var(wire_column) - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() - # 'marlo' -> 3: wire_var[3] = 4 - # 'skywalker' -> 2, 'omar' -> 2: wire_var[2] + wire_var[2] = 3+3 = 6 - self.assertAllClose(((4.,), (6.,)), predictions.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(wire_var.assign(((1.,), (2.,), (3.,), (4.,)))) + # 'marlo' -> 3: wire_var[3] = 4 + # 'skywalker' -> 2, 'omar' -> 2: wire_var[2] + wire_var[2] = 3+3 = 6 + self.assertAllClose(((4.,), (6.,)), self.evaluate(predictions)) + + @test_util.run_deprecated_v1 def test_serialization(self): wire_column = fc.categorical_column_with_hash_bucket('wire', 4) self.assertEqual(['wire'], wire_column.parents) @@ -1041,13 +1088,13 @@ class HashedCategoricalColumnTest(test.TestCase): class CrossedColumnTest(test.TestCase): def test_keys_empty(self): - with self.assertRaisesRegexp( - ValueError, 'keys must be a list with length > 1'): + with self.assertRaisesRegexp(ValueError, + 'keys must be a list with length > 1'): fc.crossed_column([], 10) def test_keys_length_one(self): - with self.assertRaisesRegexp( - ValueError, 'keys must be a list with length > 1'): + with self.assertRaisesRegexp(ValueError, + 'keys must be a list with length > 1'): fc.crossed_column(['a'], 10) def test_key_type_unsupported(self): @@ -1060,18 +1107,15 @@ class CrossedColumnTest(test.TestCase): ['a', fc.categorical_column_with_hash_bucket('c', 10)], 10) def test_hash_bucket_size_negative(self): - with self.assertRaisesRegexp( - ValueError, 'hash_bucket_size must be > 1'): + with self.assertRaisesRegexp(ValueError, 'hash_bucket_size must be > 1'): fc.crossed_column(['a', 'c'], -1) def test_hash_bucket_size_zero(self): - with self.assertRaisesRegexp( - ValueError, 'hash_bucket_size must be > 1'): + with self.assertRaisesRegexp(ValueError, 'hash_bucket_size must be > 1'): fc.crossed_column(['a', 'c'], 0) def test_hash_bucket_size_none(self): - with self.assertRaisesRegexp( - ValueError, 'hash_bucket_size must be > 1'): + with self.assertRaisesRegexp(ValueError, 'hash_bucket_size must be > 1'): fc.crossed_column(['a', 'c'], None) def test_name(self): @@ -1085,7 +1129,7 @@ class CrossedColumnTest(test.TestCase): self.assertEqual('a_bucketized_X_c_X_d1_X_d2', crossed2.name) def test_is_v2_column(self): - a = fc_old.numeric_column('a', dtype=dtypes.int32) + a = fc_old._numeric_column('a', dtype=dtypes.int32) b = fc.bucketized_column(a, boundaries=[0, 1]) crossed1 = fc.crossed_column(['d1', 'd2'], 10) self.assertTrue(crossed1._is_v2_column) @@ -1127,65 +1171,76 @@ class CrossedColumnTest(test.TestCase): crossed = fc.crossed_column([b, 'c'], 15) self.assertEqual(15, crossed.num_buckets) + @test_util.run_deprecated_v1 def test_deep_copy(self): a = fc.numeric_column('a', dtype=dtypes.int32) b = fc.bucketized_column(a, boundaries=[0, 1]) crossed1 = fc.crossed_column(['d1', 'd2'], 10) crossed2 = fc.crossed_column([b, 'c', crossed1], 15, hash_key=5) crossed2_copy = copy.deepcopy(crossed2) - self.assertEqual('a_bucketized_X_c_X_d1_X_d2', crossed2_copy.name,) + self.assertEqual( + 'a_bucketized_X_c_X_d1_X_d2', + crossed2_copy.name, + ) self.assertEqual(15, crossed2_copy.hash_bucket_size) self.assertEqual(5, crossed2_copy.hash_key) + @test_util.run_deprecated_v1 def test_parse_example(self): price = fc.numeric_column('price', shape=[2]) bucketized_price = fc.bucketized_column(price, boundaries=[0, 50]) price_cross_wire = fc.crossed_column([bucketized_price, 'wire'], 10) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'price': - feature_pb2.Feature(float_list=feature_pb2.FloatList( - value=[20., 110.])), - 'wire': - feature_pb2.Feature(bytes_list=feature_pb2.BytesList( - value=[b'omar', b'stringer'])), - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'price': + feature_pb2.Feature( + float_list=feature_pb2.FloatList(value=[20., 110.])), + 'wire': + feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[b'omar', b'stringer'])), + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([price_cross_wire])) + features=fc.make_parse_example_spec_v2([price_cross_wire])) self.assertIn('price', features) self.assertIn('wire', features) - with self.cached_session(): - self.assertAllEqual([[20., 110.]], features['price'].eval()) - wire_sparse = features['wire'] - self.assertAllEqual([[0, 0], [0, 1]], wire_sparse.indices.eval()) - # Use byte constants to pass the open-source test. - self.assertAllEqual([b'omar', b'stringer'], wire_sparse.values.eval()) - self.assertAllEqual([1, 2], wire_sparse.dense_shape.eval()) + self.assertAllEqual([[20., 110.]], self.evaluate(features['price'])) + wire_sparse = features['wire'] + self.assertAllEqual([[0, 0], [0, 1]], self.evaluate(wire_sparse.indices)) + # Use byte constants to pass the open-source test. + self.assertAllEqual([b'omar', b'stringer'], + self.evaluate(wire_sparse.values)) + self.assertAllEqual([1, 2], self.evaluate(wire_sparse.dense_shape)) + + @test_util.run_deprecated_v1 def test_transform_feature(self): price = fc.numeric_column('price', shape=[2]) bucketized_price = fc.bucketized_column(price, boundaries=[0, 50]) hash_bucket_size = 10 - price_cross_wire = fc.crossed_column( - [bucketized_price, 'wire'], hash_bucket_size) + price_cross_wire = fc.crossed_column([bucketized_price, 'wire'], + hash_bucket_size) features = { - 'price': constant_op.constant([[1., 2.], [5., 6.]]), - 'wire': sparse_tensor.SparseTensor( - values=['omar', 'stringer', 'marlo'], - indices=[[0, 0], [1, 0], [1, 1]], - dense_shape=[2, 2]), + 'price': + constant_op.constant([[1., 2.], [5., 6.]]), + 'wire': + sparse_tensor.SparseTensor( + values=['omar', 'stringer', 'marlo'], + indices=[[0, 0], [1, 0], [1, 1]], + dense_shape=[2, 2]), } - outputs = fc._transform_features(features, [price_cross_wire], None) + outputs = fc._transform_features_v2(features, [price_cross_wire], None) output = outputs[price_cross_wire] - with self.cached_session() as sess: - output_val = sess.run(output) - self.assertAllEqual( - [[0, 0], [0, 1], [1, 0], [1, 1], [1, 2], [1, 3]], output_val.indices) - for val in output_val.values: - self.assertIn(val, list(range(hash_bucket_size))) - self.assertAllEqual([2, 4], output_val.dense_shape) - + output_val = self.evaluate(output) + self.assertAllEqual([[0, 0], [0, 1], [1, 0], [1, 1], [1, 2], [1, 3]], + output_val.indices) + for val in output_val.values: + self.assertIn(val, list(range(hash_bucket_size))) + self.assertAllEqual([2, 4], output_val.dense_shape) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): a = fc.numeric_column('a', dtype=dtypes.int32, shape=(2,)) b = fc.bucketized_column(a, boundaries=(0, 1)) @@ -1212,19 +1267,21 @@ class CrossedColumnTest(test.TestCase): dense_shape=(2, 2)), }) id_weight_pair = crossed2.get_sparse_tensors(transformation_cache, None) - with _initialized_session(): - id_tensor_eval = id_weight_pair.id_tensor.eval() - self.assertAllEqual( - ((0, 0), (0, 1), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), - (1, 6), (1, 7), (1, 8), (1, 9), (1, 10), (1, 11), (1, 12), (1, 13), - (1, 14), (1, 15)), - id_tensor_eval.indices) - # Check exact hashed output. If hashing changes this test will break. - # All values are within [0, hash_bucket_size). - expected_values = ( - 6, 14, 0, 13, 8, 8, 10, 12, 2, 0, 1, 9, 8, 12, 2, 0, 10, 11) - self.assertAllEqual(expected_values, id_tensor_eval.values) - self.assertAllEqual((2, 16), id_tensor_eval.dense_shape) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + id_tensor_eval = self.evaluate(id_weight_pair.id_tensor) + self.assertAllEqual( + ((0, 0), (0, 1), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (1, 5), + (1, 6), (1, 7), (1, 8), (1, 9), (1, 10), (1, 11), (1, 12), (1, 13), + (1, 14), (1, 15)), id_tensor_eval.indices) + # Check exact hashed output. If hashing changes this test will break. + # All values are within [0, hash_bucket_size). + expected_values = (6, 14, 0, 13, 8, 8, 10, 12, 2, 0, 1, 9, 8, 12, 2, 0, + 10, 11) + self.assertAllEqual(expected_values, id_tensor_eval.values) + self.assertAllEqual((2, 16), id_tensor_eval.dense_shape) def test_get_sparse_tensors_simple(self): """Same as test_get_sparse_tensors, but with simpler values.""" @@ -1242,17 +1299,20 @@ class CrossedColumnTest(test.TestCase): dense_shape=(2, 2)), }) id_weight_pair = crossed.get_sparse_tensors(transformation_cache, None) - with _initialized_session(): - id_tensor_eval = id_weight_pair.id_tensor.eval() - self.assertAllEqual( - ((0, 0), (0, 1), (1, 0), (1, 1), (1, 2), (1, 3)), - id_tensor_eval.indices) - # Check exact hashed output. If hashing changes this test will break. - # All values are within [0, hash_bucket_size). - expected_values = (1, 0, 1, 3, 4, 2) - self.assertAllEqual(expected_values, id_tensor_eval.values) - self.assertAllEqual((2, 4), id_tensor_eval.dense_shape) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + id_tensor_eval = self.evaluate(id_weight_pair.id_tensor) + self.assertAllEqual(((0, 0), (0, 1), (1, 0), (1, 1), (1, 2), (1, 3)), + id_tensor_eval.indices) + # Check exact hashed output. If hashing changes this test will break. + # All values are within [0, hash_bucket_size). + expected_values = (1, 0, 1, 3, 4, 2) + self.assertAllEqual(expected_values, id_tensor_eval.values) + self.assertAllEqual((2, 4), id_tensor_eval.dense_shape) + + @test_util.run_deprecated_v1 def test_linear_model(self): """Tests linear_model. @@ -1274,15 +1334,15 @@ class CrossedColumnTest(test.TestCase): }) crossed_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose( - ((0.,), (0.,), (0.,), (0.,), (0.,)), crossed_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,), (0.,)), + self.evaluate(crossed_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) sess.run(crossed_var.assign(((1.,), (2.,), (3.,), (4.,), (5.,)))) # Expected ids after cross = (1, 0, 1, 3, 4, 2) - self.assertAllClose(((3.,), (14.,)), predictions.eval()) + self.assertAllClose(((3.,), (14.,)), self.evaluate(predictions)) sess.run(bias.assign((.1,))) - self.assertAllClose(((3.1,), (14.1,)), predictions.eval()) + self.assertAllClose(((3.1,), (14.1,)), self.evaluate(predictions)) def test_linear_model_with_weights(self): @@ -1301,10 +1361,11 @@ class CrossedColumnTest(test.TestCase): @property def parse_example_spec(self): return { - self.name: parsing_ops.VarLenFeature(dtypes.int32), - '{}_weights'.format(self.name): parsing_ops.VarLenFeature( - dtypes.float32), - } + self.name: + parsing_ops.VarLenFeature(dtypes.int32), + '{}_weights'.format(self.name): + parsing_ops.VarLenFeature(dtypes.float32), + } @property def num_buckets(self): @@ -1367,15 +1428,15 @@ class CrossedColumnTest(test.TestCase): bias = get_linear_model_bias() crossed_var = get_linear_model_column_var(crossed) with _initialized_session() as sess: - self.assertAllClose((0.,), bias.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) self.assertAllClose(((0.,), (0.,), (0.,), (0.,), (0.,)), - crossed_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.evaluate(crossed_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) sess.run(crossed_var.assign(((1.,), (2.,), (3.,), (4.,), (5.,)))) # Expected ids after cross = (1, 0, 1, 3, 4, 2) - self.assertAllClose(((3.,), (14.,)), predictions.eval()) + self.assertAllClose(((3.,), (14.,)), self.evaluate(predictions)) sess.run(bias.assign((.1,))) - self.assertAllClose(((3.1,), (14.1,)), predictions.eval()) + self.assertAllClose(((3.1,), (14.1,)), self.evaluate(predictions)) def test_old_linear_model_with_weights(self): @@ -1461,7 +1522,7 @@ class CrossedColumnTest(test.TestCase): Uses data from test_get_sparse_tesnsors_simple. """ - a = fc_old.numeric_column('a', dtype=dtypes.int32, shape=(2,)) + a = fc_old._numeric_column('a', dtype=dtypes.int32, shape=(2,)) b = fc.bucketized_column(a, boundaries=(0, 1)) crossed = fc.crossed_column([b, 'c'], hash_bucket_size=5, hash_key=5) with ops.Graph().as_default(): @@ -1477,16 +1538,17 @@ class CrossedColumnTest(test.TestCase): bias = get_linear_model_bias() crossed_var = get_linear_model_column_var(crossed) with _initialized_session() as sess: - self.assertAllClose((0.,), bias.eval()) + self.assertAllClose((0.,), self.evaluate(bias)) self.assertAllClose(((0.,), (0.,), (0.,), (0.,), (0.,)), - crossed_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) + self.evaluate(crossed_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) sess.run(crossed_var.assign(((1.,), (2.,), (3.,), (4.,), (5.,)))) # Expected ids after cross = (1, 0, 1, 3, 4, 2) - self.assertAllClose(((3.,), (14.,)), predictions.eval()) + self.assertAllClose(((3.,), (14.,)), self.evaluate(predictions)) sess.run(bias.assign((.1,))) - self.assertAllClose(((3.1,), (14.1,)), predictions.eval()) + self.assertAllClose(((3.1,), (14.1,)), self.evaluate(predictions)) + @test_util.run_deprecated_v1 def test_serialization(self): a = fc.numeric_column('a', dtype=dtypes.int32, shape=(2,)) b = fc.bucketized_column(a, boundaries=(0, 1)) @@ -1528,7 +1590,6 @@ class CrossedColumnTest(test.TestCase): self.assertIs(b, new_crossed.keys[0]) - class LinearModelTest(test.TestCase): def test_raises_if_empty_feature_columns(self): @@ -1581,7 +1642,7 @@ class LinearModelTest(test.TestCase): features = [[1.], [5.]] model = fc.LinearModel([price]) with self.assertRaisesRegexp(ValueError, 'We expected a dictionary here'): - predictions = model(features) + model(features) def test_dense_bias(self): price = fc.numeric_column('price') @@ -1591,10 +1652,10 @@ class LinearModelTest(test.TestCase): predictions = model(features) price_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) sess.run(price_var.assign([[10.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[15.], [55.]], predictions.eval()) + self.assertAllClose([[15.], [55.]], self.evaluate(predictions)) def test_sparse_bias(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -1608,11 +1669,12 @@ class LinearModelTest(test.TestCase): predictions = model(features) wire_cast_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.], [0.], [0.]], wire_cast_var.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.], [0.], [0.]], + self.evaluate(wire_cast_var)) sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [10015.]], predictions.eval()) + self.assertAllClose([[1005.], [10015.]], self.evaluate(predictions)) def test_dense_and_sparse_bias(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -1630,7 +1692,7 @@ class LinearModelTest(test.TestCase): sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) sess.run(price_var.assign([[10.]])) - self.assertAllClose([[1015.], [10065.]], predictions.eval()) + self.assertAllClose([[1015.], [10065.]], self.evaluate(predictions)) def test_dense_and_sparse_column(self): """When the column is both dense and sparse, uses sparse tensors.""" @@ -1682,10 +1744,11 @@ class LinearModelTest(test.TestCase): predictions = model(features) dense_and_sparse_column_var, bias = model.variables with _initialized_session() as sess: - sess.run(dense_and_sparse_column_var.assign( - [[10.], [100.], [1000.], [10000.]])) + sess.run( + dense_and_sparse_column_var.assign([[10.], [100.], [1000.], + [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [10015.]], predictions.eval()) + self.assertAllClose([[1005.], [10015.]], self.evaluate(predictions)) def test_dense_multi_output(self): price = fc.numeric_column('price') @@ -1695,12 +1758,12 @@ class LinearModelTest(test.TestCase): predictions = model(features) price_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((1, 3)), price_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((1, 3)), self.evaluate(price_var)) sess.run(price_var.assign([[10., 100., 1000.]])) sess.run(bias.assign([5., 6., 7.])) self.assertAllClose([[15., 106., 1007.], [55., 506., 5007.]], - predictions.eval()) + self.evaluate(predictions)) def test_sparse_multi_output(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -1714,15 +1777,15 @@ class LinearModelTest(test.TestCase): predictions = model(features) wire_cast_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((4, 3)), wire_cast_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((4, 3)), self.evaluate(wire_cast_var)) sess.run( - wire_cast_var.assign([[10., 11., 12.], [100., 110., 120.], [ - 1000., 1100., 1200. - ], [10000., 11000., 12000.]])) + wire_cast_var.assign([[10., 11., 12.], [100., 110., 120.], + [1000., 1100., 1200.], + [10000., 11000., 12000.]])) sess.run(bias.assign([5., 6., 7.])) self.assertAllClose([[1005., 1106., 1207.], [10015., 11017., 12019.]], - predictions.eval()) + self.evaluate(predictions)) def test_dense_multi_dimension(self): price = fc.numeric_column('price', shape=2) @@ -1732,9 +1795,9 @@ class LinearModelTest(test.TestCase): predictions = model(features) price_var, _ = model.variables with _initialized_session() as sess: - self.assertAllClose([[0.], [0.]], price_var.eval()) + self.assertAllClose([[0.], [0.]], self.evaluate(price_var)) sess.run(price_var.assign([[10.], [100.]])) - self.assertAllClose([[210.], [650.]], predictions.eval()) + self.assertAllClose([[210.], [650.]], self.evaluate(predictions)) def test_sparse_multi_rank(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -1749,7 +1812,7 @@ class LinearModelTest(test.TestCase): predictions = model(features) wire_cast_var, _ = model.variables with _initialized_session() as sess: - self.assertAllClose(np.zeros((4, 1)), wire_cast_var.eval()) + self.assertAllClose(np.zeros((4, 1)), self.evaluate(wire_cast_var)) self.assertAllClose( np.zeros((2, 1)), predictions.eval(feed_dict={wire_tensor: wire_value})) @@ -1772,7 +1835,7 @@ class LinearModelTest(test.TestCase): with _initialized_session() as sess: sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [5010.]], predictions.eval()) + self.assertAllClose([[1005.], [5010.]], self.evaluate(predictions)) def test_sparse_combiner_with_negative_weights(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -1793,7 +1856,7 @@ class LinearModelTest(test.TestCase): with _initialized_session() as sess: sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [-9985.]], predictions.eval()) + self.assertAllClose([[1005.], [-9985.]], self.evaluate(predictions)) def test_dense_multi_dimension_multi_output(self): price = fc.numeric_column('price', shape=2) @@ -1803,12 +1866,12 @@ class LinearModelTest(test.TestCase): predictions = model(features) price_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((2, 3)), price_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((2, 3)), self.evaluate(price_var)) sess.run(price_var.assign([[1., 2., 3.], [10., 100., 1000.]])) sess.run(bias.assign([2., 3., 4.])) self.assertAllClose([[23., 205., 2007.], [67., 613., 6019.]], - predictions.eval()) + self.evaluate(predictions)) def test_raises_if_shape_mismatch(self): price = fc.numeric_column('price', shape=2) @@ -1828,32 +1891,29 @@ class LinearModelTest(test.TestCase): predictions = model(features) price_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.]], price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.]], self.evaluate(price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price_var.assign([[10.], [100.]])) - self.assertAllClose([[210.], [650.]], predictions.eval()) + self.assertAllClose([[210.], [650.]], self.evaluate(predictions)) def test_dense_multi_column(self): price1 = fc.numeric_column('price1', shape=2) price2 = fc.numeric_column('price2') with ops.Graph().as_default(): - features = { - 'price1': [[1., 2.], [5., 6.]], - 'price2': [[3.], [4.]] - } + features = {'price1': [[1., 2.], [5., 6.]], 'price2': [[3.], [4.]]} model = fc.LinearModel([price1, price2]) predictions = model(features) price1_var, price2_var, bias = model.variables with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.]], price1_var.eval()) - self.assertAllClose([[0.]], price2_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.]], self.evaluate(price1_var)) + self.assertAllClose([[0.]], self.evaluate(price2_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price1_var.assign([[10.], [100.]])) sess.run(price2_var.assign([[1000.]])) sess.run(bias.assign([7.])) - self.assertAllClose([[3217.], [4657.]], predictions.eval()) + self.assertAllClose([[3217.], [4657.]], self.evaluate(predictions)) def test_dense_trainable_default(self): price = fc.numeric_column('price') @@ -2046,6 +2106,7 @@ class LinearModelTest(test.TestCase): features['price2']: [[1.], [5.]], }) + @test_util.run_deprecated_v1 def test_with_numpy_input_fn(self): price = fc.numeric_column('price') price_buckets = fc.bucketized_column( @@ -2078,11 +2139,13 @@ class LinearModelTest(test.TestCase): sess.run(body_style_var.assign([[-10.], [-100.], [-1000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[10 - 1000 + 5.], [100 - 10 + 5.]], sess.run(net)) + self.assertAllClose([[10 - 1000 + 5.], [100 - 10 + 5.]], + self.evaluate(net)) coord.request_stop() coord.join(threads) + @test_util.run_deprecated_v1 def test_with_1d_sparse_tensor(self): price = fc.numeric_column('price') price_buckets = fc.bucketized_column( @@ -2096,11 +2159,16 @@ class LinearModelTest(test.TestCase): # Provides 1-dim tensor and dense tensor. features = { - 'price': constant_op.constant([-1., 12.,]), - 'body-style': sparse_tensor.SparseTensor( - indices=((0,), (1,)), - values=('sedan', 'hardtop'), - dense_shape=(2,)), + 'price': + constant_op.constant([ + -1., + 12., + ]), + 'body-style': + sparse_tensor.SparseTensor( + indices=((0,), (1,)), + values=('sedan', 'hardtop'), + dense_shape=(2,)), } self.assertEqual(1, features['price'].shape.ndims) self.assertEqual(1, features['body-style'].dense_shape.get_shape()[0]) @@ -2114,8 +2182,10 @@ class LinearModelTest(test.TestCase): sess.run(body_style_var.assign([[-10.], [-100.], [-1000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[10 - 1000 + 5.], [1000 - 10 + 5.]], sess.run(net)) + self.assertAllClose([[10 - 1000 + 5.], [1000 - 10 + 5.]], + self.evaluate(net)) + @test_util.run_deprecated_v1 def test_with_1d_unknown_shape_sparse_tensor(self): price = fc.numeric_column('price') price_buckets = fc.bucketized_column( @@ -2140,9 +2210,7 @@ class LinearModelTest(test.TestCase): price_data = np.array([-1., 12.]) body_style_data = sparse_tensor.SparseTensorValue( - indices=((0,), (1,)), - values=('sedan', 'hardtop'), - dense_shape=(2,)) + indices=((0,), (1,)), values=('sedan', 'hardtop'), dense_shape=(2,)) country_data = np.array(['US', 'CA']) model = fc.LinearModel([price_buckets, body_style, country]) @@ -2162,6 +2230,7 @@ class LinearModelTest(test.TestCase): features['country']: country_data })) + @test_util.run_deprecated_v1 def test_with_rank_0_feature(self): price = fc.numeric_column('price') features = { @@ -2197,14 +2266,14 @@ class LinearModelTest(test.TestCase): price_var1, bias1 = model1.variables price_var2, bias2 = model2.variables with _initialized_session() as sess: - self.assertAllClose([0.], bias1.eval()) + self.assertAllClose([0.], self.evaluate(bias1)) sess.run(price_var1.assign([[10.]])) sess.run(bias1.assign([5.])) - self.assertAllClose([[15.], [55.]], predictions1.eval()) - self.assertAllClose([0.], bias2.eval()) + self.assertAllClose([[15.], [55.]], self.evaluate(predictions1)) + self.assertAllClose([0.], self.evaluate(bias2)) sess.run(price_var2.assign([[10.]])) sess.run(bias2.assign([5.])) - self.assertAllClose([[25.], [105.]], predictions2.eval()) + self.assertAllClose([[25.], [105.]], self.evaluate(predictions2)) class OldLinearModelTest(test.TestCase): @@ -2272,10 +2341,10 @@ class OldLinearModelTest(test.TestCase): bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) + self.assertAllClose([0.], self.evaluate(bias)) sess.run(price_var.assign([[10.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[15.], [55.]], predictions.eval()) + self.assertAllClose([[15.], [55.]], self.evaluate(predictions)) def test_sparse_bias(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -2289,11 +2358,12 @@ class OldLinearModelTest(test.TestCase): bias = get_linear_model_bias() wire_cast_var = get_linear_model_column_var(wire_cast) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.], [0.], [0.]], wire_cast_var.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.], [0.], [0.]], + self.evaluate(wire_cast_var)) sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [10015.]], predictions.eval()) + self.assertAllClose([[1005.], [10015.]], self.evaluate(predictions)) def test_dense_and_sparse_bias(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -2312,7 +2382,7 @@ class OldLinearModelTest(test.TestCase): sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) sess.run(price_var.assign([[10.]])) - self.assertAllClose([[1015.], [10065.]], predictions.eval()) + self.assertAllClose([[1015.], [10065.]], self.evaluate(predictions)) def test_dense_and_sparse_column(self): """When the column is both dense and sparse, uses sparse tensors.""" @@ -2394,7 +2464,7 @@ class OldLinearModelTest(test.TestCase): dense_and_sparse_column_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [10015.]], predictions.eval()) + self.assertAllClose([[1005.], [10015.]], self.evaluate(predictions)) def test_dense_multi_output(self): price = fc.numeric_column('price') @@ -2404,12 +2474,12 @@ class OldLinearModelTest(test.TestCase): bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((1, 3)), price_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((1, 3)), self.evaluate(price_var)) sess.run(price_var.assign([[10., 100., 1000.]])) sess.run(bias.assign([5., 6., 7.])) self.assertAllClose([[15., 106., 1007.], [55., 506., 5007.]], - predictions.eval()) + self.evaluate(predictions)) def test_sparse_multi_output(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -2423,15 +2493,15 @@ class OldLinearModelTest(test.TestCase): bias = get_linear_model_bias() wire_cast_var = get_linear_model_column_var(wire_cast) with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((4, 3)), wire_cast_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((4, 3)), self.evaluate(wire_cast_var)) sess.run( wire_cast_var.assign([[10., 11., 12.], [100., 110., 120.], [1000., 1100., 1200.], [10000., 11000., 12000.]])) sess.run(bias.assign([5., 6., 7.])) self.assertAllClose([[1005., 1106., 1207.], [10015., 11017., 12019.]], - predictions.eval()) + self.evaluate(predictions)) def test_dense_multi_dimension(self): price = fc.numeric_column('price', shape=2) @@ -2440,9 +2510,9 @@ class OldLinearModelTest(test.TestCase): predictions = fc_old.linear_model(features, [price]) price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([[0.], [0.]], price_var.eval()) + self.assertAllClose([[0.], [0.]], self.evaluate(price_var)) sess.run(price_var.assign([[10.], [100.]])) - self.assertAllClose([[210.], [650.]], predictions.eval()) + self.assertAllClose([[210.], [650.]], self.evaluate(predictions)) def test_sparse_multi_rank(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -2456,7 +2526,7 @@ class OldLinearModelTest(test.TestCase): predictions = fc_old.linear_model(features, [wire_cast]) wire_cast_var = get_linear_model_column_var(wire_cast) with _initialized_session() as sess: - self.assertAllClose(np.zeros((4, 1)), wire_cast_var.eval()) + self.assertAllClose(np.zeros((4, 1)), self.evaluate(wire_cast_var)) self.assertAllClose( np.zeros((2, 1)), predictions.eval(feed_dict={wire_tensor: wire_value})) @@ -2480,7 +2550,7 @@ class OldLinearModelTest(test.TestCase): with _initialized_session() as sess: sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [5010.]], predictions.eval()) + self.assertAllClose([[1005.], [5010.]], self.evaluate(predictions)) def test_sparse_combiner_with_negative_weights(self): wire_cast = fc.categorical_column_with_hash_bucket('wire_cast', 4) @@ -2502,7 +2572,7 @@ class OldLinearModelTest(test.TestCase): with _initialized_session() as sess: sess.run(wire_cast_var.assign([[10.], [100.], [1000.], [10000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[1005.], [-9985.]], predictions.eval()) + self.assertAllClose([[1005.], [-9985.]], self.evaluate(predictions)) def test_dense_multi_dimension_multi_output(self): price = fc.numeric_column('price', shape=2) @@ -2512,12 +2582,12 @@ class OldLinearModelTest(test.TestCase): bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose(np.zeros((3,)), bias.eval()) - self.assertAllClose(np.zeros((2, 3)), price_var.eval()) + self.assertAllClose(np.zeros((3,)), self.evaluate(bias)) + self.assertAllClose(np.zeros((2, 3)), self.evaluate(price_var)) sess.run(price_var.assign([[1., 2., 3.], [10., 100., 1000.]])) sess.run(bias.assign([2., 3., 4.])) self.assertAllClose([[23., 205., 2007.], [67., 613., 6019.]], - predictions.eval()) + self.evaluate(predictions)) def test_raises_if_shape_mismatch(self): price = fc.numeric_column('price', shape=2) @@ -2536,11 +2606,11 @@ class OldLinearModelTest(test.TestCase): bias = get_linear_model_bias() price_var = get_linear_model_column_var(price) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.]], price_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.]], self.evaluate(price_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price_var.assign([[10.], [100.]])) - self.assertAllClose([[210.], [650.]], predictions.eval()) + self.assertAllClose([[210.], [650.]], self.evaluate(predictions)) def test_dense_multi_column(self): price1 = fc.numeric_column('price1', shape=2) @@ -2552,14 +2622,14 @@ class OldLinearModelTest(test.TestCase): price1_var = get_linear_model_column_var(price1) price2_var = get_linear_model_column_var(price2) with _initialized_session() as sess: - self.assertAllClose([0.], bias.eval()) - self.assertAllClose([[0.], [0.]], price1_var.eval()) - self.assertAllClose([[0.]], price2_var.eval()) - self.assertAllClose([[0.], [0.]], predictions.eval()) + self.assertAllClose([0.], self.evaluate(bias)) + self.assertAllClose([[0.], [0.]], self.evaluate(price1_var)) + self.assertAllClose([[0.]], self.evaluate(price2_var)) + self.assertAllClose([[0.], [0.]], self.evaluate(predictions)) sess.run(price1_var.assign([[10.], [100.]])) sess.run(price2_var.assign([[1000.]])) sess.run(bias.assign([7.])) - self.assertAllClose([[3217.], [4657.]], predictions.eval()) + self.assertAllClose([[3217.], [4657.]], self.evaluate(predictions)) def test_fills_cols_to_vars(self): price1 = fc.numeric_column('price1', shape=2) @@ -2589,15 +2659,18 @@ class OldLinearModelTest(test.TestCase): partitioner=partitioned_variables.fixed_size_partitioner(2, axis=0)): fc_old.linear_model( features, [price1, price2], cols_to_vars=cols_to_vars) - with _initialized_session(): - self.assertEqual([0.], cols_to_vars['bias'][0].eval()) - # Partitioning shards the [2, 1] price1 var into 2 [1, 1] Variables. - self.assertAllEqual([[0.]], cols_to_vars[price1][0].eval()) - self.assertAllEqual([[0.]], cols_to_vars[price1][1].eval()) - # Partitioning shards the [3, 1] price2 var into a [2, 1] Variable and - # a [1, 1] Variable. - self.assertAllEqual([[0.], [0.]], cols_to_vars[price2][0].eval()) - self.assertAllEqual([[0.]], cols_to_vars[price2][1].eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertEqual([0.], self.evaluate(cols_to_vars['bias'][0])) + # Partitioning shards the [2, 1] price1 var into 2 [1, 1] Variables. + self.assertAllEqual([[0.]], self.evaluate(cols_to_vars[price1][0])) + self.assertAllEqual([[0.]], self.evaluate(cols_to_vars[price1][1])) + # Partitioning shards the [3, 1] price2 var into a [2, 1] Variable and + # a [1, 1] Variable. + self.assertAllEqual([[0.], [0.]], self.evaluate(cols_to_vars[price2][0])) + self.assertAllEqual([[0.]], self.evaluate(cols_to_vars[price2][1])) def test_fills_cols_to_output_tensors(self): # Provide three _DenseColumn's to input_layer: a _NumericColumn, a @@ -2795,6 +2868,7 @@ class OldLinearModelTest(test.TestCase): features['price2']: [[1.], [5.]], }) + @test_util.run_deprecated_v1 def test_with_1d_sparse_tensor(self): price = fc.numeric_column('price') price_buckets = fc.bucketized_column( @@ -2832,8 +2906,10 @@ class OldLinearModelTest(test.TestCase): sess.run(body_style_var.assign([[-10.], [-100.], [-1000.]])) sess.run(bias.assign([5.])) - self.assertAllClose([[10 - 1000 + 5.], [1000 - 10 + 5.]], sess.run(net)) + self.assertAllClose([[10 - 1000 + 5.], [1000 - 10 + 5.]], + self.evaluate(net)) + @test_util.run_deprecated_v1 def test_with_1d_unknown_shape_sparse_tensor(self): price = fc.numeric_column('price') price_buckets = fc.bucketized_column( @@ -2879,6 +2955,7 @@ class OldLinearModelTest(test.TestCase): features['country']: country_data })) + @test_util.run_deprecated_v1 def test_with_rank_0_feature(self): price = fc.numeric_column('price') features = { @@ -2912,26 +2989,27 @@ class OldLinearModelTest(test.TestCase): price_var1 = get_linear_model_column_var(price, name='linear_model') price_var2 = get_linear_model_column_var(price, name='linear_model_1') with _initialized_session() as sess: - self.assertAllClose([0.], bias1.eval()) + self.assertAllClose([0.], self.evaluate(bias1)) sess.run(price_var1.assign([[10.]])) sess.run(bias1.assign([5.])) - self.assertAllClose([[15.], [55.]], predictions1.eval()) - self.assertAllClose([0.], bias2.eval()) + self.assertAllClose([[15.], [55.]], self.evaluate(predictions1)) + self.assertAllClose([0.], self.evaluate(bias2)) sess.run(price_var2.assign([[10.]])) sess.run(bias2.assign([5.])) - self.assertAllClose([[25.], [105.]], predictions2.eval()) + self.assertAllClose([[25.], [105.]], self.evaluate(predictions2)) + @test_util.run_deprecated_v1 def test_linear_model_v1_shared_embedding_all_other_v2(self): price = fc.numeric_column('price') # v2 some_sparse_column = fc.categorical_column_with_hash_bucket( 'sparse_feature', hash_bucket_size=5) # v2 some_embedding_column = fc.embedding_column( some_sparse_column, dimension=10) # v2 - categorical_column_a = fc_old.categorical_column_with_identity( + categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) # v2 - categorical_column_b = fc_old.categorical_column_with_identity( + categorical_column_b = fc.categorical_column_with_identity( key='bbb', num_buckets=3) # v2 - shared_embedding_a, shared_embedding_b = fc_old.shared_embedding_columns( + shared_embedding_a, shared_embedding_b = fc.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) # v1 all_cols = [ price, some_embedding_column, shared_embedding_a, shared_embedding_b @@ -2954,9 +3032,13 @@ class OldLinearModelTest(test.TestCase): } fc_old.linear_model(features, all_cols) bias = get_linear_model_bias() - with _initialized_session(): - self.assertAllClose([0.], bias.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([0.], self.evaluate(bias)) + + @test_util.run_deprecated_v1 def test_linear_model_v1_shared_embedding_with_v2_cat_all_other_v2(self): price = fc.numeric_column('price') # v2 some_sparse_column = fc.categorical_column_with_hash_bucket( @@ -2967,7 +3049,7 @@ class OldLinearModelTest(test.TestCase): key='aaa', num_buckets=3) # v2 categorical_column_b = fc.categorical_column_with_identity( key='bbb', num_buckets=3) # v2 - shared_embedding_a, shared_embedding_b = fc_old.shared_embedding_columns( + shared_embedding_a, shared_embedding_b = fc.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) # v1 all_cols = [ price, some_embedding_column, shared_embedding_a, shared_embedding_b @@ -2990,20 +3072,24 @@ class OldLinearModelTest(test.TestCase): } fc_old.linear_model(features, all_cols) bias = get_linear_model_bias() - with _initialized_session(): - self.assertAllClose([0.], bias.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([0.], self.evaluate(bias)) + + @test_util.run_deprecated_v1 def test_linear_model_v1_v2_mix(self): price = fc.numeric_column('price') # v2 - some_sparse_column = fc_old.categorical_column_with_hash_bucket( + some_sparse_column = fc.categorical_column_with_hash_bucket( 'sparse_feature', hash_bucket_size=5) # v1 - some_embedding_column = fc_old.embedding_column( + some_embedding_column = fc.embedding_column( some_sparse_column, dimension=10) # v1 - categorical_column_a = fc_old.categorical_column_with_identity( + categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) # v2 - categorical_column_b = fc_old.categorical_column_with_identity( + categorical_column_b = fc.categorical_column_with_identity( key='bbb', num_buckets=3) # v2 - shared_embedding_a, shared_embedding_b = fc_old.shared_embedding_columns( + shared_embedding_a, shared_embedding_b = fc.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) # v1 all_cols = [ price, some_embedding_column, shared_embedding_a, shared_embedding_b @@ -3026,14 +3112,18 @@ class OldLinearModelTest(test.TestCase): } fc_old.linear_model(features, all_cols) bias = get_linear_model_bias() - with _initialized_session(): - self.assertAllClose([0.], bias.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([0.], self.evaluate(bias)) + + @test_util.run_deprecated_v1 def test_linear_model_v2_shared_embedding_all_other_v1(self): - price = fc_old.numeric_column('price') # v1 - some_sparse_column = fc_old.categorical_column_with_hash_bucket( + price = fc.numeric_column('price') # v1 + some_sparse_column = fc.categorical_column_with_hash_bucket( 'sparse_feature', hash_bucket_size=5) # v1 - some_embedding_column = fc_old.embedding_column( + some_embedding_column = fc.embedding_column( some_sparse_column, dimension=10) # v1 categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) # v2 @@ -3065,13 +3155,13 @@ class OldLinearModelTest(test.TestCase): fc_old.linear_model(features, all_cols) -class FeatureLayerTest(test.TestCase): +class DenseFeaturesTest(test.TestCase): @test_util.run_in_graph_and_eager_modes() def test_retrieving_input(self): features = {'a': [0.]} - feature_layer = fc.FeatureLayer(fc.numeric_column('a')) - inputs = self.evaluate(feature_layer(features)) + dense_features = fc.DenseFeatures(fc.numeric_column('a')) + inputs = self.evaluate(dense_features(features)) self.assertAllClose([[0.]], inputs) def test_reuses_variables(self): @@ -3085,6 +3175,7 @@ class FeatureLayerTest(test.TestCase): categorical_column = fc.categorical_column_with_identity( key='a', num_buckets=3) embedding_dimension = 2 + def _embedding_column_initializer(shape, dtype, partition_info): del shape # unused del dtype # unused @@ -3100,11 +3191,11 @@ class FeatureLayerTest(test.TestCase): dimension=embedding_dimension, initializer=_embedding_column_initializer) - feature_layer = fc.FeatureLayer([embedding_column]) + dense_features = fc.DenseFeatures([embedding_column]) features = {'a': sparse_input} - inputs = feature_layer(features) - variables = feature_layer.variables + inputs = dense_features(features) + variables = dense_features.variables # Sanity check: test that the inputs are correct. self.assertAllEqual([[1, 0], [0, 1], [1, 1]], inputs) @@ -3112,13 +3203,13 @@ class FeatureLayerTest(test.TestCase): # Check that only one variable was created. self.assertEqual(1, len(variables)) - # Check that invoking feature_layer on the same features does not create + # Check that invoking dense_features on the same features does not create # additional variables - _ = feature_layer(features) + _ = dense_features(features) self.assertEqual(1, len(variables)) - self.assertEqual(variables[0], feature_layer.variables[0]) + self.assertEqual(variables[0], dense_features.variables[0]) - def test_feature_column_feature_layer_gradient(self): + def test_feature_column_dense_features_gradient(self): with context.eager_mode(): sparse_input = sparse_tensor.SparseTensor( indices=((0, 0), (1, 0), (2, 0)), @@ -3145,11 +3236,11 @@ class FeatureLayerTest(test.TestCase): dimension=embedding_dimension, initializer=_embedding_column_initializer) - feature_layer = fc.FeatureLayer([embedding_column]) + dense_features = fc.DenseFeatures([embedding_column]) features = {'a': sparse_input} def scale_matrix(): - matrix = feature_layer(features) + matrix = dense_features(features) return 2 * matrix # Sanity check: Verify that scale_matrix returns the correct output. @@ -3167,11 +3258,11 @@ class FeatureLayerTest(test.TestCase): def test_raises_if_empty_feature_columns(self): with self.assertRaisesRegexp(ValueError, 'feature_columns must not be empty'): - fc.FeatureLayer(feature_columns=[])(features={}) + fc.DenseFeatures(feature_columns=[])(features={}) def test_should_be_dense_column(self): with self.assertRaisesRegexp(ValueError, 'must be a DenseColumn'): - fc.FeatureLayer(feature_columns=[ + fc.DenseFeatures(feature_columns=[ fc.categorical_column_with_hash_bucket('wire_cast', 4) ])( features={ @@ -3181,7 +3272,7 @@ class FeatureLayerTest(test.TestCase): def test_does_not_support_dict_columns(self): with self.assertRaisesRegexp( ValueError, 'Expected feature_columns to be iterable, found dict.'): - fc.FeatureLayer(feature_columns={'a': fc.numeric_column('a')})( + fc.DenseFeatures(feature_columns={'a': fc.numeric_column('a')})( features={ 'a': [[0]] }) @@ -3189,22 +3280,28 @@ class FeatureLayerTest(test.TestCase): def test_bare_column(self): with ops.Graph().as_default(): features = features = {'a': [0.]} - net = fc.FeatureLayer(fc.numeric_column('a'))(features) - with _initialized_session(): - self.assertAllClose([[0.]], net.eval()) + net = fc.DenseFeatures(fc.numeric_column('a'))(features) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[0.]], self.evaluate(net)) def test_column_generator(self): with ops.Graph().as_default(): features = features = {'a': [0.], 'b': [1.]} columns = (fc.numeric_column(key) for key in features) - net = fc.FeatureLayer(columns)(features) - with _initialized_session(): - self.assertAllClose([[0., 1.]], net.eval()) + net = fc.DenseFeatures(columns)(features) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[0., 1.]], self.evaluate(net)) def test_raises_if_duplicate_name(self): with self.assertRaisesRegexp( ValueError, 'Duplicate feature column name found for columns'): - fc.FeatureLayer( + fc.DenseFeatures( feature_columns=[fc.numeric_column('a'), fc.numeric_column('a')])( features={ @@ -3215,17 +3312,23 @@ class FeatureLayerTest(test.TestCase): price = fc.numeric_column('price') with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} - net = fc.FeatureLayer([price])(features) - with _initialized_session(): - self.assertAllClose([[1.], [5.]], net.eval()) + net = fc.DenseFeatures([price])(features) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1.], [5.]], self.evaluate(net)) def test_multi_dimension(self): price = fc.numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1., 2.], [5., 6.]]} - net = fc.FeatureLayer([price])(features) - with _initialized_session(): - self.assertAllClose([[1., 2.], [5., 6.]], net.eval()) + net = fc.DenseFeatures([price])(features) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 2.], [5., 6.]], self.evaluate(net)) def test_compute_output_shape(self): price1 = fc.numeric_column('price1', shape=2) @@ -3235,12 +3338,15 @@ class FeatureLayerTest(test.TestCase): 'price1': [[1., 2.], [5., 6.]], 'price2': [[3., 4., 5., 6.], [7., 8., 9., 10.]] } - feature_layer = fc.FeatureLayer([price1, price2]) - self.assertEqual((None, 6), feature_layer.compute_output_shape((None,))) - net = feature_layer(features) - with _initialized_session(): - self.assertAllClose( - [[1., 2., 3., 4., 5., 6.], [5., 6., 7., 8., 9., 10.]], net.eval()) + dense_features = fc.DenseFeatures([price1, price2]) + self.assertEqual((None, 6), dense_features.compute_output_shape((None,))) + net = dense_features(features) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 2., 3., 4., 5., 6.], [5., 6., 7., 8., 9., 10.]], + self.evaluate(net)) def test_raises_if_shape_mismatch(self): price = fc.numeric_column('price', shape=2) @@ -3249,27 +3355,30 @@ class FeatureLayerTest(test.TestCase): with self.assertRaisesRegexp( Exception, r'Cannot reshape a tensor with 2 elements to shape \[2,2\]'): - fc.FeatureLayer([price])(features) + fc.DenseFeatures([price])(features) def test_reshaping(self): price = fc.numeric_column('price', shape=[1, 2]) with ops.Graph().as_default(): features = {'price': [[[1., 2.]], [[5., 6.]]]} - net = fc.FeatureLayer([price])(features) - with _initialized_session(): - self.assertAllClose([[1., 2.], [5., 6.]], net.eval()) + net = fc.DenseFeatures([price])(features) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 2.], [5., 6.]], self.evaluate(net)) def test_multi_column(self): price1 = fc.numeric_column('price1', shape=2) price2 = fc.numeric_column('price2') with ops.Graph().as_default(): - features = { - 'price1': [[1., 2.], [5., 6.]], - 'price2': [[3.], [4.]] - } - net = fc.FeatureLayer([price1, price2])(features) - with _initialized_session(): - self.assertAllClose([[1., 2., 3.], [5., 6., 4.]], net.eval()) + features = {'price1': [[1., 2.], [5., 6.]], 'price2': [[3.], [4.]]} + net = fc.DenseFeatures([price1, price2])(features) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 2., 3.], [5., 6., 4.]], self.evaluate(net)) def test_cols_to_output_tensors(self): price1 = fc.numeric_column('price1', shape=2) @@ -3277,12 +3386,16 @@ class FeatureLayerTest(test.TestCase): with ops.Graph().as_default(): cols_dict = {} features = {'price1': [[1., 2.], [5., 6.]], 'price2': [[3.], [4.]]} - feature_layer = fc.FeatureLayer([price1, price2]) - net = feature_layer(features, cols_dict) - with _initialized_session(): - self.assertAllClose([[1., 2.], [5., 6.]], cols_dict[price1].eval()) - self.assertAllClose([[3.], [4.]], cols_dict[price2].eval()) - self.assertAllClose([[1., 2., 3.], [5., 6., 4.]], net.eval()) + dense_features = fc.DenseFeatures([price1, price2]) + net = dense_features(features, cols_dict) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 2.], [5., 6.]], + self.evaluate(cols_dict[price1])) + self.assertAllClose([[3.], [4.]], self.evaluate(cols_dict[price2])) + self.assertAllClose([[1., 2., 3.], [5., 6., 4.]], self.evaluate(net)) def test_column_order(self): price_a = fc.numeric_column('price_a') @@ -3292,11 +3405,14 @@ class FeatureLayerTest(test.TestCase): 'price_a': [[1.]], 'price_b': [[3.]], } - net1 = fc.FeatureLayer([price_a, price_b])(features) - net2 = fc.FeatureLayer([price_b, price_a])(features) - with _initialized_session(): - self.assertAllClose([[1., 3.]], net1.eval()) - self.assertAllClose([[1., 3.]], net2.eval()) + net1 = fc.DenseFeatures([price_a, price_b])(features) + net2 = fc.DenseFeatures([price_b, price_a])(features) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 3.]], self.evaluate(net1)) + self.assertAllClose([[1., 3.]], self.evaluate(net2)) def test_fails_for_categorical_column(self): animal = fc.categorical_column_with_identity('animal', num_buckets=4) @@ -3307,7 +3423,7 @@ class FeatureLayerTest(test.TestCase): indices=[[0, 0], [0, 1]], values=[1, 2], dense_shape=[1, 2]) } with self.assertRaisesRegexp(Exception, 'must be a DenseColumn'): - fc.FeatureLayer([animal])(features) + fc.DenseFeatures([animal])(features) def test_static_batch_size_mismatch(self): price1 = fc.numeric_column('price1') @@ -3320,7 +3436,7 @@ class FeatureLayerTest(test.TestCase): with self.assertRaisesRegexp( ValueError, 'Batch size \(first dimension\) of each feature must be same.'): # pylint: disable=anomalous-backslash-in-string - fc.FeatureLayer([price1, price2])(features) + fc.DenseFeatures([price1, price2])(features) def test_subset_of_static_batch_size_mismatch(self): price1 = fc.numeric_column('price1') @@ -3335,7 +3451,7 @@ class FeatureLayerTest(test.TestCase): with self.assertRaisesRegexp( ValueError, 'Batch size \(first dimension\) of each feature must be same.'): # pylint: disable=anomalous-backslash-in-string - fc.FeatureLayer([price1, price2, price3])(features) + fc.DenseFeatures([price1, price2, price3])(features) def test_runtime_batch_size_mismatch(self): price1 = fc.numeric_column('price1') @@ -3345,7 +3461,7 @@ class FeatureLayerTest(test.TestCase): 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 3 'price2': [[3.], [4.]] # batchsize = 2 } - net = fc.FeatureLayer([price1, price2])(features) + net = fc.DenseFeatures([price1, price2])(features) with _initialized_session() as sess: with self.assertRaisesRegexp(errors.OpError, 'Dimensions of inputs should match'): @@ -3359,7 +3475,7 @@ class FeatureLayerTest(test.TestCase): 'price1': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 2 'price2': array_ops.placeholder(dtype=dtypes.int64), # batchsize = 2 } - net = fc.FeatureLayer([price1, price2])(features) + net = fc.DenseFeatures([price1, price2])(features) with _initialized_session() as sess: sess.run( net, @@ -3379,19 +3495,20 @@ class FeatureLayerTest(test.TestCase): 'sparse_feature': [['a'], ['x']], } all_cols = [some_embedding_column] - fc.FeatureLayer(all_cols)(features) - fc.FeatureLayer(all_cols)(features) + fc.DenseFeatures(all_cols)(features) + fc.DenseFeatures(all_cols)(features) # Make sure that 2 variables get created in this case. self.assertEqual(2, len( ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES))) expected_var_names = [ - 'feature_layer/sparse_feature_embedding/embedding_weights:0', - 'feature_layer_1/sparse_feature_embedding/embedding_weights:0' + 'dense_features/sparse_feature_embedding/embedding_weights:0', + 'dense_features_1/sparse_feature_embedding/embedding_weights:0' ] self.assertItemsEqual( expected_var_names, [v.name for v in ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)]) + @test_util.run_deprecated_v1 def test_multiple_layers_with_same_shared_embedding_column(self): categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) @@ -3416,8 +3533,8 @@ class FeatureLayerTest(test.TestCase): dense_shape=(2, 2)), } all_cols = [embedding_column_a, embedding_column_b] - fc.FeatureLayer(all_cols)(features) - fc.FeatureLayer(all_cols)(features) + fc.DenseFeatures(all_cols)(features) + fc.DenseFeatures(all_cols)(features) # Make sure that only 1 variable gets created in this case. self.assertEqual(1, len( ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES))) @@ -3425,6 +3542,7 @@ class FeatureLayerTest(test.TestCase): ['aaa_bbb_shared_embedding:0'], [v.name for v in ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)]) + @test_util.run_deprecated_v1 def test_multiple_layers_with_same_shared_embedding_column_diff_graphs(self): categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) @@ -3449,7 +3567,7 @@ class FeatureLayerTest(test.TestCase): values=(1, 2, 1), dense_shape=(2, 2)), } - fc.FeatureLayer(all_cols)(features) + fc.DenseFeatures(all_cols)(features) # Make sure that only 1 variable gets created in this case. self.assertEqual(1, len( ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES))) @@ -3468,7 +3586,7 @@ class FeatureLayerTest(test.TestCase): dense_shape=(2, 2)), } - fc.FeatureLayer(all_cols)(features1) + fc.DenseFeatures(all_cols)(features1) # Make sure that only 1 variable gets created in this case. self.assertEqual(1, len( ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES))) @@ -3476,23 +3594,25 @@ class FeatureLayerTest(test.TestCase): ['aaa_bbb_shared_embedding:0'], [v.name for v in ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)]) + @test_util.run_deprecated_v1 def test_with_numpy_input_fn(self): embedding_values = ( (1., 2., 3., 4., 5.), # id 0 (6., 7., 8., 9., 10.), # id 1 (11., 12., 13., 14., 15.) # id 2 ) + def _initializer(shape, dtype, partition_info): del shape, dtype, partition_info return embedding_values - # price has 1 dimension in feature_layer + # price has 1 dimension in dense_features price = fc.numeric_column('price') body_style = fc.categorical_column_with_vocabulary_list( 'body-style', vocabulary_list=['hardtop', 'wagon', 'sedan']) - # one_hot_body_style has 3 dims in feature_layer. + # one_hot_body_style has 3 dims in dense_features. one_hot_body_style = fc.indicator_column(body_style) - # embedded_body_style has 5 dims in feature_layer. + # embedded_body_style has 5 dims in dense_features. embedded_body_style = fc.embedding_column( body_style, dimension=5, initializer=_initializer) @@ -3504,7 +3624,7 @@ class FeatureLayerTest(test.TestCase): batch_size=2, shuffle=False) features = input_fn() - net = fc.FeatureLayer([price, one_hot_body_style, embedded_body_style])( + net = fc.DenseFeatures([price, one_hot_body_style, embedded_body_style])( features) self.assertEqual(1 + 3 + 5, net.shape[1]) with _initialized_session() as sess: @@ -3513,33 +3633,33 @@ class FeatureLayerTest(test.TestCase): # Each row is formed by concatenating `embedded_body_style`, # `one_hot_body_style`, and `price` in order. - self.assertAllEqual( - [[11., 12., 13., 14., 15., 0., 0., 1., 11.], - [1., 2., 3., 4., 5., 1., 0., 0., 12]], - sess.run(net)) + self.assertAllEqual([[11., 12., 13., 14., 15., 0., 0., 1., 11.], + [1., 2., 3., 4., 5., 1., 0., 0., 12]], sess.run(net)) coord.request_stop() coord.join(threads) + @test_util.run_deprecated_v1 def test_with_1d_sparse_tensor(self): embedding_values = ( (1., 2., 3., 4., 5.), # id 0 (6., 7., 8., 9., 10.), # id 1 (11., 12., 13., 14., 15.) # id 2 ) + def _initializer(shape, dtype, partition_info): del shape, dtype, partition_info return embedding_values - # price has 1 dimension in feature_layer + # price has 1 dimension in dense_features price = fc.numeric_column('price') - # one_hot_body_style has 3 dims in feature_layer. + # one_hot_body_style has 3 dims in dense_features. body_style = fc.categorical_column_with_vocabulary_list( 'body-style', vocabulary_list=['hardtop', 'wagon', 'sedan']) one_hot_body_style = fc.indicator_column(body_style) - # embedded_body_style has 5 dims in feature_layer. + # embedded_body_style has 5 dims in dense_features. country = fc.categorical_column_with_vocabulary_list( 'country', vocabulary_list=['US', 'JP', 'CA']) embedded_country = fc.embedding_column( @@ -3547,49 +3667,56 @@ class FeatureLayerTest(test.TestCase): # Provides 1-dim tensor and dense tensor. features = { - 'price': constant_op.constant([11., 12.,]), - 'body-style': sparse_tensor.SparseTensor( - indices=((0,), (1,)), - values=('sedan', 'hardtop'), - dense_shape=(2,)), + 'price': + constant_op.constant([ + 11., + 12., + ]), + 'body-style': + sparse_tensor.SparseTensor( + indices=((0,), (1,)), + values=('sedan', 'hardtop'), + dense_shape=(2,)), # This is dense tensor for the categorical_column. - 'country': constant_op.constant(['CA', 'US']), + 'country': + constant_op.constant(['CA', 'US']), } self.assertEqual(1, features['price'].shape.ndims) self.assertEqual(1, features['body-style'].dense_shape.get_shape()[0]) self.assertEqual(1, features['country'].shape.ndims) - net = fc.FeatureLayer([price, one_hot_body_style, embedded_country])( + net = fc.DenseFeatures([price, one_hot_body_style, embedded_country])( features) self.assertEqual(1 + 3 + 5, net.shape[1]) with _initialized_session() as sess: # Each row is formed by concatenating `embedded_body_style`, # `one_hot_body_style`, and `price` in order. - self.assertAllEqual( - [[0., 0., 1., 11., 12., 13., 14., 15., 11.], - [1., 0., 0., 1., 2., 3., 4., 5., 12.]], - sess.run(net)) + self.assertAllEqual([[0., 0., 1., 11., 12., 13., 14., 15., 11.], + [1., 0., 0., 1., 2., 3., 4., 5., 12.]], + sess.run(net)) + @test_util.run_deprecated_v1 def test_with_1d_unknown_shape_sparse_tensor(self): embedding_values = ( (1., 2.), # id 0 (6., 7.), # id 1 (11., 12.) # id 2 ) + def _initializer(shape, dtype, partition_info): del shape, dtype, partition_info return embedding_values - # price has 1 dimension in feature_layer + # price has 1 dimension in dense_features price = fc.numeric_column('price') - # one_hot_body_style has 3 dims in feature_layer. + # one_hot_body_style has 3 dims in dense_features. body_style = fc.categorical_column_with_vocabulary_list( 'body-style', vocabulary_list=['hardtop', 'wagon', 'sedan']) one_hot_body_style = fc.indicator_column(body_style) - # embedded_body_style has 5 dims in feature_layer. + # embedded_body_style has 5 dims in dense_features. country = fc.categorical_column_with_vocabulary_list( 'country', vocabulary_list=['US', 'JP', 'CA']) embedded_country = fc.embedding_column( @@ -3608,12 +3735,10 @@ class FeatureLayerTest(test.TestCase): price_data = np.array([11., 12.]) body_style_data = sparse_tensor.SparseTensorValue( - indices=((0,), (1,)), - values=('sedan', 'hardtop'), - dense_shape=(2,)) + indices=((0,), (1,)), values=('sedan', 'hardtop'), dense_shape=(2,)) country_data = np.array([['US'], ['CA']]) - net = fc.FeatureLayer([price, one_hot_body_style, embedded_country])( + net = fc.DenseFeatures([price, one_hot_body_style, embedded_country])( features) self.assertEqual(1 + 3 + 2, net.shape[1]) with _initialized_session() as sess: @@ -3630,8 +3755,9 @@ class FeatureLayerTest(test.TestCase): features['country']: country_data })) + @test_util.run_deprecated_v1 def test_with_rank_0_feature(self): - # price has 1 dimension in feature_layer + # price has 1 dimension in dense_features price = fc.numeric_column('price') features = { 'price': constant_op.constant(0), @@ -3640,13 +3766,13 @@ class FeatureLayerTest(test.TestCase): # Static rank 0 should fail with self.assertRaisesRegexp(ValueError, 'Feature .* cannot have rank 0'): - fc.FeatureLayer([price])(features) + fc.DenseFeatures([price])(features) # Dynamic rank 0 should fail features = { 'price': array_ops.placeholder(dtypes.float32), } - net = fc.FeatureLayer([price])(features) + net = fc.DenseFeatures([price])(features) self.assertEqual(1, net.shape[1]) with _initialized_session() as sess: with self.assertRaisesOpError('Feature .* cannot have rank 0'): @@ -3779,16 +3905,22 @@ class FunctionalInputLayerTest(test.TestCase): with ops.Graph().as_default(): features = features = {'a': [0.]} net = fc_old.input_layer(features, fc.numeric_column('a')) - with _initialized_session(): - self.assertAllClose([[0.]], net.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[0.]], self.evaluate(net)) def test_column_generator(self): with ops.Graph().as_default(): features = features = {'a': [0.], 'b': [1.]} columns = (fc.numeric_column(key) for key in features) net = fc_old.input_layer(features, columns) - with _initialized_session(): - self.assertAllClose([[0., 1.]], net.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[0., 1.]], self.evaluate(net)) def test_raises_if_duplicate_name(self): with self.assertRaisesRegexp( @@ -3803,16 +3935,22 @@ class FunctionalInputLayerTest(test.TestCase): with ops.Graph().as_default(): features = {'price': [[1.], [5.]]} net = fc_old.input_layer(features, [price]) - with _initialized_session(): - self.assertAllClose([[1.], [5.]], net.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1.], [5.]], self.evaluate(net)) def test_multi_dimension(self): price = fc.numeric_column('price', shape=2) with ops.Graph().as_default(): features = {'price': [[1., 2.], [5., 6.]]} net = fc_old.input_layer(features, [price]) - with _initialized_session(): - self.assertAllClose([[1., 2.], [5., 6.]], net.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 2.], [5., 6.]], self.evaluate(net)) def test_raises_if_shape_mismatch(self): price = fc.numeric_column('price', shape=2) @@ -3828,8 +3966,11 @@ class FunctionalInputLayerTest(test.TestCase): with ops.Graph().as_default(): features = {'price': [[[1., 2.]], [[5., 6.]]]} net = fc_old.input_layer(features, [price]) - with _initialized_session(): - self.assertAllClose([[1., 2.], [5., 6.]], net.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 2.], [5., 6.]], self.evaluate(net)) def test_multi_column(self): price1 = fc.numeric_column('price1', shape=2) @@ -3837,8 +3978,11 @@ class FunctionalInputLayerTest(test.TestCase): with ops.Graph().as_default(): features = {'price1': [[1., 2.], [5., 6.]], 'price2': [[3.], [4.]]} net = fc_old.input_layer(features, [price1, price2]) - with _initialized_session(): - self.assertAllClose([[1., 2., 3.], [5., 6., 4.]], net.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 2., 3.], [5., 6., 4.]], self.evaluate(net)) def test_fills_cols_to_vars(self): # Provide three _DenseColumn's to input_layer: a _NumericColumn, a @@ -3869,6 +4013,7 @@ class FunctionalInputLayerTest(test.TestCase): variables_lib.Variable) self.assertAllEqual(cols_to_vars[some_embedding_column][0].shape, [5, 10]) + @test_util.run_deprecated_v1 def test_fills_cols_to_vars_shared_embedding(self): # Provide 5 DenseColumn's to input_layer: a NumericColumn, a # BucketizedColumn, an EmbeddingColumn, two SharedEmbeddingColumns. The @@ -3882,11 +4027,11 @@ class FunctionalInputLayerTest(test.TestCase): 'sparse_feature', hash_bucket_size=5) some_embedding_column = fc.embedding_column( some_sparse_column, dimension=10) - categorical_column_a = fc_old.categorical_column_with_identity( + categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) - categorical_column_b = fc_old.categorical_column_with_identity( + categorical_column_b = fc.categorical_column_with_identity( key='bbb', num_buckets=3) - shared_embedding_a, shared_embedding_b = fc_old.shared_embedding_columns( + shared_embedding_a, shared_embedding_b = fc.shared_embedding_columns( [categorical_column_a, categorical_column_b], dimension=2) with ops.Graph().as_default(): features = { @@ -3968,9 +4113,12 @@ class FunctionalInputLayerTest(test.TestCase): } net1 = fc_old.input_layer(features, [price_a, price_b]) net2 = fc_old.input_layer(features, [price_b, price_a]) - with _initialized_session(): - self.assertAllClose([[1., 3.]], net1.eval()) - self.assertAllClose([[1., 3.]], net2.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[1., 3.]], self.evaluate(net1)) + self.assertAllClose([[1., 3.]], self.evaluate(net2)) def test_fails_for_categorical_column(self): animal = fc.categorical_column_with_identity('animal', num_buckets=4) @@ -4066,6 +4214,7 @@ class FunctionalInputLayerTest(test.TestCase): expected_var_names, [v.name for v in ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)]) + @test_util.run_deprecated_v1 def test_with_1d_sparse_tensor(self): embedding_values = ( (1., 2., 3., 4., 5.), # id 0 @@ -4122,6 +4271,7 @@ class FunctionalInputLayerTest(test.TestCase): [1., 0., 0., 1., 2., 3., 4., 5., 12.]], sess.run(net)) + @test_util.run_deprecated_v1 def test_with_1d_unknown_shape_sparse_tensor(self): embedding_values = ( (1., 2.), # id 0 @@ -4180,6 +4330,7 @@ class FunctionalInputLayerTest(test.TestCase): features['country']: country_data })) + @test_util.run_deprecated_v1 def test_with_rank_0_feature(self): # price has 1 dimension in input_layer price = fc.numeric_column('price') @@ -4220,12 +4371,19 @@ class MakeParseExampleSpecTest(test.TestCase): def transform_feature(self, transformation_cache, state_manager): pass + def _transform_feature(self, inputs): + pass + @property def parse_example_spec(self): return self.parse_spec + @property + def _parse_example_spec(self): + return self.parse_spec + def test_no_feature_columns(self): - actual = fc.make_parse_example_spec([]) + actual = fc.make_parse_example_spec_v2([]) self.assertDictEqual({}, actual) def test_invalid_type(self): @@ -4235,15 +4393,17 @@ class MakeParseExampleSpecTest(test.TestCase): with self.assertRaisesRegexp( ValueError, 'All feature_columns must be FeatureColumn instances.*invalid_column'): - fc.make_parse_example_spec( - (self._TestFeatureColumn({key1: parse_spec1}), 'invalid_column')) + fc.make_parse_example_spec_v2((self._TestFeatureColumn({ + key1: parse_spec1 + }), 'invalid_column')) def test_one_feature_column(self): key1 = 'key1' parse_spec1 = parsing_ops.FixedLenFeature( shape=(2,), dtype=dtypes.float32, default_value=0.) - actual = fc.make_parse_example_spec( - (self._TestFeatureColumn({key1: parse_spec1}),)) + actual = fc.make_parse_example_spec_v2((self._TestFeatureColumn({ + key1: parse_spec1 + }),)) self.assertDictEqual({key1: parse_spec1}, actual) def test_two_feature_columns(self): @@ -4252,9 +4412,11 @@ class MakeParseExampleSpecTest(test.TestCase): shape=(2,), dtype=dtypes.float32, default_value=0.) key2 = 'key2' parse_spec2 = parsing_ops.VarLenFeature(dtype=dtypes.string) - actual = fc.make_parse_example_spec( - (self._TestFeatureColumn({key1: parse_spec1}), - self._TestFeatureColumn({key2: parse_spec2}))) + actual = fc.make_parse_example_spec_v2((self._TestFeatureColumn({ + key1: parse_spec1 + }), self._TestFeatureColumn({ + key2: parse_spec2 + }))) self.assertDictEqual({key1: parse_spec1, key2: parse_spec2}, actual) def test_equal_keys_different_parse_spec(self): @@ -4265,17 +4427,21 @@ class MakeParseExampleSpecTest(test.TestCase): with self.assertRaisesRegexp( ValueError, 'feature_columns contain different parse_spec for key key1'): - fc.make_parse_example_spec( - (self._TestFeatureColumn({key1: parse_spec1}), - self._TestFeatureColumn({key1: parse_spec2}))) + fc.make_parse_example_spec_v2((self._TestFeatureColumn({ + key1: parse_spec1 + }), self._TestFeatureColumn({ + key1: parse_spec2 + }))) def test_equal_keys_equal_parse_spec(self): key1 = 'key1' parse_spec1 = parsing_ops.FixedLenFeature( shape=(2,), dtype=dtypes.float32, default_value=0.) - actual = fc.make_parse_example_spec( - (self._TestFeatureColumn({key1: parse_spec1}), - self._TestFeatureColumn({key1: parse_spec1}))) + actual = fc.make_parse_example_spec_v2((self._TestFeatureColumn({ + key1: parse_spec1 + }), self._TestFeatureColumn({ + key1: parse_spec1 + }))) self.assertDictEqual({key1: parse_spec1}, actual) def test_multiple_features_dict(self): @@ -4287,11 +4453,17 @@ class MakeParseExampleSpecTest(test.TestCase): parse_spec2 = parsing_ops.VarLenFeature(dtype=dtypes.string) key3 = 'key3' parse_spec3 = parsing_ops.VarLenFeature(dtype=dtypes.int32) - actual = fc.make_parse_example_spec( - (self._TestFeatureColumn({key1: parse_spec1}), - self._TestFeatureColumn({key2: parse_spec2, key3: parse_spec3}))) - self.assertDictEqual( - {key1: parse_spec1, key2: parse_spec2, key3: parse_spec3}, actual) + actual = fc.make_parse_example_spec_v2((self._TestFeatureColumn({ + key1: parse_spec1 + }), self._TestFeatureColumn({ + key2: parse_spec2, + key3: parse_spec3 + }))) + self.assertDictEqual({ + key1: parse_spec1, + key2: parse_spec2, + key3: parse_spec3 + }, actual) def _assert_sparse_tensor_value(test_case, expected, actual): @@ -4299,7 +4471,8 @@ def _assert_sparse_tensor_value(test_case, expected, actual): test_case.assertAllEqual(expected.indices, actual.indices) test_case.assertEqual( - np.array(expected.values).dtype, np.array(actual.values).dtype) + np.array(expected.values).dtype, + np.array(actual.values).dtype) test_case.assertAllEqual(expected.values, actual.values) test_case.assertEqual(np.int64, np.array(actual.dense_shape).dtype) @@ -4321,6 +4494,7 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'python/feature_column/testdata/wire_vocabulary.txt') self._wire_vocabulary_size = 3 + @test_util.run_deprecated_v1 def test_defaults(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', vocabulary_file='path_to_file', vocabulary_size=3) @@ -4337,19 +4511,27 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): fc.categorical_column_with_vocabulary_file( key=('aaa',), vocabulary_file='path_to_file', vocabulary_size=3) + @test_util.run_deprecated_v1 def test_all_constructor_args(self): column = fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file='path_to_file', vocabulary_size=3, - num_oov_buckets=4, dtype=dtypes.int32) + key='aaa', + vocabulary_file='path_to_file', + vocabulary_size=3, + num_oov_buckets=4, + dtype=dtypes.int32) self.assertEqual(7, column.num_buckets) self.assertEqual({ 'aaa': parsing_ops.VarLenFeature(dtypes.int32) }, column.parse_example_spec) + @test_util.run_deprecated_v1 def test_deep_copy(self): original = fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file='path_to_file', vocabulary_size=3, - num_oov_buckets=4, dtype=dtypes.int32) + key='aaa', + vocabulary_file='path_to_file', + vocabulary_size=3, + num_oov_buckets=4, + dtype=dtypes.int32) for column in (original, copy.deepcopy(original)): self.assertEqual('aaa', column.name) self.assertEqual(7, column.num_buckets) @@ -4367,6 +4549,7 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): fc.categorical_column_with_vocabulary_file( key='aaa', vocabulary_file='', vocabulary_size=3) + @test_util.run_deprecated_v1 def test_invalid_vocabulary_file(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', vocabulary_file='file_does_not_exist', vocabulary_size=10) @@ -4379,19 +4562,21 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) with self.assertRaisesRegexp(errors.OpError, 'file_does_not_exist'): - with self.cached_session(): - lookup_ops.tables_initializer().run() + self.evaluate(lookup_ops.tables_initializer()) def test_invalid_vocabulary_size(self): with self.assertRaisesRegexp(ValueError, 'Invalid vocabulary_size'): fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file=self._wire_vocabulary_file_name, + key='aaa', + vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=-1) with self.assertRaisesRegexp(ValueError, 'Invalid vocabulary_size'): fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file=self._wire_vocabulary_file_name, + key='aaa', + vocabulary_file=self._wire_vocabulary_file_name, vocabulary_size=0) + @test_util.run_deprecated_v1 def test_too_large_vocabulary_size(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', @@ -4406,24 +4591,27 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) with self.assertRaisesRegexp(errors.OpError, 'Invalid vocab_size'): - with self.cached_session(): - lookup_ops.tables_initializer().run() + self.evaluate(lookup_ops.tables_initializer()) def test_invalid_num_oov_buckets(self): with self.assertRaisesRegexp(ValueError, 'Invalid num_oov_buckets'): fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file='path', vocabulary_size=3, + key='aaa', + vocabulary_file='path', + vocabulary_size=3, num_oov_buckets=-1) def test_invalid_dtype(self): with self.assertRaisesRegexp(ValueError, 'dtype must be string or integer'): fc.categorical_column_with_vocabulary_file( - key='aaa', vocabulary_file='path', vocabulary_size=3, + key='aaa', + vocabulary_file='path', + vocabulary_size=3, dtype=dtypes.float64) def test_invalid_buckets_and_default_value(self): - with self.assertRaisesRegexp( - ValueError, 'both num_oov_buckets and default_value'): + with self.assertRaisesRegexp(ValueError, + 'both num_oov_buckets and default_value'): fc.categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name, @@ -4463,28 +4651,31 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) + @test_util.run_deprecated_v1 def test_parse_example(self): a = fc.categorical_column_with_vocabulary_file( key='aaa', vocabulary_file='path_to_file', vocabulary_size=3) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'aaa': - feature_pb2.Feature(bytes_list=feature_pb2.BytesList( - value=[b'omar', b'stringer'])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'aaa': + feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[b'omar', b'stringer'])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([a])) + features=fc.make_parse_example_spec_v2([a])) self.assertIn('aaa', features) - with self.cached_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([b'omar', b'stringer'], dtype=np.object_), - dense_shape=[1, 2]), - features['aaa'].eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([b'omar', b'stringer'], dtype=np.object_), + dense_shape=[1, 2]), self.evaluate(features['aaa'])) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', @@ -4499,15 +4690,19 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, -1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, -1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_none_vocabulary_size(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', vocabulary_file=self._wire_vocabulary_file_name) @@ -4520,15 +4715,19 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value(self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array( - (2, -1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, -1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_transform_feature(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', @@ -4538,16 +4737,21 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): indices=((0, 0), (1, 0), (1, 1)), values=('marlo', 'skywalker', 'omar'), dense_shape=(2, 2)) - id_tensor = fc._transform_features({'aaa': inputs}, [column], None)[column] - with _initialized_session(): - _assert_sparse_tensor_value(self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array( - (2, -1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) + id_tensor = fc._transform_features_v2({ + 'aaa': inputs + }, [column], None)[column] + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, -1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_dense_input(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', @@ -4558,15 +4762,18 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': (('marlo', ''), ('skywalker', 'omar')) }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=np.array((2, -1, 0), dtype=np.int64), - dense_shape=(2, 2)), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=np.array((2, -1, 0), dtype=np.int64), + dense_shape=(2, 2)), self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_default_value_in_vocabulary(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', @@ -4582,15 +4789,19 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, 2, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, 2, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_oov_buckets(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', @@ -4606,15 +4817,19 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, 33, 0, 62), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, 33, 0, 62), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_small_vocabulary_size(self): # 'marlo' is the last entry in our vocabulary file, so be setting # `vocabulary_size` to 1 less than number of entries in file, we take @@ -4632,15 +4847,19 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((-1, -1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((-1, -1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', @@ -4656,15 +4875,19 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, -1, 0, 4), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, -1, 0, 4), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32_dense_input(self): default_value = -100 column = fc.categorical_column_with_vocabulary_file( @@ -4678,15 +4901,18 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': ((11, -1, -1), (100, 30, -1), (-1, -1, 22)) }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1), (2, 2)), - values=np.array((2, default_value, 0, 4), dtype=np.int64), - dense_shape=(3, 3)), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1), (2, 2)), + values=np.array((2, default_value, 0, 4), dtype=np.int64), + dense_shape=(3, 3)), self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32_with_oov_buckets(self): column = fc.categorical_column_with_vocabulary_file( key='aaa', @@ -4703,15 +4929,19 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, 60, 0, 4), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, 60, 0, 4), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_linear_model(self): wire_column = fc.categorical_column_with_vocabulary_file( key='wire', @@ -4729,14 +4959,17 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): dense_shape=(2, 2)) }) wire_var, bias = model.variables - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() - # 'marlo' -> 2: wire_var[2] = 3 - # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 - self.assertAllClose(((3.,), (5.,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(wire_var.assign(((1.,), (2.,), (3.,), (4.,)))) + # 'marlo' -> 2: wire_var[2] = 3 + # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 + self.assertAllClose(((3.,), (5.,)), self.evaluate(predictions)) def test_old_linear_model(self): wire_column = fc.categorical_column_with_vocabulary_file( @@ -4755,15 +4988,19 @@ class VocabularyFileCategoricalColumnTest(test.TestCase): }, (wire_column,)) bias = get_linear_model_bias() wire_var = get_linear_model_column_var(wire_column) - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() - # 'marlo' -> 2: wire_var[2] = 3 - # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 - self.assertAllClose(((3.,), (5.,)), predictions.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(wire_var.assign(((1.,), (2.,), (3.,), (4.,)))) + # 'marlo' -> 2: wire_var[2] = 3 + # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 + self.assertAllClose(((3.,), (5.,)), self.evaluate(predictions)) + + @test_util.run_deprecated_v1 def test_serialization(self): wire_column = fc.categorical_column_with_vocabulary_file( key='wire', @@ -4815,15 +5052,19 @@ class VocabularyListCategoricalColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int64) }, column.parse_example_spec) + @test_util.run_deprecated_v1 def test_all_constructor_args(self): column = fc.categorical_column_with_vocabulary_list( - key='aaa', vocabulary_list=(12, 24, 36), dtype=dtypes.int32, + key='aaa', + vocabulary_list=(12, 24, 36), + dtype=dtypes.int32, default_value=-99) self.assertEqual(3, column.num_buckets) self.assertEqual({ 'aaa': parsing_ops.VarLenFeature(dtypes.int32) }, column.parse_example_spec) + @test_util.run_deprecated_v1 def test_deep_copy(self): original = fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12, 24, 36), dtype=dtypes.int32) @@ -4837,37 +5078,39 @@ class VocabularyListCategoricalColumnTest(test.TestCase): def test_invalid_dtype(self): with self.assertRaisesRegexp(ValueError, 'dtype must be string or integer'): fc.categorical_column_with_vocabulary_list( - key='aaa', vocabulary_list=('omar', 'stringer', 'marlo'), + key='aaa', + vocabulary_list=('omar', 'stringer', 'marlo'), dtype=dtypes.float32) def test_invalid_mapping_dtype(self): - with self.assertRaisesRegexp( - ValueError, r'vocabulary dtype must be string or integer'): + with self.assertRaisesRegexp(ValueError, + r'vocabulary dtype must be string or integer'): fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12., 24., 36.)) def test_mismatched_int_dtype(self): - with self.assertRaisesRegexp( - ValueError, r'dtype.*and vocabulary dtype.*do not match'): + with self.assertRaisesRegexp(ValueError, + r'dtype.*and vocabulary dtype.*do not match'): fc.categorical_column_with_vocabulary_list( - key='aaa', vocabulary_list=('omar', 'stringer', 'marlo'), + key='aaa', + vocabulary_list=('omar', 'stringer', 'marlo'), dtype=dtypes.int32) def test_mismatched_string_dtype(self): - with self.assertRaisesRegexp( - ValueError, r'dtype.*and vocabulary dtype.*do not match'): + with self.assertRaisesRegexp(ValueError, + r'dtype.*and vocabulary dtype.*do not match'): fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12, 24, 36), dtype=dtypes.string) def test_none_mapping(self): - with self.assertRaisesRegexp( - ValueError, r'vocabulary_list.*must be non-empty'): + with self.assertRaisesRegexp(ValueError, + r'vocabulary_list.*must be non-empty'): fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=None) def test_empty_mapping(self): - with self.assertRaisesRegexp( - ValueError, r'vocabulary_list.*must be non-empty'): + with self.assertRaisesRegexp(ValueError, + r'vocabulary_list.*must be non-empty'): fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=tuple([])) @@ -4879,12 +5122,11 @@ class VocabularyListCategoricalColumnTest(test.TestCase): def test_invalid_num_oov_buckets(self): with self.assertRaisesRegexp(ValueError, 'Invalid num_oov_buckets'): fc.categorical_column_with_vocabulary_list( - key='aaa', vocabulary_list=(12, 24, 36), - num_oov_buckets=-1) + key='aaa', vocabulary_list=(12, 24, 36), num_oov_buckets=-1) def test_invalid_buckets_and_default_value(self): - with self.assertRaisesRegexp( - ValueError, 'both num_oov_buckets and default_value'): + with self.assertRaisesRegexp(ValueError, + 'both num_oov_buckets and default_value'): fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(12, 24, 36), @@ -4893,8 +5135,7 @@ class VocabularyListCategoricalColumnTest(test.TestCase): def test_invalid_input_dtype_int32(self): column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=('omar', 'stringer', 'marlo')) + key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=(12, 24, 36), @@ -4907,8 +5148,7 @@ class VocabularyListCategoricalColumnTest(test.TestCase): def test_invalid_input_dtype_string(self): column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=(12, 24, 36)) + key='aaa', vocabulary_list=(12, 24, 36)) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=('omar', 'stringer', 'marlo'), @@ -4919,54 +5159,56 @@ class VocabularyListCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) + @test_util.run_deprecated_v1 def test_parse_example_string(self): a = fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'aaa': - feature_pb2.Feature(bytes_list=feature_pb2.BytesList( - value=[b'omar', b'stringer'])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'aaa': + feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[b'omar', b'stringer'])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([a])) + features=fc.make_parse_example_spec_v2([a])) self.assertIn('aaa', features) - with self.cached_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([b'omar', b'stringer'], dtype=np.object_), - dense_shape=[1, 2]), - features['aaa'].eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([b'omar', b'stringer'], dtype=np.object_), + dense_shape=[1, 2]), self.evaluate(features['aaa'])) + + @test_util.run_deprecated_v1 def test_parse_example_int(self): a = fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=(11, 21, 31)) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'aaa': - feature_pb2.Feature(int64_list=feature_pb2.Int64List( - value=[11, 21])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'aaa': + feature_pb2.Feature( + int64_list=feature_pb2.Int64List(value=[11, 21])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([a])) + features=fc.make_parse_example_spec_v2([a])) self.assertIn('aaa', features) - with self.cached_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=[11, 21], - dense_shape=[1, 2]), - features['aaa'].eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], values=[11, 21], dense_shape=[1, 2]), + self.evaluate(features['aaa'])) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=('omar', 'stringer', 'marlo')) + key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=('marlo', 'skywalker', 'omar'), @@ -4976,51 +5218,61 @@ class VocabularyListCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, -1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, -1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_transform_feature(self): column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=('omar', 'stringer', 'marlo')) + key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) inputs = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=('marlo', 'skywalker', 'omar'), dense_shape=(2, 2)) - id_tensor = fc._transform_features({'aaa': inputs}, [column], None)[column] - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, -1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) + id_tensor = fc._transform_features_v2({ + 'aaa': inputs + }, [column], None)[column] + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, -1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_dense_input(self): column = fc.categorical_column_with_vocabulary_list( - key='aaa', - vocabulary_list=('omar', 'stringer', 'marlo')) + key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) id_weight_pair = column.get_sparse_tensors( fc.FeatureTransformationCache({ 'aaa': (('marlo', ''), ('skywalker', 'omar')) }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=np.array((2, -1, 0), dtype=np.int64), - dense_shape=(2, 2)), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=np.array((2, -1, 0), dtype=np.int64), + dense_shape=(2, 2)), self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_default_value_in_vocabulary(self): column = fc.categorical_column_with_vocabulary_list( key='aaa', @@ -5035,15 +5287,19 @@ class VocabularyListCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, 2, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, 2, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_oov_buckets(self): column = fc.categorical_column_with_vocabulary_list( key='aaa', @@ -5058,15 +5314,19 @@ class VocabularyListCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, 33, 0, 62), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, 33, 0, 62), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32(self): column = fc.categorical_column_with_vocabulary_list( key='aaa', @@ -5081,15 +5341,19 @@ class VocabularyListCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, -1, 0, 4), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, -1, 0, 4), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32_dense_input(self): default_value = -100 column = fc.categorical_column_with_vocabulary_list( @@ -5104,15 +5368,18 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dtype=np.int32) }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1), (2, 2)), - values=np.array((2, default_value, 0, 4), dtype=np.int64), - dense_shape=(3, 3)), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1), (2, 2)), + values=np.array((2, default_value, 0, 4), dtype=np.int64), + dense_shape=(3, 3)), self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_int32_with_oov_buckets(self): column = fc.categorical_column_with_vocabulary_list( key='aaa', @@ -5128,15 +5395,19 @@ class VocabularyListCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((2, 60, 0, 4), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((2, 60, 0, 4), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_linear_model(self): wire_column = fc.categorical_column_with_vocabulary_list( key='aaa', @@ -5153,14 +5424,17 @@ class VocabularyListCategoricalColumnTest(test.TestCase): dense_shape=(2, 2)) }) wire_var, bias = model.variables - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() - # 'marlo' -> 2: wire_var[2] = 3 - # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 - self.assertAllClose(((3.,), (5.,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(wire_var.assign(((1.,), (2.,), (3.,), (4.,)))) + # 'marlo' -> 2: wire_var[2] = 3 + # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 + self.assertAllClose(((3.,), (5.,)), self.evaluate(predictions)) def test_old_linear_model(self): wire_column = fc.categorical_column_with_vocabulary_list( @@ -5178,15 +5452,19 @@ class VocabularyListCategoricalColumnTest(test.TestCase): }, (wire_column,)) bias = get_linear_model_bias() wire_var = get_linear_model_column_var(wire_column) - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), wire_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - wire_var.assign(((1.,), (2.,), (3.,), (4.,))).eval() - # 'marlo' -> 2: wire_var[2] = 3 - # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 - self.assertAllClose(((3.,), (5.,)), predictions.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,), (0.,)), self.evaluate(wire_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(wire_var.assign(((1.,), (2.,), (3.,), (4.,)))) + # 'marlo' -> 2: wire_var[2] = 3 + # 'skywalker' -> 3, 'omar' -> 0: wire_var[3] + wire_var[0] = 4+1 = 5 + self.assertAllClose(((3.,), (5.,)), self.evaluate(predictions)) + + @test_util.run_deprecated_v1 def test_serialization(self): wire_column = fc.categorical_column_with_vocabulary_list( key='aaa', @@ -5208,7 +5486,6 @@ class VocabularyListCategoricalColumnTest(test.TestCase): fc.VocabularyListCategoricalColumn._from_config(config)) - class IdentityCategoricalColumnTest(test.TestCase): def test_constructor(self): @@ -5225,6 +5502,7 @@ class IdentityCategoricalColumnTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'key must be a string.'): fc.categorical_column_with_identity(key=('aaa',), num_buckets=3) + @test_util.run_deprecated_v1 def test_deep_copy(self): original = fc.categorical_column_with_identity(key='aaa', num_buckets=3) for column in (original, copy.deepcopy(original)): @@ -5264,63 +5542,70 @@ class IdentityCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) + @test_util.run_deprecated_v1 def test_parse_example(self): a = fc.categorical_column_with_identity(key='aaa', num_buckets=30) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'aaa': - feature_pb2.Feature(int64_list=feature_pb2.Int64List( - value=[11, 21])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'aaa': + feature_pb2.Feature( + int64_list=feature_pb2.Int64List(value=[11, 21])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([a])) + features=fc.make_parse_example_spec_v2([a])) self.assertIn('aaa', features) - with self.cached_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([11, 21], dtype=np.int64), - dense_shape=[1, 2]), - features['aaa'].eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([11, 21], dtype=np.int64), + dense_shape=[1, 2]), self.evaluate(features['aaa'])) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors(self): column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=(0, 1, 0), - dense_shape=(2, 2)) + indices=((0, 0), (1, 0), (1, 1)), values=(0, 1, 0), dense_shape=(2, 2)) id_weight_pair = column.get_sparse_tensors( fc.FeatureTransformationCache({ 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((0, 1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((0, 1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_transform_feature(self): column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=(0, 1, 0), - dense_shape=(2, 2)) - id_tensor = fc._transform_features({'aaa': inputs}, [column], None)[column] - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((0, 1, 0), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) - + indices=((0, 0), (1, 0), (1, 1)), values=(0, 1, 0), dense_shape=(2, 2)) + id_tensor = fc._transform_features_v2({ + 'aaa': inputs + }, [column], None)[column] + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((0, 1, 0), dtype=np.int64), + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_dense_input(self): column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) id_weight_pair = column.get_sparse_tensors( @@ -5328,47 +5613,53 @@ class IdentityCategoricalColumnTest(test.TestCase): 'aaa': ((0, -1), (1, 0)) }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=np.array((0, 1, 0), dtype=np.int64), - dense_shape=(2, 2)), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=np.array((0, 1, 0), dtype=np.int64), + dense_shape=(2, 2)), self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_inputs_too_small(self): column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=(1, -1, 0), - dense_shape=(2, 2)) + indices=((0, 0), (1, 0), (1, 1)), values=(1, -1, 0), dense_shape=(2, 2)) id_weight_pair = column.get_sparse_tensors( fc.FeatureTransformationCache({ 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - with self.assertRaisesRegexp( - errors.OpError, 'assert_greater_or_equal_0'): - id_weight_pair.id_tensor.eval() + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + with self.assertRaisesRegexp(errors.OpError, 'assert_greater_or_equal_0'): + self.evaluate(id_weight_pair.id_tensor) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_inputs_too_big(self): column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) inputs = sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=(1, 99, 0), - dense_shape=(2, 2)) + indices=((0, 0), (1, 0), (1, 1)), values=(1, 99, 0), dense_shape=(2, 2)) id_weight_pair = column.get_sparse_tensors( fc.FeatureTransformationCache({ 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - with self.assertRaisesRegexp( - errors.OpError, 'assert_less_than_num_buckets'): - id_weight_pair.id_tensor.eval() + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + with self.assertRaisesRegexp(errors.OpError, + 'assert_less_than_num_buckets'): + self.evaluate(id_weight_pair.id_tensor) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_default_value(self): column = fc.categorical_column_with_identity( key='aaa', num_buckets=4, default_value=3) @@ -5381,15 +5672,19 @@ class IdentityCategoricalColumnTest(test.TestCase): 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array((1, 3, 3), dtype=np.int64), - dense_shape=inputs.dense_shape), - id_weight_pair.id_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array((1, 3, 3), dtype=np.int64), + dense_shape=inputs.dense_shape), + self.evaluate(id_weight_pair.id_tensor)) + + @test_util.run_deprecated_v1 def test_get_sparse_tensors_with_default_value_and_placeholder_inputs(self): column = fc.categorical_column_with_identity( key='aaa', num_buckets=4, default_value=3) @@ -5397,14 +5692,15 @@ class IdentityCategoricalColumnTest(test.TestCase): input_values = array_ops.placeholder(dtype=dtypes.int32) input_shape = array_ops.placeholder(dtype=dtypes.int64) inputs = sparse_tensor.SparseTensorValue( - indices=input_indices, - values=input_values, - dense_shape=input_shape) + indices=input_indices, values=input_values, dense_shape=input_shape) id_weight_pair = column.get_sparse_tensors( fc.FeatureTransformationCache({ 'aaa': inputs }), None) self.assertIsNone(id_weight_pair.weight_tensor) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) with _initialized_session(): _assert_sparse_tensor_value( self, @@ -5412,12 +5708,14 @@ class IdentityCategoricalColumnTest(test.TestCase): indices=np.array(((0, 0), (1, 0), (1, 1)), dtype=np.int64), values=np.array((1, 3, 3), dtype=np.int64), dense_shape=np.array((2, 2), dtype=np.int64)), - id_weight_pair.id_tensor.eval(feed_dict={ - input_indices: ((0, 0), (1, 0), (1, 1)), - input_values: (1, -1, 99), - input_shape: (2, 2), - })) + id_weight_pair.id_tensor.eval( + feed_dict={ + input_indices: ((0, 0), (1, 0), (1, 1)), + input_values: (1, -1, 99), + input_shape: (2, 2), + })) + @test_util.run_deprecated_v1 def test_linear_model(self): column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) self.assertEqual(3, column.num_buckets) @@ -5431,14 +5729,17 @@ class IdentityCategoricalColumnTest(test.TestCase): dense_shape=(2, 2)) }) weight_var, bias = model.variables - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - weight_var.assign(((1.,), (2.,), (3.,))).eval() - # weight_var[0] = 1 - # weight_var[2] + weight_var[1] = 3+2 = 5 - self.assertAllClose(((1.,), (5.,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(weight_var.assign(((1.,), (2.,), (3.,)))) + # weight_var[0] = 1 + # weight_var[2] + weight_var[1] = 3+2 = 5 + self.assertAllClose(((1.,), (5.,)), self.evaluate(predictions)) def test_old_linear_model(self): column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) @@ -5453,15 +5754,19 @@ class IdentityCategoricalColumnTest(test.TestCase): }, (column,)) bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - weight_var.assign(((1.,), (2.,), (3.,))).eval() - # weight_var[0] = 1 - # weight_var[2] + weight_var[1] = 3+2 = 5 - self.assertAllClose(((1.,), (5.,)), predictions.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(weight_var.assign(((1.,), (2.,), (3.,)))) + # weight_var[0] = 1 + # weight_var[2] + weight_var[1] = 3+2 = 5 + self.assertAllClose(((1.,), (5.,)), self.evaluate(predictions)) + + @test_util.run_deprecated_v1 def test_serialization(self): column = fc.categorical_column_with_identity(key='aaa', num_buckets=3) @@ -5494,13 +5799,18 @@ class TransformFeaturesTest(test.TestCase): indices=[[0, 0], [1, 0], [1, 1]], dense_shape=[2, 2]) } - transformed = fc._transform_features( + transformed = fc._transform_features_v2( features, [bucketized_price, hashed_sparse], None) - with _initialized_session(): - self.assertIn(bucketized_price.name, transformed[bucketized_price].name) - self.assertAllEqual([[0], [3]], transformed[bucketized_price].eval()) - self.assertIn(hashed_sparse.name, transformed[hashed_sparse].name) - self.assertAllEqual([6, 4, 1], transformed[hashed_sparse].values.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertIn(bucketized_price.name, transformed[bucketized_price].name) + self.assertAllEqual([[0], [3]], + self.evaluate(transformed[bucketized_price])) + self.assertIn(hashed_sparse.name, transformed[hashed_sparse].name) + self.assertAllEqual([6, 4, 1], + self.evaluate(transformed[hashed_sparse].values)) def test_column_order(self): """When the column is both dense and sparse, uses sparse tensors.""" @@ -5531,12 +5841,12 @@ class TransformFeaturesTest(test.TestCase): column1 = _LoggerColumn('1') column2 = _LoggerColumn('2') call_logger = {'count': 0} - fc._transform_features({}, [column1, column2], None) + fc._transform_features_v2({}, [column1, column2], None) self.assertEqual(0, column1.call_order) self.assertEqual(1, column2.call_order) call_logger = {'count': 0} - fc._transform_features({}, [column2, column1], None) + fc._transform_features_v2({}, [column2, column1], None) self.assertEqual(0, column1.call_order) self.assertEqual(1, column2.call_order) @@ -5551,7 +5861,7 @@ class IndicatorColumnTest(test.TestCase): self.assertEqual(indicator_a.variable_shape, [1, 4]) self.assertTrue(indicator_a._is_v2_column) - b = fc_old.categorical_column_with_hash_bucket('b', hash_bucket_size=100) + b = fc_old._categorical_column_with_hash_bucket('b', hash_bucket_size=100) indicator_b = fc.indicator_column(b) self.assertEqual(indicator_b.categorical_column.name, 'b') self.assertEqual(indicator_b.name, 'b_indicator') @@ -5565,8 +5875,9 @@ class IndicatorColumnTest(test.TestCase): 'animal': ['fox', 'fox'] }) output = transformation_cache.get(animal, None) - with self.cached_session(): - self.assertAllEqual([[0., 0., 1., 0.], [0., 0., 1., 0.]], output.eval()) + + self.assertAllEqual([[0., 0., 1., 0.], [0., 0., 1., 0.]], + self.evaluate(output)) def test_2D_shape_succeeds(self): # TODO(ispir/cassandrax): Swith to categorical_column_with_keys when ready. @@ -5580,8 +5891,9 @@ class IndicatorColumnTest(test.TestCase): dense_shape=[2, 1]) }) output = transformation_cache.get(animal, None) - with self.cached_session(): - self.assertAllEqual([[0., 0., 1., 0.], [0., 0., 1., 0.]], output.eval()) + + self.assertAllEqual([[0., 0., 1., 0.], [0., 0., 1., 0.]], + self.evaluate(output)) def test_multi_hot(self): animal = fc.indicator_column( @@ -5593,8 +5905,8 @@ class IndicatorColumnTest(test.TestCase): indices=[[0, 0], [0, 1]], values=[1, 1], dense_shape=[1, 2]) }) output = transformation_cache.get(animal, None) - with self.cached_session(): - self.assertAllEqual([[0., 2., 0., 0.]], output.eval()) + + self.assertAllEqual([[0., 2., 0., 0.]], self.evaluate(output)) def test_multi_hot2(self): animal = fc.indicator_column( @@ -5605,9 +5917,10 @@ class IndicatorColumnTest(test.TestCase): indices=[[0, 0], [0, 1]], values=[1, 2], dense_shape=[1, 2]) }) output = transformation_cache.get(animal, None) - with self.cached_session(): - self.assertAllEqual([[0., 1., 1., 0.]], output.eval()) + self.assertAllEqual([[0., 1., 1., 0.]], self.evaluate(output)) + + @test_util.run_deprecated_v1 def test_deep_copy(self): a = fc.categorical_column_with_hash_bucket('a', 4) column = fc.indicator_column(a) @@ -5616,44 +5929,52 @@ class IndicatorColumnTest(test.TestCase): self.assertEqual(column.name, 'a_indicator') self.assertEqual(column.variable_shape, [1, 4]) + @test_util.run_deprecated_v1 def test_parse_example(self): a = fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) a_indicator = fc.indicator_column(a) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'aaa': - feature_pb2.Feature(bytes_list=feature_pb2.BytesList( - value=[b'omar', b'stringer'])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'aaa': + feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[b'omar', b'stringer'])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([a_indicator])) + features=fc.make_parse_example_spec_v2([a_indicator])) self.assertIn('aaa', features) - with self.cached_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([b'omar', b'stringer'], dtype=np.object_), - dense_shape=[1, 2]), - features['aaa'].eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([b'omar', b'stringer'], dtype=np.object_), + dense_shape=[1, 2]), self.evaluate(features['aaa'])) + + @test_util.run_deprecated_v1 def test_transform(self): a = fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) a_indicator = fc.indicator_column(a) features = { - 'aaa': sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=('marlo', 'skywalker', 'omar'), - dense_shape=(2, 2)) + 'aaa': + sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=('marlo', 'skywalker', 'omar'), + dense_shape=(2, 2)) } - indicator_tensor = fc._transform_features(features, [a_indicator], - None)[a_indicator] - with _initialized_session(): - self.assertAllEqual([[0, 0, 1], [1, 0, 0]], indicator_tensor.eval()) + indicator_tensor = fc._transform_features_v2(features, [a_indicator], + None)[a_indicator] + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual([[0, 0, 1], [1, 0, 0]], self.evaluate(indicator_tensor)) + @test_util.run_deprecated_v1 def test_transform_with_weighted_column(self): # Github issue 12557 ids = fc.categorical_column_with_vocabulary_list( @@ -5661,14 +5982,18 @@ class IndicatorColumnTest(test.TestCase): weights = fc.weighted_categorical_column(ids, 'weights') indicator = fc.indicator_column(weights) features = { - 'ids': constant_op.constant([['c', 'b', 'a']]), - 'weights': constant_op.constant([[2., 4., 6.]]) + 'ids': constant_op.constant([['c', 'b', 'a', 'c']]), + 'weights': constant_op.constant([[2., 4., 6., 1.]]) } - indicator_tensor = fc._transform_features(features, [indicator], - None)[indicator] - with _initialized_session(): - self.assertAllEqual([[6., 4., 2.]], indicator_tensor.eval()) + indicator_tensor = fc._transform_features_v2(features, [indicator], + None)[indicator] + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + self.assertAllEqual([[6., 4., 3.]], self.evaluate(indicator_tensor)) + + @test_util.run_deprecated_v1 def test_transform_with_missing_value_in_weighted_column(self): # Github issue 12583 ids = fc.categorical_column_with_vocabulary_list( @@ -5679,11 +6004,15 @@ class IndicatorColumnTest(test.TestCase): 'ids': constant_op.constant([['c', 'b', 'unknown']]), 'weights': constant_op.constant([[2., 4., 6.]]) } - indicator_tensor = fc._transform_features(features, [indicator], - None)[indicator] - with _initialized_session(): - self.assertAllEqual([[0., 4., 2.]], indicator_tensor.eval()) + indicator_tensor = fc._transform_features_v2(features, [indicator], + None)[indicator] + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + self.assertAllEqual([[0., 4., 2.]], self.evaluate(indicator_tensor)) + + @test_util.run_deprecated_v1 def test_transform_with_missing_value_in_categorical_column(self): # Github issue 12583 ids = fc.categorical_column_with_vocabulary_list( @@ -5692,11 +6021,15 @@ class IndicatorColumnTest(test.TestCase): features = { 'ids': constant_op.constant([['c', 'b', 'unknown']]), } - indicator_tensor = fc._transform_features(features, [indicator], - None)[indicator] - with _initialized_session(): - self.assertAllEqual([[0., 1., 1.]], indicator_tensor.eval()) + indicator_tensor = fc._transform_features_v2(features, [indicator], + None)[indicator] + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + self.assertAllEqual([[0., 1., 1.]], self.evaluate(indicator_tensor)) + + @test_util.run_deprecated_v1 def test_linear_model(self): animal = fc.indicator_column( fc.categorical_column_with_identity('animal', num_buckets=4)) @@ -5710,12 +6043,15 @@ class IndicatorColumnTest(test.TestCase): model = fc.LinearModel([animal]) predictions = model(features) weight_var, _ = model.variables - with _initialized_session(): - # All should be zero-initialized. - self.assertAllClose([[0.], [0.], [0.], [0.]], weight_var.eval()) - self.assertAllClose([[0.]], predictions.eval()) - weight_var.assign([[1.], [2.], [3.], [4.]]).eval() - self.assertAllClose([[2. + 3.]], predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + # All should be zero-initialized. + self.assertAllClose([[0.], [0.], [0.], [0.]], self.evaluate(weight_var)) + self.assertAllClose([[0.]], self.evaluate(predictions)) + self.evaluate(weight_var.assign([[1.], [2.], [3.], [4.]])) + self.assertAllClose([[2. + 3.]], self.evaluate(predictions)) def test_old_linear_model(self): animal = fc.indicator_column( @@ -5729,16 +6065,19 @@ class IndicatorColumnTest(test.TestCase): predictions = fc_old.linear_model(features, [animal]) weight_var = get_linear_model_column_var(animal) - with _initialized_session(): - # All should be zero-initialized. - self.assertAllClose([[0.], [0.], [0.], [0.]], weight_var.eval()) - self.assertAllClose([[0.]], predictions.eval()) - weight_var.assign([[1.], [2.], [3.], [4.]]).eval() - self.assertAllClose([[2. + 3.]], predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + # All should be zero-initialized. + self.assertAllClose([[0.], [0.], [0.], [0.]], self.evaluate(weight_var)) + self.assertAllClose([[0.]], self.evaluate(predictions)) + self.evaluate(weight_var.assign([[1.], [2.], [3.], [4.]])) + self.assertAllClose([[2. + 3.]], self.evaluate(predictions)) def test_old_linear_model_old_categorical(self): animal = fc.indicator_column( - fc_old.categorical_column_with_identity('animal', num_buckets=4)) + fc_old._categorical_column_with_identity('animal', num_buckets=4)) with ops.Graph().as_default(): features = { 'animal': @@ -5748,14 +6087,18 @@ class IndicatorColumnTest(test.TestCase): predictions = fc_old.linear_model(features, [animal]) weight_var = get_linear_model_column_var(animal) - with _initialized_session(): - # All should be zero-initialized. - self.assertAllClose([[0.], [0.], [0.], [0.]], weight_var.eval()) - self.assertAllClose([[0.]], predictions.eval()) - weight_var.assign([[1.], [2.], [3.], [4.]]).eval() - self.assertAllClose([[2. + 3.]], predictions.eval()) - - def test_feature_layer(self): + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + # All should be zero-initialized. + self.assertAllClose([[0.], [0.], [0.], [0.]], self.evaluate(weight_var)) + self.assertAllClose([[0.]], self.evaluate(predictions)) + self.evaluate(weight_var.assign([[1.], [2.], [3.], [4.]])) + self.assertAllClose([[2. + 3.]], self.evaluate(predictions)) + + @test_util.run_deprecated_v1 + def test_dense_features(self): animal = fc.indicator_column( fc.categorical_column_with_identity('animal', num_buckets=4)) with ops.Graph().as_default(): @@ -5764,10 +6107,14 @@ class IndicatorColumnTest(test.TestCase): sparse_tensor.SparseTensor( indices=[[0, 0], [0, 1]], values=[1, 2], dense_shape=[1, 2]) } - net = fc.FeatureLayer([animal])(features) - with _initialized_session(): - self.assertAllClose([[0., 1., 1., 0.]], net.eval()) + net = fc.DenseFeatures([animal])(features) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[0., 1., 1., 0.]], self.evaluate(net)) + + @test_util.run_deprecated_v1 def test_input_layer(self): animal = fc.indicator_column( fc.categorical_column_with_identity('animal', num_buckets=4)) @@ -5778,12 +6125,15 @@ class IndicatorColumnTest(test.TestCase): indices=[[0, 0], [0, 1]], values=[1, 2], dense_shape=[1, 2]) } net = fc_old.input_layer(features, [animal]) - with _initialized_session(): - self.assertAllClose([[0., 1., 1., 0.]], net.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[0., 1., 1., 0.]], self.evaluate(net)) def test_input_layer_old_categorical(self): animal = fc.indicator_column( - fc_old.categorical_column_with_identity('animal', num_buckets=4)) + fc_old._categorical_column_with_identity('animal', num_buckets=4)) with ops.Graph().as_default(): features = { 'animal': @@ -5791,9 +6141,13 @@ class IndicatorColumnTest(test.TestCase): indices=[[0, 0], [0, 1]], values=[1, 2], dense_shape=[1, 2]) } net = fc_old.input_layer(features, [animal]) - with _initialized_session(): - self.assertAllClose([[0., 1., 1., 0.]], net.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose([[0., 1., 1., 0.]], self.evaluate(net)) + + @test_util.run_deprecated_v1 def test_serialization(self): parent = fc.categorical_column_with_identity('animal', num_buckets=4) animal = fc.indicator_column(parent) @@ -5822,7 +6176,6 @@ class IndicatorColumnTest(test.TestCase): self.assertIs(parent, new_animal.categorical_column) - class _TestStateManager(fc.StateManager): def __init__(self, trainable=True): @@ -5864,6 +6217,7 @@ class _TestStateManager(fc.StateManager): class EmbeddingColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): categorical_column = fc.categorical_column_with_identity( key='aaa', num_buckets=3) @@ -5885,22 +6239,27 @@ class EmbeddingColumnTest(test.TestCase): self.assertTrue(embedding_column._is_v2_column) def test_is_v2_column(self): - categorical_column = fc_old.categorical_column_with_identity( + categorical_column = fc_old._categorical_column_with_identity( key='aaa', num_buckets=3) embedding_dimension = 2 embedding_column = fc.embedding_column( categorical_column, dimension=embedding_dimension) self.assertFalse(embedding_column._is_v2_column) + @test_util.run_deprecated_v1 def test_all_constructor_args(self): categorical_column = fc.categorical_column_with_identity( key='aaa', num_buckets=3) embedding_dimension = 2 embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, - combiner='my_combiner', initializer=lambda: 'my_initializer', - ckpt_to_load_from='my_ckpt', tensor_name_in_ckpt='my_ckpt_tensor', - max_norm=42., trainable=False) + categorical_column, + dimension=embedding_dimension, + combiner='my_combiner', + initializer=lambda: 'my_initializer', + ckpt_to_load_from='my_ckpt', + tensor_name_in_ckpt='my_ckpt_tensor', + max_norm=42., + trainable=False) self.assertIs(categorical_column, embedding_column.categorical_column) self.assertEqual(embedding_dimension, embedding_column.dimension) self.assertEqual('my_combiner', embedding_column.combiner) @@ -5914,15 +6273,20 @@ class EmbeddingColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column.parse_example_spec) + @test_util.run_deprecated_v1 def test_deep_copy(self): categorical_column = fc.categorical_column_with_identity( key='aaa', num_buckets=3) embedding_dimension = 2 original = fc.embedding_column( - categorical_column, dimension=embedding_dimension, - combiner='my_combiner', initializer=lambda: 'my_initializer', - ckpt_to_load_from='my_ckpt', tensor_name_in_ckpt='my_ckpt_tensor', - max_norm=42., trainable=False) + categorical_column, + dimension=embedding_dimension, + combiner='my_combiner', + initializer=lambda: 'my_initializer', + ckpt_to_load_from='my_ckpt', + tensor_name_in_ckpt='my_ckpt_tensor', + max_norm=42., + trainable=False) for embedding_column in (original, copy.deepcopy(original)): self.assertEqual('aaa', embedding_column.categorical_column.name) self.assertEqual(3, embedding_column.categorical_column.num_buckets) @@ -5942,51 +6306,60 @@ class EmbeddingColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column.parse_example_spec) + @test_util.run_deprecated_v1 def test_invalid_initializer(self): categorical_column = fc.categorical_column_with_identity( key='aaa', num_buckets=3) with self.assertRaisesRegexp(ValueError, 'initializer must be callable'): fc.embedding_column(categorical_column, dimension=2, initializer='not_fn') + @test_util.run_deprecated_v1 def test_parse_example(self): a = fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) a_embedded = fc.embedding_column(a, dimension=2) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'aaa': - feature_pb2.Feature(bytes_list=feature_pb2.BytesList( - value=[b'omar', b'stringer'])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'aaa': + feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[b'omar', b'stringer'])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([a_embedded])) + features=fc.make_parse_example_spec_v2([a_embedded])) self.assertIn('aaa', features) - with self.cached_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([b'omar', b'stringer'], dtype=np.object_), - dense_shape=[1, 2]), - features['aaa'].eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([b'omar', b'stringer'], dtype=np.object_), + dense_shape=[1, 2]), self.evaluate(features['aaa'])) + + @test_util.run_deprecated_v1 def test_transform_feature(self): a = fc.categorical_column_with_identity(key='aaa', num_buckets=3) a_embedded = fc.embedding_column(a, dimension=2) features = { - 'aaa': sparse_tensor.SparseTensor( - indices=((0, 0), (1, 0), (1, 1)), - values=(0, 1, 0), - dense_shape=(2, 2)) + 'aaa': + sparse_tensor.SparseTensor( + indices=((0, 0), (1, 0), (1, 1)), + values=(0, 1, 0), + dense_shape=(2, 2)) } - outputs = fc._transform_features(features, [a, a_embedded], None) + outputs = fc._transform_features_v2(features, [a, a_embedded], None) output_a = outputs[a] output_embedded = outputs[a_embedded] - with _initialized_session(): - _assert_sparse_tensor_value( - self, output_a.eval(), output_embedded.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value(self, self.evaluate(output_a), + self.evaluate(output_embedded)) + + @test_util.run_deprecated_v1 def test_get_dense_tensor(self): # Inputs. vocabulary_size = 3 @@ -6006,6 +6379,7 @@ class EmbeddingColumnTest(test.TestCase): (3., 5.), # id 1 (7., 11.) # id 2 ) + def _initializer(shape, dtype, partition_info): self.assertAllEqual((vocabulary_size, embedding_dimension), shape) self.assertEqual(dtypes.float32, dtype) @@ -6028,7 +6402,8 @@ class EmbeddingColumnTest(test.TestCase): categorical_column = fc.categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + categorical_column, + dimension=embedding_dimension, initializer=_initializer) state_manager = _TestStateManager() embedding_column.create_state(state_manager) @@ -6043,10 +6418,14 @@ class EmbeddingColumnTest(test.TestCase): global_vars = ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES) self.assertItemsEqual(('embedding_weights:0',), tuple([v.name for v in global_vars])) - with _initialized_session(): - self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, embedding_lookup.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual(embedding_values, self.evaluate(global_vars[0])) + self.assertAllEqual(expected_lookups, self.evaluate(embedding_lookup)) + + @test_util.run_deprecated_v1 def test_get_dense_tensor_old_categorical(self): # Inputs. vocabulary_size = 3 @@ -6086,7 +6465,7 @@ class EmbeddingColumnTest(test.TestCase): ) # Build columns. - categorical_column = fc_old.categorical_column_with_identity( + categorical_column = fc_old._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) embedding_column = fc.embedding_column( categorical_column, @@ -6103,10 +6482,14 @@ class EmbeddingColumnTest(test.TestCase): global_vars = ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES) self.assertItemsEqual(('embedding_weights:0',), tuple([v.name for v in global_vars])) - with _initialized_session(): - self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, embedding_lookup.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual(embedding_values, self.evaluate(global_vars[0])) + self.assertAllEqual(expected_lookups, self.evaluate(embedding_lookup)) + + @test_util.run_deprecated_v1 def test_get_dense_tensor_3d(self): # Inputs. vocabulary_size = 4 @@ -6122,11 +6505,12 @@ class EmbeddingColumnTest(test.TestCase): # Embedding variable. embedding_dimension = 3 embedding_values = ( - (1., 2., 4.), # id 0 - (3., 5., 1.), # id 1 + (1., 2., 4.), # id 0 + (3., 5., 1.), # id 1 (7., 11., 2.), # id 2 - (2., 7., 12.) # id 3 + (2., 7., 12.) # id 3 ) + def _initializer(shape, dtype, partition_info): self.assertAllEqual((vocabulary_size, embedding_dimension), shape) self.assertEqual(dtypes.float32, dtype) @@ -6150,7 +6534,8 @@ class EmbeddingColumnTest(test.TestCase): categorical_column = fc.categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + categorical_column, + dimension=embedding_dimension, initializer=_initializer) state_manager = _TestStateManager() embedding_column.create_state(state_manager) @@ -6165,10 +6550,14 @@ class EmbeddingColumnTest(test.TestCase): global_vars = ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES) self.assertItemsEqual(('embedding_weights:0',), tuple([v.name for v in global_vars])) - with _initialized_session(): - self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, embedding_lookup.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual(embedding_values, self.evaluate(global_vars[0])) + self.assertAllEqual(expected_lookups, self.evaluate(embedding_lookup)) + + @test_util.run_deprecated_v1 def test_get_dense_tensor_placeholder_inputs(self): # Inputs. vocabulary_size = 3 @@ -6188,6 +6577,7 @@ class EmbeddingColumnTest(test.TestCase): (3., 5.), # id 1 (7., 11.) # id 2 ) + def _initializer(shape, dtype, partition_info): self.assertAllEqual((vocabulary_size, embedding_dimension), shape) self.assertEqual(dtypes.float32, dtype) @@ -6210,7 +6600,8 @@ class EmbeddingColumnTest(test.TestCase): categorical_column = fc.categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + categorical_column, + dimension=embedding_dimension, initializer=_initializer) state_manager = _TestStateManager() embedding_column.create_state(state_manager) @@ -6230,17 +6621,23 @@ class EmbeddingColumnTest(test.TestCase): # Assert expected embedding variable and lookups. global_vars = ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES) - self.assertItemsEqual( - ('embedding_weights:0',), tuple([v.name for v in global_vars])) + self.assertItemsEqual(('embedding_weights:0',), + tuple([v.name for v in global_vars])) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) with _initialized_session(): - self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, embedding_lookup.eval( - feed_dict={ - input_indices: sparse_input.indices, - input_values: sparse_input.values, - input_shape: sparse_input.dense_shape, - })) + self.assertAllEqual(embedding_values, self.evaluate(global_vars[0])) + self.assertAllEqual( + expected_lookups, + embedding_lookup.eval( + feed_dict={ + input_indices: sparse_input.indices, + input_values: sparse_input.values, + input_shape: sparse_input.dense_shape, + })) + @test_util.run_deprecated_v1 def test_get_dense_tensor_restore_from_ckpt(self): # Inputs. vocabulary_size = 3 @@ -6280,7 +6677,8 @@ class EmbeddingColumnTest(test.TestCase): categorical_column = fc.categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) embedding_column = fc.embedding_column( - categorical_column, dimension=embedding_dimension, + categorical_column, + dimension=embedding_dimension, ckpt_to_load_from=ckpt_path, tensor_name_in_ckpt=ckpt_tensor) state_manager = _TestStateManager() @@ -6294,12 +6692,16 @@ class EmbeddingColumnTest(test.TestCase): # Assert expected embedding variable and lookups. global_vars = ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES) - self.assertItemsEqual( - ('embedding_weights:0',), tuple([v.name for v in global_vars])) - with _initialized_session(): - self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, embedding_lookup.eval()) + self.assertItemsEqual(('embedding_weights:0',), + tuple([v.name for v in global_vars])) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual(embedding_values, self.evaluate(global_vars[0])) + self.assertAllEqual(expected_lookups, self.evaluate(embedding_lookup)) + + @test_util.run_deprecated_v1 def test_linear_model(self): # Inputs. batch_size = 4 @@ -6317,6 +6719,7 @@ class EmbeddingColumnTest(test.TestCase): embedding_dimension = 2 embedding_shape = (vocabulary_size, embedding_dimension) zeros_embedding_values = np.zeros(embedding_shape) + def _initializer(shape, dtype, partition_info): self.assertAllEqual(embedding_shape, shape) self.assertEqual(dtypes.float32, dtype) @@ -6343,39 +6746,45 @@ class EmbeddingColumnTest(test.TestCase): expected_var_names, [v.name for v in ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)]) trainable_vars = { - v.name: v for v in ops.get_collection( - ops.GraphKeys.TRAINABLE_VARIABLES) + v.name: v + for v in ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES) } self.assertItemsEqual(expected_var_names, trainable_vars.keys()) bias = trainable_vars['linear_model/bias_weights:0'] embedding_weights = trainable_vars[ 'linear_model/aaa_embedding/embedding_weights:0'] - linear_weights = trainable_vars[ - 'linear_model/aaa_embedding/weights:0'] - with _initialized_session(): - # Predictions with all zero weights. - self.assertAllClose(np.zeros((1,)), bias.eval()) - self.assertAllClose(zeros_embedding_values, embedding_weights.eval()) - self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights.eval()) - self.assertAllClose(np.zeros((batch_size, 1)), predictions.eval()) - - # Predictions with all non-zero weights. - embedding_weights.assign(( - (1., 2.), # id 0 - (3., 5.), # id 1 - (7., 11.) # id 2 - )).eval() - linear_weights.assign(((4.,), (6.,))).eval() - # example 0, ids [2], embedding[0] = [7, 11] - # example 1, ids [0, 1], embedding[1] = mean([1, 2] + [3, 5]) = [2, 3.5] - # example 2, ids [], embedding[2] = [0, 0] - # example 3, ids [1], embedding[3] = [3, 5] - # sum(embeddings * linear_weights) - # = [4*7 + 6*11, 4*2 + 6*3.5, 4*0 + 6*0, 4*3 + 6*5] = [94, 29, 0, 42] - self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), predictions.eval()) - - def test_feature_layer(self): + linear_weights = trainable_vars['linear_model/aaa_embedding/weights:0'] + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + # Predictions with all zero weights. + self.assertAllClose(np.zeros((1,)), self.evaluate(bias)) + self.assertAllClose(zeros_embedding_values, + self.evaluate(embedding_weights)) + self.assertAllClose( + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights)) + self.assertAllClose(np.zeros((batch_size, 1)), self.evaluate(predictions)) + + # Predictions with all non-zero weights. + self.evaluate( + embedding_weights.assign(( + (1., 2.), # id 0 + (3., 5.), # id 1 + (7., 11.) # id 2 + ))) + self.evaluate(linear_weights.assign(((4.,), (6.,)))) + # example 0, ids [2], embedding[0] = [7, 11] + # example 1, ids [0, 1], embedding[1] = mean([1, 2] + [3, 5]) = [2, 3.5] + # example 2, ids [], embedding[2] = [0, 0] + # example 3, ids [1], embedding[3] = [3, 5] + # sum(embeddings * linear_weights) + # = [4*7 + 6*11, 4*2 + 6*3.5, 4*0 + 6*0, 4*3 + 6*5] = [94, 29, 0, 42] + self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), + self.evaluate(predictions)) + + @test_util.run_deprecated_v1 + def test_dense_features(self): # Inputs. vocabulary_size = 3 sparse_input = sparse_tensor.SparseTensorValue( @@ -6394,6 +6803,7 @@ class EmbeddingColumnTest(test.TestCase): (3., 5.), # id 1 (7., 11.) # id 2 ) + def _initializer(shape, dtype, partition_info): self.assertAllEqual((vocabulary_size, embedding_dimension), shape) self.assertEqual(dtypes.float32, dtype) @@ -6421,23 +6831,27 @@ class EmbeddingColumnTest(test.TestCase): initializer=_initializer) # Provide sparse input and get dense result. - l = fc.FeatureLayer((embedding_column,)) - feature_layer = l({'aaa': sparse_input}) + l = fc.DenseFeatures((embedding_column,)) + dense_features = l({'aaa': sparse_input}) # Assert expected embedding variable and lookups. global_vars = ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES) - self.assertItemsEqual(('feature_layer/aaa_embedding/embedding_weights:0',), + self.assertItemsEqual(('dense_features/aaa_embedding/embedding_weights:0',), tuple([v.name for v in global_vars])) for v in global_vars: self.assertTrue(isinstance(v, variables_lib.RefVariable)) trainable_vars = ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES) - self.assertItemsEqual(('feature_layer/aaa_embedding/embedding_weights:0',), + self.assertItemsEqual(('dense_features/aaa_embedding/embedding_weights:0',), tuple([v.name for v in trainable_vars])) - with _initialized_session(): - self.assertAllEqual(embedding_values, trainable_vars[0].eval()) - self.assertAllEqual(expected_lookups, feature_layer.eval()) - def test_feature_layer_not_trainable(self): + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual(embedding_values, self.evaluate(trainable_vars[0])) + self.assertAllEqual(expected_lookups, self.evaluate(dense_features)) + + @test_util.run_deprecated_v1 + def test_dense_features_not_trainable(self): # Inputs. vocabulary_size = 3 sparse_input = sparse_tensor.SparseTensorValue( @@ -6456,6 +6870,7 @@ class EmbeddingColumnTest(test.TestCase): (3., 5.), # id 1 (7., 11.) # id 2 ) + def _initializer(shape, dtype, partition_info): self.assertAllEqual((vocabulary_size, embedding_dimension), shape) self.assertEqual(dtypes.float32, dtype) @@ -6484,18 +6899,24 @@ class EmbeddingColumnTest(test.TestCase): trainable=False) # Provide sparse input and get dense result. - feature_layer = fc.FeatureLayer((embedding_column,))({'aaa': sparse_input}) + dense_features = fc.DenseFeatures((embedding_column,))({ + 'aaa': sparse_input + }) # Assert expected embedding variable and lookups. global_vars = ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES) - self.assertItemsEqual(('feature_layer/aaa_embedding/embedding_weights:0',), + self.assertItemsEqual(('dense_features/aaa_embedding/embedding_weights:0',), tuple([v.name for v in global_vars])) - self.assertItemsEqual( - [], ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES)) - with _initialized_session(): - self.assertAllEqual(embedding_values, global_vars[0].eval()) - self.assertAllEqual(expected_lookups, feature_layer.eval()) + self.assertItemsEqual([], + ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES)) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual(embedding_values, self.evaluate(global_vars[0])) + self.assertAllEqual(expected_lookups, self.evaluate(dense_features)) + @test_util.run_deprecated_v1 def test_input_layer(self): # Inputs. vocabulary_size = 3 @@ -6554,9 +6975,12 @@ class EmbeddingColumnTest(test.TestCase): trainable_vars = ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES) self.assertItemsEqual(('input_layer/aaa_embedding/embedding_weights:0',), tuple([v.name for v in trainable_vars])) - with _initialized_session(): - self.assertAllEqual(embedding_values, trainable_vars[0].eval()) - self.assertAllEqual(expected_lookups, feature_layer.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual(embedding_values, self.evaluate(trainable_vars[0])) + self.assertAllEqual(expected_lookups, self.evaluate(feature_layer)) def test_old_linear_model(self): # Inputs. @@ -6611,28 +7035,34 @@ class EmbeddingColumnTest(test.TestCase): embedding_weights = trainable_vars[ 'linear_model/aaa_embedding/embedding_weights:0'] linear_weights = trainable_vars['linear_model/aaa_embedding/weights:0'] - with _initialized_session(): - # Predictions with all zero weights. - self.assertAllClose(np.zeros((1,)), bias.eval()) - self.assertAllClose(zeros_embedding_values, embedding_weights.eval()) - self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights.eval()) - self.assertAllClose(np.zeros((batch_size, 1)), predictions.eval()) - - # Predictions with all non-zero weights. - embedding_weights.assign(( - (1., 2.), # id 0 - (3., 5.), # id 1 - (7., 11.) # id 2 - )).eval() - linear_weights.assign(((4.,), (6.,))).eval() - # example 0, ids [2], embedding[0] = [7, 11] - # example 1, ids [0, 1], embedding[1] = mean([1, 2] + [3, 5]) = [2, 3.5] - # example 2, ids [], embedding[2] = [0, 0] - # example 3, ids [1], embedding[3] = [3, 5] - # sum(embeddings * linear_weights) - # = [4*7 + 6*11, 4*2 + 6*3.5, 4*0 + 6*0, 4*3 + 6*5] = [94, 29, 0, 42] - self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + # Predictions with all zero weights. + self.assertAllClose(np.zeros((1,)), self.evaluate(bias)) + self.assertAllClose(zeros_embedding_values, + self.evaluate(embedding_weights)) + self.assertAllClose( + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights)) + self.assertAllClose(np.zeros((batch_size, 1)), self.evaluate(predictions)) + + # Predictions with all non-zero weights. + self.evaluate( + embedding_weights.assign(( + (1., 2.), # id 0 + (3., 5.), # id 1 + (7., 11.) # id 2 + ))) + self.evaluate(linear_weights.assign(((4.,), (6.,)))) + # example 0, ids [2], embedding[0] = [7, 11] + # example 1, ids [0, 1], embedding[1] = mean([1, 2] + [3, 5]) = [2, 3.5] + # example 2, ids [], embedding[2] = [0, 0] + # example 3, ids [1], embedding[3] = [3, 5] + # sum(embeddings * linear_weights) + # = [4*7 + 6*11, 4*2 + 6*3.5, 4*0 + 6*0, 4*3 + 6*5] = [94, 29, 0, 42] + self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), + self.evaluate(predictions)) def test_old_linear_model_old_categorical(self): # Inputs. @@ -6659,7 +7089,7 @@ class EmbeddingColumnTest(test.TestCase): return zeros_embedding_values # Build columns. - categorical_column = fc_old.categorical_column_with_identity( + categorical_column = fc_old._categorical_column_with_identity( key='aaa', num_buckets=vocabulary_size) embedding_column = fc.embedding_column( categorical_column, @@ -6687,29 +7117,36 @@ class EmbeddingColumnTest(test.TestCase): embedding_weights = trainable_vars[ 'linear_model/aaa_embedding/embedding_weights:0'] linear_weights = trainable_vars['linear_model/aaa_embedding/weights:0'] - with _initialized_session(): - # Predictions with all zero weights. - self.assertAllClose(np.zeros((1,)), bias.eval()) - self.assertAllClose(zeros_embedding_values, embedding_weights.eval()) - self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights.eval()) - self.assertAllClose(np.zeros((batch_size, 1)), predictions.eval()) - - # Predictions with all non-zero weights. - embedding_weights.assign(( - (1., 2.), # id 0 - (3., 5.), # id 1 - (7., 11.) # id 2 - )).eval() - linear_weights.assign(((4.,), (6.,))).eval() - # example 0, ids [2], embedding[0] = [7, 11] - # example 1, ids [0, 1], embedding[1] = mean([1, 2] + [3, 5]) = [2, 3.5] - # example 2, ids [], embedding[2] = [0, 0] - # example 3, ids [1], embedding[3] = [3, 5] - # sum(embeddings * linear_weights) - # = [4*7 + 6*11, 4*2 + 6*3.5, 4*0 + 6*0, 4*3 + 6*5] = [94, 29, 0, 42] - self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), predictions.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + # Predictions with all zero weights. + self.assertAllClose(np.zeros((1,)), self.evaluate(bias)) + self.assertAllClose(zeros_embedding_values, + self.evaluate(embedding_weights)) + self.assertAllClose( + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights)) + self.assertAllClose(np.zeros((batch_size, 1)), self.evaluate(predictions)) + + # Predictions with all non-zero weights. + self.evaluate( + embedding_weights.assign(( + (1., 2.), # id 0 + (3., 5.), # id 1 + (7., 11.) # id 2 + ))) + self.evaluate(linear_weights.assign(((4.,), (6.,)))) + # example 0, ids [2], embedding[0] = [7, 11] + # example 1, ids [0, 1], embedding[1] = mean([1, 2] + [3, 5]) = [2, 3.5] + # example 2, ids [], embedding[2] = [0, 0] + # example 3, ids [1], embedding[3] = [3, 5] + # sum(embeddings * linear_weights) + # = [4*7 + 6*11, 4*2 + 6*3.5, 4*0 + 6*0, 4*3 + 6*5] = [94, 29, 0, 42] + self.assertAllClose(((94.,), (29.,), (0.,), (42.,)), + self.evaluate(predictions)) + + @test_util.run_deprecated_v1 def test_serialization(self): def _initializer(shape, dtype, partition_info): @@ -6763,6 +7200,7 @@ class EmbeddingColumnTest(test.TestCase): class SharedEmbeddingColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) @@ -6787,6 +7225,7 @@ class SharedEmbeddingColumnTest(test.TestCase): 'bbb': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column_b.parse_example_spec) + @test_util.run_deprecated_v1 def test_all_constructor_args(self): categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) @@ -6818,6 +7257,7 @@ class SharedEmbeddingColumnTest(test.TestCase): 'bbb': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column_b.parse_example_spec) + @test_util.run_deprecated_v1 def test_deep_copy(self): categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) @@ -6849,6 +7289,7 @@ class SharedEmbeddingColumnTest(test.TestCase): 'aaa': parsing_ops.VarLenFeature(dtypes.int64) }, embedding_column_a.parse_example_spec) + @test_util.run_deprecated_v1 def test_invalid_initializer(self): categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) @@ -6860,6 +7301,7 @@ class SharedEmbeddingColumnTest(test.TestCase): dimension=2, initializer='not_fn') + @test_util.run_deprecated_v1 def test_incompatible_column_type(self): categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) @@ -6874,6 +7316,7 @@ class SharedEmbeddingColumnTest(test.TestCase): [categorical_column_a, categorical_column_b, categorical_column_c], dimension=2) + @test_util.run_deprecated_v1 def test_weighted_categorical_column_ok(self): categorical_column_a = fc.categorical_column_with_identity( key='aaa', num_buckets=3) @@ -6891,82 +7334,90 @@ class SharedEmbeddingColumnTest(test.TestCase): [weighted_categorical_column_a, weighted_categorical_column_b], dimension=2) + @test_util.run_deprecated_v1 def test_parse_example(self): a = fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) b = fc.categorical_column_with_vocabulary_list( key='bbb', vocabulary_list=('omar', 'stringer', 'marlo')) a_embedded, b_embedded = fc.shared_embedding_columns_v2([a, b], dimension=2) - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'aaa': - feature_pb2.Feature(bytes_list=feature_pb2.BytesList( - value=[b'omar', b'stringer'])), - 'bbb': - feature_pb2.Feature(bytes_list=feature_pb2.BytesList( - value=[b'stringer', b'marlo'])), - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'aaa': + feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[b'omar', b'stringer'])), + 'bbb': + feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[b'stringer', b'marlo'])), + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([a_embedded, b_embedded])) + features=fc.make_parse_example_spec_v2([a_embedded, b_embedded])) self.assertIn('aaa', features) self.assertIn('bbb', features) - with self.cached_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([b'omar', b'stringer'], dtype=np.object_), - dense_shape=[1, 2]), - features['aaa'].eval()) - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([b'stringer', b'marlo'], dtype=np.object_), - dense_shape=[1, 2]), - features['bbb'].eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([b'omar', b'stringer'], dtype=np.object_), + dense_shape=[1, 2]), self.evaluate(features['aaa'])) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([b'stringer', b'marlo'], dtype=np.object_), + dense_shape=[1, 2]), self.evaluate(features['bbb'])) + + @test_util.run_deprecated_v1 def test_transform_feature(self): a = fc.categorical_column_with_identity(key='aaa', num_buckets=3) b = fc.categorical_column_with_identity(key='bbb', num_buckets=3) a_embedded, b_embedded = fc.shared_embedding_columns_v2([a, b], dimension=2) features = { - 'aaa': sparse_tensor.SparseTensor( - indices=((0, 0), (1, 0), (1, 1)), - values=(0, 1, 0), - dense_shape=(2, 2)), - 'bbb': sparse_tensor.SparseTensor( - indices=((0, 0), (1, 0), (1, 1)), - values=(1, 2, 1), - dense_shape=(2, 2)), + 'aaa': + sparse_tensor.SparseTensor( + indices=((0, 0), (1, 0), (1, 1)), + values=(0, 1, 0), + dense_shape=(2, 2)), + 'bbb': + sparse_tensor.SparseTensor( + indices=((0, 0), (1, 0), (1, 1)), + values=(1, 2, 1), + dense_shape=(2, 2)), } - outputs = fc._transform_features(features, [a, a_embedded, b, b_embedded], - None) + outputs = fc._transform_features_v2(features, + [a, a_embedded, b, b_embedded], None) output_a = outputs[a] output_a_embedded = outputs[a_embedded] output_b = outputs[b] output_b_embedded = outputs[b_embedded] - with _initialized_session(): - _assert_sparse_tensor_value( - self, output_a.eval(), output_a_embedded.eval()) - _assert_sparse_tensor_value( - self, output_b.eval(), output_b_embedded.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value(self, self.evaluate(output_a), + self.evaluate(output_a_embedded)) + _assert_sparse_tensor_value(self, self.evaluate(output_b), + self.evaluate(output_b_embedded)) + + @test_util.run_deprecated_v1 def test_get_dense_tensor(self): # Inputs. vocabulary_size = 3 # -1 values are ignored. - input_a = np.array( - [[2, -1, -1], # example 0, ids [2] - [0, 1, -1]]) # example 1, ids [0, 1] - input_b = np.array( - [[0, -1, -1], # example 0, ids [0] - [-1, -1, -1]]) # example 1, ids [] - input_features = { - 'aaa': input_a, - 'bbb': input_b - } + input_a = np.array([ + [2, -1, -1], # example 0, ids [2] + [0, 1, -1] + ]) # example 1, ids [0, 1] + input_b = np.array([ + [0, -1, -1], # example 0, ids [0] + [-1, -1, -1] + ]) # example 1, ids [] + input_features = {'aaa': input_a, 'bbb': input_b} # Embedding variable. embedding_dimension = 2 @@ -6975,6 +7426,7 @@ class SharedEmbeddingColumnTest(test.TestCase): (3., 5.), # id 1 (7., 11.) # id 2 ) + def _initializer(shape, dtype, partition_info): self.assertAllEqual((vocabulary_size, embedding_dimension), shape) self.assertEqual(dtypes.float32, dtype) @@ -7016,21 +7468,27 @@ class SharedEmbeddingColumnTest(test.TestCase): self.assertItemsEqual(('aaa_bbb_shared_embedding:0',), tuple([v.name for v in global_vars])) embedding_var = global_vars[0] - with _initialized_session(): - self.assertAllEqual(embedding_values, embedding_var.eval()) - self.assertAllEqual(expected_lookups_a, embedding_lookup_a.eval()) - self.assertAllEqual(expected_lookups_b, embedding_lookup_b.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual(embedding_values, self.evaluate(embedding_var)) + self.assertAllEqual(expected_lookups_a, self.evaluate(embedding_lookup_a)) + self.assertAllEqual(expected_lookups_b, self.evaluate(embedding_lookup_b)) + + @test_util.run_deprecated_v1 def test_get_dense_tensor_placeholder_inputs(self): # Inputs. vocabulary_size = 3 # -1 values are ignored. - input_a = np.array( - [[2, -1, -1], # example 0, ids [2] - [0, 1, -1]]) # example 1, ids [0, 1] - input_b = np.array( - [[0, -1, -1], # example 0, ids [0] - [-1, -1, -1]]) # example 1, ids [] + input_a = np.array([ + [2, -1, -1], # example 0, ids [2] + [0, 1, -1] + ]) # example 1, ids [0, 1] + input_b = np.array([ + [0, -1, -1], # example 0, ids [0] + [-1, -1, -1] + ]) # example 1, ids [] # Specify shape, because dense input must have rank specified. input_a_placeholder = array_ops.placeholder( dtype=dtypes.int64, shape=[None, 3]) @@ -7052,6 +7510,7 @@ class SharedEmbeddingColumnTest(test.TestCase): (3., 5.), # id 1 (7., 11.) # id 2 ) + def _initializer(shape, dtype, partition_info): self.assertAllEqual((vocabulary_size, embedding_dimension), shape) self.assertEqual(dtypes.float32, dtype) @@ -7077,22 +7536,26 @@ class SharedEmbeddingColumnTest(test.TestCase): with _initialized_session() as sess: sess.run([embedding_lookup_a, embedding_lookup_b], feed_dict=feed_dict) + @test_util.run_deprecated_v1 def test_linear_model(self): # Inputs. batch_size = 2 vocabulary_size = 3 # -1 values are ignored. - input_a = np.array( - [[2, -1, -1], # example 0, ids [2] - [0, 1, -1]]) # example 1, ids [0, 1] - input_b = np.array( - [[0, -1, -1], # example 0, ids [0] - [-1, -1, -1]]) # example 1, ids [] + input_a = np.array([ + [2, -1, -1], # example 0, ids [2] + [0, 1, -1] + ]) # example 1, ids [0, 1] + input_b = np.array([ + [0, -1, -1], # example 0, ids [0] + [-1, -1, -1] + ]) # example 1, ids [] # Embedding variable. embedding_dimension = 2 embedding_shape = (vocabulary_size, embedding_dimension) zeros_embedding_values = np.zeros(embedding_shape) + def _initializer(shape, dtype, partition_info): self.assertAllEqual(embedding_shape, shape) self.assertEqual(dtypes.float32, dtype) @@ -7128,8 +7591,8 @@ class SharedEmbeddingColumnTest(test.TestCase): expected_var_names, [v.name for v in ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)]) trainable_vars = { - v.name: v for v in ops.get_collection( - ops.GraphKeys.TRAINABLE_VARIABLES) + v.name: v + for v in ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES) } self.assertItemsEqual(expected_var_names, trainable_vars.keys()) bias = trainable_vars['linear_model/bias_weights:0'] @@ -7138,35 +7601,40 @@ class SharedEmbeddingColumnTest(test.TestCase): 'linear_model/aaa_shared_embedding/weights:0'] linear_weights_b = trainable_vars[ 'linear_model/bbb_shared_embedding/weights:0'] - with _initialized_session(): - # Predictions with all zero weights. - self.assertAllClose(np.zeros((1,)), bias.eval()) - self.assertAllClose(zeros_embedding_values, embedding_weights.eval()) - self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights_a.eval()) - self.assertAllClose( - np.zeros((embedding_dimension, 1)), linear_weights_b.eval()) - self.assertAllClose(np.zeros((batch_size, 1)), predictions.eval()) - - # Predictions with all non-zero weights. - embedding_weights.assign(( - (1., 2.), # id 0 - (3., 5.), # id 1 - (7., 11.) # id 2 - )).eval() - linear_weights_a.assign(((4.,), (6.,))).eval() - # example 0, ids [2], embedding[0] = [7, 11] - # example 1, ids [0, 1], embedding[1] = mean([1, 2] + [3, 5]) = [2, 3.5] - # sum(embeddings * linear_weights) - # = [4*7 + 6*11, 4*2 + 6*3.5] = [94, 29] - linear_weights_b.assign(((3.,), (5.,))).eval() - # example 0, ids [0], embedding[0] = [1, 2] - # example 1, ids [], embedding[1] = 0, 0] - # sum(embeddings * linear_weights) - # = [3*1 + 5*2, 3*0 +5*0] = [13, 0] - self.assertAllClose([[94. + 13.], [29.]], predictions.eval()) - - def _test_feature_layer(self, trainable=True): + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + # Predictions with all zero weights. + self.assertAllClose(np.zeros((1,)), self.evaluate(bias)) + self.assertAllClose(zeros_embedding_values, + self.evaluate(embedding_weights)) + self.assertAllClose( + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights_a)) + self.assertAllClose( + np.zeros((embedding_dimension, 1)), self.evaluate(linear_weights_b)) + self.assertAllClose(np.zeros((batch_size, 1)), self.evaluate(predictions)) + + # Predictions with all non-zero weights. + self.evaluate( + embedding_weights.assign(( + (1., 2.), # id 0 + (3., 5.), # id 1 + (7., 11.) # id 2 + ))) + self.evaluate(linear_weights_a.assign(((4.,), (6.,)))) + # example 0, ids [2], embedding[0] = [7, 11] + # example 1, ids [0, 1], embedding[1] = mean([1, 2] + [3, 5]) = [2, 3.5] + # sum(embeddings * linear_weights) + # = [4*7 + 6*11, 4*2 + 6*3.5] = [94, 29] + self.evaluate(linear_weights_b.assign(((3.,), (5.,)))) + # example 0, ids [0], embedding[0] = [1, 2] + # example 1, ids [], embedding[1] = 0, 0] + # sum(embeddings * linear_weights) + # = [3*1 + 5*2, 3*0 +5*0] = [13, 0] + self.assertAllClose([[94. + 13.], [29.]], self.evaluate(predictions)) + + def _test_dense_features(self, trainable=True): # Inputs. vocabulary_size = 3 sparse_input_a = sparse_tensor.SparseTensorValue( @@ -7201,6 +7669,7 @@ class SharedEmbeddingColumnTest(test.TestCase): (3., 5.), # id 1 (7., 11.) # id 2 ) + def _initializer(shape, dtype, partition_info): self.assertAllEqual((vocabulary_size, embedding_dimension), shape) self.assertEqual(dtypes.float32, dtype) @@ -7252,7 +7721,7 @@ class SharedEmbeddingColumnTest(test.TestCase): } # Provide sparse input and get dense result. - feature_layer = fc.FeatureLayer( + dense_features = fc.DenseFeatures( feature_columns=(embedding_column_b, embedding_column_a, embedding_column_c, embedding_column_d))( features) @@ -7272,16 +7741,23 @@ class SharedEmbeddingColumnTest(test.TestCase): else: self.assertItemsEqual([], tuple([v.name for v in trainable_vars])) shared_embedding_vars = global_vars - with _initialized_session(): - self.assertAllEqual(embedding_values, shared_embedding_vars[0].eval()) - self.assertAllEqual(expected_lookups, feature_layer.eval()) - def test_feature_layer(self): - self._test_feature_layer() + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllEqual(embedding_values, + self.evaluate(shared_embedding_vars[0])) + self.assertAllEqual(expected_lookups, self.evaluate(dense_features)) + + @test_util.run_deprecated_v1 + def test_dense_features(self): + self._test_dense_features() - def test_feature_layer_no_trainable(self): - self._test_feature_layer(trainable=False) + @test_util.run_deprecated_v1 + def test_dense_features_no_trainable(self): + self._test_dense_features(trainable=False) + @test_util.run_deprecated_v1 def test_serialization(self): def _initializer(shape, dtype, partition_info): @@ -7302,9 +7778,9 @@ class SharedEmbeddingColumnTest(test.TestCase): # TODO(rohanj): Add tests for (from|get)_config once implemented - class WeightedCategoricalColumnTest(test.TestCase): + @test_util.run_deprecated_v1 def test_defaults(self): column = fc.weighted_categorical_column( categorical_column=fc.categorical_column_with_identity( @@ -7320,11 +7796,12 @@ class WeightedCategoricalColumnTest(test.TestCase): def test_is_v2_column(self): column = fc.weighted_categorical_column( - categorical_column=fc_old.categorical_column_with_identity( + categorical_column=fc_old._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') self.assertFalse(column._is_v2_column) + @test_util.run_deprecated_v1 def test_deep_copy(self): """Tests deepcopy of categorical_column_with_hash_bucket.""" original = fc.weighted_categorical_column( @@ -7365,7 +7842,7 @@ class WeightedCategoricalColumnTest(test.TestCase): values=('omar', 'stringer', 'marlo'), dense_shape=(2, 2)) with self.assertRaisesRegexp(ValueError, 'Bad dtype'): - fc._transform_features({ + fc._transform_features_v2({ 'ids': strings, 'values': strings }, (column,), None) @@ -7386,77 +7863,79 @@ class WeightedCategoricalColumnTest(test.TestCase): indices=((0, 0), (1, 0), (1, 1)), values=('omar', 'stringer', 'marlo'), dense_shape=(2, 2)) - with self.assertRaisesRegexp( - ValueError, 'values is not in features dictionary'): - fc._transform_features({'ids': inputs}, (column,), None) + with self.assertRaisesRegexp(ValueError, + 'values is not in features dictionary'): + fc._transform_features_v2({'ids': inputs}, (column,), None) + @test_util.run_deprecated_v1 def test_parse_example(self): a = fc.categorical_column_with_vocabulary_list( key='aaa', vocabulary_list=('omar', 'stringer', 'marlo')) a_weighted = fc.weighted_categorical_column(a, weight_feature_key='weights') - data = example_pb2.Example(features=feature_pb2.Features( - feature={ - 'aaa': - feature_pb2.Feature(bytes_list=feature_pb2.BytesList( - value=[b'omar', b'stringer'])), - 'weights': - feature_pb2.Feature(float_list=feature_pb2.FloatList( - value=[1., 10.])) - })) + data = example_pb2.Example( + features=feature_pb2.Features( + feature={ + 'aaa': + feature_pb2.Feature( + bytes_list=feature_pb2.BytesList( + value=[b'omar', b'stringer'])), + 'weights': + feature_pb2.Feature( + float_list=feature_pb2.FloatList(value=[1., 10.])) + })) features = parsing_ops.parse_example( serialized=[data.SerializeToString()], - features=fc.make_parse_example_spec([a_weighted])) + features=fc.make_parse_example_spec_v2([a_weighted])) self.assertIn('aaa', features) self.assertIn('weights', features) - with self.cached_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([b'omar', b'stringer'], dtype=np.object_), - dense_shape=[1, 2]), - features['aaa'].eval()) - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=[[0, 0], [0, 1]], - values=np.array([1., 10.], dtype=np.float32), - dense_shape=[1, 2]), - features['weights'].eval()) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([b'omar', b'stringer'], dtype=np.object_), + dense_shape=[1, 2]), self.evaluate(features['aaa'])) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=[[0, 0], [0, 1]], + values=np.array([1., 10.], dtype=np.float32), + dense_shape=[1, 2]), self.evaluate(features['weights'])) + + @test_util.run_deprecated_v1 def test_transform_features(self): column = fc.weighted_categorical_column( categorical_column=fc.categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') inputs = sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=(0, 1, 0), - dense_shape=(2, 2)) + indices=((0, 0), (1, 0), (1, 1)), values=(0, 1, 0), dense_shape=(2, 2)) weights = sparse_tensor.SparseTensorValue( indices=((0, 0), (1, 0), (1, 1)), values=(0.5, 1.0, 0.1), dense_shape=(2, 2)) - id_tensor, weight_tensor = fc._transform_features({ + id_tensor, weight_tensor = fc._transform_features_v2({ 'ids': inputs, 'values': weights, }, (column,), None)[column] - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array(inputs.values, dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=weights.indices, - values=np.array(weights.values, dtype=np.float32), - dense_shape=weights.dense_shape), - weight_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array(inputs.values, dtype=np.int64), + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=weights.indices, + values=np.array(weights.values, dtype=np.float32), + dense_shape=weights.dense_shape), self.evaluate(weight_tensor)) + + @test_util.run_deprecated_v1 def test_transform_features_dense_input(self): column = fc.weighted_categorical_column( categorical_column=fc.categorical_column_with_identity( @@ -7466,55 +7945,57 @@ class WeightedCategoricalColumnTest(test.TestCase): indices=((0, 0), (1, 0), (1, 1)), values=(0.5, 1.0, 0.1), dense_shape=(2, 2)) - id_tensor, weight_tensor = fc._transform_features({ + id_tensor, weight_tensor = fc._transform_features_v2({ 'ids': ((0, -1), (1, 0)), 'values': weights, }, (column,), None)[column] - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=np.array((0, 1, 0), dtype=np.int64), - dense_shape=(2, 2)), - id_tensor.eval()) - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=weights.indices, - values=np.array(weights.values, dtype=np.float32), - dense_shape=weights.dense_shape), - weight_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=np.array((0, 1, 0), dtype=np.int64), + dense_shape=(2, 2)), self.evaluate(id_tensor)) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=weights.indices, + values=np.array(weights.values, dtype=np.float32), + dense_shape=weights.dense_shape), self.evaluate(weight_tensor)) + + @test_util.run_deprecated_v1 def test_transform_features_dense_weights(self): column = fc.weighted_categorical_column( categorical_column=fc.categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') inputs = sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=(2, 1, 0), - dense_shape=(2, 2)) - id_tensor, weight_tensor = fc._transform_features({ + indices=((0, 0), (1, 0), (1, 1)), values=(2, 1, 0), dense_shape=(2, 2)) + id_tensor, weight_tensor = fc._transform_features_v2({ 'ids': inputs, 'values': ((.5, 0.), (1., .1)), }, (column,), None)[column] - with _initialized_session(): - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=inputs.indices, - values=np.array(inputs.values, dtype=np.int64), - dense_shape=inputs.dense_shape), - id_tensor.eval()) - _assert_sparse_tensor_value( - self, - sparse_tensor.SparseTensorValue( - indices=((0, 0), (1, 0), (1, 1)), - values=np.array((.5, 1., .1), dtype=np.float32), - dense_shape=(2, 2)), - weight_tensor.eval()) + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=inputs.indices, + values=np.array(inputs.values, dtype=np.int64), + dense_shape=inputs.dense_shape), self.evaluate(id_tensor)) + _assert_sparse_tensor_value( + self, + sparse_tensor.SparseTensorValue( + indices=((0, 0), (1, 0), (1, 1)), + values=np.array((.5, 1., .1), dtype=np.float32), + dense_shape=(2, 2)), self.evaluate(weight_tensor)) + + @test_util.run_deprecated_v1 def test_linear_model(self): column = fc.weighted_categorical_column( categorical_column=fc.categorical_column_with_identity( @@ -7535,15 +8016,18 @@ class WeightedCategoricalColumnTest(test.TestCase): dense_shape=(2, 2)) }) weight_var, bias = model.variables - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - weight_var.assign(((1.,), (2.,), (3.,))).eval() - # weight_var[0] * weights[0, 0] = 1 * .5 = .5 - # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] - # = 3*1 + 2*.1 = 3+.2 = 3.2 - self.assertAllClose(((.5,), (3.2,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(weight_var.assign(((1.,), (2.,), (3.,)))) + # weight_var[0] * weights[0, 0] = 1 * .5 = .5 + # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] + # = 3*1 + 2*.1 = 3+.2 = 3.2 + self.assertAllClose(((.5,), (3.2,)), self.evaluate(predictions)) def test_linear_model_mismatched_shape(self): column = fc.weighted_categorical_column( @@ -7589,7 +8073,7 @@ class WeightedCategoricalColumnTest(test.TestCase): rewriter_config_pb2.RewriterConfig.OFF) with _initialized_session(config): with self.assertRaisesRegexp(errors.OpError, 'Incompatible shapes'): - predictions.eval() + self.evaluate(predictions) def test_linear_model_mismatched_dense_shape(self): column = fc.weighted_categorical_column( @@ -7607,15 +8091,18 @@ class WeightedCategoricalColumnTest(test.TestCase): 'values': ((.5,), (1.,), (.1,)) }) weight_var, bias = model.variables - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - weight_var.assign(((1.,), (2.,), (3.,))).eval() - # weight_var[0] * weights[0, 0] = 1 * .5 = .5 - # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] - # = 3*1 + 2*.1 = 3+.2 = 3.2 - self.assertAllClose(((.5,), (3.2,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(weight_var.assign(((1.,), (2.,), (3.,)))) + # weight_var[0] * weights[0, 0] = 1 * .5 = .5 + # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] + # = 3*1 + 2*.1 = 3+.2 = 3.2 + self.assertAllClose(((.5,), (3.2,)), self.evaluate(predictions)) def test_old_linear_model(self): column = fc.weighted_categorical_column( @@ -7637,15 +8124,18 @@ class WeightedCategoricalColumnTest(test.TestCase): }, (column,)) bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - weight_var.assign(((1.,), (2.,), (3.,))).eval() - # weight_var[0] * weights[0, 0] = 1 * .5 = .5 - # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] - # = 3*1 + 2*.1 = 3+.2 = 3.2 - self.assertAllClose(((.5,), (3.2,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(weight_var.assign(((1.,), (2.,), (3.,)))) + # weight_var[0] * weights[0, 0] = 1 * .5 = .5 + # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] + # = 3*1 + 2*.1 = 3+.2 = 3.2 + self.assertAllClose(((.5,), (3.2,)), self.evaluate(predictions)) def test_old_linear_model_mismatched_shape(self): column = fc.weighted_categorical_column( @@ -7690,7 +8180,7 @@ class WeightedCategoricalColumnTest(test.TestCase): rewriter_config_pb2.RewriterConfig.OFF) with _initialized_session(config): with self.assertRaisesRegexp(errors.OpError, 'Incompatible shapes'): - predictions.eval() + self.evaluate(predictions) def test_old_linear_model_mismatched_dense_shape(self): column = fc.weighted_categorical_column( @@ -7708,19 +8198,22 @@ class WeightedCategoricalColumnTest(test.TestCase): }, (column,)) bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - weight_var.assign(((1.,), (2.,), (3.,))).eval() - # weight_var[0] * weights[0, 0] = 1 * .5 = .5 - # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] - # = 3*1 + 2*.1 = 3+.2 = 3.2 - self.assertAllClose(((.5,), (3.2,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(weight_var.assign(((1.,), (2.,), (3.,)))) + # weight_var[0] * weights[0, 0] = 1 * .5 = .5 + # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] + # = 3*1 + 2*.1 = 3+.2 = 3.2 + self.assertAllClose(((.5,), (3.2,)), self.evaluate(predictions)) def test_old_linear_model_old_categorical(self): column = fc.weighted_categorical_column( - categorical_column=fc_old.categorical_column_with_identity( + categorical_column=fc_old._categorical_column_with_identity( key='ids', num_buckets=3), weight_feature_key='values') with ops.Graph().as_default(): @@ -7738,18 +8231,22 @@ class WeightedCategoricalColumnTest(test.TestCase): }, (column,)) bias = get_linear_model_bias() weight_var = get_linear_model_column_var(column) - with _initialized_session(): - self.assertAllClose((0.,), bias.eval()) - self.assertAllClose(((0.,), (0.,), (0.,)), weight_var.eval()) - self.assertAllClose(((0.,), (0.,)), predictions.eval()) - weight_var.assign(((1.,), (2.,), (3.,))).eval() - # weight_var[0] * weights[0, 0] = 1 * .5 = .5 - # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] - # = 3*1 + 2*.1 = 3+.2 = 3.2 - self.assertAllClose(((.5,), (3.2,)), predictions.eval()) + + self.evaluate(variables_lib.global_variables_initializer()) + self.evaluate(lookup_ops.tables_initializer()) + + self.assertAllClose((0.,), self.evaluate(bias)) + self.assertAllClose(((0.,), (0.,), (0.,)), self.evaluate(weight_var)) + self.assertAllClose(((0.,), (0.,)), self.evaluate(predictions)) + self.evaluate(weight_var.assign(((1.,), (2.,), (3.,)))) + # weight_var[0] * weights[0, 0] = 1 * .5 = .5 + # weight_var[2] * weights[1, 0] + weight_var[1] * weights[1, 1] + # = 3*1 + 2*.1 = 3+.2 = 3.2 + self.assertAllClose(((.5,), (3.2,)), self.evaluate(predictions)) # TODO(ptucker): Add test with embedding of weighted categorical. + @test_util.run_deprecated_v1 def test_serialization(self): categorical_column = fc.categorical_column_with_identity( key='ids', num_buckets=3) diff --git a/tensorflow/python/framework/auto_control_deps.py b/tensorflow/python/framework/auto_control_deps.py index 9a9ee46aab..30dc959e9a 100644 --- a/tensorflow/python/framework/auto_control_deps.py +++ b/tensorflow/python/framework/auto_control_deps.py @@ -21,9 +21,11 @@ from __future__ import print_function from tensorflow.python.eager import context from tensorflow.python.framework import dtypes as dtypes_module from tensorflow.python.framework import ops +from tensorflow.python.framework import sparse_tensor from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import control_flow_util +from tensorflow.python.ops import tensor_array_ops from tensorflow.python.util import nest from tensorflow.python.util import tf_decorator @@ -70,6 +72,17 @@ class AutomaticControlDependencies(object): self._returned_tensors.add(indices) self._returned_tensors.add(values) return ops.IndexedSlices(values, indices, dense_shape=tensor.dense_shape) + elif isinstance(tensor, sparse_tensor.SparseTensor): + values = array_ops.identity(tensor.values) + indices = array_ops.identity(tensor.indices) + self._returned_tensors.add(indices) + self._returned_tensors.add(values) + return sparse_tensor.SparseTensor( + indices, values, dense_shape=tensor.dense_shape) + elif isinstance(tensor, tensor_array_ops.TensorArray): + flow = array_ops.identity(tensor.flow) + self._returned_tensors.add(flow) + return tensor_array_ops.build_ta_with_new_flow(tensor, flow) # We want to make the return values depend on the stateful operations, but # we don't want to introduce a cycle, so we make the return value the result # of a new identity operation that the stateful operations definitely don't diff --git a/tensorflow/python/framework/constant_op.py b/tensorflow/python/framework/constant_op.py index 53d84b2dc7..ade0797dcd 100644 --- a/tensorflow/python/framework/constant_op.py +++ b/tensorflow/python/framework/constant_op.py @@ -114,8 +114,9 @@ def convert_to_eager_tensor(value, ctx, dtype=None): return ops.EagerTensor(value, handle, device, dtype) -@tf_export("constant") -def constant(value, dtype=None, shape=None, name="Const", verify_shape=False): +@tf_export(v1=["constant"]) +def constant_v1( + value, dtype=None, shape=None, name="Const", verify_shape=False): """Creates a constant tensor. The resulting tensor is populated with values of type `dtype`, as @@ -174,6 +175,79 @@ def constant(value, dtype=None, shape=None, name="Const", verify_shape=False): Raises: TypeError: if shape is incorrectly specified or unsupported. """ + return _constant_impl(value, dtype, shape, name, verify_shape=verify_shape, + allow_broadcast=False) + + +@tf_export("constant", v1=[]) +def constant(value, dtype=None, shape=None, name="Const"): + """Creates a constant tensor. + + The resulting tensor is populated with values of type `dtype`, as + specified by arguments `value` and (optionally) `shape` (see examples + below). + + The argument `value` can be a constant value, or a list of values of type + `dtype`. If `value` is a list, then the length of the list must be less + than or equal to the number of elements implied by the `shape` argument (if + specified). In the case where the list length is less than the number of + elements specified by `shape`, the last element in the list will be used + to fill the remaining entries. + + The argument `shape` is optional. If present, it specifies the dimensions of + the resulting tensor. If not present, the shape of `value` is used. + + If the argument `dtype` is not specified, then the type is inferred from + the type of `value`. + + For example: + + ```python + # Constant 1-D Tensor populated with value list. + tensor = tf.constant([1, 2, 3, 4, 5, 6]) => [1 2 3 4 5 6] + + # Constant 1-D Tensor populated with value list. + tensor = tf.constant([1, 2, 3, 4, 5, 6], shape=(2,3)) + => [[1 2 3], [4 5 6]] + + # Constant 2-D tensor populated with scalar value -1. + tensor = tf.constant(-1.0, shape=[2, 3]) => [[-1. -1. -1.] + [-1. -1. -1.]] + ``` + + `tf.constant` differs from `tf.fill` in a few ways: + + * `tf.constant` supports arbitrary constants, not just uniform scalar + Tensors like `tf.fill`. + * `tf.constant` creates a `Const` node in the computation graph with the + exact value at graph construction time. On the other hand, `tf.fill` + creates an Op in the graph that is expanded at runtime. + * Because `tf.constant` only embeds constant values in the graph, it does + not support dynamic shapes based on other runtime Tensors, whereas + `tf.fill` does. + + Args: + value: A constant value (or list) of output type `dtype`. + + dtype: The type of the elements of the resulting tensor. + + shape: Optional dimensions of resulting tensor. + + name: Optional name for the tensor. + + Returns: + A Constant Tensor. + + Raises: + TypeError: if shape is incorrectly specified or unsupported. + """ + return _constant_impl(value, dtype, shape, name, verify_shape=False, + allow_broadcast=True) + + +def _constant_impl( + value, dtype, shape, name, verify_shape, allow_broadcast): + """Implementation of constant.""" ctx = context.context() if ctx.executing_eagerly(): t = convert_to_eager_tensor(value, ctx, dtype) @@ -205,7 +279,8 @@ def constant(value, dtype=None, shape=None, name="Const", verify_shape=False): tensor_value = attr_value_pb2.AttrValue() tensor_value.tensor.CopyFrom( tensor_util.make_tensor_proto( - value, dtype=dtype, shape=shape, verify_shape=verify_shape)) + value, dtype=dtype, shape=shape, verify_shape=verify_shape, + allow_broadcast=allow_broadcast)) dtype_value = attr_value_pb2.AttrValue(type=tensor_value.tensor.dtype) const_tensor = g.create_op( "Const", [], [dtype_value.type], diff --git a/tensorflow/python/framework/device.py b/tensorflow/python/framework/device.py index 7f6e0a75a5..e7ac6444a4 100644 --- a/tensorflow/python/framework/device.py +++ b/tensorflow/python/framework/device.py @@ -23,7 +23,7 @@ import threading from tensorflow.python.util.tf_export import tf_export -@tf_export("DeviceSpec") +@tf_export(v1=["DeviceSpec"]) class DeviceSpec(object): """Represents a (possibly partial) specification for a TensorFlow device. diff --git a/tensorflow/python/framework/dtypes.py b/tensorflow/python/framework/dtypes.py index 48e9f0524e..f7a12d27df 100644 --- a/tensorflow/python/framework/dtypes.py +++ b/tensorflow/python/framework/dtypes.py @@ -18,6 +18,7 @@ from __future__ import division from __future__ import print_function import numpy as np +from six.moves import builtins from tensorflow.core.framework import types_pb2 from tensorflow.python import pywrap_tensorflow @@ -548,8 +549,8 @@ _NP_TO_TF = frozenset([ (np.int8, int8), (np.complex64, complex64), (np.complex128, complex128), - (np.object, string), - (np.bool, bool), + (np.object_, string), + (np.bool_, bool), (_np_qint8, qint8), (_np_quint8, quint8), (_np_qint16, qint16), @@ -658,8 +659,9 @@ tf_export( __name__, "QUANTIZED_DTYPES") _PYTHON_TO_TF = { - float: float32, - bool: bool, + builtins.float: float32, + builtins.bool: bool, + builtins.object: string } diff --git a/tensorflow/python/framework/dtypes_test.py b/tensorflow/python/framework/dtypes_test.py index a873670e04..719fdc0953 100644 --- a/tensorflow/python/framework/dtypes_test.py +++ b/tensorflow/python/framework/dtypes_test.py @@ -81,10 +81,10 @@ class TypesTest(test_util.TensorFlowTestCase): self.assertIs(dtypes.int8, dtypes.as_dtype(np.int8)) self.assertIs(dtypes.complex64, dtypes.as_dtype(np.complex64)) self.assertIs(dtypes.complex128, dtypes.as_dtype(np.complex128)) - self.assertIs(dtypes.string, dtypes.as_dtype(np.object)) + self.assertIs(dtypes.string, dtypes.as_dtype(np.object_)) self.assertIs(dtypes.string, dtypes.as_dtype(np.array(["foo", "bar"]).dtype)) - self.assertIs(dtypes.bool, dtypes.as_dtype(np.bool)) + self.assertIs(dtypes.bool, dtypes.as_dtype(np.bool_)) with self.assertRaises(TypeError): dtypes.as_dtype(np.dtype([("f1", np.uint), ("f2", np.int32)])) diff --git a/tensorflow/python/framework/file_system_test.py b/tensorflow/python/framework/file_system_test.py index 6901715e5d..8687bc5a78 100644 --- a/tensorflow/python/framework/file_system_test.py +++ b/tensorflow/python/framework/file_system_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import os from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.framework import load_library from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import io_ops @@ -36,13 +37,14 @@ class FileSystemTest(test.TestCase): "test_file_system.so") load_library.load_file_system_library(file_system_library) + @test_util.run_deprecated_v1 def testBasic(self): with self.cached_session() as sess: reader = io_ops.WholeFileReader("test_reader") queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) queue.enqueue_many([["test://foo"]]).run() queue.close().run() - key, value = sess.run(reader.read(queue)) + key, value = self.evaluate(reader.read(queue)) self.assertEqual(key, compat.as_bytes("test://foo")) self.assertEqual(value, compat.as_bytes("AAAAAAAAAA")) diff --git a/tensorflow/python/framework/func_graph.py b/tensorflow/python/framework/func_graph.py index c7a5d1ee20..f74d072e8e 100644 --- a/tensorflow/python/framework/func_graph.py +++ b/tensorflow/python/framework/func_graph.py @@ -26,11 +26,13 @@ from tensorflow.python.eager import context from tensorflow.python.eager import tape from tensorflow.python.eager.graph_only_ops import graph_placeholder from tensorflow.python.framework import ops +from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_spec from tensorflow.python.framework.auto_control_deps import AutomaticControlDependencies from tensorflow.python.ops import array_ops from tensorflow.python.ops import custom_gradient from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import tensor_array_ops from tensorflow.python.ops import variable_scope from tensorflow.python.util import compat from tensorflow.python.util import nest @@ -111,7 +113,7 @@ class FuncGraph(ops.Graph): # this stack from the default graph even in eager mode. Maybe it should be # part of the eager context? This would also allow us to remove a # get_default_graph() call from the function cache lookup. - self._distribution_strategy_stack = graph._distribution_strategy_stack + self._distribution_strategy_stack = list(graph._distribution_strategy_stack) # We ignore device placements from any outer scopes while tracing the # function when possible, to avoid hard-coding them in the function # graph. "Default" placements come from the PartitionedCallOp's placement, @@ -372,7 +374,7 @@ def func_graph_from_py_func(name, # captured Operations). with ops.control_dependencies([x]): x = array_ops.identity(op_return_value) - else: + elif not isinstance(x, tensor_array_ops.TensorArray): try: x = ops.convert_to_tensor_or_indexed_slices(x) except (ValueError, TypeError): @@ -395,9 +397,9 @@ def func_graph_from_py_func(name, return autograph.converted_call( original_func, None, autograph.ConversionOptions( - verbose=True, + verbose=autograph.Verbosity.BRIEF, recursive=True, - strip_decorators=(function.defun, def_function.function), + strip_decorators=(def_function.function,), optional_features=(), ), *args, **kwargs) @@ -408,7 +410,8 @@ def func_graph_from_py_func(name, func_outputs = python_func(*func_args, **func_kwargs) - # invariant: `func_outputs` contains only Tensors and `None`s. + # invariant: `func_outputs` contains only Tensors, IndexedSlices, + # SparseTensors, TensorArrays and `None`s. func_outputs = nest.map_structure(convert, func_outputs) check_mutation(func_args_before, func_args) @@ -495,7 +498,17 @@ def check_mutation(n1, n2): def flatten(sequence): - """A wrapper around `nest.flatten` that also unpacks `IndexedSlices`.""" + """Like `nest.flatten` but also unpacks other Tensor-like objects. + + Flattens non-tensor objects into their constituent tensors. + + Args: + sequence: A nested structure of Tensors, IndexedSlices, SparseTensors and + TensorArrays. + + Returns: + A list of tensors. + """ # TODO(akshayka): Support `SparseTensor` in a similar fashion. flat_sequence = nest.flatten(sequence) outputs = [] @@ -505,11 +518,58 @@ def flatten(sequence): outputs.extend([item.values, item.indices, item.dense_shape]) else: outputs.extend([item.values, item.indices]) + elif isinstance(item, sparse_tensor.SparseTensor): + outputs.extend([item.indices, item.values, item.dense_shape]) + elif isinstance(item, tensor_array_ops.TensorArray): + outputs.append(item.flow) else: outputs.append(item) return outputs +def pack_sequence_as(structure, flat_sequence): + """Like `nest.pack_sequence_as` but also packs other Tensor-like objects. + + Args: + structure: The structure to pack into. May contain Tensors, IndexedSlices, + TensorArrays or SparseTensors. + flat_sequence: An iterable containing tensors. + + Returns: + A nested structure. + + Raises: + AssertionError if `structure` and `flat_sequence` are not compatible. + """ + flattened_structure = nest.flatten(structure) + flat_sequence_with_slices_and_tas = [] + index = 0 + for t in flattened_structure: + if isinstance(t, ops.IndexedSlices): + if t.dense_shape is not None: + flat_sequence_with_slices_and_tas.append( + ops.IndexedSlices(*flat_sequence[index:index + 3])) + index += 3 + else: + flat_sequence_with_slices_and_tas.append( + ops.IndexedSlices(*flat_sequence[index:index + 2])) + index += 2 + elif isinstance(t, sparse_tensor.SparseTensor): + flat_sequence_with_slices_and_tas.append( + sparse_tensor.SparseTensor(*flat_sequence[index:index + 3])) + index += 3 + elif isinstance(t, tensor_array_ops.TensorArray): + flow = flat_sequence[index] + ta = tensor_array_ops.build_ta_with_new_flow(t, flow) + flat_sequence_with_slices_and_tas.append(ta) + index += 1 + else: + flat_sequence_with_slices_and_tas.append(flat_sequence[index]) + index += 1 + assert len(flattened_structure) == len(flat_sequence_with_slices_and_tas) + return nest.pack_sequence_as(structure, flat_sequence_with_slices_and_tas) + + def _create_substitute_placeholder(value, name=None, dtype=None): """Creates a placeholder for `value` and propagates shape info to it.""" # Note: setting ops.control_dependencies(None) ensures we always put diff --git a/tensorflow/python/framework/function.py b/tensorflow/python/framework/function.py index 230a554641..622686ce00 100644 --- a/tensorflow/python/framework/function.py +++ b/tensorflow/python/framework/function.py @@ -874,7 +874,7 @@ def func_graph_from_py_func(func, arg_names, arg_types, name=None, # If func only returned one value, make it a tuple. if not isinstance(outputs, (list, tuple)): outputs = (outputs,) - if any([_ is None for _ in outputs]): + if any(_ is None for _ in outputs): raise ValueError("Function %s can not return None." % name) # Ensures each output is a Tensor in the function graph. outputs = [ops.convert_to_tensor(t) for t in outputs] @@ -1190,7 +1190,7 @@ def get_extra_args(): def _type_list_to_str(types): - if any([_ not in _DTYPE_TO_STR for _ in types]): + if any(_ not in _DTYPE_TO_STR for _ in types): raise ValueError("Unsupported dtypes: %s" % types) return "".join([_DTYPE_TO_STR[_] for _ in types]) diff --git a/tensorflow/python/framework/function_def_to_graph_test.py b/tensorflow/python/framework/function_def_to_graph_test.py index b2ef64f873..ddf1a6e74d 100644 --- a/tensorflow/python/framework/function_def_to_graph_test.py +++ b/tensorflow/python/framework/function_def_to_graph_test.py @@ -25,6 +25,7 @@ from tensorflow.python.framework import function_def_to_graph from tensorflow.python.framework import graph_to_function_def from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.framework import test_ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops @@ -52,6 +53,7 @@ class FunctionDefToGraphTest(test.TestCase): fdef.signature.name = "_whats_in_a_name" return fdef + @test_util.run_deprecated_v1 def testInputsAndOutputs(self): fdef = self._build_function_def() g = function_def_to_graph.function_def_to_graph(fdef) @@ -186,6 +188,7 @@ class FunctionDefToGraphDefTest(test.TestCase): self.assertEqual(g.node[0].attr["shape"].shape.unknown_rank, False) self.assertFalse("shape" in g.node[2].attr) + @test_util.run_deprecated_v1 def testFunctionCallsFromFunction(self): x = constant_op.constant(5.0) y = constant_op.constant(10.0) diff --git a/tensorflow/python/framework/function_test.py b/tensorflow/python/framework/function_test.py index 13ee6c5d2d..d71f06ea52 100644 --- a/tensorflow/python/framework/function_test.py +++ b/tensorflow/python/framework/function_test.py @@ -35,6 +35,7 @@ from tensorflow.python.framework import function from tensorflow.python.framework import graph_to_function_def from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.framework.errors import InvalidArgumentError from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops @@ -102,8 +103,9 @@ class FunctionTest(test.TestCase): call = MyIdentityFunc([18.0]) self.assertEqual("MyIdentity", call.op.name) with session.Session() as sess: - self.assertAllEqual([18.0], sess.run(call)) + self.assertAllEqual([18.0], self.evaluate(call)) + @test_util.run_deprecated_v1 def testIdentityImplicitDeref(self): @function.Defun(dtypes.float32, func_name="MyIdentity") @@ -116,8 +118,8 @@ class FunctionTest(test.TestCase): self.assertEqual("MyIdentity", call.op.name) for cfg in _OptimizerOptions(): with session.Session(config=cfg) as sess: - sess.run(var.initializer) - self.assertAllEqual([18.0], sess.run(call)) + self.evaluate(var.initializer) + self.assertAllEqual([18.0], self.evaluate(call)) def testIdentityOutputName(self): @@ -130,7 +132,7 @@ class FunctionTest(test.TestCase): call = MyIdentityFunc([18.0]) self.assertEqual("MyIdentity", call.op.name) with session.Session() as sess: - self.assertAllEqual([18.0], sess.run(call)) + self.assertAllEqual([18.0], self.evaluate(call)) def testTooManyOutputNames(self): @@ -158,7 +160,7 @@ class FunctionTest(test.TestCase): call = APlus2B([1.0], [2.0]) self.assertEqual("APlus2B", call.op.name) with session.Session() as sess: - self.assertAllEqual([5.0], sess.run(call)) + self.assertAllEqual([5.0], self.evaluate(call)) def testFunctionWithNoOutput(self): @@ -187,7 +189,7 @@ class FunctionTest(test.TestCase): call = APlus2B([1.0], [2.0]) self.assertEqual("APlus2B", call.op.name) with session.Session() as sess: - self.assertAllEqual([5.0], sess.run(call)) + self.assertAllEqual([5.0], self.evaluate(call)) def testDefineFunctionDuplicateOutputs(self): @@ -224,8 +226,8 @@ class FunctionTest(test.TestCase): call_g = XSquarePlusOneGrad([2.0], [0.1]) with session.Session() as sess: - self.assertAllClose([5.0], sess.run(call_f)) - self.assertAllClose([0.4], sess.run(call_g)) + self.assertAllClose([5.0], self.evaluate(call_f)) + self.assertAllClose([0.4], self.evaluate(call_g)) def testTanhSymGrad(self): @@ -322,6 +324,7 @@ class FunctionTest(test.TestCase): self.assertEqual(x.get_shape(), dx.get_shape()) self.assertEqual(y.get_shape(), dy.get_shape()) + @test_util.run_deprecated_v1 def testSymGradAttr(self): @function.Defun(noinline=True) @@ -365,7 +368,7 @@ class FunctionTest(test.TestCase): else: dx, dy = gradients_impl.gradients([z], [x, y]) with session.Session() as sess: - dx_val, dy_val = sess.run([dx, dy]) + dx_val, dy_val = self.evaluate([dx, dy]) self.assertEqual([2.0], dx_val) self.assertEqual([0.0], dy_val) @@ -387,7 +390,7 @@ class FunctionTest(test.TestCase): call = AConstant() self.assertEqual("AConstant", call.op.name) with session.Session() as sess: - self.assertAllEqual([42], sess.run(call)) + self.assertAllEqual([42], self.evaluate(call)) def testDefineFunctionNames(self): @@ -438,6 +441,7 @@ class FunctionTest(test.TestCase): "assertion failed.*-3"): self.assertAllEqual(Foo(constant_op.constant(-3.0)).eval(), 6.0) + @test_util.run_deprecated_v1 def testAssertWrapper(self): @function.Defun(dtypes.float32) @@ -452,6 +456,7 @@ class FunctionTest(test.TestCase): "assertion"): _ = MyFn(100.0).eval() + @test_util.run_deprecated_v1 def testWhileLoopCallsFunc(self): with self.session(use_gpu=True) as sess: @@ -468,9 +473,10 @@ class FunctionTest(test.TestCase): loop = control_flow_ops.while_loop(lambda x: x < 1e5, Body, [1.0]) - ans = sess.run(loop) + ans = self.evaluate(loop) self.assertAllClose(ans, 131072.) + @test_util.run_deprecated_v1 def testControlFlowStrictness(self): """Inlined functions must not execute in a untaken control flow branch.""" @@ -517,6 +523,7 @@ class FunctionTest(test.TestCase): "assertion"): sess.run(loop, {pred: True, x: 3}) + @test_util.run_deprecated_v1 def testVar(self): @function.Defun(dtypes.float32) @@ -532,6 +539,7 @@ class FunctionTest(test.TestCase): variables.global_variables_initializer().run() self.assertAllEqual(z.eval(), 101.) + @test_util.run_deprecated_v1 def testResourceVarAsImplicitInput(self): g = ops.Graph() with g.as_default(), ops.device("cpu:0"): @@ -552,8 +560,8 @@ class FunctionTest(test.TestCase): with self.session(graph=g): v.initializer.run() - self.assertAllEqual(expected_val.eval(), actual_val.eval()) - self.assertAllEqual(expected_shape, actual_shape.eval()) + self.assertAllEqual(expected_val.eval(), self.evaluate(actual_val)) + self.assertAllEqual(expected_shape, self.evaluate(actual_shape)) def testDefineErrors(self): with ops.Graph().as_default(): @@ -650,8 +658,8 @@ class FunctionTest(test.TestCase): # pylint: enable=unexpected-keyword-arg self.assertEqual("next", call2.op.name) with session.Session() as sess: - self.assertAllEqual([1], sess.run(call1)) - self.assertAllEqual([0], sess.run(call2)) + self.assertAllEqual([1], self.evaluate(call1)) + self.assertAllEqual([0], self.evaluate(call2)) def testNestedFunction(self): @@ -707,6 +715,7 @@ class FunctionTest(test.TestCase): gdef = g.as_graph_def() self.assertEqual(0, len(gdef.library.function)) + @test_util.run_deprecated_v1 def testReduction(self): g = ops.Graph() @@ -735,6 +744,7 @@ class FunctionTest(test.TestCase): self.assertAllClose(vals[0], vals[1]) self.assertAllClose(vals[2], vals[3]) + @test_util.run_deprecated_v1 def testCapture(self): g = ops.Graph() with g.as_default(): @@ -781,6 +791,7 @@ class FunctionTest(test.TestCase): # NOTE: We still do not support capturing control deps. _ = Foo(x) + @test_util.run_deprecated_v1 def testCaptureInWhileLoop(self): g = ops.Graph() with g.as_default(): @@ -794,8 +805,9 @@ class FunctionTest(test.TestCase): y = Foo() with self.session(graph=g) as sess: - self.assertEqual(sess.run(y), 10) + self.assertEqual(self.evaluate(y), 10) + @test_util.run_deprecated_v1 def testCaptureInCond(self): g = ops.Graph() with g.as_default(): @@ -809,8 +821,8 @@ class FunctionTest(test.TestCase): z = Foo(False) with self.session(graph=g) as sess: - self.assertEqual(sess.run(y), 1) - self.assertEqual(sess.run(z), 2) + self.assertEqual(self.evaluate(y), 1) + self.assertEqual(self.evaluate(z), 2) def testStableName(self): @@ -825,6 +837,7 @@ class FunctionTest(test.TestCase): self.assertEqual("Foo_aCYSbwBkR5A", Foo.instantiate([dtypes.float32] * 3).name) + @test_util.run_deprecated_v1 def testSignatureHash(self): # Foo.Inner and Bar.Inner have identical function body but have # different signatures. They should be treated as two different functions. @@ -854,7 +867,7 @@ class FunctionTest(test.TestCase): z = Bar(x) with self.session(graph=g) as sess: - v0, v1 = sess.run([y, z]) + v0, v1 = self.evaluate([y, z]) self.assertAllEqual(v0, 20.) self.assertAllEqual(v1, 20.) @@ -877,6 +890,7 @@ class FunctionTest(test.TestCase): y = Bar(array_ops.zeros([1, 2, 3])) self.assertAllEqual(y.get_shape().as_list(), [1, 1, 2, 3]) + @test_util.run_deprecated_v1 def testVariableReuse(self): def LinearWithReuse(input_tensor, reuse=None): @@ -900,11 +914,12 @@ class FunctionTest(test.TestCase): self.assertEqual(global_vars[0].name, "linear/w:0") with session.Session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) output_val = sess.run( output_op, feed_dict={input_op: np.random.rand(32, 100)}) self.assertEqual(output_val.shape, (32, 100)) + @test_util.run_deprecated_v1 def testFunctionCallInDifferentVariableScopes(self): @function.Defun(dtypes.float32) @@ -928,7 +943,7 @@ class FunctionTest(test.TestCase): self.assertEqual(global_vars[0].name, "vs1/var:0") with session.Session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) out1, out2 = sess.run( [out1_op, out2_op], feed_dict={input_op: np.linspace(1, 10, 10)}) self.assertAllEqual(out1, np.linspace(2, 11, 10)) @@ -968,6 +983,7 @@ class FunctionTest(test.TestCase): self.assertAllClose( np.array([1.0, 0.0]).astype(np.float32), sess.run(dinp, {inp: x})) + @test_util.run_deprecated_v1 def testFunctionMarkedStateful(self): @function.Defun(dtypes.int32, dtypes.float32) @@ -991,10 +1007,11 @@ class FunctionTest(test.TestCase): result_2 = Bar(constant_op.constant(100, dtype=dtypes.int64)) with session.Session() as sess: - self.assertEqual(4.0, sess.run(result_1)) - self.assertEqual(100, sess.run(result_2)) + self.assertEqual(4.0, self.evaluate(result_1)) + self.assertEqual(100, self.evaluate(result_2)) self.assertEqual((4.0, 100), sess.run((result_1, result_2))) + @test_util.run_deprecated_v1 def testStatefulFunction(self): @function.Defun() @@ -1037,6 +1054,7 @@ class FunctionTest(test.TestCase): self.assertFalse(all(val3 == val1)) self.assertFalse(all(val4 == val2)) + @test_util.run_deprecated_v1 def testSameFunctionOnTwoDevices(self): @function.Defun(dtypes.float32) @@ -1052,10 +1070,11 @@ class FunctionTest(test.TestCase): for config in _OptimizerOptions(): config.device_count["CPU"] = 2 with session.Session(config=config) as sess: - self.assertEqual(42.0, sess.run(f_0)) - self.assertEqual(44.0, sess.run(f_1)) + self.assertEqual(42.0, self.evaluate(f_0)) + self.assertEqual(44.0, self.evaluate(f_1)) self.assertEqual((42.0, 44.0), sess.run((f_0, f_1))) + @test_util.run_deprecated_v1 def testGuaranteedConstsAreCaptured(self): var = variables.Variable(1.0) const = array_ops.guarantee_const(var) @@ -1076,9 +1095,10 @@ class FunctionTest(test.TestCase): return output with self.session(use_gpu=False) as sess: - sess.run(var.initializer) + self.evaluate(var.initializer) _ = sess.run(CapturesGuaranteedConst(), {also_not_const: 1.0}) + @test_util.run_deprecated_v1 def testSameFunctionDifferentGrads(self): def PartOne(x): @@ -1127,7 +1147,7 @@ class FunctionTest(test.TestCase): dx2, = gradients_impl.gradients(ys=[y2], xs=[x2]) with self.session(graph=g) as sess: - v0, v1, v2 = sess.run([dx0, dx1, dx2]) + v0, v1, v2 = self.evaluate([dx0, dx1, dx2]) self.assertAllEqual(v0, 2.) self.assertAllEqual(v1, 101.) @@ -1150,6 +1170,7 @@ class FunctionsFromProtos(test.TestCase): self.assertEqual(func.declared_input_types, new_func.declared_input_types) self.assertEqual(func.captured_inputs, new_func.captured_inputs) + @test_util.run_deprecated_v1 def testBasic(self): @function.Defun(dtypes.float32, dtypes.float32) @@ -1359,6 +1380,7 @@ class FunctionsFromProtos(test.TestCase): class FunctionOverloadTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): @function.Defun() @@ -1411,6 +1433,7 @@ class FunctionOverloadTest(test.TestCase): class FunctionCaptureByValueTest(test.TestCase): + @test_util.run_deprecated_v1 def testCaptureByValue(self): g = ops.Graph() with g.as_default(): @@ -1532,7 +1555,7 @@ class UnrollLSTMTest(test.TestCase): tf_logging.info("time: %f txt size: %d gdef bin size: %d", finish - start, len(str(gdef)), len(gdef.SerializeToString())) with g.as_default(), session.Session(config=cfg) as sess: - return sess.run(m) + return self.evaluate(m) mv0 = RunForward("complete") for cfg in _OptimizerOptions(): @@ -1561,7 +1584,7 @@ class UnrollLSTMTest(test.TestCase): tf_logging.info("time: %f txt size: %d gdef bin size: %d", finish - start, len(str(gdef)), len(gdef.SerializeToString())) with g.as_default(), session.Session(config=cfg) as sess: - return sess.run(dw) + return self.evaluate(dw) d0 = RunForwardBackward("complete") for cfg in _OptimizerOptions(): @@ -1634,6 +1657,7 @@ class FunctionInlineControlTest(test.TestCase): class ModuleFunctionTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): @function.Defun(*[dtypes.float32] * 3) @@ -1651,8 +1675,8 @@ class ModuleFunctionTest(test.TestCase): y = LinearWithCApi(a, b, c) z = Linear2WithCApi(a, b, c, d, e) with session.Session() as sess: - self.assertAllEqual([[1]], sess.run(y)) - self.assertAllEqual([[5]], sess.run(z)) + self.assertAllEqual([[1]], self.evaluate(y)) + self.assertAllEqual([[5]], self.evaluate(z)) class VariableHoistingTest(test.TestCase): @@ -1704,8 +1728,8 @@ class VariableHoistingTest(test.TestCase): self.assertEqual("Foo/b", b.op.name) with self.session(graph=g) as sess: - sess.run(variables.global_variables_initializer()) - w, b, x, y0, loss, dw, db = sess.run([w, b, x, y0, loss, dw, db]) + self.evaluate(variables.global_variables_initializer()) + w, b, x, y0, loss, dw, db = self.evaluate([w, b, x, y0, loss, dw, db]) self.assertAllEqual(w.shape, (64, 64)) self.assertAllClose(np.sum(w), 2050.44) @@ -1717,10 +1741,12 @@ class VariableHoistingTest(test.TestCase): self.assertAllEqual(db.shape, (64,)) self.assertAllClose(np.sum(db), 0.509, rtol=1e-2) + @test_util.run_deprecated_v1 def testBasic(self): self._testSimpleModel(True) self._testSimpleModel(False) + @test_util.run_deprecated_v1 def testBasicResource(self): self._testSimpleModel(True, use_resource=True) self._testSimpleModel(False, use_resource=True) diff --git a/tensorflow/python/framework/graph_util_test.py b/tensorflow/python/framework/graph_util_test.py index 563a177dd0..4e7408ad49 100644 --- a/tensorflow/python/framework/graph_util_test.py +++ b/tensorflow/python/framework/graph_util_test.py @@ -29,6 +29,7 @@ from tensorflow.python.framework import graph_util from tensorflow.python.framework import importer from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util +from tensorflow.python.framework import test_util from tensorflow.python.ops import gen_state_ops from tensorflow.python.ops import math_ops # pylint: disable=unused-import from tensorflow.python.ops import math_ops as math_ops_lib @@ -102,6 +103,7 @@ class DeviceFunctionsTest(test.TestCase): self.assertDeviceEqual(var_5.device, "/device:GPU:0") self.assertDeviceEqual(var_6.device, "/device:CPU:0") + @test_util.run_deprecated_v1 def testNestedDeviceFunctions(self): with ops.Graph().as_default(): var_0 = variables.VariableV1(0) @@ -210,8 +212,8 @@ class DeviceFunctionsTest(test.TestCase): with session.Session() as sess: init = variables.variables_initializer([variable_node]) - sess.run(init) - output = sess.run(output_node) + self.evaluate(init) + output = self.evaluate(output_node) self.assertNear(4.0, output, 0.00001) variable_graph_def = sess.graph.as_graph_def() @@ -242,8 +244,8 @@ class DeviceFunctionsTest(test.TestCase): output_node = math_ops_lib.multiply( variable_node, 2.0, name="output_node") with session.Session() as sess: - sess.run(variable_node.initializer) - output = sess.run(output_node) + self.evaluate(variable_node.initializer) + output = self.evaluate(output_node) self.assertNear(2.0, output, 0.00001) variable_graph_def = sess.graph.as_graph_def() # First get the constant_graph_def when variable_names_whitelist is @@ -256,7 +258,7 @@ class DeviceFunctionsTest(test.TestCase): # Then initialize the unused variable, and get another # constant_graph_def when variable_names_whitelist is not set. - sess.run(another_variable.initializer) + self.evaluate(another_variable.initializer) constant_graph_def_without_variable_whitelist = ( graph_util.convert_variables_to_constants( sess, variable_graph_def, ["output_node"])) @@ -295,7 +297,7 @@ class DeviceFunctionsTest(test.TestCase): ["Variable", "VariableV2", "VarHandleOp", "ReadVariableOp"]) with session.Session() as sess: output_node = sess.graph.get_tensor_by_name("output_node:0") - output = sess.run(output_node) + output = self.evaluate(output_node) self.assertNear(2.0, output, 0.00001) def create_node_def(self, op, name, inputs): diff --git a/tensorflow/python/framework/importer.py b/tensorflow/python/framework/importer.py index c9ac27e788..98c7aeccc4 100644 --- a/tensorflow/python/framework/importer.py +++ b/tensorflow/python/framework/importer.py @@ -21,6 +21,7 @@ import contextlib from tensorflow.core.framework import graph_pb2 from tensorflow.python import pywrap_tensorflow as c_api +from tensorflow.python import tf2 from tensorflow.python.framework import c_api_util from tensorflow.python.framework import device as pydev from tensorflow.python.framework import errors @@ -253,7 +254,9 @@ def _ProcessNewOps(graph): # Find any device in the list of colocated ops that have a device, if it # exists. We assume that if multiple ops have devices, they refer to the # same device. Otherwise, a runtime error will occur since the colocation - # property cannot be guaranteed. + # property cannot be guaranteed. Note in TF2 colocations have been removed + # from the public API and will be considered a hint, so there is no runtime + # error. # # One possible improvement is to try to check for compatibility of all # devices in this list at import time here, which would require @@ -262,6 +265,10 @@ def _ProcessNewOps(graph): try: coloc_op = graph._get_operation_by_name_unsafe(coloc_op_name) # pylint: disable=protected-access except KeyError: + # Do not error in TF2 if the colocation cannot be guaranteed + if tf2.enabled(): + continue + raise ValueError('Specified colocation to an op that ' 'does not exist during import: %s in %s' % (coloc_op_name, op.name)) @@ -431,17 +438,16 @@ def import_graph_def(graph_def, # # TODO(skyewm): fetch the TF_Functions directly from the TF_Graph # TODO(skyewm): avoid sending serialized FunctionDefs back to the TF_Graph - # TODO(b/74620627): move this after _ProcessNewOps outside the lock once - # _USE_C_SHAPES is removed. - if graph_def.library and graph_def.library.function: - # pylint: disable=protected-access - functions = function._from_library(graph_def.library) - for f in functions: - f.add_to_graph(graph) - # pylint: enable=protected-access _ProcessNewOps(graph) + if graph_def.library and graph_def.library.function: + # pylint: disable=protected-access + functions = function._from_library(graph_def.library) + for f in functions: + f.add_to_graph(graph) + # pylint: enable=protected-access + # Treat input mappings that don't appear in the graph as an error, because # they are likely to be due to a typo. missing_unused_input_keys = ( diff --git a/tensorflow/python/framework/importer_test.py b/tensorflow/python/framework/importer_test.py index 2b4d8e7299..66e80b5585 100644 --- a/tensorflow/python/framework/importer_test.py +++ b/tensorflow/python/framework/importer_test.py @@ -397,11 +397,11 @@ class ImportGraphDefTest(test.TestCase): # Run the imported graph. # TODO(b/76173421): make this work (currently DCHECKS) # with self.cached_session() as sess: - # sess.run(imported_init) - # self.assertEqual(sess.run(imported_var), 1.0) - # self.assertEqual(sess.run(imported_assign), 2.0) - # self.assertEqual(list(sess.run(imported_shape)), []) - # self.assertEqual(list(sess.run(new_var_shape)), []) + # self.evaluate(imported_init) + # self.assertEqual(self.evaluate(imported_var), 1.0) + # self.assertEqual(self.evaluate(imported_assign), 2.0) + # self.assertEqual(list(self.evaluate(imported_shape)), []) + # self.assertEqual(list(self.evaluate(new_var_shape)), []) def testWhileLoop(self): # Produce GraphDef containing while loop. @@ -418,7 +418,7 @@ class ImportGraphDefTest(test.TestCase): return_elements=[r.name]) self.assertEqual(imported_r.name, "import/" + r.name) with self.cached_session() as sess: - self.assertEqual(sess.run(imported_r), 10) + self.assertEqual(self.evaluate(imported_r), 10) def testImportWhileLoopInCond(self): # Produce GraphDef containing while loop. @@ -458,7 +458,7 @@ class ImportGraphDefTest(test.TestCase): lambda i: i < 2, ImportFn, [0], shape_invariants=[tensor_shape.TensorShape(None)]) with self.cached_session() as sess: - self.assertEqual(sess.run(out), 10) + self.assertEqual(self.evaluate(out), 10) def testTypeMismatchInGraphDef(self): # TODO(skyewm): improve error message @@ -930,7 +930,7 @@ class ImportGraphDefTest(test.TestCase): name="", return_elements=["id:0"]) with self.cached_session(): - self.assertEqual(5.0, t.eval()) + self.assertEqual(5.0, self.evaluate(t)) def testInvalidInputForReturnOperations(self): with ops.Graph().as_default(): @@ -1071,7 +1071,7 @@ class ImportGraphDefTest(test.TestCase): tensor_input = np.ones(input_shape, dtype=np.float32) t = constant_op.constant(tensor_input, shape=input_shape) g = array_ops.identity(t) - g.eval() + self.evaluate(g) def testVersion(self): v0 = versions.GRAPH_DEF_VERSION_MIN_CONSUMER @@ -1255,7 +1255,7 @@ class ImportGraphDefTest(test.TestCase): z = TestFunc() with self.cached_session(): - z_val = z.eval() + z_val = self.evaluate(z) self.assertEqual(z_val, -2.0) def testImportGraphWithFunctionTwice(self): diff --git a/tensorflow/python/framework/load_library.py b/tensorflow/python/framework/load_library.py index 908a5f521e..727f6aa44c 100644 --- a/tensorflow/python/framework/load_library.py +++ b/tensorflow/python/framework/load_library.py @@ -31,6 +31,7 @@ from tensorflow.core.lib.core import error_codes_pb2 # pylint: disable=unused-i from tensorflow.python import pywrap_tensorflow as py_tf from tensorflow.python.lib.io import file_io from tensorflow.python.util import compat +from tensorflow.python.util import deprecation from tensorflow.python.util.tf_export import tf_export @@ -83,7 +84,8 @@ def load_op_library(library_filename): return module -@tf_export('load_file_system_library') +@deprecation.deprecated(date=None, instructions='Use tf.load_library instead.') +@tf_export(v1=['load_file_system_library']) def load_file_system_library(library_filename): """Loads a TensorFlow plugin, containing file system implementation. diff --git a/tensorflow/python/framework/meta_graph_test.py b/tensorflow/python/framework/meta_graph_test.py index fc98b91a01..46ce4616a5 100644 --- a/tensorflow/python/framework/meta_graph_test.py +++ b/tensorflow/python/framework/meta_graph_test.py @@ -63,6 +63,7 @@ def _TestDir(test_name): class SimpleMetaGraphTest(test.TestCase): + @test_util.run_deprecated_v1 def testNoVariables(self): test_dir = _TestDir("no_variables") filename = os.path.join(test_dir, "metafile") @@ -116,6 +117,7 @@ class SimpleMetaGraphTest(test.TestCase): {new_input_tensor: input_feed_value}) self.assertEqual(new_output_value, output_value) + @test_util.run_deprecated_v1 def testStrippedOpListNestedFunctions(self): with self.cached_session(): # Square two levels deep @@ -158,6 +160,7 @@ class SimpleMetaGraphTest(test.TestCase): op_list = meta_graph.stripped_op_list_for_graph(graph) self.assertEqual(["Const"], [op.name for op in op_list.op]) + @test_util.run_deprecated_v1 def testDefaultAttrStripping(self): """Verifies that default attributes are stripped from a graph def.""" @@ -210,6 +213,7 @@ class SimpleMetaGraphTest(test.TestCase): self.assertEqual(node_def.attr["Tout"].type, dtypes.complex128) self.assertTrue(meta_graph_def.meta_info_def.stripped_default_attrs) + @test_util.run_deprecated_v1 def testDefaultAttrStrippingNestedFunctions(self): """Verifies that default attributes are stripped from function node defs.""" with self.cached_session(): @@ -261,6 +265,7 @@ class SimpleMetaGraphTest(test.TestCase): self.assertEqual(node_def.attr["attr_1"].i, 1) self.assertTrue(meta_graph_def.meta_info_def.stripped_default_attrs) + @test_util.run_deprecated_v1 def testVariableObjectsAreSharedAmongCollections(self): with ops.Graph().as_default() as graph1: v = variables.Variable(3.0) @@ -454,6 +459,7 @@ class ScopedMetaGraphTest(test.TestCase): # Verifies that we can export the subgraph under each layer and import # them into new layers in a new graph. + @test_util.run_deprecated_v1 def testScopedExportAndImport(self): test_dir = _TestDir("scoped_export_import") filenames = [ @@ -492,8 +498,8 @@ class ScopedMetaGraphTest(test.TestCase): init_op = variables.global_variables_initializer() grad = gradients_impl.gradients([output], [var]) with session.Session() as sess: - sess.run(init_op) - expected_grad_value = sess.run(grad) + self.evaluate(init_op) + expected_grad_value = self.evaluate(grad) # Restore the MetaGraphDef into a new Graph with an import scope. with ops.Graph().as_default(): @@ -518,10 +524,11 @@ class ScopedMetaGraphTest(test.TestCase): init_op = variables.global_variables_initializer() with session.Session() as sess: - sess.run(init_op) - actual_grad_value = sess.run(grad) + self.evaluate(init_op) + actual_grad_value = self.evaluate(grad) self.assertEqual(expected_grad_value, actual_grad_value) + @test_util.run_deprecated_v1 def testImportWhileLoopInWhileLoop(self): # Create a simple while loop. with ops.Graph().as_default(): @@ -544,9 +551,10 @@ class ScopedMetaGraphTest(test.TestCase): _, x = control_flow_ops.while_loop(lambda i, x: i < 2, body, [0, 0.0], name="") with session.Session() as sess: - sess.run(variables.global_variables_initializer()) - sess.run(x) + self.evaluate(variables.global_variables_initializer()) + self.evaluate(x) + @test_util.run_deprecated_v1 def testScopedImportUnderNameScope(self): graph = ops.Graph() with graph.as_default(): @@ -562,6 +570,7 @@ class ScopedMetaGraphTest(test.TestCase): self.assertEqual(list(imported_variables.values())[0].name, "foo/bar/myvar:0") + @test_util.run_deprecated_v1 def testScopedImportUnderNameScopeNoVarScope(self): graph = ops.Graph() with graph.as_default(): @@ -590,6 +599,7 @@ class ScopedMetaGraphTest(test.TestCase): self.assertEqual(list(imported_variables.values())[0].name, "s" + suffix + "/v:0") + @test_util.run_deprecated_v1 def testScopedImportWithSelectedCollections(self): meta_graph_filename = os.path.join( _TestDir("selected_collections_import"), "meta_graph.pb") @@ -600,11 +610,11 @@ class ScopedMetaGraphTest(test.TestCase): with graph.as_default(): variables.Variable(initial_value=1.0, trainable=True) self.assertTrue( - all([ + all( graph.get_collection(key) for key in [ops.GraphKeys.GLOBAL_VARIABLES, ops.GraphKeys.TRAINABLE_VARIABLES] - ])) + )) meta_graph.export_scoped_meta_graph( filename=meta_graph_filename, graph=graph) @@ -687,6 +697,7 @@ class ScopedMetaGraphTest(test.TestCase): # Verifies that we can export the subgraph containing a FIFOQueue under # "queue1" and import it into "new_queue1" in a new graph. + @test_util.run_deprecated_v1 def testScopedWithQueue(self): test_dir = _TestDir("scoped_with_queue") orig_meta_graph = self._testScopedExportWithQueue(test_dir, @@ -749,12 +760,15 @@ class ScopedMetaGraphTest(test.TestCase): for n, e in zip(nodes, expected): self.assertEqual([e], graph2.get_operation_by_name(n).get_attr("_class")) + @test_util.run_deprecated_v1 def testExportNestedNames(self): self.doTestExportNestedNames(use_resource=False) + @test_util.run_deprecated_v1 def testExportNestedNamesResource(self): self.doTestExportNestedNames(use_resource=True) + @test_util.run_deprecated_v1 def testPotentialCycle(self): graph1 = ops.Graph() with graph1.as_default(): @@ -783,6 +797,7 @@ class ScopedMetaGraphTest(test.TestCase): 4.0, shape=[2, 2]) }) + @test_util.run_deprecated_v1 def testClearDevices(self): graph1 = ops.Graph() with graph1.as_default(): @@ -842,6 +857,7 @@ class ScopedMetaGraphTest(test.TestCase): class MetaGraphWithVariableScopeTest(test.TestCase): + @test_util.run_deprecated_v1 def testMetricsCollection(self): def _enqueue_vector(sess, queue, values, shape=None): @@ -868,8 +884,8 @@ class MetaGraphWithVariableScopeTest(test.TestCase): _, update_op = metrics.mean(values) initializer = variables.local_variables_initializer() - sess.run(initializer) - sess.run(update_op) + self.evaluate(initializer) + self.evaluate(update_op) meta_graph.export_scoped_meta_graph( filename=meta_graph_filename, graph=graph) @@ -880,7 +896,7 @@ class MetaGraphWithVariableScopeTest(test.TestCase): with self.session(graph=graph) as sess: meta_graph.import_scoped_meta_graph(meta_graph_filename) initializer = variables.local_variables_initializer() - sess.run(initializer) + self.evaluate(initializer) # Verifies that importing an old meta_graph where "local_variables" # collection is of node_list type works, but cannot build initializer @@ -899,6 +915,7 @@ class MetaGraphWithVariableScopeTest(test.TestCase): class ExportImportAcrossScopesTest(test.TestCase): + @test_util.run_deprecated_v1 def testPartionedVariables(self): def make_graph_with_partitioned_variables(use_resource): diff --git a/tensorflow/python/framework/op_def_library.py b/tensorflow/python/framework/op_def_library.py index 9955a9a2cd..2318b32ef1 100644 --- a/tensorflow/python/framework/op_def_library.py +++ b/tensorflow/python/framework/op_def_library.py @@ -570,7 +570,7 @@ class OpDefLibrary(object): "than minimum length %d." % (input_name, op_type_name, len(values), num_attr.minimum)) # All tensors must have the same base type. - if any([bt != base_types[0] for bt in base_types]): + if any(bt != base_types[0] for bt in base_types): raise TypeError( "All tensors passed to '%s' of '%s' Op " "must have the same type." % diff --git a/tensorflow/python/framework/ops.py b/tensorflow/python/framework/ops.py index aaa12bf71f..1a26984809 100644 --- a/tensorflow/python/framework/ops.py +++ b/tensorflow/python/framework/ops.py @@ -36,14 +36,13 @@ from tensorflow.core.framework import op_def_pb2 from tensorflow.core.framework import versions_pb2 from tensorflow.core.protobuf import config_pb2 from tensorflow.python import pywrap_tensorflow as c_api +from tensorflow.python import tf2 from tensorflow.python.eager import context from tensorflow.python.eager import core from tensorflow.python.eager import tape from tensorflow.python.framework import c_api_util -from tensorflow.python.framework import cpp_shape_inference_pb2 from tensorflow.python.framework import device as pydev from tensorflow.python.framework import dtypes -from tensorflow.python.framework import error_interpolation from tensorflow.python.framework import errors from tensorflow.python.framework import op_def_registry from tensorflow.python.framework import registry @@ -318,22 +317,13 @@ class Tensor(_TensorLike): self._op = op self._value_index = value_index self._dtype = dtypes.as_dtype(dtype) - # This will be set by self._as_tf_output(). self._tf_output = None - # This will be set by self.shape(). self._shape_val = None - # List of operations that use this Tensor as input. We maintain this list # to easily navigate a computation graph. self._consumers = [] - - if not _USE_C_SHAPES: - # Attributes used for C++ shape inference. Not inspected, only forwarded. - # If set, will be a HandleData object from cpp_shape_inference.proto. - self._handle_data = None - self._id = uid() @property @@ -408,17 +398,7 @@ class Tensor(_TensorLike): """ if self._shape_val is None: - if _USE_C_SHAPES: - self._shape_val = self._c_api_shape() - else: - # Call set_shape_and_handle_data_for_outputs in topological order on all - # ops that are needed to compute self.op's shape. We do this instead of - # having set_shape_and_handle_data_for_outputs recursively call - # Operation.shape on self.op.inputs to overflowing the call stack. - need_shapes = self._get_input_ops_without_shapes(self.op) - need_shapes.sort(key=lambda op: op._id) - for op in need_shapes: - set_shape_and_handle_data_for_outputs(op) + self._shape_val = self._c_api_shape() return self._shape_val def _get_input_ops_without_shapes(self, target_op): @@ -533,14 +513,10 @@ class Tensor(_TensorLike): ValueError: If `shape` is not compatible with the current shape of this tensor. """ - if _USE_C_SHAPES: # pylint: disable=protected-access - # Reset cached shape. - self._shape_val = None - else: - self._shape_val = self.shape.merge_with(shape) + # Reset cached shape. + self._shape_val = None - # Update C shape even if _USE_C_SHAPES = False, since we still want - # set_shape to be reflected in the C API graph for when we run it. + # We want set_shape to be reflected in the C API graph for when we run it. if not isinstance(shape, tensor_shape.TensorShape): shape = tensor_shape.TensorShape(shape) dim_list = [] @@ -634,10 +610,7 @@ class Tensor(_TensorLike): return id(self) == id(other) def __copy__(self): - # Make sure _shape_val is computed before we copy. # TODO(b/77597810): get rid of Tensor copies. - if self._shape_val is None: - set_shape_and_handle_data_for_outputs(self.op) cls = self.__class__ result = cls.__new__(cls) result.__dict__.update(self.__dict__) @@ -774,6 +747,18 @@ class _EagerTensorBase(Tensor): def _numpy(self): raise NotImplementedError() + @property + def backing_device(self): + """Returns the name of the device holding this tensor's memory. + + `.backing_device` is usually the same as `.device`, which returns + the device on which the kernel of the operation that produced this tensor + ran. However, some operations can produce tensors on a different device + (e.g., an operation that executes on the GPU but produces output tensors + in host memory). + """ + raise NotImplementedError() + def __copy__(self): # Eager Tensors are immutable so it's safe to return themselves as a copy. return self @@ -890,6 +875,12 @@ class _EagerTensorBase(Tensor): """Returns the number of Tensor dimensions.""" return self.shape.ndims + def __len__(self): + """Returns the length of the first dimension in the Tensor.""" + if not self.shape.ndims: + raise TypeError("Scalar tensor has no `len()`") + return self._shape_tuple()[0] + def _cpu_nograd(self): """A copy of this Tensor with contents backed by host memory. @@ -918,13 +909,7 @@ class _EagerTensorBase(Tensor): return self._copy(context.context(), "GPU:" + str(gpu_index)) def __bool__(self): - if self._shape_tuple() != (): # pylint: disable=g-explicit-bool-comparison - raise ValueError( - "Non-scalar tensor %s cannot be converted to boolean." % repr(self)) - if self.dtype != dtypes.bool: - raise ValueError( - "Non-boolean tensor %s cannot be converted to boolean." % repr(self)) - return bool(self.cpu().numpy()) + return bool(self.numpy()) def __nonzero__(self): return self.__bool__() @@ -1044,12 +1029,12 @@ def convert_to_tensor(value, dtype=None, name=None, preferred_dtype=None): `preferred_dtype` is not possible, this argument has no effect. Returns: - An `Output` based on `value`. + An `Tensor` based on `value`. Raises: - TypeError: If no conversion function is registered for `value`. + TypeError: If no conversion function is registered for `value` to `dtype`. RuntimeError: If a registered conversion function returns an invalid value. - + ValueError: If the `value` is a tensor not of given `dtype` in graph mode. """ return convert_to_tensor_v2(value, dtype, preferred_dtype, name) @@ -1097,12 +1082,12 @@ def convert_to_tensor_v2(value, dtype=None, dtype_hint=None, name=None): name: Optional name to use if a new `Tensor` is created. Returns: - An `Output` based on `value`. + An `Tensor` based on `value`. Raises: - TypeError: If no conversion function is registered for `value`. + TypeError: If no conversion function is registered for `value` to `dtype`. RuntimeError: If a registered conversion function returns an invalid value. - + ValueError: If the `value` is a tensor not of given `dtype` in graph mode. """ return internal_convert_to_tensor( value=value, @@ -1123,49 +1108,13 @@ def internal_convert_to_tensor(value, preferred_dtype=None, ctx=None, accept_symbolic_tensors=True): - """Converts the given `value` to an `Tensor`. - - This function converts Python objects of various types to `Tensor` - objects. It accepts `Tensor` objects, numpy arrays, Python lists, - and Python scalars. For example: - - This function can be useful when composing a new operation in Python - All standard Python op constructors apply this function to each of their - Tensor-valued inputs, which allows those ops to accept numpy arrays, Python - lists, and scalars in addition to `Tensor` objects. - - Args: - value: An object whose type has a registered `Tensor` conversion function. - dtype: Optional element type for the returned tensor. If missing, the - type is inferred from the type of `value`. - name: Optional name to use if a new `Tensor` is created. - as_ref: True if we want the mutable view of Variables, if applicable. - preferred_dtype: Optional element type for the returned tensor, - used when dtype is None. In some cases, a caller may not have a - dtype in mind when converting to a tensor, so preferred_dtype - can be used as a soft preference. If the conversion to - `preferred_dtype` is not possible, this argument has no effect. - ctx: Optional: The value of context.context(). - accept_symbolic_tensors: Whether Keras graph tensors should be accepted as - a valid tensor type during eager execution. - If False, this function will raise an exception if it is passed such - a tensor during eager eager execution. - - Returns: - A `Tensor` based on `value`. - - Raises: - TypeError: If no conversion function is registered for `value`. - RuntimeError: If a registered conversion function returns an invalid value. - - """ + """Implementation of the public convert_to_tensor.""" if ctx is None: ctx = context.context() if isinstance(value, EagerTensor): if ctx.executing_eagerly(): - # Fast path for EagerTensors that don't need any conversion. - # Note that we don't check that value's dtype matches the dtype - # argument. We expect that the C runtime will do that checking - # when we execute the kernel. + if dtype is not None: + dtype = dtypes.as_dtype(dtype) + value = _TensorTensorConversionFunction(value, dtype=dtype) return value else: graph = get_default_graph() @@ -2129,12 +2078,6 @@ class Operation(object): raise TypeError("tensor must be a Tensor: %s" % tensor) _assert_same_graph(self, tensor) - # Make sure output shapes are already computed for this op in case we create - # a cycle (we cannot compute shapes for cycles). Usually shapes are computed - # lazily upon request. - if not _USE_C_SHAPES: - set_shape_and_handle_data_for_outputs(self) - # Reset cached inputs. self._inputs_val = None c_api.UpdateEdge( @@ -2142,6 +2085,31 @@ class Operation(object): tensor._as_tf_output(), # pylint: disable=protected-access self._tf_input(index)) + def _add_while_inputs(self, tensors): + """See AddWhileInputHack in python_api.h. + + NOTE: This is for TF internal use only. Please don't use it. + + Args: + tensors: list of Tensors + + Raises: + TypeError: if tensor is not a Tensor, + or if input tensor type is not convertible to dtype. + ValueError: if the Tensor is from a different graph. + """ + for tensor in tensors: + if not isinstance(tensor, Tensor): + raise TypeError("tensor must be a Tensor: %s" % tensor) + _assert_same_graph(self, tensor) + + # Reset cached inputs. + self._inputs_val = None + c_api.AddWhileInputHack( + self._graph._c_graph, # pylint: disable=protected-access + tensor._as_tf_output(), # pylint: disable=protected-access + self._c_op) + def _add_control_inputs(self, ops): """Add a list of new control inputs to this operation. @@ -2175,6 +2143,23 @@ class Operation(object): """Removes any control inputs to this operation.""" c_api.RemoveAllControlInputs(self._graph._c_graph, self._c_op) # pylint: disable=protected-access + def _add_outputs(self, types, shapes): + """Adds new Tensors to self.outputs. + + Note: this is generally unsafe to use. This is used in certain situations in + conjunction with _set_type_list_attr. + + Arguments: + types: list of DTypes + shapes: list of TensorShapes + """ + assert len(types) == len(shapes) + orig_num_outputs = len(self.outputs) + for i in range(len(types)): + t = Tensor(self, orig_num_outputs + i, types[i]) + self._outputs.append(t) + t.set_shape(shapes[i]) + def __str__(self): return str(self.node_def) @@ -2387,6 +2372,25 @@ class Operation(object): finally: c_api.TF_DeleteBuffer(buf) + def _set_func_attr(self, attr_name, func_name): + """Private method used to set a function attribute in the node_def.""" + func = attr_value_pb2.NameAttrList(name=func_name) + self._set_attr(attr_name, attr_value_pb2.AttrValue(func=func)) + + def _set_type_list_attr(self, attr_name, types): + """Private method used to set a function attribute in the node_def.""" + if not types: return + if isinstance(types[0], dtypes.DType): + types = [dt.as_datatype_enum for dt in types] + types_list = attr_value_pb2.AttrValue.ListValue(type=types) + self._set_attr(attr_name, attr_value_pb2.AttrValue(list=types_list)) + + def _set_shape_list_attr(self, attr_name, shapes): + """Private method used to set a function attribute in the node_def.""" + shapes = [s.as_proto() for s in shapes] + shapes_list = attr_value_pb2.AttrValue.ListValue(shape=shapes) + self._set_attr(attr_name, attr_value_pb2.AttrValue(list=shapes_list)) + def get_attr(self, name): """Returns the value of the attr of this op with the given `name`. @@ -2399,7 +2403,7 @@ class Operation(object): Raises: ValueError: If this op does not have an attr with the given `name`. """ - fields = ["s", "i", "f", "b", "type", "shape", "tensor", "func"] + fields = ("s", "i", "f", "b", "type", "shape", "tensor", "func") try: with c_api_util.tf_buffer() as buf: c_api.TF_OperationGetAttrValueProto(self._c_op, name, buf) @@ -2410,25 +2414,21 @@ class Operation(object): x = attr_value_pb2.AttrValue() x.ParseFromString(data) - # Treat an empty oneof value as an empty list. - if not x.WhichOneof("value"): + oneof_value = x.WhichOneof("value") + if oneof_value is None: return [] - if x.HasField("list"): + if oneof_value == "list": for f in fields: if getattr(x.list, f): if f == "type": - return [dtypes.as_dtype(x) for x in list(getattr(x.list, f))] + return [dtypes.as_dtype(t) for t in x.list.type] else: return list(getattr(x.list, f)) return [] - else: - for f in fields: - if x.HasField(f): - if f == "type": - return dtypes.as_dtype(getattr(x, f)) - else: - return getattr(x, f) - assert False, "Unsupported field type in " + str(x) + if oneof_value == "type": + return dtypes.as_dtype(x.type) + assert oneof_value in fields, "Unsupported field type in " + str(x) + return getattr(x, oneof_value) def run(self, feed_dict=None, session=None): """Runs this operation in a `Session`. @@ -2608,72 +2608,9 @@ class RegisterShape(object): return f -# TODO(b/74620627): remove when _USE_C_SHAPES is removed -def _set_shape_and_handle_data_for_outputs_c_api(op): - """Set shapes and resource handle data using info from the C API.""" - assert not _USE_C_SHAPES - for output in op.outputs: - output._shape_val = output._c_api_shape() - # Set the resource handle data for compatibility with the Python shape - # inference code. - serialized = c_api.GetHandleShapeAndType(op._graph._c_graph, # pylint: disable=protected-access - output._as_tf_output()) - if serialized: - output._handle_data = ( - cpp_shape_inference_pb2.CppShapeInferenceResult.HandleData - .FromString(compat.as_bytes(serialized))) - else: - output._handle_data = None - - -# TODO(b/74620627): remove when _USE_C_SHAPES is removed -def set_shape_and_handle_data_for_outputs(op): - """Set the shapes and resource handle data for op's outputs. - - When _USE_C_SHAPES = False, this is lazily called when a tensor's shape is - first requested. Usually this should work automatically, but some edge cases - may require manually calling this first to make sure Tensor._shape_val and - Tensor._handle_data are set (e.g. manually overriding _handle_data, copying a - Tensor). - """ - if _USE_C_SHAPES: return - - if op.graph._is_function(op.type): - for output in op.outputs: - output._shape_val = tensor_shape.unknown_shape() - return - - try: - shape_func = _shape_registry.lookup(op.type) - except LookupError: - try: - shape_func = _default_shape_function_registry.lookup(op.type) - except LookupError: - shape_func = _call_cpp_shape_fn_and_require_op - - shapes = shape_func(op) - if shapes is None: - raise RuntimeError( - "Shape function for op %s did not return any shapes" % op) - elif isinstance(shapes, dict): - # Returned by call_cpp_shape_fn - shapes_dict = shapes - shapes = shapes_dict["shapes"] - handle_datas = shapes_dict["handle_data"] - for output, handle_data in zip(op.outputs, handle_datas): - # Don't override any existing handle data that may have been manually set. - # pylint: disable=protected-access - if output._handle_data is None: - output._handle_data = handle_data - # pylint: enable=protected-access - - if len(op.outputs) != len(shapes): - raise RuntimeError( - "Shape function for op %s returned %d shapes but expected %d %s %s" % - (op, len(shapes), len(op.outputs), shape_func.__name__, str(shapes))) - for output, s in zip(op.outputs, shapes): - output._shape_val = tensor_shape.unknown_shape() - output._shape_val = output._shape_val.merge_with(s) +def set_shape_and_handle_data_for_outputs(_): + """No op. TODO(b/74620627): Remove this.""" + pass class OpStats(object): @@ -2901,8 +2838,8 @@ class Graph(object): self._stack_state_is_thread_local = False self._thread_local = threading.local() # Functions that will be applied to choose a device if none is specified. - # After switch_to_thread_local(), self._thread_local._device_function_stack - # is used instead. + # In TF2.x or after switch_to_thread_local(), + # self._thread_local._device_function_stack is used instead. self._graph_device_function_stack = traceable_stack.TraceableStack() # Default original_op applied to new ops. self._default_original_op = None @@ -2910,7 +2847,7 @@ class Graph(object): # WhileContext defined in ops/control_flow_ops.py self._control_flow_context = None # A new node will depend of the union of all of the nodes in the stack. - # After switch_to_thread_local(), + # In TF2.x or after switch_to_thread_local(), # self._thread_local._control_dependencies_stack is used instead. self._graph_control_dependencies_stack = [] # Arbitrary collections of objects. @@ -2934,7 +2871,7 @@ class Graph(object): producer=versions.GRAPH_DEF_VERSION, min_consumer=versions.GRAPH_DEF_VERSION_MIN_CONSUMER) self._building_function = False - # Stack of colocate_with ops. After switch_to_thread_local(), + # Stack of colocate_with ops. In TF2.x or after switch_to_thread_local(), # self._thread_local._colocation_stack is used instead. self._graph_colocation_stack = traceable_stack.TraceableStack() # Set of tensors that are dangerous to feed! @@ -2967,6 +2904,8 @@ class Graph(object): # requirement (many custom ops do not have shape functions, and we don't # want to break these existing cases). c_api.SetRequireShapeInferenceFns(self._c_graph, False) + if tf2.enabled(): + self.switch_to_thread_local() # Note: this method is private because the API of tf.Graph() is public and # frozen, and this functionality is still not ready for public visibility. @@ -3391,36 +3330,6 @@ class Graph(object): self._create_op_helper(ret, compute_device=compute_device) return ret - def _make_colocation_conflict_message(self, op, colocation_op): - """Return detailed error message about device conflict due to colocation.""" - # Example error message: - # Tried to colocate op 'a' (defined at file1.py:149) having device - # '/device:GPU:0' with op 'b' (defined at file2:96) which had an - # incompatible device '/device:CPU:0'. - # - # No node-device colocations were active during op 'a' creation. - # Device assignments active during op 'a' creation: - # with tf.device(/device:GPU:0): file1.py:148> - # - # Node-device colocations active during op 'b' creation: - # with tf.colocate_with(a): file2.py:93> - # Device assignments active during op 'b' creation: - # with tf.device(/cpu:0): file2.py:94 - op_info = error_interpolation.compute_field_dict(op) - coloc_op_info = error_interpolation.compute_field_dict(colocation_op) - msg = ("Tried to colocate op '{op_name}'{op_loc} having device '{op_dev}' " - "with op '{coloc_op_name}'{coloc_op_loc} which had an incompatible " - "device '{coloc_op_dev}'.\n\n{op_summary}\n\n{coloc_op_summary}" - .format(op_name=op.name, - op_loc=op_info["defined_at"], - op_dev=op.device, - op_summary=op_info["devs_and_colocs"], - coloc_op_name=colocation_op.name, - coloc_op_loc=coloc_op_info["defined_at"], - coloc_op_dev=colocation_op.device, - coloc_op_summary=coloc_op_info["devs_and_colocs"])) - return msg - def _create_op_helper(self, op, compute_device=True): """Common logic for creating an op in this graph.""" # Apply any additional attributes requested. Do not overwrite any existing @@ -3473,12 +3382,9 @@ class Graph(object): for colocation_op in self._colocation_stack.peek_objs(): all_colocation_groups.extend(colocation_op.colocation_groups()) if colocation_op.device: - if (op.device and pydev.canonical_name(op.device) != - pydev.canonical_name(colocation_op.device)): - msg = self._make_colocation_conflict_message(op, colocation_op) - logging.warning(msg) - else: - op._set_device(colocation_op.device) # pylint: disable=protected-access + # pylint: disable=protected-access + op._set_device(colocation_op.device) + # pylint: enable=protected-access all_colocation_groups = sorted(set(all_colocation_groups)) # pylint: disable=protected-access @@ -3526,11 +3432,6 @@ class Graph(object): # pylint: disable=protected-access for op in new_ops: - # Operations created by the C API always retrieve shapes from the C API so - # we preserve the shapes of ops created in import_graph_def (from the - # "_output_shapes" attr of the imported NodeDef). - if not _USE_C_SHAPES: - _set_shape_and_handle_data_for_outputs_c_api(op) new_control_inputs = self._control_dependencies_for_inputs(op.inputs) op._add_control_inputs(new_control_inputs) op._control_flow_post_processing() @@ -5482,7 +5383,7 @@ def inside_function(): return get_default_graph().building_function -@tf_export("enable_eager_execution") +@tf_export(v1=["enable_eager_execution"]) def enable_eager_execution(config=None, device_policy=None, execution_mode=None): @@ -5553,6 +5454,17 @@ def enable_eager_execution(config=None, server_def=None) +@tf_export(v1=["disable_eager_execution"]) +def disable_eager_execution(): + """Disables eager execution. + + This function can only be called before any Graphs, Ops, or Tensors have been + created. It can be used at the beginning of the program for complex migration + projects from TensorFlow 1.x to 2.x. + """ + context.default_execution_mode = context.GRAPH_MODE + + def enable_eager_execution_internal(config=None, device_policy=None, execution_mode=None, @@ -5560,6 +5472,7 @@ def enable_eager_execution_internal(config=None, """Enables eager execution for the lifetime of this program. Most of the doc string for enable_eager_execution is relevant here as well. + Args: config: See enable_eager_execution doc string device_policy: See enable_eager_execution doc string @@ -5652,7 +5565,7 @@ def eager_run(main=None, argv=None): app.run(main, argv) -@tf_export("reset_default_graph") +@tf_export(v1=["reset_default_graph"]) def reset_default_graph(): """Clears the default graph stack and resets the global default graph. @@ -5671,7 +5584,7 @@ def reset_default_graph(): _default_graph_stack.reset() -@tf_export("get_default_graph") +@tf_export(v1=["get_default_graph"]) def get_default_graph(): """Returns the default graph for the current thread. @@ -5798,7 +5711,7 @@ def _get_graph_from_inputs(op_input_list, graph=None): return graph or get_default_graph() -@tf_export("GraphKeys") +@tf_export(v1=["GraphKeys"]) class GraphKeys(object): """Standard names to use for graph collections. @@ -6004,7 +5917,7 @@ def add_to_collections(names, value): get_default_graph().add_to_collections(names, value) -@tf_export("get_collection_ref") +@tf_export(v1=["get_collection_ref"]) def get_collection_ref(key): """Wrapper for `Graph.get_collection_ref()` using the default graph. @@ -6028,7 +5941,7 @@ def get_collection_ref(key): return get_default_graph().get_collection_ref(key) -@tf_export("get_collection") +@tf_export(v1=["get_collection"]) def get_collection(key, scope=None): """Wrapper for `Graph.get_collection()` using the default graph. diff --git a/tensorflow/python/framework/ops_test.py b/tensorflow/python/framework/ops_test.py index 0fb17081e7..7baa02b446 100644 --- a/tensorflow/python/framework/ops_test.py +++ b/tensorflow/python/framework/ops_test.py @@ -57,11 +57,13 @@ ops._set_call_cpp_shape_fn(common_shapes.call_cpp_shape_fn) class ResourceTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testBuildGraph(self): with self.cached_session(): pt = test_ops.stub_resource_handle_op(container="a", shared_name="b") test_ops.resource_create_op(pt).run() + @test_util.run_deprecated_v1 def testInitialize(self): with self.cached_session(): handle = test_ops.stub_resource_handle_op(container="a", shared_name="b") @@ -106,6 +108,7 @@ class TensorAndShapeTest(test_util.TensorFlowTestCase): c = a + b self.assertEqual([2, 3], c.shape) + @test_util.run_deprecated_v1 def testUnknownDim(self): with self.cached_session(): a = array_ops.placeholder(dtype=dtypes.float32, shape=[2, None, 3]) @@ -113,6 +116,7 @@ class TensorAndShapeTest(test_util.TensorFlowTestCase): c = a + b self.assertEqual([2, None, 3], c.shape.as_list()) + @test_util.run_deprecated_v1 def testUnknownShape(self): with self.cached_session(): a = array_ops.placeholder(dtype=dtypes.float32, shape=None) @@ -120,6 +124,7 @@ class TensorAndShapeTest(test_util.TensorFlowTestCase): c = a + b self.assertEqual(tensor_shape.unknown_shape(), c.shape) + @test_util.run_deprecated_v1 def testScalarShape(self): with self.cached_session(): a = array_ops.placeholder(dtype=dtypes.float32, shape=[]) @@ -127,6 +132,7 @@ class TensorAndShapeTest(test_util.TensorFlowTestCase): c = a + b self.assertEqual(tensor_shape.scalar(), c.shape) + @test_util.run_deprecated_v1 def testShapeFunctionError(self): with self.cached_session(): a = array_ops.ones([1, 2, 3]) @@ -140,15 +146,16 @@ class TensorAndShapeTest(test_util.TensorFlowTestCase): class IndexedSlicesTest(test_util.TensorFlowTestCase): + @test_util.run_in_graph_and_eager_modes def testToTensor(self): - with self.cached_session(): - values = constant_op.constant([2, 3, 5, 7], shape=[2, 2]) - indices = constant_op.constant([0, 2]) - dense_shape = constant_op.constant([3, 2]) - x = ops.IndexedSlices(values, indices, dense_shape) - tensor = ops.convert_to_tensor(x, name="tensor") - self.assertAllEqual(tensor.eval(), [[2, 3], [0, 0], [5, 7]]) - + values = constant_op.constant([2, 3, 5, 7], shape=[2, 2]) + indices = constant_op.constant([0, 2]) + dense_shape = constant_op.constant([3, 2]) + x = ops.IndexedSlices(values, indices, dense_shape) + tensor = ops.convert_to_tensor(x, name="tensor") + self.assertAllEqual(self.evaluate(tensor), [[2, 3], [0, 0], [5, 7]]) + + @test_util.run_deprecated_v1 def testNegation(self): with self.cached_session(): values = constant_op.constant([2, 3, 5, 7], shape=[2, 2]) @@ -157,6 +164,7 @@ class IndexedSlicesTest(test_util.TensorFlowTestCase): self.assertAllEqual(x.values.eval(), [[-2, -3], [-5, -7]]) self.assertAllEqual(x.indices.eval(), [0, 2]) + @test_util.run_deprecated_v1 def testScalarMul(self): with self.cached_session(): values = constant_op.constant([2, 3, 5, 7], shape=[2, 2]) @@ -190,6 +198,7 @@ def _apply_op(g, *args, **kwargs): class OperationTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testNoInputs(self): op = test_ops.float_output_string_output(name="myop").a.op self.assertEqual(2, len(op.values())) @@ -212,6 +221,7 @@ class OperationTest(test_util.TensorFlowTestCase): self.assertProtoEquals("op:'FloatOutputStringOutput' name:'myop'", op.node_def) + @test_util.run_deprecated_v1 def testNoOutputs(self): op1 = test_ops.float_output(name="myop1").op float_t, = op1.values() @@ -227,6 +237,7 @@ class OperationTest(test_util.TensorFlowTestCase): self.assertProtoEquals("op:'FloatInput' name:'myop2' input:'myop1'", op2.node_def) + @test_util.run_deprecated_v1 def testInputsAndOutputs(self): op1 = test_ops.float_output(name="myop1").op self.assertEqual(1, len(op1.values())) @@ -308,16 +319,17 @@ class OperationTest(test_util.TensorFlowTestCase): with self.assertRaises(ValueError): ops.Operation(ops._NodeDef("op", "invalid:0"), g) + @test_util.run_deprecated_v1 def testNoShapeFunction(self): op = test_ops.a() self.assertEqual(tensor_shape.unknown_shape(), op.get_shape()) + @test_util.run_in_graph_and_eager_modes def testConvertToTensorNestedArray(self): - with self.cached_session(): - values = [[2], [3], [5], [7]] - tensor = ops.convert_to_tensor(values) - self.assertAllEqual((4, 1), tensor.get_shape().as_list()) - self.assertAllEqual(values, tensor.eval()) + values = [[2], [3], [5], [7]] + tensor = ops.convert_to_tensor(values) + self.assertAllEqual((4, 1), tensor.get_shape().as_list()) + self.assertAllEqual(values, self.evaluate(tensor)) def testShapeTuple(self): with self.cached_session(): @@ -333,57 +345,63 @@ class OperationTest(test_util.TensorFlowTestCase): converted = ops.convert_to_tensor(1) self.assertTrue(isinstance(converted, ops.EagerTensor)) + @test_util.run_in_graph_and_eager_modes def testConvertToTensorNestedTuple(self): - with self.cached_session(): - values = ((2,), (3,), (5,), (7,)) - tensor = ops.convert_to_tensor(values) - self.assertAllEqual((4, 1), tensor.get_shape().as_list()) - self.assertAllEqual(values, ops.convert_to_tensor(values).eval()) + values = ((2,), (3,), (5,), (7,)) + tensor = ops.convert_to_tensor(values) + self.assertAllEqual((4, 1), tensor.get_shape().as_list()) + self.assertAllEqual(values, self.evaluate(ops.convert_to_tensor(values))) + @test_util.run_in_graph_and_eager_modes def testConvertToTensorNestedTensors(self): - with self.cached_session(): - values = ((2,), (3,), (5,), (7,)) - tensor = ops.convert_to_tensor( - [constant_op.constant(row) for row in values]) - self.assertAllEqual((4, 1), tensor.get_shape().as_list()) - self.assertAllEqual(values, tensor.eval()) - tensor = ops.convert_to_tensor( - [[constant_op.constant(v) for v in row] for row in values]) - self.assertAllEqual((4, 1), tensor.get_shape().as_list()) - self.assertAllEqual(values, tensor.eval()) + values = ((2,), (3,), (5,), (7,)) + tensor = ops.convert_to_tensor( + [constant_op.constant(row) for row in values]) + self.assertAllEqual((4, 1), tensor.get_shape().as_list()) + self.assertAllEqual(values, self.evaluate(tensor)) + tensor = ops.convert_to_tensor( + [[constant_op.constant(v) for v in row] for row in values]) + self.assertAllEqual((4, 1), tensor.get_shape().as_list()) + self.assertAllEqual(values, self.evaluate(tensor)) + @test_util.run_in_graph_and_eager_modes def testConvertToTensorNestedMix(self): - with self.cached_session(): - values = ([2], (3,), [constant_op.constant(5)], constant_op.constant([7])) - tensor = ops.convert_to_tensor(values) - self.assertAllEqual((4, 1), tensor.get_shape().as_list()) - self.assertAllEqual(((2,), (3,), (5,), (7,)), tensor.eval()) + values = ([2], (3,), [constant_op.constant(5)], constant_op.constant([7])) + tensor = ops.convert_to_tensor(values) + self.assertAllEqual((4, 1), tensor.get_shape().as_list()) + self.assertAllEqual(((2,), (3,), (5,), (7,)), self.evaluate(tensor)) + @test_util.run_in_graph_and_eager_modes def testConvertToTensorPreferred(self): - with self.cached_session(): - values = [2, 3, 5, 7] - tensor = ops.convert_to_tensor(values, preferred_dtype=dtypes.float32) - self.assertEqual(dtypes.float32, tensor.dtype) + values = [2, 3, 5, 7] + tensor = ops.convert_to_tensor(values, preferred_dtype=dtypes.float32) + self.assertEqual(dtypes.float32, tensor.dtype) - with self.cached_session(): - # Convert empty tensor to anything. - values = [] - tensor = ops.convert_to_tensor(values, preferred_dtype=dtypes.int64) - self.assertEqual(dtypes.int64, tensor.dtype) + # Convert empty tensor to anything. + values = [] + tensor = ops.convert_to_tensor(values, preferred_dtype=dtypes.int64) + self.assertEqual(dtypes.int64, tensor.dtype) - with self.cached_session(): - # The preferred dtype is a type error and will convert to - # float32 instead. - values = [1.23] - tensor = ops.convert_to_tensor(values, preferred_dtype=dtypes.int64) - self.assertEqual(dtypes.float32, tensor.dtype) + # The preferred dtype is a type error and will convert to + # float32 instead. + values = [1.23] + tensor = ops.convert_to_tensor(values, preferred_dtype=dtypes.int64) + self.assertEqual(dtypes.float32, tensor.dtype) + @test_util.run_in_graph_and_eager_modes def testConvertToInvalidTensorType(self): with self.assertRaises(TypeError): # Forcing an invalid dtype should fail with a type error. values = [1.23] - _ = ops.convert_to_tensor(values, dtype=dtypes.int64) + ops.convert_to_tensor(values, dtype=dtypes.int64) + @test_util.run_in_graph_and_eager_modes + def testConvertToTensorFromInvalidTensor(self): + tensor = constant_op.constant(42.0, dtype=dtypes.float32) + with self.assertRaises(ValueError): + ops.convert_to_tensor(tensor, dtype=dtypes.int32) + + @test_util.run_deprecated_v1 def testNoConvert(self): # Operation cannot be converted to Tensor. op = control_flow_ops.no_op() @@ -401,6 +419,7 @@ class OperationTest(test_util.TensorFlowTestCase): ops._NodeDef("None", "op1"), ops.Graph(), [], [dtypes.float32]) self.assertEqual("", repr(op)) + @test_util.run_deprecated_v1 def testGetAttr(self): op = test_ops.default_attrs() self.assertEqual(op.get_attr("string_val"), b"abc") @@ -446,6 +465,7 @@ class OperationTest(test_util.TensorFlowTestCase): # TODO(b/65162920): remove this test when users who are directly mutating the # node_def have been updated to proper usage. + @test_util.run_deprecated_v1 def testSetAttr(self): op = test_ops.int_attr().op op._set_attr("foo", attr_value_pb2.AttrValue(i=2)) @@ -466,6 +486,7 @@ class OperationTest(test_util.TensorFlowTestCase): self.assertEqual(z.control_inputs, [x, y]) self.assertEqual(x._control_outputs, [z]) + @test_util.run_deprecated_v1 def testRemoveAllControlInputs(self): a = constant_op.constant(1) with ops.control_dependencies([a]): @@ -490,6 +511,7 @@ class OperationTest(test_util.TensorFlowTestCase): self.assertEqual(f.op.control_inputs, []) self.assertEqual(list(f.op.inputs), [d, e]) + @test_util.run_deprecated_v1 def testControlInputCycle(self): graph = ops.Graph() with graph.as_default(): @@ -503,7 +525,7 @@ class OperationTest(test_util.TensorFlowTestCase): with self.assertRaisesRegexp( errors.InvalidArgumentError, "Graph is invalid, contains a cycle with 2 nodes"): - sess.run(x) + self.evaluate(x) def testUpdateInput(self): g = ops.Graph() @@ -517,21 +539,21 @@ class OperationTest(test_util.TensorFlowTestCase): self.assertEquals(x.consumers(), []) self.assertEquals(y.consumers(), [z.op, z.op]) with session.Session(graph=g) as sess: - self.assertEquals(sess.run(z), 4) + self.assertEquals(self.evaluate(z), 4) z.op._update_input(0, x) # pylint: disable=protected-access self.assertEquals(list(z.op.inputs), [x, y]) self.assertEquals(x.consumers(), [z.op]) self.assertEquals(y.consumers(), [z.op]) with session.Session(graph=g) as sess: - self.assertEquals(sess.run(z), 3) + self.assertEquals(self.evaluate(z), 3) z.op._update_input(1, y) # pylint: disable=protected-access self.assertEquals(list(z.op.inputs), [x, y]) self.assertEquals(x.consumers(), [z.op]) self.assertEquals(y.consumers(), [z.op]) with session.Session(graph=g) as sess: - self.assertEquals(sess.run(z), 3) + self.assertEquals(self.evaluate(z), 3) def testUpdateInputGraphError(self): g_0 = ops.Graph() @@ -557,7 +579,7 @@ class OperationTest(test_util.TensorFlowTestCase): errors.InvalidArgumentError, "Input 0 of node add was passed string from Const_1:0 incompatible " "with expected int32"): - sess.run(z) + self.evaluate(z) def testUpdateInputShapeError(self): g = ops.Graph() @@ -582,6 +604,32 @@ class OperationTest(test_util.TensorFlowTestCase): ): x.op._update_input(1, x) # pylint: disable=protected-access + @test_util.enable_control_flow_v2 + def testAddWhileInput(self): + @eager_function.defun + def test(): + output = control_flow_ops.while_loop(lambda x: x < 3, lambda x: x + 1, + [1]) + while_op = output.op.inputs[0].op + self.assertEqual(while_op.type, "While") + orig_num_inputs = len(while_op.inputs) + + new_input1 = constant_op.constant(1.0) + new_input2 = constant_op.constant(True) + + while_op._set_type_list_attr("T", + [t.dtype for t in while_op.inputs] + + [new_input1.dtype, new_input2.dtype]) + + while_op._add_while_inputs([new_input1, new_input2]) + # Can't add an edge beyond what's specified by "T" + with self.assertRaises(errors.OutOfRangeError): + while_op._add_while_inputs([new_input2]) + self.assertEqual(len(while_op.inputs), orig_num_inputs + 2) # pylint: disable=g-deprecated-assert + + test() + + @test_util.run_deprecated_v1 def testOpDef(self): x = constant_op.constant(0) y = constant_op.constant(1) @@ -681,6 +729,7 @@ class CreateOpTest(test_util.TensorFlowTestCase): # the low-level behavior. class CreateOpFromTFOperationTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testBasic(self): g = ops.Graph() with g.as_default(): @@ -701,7 +750,6 @@ class CreateOpFromTFOperationTest(test_util.TensorFlowTestCase): self.assertEqual(g.get_operation_by_name("myop"), op) self.assertEqual(g.get_tensor_by_name("myop:0"), op.outputs[0]) - @test_util.enable_c_shapes def testShape(self): g = ops.Graph() with g.as_default(): @@ -732,6 +780,7 @@ class CreateOpFromTFOperationTest(test_util.TensorFlowTestCase): self.assertEqual(op3.name, "myop_2") self.assertEqual(op4.name, "myop_1_1") + @test_util.run_deprecated_v1 def testCond(self): g = ops.Graph() with g.as_default(): @@ -761,6 +810,7 @@ class CreateOpFromTFOperationTest(test_util.TensorFlowTestCase): "cond/cond_text") # pylint: enable=protected-access + @test_util.run_deprecated_v1 def testWhileLoop(self): g = ops.Graph() with g.as_default(): @@ -790,6 +840,7 @@ class CreateOpFromTFOperationTest(test_util.TensorFlowTestCase): "myloop/while_context") # pylint: enable=protected-access + @test_util.run_deprecated_v1 def testWhileLoopWithInternalControlDep(self): g = ops.Graph() with g.as_default(): @@ -813,6 +864,7 @@ class CreateOpFromTFOperationTest(test_util.TensorFlowTestCase): # Internal control dep is preserved self.assertEqual(op.control_inputs, [c]) + @test_util.run_deprecated_v1 def testWhileLoopWithExternalControlDep(self): g = ops.Graph() with g.as_default(): @@ -946,6 +998,7 @@ class NameStackTest(test_util.TensorFlowTestCase): self.assertEqual("bar_2", g.unique_name("bar", mark_as_used=False)) self.assertEqual("bar_2", g.unique_name("bar")) + @test_util.run_deprecated_v1 def testNameAndVariableScope(self): with self.cached_session() as sess: with sess.graph.name_scope("l0"): @@ -1076,6 +1129,13 @@ class DeviceTest(test_util.TensorFlowTestCase): node { name: "FloatOutput" op: "FloatOutput" } """, gd) + def testEagerBackingDevice(self): + with context.eager_mode(): + with ops.device("/device:CPU:0"): + t = constant_op.constant(1.0) + self.assertRegexpMatches(t.device, "/device:CPU:0") + self.assertRegexpMatches(t.backing_device, "/device:CPU:0") + def testDevicePartialString(self): g = ops.Graph() with g.device("/job:worker/replica:2"): @@ -1665,6 +1725,7 @@ def _CopyOverrideGrad(op, x_grad): # pylint: disable=invalid-name class RegistrationTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testRegisterGradients(self): x = test_ops.float_output() y = test_ops.copy_op(x) @@ -1704,6 +1765,7 @@ class ComparisonTest(test_util.TensorFlowTestCase): class ControlDependenciesTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testBasic(self): g = ops.Graph() with g.as_default(): @@ -1947,6 +2009,7 @@ class OpScopeTest(test_util.TensorFlowTestCase): with ops.name_scope(None, "default2") as scope2: self.assertEqual(scope2, "default/default2/") + @test_util.run_deprecated_v1 def testNoScopeName(self): g0 = ops.Graph() values = [ @@ -1960,6 +2023,7 @@ class OpScopeTest(test_util.TensorFlowTestCase): with ops.name_scope(None, None, values): pass + @test_util.run_deprecated_v1 def testEmptyScopeName(self): g0 = ops.Graph() a = g0.create_op("A", [], [dtypes.float32]) @@ -1971,6 +2035,7 @@ class OpScopeTest(test_util.TensorFlowTestCase): self.assertEqual("", scope) self.assertEqual(g0, ops.get_default_graph()) + @test_util.run_deprecated_v1 def testDefaultScopeName(self): g0 = ops.Graph() a = g0.create_op("A", [], [dtypes.float32]) @@ -1995,12 +2060,14 @@ class OpScopeTest(test_util.TensorFlowTestCase): with ops.name_scope(scope_name, values=graph_elements + [a]): pass + @test_util.run_deprecated_v1 def testTensor(self): g0 = ops.Graph() a = g0.create_op("A", [], [dtypes.float32]) b = g0.create_op("B", [], [dtypes.float32]) self._testGraphElements([a, b]) + @test_util.run_deprecated_v1 def testSparseTensor(self): g0 = ops.Graph() a = g0.create_op("A", [], [dtypes.float32]) @@ -2011,6 +2078,7 @@ class OpScopeTest(test_util.TensorFlowTestCase): _apply_op(g0, "Int64Output", [], [dtypes.int64])) self._testGraphElements([a, sparse, b]) + @test_util.run_deprecated_v1 def testVariable(self): g0 = ops.Graph() with g0.as_default(): @@ -2215,6 +2283,7 @@ class InitScopeTest(test_util.TensorFlowTestCase): self.assertEqual(4, int(compiled_outer(inner=compiled_inner))) self.assertEqual(7, int(compiled_outer(inner=compiled_inner))) + @test_util.run_deprecated_v1 def testFallsBackToGlobalGraphWhenAllGraphsAreBuildingFunctions(self): with context.graph_mode(): ops.reset_default_graph() @@ -2351,6 +2420,7 @@ class GraphTest(test_util.TensorFlowTestCase): g.prevent_feeding(a) self.assertFalse(g.is_feedable(a)) + @test_util.run_deprecated_v1 def testPreventFetching(self): g = ops.Graph() a = constant_op.constant(2.0) @@ -2391,7 +2461,7 @@ class GraphTest(test_util.TensorFlowTestCase): c = math_ops.add(a, b) # Create a session we can delete with session.Session(graph=g) as sess: - sess.run(c) + self.evaluate(c) # Delete all references and trigger gc del g del a @@ -2407,7 +2477,7 @@ class GraphTest(test_util.TensorFlowTestCase): math_ops.add([1, 2], [1, 2, 3]) a = constant_op.constant(1) with session.Session() as sess: - sess.run(a) + self.evaluate(a) def testRunnableAfterInvalidShapeWithKernelLabelMap(self): g = ops.Graph() @@ -2417,7 +2487,7 @@ class GraphTest(test_util.TensorFlowTestCase): test_ops.kernel_label_required(1) a = constant_op.constant(1) with session.Session() as sess: - sess.run(a) + self.evaluate(a) class AttrScopeTest(test_util.TensorFlowTestCase): @@ -2434,10 +2504,12 @@ class AttrScopeTest(test_util.TensorFlowTestCase): b = None return (a, b) + @test_util.run_deprecated_v1 def testNoLabel(self): with self.cached_session(): self.assertAllEqual((None, None), self._get_test_attrs()) + @test_util.run_deprecated_v1 def testLabelMap(self): with self.cached_session() as sess: a1 = self._get_test_attrs() @@ -2472,11 +2544,13 @@ ops.RegisterShape("KernelLabel")(common_shapes.scalar_shape) class KernelLabelTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testNoLabel(self): with self.cached_session(): self.assertAllEqual(b"My label is: default", test_ops.kernel_label().eval()) + @test_util.run_deprecated_v1 def testLabelMap(self): with self.cached_session() as sess: default_1 = test_ops.kernel_label() @@ -2491,12 +2565,14 @@ class KernelLabelTest(test_util.TensorFlowTestCase): # pylint: enable=protected-access default_3 = test_ops.kernel_label() - self.assertAllEqual(b"My label is: default", default_1.eval()) - self.assertAllEqual(b"My label is: default", default_2.eval()) - self.assertAllEqual(b"My label is: default", default_3.eval()) - self.assertAllEqual(b"My label is: overload_1", overload_1_1.eval()) - self.assertAllEqual(b"My label is: overload_1", overload_1_2.eval()) - self.assertAllEqual(b"My label is: overload_2", overload_2.eval()) + self.assertAllEqual(b"My label is: default", self.evaluate(default_1)) + self.assertAllEqual(b"My label is: default", self.evaluate(default_2)) + self.assertAllEqual(b"My label is: default", self.evaluate(default_3)) + self.assertAllEqual(b"My label is: overload_1", + self.evaluate(overload_1_1)) + self.assertAllEqual(b"My label is: overload_1", + self.evaluate(overload_1_2)) + self.assertAllEqual(b"My label is: overload_2", self.evaluate(overload_2)) class AsGraphDefTest(test_util.TensorFlowTestCase): @@ -2591,6 +2667,7 @@ class StatisticsTest(test_util.TensorFlowTestCase): class DeviceStackTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testBasicDeviceAssignmentMetadata(self): def device_func(unused_op): @@ -2622,6 +2699,7 @@ class DeviceStackTest(test_util.TensorFlowTestCase): expected_regex = r"device_func<.*ops_test.py, [0-9]+" self.assertRegexpMatches(func_description, expected_regex) + @test_util.run_deprecated_v1 def testDeviceAssignmentMetadataForGraphDeviceAndTfDeviceFunctions(self): with ops.device("/cpu"): @@ -2641,6 +2719,7 @@ class DeviceStackTest(test_util.TensorFlowTestCase): class ColocationGroupTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testBasic(self): a = constant_op.constant([2.0], name="a") with ops.colocate_with(a.op): @@ -2651,6 +2730,7 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): with self.assertRaises(ValueError): c.op.get_attr("_class") + @test_util.run_deprecated_v1 def testBasicColocationMetadata(self): const_two = constant_op.constant([2.0], name="two") with ops.colocate_with(const_two.op): @@ -2663,6 +2743,7 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): # colocation statement. self.assertEqual("ops_test.py", os.path.basename(metadata.filename)) + @test_util.run_deprecated_v1 def testColocationDeviceInteraction(self): with ops.device("/cpu:0"): with ops.device("/device:GPU:0"): @@ -2675,6 +2756,7 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): self.assertEqual([b"loc:@a"], b.op.colocation_groups()) self.assertEqual(a.op.device, b.op.device) + @test_util.run_deprecated_v1 def testColocationCanonicalization(self): with ops.device("/device:GPU:0"): _ = constant_op.constant(2.0) @@ -2690,6 +2772,7 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): # inherits B's device name, after canonicalizing the names. self.assertEqual(b.op.device, c.op.device) + @test_util.run_deprecated_v1 def testLocationOverrides(self): with ops.device("/cpu:0"): with ops.device("/device:GPU:0"): @@ -2711,6 +2794,7 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): self.assertEqual("/device:GPU:0", c.op.device) self.assertEqual("/device:CPU:0", d.op.device) + @test_util.run_deprecated_v1 def testNestedColocateWith(self): a = constant_op.constant([2.0], name="a") with ops.colocate_with(a.op): @@ -2720,6 +2804,7 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): self.assertEqual([b"loc:@a"], b.op.colocation_groups()) self.assertEqual([b"loc:@a"], c.op.colocation_groups()) + @test_util.run_deprecated_v1 def testMultiColocationGroups(self): a = constant_op.constant([2.0], name="a") b = constant_op.constant(3.0, name="b") @@ -2728,6 +2813,7 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): c = constant_op.constant(4.0) self.assertEqual(set([b"loc:@a", b"loc:@b"]), set(c.op.colocation_groups())) + @test_util.run_deprecated_v1 def testColocationIgnoreStack(self): a = constant_op.constant([2.0], name="a") b = constant_op.constant(3.0, name="b") @@ -2736,6 +2822,7 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): c = constant_op.constant(4.0) self.assertEqual(set([b"loc:@b"]), set(c.op.colocation_groups())) + @test_util.run_deprecated_v1 def testColocateWithReset(self): a = constant_op.constant([2.0], name="a") with ops.colocate_with(a.op): @@ -2745,6 +2832,7 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): self.assertEqual([b"loc:@a"], b.op.colocation_groups()) self.assertEqual([b"loc:@c"], c.op.colocation_groups()) + @test_util.run_deprecated_v1 def testColocateWithInitialNoneThenNested(self): a = constant_op.constant([2.0], name="a") with ops.colocate_with(a.op): @@ -2755,47 +2843,13 @@ class ColocationGroupTest(test_util.TensorFlowTestCase): self.assertEqual([b"loc:@b"], b.op.colocation_groups()) self.assertEqual([b"loc:@b"], c.op.colocation_groups()) + @test_util.run_deprecated_v1 def testColocateVariables(self): a = variables.Variable([2.0], name="a") with ops.colocate_with(a.op): b = variables.Variable([3.0], name="b") self.assertEqual([b"loc:@a"], b.op.colocation_groups()) - def testInconsistentDeviceWithinColocate(self): - with ops.device("/device:GPU:0"): - a = constant_op.constant([2.0], name="a") - with ops.colocate_with(a.op): - # This is allowed due to legacy but clearly wrong, since we - # should really be colocating with 'a'. We allow devices to - # override colocate_with, but we log warnings to suggest that - # this is probably unintentional or misguided. - with ops.device("/cpu:0"): - b = constant_op.constant([3.0], name="b") - - self.assertEqual("/device:CPU:0", b.device) - - def testMakeColocationConflictMessage(self): - """Test that provides an example of a complicated error message.""" - # We could test the message with any ops, but this test will be more - # instructive with a real colocation conflict. - with ops.device("/device:GPU:0"): - a = constant_op.constant([2.0], name="a") - with ops.colocate_with(a.op): - with ops.device("/cpu:0"): - b = constant_op.constant([3.0], name="b") - # The definition-location of the nodes will be wrong because of running - # from within a TF unittest. The rest of the info should be correct. - message = ops.get_default_graph()._make_colocation_conflict_message(a.op, - b.op) - self.assertRegexpMatches(message, - r"Tried to colocate op 'a' \(defined at.*\)") - self.assertRegexpMatches(message, "No node-device.*'a'") - self.assertRegexpMatches(message, "Device assignments active.*'a'") - self.assertRegexpMatches(message, "GPU:0") - self.assertRegexpMatches(message, "Node-device colocations active.*'b'") - self.assertRegexpMatches(message, "Device assignments active.*'b'") - self.assertRegexpMatches(message, "cpu:0") - class DeprecatedTest(test_util.TensorFlowTestCase): @@ -2918,6 +2972,7 @@ class NameScopeTest(test_util.TensorFlowTestCase): class TracebackTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testTracebackWithStartLines(self): with self.cached_session() as sess: a = constant_op.constant(2.0) @@ -2939,6 +2994,7 @@ class TracebackTest(test_util.TensorFlowTestCase): class EnableEagerExecutionTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testBadArgumentsToEnableEagerExecution(self): with self.assertRaisesRegexp(TypeError, "config must be a tf.ConfigProto"): ops.enable_eager_execution(context.DEVICE_PLACEMENT_SILENT) diff --git a/tensorflow/python/framework/python_op_gen.cc b/tensorflow/python/framework/python_op_gen.cc index 465016b808..d91f7b0bdd 100644 --- a/tensorflow/python/framework/python_op_gen.cc +++ b/tensorflow/python/framework/python_op_gen.cc @@ -142,6 +142,7 @@ class GenEagerPythonOp : public python_op_gen_internal::GenPythonOp { void AddEagerAttrs(const string& indentation); void AddEagerExecute(const string& indentation, const string& num_outputs_expr); + void AddDispatch(const string& prefix); void AddAttrForArg(const string& attr, int arg_index) { gtl::InsertIfNotPresent(&inferred_attrs_, attr, @@ -356,9 +357,14 @@ string GenEagerPythonOp::Code() { void GenEagerPythonOp::HandleGraphMode(const string& function_setup) { strings::StrAppend(&result_, " # Add nodes to the TensorFlow graph.\n"); - strings::StrAppend(&result_, function_setup, - " _, _, _op = _op_def_lib._apply_op_helper(\n"); - AddBodyNoReturn(" "); + strings::StrAppend(&result_, function_setup); + if (api_def_.visibility() == ApiDef::VISIBLE) { + strings::StrAppend(&result_, " try:\n "); + } + strings::StrAppend(&result_, " _, _, _op = _op_def_lib._apply_op_helper(\n"); + AddBodyNoReturn(strings::StrCat(" \"", op_def_.name(), "\", ")); + AddDispatch(" "); + if (num_outs_ > 0) { strings::StrAppend(&result_, " _result = _op.outputs[:]\n"); // Special case handling for stateful op with single list output @@ -628,6 +634,7 @@ void GenEagerPythonOp::AddEagerFunctionTeardown( bool GenEagerPythonOp::AddEagerFastPathAndGraphCode( const string& parameters, const std::vector& output_sizes, const string& eager_not_allowed_error) { + strings::StrAppend(&result_, "@_dispatch.add_dispatch_list\n"); AddExport(); AddDefLine(function_name_, parameters); AddDocStringDescription(); @@ -758,6 +765,7 @@ void GenEagerPythonOp::AddEagerFastPathExecute() { strings::StrAppend(&result_, " except _core._SymbolicException:\n"); strings::StrAppend(&result_, " pass # Add nodes to the TensorFlow graph.\n"); + AddDispatch(" "); // Any errors thrown from execute need to be unwrapped from // _NotOkStatusException. @@ -898,6 +906,19 @@ void GenEagerPythonOp::AddEagerExecute(const string& indentation, WordWrap(return_prefix, return_args, kRightMargin), "\n"); } +void GenEagerPythonOp::AddDispatch(const string& prefix) { + if (api_def_.visibility() != ApiDef::VISIBLE) return; + + strings::StrAppend(&result_, prefix, "except (TypeError, ValueError):\n"); + strings::StrAppend(&result_, prefix, " result = _dispatch.dispatch(\n"); + AddBodyNoReturn(strings::StrCat(prefix, " ", function_name_, ", ")); + strings::StrAppend(&result_, prefix, + " if result is not " + "_dispatch.OpDispatcher.NOT_SUPPORTED:\n"); + strings::StrAppend(&result_, prefix, " return result\n"); + strings::StrAppend(&result_, prefix, " raise\n"); +} + string GetPythonOps(const OpList& ops, const ApiDefMap& api_defs, const std::vector& hidden_ops, bool require_shapes, const string& source_file_name = "") { @@ -937,6 +958,7 @@ from tensorflow.python.framework import op_def_registry as _op_def_registry from tensorflow.python.framework import ops as _ops from tensorflow.python.framework import op_def_library as _op_def_library from tensorflow.python.util.deprecation import deprecated_endpoints +from tensorflow.python.util import dispatch as _dispatch from tensorflow.python.util.tf_export import tf_export )"); diff --git a/tensorflow/python/framework/python_op_gen_internal.cc b/tensorflow/python/framework/python_op_gen_internal.cc index 65b9ad5c6a..cbdeecfbfb 100644 --- a/tensorflow/python/framework/python_op_gen_internal.cc +++ b/tensorflow/python/framework/python_op_gen_internal.cc @@ -804,8 +804,8 @@ void GenPythonOp::AddDocStringOutputs() { } void GenPythonOp::AddBody(const string& prefix) { - const string apply_prefix = - strings::StrCat(prefix, "_result = _op_def_lib.apply_op("); + const string apply_prefix = strings::StrCat( + prefix, "_result = _op_def_lib.apply_op(\"", op_def_.name(), "\", "); AddBodyNoReturn(apply_prefix); if (num_outs_ > 1) { strings::StrAppend(&result_, prefix, "_result = _", op_def_.name(), @@ -815,7 +815,7 @@ void GenPythonOp::AddBody(const string& prefix) { } void GenPythonOp::AddBodyNoReturn(const string& apply_prefix) { - string args = strings::StrCat("\"", op_def_.name(), "\", "); + string args; for (size_t i = 0; i < param_names_.size(); ++i) { strings::StrAppend(&args, AvoidPythonReserved(param_names_[i].GetName()), "=", param_names_[i].GetRenameTo(), ", "); diff --git a/tensorflow/python/framework/random_seed.py b/tensorflow/python/framework/random_seed.py index 777bb2fe8c..6b7f56a92c 100644 --- a/tensorflow/python/framework/random_seed.py +++ b/tensorflow/python/framework/random_seed.py @@ -34,7 +34,7 @@ def _truncate_seed(seed): return seed % _MAXINT32 # Truncate to fit into 32-bit integer -@tf_export('random.get_seed', v1=['random.get_seed', 'get_seed']) +@tf_export(v1=['random.get_seed', 'get_seed']) @deprecation.deprecated_endpoints('get_seed') def get_seed(op_seed): """Returns the local seeds an operation should use given an op-specific seed. @@ -45,7 +45,7 @@ def get_seed(op_seed): graph, or for only specific operations. For details on how the graph-level seed interacts with op seeds, see - `tf.set_random_seed`. + `tf.random.set_random_seed`. Args: op_seed: integer. @@ -82,7 +82,7 @@ def get_seed(op_seed): return seeds -@tf_export('random.set_random_seed', 'set_random_seed') +@tf_export(v1=['random.set_random_seed', 'set_random_seed']) def set_random_seed(seed): """Sets the graph-level random seed. @@ -154,7 +154,7 @@ def set_random_seed(seed): sessions, set a graph-level seed: ```python - tf.set_random_seed(1234) + tf.random.set_random_seed(1234) a = tf.random_uniform([1]) b = tf.random_normal([1]) @@ -182,3 +182,103 @@ def set_random_seed(seed): context.set_global_seed(seed) else: ops.get_default_graph().seed = seed + + +@tf_export('random.set_seed', v1=[]) +def set_seed(seed): + """Sets the graph-level random seed. + + Operations that rely on a random seed actually derive it from two seeds: + the graph-level and operation-level seeds. This sets the graph-level seed. + + Its interactions with operation-level seeds is as follows: + + 1. If neither the graph-level nor the operation seed is set: + A random seed is used for this op. + 2. If the graph-level seed is set, but the operation seed is not: + The system deterministically picks an operation seed in conjunction + with the graph-level seed so that it gets a unique random sequence. + 3. If the graph-level seed is not set, but the operation seed is set: + A default graph-level seed and the specified operation seed are used to + determine the random sequence. + 4. If both the graph-level and the operation seed are set: + Both seeds are used in conjunction to determine the random sequence. + + To illustrate the user-visible effects, consider these examples: + + To generate different sequences across sessions, set neither + graph-level nor op-level seeds: + + ```python + a = tf.random_uniform([1]) + b = tf.random_normal([1]) + + print("Session 1") + with tf.Session() as sess1: + print(sess1.run(a)) # generates 'A1' + print(sess1.run(a)) # generates 'A2' + print(sess1.run(b)) # generates 'B1' + print(sess1.run(b)) # generates 'B2' + + print("Session 2") + with tf.Session() as sess2: + print(sess2.run(a)) # generates 'A3' + print(sess2.run(a)) # generates 'A4' + print(sess2.run(b)) # generates 'B3' + print(sess2.run(b)) # generates 'B4' + ``` + + To generate the same repeatable sequence for an op across sessions, set the + seed for the op: + + ```python + a = tf.random_uniform([1], seed=1) + b = tf.random_normal([1]) + + # Repeatedly running this block with the same graph will generate the same + # sequence of values for 'a', but different sequences of values for 'b'. + print("Session 1") + with tf.Session() as sess1: + print(sess1.run(a)) # generates 'A1' + print(sess1.run(a)) # generates 'A2' + print(sess1.run(b)) # generates 'B1' + print(sess1.run(b)) # generates 'B2' + + print("Session 2") + with tf.Session() as sess2: + print(sess2.run(a)) # generates 'A1' + print(sess2.run(a)) # generates 'A2' + print(sess2.run(b)) # generates 'B3' + print(sess2.run(b)) # generates 'B4' + ``` + + To make the random sequences generated by all ops be repeatable across + sessions, set a graph-level seed: + + ```python + tf.random.set_seed(1234) + a = tf.random_uniform([1]) + b = tf.random_normal([1]) + + # Repeatedly running this block with the same graph will generate the same + # sequences of 'a' and 'b'. + print("Session 1") + with tf.Session() as sess1: + print(sess1.run(a)) # generates 'A1' + print(sess1.run(a)) # generates 'A2' + print(sess1.run(b)) # generates 'B1' + print(sess1.run(b)) # generates 'B2' + + print("Session 2") + with tf.Session() as sess2: + print(sess2.run(a)) # generates 'A1' + print(sess2.run(a)) # generates 'A2' + print(sess2.run(b)) # generates 'B1' + print(sess2.run(b)) # generates 'B2' + ``` + + Args: + seed: integer. + """ + # TODO(go/tf2-random): change doc, update to match design doc + set_random_seed(seed) diff --git a/tensorflow/python/framework/registry.py b/tensorflow/python/framework/registry.py index 2e45acb499..4357c76bd6 100644 --- a/tensorflow/python/framework/registry.py +++ b/tensorflow/python/framework/registry.py @@ -23,10 +23,9 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import traceback - from tensorflow.python.platform import tf_logging as logging from tensorflow.python.util import compat +from tensorflow.python.util import tf_stack # Registry mechanism below is based on mapreduce.python.mrpython.Register. @@ -57,15 +56,17 @@ class Registry(object): if name in self._registry: (filename, line_number, function_name, _) = ( self._registry[name][_LOCATION_TAG]) - raise KeyError("Registering two %s with name '%s' !" + raise KeyError("Registering two %s with name '%s'! " "(Previous registration was in %s %s:%d)" % (self._name, name, function_name, filename, line_number)) logging.vlog(1, "Registering %s (%s) in %s.", name, candidate, self._name) # stack trace is [this_function, Register(), user_function,...] # so the user function is #2. - stack = traceback.extract_stack() - self._registry[name] = {_TYPE_TAG: candidate, _LOCATION_TAG: stack[2]} + stack = tf_stack.extract_stack() + user_function = stack[2] + location_tag = tf_stack.convert_stack([user_function])[0] + self._registry[name] = {_TYPE_TAG: candidate, _LOCATION_TAG: location_tag} def list(self): """Lists registered items. diff --git a/tensorflow/python/framework/registry_test.py b/tensorflow/python/framework/registry_test.py index a821e16f26..1a0d3f200d 100644 --- a/tensorflow/python/framework/registry_test.py +++ b/tensorflow/python/framework/registry_test.py @@ -45,7 +45,9 @@ class RegistryTest(test.TestCase): def testDuplicate(self): myreg = registry.Registry('testbar') myreg.register(bar, 'Bar') - with self.assertRaises(KeyError): + with self.assertRaisesRegexp( + KeyError, r'Registering two testbar with name \'Bar\'! ' + r'\(Previous registration was in [^ ]+ .*.py:[0-9]+\)'): myreg.register(bar, 'Bar') diff --git a/tensorflow/python/framework/smart_cond_test.py b/tensorflow/python/framework/smart_cond_test.py index b8a9672b06..f964c87f02 100644 --- a/tensorflow/python/framework/smart_cond_test.py +++ b/tensorflow/python/framework/smart_cond_test.py @@ -35,6 +35,7 @@ def raise_exception(): class SmartCondTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testTrue(self): with ops.Graph().as_default(): with session.Session(): @@ -44,6 +45,7 @@ class SmartCondTest(test_util.TensorFlowTestCase): lambda: math_ops.multiply(y, 5)) self.assertEqual(z.eval(), 32) + @test_util.run_deprecated_v1 def testFalse(self): with ops.Graph().as_default(): with session.Session(): @@ -99,6 +101,7 @@ class SmartCondTest(test_util.TensorFlowTestCase): class SmartCaseTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testTrue(self): x = array_ops.placeholder(dtype=dtypes.int32, shape=[]) conditions = [(True, lambda: constant_op.constant(1)), @@ -109,9 +112,10 @@ class SmartCaseTest(test_util.TensorFlowTestCase): exclusive=True) with session.Session() as sess: # No feed_dict necessary - self.assertEqual(sess.run(y), 1) - self.assertEqual(sess.run(z), 1) + self.assertEqual(self.evaluate(y), 1) + self.assertEqual(self.evaluate(z), 1) + @test_util.run_deprecated_v1 def testFalse(self): conditions = [(False, raise_exception)] y = smart_cond.smart_case(conditions, @@ -121,9 +125,10 @@ class SmartCaseTest(test_util.TensorFlowTestCase): default=lambda: constant_op.constant(1), exclusive=True) with session.Session() as sess: - self.assertEqual(sess.run(y), 1) - self.assertEqual(sess.run(z), 1) + self.assertEqual(self.evaluate(y), 1) + self.assertEqual(self.evaluate(z), 1) + @test_util.run_deprecated_v1 def testMix(self): x = array_ops.placeholder(dtype=dtypes.int32, shape=[]) y = constant_op.constant(10) diff --git a/tensorflow/python/framework/sparse_tensor_test.py b/tensorflow/python/framework/sparse_tensor_test.py index 22423c4f58..a999c12ca8 100644 --- a/tensorflow/python/framework/sparse_tensor_test.py +++ b/tensorflow/python/framework/sparse_tensor_test.py @@ -46,11 +46,11 @@ class SparseTensorTest(test_util.TensorFlowTestCase): self.assertEqual(sp.get_shape(), (4, 5)) with self.cached_session() as sess: - value = sp.eval() + value = self.evaluate(sp) self.assertAllEqual(indices, value.indices) self.assertAllEqual(values, value.values) self.assertAllEqual(shape, value.dense_shape) - sess_run_value = sess.run(sp) + sess_run_value = self.evaluate(sp) self.assertAllEqual(sess_run_value.indices, value.indices) self.assertAllEqual(sess_run_value.values, value.values) self.assertAllEqual(sess_run_value.dense_shape, value.dense_shape) @@ -65,6 +65,7 @@ class SparseTensorTest(test_util.TensorFlowTestCase): sparse_tensor.is_sparse( sparse_tensor.SparseTensorValue([[0]], [0], [1]))) + @test_util.run_deprecated_v1 def testConsumers(self): sp = sparse_tensor.SparseTensor([[0, 0], [1, 2]], [1.0, 3.0], [3, 4]) w = ops.convert_to_tensor(np.ones([4, 1], np.float32)) @@ -85,8 +86,9 @@ class ConvertToTensorOrSparseTensorTest(test_util.TensorFlowTestCase): value = [42, 43] from_value = sparse_tensor.convert_to_tensor_or_sparse_tensor( value) - self.assertAllEqual(value, from_value.eval()) + self.assertAllEqual(value, self.evaluate(from_value)) + @test_util.run_deprecated_v1 def test_convert_sparse(self): with self.cached_session(): indices = [[0, 1], [1, 0]] diff --git a/tensorflow/python/framework/subscribe_test.py b/tensorflow/python/framework/subscribe_test.py index cab426844d..61c6ea6519 100644 --- a/tensorflow/python/framework/subscribe_test.py +++ b/tensorflow/python/framework/subscribe_test.py @@ -43,6 +43,7 @@ class SubscribeTest(test_util.TensorFlowTestCase): self.assertTrue( all(subscribe._is_subscribed_identity(x) for x in container)) + @test_util.run_deprecated_v1 def testSideEffect(self): a = constant_op.constant(1) b = constant_op.constant(1) @@ -66,15 +67,16 @@ class SubscribeTest(test_util.TensorFlowTestCase): self.assertTrue(c.op in d.op.control_inputs) with self.cached_session() as sess: - c_out = sess.run([c]) - n_out = sess.run([n]) - d_out = sess.run([d]) + c_out = self.evaluate([c]) + n_out = self.evaluate([n]) + d_out = self.evaluate([d]) self.assertEqual(n_out, [-2]) self.assertEqual(c_out, [2]) self.assertEqual(d_out, [42]) self.assertEqual(shared, [2, 2, 2]) + @test_util.run_deprecated_v1 def testSupportedTypes(self): """Confirm that supported types are correctly detected and handled.""" @@ -120,6 +122,7 @@ class SubscribeTest(test_util.TensorFlowTestCase): subscribe.subscribe(c.name, lambda t: script_ops.py_func(sub, [t], [t.dtype])) + @test_util.run_deprecated_v1 def testCaching(self): """Confirm caching of control output is recalculated between calls.""" a = constant_op.constant(1) @@ -145,13 +148,14 @@ class SubscribeTest(test_util.TensorFlowTestCase): lambda t: script_ops.py_func(sub, [t], [t.dtype])) with self.cached_session() as sess: - c_out = sess.run([c]) - d_out = sess.run([d]) + c_out = self.evaluate([c]) + d_out = self.evaluate([d]) self.assertEqual(c_out, [42]) self.assertEqual(d_out, [11]) self.assertEqual(shared, {2: 1, 1: 1}) + @test_util.run_deprecated_v1 def testIsSubscribedIdentity(self): """Confirm subscribed identity ops are correctly detected.""" a = constant_op.constant(1) @@ -165,6 +169,7 @@ class SubscribeTest(test_util.TensorFlowTestCase): self.assertFalse(subscribe._is_subscribed_identity(idop)) self.assertTrue(subscribe._is_subscribed_identity(c_sub)) + @test_util.run_deprecated_v1 def testSubscribeExtend(self): """Confirm side effect are correctly added for different input types.""" a = constant_op.constant(1) @@ -205,11 +210,12 @@ class SubscribeTest(test_util.TensorFlowTestCase): # Expect the three side effect graphs to have been evaluated. with self.cached_session() as sess: - sess.run([c_sub]) + self.evaluate([c_sub]) self.assertIn('graph1', shared) self.assertIn('graph2', shared) self.assertIn('graph3', shared) + @test_util.run_deprecated_v1 def testSubscribeVariable(self): """Confirm that variables can be subscribed.""" v1 = variables.VariableV1(0.0) @@ -229,25 +235,26 @@ class SubscribeTest(test_util.TensorFlowTestCase): with self.cached_session() as sess: # Initialize the variables first. - sess.run([v1.initializer]) - sess.run([v2.initializer]) + self.evaluate([v1.initializer]) + self.evaluate([v2.initializer]) # Expect the side effects to be triggered when evaluating the add op as # it will read the value of the variable. - sess.run([add]) + self.evaluate([add]) self.assertEqual(1, len(shared)) # Expect the side effect not to be triggered when evaluating the assign # op as it will not access the 'read' output of the variable. - sess.run([assign_v1]) + self.evaluate([assign_v1]) self.assertEqual(1, len(shared)) - sess.run([add]) + self.evaluate([add]) self.assertEqual(2, len(shared)) # Make sure the values read from the variable match the expected ones. self.assertEqual([0.0, 3.0], shared) + @test_util.run_deprecated_v1 def testResourceType(self): """Confirm that subscribe correctly handles tensors with 'resource' type.""" tensor_array = tensor_array_ops.TensorArray( @@ -273,9 +280,10 @@ class SubscribeTest(test_util.TensorFlowTestCase): self.assertFalse(subscribe._is_subscribed_identity(tensor_array.handle)) with self.cached_session() as sess: - sess.run([reader]) + self.evaluate([reader]) self.assertEqual(0, len(shared)) + @test_util.run_deprecated_v1 def testMultipleOutputs(self): """Handle subscriptions to multiple outputs from the same op.""" sparse_tensor_1 = sparse_tensor.SparseTensor( @@ -304,11 +312,12 @@ class SubscribeTest(test_util.TensorFlowTestCase): lambda t: script_ops.py_func(sub, [t], [t.dtype])) with self.cached_session() as sess: - sess.run([neg]) + self.evaluate([neg]) # All three ops have been processed. self.assertEqual(3, len(shared)) + @test_util.run_deprecated_v1 def test_subscribe_tensors_on_different_devices(self): """Side effect ops are added with the same device of the subscribed op.""" c1 = constant_op.constant(10) @@ -335,6 +344,7 @@ class SubscribeTest(test_util.TensorFlowTestCase): self.assertEqual(add.device, add_sub.device) self.assertEqual(mul.device, mul_sub.device) + @test_util.run_deprecated_v1 def test_subscribe_tensors_within_control_flow_context(self): """Side effect ops are added with the same control flow context.""" c1 = constant_op.constant(10) @@ -375,7 +385,7 @@ class SubscribeTest(test_util.TensorFlowTestCase): self.assertIsNot(context(subscriptions[0]), context(subscriptions[1])) with self.cached_session() as sess: - sess.run(cond) + self.evaluate(cond) self.assertEqual(3, len(results)) diff --git a/tensorflow/python/framework/tensor_shape.py b/tensorflow/python/framework/tensor_shape.py index 5a58d27148..960a3dad73 100644 --- a/tensorflow/python/framework/tensor_shape.py +++ b/tensorflow/python/framework/tensor_shape.py @@ -169,7 +169,7 @@ def dimension_at_index(shape, index): return shape.dims[index] -@tf_export("Dimension") +@tf_export(v1=["Dimension"]) class Dimension(object): """Represents the value of one dimension in a TensorShape.""" diff --git a/tensorflow/python/framework/tensor_spec.py b/tensorflow/python/framework/tensor_spec.py index fbea930fe0..c44636edc4 100644 --- a/tensorflow/python/framework/tensor_spec.py +++ b/tensorflow/python/framework/tensor_spec.py @@ -24,14 +24,15 @@ from tensorflow.python.framework import common_shapes from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.util.tf_export import tf_export +@tf_export("TensorSpec") class TensorSpec(object): """Describes a tf.Tensor. - A TensorSpec allows an API to describe the Tensors that it accepts or - returns, before that Tensor exists. This allows dynamic and flexible graph - construction and configuration. + Metadata for describing the `tf.Tensor` objects accepted or returned + by some TensorFlow APIs. """ __slots__ = ["_shape", "_shape_tuple", "_dtype", "_name"] @@ -69,11 +70,6 @@ class TensorSpec(object): else: raise ValueError("`tensor` should be a tf.Tensor") - @classmethod - def is_bounded(cls): - del cls - return False - @property def shape(self): """Returns the `TensorShape` that represents the shape of the tensor.""" @@ -86,21 +82,21 @@ class TensorSpec(object): @property def name(self): - """Returns the name of the described tensor.""" + """Returns the (optionally provided) name of the described tensor.""" return self._name - @property - def is_discrete(self): - """Whether spec is discrete.""" - return self.dtype.is_integer + def is_compatible_with(self, spec_or_tensor): + """Returns True if spec_or_tensor is compatible with this TensorSpec. - @property - def is_continuous(self): - """Whether spec is continuous.""" - return self.dtype.is_floating + Two tensors are considered compatible if they have the same dtype + and their shapes are compatible (see `tf.TensorShape.is_compatible_with`). - def is_compatible_with(self, spec_or_tensor): - """True if the shape and dtype of `spec_or_tensor` are compatible.""" + Args: + spec_or_tensor: A tf.TensorSpec or a tf.Tensor + + Returns: + True if spec_or_tensor is compatible with self. + """ return (self._dtype.is_compatible_with(spec_or_tensor.dtype) and self._shape.is_compatible_with(spec_or_tensor.shape)) @@ -188,11 +184,6 @@ class BoundedTensorSpec(TensorSpec): self._maximum = np.array(maximum, dtype=self.dtype.as_numpy_dtype()) self._maximum.setflags(write=False) - @classmethod - def is_bounded(cls): - del cls - return True - @classmethod def from_spec(cls, spec): dtype = dtypes.as_dtype(spec.dtype) @@ -223,4 +214,3 @@ class BoundedTensorSpec(TensorSpec): def __reduce__(self): return BoundedTensorSpec, (self._shape, self._dtype, self._minimum, self._maximum, self._name) - diff --git a/tensorflow/python/framework/tensor_spec_test.py b/tensorflow/python/framework/tensor_spec_test.py index 40611e5f84..75c197df09 100644 --- a/tensorflow/python/framework/tensor_spec_test.py +++ b/tensorflow/python/framework/tensor_spec_test.py @@ -45,6 +45,7 @@ class TensorSpecTest(test_util.TensorFlowTestCase): desc = tensor_spec.TensorSpec(shape=None, dtype=dtypes.float32) self.assertEqual(desc.shape, tensor_shape.TensorShape(None)) + @test_util.run_deprecated_v1 def testShapeCompatibility(self): unknown = array_ops.placeholder(dtypes.int64) partial = array_ops.placeholder(dtypes.int64, shape=[None, 1]) @@ -75,6 +76,7 @@ class TensorSpecTest(test_util.TensorFlowTestCase): self.assertFalse(desc_rank3.is_compatible_with(full)) self.assertTrue(desc_rank3.is_compatible_with(rank3)) + @test_util.run_deprecated_v1 def testTypeCompatibility(self): floats = array_ops.placeholder(dtypes.float32, shape=[10, 10]) ints = array_ops.placeholder(dtypes.int32, shape=[10, 10]) @@ -106,6 +108,7 @@ class TensorSpecTest(test_util.TensorFlowTestCase): spec_2 = tensor_spec.TensorSpec.from_spec(spec_1) self.assertEqual(spec_1, spec_2) + @test_util.run_deprecated_v1 def testFromTensor(self): zero = constant_op.constant(0) spec = tensor_spec.TensorSpec.from_tensor(zero) @@ -113,6 +116,7 @@ class TensorSpecTest(test_util.TensorFlowTestCase): self.assertEqual(spec.shape, []) self.assertEqual(spec.name, "Const") + @test_util.run_deprecated_v1 def testFromPlaceholder(self): unknown = array_ops.placeholder(dtypes.int64, name="unknown") partial = array_ops.placeholder(dtypes.float32, @@ -134,22 +138,6 @@ class TensorSpecTest(test_util.TensorFlowTestCase): self.assertEqual(bounded_spec.dtype, spec.dtype) self.assertEqual(bounded_spec.name, spec.name) - def testIsDiscrete(self): - discrete_spec = tensor_spec.TensorSpec((1, 2), dtypes.int32) - continuous_spec = tensor_spec.TensorSpec((1, 2), dtypes.float32) - self.assertTrue(discrete_spec.is_discrete) - self.assertFalse(continuous_spec.is_discrete) - - def testIsContinuous(self): - discrete_spec = tensor_spec.TensorSpec((1, 2), dtypes.int32) - continuous_spec = tensor_spec.TensorSpec((1, 2), dtypes.float32) - self.assertFalse(discrete_spec.is_continuous) - self.assertTrue(continuous_spec.is_continuous) - - def testIsBounded(self): - unbounded_spec = tensor_spec.TensorSpec((1, 2), dtypes.int32) - self.assertFalse(unbounded_spec.is_bounded()) - def testSerialization(self): desc = tensor_spec.TensorSpec([1, 5], dtypes.float32, "test") self.assertEqual(pickle.loads(pickle.dumps(desc)), desc) @@ -165,11 +153,6 @@ class BoundedTensorSpecTest(test_util.TensorFlowTestCase): with self.assertRaisesRegexp(ValueError, "not compatible"): tensor_spec.BoundedTensorSpec((3, 5), dtypes.uint8, 0, (1, 1, 1)) - def testIsBounded(self): - bounded_spec = tensor_spec.BoundedTensorSpec( - (1, 2), dtypes.int32, minimum=0, maximum=1) - self.assertTrue(bounded_spec.is_bounded()) - def testMinimumMaximumAttributes(self): spec = tensor_spec.BoundedTensorSpec( (1, 2, 3), dtypes.float32, 0, (5, 5, 5)) diff --git a/tensorflow/python/framework/tensor_util.py b/tensorflow/python/framework/tensor_util.py index 9db94f5288..f98f301b38 100644 --- a/tensorflow/python/framework/tensor_util.py +++ b/tensorflow/python/framework/tensor_util.py @@ -371,8 +371,10 @@ def _AssertCompatible(values, dtype): (dtype.name, repr(mismatch), type(mismatch).__name__)) +# pylint: disable=invalid-name @tf_export(v1=["make_tensor_proto"]) -def make_tensor_proto(values, dtype=None, shape=None, verify_shape=False): +def make_tensor_proto(values, dtype=None, shape=None, verify_shape=False, + allow_broadcast=False): """Create a TensorProto. Args: @@ -380,6 +382,8 @@ def make_tensor_proto(values, dtype=None, shape=None, verify_shape=False): dtype: Optional tensor_pb2 DataType value. shape: List of integers representing the dimensions of tensor. verify_shape: Boolean that enables verification of a shape of values. + allow_broadcast:Boolean that enables allowing scalars and 1 length vector + broadcasting. Cannot be true when verify_shape is true. Returns: A `TensorProto`. Depending on the type, it may contain data in the @@ -416,6 +420,8 @@ def make_tensor_proto(values, dtype=None, shape=None, verify_shape=False): can not have more elements than what "shape" specifies. """ + if allow_broadcast and verify_shape: + raise ValueError("allow_broadcast and verify_shape are not both allowed.") if isinstance(values, tensor_pb2.TensorProto): return values @@ -504,15 +510,22 @@ def make_tensor_proto(values, dtype=None, shape=None, verify_shape=False): shape_size = np.prod(shape, dtype=np.int64) is_same_size = shape_size == nparray.size - if verify_shape: - if not nparray.shape == tuple(shape): + if allow_broadcast: + if nparray.shape == (1,) or nparray.shape == tuple(): + pass + elif nparray.size != shape_size: raise TypeError("Expected Tensor's shape: %s, got %s." % (tuple(shape), nparray.shape)) - if nparray.size > shape_size: - raise ValueError( - "Too many elements provided. Needed at most %d, but received %d" % - (shape_size, nparray.size)) + else: + if verify_shape and nparray.shape != tuple(shape): + raise TypeError("Expected Tensor's shape: %s, got %s." % + (tuple(shape), nparray.shape)) + + if nparray.size > shape_size: + raise ValueError( + "Too many elements provided. Needed at most %d, but received %d" % + (shape_size, nparray.size)) tensor_proto = tensor_pb2.TensorProto( dtype=numpy_dtype.as_datatype_enum, @@ -560,6 +573,7 @@ def make_tensor_proto(values, dtype=None, shape=None, verify_shape=False): append_fn(tensor_proto, proto_values) return tensor_proto +# pylint: enable=invalid-name @tf_export("make_ndarray") diff --git a/tensorflow/python/framework/tensor_util_test.py b/tensorflow/python/framework/tensor_util_test.py index bdf759f220..0033754618 100644 --- a/tensorflow/python/framework/tensor_util_test.py +++ b/tensorflow/python/framework/tensor_util_test.py @@ -758,6 +758,7 @@ class TensorUtilTest(test.TestCase): self.assertFalse(tensor_util.ShapeEquals(t, [1, 4])) self.assertFalse(tensor_util.ShapeEquals(t, [4])) + @test_util.run_deprecated_v1 def testMockArray(self): class MockArray(object): @@ -771,7 +772,7 @@ class TensorUtilTest(test.TestCase): with self.cached_session() as sess: ma = MockArray(np.array([10, 20, 30])) t = ops.convert_to_tensor(ma) - a = sess.run(t) + a = self.evaluate(t) self.assertEquals(np.int64, a.dtype) self.assertAllClose(np.array([10, 20, 30], dtype=np.int64), a) @@ -787,6 +788,7 @@ class ConstantValueTest(test.TestCase): tf_val = constant_op.constant(np_val) self.assertAllClose(np_val, tensor_util.constant_value(tf_val)) + @test_util.run_deprecated_v1 def testUnknown(self): tf_val = gen_state_ops.variable( shape=[3, 4, 7], @@ -815,12 +817,14 @@ class ConstantValueTest(test.TestCase): c_val = tensor_util.constant_value(tf_val) self.assertEqual(6, c_val) + @test_util.run_deprecated_v1 def testSizeOfScalar(self): tf_val = array_ops.size(constant_op.constant(0.0)) c_val = tensor_util.constant_value(tf_val) self.assertEqual(1, c_val) self.assertEqual(np.ndarray, type(c_val)) + @test_util.run_deprecated_v1 def testRank(self): tf_val = array_ops.rank(constant_op.constant(0.0, shape=[1, 2, 3])) c_val = tensor_util.constant_value(tf_val) @@ -852,6 +856,7 @@ class ConstantValueTest(test.TestCase): c_val = tensor_util.constant_value(tf_val) self.assertAllClose(np_val.astype(np.float64), c_val) + @test_util.run_deprecated_v1 def testConcat(self): np_val = np.random.rand(3, 4, 7).astype(np.float32) tf_val = array_ops.concat( @@ -871,6 +876,7 @@ class ConstantValueTest(test.TestCase): c_val = tensor_util.constant_value(tf_val) self.assertIs(None, c_val) + @test_util.run_deprecated_v1 def testPack_Axis0(self): inputs = [np.random.rand(4, 7) for _ in range(3)] np_val = np.array(inputs) @@ -883,6 +889,7 @@ class ConstantValueTest(test.TestCase): c_val = tensor_util.constant_value(tf_val) self.assertIs(None, c_val) + @test_util.run_deprecated_v1 def testPack_Axis1(self): inputs = [np.random.rand(4, 7) for _ in range(3)] tf_val = array_ops.stack(inputs, axis=1) @@ -894,6 +901,7 @@ class ConstantValueTest(test.TestCase): c_val = tensor_util.constant_value(tf_val) self.assertIs(None, c_val) + @test_util.run_deprecated_v1 def testPack_Partial_Axis0(self): input_ = np.random.rand(4, 7) tf_val = array_ops.stack([input_, array_ops.placeholder(dtypes.float32)]) @@ -901,6 +909,7 @@ class ConstantValueTest(test.TestCase): self.assertAllClose(input_, c_val[0]) self.assertIsNone(c_val[1]) + @test_util.run_deprecated_v1 def testPack_Partial_Axis1(self): input_ = np.random.rand(4, 7) tf_val = array_ops.stack([input_, array_ops.placeholder(dtypes.float32)], @@ -966,12 +975,14 @@ class ConstantValueAsShapeTest(test.TestCase): c_val = tensor_util.constant_value_as_shape(tf_val) self.assertEqual([None, 1, None], c_val.as_list()) + @test_util.run_deprecated_v1 def testPack(self): tf_val = array_ops.stack( [constant_op.constant(16), 37, array_ops.placeholder(dtypes.int32)]) c_val = tensor_util.constant_value_as_shape(tf_val) self.assertEqual([16, 37, None], c_val.as_list()) + @test_util.run_deprecated_v1 def testConcat(self): tf_val = array_ops.concat( [[16, 37], array_ops.placeholder( @@ -985,6 +996,7 @@ class ConstantValueAsShapeTest(test.TestCase): c_val = tensor_util.constant_value_as_shape(tf_val) self.assertEqual([16, 37, None, 48], c_val.as_list()) + @test_util.run_deprecated_v1 def testSlice(self): tf_val = array_ops.placeholder(dtypes.int32, shape=(4,))[0:2] c_val = tensor_util.constant_value_as_shape(tf_val) diff --git a/tensorflow/python/framework/test_util.py b/tensorflow/python/framework/test_util.py index fd55ad2af9..fc1a5fbe85 100644 --- a/tensorflow/python/framework/test_util.py +++ b/tensorflow/python/framework/test_util.py @@ -50,6 +50,7 @@ from tensorflow.core.framework import graph_pb2 from tensorflow.core.protobuf import config_pb2 from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.python import pywrap_tensorflow +from tensorflow.python import tf2 from tensorflow.python.client import device_lib from tensorflow.python.client import session from tensorflow.python.eager import context @@ -66,6 +67,7 @@ from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import versions from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import tensor_array_ops from tensorflow.python.ops import variables from tensorflow.python.platform import googletest from tensorflow.python.platform import tf_logging as logging @@ -114,8 +116,28 @@ def assert_ops_in_graph(expected_ops, graph): return actual_ops -@tf_export("test.assert_equal_graph_def") -def assert_equal_graph_def(actual, expected, checkpoint_v2=False): +@tf_export("test.assert_equal_graph_def", v1=[]) +def assert_equal_graph_def_v2(actual, expected): + """Asserts that two `GraphDef`s are (mostly) the same. + + Compares two `GraphDef` protos for equality, ignoring versions and ordering of + nodes, attrs, and control inputs. Node names are used to match up nodes + between the graphs, so the naming of nodes must be consistent. This function + ignores randomized attribute values that may appear in V2 checkpoints. + + Args: + actual: The `GraphDef` we have. + expected: The `GraphDef` we expected. + + Raises: + AssertionError: If the `GraphDef`s do not match. + TypeError: If either argument is not a `GraphDef`. + """ + assert_equal_graph_def(actual, expected, checkpoint_v2=True) + + +@tf_export(v1=["test.assert_equal_graph_def"]) +def assert_equal_graph_def_v1(actual, expected, checkpoint_v2=False): """Asserts that two `GraphDef`s are (mostly) the same. Compares two `GraphDef` protos for equality, ignoring versions and ordering of @@ -132,6 +154,10 @@ def assert_equal_graph_def(actual, expected, checkpoint_v2=False): AssertionError: If the `GraphDef`s do not match. TypeError: If either argument is not a `GraphDef`. """ + assert_equal_graph_def(actual, expected, checkpoint_v2) + + +def assert_equal_graph_def(actual, expected, checkpoint_v2=False): if not isinstance(actual, graph_pb2.GraphDef): raise TypeError( "Expected tf.GraphDef for actual, got %s" % type(actual).__name__) @@ -354,53 +380,12 @@ def skip_if(condition): def enable_c_shapes(fn): - """Decorator for enabling C shapes on a test. - - Note this enables the C shapes after running the test class's setup/teardown - methods. - - Args: - fn: the function to be wrapped - - Returns: - The wrapped function - """ - - # pylint: disable=protected-access - def wrapper(*args, **kwargs): - prev_value = ops._USE_C_SHAPES - ops._USE_C_SHAPES = True - try: - fn(*args, **kwargs) - finally: - ops._USE_C_SHAPES = prev_value - - # pylint: enable=protected-access - - return wrapper + """No-op. TODO(b/74620627): Remove this.""" + return fn def with_c_shapes(cls): - """Adds methods that call original methods but with C API shapes enabled. - - Note this enables C shapes in new methods after running the test class's - setup method. - - Args: - cls: class to decorate - - Returns: - cls with new test methods added - """ - # If C shapes are already enabled, don't do anything. Some tests break if the - # same test is run twice, so this allows us to turn on the C shapes by default - # without breaking these tests. - if ops._USE_C_SHAPES: - return cls - - for name, value in cls.__dict__.copy().items(): - if callable(value) and name.startswith("test"): - setattr(cls, name + "WithCShapes", enable_c_shapes(value)) + """No-op. TODO(b/74620627): Remove this.""" return cls @@ -423,13 +408,40 @@ def enable_control_flow_v2(fn): def wrapper(*args, **kwargs): enable_cond_v2_old = control_flow_ops.ENABLE_COND_V2 enable_while_v2_old = control_flow_ops.ENABLE_WHILE_V2 + enable_tensor_array_v2_old = tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 control_flow_ops.ENABLE_COND_V2 = True control_flow_ops.ENABLE_WHILE_V2 = True + tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 = True try: fn(*args, **kwargs) finally: control_flow_ops.ENABLE_COND_V2 = enable_cond_v2_old control_flow_ops.ENABLE_WHILE_V2 = enable_while_v2_old + tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 = enable_tensor_array_v2_old + + return wrapper + + +def enable_tensor_array_v2(fn): + """Decorator for enabling _GraphTensorArrayV2 on a test. + + Note this enables _GraphTensorArrayV2 after running the test class's + setup/teardown methods. + + Args: + fn: the function to be wrapped + + Returns: + The wrapped function + """ + + def wrapper(*args, **kwargs): + enable_tensor_array_v2_old = tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 + tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 = True + try: + fn(*args, **kwargs) + finally: + tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 = enable_tensor_array_v2_old return wrapper @@ -881,8 +893,8 @@ def run_all_in_graph_and_eager_modes(cls): """Execute all test methods in the given class with and without eager.""" base_decorator = run_in_graph_and_eager_modes for name, value in cls.__dict__.copy().items(): - if callable(value) and name.startswith( - "test") and not name.startswith("testSkipEager"): + if callable(value) and name.startswith("test") and not ( + name.startswith("testSkipEager") or name.startswith("test_skip_eager")): setattr(cls, name, base_decorator(value)) return cls @@ -949,7 +961,7 @@ def run_in_graph_and_eager_modes(func=None, def decorator(f): if tf_inspect.isclass(f): raise ValueError( - "`run_test_in_graph_and_eager_modes` only supports test methods. " + "`run_in_graph_and_eager_modes` only supports test methods. " "Did you mean to use `run_all_in_graph_and_eager_modes`?") def decorated(self, *args, **kwargs): @@ -994,6 +1006,174 @@ def run_in_graph_and_eager_modes(func=None, return decorator +def run_deprecated_v1(func=None): + """Execute the decorated test in graph mode. + + This function returns a decorator intended to be applied to tests that have + not been updated to a style that is compatible with both TensorFlow 1.x and + 2.x. When this decorated is applied, the test body will be run in + an environment where API calls construct graphs instead of executing eagerly. + + Args: + func: function to be annotated. If `func` is None, this method returns a + decorator the can be applied to a function. If `func` is not None this + returns the decorator applied to `func`. + Returns: + Returns a decorator that will run the decorated test method in graph mode. + """ + + def decorator(f): + if tf_inspect.isclass(f): + raise ValueError("`run_deprecated_v1` only supports test methods.") + + def decorated(self, *args, **kwargs): + if tf2.enabled(): + with context.graph_mode(): + f(self, *args, **kwargs) + else: + f(self, *args, **kwargs) + + return decorated + + if func is not None: + return decorator(func) + + return decorator + + +def run_v1_only(reason, func=None): + """Execute the decorated test only if running in v1 mode. + + This function is intended to be applied to tests that exercise v1 only + functionality. If the test is run in v2 mode it will simply be skipped. + + Args: + reason: string giving a reason for limiting the test to v1 only. + func: function to be annotated. If `func` is None, this method returns a + decorator the can be applied to a function. If `func` is not None this + returns the decorator applied to `func`. + + Returns: + Returns a decorator that will conditionally skip the decorated test method. + """ + + def decorator(f): + if tf_inspect.isclass(f): + raise ValueError("`run_v1_only` only supports test methods.") + + def decorated(self, *args, **kwargs): + if tf2.enabled(): + self.skipTest(reason) + + f(self, *args, **kwargs) + + return decorated + + if func is not None: + return decorator(func) + + return decorator + + +def run_v2_only(func=None): + """Execute the decorated test only if running in v2 mode. + + This function is intended to be applied to tests that exercise v2 only + functionality. If the test is run in v1 mode it will simply be skipped. + + Args: + func: function to be annotated. If `func` is None, this method returns a + decorator the can be applied to a function. If `func` is not None this + returns the decorator applied to `func`. + + Returns: + Returns a decorator that will conditionally skip the decorated test method. + """ + + def decorator(f): + if tf_inspect.isclass(f): + raise ValueError("`run_v2_only` only supports test methods.") + + def decorated(self, *args, **kwargs): + if not tf2.enabled(): + self.skipTest("Test is only comptaible in v2") + + f(self, *args, **kwargs) + + return decorated + + if func is not None: + return decorator(func) + + return decorator + + +def run_gpu_only(func=None): + """Execute the decorated test only if a GPU is available. + + This function is intended to be applied to tests that require the precense + of a GPU. If a GPU is absent, it will simply be skipped. + + Args: + func: function to be annotated. If `func` is None, this method returns a + decorator the can be applied to a function. If `func` is not None this + returns the decorator applied to `func`. + + Returns: + Returns a decorator that will conditionally skip the decorated test method. + """ + + def decorator(f): + if tf_inspect.isclass(f): + raise ValueError("`run_gpu_only` only supports test methods.") + + def decorated(self, *args, **kwargs): + if not is_gpu_available(): + self.skipTest("Test requires GPU") + + f(self, *args, **kwargs) + + return decorated + + if func is not None: + return decorator(func) + + return decorator + + +def run_cuda_only(func=None): + """Execute the decorated test only if a GPU is available. + + This function is intended to be applied to tests that require the precense + of a CUDA GPU. If a CUDA GPU is absent, it will simply be skipped. + + Args: + func: function to be annotated. If `func` is None, this method returns a + decorator the can be applied to a function. If `func` is not None this + returns the decorator applied to `func`. + + Returns: + Returns a decorator that will conditionally skip the decorated test method. + """ + + def decorator(f): + if tf_inspect.isclass(f): + raise ValueError("`run_cuda_only` only supports test methods.") + + def decorated(self, *args, **kwargs): + if not is_gpu_available(cuda_only=True): + self.skipTest("Test requires CUDA GPU") + + f(self, *args, **kwargs) + + return decorated + + if func is not None: + return decorator(func) + + return decorator + + @tf_export("test.is_gpu_available") def is_gpu_available(cuda_only=False, min_cuda_compute_capability=None): """Returns whether TensorFlow can access a GPU. @@ -1033,7 +1213,7 @@ def is_gpu_available(cuda_only=False, min_cuda_compute_capability=None): return True return False except errors_impl.NotFoundError as e: - if not all([x in str(e) for x in ["CUDA", "not find"]]): + if not all(x in str(e) for x in ["CUDA", "not find"]): raise e else: logging.error(str(e)) @@ -1051,6 +1231,27 @@ def device(use_gpu): yield +@contextlib.contextmanager +def use_gpu(): + """Uses gpu when requested and available.""" + with device(use_gpu=True): + yield + + +@contextlib.contextmanager +def force_gpu(): + """Force the gpu to be used.""" + with ops.device("/device:GPU:0"): + yield + + +@contextlib.contextmanager +def force_cpu(): + """Force the cpu to be used.""" + with ops.device("/device:CPU:0"): + yield + + class CapturedWrites(object): """A utility class to load the captured writes made to a stream.""" diff --git a/tensorflow/python/framework/test_util_test.py b/tensorflow/python/framework/test_util_test.py index cbefe86481..dfdced5a98 100644 --- a/tensorflow/python/framework/test_util_test.py +++ b/tensorflow/python/framework/test_util_test.py @@ -49,6 +49,7 @@ from tensorflow.python.platform import googletest class TestUtilTest(test_util.TensorFlowTestCase, parameterized.TestCase): + @test_util.run_deprecated_v1 def test_assert_ops_in_graph(self): with self.test_session(): constant_op.constant(["hello", "taffy"], name="hello") @@ -60,6 +61,7 @@ class TestUtilTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertRaises(ValueError, test_util.assert_ops_in_graph, {"hello": "Variable"}, ops.get_default_graph()) + @test_util.run_deprecated_v1 def test_session_functions(self): with self.test_session() as sess: sess_ref = weakref.ref(sess) @@ -551,6 +553,7 @@ class TestUtilTest(test_util.TensorFlowTestCase, parameterized.TestCase): with self.assertRaises(AssertionError): self.assertAllLessEqual(x, 95.0) + @test_util.run_deprecated_v1 def testAssertAllInRangeWithNonNumericValuesFails(self): s1 = constant_op.constant("Hello, ", name="s1") c = constant_op.constant([1 + 2j, -3 + 5j], name="c") @@ -614,6 +617,7 @@ class TestUtilTest(test_util.TensorFlowTestCase, parameterized.TestCase): with self.assertRaises(AssertionError): self.assertAllInSet(x, (42,)) + @test_util.run_deprecated_v1 def testRandomSeed(self): # Call setUp again for WithCApi case (since it makes a new defeault graph # after setup). @@ -681,7 +685,7 @@ class TestUtilTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertIsNone(test_util.get_node_def_from_graph("bar", graph_def)) def test_run_in_eager_and_graph_modes_test_class(self): - msg = "`run_test_in_graph_and_eager_modes` only supports test methods.*" + msg = "`run_in_graph_and_eager_modes` only supports test methods.*" with self.assertRaisesRegexp(ValueError, msg): @test_util.run_in_graph_and_eager_modes() class Foo(object): @@ -706,6 +710,7 @@ class TestUtilTest(test_util.TensorFlowTestCase, parameterized.TestCase): test_util.run_in_graph_and_eager_modes(_test)(self) self.assertEqual(modes, ["graph"]) + @test_util.run_deprecated_v1 def test_run_in_graph_and_eager_modes_setup_in_same_mode(self): modes = [] mode_name = lambda: "eager" if context.executing_eagerly() else "graph" diff --git a/tensorflow/python/grappler/constant_folding_test.py b/tensorflow/python/grappler/constant_folding_test.py index ab1d0ed25b..30c1e14681 100644 --- a/tensorflow/python/grappler/constant_folding_test.py +++ b/tensorflow/python/grappler/constant_folding_test.py @@ -61,7 +61,7 @@ class ConstantFoldingTest(test.TestCase): back_prop=False, parallel_iterations=1) with session.Session() as sess: - y_v = sess.run(y) + y_v = self.evaluate(y) self.assertAllEqual(np.zeros([10, 20, 30]), y_v) diff --git a/tensorflow/python/grappler/cost_analyzer_test.py b/tensorflow/python/grappler/cost_analyzer_test.py index b8225b81a5..ee3e289f65 100644 --- a/tensorflow/python/grappler/cost_analyzer_test.py +++ b/tensorflow/python/grappler/cost_analyzer_test.py @@ -38,6 +38,7 @@ from tensorflow.python.training import adam class CostAnalysisTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasicCost(self): """Make sure arguments can be passed correctly.""" a = constant_op.constant(10, name="a") @@ -62,6 +63,7 @@ class CostAnalysisTest(test.TestCase): # Also print the report to make it easier to debug print("{}".format(report)) + @test_util.run_deprecated_v1 def testVerbose(self): """Make sure the full report is generated with verbose=True.""" a = constant_op.constant(10, name="a") @@ -81,6 +83,7 @@ class CostAnalysisTest(test.TestCase): # Also print the report to make it easier to debug print("{}".format(report)) + @test_util.run_deprecated_v1 def testSmallNetworkCost(self): image = array_ops.placeholder(dtypes.float32, shape=[1, 28, 28, 1]) label = array_ops.placeholder(dtypes.float32, shape=[1, 10]) @@ -96,8 +99,8 @@ class CostAnalysisTest(test.TestCase): b_fc = variables.Variable(random_ops.truncated_normal([10], stddev=0.1)) y_conv = nn_ops.softmax(math_ops.matmul(h_conv_flat, w_fc) + b_fc) - cross_entropy = math_ops.reduce_mean(-math_ops.reduce_sum( - label * math_ops.log(y_conv), reduction_indices=[1])) + cross_entropy = math_ops.reduce_mean( + -math_ops.reduce_sum(label * math_ops.log(y_conv), axis=[1])) _ = adam.AdamOptimizer(1e-4).minimize(cross_entropy) mg = meta_graph.create_meta_graph_def(graph=ops.get_default_graph()) @@ -129,6 +132,7 @@ class CostAnalysisTest(test.TestCase): # self.assertTrue(0 < upper) # self.assertTrue(lower <= upper) + @test_util.run_deprecated_v1 def testBasicMemory(self): """Make sure arguments can be passed correctly.""" with test_util.device(use_gpu=False): diff --git a/tensorflow/python/grappler/cost_analyzer_tool.py b/tensorflow/python/grappler/cost_analyzer_tool.py index e6229e1856..7dbaf449ca 100644 --- a/tensorflow/python/grappler/cost_analyzer_tool.py +++ b/tensorflow/python/grappler/cost_analyzer_tool.py @@ -25,8 +25,8 @@ from google.protobuf import message from google.protobuf import text_format from tensorflow.contrib.fused_conv.ops import gen_fused_conv2d_bias_activation_op # pylint: disable=unused-import from tensorflow.core.framework import graph_pb2 +from tensorflow.core.protobuf import config_pb2 from tensorflow.core.protobuf import meta_graph_pb2 -from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.core.protobuf import saved_model_pb2 from tensorflow.python.framework import importer from tensorflow.python.framework import ops @@ -79,10 +79,11 @@ def get_metagraph(): def main(_): metagraph = get_metagraph() - rewriter_config = rewriter_config_pb2.RewriterConfig() + config = config_pb2.ConfigProto() if FLAGS.rewriter_config is not None: - text_format.Merge(FLAGS.rewriter_config, rewriter_config) - optimized_graph = tf_optimizer.OptimizeGraph(rewriter_config, metagraph) + text_format.Merge(FLAGS.rewriter_config, + config.graph_options.rewrite_options) + optimized_graph = tf_optimizer.OptimizeGraph(config, metagraph) metagraph.graph_def.CopyFrom(optimized_graph) report = cost_analyzer.GenerateCostReport(metagraph, FLAGS.per_node_report, diff --git a/tensorflow/python/grappler/datasets_test.py b/tensorflow/python/grappler/datasets_test.py index bd870ad8de..6937301ab2 100644 --- a/tensorflow/python/grappler/datasets_test.py +++ b/tensorflow/python/grappler/datasets_test.py @@ -48,7 +48,7 @@ class GrapplerTest(test.TestCase): for test_case in test_cases: with ops.Graph().as_default() as g: dataset = dataset_ops.Dataset.from_tensors(test_case['tensor']) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) @@ -73,7 +73,7 @@ class GrapplerTest(test.TestCase): for test_case in test_cases: with ops.Graph().as_default() as g: dataset = dataset_ops.Dataset.from_tensor_slices(test_case['tensor']) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) @@ -109,7 +109,7 @@ class GrapplerTest(test.TestCase): make_generator(test_case['tensor']), dtypes.int64, output_shapes=test_case['shape']) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) @@ -122,7 +122,7 @@ class GrapplerTest(test.TestCase): def testRange(self): with ops.Graph().as_default() as g: dataset = dataset_ops.Dataset.range(42) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) @@ -148,7 +148,7 @@ class GrapplerTest(test.TestCase): with ops.Graph().as_default() as g: dataset = dataset_ops.Dataset.from_tensors(test_case['tensor']) dataset = fn(dataset, test_case['tensor'], test_case['shape']) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) @@ -252,7 +252,7 @@ class GrapplerTest(test.TestCase): with ops.Graph().as_default() as g: dataset = dataset_ops.Dataset.from_tensors(test_case['tensor']) dataset = dataset.batch(42) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) @@ -281,7 +281,7 @@ class GrapplerTest(test.TestCase): with ops.Graph().as_default() as g: dataset = dataset_ops.Dataset.from_tensors(test_case['tensor']) dataset = dataset.padded_batch(42, padded_shapes=test_case['shape'][1:]) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) @@ -318,7 +318,7 @@ class GrapplerTest(test.TestCase): return dataset_fn dataset = dataset.flat_map(make_dataset(test_case['tensor'])) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) @@ -353,7 +353,7 @@ class GrapplerTest(test.TestCase): dataset = dataset.interleave( make_dataset(test_case['tensor']), cycle_length=42) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) @@ -382,7 +382,7 @@ class GrapplerTest(test.TestCase): with ops.Graph().as_default() as g: dataset = dataset_ops.Dataset.from_tensors(test_case['tensor']) dataset = dataset.map(array_ops.transpose) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() train_op = ops.get_collection_ref(ops.GraphKeys.TRAIN_OP) train_op.append(get_next) diff --git a/tensorflow/python/grappler/graph_placer.py b/tensorflow/python/grappler/graph_placer.py index 654013b23c..9c05ad8179 100644 --- a/tensorflow/python/grappler/graph_placer.py +++ b/tensorflow/python/grappler/graph_placer.py @@ -19,8 +19,8 @@ from __future__ import division from __future__ import print_function import time +from tensorflow.core.protobuf import config_pb2 from tensorflow.core.protobuf import meta_graph_pb2 -from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.python.framework import errors from tensorflow.python.framework import ops as tf_ops from tensorflow.python.grappler import cluster as gcluster @@ -54,9 +54,9 @@ def PlaceGraph(metagraph, cluster = gcluster.Cluster() # Optimize the metagraph to speedup the placement - rewriter_config = rewriter_config_pb2.RewriterConfig() + config = config_pb2.ConfigProto() optimized_graph = tf_optimizer.OptimizeGraph( - rewriter_config, metagraph, verbose=verbose, cluster=cluster) + config, metagraph, verbose=verbose, cluster=cluster) optimized_metagraph = meta_graph_pb2.MetaGraphDef() optimized_metagraph.CopyFrom(metagraph) optimized_metagraph.graph_def.CopyFrom(optimized_graph) diff --git a/tensorflow/python/grappler/item_test.py b/tensorflow/python/grappler/item_test.py index d3d96c646c..78604b259c 100644 --- a/tensorflow/python/grappler/item_test.py +++ b/tensorflow/python/grappler/item_test.py @@ -24,6 +24,7 @@ from tensorflow.python.framework import errors_impl from tensorflow.python.framework import meta_graph from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.grappler import item from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_array_ops @@ -107,6 +108,7 @@ class ItemTest(test.TestCase): newest_tf_item = grappler_item.tf_item self.assertEqual(new_tf_item, newest_tf_item) + @test_util.run_deprecated_v1 def testColocationContraints(self): with ops.Graph().as_default() as g: c = constant_op.constant([10]) diff --git a/tensorflow/python/grappler/layout_optimizer_test.py b/tensorflow/python/grappler/layout_optimizer_test.py index 8cc971c61d..98f2e6d718 100644 --- a/tensorflow/python/grappler/layout_optimizer_test.py +++ b/tensorflow/python/grappler/layout_optimizer_test.py @@ -29,6 +29,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util from tensorflow.python.grappler import cluster as gcluster from tensorflow.python.grappler import tf_optimizer from tensorflow.python.layers import convolutional as conv_layers @@ -241,7 +242,7 @@ class LayoutOptimizerTest(test.TestCase): if restore: saver.restore(sess, checkpoint_path) else: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) np.random.seed(0) for _ in range(2): @@ -262,7 +263,7 @@ class LayoutOptimizerTest(test.TestCase): output = _two_layer_model(x) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -365,7 +366,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(pad) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -396,7 +397,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(reduce_sum) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -425,7 +426,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(cast) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -456,7 +457,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(squeeze) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -486,7 +487,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(squeeze) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -516,7 +517,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(squeeze) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -545,7 +546,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(reduce_sum) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -574,7 +575,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(reduce_sum) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -603,7 +604,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(reduce_sum) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -632,7 +633,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(reduce_sum) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -662,7 +663,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(reduce_sum) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -691,7 +692,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(reduce_sum) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -724,7 +725,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(concat) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -835,7 +836,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(reverse) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -905,7 +906,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(select) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -966,7 +967,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(select) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -1179,7 +1180,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(s) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -1214,7 +1215,7 @@ class LayoutOptimizerTest(test.TestCase): output = array_ops.identity(s) with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -1347,7 +1348,7 @@ class LayoutOptimizerTest(test.TestCase): output = _loop() with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -1374,7 +1375,7 @@ class LayoutOptimizerTest(test.TestCase): output = _loop_with_branch() with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -1398,7 +1399,7 @@ class LayoutOptimizerTest(test.TestCase): output = _loop_with_vec_and_4d() with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -1422,7 +1423,7 @@ class LayoutOptimizerTest(test.TestCase): output = _model_with_second_port() with session.Session(config=_get_config(False)) as sess: - output_val_ref = sess.run(output) + output_val_ref = self.evaluate(output) with session.Session(config=_get_config()) as sess: metadata = config_pb2.RunMetadata() @@ -1441,13 +1442,16 @@ class LayoutOptimizerTest(test.TestCase): self._assert_trans_nchw_to_nhwc('Add-0-0', nodes) self.assertAllClose(output_val_ref, output_val, atol=1e-3) + @test_util.run_deprecated_v1 def testGradient(self): meta_graph = _simple_metagraph() - rewrite_options = rewriter_config_pb2.RewriterConfig( - layout_optimizer=rewriter_config_pb2.RewriterConfig.ON, - min_graph_nodes=-1) + config = config_pb2.ConfigProto() + config.graph_options.rewrite_options.CopyFrom( + rewriter_config_pb2.RewriterConfig( + layout_optimizer=rewriter_config_pb2.RewriterConfig.ON, + min_graph_nodes=-1)) optimized_graph = tf_optimizer.OptimizeGraph( - rewrite_options, meta_graph, cluster=_get_cluster()) + config, meta_graph, cluster=_get_cluster()) found = 0 for node in optimized_graph.node: @@ -1456,13 +1460,16 @@ class LayoutOptimizerTest(test.TestCase): self.assertEqual(node.attr['data_format'].s, b'NCHW') self.assertEqual(found, 5) + @test_util.run_deprecated_v1 def testDepthwise(self): meta_graph = _simple_metagraph(depthwise=True) - rewrite_options = rewriter_config_pb2.RewriterConfig( - layout_optimizer=rewriter_config_pb2.RewriterConfig.ON, - min_graph_nodes=-1) + config = config_pb2.ConfigProto() + config.graph_options.rewrite_options.CopyFrom( + rewriter_config_pb2.RewriterConfig( + layout_optimizer=rewriter_config_pb2.RewriterConfig.ON, + min_graph_nodes=-1)) optimized_graph = tf_optimizer.OptimizeGraph( - rewrite_options, meta_graph, cluster=_get_cluster()) + config, meta_graph, cluster=_get_cluster()) found = 0 for node in optimized_graph.node: diff --git a/tensorflow/python/grappler/memory_optimizer_test.py b/tensorflow/python/grappler/memory_optimizer_test.py index 03b42f6453..6eb16fbd39 100644 --- a/tensorflow/python/grappler/memory_optimizer_test.py +++ b/tensorflow/python/grappler/memory_optimizer_test.py @@ -25,6 +25,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import meta_graph from tensorflow.python.framework import ops from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util from tensorflow.python.grappler import tf_optimizer from tensorflow.python.ops import math_ops from tensorflow.python.ops import nn @@ -37,6 +38,7 @@ from tensorflow.python.training import training as train class MemoryOptimizerSwapTest(test.TestCase): """Tests the Grappler memory optimizer.""" + @test_util.run_deprecated_v1 def testNoSwapping(self): """Make sure the graph is preserved when there is nothing to swap.""" a = variables.VariableV1(10, name='a') @@ -49,15 +51,18 @@ class MemoryOptimizerSwapTest(test.TestCase): graph_size = len(mg.graph_def.node) nodes = [node.name for node in mg.graph_def.node] - rewriter_config = rewriter_config_pb2.RewriterConfig( - disable_model_pruning=True, - constant_folding=rewriter_config_pb2.RewriterConfig.OFF, - memory_optimization=rewriter_config_pb2.RewriterConfig.MANUAL) - graph = tf_optimizer.OptimizeGraph(rewriter_config, mg) + config = config_pb2.ConfigProto() + config.graph_options.rewrite_options.CopyFrom( + rewriter_config_pb2.RewriterConfig( + disable_model_pruning=True, + constant_folding=rewriter_config_pb2.RewriterConfig.OFF, + memory_optimization=rewriter_config_pb2.RewriterConfig.MANUAL)) + graph = tf_optimizer.OptimizeGraph(config, mg) self.assertEqual(len(graph.node), graph_size) self.assertItemsEqual([node.name for node in graph.node], nodes) + @test_util.run_deprecated_v1 def testSimpleSwap(self): """Check that the swap annotations are followed.""" a = variables.VariableV1(10, name='a') @@ -72,13 +77,15 @@ class MemoryOptimizerSwapTest(test.TestCase): mg = meta_graph.create_meta_graph_def(graph=ops.get_default_graph()) graph_size = len(mg.graph_def.node) - rewriter_config = rewriter_config_pb2.RewriterConfig( - disable_model_pruning=True, - meta_optimizer_iterations=rewriter_config_pb2.RewriterConfig.ONE, - constant_folding=rewriter_config_pb2.RewriterConfig.OFF, - memory_optimization=rewriter_config_pb2.RewriterConfig.MANUAL, - min_graph_nodes=-1) - graph = tf_optimizer.OptimizeGraph(rewriter_config, mg) + config = config_pb2.ConfigProto() + config.graph_options.rewrite_options.CopyFrom( + rewriter_config_pb2.RewriterConfig( + disable_model_pruning=True, + meta_optimizer_iterations=rewriter_config_pb2.RewriterConfig.ONE, + constant_folding=rewriter_config_pb2.RewriterConfig.OFF, + memory_optimization=rewriter_config_pb2.RewriterConfig.MANUAL, + min_graph_nodes=-1)) + graph = tf_optimizer.OptimizeGraph(config, mg) self.assertEqual(len(graph.node), graph_size + 2) self.assertTrue( @@ -127,7 +134,8 @@ class MemoryOptimizerRecomputeTest(test.TestCase): def testRewritingDefaultGradientNames(self): """Tests that rewriting occurs with default gradient names.""" (original_metagraph, _, _, _) = self._GetMetaGraph() - rewritten_graph_def = tf_optimizer.OptimizeGraph( + config = config_pb2.ConfigProto() + config.graph_options.rewrite_options.CopyFrom( rewriter_config_pb2.RewriterConfig( disable_model_pruning=True, constant_folding=rewriter_config_pb2.RewriterConfig.OFF, @@ -135,8 +143,9 @@ class MemoryOptimizerRecomputeTest(test.TestCase): layout_optimizer=rewriter_config_pb2.RewriterConfig.OFF, arithmetic_optimization=rewriter_config_pb2.RewriterConfig.OFF, min_graph_nodes=-1, - memory_optimization=rewriter_config_pb2.RewriterConfig. - RECOMPUTATION_HEURISTICS), original_metagraph) + memory_optimization=( + rewriter_config_pb2.RewriterConfig.RECOMPUTATION_HEURISTICS))) + rewritten_graph_def = tf_optimizer.OptimizeGraph(config, original_metagraph) self.assertGreater( len(rewritten_graph_def.node), len(original_metagraph.graph_def.node)) @@ -153,7 +162,8 @@ class MemoryOptimizerRecomputeTest(test.TestCase): """Tests that rewriting occurs with non-standard gradient names.""" (original_metagraph, _, _, _) = self._GetMetaGraph( optimizer_scope_name='optimizer') - rewritten_graph_def = tf_optimizer.OptimizeGraph( + config = config_pb2.ConfigProto() + config.graph_options.rewrite_options.CopyFrom( rewriter_config_pb2.RewriterConfig( disable_model_pruning=True, constant_folding=rewriter_config_pb2.RewriterConfig.OFF, @@ -161,11 +171,11 @@ class MemoryOptimizerRecomputeTest(test.TestCase): layout_optimizer=rewriter_config_pb2.RewriterConfig.OFF, arithmetic_optimization=rewriter_config_pb2.RewriterConfig.OFF, min_graph_nodes=-1, - memory_optimization=rewriter_config_pb2.RewriterConfig. - RECOMPUTATION_HEURISTICS, + memory_optimization=rewriter_config_pb2.RewriterConfig + .RECOMPUTATION_HEURISTICS, # Checks that name scope "gradients/" also match sub-scope. - memory_optimizer_target_node_name_scope='gradients/'), - original_metagraph) + memory_optimizer_target_node_name_scope='gradients/')) + rewritten_graph_def = tf_optimizer.OptimizeGraph(config, original_metagraph) self.assertGreater( len(rewritten_graph_def.node), len(original_metagraph.graph_def.node)) @@ -182,18 +192,19 @@ class MemoryOptimizerRecomputeTest(test.TestCase): """Tests that rewriting occurs with non-standard gradient names.""" (original_metagraph, _, _, _) = self._GetMetaGraph(optimizer_scope_name='foo/bar') - rewritten_graph_def = tf_optimizer.OptimizeGraph( + config = config_pb2.ConfigProto() + config.graph_options.rewrite_options.CopyFrom( rewriter_config_pb2.RewriterConfig( disable_model_pruning=True, constant_folding=rewriter_config_pb2.RewriterConfig.OFF, dependency_optimization=rewriter_config_pb2.RewriterConfig.OFF, layout_optimizer=rewriter_config_pb2.RewriterConfig.OFF, arithmetic_optimization=rewriter_config_pb2.RewriterConfig.OFF, - memory_optimization=rewriter_config_pb2.RewriterConfig. - RECOMPUTATION_HEURISTICS, + memory_optimization=rewriter_config_pb2.RewriterConfig + .RECOMPUTATION_HEURISTICS, # This should not match anything. - memory_optimizer_target_node_name_scope='r/gradients/'), - original_metagraph) + memory_optimizer_target_node_name_scope='r/gradients/')) + rewritten_graph_def = tf_optimizer.OptimizeGraph(config, original_metagraph) self.assertEqual( len(rewritten_graph_def.node), len(original_metagraph.graph_def.node)) self.assertEqual(0, @@ -223,10 +234,10 @@ class MemoryOptimizerRecomputeTest(test.TestCase): train_op = graph.get_operation_by_name(train_op_name) loss_op = graph.get_tensor_by_name(loss_op_name) with session.Session(config=config, graph=graph) as sess: - sess.run(init_op) - sess.run(train_op) - sess.run(train_op) - return sess.run(loss_op) + self.evaluate(init_op) + self.evaluate(train_op) + self.evaluate(train_op) + return self.evaluate(loss_op) def testRecomputationRewritingNoErrors(self): """Tests that graph output is not significantly different with rewriting.""" @@ -287,8 +298,8 @@ class MemoryOptimizerRecomputeTest(test.TestCase): rewrite_options=manual_memory_config) session_config = config_pb2.ConfigProto(graph_options=graph_options) with session.Session(config=session_config) as sess: - sess.run(init_op) - sess.run(train_op) + self.evaluate(init_op) + self.evaluate(train_op) def testHintDoesRewrite(self): graph = self._annotated_graph()[0] @@ -298,11 +309,12 @@ class MemoryOptimizerRecomputeTest(test.TestCase): 0, len([node for node in metagraph.graph_def.node if 'Recomputed/' in node.name])) - rewritten_graph_def = tf_optimizer.OptimizeGraph( + config = config_pb2.ConfigProto() + config.graph_options.rewrite_options.CopyFrom( rewriter_config_pb2.RewriterConfig( min_graph_nodes=-1, - memory_optimization=rewriter_config_pb2.RewriterConfig.MANUAL), - metagraph) + memory_optimization=rewriter_config_pb2.RewriterConfig.MANUAL)) + rewritten_graph_def = tf_optimizer.OptimizeGraph(config, metagraph) self.assertEqual( 9, len([node for node in rewritten_graph_def.node diff --git a/tensorflow/python/grappler/model_analyzer_test.py b/tensorflow/python/grappler/model_analyzer_test.py index ec172755f1..d000cfa1ba 100644 --- a/tensorflow/python/grappler/model_analyzer_test.py +++ b/tensorflow/python/grappler/model_analyzer_test.py @@ -21,6 +21,7 @@ from __future__ import print_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import meta_graph from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.grappler import model_analyzer from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -28,6 +29,7 @@ from tensorflow.python.platform import test class PyWrapOptimizeGraphTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): """Make sure arguments can be passed correctly.""" a = constant_op.constant([10, 11], name="a") @@ -49,6 +51,7 @@ class PyWrapOptimizeGraphTest(test.TestCase): # Also print the report to make it easier to debug print("{}".format(report)) + @test_util.run_deprecated_v1 def testDebugMode(self): """Make sure arguments can be passed correctly.""" a = constant_op.constant([10, 11], name="a") diff --git a/tensorflow/python/grappler/tf_optimizer.i b/tensorflow/python/grappler/tf_optimizer.i index 39ca71e99a..b746c3ec26 100644 --- a/tensorflow/python/grappler/tf_optimizer.i +++ b/tensorflow/python/grappler/tf_optimizer.i @@ -34,8 +34,8 @@ limitations under the License. $1 = &temp; } -%typemap(in) const tensorflow::RewriterConfig& ( - tensorflow::RewriterConfig temp) { +%typemap(in) const tensorflow::ConfigProto& ( + tensorflow::ConfigProto temp) { char* c_string; Py_ssize_t py_size; if (PyBytes_AsStringAndSize($input, &c_string, &py_size) == -1) { @@ -46,7 +46,7 @@ limitations under the License. if (!temp.ParseFromString(string(c_string, py_size))) { PyErr_SetString( PyExc_TypeError, - "The RewriterConfig could not be parsed as a valid protocol buffer"); + "The ConfigProto could not be parsed as a valid protocol buffer"); SWIG_fail; } $1 = &temp; @@ -67,20 +67,20 @@ limitations under the License. #include "tensorflow/core/grappler/clusters/utils.h" #include "tensorflow/core/grappler/clusters/virtual_cluster.h" #include "tensorflow/core/grappler/optimizers/meta_optimizer.h" + #include "tensorflow/core/protobuf/config.pb.h" #include "tensorflow/core/protobuf/meta_graph.pb.h" - #include "tensorflow/core/protobuf/rewriter_config.pb.h" #include "tensorflow/core/public/session_options.h" void DetectDevices(std::unordered_map* device_map) { tensorflow::SessionOptions options; - std::vector devices; + std::vector> devices; tensorflow::Status status = tensorflow::DeviceFactory::AddDevices(options, "", &devices); if (!status.ok()) { return; } - for (const tensorflow::Device* device : devices) { + for (const std::unique_ptr& device : devices) { tensorflow::DeviceProperties& prop = (*device_map)[device->name()]; prop = tensorflow::grappler::GetDeviceInfo(device->parsed_name()); @@ -88,13 +88,12 @@ void DetectDevices(std::unordered_map* dev // available device memory. const tensorflow::DeviceAttributes& attr = device->attributes(); prop.set_memory_size(attr.memory_limit()); - delete device; } } PyObject* TF_OptimizeGraph( GCluster cluster, - const tensorflow::RewriterConfig& rewriter_config, + const tensorflow::ConfigProto& config_proto, const tensorflow::MetaGraphDef& metagraph, bool verbose, const string& graph_id, TF_Status* out_status) { tensorflow::grappler::ItemConfig item_config; @@ -110,7 +109,7 @@ PyObject* TF_OptimizeGraph( tensorflow::DeviceBase* cpu_device = nullptr; tensorflow::GraphDef out_graph; - tensorflow::grappler::MetaOptimizer optimizer(cpu_device, rewriter_config); + tensorflow::grappler::MetaOptimizer optimizer(cpu_device, config_proto); tensorflow::Status status = optimizer.Optimize(cluster.get(), *grappler_item, &out_graph); if (verbose) { optimizer.PrintResult(); @@ -127,7 +126,7 @@ PyObject* TF_OptimizeGraph( // Wrap this function PyObject* TF_OptimizeGraph( GCluster cluster, - const tensorflow::RewriterConfig& rewriter_config, + const tensorflow::ConfigProto& config_proto, const tensorflow::MetaGraphDef& metagraph, bool verbose, const string& graph_id, TF_Status* out_status); diff --git a/tensorflow/python/grappler/tf_optimizer.py b/tensorflow/python/grappler/tf_optimizer.py index a73a4a98fc..e72667b6f3 100644 --- a/tensorflow/python/grappler/tf_optimizer.py +++ b/tensorflow/python/grappler/tf_optimizer.py @@ -19,22 +19,26 @@ from __future__ import division from __future__ import print_function from tensorflow.core.framework import graph_pb2 +from tensorflow.core.protobuf import config_pb2 from tensorflow.python import pywrap_tensorflow as tf_opt from tensorflow.python.framework import errors from tensorflow.python.grappler import cluster as gcluster -def OptimizeGraph(rewriter_config, +def OptimizeGraph(config_proto, metagraph, verbose=True, graph_id=b'graph_to_optimize', cluster=None): """Optimize the provided metagraph.""" + if not isinstance(config_proto, config_pb2.ConfigProto): + raise TypeError('Expected config_proto to be a ConfigProto, saw type %s' % + type(config_proto)) with errors.raise_exception_on_not_ok_status() as status: if cluster is None: cluster = gcluster.Cluster() ret_from_swig = tf_opt.TF_OptimizeGraph(cluster.tf_cluster, - rewriter_config.SerializeToString(), + config_proto.SerializeToString(), metagraph.SerializeToString(), verbose, graph_id, status) if ret_from_swig is None: diff --git a/tensorflow/python/grappler/tf_optimizer_test.py b/tensorflow/python/grappler/tf_optimizer_test.py index eca0f67982..06ccaa813f 100644 --- a/tensorflow/python/grappler/tf_optimizer_test.py +++ b/tensorflow/python/grappler/tf_optimizer_test.py @@ -17,12 +17,13 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.core.protobuf import rewriter_config_pb2 +from tensorflow.core.protobuf import config_pb2 from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import meta_graph from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.grappler import item as gitem from tensorflow.python.grappler import tf_optimizer from tensorflow.python.ops import array_ops @@ -34,6 +35,7 @@ from tensorflow.python.platform import test class PyWrapOptimizeGraphTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): """Make sure arguments can be passed correctly.""" a = constant_op.constant(10, name='a') @@ -45,15 +47,17 @@ class PyWrapOptimizeGraphTest(test.TestCase): train_op.append(d) mg = meta_graph.create_meta_graph_def(graph=ops.get_default_graph()) - rewriter_config = rewriter_config_pb2.RewriterConfig() + config = config_pb2.ConfigProto() + rewriter_config = config.graph_options.rewrite_options rewriter_config.optimizers.append('constfold') rewriter_config.min_graph_nodes = -1 - graph = tf_optimizer.OptimizeGraph(rewriter_config, mg) + graph = tf_optimizer.OptimizeGraph(config, mg) self.assertEqual(len(graph.node), 1) self.assertItemsEqual([node.name for node in graph.node], ['d']) + @test_util.run_deprecated_v1 def testKeepNodes(self): g = ops.Graph() with g.as_default(): @@ -68,18 +72,21 @@ class PyWrapOptimizeGraphTest(test.TestCase): # Optimize the graph. mg = meta_graph.create_meta_graph_def(graph=g) - rewriter_config = rewriter_config_pb2.RewriterConfig() + config = config_pb2.ConfigProto() + rewriter_config = config.graph_options.rewrite_options rewriter_config.min_graph_nodes = -1 - optimized_graph = tf_optimizer.OptimizeGraph(rewriter_config, mg) + optimized_graph = tf_optimizer.OptimizeGraph(config, mg) # Check that the nodes referenced in various collections have been preserved - self.assertEqual(len(optimized_graph.node), 5) - self.assertEqual(d.op.name, optimized_graph.node[0].name) - self.assertEqual(a1.op.name, optimized_graph.node[1].name) - self.assertEqual('Variable/initial_value', optimized_graph.node[2].name) - self.assertEqual(a2.op.name, optimized_graph.node[3].name) - self.assertEqual('Variable/Assign', optimized_graph.node[4].name) - + optimized_graph_nodes = [node.name for node in optimized_graph.node] + expected_nodes = [ + d.op.name, a1.op.name, a2.op.name, 'Variable/initial_value', + 'Variable/Assign' + ] + self.assertEqual(len(optimized_graph_nodes), len(expected_nodes)) + self.assertAllInSet(optimized_graph_nodes, expected_nodes) + + @test_util.run_deprecated_v1 def testLoops(self): g = ops.Graph() with g.as_default(): @@ -110,9 +117,10 @@ class PyWrapOptimizeGraphTest(test.TestCase): # Optimize the graph. mg = meta_graph.create_meta_graph_def(graph=g) - rewriter_config = rewriter_config_pb2.RewriterConfig() + config = config_pb2.ConfigProto() + rewriter_config = config.graph_options.rewrite_options rewriter_config.min_graph_nodes = -1 - optimized_graph = tf_optimizer.OptimizeGraph(rewriter_config, mg) + optimized_graph = tf_optimizer.OptimizeGraph(config, mg) mg.graph_def.CopyFrom(optimized_graph) # Check that the nodes referenced in various collections have been preserved diff --git a/tensorflow/python/keras/BUILD b/tensorflow/python/keras/BUILD index 6f38d822e7..ab5628b1d2 100755 --- a/tensorflow/python/keras/BUILD +++ b/tensorflow/python/keras/BUILD @@ -3,10 +3,10 @@ licenses(["notice"]) # Apache 2.0 -exports_files(["LICENSE"]) - package(default_visibility = ["//visibility:public"]) +exports_files(["LICENSE"]) + load("//tensorflow:tensorflow.bzl", "py_test") load("//tensorflow:tensorflow.bzl", "cuda_py_test") @@ -122,8 +122,10 @@ py_library( "constraints.py", "engine/__init__.py", "engine/base_layer.py", + "engine/base_layer_utils.py", "engine/distributed_training_utils.py", "engine/input_layer.py", + "engine/input_spec.py", "engine/network.py", "engine/saving.py", "engine/sequential.py", @@ -141,11 +143,14 @@ py_library( "regularizers.py", "utils/data_utils.py", "utils/io_utils.py", + "utils/losses_utils.py", ], srcs_version = "PY2AND3", deps = [ ":backend", "//tensorflow/python/data", + "//tensorflow/python/distribute:reduce_util", + "//tensorflow/python/keras/optimizer_v2", "//tensorflow/python/training/checkpointable:data_structures", "//tensorflow/tools/docs:doc_controls", "@six_archive//:six", @@ -180,7 +185,6 @@ py_library( ":engine", "//tensorflow/python:array_ops", "//tensorflow/python:cudnn_rnn_ops_gen", - "//tensorflow/python:distribute", "//tensorflow/python:dtypes", "//tensorflow/python:embedding_ops", "//tensorflow/python:framework_ops", @@ -194,6 +198,7 @@ py_library( "//tensorflow/python:tensor_array_ops", "//tensorflow/python:tensor_shape", "//tensorflow/python:util", + "//tensorflow/python/distribute:distribute_lib", ], ) @@ -264,6 +269,7 @@ py_test( name = "optimizers_test", size = "medium", srcs = ["optimizers_test.py"], + shard_count = 2, srcs_version = "PY2AND3", tags = ["notsan"], deps = [ @@ -271,6 +277,7 @@ py_test( "//tensorflow/python:client_testlib", "//tensorflow/python:training", "//third_party/py/numpy", + "@absl_py//absl/testing:parameterized", ], ) @@ -300,6 +307,7 @@ py_test( ":keras", "//tensorflow/python:client_testlib", "//third_party/py/numpy", + "@absl_py//absl/testing:parameterized", ], ) @@ -318,7 +326,7 @@ py_test( py_test( name = "advanced_activations_test", - size = "small", + size = "medium", srcs = ["layers/advanced_activations_test.py"], srcs_version = "PY2AND3", deps = [ @@ -369,7 +377,7 @@ cuda_py_test( py_test( name = "pooling_test", - size = "medium", + size = "large", srcs = ["layers/pooling_test.py"], srcs_version = "PY2AND3", deps = [ @@ -491,12 +499,13 @@ py_test( ":keras", "//tensorflow/python:client_testlib", "//third_party/py/numpy", + "@absl_py//absl/testing:parameterized", ], ) py_test( name = "recurrent_test", - size = "medium", + size = "large", srcs = ["layers/recurrent_test.py"], srcs_version = "PY2AND3", deps = [ @@ -506,6 +515,19 @@ py_test( ], ) +cuda_py_test( + name = "unified_lstm_test", + size = "medium", + srcs = ["layers/unified_lstm_test.py"], + additional_deps = [ + ":keras", + "@absl_py//absl/testing:parameterized", + "//third_party/py/numpy", + "//tensorflow/python:client_testlib", + ], + shard_count = 4, +) + py_test( name = "serialization_test", size = "small", @@ -577,6 +599,17 @@ py_test( ], ) +py_test( + name = "tf_utils_test", + size = "small", + srcs = ["utils/tf_utils_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":keras", + "//tensorflow/python:client_testlib", + ], +) + py_test( name = "io_utils_test", size = "small", @@ -706,16 +739,34 @@ py_test( ], ) +py_test( + name = "training_dataset_test", + size = "medium", + srcs = ["engine/training_dataset_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":keras", + "//tensorflow/python:client_testlib", + "//third_party/py/numpy", + "@absl_py//absl/testing:parameterized", + ], +) + py_test( name = "training_generator_test", size = "enormous", srcs = ["engine/training_generator_test.py"], + shard_count = 3, srcs_version = "PY2AND3", - tags = ["notsan"], + tags = [ + "no_oss", + "notsan", + ], deps = [ ":keras", "//tensorflow/python:client_testlib", "//third_party/py/numpy", + "@absl_py//absl/testing:parameterized", ], ) @@ -730,6 +781,7 @@ py_test( "//tensorflow/python:client_testlib", "//tensorflow/python/feature_column:feature_column_py", "//third_party/py/numpy", + "@absl_py//absl/testing:parameterized", ], ) @@ -763,6 +815,7 @@ py_test( name = "model_subclassing_test", size = "medium", srcs = ["model_subclassing_test.py"], + shard_count = 2, srcs_version = "PY2AND3", tags = ["notsan"], deps = [ diff --git a/tensorflow/python/keras/activations_test.py b/tensorflow/python/keras/activations_test.py index ad238cb0a9..6b7bfb698b 100644 --- a/tensorflow/python/keras/activations_test.py +++ b/tensorflow/python/keras/activations_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python import keras +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -67,6 +68,7 @@ class KerasActivationsTest(test.TestCase): expected = _ref_softmax(test_values[0, 0]) self.assertAllClose(result[0, 0], expected, rtol=1e-05) + @test_util.run_deprecated_v1 def test_selu(self): x = keras.backend.placeholder(ndim=2) f = keras.backend.function([x], [keras.activations.selu(x)]) @@ -124,6 +126,7 @@ class KerasActivationsTest(test.TestCase): expected = sigmoid(test_values) self.assertAllClose(result, expected, rtol=1e-05) + @test_util.run_deprecated_v1 def test_hard_sigmoid(self): def ref_hard_sigmoid(x): x = (x * 0.2) + 0.5 @@ -147,6 +150,7 @@ class KerasActivationsTest(test.TestCase): # No negative values in test values... self.assertAllClose(result, test_values, rtol=1e-05) + @test_util.run_deprecated_v1 def test_elu(self): with self.cached_session(): x = keras.backend.placeholder(ndim=2) diff --git a/tensorflow/python/keras/backend.py b/tensorflow/python/keras/backend.py index dd9b0c07e7..1277746716 100644 --- a/tensorflow/python/keras/backend.py +++ b/tensorflow/python/keras/backend.py @@ -25,6 +25,7 @@ import collections import itertools import json import os +import threading import weakref import numpy as np @@ -73,9 +74,9 @@ py_sum = sum # while executing eagerly (such as the functional API for model-building). _GRAPH = None -# This is the default internal TF session used by Keras. -# It can be set manually via `set_session(sess)`. -_SESSION = None +# This is a thread local object that will hold the default internal TF session +# used by Keras. It can be set manually via `set_session(sess)`. +_SESSION = threading.local() # This dictionary holds a mapping {graph: learning_phase}. # A learning phase is a bool tensor used to run Keras models in @@ -337,7 +338,7 @@ def clear_session(): global _GRAPH_TF_OPTIMIZERS # pylint: disable=global-variable-not-assigned ops.reset_default_graph() reset_uids() - _SESSION = None + _SESSION.session = None graph = get_graph() with graph.as_default(): phase = array_ops.placeholder_with_default( @@ -376,27 +377,22 @@ def learning_phase(): Returns: Learning phase (scalar integer tensor or Python integer). """ - with ops.init_scope(): - # We always check & set the learning phase inside the init_scope, - # otherwise the wrong default_graph will be used to look up the learning - # phase inside of functions & defuns. - # - # This is because functions & defuns (both in graph & in eager mode) - # will always execute non-eagerly using a function-specific default - # subgraph. - if context.executing_eagerly(): - if _DUMMY_EAGER_GRAPH not in _GRAPH_LEARNING_PHASES: - # Fallback to inference mode as default. - return 0 - return _GRAPH_LEARNING_PHASES[_DUMMY_EAGER_GRAPH] + if context.executing_eagerly(): + if _DUMMY_EAGER_GRAPH not in _GRAPH_LEARNING_PHASES: + # Fallback to inference mode as default. + return 0 + return _GRAPH_LEARNING_PHASES[_DUMMY_EAGER_GRAPH] + return symbolic_learning_phase() - graph = get_graph() - with graph.as_default(): - if graph not in _GRAPH_LEARNING_PHASES: - phase = array_ops.placeholder_with_default( - False, shape=(), name='keras_learning_phase') - _GRAPH_LEARNING_PHASES[graph] = phase - return _GRAPH_LEARNING_PHASES[graph] + +def symbolic_learning_phase(): + graph = get_graph() + with graph.as_default(): + if graph not in _GRAPH_LEARNING_PHASES: + phase = array_ops.placeholder_with_default( + False, shape=(), name='keras_learning_phase') + _GRAPH_LEARNING_PHASES[graph] = phase + return _GRAPH_LEARNING_PHASES[graph] @tf_export('keras.backend.set_learning_phase') @@ -449,6 +445,20 @@ def learning_phase_scope(value): _GRAPH_LEARNING_PHASES[get_graph()] = previous_value +def _get_session(): + """Returns the session object for the current thread.""" + global _SESSION + default_session = ops.get_default_session() + if default_session is not None: + session = default_session + else: + if getattr(_SESSION, 'session', None) is None: + _SESSION.session = session_module.Session( + config=get_default_session_config()) + session = _SESSION.session + return session + + @tf_export(v1=['keras.backend.get_session']) def get_session(): """Returns the TF session to be used by the backend. @@ -466,14 +476,7 @@ def get_session(): Returns: A TensorFlow session. """ - global _SESSION - default_session = ops.get_default_session() - if default_session is not None: - session = default_session - else: - if _SESSION is None: - _SESSION = session_module.Session(config=get_default_session_config()) - session = _SESSION + session = _get_session() if not _MANUAL_VAR_INIT: with session.graph.as_default(): _initialize_variables(session) @@ -498,7 +501,7 @@ def set_session(session): session: A TF Session. """ global _SESSION - _SESSION = session + _SESSION.session = session def get_default_session_config(): @@ -2322,7 +2325,7 @@ def concatenate(tensors, axis=-1): else: axis = 0 - if py_all([is_sparse(x) for x in tensors]): + if py_all(is_sparse(x) for x in tensors): return sparse_ops.sparse_concat(axis, tensors) else: return array_ops.concat([to_dense(x) for x in tensors], axis) @@ -2552,7 +2555,7 @@ def arange(start, stop=None, step=1, dtype='int32'): result = cast(result, dtype) return result - +@tf_export('keras.backend.tile') def tile(x, n): """Creates a tensor by tiling `x` by `n`. @@ -3123,20 +3126,20 @@ class EagerExecutionFunction(object): updates_ops.append(update) # We set the update ops to run at the end by conditioning it on output[0] - if updates and not outputs: + if updates and not self.outputs: # Edge case; never happens in practice raise ValueError('Cannot create a Keras backend function with updates' ' but no outputs during eager execution.') with ops.control_dependencies(updates_ops): - outputs[0] = array_ops.identity(outputs[0]) + self.outputs[0] = array_ops.identity(self.outputs[0]) # Prepare graph function # TODO(fchollet): can we restrict `captures` to variables actually used in # the relevant subgraph? - graph.inputs = inputs + list(graph.captures.values()) - graph.outputs = outputs + graph.inputs = self.inputs + list(graph.captures.values()) + graph.outputs = self.outputs graph_fn = eager_function.Function(graph) - graph_fn._num_positional_args = len(inputs) + graph_fn._num_positional_args = len(self.inputs) graph_fn._arg_keywords = [] self._graph_fn = graph_fn @@ -3158,8 +3161,13 @@ class EagerExecutionFunction(object): if value is None: raise ValueError( 'You must feed a value for placeholder %s' % (tensor,)) - converted_inputs.append( - ops.convert_to_tensor(value, dtype=tensor.dtype)) + if not isinstance(value, ops.Tensor): + value = ops.convert_to_tensor(value, dtype=tensor.dtype) + if value.dtype != tensor.dtype: + # Temporary workaround due to `convert_to_tensor` not casting floats. + # See b/119637405 + value = math_ops.cast(value, tensor.dtype) + converted_inputs.append(value) outputs = self._graph_fn(*converted_inputs) return [x.numpy() for x in outputs] @@ -3181,7 +3189,7 @@ def function(inputs, outputs, updates=None, name=None, **kwargs): Raises: ValueError: if invalid kwargs are passed in or if in eager execution. """ - if context.executing_eagerly(): + if ops.executing_eagerly_outside_functions(): if kwargs: raise ValueError('Session keyword arguments are not support during ' 'eager execution. You passed: %s' % (kwargs,)) @@ -3242,7 +3250,8 @@ def rnn(step_function, constants=None, unroll=False, input_length=None, - time_major=False): + time_major=False, + zero_output_for_mask=False): """Iterates over the time dimension of a tensor. Arguments: @@ -3280,7 +3289,9 @@ def rnn(step_function, RNN calculation. However, most TensorFlow data is batch-major, so by default this function accepts input and emits output in batch-major form. - + zero_output_for_mask: Boolean. If True, the output for masked timestep + will be zeros, whereas in the False case, output from previous + timestep is returned. Returns: A tuple, `(last_output, outputs, new_states)`. last_output: the latest output of the rnn, of shape `(samples, ...)` @@ -3332,13 +3343,13 @@ def rnn(step_function, # So we need to broadcast the mask to match the shape of inputs. # That's what the tile call does, it just repeats the mask along its # second dimension n times. - def _expand_mask(mask_t, input_t): + def _expand_mask(mask_t, input_t, fixed_dim=1): assert not nest.is_sequence(mask_t) assert not nest.is_sequence(input_t) rank_diff = len(input_t.shape) - len(mask_t.shape) for _ in range(rank_diff): mask_t = array_ops.expand_dims(mask_t) - expand_dims = [1] + input_t.shape.as_list()[1:] + expand_dims = [1] * fixed_dim + input_t.shape.as_list()[fixed_dim:] return array_ops.tile(mask_t, expand_dims) if unroll: @@ -3397,6 +3408,17 @@ def rnn(step_function, last_output = successive_outputs[-1] new_states = successive_states[-1] outputs = array_ops.stack(successive_outputs) + + if zero_output_for_mask: + last_output = array_ops.where( + _expand_mask(mask_list[-1], last_output), + last_output, + zeros_like(last_output)) + outputs = array_ops.where( + _expand_mask(mask, outputs, fixed_dim=2), + outputs, + zeros_like(outputs)) + else: for i in range(time_steps): inp = _get_input_tensor(i) @@ -3490,11 +3512,12 @@ def rnn(step_function, tuple(states) + tuple(constants)) # mask output flat_output = nest.flatten(output) - flat_previous_output = nest.flatten(prev_output) + flat_mask_output = (flat_zero_output if zero_output_for_mask + else nest.flatten(prev_output)) tiled_mask_t = tuple(_expand_mask(mask_t, o) for o in flat_output) flat_new_output = tuple( - array_ops.where(m, o, po) for m, o, po in zip( - tiled_mask_t, flat_output, flat_previous_output)) + array_ops.where(m, o, zo) for m, o, zo in zip( + tiled_mask_t, flat_output, flat_mask_output)) # mask states flat_state = nest.flatten(states) @@ -3503,8 +3526,8 @@ def rnn(step_function, new_state.set_shape(state.shape) tiled_mask_t = tuple(_expand_mask(mask_t, s) for s in flat_state) flat_final_state = tuple( - array_ops.where(m, o, po) - for m, o, po in zip(tiled_mask_t, flat_new_state, flat_state)) + array_ops.where(m, s, ps) + for m, s, ps in zip(tiled_mask_t, flat_new_state, flat_state)) new_states = nest.pack_sequence_as(new_states, flat_final_state) output_ta_t = tuple( @@ -3552,12 +3575,12 @@ def rnn(step_function, **while_loop_kwargs) new_states = final_outputs[2:] - last_time = final_outputs[0] output_ta = final_outputs[1] outputs = tuple(o.stack() for o in output_ta) + last_output = tuple(o[-1] for o in outputs) + outputs = nest.pack_sequence_as(output_time_zero, outputs) - last_output = tuple(o.read(last_time - 1) for o in output_ta) last_output = nest.pack_sequence_as(output_time_zero, last_output) # static shape inference @@ -3662,13 +3685,13 @@ def in_train_phase(x, alt, training=None): if training is None: training = learning_phase() - if training is 1 or training is True: + if training == 1 or training is True: if callable(x): return x() else: return x - elif training is 0 or training is False: + elif training == 0 or training is False: if callable(alt): return alt() else: diff --git a/tensorflow/python/keras/backend_test.py b/tensorflow/python/keras/backend_test.py index d8aa3e9b52..fdb9b281cb 100644 --- a/tensorflow/python/keras/backend_test.py +++ b/tensorflow/python/keras/backend_test.py @@ -136,7 +136,7 @@ class BackendUtilsTest(test.TestCase): x = keras.Input((3,)) y = keras.layers.BatchNormalization()(x) if not context.executing_eagerly(): - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) sess.run(y, feed_dict={x: np.random.random((2, 3))}) def test_learning_phase_scope(self): @@ -1069,13 +1069,13 @@ class BackendNNOpsTest(test.TestCase, parameterized.TestCase): initial_states, **kwargs) # check static shape inference - self.assertEquals(last_output.get_shape().as_list(), - [num_samples, output_dim]) - self.assertEquals(outputs.get_shape().as_list(), - [num_samples, timesteps, output_dim]) + self.assertEqual(last_output.get_shape().as_list(), + [num_samples, output_dim]) + self.assertEqual(outputs.get_shape().as_list(), + [num_samples, timesteps, output_dim]) for state in new_states: - self.assertEquals(state.get_shape().as_list(), - [num_samples, output_dim]) + self.assertEqual(state.get_shape().as_list(), + [num_samples, output_dim]) last_output_list[i].append(keras.backend.eval(last_output)) outputs_list[i].append(keras.backend.eval(outputs)) @@ -1173,7 +1173,7 @@ class BackendNNOpsTest(test.TestCase, parameterized.TestCase): self.assertEqual(outputs.get_shape().as_list(), [num_samples, timesteps, output_dim]) # for state in new_states: - # self.assertEquals(state.get_shape().as_list(), + # self.assertEqual(state.get_shape().as_list(), # [num_samples, output_dim]) self.assertEqual(new_states[0].get_shape().as_list(), [num_samples, output_dim]) @@ -1223,6 +1223,121 @@ class BackendNNOpsTest(test.TestCase, parameterized.TestCase): for s, u_s in zip(additional_state_list[2], additional_state_list[3]): self.assertAllClose(s, u_s, atol=1e-04) + def test_rnn_output_and_state_masking_independent(self): + num_samples = 2 + num_timesteps = 4 + state_and_io_size = 2 + mask_last_num_timesteps = 2 # for second sample only + + # a step function that just outputs inputs, + # but increments states +1 per timestep + def step_function(inputs, states): + return inputs, [s + 1 for s in states] + + inputs_vals = np.random.random( + (num_samples, num_timesteps, state_and_io_size)) + initial_state_vals = np.random.random((num_samples, state_and_io_size)) + # masking of two last timesteps for second sample only + mask_vals = np.ones((num_samples, num_timesteps)) + mask_vals[1, -mask_last_num_timesteps:] = 0 + + # outputs expected to be same as inputs for the first sample + expected_outputs = inputs_vals.copy() + # but for the second sample all outputs in masked region should be the same + # as last output before masked region + expected_outputs[1, -mask_last_num_timesteps:] = \ + expected_outputs[1, -(mask_last_num_timesteps + 1)] + + expected_last_state = initial_state_vals.copy() + # first state should be incremented for every timestep (no masking) + expected_last_state[0] += num_timesteps + # second state should not be incremented for last two timesteps + expected_last_state[1] += (num_timesteps - mask_last_num_timesteps) + + # verify same expected output for `unroll=true/false` + inputs = keras.backend.variable(inputs_vals) + initial_states = [keras.backend.variable(initial_state_vals)] + mask = keras.backend.variable(mask_vals) + for unroll in [True, False]: + _, outputs, last_states = keras.backend.rnn( + step_function, + inputs, + initial_states, + mask=mask, + unroll=unroll, + input_length=num_timesteps if unroll else None) + + self.assertAllClose(keras.backend.eval(outputs), expected_outputs) + self.assertAllClose(keras.backend.eval( + last_states[0]), expected_last_state) + + def test_rnn_output_num_dim_larger_than_2_masking(self): + num_samples = 3 + num_timesteps = 4 + num_features = 5 + + def step_function(inputs, states): + outputs = keras.backend.tile(keras.backend.expand_dims(inputs), [1, 1, 2]) + return outputs, [keras.backend.identity(s) for s in states] + # Note: cannot just return states (which can be a problem) -> + # tensorflow/python/ops/resource_variable_ops.py", line 824, in set_shape + # NotImplementedError: ResourceVariable does not implement set_shape() + + inputs_vals = np.random.random((num_samples, num_timesteps, num_features)) + initial_state_vals = np.random.random((num_samples, 6)) + mask_vals = np.ones((num_samples, num_timesteps)) + mask_vals[-1, -1] = 0 # final timestep masked for last sample + + expected_outputs = np.repeat(inputs_vals[..., None], repeats=2, axis=-1) + # for the last sample, the final timestep (in masked region) should be the + # same as the second to final output (before masked region) + expected_outputs[-1, -1] = expected_outputs[-1, -2] + + inputs = keras.backend.variable(inputs_vals) + initial_states = [keras.backend.variable(initial_state_vals)] + mask = keras.backend.variable(mask_vals) + for unroll in [True, False]: + _, outputs, _ = keras.backend.rnn( + step_function, + inputs, + initial_states, + mask=mask, + unroll=unroll, + input_length=num_timesteps if unroll else None) + + self.assertAllClose(keras.backend.eval(outputs), expected_outputs) + + def test_rnn_state_num_dim_larger_than_2_masking(self): + num_samples = 3 + num_timesteps = 4 + + def step_function(inputs, states): + return inputs, [s + 1 for s in states] + + inputs_vals = np.random.random((num_samples, num_timesteps, 5)) + initial_state_vals = np.random.random((num_samples, 6, 7)) + mask_vals = np.ones((num_samples, num_timesteps)) + mask_vals[0, -2:] = 0 # final two timesteps masked for first sample + + expected_last_state = initial_state_vals.copy() + expected_last_state[0] += (num_timesteps - 2) + expected_last_state[1:] += num_timesteps + + inputs = keras.backend.variable(inputs_vals) + initial_states = [keras.backend.variable(initial_state_vals)] + mask = keras.backend.variable(mask_vals) + for unroll in [True, False]: + _, _, last_states = keras.backend.rnn( + step_function, + inputs, + initial_states, + mask=mask, + unroll=unroll, + input_length=num_timesteps if unroll else None) + + self.assertAllClose( + keras.backend.eval(last_states[0]), expected_last_state) + def test_normalize_batch_in_training(self): val = np.random.random((10, 3, 10, 10)) x = keras.backend.variable(val) @@ -1307,6 +1422,7 @@ class TestCTC(test.TestCase): decode_truth[i] == keras.backend.eval(decode_pred_tf[i]))) self.assertAllClose(log_prob_truth, log_prob_pred) + @test_util.run_deprecated_v1 def test_ctc_batch_cost(self): with self.cached_session(): label_lens = np.expand_dims(np.asarray([5, 4]), 1) @@ -1392,6 +1508,7 @@ class TestRandomOps(test.TestCase): class BackendGraphTests(test.TestCase): + @test_util.run_deprecated_v1 def test_is_placeholder(self): x = keras.backend.placeholder(shape=(1,)) self.assertEqual(keras.backend.is_placeholder(x), True) @@ -1431,6 +1548,7 @@ class BackendGraphTests(test.TestCase): output_values = f([None, None]) self.assertEqual(output_values, [5., 6.]) + @test_util.run_deprecated_v1 def test_function_tf_feed_symbols(self): # Test Keras backend functions with TF tensor inputs. with self.cached_session(): @@ -1464,6 +1582,7 @@ class BackendGraphTests(test.TestCase): outs = f([y5, y2, None]) self.assertEqual(outs, [11., 2.]) + @test_util.run_deprecated_v1 def test_function_tf_fetches(self): # Additional operations can be passed to tf.Session().run() via its # `fetches` arguments. In contrast to `updates` argument of @@ -1486,6 +1605,7 @@ class BackendGraphTests(test.TestCase): self.assertEqual(keras.backend.get_session().run(fetches=[x, y]), [11., 5.]) + @test_util.run_deprecated_v1 def test_function_tf_feed_dict(self): # Additional substitutions can be passed to `tf.Session().run()` via its # `feed_dict` arguments. Note that the feed_dict is passed once in the @@ -1518,6 +1638,7 @@ class BackendGraphTests(test.TestCase): self.assertEqual(keras.backend.get_session().run(fetches=[x, y]), [30., 40.]) + @test_util.run_deprecated_v1 def test_function_tf_run_options_with_run_metadata(self): with self.cached_session(): x_placeholder = keras.backend.placeholder(shape=()) @@ -1543,6 +1664,7 @@ class BackendGraphTests(test.TestCase): self.assertEqual(output1, [30.]) self.assertEqual(len(run_metadata.partition_graphs), 0) + @test_util.run_deprecated_v1 def test_function_fetch_callbacks(self): class CallbackStub(object): @@ -1579,6 +1701,7 @@ class BackendGraphTests(test.TestCase): x = keras.backend.placeholder(shape=(3, 4), sparse=True) self.assertEqual(x.get_shape().as_list(), [3, 4]) + @test_util.run_deprecated_v1 def test_batch_normalization(self): # No eager CPU kernel. g_val = np.random.random((3,)) diff --git a/tensorflow/python/keras/callbacks.py b/tensorflow/python/keras/callbacks.py index fde17cb6bc..2d7d5a415d 100644 --- a/tensorflow/python/keras/callbacks.py +++ b/tensorflow/python/keras/callbacks.py @@ -24,7 +24,6 @@ import copy import csv import io import json -import math import os import time @@ -35,7 +34,6 @@ from tensorflow.python.data.ops import iterator_ops from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.keras import backend as K -from tensorflow.python.keras.engine.training_utils import standardize_input_data from tensorflow.python.keras.utils.data_utils import Sequence from tensorflow.python.keras.utils.generic_utils import Progbar from tensorflow.python.ops import array_ops @@ -54,17 +52,14 @@ except ImportError: requests = None +# pylint: disable=protected-access def configure_callbacks(callbacks, model, do_validation=False, - val_inputs=None, - val_targets=None, - val_sample_weights=None, batch_size=None, epochs=None, steps_per_epoch=None, samples=None, - validation_steps=None, verbose=1, count_mode='steps', mode='train'): @@ -74,17 +69,10 @@ def configure_callbacks(callbacks, callbacks: List of Callbacks. model: Model being trained. do_validation: Whether or not validation loop will be run. - val_inputs: Inputs to Model for validation loop. Can be any - data format Keras accepts. - val_targets: Targets for Model for validation loop. Can be any - data format Keras accepts. - val_sample_weights: Sample weights for Model for validation loop. - Can be any data format Keras accepts. batch_size: Number of samples per batch. epochs: Number of epoch to train. steps_per_epoch: Number of batches to run per training epoch. samples: Number of training samples. - validation_steps: Number of batches to run per validation epoch. verbose: int, 0 or 1. Keras logging verbosity to pass to ProgbarLogger. count_mode: One of 'steps' or 'samples'. Per-batch or per-sample count. mode: String. One of 'train', 'test', or 'predict'. Which loop mode to @@ -114,24 +102,17 @@ def configure_callbacks(callbacks, callback_list = CallbackList(callbacks) # Set callback model - callback_model = model._get_callback_model() # pylint: disable=protected-access - if do_validation and val_inputs and not context.executing_eagerly(): - # Need to create the eval_function before start of the first epoch - # because TensorBoard callback on_epoch_begin adds summary to the - # list of fetches of the eval_function - callback_model._make_eval_function() # pylint: disable=protected-access + callback_model = model._get_callback_model() callback_list.set_model(callback_model) # Set callback parameters callback_metrics = [] # When we have deferred build scenario with iterator input, we will compile # when we standardize first batch of data. - if mode != 'predict' and model._is_compiled: # pylint: disable=protected-access + if mode != 'predict' and hasattr(model, 'metrics_names'): callback_metrics = copy.copy(model.metrics_names) if do_validation: callback_metrics += ['val_' + n for n in model.metrics_names] - if validation_steps is None and isinstance(val_inputs, Sequence): - validation_steps = len(val_inputs) callback_params = { 'batch_size': batch_size, 'epochs': epochs, @@ -140,27 +121,19 @@ def configure_callbacks(callbacks, 'verbose': verbose, 'do_validation': do_validation, 'metrics': callback_metrics, - 'validation_steps': validation_steps } callback_list.set_params(callback_params) - # Pass validation data to callbacks - # TODO(omalleyt): remove this once val hooks are ready. - if not val_inputs: - val_data = [] - elif _is_generator_like(val_inputs): - val_data = val_inputs - else: - val_data = val_inputs + val_targets - if val_sample_weights: - val_data += val_sample_weights - if not isinstance(K.learning_phase(), int): - val_data += [0.] - for cbk in callbacks: - cbk.validation_data = val_data + if (do_validation and not model._distribution_strategy and + not model.run_eagerly): + # Need to create the eval_function before start of the first epoch + # because TensorBoard callback on_epoch_begin adds summary to the + # list of fetches of the eval_function + callback_model._make_eval_function() callback_list.model.stop_training = False return callback_list +# pylint: enable=protected-access def _is_generator_like(data): @@ -491,7 +464,8 @@ class ProgbarLogger(Callback): self.progbar = Progbar( target=self.target, verbose=self.verbose, - stateful_metrics=self.stateful_metrics) + stateful_metrics=self.stateful_metrics, + unit_name='step' if self.use_steps else 'sample') def on_batch_begin(self, batch, logs=None): if self.seen < self.target: @@ -953,6 +927,7 @@ class TensorBoard(Callback): self.batch_size = batch_size self._current_batch = 0 self._total_batches_seen = 0 + self._total_val_batches_seen = 0 self.embeddings_freq = embeddings_freq self.embeddings_layer_names = embeddings_layer_names self.embeddings_metadata = embeddings_metadata @@ -1041,8 +1016,10 @@ class TensorBoard(Callback): # If both embedding_freq and embeddings_data are available, we will # visualize embeddings. if self.embeddings_freq and self.embeddings_data is not None: - self.embeddings_data = standardize_input_data(self.embeddings_data, - model.input_names) + # Avoid circular dependency. + from tensorflow.python.keras.engine import training_utils # pylint: disable=g-import-not-at-top + self.embeddings_data = training_utils.standardize_input_data( + self.embeddings_data, model.input_names) # If embedding_layer_names are not provided, get all of the embedding # layers from the model. @@ -1107,10 +1084,8 @@ class TensorBoard(Callback): projector.visualize_embeddings(self.writer, config) def _fetch_callback(self, summary): - self.writer.add_summary( - summary, - self._epoch + self._current_val_batch / self._validation_batches) - self._current_val_batch += 1 + self.writer.add_summary(summary, self._total_val_batches_seen) + self._total_val_batches_seen += 1 def _write_custom_summaries(self, step, logs=None): """Writes metrics out as custom scalar summaries. @@ -1141,22 +1116,6 @@ class TensorBoard(Callback): self.writer.add_summary(summary, step) self.writer.flush() - def on_train_begin(self, logs=None): - """Checks if histogram summaries can be run.""" - # will never be set when in eager - if self.histogram_freq: - if self.params.get('validation_steps', None) is not None: - self._validation_batches = self.params['validation_steps'] - elif self.validation_data: - self._validation_batches = math.ceil( - self.validation_data[0].shape[0] / self.batch_size) - else: - raise ValueError('If printing histograms, validation data must be ' - 'provided.') - if self._validation_batches == 0: - raise ValueError( - 'If printing histograms, validation data must have length > 0.') - def on_batch_end(self, batch, logs=None): """Writes scalar summaries for metrics on every training batch.""" # Don't output batch_size and batch number as Tensorboard summaries @@ -1177,7 +1136,6 @@ class TensorBoard(Callback): # check if histogram summary should be run for this epoch if self.histogram_freq and epoch % self.histogram_freq == 0: self._epoch = epoch - self._current_val_batch = 0 # pylint: disable=protected-access # add the histogram summary op if it should run this epoch if self.merged not in self.model._eval_function.fetches: diff --git a/tensorflow/python/keras/callbacks_test.py b/tensorflow/python/keras/callbacks_test.py index 9d9ede22c0..6c9a382b32 100644 --- a/tensorflow/python/keras/callbacks_test.py +++ b/tensorflow/python/keras/callbacks_test.py @@ -36,7 +36,6 @@ from tensorflow.python.framework import test_util from tensorflow.python.keras import testing_utils from tensorflow.python.platform import test from tensorflow.python.platform import tf_logging as logging -from tensorflow.python.summary.writer import writer_cache from tensorflow.python.training import adam try: @@ -404,6 +403,7 @@ class KerasCallbacksTest(test.TestCase): float(keras.backend.get_value( model.optimizer.lr)) - 0.01 / 4) < keras.backend.epsilon() + @test_util.run_deprecated_v1 def test_ReduceLROnPlateau(self): with self.cached_session(): np.random.seed(1337) @@ -675,6 +675,7 @@ class KerasCallbacksTest(test.TestCase): self.assertEqual(len(loss), 1) self.assertEqual(loss[0], np.inf) + @test_util.run_deprecated_v1 def test_TensorBoard(self): np.random.seed(1337) @@ -778,78 +779,7 @@ class KerasCallbacksTest(test.TestCase): data_generator(True), len(x_train), epochs=2, callbacks=cbks) assert os.path.exists(temp_dir) - def test_TensorBoard_histogram_freq_must_have_validation_data(self): - np.random.seed(1337) - tmpdir = self.get_temp_dir() - self.addCleanup(shutil.rmtree, tmpdir, ignore_errors=True) - - with self.cached_session(): - filepath = os.path.join(tmpdir, 'logs') - - (x_train, y_train), (x_test, y_test) = testing_utils.get_test_data( - train_samples=TRAIN_SAMPLES, - test_samples=TEST_SAMPLES, - input_shape=(INPUT_DIM,), - num_classes=NUM_CLASSES) - y_test = keras.utils.to_categorical(y_test) - y_train = keras.utils.to_categorical(y_train) - - def data_generator(train): - if train: - max_batch_index = len(x_train) // BATCH_SIZE - else: - max_batch_index = len(x_test) // BATCH_SIZE - i = 0 - while 1: - if train: - # simulate multi-input/output models - yield (x_train[i * BATCH_SIZE: (i + 1) * BATCH_SIZE], - y_train[i * BATCH_SIZE: (i + 1) * BATCH_SIZE]) - else: - yield (x_test[i * BATCH_SIZE: (i + 1) * BATCH_SIZE], - y_test[i * BATCH_SIZE: (i + 1) * BATCH_SIZE]) - i += 1 - i %= max_batch_index - - inp = keras.Input((INPUT_DIM,)) - hidden = keras.layers.Dense(2, activation='relu')(inp) - hidden = keras.layers.Dropout(0.1)(hidden) - output = keras.layers.Dense(NUM_CLASSES, activation='softmax')(hidden) - model = keras.models.Model(inputs=inp, outputs=output) - model.compile(loss='categorical_crossentropy', - optimizer='sgd', - metrics=['accuracy']) - - # we must generate new callbacks for each test, as they aren't stateless - def callbacks_factory(histogram_freq): - return [keras.callbacks.TensorBoard( - log_dir=filepath, - histogram_freq=histogram_freq, - write_images=True, write_grads=True, - batch_size=5)] - - # fit w/o validation data should raise ValueError if histogram_freq > 0 - cbs = callbacks_factory(histogram_freq=1) - with self.assertRaises(ValueError): - model.fit( - x_train, y_train, batch_size=BATCH_SIZE, callbacks=cbs, epochs=3) - - for cb in cbs: - cb.on_train_end() - - # fit generator without validation data should raise ValueError if - # histogram_freq > 0 - cbs = callbacks_factory(histogram_freq=1) - with self.assertRaises(ValueError): - model.fit_generator( - data_generator(True), len(x_train), epochs=2, callbacks=cbs) - - for cb in cbs: - cb.on_train_end() - - # Make sure file writer cache is clear to avoid failures during cleanup. - writer_cache.FileWriterCache.clear() - + @test_util.run_deprecated_v1 def test_TensorBoard_multi_input_output(self): np.random.seed(1337) tmpdir = self.get_temp_dir() @@ -921,6 +851,7 @@ class KerasCallbacksTest(test.TestCase): callbacks=callbacks_factory(histogram_freq=1)) assert os.path.isdir(filepath) + @test_util.run_deprecated_v1 def test_Tensorboard_histogram_summaries_in_test_function(self): class FileWriterStub(object): @@ -996,8 +927,9 @@ class KerasCallbacksTest(test.TestCase): epochs=3, verbose=0) - self.assertAllEqual(tsb.writer.steps_seen, [0, 0.5, 1, 1.5, 2, 2.5]) + self.assertAllEqual(tsb.writer.steps_seen, [0, 1, 2, 3, 4, 5]) + @test_util.run_deprecated_v1 def test_Tensorboard_histogram_summaries_with_generator(self): np.random.seed(1337) tmpdir = self.get_temp_dir() @@ -1129,6 +1061,7 @@ class KerasCallbacksTest(test.TestCase): assert os.path.exists(temp_dir) + @test_util.run_deprecated_v1 def test_Tensorboard_batch_logging(self): class FileWriterStub(object): @@ -1163,6 +1096,7 @@ class KerasCallbacksTest(test.TestCase): self.assertEqual(tb_cbk.writer.summary_values, [0., 1., 2., 3., 4.]) self.assertEqual(tb_cbk.writer.summary_tags, ['batch_acc'] * 5) + @test_util.run_deprecated_v1 def test_Tensorboard_epoch_and_batch_logging(self): class FileWriterStub(object): @@ -1234,6 +1168,7 @@ class KerasCallbacksTest(test.TestCase): self.assertTrue(os.path.exists(temp_dir)) + @test_util.run_deprecated_v1 def test_TensorBoard_update_freq(self): class FileWriterStub(object): @@ -1325,6 +1260,7 @@ class KerasCallbacksTest(test.TestCase): callbacks=cbks, epochs=1) + @test_util.run_deprecated_v1 def test_fit_generator_with_callback(self): class TestCallback(keras.callbacks.Callback): diff --git a/tensorflow/python/keras/engine/__init__.py b/tensorflow/python/keras/engine/__init__.py index 26aed34766..005f6462ff 100644 --- a/tensorflow/python/keras/engine/__init__.py +++ b/tensorflow/python/keras/engine/__init__.py @@ -20,10 +20,10 @@ from __future__ import print_function # TODO(fchollet): Remove hourglass imports once external code is done importing # non-public APIs. -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer from tensorflow.python.keras.engine.input_layer import Input from tensorflow.python.keras.engine.input_layer import InputLayer +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.utils.layer_utils import get_source_inputs del absolute_import diff --git a/tensorflow/python/keras/engine/base_layer.py b/tensorflow/python/keras/engine/base_layer.py index 23419ae150..8e35300342 100644 --- a/tensorflow/python/keras/engine/base_layer.py +++ b/tensorflow/python/keras/engine/base_layer.py @@ -18,8 +18,6 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import collections as collections_lib -import enum # pylint: disable=g-bad-import-order import functools import inspect # Necessary supplement to tf_inspect to deal with variadic args. @@ -36,13 +34,14 @@ from tensorflow.python.keras import backend from tensorflow.python.keras import constraints from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers +from tensorflow.python.keras.engine import base_layer_utils +from tensorflow.python.keras.engine import input_spec from tensorflow.python.keras.utils import generic_utils from tensorflow.python.keras.utils import tf_utils # A module that only depends on `keras.layers` import these from here. from tensorflow.python.keras.utils.generic_utils import to_snake_case # pylint: disable=unused-import from tensorflow.python.keras.utils.tf_utils import is_tensor_or_tensor_list # pylint: disable=unused-import from tensorflow.python.ops import array_ops -from tensorflow.python.ops import init_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables as tf_variables from tensorflow.python.training.checkpointable import base as checkpointable @@ -54,20 +53,6 @@ from tensorflow.python.util.tf_export import tf_export from tensorflow.tools.docs import doc_controls -class CallConvention(enum.Enum): - """Calling conventions for passing `Layer` inputs to `Layer.call`.""" - # The Layer takes inputs as its first argument, named "inputs" for - # compatibility with the signature of Layer.__call__. This is the mode assumed - # for Layers which are not subclassed Models. - EXPLICIT_INPUTS_ARGUMENT = 1 - # The Layer takes a single positional argument, not named "inputs". It's - # treated like an "inputs" argument. - SINGLE_POSITIONAL_ARGUMENT = 2 - # The Layer has multiple positional arguments to which its inputs should be - # bound. - POSITIONAL_ARGUMENTS_ARE_INPUTS = 3 - - @tf_export('keras.layers.Layer') class Layer(checkpointable.CheckpointableBase): """Base layer class. @@ -102,10 +87,6 @@ class Layer(checkpointable.CheckpointableBase): name: The name of the layer (string). dtype: Default dtype of the layer's weights (default of `None` means use the type of the first input). - trainable_variables: List of trainable variables. - non_trainable_variables: List of non-trainable variables. - variables: List of all variables of this layer, trainable and - non-trainable. updates: List of update ops of this layer. losses: List of losses added by this layer. trainable_weights: List of variables to be included in backprop. @@ -150,9 +131,9 @@ class Layer(checkpointable.CheckpointableBase): self.built = False # Provides information about which inputs are compatible with the layer. self.input_spec = None + self.supports_masking = False self._init_set_name(name) - self._activity_regularizer = kwargs.pop('activity_regularizer', None) self._trainable_weights = [] self._non_trainable_weights = [] @@ -170,29 +151,25 @@ class Layer(checkpointable.CheckpointableBase): # in eager mode or graph mode alternatively, we need to keep track of # eager losses and symbolic losses via separate attributes. self._eager_losses = [] + # A list of metric instances corresponding to the symbolic metric tensors + # added using the `add_metric` API. + self._metrics = [] + # TODO(psv): Remove this property. + # A dictionary that maps metric names to metric result tensors. The results + # are the running averages of metric values over an epoch. + self._metrics_tensors = {} self._dtype = None if dtype is None else dtypes.as_dtype(dtype).name self._call_fn_args = function_utils.fn_args(self.call) self._compute_previous_mask = ('mask' in self._call_fn_args or hasattr(self, 'compute_mask')) - self._call_convention = CallConvention.EXPLICIT_INPUTS_ARGUMENT + self._call_convention = (base_layer_utils + .CallConvention.EXPLICIT_INPUTS_ARGUMENT) # These lists will be filled via successive calls # to self._add_inbound_node(). self._inbound_nodes = [] self._outbound_nodes = [] - self.supports_masking = False - - # Mark if a layer supports using graph functions in the eager - # fit/predict/evaluate loop - # TODO(kaftan): merge this with the _static_graph_friendly flag once - # enough eager function bugs involving control flow / tensorarrays have - # been fixed, and static-graph-friendly layers will almost always work in - # eager graph functions. - # We conservatively make this flag opt-in for now to avoid causing existing - # custom layers to crash. - self._can_use_graph_functions = False - call_argspec = tf_inspect.getfullargspec(self.call) if 'training' in call_argspec.args: self._expects_training_arg = True @@ -200,7 +177,7 @@ class Layer(checkpointable.CheckpointableBase): self._expects_training_arg = False # Whether the `call` method can be used to build a TF graph without issues. - self._static_graph_friendly = True + self._call_is_graph_friendly = True # Manage input shape information if passed. if 'input_shape' in kwargs or 'batch_input_shape' in kwargs: @@ -222,543 +199,348 @@ class Layer(checkpointable.CheckpointableBase): else: self._initial_weights = None - @property - def _is_static_graph_friendly(self): - return self._static_graph_friendly - - @_is_static_graph_friendly.setter - def _is_static_graph_friendly(self, value): - if value not in {True, False}: - raise ValueError('`static_graph_friendly` requires a boolean value. ' - 'Received: {}'.format(value)) - self._static_graph_friendly = value - - def _init_set_name(self, name, zero_based=True): - if not name: - self._name = unique_layer_name( - generic_utils.to_snake_case(self.__class__.__name__), - zero_based=zero_based) - else: - self._name = name - - @property - def dtype(self): - return self._dtype - - @property - def name(self): - return self._name - - @property - def activity_regularizer(self): - """Optional regularizer function for the output of this layer.""" - return self._activity_regularizer - - @activity_regularizer.setter - def activity_regularizer(self, regularizer): - """Optional regularizer function for the output of this layer.""" - self._activity_regularizer = self._no_dependency(regularizer) + def build(self, input_shape): + """Creates the variables of the layer (optional, for subclass implementers). - @property - def trainable_weights(self): - return self._trainable_weights if self.trainable else [] + This is a method that implementers of subclasses of `Layer` or `Model` + can override if they need a state-creation step in-between + layer instantiation and layer call. - @property - def non_trainable_weights(self): - if self.trainable: - return self._non_trainable_weights - else: - return self._trainable_weights + self._non_trainable_weights + This is typically used to create the weights of `Layer` subclasses. - @property - def trainable_variables(self): - return self.trainable_weights + Arguments: + input_shape: Instance of `TensorShape`, or list of instances of + `TensorShape` if the layer expects a list of inputs + (one instance per input). + """ + self.built = True - @property - def non_trainable_variables(self): - return self.non_trainable_weights + @doc_controls.for_subclass_implementers + def call(self, inputs, **kwargs): # pylint: disable=unused-argument + """This is where the layer's logic lives. - @property - def weights(self): - """Returns the list of all layer variables/weights. + Arguments: + inputs: Input tensor, or list/tuple of input tensors. + **kwargs: Additional keyword arguments. Returns: - A list of variables. + A tensor or list/tuple of tensors. """ - return self.trainable_weights + self.non_trainable_weights + return inputs - @property - def variables(self): - """Returns the list of all layer variables/weights. + @doc_controls.for_subclass_implementers + def add_weight(self, + name, + shape, + dtype=None, + initializer=None, + regularizer=None, + trainable=None, + constraint=None, + partitioner=None, + use_resource=None, + synchronization=tf_variables.VariableSynchronization.AUTO, + aggregation=tf_variables.VariableAggregation.NONE, + **kwargs): + """Adds a new variable to the layer, or gets an existing one; returns it. - Returns: - A list of variables. - """ - return self.weights + Arguments: + name: variable name. + shape: variable shape. + dtype: The type of the variable. Defaults to `self.dtype` or `float32`. + initializer: initializer instance (callable). + regularizer: regularizer instance (callable). + trainable: whether the variable should be part of the layer's + "trainable_variables" (e.g. variables, biases) + or "non_trainable_variables" (e.g. BatchNorm mean, stddev). + Note, if the current variable scope is marked as non-trainable + then this parameter is ignored and any added variables are also + marked as non-trainable. `trainable` defaults to `True` unless + `synchronization` is set to `ON_READ`. + constraint: constraint instance (callable). + partitioner: Partitioner to be passed to the `Checkpointable` API. + use_resource: Whether to use `ResourceVariable`. + synchronization: Indicates when a distributed a variable will be + aggregated. Accepted values are constants defined in the class + `tf.VariableSynchronization`. By default the synchronization is set to + `AUTO` and the current `DistributionStrategy` chooses + when to synchronize. If `synchronization` is set to `ON_READ`, + `trainable` must not be set to `True`. + aggregation: Indicates how a distributed variable will be aggregated. + Accepted values are constants defined in the class + `tf.VariableAggregation`. + **kwargs: Additional keyword arguments. Accepted values are `getter` and + `collections`. - @property - def updates(self): - if context.executing_eagerly(): - raise RuntimeError('Layer.updates not supported in Eager mode.') - if not self.trainable and not self.stateful: - return [] - return self._updates + Returns: + The created variable. Usually either a `Variable` or `ResourceVariable` + instance. If `partitioner` is not `None`, a `PartitionedVariable` + instance is returned. - @doc_controls.for_subclass_implementers - def add_update(self, updates, inputs=None): - """Add update op(s), potentially dependent on layer inputs. + Raises: + RuntimeError: If called with partioned variable regularization and + eager execution is enabled. + ValueError: When giving unsupported dtype and no initializer or when + trainable has been set to True with synchronization set as `ON_READ`. + """ + # Validate optional keyword arguments. + for kwarg in kwargs: + if kwarg not in ['getter', 'collections']: + raise TypeError('Unknown keyword argument:', kwarg) + getter = kwargs.pop('getter', None) + collections = kwargs.pop('collections', None) - Weight updates (for instance, the updates of the moving mean and variance - in a BatchNormalization layer) may be dependent on the inputs passed - when calling a layer. Hence, when reusing the same layer on - different inputs `a` and `b`, some entries in `layer.updates` may be - dependent on `a` and some on `b`. This method automatically keeps track - of dependencies. + if dtype is None: + dtype = self.dtype or backend.floatx() + dtype = dtypes.as_dtype(dtype) + initializer = initializers.get(initializer) + regularizer = regularizers.get(regularizer) + constraint = constraints.get(constraint) - The `get_updates_for` method allows to retrieve the updates relevant to a - specific set of inputs. + if synchronization == tf_variables.VariableSynchronization.ON_READ: + if trainable: + raise ValueError( + 'Synchronization value can be set to ' + 'VariableSynchronization.ON_READ only for non-trainable variables. ' + 'You have specified trainable=True and ' + 'synchronization=VariableSynchronization.ON_READ.') + else: + # Set trainable to be false when variable is to be synced on read. + trainable = False + elif trainable is None: + trainable = True - This call is ignored when eager execution is enabled (in that case, variable - updates are run on the fly and thus do not need to be tracked for later - execution). + # Initialize variable when no initializer provided + if initializer is None: + # If dtype is DT_FLOAT, provide a uniform unit scaling initializer + if dtype.is_floating: + initializer = initializers.glorot_uniform() + # If dtype is DT_INT/DT_UINT, provide a default value `zero` + # If dtype is DT_BOOL, provide a default value `FALSE` + elif dtype.is_integer or dtype.is_unsigned or dtype.is_bool: + initializer = initializers.zeros() + # NOTES:Do we need to support for handling DT_STRING and DT_COMPLEX here? + else: + raise ValueError('An initializer for variable %s of type %s is required' + ' for layer %s' % (name, dtype.base_dtype, self.name)) - Arguments: - updates: Update op, or list/tuple of update ops. - inputs: If anything other than None is passed, it signals the updates - are conditional on some of the layer's inputs, - and thus they should only be run where these inputs are available. - This is the case for BatchNormalization updates, for instance. - If None, the updates will be taken into account unconditionally, - and you are responsible for making sure that any dependency they might - have is available at runtime. - A step counter might fall into this category. - """ - if context.executing_eagerly(): - return # Updates already applied when in eager mode. + variable = self._add_variable_with_custom_getter( + name=name, + shape=shape, + # TODO(allenl): a `make_variable` equivalent should be added as a + # `Checkpointable` method. + getter=getter or base_layer_utils.make_variable, + # Manage errors in Layer rather than Checkpointable. + overwrite=True, + initializer=initializer, + dtype=dtype, + constraint=constraint, + trainable=trainable and self.trainable, + partitioner=partitioner, + use_resource=use_resource, + collections=collections, + synchronization=synchronization, + aggregation=aggregation) + backend.track_variable(variable) - def process_update(x): - if isinstance(x, ops.Operation): - return x - elif hasattr(x, 'op'): - return x.op - else: - return ops.convert_to_tensor(x) + if regularizer is not None: + # TODO(fchollet): in the future, this should be handled at the + # level of variable creation, and weight regularization losses + # should be variable attributes. + self._handle_weight_regularization(name, variable, regularizer) - updates = generic_utils.to_list(updates) - updates = [process_update(x) for x in updates] - self._updates += updates - if inputs is None: - for u in updates: - u._unconditional_update = True # pylint: disable=protected-access + if trainable: + self._trainable_weights.append(variable) else: - for u in updates: - u._unconditional_update = False # pylint: disable=protected-access + self._non_trainable_weights.append(variable) + return variable - def get_updates_for(self, inputs): - """Retrieves updates relevant to a specific set of inputs. + def get_config(self): + """Returns the config of the layer. - Arguments: - inputs: Input tensor or list/tuple of input tensors. + A layer config is a Python dictionary (serializable) + containing the configuration of a layer. + The same layer can be reinstantiated later + (without its trained weights) from this configuration. - Returns: - List of update ops of the layer that depend on `inputs`. + The config of a layer does not include connectivity + information, nor the layer class name. These are handled + by `Network` (one layer of abstraction above). - Raises: - RuntimeError: If called in Eager mode. + Returns: + Python dictionary. """ - if context.executing_eagerly(): - raise RuntimeError('`get_updates_for()` not supported in Eager mode.') + config = {'name': self.name, 'trainable': self.trainable} + if hasattr(self, '_batch_input_shape'): + config['batch_input_shape'] = self._batch_input_shape + if hasattr(self, 'dtype'): + config['dtype'] = self.dtype + return config - # Updates disabled if layer is not trainable and not explicitly stateful. - if not self.trainable and not self.stateful: - return [] + @classmethod + def from_config(cls, config): + """Creates a layer from its config. - if inputs is None: - # Requesting unconditional updates. - return [x for x in self.updates if x._unconditional_update] # pylint: disable=protected-access + This method is the reverse of `get_config`, + capable of instantiating the same layer from the config + dictionary. It does not handle layer connectivity + (handled by Network), nor weights (handled by `set_weights`). - # Requesting input-conditional updates. - inputs = nest.flatten(inputs) - reachable = tf_utils.get_reachable_from_inputs(inputs, self.updates) - updates = [] - for update in self.updates: - if update in reachable: - updates.append(update) - return updates + Arguments: + config: A Python dictionary, typically the + output of get_config. - @property - def losses(self): - """Losses which are associated with this `Layer`. + Returns: + A layer instance. + """ + return cls(**config) - Variable regularization tensors are created when this property is accessed, - so it is eager safe: accessing `losses` under a `tf.GradientTape` will - propagate gradients back to the corresponding variables. + def compute_output_shape(self, input_shape): + """Computes the output shape of the layer. + + Assumes that the layer will be built + to match that input shape provided. + + Arguments: + input_shape: Shape tuple (tuple of integers) + or list of shape tuples (one per output tensor of the layer). + Shape tuples can include None for free dimensions, + instead of an integer. Returns: - A list of tensors. + An input shape tuple. """ - collected_losses = [] if context.executing_eagerly(): - collected_losses.extend(self._eager_losses) - else: - collected_losses.extend(self._losses) - for regularizer in self._callable_losses: - loss_tensor = regularizer() - if loss_tensor is not None: - collected_losses.append(loss_tensor) - return collected_losses - - @doc_controls.for_subclass_implementers - def add_loss(self, losses, inputs=None): - """Add loss tensor(s), potentially dependent on layer inputs. - - Some losses (for instance, activity regularization losses) may be dependent - on the inputs passed when calling a layer. Hence, when reusing the same - layer on different inputs `a` and `b`, some entries in `layer.losses` may - be dependent on `a` and some on `b`. This method automatically keeps track - of dependencies. + # In this case we build the model first in order to do shape inference. + # This is acceptable because the framework only calls + # `compute_output_shape` on shape values that the layer would later be + # built for. It would however cause issues in case a user attempts to + # use `compute_output_shape` manually (these users will have to + # implement `compute_output_shape` themselves). + self.build(input_shape) + with context.graph_mode(): + graph = func_graph.FuncGraph('graph') + with graph.as_default(): + if isinstance(input_shape, list): + inputs = [base_layer_utils.generate_placeholders_from_shape(shape) + for shape in input_shape] + else: + inputs = base_layer_utils.generate_placeholders_from_shape( + input_shape) - The `get_losses_for` method allows to retrieve the losses relevant to a - specific set of inputs. + try: + if self._expects_training_arg: + outputs = self(inputs, training=False) + else: + outputs = self(inputs) + except TypeError: + raise NotImplementedError('We could not automatically infer ' + 'the static shape of the layer\'s output.' + ' Please implement the ' + '`compute_output_shape` method on your ' + 'layer (%s).' % self.__class__.__name__) + if isinstance(outputs, list): + return [output.shape for output in outputs] + else: + return outputs.shape + raise NotImplementedError - Note that `add_loss` is not supported when executing eagerly. Instead, - variable regularizers may be added through `add_variable`. Activity - regularization is not supported directly (but such losses may be returned - from `Layer.call()`). + def compute_mask(self, inputs, mask=None): # pylint: disable=unused-argument + """Computes an output mask tensor. Arguments: - losses: Loss tensor, or list/tuple of tensors. Rather than tensors, losses - may also be zero-argument callables which create a loss tensor. - inputs: Ignored when executing eagerly. If anything other than None is - passed, it signals the losses are conditional on some of the layer's - inputs, and thus they should only be run where these inputs are - available. This is the case for activity regularization losses, for - instance. If `None` is passed, the losses are assumed - to be unconditional, and will apply across all dataflows of the layer - (e.g. weight regularization losses). - """ - losses = generic_utils.to_list(losses) - - def _tag_unconditional(loss): - if callable(loss): - loss = loss() - if loss is None: - return None # Will be filtered out when computing the .losses property - if not tensor_util.is_tensor(loss): - loss = ops.convert_to_tensor(loss, dtype=backend.floatx()) - loss._unconditional_loss = (inputs is None) # pylint: disable=protected-access - return loss + inputs: Tensor or list of tensors. + mask: Tensor or list of tensors. - for loss in losses: - if callable(loss): - self._callable_losses.append( - functools.partial(_tag_unconditional, loss)) - else: - if context.executing_eagerly(): - self._eager_losses.append(_tag_unconditional(loss)) + Returns: + None or a tensor (or list of tensors, + one per output tensor of the layer). + """ + if not self.supports_masking: + if mask is not None: + if isinstance(mask, list): + if any(m is not None for m in mask): + raise TypeError('Layer ' + self.name + ' does not support masking, ' + 'but was passed an input_mask: ' + str(mask)) else: - self._losses.append(_tag_unconditional(loss)) + raise TypeError('Layer ' + self.name + ' does not support masking, ' + 'but was passed an input_mask: ' + str(mask)) + # masking not explicitly supported: return None as mask + return None + # if masking is explicitly supported, by default + # carry over the input mask + return mask - def get_losses_for(self, inputs): - """Retrieves losses relevant to a specific set of inputs. + def __call__(self, inputs, *args, **kwargs): + """Wraps `call`, applying pre- and post-processing steps. Arguments: - inputs: Input tensor or list/tuple of input tensors. + inputs: input tensor(s). + *args: additional positional arguments to be passed to `self.call`. + **kwargs: additional keyword arguments to be passed to `self.call`. Returns: - List of loss tensors of the layer that depend on `inputs`. + Output tensor(s). + + Note: + - The following optional keyword arguments are reserved for specific uses: + * `training`: Boolean scalar tensor of Python boolean indicating + whether the `call` is meant for training or inference. + * `mask`: Boolean input mask. + - If the layer's `call` method takes a `mask` argument (as some Keras + layers do), its default value will be set to the mask generated + for `inputs` by the previous layer (if `input` did come from + a layer that generated a corresponding mask, i.e. if it came from + a Keras layer with masking support. Raises: - RuntimeError: If called in Eager mode. + ValueError: if the layer's `call` method returns None (an invalid value). """ - if context.executing_eagerly(): - raise RuntimeError('Layer.get_losses_for not supported in Eager mode.') - - if inputs is None: - # Requesting unconditional losses. - return [x for x in self.losses if x._unconditional_loss] # pylint: disable=protected-access + input_list = nest.flatten(inputs) - # Requesting input-conditional losses. - inputs = nest.flatten(inputs) - # Retrieve the set of tensors in the TF graph that depend on `inputs`. - # The losses we want to return will be part of this set. - # To avoid unnecessary work, we stop the search in case all of - # `self.losses` have been retrieved. - reachable = tf_utils.get_reachable_from_inputs(inputs, self.losses) - losses = [] - for loss in self.losses: - if loss in reachable: - losses.append(loss) - return losses + if context.executing_eagerly(): + # Accept NumPy inputs by converting to Tensors when executing eagerly. + if all(isinstance(x, (np.ndarray, float, int)) for x in input_list): + inputs = nest.map_structure(ops.convert_to_tensor, inputs) + input_list = nest.flatten(inputs) - def _name_scope(self): - return self.name + # We will attempt to build a TF graph if & only if all inputs are symbolic. + # This is always the case in graph mode. It can also be the case in eager + # mode when all inputs can be traced back to `keras.Input()` (when building + # models using the functional API). + build_graph = tf_utils.are_all_symbolic_tensors(input_list) + executing_eagerly = context.executing_eagerly() - def build(self, input_shape): - """Creates the variables of the layer.""" - self.built = True + # Handle Keras mask propagation from previous layer to current layer. + previous_mask = None + if build_graph and (not hasattr(self, '_compute_previous_mask') or + self._compute_previous_mask): + previous_mask = base_layer_utils.collect_previous_mask(inputs) + if not hasattr(self, '_call_fn_args'): + self._call_fn_args = self._no_dependency( + function_utils.fn_args(self.call)) + if ('mask' in self._call_fn_args and 'mask' not in kwargs and + not generic_utils.is_all_none(previous_mask)): + # The previous layer generated a mask, and mask was not explicitly pass + # to __call__, hence we set previous_mask as the default value. + kwargs['mask'] = previous_mask - @doc_controls.for_subclass_implementers - def add_variable(self, *args, **kwargs): - """Alias for `add_weight`.""" - return self.add_weight(*args, **kwargs) + input_shapes = None - @doc_controls.for_subclass_implementers - def add_weight(self, - name, - shape, - dtype=None, - initializer=None, - regularizer=None, - trainable=None, - constraint=None, - partitioner=None, - use_resource=None, - synchronization=tf_variables.VariableSynchronization.AUTO, - aggregation=tf_variables.VariableAggregation.NONE, - **kwargs): - """Adds a new variable to the layer, or gets an existing one; returns it. - - Arguments: - name: variable name. - shape: variable shape. - dtype: The type of the variable. Defaults to `self.dtype` or `float32`. - initializer: initializer instance (callable). - regularizer: regularizer instance (callable). - trainable: whether the variable should be part of the layer's - "trainable_variables" (e.g. variables, biases) - or "non_trainable_variables" (e.g. BatchNorm mean, stddev). - Note, if the current variable scope is marked as non-trainable - then this parameter is ignored and any added variables are also - marked as non-trainable. `trainable` defaults to `True` unless - `synchronization` is set to `ON_READ`. - constraint: constraint instance (callable). - partitioner: Partitioner to be passed to the `Checkpointable` API. - use_resource: Whether to use `ResourceVariable`. - synchronization: Indicates when a distributed a variable will be - aggregated. Accepted values are constants defined in the class - `tf.VariableSynchronization`. By default the synchronization is set to - `AUTO` and the current `DistributionStrategy` chooses - when to synchronize. If `synchronization` is set to `ON_READ`, - `trainable` must not be set to `True`. - aggregation: Indicates how a distributed variable will be aggregated. - Accepted values are constants defined in the class - `tf.VariableAggregation`. - **kwargs: Additional keyword arguments. Accepted values are `getter` and - `collections`. - - Returns: - The created variable. Usually either a `Variable` or `ResourceVariable` - instance. If `partitioner` is not `None`, a `PartitionedVariable` - instance is returned. - - Raises: - RuntimeError: If called with partioned variable regularization and - eager execution is enabled. - ValueError: When giving unsupported dtype and no initializer or when - trainable has been set to True with synchronization set as `ON_READ`. - """ - # Validate optional keyword arguments. - for kwarg in kwargs: - if kwarg not in ['getter', 'collections']: - raise TypeError('Unknown keyword argument:', kwarg) - getter = kwargs.pop('getter', None) - collections = kwargs.pop('collections', None) - - if dtype is None: - dtype = self.dtype or backend.floatx() - dtype = dtypes.as_dtype(dtype) - initializer = initializers.get(initializer) - regularizer = regularizers.get(regularizer) - constraint = constraints.get(constraint) - - if synchronization == tf_variables.VariableSynchronization.ON_READ: - if trainable: - raise ValueError( - 'Synchronization value can be set to ' - 'VariableSynchronization.ON_READ only for non-trainable variables. ' - 'You have specified trainable=True and ' - 'synchronization=VariableSynchronization.ON_READ.') - else: - # Set trainable to be false when variable is to be synced on read. - trainable = False - elif trainable is None: - trainable = True - - # Initialize variable when no initializer provided - if initializer is None: - # If dtype is DT_FLOAT, provide a uniform unit scaling initializer - if dtype.is_floating: - initializer = initializers.glorot_uniform() - # If dtype is DT_INT/DT_UINT, provide a default value `zero` - # If dtype is DT_BOOL, provide a default value `FALSE` - elif dtype.is_integer or dtype.is_unsigned or dtype.is_bool: - initializer = initializers.zeros() - # NOTES:Do we need to support for handling DT_STRING and DT_COMPLEX here? - else: - raise ValueError('An initializer for variable %s of type %s is required' - ' for layer %s' % (name, dtype.base_dtype, self.name)) - - variable = self._add_variable_with_custom_getter( - name=name, - shape=shape, - # TODO(allenl): a `make_variable` equivalent should be added as a - # `Checkpointable` method. - getter=getter or make_variable, - # Manage errors in Layer rather than Checkpointable. - overwrite=True, - initializer=initializer, - dtype=dtype, - constraint=constraint, - trainable=trainable and self.trainable, - partitioner=partitioner, - use_resource=use_resource, - collections=collections, - synchronization=synchronization, - aggregation=aggregation) - backend.track_variable(variable) - - if regularizer is not None: - # TODO(fchollet): in the future, this should be handled at the - # level of variable creation, and weight regularization losses - # should be variable attributes. - self._handle_weight_regularization(name, variable, regularizer) - - if trainable: - self._trainable_weights.append(variable) - else: - self._non_trainable_weights.append(variable) - return variable - - def _handle_weight_regularization(self, name, variable, regularizer): - """Create lambdas which compute regularization losses.""" - - def _loss_for_variable(v): - """Creates a regularization loss `Tensor` for variable `v`.""" - with ops.colocate_with(v): - with ops.name_scope(name + '/Regularizer'): - regularization = regularizer(v) - return regularization - - if isinstance(variable, tf_variables.PartitionedVariable): - for v in variable: - self.add_loss(functools.partial(_loss_for_variable, v)) - else: - self.add_loss(functools.partial(_loss_for_variable, variable)) - - def _handle_activity_regularization(self, inputs, outputs): - # Apply activity regularization. - # Note that it should be applied every time the layer creates a new - # output, since it is output-specific. - if self._activity_regularizer: - output_list = nest.flatten(outputs) - with ops.name_scope('ActivityRegularizer'): - for output in output_list: - activity_loss = self._activity_regularizer(output) - batch_size = math_ops.cast( - array_ops.shape(output)[0], activity_loss.dtype) - # Make activity regularization strength batch-agnostic. - mean_activity_loss = activity_loss / batch_size - self.add_loss(mean_activity_loss, inputs=inputs) - - @doc_controls.for_subclass_implementers - def call(self, inputs, **kwargs): # pylint: disable=unused-argument - """This is where the layer's logic lives. - - Arguments: - inputs: Input tensor, or list/tuple of input tensors. - **kwargs: Additional keyword arguments. - - Returns: - A tensor or list/tuple of tensors. - """ - return inputs - - def __call__(self, inputs, *args, **kwargs): - """Wraps `call`, applying pre- and post-processing steps. - - Arguments: - inputs: input tensor(s). - *args: additional positional arguments to be passed to `self.call`. - **kwargs: additional keyword arguments to be passed to `self.call`. - - Returns: - Output tensor(s). - - Note: - - The following optional keyword arguments are reserved for specific uses: - * `training`: Boolean scalar tensor of Python boolean indicating - whether the `call` is meant for training or inference. - * `mask`: Boolean input mask. - - If the layer's `call` method takes a `mask` argument (as some Keras - layers do), its default value will be set to the mask generated - for `inputs` by the previous layer (if `input` did come from - a layer that generated a corresponding mask, i.e. if it came from - a Keras layer with masking support. - - Raises: - ValueError: if the layer's `call` method returns None (an invalid value). - """ - input_list = nest.flatten(inputs) - - if context.executing_eagerly(): - # Accept NumPy inputs by converting to Tensors when executing eagerly. - if all([isinstance(x, (np.ndarray, float, int)) for x in input_list]): - inputs = nest.map_structure(ops.convert_to_tensor, inputs) - input_list = nest.flatten(inputs) - - # We will attempt to build a TF graph if & only if all inputs are symbolic. - # This is always the case in graph mode. It can also be the case in eager - # mode when all inputs can be traced back to `keras.Input()` (when building - # models using the functional API). - build_graph = tf_utils.are_all_symbolic_tensors(input_list) - executing_eagerly = context.executing_eagerly() - - # Handle Keras mask propagation from previous layer to current layer. - previous_mask = None - if build_graph and (not hasattr(self, '_compute_previous_mask') or - self._compute_previous_mask): - previous_mask = collect_previous_mask(inputs) - if not hasattr(self, '_call_fn_args'): - self._call_fn_args = self._no_dependency( - function_utils.fn_args(self.call)) - if ('mask' in self._call_fn_args and 'mask' not in kwargs and - not generic_utils.is_all_none(previous_mask)): - # The previous layer generated a mask, and mask was not explicitly pass - # to __call__, hence we set previous_mask as the default value. - kwargs['mask'] = previous_mask - - input_shapes = None - - with ops.name_scope(self._name_scope()): - if not self.built: - # Check input assumptions set before layer building, e.g. input rank. - self._assert_input_compatibility(inputs) - if input_list and self._dtype is None: - try: - self._dtype = input_list[0].dtype.base_dtype.name - except AttributeError: - pass - - if all(hasattr(x, 'shape') for x in input_list): - input_shapes = nest.map_structure(lambda x: x.shape, inputs) - - if (not hasattr(self, '_is_graph_network') or - self.__class__.__name__ == 'Sequential' or - not hasattr(self.build, '_is_default')): - # Only if self is a layer, an instance of a sequential model, or - # the user has manually overwritten the build method do we need to - # build it. - self.build(input_shapes) - # We must set self.built since user defined build functions are not - # constrained to set self.built. - self.built = True + with ops.name_scope(self._name_scope()): + if not self.built: + # Build layer if applicable (if the `build` method has been overridden). + self._maybe_build(inputs) + # We must set self.built since user defined build functions are not + # constrained to set self.built. + self.built = True # Check input assumptions set after layer building, e.g. input shape. if build_graph: # Symbolic execution on symbolic tensors. We will attempt to build # the corresponding TF subgraph inside `backend.get_graph()` - self._assert_input_compatibility(inputs) + input_spec.assert_input_compatibility( + self.input_spec, inputs, self.name) graph = backend.get_graph() with graph.as_default(): if not executing_eagerly: @@ -772,10 +554,10 @@ class Layer(checkpointable.CheckpointableBase): # Any issue during graph-building means we will later run the # model in eager mode, whether the issue was related to # graph mode or not. This provides a nice debugging experience. - self._is_static_graph_friendly = False + self._call_is_graph_friendly = False # We will use static shape inference to return symbolic tensors # matching the specifications of the layer outputs. - # Since we have set `self._is_static_graph_friendly = False`, + # Since we have set `self._call_is_graph_friendly = False`, # we will never attempt to run the underlying TF graph (which is # disconnected). # TODO(fchollet): consider py_func as an alternative, which @@ -792,7 +574,7 @@ class Layer(checkpointable.CheckpointableBase): '(layer: ' + self.name + ').') self._handle_activity_regularization(inputs, outputs) self._set_mask_metadata(inputs, outputs, previous_mask) - if have_all_keras_metadata(inputs): + if base_layer_utils.have_all_keras_metadata(inputs): inputs, outputs = self._set_connectivity_metadata_( inputs, outputs, args, kwargs) if hasattr(self, '_set_inputs') and not self.inputs: @@ -815,313 +597,299 @@ class Layer(checkpointable.CheckpointableBase): del self._initial_weights return outputs - def apply(self, inputs, *args, **kwargs): - """Apply the layer on a input. + @property + def dtype(self): + return self._dtype - This simply wraps `self.__call__`. + @property + def name(self): + return self._name - Arguments: - inputs: Input tensor(s). - *args: additional positional arguments to be passed to `self.call`. - **kwargs: additional keyword arguments to be passed to `self.call`. + @property + def activity_regularizer(self): + """Optional regularizer function for the output of this layer.""" + return self._activity_regularizer + + @activity_regularizer.setter + def activity_regularizer(self, regularizer): + """Optional regularizer function for the output of this layer.""" + self._activity_regularizer = self._no_dependency(regularizer) + + @property + def trainable_weights(self): + return self._trainable_weights if self.trainable else [] + + @property + def non_trainable_weights(self): + if self.trainable: + return self._non_trainable_weights + else: + return self._trainable_weights + self._non_trainable_weights + + @property + def weights(self): + """Returns the list of all layer variables/weights. Returns: - Output tensor(s). + A list of variables. """ - return self.__call__(inputs, *args, **kwargs) + return self.trainable_weights + self.non_trainable_weights - def _set_mask_metadata(self, inputs, outputs, previous_mask): - # In some cases the mask of the outputs has already been computed by - # inner layers and does not need to be recomputed by this layer. - mask_already_computed = all( - hasattr(x, '_keras_mask') for x in generic_utils.to_list(outputs)) - if hasattr(self, 'compute_mask') and not mask_already_computed: - output_mask = self.compute_mask(inputs, previous_mask) - else: - output_mask = None - if isinstance(outputs, (list, tuple)): - if output_mask is None: - output_mask = [None for _ in range(len(outputs))] - for x, m in zip(outputs, output_mask): - try: - x._keras_mask = m # pylint: disable=protected-access - except AttributeError: - pass # C type such as dict. Masking not supported in this case. - else: - try: - outputs._keras_mask = output_mask # pylint: disable=protected-access - except AttributeError: - pass # C type such as dict. Masking not supported in this case. + @property + def updates(self): + if not self.trainable and not self.stateful: + return [] + return self._updates - def _set_connectivity_metadata_(self, inputs, outputs, args, kwargs): - call_convention = getattr(self, '_call_convention', - CallConvention.EXPLICIT_INPUTS_ARGUMENT) - if args: - if call_convention == CallConvention.EXPLICIT_INPUTS_ARGUMENT: - raise TypeError( - 'This layer ("{}") takes an `inputs` argument in `call()`, ' - 'and only the `inputs` argument may be specified as a positional ' - 'argument. Pass everything else as a keyword argument ' - '(those arguments will not be tracked ' - 'as inputs to the layer).'.format(self.name)) - elif call_convention == CallConvention.SINGLE_POSITIONAL_ARGUMENT: - raise TypeError( - 'This layer ("{}") takes a single positional argument in `call()`,' - ' which is by convention the `inputs` argument, ' - 'and only this argument may be specified as a positional argument. ' - 'Pass everything else as a keyword argument ' - '(those arguments will not be tracked ' - 'as inputs to the layer).'.format(self.name)) + @property + def losses(self): + """Losses which are associated with this `Layer`. - # If the layer returns tensors from its inputs, unmodified, - # we copy them to avoid loss of tensor metadata. - output_ls = nest.flatten(outputs) - output_ls_copy = [] - for x in output_ls: - if x in nest.flatten(inputs): - with ops.name_scope(self.name): - x = array_ops.identity(x) - output_ls_copy.append(x) - if len(output_ls_copy) == 1: - outputs = output_ls_copy[0] + Variable regularization tensors are created when this property is accessed, + so it is eager safe: accessing `losses` under a `tf.GradientTape` will + propagate gradients back to the corresponding variables. + + Returns: + A list of tensors. + """ + collected_losses = [] + if context.executing_eagerly(): + collected_losses.extend(self._eager_losses) else: - outputs = output_ls_copy + collected_losses.extend(self._losses) + for regularizer in self._callable_losses: + loss_tensor = regularizer() + if loss_tensor is not None: + collected_losses.append(loss_tensor) + return collected_losses - inputs, kwargs = self._inputs_from_call_args( - call_args=(inputs,) + args, call_kwargs=kwargs) - # Add an inbound node to the layer, so it can keep track of this call. - # This updates the layer history of the output tensor(s). - kwargs.pop('mask', None) # `mask` should not be serialized. - self._add_inbound_node( - input_tensors=inputs, output_tensors=outputs, arguments=kwargs) - return inputs, outputs + @doc_controls.for_subclass_implementers + def add_loss(self, losses, inputs=None): + """Add loss tensor(s), potentially dependent on layer inputs. - def _inputs_from_call_args(self, call_args, call_kwargs): - """Get Layer inputs from __call__ *args and **kwargs. + Some losses (for instance, activity regularization losses) may be dependent + on the inputs passed when calling a layer. Hence, when reusing the same + layer on different inputs `a` and `b`, some entries in `layer.losses` may + be dependent on `a` and some on `b`. This method automatically keeps track + of dependencies. - Args: - call_args: The positional arguments passed to __call__. - call_kwargs: The keyword argument dict passed to __call__. + The `get_losses_for` method allows to retrieve the losses relevant to a + specific set of inputs. - Returns: - A tuple of (inputs, non_input_kwargs). These may be the same objects as - were passed in (call_args and call_kwargs). + Note that `add_loss` is not supported when executing eagerly. Instead, + variable regularizers may be added through `add_variable`. Activity + regularization is not supported directly (but such losses may be returned + from `Layer.call()`). + + Arguments: + losses: Loss tensor, or list/tuple of tensors. Rather than tensors, losses + may also be zero-argument callables which create a loss tensor. + inputs: Ignored when executing eagerly. If anything other than None is + passed, it signals the losses are conditional on some of the layer's + inputs, and thus they should only be run where these inputs are + available. This is the case for activity regularization losses, for + instance. If `None` is passed, the losses are assumed + to be unconditional, and will apply across all dataflows of the layer + (e.g. weight regularization losses). """ - call_convention = getattr(self, '_call_convention', - CallConvention.EXPLICIT_INPUTS_ARGUMENT) - if (call_convention in ( - CallConvention.EXPLICIT_INPUTS_ARGUMENT, - CallConvention.SINGLE_POSITIONAL_ARGUMENT)): - assert len(call_args) == 1 # TypeError raised earlier in __call__. - return call_args[0], call_kwargs - else: - call_arg_spec = tf_inspect.getfullargspec(self.call) - # There is no explicit "inputs" argument expected or provided to - # call(). Arguments which have default values are considered non-inputs, - # and arguments without are considered inputs. - if call_arg_spec.defaults: - if call_arg_spec.varargs is not None: - raise TypeError( - 'Layers may not accept both positional arguments and ' - 'arguments with default values (unable to determine which ' - 'are inputs to the layer). ' - 'Issue occurred with layer "%s"' % (self.name)) - keyword_arg_names = set( - call_arg_spec.args[-len(call_arg_spec.defaults):]) + losses = generic_utils.to_list(losses) + + def _tag_unconditional(loss): + if callable(loss): + loss = loss() + if loss is None: + return None # Will be filtered out when computing the .losses property + if not tensor_util.is_tensor(loss): + loss = ops.convert_to_tensor(loss, dtype=backend.floatx()) + loss._unconditional_loss = (inputs is None) # pylint: disable=protected-access + return loss + + for loss in losses: + if callable(loss): + self._callable_losses.append( + functools.partial(_tag_unconditional, loss)) else: - keyword_arg_names = set() - # Training is never an input argument name, to allow signatures like - # call(x, training). - keyword_arg_names.add('training') - _, unwrapped_call = tf_decorator.unwrap(self.call) - bound_args = inspect.getcallargs( - unwrapped_call, *call_args, **call_kwargs) - if call_arg_spec.varkw is not None: - var_kwargs = bound_args.pop(call_arg_spec.varkw) - bound_args.update(var_kwargs) - keyword_arg_names = keyword_arg_names.union(var_kwargs.keys()) - all_args = call_arg_spec.args - if all_args and bound_args[all_args[0]] is self: - # Ignore the 'self' argument of methods - bound_args.pop(call_arg_spec.args[0]) - all_args = all_args[1:] - non_input_arg_values = {} - input_arg_values = [] - remaining_args_are_keyword = False - for argument_name in all_args: - if argument_name in keyword_arg_names: - remaining_args_are_keyword = True - else: - if remaining_args_are_keyword: - raise TypeError( - 'Found a positional argument in a layer call after a non-input ' - 'argument. All arguments after "training" must be keyword ' - 'arguments, and are not tracked as inputs to the layer. ' - 'Issue occurred with layer "%s"' % (self.name)) - if remaining_args_are_keyword: - non_input_arg_values[argument_name] = bound_args[argument_name] + if context.executing_eagerly(): + self._eager_losses.append(_tag_unconditional(loss)) else: - input_arg_values.append(bound_args[argument_name]) - if call_arg_spec.varargs is not None: - input_arg_values.extend(bound_args[call_arg_spec.varargs]) - return input_arg_values, non_input_arg_values + self._losses.append(_tag_unconditional(loss)) - def compute_output_shape(self, input_shape): - """Computes the output shape of the layer. + @doc_controls.for_subclass_implementers + def add_metric(self, value, aggregation=None, name=None): + """Adds metric tensor to the layer. - Assumes that the layer will be built - to match that input shape provided. + Args: + value: Metric tensor. + aggregation: Sample-wise metric reduction function. If `aggregation=None`, + it indicates that the metric tensor provided has been aggregated + already. eg, `model.add_metric(BinaryAccuracy(name='acc')(y_true, + y_pred))`. If aggregation='mean', the given metric tensor will be + sample-wise reduced using `mean` function. eg, `model.add_metric( + tf.reduce_mean(outputs), name='output_mean', aggregation='mean')`. + name: String metric name. - Arguments: - input_shape: Shape tuple (tuple of integers) - or list of shape tuples (one per output tensor of the layer). - Shape tuples can include None for free dimensions, - instead of an integer. + Raises: + ValueError: If `aggregation` is anything other than None or `mean`. + """ + if aggregation is not None and aggregation != 'mean': + raise ValueError( + 'We currently support only `mean` sample-wise metric aggregation. ' + 'You provided aggregation=`%s`' % aggregation) - Returns: - An input shape tuple. + if tf_utils.is_symbolic_tensor(value): + self._symbolic_add_metric(value, aggregation, name) + else: + self._eager_add_metric(value, aggregation, name) + + @doc_controls.for_subclass_implementers + def add_update(self, updates, inputs=None): + """Add update op(s), potentially dependent on layer inputs. + + Weight updates (for instance, the updates of the moving mean and variance + in a BatchNormalization layer) may be dependent on the inputs passed + when calling a layer. Hence, when reusing the same layer on + different inputs `a` and `b`, some entries in `layer.updates` may be + dependent on `a` and some on `b`. This method automatically keeps track + of dependencies. + + The `get_updates_for` method allows to retrieve the updates relevant to a + specific set of inputs. + + This call is ignored when eager execution is enabled (in that case, variable + updates are run on the fly and thus do not need to be tracked for later + execution). + + Arguments: + updates: Update op, or list/tuple of update ops. + inputs: If anything other than None is passed, it signals the updates + are conditional on some of the layer's inputs, + and thus they should only be run where these inputs are available. + This is the case for BatchNormalization updates, for instance. + If None, the updates will be taken into account unconditionally, + and you are responsible for making sure that any dependency they might + have is available at runtime. + A step counter might fall into this category. """ if context.executing_eagerly(): - # In this case we build the model first in order to do shape inference. - # This is acceptable because the framework only calls - # `compute_output_shape` on shape values that the layer would later be - # built for. It would however cause issues in case a user attempts to - # use `compute_output_shape` manually (these users will have to - # implement `compute_output_shape` themselves). - self.build(input_shape) - - with context.graph_mode(): - graph = func_graph.FuncGraph('graph') - with graph.as_default(): - if isinstance(input_shape, list): - inputs = [generate_placeholders_from_shape(shape) - for shape in input_shape] - else: - inputs = generate_placeholders_from_shape(input_shape) + return # Updates already applied when in eager mode. - try: - if self._expects_training_arg: - outputs = self(inputs, training=False) - else: - outputs = self(inputs) - except TypeError: - raise NotImplementedError('We could not automatically infer ' - 'the static shape of the layer\'s output.' - ' Please implement the ' - '`compute_output_shape` method on your ' - 'layer (%s).' % self.__class__.__name__) - if isinstance(outputs, list): - return [output.shape for output in outputs] + def process_update(x): + if isinstance(x, ops.Operation): + return x + elif hasattr(x, 'op'): + return x.op else: - return outputs.shape - raise NotImplementedError + return ops.convert_to_tensor(x) - def compute_mask(self, inputs, mask=None): # pylint: disable=unused-argument - """Computes an output mask tensor. + updates = generic_utils.to_list(updates) + updates = [process_update(x) for x in updates] + self._updates += updates + if inputs is None: + for u in updates: + u._unconditional_update = True # pylint: disable=protected-access + else: + for u in updates: + u._unconditional_update = False # pylint: disable=protected-access + + def set_weights(self, weights): + """Sets the weights of the layer, from Numpy arrays. Arguments: - inputs: Tensor or list of tensors. - mask: Tensor or list of tensors. + weights: a list of Numpy arrays. The number + of arrays and their shape must match + number of the dimensions of the weights + of the layer (i.e. it should match the + output of `get_weights`). + + Raises: + ValueError: If the provided weights list does not match the + layer's specifications. + """ + params = self.weights + if len(params) != len(weights): + raise ValueError('You called `set_weights(weights)` on layer "' + + self.name + '" with a weight list of length ' + + str(len(weights)) + ', but the layer was expecting ' + + str(len(params)) + ' weights. Provided weights: ' + + str(weights)[:50] + '...') + if not params: + return + weight_value_tuples = [] + param_values = backend.batch_get_value(params) + for pv, p, w in zip(param_values, params, weights): + if pv.shape != w.shape: + raise ValueError('Layer weight shape ' + str(pv.shape) + + ' not compatible with ' + 'provided weight shape ' + str(w.shape)) + weight_value_tuples.append((p, w)) + backend.batch_set_value(weight_value_tuples) + + def get_weights(self): + """Returns the current weights of the layer. Returns: - None or a tensor (or list of tensors, - one per output tensor of the layer). + Weights values as a list of numpy arrays. """ - if not self.supports_masking: - if mask is not None: - if isinstance(mask, list): - if any(m is not None for m in mask): - raise TypeError('Layer ' + self.name + ' does not support masking, ' - 'but was passed an input_mask: ' + str(mask)) - else: - raise TypeError('Layer ' + self.name + ' does not support masking, ' - 'but was passed an input_mask: ' + str(mask)) - # masking not explicitly supported: return None as mask - return None - # if masking is explicitly supported, by default - # carry over the input mask - return mask + params = self.weights + return backend.batch_get_value(params) - def _add_inbound_node(self, - input_tensors, - output_tensors, - arguments=None): - """Internal method to create an inbound node for the layer. + def get_updates_for(self, inputs): + """Retrieves updates relevant to a specific set of inputs. Arguments: - input_tensors: list of input tensors. - output_tensors: list of output tensors. - arguments: dictionary of keyword arguments that were passed to the - `call` method of the layer at the call that created the node. - """ - input_tensors = nest.flatten(input_tensors) - output_tensors = nest.flatten(output_tensors) + inputs: Input tensor or list/tuple of input tensors. - # Collect input tensor(s) coordinates. - inbound_layers = [] - node_indices = [] - tensor_indices = [] - for x in input_tensors: - assert hasattr(x, '_keras_history') - inbound_layer, node_index, tensor_index = x._keras_history # pylint: disable=protected-access - inbound_layers.append(inbound_layer) - node_indices.append(node_index) - tensor_indices.append(tensor_index) + Returns: + List of update ops of the layer that depend on `inputs`. - # Create node, add it to inbound nodes. - Node( - self, - inbound_layers=inbound_layers, - node_indices=node_indices, - tensor_indices=tensor_indices, - input_tensors=input_tensors, - output_tensors=output_tensors, - arguments=arguments) + Raises: + RuntimeError: If called in Eager mode. + """ + # Updates disabled if layer is not trainable and not explicitly stateful. + if not self.trainable and not self.stateful: + return [] - # Update tensor history metadata. - for i in range(len(output_tensors)): - # The metadata attribute consists of 1) a layer instance - # 2) a node index for the layer, 3) a tensor index for the node. - # The allows layer reuse (multiple nodes per layer) and multi-output - # or multi-input layers (e.g. a layer can return multiple tensors, - # and each can be sent to a different layer). - output_tensors[i]._keras_history = (self, len(self._inbound_nodes) - 1, i) # pylint: disable=protected-access + if inputs is None: + # Requesting unconditional updates. + return [x for x in self.updates if x._unconditional_update] # pylint: disable=protected-access - def _get_node_attribute_at_index(self, node_index, attr, attr_name): - """Private utility to retrieves an attribute (e.g. inputs) from a node. + # Requesting input-conditional updates. + inputs = nest.flatten(inputs) + reachable = tf_utils.get_reachable_from_inputs(inputs, self.updates) + updates = [] + for update in self.updates: + if update in reachable: + updates.append(update) + return updates - This is used to implement the methods: - - get_input_shape_at - - get_output_shape_at - - get_input_at - etc... + def get_losses_for(self, inputs): + """Retrieves losses relevant to a specific set of inputs. Arguments: - node_index: Integer index of the node from which - to retrieve the attribute. - attr: Exact node attribute name. - attr_name: Human-readable attribute name, for error messages. + inputs: Input tensor or list/tuple of input tensors. Returns: - The layer's attribute `attr` at the node of index `node_index`. + List of loss tensors of the layer that depend on `inputs`. Raises: - RuntimeError: If the layer has no inbound nodes, or if called in Eager - mode. - ValueError: If the index provided does not match any node. + RuntimeError: If called in Eager mode. """ - if not self._inbound_nodes: - raise RuntimeError('The layer has never been called ' - 'and thus has no defined ' + attr_name + '.') - if not len(self._inbound_nodes) > node_index: - raise ValueError('Asked to get ' + attr_name + ' at node ' + - str(node_index) + ', but the layer has only ' + - str(len(self._inbound_nodes)) + ' inbound nodes.') - values = getattr(self._inbound_nodes[node_index], attr) - if len(values) == 1: - return values[0] - else: - return values + if inputs is None: + # Requesting unconditional losses. + return [x for x in self.losses if x._unconditional_loss] # pylint: disable=protected-access + + # Requesting input-conditional losses. + inputs = nest.flatten(inputs) + # Retrieve the set of tensors in the TF graph that depend on `inputs`. + # The losses we want to return will be part of this set. + # To avoid unnecessary work, we stop the search in case all of + # `self.losses` have been retrieved. + reachable = tf_utils.get_reachable_from_inputs(inputs, self.losses) + losses = [] + for loss in self.losses: + if loss in reachable: + losses.append(loss) + return losses def get_input_mask_at(self, node_index): """Retrieves the input mask tensor(s) of a layer at a given node. @@ -1376,8 +1144,7 @@ class Layer(checkpointable.CheckpointableBase): ', but the layer isn\'t built. ' 'You can build it manually via: `' + self.name + '.build(batch_input_shape)`.') - weight_shapes = [w.shape.as_list() for w in self.weights] - return int(sum([np.prod(w) for w in weight_shapes])) + return int(sum(np.prod(w.shape.as_list()) for w in self.weights)) @property def output_shape(self): @@ -1429,231 +1196,401 @@ class Layer(checkpointable.CheckpointableBase): """Deprecated, do NOT use! Only for compatibility with external Keras.""" return self._outbound_nodes - def _assert_input_compatibility(self, inputs): - """Checks compatibility between the layer and provided inputs. + ############################################################################## + # Methods & attributes below are public aliases of other methods. # + ############################################################################## + + def apply(self, inputs, *args, **kwargs): + """Apply the layer on a input. + + This is an alias of `self.__call__`. + + Arguments: + inputs: Input tensor(s). + *args: additional positional arguments to be passed to `self.call`. + **kwargs: additional keyword arguments to be passed to `self.call`. + + Returns: + Output tensor(s). + """ + return self.__call__(inputs, *args, **kwargs) + + @doc_controls.for_subclass_implementers + def add_variable(self, *args, **kwargs): + """Alias for `add_weight`.""" + return self.add_weight(*args, **kwargs) + + @property + def variables(self): + """Returns the list of all layer variables/weights. + + Alias of `self.weights`. + + Returns: + A list of variables. + """ + return self.weights + + @property + def trainable_variables(self): + return self.trainable_weights + + @property + def non_trainable_variables(self): + return self.non_trainable_weights + + ############################################################################## + # Methods & attributes below are all private and only used by the framework. # + ############################################################################## + + def _name_scope(self): + return self.name + + def _init_set_name(self, name, zero_based=True): + if not name: + self._name = base_layer_utils.unique_layer_name( + generic_utils.to_snake_case(self.__class__.__name__), + zero_based=zero_based) + else: + self._name = name + + def _get_existing_metric(self, name=None): + match = [m for m in self._metrics if m.name == name] + if not match: + return + if len(match) > 1: + raise ValueError( + 'Please provide different names for the metrics you have added. ' + 'We found {} metrics with the name: "{}"'.format(len(match), name)) + return match[0] + + def _eager_add_metric(self, value, aggregation=None, name=None): + # If the given metric is available in `metrics` list we just update state + # on it, otherwise we create a new metric instance and + # add it to the `metrics` list. + match = self._get_existing_metric(name) + if match: + match(value) # Update the metric state. + return + else: + if aggregation is None: + raise ValueError('We do not support adding an aggregated metric tensor ' + 'in `call` in eager execution.') + metric_obj, _ = base_layer_utils.create_mean_metric(value, name) + self._metrics.append(metric_obj) + + def _symbolic_add_metric(self, value, aggregation=None, name=None): + if aggregation is None: + # Iterate over the metrics and check if the given metric exists already. + # This can happen when a metric instance is created in subclassed model + # layer `__init__` and we have tracked that instance already in + # model.__setattr__. + match = self._get_existing_metric(name) + if match: + result_tensor = value + if match.name not in self._metrics_tensors: + self._metrics_tensors[match.name] = result_tensor + return + else: + raise ValueError( + 'We currently do not support reusing a metric instance.') + else: + # We track the instance using the metadata on the result tensor. + result_tensor = value + metric_obj = result_tensor._metric_obj + else: + # If a non-aggregated tensor is given as input (ie. `aggregation` is + # explicitly set to `mean`), we wrap the tensor in `Mean` metric. + metric_obj, result_tensor = base_layer_utils.create_mean_metric( + value, name) + self._metrics.append(metric_obj) + self._metrics_tensors[metric_obj.name] = result_tensor + + def _handle_weight_regularization(self, name, variable, regularizer): + """Create lambdas which compute regularization losses.""" + + def _loss_for_variable(v): + """Creates a regularization loss `Tensor` for variable `v`.""" + with ops.colocate_with(v): + with ops.name_scope(name + '/Regularizer'): + regularization = regularizer(v) + return regularization + + if isinstance(variable, tf_variables.PartitionedVariable): + for v in variable: + self.add_loss(functools.partial(_loss_for_variable, v)) + else: + self.add_loss(functools.partial(_loss_for_variable, variable)) + + def _handle_activity_regularization(self, inputs, outputs): + # Apply activity regularization. + # Note that it should be applied every time the layer creates a new + # output, since it is output-specific. + if self._activity_regularizer: + output_list = nest.flatten(outputs) + with ops.name_scope('ActivityRegularizer'): + for output in output_list: + activity_loss = self._activity_regularizer(output) + batch_size = math_ops.cast( + array_ops.shape(output)[0], activity_loss.dtype) + # Make activity regularization strength batch-agnostic. + mean_activity_loss = activity_loss / batch_size + self.add_loss(mean_activity_loss, inputs=inputs) + + def _set_mask_metadata(self, inputs, outputs, previous_mask): + # In some cases the mask of the outputs has already been computed by + # inner layers and does not need to be recomputed by this layer. + mask_already_computed = all( + hasattr(x, '_keras_mask') for x in generic_utils.to_list(outputs)) + if hasattr(self, 'compute_mask') and not mask_already_computed: + output_mask = self.compute_mask(inputs, previous_mask) + else: + output_mask = None + if isinstance(outputs, (list, tuple)): + if output_mask is None: + output_mask = [None for _ in range(len(outputs))] + for x, m in zip(outputs, output_mask): + try: + x._keras_mask = m # pylint: disable=protected-access + except AttributeError: + pass # C type such as dict. Masking not supported in this case. + else: + try: + outputs._keras_mask = output_mask # pylint: disable=protected-access + except AttributeError: + pass # C type such as dict. Masking not supported in this case. + + def _set_connectivity_metadata_(self, inputs, outputs, args, kwargs): + call_convention = getattr( + self, '_call_convention', + base_layer_utils.CallConvention.EXPLICIT_INPUTS_ARGUMENT) + if args: + if call_convention == (base_layer_utils + .CallConvention.EXPLICIT_INPUTS_ARGUMENT): + raise TypeError( + 'This layer ("{}") takes an `inputs` argument in `call()`, ' + 'and only the `inputs` argument may be specified as a positional ' + 'argument. Pass everything else as a keyword argument ' + '(those arguments will not be tracked ' + 'as inputs to the layer).'.format(self.name)) + elif call_convention == (base_layer_utils + .CallConvention.SINGLE_POSITIONAL_ARGUMENT): + raise TypeError( + 'This layer ("{}") takes a single positional argument in `call()`,' + ' which is by convention the `inputs` argument, ' + 'and only this argument may be specified as a positional argument. ' + 'Pass everything else as a keyword argument ' + '(those arguments will not be tracked ' + 'as inputs to the layer).'.format(self.name)) + + # If the layer returns tensors from its inputs, unmodified, + # we copy them to avoid loss of tensor metadata. + output_ls = nest.flatten(outputs) + output_ls_copy = [] + for x in output_ls: + if x in nest.flatten(inputs): + with ops.name_scope(self.name): + x = array_ops.identity(x) + output_ls_copy.append(x) + if len(output_ls_copy) == 1: + outputs = output_ls_copy[0] + else: + outputs = output_ls_copy + + inputs, kwargs = self._inputs_from_call_args( + call_args=(inputs,) + args, call_kwargs=kwargs) + # Add an inbound node to the layer, so it can keep track of this call. + # This updates the layer history of the output tensor(s). + kwargs.pop('mask', None) # `mask` should not be serialized. + self._add_inbound_node( + input_tensors=inputs, output_tensors=outputs, arguments=kwargs) + return inputs, outputs - This checks that the tensor(s) `inputs` verify the input assumptions - of the layer (if any). If not, a clear and actional exception gets raised. + def _inputs_from_call_args(self, call_args, call_kwargs): + """Get Layer inputs from __call__ *args and **kwargs. - Arguments: - inputs: input tensor or list of input tensors. + Args: + call_args: The positional arguments passed to __call__. + call_kwargs: The keyword argument dict passed to __call__. - Raises: - ValueError: in case of mismatch between - the provided inputs and the expectations of the layer. + Returns: + A tuple of (inputs, non_input_kwargs). These may be the same objects as + were passed in (call_args and call_kwargs). """ - if not self.input_spec: - return - if not isinstance(self.input_spec, (list, tuple)): - input_spec = nest.flatten(self.input_spec) + call_convention = getattr( + self, '_call_convention', + base_layer_utils.CallConvention.EXPLICIT_INPUTS_ARGUMENT) + if (call_convention in ( + base_layer_utils.CallConvention.EXPLICIT_INPUTS_ARGUMENT, + base_layer_utils.CallConvention.SINGLE_POSITIONAL_ARGUMENT)): + assert len(call_args) == 1 # TypeError raised earlier in __call__. + return call_args[0], call_kwargs else: - input_spec = self.input_spec - inputs = nest.flatten(inputs) - if len(inputs) != len(input_spec): - raise ValueError('Layer ' + self.name + ' expects ' + - str(len(input_spec)) + ' inputs, ' - 'but it received ' + str(len(inputs)) + - ' input tensors. Inputs received: ' + str(inputs)) - for input_index, (x, spec) in enumerate(zip(inputs, input_spec)): - if spec is None: - continue - - if (spec.ndim is not None or - spec.min_ndim is not None or - spec.max_ndim is not None): - if x.shape.ndims is None: - raise ValueError('Input ' + str(input_index) + ' of layer ' + - self.name + ' is incompatible with the layer: ' - 'its rank is undefined, but the layer requires a ' - 'defined rank.') - - # Check ndim. - if spec.ndim is not None: - ndim = x.shape.ndims - if ndim != spec.ndim: - raise ValueError('Input ' + str(input_index) + ' of layer ' + - self.name + ' is incompatible with the layer: ' - 'expected ndim=' + str(spec.ndim) + ', found ndim=' + - str(ndim) + '. Full shape received: ' + - str(x.shape.as_list())) - if spec.max_ndim is not None: - ndim = x.shape.ndims - if ndim is not None and ndim > spec.max_ndim: - raise ValueError('Input ' + str(input_index) + ' of layer ' + - self.name + ' is incompatible with the layer: ' - 'expected max_ndim=' + str(spec.max_ndim) + - ', found ndim=' + str(ndim)) - if spec.min_ndim is not None: - ndim = x.shape.ndims - if ndim is not None and ndim < spec.min_ndim: - raise ValueError('Input ' + str(input_index) + ' of layer ' + - self.name + ' is incompatible with the layer: ' - ': expected min_ndim=' + str(spec.min_ndim) + - ', found ndim=' + str(ndim) + - '. Full shape received: ' + - str(x.shape.as_list())) - # Check dtype. - if spec.dtype is not None: - if x.dtype != spec.dtype: - raise ValueError('Input ' + str(input_index) + ' of layer ' + - self.name + ' is incompatible with the layer: ' - 'expected dtype=' + str(spec.dtype) + - ', found dtype=' + str(x.dtype)) - # Check specific shape axes. - if spec.axes: - shape = x.shape.as_list() - if shape is not None: - for axis, value in spec.axes.items(): - if hasattr(value, 'value'): - value = value.value - if value is not None and shape[int(axis)] not in {value, None}: - raise ValueError( - 'Input ' + str(input_index) + ' of layer ' + self.name + ' is' - ' incompatible with the layer: expected axis ' + str(axis) + - ' of input shape to have value ' + str(value) + - ' but received input with shape ' + str(shape)) - # Check shape. - if spec.shape is not None: - shape = x.shape.as_list() - if shape is not None: - for spec_dim, dim in zip(spec.shape, shape): - if spec_dim is not None and dim is not None: - if spec_dim != dim: - raise ValueError('Input ' + str(input_index) + - ' is incompatible with layer ' + self.name + - ': expected shape=' + str(spec.shape) + - ', found shape=' + str(shape)) + call_arg_spec = tf_inspect.getfullargspec(self.call) + # There is no explicit "inputs" argument expected or provided to + # call(). Arguments which have default values are considered non-inputs, + # and arguments without are considered inputs. + if call_arg_spec.defaults: + if call_arg_spec.varargs is not None: + raise TypeError( + 'Layers may not accept both positional arguments and ' + 'arguments with default values (unable to determine which ' + 'are inputs to the layer). ' + 'Issue occurred with layer "%s"' % (self.name)) + keyword_arg_names = set( + call_arg_spec.args[-len(call_arg_spec.defaults):]) + else: + keyword_arg_names = set() + # Training is never an input argument name, to allow signatures like + # call(x, training). + keyword_arg_names.add('training') + _, unwrapped_call = tf_decorator.unwrap(self.call) + bound_args = inspect.getcallargs( + unwrapped_call, *call_args, **call_kwargs) + if call_arg_spec.varkw is not None: + var_kwargs = bound_args.pop(call_arg_spec.varkw) + bound_args.update(var_kwargs) + keyword_arg_names = keyword_arg_names.union(var_kwargs.keys()) + all_args = call_arg_spec.args + if all_args and bound_args[all_args[0]] is self: + # Ignore the 'self' argument of methods + bound_args.pop(call_arg_spec.args[0]) + all_args = all_args[1:] + non_input_arg_values = {} + input_arg_values = [] + remaining_args_are_keyword = False + for argument_name in all_args: + if argument_name in keyword_arg_names: + remaining_args_are_keyword = True + else: + if remaining_args_are_keyword: + raise TypeError( + 'Found a positional argument in a layer call after a non-input ' + 'argument. All arguments after "training" must be keyword ' + 'arguments, and are not tracked as inputs to the layer. ' + 'Issue occurred with layer "%s"' % (self.name)) + if remaining_args_are_keyword: + non_input_arg_values[argument_name] = bound_args[argument_name] + else: + input_arg_values.append(bound_args[argument_name]) + if call_arg_spec.varargs is not None: + input_arg_values.extend(bound_args[call_arg_spec.varargs]) + return input_arg_values, non_input_arg_values - def set_weights(self, weights): - """Sets the weights of the layer, from Numpy arrays. + def _add_inbound_node(self, + input_tensors, + output_tensors, + arguments=None): + """Internal method to create an inbound node for the layer. Arguments: - weights: a list of Numpy arrays. The number - of arrays and their shape must match - number of the dimensions of the weights - of the layer (i.e. it should match the - output of `get_weights`). - - Raises: - ValueError: If the provided weights list does not match the - layer's specifications. - """ - params = self.weights - if len(params) != len(weights): - raise ValueError('You called `set_weights(weights)` on layer "' + - self.name + '" with a weight list of length ' + - str(len(weights)) + ', but the layer was expecting ' + - str(len(params)) + ' weights. Provided weights: ' + - str(weights)[:50] + '...') - if not params: - return - weight_value_tuples = [] - param_values = backend.batch_get_value(params) - for pv, p, w in zip(param_values, params, weights): - if pv.shape != w.shape: - raise ValueError('Layer weight shape ' + str(pv.shape) + - ' not compatible with ' - 'provided weight shape ' + str(w.shape)) - weight_value_tuples.append((p, w)) - backend.batch_set_value(weight_value_tuples) - - def get_weights(self): - """Returns the current weights of the layer. - - Returns: - Weights values as a list of numpy arrays. + input_tensors: list of input tensors. + output_tensors: list of output tensors. + arguments: dictionary of keyword arguments that were passed to the + `call` method of the layer at the call that created the node. """ - params = self.weights - return backend.batch_get_value(params) - - def get_config(self): - """Returns the config of the layer. + input_tensors = nest.flatten(input_tensors) + output_tensors = nest.flatten(output_tensors) - A layer config is a Python dictionary (serializable) - containing the configuration of a layer. - The same layer can be reinstantiated later - (without its trained weights) from this configuration. + # Collect input tensor(s) coordinates. + inbound_layers = [] + node_indices = [] + tensor_indices = [] + for x in input_tensors: + assert hasattr(x, '_keras_history') + inbound_layer, node_index, tensor_index = x._keras_history # pylint: disable=protected-access + inbound_layers.append(inbound_layer) + node_indices.append(node_index) + tensor_indices.append(tensor_index) - The config of a layer does not include connectivity - information, nor the layer class name. These are handled - by `Network` (one layer of abstraction above). + # Create node, add it to inbound nodes. + Node( + self, + inbound_layers=inbound_layers, + node_indices=node_indices, + tensor_indices=tensor_indices, + input_tensors=input_tensors, + output_tensors=output_tensors, + arguments=arguments) - Returns: - Python dictionary. - """ - config = {'name': self.name, 'trainable': self.trainable} - if hasattr(self, '_batch_input_shape'): - config['batch_input_shape'] = self._batch_input_shape - if hasattr(self, 'dtype'): - config['dtype'] = self.dtype - return config + # Update tensor history metadata. + for i in range(len(output_tensors)): + # The metadata attribute consists of 1) a layer instance + # 2) a node index for the layer, 3) a tensor index for the node. + # The allows layer reuse (multiple nodes per layer) and multi-output + # or multi-input layers (e.g. a layer can return multiple tensors, + # and each can be sent to a different layer). + output_tensors[i]._keras_history = (self, len(self._inbound_nodes) - 1, i) # pylint: disable=protected-access - @classmethod - def from_config(cls, config): - """Creates a layer from its config. + def _get_node_attribute_at_index(self, node_index, attr, attr_name): + """Private utility to retrieves an attribute (e.g. inputs) from a node. - This method is the reverse of `get_config`, - capable of instantiating the same layer from the config - dictionary. It does not handle layer connectivity - (handled by Network), nor weights (handled by `set_weights`). + This is used to implement the methods: + - get_input_shape_at + - get_output_shape_at + - get_input_at + etc... Arguments: - config: A Python dictionary, typically the - output of get_config. + node_index: Integer index of the node from which + to retrieve the attribute. + attr: Exact node attribute name. + attr_name: Human-readable attribute name, for error messages. Returns: - A layer instance. - """ - return cls(**config) - - -@tf_export( - 'keras.layers.InputSpec', v1=['keras.layers.InputSpec', 'layers.InputSpec']) -class InputSpec(object): - """Specifies the ndim, dtype and shape of every input to a layer. + The layer's attribute `attr` at the node of index `node_index`. - Every layer should expose (if appropriate) an `input_spec` attribute: - a list of instances of InputSpec (one per input tensor). + Raises: + RuntimeError: If the layer has no inbound nodes, or if called in Eager + mode. + ValueError: If the index provided does not match any node. + """ + if not self._inbound_nodes: + raise RuntimeError('The layer has never been called ' + 'and thus has no defined ' + attr_name + '.') + if not len(self._inbound_nodes) > node_index: + raise ValueError('Asked to get ' + attr_name + ' at node ' + + str(node_index) + ', but the layer has only ' + + str(len(self._inbound_nodes)) + ' inbound nodes.') + values = getattr(self._inbound_nodes[node_index], attr) + if len(values) == 1: + return values[0] + else: + return values - A None entry in a shape is compatible with any dimension, - a None shape is compatible with any shape. + @property + def _static_graph_friendly(self): + """Whether the layer can be called to create a static graph. - Arguments: - dtype: Expected DataType of the input. - shape: Shape tuple, expected shape of the input - (may include None for unchecked axes). - ndim: Integer, expected rank of the input. - max_ndim: Integer, maximum rank of the input. - min_ndim: Integer, minimum rank of the input. - axes: Dictionary mapping integer axes to - a specific dimension value. - """ + Because of nesting, there are two components to being "graph-friendly": + 1) all inner layers are graph-friendly + 2) the way they are composed is graph-friendly. + We denote the latter as "_call_is_graph_friendly", and define + "_static_graph_friendly" as being the combination of + "_call_is_graph_friendly" and "all inner layers are _static_graph_friendly". + For atomic layers (no inner layers), this is just "_call_is_graph_friendly". - def __init__(self, - dtype=None, - shape=None, - ndim=None, - max_ndim=None, - min_ndim=None, - axes=None): - self.dtype = dtype - self.shape = shape - if shape is not None: - self.ndim = len(shape) - else: - self.ndim = ndim - self.max_ndim = max_ndim - self.min_ndim = min_ndim - self.axes = axes or {} + Returns: + Boolean. + """ + return self._call_is_graph_friendly - def __repr__(self): - spec = [('dtype=' + str(self.dtype)) if self.dtype else '', - ('shape=' + str(self.shape)) if self.shape else '', - ('ndim=' + str(self.ndim)) if self.ndim else '', - ('max_ndim=' + str(self.max_ndim)) if self.max_ndim else '', - ('min_ndim=' + str(self.min_ndim)) if self.min_ndim else '', - ('axes=' + str(self.axes)) if self.axes else ''] - return 'InputSpec(%s)' % ', '.join(x for x in spec if x) + def _maybe_build(self, inputs): + # Check input assumptions set before layer building, e.g. input rank. + input_spec.assert_input_compatibility( + self.input_spec, inputs, self.name) + input_list = nest.flatten(inputs) + if input_list and self._dtype is None: + try: + self._dtype = input_list[0].dtype.base_dtype.name + except AttributeError: + pass + input_shapes = None + if all(hasattr(x, 'shape') for x in input_list): + input_shapes = nest.map_structure(lambda x: x.shape, inputs) + # Only call `build` if the user has manually overridden the build method. + if not hasattr(self.build, '_is_default'): + self.build(input_shapes) class Node(object): @@ -1768,192 +1705,12 @@ class Node(object): } -def unique_layer_name(name, name_uid_map=None, avoid_names=None, namespace='', - zero_based=False): - """Makes a layer name (or arbitrary string) unique within a TensorFlow graph. - - Arguments: - name: String name to make unique. - name_uid_map: An optional defaultdict(int) to use when creating unique - names. If None (default), uses a per-Graph dictionary. - avoid_names: An optional set or dict with names which should not be used. If - None (default) does not avoid any names. - namespace: Gets a name which is unique within the (graph, namespace). Layers - which are not Networks use a blank namespace and so get graph-global - names. - zero_based: If True, name sequences start with no suffix (e.g. "dense", - "dense_1"). If False, naming is one-based ("dense_1", "dense_2"). - - Returns: - Unique string name. - - Example: - - ```python - _unique_layer_name('dense') # dense_1 - _unique_layer_name('dense') # dense_2 - ``` - """ - if name_uid_map is None: - name_uid_map = get_default_graph_uid_map() - if avoid_names is None: - avoid_names = set() - proposed_name = None - while proposed_name is None or proposed_name in avoid_names: - name_key = (namespace, name) - if zero_based: - number = name_uid_map[name_key] - if number: - proposed_name = name + '_' + str(number) - else: - proposed_name = name - name_uid_map[name_key] += 1 - else: - name_uid_map[name_key] += 1 - proposed_name = name + '_' + str(name_uid_map[name_key]) - return proposed_name - - -def have_all_keras_metadata(iterable_or_element): - if not isinstance(iterable_or_element, (list, tuple)): - iterable = [iterable_or_element] - else: - iterable = nest.flatten(iterable_or_element) - return all([hasattr(x, '_keras_history') for x in iterable]) - - -def collect_previous_mask(input_tensors): - """Retrieves the output mask(s) of the previous node. - - Arguments: - input_tensors: A tensor or list of tensors. - - Returns: - A mask tensor or list of mask tensors. - """ - input_tensors = nest.flatten(input_tensors) - masks = [] - for x in input_tensors: - if hasattr(x, '_keras_mask'): - mask = x._keras_mask # pylint: disable=protected-access - masks.append(mask) - else: - masks.append(None) - if len(masks) == 1: - return masks[0] - return masks - - -def get_default_graph_uid_map(): - # TODO(fchollet): refactor this into backend. - graph = ops.get_default_graph() - name_uid_map = backend.PER_GRAPH_LAYER_NAME_UIDS.get(graph, None) - if name_uid_map is None: - name_uid_map = collections_lib.defaultdict(int) - backend.PER_GRAPH_LAYER_NAME_UIDS[graph] = name_uid_map - return name_uid_map - - -def make_variable(name, - shape=None, - dtype=dtypes.float32, - initializer=None, - partition_info=None, - trainable=None, - caching_device=None, - validate_shape=True, - constraint=None, - use_resource=None, - collections=None, - synchronization=tf_variables.VariableSynchronization.AUTO, - aggregation=tf_variables.VariableAggregation.NONE, - partitioner=None): # pylint: disable=unused-argument - """Temporary util to create a variable (relies on `variable_scope.variable`). - - Some reuse-related technicalities prevent us from using - `variable_scope.get_variable()` directly, so we use a subcomponent - that has fewer constraints (`variable_scope.variable()`). - - In the longer term, it seems like a similar "default variable creator" method - should exist in `CheckpointableBase` instead. When this happens, we can get - rid of this temporary solution. - - TODO(fchollet): remove this method when no longer needed. - TODO(fchollet): handle `partitioner` argument. - - Arguments: - name: Variable name. - shape: Variable shape. - dtype: The type of the variable. Defaults to `self.dtype` or `float32`. - initializer: Initializer instance (callable). - partition_info: Not handled at this time. - trainable: Whether the variable should be part of the layer's - "trainable_variables" (e.g. variables, biases) - or "non_trainable_variables" (e.g. BatchNorm mean, stddev). - Note, if the current variable scope is marked as non-trainable - then this parameter is ignored and any added variables are also - marked as non-trainable. `trainable` defaults to `True` unless - `synchronization` is set to `ON_READ`. - caching_device: Passed to `tf.Variable`. - validate_shape: Passed to `tf.Variable`. - constraint: Constraint instance (callable). - use_resource: Whether to use a `ResourceVariable`. - collections: List of graph collections keys. The new variable is added to - these collections. Defaults to `[GraphKeys.GLOBAL_VARIABLES]`. - synchronization: Indicates when a distributed a variable will be - aggregated. Accepted values are constants defined in the class - `tf.VariableSynchronization`. By default the synchronization is set to - `AUTO` and the current `DistributionStrategy` chooses - when to synchronize. If `synchronization` is set to `ON_READ`, - `trainable` must not be set to `True`. - aggregation: Indicates how a distributed variable will be aggregated. - Accepted values are constants defined in the class - `tf.VariableAggregation`. - partitioner: Not handled at this time. - - Returns: - Variable instance. - """ - initializing_from_value = False - if initializer is not None and not callable(initializer): - initializing_from_value = True - - with ops.init_scope(): - if initializing_from_value: - init_val = initializer - variable_dtype = None - else: - # Instantiate initializer if provided initializer is a type object. - if isinstance(initializer, type(init_ops.Initializer)): - initializer = initializer(dtype=dtype) - init_val = lambda: initializer( # pylint: disable=g-long-lambda - shape, dtype=dtype, partition_info=partition_info) - variable_dtype = dtype.base_dtype - if use_resource is None: - use_resource = True - - # TODO(apassos,rohanj) figure out how to remove collections from here so we - # can remove the V1. - v = tf_variables.VariableV1( - initial_value=init_val, - name=name, - trainable=trainable, - caching_device=caching_device, - dtype=variable_dtype, - validate_shape=validate_shape, - constraint=constraint, - use_resource=use_resource, - collections=collections, - synchronization=synchronization, - aggregation=aggregation) - return v - - def default(method): """Decorates a method to detect overrides in subclasses.""" method._is_default = True return method -def generate_placeholders_from_shape(shape): - return array_ops.placeholder(shape=shape, dtype=backend.floatx()) +# Avoid breaking users who directly import this symbol from this file. +# TODO(fchollet): remove this. +InputSpec = input_spec.InputSpec # pylint:disable=invalid-name diff --git a/tensorflow/python/keras/engine/base_layer_test.py b/tensorflow/python/keras/engine/base_layer_test.py index 704589349a..798775b6a5 100644 --- a/tensorflow/python/keras/engine/base_layer_test.py +++ b/tensorflow/python/keras/engine/base_layer_test.py @@ -81,14 +81,14 @@ class BaseLayerTest(test.TestCase): inputs = keras.Input((3,)) outputs = DynamicLayer1()(inputs) model = keras.Model(inputs, outputs) - self.assertEqual(model._is_static_graph_friendly, False) + self.assertEqual(model._static_graph_friendly, False) model.compile(RMSPropOptimizer(0.001), loss='mse') model.train_on_batch(np.random.random((2, 3)), np.random.random((2, 3))) inputs = keras.Input((3,)) outputs = DynamicLayer2()(inputs) model = keras.Model(inputs, outputs) - self.assertEqual(model._is_static_graph_friendly, False) + self.assertEqual(model._static_graph_friendly, False) model.compile(RMSPropOptimizer(0.001), loss='mse') model.train_on_batch(np.random.random((2, 3)), np.random.random((2, 3))) @@ -102,7 +102,7 @@ class BaseLayerTest(test.TestCase): outputs = inner_model(x) model = keras.Model(inputs, outputs) - self.assertEqual(model._is_static_graph_friendly, False) + self.assertEqual(model._static_graph_friendly, False) model.compile(RMSPropOptimizer(0.001), loss='mse') model.train_on_batch(np.random.random((2, 3)), np.random.random((2, 3))) @@ -116,7 +116,7 @@ class BaseLayerTest(test.TestCase): inputs = keras.Input((3,)) outputs = InvalidLayer()(inputs) model = keras.Model(inputs, outputs) - self.assertEqual(model._is_static_graph_friendly, False) + self.assertEqual(model._static_graph_friendly, False) model.compile(RMSPropOptimizer(0.001), loss='mse') with self.assertRaisesRegexp(ValueError, 'You did something wrong!'): model.train_on_batch(np.random.random((2, 3)), np.random.random((2, 3))) diff --git a/tensorflow/python/keras/engine/base_layer_utils.py b/tensorflow/python/keras/engine/base_layer_utils.py new file mode 100644 index 0000000000..d2f947f177 --- /dev/null +++ b/tensorflow/python/keras/engine/base_layer_utils.py @@ -0,0 +1,236 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Contains private utilities used mainly by the base Layer class.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import collections as collections_lib +import enum + +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.keras import backend +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import init_ops +from tensorflow.python.ops import variables as tf_variables +from tensorflow.python.util import nest + + +class CallConvention(enum.Enum): + """Calling conventions for passing `Layer` inputs to `Layer.call`.""" + # The Layer takes inputs as its first argument, named "inputs" for + # compatibility with the signature of Layer.__call__. This is the mode assumed + # for Layers which are not subclassed Models. + EXPLICIT_INPUTS_ARGUMENT = 1 + # The Layer takes a single positional argument, not named "inputs". It's + # treated like an "inputs" argument. + SINGLE_POSITIONAL_ARGUMENT = 2 + # The Layer has multiple positional arguments to which its inputs should be + # bound. + POSITIONAL_ARGUMENTS_ARE_INPUTS = 3 + + +def create_mean_metric(value, name=None): + # TODO(psv): Remove this import when b/110718070 is fixed. + from tensorflow.python.keras import metrics as metrics_module # pylint: disable=g-import-not-at-top + metric_obj = metrics_module.Mean(name=name) + result = metric_obj(value) + return metric_obj, result + + +def make_variable(name, + shape=None, + dtype=dtypes.float32, + initializer=None, + partition_info=None, + trainable=None, + caching_device=None, + validate_shape=True, + constraint=None, + use_resource=None, + collections=None, + synchronization=tf_variables.VariableSynchronization.AUTO, + aggregation=tf_variables.VariableAggregation.NONE, + partitioner=None): # pylint: disable=unused-argument + """Temporary util to create a variable (relies on `variable_scope.variable`). + + Some reuse-related technicalities prevent us from using + `variable_scope.get_variable()` directly, so we use a subcomponent + that has fewer constraints (`variable_scope.variable()`). + + In the longer term, it seems like a similar "default variable creator" method + should exist in `CheckpointableBase` instead. When this happens, we can get + rid of this temporary solution. + + TODO(fchollet): remove this method when no longer needed. + TODO(fchollet): handle `partitioner` argument. + + Arguments: + name: Variable name. + shape: Variable shape. + dtype: The type of the variable. Defaults to `self.dtype` or `float32`. + initializer: Initializer instance (callable). + partition_info: Not handled at this time. + trainable: Whether the variable should be part of the layer's + "trainable_variables" (e.g. variables, biases) + or "non_trainable_variables" (e.g. BatchNorm mean, stddev). + Note, if the current variable scope is marked as non-trainable + then this parameter is ignored and any added variables are also + marked as non-trainable. `trainable` defaults to `True` unless + `synchronization` is set to `ON_READ`. + caching_device: Passed to `tf.Variable`. + validate_shape: Passed to `tf.Variable`. + constraint: Constraint instance (callable). + use_resource: Whether to use a `ResourceVariable`. + collections: List of graph collections keys. The new variable is added to + these collections. Defaults to `[GraphKeys.GLOBAL_VARIABLES]`. + synchronization: Indicates when a distributed a variable will be + aggregated. Accepted values are constants defined in the class + `tf.VariableSynchronization`. By default the synchronization is set to + `AUTO` and the current `DistributionStrategy` chooses + when to synchronize. If `synchronization` is set to `ON_READ`, + `trainable` must not be set to `True`. + aggregation: Indicates how a distributed variable will be aggregated. + Accepted values are constants defined in the class + `tf.VariableAggregation`. + partitioner: Not handled at this time. + + Returns: + Variable instance. + """ + initializing_from_value = False + if initializer is not None and not callable(initializer): + initializing_from_value = True + + with ops.init_scope(): + if initializing_from_value: + init_val = initializer + variable_dtype = None + else: + # Instantiate initializer if provided initializer is a type object. + if isinstance(initializer, type(init_ops.Initializer)): + initializer = initializer(dtype=dtype) + init_val = lambda: initializer( # pylint: disable=g-long-lambda + shape, dtype=dtype, partition_info=partition_info) + variable_dtype = dtype.base_dtype + if use_resource is None: + use_resource = True + + # TODO(apassos,rohanj) figure out how to remove collections from here so we + # can remove the V1. + v = tf_variables.VariableV1( + initial_value=init_val, + name=name, + trainable=trainable, + caching_device=caching_device, + dtype=variable_dtype, + validate_shape=validate_shape, + constraint=constraint, + use_resource=use_resource, + collections=collections, + synchronization=synchronization, + aggregation=aggregation) + return v + + +def get_default_graph_uid_map(): + # TODO(fchollet): refactor this into backend. + graph = ops.get_default_graph() + name_uid_map = backend.PER_GRAPH_LAYER_NAME_UIDS.get(graph, None) + if name_uid_map is None: + name_uid_map = collections_lib.defaultdict(int) + backend.PER_GRAPH_LAYER_NAME_UIDS[graph] = name_uid_map + return name_uid_map + + +def unique_layer_name(name, name_uid_map=None, avoid_names=None, namespace='', + zero_based=False): + """Makes a layer name (or arbitrary string) unique within a TensorFlow graph. + + Arguments: + name: String name to make unique. + name_uid_map: An optional defaultdict(int) to use when creating unique + names. If None (default), uses a per-Graph dictionary. + avoid_names: An optional set or dict with names which should not be used. If + None (default) does not avoid any names. + namespace: Gets a name which is unique within the (graph, namespace). Layers + which are not Networks use a blank namespace and so get graph-global + names. + zero_based: If True, name sequences start with no suffix (e.g. "dense", + "dense_1"). If False, naming is one-based ("dense_1", "dense_2"). + + Returns: + Unique string name. + + Example: + + ```python + _unique_layer_name('dense') # dense_1 + _unique_layer_name('dense') # dense_2 + ``` + """ + if name_uid_map is None: + name_uid_map = get_default_graph_uid_map() + if avoid_names is None: + avoid_names = set() + proposed_name = None + while proposed_name is None or proposed_name in avoid_names: + name_key = (namespace, name) + if zero_based: + number = name_uid_map[name_key] + if number: + proposed_name = name + '_' + str(number) + else: + proposed_name = name + name_uid_map[name_key] += 1 + else: + name_uid_map[name_key] += 1 + proposed_name = name + '_' + str(name_uid_map[name_key]) + return proposed_name + + +def collect_previous_mask(input_tensors): + """Retrieves the output mask(s) of the previous node. + + Arguments: + input_tensors: A tensor or list of tensors. + + Returns: + A mask tensor or list of mask tensors. + """ + input_tensors = nest.flatten(input_tensors) + masks = [] + for x in input_tensors: + if hasattr(x, '_keras_mask'): + mask = x._keras_mask # pylint: disable=protected-access + masks.append(mask) + else: + masks.append(None) + if len(masks) == 1: + return masks[0] + return masks + + +def have_all_keras_metadata(iterable_or_element): + if not isinstance(iterable_or_element, (list, tuple)): + iterable = [iterable_or_element] + else: + iterable = nest.flatten(iterable_or_element) + return all(hasattr(x, '_keras_history') for x in iterable) + + +def generate_placeholders_from_shape(shape): + return array_ops.placeholder(shape=shape, dtype=backend.floatx()) diff --git a/tensorflow/python/keras/engine/distributed_training_utils.py b/tensorflow/python/keras/engine/distributed_training_utils.py index f939b7565a..d100182381 100644 --- a/tensorflow/python/keras/engine/distributed_training_utils.py +++ b/tensorflow/python/keras/engine/distributed_training_utils.py @@ -22,15 +22,17 @@ import numpy as np from tensorflow.python.client import session as session_module from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import iterator_ops +from tensorflow.python.distribute import distribute_coordinator_context as dc_context +from tensorflow.python.distribute import distribute_lib from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util from tensorflow.python.keras import backend as K from tensorflow.python.keras import callbacks +from tensorflow.python.keras.optimizer_v2 import optimizer_v2 from tensorflow.python.ops import array_ops from tensorflow.python.ops import variables from tensorflow.python.platform import tf_logging as logging -from tensorflow.python.training import distribute as distribute_lib from tensorflow.python.util import nest @@ -52,14 +54,18 @@ def set_weights(distribution_strategy, dist_model, weights): num_param = len(layer.weights) layer_weights = weights[:num_param] for sw, w in zip(layer.weights, layer_weights): - assign_ops.append(distribution_strategy.unwrap(sw.assign(w))) - + if ops.executing_eagerly_outside_functions(): + sw.assign(w) + else: + assign_ops.append(distribution_strategy.unwrap(sw.assign(w))) weights = weights[num_param:] - K.get_session().run(assign_ops) + + if not ops.executing_eagerly_outside_functions(): + K.get_session().run(assign_ops) def unwrap_values(distribution_strategy, grouped_inputs, grouped_outputs, - grouped_updates, grouped_session_args, + grouped_updates=None, grouped_session_args=None, with_loss_tensor=False): """Unwrap and return the list of values contained in the PerDevice parameters. @@ -92,11 +98,8 @@ def unwrap_values(distribution_strategy, grouped_inputs, grouped_outputs, grouped_inputs) if with_loss_tensor: # reduce loss tensor before adding it to the list of fetches - loss = distribution_strategy.unwrap( - distribution_strategy.reduce(distribute_lib.get_loss_reduction(), - grouped_outputs[0], - destinations='/device:CPU:0'))[0] - + loss = distribution_strategy.reduce(distribute_lib.get_loss_reduction(), + grouped_outputs[0]) all_outputs = flatten_perdevice_values(distribution_strategy, grouped_outputs[1:]) all_outputs = [loss] + all_outputs @@ -104,20 +107,25 @@ def unwrap_values(distribution_strategy, grouped_inputs, grouped_outputs, all_outputs = flatten_perdevice_values(distribution_strategy, grouped_outputs) - all_updates = flatten_perdevice_values(distribution_strategy, - grouped_updates) + if grouped_updates: + all_updates = flatten_perdevice_values(distribution_strategy, + grouped_updates) + else: + all_updates = None all_session_args = {} - grouped_feed_dict = grouped_session_args.get('feed_dict') - if grouped_feed_dict: - all_session_args['feed_dict'] = flatten_perdevice_values( - distribution_strategy, grouped_feed_dict) - - grouped_fetches = grouped_session_args.get('fetches') - if grouped_fetches: - all_session_args['fetches'] = flatten_perdevice_values( - distribution_strategy, grouped_fetches) - + if grouped_session_args: + grouped_feed_dict = grouped_session_args.get('feed_dict') + if grouped_feed_dict: + all_session_args['feed_dict'] = flatten_perdevice_values( + distribution_strategy, grouped_feed_dict) + + grouped_fetches = grouped_session_args.get('fetches') + if grouped_fetches: + all_session_args['fetches'] = flatten_perdevice_values( + distribution_strategy, grouped_fetches) + + # TODO(priyag): Return only non empty/None values return all_inputs, all_outputs, all_updates, all_session_args @@ -144,11 +152,14 @@ def flatten_perdevice_values(distribution_strategy, perdevice_values): for e in distribution_strategy.unwrap(flattened)] -def validate_callbacks(input_callbacks): +def validate_callbacks(input_callbacks, optimizer, current_strategy): """Validate whether given callbacks are supported by DistributionStrategy. Args: input_callbacks: List of callbacks passed by the user to fit. + optimizer: Optimizer instance used to train the model. + current_strategy: The DistributionStrategy used to distribute training + and validation. Raises: ValueError: If `LearningRateScheduler` or `ReduceLROnPlateau` is one of the @@ -170,12 +181,18 @@ def validate_callbacks(input_callbacks): 'these attributes are not set. You can access each of ' 'the individual distributed models using the ' '`_grouped_model` attribute of your original model.') - if isinstance(callback, callbacks.LearningRateScheduler): - raise ValueError('LearningRateScheduler callback is not supported with ' - 'DistributionStrategy.') - if isinstance(callback, callbacks.ReduceLROnPlateau): - raise ValueError('ReduceLROnPlateau callback is not supported with ' - 'DistributionStrategy.') + if isinstance(callback, (callbacks.LearningRateScheduler, + callbacks.ReduceLROnPlateau)): + strategy_name = current_strategy.__class__.__name__ + # TODO(anjalisridhar): We might need to add a condition for multi + # worker strategy when we support it in Keras. + if is_tpu_strategy(current_strategy): + raise ValueError('%s callback is not supported with %s.' % + (callback, strategy_name)) + + if not isinstance(optimizer, optimizer_v2.OptimizerV2): + raise ValueError('You must specify a Keras Optimizer V2 when using ' + '%s callback with DistributionStrategy.' % callback) # If users want to use the TensorBoard callback they cannot use certain # features of the callback that involve accessing model attributes and @@ -293,19 +310,64 @@ def validate_all_tensor_shapes(x, x_values): ' inputs {}'.format(x)) +def _wait_for_variable_initialization(session): + """Utility to wait for variables to be initialized.""" + all_variables = K._get_variables(K.get_graph()) # pylint: disable=protected-access + candidate_vars = [] + for v in all_variables: + if not getattr(v, '_keras_initialized', False): + candidate_vars.append(v) + + if not candidate_vars: + return + + while True: + is_initialized = session.run( + [variables.is_variable_initialized(v) for v in candidate_vars]) + uninitialized_vars = [] + for flag, v in zip(is_initialized, candidate_vars): + if not flag: + uninitialized_vars.append(v) + v._keras_initialized = True # pylint: disable=protected-access + if not uninitialized_vars: + break + + +def init_restore_or_wait_for_variables(): + """Initialize or restore variables or wait for variables to be initialized.""" + session = K._get_session() # pylint: disable=protected-access + worker_context = dc_context.get_current_worker_context() + if not worker_context or worker_context.experimental_should_init: + # TODO(yuefengz): if checkpoints exit, restore from checkpoint. + K._initialize_variables(session) # pylint: disable=protected-access + else: + _wait_for_variable_initialization(session) + + def configure_and_create_session(distribution_strategy): """Configure session config and create a session with it.""" # TODO(priyag): Throw error if a session already exists. session_config = K.get_default_session_config() - distribution_strategy.configure(session_config) - if distribution_strategy.__class__.__name__ == 'TPUStrategy': - # TODO(priyag): Remove this workaround when Distributed Coordinator is - # integrated with keras and we can create a session from there. - master = distribution_strategy._tpu_cluster_resolver.master() # pylint: disable=protected-access + if is_tpu_strategy(distribution_strategy): + # TODO(priyag, yuefengz): Remove this workaround when Distribute + # Coordinator is integrated with keras and we can create a session from + # there. + distribution_strategy.configure(session_config) + master = distribution_strategy.extended._tpu_cluster_resolver.master() # pylint: disable=protected-access session = session_module.Session(config=session_config, target=master) else: - session = session_module.Session(config=session_config) + worker_context = dc_context.get_current_worker_context() + if worker_context: + dc_session_config = worker_context.session_config + # Merge the default session config to the one from distribute coordinator, + # which is fine for now since they don't have conflicting configurations. + dc_session_config.MergeFrom(session_config) + session = session_module.Session( + config=dc_session_config, target=worker_context.master_target) + else: + distribution_strategy.configure(session_config) + session = session_module.Session(config=session_config) K.set_session(session) @@ -334,11 +396,15 @@ def validate_inputs(x, y, distribution_strategy): 'Iterator. You must pass a `tf.data.Dataset` object or a ' 'numpy array as input.') - if distribution_strategy.__class__.__name__ == 'TPUStrategy': + if is_tpu_strategy(distribution_strategy): for i in [x, y]: - if isinstance(i, dataset_ops.Dataset): + if isinstance(i, dataset_ops.DatasetV2): shapes = nest.flatten(i.output_shapes) - if any([not s.is_fully_defined() for s in shapes]): + try: + s = next(s for s in shapes if not s.is_fully_defined()) + except StopIteration: + continue + else: raise ValueError( 'Using TPUs currently requires fully defined shapes. Either use ' 'set_shape() on the input tensors or use ' @@ -346,37 +412,97 @@ def validate_inputs(x, y, distribution_strategy): 'Found unknown shape {} in input {}.'.format(s, i)) -def get_input_batch_params(first_x_value, batch_size, distribution_strategy): +# TODO(b/118776054): Currently we support global batch size for TPUStrategy and +# core MirroredStrategy only. Remove this check when contrib MirroredStrategy is +# no longer needed. +def global_batch_size_supported(distribution_strategy): + return distribution_strategy.extended._global_batch_size # pylint: disable=protected-access + + +# TODO(sourabhbajaj): Remove this once we use the same API for all strategies. +def is_tpu_strategy(strategy): + """We're executing TPU Strategy.""" + return strategy is not None and strategy.__class__.__name__ == 'TPUStrategy' + + +def get_input_params(distribution_strategy, first_x_value, steps, batch_size, + is_training=False): """Calculate the number of batches and steps/steps_per_epoch. Args: + distribution_strategy: The DistributionStrategy used to compile the model. first_x_value: This is the first input numpy array that is passed in as the model input. - batch_size: The specified batch_size or the default batch_size of 32. - distribution_strategy: The current DistributionStrategy used to compile the - model. + steps: The specified number of steps. + batch_size: The specified batch_size. + is_training: Boolean to relax the constraints on consuming all the training + samples to keep compatibility till we support partial batches. Returns: - The steps or steps_per_epoch argument depending on if a user is - calling `fit`, `evaluate` or `predict`. + steps: The steps or steps_per_epoch argument depending on if a user is + calling `fit`, `evaluate` or `predict`. If the is_training flag is set + we don't require the number of samples to be used completely. + batch_size: The batch size to be used in model iterations. Raises: ValueError: If the number of batches or steps evaluates to 0. """ - num_batches = first_x_value.shape[0] // batch_size - if not num_batches: - raise ValueError('Please specify a batch_size that is smaller than' - 'the number of input samples %d.' % first_x_value.shape[0]) - steps = num_batches // distribution_strategy.num_replicas_in_sync - if not steps: - # TODO(anjalisridhar): Number of replicas in the error message may not - # convey what we want to the user. Is there another terminology that we can - # use that is consistent across different strategies? - raise ValueError('The number of batches %d is smaller than the number ' - 'of replicas %d used for DistributionStrategy. ' % - (num_batches, distribution_strategy.num_replicas_in_sync)) - return steps + num_samples = first_x_value.shape[0] + # TODO(b/118776054): Use global batch size for Keras/DS support. + # Currently this is only supported in TPUStrategy and CoreMirroredStrategy. + use_per_replica_batch = not global_batch_size_supported( + distribution_strategy) + + if steps is None: + if batch_size is None: + # If neither the batch size or number of steps are set. We choose the + # global batch size as the minimum of number of samples and 32. 32 is + # chosen to provide backward compatibility. + global_batch_size = min(num_samples, 32) + else: + # If the user provided the batch size we need to handle the case + # between different strategies that use the global/per-replica batch size + global_batch_size = batch_size + if use_per_replica_batch: + global_batch_size *= distribution_strategy.num_replicas_in_sync + if not is_training and num_samples % global_batch_size: + raise ValueError('The number of samples %s is not divisible by ' + 'batch size %s.' % (num_samples, global_batch_size)) + steps = num_samples // global_batch_size + else: + if batch_size is None: + # We calculate the batch size based on the number of steps specified + if num_samples % steps: + raise ValueError('The number of samples %s is not divisible by ' + 'steps %s. Please change the number of steps to a ' + 'value that can consume all the samples' % ( + num_samples, steps)) + global_batch_size = num_samples // steps + else: + # If the user provided the batch size we need to handle the case + # between different strategies that use the global/per-replica batch size + global_batch_size = batch_size + if use_per_replica_batch: + global_batch_size *= distribution_strategy.num_replicas_in_sync + + if num_samples < (global_batch_size * steps): + raise ValueError('Number of samples %s is less than samples required ' + 'for specified batch_size %s and steps %s' % ( + num_samples, global_batch_size, steps)) + + # We need to return the per replica or global batch size based on the strategy + if use_per_replica_batch: + if global_batch_size % distribution_strategy.num_replicas_in_sync: + raise ValueError( + 'The batch size (%s) could not be sharded evenly across the sync ' + 'replicas (%s) in the distribution strategy.' % ( + global_batch_size, distribution_strategy.num_replicas_in_sync)) + batch_size = global_batch_size // distribution_strategy.num_replicas_in_sync + else: + batch_size = global_batch_size + + return steps, batch_size def get_batch_dimension(iterator): @@ -387,33 +513,6 @@ def get_batch_dimension(iterator): return dims[0] if dims else None -def get_batch_size(num_replicas, num_samples, steps): - """Calculate and return batch size for numpy inputs. - - Args: - num_replicas: Number of devices over which the model input is distributed. - num_samples: Total number of input samples in the input numpy arrays. - steps: Number of steps that we run the model for. - - Returns: - batch size used to create the Dataset object from the input numpy arrays. - - """ - if num_samples % steps != 0: - logging.warning('The number of input samples %d is not evenly ' - 'divisible by the number of steps %d. ' - 'Some samples will not be processed as expected.' % - (num_samples, steps)) - global_batch_size = num_samples // steps - if global_batch_size % num_replicas != 0: - logging.warning('The total number of batches per step %d is not evenly ' - 'divisible by the number of replicas %d used in ' - 'DistributionStrategy. Some samples will not be processed ' - 'as expected.' % - (global_batch_size, num_replicas)) - return global_batch_size // num_replicas - - def get_cpu_device(distribution_strategy): """Returns the CPU device of the TPU host or the default CPU device string. @@ -429,12 +528,12 @@ def get_cpu_device(distribution_strategy): NotImplementedError: We currently don't support copying numpy data to multiple hosts in the case of Cloud TPU pods. """ - if distribution_strategy.__class__.__name__ == 'TPUStrategy': - if distribution_strategy.num_hosts > 1: + if is_tpu_strategy(distribution_strategy): + if distribution_strategy.extended.num_hosts > 1: raise NotImplementedError('TPUDistributionStrategy does not ' 'support numpy inputs when running on Cloud' 'TPU pods.') - return distribution_strategy.get_host_cpu_device(0) + return distribution_strategy.extended.get_host_cpu_device(0) else: # For all strategies except TPUDistributionStrategy # TODO(anjalisridhar): We may need to modify this when we add support for diff --git a/tensorflow/python/keras/engine/feature_columns_integration_test.py b/tensorflow/python/keras/engine/feature_columns_integration_test.py index e0478ee357..b7549e013c 100644 --- a/tensorflow/python/keras/engine/feature_columns_integration_test.py +++ b/tensorflow/python/keras/engine/feature_columns_integration_test.py @@ -18,11 +18,13 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from absl.testing import parameterized import numpy as np from tensorflow.python import keras from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.feature_column import feature_column_v2 as fc +from tensorflow.python.eager import context +from tensorflow.python.feature_column import feature_column_lib as fc from tensorflow.python.framework import test_util as tf_test_util from tensorflow.python.keras import metrics as metrics_module from tensorflow.python.platform import test @@ -33,7 +35,7 @@ class TestDNNModel(keras.models.Model): def __init__(self, feature_columns, units, name=None, **kwargs): super(TestDNNModel, self).__init__(name=name, **kwargs) - self._input_layer = fc.FeatureLayer(feature_columns, name='input_layer') + self._input_layer = fc.DenseFeatures(feature_columns, name='input_layer') self._dense_layer = keras.layers.Dense(units, name='dense_layer') def call(self, features): @@ -42,7 +44,7 @@ class TestDNNModel(keras.models.Model): return net -class FeatureColumnsIntegrationTest(test.TestCase): +class FeatureColumnsIntegrationTest(test.TestCase, parameterized.TestCase): """Most Sequential model API tests are covered in `training_test.py`. """ @@ -51,7 +53,7 @@ class FeatureColumnsIntegrationTest(test.TestCase): def test_sequential_model(self): columns = [fc.numeric_column('a')] model = keras.models.Sequential([ - fc.FeatureLayer(columns), + fc.DenseFeatures(columns), keras.layers.Dense(64, activation='relu'), keras.layers.Dense(20, activation='softmax') ]) @@ -72,7 +74,7 @@ class FeatureColumnsIntegrationTest(test.TestCase): def test_sequential_model_with_ds_input(self): columns = [fc.numeric_column('a')] model = keras.models.Sequential([ - fc.FeatureLayer(columns), + fc.DenseFeatures(columns), keras.layers.Dense(64, activation='relu'), keras.layers.Dense(20, activation='softmax') ]) @@ -112,8 +114,10 @@ class FeatureColumnsIntegrationTest(test.TestCase): dnn_model.evaluate(x=x, y=y, batch_size=5) dnn_model.predict(x=x, batch_size=5) + @parameterized.parameters(True, False) @tf_test_util.run_in_graph_and_eager_modes - def test_subclassed_model_with_feature_columns_with_ds_input(self): + def test_subclassed_model_with_feature_columns_with_ds_input(self, + run_eagerly): col_a = fc.numeric_column('a') col_b = fc.numeric_column('b') @@ -122,7 +126,8 @@ class FeatureColumnsIntegrationTest(test.TestCase): dnn_model.compile( optimizer=rmsprop.RMSPropOptimizer(learning_rate=0.001), loss='categorical_crossentropy', - metrics=['accuracy']) + metrics=['accuracy'], + run_eagerly=run_eagerly and context.executing_eagerly()) y = np.random.randint(20, size=(100, 1)) y = keras.utils.to_categorical(y, num_classes=20) @@ -140,10 +145,10 @@ class FeatureColumnsIntegrationTest(test.TestCase): col_a = fc.numeric_column('a') col_b = fc.numeric_column('b') - feature_layer = fc.FeatureLayer([col_a, col_b], name='fc') + feature_layer = fc.DenseFeatures([col_a, col_b], name='fc') dense = keras.layers.Dense(4) - # This seems problematic.... We probably need something for FeatureLayer + # This seems problematic.... We probably need something for DenseFeatures # the way Input is for InputLayer. output = dense(feature_layer) @@ -167,11 +172,11 @@ class FeatureColumnsIntegrationTest(test.TestCase): col_b = fc.numeric_column('b') col_c = fc.numeric_column('c') - fc1 = fc.FeatureLayer([col_a, col_b], name='fc1') - fc2 = fc.FeatureLayer([col_b, col_c], name='fc2') + fc1 = fc.DenseFeatures([col_a, col_b], name='fc1') + fc2 = fc.DenseFeatures([col_b, col_c], name='fc2') dense = keras.layers.Dense(4) - # This seems problematic.... We probably need something for FeatureLayer + # This seems problematic.... We probably need something for DenseFeatures # the way Input is for InputLayer. output = dense(fc1) + dense(fc2) diff --git a/tensorflow/python/keras/engine/input_layer.py b/tensorflow/python/keras/engine/input_layer.py index 4e96106004..9874efe2bc 100644 --- a/tensorflow/python/keras/engine/input_layer.py +++ b/tensorflow/python/keras/engine/input_layer.py @@ -19,12 +19,10 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.python.eager import context from tensorflow.python.framework import tensor_shape from tensorflow.python.keras import backend from tensorflow.python.keras.engine import base_layer from tensorflow.python.keras.utils import tf_utils -from tensorflow.python.ops import array_ops from tensorflow.python.util.tf_export import tf_export @@ -84,7 +82,6 @@ class InputLayer(base_layer.Layer): self.sparse = sparse self.batch_size = batch_size self.supports_masking = True - self._can_use_graph_functions = True if isinstance(input_shape, tensor_shape.TensorShape): input_shape = tuple(input_shape.as_list()) @@ -95,19 +92,19 @@ class InputLayer(base_layer.Layer): else: batch_input_shape = None graph = backend.get_graph() - with context.graph_mode(): - with graph.as_default(): - # In graph mode, create a graph placeholder to call the layer on. - if sparse: - input_tensor = array_ops.sparse_placeholder( - shape=batch_input_shape, - dtype=dtype, - name=self.name) - else: - input_tensor = array_ops.placeholder( - shape=batch_input_shape, - dtype=dtype, - name=self.name) + with graph.as_default(): + # In graph mode, create a graph placeholder to call the layer on. + if sparse: + input_tensor = backend.placeholder( + shape=batch_input_shape, + dtype=dtype, + name=self.name, + sparse=True) + else: + input_tensor = backend.placeholder( + shape=batch_input_shape, + dtype=dtype, + name=self.name) self.is_placeholder = True self._batch_input_shape = batch_input_shape diff --git a/tensorflow/python/keras/engine/input_spec.py b/tensorflow/python/keras/engine/input_spec.py new file mode 100644 index 0000000000..7277c16fe5 --- /dev/null +++ b/tensorflow/python/keras/engine/input_spec.py @@ -0,0 +1,170 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# pylint: disable=protected-access +"""Contains the InputSpec class.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from six.moves import zip # pylint: disable=redefined-builtin + +from tensorflow.python.util import nest +from tensorflow.python.util.tf_export import tf_export + + +@tf_export('keras.layers.InputSpec', + v1=['keras.layers.InputSpec', 'layers.InputSpec']) +class InputSpec(object): + """Specifies the ndim, dtype and shape of every input to a layer. + + Every layer should expose (if appropriate) an `input_spec` attribute: + a list of instances of InputSpec (one per input tensor). + + A None entry in a shape is compatible with any dimension, + a None shape is compatible with any shape. + + Arguments: + dtype: Expected DataType of the input. + shape: Shape tuple, expected shape of the input + (may include None for unchecked axes). + ndim: Integer, expected rank of the input. + max_ndim: Integer, maximum rank of the input. + min_ndim: Integer, minimum rank of the input. + axes: Dictionary mapping integer axes to + a specific dimension value. + """ + + def __init__(self, + dtype=None, + shape=None, + ndim=None, + max_ndim=None, + min_ndim=None, + axes=None): + self.dtype = dtype + self.shape = shape + if shape is not None: + self.ndim = len(shape) + else: + self.ndim = ndim + self.max_ndim = max_ndim + self.min_ndim = min_ndim + self.axes = axes or {} + + def __repr__(self): + spec = [('dtype=' + str(self.dtype)) if self.dtype else '', + ('shape=' + str(self.shape)) if self.shape else '', + ('ndim=' + str(self.ndim)) if self.ndim else '', + ('max_ndim=' + str(self.max_ndim)) if self.max_ndim else '', + ('min_ndim=' + str(self.min_ndim)) if self.min_ndim else '', + ('axes=' + str(self.axes)) if self.axes else ''] + return 'InputSpec(%s)' % ', '.join(x for x in spec if x) + + +def assert_input_compatibility(input_spec, inputs, layer_name): + """Checks compatibility between the layer and provided inputs. + + This checks that the tensor(s) `inputs` verify the input assumptions + of a layer (if any). If not, a clear and actional exception gets raised. + + Arguments: + input_spec: An InputSpec instance, or None. + inputs: Input tensor or list of input tensors. + layer_name: String, name of the layer (for error message formatting). + + Raises: + ValueError: in case of mismatch between + the provided inputs and the expectations of the layer. + """ + if not input_spec: + return + if not isinstance(input_spec, (list, tuple)): + input_spec = nest.flatten(input_spec) + + inputs = nest.flatten(inputs) + if len(inputs) != len(input_spec): + raise ValueError('Layer ' + layer_name + ' expects ' + + str(len(input_spec)) + ' inputs, ' + 'but it received ' + str(len(inputs)) + + ' input tensors. Inputs received: ' + str(inputs)) + for input_index, (x, spec) in enumerate(zip(inputs, input_spec)): + if spec is None: + continue + + if (spec.ndim is not None or + spec.min_ndim is not None or + spec.max_ndim is not None): + if x.shape.ndims is None: + raise ValueError('Input ' + str(input_index) + ' of layer ' + + layer_name + ' is incompatible with the layer: ' + 'its rank is undefined, but the layer requires a ' + 'defined rank.') + + # Check ndim. + if spec.ndim is not None: + ndim = x.shape.ndims + if ndim != spec.ndim: + raise ValueError('Input ' + str(input_index) + ' of layer ' + + layer_name + ' is incompatible with the layer: ' + 'expected ndim=' + str(spec.ndim) + ', found ndim=' + + str(ndim) + '. Full shape received: ' + + str(x.shape.as_list())) + if spec.max_ndim is not None: + ndim = x.shape.ndims + if ndim is not None and ndim > spec.max_ndim: + raise ValueError('Input ' + str(input_index) + ' of layer ' + + layer_name + ' is incompatible with the layer: ' + 'expected max_ndim=' + str(spec.max_ndim) + + ', found ndim=' + str(ndim)) + if spec.min_ndim is not None: + ndim = x.shape.ndims + if ndim is not None and ndim < spec.min_ndim: + raise ValueError('Input ' + str(input_index) + ' of layer ' + + layer_name + ' is incompatible with the layer: ' + ': expected min_ndim=' + str(spec.min_ndim) + + ', found ndim=' + str(ndim) + + '. Full shape received: ' + + str(x.shape.as_list())) + # Check dtype. + if spec.dtype is not None: + if x.dtype != spec.dtype: + raise ValueError('Input ' + str(input_index) + ' of layer ' + + layer_name + ' is incompatible with the layer: ' + 'expected dtype=' + str(spec.dtype) + + ', found dtype=' + str(x.dtype)) + # Check specific shape axes. + if spec.axes: + shape = x.shape.as_list() + if shape is not None: + for axis, value in spec.axes.items(): + if hasattr(value, 'value'): + value = value.value + if value is not None and shape[int(axis)] not in {value, None}: + raise ValueError( + 'Input ' + str(input_index) + ' of layer ' + layer_name + ' is' + ' incompatible with the layer: expected axis ' + str(axis) + + ' of input shape to have value ' + str(value) + + ' but received input with shape ' + str(shape)) + # Check shape. + if spec.shape is not None: + shape = x.shape.as_list() + if shape is not None: + for spec_dim, dim in zip(spec.shape, shape): + if spec_dim is not None and dim is not None: + if spec_dim != dim: + raise ValueError('Input ' + str(input_index) + + ' is incompatible with layer ' + layer_name + + ': expected shape=' + str(spec.shape) + + ', found shape=' + str(shape)) diff --git a/tensorflow/python/keras/engine/network.py b/tensorflow/python/keras/engine/network.py index 9b58180e3d..7e6cc7bfee 100644 --- a/tensorflow/python/keras/engine/network.py +++ b/tensorflow/python/keras/engine/network.py @@ -36,7 +36,9 @@ from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.keras import backend from tensorflow.python.keras.engine import base_layer +from tensorflow.python.keras.engine import base_layer_utils from tensorflow.python.keras.engine import saving +from tensorflow.python.keras.engine import training_utils from tensorflow.python.keras.utils import generic_utils from tensorflow.python.keras.utils import layer_utils from tensorflow.python.keras.utils import tf_utils @@ -112,11 +114,6 @@ class Network(base_layer.Layer): self.trainable = True self._is_compiled = False self._expects_training_arg = False - # A list of "extra" variables assigned to attributes of this class, included - # in self.weights and self.variables. Always empty for graph networks (but - # included in base_init to avoid excessive special casing when retrieving - # the value). - self._extra_variables = [] # In many internal cases one needs to compute both the model's output # and its output mask without relying on `__call__` (which would do both and # set mask metadata), but for models, computing the mask requires to @@ -134,12 +131,19 @@ class Network(base_layer.Layer): self.optimizer = None # Private attributes to implement compatibility with Layer. + self._trainable_weights = [] + self._non_trainable_weights = [] self._updates = [] # Used in symbolic mode only. self._losses = [] self._eager_losses = [] + # A list of metric instances corresponding to the symbolic metric tensors + # added using the `add_metric` API. + self._metrics = [] + # A dictionary that maps metric names to metric result tensors. + self._metrics_tensors = {} self._scope = None # Never used. self._reuse = None # Never used. - self._can_use_graph_functions = False + self._call_is_graph_friendly = True if context.executing_eagerly(): self._graph = None else: @@ -160,7 +164,8 @@ class Network(base_layer.Layer): @checkpointable.no_automatic_dependency_tracking def _init_graph_network(self, inputs, outputs, name=None): - self._call_convention = base_layer.CallConvention.EXPLICIT_INPUTS_ARGUMENT + self._call_convention = (base_layer_utils + .CallConvention.EXPLICIT_INPUTS_ARGUMENT) # Normalize and set self.inputs, self.outputs. if isinstance(inputs, (list, tuple)): self.inputs = list(inputs) # Tensor or list of tensors. @@ -170,43 +175,7 @@ class Network(base_layer.Layer): self.outputs = list(outputs) else: self.outputs = [outputs] - - # Check for redundancy in inputs. - if len(set(self.inputs)) != len(self.inputs): - raise ValueError('The list of inputs passed to the model ' - 'is redundant. ' - 'All inputs should only appear once.' - ' Found: ' + str(self.inputs)) - for x in self.inputs: - # Check that x has appropriate `_keras_history` metadata. - if not hasattr(x, '_keras_history'): - cls_name = self.__class__.__name__ - raise ValueError('Input tensors to a ' + cls_name + ' ' + - 'must come from `tf.keras.Input`. ' - 'Received: ' + str(x) + - ' (missing previous layer metadata).') - # Check that x is an input tensor. - # pylint: disable=protected-access - layer, node_index, tensor_index = x._keras_history - if len(layer._inbound_nodes) > 1 or ( - layer._inbound_nodes and layer._inbound_nodes[0].inbound_layers): - cls_name = self.__class__.__name__ - logging.warning(cls_name + ' inputs must come from ' - '`tf.keras.Input` (thus holding past layer metadata), ' - 'they cannot be the output of ' - 'a previous non-Input layer. ' - 'Here, a tensor specified as ' - 'input to "' + self.name + '" was not an Input tensor, ' - 'it was generated by layer ' + layer.name + '.\n' - 'Note that input tensors are ' - 'instantiated via `tensor = tf.keras.Input(shape)`.\n' - 'The tensor that caused the issue was: ' + str(x.name)) - for x in self.outputs: - if not hasattr(x, '_keras_history'): - cls_name = self.__class__.__name__ - raise ValueError('Output tensors to a ' + cls_name + ' must be ' - 'the output of a TensorFlow `Layer` ' - '(thus holding past layer metadata). Found: ' + str(x)) + self._validate_graph_inputs_and_outputs() self._base_init(name=name) self._compute_previous_mask = ( @@ -258,10 +227,6 @@ class Network(base_layer.Layer): self._track_layers(layers) - # A Graph network supports defun-ed eager loops if all of its layers do. - self._can_use_graph_functions = all( - layer._can_use_graph_functions for layer in layers) - # Create the node linking internal inputs to internal outputs. base_layer.Node( outbound_layer=self, @@ -282,9 +247,7 @@ class Network(base_layer.Layer): if layer.is_placeholder: self._feed_input_names.append(layer.name) self._feed_input_shapes.append(backend.int_shape(self.inputs[i])) - # layer.input gives an error in eager mode - if not context.executing_eagerly(): - self._feed_inputs.append(layer.input) + self._feed_inputs.append(layer.input) for layer in self._output_layers: self.output_names.append(layer.name) @@ -301,16 +264,15 @@ class Network(base_layer.Layer): self.outputs = [] self.inputs = [] self.built = False - self._static_graph_friendly = True @property - def _is_static_graph_friendly(self): + def _static_graph_friendly(self): if self._is_graph_network: - return all(layer._is_static_graph_friendly for layer in self.layers) - return self._static_graph_friendly + return all(layer._static_graph_friendly for layer in self.layers) + return self._call_is_graph_friendly def _determine_call_convention(self, call_argspec): - """Decides how `self.call()` is invoked. See base_layer.CallConvention.""" + """Decides how `self.call()` is invoked. See `CallConvention`.""" if call_argspec.varargs: may_take_single_argument = False else: @@ -342,11 +304,11 @@ class Network(base_layer.Layer): "Model.call() takes a single positional argument (to which " "inputs are passed by convention) and a separate 'inputs' " "argument. Unable to determine which arguments are inputs.") - return base_layer.CallConvention.SINGLE_POSITIONAL_ARGUMENT + return base_layer_utils.CallConvention.SINGLE_POSITIONAL_ARGUMENT if 'inputs' in call_argspec.args: - return base_layer.CallConvention.EXPLICIT_INPUTS_ARGUMENT + return base_layer_utils.CallConvention.EXPLICIT_INPUTS_ARGUMENT else: - return base_layer.CallConvention.POSITIONAL_ARGUMENTS_ARE_INPUTS + return base_layer_utils.CallConvention.POSITIONAL_ARGUMENTS_ARE_INPUTS def _track_layers(self, layers): """Add Checkpointable dependencies on a list of Layers.""" @@ -415,44 +377,26 @@ class Network(base_layer.Layer): # simply by assigning them to attributes. not self._is_graph_network and isinstance(value, variables.Variable)): - self._extra_variables.append(value) + if value.trainable: + # Could already be added via `add_weight`. + if value not in self._trainable_weights: + self._trainable_weights.append(value) + else: + if value not in self._non_trainable_weights: + self._non_trainable_weights.append(value) + + # Keeping track of metric instance created in subclassed model/layer. + # We do this so that we can maintain the correct order of metrics by adding + # the instance to the `metrics` list as soon as it is created. + from tensorflow.python.keras import metrics as metrics_module # pylint: disable=g-import-not-at-top + if isinstance(value, metrics_module.Metric): + self._metrics.append(value) super(Network, self).__setattr__(name, value) - def add_variable(self, name, shape, dtype=None, initializer=None, - regularizer=None, trainable=True, constraint=None): - if self._is_graph_network: - raise NotImplementedError('`add_variable` is not supported on Networks.') - else: - raise NotImplementedError( - '`add_variable` is not supported on Networks. However, you may ' - 'assign variables to attributes and they will show up in the weights ' - 'and variables properties.') - - def add_weight(self, - name, - shape, - dtype=None, - initializer=None, - regularizer=None, - trainable=None, - constraint=None, - partitioner=None, - use_resource=None, - synchronization=variables.VariableSynchronization.AUTO, - aggregation=variables.VariableAggregation.NONE, - **kwargs): - if self._is_graph_network: - raise NotImplementedError('`add_weight` is not supported on Networks.') - else: - raise NotImplementedError( - '`add_weight` is not supported on Networks. However, you may ' - 'assign variables to attributes and they will show up in the weights ' - 'and variables properties.') - @property def stateful(self): - return any([(hasattr(layer, 'stateful') and layer.stateful) - for layer in self.layers]) + return any((hasattr(layer, 'stateful') and layer.stateful) + for layer in self.layers) def reset_states(self): for layer in self.layers: @@ -557,14 +501,13 @@ class Network(base_layer.Layer): @property def _unfiltered_updates(self): - if context.executing_eagerly(): - return [] updates = [] for layer in self.layers: if isinstance(layer, Network): updates += layer._unfiltered_updates else: updates += layer.updates + updates += self._updates return updates @property @@ -641,9 +584,6 @@ class Network(base_layer.Layer): Returns: A list of update ops. """ - if context.executing_eagerly(): - return [] - if not self.trainable and not self.stateful: return [] @@ -659,7 +599,7 @@ class Network(base_layer.Layer): else: relevant_inputs.append(inputs) if not relevant_inputs: - return updates + return list(set(updates)) reachable = tf_utils.get_reachable_from_inputs(relevant_inputs, updates) relevant_conditional_updates = [x for x in updates if x in reachable] @@ -667,8 +607,7 @@ class Network(base_layer.Layer): x for x in updates if x._unconditional_update] # pylint: disable=protected-access # A layer could be used multiple times in a nested structure, # so the updates list must be de-duped. - return list(set( - relevant_conditional_updates + unconditional_updates + self._updates)) + return list(set(relevant_conditional_updates + unconditional_updates)) @property def losses(self): @@ -728,14 +667,38 @@ class Network(base_layer.Layer): return checkpointable_layer_utils.gather_trainable_weights( trainable=self.trainable, sub_layers=self._layers, - extra_variables=self._extra_variables) + extra_variables=self._trainable_weights) @property def non_trainable_weights(self): return checkpointable_layer_utils.gather_non_trainable_weights( trainable=self.trainable, sub_layers=self._layers, - extra_variables=self._extra_variables) + extra_variables=self._non_trainable_weights + self._trainable_weights) + + @property + def metrics(self): + """Returns the network's symbolic metrics. + + Model overrides this function to include the metrics from `compile` API. + """ + metrics = [] + for layer in self.layers: + metrics += layer._metrics # pylint: disable=protected-access + return metrics + self._metrics + + @property + def _all_metrics_tensors(self): + """Returns the network's symbolic metric tensors.""" + # TODO(psv): Remove this property. + metrics_tensors = {} + for layer in self.layers: + if isinstance(layer, Network): + metrics_tensors.update(layer._all_metrics_tensors) + else: + metrics_tensors.update(layer._metrics_tensors) + metrics_tensors.update(self._metrics_tensors) + return metrics_tensors @property def input_spec(self): @@ -771,6 +734,11 @@ class Network(base_layer.Layer): This is to be used for subclassed models, which do not know at instantiation time what their inputs look like. + This method only exists for users who want to call `model.build()` in a + standalone way (as a substitute for calling the model on real data to + build it). It will never be called by the framework (and thus it will + never throw unexpected errors in an unrelated workflow). + Args: input_shape: Single tuple, TensorShape, or list of shapes, where shapes are tuples, integers, or TensorShapes. @@ -807,48 +775,53 @@ class Network(base_layer.Layer): # in a Graph. Since tf.Variable is compatible with both eager execution # and graph building, the variables created after building the model in # a Graph are still valid when executing eagerly. - with context.graph_mode(): - graph = func_graph.FuncGraph('graph') - with graph.as_default(): - if isinstance(input_shape, list): - x = [base_layer.generate_placeholders_from_shape(shape) - for shape in input_shape] + if context.executing_eagerly(): + graph = func_graph.FuncGraph('build_graph') + else: + graph = backend.get_graph() + with graph.as_default(): + if isinstance(input_shape, list): + x = [base_layer_utils.generate_placeholders_from_shape(shape) + for shape in input_shape] + else: + x = base_layer_utils.generate_placeholders_from_shape(input_shape) + + kwargs = {} + call_signature = tf_inspect.getfullargspec(self.call) + call_args = call_signature.args + # Exclude `self`, `inputs`, and any argument with a default value. + if len(call_args) > 2: + if call_signature.defaults: + call_args = call_args[2:-len(call_signature.defaults)] else: - x = base_layer.generate_placeholders_from_shape(input_shape) - - kwargs = {} - num_call_args = len(tf_inspect.getfullargspec(self.call).args) - if self._expects_training_arg and num_call_args == 3: - # Has call signature of call(self, input, training) - kwargs['training'] = False - elif num_call_args > 2: - # Has invalid call signature of call(self, input, *args, **kwargs) - raise ValueError('Currently, you cannot build your model if it has ' - 'positional or keyword arguments that are not ' - 'inputs to the model, but are required for its ' - '`call` method. Instead, in order to instantiate ' - 'and build your model, `call` your model on real ' - 'tensor data with all expected call arguments.') - - try: - self.call(x, **kwargs) - except (errors.InvalidArgumentError, TypeError): - raise ValueError('You cannot build your model by calling `build` ' - 'if your layers do not support float type inputs. ' - 'Instead, in order to instantiate and build your ' - 'model, `call` your model on real tensor data (of ' - 'the correct dtype).') - + call_args = call_args[2:] + for arg in call_args: + if arg == 'training': + # Case where `training` is a positional arg with no default. + kwargs['training'] = False + else: + # Has invalid call signature with unknown positional arguments. + raise ValueError( + 'Currently, you cannot build your model if it has ' + 'positional or keyword arguments that are not ' + 'inputs to the model, but are required for its ' + '`call` method. Instead, in order to instantiate ' + 'and build your model, `call` your model on real ' + 'tensor data with all expected call arguments.') + elif len(call_args) < 2: + # Signature without `inputs`. + raise ValueError('You can only call `build` on a model if its `call` ' + 'method accepts an `inputs` argument.') + try: + self.call(x, **kwargs) + except (errors.InvalidArgumentError, TypeError): + raise ValueError('You cannot build your model by calling `build` ' + 'if your layers do not support float type inputs. ' + 'Instead, in order to instantiate and build your ' + 'model, `call` your model on real tensor data (of ' + 'the correct dtype).') if self._layers: self._track_layers(self._layers) - if self.layers: - for layer in self.layers: - if not layer.built: - raise ValueError('Layer: {} was not built in your model. Calling ' - '`build` manually on a subclassed model is only ' - 'allowed for models with a static topology. ' - 'In this case, you can build your model by ' - 'calling it on real tensor data.'.format(layer)) self.built = True def call(self, inputs, training=None, mask=None): @@ -895,9 +868,7 @@ class Network(base_layer.Layer): def compute_output_shape(self, input_shape): if not self._is_graph_network: - if context.executing_eagerly(): - return super(Network, self).compute_output_shape(input_shape) - raise NotImplementedError + return super(Network, self).compute_output_shape(input_shape) if isinstance(input_shape, list): input_shapes = [] @@ -1686,6 +1657,62 @@ class Network(base_layer.Layer): positions=positions, print_fn=print_fn) + def _validate_graph_inputs_and_outputs(self): + """Validates the inputs and outputs of a Graph Network.""" + # Check for redundancy in inputs. + if len(set(self.inputs)) != len(self.inputs): + raise ValueError('The list of inputs passed to the model ' + 'is redundant. ' + 'All inputs should only appear once.' + ' Found: ' + str(self.inputs)) + + for x in self.inputs: + # Check that x has appropriate `_keras_history` metadata. + if not hasattr(x, '_keras_history'): + cls_name = self.__class__.__name__ + raise ValueError('Input tensors to a ' + cls_name + ' ' + + 'must come from `tf.keras.Input`. ' + 'Received: ' + str(x) + + ' (missing previous layer metadata).') + # Check that x is an input tensor. + # pylint: disable=protected-access + layer, _, _ = x._keras_history + if len(layer._inbound_nodes) > 1 or ( + layer._inbound_nodes and layer._inbound_nodes[0].inbound_layers): + cls_name = self.__class__.__name__ + logging.warning(cls_name + ' inputs must come from ' + '`tf.keras.Input` (thus holding past layer metadata), ' + 'they cannot be the output of ' + 'a previous non-Input layer. ' + 'Here, a tensor specified as ' + 'input to "' + self.name + '" was not an Input tensor, ' + 'it was generated by layer ' + layer.name + '.\n' + 'Note that input tensors are ' + 'instantiated via `tensor = tf.keras.Input(shape)`.\n' + 'The tensor that caused the issue was: ' + str(x.name)) + + # Check compatibility of batch sizes of Input Layers. + input_batch_sizes = [ + training_utils.get_static_batch_size(x._keras_history[0]) + for x in self.inputs + ] + consistent_batch_size = None + for batch_size in input_batch_sizes: + if batch_size is not None: + if (consistent_batch_size is not None and + batch_size != consistent_batch_size): + raise ValueError('The specified batch sizes of the Input Layers' + ' are incompatible. Found batch sizes: {}'.format( + input_batch_sizes)) + consistent_batch_size = batch_size + + for x in self.outputs: + if not hasattr(x, '_keras_history'): + cls_name = self.__class__.__name__ + raise ValueError('Output tensors to a ' + cls_name + ' must be ' + 'the output of a TensorFlow `Layer` ' + '(thus holding past layer metadata). Found: ' + str(x)) + def _is_hdf5_filepath(filepath): return (filepath.endswith('.h5') or filepath.endswith('.keras') or diff --git a/tensorflow/python/keras/engine/saving.py b/tensorflow/python/keras/engine/saving.py index 61bff7fff2..54d9e32fb2 100644 --- a/tensorflow/python/keras/engine/saving.py +++ b/tensorflow/python/keras/engine/saving.py @@ -79,6 +79,10 @@ def save_model(model, filepath, overwrite=True, include_optimizer=True): from tensorflow.python.keras import __version__ as keras_version # pylint: disable=g-import-not-at-top + # TODO(psv) Add warning when we save models that contain non-serializable + # entities like metrics added using `add_metric` and losses added using + # `add_loss.` + if not isinstance(filepath, h5py.File): # If file exists and should not be overwritten. if not overwrite and os.path.isfile(filepath): @@ -126,8 +130,8 @@ def save_model(model, filepath, overwrite=True, include_optimizer=True): 'config': model.optimizer.get_config() }, 'loss': model.loss, - 'metrics': model.metrics, - 'weighted_metrics': model.weighted_metrics, + 'metrics': model._compile_metrics, + 'weighted_metrics': model._compile_weighted_metrics, 'sample_weight_mode': model.sample_weight_mode, 'loss_weights': model.loss_weights, }, @@ -913,7 +917,7 @@ def save_attributes_to_hdf5_group(group, name, data): chunked_data = np.array_split(data_npy, num_chunks) # This will never loop forever thanks to the test above. - while any([x.nbytes > HDF5_OBJECT_HEADER_LIMIT for x in chunked_data]): + while any(x.nbytes > HDF5_OBJECT_HEADER_LIMIT for x in chunked_data): num_chunks += 1 chunked_data = np.array_split(data_npy, num_chunks) diff --git a/tensorflow/python/keras/engine/saving_test.py b/tensorflow/python/keras/engine/saving_test.py index f376f081cf..6d9d9a2fca 100644 --- a/tensorflow/python/keras/engine/saving_test.py +++ b/tensorflow/python/keras/engine/saving_test.py @@ -32,6 +32,7 @@ from tensorflow.python.framework import ops from tensorflow.python.framework import test_util from tensorflow.python.keras.engine import saving from tensorflow.python.keras.engine import training +from tensorflow.python.lib.io import file_io from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops from tensorflow.python.platform import test @@ -288,6 +289,7 @@ class TestWeightSavingAndLoading(test.TestCase, parameterized.TestCase): r'element\(s\)\.'): saving.load_weights_from_hdf5_group_by_name(f_model, model.layers) + @test_util.run_deprecated_v1 def test_sequential_weight_loading_group_name_with_incorrect_shape(self): if h5py is None: return @@ -330,6 +332,7 @@ class TestWeightSavingAndLoading(test.TestCase, parameterized.TestCase): class TestWholeModelSaving(test.TestCase): + @test_util.run_deprecated_v1 def test_sequential_model_saving(self): if h5py is None: self.skipTest('h5py required to run this test') @@ -382,6 +385,7 @@ class TestWholeModelSaving(test.TestCase): out2 = new_model.predict(x) self.assertAllClose(out, out2, atol=1e-05) + @test_util.run_deprecated_v1 def test_sequential_model_saving_without_input_shape(self): if h5py is None: self.skipTest('h5py required to run this test') @@ -442,6 +446,7 @@ class TestWholeModelSaving(test.TestCase): out2 = new_model.predict(x) self.assertAllClose(out, out2, atol=1e-05) + @test_util.run_deprecated_v1 def test_sequential_model_saving_2(self): if h5py is None: self.skipTest('h5py required to run this test') @@ -478,6 +483,7 @@ class TestWholeModelSaving(test.TestCase): out2 = model.predict(x) self.assertAllClose(out, out2, atol=1e-05) + @test_util.run_deprecated_v1 def test_functional_model_saving(self): if h5py is None: self.skipTest('h5py required to run this test') @@ -629,6 +635,7 @@ class TestWholeModelSaving(test.TestCase): os.close(fd) os.remove(fname) + @test_util.run_deprecated_v1 def test_saving_model_with_long_weights_names(self): if h5py is None: self.skipTest('h5py required to run this test') @@ -674,6 +681,7 @@ class TestWholeModelSaving(test.TestCase): os.close(fd) os.remove(fname) + @test_util.run_deprecated_v1 def test_model_saving_to_pre_created_h5py_file(self): if h5py is None: self.skipTest('h5py required to run this test') @@ -715,7 +723,6 @@ class TestWholeModelSaving(test.TestCase): os.close(fd) os.remove(fname) - def test_saving_constant_initializer_with_numpy(self): if h5py is None: self.skipTest('h5py required to run this test') @@ -749,6 +756,7 @@ class SubclassedModel(training.Model): class TestWeightSavingAndLoadingTFFormat(test.TestCase): + @test_util.run_deprecated_v1 def test_keras_optimizer_warning(self): graph = ops.Graph() with graph.as_default(), self.session(graph): @@ -992,5 +1000,57 @@ class TestWeightSavingAndLoadingTFFormat(test.TestCase): AssertionError, 'Nothing except the root object matched'): m.load_weights(save_path) + @test_util.run_in_graph_and_eager_modes + def test_directory_passed(self): + m = keras.Model() + v = m.add_weight(name='v', shape=[]) + self.evaluate(v.assign(42.)) + prefix = os.path.join(self.get_temp_dir(), '{}'.format(ops.uid()), 'ckpt/') + m.save_weights(prefix) + self.evaluate(v.assign(2.)) + m.load_weights(prefix) + self.assertEqual(42., self.evaluate(v)) + + @test_util.run_in_graph_and_eager_modes + def test_relative_path(self): + m = keras.Model() + v = m.add_weight(name='v', shape=[]) + os.chdir(self.get_temp_dir()) + + prefix = 'ackpt' + self.evaluate(v.assign(42.)) + m.save_weights(prefix) + self.assertTrue(file_io.file_exists('ackpt.index')) + self.evaluate(v.assign(1.)) + m.load_weights(prefix) + self.assertEqual(42., self.evaluate(v)) + + prefix = 'subdir/ackpt' + self.evaluate(v.assign(43.)) + m.save_weights(prefix) + self.assertTrue(file_io.file_exists('subdir/ackpt.index')) + self.evaluate(v.assign(2.)) + m.load_weights(prefix) + self.assertEqual(43., self.evaluate(v)) + + prefix = 'ackpt/' + self.evaluate(v.assign(44.)) + m.save_weights(prefix) + self.assertTrue(file_io.file_exists('ackpt/.index')) + self.evaluate(v.assign(3.)) + m.load_weights(prefix) + self.assertEqual(44., self.evaluate(v)) + + @test_util.run_in_graph_and_eager_modes + def test_nonexistant_prefix_directory(self): + m = keras.Model() + v = m.add_weight(name='v', shape=[]) + self.evaluate(v.assign(42.)) + prefix = os.path.join(self.get_temp_dir(), '{}'.format(ops.uid()), 'bckpt') + m.save_weights(prefix) + self.evaluate(v.assign(2.)) + m.load_weights(prefix) + self.assertEqual(42., self.evaluate(v)) + if __name__ == '__main__': test.main() diff --git a/tensorflow/python/keras/engine/sequential.py b/tensorflow/python/keras/engine/sequential.py index 5ce4ca4df4..3255613f6a 100644 --- a/tensorflow/python/keras/engine/sequential.py +++ b/tensorflow/python/keras/engine/sequential.py @@ -25,6 +25,7 @@ from tensorflow.python.eager import context from tensorflow.python.framework import ops from tensorflow.python.keras import layers as layer_module from tensorflow.python.keras.engine import base_layer +from tensorflow.python.keras.engine import training_utils from tensorflow.python.keras.engine.input_layer import Input from tensorflow.python.keras.engine.input_layer import InputLayer from tensorflow.python.keras.engine.network import Network @@ -120,8 +121,8 @@ class Sequential(Model): return layers[:] @property - def _is_static_graph_friendly(self): - return all(layer._is_static_graph_friendly for layer in self.layers) + def _static_graph_friendly(self): + return all(layer._static_graph_friendly for layer in self.layers) @checkpointable.no_automatic_dependency_tracking def add(self, layer): @@ -150,7 +151,7 @@ class Sequential(Model): assert len(layer._inbound_nodes[-1].output_tensors) == 1 set_inputs = True else: - batch_shape, dtype = get_input_shape_and_dtype(layer) + batch_shape, dtype = training_utils.get_input_shape_and_dtype(layer) if batch_shape: # Instantiate an input layer. x = Input( @@ -190,8 +191,6 @@ class Sequential(Model): self._layers.append(layer) if self._layers: self._track_layers(self._layers) - self._can_use_graph_functions = all( - layer._can_use_graph_functions for layer in self.layers) @checkpointable.no_automatic_dependency_tracking def pop(self): @@ -213,23 +212,17 @@ class Sequential(Model): self.outputs = [self.layers[-1].output] self._init_graph_network(self.inputs, self.outputs, name=self.name) self.built = True - self._can_use_graph_functions = all( - layer._can_use_graph_functions for layer in self.layers) + @base_layer.default def build(self, input_shape=None): if self._is_graph_network: self._init_graph_network(self.inputs, self.outputs, name=self.name) else: if input_shape is None: raise ValueError('You must provide an `input_shape` argument.') + input_shape = tuple(input_shape) self._build_input_shape = input_shape - shape = input_shape - for layer in self.layers: - if not layer.built: - with ops.name_scope(layer._name_scope()): - layer.build(shape) - layer.built = True - shape = layer.compute_output_shape(shape) + super(Sequential, self).build(input_shape) self.built = True def call(self, inputs, training=None, mask=None): @@ -241,8 +234,8 @@ class Sequential(Model): return outputs def _call_and_compute_mask(self, inputs, training=None, mask=None): - if not self.built: - self.build(inputs.shape) + if not self.built and self._is_graph_network: + self._init_graph_network(self.inputs, self.outputs, name=self.name) x = inputs for layer in self.layers: @@ -255,6 +248,11 @@ class Sequential(Model): if isinstance(layer, Network) and layer._compute_output_and_mask_jointly: x, mask = layer._call_and_compute_mask(x, **kwargs) else: + if not layer.built: + # Build layer if applicable. + with ops.name_scope(layer._name_scope()): + layer._maybe_build(x) + layer.built = True x = layer.call(x, **kwargs) if layer.supports_masking: mask = layer.compute_mask(x, mask) @@ -362,38 +360,3 @@ class Sequential(Model): if self.layers and hasattr(self.layers[0], 'input_spec'): return self.layers[0].input_spec return None - - -def get_input_shape_and_dtype(layer): - """Retrieve input shape and input dtype of layer if applicable. - - Args: - layer: Layer (or model) instance. - - Returns: - Tuple (input_shape, input_dtype). Both could be None if the layer - does not have a defined input shape. - - Raises: - ValueError: in case an empty Sequential or Graph Network is passed. - """ - if ((isinstance(layer, Model) and layer._is_graph_network) - or isinstance(layer, Sequential)): - # We were passed a model as first layer. - # This requires a specific way to figure out the - # input shape and dtype. - if not layer.layers: - raise ValueError('Cannot add an empty model ' - 'to a `Sequential` model.') - # In case of nested models: recover the first layer - # of the deepest model to infer input shape and dtype. - layer = layer.layers[0] - while ((isinstance(layer, Model) and layer._is_graph_network) - or isinstance(layer, Sequential)): - layer = layer.layers[0] - - if hasattr(layer, '_batch_input_shape'): - batch_shape = layer._batch_input_shape - dtype = layer.dtype - return batch_shape, dtype - return None, None diff --git a/tensorflow/python/keras/engine/sequential_test.py b/tensorflow/python/keras/engine/sequential_test.py index ea8fdf675a..b6d2510897 100644 --- a/tensorflow/python/keras/engine/sequential_test.py +++ b/tensorflow/python/keras/engine/sequential_test.py @@ -124,7 +124,7 @@ class TestSequential(test.TestCase, parameterized.TestCase): dataset = dataset_ops.Dataset.from_tensor_slices((x, y)) dataset = dataset.repeat(100) dataset = dataset.batch(10) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) model.fit(iterator, epochs=1, steps_per_epoch=steps_per_epoch) self.assertTrue(model.built) @@ -132,6 +132,7 @@ class TestSequential(test.TestCase, parameterized.TestCase): self.assertFalse(model._is_graph_network) @parameterized.parameters((True,), (False,)) + @tf_test_util.run_deprecated_v1 def test_training_and_eval_methods_on_symbolic_tensors(self, deferred): with self.cached_session(): @@ -219,6 +220,7 @@ class TestSequential(test.TestCase, parameterized.TestCase): inner_model.trainable = True self.assertEqual(len(model.trainable_weights), 4) + @tf_test_util.run_deprecated_v1 def test_sequential_update_disabling(self): val_a = np.random.random((10, 4)) val_out = np.random.random((10, 4)) @@ -294,7 +296,6 @@ class TestSequential(test.TestCase, parameterized.TestCase): model.build((None, 10)) self.assertTrue(model.built) - self.assertTrue(model.layers[-1].built) self.assertEqual(len(model.weights), 8) @tf_test_util.run_in_graph_and_eager_modes @@ -362,29 +363,6 @@ class TestSequentialEagerIntegration(test.TestCase): y = np.random.random((2, 5)) model.fit(x, y, epochs=1) - @tf_test_util.run_in_graph_and_eager_modes - def test_sequential_can_use_graph_functions(self): - model = testing_utils.get_small_sequential_mlp(4, 3) - self.assertTrue(model._can_use_graph_functions) - inner_model = testing_utils.get_small_sequential_mlp(4, 5) - model.add(inner_model) - - self.assertTrue(model._can_use_graph_functions) - - inner_model_two = testing_utils.get_small_sequential_mlp(5, 7) - self.assertTrue(inner_model_two._can_use_graph_functions) - - layer = keras.layers.Lambda(lambda x: x) - layer._can_use_graph_functions = False - inner_model_two.add(layer) - self.assertFalse(inner_model_two._can_use_graph_functions) - - model.add(inner_model_two) - self.assertFalse(model._can_use_graph_functions) - - model.pop() - self.assertTrue(model._can_use_graph_functions) - @tf_test_util.run_in_graph_and_eager_modes def test_sequential_model_fails_with_dict_inputs(self): num_classes = 5 diff --git a/tensorflow/python/keras/engine/topology_test.py b/tensorflow/python/keras/engine/topology_test.py index b4a4babf25..03bfd35589 100644 --- a/tensorflow/python/keras/engine/topology_test.py +++ b/tensorflow/python/keras/engine/topology_test.py @@ -42,6 +42,7 @@ except ImportError: class TopologyConstructionTest(test.TestCase): + @test_util.run_deprecated_v1 def test_get_updates(self): class MyLayer(keras.layers.Layer): @@ -115,6 +116,7 @@ class TopologyConstructionTest(test.TestCase): self.assertEqual(len(layer.get_updates_for(x1)), 2) self.assertEqual(len(layer.get_updates_for(None)), 0) + @test_util.run_deprecated_v1 def test_get_losses(self): class MyLayer(keras.layers.Layer): @@ -268,6 +270,7 @@ class TopologyConstructionTest(test.TestCase): self.assertEqual(test_layer.input_shape, [(None, 32), (None, 32)]) self.assertEqual(test_layer.output_shape, (None, 32)) + @test_util.run_deprecated_v1 def testBasicNetwork(self): # minimum viable network x = input_layer_lib.Input(shape=(32,)) @@ -341,6 +344,7 @@ class TopologyConstructionTest(test.TestCase): self.assertListEqual(model.trainable_weights, []) self.assertListEqual(model.non_trainable_weights, weights) + @test_util.run_deprecated_v1 def test_layer_call_arguments(self): # Test the ability to pass and serialize arguments to `call`. inp = keras.layers.Input(shape=(2,)) @@ -491,6 +495,7 @@ class TopologyConstructionTest(test.TestCase): fn_outputs = fn([input_a_np, input_b_np]) self.assertListEqual([x.shape for x in fn_outputs], [(10, 64), (10, 5)]) + @test_util.run_deprecated_v1 def test_recursion(self): with self.cached_session(): a = keras.layers.Input(shape=(32,), name='input_a') @@ -675,6 +680,7 @@ class TopologyConstructionTest(test.TestCase): with self.assertRaises(Exception): keras.models.Model([j, k], [m, n, 0]) + @test_util.run_deprecated_v1 def test_raw_tf_compatibility(self): # test calling layers/models on TF tensors a = keras.layers.Input(shape=(32,), name='input_a') @@ -719,6 +725,7 @@ class TopologyConstructionTest(test.TestCase): model = keras.models.Model(a, b) self.assertEqual(model.output_mask.get_shape().as_list(), [None, 10]) + @test_util.run_deprecated_v1 def testMaskingSingleInput(self): class MaskedLayer(keras.layers.Layer): @@ -756,6 +763,7 @@ class TopologyConstructionTest(test.TestCase): y_2 = network(x_2) self.assertEqual(y_2.get_shape().as_list(), [None, 32]) + @test_util.run_deprecated_v1 def test_activity_regularization_with_model_composition(self): def reg(x): @@ -825,6 +833,7 @@ class TopologyConstructionTest(test.TestCase): output_val_2 = m2.predict(x_val) self.assertAllClose(output_val, output_val_2, atol=1e-6) + @test_util.run_deprecated_v1 def test_explicit_training_argument(self): with self.cached_session(): a = keras.layers.Input(shape=(2,)) @@ -1145,6 +1154,7 @@ class DefaultShapeInferenceBehaviorTest(test.TestCase): class GraphUtilsTest(test.TestCase): + @test_util.run_deprecated_v1 def testGetReachableFromInputs(self): with self.cached_session(): diff --git a/tensorflow/python/keras/engine/training.py b/tensorflow/python/keras/engine/training.py index cb96e3e5d2..2236bcf27c 100644 --- a/tensorflow/python/keras/engine/training.py +++ b/tensorflow/python/keras/engine/training.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import collections import weakref import numpy as np @@ -26,6 +27,7 @@ from tensorflow.python.data.ops import iterator_ops from tensorflow.python.eager import context from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import tensor_util from tensorflow.python.keras import backend as K from tensorflow.python.keras import losses @@ -40,6 +42,8 @@ from tensorflow.python.keras.engine import training_utils from tensorflow.python.keras.engine.network import Network from tensorflow.python.keras.utils import data_utils from tensorflow.python.keras.utils.generic_utils import slice_arrays +from tensorflow.python.keras.utils.losses_utils import squeeze_or_expand_dimensions +from tensorflow.python.ops import math_ops from tensorflow.python.platform import tf_logging as logging from tensorflow.python.training import optimizer as tf_optimizer_module from tensorflow.python.training.checkpointable import base as checkpointable @@ -121,11 +125,8 @@ class Model(Network): # initializing _distribution_strategy here since it is possible to call # predict on a model without compiling it. self._distribution_strategy = None - # This flag must be disabled upon model mutation, such as changing the model - # layers or recompiling the model to use a different optimizer. New function - # definitions are generated whenever this flag is disabled, ensuring that - # internal graph functions are always using the current model structure. - self._built_graph_functions = False + + self.run_eagerly = None def _set_sample_weight_attributes(self, sample_weight_mode, skip_target_weighing_indices): @@ -177,25 +178,66 @@ class Model(Network): metric_name = '%s_%s' % (self.output_names[output_index], metric_name) j = 1 base_metric_name = metric_name - while metric_name in self.metrics_names: + while metric_name in self._compile_metrics_names: metric_name = '%s_%d' % (base_metric_name, j) j += 1 return metric_name + @property + def metrics(self): + """Returns the model's metrics added using `compile`, `add_metric` APIs.""" + metrics = [] + if self._is_compiled: + metrics += self._compile_stateful_metric_functions + return metrics + super(Model, self).metrics + + @property + def metrics_names(self): + """Returns the model's display labels for all outputs.""" + metrics_names = [] + if self._is_compiled: + metrics_names += self._compile_metrics_names # Includes names of losses. + + # Add metric names from layers. + for layer in self.layers: + metrics_names += [m.name for m in layer._metrics] # pylint: disable=protected-access + metrics_names += [m.name for m in self._metrics] + return metrics_names + + @property + def _all_metrics_tensors(self): + """Returns the network's symbolic metric tensors.""" + metrics_tensors = {} + if self._is_compiled: + metrics_tensors.update(self._compile_metrics_tensors) + metrics_tensors.update(super(Model, self)._all_metrics_tensors) + return metrics_tensors + + @property + def _all_stateful_metrics_tensors(self): + """Returns the network's symbolic metric tensors.""" + metrics_tensors = {} + if self._is_compiled: + metrics_tensors.update(self._compile_stateful_metrics_tensors) + metrics_tensors.update(super(Model, self)._all_metrics_tensors) + return metrics_tensors + def _init_metric_attributes(self): """Initialized model metric attributes.""" # List of all metric names in the model. - self.metrics_names = ['loss'] - # List of all aggregated metric result tensors. This includes aggregated - # loss result tensors. - self._stateful_metrics_tensors = [] - # List of all metric result tensors (aggregated or not - based on the - # values given in compile.) - self.metrics_tensors = [] + self._compile_metrics_names = ['loss'] # List of stateful metric functions. Used for resetting metric state during - # training/eval. This includes loss functions. - self.stateful_metric_functions = [] + # training/eval. + # This includes loss functions when there are multiple outputs. + self._compile_stateful_metric_functions = [] + # Dict of all aggregated metric result tensors. This includes aggregated + # loss result tensors when there are multiple outputs. + self._compile_stateful_metrics_tensors = {} + # Dict of all metric result tensors (aggregated or not - based on the + # values given in compile.). This includes aggregated loss result tensors + # when there are multiple outputs. + self._compile_metrics_tensors = {} def _set_per_output_metric_attributes(self, metrics_dict, output_index): """Sets the metric attributes on the model for the given output. @@ -204,24 +246,39 @@ class Model(Network): metrics_dict: A dict with metric names as keys and metric fns as values. output_index: The index of the model output for which the metric attributes are added. + + Returns: + Metrics dict updated with unique metric names as keys. """ - for metric_name, (_, stateful_metric_fn) in metrics_dict.items(): + updated_metrics_dict = collections.OrderedDict() + for metric_name, (metric_fn, stateful_metric_fn) in metrics_dict.items(): metric_name = self._add_unique_metric_name(metric_name, output_index) - # Keep track of metric name. - self.metrics_names.append(metric_name) - - # Keep track of stateful metric function. - self.stateful_metric_functions.append(stateful_metric_fn) + updated_metrics_dict[metric_name] = (metric_fn, stateful_metric_fn) + # Keep track of metric name, function and stateful function. + self._compile_metrics_names.append(metric_name) + self._compile_stateful_metric_functions.append(stateful_metric_fn) + return updated_metrics_dict def _set_metric_attributes(self, outputs, skip_target_indices=None): """Sets the metric attributes on the model for all the model outputs.""" skip_target_indices = skip_target_indices or [] + updated_per_output_metrics = [] + updated_per_output_weighted_metrics = [] for i in range(len(outputs)): if i in skip_target_indices: + updated_per_output_metrics.append(self._per_output_metrics[i]) + updated_per_output_weighted_metrics.append( + self._per_output_weighted_metrics[i]) continue - self._set_per_output_metric_attributes(self._per_output_metrics[i], i) - self._set_per_output_metric_attributes( - self._per_output_weighted_metrics[i], i) + updated_per_output_metrics.append( + self._set_per_output_metric_attributes(self._per_output_metrics[i], + i)) + updated_per_output_weighted_metrics.append( + self._set_per_output_metric_attributes( + self._per_output_weighted_metrics[i], i)) + + self._per_output_metrics = updated_per_output_metrics + self._per_output_weighted_metrics = updated_per_output_weighted_metrics def _handle_per_output_metrics(self, metrics_dict, @@ -256,17 +313,17 @@ class Model(Network): weighted_metric_fn = training_utils.weighted_masked_objective(fn) return weighted_metric_fn(y_true, y_pred, weights=weights, mask=mask) - def _track_metric_tensors(stateless_result, stateful_result): - self.metrics_tensors.append(stateless_result) - self._stateful_metrics_tensors.append(stateful_result) + def _track_metric_tensors(name, stateless_result, stateful_result): + self._compile_metrics_tensors[name] = stateless_result + self._compile_stateful_metrics_tensors[name] = stateful_result if isinstance(metric_fn, metrics_module.Metric): # If the given metric fn is stateful, call the fn and return result. metric_result = _call_stateful_fn(metric_fn) metric_results.append(metric_result) - if not context.executing_eagerly(): - _track_metric_tensors(metric_result, metric_result) - elif context.executing_eagerly(): + if not self.run_eagerly: + _track_metric_tensors(metric_name, metric_result, metric_result) + elif self.run_eagerly: # In eager mode, if the given metric fn is not stateful, we invoke the # given fn or its stateful version based on the given flag. if return_stateful_result: @@ -279,7 +336,8 @@ class Model(Network): # stateless fns. stateful_metric_result = _call_stateful_fn(stateful_fn) metric_result = _call_stateless_fn(metric_fn) - _track_metric_tensors(metric_result, stateful_metric_result) + _track_metric_tensors(metric_name, metric_result, + stateful_metric_result) return metric_results @@ -307,6 +365,7 @@ class Model(Network): skip_target_indices = skip_target_indices or [] metric_results = [] with K.name_scope('metrics'): + # Invoke all metrics added using `compile`. for i in range(len(outputs)): if i in skip_target_indices: continue @@ -328,8 +387,48 @@ class Model(Network): output_mask, weights=sample_weights[i], return_stateful_result=return_stateful_result)) + + # Add metric results from the `add_metric` metrics in eager mode. + if context.executing_eagerly(): + for m in self.metrics: + if m not in self._compile_stateful_metric_functions: + metric_results.append(m.result()) return metric_results + @property + def run_eagerly(self): + """Settable attribute indicating whether the model should run eagerly. + + Running eagerly means that your model will be run step by step, + like Python code. Your model might run slower, but it should become easier + for you to debug it by stepping into individual layer calls. + + By default, we will attempt to compile your model to a static graph to + deliver the best execution performance. + + Returns: + Boolean, whether the model should run eagerly. + """ + if self._run_eagerly is True and not context.executing_eagerly(): + raise ValueError('You can only set `run_eagerly=True` if eager execution ' + 'is enabled.') + if self._static_graph_friendly: + if self._run_eagerly is None: + return False + else: + return self._run_eagerly + else: + if self._run_eagerly is False: + # TODO(fchollet): consider using py_func to enable this. + raise ValueError('Your model contains layers that can only be ' + 'successfully run in eager execution. ' + 'You cannot set `run_eagerly=False`.') + return context.executing_eagerly() + + @run_eagerly.setter + def run_eagerly(self, value): + self._run_eagerly = value + @checkpointable.no_automatic_dependency_tracking def compile(self, optimizer, @@ -391,9 +490,8 @@ class Model(Network): ValueError: In case of invalid arguments for `optimizer`, `loss`, `metrics` or `sample_weight_mode`. """ - # The correct graph function may have changed, - # already-built ones must be updated - self._built_graph_functions = False + run_eagerly = kwargs.pop('run_eagerly', None) + self._run_eagerly = run_eagerly # Validate that arguments passed by the user to `compile` are supported by # DistributionStrategy. @@ -403,9 +501,6 @@ class Model(Network): raise NotImplementedError( 'optimizer must be an instance of ' 'tf.train.Optimizer, not a %s' % type(optimizer)) - if context.executing_eagerly(): - raise NotImplementedError('DistributionStrategy is not supported ' - 'when eager execution is enabled.') if sample_weight_mode: raise NotImplementedError('sample_weight_mode is not supported with ' 'DistributionStrategy.') @@ -417,11 +512,12 @@ class Model(Network): 'DistributionStrategy.') loss = loss or {} - if context.executing_eagerly() and not isinstance( + if self.run_eagerly and not isinstance( optimizer, (tf_optimizer_module.Optimizer, optimizers.TFOptimizer)): raise ValueError( - 'optimizer must be an instance of tf.train.Optimizer, not ' - 'a %s' % type(optimizer)) + 'When running a model in eager execution, the optimizer must be an ' + 'instance of tf.train.Optimizer. Received: ' + '%s' % optimizer) self.optimizer = optimizers.get(optimizer) # We've disabled automatic dependency tracking for this method, but do want @@ -430,12 +526,14 @@ class Model(Network): self._track_checkpointable( self.optimizer, name='optimizer', overwrite=True) self.loss = loss - self.metrics = metrics or [] + self._compile_metrics = metrics or [] self.loss_weights = loss_weights self.sample_weight_mode = sample_weight_mode - self.weighted_metrics = weighted_metrics - if context.executing_eagerly() and target_tensors is not None: - raise ValueError('target_tensors is not supported in Eager mode.') + self._compile_weighted_metrics = weighted_metrics + if self.run_eagerly and target_tensors is not None: + raise ValueError( + 'target_tensors argument is not supported when ' + 'running a model eagerly.') self.target_tensors = target_tensors # Set DistributionStrategy specific parameters. @@ -445,6 +543,8 @@ class Model(Network): if self._distribution_strategy is not None: distributed_training_utils.configure_and_create_session( self._distribution_strategy) + # Initialize model metric attributes. + self._init_metric_attributes() if not self.built: # Model is not compilable because it does not know its number of inputs # and outputs, nor their shapes and names. We will compile after the first @@ -468,16 +568,16 @@ class Model(Network): '" missing from loss dictionary. We assume ' 'this was done on purpose. The fit and evaluate APIs will not be ' 'expecting any data to be passed to "' + name + '".') - loss_functions.append(losses.get(loss.get(name))) + loss_functions.append(training_utils.get_loss_function(loss.get(name))) elif isinstance(loss, list): if len(loss) != len(self.outputs): raise ValueError('When passing a list as loss, ' 'it should have one entry per model outputs. ' 'The model has ' + str(len(self.outputs)) + ' outputs, but you passed loss=' + str(loss)) - loss_functions = [losses.get(l) for l in loss] + loss_functions = [training_utils.get_loss_function(l) for l in loss] else: - loss_function = losses.get(loss) + loss_function = training_utils.get_loss_function(loss) loss_functions = [loss_function for _ in range(len(self.outputs))] self.loss_functions = loss_functions @@ -493,7 +593,7 @@ class Model(Network): skip_target_weighing_indices.append(i) # Prepare output masks. - if not context.executing_eagerly(): + if not self.run_eagerly: masks = [getattr(x, '_keras_mask', None) for x in self.outputs] if not isinstance(masks, list): masks = [masks] @@ -524,11 +624,8 @@ class Model(Network): str(loss_weights) + ' - expected a list of dicts.') self.loss_weights_list = loss_weights_list - # Initialize model metric attributes. - self._init_metric_attributes() - # Initialization for Eager mode execution. - if context.executing_eagerly(): + if self.run_eagerly: # Prepare sample weights. self._set_sample_weight_attributes(sample_weight_mode, skip_target_weighing_indices) @@ -541,7 +638,7 @@ class Model(Network): self.total_loss = None for i in range(len(self.outputs)): if len(self.outputs) > 1: - self.metrics_names.append(self.output_names[i] + '_loss') + self._compile_metrics_names.append(self.output_names[i] + '_loss') # Set metric attributes on model. self._set_metric_attributes( @@ -555,145 +652,167 @@ class Model(Network): self._collected_trainable_weights = self.trainable_weights return - # Prepare targets of model. - self.targets = [] - self._feed_targets = [] - if target_tensors not in (None, []): - if isinstance(target_tensors, list): - if len(target_tensors) != len(self.outputs): - raise ValueError( - 'When passing a list as `target_tensors`, ' - 'it should have one entry per model output. ' - 'The model has ' + str(len(self.outputs)) + - ' outputs, but you passed target_tensors=' + str(target_tensors)) - elif isinstance(target_tensors, dict): - for name in target_tensors: - if name not in self.output_names: + with K.get_graph().as_default(): + # Prepare targets of model. + self.targets = [] + self._feed_targets = [] + if target_tensors not in (None, []): + if isinstance(target_tensors, list): + if len(target_tensors) != len(self.outputs): raise ValueError( - 'Unknown entry in `target_tensors` ' - 'dictionary: "' + name + '". ' - 'Only expected the following keys: ' + str(self.output_names)) - tmp_target_tensors = [] - for name in self.output_names: - tmp_target_tensors.append(target_tensors.get(name, None)) - target_tensors = tmp_target_tensors - elif tensor_util.is_tensor(target_tensors): - target_tensors = [target_tensors] - else: - raise TypeError('Expected `target_tensors` to be a list or tuple or ' - 'dict or a single tensor, but got:', target_tensors) - - for i in range(len(self.outputs)): - if i in skip_target_indices: - self.targets.append(None) - else: - shape = K.int_shape(self.outputs[i]) - name = self.output_names[i] - if target_tensors not in (None, []): - target = target_tensors[i] - else: - target = None - if target is None or K.is_placeholder(target): - if target is None: - target = K.placeholder( - ndim=len(shape), - name=name + '_target', - sparse=K.is_sparse(self.outputs[i]), - dtype=K.dtype(self.outputs[i])) - self._feed_targets.append(target) - self._feed_outputs.append(self.outputs[i]) - self._feed_output_names.append(name) - self._feed_output_shapes.append(shape) - self._feed_loss_fns.append(self.loss_functions[i]) + 'When passing a list as `target_tensors`, ' + 'it should have one entry per model output. ' + 'The model has %s outputs, but you passed target_tensors=%s' % + (len(self.outputs), target_tensors)) + elif isinstance(target_tensors, dict): + for name in target_tensors: + if name not in self.output_names: + raise ValueError( + 'Unknown entry in `target_tensors` ' + 'dictionary: "' + name + '". ' + 'Only expected the following keys: ' + str(self.output_names)) + tmp_target_tensors = [] + for name in self.output_names: + tmp_target_tensors.append(target_tensors.get(name, None)) + target_tensors = tmp_target_tensors + elif tensor_util.is_tensor(target_tensors): + target_tensors = [target_tensors] else: - skip_target_weighing_indices.append(i) - self.targets.append(target) - - # Prepare sample weights. - self._set_sample_weight_attributes(sample_weight_mode, - skip_target_weighing_indices) - # Save all metric attributes per output of the model. - self._cache_output_metric_attributes(metrics, weighted_metrics) - - # Compute total loss. - total_loss = None - with K.name_scope('loss'): + raise TypeError('Expected `target_tensors` to be a list or tuple or ' + 'dict or a single tensor, but got:', target_tensors) + for i in range(len(self.outputs)): if i in skip_target_indices: - continue - y_true = self.targets[i] - y_pred = self.outputs[i] - loss_fn = loss_functions[i] - sample_weight = self.sample_weights[i] - mask = masks[i] - loss_weight = loss_weights_list[i] - with K.name_scope(self.output_names[i] + '_loss'): - weighted_loss = training_utils.weighted_masked_objective(loss_fn) - output_loss = weighted_loss(y_true, y_pred, sample_weight, mask) + self.targets.append(None) + else: + shape = K.int_shape(self.outputs[i]) + name = self.output_names[i] + if target_tensors not in (None, []): + target = target_tensors[i] + else: + target = None + if target is None or K.is_placeholder(target): + if target is None: + target_dtype = losses.LABEL_DTYPES_FOR_LOSSES.get( + self.loss_functions[i], + K.dtype(self.outputs[i])) + + target = K.placeholder( + ndim=len(shape), + name=name + '_target', + sparse=K.is_sparse(self.outputs[i]), + dtype=target_dtype) + self._feed_targets.append(target) + self._feed_outputs.append(self.outputs[i]) + self._feed_output_names.append(name) + self._feed_output_shapes.append(shape) + self._feed_loss_fns.append(self.loss_functions[i]) + else: + skip_target_weighing_indices.append(i) + self.targets.append(target) - if len(self.outputs) > 1: - # Keep track of the un-aggregated loss result tensor. - self.metrics_tensors.append(output_loss) - - # Keep track of stateful result tensor and function for the loss. - mean_wrapped_loss = metrics_module.MeanMetricWrapper( - loss_fn, name=loss_fn.__name__) - result_tensor = training_utils.call_metric_function( - mean_wrapped_loss, - y_true, - y_pred, - weights=sample_weight, - mask=mask) - self._stateful_metrics_tensors.append(result_tensor) - self.stateful_metric_functions.append(mean_wrapped_loss) - - self.metrics_names.append(self.output_names[i] + '_loss') + # Prepare sample weights. + self._set_sample_weight_attributes(sample_weight_mode, + skip_target_weighing_indices) + # Save all metric attributes per output of the model. + self._cache_output_metric_attributes(metrics, weighted_metrics) + + # Compute total loss. + total_loss = None + with K.name_scope('loss'): + for i in range(len(self.outputs)): + if i in skip_target_indices: + continue + y_true = self.targets[i] + y_pred = self.outputs[i] + loss_fn = loss_functions[i] + sample_weight = self.sample_weights[i] + mask = masks[i] + loss_weight = loss_weights_list[i] + with K.name_scope(self.output_names[i] + '_loss'): + if isinstance(loss_fn, losses.Loss): + if mask is not None: + mask = math_ops.cast(mask, y_pred.dtype) + # Update weights with mask. + if sample_weight is None: + sample_weight = mask + else: + # Update dimensions of weights to match with mask if possible. + mask, _, sample_weight = squeeze_or_expand_dimensions( + mask, None, sample_weight) + sample_weight *= mask + output_loss = loss_fn(y_true, y_pred, sample_weight=sample_weight) + else: + weighted_loss = training_utils.weighted_masked_objective(loss_fn) + output_loss = weighted_loss(y_true, y_pred, sample_weight, mask) + + if len(self.outputs) > 1: + # Keep track of the un-aggregated loss result tensor. + self._compile_metrics_tensors[self.output_names[i] + + '_loss'] = output_loss + + # Keep track of stateful result tensor and function for the loss. + loss_name = loss_fn.name if isinstance( + loss_fn, losses.Loss) else loss_fn.__name__ + mean_wrapped_loss = metrics_module.MeanMetricWrapper( + loss_fn, name=loss_name) + result_tensor = training_utils.call_metric_function( + mean_wrapped_loss, + y_true, + y_pred, + weights=sample_weight, + mask=mask) + self._compile_stateful_metrics_tensors[self.output_names[i] + + '_loss'] = result_tensor + self._compile_stateful_metric_functions.append(mean_wrapped_loss) + + self._compile_metrics_names.append(self.output_names[i] + '_loss') + if total_loss is None: + total_loss = loss_weight * output_loss + else: + total_loss += loss_weight * output_loss if total_loss is None: - total_loss = loss_weight * output_loss - else: - total_loss += loss_weight * output_loss - if total_loss is None: - if not self.losses: - raise ValueError('The model cannot be compiled ' - 'because it has no loss to optimize.') - else: - total_loss = 0. - - # Add regularization penalties - # and other layer-specific losses. - for loss_tensor in self.losses: - total_loss += loss_tensor - - # Set metric attributes on model. - self._set_metric_attributes( - self.outputs, - skip_target_indices=skip_target_indices, - ) - # Invoke metric functions for all the outputs. - self._handle_metrics( - self.outputs, - masks=masks, - targets=self.targets, - skip_target_indices=skip_target_indices, - sample_weights=self.sample_weights) - - # Prepare gradient updates and state updates. - self.total_loss = total_loss - - # Functions for train, test and predict will - # be compiled lazily when required. - # This saves time when the user is not using all functions. - self._function_kwargs = kwargs - - self._fit_function = None - self._eval_function = None - self.train_function = None - self.test_function = None - self.predict_function = None - - # Collected trainable weights, sorted in topological order. - trainable_weights = self.trainable_weights - self._collected_trainable_weights = trainable_weights + if not self.losses: + raise ValueError('The model cannot be compiled ' + 'because it has no loss to optimize.') + else: + total_loss = 0. + + # Add regularization penalties + # and other layer-specific losses. + for loss_tensor in self.losses: + total_loss += loss_tensor + + # Set metric attributes on model. + self._set_metric_attributes( + self.outputs, + skip_target_indices=skip_target_indices, + ) + # Invoke metric functions for all the outputs. + self._handle_metrics( + self.outputs, + masks=masks, + targets=self.targets, + skip_target_indices=skip_target_indices, + sample_weights=self.sample_weights) + + # Prepare gradient updates and state updates. + self.total_loss = total_loss + + # Functions for train, test and predict will + # be compiled lazily when required. + # This saves time when the user is not using all functions. + self._function_kwargs = kwargs + + self._fit_function = None + self._eval_function = None + self.train_function = None + self.test_function = None + self.predict_function = None + + # Collected trainable weights, sorted in topological order. + trainable_weights = self.trainable_weights + self._collected_trainable_weights = trainable_weights def _check_trainable_weights_consistency(self): """Check trainable weights count consistency. @@ -721,21 +840,24 @@ class Model(Network): inputs = (self._feed_inputs + self._feed_targets + self._feed_sample_weights) - if not isinstance(K.learning_phase(), int): - inputs += [K.learning_phase()] + if not isinstance(K.symbolic_learning_phase(), int): + inputs += [K.symbolic_learning_phase()] + + with K.get_graph().as_default(): + with K.name_scope('training'): + with K.name_scope(self.optimizer.__class__.__name__): + # Training updates + updates = self.optimizer.get_updates( + params=self._collected_trainable_weights, loss=self.total_loss) + # Unconditional updates + updates += self.get_updates_for(None) + # Conditional updates relevant to this model + updates += self.get_updates_for(self.inputs) + # Add stateful metrics updates. + if metric_updates is not None: + updates += metric_updates with K.name_scope('training'): - with K.name_scope(self.optimizer.__class__.__name__): - # Training updates - updates = self.optimizer.get_updates( - params=self._collected_trainable_weights, loss=self.total_loss) - # Unconditional updates - updates += self.get_updates_for(None) - # Conditional updates relevant to this model - updates += self.get_updates_for(self.inputs) - # Add stateful metrics updates. - if metric_updates is not None: - updates += metric_updates # Gets loss and metrics. Updates weights at each call. fn = K.function( inputs, @@ -746,18 +868,24 @@ class Model(Network): setattr(self, fn_name, fn) def _make_train_function(self): + metrics_tensors = [ + self._all_metrics_tensors[m] for m in self.metrics_names[1:] + ] self._make_train_function_helper('train_function', - [self.total_loss] + self.metrics_tensors) + [self.total_loss] + metrics_tensors) def _make_fit_function(self): # TODO(psv/anjalisridhar): Remove updates after we fix b/118841692 # Stateful metrics updates metric_updates = [] - for m in self.stateful_metric_functions: + for m in self.metrics: metric_updates += m.updates + + metrics_tensors = [ + self._all_stateful_metrics_tensors[m] for m in self.metrics_names[1:] + ] self._make_train_function_helper( - '_fit_function', [self.total_loss] + self._stateful_metrics_tensors, - metric_updates) + '_fit_function', [self.total_loss] + metrics_tensors, metric_updates) def _make_test_function_helper(self, fn_name, outputs, metric_updates=None): if not hasattr(self, fn_name): @@ -766,49 +894,53 @@ class Model(Network): inputs = (self._feed_inputs + self._feed_targets + self._feed_sample_weights) - if not isinstance(K.learning_phase(), int): - inputs += [K.learning_phase()] - updates = self.state_updates - # Add stateful metrics updates. - if metric_updates is not None: - updates += metric_updates - # Return loss and metrics, no gradient updates. - # Does update the network states. - fn = K.function( - inputs, - outputs, - updates=updates, - name='test_function', - **self._function_kwargs) - setattr(self, fn_name, fn) + + with K.name_scope('evaluation'): + updates = self.state_updates + # Add stateful metrics updates. + if metric_updates is not None: + updates += metric_updates + # Return loss and metrics, no gradient updates. + # Does update the network states. + fn = K.function( + inputs, + outputs, + updates=updates, + name='test_function', + **self._function_kwargs) + setattr(self, fn_name, fn) def _make_test_function(self): + metrics_tensors = [ + self._all_metrics_tensors[m] for m in self.metrics_names[1:] + ] self._make_test_function_helper('test_function', - [self.total_loss] + self.metrics_tensors) + [self.total_loss] + metrics_tensors) def _make_eval_function(self): - self._make_test_function_helper( - '_eval_function', [self.total_loss] + self._stateful_metrics_tensors) + metrics_tensors = [ + self._all_stateful_metrics_tensors[m] for m in self.metrics_names[1:] + ] + self._make_test_function_helper('_eval_function', + [self.total_loss] + metrics_tensors) def _make_predict_function(self): if not hasattr(self, 'predict_function'): self.predict_function = None if self.predict_function is None: - if not isinstance(K.learning_phase(), int): - inputs = self._feed_inputs + [K.learning_phase()] - else: - inputs = self._feed_inputs + inputs = self._feed_inputs # Gets network outputs. Does not update weights. # Does update the network states. kwargs = getattr(self, '_function_kwargs', {}) - self.predict_function = K.function( - inputs, - self.outputs, - updates=self.state_updates, - name='predict_function', - **kwargs) + with K.name_scope('predict'): + self.predict_function = K.function( + inputs, + self.outputs, + updates=self.state_updates, + name='predict_function', + **kwargs) - def _get_execution_function(self, mode): + def _make_execution_function(self, mode): if mode == 'train': self._make_fit_function() return self._fit_function @@ -873,7 +1005,8 @@ class Model(Network): 'when using DistributionStrategy.') if (sample_weight is not None and sample_weight.all() and - self._distribution_strategy.__class__.__name__ == 'TPUStrategy'): + distributed_training_utils.is_tpu_strategy( + self._distribution_strategy)): raise NotImplementedError('`sample_weight` is currently not supported ' 'when using TPUStrategy.') @@ -882,18 +1015,13 @@ class Model(Network): # TODO(anjalisridhar): Remove this check once we refactor the # _standardize_user_data code path. This check is already present elsewhere # in the codebase. - if check_steps and isinstance(x, dataset_ops.Dataset) and steps is None: + if check_steps and isinstance(x, dataset_ops.DatasetV2) and steps is None: raise ValueError('When using Datasets as input, ' 'you should specify the `{steps_name}` argument.' .format(steps_name=steps_name)) first_x_value = nest.flatten(x)[0] if isinstance(first_x_value, np.ndarray): - assert steps is not None - x_shape = first_x_value.shape - if batch_size is None: - batch_size = distributed_training_utils.get_batch_size( - self._distribution_strategy.num_replicas_in_sync, x_shape[0], steps) # We need to use the drop_remainder argument to allow for a static # input shape which is required for TPUs. drop_remainder = self._distribution_strategy.require_static_shapes @@ -928,19 +1056,15 @@ class Model(Network): var_x = distributed_training_utils.get_var_for_numpy( self._distribution_strategy, x) x = dataset_ops.Dataset.from_tensor_slices(var_x) - x = x.repeat() x = x.batch(batch_size, drop_remainder=drop_remainder) - assert isinstance(x, dataset_ops.Dataset) + assert isinstance(x, dataset_ops.DatasetV2) - # TODO(anjalisridhar): We want distribute_dataset() to accept a Dataset or a - # function which returns a Dataset. Currently distribute_dataset() only - # accepts a function that returns a Dataset. Once we add support for being - # able to clone a Dataset on multiple workers we can remove this lambda. - result = self._distribution_strategy.distribute_dataset(lambda: x) - iterator = result.make_initializable_iterator() with self._distribution_strategy.scope(): - K.get_session().run(iterator.initializer) + iterator = self._distribution_strategy.make_dataset_iterator(x) + init_op = iterator.initialize() + if not context.executing_eagerly(): + K.get_session().run(init_op) training_utils.validate_iterator_input(x, y, sample_weight, validation_split) @@ -1025,14 +1149,14 @@ class Model(Network): shuffle=shuffle) return iterator, None, None - if isinstance(x, dataset_ops.Dataset): + if isinstance(x, dataset_ops.DatasetV2): if context.executing_eagerly(): - x = x.make_one_shot_iterator() + x = iter(x) else: if x in self._dataset_iterator_cache: x = self._dataset_iterator_cache[x] else: - iterator = x.make_initializable_iterator() + iterator = dataset_ops.make_initializable_iterator(x) self._dataset_iterator_cache[x] = iterator x = iterator K.get_session().run(x.initializer) @@ -1052,7 +1176,7 @@ class Model(Network): # For eager iterators, when we have to process multiple batches of samples, # we will standardize the data when we actually loop over iterator and get # the batches. For now, we just return the iterator as is. - if is_x_eager_iterator and steps is not None: + if is_x_eager_iterator: return x, y, sample_weight # If input data is a dataset iterator in graph mode or if it is an eager @@ -1096,6 +1220,8 @@ class Model(Network): all_inputs = [] is_build_called = False is_compile_called = False + # Whether this is a subclassed model that expects dictionary inputs + # rather than list inputs (e.g. FeatureColumn-based models). dict_inputs = False if not self.inputs: # We need to use `x` to set the model inputs. @@ -1122,9 +1248,16 @@ class Model(Network): # to match the value shapes. if not self.inputs: is_build_called = True - self._set_inputs(x) + cast_inputs = x + if training_utils.has_tensors(x): + cast_inputs = training_utils.cast_if_floating_dtype(x) + self._set_inputs(cast_inputs) else: dict_inputs = isinstance(self.inputs, dict) + if dict_inputs and context.executing_eagerly(): + # No support for graph functions when the model expects dictionary inputs + # (i.e. FeatureColumn-based models). + self.run_eagerly = True if y is not None: if not self.optimizer: @@ -1134,6 +1267,8 @@ class Model(Network): if not self._is_compiled: # On-the-fly compilation of the model. # We need to use `y` to set the model targets. + if training_utils.has_tensors(y): + y = training_utils.cast_if_floating_dtype(y) if isinstance(y, (list, tuple)): if not all(isinstance(v, np.ndarray) or tensor_util.is_tensor(v) for v in y): @@ -1158,19 +1293,22 @@ class Model(Network): 'TensorFlow tensors. ' 'You passed: x=' + str(x) + '; y=' + str(y)) - if context.executing_eagerly(): + if self.run_eagerly: target_tensors = None else: # Handle target tensors if any passed. if not isinstance(y, (list, tuple)): y = [y] - target_tensors = [v for v in y if tensor_util.is_tensor(v)] + target_tensors = [v for v in y if _is_symbolic_tensor(v)] is_compile_called = True - self.compile(optimizer=self.optimizer, - loss=self.loss, - metrics=self.metrics, - loss_weights=self.loss_weights, - target_tensors=target_tensors) + self.compile( + optimizer=self.optimizer, + loss=self.loss, + metrics=self._compile_metrics, + weighted_metrics=self._compile_weighted_metrics, + loss_weights=self.loss_weights, + target_tensors=target_tensors, + run_eagerly=self.run_eagerly) # In graph mode, if we had just set inputs and targets as symbolic tensors # by invoking build and compile on the model respectively, we do not have to @@ -1178,15 +1316,15 @@ class Model(Network): # part of the graph. # Note: in this case, `any` and `all` are equivalent since we disallow # mixed symbolic/value inputs. - if (not context.executing_eagerly() and is_build_called and + if (not self.run_eagerly and is_build_called and is_compile_called and - any(tensor_util.is_tensor(v) for v in all_inputs)): + any(_is_symbolic_tensor(v) for v in all_inputs)): return [], [], [] # What follows is input validation and standardization to list format, # in the case where all inputs are value arrays. - if context.executing_eagerly(): + if self.run_eagerly: # In eager mode, do not do shape validation # since the network has no input nodes (placeholders) to be fed. feed_input_names = self.input_names @@ -1242,7 +1380,9 @@ class Model(Network): y = training_utils.standardize_input_data( y, feed_output_names, - feed_output_shapes, + # Don't enforce target shapes to match output shapes. + # Precise checks will be run in `check_loss_and_target_compatibility`. + shapes=None, check_batch_axis=False, # Don't enforce the batch size. exception_prefix='target') @@ -1260,7 +1400,7 @@ class Model(Network): # Check that all arrays have the same length. if not self._distribution_strategy: training_utils.check_array_lengths(x, y, sample_weights) - if self._is_graph_network and not context.executing_eagerly(): + if self._is_graph_network and not self.run_eagerly: # Additional checks to avoid users mistakenly using improper loss fns. training_utils.check_loss_and_target_compatibility( y, self._feed_loss_fns, feed_output_shapes) @@ -1315,8 +1455,7 @@ class Model(Network): if self.__class__.__name__ == 'Sequential' and not self.built: if tensor_util.is_tensor(inputs): - input_shape = (None,) + tuple(inputs.get_shape().as_list()[1:]) - self.build(input_shape=input_shape) + input_shape = (None,) + tuple(inputs.shape.as_list()[1:]) elif isinstance(inputs, dict): # We assert that the first layer is a FeatureLayer. if not training_utils.is_feature_layer(self.layers[0]): @@ -1324,10 +1463,9 @@ class Model(Network): 'which doesn\'t have FeatureLayer as the first layer' ' is an error.') input_shape = (None,) - self.build(input_shape=input_shape) else: - input_shape = (None,) + inputs.shape[1:] - self.build(input_shape=input_shape) + input_shape = (None,) + tuple(inputs.shape[1:]) + self._build_input_shape = input_shape # On-the-fly setting of symbolic model inputs (either by using the tensor # provided, or by creating a placeholder if Numpy data was provided). @@ -1346,10 +1484,11 @@ class Model(Network): self._feed_input_names.append(k) self._feed_input_shapes.append(K.int_shape(v)) + # TODO(fchollet): consider calling `_maybe_build` before calling the model. + if outputs is None: # Obtain symbolic outputs by calling the model. - graph = K.get_graph() - with graph.as_default(): + with K.get_graph().as_default(): if self._expects_training_arg: outputs = self.call(inputs, training=training) else: @@ -1509,7 +1648,6 @@ class Model(Network): """ # TODO(fchollet): this method may be creating reference cycles, which would # lead to accumulating garbage in memory when called in a loop. Investigate. - if data_utils.is_generator_or_sequence(x): training_utils.check_generator_arguments(y, sample_weight) return self.fit_generator( @@ -1527,9 +1665,6 @@ class Model(Network): shuffle=shuffle, initial_epoch=initial_epoch) - # Backwards compatibility - if batch_size is None and steps_per_epoch is None: - batch_size = 32 # Legacy support if 'nb_epoch' in kwargs: logging.warning( @@ -1541,15 +1676,21 @@ class Model(Network): # Validate and standardize user data. if self._distribution_strategy: - distributed_training_utils.validate_callbacks(callbacks) + distributed_training_utils.validate_callbacks(callbacks, self.optimizer, + self._distribution_strategy) distributed_training_utils.validate_inputs( x, y, self._distribution_strategy) first_x_value = nest.flatten(x)[0] - if not steps_per_epoch and isinstance(first_x_value, np.ndarray): - steps_per_epoch = distributed_training_utils.get_input_batch_params( - first_x_value, batch_size, self._distribution_strategy) + if isinstance(first_x_value, np.ndarray): + steps_per_epoch, batch_size = ( + distributed_training_utils.get_input_params( + self._distribution_strategy, first_x_value, steps_per_epoch, + batch_size, is_training=True)) + + batch_size = self._validate_or_infer_batch_size(batch_size, steps_per_epoch, + x) x, y, sample_weights = self._standardize_user_data( x, @@ -1567,7 +1708,7 @@ class Model(Network): if validation_data: if (isinstance(validation_data, iterator_ops.Iterator) or isinstance(validation_data, iterator_ops.EagerIterator) or - isinstance(validation_data, dataset_ops.Dataset)): + isinstance(validation_data, dataset_ops.DatasetV2)): val_x = validation_data val_y = None val_sample_weight = None @@ -1590,9 +1731,10 @@ class Model(Network): distributed_training_utils.validate_inputs( val_x, val_y, self._distribution_strategy) first_valx_value = nest.flatten(val_x)[0] - if not validation_steps and isinstance(first_valx_value, np.ndarray): - validation_steps = distributed_training_utils.get_input_batch_params( - first_valx_value, batch_size, self._distribution_strategy) + if isinstance(first_valx_value, np.ndarray): + validation_steps, _ = distributed_training_utils.get_input_params( + self._distribution_strategy, first_valx_value, validation_steps, + batch_size) val_x, val_y, val_sample_weights = self._standardize_user_data( val_x, @@ -1622,27 +1764,25 @@ class Model(Network): val_y = None val_sample_weights = None - if context.executing_eagerly(): - return training_eager.fit_loop( - self, - inputs=x, - targets=y, - sample_weights=sample_weights, - class_weight=class_weight, + if (self.run_eagerly or (isinstance(x, iterator_ops.EagerIterator) and + not self._distribution_strategy)): + return training_generator.fit_generator( + self, (x, y, sample_weights), + steps_per_epoch=steps_per_epoch, batch_size=batch_size, epochs=epochs, + shuffle=shuffle, verbose=verbose, callbacks=callbacks, - val_inputs=val_x, - val_targets=val_y, - val_sample_weights=val_sample_weights, - shuffle=shuffle, - initial_epoch=initial_epoch, - steps_per_epoch=steps_per_epoch, - validation_steps=validation_steps) - elif self._distribution_strategy: - return training_distributed.fit_loop( - self, x, + validation_data=validation_data, + validation_steps=validation_steps, + workers=0, + initial_epoch=initial_epoch) + elif distributed_training_utils.is_tpu_strategy( + self._distribution_strategy): + return training_distributed.experimental_fit_loop( + self, + x, epochs=epochs, verbose=verbose, callbacks=callbacks, @@ -1757,19 +1897,16 @@ class Model(Network): max_queue_size=max_queue_size, workers=workers, use_multiprocessing=use_multiprocessing) - - # Backwards compatibility. - if batch_size is None and steps is None: - batch_size = 32 - # Validate and standardize user data. if self._distribution_strategy: distributed_training_utils.validate_inputs( x, y, self._distribution_strategy) first_x_value = nest.flatten(x)[0] - if isinstance(first_x_value, np.ndarray) and not steps: - steps = distributed_training_utils.get_input_batch_params( - first_x_value, batch_size, self._distribution_strategy) + if isinstance(first_x_value, np.ndarray): + steps, batch_size = distributed_training_utils.get_input_params( + self._distribution_strategy, first_x_value, steps, batch_size) + + batch_size = self._validate_or_infer_batch_size(batch_size, steps, x) x, y, sample_weights = self._standardize_user_data( x, @@ -1780,21 +1917,18 @@ class Model(Network): steps_name='steps', steps=steps) - if context.executing_eagerly(): - return training_eager.test_loop( - self, - inputs=x, - targets=y, - sample_weights=sample_weights, + if (self.run_eagerly or (isinstance(x, iterator_ops.EagerIterator) and + not self._distribution_strategy)): + return training_generator.evaluate_generator( + self, (x, y, sample_weights), + steps=steps, batch_size=batch_size, verbose=verbose, - steps=steps) - elif self._distribution_strategy: - return training_distributed.test_loop( - self, - iterator=x, - verbose=verbose, - steps=steps) + workers=0) + elif distributed_training_utils.is_tpu_strategy( + self._distribution_strategy): + return training_distributed.experimental_test_loop( + self, iterator=x, verbose=verbose, steps=steps) else: return training_arrays.test_loop( self, @@ -1868,37 +2002,57 @@ class Model(Network): max_queue_size=max_queue_size, workers=workers, use_multiprocessing=use_multiprocessing) - - # Backwards compatibility. - if batch_size is None and steps is None: - batch_size = 32 - if self._distribution_strategy: distributed_training_utils.validate_inputs( x, None, self._distribution_strategy) first_x_value = nest.flatten(x)[0] - if isinstance(first_x_value, np.ndarray) and not steps: - steps = distributed_training_utils.get_input_batch_params( - first_x_value, batch_size, self._distribution_strategy) + if isinstance(first_x_value, np.ndarray): + steps, batch_size = distributed_training_utils.get_input_params( + self._distribution_strategy, first_x_value, steps, batch_size) - # Validate and standardize user data. - # TODO(anjalisridhar): We don't pass batch_size here for some reason. This - # means that we end up calculating it twice which we should avoid. - x, _, _ = self._standardize_user_data( - x, check_steps=True, steps_name='steps', steps=steps) + batch_size = self._validate_or_infer_batch_size(batch_size, steps, x) - if context.executing_eagerly(): - return training_eager.predict_loop( - self, x, batch_size=batch_size, verbose=verbose, steps=steps) - elif self._distribution_strategy: - results = training_distributed.predict_loop( + # Validate and standardize user data. + if self._distribution_strategy: + x, _, _ = self._standardize_user_data( + x, check_steps=True, steps_name='steps', steps=steps, + batch_size=batch_size) + else: + # TODO(anjalisridhar): We don't pass batch_size here for some reason. This + # means we need to special case distribution strategy which needs the + # batch size. + x, _, _ = self._standardize_user_data( + x, check_steps=True, steps_name='steps', steps=steps) + + if (self.run_eagerly or (isinstance(x, iterator_ops.EagerIterator) and + not self._distribution_strategy)): + return training_generator.predict_generator( + self, + x, + steps=steps, + batch_size=batch_size, + verbose=verbose, + workers=0) + elif distributed_training_utils.is_tpu_strategy( + self._distribution_strategy): + return training_distributed.experimental_predict_loop( self, x, verbose=verbose, steps=steps) - return results else: return training_arrays.predict_loop( self, x, batch_size=batch_size, verbose=verbose, steps=steps) - def train_on_batch(self, x, y=None, sample_weight=None, class_weight=None): + def reset_metrics(self): + """Resets the state of metrics.""" + if hasattr(self, 'metrics'): + for m in self.metrics: + m.reset_states() + + def train_on_batch(self, + x, + y=None, + sample_weight=None, + class_weight=None, + reset_metrics=True): """Runs a single gradient update on a single batch of data. Arguments: @@ -1926,6 +2080,9 @@ class Model(Network): weight (float) to apply to the model's loss for the samples from this class during training. This can be useful to tell the model to "pay more attention" to samples from an under-represented class. + reset_metrics: If `True`, the metrics returned will be only for this + batch. If `False`, the metrics will be statefully accumulated across + batches. Returns: Scalar training loss @@ -1944,23 +2101,30 @@ class Model(Network): x, y, sample_weights = self._standardize_user_data( x, y, sample_weight=sample_weight, class_weight=class_weight) - if context.executing_eagerly(): + if self.run_eagerly: outputs = training_eager.train_on_batch( self, x, y, sample_weights=sample_weights) else: - if not isinstance(K.learning_phase(), int): - ins = x + y + sample_weights + [1] + if not isinstance(K.symbolic_learning_phase(), int): + ins = x + y + sample_weights + [True] else: ins = x + y + sample_weights - self._make_train_function() - outputs = self.train_function(ins) # pylint: disable=not-callable + if reset_metrics: + self._make_train_function() + outputs = self.train_function(ins) # pylint: disable=not-callable + else: + self._make_fit_function() + outputs = self._fit_function(ins) # pylint: disable=not-callable + + if reset_metrics: + self.reset_metrics() if len(outputs) == 1: return outputs[0] return outputs - def test_on_batch(self, x, y=None, sample_weight=None): + def test_on_batch(self, x, y=None, sample_weight=None, reset_metrics=True): """Test the model on a single batch of samples. Arguments: @@ -1986,6 +2150,9 @@ class Model(Network): In this case you should make sure to specify sample_weight_mode="temporal" in compile(). This argument is not supported when `x` is a dataset or a dataset iterator. + reset_metrics: If `True`, the metrics returned will be only for this + batch. If `False`, the metrics will be statefully accumulated across + batches. Returns: Scalar test loss (if the model has a single output and no metrics) @@ -2003,16 +2170,20 @@ class Model(Network): x, y, sample_weights = self._standardize_user_data( x, y, sample_weight=sample_weight) - if context.executing_eagerly(): + if self.run_eagerly: outputs = training_eager.test_on_batch( self, x, y, sample_weights=sample_weights) else: - if not isinstance(K.learning_phase(), int): - ins = x + y + sample_weights + [0] + inputs = x + y + sample_weights + if reset_metrics: + self._make_test_function() + outputs = self.test_function(inputs) # pylint: disable=not-callable else: - ins = x + y + sample_weights - self._make_test_function() - outputs = self.test_function(ins) # pylint: disable=not-callable + self._make_eval_function() + outputs = self._eval_function(inputs) # pylint: disable=not-callable + + if reset_metrics: + self.reset_metrics() if len(outputs) == 1: return outputs[0] @@ -2041,28 +2212,21 @@ class Model(Network): 'models compiled with DistributionStrategy.') # Validate and standardize user data. inputs, _, _ = self._standardize_user_data(x) - if context.executing_eagerly(): - if (isinstance(x, iterator_ops.EagerIterator) or - (isinstance(x, dataset_ops.Dataset) and context.executing_eagerly())): + if self.run_eagerly: + if (isinstance(inputs, iterator_ops.EagerIterator) or + (isinstance(inputs, dataset_ops.DatasetV2))): inputs = training_utils.cast_if_floating_dtype(inputs) - else: + elif isinstance(inputs, collections.Sequence): inputs = [ - ops.convert_to_tensor(val, dtype=K.floatx()) for val in inputs - ] + ops.convert_to_tensor(val, dtype=K.floatx()) for val in inputs] return self(inputs) # pylint: disable=not-callable - if not context.executing_eagerly(): - if not isinstance(K.learning_phase(), int): - ins = inputs + [0] - else: - ins = inputs - - self._make_predict_function() - outputs = self.predict_function(ins) + self._make_predict_function() + outputs = self.predict_function(inputs) - if len(outputs) == 1: - return outputs[0] - return outputs + if len(outputs) == 1: + return outputs[0] + return outputs def fit_generator(self, generator, @@ -2172,11 +2336,6 @@ class Model(Network): if self._distribution_strategy: raise NotImplementedError('`fit_generator` is not supported for ' 'models compiled with DistributionStrategy.') - - if not self.built and not self._is_graph_network: - raise NotImplementedError( - '`fit_generator` is not yet enabled for unbuilt Model subclasses') - return training_generator.fit_generator( self, generator, @@ -2243,12 +2402,6 @@ class Model(Network): if self._distribution_strategy: raise NotImplementedError('`evaluate_generator` is not supported for ' 'models compiled with DistributionStrategy.') - - if not self.built and not self._is_graph_network: - raise NotImplementedError( - '`evaluate_generator` is not yet enabled for ' - 'unbuilt Model subclasses') - return training_generator.evaluate_generator( self, generator, @@ -2300,11 +2453,6 @@ class Model(Network): if self._distribution_strategy: raise NotImplementedError('`predict_generator` is not supported for ' 'models compiled with DistributionStrategy.') - - if not self.built and not self._is_graph_network: - raise NotImplementedError( - '`predict_generator` is not yet enabled for unbuilt Model subclasses') - return training_generator.predict_generator( self, generator, @@ -2336,15 +2484,63 @@ class Model(Network): self._replicated_model = DistributedCallbackModel(first_replicated_model) self._replicated_model.set_original_model(self) + def _validate_or_infer_batch_size(self, batch_size, steps, x): + """Validates that the `batch_size` provided is consistent with InputLayer. + + It's possible that the user specified a static batch size in their + InputLayer. If so, this method checks the provided `batch_size` and `x` + arguments are consistent with this static batch size. Also, if + `batch_size` is `None`, this method will attempt to infer the batch size + from the static batch size of the InputLayer. + + Arguments: + batch_size: The batch_size provided as an argument to + fit/evaluate/predict. + steps: The steps provided as an argument to fit/evaluate/predict. + x: The data passed as `x` to fit/evaluate/predict. + + Returns: + The validated batch_size, auto-inferred from the first layer if not + provided. + """ + first_layer = super(Model, + self).layers[0] # Avoids the override in Sequential. + static_batch_size = training_utils.get_static_batch_size(first_layer) + if static_batch_size is not None: + + # Check `batch_size` argument is consistent with InputLayer. + if batch_size is not None and batch_size != static_batch_size: + raise ValueError('The `batch_size` argument value ' + str(batch_size) + + ' is incompatible with the specified batch size ' + 'of your Input Layer: ' + str(static_batch_size)) + + # Check Dataset/Iterator batch size is consistent with InputLayer. + if isinstance(x, (dataset_ops.DatasetV2, iterator_ops.Iterator, + iterator_ops.EagerIterator)): + ds_batch_size = tensor_shape.as_dimension( + nest.flatten(x.output_shapes)[0][0]).value + if ds_batch_size is not None and ds_batch_size != static_batch_size: + raise ValueError('The batch output shape of your `Dataset` is ' + + str(ds_batch_size) + ' which is incompatible ' + 'with the specified batch size of your Input ' + 'Layer: ' + str(static_batch_size)) + + # Set inferred batch size from the InputLayer. + if steps is None: + batch_size = static_batch_size + + if batch_size is None and steps is None: + # Backwards compatibility + batch_size = 32 + return batch_size + class DistributedCallbackModel(Model): """Model that is used for callbacks with DistributionStrategy.""" def __init__(self, model): super(DistributedCallbackModel, self).__init__() - # TODO(anjalisridhar): Right now the only attributes set are the layer and - # weights. We may need to set additional attributes as needed since we have - # not called compile on this model. + self.optimizer = model.optimizer def set_original_model(self, orig_model): self._original_model = orig_model @@ -2376,3 +2572,7 @@ class DistributedCallbackModel(Model): logging.warning('You are accessing attribute ' + item + ' of the ' 'DistributedCallbackModel that may not have been set ' 'correctly.') + + +def _is_symbolic_tensor(x): + return tensor_util.is_tensor(x) and not isinstance(x, ops.EagerTensor) diff --git a/tensorflow/python/keras/engine/training_arrays.py b/tensorflow/python/keras/engine/training_arrays.py index a2a13b9bd6..e9dfbcbcc0 100644 --- a/tensorflow/python/keras/engine/training_arrays.py +++ b/tensorflow/python/keras/engine/training_arrays.py @@ -23,9 +23,11 @@ import functools import numpy as np +from tensorflow.python.eager import context from tensorflow.python.framework import errors from tensorflow.python.keras import backend as K from tensorflow.python.keras import callbacks as cbks +from tensorflow.python.keras.engine import training_distributed from tensorflow.python.keras.engine import training_utils from tensorflow.python.keras.utils.generic_utils import make_batches from tensorflow.python.keras.utils.generic_utils import slice_arrays @@ -37,91 +39,6 @@ except ImportError: issparse = None -class Aggregator(object): - """Abstract base class used to aggregate batch-level outputs of a loop. - - Arguments: - use_steps: Whether the loop is using `step` or `batch_size`. - num_samples_or_steps: Either `batch_size*num_batches` or `steps`. - """ - - def __init__(self, use_steps, num_samples_or_steps): - self.use_steps = use_steps - self.num_samples_or_steps = num_samples_or_steps - self.results = [] - - def create(self, batch_outs): - """Create the initial results from the first batch outputs. - - Arguments: - batch_outs: A list of batch-level outputs. - """ - raise NotImplementedError - - def aggregate(self, batch_outs, batch_start=None, batch_end=None): - """Aggregate batch-level results into total results. - - Arguments: - batch_outs: A list of batch-level outputs. - batch_start: The start index of this batch. Always `None` if `use_steps` - is `True`. - batch_end: The end index of this batch. Always `None` if `use_steps` is - `True`. - """ - raise NotImplementedError - - def finalize(self): - """Prepare the total results to be returned.""" - raise NotImplementedError - - -class MetricsAggregator(Aggregator): - """Aggregator that calculates loss and metrics info.""" - - def create(self, batch_outs): - self.results = [0.] * len(batch_outs) - - def aggregate(self, batch_outs, batch_start=None, batch_end=None): - # Loss. - if self.use_steps: - self.results[0] += batch_outs[0] - else: - self.results[0] += batch_outs[0] * (batch_end - batch_start) - # Metrics (always stateful, just grab current values.) - self.results[1:] = batch_outs[1:] - - def finalize(self): - self.results[0] /= self.num_samples_or_steps - - -class OutputsAggregator(Aggregator): - """Aggregator that concatenates outputs.""" - - def create(self, batch_outs): - if self.use_steps: - # Cannot pre-allocate the returned NumPy arrays bc - # batch sizes are unknown. Concatenate batches at the end. - for _ in batch_outs: - self.results.append([]) - else: - # Pre-allocate NumPy arrays. - for batch_out in batch_outs: - shape = (self.num_samples_or_steps,) + batch_out.shape[1:] - self.results.append(np.zeros(shape, dtype=batch_out.dtype)) - - def aggregate(self, batch_outs, batch_start=None, batch_end=None): - if self.use_steps: - for i, batch_out in enumerate(batch_outs): - self.results[i].append(batch_out) - else: - for i, batch_out in enumerate(batch_outs): - self.results[i][batch_start:batch_end] = batch_out - - def finalize(self): - if self.use_steps: - self.results = [np.concatenate(result, axis=0) for result in self.results] - - def _get_model_feed(model, mode): if mode == 'predict': feed = model._feed_inputs @@ -151,13 +68,6 @@ def _print_train_info(inputs, val_inputs, steps_per_epoch, verbose): (inputs[0].shape[0], val_inputs[0].shape[0])) -def _get_progbar(model, count_mode): - stateful_metric_names = None - if hasattr(model, 'metrics_names'): - stateful_metric_names = model.metrics_names[1:] # Exclude `loss` - return cbks.ProgbarLogger(count_mode, stateful_metrics=stateful_metric_names) - - def _get_num_samples_or_steps(ins, batch_size, steps_per_epoch): """Returns total number of samples (when training in batch mode) or steps.""" if steps_per_epoch: @@ -166,16 +76,50 @@ def _get_num_samples_or_steps(ins, batch_size, steps_per_epoch): 'steps_per_epoch') -def _make_logs(model, outputs, mode, prefix=''): - """Used to make logs to send to `on_batch_end` methods.""" - logs = {} - # TODO(omalleyt): handle outputs in prediction when Callback - # hooks are ready. - if mode in ['train', 'test']: - if hasattr(model, 'metrics_names'): - for label, output in zip(model.metrics_names, outputs): - logs[prefix + label] = output - return logs +def _prepare_feed_values(model, inputs, targets, sample_weights, mode): + """Prepare feed values to the model execution function. + + Arguments: + model: Model to prepare feed values for. + inputs: List or dict of model inputs. + targets: Optional list of model targets. + sample_weights: Optional list of sample weight arrays. + mode: One of 'train'/'test'/'predict'. + + Returns: + Feed values for the model in the given mode. + """ + if model._distribution_strategy: + def get_distributed_inputs(): + return training_distributed._prepare_feed_values( + model, inputs, targets, sample_weights, mode) + + # In the eager case, we want to call the input method per step, so return + # a lambda from here that can be called. Note that this is applicable only + # in Distribution Strategy case as it follows the same code path for both + # eager and graph modes. + # TODO(priyag,omalleyt): Either we should move the training DS with + # EagerIterator to use training_generator code path, or figure out how to + # set a symbolic Iterator out of a Dataset when in eager mode. + if context.executing_eagerly(): + return get_distributed_inputs + else: + return get_distributed_inputs() + + inputs = training_utils.ModelInputs(inputs).as_list() + targets = targets or [] + sample_weights = sample_weights or [] + ins = inputs + targets + sample_weights + if mode == 'train' and not isinstance(K.symbolic_learning_phase(), int): + ins += [True] + return ins + + +def _make_execution_function(model, mode): + """Makes function to run one step of model execution.""" + if model._distribution_strategy: + return training_distributed._make_execution_function(model, mode) + return model._make_execution_function(mode) def model_iteration(model, @@ -238,19 +182,18 @@ def model_iteration(model, if mode == 'train': _print_train_info(inputs, val_inputs, steps_per_epoch, verbose) + # Enter DistributionStrategy scope. + if model._distribution_strategy: + scope = model._distribution_strategy.scope() + scope.__enter__() + # Get step function and loop type. - f = model._get_execution_function(mode) + f = _make_execution_function(model, mode) use_steps = steps_per_epoch is not None do_validation = val_inputs is not None # Prepare input data. - inputs = training_utils.ModelInputs(inputs).as_list() - targets = targets or [] - sample_weights = sample_weights or [] - learning_phase_input = [] - if not isinstance(K.learning_phase(), int): - learning_phase_input = [1] if mode == 'train' else [0] - ins = inputs + targets + sample_weights + learning_phase_input + ins = _prepare_feed_values(model, inputs, targets, sample_weights, mode) num_samples_or_steps = _get_num_samples_or_steps(ins, batch_size, steps_per_epoch) @@ -260,24 +203,19 @@ def model_iteration(model, callbacks, model, do_validation=do_validation, - val_inputs=val_inputs, - val_targets=val_targets, - val_sample_weights=val_sample_weights, batch_size=batch_size, epochs=epochs, steps_per_epoch=steps_per_epoch, samples=num_samples_or_steps, - validation_steps=validation_steps, verbose=0, # Handle ProgBarLogger separately in this loop. - count_mode=count_mode, mode=mode) # TODO(omalleyt): Handle ProgBar as part of Callbacks once hooks are ready. - progbar = _get_progbar(model, count_mode) + progbar = training_utils.get_progbar(model, count_mode) progbar.params = callbacks.params progbar.params['verbose'] = verbose # Find beforehand arrays that need sparse-to-dense conversion. - if issparse is not None: + if issparse is not None and not use_steps: indices_for_conversion_to_dense = [] feed = _get_model_feed(model, mode) for i, (input_data, feed_tensor) in enumerate(zip(ins, feed)): @@ -286,9 +224,14 @@ def model_iteration(model, # Select aggregation method. if mode == 'predict': - aggregator = OutputsAggregator(use_steps, num_samples_or_steps) + aggregator = training_utils.OutputsAggregator(use_steps, + num_samples_or_steps) else: - aggregator = MetricsAggregator(use_steps, num_samples_or_steps) + aggregator = training_utils.MetricsAggregator(use_steps, + num_samples_or_steps) + + if model._distribution_strategy: + training_distributed._copy_weights_to_distributed_model(model) callbacks.model.stop_training = False callbacks._call_begin_hook(mode) @@ -298,10 +241,9 @@ def model_iteration(model, break # Setup work for each epoch - results = [] epoch_logs = {} - if hasattr(model, 'stateful_metric_functions'): - for m in model.stateful_metric_functions: + if hasattr(model, 'metrics'): + for m in model.metrics: m.reset_states() callbacks.on_epoch_begin(epoch, epoch_logs, mode=mode) progbar.on_epoch_begin(epoch, epoch_logs) @@ -315,26 +257,31 @@ def model_iteration(model, # Get outputs. try: - batch_outs = f(ins) + # `ins` can be callable in DistributionStrategy + eager case. + actual_inputs = ins() if callable(ins) else ins + batch_outs = f(actual_inputs) except errors.OutOfRangeError: logging.warning('Your dataset iterator ran out of data; ' 'interrupting training. Make sure that your dataset ' 'can generate at least `steps_per_epoch * epochs` ' 'batches (in this case, %d batches). You may need to' 'use the repeat() function when building your ' - 'dataset.' % - steps_per_epoch * epochs) + 'dataset.' % steps_per_epoch * epochs) break if not isinstance(batch_outs, list): batch_outs = [batch_outs] + if model._distribution_strategy: + batch_outs = training_distributed._per_device_aggregate_batch( + batch_outs, model, mode) + # Aggregate results. if step == 0: aggregator.create(batch_outs) aggregator.aggregate(batch_outs) # Callbacks batch end. - batch_logs.update(_make_logs(model, batch_outs, mode)) + batch_logs.update(training_utils.make_logs(model, batch_outs, mode)) callbacks._call_batch_hook(mode, 'end', step, batch_logs) progbar.on_batch_end(step, batch_logs) @@ -365,8 +312,9 @@ def model_iteration(model, 'pass shuffle="batch".') # Sparse to dense conversion. - for i in indices_for_conversion_to_dense: - ins_batch[i] = ins_batch[i].toarray() + if issparse is not None: + for i in indices_for_conversion_to_dense: + ins_batch[i] = ins_batch[i].toarray() # Callbacks batch_begin. batch_logs = {'batch': batch_index, 'size': len(batch_ids)} @@ -384,7 +332,7 @@ def model_iteration(model, aggregator.aggregate(batch_outs, batch_start, batch_end) # Callbacks batch end. - batch_logs.update(_make_logs(model, batch_outs, mode)) + batch_logs.update(training_utils.make_logs(model, batch_outs, mode)) callbacks._call_batch_hook(mode, 'end', batch_index, batch_logs) progbar.on_batch_end(batch_index, batch_logs) @@ -393,7 +341,7 @@ def model_iteration(model, aggregator.finalize() results = aggregator.results - epoch_logs.update(_make_logs(model, results, mode)) + epoch_logs.update(training_utils.make_logs(model, results, mode)) if len(results) == 1: results = results[0] @@ -411,12 +359,17 @@ def model_iteration(model, mode='test') if not isinstance(val_results, list): val_results = [val_results] - epoch_logs.update(_make_logs(model, val_results, mode, prefix='val_')) + epoch_logs.update( + training_utils.make_logs(model, val_results, mode, prefix='val_')) callbacks.on_epoch_end(epoch, epoch_logs, mode=mode) progbar.on_epoch_end(epoch, epoch_logs) callbacks._call_end_hook(mode) + if model._distribution_strategy: + training_distributed._copy_weights_to_original_model(model, mode) + scope.__exit__(None, None, None) + if mode == 'train': return model.history return results diff --git a/tensorflow/python/keras/engine/training_dataset_test.py b/tensorflow/python/keras/engine/training_dataset_test.py new file mode 100644 index 0000000000..1b2d0e88e3 --- /dev/null +++ b/tensorflow/python/keras/engine/training_dataset_test.py @@ -0,0 +1,344 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for training routines.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import logging + +from absl.testing import parameterized + +import numpy as np + +from tensorflow.python import keras +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util as tf_test_util +from tensorflow.python.keras import metrics as metrics_module +from tensorflow.python.keras import testing_utils +from tensorflow.python.ops.losses import losses_impl +from tensorflow.python.platform import test +from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.training.rmsprop import RMSPropOptimizer + + +class TestTrainingWithDatasetIterators(test.TestCase, parameterized.TestCase): + + @parameterized.parameters( + {'model': 'functional'}, + {'model': 'subclass'}, + ) + @tf_test_util.run_in_graph_and_eager_modes + def test_training_and_eval_methods_on_iterators_single_io(self, model): + if model == 'functional': + model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) + elif model == 'subclass': + model = testing_utils.get_small_sequential_mlp(1, 4) + optimizer = RMSPropOptimizer(learning_rate=0.001) + loss = 'mse' + metrics = ['mae', metrics_module.CategoricalAccuracy()] + model.compile(optimizer, loss, metrics=metrics) + + inputs = np.zeros((10, 3), np.float32) + targets = np.zeros((10, 4), np.float32) + dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) + dataset = dataset.repeat(100) + dataset = dataset.batch(10) + iterator = dataset_ops.make_one_shot_iterator(dataset) + + model.fit(iterator, epochs=1, steps_per_epoch=2, verbose=1) + model.evaluate(iterator, steps=2, verbose=1) + model.predict(iterator, steps=2) + + # Test with validation data + model.fit(iterator, + epochs=1, steps_per_epoch=2, verbose=0, + validation_data=iterator, validation_steps=2) + # Test with validation split + with self.assertRaisesRegexp( + ValueError, '`validation_split` argument is not supported ' + 'when input `x` is a dataset or a dataset iterator'): + model.fit(iterator, + epochs=1, steps_per_epoch=2, verbose=0, + validation_split=0.5, validation_steps=2) + + # Test with sample weight. + sample_weight = np.random.random((10,)) + with self.assertRaisesRegexp( + ValueError, '`sample_weight` argument is not supported ' + 'when input `x` is a dataset or a dataset iterator'): + model.fit( + iterator, + epochs=1, + steps_per_epoch=2, + verbose=0, + sample_weight=sample_weight) + + # Test invalid usage + with self.assertRaisesRegexp(ValueError, + 'you should not specify a target'): + model.fit(iterator, iterator, + epochs=1, steps_per_epoch=2, verbose=0) + + with self.assertRaisesRegexp( + ValueError, 'you should specify the `steps_per_epoch` argument'): + model.fit(iterator, epochs=1, verbose=0) + with self.assertRaisesRegexp(ValueError, + 'you should specify the `steps` argument'): + model.evaluate(iterator, verbose=0) + with self.assertRaisesRegexp(ValueError, + 'you should specify the `steps` argument'): + model.predict(iterator, verbose=0) + + @tf_test_util.run_in_graph_and_eager_modes + def test_get_next_op_created_once(self): + model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) + optimizer = RMSPropOptimizer(learning_rate=0.001) + loss = 'mse' + metrics = ['mae'] + model.compile(optimizer, loss, metrics=metrics) + + inputs = np.zeros((10, 3), np.float32) + targets = np.zeros((10, 4), np.float32) + dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) + dataset = dataset.repeat(100) + dataset = dataset.batch(10) + iterator = dataset_ops.make_one_shot_iterator(dataset) + + model.fit(iterator, epochs=1, steps_per_epoch=2, verbose=1) + # Finalize graph to make sure we are not appending another iterator + # get_next op in the graph. + ops.get_default_graph().finalize() + model.fit(iterator, epochs=1, steps_per_epoch=2, verbose=1) + + @tf_test_util.run_in_graph_and_eager_modes + def test_iterators_running_out_of_data(self): + model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) + optimizer = RMSPropOptimizer(learning_rate=0.001) + loss = 'mse' + metrics = ['mae'] + model.compile(optimizer, loss, metrics=metrics) + + inputs = np.zeros((10, 3), np.float32) + targets = np.zeros((10, 4), np.float32) + dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) + dataset = dataset.repeat(2) + dataset = dataset.batch(10) + iterator = dataset_ops.make_one_shot_iterator(dataset) + + with test.mock.patch.object(logging, 'warning') as mock_log: + model.fit(iterator, epochs=1, steps_per_epoch=3, verbose=0) + self.assertRegexpMatches( + str(mock_log.call_args), + 'dataset iterator ran out of data') + + +class TestTrainingWithDataset(test.TestCase, parameterized.TestCase): + + @tf_test_util.run_in_graph_and_eager_modes + def test_calling_model_on_same_dataset(self): + model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) + optimizer = RMSPropOptimizer(learning_rate=0.001) + loss = 'mse' + metrics = ['mae'] + model.compile(optimizer, loss, metrics=metrics) + + inputs = np.zeros((10, 3), np.float32) + targets = np.zeros((10, 4), np.float32) + dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) + dataset = dataset.repeat(100) + dataset = dataset.batch(10) + + # Call fit with validation data + model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0, + validation_data=dataset, validation_steps=2) + # Finalize the graph to make sure new ops aren't added when calling on the + # same dataset + ops.get_default_graph().finalize() + model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0, + validation_data=dataset, validation_steps=2) + + @tf_test_util.run_in_graph_and_eager_modes + def test_training_and_eval_methods_on_dataset(self): + model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) + optimizer = RMSPropOptimizer(learning_rate=0.001) + loss = 'mse' + metrics = ['mae', metrics_module.CategoricalAccuracy()] + model.compile(optimizer, loss, metrics=metrics) + + inputs = np.zeros((10, 3), np.float32) + targets = np.zeros((10, 4), np.float32) + dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) + dataset = dataset.repeat(100) + dataset = dataset.batch(10) + + model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=1) + model.evaluate(dataset, steps=2, verbose=1) + model.predict(dataset, steps=2) + + # Test with validation data + model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0, + validation_data=dataset, validation_steps=2) + + # Test with validation split + with self.assertRaisesRegexp( + ValueError, '`validation_split` argument is not supported ' + 'when input `x` is a dataset or a dataset iterator'): + model.fit(dataset, + epochs=1, steps_per_epoch=2, verbose=0, + validation_split=0.5, validation_steps=2) + + # Test with sample weight. + sample_weight = np.random.random((10,)) + with self.assertRaisesRegexp( + ValueError, '`sample_weight` argument is not supported ' + 'when input `x` is a dataset or a dataset iterator'): + model.fit( + dataset, + epochs=1, + steps_per_epoch=2, + verbose=0, + sample_weight=sample_weight) + + # Test invalid usage + with self.assertRaisesRegexp(ValueError, + 'you should not specify a target'): + model.fit(dataset, dataset, + epochs=1, steps_per_epoch=2, verbose=0) + + with self.assertRaisesRegexp( + ValueError, 'you should specify the `steps_per_epoch` argument'): + model.fit(dataset, epochs=1, verbose=0) + with self.assertRaisesRegexp(ValueError, + 'you should specify the `steps` argument'): + model.evaluate(dataset, verbose=0) + with self.assertRaisesRegexp(ValueError, + 'you should specify the `steps` argument'): + model.predict(dataset, verbose=0) + + @tf_test_util.run_in_graph_and_eager_modes + def test_dataset_with_sample_weights(self): + model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) + optimizer = RMSPropOptimizer(learning_rate=0.001) + loss = 'mse' + metrics = ['mae', metrics_module.CategoricalAccuracy()] + model.compile(optimizer, loss, metrics=metrics) + + inputs = np.zeros((10, 3), np.float32) + targets = np.zeros((10, 4), np.float32) + sample_weights = np.ones((10), np.float32) + dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets, + sample_weights)) + dataset = dataset.repeat(100) + dataset = dataset.batch(10) + + model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=1) + model.evaluate(dataset, steps=2, verbose=1) + model.predict(dataset, steps=2) + + @parameterized.parameters( + {'model': 'functional'}, + {'model': 'subclass'}, + ) + @tf_test_util.run_in_graph_and_eager_modes + def test_dataset_with_sparse_labels(self, model): + if model == 'functional': + model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) + elif model == 'subclass': + model = testing_utils.get_small_sequential_mlp(1, 4) + + for loss in ['sparse_categorical_crossentropy', + losses_impl.sparse_softmax_cross_entropy]: + optimizer = RMSPropOptimizer(learning_rate=0.001) + model.compile(optimizer, loss) + + inputs = np.zeros((10, 3), dtype=np.float32) + targets = np.random.randint(0, 4, size=10, dtype=np.int32) + dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) + dataset = dataset.repeat(100) + dataset = dataset.batch(10) + + model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=1) + + @tf_test_util.run_deprecated_v1 + def test_dataset_input_shape_validation(self): + with self.cached_session(): + model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) + model.compile(optimizer=RMSPropOptimizer(learning_rate=0.001), loss='mse') + + # User forgets to batch the dataset + inputs = np.zeros((10, 3)) + targets = np.zeros((10, 4)) + dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) + dataset = dataset.repeat(100) + + with self.assertRaisesRegexp( + ValueError, + r'expected (.*?) to have shape \(3,\) but got array with shape \(1,\)' + ): + model.train_on_batch(dataset) + + # Wrong input shape + inputs = np.zeros((10, 5)) + targets = np.zeros((10, 4)) + dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) + dataset = dataset.repeat(100) + dataset = dataset.batch(10) + + with self.assertRaisesRegexp(ValueError, + r'expected (.*?) to have shape \(3,\)'): + model.train_on_batch(dataset) + + +class TestMetricsWithDatasetIterators(test.TestCase): + + @tf_test_util.run_in_graph_and_eager_modes + def test_metrics_correctness_with_iterator(self): + model = keras.Sequential() + model.add( + keras.layers.Dense( + 8, activation='relu', input_dim=4, kernel_initializer='ones')) + model.add( + keras.layers.Dense( + 1, activation='sigmoid', kernel_initializer='ones')) + model.compile( + loss='binary_crossentropy', + metrics=['accuracy', metrics_module.BinaryAccuracy()], + optimizer=RMSPropOptimizer(learning_rate=0.001)) + + np.random.seed(123) + x = np.random.randint(10, size=(100, 4)).astype(np.float32) + y = np.random.randint(2, size=(100, 1)).astype(np.float32) + dataset = dataset_ops.Dataset.from_tensor_slices((x, y)) + dataset = dataset.batch(10) + iterator = dataset_ops.make_one_shot_iterator(dataset) + outs = model.evaluate(iterator, steps=10) + self.assertEqual(np.around(outs[1], decimals=1), 0.5) + self.assertEqual(np.around(outs[2], decimals=1), 0.5) + + y = np.zeros((100, 1), dtype=np.float32) + dataset = dataset_ops.Dataset.from_tensor_slices((x, y)) + dataset = dataset.repeat(100) + dataset = dataset.batch(10) + iterator = dataset_ops.make_one_shot_iterator(dataset) + outs = model.evaluate(iterator, steps=10) + self.assertEqual(outs[1], 0.) + self.assertEqual(outs[2], 0.) + + +if __name__ == '__main__': + test.main() diff --git a/tensorflow/python/keras/engine/training_distributed.py b/tensorflow/python/keras/engine/training_distributed.py index 808d7c9f33..473f06ded7 100644 --- a/tensorflow/python/keras/engine/training_distributed.py +++ b/tensorflow/python/keras/engine/training_distributed.py @@ -19,9 +19,12 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import enum +import enum # pylint: disable=g-bad-import-order import numpy as np +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import reduce_util as ds_reduce_util +from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors @@ -34,9 +37,7 @@ from tensorflow.python.keras.engine import distributed_training_utils from tensorflow.python.keras.utils.generic_utils import Progbar from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops -from tensorflow.python.ops import variable_scope from tensorflow.python.platform import tf_logging as logging -from tensorflow.python.training import distribute as distribute_lib from tensorflow.python.util import nest @@ -48,180 +49,15 @@ class _Mode(enum.Enum): # TODO(priyag, sourabhbajaj): Refactor this file to address code duplication. -def fit_loop( - model, - iterator, - epochs=100, - verbose=1, - callbacks=None, - val_iterator=None, - initial_epoch=0, - steps_per_epoch=None, - validation_steps=None): - """Fit loop for training with DistributionStrategy. - - Arguments: - model: Keras Model instance. - iterator: Iterator for input data. - epochs: Number of times to iterate over the data - verbose: Integer, Verbosity mode, 0, 1 or 2 - callbacks: List of callbacks to be called during training - val_iterator: Iterator for validation data. - initial_epoch: Epoch at which to start training - (useful for resuming a previous training run) - steps_per_epoch: Total number of steps (batches of samples) - before declaring one epoch finished and starting the - next epoch. Ignored with the default value of `None`. - validation_steps: Number of steps to run validation for - (only if doing validation from data tensors). - Ignored with the default value of `None`. - - Returns: - `History` object. - - Raises: - ValueError: in case of invalid arguments. - """ - current_strategy = model._distribution_strategy - - # TODO(priyag, sourabhbajaj): Remove this when the codepaths are merged. - if current_strategy.__class__.__name__ == 'TPUStrategy': - return _experimental_fit_loop( - model, iterator, epochs, verbose, callbacks, initial_epoch, - steps_per_epoch, val_iterator, validation_steps) - - if not model._grouped_model: - clone_model_on_replicas(model, current_strategy, make_callback_model=True) - - def _per_device_fit_function(model): - model._make_fit_function() - return (model._fit_function.inputs, model._fit_function.outputs, - model._fit_function.updates_op, model._fit_function.session_kwargs) - - inputs, targets, sample_weights = _get_input_from_iterator(iterator, model) - with current_strategy.scope(): - # Create train ops on each of the devices when we call - # `_per_device_fit_function`. - (grouped_inputs, grouped_outputs, grouped_updates, - grouped_session_args) = current_strategy.call_for_each_replica( - _per_device_fit_function, args=(model._grouped_model,)) - # Unwrap all the per device values returned from `call_for_each_replica`. - # Unwrapping per device values gives you a list of values that can be - # used to construct a new train function that is composed of update ops on - # all the devices over which the model is distributed. - (all_inputs, all_outputs, all_updates, - all_session_args) = distributed_training_utils.unwrap_values( - current_strategy, grouped_inputs, grouped_outputs, - grouped_updates, grouped_session_args, with_loss_tensor=True) - - # Dataset inputs and targets are also per devices values that need to be - # unwrapped. - dataset_inputs = distributed_training_utils.flatten_perdevice_values( - current_strategy, inputs) - dataset_targets = distributed_training_utils.flatten_perdevice_values( - current_strategy, targets) - - # Create a train function that is composed of all the parameters above. - distributed_fit_function = K.function( - all_inputs, - all_outputs, - updates=all_updates, - name='distributed_fit_function', - **all_session_args) - - # We need to set sample_weights to None since there are sample weight - # placeholders that are created with default values. - sample_weights = [None for _ in range( - len(model.outputs) * current_strategy.num_replicas_in_sync)] - if not isinstance(K.learning_phase(), int): - ins = dataset_inputs + dataset_targets + sample_weights + [1] - else: - ins = dataset_inputs + dataset_targets - - do_validation = False - if validation_steps: - do_validation = True - - # Copy the weights from the original model to each of the replicated models. - orig_model_weights = model.get_weights() - distributed_model = current_strategy.unwrap(model._grouped_model)[0] - distributed_training_utils.set_weights( - current_strategy, distributed_model, orig_model_weights) - - callbacks = cbks.configure_callbacks( - callbacks, - model, - do_validation=do_validation, - val_inputs=None, - val_targets=None, - epochs=epochs, - steps_per_epoch=steps_per_epoch, - verbose=verbose) - out_labels = model.metrics_names or [] - callbacks.on_train_begin() - - assert steps_per_epoch is not None - - for epoch in range(initial_epoch, epochs): - # Reset stateful metrics - for m in model.stateful_metric_functions: - m.reset_states() - callbacks.on_epoch_begin(epoch) - epoch_logs = {} - for step_index in range(steps_per_epoch): - batch_logs = {'batch': step_index, 'size': 1} - callbacks.on_batch_begin(step_index, batch_logs) - try: - outs = distributed_fit_function(ins) - except errors.OutOfRangeError: - logging.warning('Your dataset iterator ran out of data; ' - 'interrupting training. Make sure that your dataset ' - 'can generate at least `steps_per_epoch * epochs` ' - 'batches (in this case, %d batches).' % - steps_per_epoch * epochs) - break - - if not isinstance(outs, list): - outs = [outs] - for l, o in zip(out_labels, outs): - batch_logs[l] = o - callbacks.on_batch_end(step_index, batch_logs) - if callbacks.model.stop_training: - break - if do_validation: - val_outs = test_loop( - model, - val_iterator, - steps=validation_steps, - verbose=0) - if not isinstance(val_outs, list): - val_outs = [val_outs] - # Same labels assumed. - for l, o in zip(out_labels, val_outs): - epoch_logs['val_' + l] = o - - callbacks.on_epoch_end(epoch, epoch_logs) - if callbacks.model.stop_training: - break - callbacks.on_train_end() - - # Copy the weights back from the replicated model to the original model. - updated_weights = current_strategy.unwrap( - model._grouped_model)[0].get_weights() - model.set_weights(updated_weights) - return model.history - - -def _experimental_fit_loop( - model, - iterator, - epochs=100, - verbose=1, - callbacks=None, - initial_epoch=0, - steps_per_epoch=None, - val_iterator=None, - validation_steps=None): +def experimental_fit_loop(model, + iterator, + epochs=100, + verbose=1, + callbacks=None, + initial_epoch=0, + steps_per_epoch=None, + val_iterator=None, + validation_steps=None): """Fit loop for training with TPU DistributionStrategy. Arguments: @@ -259,11 +95,12 @@ def _experimental_fit_loop( K.set_learning_phase(1) out_labels = model.metrics_names or [] - def step_fn(ctx, inputs, targets): + def step_fn(ctx, inputs): """Clones the model and calls make_fit_function.""" # TODO(priyag, sourabhbajaj): The model gets cloned every time # fit/test/predict is called. We should look into caching this keyed on # input shapes. + inputs, targets = inputs clone_model_on_replicas( model, current_strategy, @@ -273,7 +110,7 @@ def _experimental_fit_loop( mode=_Mode.TRAIN) (grouped_inputs, grouped_outputs, grouped_updates, - grouped_session_args) = current_strategy.call_for_each_replica( + grouped_session_args) = current_strategy.extended.call_for_each_replica( _per_device_fit_function, args=(model._grouped_model_train,)) (all_inputs, all_outputs, all_updates, all_session_args) = distributed_training_utils.unwrap_values( @@ -288,12 +125,12 @@ def _experimental_fit_loop( for label, output in zip(out_labels, combined_fn.outputs): if label == 'loss': - aggregation = distribute_lib.get_loss_reduction() + reduce_op = distribute_lib.get_loss_reduction() else: - # We aggregate all other metrics using mean for now. This is temporary + # We reduce all other metrics using mean for now. This is temporary # workaround until new metrics are in place. - aggregation = variable_scope.VariableAggregation.MEAN - ctx.set_last_step_output(label, output, aggregation) + reduce_op = ds_reduce_util.ReduceOp.MEAN + ctx.set_last_step_output(label, output, reduce_op) # TODO(priyag, sourabhbajaj): Ignoring these things from the combined_fn: # feed_dict, session kwargs, run options, run_metadata for now. These should @@ -303,19 +140,20 @@ def _experimental_fit_loop( # Add initial dummy values for loss and other metric tensors. initial_loop_values = {} initial_loop_values['loss'] = constant_op.constant(1e7) - for name, tensor in zip(model.metrics_names[1:], model.metrics_tensors): + for name in model.metrics_names[1:]: + tensor = model._all_stateful_metrics_tensors[name] initial_loop_values[name] = array_ops.zeros(tensor.shape, tensor.dtype) if steps_per_epoch is None: raise ValueError('`steps_per_epoch` should be specified when calling ' '`fit` on the model.') steps_per_run = K.variable( - value=min(steps_per_epoch, current_strategy.steps_per_run), + value=min(steps_per_epoch, current_strategy.extended.steps_per_run), dtype='int32', name='steps_per_run') with current_strategy.scope(): - ctx = current_strategy.run_steps_on_dataset( + ctx = current_strategy.extended.experimental_run_steps_on_iterator( step_fn, iterator, iterations=steps_per_run, initial_loop_values=initial_loop_values) @@ -334,17 +172,16 @@ def _experimental_fit_loop( callbacks, model, do_validation=do_validation, - val_inputs=None, - val_targets=None, epochs=epochs, steps_per_epoch=steps_per_epoch, verbose=verbose) # Calculate the steps each time on the device. - steps_to_run = [current_strategy.steps_per_run] * ( - steps_per_epoch // current_strategy.steps_per_run) - if steps_per_epoch % current_strategy.steps_per_run: - steps_to_run.append(steps_per_epoch % current_strategy.steps_per_run) + steps_to_run = [current_strategy.extended.steps_per_run] * ( + steps_per_epoch // current_strategy.extended.steps_per_run) + if steps_per_epoch % current_strategy.extended.steps_per_run: + steps_to_run.append( + steps_per_epoch % current_strategy.extended.steps_per_run) callbacks.on_train_begin() for epoch in range(initial_epoch, epochs): @@ -384,7 +221,7 @@ def _experimental_fit_loop( model._grouped_model_train)[0].get_weights() model.set_weights(updated_weights) - val_outs = _experimental_test_loop( + val_outs = experimental_test_loop( # pylint: disable=undefined-variable model, val_iterator, steps=validation_steps, @@ -411,105 +248,11 @@ def _experimental_fit_loop( return model.history -def test_loop(model, iterator, verbose=0, steps=None): - """Test loop for evaluating with DistributionStrategy. - - Arguments: - model: Keras Model instance. - iterator: Iterator for input data. - verbose: Integer, Verbosity mode 0 or 1. - steps: Total number of steps (batches of samples) - before declaring predictions finished. - Ignored with the default value of `None`. - - Returns: - Scalar loss (if the model has a single output and no metrics) - or list of scalars (if the model has multiple outputs - and/or metrics). The attribute `model.metrics_names` will give you - the display labels for the outputs. - """ - current_strategy = model._distribution_strategy - - # TODO(priyag, sourabhbajaj): Remove this when the codepaths are merged. - if current_strategy.__class__.__name__ == 'TPUStrategy': - return _experimental_test_loop(model, iterator, verbose, steps) - - if not model._grouped_model: - clone_model_on_replicas(model, current_strategy) - - def _per_device_eval_function(model): - model._make_eval_function() - return (model._eval_function.inputs, model._eval_function.outputs, - model._eval_function.updates_op, - model._eval_function.session_kwargs) - - inputs, targets, sample_weights = _get_input_from_iterator(iterator, model) - with current_strategy.scope(): - (grouped_inputs, grouped_outputs, grouped_updates, - grouped_session_args) = current_strategy.call_for_each_replica( - _per_device_eval_function, args=(model._grouped_model,)) - - (all_inputs, all_outputs, all_updates, - all_session_args) = distributed_training_utils.unwrap_values( - current_strategy, grouped_inputs, grouped_outputs, grouped_updates, - grouped_session_args, with_loss_tensor=True) - - dataset_inputs = distributed_training_utils.flatten_perdevice_values( - current_strategy, inputs) - dataset_targets = distributed_training_utils.flatten_perdevice_values( - current_strategy, targets) - - distributed_test_function = K.function( - all_inputs, all_outputs, - updates=all_updates, - name='distributed_test_function', - **all_session_args) - - # We need to set sample_weights to None since there are sample weight - # placeholders that are created with default values. - sample_weights = [None for _ in range( - len(model.outputs) * current_strategy.num_replicas_in_sync)] - if not isinstance(K.learning_phase(), int): - ins = dataset_inputs + dataset_targets + sample_weights + [0] - else: - ins = dataset_inputs + dataset_targets - - for m in model.stateful_metric_functions: - m.reset_states() - - outs = [] - if verbose == 1: - progbar = Progbar(target=steps) - - # Copy the weights from the original model to each of the replicated models. - orig_model_weights = model.get_weights() - distributed_model = current_strategy.unwrap(model._grouped_model)[0] - distributed_training_utils.set_weights( - current_strategy, distributed_model, orig_model_weights) - - assert steps is not None - for step in range(steps): - batch_outs = distributed_test_function(ins) - if isinstance(batch_outs, list): - if step == 0: - outs = [0.] * len(batch_outs) - outs[0] += batch_outs[0] # index 0 = 'loss' - outs[1:] = batch_outs[1:] - else: - if step == 0: - outs.append(0.) - outs[0] += batch_outs # index 0 = 'loss' - if verbose >= 1: - progbar.update(step + 1) - outs[0] /= steps # index 0 = 'loss' - - if len(outs) == 1: - return outs[0] - return outs - - -def _experimental_test_loop(model, iterator, verbose=0, steps=None, - initialize_finalize_strategy=True): +def experimental_test_loop(model, + iterator, + verbose=0, + steps=None, + initialize_finalize_strategy=True): """Test loop for evaluating with TPU DistributionStrategy. Arguments: @@ -541,11 +284,12 @@ def _experimental_test_loop(model, iterator, verbose=0, steps=None, # TODO(priyag, sourabhbajaj): This should likely not be hardcoded here. K.set_learning_phase(0) - def step_fn(ctx, inputs, targets): + def step_fn(ctx, inputs): """Clones the model and calls make_eval_function.""" # TODO(priyag, sourabhbajaj): The model gets cloned every time # fit/test/predict is called. We should look into caching this keyed on # input shapes. + inputs, targets = inputs clone_model_on_replicas( model, current_strategy, @@ -555,7 +299,7 @@ def _experimental_test_loop(model, iterator, verbose=0, steps=None, mode=_Mode.TEST) (grouped_inputs, grouped_outputs, grouped_updates, - grouped_session_args) = current_strategy.call_for_each_replica( + grouped_session_args) = current_strategy.extended.call_for_each_replica( _per_device_eval_function, args=(model._grouped_model_test,)) (all_inputs, all_outputs, all_updates, @@ -571,25 +315,26 @@ def _experimental_test_loop(model, iterator, verbose=0, steps=None, for label, output in zip(model.metrics_names, combined_fn.outputs): if label == 'loss': - aggregation = distribute_lib.get_loss_reduction() + reduce_op = distribute_lib.get_loss_reduction() else: - # We aggregate all other metrics using mean for now. This is temporary + # We reduce all other metrics using mean for now. This is temporary # workaround until new metrics are in place. - aggregation = variable_scope.VariableAggregation.MEAN - ctx.set_last_step_output(label, output, aggregation) + reduce_op = ds_reduce_util.ReduceOp.MEAN + ctx.set_last_step_output(label, output, reduce_op) return combined_fn.updates_op # Add initial dummy values for loss and other metric tensors. initial_loop_values = {} initial_loop_values['loss'] = constant_op.constant(1e7) - for name, tensor in zip(model.metrics_names[1:], model.metrics_tensors): + for name in model.metrics_names[1:]: + tensor = model._all_stateful_metrics_tensors[name] initial_loop_values[name] = array_ops.zeros(tensor.shape, tensor.dtype) with current_strategy.scope(): # TODO(priyag): Use steps_per_run when we use new metrics as they will # allow handling metric computation at each step using variables. - ctx = current_strategy.run_steps_on_dataset( + ctx = current_strategy.extended.experimental_run_steps_on_iterator( step_fn, iterator, iterations=1, initial_loop_values=initial_loop_values) @@ -625,103 +370,7 @@ def _experimental_test_loop(model, iterator, verbose=0, steps=None, return outs -def predict_loop(model, iterator, verbose=0, steps=None): - """Predict loop for predicting with DistributionStrategy. - - Arguments: - model: Keras Model instance. - iterator: Iterator for input data. - verbose: Integer, Verbosity mode 0 or 1. - steps: Total number of steps (batches of samples) - before declaring `_predict_loop` finished. - Ignored with the default value of `None`. - - Returns: - Array of predictions (if the model has a single output) - or list of arrays of predictions - (if the model has multiple outputs). - """ - current_strategy = model._distribution_strategy - - # TODO(priyag, sourabhbajaj): Remove this when the codepaths are merged. - if current_strategy.__class__.__name__ == 'TPUStrategy': - return _experimental_predict_loop(model, iterator, verbose, steps) - - if not model._grouped_model: - clone_model_on_replicas(model, current_strategy) - - def _per_device_predict_function(model): - model._make_predict_function() - return (model.predict_function.inputs, - model.predict_function.outputs, - model.predict_function.updates_op, - model.predict_function.session_kwargs) - - inputs, _, _ = _get_input_from_iterator(iterator, model) - with current_strategy.scope(): - (grouped_inputs, grouped_outputs, grouped_updates, - grouped_session_args) = current_strategy.call_for_each_replica( - _per_device_predict_function, args=(model._grouped_model,)) - - (all_inputs, all_outputs, all_updates, - all_session_args) = distributed_training_utils.unwrap_values( - current_strategy, grouped_inputs, grouped_outputs, grouped_updates, - grouped_session_args) - - dataset_inputs = distributed_training_utils.flatten_perdevice_values( - current_strategy, inputs) - - distributed_predict_function = K.function( - all_inputs, all_outputs, - updates=all_updates, - name='distributed_predict_function', - **all_session_args) - - if not isinstance(K.learning_phase(), int): - ins = dataset_inputs + [0] - else: - ins = dataset_inputs - - if verbose == 1: - progbar = Progbar(target=steps) - - # Copy the weights from the original model to each of the replicated models. - orig_model_weights = model.get_weights() - distributed_model = current_strategy.unwrap(model._grouped_model)[0] - distributed_training_utils.set_weights( - current_strategy, distributed_model, orig_model_weights) - - num_replicas = current_strategy.num_replicas_in_sync - # Since we do not know how many samples we will see, we cannot - # pre-allocate the returned Numpy arrays. Instead, we store one array per - # batch seen and concatenate them upon returning. - unconcatenated_outs = [] - assert steps is not None - for step in range(steps): - batch_outs = distributed_predict_function(ins) - if not isinstance(batch_outs, list): - batch_outs = [batch_outs] - if step == 0: - # batch_outs gives you the number of model outputs. In the distributed - # case this will be number of model_outputs * num_replicas. - for _ in range(len(model.outputs)): - unconcatenated_outs.append([]) - for i in range(len(model.outputs)): - nested_outs = batch_outs[i * num_replicas: - i * num_replicas + num_replicas] - outs = nest.flatten(nested_outs) - unconcatenated_outs[i].extend(outs) - if verbose >= 1: - progbar.update(step + 1) - if len(unconcatenated_outs) == 1: - return np.concatenate(unconcatenated_outs[0], axis=0) - return [ - np.concatenate(unconcatenated_outs[i], axis=0) - for i in range(len(unconcatenated_outs)) - ] - - -def _experimental_predict_loop(model, iterator, verbose=0, steps=None): +def experimental_predict_loop(model, iterator, verbose=0, steps=None): """Predict loop for predicting with TPU DistributionStrategy. Arguments: @@ -750,7 +399,7 @@ def _experimental_predict_loop(model, iterator, verbose=0, steps=None): model.predict_function.updates_op, model.predict_function.session_kwargs) - def step_fn(ctx, *inputs): + def step_fn(ctx, inputs): """Clones the model and calls make_predict_function.""" # TODO(priyag, sourabhbajaj): The model gets cloned every time @@ -764,7 +413,7 @@ def _experimental_predict_loop(model, iterator, verbose=0, steps=None): mode=_Mode.PREDICT) (grouped_inputs, grouped_outputs, grouped_updates, - grouped_session_args) = current_strategy.call_for_each_replica( + grouped_session_args) = current_strategy.extended.call_for_each_replica( _per_device_predict_function, args=(model._grouped_model_predict,)) (all_inputs, all_outputs, all_updates, @@ -795,7 +444,7 @@ def _experimental_predict_loop(model, iterator, verbose=0, steps=None): with current_strategy.scope(): # TODO(priyag, sourabhbajaj): Support steps_per_run if/when we add outfeed. - ctx = current_strategy.run_steps_on_dataset( + ctx = current_strategy.extended.experimental_run_steps_on_iterator( step_fn, iterator, iterations=1, initial_loop_values=initial_loop_values) @@ -835,7 +484,17 @@ def _experimental_predict_loop(model, iterator, verbose=0, steps=None): ] -def _clone_and_build_model(model, inputs=None, targets=None): +def _custom_compile_for_predict(model): + """Custom compile for TPU predict mode.""" + model.total_loss = None + model._fit_function = None + model._eval_function = None + model.train_function = None + model.test_function = None + model.predict_function = None + + +def _clone_and_build_model(model, inputs=None, targets=None, mode=None): """Clone and build the given keras_model.""" # We need to set the import here since we run into a circular dependency # error. @@ -862,23 +521,27 @@ def _clone_and_build_model(model, inputs=None, targets=None): if isinstance(targets, tuple): targets = nest.flatten(targets) - cloned_model.compile( - optimizer, - model.loss, - metrics=metrics_module.clone_metrics(model.metrics), - loss_weights=model.loss_weights, - sample_weight_mode=model.sample_weight_mode, - weighted_metrics=metrics_module.clone_metrics(model.weighted_metrics), - target_tensors=targets) + if mode == _Mode.PREDICT: + _custom_compile_for_predict(cloned_model) + else: + cloned_model.compile( + optimizer, + model.loss, + metrics=metrics_module.clone_metrics(model._compile_metrics), + loss_weights=model.loss_weights, + sample_weight_mode=model.sample_weight_mode, + weighted_metrics=metrics_module.clone_metrics( + model._compile_weighted_metrics), + target_tensors=targets) return cloned_model def clone_model_on_replicas(model, strategy, make_callback_model=False, inputs=None, targets=None, mode=None): """Create a cloned model on each replica.""" - with strategy.scope(): - grouped_model = strategy.call_for_each_replica( - _clone_and_build_model, args=(model, inputs, targets)) + with K.get_graph().as_default(), strategy.scope(): + grouped_model = strategy.extended.call_for_each_replica( + _clone_and_build_model, args=(model, inputs, targets, mode)) if mode is _Mode.TRAIN: model._grouped_model_train = grouped_model elif mode is _Mode.TEST: @@ -915,3 +578,149 @@ def _get_input_from_iterator(iterator, model): model._standardize_weights(x_values, y_values, sample_weight=sample_weights_values) return x, y, sample_weights + + +def _make_execution_function(model, mode): + """Makes function to run one step of distributed model execution.""" + if context.executing_eagerly(): + return _make_eager_execution_function(model, mode) + + strategy = model._distribution_strategy + if not model._grouped_model: + clone_model_on_replicas( + model, strategy, make_callback_model=(mode == 'train')) + + def _per_device_function(model): + f = model._make_execution_function(mode) + return (f.inputs, f.outputs, f.updates_op, f.session_kwargs) + + with strategy.scope(): + # Create train ops on each of the devices when we call + # `_per_device_fit_function`. + (grouped_inputs, grouped_outputs, grouped_updates, + grouped_session_args) = strategy.extended.call_for_each_replica( + _per_device_function, args=(model._grouped_model,)) + + if mode == 'train': + # Initialize the variables in the replicated model. This is necessary for + # multi-worker training because on some workers, initialization is not + # needed. This method does initialization or waiting for initialization + # according to the context object of distribute coordinator. + distributed_training_utils.init_restore_or_wait_for_variables() + + # Unwrap all the per device values returned from `call_for_each_replica`. + # Unwrapping per device values gives you a list of values that can be + # used to construct a new train function that is composed of update ops on + # all the devices over which the model is distributed. + (all_inputs, all_outputs, all_updates, + all_session_args) = distributed_training_utils.unwrap_values( + strategy, + grouped_inputs, + grouped_outputs, + grouped_updates, + grouped_session_args, + with_loss_tensor=(mode != 'predict')) + + return K.function( + all_inputs, + all_outputs, + updates=all_updates, + name='distributed_{}_function'.format(mode), + **all_session_args) + + +def _make_eager_execution_function(model, mode): + """Makes function to run one step of distributed model eager execution.""" + strategy = model._distribution_strategy + if not model._grouped_model: + clone_model_on_replicas( + model, strategy, make_callback_model=(mode == 'train')) + + def _per_device_function(model): + f = model._make_execution_function(mode) + return (f.inputs, f.outputs) + + # NOTE(priyag): Try creating a new FuncGraph within DS scope instead of using + # the global one. + with K.get_graph().as_default(), strategy.scope(): + # Create train ops on each of the devices when we call + # `_per_device_fit_function`. + (grouped_inputs, grouped_outputs) = strategy.call_for_each_replica( + _per_device_function, args=(model._grouped_model,)) + + # Unwrap all the per device values returned from `call_for_each_replica`. + # Unwrapping per device values gives you a list of values that can be + # used to construct a new train function that is composed of inptus/outputs + # on all the devices over which the model is distributed. + (all_inputs, all_outputs, _, _) = distributed_training_utils.unwrap_values( + strategy, + grouped_inputs, + grouped_outputs, + with_loss_tensor=(mode != 'predict')) + + return K.function( + all_inputs, + all_outputs, + name='eager_distributed_{}_function'.format(mode)) + + +def _prepare_feed_values(model, inputs, targets, sample_weights, mode): + """Prepare feed values to the model execution function. + + Arguments: + model: Model to prepare feed values for. + inputs: List or dict of model inputs. + targets: Optional list of model targets. + sample_weights: Optional list of sample weight arrays. + mode: One of 'train'/'test'/'predict'. + + Returns: + Feed values for the model in the given mode. + """ + strategy = model._distribution_strategy + inputs, targets, sample_weights = _get_input_from_iterator(inputs, model) + inputs = distributed_training_utils.flatten_perdevice_values(strategy, inputs) + targets = distributed_training_utils.flatten_perdevice_values( + strategy, targets) + if mode == 'predict': + sample_weights = [] + targets = [] + else: + sample_weights = [ + None for _ in range(len(model.outputs) * strategy.num_replicas_in_sync) + ] + ins = inputs + targets + sample_weights + if mode == 'train' and not isinstance(K.symbolic_learning_phase(), int): + ins += [True] + return ins + + +def _copy_weights_to_distributed_model(model): + """Copies weights from original model to distributed models.""" + if model._distribution_strategy: + # Copy the weights from the original model to each of the replicated models. + orig_model_weights = model.get_weights() + distributed_model = model._distribution_strategy.unwrap( + model._grouped_model)[0] + distributed_training_utils.set_weights( + model._distribution_strategy, distributed_model, orig_model_weights) + + +def _copy_weights_to_original_model(model, mode): + """Copies weights from first distributed model back to original model.""" + if model._distribution_strategy and mode == 'train': + updated_weights = model._distribution_strategy.unwrap( + model._grouped_model)[0].get_weights() + model.set_weights(updated_weights) + + +def _per_device_aggregate_batch(batch_outs, model, mode): + """Aggregates the per-device batch-level outputs from a distributed step.""" + if model._distribution_strategy is not None and mode == 'predict': + total_batch_outs = [] + for i in range(len(model.outputs)): + num_replicas = model._distribution_strategy.num_replicas_in_sync + nested_outs = batch_outs[i * num_replicas:i * num_replicas + num_replicas] + total_batch_outs.append(np.concatenate(nest.flatten(nested_outs))) + return total_batch_outs + return batch_outs diff --git a/tensorflow/python/keras/engine/training_eager.py b/tensorflow/python/keras/engine/training_eager.py index 9131df5cd0..1d1cec1c50 100644 --- a/tensorflow/python/keras/engine/training_eager.py +++ b/tensorflow/python/keras/engine/training_eager.py @@ -19,30 +19,20 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import copy -import threading +import collections -import numpy as np - -from tensorflow.python.data.ops import iterator_ops -from tensorflow.python.eager import function as eager_function from tensorflow.python.eager.backprop import GradientTape -from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util from tensorflow.python.keras import backend -from tensorflow.python.keras import callbacks as cbks -from tensorflow.python.keras import metrics as metrics_module +from tensorflow.python.keras import losses as losses_module from tensorflow.python.keras.engine import training_utils from tensorflow.python.keras.utils import generic_utils +from tensorflow.python.keras.utils.losses_utils import squeeze_or_expand_dimensions from tensorflow.python.ops import math_ops from tensorflow.python.platform import tf_logging as logging -# A lock for assigning polymorphic functions to models in a thread-safe way -_graph_function_building_lock = threading.Lock() - - def _eager_loss_fn(outputs, targets, loss_fn, output_name): with backend.name_scope(output_name + '_loss'): loss = loss_fn(targets, outputs) @@ -133,11 +123,24 @@ def _model_loss(model, else: weights = None mask = masks[i] - - weighted_masked_fn = training_utils.weighted_masked_objective(loss_fn) with backend.name_scope(model.output_names[i] + '_loss'): - output_loss = weighted_masked_fn( - targets[i], outs[i], weights, mask=mask) + if isinstance(loss_fn, losses_module.Loss): + if mask is not None: + mask = math_ops.cast(mask, outs[i].dtype) + # Update weights with mask. + if weights is None: + weights = mask + else: + # Update dimensions of weights to match with mask if possible. + mask, _, weights = squeeze_or_expand_dimensions( + mask, None, weights) + weights *= mask + output_loss = loss_fn(targets[i], outs[i], sample_weight=weights) + else: + weighted_masked_fn = training_utils.weighted_masked_objective(loss_fn) + output_loss = weighted_masked_fn( + targets[i], outs[i], weights, mask=mask) + # If the number of outputs is 1 then we don't append the loss metric # associated with each model output. When there are multiple outputs # associated with a model, each output's loss is calculated and returned @@ -171,412 +174,6 @@ def _model_loss(model, return outs, total_loss, loss_metrics, aggregated_loss_metrics, masks -def _maybe_build_graph_functions(model): - """Constructs polymorphic functions to use for fit, evaluate and predict.""" - # We lock this function to ensure thread-safety in case users are - # hypothetically trying to call '.predict' on a model in multiple threads - # at once when the graph functions were never previously built. - with _graph_function_building_lock: - if not model._built_graph_functions: - model._eager_process_single_batch_graph_function = eager_function.defun( - _process_single_batch - ) - model._eager_model_loss_graph_function = eager_function.defun(_model_loss) - model._eager_call_graph_function = eager_function.defun(model.call) - model._built_graph_functions = True - - -def _maybe_graph_function_model_loss(model, - inputs, - targets, - output_loss_metrics=None, - sample_weights=None, - training=False): - """Compute model loss, using defun if the model supports it.""" - if model._can_use_graph_functions: - _maybe_build_graph_functions(model) - return model._eager_model_loss_graph_function( - model, - inputs, - targets, - output_loss_metrics=output_loss_metrics, - sample_weights=sample_weights, - training=training) - else: - return _model_loss( - model, - inputs, - targets, - output_loss_metrics=output_loss_metrics, - sample_weights=sample_weights, - training=training) - - -def _maybe_graph_function_model_call(model, *args, **kwargs): - """Compute model loss, using defun if the model supports it.""" - if model._can_use_graph_functions: - _maybe_build_graph_functions(model) - return model._eager_call_graph_function(*args, **kwargs) - else: - return model.call(*args, **kwargs) - - -def iterator_fit_loop(model, - inputs, - class_weight, - steps_per_epoch, - epoch_logs, - val_inputs=None, - val_targets=None, - val_sample_weights=None, - epochs=1, - verbose=1, - callbacks=None, - validation_steps=None, - do_validation=False, - batch_size=None, - output_loss_metrics=None): - """Fit function for eager execution when input is given as dataset iterator. - - Updates the given epoch logs. - - Arguments: - model: Instance of the `Model`. - inputs: Input dataset iterator. - class_weight: Optional class-weight array to weight the importance of - samples in `inputs` based on the class they belong to, as conveyed by - the targets from the `inputs` iterator. - steps_per_epoch: Total number of steps (batches of samples) - before declaring one epoch finished and starting the - next epoch. - epoch_logs: Dictionary of logs from every epoch. - val_inputs: Input data for validation. - val_targets: Target data for validation. - val_sample_weights: Sample weight data for validation. - epochs: Number of times to iterate over the data - verbose: Verbosity mode, 0, 1 or 2 - callbacks: CallbackList instance. Controls callbacks during training. - validation_steps: Number of steps to run validation for (only if doing - validation from data tensors). Ignored with default value of `None`. - do_validation: Boolean value indicating whether we should do validation. - batch_size: int, val_inputs and val_targets will be evaled batch by - batch with size batch_size if they are array. - output_loss_metrics: List of metrics that are used to aggregated output - loss values. - - Raises: - ValueError: In case of mismatch between given number of inputs and - expectations of the model. - """ - assert isinstance(inputs, iterator_ops.EagerIterator) - - # make sure either x,y or x,y,sample_weights is provided - if (not isinstance(inputs.output_shapes, (list, tuple)) or - len(inputs.output_shapes) not in (2, 3)): - raise ValueError('Please provide either inputs and targets ' - 'or inputs, targets, and sample_weights') - - for step_index in range(steps_per_epoch): - batch_logs = {'batch': step_index, 'size': 1} - callbacks.on_batch_begin(step_index, batch_logs) - - # Get data from the iterator. - try: - next_element = inputs.get_next() - except errors.OutOfRangeError: - logging.warning( - 'Your dataset iterator ran out of data; interrupting training. Make ' - 'sure that your dataset can generate at least ' - '`steps_per_epoch * epochs` batches (in this case, %d batches). You ' - 'may need to use the repeat() function when building your ' - 'dataset.' % steps_per_epoch * epochs) - break - - if len(inputs.output_shapes) == 2: - x, y = next_element - sample_weights = None - else: - x, y, sample_weights = next_element - - # Validate and standardize data. - x, y, sample_weights = model._standardize_user_data( - x, y, sample_weight=sample_weights, class_weight=class_weight) - x = training_utils.cast_if_floating_dtype(x) - y = training_utils.cast_if_floating_dtype(y) - if sample_weights: - sample_weights = [ - training_utils.cast_if_floating_dtype( - ops.convert_to_tensor(val, dtype=backend.floatx())) - if val is not None else None for val in sample_weights - ] - - # Set stateful_metrics in callbacks. We do not do this before the - # `steps_per_epoch` loop because model will be compiled only in the first - # iteration of this loop in the deferred build scenario. - if step_index == 0: - for cbk in callbacks: - if (isinstance(cbk, cbks.BaseLogger) or - isinstance(cbk, cbks.ProgbarLogger)): - cbk.stateful_metrics = model.metrics_names[1:] # Exclude `loss` - - if step_index == 0 and not callbacks.params['metrics']: - callback_metrics = copy.copy(model.metrics_names) - if do_validation: - callback_metrics += ['val_' + n for n in model.metrics_names] - callbacks.set_params({ - 'batch_size': batch_size, - 'epochs': epochs, - 'steps': steps_per_epoch, - 'verbose': verbose, - 'do_validation': do_validation, - 'metrics': callback_metrics or [], - 'validation_steps': validation_steps - }) - - # Train model. - outs, loss, _, aggregated_loss_metrics, masks = \ - _maybe_graph_function_process_single_batch( - model, - x, - y, - output_loss_metrics=output_loss_metrics, - sample_weights=sample_weights, - training=True) - outs = generic_utils.to_list(outs) - - # Calculate metrics. - for l, o in zip(model.metrics_names, outs): - batch_logs[l] = o - metrics_results = _eager_metrics_fn( - model, outs, y, sample_weights=sample_weights, masks=masks) - batch_logs['loss'] = tensor_util.constant_value(backend.mean(loss)) - - for k, v in zip( - model.metrics_names, - [backend.mean(loss)] + aggregated_loss_metrics + metrics_results): - batch_logs[k] = tensor_util.constant_value(v) - callbacks.on_batch_end(step_index, batch_logs) - if callbacks.model.stop_training: - break - - if step_index == steps_per_epoch - 1: - if do_validation: - val_outs = test_loop( - model, - val_inputs, - val_targets, - sample_weights=val_sample_weights, - steps=validation_steps, - verbose=0, - batch_size=batch_size) - if not isinstance(val_outs, list): - val_outs = [val_outs] - # Same labels assumed. - for l, o in zip(model.metrics_names, val_outs): - epoch_logs['val_' + l] = o - - -def iterator_test_loop(model, inputs, steps, verbose=0): - """Test function for eager execution when input is given as dataset iterator. - - Arguments: - model: Model instance that is being evaluated in Eager mode. - inputs: Input dataset iterator. - steps: Total number of steps (batches of samples) before declaring - predictions finished. - verbose: Verbosity mode. - - Returns: - Scalar loss (if the model has a single output and no metrics) - or list of scalars (if the model has multiple outputs - and/or metrics). The attribute `model.metrics_names` will give you - the display labels for the scalar outputs. - - Raises: - ValueError: In case of mismatch between given number of inputs and - expectations of the model. - """ - assert isinstance(inputs, iterator_ops.EagerIterator) - # make sure either x,y or x,y,sample_weights is provided - if (not isinstance(inputs.output_shapes, (list, tuple)) or - len(inputs.output_shapes) < 2 or len(inputs.output_shapes) > 3): - raise ValueError('Please provide either inputs and targets' - 'or inputs, targets, and sample_weights') - outs = [] - - # Create metric wrapper for the losses. - output_loss_metrics = [] - for i in range(len(model.outputs)): - loss_fn = model.loss_functions[i] - mean_wrapped_loss = metrics_module.MeanMetricWrapper( - loss_fn, name=loss_fn.__name__) - output_loss_metrics.append(mean_wrapped_loss) - - num_samples = 0 - if verbose == 1: - progbar = generic_utils.Progbar(target=steps) - for step_index in range(steps): - # Get data from the iterator. - try: - next_element = inputs.get_next() - except errors.OutOfRangeError: - logging.warning( - 'Your dataset iterator ran out of data interrupting testing. ' - 'Make sure that your dataset can generate at least `steps` batches ' - '(in this case, %d batches). You may need to use the repeat() ' - 'function when building your dataset.', steps) - break - - if len(inputs.output_shapes) == 2: - x, y = next_element - sample_weights = None - else: - x, y, sample_weights = next_element - - # Validate and standardize data. - x, y, sample_weights = model._standardize_user_data( - x, y, sample_weight=sample_weights) - x = training_utils.cast_if_floating_dtype(x) - y = training_utils.cast_if_floating_dtype(y) - if sample_weights: - sample_weights = [ - training_utils.cast_if_floating_dtype( - ops.convert_to_tensor(val, dtype=backend.floatx())) - if val is not None else None for val in sample_weights - ] - - if step_index == 0: - # Get stateful metrics indices. We do not do this before the `steps` loop - # because model will be compiled only in the first iteration of this loop - # in the deferred build scenario. - if hasattr(model, 'metrics'): - for m in model.stateful_metric_functions: - m.reset_states() - for m in output_loss_metrics: - m.reset_states() - - # Calculate model output, loss values. - loss_outs, loss, _, aggregated_loss_metrics, masks = \ - _maybe_graph_function_model_loss( - model, - x, - y, - output_loss_metrics=output_loss_metrics, - sample_weights=sample_weights, - training=False) - metrics_results = _eager_metrics_fn( - model, loss_outs, y, sample_weights=sample_weights, masks=masks) - batch_outs = [] - for _, v in zip( - model.metrics_names, - [backend.mean(loss)] + aggregated_loss_metrics + metrics_results): - batch_outs.append(tensor_util.constant_value(v)) - - # Get current step size. - if isinstance(x, list): - step_size = x[0].get_shape().as_list()[0] - elif isinstance(x, dict): - step_size = list(x.values())[0].get_shape().as_list()[0] - else: - step_size = x.get_shape().as_list()[0] - - # Accumulate results in output array. - if not isinstance(batch_outs, list): - batch_outs = [batch_outs] - if step_index == 0: - for _ in enumerate(batch_outs): - outs.append(0.) - outs[0] += batch_outs[0] * step_size # index 0 = 'loss' - outs[1:] = batch_outs[1:] - - # Calculate sample size. - num_samples += step_size - if verbose == 1: - progbar.update(step_index + 1) - - outs[0] /= num_samples # index 0 = 'loss' - if len(outs) == 1: - return outs[0] - return outs - - -def iterator_predict_loop(model, inputs, steps, verbose=0): - """Predict function for eager execution when input is dataset iterator. - - Arguments: - model: Instance of `Model`. - inputs: Input dataset iterator. - steps: Total number of steps (batches of samples) before declaring - `_predict_loop` finished. - verbose: Verbosity mode. - - Returns: - Array of predictions (if the model has a single output) - or list of arrays of predictions (if the model has multiple outputs). - - Raises: - ValueError: In case of mismatch between given number of inputs and - expectations of the model. - """ - assert isinstance(inputs, iterator_ops.EagerIterator) - if not isinstance(inputs.output_shapes, - (list, tuple)) or len(inputs.output_shapes) > 3: - raise ValueError( - 'Please provide data as a list or tuple of 1, 2, or 3 elements ' - ' - `(input)`, or `(input, target)`, or `(input, target,' - 'sample_weights)`. Received %s. We do not use the `target` or' - '`sample_weights` value here.' % inputs.output_shapes) - outs = [] - if verbose == 1: - progbar = generic_utils.Progbar(target=steps) - - for step_index in range(steps): - # Get data from the iterator. - try: - next_element = inputs.get_next() - except errors.OutOfRangeError: - logging.warning( - 'Your dataset iterator ran out of data; interrupting prediction. ' - 'Make sure that your dataset can generate at least `steps` batches ' - '(in this case, %d batches). You may need to use the repeat() ' - 'function when building your dataset.', steps) - break - - # expects a tuple, where first element of tuple represents inputs - x = next_element[0] - - # Validate and standardize data. - x, _, _ = model._standardize_user_data(x) - x = training_utils.cast_if_floating_dtype(x) - - if isinstance(x, list) and len(x) == 1: - x = x[0] - - if model._expects_training_arg: - batch_outs = _maybe_graph_function_model_call(model, x, training=False) - else: - batch_outs = _maybe_graph_function_model_call(model, x) - if not isinstance(batch_outs, list): - batch_outs = [batch_outs] - - # We collect the results from every step and then concatenate them once - # in the end. This is an expensive process. We are doing this because we - # do not know the number of samples beforehand. - if step_index == 0: - for _ in batch_outs: - outs.append([]) - for i, batch_out in enumerate(batch_outs): - outs[i].append(backend.get_value(batch_out)) - - if verbose == 1: - progbar.update(step_index + 1) - for i, out in enumerate(outs): - outs[i] = np.concatenate(tuple(out), axis=0) - if len(outs) == 1: - return outs[0] - return outs - - def _process_single_batch(model, inputs, targets, @@ -630,32 +227,6 @@ def _process_single_batch(model, return outs, loss, loss_metrics, aggregated_loss_metrics, masks -def _maybe_graph_function_process_single_batch(model, - inputs, - targets, - output_loss_metrics=None, - sample_weights=None, - training=False): - """Process a single batch, using defun if the model supports it.""" - if model._can_use_graph_functions: - _maybe_build_graph_functions(model) - return model._eager_process_single_batch_graph_function( - model, - inputs, - targets, - output_loss_metrics=output_loss_metrics, - sample_weights=sample_weights, - training=training) - else: - return _process_single_batch( - model, - inputs, - targets, - output_loss_metrics=output_loss_metrics, - sample_weights=sample_weights, - training=training) - - def train_on_batch(model, inputs, targets, sample_weights=None): """Calculates the loss and gradient updates for one input batch. @@ -668,25 +239,25 @@ def train_on_batch(model, inputs, targets, sample_weights=None): Returns: total loss and the loss associated with each output. """ - if len(inputs) and tensor_util.is_tensor(inputs[0]): - inputs = training_utils.cast_if_floating_dtype(inputs) - targets = training_utils.cast_if_floating_dtype(targets) - else: - inputs = [ - ops.convert_to_tensor(val, dtype=backend.floatx()) for val in inputs - ] - targets = [ - ops.convert_to_tensor(val, dtype=backend.floatx()) for val in targets - ] + if isinstance(inputs, collections.Sequence): + if len(inputs) and tensor_util.is_tensor(inputs[0]): + inputs = training_utils.cast_if_floating_dtype(inputs) + targets = training_utils.cast_if_floating_dtype(targets) + else: + inputs = [ + ops.convert_to_tensor(val, dtype=backend.floatx()) for val in inputs + ] + targets = [ + ops.convert_to_tensor(val, dtype=backend.floatx()) for val in targets + ] if sample_weights: sample_weights = [ ops.convert_to_tensor(val, dtype=backend.floatx()) if val is not None else None for val in sample_weights ] - outs, loss, loss_metrics, _, masks = \ - _maybe_graph_function_process_single_batch( - model, inputs, targets, sample_weights=sample_weights, training=True) + outs, loss, loss_metrics, _, masks = _process_single_batch( + model, inputs, targets, sample_weights=sample_weights, training=True) if not isinstance(outs, list): outs = [outs] metrics_results = _eager_metrics_fn( @@ -695,7 +266,7 @@ def train_on_batch(model, inputs, targets, sample_weights=None): targets, sample_weights=sample_weights, masks=masks, - return_stateful_result=False) + return_stateful_result=True) loss = generic_utils.to_list(loss) return [ @@ -716,22 +287,23 @@ def test_on_batch(model, inputs, targets, sample_weights=None): Returns: total loss, loss and metrics associated with each output. """ - if len(inputs) and tensor_util.is_tensor(inputs[0]): - inputs = training_utils.cast_if_floating_dtype(inputs) - targets = training_utils.cast_if_floating_dtype(targets) - else: - inputs = [ - ops.convert_to_tensor(val, dtype=backend.floatx()) for val in inputs - ] - targets = [ - ops.convert_to_tensor(val, dtype=backend.floatx()) for val in targets - ] + if isinstance(inputs, collections.Sequence): + if len(inputs) and tensor_util.is_tensor(inputs[0]): + inputs = training_utils.cast_if_floating_dtype(inputs) + targets = training_utils.cast_if_floating_dtype(targets) + else: + inputs = [ + ops.convert_to_tensor(val, dtype=backend.floatx()) for val in inputs + ] + targets = [ + ops.convert_to_tensor(val, dtype=backend.floatx()) for val in targets + ] if sample_weights: sample_weights = [ ops.convert_to_tensor(val, dtype=backend.floatx()) if val is not None else None for val in sample_weights ] - outs, loss, loss_metrics, _, masks = _maybe_graph_function_model_loss( + outs, loss, loss_metrics, _, masks = _model_loss( model, inputs, targets, sample_weights=sample_weights, training=False) if not isinstance(outs, list): outs = [outs] @@ -741,184 +313,10 @@ def test_on_batch(model, inputs, targets, sample_weights=None): targets, sample_weights=sample_weights, masks=masks, - return_stateful_result=False) + return_stateful_result=True) loss = generic_utils.to_list(loss) return [ tensor_util.constant_value(v) for v in loss + loss_metrics + metrics_results ] - - -def fit_loop(model, - inputs, - targets, - sample_weights=None, - class_weight=None, - val_inputs=None, - val_targets=None, - val_sample_weights=None, - batch_size=None, - epochs=1, - verbose=1, - callbacks=None, - shuffle=True, - initial_epoch=0, - steps_per_epoch=None, - validation_steps=None): - """Fit function for eager execution. - - Arguments: - model: Instance of the model that is being executed in Eager mode. - inputs: List of input arrays. - targets: List of target arrays. - sample_weights: Optional list of sample weight arrays. - class_weight: Optional class-weight array to weight the importance of - samples in `inputs` based on the class they belong to, as conveyed by - `targets`. - val_inputs: Input data for validation. - val_targets: Target data for validation. - val_sample_weights: Sample weight data for validation. - batch_size: Integer batch size or None if unknown. - epochs: Number of times to iterate over the data - verbose: Verbosity mode, 0, 1 or 2 - callbacks: List of callbacks to be called during training - shuffle: Whether to shuffle the data at the beginning of each epoch - initial_epoch: Epoch at which to start training - (useful for resuming a previous training run) - steps_per_epoch: Total number of steps (batches of samples) - before declaring one epoch finished and starting the - next epoch. Ignored with the default value of `None`. - validation_steps: Number of steps to run validation for (only if doing - validation from data tensors). Ignored with default value of `None`. - - Returns: - `History` object. - - Raises: - ValueError: In case of invalid argument values. - """ - # Convert training inputs to an EagerIterator - inputs, steps_per_epoch = training_utils.convert_to_iterator( - x=inputs, - y=targets, - sample_weights=sample_weights, - batch_size=batch_size, - steps_per_epoch=steps_per_epoch, - epochs=epochs, - shuffle=shuffle) - # Required for eager execution - with backend.learning_phase_scope(1): - do_validation = val_inputs is not None - callbacks = cbks.configure_callbacks( - callbacks, - model, - do_validation=do_validation, - batch_size=batch_size, - epochs=epochs, - steps_per_epoch=steps_per_epoch, - val_inputs=val_inputs, - val_targets=val_targets, - val_sample_weights=val_sample_weights, - validation_steps=validation_steps, - verbose=verbose) - - # Create metric wrapper for the losses. - output_loss_metrics = [] - for i in range(len(model.outputs)): - loss_fn = model.loss_functions[i] - mean_wrapped_loss = metrics_module.MeanMetricWrapper( - loss_fn, name=loss_fn.__name__) - output_loss_metrics.append(mean_wrapped_loss) - - callbacks.on_train_begin() - for epoch in range(initial_epoch, epochs): - if model._is_compiled: # Model may not be compiled the first time. - # Reset stateful metrics - for m in model.stateful_metric_functions: - m.reset_states() - - for m in output_loss_metrics: - m.reset_states() - - callbacks.on_epoch_begin(epoch) - epoch_logs = {} - iterator_fit_loop( - model, - inputs, - class_weight, - steps_per_epoch=steps_per_epoch, - epoch_logs=epoch_logs, - val_inputs=val_inputs, - val_targets=val_targets, - val_sample_weights=val_sample_weights, - epochs=epochs, - verbose=verbose, - callbacks=callbacks, - validation_steps=validation_steps, - do_validation=do_validation, - batch_size=batch_size, - output_loss_metrics=output_loss_metrics) - callbacks.on_epoch_end(epoch, epoch_logs) - if callbacks.model.stop_training: - break - callbacks.on_train_end() - return model.history - - -def test_loop(model, inputs, targets, - sample_weights=None, - batch_size=None, - verbose=0, - steps=None): - """Test function for eager execution. - - Arguments: - model: Model instance that is being evaluated in Eager mode. - inputs: List of input arrays. - targets: List of target arrays. - sample_weights: Optional list of sample weight arrays. - batch_size: integer batch size or `None`. - verbose: verbosity mode. - steps: Total number of steps (batches of samples) - before declaring predictions finished. - Ignored with the default value of `None`. - - Returns: - Scalar loss (if the model has a single output and no metrics) - or list of scalars (if the model has multiple outputs - and/or metrics). The attribute `model.metrics_names` will give you - the display labels for the scalar outputs. - """ - inputs, steps = training_utils.convert_to_iterator( - x=inputs, - y=targets, - sample_weights=sample_weights, - batch_size=batch_size, - steps_per_epoch=steps, - is_validation=True) - with backend.learning_phase_scope(0): - return iterator_test_loop(model, inputs, steps, verbose=verbose) - - -def predict_loop(model, inputs, batch_size=32, verbose=0, steps=None): - """Predict function for eager execution. - - Arguments: - model: Instance of `Model`. - inputs: List of input arrays. - batch_size: integer batch size. - verbose: verbosity mode. - steps: Total number of steps (batches of samples) - before declaring `_predict_loop` finished. - Ignored with the default value of `None`. - - Returns: - Array of predictions (if the model has a single output) - or list of arrays of predictions - (if the model has multiple outputs). - """ - with backend.learning_phase_scope(0): - inputs, steps = training_utils.convert_to_iterator( - x=inputs, batch_size=batch_size, steps_per_epoch=steps) - return iterator_predict_loop(model, inputs, steps, verbose=verbose) diff --git a/tensorflow/python/keras/engine/training_eager_test.py b/tensorflow/python/keras/engine/training_eager_test.py index 76aaf1643b..3fabbb17ed 100644 --- a/tensorflow/python/keras/engine/training_eager_test.py +++ b/tensorflow/python/keras/engine/training_eager_test.py @@ -20,10 +20,10 @@ from __future__ import print_function import numpy as np -from tensorflow.python.data.ops import dataset_ops from tensorflow.python import keras +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.eager import context from tensorflow.python.framework import ops -from tensorflow.python.framework import test_util as tf_test_util from tensorflow.python.keras import metrics as metrics_module from tensorflow.python.platform import test from tensorflow.python.training.rmsprop import RMSPropOptimizer @@ -51,6 +51,7 @@ class TrainingTest(test.TestCase): loss, metrics=metrics, loss_weights=loss_weights, + run_eagerly=True, sample_weight_mode=None) input_a = keras.backend.zeros(shape=(10, 3)) @@ -111,7 +112,7 @@ class TrainingTest(test.TestCase): optimizer = RMSPropOptimizer(learning_rate=0.001) loss = 'mse' metrics = ['mae', metrics_module.CategoricalAccuracy()] - model.compile(optimizer, loss, metrics=metrics) + model.compile(optimizer, loss, metrics=metrics, run_eagerly=True) inputs = keras.backend.zeros(shape=(10, 3)) targets = keras.backend.zeros(shape=(10, 4)) @@ -129,29 +130,34 @@ class TrainingTest(test.TestCase): x = keras.layers.Input(shape=(3,), name='input') y = keras.layers.Dense(4, name='dense')(x) model = keras.Model(x, y) - model.compile(optimizer=RMSPropOptimizer(learning_rate=0.001), loss='mse') + model.compile(optimizer=RMSPropOptimizer(learning_rate=0.001), + loss='mse', + run_eagerly=True) x = keras.backend.zeros(shape=(10, 3)) y = keras.backend.zeros(shape=(10, 4)) dataset = dataset_ops.Dataset.from_tensor_slices((x, y)).repeat(10).batch(5) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) validation_dataset = dataset_ops.Dataset.from_tensor_slices( (x, y)).repeat(10).batch(5) - validation_iterator = validation_dataset.make_one_shot_iterator() + validation_iterator = dataset_ops.make_one_shot_iterator(validation_dataset) with self.assertRaisesRegexp( ValueError, r'specify .* `steps_per_epoch`'): model.fit(iterator, epochs=1, verbose=0) - with self.assertRaisesRegexp( - ValueError, r'provide either `batch_size` or `validation_steps`'): - model.fit(iterator, steps_per_epoch=2, epochs=1, verbose=0, - validation_data=(x, y)) - with self.assertRaisesRegexp( - ValueError, r'provide either `batch_size` or `validation_steps`'): + if not context.executing_eagerly(): + # In eager execution, `keras.backend.zeros` returns value tensors + # which can be used for validation without a `validation_steps` argument. + with self.assertRaisesRegexp( + ValueError, r'provide either `batch_size` or `validation_steps`'): + model.fit(iterator, steps_per_epoch=2, epochs=1, verbose=0, + validation_data=(x, y)) + with self.assertRaisesRegexp(ValueError, + 'specify the `validation_steps` argument.'): model.fit(iterator, steps_per_epoch=2, epochs=1, verbose=0, validation_data=validation_dataset) - with self.assertRaisesRegexp( - ValueError, r'provide either `batch_size` or `validation_steps`'): + with self.assertRaisesRegexp(ValueError, + 'specify the `validation_steps` argument.'): model.fit(iterator, steps_per_epoch=2, epochs=1, verbose=0, validation_data=validation_iterator) @@ -160,25 +166,31 @@ class TrainingTest(test.TestCase): model.add(keras.layers.Dense(4, input_shape=(3,))) optimizer = RMSPropOptimizer(learning_rate=0.001) model.compile( - optimizer, 'mse', metrics=['mae', - metrics_module.CategoricalAccuracy()]) + optimizer, + loss='mse', + metrics=['mae', metrics_module.CategoricalAccuracy()], + run_eagerly=True) x = np.random.random((10, 3)) y = np.random.random((10, 4)) - def iterator(): + def numpy_iterator(): while True: yield x, y - model.fit_generator(iterator(), steps_per_epoch=3, epochs=1) - model.evaluate_generator(iterator(), steps=3) - out = model.predict_generator(iterator(), steps=3) + model.fit_generator(numpy_iterator(), steps_per_epoch=3, epochs=1) + model.evaluate_generator(numpy_iterator(), steps=3) + + def inference_numpy_iterator(): + while True: + yield x + + out = model.predict_generator(inference_numpy_iterator(), steps=3) self.assertEqual(out.shape, (30, 4)) class CorrectnessTest(test.TestCase): - @tf_test_util.run_in_graph_and_eager_modes def test_loss_correctness(self): # Test that training loss is the same in eager and graph # (by comparing it to a reference value in a deterministic case) @@ -191,14 +203,14 @@ class CorrectnessTest(test.TestCase): activation='softmax', kernel_initializer='ones')) model.compile(loss='sparse_categorical_crossentropy', - optimizer=RMSPropOptimizer(learning_rate=0.001)) + optimizer=RMSPropOptimizer(learning_rate=0.001), + run_eagerly=False) x = np.ones((100, 4)) np.random.seed(123) y = np.random.randint(0, 1, size=(100, 1)) history = model.fit(x, y, epochs=1, batch_size=10) self.assertAlmostEqual(history.history['loss'][-1], 0.6173, 4) - @tf_test_util.run_in_graph_and_eager_modes def test_loss_correctness_with_iterator(self): # Test that training loss is the same in eager and graph # (by comparing it to a reference value in a deterministic case) @@ -210,14 +222,15 @@ class CorrectnessTest(test.TestCase): keras.layers.Dense(2, activation='softmax', kernel_initializer='ones')) model.compile( loss='sparse_categorical_crossentropy', - optimizer=RMSPropOptimizer(learning_rate=0.001)) + optimizer=RMSPropOptimizer(learning_rate=0.001), + run_eagerly=True) x = np.ones((100, 4), dtype=np.float32) np.random.seed(123) y = np.random.randint(0, 1, size=(100, 1)) dataset = dataset_ops.Dataset.from_tensor_slices((x, y)) dataset = dataset.repeat(100) dataset = dataset.batch(10) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) history = model.fit(iterator, epochs=1, steps_per_epoch=10) self.assertAlmostEqual(history.history['loss'][-1], 0.6173, 4) diff --git a/tensorflow/python/keras/engine/training_generator.py b/tensorflow/python/keras/engine/training_generator.py index b5e3a03976..0abf0b8270 100644 --- a/tensorflow/python/keras/engine/training_generator.py +++ b/tensorflow/python/keras/engine/training_generator.py @@ -19,412 +19,433 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import functools +import math + import numpy as np +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.ops import iterator_ops from tensorflow.python.eager import context +from tensorflow.python.framework import errors +from tensorflow.python.keras import backend from tensorflow.python.keras import callbacks as cbks -from tensorflow.python.keras.utils.data_utils import GeneratorEnqueuer -from tensorflow.python.keras.utils.data_utils import iter_sequence_infinite -from tensorflow.python.keras.utils.data_utils import OrderedEnqueuer -from tensorflow.python.keras.utils.data_utils import Sequence -from tensorflow.python.keras.utils.generic_utils import Progbar +from tensorflow.python.keras.engine import training_utils +from tensorflow.python.keras.utils import data_utils +from tensorflow.python.keras.utils import generic_utils from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.util import nest + + +def model_iteration(model, + data, + steps_per_epoch=None, + epochs=1, + verbose=1, + callbacks=None, + validation_data=None, + validation_steps=None, + class_weight=None, + max_queue_size=10, + workers=1, + use_multiprocessing=False, + shuffle=True, + initial_epoch=0, + mode='train', + batch_size=None, + **kwargs): + """Loop function for arrays of data with modes 'train'/'test'/'predict'. + + Arguments: + model: Keras Model instance. + data: Either a tuple of NumPy/Tensor inputs (i.e. `(x,)` or `(x, y)` or + `(x, y, sample_weights)`) or a generator or + `keras.utils.data_utils.Sequence` object or Eager Iterator or Dataset. + steps_per_epoch: Total number of steps (batches of samples) before + declaring one epoch finished and starting the next epoch. Ignored with + the default value of `None`. + epochs: Number of times to iterate over the data. + verbose: Verbosity mode, 0, 1 or 2. + callbacks: List of callbacks to be called during training. + validation_data: Either a tuple of NumPy/Tensor inputs (i.e. `(x,)` or + `(x, y)` or `(x, y, sample_weights)`) or a generator or + `keras.utils.data_utils.Sequence` object or Eager Iterator or Dataset. + validation_steps: Total number of steps (batches of samples) before + declaring validation finished. + class_weight: Dictionary mapping class indices to a weight for the class. + max_queue_size: Integer. Maximum size for the generator queue. If + unspecified, `max_queue_size` will default to 10. + workers: Integer. Maximum number of processes to spin up when using + process-based threading. If unspecified, `workers` will default to 1. If + 0, will execute the generator on the main thread. + use_multiprocessing: Boolean. If `True`, use process-based threading. If + unspecified, `use_multiprocessing` will default to `False`. Note that + because this implementation relies on multiprocessing, you should not + pass non-picklable arguments to the generator as they can't be passed + easily to children processes. + shuffle: Boolean. Whether to shuffle the order of the batches at the + beginning of each epoch. Only used with instances of `Sequence` + (`keras.utils.Sequence`). Has no effect when `steps_per_epoch` is not + `None`. + initial_epoch: Epoch at which to start training (useful for resuming a + previous training run). + mode: One of 'train'/'test'/'predict'. + batch_size: Integer batch size or None if unknown. Will only be used if + `data` is in NumPy/Tensor format. + **kwargs: Additional arguments for backwards compatibility. `steps` is + accepted as an alias for `steps_per_epoch`. + + Returns: + - In 'train' mode: `History` object. + - In 'test' mode: Evaluation metrics. + - In 'predict' mode: Outputs of the Model called on inputs. + + Raises: + ValueError: in case of invalid arguments. + """ + if 'steps' in kwargs: + steps_per_epoch = kwargs['steps'] + + # Convert to a format that supports `next(generator)`. + generator, steps_per_epoch = convert_to_generator_like( + data, + steps_per_epoch=steps_per_epoch, + batch_size=batch_size, + epochs=epochs - initial_epoch, + shuffle=shuffle) + + do_validation = validation_data is not None + should_set_learning_phase = context.executing_eagerly() and model.run_eagerly + is_sequence = isinstance(generator, data_utils.Sequence) + _validate_arguments(is_sequence, use_multiprocessing, workers, + steps_per_epoch, validation_data, validation_steps, mode, + kwargs) + + batch_function = _make_execution_function( + model, mode, class_weight=class_weight) + + # Create the queue for the generator. + output_generator, enqueuer = _make_enqueued_generator( + generator, + workers=workers, + use_multiprocessing=use_multiprocessing, + max_queue_size=max_queue_size, + shuffle=shuffle) + + num_samples_or_steps, use_steps = _get_num_samples_or_steps( + data, steps_per_epoch) + + count_mode = 'steps' if use_steps else 'samples' + callbacks = cbks.configure_callbacks( + callbacks, + model, + do_validation=do_validation, + epochs=epochs, + steps_per_epoch=steps_per_epoch, + batch_size=batch_size, + samples=num_samples_or_steps, + verbose=0, # Handle ProgBar as part of Callbacks once hooks are ready. + mode=mode) + # TODO(omalleyt): Handle ProgBar as part of Callbacks once hooks are ready. + progbar = training_utils.get_progbar(model, count_mode) + progbar.params = callbacks.params + progbar.params['verbose'] = verbose + + if mode == 'predict': + aggregator = training_utils.OutputsAggregator(True, steps_per_epoch) + else: + aggregator = training_utils.MetricsAggregator(True, steps_per_epoch) + if should_set_learning_phase: + old_learning_phase = backend.learning_phase() + backend.set_learning_phase(1 if mode == 'train' else 0) -def fit_generator(model, - generator, - steps_per_epoch=None, - epochs=1, - verbose=1, - callbacks=None, - validation_data=None, - validation_steps=None, - class_weight=None, - max_queue_size=10, - workers=1, - use_multiprocessing=False, - shuffle=True, - initial_epoch=0): - """See docstring for `Model.fit_generator`.""" - epoch = initial_epoch - - do_validation = bool(validation_data) - if not context.executing_eagerly(): - model._make_train_function() - if do_validation: - model._make_test_function() - - is_sequence = isinstance(generator, Sequence) - if not is_sequence and use_multiprocessing and workers > 1: - logging.warning( - UserWarning('Using a generator with `use_multiprocessing=True`' - ' and multiple workers may duplicate your data.' - ' Please consider using the`keras.utils.Sequence' - ' class.')) - if steps_per_epoch is None: - if is_sequence: - steps_per_epoch = len(generator) - else: - raise ValueError('`steps_per_epoch=None` is only valid for a' - ' generator based on the `keras.utils.Sequence`' - ' class. Please specify `steps_per_epoch` or use' - ' the `keras.utils.Sequence` class.') + callbacks.model.stop_training = False + callbacks._call_begin_hook(mode) + progbar.on_train_begin() + for epoch in range(initial_epoch, epochs): + if callbacks.model.stop_training: + break - # python 2 has 'next', 3 has '__next__' - # avoid any explicit version checks - val_gen = ( - hasattr(validation_data, 'next') or - hasattr(validation_data, '__next__') or - isinstance(validation_data, Sequence)) - if (val_gen and not isinstance(validation_data, Sequence) and - not validation_steps): - raise ValueError('`validation_steps=None` is only valid for a' - ' generator based on the `keras.utils.Sequence`' - ' class. Please specify `validation_steps` or use' - ' the `keras.utils.Sequence` class.') + # Setup work for each epoch. + model.reset_metrics() + epoch_logs = {} + callbacks.on_epoch_begin(epoch, epoch_logs, mode=mode) + progbar.on_epoch_begin(epoch, epoch_logs) - enqueuer = None - val_enqueuer = None + for step in range(steps_per_epoch): + batch_data = _get_next_batch(output_generator, mode) + if batch_data is None: + callbacks.model.stop_training = True + break - try: - val_x, val_y, val_sample_weights = validation_data, None, None - if do_validation and not val_gen: - # Prepare data for validation - if len(validation_data) == 2: - val_x, val_y = validation_data # pylint: disable=unpacking-non-sequence - val_sample_weights = None - elif len(validation_data) == 3: - val_x, val_y, val_sample_weights = validation_data # pylint: disable=unpacking-non-sequence - else: - raise ValueError( - '`validation_data` should be a tuple ' - '`(val_x, val_y, val_sample_weight)` ' - 'or `(val_x, val_y)`. Found: ' + str(validation_data)) - val_x, val_y, val_sample_weights = model._standardize_user_data( - val_x, val_y, val_sample_weights) - - callbacks = cbks.configure_callbacks( - callbacks, - model, - do_validation=do_validation, - val_inputs=val_x, - val_targets=val_y, - val_sample_weights=val_sample_weights, - epochs=epochs, - validation_steps=validation_steps, - steps_per_epoch=steps_per_epoch, - verbose=verbose) - - if workers > 0: - if is_sequence: - enqueuer = OrderedEnqueuer( - generator, - use_multiprocessing=use_multiprocessing, - shuffle=shuffle) - else: - enqueuer = GeneratorEnqueuer( - generator, - use_multiprocessing=use_multiprocessing) - enqueuer.start(workers=workers, max_queue_size=max_queue_size) - output_generator = enqueuer.get() - else: - if is_sequence: - output_generator = iter_sequence_infinite(generator) - else: - output_generator = generator + # `batch_size` used for validation data if validation + # data is NumPy/EagerTensors. + batch_size = int(nest.flatten(batch_data)[0].shape[0]) + + # Callbacks batch begin. + batch_logs = {'batch': step, 'size': batch_size} + callbacks._call_batch_hook(mode, 'begin', step, batch_logs) + progbar.on_batch_begin(step, batch_logs) + + batch_outs = batch_function(*batch_data) + if not isinstance(batch_outs, list): + batch_outs = [batch_outs] + + # Aggregate results. + if step == 0: + aggregator.create(batch_outs) + aggregator.aggregate(batch_outs) + + # Callbacks batch end. + batch_logs.update(training_utils.make_logs(model, batch_outs, mode)) + callbacks._call_batch_hook(mode, 'end', step, batch_logs) + progbar.on_batch_end(step, batch_logs) - callbacks.on_train_begin() - # Construct epoch logs. - epoch_logs = {} - while epoch < epochs: - for m in model.stateful_metric_functions: - m.reset_states() - callbacks.on_epoch_begin(epoch) - steps_done = 0 - batch_index = 0 - while steps_done < steps_per_epoch: - generator_output = next(output_generator) - - if not hasattr(generator_output, '__len__'): - raise ValueError('Output of generator should be ' - 'a tuple `(x, y, sample_weight)` ' - 'or `(x, y)`. Found: ' + str(generator_output)) - - if len(generator_output) == 2: - x, y = generator_output - sample_weight = None - elif len(generator_output) == 3: - x, y, sample_weight = generator_output - else: - raise ValueError('Output of generator should be ' - 'a tuple `(x, y, sample_weight)` ' - 'or `(x, y)`. Found: ' + str(generator_output)) - # build batch logs - batch_logs = {} - if isinstance(x, list): - batch_size = x[0].shape[0] - elif isinstance(x, dict): - batch_size = list(x.values())[0].shape[0] - else: - batch_size = x.shape[0] - batch_logs['batch'] = batch_index - batch_logs['size'] = batch_size - callbacks.on_batch_begin(batch_index, batch_logs) - - outs = model.train_on_batch( - x, y, sample_weight=sample_weight, class_weight=class_weight) - - if not isinstance(outs, list): - outs = [outs] - for l, o in zip(model.metrics_names, outs): - batch_logs[l] = o - - callbacks.on_batch_end(batch_index, batch_logs) - - batch_index += 1 - steps_done += 1 - - # Epoch finished. - if steps_done >= steps_per_epoch and do_validation: - if val_gen: - val_outs = evaluate_generator( - model, - validation_data, - validation_steps, - workers=workers, - use_multiprocessing=use_multiprocessing, - max_queue_size=max_queue_size) - else: - # No need for try/except because - # data has already been validated. - val_outs = model.evaluate( - val_x, - val_y, - batch_size=batch_size, - sample_weight=val_sample_weights, - verbose=0) - if not isinstance(val_outs, list): - val_outs = [val_outs] - # Same labels assumed. - for l, o in zip(model.metrics_names, val_outs): - epoch_logs['val_' + l] = o - - if callbacks.model.stop_training: - break - - callbacks.on_epoch_end(epoch, epoch_logs) - epoch += 1 if callbacks.model.stop_training: break - finally: - try: - if enqueuer is not None: - enqueuer.stop() - finally: - if val_enqueuer is not None: - val_enqueuer.stop() - - callbacks.on_train_end() - return model.history - - -def evaluate_generator(model, - generator, - steps=None, - max_queue_size=10, - workers=1, - use_multiprocessing=False, - verbose=0): - """See docstring for `Model.evaluate_generator`.""" - if not context.executing_eagerly(): - model._make_test_function() - - if hasattr(model, 'metrics'): - for m in model.stateful_metric_functions: - m.reset_states() - - steps_done = 0 - all_outs = [] - batch_sizes = [] - is_sequence = isinstance(generator, Sequence) - if not is_sequence and use_multiprocessing and workers > 1: - logging.warning( - UserWarning('Using a generator with `use_multiprocessing=True`' - ' and multiple workers may duplicate your data.' - ' Please consider using the`keras.utils.Sequence' - ' class.')) - if steps is None: - if is_sequence: - steps = len(generator) - else: - raise ValueError('`steps=None` is only valid for a generator' - ' based on the `keras.utils.Sequence` class.' - ' Please specify `steps` or use the' - ' `keras.utils.Sequence` class.') - enqueuer = None - + aggregator.finalize() + results = aggregator.results + epoch_logs.update(training_utils.make_logs(model, results, mode)) + if len(results) == 1: + results = results[0] + + # Run the test loop every epoch during training. + if do_validation and not callbacks.model.stop_training: + val_results = model_iteration( + model, + validation_data, + steps_per_epoch=validation_steps, + batch_size=batch_size, + class_weight=class_weight, + workers=workers, + use_multiprocessing=use_multiprocessing, + max_queue_size=max_queue_size, + mode='test') + + if not isinstance(val_results, list): + val_results = [val_results] + epoch_logs.update( + training_utils.make_logs(model, val_results, mode, prefix='val_')) + + callbacks.on_epoch_end(epoch, epoch_logs, mode=mode) + progbar.on_epoch_end(epoch, epoch_logs) + callbacks._call_end_hook(mode) + + if enqueuer is not None: + enqueuer.stop() + + if should_set_learning_phase: + backend.set_learning_phase(old_learning_phase) + + if mode == 'train': + return model.history + return results + + +# Maintain compatibility with the existing names. +fit_generator = functools.partial(model_iteration, mode='train') +evaluate_generator = functools.partial(model_iteration, mode='test') +predict_generator = functools.partial(model_iteration, mode='predict') + + +def _get_next_batch(output_generator, mode): + """Retrieves the next batch of input data.""" try: - if workers > 0: - if is_sequence: - enqueuer = OrderedEnqueuer( - generator, use_multiprocessing=use_multiprocessing) - else: - enqueuer = GeneratorEnqueuer( - generator, - use_multiprocessing=use_multiprocessing) - enqueuer.start(workers=workers, max_queue_size=max_queue_size) - output_generator = enqueuer.get() + generator_output = next(output_generator) + except (errors.OutOfRangeError, StopIteration): + # Returning `None` will trigger looping to stop. + logging.warning('Your dataset iterator ran out of data.') + return None + if not isinstance(generator_output, tuple): + if mode == 'predict': + # Always wrap in a tuple. + return (generator_output,) else: - if is_sequence: - output_generator = iter_sequence_infinite(generator) - else: - output_generator = generator - - if verbose == 1: - progbar = Progbar(target=steps) - - while steps_done < steps: - generator_output = next(output_generator) - if not hasattr(generator_output, '__len__'): - raise ValueError('Output of generator should be a tuple ' - '(x, y, sample_weight) ' - 'or (x, y). Found: ' + str(generator_output)) - if len(generator_output) == 2: - x, y = generator_output - sample_weight = None - elif len(generator_output) == 3: - x, y, sample_weight = generator_output - else: - raise ValueError('Output of generator should be a tuple ' - '(x, y, sample_weight) ' - 'or (x, y). Found: ' + str(generator_output)) - outs = model.test_on_batch(x, y, sample_weight=sample_weight) - - if isinstance(x, list): - batch_size = x[0].shape[0] - elif isinstance(x, dict): - batch_size = list(x.values())[0].shape[0] - else: - batch_size = x.shape[0] - if batch_size == 0: - raise ValueError('Received an empty batch. ' - 'Batches should at least contain one item.') - all_outs.append(outs) - - steps_done += 1 - batch_sizes.append(batch_size) - if verbose == 1: - progbar.update(steps_done) - - finally: - if enqueuer is not None: - enqueuer.stop() - - if not isinstance(outs, list): - return np.average(np.asarray(all_outs), weights=batch_sizes) - else: - averages = [float(all_outs[-1][0])] # index 0 = 'loss' - averages.extend([ - np.average([out[i] - for out in all_outs], weights=batch_sizes) - for i in range(1, len(outs)) - ]) - return averages - - -def predict_generator(model, - generator, - steps=None, - max_queue_size=10, - workers=1, - use_multiprocessing=False, - verbose=0): - """See docstring for `Model.predict_generator`.""" - if not context.executing_eagerly(): - model._make_predict_function() - - steps_done = 0 - all_outs = [] - is_sequence = isinstance(generator, Sequence) + raise ValueError('Output of generator should be ' + 'a tuple `(x, y, sample_weight)` ' + 'or `(x, y)`. Found: ' + str(generator_output)) + + if len(generator_output) < 1 or len(generator_output) > 3: + raise ValueError('Output of generator should be ' + 'a tuple `(x, y, sample_weight)` ' + 'or `(x, y)` or (x,). Found: ' + str(generator_output)) + return generator_output + + +def _validate_arguments(is_sequence, use_multiprocessing, workers, + steps_per_epoch, validation_data, validation_steps, + mode, kwargs): + """Raises errors if arguments are invalid. + + Arguments: + is_sequence: Boolean, whether data is a `keras.utils.data_utils.Sequence` + instance. + use_multiprocessing: Boolean. If `True`, use process-based threading. If + unspecified, `use_multiprocessing` will default to `False`. Note that + because this implementation relies on multiprocessing, you should not pass + non-picklable arguments to the generator as they can't be passed easily to + children processes. + workers: Integer. Maximum number of processes to spin up when using + process-based threading. If unspecified, `workers` will default to 1. If + 0, will execute the generator on the main thread. + steps_per_epoch: Total number of steps (batches of samples) before declaring + one epoch finished and starting the next epoch. Ignored with the default + value of `None`. + validation_data: Either a tuple of NumPy/Tensor inputs (i.e. `(x,)` or `(x, + y)` or `(x, y, sample_weights)`) or a generator or + `keras.utils.data_utils.Sequence` object or Eager Iterator or Dataset. + validation_steps: Total number of steps (batches of samples) before + declaring validation finished. + mode: One of 'train'/'test'/'predict'. + kwargs: Additional arguments for backwards compatibility. + + Raises: + ValueError: If `steps_per_epoch` or `validation_steps` are not passed + for data types that require them, or if unrecognized keyword + arguments are passed. + """ if not is_sequence and use_multiprocessing and workers > 1: logging.warning( UserWarning('Using a generator with `use_multiprocessing=True`' ' and multiple workers may duplicate your data.' - ' Please consider using the`keras.utils.Sequence' + ' Please consider using the `keras.utils.Sequence`' ' class.')) - if steps is None: - if is_sequence: - steps = len(generator) - else: - raise ValueError('`steps=None` is only valid for a generator' - ' based on the `keras.utils.Sequence` class.' - ' Please specify `steps` or use the' - ' `keras.utils.Sequence` class.') - enqueuer = None - try: - if workers > 0: - if is_sequence: - enqueuer = OrderedEnqueuer( - generator, use_multiprocessing=use_multiprocessing) - else: - enqueuer = GeneratorEnqueuer( - generator, - use_multiprocessing=use_multiprocessing) - enqueuer.start(workers=workers, max_queue_size=max_queue_size) - output_generator = enqueuer.get() + if steps_per_epoch is None: + arg_name = 'steps_per_epoch' if mode == 'train' else 'steps' + raise ValueError('Please specify the number of steps via the ' + '`{}` argument.'.format(arg_name)) + + val_gen = ( + data_utils.is_generator_or_sequence(validation_data) or + isinstance(validation_data, iterator_ops.EagerIterator) or + isinstance(validation_data, dataset_ops.DatasetV2)) + if (val_gen and not isinstance(validation_data, data_utils.Sequence) and + not validation_steps): + raise ValueError('Please specify the `validation_steps` argument.') + + if any(k != 'steps' for k in kwargs): + raise ValueError('Invalid arguments passed: {}'.format( + [k for k in kwargs if k != 'steps'])) + + +def convert_to_generator_like(data, + batch_size=None, + steps_per_epoch=None, + epochs=1, + shuffle=False): + """Make a generator out of NumPy or EagerTensor inputs. + + Arguments: + data: Either a generator or `keras.utils.data_utils.Sequence` object or + `Dataset` or `EagerIterator` or a {1,2,3}-tuple of NumPy arrays or + EagerTensors. If a tuple, the elements represent `(x, y, sample_weights)` + and may be `None` or `[None]`. + batch_size: Used when creating a generator out of tuples of NumPy arrays or + EagerTensors. + steps_per_epoch: Steps of the generator to run each epoch. + epochs: Total number of epochs to run. + shuffle: Whether the data should be shuffled. + + Returns: + - Generator or `keras.utils.data_utils.Sequence` or EagerIterator. + + Raises: + - ValueError: If `batch_size` is not provided for NumPy or EagerTensor + inputs. + """ + if isinstance(data, tuple): + # Scrub `Nones` that might have been passed for `targets`, `sample_weights`. + data = tuple( + ele for ele in data if not all(e is None for e in nest.flatten(ele))) + if len(data) == 1: + data = data[0] + + if data_utils.is_generator_or_sequence(data) or isinstance( + data, iterator_ops.EagerIterator): + if isinstance(data, data_utils.Sequence): + steps_per_epoch = len(data) + return data, steps_per_epoch + if isinstance(data, dataset_ops.DatasetV2): + return dataset_ops.make_one_shot_iterator(data), steps_per_epoch + + # Create generator from NumPy or EagerTensor Input. + num_samples = int(nest.flatten(data)[0].shape[0]) + if batch_size is None: + raise ValueError('You must specify `batch_size`') + steps_per_epoch = int(math.ceil(num_samples / batch_size)) + + def _gen(data): + """Makes a generator out of a structure of NumPy/EagerTensors.""" + index_array = np.arange(num_samples) + for _ in range(epochs): + if shuffle: + np.random.shuffle(index_array) + batches = generic_utils.make_batches(num_samples, batch_size) + for (batch_start, batch_end) in batches: + batch_ids = index_array[batch_start:batch_end] + flat_batch_data = training_utils.slice_arrays( + nest.flatten(data), batch_ids, contiguous=(not shuffle)) + yield nest.pack_sequence_as(data, flat_batch_data) + + return _gen(data), steps_per_epoch + + +def _make_enqueued_generator(generator, + workers=1, + use_multiprocessing=False, + max_queue_size=10, + shuffle=False): + """Create a buffered queue of next elements of the generator.""" + is_sequence = isinstance(generator, data_utils.Sequence) + enqueuer = None + if workers > 0: + if is_sequence: + enqueuer = data_utils.OrderedEnqueuer( + generator, use_multiprocessing=use_multiprocessing, shuffle=shuffle) else: - if is_sequence: - output_generator = iter_sequence_infinite(generator) - else: - output_generator = generator - - if verbose == 1: - progbar = Progbar(target=steps) - - while steps_done < steps: - generator_output = next(output_generator) - if isinstance(generator_output, tuple): - # Compatibility with the generators - # used for training. - if len(generator_output) == 2: - x, _ = generator_output - elif len(generator_output) == 3: - x, _, _ = generator_output - else: - raise ValueError('Output of generator should be ' - 'a tuple `(x, y, sample_weight)` ' - 'or `(x, y)`. Found: ' + str(generator_output)) - else: - # Assumes a generator that only - # yields inputs (not targets and sample weights). - x = generator_output - - outs = model.predict_on_batch(x) - if not isinstance(outs, list): - outs = [outs] - - if not all_outs: - for out in outs: - all_outs.append([]) - - for i, out in enumerate(outs): - all_outs[i].append(out) - steps_done += 1 - if verbose == 1: - progbar.update(steps_done) - - finally: - if enqueuer is not None: - enqueuer.stop() - - if len(all_outs) == 1: - if steps_done == 1: - return all_outs[0][0] + enqueuer = data_utils.GeneratorEnqueuer( + generator, use_multiprocessing=use_multiprocessing) + enqueuer.start(workers=workers, max_queue_size=max_queue_size) + output_generator = enqueuer.get() + else: + if is_sequence: + output_generator = data_utils.iter_sequence_infinite(generator) else: - return np.concatenate(all_outs[0]) - if steps_done == 1: - return [out[0] for out in all_outs] + output_generator = generator + return output_generator, enqueuer + + +def _make_execution_function(model, mode, class_weight=None): + """Makes function to run one step of model execution.""" + if mode == 'train': + if not context.executing_eagerly(): + model._make_fit_function() + f = functools.partial(model.train_on_batch, class_weight=class_weight) + elif mode == 'test': + if not context.executing_eagerly(): + model._make_eval_function() + f = model.test_on_batch else: - return [np.concatenate(out) for out in all_outs] + # Match signature of other modes to allow + # 1, 2, or 3-tuples from generator + def predict_on_batch(x, y=None, sample_weights=None): # pylint: disable=unused-argument + return model.predict_on_batch(x) + + f = predict_on_batch + + # Maintain stateful metrics across batch-level calls. + if mode != 'predict': + f = functools.partial(f, reset_metrics=False) + + return f + + +def _get_num_samples_or_steps(data, steps_per_epoch): + """Returns number of samples or steps, and whether to use steps count mode.""" + flat_inputs = nest.flatten(data) + if hasattr(flat_inputs[0], 'shape'): + return int(flat_inputs[0].shape[0]), False + return steps_per_epoch, True diff --git a/tensorflow/python/keras/engine/training_generator_test.py b/tensorflow/python/keras/engine/training_generator_test.py index 88e8943424..8941428e43 100644 --- a/tensorflow/python/keras/engine/training_generator_test.py +++ b/tensorflow/python/keras/engine/training_generator_test.py @@ -21,220 +21,274 @@ from __future__ import print_function import os import unittest +from absl.testing import parameterized import numpy as np from tensorflow.python import keras +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.ops import iterator_ops +from tensorflow.python.eager import context from tensorflow.python.framework import test_util as tf_test_util from tensorflow.python.keras import metrics as metrics_module +from tensorflow.python.keras import testing_utils +from tensorflow.python.keras.engine import training_generator from tensorflow.python.platform import test from tensorflow.python.training.rmsprop import RMSPropOptimizer +from tensorflow.python.util import nest + + +def custom_generator(mode=2): + batch_size = 10 + num_samples = 50 + arr_data = np.random.random((num_samples, 2)) + arr_labels = np.random.random((num_samples, 4)) + arr_weights = np.random.random((num_samples,)) + i = 0 + while True: + batch_index = i * batch_size % num_samples + i += 1 + start = batch_index + end = start + batch_size + x = arr_data[start: end] + y = arr_labels[start: end] + w = arr_weights[start: end] + if mode == 1: + yield x + elif mode == 2: + yield x, y + else: + yield x, y, w + + +@tf_test_util.run_all_in_graph_and_eager_modes +class TestGeneratorMethods(test.TestCase, parameterized.TestCase): - -class TestGeneratorMethods(test.TestCase): + @unittest.skipIf( + os.name == 'nt', + 'use_multiprocessing=True does not work on windows properly.') + @parameterized.parameters('sequential', 'functional') + def test_fit_generator_method(self, model_type): + if model_type == 'sequential': + model = testing_utils.get_small_sequential_mlp( + num_hidden=3, num_classes=4, input_dim=2) + else: + model = testing_utils.get_small_functional_mlp( + num_hidden=3, num_classes=4, input_dim=2) + model.compile( + loss='mse', + optimizer='sgd', + metrics=['mae', metrics_module.CategoricalAccuracy()]) + + model.fit_generator(custom_generator(), + steps_per_epoch=5, + epochs=1, + verbose=1, + max_queue_size=10, + workers=4, + use_multiprocessing=True) + model.fit_generator(custom_generator(), + steps_per_epoch=5, + epochs=1, + verbose=1, + max_queue_size=10, + use_multiprocessing=False) + model.fit_generator(custom_generator(), + steps_per_epoch=5, + epochs=1, + verbose=1, + max_queue_size=10, + use_multiprocessing=False, + validation_data=custom_generator(), + validation_steps=10) + model.fit_generator(custom_generator(), + steps_per_epoch=5, + validation_data=custom_generator(), + validation_steps=1, + workers=0) @unittest.skipIf( os.name == 'nt', 'use_multiprocessing=True does not work on windows properly.') - def test_generator_methods(self): - arr_data = np.random.random((50, 2)) - arr_labels = np.random.random((50,)) + @parameterized.parameters('sequential', 'functional') + def test_evaluate_generator_method(self, model_type): + if model_type == 'sequential': + model = testing_utils.get_small_sequential_mlp( + num_hidden=3, num_classes=4, input_dim=2) + else: + model = testing_utils.get_small_functional_mlp( + num_hidden=3, num_classes=4, input_dim=2) + model.compile( + loss='mse', + optimizer='sgd', + metrics=['mae', metrics_module.CategoricalAccuracy()]) + model.summary() + + model.evaluate_generator(custom_generator(), + steps=5, + max_queue_size=10, + workers=2, + verbose=1, + use_multiprocessing=True) + model.evaluate_generator(custom_generator(), + steps=5, + max_queue_size=10, + use_multiprocessing=False) + model.evaluate_generator(custom_generator(), + steps=5, + max_queue_size=10, + use_multiprocessing=False, + workers=0) - def custom_generator(): - batch_size = 10 - num_samples = 50 - while True: - batch_index = np.random.randint(0, num_samples - batch_size) - start = batch_index - end = start + batch_size - x = arr_data[start: end] - y = arr_labels[start: end] - yield x, y - - with self.cached_session(): - x = keras.Input((2,)) - y = keras.layers.Dense(1)(x) - fn_model = keras.models.Model(x, y) - fn_model.compile( - loss='mse', - optimizer='sgd', - metrics=['mae', metrics_module.CategoricalAccuracy()]) - - seq_model = keras.models.Sequential() - seq_model.add(keras.layers.Dense(1, input_shape=(2,))) - seq_model.compile(loss='mse', optimizer='sgd') - - for model in [fn_model, seq_model]: - model.fit_generator(custom_generator(), - steps_per_epoch=5, - epochs=1, - verbose=1, + @unittest.skipIf( + os.name == 'nt', + 'use_multiprocessing=True does not work on windows properly.') + @parameterized.parameters('sequential', 'functional') + def test_predict_generator_method(self, model_type): + if model_type == 'sequential': + model = testing_utils.get_small_sequential_mlp( + num_hidden=3, num_classes=4, input_dim=2) + else: + model = testing_utils.get_small_functional_mlp( + num_hidden=3, num_classes=4, input_dim=2) + model.compile( + loss='mse', + optimizer='sgd', + metrics=['mae', metrics_module.CategoricalAccuracy()]) + + model.predict_generator(custom_generator(), + steps=5, + max_queue_size=10, + workers=2, + use_multiprocessing=True) + model.predict_generator(custom_generator(), + steps=5, + max_queue_size=10, + use_multiprocessing=False) + model.predict_generator(custom_generator(), + steps=5, + max_queue_size=10, + workers=0) + # Test generator with just inputs (no targets) + model.predict_generator(custom_generator(mode=1), + steps=5, max_queue_size=10, - workers=4, + workers=2, use_multiprocessing=True) - model.fit_generator(custom_generator(), - steps_per_epoch=5, - epochs=1, - verbose=1, + model.predict_generator(custom_generator(mode=1), + steps=5, max_queue_size=10, use_multiprocessing=False) - model.fit_generator(custom_generator(), - steps_per_epoch=5, - epochs=1, - verbose=1, + model.predict_generator(custom_generator(mode=1), + steps=5, max_queue_size=10, - use_multiprocessing=False, - validation_data=custom_generator(), - validation_steps=10) - model.fit_generator(custom_generator(), - steps_per_epoch=5, - validation_data=custom_generator(), - validation_steps=1, workers=0) - model.predict_generator(custom_generator(), - steps=5, - max_queue_size=10, - workers=2, - use_multiprocessing=True) - model.predict_generator(custom_generator(), - steps=5, - max_queue_size=10, - use_multiprocessing=False) - model.predict_generator(custom_generator(), - steps=5, - max_queue_size=10, - workers=0) - model.evaluate_generator(custom_generator(), - steps=5, - max_queue_size=10, - workers=2, - verbose=1, - use_multiprocessing=True) - model.evaluate_generator(custom_generator(), - steps=5, - max_queue_size=10, - use_multiprocessing=False) - model.evaluate_generator(custom_generator(), - steps=5, - max_queue_size=10, - use_multiprocessing=False, - workers=0) def test_generator_methods_with_sample_weights(self): - arr_data = np.random.random((50, 2)) - arr_labels = np.random.random((50,)) - arr_sample_weights = np.random.random((50,)) + model = keras.models.Sequential() + model.add(keras.layers.Dense(4, input_shape=(2,))) + model.compile( + loss='mse', + optimizer='sgd', + metrics=['mae', metrics_module.CategoricalAccuracy()]) + + model.fit_generator(custom_generator(mode=3), + steps_per_epoch=5, + epochs=1, + verbose=1, + max_queue_size=10, + use_multiprocessing=False) + model.fit_generator(custom_generator(mode=3), + steps_per_epoch=5, + epochs=1, + verbose=1, + max_queue_size=10, + use_multiprocessing=False, + validation_data=custom_generator(mode=3), + validation_steps=10) + model.predict_generator(custom_generator(mode=3), + steps=5, + max_queue_size=10, + use_multiprocessing=False) + model.evaluate_generator(custom_generator(mode=3), + steps=5, + max_queue_size=10, + use_multiprocessing=False) - def custom_generator(): - batch_size = 10 - num_samples = 50 - while True: - batch_index = np.random.randint(0, num_samples - batch_size) - start = batch_index - end = start + batch_size - x = arr_data[start: end] - y = arr_labels[start: end] - w = arr_sample_weights[start: end] - yield x, y, w - - with self.cached_session(): - model = keras.models.Sequential() - model.add(keras.layers.Dense(1, input_shape=(2,))) - model.compile( - loss='mse', - optimizer='sgd', - metrics=['mae', metrics_module.CategoricalAccuracy()]) + def test_generator_methods_invalid_use_case(self): - model.fit_generator(custom_generator(), + def invalid_generator(): + while 1: + yield 0 + + model = keras.models.Sequential() + model.add(keras.layers.Dense(4, input_shape=(2,))) + model.compile(loss='mse', optimizer='sgd') + + with self.assertRaises(ValueError): + model.fit_generator(invalid_generator(), steps_per_epoch=5, epochs=1, verbose=1, max_queue_size=10, use_multiprocessing=False) + with self.assertRaises(ValueError): model.fit_generator(custom_generator(), steps_per_epoch=5, epochs=1, verbose=1, max_queue_size=10, use_multiprocessing=False, - validation_data=custom_generator(), + validation_data=invalid_generator(), validation_steps=10) - model.predict_generator(custom_generator(), + with self.assertRaises(AttributeError): + model.predict_generator(invalid_generator(), steps=5, max_queue_size=10, use_multiprocessing=False) - model.evaluate_generator(custom_generator(), + with self.assertRaises(ValueError): + model.evaluate_generator(invalid_generator(), steps=5, max_queue_size=10, use_multiprocessing=False) - def test_generator_methods_invalid_use_case(self): + def test_generator_input_to_fit_eval_predict(self): + val_data = np.ones([10, 10], np.float32), np.ones([10, 1], np.float32) - def custom_generator(): - while 1: - yield 0 + def ones_generator(): + while True: + yield np.ones([10, 10], np.float32), np.ones([10, 1], np.float32) + + inputs = keras.layers.Input(shape=(10,)) + x = keras.layers.Dense(10, activation='relu')(inputs) + outputs = keras.layers.Dense(1, activation='sigmoid')(x) + model = keras.Model(inputs, outputs) - with self.cached_session(): - model = keras.models.Sequential() - model.add(keras.layers.Dense(1, input_shape=(2,))) - model.compile(loss='mse', optimizer='sgd') + model.compile(RMSPropOptimizer(0.001), 'binary_crossentropy') + model.fit( + ones_generator(), + steps_per_epoch=2, + validation_data=val_data, + epochs=2) + model.evaluate(ones_generator(), steps=2) + model.predict(ones_generator(), steps=2) - with self.assertRaises(ValueError): - model.fit_generator(custom_generator(), - steps_per_epoch=5, - epochs=1, - verbose=1, - max_queue_size=10, - use_multiprocessing=False) - with self.assertRaises(ValueError): - model.fit_generator(custom_generator(), - steps_per_epoch=5, - epochs=1, - verbose=1, - max_queue_size=10, - use_multiprocessing=False, - validation_data=custom_generator(), - validation_steps=10) - with self.assertRaises(AttributeError): - model.predict_generator(custom_generator(), - steps=5, - max_queue_size=10, - use_multiprocessing=False) - with self.assertRaises(ValueError): - model.evaluate_generator(custom_generator(), - steps=5, - max_queue_size=10, - use_multiprocessing=False) + +@tf_test_util.run_all_in_graph_and_eager_modes +class TestGeneratorMethodsWithSequences(test.TestCase): def test_training_with_sequences(self): class DummySequence(keras.utils.Sequence): def __getitem__(self, idx): - return np.zeros([10, 2]), np.ones([10]) + return np.zeros([10, 2]), np.ones([10, 4]) def __len__(self): return 10 - arr_data = np.random.random((50, 2)) - arr_labels = np.random.random((50,)) - arr_sample_weights = np.random.random((50,)) - - def custom_generator(): - batch_size = 10 - num_samples = 50 - while True: - batch_index = np.random.randint(0, num_samples - batch_size) - start = batch_index - end = start + batch_size - x = arr_data[start: end] - y = arr_labels[start: end] - w = arr_sample_weights[start: end] - yield x, y, w - - with self.cached_session(): - model = keras.models.Sequential() - model.add(keras.layers.Dense(1, input_shape=(2,))) - model.compile(loss='mse', optimizer='sgd') + model = keras.models.Sequential() + model.add(keras.layers.Dense(4, input_shape=(2,))) + model.compile(loss='mse', optimizer='sgd') model.fit_generator(DummySequence(), steps_per_epoch=10, @@ -251,29 +305,6 @@ class TestGeneratorMethods(test.TestCase): workers=0, use_multiprocessing=False) - @tf_test_util.run_in_graph_and_eager_modes - def test_generator_input_to_fit_eval_predict(self): - val_data = np.ones([10, 10], np.float32), np.ones([10, 1], np.float32) - - def custom_generator(): - while True: - yield np.ones([10, 10], np.float32), np.ones([10, 1], np.float32) - - inputs = keras.layers.Input(shape=(10,)) - x = keras.layers.Dense(10, activation='relu')(inputs) - outputs = keras.layers.Dense(1, activation='sigmoid')(x) - model = keras.Model(inputs, outputs) - - model.compile(RMSPropOptimizer(0.001), 'binary_crossentropy') - model.fit( - custom_generator(), - steps_per_epoch=2, - validation_data=val_data, - epochs=2) - model.evaluate(custom_generator(), steps=2) - model.predict(custom_generator(), steps=2) - - @tf_test_util.run_in_graph_and_eager_modes def test_sequence_input_to_fit_eval_predict(self): val_data = np.ones([10, 10], np.float32), np.ones([10, 1], np.float32) @@ -303,5 +334,56 @@ class TestGeneratorMethods(test.TestCase): model.fit(CustomSequence(), sample_weight=np.ones([10, 1])) +@tf_test_util.run_all_in_graph_and_eager_modes +class TestConvertToGeneratorLike(test.TestCase, parameterized.TestCase): + simple_inputs = (np.ones((10, 10)), np.ones((10, 1))) + nested_inputs = ((np.ones((10, 10)), np.ones((10, 20))), (np.ones((10, 1)), + np.ones((10, 3)))) + + def _make_dataset(self, inputs, batches): + return dataset_ops.DatasetV2.from_tensors(inputs).repeat(batches) + + def _make_iterator(self, inputs, batches): + return dataset_ops.make_one_shot_iterator( + self._make_dataset(inputs, batches)) + + def _make_generator(self, inputs, batches): + + def _gen(): + for _ in range(batches): + yield inputs + + return _gen() + + def _make_numpy(self, inputs, _): + return inputs + + @parameterized.named_parameters( + ('simple_dataset', _make_dataset, simple_inputs), + ('simple_iterator', _make_iterator, simple_inputs), + ('simple_generator', _make_generator, simple_inputs), + ('simple_numpy', _make_numpy, simple_inputs), + ('nested_dataset', _make_dataset, nested_inputs), + ('nested_iterator', _make_iterator, nested_inputs), + ('nested_generator', _make_generator, nested_inputs), + ('nested_numpy', _make_numpy, nested_inputs)) + def test_convert_to_generator_like(self, input_fn, inputs): + expected_batches = 5 + data = input_fn(self, inputs, expected_batches) + + # Dataset and Iterator not supported in Legacy Graph mode. + if (not context.executing_eagerly() and + isinstance(data, (dataset_ops.DatasetV2, iterator_ops.Iterator))): + return + + generator, steps = training_generator.convert_to_generator_like( + data, batch_size=2, steps_per_epoch=expected_batches) + self.assertEqual(steps, expected_batches) + + for _ in range(expected_batches): + outputs = next(generator) + nest.assert_same_structure(outputs, inputs) + + if __name__ == '__main__': test.main() diff --git a/tensorflow/python/keras/engine/training_gpu_test.py b/tensorflow/python/keras/engine/training_gpu_test.py index 596d085f3f..45dcfe4399 100644 --- a/tensorflow/python/keras/engine/training_gpu_test.py +++ b/tensorflow/python/keras/engine/training_gpu_test.py @@ -69,7 +69,7 @@ class TrainingGPUTest(test.TestCase): return simple_model if test.is_gpu_available(cuda_only=True): - with self.session(use_gpu=True): + with test_util.use_gpu(): losses_to_test = ['sparse_categorical_crossentropy', 'categorical_crossentropy', 'binary_crossentropy'] diff --git a/tensorflow/python/keras/engine/training_test.py b/tensorflow/python/keras/engine/training_test.py index 3cb24255d1..8e3b61be0c 100644 --- a/tensorflow/python/keras/engine/training_test.py +++ b/tensorflow/python/keras/engine/training_test.py @@ -37,6 +37,7 @@ from tensorflow.python.keras import testing_utils from tensorflow.python.keras.callbacks import Callback from tensorflow.python.keras.engine.training_utils import weighted_masked_objective from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.ops import variables as variables_lib from tensorflow.python.platform import test @@ -448,6 +449,7 @@ class TrainingTest(test.TestCase): optimizer=keras.optimizers.Adam(lr=0.0001), metrics=['accuracy']) + @tf_test_util.run_deprecated_v1 def test_that_trainable_disables_updates(self): val_a = np.random.random((10, 4)) val_out = np.random.random((10, 4)) @@ -544,6 +546,152 @@ class TrainingTest(test.TestCase): 'val_loss', 'val_weighted_mean_absolute_error' ])) + @tf_test_util.run_in_graph_and_eager_modes + def test_mismatched_output_shape_and_target_shape(self): + model = keras.Sequential([ + keras.layers.Dense(2, input_shape=(3, 4)), + keras.layers.Dense(5), + ]) + model.compile(RMSPropOptimizer(learning_rate=0.001), + loss='sparse_categorical_crossentropy') + # Test with Numpy data + x_train = np.random.random((10, 3, 4)) + y_train = np.random.randint(0, 5, size=(10, 3)) + model.fit(x_train, y_train, batch_size=5, epochs=1) + + # Test with iterator + dataset = dataset_ops.Dataset.from_tensor_slices((x_train, y_train)) + dataset = dataset.repeat(10) + dataset = dataset.batch(10) + iterator = dataset_ops.make_one_shot_iterator(dataset) + model.fit(iterator, epochs=1, steps_per_epoch=2) + + if context.executing_eagerly(): + # Test with eager execution + model.compile(RMSPropOptimizer(learning_rate=0.001), + loss='sparse_categorical_crossentropy', + run_eagerly=True) + model.fit(x_train, y_train, batch_size=5, epochs=1) + + # Test with eager execution and iterator + model.fit(iterator, epochs=1, steps_per_epoch=2) + + def test_losses_in_defun(self): + with context.eager_mode(): + layer = keras.layers.Dense(1, kernel_regularizer='l1') + layer(array_ops.ones([1, 10])) + + @function.defun + def get_losses(): + return layer.losses + + self.assertAllEqual( + self.evaluate(layer.losses), self.evaluate(get_losses())) + + @tf_test_util.run_in_graph_and_eager_modes + def test_logging(self): + mock_stdout = io.BytesIO() if six.PY2 else io.StringIO() + model = keras.models.Sequential() + model.add(keras.layers.Dense(10, activation='relu')) + model.add(keras.layers.Dense(1, activation='sigmoid')) + model.compile( + RMSPropOptimizer(learning_rate=0.001), loss='binary_crossentropy') + with test.mock.patch.object(sys, 'stdout', mock_stdout): + model.fit( + np.ones((10, 10), 'float32'), np.ones((10, 1), 'float32'), epochs=10) + self.assertTrue('Epoch 5/10' in mock_stdout.getvalue()) + + @tf_test_util.run_in_graph_and_eager_modes + def test_training_with_loss_instance(self): + a = keras.layers.Input(shape=(3,), name='input_a') + b = keras.layers.Input(shape=(3,), name='input_b') + + dense = keras.layers.Dense(4, name='dense') + c = dense(a) + d = dense(b) + e = keras.layers.Dropout(0.5, name='dropout')(c) + + model = keras.models.Model([a, b], [d, e]) + loss_weights = [1., 0.5] + model.compile( + RMSPropOptimizer(learning_rate=0.001), + loss=keras.losses.MeanSquaredError(), + metrics=[metrics_module.CategoricalAccuracy(), 'mae'], + loss_weights=loss_weights) + + input_a_np = np.random.random((10, 3)) + input_b_np = np.random.random((10, 3)) + + output_d_np = np.random.random((10, 4)) + output_e_np = np.random.random((10, 4)) + + model.fit([input_a_np, input_b_np], [output_d_np, output_e_np], + epochs=1, + batch_size=5) + + @tf_test_util.run_in_graph_and_eager_modes + def test_static_batch_in_input_layer(self): + + class Counter(keras.callbacks.Callback): + + def __init__(self): + self.batches = 0 + + def on_batch_end(self, batch, logs=None): + self.batches += 1 + + x, y = np.ones((64, 10), 'float32'), np.ones((64, 1), 'float32') + + for batch_size, expected_batches in [(None, 2), (4, 16)]: + inputs = keras.Input(batch_size=batch_size, shape=(10,)) + outputs = keras.layers.Dense(1, activation='sigmoid')(inputs) + model = keras.Model(inputs, outputs) + + model.compile(keras.optimizer_v2.adam.Adam(0.001), 'binary_crossentropy') + counter = Counter() + model.fit(x, y, callbacks=[counter]) + self.assertEqual(counter.batches, expected_batches) + + model = keras.Sequential( + [keras.layers.Dense(1, batch_input_shape=(batch_size, 10))]) + model.compile(keras.optimizer_v2.adam.Adam(0.001), 'binary_crossentropy') + counter = Counter() + model.fit(x, y, callbacks=[counter]) + self.assertEqual(counter.batches, expected_batches) + + @tf_test_util.run_in_graph_and_eager_modes + def test_static_batch_in_input_layer_consistency_checks(self): + x, y = np.ones((64, 10), 'float32'), np.ones((64, 1), 'float32') + + inputs = keras.Input(batch_size=2, shape=(10,)) + outputs = keras.layers.Dense(1, activation='sigmoid')(inputs) + model = keras.Model(inputs, outputs) + model.compile(keras.optimizer_v2.adam.Adam(0.001), 'binary_crossentropy') + with self.assertRaisesRegexp(ValueError, + 'incompatible with the specified batch size'): + model.fit(x, y, batch_size=4) + + data = dataset_ops.DatasetV2.from_tensor_slices((x, y)) + data = data.batch(4, drop_remainder=True) + with self.assertRaisesRegexp(ValueError, + 'incompatible with the specified batch size'): + model.fit(data, steps_per_epoch=16) + + @tf_test_util.run_in_graph_and_eager_modes + def test_compatible_batch_size_functional_model(self): + + class MyLayer(keras.layers.Layer): + + def call(self, inputs): + return array_ops.concat(inputs, axis=0) + + input1 = keras.Input(batch_size=2, shape=(10,)) + input2 = keras.Input(batch_size=3, shape=(10,)) + outputs = MyLayer()([input1, input2]) + with self.assertRaisesRegexp(ValueError, + 'specified batch sizes of the Input Layers'): + keras.Model([input1, input2], outputs) + class TestExceptionsAndWarnings(test.TestCase): @@ -1062,6 +1210,7 @@ class LossMaskingTest(test.TestCase): class TestDynamicTrainability(test.TestCase): + @tf_test_util.run_deprecated_v1 def test_trainable_warning(self): with self.cached_session(): x = np.random.random((5, 3)) @@ -1075,6 +1224,7 @@ class TestDynamicTrainability(test.TestCase): model.train_on_batch(x, y) self.assertRaises(Warning) + @tf_test_util.run_deprecated_v1 def test_trainable_argument(self): with self.cached_session(): x = np.random.random((5, 3)) @@ -1205,6 +1355,7 @@ class TestDynamicTrainability(test.TestCase): class TestTrainingWithDataTensors(test.TestCase): + @tf_test_util.run_deprecated_v1 def test_training_and_eval_methods_on_symbolic_tensors_single_io(self): with self.cached_session(): x = keras.layers.Input(shape=(3,), name='input') @@ -1245,6 +1396,7 @@ class TestTrainingWithDataTensors(test.TestCase): epochs=1, steps_per_epoch=2, verbose=0, validation_data=(inputs, targets), validation_steps=2) + @tf_test_util.run_deprecated_v1 def test_training_and_eval_methods_on_symbolic_tensors_multi_io(self): with self.cached_session(): a = keras.layers.Input(shape=(3,), name='input_a') @@ -1340,6 +1492,7 @@ class TestTrainingWithDataTensors(test.TestCase): model.predict([input_a_tf, input_b_tf], steps=2) model.test_on_batch([input_a_tf, input_b_tf], [output_d_tf, output_e_tf]) + @tf_test_util.run_deprecated_v1 def test_model_with_input_feed_tensor(self): """We test building a model with a TF variable as input. @@ -1518,6 +1671,7 @@ class TestTrainingWithDataTensors(test.TestCase): # evaluate _ = model.evaluate(input_a_np, [output_a_np]) + @tf_test_util.run_deprecated_v1 def test_model_with_external_loss(self): with self.cached_session(): # None loss, only regularization loss. @@ -1713,6 +1867,7 @@ class TestTrainingWithDataTensors(test.TestCase): model.train_on_batch(input_val, None, sample_weight={'dense_a': np.random.random((10,))}) + @tf_test_util.run_deprecated_v1 def test_model_custom_target_tensors(self): with self.cached_session(): a = keras.Input(shape=(3,), name='input_a') @@ -1774,264 +1929,6 @@ class TestTrainingWithDataTensors(test.TestCase): [output_a_np, output_b_np]) -class TestTrainingWithDatasetIterators(test.TestCase): - - @tf_test_util.run_in_graph_and_eager_modes - def test_training_and_eval_methods_on_iterators_single_io(self): - model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) - optimizer = RMSPropOptimizer(learning_rate=0.001) - loss = 'mse' - metrics = ['mae', metrics_module.CategoricalAccuracy()] - model.compile(optimizer, loss, metrics=metrics) - - inputs = np.zeros((10, 3)) - targets = np.zeros((10, 4)) - dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) - dataset = dataset.repeat(100) - dataset = dataset.batch(10) - iterator = dataset.make_one_shot_iterator() - - model.fit(iterator, epochs=1, steps_per_epoch=2, verbose=1) - model.evaluate(iterator, steps=2, verbose=1) - model.predict(iterator, steps=2) - model.train_on_batch(iterator) - model.test_on_batch(iterator) - model.predict_on_batch(iterator) - - # Test with validation data - model.fit(iterator, - epochs=1, steps_per_epoch=2, verbose=0, - validation_data=iterator, validation_steps=2) - # Test with validation split - with self.assertRaisesRegexp( - ValueError, '`validation_split` argument is not supported ' - 'when input `x` is a dataset or a dataset iterator'): - model.fit(iterator, - epochs=1, steps_per_epoch=2, verbose=0, - validation_split=0.5, validation_steps=2) - - # Test with sample weight. - sample_weight = np.random.random((10,)) - with self.assertRaisesRegexp( - ValueError, '`sample_weight` argument is not supported ' - 'when input `x` is a dataset or a dataset iterator'): - model.fit( - iterator, - epochs=1, - steps_per_epoch=2, - verbose=0, - sample_weight=sample_weight) - - # Test invalid usage - with self.assertRaisesRegexp(ValueError, - 'you should not specify a target'): - model.fit(iterator, iterator, - epochs=1, steps_per_epoch=2, verbose=0) - - with self.assertRaisesRegexp( - ValueError, 'you should specify the `steps_per_epoch` argument'): - model.fit(iterator, epochs=1, verbose=0) - with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): - model.evaluate(iterator, verbose=0) - with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): - model.predict(iterator, verbose=0) - - @tf_test_util.run_in_graph_and_eager_modes - def test_get_next_op_created_once(self): - model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) - optimizer = RMSPropOptimizer(learning_rate=0.001) - loss = 'mse' - metrics = ['mae'] - model.compile(optimizer, loss, metrics=metrics) - - inputs = np.zeros((10, 3)) - targets = np.zeros((10, 4)) - dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) - dataset = dataset.repeat(100) - dataset = dataset.batch(10) - iterator = dataset.make_one_shot_iterator() - - model.fit(iterator, epochs=1, steps_per_epoch=2, verbose=1) - # Finalize graph to make sure we are not appending another iterator - # get_next op in the graph. - ops.get_default_graph().finalize() - model.fit(iterator, epochs=1, steps_per_epoch=2, verbose=1) - - @tf_test_util.run_in_graph_and_eager_modes - def test_iterators_running_out_of_data(self): - model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) - optimizer = RMSPropOptimizer(learning_rate=0.001) - loss = 'mse' - metrics = ['mae'] - model.compile(optimizer, loss, metrics=metrics) - - inputs = np.zeros((10, 3)) - targets = np.zeros((10, 4)) - dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) - dataset = dataset.repeat(2) - dataset = dataset.batch(10) - iterator = dataset.make_one_shot_iterator() - - with test.mock.patch.object(logging, 'warning') as mock_log: - model.fit(iterator, epochs=1, steps_per_epoch=3, verbose=0) - self.assertRegexpMatches( - str(mock_log.call_args), - 'dataset iterator ran out of data') - - -class TestTrainingWithDataset(test.TestCase): - - @tf_test_util.run_in_graph_and_eager_modes - def test_calling_model_on_same_dataset(self): - model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) - optimizer = RMSPropOptimizer(learning_rate=0.001) - loss = 'mse' - metrics = ['mae'] - model.compile(optimizer, loss, metrics=metrics) - - inputs = np.zeros((10, 3)) - targets = np.zeros((10, 4)) - dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) - dataset = dataset.repeat(100) - dataset = dataset.batch(10) - - # Call fit with validation data - model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0, - validation_data=dataset, validation_steps=2) - # Finalize the graph to make sure new ops aren't added when calling on the - # same dataset - ops.get_default_graph().finalize() - model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0, - validation_data=dataset, validation_steps=2) - - @tf_test_util.run_in_graph_and_eager_modes - def test_training_and_eval_methods_on_dataset(self): - model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) - optimizer = RMSPropOptimizer(learning_rate=0.001) - loss = 'mse' - metrics = ['mae', metrics_module.CategoricalAccuracy()] - model.compile(optimizer, loss, metrics=metrics) - - inputs = np.zeros((10, 3)) - targets = np.zeros((10, 4)) - dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) - dataset = dataset.repeat(100) - dataset = dataset.batch(10) - - model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=1) - model.evaluate(dataset, steps=2, verbose=1) - model.predict(dataset, steps=2) - model.train_on_batch(dataset) - model.predict_on_batch(dataset) - - # Test with validation data - model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=0, - validation_data=dataset, validation_steps=2) - - # Test with validation split - with self.assertRaisesRegexp( - ValueError, '`validation_split` argument is not supported ' - 'when input `x` is a dataset or a dataset iterator'): - model.fit(dataset, - epochs=1, steps_per_epoch=2, verbose=0, - validation_split=0.5, validation_steps=2) - - # Test with sample weight. - sample_weight = np.random.random((10,)) - with self.assertRaisesRegexp( - ValueError, '`sample_weight` argument is not supported ' - 'when input `x` is a dataset or a dataset iterator'): - model.fit( - dataset, - epochs=1, - steps_per_epoch=2, - verbose=0, - sample_weight=sample_weight) - - # Test invalid usage - with self.assertRaisesRegexp(ValueError, - 'you should not specify a target'): - model.fit(dataset, dataset, - epochs=1, steps_per_epoch=2, verbose=0) - - with self.assertRaisesRegexp( - ValueError, 'you should specify the `steps_per_epoch` argument'): - model.fit(dataset, epochs=1, verbose=0) - with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): - model.evaluate(dataset, verbose=0) - with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): - model.predict(dataset, verbose=0) - - @tf_test_util.run_in_graph_and_eager_modes - def test_dataset_with_sample_weights(self): - model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) - optimizer = RMSPropOptimizer(learning_rate=0.001) - loss = 'mse' - metrics = ['mae', metrics_module.CategoricalAccuracy()] - model.compile(optimizer, loss, metrics=metrics) - - inputs = np.zeros((10, 3), np.float32) - targets = np.zeros((10, 4), np.float32) - sample_weights = np.ones((10), np.float32) - dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets, - sample_weights)) - dataset = dataset.repeat(100) - dataset = dataset.batch(10) - - model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=1) - model.evaluate(dataset, steps=2, verbose=1) - model.predict(dataset, steps=2) - model.train_on_batch(dataset) - model.predict_on_batch(dataset) - - @tf_test_util.run_in_graph_and_eager_modes - def test_dataset_with_sparse_labels(self): - model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) - optimizer = RMSPropOptimizer(learning_rate=0.001) - loss = 'sparse_categorical_crossentropy' - model.compile(optimizer, loss) - - inputs = np.zeros((10, 3)) - targets = np.random.randint(0, 4, size=10, dtype=np.int32) - dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) - dataset = dataset.repeat(100) - dataset = dataset.batch(10) - - model.fit(dataset, epochs=1, steps_per_epoch=2, verbose=1) - - def test_dataset_input_shape_validation(self): - with self.cached_session(): - model = testing_utils.get_small_functional_mlp(1, 4, input_dim=3) - model.compile(optimizer=RMSPropOptimizer(learning_rate=0.001), loss='mse') - - # User forgets to batch the dataset - inputs = np.zeros((10, 3)) - targets = np.zeros((10, 4)) - dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) - dataset = dataset.repeat(100) - - with self.assertRaisesRegexp( - ValueError, - r'expected (.*?) to have shape \(3,\) but got array with shape \(1,\)' - ): - model.train_on_batch(dataset) - - # Wrong input shape - inputs = np.zeros((10, 5)) - targets = np.zeros((10, 4)) - dataset = dataset_ops.Dataset.from_tensor_slices((inputs, targets)) - dataset = dataset.repeat(100) - dataset = dataset.batch(10) - - with self.assertRaisesRegexp(ValueError, - r'expected (.*?) to have shape \(3,\)'): - model.train_on_batch(dataset) - - class TestTrainingWithMetrics(test.TestCase): """Training tests related to metrics.""" @@ -2095,39 +1992,6 @@ class TestTrainingWithMetrics(test.TestCase): self.assertEqual(outs[1], 0.) self.assertEqual(outs[2], 0.) - @tf_test_util.run_in_graph_and_eager_modes - def test_metrics_correctness_with_iterator(self): - model = keras.Sequential() - model.add( - keras.layers.Dense( - 8, activation='relu', input_dim=4, kernel_initializer='ones')) - model.add( - keras.layers.Dense( - 1, activation='sigmoid', kernel_initializer='ones')) - model.compile( - loss='binary_crossentropy', - metrics=['accuracy', metrics_module.BinaryAccuracy()], - optimizer=RMSPropOptimizer(learning_rate=0.001)) - - np.random.seed(123) - x = np.random.randint(10, size=(100, 4)).astype(np.float32) - y = np.random.randint(2, size=(100, 1)).astype(np.float32) - dataset = dataset_ops.Dataset.from_tensor_slices((x, y)) - dataset = dataset.batch(10) - iterator = dataset.make_one_shot_iterator() - outs = model.evaluate(iterator, steps=10) - self.assertEqual(np.around(outs[1], decimals=1), 0.5) - self.assertEqual(np.around(outs[2], decimals=1), 0.5) - - y = np.zeros((100, 1), dtype=np.float32) - dataset = dataset_ops.Dataset.from_tensor_slices((x, y)) - dataset = dataset.repeat(100) - dataset = dataset.batch(10) - iterator = dataset.make_one_shot_iterator() - outs = model.evaluate(iterator, steps=10) - self.assertEqual(outs[1], 0.) - self.assertEqual(outs[2], 0.) - @tf_test_util.run_in_graph_and_eager_modes def test_metrics_correctness_with_weighted_metrics(self): np.random.seed(1337) @@ -2153,7 +2017,7 @@ class TestTrainingWithMetrics(test.TestCase): w = np.array([[3., 4.], [1., 2.]]) outs = model.evaluate(x, y, sample_weight=w) - self.assertArrayNear(outs, [0.3, 0.7, 0.3], .001) + self.assertArrayNear(outs, [0.75, 0.7, 0.3], .001) # Verify that metric value is same with arbitrary weights and batch size. x = np.random.random((50, 2, 1)) @@ -2223,32 +2087,331 @@ class TestTrainingWithMetrics(test.TestCase): # verify that masking is combined with sample weights. w = np.array([3, 2, 4]) scores = model.train_on_batch(x, y, sample_weight=w) - self.assertArrayNear(scores, [0.2, 0.8], 0.1) + self.assertArrayNear(scores, [0.3328, 0.8], 0.001) + + @tf_test_util.run_deprecated_v1 + def test_add_metric_with_tensor_on_model_in_graph_mode(self): + with self.cached_session(): + x = keras.layers.Input(shape=(1,)) + y = keras.layers.Dense(1, kernel_initializer='ones')(x) + model = keras.models.Model(x, y) + model.add_metric( + math_ops.reduce_sum(y), name='metric_1', aggregation='mean') + + # test with a metric which does not have the standard signature: + # (y_true, y_pred, sample_Weight) + model.add_metric(metrics_module.Mean(name='metric_2')(y)) + model.compile('sgd', loss='mse') + + inputs = np.ones(shape=(10, 1)) + targets = np.ones(shape=(10, 1)) + history = model.fit( + inputs, + targets, + epochs=2, + batch_size=5, + validation_data=(inputs, targets)) + self.assertEqual(history.history['metric_1'][-1], 5) + self.assertEqual(history.history['metric_2'][-1], 1) + self.assertEqual(history.history['val_metric_1'][-1], 5) + self.assertEqual(history.history['val_metric_2'][-1], 1) + + eval_results = model.evaluate(inputs, targets, batch_size=5) + self.assertEqual(eval_results[-1], 1) + self.assertEqual(eval_results[-2], 5) + + model.predict(inputs, batch_size=5) + model.train_on_batch(inputs, targets) + model.test_on_batch(inputs, targets) @tf_test_util.run_in_graph_and_eager_modes - def test_logging(self): - mock_stdout = io.BytesIO() if six.PY2 else io.StringIO() - model = keras.models.Sequential() - model.add(keras.layers.Dense(10, activation='relu')) - model.add(keras.layers.Dense(1, activation='sigmoid')) - model.compile( - RMSPropOptimizer(learning_rate=0.001), loss='binary_crossentropy') - with test.mock.patch.object(sys, 'stdout', mock_stdout): - model.fit( - np.ones((10, 10), 'float32'), np.ones((10, 1), 'float32'), epochs=10) - self.assertTrue('Epoch 5/10' in mock_stdout.getvalue()) + def test_add_metric_in_model_call(self): - def test_losses_in_defun(self): + class TestModel(keras.Model): + + def __init__(self): + super(TestModel, self).__init__(name='test_model') + self.dense1 = keras.layers.Dense(2, kernel_initializer='ones') + self.mean = metrics_module.Mean(name='metric_1') + + def call(self, x): + self.add_metric( + math_ops.reduce_sum(x), name='metric_2', aggregation='mean') + # Provide same name as in the instance created in __init__ + # for eager mode + self.add_metric(self.mean(x), name='metric_1') + return self.dense1(x) + + model = TestModel() + model.compile(loss='mse', optimizer=RMSPropOptimizer(0.01)) + + x = np.ones(shape=(10, 1)) + y = np.ones(shape=(10, 2)) + history = model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) + self.assertAlmostEqual(history.history['metric_1'][-1], 1, 0) + self.assertAlmostEqual(history.history['val_metric_1'][-1], 1, 0) + self.assertAlmostEqual(history.history['metric_2'][-1], 5, 0) + self.assertAlmostEqual(history.history['val_metric_2'][-1], 5, 0) + + eval_results = model.evaluate(x, y, batch_size=5) + self.assertAlmostEqual(eval_results[1], 1, 0) + self.assertAlmostEqual(eval_results[2], 5, 0) + + model.predict(x, batch_size=5) + model.train_on_batch(x, y) + model.test_on_batch(x, y) + + def test_add_metric_in_model_call_run_eagerly(self): with context.eager_mode(): - layer = keras.layers.Dense(1, kernel_regularizer='l1') - layer(array_ops.ones([1, 10])) - @function.defun - def get_losses(): - return layer.losses + class TestModel(keras.Model): + + def __init__(self): + super(TestModel, self).__init__(name='test_model') + self.dense1 = keras.layers.Dense(2, kernel_initializer='ones') + self.mean = metrics_module.Mean(name='metric_1') + + def call(self, x): + self.add_metric( + math_ops.reduce_sum(x), name='metric_2', aggregation='mean') + # Provide same name as in the instance created in __init__ + # for eager mode + self.add_metric(self.mean(x), name='metric_1') + return self.dense1(x) + + model = TestModel() + model.compile( + loss='mse', optimizer=RMSPropOptimizer(0.01), run_eagerly=True) + + x = np.ones(shape=(10, 1)) + y = np.ones(shape=(10, 2)) + history = model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) + self.assertAlmostEqual(history.history['metric_1'][-1], 1, 0) + self.assertAlmostEqual(history.history['val_metric_1'][-1], 1, 0) + self.assertAlmostEqual(history.history['metric_2'][-1], 5, 0) + self.assertAlmostEqual(history.history['val_metric_2'][-1], 5, 0) + + eval_results = model.evaluate(x, y, batch_size=5) + self.assertAlmostEqual(eval_results[1], 1, 0) + self.assertAlmostEqual(eval_results[2], 5, 0) + + model.predict(x, batch_size=5) + model.train_on_batch(x, y) + model.test_on_batch(x, y) + + @tf_test_util.run_in_graph_and_eager_modes + def test_add_metric_in_layer_call(self): + + class TestLayer(keras.layers.Layer): + + def build(self, input_shape): + self.a = self.add_variable( + 'a', (1, 1), initializer='ones', trainable=False) + self.built = True + + def call(self, inputs): + self.add_metric( + math_ops.reduce_sum(inputs), name='metric_1', aggregation='mean') + return inputs + 1 + + model = keras.Sequential() + model.add(TestLayer(input_shape=(1,))) + model.add(keras.layers.Dense(2, kernel_initializer='ones')) + model.compile(loss='mse', optimizer=RMSPropOptimizer(0.01)) + + x = np.ones(shape=(10, 1)) + y = np.ones(shape=(10, 2)) + history = model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) + self.assertEqual(history.history['metric_1'][-1], 5) + self.assertAlmostEqual(history.history['val_metric_1'][-1], 5, 0) + + def test_add_metric_in_layer_call_run_eagerly(self): + with context.eager_mode(): + + class TestLayer(keras.layers.Layer): + + def build(self, input_shape): + self.a = self.add_variable( + 'a', (1, 1), initializer='ones', trainable=False) + self.built = True + + def call(self, inputs): + self.add_metric( + math_ops.reduce_sum(inputs), name='metric_1', aggregation='mean') + return inputs + 1 + + model = keras.Sequential() + model.add(TestLayer(input_shape=(1,))) + model.add(keras.layers.Dense(2, kernel_initializer='ones')) + model.compile( + loss='mse', optimizer=RMSPropOptimizer(0.01), run_eagerly=True) + + x = np.ones(shape=(10, 1)) + y = np.ones(shape=(10, 2)) + history = model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) + self.assertEqual(history.history['metric_1'][-1], 5) + self.assertAlmostEqual(history.history['val_metric_1'][-1], 5, 0) + + @tf_test_util.run_deprecated_v1 + def test_model_metrics_list(self): + with self.cached_session(): + x = keras.layers.Input(shape=(1,)) + y = keras.layers.Dense(1, kernel_initializer='ones')(x) + model = keras.models.Model(x, y) + model.add_metric( + math_ops.reduce_sum(y), name='metric_1', aggregation='mean') + model.add_metric(metrics_module.Mean(name='metric_2')(y)) + model.compile('sgd', loss='mse', metrics=['acc']) + + # Verify that the metrics added using `compile` and `add_metric` API are + # included + self.assertEqual(model._compile_metrics, ['acc']) + names = [] + for m in model.metrics: + if isinstance(m, metrics_module.Metric): + names.append(m.name) + else: + names.append(m.__name__) + self.assertEqual(names, ['binary_accuracy', 'metric_1', 'metric_2']) + + def test_model_eager_metrics_list(self): + with context.eager_mode(): + + class TestModel(keras.Model): + + def __init__(self): + super(TestModel, self).__init__(name='test_model') + self.dense1 = keras.layers.Dense(2, kernel_initializer='ones') + + def call(self, x): + self.add_metric( + math_ops.reduce_sum(x), name='metric_1', aggregation='mean') + return self.dense1(x) + + model = TestModel() + model.compile( + loss='mse', + optimizer=RMSPropOptimizer(0.01), + metrics=['acc'], + run_eagerly=True) + x = np.ones(shape=(10, 1)) + y = np.ones(shape=(10, 2)) + model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) + + self.assertEqual(model._compile_metrics, ['acc']) + names = [] + for m in model.metrics: + if isinstance(m, metrics_module.Metric): + names.append(m.name) + else: + names.append(m.__name__) + self.assertEqual(names, ['categorical_accuracy', 'metric_1']) + + @tf_test_util.run_in_graph_and_eager_modes + def test_multiple_add_metric_calls(self): + + class TestModel(keras.Model): + + def __init__(self): + super(TestModel, self).__init__(name='test_model') + self.dense1 = keras.layers.Dense(2, kernel_initializer='ones') + self.mean1 = metrics_module.Mean(name='metric_1') + self.mean2 = metrics_module.Mean(name='metric_2') + + def call(self, x): + self.add_metric(self.mean2(x), name='metric_2') + self.add_metric(self.mean1(x), name='metric_1') + self.add_metric( + math_ops.reduce_sum(x), name='metric_3', aggregation='mean') + return self.dense1(x) + + model = TestModel() + model.compile(loss='mse', optimizer=RMSPropOptimizer(0.01)) + + x = np.ones(shape=(10, 1)) + y = np.ones(shape=(10, 2)) + history = model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) + self.assertAlmostEqual(history.history['metric_1'][-1], 1, 0) + self.assertAlmostEqual(history.history['metric_2'][-1], 1, 0) + self.assertAlmostEqual(history.history['metric_3'][-1], 5, 0) + + eval_results = model.evaluate(x, y, batch_size=5) + self.assertArrayNear(eval_results[1:4], [1, 1, 5], 0.1) + + model.predict(x, batch_size=5) + model.train_on_batch(x, y) + model.test_on_batch(x, y) + + def test_invalid_metric_tensor_in_call(self): + with context.eager_mode(): + + class TestLayer(keras.layers.Layer): + + def call(self, inputs): + self.add_metric(metrics_module.Mean(name='metric_1')(inputs)) + return inputs + 1 + + model = keras.Sequential() + model.add(TestLayer(input_shape=(1,))) + model.add(keras.layers.Dense(2, kernel_initializer='ones')) + model.compile( + loss='mse', optimizer=RMSPropOptimizer(0.01), run_eagerly=True) + + x = np.ones(shape=(10, 1)) + y = np.ones(shape=(10, 2)) + with self.assertRaisesRegexp( + ValueError, + 'We do not support adding an aggregated metric tensor in `call` in ' + 'eager execution.'): + model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) + + @tf_test_util.run_in_graph_and_eager_modes + def test_duplicate_metric_name_in_add_metric(self): + + class TestModel(keras.Model): + + def __init__(self): + super(TestModel, self).__init__(name='test_model') + self.dense1 = keras.layers.Dense(2, kernel_initializer='ones') + self.mean = metrics_module.Mean(name='metric_1') + self.mean2 = metrics_module.Mean(name='metric_1') + + def call(self, x): + self.add_metric(self.mean(x), name='metric_1') + return self.dense1(x) + + model = TestModel() + model.compile(loss='mse', optimizer=RMSPropOptimizer(0.01)) + + x = np.ones(shape=(10, 1)) + y = np.ones(shape=(10, 2)) + with self.assertRaisesRegexp( + ValueError, + 'Please provide different names for the metrics you have added. ' + 'We found 2 metrics with the name: "metric_1"'): + model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) + + @tf_test_util.run_in_graph_and_eager_modes + def test_multiple_no_name_input_to_add_metric(self): + + class TestModel(keras.Model): + + def __init__(self): + super(TestModel, self).__init__(name='test_model') + self.dense1 = keras.layers.Dense(2, kernel_initializer='ones') + + def call(self, x): + self.add_metric(math_ops.reduce_sum(x), aggregation='mean') + self.add_metric(math_ops.reduce_sum(x), aggregation='mean') + return self.dense1(x) + + model = TestModel() + model.compile(loss='mse', optimizer=RMSPropOptimizer(0.01)) + x = np.ones(shape=(10, 1)) + y = np.ones(shape=(10, 2)) + model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) + self.assertEqual([m.name for m in model.metrics], ['mean', 'mean_1']) - self.assertAllEqual(self.evaluate(layer.losses), - self.evaluate(get_losses())) if __name__ == '__main__': test.main() diff --git a/tensorflow/python/keras/engine/training_utils.py b/tensorflow/python/keras/engine/training_utils.py index e563b7a23d..0157fe084c 100644 --- a/tensorflow/python/keras/engine/training_utils.py +++ b/tensorflow/python/keras/engine/training_utils.py @@ -18,163 +18,176 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import abc from collections import OrderedDict import copy -import math import numpy as np import six -from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import iterator_ops from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import tensor_util from tensorflow.python.keras import backend as K +from tensorflow.python.keras import callbacks as cbks from tensorflow.python.keras import losses from tensorflow.python.keras import metrics as metrics_module from tensorflow.python.keras.engine import base_layer +from tensorflow.python.keras.utils import generic_utils +from tensorflow.python.keras.utils.losses_utils import squeeze_or_expand_dimensions from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import weights_broadcast_ops from tensorflow.python.util import nest -def _map_nested(data, func): - """Maps each nested element using func.""" - if isinstance(data, list): - return [_map_nested(nested_data, func) for nested_data in data] - elif isinstance(data, tuple): - return tuple(_map_nested(nested_data, func) for nested_data in data) - elif isinstance(data, dict): - return { - k: _map_nested(nested_data, func) for k, nested_data in data.items() - } - else: - return func(data) +@six.add_metaclass(abc.ABCMeta) +class Aggregator(object): + """Abstract base class used to aggregate batch-level outputs of a loop. + Attributes: + use_steps: Whether the loop is using `step` or `batch_size`. + num_samples_or_steps: Either `batch_size*num_batches` or `steps`. + results: What to return at the end of the aggregation loop. + """ -def _nested_all(data, cond_func): - """Checks if all elements in a nested structure satisfy cond_func.""" - if isinstance(data, (tuple, list)): - return all([_nested_all(nested_data, cond_func) for nested_data in data]) - elif isinstance(data, dict): - return all( - [_nested_all(nested_data, cond_func) for nested_data in data.values()]) - else: - return cond_func(data) + def __init__(self, use_steps, num_samples_or_steps): + self.use_steps = use_steps + self.num_samples_or_steps = num_samples_or_steps + self.results = [] + @abc.abstractmethod + def create(self, batch_outs): + """Creates the initial results from the first batch outputs. -def _nested_any(data, cond_func): - """Checks if any nested_elements in a nested structure satisfy cond_func.""" - if isinstance(data, (tuple, list)): - return any([_nested_any(nested_data, cond_func) for nested_data in data]) - elif isinstance(data, dict): - return any( - [_nested_any(nested_data, cond_func) for nested_data in data.values()]) - else: - return cond_func(data) - - -def _convert_lists_to_tuples(data): - """Converts all lists to tuples, since Datasets expect tuples.""" - if isinstance(data, (tuple, list)): - return tuple(_convert_lists_to_tuples(nested_data) for nested_data in data) - elif isinstance(data, dict): - return { - k: _convert_lists_to_tuples(nested_data) - for k, nested_data in data.items() - } - else: - return data + Arguments: + batch_outs: A list of batch-level outputs. + """ + NotImplementedError('Must be implemented in subclasses.') + @abc.abstractmethod + def aggregate(self, batch_outs, batch_start=None, batch_end=None): + """Aggregates batch-level results into total results. -def _get_batch_axis_size(data): - """Returns batch axis shape for nested data.""" - if isinstance(data, (tuple, list)): - return _get_batch_axis_size(data[0]) - elif isinstance(data, dict): - return _get_batch_axis_size(list(data.values())) - else: - return int(data.shape[0]) + Arguments: + batch_outs: A list of batch-level outputs. + batch_start: The start index of this batch. Always `None` if `use_steps` + is `True`. + batch_end: The end index of this batch. Always `None` if `use_steps` is + `True`. + """ + NotImplementedError('Must be implemented in subclasses.') + @abc.abstractmethod + def finalize(self): + """Prepares the total results to be returned.""" + NotImplementedError('Must be implemented in subclasses.') -def convert_to_iterator(x=None, - y=None, - sample_weights=None, - batch_size=None, - steps_per_epoch=None, - epochs=1, - shuffle=False, - is_validation=False): - """Converts NumPy arrays or EagerTensors to an EagerIterator. - Combines all provided data into a single EagerIterator. +class MetricsAggregator(Aggregator): + """Aggregator that calculates loss and metrics info.""" - Arguments: - x: NumPy array or EagerTensor, or list of Numpy arrays or EagerTensors - representing inputs to a model. - y: Optional. NumPy array or EagerTensor, or list of Numpy arrays or - EagerTensors representing targets of a model. - sample_weights: Optional NumPy array or EagerTensor representing sample - weights. - batch_size: Used to batch data and calculate how many steps EagerIterator - should take per epoch. - steps_per_epoch: If provided, how many steps EagerIterator should take per - epoch. - epochs: Epochs to repeat iterator for. - shuffle: Whether to shuffle data after each epoch. - is_validation: Whether this call is for validation during a training - (e.g., `fit()`) call. This info is used to construct error messages - (if any). + def create(self, batch_outs): + self.results = [0.] * len(batch_outs) - Raises: - ValueError: if steps_per_epoch cannot be calculated from the data - provided. + def aggregate(self, batch_outs, batch_start=None, batch_end=None): + # Loss. + if self.use_steps: + self.results[0] += batch_outs[0] + else: + self.results[0] += batch_outs[0] * (batch_end - batch_start) + # Metrics (always stateful, just grab current values.) + self.results[1:] = batch_outs[1:] - Returns: - (Iterator, steps_per_epoch). + def finalize(self): + self.results[0] /= self.num_samples_or_steps - """ - if isinstance(x, iterator_ops.EagerIterator): - return x, steps_per_epoch - if not _nested_any(sample_weights, lambda x: x is None): - data = (x, y, sample_weights) - elif not _nested_any(y, lambda x: x is None): - data = (x, y) - else: - # always wrap in a tuple, so we know y, sample_weights weren't set - # even when x has multiple elements - data = (x,) - - data = _convert_lists_to_tuples(data) - if steps_per_epoch is None and batch_size is not None: - num_samples = _get_batch_axis_size(data) - steps_per_epoch = int(math.ceil(num_samples / batch_size)) - - if steps_per_epoch is None: - alternative_arg_name = ( - 'validation_steps' if is_validation else 'steps_per_epoch') - raise ValueError( - 'Could not determine how to convert EagerTensors into EagerIterator. ' - 'Please provide either `batch_size` or ' - '`%s`.' % alternative_arg_name) +class OutputsAggregator(Aggregator): + """Aggregator that concatenates outputs.""" + + def create(self, batch_outs): + if self.use_steps: + # Cannot pre-allocate the returned NumPy arrays bc + # batch sizes are unknown. Concatenate batches at the end. + for _ in batch_outs: + self.results.append([]) + else: + # Pre-allocate NumPy arrays. + for batch_out in batch_outs: + shape = (self.num_samples_or_steps,) + batch_out.shape[1:] + self.results.append(np.zeros(shape, dtype=batch_out.dtype)) + + def aggregate(self, batch_outs, batch_start=None, batch_end=None): + if self.use_steps: + for i, batch_out in enumerate(batch_outs): + self.results[i].append(batch_out) + else: + for i, batch_out in enumerate(batch_outs): + self.results[i][batch_start:batch_end] = batch_out - # TODO(omalleyt) for NumPy arrays in graph mode - # placeholder ops should be used - # this is only ideal for eager mode - dataset = dataset_ops.Dataset.from_tensor_slices(data) + def finalize(self): + if self.use_steps: + self.results = [np.concatenate(result, axis=0) for result in self.results] - if batch_size is not None: - dataset = dataset.batch(batch_size) - if shuffle: - dataset = dataset.shuffle(buffer_size=10000) - dataset = dataset.repeat(epochs) - iterator = dataset.make_one_shot_iterator() - return iterator, steps_per_epoch +def make_logs(model, outputs, mode, prefix=''): + """Computes logs for sending to `on_batch_end` methods.""" + logs = {} + # TODO(omalleyt): handle outputs in prediction when Callback + # hooks are ready. + if mode in ['train', 'test']: + if hasattr(model, 'metrics_names'): + for label, output in zip(model.metrics_names, outputs): + logs[prefix + label] = output + return logs + + +def get_progbar(model, count_mode): + """Get Progbar.""" + stateful_metric_names = None + if hasattr(model, 'metrics_names'): + stateful_metric_names = model.metrics_names[1:] # Exclude `loss` + return cbks.ProgbarLogger(count_mode, stateful_metrics=stateful_metric_names) + + +def slice_arrays(arrays, indices, contiguous=True): + """Slices batches out of provided arrays (workaround for eager tensors). + + Unfortunately eager tensors don't have the same slicing behavior as + Numpy arrays (they follow the same slicing behavior as symbolic TF tensors), + hence we cannot use `generic_utils.slice_arrays` directly + and we have to implement this workaround based on `concat`. This has a + performance cost. + + Arguments: + arrays: Single array or list of arrays. + indices: List of indices in the array that should be included in the output + batch. + contiguous: Boolean flag indicating whether the indices are contiguous. + + Returns: + Slice of data (either single array or list of arrays). + """ + converted_to_list = False + if not isinstance(arrays, list): + converted_to_list = True + arrays = [arrays] + if any(tensor_util.is_tensor(x) for x in arrays): + if not contiguous: + entries = [[x[i:i + 1] for i in indices] for x in arrays] + slices = [array_ops.concat(x, axis=0) for x in entries] + else: + slices = [x[indices[0]:indices[-1] + 1] for x in arrays] + else: + slices = generic_utils.slice_arrays(arrays, indices) + + if converted_to_list: + slices = slices[0] + return slices def check_num_samples(ins, @@ -224,9 +237,9 @@ def standardize_single_array(x): return None if x.shape is not None and len(x.shape) == 1: if tensor_util.is_tensor(x): - return array_ops.expand_dims(x, axis=1) + x = array_ops.expand_dims(x, axis=1) else: - return np.expand_dims(x, 1) + x = np.expand_dims(x, 1) return x @@ -629,15 +642,14 @@ def weighted_masked_objective(fn): weights = mask else: # Update dimensions of weights to match with mask if possible. - mask, _, weights = metrics_module.squeeze_or_expand_dimensions( - mask, None, weights) + mask, _, weights = squeeze_or_expand_dimensions(mask, None, weights) weights *= mask # Apply sample weighting. if weights is not None: # Update dimensions of weights to match with values if possible. - score_array, _, weights = metrics_module.squeeze_or_expand_dimensions( + score_array, _, weights = squeeze_or_expand_dimensions( score_array, None, weights) try: # Broadcast weights if possible. @@ -651,7 +663,7 @@ def weighted_masked_objective(fn): score_array = math_ops.multiply(score_array, weights) score_array = math_ops.reduce_sum(score_array) weights = math_ops.reduce_sum(weights) - score_array = metrics_module.safe_div(score_array, weights) + score_array = math_ops.div_no_nan(score_array, weights) return K.mean(score_array) return weighted @@ -835,12 +847,22 @@ def call_metric_function(metric_fn, y_true, y_pred, weights=None, mask=None): return metric_fn(y_true, y_pred, sample_weight=mask) # Update dimensions of weights to match with mask. - mask, _, weights = metrics_module.squeeze_or_expand_dimensions( - mask, None, weights) + mask, _, weights = squeeze_or_expand_dimensions(mask, None, weights) weights *= mask return metric_fn(y_true, y_pred, sample_weight=weights) +def get_loss_function(loss): + """Returns the loss function corresponding to the given loss input.""" + if loss is None or isinstance(loss, losses.Loss): + return loss + + # TODO(psv): After we have added all V2 losses, update this function. + if loss in ['mse', 'MSE', 'mean_squared_error']: + return losses.MeanSquaredError() + return losses.get(loss) + + def validate_iterator_input(x, y, sample_weight, validation_split=None): """Validates user input arguments when a dataset iterator is passed. @@ -1053,9 +1075,11 @@ class ModelInputs(object): self._inputs = inputs self._is_dict = isinstance(self._inputs, dict) self._is_single_input = not isinstance(self._inputs, (list, tuple, dict)) + self._flattened_inputs = [] self._input_names = [] - if isinstance(self._inputs, dict): + + if self._is_dict: for k in sorted(self._inputs.keys()): self._flattened_inputs.append(self._inputs[k]) self._input_names.append(k) @@ -1064,7 +1088,6 @@ class ModelInputs(object): self._input_names = [ 'input_%d' % (i + 1) for i in range(len(self._flattened_inputs)) ] - assert len(self._input_names) == len(self._flattened_inputs) def get_input_names(self): """Returns keys to name inputs by. @@ -1074,56 +1097,29 @@ class ModelInputs(object): """ return self._input_names - def _get(self, return_single_as_list=False): - """Returns provided inputs, potentially transformed. - - Inputs are returned in the same format they were provided i.e. lists - are returned as lists, single entries as single entries (unless - `return_single_as_list` is true), dictionaries as dictionaries. - - Args: - return_single_as_list: Returns a list of size 1 for single entry case. - """ - if self._is_dict: - return dict(zip(self._input_names, self._flattened_inputs)) - if self._is_single_input and not return_single_as_list: - return self._flattened_inputs[0] - return self._flattened_inputs - - def get_input_values(self): - """Returns input values passed in.""" - if context.executing_eagerly(): - for i in range(len(self._flattened_inputs)): - v = self._flattened_inputs[i] - if tensor_util.is_tensor(v): - v = cast_single_tensor(v) - else: - v = ops.convert_to_tensor(v, dtype=K.floatx()) - self._flattened_inputs[i] = v - return self._get(return_single_as_list=False) - def get_symbolic_inputs(self, return_single_as_list=False): """Returns inputs to be set as self.inputs for a model.""" for i in range(len(self._flattened_inputs)): k = self._input_names[i] v = self._flattened_inputs[i] - if context.executing_eagerly(): - v = K.placeholder((None,) + tuple(v.shape[1:]), name=k) - else: - if isinstance(v, list): - v = np.asarray(v) - if v.ndim == 1: - v = np.expand_dims(v, 1) - if isinstance(v, (np.ndarray)): - # We fix the placeholder shape except the batch size. - # This is suboptimal, but it is the best we can do with the info - # we have. The user should call `model._set_inputs(placeholders)` - # to specify custom placeholders if the need arises. - shape = (None,) + v.shape[1:] - v = K.placeholder(shape=shape, name=k) + if isinstance(v, (list, float, int)): + v = np.asarray(v) + if v.ndim == 1: + v = np.expand_dims(v, 1) + if isinstance(v, (np.ndarray, ops.EagerTensor)): + # We fix the placeholder shape except the batch size. + # This is suboptimal, but it is the best we can do with the info + # we have. The user should call `model._set_inputs(placeholders)` + # to specify custom placeholders if the need arises. + shape = (None,) + tuple(v.shape[1:]) + v = K.placeholder(shape=shape, name=k) self._flattened_inputs[i] = v - return self._get(return_single_as_list) + if self._is_dict: + return dict(zip(self._input_names, self._flattened_inputs)) + if self._is_single_input and not return_single_as_list: + return self._flattened_inputs[0] + return self._flattened_inputs def as_dict(self): """An iterable over a dictionary version of inputs.""" @@ -1133,3 +1129,54 @@ class ModelInputs(object): def as_list(self): """Returning the inputs as a list.""" return self._flattened_inputs + + +# Allow use of methods not exposed to the user. +# pylint: disable=protected-access +def get_input_shape_and_dtype(layer): + """Retrieves input shape and input dtype of layer if applicable. + + Args: + layer: Layer (or model) instance. + + Returns: + Tuple (input_shape, input_dtype). Both could be None if the layer + does not have a defined input shape. + + Raises: + ValueError: in case an empty Sequential or Graph Network is passed. + """ + + def _is_graph_model(layer): + return ((hasattr(layer, '_is_graph_network') and layer._is_graph_network) or + layer.__class__.__name__ == 'Sequential') + + # In case of nested models: recover the first layer + # of the deepest model to infer input shape and dtype. + # Subclassed Models may not have been built so can't be checked. + while _is_graph_model(layer): + if not layer.layers: + raise ValueError('An empty Model cannot be used as a Layer.') + layer = layer.layers[0] + + if hasattr(layer, '_batch_input_shape'): + return layer._batch_input_shape, layer.dtype + return None, None + + +# pylint: enable=protected-access + + +def get_static_batch_size(layer): + """Gets the static batch size of a Layer. + + Arguments: + layer: a `Layer` instance. + + Returns: + The static batch size of a Layer. + """ + batch_input_shape, _ = get_input_shape_and_dtype(layer) + if batch_input_shape is not None: + return tensor_shape.as_dimension(batch_input_shape[0]).value + return None diff --git a/tensorflow/python/keras/engine/training_utils_test.py b/tensorflow/python/keras/engine/training_utils_test.py index 7b217cf373..44ea23998f 100644 --- a/tensorflow/python/keras/engine/training_utils_test.py +++ b/tensorflow/python/keras/engine/training_utils_test.py @@ -21,185 +21,39 @@ from __future__ import print_function import numpy as np from tensorflow.python.eager import context -from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util -from tensorflow.python.framework import test_util from tensorflow.python.keras.engine import training_utils from tensorflow.python.keras.utils import tf_utils from tensorflow.python.platform import test -class TrainingUtilTest(test.TestCase): - - @test_util.run_in_graph_and_eager_modes - def test_convert_to_iterator_single_numpy(self): - batch_size = 2 - a = np.ones([10, 10]) - iterator, steps_per_epoch = training_utils.convert_to_iterator( - x=a, batch_size=batch_size) - self.assertEquals(steps_per_epoch, 5) - - expected_batch = a[:batch_size, :] - actual_batch, = iterator.get_next() - self.assertAllEqual(expected_batch, actual_batch) - - @test_util.run_in_graph_and_eager_modes - def test_convert_to_iterator_single_tensor(self): - batch_size = 2 - a = ops.convert_to_tensor(np.ones([10, 10])) - iterator, steps_per_epoch = training_utils.convert_to_iterator( - x=a, batch_size=batch_size) - self.assertEquals(steps_per_epoch, 5) - - expected_batch = a[:batch_size, :] - actual_batch, = iterator.get_next() - self.assertAllEqual(expected_batch, actual_batch) - - @test_util.run_in_graph_and_eager_modes - def test_convert_to_iterator_y(self): - batch_size = 2 - a = np.ones([10, 100]) - b = np.ones([10, 10]) - iterator, steps_per_epoch = training_utils.convert_to_iterator( - x=a, y=b, batch_size=batch_size) - self.assertEquals(steps_per_epoch, 5) - - expected_x = a[:batch_size, :] - expected_y = b[:batch_size, :] - actual_x, actual_y = iterator.get_next() - self.assertAllEqual(expected_x, actual_x) - self.assertAllEqual(expected_y, actual_y) - - @test_util.run_in_graph_and_eager_modes - def test_convert_to_iterator_sample_weights(self): - batch_size = 2 - a = ops.convert_to_tensor(np.ones([10, 100])) - b = ops.convert_to_tensor(np.ones([10, 10])) - sw = ops.convert_to_tensor(np.ones([10])) - iterator, steps_per_epoch = training_utils.convert_to_iterator( - x=a, y=b, sample_weights=sw, batch_size=batch_size) - self.assertEquals(steps_per_epoch, 5) - - expected_x = a[:batch_size, :] - expected_y = b[:batch_size, :] - expected_sw = sw[:batch_size] - actual_x, actual_y, actual_sw = iterator.get_next() - self.assertAllEqual(expected_x, actual_x) - self.assertAllEqual(expected_y, actual_y) - self.assertAllEqual(expected_sw, actual_sw) - - @test_util.run_in_graph_and_eager_modes - def test_convert_to_iterator_nested(self): - batch_size = 2 - x = {'1': np.ones([10, 100]), '2': [np.zeros([10, 10]), np.ones([10, 20])]} - iterator, steps_per_epoch = training_utils.convert_to_iterator( - x=x, batch_size=batch_size) - self.assertEquals(steps_per_epoch, 5) - - expected_x1 = x['1'][:batch_size, :] - expected_x2_0 = x['2'][0][:batch_size, :] - expected_x2_1 = x['2'][1][:batch_size, :] - - actual_x, = iterator.get_next() - actual_x1 = actual_x['1'][:batch_size, :] - actual_x2_0 = actual_x['2'][0][:batch_size, :] - actual_x2_1 = actual_x['2'][1][:batch_size, :] - - self.assertAllEqual(expected_x1, actual_x1) - self.assertAllEqual(expected_x2_0, actual_x2_0) - self.assertAllEqual(expected_x2_1, actual_x2_1) - - @test_util.run_in_graph_and_eager_modes - def test_convert_to_iterator_epochs(self): - batch_size = 2 - a = np.ones([10, 10]) - iterator, steps_per_epoch = training_utils.convert_to_iterator( - x=a, batch_size=batch_size, epochs=2) - self.assertEquals(steps_per_epoch, 5) - - expected_batch = a[:batch_size, :] - # loop through one whole epoch - for _ in range(6): - actual_batch, = iterator.get_next() - self.assertAllEqual(expected_batch, actual_batch) - - @test_util.run_in_graph_and_eager_modes - def test_convert_to_iterator_insufficient_info(self): - # with batch_size and steps_per_epoch not set - with self.assertRaises(ValueError): - a = np.ones([10, 10]) - _ = training_utils.convert_to_iterator(x=a) - - def test_nested_all(self): - nested_data = {'a': True, 'b': [True, True, (False, True)]} - all_true = training_utils._nested_all(nested_data, lambda x: x) - self.assertEquals(all_true, False) - - nested_data = {'a': True, 'b': [True, True, (True, True)]} - all_true = training_utils._nested_all(nested_data, lambda x: x) - self.assertEquals(all_true, True) - - def test_nested_any(self): - nested_data = [False, {'a': False, 'b': (False, True)}] - any_true = training_utils._nested_any(nested_data, lambda x: x) - self.assertEquals(any_true, True) - - nested_data = [False, {'a': False, 'b': (False, False)}] - any_true = training_utils._nested_any(nested_data, lambda x: x) - self.assertEquals(any_true, False) - - def test_check_array_lengths(self): - training_utils.check_array_lengths(None, None, None) - a_np = np.random.random((4, 3, 3)) - training_utils.check_array_lengths(a_np, a_np, a_np) - training_utils.check_array_lengths( - [a_np, a_np], [a_np, a_np], [a_np, a_np]) - training_utils.check_array_lengths([None], [None], [None]) - - b_np = np.random.random((3, 4)) - with self.assertRaises(ValueError): - training_utils.check_array_lengths([a_np], [b_np], None) - - class ModelInputsTest(test.TestCase): def test_single_thing(self): a = np.ones(10) model_inputs = training_utils.ModelInputs(a) - self.assertEquals(['input_1'], model_inputs.get_input_names()) - vals = model_inputs.get_input_values() - self.assertAllEqual(np.ones(10), vals) - self.assertFalse(tensor_util.is_tensor(vals)) + self.assertEqual(['input_1'], model_inputs.get_input_names()) vals = model_inputs.get_symbolic_inputs() self.assertTrue(tensor_util.is_tensor(vals)) vals = model_inputs.get_symbolic_inputs(return_single_as_list=True) - self.assertEquals(1, len(vals)) + self.assertEqual(1, len(vals)) self.assertTrue(tensor_util.is_tensor(vals[0])) def test_single_thing_eager(self): with context.eager_mode(): a = np.ones(10) model_inputs = training_utils.ModelInputs(a) - self.assertEquals(['input_1'], model_inputs.get_input_names()) - val = model_inputs.get_input_values() - self.assertAllEqual(np.ones(10), val) - self.assertTrue(tensor_util.is_tensor(val)) + self.assertEqual(['input_1'], model_inputs.get_input_names()) val = model_inputs.get_symbolic_inputs() self.assertTrue(tf_utils.is_symbolic_tensor(val)) vals = model_inputs.get_symbolic_inputs(return_single_as_list=True) - self.assertEquals(1, len(vals)) + self.assertEqual(1, len(vals)) self.assertTrue(tf_utils.is_symbolic_tensor(vals[0])) def test_list(self): a = [np.ones(10), np.ones(20)] model_inputs = training_utils.ModelInputs(a) - self.assertEquals(['input_1', 'input_2'], model_inputs.get_input_names()) - vals = model_inputs.get_input_values() - self.assertEqual(2, len(vals)) - self.assertAllEqual(np.ones(10), vals[0]) - self.assertAllEqual(np.ones(20), vals[1]) - self.assertFalse(tensor_util.is_tensor(vals[0])) - self.assertFalse(tensor_util.is_tensor(vals[1])) + self.assertEqual(['input_1', 'input_2'], model_inputs.get_input_names()) vals = model_inputs.get_symbolic_inputs() self.assertTrue(tensor_util.is_tensor(vals[0])) self.assertTrue(tensor_util.is_tensor(vals[1])) @@ -208,13 +62,7 @@ class ModelInputsTest(test.TestCase): with context.eager_mode(): a = [np.ones(10), np.ones(20)] model_inputs = training_utils.ModelInputs(a) - self.assertEquals(['input_1', 'input_2'], model_inputs.get_input_names()) - vals = model_inputs.get_input_values() - self.assertEqual(2, len(vals)) - self.assertAllEqual(np.ones(10), vals[0]) - self.assertAllEqual(np.ones(20), vals[1]) - self.assertTrue(tensor_util.is_tensor(vals[0])) - self.assertTrue(tensor_util.is_tensor(vals[1])) + self.assertEqual(['input_1', 'input_2'], model_inputs.get_input_names()) vals = model_inputs.get_symbolic_inputs() self.assertTrue(tf_utils.is_symbolic_tensor(vals[0])) self.assertTrue(tf_utils.is_symbolic_tensor(vals[1])) @@ -222,12 +70,7 @@ class ModelInputsTest(test.TestCase): def test_dict(self): a = {'b': np.ones(10), 'a': np.ones(20)} model_inputs = training_utils.ModelInputs(a) - self.assertEquals(['a', 'b'], model_inputs.get_input_names()) - vals = model_inputs.get_input_values() - self.assertAllEqual(np.ones(20), vals['a']) - self.assertAllEqual(np.ones(10), vals['b']) - self.assertFalse(tensor_util.is_tensor(vals['a'])) - self.assertFalse(tensor_util.is_tensor(vals['b'])) + self.assertEqual(['a', 'b'], model_inputs.get_input_names()) vals = model_inputs.get_symbolic_inputs() self.assertTrue(tensor_util.is_tensor(vals['a'])) self.assertTrue(tensor_util.is_tensor(vals['b'])) @@ -236,12 +79,7 @@ class ModelInputsTest(test.TestCase): with context.eager_mode(): a = {'b': np.ones(10), 'a': np.ones(20)} model_inputs = training_utils.ModelInputs(a) - self.assertEquals(['a', 'b'], model_inputs.get_input_names()) - vals = model_inputs.get_input_values() - self.assertAllEqual(np.ones(20), vals['a']) - self.assertAllEqual(np.ones(10), vals['b']) - self.assertTrue(tensor_util.is_tensor(vals['a'])) - self.assertTrue(tensor_util.is_tensor(vals['b'])) + self.assertEqual(['a', 'b'], model_inputs.get_input_names()) vals = model_inputs.get_symbolic_inputs() self.assertTrue(tf_utils.is_symbolic_tensor(vals['a'])) self.assertTrue(tf_utils.is_symbolic_tensor(vals['b'])) diff --git a/tensorflow/python/keras/estimator/__init__.py b/tensorflow/python/keras/estimator/__init__.py index b244beb5b5..dcd0600897 100644 --- a/tensorflow/python/keras/estimator/__init__.py +++ b/tensorflow/python/keras/estimator/__init__.py @@ -24,23 +24,54 @@ from tensorflow.python.util.tf_export import tf_export # As long as you depend //third_party/py/tensorflow:tensorflow target # everything will work as normal. -try: - from tensorflow.python.estimator import keras as keras_lib # pylint: disable=g-import-not-at-top - model_to_estimator = tf_export('keras.estimator.model_to_estimator')( - keras_lib.model_to_estimator) -except Exception: # pylint: disable=broad-except - - # pylint: disable=unused-argument - def stub_model_to_estimator(keras_model=None, - keras_model_path=None, - custom_objects=None, - model_dir=None, - config=None): + +# LINT.IfChange +@tf_export('keras.estimator.model_to_estimator') +def model_to_estimator( + keras_model=None, + keras_model_path=None, + custom_objects=None, + model_dir=None, + config=None): + """Constructs an `Estimator` instance from given keras model. + + For usage example, please see: + [Creating estimators from Keras + Models](https://tensorflow.org/guide/estimators#model_to_estimator). + + Args: + keras_model: A compiled Keras model object. This argument is mutually + exclusive with `keras_model_path`. + keras_model_path: Path to a compiled Keras model saved on disk, in HDF5 + format, which can be generated with the `save()` method of a Keras model. + This argument is mutually exclusive with `keras_model`. + custom_objects: Dictionary for custom objects. + model_dir: Directory to save `Estimator` model parameters, graph, summary + files for TensorBoard, etc. + config: `RunConfig` to config `Estimator`. + + Returns: + An Estimator from given keras model. + + Raises: + ValueError: if neither keras_model nor keras_model_path was given. + ValueError: if both keras_model and keras_model_path was given. + ValueError: if the keras_model_path is a GCS URI. + ValueError: if keras_model has not been compiled. + """ + try: + from tensorflow_estimator.python.estimator import keras as keras_lib # pylint: disable=g-import-not-at-top + except ImportError: raise NotImplementedError( 'tf.keras.estimator.model_to_estimator function not available in your ' 'installation.') - # pylint: enable=unused-argument + return keras_lib.model_to_estimator( + keras_model=keras_model, + keras_model_path=keras_model_path, + custom_objects=custom_objects, + model_dir=model_dir, + config=config) + +# LINT.ThenChange(//third_party/tensorflow_estimator/python/estimator/keras.py) - model_to_estimator = tf_export('keras.estimator.model_to_estimator')( - stub_model_to_estimator) diff --git a/tensorflow/python/keras/initializers_test.py b/tensorflow/python/keras/initializers_test.py index 2b758a98f3..4f91bea1e3 100644 --- a/tensorflow/python/keras/initializers_test.py +++ b/tensorflow/python/keras/initializers_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python import keras from tensorflow.python.ops import init_ops +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -38,6 +39,7 @@ class KerasInitializersTest(test.TestCase): output_2 = keras.backend.get_value(variable) self.assertAllClose(output, output_2, atol=1e-4) + @test_util.run_deprecated_v1 def test_uniform(self): tensor_shape = (9, 6, 7) with self.cached_session(): @@ -47,6 +49,7 @@ class KerasInitializersTest(test.TestCase): tensor_shape, target_mean=0., target_max=1, target_min=-1) + @test_util.run_deprecated_v1 def test_normal(self): tensor_shape = (8, 12, 99) with self.cached_session(): @@ -54,6 +57,7 @@ class KerasInitializersTest(test.TestCase): tensor_shape, target_mean=0., target_std=1) + @test_util.run_deprecated_v1 def test_truncated_normal(self): tensor_shape = (12, 99, 7) with self.cached_session(): @@ -69,6 +73,7 @@ class KerasInitializersTest(test.TestCase): self._runner(keras.initializers.Constant(2), tensor_shape, target_mean=2, target_max=2, target_min=2) + @test_util.run_deprecated_v1 def test_lecun_uniform(self): tensor_shape = (5, 6, 4, 2) with self.cached_session(): @@ -77,6 +82,7 @@ class KerasInitializersTest(test.TestCase): self._runner(keras.initializers.lecun_uniform(seed=123), tensor_shape, target_mean=0., target_std=std) + @test_util.run_deprecated_v1 def test_glorot_uniform(self): tensor_shape = (5, 6, 4, 2) with self.cached_session(): @@ -85,6 +91,7 @@ class KerasInitializersTest(test.TestCase): self._runner(keras.initializers.glorot_uniform(seed=123), tensor_shape, target_mean=0., target_std=std) + @test_util.run_deprecated_v1 def test_he_uniform(self): tensor_shape = (5, 6, 4, 2) with self.cached_session(): @@ -93,6 +100,7 @@ class KerasInitializersTest(test.TestCase): self._runner(keras.initializers.he_uniform(seed=123), tensor_shape, target_mean=0., target_std=std) + @test_util.run_deprecated_v1 def test_lecun_normal(self): tensor_shape = (5, 6, 4, 2) with self.cached_session(): @@ -101,6 +109,7 @@ class KerasInitializersTest(test.TestCase): self._runner(keras.initializers.lecun_normal(seed=123), tensor_shape, target_mean=0., target_std=std) + @test_util.run_deprecated_v1 def test_glorot_normal(self): tensor_shape = (5, 6, 4, 2) with self.cached_session(): @@ -109,6 +118,7 @@ class KerasInitializersTest(test.TestCase): self._runner(keras.initializers.glorot_normal(seed=123), tensor_shape, target_mean=0., target_std=std) + @test_util.run_deprecated_v1 def test_he_normal(self): tensor_shape = (5, 6, 4, 2) with self.cached_session(): @@ -117,6 +127,7 @@ class KerasInitializersTest(test.TestCase): self._runner(keras.initializers.he_normal(seed=123), tensor_shape, target_mean=0., target_std=std) + @test_util.run_deprecated_v1 def test_orthogonal(self): tensor_shape = (20, 20) with self.cached_session(): diff --git a/tensorflow/python/keras/integration_test.py b/tensorflow/python/keras/integration_test.py index 3c0f73b1c3..23f5438505 100644 --- a/tensorflow/python/keras/integration_test.py +++ b/tensorflow/python/keras/integration_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python import keras from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.keras import testing_utils from tensorflow.python.layers import core as tf_core_layers from tensorflow.python.ops import nn @@ -34,6 +35,7 @@ class KerasIntegrationTest(test.TestCase): def test_version(self): self.assertTrue(keras.__version__.endswith('-tf')) + @test_util.run_deprecated_v1 def test_vector_classification_sequential(self): with self.cached_session(): np.random.seed(1337) @@ -59,6 +61,7 @@ class KerasIntegrationTest(test.TestCase): verbose=2) self.assertGreater(history.history['val_acc'][-1], 0.7) + @test_util.run_deprecated_v1 def test_vector_classification_functional(self): with self.cached_session(): np.random.seed(1337) @@ -83,6 +86,7 @@ class KerasIntegrationTest(test.TestCase): verbose=2) self.assertGreater(history.history['val_acc'][-1], 0.7) + @test_util.run_deprecated_v1 def test_temporal_classification_sequential(self): with self.cached_session(): np.random.seed(1337) @@ -105,6 +109,7 @@ class KerasIntegrationTest(test.TestCase): verbose=2) self.assertGreater(history.history['val_acc'][-1], 0.7) + @test_util.run_deprecated_v1 def test_temporal_classification_sequential_tf_rnn(self): with self.cached_session(): np.random.seed(1337) @@ -163,6 +168,7 @@ class KerasIntegrationTest(test.TestCase): verbose=2) self.assertGreater(history.history['val_acc'][-1], 0.7) + @test_util.run_deprecated_v1 def test_video_classification_functional(self): with self.cached_session(): np.random.seed(1337) @@ -191,6 +197,7 @@ class KerasIntegrationTest(test.TestCase): verbose=2) self.assertGreater(history.history['val_acc'][-1], 0.7) + @test_util.run_deprecated_v1 def test_vector_classification_shared_sequential(self): # Test that Sequential models that feature internal updates # and internal losses can be shared. @@ -225,6 +232,7 @@ class KerasIntegrationTest(test.TestCase): verbose=2) self.assertGreater(history.history['val_acc'][-1], 0.7) + @test_util.run_deprecated_v1 def test_vector_classification_shared_model(self): # Test that functional models that feature internal updates # and internal losses can be shared. @@ -312,6 +320,15 @@ class KerasIntegrationTest(test.TestCase): verbose=0) self.assertGreater(history.history['val_acc'][-1], 0.7) + def test_regularizers_with_get_variable(self): + # Test case for GitHub issue 22470. + with self.cached_session(): + v = variable_scope.get_variable( + "v", + shape=[4, 4], + initializer=keras.initializers.glorot_uniform(), + regularizer=keras.regularizers.l2(0.)) + if __name__ == '__main__': test.main() diff --git a/tensorflow/python/keras/layers/__init__.py b/tensorflow/python/keras/layers/__init__.py index 7268040b02..49990b6bf4 100644 --- a/tensorflow/python/keras/layers/__init__.py +++ b/tensorflow/python/keras/layers/__init__.py @@ -22,7 +22,7 @@ from __future__ import print_function # pylint: disable=g-bad-import-order from tensorflow.python.keras.engine.input_layer import Input from tensorflow.python.keras.engine.input_layer import InputLayer -from tensorflow.python.keras.engine.base_layer import InputSpec +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.engine.base_layer import Layer # Advanced activations. diff --git a/tensorflow/python/keras/layers/advanced_activations.py b/tensorflow/python/keras/layers/advanced_activations.py index b0dffced3e..35ac7830b2 100644 --- a/tensorflow/python/keras/layers/advanced_activations.py +++ b/tensorflow/python/keras/layers/advanced_activations.py @@ -22,8 +22,8 @@ from tensorflow.python.keras import backend as K from tensorflow.python.keras import constraints from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.utils import tf_utils from tensorflow.python.ops import math_ops from tensorflow.python.util.tf_export import tf_export @@ -54,7 +54,6 @@ class LeakyReLU(Layer): super(LeakyReLU, self).__init__(**kwargs) self.supports_masking = True self.alpha = K.cast_to_floatx(alpha) - self._can_use_graph_functions = True def call(self, inputs): return K.relu(inputs, alpha=self.alpha) @@ -118,7 +117,6 @@ class PReLU(Layer): self.shared_axes = [shared_axes] else: self.shared_axes = list(shared_axes) - self._can_use_graph_functions = True @tf_utils.shape_type_conversion def build(self, input_shape): @@ -193,7 +191,6 @@ class ELU(Layer): super(ELU, self).__init__(**kwargs) self.supports_masking = True self.alpha = K.cast_to_floatx(alpha) - self._can_use_graph_functions = True def call(self, inputs): return K.elu(inputs, self.alpha) @@ -233,7 +230,6 @@ class ThresholdedReLU(Layer): super(ThresholdedReLU, self).__init__(**kwargs) self.supports_masking = True self.theta = K.cast_to_floatx(theta) - self._can_use_graph_functions = True def call(self, inputs, mask=None): return inputs * math_ops.cast( @@ -269,7 +265,6 @@ class Softmax(Layer): super(Softmax, self).__init__(**kwargs) self.supports_masking = True self.axis = axis - self._can_use_graph_functions = True def call(self, inputs): return K.softmax(inputs, axis=self.axis) @@ -324,7 +319,6 @@ class ReLU(Layer): self.max_value = max_value self.negative_slope = K.cast_to_floatx(negative_slope) self.threshold = K.cast_to_floatx(threshold) - self._can_use_graph_functions = True def call(self, inputs): # alpha is used for leaky relu slope in activations instead of diff --git a/tensorflow/python/keras/layers/convolutional.py b/tensorflow/python/keras/layers/convolutional.py index 0671a5a36d..6564d6e8fd 100644 --- a/tensorflow/python/keras/layers/convolutional.py +++ b/tensorflow/python/keras/layers/convolutional.py @@ -26,8 +26,8 @@ from tensorflow.python.keras import backend from tensorflow.python.keras import constraints from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer +from tensorflow.python.keras.engine.input_spec import InputSpec # imports for backwards namespace compatibility # pylint: disable=unused-import from tensorflow.python.keras.layers.pooling import AveragePooling1D @@ -120,7 +120,6 @@ class Conv(Layer): name=name, activity_regularizer=regularizers.get(activity_regularizer), **kwargs) - self._can_use_graph_functions = True self.rank = rank self.filters = filters self.kernel_size = conv_utils.normalize_tuple( @@ -1916,7 +1915,6 @@ class UpSampling1D(Layer): super(UpSampling1D, self).__init__(**kwargs) self.size = int(size) self.input_spec = InputSpec(ndim=3) - self._can_use_graph_functions = True def compute_output_shape(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape).as_list() @@ -1983,7 +1981,6 @@ class UpSampling2D(Layer): 'or `"bilinear"`.') self.interpolation = interpolation self.input_spec = InputSpec(ndim=4) - self._can_use_graph_functions = True def compute_output_shape(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape).as_list() @@ -2054,7 +2051,6 @@ class UpSampling3D(Layer): self.size = conv_utils.normalize_tuple(size, 3, 'size') self.input_spec = InputSpec(ndim=5) super(UpSampling3D, self).__init__(**kwargs) - self._can_use_graph_functions = True def compute_output_shape(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape).as_list() @@ -2109,7 +2105,6 @@ class ZeroPadding1D(Layer): def __init__(self, padding=1, **kwargs): super(ZeroPadding1D, self).__init__(**kwargs) - self._can_use_graph_functions = True self.padding = conv_utils.normalize_tuple(padding, 2, 'padding') self.input_spec = InputSpec(ndim=3) @@ -2175,7 +2170,6 @@ class ZeroPadding2D(Layer): def __init__(self, padding=(1, 1), data_format=None, **kwargs): super(ZeroPadding2D, self).__init__(**kwargs) - self._can_use_graph_functions = True self.data_format = conv_utils.normalize_data_format(data_format) if isinstance(padding, int): self.padding = ((padding, padding), (padding, padding)) @@ -2280,7 +2274,6 @@ class ZeroPadding3D(Layer): def __init__(self, padding=(1, 1, 1), data_format=None, **kwargs): super(ZeroPadding3D, self).__init__(**kwargs) - self._can_use_graph_functions = True self.data_format = conv_utils.normalize_data_format(data_format) if isinstance(padding, int): self.padding = ((padding, padding), (padding, padding), (padding, @@ -2375,7 +2368,6 @@ class Cropping1D(Layer): super(Cropping1D, self).__init__(**kwargs) self.cropping = conv_utils.normalize_tuple(cropping, 2, 'cropping') self.input_spec = InputSpec(ndim=3) - self._can_use_graph_functions = True def compute_output_shape(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape).as_list() @@ -2475,7 +2467,6 @@ class Cropping2D(Layer): '((top_crop, bottom_crop), (left_crop, right_crop)). ' 'Found: ' + str(cropping)) self.input_spec = InputSpec(ndim=4) - self._can_use_graph_functions = True def compute_output_shape(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape).as_list() @@ -2609,7 +2600,6 @@ class Cropping3D(Layer): ' (left_dim3_crop, right_dim2_crop)). ' 'Found: ' + str(cropping)) self.input_spec = InputSpec(ndim=5) - self._can_use_graph_functions = True def compute_output_shape(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape).as_list() diff --git a/tensorflow/python/keras/layers/convolutional_recurrent.py b/tensorflow/python/keras/layers/convolutional_recurrent.py index 100542129b..cf3861da21 100644 --- a/tensorflow/python/keras/layers/convolutional_recurrent.py +++ b/tensorflow/python/keras/layers/convolutional_recurrent.py @@ -26,8 +26,8 @@ from tensorflow.python.keras import backend as K from tensorflow.python.keras import constraints from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.layers.recurrent import _generate_dropout_mask from tensorflow.python.keras.layers.recurrent import _standardize_args from tensorflow.python.keras.layers.recurrent import RNN diff --git a/tensorflow/python/keras/layers/core.py b/tensorflow/python/keras/layers/core.py index e5c37be0aa..56dd70558c 100644 --- a/tensorflow/python/keras/layers/core.py +++ b/tensorflow/python/keras/layers/core.py @@ -34,8 +34,8 @@ from tensorflow.python.keras import backend as K from tensorflow.python.keras import constraints from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.utils import conv_utils from tensorflow.python.keras.utils import generic_utils from tensorflow.python.keras.utils import tf_utils @@ -81,7 +81,6 @@ class Masking(Layer): super(Masking, self).__init__(**kwargs) self.supports_masking = True self.mask_value = mask_value - self._can_use_graph_functions = True def compute_mask(self, inputs, mask=None): return K.any(math_ops.not_equal(inputs, self.mask_value), axis=-1) @@ -125,7 +124,6 @@ class Dropout(Layer): self.noise_shape = noise_shape self.seed = seed self.supports_masking = True - self._can_use_graph_functions = True def _get_noise_shape(self, inputs): # Subclasses of `Dropout` may implement `_get_noise_shape(self, inputs)`, @@ -326,7 +324,6 @@ class Activation(Layer): super(Activation, self).__init__(**kwargs) self.supports_masking = True self.activation = activations.get(activation) - self._can_use_graph_functions = True def call(self, inputs): return self.activation(inputs) @@ -379,7 +376,6 @@ class Reshape(Layer): def __init__(self, target_shape, **kwargs): super(Reshape, self).__init__(**kwargs) self.target_shape = tuple(target_shape) - self._can_use_graph_functions = True def _fix_unknown_dimension(self, input_shape, output_shape): """Find and replace a missing dimension in an output shape. @@ -488,7 +484,6 @@ class Permute(Layer): 'The set of indices in `dims` must be consecutive and start from 1.' % (dims,)) self.input_spec = InputSpec(ndim=len(self.dims) + 1) - self._can_use_graph_functions = True def compute_output_shape(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape).as_list() @@ -540,7 +535,6 @@ class Flatten(Layer): super(Flatten, self).__init__(**kwargs) self.data_format = conv_utils.normalize_data_format(data_format) self.input_spec = InputSpec(min_ndim=2) - self._can_use_graph_functions = True def call(self, inputs): if self.data_format == 'channels_first': @@ -600,7 +594,6 @@ class RepeatVector(Layer): super(RepeatVector, self).__init__(**kwargs) self.n = n self.input_spec = InputSpec(ndim=2) - self._can_use_graph_functions = True def compute_output_shape(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape).as_list() @@ -929,7 +922,6 @@ class Dense(Layer): self.supports_masking = True self.input_spec = InputSpec(min_ndim=2) - self._can_use_graph_functions = True def build(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape) @@ -1029,7 +1021,6 @@ class ActivityRegularization(Layer): self.supports_masking = True self.l1 = l1 self.l2 = l2 - self._can_use_graph_functions = True def compute_output_shape(self, input_shape): return input_shape diff --git a/tensorflow/python/keras/layers/cudnn_recurrent.py b/tensorflow/python/keras/layers/cudnn_recurrent.py index beacdf2515..16692753af 100644 --- a/tensorflow/python/keras/layers/cudnn_recurrent.py +++ b/tensorflow/python/keras/layers/cudnn_recurrent.py @@ -25,7 +25,8 @@ from tensorflow.python.keras import backend as K from tensorflow.python.keras import constraints from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers -from tensorflow.python.keras.engine.base_layer import InputSpec +from tensorflow.python.keras.engine.input_spec import InputSpec +from tensorflow.python.keras.layers import recurrent from tensorflow.python.keras.layers.recurrent import RNN from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_cudnn_rnn_ops @@ -80,11 +81,6 @@ class _CuDNNRNN(RNN): self._num_inputs = None self._vector_shape = constant_op.constant([-1]) - def _canonical_to_params(self, weights, biases): - weights = [array_ops.reshape(x, self._vector_shape) for x in weights] - biases = [array_ops.reshape(x, self._vector_shape) for x in biases] - return array_ops.concat(weights + biases, axis=0) - def call(self, inputs, mask=None, training=None, initial_state=None): if isinstance(mask, list): mask = mask[0] @@ -279,7 +275,7 @@ class CuDNNGRU(_CuDNNRNN): input_h = initial_state[0] input_h = array_ops.expand_dims(input_h, axis=0) - params = self._canonical_to_params( + params = recurrent._canonical_to_params( # pylint: disable=protected-access weights=[ self.kernel[:, self.units:self.units * 2], self.kernel[:, :self.units], @@ -296,7 +292,7 @@ class CuDNNGRU(_CuDNNRNN): self.bias[self.units * 3:self.units * 4], self.bias[self.units * 5:], ], - ) + shape=self._vector_shape) outputs, h, _, _ = gen_cudnn_rnn_ops.cudnn_rnn( inputs, @@ -474,7 +470,7 @@ class CuDNNLSTM(_CuDNNRNN): input_h = array_ops.expand_dims(input_h, axis=0) input_c = array_ops.expand_dims(input_c, axis=0) - params = self._canonical_to_params( + params = recurrent._canonical_to_params( # pylint: disable=protected-access weights=[ self.kernel[:, :self.units], self.kernel[:, self.units:self.units * 2], @@ -495,7 +491,7 @@ class CuDNNLSTM(_CuDNNRNN): self.bias[self.units * 6:self.units * 7], self.bias[self.units * 7:], ], - ) + shape=self._vector_shape) outputs, h, c, _ = gen_cudnn_rnn_ops.cudnn_rnn( inputs, diff --git a/tensorflow/python/keras/layers/embeddings.py b/tensorflow/python/keras/layers/embeddings.py index 5d805ea684..e8a8575705 100644 --- a/tensorflow/python/keras/layers/embeddings.py +++ b/tensorflow/python/keras/layers/embeddings.py @@ -45,11 +45,11 @@ class Embedding(Layer): model = Sequential() model.add(Embedding(1000, 64, input_length=10)) # the model will take as input an integer matrix of size (batch, - input_length). + # input_length). # the largest integer (i.e. word index) in the input should be no larger - than 999 (vocabulary size). + # than 999 (vocabulary size). # now model.output_shape == (None, 10, 64), where None is the batch - dimension. + # dimension. input_array = np.random.randint(1000, size=(32, 10)) @@ -116,7 +116,6 @@ class Embedding(Layer): self.mask_zero = mask_zero self.supports_masking = mask_zero self.input_length = input_length - self._can_use_graph_functions = True @tf_utils.shape_type_conversion def build(self, input_shape): diff --git a/tensorflow/python/keras/layers/local.py b/tensorflow/python/keras/layers/local.py index 30b83eaf50..d2c4aaa125 100644 --- a/tensorflow/python/keras/layers/local.py +++ b/tensorflow/python/keras/layers/local.py @@ -23,8 +23,8 @@ from tensorflow.python.keras import backend as K from tensorflow.python.keras import constraints from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.utils import conv_utils from tensorflow.python.keras.utils import tf_utils from tensorflow.python.util.tf_export import tf_export @@ -154,7 +154,6 @@ class LocallyConnected1D(Layer): self.bias_constraint = constraints.get(bias_constraint) self.implementation = implementation self.input_spec = InputSpec(ndim=3) - self._can_use_graph_functions = True @tf_utils.shape_type_conversion def build(self, input_shape): @@ -430,7 +429,6 @@ class LocallyConnected2D(Layer): self.bias_constraint = constraints.get(bias_constraint) self.implementation = implementation self.input_spec = InputSpec(ndim=4) - self._can_use_graph_functions = True @tf_utils.shape_type_conversion def build(self, input_shape): diff --git a/tensorflow/python/keras/layers/local_test.py b/tensorflow/python/keras/layers/local_test.py index 300e7c9654..e4f4d0a639 100644 --- a/tensorflow/python/keras/layers/local_test.py +++ b/tensorflow/python/keras/layers/local_test.py @@ -28,39 +28,43 @@ from tensorflow.python.training.rmsprop import RMSPropOptimizer class LocallyConnected1DLayersTest(test.TestCase): + # TODO(fchollet): investigate why LocallyConnected1D + # fails inside a graph function in an eager context (fails with error + # "Incompatible shapes between op input and calculated input gradient"). - @tf_test_util.run_in_graph_and_eager_modes + @tf_test_util.run_deprecated_v1 def test_locallyconnected_1d(self): - num_samples = 2 - num_steps = 8 - input_dim = 5 - filter_length = 3 - filters = 4 - - for padding in ['valid', 'same']: - for strides in [1]: - if padding == 'same' and strides != 1: - continue - for data_format in ['channels_first', 'channels_last']: - for implementation in [1, 2]: - kwargs = { - 'filters': filters, - 'kernel_size': filter_length, - 'padding': padding, - 'strides': strides, - 'data_format': data_format, - 'implementation': implementation - } + with self.cached_session(): + num_samples = 2 + num_steps = 8 + input_dim = 5 + filter_length = 3 + filters = 4 - if padding == 'same' and implementation == 1: - self.assertRaises(ValueError, - keras.layers.LocallyConnected1D, - **kwargs) - else: - testing_utils.layer_test( - keras.layers.LocallyConnected1D, - kwargs=kwargs, - input_shape=(num_samples, num_steps, input_dim)) + for padding in ['valid', 'same']: + for strides in [1]: + if padding == 'same' and strides != 1: + continue + for data_format in ['channels_first', 'channels_last']: + for implementation in [1, 2]: + kwargs = { + 'filters': filters, + 'kernel_size': filter_length, + 'padding': padding, + 'strides': strides, + 'data_format': data_format, + 'implementation': implementation + } + + if padding == 'same' and implementation == 1: + self.assertRaises(ValueError, + keras.layers.LocallyConnected1D, + **kwargs) + else: + testing_utils.layer_test( + keras.layers.LocallyConnected1D, + kwargs=kwargs, + input_shape=(num_samples, num_steps, input_dim)) def test_locallyconnected_1d_regularization(self): num_samples = 2 @@ -113,30 +117,63 @@ class LocallyConnected1DLayersTest(test.TestCase): class LocallyConnected2DLayersTest(test.TestCase): + # TODO(fchollet): investigate why LocallyConnected2D + # fails inside a graph function in an eager context (fails with error + # "Incompatible shapes between op input and calculated input gradient"). - @tf_test_util.run_in_graph_and_eager_modes + @tf_test_util.run_deprecated_v1 def test_locallyconnected_2d(self): - num_samples = 8 - filters = 3 - stack_size = 4 - num_row = 6 - num_col = 10 + with self.cached_session(): + num_samples = 8 + filters = 3 + stack_size = 4 + num_row = 6 + num_col = 10 - for padding in ['valid', 'same']: - for strides in [(1, 1), (2, 2)]: - for implementation in [1, 2]: - if padding == 'same' and strides != (1, 1): - continue + for padding in ['valid', 'same']: + for strides in [(1, 1), (2, 2)]: + for implementation in [1, 2]: + if padding == 'same' and strides != (1, 1): + continue + + kwargs = { + 'filters': filters, + 'kernel_size': 3, + 'padding': padding, + 'kernel_regularizer': 'l2', + 'bias_regularizer': 'l2', + 'strides': strides, + 'data_format': 'channels_last', + 'implementation': implementation + } + if padding == 'same' and implementation == 1: + self.assertRaises(ValueError, + keras.layers.LocallyConnected2D, + **kwargs) + else: + testing_utils.layer_test( + keras.layers.LocallyConnected2D, + kwargs=kwargs, + input_shape=(num_samples, num_row, num_col, stack_size)) + + @tf_test_util.run_deprecated_v1 + def test_locallyconnected_2d_channels_first(self): + with self.cached_session(): + num_samples = 8 + filters = 3 + stack_size = 4 + num_row = 6 + num_col = 10 + + for implementation in [1, 2]: + for padding in ['valid', 'same']: kwargs = { 'filters': filters, 'kernel_size': 3, - 'padding': padding, - 'kernel_regularizer': 'l2', - 'bias_regularizer': 'l2', - 'strides': strides, - 'data_format': 'channels_last', - 'implementation': implementation + 'data_format': 'channels_first', + 'implementation': implementation, + 'padding': padding } if padding == 'same' and implementation == 1: @@ -149,34 +186,6 @@ class LocallyConnected2DLayersTest(test.TestCase): kwargs=kwargs, input_shape=(num_samples, num_row, num_col, stack_size)) - @tf_test_util.run_in_graph_and_eager_modes - def test_locallyconnected_2d_channels_first(self): - num_samples = 8 - filters = 3 - stack_size = 4 - num_row = 6 - num_col = 10 - - for implementation in [1, 2]: - for padding in ['valid', 'same']: - kwargs = { - 'filters': filters, - 'kernel_size': 3, - 'data_format': 'channels_first', - 'implementation': implementation, - 'padding': padding - } - - if padding == 'same' and implementation == 1: - self.assertRaises(ValueError, - keras.layers.LocallyConnected2D, - **kwargs) - else: - testing_utils.layer_test( - keras.layers.LocallyConnected2D, - kwargs=kwargs, - input_shape=(num_samples, num_row, num_col, stack_size)) - def test_locallyconnected_2d_regularization(self): num_samples = 2 filters = 3 @@ -226,64 +235,67 @@ class LocallyConnected2DLayersTest(test.TestCase): class LocallyConnectedImplementationModeTest(test.TestCase): - @tf_test_util.run_in_graph_and_eager_modes + @tf_test_util.run_deprecated_v1 def test_locallyconnected_implementation(self): - num_samples = 4 - num_classes = 3 - num_epochs = 2 - - np.random.seed(1) - targets = np.random.randint(0, num_classes, (num_samples,)) - - for width in [1, 6]: - for height in [7]: - for filters in [2]: - for data_format in ['channels_first', 'channels_last']: - inputs = get_inputs( - data_format, filters, height, num_samples, width) - - for kernel_x in [(3,)]: - for kernel_y in [()] if width == 1 else [(2,)]: - for stride_x in [(1,)]: - for stride_y in [()] if width == 1 else [(3,)]: - for layers in [2]: - kwargs = { - 'layers': layers, - 'filters': filters, - 'kernel_size': kernel_x + kernel_y, - 'strides': stride_x + stride_y, - 'data_format': data_format, - 'num_classes': num_classes, - 'input_shape': inputs.shape - } - - model_1 = get_model(implementation=1, **kwargs) - model_2 = get_model(implementation=2, **kwargs) - - copy_model_weights(model_2, model_1) - - # Compare outputs at initialization. - out_1 = model_1.call(inputs) - out_2 = model_2.call(inputs) - self.assertAllCloseAccordingToType(out_1, out_2, - rtol=1e-5, atol=1e-5) - - # Train. - model_1.fit(x=inputs, - y=targets, - epochs=num_epochs, - batch_size=num_samples) - - model_2.fit(x=inputs, - y=targets, - epochs=num_epochs, - batch_size=num_samples) - - # Compare outputs after a few training steps. - out_1 = model_1.call(inputs) - out_2 = model_2.call(inputs) - self.assertAllCloseAccordingToType(out_1, out_2, - rtol=1e-5, atol=1e-5) + with self.cached_session(): + num_samples = 4 + num_classes = 3 + num_epochs = 2 + + np.random.seed(1) + targets = np.random.randint(0, num_classes, (num_samples,)) + + for width in [1, 6]: + for height in [7]: + for filters in [2]: + for data_format in ['channels_first', 'channels_last']: + inputs = get_inputs( + data_format, filters, height, num_samples, width) + + for kernel_x in [(3,)]: + for kernel_y in [()] if width == 1 else [(2,)]: + for stride_x in [(1,)]: + for stride_y in [()] if width == 1 else [(3,)]: + for layers in [2]: + kwargs = { + 'layers': layers, + 'filters': filters, + 'kernel_size': kernel_x + kernel_y, + 'strides': stride_x + stride_y, + 'data_format': data_format, + 'num_classes': num_classes + } + model_1 = get_model(implementation=1, **kwargs) + model_2 = get_model(implementation=2, **kwargs) + + # Build models. + model_1.train_on_batch(inputs, targets) + model_2.train_on_batch(inputs, targets) + + # Copy weights. + copy_model_weights(model_2, model_1) + + # Compare outputs at initialization. + out_1 = model_1.call(inputs) + out_2 = model_2.call(inputs) + self.assertAllCloseAccordingToType(out_1, out_2, + rtol=1e-5, atol=1e-5) + + # Train. + model_1.fit(x=inputs, + y=targets, + epochs=num_epochs, + batch_size=num_samples) + model_2.fit(x=inputs, + y=targets, + epochs=num_epochs, + batch_size=num_samples) + + # Compare outputs after a few training steps. + out_1 = model_1.call(inputs) + out_2 = model_2.call(inputs) + self.assertAllCloseAccordingToType( + out_1, out_2, atol=2e-4) @tf_test_util.run_in_graph_and_eager_modes def test_make_2d(self): @@ -360,8 +372,7 @@ def get_model(implementation, strides, layers, num_classes, - data_format, - input_shape): + data_format): model = keras.Sequential() if len(kernel_size) == 1: @@ -390,7 +401,6 @@ def get_model(implementation, metrics=[keras.metrics.categorical_accuracy], loss=xent ) - model.build(input_shape) return model diff --git a/tensorflow/python/keras/layers/lstm_test.py b/tensorflow/python/keras/layers/lstm_test.py index 9db697871f..3f89cc398e 100644 --- a/tensorflow/python/keras/layers/lstm_test.py +++ b/tensorflow/python/keras/layers/lstm_test.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from absl.testing import parameterized import numpy as np from tensorflow.python import keras @@ -30,7 +31,7 @@ from tensorflow.python.training.rmsprop import RMSPropOptimizer @tf_test_util.run_all_in_graph_and_eager_modes -class LSTMLayerTest(test.TestCase): +class LSTMLayerTest(test.TestCase, parameterized.TestCase): def test_return_sequences_LSTM(self): num_samples = 2 @@ -56,7 +57,7 @@ class LSTMLayerTest(test.TestCase): layer = keras.layers.LSTM(units, return_sequences=True) model.add(layer) outputs = model.layers[-1].output - self.assertEquals(outputs.get_shape().as_list(), [None, timesteps, units]) + self.assertEqual(outputs.get_shape().as_list(), [None, timesteps, units]) def test_dynamic_behavior_LSTM(self): num_samples = 2 @@ -83,17 +84,17 @@ class LSTMLayerTest(test.TestCase): 'recurrent_dropout': 0.1}, input_shape=(num_samples, timesteps, embedding_dim)) - def test_implementation_mode_LSTM(self): + @parameterized.parameters([0, 1, 2]) + def test_implementation_mode_LSTM(self, implementation_mode): num_samples = 2 timesteps = 3 embedding_dim = 4 units = 2 - for mode in [0, 1, 2]: - testing_utils.layer_test( - keras.layers.LSTM, - kwargs={'units': units, - 'implementation': mode}, - input_shape=(num_samples, timesteps, embedding_dim)) + testing_utils.layer_test( + keras.layers.LSTM, + kwargs={'units': units, + 'implementation': implementation_mode}, + input_shape=(num_samples, timesteps, embedding_dim)) def test_constraints_LSTM(self): embedding_dim = 4 @@ -114,6 +115,7 @@ class LSTMLayerTest(test.TestCase): self.assertEqual(layer.cell.recurrent_kernel.constraint, r_constraint) self.assertEqual(layer.cell.bias.constraint, b_constraint) + @tf_test_util.run_deprecated_v1 def test_with_masking_layer_LSTM(self): layer_class = keras.layers.LSTM inputs = np.random.random((2, 3, 4)) @@ -126,6 +128,7 @@ class LSTMLayerTest(test.TestCase): optimizer=RMSPropOptimizer(0.01)) model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1) + @tf_test_util.run_deprecated_v1 def test_masking_with_stacking_LSTM(self): inputs = np.random.random((2, 3, 4)) targets = np.abs(np.random.random((2, 3, 5))) @@ -311,6 +314,7 @@ class LSTMLayerTest(test.TestCase): class LSTMLayerGraphOnlyTest(test.TestCase): + @tf_test_util.run_deprecated_v1 def test_statefulness_LSTM(self): num_samples = 2 timesteps = 3 @@ -374,6 +378,7 @@ class LSTMLayerGraphOnlyTest(test.TestCase): self.assertAllClose(out7, out6, atol=1e-5) + @tf_test_util.run_deprecated_v1 def test_regularizers_LSTM(self): embedding_dim = 4 layer_class = keras.layers.LSTM diff --git a/tensorflow/python/keras/layers/merge.py b/tensorflow/python/keras/layers/merge.py index 0ded0e42ed..45e705c696 100644 --- a/tensorflow/python/keras/layers/merge.py +++ b/tensorflow/python/keras/layers/merge.py @@ -40,7 +40,6 @@ class _Merge(Layer): def __init__(self, **kwargs): super(_Merge, self).__init__(**kwargs) - self._can_use_graph_functions = True self.supports_masking = True def _merge_function(self, inputs): @@ -213,7 +212,7 @@ class _Merge(Layer): if len(mask) != len(inputs): raise ValueError('The lists `inputs` and `mask` ' 'should have the same length.') - if all([m is None for m in mask]): + if all(m is None for m in mask): return None masks = [array_ops.expand_dims(m, axis=0) for m in mask if m is not None] return K.all(K.concatenate(masks, axis=0), axis=0, keepdims=False) @@ -369,7 +368,6 @@ class Concatenate(_Merge): def __init__(self, axis=-1, **kwargs): super(Concatenate, self).__init__(**kwargs) - self._can_use_graph_functions = True self.axis = axis self.supports_masking = True self._reshape_required = False @@ -380,7 +378,7 @@ class Concatenate(_Merge): if not isinstance(input_shape, list) or len(input_shape) < 2: raise ValueError('A `Concatenate` layer should be called ' 'on a list of at least 2 inputs') - if all([shape is None for shape in input_shape]): + if all(shape is None for shape in input_shape): return reduced_inputs_shapes = [list(shape) for shape in input_shape] shape_set = set() @@ -420,7 +418,7 @@ class Concatenate(_Merge): if len(mask) != len(inputs): raise ValueError('The lists `inputs` and `mask` ' 'should have the same length.') - if all([m is None for m in mask]): + if all(m is None for m in mask): return None # Make a list of masks while making sure # the dimensionality of each mask @@ -467,7 +465,6 @@ class Dot(_Merge): def __init__(self, axes, normalize=False, **kwargs): super(Dot, self).__init__(**kwargs) - self._can_use_graph_functions = True if not isinstance(axes, int): if not isinstance(axes, (list, tuple)): raise TypeError('Invalid type for `axes` - ' diff --git a/tensorflow/python/keras/layers/merge_test.py b/tensorflow/python/keras/layers/merge_test.py index 698c5662b6..fcb161ae20 100644 --- a/tensorflow/python/keras/layers/merge_test.py +++ b/tensorflow/python/keras/layers/merge_test.py @@ -207,6 +207,7 @@ class MergeLayersGraphOnlyTest(test.TestCase): mask = layer.output_mask self.assertListEqual(mask.get_shape().as_list(), [None, 4]) + @tf_test_util.run_deprecated_v1 def test_merge_add_dynamic_shape(self): with self.cached_session(): i1 = array_ops.placeholder(shape=(4, None), dtype='float32') diff --git a/tensorflow/python/keras/layers/noise.py b/tensorflow/python/keras/layers/noise.py index e7c0478513..cb7cee3ebc 100644 --- a/tensorflow/python/keras/layers/noise.py +++ b/tensorflow/python/keras/layers/noise.py @@ -55,7 +55,6 @@ class GaussianNoise(Layer): super(GaussianNoise, self).__init__(**kwargs) self.supports_masking = True self.stddev = stddev - self._can_use_graph_functions = True def call(self, inputs, training=None): @@ -100,7 +99,6 @@ class GaussianDropout(Layer): super(GaussianDropout, self).__init__(**kwargs) self.supports_masking = True self.rate = rate - self._can_use_graph_functions = True def call(self, inputs, training=None): if 0 < self.rate < 1: @@ -155,7 +153,6 @@ class AlphaDropout(Layer): self.noise_shape = noise_shape self.seed = seed self.supports_masking = True - self._can_use_graph_functions = True def _get_noise_shape(self, inputs): return self.noise_shape if self.noise_shape else array_ops.shape(inputs) diff --git a/tensorflow/python/keras/layers/normalization.py b/tensorflow/python/keras/layers/normalization.py index 3d3bf647e6..d958497655 100644 --- a/tensorflow/python/keras/layers/normalization.py +++ b/tensorflow/python/keras/layers/normalization.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python import tf2 from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops @@ -26,8 +27,8 @@ from tensorflow.python.keras import backend as K from tensorflow.python.keras import constraints from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.utils import tf_utils from tensorflow.python.ops import array_ops from tensorflow.python.ops import init_ops @@ -40,8 +41,8 @@ from tensorflow.python.training import distribution_strategy_context from tensorflow.python.util.tf_export import tf_export -@tf_export('keras.layers.BatchNormalization') -class BatchNormalization(Layer): +@tf_export('keras.layers.BatchNormalization', v1=[]) +class BatchNormalizationV2(Layer): """Batch normalization layer (Ioffe and Szegedy, 2014). Normalize the activations of the previous layer at each batch, @@ -84,8 +85,10 @@ class BatchNormalization(Layer): and should be neither too small (which would add noise) nor too large (which would give stale estimates). Note that `momentum` is still applied to get the means and variances for inference. - fused: if `None` or `True`, use a faster, fused implementation if possible. - If `False`, use the system recommended implementation. + fused: if `True`, use a faster, fused implementation, or raise a ValueError + if the fused implementation cannot be used. If `None`, use the faster + implementation if possible. If False, do not used the fused + implementation. trainable: Boolean, if `True` also add variables to the graph collection `GraphKeys.TRAINABLE_VARIABLES` (see tf.Variable). virtual_batch_size: An `int`. By default, `virtual_batch_size` is `None`, @@ -120,6 +123,9 @@ class BatchNormalization(Layer): Internal Covariate Shift](https://arxiv.org/abs/1502.03167) """ + # The BatchNormalizationV1 subclass sets this to False to use the V1 behavior. + _USE_V2_BEHAVIOR = True + def __init__(self, axis=-1, momentum=0.99, @@ -143,13 +149,15 @@ class BatchNormalization(Layer): adjustment=None, name=None, **kwargs): - super(BatchNormalization, self).__init__( + super(BatchNormalizationV2, self).__init__( name=name, trainable=trainable, **kwargs) - self._can_use_graph_functions = True if isinstance(axis, list): self.axis = axis[:] - else: + elif isinstance(axis, int): self.axis = axis + else: + raise TypeError('axis must be int or list, type given: %s' + % type(self.axis)) self.momentum = momentum self.epsilon = epsilon self.center = center @@ -166,7 +174,14 @@ class BatchNormalization(Layer): self.renorm = renorm self.virtual_batch_size = virtual_batch_size self.adjustment = adjustment - if fused is None: + if self._USE_V2_BEHAVIOR: + if fused: + self._raise_if_fused_cannot_be_used() + # We leave fused as None if self._fused_can_be_used()==True, since we + # still may set it to False in self.build() if the input rank is not 4. + elif fused is None and not self._fused_can_be_used(): + fused = False + elif fused is None: fused = True self.supports_masking = True @@ -182,6 +197,38 @@ class BatchNormalization(Layer): self.renorm_clipping = renorm_clipping self.renorm_momentum = renorm_momentum + def _raise_if_fused_cannot_be_used(self): + """Raises a ValueError if fused implementation cannot be used. + + In addition to the checks done in this function, the input tensors rank must + be 4. The input rank check can only be done once the input shape is known. + """ + # Currently fused batch norm doesn't support renorm. It also only supports a + # channel dimension on axis 1 or 3, when no virtual batch size or adjustment + # is used. + if self.renorm: + raise ValueError('Passing both fused=True and renorm=True is ' + 'unsupported') + axis = [self.axis] if isinstance(self.axis, int) else self.axis + # Axis -3 is equivalent to 1, and axis -1 is equivalent to 3, because the + # input rank is required to be 4 (which is checked later). + if len(axis) > 1 or axis[0] not in (-3, -1, 1, 3): + raise ValueError('Passing fused=True is only supported when axis is 1 ' + 'or 3') + if self.virtual_batch_size is not None: + raise ValueError('Passing fused=True is unsupported when ' + 'virtual_batch_size is specified.') + if self.adjustment is not None: + raise ValueError('Passing fused=True is unsupported when ' + 'adjustment is specified.') + + def _fused_can_be_used(self): + try: + self._raise_if_fused_cannot_be_used() + return True + except ValueError: + return False + def build(self, input_shape): input_shape = tensor_shape.TensorShape(input_shape) if not input_shape.ndims: @@ -192,10 +239,6 @@ class BatchNormalization(Layer): if isinstance(self.axis, int): self.axis = [self.axis] - if not isinstance(self.axis, list): - raise TypeError('axis must be int or list, type given: %s' - % type(self.axis)) - for idx, x in enumerate(self.axis): if x < 0: self.axis[idx] = ndims + x @@ -220,16 +263,18 @@ class BatchNormalization(Layer): raise ValueError('When using virtual_batch_size, adjustment cannot ' 'be specified') - if self.fused: - # Currently fused batch norm doesn't support renorm. It also only supports - # an input tensor of rank 4 and a channel dimension on axis 1 or 3. + if self.fused in (None, True): # TODO(yaozhang): if input is not 4D, reshape it to 4D and reshape the # output back to its original shape accordingly. - self.fused = (not self.renorm and - ndims == 4 and - self.axis in [[1], [3]] and - self.virtual_batch_size is None and - self.adjustment is None) + if self._USE_V2_BEHAVIOR: + if self.fused is None: + self.fused = (ndims == 4) + elif self.fused and ndims != 4: + raise ValueError('Batch normalization layers with fused=True only ' + 'support 4D input tensors.') + else: + assert self.fused is not None + self.fused = (ndims == 4 and self._fused_can_be_used()) # TODO(chrisying): fused batch norm is currently not supported for # multi-axis batch norm and by extension virtual batches. In some cases, # it might be possible to use fused batch norm but would require reshaping @@ -492,6 +537,9 @@ class BatchNormalization(Layer): return (r, d, new_mean, new_variance) + def _moments(self, inputs, reduction_axes, keep_dims): + return nn.moments(inputs, reduction_axes, keep_dims=keep_dims) + def call(self, inputs, training=None): if training is None: training = K.learning_phase() @@ -563,7 +611,8 @@ class BatchNormalization(Layer): # Some of the computations here are not necessary when training==False # but not a constant. However, this makes the code simpler. keep_dims = self.virtual_batch_size is not None or len(self.axis) > 1 - mean, variance = nn.moments(inputs, reduction_axes, keep_dims=keep_dims) + mean, variance = self._moments( + inputs, reduction_axes, keep_dims=keep_dims) moving_mean = self.moving_mean moving_variance = self.moving_variance @@ -669,5 +718,36 @@ class BatchNormalization(Layer): 'layer cannot be serialized and has been omitted from ' 'the layer config. It will not be included when ' 're-creating the layer from the saved config.') - base_config = super(BatchNormalization, self).get_config() + base_config = super(BatchNormalizationV2, self).get_config() return dict(list(base_config.items()) + list(config.items())) + + +def _replace_in_v2_docstring(old, new): + string = BatchNormalizationV2.__doc__ + if old not in string: + raise ValueError('Could not find following string in BatchNormalizationV2 ' + 'docstring: "{}"'.format(old)) + return string.replace(old, new) + + +@tf_export(v1=['keras.layers.BatchNormalization']) # pylint: disable=missing-docstring +class BatchNormalizationV1(BatchNormalizationV2): + + __doc__ = _replace_in_v2_docstring( + ''' + fused: if `True`, use a faster, fused implementation, or raise a ValueError + if the fused implementation cannot be used. If `None`, use the faster + implementation if possible. If False, do not used the fused + implementation.''', + + ''' + fused: if `None` or `True`, use a faster, fused implementation if possible. + If `False`, use the system recommended implementation.''') + + _USE_V2_BEHAVIOR = False + + +if tf2.enabled(): + BatchNormalization = BatchNormalizationV2 +else: + BatchNormalization = BatchNormalizationV1 diff --git a/tensorflow/python/keras/layers/normalization_test.py b/tensorflow/python/keras/layers/normalization_test.py index 92e4128707..9138c0a08a 100644 --- a/tensorflow/python/keras/layers/normalization_test.py +++ b/tensorflow/python/keras/layers/normalization_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python import keras from tensorflow.python.framework import test_util as tf_test_util from tensorflow.python.keras import testing_utils +from tensorflow.python.keras.layers import normalization from tensorflow.python.platform import test from tensorflow.python.training import gradient_descent @@ -54,6 +55,14 @@ class NormalizationLayersTest(test.TestCase): kwargs={'scale': False, 'center': False}, input_shape=(3, 3)) + testing_utils.layer_test( + normalization.BatchNormalizationV2, + kwargs={'fused': True}, + input_shape=(3, 3, 3, 3)) + testing_utils.layer_test( + normalization.BatchNormalizationV2, + kwargs={'fused': None}, + input_shape=(3, 3, 3)) def test_batchnorm_weights(self): layer = keras.layers.BatchNormalization(scale=False, center=False) @@ -78,15 +87,18 @@ class NormalizationLayersTest(test.TestCase): self.assertEqual(layer.gamma.constraint, max_norm) self.assertEqual(layer.beta.constraint, max_norm) - def test_batchnorm_correctness(self): + def _test_batchnorm_correctness(self, dtype, use_v2=True, fused=False): model = keras.models.Sequential() - norm = keras.layers.BatchNormalization(input_shape=(10,), momentum=0.8) + layer_ctor = (normalization.BatchNormalizationV2 if use_v2 + else normalization.BatchNormalizationV1) + norm = layer_ctor(input_shape=(2, 2, 2), momentum=0.8, fused=fused) model.add(norm) model.compile(loss='mse', optimizer=gradient_descent.GradientDescentOptimizer(0.01)) # centered on 5.0, variance 10.0 - x = np.random.normal(loc=5.0, scale=10.0, size=(1000, 10)) + x = (np.random.normal(loc=5.0, scale=10.0, size=(1000, 2, 2, 2)) + .astype(dtype)) model.fit(x, x, epochs=4, verbose=0) out = model.predict(x) out -= keras.backend.eval(norm.beta) @@ -95,23 +107,15 @@ class NormalizationLayersTest(test.TestCase): np.testing.assert_allclose(out.mean(), 0.0, atol=1e-1) np.testing.assert_allclose(out.std(), 1.0, atol=1e-1) - def test_batchnorm_mixed_precision(self): - model = keras.models.Sequential() - norm = keras.layers.BatchNormalization(input_shape=(10,), momentum=0.8) - model.add(norm) - model.compile(loss='mse', - optimizer=gradient_descent.GradientDescentOptimizer(0.01)) - - # centered on 5.0, variance 10.0 - x = np.random.normal( - loc=5.0, scale=10.0, size=(1000, 10)).astype(np.float16) - model.fit(x, x, epochs=4, verbose=0) - out = model.predict(x) - out -= keras.backend.eval(norm.beta) - out /= keras.backend.eval(norm.gamma) + def test_batchnorm_correctness(self): + self._test_batchnorm_correctness(np.float32) + self._test_batchnorm_correctness(np.float32, fused=True) + self._test_batchnorm_correctness(np.float32, use_v2=False) - np.testing.assert_allclose(out.mean(), 0.0, atol=1e-1) - np.testing.assert_allclose(out.std(), 1.0, atol=1e-1) + def test_batchnorm_mixed_precision(self): + self._test_batchnorm_correctness(np.float16) + self._test_batchnorm_correctness(np.float16, fused=True) + self._test_batchnorm_correctness(np.float16, use_v2=False) def test_batchnorm_convnet(self): if test.is_gpu_available(cuda_only=True): @@ -151,6 +155,77 @@ class NormalizationLayersTest(test.TestCase): np.testing.assert_allclose(np.mean(out, axis=(0, 1, 2)), 0.0, atol=1e-1) np.testing.assert_allclose(np.std(out, axis=(0, 1, 2)), 1.0, atol=1e-1) + def test_v1_fused_attribute(self): + norm = normalization.BatchNormalizationV1() + inp = keras.layers.Input((4, 4, 4)) + norm(inp) + self.assertEqual(norm.fused, True) + + norm = normalization.BatchNormalizationV1(fused=False) + self.assertEqual(norm.fused, False) + inp = keras.layers.Input(shape=(4, 4, 4)) + norm(inp) + self.assertEqual(norm.fused, False) + + norm = normalization.BatchNormalizationV1(virtual_batch_size=2) + self.assertEqual(norm.fused, True) + inp = keras.layers.Input(shape=(2, 2, 2)) + norm(inp) + self.assertEqual(norm.fused, False) + + def test_v2_fused_attribute(self): + norm = normalization.BatchNormalizationV2() + self.assertEqual(norm.fused, None) + inp = keras.layers.Input(shape=(4, 4, 4)) + norm(inp) + self.assertEqual(norm.fused, True) + + norm = normalization.BatchNormalizationV2() + self.assertEqual(norm.fused, None) + inp = keras.layers.Input(shape=(4, 4)) + norm(inp) + self.assertEqual(norm.fused, False) + + norm = normalization.BatchNormalizationV2(virtual_batch_size=2) + self.assertEqual(norm.fused, False) + inp = keras.layers.Input(shape=(4, 4, 4)) + norm(inp) + self.assertEqual(norm.fused, False) + + norm = normalization.BatchNormalizationV2(fused=False) + self.assertEqual(norm.fused, False) + inp = keras.layers.Input(shape=(4, 4, 4)) + norm(inp) + self.assertEqual(norm.fused, False) + + norm = normalization.BatchNormalizationV2(fused=True, axis=[3]) + self.assertEqual(norm.fused, True) + inp = keras.layers.Input(shape=(4, 4, 4)) + norm(inp) + self.assertEqual(norm.fused, True) + + with self.assertRaisesRegexp(ValueError, 'fused.*renorm'): + normalization.BatchNormalizationV2(fused=True, renorm=True) + + with self.assertRaisesRegexp(ValueError, 'fused.*when axis is 1 or 3'): + normalization.BatchNormalizationV2(fused=True, axis=2) + + with self.assertRaisesRegexp(ValueError, 'fused.*when axis is 1 or 3'): + normalization.BatchNormalizationV2(fused=True, axis=[1, 3]) + + with self.assertRaisesRegexp(ValueError, 'fused.*virtual_batch_size'): + normalization.BatchNormalizationV2(fused=True, virtual_batch_size=2) + + with self.assertRaisesRegexp(ValueError, 'fused.*adjustment'): + normalization.BatchNormalizationV2(fused=True, + adjustment=lambda _: (1, 0)) + + norm = normalization.BatchNormalizationV2(fused=True) + self.assertEqual(norm.fused, True) + inp = keras.layers.Input(shape=(4, 4)) + with self.assertRaisesRegexp(ValueError, '4D input tensors'): + norm(inp) + class NormalizationLayersGraphModeOnlyTest(test.TestCase): @@ -226,6 +301,7 @@ class NormalizationLayersGraphModeOnlyTest(test.TestCase): x2 = model.predict(val_a) self.assertAllClose(x1, x2, atol=1e-7) + @tf_test_util.run_deprecated_v1 def test_batchnorm_trainable(self): """Tests that batchnorm layer is trainable when learning phase is enabled. diff --git a/tensorflow/python/keras/layers/pooling.py b/tensorflow/python/keras/layers/pooling.py index b8d6b03664..a0744cddad 100644 --- a/tensorflow/python/keras/layers/pooling.py +++ b/tensorflow/python/keras/layers/pooling.py @@ -22,8 +22,8 @@ import functools from tensorflow.python.framework import tensor_shape from tensorflow.python.keras import backend -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.utils import conv_utils from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops @@ -58,7 +58,6 @@ class Pooling1D(Layer): padding='valid', data_format='channels_last', name=None, **kwargs): super(Pooling1D, self).__init__(name=name, **kwargs) - self._can_use_graph_functions = True if data_format is None: data_format = backend.image_data_format() if strides is None: @@ -231,7 +230,6 @@ class Pooling2D(Layer): padding='valid', data_format=None, name=None, **kwargs): super(Pooling2D, self).__init__(name=name, **kwargs) - self._can_use_graph_functions = True if data_format is None: data_format = backend.image_data_format() if strides is None: @@ -427,7 +425,6 @@ class Pooling3D(Layer): padding='valid', data_format='channels_last', name=None, **kwargs): super(Pooling3D, self).__init__(name=name, **kwargs) - self._can_use_graph_functions = True if data_format is None: data_format = backend.image_data_format() if strides is None: @@ -599,7 +596,6 @@ class GlobalPooling1D(Layer): def __init__(self, data_format='channels_last', **kwargs): super(GlobalPooling1D, self).__init__(**kwargs) - self._can_use_graph_functions = True self.input_spec = InputSpec(ndim=3) self.data_format = conv_utils.normalize_data_format(data_format) @@ -705,7 +701,6 @@ class GlobalPooling2D(Layer): def __init__(self, data_format=None, **kwargs): super(GlobalPooling2D, self).__init__(**kwargs) - self._can_use_graph_functions = True self.data_format = conv_utils.normalize_data_format(data_format) self.input_spec = InputSpec(ndim=4) @@ -804,7 +799,6 @@ class GlobalPooling3D(Layer): def __init__(self, data_format=None, **kwargs): super(GlobalPooling3D, self).__init__(**kwargs) - self._can_use_graph_functions = True self.data_format = conv_utils.normalize_data_format(data_format) self.input_spec = InputSpec(ndim=5) diff --git a/tensorflow/python/keras/layers/recurrent.py b/tensorflow/python/keras/layers/recurrent.py index 979187c719..d9502dfc5b 100644 --- a/tensorflow/python/keras/layers/recurrent.py +++ b/tensorflow/python/keras/layers/recurrent.py @@ -19,20 +19,27 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import uuid + import numpy as np from tensorflow.python.eager import context +from tensorflow.python.eager import function +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.keras import activations from tensorflow.python.keras import backend as K from tensorflow.python.keras import constraints from tensorflow.python.keras import initializers from tensorflow.python.keras import regularizers -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.utils import generic_utils from tensorflow.python.keras.utils import tf_utils from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gen_cudnn_rnn_ops from tensorflow.python.ops import state_ops from tensorflow.python.platform import tf_logging as logging from tensorflow.python.training.checkpointable import base as checkpointable @@ -446,6 +453,9 @@ class RNN(Layer): 'an attribute `state_size` ' '(tuple of integers, ' 'one integer per RNN state).') + # If True, the output for masked timestep will be zeros, whereas in the + # False case, output from previous timestep is returned for masked timestep. + self.zero_output_for_mask = kwargs.pop('zero_output_for_mask', False) super(RNN, self).__init__(**kwargs) self.cell = cell if isinstance(cell, checkpointable.CheckpointableBase): @@ -743,35 +753,12 @@ class RNN(Layer): training=None, initial_state=None, constants=None): - # input shape: `(samples, time (padded with zeros), input_dim)` - # note that the .build() method of subclasses MUST define - # self.input_spec and self.state_spec with complete input shapes. - if isinstance(inputs, list): - # get initial_state from full input spec - # as they could be copied to multiple GPU. - if self._num_constants is None: - initial_state = inputs[1:] - else: - initial_state = inputs[1:-self._num_constants] - constants = inputs[-self._num_constants:] - if len(initial_state) == 0: - initial_state = None - inputs = inputs[0] - if initial_state is not None: - pass - elif self.stateful: - initial_state = self.states - else: - initial_state = self.get_initial_state(inputs) + inputs, initial_state, constants = self._process_inputs( + inputs, initial_state, constants) if isinstance(mask, list): mask = mask[0] - if len(initial_state) != len(self.states): - raise ValueError( - 'Layer has ' + str(len(self.states)) + ' states but was passed ' + - str(len(initial_state)) + ' initial states.') - if nest.is_sequence(inputs): # In the case of nested input, use the first element for shape check. input_shape = K.int_shape(nest.flatten(inputs)[0]) @@ -829,7 +816,8 @@ class RNN(Layer): mask=mask, unroll=self.unroll, input_length=timesteps, - time_major=self.time_major) + time_major=self.time_major, + zero_output_for_mask=self.zero_output_for_mask) if self.stateful: updates = [] for i in range(len(states)): @@ -850,6 +838,34 @@ class RNN(Layer): else: return output + def _process_inputs(self, inputs, initial_state, constants): + # input shape: `(samples, time (padded with zeros), input_dim)` + # note that the .build() method of subclasses MUST define + # self.input_spec and self.state_spec with complete input shapes. + if isinstance(inputs, list): + # get initial_state from full input spec + # as they could be copied to multiple GPU. + if self._num_constants is None: + initial_state = inputs[1:] + else: + initial_state = inputs[1:-self._num_constants] + constants = inputs[-self._num_constants:] + if len(initial_state) == 0: + initial_state = None + inputs = inputs[0] + if initial_state is not None: + pass + elif self.stateful: + initial_state = self.states + else: + initial_state = self.get_initial_state(inputs) + + if len(initial_state) != len(self.states): + raise ValueError('Layer has ' + str(len(self.states)) + + ' states but was passed ' + str(len(initial_state)) + + ' initial states.') + return inputs, initial_state, constants + def reset_states(self, states=None): if not self.stateful: raise AttributeError('Layer must be stateful.') @@ -923,6 +939,8 @@ class RNN(Layer): } if self._num_constants is not None: config['num_constants'] = self._num_constants + if self.zero_output_for_mask: + config['zero_output_for_mask'] = self.zero_output_for_mask cell_config = self.cell.get_config() config['cell'] = { @@ -2515,6 +2533,416 @@ class LSTM(RNN): return cls(**config) +class UnifiedLSTM(LSTM): + """Long Short-Term Memory layer - Hochreiter 1997. + + `UnifiedLSTM` unifies the implementations between standard `LSTM` layer and + `CuDNNLSTM` layer. Based on available runtime hardware and constrains, + `UnifiedLSTM` will choose different implementations to maximize the + performance. For instance, if GPU is available and all the parameters meet the + requirement of CuDNN kernel, `UnifiedLSTM` will use CuDNN kernel for the + calculation. + + Arguments: + units: Positive integer, dimensionality of the output space. + activation: Activation function to use. + Default: hyperbolic tangent (`tanh`). If you pass `None`, no activation + is applied + (ie. "linear" activation: `a(x) = x`). + recurrent_activation: Activation function to use for the recurrent step. + Default: hard sigmoid (`hard_sigmoid`). If you pass `None`, no + activation is applied + (ie. "linear" activation: `a(x) = x`). + use_bias: Boolean, whether the layer uses a bias vector. + kernel_initializer: Initializer for the `kernel` weights matrix, used for + the linear transformation of the inputs.. + recurrent_initializer: Initializer for the `recurrent_kernel` weights + matrix, used for the linear transformation of the recurrent state.. + bias_initializer: Initializer for the bias vector. + unit_forget_bias: Boolean. If True, add 1 to the bias of the forget gate at + initialization. Setting it to true will also force + `bias_initializer="zeros"`. This is recommended in [Jozefowicz et + al.](http://www.jmlr.org/proceedings/papers/v37/jozefowicz15.pdf) + kernel_regularizer: Regularizer function applied to the `kernel` weights + matrix. + recurrent_regularizer: Regularizer function applied to the + `recurrent_kernel` weights matrix. + bias_regularizer: Regularizer function applied to the bias vector. + activity_regularizer: Regularizer function applied to the output of the + layer (its "activation").. + kernel_constraint: Constraint function applied to the `kernel` weights + matrix. + recurrent_constraint: Constraint function applied to the `recurrent_kernel` + weights matrix. + bias_constraint: Constraint function applied to the bias vector. + dropout: Float between 0 and 1. Fraction of the units to drop for the linear + transformation of the inputs. + recurrent_dropout: Float between 0 and 1. Fraction of the units to drop for + the linear transformation of the recurrent state. + implementation: Implementation mode, either 1 or 2. Mode 1 will structure + its operations as a larger number of smaller dot products and additions, + whereas mode 2 will batch them into fewer, larger operations. These modes + will have different performance profiles on different hardware and for + different applications. + return_sequences: Boolean. Whether to return the last output. in the output + sequence, or the full sequence. + return_state: Boolean. Whether to return the last state in addition to the + output. + go_backwards: Boolean (default False). If True, process the input sequence + backwards and return the reversed sequence. + stateful: Boolean (default False). If True, the last state for each sample + at index i in a batch will be used as initial state for the sample of + index i in the following batch. + unroll: Boolean (default False). If True, the network will be unrolled, else + a symbolic loop will be used. Unrolling can speed-up a RNN, although it + tends to be more memory-intensive. Unrolling is only suitable for short + sequences. + """ + + def __init__(self, + units, + activation='tanh', + recurrent_activation='hard_sigmoid', + use_bias=True, + kernel_initializer='glorot_uniform', + recurrent_initializer='orthogonal', + bias_initializer='zeros', + unit_forget_bias=True, + kernel_regularizer=None, + recurrent_regularizer=None, + bias_regularizer=None, + activity_regularizer=None, + kernel_constraint=None, + recurrent_constraint=None, + bias_constraint=None, + dropout=0., + recurrent_dropout=0., + implementation=1, + return_sequences=False, + return_state=False, + go_backwards=False, + stateful=False, + time_major=False, + unroll=False, + **kwargs): + # return_runtime is a flag for testing, which shows the real backend + # implementation chosen by grappler in graph mode. + self.return_runtime = kwargs.pop('return_runtime', False) + + super(UnifiedLSTM, self).__init__( + units, + activation=activation, + recurrent_activation=recurrent_activation, + use_bias=use_bias, + kernel_initializer=kernel_initializer, + recurrent_initializer=recurrent_initializer, + bias_initializer=bias_initializer, + unit_forget_bias=unit_forget_bias, + kernel_regularizer=kernel_regularizer, + recurrent_regularizer=recurrent_regularizer, + bias_regularizer=bias_regularizer, + activity_regularizer=activity_regularizer, + kernel_constraint=kernel_constraint, + recurrent_constraint=recurrent_constraint, + bias_constraint=bias_constraint, + dropout=dropout, + recurrent_dropout=recurrent_dropout, + implementation=implementation, + return_sequences=return_sequences, + return_state=return_state, + go_backwards=go_backwards, + stateful=stateful, + time_major=time_major, + unroll=unroll, + **kwargs) + + self.state_spec = [ + InputSpec(shape=(None, dim)) for dim in (self.units, self.units) + ] + self._num_constants = None + self._num_inputs = None + self.could_use_cudnn = ( + activation == 'tanh' and dropout == 0 and not unroll and use_bias and + unit_forget_bias) + + def build(self, input_shape): + super(UnifiedLSTM, self).build(input_shape) + if self.could_use_cudnn: + # Add a new set of bias for CuDNN implementation only. Standard LSTM only + # has bias for recurrent kernel, while CuDNN LSTM has an extra set for + # input gate as well. + self.cudnn_bias = self.add_weight( + shape=(self.units * 4,), + name='cudnn_bias', + use_resource=True, + initializer=self.bias_initializer, + regularizer=self.bias_regularizer, + constraint=self.bias_constraint) + self.built = True + + def call(self, inputs, mask=None, training=None, initial_state=None): + # LSTM does not support constants. Ignore it during process. + inputs, initial_state, _ = self._process_inputs(inputs, initial_state, None) + + if isinstance(mask, list): + mask = mask[0] + + input_shape = K.int_shape(inputs) + timesteps = input_shape[0] if self.time_major else input_shape[1] + + if mask is not None or not self.could_use_cudnn: + # CuDNN does not support masking, fall back to use the normal LSTM. + kwargs = {'training': training} + + def step(inputs, states): + return self.cell.call(inputs, states, **kwargs) + + last_output, outputs, states = K.rnn( + step, + inputs, + initial_state, + constants=None, + go_backwards=self.go_backwards, + mask=mask, + unroll=self.unroll, + input_length=timesteps, + time_major=self.time_major, + zero_output_for_mask=self.zero_output_for_mask) + runtime = constant_op.constant( + 'unknown', dtype=dtypes.string, name='runtime') + else: + # Use the new defun approach for backend implementation swap. + # Note that different implementations need to have same function + # signature, eg, the tensor parameters need to have same shape and dtypes. + # Since the CuDNN has an extra set of bias, those bias will be passed to + # both normal and CuDNN implementations. + if self.go_backwards: + # Reverse time axis. + inputs = K.reverse(inputs, 1) + + combined_bias = array_ops.concat([self.cudnn_bias, self.cell.bias], 0) + + # Each time a defun function is called, we will give a unique identifiable + # API name, so that the grappler won't get confused when it sees multiple + # LSTM layer added into same graph, and it will be able to pair up the + # different implementations across them. + experimental_api_name = 'lstm_' + str(uuid.uuid4()) + standard_lstm_attributes = { + 'experimental_api_implements': experimental_api_name, + 'experimental_api_preferred_device': 'CPU', + } + cudnn_lstm_attributes = { + 'experimental_api_implements': experimental_api_name, + 'experimental_api_preferred_device': 'GPU', + } + defun_standard_lstm = function.defun_with_attributes( + standard_lstm, attributes=standard_lstm_attributes) + defun_cudnn_lstm = function.defun_with_attributes( + cudnn_lstm, attributes=cudnn_lstm_attributes) + + if ops.executing_eagerly_outside_functions(): + # Under eager context, the device placement is already known. Prefer the + # GPU implementation here. + if context.num_gpus() > 0: + last_output, outputs, new_h, new_c, runtime = defun_cudnn_lstm( + inputs, initial_state[0], initial_state[1], self.cell.kernel, + self.cell.recurrent_kernel, combined_bias, self.time_major) + else: + last_output, outputs, new_h, new_c, runtime = defun_standard_lstm( + inputs, initial_state[0], initial_state[1], self.cell.kernel, + self.cell.recurrent_kernel, combined_bias, self.activation, + self.recurrent_activation, self.time_major) + else: + # Call the normal LSTM impl and register the CuDNN impl function. The + # grappler will kick in during session execution to optimize the graph. + last_output, outputs, new_h, new_c, runtime = defun_standard_lstm( + inputs, initial_state[0], initial_state[1], self.cell.kernel, + self.cell.recurrent_kernel, combined_bias, self.activation, + self.recurrent_activation, self.time_major) + + function.register(defun_cudnn_lstm, inputs, initial_state[0], + initial_state[1], self.cell.kernel, + self.cell.recurrent_kernel, combined_bias, + self.time_major) + states = [new_h, new_c] + + if self.stateful: + updates = [] + for i in range(len(states)): + updates.append(state_ops.assign(self.states[i], states[i])) + self.add_update(updates, inputs) + + if self.return_sequences: + output = outputs + else: + output = last_output + + if self.return_state: + return [output] + states + elif self.return_runtime: + return output, runtime + else: + return output + + @property + def trainable_weights(self): + if self.trainable: + weights = [] + weights += self.cell.trainable_weights + if getattr(self, 'cudnn_bias', None) is not None: + weights += [self.cudnn_bias] + return weights + return [] + + @property + def non_trainable_weights(self): + if not self.trainable: + weights = [] + weights += self.cell.non_trainable_weights + if getattr(self, 'cudnn_bias', None) is not None: + weights += [self.cudnn_bias] + return weights + return [] + + @property + def losses(self): + losses = [] + losses += self.cell.losses + return losses + self._losses + + @property + def updates(self): + updates = [] + updates += self.cell.updates + return updates + self._updates + + def get_weights(self): + weights = [] + weights += self.cell.weights + if getattr(self, 'cudnn_bias', None) is not None: + weights += [self.cudnn_bias] + return K.batch_get_value(weights) + + def set_weights(self, weights): + tuples = [] + cell_weights = weights[:len(self.cell.weights)] + if cell_weights: + tuples.append((self.cell.weights, cell_weights)) + if getattr(self, 'cudnn_bias', None) is not None: + cudnn_bias_weights = weights[len(self.cell.weights):] + if cudnn_bias_weights: + tuples.append((self.cudnn_bias, cudnn_bias_weights)) + K.batch_set_value(tuples) + + +def _canonical_to_params(weights, biases, shape): + """Utility function convert variable to CuDNN compatible parameter.""" + weights = [array_ops.reshape(x, shape) for x in weights] + biases = [array_ops.reshape(x, shape) for x in biases] + return array_ops.concat(weights + biases, axis=0) + + +def standard_lstm(inputs, init_h, init_c, kernel, recurrent_kernel, bias, + activation, recurrent_activation, time_major): + """LSTM with standard kernel implementation. + + This implementation can be run on all types for hardware. + + This implementation lifts out all the layer weights and make them function + parameters. It has same number of tensor input params as the CuDNN + counterpart. The RNN step logic has been simplified, eg dropout and mask is + removed since CuDNN implementation does not support that. + + Note that the first half of the bias tensor should be ignored by this impl. + The CuDNN impl need an extra set of input gate bias. In order to make the both + function take same shape of parameter, that extra set of bias is also feed + here. + + Args: + inputs: input tensor of LSTM layer. + init_h: initial state tensor for the cell output. + init_c: initial state tensor for the cell hidden state. + kernel: weights for cell kernel. + recurrent_kernel: weights for cell recurrent kernel. + bias: weights for cell kernel bias and recurrent bias. Only recurrent bias + is used in this case. + activation: Activation function to use for output. + recurrent_activation: Activation function to use for hidden recurrent state. + time_major: boolean, whether the inputs are in the format of + [time, batch, feature] or [batch, time, feature]. + + Returns: + last_output: output tensor for the last timestep, which has shape + [batch, units]. + outputs: output tensor for all timesteps, which has shape + [batch, time, units]. + state_0: the cell output, which has same shape as init_h. + state_1: the cell hidden state, which has same shape as init_c. + runtime: constant string tensor which indicate real runtime hardware. This + value is for testing purpose and should be used by user. + """ + input_shape = K.int_shape(inputs) + timesteps = input_shape[0] if time_major else input_shape[1] + + # Only use the second half of the bias weights. + _, real_bias = array_ops.split(bias, 2) + + def step(cell_inputs, cell_states): + """Step function that will be used by Keras RNN backend.""" + h_tm1 = cell_states[0] # previous memory state + c_tm1 = cell_states[1] # previous carry state + + z = K.dot(cell_inputs, kernel) + z += K.dot(h_tm1, recurrent_kernel) + z = K.bias_add(z, real_bias) + + z0, z1, z2, z3 = array_ops.split(z, 4, axis=1) + + i = recurrent_activation(z0) + f = recurrent_activation(z1) + c = f * c_tm1 + i * activation(z2) + o = recurrent_activation(z3) + + h = o * activation(c) + return h, [h, c] + + last_output, outputs, new_states = K.rnn( + step, + inputs, [init_h, init_c], + constants=None, + unroll=False, + time_major=time_major, + input_length=timesteps) + return last_output, outputs, new_states[0], new_states[ + 1], constant_op.constant('cpu', dtype=dtypes.string, name='runtime') + + +def cudnn_lstm(inputs, input_h, input_c, kernel, recurrent_kernel, bias, + time_major): + """LSTM with CuDNN implementation which is only available for GPU.""" + if not time_major: + inputs = array_ops.transpose(inputs, perm=(1, 0, 2)) + input_h = array_ops.expand_dims(input_h, axis=0) + input_c = array_ops.expand_dims(input_c, axis=0) + + weights = array_ops.split(kernel, 4, axis=1) + weights += array_ops.split(recurrent_kernel, 4, axis=1) + params = _canonical_to_params( + weights=weights, + biases=array_ops.split(bias, 8), + shape=constant_op.constant([-1])) + + outputs, h, c, _ = gen_cudnn_rnn_ops.cudnn_rnn( + inputs, input_h=input_h, input_c=input_c, params=params) + if not time_major: + outputs = array_ops.transpose(outputs, perm=[1, 0, 2]) + h = h[0] + c = c[0] + last_output = outputs[:, -1, :] + return last_output, outputs, h, c, constant_op.constant( + 'cudnn', dtype=dtypes.string, name='runtime') + + def _generate_dropout_mask(ones, rate, training=None, count=1): def dropped_inputs(): return K.dropout(ones, rate) diff --git a/tensorflow/python/keras/layers/recurrent_test.py b/tensorflow/python/keras/layers/recurrent_test.py index bb14a7a505..b1449069e3 100644 --- a/tensorflow/python/keras/layers/recurrent_test.py +++ b/tensorflow/python/keras/layers/recurrent_test.py @@ -1013,8 +1013,8 @@ class RNNTest(test.TestCase): inputs, _ = cell(inputs, initial_state) output = inputs if not context.executing_eagerly(): - sess.run(variables_lib.global_variables_initializer()) - output = sess.run(output) + self.evaluate(variables_lib.global_variables_initializer()) + output = self.evaluate(output) return output random_seed.set_random_seed(12345) @@ -1079,6 +1079,32 @@ class RNNTest(test.TestCase): # Expect last output to be the same as last output before masking self.assertAllClose(y_np, x_np[:, 1, :]) + def test_zero_output_for_masking(self): + + for unroll in [True, False]: + cell = keras.layers.SimpleRNNCell(5) + x = keras.Input((5, 5)) + mask = keras.layers.Masking() + layer = keras.layers.RNN( + cell, return_sequences=True, zero_output_for_mask=True, unroll=unroll) + masked_input = mask(x) + y = layer(masked_input) + model = keras.models.Model(x, y) + model.compile(optimizer=rmsprop.RMSPropOptimizer(learning_rate=0.001), + loss='mse') + + np_x = np.ones((6, 5, 5)) + result_1 = model.predict(np_x) + + # set the time 4 and 5 for last record to be zero (masked). + np_x[5, 3:] = 0 + result_2 = model.predict(np_x) + + # expect the result_2 has same output, except the time 4,5 for last + # record. + result_1[5, 3:] = 0 + self.assertAllClose(result_1, result_2) + class Minimal2DRNNCell(keras.layers.Layer): """The minimal 2D RNN cell is a simple combination of 2 1-D RNN cell. diff --git a/tensorflow/python/keras/layers/simplernn_test.py b/tensorflow/python/keras/layers/simplernn_test.py index 93456b5e3a..b49b159b71 100644 --- a/tensorflow/python/keras/layers/simplernn_test.py +++ b/tensorflow/python/keras/layers/simplernn_test.py @@ -98,6 +98,7 @@ class SimpleRNNLayerTest(test.TestCase): self.assertEqual(layer.cell.recurrent_kernel.constraint, r_constraint) self.assertEqual(layer.cell.bias.constraint, b_constraint) + @tf_test_util.run_deprecated_v1 def test_with_masking_layer_SimpleRNN(self): layer_class = keras.layers.SimpleRNN inputs = np.random.random((2, 3, 4)) @@ -120,6 +121,7 @@ class SimpleRNNLayerTest(test.TestCase): class SimpleRNNLayerGraphOnlyTest(test.TestCase): + @tf_test_util.run_deprecated_v1 def test_statefulness_SimpleRNN(self): num_samples = 2 timesteps = 3 @@ -183,6 +185,7 @@ class SimpleRNNLayerGraphOnlyTest(test.TestCase): np.testing.assert_allclose(out7, out6, atol=1e-5) + @tf_test_util.run_deprecated_v1 def test_regularizers_SimpleRNN(self): embedding_dim = 4 layer_class = keras.layers.SimpleRNN diff --git a/tensorflow/python/keras/layers/unified_lstm_test.py b/tensorflow/python/keras/layers/unified_lstm_test.py new file mode 100644 index 0000000000..d229d14312 --- /dev/null +++ b/tensorflow/python/keras/layers/unified_lstm_test.py @@ -0,0 +1,724 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for UnifiedLSTM layer.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import time + +from absl.testing import parameterized +import numpy as np + +from tensorflow.core.protobuf import config_pb2 +from tensorflow.core.protobuf import rewriter_config_pb2 +from tensorflow.python import keras +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util +from tensorflow.python.keras import testing_utils +from tensorflow.python.keras.layers.cudnn_recurrent import CuDNNLSTM +from tensorflow.python.keras.layers.recurrent import UnifiedLSTM +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import gen_math_ops +from tensorflow.python.ops import variables +from tensorflow.python.ops.losses import losses +from tensorflow.python.platform import test +from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.training import gradient_descent + + +# Global config for grappler setting that is used for graph mode test. +_rewrites = rewriter_config_pb2.RewriterConfig() +_rewrites.function_optimization = rewriter_config_pb2.RewriterConfig.OFF +_customer_optimizer = _rewrites.custom_optimizers.add() +_customer_optimizer.name = 'ExperimentalImplementationSelector' +_rewrites.min_graph_nodes = -1 +_graph_options = config_pb2.GraphOptions(rewrite_options=_rewrites) +_config = config_pb2.ConfigProto(graph_options=_graph_options) + + +class UnifiedLSTMTest(test.TestCase, parameterized.TestCase): + + @test_util.run_deprecated_v1 + def test_unifiedLSTM(self): + input_shape = 10 + rnn_state_size = 8 + output_shape = 8 + timestep = 4 + batch = 100 + epoch = 1 + + with self.cached_session(config=_config, use_gpu=True) as sess: + (x_train, y_train), _ = testing_utils.get_test_data( + train_samples=batch, + test_samples=0, + input_shape=(timestep, input_shape), + num_classes=output_shape) + y_train = keras.utils.to_categorical(y_train, output_shape) + + layer = UnifiedLSTM(rnn_state_size, return_runtime=True) + + inputs = array_ops.placeholder( + dtypes.float32, shape=(None, timestep, input_shape), name='inputs') + predict = array_ops.placeholder( + dtypes.float32, shape=(None, output_shape), name='predict') + + outputs, runtime = layer(inputs) + loss = losses.softmax_cross_entropy(predict, outputs) + optimizer = gradient_descent.GradientDescentOptimizer(0.001) + train_op = optimizer.minimize(loss) + + sess.run([variables.global_variables_initializer()]) + existing_loss = 0 + for _ in range(epoch): + loss_value, _, runtime_value = sess.run([loss, train_op, runtime], { + inputs: x_train, + predict: y_train + }) + if test.is_gpu_available(): + self.assertEqual(runtime_value, b'cudnn') + else: + self.assertEqual(runtime_value, b'cpu') + # Make sure the loss is updated for every epoch + # (layer weights properly updated). + self.assertNotEqual(existing_loss, loss_value) + existing_loss = loss_value + + @test_util.run_deprecated_v1 + def test_unifiedLSTM_with_cond(self): + # This test is to demonstrate the graph rewrite of grappler plugin under + # the condition that the function returns different number of internal + # states. + input_shape = 10 + rnn_state_size = 8 + output_shape = 8 + timestep = 4 + batch = 100 + epoch = 1 + + with self.cached_session(config=_config, use_gpu=True) as sess: + (x_train, y_train), _ = testing_utils.get_test_data( + train_samples=batch, + test_samples=0, + input_shape=(timestep, input_shape), + num_classes=output_shape) + y_train = keras.utils.to_categorical(y_train, output_shape) + + layer = UnifiedLSTM(rnn_state_size, return_runtime=True) + + inputs = array_ops.placeholder( + dtypes.float32, shape=(None, timestep, input_shape), name='inputs') + predict = array_ops.placeholder( + dtypes.float32, shape=(None, output_shape), name='predict') + + zeros = array_ops.zeros([batch, output_shape]) + dummy_runtime = constant_op.constant( + 'unknown', dtype=dtypes.string, name='runtime') + a = constant_op.constant(0) + b = constant_op.constant(1) + # Will always run the lstm layer. + outputs, runtime = control_flow_ops.cond( + gen_math_ops.less(a, b), + lambda: layer(inputs), + lambda: (zeros, dummy_runtime)) + loss = losses.softmax_cross_entropy(predict, outputs) + optimizer = gradient_descent.GradientDescentOptimizer(0.001) + train_op = optimizer.minimize(loss) + + sess.run([variables.global_variables_initializer()]) + existing_loss = 0 + + for _ in range(epoch): + loss_value, _, runtime_value = sess.run([loss, train_op, runtime], { + inputs: x_train, + predict: y_train + }) + if test.is_gpu_available(): + self.assertEqual(runtime_value, b'cudnn') + else: + self.assertEqual(runtime_value, b'cpu') + # Make sure the loss is updated for every epoch + # (layer weights properly updated). + self.assertNotEqual(existing_loss, loss_value) + existing_loss = loss_value + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_keras_model_with_lstm(self): + input_shape = 10 + rnn_state_size = 8 + output_shape = 8 + timestep = 4 + batch = 100 + epoch = 10 + + (x_train, y_train), _ = testing_utils.get_test_data( + train_samples=batch, + test_samples=0, + input_shape=(timestep, input_shape), + num_classes=output_shape) + y_train = keras.utils.to_categorical(y_train, output_shape) + + layer = UnifiedLSTM(rnn_state_size) + + inputs = keras.layers.Input( + shape=[timestep, input_shape], dtype=dtypes.float32) + + outputs = layer(inputs) + model = keras.models.Model(inputs, outputs) + model.compile('rmsprop', loss='mse') + model.fit(x_train, y_train, epochs=epoch) + model.evaluate(x_train, y_train) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_return_sequences_LSTM(self): + num_samples = 2 + timesteps = 3 + embedding_dim = 4 + units = 2 + testing_utils.layer_test( + UnifiedLSTM, + kwargs={ + 'units': units, + 'return_sequences': True + }, + input_shape=(num_samples, timesteps, embedding_dim)) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_static_shape_inference_LSTM(self): + # Github issue: 15165 + timesteps = 3 + embedding_dim = 4 + units = 2 + + model = keras.models.Sequential() + inputs = keras.layers.Dense( + embedding_dim, input_shape=(timesteps, embedding_dim)) + model.add(inputs) + layer = UnifiedLSTM(units, return_sequences=True) + model.add(layer) + outputs = model.layers[-1].output + self.assertEqual(outputs.get_shape().as_list(), [None, timesteps, units]) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_dynamic_behavior_LSTM(self): + num_samples = 2 + timesteps = 3 + embedding_dim = 4 + units = 2 + layer = UnifiedLSTM(units, input_shape=(None, embedding_dim)) + model = keras.models.Sequential() + model.add(layer) + model.compile(gradient_descent.GradientDescentOptimizer(0.001), 'mse') + x = np.random.random((num_samples, timesteps, embedding_dim)) + y = np.random.random((num_samples, units)) + model.train_on_batch(x, y) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_dropout_LSTM(self): + num_samples = 2 + timesteps = 3 + embedding_dim = 4 + units = 2 + testing_utils.layer_test( + UnifiedLSTM, + kwargs={ + 'units': units, + 'dropout': 0.1, + 'recurrent_dropout': 0.1 + }, + input_shape=(num_samples, timesteps, embedding_dim)) + + @parameterized.parameters([0, 1, 2]) + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_implementation_mode_LSTM(self, implementation_mode): + num_samples = 2 + timesteps = 3 + embedding_dim = 4 + units = 2 + testing_utils.layer_test( + UnifiedLSTM, + kwargs={ + 'units': units, + 'implementation': implementation_mode + }, + input_shape=(num_samples, timesteps, embedding_dim)) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_constraints_LSTM(self): + embedding_dim = 4 + layer_class = UnifiedLSTM + k_constraint = keras.constraints.max_norm(0.01) + r_constraint = keras.constraints.max_norm(0.01) + b_constraint = keras.constraints.max_norm(0.01) + layer = layer_class( + 5, + return_sequences=False, + weights=None, + input_shape=(None, embedding_dim), + kernel_constraint=k_constraint, + recurrent_constraint=r_constraint, + bias_constraint=b_constraint) + layer.build((None, None, embedding_dim)) + self.assertEqual(layer.cell.kernel.constraint, k_constraint) + self.assertEqual(layer.cell.recurrent_kernel.constraint, r_constraint) + self.assertEqual(layer.cell.bias.constraint, b_constraint) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_with_masking_layer_LSTM(self): + layer_class = UnifiedLSTM + inputs = np.random.random((2, 3, 4)) + targets = np.abs(np.random.random((2, 3, 5))) + targets /= targets.sum(axis=-1, keepdims=True) + model = keras.models.Sequential() + model.add(keras.layers.Masking(input_shape=(3, 4))) + model.add(layer_class(units=5, return_sequences=True, unroll=False)) + model.compile( + loss='categorical_crossentropy', + optimizer=gradient_descent.GradientDescentOptimizer(0.01)) + model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_stacking_LSTM(self): + inputs = np.random.random((2, 3, 4)) + targets = np.abs(np.random.random((2, 3, 5))) + targets /= targets.sum(axis=-1, keepdims=True) + model = keras.models.Sequential() + model.add(UnifiedLSTM(10, return_sequences=True, unroll=False)) + model.add(UnifiedLSTM(5, return_sequences=True, unroll=False)) + model.compile( + loss='categorical_crossentropy', + optimizer=gradient_descent.GradientDescentOptimizer(0.01)) + model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_masking_with_stacking_LSTM(self): + inputs = np.random.random((2, 3, 4)) + targets = np.abs(np.random.random((2, 3, 5))) + targets /= targets.sum(axis=-1, keepdims=True) + model = keras.models.Sequential() + model.add(keras.layers.Masking(input_shape=(3, 4))) + model.add(UnifiedLSTM(10, return_sequences=True, unroll=False)) + model.add(UnifiedLSTM(5, return_sequences=True, unroll=False)) + model.compile( + loss='categorical_crossentropy', + optimizer=gradient_descent.GradientDescentOptimizer(0.01)) + model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_from_config_LSTM(self): + layer_class = UnifiedLSTM + for stateful in (False, True): + l1 = layer_class(units=1, stateful=stateful) + l2 = layer_class.from_config(l1.get_config()) + assert l1.get_config() == l2.get_config() + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_specify_initial_state_keras_tensor(self): + num_states = 2 + timesteps = 3 + embedding_dim = 4 + units = 3 + num_samples = 2 + + # Test with Keras tensor + inputs = keras.Input((timesteps, embedding_dim)) + initial_state = [keras.Input((units,)) for _ in range(num_states)] + layer = UnifiedLSTM(units) + if len(initial_state) == 1: + output = layer(inputs, initial_state=initial_state[0]) + else: + output = layer(inputs, initial_state=initial_state) + assert initial_state[0] in layer._inbound_nodes[0].input_tensors + + model = keras.models.Model([inputs] + initial_state, output) + model.compile( + loss='categorical_crossentropy', + optimizer=gradient_descent.GradientDescentOptimizer(0.01)) + + inputs = np.random.random((num_samples, timesteps, embedding_dim)) + initial_state = [ + np.random.random((num_samples, units)) for _ in range(num_states) + ] + targets = np.random.random((num_samples, units)) + model.train_on_batch([inputs] + initial_state, targets) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def DISABLED_test_specify_initial_state_non_keras_tensor(self): + num_states = 2 + timesteps = 3 + embedding_dim = 4 + units = 3 + num_samples = 2 + + # Test with non-Keras tensor + inputs = keras.Input((timesteps, embedding_dim)) + initial_state = [ + keras.backend.random_normal_variable((num_samples, units), 0, 1) + for _ in range(num_states) + ] + layer = UnifiedLSTM(units) + output = layer(inputs, initial_state=initial_state) + + model = keras.models.Model(inputs, output) + model.compile( + loss='categorical_crossentropy', + optimizer=gradient_descent.GradientDescentOptimizer(0.01)) + + inputs = np.random.random((num_samples, timesteps, embedding_dim)) + targets = np.random.random((num_samples, units)) + model.train_on_batch(inputs, targets) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_reset_states_with_values(self): + num_states = 2 + timesteps = 3 + embedding_dim = 4 + units = 3 + num_samples = 2 + + layer = UnifiedLSTM(units, stateful=True) + layer.build((num_samples, timesteps, embedding_dim)) + layer.reset_states() + assert len(layer.states) == num_states + assert layer.states[0] is not None + self.assertAllClose( + keras.backend.eval(layer.states[0]), + np.zeros(keras.backend.int_shape(layer.states[0])), + atol=1e-4) + state_shapes = [keras.backend.int_shape(state) for state in layer.states] + values = [np.ones(shape) for shape in state_shapes] + if len(values) == 1: + values = values[0] + layer.reset_states(values) + self.assertAllClose( + keras.backend.eval(layer.states[0]), + np.ones(keras.backend.int_shape(layer.states[0])), + atol=1e-4) + + # Test with invalid data + with self.assertRaises(ValueError): + layer.reset_states([1] * (len(layer.states) + 1)) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_specify_state_with_masking(self): + num_states = 2 + timesteps = 3 + embedding_dim = 4 + units = 3 + num_samples = 2 + + inputs = keras.Input((timesteps, embedding_dim)) + _ = keras.layers.Masking()(inputs) + initial_state = [keras.Input((units,)) for _ in range(num_states)] + output = UnifiedLSTM(units)(inputs, initial_state=initial_state) + + model = keras.models.Model([inputs] + initial_state, output) + model.compile( + loss='categorical_crossentropy', + optimizer=gradient_descent.GradientDescentOptimizer(0.01)) + + inputs = np.random.random((num_samples, timesteps, embedding_dim)) + initial_state = [ + np.random.random((num_samples, units)) for _ in range(num_states) + ] + targets = np.random.random((num_samples, units)) + model.train_on_batch([inputs] + initial_state, targets) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_return_state(self): + num_states = 2 + timesteps = 3 + embedding_dim = 4 + units = 3 + num_samples = 2 + + inputs = keras.Input(batch_shape=(num_samples, timesteps, embedding_dim)) + layer = UnifiedLSTM(units, return_state=True, stateful=True) + outputs = layer(inputs) + state = outputs[1:] + assert len(state) == num_states + model = keras.models.Model(inputs, state[0]) + + inputs = np.random.random((num_samples, timesteps, embedding_dim)) + state = model.predict(inputs) + self.assertAllClose(keras.backend.eval(layer.states[0]), state, atol=1e-4) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_state_reuse(self): + timesteps = 3 + embedding_dim = 4 + units = 3 + num_samples = 2 + + inputs = keras.Input(batch_shape=(num_samples, timesteps, embedding_dim)) + layer = UnifiedLSTM(units, return_state=True, return_sequences=True) + outputs = layer(inputs) + output, state = outputs[0], outputs[1:] + output = UnifiedLSTM(units)(output, initial_state=state) + model = keras.models.Model(inputs, output) + + inputs = np.random.random((num_samples, timesteps, embedding_dim)) + model.predict(inputs) + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_initial_states_as_other_inputs(self): + timesteps = 3 + embedding_dim = 4 + units = 3 + num_samples = 2 + num_states = 2 + layer_class = UnifiedLSTM + + # Test with Keras tensor + main_inputs = keras.Input((timesteps, embedding_dim)) + initial_state = [keras.Input((units,)) for _ in range(num_states)] + inputs = [main_inputs] + initial_state + + layer = layer_class(units) + output = layer(inputs) + assert initial_state[0] in layer._inbound_nodes[0].input_tensors + + model = keras.models.Model(inputs, output) + model.compile( + loss='categorical_crossentropy', + optimizer=gradient_descent.GradientDescentOptimizer(0.01)) + + main_inputs = np.random.random((num_samples, timesteps, embedding_dim)) + initial_state = [ + np.random.random((num_samples, units)) for _ in range(num_states) + ] + targets = np.random.random((num_samples, units)) + model.train_on_batch([main_inputs] + initial_state, targets) + + +class LSTMLayerGraphOnlyTest(test.TestCase): + + def test_statefulness_LSTM(self): + num_samples = 2 + timesteps = 3 + embedding_dim = 4 + units = 2 + layer_class = UnifiedLSTM + with self.cached_session(config=_config): + model = keras.models.Sequential() + model.add( + keras.layers.Embedding( + 4, + embedding_dim, + mask_zero=True, + input_length=timesteps, + batch_input_shape=(num_samples, timesteps))) + layer = layer_class( + units, return_sequences=False, stateful=True, weights=None) + model.add(layer) + model.compile( + optimizer=gradient_descent.GradientDescentOptimizer(0.01), loss='mse') + out1 = model.predict(np.ones((num_samples, timesteps))) + self.assertEqual(out1.shape, (num_samples, units)) + + # train once so that the states change + model.train_on_batch( + np.ones((num_samples, timesteps)), np.ones((num_samples, units))) + out2 = model.predict(np.ones((num_samples, timesteps))) + + # if the state is not reset, output should be different + self.assertNotEqual(out1.max(), out2.max()) + + # check that output changes after states are reset + # (even though the model itself didn't change) + layer.reset_states() + out3 = model.predict(np.ones((num_samples, timesteps))) + self.assertNotEqual(out2.max(), out3.max()) + + # check that container-level reset_states() works + model.reset_states() + out4 = model.predict(np.ones((num_samples, timesteps))) + self.assertAllClose(out3, out4, atol=1e-5) + + # check that the call to `predict` updated the states + out5 = model.predict(np.ones((num_samples, timesteps))) + self.assertNotEqual(out4.max(), out5.max()) + + # Check masking + layer.reset_states() + + left_padded_input = np.ones((num_samples, timesteps)) + left_padded_input[0, :1] = 0 + left_padded_input[1, :2] = 0 + out6 = model.predict(left_padded_input) + + layer.reset_states() + + right_padded_input = np.ones((num_samples, timesteps)) + right_padded_input[0, -1:] = 0 + right_padded_input[1, -2:] = 0 + out7 = model.predict(right_padded_input) + + self.assertAllClose(out7, out6, atol=1e-5) + + def test_regularizers_LSTM(self): + embedding_dim = 4 + layer_class = UnifiedLSTM + with self.cached_session(config=_config): + layer = layer_class( + 5, + return_sequences=False, + weights=None, + input_shape=(None, embedding_dim), + kernel_regularizer=keras.regularizers.l1(0.01), + recurrent_regularizer=keras.regularizers.l1(0.01), + bias_regularizer='l2', + activity_regularizer='l1') + layer.build((None, None, 2)) + self.assertEqual(len(layer.losses), 3) + x = keras.backend.variable(np.ones((2, 3, 2))) + layer(x) + self.assertEqual(len(layer.get_losses_for(x)), 1) + + +class UnifiedLSTMPerformanceTest(test.TestCase): + + def _measure_performance(self, test_config, model, x_train, y_train): + batch = test_config['batch'] + epoch = test_config['epoch'] + warmup_epoch = test_config['warmup_epoch'] + + # warm up the model + model.fit(x_train, y_train, batch_size=batch, epochs=warmup_epoch) + start_time = time.time() + model.fit(x_train, y_train, batch_size=batch, epochs=epoch - warmup_epoch) + end_time = time.time() + return (end_time - start_time) / (epoch - warmup_epoch) + + def _time_performance_run_cudnn_lstm(self, test_config, x_train, y_train): + # Get the performance number for standard Cudnn LSTM + input_shape = test_config['input_shape'] + rnn_state_size = test_config['rnn_state_size'] + timestep = test_config['timestep'] + + cudnn_lstm_layer = CuDNNLSTM(rnn_state_size) + inputs = keras.layers.Input( + shape=[timestep, input_shape], dtype=dtypes.float32) + + outputs = cudnn_lstm_layer(inputs) + model = keras.models.Model(inputs, outputs) + model.compile('sgd', 'mse') + + sec_per_epoch = self._measure_performance( + test_config, model, x_train, y_train) + logging.info('Average performance for %s per epoch is: %s', + 'CuDNN LSTM', sec_per_epoch) + return sec_per_epoch + + def _time_performance_run_unifed_lstm_gpu( + self, test_config, x_train, y_train): + # Get performance number for Unified_LSTM with grappler swap the impl + input_shape = test_config['input_shape'] + rnn_state_size = test_config['rnn_state_size'] + timestep = test_config['timestep'] + + layer = UnifiedLSTM(rnn_state_size) + inputs = keras.layers.Input( + shape=[timestep, input_shape], dtype=dtypes.float32) + + outputs = layer(inputs) + model = keras.models.Model(inputs, outputs) + model.compile('sgd', 'mse') + + sec_per_epoch = self._measure_performance( + test_config, model, x_train, y_train) + logging.info('Average performance for %s per epoch is: %s', + 'Unified LSTM', sec_per_epoch) + return sec_per_epoch + + def _time_performance_run_normal_lstm( + self, test_config, x_train, y_train): + # Get performance number for standard LSTM on GPU. + input_shape = test_config['input_shape'] + rnn_state_size = test_config['rnn_state_size'] + timestep = test_config['timestep'] + + layer = keras.layers.LSTM(rnn_state_size) + inputs = keras.layers.Input( + shape=[timestep, input_shape], dtype=dtypes.float32) + + outputs = layer(inputs) + model = keras.models.Model(inputs, outputs) + model.compile('sgd', 'mse') + + sec_per_epoch = self._measure_performance( + test_config, model, x_train, y_train) + logging.info('Average performance for %s per epoch is: %s', + 'Normal LSTM', sec_per_epoch) + return sec_per_epoch + + @test_util.run_in_graph_and_eager_modes(config=_config, use_gpu=True) + def test_performance_with_standard_cudnn_impl(self): + if not test.is_gpu_available(): + self.skipTest('performance test will only run on GPU') + + batch = 64 + num_batch = 10 + test_config = { + 'input_shape': 128, + 'rnn_state_size': 64, + 'output_shape': 64, + 'timestep': 50, + 'batch': batch, + 'epoch': 20, + # The performance for warmup epoch is ignored. + 'warmup_epoch': 1, + } + (x_train, y_train), _ = testing_utils.get_test_data( + train_samples=(batch * num_batch), + test_samples=0, + input_shape=(test_config['timestep'], test_config['input_shape']), + num_classes=test_config['output_shape']) + y_train = keras.utils.to_categorical(y_train, test_config['output_shape']) + + cudnn_duration = self._time_performance_run_cudnn_lstm( + test_config, x_train, y_train) + unified_lstm_gpu_duration = self._time_performance_run_unifed_lstm_gpu( + test_config, x_train, y_train) + normal_lstm_duration = self._time_performance_run_normal_lstm( + test_config, x_train, y_train) + + cudnn_vs_unified = cudnn_duration / unified_lstm_gpu_duration + unified_vs_normal = normal_lstm_duration / unified_lstm_gpu_duration + + # TODO(scottzhu): reeanble the test after moving it to benchmark test suite. + # The current test has performance flakiness issue. + logging.info('Expect the performance of Unified LSTM is within 80% of ' + 'CuDNN LSTM, got {0:.2f}%'.format(cudnn_vs_unified * 100)) + logging.info('Expect the performance of Unified LSTM is more than 5 times' + ' of normal LSTM, got {0:.2f}'.format(unified_vs_normal)) + + # Assert the performance diff should be within 80% of the native cudnn. + # self.assertGreaterEqual( + # cudnn_vs_unified, 0.80, + # 'Expect the performance of Unified LSTM is within 80% of CuDNN LSTM, ' + # 'but got {0:.2f}%'.format(cudnn_vs_unified * 100)) + # # Assert the performance diff between CPU impl and GPU impl should be more + # # than 5 times. + # self.assertGreaterEqual( + # unified_vs_normal, 5, + # 'Expect the performance of Unified LSTM is more than 5 times of ' + # 'normal LSTM, but got {0:.2f}'.format(unified_vs_normal)) + +if __name__ == '__main__': + test.main() diff --git a/tensorflow/python/keras/layers/wrappers.py b/tensorflow/python/keras/layers/wrappers.py index d40f7a2e80..67b154141e 100644 --- a/tensorflow/python/keras/layers/wrappers.py +++ b/tensorflow/python/keras/layers/wrappers.py @@ -23,8 +23,8 @@ import copy from tensorflow.python.framework import tensor_shape from tensorflow.python.keras import backend as K -from tensorflow.python.keras.engine.base_layer import InputSpec from tensorflow.python.keras.engine.base_layer import Layer +from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.layers.recurrent import _standardize_args from tensorflow.python.keras.utils import generic_utils from tensorflow.python.keras.utils import tf_utils @@ -389,6 +389,10 @@ class Bidirectional(Wrapper): raise ValueError('Invalid merge mode. ' 'Merge mode should be one of ' '{"sum", "mul", "ave", "concat", None}') + if getattr(layer, 'zero_output_for_mask', None) is not None: + # Force the zero_output_for_mask to be True if it presents. + layer.zero_output_for_mask = True + self.forward_layer = copy.copy(layer) config = layer.get_config() config['go_backwards'] = not config['go_backwards'] diff --git a/tensorflow/python/keras/layers/wrappers_test.py b/tensorflow/python/keras/layers/wrappers_test.py index 9584b0186c..b9196416dd 100644 --- a/tensorflow/python/keras/layers/wrappers_test.py +++ b/tensorflow/python/keras/layers/wrappers_test.py @@ -192,8 +192,8 @@ class TimeDistributedTest(test.TestCase): x = keras.layers.Input(shape=(3, 2)) layer = keras.layers.TimeDistributed(keras.layers.BatchNormalization()) _ = layer(x) - self.assertEquals(len(layer.updates), 2) - self.assertEquals(len(layer.trainable_weights), 2) + self.assertEqual(len(layer.updates), 2) + self.assertEqual(len(layer.trainable_weights), 2) layer.trainable = False assert not layer.updates assert not layer.trainable_weights @@ -201,6 +201,7 @@ class TimeDistributedTest(test.TestCase): assert len(layer.updates) == 2 assert len(layer.trainable_weights) == 2 + @tf_test_util.run_deprecated_v1 def test_TimeDistributed_with_masked_embedding_and_unspecified_shape(self): with self.cached_session(): # test with unspecified shape and Embeddings with mask_zero @@ -233,6 +234,7 @@ class TimeDistributedTest(test.TestCase): self.assertAllEqual(mask_outputs_val[i], ref_mask_val[i]) self.assertIs(mask_outputs[-1], None) # final layer + @tf_test_util.run_deprecated_v1 def test_TimeDistributed_with_masking_layer(self): with self.cached_session(): # test with Masking layer @@ -375,6 +377,7 @@ class BidirectionalTest(test.TestCase): model.compile(loss='mse', optimizer='sgd') model.fit(x, y, epochs=1, batch_size=1) + @tf_test_util.run_deprecated_v1 def test_Bidirectional_merged_value(self): rnn = keras.layers.LSTM samples = 2 @@ -505,6 +508,7 @@ class BidirectionalTest(test.TestCase): layer.trainable = True assert len(layer.trainable_weights) == 6 + @tf_test_util.run_deprecated_v1 def test_Bidirectional_updates(self): with self.cached_session(): x = keras.layers.Input(shape=(3, 2)) @@ -635,6 +639,34 @@ class BidirectionalTest(test.TestCase): y_np_3 = model.predict([x_np, s_fw_np, s_bk_np, c_np]) self.assertAllClose(y_np, y_np_3, atol=1e-4) + def test_Bidirectional_with_masking(self): + rnn = keras.layers.LSTM + samples = 2 + dim = 5 + timesteps = 3 + units = 3 + merge_mode = 'concat' + x = np.random.rand(samples, timesteps, dim) + # clear the first record's timestep 2, and expect the output of timestep 2 + # is also 0s. + x[0, 2] = 0 + + with self.cached_session(): + inputs = keras.Input((timesteps, dim)) + masked_inputs = keras.layers.Masking()(inputs) + wrapped = keras.layers.Bidirectional( + rnn(units, return_sequences=True), + merge_mode=merge_mode) + outputs = _to_list(wrapped(masked_inputs, training=True)) + self.assertEqual(len(outputs), 1) + self.assertEqual(outputs[0].get_shape().as_list(), + [None, timesteps, units * 2]) + + model = keras.Model(inputs, outputs) + y = _to_list(model.predict(x)) + self.assertEqual(len(y), 1) + self.assertAllClose(y[0][0, 2], np.zeros(units * 2)) + def _to_list(ls): if isinstance(ls, list): diff --git a/tensorflow/python/keras/losses.py b/tensorflow/python/keras/losses.py index 9f548bfe04..4c584d0ff0 100644 --- a/tensorflow/python/keras/losses.py +++ b/tensorflow/python/keras/losses.py @@ -19,16 +19,382 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import abc + import six +from tensorflow.python.framework import ops from tensorflow.python.keras import backend as K from tensorflow.python.keras.utils.generic_utils import deserialize_keras_object from tensorflow.python.keras.utils.generic_utils import serialize_keras_object +from tensorflow.python.keras.utils.losses_utils import compute_weighted_loss +from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import nn +from tensorflow.python.ops.losses import losses_impl from tensorflow.python.util.tf_export import tf_export +class Loss(object): + """Loss base class. + + To be implemented by subclasses: + * `call()`: Contains the logic for loss calculation using `y_true`, `y_pred`. + + Example subclass implementation: + ``` + class MeanSquaredError(Loss): + def call(self, y_true, y_pred): + y_pred = ops.convert_to_tensor(y_pred) + y_true = math_ops.cast(y_true, y_pred.dtype) + return K.mean(math_ops.square(y_pred - y_true), axis=-1) + ``` + + Args: + reduction: Type of `tf.losses.Reduction` to apply to loss. Default value is + `SUM_OVER_BATCH_SIZE`. + name: Optional name for the op. + """ + + def __init__(self, + reduction=losses_impl.ReductionV2.SUM_OVER_BATCH_SIZE, + name=None): + self.reduction = reduction + self.name = name + + def __call__(self, y_true, y_pred, sample_weight=None): + """Invokes the `Loss` instance. + + Args: + y_true: Ground truth values. + y_pred: The predicted values. + sample_weight: Optional `Tensor` whose rank is either 0, or the same rank + as `y_true`, or is broadcastable to `y_true`. `sample_weight` acts as a + coefficient for the loss. If a scalar is provided, then the loss is + simply scaled by the given value. If `sample_weight` is a tensor of size + `[batch_size]`, then the total loss for each sample of the batch is + rescaled by the corresponding element in the `sample_weight` vector. If + the shape of `sample_weight` matches the shape of `y_pred`, then the + loss of each measurable element of `y_pred` is scaled by the + corresponding value of `sample_weight`. + + Returns: + Weighted loss float `Tensor`. If `reduction` is `NONE`, this has the same + shape as `y_true`; otherwise, it is scalar. + + Raises: + ValueError: If the shape of `sample_weight` is invalid. + """ + with ops.name_scope(self.name, format(self.__class__.__name__), + (y_pred, y_true, sample_weight)): + losses = self.call(y_true, y_pred) + return compute_weighted_loss( + losses, sample_weight, reduction=self.reduction) + + @classmethod + def from_config(cls, config): + """Instantiates a `Loss` from its config (output of `get_config()`). + + Args: + config: Output of `get_config()`. + + Returns: + A `Loss` instance. + """ + return cls(**config) + + def get_config(self): + return {'reduction': self.reduction, 'name': self.name} + + @abc.abstractmethod + def call(self, y_true, y_pred): + """Invokes the `Loss` instance. + + Args: + y_true: Ground truth values, with the same shape as 'y_pred'. + y_pred: The predicted values. + """ + NotImplementedError('Must be implemented in subclasses.') + + +@tf_export('keras.losses.MeanSquaredError') +class MeanSquaredError(Loss): + """Computes the mean of squares of errors between labels and predictions. + + For example, if `y_true` is [0., 0., 1., 1.] and `y_pred` is [1., 1., 1., 0.] + then the mean squared error value is 3/4 (0.75). + + Usage: + + ```python + mse = tf.keras.losses.MeanSquaredError() + loss = mse([0., 0., 1., 1.], [1., 1., 1., 0.]) + print('Loss: ', loss.numpy()) # Loss: 0.75 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.MeanSquaredError()) + ``` + """ + + def call(self, y_true, y_pred): + """Invokes the `MeanSquaredError` instance. + + Args: + y_true: Ground truth values. + y_pred: The predicted values. + + Returns: + Mean squared error losses. + """ + y_pred = ops.convert_to_tensor(y_pred) + y_true = math_ops.cast(y_true, y_pred.dtype) + return mean_squared_error(y_true, y_pred) + + +@tf_export('keras.losses.MeanAbsoluteError') +class MeanAbsoluteError(Loss): + """Computes the mean of absolute difference between labels and predictions. + + For example, if `y_true` is [0., 0., 1., 1.] and `y_pred` is [1., 1., 1., 0.] + then the mean absolute error value is 3/4 (0.75). + + Usage: + + ```python + mae = tf.keras.losses.MeanAbsoluteError() + loss = mae([0., 0., 1., 1.], [1., 1., 1., 0.]) + print('Loss: ', loss.numpy()) # Loss: 0.75 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.MeanAbsoluteError()) + ``` + """ + + def call(self, y_true, y_pred): + """Invokes the `MeanAbsoluteError` instance. + + Args: + y_true: Ground truth values. + y_pred: The predicted values. + + Returns: + Mean absolute error losses. + """ + y_pred = ops.convert_to_tensor(y_pred) + y_true = math_ops.cast(y_true, y_pred.dtype) + return mean_absolute_error(y_true, y_pred) + + +@tf_export('keras.losses.MeanAbsolutePercentageError') +class MeanAbsolutePercentageError(Loss): + """Computes the mean absolute percentage error between `y_true` and `y_pred`. + + For example, if `y_true` is [0., 0., 1., 1.] and `y_pred` is [1., 1., 1., 0.] + then the mean absolute percentage error value is 5e+08. + + Usage: + + ```python + mape = tf.keras.losses.MeanAbsolutePercentageError() + loss = mape([0., 0., 1., 1.], [1., 1., 1., 0.]) + print('Loss: ', loss.numpy()) # Loss: 5e+08 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.MeanAbsolutePercentageError()) + ``` + """ + + def call(self, y_true, y_pred): + """Invokes the `MeanAbsolutePercentageError` instance. + + Args: + y_true: Ground truth values. + y_pred: The predicted values. + + Returns: + Mean absolute percentage error losses. + """ + y_pred = ops.convert_to_tensor(y_pred) + y_true = math_ops.cast(y_true, y_pred.dtype) + return mean_absolute_percentage_error(y_true, y_pred) + + +@tf_export('keras.losses.MeanSquaredLogarithmicError') +class MeanSquaredLogarithmicError(Loss): + """Computes the mean squared logarithmic error between `y_true` and `y_pred`. + + For example, if `y_true` is [0., 0., 1., 1.] and `y_pred` is [1., 1., 1., 0.] + then the mean squared logarithmic error value is 0.36034. + + Usage: + + ```python + msle = tf.keras.losses.MeanSquaredLogarithmicError() + loss = msle([0., 0., 1., 1.], [1., 1., 1., 0.]) + print('Loss: ', loss.numpy()) # Loss: 0.36034 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.MeanSquaredLogarithmicError()) + ``` + """ + + def call(self, y_true, y_pred): + """Invokes the `MeanSquaredLogarithmicError` instance. + + Args: + y_true: Ground truth values. + y_pred: The predicted values. + + Returns: + Mean squared logarithmic error losses. + """ + y_pred = ops.convert_to_tensor(y_pred) + y_true = math_ops.cast(y_true, y_pred.dtype) + return mean_squared_logarithmic_error(y_true, y_pred) + + +@tf_export('keras.losses.BinaryCrossentropy') +class BinaryCrossentropy(Loss): + """Computes the binary cross entropy loss between the labels and predictions. + + Usage: + + ```python + bce = tf.keras.losses.BinaryCrossentropy() + loss = bce([0., 0., 1., 1.], [1., 1., 1., 0.]) + print('Loss: ', loss.numpy()) # Loss: 12.007 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.BinaryCrossentropy()) + ```` + + Args: + from_logits: Whether `output` is expected to be a logits tensor. By default, + we consider that `output` encodes a probability distribution. + label_smoothing: If greater than `0` then smooth the labels. + reduction: Type of `tf.losses.Reduction` to apply to loss. Default value is + `SUM_OVER_BATCH_SIZE`. + name: Optional name for the op. + """ + + def __init__(self, + from_logits=False, + label_smoothing=0, + reduction=losses_impl.ReductionV2.SUM_OVER_BATCH_SIZE, + name=None): + super(BinaryCrossentropy, self).__init__(reduction=reduction, name=name) + self.from_logits = from_logits + self.label_smoothing = label_smoothing + + def call(self, y_true, y_pred): + """Invokes the `BinaryCrossentropy` instance. + + Args: + y_true: Ground truth values. + y_pred: The predicted values. + + Returns: + Binary cross entropy losses. + """ + y_pred = ops.convert_to_tensor(y_pred) + y_true = math_ops.cast(y_true, y_pred.dtype) + + if self.label_smoothing > 0: + y_true = y_true * (1 - self.label_smoothing) + 0.5 * self.label_smoothing + + return binary_crossentropy(y_true, y_pred, from_logits=self.from_logits) + + +@tf_export('keras.losses.CategoricalCrossentropy') +class CategoricalCrossentropy(Loss): + """Computes categorical cross entropy loss between the `y_true` and `y_pred`. + + Usage: + + ```python + cce = tf.keras.losses.CategoricalCrossentropy() + loss = cce( + [[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]], + [[.9, .05, .05], [.5, .89, .6], [.05, .01, .94]]) + print('Loss: ', loss.numpy()) # Loss: 0.3239 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.CategoricalCrossentropy()) + ```` + + Args: + from_logits: Whether `output` is expected to be a logits tensor. By default, + we consider that `output` encodes a probability distribution. + label_smoothing: If greater than `0` then smooth the labels. This option is + currently not supported when `y_pred` is a sparse input (not one-hot). + reduction: Type of `tf.losses.Reduction` to apply to loss. Default value is + `SUM_OVER_BATCH_SIZE`. + name: Optional name for the op. + """ + + def __init__(self, + from_logits=False, + label_smoothing=0, + reduction=losses_impl.ReductionV2.SUM_OVER_BATCH_SIZE, + name=None): + super(CategoricalCrossentropy, self).__init__( + reduction=reduction, name=name) + self.from_logits = from_logits + self.label_smoothing = label_smoothing + + def call(self, y_true, y_pred): + """Invokes the `CategoricalCrossentropy` instance. + + Args: + y_true: Ground truth values. + y_pred: The predicted values. + + Returns: + Categorical cross entropy losses. + """ + y_pred = ops.convert_to_tensor(y_pred) + y_true = ops.convert_to_tensor(y_true) + is_sparse = y_pred.shape != y_true.shape + + if is_sparse: + return sparse_categorical_crossentropy( + y_true, y_pred, from_logits=self.from_logits) + else: + y_true = math_ops.cast(y_true, y_pred.dtype) + if self.label_smoothing > 0: + num_classes = math_ops.cast(array_ops.shape(y_true)[1], y_pred.dtype) + smooth_positives = 1.0 - self.label_smoothing + smooth_negatives = self.label_smoothing / num_classes + y_true = y_true * smooth_positives + smooth_negatives + + return categorical_crossentropy( + y_true, y_pred, from_logits=self.from_logits) + + @tf_export('keras.metrics.mean_squared_error', 'keras.metrics.mse', 'keras.metrics.MSE', @@ -116,20 +482,22 @@ def logcosh(y_true, y_pred): @tf_export('keras.metrics.categorical_crossentropy', 'keras.losses.categorical_crossentropy') -def categorical_crossentropy(y_true, y_pred): - return K.categorical_crossentropy(y_true, y_pred) +def categorical_crossentropy(y_true, y_pred, from_logits=False): + return K.categorical_crossentropy(y_true, y_pred, from_logits=from_logits) @tf_export('keras.metrics.sparse_categorical_crossentropy', 'keras.losses.sparse_categorical_crossentropy') -def sparse_categorical_crossentropy(y_true, y_pred): - return K.sparse_categorical_crossentropy(y_true, y_pred) +def sparse_categorical_crossentropy(y_true, y_pred, from_logits=False): + return K.sparse_categorical_crossentropy( + y_true, y_pred, from_logits=from_logits) @tf_export('keras.metrics.binary_crossentropy', 'keras.losses.binary_crossentropy') -def binary_crossentropy(y_true, y_pred): - return K.mean(K.binary_crossentropy(y_true, y_pred), axis=-1) +def binary_crossentropy(y_true, y_pred, from_logits=False): + return K.mean( + K.binary_crossentropy(y_true, y_pred, from_logits=from_logits), axis=-1) @tf_export('keras.metrics.kullback_leibler_divergence', @@ -159,6 +527,40 @@ def cosine_proximity(y_true, y_pred): return -math_ops.reduce_sum(y_true * y_pred, axis=-1) +class CosineProximity(Loss): + """Computes the cosine distance between `y_true` and `y_pred`. + + Usage: + + ```python + cosine_loss = tf.losses.CosineProximity() + loss = cosine_loss([0., 1., 1.], [1., 0., 1.]) + print('Loss: ', loss.numpy()) # Loss: -0.5 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.losses.CosineProximity()) + ``` + """ + + def call(self, y_true, y_pred): + """Calculates the cosine proximity loss. + + Args: + y_true: Ground truth values. + y_pred: The predicted values. + + Returns: + Cosine distance loss. + """ + y_pred = ops.convert_to_tensor(y_pred) + y_true = math_ops.cast(y_true, y_pred.dtype) + return cosine_proximity(y_true, y_pred) + + # Aliases. mse = MSE = mean_squared_error @@ -197,3 +599,9 @@ def get(identifier): else: raise ValueError('Could not interpret ' 'loss function identifier:', identifier) + + +LABEL_DTYPES_FOR_LOSSES = { + losses_impl.sparse_softmax_cross_entropy: 'int32', + sparse_categorical_crossentropy: 'int32' +} diff --git a/tensorflow/python/keras/losses_test.py b/tensorflow/python/keras/losses_test.py index c7015270ac..d2791cdcd3 100644 --- a/tensorflow/python/keras/losses_test.py +++ b/tensorflow/python/keras/losses_test.py @@ -24,6 +24,11 @@ import shutil import numpy as np from tensorflow.python import keras +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops.losses import losses_impl from tensorflow.python.platform import test try: @@ -138,5 +143,633 @@ class KerasLossesTest(test.TestCase): loaded_model.predict(np.random.rand(128, 2)) +@test_util.run_all_in_graph_and_eager_modes +class MeanSquaredErrorTest(test.TestCase): + + def test_config(self): + mse_obj = keras.losses.MeanSquaredError( + reduction=losses_impl.ReductionV2.SUM, name='mse_1') + self.assertEqual(mse_obj.name, 'mse_1') + self.assertEqual(mse_obj.reduction, losses_impl.ReductionV2.SUM) + + def test_all_correct_unweighted(self): + mse_obj = keras.losses.MeanSquaredError() + y_true = constant_op.constant([4, 8, 12, 8, 1, 3], shape=(2, 3)) + loss = mse_obj(y_true, y_true) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + def test_unweighted(self): + mse_obj = keras.losses.MeanSquaredError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mse_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), 49.5, 3) + + def test_scalar_weighted(self): + mse_obj = keras.losses.MeanSquaredError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mse_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), 113.85, 3) + + def test_sample_weighted(self): + mse_obj = keras.losses.MeanSquaredError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + sample_weight = constant_op.constant([1.2, 3.4], shape=(2, 1)) + loss = mse_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 767.8 / 6, 3) + + def test_timestep_weighted(self): + mse_obj = keras.losses.MeanSquaredError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3, 1)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3, 1), + dtype=dtypes.float32) + sample_weight = constant_op.constant([3, 6, 5, 0, 4, 2], shape=(2, 3)) + loss = mse_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 587 / 6, 3) + + def test_zero_weighted(self): + mse_obj = keras.losses.MeanSquaredError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mse_obj(y_true, y_pred, sample_weight=0) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + def test_invalid_sample_weight(self): + mse_obj = keras.losses.MeanSquaredError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3, 1)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], shape=(2, 3, 1)) + sample_weight = constant_op.constant([3, 6, 5, 0], shape=(2, 2)) + with self.assertRaisesRegexp( + ValueError, r'Shapes \(2, 2\) and \(2, 3\) are incompatible'): + mse_obj(y_true, y_pred, sample_weight=sample_weight) + + def test_no_reduction(self): + mse_obj = keras.losses.MeanSquaredError( + reduction=losses_impl.ReductionV2.NONE) + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mse_obj(y_true, y_pred, sample_weight=2.3) + loss = self.evaluate(loss) + self.assertArrayNear(loss, [84.3333, 143.3666], 1e-3) + + def test_sum_reduction(self): + mse_obj = keras.losses.MeanSquaredError( + reduction=losses_impl.ReductionV2.SUM) + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mse_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), 227.69998, 3) + + +@test_util.run_all_in_graph_and_eager_modes +class MeanAbsoluteErrorTest(test.TestCase): + + def test_config(self): + mae_obj = keras.losses.MeanAbsoluteError( + reduction=losses_impl.ReductionV2.SUM, name='mae_1') + self.assertEqual(mae_obj.name, 'mae_1') + self.assertEqual(mae_obj.reduction, losses_impl.ReductionV2.SUM) + + def test_all_correct_unweighted(self): + mae_obj = keras.losses.MeanAbsoluteError() + y_true = constant_op.constant([4, 8, 12, 8, 1, 3], shape=(2, 3)) + loss = mae_obj(y_true, y_true) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + def test_unweighted(self): + mae_obj = keras.losses.MeanAbsoluteError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mae_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), 5.5, 3) + + def test_scalar_weighted(self): + mae_obj = keras.losses.MeanAbsoluteError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mae_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), 12.65, 3) + + def test_sample_weighted(self): + mae_obj = keras.losses.MeanAbsoluteError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + sample_weight = constant_op.constant([1.2, 3.4], shape=(2, 1)) + loss = mae_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 81.4 / 6, 3) + + def test_timestep_weighted(self): + mae_obj = keras.losses.MeanAbsoluteError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3, 1)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3, 1), + dtype=dtypes.float32) + sample_weight = constant_op.constant([3, 6, 5, 0, 4, 2], shape=(2, 3)) + loss = mae_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 83 / 6, 3) + + def test_zero_weighted(self): + mae_obj = keras.losses.MeanAbsoluteError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mae_obj(y_true, y_pred, sample_weight=0) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + def test_invalid_sample_weight(self): + mae_obj = keras.losses.MeanAbsoluteError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3, 1)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], shape=(2, 3, 1)) + sample_weight = constant_op.constant([3, 6, 5, 0], shape=(2, 2)) + with self.assertRaisesRegexp( + ValueError, r'Shapes \(2, 2\) and \(2, 3\) are incompatible'): + mae_obj(y_true, y_pred, sample_weight=sample_weight) + + def test_no_reduction(self): + mae_obj = keras.losses.MeanAbsoluteError( + reduction=losses_impl.ReductionV2.NONE) + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mae_obj(y_true, y_pred, sample_weight=2.3) + loss = self.evaluate(loss) + self.assertArrayNear(loss, [10.7333, 14.5666], 1e-3) + + def test_sum_reduction(self): + mae_obj = keras.losses.MeanAbsoluteError( + reduction=losses_impl.ReductionV2.SUM) + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mae_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), 25.29999, 3) + + +@test_util.run_all_in_graph_and_eager_modes +class MeanAbsolutePercentageErrorTest(test.TestCase): + + def test_config(self): + mape_obj = keras.losses.MeanAbsolutePercentageError( + reduction=losses_impl.ReductionV2.SUM, name='mape_1') + self.assertEqual(mape_obj.name, 'mape_1') + self.assertEqual(mape_obj.reduction, losses_impl.ReductionV2.SUM) + + def test_unweighted(self): + mape_obj = keras.losses.MeanAbsolutePercentageError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mape_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), 211.8518, 3) + + def test_scalar_weighted(self): + mape_obj = keras.losses.MeanAbsolutePercentageError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mape_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), 487.259, 3) + + def test_sample_weighted(self): + mape_obj = keras.losses.MeanAbsolutePercentageError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + sample_weight = constant_op.constant([1.2, 3.4], shape=(2, 1)) + loss = mape_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 422.8888, 3) + + def test_timestep_weighted(self): + mape_obj = keras.losses.MeanAbsolutePercentageError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3, 1)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3, 1), + dtype=dtypes.float32) + sample_weight = constant_op.constant([3, 6, 5, 0, 4, 2], shape=(2, 3)) + loss = mape_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 694.4445, 3) + + def test_zero_weighted(self): + mape_obj = keras.losses.MeanAbsolutePercentageError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = mape_obj(y_true, y_pred, sample_weight=0) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + +@test_util.run_all_in_graph_and_eager_modes +class MeanSquaredLogarithmicErrorTest(test.TestCase): + + def test_config(self): + msle_obj = keras.losses.MeanSquaredLogarithmicError( + reduction=losses_impl.ReductionV2.SUM, name='mape_1') + self.assertEqual(msle_obj.name, 'mape_1') + self.assertEqual(msle_obj.reduction, losses_impl.ReductionV2.SUM) + + def test_unweighted(self): + msle_obj = keras.losses.MeanSquaredLogarithmicError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = msle_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), 1.4370, 3) + + def test_scalar_weighted(self): + msle_obj = keras.losses.MeanSquaredLogarithmicError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = msle_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), 3.3051, 3) + + def test_sample_weighted(self): + msle_obj = keras.losses.MeanSquaredLogarithmicError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + sample_weight = constant_op.constant([1.2, 3.4], shape=(2, 1)) + loss = msle_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 3.7856, 3) + + def test_timestep_weighted(self): + msle_obj = keras.losses.MeanSquaredLogarithmicError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3, 1)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3, 1), + dtype=dtypes.float32) + sample_weight = constant_op.constant([3, 6, 5, 0, 4, 2], shape=(2, 3)) + loss = msle_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 2.6473, 3) + + def test_zero_weighted(self): + msle_obj = keras.losses.MeanSquaredLogarithmicError() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = msle_obj(y_true, y_pred, sample_weight=0) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + +@test_util.run_all_in_graph_and_eager_modes +class CosineProximityTest(test.TestCase): + + def test_config(self): + cosine_obj = keras.losses.CosineProximity( + reduction=losses_impl.ReductionV2.SUM, name='cosine_loss') + self.assertEqual(cosine_obj.name, 'cosine_loss') + self.assertEqual(cosine_obj.reduction, losses_impl.ReductionV2.SUM) + + def test_unweighted(self): + cosine_obj = keras.losses.CosineProximity() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = cosine_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), -0.18722, 3) + + def test_scalar_weighted(self): + cosine_obj = keras.losses.CosineProximity() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = cosine_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), -0.43060, 3) + + def test_sample_weighted(self): + cosine_obj = keras.losses.CosineProximity() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + sample_weight = constant_op.constant([1.2, 3.4], shape=(2, 1)) + loss = cosine_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 0.15599, 3) + + def test_timestep_weighted(self): + cosine_obj = keras.losses.CosineProximity() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3, 1)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3, 1), + dtype=dtypes.float32) + sample_weight = constant_op.constant([3, 6, 5, 0, 4, 2], shape=(2, 3)) + loss = cosine_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), -2.0000, 3) + + def test_zero_weighted(self): + cosine_obj = keras.losses.CosineProximity() + y_true = constant_op.constant([1, 9, 2, -5, -2, 6], shape=(2, 3)) + y_pred = constant_op.constant([4, 8, 12, 8, 1, 3], + shape=(2, 3), + dtype=dtypes.float32) + loss = cosine_obj(y_true, y_pred, sample_weight=0) + self.assertAlmostEqual(self.evaluate(loss), 0., 3) + + +@test_util.run_all_in_graph_and_eager_modes +class BinaryCrossentropyTest(test.TestCase): + + def test_config(self): + bce_obj = keras.losses.BinaryCrossentropy( + reduction=losses_impl.ReductionV2.SUM, name='bce_1') + self.assertEqual(bce_obj.name, 'bce_1') + self.assertEqual(bce_obj.reduction, losses_impl.ReductionV2.SUM) + + def test_all_correct_unweighted(self): + y_true = constant_op.constant([[1, 0, 0], [0, 1, 0], [0, 0, 1]], + dtype=dtypes.float32) + bce_obj = keras.losses.BinaryCrossentropy() + loss = bce_obj(y_true, y_true) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + # Test with logits. + logits = constant_op.constant([[100.0, -100.0, -100.0], + [-100.0, 100.0, -100.0], + [-100.0, -100.0, 100.0]]) + bce_obj = keras.losses.BinaryCrossentropy(from_logits=True) + loss = bce_obj(y_true, logits) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + def test_unweighted(self): + bce_obj = keras.losses.BinaryCrossentropy() + y_true = constant_op.constant([1, 0, 1, 0, 0, 1], shape=(2, 3)) + y_pred = constant_op.constant([1, 1, 1, 0, 1, 0], + shape=(2, 3), + dtype=dtypes.float32) + loss = bce_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), 8.0004, 3) + + # Test with logits. + logits = constant_op.constant([10., 10., 10., -10., 10, -10], + shape=(2, 3), + dtype=dtypes.float32) + bce_obj = keras.losses.BinaryCrossentropy(from_logits=True) + loss = bce_obj(y_true, logits) + self.assertAlmostEqual(self.evaluate(loss), 5., 3) + + def test_scalar_weighted(self): + bce_obj = keras.losses.BinaryCrossentropy() + y_true = constant_op.constant([1, 0, 1, 0, 0, 1], shape=(2, 3)) + y_pred = constant_op.constant([1, 1, 1, 0, 1, 0], + shape=(2, 3), + dtype=dtypes.float32) + loss = bce_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), 18.4010, 3) + + # Test with logits. + y_true = array_ops.ones((32, 1)) + logits = array_ops.ones((32, 1), dtype=dtypes.float32) + bce_obj = keras.losses.BinaryCrossentropy(from_logits=True) + loss = bce_obj(y_true, logits, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), 0.7205, 3) + + def test_sample_weighted(self): + bce_obj = keras.losses.BinaryCrossentropy() + y_true = constant_op.constant([1, 0, 1, 0, 0, 1], shape=(2, 3)) + y_pred = constant_op.constant([1, 1, 1, 0, 1, 0], + shape=(2, 3), + dtype=dtypes.float64) + sample_weight = constant_op.constant([1.2, 3.4], shape=(2, 1)) + loss = bce_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 21.4907, 3) + + # Test with logits. + y_true = constant_op.constant([[0, 0, 1], [1, 0, 0], [0, 1, 0]]) + logits = constant_op.constant( + [[100.0, -100.0, -100.0], [-100.0, 100.0, -100.0], + [-100.0, -100.0, 100.0]], + dtype=dtypes.float64) + weights = constant_op.constant([3, 2, 8]) + bce_obj = keras.losses.BinaryCrossentropy(from_logits=True) + loss = bce_obj(y_true, logits, sample_weight=weights) + self.assertAlmostEqual(self.evaluate(loss), 288.8888, 3) + + def test_no_reduction(self): + y_true = constant_op.constant(((1, 0, 1), (1, 1, 0), (0, 1, 1))) + logits = constant_op.constant(((100.0, -100.0, 100.0), + (100.0, -100.0, 100.0), + (100.0, 100.0, -100.0))) + bce_obj = keras.losses.BinaryCrossentropy( + from_logits=True, reduction=losses_impl.ReductionV2.NONE) + loss = bce_obj(y_true, logits) + self.assertAllClose((0., 66.6666, 66.6666), self.evaluate(loss), 3) + + def test_label_smoothing(self): + logits = constant_op.constant([[100.0, -100.0, -100.0]]) + y_true = constant_op.constant([[1, 0, 1]]) + label_smoothing = 0.1 + # Loss: max(x, 0) - x * z + log(1 + exp(-abs(x))) + # Label smoothing: z' = z * (1 - L) + 0.5L + # 1 = 1 - 0.5L + # 0 = 0.5L + # Applying the above two fns to the given input: + # (100 - 100 * (1 - 0.5 L) + 0 + + # 0 + 100 * (0.5 L) + 0 + + # 0 + 100 * (1 - 0.5 L) + 0) * (1/3) + # = (100 + 50L) * 1/3 + bce_obj = keras.losses.BinaryCrossentropy( + from_logits=True, label_smoothing=label_smoothing) + loss = bce_obj(y_true, logits) + expected_value = (100.0 + 50.0 * label_smoothing) / 3.0 + self.assertAlmostEqual(self.evaluate(loss), expected_value, 3) + + +@test_util.run_all_in_graph_and_eager_modes +class CategoricalCrossentropyTest(test.TestCase): + + def test_config(self): + cce_obj = keras.losses.CategoricalCrossentropy( + reduction=losses_impl.ReductionV2.SUM, name='bce_1') + self.assertEqual(cce_obj.name, 'bce_1') + self.assertEqual(cce_obj.reduction, losses_impl.ReductionV2.SUM) + + def test_all_correct_unweighted(self): + y_true = constant_op.constant([[1, 0, 0], [0, 1, 0], [0, 0, 1]], + dtype=dtypes.int64) + y_pred = constant_op.constant([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]], + dtype=dtypes.float32) + cce_obj = keras.losses.CategoricalCrossentropy() + loss = cce_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + # Test with logits. + logits = constant_op.constant([[10., 0., 0.], [0., 10., 0.], [0., 0., 10.]]) + cce_obj = keras.losses.CategoricalCrossentropy(from_logits=True) + loss = cce_obj(y_true, logits) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + def test_unweighted(self): + cce_obj = keras.losses.CategoricalCrossentropy() + y_true = constant_op.constant([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + y_pred = constant_op.constant( + [[.9, .05, .05], [.5, .89, .6], [.05, .01, .94]], dtype=dtypes.float32) + loss = cce_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), .3239, 3) + + # Test with logits. + logits = constant_op.constant([[8., 1., 1.], [0., 9., 1.], [2., 3., 5.]]) + cce_obj = keras.losses.CategoricalCrossentropy(from_logits=True) + loss = cce_obj(y_true, logits) + self.assertAlmostEqual(self.evaluate(loss), .0573, 3) + + def test_scalar_weighted(self): + cce_obj = keras.losses.CategoricalCrossentropy() + y_true = constant_op.constant([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + y_pred = constant_op.constant( + [[.9, .05, .05], [.5, .89, .6], [.05, .01, .94]], dtype=dtypes.float32) + loss = cce_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), .7449, 3) + + # Test with logits. + logits = constant_op.constant([[8., 1., 1.], [0., 9., 1.], [2., 3., 5.]]) + cce_obj = keras.losses.CategoricalCrossentropy(from_logits=True) + loss = cce_obj(y_true, logits, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), .1317, 3) + + def test_sample_weighted(self): + cce_obj = keras.losses.CategoricalCrossentropy() + y_true = constant_op.constant([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + y_pred = constant_op.constant( + [[.9, .05, .05], [.5, .89, .6], [.05, .01, .94]], dtype=dtypes.float32) + sample_weight = constant_op.constant([[1.2], [3.4], [5.6]], shape=(3, 1)) + loss = cce_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 1.0696, 3) + + # Test with logits. + logits = constant_op.constant([[8., 1., 1.], [0., 9., 1.], [2., 3., 5.]]) + cce_obj = keras.losses.CategoricalCrossentropy(from_logits=True) + loss = cce_obj(y_true, logits, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 0.31829, 3) + + def test_no_reduction(self): + y_true = constant_op.constant([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + logits = constant_op.constant([[8., 1., 1.], [0., 9., 1.], [2., 3., 5.]]) + cce_obj = keras.losses.CategoricalCrossentropy( + from_logits=True, reduction=losses_impl.ReductionV2.NONE) + loss = cce_obj(y_true, logits) + self.assertAllClose((0.001822, 0.000459, 0.169846), self.evaluate(loss), 3) + + def test_label_smoothing(self): + logits = constant_op.constant([[100.0, -100.0, -100.0]]) + y_true = constant_op.constant([[1, 0, 0]]) + label_smoothing = 0.1 + # Softmax Cross Entropy Loss: -\sum_i p_i \log q_i + # where for a softmax activation + # \log q_i = x_i - \log \sum_j \exp x_j + # = x_i - x_max - \log \sum_j \exp (x_j - x_max) + # For our activations, [100, -100, -100] + # \log ( exp(0) + exp(-200) + exp(-200) ) = 0 + # so our log softmaxes become: [0, -200, -200] + # Label smoothing: z' = z * (1 - L) + L/n + # 1 = 1 - L + L/n + # 0 = L/n + # Applying the above two fns to the given input: + # -0 * (1 - L + L/n) + 200 * L/n + 200 * L/n = 400 L/n + cce_obj = keras.losses.CategoricalCrossentropy( + from_logits=True, label_smoothing=label_smoothing) + loss = cce_obj(y_true, logits) + expected_value = 400.0 * label_smoothing / 3.0 + self.assertAlmostEqual(self.evaluate(loss), expected_value, 3) + + def test_all_correct_unweighted_sparse(self): + y_true = constant_op.constant([[0], [1], [2]], dtype=dtypes.int64) + y_pred = constant_op.constant([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]], + dtype=dtypes.float32) + cce_obj = keras.losses.CategoricalCrossentropy() + loss = cce_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + # Test with logits. + logits = constant_op.constant([[10., 0., 0.], [0., 10., 0.], [0., 0., 10.]]) + cce_obj = keras.losses.CategoricalCrossentropy(from_logits=True) + loss = cce_obj(y_true, logits) + self.assertAlmostEqual(self.evaluate(loss), 0.0, 3) + + def test_unweighted_sparse(self): + cce_obj = keras.losses.CategoricalCrossentropy() + y_true = constant_op.constant([0, 1, 2]) + y_pred = constant_op.constant( + [[.9, .05, .05], [.5, .89, .6], [.05, .01, .94]], dtype=dtypes.float32) + loss = cce_obj(y_true, y_pred) + self.assertAlmostEqual(self.evaluate(loss), .3239, 3) + + # Test with logits. + logits = constant_op.constant([[8., 1., 1.], [0., 9., 1.], [2., 3., 5.]]) + cce_obj = keras.losses.CategoricalCrossentropy(from_logits=True) + loss = cce_obj(y_true, logits) + self.assertAlmostEqual(self.evaluate(loss), .0573, 3) + + def test_scalar_weighted_sparse(self): + cce_obj = keras.losses.CategoricalCrossentropy() + y_true = constant_op.constant([[0], [1], [2]]) + y_pred = constant_op.constant( + [[.9, .05, .05], [.5, .89, .6], [.05, .01, .94]], dtype=dtypes.float32) + loss = cce_obj(y_true, y_pred, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), .7449, 3) + + # Test with logits. + logits = constant_op.constant([[8., 1., 1.], [0., 9., 1.], [2., 3., 5.]]) + cce_obj = keras.losses.CategoricalCrossentropy(from_logits=True) + loss = cce_obj(y_true, logits, sample_weight=2.3) + self.assertAlmostEqual(self.evaluate(loss), .1317, 3) + + def test_sample_weighted_sparse(self): + cce_obj = keras.losses.CategoricalCrossentropy() + y_true = constant_op.constant([[0], [1], [2]]) + y_pred = constant_op.constant( + [[.9, .05, .05], [.5, .89, .6], [.05, .01, .94]], dtype=dtypes.float32) + sample_weight = constant_op.constant([[1.2], [3.4], [5.6]], shape=(3, 1)) + loss = cce_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 1.0696, 3) + + # Test with logits. + logits = constant_op.constant([[8., 1., 1.], [0., 9., 1.], [2., 3., 5.]]) + cce_obj = keras.losses.CategoricalCrossentropy(from_logits=True) + loss = cce_obj(y_true, logits, sample_weight=sample_weight) + self.assertAlmostEqual(self.evaluate(loss), 0.31829, 3) + + def test_no_reduction_sparse(self): + y_true = constant_op.constant([[0], [1], [2]]) + logits = constant_op.constant([[8., 1., 1.], [0., 9., 1.], [2., 3., 5.]]) + cce_obj = keras.losses.CategoricalCrossentropy( + from_logits=True, reduction=losses_impl.ReductionV2.NONE) + loss = cce_obj(y_true, logits) + self.assertAllClose((0.001822, 0.000459, 0.169846), self.evaluate(loss), 3) + + if __name__ == '__main__': test.main() diff --git a/tensorflow/python/keras/metrics.py b/tensorflow/python/keras/metrics.py index 2ea6405597..3c2682e4c6 100644 --- a/tensorflow/python/keras/metrics.py +++ b/tensorflow/python/keras/metrics.py @@ -24,9 +24,10 @@ import functools import sys import types import weakref +from enum import Enum +import numpy as np import six -from tensorflow.python.compat import compat from tensorflow.python.eager import context from tensorflow.python.eager import function from tensorflow.python.framework import dtypes @@ -48,8 +49,10 @@ from tensorflow.python.keras.losses import sparse_categorical_crossentropy from tensorflow.python.keras.losses import squared_hinge from tensorflow.python.keras.utils.generic_utils import deserialize_keras_object from tensorflow.python.keras.utils.generic_utils import serialize_keras_object +from tensorflow.python.keras.utils.generic_utils import to_list +from tensorflow.python.keras.utils.losses_utils import squeeze_or_expand_dimensions from tensorflow.python.ops import array_ops -from tensorflow.python.ops import confusion_matrix +from tensorflow.python.ops import check_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import init_ops from tensorflow.python.ops import math_ops @@ -63,13 +66,6 @@ from tensorflow.python.util.tf_export import tf_export from tensorflow.tools.docs import doc_controls -def check_is_tensor_or_operation(x, name): - """Raises type error if the given input is not a tensor or operation.""" - if not (isinstance(x, ops.Tensor) or isinstance(x, ops.Operation)): - raise TypeError('{0} must be a Tensor or Operation, given: {1}'.format( - name, x)) - - def clone_metric(metric): """Returns a clone of the metric if stateful, otherwise returns it as is.""" if isinstance(metric, Metric): @@ -102,8 +98,6 @@ def update_state_wrapper(update_state_fn): update_op = update_state_fn(*args, **kwargs) if update_op is not None: # update_op will be None in eager execution. metric_obj.add_update(update_op, inputs=True) - check_is_tensor_or_operation( - update_op, 'Metric {0}\'s update'.format(metric_obj.name)) return update_op return tf_decorator.make_decorator(update_state_fn, decorated) @@ -128,7 +122,7 @@ def result_wrapper(result_fn): `merge_call()`. """ - def decorated(metric_obj, *args): + def decorated(_, *args): """Decorated function with merge_call.""" replica_context = distribution_strategy_context.get_replica_context() if replica_context is None: # if in cross replica context already @@ -147,9 +141,8 @@ def result_wrapper(result_fn): # Wrapping result in merge_call. merge_call is used when we want to leave # replica mode and compute a value in cross replica mode. - result_t = replica_context.merge_call(merge_fn_wrapper, result_fn, *args) - check_is_tensor_or_operation(result_t, - 'Metric {0}\'s result'.format(metric_obj.name)) + result_t = replica_context.merge_call( + merge_fn_wrapper, args=(result_fn,) + args) return result_t return tf_decorator.make_decorator(result_fn, decorated) @@ -170,108 +163,169 @@ def weakmethod(method): return inner -def safe_div(numerator, denominator): - """Computes a safe divide which returns 0 if the denominator is zero. +class _ConfusionMatrix(Enum): + TRUE_POSITIVES = 'tp' + FALSE_POSITIVES = 'fp' + TRUE_NEGATIVES = 'tn' + FALSE_NEGATIVES = 'fn' - Note that the function contains an additional conditional check that is - necessary for avoiding situations where the loss is zero causing NaNs to - creep into the gradient computation. - Args: - numerator: An arbitrary `Tensor`. - denominator: A `Tensor` whose shape matches `numerator` and whose values are - assumed to be non-negative. +def _assert_thresholds_range(thresholds): + invalid_thresholds = [t for t in thresholds if t < 0 or t > 1] + if any(invalid_thresholds): + raise ValueError('Threshold values must be in [0, 1]. Invalid values: {}' + .format(invalid_thresholds)) - Returns: - The element-wise value of the numerator divided by the denominator. - """ - if compat.forward_compatible(2018, 11, 1): - return math_ops.div_no_nan(numerator, denominator) - return array_ops.where( - math_ops.greater(denominator, 0), - math_ops.div(numerator, - array_ops.where( - math_ops.equal(denominator, 0), - array_ops.ones_like(denominator), denominator)), - array_ops.zeros_like(numerator)) +def _update_confusion_matrix_variables(variables_to_update, + y_true, + y_pred, + thresholds, + sample_weight=None): + """Returns op to update the given confusion matrix variables. + + For every pair of values in y_true and y_pred: -def squeeze_or_expand_dimensions(y_pred, y_true, sample_weight): - """Squeeze or expand last dimension if needed. + true_positive: y_true == True and y_pred > thresholds + false_negatives: y_true == True and y_pred <= thresholds + true_negatives: y_true == False and y_pred <= thresholds + false_positive: y_true == False and y_pred > thresholds - 1. Squeezes last dim of `y_pred` or `y_true` if their rank differs by 1 - (using `confusion_matrix.remove_squeezable_dimensions`). - 2. Squeezes or expands last dim of `sample_weight` if its rank differs by 1 - from the new rank of `y_pred`. - If `sample_weight` is scalar, it is kept scalar. + The results will be weighted and added together. When multiple thresholds are + provided, we will repeat the same for every threshold. - This will use static shape if available. Otherwise, it will add graph - operations, which could result in a performance hit. + For estimation of these metrics over a stream of data, the function creates an + `update_op` operation that updates the given variables. + + If `sample_weight` is `None`, weights default to 1. + Use weights of 0 to mask values. Args: - y_pred: Predicted values, a `Tensor` of arbitrary dimensions. - y_true: Optional label `Tensor` whose dimensions match `y_pred`. - sample_weight: Optional weight scalar or `Tensor` whose dimensions match - `y_pred`. + variables_to_update: Dictionary with 'tp', 'fn', 'tn', 'fp' as valid keys + and corresponding variables to update as values. + y_true: A `Tensor` whose shape matches `y_pred`. Will be cast to `bool`. + y_pred: A floating point `Tensor` of arbitrary shape and whose values are in + the range `[0, 1]`. + thresholds: A float value or a python list or tuple of float thresholds in + `[0, 1]`. + sample_weight: Optional `Tensor` whose rank is either 0, or the same rank as + `y_true`, and must be broadcastable to `y_true` (i.e., all dimensions must + be either `1`, or the same as the corresponding `y_true` dimension). Returns: - Tuple of `y_pred`, `y_true` and `sample_weight`. Each of them possibly has - the last dimension squeezed, - `sample_weight` could be extended by one dimension. + Update op. + + Raises: + ValueError: If `y_pred` and `y_true` have mismatched shapes, or if + `sample_weight` is not `None` and its shape doesn't match `y_pred`, or if + `variables_to_update` contains invalid keys. """ - if y_true is not None: - # squeeze last dim of `y_pred` or `y_true` if their rank differs by 1 - y_true, y_pred = confusion_matrix.remove_squeezable_dimensions( - y_true, y_pred) - - if sample_weight is None: - return y_pred, y_true, None - - sample_weight = ops.convert_to_tensor(sample_weight) - weights_shape = sample_weight.get_shape() - weights_rank = weights_shape.ndims - if weights_rank == 0: # If weights is scalar, do nothing. - return y_pred, y_true, sample_weight - - y_pred_shape = y_pred.get_shape() - y_pred_rank = y_pred_shape.ndims - if (y_pred_rank is not None) and (weights_rank is not None): - # Use static rank. - if weights_rank - y_pred_rank == 1: - sample_weight = array_ops.squeeze(sample_weight, [-1]) - elif y_pred_rank - weights_rank == 1: - sample_weight = array_ops.expand_dims(sample_weight, [-1]) - return y_pred, y_true, sample_weight - - # Use dynamic rank. - weights_rank_tensor = array_ops.rank(sample_weight) - rank_diff = weights_rank_tensor - array_ops.rank(y_pred) - maybe_squeeze_weights = lambda: array_ops.squeeze(sample_weight, [-1]) - - def _maybe_expand_weights(): - return control_flow_ops.cond( - math_ops.equal(rank_diff, - -1), lambda: array_ops.expand_dims(sample_weight, [-1]), - lambda: sample_weight) - - def _maybe_adjust_weights(): - return control_flow_ops.cond( - math_ops.equal(rank_diff, 1), maybe_squeeze_weights, - _maybe_expand_weights) - - # squeeze or expand last dim of `sample_weight` if its rank differs by 1 - # from the new rank of `y_pred`. - sample_weight = control_flow_ops.cond( - math_ops.equal(weights_rank_tensor, 0), lambda: sample_weight, - _maybe_adjust_weights) - return y_pred, y_true, sample_weight + if variables_to_update is None: + return + y_true = ops.convert_to_tensor(y_true) + y_pred = ops.convert_to_tensor(y_pred) + y_pred.shape.assert_is_compatible_with(y_true.shape) + + if not any( + key for key in variables_to_update if key in list(_ConfusionMatrix)): + raise ValueError( + 'Please provide at least one valid confusion matrix ' + 'variable to update. Valid variable key options are: "{}". ' + 'Received: "{}"'.format( + list(_ConfusionMatrix), variables_to_update.keys())) + + invalid_keys = [ + key for key in variables_to_update if key not in list(_ConfusionMatrix) + ] + if invalid_keys: + raise ValueError( + 'Invalid keys: {}. Valid variable key options are: "{}"'.format( + invalid_keys, list(_ConfusionMatrix))) + + with ops.control_dependencies([ + check_ops.assert_greater_equal( + y_pred, + math_ops.cast(0.0, dtype=y_pred.dtype), + message='predictions must be >= 0'), + check_ops.assert_less_equal( + y_pred, + math_ops.cast(1.0, dtype=y_pred.dtype), + message='predictions must be <= 1') + ]): + y_pred, y_true, sample_weight = squeeze_or_expand_dimensions( + math_ops.cast(y_pred, dtype=dtypes.float32), + math_ops.cast(y_true, dtype=dtypes.bool), sample_weight) + + thresholds = to_list(thresholds) + num_thresholds = len(thresholds) + num_predictions = array_ops.size(y_pred) + + # Reshape predictions and labels. + predictions_2d = array_ops.reshape(y_pred, [1, -1]) + labels_2d = array_ops.reshape( + math_ops.cast(y_true, dtype=dtypes.bool), [1, -1]) + + # Tile the thresholds for every prediction. + thresh_tiled = array_ops.tile( + array_ops.expand_dims(array_ops.constant(thresholds), 1), + array_ops.stack([1, num_predictions])) + + # Tile the predictions for every threshold. + preds_tiled = array_ops.tile(predictions_2d, [num_thresholds, 1]) + + # Compare predictions and threshold. + pred_is_pos = math_ops.greater(preds_tiled, thresh_tiled) + + # Tile labels by number of thresholds + label_is_pos = array_ops.tile(labels_2d, [num_thresholds, 1]) + + if sample_weight is not None: + weights = weights_broadcast_ops.broadcast_weights( + math_ops.cast(sample_weight, dtype=dtypes.float32), y_pred) + weights_tiled = array_ops.tile( + array_ops.reshape(weights, [1, -1]), [num_thresholds, 1]) + else: + weights_tiled = None + + update_ops = [] + + def weighted_assign_add(label, pred, weights, var): + label_and_pred = math_ops.cast( + math_ops.logical_and(label, pred), dtype=dtypes.float32) + if weights is not None: + label_and_pred *= weights + return state_ops.assign_add(var, math_ops.reduce_sum(label_and_pred, 1)) + + loop_vars = { + _ConfusionMatrix.TRUE_POSITIVES: (label_is_pos, pred_is_pos), + } + update_tn = _ConfusionMatrix.TRUE_NEGATIVES in variables_to_update + update_fp = _ConfusionMatrix.FALSE_POSITIVES in variables_to_update + update_fn = _ConfusionMatrix.FALSE_NEGATIVES in variables_to_update + + if update_fn or update_tn: + pred_is_neg = math_ops.logical_not(pred_is_pos) + loop_vars[_ConfusionMatrix.FALSE_NEGATIVES] = (label_is_pos, pred_is_neg) + + if update_fp or update_tn: + label_is_neg = math_ops.logical_not(label_is_pos) + loop_vars[_ConfusionMatrix.FALSE_POSITIVES] = (label_is_neg, pred_is_pos) + if update_tn: + loop_vars[_ConfusionMatrix.TRUE_NEGATIVES] = (label_is_neg, pred_is_neg) + + for matrix_cond, (label, pred) in loop_vars.items(): + if matrix_cond in variables_to_update: + update_ops.append( + weighted_assign_add(label, pred, weights_tiled, + variables_to_update[matrix_cond])) + return control_flow_ops.group(update_ops) @six.add_metaclass(abc.ABCMeta) class Metric(Layer): """Encapsulates metric logic and state. - Usage with eager execution: + Usage: ```python m = SomeMetric(...) @@ -280,19 +334,6 @@ class Metric(Layer): print('Final result: ', m.result().numpy()) ``` - Usage with graph execution: - - ```python - m = SomeMetric(...) - init_op = tf.variables_initializer(m.variables) # Initialize variables - with tf.Session() as sess: - sess.run(init_op) - for input in ...: - update_op = m.update_state(input) - sess.run(update_op) - print('Final result: ', sess.run(m.result())) - ``` - Usage with tf.keras API: ```python @@ -388,9 +429,20 @@ class Metric(Layer): Returns: The metric value tensor. """ - update_op = self.update_state(*args, **kwargs) # pylint: disable=not-callable + update_op = self.update_state(*args, **kwargs) with ops.control_dependencies([update_op]): - return self.result() # pylint: disable=not-callable + result_t = self.result() + + # We are adding the metric object as metadata on the result tensor. + # This is required when we want to use a metric with `add_metric` API on + # a Model/Layer in graph mode. This metric instance will later be used + # to reset variable state after each epoch of training. + # Example: + # model = Model() + # model.add_metric(Mean()(values), name='mean') + if not context.executing_eagerly(): + result_t._metric_obj = self # pylint: disable=protected-access + return result_t def reset_states(self): """Resets all of the metric state variables. @@ -459,15 +511,35 @@ class Metric(Layer): ### End: For use by subclasses ### +@tf_export('metrics.Mean', 'keras.metrics.Mean') class Mean(Metric): """Computes the (weighted) mean of the given values. + For example, if values is [1, 3, 5, 7] then the mean is 4. + If the weights were specified as [1, 1, 0, 0] then the mean would be 2. + This metric creates two variables, `total` and `count` that are used to compute the average of `values`. This average is ultimately returned as `mean` which is an idempotent operation that simply divides `total` by `count`. If `sample_weight` is `None`, weights default to 1. Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.Mean() + m.update_state([1, 3, 5, 7]) + print('Final result: ', m.result().numpy()) # Final result: 4.0 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.add_metric(metrics_module.Mean(name='mean_1')(outputs)) + model.compile('sgd', loss='mse') + ``` """ def __init__(self, name='mean', dtype=None): @@ -525,11 +597,10 @@ class Mean(Metric): # updated. update_total_op = state_ops.assign_add(self.total, values) with ops.control_dependencies([update_total_op]): - update_count_op = state_ops.assign_add(self.count, num_values) - return ops.convert_to_tensor(update_count_op) + return state_ops.assign_add(self.count, num_values) def result(self): - return safe_div(self.total, self.count) + return math_ops.div_no_nan(self.total, self.count) class MeanMetricWrapper(Mean): @@ -574,14 +645,62 @@ class MeanMetricWrapper(Mean): matches, sample_weight=sample_weight) def get_config(self): - config = self._fn_kwargs + config = {'fn': self._fn} + config.update(self._fn_kwargs) base_config = super(MeanMetricWrapper, self).get_config() return dict(list(base_config.items()) + list(config.items())) +@tf_export('metrics.Accuracy', 'keras.metrics.Accuracy') +class Accuracy(MeanMetricWrapper): + """Calculates how often predictions matches labels. + + For example, if `y_true` is [1, 2, 3, 4] and `y_pred` is [0, 2, 3, 4] + then the accuracy is 3/4 or .75. If the weights were specified as + [1, 1, 0, 0] then the accuracy would be 1/2 or .5. + + This metric creates two local variables, `total` and `count` that are used to + compute the frequency with which `y_pred` matches `y_true`. This frequency is + ultimately returned as `binary accuracy`: an idempotent operation that simply + divides `total` by `count`. + + If `sample_weight` is `None`, weights default to 1. + Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.Accuracy() + m.update_state([1, 2, 3, 4], [0, 2, 3, 4]) + print('Final result: ', m.result().numpy()) # Final result: 0.75 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss='mse', metrics=[tf.metrics.Accuracy()]) + ``` + """ + + def __init__(self, name='accuracy', dtype=None): + super(Accuracy, self).__init__(accuracy, name, dtype=dtype) + + @classmethod + def from_config(cls, config): + if 'fn' in config: + config.pop('fn') + return super(Accuracy, cls).from_config(config) + + +@tf_export('metrics.BinaryAccuracy', 'keras.metrics.BinaryAccuracy') class BinaryAccuracy(MeanMetricWrapper): """Calculates how often predictions matches labels. + For example, if `y_true` is [1, 1, 0, 0] and `y_pred` is [0.98, 1, 0, 0.6] + then the binary accuracy is 3/4 or .75. If the weights were specified as + [1, 0, 0, 1] then the binary accuracy would be 1/2 or .5. + This metric creates two local variables, `total` and `count` that are used to compute the frequency with which `y_pred` matches `y_true`. This frequency is ultimately returned as `binary accuracy`: an idempotent operation that simply @@ -589,6 +708,21 @@ class BinaryAccuracy(MeanMetricWrapper): If `sample_weight` is `None`, weights default to 1. Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.BinaryAccuracy() + m.update_state([1, 1, 0, 0], [0.98, 1, 0, 0.6]) + print('Final result: ', m.result().numpy()) # Final result: 0.75 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss='mse', metrics=[tf.metrics.BinaryAccuracy()]) + ``` """ def __init__(self, name='binary_accuracy', dtype=None, threshold=0.5): @@ -603,17 +737,48 @@ class BinaryAccuracy(MeanMetricWrapper): super(BinaryAccuracy, self).__init__( binary_accuracy, name, dtype=dtype, threshold=threshold) + @classmethod + def from_config(cls, config): + if 'fn' in config: + config.pop('fn') + return super(BinaryAccuracy, cls).from_config(config) + +@tf_export( + 'metrics.CategoricalAccuracy', 'keras.metrics.CategoricalAccuracy') class CategoricalAccuracy(MeanMetricWrapper): """Calculates how often predictions matches labels. + For example, if `y_true` is [[0, 0, 1], [0, 1, 0]] and `y_pred` is + [[0.1, 0.9, 0.8], [0.05, 0.95, 0]] then the categorical accuracy is 1/2 or .5. + If the weights were specified as [0.7, 0.3] then the categorical accuracy + would be .3. + This metric creates two local variables, `total` and `count` that are used to compute the frequency with which `y_pred` matches `y_true`. This frequency is ultimately returned as `categorical accuracy`: an idempotent operation that simply divides `total` by `count`. + `y_pred` and `y_true` should be passed in as vectors of probabilities, rather + than as labels. If necessary, use `tf.one_hot` to expand `y_true` as a vector. + If `sample_weight` is `None`, weights default to 1. Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.CategoricalAccuracy() + m.update_state([[0, 0, 1], [0, 1, 0]], [[0.1, 0.9, 0.8], [0.05, 0.95, 0]]) + print('Final result: ', m.result().numpy()) # Final result: 0.5 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss='mse', metrics=[tf.metrics.CategoricalAccuracy()]) + ``` """ def __init__(self, name='categorical_accuracy', dtype=None): @@ -626,10 +791,24 @@ class CategoricalAccuracy(MeanMetricWrapper): super(CategoricalAccuracy, self).__init__( categorical_accuracy, name, dtype=dtype) + @classmethod + def from_config(cls, config): + if 'fn' in config: + config.pop('fn') + return super(CategoricalAccuracy, cls).from_config(config) + +@tf_export( + 'metrics.SparseCategoricalAccuracy', + 'keras.metrics.SparseCategoricalAccuracy') class SparseCategoricalAccuracy(MeanMetricWrapper): """Calculates how often predictions matches integer labels. + For example, if `y_true` is [[2], [1]] and `y_pred` is + [[0.1, 0.9, 0.8], [0.05, 0.95, 0]] then the categorical accuracy is 1/2 or .5. + If the weights were specified as [0.7, 0.3] then the categorical accuracy + would be .3. + This metric creates two local variables, `total` and `count` that are used to compute the frequency with which `y_pred` matches `y_true`. This frequency is ultimately returned as `sparse categorical accuracy`: an idempotent operation @@ -637,12 +816,710 @@ class SparseCategoricalAccuracy(MeanMetricWrapper): If `sample_weight` is `None`, weights default to 1. Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.SparseCategoricalAccuracy() + m.update_state([[2], [1]], [[0.1, 0.9, 0.8], [0.05, 0.95, 0]]) + print('Final result: ', m.result().numpy()) # Final result: 0.5 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile( + 'sgd', + loss='mse', + metrics=[tf.metrics.SparseCategoricalAccuracy()]) + ``` """ def __init__(self, name='sparse_categorical_accuracy', dtype=None): super(SparseCategoricalAccuracy, self).__init__( sparse_categorical_accuracy, name, dtype=dtype) + @classmethod + def from_config(cls, config): + if 'fn' in config: + config.pop('fn') + return super(SparseCategoricalAccuracy, cls).from_config(config) + + +class _ConfusionMatrixConditionCount(Metric): + """Calculates the number of the given confusion matrix condition.""" + + def __init__(self, + confusion_matrix_cond, + thresholds=None, + name=None, + dtype=None): + """Creates a `_ConfusionMatrixConditionCount` instance. + + Args: + confusion_matrix_cond: One of `_ConfusionMatrix` conditions. + thresholds: (Optional) Defaults to 0.5. A float value or a python + list/tuple of float threshold values in [0, 1]. A threshold is compared + with prediction values to determine the truth value of predictions + (i.e., above the threshold is `true`, below is `false`). One metric + value is generated for each threshold value. + name: (Optional) string name of the metric instance. + dtype: (Optional) data type of the metric result. + """ + super(_ConfusionMatrixConditionCount, self).__init__(name=name, dtype=dtype) + self._confusion_matrix_cond = confusion_matrix_cond + self.thresholds = 0.5 if thresholds is None else thresholds + thresholds = to_list(thresholds) + _assert_thresholds_range(thresholds) + self.accumulator = self.add_weight( + 'accumulator', + shape=(len(thresholds),), + initializer=init_ops.zeros_initializer) + + def update_state(self, y_true, y_pred, sample_weight=None): + """Accumulates the given confusion matrix condition statistics. + + Args: + y_true: The ground truth values. + y_pred: The predicted values. + sample_weight: Optional weighting of each example. Defaults to 1. Can be a + `Tensor` whose rank is either 0, or the same rank as `y_true`, and must + be broadcastable to `y_true`. + + Returns: + Update op. + """ + return _update_confusion_matrix_variables({ + self._confusion_matrix_cond: self.accumulator + }, y_true, y_pred, self.thresholds, sample_weight) + + def result(self): + if isinstance(self.thresholds, (list, tuple)): + result = self.accumulator + else: + result = self.accumulator[0] + return ops.convert_to_tensor(result) + + def reset_states(self): + num_thresholds = len(to_list(self.thresholds)) + for v in self.variables: + K.set_value(v, np.zeros((num_thresholds,))) + + +@tf_export('metrics.FalsePositives', 'keras.metrics.FalsePositives') +class FalsePositives(_ConfusionMatrixConditionCount): + """Calculates the number of false positives. + + For example, if `y_true` is [0, 1, 0, 0] and `y_pred` is [0, 0, 1, 1] + then the false positives value is 2. If the weights were specified as + [0, 0, 1, 0] then the false positives value would be 1. + + If `sample_weight` is given, calculates the sum of the weights of + false positives. This metric creates one local variable, `accumulator` + that is used to keep track of the number of false positives. + + If `sample_weight` is `None`, weights default to 1. + Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.FalsePositives() + m.update_state([0, 1, 0, 0], [0, 0, 1, 1]) + print('Final result: ', m.result().numpy()) # Final result: 2 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss='mse', metrics=[tf.metrics.FalsePositives()]) + ``` + """ + + def __init__(self, thresholds=None, name=None, dtype=None): + """Creates a `FalsePositives` instance. + + Args: + thresholds: (Optional) Defaults to 0.5. A float value or a python + list/tuple of float threshold values in [0, 1]. A threshold is compared + with prediction values to determine the truth value of predictions + (i.e., above the threshold is `true`, below is `false`). One metric + value is generated for each threshold value. + name: (Optional) string name of the metric instance. + dtype: (Optional) data type of the metric result. + """ + super(FalsePositives, self).__init__( + confusion_matrix_cond=_ConfusionMatrix.FALSE_POSITIVES, + thresholds=thresholds, + name=name, + dtype=dtype) + + +@tf_export('metrics.FalseNegatives', 'keras.metrics.FalseNegatives') +class FalseNegatives(_ConfusionMatrixConditionCount): + """Calculates the number of false negatives. + + For example, if `y_true` is [0, 1, 1, 1] and `y_pred` is [0, 1, 0, 0] + then the false negatives value is 2. If the weights were specified as + [0, 0, 1, 0] then the false negatives value would be 1. + + If `sample_weight` is given, calculates the sum of the weights of + false negatives. This metric creates one local variable, `accumulator` + that is used to keep track of the number of false negatives. + + If `sample_weight` is `None`, weights default to 1. + Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.FalseNegatives() + m.update_state([0, 1, 1, 1], [0, 1, 0, 0]) + print('Final result: ', m.result().numpy()) # Final result: 2 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss='mse', metrics=[tf.metrics.FalseNegatives()]) + ``` + """ + + def __init__(self, thresholds=None, name=None, dtype=None): + """Creates a `FalseNegatives` instance. + + Args: + thresholds: (Optional) Defaults to 0.5. A float value or a python + list/tuple of float threshold values in [0, 1]. A threshold is compared + with prediction values to determine the truth value of predictions + (i.e., above the threshold is `true`, below is `false`). One metric + value is generated for each threshold value. + name: (Optional) string name of the metric instance. + dtype: (Optional) data type of the metric result. + """ + super(FalseNegatives, self).__init__( + confusion_matrix_cond=_ConfusionMatrix.FALSE_NEGATIVES, + thresholds=thresholds, + name=name, + dtype=dtype) + + +@tf_export('metrics.TrueNegatives', 'keras.metrics.TrueNegatives') +class TrueNegatives(_ConfusionMatrixConditionCount): + """Calculates the number of true negatives. + + For example, if `y_true` is [0, 1, 0, 0] and `y_pred` is [1, 1, 0, 0] + then the true negatives value is 2. If the weights were specified as + [0, 0, 1, 0] then the true negatives value would be 1. + + If `sample_weight` is given, calculates the sum of the weights of + true negatives. This metric creates one local variable, `accumulator` + that is used to keep track of the number of true negatives. + + If `sample_weight` is `None`, weights default to 1. + Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.TrueNegatives() + m.update_state([0, 1, 0, 0], [1, 1, 0, 0]) + print('Final result: ', m.result().numpy()) # Final result: 2 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss='mse', metrics=[tf.metrics.TrueNegatives()]) + ``` + """ + + def __init__(self, thresholds=None, name=None, dtype=None): + """Creates a `TrueNegatives` instance. + + Args: + thresholds: (Optional) Defaults to 0.5. A float value or a python + list/tuple of float threshold values in [0, 1]. A threshold is compared + with prediction values to determine the truth value of predictions + (i.e., above the threshold is `true`, below is `false`). One metric + value is generated for each threshold value. + name: (Optional) string name of the metric instance. + dtype: (Optional) data type of the metric result. + """ + super(TrueNegatives, self).__init__( + confusion_matrix_cond=_ConfusionMatrix.TRUE_NEGATIVES, + thresholds=thresholds, + name=name, + dtype=dtype) + + +@tf_export('metrics.TruePositives', 'keras.metrics.TruePositives') +class TruePositives(_ConfusionMatrixConditionCount): + """Calculates the number of true positives. + + For example, if `y_true` is [0, 1, 1, 1] and `y_pred` is [1, 0, 1, 1] + then the true positives value is 2. If the weights were specified as + [0, 0, 1, 0] then the true positives value would be 1. + + If `sample_weight` is given, calculates the sum of the weights of + true positives. This metric creates one local variable, `true_positives` + that is used to keep track of the number of true positives. + + If `sample_weight` is `None`, weights default to 1. + Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.TruePositives() + m.update_state([0, 1, 1, 1], [1, 0, 1, 1]) + print('Final result: ', m.result().numpy()) # Final result: 2 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss='mse', metrics=[tf.metrics.TruePositives()]) + ``` + """ + + def __init__(self, thresholds=None, name=None, dtype=None): + """Creates a `TruePositives` instance. + + Args: + thresholds: (Optional) Defaults to 0.5. A float value or a python + list/tuple of float threshold values in [0, 1]. A threshold is compared + with prediction values to determine the truth value of predictions + (i.e., above the threshold is `true`, below is `false`). One metric + value is generated for each threshold value. + name: (Optional) string name of the metric instance. + dtype: (Optional) data type of the metric result. + """ + super(TruePositives, self).__init__( + confusion_matrix_cond=_ConfusionMatrix.TRUE_POSITIVES, + thresholds=thresholds, + name=name, + dtype=dtype) + + +@tf_export('metrics.Precision', 'keras.metrics.Precision') +class Precision(Metric): + """Computes the precision of the predictions with respect to the labels. + + For example, if `y_true` is [0, 1, 1, 1] and `y_pred` is [1, 0, 1, 1] + then the precision value is 2/(2+1) ie. 0.66. If the weights were specified as + [0, 0, 1, 0] then the precision value would be 1. + + The metric creates two local variables, `true_positives` and `false_positives` + that are used to compute the precision. This value is ultimately returned as + `precision`, an idempotent operation that simply divides `true_positives` + by the sum of `true_positives` and `false_positives`. + + If `sample_weight` is `None`, weights default to 1. + Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.Precision() + m.update_state([0, 1, 1, 1], [1, 0, 1, 1]) + print('Final result: ', m.result().numpy()) # Final result: 0.66 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss='mse', metrics=[tf.metrics.Precision()]) + ``` + """ + + def __init__(self, thresholds=None, name=None, dtype=None): + """Creates a `Precision` instance. + + Args: + thresholds: (Optional) Defaults to 0.5. A float value or a python + list/tuple of float threshold values in [0, 1]. A threshold is compared + with prediction values to determine the truth value of predictions + (i.e., above the threshold is `true`, below is `false`). One metric + value is generated for each threshold value. + name: (Optional) string name of the metric instance. + dtype: (Optional) data type of the metric result. + """ + super(Precision, self).__init__(name=name, dtype=dtype) + self.thresholds = 0.5 if thresholds is None else thresholds + thresholds = to_list(thresholds) + _assert_thresholds_range(thresholds) + self.tp = self.add_weight( + 'true_positives', + shape=(len(thresholds),), + initializer=init_ops.zeros_initializer) + self.fp = self.add_weight( + 'false_positives', + shape=(len(thresholds),), + initializer=init_ops.zeros_initializer) + + def update_state(self, y_true, y_pred, sample_weight=None): + """Accumulates true positive and false positive statistics. + + Args: + y_true: The ground truth values. + y_pred: The predicted values. + sample_weight: Optional weighting of each example. Defaults to 1. Can be a + `Tensor` whose rank is either 0, or the same rank as `y_true`, and must + be broadcastable to `y_true`. + + Returns: + Update op. + """ + return _update_confusion_matrix_variables({ + _ConfusionMatrix.TRUE_POSITIVES: self.tp, + _ConfusionMatrix.FALSE_POSITIVES: self.fp + }, y_true, y_pred, self.thresholds, sample_weight) + + def result(self): + result = math_ops.div_no_nan(self.tp, self.tp + self.fp) + return result if isinstance(self.thresholds, (list, tuple)) else result[0] + + def reset_states(self): + num_thresholds = len(to_list(self.thresholds)) + for v in self.variables: + K.set_value(v, np.zeros((num_thresholds,))) + + +@tf_export('metrics.Recall', 'keras.metrics.Recall') +class Recall(Metric): + """Computes the recall of the predictions with respect to the labels. + + For example, if `y_true` is [0, 1, 1, 1] and `y_pred` is [1, 0, 1, 1] + then the recall value is 2/(2+1) ie. 0.66. If the weights were specified as + [0, 0, 1, 0] then the recall value would be 1. + + This metric creates two local variables, `true_positives` and + `false_negatives`, that are used to compute the recall. This value is + ultimately returned as `recall`, an idempotent operation that simply divides + `true_positives` by the sum of `true_positives` and `false_negatives`. + + If `sample_weight` is `None`, weights default to 1. + Use `sample_weight` of 0 to mask values. + + Usage: + + ```python + m = tf.metrics.Recall() + m.update_state([0, 1, 1, 1], [1, 0, 1, 1]) + print('Final result: ', m.result().numpy()) # Final result: 0.66 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss='mse', metrics=[tf.metrics.Recall()]) + ``` + """ + + def __init__(self, thresholds=None, name=None, dtype=None): + """Creates a `Recall` instance. + + Args: + thresholds: (Optional) Defaults to 0.5. A float value or a python + list/tuple of float threshold values in [0, 1]. A threshold is compared + with prediction values to determine the truth value of predictions + (i.e., above the threshold is `true`, below is `false`). One metric + value is generated for each threshold value. + name: (Optional) string name of the metric instance. + dtype: (Optional) data type of the metric result. + """ + super(Recall, self).__init__(name=name, dtype=dtype) + self.thresholds = 0.5 if thresholds is None else thresholds + thresholds = to_list(thresholds) + _assert_thresholds_range(thresholds) + self.tp = self.add_weight( + 'true_positives', + shape=(len(thresholds),), + initializer=init_ops.zeros_initializer) + self.fn = self.add_weight( + 'false_negatives', + shape=(len(thresholds),), + initializer=init_ops.zeros_initializer) + + def update_state(self, y_true, y_pred, sample_weight=None): + """Accumulates true positive and false negative statistics. + + Args: + y_true: The ground truth values. + y_pred: The predicted values. + sample_weight: Optional weighting of each example. Defaults to 1. Can be a + `Tensor` whose rank is either 0, or the same rank as `y_true`, and must + be broadcastable to `y_true`. + + Returns: + Update op. + """ + return _update_confusion_matrix_variables({ + _ConfusionMatrix.TRUE_POSITIVES: self.tp, + _ConfusionMatrix.FALSE_NEGATIVES: self.fn + }, y_true, y_pred, self.thresholds, sample_weight) + + def result(self): + result = math_ops.div_no_nan(self.tp, self.tp + self.fn) + return result if isinstance(self.thresholds, (list, tuple)) else result[0] + + def reset_states(self): + num_thresholds = len(to_list(self.thresholds)) + for v in self.variables: + K.set_value(v, np.zeros((num_thresholds,))) + + +@six.add_metaclass(abc.ABCMeta) +class SensitivitySpecificityBase(Metric): + """Abstract base class for computing sensitivity and specificity. + + For additional information about specificity and sensitivity, see the + following: https://en.wikipedia.org/wiki/Sensitivity_and_specificity + """ + + def __init__(self, value, num_thresholds=200, name=None, dtype=None): + super(SensitivitySpecificityBase, self).__init__(name=name, dtype=dtype) + if num_thresholds <= 0: + raise ValueError('`num_thresholds` must be > 0.') + self.value = value + self.tp = self.add_weight( + 'true_positives', + shape=(num_thresholds,), + initializer=init_ops.zeros_initializer) + self.tn = self.add_weight( + 'true_negatives', + shape=(num_thresholds,), + initializer=init_ops.zeros_initializer) + self.fp = self.add_weight( + 'false_positives', + shape=(num_thresholds,), + initializer=init_ops.zeros_initializer) + self.fn = self.add_weight( + 'false_negatives', + shape=(num_thresholds,), + initializer=init_ops.zeros_initializer) + + # Compute `num_thresholds` thresholds in [0, 1] + if num_thresholds == 1: + self.thresholds = [0.5] + else: + thresholds = [(i + 1) * 1.0 / (num_thresholds - 1) + for i in range(num_thresholds - 2)] + self.thresholds = [0.0] + thresholds + [1.0] + + def update_state(self, y_true, y_pred, sample_weight=None): + """Accumulates confusion matrix statistics. + + Args: + y_true: The ground truth values. + y_pred: The predicted values. + sample_weight: Optional weighting of each example. Defaults to 1. Can be a + `Tensor` whose rank is either 0, or the same rank as `y_true`, and must + be broadcastable to `y_true`. + + Returns: + Update op. + """ + return _update_confusion_matrix_variables({ + _ConfusionMatrix.TRUE_POSITIVES: self.tp, + _ConfusionMatrix.TRUE_NEGATIVES: self.tn, + _ConfusionMatrix.FALSE_POSITIVES: self.fp, + _ConfusionMatrix.FALSE_NEGATIVES: self.fn, + }, y_true, y_pred, self.thresholds, sample_weight) + + def reset_states(self): + num_thresholds = len(self.thresholds) + for v in self.variables: + K.set_value(v, np.zeros((num_thresholds,))) + + +class SensitivityAtSpecificity(SensitivitySpecificityBase): + """Computes the sensitivity at a given specificity. + + `Sensitivity` measures the proportion of actual positives that are correctly + identified as such (tp / (tp + fn)). + `Specificity` measures the proportion of actual negatives that are correctly + identified as such (tn / (tn + fp)). + + This metric creates four local variables, `true_positives`, `true_negatives`, + `false_positives` and `false_negatives` that are used to compute the + sensitivity at the given specificity. The threshold for the given specificity + value is computed and used to evaluate the corresponding sensitivity. + + If `sample_weight` is `None`, weights default to 1. + Use `sample_weight` of 0 to mask values. + + For additional information about specificity and sensitivity, see the + following: https://en.wikipedia.org/wiki/Sensitivity_and_specificity + + Usage: + + ```python + m = tf.metrics.SensitivityAtSpecificity(0.4, num_thresholds=1) + m.update_state([0, 0, 1, 1], [0, 0.5, 0.3, 0.9]) + print('Final result: ', m.result().numpy()) # Final result: 0.5 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile( + 'sgd', + loss='mse', + metrics=[tf.metrics.SensitivityAtSpecificity()]) + ``` + """ + + def __init__(self, specificity, num_thresholds=200, name=None, dtype=None): + """Creates a `SensitivityAtSpecificity` instance. + + Args: + specificity: A scalar value in range `[0, 1]`. + num_thresholds: (Optional) Defaults to 200. The number of thresholds to + use for matching the given specificity. + name: (Optional) string name of the metric instance. + dtype: (Optional) data type of the metric result. + """ + if specificity < 0 or specificity > 1: + raise ValueError('`specificity` must be in the range [0, 1].') + super(SensitivityAtSpecificity, self).__init__( + specificity, num_thresholds=num_thresholds, name=name, dtype=dtype) + + def result(self): + # Calculate specificities at all the thresholds. + specificities = math_ops.div_no_nan(self.tn, self.tn + self.fp) + + # Find the index of the threshold where the specificity is closest to the + # given specificity. + min_index = math_ops.argmin( + math_ops.abs(specificities - self.value), axis=0) + min_index = math_ops.cast(min_index, dtypes.int32) + + # Compute sensitivity at that index. + return math_ops.div_no_nan(self.tp[min_index], + self.tp[min_index] + self.fn[min_index]) + + +class SpecificityAtSensitivity(SensitivitySpecificityBase): + """Computes the specificity at a given sensitivity. + + `Sensitivity` measures the proportion of actual positives that are correctly + identified as such (tp / (tp + fn)). + `Specificity` measures the proportion of actual negatives that are correctly + identified as such (tn / (tn + fp)). + + This metric creates four local variables, `true_positives`, `true_negatives`, + `false_positives` and `false_negatives` that are used to compute the + specificity at the given sensitivity. The threshold for the given sensitivity + value is computed and used to evaluate the corresponding specificity. + + If `sample_weight` is `None`, weights default to 1. + Use `sample_weight` of 0 to mask values. + + For additional information about specificity and sensitivity, see the + following: https://en.wikipedia.org/wiki/Sensitivity_and_specificity + + Usage: + + ```python + m = tf.metrics.SpecificityAtSensitivity(0.8, num_thresholds=1) + m.update_state([0, 0, 1, 1], [0, 0.5, 0.3, 0.9]) + print('Final result: ', m.result().numpy()) # Final result: 1.0 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile( + 'sgd', + loss='mse', + metrics=[tf.metrics.SpecificityAtSensitivity()]) + ``` + """ + + def __init__(self, sensitivity, num_thresholds=200, name=None, dtype=None): + """Creates a `SpecificityAtSensitivity` instance. + + Args: + sensitivity: A scalar value in range `[0, 1]`. + num_thresholds: (Optional) Defaults to 200. The number of thresholds to + use for matching the given specificity. + name: (Optional) string name of the metric instance. + dtype: (Optional) data type of the metric result. + """ + if sensitivity < 0 or sensitivity > 1: + raise ValueError('`sensitivity` must be in the range [0, 1].') + super(SpecificityAtSensitivity, self).__init__( + sensitivity, num_thresholds=num_thresholds, name=name, dtype=dtype) + + def result(self): + # Calculate sensitivities at all the thresholds. + sensitivities = math_ops.div_no_nan(self.tp, self.tp + self.fn) + + # Find the index of the threshold where the sensitivity is closest to the + # given specificity. + min_index = math_ops.argmin( + math_ops.abs(sensitivities - self.value), axis=0) + min_index = math_ops.cast(min_index, dtypes.int32) + + # Compute specificity at that index. + return math_ops.div_no_nan(self.tn[min_index], + self.tn[min_index] + self.fp[min_index]) + + +class CosineProximity(MeanMetricWrapper): + """Computes the cosine distance between the labels and predictions. + + For example, if `y_true` is [0, 1, 1], and `y_pred` is [1, 0, 1], the cosine + proximity is -0.5. + + This metric keeps the average cosine distance between `predictions` and + `labels` over a stream of data. + + Usage: + ```python + m = tf.metrics.CosineProximity() + m.update_state([0, 1, 1], [1, 0, 1]) + print('Final result: ', m.result().numpy()) # Final result: -0.5 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile( + 'sgd', + loss='mse', + metrics=[tf.metrics.CosineProximity()]) + ``` + """ + + def __init__(self, name='cosine_proximity', dtype=None): + super(CosineProximity, self).__init__(cosine, name, dtype=dtype) + + @classmethod + def from_config(cls, config): + if 'fn' in config: + config.pop('fn') + return super(CosineProximity, cls).from_config(config) + + +def accuracy(y_true, y_pred): + y_pred.get_shape().assert_is_compatible_with(y_true.get_shape()) + if y_true.dtype != y_pred.dtype: + y_pred = math_ops.cast(y_pred, y_true.dtype) + return math_ops.cast(math_ops.equal(y_true, y_pred), K.floatx()) + @tf_export('keras.metrics.binary_accuracy') def binary_accuracy(y_true, y_pred, threshold=0.5): diff --git a/tensorflow/python/keras/metrics_test.py b/tensorflow/python/keras/metrics_test.py index 5f5565d4d5..92398acd8e 100644 --- a/tensorflow/python/keras/metrics_test.py +++ b/tensorflow/python/keras/metrics_test.py @@ -19,22 +19,25 @@ from __future__ import division from __future__ import print_function import os +from absl.testing import parameterized import numpy as np from tensorflow.python.eager import context +from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import test_util from tensorflow.python.keras import backend as K from tensorflow.python.keras import layers from tensorflow.python.keras import metrics -from tensorflow.python.keras.engine.training import Model +from tensorflow.python.keras.models import Sequential from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops -from tensorflow.python.ops import state_ops +from tensorflow.python.ops import random_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test from tensorflow.python.training.checkpointable import util as checkpointable_utils +from tensorflow.python.training.rmsprop import RMSPropOptimizer class KerasMetricsTest(test.TestCase): @@ -47,7 +50,7 @@ class KerasMetricsTest(test.TestCase): output = metric(y_a, y_b) self.assertEqual(K.eval(output).shape, (6,)) - def test_sparse_categorical_accuracy(self): + def test_sparse_categorical_accuracy_int(self): with self.cached_session(): metric = metrics.sparse_categorical_accuracy y_true = K.variable(np.random.randint(0, 7, (6,))) @@ -128,116 +131,6 @@ class KerasMetricsTest(test.TestCase): result = K.eval(metrics.top_k_categorical_accuracy(y_true, y_pred, k=1)) self.assertEqual(result, 0.) - def test_stateful_metrics(self): - with self.cached_session(): - np.random.seed(1334) - - class BinaryTruePositives(layers.Layer): - """Stateful Metric to count the total true positives over all batches. - - Assumes predictions and targets of shape `(samples, 1)`. - - Arguments: - threshold: Float, lower limit on prediction value that counts as a - positive class prediction. - name: String, name for the metric. - """ - - def __init__(self, name='true_positives', **kwargs): - super(BinaryTruePositives, self).__init__(name=name, **kwargs) - self.true_positives = K.variable(value=0, dtype='int32') - self.stateful = True - - def reset_states(self): - K.set_value(self.true_positives, 0) - - def __call__(self, y_true, y_pred): - """Computes the number of true positives in a batch. - - Args: - y_true: Tensor, batch_wise labels - y_pred: Tensor, batch_wise predictions - - Returns: - The total number of true positives seen this epoch at the - completion of the batch. - """ - y_true = math_ops.cast(y_true, 'int32') - y_pred = math_ops.cast(math_ops.round(y_pred), 'int32') - correct_preds = math_ops.cast(math_ops.equal(y_pred, y_true), 'int32') - true_pos = math_ops.cast( - math_ops.reduce_sum(correct_preds * y_true), 'int32') - current_true_pos = self.true_positives * 1 - self.add_update( - state_ops.assign_add(self.true_positives, true_pos), - inputs=[y_true, y_pred]) - return current_true_pos + true_pos - - metric_fn = BinaryTruePositives() - config = metrics.serialize(metric_fn) - metric_fn = metrics.deserialize( - config, custom_objects={'BinaryTruePositives': BinaryTruePositives}) - - # Test on simple model - inputs = layers.Input(shape=(2,)) - outputs = layers.Dense(1, activation='sigmoid')(inputs) - model = Model(inputs, outputs) - model.compile(optimizer='sgd', - loss='binary_crossentropy', - metrics=['acc', metric_fn]) - - # Test fit, evaluate - samples = 100 - x = np.random.random((samples, 2)) - y = np.random.randint(2, size=(samples, 1)) - val_samples = 10 - val_x = np.random.random((val_samples, 2)) - val_y = np.random.randint(2, size=(val_samples, 1)) - - history = model.fit(x, y, - epochs=1, - batch_size=10, - validation_data=(val_x, val_y)) - outs = model.evaluate(x, y, batch_size=10) - preds = model.predict(x) - - def ref_true_pos(y_true, y_pred): - return np.sum(np.logical_and(y_pred > 0.5, y_true == 1)) - - # Test correctness (e.g. updates should have been run) - self.assertAllClose(outs[2], ref_true_pos(y, preds), atol=1e-5) - - # Test correctness of the validation metric computation - val_preds = model.predict(val_x) - val_outs = model.evaluate(val_x, val_y, batch_size=10) - self.assertAllClose( - val_outs[2], ref_true_pos(val_y, val_preds), atol=1e-5) - self.assertAllClose( - val_outs[2], history.history['val_true_positives'][-1], atol=1e-5) - - # Test with generators - gen = [(np.array([x0]), np.array([y0])) for x0, y0 in zip(x, y)] - val_gen = [(np.array([x0]), np.array([y0])) - for x0, y0 in zip(val_x, val_y)] - history = model.fit_generator(iter(gen), - epochs=1, - steps_per_epoch=samples, - validation_data=iter(val_gen), - validation_steps=val_samples) - outs = model.evaluate_generator(iter(gen), steps=samples) - preds = model.predict_generator(iter(gen), steps=samples) - - # Test correctness of the metric results - self.assertAllClose(outs[2], ref_true_pos(y, preds), atol=1e-5) - - # Test correctness of the validation metric computation - val_preds = model.predict_generator(iter(val_gen), steps=val_samples) - val_outs = model.evaluate_generator(iter(val_gen), steps=val_samples) - self.assertAllClose( - val_outs[2], ref_true_pos(val_y, val_preds), atol=1e-5) - self.assertAllClose( - val_outs[2], history.history['val_true_positives'][-1], atol=1e-5) - @test_util.run_in_graph_and_eager_modes(assert_no_eager_garbage=True) def test_mean(self): m = metrics.Mean(name='my_mean') @@ -319,19 +212,19 @@ class KerasMetricsTest(test.TestCase): m = metrics.Mean() v = array_ops.placeholder(dtypes.float32) w = array_ops.placeholder(dtypes.float32) - sess.run(variables.variables_initializer(m.variables)) + self.evaluate(variables.variables_initializer(m.variables)) # check __call__() result_t = m(v, sample_weight=w) result = sess.run(result_t, feed_dict=({v: 100, w: 0.5})) - self.assertEqual(sess.run(m.total), 50) - self.assertEqual(sess.run(m.count), 0.5) + self.assertEqual(self.evaluate(m.total), 50) + self.assertEqual(self.evaluate(m.count), 0.5) self.assertEqual(result, 50 / 0.5) # check update_state() and result() result = sess.run(result_t, feed_dict=({v: [1, 5], w: [1, 0.2]})) - self.assertAlmostEqual(sess.run(m.total), 52, 2) # 50 + 1 + 5 * 0.2 - self.assertAlmostEqual(sess.run(m.count), 1.7, 2) # 0.5 + 1.2 + self.assertAlmostEqual(self.evaluate(m.total), 52, 2) # 50 + 1 + 5 * 0.2 + self.assertAlmostEqual(self.evaluate(m.count), 1.7, 2) # 0.5 + 1.2 self.assertAlmostEqual(result, 52 / 1.7, 2) @test_util.run_in_graph_and_eager_modes @@ -365,6 +258,28 @@ class KerasMetricsTest(test.TestCase): self.assertEqual(200., self.evaluate(restore_mean.result())) self.assertEqual(3, self.evaluate(restore_mean.count)) + @test_util.run_in_graph_and_eager_modes + def test_accuracy(self): + acc_obj = metrics.Accuracy(name='my acc') + + # check config + self.assertEqual(acc_obj.name, 'my acc') + self.assertTrue(acc_obj.stateful) + self.assertEqual(len(acc_obj.variables), 2) + self.assertEqual(acc_obj.dtype, dtypes.float32) + self.evaluate(variables.variables_initializer(acc_obj.variables)) + + # verify that correct value is returned + update_op = acc_obj.update_state([[1], [2], [3], [4]], [[1], [2], [3], [4]]) + self.evaluate(update_op) + result = self.evaluate(acc_obj.result()) + self.assertEqual(result, 1) # 2/2 + + # check with sample_weight + result_t = acc_obj([[2], [1]], [[2], [0]], sample_weight=[[0.5], [0.2]]) + result = self.evaluate(result_t) + self.assertAlmostEqual(result, 0.96, 2) # 4.5/4.7 + @test_util.run_in_graph_and_eager_modes def test_binary_accuracy(self): acc_obj = metrics.BinaryAccuracy(name='my acc') @@ -398,11 +313,6 @@ class KerasMetricsTest(test.TestCase): result = self.evaluate(result_t) self.assertAlmostEqual(result, 0.67, 2) # 4.5/6.7 - # check incompatible shapes - with self.assertRaisesRegexp(ValueError, - r'Shapes \(1,\) and \(2,\) are incompatible'): - acc_obj.update_state([1, 1], [1]) - @test_util.run_in_graph_and_eager_modes def test_binary_accuracy_threshold(self): acc_obj = metrics.BinaryAccuracy(threshold=0.7) @@ -436,47 +346,830 @@ class KerasMetricsTest(test.TestCase): self.assertAlmostEqual(result, 0.93, 2) # 2.5/2.7 @test_util.run_in_graph_and_eager_modes - def test_invalid_result(self): + def test_sparse_categorical_accuracy(self): + acc_obj = metrics.SparseCategoricalAccuracy(name='my acc') + + # check config + self.assertEqual(acc_obj.name, 'my acc') + self.assertTrue(acc_obj.stateful) + self.assertEqual(len(acc_obj.variables), 2) + self.assertEqual(acc_obj.dtype, dtypes.float32) + self.evaluate(variables.variables_initializer(acc_obj.variables)) - class InvalidResult(metrics.Metric): + # verify that correct value is returned + update_op = acc_obj.update_state([[2], [1]], + [[0.1, 0.1, 0.8], [0.05, 0.95, 0]]) + self.evaluate(update_op) + result = self.evaluate(acc_obj.result()) + self.assertEqual(result, 1) # 2/2 - def __init__(self, name='invalid-result', dtype=dtypes.float64): - super(InvalidResult, self).__init__(name=name, dtype=dtype) + # check with sample_weight + result_t = acc_obj([[2], [1]], [[0.1, 0.1, 0.8], [0.05, 0, 0.95]], + [[0.5], [0.2]]) + result = self.evaluate(result_t) + self.assertAlmostEqual(result, 0.93, 2) # 2.5/2.7 - def update_state(self, *args, **kwargs): - pass - def result(self): - return 1 +def _get_simple_sequential_model(compile_metrics): + model = Sequential() + model.add( + layers.Dense( + 3, activation='relu', input_dim=4, kernel_initializer='ones')) + model.add(layers.Dense(1, activation='sigmoid', kernel_initializer='ones')) + model.compile( + loss='mae', + metrics=compile_metrics, + optimizer=RMSPropOptimizer(learning_rate=0.001)) + return model - invalid_result_obj = InvalidResult() - with self.assertRaisesRegexp( - TypeError, - 'Metric invalid-result\'s result must be a Tensor or Operation, given:' - ): - invalid_result_obj.result() - @test_util.run_in_graph_and_eager_modes - def test_invalid_update(self): +@test_util.run_all_in_graph_and_eager_modes +class FalsePositivesTest(test.TestCase): - class InvalidUpdate(metrics.Metric): + def test_config(self): + fp_obj = metrics.FalsePositives(name='my_fp', thresholds=[0.4, 0.9]) + self.assertEqual(fp_obj.name, 'my_fp') + self.assertEqual(len(fp_obj.variables), 1) + self.assertEqual(fp_obj.thresholds, [0.4, 0.9]) - def __init__(self, name='invalid-update', dtype=dtypes.float64): - super(InvalidUpdate, self).__init__(name=name, dtype=dtype) + def test_unweighted(self): + fp_obj = metrics.FalsePositives() + self.evaluate(variables.variables_initializer(fp_obj.variables)) - def update_state(self, *args, **kwargs): - return [1] + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) - def result(self): - pass + update_op = fp_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = fp_obj.result() + self.assertAllClose(7., result) + + def test_weighted(self): + fp_obj = metrics.FalsePositives() + self.evaluate(variables.variables_initializer(fp_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + sample_weight = constant_op.constant((1., 1.5, 2., 2.5)) + result = fp_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose(14., self.evaluate(result)) + + def test_unweighted_with_thresholds(self): + fp_obj = metrics.FalsePositives(thresholds=[0.15, 0.5, 0.85]) + self.evaluate(variables.variables_initializer(fp_obj.variables)) + + y_pred = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), + (0.1, 0.2, 0.4, 0.3), (0, 1, 0.7, 0.3))) + y_true = constant_op.constant(((0, 1, 1, 0), (1, 0, 0, 0), (0, 0, 0, 0), + (1, 1, 1, 1))) + + update_op = fp_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = fp_obj.result() + self.assertAllClose([7., 4., 2.], result) - invalid_update_obj = InvalidUpdate() - with self.assertRaisesRegexp( - TypeError, - 'Metric invalid-update\'s update must be a Tensor or Operation, given:' - ): - invalid_update_obj.update_state() + def test_weighted_with_thresholds(self): + fp_obj = metrics.FalsePositives(thresholds=[0.15, 0.5, 0.85]) + self.evaluate(variables.variables_initializer(fp_obj.variables)) + + y_pred = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), + (0.1, 0.2, 0.4, 0.3), (0, 1, 0.7, 0.3))) + y_true = constant_op.constant(((0, 1, 1, 0), (1, 0, 0, 0), (0, 0, 0, 0), + (1, 1, 1, 1))) + sample_weight = ((1.0, 2.0, 3.0, 5.0), (7.0, 11.0, 13.0, 17.0), + (19.0, 23.0, 29.0, 31.0), (5.0, 15.0, 10.0, 0)) + result = fp_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose([125., 42., 12.], self.evaluate(result)) + + def test_threshold_limit(self): + with self.assertRaisesRegexp( + ValueError, + r'Threshold values must be in \[0, 1\]. Invalid values: \[-1, 2\]'): + metrics.FalsePositives(thresholds=[-1, 0.5, 2]) + + def test_reset_states(self): + fp_obj = metrics.FalsePositives() + model = _get_simple_sequential_model([fp_obj]) + x = np.ones((100, 4)) + y = np.zeros((100, 1)) + model.evaluate(x, y) + self.assertEqual(self.evaluate(fp_obj.accumulator), 100.) + model.evaluate(x, y) + self.assertEqual(self.evaluate(fp_obj.accumulator), 100.) + + +@test_util.run_all_in_graph_and_eager_modes +class FalseNegativesTest(test.TestCase): + + def test_config(self): + fn_obj = metrics.FalseNegatives(name='my_fn', thresholds=[0.4, 0.9]) + self.assertEqual(fn_obj.name, 'my_fn') + self.assertEqual(len(fn_obj.variables), 1) + self.assertEqual(fn_obj.thresholds, [0.4, 0.9]) + + def test_unweighted(self): + fn_obj = metrics.FalseNegatives() + self.evaluate(variables.variables_initializer(fn_obj.variables)) + + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + + update_op = fn_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = fn_obj.result() + self.assertAllClose(3., result) + + def test_weighted(self): + fn_obj = metrics.FalseNegatives() + self.evaluate(variables.variables_initializer(fn_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + sample_weight = constant_op.constant((1., 1.5, 2., 2.5)) + result = fn_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose(5., self.evaluate(result)) + + def test_unweighted_with_thresholds(self): + fn_obj = metrics.FalseNegatives(thresholds=[0.15, 0.5, 0.85]) + self.evaluate(variables.variables_initializer(fn_obj.variables)) + + y_pred = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), + (0.1, 0.2, 0.4, 0.3), (0, 1, 0.7, 0.3))) + y_true = constant_op.constant(((0, 1, 1, 0), (1, 0, 0, 0), (0, 0, 0, 0), + (1, 1, 1, 1))) + + update_op = fn_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = fn_obj.result() + self.assertAllClose([1., 4., 6.], result) + + def test_weighted_with_thresholds(self): + fn_obj = metrics.FalseNegatives(thresholds=[0.15, 0.5, 0.85]) + self.evaluate(variables.variables_initializer(fn_obj.variables)) + + y_pred = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), + (0.1, 0.2, 0.4, 0.3), (0, 1, 0.7, 0.3))) + y_true = constant_op.constant(((0, 1, 1, 0), (1, 0, 0, 0), (0, 0, 0, 0), + (1, 1, 1, 1))) + sample_weight = ((3.0,), (5.0,), (7.0,), (4.0,)) + + result = fn_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose([4., 16., 23.], self.evaluate(result)) + + def test_reset_states(self): + fn_obj = metrics.FalseNegatives() + model = _get_simple_sequential_model([fn_obj]) + x = np.zeros((100, 4)) + y = np.ones((100, 1)) + model.evaluate(x, y) + self.assertEqual(self.evaluate(fn_obj.accumulator), 100.) + model.evaluate(x, y) + self.assertEqual(self.evaluate(fn_obj.accumulator), 100.) + + +@test_util.run_all_in_graph_and_eager_modes +class TrueNegativesTest(test.TestCase): + + def test_config(self): + tn_obj = metrics.TrueNegatives(name='my_tn', thresholds=[0.4, 0.9]) + self.assertEqual(tn_obj.name, 'my_tn') + self.assertEqual(len(tn_obj.variables), 1) + self.assertEqual(tn_obj.thresholds, [0.4, 0.9]) + + def test_unweighted(self): + tn_obj = metrics.TrueNegatives() + self.evaluate(variables.variables_initializer(tn_obj.variables)) + + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + + update_op = tn_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = tn_obj.result() + self.assertAllClose(3., result) + + def test_weighted(self): + tn_obj = metrics.TrueNegatives() + self.evaluate(variables.variables_initializer(tn_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + sample_weight = constant_op.constant((1., 1.5, 2., 2.5)) + result = tn_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose(4., self.evaluate(result)) + + def test_unweighted_with_thresholds(self): + tn_obj = metrics.TrueNegatives(thresholds=[0.15, 0.5, 0.85]) + self.evaluate(variables.variables_initializer(tn_obj.variables)) + + y_pred = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), + (0.1, 0.2, 0.4, 0.3), (0, 1, 0.7, 0.3))) + y_true = constant_op.constant(((0, 1, 1, 0), (1, 0, 0, 0), (0, 0, 0, 0), + (1, 1, 1, 1))) + + update_op = tn_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = tn_obj.result() + self.assertAllClose([2., 5., 7.], result) + + def test_weighted_with_thresholds(self): + tn_obj = metrics.TrueNegatives(thresholds=[0.15, 0.5, 0.85]) + self.evaluate(variables.variables_initializer(tn_obj.variables)) + + y_pred = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), + (0.1, 0.2, 0.4, 0.3), (0, 1, 0.7, 0.3))) + y_true = constant_op.constant(((0, 1, 1, 0), (1, 0, 0, 0), (0, 0, 0, 0), + (1, 1, 1, 1))) + sample_weight = ((0.0, 2.0, 3.0, 5.0),) + + result = tn_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose([5., 15., 23.], self.evaluate(result)) + + def test_reset_states(self): + tn_obj = metrics.TrueNegatives() + model = _get_simple_sequential_model([tn_obj]) + x = np.zeros((100, 4)) + y = np.zeros((100, 1)) + model.evaluate(x, y) + self.assertEqual(self.evaluate(tn_obj.accumulator), 100.) + model.evaluate(x, y) + self.assertEqual(self.evaluate(tn_obj.accumulator), 100.) + + +@test_util.run_all_in_graph_and_eager_modes +class TruePositivesTest(test.TestCase): + + def test_config(self): + tp_obj = metrics.TruePositives(name='my_tp', thresholds=[0.4, 0.9]) + self.assertEqual(tp_obj.name, 'my_tp') + self.assertEqual(len(tp_obj.variables), 1) + self.assertEqual(tp_obj.thresholds, [0.4, 0.9]) + + def test_unweighted(self): + tp_obj = metrics.TruePositives() + self.evaluate(variables.variables_initializer(tp_obj.variables)) + + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + + update_op = tp_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = tp_obj.result() + self.assertAllClose(7., result) + + def test_weighted(self): + tp_obj = metrics.TruePositives() + self.evaluate(variables.variables_initializer(tp_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + sample_weight = constant_op.constant((1., 1.5, 2., 2.5)) + result = tp_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose(12., self.evaluate(result)) + + def test_unweighted_with_thresholds(self): + tp_obj = metrics.TruePositives(thresholds=[0.15, 0.5, 0.85]) + self.evaluate(variables.variables_initializer(tp_obj.variables)) + + y_pred = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), + (0.1, 0.2, 0.4, 0.3), (0, 1, 0.7, 0.3))) + y_true = constant_op.constant(((0, 1, 1, 0), (1, 0, 0, 0), (0, 0, 0, 0), + (1, 1, 1, 1))) + + update_op = tp_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = tp_obj.result() + self.assertAllClose([6., 3., 1.], result) + + def test_weighted_with_thresholds(self): + tp_obj = metrics.TruePositives(thresholds=[0.15, 0.5, 0.85]) + self.evaluate(variables.variables_initializer(tp_obj.variables)) + + y_pred = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), + (0.1, 0.2, 0.4, 0.3), (0, 1, 0.7, 0.3))) + y_true = constant_op.constant(((0, 1, 1, 0), (1, 0, 0, 0), (0, 0, 0, 0), + (1, 1, 1, 1))) + + result = tp_obj(y_true, y_pred, sample_weight=37.) + self.assertAllClose([222., 111., 37.], self.evaluate(result)) + + def test_reset_states(self): + tp_obj = metrics.TruePositives() + model = _get_simple_sequential_model([tp_obj]) + x = np.ones((100, 4)) + y = np.ones((100, 1)) + model.evaluate(x, y) + self.assertEqual(self.evaluate(tp_obj.accumulator), 100.) + model.evaluate(x, y) + self.assertEqual(self.evaluate(tp_obj.accumulator), 100.) + + +@test_util.run_all_in_graph_and_eager_modes +class PrecisionTest(test.TestCase): + + def test_config(self): + p_obj = metrics.Precision(name='my_precision', thresholds=[0.4, 0.9]) + self.assertEqual(p_obj.name, 'my_precision') + self.assertLen(p_obj.variables, 2) + self.assertEqual([v.name for v in p_obj.variables], + ['true_positives:0', 'false_positives:0']) + self.assertEqual(p_obj.thresholds, [0.4, 0.9]) + + def test_value_is_idempotent(self): + p_obj = metrics.Precision(thresholds=[0.3, 0.72]) + y_pred = random_ops.random_uniform(shape=(10, 3)) + y_true = random_ops.random_uniform(shape=(10, 3)) + update_op = p_obj.update_state(y_true, y_pred) + self.evaluate(variables.variables_initializer(p_obj.variables)) + + # Run several updates. + for _ in range(10): + self.evaluate(update_op) + + # Then verify idempotency. + initial_precision = self.evaluate(p_obj.result()) + for _ in range(10): + self.assertArrayNear(initial_precision, self.evaluate(p_obj.result()), + 1e-3) + + def test_unweighted(self): + p_obj = metrics.Precision() + y_pred = constant_op.constant([1, 0, 1, 0], shape=(1, 4)) + y_true = constant_op.constant([0, 1, 1, 0], shape=(1, 4)) + self.evaluate(variables.variables_initializer(p_obj.variables)) + result = p_obj(y_true, y_pred) + self.assertAlmostEqual(0.5, self.evaluate(result)) + + def test_unweighted_all_incorrect(self): + p_obj = metrics.Precision(thresholds=[0.5]) + inputs = np.random.randint(0, 2, size=(100, 1)) + y_pred = constant_op.constant(inputs) + y_true = constant_op.constant(1 - inputs) + self.evaluate(variables.variables_initializer(p_obj.variables)) + result = p_obj(y_true, y_pred) + self.assertAlmostEqual(0, self.evaluate(result)) + + def test_weighted(self): + p_obj = metrics.Precision() + y_pred = constant_op.constant([[1, 0, 1, 0], [1, 0, 1, 0]]) + y_true = constant_op.constant([[0, 1, 1, 0], [1, 0, 0, 1]]) + self.evaluate(variables.variables_initializer(p_obj.variables)) + result = p_obj( + y_true, + y_pred, + sample_weight=constant_op.constant([[1, 2, 3, 4], [4, 3, 2, 1]])) + weighted_tp = 3.0 + 4.0 + weighted_positives = (1.0 + 3.0) + (4.0 + 2.0) + expected_precision = weighted_tp / weighted_positives + self.assertAlmostEqual(expected_precision, self.evaluate(result)) + + def test_div_by_zero(self): + p_obj = metrics.Precision() + y_pred = constant_op.constant([0, 0, 0, 0]) + y_true = constant_op.constant([0, 0, 0, 0]) + self.evaluate(variables.variables_initializer(p_obj.variables)) + result = p_obj(y_true, y_pred) + self.assertEqual(0, self.evaluate(result)) + + def test_unweighted_with_threshold(self): + p_obj = metrics.Precision(thresholds=[0.5, 0.7]) + y_pred = constant_op.constant([1, 0, 0.6, 0], shape=(1, 4)) + y_true = constant_op.constant([0, 1, 1, 0], shape=(1, 4)) + self.evaluate(variables.variables_initializer(p_obj.variables)) + result = p_obj(y_true, y_pred) + self.assertArrayNear([0.5, 0.], self.evaluate(result), 0) + + def test_weighted_with_threshold(self): + p_obj = metrics.Precision(thresholds=[0.5, 1.]) + y_true = constant_op.constant([[0, 1], [1, 0]], shape=(2, 2)) + y_pred = constant_op.constant([[1, 0], [0.6, 0]], + shape=(2, 2), + dtype=dtypes.float32) + weights = constant_op.constant([[4, 0], [3, 1]], + shape=(2, 2), + dtype=dtypes.float32) + self.evaluate(variables.variables_initializer(p_obj.variables)) + result = p_obj(y_true, y_pred, sample_weight=weights) + weighted_tp = 0 + 3. + weighted_positives = (0 + 3.) + (4. + 0.) + expected_precision = weighted_tp / weighted_positives + self.assertArrayNear([expected_precision, 0], self.evaluate(result), 1e-3) + + def test_multiple_updates(self): + p_obj = metrics.Precision(thresholds=[0.5, 1.]) + y_true = constant_op.constant([[0, 1], [1, 0]], shape=(2, 2)) + y_pred = constant_op.constant([[1, 0], [0.6, 0]], + shape=(2, 2), + dtype=dtypes.float32) + weights = constant_op.constant([[4, 0], [3, 1]], + shape=(2, 2), + dtype=dtypes.float32) + self.evaluate(variables.variables_initializer(p_obj.variables)) + update_op = p_obj.update_state(y_true, y_pred, sample_weight=weights) + for _ in range(2): + self.evaluate(update_op) + + weighted_tp = (0 + 3.) + (0 + 3.) + weighted_positives = ((0 + 3.) + (4. + 0.)) + ((0 + 3.) + (4. + 0.)) + expected_precision = weighted_tp / weighted_positives + self.assertArrayNear([expected_precision, 0], self.evaluate(p_obj.result()), + 1e-3) + + def test_reset_states(self): + p_obj = metrics.Precision() + model = _get_simple_sequential_model([p_obj]) + x = np.concatenate((np.ones((50, 4)), np.ones((50, 4)))) + y = np.concatenate((np.ones((50, 1)), np.zeros((50, 1)))) + model.evaluate(x, y) + self.assertEqual(self.evaluate(p_obj.tp), 50.) + self.assertEqual(self.evaluate(p_obj.fp), 50.) + model.evaluate(x, y) + self.assertEqual(self.evaluate(p_obj.tp), 50.) + self.assertEqual(self.evaluate(p_obj.fp), 50.) + + +@test_util.run_all_in_graph_and_eager_modes +class RecallTest(test.TestCase): + + def test_config(self): + r_obj = metrics.Recall(name='my_recall', thresholds=[0.4, 0.9]) + self.assertEqual(r_obj.name, 'my_recall') + self.assertLen(r_obj.variables, 2) + self.assertEqual([v.name for v in r_obj.variables], + ['true_positives:0', 'false_negatives:0']) + self.assertEqual(r_obj.thresholds, [0.4, 0.9]) + + def test_value_is_idempotent(self): + r_obj = metrics.Recall(thresholds=[0.3, 0.72]) + y_pred = random_ops.random_uniform(shape=(10, 3)) + y_true = random_ops.random_uniform(shape=(10, 3)) + update_op = r_obj.update_state(y_true, y_pred) + self.evaluate(variables.variables_initializer(r_obj.variables)) + + # Run several updates. + for _ in range(10): + self.evaluate(update_op) + + # Then verify idempotency. + initial_recall = self.evaluate(r_obj.result()) + for _ in range(10): + self.assertArrayNear(initial_recall, self.evaluate(r_obj.result()), 1e-3) + + def test_unweighted(self): + r_obj = metrics.Recall() + y_pred = constant_op.constant([1, 0, 1, 0], shape=(1, 4)) + y_true = constant_op.constant([0, 1, 1, 0], shape=(1, 4)) + self.evaluate(variables.variables_initializer(r_obj.variables)) + result = r_obj(y_true, y_pred) + self.assertAlmostEqual(0.5, self.evaluate(result)) + + def test_unweighted_all_incorrect(self): + r_obj = metrics.Recall(thresholds=[0.5]) + inputs = np.random.randint(0, 2, size=(100, 1)) + y_pred = constant_op.constant(inputs) + y_true = constant_op.constant(1 - inputs) + self.evaluate(variables.variables_initializer(r_obj.variables)) + result = r_obj(y_true, y_pred) + self.assertAlmostEqual(0, self.evaluate(result)) + + def test_weighted(self): + r_obj = metrics.Recall() + y_pred = constant_op.constant([[1, 0, 1, 0], [0, 1, 0, 1]]) + y_true = constant_op.constant([[0, 1, 1, 0], [1, 0, 0, 1]]) + self.evaluate(variables.variables_initializer(r_obj.variables)) + result = r_obj( + y_true, + y_pred, + sample_weight=constant_op.constant([[1, 2, 3, 4], [4, 3, 2, 1]])) + weighted_tp = 3.0 + 1.0 + weighted_t = (2.0 + 3.0) + (4.0 + 1.0) + expected_recall = weighted_tp / weighted_t + self.assertAlmostEqual(expected_recall, self.evaluate(result)) + + def test_div_by_zero(self): + r_obj = metrics.Recall() + y_pred = constant_op.constant([0, 0, 0, 0]) + y_true = constant_op.constant([0, 0, 0, 0]) + self.evaluate(variables.variables_initializer(r_obj.variables)) + result = r_obj(y_true, y_pred) + self.assertEqual(0, self.evaluate(result)) + + def test_unweighted_with_threshold(self): + r_obj = metrics.Recall(thresholds=[0.5, 0.7]) + y_pred = constant_op.constant([1, 0, 0.6, 0], shape=(1, 4)) + y_true = constant_op.constant([0, 1, 1, 0], shape=(1, 4)) + self.evaluate(variables.variables_initializer(r_obj.variables)) + result = r_obj(y_true, y_pred) + self.assertArrayNear([0.5, 0.], self.evaluate(result), 0) + + def test_weighted_with_threshold(self): + r_obj = metrics.Recall(thresholds=[0.5, 1.]) + y_true = constant_op.constant([[0, 1], [1, 0]], shape=(2, 2)) + y_pred = constant_op.constant([[1, 0], [0.6, 0]], + shape=(2, 2), + dtype=dtypes.float32) + weights = constant_op.constant([[1, 4], [3, 2]], + shape=(2, 2), + dtype=dtypes.float32) + self.evaluate(variables.variables_initializer(r_obj.variables)) + result = r_obj(y_true, y_pred, sample_weight=weights) + weighted_tp = 0 + 3. + weighted_positives = (0 + 3.) + (4. + 0.) + expected_recall = weighted_tp / weighted_positives + self.assertArrayNear([expected_recall, 0], self.evaluate(result), 1e-3) + + def test_multiple_updates(self): + r_obj = metrics.Recall(thresholds=[0.5, 1.]) + y_true = constant_op.constant([[0, 1], [1, 0]], shape=(2, 2)) + y_pred = constant_op.constant([[1, 0], [0.6, 0]], + shape=(2, 2), + dtype=dtypes.float32) + weights = constant_op.constant([[1, 4], [3, 2]], + shape=(2, 2), + dtype=dtypes.float32) + self.evaluate(variables.variables_initializer(r_obj.variables)) + update_op = r_obj.update_state(y_true, y_pred, sample_weight=weights) + for _ in range(2): + self.evaluate(update_op) + + weighted_tp = (0 + 3.) + (0 + 3.) + weighted_positives = ((0 + 3.) + (4. + 0.)) + ((0 + 3.) + (4. + 0.)) + expected_recall = weighted_tp / weighted_positives + self.assertArrayNear([expected_recall, 0], self.evaluate(r_obj.result()), + 1e-3) + + def test_reset_states(self): + r_obj = metrics.Recall() + model = _get_simple_sequential_model([r_obj]) + x = np.concatenate((np.ones((50, 4)), np.zeros((50, 4)))) + y = np.concatenate((np.ones((50, 1)), np.ones((50, 1)))) + model.evaluate(x, y) + self.assertEqual(self.evaluate(r_obj.tp), 50.) + self.assertEqual(self.evaluate(r_obj.fn), 50.) + model.evaluate(x, y) + self.assertEqual(self.evaluate(r_obj.tp), 50.) + self.assertEqual(self.evaluate(r_obj.fn), 50.) + + +@test_util.run_all_in_graph_and_eager_modes +class SensitivityAtSpecificityTest(test.TestCase, parameterized.TestCase): + + def test_config(self): + s_obj = metrics.SensitivityAtSpecificity( + 0.4, num_thresholds=100, name='sensitivity_at_specificity_1') + self.assertEqual(s_obj.name, 'sensitivity_at_specificity_1') + self.assertLen(s_obj.variables, 4) + self.assertEqual(s_obj.value, 0.4) + self.assertLen(s_obj.thresholds, 100) + + def test_value_is_idempotent(self): + s_obj = metrics.SensitivityAtSpecificity(0.7) + y_pred = random_ops.random_uniform((10, 3), + maxval=1, + dtype=dtypes.float32, + seed=1) + y_true = random_ops.random_uniform((10, 3), + maxval=2, + dtype=dtypes.int64, + seed=1) + update_op = s_obj.update_state(y_true, y_pred) + self.evaluate(variables.variables_initializer(s_obj.variables)) + + # Run several updates. + for _ in range(10): + self.evaluate(update_op) + + # Then verify idempotency. + initial_sensitivity = self.evaluate(s_obj.result()) + for _ in range(10): + self.assertAlmostEqual(initial_sensitivity, self.evaluate(s_obj.result()), + 1e-3) + + def test_unweighted_all_correct(self): + s_obj = metrics.SensitivityAtSpecificity(0.7) + inputs = np.random.randint(0, 2, size=(100, 1)) + y_pred = constant_op.constant(inputs, dtype=dtypes.float32) + y_true = constant_op.constant(inputs) + self.evaluate(variables.variables_initializer(s_obj.variables)) + result = s_obj(y_true, y_pred) + self.assertAlmostEqual(1, self.evaluate(result)) + + def test_unweighted_high_specificity(self): + s_obj = metrics.SensitivityAtSpecificity(0.8) + pred_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.1, 0.45, 0.5, 0.8, 0.9] + label_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] + + y_pred = constant_op.constant(pred_values, dtype=dtypes.float32) + y_true = constant_op.constant(label_values) + self.evaluate(variables.variables_initializer(s_obj.variables)) + result = s_obj(y_true, y_pred) + self.assertAlmostEqual(0.8, self.evaluate(result)) + + def test_unweighted_low_specificity(self): + s_obj = metrics.SensitivityAtSpecificity(0.4) + pred_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.25, 0.26, 0.26] + label_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] + + y_pred = constant_op.constant(pred_values, dtype=dtypes.float32) + y_true = constant_op.constant(label_values) + self.evaluate(variables.variables_initializer(s_obj.variables)) + result = s_obj(y_true, y_pred) + self.assertAlmostEqual(0.6, self.evaluate(result)) + + @parameterized.parameters([dtypes.bool, dtypes.int32, dtypes.float32]) + def test_weighted(self, label_dtype): + s_obj = metrics.SensitivityAtSpecificity(0.4) + pred_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.25, 0.26, 0.26] + label_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] + weight_values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + y_pred = constant_op.constant(pred_values, dtype=dtypes.float32) + y_true = math_ops.cast(label_values, dtype=label_dtype) + weights = constant_op.constant(weight_values) + self.evaluate(variables.variables_initializer(s_obj.variables)) + result = s_obj(y_true, y_pred, sample_weight=weights) + self.assertAlmostEqual(0.675, self.evaluate(result)) + + def test_invalid_specificity(self): + with self.assertRaisesRegexp( + ValueError, r'`specificity` must be in the range \[0, 1\].'): + metrics.SensitivityAtSpecificity(-1) + + def test_invalid_num_thresholds(self): + with self.assertRaisesRegexp(ValueError, '`num_thresholds` must be > 0.'): + metrics.SensitivityAtSpecificity(0.4, num_thresholds=-1) + + def test_reset_states(self): + s_obj = metrics.SensitivityAtSpecificity(0.5, num_thresholds=1) + model = _get_simple_sequential_model([s_obj]) + x = np.concatenate((np.ones((25, 4)), np.zeros((25, 4)), np.zeros((25, 4)), + np.ones((25, 4)))) + y = np.concatenate((np.ones((25, 1)), np.zeros((25, 1)), np.ones((25, 1)), + np.zeros((25, 1)))) + model.evaluate(x, y) + self.assertEqual(self.evaluate(s_obj.tp), 25.) + self.assertEqual(self.evaluate(s_obj.fp), 25.) + self.assertEqual(self.evaluate(s_obj.fn), 25.) + self.assertEqual(self.evaluate(s_obj.tn), 25.) + model.evaluate(x, y) + self.assertEqual(self.evaluate(s_obj.tp), 25.) + self.assertEqual(self.evaluate(s_obj.fp), 25.) + self.assertEqual(self.evaluate(s_obj.fn), 25.) + self.assertEqual(self.evaluate(s_obj.tn), 25.) + + +@test_util.run_all_in_graph_and_eager_modes +class SpecificityAtSensitivityTest(test.TestCase, parameterized.TestCase): + + def test_config(self): + s_obj = metrics.SpecificityAtSensitivity( + 0.4, num_thresholds=100, name='specificity_at_sensitivity_1') + self.assertEqual(s_obj.name, 'specificity_at_sensitivity_1') + self.assertLen(s_obj.variables, 4) + self.assertEqual(s_obj.value, 0.4) + self.assertLen(s_obj.thresholds, 100) + + def test_value_is_idempotent(self): + s_obj = metrics.SpecificityAtSensitivity(0.7) + y_pred = random_ops.random_uniform((10, 3), + maxval=1, + dtype=dtypes.float32, + seed=1) + y_true = random_ops.random_uniform((10, 3), + maxval=2, + dtype=dtypes.int64, + seed=1) + update_op = s_obj.update_state(y_true, y_pred) + self.evaluate(variables.variables_initializer(s_obj.variables)) + + # Run several updates. + for _ in range(10): + self.evaluate(update_op) + + # Then verify idempotency. + initial_specificity = self.evaluate(s_obj.result()) + for _ in range(10): + self.assertAlmostEqual(initial_specificity, self.evaluate(s_obj.result()), + 1e-3) + + def test_unweighted_all_correct(self): + s_obj = metrics.SpecificityAtSensitivity(0.7) + inputs = np.random.randint(0, 2, size=(100, 1)) + y_pred = constant_op.constant(inputs, dtype=dtypes.float32) + y_true = constant_op.constant(inputs) + self.evaluate(variables.variables_initializer(s_obj.variables)) + result = s_obj(y_true, y_pred) + self.assertAlmostEqual(1, self.evaluate(result)) + + def test_unweighted_high_sensitivity(self): + s_obj = metrics.SpecificityAtSensitivity(0.8) + pred_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.1, 0.45, 0.5, 0.8, 0.9] + label_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] + + y_pred = constant_op.constant(pred_values, dtype=dtypes.float32) + y_true = constant_op.constant(label_values) + self.evaluate(variables.variables_initializer(s_obj.variables)) + result = s_obj(y_true, y_pred) + self.assertAlmostEqual(0.4, self.evaluate(result)) + + def test_unweighted_low_sensitivity(self): + s_obj = metrics.SpecificityAtSensitivity(0.4) + pred_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.25, 0.26, 0.26] + label_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] + + y_pred = constant_op.constant(pred_values, dtype=dtypes.float32) + y_true = constant_op.constant(label_values) + self.evaluate(variables.variables_initializer(s_obj.variables)) + result = s_obj(y_true, y_pred) + self.assertAlmostEqual(0.6, self.evaluate(result)) + + @parameterized.parameters([dtypes.bool, dtypes.int32, dtypes.float32]) + def test_weighted(self, label_dtype): + s_obj = metrics.SpecificityAtSensitivity(0.4) + pred_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.25, 0.26, 0.26] + label_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] + weight_values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + + y_pred = constant_op.constant(pred_values, dtype=dtypes.float32) + y_true = math_ops.cast(label_values, dtype=label_dtype) + weights = constant_op.constant(weight_values) + self.evaluate(variables.variables_initializer(s_obj.variables)) + result = s_obj(y_true, y_pred, sample_weight=weights) + self.assertAlmostEqual(0.4, self.evaluate(result)) + + def test_invalid_sensitivity(self): + with self.assertRaisesRegexp( + ValueError, r'`sensitivity` must be in the range \[0, 1\].'): + metrics.SpecificityAtSensitivity(-1) + + def test_invalid_num_thresholds(self): + with self.assertRaisesRegexp(ValueError, '`num_thresholds` must be > 0.'): + metrics.SpecificityAtSensitivity(0.4, num_thresholds=-1) + + def test_reset_states(self): + s_obj = metrics.SpecificityAtSensitivity(0.5, num_thresholds=1) + model = _get_simple_sequential_model([s_obj]) + x = np.concatenate((np.ones((25, 4)), np.zeros((25, 4)), np.zeros((25, 4)), + np.ones((25, 4)))) + y = np.concatenate((np.ones((25, 1)), np.zeros((25, 1)), np.ones((25, 1)), + np.zeros((25, 1)))) + model.evaluate(x, y) + self.assertEqual(self.evaluate(s_obj.tp), 25.) + self.assertEqual(self.evaluate(s_obj.fp), 25.) + self.assertEqual(self.evaluate(s_obj.fn), 25.) + self.assertEqual(self.evaluate(s_obj.tn), 25.) + model.evaluate(x, y) + self.assertEqual(self.evaluate(s_obj.tp), 25.) + self.assertEqual(self.evaluate(s_obj.fp), 25.) + self.assertEqual(self.evaluate(s_obj.fn), 25.) + self.assertEqual(self.evaluate(s_obj.tn), 25.) + + +@test_util.run_all_in_graph_and_eager_modes +class CosineProximityTest(test.TestCase): + + def test_config(self): + cosine_obj = metrics.CosineProximity(name='my_cos', dtype=dtypes.int32) + self.assertEqual(cosine_obj.name, 'my_cos') + self.assertEqual(cosine_obj._dtype, dtypes.int32) + + def test_unweighted(self): + cosine_obj = metrics.CosineProximity() + self.evaluate(variables.variables_initializer(cosine_obj.variables)) + + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + + update_op = cosine_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = cosine_obj.result() + self.assertAllClose(-0.60723, result, atol=1e-5) + + def test_weighted(self): + cosine_obj = metrics.CosineProximity() + self.evaluate(variables.variables_initializer(cosine_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + sample_weight = constant_op.constant((1., 1.5, 2., 2.5)) + result = cosine_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose(-0.59916, self.evaluate(result), atol=1e-5) if __name__ == '__main__': test.main() diff --git a/tensorflow/python/keras/model_subclassing_test.py b/tensorflow/python/keras/model_subclassing_test.py index aca058b111..620275e50f 100644 --- a/tensorflow/python/keras/model_subclassing_test.py +++ b/tensorflow/python/keras/model_subclassing_test.py @@ -25,6 +25,7 @@ import numpy as np from tensorflow.python import keras from tensorflow.python.data.ops import dataset_ops from tensorflow.python.eager import context +from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops @@ -455,12 +456,12 @@ class ModelSubclassingTest(test.TestCase): model = SimpleTestModel(num_classes=num_classes, use_dp=True, use_bn=True) model.compile(loss='mse', optimizer=RMSPropOptimizer(learning_rate=0.001)) - x = np.ones((num_samples, input_dim)) - y = np.zeros((num_samples, num_classes)) + x = np.ones((num_samples, input_dim), dtype=np.float32) + y = np.zeros((num_samples, num_classes), dtype=np.float32) dataset = dataset_ops.Dataset.from_tensor_slices((x, y)) dataset = dataset.repeat(100) dataset = dataset.batch(10) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) model.fit(iterator, epochs=2, steps_per_epoch=10, verbose=0) _ = model.evaluate(iterator, steps=10, verbose=0) @@ -725,10 +726,41 @@ class ModelSubclassingTest(test.TestCase): _ = model.evaluate(x, y, verbose=0) self.assertEqual(len(model.weights), 16) - self.assertEqual( - len(model.non_trainable_weights), 4) + self.assertEqual(len(model.non_trainable_weights), 4) self.assertEqual(len(model.trainable_weights), 12) + def test_subclass_nested_in_sequential(self): + num_classes = 2 + num_samples = 100 + input_dim = 50 + + class Inner(keras.Model): + + def __init__(self): + super(Inner, self).__init__() + self.dense1 = keras.layers.Dense(32, activation='relu') + self.dense2 = keras.layers.Dense(num_classes, activation='relu') + self.bn = keras.layers.BatchNormalization() + + def call(self, inputs): + x = self.dense1(inputs) + x = self.dense2(x) + return self.bn(x) + + model = keras.Sequential([Inner()]) + model.compile(loss='mse', + optimizer=RMSPropOptimizer(learning_rate=0.001), + metrics=['acc']) + + x = np.ones((num_samples, input_dim)) + y = np.zeros((num_samples, num_classes)) + model.fit(x, y, epochs=2, batch_size=32, verbose=0) + _ = model.evaluate(x, y, verbose=0) + + self.assertEqual(len(model.weights), 8) + self.assertEqual(len(model.non_trainable_weights), 2) + self.assertEqual(len(model.trainable_weights), 6) + def test_support_for_manual_training_arg(self): # In most cases, the `training` argument is left unspecified, in which # case it defaults to value corresponding to the Model method being used @@ -819,9 +851,73 @@ class ModelSubclassingTest(test.TestCase): self.assertEqual([m.dense.kernel, m.dense.bias, m.not_trainable_var], m.non_trainable_variables) + @test_util.run_in_graph_and_eager_modes + def test_add_weight_in_model(self): + + class MyModel(keras.Model): + + def __init__(self): + super(MyModel, self).__init__() + self.b = self.add_weight('bias', (10,)) + self.c = self.add_weight('bias2', (10,), trainable=False) + + def call(self, inputs): + return inputs + self.b + self.c + + x = ops.convert_to_tensor(np.ones((10, 10), 'float32')) + model = MyModel() + model(x) + self.assertEqual(1, len(model.trainable_weights)) + self.assertEqual(1, len(model.non_trainable_weights)) + self.assertEqual(2, len(model.weights)) + + class MyModelCustomBuild(keras.Model): + + def build(self, input_shape): + self.b = self.add_weight('bias', (10,)) + self.c = self.add_weight('bias2', (10,), trainable=False) + + def call(self, inputs): + return inputs + self.b + self.c + + x = ops.convert_to_tensor(np.ones((10, 10), 'float32')) + model = MyModelCustomBuild() + model(x) + self.assertEqual(1, len(model.trainable_weights)) + self.assertEqual(1, len(model.non_trainable_weights)) + self.assertEqual(2, len(model.weights)) + + def test_add_update_in_model(self): + + class MyModel(keras.Model): + + def __init__(self): + super(MyModel, self).__init__() + self.b = self.add_weight('bias', (10,)) + self.c = self.add_weight('bias2', (10,)) + + def call(self, inputs): + # Unconditional + self.add_update(self.b.assign(self.b * 2)) + # Conditional + self.add_update(self.c.assign(inputs[1, :]), inputs) + return inputs + self.b + self.c + + x = ops.convert_to_tensor(np.ones((10, 10), 'float32')) + model = MyModel() + model(x) + + if context.executing_eagerly(): + self.assertEqual(0, len(model.updates)) + else: + self.assertEqual(2, len(model.updates)) + self.assertEqual(1, len(model.get_updates_for(None))) + self.assertEqual(1, len(model.get_updates_for(x))) + class GraphSpecificModelSubclassingTests(test.TestCase): + @test_util.run_deprecated_v1 def test_single_io_workflow_with_tensors(self): num_classes = 2 num_samples = 10 @@ -839,6 +935,7 @@ class GraphSpecificModelSubclassingTests(test.TestCase): model.fit(x, y, epochs=2, steps_per_epoch=10, verbose=0) _ = model.evaluate(steps=10, verbose=0) + @test_util.run_deprecated_v1 def test_multi_io_workflow_with_tensors(self): num_classes = (2, 3) num_samples = 10 @@ -858,6 +955,7 @@ class GraphSpecificModelSubclassingTests(test.TestCase): model.fit([x1, x2], [y1, y2], epochs=2, steps_per_epoch=10, verbose=0) _ = model.evaluate(steps=10, verbose=0) + @test_util.run_deprecated_v1 def test_updates_and_losses_for_nested_models_in_subclassed_model(self): # Case 1: deferred-build sequential nested in subclass. @@ -925,6 +1023,7 @@ class GraphSpecificModelSubclassingTests(test.TestCase): self.assertEqual(len(model.get_updates_for(x)), 2) self.assertEqual(len(model.get_losses_for(x)), 1) + @test_util.run_deprecated_v1 def test_multi_io_workflow_with_numpy_arrays_and_custom_placeholders(self): num_classes = (2, 3) num_samples = 1000 @@ -974,6 +1073,16 @@ class TrainingNoDefaultModel(keras.Model): return self.dense1(x) +class TrainingMaskingModel(keras.Model): + + def __init__(self): + super(TrainingMaskingModel, self).__init__() + self.dense1 = keras.layers.Dense(1) + + def call(self, x, training=False, mask=None): + return self.dense1(x) + + class CustomCallSignatureTests(test.TestCase): @test_util.run_in_graph_and_eager_modes @@ -1003,6 +1112,19 @@ class CustomCallSignatureTests(test.TestCase): 'has been properly built.')) self.assertTrue(model.built, 'Model should be built after calling `build`.') + @test_util.run_in_graph_and_eager_modes + def test_training_and_mask_args_call_build(self): + input_dim = 2 + + model = TrainingMaskingModel() + self.assertFalse(model.built, 'Model should not have been built') + self.assertFalse(model.weights, ('Model should have no weights since it ' + 'has not been built.')) + model.build((None, input_dim)) + self.assertTrue(model.weights, ('Model should have weights now that it ' + 'has been properly built.')) + self.assertTrue(model.built, 'Model should be built after calling `build`.') + @test_util.run_in_graph_and_eager_modes def test_custom_call_kwargs_and_build(self): first_input_shape = (2, 3) diff --git a/tensorflow/python/keras/models.py b/tensorflow/python/keras/models.py index 225c6c6af8..2637191bb7 100644 --- a/tensorflow/python/keras/models.py +++ b/tensorflow/python/keras/models.py @@ -100,17 +100,19 @@ def _clone_functional_model(model, input_tensors=None): input_tensors = list(input_tensors) input_tensors = generic_utils.to_list(input_tensors) input_tensors_ = [] - for i, x in enumerate(input_tensors): - if not K.is_keras_tensor(x): - name = model._input_layers[i].name - input_tensor = Input(tensor=x, name='input_wrapper_for_' + name) + for i in range(len(input_tensors)): + input_tensor = input_tensors[i] + if not K.is_keras_tensor(input_tensor): + original_input_layer = model._input_layers[i] + name = original_input_layer.name + input_tensor = Input(tensor=input_tensor, + name='input_wrapper_for_' + name) input_tensors_.append(input_tensor) # Cache newly created input layer. - original_input_layer = x._keras_history[0] newly_created_input_layer = input_tensor._keras_history[0] layer_map[original_input_layer] = newly_created_input_layer else: - input_tensors_.append(x) + input_tensors_.append(input_tensor) input_tensors = input_tensors_ for x, y in zip(model.inputs, input_tensors): @@ -209,14 +211,17 @@ def _clone_sequential_model(model, input_tensors=None): # Use model._layers to ensure that all layers are cloned. The model's layers # property will exclude the initial InputLayer (if it exists) in the model, # resulting in a different Sequential model structure. - layers = [clone(layer) for layer in model._layers] if input_tensors is None: + layers = [clone(layer) for layer in model._layers] return Sequential(layers=layers, name=model.name) else: # If input tensors are provided, the original model's InputLayer is # overwritten with a different InputLayer. - if isinstance(layers[0], InputLayer): - layers = layers[1:] + layers = [ + clone(layer) + for layer in model._layers + if not isinstance(layer, InputLayer) + ] if len(generic_utils.to_list(input_tensors)) != 1: raise ValueError('To clone a `Sequential` model, we expect ' ' at most one tensor ' @@ -304,8 +309,9 @@ def _in_place_subclassed_model_reset(model): attributes_cache[name] = value assert value in model._layers elif isinstance( - value, (list, tuple)) and name not in ('layers', '_layers', - 'stateful_metric_functions'): + value, + (list, tuple)) and name not in ('layers', '_layers', 'metrics', + '_compile_stateful_metric_functions'): # Handle case: list/tuple of layers (also tracked by the Network API). if value and all(isinstance(val, Layer) for val in value): raise ValueError('We do not support the use of list-of-layers ' @@ -345,9 +351,6 @@ def _in_place_subclassed_model_reset(model): 'targets', '_feed_targets', 'sample_weight_modes', - 'weighted_metrics', - 'metrics_names', - 'metrics_tensors', 'total_loss', 'sample_weights', '_feed_sample_weights', @@ -495,10 +498,11 @@ def clone_and_build_model( clone.compile( optimizer, model.loss, - metrics=metrics_module.clone_metrics(model.metrics), + metrics=metrics_module.clone_metrics(model._compile_metrics), loss_weights=model.loss_weights, sample_weight_mode=model.sample_weight_mode, - weighted_metrics=metrics_module.clone_metrics(model.weighted_metrics), + weighted_metrics=metrics_module.clone_metrics( + model._compile_weighted_metrics), target_tensors=target_tensors) return clone diff --git a/tensorflow/python/keras/models_test.py b/tensorflow/python/keras/models_test.py index bf778f1497..b0872ae3ab 100644 --- a/tensorflow/python/keras/models_test.py +++ b/tensorflow/python/keras/models_test.py @@ -26,10 +26,12 @@ import numpy as np from tensorflow.python import keras from tensorflow.python.eager import context from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops from tensorflow.python.framework import test_util from tensorflow.python.keras import backend as K from tensorflow.python.keras import metrics from tensorflow.python.keras import models +from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import resource_variable_ops from tensorflow.python.platform import test @@ -67,6 +69,7 @@ def sequential_model(add_input_layer, include_input_shape=True): class TestModelCloning(test.TestCase): + @test_util.run_deprecated_v1 def test_clone_sequential_model(self): with self.cached_session(): val_a = np.random.random((10, 4)) @@ -81,25 +84,28 @@ class TestModelCloning(test.TestCase): # With placeholder creation new_model = keras.models.clone_model(model) # update ops from batch norm needs to be included - self.assertEquals(len(new_model.get_updates_for(new_model.inputs)), 2) + self.assertEqual(len(new_model.get_updates_for(new_model.inputs)), 2) new_model.compile('rmsprop', 'mse') new_model.train_on_batch(val_a, val_out) # On top of new tensor input_a = keras.Input(shape=(4,)) new_model = keras.models.clone_model(model, input_tensors=input_a) - self.assertEquals(len(new_model.get_updates_for(new_model.inputs)), 2) + self.assertEqual(len(new_model.get_updates_for(new_model.inputs)), 2) new_model.compile('rmsprop', 'mse') new_model.train_on_batch(val_a, val_out) # On top of new, non-Keras tensor input_a = keras.backend.variable(val_a) new_model = keras.models.clone_model(model, input_tensors=input_a) - self.assertEquals(len(new_model.get_updates_for(new_model.inputs)), 2) + self.assertEqual(len(new_model.get_updates_for(new_model.inputs)), 2) new_model.compile('rmsprop', 'mse') new_model.train_on_batch(None, val_out) + @test_util.run_deprecated_v1 def test_clone_sequential_model_input_layer(self): + + @test_util.run_deprecated_v1 def test_input_layer(include_inputs): with self.cached_session(): val_a = np.random.random((10, 4)) @@ -136,6 +142,7 @@ class TestModelCloning(test.TestCase): test_input_layer(True) test_input_layer(False) + @test_util.run_deprecated_v1 def test_clone_functional_model(self): with self.cached_session(): val_a = np.random.random((10, 4)) @@ -161,7 +168,7 @@ class TestModelCloning(test.TestCase): with self.cached_session(): # With placeholder creation new_model = keras.models.clone_model(model) - self.assertEquals(len(new_model.get_updates_for(new_model.inputs)), 2) + self.assertEqual(len(new_model.get_updates_for(new_model.inputs)), 2) new_model.compile('rmsprop', 'mse') new_model.train_on_batch([val_a, val_b], val_out) @@ -170,7 +177,7 @@ class TestModelCloning(test.TestCase): input_b = keras.Input(shape=(4,), name='b') new_model = keras.models.clone_model( model, input_tensors=[input_a, input_b]) - self.assertEquals(len(new_model.get_updates_for(new_model.inputs)), 2) + self.assertEqual(len(new_model.get_updates_for(new_model.inputs)), 2) new_model.compile('rmsprop', 'mse') new_model.train_on_batch([val_a, val_b], val_out) @@ -179,7 +186,7 @@ class TestModelCloning(test.TestCase): input_b = keras.backend.variable(val_b) new_model = keras.models.clone_model( model, input_tensors=[input_a, input_b]) - self.assertEquals(len(new_model.get_updates_for(new_model.inputs)), 2) + self.assertEqual(len(new_model.get_updates_for(new_model.inputs)), 2) new_model.compile('rmsprop', 'mse') new_model.train_on_batch(None, val_out) @@ -219,6 +226,34 @@ class TestModelCloning(test.TestCase): with self.assertRaises(ValueError): keras.models._clone_sequential_model(seq_model, input_tensors=y) + def test_functional_cloning_does_not_create_unnecessary_placeholders(self): + with ops.Graph().as_default(): + x = keras.Input((4,)) + y = keras.layers.Dense(4)(x) + model = keras.models.Model(x, y) + graph = ops.Graph() + with graph.as_default(): + x = array_ops.ones((10, 4)) + _ = keras.models.clone_model(model, input_tensors=[x]) + has_placeholder = _has_placeholder(graph) + self.assertFalse(has_placeholder) + + def test_sequential_cloning_does_not_create_unnecessary_placeholders(self): + with ops.Graph().as_default(): + model = keras.models.Sequential() + model.add(keras.layers.Dense(4, input_shape=(4,))) + graph = ops.Graph() + with graph.as_default(): + x = array_ops.ones((10, 4)) + _ = keras.models.clone_model(model, input_tensors=[x]) + has_placeholder = _has_placeholder(graph) + self.assertFalse(has_placeholder) + + +def _has_placeholder(graph): + ops_types = [op.type for op in graph.get_operations()] + return any('Placeholder' in s for s in ops_types) + class CheckpointingTests(test.TestCase): @@ -331,7 +366,8 @@ class TestCloneAndBuildModel(test.TestCase): self.assertEqual('mse', model.loss) self.assertTrue( isinstance(model.optimizer, keras.optimizers.RMSprop)) - self.assertEqual(['acc', metrics.categorical_accuracy], model.metrics) + self.assertEqual(['acc', metrics.categorical_accuracy], + model._compile_metrics) def _clone_and_build_test_helper(self, model, is_subclassed=False): inp = np.random.random((10, 4)) @@ -366,6 +402,7 @@ class TestCloneAndBuildModel(test.TestCase): new_model.train_on_batch(inp, out) new_model.evaluate(inp, out) + @test_util.run_deprecated_v1 def test_clone_and_build_compiled_sequential_model(self): with self.cached_session(): model = keras.models.Sequential() @@ -378,6 +415,7 @@ class TestCloneAndBuildModel(test.TestCase): self._clone_and_build_test_helper(model) + @test_util.run_deprecated_v1 def test_clone_and_build_functional_model(self): with self.cached_session(): input_a = keras.Input(shape=(4,)) @@ -394,6 +432,7 @@ class TestCloneAndBuildModel(test.TestCase): self._clone_and_build_test_helper(model) + @test_util.run_deprecated_v1 def test_clone_and_build_subclassed_model(self): class SubclassedModel(keras.Model): @@ -442,9 +481,11 @@ class TestCloneAndBuildModel(test.TestCase): def test_replace_tf_optimizer_iterations_variable(self): self.assert_optimizer_iterations_increases(adam.AdamOptimizer(0.01)) + @test_util.run_deprecated_v1 def test_replace_keras_optimizer_iterations_variable(self): self.assert_optimizer_iterations_increases('adam') + @test_util.run_deprecated_v1 def test_clone_and_build_sequential_model_without_inputs_defined(self): with self.cached_session(): model = sequential_model(False, False) diff --git a/tensorflow/python/keras/optimizer_v2/BUILD b/tensorflow/python/keras/optimizer_v2/BUILD index fb43775fdc..b8f0124941 100644 --- a/tensorflow/python/keras/optimizer_v2/BUILD +++ b/tensorflow/python/keras/optimizer_v2/BUILD @@ -7,14 +7,21 @@ licenses(["notice"]) # Apache 2.0 exports_files(["LICENSE"]) +load("//tensorflow:tensorflow.bzl", "py_test") load("//tensorflow:tensorflow.bzl", "cuda_py_test") py_library( name = "optimizer_v2", srcs = [ + "adadelta.py", + "adagrad.py", "adam.py", + "adamax.py", + "ftrl.py", "gradient_descent.py", + "nadam.py", "optimizer_v2.py", + "rmsprop.py", ], srcs_version = "PY2AND3", deps = [ @@ -24,12 +31,107 @@ py_library( "//tensorflow/python:math_ops", "//tensorflow/python:resource_variable_ops", "//tensorflow/python:state_ops", - "//tensorflow/python:training", "//tensorflow/python:variable_scope", "//tensorflow/python:variables", + "//tensorflow/python/distribute:reduce_util", ], ) +cuda_py_test( + name = "adagrad_test", + size = "medium", + srcs = ["adagrad_test.py"], + additional_deps = [ + ":optimizer_v2", + "//tensorflow/python:client_testlib", + "//tensorflow/python:embedding_ops", + "//tensorflow/python:platform_test", + "//tensorflow/python:framework", + "//tensorflow/python:math_ops", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:resources", + "//tensorflow/python:variables", + "//tensorflow/python/eager:context", + ], + shard_count = 4, +) + +cuda_py_test( + name = "adam_test", + size = "medium", + srcs = ["adam_test.py"], + additional_deps = [ + ":optimizer_v2", + "//tensorflow/python:client_testlib", + "//tensorflow/python:embedding_ops", + "//tensorflow/python:platform_test", + "//tensorflow/python:framework", + "//tensorflow/python:math_ops", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:resources", + "//tensorflow/python:variables", + "//tensorflow/python/eager:context", + ], + shard_count = 4, +) + +cuda_py_test( + name = "adamax_test", + size = "medium", + srcs = ["adamax_test.py"], + additional_deps = [ + ":optimizer_v2", + "//tensorflow/python:client_testlib", + "//tensorflow/python:embedding_ops", + "//tensorflow/python:platform_test", + "//tensorflow/python:framework", + "//tensorflow/python:math_ops", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:resources", + "//tensorflow/python:variables", + "//tensorflow/python/eager:context", + ], + shard_count = 4, +) + +cuda_py_test( + name = "adadelta_test", + size = "medium", + srcs = ["adadelta_test.py"], + additional_deps = [ + ":optimizer_v2", + "//tensorflow/python:client_testlib", + "//tensorflow/python:embedding_ops", + "//tensorflow/python:platform_test", + "//tensorflow/python:framework", + "//tensorflow/python:math_ops", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:resources", + "//tensorflow/python:variables", + "//tensorflow/python/eager:context", + ], + shard_count = 4, +) + +cuda_py_test( + name = "ftrl_test", + size = "medium", + srcs = ["ftrl_test.py"], + additional_deps = [ + ":optimizer_v2", + "//tensorflow/python:client_testlib", + "//tensorflow/python:embedding_ops", + "//tensorflow/python:platform_test", + "//tensorflow/python:framework", + "//tensorflow/python:math_ops", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:resources", + "//tensorflow/python:variables", + "//tensorflow/python/eager:context", + ], + shard_count = 4, +) + cuda_py_test( name = "gradient_descent_test", size = "medium", @@ -50,9 +152,53 @@ cuda_py_test( ) cuda_py_test( - name = "optimizer_v2_test", + name = "nadam_test", size = "medium", + srcs = ["nadam_test.py"], + additional_deps = [ + ":optimizer_v2", + "//tensorflow/python:client_testlib", + "//tensorflow/python:embedding_ops", + "//tensorflow/python:platform_test", + "//tensorflow/python:framework", + "//tensorflow/python:math_ops", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:resources", + "//tensorflow/python:variables", + "//tensorflow/python/eager:context", + ], + shard_count = 4, +) + +py_test( + name = "optimizer_v2_test", + size = "large", srcs = ["optimizer_v2_test.py"], + shard_count = 4, + tags = [ + "no_windows", + ], + deps = [ + ":optimizer_v2", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:clip_ops", + "//tensorflow/python:framework", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:gradients", + "//tensorflow/python:resource_variable_ops", + "//tensorflow/python:state_ops", + "//tensorflow/python:variables", + "//tensorflow/python/eager:def_function", + "//tensorflow/python/keras", + "@absl_py//absl/testing:parameterized", + ], +) + +cuda_py_test( + name = "rmsprop_test", + size = "medium", + srcs = ["rmsprop_test.py"], additional_deps = [ ":optimizer_v2", "//tensorflow/python/eager:def_function", diff --git a/tensorflow/python/keras/optimizer_v2/adadelta.py b/tensorflow/python/keras/optimizer_v2/adadelta.py new file mode 100644 index 0000000000..55b4eba105 --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/adadelta.py @@ -0,0 +1,148 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Adadelta for TensorFlow.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.keras.optimizer_v2 import optimizer_v2 +from tensorflow.python.training import training_ops + + +class Adadelta(optimizer_v2.OptimizerV2): + r"""Optimizer that implements the Adadelta algorithm. + + Adadelta optimization is a stochastic gradient descent method that is based on + adaptive learning rate per dimension to address two drawbacks: + 1) the continual decay of learning rates throughout training + 2) the need for a manually selected global learning rate + + Two accumulation steps are required: + 1) the accumulation of gradients squared, + 2) the accumulation of updates squared. + + Initialization: + + $$accum_g_0 := 0 \text{(Initialize gradient 2nd order moment vector)}$$ + $$accum_x_0 := 0 \text{(Initialize variable update 2nd order moment vector)}$$ + + $$t := t + 1$$ + $$accum_g_t := rho * accum_g_{t-1} + (1 - rho) * g * g$$ + $$delta = -\sqrt{accum_x_{t-1}} / (\sqrt{accum_g_{t-1}} + \epsilon)$$ + $$accum_x_t := rho * accum_x_{t-1} + (1 - rho) * delta * delta$$ + + References + See [M. D. Zeiler](http://arxiv.org/abs/1212.5701) + ([pdf](http://arxiv.org/pdf/1212.5701v1.pdf)) + + """ + + def __init__(self, + learning_rate=0.001, + rho=0.95, + epsilon=1e-7, + name='Adadelta', + **kwargs): + """Construct a new Adadelta optimizer. + + Adadelta is a more robust extension of Adagrad that adapts learning rates + based on a moving window of gradient updates, instead of accumulating all + past gradients. This way, Adadelta continues learning even when many updates + have been done. Compared to Adagrad, in the original version of Adadelta you + don't have to set an initial learning rate. In this version, initial + learning rate can be set, as in most other Keras optimizers. + + Args: + learning_rate: A `Tensor` or a floating point value. The learning rate. + To match the exact form in the original paper use 1.0. + rho: A `Tensor` or a floating point value. The decay rate. + epsilon: A `Tensor` or a floating point value. A constant epsilon used + to better conditioning the grad update. + name: Optional name prefix for the operations created when applying + gradients. Defaults to "Adadelta". + **kwargs: keyword arguments. Allowed to be {`decay`} + + @compatibility(eager) + When eager execution is enabled, `learning_rate`, `rho`, and `epsilon` can + each be a callable that takes no arguments and returns the actual value to + use. This can be useful for changing these values across different + invocations of optimizer functions. + @end_compatibility + """ + super(Adadelta, self).__init__(name, **kwargs) + self._set_hyper('learning_rate', learning_rate) + self._set_hyper('decay', self._initial_decay) + self._set_hyper('rho', rho) + self._set_hyper('epsilon', epsilon) + + def _create_slots(self, var_list): + # Separate for-loops to respect the ordering of slot variables from v1. + for v in var_list: + self.add_slot(v, 'accum_grad') + for v in var_list: + self.add_slot(v, 'accum_var') + + def set_weights(self, weights): + params = self.weights + # Override set_weights for backward compatibility of Keras V1 optimizer + # since it does not include iteration at head of the weight list. Set + # iteration to 0. + if len(params) == len(weights) + 1: + weights = [np.array(0)] + weights + super(Adadelta, self).set_weights(weights) + + def _resource_apply_dense(self, grad, var): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + accum_grad = self.get_slot(var, 'accum_grad') + accum_var = self.get_slot(var, 'accum_var') + return training_ops.resource_apply_adadelta( + var.handle, + accum_grad.handle, + accum_var.handle, + lr_t, + self._get_hyper('rho', var_dtype), + self._get_hyper('epsilon', var_dtype), + grad, + use_locking=self._use_locking) + + def _resource_apply_sparse(self, grad, var, indices): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + accum_grad = self.get_slot(var, 'accum_grad') + accum_var = self.get_slot(var, 'accum_var') + return training_ops.resource_sparse_apply_adadelta( + var.handle, + accum_grad.handle, + accum_var.handle, + lr_t, + self._get_hyper('rho', var_dtype), + self._get_hyper('epsilon', var_dtype), + grad, + indices, + use_locking=self._use_locking) + + def get_config(self): + config = super(Adadelta, self).get_config() + config.update({ + 'learning_rate': self._serialize_hyperparameter('learning_rate'), + 'decay': self._serialize_hyperparameter('decay'), + 'rho': self._serialize_hyperparameter('rho'), + 'epsilon': self._serialize_hyperparameter('epsilon'), + }) + return config diff --git a/tensorflow/python/keras/optimizer_v2/adadelta_test.py b/tensorflow/python/keras/optimizer_v2/adadelta_test.py new file mode 100644 index 0000000000..0fb67d0cd1 --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/adadelta_test.py @@ -0,0 +1,170 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for Adadelta Optimizer.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.eager import context +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util +from tensorflow.python.keras.optimizer_v2 import adadelta +from tensorflow.python.ops import embedding_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import variables +from tensorflow.python.platform import test + + +class AdadeltaOptimizerTest(test.TestCase): + + def doTestBasic(self, use_resource=False, use_callable_params=False): + num_updates = 4 # number of ADADELTA steps to perform + for dtype in [dtypes.half, dtypes.float32]: + for grad in [0.2, 0.1, 0.01]: + for lr in [1.0, 0.5, 0.1]: + var0_init = [1.0, 2.0] + var1_init = [3.0, 4.0] + if use_resource: + var0 = resource_variable_ops.ResourceVariable( + var0_init, dtype=dtype) + var1 = resource_variable_ops.ResourceVariable( + var1_init, dtype=dtype) + else: + var0 = variables.Variable(var0_init, dtype=dtype) + var1 = variables.Variable(var1_init, dtype=dtype) + + grads = constant_op.constant([grad, grad], dtype=dtype) + + accum = 0.0 + accum_update = 0.0 + + # ADADELTA gradient optimizer + rho = 0.95 + epsilon = 1e-8 + if use_callable_params: + adadelta_opt = adadelta.Adadelta( + learning_rate=lambda: lr, # pylint: disable=cell-var-from-loop + rho=lambda: rho, # pylint: disable=cell-var-from-loop + epsilon=lambda: epsilon) # pylint: disable=cell-var-from-loop + else: + adadelta_opt = adadelta.Adadelta( + learning_rate=lr, rho=rho, epsilon=epsilon) + if not context.executing_eagerly(): + adadelta_update = adadelta_opt.apply_gradients( + zip([grads, grads], [var0, var1])) + self.evaluate(variables.global_variables_initializer()) + + # Assign slots + slot = [None] * 2 + slot_update = [None] * 2 + slot[0] = adadelta_opt.get_slot(var0, "accum_grad") + self.assertEqual(slot[0].get_shape(), var0.get_shape()) + + slot_update[0] = adadelta_opt.get_slot(var0, "accum_var") + self.assertEqual(slot_update[0].get_shape(), var0.get_shape()) + + slot[1] = adadelta_opt.get_slot(var1, "accum_grad") + self.assertEqual(slot[1].get_shape(), var1.get_shape()) + + slot_update[1] = adadelta_opt.get_slot(var1, "accum_var") + self.assertEqual(slot_update[1].get_shape(), var1.get_shape()) + + # Fetch params to validate initial values + self.assertAllClose(var0_init, self.evaluate(var0)) + self.assertAllClose(var1_init, self.evaluate(var1)) + + update = [None] * num_updates + tot_update = 0 + for step in range(num_updates): + # Run adadelta update for comparison + if not context.executing_eagerly(): + self.evaluate(adadelta_update) + else: + adadelta_opt.apply_gradients(zip([grads, grads], [var0, var1])) + + # Perform initial update without previous accum values + accum = accum * rho + (grad**2) * (1 - rho) + update[step] = ( + np.sqrt(accum_update + epsilon) * + (1. / np.sqrt(accum + epsilon)) * grad) + accum_update = ( + accum_update * rho + (update[step]**2) * (1.0 - rho)) + tot_update += update[step] * lr + + if not context.executing_eagerly(): + # Check that the accumulators have been updated + # TODO(lxuechen): This is hard to test in eager mode + for slot_idx in range(2): + self.assertAllCloseAccordingToType( + np.array([accum, accum], dtype=dtype.as_numpy_dtype()), + self.evaluate(slot[slot_idx]), + rtol=1e-5) + + self.assertAllCloseAccordingToType( + np.array( + [accum_update, accum_update], + dtype=dtype.as_numpy_dtype()), + self.evaluate(slot_update[slot_idx]), + rtol=1e-5) + + # Check that the parameters have been updated + self.assertAllCloseAccordingToType( + np.array( + [var0_init[0] - tot_update, var0_init[1] - tot_update], + dtype=dtype.as_numpy_dtype()), + self.evaluate(var0), + rtol=1e-5) + + self.assertAllCloseAccordingToType( + np.array( + [var1_init[0] - tot_update, var1_init[1] - tot_update], + dtype=dtype.as_numpy_dtype()), + self.evaluate(var1), + rtol=1e-5) + + @test_util.run_in_graph_and_eager_modes(reset_test=True) + def testResourceBasic(self): + self.doTestBasic(use_resource=True) + + def testBasicCallableParams(self): + with context.eager_mode(): + self.doTestBasic(use_resource=True, use_callable_params=True) + + @test_util.run_deprecated_v1 + def testMinimizeSparseResourceVariable(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0 = resource_variable_ops.ResourceVariable([[1.0, 2.0]], dtype=dtype) + x = constant_op.constant([[4.0], [5.0]], dtype=dtype) + pred = math_ops.matmul(embedding_ops.embedding_lookup([var0], [0]), x) + loss = pred * pred + sgd_op = adadelta.Adadelta(1.0, 1.0, 1.0).minimize( + loss, var_list=[var0]) + variables.global_variables_initializer().run() + # Fetch params to validate initial values + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) + # Run 1 step of sgd + sgd_op.run() + # Validate updated params + self.assertAllCloseAccordingToType([[-111, -138]], self.evaluate(var0)) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/keras/optimizer_v2/adagrad.py b/tensorflow/python/keras/optimizer_v2/adagrad.py new file mode 100644 index 0000000000..670cad70e6 --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/adagrad.py @@ -0,0 +1,171 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Adagrad for TensorFlow.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.framework import ops +from tensorflow.python.keras.optimizer_v2 import optimizer_v2 +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import init_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import state_ops + + +class Adagrad(optimizer_v2.OptimizerV2): + r"""Optimizer that implements the Adagrad algorithm. + + Adagrad is an optimizer with parameter-specific learning rates, + which are adapted relative to how frequently a parameter gets + updated during training. The more updates a parameter receives, + the smaller the updates. + + Initialization: + + $$accum_g_0 := initial_accumulator_value$$ + + $$t := t + 1$$ + $$accum_g_t := accum_g_{t-1} + g * g$$ + $$theta_t := theta_{t-1} - lr * g / (\sqrt{accum_g_t} + \epsilon)$$ + + References + See [paper] + (http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf) + or this + [intro](https://ppasupat.github.io/a9online/uploads/proximal_notes.pdf). + """ + + def __init__(self, + learning_rate=0.001, + initial_accumulator_value=0.1, + epsilon=1e-7, + name='Adagrad', + **kwargs): + """Construct a new Adagrad optimizer. + + Args: + learning_rate: A `Tensor` or a floating point value. The learning rate. + initial_accumulator_value: A floating point value. + Starting value for the accumulators, must be positive. + epsilon: A floating point value. + Starting value for the accumulators, must be positive. + name: Optional name prefix for the operations created when applying + gradients. Defaults to "Adagrad". + **kwargs: keyword arguments. Allowed to be {`decay`} + + Raises: + ValueError: If the `initial_accumulator_value` or `epsilon` is invalid. + + @compatibility(eager) + When eager execution is enabled, `learning_rate` can be a callable that + takes no arguments and returns the actual value to use. This can be useful + for changing these values across different invocations of optimizer + functions. + @end_compatibility + """ + if initial_accumulator_value < 0.0: + raise ValueError('initial_accumulator_value must be non-negative: %s' % + initial_accumulator_value) + if epsilon < 1e-7: + raise ValueError('epsilon must be larger than 1e-7: %s' % epsilon) + super(Adagrad, self).__init__(name, **kwargs) + self._set_hyper('learning_rate', learning_rate) + self._set_hyper('decay', self._initial_decay) + self._initial_accumulator_value = initial_accumulator_value + self._set_hyper('epsilon', epsilon) + + def _create_slots(self, var_list): + for var in var_list: + dtype = var.dtype.base_dtype + init = init_ops.constant_initializer( + self._initial_accumulator_value, dtype=dtype) + self.add_slot(var, 'accumulator', init) + + def set_weights(self, weights): + params = self.weights + # Override set_weights for backward compatibility of Keras V1 optimizer + # since it does not include iteration at head of the weight list. Set + # iteration to 0. + if len(params) == len(weights) + 1: + weights = [np.array(0)] + weights + super(Adagrad, self).set_weights(weights) + + @classmethod + def from_config(cls, config, custom_objects=None): + """Creates an optimizer from its config. + + This method is the reverse of `get_config`, + capable of instantiating the same optimizer from the config + dictionary. + + Arguments: + config: A Python dictionary, typically the output of get_config. + custom_objects: A Python dictionary mapping names to additional Python + objects used to create this optimizer, such as a function used for a + hyperparameter. + + Returns: + An optimizer instance. + """ + if 'initial_accumulator_value' not in config: + config['initial_accumulator_value'] = 0. + if 'lr' in config: + config['learning_rate'] = config.pop('lr') + return cls(**config) + + def _resource_apply_dense(self, grad, var): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + epsilon = self._get_hyper('epsilon', var_dtype) + acc = self.get_slot(var, 'accumulator') + + acc_t = state_ops.assign_add( + acc, math_ops.square(grad), use_locking=self._use_locking) + var_update = state_ops.assign_sub( + var, lr_t * grad / (math_ops.sqrt(acc_t) + epsilon)) + return var_update + + def _resource_apply_sparse(self, grad, var, indices): + + def _resource_scatter_add(x, i, v): + with ops.control_dependencies( + [resource_variable_ops.resource_scatter_add(x.handle, i, v)]): + return x.value() + + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + epsilon = self._get_hyper('epsilon', var_dtype) + acc = self.get_slot(var, 'accumulator') + + acc_t = _resource_scatter_add(acc, indices, math_ops.square(grad)) + acc_t_slice = array_ops.gather(acc_t, indices) + var_update = _resource_scatter_add( + var, indices, -lr_t * grad / (math_ops.sqrt(acc_t_slice) + epsilon)) + return var_update + + def get_config(self): + config = super(Adagrad, self).get_config() + config.update({ + 'learning_rate': self._serialize_hyperparameter('learning_rate'), + 'decay': self._serialize_hyperparameter('decay'), + 'initial_accumulator_value': self._initial_accumulator_value, + 'epsilon': self._serialize_hyperparameter('epsilon'), + }) + return config diff --git a/tensorflow/python/keras/optimizer_v2/adagrad_test.py b/tensorflow/python/keras/optimizer_v2/adagrad_test.py new file mode 100644 index 0000000000..b2c290178f --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/adagrad_test.py @@ -0,0 +1,400 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Functional tests for aggregate operations.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import copy + +import numpy as np + +from tensorflow.python.eager import context +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util +from tensorflow.python.keras.optimizer_v2 import adagrad +from tensorflow.python.ops import embedding_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import variables +from tensorflow.python.platform import test + + +def adagrad_update_numpy(param, accum, g_t, lr=0.001, epsilon=1e-7): + accum_t = accum + g_t * g_t + param_t = param - lr * g_t / (np.sqrt(accum_t) + epsilon) + return param_t, accum_t + + +def sparse_adagrad_update_numpy(param, + accum, + gindexs, + gvalues, + lr=0.001, + epsilon=1e-7): + accum_t = copy.deepcopy(accum) + param_t = copy.deepcopy(param) + # first loop accumulates repeated indices if necessary. + for i in range(len(gindexs)): + gindex = gindexs[i] + gvalue = gvalues[i] + accum_t[gindex] = accum_t[gindex] + gvalue * gvalue + for i in range(len(gindexs)): + gindex = gindexs[i] + gvalue = gvalues[i] + param_t[gindex] = param_t[gindex] - lr * gvalue / ( + np.sqrt(accum_t[gindex]) + epsilon) + return param_t, accum_t + + +class AdagradOptimizerTest(test.TestCase): + + def doTestBasic(self, use_callable_params=False): + for dtype in [dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + + learning_rate = lambda: 3.0 + if not use_callable_params: + learning_rate = learning_rate() + + ada_opt = adagrad.Adagrad(learning_rate) + + accum0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + accum1_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + + if not context.executing_eagerly(): + ada_update = ada_opt.apply_gradients( + zip([grads0, grads1], [var0, var1])) + self.evaluate(variables.global_variables_initializer()) + + # Fetch params to validate initial values + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllClose([1.0, 2.0], v0_val) + self.assertAllClose([3.0, 4.0], v1_val) + + # Run 3 steps of adagrad + for _ in range(3): + if not context.executing_eagerly(): + self.evaluate(ada_update) + else: + ada_opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + var0_np, accum0_np = adagrad_update_numpy(var0_np, accum0_np, + grads0_np, 3.0) + var1_np, accum1_np = adagrad_update_numpy(var1_np, accum1_np, + grads1_np, 3.0) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_in_graph_and_eager_modes(reset_test=True) + def testBasic(self): + self.doTestBasic() + + def testBasicCallableParams(self): + with context.eager_mode(): + self.doTestBasic(use_callable_params=True) + + def testBasicWithLearningRateDecay(self): + for dtype in [dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + + learning_rate = 3.0 + decay = 0.5 + + ada_opt = adagrad.Adagrad(learning_rate, decay=decay) + + accum0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + accum1_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + + if not context.executing_eagerly(): + ada_update = ada_opt.apply_gradients( + zip([grads0, grads1], [var0, var1])) + self.evaluate(variables.global_variables_initializer()) + + # Fetch params to validate initial values + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllClose([1.0, 2.0], v0_val) + self.assertAllClose([3.0, 4.0], v1_val) + + # Run 3 steps of adagrad + for t in range(3): + if not context.executing_eagerly(): + self.evaluate(ada_update) + else: + ada_opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + lr_np = learning_rate / (1 + decay * t) + var0_np, accum0_np = adagrad_update_numpy(var0_np, accum0_np, + grads0_np, lr_np) + var1_np, accum1_np = adagrad_update_numpy(var1_np, accum1_np, + grads1_np, lr_np) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 + def testMinimizeSparseResourceVariable(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0 = resource_variable_ops.ResourceVariable( + [[1.0, 2.0], [3.0, 4.0]], dtype=dtype) + x = constant_op.constant([[4.0], [5.0]], dtype=dtype) + pred = math_ops.matmul(embedding_ops.embedding_lookup([var0], [0]), x) + loss = pred * pred + sgd_op = adagrad.Adagrad(1.0).minimize(loss, var_list=[var0]) + variables.global_variables_initializer().run() + # Fetch params to validate initial values + self.assertAllCloseAccordingToType( + [[1.0, 2.0], [3.0, 4.0]], var0.eval()) + # Run 1 step of sgd + sgd_op.run() + # Validate updated params + self.assertAllCloseAccordingToType( + [[0, 1], [3, 4]], var0.eval(), atol=0.01) + + @test_util.run_deprecated_v1 + def testTensorLearningRate(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + + learning_rate = constant_op.constant(3.0) + ada_opt = adagrad.Adagrad(learning_rate) + ada_update = ada_opt.apply_gradients( + zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], var0.eval()) + self.assertAllClose([3.0, 4.0], var1.eval()) + accum0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + accum1_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + # Run 3 steps of adagrad + for _ in range(3): + ada_update.run() + var0_np, accum0_np = adagrad_update_numpy(var0_np, accum0_np, + grads0_np, learning_rate) + var1_np, accum1_np = adagrad_update_numpy(var1_np, accum1_np, + grads1_np, learning_rate) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 + def testSparseBasic(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0_np = np.array([1.0, 1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + grads0_np_indices = np.array([0, 2], dtype=np.int32) + grads0 = ops.IndexedSlices( + constant_op.constant(grads0_np[grads0_np_indices]), + constant_op.constant(grads0_np_indices), constant_op.constant([3])) + grads1_np_indices = np.array([0, 2], dtype=np.int32) + grads1 = ops.IndexedSlices( + constant_op.constant(grads1_np[grads1_np_indices]), + constant_op.constant(grads1_np_indices), constant_op.constant([3])) + learning_rate = 3.0 + ada_opt = adagrad.Adagrad(learning_rate) + ada_update = ada_opt.apply_gradients( + zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + # Fetch params to validate initial values + self.assertAllClose([1.0, 1.0, 2.0], var0.eval()) + self.assertAllClose([3.0, 3.0, 4.0], var1.eval()) + + accum0_np = np.array([0.1, 0.1, 0.1], dtype=dtype.as_numpy_dtype) + accum1_np = np.array([0.1, 0.1, 0.1], dtype=dtype.as_numpy_dtype) + + # Run 3 step of sgd + for _ in range(3): + ada_update.run() + + var0_np, accum0_np = sparse_adagrad_update_numpy( + var0_np, accum0_np, grads0_np_indices, + grads0_np[grads0_np_indices], learning_rate) + var1_np, accum1_np = sparse_adagrad_update_numpy( + var1_np, accum1_np, grads1_np_indices, + grads1_np[grads1_np_indices], learning_rate) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 + def testSparseRepeatedIndices(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var_np = np.array([[1.0], [2.0]], dtype=dtype.as_numpy_dtype) + + repeated_index_update_var = resource_variable_ops.ResourceVariable( + var_np, dtype=dtype) + aggregated_update_var = resource_variable_ops.ResourceVariable( + var_np, dtype=dtype) + grad_repeated_index = ops.IndexedSlices( + constant_op.constant( + [0.1, 0.1], shape=[2, 1], dtype=dtype), + constant_op.constant([1, 1]), + constant_op.constant([2, 1])) + grad_aggregated = ops.IndexedSlices( + constant_op.constant( + [0.2], shape=[1, 1], dtype=dtype), + constant_op.constant([1]), + constant_op.constant([2, 1])) + repeated_update = adagrad.Adagrad(3.0).apply_gradients( + [(grad_repeated_index, repeated_index_update_var)]) + aggregated_update = adagrad.Adagrad(3.0).apply_gradients( + [(grad_aggregated, aggregated_update_var)]) + variables.global_variables_initializer().run() + self.assertAllClose(aggregated_update_var.eval(), + repeated_index_update_var.eval()) + for _ in range(3): + repeated_update.run() + aggregated_update.run() + self.assertAllClose(aggregated_update_var.eval(), + repeated_index_update_var.eval()) + + @test_util.run_deprecated_v1 + def testSparseRepeatedIndicesByEmbeddingLookUp(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var_repeated = resource_variable_ops.ResourceVariable( + [1.0, 2.0], dtype=dtype) + loss_repeated = math_ops.reduce_sum( + embedding_ops.embedding_lookup(var_repeated, [0, 0])) + var_aggregated = resource_variable_ops.ResourceVariable( + [1.0, 2.0], dtype=dtype) + loss_aggregated = 2 * math_ops.reduce_sum( + embedding_ops.embedding_lookup(var_aggregated, [0])) + update_op_repeated = adagrad.Adagrad(2.0).minimize( + loss_repeated, var_list=[var_repeated]) + update_op_aggregated = adagrad.Adagrad(2.0).minimize( + loss_aggregated, var_list=[var_aggregated]) + variables.global_variables_initializer().run() + self.assertAllCloseAccordingToType( + var_repeated.eval(), var_aggregated.eval()) + for _ in range(3): + update_op_repeated.run() + update_op_aggregated.run() + self.assertAllCloseAccordingToType( + var_repeated.eval(), var_aggregated.eval()) + + @test_util.run_deprecated_v1 + def testSparseStability(self): + for dtype in [dtypes.half]: + with self.cached_session(): + shape = [1, 6] + var0_np = np.array([[ + 0.00872496, -0.106952, 0.110467, 0.226505, -0.0147257, -0.0105945 + ]], + dtype=dtype.as_numpy_dtype) + var0 = resource_variable_ops.ResourceVariable(var0_np) + grads0_np = np.array([[ + -5.91278e-05, 5.31673e-05, -2.5779e-06, 4.29153e-05, -8.4877e-05, + -9.48906e-05 + ]], + dtype=dtype.as_numpy_dtype) + grads0 = ops.IndexedSlices( + constant_op.constant(grads0_np), constant_op.constant([0]), + constant_op.constant(shape)) + ada_opt = adagrad.Adagrad(1.0) + ada_update = ada_opt.apply_gradients(zip([grads0], [var0])) + slot0 = ada_opt.get_slot(var0, "accumulator") + init = variables.global_variables_initializer() + for _ in range(100): + init.run() + ada_update.run() + self.assertAllCloseAccordingToType( + np.array([[0.1, 0.1, 0.1, 0.1, 0.1, 0.1]]), slot0.eval()) + self.assertAllCloseAccordingToType( + np.array([[ + 0.00891194, -0.10712013, 0.11047515, 0.22636929, -0.0144573, + -0.01029443 + ]]), var0.eval()) + + @test_util.run_deprecated_v1 + def testSharing(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + + learning_rate = 3.0 + ada_opt = adagrad.Adagrad(learning_rate) + # Apply the optimizer twice. Both applications will use + # the same accums. + ada_update1 = ada_opt.apply_gradients( + zip([grads0, grads1], [var0, var1])) + ada_update2 = ada_opt.apply_gradients( + zip([grads0, grads1], [var0, var1])) + slot0 = ada_opt.get_slot(var0, "accumulator") + self.assertEqual(slot0.get_shape(), var0.get_shape()) + slot1 = ada_opt.get_slot(var1, "accumulator") + self.assertEqual(slot1.get_shape(), var1.get_shape()) + variables.global_variables_initializer().run() + + # Fetch params to validate initial values. + self.assertAllClose([1.0, 2.0], var0.eval()) + self.assertAllClose([3.0, 4.0], var1.eval()) + # Mix the first and the second adagrad for 3 steps. + ada_update1.run() + ada_update2.run() + ada_update1.run() + + accum0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + accum1_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + for _ in range(3): + var0_np, accum0_np = adagrad_update_numpy(var0_np, accum0_np, + grads0_np, learning_rate) + var1_np, accum1_np = adagrad_update_numpy(var1_np, accum1_np, + grads1_np, learning_rate) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/keras/optimizer_v2/adam.py b/tensorflow/python/keras/optimizer_v2/adam.py index b05811c419..ef3d783f89 100644 --- a/tensorflow/python/keras/optimizer_v2/adam.py +++ b/tensorflow/python/keras/optimizer_v2/adam.py @@ -1,4 +1,4 @@ -# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,8 +17,12 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import ops from tensorflow.python.keras.optimizer_v2 import optimizer_v2 +from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import state_ops from tensorflow.python.training import training_ops @@ -31,36 +35,62 @@ class Adam(optimizer_v2.OptimizerV2): requirement, invariant to diagonal rescaling of gradients, and is well suited for problems that are large in terms of data/parameters'. + Note, amsgrad is currently not supported and the argument can only be False. + # References See [Kingma et al., 2014](http://arxiv.org/abs/1412.6980) ([pdf](http://arxiv.org/pdf/1412.6980.pdf)). + For AMSGrad see [Reddi et al., 2-18] + (https://openreview.net/pdf?id=ryQu7f-RZ) """ def __init__(self, learning_rate=0.001, beta_1=0.9, beta_2=0.999, - epsilon=1e-8, - name='Adam'): + epsilon=1e-7, + amsgrad=False, + name='Adam', + **kwargs): r"""Construct a new Adam optimizer. - Initialization: + If amsgrad = False: + Initialization: + + $$m_0 := 0 \text{(Initialize initial 1st moment vector)}$$ + $$v_0 := 0 \text{(Initialize initial 2nd moment vector)}$$ + $$t := 0 \text{(Initialize timestep)}$$ + + The update rule for `variable` with gradient `g` uses an optimization + described at the end of section2 of the paper: + + $$t := t + 1$$ + $$lr_t := \text{learning\_rate} * \sqrt{1 - beta_2^t} / (1 - beta_1^t)$$ - $$m_0 := 0 \text{(Initialize initial 1st moment vector)}$$ - $$v_0 := 0 \text{(Initialize initial 2nd moment vector)}$$ - $$t := 0 \text{(Initialize timestep)}$$ + $$m_t := beta_1 * m_{t-1} + (1 - beta_1) * g$$ + $$v_t := beta_2 * v_{t-1} + (1 - beta_2) * g * g$$ + $$variable := variable - lr_t * m_t / (\sqrt{v_t} + \epsilon)$$ - The update rule for `variable` with gradient `g` uses an optimization - described at the end of section2 of the paper: + If amsgrad = True: + Initialization: - $$t := t + 1$$ - $$lr_t := \text{learning\_rate} * \sqrt{1 - beta_2^t} / (1 - beta_1^t)$$ + $$m_0 := 0 \text{(Initialize initial 1st moment vector)}$$ + $$v_0 := 0 \text{(Initialize initial 2nd moment vector)}$$ + $$v_hat_0 := 0 \text{(Initialize initial 2nd moment vector)}$$ + $$t := 0 \text{(Initialize timestep)}$$ - $$m_t := beta_1 * m_{t-1} + (1 - beta_1) * g$$ - $$v_t := beta_2 * v_{t-1} + (1 - beta_2) * g * g$$ - $$variable := variable - lr_t * m_t / (\sqrt{v_t} + \epsilon)$$ + The update rule for `variable` with gradient `g` uses an optimization + described at the end of section2 of the paper: - The default value of 1e-8 for epsilon might not be a good default in + $$t := t + 1$$ + $$lr_t := \text{learning\_rate} * \sqrt{1 - beta_2^t} / (1 - beta_1^t)$$ + + $$m_t := beta_1 * m_{t-1} + (1 - beta_1) * g$$ + $$v_t := beta_2 * v_{t-1} + (1 - beta_2) * g * g$$ + $$v_hat_t := max(v_hat_{t-1}, v_t) + $$variable := variable - lr_t * m_t / (\sqrt{v_hat_t} + \epsilon)$$ + + The default value of 1e-7 for epsilon might not be a good default in general. For example, when training an Inception network on ImageNet a current good choice is 1.0 or 0.1. Note that since AdamOptimizer uses the formulation just before Section 2.1 of the Kingma and Ba paper rather than @@ -85,50 +115,142 @@ class Adam(optimizer_v2.OptimizerV2): epsilon: A small constant for numerical stability. This epsilon is "epsilon hat" in the Kingma and Ba paper (in the formula just before Section 2.1), not the epsilon in Algorithm 1 of the paper. + amsgrad: boolean. Whether to apply AMSGrad variant of this algorithm from + the paper "On the Convergence of Adam and beyond". name: Optional name for the operations created when applying gradients. Defaults to "Adam". @compatibility(eager) When eager execution is enabled, `learning_rate`, `beta_1`, `beta_2`, and `epsilon` can each be a callable that takes no arguments and returns the actual value to use. This can be useful for changing these values across different invocations of optimizer functions. @end_compatibility + **kwargs: keyword arguments. Allowed to be {`decay`} """ - super(Adam, self).__init__(name) + super(Adam, self).__init__(name, **kwargs) self._set_hyper('learning_rate', learning_rate) + self._set_hyper('decay', self._initial_decay) self._set_hyper('beta_1', beta_1) self._set_hyper('beta_2', beta_2) self._set_hyper('epsilon', epsilon) + self._amsgrad = amsgrad def _create_slots(self, var_list): # Create slots for the first and second moments. + # Separate for-loops to respect the ordering of slot variables from v1. for var in var_list: self.add_slot(var, 'm') + for var in var_list: self.add_slot(var, 'v') + if self._amsgrad: + for var in var_list: + self.add_slot(var, 'vhat') + + def set_weights(self, weights): + params = self.weights + # If the weights are generated by Keras V1 optimizer, it includes vhats + # even without amsgrad, i.e, V1 optimizer has 3x + 1 variables, while V2 + # optimizer has 2x + 1 variables. Filter vhats out for compatibility. + num_vars = int((len(params) - 1) / 2) + if len(weights) == 3 * num_vars + 1: + weights = weights[:len(params)] + super(Adam, self).set_weights(weights) def _resource_apply_dense(self, grad, var): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) m = self.get_slot(var, 'm') v = self.get_slot(var, 'v') - # TODO(tanzheny): let optimizer have its own step counter, and let - # beta1_power and beta2_power depend on it. - return training_ops.resource_apply_adam( - var.handle, - m.handle, - v.handle, - math_ops.cast(self._get_hyper('beta_1'), grad.dtype.base_dtype), - math_ops.cast(self._get_hyper('beta_2'), grad.dtype.base_dtype), - math_ops.cast(self._get_hyper('learning_rate'), grad.dtype.base_dtype), - math_ops.cast(self._get_hyper('beta_1'), grad.dtype.base_dtype), - math_ops.cast(self._get_hyper('beta_2'), grad.dtype.base_dtype), - math_ops.cast(self._get_hyper('epsilon'), grad.dtype.base_dtype), - grad, - use_locking=self._use_locking) + beta_1_t = self._get_hyper('beta_1', var_dtype) + beta_2_t = self._get_hyper('beta_2', var_dtype) + epsilon = self._get_hyper('epsilon', var_dtype) + local_step = math_ops.cast(self.iterations + 1, var_dtype) + beta_1_power = math_ops.pow(beta_1_t, local_step) + beta_2_power = math_ops.pow(beta_2_t, local_step) + if not self._amsgrad: + return training_ops.resource_apply_adam( + var.handle, + m.handle, + v.handle, + beta_1_power, + beta_2_power, + lr_t, + beta_1_t, + beta_2_t, + epsilon, + grad, + use_locking=self._use_locking) + else: + vhat = self.get_slot(var, 'vhat') + return training_ops.resource_apply_adam_with_amsgrad( + var.handle, + m.handle, + v.handle, + vhat.handle, + beta_1_power, + beta_2_power, + lr_t, + beta_1_t, + beta_2_t, + epsilon, + grad, + use_locking=self._use_locking) + + def _resource_apply_sparse(self, grad, var, indices): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + beta_1_t = self._get_hyper('beta_1', var_dtype) + beta_2_t = self._get_hyper('beta_2', var_dtype) + local_step = math_ops.cast(self.iterations + 1, var_dtype) + beta_1_power = math_ops.pow(beta_1_t, local_step) + beta_2_power = math_ops.pow(beta_2_t, local_step) + epsilon_t = self._get_hyper('epsilon', var_dtype) + lr = (lr_t * math_ops.sqrt(1 - beta_2_power) / (1 - beta_1_power)) + + # m_t = beta1 * m + (1 - beta1) * g_t + m = self.get_slot(var, 'm') + m_scaled_g_values = grad * (1 - beta_1_t) + m_t = state_ops.assign(m, m * beta_1_t, use_locking=self._use_locking) + with ops.control_dependencies([m_t]): + m_t = self._resource_scatter_add(m, indices, m_scaled_g_values) + + # v_t = beta2 * v + (1 - beta2) * (g_t * g_t) + v = self.get_slot(var, 'v') + v_scaled_g_values = (grad * grad) * (1 - beta_2_t) + v_t = state_ops.assign(v, v * beta_2_t, use_locking=self._use_locking) + with ops.control_dependencies([v_t]): + v_t = self._resource_scatter_add(v, indices, v_scaled_g_values) + + if not self._amsgrad: + v_sqrt = math_ops.sqrt(v_t) + var_update = state_ops.assign_sub( + var, lr * m_t / (v_sqrt + epsilon_t), use_locking=self._use_locking) + return control_flow_ops.group(*[var_update, m_t, v_t]) + else: + v_hat = self.get_slot(var, 'vhat') + v_hat_t = math_ops.maximum(v_hat, v_t) + with ops.control_dependencies([v_hat_t]): + v_hat_t = state_ops.assign( + v_hat, v_hat_t, use_locking=self._use_locking) + v_hat_sqrt = math_ops.sqrt(v_hat_t) + var_update = state_ops.assign_sub( + var, + lr * m_t / (v_hat_sqrt + epsilon_t), + use_locking=self._use_locking) + return control_flow_ops.group(*[var_update, m_t, v_t, v_hat_t]) + + def _resource_scatter_add(self, x, i, v): + with ops.control_dependencies( + [resource_variable_ops.resource_scatter_add(x.handle, i, v)]): + return x.value() def get_config(self): config = super(Adam, self).get_config() config.update({ 'learning_rate': self._serialize_hyperparameter('learning_rate'), + 'decay': self._serialize_hyperparameter('decay'), 'beta_1': self._serialize_hyperparameter('beta_1'), 'beta_2': self._serialize_hyperparameter('beta_2'), 'epsilon': self._serialize_hyperparameter('epsilon'), + 'amsgrad': self._amsgrad, }) return config diff --git a/tensorflow/python/keras/optimizer_v2/adam_test.py b/tensorflow/python/keras/optimizer_v2/adam_test.py new file mode 100644 index 0000000000..3bbafe12f8 --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/adam_test.py @@ -0,0 +1,508 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for Adam.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.eager import context +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util +from tensorflow.python.keras import optimizers +from tensorflow.python.keras.optimizer_v2 import adam +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import variables +from tensorflow.python.platform import test + + +def adam_update_numpy(param, + g_t, + t, + m, + v, + lr=0.001, + beta1=0.9, + beta2=0.999, + epsilon=1e-7): + lr_t = lr * np.sqrt(1 - beta2**(t + 1)) / (1 - beta1**(t + 1)) + + m_t = beta1 * m + (1 - beta1) * g_t + v_t = beta2 * v + (1 - beta2) * g_t * g_t + + param_t = param - lr_t * m_t / (np.sqrt(v_t) + epsilon) + return param_t, m_t, v_t + + +def adam_update_numpy_amsgrad(param, + g_t, + t, + m, + v, + vhat, + lr=0.001, + beta1=0.9, + beta2=0.999, + epsilon=1e-7): + lr_t = lr * np.sqrt(1 - beta2**(t + 1)) / (1 - beta1**(t + 1)) + + m_t = beta1 * m + (1 - beta1) * g_t + v_t = beta2 * v + (1 - beta2) * g_t * g_t + vhat_t = np.maximum(vhat, v_t) + + param_t = param - lr_t * m_t / (np.sqrt(vhat_t) + epsilon) + return param_t, m_t, v_t, vhat_t + + +def adam_sparse_update_numpy_amsgrad(param, + indices, + g_t, + t, + m, + v, + vhat, + lr=0.001, + beta1=0.9, + beta2=0.999, + epsilon=1e-7): + m_t, v_t, vhat_t, param_t = (np.copy(m), np.copy(v), np.copy(vhat), + np.copy(param)) + lr_t = lr * np.sqrt(1 - beta2**(t + 1)) / (1 - beta1**(t + 1)) + m_t_slice = beta1 * m[indices] + (1 - beta1) * g_t + v_t_slice = beta2 * v[indices] + (1 - beta2) * g_t * g_t + m_t[indices] = m_t_slice + v_t[indices] = v_t_slice + v_hat_t = np.maximum(vhat_t, v_t) + v_hat_t_slice = v_hat_t[indices] + param_t_slice = param[indices] - ( + lr_t * (m_t_slice / (np.sqrt(v_hat_t_slice) + epsilon))) + param_t[indices] = param_t_slice + return param_t, m_t, v_t, vhat_t + + +def get_beta_accumulators(opt, dtype): + local_step = math_ops.cast(opt.iterations + 1, dtype) + beta_1_t = math_ops.cast(opt._get_hyper("beta_1"), dtype) + beta_1_power = math_ops.pow(beta_1_t, local_step) + beta_2_t = math_ops.cast(opt._get_hyper("beta_2"), dtype) + beta_2_power = math_ops.pow(beta_2_t, local_step) + return (beta_1_power, beta_2_power) + + +class AdamOptimizerTest(test.TestCase): + + @test_util.run_deprecated_v1 + def testSparse(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.0, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.0, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + grads0_np_indices = np.array([0, 2], dtype=np.int32) + grads0 = ops.IndexedSlices( + constant_op.constant(grads0_np[grads0_np_indices]), + constant_op.constant(grads0_np_indices), constant_op.constant([3])) + grads1_np_indices = np.array([0, 2], dtype=np.int32) + grads1 = ops.IndexedSlices( + constant_op.constant(grads1_np[grads1_np_indices]), + constant_op.constant(grads1_np_indices), constant_op.constant([3])) + opt = adam.Adam() + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + # Fetch params to validate initial values + self.assertAllClose([1.0, 1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 3.0, 4.0], self.evaluate(var1)) + + beta_1_power, beta_2_power = get_beta_accumulators(opt, dtype) + # Run 3 steps of Adam + for t in range(3): + self.assertAllCloseAccordingToType(0.9**(t + 1), + self.evaluate(beta_1_power)) + self.assertAllCloseAccordingToType(0.999**(t + 1), + self.evaluate(beta_2_power)) + update.run() + + var0_np, m0, v0 = adam_update_numpy(var0_np, grads0_np, t, m0, v0) + var1_np, m1, v1 = adam_update_numpy(var1_np, grads1_np, t, m1, v1) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 + def testSparseDevicePlacement(self): + for index_dtype in [dtypes.int32, dtypes.int64]: + with self.cached_session(force_gpu=test.is_gpu_available()): + # If a GPU is available, tests that all optimizer ops can be placed on + # it (i.e. they have GPU kernels). + var = variables.Variable([[1.0], [2.0]]) + indices = constant_op.constant([0, 1], dtype=index_dtype) + gathered_sum = math_ops.reduce_sum(array_ops.gather(var, indices)) + optimizer = adam.Adam(3.0) + minimize_op = optimizer.minimize(gathered_sum, var_list=[var]) + variables.global_variables_initializer().run() + minimize_op.run() + + @test_util.run_deprecated_v1 + def testSparseRepeatedIndices(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + repeated_index_update_var = variables.Variable( + [[1.0], [2.0]], dtype=dtype) + aggregated_update_var = variables.Variable( + [[1.0], [2.0]], dtype=dtype) + grad_repeated_index = ops.IndexedSlices( + constant_op.constant( + [0.1, 0.1], shape=[2, 1], dtype=dtype), + constant_op.constant([1, 1]), + constant_op.constant([2, 1])) + grad_aggregated = ops.IndexedSlices( + constant_op.constant( + [0.2], shape=[1, 1], dtype=dtype), + constant_op.constant([1]), + constant_op.constant([2, 1])) + repeated_update = adam.Adam().apply_gradients( + [(grad_repeated_index, repeated_index_update_var)]) + aggregated_update = adam.Adam().apply_gradients( + [(grad_aggregated, aggregated_update_var)]) + variables.global_variables_initializer().run() + self.assertAllClose(aggregated_update_var.eval(), + self.evaluate(repeated_index_update_var)) + for _ in range(3): + repeated_update.run() + aggregated_update.run() + self.assertAllClose(aggregated_update_var.eval(), + self.evaluate(repeated_index_update_var)) + + def doTestBasic(self, use_callable_params=False): + for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]): + with self.session(graph=ops.Graph()): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable( + var0_np, name="var0_%d" % i) + var1 = resource_variable_ops.ResourceVariable( + var1_np, name="var1_%d" % i) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + + learning_rate = lambda: 0.001 + beta1 = lambda: 0.9 + beta2 = lambda: 0.999 + epsilon = lambda: 1e-8 + if not use_callable_params: + learning_rate = learning_rate() + beta1 = beta1() + beta2 = beta2() + epsilon = epsilon() + + opt = adam.Adam(learning_rate=learning_rate) + if not context.executing_eagerly(): + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + + self.evaluate(variables.global_variables_initializer()) + # Run 3 steps of Adam + for t in range(3): + beta_1_power, beta_2_power = get_beta_accumulators(opt, dtype) + self.assertAllCloseAccordingToType(0.9**(t + 1), + self.evaluate(beta_1_power)) + self.assertAllCloseAccordingToType(0.999**(t + 1), + self.evaluate(beta_2_power)) + if not context.executing_eagerly(): + self.evaluate(update) + else: + opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + + var0_np, m0, v0 = adam_update_numpy(var0_np, grads0_np, t, m0, v0) + var1_np, m1, v1 = adam_update_numpy(var1_np, grads1_np, t, m1, v1) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_in_graph_and_eager_modes(reset_test=True) + def testResourceBasic(self): + self.doTestBasic() + + def testBasicCallableParams(self): + with context.eager_mode(): + self.doTestBasic(use_callable_params=True) + + @test_util.run_in_graph_and_eager_modes(reset_test=True) + def testBasicWithAmsgrad(self): + for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]): + with self.session(graph=ops.Graph()): + # Initialize variables for numpy implementation. + m0, v0, v0hat, m1, v1, v1hat = 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable( + var0_np, name="var0_%d" % i) + var1 = resource_variable_ops.ResourceVariable( + var1_np, name="var1_%d" % i) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + + opt = adam.Adam(amsgrad=True) + if not context.executing_eagerly(): + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + + self.evaluate(variables.global_variables_initializer()) + # Run 3 steps of Adam + for t in range(3): + beta_1_power, beta_2_power = get_beta_accumulators(opt, dtype) + self.assertAllCloseAccordingToType(0.9**(t + 1), + self.evaluate(beta_1_power)) + self.assertAllCloseAccordingToType(0.999**(t + 1), + self.evaluate(beta_2_power)) + if not context.executing_eagerly(): + self.evaluate(update) + else: + opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + + var0_np, m0, v0, v0hat = adam_update_numpy_amsgrad( + var0_np, grads0_np, t, m0, v0, v0hat) + var1_np, m1, v1, v1hat = adam_update_numpy_amsgrad( + var1_np, grads1_np, t, m1, v1, v1hat) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_in_graph_and_eager_modes + def testSparseWithAmsgrad(self): + # dtypes.half does not work on gpu + eager. + for dtype in [dtypes.float32, dtypes.float64]: + with self.cached_session(): + m0 = np.array([[0.0], [0.0]]) + v0 = np.array([[0.0], [0.0]]) + v0hat = np.array([[0.0], [0.0]]) + indices_np = np.array([1]) + indices = constant_op.constant(indices_np, dtype=dtypes.int32) + var0_np = np.array([[1.0], [2.0]], dtype=dtype.as_numpy_dtype) + repeated_index_update_var = variables.Variable(var0_np, dtype=dtype) + aggregated_update_var = variables.Variable(var0_np, dtype=dtype) + grads0_np = np.array([[0.2]], dtype=dtype.as_numpy_dtype) + grad_repeated_index = ops.IndexedSlices( + constant_op.constant([0.1, 0.1], shape=[2, 1], dtype=dtype), + constant_op.constant([1, 1]), constant_op.constant([2, 1])) + grad_aggregated = ops.IndexedSlices(grads0_np, indices, + constant_op.constant([2, 1])) + opt_repeated = adam.Adam(amsgrad=True) + opt_aggregated = adam.Adam(amsgrad=True) + if not context.executing_eagerly(): + repeated_update = opt_repeated.apply_gradients( + [(grad_repeated_index, repeated_index_update_var)]) + aggregated_update = opt_aggregated.apply_gradients( + [(grad_aggregated, aggregated_update_var)]) + self.evaluate(variables.global_variables_initializer()) + self.assertAllClose( + self.evaluate(aggregated_update_var), + self.evaluate(repeated_index_update_var)) + for t in range(3): + if not context.executing_eagerly(): + self.evaluate(repeated_update) + self.evaluate(aggregated_update) + else: + opt_repeated.apply_gradients( + [(grad_repeated_index, repeated_index_update_var)]) + opt_aggregated.apply_gradients( + [(grad_aggregated, aggregated_update_var)]) + + var0_np, m0, v0, v0hat = adam_sparse_update_numpy_amsgrad( + var0_np, indices_np, grads0_np, t, m0, v0, v0hat) + + # Validate updated params + self.assertAllCloseAccordingToType( + var0_np, self.evaluate(aggregated_update_var)) + self.assertAllCloseAccordingToType( + self.evaluate(aggregated_update_var), + self.evaluate(repeated_index_update_var)) + + @test_util.run_deprecated_v1 + def testBasicWithLearningRateDecay(self): + for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]): + with self.session(graph=ops.Graph()): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable( + var0_np, name="var0_%d" % i) + var1 = resource_variable_ops.ResourceVariable( + var1_np, name="var1_%d" % i) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + + learning_rate = 0.001 + beta_1 = 0.9 + beta_2 = 0.999 + epsilon = 1e-7 + decay = 0.5 + + opt = adam.Adam( + learning_rate=learning_rate, + beta_1=beta_1, + beta_2=beta_2, + epsilon=epsilon, + decay=decay) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + + self.evaluate(variables.global_variables_initializer()) + # Run 3 steps of Adam + for t in range(3): + self.evaluate(update) + lr_np = learning_rate / (1 + decay * t) + + var0_np, m0, v0 = adam_update_numpy( + var0_np, grads0_np, t, m0, v0, lr=lr_np) + var1_np, m1, v1 = adam_update_numpy( + var1_np, grads1_np, t, m1, v1, lr=lr_np) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 + def testTensorLearningRate(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = variables.Variable(var0_np) + var1 = variables.Variable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + opt = adam.Adam(constant_op.constant(0.001)) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) + + beta_1_power, beta_2_power = get_beta_accumulators(opt, dtype) + # Run 3 steps of Adam + for t in range(3): + self.assertAllCloseAccordingToType(0.9**(t + 1), + self.evaluate(beta_1_power)) + self.assertAllCloseAccordingToType(0.999**(t + 1), + self.evaluate(beta_2_power)) + update.run() + + var0_np, m0, v0 = adam_update_numpy(var0_np, grads0_np, t, m0, v0) + var1_np, m1, v1 = adam_update_numpy(var1_np, grads1_np, t, m1, v1) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 + def testSharing(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = variables.Variable(var0_np) + var1 = variables.Variable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + opt = adam.Adam() + update1 = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + update2 = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + beta_1_power, beta_2_power = get_beta_accumulators(opt, dtype) + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) + + # Run 3 steps of intertwined Adam1 and Adam2. + for t in range(3): + self.assertAllCloseAccordingToType(0.9**(t + 1), + self.evaluate(beta_1_power)) + self.assertAllCloseAccordingToType(0.999**(t + 1), + self.evaluate(beta_2_power)) + if t % 2 == 0: + update1.run() + else: + update2.run() + + var0_np, m0, v0 = adam_update_numpy(var0_np, grads0_np, t, m0, v0) + var1_np, m1, v1 = adam_update_numpy(var1_np, grads1_np, t, m1, v1) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + def testSlotsUniqueEager(self): + with context.eager_mode(): + v1 = resource_variable_ops.ResourceVariable(1.) + v2 = resource_variable_ops.ResourceVariable(1.) + opt = adam.Adam(1.) + opt.minimize(lambda: v1 + v2, var_list=[v1, v2]) + # There should be iteration, and two unique slot variables for v1 and v2. + self.assertEqual(5, len(set(opt.variables()))) + self.assertEqual( + self.evaluate(opt.variables()[0]), self.evaluate(opt.iterations)) + + def testSetWeightsFromV1AdamWithoutMinimize(self): + keras_v1_adam = optimizers.Adam() + keras_v2_adam = adam.Adam() + keras_v2_adam.set_weights(keras_v1_adam.get_weights()) + keras_v1_iteration = keras_v1_adam.iterations + keras_v2_iteration = keras_v2_adam.iterations + self.evaluate(variables.global_variables_initializer()) + self.assertEqual( + self.evaluate(keras_v1_iteration), self.evaluate(keras_v2_iteration)) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/keras/optimizer_v2/adamax.py b/tensorflow/python/keras/optimizer_v2/adamax.py new file mode 100644 index 0000000000..ddd78584f8 --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/adamax.py @@ -0,0 +1,159 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Adamax for TensorFlow.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import ops +from tensorflow.python.keras.optimizer_v2 import adam +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.training import training_ops + + +class Adamax(adam.Adam): + """Optimizer that implements the Adamax algorithm. + + It is a variant of Adam based on the infinity norm. + Default parameters follow those provided in the paper. + Adamax is sometimes superior to adam, specially in models with embeddings. + + References + see Section 7 of [Kingma et al., 2014](http://arxiv.org/abs/1412.6980) + ([pdf](http://arxiv.org/pdf/1412.6980.pdf)). + """ + + def __init__(self, + learning_rate=0.001, + beta_1=0.9, + beta_2=0.999, + epsilon=1e-7, + name='Adamax', + **kwargs): + """Construct a new Adamax optimizer. + + Initialization: + + ``` + m_0 <- 0 (Initialize initial 1st moment vector) + v_0 <- 0 (Initialize the exponentially weighted infinity norm) + t <- 0 (Initialize timestep) + ``` + + The update rule for `variable` with gradient `g` uses an optimization + described at the end of section 7.1 of the paper: + + ``` + t <- t + 1 + + m_t <- beta1 * m_{t-1} + (1 - beta1) * g + v_t <- max(beta2 * v_{t-1}, abs(g)) + variable <- variable - learning_rate / (1 - beta1^t) * m_t / (v_t + epsilon) + ``` + + Similar to AdamOptimizer, the epsilon is added for numerical stability + (especially to get rid of division by zero when v_t = 0). + + Contrast to AdamOptimizer, the sparse implementation of this algorithm + (used when the gradient is an IndexedSlices object, typically because of + `tf.gather` or an embedding lookup in the forward pass) only updates + variable slices and corresponding `m_t`, `v_t` terms when that part of + the variable was used in the forward pass. This means that the sparse + behavior is contrast to the dense behavior (similar to some momentum + implementations which ignore momentum unless a variable slice was actually + used). + + Args: + learning_rate: A Tensor or a floating point value. The learning rate. + beta_1: A float value or a constant float tensor. The exponential decay + rate for the 1st moment estimates. + beta_2: A float value or a constant float tensor. The exponential decay + rate for the exponentially weighted infinity norm. + epsilon: A small constant for numerical stability. + name: Optional name for the operations created when applying gradients. + Defaults to "Adamax". + **kwargs: keyword arguments. Allowed to be {`decay`} + """ + # pylint: disable=useless-super-delegation + super(Adamax, self).__init__( + learning_rate=learning_rate, + beta_1=beta_1, + beta_2=beta_2, + epsilon=epsilon, + amsgrad=False, + name=name, + **kwargs) + # pylint: enable=useless-super-delegation + + def _resource_apply_dense(self, grad, var): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + m = self.get_slot(var, 'm') + v = self.get_slot(var, 'v') + beta_1_t = self._get_hyper('beta_1', var_dtype) + beta_2_t = self._get_hyper('beta_2', var_dtype) + local_step = math_ops.cast(self.iterations + 1, var_dtype) + beta_1_power = math_ops.pow(beta_1_t, local_step) + return training_ops.resource_apply_ada_max( + var.handle, + m.handle, + v.handle, + beta_1_power, + lr_t, + beta_1_t, + beta_2_t, + self._get_hyper('epsilon', var_dtype), + grad, + use_locking=self._use_locking) + + def _resource_apply_sparse(self, grad, var, indices): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + + beta_1_t = self._get_hyper('beta_1', var_dtype) + beta_2_t = self._get_hyper('beta_2', var_dtype) + local_step = math_ops.cast(self.iterations + 1, var_dtype) + beta_1_power = math_ops.pow(beta_1_t, local_step) + epsilon_t = self._get_hyper('epsilon', var_dtype) + + # m_t = beta1 * m + (1 - beta1) * g_t + m = self.get_slot(var, 'm') + m_slice = array_ops.gather(m, indices) + m_t_slice = m_slice * beta_1_t + grad * (1 - beta_1_t) + with ops.control_dependencies([m_t_slice]): + m_t = self._resource_scatter_update(m, indices, m_t_slice) + + # u_t = max(beta2 * u, abs(g_t)) + v = self.get_slot(var, 'v') + v_slice = array_ops.gather(v, indices) + v_t_slice = math_ops.maximum(v_slice * beta_2_t, math_ops.abs(grad)) + with ops.control_dependencies([v_t_slice]): + v_t = self._resource_scatter_update(v, indices, v_t_slice) + # theta_t = theta - lr / (1 - beta1^t) * m_t / u_t + var_slice = -lr_t / (1 - beta_1_power) * ( + m_t_slice / (v_t_slice + epsilon_t)) + with ops.control_dependencies([var_slice]): + var_update = self._resource_scatter_add(var, indices, var_slice) + return control_flow_ops.group(*[var_update, m_t, v_t]) + + def _resource_scatter_update(self, x, i, v): + with ops.control_dependencies( + [resource_variable_ops.resource_scatter_update( + x.handle, i, v)]): + return x.value() diff --git a/tensorflow/python/keras/optimizer_v2/adamax_test.py b/tensorflow/python/keras/optimizer_v2/adamax_test.py new file mode 100644 index 0000000000..baf131fbb0 --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/adamax_test.py @@ -0,0 +1,367 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for Adamax.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.eager import context +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util +from tensorflow.python.keras.optimizer_v2 import adamax +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import variables +from tensorflow.python.platform import test + + +def adamax_update_numpy(param, + g_t, + t, + m, + v, + alpha=0.001, + beta1=0.9, + beta2=0.999, + epsilon=1e-8): + m_t = beta1 * m + (1 - beta1) * g_t + v_t = np.maximum(beta2 * v, np.abs(g_t)) + param_t = param - (alpha / (1 - beta1**(t + 1))) * (m_t / (v_t + epsilon)) + return param_t, m_t, v_t + + +def adamax_sparse_update_numpy(param, + indices, + g_t, + t, + m, + v, + alpha=0.001, + beta1=0.9, + beta2=0.999, + epsilon=1e-8): + m_t, v_t, param_t = np.copy(m), np.copy(v), np.copy(param) + m_t_slice = beta1 * m[indices] + (1 - beta1) * g_t + v_t_slice = np.maximum(beta2 * v[indices], np.abs(g_t)) + param_t_slice = param[indices] - ( + (alpha / (1 - beta1**(t + 1))) * (m_t_slice / (v_t_slice + epsilon))) + m_t[indices] = m_t_slice + v_t[indices] = v_t_slice + param_t[indices] = param_t_slice + return param_t, m_t, v_t + + +def get_beta_accumulators(opt, dtype): + local_step = math_ops.cast(opt.iterations + 1, dtype) + beta_1_t = math_ops.cast(opt._get_hyper("beta_1"), dtype) + beta_1_power = math_ops.pow(beta_1_t, local_step) + return beta_1_power + + +class AdamaxOptimizerTest(test.TestCase): + + def doTestSparse(self, use_resource=False): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + # Initialize variables for numpy implementation. + zero_slots = lambda: np.zeros((3), dtype=dtype.as_numpy_dtype) # pylint: disable=cell-var-from-loop + m0, v0, m1, v1 = zero_slots(), zero_slots(), zero_slots(), zero_slots() + var0_np = np.array([1.0, 2.0, 3.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([4.0, 5.0, 6.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + + grads0_np_indices = np.array([0, 1], dtype=np.int32) + grads0 = ops.IndexedSlices( + constant_op.constant(grads0_np), + constant_op.constant(grads0_np_indices), constant_op.constant([3])) + grads1_np_indices = np.array([2, 1], dtype=np.int32) + grads1 = ops.IndexedSlices( + constant_op.constant(grads1_np), + constant_op.constant(grads1_np_indices), constant_op.constant([3])) + opt = adamax.Adamax() + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0, 3.0], var0.eval()) + self.assertAllClose([4.0, 5.0, 6.0], var1.eval()) + + beta1_power = get_beta_accumulators(opt, dtype) + + # Run 3 steps of Adamax + for t in range(3): + self.assertAllCloseAccordingToType(0.9**(t + 1), beta1_power.eval()) + update.run() + + var0_np, m0, v0 = adamax_sparse_update_numpy( + var0_np, grads0_np_indices, grads0_np, t, m0, v0) + var1_np, m1, v1 = adamax_sparse_update_numpy( + var1_np, grads1_np_indices, grads1_np, t, m1, v1) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, var0.eval()) + self.assertAllCloseAccordingToType(var1_np, var1.eval()) + + @test_util.run_deprecated_v1 + def testResourceSparse(self): + self.doTestSparse(use_resource=True) + + @test_util.run_deprecated_v1 + def testSparseDevicePlacement(self): + for index_dtype in [dtypes.int32, dtypes.int64]: + with self.cached_session(force_gpu=test.is_gpu_available()): + # If a GPU is available, tests that all optimizer ops can be placed on + # it (i.e. they have GPU kernels). + var = variables.Variable([[1.0], [2.0]]) + indices = constant_op.constant([0, 1], dtype=index_dtype) + gathered_sum = math_ops.reduce_sum(array_ops.gather(var, indices)) + optimizer = adamax.Adamax(3.0) + minimize_op = optimizer.minimize(gathered_sum, var_list=[var]) + variables.global_variables_initializer().run() + minimize_op.run() + + @test_util.run_deprecated_v1 + def testSparseRepeatedIndices(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + repeated_index_update_var = variables.Variable( + [[1.0], [2.0]], dtype=dtype) + aggregated_update_var = variables.Variable( + [[1.0], [2.0]], dtype=dtype) + grad_repeated_index = ops.IndexedSlices( + constant_op.constant( + [0.1, 0.1], shape=[2, 1], dtype=dtype), + constant_op.constant([1, 1]), + constant_op.constant([2, 1])) + grad_aggregated = ops.IndexedSlices( + constant_op.constant( + [0.2], shape=[1, 1], dtype=dtype), + constant_op.constant([1]), + constant_op.constant([2, 1])) + repeated_update = adamax.Adamax().apply_gradients( + [(grad_repeated_index, repeated_index_update_var)]) + aggregated_update = adamax.Adamax().apply_gradients( + [(grad_aggregated, aggregated_update_var)]) + variables.global_variables_initializer().run() + self.assertAllClose(aggregated_update_var.eval(), + repeated_index_update_var.eval()) + for _ in range(3): + repeated_update.run() + aggregated_update.run() + self.assertAllClose(aggregated_update_var.eval(), + repeated_index_update_var.eval()) + + @test_util.run_in_graph_and_eager_modes(reset_test=True) + def testBasic(self): + for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]): + with self.session(graph=ops.Graph()): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable( + var0_np, name="var0_%d" % i) + var1 = resource_variable_ops.ResourceVariable( + var1_np, name="var1_%d" % i) + + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + + opt = adamax.Adamax() + if not context.executing_eagerly(): + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + + if not context.executing_eagerly(): + self.evaluate(variables.global_variables_initializer()) + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) + + # Run 3 steps of Adamax + for t in range(3): + beta_1_power = get_beta_accumulators(opt, dtype) + self.assertAllCloseAccordingToType(0.9**(t + 1), + self.evaluate(beta_1_power)) + if not context.executing_eagerly(): + self.evaluate(update) + else: + opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + + var0_np, m0, v0 = adamax_update_numpy(var0_np, grads0_np, t, m0, v0) + var1_np, m1, v1 = adamax_update_numpy(var1_np, grads1_np, t, m1, v1) + + # Validate updated params + self.assertAllCloseAccordingToType( + var0_np, self.evaluate(var0), rtol=1e-2) + self.assertAllCloseAccordingToType( + var1_np, self.evaluate(var1), rtol=1e-2) + + @test_util.run_in_graph_and_eager_modes(reset_test=True) + def testBasicWithLearningRateDecay(self): + for i, dtype in enumerate([dtypes.half, dtypes.float32, dtypes.float64]): + with self.session(graph=ops.Graph()): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable( + var0_np, name="var0_%d" % i) + var1 = resource_variable_ops.ResourceVariable( + var1_np, name="var1_%d" % i) + + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + + learning_rate = 0.001 + decay = 0.002 + opt = adamax.Adamax(learning_rate=learning_rate, decay=decay) + if not context.executing_eagerly(): + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + + if not context.executing_eagerly(): + self.evaluate(variables.global_variables_initializer()) + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) + + # Run 3 steps of Adamax + for t in range(3): + beta_1_power = get_beta_accumulators(opt, dtype) + self.assertAllCloseAccordingToType(0.9**(t + 1), + self.evaluate(beta_1_power)) + if not context.executing_eagerly(): + self.evaluate(update) + else: + opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + + lr = learning_rate / (1 + decay * t) + + var0_np, m0, v0 = adamax_update_numpy( + var0_np, grads0_np, t, m0, v0, alpha=lr) + var1_np, m1, v1 = adamax_update_numpy( + var1_np, grads1_np, t, m1, v1, alpha=lr) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0), + rtol=1e-2) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1), + rtol=1e-2) + + @test_util.run_deprecated_v1 + def testTensorLearningRate(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = variables.Variable(var0_np) + var1 = variables.Variable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + opt = adamax.Adamax(constant_op.constant(0.001)) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], var0.eval()) + self.assertAllClose([3.0, 4.0], var1.eval()) + + beta1_power = get_beta_accumulators(opt, dtype) + + # Run 3 steps of Adamax + for t in range(3): + self.assertAllCloseAccordingToType(0.9**(t + 1), beta1_power.eval()) + update.run() + + var0_np, m0, v0 = adamax_update_numpy(var0_np, grads0_np, t, m0, v0) + var1_np, m1, v1 = adamax_update_numpy(var1_np, grads1_np, t, m1, v1) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, var0.eval()) + self.assertAllCloseAccordingToType(var1_np, var1.eval()) + + @test_util.run_deprecated_v1 + def testSharing(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = variables.Variable(var0_np) + var1 = variables.Variable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + opt = adamax.Adamax() + update1 = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + update2 = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + beta1_power = get_beta_accumulators(opt, dtype) + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], var0.eval()) + self.assertAllClose([3.0, 4.0], var1.eval()) + + # Run 3 steps of intertwined Adamax1 and Adamax2. + for t in range(3): + self.assertAllCloseAccordingToType(0.9**(t + 1), beta1_power.eval()) + if t % 2 == 0: + update1.run() + else: + update2.run() + + var0_np, m0, v0 = adamax_update_numpy(var0_np, grads0_np, t, m0, v0) + var1_np, m1, v1 = adamax_update_numpy(var1_np, grads1_np, t, m1, v1) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, var0.eval()) + self.assertAllCloseAccordingToType(var1_np, var1.eval()) + + def testSlotsUniqueEager(self): + with context.eager_mode(): + v1 = resource_variable_ops.ResourceVariable(1.) + v2 = resource_variable_ops.ResourceVariable(1.) + opt = adamax.Adamax(1.) + opt.minimize(lambda: v1 + v2, var_list=[v1, v2]) + # There should be iteration, and two unique slot variables for v1 and v2. + self.assertEqual(5, len(set(opt.variables()))) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/keras/optimizer_v2/ftrl.py b/tensorflow/python/keras/optimizer_v2/ftrl.py new file mode 100644 index 0000000000..e278e352f5 --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/ftrl.py @@ -0,0 +1,210 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Ftrl-proximal for TensorFlow.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.keras.optimizer_v2 import optimizer_v2 +from tensorflow.python.ops import init_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.training import training_ops + + +class Ftrl(optimizer_v2.OptimizerV2): + """Optimizer that implements the FTRL algorithm. + + See this [paper]( + https://www.eecs.tufts.edu/~dsculley/papers/ad-click-prediction.pdf). + This version has support for both online L2 (the L2 penalty given in the paper + above) and shrinkage-type L2 (which is the addition of an L2 penalty to the + loss function). + """ + + def __init__(self, + learning_rate, + learning_rate_power=-0.5, + initial_accumulator_value=0.1, + l1_regularization_strength=0.0, + l2_regularization_strength=0.0, + name='Ftrl', + l2_shrinkage_regularization_strength=0.0, + **kwargs): + r"""Construct a new FTRL optimizer. + + Args: + learning_rate: A float value or a constant float `Tensor`. + learning_rate_power: A float value, must be less or equal to zero. + Controls how the learning rate decreases during training. Use zero for + a fixed learning rate. + initial_accumulator_value: The starting value for accumulators. + Only zero or positive values are allowed. + l1_regularization_strength: A float value, must be greater than or + equal to zero. + l2_regularization_strength: A float value, must be greater than or + equal to zero. + name: Optional name prefix for the operations created when applying + gradients. Defaults to "Ftrl". + l2_shrinkage_regularization_strength: A float value, must be greater than + or equal to zero. This differs from L2 above in that the L2 above is a + stabilization penalty, whereas this L2 shrinkage is a magnitude penalty. + The FTRL formulation can be written as: + w_{t+1} = argmin_w(\hat{g}_{1:t}w + L1*||w||_1 + L2*||w||_2^2), where + \hat{g} = g + (2*L2_shrinkage*w), and g is the gradient of the loss + function w.r.t. the weights w. + Specifically, in the absence of L1 regularization, it is equivalent to + the following update rule: + w_{t+1} = w_t - lr_t / (1 + 2*L2*lr_t) * g_t - + 2*L2_shrinkage*lr_t / (1 + 2*L2*lr_t) * w_t + where lr_t is the learning rate at t. + When input is sparse shrinkage will only happen on the active weights.\ + **kwargs: keyword arguments. Allowed to be {`decay`} + + Raises: + ValueError: If one of the arguments is invalid. + + References + See [paper] + (https://www.eecs.tufts.edu/~dsculley/papers/ad-click-prediction.pdf) + """ + super(Ftrl, self).__init__(name, **kwargs) + + if initial_accumulator_value < 0.0: + raise ValueError( + 'initial_accumulator_value %f needs to be positive or zero' % + initial_accumulator_value) + if learning_rate_power > 0.0: + raise ValueError('learning_rate_power %f needs to be negative or zero' % + learning_rate_power) + if l1_regularization_strength < 0.0: + raise ValueError( + 'l1_regularization_strength %f needs to be positive or zero' % + l1_regularization_strength) + if l2_regularization_strength < 0.0: + raise ValueError( + 'l2_regularization_strength %f needs to be positive or zero' % + l2_regularization_strength) + if l2_shrinkage_regularization_strength < 0.0: + raise ValueError( + 'l2_shrinkage_regularization_strength %f needs to be positive' + ' or zero' % l2_shrinkage_regularization_strength) + + self._set_hyper('learning_rate', learning_rate) + self._set_hyper('decay', self._initial_decay) + self._set_hyper('learning_rate_power', learning_rate_power) + self._set_hyper('l1_regularization_strength', l1_regularization_strength) + self._set_hyper('l2_regularization_strength', l2_regularization_strength) + self._initial_accumulator_value = initial_accumulator_value + self._l2_shrinkage_regularization_strength = ( + l2_shrinkage_regularization_strength) + + def _create_slots(self, var_list): + # Create the "accum" and "linear" slots. + for var in var_list: + dtype = var.dtype.base_dtype + init = init_ops.constant_initializer( + self._initial_accumulator_value, dtype=dtype) + self.add_slot(var, 'accumulator', init) + self.add_slot(var, 'linear') + + def _resource_apply_dense(self, grad, var): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + learning_rate_power = self._get_hyper('learning_rate_power', var_dtype) + l1_regularization_strength = self._get_hyper('l1_regularization_strength', + var_dtype) + l2_regularization_strength = self._get_hyper('l2_regularization_strength', + var_dtype) + accum = self.get_slot(var, 'accumulator') + linear = self.get_slot(var, 'linear') + if self._l2_shrinkage_regularization_strength <= 0.0: + return training_ops.resource_apply_ftrl( + var.handle, + accum.handle, + linear.handle, + grad, + lr_t, + l1_regularization_strength, + l2_regularization_strength, + learning_rate_power, + use_locking=self._use_locking) + else: + return training_ops.resource_apply_ftrl_v2( + var.handle, + accum.handle, + linear.handle, + grad, + lr_t, + l1_regularization_strength, + l2_regularization_strength, + math_ops.cast(self._l2_shrinkage_regularization_strength, var_dtype), + learning_rate_power, + use_locking=self._use_locking) + + def _resource_apply_sparse(self, grad, var, indices): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + learning_rate_power = self._get_hyper('learning_rate_power', var_dtype) + l1_regularization_strength = self._get_hyper('l1_regularization_strength', + var_dtype) + l2_regularization_strength = self._get_hyper('l2_regularization_strength', + var_dtype) + accum = self.get_slot(var, 'accumulator') + linear = self.get_slot(var, 'linear') + if self._l2_shrinkage_regularization_strength <= 0.0: + return training_ops.resource_sparse_apply_ftrl( + var.handle, + accum.handle, + linear.handle, + grad, + indices, + lr_t, + l1_regularization_strength, + l2_regularization_strength, + learning_rate_power, + use_locking=self._use_locking) + else: + return training_ops.resource_sparse_apply_ftrl_v2( + var.handle, + accum.handle, + linear.handle, + grad, + indices, + lr_t, + l1_regularization_strength, + l2_regularization_strength, + math_ops.cast(self._l2_shrinkage_regularization_strength, var_dtype), + learning_rate_power, + use_locking=self._use_locking) + + def get_config(self): + config = super(Ftrl, self).get_config() + config.update({ + 'learning_rate': + self._serialize_hyperparameter('learning_rate'), + 'decay': + self._serialize_hyperparameter('decay'), + 'initial_accumulator_value': + self._initial_accumulator_value, + 'learning_rate_power': + self._serialize_hyperparameter('learning_rate_power'), + 'l1_regularization_strength': + self._serializer_hyperparameter('l1_regularization_strength'), + 'l2_regularization_strength': + self._serializer_hyperparameter('l2_regularization_strength'), + 'l2_shrinkage_regularization_strength': + self._l2_shrinkage_regularization_strength, + }) + return config diff --git a/tensorflow/python/keras/optimizer_v2/ftrl_test.py b/tensorflow/python/keras/optimizer_v2/ftrl_test.py new file mode 100644 index 0000000000..bec400e8cb --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/ftrl_test.py @@ -0,0 +1,440 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Functional tests for Ftrl operations.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util +from tensorflow.python.keras.optimizer_v2 import ftrl +from tensorflow.python.ops import embedding_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import variables +from tensorflow.python.platform import test +from tensorflow.python.training import adagrad +from tensorflow.python.training import gradient_descent + + +class FtrlOptimizerTest(test.TestCase): + + def doTestFtrlwithoutRegularization(self, use_resource=False): + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session() as sess: + if use_resource: + var0 = resource_variable_ops.ResourceVariable([0.0, 0.0], dtype=dtype) + var1 = resource_variable_ops.ResourceVariable([0.0, 0.0], dtype=dtype) + else: + var0 = variables.Variable([0.0, 0.0], dtype=dtype) + var1 = variables.Variable([0.0, 0.0], dtype=dtype) + grads0 = constant_op.constant([0.1, 0.2], dtype=dtype) + grads1 = constant_op.constant([0.01, 0.02], dtype=dtype) + opt = ftrl.Ftrl( + 3.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.0, + l2_regularization_strength=0.0) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllClose([0.0, 0.0], v0_val) + self.assertAllClose([0.0, 0.0], v1_val) + + # Run 3 steps FTRL + for _ in range(3): + update.run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType( + np.array([-2.60260963, -4.29698515]), v0_val) + self.assertAllCloseAccordingToType( + np.array([-0.28432083, -0.56694895]), v1_val) + + @test_util.run_deprecated_v1 + def testFtrlWithoutRegularization(self): + self.doTestFtrlwithoutRegularization(use_resource=False) + + @test_util.run_deprecated_v1 + def testResourceFtrlWithoutRegularization(self): + self.doTestFtrlwithoutRegularization(use_resource=True) + + @test_util.run_deprecated_v1 + def testFtrlwithoutRegularization2(self): + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session() as sess: + var0 = variables.Variable([1.0, 2.0], dtype=dtype) + var1 = variables.Variable([4.0, 3.0], dtype=dtype) + grads0 = constant_op.constant([0.1, 0.2], dtype=dtype) + grads1 = constant_op.constant([0.01, 0.02], dtype=dtype) + + opt = ftrl.Ftrl( + 3.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.0, + l2_regularization_strength=0.0) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) + self.assertAllCloseAccordingToType([4.0, 3.0], v1_val) + + # Run 3 steps FTRL + for _ in range(3): + update.run() + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType( + np.array([-2.55607247, -3.98729396]), v0_val) + self.assertAllCloseAccordingToType( + np.array([-0.28232238, -0.56096673]), v1_val) + + @test_util.run_deprecated_v1 + def testMinimizeSparseResourceVariable(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0 = resource_variable_ops.ResourceVariable([[1.0, 2.0]], dtype=dtype) + x = constant_op.constant([[4.0], [5.0]], dtype=dtype) + pred = math_ops.matmul(embedding_ops.embedding_lookup([var0], [0]), x) + loss = pred * pred + sgd_op = ftrl.Ftrl(1.0).minimize(loss, var_list=[var0]) + variables.global_variables_initializer().run() + # Fetch params to validate initial values + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) + # Run 1 step of sgd + sgd_op.run() + # Validate updated params + self.assertAllCloseAccordingToType([[0, 1]], + self.evaluate(var0), + atol=0.01) + + @test_util.run_deprecated_v1 + def testFtrlWithL1(self): + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session() as sess: + var0 = variables.Variable([1.0, 2.0], dtype=dtype) + var1 = variables.Variable([4.0, 3.0], dtype=dtype) + grads0 = constant_op.constant([0.1, 0.2], dtype=dtype) + grads1 = constant_op.constant([0.01, 0.02], dtype=dtype) + + opt = ftrl.Ftrl( + 3.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.001, + l2_regularization_strength=0.0) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) + self.assertAllCloseAccordingToType([4.0, 3.0], v1_val) + + # Run 10 steps FTRL + for _ in range(10): + update.run() + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType( + np.array([-7.66718769, -10.91273689]), v0_val) + self.assertAllCloseAccordingToType( + np.array([-0.93460727, -1.86147261]), v1_val) + + @test_util.run_deprecated_v1 + def testFtrlWithL1_L2(self): + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session() as sess: + var0 = variables.Variable([1.0, 2.0], dtype=dtype) + var1 = variables.Variable([4.0, 3.0], dtype=dtype) + grads0 = constant_op.constant([0.1, 0.2], dtype=dtype) + grads1 = constant_op.constant([0.01, 0.02], dtype=dtype) + + opt = ftrl.Ftrl( + 3.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.001, + l2_regularization_strength=2.0) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) + self.assertAllCloseAccordingToType([4.0, 3.0], v1_val) + + # Run 10 steps FTRL + for _ in range(10): + update.run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType( + np.array([-0.24059935, -0.46829352]), v0_val) + self.assertAllCloseAccordingToType( + np.array([-0.02406147, -0.04830509]), v1_val) + + @test_util.run_deprecated_v1 + def testFtrlWithL1_L2_L2Shrinkage(self): + """Test the new FTRL op with support for l2 shrinkage. + + The addition of this parameter which places a constant pressure on weights + towards the origin causes the gradient descent trajectory to differ. The + weights will tend to have smaller magnitudes with this parameter set. + """ + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session() as sess: + var0 = variables.Variable([1.0, 2.0], dtype=dtype) + var1 = variables.Variable([4.0, 3.0], dtype=dtype) + grads0 = constant_op.constant([0.1, 0.2], dtype=dtype) + grads1 = constant_op.constant([0.01, 0.02], dtype=dtype) + + opt = ftrl.Ftrl( + 3.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.001, + l2_regularization_strength=2.0, + l2_shrinkage_regularization_strength=0.1) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) + self.assertAllCloseAccordingToType([4.0, 3.0], v1_val) + + # Run 10 steps FTRL + for _ in range(10): + update.run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType( + np.array([-0.22578995, -0.44345796]), v0_val) + self.assertAllCloseAccordingToType( + np.array([-0.14378493, -0.13229476]), v1_val) + + @test_util.run_deprecated_v1 + def testFtrlWithL1_L2_L2ShrinkageSparse(self): + """Tests the new FTRL op with support for l2 shrinkage on sparse grads.""" + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session() as sess: + var0 = variables.Variable([[1.0], [2.0]], dtype=dtype) + var1 = variables.Variable([[4.0], [3.0]], dtype=dtype) + grads0 = ops.IndexedSlices( + constant_op.constant([0.1], shape=[1, 1], dtype=dtype), + constant_op.constant([0]), constant_op.constant([2, 1])) + grads1 = ops.IndexedSlices( + constant_op.constant([0.02], shape=[1, 1], dtype=dtype), + constant_op.constant([1]), constant_op.constant([2, 1])) + + opt = ftrl.Ftrl( + 3.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.001, + l2_regularization_strength=2.0, + l2_shrinkage_regularization_strength=0.1) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType([[1.0], [2.0]], v0_val) + self.assertAllCloseAccordingToType([[4.0], [3.0]], v1_val) + + # Run 10 steps FTRL + for _ in range(10): + update.run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType([[-0.22578995], [2.]], v0_val) + self.assertAllCloseAccordingToType([[4.], [-0.13229476]], v1_val) + + @test_util.run_deprecated_v1 + def testFtrlWithL2ShrinkageDoesNotChangeLrSchedule(self): + """Verifies that l2 shrinkage in FTRL does not change lr schedule.""" + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session() as sess: + var0 = variables.Variable([1.0, 2.0], dtype=dtype) + var1 = variables.Variable([1.0, 2.0], dtype=dtype) + grads0 = constant_op.constant([0.1, 0.2], dtype=dtype) + grads1 = constant_op.constant([0.1, 0.2], dtype=dtype) + + opt0 = ftrl.Ftrl( + 3.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.001, + l2_regularization_strength=2.0, + l2_shrinkage_regularization_strength=0.1) + opt1 = ftrl.Ftrl( + 3.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.001, + l2_regularization_strength=2.0) + update0 = opt0.apply_gradients([(grads0, var0)]) + update1 = opt1.apply_gradients([(grads1, var1)]) + variables.global_variables_initializer().run() + + v0_val, v1_val = self.evaluate([var0, var1]) + self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) + self.assertAllCloseAccordingToType([1.0, 2.0], v1_val) + + # Run 10 steps FTRL + for _ in range(10): + update0.run() + update1.run() + + v0_val, v1_val = self.evaluate([var0, var1]) + # var0 is experiencing L2 shrinkage so it should be smaller than var1 + # in magnitude. + self.assertTrue((v0_val**2 < v1_val**2).all()) + accum0 = sess.run(opt0.get_slot(var0, "accumulator")) + accum1 = sess.run(opt1.get_slot(var1, "accumulator")) + # L2 shrinkage should not change how we update grad accumulator. + self.assertAllCloseAccordingToType(accum0, accum1) + + def applyOptimizer(self, opt, dtype, steps=5, is_sparse=False): + if is_sparse: + var0 = variables.Variable([[0.0], [0.0]], dtype=dtype) + var1 = variables.Variable([[0.0], [0.0]], dtype=dtype) + grads0 = ops.IndexedSlices( + constant_op.constant([0.1], shape=[1, 1], dtype=dtype), + constant_op.constant([0]), constant_op.constant([2, 1])) + grads1 = ops.IndexedSlices( + constant_op.constant([0.02], shape=[1, 1], dtype=dtype), + constant_op.constant([1]), constant_op.constant([2, 1])) + else: + var0 = variables.Variable([0.0, 0.0], dtype=dtype) + var1 = variables.Variable([0.0, 0.0], dtype=dtype) + grads0 = constant_op.constant([0.1, 0.2], dtype=dtype) + grads1 = constant_op.constant([0.01, 0.02], dtype=dtype) + + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + sess = ops.get_default_session() + v0_val, v1_val = self.evaluate([var0, var1]) + if is_sparse: + self.assertAllCloseAccordingToType([[0.0], [0.0]], v0_val) + self.assertAllCloseAccordingToType([[0.0], [0.0]], v1_val) + else: + self.assertAllCloseAccordingToType([0.0, 0.0], v0_val) + self.assertAllCloseAccordingToType([0.0, 0.0], v1_val) + + # Run Ftrl for a few steps + for _ in range(steps): + update.run() + + v0_val, v1_val = self.evaluate([var0, var1]) + return v0_val, v1_val + + # When variables are initialized with Zero, FTRL-Proximal has two properties: + # 1. Without L1&L2 but with fixed learning rate, FTRL-Proximal is identical + # with GradientDescent. + # 2. Without L1&L2 but with adaptive learning rate, FTRL-Proximal is identical + # with Adagrad. + # So, basing on these two properties, we test if our implementation of + # FTRL-Proximal performs same updates as Adagrad or GradientDescent. + @test_util.run_deprecated_v1 + def testEquivAdagradwithoutRegularization(self): + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session(): + val0, val1 = self.applyOptimizer( + ftrl.Ftrl( + 3.0, + # Adagrad learning rate + learning_rate_power=-0.5, + initial_accumulator_value=0.1, + l1_regularization_strength=0.0, + l2_regularization_strength=0.0), + dtype) + + with self.cached_session(): + val2, val3 = self.applyOptimizer( + adagrad.AdagradOptimizer(3.0, initial_accumulator_value=0.1), dtype) + + self.assertAllCloseAccordingToType(val0, val2) + self.assertAllCloseAccordingToType(val1, val3) + + @test_util.run_deprecated_v1 + def testEquivSparseAdagradwithoutRegularization(self): + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session(): + val0, val1 = self.applyOptimizer( + ftrl.Ftrl( + 3.0, + # Adagrad learning rate + learning_rate_power=-0.5, + initial_accumulator_value=0.1, + l1_regularization_strength=0.0, + l2_regularization_strength=0.0), + dtype, + is_sparse=True) + + with self.cached_session(): + val2, val3 = self.applyOptimizer( + adagrad.AdagradOptimizer(3.0, initial_accumulator_value=0.1), + dtype, + is_sparse=True) + + self.assertAllCloseAccordingToType(val0, val2) + self.assertAllCloseAccordingToType(val1, val3) + + @test_util.run_deprecated_v1 + def testEquivSparseGradientDescentwithoutRegularization(self): + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session(): + val0, val1 = self.applyOptimizer( + ftrl.Ftrl( + 3.0, + # Fixed learning rate + learning_rate_power=-0.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.0, + l2_regularization_strength=0.0), + dtype, + is_sparse=True) + + with self.cached_session(): + val2, val3 = self.applyOptimizer( + gradient_descent.GradientDescentOptimizer(3.0), + dtype, + is_sparse=True) + + self.assertAllCloseAccordingToType(val0, val2) + self.assertAllCloseAccordingToType(val1, val3) + + @test_util.run_deprecated_v1 + def testEquivGradientDescentwithoutRegularization(self): + for dtype in [dtypes.half, dtypes.float32]: + with self.cached_session(): + val0, val1 = self.applyOptimizer( + ftrl.Ftrl( + 3.0, + # Fixed learning rate + learning_rate_power=-0.0, + initial_accumulator_value=0.1, + l1_regularization_strength=0.0, + l2_regularization_strength=0.0), + dtype) + + with self.cached_session(): + val2, val3 = self.applyOptimizer( + gradient_descent.GradientDescentOptimizer(3.0), dtype) + + self.assertAllCloseAccordingToType(val0, val2) + self.assertAllCloseAccordingToType(val1, val3) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/keras/optimizer_v2/gradient_descent.py b/tensorflow/python/keras/optimizer_v2/gradient_descent.py index 90106c941c..2b82b5e78d 100644 --- a/tensorflow/python/keras/optimizer_v2/gradient_descent.py +++ b/tensorflow/python/keras/optimizer_v2/gradient_descent.py @@ -19,7 +19,6 @@ from __future__ import print_function from tensorflow.python.framework import ops from tensorflow.python.keras.optimizer_v2 import optimizer_v2 -from tensorflow.python.ops import math_ops from tensorflow.python.ops import resource_variable_ops from tensorflow.python.training import training_ops @@ -62,7 +61,8 @@ class SGD(optimizer_v2.OptimizerV2): learning_rate=0.001, momentum=0.0, nesterov=False, - name="SGD"): + name="SGD", + **kwargs): """Construct a new Stochastic Gradient Descent or Momentum optimizer. Arguments: @@ -72,9 +72,11 @@ class SGD(optimizer_v2.OptimizerV2): nesterov: boolean. Whether to apply Nesterov momentum. name: Optional name prefix for the operations created when applying gradients. Defaults to 'SGD'. + **kwargs: keyword arguments. Allowed to be {`decay`} """ - super(SGD, self).__init__(name) + super(SGD, self).__init__(name, **kwargs) self._set_hyper("learning_rate", learning_rate) + self._set_hyper("decay", self._initial_decay) self._momentum = False if isinstance(momentum, ops.Tensor) or callable(momentum) or momentum > 0: @@ -91,44 +93,44 @@ class SGD(optimizer_v2.OptimizerV2): self.add_slot(var, "momentum") def _resource_apply_dense(self, grad, var): - learning_rate = self._get_hyper("learning_rate") + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) if self._momentum: momentum_var = self.get_slot(var, "momentum") - return training_ops.resource_apply_momentum( + return training_ops.resource_apply_keras_momentum( var.handle, momentum_var.handle, - math_ops.cast(learning_rate, grad.dtype.base_dtype), + lr_t, grad, - math_ops.cast(self._get_hyper("momentum"), grad.dtype.base_dtype), + self._get_hyper("momentum", var_dtype), use_locking=self._use_locking, use_nesterov=self._nesterov) else: return training_ops.resource_apply_gradient_descent( - var.handle, - math_ops.cast(learning_rate, grad.dtype.base_dtype), - grad, - use_locking=self._use_locking) + var.handle, lr_t, grad, use_locking=self._use_locking) def _resource_apply_sparse_duplicate_indices(self, grad, var, indices): if self._momentum: return super(SGD, self)._resource_apply_sparse_duplicate_indices( grad, var, indices) else: - return resource_variable_ops.resource_scatter_add( - var.handle, indices, -grad * math_ops.cast( - self._get_hyper("learning_rate"), grad.dtype.base_dtype)) + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + return resource_variable_ops.resource_scatter_add(var.handle, indices, + -grad * lr_t) def _resource_apply_sparse(self, grad, var, indices): # This method is only needed for momentum optimization. - learning_rate = self._get_hyper("learning_rate") + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) momentum_var = self.get_slot(var, "momentum") - return training_ops.resource_sparse_apply_momentum( + return training_ops.resource_sparse_apply_keras_momentum( var.handle, momentum_var.handle, - math_ops.cast(learning_rate, grad.dtype.base_dtype), + lr_t, grad, indices, - math_ops.cast(self._get_hyper("momentum"), grad.dtype.base_dtype), + self._get_hyper("momentum", var_dtype), use_locking=self._use_locking, use_nesterov=self._nesterov) @@ -136,6 +138,7 @@ class SGD(optimizer_v2.OptimizerV2): config = super(SGD, self).get_config() config.update({ "learning_rate": self._serialize_hyperparameter("learning_rate"), + "decay": self._serialize_hyperparameter("decay"), "momentum": self._serialize_hyperparameter("momentum"), "nesterov": self._nesterov, }) diff --git a/tensorflow/python/keras/optimizer_v2/gradient_descent_test.py b/tensorflow/python/keras/optimizer_v2/gradient_descent_test.py index b84bf1a6ec..0c64202da8 100644 --- a/tensorflow/python/keras/optimizer_v2/gradient_descent_test.py +++ b/tensorflow/python/keras/optimizer_v2/gradient_descent_test.py @@ -47,7 +47,6 @@ class GradientDescentOptimizerTest(test.TestCase): grads0 = constant_op.constant([0.1, 0.1], dtype=dtype) grads1 = constant_op.constant([0.01, 0.01], dtype=dtype) sgd = gradient_descent.SGD(3.0) - # self.assertFalse(sgd._initial_decay) sgd_op = sgd.apply_gradients(zip([grads0, grads1], [var0, var1])) self.evaluate(variables.global_variables_initializer()) # Run 1 step of sgd @@ -58,6 +57,43 @@ class GradientDescentOptimizerTest(test.TestCase): self.assertAllCloseAccordingToType([3.0 - 3.0 * 0.01, 4.0 - 3.0 * 0.01], self.evaluate(var1)) + @test_util.run_in_graph_and_eager_modes + def testBasicWithLearningRateDecay(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0 = resource_variable_ops.ResourceVariable([1.0, 2.0], dtype=dtype) + var1 = resource_variable_ops.ResourceVariable([3.0, 4.0], dtype=dtype) + grads0 = constant_op.constant([0.1, 0.1], dtype=dtype) + grads1 = constant_op.constant([0.01, 0.01], dtype=dtype) + learning_rate = 3.0 + decay = 0.5 + sgd = gradient_descent.SGD(learning_rate=learning_rate, decay=decay) + if not context.executing_eagerly(): + sgd_op = sgd.apply_gradients(zip([grads0, grads1], [var0, var1])) + self.evaluate(variables.global_variables_initializer()) + # Run 2 steps of sgd + if not context.executing_eagerly(): + self.evaluate(sgd_op) + else: + sgd.apply_gradients(zip([grads0, grads1], [var0, var1])) + # Validate updated params + self.assertAllCloseAccordingToType([1.0 - 3.0 * 0.1, 2.0 - 3.0 * 0.1], + self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0 - 3.0 * 0.01, 4.0 - 3.0 * 0.01], + self.evaluate(var1)) + + if not context.executing_eagerly(): + self.evaluate(sgd_op) + else: + sgd.apply_gradients(zip([grads0, grads1], [var0, var1])) + # Validate updated params + self.assertAllCloseAccordingToType( + [1.0 - 3.0 * 0.1 - 2.0 * 0.1, 2.0 - 3.0 * 0.1 - 2.0 * 0.1], + self.evaluate(var0)) + self.assertAllCloseAccordingToType( + [3.0 - 3.0 * 0.01 - 2.0 * 0.01, 4.0 - 3.0 * 0.01 - 2.0 * 0.01], + self.evaluate(var1)) + @test_util.run_in_graph_and_eager_modes def testBasicCallableParams(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: @@ -98,6 +134,7 @@ class GradientDescentOptimizerTest(test.TestCase): self.evaluate(var0)) self.assertAllCloseAccordingToType([3.0 - 1.0], self.evaluate(var1)) + @test_util.run_deprecated_v1 def testMinimizeSparseResourceVariable(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -137,6 +174,7 @@ class GradientDescentOptimizerTest(test.TestCase): self.assertAllCloseAccordingToType([3.0 - 3.0 * 0.01, 4.0 - 3.0 * 0.01], self.evaluate(var1)) + @test_util.run_deprecated_v1 def testGradWrtRef(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -170,6 +208,37 @@ class GradientDescentOptimizerTest(test.TestCase): self.assertAllCloseAccordingToType([[3.0], [4.0 - 3.0 * 0.01]], self.evaluate(var1)) + @test_util.run_deprecated_v1 + def testSparseBasicWithLearningRateDecay(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0 = variables.Variable([[1.0], [2.0]], dtype=dtype) + var1 = variables.Variable([[3.0], [4.0]], dtype=dtype) + grads0 = ops.IndexedSlices( + constant_op.constant([0.1], shape=[1, 1], dtype=dtype), + constant_op.constant([0]), constant_op.constant([2, 1])) + grads1 = ops.IndexedSlices( + constant_op.constant([0.01], shape=[1, 1], dtype=dtype), + constant_op.constant([1]), constant_op.constant([2, 1])) + sgd_op = gradient_descent.SGD( + 3.0, decay=0.5).apply_gradients( + zip([grads0, grads1], [var0, var1])) + self.evaluate(variables.global_variables_initializer()) + # Run 2 steps of sgd + self.evaluate(sgd_op) + # Validate updated params + self.assertAllCloseAccordingToType([[1.0 - 3.0 * 0.1], [2.0]], + self.evaluate(var0)) + self.assertAllCloseAccordingToType([[3.0], [4.0 - 3.0 * 0.01]], + self.evaluate(var1)) + + self.evaluate(sgd_op) + # Validate updated params + self.assertAllCloseAccordingToType( + [[1.0 - 3.0 * 0.1 - 2.0 * 0.1], [2.0]], self.evaluate(var0)) + self.assertAllCloseAccordingToType( + [[3.0], [4.0 - 3.0 * 0.01 - 2.0 * 0.01]], self.evaluate(var1)) + def testCapturingInDefunWhileExecutingEagerly(self): with context.eager_mode(): optimizer = gradient_descent.SGD(1.0) @@ -194,10 +263,8 @@ class GradientDescentOptimizerTest(test.TestCase): class MomentumOptimizerTest(test.TestCase): def _update_nesterov_momentum_numpy(self, var, accum, g, lr, momentum): - var = var + accum * lr * momentum - accum = accum * momentum + g - var = var - lr * accum - var = var - accum * lr * momentum + accum = accum * momentum - g * lr + var += (accum * momentum - g * lr) return var, accum @test_util.run_in_graph_and_eager_modes @@ -222,9 +289,9 @@ class MomentumOptimizerTest(test.TestCase): # Check we have slots slot0 = mom_opt.get_slot(var0, "momentum") - self.assertEquals(slot0.get_shape(), var0.get_shape()) + self.assertEqual(slot0.get_shape(), var0.get_shape()) slot1 = mom_opt.get_slot(var1, "momentum") - self.assertEquals(slot1.get_shape(), var1.get_shape()) + self.assertEqual(slot1.get_shape(), var1.get_shape()) # Step 1: the momentum accumulators where 0. So we should see a normal # update: v -= grad * learning_rate @@ -232,9 +299,9 @@ class MomentumOptimizerTest(test.TestCase): self.evaluate(mom_update) # Check that the momentum accumulators have been updated. self.assertAllCloseAccordingToType( - np.array([0.1, 0.1]), self.evaluate(slot0)) + np.array([-0.2, -0.2]), self.evaluate(slot0)) self.assertAllCloseAccordingToType( - np.array([0.01, 0.01]), self.evaluate(slot1)) + np.array([-0.02, -0.02]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), @@ -248,11 +315,11 @@ class MomentumOptimizerTest(test.TestCase): mom_opt.apply_gradients(zip([grads0, grads1], [var0, var1])) # Check that the momentum accumulators have been updated. self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), + np.array([(0.9 * (-0.2) - 2.0 * 0.1), (0.9 * (-0.2) - 2.0 * 0.1)]), self.evaluate(slot0)) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), - self.evaluate(slot1)) + np.array([(0.9 * (-0.02) - 2.0 * 0.01), + (0.9 * (-0.02) - 2.0 * 0.01)]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( np.array([ @@ -265,6 +332,7 @@ class MomentumOptimizerTest(test.TestCase): 3.98 - ((0.9 * 0.01 + 0.01) * 2.0) ]), self.evaluate(var1)) + @test_util.run_deprecated_v1 def testNesterovMomentum(self): for dtype in [dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -289,9 +357,10 @@ class MomentumOptimizerTest(test.TestCase): var0_np, accum0_np, var0_np * 10, 2.0, 0.9) var1_np, accum1_np = self._update_nesterov_momentum_numpy( var1_np, accum1_np, 3, 2.0, 0.9) - self.assertAllClose(var0_np, var0.eval()) - self.assertAllClose(var1_np, var1.eval()) + self.assertAllClose(var0_np, self.evaluate(var0)) + self.assertAllClose(var1_np, self.evaluate(var1)) + @test_util.run_deprecated_v1 def testSparseNesterovMomentum(self): for dtype in [dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -329,10 +398,11 @@ class MomentumOptimizerTest(test.TestCase): var0_np, accum0_np, var0_np * 10, 2.0, 0.9) var1_np, accum1_np = self._update_nesterov_momentum_numpy( var1_np, accum1_np, 3, 2.0, 0.9) - self.assertAllClose(var0_np, var0.eval()) - self.assertAllClose(var1_np, var1.eval()) + self.assertAllClose(var0_np, self.evaluate(var0)) + self.assertAllClose(var1_np, self.evaluate(var1)) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testMinimizeSparseResourceVariable(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: # This test invokes the ResourceSparseApplyMomentum operation, which @@ -386,6 +456,7 @@ class MomentumOptimizerTest(test.TestCase): self.evaluate(sgd_op) self.assertAllCloseAccordingToType([[1, 1], [0, 0]], self.evaluate(var0)) + @test_util.run_deprecated_v1 def testTensorLearningRateAndMomentum(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -401,43 +472,50 @@ class MomentumOptimizerTest(test.TestCase): variables.global_variables_initializer().run() # Check we have slots slot0 = mom_opt.get_slot(var0, "momentum") - self.assertEquals(slot0.get_shape(), var0.get_shape()) + self.assertEqual(slot0.get_shape(), var0.get_shape()) slot1 = mom_opt.get_slot(var1, "momentum") - self.assertEquals(slot1.get_shape(), var1.get_shape()) + self.assertEqual(slot1.get_shape(), var1.get_shape()) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Step 1: the momentum accumulators where 0. So we should see a normal # update: v -= grad * learning_rate mom_update.run() # Check that the momentum accumulators have been updated. - self.assertAllCloseAccordingToType(np.array([0.1, 0.1]), slot0.eval()) - self.assertAllCloseAccordingToType(np.array([0.01, 0.01]), slot1.eval()) + self.assertAllCloseAccordingToType( + np.array([-0.2, -0.2]), self.evaluate(slot0)) + self.assertAllCloseAccordingToType( + np.array([-0.02, -0.02]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( - np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), var0.eval()) + np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), + self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), var1.eval()) + np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), + self.evaluate(var1)) # Step 2: the momentum accumulators contain the previous update. mom_update.run() # Check that the momentum accumulators have been updated. self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), slot0.eval()) + np.array([(0.9 * (-0.2) - 2.0 * 0.1), (0.9 * (-0.2) - 2.0 * 0.1)]), + self.evaluate(slot0)) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), slot1.eval()) + np.array([(0.9 * (-0.02) - 2.0 * 0.01), + (0.9 * (-0.02) - 2.0 * 0.01)]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( np.array([ 1.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0), 2.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), 3.98 - ((0.9 * 0.01 + 0.01) * 2.0) - ]), var1.eval()) + ]), self.evaluate(var1)) + @test_util.run_deprecated_v1 def testSparse(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -456,57 +534,65 @@ class MomentumOptimizerTest(test.TestCase): # Check we have slots slot0 = mom_opt.get_slot(var0, "momentum") - self.assertEquals(slot0.get_shape(), var0.get_shape()) + self.assertEqual(slot0.get_shape(), var0.get_shape()) slot1 = mom_opt.get_slot(var1, "momentum") - self.assertEquals(slot1.get_shape(), var1.get_shape()) + self.assertEqual(slot1.get_shape(), var1.get_shape()) # Fetch params to validate initial values - self.assertAllClose([0, 0], var0.eval()[0]) - self.assertAllClose([0, 0], var0.eval()[1]) - self.assertAllClose([1, 1], var1.eval()[2]) + self.assertAllClose([0, 0], self.evaluate(var0)[0]) + self.assertAllClose([0, 0], self.evaluate(var0)[1]) + self.assertAllClose([1, 1], self.evaluate(var1)[2]) # Step 1: the momentum accumulators are 0. So we should see a normal # update: v -= grad * learning_rate mom_update.run() # Check that the momentum accumulators have been updated. - self.assertAllCloseAccordingToType(np.array([0, 0]), slot0.eval()[0]) - self.assertAllCloseAccordingToType(np.array([.1, .1]), slot0.eval()[1]) self.assertAllCloseAccordingToType( - np.array([.01, .01]), - slot1.eval()[2]) + np.array([0, 0]), + self.evaluate(slot0)[0]) + self.assertAllCloseAccordingToType( + np.array([-2.0 * .1, -2.0 * .1]), + self.evaluate(slot0)[1]) + self.assertAllCloseAccordingToType( + np.array([-2.0 * .01, -2.0 * .01]), + self.evaluate(slot1)[2]) # Check that the parameters have been updated. - self.assertAllCloseAccordingToType(np.array([0, 0]), var0.eval()[0]) + self.assertAllCloseAccordingToType( + np.array([0, 0]), + self.evaluate(var0)[0]) self.assertAllCloseAccordingToType( np.array([-(0.1 * 2.0), -(0.1 * 2.0)]), - var0.eval()[1]) + self.evaluate(var0)[1]) self.assertAllCloseAccordingToType( np.array([1.0 - (0.01 * 2.0), 1.0 - (0.01 * 2.0)]), - var1.eval()[2]) + self.evaluate(var1)[2]) # Step 2: the momentum accumulators contain the previous update. mom_update.run() # Check that the momentum accumulators have been updated. - self.assertAllClose(np.array([0, 0]), slot0.eval()[0]) + self.assertAllClose(np.array([0, 0]), self.evaluate(slot0)[0]) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), - slot0.eval()[1]) + np.array([(0.9 * (-0.2) - 2.0 * 0.1), (0.9 * (-0.2) - 2.0 * 0.1)]), + self.evaluate(slot0)[1]) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), - slot1.eval()[2]) + np.array([(0.9 * (-0.02) - 2.0 * 0.01), + (0.9 * (-0.02) - 2.0 * 0.01)]), + self.evaluate(slot1)[2]) # Check that the parameters have been updated. - self.assertAllClose(np.array([0, 0]), var0.eval()[0]) + self.assertAllClose(np.array([0, 0]), self.evaluate(var0)[0]) self.assertAllCloseAccordingToType( np.array([ -(0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0), -(0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0) ]), - var0.eval()[1]) + self.evaluate(var0)[1]) self.assertAllCloseAccordingToType( np.array([ 0.98 - ((0.9 * 0.01 + 0.01) * 2.0), 0.98 - ((0.9 * 0.01 + 0.01) * 2.0) ]), - var1.eval()[2]) + self.evaluate(var1)[2]) + @test_util.run_deprecated_v1 def testSharing(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -522,42 +608,48 @@ class MomentumOptimizerTest(test.TestCase): variables.global_variables_initializer().run() slot0 = mom_opt.get_slot(var0, "momentum") - self.assertEquals(slot0.get_shape(), var0.get_shape()) + self.assertEqual(slot0.get_shape(), var0.get_shape()) slot1 = mom_opt.get_slot(var1, "momentum") - self.assertEquals(slot1.get_shape(), var1.get_shape()) + self.assertEqual(slot1.get_shape(), var1.get_shape()) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Step 1: the momentum accumulators where 0. So we should see a normal # update: v -= grad * learning_rate mom_update1.run() # Check that the momentum accumulators have been updated. - self.assertAllCloseAccordingToType(np.array([0.1, 0.1]), slot0.eval()) - self.assertAllCloseAccordingToType(np.array([0.01, 0.01]), slot1.eval()) + self.assertAllCloseAccordingToType( + np.array([-0.2, -0.2]), self.evaluate(slot0)) + self.assertAllCloseAccordingToType( + np.array([-0.02, -0.02]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( - np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), var0.eval()) + np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), + self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), var1.eval()) + np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), + self.evaluate(var1)) # Step 2: the second momentum accumulators contain the previous update. mom_update2.run() # Check that the momentum accumulators have been updated. self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), slot0.eval()) + np.array([(0.9 * (-0.2) - 2.0 * 0.1), (0.9 * (-0.2) - 2.0 * 0.1)]), + self.evaluate(slot0)) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), slot1.eval()) + np.array([(0.9 * (-0.02) - 2.0 * 0.01), + (0.9 * (-0.02) - 2.0 * 0.01)]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( np.array([ 1.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0), 2.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), 3.98 - ((0.9 * 0.01 + 0.01) * 2.0) - ]), var1.eval()) + ]), self.evaluate(var1)) @test_util.run_in_graph_and_eager_modes def testConfig(self): diff --git a/tensorflow/python/keras/optimizer_v2/nadam.py b/tensorflow/python/keras/optimizer_v2/nadam.py new file mode 100644 index 0000000000..00b095e0dc --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/nadam.py @@ -0,0 +1,143 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Nadam for TensorFlow.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import ops +from tensorflow.python.keras.optimizer_v2 import adam +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import state_ops +from tensorflow.python.training import training_ops + + +class Nadam(adam.Adam): + r"""Optimizer that implements the NAdam algorithm. + + Much like Adam is essentially RMSprop with momentum, Nadam is Adam with + Nesterov momentum. + + Initialization: + + $$m_0 := 0 \text{(Initialize initial 1st moment vector)}$$ + $$v_0 := 0 \text{(Initialize initial 2nd moment vector)}$$ + $$t := 0 \text{(Initialize timestep)}$$ + + Computes: + $$t := t + 1$$ + $$lr_t := \text{learning\_rate} * \sqrt{1 - beta_2^t} / (1 - beta_1^t)$$ + $$m_t := beta_1 * m_{t-1} + (1 - beta_1) * g$$ + $$v_t := beta_2 * v_{t-1} + (1 - beta_2) * g * g$$ + $$m_bar_t := beta_1 * v_t + (1 - beta_1) * g$$ + $$theta_t := theta_{t-1} - lr_t * m_bar_t / (\sqrt{v_t} + \epsilon)$$ + + gradient is evaluated at theta(t) + momentum * v(t), and the variables always + store theta + beta_1 * m / sqrt(v) instead of theta. + + References + See [Dozat, T., 2015](http://cs229.stanford.edu/proj2015/054_report.pdf). + """ + + def __init__(self, + learning_rate=0.001, + beta_1=0.9, + beta_2=0.999, + epsilon=1e-7, + name='Nadam', + **kwargs): + """Construct a new Nadam optimizer. + + Args: + learning_rate: A Tensor or a floating point value. The learning rate. + beta_1: A float value or a constant float tensor. The exponential decay + rate for the 1st moment estimates. + beta_2: A float value or a constant float tensor. The exponential decay + rate for the exponentially weighted infinity norm. + epsilon: A small constant for numerical stability. + name: Optional name for the operations created when applying gradients. + Defaults to "Adamax". + **kwargs: keyword arguments. Allowed to be {`decay`} + """ + + # pylint: disable=useless-super-delegation + super(Nadam, self).__init__( + learning_rate=learning_rate, + beta_1=beta_1, + beta_2=beta_2, + epsilon=epsilon, + amsgrad=False, + name=name, + **kwargs) + # pylint: enable=useless-super-delegation + + def _resource_apply_dense(self, grad, var): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + m = self.get_slot(var, 'm') + v = self.get_slot(var, 'v') + beta_1_t = self._get_hyper('beta_1', var_dtype) + beta_2_t = self._get_hyper('beta_2', var_dtype) + local_step = math_ops.cast(self.iterations + 1, var_dtype) + beta_1_power = math_ops.pow(beta_1_t, local_step) + beta_2_power = math_ops.pow(beta_2_t, local_step) + return training_ops.resource_apply_adam( + var.handle, + m.handle, + v.handle, + beta_1_power, + beta_2_power, + lr_t, + beta_1_t, + beta_2_t, + self._get_hyper('epsilon', var_dtype), + grad, + use_locking=self._use_locking, + use_nesterov=True) + + def _resource_apply_sparse(self, grad, var, indices): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + beta_1_t = self._get_hyper('beta_1', var_dtype) + beta_2_t = self._get_hyper('beta_2', var_dtype) + local_step = math_ops.cast(self.iterations + 1, var_dtype) + beta_1_power = math_ops.pow(beta_1_t, local_step) + beta_2_power = math_ops.pow(beta_2_t, local_step) + epsilon_t = self._get_hyper('epsilon', var_dtype) + lr = (lr_t * math_ops.sqrt(1 - beta_2_power) / (1 - beta_1_power)) + + # m_t = beta1 * m + (1 - beta1) * g_t + m = self.get_slot(var, 'm') + m_scaled_g_values = grad * (1 - beta_1_t) + m_t = state_ops.assign(m, m * beta_1_t, use_locking=self._use_locking) + with ops.control_dependencies([m_t]): + m_t = self._resource_scatter_add(m, indices, m_scaled_g_values) + # m_bar = (1 - beta1) * g_t + beta1 * m_t + m_bar = m_scaled_g_values + beta_1_t * array_ops.gather(m_t, indices) + + # v_t = beta2 * v + (1 - beta2) * (g_t * g_t) + v = self.get_slot(var, 'v') + v_scaled_g_values = (grad * grad) * (1 - beta_2_t) + v_t = state_ops.assign(v, v * beta_2_t, use_locking=self._use_locking) + with ops.control_dependencies([v_t]): + v_t = self._resource_scatter_add(v, indices, v_scaled_g_values) + + v_t_slice = array_ops.gather(v_t, indices) + v_sqrt = math_ops.sqrt(v_t_slice) + var_update = self._resource_scatter_add(var, indices, + -lr * m_bar / (v_sqrt + epsilon_t)) + return control_flow_ops.group(*[var_update, m_bar, v_t]) diff --git a/tensorflow/python/keras/optimizer_v2/nadam_test.py b/tensorflow/python/keras/optimizer_v2/nadam_test.py new file mode 100644 index 0000000000..d991e3117c --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/nadam_test.py @@ -0,0 +1,213 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for Nadam.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util +from tensorflow.python.keras.optimizer_v2 import nadam +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import variables +from tensorflow.python.platform import test + + +def get_beta_accumulators(opt, dtype): + local_step = math_ops.cast(opt.iterations + 1, dtype) + beta_1_t = math_ops.cast(opt._get_hyper("beta_1"), dtype) + beta_1_power = math_ops.pow(beta_1_t, local_step) + beta_2_t = math_ops.cast(opt._get_hyper("beta_2"), dtype) + beta_2_power = math_ops.pow(beta_2_t, local_step) + return (beta_1_power, beta_2_power) + + +def nadam_update_numpy(param, + g_t, + t, + m, + v, + alpha=0.001, + beta1=0.9, + beta2=0.999, + epsilon=1e-8): + alpha_t = alpha * np.sqrt(1 - beta2**(t + 1)) / (1 - beta1**(t + 1)) + + m_t = beta1 * m + (1 - beta1) * g_t + v_t = beta2 * v + (1 - beta2) * g_t * g_t + + m_bar = (1 - beta1) * g_t + beta1 * m_t + + param_t = param - alpha_t * m_bar / (np.sqrt(v_t) + epsilon) + return param_t, m_t, v_t + + +class NadamOptimizerTest(test.TestCase): + + def doTestSparse(self, use_resource=False): + sparse_epsilon = 1e-7 + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0, 0.01], dtype=dtype.as_numpy_dtype) + + if use_resource: + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + else: + var0 = variables.Variable(var0_np) + var1 = variables.Variable(var1_np) + grads0_np_indices = np.array([0, 2], dtype=np.int32) + grads0 = ops.IndexedSlices( + constant_op.constant(grads0_np[grads0_np_indices]), + constant_op.constant(grads0_np_indices), constant_op.constant([3])) + grads1_np_indices = np.array([0, 2], dtype=np.int32) + grads1 = ops.IndexedSlices( + constant_op.constant(grads1_np[grads1_np_indices]), + constant_op.constant(grads1_np_indices), constant_op.constant([3])) + opt = nadam.Nadam(epsilon=sparse_epsilon) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + # Fetch params to validate initial values + self.assertAllClose([1.0, 1.0, 2.0], var0.eval()) + self.assertAllClose([3.0, 3.0, 4.0], var1.eval()) + + beta1_power, beta2_power = get_beta_accumulators(opt, dtype) + + # Run 3 steps of Nadam + for t in range(3): + self.assertAllCloseAccordingToType(0.9**(t + 1), beta1_power.eval()) + self.assertAllCloseAccordingToType(0.999**(t + 1), beta2_power.eval()) + update.run() + + var0_np, m0, v0 = nadam_update_numpy( + var0_np, grads0_np, t, m0, v0, epsilon=sparse_epsilon) + var1_np, m1, v1 = nadam_update_numpy( + var1_np, grads1_np, t, m1, v1, epsilon=sparse_epsilon) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, var0.eval()) + self.assertAllCloseAccordingToType(var1_np, var1.eval()) + + @test_util.run_deprecated_v1 + def testSparse(self): + self.doTestSparse(use_resource=False) + + @test_util.run_deprecated_v1 + def testResourceSparse(self): + self.doTestSparse(use_resource=True) + + def doTestBasic(self, use_resource=False): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + if use_resource: + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + else: + var0 = variables.Variable(var0_np) + var1 = variables.Variable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + opt = nadam.Nadam() + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], var0.eval()) + self.assertAllClose([3.0, 4.0], var1.eval()) + + beta1_power, beta2_power = get_beta_accumulators(opt, dtype) + + # Run 3 steps of Nadam + for t in range(3): + self.assertAllCloseAccordingToType(0.9**(t + 1), beta1_power.eval()) + self.assertAllCloseAccordingToType(0.999**(t + 1), beta2_power.eval()) + update.run() + + var0_np, m0, v0 = nadam_update_numpy(var0_np, grads0_np, t, m0, v0) + var1_np, m1, v1 = nadam_update_numpy(var1_np, grads1_np, t, m1, v1) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, var0.eval()) + self.assertAllCloseAccordingToType(var1_np, var1.eval()) + + @test_util.run_deprecated_v1 + def testResourceBasic(self): + self.doTestBasic(use_resource=True) + + @test_util.run_deprecated_v1 + def testBasicWithLearningRateDecay(self): + for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: + with self.cached_session(): + # Initialize variables for numpy implementation. + m0, v0, m1, v1 = 0.0, 0.0, 0.0, 0.0 + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.01], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + learning_rate = 0.001 + decay = 0.5 + opt = nadam.Nadam(learning_rate=learning_rate, decay=decay) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + variables.global_variables_initializer().run() + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], var0.eval()) + self.assertAllClose([3.0, 4.0], var1.eval()) + + beta1_power, beta2_power = get_beta_accumulators(opt, dtype) + + # Run 3 steps of Nadam + for t in range(3): + self.assertAllCloseAccordingToType(0.9**(t + 1), beta1_power.eval()) + self.assertAllCloseAccordingToType(0.999**(t + 1), beta2_power.eval()) + update.run() + + lr = learning_rate / (1 + decay * t) + var0_np, m0, v0 = nadam_update_numpy( + var0_np, grads0_np, t, m0, v0, alpha=lr) + var1_np, m1, v1 = nadam_update_numpy( + var1_np, grads1_np, t, m1, v1, alpha=lr) + + # Validate updated params + self.assertAllCloseAccordingToType(var0_np, var0.eval()) + self.assertAllCloseAccordingToType(var1_np, var1.eval()) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/keras/optimizer_v2/optimizer_v2.py b/tensorflow/python/keras/optimizer_v2/optimizer_v2.py index c6e1d57c5e..b26b3cefc8 100644 --- a/tensorflow/python/keras/optimizer_v2/optimizer_v2.py +++ b/tensorflow/python/keras/optimizer_v2/optimizer_v2.py @@ -24,16 +24,17 @@ import abc import six +from tensorflow.python.distribute import reduce_util as ds_reduce_util from tensorflow.python.eager import backprop from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.keras import backend from tensorflow.python.keras import initializers -from tensorflow.python.keras.engine import base_layer +from tensorflow.python.keras.engine import base_layer_utils from tensorflow.python.ops import gradients -from tensorflow.python.ops import variable_scope -from tensorflow.python.ops import variables +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import variables as tf_variables from tensorflow.python.platform import tf_logging as logging from tensorflow.python.training import distribution_strategy_context from tensorflow.python.training import optimizer as optimizer_v1 @@ -114,7 +115,7 @@ class OptimizerV2(optimizer_v1.Optimizer): """ - def __init__(self, name): + def __init__(self, name, **kwargs): """Create a new Optimizer. This must be called by the constructors of subclasses. @@ -128,6 +129,7 @@ class OptimizerV2(optimizer_v1.Optimizer): Args: name: A non-empty string. The name to use for accumulators created for the optimizer. + **kwargs: keyword arguments. Allowed to be {`decay`} Raises: ValueError: If name is malformed. @@ -140,6 +142,12 @@ class OptimizerV2(optimizer_v1.Optimizer): # dict: {variable name : {slot name : variable}} self._slots = {} self._weights = [] + + decay = kwargs.pop("decay", 0.0) + if decay < 0.: + raise ValueError("decay cannot be less than 0: {}".format(decay)) + self._initial_decay = decay + self._prepared = False def minimize(self, @@ -296,6 +304,7 @@ class OptimizerV2(optimizer_v1.Optimizer): grads_and_vars = zip(reduced_grads, var_list) with ops.init_scope(): + self._prepare() self._create_slots(var_list) update_ops = [] @@ -317,19 +326,21 @@ class OptimizerV2(optimizer_v1.Optimizer): return update_op with ops.name_scope(name, self._name) as name: - self._prepare() for grad, var in grads_and_vars: scope_name = ("" if ops.executing_eagerly_outside_functions() else "_" + var.op.name) - with ops.name_scope("update" + scope_name), ops.colocate_with(var): + with ops.name_scope("update" + scope_name): update_ops.append(update_grad_to_var(grad, var)) # control dependencies does not work in per replica mode, please change # this once b/118841692 is fixed. # with ops.control_dependencies(update_ops): # apply_updates = self._iterations.assign_add(1).op - apply_updates = merge_update_step(update_ops, self.iteration) + apply_updates = merge_update_step(update_ops, self.iterations) return apply_updates + def get_updates(self, loss, params): + return [self.minimize(loss, params)] + def _set_hyper(self, name, value): """set hyper `name` to value. value can be callable, tensor, numeric.""" if name not in self._hyper: @@ -342,9 +353,14 @@ class OptimizerV2(optimizer_v1.Optimizer): else: backend.set_value(self._hyper[name], value) - def _get_hyper(self, name): + def _get_hyper(self, name, dtype=None): value = self._hyper[name] - return self._call_if_callable(value) + if callable(value): + value = value() + if dtype: + return math_ops.cast(value, dtype) + else: + return value def __getattribute__(self, name): """Overridden to support hyperparameter access.""" @@ -371,12 +387,16 @@ class OptimizerV2(optimizer_v1.Optimizer): else: super(OptimizerV2, self).__setattr__(name, value) - def add_slot(self, var, slot_name): + def add_slot(self, var, slot_name, initializer="zeros"): var_key = _var_key(var) slot_dict = self._slots.setdefault(var_key, {}) if slot_name not in slot_dict: slot_key = _get_slot_key_from_var(var, slot_name) - weight = self.add_weight(name=slot_key, shape=var.shape, dtype=var.dtype) + weight = self.add_weight( + name=slot_key, + shape=var.shape, + dtype=var.dtype, + initializer=initializer) slot_dict[slot_name] = weight self._weights.append(weight) @@ -392,8 +412,10 @@ class OptimizerV2(optimizer_v1.Optimizer): self._iterations = self.add_weight( "iter", shape=[], + dtype=dtypes.int64, trainable=False, - aggregation=variables.VariableAggregation.ONLY_FIRST_REPLICA) + aggregation=tf_variables.VariableAggregation.ONLY_FIRST_REPLICA) + self._weights.append(self._iterations) for name, value in self._hyper.items(): if isinstance(value, ops.Tensor) or callable(value): pass @@ -403,15 +425,24 @@ class OptimizerV2(optimizer_v1.Optimizer): shape=[], trainable=False, initializer=value, - aggregation=variables.VariableAggregation.ONLY_FIRST_REPLICA) + aggregation=tf_variables.VariableAggregation.ONLY_FIRST_REPLICA) self._prepared = True @property - def iteration(self): + def iterations(self): if not self._prepared: self._prepare() return self._iterations + def _decayed_lr(self, var_dtype): + """Get decayed learning rate as a Tensor with dtype=var_dtype.""" + lr_t = self._get_hyper("learning_rate", var_dtype) + if self._initial_decay > 0.: + local_step = math_ops.cast(self.iterations, var_dtype) + decay_t = self._get_hyper("decay", var_dtype) + lr_t = lr_t / (1. + decay_t * local_step) + return lr_t + @abc.abstractmethod def get_config(self): """Returns the config of the optimimizer. @@ -443,6 +474,8 @@ class OptimizerV2(optimizer_v1.Optimizer): Returns: An optimizer instance. """ + if "lr" in config: + config["learning_rate"] = config.pop("lr") return cls(**config) def _serialize_hyperparameter(self, hyperparameter_name): @@ -450,10 +483,14 @@ class OptimizerV2(optimizer_v1.Optimizer): value = self._get_hyper(hyperparameter_name) if callable(value): return value() - if isinstance(value, (ops.Tensor, variables.Variable)): + if isinstance(value, (ops.Tensor, tf_variables.Variable)): return backend.get_value(value) return value + def variables(self): + """Returns variables of this Optimizer based on the order created.""" + return self._weights + @property def weights(self): """Returns variables of this Optimizer based on the order created.""" @@ -490,15 +527,15 @@ class OptimizerV2(optimizer_v1.Optimizer): dtype=None, initializer="zeros", trainable=None, - synchronization=variables.VariableSynchronization.AUTO, - aggregation=variables.VariableAggregation.NONE): + synchronization=tf_variables.VariableSynchronization.AUTO, + aggregation=tf_variables.VariableAggregation.NONE): if dtype is None: dtype = dtypes.float32 if isinstance(initializer, six.string_types) or callable(initializer): initializer = initializers.get(initializer) - if synchronization == variables.VariableSynchronization.ON_READ: + if synchronization == tf_variables.VariableSynchronization.ON_READ: if trainable: raise ValueError( "Synchronization value can be set to " @@ -514,7 +551,7 @@ class OptimizerV2(optimizer_v1.Optimizer): variable = self._add_variable_with_custom_getter( name=name, shape=shape, - getter=base_layer.make_variable, + getter=base_layer_utils.make_variable, overwrite=True, initializer=initializer, dtype=dtype, @@ -522,6 +559,7 @@ class OptimizerV2(optimizer_v1.Optimizer): use_resource=True, synchronization=synchronization, aggregation=aggregation) + backend.track_variable(variable) return variable @@ -561,7 +599,7 @@ def merge_update_step(update_ops, local_step): return incre_op return distribution_strategy_context.get_replica_context().merge_call( - merge_update_step_fn, update_ops, local_step) + merge_update_step_fn, args=(update_ops, local_step)) def merge_grads(grads_and_vars): @@ -569,11 +607,11 @@ def merge_grads(grads_and_vars): def merge_grad_fn(strategy, grads_and_vars): reduced_grads = strategy.batch_reduce( - variable_scope.VariableAggregation.MEAN, grads_and_vars) + ds_reduce_util.ReduceOp.MEAN, grads_and_vars) return reduced_grads return distribution_strategy_context.get_replica_context().merge_call( - merge_grad_fn, grads_and_vars) + merge_grad_fn, args=(grads_and_vars,)) def _var_key(var): diff --git a/tensorflow/python/keras/optimizer_v2/optimizer_v2_test.py b/tensorflow/python/keras/optimizer_v2/optimizer_v2_test.py index 682deda23f..158577fe64 100644 --- a/tensorflow/python/keras/optimizer_v2/optimizer_v2_test.py +++ b/tensorflow/python/keras/optimizer_v2/optimizer_v2_test.py @@ -18,6 +18,13 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import os +import tempfile + +from absl.testing import parameterized +import numpy as np + +from tensorflow.python import keras from tensorflow.python.eager import context from tensorflow.python.eager import def_function from tensorflow.python.eager import function @@ -25,15 +32,27 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import test_util +from tensorflow.python.keras import backend +from tensorflow.python.keras import callbacks +from tensorflow.python.keras import optimizers +from tensorflow.python.keras import testing_utils +from tensorflow.python.keras.engine import input_layer +from tensorflow.python.keras.engine import saving +from tensorflow.python.keras.engine import sequential +from tensorflow.python.keras.engine import training +from tensorflow.python.keras.layers import core from tensorflow.python.keras.optimizer_v2 import adam from tensorflow.python.keras.optimizer_v2 import gradient_descent +from tensorflow.python.keras.optimizer_v2 import optimizer_v2 from tensorflow.python.ops import array_ops from tensorflow.python.ops import clip_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import state_ops from tensorflow.python.ops import variables +from tensorflow.python.platform import gfile from tensorflow.python.platform import test +from tensorflow.python.training import momentum class OptimizerTest(test.TestCase): @@ -279,8 +298,8 @@ class OptimizerTest(test.TestCase): def testIterationWithoutMinimize(self): with self.cached_session(): sgd = gradient_descent.SGD(3.0) - self.evaluate(sgd.iteration.initializer) - self.assertEqual(0, self.evaluate(sgd.iteration)) + self.evaluate(sgd.iterations.initializer) + self.assertEqual(0, self.evaluate(sgd.iterations)) @test_util.run_in_graph_and_eager_modes def testSerializationWithinDefun(self): @@ -341,8 +360,8 @@ class OptimizerTest(test.TestCase): opt2.set_weights(weights) self.evaluate([opt_op_1, opt_op_2]) self.assertAllClose(self.evaluate(var1), self.evaluate(var2)) - self.assertEqual(1, self.evaluate(opt1.iteration)) - self.assertEqual(1, self.evaluate(opt2.iteration)) + self.assertEqual(1, self.evaluate(opt1.iterations)) + self.assertEqual(1, self.evaluate(opt2.iterations)) var3 = resource_variable_ops.ResourceVariable([1.0, 2.0, 3.0], dtype=dtypes.float32) @@ -394,7 +413,231 @@ class OptimizerTest(test.TestCase): with self.assertRaises(AttributeError): opt.not_an_attr += 3 - def testOptimizerWithFunction(self): + @test_util.run_in_graph_and_eager_modes + def testOptimizerWithKerasModel(self): + a = input_layer.Input(shape=(3,), name='input_a') + b = input_layer.Input(shape=(3,), name='input_b') + + dense = core.Dense(4, name='dense') + c = dense(a) + d = dense(b) + e = core.Dropout(0.5, name='dropout')(c) + + model = training.Model([a, b], [d, e]) + + optimizer = gradient_descent.SGD(learning_rate=0.001) + loss = 'mse' + model.compile(optimizer, loss, metrics=['mae']) + + input_a_np = np.random.random((10, 3)) + input_b_np = np.random.random((10, 3)) + + output_d_np = np.random.random((10, 4)) + output_e_np = np.random.random((10, 4)) + + model.fit([input_a_np, input_b_np], [output_d_np, output_e_np], + epochs=1, + batch_size=5) + + @test_util.run_in_graph_and_eager_modes + def testOptimizerWithCallbacks(self): + input_np = np.random.random((10, 3)) + output_np = np.random.random((10, 4)) + a = input_layer.Input(shape=(3,), name='input_a') + model = sequential.Sequential() + model.add(core.Dense(4, name='dense')) + model.add(core.Dropout(0.5, name='dropout')) + model(a) + optimizer = gradient_descent.SGD(learning_rate=0.1) + model.compile(optimizer, loss='mse', metrics=['mae']) + # This does not reduce the LR after the first epoch (due to low delta). + cbks = [ + callbacks.ReduceLROnPlateau( + monitor='val_loss', factor=0.1, min_delta=0, patience=1, cooldown=5) + ] + model.fit( + input_np, + output_np, + batch_size=10, + validation_data=(input_np, output_np), + callbacks=cbks, + epochs=5, + verbose=0) + self.assertAllClose( + float(backend.get_value(model.optimizer.lr)), 0.1, atol=1e-4) + + # This should reduce the LR after the first epoch (due to high delta). + cbks = [ + callbacks.ReduceLROnPlateau( + monitor='val_loss', + factor=0.1, + min_delta=10, + patience=1, + cooldown=5) + ] + model.fit( + input_np, + output_np, + batch_size=10, + validation_data=(input_np, output_np), + callbacks=cbks, + epochs=5, + verbose=2) + self.assertAllClose( + float(backend.get_value(model.optimizer.lr)), 0.01, atol=1e-4) + + +class OptimizersCompatibilityTest(test.TestCase, parameterized.TestCase): + + # TODO(tanzheny): remove test_numeric after algorithm for Momentum, Adam and + # NAdam has been unified: currently these three algorithms behave differently. + @parameterized.named_parameters( + ('adadelta', 'adadelta', True, True), ('adagrad', 'adagrad', True, True), + ('adam', 'adam', True, True), ('adamax', 'adamax', True, True), + ('nadam', 'nadam', True, False), ('momentum', 'momentum', True, True), + ('sgd', 'sgd', False, True)) + def testOptimizersCompatibility(self, opt_str, test_weights, test_numeric): + np.random.seed(1331) + with self.cached_session(): + train_samples = 20 + input_dim = 3 + num_classes = 2 + (x, y), _ = testing_utils.get_test_data( + train_samples=train_samples, + test_samples=10, + input_shape=(input_dim,), + num_classes=num_classes) + y = keras.utils.to_categorical(y) + + num_hidden = 5 + model = testing_utils.get_small_sequential_mlp( + num_hidden=num_hidden, num_classes=num_classes, input_dim=input_dim) + + old_mode = os.environ.get('TF2_BEHAVIOR', None) + # Disable tf2 to create V1 optimizer. + disable_tf2() + if opt_str == 'momentum': + opt_v1 = optimizers.SGD(momentum=0.9) + else: + opt_v1 = optimizers.get(opt_str) + + # Test compile and fit with v1 optimizer. + model.compile(opt_v1, loss='categorical_crossentropy', metrics=[]) + model.fit(x, y, batch_size=5, epochs=1) + model_dir = tempfile.mkdtemp() + gfile.MakeDirs(model_dir) + file_name = os.path.join(model_dir, 'model.h5') + model.save(file_name) + + enable_tf2() + # Test load and fit with v2 optimizer. + model_2 = saving.load_model(file_name) + opt_v2 = model_2.optimizer + self.assertIsInstance(opt_v2, optimizer_v2.OptimizerV2) + # set_weights is called inside load_model but exception is swallowed, + # this call checks the weights can be set correctly. + if test_weights: + opt_v2.set_weights(opt_v1.get_weights()) + if test_numeric: + hist_1 = model.fit(x, y, batch_size=5, epochs=1, shuffle=False) + hist_2 = model_2.fit(x, y, batch_size=5, epochs=1, shuffle=False) + self.assertAllClose(model.get_weights(), model_2.get_weights()) + self.assertAllClose(model.get_weights(), model_2.get_weights()) + self.assertAllClose(hist_1.history['loss'], hist_2.history['loss']) + + if old_mode is not None: + os.environ['TF2_BEHAVIOR'] = old_mode + + def testNumericEquivalenceForNesterovMomentum(self): + np.random.seed(1331) + with self.cached_session(): + train_samples = 20 + input_dim = 3 + num_classes = 2 + (x, y), _ = testing_utils.get_test_data( + train_samples=train_samples, + test_samples=10, + input_shape=(input_dim,), + num_classes=num_classes) + y = keras.utils.to_categorical(y) + + num_hidden = 5 + model_k_v1 = testing_utils.get_small_sequential_mlp( + num_hidden=num_hidden, num_classes=num_classes, input_dim=input_dim) + model_k_v2 = testing_utils.get_small_sequential_mlp( + num_hidden=num_hidden, num_classes=num_classes, input_dim=input_dim) + model_k_v2.set_weights(model_k_v1.get_weights()) + model_tf = testing_utils.get_small_sequential_mlp( + num_hidden=num_hidden, num_classes=num_classes, input_dim=input_dim) + model_tf.set_weights(model_k_v2.get_weights()) + + opt_k_v1 = optimizers.SGD(lr=0.001, momentum=0.9, nesterov=True) + opt_k_v2 = gradient_descent.SGD(momentum=0.9, nesterov=True) + opt_tf = momentum.MomentumOptimizer( + learning_rate=0.001, momentum=0.9, use_nesterov=True) + + model_k_v1.compile(opt_k_v1, loss='categorical_crossentropy', metrics=[]) + model_k_v2.compile(opt_k_v2, loss='categorical_crossentropy', metrics=[]) + model_tf.compile(opt_tf, loss='categorical_crossentropy', metrics=[]) + + hist_k_v1 = model_k_v1.fit(x, y, batch_size=5, epochs=10, shuffle=False) + hist_k_v2 = model_k_v2.fit(x, y, batch_size=5, epochs=10, shuffle=False) + hist_tf = model_tf.fit(x, y, batch_size=5, epochs=10, shuffle=False) + + self.assertAllClose(model_k_v1.get_weights(), model_tf.get_weights()) + self.assertAllClose(model_k_v1.get_weights(), model_k_v2.get_weights()) + self.assertAllClose(opt_k_v1.get_weights(), opt_k_v2.get_weights()) + self.assertAllClose(hist_k_v1.history['loss'], hist_tf.history['loss']) + self.assertAllClose(hist_k_v1.history['loss'], hist_k_v2.history['loss']) + + def testNumericEquivalenceForAmsgrad(self): + np.random.seed(1331) + with self.cached_session(): + train_samples = 20 + input_dim = 3 + num_classes = 2 + (x, y), _ = testing_utils.get_test_data( + train_samples=train_samples, + test_samples=10, + input_shape=(input_dim,), + num_classes=num_classes) + y = keras.utils.to_categorical(y) + + num_hidden = 5 + model_k_v1 = testing_utils.get_small_sequential_mlp( + num_hidden=num_hidden, num_classes=num_classes, input_dim=input_dim) + model_k_v2 = testing_utils.get_small_sequential_mlp( + num_hidden=num_hidden, num_classes=num_classes, input_dim=input_dim) + model_k_v2.set_weights(model_k_v1.get_weights()) + + opt_k_v1 = optimizers.Adam(amsgrad=True) + opt_k_v2 = adam.Adam(amsgrad=True) + + model_k_v1.compile(opt_k_v1, loss='categorical_crossentropy', metrics=[]) + model_k_v2.compile(opt_k_v2, loss='categorical_crossentropy', metrics=[]) + + hist_k_v1 = model_k_v1.fit(x, y, batch_size=5, epochs=10, shuffle=False) + hist_k_v2 = model_k_v2.fit(x, y, batch_size=5, epochs=10, shuffle=False) + + self.assertAllClose(model_k_v1.get_weights(), model_k_v2.get_weights()) + self.assertAllClose(opt_k_v1.get_weights(), opt_k_v2.get_weights()) + self.assertAllClose(hist_k_v1.history['loss'], hist_k_v2.history['loss']) + + +def disable_tf2(): + if 'TF2_BEHAVIOR' in os.environ: + del os.environ['TF2_BEHAVIOR'] + + +def enable_tf2(): + os.environ['TF2_BEHAVIOR'] = 'enabled' + + +# Note: These tests are kept in a separate class to avoid bugs in some +# distributions of Python that break AutoGraph which is used by tf.function. +class OptimizerWithFunctionTest(test.TestCase): + + def testBasic(self): with context.eager_mode(): var = resource_variable_ops.ResourceVariable([1.0, 2.0], dtype=dtypes.float32) @@ -406,10 +649,8 @@ class OptimizerTest(test.TestCase): opt.minimize(loss, [var]) return var - self.assertAllClose([0., 1.], fn()) - # This is just to test tf.function. The values needs to be updated - # when adam updates beta_1_power. - self.assertAllClose([-1.343838, -0.343838], fn()) + self.assertAllClose([0., 1.], fn(), atol=1e-4) + self.assertAllClose([-1, 0.], fn(), atol=1e-4) if __name__ == '__main__': diff --git a/tensorflow/python/keras/optimizer_v2/rmsprop.py b/tensorflow/python/keras/optimizer_v2/rmsprop.py new file mode 100644 index 0000000000..6a5b334fc4 --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/rmsprop.py @@ -0,0 +1,196 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""RMSprop for TensorFlow.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import ops +from tensorflow.python.keras.optimizer_v2 import optimizer_v2 +from tensorflow.python.training import training_ops + + +class RMSprop(optimizer_v2.OptimizerV2): + r"""Optimizer that implements the RMSprop algorithm. + + A detailed description of rmsprop. + + - maintain a moving (discounted) average of the square of gradients + - divide gradient by the root of this average + + $$mean_square_t = rho * mean_square{t-1} + (1-rho) * gradient ** 2$$ + $$mom_t = momentum * mom_{t-1} + learning_rate * gradient / \sqrt{ / + mean_square_t + \epsilon}$$ + $$variable_t := variable_{t-1} - mom_t + + This implementation of RMSprop uses plain momentum, not Nesterov momentum. + + The centered version additionally maintains a moving average of the + gradients, and uses that average to estimate the variance: + + $$mean_grad_t = rho * mean_grad_{t-1} + (1-rho) * gradient$$ + $$mean_square_t = rho * mean_square_{t-1} + (1-rho) * gradient ** 2$$ + $$mom_t = momentum * mom_{t-1} + learning_rate * gradient / + sqrt(mean_square_t - mean_grad_t**2 + epsilon)$$ + $$variable_t := variable_{t-1} - mom_t + + References + See ([pdf] + http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf). + """ + + def __init__(self, + learning_rate=0.001, + rho=0.9, + momentum=0.0, + epsilon=1e-7, + centered=False, + name="RMSprop", + **kwargs): + """Construct a new RMSprop optimizer. + + Note that in the dense implementation of this algorithm, variables and their + corresponding accumulators (momentum, gradient moving average, square + gradient moving average) will be updated even if the gradient is zero + (i.e. accumulators will decay, momentum will be applied). The sparse + implementation (used when the gradient is an `IndexedSlices` object, + typically because of `tf.gather` or an embedding lookup in the forward pass) + will not update variable slices or their accumulators unless those slices + were used in the forward pass (nor is there an "eventual" correction to + account for these omitted updates). This leads to more efficient updates for + large embedding lookup tables (where most of the slices are not accessed in + a particular graph execution), but differs from the published algorithm. + + Args: + learning_rate: A Tensor or a floating point value. The learning rate. + rho: Discounting factor for the history/coming gradient + momentum: A scalar tensor. + epsilon: Small value to avoid zero denominator. + centered: If True, gradients are normalized by the estimated variance of + the gradient; if False, by the uncentered second moment. Setting this to + True may help with training, but is slightly more expensive in terms of + computation and memory. Defaults to False. + name: Optional name prefix for the operations created when applying + gradients. Defaults to "RMSprop". @compatibility(eager) When eager + execution is enabled, `learning_rate`, `decay`, `momentum`, and + `epsilon` can each be a callable that takes no arguments and returns the + actual value to use. This can be useful for changing these values across + different invocations of optimizer functions. @end_compatibility + **kwargs: keyword arguments. Allowed to be {`decay`} + """ + super(RMSprop, self).__init__(name, **kwargs) + self._set_hyper("learning_rate", learning_rate) + self._set_hyper("decay", self._initial_decay) + self._set_hyper("rho", rho) + + self._momentum = False + if isinstance(momentum, ops.Tensor) or callable(momentum) or momentum > 0: + self._momentum = True + if isinstance(momentum, (int, float)) and (momentum < 0 or momentum > 1): + raise ValueError("`momentum` must be between [0, 1].") + self._set_hyper("momentum", momentum) + + self._set_hyper("epsilon", epsilon) + self._centered = centered + + def _create_slots(self, var_list): + for var in var_list: + self.add_slot(var, "rms") + self.add_slot(var, "momentum") + if self._centered: + self.add_slot(var, "mg") + + def _resource_apply_dense(self, grad, var): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + rms = self.get_slot(var, "rms") + mom = self.get_slot(var, "momentum") + rho = self._get_hyper("rho", var_dtype) + momentum = self._get_hyper("momentum", var_dtype) + epsilon = self._get_hyper("epsilon", var_dtype) + if self._centered: + mg = self.get_slot(var, "mg") + return training_ops.resource_apply_centered_rms_prop( + var.handle, + mg.handle, + rms.handle, + mom.handle, + lr_t, + rho, + momentum, + epsilon, + grad, + use_locking=self._use_locking) + else: + return training_ops.resource_apply_rms_prop( + var.handle, + rms.handle, + mom.handle, + lr_t, + rho, + momentum, + epsilon, + grad, + use_locking=self._use_locking) + + def _resource_apply_sparse(self, grad, var, indices): + var_dtype = var.dtype.base_dtype + lr_t = self._decayed_lr(var_dtype) + rms = self.get_slot(var, "rms") + mom = self.get_slot(var, "momentum") + rho = self._get_hyper("rho", var_dtype) + momentum = self._get_hyper("momentum", var_dtype) + epsilon = self._get_hyper("epsilon", var_dtype) + if self._centered: + mg = self.get_slot(var, "mg") + return training_ops.resource_sparse_apply_centered_rms_prop( + var.handle, + mg.handle, + rms.handle, + mom.handle, + lr_t, + rho, + momentum, + epsilon, + grad, + indices, + use_locking=self._use_locking) + else: + return training_ops.resource_sparse_apply_rms_prop( + var.handle, + rms.handle, + mom.handle, + lr_t, + rho, + momentum, + epsilon, + grad, + indices, + use_locking=self._use_locking) + + def get_config(self): + config = super(RMSprop, self).get_config() + config.update({ + "learning_rate": self._serialize_hyperparameter("learning_rate"), + "decay": self._serialize_hyperparameter("decay"), + "rho": self._serialize_hyperparameter("rho"), + "momentum": self._serialize_hyperparameter("momentum"), + "epsilon": self._serialize_hyperparameter("epsilon"), + "centered": self._centered, + }) + return config + + +RMSProp = RMSprop diff --git a/tensorflow/python/keras/optimizer_v2/rmsprop_test.py b/tensorflow/python/keras/optimizer_v2/rmsprop_test.py new file mode 100644 index 0000000000..a8658a8550 --- /dev/null +++ b/tensorflow/python/keras/optimizer_v2/rmsprop_test.py @@ -0,0 +1,410 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for rmsprop.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import copy +import itertools +import math + +import numpy as np + +from tensorflow.python.eager import context +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util +from tensorflow.python.keras.optimizer_v2 import rmsprop +from tensorflow.python.ops import embedding_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.ops import variables +from tensorflow.python.platform import test + +_DATA_TYPES = [dtypes.half, dtypes.float32] + +_TEST_PARAM_VALUES = [ + # learning_rate, rho, momentum, epsilon, centered + [0.05, 0.9, 0.0, 1e-3, True], + [0.05, 0.9, 0.0, 1e-3, False], + [0.1, 0.9, 0.0, 1e-3, True], + [0.01, 0.9, 0.0, 1e-5, True], + [0.01, 0.9, 0.9, 1e-5, True], +] + +_TESTPARAMS = [ + [data_type] + values + for data_type, values in itertools.product(_DATA_TYPES, _TEST_PARAM_VALUES) +] + + +class RMSpropOptimizerTest(test.TestCase): + + def _rmsprop_update_numpy(self, var, g, mg, rms, mom, lr, rho, momentum, + epsilon, centered): + rms_t = rms * rho + (1 - rho) * g * g + denom_t = rms_t + epsilon + if centered: + mg_t = mg * rho + (1 - rho) * g + denom_t -= mg_t * mg_t + else: + mg_t = mg + mom_t = momentum * mom + lr * g / np.sqrt(denom_t, dtype=denom_t.dtype) + var_t = var - mom_t + return var_t, mg_t, rms_t, mom_t + + def _sparse_rmsprop_update_numpy(self, var, gindexs, gvalues, mg, rms, mom, + lr, rho, momentum, epsilon, centered): + mg_t = copy.deepcopy(mg) + rms_t = copy.deepcopy(rms) + mom_t = copy.deepcopy(mom) + var_t = copy.deepcopy(var) + for i in range(len(gindexs)): + gindex = gindexs[i] + gvalue = gvalues[i] + rms_t[gindex] = rms[gindex] * rho + (1 - rho) * gvalue * gvalue + denom_t = rms_t[gindex] + epsilon + if centered: + mg_t[gindex] = mg_t[gindex] * rho + (1 - rho) * gvalue + denom_t -= mg_t[gindex] * mg_t[gindex] + mom_t[gindex] = momentum * mom[gindex] + lr * gvalue / np.sqrt(denom_t) + var_t[gindex] = var[gindex] - mom_t[gindex] + return var_t, mg_t, rms_t, mom_t + + @test_util.run_deprecated_v1 + def testDense(self): + for (dtype, learning_rate, rho, momentum, epsilon, centered) in _TESTPARAMS: + with test_util.use_gpu(): + # Initialize variables for numpy implementation. + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1, 0.2], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01, 0.2], dtype=dtype.as_numpy_dtype) + + var0 = resource_variable_ops.ResourceVariable(var0_np, dtype=dtype) + var1 = resource_variable_ops.ResourceVariable(var1_np, dtype=dtype) + grads0 = constant_op.constant(grads0_np, dtype=dtype) + grads1 = constant_op.constant(grads1_np, dtype=dtype) + opt = rmsprop.RMSprop( + learning_rate=learning_rate, + rho=rho, + momentum=momentum, + epsilon=epsilon, + centered=centered) + + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + self.evaluate(variables.global_variables_initializer()) + + if centered: + mg0 = opt.get_slot(var0, "mg") + mg1 = opt.get_slot(var1, "mg") + else: + mg0 = None + mg1 = None + + rms0 = opt.get_slot(var0, "rms") + self.assertTrue(rms0 is not None) + rms1 = opt.get_slot(var1, "rms") + self.assertTrue(rms1 is not None) + mom0 = opt.get_slot(var0, "momentum") + self.assertTrue(mom0 is not None) + mom1 = opt.get_slot(var1, "momentum") + self.assertTrue(mom1 is not None) + + mg0_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + mg1_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + rms0_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + rms1_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + mom0_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + mom1_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) + + # Run 4 steps of RMSprop + for _ in range(1, 5): + self.evaluate(update) + + var0_np, mg0_np, rms0_np, mom0_np = self._rmsprop_update_numpy( + var0_np, grads0_np, mg0_np, rms0_np, mom0_np, learning_rate, rho, + momentum, epsilon, centered) + var1_np, mg1_np, rms1_np, mom1_np = self._rmsprop_update_numpy( + var1_np, grads1_np, mg1_np, rms1_np, mom1_np, learning_rate, rho, + momentum, epsilon, centered) + + # Validate updated params + if centered: + self.assertAllCloseAccordingToType(mg0_np, self.evaluate(mg0)) + self.assertAllCloseAccordingToType(mg1_np, self.evaluate(mg1)) + self.assertAllCloseAccordingToType(rms0_np, self.evaluate(rms0)) + self.assertAllCloseAccordingToType(rms1_np, self.evaluate(rms1)) + self.assertAllCloseAccordingToType(mom0_np, self.evaluate(mom0)) + self.assertAllCloseAccordingToType(mom1_np, self.evaluate(mom1)) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 + def testDenseWithLearningRateDecay(self): + var0_np = np.array([1.0, 2.0]) + grads0_np = np.array([0.1, 0.2]) + var1_np = np.array([3.0, 4.0]) + grads1_np = np.array([0.01, 0.2]) + + var0 = resource_variable_ops.ResourceVariable(var0_np) + var1 = resource_variable_ops.ResourceVariable(var1_np) + grads0 = constant_op.constant(grads0_np) + grads1 = constant_op.constant(grads1_np) + learning_rate = 0.01 + rho = 0.9 + momentum = 0.0 + epsilon = 1e-7 + centered = False + decay = 0.5 + opt = rmsprop.RMSprop( + learning_rate=learning_rate, + rho=rho, + momentum=momentum, + epsilon=epsilon, + centered=centered, + decay=decay) + + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + self.evaluate(variables.global_variables_initializer()) + + rms0 = opt.get_slot(var0, "rms") + self.assertTrue(rms0 is not None) + rms1 = opt.get_slot(var1, "rms") + self.assertTrue(rms1 is not None) + mom0 = opt.get_slot(var0, "momentum") + self.assertTrue(mom0 is not None) + mom1 = opt.get_slot(var1, "momentum") + self.assertTrue(mom1 is not None) + + mg0_np = np.array([0.0, 0.0]) + mg1_np = np.array([0.0, 0.0]) + rms0_np = np.array([0.0, 0.0]) + rms1_np = np.array([0.0, 0.0]) + mom0_np = np.array([0.0, 0.0]) + mom1_np = np.array([0.0, 0.0]) + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) + + # Run 4 steps of RMSprop + for t in range(2): + self.evaluate(update) + + lr = learning_rate / (1 + decay * t) + var0_np, mg0_np, rms0_np, mom0_np = self._rmsprop_update_numpy( + var0_np, grads0_np, mg0_np, rms0_np, mom0_np, lr, rho, momentum, + epsilon, centered) + var1_np, mg1_np, rms1_np, mom1_np = self._rmsprop_update_numpy( + var1_np, grads1_np, mg1_np, rms1_np, mom1_np, lr, rho, momentum, + epsilon, centered) + + # Validate updated params + self.assertAllCloseAccordingToType(rms0_np, self.evaluate(rms0)) + self.assertAllCloseAccordingToType(rms1_np, self.evaluate(rms1)) + self.assertAllCloseAccordingToType(mom0_np, self.evaluate(mom0)) + self.assertAllCloseAccordingToType(mom1_np, self.evaluate(mom1)) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 + def testMinimizeSparseResourceVariable(self): + for dtype in [dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0 = resource_variable_ops.ResourceVariable([[1.0, 2.0]], dtype=dtype) + x = constant_op.constant([[4.0], [5.0]], dtype=dtype) + pred = math_ops.matmul(embedding_ops.embedding_lookup([var0], [0]), x) + loss = pred * pred + sgd_op = rmsprop.RMSprop( + learning_rate=1.0, + rho=0.0, + momentum=0.0, + epsilon=0.0, + centered=False).minimize( + loss, var_list=[var0]) + self.evaluate(variables.global_variables_initializer()) + # Fetch params to validate initial values + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) + # Run 1 step of sgd + self.evaluate(sgd_op) + # Validate updated params + self.assertAllCloseAccordingToType([[0., 1.]], + self.evaluate(var0), + atol=0.01) + + @test_util.run_deprecated_v1 + def testMinimizeSparseResourceVariableCentered(self): + for dtype in [dtypes.float32, dtypes.float64]: + with self.cached_session(): + var0 = resource_variable_ops.ResourceVariable([[1.0, 2.0]], dtype=dtype) + x = constant_op.constant([[4.0], [5.0]], dtype=dtype) + pred = math_ops.matmul(embedding_ops.embedding_lookup([var0], [0]), x) + loss = pred * pred + sgd_op = rmsprop.RMSprop( + learning_rate=1.0, + rho=0.0, + momentum=0.0, + epsilon=1.0, + centered=True).minimize( + loss, var_list=[var0]) + self.evaluate(variables.global_variables_initializer()) + # Fetch params to validate initial values + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) + # Run 1 step of sgd + self.evaluate(sgd_op) + # Validate updated params + self.assertAllCloseAccordingToType([[-111, -138]], + self.evaluate(var0), + atol=0.01) + + @test_util.run_deprecated_v1 + def testSparse(self): + for (dtype, learning_rate, rho, momentum, epsilon, centered) in _TESTPARAMS: + with test_util.use_gpu(): + # Initialize variables for numpy implementation. + var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) + grads0_np = np.array([0.1], dtype=dtype.as_numpy_dtype) + var1_np = np.array([3.0, 4.0], dtype=dtype.as_numpy_dtype) + grads1_np = np.array([0.01], dtype=dtype.as_numpy_dtype) + + var0 = variables.Variable(var0_np) + var1 = variables.Variable(var1_np) + grads0_np_indices = np.array([0], dtype=np.int32) + grads0 = ops.IndexedSlices( + constant_op.constant(grads0_np), + constant_op.constant(grads0_np_indices), constant_op.constant([1])) + grads1_np_indices = np.array([1], dtype=np.int32) + grads1 = ops.IndexedSlices( + constant_op.constant(grads1_np), + constant_op.constant(grads1_np_indices), constant_op.constant([1])) + opt = rmsprop.RMSprop( + learning_rate=learning_rate, + rho=rho, + momentum=momentum, + epsilon=epsilon, + centered=centered) + update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + self.evaluate(variables.global_variables_initializer()) + + if centered: + mg0 = opt.get_slot(var0, "mg") + self.assertEqual(mg0 is not None, centered) + mg1 = opt.get_slot(var1, "mg") + self.assertEqual(mg1 is not None, centered) + else: + mg0 = None + mg1 = None + rms0 = opt.get_slot(var0, "rms") + self.assertTrue(rms0 is not None) + rms1 = opt.get_slot(var1, "rms") + self.assertTrue(rms1 is not None) + mom0 = opt.get_slot(var0, "momentum") + self.assertTrue(mom0 is not None) + mom1 = opt.get_slot(var1, "momentum") + self.assertTrue(mom1 is not None) + + mg0_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + mg1_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + rms0_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + rms1_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + mom0_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + mom1_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) + + # Run 4 steps of RMSprop + for _ in range(1, 5): + self.evaluate(update) + + var0_np, mg0_np, rms0_np, mom0_np = self._sparse_rmsprop_update_numpy( + var0_np, grads0_np_indices, grads0_np, mg0_np, rms0_np, mom0_np, + learning_rate, rho, momentum, epsilon, centered) + var1_np, mg1_np, rms1_np, mom1_np = self._sparse_rmsprop_update_numpy( + var1_np, grads1_np_indices, grads1_np, mg1_np, rms1_np, mom1_np, + learning_rate, rho, momentum, epsilon, centered) + + # Validate updated params + if centered: + self.assertAllCloseAccordingToType(mg0_np, self.evaluate(mg0)) + self.assertAllCloseAccordingToType(mg1_np, self.evaluate(mg1)) + self.assertAllCloseAccordingToType(rms0_np, self.evaluate(rms0)) + self.assertAllCloseAccordingToType(rms1_np, self.evaluate(rms1)) + self.assertAllCloseAccordingToType(mom0_np, self.evaluate(mom0)) + self.assertAllCloseAccordingToType(mom1_np, self.evaluate(mom1)) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + def testCallableParams(self): + with context.eager_mode(): + for dtype in [dtypes.half, dtypes.float32]: + var0 = resource_variable_ops.ResourceVariable([1.0, 2.0], dtype=dtype) + var1 = resource_variable_ops.ResourceVariable([3.0, 4.0], dtype=dtype) + grads0 = constant_op.constant([0.1, 0.1], dtype=dtype) + grads1 = constant_op.constant([0.01, 0.01], dtype=dtype) + + learning_rate = lambda: 2.0 + rho = lambda: 0.9 + momentum = lambda: 0.0 + epsilon = lambda: 1.0 + opt = rmsprop.RMSprop(learning_rate, rho, momentum, epsilon) + + # Fetch params to validate initial values + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) + # Step 1: the rms accumulators where 1. So we should see a normal + # update: v -= grad * learning_rate + opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + # Check the parameters. + self.assertAllCloseAccordingToType( + np.array([ + 1.0 - (0.1 * 2.0 / math.sqrt(0.001 + 1.0)), + 2.0 - (0.1 * 2.0 / math.sqrt(0.001 + 1.0)) + ]), self.evaluate(var0)) + self.assertAllCloseAccordingToType( + np.array([ + 3.0 - (0.01 * 2.0 / math.sqrt(0.00001 + 1.0)), + 4.0 - (0.01 * 2.0 / math.sqrt(0.00001 + 1.0)) + ]), self.evaluate(var1)) + # Step 2: the root mean square accumulators contain the previous update. + opt.apply_gradients(zip([grads0, grads1], [var0, var1])) + # Check the parameters. + self.assertAllCloseAccordingToType( + np.array([ + 1.0 - (0.1 * 2.0 / math.sqrt(0.001 + 1.0)) - + (0.1 * 2.0 / math.sqrt(0.001 * 0.9 + 0.001 + 1.0)), + 2.0 - (0.1 * 2.0 / math.sqrt(0.001 + 1.0)) - + (0.1 * 2.0 / math.sqrt(0.001 * 0.9 + 0.001 + 1.0)) + ]), self.evaluate(var0)) + self.assertAllCloseAccordingToType( + np.array([ + 3.0 - (0.01 * 2.0 / math.sqrt(0.00001 + 1.0)) - + (0.01 * 2.0 / math.sqrt(0.00001 * 0.9 + 1e-5 + 1.0)), + 4.0 - (0.01 * 2.0 / math.sqrt(0.00001 + 1.0)) - + (0.01 * 2.0 / math.sqrt(0.00001 * 0.9 + 1e-5 + 1.0)) + ]), self.evaluate(var1)) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/keras/optimizers.py b/tensorflow/python/keras/optimizers.py index 715d80a116..10466eb573 100644 --- a/tensorflow/python/keras/optimizers.py +++ b/tensorflow/python/keras/optimizers.py @@ -22,7 +22,17 @@ from __future__ import print_function import six from six.moves import zip # pylint: disable=redefined-builtin +from tensorflow.python import tf2 +from tensorflow.python.framework import ops from tensorflow.python.keras import backend as K +from tensorflow.python.keras.optimizer_v2 import adadelta as adadelta_v2 +from tensorflow.python.keras.optimizer_v2 import adagrad as adagrad_v2 +from tensorflow.python.keras.optimizer_v2 import adam as adam_v2 +from tensorflow.python.keras.optimizer_v2 import adamax as adamax_v2 +from tensorflow.python.keras.optimizer_v2 import gradient_descent as gradient_descent_v2 +from tensorflow.python.keras.optimizer_v2 import nadam as nadam_v2 +from tensorflow.python.keras.optimizer_v2 import optimizer_v2 +from tensorflow.python.keras.optimizer_v2 import rmsprop as rmsprop_v2 from tensorflow.python.keras.utils.generic_utils import deserialize_keras_object from tensorflow.python.keras.utils.generic_utils import serialize_keras_object from tensorflow.python.ops import clip_ops @@ -473,7 +483,7 @@ class Adam(Optimizer): def get_updates(self, loss, params): grads = self.get_gradients(loss, params) - self.updates = [state_ops.assign_add(self.iterations, 1)] + self.updates = [] lr = self.lr if self.initial_decay > 0: @@ -481,7 +491,8 @@ class Adam(Optimizer): 1. / (1. + self.decay * math_ops.cast(self.iterations, K.dtype(self.decay)))) - t = math_ops.cast(self.iterations, K.floatx()) + 1 + with ops.control_dependencies([state_ops.assign_add(self.iterations, 1)]): + t = math_ops.cast(self.iterations, K.floatx()) lr_t = lr * ( K.sqrt(1. - math_ops.pow(self.beta_2, t)) / (1. - math_ops.pow(self.beta_1, t))) @@ -795,16 +806,27 @@ def deserialize(config, custom_objects=None): Returns: A Keras Optimizer instance. """ - all_classes = { - 'sgd': SGD, - 'rmsprop': RMSprop, - 'adagrad': Adagrad, - 'adadelta': Adadelta, - 'adam': Adam, - 'adamax': Adamax, - 'nadam': Nadam, - 'tfoptimizer': TFOptimizer, - } + if tf2.enabled(): + all_classes = { + 'adadelta': adadelta_v2.Adadelta, + 'adagrad': adagrad_v2.Adagrad, + 'adam': adam_v2.Adam, + 'adamax': adamax_v2.Adamax, + 'nadam': nadam_v2.Nadam, + 'rmsprop': rmsprop_v2.RMSprop, + 'sgd': gradient_descent_v2.SGD + } + else: + all_classes = { + 'adadelta': Adadelta, + 'adagrad': Adagrad, + 'adam': Adam, + 'adamax': Adamax, + 'nadam': Nadam, + 'rmsprop': RMSprop, + 'sgd': SGD, + 'tfoptimizer': TFOptimizer + } # Make deserialization case-insensitive for built-in optimizers. if config['class_name'].lower() in all_classes: config['class_name'] = config['class_name'].lower() @@ -833,17 +855,17 @@ def get(identifier): Raises: ValueError: If `identifier` cannot be interpreted. """ + if isinstance(identifier, (Optimizer, optimizer_v2.OptimizerV2)): + return identifier # Wrap TF optimizer instances - if isinstance(identifier, tf_optimizer_module.Optimizer): + elif isinstance(identifier, tf_optimizer_module.Optimizer): opt = TFOptimizer(identifier) K.track_tf_optimizer(opt) return opt - if isinstance(identifier, dict): + elif isinstance(identifier, dict): return deserialize(identifier) elif isinstance(identifier, six.string_types): config = {'class_name': str(identifier), 'config': {}} return deserialize(config) - if isinstance(identifier, Optimizer): - return identifier else: raise ValueError('Could not interpret optimizer identifier:', identifier) diff --git a/tensorflow/python/keras/optimizers_test.py b/tensorflow/python/keras/optimizers_test.py index 9664f09fff..d3cacb702c 100644 --- a/tensorflow/python/keras/optimizers_test.py +++ b/tensorflow/python/keras/optimizers_test.py @@ -19,11 +19,14 @@ from __future__ import division from __future__ import print_function import gc +import os import weakref +from absl.testing import parameterized import numpy as np from tensorflow.python import keras +from tensorflow.python import tf2 from tensorflow.python.eager import context from tensorflow.python.framework import ops from tensorflow.python.framework import test_util @@ -88,22 +91,26 @@ def _test_optimizer(optimizer, target=0.75): class KerasOptimizersTest(test.TestCase): + @test_util.run_deprecated_v1 def test_sgd(self): with self.cached_session(): _test_optimizer(keras.optimizers.SGD(lr=0.01, momentum=0.9, nesterov=True)) + @test_util.run_deprecated_v1 def test_rmsprop(self): with self.cached_session(): _test_optimizer(keras.optimizers.RMSprop()) _test_optimizer(keras.optimizers.RMSprop(decay=1e-3)) + @test_util.run_deprecated_v1 def test_adagrad(self): with self.cached_session(): _test_optimizer(keras.optimizers.Adagrad()) _test_optimizer(keras.optimizers.Adagrad(decay=1e-3)) + @test_util.run_deprecated_v1 def test_adadelta(self): with self.cached_session(): _test_optimizer(keras.optimizers.Adadelta(), target=0.6) @@ -112,27 +119,32 @@ class KerasOptimizersTest(test.TestCase): # the accuracy. _test_optimizer(keras.optimizers.Adadelta(decay=1e-3), target=0.4) + @test_util.run_deprecated_v1 def test_adam(self): with self.cached_session(): _test_optimizer(keras.optimizers.Adam()) _test_optimizer(keras.optimizers.Adam(decay=1e-3)) _test_optimizer(keras.optimizers.Adam(amsgrad=True)) + @test_util.run_deprecated_v1 def test_adamax(self): with self.cached_session(): _test_optimizer(keras.optimizers.Adamax()) _test_optimizer(keras.optimizers.Adamax(decay=1e-3)) + @test_util.run_deprecated_v1 def test_nadam(self): with self.cached_session(): _test_optimizer(keras.optimizers.Nadam()) + @test_util.run_deprecated_v1 def test_clipnorm(self): with self.cached_session(): _test_optimizer(keras.optimizers.SGD(lr=0.01, momentum=0.9, clipnorm=0.5)) + @test_util.run_deprecated_v1 def test_clipvalue(self): with self.cached_session(): _test_optimizer(keras.optimizers.SGD(lr=0.01, @@ -208,5 +220,40 @@ class KerasOptimizersTest(test.TestCase): _ = keras.optimizers.Adam(clipnorm=-2.0) +@test_util.run_all_in_graph_and_eager_modes +class KerasV2OptimizersTest(test.TestCase, parameterized.TestCase): + + @parameterized.named_parameters( + ('adadelta_tf2', 'adadelta', True), ('adadelta_tf1', 'adadelta', False), + ('adagrad_tf2', 'adagrad', True), ('adagrad_tf1', 'adagrad', False), + ('adam_tf2', 'adam', True), ('adam_tf1', 'adam', False), + ('adamax_tf2', 'adamax', True), ('adamax_tf1', 'adamax', False), + ('sgd_tf2', 'sgd', True), ('sgd_tf1', 'sgd', False), + ('nadam_tf2', 'nadam', True), ('nadam_tf1', 'nadam', False), + ('rmsprop_tf2', 'rmsprop', True), ('rmsprop_tf1', 'rmsprop', False)) + def test_load_from_string(self, optimizer_string, tf2mode): + old_mode = os.environ.get('TF2_BEHAVIOR', None) + if tf2mode: + os.environ['TF2_BEHAVIOR'] = 'enabled' + else: + if 'TF2_BEHAVIOR' in os.environ: + del os.environ['TF2_BEHAVIOR'] + + # Sanity check. + self.assertEqual(tf2.enabled(), tf2mode) + + model = keras.models.Sequential() + model.add(keras.layers.Dense(1, input_shape=(10,))) + model.compile(optimizer_string, 'binary_crossentropy') + + self.assertEqual(optimizer_string, + model.optimizer.__class__.__name__.lower()) + + model.fit(np.ones((10, 10), 'float32'), np.ones((10, 1), 'float32')) + + if old_mode is not None: + os.environ['TF2_BEHAVIOR'] = old_mode + + if __name__ == '__main__': test.main() diff --git a/tensorflow/python/keras/regularizers_test.py b/tensorflow/python/keras/regularizers_test.py index bba4ebb287..3d6b259d87 100644 --- a/tensorflow/python/keras/regularizers_test.py +++ b/tensorflow/python/keras/regularizers_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python import keras from tensorflow.python.keras import testing_utils +from tensorflow.python.framework import test_util from tensorflow.python.platform import test @@ -61,6 +62,7 @@ class KerasRegularizersTest(test.TestCase): model.fit(x_train, y_train, batch_size=10, epochs=1, verbose=0) + @test_util.run_deprecated_v1 def test_activity_regularization(self): with self.cached_session(): (x_train, y_train), _ = get_data() diff --git a/tensorflow/python/keras/testing_utils.py b/tensorflow/python/keras/testing_utils.py index d342131a52..7827e16627 100644 --- a/tensorflow/python/keras/testing_utils.py +++ b/tensorflow/python/keras/testing_utils.py @@ -149,6 +149,10 @@ def layer_test(layer_cls, kwargs=None, input_shape=None, input_dtype=None, np.testing.assert_allclose(output, actual_output, rtol=1e-3) # test training mode (e.g. useful for dropout tests) + # Rebuild the model to avoid the graph being reused between predict() and + # train(). This was causing some error for layer with Defun as it body. + # See b/120160788 for more details. This should be mitigated after 2.0. + model = keras.models.Model(x, layer(x)) model.compile(RMSPropOptimizer(0.01), 'mse', weighted_metrics=['acc']) model.train_on_batch(input_data, actual_output) diff --git a/tensorflow/python/keras/utils/__init__.py b/tensorflow/python/keras/utils/__init__.py index 8939044f71..61940ad789 100644 --- a/tensorflow/python/keras/utils/__init__.py +++ b/tensorflow/python/keras/utils/__init__.py @@ -34,6 +34,7 @@ from tensorflow.python.keras.utils.generic_utils import serialize_keras_object from tensorflow.python.keras.utils.io_utils import HDF5Matrix from tensorflow.python.keras.utils.layer_utils import convert_all_kernels_in_model from tensorflow.python.keras.utils.layer_utils import get_source_inputs +from tensorflow.python.keras.utils.losses_utils import squeeze_or_expand_dimensions from tensorflow.python.keras.utils.multi_gpu_utils import multi_gpu_model from tensorflow.python.keras.utils.np_utils import normalize from tensorflow.python.keras.utils.np_utils import to_categorical diff --git a/tensorflow/python/keras/utils/generic_utils.py b/tensorflow/python/keras/utils/generic_utils.py index 375bd9d196..c331ce430b 100644 --- a/tensorflow/python/keras/utils/generic_utils.py +++ b/tensorflow/python/keras/utils/generic_utils.py @@ -319,14 +319,16 @@ class Progbar(object): will be displayed as-is. All others will be averaged by the progbar before display. interval: Minimum visual progress update interval (in seconds). + unit_name: Display name for step counts (usually "step" or "sample"). """ def __init__(self, target, width=30, verbose=1, interval=0.05, - stateful_metrics=None): + stateful_metrics=None, unit_name='step'): self.target = target self.width = width self.verbose = verbose self.interval = interval + self.unit_name = unit_name if stateful_metrics: self.stateful_metrics = set(stateful_metrics) else: @@ -425,12 +427,12 @@ class Progbar(object): info = ' - ETA: %s' % eta_format else: - if time_per_unit >= 1: - info += ' %.0fs/step' % time_per_unit + if time_per_unit >= 1 or time_per_unit == 0: + info += ' %.0fs/%s' % (time_per_unit, self.unit_name) elif time_per_unit >= 1e-3: - info += ' %.0fms/step' % (time_per_unit * 1e3) + info += ' %.0fms/%s' % (time_per_unit * 1e3, self.unit_name) else: - info += ' %.0fus/step' % (time_per_unit * 1e6) + info += ' %.0fus/%s' % (time_per_unit * 1e6, self.unit_name) for k in self._values_order: info += ' - %s:' % k diff --git a/tensorflow/python/keras/utils/layer_utils.py b/tensorflow/python/keras/utils/layer_utils.py index 158a9a5e76..60677be735 100644 --- a/tensorflow/python/keras/utils/layer_utils.py +++ b/tensorflow/python/keras/utils/layer_utils.py @@ -77,7 +77,7 @@ def count_params(weights): Returns: The total number of scalars composing the weights """ - return int(np.sum([np.prod(p.get_shape().as_list()) for p in set(weights)])) + return int(sum(np.prod(p.get_shape().as_list()) for p in set(weights))) def print_summary(model, line_length=None, positions=None, print_fn=None): diff --git a/tensorflow/python/keras/utils/losses_utils.py b/tensorflow/python/keras/utils/losses_utils.py new file mode 100644 index 0000000000..fc4b4ac7df --- /dev/null +++ b/tensorflow/python/keras/utils/losses_utils.py @@ -0,0 +1,189 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +# pylint: disable=protected-access +"""Utilities related to loss functions.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import ops +from tensorflow.python.keras import backend as K +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import confusion_matrix +from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import weights_broadcast_ops +from tensorflow.python.ops.losses import losses_impl + + +def squeeze_or_expand_dimensions(y_pred, y_true, sample_weight): + """Squeeze or expand last dimension if needed. + + 1. Squeezes last dim of `y_pred` or `y_true` if their rank differs by 1 + (using `confusion_matrix.remove_squeezable_dimensions`). + 2. Squeezes or expands last dim of `sample_weight` if its rank differs by 1 + from the new rank of `y_pred`. + If `sample_weight` is scalar, it is kept scalar. + + This will use static shape if available. Otherwise, it will add graph + operations, which could result in a performance hit. + + Args: + y_pred: Predicted values, a `Tensor` of arbitrary dimensions. + y_true: Optional label `Tensor` whose dimensions match `y_pred`. + sample_weight: Optional weight scalar or `Tensor` whose dimensions match + `y_pred`. + + Returns: + Tuple of `y_pred`, `y_true` and `sample_weight`. Each of them possibly has + the last dimension squeezed, + `sample_weight` could be extended by one dimension. + """ + if y_true is not None: + # squeeze last dim of `y_pred` or `y_true` if their rank differs by 1 + y_true, y_pred = confusion_matrix.remove_squeezable_dimensions( + y_true, y_pred) + + if sample_weight is None: + return y_pred, y_true, None + + sample_weight = ops.convert_to_tensor(sample_weight) + weights_shape = sample_weight.get_shape() + weights_rank = weights_shape.ndims + if weights_rank == 0: # If weights is scalar, do nothing. + return y_pred, y_true, sample_weight + + y_pred_shape = y_pred.get_shape() + y_pred_rank = y_pred_shape.ndims + if (y_pred_rank is not None) and (weights_rank is not None): + # Use static rank. + if weights_rank - y_pred_rank == 1: + sample_weight = array_ops.squeeze(sample_weight, [-1]) + elif y_pred_rank - weights_rank == 1: + sample_weight = array_ops.expand_dims(sample_weight, [-1]) + return y_pred, y_true, sample_weight + + # Use dynamic rank. + weights_rank_tensor = array_ops.rank(sample_weight) + rank_diff = weights_rank_tensor - array_ops.rank(y_pred) + maybe_squeeze_weights = lambda: array_ops.squeeze(sample_weight, [-1]) + + def _maybe_expand_weights(): + return control_flow_ops.cond( + math_ops.equal(rank_diff, + -1), lambda: array_ops.expand_dims(sample_weight, [-1]), + lambda: sample_weight) + + def _maybe_adjust_weights(): + return control_flow_ops.cond( + math_ops.equal(rank_diff, 1), maybe_squeeze_weights, + _maybe_expand_weights) + + # squeeze or expand last dim of `sample_weight` if its rank differs by 1 + # from the new rank of `y_pred`. + sample_weight = control_flow_ops.cond( + math_ops.equal(weights_rank_tensor, 0), lambda: sample_weight, + _maybe_adjust_weights) + return y_pred, y_true, sample_weight + + +def _safe_mean(losses, num_present): + """Computes a safe mean of the losses. + + Args: + losses: `Tensor` whose elements contain individual loss measurements. + num_present: The number of measurable elements in `losses`. + + Returns: + A scalar representing the mean of `losses`. If `num_present` is zero, + then zero is returned. + """ + total_loss = math_ops.reduce_sum(losses) + return math_ops.div_no_nan(total_loss, num_present, name='value') + + +def _num_elements(losses): + """Computes the number of elements in `losses` tensor.""" + with ops.name_scope(None, 'num_elements', values=[losses]) as scope: + return math_ops.cast(array_ops.size(losses, name=scope), dtype=losses.dtype) + + +def _reduce_weighted_loss( + weighted_losses, reduction=losses_impl.ReductionV2.SUM_OVER_BATCH_SIZE): + """Reduces the individual weighted loss measurements.""" + if reduction == losses_impl.ReductionV2.NONE: + loss = weighted_losses + else: + loss = math_ops.reduce_sum(weighted_losses) + if reduction == losses_impl.ReductionV2.SUM_OVER_BATCH_SIZE: + loss = _safe_mean(loss, _num_elements(weighted_losses)) + return loss + + +def compute_weighted_loss(losses, + sample_weight=None, + reduction=losses_impl.ReductionV2.SUM_OVER_BATCH_SIZE, + name=None): + """Computes the weighted loss. + + Args: + losses: `Tensor` of shape `[batch_size, d1, ... dN]`. + sample_weight: Optional `Tensor` whose rank is either 0, or the same rank as + `losses`, or be broadcastable to `losses`. + reduction: Type of `tf.losses.Reduction` to apply to loss. Default value is + `SUM_OVER_BATCH_SIZE`. + name: Optional name for the op. + + Raises: + ValueError: If the shape of `sample_weight` is not compatible with `losses`. + + Returns: + Weighted loss `Tensor` of the same type as `losses`. If `reduction` is + `NONE`, this has the same shape as `losses`; otherwise, it is scalar. + """ + losses_impl.ReductionV2.validate(reduction) + if sample_weight is None: + sample_weight = 1.0 + with ops.name_scope(name, 'weighted_loss', (losses, sample_weight)): + # Save the `reduction` argument for loss normalization when distributing + # to multiple replicas. + # TODO(josh11b): Associate it with the returned op for more precision. + ops.get_default_graph()._last_loss_reduction = reduction # pylint: disable=protected-access + + # Update dimensions of `sample_weight` to match with `losses` if possible. + losses, _, sample_weight = squeeze_or_expand_dimensions( + losses, None, sample_weight) + losses = ops.convert_to_tensor(losses) + input_dtype = losses.dtype + losses = math_ops.to_float(losses) + sample_weight = math_ops.to_float(sample_weight) + + try: + # Broadcast weights if possible. + sample_weight = weights_broadcast_ops.broadcast_weights( + sample_weight, losses) + except ValueError: + # Reduce values to same ndim as weight array. + ndim = K.ndim(losses) + weight_ndim = K.ndim(sample_weight) + losses = K.mean(losses, axis=list(range(weight_ndim, ndim))) + + sample_weight.get_shape().assert_is_compatible_with(losses.get_shape()) + weighted_losses = math_ops.multiply(losses, sample_weight) + # Apply reduction function to the individual weighted losses. + loss = _reduce_weighted_loss(weighted_losses, reduction) + # Convert the result back to the input type. + loss = math_ops.cast(loss, input_dtype) + return loss diff --git a/tensorflow/python/keras/utils/multi_gpu_utils_test.py b/tensorflow/python/keras/utils/multi_gpu_utils_test.py index 1780ab6587..8c1abd6324 100644 --- a/tensorflow/python/keras/utils/multi_gpu_utils_test.py +++ b/tensorflow/python/keras/utils/multi_gpu_utils_test.py @@ -158,7 +158,7 @@ class TestMultiGPUModel(test.TestCase): dataset = data.Dataset.from_tensor_slices((x_train, y_train)) dataset = dataset.repeat() dataset = dataset.batch(4) - iterator = dataset.make_one_shot_iterator() + iterator = data.make_one_shot_iterator(dataset) inputs, targets = iterator.get_next() diff --git a/tensorflow/python/keras/utils/tf_utils.py b/tensorflow/python/keras/utils/tf_utils.py index 6b7c6c34a2..7b4c9e7239 100644 --- a/tensorflow/python/keras/utils/tf_utils.py +++ b/tensorflow/python/keras/utils/tf_utils.py @@ -161,6 +161,9 @@ def are_all_symbolic_tensors(tensors): return all(is_symbolic_tensor(tensor) for tensor in tensors) +_user_convertible_tensor_types = set() + + def is_symbolic_tensor(tensor): """Returns whether a tensor is symbolic (from a TF graph) or an eager tensor. @@ -176,9 +179,40 @@ def is_symbolic_tensor(tensor): if isinstance(tensor, variables.Variable): return not context.executing_eagerly() if isinstance(tensor, (ops.Tensor, sparse_tensor.SparseTensor)): - try: - _ = tensor.graph - return True - except AttributeError: - return False + return hasattr(tensor, 'graph') + if isinstance(tensor, tuple(_user_convertible_tensor_types)): + return hasattr(ops.convert_to_tensor(tensor), 'graph') return False + + +def register_symbolic_tensor_type(cls): + """Allows users to specify types regarded as symbolic `Tensor`s. + + Used in conjunction with `tf.register_tensor_conversion_function`, calling + `tf.keras.utils.register_symbolic_tensor_type(cls)` allows non-`Tensor` + objects to be plumbed through Keras layers. + + Example: + + ```python + # One-time setup. + class Foo(object): + def __init__(self, input_): + self._input = input_ + def value(self): + return tf.constant(42.) + + tf.register_tensor_conversion_function( + Foo, lambda x, *args, **kwargs: x.value()) + + tf.keras.utils.register_symbolic_tensor_type(Foo) + + # User-land. + layer = tf.keras.layers.Lambda(lambda input_: Foo(input_)) + ``` + + Arguments: + cls: A `class` type which shall be regarded as a symbolic `Tensor`. + """ + global _user_convertible_tensor_types + _user_convertible_tensor_types.add(cls) diff --git a/tensorflow/python/keras/utils/tf_utils_test.py b/tensorflow/python/keras/utils/tf_utils_test.py new file mode 100644 index 0000000000..9833a49299 --- /dev/null +++ b/tensorflow/python/keras/utils/tf_utils_test.py @@ -0,0 +1,134 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for Keras TF utils.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python import keras +from tensorflow.python.eager import context +from tensorflow.python.framework import ops +from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util +from tensorflow.python.keras.utils import tf_utils +from tensorflow.python.ops import variables +from tensorflow.python.platform import test + + +@test_util.run_all_in_graph_and_eager_modes +class TestIsSymbolicTensor(test.TestCase): + + def test_default_behavior(self): + if context.executing_eagerly(): + self.assertFalse(tf_utils.is_symbolic_tensor( + variables.Variable(name='blah', initial_value=0.))) + self.assertFalse(tf_utils.is_symbolic_tensor( + ops.convert_to_tensor(0.))) + self.assertFalse(tf_utils.is_symbolic_tensor( + sparse_tensor.SparseTensor( + indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4]))) + else: + self.assertTrue(tf_utils.is_symbolic_tensor( + variables.Variable(name='blah', initial_value=0.))) + self.assertTrue(tf_utils.is_symbolic_tensor( + ops.convert_to_tensor(0.))) + self.assertTrue(tf_utils.is_symbolic_tensor( + sparse_tensor.SparseTensor( + indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4]))) + + def test_works_with_registered(self): + + class CustomClass(object): + + def value(self): + return ops.convert_to_tensor(42.) + + ops.register_tensor_conversion_function( + CustomClass, lambda value, **_: value.value()) + + tf_utils.register_symbolic_tensor_type(CustomClass) + + if context.executing_eagerly(): + self.assertFalse(tf_utils.is_symbolic_tensor( + variables.Variable(name='blah', initial_value=0.))) + self.assertFalse(tf_utils.is_symbolic_tensor( + ops.convert_to_tensor(0.))) + self.assertFalse(tf_utils.is_symbolic_tensor( + sparse_tensor.SparseTensor( + indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4]))) + self.assertFalse(tf_utils.is_symbolic_tensor(CustomClass())) + else: + self.assertTrue(tf_utils.is_symbolic_tensor( + variables.Variable(name='blah', initial_value=0.))) + self.assertTrue(tf_utils.is_symbolic_tensor( + ops.convert_to_tensor(0.))) + self.assertTrue(tf_utils.is_symbolic_tensor( + sparse_tensor.SparseTensor( + indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4]))) + self.assertTrue(tf_utils.is_symbolic_tensor(CustomClass())) + + def test_enables_nontensor_plumbing(self): + # Setup. + + class Foo(object): + + def __init__(self, input_): + self._input = input_ + self.value = ops.convert_to_tensor(42.) + + ops.register_tensor_conversion_function( + Foo, lambda x, *args, **kwargs: x.value) + tf_utils.register_symbolic_tensor_type(Foo) + + class PlumbingLayer(keras.layers.Lambda): + + def __init__(self, fn, **kwargs): + def _fn(*fargs, **fkwargs): + d = fn(*fargs, **fkwargs) + x = ops.convert_to_tensor(d) + d.shape = x.shape + d.get_shape = x.get_shape + return d, x + super(PlumbingLayer, self).__init__(_fn, **kwargs) + self._enter_dunder_call = False + + def __call__(self, inputs, *args, **kwargs): + self._enter_dunder_call = True + d, _ = super(PlumbingLayer, self).__call__(inputs, *args, **kwargs) + self._enter_dunder_call = False + return d + + def call(self, inputs, *args, **kwargs): + d, v = super(PlumbingLayer, self).call(inputs, *args, **kwargs) + if self._enter_dunder_call: + return d, v + return d + + # User-land. + model = keras.Sequential([ + keras.layers.InputLayer([]), + PlumbingLayer(Foo), # Makes a `Foo` object. + ]) + # Let's ensure Keras graph history is preserved by composing the models. + model = keras.Model(model.inputs, model(model.outputs)) + # Now we instantiate the model and verify we have a `Foo` object, not a + # `Tensor`. + y = model(ops.convert_to_tensor(7.)) + self.assertIsInstance(y, Foo) + + +if __name__ == '__main__': + test.main() diff --git a/tensorflow/python/kernel_tests/BUILD b/tensorflow/python/kernel_tests/BUILD index 6b990d3a92..97ac21b8ad 100644 --- a/tensorflow/python/kernel_tests/BUILD +++ b/tensorflow/python/kernel_tests/BUILD @@ -121,8 +121,10 @@ cuda_py_test( "@absl_py//absl/testing:parameterized", "//third_party/py/numpy", "//tensorflow/python:array_ops", - "//tensorflow/python:math_ops", + "//tensorflow/python:gradients_impl", "//tensorflow/python:list_ops", + "//tensorflow/python:math_ops", + "//tensorflow/python:tensor_shape", "//tensorflow/python/eager:context", "//tensorflow/python:framework_for_generated_wrappers", "//tensorflow/python:framework_test_lib", @@ -268,7 +270,7 @@ tf_py_test( ], ) -tf_py_test( +cuda_py_test( name = "ctc_loss_op_test", size = "small", srcs = ["ctc_loss_op_test.py"], @@ -659,6 +661,18 @@ cuda_py_test( ], ) +cuda_py_test( + name = "matrix_square_root_op_test", + size = "medium", + srcs = ["matrix_square_root_op_test.py"], + additional_deps = [ + "//third_party/py/numpy", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:linalg_ops", + ], +) + cuda_py_test( name = "matrix_solve_op_test", size = "medium", @@ -817,6 +831,7 @@ tf_py_test( "//tensorflow/core:protos_all_py", "//tensorflow/python:client", "//tensorflow/python:client_testlib", + "//tensorflow/python:constant_op", "//tensorflow/python:io_ops", "//tensorflow/python:io_ops_gen", ], @@ -1142,6 +1157,21 @@ cuda_py_test( ], ) +tf_py_test( + name = "unicode_encode_op_test", + size = "small", + srcs = ["unicode_encode_op_test.py"], + additional_deps = [ + "@absl_py//absl/testing:parameterized", + "//third_party/py/numpy", + "//tensorflow/python:client_testlib", + "//tensorflow/python:constant_op", + "//tensorflow/python:errors", + "//tensorflow/python/ops/ragged:ragged_factory_ops", + "//tensorflow/python/ops/ragged:ragged_string_ops", + ], +) + tf_py_test( name = "unicode_transcode_op_test", size = "small", @@ -1154,6 +1184,18 @@ tf_py_test( ], ) +tf_py_test( + name = "unicode_decode_op_test", + size = "small", + srcs = ["unicode_decode_op_test.py"], + additional_deps = [ + "@absl_py//absl/testing:parameterized", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:string_ops", + ], +) + tf_py_test( name = "unique_op_test", size = "small", @@ -1338,6 +1380,7 @@ cuda_py_test( "//tensorflow/python:test_ops", "//tensorflow/python:variables", "//tensorflow/python/eager:context", + "//tensorflow/python/eager:def_function", ], shard_count = 10, tags = [ @@ -1449,6 +1492,7 @@ cuda_py_test( additional_deps = [ "//third_party/py/numpy", "//tensorflow/python/eager:context", + "//tensorflow/python/eager:def_function", "//tensorflow/python:array_ops", "//tensorflow/python:check_ops", "//tensorflow/python:math_ops", @@ -1736,9 +1780,11 @@ cuda_py_test( "//tensorflow/python:tensor_array_grad", "//tensorflow/python:variable_scope", "//tensorflow/python:variables", + "//tensorflow/python:while_v2", "//tensorflow/python/data/ops:iterator_ops", ], grpc_enabled = True, + shard_count = 2, tags = ["no_windows"], ) @@ -2371,6 +2417,8 @@ cuda_py_test( "//tensorflow/python:tensor_array_ops", "//tensorflow/python:variables", "//tensorflow/python:variable_scope", + "//tensorflow/python:cond_v2", + "//tensorflow/python:while_v2", "//tensorflow/python/eager:backprop", "//tensorflow/python/eager:context", ], @@ -2614,34 +2662,6 @@ cuda_py_test( tags = ["manual"], ) -cuda_py_test( - name = "dct_ops_test", - srcs = ["dct_ops_test.py"], - additional_deps = [ - "//third_party/py/numpy", - "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_for_generated_wrappers", - "//tensorflow/python:spectral_ops", - "//tensorflow/python:spectral_ops_test_util", - ], -) - -cuda_py_test( - name = "fft_ops_test", - size = "medium", - srcs = ["fft_ops_test.py"], - additional_deps = [ - "//third_party/py/numpy", - "//tensorflow/python:client_testlib", - "//tensorflow/python:framework_for_generated_wrappers", - "//tensorflow/python:math_ops", - "//tensorflow/python:spectral_ops", - "//tensorflow/python:spectral_ops_test_util", - ], - shard_count = 4, - tags = ["optonly"], -) - cuda_py_test( name = "pooling_ops_3d_test", size = "medium", @@ -3330,7 +3350,9 @@ cuda_py_test( "//tensorflow/python:framework", "//tensorflow/python:framework_ops", "//tensorflow/python:gradients", + "//tensorflow/python:tensor_array_ops", "//tensorflow/python:training", + "//tensorflow/python:while_v2", ], grpc_enabled = True, ) diff --git a/tensorflow/python/kernel_tests/accumulate_n_test.py b/tensorflow/python/kernel_tests/accumulate_n_test.py index 7889edc198..5eece9c941 100644 --- a/tensorflow/python/kernel_tests/accumulate_n_test.py +++ b/tensorflow/python/kernel_tests/accumulate_n_test.py @@ -32,6 +32,7 @@ from tensorflow.python.platform import googletest class AccumulateNV2Test(test_util.TensorFlowTestCase): """Tests of the new, differentiable version of accumulate_n.""" + @test_util.run_deprecated_v1 def testFloat(self): np.random.seed(12345) x = [np.random.random((1, 2, 3, 4, 5)) - 0.5 for _ in range(5)] @@ -41,6 +42,7 @@ class AccumulateNV2Test(test_util.TensorFlowTestCase): self.assertAllClose(x[0] * 5, math_ops.accumulate_n([tf_x[0]] * 5).eval()) + @test_util.run_deprecated_v1 def testInt(self): np.random.seed(54321) x = [np.random.randint(-128, 128, (5, 4, 3, 2, 1)) for _ in range(6)] @@ -50,12 +52,14 @@ class AccumulateNV2Test(test_util.TensorFlowTestCase): self.assertAllEqual(x[0] * 6, math_ops.accumulate_n([tf_x[0]] * 6).eval()) + @test_util.run_deprecated_v1 def testUnknownShape(self): with self.session(use_gpu=True): x0 = array_ops.placeholder(dtype=dtypes_lib.int32, shape=[None]) acc = math_ops.accumulate_n([x0, x0], shape=[None]) self.assertAllEqual([2, 4], acc.eval(feed_dict={x0: [1, 2]})) + @test_util.run_deprecated_v1 def testGrad(self): np.random.seed(42) for num_inputs in range(1, 10): @@ -65,7 +69,7 @@ class AccumulateNV2Test(test_util.TensorFlowTestCase): for _ in range(0, num_inputs) ] accum_n = math_ops.accumulate_n(input_vars) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) accum_n_grad = gradients.gradients(accum_n, input_vars) self.assertAllEqual( np.repeat(1.0, num_inputs), # d/dx (x + y + ...) = 1 @@ -88,13 +92,13 @@ class AccumulateNV2Test(test_util.TensorFlowTestCase): np_val = random_arrays[0] for random_array in random_arrays[1:]: np_val += random_array - self.assertAllClose(np_val, tf_val.eval()) + self.assertAllClose(np_val, self.evaluate(tf_val)) def testZeroArgs(self): with self.cached_session(): with self.assertRaises(ValueError): tf_val = math_ops.accumulate_n([]) - tf_val.eval() + self.evaluate(tf_val) def testWrongShape(self): with self.cached_session(): diff --git a/tensorflow/python/kernel_tests/ackermann_test.py b/tensorflow/python/kernel_tests/ackermann_test.py index d267e49752..6c20b19be9 100644 --- a/tensorflow/python/kernel_tests/ackermann_test.py +++ b/tensorflow/python/kernel_tests/ackermann_test.py @@ -20,12 +20,14 @@ from __future__ import print_function import os from tensorflow.python.framework import load_library +from tensorflow.python.framework import test_util from tensorflow.python.platform import resource_loader from tensorflow.python.platform import test class AckermannTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): library_filename = os.path.join(resource_loader.get_data_files_path(), 'ackermann_op.so') diff --git a/tensorflow/python/kernel_tests/aggregate_ops_test.py b/tensorflow/python/kernel_tests/aggregate_ops_test.py index 0f15319cb5..d9787cc3bf 100644 --- a/tensorflow/python/kernel_tests/aggregate_ops_test.py +++ b/tensorflow/python/kernel_tests/aggregate_ops_test.py @@ -24,6 +24,7 @@ from tensorflow.core.framework import tensor_pb2 from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import logging_ops from tensorflow.python.ops import math_ops @@ -61,12 +62,13 @@ class AddNTest(test.TestCase): for dtype in self._supported_types(): for count in range(1, self._MAX_N + 1): data = [self._buildData((2, 2), dtype) for _ in range(count)] - actual = sess.run(math_ops.add_n(data)) + actual = self.evaluate(math_ops.add_n(data)) expected = np.sum(np.vstack( [np.expand_dims(d, 0) for d in data]), axis=0) tol = 5e-3 if dtype == dtypes.float16 else 5e-7 self.assertAllClose(expected, actual, rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testUnknownShapes(self): np.random.seed(12345) with self.session(use_gpu=True) as sess: @@ -80,6 +82,7 @@ class AddNTest(test.TestCase): tol = 5e-3 if dtype == dtypes.float16 else 5e-7 self.assertAllClose(expected, actual, rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testVariant(self): def create_constant_variant(value): diff --git a/tensorflow/python/kernel_tests/argmax_op_test.py b/tensorflow/python/kernel_tests/argmax_op_test.py index fa370c17b4..06ec0948c2 100644 --- a/tensorflow/python/kernel_tests/argmax_op_test.py +++ b/tensorflow/python/kernel_tests/argmax_op_test.py @@ -20,6 +20,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -37,14 +38,14 @@ class ArgMaxTest(test.TestCase): with self.session(use_gpu=use_gpu): ans = method(x, axis=axis) if expected_err_re is None: - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) # Defaults to int64 output. self.assertEqual(np.int64, tf_ans.dtype) self.assertAllEqual(tf_ans, expected_values) self.assertShapeEqual(expected_values, ans) else: with self.assertRaisesOpError(expected_err_re): - ans.eval() + self.evaluate(ans) def _testBothArg(self, method, @@ -79,7 +80,7 @@ class ArgMaxTest(test.TestCase): expected_values = x.argmax() with self.session(use_gpu=True): ans = math_ops.argmax(x, axis=0, output_type=dtypes.int32) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertEqual(np.int32, tf_ans.dtype) # The values are equal when comparing int32 to int64 because # the values don't have a range that exceeds 32-bit integers. @@ -87,7 +88,7 @@ class ArgMaxTest(test.TestCase): expected_values = x.argmin() with self.session(use_gpu=True): ans = math_ops.argmin(x, axis=0, output_type=dtypes.int32) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertEqual(np.int32, tf_ans.dtype) self.assertAllEqual(tf_ans, expected_values) @@ -110,12 +111,14 @@ class ArgMaxTest(test.TestCase): r"Reduction axis 0 is empty in shape \[0\]"): op([], 0).eval() + @test_util.run_deprecated_v1 def testDefaultAxis(self): with self.cached_session(): for op in math_ops.argmin, math_ops.argmax: ans = op([1]).eval() self.assertAllEqual(ans, 0) + @test_util.run_deprecated_v1 def testOutputEmpty(self): with self.cached_session(): for op in math_ops.argmin, math_ops.argmax: diff --git a/tensorflow/python/kernel_tests/array_ops_test.py b/tensorflow/python/kernel_tests/array_ops_test.py index c90794c789..f4c442b7b1 100644 --- a/tensorflow/python/kernel_tests/array_ops_test.py +++ b/tensorflow/python/kernel_tests/array_ops_test.py @@ -25,6 +25,7 @@ import numpy as np from tensorflow.python.client import session from tensorflow.python.eager import context +from tensorflow.python.eager import def_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors @@ -32,6 +33,7 @@ from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import tensor_spec from tensorflow.python.framework import test_ops from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops @@ -46,24 +48,23 @@ from tensorflow.python.ops import variables from tensorflow.python.platform import test as test_lib +@test_util.run_all_in_graph_and_eager_modes class BatchMatrixTransposeTest(test_util.TensorFlowTestCase): def testNonBatchMatrix(self): matrix = [[1, 2, 3], [4, 5, 6]] # Shape (2, 3) expected_transposed = [[1, 4], [2, 5], [3, 6]] # Shape (3, 2) - with self.cached_session(): - transposed = array_ops.matrix_transpose(matrix) - self.assertEqual((3, 2), transposed.get_shape()) - self.assertAllEqual(expected_transposed, transposed.eval()) + transposed = array_ops.matrix_transpose(matrix) + self.assertEqual((3, 2), transposed.get_shape()) + self.assertAllEqual(expected_transposed, transposed) def testConjugate(self): m = [[1 + 1j, 2 + 2j, 3 + 3j], [4 + 4j, 5 + 5j, 6 + 6j]] expected_transposed = [[1 - 1j, 4 - 4j], [2 - 2j, 5 - 5j], [3 - 3j, 6 - 6j]] - with self.cached_session(): - matrix = ops.convert_to_tensor(m) - transposed = array_ops.matrix_transpose(matrix, conjugate=True) - self.assertEqual((3, 2), transposed.get_shape()) - self.assertAllEqual(expected_transposed, transposed.eval()) + matrix = ops.convert_to_tensor(m) + transposed = array_ops.matrix_transpose(matrix, conjugate=True) + self.assertEqual((3, 2), transposed.get_shape()) + self.assertAllEqual(expected_transposed, transposed) def testBatchMatrix(self): matrix_0 = [[1, 2, 3], [4, 5, 6]] @@ -72,43 +73,44 @@ class BatchMatrixTransposeTest(test_util.TensorFlowTestCase): matrix_1_t = [[11, 44], [22, 55], [33, 66]] batch_matrix = [matrix_0, matrix_1] # Shape (2, 2, 3) expected_transposed = [matrix_0_t, matrix_1_t] # Shape (2, 3, 2) - with self.cached_session(): - transposed = array_ops.matrix_transpose(batch_matrix) - self.assertEqual((2, 3, 2), transposed.get_shape()) - self.assertAllEqual(expected_transposed, transposed.eval()) + transposed = array_ops.matrix_transpose(batch_matrix) + self.assertEqual((2, 3, 2), transposed.get_shape()) + self.assertAllEqual(expected_transposed, transposed) def testNonBatchMatrixDynamicallyDefined(self): - matrix = [[1, 2, 3], [4, 5, 6]] # Shape (2, 3) + # needs explicit `constant` because lists are not automatically + # converted to sensors when applying `transpose` below + matrix = constant_op.constant([[1, 2, 3], [4, 5, 6]]) # Shape (2, 3) expected_transposed = [[1, 4], [2, 5], [3, 6]] # Shape (3, 2) - with self.cached_session(): - matrix_ph = array_ops.placeholder(dtypes.int32) - transposed = array_ops.matrix_transpose(matrix_ph) - self.assertAllEqual( - expected_transposed, transposed.eval(feed_dict={ - matrix_ph: matrix - })) + @def_function.function(input_signature= + [tensor_spec.TensorSpec + (shape=None, dtype=dtypes.int32)]) + def transpose(matrix): + self.assertIs(matrix.shape.ndims, None) + return array_ops.matrix_transpose(matrix) + self.assertAllEqual(expected_transposed, transpose(matrix)) def testBatchMatrixDynamicallyDefined(self): matrix_0 = [[1, 2, 3], [4, 5, 6]] matrix_0_t = [[1, 4], [2, 5], [3, 6]] matrix_1 = [[11, 22, 33], [44, 55, 66]] matrix_1_t = [[11, 44], [22, 55], [33, 66]] - batch_matrix = [matrix_0, matrix_1] # Shape (2, 2, 3) + # needs explicit `constant` because lists are not automatically + # converted to sensors when applying `transpose` below + batch_matrix = constant_op.constant([matrix_0, matrix_1]) # Shape (2, 2, 3) expected_transposed = [matrix_0_t, matrix_1_t] # Shape (2, 3, 2) - with self.cached_session(): - batch_matrix_ph = array_ops.placeholder(dtypes.int32) - transposed = array_ops.matrix_transpose(batch_matrix_ph) - self.assertAllEqual( - expected_transposed, - transposed.eval(feed_dict={ - batch_matrix_ph: batch_matrix - })) + @def_function.function(input_signature= + [tensor_spec.TensorSpec + (shape=None, dtype=dtypes.int32)]) + def transpose(matrix): + self.assertIs(matrix.shape.ndims, None) + return array_ops.matrix_transpose(matrix) + self.assertAllEqual(expected_transposed, transpose(batch_matrix)) def testTensorWithStaticRankLessThanTwoRaisesBecauseNotAMatrix(self): vector = [1, 2, 3] - with self.cached_session(): - with self.assertRaisesRegexp(ValueError, "should be a "): - array_ops.matrix_transpose(vector) + with self.assertRaisesRegexp(ValueError, "should be a "): + array_ops.matrix_transpose(vector) class BooleanMaskTest(test_util.TensorFlowTestCase): @@ -141,36 +143,43 @@ class BooleanMaskTest(test_util.TensorFlowTestCase): self.assertAllClose(masked_arr, masked_tensor.eval()) + @test_util.run_deprecated_v1 def testMaskDim1ArrDim2Axis1(self): ndims_mask = 1 for arr_shape in [(1, 1), (2, 2), (2, 5)]: self.CheckVersusNumpy(ndims_mask, arr_shape, axis=1) + @test_util.run_deprecated_v1 def testMaskDim2ArrDim2Axis1(self): ndims_mask = 2 for arr_shape in [(1, 1), (2, 2), (2, 5)]: self.CheckVersusNumpy(ndims_mask, arr_shape, axis=1) + @test_util.run_deprecated_v1 def testMaskDim1ArrDim1(self): ndims_mask = 1 for arr_shape in [(1,), (2,), (3,), (10,)]: self.CheckVersusNumpy(ndims_mask, arr_shape) + @test_util.run_deprecated_v1 def testMaskDim1ArrDim2(self): ndims_mask = 1 for arr_shape in [(1, 1), (2, 2), (2, 5)]: self.CheckVersusNumpy(ndims_mask, arr_shape) + @test_util.run_deprecated_v1 def testMaskDim2ArrDim2(self): ndims_mask = 2 for arr_shape in [(1, 1), (2, 2), (2, 5)]: self.CheckVersusNumpy(ndims_mask, arr_shape) + @test_util.run_deprecated_v1 def testMaskDim2ArrDim3(self): ndims_mask = 2 for arr_shape in [(1, 1, 1), (1, 2, 2), (2, 2, 1)]: self.CheckVersusNumpy(ndims_mask, arr_shape) + @test_util.run_deprecated_v1 def testEmptyInput2D(self): mask = np.array([True, False]) arr = np.array([[], []]).astype(np.float32) @@ -189,6 +198,7 @@ class BooleanMaskTest(test_util.TensorFlowTestCase): with self.cached_session(): self.assertAllClose(numpy_result, tf_result.eval()) + @test_util.run_deprecated_v1 def testEmptyOutput(self): make_mask = lambda shape: np.zeros(shape, dtype=bool) for ndims_mask in range(1, 4): @@ -197,6 +207,7 @@ class BooleanMaskTest(test_util.TensorFlowTestCase): arr_shape = np.random.randint(1, 5, size=ndims_arr) self.CheckVersusNumpy(ndims_mask, arr_shape, make_mask=make_mask) + @test_util.run_deprecated_v1 def testWorksWithDimensionsEqualToNoneDuringGraphBuild(self): # The rank of the mask tensor must be specified. This is explained # in the docstring as well. @@ -215,6 +226,7 @@ class BooleanMaskTest(test_util.TensorFlowTestCase): }) np.testing.assert_allclose(masked_tensor, arr[mask]) + @test_util.run_deprecated_v1 def testMaskDimensionsSetToNoneRaises(self): # The rank of the mask tensor must be specified. This is explained # in the docstring as well. @@ -281,6 +293,7 @@ class OperatorShapeTest(test_util.TensorFlowTestCase): class ReverseV2Test(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testReverse0DimAuto(self): x_np = 4 for use_gpu in [False, True]: @@ -325,6 +338,7 @@ class ReverseV2Test(test_util.TensorFlowTestCase): # This test covers the axis validation in the shape function # (no eval()) + @test_util.run_deprecated_v1 def testInvalidAxis(self): x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32) with self.assertRaisesRegexp(ValueError, @@ -343,6 +357,7 @@ class ReverseV2Test(test_util.TensorFlowTestCase): # # Note: this test passes placeholder as constant axis is validated # in shape function (see testInvalidAxis) + @test_util.run_deprecated_v1 def testInvalid(self): x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.float32) axis = array_ops.placeholder(dtypes.int32) @@ -357,6 +372,7 @@ class ReverseV2Test(test_util.TensorFlowTestCase): "axis 0 specified more than once"): array_ops.reverse_v2(x_np, axis).eval(feed_dict={axis: [0, -2]}) + @test_util.run_deprecated_v1 def testReverse1DimAuto(self): for dtype in [ np.uint8, np.int8, np.uint16, np.int16, np.int32, np.int64, np.bool, @@ -365,6 +381,7 @@ class ReverseV2Test(test_util.TensorFlowTestCase): ]: self._reverse1DimAuto(dtype) + @test_util.run_deprecated_v1 def testReverse2DimAuto(self): for dtype in [ np.uint8, np.int8, np.uint16, np.int16, np.int32, np.int64, np.bool, @@ -373,6 +390,7 @@ class ReverseV2Test(test_util.TensorFlowTestCase): ]: self._reverse2DimAuto(dtype) + @test_util.run_deprecated_v1 def testUnknownDims(self): reverse_v2 = array_ops.reverse_v2 data_t = array_ops.placeholder(dtypes.float32) @@ -390,6 +408,7 @@ class ReverseV2Test(test_util.TensorFlowTestCase): reverse_2d_t = reverse_v2(data_2d_t, axis_2d_t) self.assertEqual(2, reverse_2d_t.get_shape().ndims) + @test_util.run_deprecated_v1 def testReverseRowsOf3Channels(self): """Tests optimized code for reversing rows with last dim size = 3.""" with self.session(use_gpu=True): @@ -403,6 +422,7 @@ class ReverseV2Test(test_util.TensorFlowTestCase): np_answer = x_np[:, ::-1, :] self.assertAllEqual(x_tf, np_answer) + @test_util.run_deprecated_v1 def testReverseRowsOf4Channels(self): with self.session(use_gpu=True): for reverse_f in [array_ops.reverse_v2, array_ops.reverse]: @@ -452,6 +472,7 @@ class MeshgridTest(test_util.TensorFlowTestCase): for x_np, x_tf in zip(numpy_out, tf_out): self.assertAllEqual(x_np, x_tf.eval()) + @test_util.run_deprecated_v1 def testCompare(self): for t in (np.float16, np.float32, np.float64, np.int32, np.int64, np.complex64, np.complex128): @@ -524,6 +545,7 @@ STRIDED_SLICE_TYPES = [ class StridedSliceTest(test_util.TensorFlowTestCase): """Test the strided slice operation with variants of slices.""" + @test_util.run_deprecated_v1 def test_basic_slice(self): for tensor_type in STRIDED_SLICE_TYPES: with self.cached_session(use_gpu=True): @@ -554,7 +576,8 @@ class StridedSliceTest(test_util.TensorFlowTestCase): def testInt64GPU(self): if not test_util.is_gpu_available(): self.skipTest("No GPU available") - with self.session(use_gpu=True, force_gpu=True): + + with test_util.force_gpu(): x = constant_op.constant([1., 2., 3.]) begin = constant_op.constant([2], dtype=dtypes.int64) end = constant_op.constant([3], dtype=dtypes.int64) @@ -578,6 +601,7 @@ class StridedSliceTest(test_util.TensorFlowTestCase): v = variables.Variable([1., 2.]) v[0] # pylint: disable=pointless-statement + @test_util.run_deprecated_v1 def testDegenerateSlices(self): with self.session(use_gpu=True): checker = StridedSliceChecker(self, StridedSliceChecker.REF_TENSOR) @@ -588,6 +612,7 @@ class StridedSliceTest(test_util.TensorFlowTestCase): # empty interval in every dimension _ = checker[-1:0, 2:2, 2:3:-1] + @test_util.run_deprecated_v1 def testEllipsis(self): with self.session(use_gpu=True): raw = [[[[[1, 2], [3, 4], [5, 6]]], [[[7, 8], [9, 10], [11, 12]]]]] @@ -608,6 +633,7 @@ class StridedSliceTest(test_util.TensorFlowTestCase): with self.assertRaisesRegexp(ValueError, "Multiple ellipses"): _ = checker[..., :, ...].eval() + @test_util.run_deprecated_v1 def testShrink(self): with self.session(use_gpu=True): raw = [[[[[1, 2, 4, 5], [5, 6, 7, 8], [9, 10, 11, 12]]], @@ -618,6 +644,7 @@ class StridedSliceTest(test_util.TensorFlowTestCase): _ = checker[:, 0] _ = checker[:, :, 0] + @test_util.run_deprecated_v1 def testBothNewAxisAndShrink(self): with self.session(use_gpu=True): ones = array_ops.placeholder(shape=[2, 2], dtype=dtypes.int16) @@ -626,6 +653,7 @@ class StridedSliceTest(test_util.TensorFlowTestCase): feed_dict={ones: [[1, 1], [1, 1]]}), [[1, 1]]) + @test_util.run_deprecated_v1 def testTensorIndexing(self): with self.session(use_gpu=True): raw = [[[[[1, 2, 4, 5], [5, 6, 7, 8], [9, 10, 11, 12]]], @@ -636,6 +664,7 @@ class StridedSliceTest(test_util.TensorFlowTestCase): _ = checker[..., bar:bar2] _ = checker[..., bar] _ = checker[..., 3] + _ = checker[..., 2 ** 64 // 2**63] # Test longs in Python 2 def testTensorIndexingTypeError(self): with self.session(use_gpu=True): @@ -650,6 +679,7 @@ class StridedSliceTest(test_util.TensorFlowTestCase): with self.assertRaisesRegexp(TypeError, expected): _ = checker[constant_op.constant(0.0)] + @test_util.run_deprecated_v1 def testExpand(self): with self.session(use_gpu=True): raw = [[[[[1, 2, 4, 5], [5, 6, 7, 8], [9, 10, 11, 12]]], @@ -667,6 +697,7 @@ class StridedSliceTest(test_util.TensorFlowTestCase): # Ellipsis in middle of two newaxis _ = checker[np.newaxis, ..., np.newaxis] + @test_util.run_deprecated_v1 def testExpandVariable(self): with self.session(use_gpu=True): x = variables.Variable(7, dtype=dtypes.int32) @@ -675,6 +706,7 @@ class StridedSliceTest(test_util.TensorFlowTestCase): self.assertEqual(y.shape, (1,)) self.assertAllEqual(y, (7,)) + @test_util.run_deprecated_v1 def testOptimizedCases(self): with self.session(use_gpu=True): checker = StridedSliceChecker(self, @@ -704,6 +736,7 @@ class StridedSliceShapeChecker(object): class StridedSliceShapeTest(test_util.TensorFlowTestCase): """Test the shape inference of StridedSliceShapes.""" + @test_util.run_deprecated_v1 def testUnknown(self): with self.session(use_gpu=True): uncertain_tensor = array_ops.placeholder(dtypes.float32) @@ -715,6 +748,7 @@ class StridedSliceShapeTest(test_util.TensorFlowTestCase): self.assertTrue(x is not None and y is not None or x is None and y is None) self.assertEqual(x.as_list(), y.as_list()) + @test_util.run_deprecated_v1 def testTensorShapeUncertain(self): with self.session(use_gpu=True): uncertain_tensor = array_ops.placeholder( @@ -738,6 +772,7 @@ class StridedSliceShapeTest(test_util.TensorFlowTestCase): self.tensorShapeEqual(a[::-1, :, array_ops.newaxis, ::-2], tensor_shape.TensorShape([5, None, 1, 4])) + @test_util.run_deprecated_v1 def testTensorValuedIndexShape(self): with self.session(use_gpu=True): defined_shape_tensor = array_ops.placeholder( @@ -794,6 +829,7 @@ class GradSliceChecker(object): class StridedSliceGradTest(test_util.TensorFlowTestCase): """Test that strided slice's custom gradient produces correct gradients.""" + @test_util.run_deprecated_v1 def testGradient(self): with self.session(use_gpu=True) as sess: var = variables.Variable( @@ -823,18 +859,20 @@ class StridedSliceGradTest(test_util.TensorFlowTestCase): grad = GradSliceChecker(self, sess, var, np.array(8)) _ = grad[tuple()] + @test_util.run_deprecated_v1 def testInt64Indices(self): with self.session(use_gpu=True) as sess: a = math_ops.range(3, dtype=dtypes.float32) index = constant_op.constant(1, dtype=dtypes.int64) b = 2. * a[index] grad, = gradients_impl.gradients(b, a) - self.assertAllEqual(sess.run(grad), [0., 2., 0.]) + self.assertAllEqual(self.evaluate(grad), [0., 2., 0.]) class StridedSliceGradTypeTest(test_util.TensorFlowTestCase): """Test varied index types and host located memory.""" + @test_util.run_deprecated_v1 def testHostVsDevice(self): with self.session(use_gpu=True) as sess: var2 = variables.Variable( @@ -842,20 +880,21 @@ class StridedSliceGradTypeTest(test_util.TensorFlowTestCase): math_ops.cast(math_ops.range(1, 5, 1), dtypes.float32), shape=(4, 1, 1))) varshape = variables.Variable([6, 4, 4], dtype=dtypes.int32) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) begin = constant_op.constant([0, 0, 0]) end = constant_op.constant([4, 1, 1]) strides = constant_op.constant([1, 1, 1]) foo = array_ops.strided_slice_grad(varshape, begin, end, strides, var2) sess.run(foo) + @test_util.run_deprecated_v1 def testInt64Shape(self): with self.session(use_gpu=True) as sess: original_dy = array_ops.reshape( math_ops.cast(math_ops.range(1, 5, 1), dtypes.float32), shape=(4, 1, 1)) original_shape = constant_op.constant([6, 4, 4], dtype=dtypes.int64) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) begin = constant_op.constant([0, 0, 0], dtype=dtypes.int64) end = constant_op.constant([4, 1, 1], dtype=dtypes.int64) strides = constant_op.constant([1, 1, 1], dtype=dtypes.int64) @@ -863,13 +902,14 @@ class StridedSliceGradTypeTest(test_util.TensorFlowTestCase): original_dy) sess.run(dx) + @test_util.run_deprecated_v1 def testMixedIndexTypes(self): with self.session(use_gpu=True) as sess: original_dy = array_ops.reshape( math_ops.cast(math_ops.range(1, 5, 1), dtypes.float32), shape=(4, 1, 1)) original_shape = constant_op.constant([6, 4, 4], dtype=dtypes.int64) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) begin = constant_op.constant([0, 0, 0], dtype=dtypes.int32) end = constant_op.constant([4, 1, 1], dtype=dtypes.int64) strides = constant_op.constant([1, 1, 1], dtype=dtypes.int64) @@ -971,6 +1011,7 @@ class StridedSliceAssignChecker(object): class SliceAssignTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testInvalidSlice(self): with self.cached_session() as sess: foo = constant_op.constant([1, 2, 3]) @@ -1008,12 +1049,15 @@ class SliceAssignTest(test_util.TensorFlowTestCase): checker2[...] = 6 # ellipsis checker2[None] = [6] # new axis + @test_util.run_deprecated_v1 def testSliceAssign(self): self.doTestSliceAssign(use_resource=False) + @test_util.run_deprecated_v1 def testSliceAssignResource(self): self.doTestSliceAssign(use_resource=True) + @test_util.run_deprecated_v1 def testUninitialized(self): with self.assertRaisesRegexp( errors.FailedPreconditionError, @@ -1032,13 +1076,14 @@ class SliceAssignTest(test_util.TensorFlowTestCase): with self.assertRaises(TypeError): v[:].assign(too_large_val) + @test_util.run_deprecated_v1 def testTypeErrorResource(self): init_val = constant_op.constant([1, 2], dtype=dtypes.int32) too_small_val = constant_op.constant([3, 4], dtype=dtypes.int8) too_large_val = constant_op.constant([3, 4], dtype=dtypes.int64) v = resource_variable_ops.ResourceVariable(init_val) with self.cached_session() as sess: - sess.run(v.initializer) + self.evaluate(v.initializer) with self.assertRaises(ValueError): sess.run(v[:].assign(too_large_val)) with self.assertRaises(ValueError): @@ -1088,6 +1133,7 @@ class SequenceMaskTest(test_util.TensorFlowTestCase): with self.assertRaisesRegexp(ValueError, "maxlen must be scalar"): array_ops.sequence_mask([10, 20], [10, 20]) + @test_util.run_deprecated_v1 def testOneDimensionalWithMaxlen(self): with self.cached_session(): res = array_ops.sequence_mask(constant_op.constant([1, 3, 2]), 5) @@ -1097,7 +1143,7 @@ class SequenceMaskTest(test_util.TensorFlowTestCase): [[True, False, False, False, False], [True, True, True, False, False], [True, True, False, False, False]]) - @test_util.enable_c_shapes + @test_util.run_deprecated_v1 def testOneDimensionalDtypeWithoutMaxlen(self): with self.cached_session(): # test dtype and default maxlen: @@ -1108,7 +1154,7 @@ class SequenceMaskTest(test_util.TensorFlowTestCase): res.eval(), [[0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]]) - @test_util.enable_c_shapes + @test_util.run_deprecated_v1 def testOneDimensionalWithoutMaxlen(self): with self.cached_session(): res = array_ops.sequence_mask( @@ -1120,7 +1166,6 @@ class SequenceMaskTest(test_util.TensorFlowTestCase): [True, False, False, False], [True, True, True, True]]) - @test_util.enable_c_shapes def testTwoDimensional(self): with self.cached_session(): res = array_ops.sequence_mask(constant_op.constant([[1, 3, 2]]), 5) @@ -1138,11 +1183,13 @@ class SequenceMaskTest(test_util.TensorFlowTestCase): [[[0.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]], [[1.0, 0.0, 0.0, 0.0], [1.0, 1.0, 0.0, 0.0], [1.0, 1.0, 1.0, 0.0]]]) + @test_util.run_deprecated_v1 def testUnknownShape(self): lengths = array_ops.placeholder(dtype=dtypes.int32) res = array_ops.sequence_mask(lengths) self.assertEqual(res.shape, None) + @test_util.run_deprecated_v1 def testDtypes(self): def check_dtypes(lengths_dtype, maxlen_dtype): @@ -1165,6 +1212,7 @@ class SequenceMaskTest(test_util.TensorFlowTestCase): class ConcatSliceResourceTest(test_util.TensorFlowTestCase): @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testConcatSlice(self): r1 = test_ops.stub_resource_handle_op(container="a", shared_name="b") r2 = test_ops.stub_resource_handle_op(container="a", shared_name="c") @@ -1187,18 +1235,18 @@ class IdentityTest(test_util.TensorFlowTestCase): self.assertAllEqual(x.numpy(), y.numpy()) self.assertTrue(device in y.device.lower()) - with ops.device("gpu:0"): + with test_util.force_gpu(): a = constant_op.constant([[2], [3]], dtype=dtypes.float32) - with ops.device("gpu:0"): + with test_util.force_gpu(): b = array_ops.identity(a) _test(a, b, "gpu") - with ops.device("cpu:0"): + with test_util.force_cpu(): c = array_ops.identity(b) _test(b, c, "cpu") - with ops.device("cpu:0"): + with test_util.force_cpu(): d = array_ops.identity(c) _test(c, d, "cpu") - with ops.device("gpu:0"): + with test_util.force_gpu(): e = array_ops.identity(d) _test(d, e, "gpu") @@ -1220,6 +1268,7 @@ class PadTest(test_util.TensorFlowTestCase): class InvertPermutationTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testInvertPermutation(self): for dtype in [dtypes.int32, dtypes.int64]: with self.cached_session(use_gpu=True): @@ -1254,12 +1303,14 @@ class UnravelIndexTest(test_util.TensorFlowTestCase): class GuaranteeConstOpTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testSimple(self): with self.cached_session(): a = array_ops.constant(10) guarantee_a = array_ops.guarantee_const(a) self.assertEqual(10, guarantee_a.eval()) + @test_util.run_deprecated_v1 def testVariables(self): with self.cached_session() as sess: for use_resource in [False, True]: @@ -1268,9 +1319,10 @@ class GuaranteeConstOpTest(test_util.TensorFlowTestCase): initializer=init_ops.constant_initializer(10.0), use_resource=use_resource) guarantee_a = array_ops.guarantee_const(a) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertEqual(10.0, guarantee_a.eval()) + @test_util.run_deprecated_v1 def testResourceRejection(self): with self.cached_session() as sess: a = variable_scope.get_variable( @@ -1278,7 +1330,7 @@ class GuaranteeConstOpTest(test_util.TensorFlowTestCase): initializer=init_ops.constant_initializer(10.0), use_resource=True) guarantee_a = array_ops.guarantee_const(a.handle) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) with self.assertRaisesWithPredicateMatch(errors.InvalidArgumentError, "cannot be a resource variable"): guarantee_a.eval() @@ -1286,6 +1338,7 @@ class GuaranteeConstOpTest(test_util.TensorFlowTestCase): class SnapshotOpTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testInvertPermutation(self): for dtype in [dtypes.int32, dtypes.int64, dtypes.float32, dtypes.float64]: with self.cached_session(use_gpu=True): diff --git a/tensorflow/python/kernel_tests/as_string_op_test.py b/tensorflow/python/kernel_tests/as_string_op_test.py index dd4a90e5f6..287701a73e 100644 --- a/tensorflow/python/kernel_tests/as_string_op_test.py +++ b/tensorflow/python/kernel_tests/as_string_op_test.py @@ -20,6 +20,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import string_ops from tensorflow.python.platform import test @@ -27,6 +28,7 @@ from tensorflow.python.platform import test class AsStringOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testFloat(self): float_inputs_ = [ 0, 1, -1, 0.5, 0.25, 0.125, float("INF"), float("NAN"), float("-INF") @@ -78,6 +80,7 @@ class AsStringOpTest(test.TestCase): output = string_ops.as_string(input_, fill="ab") output.eval(feed_dict={input_: float_inputs_}) + @test_util.run_deprecated_v1 def testInt(self): # Cannot use values outside -128..127 for test, because we're also # testing int8 @@ -112,6 +115,7 @@ class AsStringOpTest(test.TestCase): output = string_ops.as_string(input_, precision=0) output.eval(feed_dict={input_: int_inputs_}) + @test_util.run_deprecated_v1 def testLargeInt(self): # Cannot use values outside -128..127 for test, because we're also # testing int8 @@ -130,6 +134,7 @@ class AsStringOpTest(test.TestCase): result = output.eval(feed_dict={input_: int_inputs_}) self.assertAllEqual(s(result), ["%d" % x for x in int_inputs_]) + @test_util.run_deprecated_v1 def testHalfInt(self): s = lambda strs: [x.decode("ascii") for x in strs] @@ -140,6 +145,7 @@ class AsStringOpTest(test.TestCase): result = output.eval(feed_dict={input_: int_inputs_}) self.assertAllEqual(s(result), ["%d" % x for x in int_inputs_]) + @test_util.run_deprecated_v1 def testBool(self): bool_inputs_ = [False, True] s = lambda strs: [x.decode("ascii") for x in strs] @@ -152,6 +158,7 @@ class AsStringOpTest(test.TestCase): result = output.eval(feed_dict={input_: bool_inputs_}) self.assertAllEqual(s(result), ["false", "true"]) + @test_util.run_deprecated_v1 def testComplex(self): float_inputs_ = [ 0, 1, -1, 0.5, 0.25, 0.125, complex("INF"), complex("NAN"), diff --git a/tensorflow/python/kernel_tests/atrous_conv2d_test.py b/tensorflow/python/kernel_tests/atrous_conv2d_test.py index 1d82b3d058..a13e325835 100644 --- a/tensorflow/python/kernel_tests/atrous_conv2d_test.py +++ b/tensorflow/python/kernel_tests/atrous_conv2d_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import nn_impl @@ -58,6 +59,7 @@ def _upsample_filters(filters, rate): class AtrousConv2DTest(test.TestCase): + @test_util.run_deprecated_v1 def testAtrousConv2DForward(self): with self.session(use_gpu=True): # Input: [batch, height, width, input_depth] @@ -79,8 +81,10 @@ class AtrousConv2DTest(test.TestCase): y1 = nn_ops.atrous_conv2d(x, f, rate, padding=padding) y2 = nn_ops.conv2d( x, f_up, strides=[1, 1, 1, 1], padding=padding) - self.assertAllClose(y1.eval(), y2.eval(), rtol=1e-3, atol=1e-3) + self.assertAllClose( + y1.eval(), self.evaluate(y2), rtol=1e-3, atol=1e-3) + @test_util.run_deprecated_v1 def testAtrousSequence(self): """Tests optimization of sequence of atrous convolutions. @@ -131,8 +135,10 @@ class AtrousConv2DTest(test.TestCase): y2 = nn_ops.conv2d(y2, f, strides=[1, 1, 1, 1], padding=padding) y2 = nn_ops.conv2d(y2, f, strides=[1, 1, 1, 1], padding=padding) y2 = array_ops.batch_to_space(y2, crops=pad, block_size=rate) - self.assertAllClose(y1.eval(), y2.eval(), rtol=1e-2, atol=1e-2) + self.assertAllClose( + y1.eval(), self.evaluate(y2), rtol=1e-2, atol=1e-2) + @test_util.run_deprecated_v1 def testGradient(self): with self.session(use_gpu=True): # Input: [batch, height, width, input_depth] @@ -160,6 +166,7 @@ class AtrousConv2DTest(test.TestCase): class AtrousConv2DTransposeTest(test.TestCase): + @test_util.run_deprecated_v1 def testAtrousConv2DTransposeForward(self): with self.session(use_gpu=True): # Input: [batch, height, width, input_depth] @@ -193,11 +200,13 @@ class AtrousConv2DTransposeTest(test.TestCase): padding) y2 = nn_ops.conv2d_transpose( x, f_up, y_shape, strides=[1, 1, 1, 1], padding=padding) - self.assertAllClose(y1.eval(), y2.eval(), rtol=1e-3, atol=1e-3) + self.assertAllClose( + y1.eval(), self.evaluate(y2), rtol=1e-3, atol=1e-3) class AtrousDepthwiseConv2DTest(test.TestCase): + @test_util.run_deprecated_v1 def testAtrousDepthwiseConv2DForward(self): strides = [1, 1, 1, 1] with self.session(use_gpu=True): @@ -220,7 +229,8 @@ class AtrousDepthwiseConv2DTest(test.TestCase): y1 = nn_impl.depthwise_conv2d( x, f, strides, padding, rate=[rate, rate]) y2 = nn_impl.depthwise_conv2d(x, f_up, strides, padding) - self.assertAllClose(y1.eval(), y2.eval(), rtol=1e-3, atol=1e-3) + self.assertAllClose( + y1.eval(), self.evaluate(y2), rtol=1e-3, atol=1e-3) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/attention_ops_test.py b/tensorflow/python/kernel_tests/attention_ops_test.py index 1e09ba5b65..00dba9996d 100644 --- a/tensorflow/python/kernel_tests/attention_ops_test.py +++ b/tensorflow/python/kernel_tests/attention_ops_test.py @@ -85,7 +85,7 @@ class ExtractGlimpseTest(test.TestCase): # Evaluate the TensorFlow Graph. with self.cached_session() as sess: - value_rows, value_cols = sess.run([glimpse_rows, glimpse_cols]) + value_rows, value_cols = self.evaluate([glimpse_rows, glimpse_cols]) # Check dimensions of returned glimpse. self.assertEqual(value_rows.shape[1], glimpse_sizes[0]) @@ -121,8 +121,7 @@ class ExtractGlimpseTest(test.TestCase): with self.cached_session(): result = image_ops.extract_glimpse(empty_image, [1, 1], offsets) self.assertAllEqual( - np.zeros( - (0, 1, 1, 0), dtype=np.float32), result.eval()) + np.zeros((0, 1, 1, 0), dtype=np.float32), self.evaluate(result)) def testLargeCenterGlimpse(self): self._VerifyValues( diff --git a/tensorflow/python/kernel_tests/barrier_ops_test.py b/tensorflow/python/kernel_tests/barrier_ops_test.py index 4d36b3a465..60fe6f0eec 100644 --- a/tensorflow/python/kernel_tests/barrier_ops_test.py +++ b/tensorflow/python/kernel_tests/barrier_ops_test.py @@ -25,6 +25,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import data_flow_ops from tensorflow.python.platform import test @@ -66,6 +67,7 @@ class BarrierTest(test.TestCase): attr { key: 'shared_name' value: { s: 'B' } } """, b.barrier_ref.op.node_def) + @test_util.run_deprecated_v1 def testInsertMany(self): with self.cached_session(): b = data_flow_ops.Barrier( @@ -90,6 +92,7 @@ class BarrierTest(test.TestCase): data_flow_ops.Barrier( (dtypes.float32, dtypes.float32), shapes=((1,), (0,)), name="B") + @test_util.run_deprecated_v1 def testInsertManyEmptyTensorUnknown(self): with self.cached_session(): b = data_flow_ops.Barrier((dtypes.float32, dtypes.float32), name="B") @@ -102,6 +105,7 @@ class BarrierTest(test.TestCase): ".*Tensors with no elements are not supported.*"): insert_0_op.run() + @test_util.run_deprecated_v1 def testTakeMany(self): with self.cached_session() as sess: b = data_flow_ops.Barrier( @@ -127,6 +131,7 @@ class BarrierTest(test.TestCase): self.assertEqual(values_0_val[idx], v0) self.assertEqual(values_1_val[idx], v1) + @test_util.run_deprecated_v1 def testTakeManySmallBatch(self): with self.cached_session() as sess: b = data_flow_ops.Barrier( @@ -191,6 +196,7 @@ class BarrierTest(test.TestCase): with self.assertRaisesOpError("is closed"): insert_1_3_op.run() + @test_util.run_deprecated_v1 def testUseBarrierWithShape(self): with self.cached_session() as sess: b = data_flow_ops.Barrier( @@ -220,6 +226,7 @@ class BarrierTest(test.TestCase): self.assertAllEqual(values_0_val[idx], v0) self.assertAllEqual(values_1_val[idx], v1) + @test_util.run_deprecated_v1 def testParallelInsertMany(self): with self.cached_session() as sess: b = data_flow_ops.Barrier(dtypes.float32, shapes=()) @@ -229,7 +236,7 @@ class BarrierTest(test.TestCase): insert_ops = [b.insert_many(0, [k], [v]) for k, v in zip(keys, values)] take_t = b.take_many(10) - sess.run(insert_ops) + self.evaluate(insert_ops) self.assertEquals(size_t.eval(), [10]) indices_val, keys_val, values_val = sess.run( @@ -240,6 +247,7 @@ class BarrierTest(test.TestCase): idx = keys_val.tolist().index(k) self.assertEqual(values_val[idx], v) + @test_util.run_deprecated_v1 def testParallelTakeMany(self): with self.cached_session() as sess: b = data_flow_ops.Barrier(dtypes.float32, shapes=()) @@ -274,6 +282,7 @@ class BarrierTest(test.TestCase): self.assertItemsEqual( zip(keys, values), [(k[0], v[0]) for k, v in zip(key_vals, value_vals)]) + @test_util.run_deprecated_v1 def testBlockingTakeMany(self): with self.cached_session() as sess: b = data_flow_ops.Barrier(dtypes.float32, shapes=()) @@ -296,6 +305,7 @@ class BarrierTest(test.TestCase): insert_op.run() t.join() + @test_util.run_deprecated_v1 def testParallelInsertManyTakeMany(self): with self.cached_session() as sess: b = data_flow_ops.Barrier( @@ -375,6 +385,7 @@ class BarrierTest(test.TestCase): 2 + outer_indices_from_keys + inner_indices_from_keys)).T self.assertAllEqual(taken_i["values_1"], expected_values_1) + @test_util.run_deprecated_v1 def testClose(self): with self.cached_session() as sess: b = data_flow_ops.Barrier( @@ -433,6 +444,7 @@ class BarrierTest(test.TestCase): with self.assertRaisesOpError("is closed and has insufficient elements"): sess.run(take_t[0]) + @test_util.run_deprecated_v1 def testCancel(self): with self.cached_session() as sess: b = data_flow_ops.Barrier( @@ -491,10 +503,11 @@ class BarrierTest(test.TestCase): b = data_flow_ops.Barrier( (dtypes.float32, dtypes.float32), shapes=((), ()), name="B") take_t = b.take_many(1, allow_small_batch=True) - sess.run(b.close(cancel)) + self.evaluate(b.close(cancel)) with self.assertRaisesOpError("is closed and has insufficient elements"): - sess.run(take_t) + self.evaluate(take_t) + @test_util.run_deprecated_v1 def testClosedEmptyBarrierTakeManyAllowSmallBatchRaises(self): self._testClosedEmptyBarrierTakeManyAllowSmallBatchRaises(cancel=False) self._testClosedEmptyBarrierTakeManyAllowSmallBatchRaises(cancel=True) @@ -569,9 +582,11 @@ class BarrierTest(test.TestCase): sorted(taken), [0] * (num_iterations // 2) + [10] * (num_iterations // 2)) + @test_util.run_deprecated_v1 def testParallelInsertManyTakeManyCloseHalfwayThrough(self): self._testParallelInsertManyTakeManyCloseHalfwayThrough(cancel=False) + @test_util.run_deprecated_v1 def testParallelInsertManyTakeManyCancelHalfwayThrough(self): self._testParallelInsertManyTakeManyCloseHalfwayThrough(cancel=True) @@ -669,12 +684,15 @@ class BarrierTest(test.TestCase): else: self.assertEqual(taken, [10] * num_iterations) + @test_util.run_deprecated_v1 def testParallelPartialInsertManyTakeManyCloseHalfwayThrough(self): self._testParallelPartialInsertManyTakeManyCloseHalfwayThrough(cancel=False) + @test_util.run_deprecated_v1 def testParallelPartialInsertManyTakeManyCancelHalfwayThrough(self): self._testParallelPartialInsertManyTakeManyCloseHalfwayThrough(cancel=True) + @test_util.run_deprecated_v1 def testIncompatibleSharedBarrierErrors(self): with self.cached_session(): # Do component types and shapes. diff --git a/tensorflow/python/kernel_tests/base64_ops_test.py b/tensorflow/python/kernel_tests/base64_ops_test.py index 1b399942ef..bb903d827f 100644 --- a/tensorflow/python/kernel_tests/base64_ops_test.py +++ b/tensorflow/python/kernel_tests/base64_ops_test.py @@ -93,7 +93,7 @@ class Base64OpsTest(test_util.TensorFlowTestCase): decoded = string_ops.decode_base64(encoded) with self.cached_session() as sess: - encoded_value, decoded_value = sess.run([encoded, decoded]) + encoded_value, decoded_value = self.evaluate([encoded, decoded]) self.assertEqual(encoded_value.shape, msg.shape) self.assertEqual(decoded_value.shape, msg.shape) diff --git a/tensorflow/python/kernel_tests/basic_gpu_test.py b/tensorflow/python/kernel_tests/basic_gpu_test.py index 225c1b35ae..1a8513d022 100644 --- a/tensorflow/python/kernel_tests/basic_gpu_test.py +++ b/tensorflow/python/kernel_tests/basic_gpu_test.py @@ -44,13 +44,13 @@ class GPUBinaryOpsTest(test.TestCase): inx = ops.convert_to_tensor(x) iny = ops.convert_to_tensor(y) out = tf_func(inx, iny) - tf_gpu = sess.run(out) + tf_gpu = self.evaluate(out) with self.cached_session(use_gpu=False) as sess: inx = ops.convert_to_tensor(x) iny = ops.convert_to_tensor(y) out = tf_func(inx, iny) - tf_cpu = sess.run(out) + tf_cpu = self.evaluate(out) self.assertAllClose(tf_cpu, tf_gpu) @@ -96,7 +96,7 @@ class MathBuiltinUnaryTest(test.TestCase): with self.cached_session(use_gpu=use_gpu) as sess: inx = ops.convert_to_tensor(x) ofunc = tf_func(inx) - tf_out = sess.run(ofunc) + tf_out = self.evaluate(ofunc) self.assertAllClose(np_out, tf_out) def _inv(self, x): @@ -148,7 +148,7 @@ class MathBuiltinUnaryTest(test.TestCase): iny = ops.convert_to_tensor(y + 0.1) ofunc = inx / iny out_func2 = math_ops.floor(ofunc) - tf_out = sess.run(out_func2) + tf_out = self.evaluate(out_func2) self.assertAllClose(np_out, tf_out) @@ -159,6 +159,7 @@ class BroadcastSimpleTest(test.TestCase): with self.cached_session(use_gpu=True) as sess: return sess.run(broadcast_gradient_args(xs, ys)) + @test_util.run_deprecated_v1 def testBroadcast(self): r0, r1 = self._GetGradientArgs([2, 3, 5], [1]) self.assertAllEqual(r0, []) @@ -214,11 +215,12 @@ class BroadcastSimpleTest(test.TestCase): inx = ops.convert_to_tensor(x) iny = ops.convert_to_tensor(y) out = tf_func(inx, iny) - tf_gpu = out.eval() + tf_gpu = self.evaluate(out) self.assertAllClose(np_ans, tf_gpu) self.assertShapeEqual(np_ans, out) # TODO(zhifengc/ke): make gradient checker work on GPU. + @test_util.run_deprecated_v1 def testGradient(self): x = (1 + np.linspace(0, 5, np.prod([1, 3, 2]))).astype(np.float32).reshape( [1, 3, 2]) @@ -255,6 +257,7 @@ class GpuMultiSessionMemoryTest(test_util.TensorFlowTestCase): if len(results) != 1: break + @test_util.run_deprecated_v1 def testConcurrentSessions(self): n_threads = 4 threads = [] diff --git a/tensorflow/python/kernel_tests/batch_gather_op_test.py b/tensorflow/python/kernel_tests/batch_gather_op_test.py index 547506d844..7e0b3e1b5e 100644 --- a/tensorflow/python/kernel_tests/batch_gather_op_test.py +++ b/tensorflow/python/kernel_tests/batch_gather_op_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test @@ -52,7 +53,7 @@ class GatherTest(test.TestCase, parameterized.TestCase): gather_t = array_ops.batch_gather(params, indices_tf) expected_result = np.array([3, 7]) np_val = self._buildParams(expected_result, dtype) - gather_val = gather_t.eval() + gather_val = self.evaluate(gather_t) self.assertAllEqual(np_val, gather_val) self.assertEqual(np_val.shape, gather_t.get_shape()) @@ -68,7 +69,7 @@ class GatherTest(test.TestCase, parameterized.TestCase): gather_t = array_ops.batch_gather(params, indices_tf) expected_result = np.array([[3], [15]]) np_val = self._buildParams(expected_result, dtype) - gather_val = gather_t.eval() + gather_val = self.evaluate(gather_t) self.assertAllEqual(np_val, gather_val) self.assertEqual(np_val.shape, gather_t.get_shape()) @@ -81,12 +82,13 @@ class GatherTest(test.TestCase, parameterized.TestCase): params = constant_op.constant(params_np) indices_tf = constant_op.constant(indices) gather_t = array_ops.batch_gather(params, indices_tf) - gather_val = gather_t.eval() + gather_val = self.evaluate(gather_t) expected_result = np.array([[[2, 0], [7, 5]], [[10, 8], [11, 15]]]) np_val = self._buildParams(expected_result, dtype) self.assertAllEqual(np_val, gather_val) self.assertEqual(np_val.shape, gather_t.get_shape()) + @test_util.run_deprecated_v1 def testString(self): params = np.array([[b"asdf", b"zxcv"], [b"qwer", b"uiop"]]) with self.cached_session(): @@ -94,6 +96,7 @@ class GatherTest(test.TestCase, parameterized.TestCase): self.assertAllEqual([[b"qwer", b"uiop"]], array_ops.batch_gather(params, indices_tf).eval()) + @test_util.run_deprecated_v1 def testUnknownIndices(self): params = constant_op.constant([[0, 1, 2]]) indices = array_ops.placeholder(dtypes.int32, shape=[None, None]) @@ -106,6 +109,7 @@ class GatherTest(test.TestCase, parameterized.TestCase): with self.assertRaisesOpError(r"indices\[0\] = 7 is not in \[0, 2\)"): array_ops.batch_gather(params, [7]).eval() + @test_util.run_deprecated_v1 def testEmptySlices(self): with self.session(use_gpu=True): for dtype in _TEST_TYPES: diff --git a/tensorflow/python/kernel_tests/batch_matmul_op_test.py b/tensorflow/python/kernel_tests/batch_matmul_op_test.py index 8f6c089b42..a0ad8151b2 100644 --- a/tensorflow/python/kernel_tests/batch_matmul_op_test.py +++ b/tensorflow/python/kernel_tests/batch_matmul_op_test.py @@ -86,7 +86,7 @@ class BatchMatmulOpTest(test.TestCase): with self.cached_session(use_gpu=is_floating) as sess: if static_shape: z0 = math_ops.matmul(x, y, adjoint_a=adjoint_a, adjoint_b=adjoint_b) - z0_val = z0.eval() + z0_val = self.evaluate(z0) else: x_ph = array_ops.placeholder(x.dtype) y_ph = array_ops.placeholder(y.dtype) diff --git a/tensorflow/python/kernel_tests/batch_scatter_ops_test.py b/tensorflow/python/kernel_tests/batch_scatter_ops_test.py index 742a204883..eefcdc508f 100644 --- a/tensorflow/python/kernel_tests/batch_scatter_ops_test.py +++ b/tensorflow/python/kernel_tests/batch_scatter_ops_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import state_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test @@ -73,6 +74,7 @@ class ScatterTest(test.TestCase): tf_scatter(ref, indices, updates).eval() self.assertAllClose(ref.eval(), new) + @test_util.run_deprecated_v1 def testVariableRankUpdate(self): vtypes = [np.float32, np.float64] for vtype in vtypes: @@ -80,6 +82,7 @@ class ScatterTest(test.TestCase): self._VariableRankTest( state_ops.batch_scatter_update, vtype, itype) + @test_util.run_deprecated_v1 def testBooleanScatterUpdate(self): with self.session(use_gpu=False) as session: var = variables.Variable([True, False]) @@ -91,8 +94,9 @@ class ScatterTest(test.TestCase): session.run([update0, update1]) - self.assertAllEqual([False, True], var.eval()) + self.assertAllEqual([False, True], self.evaluate(var)) + @test_util.run_deprecated_v1 def testScatterOutOfRange(self): params = np.array([1, 2, 3, 4, 5, 6]).astype(np.float32) updates = np.array([-3, -4, -5]).astype(np.float32) diff --git a/tensorflow/python/kernel_tests/batchtospace_op_test.py b/tensorflow/python/kernel_tests/batchtospace_op_test.py index 03f3f64353..c422df8806 100644 --- a/tensorflow/python/kernel_tests/batchtospace_op_test.py +++ b/tensorflow/python/kernel_tests/batchtospace_op_test.py @@ -27,6 +27,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_array_ops from tensorflow.python.ops import gradient_checker @@ -50,6 +51,7 @@ class CppOpImpl(object): class BatchToSpaceDepthToSpace(test.TestCase, PythonOpImpl): # Verifies that: batch_to_space(x) = transpose(depth_to_space(transpose(x))) + @test_util.run_deprecated_v1 def testDepthToSpaceTranspose(self): x = np.arange(20 * 5 * 8 * 7, dtype=np.float32).reshape([20, 5, 8, 7]) block_size = 2 @@ -70,6 +72,7 @@ class BatchToSpaceDepthToSpaceCpp(BatchToSpaceDepthToSpace, CppOpImpl): class BatchToSpaceErrorHandlingTest(test.TestCase, PythonOpImpl): + @test_util.run_deprecated_v1 def testInputWrongDimMissingBatch(self): # The input is missing the first dimension ("batch") x_np = [[[1], [2]], [[3], [4]]] @@ -78,6 +81,7 @@ class BatchToSpaceErrorHandlingTest(test.TestCase, PythonOpImpl): with self.assertRaises(ValueError): _ = self.batch_to_space(x_np, crops, block_size) + @test_util.run_deprecated_v1 def testBlockSize0(self): # The block size is 0. x_np = [[[[1], [2]], [[3], [4]]]] @@ -87,6 +91,7 @@ class BatchToSpaceErrorHandlingTest(test.TestCase, PythonOpImpl): out_tf = self.batch_to_space(x_np, crops, block_size) out_tf.eval() + @test_util.run_deprecated_v1 def testBlockSizeOne(self): # The block size is 1. The block size needs to be > 1. x_np = [[[[1], [2]], [[3], [4]]]] @@ -96,6 +101,7 @@ class BatchToSpaceErrorHandlingTest(test.TestCase, PythonOpImpl): out_tf = self.batch_to_space(x_np, crops, block_size) out_tf.eval() + @test_util.run_deprecated_v1 def testBlockSizeLarger(self): # The block size is too large for this input. x_np = [[[[1], [2]], [[3], [4]]]] @@ -105,6 +111,7 @@ class BatchToSpaceErrorHandlingTest(test.TestCase, PythonOpImpl): out_tf = self.batch_to_space(x_np, crops, block_size) out_tf.eval() + @test_util.run_deprecated_v1 def testBlockSizeSquaredNotDivisibleBatch(self): # The block size squared does not divide the batch. x_np = [[[[1], [2], [3]], [[3], [4], [7]]]] @@ -113,6 +120,7 @@ class BatchToSpaceErrorHandlingTest(test.TestCase, PythonOpImpl): with self.assertRaises(ValueError): _ = self.batch_to_space(x_np, crops, block_size) + @test_util.run_deprecated_v1 def testUnknownShape(self): t = self.batch_to_space( array_ops.placeholder(dtypes.float32), @@ -160,28 +168,35 @@ class BatchToSpaceNDErrorHandlingTest(test.TestCase): self._testStaticShape(input_shape, block_shape, paddings, error) self._testDynamicShape(input_shape, block_shape, paddings) + @test_util.run_deprecated_v1 def testInputWrongDimMissingBatch(self): self._testShape([2, 2], [2, 2], [[0, 0], [0, 0]], ValueError) self._testShape([2, 2, 3], [2, 2, 3], [[0, 0], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testBlockSize0(self): # The block size is 0. self._testShape([1, 2, 2, 1], [0, 1], [[0, 0], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testBlockSizeNegative(self): self._testShape([1, 2, 2, 1], [-1, 1], [[0, 0], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testNegativePadding(self): self._testShape([1, 2, 2], [1, 1], [[0, -1], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testCropTooLarge(self): # The amount to crop exceeds the padded size. self._testShape([1 * 2 * 2, 2, 3, 1], [2, 2], [[3, 2], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testBlockSizeSquaredNotDivisibleBatch(self): # The batch dimension is not divisible by the product of the block_shape. self._testShape([3, 1, 1, 1], [2, 3], [[0, 0], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testUnknownShape(self): # Verify that input shape and paddings shape can be unknown. _ = array_ops.batch_to_space_nd( @@ -263,18 +278,21 @@ class BatchToSpaceGradientTest(test.TestCase, PythonOpImpl): # Don't use very large numbers as dimensions here as the result is tensor # with cartesian product of the dimensions. + @test_util.run_deprecated_v1 def testSmall(self): block_size = 2 crop_beg = 0 crop_end = 0 self._compare(1, 2, 3, 5, block_size, crop_beg, crop_end) + @test_util.run_deprecated_v1 def testSmall2(self): block_size = 2 crop_beg = 0 crop_end = 0 self._compare(2, 4, 3, 2, block_size, crop_beg, crop_end) + @test_util.run_deprecated_v1 def testSmallCrop1x1(self): block_size = 2 crop_beg = 1 @@ -316,14 +334,17 @@ class BatchToSpaceNDGradientTest(test.TestCase): # Don't use very large numbers as dimensions here as the result is tensor # with cartesian product of the dimensions. + @test_util.run_deprecated_v1 def testSmall(self): for dtype in [dtypes.int64, dtypes.int32]: self._compare([1, 2, 3, 5], [2, 2], [[0, 0], [0, 0]], dtype) + @test_util.run_deprecated_v1 def testSmall2(self): for dtype in [dtypes.int64, dtypes.int32]: self._compare([2, 4, 3, 2], [2, 2], [[0, 0], [0, 0]], dtype) + @test_util.run_deprecated_v1 def testSmallCrop1x1(self): for dtype in [dtypes.int64, dtypes.int32]: self._compare([1, 2, 3, 5], [2, 2], [[1, 1], [1, 1]], dtype) diff --git a/tensorflow/python/kernel_tests/bcast_ops_test.py b/tensorflow/python/kernel_tests/bcast_ops_test.py index 3ec820aead..ae00955ac2 100644 --- a/tensorflow/python/kernel_tests/bcast_ops_test.py +++ b/tensorflow/python/kernel_tests/bcast_ops_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops.gen_array_ops import broadcast_args from tensorflow.python.ops.gen_array_ops import broadcast_gradient_args from tensorflow.python.platform import test @@ -35,6 +36,7 @@ class BcastOpsTest(test.TestCase): with self.cached_session() as sess: return sess.run(broadcast_gradient_args(xs, ys)) + @test_util.run_deprecated_v1 def testBasic(self): r = self._GetBroadcastShape([2, 3, 5], [1]) self.assertAllEqual(r, [2, 3, 5]) @@ -66,6 +68,7 @@ class BcastOpsTest(test.TestCase): r = self._GetBroadcastShape([3, 1], [2, 1, 5]) self.assertAllEqual(r, [2, 3, 5]) + @test_util.run_deprecated_v1 def testBasicGradient(self): r0, r1 = self._GetGradientArgs([2, 3, 5], [1]) self.assertAllEqual(r0, []) @@ -107,6 +110,7 @@ class BcastOpsTest(test.TestCase): self.assertAllEqual(r0, [0, 2]) self.assertAllEqual(r1, [1]) + @test_util.run_deprecated_v1 def testZeroDims(self): r = self._GetBroadcastShape([2, 0, 3, 0, 5], [3, 0, 5]) self.assertAllEqual(r, [2, 0, 3, 0, 5]) @@ -120,6 +124,7 @@ class BcastOpsTest(test.TestCase): r = self._GetBroadcastShape([3, 1, 5], [2, 0, 3, 0, 5]) self.assertAllEqual(r, [2, 0, 3, 0, 5]) + @test_util.run_deprecated_v1 def testZeroDimsGradient(self): r0, r1 = self._GetGradientArgs([2, 0, 3, 0, 5], [3, 0, 5]) self.assertAllEqual(r0, []) @@ -137,6 +142,7 @@ class BcastOpsTest(test.TestCase): self.assertAllEqual(r0, [0, 1, 3]) self.assertAllEqual(r1, []) + @test_util.run_deprecated_v1 def testDataTypes(self): for dtype in [dtypes.int32, dtypes.int64]: r = self._GetBroadcastShape( diff --git a/tensorflow/python/kernel_tests/benchmark_test.py b/tensorflow/python/kernel_tests/benchmark_test.py index 5777a5d097..bffa5e6e8f 100644 --- a/tensorflow/python/kernel_tests/benchmark_test.py +++ b/tensorflow/python/kernel_tests/benchmark_test.py @@ -21,9 +21,12 @@ import json import os import random +import numpy as np + from tensorflow.core.util import test_log_pb2 from tensorflow.python.client import session -from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.ops import array_ops from tensorflow.python.platform import benchmark from tensorflow.python.platform import gfile from tensorflow.python.platform import test @@ -64,11 +67,17 @@ class TestReportingBenchmark(test.Benchmark): "other_key": "string"}) def benchmark_times_an_op(self): + input_size = 5 with session.Session(config=benchmark.benchmark_config()) as sess: - a = constant_op.constant(0.0) + a = array_ops.placeholder(dtype=dtypes.float32, shape=(input_size)) a_plus_a = a + a return self.run_op_benchmark( - sess, a_plus_a, min_iters=1000, store_trace=True, name="op_benchmark") + sess, + a_plus_a, + feed_dict={a: np.arange(input_size)}, + min_iters=1000, + store_trace=True, + name="op_benchmark") class BenchmarkTest(test.TestCase): diff --git a/tensorflow/python/kernel_tests/betainc_op_test.py b/tensorflow/python/kernel_tests/betainc_op_test.py index 92d21462d5..9dc34a6062 100644 --- a/tensorflow/python/kernel_tests/betainc_op_test.py +++ b/tensorflow/python/kernel_tests/betainc_op_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl @@ -48,7 +49,7 @@ class BetaincTest(test.TestCase): tf_x_s = constant_op.constant(x_s, dtype=dtype) tf_out_t = math_ops.betainc(tf_a_s, tf_b_s, tf_x_s) with self.cached_session(): - tf_out = tf_out_t.eval() + tf_out = self.evaluate(tf_out_t) scipy_out = special.betainc(a_s, b_s, x_s).astype(np_dt) # the scipy version of betainc uses a double-only implementation. @@ -109,36 +110,42 @@ class BetaincTest(test.TestCase): except ImportError as e: tf_logging.warn("Cannot test special functions: %s" % str(e)) + @test_util.run_deprecated_v1 def testBetaIncFloat(self): a_s = np.abs(np.random.randn(10, 10) * 30) # in (0, infty) b_s = np.abs(np.random.randn(10, 10) * 30) # in (0, infty) x_s = np.random.rand(10, 10) # in (0, 1) self._testBetaInc(a_s, b_s, x_s, dtypes.float32) + @test_util.run_deprecated_v1 def testBetaIncDouble(self): a_s = np.abs(np.random.randn(10, 10) * 30) # in (0, infty) b_s = np.abs(np.random.randn(10, 10) * 30) # in (0, infty) x_s = np.random.rand(10, 10) # in (0, 1) self._testBetaInc(a_s, b_s, x_s, dtypes.float64) + @test_util.run_deprecated_v1 def testBetaIncDoubleVeryLargeValues(self): a_s = np.abs(np.random.randn(10, 10) * 1e15) # in (0, infty) b_s = np.abs(np.random.randn(10, 10) * 1e15) # in (0, infty) x_s = np.random.rand(10, 10) # in (0, 1) self._testBetaInc(a_s, b_s, x_s, dtypes.float64) + @test_util.run_deprecated_v1 def testBetaIncDoubleVerySmallValues(self): a_s = np.abs(np.random.randn(10, 10) * 1e-16) # in (0, infty) b_s = np.abs(np.random.randn(10, 10) * 1e-16) # in (0, infty) x_s = np.random.rand(10, 10) # in (0, 1) self._testBetaInc(a_s, b_s, x_s, dtypes.float64) + @test_util.run_deprecated_v1 def testBetaIncFloatVerySmallValues(self): a_s = np.abs(np.random.randn(10, 10) * 1e-8) # in (0, infty) b_s = np.abs(np.random.randn(10, 10) * 1e-8) # in (0, infty) x_s = np.random.rand(10, 10) # in (0, 1) self._testBetaInc(a_s, b_s, x_s, dtypes.float32) + @test_util.run_deprecated_v1 def testBetaIncFpropAndBpropAreNeverNAN(self): with self.cached_session() as sess: space = np.logspace(-8, 5).tolist() @@ -159,6 +166,7 @@ class BetaincTest(test.TestCase): self.assertAllEqual(np.zeros_like(grads_x).astype(np.bool), np.isnan(grads_x)) + @test_util.run_deprecated_v1 def testBetaIncGrads(self): err_tolerance = 1e-3 with self.cached_session(): diff --git a/tensorflow/python/kernel_tests/bias_op_test.py b/tensorflow/python/kernel_tests/bias_op_test.py index 749d6a791e..66f442dbdd 100644 --- a/tensorflow/python/kernel_tests/bias_op_test.py +++ b/tensorflow/python/kernel_tests/bias_op_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl @@ -89,10 +90,12 @@ class BiasAddTest(test.TestCase): self._testBiasNCHW(np_inputs, np_bias, use_gpu=True) + @test_util.run_deprecated_v1 def testInputDims(self): with self.assertRaises(ValueError): nn_ops.bias_add([1, 2], [1]) + @test_util.run_deprecated_v1 def testBiasVec(self): with self.assertRaises(ValueError): nn_ops.bias_add( @@ -101,6 +104,7 @@ class BiasAddTest(test.TestCase): array_ops.reshape( [1, 2], shape=[1, 2])) + @test_util.run_deprecated_v1 def testBiasInputsMatch(self): with self.assertRaises(ValueError): nn_ops.bias_add( @@ -109,23 +113,27 @@ class BiasAddTest(test.TestCase): array_ops.reshape( [1], shape=[1])) + @test_util.run_deprecated_v1 def testIntTypes(self): for t in [np.int8, np.int16, np.int32, np.int64]: self._testAll( np.array([[10, 20, 30], [40, 50, 60]]).astype(t), np.array([1, 2, 3]).astype(t)) + @test_util.run_deprecated_v1 def testFloatTypes(self): for t in [np.float16, np.float32, np.float64]: self._testAll( np.random.rand(4, 3, 3).astype(t), np.random.rand(3).astype(t)) + @test_util.run_deprecated_v1 def test4DFloatTypes(self): for t in [np.float16, np.float32, np.float64]: self._testAll( np.random.rand(4, 3, 2, 3).astype(t), np.random.rand(3).astype(t)) + @test_util.run_deprecated_v1 def test5DFloatTypes(self): for t in [np.float16, np.float32, np.float64]: self._testAll( @@ -187,6 +195,7 @@ class BiasAddTest(test.TestCase): self.assertAllClose(bias_jacob_t, bias_jacob_n, threshold, threshold) self.assertAllClose(grad_jacob_t, grad_jacob_n, threshold, threshold) + @test_util.run_deprecated_v1 def testGradientTensor(self): # TODO(yongtang): BiasAddGrad with NCHW only works 4D. Reenable once # all dimensions are supported. @@ -198,6 +207,7 @@ class BiasAddTest(test.TestCase): bias = np.array([1.3, 2.4], dtype=dtype.as_numpy_dtype) self._testGradient(np_input, bias, dtype, data_format, use_gpu) + @test_util.run_deprecated_v1 def testGradientTensor4D(self): # BiasAddGrad with NCHW support 4D so all are enabled. for (data_format, use_gpu) in [("NHWC", False), ("NHWC", True), @@ -209,11 +219,13 @@ class BiasAddTest(test.TestCase): bias = np.array([1.3, 2.4], dtype=dtype.as_numpy_dtype) self._testGradient(np_input, bias, dtype, data_format, use_gpu) + @test_util.run_deprecated_v1 def testEmpty(self): np.random.seed(7) for shape in (0, 0), (2, 0), (0, 2), (4, 3, 0), (4, 0, 3), (0, 4, 3): self._testAll(np.random.randn(*shape), np.random.randn(shape[-1])) + @test_util.run_deprecated_v1 def testEmptyGradient(self): # TODO(yongtang): BiasAddGrad with NCHW only works 4D. Reenable once # all dimensions are supported. diff --git a/tensorflow/python/kernel_tests/bincount_op_test.py b/tensorflow/python/kernel_tests/bincount_op_test.py index 49eb835847..d064d736cf 100644 --- a/tensorflow/python/kernel_tests/bincount_op_test.py +++ b/tensorflow/python/kernel_tests/bincount_op_test.py @@ -30,6 +30,7 @@ from tensorflow.python.platform import googletest class BincountTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def test_empty(self): with self.session(use_gpu=True): self.assertAllEqual( @@ -43,6 +44,7 @@ class BincountTest(test_util.TensorFlowTestCase): math_ops.bincount([], minlength=3, dtype=np.float64).eval().dtype, np.float64) + @test_util.run_deprecated_v1 def test_values(self): with self.session(use_gpu=True): self.assertAllEqual( @@ -58,12 +60,14 @@ class BincountTest(test_util.TensorFlowTestCase): self.assertAllEqual( math_ops.bincount(np.arange(10000)).eval(), np.ones(10000)) + @test_util.run_deprecated_v1 def test_maxlength(self): with self.session(use_gpu=True): self.assertAllEqual(math_ops.bincount([5], maxlength=3).eval(), [0, 0, 0]) self.assertAllEqual(math_ops.bincount([1], maxlength=3).eval(), [0, 1]) self.assertAllEqual(math_ops.bincount([], maxlength=3).eval(), []) + @test_util.run_deprecated_v1 def test_random_with_weights(self): num_samples = 10000 with self.session(use_gpu=True): @@ -77,6 +81,7 @@ class BincountTest(test_util.TensorFlowTestCase): self.assertAllClose( math_ops.bincount(arr, weights).eval(), np.bincount(arr, weights)) + @test_util.run_deprecated_v1 def test_random_without_weights(self): num_samples = 10000 with self.session(use_gpu=True): @@ -87,6 +92,7 @@ class BincountTest(test_util.TensorFlowTestCase): self.assertAllClose( math_ops.bincount(arr, None).eval(), np.bincount(arr, weights)) + @test_util.run_deprecated_v1 def test_zero_weights(self): with self.session(use_gpu=True): self.assertAllEqual( @@ -99,6 +105,7 @@ class BincountTest(test_util.TensorFlowTestCase): with self.assertRaises(errors.InvalidArgumentError): math_ops.bincount([1, 2, 3, -1, 6, 8]).eval() + @test_util.run_deprecated_v1 def test_shape_function(self): # size must be scalar. with self.assertRaisesRegexp( diff --git a/tensorflow/python/kernel_tests/bitcast_op_test.py b/tensorflow/python/kernel_tests/bitcast_op_test.py index 79e0f36d24..b4f9a21a89 100644 --- a/tensorflow/python/kernel_tests/bitcast_op_test.py +++ b/tensorflow/python/kernel_tests/bitcast_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test @@ -28,9 +29,9 @@ from tensorflow.python.platform import test class BitcastTest(test.TestCase): def _testBitcast(self, x, datatype, shape): - with self.session(use_gpu=True): + with test_util.use_gpu(): tf_ans = array_ops.bitcast(x, datatype) - out = tf_ans.eval() + out = self.evaluate(tf_ans) buff_after = memoryview(out).tobytes() buff_before = memoryview(x).tobytes() self.assertEqual(buff_before, buff_after) @@ -59,6 +60,7 @@ class BitcastTest(test.TestCase): shape = [3, 4] self._testBitcast(x, dtypes.int64, shape) + @test_util.run_deprecated_v1 def testErrors(self): x = np.zeros([1, 1], np.int8) datatype = dtypes.int32 @@ -71,6 +73,7 @@ class BitcastTest(test.TestCase): shape = [4] self._testBitcast(x, datatype, shape) + @test_util.run_deprecated_v1 def testUnknown(self): x = array_ops.placeholder(dtypes.float32) datatype = dtypes.int8 diff --git a/tensorflow/python/kernel_tests/boosted_trees/prediction_ops_test.py b/tensorflow/python/kernel_tests/boosted_trees/prediction_ops_test.py index 7cdc67f83f..6b04e8abf4 100644 --- a/tensorflow/python/kernel_tests/boosted_trees/prediction_ops_test.py +++ b/tensorflow/python/kernel_tests/boosted_trees/prediction_ops_test.py @@ -28,6 +28,7 @@ from tensorflow.python.platform import googletest class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): """Tests prediction ops for training.""" + @test_util.run_deprecated_v1 def testCachedPredictionOnEmptyEnsemble(self): """Tests that prediction on a dummy ensemble does not fail.""" with self.cached_session() as session: @@ -61,6 +62,7 @@ class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): self.assertAllClose(cached_node_ids, new_node_ids) self.assertAllClose([[0], [0]], logits_updates) + @test_util.run_deprecated_v1 def testNoCachedPredictionButTreeExists(self): """Tests that predictions are updated once trees are added.""" with self.cached_session() as session: @@ -127,6 +129,7 @@ class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): self.assertAllClose([2, 1], new_node_ids) self.assertAllClose([[0.1 * 8.79], [0.1 * 1.14]], logits_updates) + @test_util.run_deprecated_v1 def testCachedPredictionIsCurrent(self): """Tests that prediction based on previous node in the tree works.""" with self.cached_session() as session: @@ -199,6 +202,7 @@ class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): self.assertAllClose(cached_node_ids, new_node_ids) self.assertAllClose([[0], [0]], logits_updates) + @test_util.run_deprecated_v1 def testCachedPredictionFromTheSameTree(self): """Tests that prediction based on previous node in the tree works.""" with self.cached_session() as session: @@ -313,6 +317,7 @@ class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): # 1.65 and -3.875, and then multiply them by 0.1 (lr) self.assertAllClose([[0.1 * 1.65], [0.1 * -3.875]], logits_updates) + @test_util.run_deprecated_v1 def testCachedPredictionFromPreviousTree(self): """Tests the predictions work when we have cache from previous trees.""" with self.cached_session() as session: @@ -445,6 +450,7 @@ class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): # change= 0.1(1.14+7.0-7.0) self.assertAllClose([[1], [0.114]], logits_updates) + @test_util.run_deprecated_v1 def testCategoricalSplits(self): """Tests the training prediction work for categorical splits.""" with self.cached_session() as session: @@ -517,6 +523,7 @@ class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): self.assertAllClose([3, 4, 2], new_node_ids) self.assertAllClose([[5.], [6.], [7.]], logits_updates) + @test_util.run_deprecated_v1 def testCachedPredictionFromTheSameTreeWithPostPrunedNodes(self): """Tests that prediction based on previous node in the tree works.""" with self.cached_session() as session: @@ -647,6 +654,7 @@ class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): self.assertAllClose([[0.01], [0.01], [0.0553], [0.0783], [0.01], [0.01]], logits_updates + cached_values) + @test_util.run_deprecated_v1 def testCachedPredictionFromThePreviousTreeWithPostPrunedNodes(self): """Tests that prediction based on previous node in the tree works.""" with self.cached_session() as session: @@ -792,6 +800,7 @@ class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): [root + 0.0783], [root + 0.01], [root + 0.01]], logits_updates + cached_values) + @test_util.run_deprecated_v1 def testCachedPredictionTheWholeTreeWasPruned(self): """Tests that prediction based on previous node in the tree works.""" with self.cached_session() as session: @@ -864,6 +873,7 @@ class TrainingPredictionOpsTest(test_util.TensorFlowTestCase): class PredictionOpsTest(test_util.TensorFlowTestCase): """Tests prediction ops for inference.""" + @test_util.run_deprecated_v1 def testPredictionOnEmptyEnsemble(self): """Tests that prediction on a empty ensemble does not fail.""" with self.cached_session() as session: @@ -886,6 +896,7 @@ class PredictionOpsTest(test_util.TensorFlowTestCase): logits = session.run(predict_op) self.assertAllClose(expected_logits, logits) + @test_util.run_deprecated_v1 def testPredictionMultipleTree(self): """Tests the predictions work when we have multiple trees.""" with self.cached_session() as session: @@ -996,6 +1007,7 @@ class PredictionOpsTest(test_util.TensorFlowTestCase): logits = session.run(predict_op) self.assertAllClose(expected_logits, logits) + @test_util.run_deprecated_v1 def testCategoricalSplits(self): """Tests the predictions work for categorical splits.""" with self.cached_session() as session: @@ -1062,6 +1074,7 @@ class PredictionOpsTest(test_util.TensorFlowTestCase): class FeatureContribsOpsTest(test_util.TensorFlowTestCase): """Tests feature contribs ops for model understanding.""" + @test_util.run_deprecated_v1 def testContribsForOnlyABiasNode(self): """Tests case when, after training, only left with a bias node. @@ -1122,6 +1135,7 @@ class FeatureContribsOpsTest(test_util.TensorFlowTestCase): self.assertAllClose(feature_ids, expected_feature_ids) self.assertAllClose(logits_paths, expected_logits_paths) + @test_util.run_deprecated_v1 def testContribsMultipleTreeWhenFirstTreeIsABiasNode(self): """Tests case when, after training, first tree contains only a bias node.""" with self.cached_session() as session: @@ -1219,6 +1233,7 @@ class FeatureContribsOpsTest(test_util.TensorFlowTestCase): self.assertAllClose(feature_ids, expected_feature_ids) self.assertAllClose(logits_paths, expected_logits_paths) + @test_util.run_deprecated_v1 def testContribsMultipleTree(self): """Tests that the contribs work when we have multiple trees.""" with self.cached_session() as session: diff --git a/tensorflow/python/kernel_tests/boosted_trees/quantile_ops_test.py b/tensorflow/python/kernel_tests/boosted_trees/quantile_ops_test.py index 12afb6a2ad..390672febe 100644 --- a/tensorflow/python/kernel_tests/boosted_trees/quantile_ops_test.py +++ b/tensorflow/python/kernel_tests/boosted_trees/quantile_ops_test.py @@ -82,6 +82,7 @@ class QuantileOpsTest(test_util.TensorFlowTestCase): self.max_elements = 1 << 16 self.num_quantiles = constant_op.constant(3, dtype=dtypes.int64) + @test_util.run_deprecated_v1 def testBasicQuantileBucketsSingleResource(self): with self.cached_session() as sess: quantile_accumulator_handle = self.create_resource("floats", self.eps, @@ -98,14 +99,15 @@ class QuantileOpsTest(test_util.TensorFlowTestCase): quantile_accumulator_handle, num_features=2) quantiles = boosted_trees_ops.boosted_trees_bucketize( [self._feature_0, self._feature_1], buckets) - sess.run(summary_op) - sess.run(flush_op) + self.evaluate(summary_op) + self.evaluate(flush_op) self.assertAllClose(self._feature_0_boundaries, buckets[0].eval()) self.assertAllClose(self._feature_1_boundaries, buckets[1].eval()) self.assertAllClose(self._feature_0_quantiles, quantiles[0].eval()) self.assertAllClose(self._feature_1_quantiles, quantiles[1].eval()) + @test_util.run_deprecated_v1 def testBasicQuantileBucketsMultipleResources(self): with self.cached_session() as sess: quantile_accumulator_handle_0 = self.create_resource("float_0", self.eps, @@ -132,14 +134,15 @@ class QuantileOpsTest(test_util.TensorFlowTestCase): quantile_accumulator_handle_1, num_features=1) quantiles = boosted_trees_ops.boosted_trees_bucketize( [self._feature_0, self._feature_1], bucket_0 + bucket_1) - sess.run([summary_op_0, summary_op_1]) - sess.run([flush_op_0, flush_op_1]) + self.evaluate([summary_op_0, summary_op_1]) + self.evaluate([flush_op_0, flush_op_1]) self.assertAllClose(self._feature_0_boundaries, bucket_0[0].eval()) self.assertAllClose(self._feature_1_boundaries, bucket_1[0].eval()) self.assertAllClose(self._feature_0_quantiles, quantiles[0].eval()) self.assertAllClose(self._feature_1_quantiles, quantiles[1].eval()) + @test_util.run_deprecated_v1 def testSaveRestoreAfterFlush(self): save_dir = os.path.join(self.get_temp_dir(), "save_restore") save_path = os.path.join(tempfile.mkdtemp(prefix=save_dir), "hash") @@ -158,7 +161,7 @@ class QuantileOpsTest(test_util.TensorFlowTestCase): self._example_weights) with ops.control_dependencies([summaries]): flush = accumulator.flush() - sess.run(flush) + self.evaluate(flush) self.assertAllClose(self._feature_0_boundaries, buckets[0].eval()) self.assertAllClose(self._feature_1_boundaries, buckets[1].eval()) save.save(sess, save_path) @@ -172,6 +175,7 @@ class QuantileOpsTest(test_util.TensorFlowTestCase): self.assertAllClose(self._feature_0_boundaries, buckets[0].eval()) self.assertAllClose(self._feature_1_boundaries, buckets[1].eval()) + @test_util.run_deprecated_v1 def testSaveRestoreBeforeFlush(self): save_dir = os.path.join(self.get_temp_dir(), "save_restore") save_path = os.path.join(tempfile.mkdtemp(prefix=save_dir), "hash") @@ -185,12 +189,12 @@ class QuantileOpsTest(test_util.TensorFlowTestCase): summaries = accumulator.add_summaries([self._feature_0, self._feature_1], self._example_weights) - sess.run(summaries) + self.evaluate(summaries) buckets = accumulator.get_bucket_boundaries() self.assertAllClose([], buckets[0].eval()) self.assertAllClose([], buckets[1].eval()) save.save(sess, save_path) - sess.run(accumulator.flush()) + self.evaluate(accumulator.flush()) self.assertAllClose(self._feature_0_boundaries, buckets[0].eval()) self.assertAllClose(self._feature_1_boundaries, buckets[1].eval()) diff --git a/tensorflow/python/kernel_tests/boosted_trees/resource_ops_test.py b/tensorflow/python/kernel_tests/boosted_trees/resource_ops_test.py index 65bb9ab55f..0a34277bbd 100644 --- a/tensorflow/python/kernel_tests/boosted_trees/resource_ops_test.py +++ b/tensorflow/python/kernel_tests/boosted_trees/resource_ops_test.py @@ -30,19 +30,21 @@ from tensorflow.python.platform import googletest class ResourceOpsTest(test_util.TensorFlowTestCase): """Tests resource_ops.""" + @test_util.run_deprecated_v1 def testCreate(self): with self.cached_session(): ensemble = boosted_trees_ops.TreeEnsemble('ensemble') resources.initialize_resources(resources.shared_resources()).run() stamp_token = ensemble.get_stamp_token() - self.assertEqual(0, stamp_token.eval()) + self.assertEqual(0, self.evaluate(stamp_token)) (_, num_trees, num_finalized_trees, num_attempted_layers, nodes_range) = ensemble.get_states() - self.assertEqual(0, num_trees.eval()) - self.assertEqual(0, num_finalized_trees.eval()) - self.assertEqual(0, num_attempted_layers.eval()) - self.assertAllEqual([0, 1], nodes_range.eval()) + self.assertEqual(0, self.evaluate(num_trees)) + self.assertEqual(0, self.evaluate(num_finalized_trees)) + self.assertEqual(0, self.evaluate(num_attempted_layers)) + self.assertAllEqual([0, 1], self.evaluate(nodes_range)) + @test_util.run_deprecated_v1 def testCreateWithProto(self): with self.cached_session(): ensemble_proto = boosted_trees_pb2.TreeEnsemble() @@ -154,12 +156,13 @@ class ResourceOpsTest(test_util.TensorFlowTestCase): resources.initialize_resources(resources.shared_resources()).run() (stamp_token, num_trees, num_finalized_trees, num_attempted_layers, nodes_range) = ensemble.get_states() - self.assertEqual(7, stamp_token.eval()) - self.assertEqual(2, num_trees.eval()) - self.assertEqual(1, num_finalized_trees.eval()) - self.assertEqual(6, num_attempted_layers.eval()) - self.assertAllEqual([16, 19], nodes_range.eval()) + self.assertEqual(7, self.evaluate(stamp_token)) + self.assertEqual(2, self.evaluate(num_trees)) + self.assertEqual(1, self.evaluate(num_finalized_trees)) + self.assertEqual(6, self.evaluate(num_attempted_layers)) + self.assertAllEqual([16, 19], self.evaluate(nodes_range)) + @test_util.run_deprecated_v1 def testSerializeDeserialize(self): with self.cached_session(): # Initialize. @@ -167,11 +170,11 @@ class ResourceOpsTest(test_util.TensorFlowTestCase): resources.initialize_resources(resources.shared_resources()).run() (stamp_token, num_trees, num_finalized_trees, num_attempted_layers, nodes_range) = ensemble.get_states() - self.assertEqual(5, stamp_token.eval()) - self.assertEqual(0, num_trees.eval()) - self.assertEqual(0, num_finalized_trees.eval()) - self.assertEqual(0, num_attempted_layers.eval()) - self.assertAllEqual([0, 1], nodes_range.eval()) + self.assertEqual(5, self.evaluate(stamp_token)) + self.assertEqual(0, self.evaluate(num_trees)) + self.assertEqual(0, self.evaluate(num_finalized_trees)) + self.assertEqual(0, self.evaluate(num_attempted_layers)) + self.assertAllEqual([0, 1], self.evaluate(nodes_range)) # Deserialize. ensemble_proto = boosted_trees_pb2.TreeEnsemble() @@ -219,18 +222,18 @@ class ResourceOpsTest(test_util.TensorFlowTestCase): ]): (stamp_token, num_trees, num_finalized_trees, num_attempted_layers, nodes_range) = ensemble.get_states() - self.assertEqual(3, stamp_token.eval()) - self.assertEqual(1, num_trees.eval()) + self.assertEqual(3, self.evaluate(stamp_token)) + self.assertEqual(1, self.evaluate(num_trees)) # This reads from metadata, not really counting the layers. - self.assertEqual(5, num_attempted_layers.eval()) - self.assertEqual(0, num_finalized_trees.eval()) - self.assertAllEqual([3, 7], nodes_range.eval()) + self.assertEqual(5, self.evaluate(num_attempted_layers)) + self.assertEqual(0, self.evaluate(num_finalized_trees)) + self.assertAllEqual([3, 7], self.evaluate(nodes_range)) # Serialize. new_ensemble_proto = boosted_trees_pb2.TreeEnsemble() new_stamp_token, new_serialized = ensemble.serialize() - self.assertEqual(3, new_stamp_token.eval()) + self.assertEqual(3, self.evaluate(new_stamp_token)) new_ensemble_proto.ParseFromString(new_serialized.eval()) self.assertProtoEquals(ensemble_proto, new_ensemble_proto) diff --git a/tensorflow/python/kernel_tests/boosted_trees/stats_ops_test.py b/tensorflow/python/kernel_tests/boosted_trees/stats_ops_test.py index 09e9cfa3af..e2e23486b5 100644 --- a/tensorflow/python/kernel_tests/boosted_trees/stats_ops_test.py +++ b/tensorflow/python/kernel_tests/boosted_trees/stats_ops_test.py @@ -65,16 +65,16 @@ class StatsOpsTest(test_util.TensorFlowTestCase): min_node_weight=0, max_splits=max_splits) - self.assertAllEqual([[1, 2], [1, 2]], sess.run(node_ids_list)) + self.assertAllEqual([[1, 2], [1, 2]], self.evaluate(node_ids_list)) self.assertAllClose([[0.004775, 0.41184], [0.02823, 0.41184]], - sess.run(gains_list)) - self.assertAllEqual([[1, 1], [1, 1]], sess.run(thresholds_list)) + self.evaluate(gains_list)) + self.assertAllEqual([[1, 1], [1, 1]], self.evaluate(thresholds_list)) # The left node contrib will be later added to the previous node value to # make the left node value, and the same for right node contrib. self.assertAllClose([[[-.416667], [.568966]], [[-.6], [-.75]]], - sess.run(left_node_contribs_list)) + self.evaluate(left_node_contribs_list)) self.assertAllClose([[[-.592593], [-.75]], [[-.076923], [.568966]]], - sess.run(right_node_contribs_list)) + self.evaluate(right_node_contribs_list)) def testCalculateBestGainsWithL2(self): """Testing Gain calculation with L2.""" @@ -113,16 +113,16 @@ class StatsOpsTest(test_util.TensorFlowTestCase): min_node_weight=0, max_splits=max_splits) - self.assertAllEqual([[1, 2], [1, 2]], sess.run(node_ids_list)) + self.assertAllEqual([[1, 2], [1, 2]], self.evaluate(node_ids_list)) self.assertAllClose([[0., 0.33931375], [0.01879096, 0.33931375]], - sess.run(gains_list)) - self.assertAllEqual([[0, 1], [1, 1]], sess.run(thresholds_list)) + self.evaluate(gains_list)) + self.assertAllEqual([[0, 1], [1, 1]], self.evaluate(thresholds_list)) # The left node contrib will be later added to the previous node value to # make the left node value, and the same for right node contrib. self.assertAllClose([[[0.], [.485294]], [[-.5], [-.6]]], - sess.run(left_node_contribs_list)) + self.evaluate(left_node_contribs_list)) self.assertAllClose([[[-.424658], [-.6]], [[-.043478], [.485294]]], - sess.run(right_node_contribs_list)) + self.evaluate(right_node_contribs_list)) def testCalculateBestGainsWithL1(self): """Testing Gain calculation with L1.""" @@ -162,18 +162,18 @@ class StatsOpsTest(test_util.TensorFlowTestCase): min_node_weight=0, max_splits=max_splits) - self.assertAllEqual([[0, 1], [1, 1]], sess.run(thresholds_list)) + self.assertAllEqual([[0, 1], [1, 1]], self.evaluate(thresholds_list)) - self.assertAllEqual([[1, 2], [1, 2]], sess.run(node_ids_list)) + self.assertAllEqual([[1, 2], [1, 2]], self.evaluate(node_ids_list)) self.assertAllClose([[[0.0], [0.3965517]], [[-0.4], [-0.5]]], - sess.run(left_node_contribs_list)) + self.evaluate(left_node_contribs_list)) self.assertAllClose([[[-0.3333333], [-0.5]], [[0.0], [0.396552]]], - sess.run(right_node_contribs_list)) + self.evaluate(right_node_contribs_list)) # Gain should also include an adjustment of the gradient by l1. self.assertAllClose([[0.0, 0.191207], [0.01, 0.191207]], - sess.run(gains_list)) + self.evaluate(gains_list)) def testCalculateBestGainsWithTreeComplexity(self): """Testing Gain calculation with L2.""" @@ -214,18 +214,18 @@ class StatsOpsTest(test_util.TensorFlowTestCase): min_node_weight=0, max_splits=max_splits) - self.assertAllEqual([[1, 2], [1, 2]], sess.run(node_ids_list)) + self.assertAllEqual([[1, 2], [1, 2]], self.evaluate(node_ids_list)) self.assertAllClose([[-3., -2.66068625], [-2.98120904, -2.66068625]], - sess.run(gains_list)) + self.evaluate(gains_list)) - self.assertAllEqual([[0, 1], [1, 1]], sess.run(thresholds_list)) + self.assertAllEqual([[0, 1], [1, 1]], self.evaluate(thresholds_list)) # The left node contrib will be later added to the previous node value to # make the left node value, and the same for right node contrib. self.assertAllClose([[[0.], [.485294]], [[-.5], [-.6]]], - sess.run(left_node_contribs_list)) + self.evaluate(left_node_contribs_list)) self.assertAllClose([[[-.424658], [-.6]], [[-.043478], [.485294]]], - sess.run(right_node_contribs_list)) + self.evaluate(right_node_contribs_list)) def testCalculateBestGainsWithMinNodeWeight(self): """Testing Gain calculation without any regularization.""" @@ -266,13 +266,13 @@ class StatsOpsTest(test_util.TensorFlowTestCase): # We can't split node 1 on feature 1 and node 2 on feature 2 because of # the min node weight. - self.assertAllEqual([[2], [1]], sess.run(node_ids_list)) - self.assertAllClose([[0.384314], [0.098013]], sess.run(gains_list)) - self.assertAllEqual([[1], [1]], sess.run(thresholds_list)) + self.assertAllEqual([[2], [1]], self.evaluate(node_ids_list)) + self.assertAllClose([[0.384314], [0.098013]], self.evaluate(gains_list)) + self.assertAllEqual([[1], [1]], self.evaluate(thresholds_list)) self.assertAllClose([[[0.4852941]], [[-.6]]], - sess.run(left_node_contribs_list)) + self.evaluate(left_node_contribs_list)) self.assertAllClose([[[-0.75]], [[-0.014925]]], - sess.run(right_node_contribs_list)) + self.evaluate(right_node_contribs_list)) def testCalculateBestGainsWithMinNodeWeightNoSplitOnFeturePossible(self): """Testing Gain calculation without any regularization.""" @@ -311,9 +311,9 @@ class StatsOpsTest(test_util.TensorFlowTestCase): max_splits=max_splits) # We can't split either of the nodes on the first feature - self.assertEqual(2, len(sess.run(node_ids_list))) - self.assertAllEqual([], sess.run(node_ids_list)[0]) - self.assertAllEqual([1], sess.run(node_ids_list)[1]) + self.assertEqual(2, len(self.evaluate(node_ids_list))) + self.assertAllEqual([], self.evaluate(node_ids_list)[0]) + self.assertAllEqual([1], self.evaluate(node_ids_list)[1]) # Now check when we can't split on any feature (node_ids_list, _, _, _, @@ -325,8 +325,9 @@ class StatsOpsTest(test_util.TensorFlowTestCase): tree_complexity=0.0, min_node_weight=10, max_splits=max_splits) - self.assertAllEqual([[], []], sess.run(node_ids_list)) + self.assertAllEqual([[], []], self.evaluate(node_ids_list)) + @test_util.run_deprecated_v1 def testMakeStatsSummarySimple(self): """Simple test for MakeStatsSummary.""" with self.cached_session(): @@ -359,7 +360,7 @@ class StatsOpsTest(test_util.TensorFlowTestCase): [[0., 0.], [.15, .36], [.06, .07], [.1, .2]], # node 1 [[-.33, .58], [0., 0.], [.3, .4], [0., 0.]], # node 2 ]], - result.eval()) + self.evaluate(result)) def testMakeStatsSummaryMultipleFeatures(self): """Tests that MakeStatsSummary works for multiple features.""" @@ -389,7 +390,7 @@ class StatsOpsTest(test_util.TensorFlowTestCase): [[.3, .4], [0., 0.], [-.4, .5], [.07, .08]], # node 2 ], # feature 1 ], - result.eval()) + self.evaluate(result)) def _verify_precision(self, length): with self.cached_session(): @@ -408,7 +409,7 @@ class StatsOpsTest(test_util.TensorFlowTestCase): node_ids, gradients, hessians, [bucketized_features], max_splits, num_buckets) # shape=[max_splits, num_buckets, num_features, 2] - self.assertAllClose([[[[2., 0.2]]]], result.eval()) + self.assertAllClose([[[[2., 0.2]]]], self.evaluate(result)) def testMakeStatsSummaryNumericalPrecisionSmallBatch(self): """Tests numeric precision.""" diff --git a/tensorflow/python/kernel_tests/boosted_trees/training_ops_test.py b/tensorflow/python/kernel_tests/boosted_trees/training_ops_test.py index ea022820e4..afc0564fc5 100644 --- a/tensorflow/python/kernel_tests/boosted_trees/training_ops_test.py +++ b/tensorflow/python/kernel_tests/boosted_trees/training_ops_test.py @@ -30,6 +30,7 @@ from tensorflow.python.platform import googletest class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): """Tests for growing tree ensemble from split candidates.""" + @test_util.run_deprecated_v1 def testGrowWithEmptyEnsemble(self): """Test growing an empty ensemble.""" with self.cached_session() as session: @@ -139,6 +140,7 @@ class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): self.assertEqual(new_stamp, 1) self.assertProtoEquals(expected_result, tree_ensemble) + @test_util.run_deprecated_v1 def testBiasCenteringOnEmptyEnsemble(self): """Test growing with bias centering on an empty ensemble.""" with self.cached_session() as session: @@ -182,6 +184,7 @@ class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): self.assertEqual(new_stamp, 1) self.assertProtoEquals(expected_result, tree_ensemble) + @test_util.run_deprecated_v1 def testGrowExistingEnsembleTreeNotFinalized(self): """Test growing an existing ensemble with the last tree not finalized.""" with self.cached_session() as session: @@ -366,6 +369,7 @@ class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): self.assertEqual(new_stamp, 1) self.assertProtoEquals(expected_result, tree_ensemble) + @test_util.run_deprecated_v1 def testGrowExistingEnsembleTreeFinalized(self): """Test growing an existing ensemble with the last tree finalized.""" with self.cached_session() as session: @@ -515,6 +519,7 @@ class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): self.assertEqual(new_stamp, 1) self.assertProtoEquals(expected_result, tree_ensemble) + @test_util.run_deprecated_v1 def testPrePruning(self): """Test growing an existing ensemble with pre-pruning.""" with self.cached_session() as session: @@ -671,6 +676,7 @@ class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): self.assertEqual(new_stamp, 1) self.assertProtoEquals(expected_result, tree_ensemble) + @test_util.run_deprecated_v1 def testMetadataWhenCantSplitDueToEmptySplits(self): """Test that the metadata is updated even though we can't split.""" with self.cached_session() as session: @@ -782,6 +788,7 @@ class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): self.assertEqual(new_stamp, 1) self.assertProtoEquals(expected_result, tree_ensemble) + @test_util.run_deprecated_v1 def testMetadataWhenCantSplitDuePrePruning(self): """Test metadata is updated correctly when no split due to prepruning.""" with self.cached_session() as session: @@ -917,6 +924,7 @@ class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): self.assertEqual(new_stamp, 1) self.assertProtoEquals(expected_result, tree_ensemble) + @test_util.run_deprecated_v1 def testPostPruningOfSomeNodes(self): """Test growing an ensemble with post-pruning.""" with self.cached_session() as session: @@ -1251,6 +1259,7 @@ class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): self.assertEqual(new_stamp, 3) self.assertProtoEquals(expected_result, res_ensemble) + @test_util.run_deprecated_v1 def testPostPruningOfAllNodes(self): """Test growing an ensemble with post-pruning, with all nodes are pruned.""" with self.cached_session() as session: @@ -1434,6 +1443,7 @@ class UpdateTreeEnsembleOpTest(test_util.TensorFlowTestCase): } """, res_ensemble) + @test_util.run_deprecated_v1 def testPostPruningChangesNothing(self): """Test growing an ensemble with post-pruning with all gains >0.""" with self.cached_session() as session: diff --git a/tensorflow/python/kernel_tests/broadcast_to_ops_test.py b/tensorflow/python/kernel_tests/broadcast_to_ops_test.py index 233c166405..b9eb2391b4 100644 --- a/tensorflow/python/kernel_tests/broadcast_to_ops_test.py +++ b/tensorflow/python/kernel_tests/broadcast_to_ops_test.py @@ -29,6 +29,7 @@ from tensorflow.python.platform import test as test_lib class BroadcastToTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testBroadcastToBasic(self): for dtype in [np.uint8, np.uint16, np.int8, np.int16, np.int32, np.int64]: with self.session(use_gpu=True): @@ -37,6 +38,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): v_np = np.broadcast_to(x, [3, 3]) self.assertAllEqual(v_tf.eval(), v_np) + @test_util.run_deprecated_v1 def testBroadcastToString(self): with self.session(use_gpu=True): x = np.array([b"1", b"2", b"3"]) @@ -44,6 +46,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): v_np = np.broadcast_to(x, [3, 3]) self.assertAllEqual(v_tf.eval(), v_np) + @test_util.run_deprecated_v1 def testBroadcastToBool(self): with self.session(use_gpu=True): x = np.array([True, False, True], dtype=np.bool) @@ -51,6 +54,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): v_np = np.broadcast_to(x, [3, 3]) self.assertAllEqual(v_tf.eval(), v_np) + @test_util.run_deprecated_v1 def testBroadcastToShape(self): for input_dim in range(1, 6): for output_dim in range(input_dim, 6): @@ -62,6 +66,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): v_np = np.broadcast_to(x, output_shape) self.assertAllEqual(v_tf.eval(), v_np) + @test_util.run_deprecated_v1 def testBroadcastToScalar(self): with self.session(use_gpu=True): x = np.array(1, dtype=np.int32) @@ -69,6 +74,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): v_np = np.broadcast_to(x, [3, 3]) self.assertAllEqual(v_tf.eval(), v_np) + @test_util.run_deprecated_v1 def testBroadcastScalarToNonScalar(self): with self.session(use_gpu=True): x = np.array(1.0, dtype=np.float) @@ -76,6 +82,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): v_np = np.broadcast_to(x, [2, 3, 4]) self.assertAllEqual(v_tf.eval(), v_np) + @test_util.run_deprecated_v1 def testBroadcastToShapeTypeAndInference(self): for dtype in [dtypes.int32, dtypes.int64]: with self.cached_session(use_gpu=True): @@ -89,6 +96,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): # check shape inference when shape input is constant self.assertAllEqual(shape, v_np.shape) + @test_util.run_deprecated_v1 def testGradientForScalar(self): x = constant_op.constant(1, dtype=dtypes.float32) v = array_ops.broadcast_to(x, [2, 4, 3]) @@ -98,6 +106,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): out.get_shape()) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradientWithSameRank(self): x = constant_op.constant(np.reshape(np.arange(6), (2, 1, 3)), dtype=dtypes.float32) @@ -108,6 +117,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): out, out.get_shape()) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradientWithIncreasingRank(self): x = constant_op.constant([[1], [2]], dtype=dtypes.float32) @@ -118,6 +128,7 @@ class BroadcastToTest(test_util.TensorFlowTestCase): out, out.get_shape()) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradientWithBroadcastAllDimensions(self): x = constant_op.constant([[1, 2, 3], [4, 5, 6]], dtype=dtypes.float32) v = array_ops.broadcast_to(x, [5, 4, 6]) diff --git a/tensorflow/python/kernel_tests/bucketize_op_test.py b/tensorflow/python/kernel_tests/bucketize_op_test.py index 57413e6af5..95df694370 100644 --- a/tensorflow/python/kernel_tests/bucketize_op_test.py +++ b/tensorflow/python/kernel_tests/bucketize_op_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -32,7 +33,7 @@ class BucketizationOpTest(test.TestCase): boundaries=[0, 3, 8, 11]) expected_out = [0, 1, 1, 2, 2, 3, 3, 4, 4] with self.session(use_gpu=True) as sess: - self.assertAllEqual(expected_out, sess.run(op)) + self.assertAllEqual(expected_out, self.evaluate(op)) def testFloat(self): op = math_ops._bucketize( @@ -40,7 +41,7 @@ class BucketizationOpTest(test.TestCase): boundaries=[0., 3., 8., 11.]) expected_out = [0, 1, 1, 2, 2, 3, 3, 4, 4] with self.session(use_gpu=True) as sess: - self.assertAllEqual(expected_out, sess.run(op)) + self.assertAllEqual(expected_out, self.evaluate(op)) def test2DInput(self): op = math_ops._bucketize( @@ -48,15 +49,16 @@ class BucketizationOpTest(test.TestCase): boundaries=[0, 3, 8, 11]) expected_out = [[0, 1, 1, 2, 2], [3, 3, 4, 4, 1]] with self.session(use_gpu=True) as sess: - self.assertAllEqual(expected_out, sess.run(op)) + self.assertAllEqual(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def testInvalidBoundariesOrder(self): op = math_ops._bucketize( constant_op.constant([-5, 0]), boundaries=[0, 8, 3, 11]) with self.session(use_gpu=True) as sess: with self.assertRaisesRegexp( errors_impl.InvalidArgumentError, "Expected sorted boundaries"): - sess.run(op) + self.evaluate(op) def testBoundariesNotList(self): with self.assertRaisesRegexp( diff --git a/tensorflow/python/kernel_tests/candidate_sampler_ops_test.py b/tensorflow/python/kernel_tests/candidate_sampler_ops_test.py index b19077db56..fa6eb5c968 100644 --- a/tensorflow/python/kernel_tests/candidate_sampler_ops_test.py +++ b/tensorflow/python/kernel_tests/candidate_sampler_ops_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import candidate_sampling_ops from tensorflow.python.ops import math_ops @@ -37,6 +38,7 @@ class RangeSamplerOpsTest(test.TestCase): TRUE_LABELS = [[1, 2], [0, 4], [3, 3]] + @test_util.run_deprecated_v1 def testTrueCandidates(self): with self.cached_session() as sess: indices = constant_op.constant([0, 0, 1, 1, 2, 2]) @@ -55,7 +57,7 @@ class RangeSamplerOpsTest(test.TestCase): [[1, 2], [0, 4], [3, 3]], dtype=dtypes.int64) sampled_candidates, _, _ = candidate_sampling_ops.all_candidate_sampler( true_classes, self.NUM_TRUE, self.NUM_SAMPLED, True) - result = sampled_candidates.eval() + result = self.evaluate(sampled_candidates) expected_ids = [0, 1, 2, 3, 4] self.assertAllEqual(result, expected_ids) @@ -68,7 +70,7 @@ class RangeSamplerOpsTest(test.TestCase): _, true_expected_count, _ = candidate_sampling_ops.all_candidate_sampler( true_classes, self.NUM_TRUE, self.NUM_SAMPLED, True) true_log_expected_count = math_ops.log(true_expected_count) - result = true_log_expected_count.eval() + result = self.evaluate(true_log_expected_count) self.assertAllEqual(result, [[0.0] * self.NUM_TRUE] * self.BATCH_SIZE) self.assertEqual(true_expected_count.get_shape(), @@ -83,7 +85,7 @@ class RangeSamplerOpsTest(test.TestCase): _, _, sampled_expected_count = candidate_sampling_ops.all_candidate_sampler( # pylint: disable=line-too-long true_classes, self.NUM_TRUE, self.NUM_SAMPLED, True) sampled_log_expected_count = math_ops.log(sampled_expected_count) - result = sampled_log_expected_count.eval() + result = self.evaluate(sampled_log_expected_count) self.assertAllEqual(result, [0.0] * self.NUM_SAMPLED) self.assertEqual(sampled_expected_count.get_shape(), [self.NUM_SAMPLED]) @@ -97,7 +99,7 @@ class RangeSamplerOpsTest(test.TestCase): true_classes, self.NUM_TRUE, self.NUM_SAMPLED, True) accidental_hits = candidate_sampling_ops.compute_accidental_hits( true_classes, sampled_candidates, self.NUM_TRUE) - indices, ids, weights = sess.run(accidental_hits) + indices, ids, weights = self.evaluate(accidental_hits) self.assertEqual(1, accidental_hits[0].get_shape().ndims) self.assertEqual(1, accidental_hits[1].get_shape().ndims) @@ -106,6 +108,7 @@ class RangeSamplerOpsTest(test.TestCase): self.assertTrue(id_ in self.TRUE_LABELS[index]) self.assertLess(weight, -1.0e37) + @test_util.run_deprecated_v1 def testSeed(self): def draw(seed): @@ -114,7 +117,7 @@ class RangeSamplerOpsTest(test.TestCase): [[1, 2], [0, 4], [3, 3]], dtype=dtypes.int64) sampled, _, _ = candidate_sampling_ops.log_uniform_candidate_sampler( true_classes, self.NUM_TRUE, self.NUM_SAMPLED, True, 5, seed=seed) - return sampled.eval() + return self.evaluate(sampled) # Non-zero seed. Repeatable. for seed in [1, 12, 123, 1234]: diff --git a/tensorflow/python/kernel_tests/cast_op_test.py b/tensorflow/python/kernel_tests/cast_op_test.py index a5dff5df62..b3187e1637 100644 --- a/tensorflow/python/kernel_tests/cast_op_test.py +++ b/tensorflow/python/kernel_tests/cast_op_test.py @@ -25,6 +25,7 @@ import platform from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops @@ -90,10 +91,12 @@ class CastOpTest(test.TestCase): if x.dtype == np.float32 or x.dtype == np.float64: self._testTypes(x, use_gpu=True) + @test_util.run_deprecated_v1 def testBasic(self): self._testAll(np.arange(-10, 10).reshape(2, 10)) self._testAll(np.linspace(-10, 10, 17)) + @test_util.run_deprecated_v1 def testSmallValues(self): f4 = np.finfo(np.float32) f8 = np.finfo(np.float64) @@ -107,11 +110,12 @@ class CastOpTest(test.TestCase): a = np.random.uniform(-100, 100, 100).astype(np.float32) with self.cached_session(use_gpu=False): b = math_ops.cast(math_ops.cast(a, dtypes.bfloat16), dtypes.float32) - self.assertAllClose(a, b.eval(), rtol=1 / 128.) + self.assertAllClose(a, self.evaluate(b), rtol=1 / 128.) with self.cached_session(use_gpu=True): b = math_ops.cast(math_ops.cast(a, dtypes.bfloat16), dtypes.float32) - self.assertAllClose(a, b.eval(), rtol=1 / 128.) + self.assertAllClose(a, self.evaluate(b), rtol=1 / 128.) + @test_util.run_deprecated_v1 def testRandom(self): self._testAll(np.random.normal(0, 10, 210).reshape([2, 3, 5, 7])) self._testAll(np.random.normal(0, 1e6, 210).reshape([2, 3, 5, 7])) @@ -124,6 +128,7 @@ class CastOpTest(test.TestCase): self._cast( x, dst_dtype, use_gpu=use_gpu), dst_dtype(expected)) + @test_util.run_deprecated_v1 def testIntToFloatBoundary(self): i4 = np.iinfo(np.int32) i8 = np.iinfo(np.int64) @@ -138,6 +143,7 @@ class CastOpTest(test.TestCase): self._compare(i8.max, np.float64, i8.max, False) # NOTE: GPU does not support int32/int64 for casting. + @test_util.run_deprecated_v1 def testInfNan(self): i4 = np.iinfo(np.int32) i8 = np.iinfo(np.int64) @@ -181,14 +187,16 @@ class CastOpTest(test.TestCase): def testNotImplemented(self): self._OpError(np.arange(0, 10), dtypes.string, "Cast.*int64.*string.*") + @test_util.run_deprecated_v1 def testCastToTypeOfVariable(self): with self.cached_session() as sess: x = variables.Variable(5, dtype=dtypes.float32) y = variables.Variable(True, dtype=dtypes.bool) cast = math_ops.cast(y, x.dtype) variables.global_variables_initializer().run() - self.assertEqual(1.0, sess.run(cast)) + self.assertEqual(1.0, self.evaluate(cast)) + @test_util.run_deprecated_v1 def testGradients(self): t = [dtypes.float32, dtypes.float64, dtypes.complex64, dtypes.complex128] for src_t in t: @@ -203,6 +211,7 @@ class CastOpTest(test.TestCase): class SparseTensorCastTest(test.TestCase): + @test_util.run_deprecated_v1 def testCast(self): indices = constant_op.constant([[0], [1], [2]], dtypes.int64) values = constant_op.constant(np.array([1, 2, 3], np.int64)) @@ -229,7 +238,7 @@ class SaturateCastTest(test.TestCase): [lo, lo + 1, lo // 2, hi // 2, hi - 1, hi], dtype=in_type) y = math_ops.saturate_cast(x, dtype=out_type) self.assertEqual(y.dtype, out_type) - x, y = sess.run([x, y]) + x, y = self.evaluate([x, y]) correct = np.maximum(out_type.min, np.minimum(out_type.max, x)) self.assertAllEqual(correct, y) diff --git a/tensorflow/python/kernel_tests/check_ops_test.py b/tensorflow/python/kernel_tests/check_ops_test.py index 88f5cd6f22..95bac85027 100644 --- a/tensorflow/python/kernel_tests/check_ops_test.py +++ b/tensorflow/python/kernel_tests/check_ops_test.py @@ -25,6 +25,7 @@ from tensorflow.core.protobuf import config_pb2 from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.python.client import session from tensorflow.python.eager import context +from tensorflow.python.eager import def_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors @@ -39,6 +40,69 @@ from tensorflow.python.ops import random_ops from tensorflow.python.platform import test +class AssertV2Asserts(test.TestCase): + + def test_passes_when_it_should(self): + # This is a v2 test and need to run eagerly + with context.eager_mode(): + c1 = constant_op.constant(-1, name="minus_one", dtype=dtypes.int32) + c2 = constant_op.constant(2, name="two", dtype=dtypes.int32) + c3 = constant_op.constant([3., 3.], name="three", dtype=dtypes.float32) + c4 = constant_op.constant([3., 3.5], name="three_and_a_half", + dtype=dtypes.float32) + scalar = c1 + non_scalar = c3 + integer = c1 + non_integer = c3 + positive = c2 + negative = c1 + cases = [ + (check_ops.assert_equal_v2, (c1, c1), (c1, c2)), + (check_ops.assert_less_v2, (c1, c2), (c1, c1)), + (check_ops.assert_near_v2, (c3, c3), (c3, c4)), + (check_ops.assert_greater_v2, (c2, c1), (c1, c1)), + (check_ops.assert_negative_v2, (negative,), (positive,)), + (check_ops.assert_positive_v2, (positive,), (negative,)), + (check_ops.assert_less_equal_v2, (c1, c1), (c2, c1)), + (check_ops.assert_none_equal_v2, (c1, c2), (c3, c4)), + (check_ops.assert_non_negative_v2, (positive,), (negative,)), + (check_ops.assert_non_positive_v2, (negative,), (positive,)), + (check_ops.assert_greater_equal_v2, (c1, c1), (c1, c2)), + (check_ops.assert_type_v2, (c1, dtypes.int32), (c1, dtypes.float32), + TypeError), + (check_ops.assert_integer_v2, (integer,), (non_integer,), + TypeError), + (check_ops.assert_scalar_v2, (scalar,), (non_scalar,), + ValueError), + (check_ops.assert_rank_v2, (c1, 0), (c3, 2), ValueError), + (check_ops.assert_rank_in_v2, (c1, [0, 1]), (c1, [1, 2]), + ValueError), + (check_ops.assert_rank_at_least_v2, (non_scalar, 1), (scalar, 1), + ValueError), + ] + + for case in cases: + fn = case[0] + passing_args = case[1] + failing_args = case[2] + error = errors.InvalidArgumentError if len(case) < 4 else case[3] + + print("Testing %s passing properly." % fn) + + fn(*passing_args) + + print("Testing %s failing properly." % fn) + + @def_function.function + def failing_fn(): + fn(*failing_args, message="fail") # pylint: disable=cell-var-from-loop + + with self.assertRaisesRegexp(error, "fail"): + failing_fn() + + del failing_fn + + class AssertProperIterableTest(test.TestCase): @test_util.run_in_graph_and_eager_modes @@ -109,6 +173,7 @@ class AssertEqualTest(test.TestCase): assert x is None @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_greater(self): # Static check static_small = constant_op.constant([1, 2], name="small") @@ -116,6 +181,7 @@ class AssertEqualTest(test.TestCase): with self.assertRaisesRegexp(errors.InvalidArgumentError, "fail"): check_ops.assert_equal(static_big, static_small, message="fail") + @test_util.run_deprecated_v1 def test_raises_when_greater_dynamic(self): with self.cached_session(): small = array_ops.placeholder(dtypes.int32, name="small") @@ -187,6 +253,7 @@ First 2 elements of y: summarize=2) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_less(self): # Static check static_small = constant_op.constant([3, 1], name="small") @@ -194,6 +261,7 @@ First 2 elements of y: with self.assertRaisesRegexp(errors.InvalidArgumentError, "fail"): check_ops.assert_equal(static_big, static_small, message="fail") + @test_util.run_deprecated_v1 def test_raises_when_less_dynamic(self): with self.cached_session(): small = array_ops.placeholder(dtypes.int32, name="small") @@ -253,6 +321,7 @@ class AssertNoneEqualTest(test.TestCase): self.evaluate(out) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_equal(self): small = constant_op.constant([3, 1], name="small") with self.assertRaisesOpError("x != y did not hold"): @@ -442,6 +511,7 @@ class AssertAllCloseTest(test.TestCase): class AssertLessTest(test.TestCase): @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_equal(self): small = constant_op.constant([1, 2], name="small") with self.assertRaisesOpError("failure message.*\n*.* x < y did not hold"): @@ -452,6 +522,7 @@ class AssertLessTest(test.TestCase): self.evaluate(out) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_greater(self): small = constant_op.constant([1, 2], name="small") big = constant_op.constant([3, 4], name="big") @@ -518,6 +589,7 @@ class AssertLessEqualTest(test.TestCase): self.evaluate(out) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_greater(self): small = constant_op.constant([1, 2], name="small") big = constant_op.constant([3, 4], name="big") @@ -573,6 +645,7 @@ class AssertLessEqualTest(test.TestCase): class AssertGreaterTest(test.TestCase): @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_equal(self): small = constant_op.constant([1, 2], name="small") with self.assertRaisesOpError("fail"): @@ -583,6 +656,7 @@ class AssertGreaterTest(test.TestCase): self.evaluate(out) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_less(self): small = constant_op.constant([1, 2], name="small") big = constant_op.constant([3, 4], name="big") @@ -642,6 +716,7 @@ class AssertGreaterEqualTest(test.TestCase): self.evaluate(out) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_less(self): small = constant_op.constant([1, 2], name="small") big = constant_op.constant([3, 4], name="big") @@ -706,6 +781,7 @@ class AssertNegativeTest(test.TestCase): self.evaluate(out) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_positive(self): doug = constant_op.constant([1, 2], name="doug") with self.assertRaisesOpError("fail"): @@ -716,6 +792,7 @@ class AssertNegativeTest(test.TestCase): self.evaluate(out) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_zero(self): claire = constant_op.constant([0], name="claire") with self.assertRaisesOpError("x < 0 did not hold"): @@ -738,6 +815,7 @@ class AssertNegativeTest(test.TestCase): class AssertPositiveTest(test.TestCase): @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_negative(self): freddie = constant_op.constant([-1, -2], name="freddie") with self.assertRaisesOpError("fail"): @@ -755,6 +833,7 @@ class AssertPositiveTest(test.TestCase): self.evaluate(out) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_zero(self): meechum = constant_op.constant([0], name="meechum") with self.assertRaisesOpError("x > 0 did not hold"): @@ -777,26 +856,31 @@ class AssertPositiveTest(test.TestCase): class EnsureShapeTest(test.TestCase): # Static shape inference + @test_util.run_deprecated_v1 def testStaticShape(self): placeholder = array_ops.placeholder(dtypes.int32) ensure_shape_op = check_ops.ensure_shape(placeholder, (3, 3, 3)) self.assertEqual(ensure_shape_op.get_shape(), (3, 3, 3)) + @test_util.run_deprecated_v1 def testStaticShape_MergesShapes(self): placeholder = array_ops.placeholder(dtypes.int32, shape=(None, None, 3)) ensure_shape_op = check_ops.ensure_shape(placeholder, (5, 4, None)) self.assertEqual(ensure_shape_op.get_shape(), (5, 4, 3)) + @test_util.run_deprecated_v1 def testStaticShape_RaisesErrorWhenRankIncompatible(self): placeholder = array_ops.placeholder(dtypes.int32, shape=(None, None, 3)) with self.assertRaises(ValueError): check_ops.ensure_shape(placeholder, (2, 3)) + @test_util.run_deprecated_v1 def testStaticShape_RaisesErrorWhenDimIncompatible(self): placeholder = array_ops.placeholder(dtypes.int32, shape=(None, None, 3)) with self.assertRaises(ValueError): check_ops.ensure_shape(placeholder, (2, 2, 4)) + @test_util.run_deprecated_v1 def testStaticShape_CanSetUnknownShape(self): placeholder = array_ops.placeholder(dtypes.int32) derived = placeholder / 3 @@ -804,6 +888,7 @@ class EnsureShapeTest(test.TestCase): self.assertEqual(ensure_shape_op.get_shape(), None) # Dynamic shape check + @test_util.run_deprecated_v1 def testEnsuresDynamicShape_RaisesError(self): placeholder = array_ops.placeholder(dtypes.int32) derived = math_ops.divide(placeholder, 3, name="MyDivide") @@ -816,6 +901,7 @@ class EnsureShapeTest(test.TestCase): r"expected shape \[3,3,3\]."): sess.run(derived, feed_dict={placeholder: feed_val}) + @test_util.run_deprecated_v1 def testEnsuresDynamicShape_RaisesErrorDimUnknown(self): placeholder = array_ops.placeholder(dtypes.int32) derived = placeholder / 3 @@ -828,6 +914,7 @@ class EnsureShapeTest(test.TestCase): r"expected shape \[\?,\?,3\]."): sess.run(derived, feed_dict={placeholder: feed_val}) + @test_util.run_deprecated_v1 def testEnsuresDynamicShape(self): placeholder = array_ops.placeholder(dtypes.int32) derived = placeholder / 3 @@ -836,6 +923,7 @@ class EnsureShapeTest(test.TestCase): with self.cached_session() as sess: sess.run(derived, feed_dict={placeholder: feed_val}) + @test_util.run_deprecated_v1 def testEnsuresDynamicShape_WithUnknownDims(self): placeholder = array_ops.placeholder(dtypes.int32) derived = placeholder / 3 @@ -844,6 +932,7 @@ class EnsureShapeTest(test.TestCase): with self.cached_session() as sess: sess.run(derived, feed_dict={placeholder: feed_val}) + @test_util.run_deprecated_v1 def testGradient(self): placeholder = array_ops.placeholder(dtypes.float32) derived = check_ops.ensure_shape(placeholder, (None, None)) @@ -939,6 +1028,7 @@ class AssertRankTest(test.TestCase): tensor, desired_rank, message="fail")]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_zero_tensor_raises_if_rank_too_small_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -957,6 +1047,7 @@ class AssertRankTest(test.TestCase): [check_ops.assert_rank(tensor, desired_rank)]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_zero_tensor_doesnt_raise_if_rank_just_right_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -974,6 +1065,7 @@ class AssertRankTest(test.TestCase): [check_ops.assert_rank(tensor, desired_rank)]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_one_tensor_raises_if_rank_too_large_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -991,6 +1083,7 @@ class AssertRankTest(test.TestCase): [check_ops.assert_rank(tensor, desired_rank)]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_one_tensor_doesnt_raise_if_rank_just_right_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1008,6 +1101,7 @@ class AssertRankTest(test.TestCase): [check_ops.assert_rank(tensor, desired_rank)]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_one_tensor_raises_if_rank_too_small_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1023,6 +1117,7 @@ class AssertRankTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "Rank must be a scalar"): check_ops.assert_rank(tensor, np.array([], dtype=np.int32)) + @test_util.run_deprecated_v1 def test_raises_if_rank_is_not_scalar_dynamic(self): with self.cached_session(): tensor = constant_op.constant( @@ -1040,6 +1135,7 @@ class AssertRankTest(test.TestCase): "must be of type "): check_ops.assert_rank(tensor, .5) + @test_util.run_deprecated_v1 def test_raises_if_rank_is_not_integer_dynamic(self): with self.cached_session(): tensor = constant_op.constant( @@ -1063,6 +1159,7 @@ class AssertRankInTest(test.TestCase): check_ops.assert_rank_in(tensor_rank0, (1, 2), message="fail")]): self.evaluate(array_ops.identity(tensor_rank0)) + @test_util.run_deprecated_v1 def test_rank_zero_tensor_raises_if_rank_mismatch_dynamic_rank(self): with self.cached_session(): tensor_rank0 = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1079,6 +1176,7 @@ class AssertRankInTest(test.TestCase): check_ops.assert_rank_in(tensor_rank0, desired_ranks)]): self.evaluate(array_ops.identity(tensor_rank0)) + @test_util.run_deprecated_v1 def test_rank_zero_tensor_doesnt_raise_if_rank_matches_dynamic_rank(self): with self.cached_session(): tensor_rank0 = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1095,6 +1193,7 @@ class AssertRankInTest(test.TestCase): check_ops.assert_rank_in(tensor_rank1, desired_ranks)]): self.evaluate(array_ops.identity(tensor_rank1)) + @test_util.run_deprecated_v1 def test_rank_one_tensor_doesnt_raise_if_rank_matches_dynamic_rank(self): with self.cached_session(): tensor_rank1 = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1113,6 +1212,7 @@ class AssertRankInTest(test.TestCase): check_ops.assert_rank_in(tensor_rank1, (0, 2))]): self.evaluate(array_ops.identity(tensor_rank1)) + @test_util.run_deprecated_v1 def test_rank_one_tensor_raises_if_rank_mismatches_dynamic_rank(self): with self.cached_session(): tensor_rank1 = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1132,6 +1232,7 @@ class AssertRankInTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "Rank must be a scalar"): check_ops.assert_rank_in(tensor, desired_ranks) + @test_util.run_deprecated_v1 def test_raises_if_rank_is_not_scalar_dynamic(self): with self.cached_session(): tensor = constant_op.constant( @@ -1154,6 +1255,7 @@ class AssertRankInTest(test.TestCase): "must be of type "): check_ops.assert_rank_in(tensor, (1, .5,)) + @test_util.run_deprecated_v1 def test_raises_if_rank_is_not_integer_dynamic(self): with self.cached_session(): tensor = constant_op.constant( @@ -1177,6 +1279,7 @@ class AssertRankAtLeastTest(test.TestCase): [check_ops.assert_rank_at_least(tensor, desired_rank)]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_zero_tensor_raises_if_rank_too_small_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1194,6 +1297,7 @@ class AssertRankAtLeastTest(test.TestCase): [check_ops.assert_rank_at_least(tensor, desired_rank)]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_zero_tensor_doesnt_raise_if_rank_just_right_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1210,6 +1314,7 @@ class AssertRankAtLeastTest(test.TestCase): [check_ops.assert_rank_at_least(tensor, desired_rank)]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_one_ten_doesnt_raise_if_rank_too_large_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1226,6 +1331,7 @@ class AssertRankAtLeastTest(test.TestCase): [check_ops.assert_rank_at_least(tensor, desired_rank)]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_one_tensor_doesnt_raise_if_rank_just_right_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1243,6 +1349,7 @@ class AssertRankAtLeastTest(test.TestCase): [check_ops.assert_rank_at_least(tensor, desired_rank)]): self.evaluate(array_ops.identity(tensor)) + @test_util.run_deprecated_v1 def test_rank_one_tensor_raises_if_rank_too_small_dynamic_rank(self): with self.cached_session(): tensor = array_ops.placeholder(dtypes.float32, name="my_tensor") @@ -1256,6 +1363,7 @@ class AssertRankAtLeastTest(test.TestCase): class AssertNonNegativeTest(test.TestCase): @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_negative(self): zoe = constant_op.constant([-1, -2], name="zoe") with self.assertRaisesOpError("x >= 0 did not hold"): @@ -1292,6 +1400,7 @@ class AssertNonPositiveTest(test.TestCase): self.evaluate(out) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_raises_when_positive(self): rachel = constant_op.constant([0, 2], name="rachel") with self.assertRaisesOpError("x <= 0 did not hold"): diff --git a/tensorflow/python/kernel_tests/checkpoint_ops_test.py b/tensorflow/python/kernel_tests/checkpoint_ops_test.py index 51611b75af..b8c8c9edb5 100644 --- a/tensorflow/python/kernel_tests/checkpoint_ops_test.py +++ b/tensorflow/python/kernel_tests/checkpoint_ops_test.py @@ -24,6 +24,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import gen_checkpoint_ops from tensorflow.python.ops import partitioned_variables from tensorflow.python.ops import variable_scope @@ -48,6 +49,7 @@ class GenerateVocabRemappingTest(test.TestCase): with open(self.old_vocab_file, 'w') as f: f.write('\n'.join(['knitting', 'eminem', 'MISSING']) + '\n') + @test_util.run_deprecated_v1 def test_generate_remapping_with_no_vocab_changes(self): """Tests where vocab does not change at all.""" remapping, num_present = gen_checkpoint_ops.generate_vocab_remapping( @@ -58,8 +60,8 @@ class GenerateVocabRemappingTest(test.TestCase): expected_remapping = range(0, 3) expected_num_present = 3 with self.cached_session(): - self.assertAllEqual(expected_remapping, remapping.eval()) - self.assertAllEqual(expected_num_present, num_present.eval()) + self.assertAllEqual(expected_remapping, self.evaluate(remapping)) + self.assertAllEqual(expected_num_present, self.evaluate(num_present)) def test_generate_remapping_with_shifted_vocab(self): """Tests where vocab is the same, but shifted / ordered differently.""" @@ -71,8 +73,8 @@ class GenerateVocabRemappingTest(test.TestCase): expected_remapping = [2, 0, 1] expected_num_present = 3 with self.cached_session(): - self.assertAllEqual(expected_remapping, remapping.eval()) - self.assertAllEqual(expected_num_present, num_present.eval()) + self.assertAllEqual(expected_remapping, self.evaluate(remapping)) + self.assertAllEqual(expected_num_present, self.evaluate(num_present)) def test_generate_remapping_with_offset(self): """Tests offset and num_new_vocab logic.""" @@ -84,8 +86,8 @@ class GenerateVocabRemappingTest(test.TestCase): expected_remapping = [0] expected_num_present = 1 with self.cached_session(): - self.assertAllEqual(expected_remapping, remapping.eval()) - self.assertAllEqual(expected_num_present, num_present.eval()) + self.assertAllEqual(expected_remapping, self.evaluate(remapping)) + self.assertAllEqual(expected_num_present, self.evaluate(num_present)) def test_generate_remapping_with_old_vocab_size(self): """Tests where old_vocab_size is specified.""" @@ -99,8 +101,8 @@ class GenerateVocabRemappingTest(test.TestCase): expected_remapping = [-1, 0, 1] expected_num_present = 2 with self.cached_session(): - self.assertAllEqual(expected_remapping, remapping.eval()) - self.assertAllEqual(expected_num_present, num_present.eval()) + self.assertAllEqual(expected_remapping, self.evaluate(remapping)) + self.assertAllEqual(expected_num_present, self.evaluate(num_present)) class LoadAndRemapMatrixTest(test.TestCase): @@ -142,7 +144,7 @@ class LoadAndRemapMatrixTest(test.TestCase): num_cols=self.old_num_cols) with self.cached_session(): self.assertAllClose(self.matrix_value[row_remapping], - remapped_matrix.eval()) + self.evaluate(remapped_matrix)) # No row remapping, new weight matrix has third col, then first col. row_remapping = list(range(self.old_num_rows)) @@ -157,7 +159,7 @@ class LoadAndRemapMatrixTest(test.TestCase): num_cols=len(col_remapping)) with self.cached_session(): self.assertAllClose(self.matrix_value[row_remapping][:, col_remapping], - remapped_matrix.eval()) + self.evaluate(remapped_matrix)) # Both row and column remappings. row_remapping = [1, 0, 4] @@ -172,7 +174,7 @@ class LoadAndRemapMatrixTest(test.TestCase): num_cols=len(col_remapping)) with self.cached_session(): self.assertAllClose(self.matrix_value[row_remapping][:, col_remapping], - remapped_matrix.eval()) + self.evaluate(remapped_matrix)) def test_load_and_remap_with_init(self): """Tests the op's load and remap where there are missing entries.""" @@ -190,7 +192,8 @@ class LoadAndRemapMatrixTest(test.TestCase): [33, init_val, init_val, init_val, 1, init_val], [3, 2]) with self.cached_session(): - self.assertAllClose(expected_remapped_matrix, remapped_matrix.eval()) + self.assertAllClose(expected_remapped_matrix, + self.evaluate(remapped_matrix)) def test_load_and_remap_all_missing_rows(self): """Tests when all the rows are missing and need to be initialized.""" @@ -207,7 +210,7 @@ class LoadAndRemapMatrixTest(test.TestCase): with self.cached_session(): self.assertAllClose( np.reshape(initializing_values, (num_rows, self.old_num_cols)), - remapped_matrix.eval()) + self.evaluate(remapped_matrix)) def test_load_and_remap_all_missing_rows_and_cols(self): """Tests when all the rows & cols are missing and need to be initialized.""" @@ -225,7 +228,7 @@ class LoadAndRemapMatrixTest(test.TestCase): with self.cached_session(): self.assertAllClose( np.reshape(initializing_values, (num_rows, num_cols)), - remapped_matrix.eval()) + self.evaluate(remapped_matrix)) def test_load_and_remap_invalid_remapping(self): """Tests that errors are raised when an ID maps to multiple new IDs. @@ -244,7 +247,7 @@ class LoadAndRemapMatrixTest(test.TestCase): num_rows=len(invalid_remapping), num_cols=self.old_num_cols) with self.cached_session(), self.assertRaises(errors.UnimplementedError): - remapped_matrix.eval() + self.evaluate(remapped_matrix) # Invalid column remapping. remapped_matrix = gen_checkpoint_ops.load_and_remap_matrix( @@ -256,7 +259,7 @@ class LoadAndRemapMatrixTest(test.TestCase): num_rows=self.old_num_rows, num_cols=len(invalid_remapping)) with self.cached_session(), self.assertRaises(errors.UnimplementedError): - remapped_matrix.eval() + self.evaluate(remapped_matrix) def test_load_and_remap_incorrect_initializing_values(self): """Tests that errors are raised with incorrect number of init values.""" @@ -273,7 +276,7 @@ class LoadAndRemapMatrixTest(test.TestCase): num_rows=3, num_cols=2) with self.cached_session(), self.assertRaises(errors.InvalidArgumentError): - remapped_matrix.eval() + self.evaluate(remapped_matrix) remapped_matrix = gen_checkpoint_ops.load_and_remap_matrix( ckpt_path=[self.bundle_file], @@ -285,7 +288,7 @@ class LoadAndRemapMatrixTest(test.TestCase): num_rows=3, num_cols=2) with self.cached_session(), self.assertRaises(errors.InvalidArgumentError): - remapped_matrix.eval() + self.evaluate(remapped_matrix) class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): @@ -324,7 +327,7 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): num_rows=num_rows, num_cols=num_cols, max_rows_in_memory=max_rows_in_memory) - self.assertAllClose(np_value[::-1], remapped_matrix.eval()) + self.assertAllClose(np_value[::-1], self.evaluate(remapped_matrix)) # Tests loading the tensor (except for the first and last rows), with # uninitialized values. Requires num_rows to be at least 3 since we're @@ -348,7 +351,7 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): np.vstack([ np.tile(42, [prefix_rows, num_cols]), np_value[1:-1], np.tile(42, [suffix_rows, num_cols]) - ]), remapped_matrix.eval()) + ]), self.evaluate(remapped_matrix)) # Tests when everything is taken from initializing_values. new_rows = 7 @@ -365,8 +368,9 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): max_rows_in_memory=max_rows_in_memory) self.assertAllClose( np.reshape(initializing_values, (new_rows, num_cols)), - remapped_matrix.eval()) + self.evaluate(remapped_matrix)) + @test_util.run_deprecated_v1 def test_loading_rows_divisible_by_max_rows(self): """Tests loading normal var when rows are evenly divisible by max_rows.""" self._test_loading_variable_with_max_rows( @@ -375,6 +379,7 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): # 9 is evenly divisible by 3. max_rows_in_memory=3) + @test_util.run_deprecated_v1 def test_loading_rows_not_divisible_by_max_rows(self): """Tests loading normal var when rows aren't divisible by max_rows.""" self._test_loading_variable_with_max_rows( @@ -383,6 +388,7 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): # 9 is not evenly divisible by 4. max_rows_in_memory=4) + @test_util.run_deprecated_v1 def test_loading_rows_less_than_max_rows(self): """Tests loading normal var as a single slice. @@ -394,6 +400,7 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): # 10 > 9. max_rows_in_memory=10) + @test_util.run_deprecated_v1 def test_loading_no_max_rows(self): """Tests loading normal var as a single slice with no valid max_rows.""" self._test_loading_variable_with_max_rows( @@ -401,6 +408,7 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): partitioner=None, max_rows_in_memory=-1) + @test_util.run_deprecated_v1 def test_loading_partitions_equals_max_rows(self): """Tests loading partitioned var sliced on partition boundary.""" self._test_loading_variable_with_max_rows( @@ -410,6 +418,7 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): # exactly 3 rows. max_rows_in_memory=3) + @test_util.run_deprecated_v1 def test_loading_partitions_greater_than_max_rows(self): """Tests loading partitioned var with more slices than partitions.""" self._test_loading_variable_with_max_rows( @@ -419,6 +428,7 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): # row at a time. max_rows_in_memory=1) + @test_util.run_deprecated_v1 def test_loading_partitions_less_than_max_rows(self): """Tests loading partitioned var as a single slice. @@ -429,6 +439,7 @@ class LoadAndRemapMatrixWithMaxRowsTest(test.TestCase): partitioner=partitioned_variables.fixed_size_partitioner(3), max_rows_in_memory=10) + @test_util.run_deprecated_v1 def test_loading_partitions_no_max_rows(self): """Tests loading partitioned var as single slice with no valid max_rows.""" self._test_loading_variable_with_max_rows( diff --git a/tensorflow/python/kernel_tests/cholesky_op_test.py b/tensorflow/python/kernel_tests/cholesky_op_test.py index e96b277266..f3947236b1 100644 --- a/tensorflow/python/kernel_tests/cholesky_op_test.py +++ b/tensorflow/python/kernel_tests/cholesky_op_test.py @@ -26,6 +26,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes as dtypes_lib from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_linalg_ops @@ -97,7 +98,7 @@ def TriAngInvCompositeGrad(l, grad): class CholeskyOpTest(test.TestCase): def _verifyCholeskyBase(self, sess, x, chol, verification): - chol_np, verification_np = sess.run([chol, verification]) + chol_np, verification_np = self.evaluate([chol, verification]) self.assertAllClose(x, verification_np) self.assertShapeEqual(x, chol) # Check that the cholesky is lower triangular, and has positive diagonal @@ -145,6 +146,7 @@ class CholeskyOpTest(test.TestCase): matrices[i] = np.dot(matrices[i].T.conj(), matrices[i]) self._verifyCholesky(matrices) + @test_util.run_deprecated_v1 def testNonSquareMatrix(self): with self.assertRaises(ValueError): linalg_ops.cholesky(np.array([[1., 2., 3.], [3., 4., 5.]])) @@ -175,6 +177,7 @@ class CholeskyOpTest(test.TestCase): self._verifyCholesky(np.empty([0, 2, 2])) self._verifyCholesky(np.empty([2, 0, 0])) + @test_util.run_deprecated_v1 def testConcurrentExecutesWithoutError(self): with self.session(use_gpu=True) as sess: matrix1 = random_ops.random_normal([5, 5], seed=42) @@ -183,8 +186,8 @@ class CholeskyOpTest(test.TestCase): matrix2 = math_ops.matmul(matrix2, matrix2, adjoint_a=True) c1 = linalg_ops.cholesky(matrix1) c2 = linalg_ops.cholesky(matrix2) - c1_val, c2_val = sess.run([c1, c2]) - self.assertAllEqual(c1_val, c2_val) + c1_val, c2_val = self.evaluate([c1, c2]) + self.assertAllClose(c1_val, c2_val) class CholeskyGradTest(test.TestCase): @@ -193,18 +196,21 @@ class CholeskyGradTest(test.TestCase): def getShapes(self, shapeList): return ((elem, int(np.floor(1.2 * elem))) for elem in shapeList) + @test_util.run_deprecated_v1 def testSmallMatrices(self): np.random.seed(0) shapes = self.getShapes([1, 2, 10]) self.runFiniteDifferences( shapes, dtypes=(dtypes_lib.float32, dtypes_lib.float64)) + @test_util.run_deprecated_v1 def testSmallMatricesComplex(self): np.random.seed(0) shapes = self.getShapes([1, 2, 10]) self.runFiniteDifferences( shapes, dtypes=(dtypes_lib.complex64, dtypes_lib.complex128)) + @test_util.run_deprecated_v1 def testOneBlockMatrices(self): np.random.seed(0) shapes = self.getShapes([self._backprop_block_size + 1]) @@ -213,12 +219,14 @@ class CholeskyGradTest(test.TestCase): dtypes=(dtypes_lib.float32, dtypes_lib.float64), scalarTest=True) + @test_util.run_deprecated_v1 def testTwoBlockMatrixFloat(self): np.random.seed(0) shapes = self.getShapes([2 * self._backprop_block_size + 1]) self.runFiniteDifferences( shapes, dtypes=(dtypes_lib.float32,), scalarTest=True) + @test_util.run_deprecated_v1 def testTwoBlockMatrixDouble(self): np.random.seed(0) shapes = self.getShapes([2 * self._backprop_block_size + 1]) @@ -231,6 +239,7 @@ class CholeskyGradTest(test.TestCase): self.runFiniteDifferences( shapes, dtypes=(dtypes_lib.complex64,), scalarTest=True) + @test_util.run_deprecated_v1 def testTwoBlockMatrixComplexDouble(self): np.random.seed(0) shapes = self.getShapes([2 * self._backprop_block_size + 1]) diff --git a/tensorflow/python/kernel_tests/clip_ops_test.py b/tensorflow/python/kernel_tests/clip_ops_test.py index efd7eee847..45f1e6152a 100644 --- a/tensorflow/python/kernel_tests/clip_ops_test.py +++ b/tensorflow/python/kernel_tests/clip_ops_test.py @@ -24,10 +24,12 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import clip_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl +from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -55,7 +57,7 @@ class ClipTest(test.TestCase): np_ans = [[-4.4, 2.0, 3.0], [4.0, 4.4, 4.4]] clip_value = 4.4 ans = clip_ops.clip_by_value(x, -clip_value, clip_value) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -71,7 +73,7 @@ class ClipTest(test.TestCase): clip_value_min = 2 clip_value_max = 4 ans = clip_ops.clip_by_value(x, clip_value_min, clip_value_max) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -88,7 +90,7 @@ class ClipTest(test.TestCase): [2, 2, 2, 3, 3, 3], shape=[2, 3], dtype=dtype) clip_value_max = 4 ans = clip_ops.clip_by_value(x, clip_value_min, clip_value_max) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -105,7 +107,7 @@ class ClipTest(test.TestCase): clip_value_max = constant_op.constant( [6, 6, 6, 6, 6, 6], shape=[2, 3], dtype=dtype) ans = clip_ops.clip_by_value(x, clip_value_min, clip_value_max) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -123,7 +125,7 @@ class ClipTest(test.TestCase): clip_value_max = constant_op.constant( [5, 5, 5, 7, 7, 7], shape=[2, 3], dtype=dtype) ans = clip_ops.clip_by_value(x, clip_value_min, clip_value_max) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -144,7 +146,7 @@ class ClipTest(test.TestCase): np_ans = [float('NaN'), 4.0, -4.0] clip_value = 4.0 ans = clip_ops.clip_by_value(x, -clip_value, clip_value) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -157,14 +159,15 @@ class ClipTest(test.TestCase): np_ans = [[-2.4, 0.0, 0.0], [3.2, 0.0, 0.0]] clip_norm = 4.0 ans = clip_ops.clip_by_norm(x, clip_norm) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) ans = clip_ops.clip_by_norm(x, clip_norm) - tf_ans_tensor = ans.eval() + tf_ans_tensor = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) self.assertAllClose(np_ans, tf_ans_tensor) + @test_util.run_deprecated_v1 def testClipByNormGradientZeros(self): with self.session(use_gpu=True): x = array_ops.zeros([3]) @@ -188,7 +191,7 @@ class ClipTest(test.TestCase): np_ans = [[-3.0, 0.0, 0.0], [4.0, 0.0, 0.0]] clip_norm = 6.0 ans = clip_ops.clip_by_norm(x, clip_norm) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -200,7 +203,7 @@ class ClipTest(test.TestCase): np_ans = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] clip_norm = 6.0 ans = clip_ops.clip_by_norm(x, clip_norm) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -212,7 +215,7 @@ class ClipTest(test.TestCase): np_ans = [[-2.4, 0.0, 0.0], [3.2, 0.0, 3.0]] clip_norm = 4.0 ans = clip_ops.clip_by_norm(x, clip_norm, [0]) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -224,7 +227,7 @@ class ClipTest(test.TestCase): np_ans = [[-3.0, 0.0, 0.0], [3.2, 0.0, 2.4]] clip_norm = 4.0 ans = clip_ops.clip_by_norm(x, clip_norm, [1]) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -236,11 +239,12 @@ class ClipTest(test.TestCase): np_ans = [[-3.0, 0.0, 0.0], [4.0, 0.0, 3.0]] clip_norm = 6.0 ans = clip_ops.clip_by_norm(x, clip_norm, [1]) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) # ClipByGlobalNorm tests + @test_util.run_deprecated_v1 def testClipByGlobalNormClipped(self): # Norm clipping when clip_norm < 5 with self.session(use_gpu=True): @@ -256,12 +260,13 @@ class ClipTest(test.TestCase): ans, norm = clip_ops.clip_by_global_norm((x0, x1), clip_norm) tf_ans_1 = ans[0].eval() tf_ans_2 = ans[1].eval() - tf_norm = norm.eval() + tf_norm = self.evaluate(norm) self.assertAllClose(tf_norm, 5.0) self.assertAllClose(np_ans_0, tf_ans_1) self.assertAllClose(np_ans_1, tf_ans_2) + @test_util.run_deprecated_v1 def testClipByGlobalNormClippedTensor(self): # Norm clipping when clip_norm < 5 with self.session(use_gpu=True): @@ -277,12 +282,13 @@ class ClipTest(test.TestCase): ans, norm = clip_ops.clip_by_global_norm((x0, x1), clip_norm) tf_ans_1 = ans[0].eval() tf_ans_2 = ans[1].eval() - tf_norm = norm.eval() + tf_norm = self.evaluate(norm) self.assertAllClose(tf_norm, 5.0) self.assertAllClose(np_ans_0, tf_ans_1) self.assertAllClose(np_ans_1, tf_ans_2) + @test_util.run_deprecated_v1 def testClipByGlobalNormSupportsNone(self): # Norm clipping when clip_norm < 5 with self.session(use_gpu=True): @@ -300,12 +306,13 @@ class ClipTest(test.TestCase): self.assertTrue(ans[3] is None) tf_ans_1 = ans[0].eval() tf_ans_2 = ans[2].eval() - tf_norm = norm.eval() + tf_norm = self.evaluate(norm) self.assertAllClose(tf_norm, 5.0) self.assertAllClose(np_ans_0, tf_ans_1) self.assertAllClose(np_ans_1, tf_ans_2) + @test_util.run_deprecated_v1 def testClipByGlobalNormWithIndexedSlicesClipped(self): # Norm clipping when clip_norm < 5 with self.session(use_gpu=True): @@ -322,7 +329,7 @@ class ClipTest(test.TestCase): ans, norm = clip_ops.clip_by_global_norm([x0, x1], clip_norm) tf_ans_1 = ans[0].eval() tf_ans_2 = ans[1].values.eval() - tf_norm = norm.eval() + tf_norm = self.evaluate(norm) self.assertAllClose(tf_norm, 5.0) self.assertAllClose(np_ans_0, tf_ans_1) @@ -339,6 +346,7 @@ class ClipTest(test.TestCase): self.assertEqual(dense_shape, slices.dense_shape) self.assertEqual(dense_shape, modified_slices.dense_shape) + @test_util.run_deprecated_v1 def testClipByGlobalNormNotClipped(self): # No norm clipping when clip_norm >= 5 with self.session(use_gpu=True): @@ -352,12 +360,13 @@ class ClipTest(test.TestCase): ans, norm = clip_ops.clip_by_global_norm([x0, x1], clip_norm) tf_ans_1 = ans[0].eval() tf_ans_2 = ans[1].eval() - tf_norm = norm.eval() + tf_norm = self.evaluate(norm) self.assertAllClose(tf_norm, 5.0) self.assertAllClose(np_ans_0, tf_ans_1) self.assertAllClose(np_ans_1, tf_ans_2) + @test_util.run_deprecated_v1 def testClipByGlobalNormZero(self): # No norm clipping when norm = 0 with self.session(use_gpu=True): @@ -371,12 +380,13 @@ class ClipTest(test.TestCase): ans, norm = clip_ops.clip_by_global_norm([x0, x1], clip_norm) tf_ans_1 = ans[0].eval() tf_ans_2 = ans[1].eval() - tf_norm = norm.eval() + tf_norm = self.evaluate(norm) self.assertAllClose(tf_norm, 0.0) self.assertAllClose(np_ans_0, tf_ans_1) self.assertAllClose(np_ans_1, tf_ans_2) + @test_util.run_deprecated_v1 def testClipByGlobalNormInf(self): with self.session(use_gpu=True): x0 = constant_op.constant([-2.0, 0.0, np.inf, 4.0, 0.0, 0.0], @@ -386,7 +396,7 @@ class ClipTest(test.TestCase): ans, norm = clip_ops.clip_by_global_norm([x0, x1], clip_norm) with self.assertRaisesRegexp(errors.InvalidArgumentError, "global norm"): - norm.eval() + self.evaluate(norm) with self.assertRaisesRegexp(errors.InvalidArgumentError, "global norm"): ans[0].eval() with self.assertRaisesRegexp(errors.InvalidArgumentError, "global norm"): @@ -400,7 +410,7 @@ class ClipTest(test.TestCase): np_ans = [[-2.88, 0.0, 0.0], [3.84, 0.0, 0.0]] clip_norm = 0.8 ans = clip_ops.clip_by_average_norm(x, clip_norm) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -412,7 +422,7 @@ class ClipTest(test.TestCase): np_ans = [[-2.88, 0.0, 0.0], [3.84, 0.0, 0.0]] clip_norm = constant_op.constant(0.8) ans = clip_ops.clip_by_average_norm(x, clip_norm) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -424,7 +434,7 @@ class ClipTest(test.TestCase): np_ans = [[-3.0, 0.0, 0.0], [4.0, 0.0, 0.0]] clip_norm = 0.9 ans = clip_ops.clip_by_average_norm(x, clip_norm) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) @@ -436,10 +446,26 @@ class ClipTest(test.TestCase): np_ans = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] clip_norm = 0.9 ans = clip_ops.clip_by_average_norm(x, clip_norm) - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(np_ans, tf_ans) + def testClipByAverageNormReplacedWithClipByNorm(self): + # Check clip_by_average_norm(t) is the same as + # clip_by_norm(t, clip_norm * tf.to_float(tf.size(t))) + with self.session(use_gpu=True): + x = constant_op.constant([-3.0, 0.0, 0.0, 4.0, 0.0, 0.0], shape=[2, 3]) + # Average norm of x = sqrt(3^2 + 4^2) / 6 = 0.83333333 + # expected answer [[-2.88, 0.0, 0.0], [3.84, 0.0, 0.0]] + clip_norm = constant_op.constant(0.8) + with_norm = clip_ops.clip_by_average_norm(x, clip_norm) + without_norm = clip_ops.clip_by_norm( + x, clip_norm * math_ops.to_float(array_ops.size(x))) + clip_by_average_norm_ans = self.evaluate(with_norm) + clip_by_norm_ans = self.evaluate(without_norm) + self.assertAllClose(clip_by_average_norm_ans, clip_by_norm_ans) + + @test_util.run_deprecated_v1 def testClipByValueEmptyTensor(self): # Test case for GitHub issue 19337 zero = array_ops.placeholder(dtype=dtypes.float32, shape=None) diff --git a/tensorflow/python/kernel_tests/compare_and_bitpack_op_test.py b/tensorflow/python/kernel_tests/compare_and_bitpack_op_test.py index f27a0fc472..215ea97f36 100644 --- a/tensorflow/python/kernel_tests/compare_and_bitpack_op_test.py +++ b/tensorflow/python/kernel_tests/compare_and_bitpack_op_test.py @@ -20,6 +20,7 @@ from __future__ import print_function import numpy as np +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -30,15 +31,15 @@ class CompareAndBitpackTest(test.TestCase): x, threshold, truth, expected_err_re=None): - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): ans = math_ops.compare_and_bitpack(x, threshold) if expected_err_re is None: - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertShapeEqual(truth, ans) self.assertAllEqual(tf_ans, truth) else: with self.assertRaisesOpError(expected_err_re): - ans.eval() + self.evaluate(ans) def _testBasic(self, dtype): rows = 371 diff --git a/tensorflow/python/kernel_tests/concat_op_test.py b/tensorflow/python/kernel_tests/concat_op_test.py index 92d09986e6..474760a93f 100644 --- a/tensorflow/python/kernel_tests/concat_op_test.py +++ b/tensorflow/python/kernel_tests/concat_op_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_array_ops from tensorflow.python.ops import gradient_checker @@ -34,6 +35,7 @@ from tensorflow.python.platform import test class ConcatOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testHStack(self): with self.session(use_gpu=True): p1 = array_ops.placeholder(dtypes.float32, shape=[4, 4]) @@ -49,6 +51,7 @@ class ConcatOpTest(test.TestCase): self.assertAllEqual(result[:4, :], params[p1]) self.assertAllEqual(result[4:, :], params[p2]) + @test_util.run_deprecated_v1 def testVStack(self): with self.session(use_gpu=True): p1 = array_ops.placeholder(dtypes.float32, shape=[4, 4]) @@ -65,25 +68,25 @@ class ConcatOpTest(test.TestCase): self.assertAllEqual(result[:, 4:], params[p2]) def testInt32GPU(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): p1 = np.random.rand(2, 3).astype("i") p2 = np.random.rand(2, 3).astype("i") x1 = constant_op.constant(p1) x2 = constant_op.constant(p2) c = array_ops.concat([x1, x2], 0) - result = c.eval() + result = self.evaluate(c) self.assertAllEqual(result[:2, :], p1) self.assertAllEqual(result[2:, :], p2) def testRefType(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): p1 = np.random.rand(4, 4).astype("f") p2 = np.random.rand(4, 4).astype("f") v1 = variables.Variable(p1) v2 = variables.Variable(p2) c = array_ops.concat([v1, v2], 0) - variables.global_variables_initializer().run() - result = c.eval() + self.evaluate(variables.global_variables_initializer()) + result = self.evaluate(c) self.assertEqual(result.shape, c.get_shape()) self.assertAllEqual(result[:4, :], p1) @@ -137,6 +140,7 @@ class ConcatOpTest(test.TestCase): else: self.assertAllClose(result[ind], params[p[i]], 0.01) + @test_util.run_deprecated_v1 def testRandom(self): self._testRandom(dtypes.bool) self._testRandom(dtypes.float32) @@ -147,6 +151,7 @@ class ConcatOpTest(test.TestCase): self._testRandom(dtypes.complex64) self._testRandom(dtypes.complex128) + @test_util.run_deprecated_v1 def testInvalidConcatDimTypeAndShape(self): a = variables.Variable(constant_op.constant(1.0, shape=[1])) b = variables.Variable(constant_op.constant(2.0, shape=[1])) @@ -172,7 +177,7 @@ class ConcatOpTest(test.TestCase): # Test both positive and negative concat axis. # -2 and 1 correspond to the same axis for 3-dimensional tensors. for axis in [-2, 1]: - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): inp = [] inp_tensors = [] for x in [1, 2, 6]: @@ -195,15 +200,17 @@ class ConcatOpTest(test.TestCase): grad_inp.flatten(), shape=output_shape) grad = gradients_impl.gradients([c], inp_tensors, [grad_tensor]) concated_grad = array_ops.concat(grad, axis) - result = concated_grad.eval() + result = self.evaluate(concated_grad) self.assertAllEqual(result, grad_inp) + @test_util.run_deprecated_v1 def testGradientsSimple(self): self._testGradientsSimple(dtypes.float32) self._testGradientsSimple(dtypes.complex64) + @test_util.run_deprecated_v1 def testGradientsFirstDim(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): inp = [] inp_tensors = [] for x in [1, 2, 6]: @@ -222,15 +229,16 @@ class ConcatOpTest(test.TestCase): grad_inp.flatten(), shape=output_shape) grad = gradients_impl.gradients([c], inp_tensors, [grad_tensor]) concated_grad = array_ops.concat(grad, 0) - result = concated_grad.eval() + result = self.evaluate(concated_grad) self.assertAllEqual(result, grad_inp) + @test_util.run_deprecated_v1 def testGradientsLastDim(self): # Test both positive and negative concat axis. # -1 and 2 correspond to the same axis for 3-dimensional tensors. for axis in [-1, 2]: - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): inp = [] inp_tensors = [] for x in [1, 2, 6]: @@ -249,7 +257,7 @@ class ConcatOpTest(test.TestCase): grad_inp.flatten(), shape=output_shape) grad = gradients_impl.gradients([c], inp_tensors, [grad_tensor]) concated_grad = array_ops.concat(grad, axis) - result = concated_grad.eval() + result = self.evaluate(concated_grad) self.assertAllEqual(result, grad_inp) @@ -261,7 +269,7 @@ class ConcatOpTest(test.TestCase): # Random dim to concat on concat_dim = np.random.randint(5) concat_dim_sizes = np.random.randint(1, 5, size=num_tensors) - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): inp = [] inp_tensors = [] for x in concat_dim_sizes: @@ -279,14 +287,16 @@ class ConcatOpTest(test.TestCase): grad_tensor = constant_op.constant(grad_inp.flatten(), shape=output_shape) grad = gradients_impl.gradients([c], inp_tensors, [grad_tensor]) concated_grad = array_ops.concat(grad, concat_dim) - result = concated_grad.eval() + result = self.evaluate(concated_grad) self.assertAllEqual(result, grad_inp) + @test_util.run_deprecated_v1 def testGradientsRandom(self): for _ in range(5): self._RunAndVerifyGradientsRandom() + @test_util.run_deprecated_v1 def testGradientWithUnknownInputDim(self): with self.session(use_gpu=True): x = array_ops.placeholder(dtypes.float32) @@ -308,6 +318,7 @@ class ConcatOpTest(test.TestCase): self.assertAllEqual(result, grad_inp) + @test_util.run_deprecated_v1 def testShapeError(self): # Rank doesn't match. with self.assertRaises(ValueError): @@ -337,6 +348,7 @@ class ConcatOpTest(test.TestCase): constant_op.constant(20.0, shape=[4, 4, 4]) ], -4) + @test_util.run_deprecated_v1 def testShapeWithUnknownConcatDim(self): p1 = array_ops.placeholder(dtypes.float32) c1 = constant_op.constant(10.0, shape=[4, 4, 4, 4]) @@ -355,10 +367,11 @@ class ConcatOpTest(test.TestCase): with self.assertRaises(ValueError): array_ops.concat([p1, c1, p2, c3], dim) + @test_util.run_deprecated_v1 def testZeroSize(self): # Verify that concat doesn't crash and burn for zero size inputs np.random.seed(7) - with self.session(use_gpu=True) as sess: + with test_util.use_gpu(): for shape0 in (), (2,): axis = len(shape0) for shape1 in (), (3,): @@ -370,12 +383,13 @@ class ConcatOpTest(test.TestCase): # TODO(irving): Make tf.concat handle map, then drop list(). xs = list(map(constant_op.constant, [x0, x1])) c = array_ops.concat(xs, axis) - self.assertAllEqual(c.eval(), correct) + self.assertAllEqual(self.evaluate(c), correct) # Check gradients dc = np.random.randn(*c.get_shape().as_list()) - dxs = sess.run(gradients_impl.gradients(c, xs, dc)) + dxs = self.evaluate(gradients_impl.gradients(c, xs, dc)) self.assertAllEqual(dc, np.concatenate(dxs, axis=axis)) + @test_util.run_deprecated_v1 def testTensorConcatDim0Grad(self): x_shapes = [[20, 7, 3], [10, 7, 3], [14, 7, 3]] output_shape = [44, 7, 3] @@ -390,6 +404,7 @@ class ConcatOpTest(test.TestCase): output_shape) self.assertLess(err, 1e-11) + @test_util.run_deprecated_v1 def testTensorConcatDim1Grad(self): x_shapes = [[20, 7, 3], [20, 3, 3], [20, 1, 3]] output_shape = [20, 11, 3] @@ -404,6 +419,7 @@ class ConcatOpTest(test.TestCase): output_shape) self.assertLess(err, 1e-11) + @test_util.run_deprecated_v1 def testIndexedSlicesConcatDim0Grad(self): x_shapes = [[20, 7, 3], [10, 7, 3], [14, 7, 3]] output_shape = [4, 7, 3] @@ -419,6 +435,7 @@ class ConcatOpTest(test.TestCase): output_shape) self.assertLess(err, 1e-11) + @test_util.run_deprecated_v1 def testIndexedSlicesConcatDim1Grad(self): x_shapes = [[20, 7, 3], [20, 3, 3], [20, 1, 3]] output_shape = [4, 11, 3] @@ -434,6 +451,7 @@ class ConcatOpTest(test.TestCase): output_shape) self.assertLess(err, 1e-11) + @test_util.run_deprecated_v1 def testIndexedSlicesConcatDim2Grad(self): x_shapes = [[20, 7, 3], [20, 7, 1], [20, 7, 2]] output_shape = [4, 7, 6] @@ -449,6 +467,7 @@ class ConcatOpTest(test.TestCase): output_shape) self.assertLess(err, 1e-11) + @test_util.run_deprecated_v1 def testIndexedSlicesConcatDim1Grad_UnknownInputDim(self): x_shapes = [[20, 7, 3], [20, 3, 3], [20, 1, 3]] output_shape = [4, 11, 3] @@ -473,21 +492,22 @@ class ConcatOpTest(test.TestCase): def testConcatTuple(self): c1 = np.random.rand(4, 4) c2 = np.random.rand(4, 4) - with self.cached_session(): - concat_list_t = array_ops.concat([c1, c2], 0) - concat_tuple_t = array_ops.concat((c1, c2), 0) - self.assertAllEqual(concat_list_t.eval(), concat_tuple_t.eval()) + concat_list_t = array_ops.concat([c1, c2], 0) + concat_tuple_t = array_ops.concat((c1, c2), 0) + self.assertAllEqual( + self.evaluate(concat_list_t), self.evaluate(concat_tuple_t)) + @test_util.run_deprecated_v1 def testConcatNoScalars(self): - with self.cached_session(): - scalar = constant_op.constant(7) - dim = array_ops.placeholder(dtypes.int32) - with self.assertRaisesRegexp( - ValueError, r"Can't concatenate scalars \(use tf\.stack instead\)"): - array_ops.concat([scalar, scalar, scalar], dim) + scalar = constant_op.constant(7) + dim = array_ops.placeholder(dtypes.int32) + with self.assertRaisesRegexp( + ValueError, r"Can't concatenate scalars \(use tf\.stack instead\)"): + array_ops.concat([scalar, scalar, scalar], dim) # important as gpu implementation could fail if # shared memory is not large for all the inputs + @test_util.run_deprecated_v1 def testConcatLargeNumberOfTensors(self): with self.session(use_gpu=True): for concat_dim in range(2): @@ -523,33 +543,34 @@ class ConcatOpTest(test.TestCase): self.assertAllEqual(result[index], params[p[i]]) def testConcatEmpty(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): t1 = [] t2 = [] - output = gen_array_ops.concat_v2([t1, t2], 0).eval() - self.assertFalse(output) # Checks that output is empty + output = gen_array_ops.concat_v2([t1, t2], 0) + self.assertFalse(self.evaluate(output)) # Checks that output is empty + @test_util.run_deprecated_v1 def testConcatInvalidAxis(self): with self.assertRaises(ValueError): - with self.session(use_gpu=True): + with test_util.use_gpu(): t1 = [1] t2 = [2] gen_array_ops.concat_v2([t1, t2], 1).eval() def testConcatNegativeAxis(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): t1 = [[1, 2, 3], [4, 5, 6]] t2 = [[7, 8, 9], [10, 11, 12]] c = gen_array_ops.concat_v2([t1, t2], -2) self.assertEqual([4, 3], c.get_shape().as_list()) - output = c.eval() + output = self.evaluate(c) self.assertAllEqual([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]], output) c = gen_array_ops.concat_v2([t1, t2], -1) self.assertEqual([2, 6], c.get_shape().as_list()) - output = c.eval() + output = self.evaluate(c) self.assertAllEqual([[1, 2, 3, 7, 8, 9], [4, 5, 6, 10, 11, 12]], output) def _testGradientsForAxis( @@ -578,6 +599,7 @@ class ConcatOpTest(test.TestCase): result = concated_grad.eval(feed_dict=feed_dict) self.assertAllEqual(result, grad_inp) + @test_util.run_deprecated_v1 def testGradientsNegativeAxis(self): x1 = [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]] x2 = [[7.0, 8.0, 9.0], [10.0, 11.0, 12.0]] @@ -608,78 +630,78 @@ class ConcatOpTest(test.TestCase): def testConcatAxisType(self): for dtype in [dtypes.int32, dtypes.int64]: - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): t1 = [[1, 2, 3], [4, 5, 6]] t2 = [[7, 8, 9], [10, 11, 12]] c = gen_array_ops.concat_v2([t1, t2], constant_op.constant(1, dtype=dtype)) self.assertEqual([2, 6], c.get_shape().as_list()) - output = c.eval() + output = self.evaluate(c) self.assertAllEqual([[1, 2, 3, 7, 8, 9], [4, 5, 6, 10, 11, 12]], output) class ConcatOffsetTest(test.TestCase): def testBasic(self): - with self.session(use_gpu=True) as sess: + with test_util.use_gpu(): cdim = constant_op.constant(1, dtypes.int32) s0 = constant_op.constant([2, 3, 5], dtypes.int32) s1 = constant_op.constant([2, 7, 5], dtypes.int32) s2 = constant_op.constant([2, 20, 5], dtypes.int32) off = gen_array_ops.concat_offset(cdim, [s0, s1, s2]) - ans = sess.run(off) + ans = self.evaluate(off) self.assertAllEqual(ans, [[0, 0, 0], [0, 3, 0], [0, 10, 0]]) + @test_util.run_deprecated_v1 def testNotVector(self): - with self.cached_session() as sess: - cdim = constant_op.constant(1, dtypes.int32) - s0 = constant_op.constant([[2, 3, 5]], dtypes.int32) - s1 = constant_op.constant([[2, 7, 5]], dtypes.int32) - off = gen_array_ops.concat_offset(cdim, [s0, s1]) - with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, - r"should be a vector"): - sess.run(off) - + cdim = constant_op.constant(1, dtypes.int32) + s0 = constant_op.constant([[2, 3, 5]], dtypes.int32) + s1 = constant_op.constant([[2, 7, 5]], dtypes.int32) + off = gen_array_ops.concat_offset(cdim, [s0, s1]) + with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, + r"should be a vector"): + self.evaluate(off) + + @test_util.run_deprecated_v1 def testConcatDimOutOfRange(self): - with self.cached_session() as sess: - cdim = constant_op.constant(4, dtypes.int32) - s0 = constant_op.constant([2, 3, 5], dtypes.int32) - s1 = constant_op.constant([2, 7, 5], dtypes.int32) - off = gen_array_ops.concat_offset(cdim, [s0, s1]) - with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, - r"Concat dim is out of range: 4 vs. 3"): - sess.run(off) - + cdim = constant_op.constant(4, dtypes.int32) + s0 = constant_op.constant([2, 3, 5], dtypes.int32) + s1 = constant_op.constant([2, 7, 5], dtypes.int32) + off = gen_array_ops.concat_offset(cdim, [s0, s1]) + with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, + r"Concat dim is out of range: 4 vs. 3"): + self.evaluate(off) + + @test_util.run_deprecated_v1 def testDimMismatch(self): - with self.cached_session() as sess: - cdim = constant_op.constant(1, dtypes.int32) - s0 = constant_op.constant([2, 3, 5], dtypes.int32) - s1 = constant_op.constant([2, 7, 5, 10], dtypes.int32) - off = gen_array_ops.concat_offset(cdim, [s0, s1]) - with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, - r"should contain 3 elem"): - sess.run(off) - + cdim = constant_op.constant(1, dtypes.int32) + s0 = constant_op.constant([2, 3, 5], dtypes.int32) + s1 = constant_op.constant([2, 7, 5, 10], dtypes.int32) + off = gen_array_ops.concat_offset(cdim, [s0, s1]) + with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, + r"should contain 3 elem"): + self.evaluate(off) + + @test_util.run_deprecated_v1 def testSizeMismatch(self): - with self.cached_session() as sess: - cdim = constant_op.constant(1, dtypes.int32) - s0 = constant_op.constant([2, 3, 5], dtypes.int32) - s1 = constant_op.constant([2, 7, 10], dtypes.int32) - off = gen_array_ops.concat_offset(cdim, [s0, s1]) - with self.assertRaisesRegexp( - errors_impl.InvalidArgumentError, - r"All dimensions except 1 must match. Input 1 has shape \[2 7 10\] " - r"and doesn't match input 0 with shape \[2 3 5\]."): - sess.run(off) + cdim = constant_op.constant(1, dtypes.int32) + s0 = constant_op.constant([2, 3, 5], dtypes.int32) + s1 = constant_op.constant([2, 7, 10], dtypes.int32) + off = gen_array_ops.concat_offset(cdim, [s0, s1]) + with self.assertRaisesRegexp( + errors_impl.InvalidArgumentError, + r"All dimensions except 1 must match. Input 1 has shape \[2 7 10\] " + r"and doesn't match input 0 with shape \[2 3 5\]."): + self.evaluate(off) def testNegativeDim(self): - with self.session(use_gpu=True) as sess: + with test_util.use_gpu(): cdim = constant_op.constant(-2, dtypes.int32) s0 = constant_op.constant([2, 3, 5], dtypes.int32) s1 = constant_op.constant([2, 7, 5], dtypes.int32) s2 = constant_op.constant([2, 20, 5], dtypes.int32) off = gen_array_ops.concat_offset(cdim, [s0, s1, s2]) - ans = sess.run(off) + ans = self.evaluate(off) self.assertAllEqual(ans, [[0, 0, 0], [0, 3, 0], [0, 10, 0]]) cdim = constant_op.constant(-3, dtypes.int32) @@ -687,7 +709,7 @@ class ConcatOffsetTest(test.TestCase): s1 = constant_op.constant([1, 3, 5], dtypes.int32) s2 = constant_op.constant([3, 3, 5], dtypes.int32) off = gen_array_ops.concat_offset(cdim, [s0, s1, s2]) - ans = sess.run(off) + ans = self.evaluate(off) self.assertAllEqual(ans, [[0, 0, 0], [2, 0, 0], [3, 0, 0]]) diff --git a/tensorflow/python/kernel_tests/cond_v2_test.py b/tensorflow/python/kernel_tests/cond_v2_test.py index b077b853ed..1f4b37ce2a 100644 --- a/tensorflow/python/kernel_tests/cond_v2_test.py +++ b/tensorflow/python/kernel_tests/cond_v2_test.py @@ -20,6 +20,7 @@ from __future__ import division from __future__ import print_function from tensorflow.core.protobuf import config_pb2 +from tensorflow.python.eager import context from tensorflow.python.eager import function from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes @@ -32,6 +33,7 @@ from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import math_ops +from tensorflow.python.ops import tensor_array_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test from tensorflow.python.training import saver @@ -66,6 +68,7 @@ class CondV2Test(test.TestCase): self.assertEqual(expected_val, actual_val) self.assertEqual(expected_grad_val, actual_grad_val) + @test_util.run_deprecated_v1 def testBasic(self): x = constant_op.constant(1.0, name="x") y = constant_op.constant(2.0, name="y") @@ -80,6 +83,7 @@ class CondV2Test(test.TestCase): self._testCond(true_fn, false_fn, [x, y]) self._testCond(true_fn, false_fn, [y]) + @test_util.run_deprecated_v1 def testMultipleOutputs(self): x = constant_op.constant(1.0, name="x") y = constant_op.constant(3.0, name="y") @@ -94,6 +98,7 @@ class CondV2Test(test.TestCase): self._testCond(true_fn, false_fn, [x, y]) self._testCond(true_fn, false_fn, [y]) + @test_util.run_deprecated_v1 def testBasic2(self): x = constant_op.constant(1.0, name="x") y = constant_op.constant(2.0, name="y") @@ -108,6 +113,7 @@ class CondV2Test(test.TestCase): self._testCond(true_fn, false_fn, [x, y]) self._testCond(true_fn, false_fn, [y]) + @test_util.run_deprecated_v1 def testNoInputs(self): with self.cached_session() as sess: pred = array_ops.placeholder(dtypes.bool, name="pred") @@ -124,7 +130,7 @@ class CondV2Test(test.TestCase): self.assertEqual(sess.run(out, {pred: False}), (2.0,)) def _createCond(self, name): - """Helper function for testDefaultName.""" + """Creates a cond_v2 call and returns the output tensor and the cond op.""" pred = constant_op.constant(True, name="pred") x = constant_op.constant(1.0, name="x") @@ -137,11 +143,11 @@ class CondV2Test(test.TestCase): output = cond_v2.cond_v2(pred, true_fn, false_fn, name=name) cond_op = output.op.inputs[0].op self.assertEqual(cond_op.type, "If") - return cond_op + return output, cond_op def testDefaultName(self): with ops.Graph().as_default(): - cond_op = self._createCond(None) + _, cond_op = self._createCond(None) self.assertEqual(cond_op.name, "cond") self.assertRegexpMatches( cond_op.get_attr("then_branch").name, r"cond_true_\d*") @@ -150,14 +156,14 @@ class CondV2Test(test.TestCase): with ops.Graph().as_default(): with ops.name_scope("foo"): - cond1_op = self._createCond("") + _, cond1_op = self._createCond("") self.assertEqual(cond1_op.name, "foo/cond") self.assertRegexpMatches( cond1_op.get_attr("then_branch").name, r"foo_cond_true_\d*") self.assertRegexpMatches( cond1_op.get_attr("else_branch").name, r"foo_cond_false_\d*") - cond2_op = self._createCond(None) + _, cond2_op = self._createCond(None) self.assertEqual(cond2_op.name, "foo/cond_1") self.assertRegexpMatches( cond2_op.get_attr("then_branch").name, r"foo_cond_1_true_\d*") @@ -538,6 +544,7 @@ class CondV2Test(test.TestCase): pred_inner: False }), [5., 0.]) + @test_util.run_deprecated_v1 def testSecondDerivative(self): with self.cached_session() as sess: pred = array_ops.placeholder(dtypes.bool, name="pred") @@ -610,11 +617,11 @@ class CondV2Test(test.TestCase): def testLowering(self): with ops.Graph().as_default() as g: with self.session(graph=g) as sess: - out_cond = self._createCond("cond") + cond_output, _ = self._createCond("cond") run_options = config_pb2.RunOptions(output_partition_graphs=True) run_metadata = config_pb2.RunMetadata() - sess.run(out_cond, options=run_options, run_metadata=run_metadata) + sess.run(cond_output, options=run_options, run_metadata=run_metadata) # If lowering was enabled, there should be a `Switch` node switch_found = any( @@ -634,17 +641,18 @@ class CondV2Test(test.TestCase): self.assertFalse(if_found, "An `If` op was found, but it should be lowered.") + @test_util.run_deprecated_v1 def testLoweringDisabledInXLA(self): with self.session(graph=ops.Graph()) as sess: # Build the cond_v2 in an XLA context xla_context = control_flow_ops.XLAControlFlowContext() xla_context.Enter() - out_cond = self._createCond("cond") + cond_output, _ = self._createCond("cond") xla_context.Exit() run_options = config_pb2.RunOptions(output_partition_graphs=True) run_metadata = config_pb2.RunMetadata() - sess.run(out_cond, options=run_options, run_metadata=run_metadata) + sess.run(cond_output, options=run_options, run_metadata=run_metadata) # Lowering disabled in XLA, there should be no `Switch` node switch_found = any( @@ -666,6 +674,110 @@ class CondV2Test(test.TestCase): if_found, "An `If` op was not found, but the graph should not be lowered.") + @test_util.run_deprecated_v1 + def testLoweringDisabledWithSingleThreadedExecutorContext(self): + with self.session(graph=ops.Graph()) as sess: + @function.defun + def _add_cond(x): + return cond_v2.cond_v2( + constant_op.constant(True, name="pred"), + lambda: x, + lambda: x + 1) + + x = array_ops.placeholder(shape=None, dtype=dtypes.float32) + with context.function_executor_type("SINGLE_THREADED_EXECUTOR"): + out_cond = _add_cond(x) + + # The fact that sess.run() succeeds means lowering is disabled, because + # the single threaded executor does not support cond v1 ops. + sess.run(out_cond, feed_dict={x: 1.0}) + + @test_util.enable_control_flow_v2 + def testStructuredOutputs(self): + x = constant_op.constant(1.0, name="x") + y = constant_op.constant(3.0, name="y") + + def true_fn(): + return ((x * y,), y) + + def false_fn(): + return ((x,), y * 3.0) + + output = control_flow_ops.cond( + constant_op.constant(False), true_fn, false_fn) + self.assertEqual(self.evaluate(output[0][0]), 1.) + self.assertEqual(self.evaluate(output[1]), 9.) + + @test_util.enable_control_flow_v2 + @test_util.run_deprecated_v1 + def testRaisesOutputStructuresMismatch(self): + x = constant_op.constant(1.0, name="x") + y = constant_op.constant(3.0, name="y") + + def true_fn(): + return x * y, y + + def false_fn(): + return ((x,), y * 3.0) + + with self.assertRaisesRegexp( + ValueError, "Outputs of true_fn and false_fn must" + " have the same structure"): + control_flow_ops.cond(constant_op.constant(False), true_fn, false_fn) + + @test_util.enable_control_flow_v2 + def testCondAndTensorArray(self): + x = math_ops.range(-5, 5) + output = tensor_array_ops.TensorArray(dtype=dtypes.int32, size=x.shape[0]) + + def loop_body(i, output): + + def if_true(): + return output.write(i, x[i]**2) + + def if_false(): + return output.write(i, x[i]) + + output = control_flow_ops.cond(x[i] > 0, if_true, if_false) + return i + 1, output + + _, output = control_flow_ops.while_loop( + lambda i, arr: i < x.shape[0], + loop_body, + loop_vars=(constant_op.constant(0), output)) + output_t = output.stack() + self.assertAllEqual( + self.evaluate(output_t), [-5, -4, -3, -2, -1, 0, 1, 4, 9, 16]) + + @test_util.enable_control_flow_v2 + def testCondAndTensorArrayInDefun(self): + + @function.defun + def f(): + x = math_ops.range(-5, 5) + output = tensor_array_ops.TensorArray(dtype=dtypes.int32, size=x.shape[0]) + + def loop_body(i, output): + + def if_true(): + return output.write(i, x[i]**2) + + def if_false(): + return output.write(i, x[i]) + + output = control_flow_ops.cond(x[i] > 0, if_true, if_false) + return i + 1, output + + _, output = control_flow_ops.while_loop( + lambda i, arr: i < x.shape[0], + loop_body, + loop_vars=(constant_op.constant(0), output)) + return output.stack() + + output_t = f() + self.assertAllEqual( + self.evaluate(output_t), [-5, -4, -3, -2, -1, 0, 1, 4, 9, 16]) + class CondV2CollectionTest(test.TestCase): diff --git a/tensorflow/python/kernel_tests/conditional_accumulator_test.py b/tensorflow/python/kernel_tests/conditional_accumulator_test.py index 97ab23fe49..5847e4639b 100644 --- a/tensorflow/python/kernel_tests/conditional_accumulator_test.py +++ b/tensorflow/python/kernel_tests/conditional_accumulator_test.py @@ -26,6 +26,7 @@ from tensorflow.python.framework import dtypes as dtypes_lib from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import math_ops @@ -79,11 +80,13 @@ class ConditionalAccumulatorTest(test.TestCase): attr { key: 'reduction_type' value {s: 'MEAN'} } """, q.accumulator_ref.op.node_def) + @test_util.run_deprecated_v1 def testAccumulatorSizeEmpty(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator(dtypes_lib.float32, name="Q") self.assertEqual(q.num_accumulated().eval(), 0) + @test_util.run_deprecated_v1 def testAccumulatorSetGlobalStep(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -91,6 +94,7 @@ class ConditionalAccumulatorTest(test.TestCase): set_global_step_op = q.set_global_step(1) set_global_step_op.run() + @test_util.run_deprecated_v1 def testAccumulatorApplyGradFloat32(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -98,6 +102,7 @@ class ConditionalAccumulatorTest(test.TestCase): accum_op = q.apply_grad((10.0,)) accum_op.run() + @test_util.run_deprecated_v1 def testDtypes(self): with self.cached_session() as sess: dtypes = [dtypes_lib.float16, dtypes_lib.float32, dtypes_lib.float64] @@ -111,10 +116,11 @@ class ConditionalAccumulatorTest(test.TestCase): for e in elems: q.apply_grad((e,)).run() - result = sess.run(q.take_grad(1)) + result = self.evaluate(q.take_grad(1)) self.assertEqual(sum(elems) / len(elems), result) + @test_util.run_deprecated_v1 def testAccumulatorMultipleAccumulators(self): with self.cached_session(): q_f32_0 = data_flow_ops.ConditionalAccumulator( @@ -134,6 +140,7 @@ class ConditionalAccumulatorTest(test.TestCase): result = accums[i].take_grad(1).eval() self.assertEqual(result, i + 10.0) + @test_util.run_deprecated_v1 def testAccumulatorApplyAndTakeGradWithShape(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -149,12 +156,13 @@ class ConditionalAccumulatorTest(test.TestCase): accum_op.run() is_all_equal = True - val = takeg_t.eval() + val = self.evaluate(takeg_t) for i in range(len(val)): for j in range(len(val[i])): is_all_equal &= (val[i][j] == elems_ave[i][j]) self.assertTrue(is_all_equal) + @test_util.run_deprecated_v1 def testAccumulatorApplyGradWithWrongShape(self): q = data_flow_ops.ConditionalAccumulator( dtypes_lib.float32, name="Q", shape=(3, 2)) @@ -165,6 +173,7 @@ class ConditionalAccumulatorTest(test.TestCase): with self.assertRaises(ValueError): q.apply_grad([[1.0], [2.0], [3.0]]) + @test_util.run_deprecated_v1 def testAccumulatorDynamicShape(self): with self.cached_session() as sess: q = data_flow_ops.ConditionalAccumulator( @@ -184,12 +193,13 @@ class ConditionalAccumulatorTest(test.TestCase): sess.run(accum_op, feed_dict={x: elem}) is_all_equal = True - val = takeg_t.eval() + val = self.evaluate(takeg_t) for i in range(len(val)): for j in range(len(val[i])): is_all_equal &= (val[i][j] == elems_ave[i][j]) self.assertTrue(is_all_equal) + @test_util.run_deprecated_v1 def testAccumulatorWrongDynamicShape(self): with self.cached_session() as sess: q = data_flow_ops.ConditionalAccumulator( @@ -208,6 +218,7 @@ class ConditionalAccumulatorTest(test.TestCase): with self.assertRaises(errors_impl.InvalidArgumentError): sess.run(accum_op, feed_dict={x: [[1.0], [2.0], [3.0]]}) + @test_util.run_deprecated_v1 def testAccumulatorSizeAfterApplyGrad(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -219,6 +230,7 @@ class ConditionalAccumulatorTest(test.TestCase): accum_op.run() self.assertEqual(q.num_accumulated().eval(), 2) + @test_util.run_deprecated_v1 def testAccumulatorSizeAfterApplyGradAndTakeGrad(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -247,6 +259,7 @@ class ConditionalAccumulatorTest(test.TestCase): extract_t.op.run() self.assertEqual(q.num_accumulated().eval(), 0) + @test_util.run_deprecated_v1 def testAccumulatorTakeGradMean(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -259,7 +272,7 @@ class ConditionalAccumulatorTest(test.TestCase): for accum_op in accum_ops: accum_op.run() - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(15.0, val) accum_ops = [q.apply_grad((x,), local_step=1) for x in elems] @@ -268,9 +281,10 @@ class ConditionalAccumulatorTest(test.TestCase): for accum_op in accum_ops: accum_op.run() - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(15.0, val) + @test_util.run_deprecated_v1 def testAccumulatorTakeGradSum(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -286,7 +300,7 @@ class ConditionalAccumulatorTest(test.TestCase): for accum_op in accum_ops: accum_op.run() - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(30.0, val) accum_ops = [q.apply_grad((x,), local_step=1) for x in elems] @@ -295,9 +309,10 @@ class ConditionalAccumulatorTest(test.TestCase): for accum_op in accum_ops: accum_op.run() - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(30.0, val) + @test_util.run_deprecated_v1 def testAccumulatorTakeGradInvalidReductionType(self): with self.assertRaises(ValueError): data_flow_ops.ConditionalAccumulator( @@ -306,6 +321,7 @@ class ConditionalAccumulatorTest(test.TestCase): shape=tensor_shape.TensorShape([1]), reduction_type="Invalid") + @test_util.run_deprecated_v1 def testAccumulatorInvalidTakeGrad(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -319,8 +335,9 @@ class ConditionalAccumulatorTest(test.TestCase): accum_op.run() with self.assertRaises(errors_impl.InvalidArgumentError): - takeg_t.eval() + self.evaluate(takeg_t) + @test_util.run_deprecated_v1 def testAccumulatorRepeatedTakeGradMean(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -334,7 +351,7 @@ class ConditionalAccumulatorTest(test.TestCase): for accum_op in accum_ops: accum_op.run() - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(elems_ave, val) elems = [20.0, 30.0] @@ -345,9 +362,10 @@ class ConditionalAccumulatorTest(test.TestCase): for accum_op in accum_ops: accum_op.run() - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(elems_ave + 0.0, val) + @test_util.run_deprecated_v1 def testAccumulatorRepeatedTakeGradSum(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -364,7 +382,7 @@ class ConditionalAccumulatorTest(test.TestCase): for accum_op in accum_ops: accum_op.run() - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(elems_sum, val) elems = [20.0, 30.0] @@ -375,9 +393,10 @@ class ConditionalAccumulatorTest(test.TestCase): for accum_op in accum_ops: accum_op.run() - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(elems_sum, val) + @test_util.run_deprecated_v1 def testAccumulatorIncrementGlobalStep(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -392,8 +411,9 @@ class ConditionalAccumulatorTest(test.TestCase): variables.global_variables_initializer().run() for _ in range(3): set_global_step_op.run() - inc_global_step.eval() + self.evaluate(inc_global_step) + @test_util.run_deprecated_v1 def testAccumulatorSetGlobalStepPreventsAccumulation(self): with self.cached_session(): q = data_flow_ops.ConditionalAccumulator( @@ -410,11 +430,12 @@ class ConditionalAccumulatorTest(test.TestCase): accum_op.run() takeg_t = q.take_grad(1) - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(0.0 + sum(x for x in local_steps if x >= ls) / sum(1 for x in local_steps if x >= ls), val) + @test_util.run_deprecated_v1 def testParallelApplyGrad(self): with self.cached_session() as sess: q = data_flow_ops.ConditionalAccumulator( @@ -424,7 +445,7 @@ class ConditionalAccumulatorTest(test.TestCase): takeg_t = q.take_grad(1) def apply_grad(accum_op): - sess.run(accum_op) + self.evaluate(accum_op) threads = [ self.checkedThread( @@ -436,10 +457,11 @@ class ConditionalAccumulatorTest(test.TestCase): for thread in threads: thread.join() - val = takeg_t.eval() + val = self.evaluate(takeg_t) self.assertEqual(val, sum(elems) / len(elems)) + @test_util.run_deprecated_v1 def testParallelTakeGrad(self): with self.cached_session() as sess: q = data_flow_ops.ConditionalAccumulator( @@ -451,14 +473,14 @@ class ConditionalAccumulatorTest(test.TestCase): def apply_grad(): for accum_op in accum_ops: time.sleep(1.0) - sess.run(accum_op) + self.evaluate(accum_op) apply_grad_thread = self.checkedThread(target=apply_grad) results = [] def take_grad(): - results.append(sess.run(takeg_t)) + results.append(self.evaluate(takeg_t)) threads = [self.checkedThread(target=take_grad) for _ in range(10)] @@ -472,6 +494,7 @@ class ConditionalAccumulatorTest(test.TestCase): self.assertItemsEqual(elems, results) + @test_util.run_deprecated_v1 def testAccumulatorApplyAndBlockingTake(self): with self.cached_session() as sess: q = data_flow_ops.ConditionalAccumulator( @@ -485,12 +508,12 @@ class ConditionalAccumulatorTest(test.TestCase): def apply_grad(): time.sleep(1.0) for accum_op in accum_ops: - sess.run(accum_op) + self.evaluate(accum_op) return_array = [] def take_grad(): - return_array.append(sess.run(takeg_t)) + return_array.append(self.evaluate(takeg_t)) accum_thread = self.checkedThread(target=apply_grad) takeg_thread = self.checkedThread(target=take_grad) @@ -503,8 +526,9 @@ class ConditionalAccumulatorTest(test.TestCase): def _blocking_takeg(self, sess, takeg_op): with self.assertRaisesOpError("was cancelled"): - sess.run(takeg_op) + self.evaluate(takeg_op) + @test_util.run_deprecated_v1 def testAccumulatorCancel(self): with self.cached_session() as sess: q = data_flow_ops.ConditionalAccumulator( diff --git a/tensorflow/python/kernel_tests/confusion_matrix_test.py b/tensorflow/python/kernel_tests/confusion_matrix_test.py index bc24345261..ae13c8e32e 100644 --- a/tensorflow/python/kernel_tests/confusion_matrix_test.py +++ b/tensorflow/python/kernel_tests/confusion_matrix_test.py @@ -71,9 +71,11 @@ class ConfusionMatrixTest(test.TestCase): self._testConfMatrix(labels=labels, predictions=predictions, truth=truth) + @test_util.run_deprecated_v1 def testInt32Basic(self): self._testBasic(dtype=np.int32) + @test_util.run_deprecated_v1 def testInt64Basic(self): self._testBasic(dtype=np.int64) @@ -111,9 +113,11 @@ class ConfusionMatrixTest(test.TestCase): self.assertEqual(cm_out.dtype, np_dtype) self.assertAllClose(cm_out, truth, atol=1e-10) + @test_util.run_deprecated_v1 def testOnTensors_int32(self): self._testConfMatrixOnTensors(dtypes.int32, np.int32) + @test_util.run_deprecated_v1 def testOnTensors_int64(self): self._testConfMatrixOnTensors(dtypes.int64, np.int64) @@ -133,9 +137,11 @@ class ConfusionMatrixTest(test.TestCase): self._testConfMatrix(labels=labels, predictions=predictions, truth=truth) + @test_util.run_deprecated_v1 def testInt32DifferentLabels(self, dtype=np.int32): self._testDifferentLabelsInPredictionAndTarget(dtype) + @test_util.run_deprecated_v1 def testInt64DifferentLabels(self, dtype=np.int64): self._testDifferentLabelsInPredictionAndTarget(dtype) @@ -155,12 +161,15 @@ class ConfusionMatrixTest(test.TestCase): self._testConfMatrix(labels=labels, predictions=predictions, truth=truth) + @test_util.run_deprecated_v1 def testInt32MultipleLabels(self, dtype=np.int32): self._testMultipleLabels(dtype) + @test_util.run_deprecated_v1 def testInt64MultipleLabels(self, dtype=np.int64): self._testMultipleLabels(dtype) + @test_util.run_deprecated_v1 def testWeighted(self): labels = np.arange(5, dtype=np.int32) predictions = np.arange(5, dtype=np.int32) @@ -177,6 +186,7 @@ class ConfusionMatrixTest(test.TestCase): self._testConfMatrix( labels=labels, predictions=predictions, weights=weights, truth=truth) + @test_util.run_deprecated_v1 def testLabelsTooLarge(self): labels = np.asarray([1, 1, 0, 3, 5], dtype=np.int32) predictions = np.asarray([2, 1, 0, 2, 2], dtype=np.int32) @@ -191,6 +201,7 @@ class ConfusionMatrixTest(test.TestCase): self._testConfMatrix( labels=labels, predictions=predictions, num_classes=3, truth=None) + @test_util.run_deprecated_v1 def testPredictionsTooLarge(self): labels = np.asarray([1, 1, 0, 2, 2], dtype=np.int32) predictions = np.asarray([2, 1, 0, 3, 5], dtype=np.int32) @@ -205,6 +216,7 @@ class ConfusionMatrixTest(test.TestCase): self._testConfMatrix( labels=labels, predictions=predictions, num_classes=3, truth=None) + @test_util.run_deprecated_v1 def testInvalidRank_predictionsTooBig(self): labels = np.asarray([1, 2, 3]) predictions = np.asarray([[1, 2, 3]]) @@ -212,6 +224,7 @@ class ConfusionMatrixTest(test.TestCase): confusion_matrix.confusion_matrix, predictions, labels) + @test_util.run_deprecated_v1 def testInvalidRank_predictionsTooSmall(self): labels = np.asarray([[1, 2, 3]]) predictions = np.asarray([1, 2, 3]) @@ -219,6 +232,7 @@ class ConfusionMatrixTest(test.TestCase): confusion_matrix.confusion_matrix, predictions, labels) + @test_util.run_deprecated_v1 def testInputDifferentSize(self): labels = np.asarray([1, 2]) predictions = np.asarray([1, 2, 3]) @@ -232,7 +246,7 @@ class ConfusionMatrixTest(test.TestCase): with self.cached_session(): cm = confusion_matrix.confusion_matrix( labels, predictions, dtype=dtypes.int32) - tf_cm = cm.eval() + tf_cm = self.evaluate(cm) self.assertEqual(tf_cm.dtype, np.int32) def testOutputIsInt64(self): @@ -241,12 +255,13 @@ class ConfusionMatrixTest(test.TestCase): with self.cached_session(): cm = confusion_matrix.confusion_matrix( labels, predictions, dtype=dtypes.int64) - tf_cm = cm.eval() + tf_cm = self.evaluate(cm) self.assertEqual(tf_cm.dtype, np.int64) class RemoveSqueezableDimensionsTest(test.TestCase): + @test_util.run_deprecated_v1 def testBothScalarShape(self): label_values = 1.0 prediction_values = 0.0 @@ -261,8 +276,8 @@ class RemoveSqueezableDimensionsTest(test.TestCase): labels_placeholder, predictions_placeholder)) with self.cached_session(): - self.assertAllEqual(label_values, static_labels.eval()) - self.assertAllEqual(prediction_values, static_predictions.eval()) + self.assertAllEqual(label_values, self.evaluate(static_labels)) + self.assertAllEqual(prediction_values, self.evaluate(static_predictions)) feed_dict = { labels_placeholder: label_values, predictions_placeholder: prediction_values @@ -272,6 +287,7 @@ class RemoveSqueezableDimensionsTest(test.TestCase): self.assertAllEqual( prediction_values, dynamic_predictions.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testSameShape(self): label_values = np.ones(shape=(2, 3, 1)) prediction_values = np.zeros_like(label_values) @@ -286,8 +302,8 @@ class RemoveSqueezableDimensionsTest(test.TestCase): labels_placeholder, predictions_placeholder)) with self.cached_session(): - self.assertAllEqual(label_values, static_labels.eval()) - self.assertAllEqual(prediction_values, static_predictions.eval()) + self.assertAllEqual(label_values, self.evaluate(static_labels)) + self.assertAllEqual(prediction_values, self.evaluate(static_predictions)) feed_dict = { labels_placeholder: label_values, predictions_placeholder: prediction_values @@ -297,6 +313,7 @@ class RemoveSqueezableDimensionsTest(test.TestCase): self.assertAllEqual( prediction_values, dynamic_predictions.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testSameShapeExpectedRankDiff0(self): label_values = np.ones(shape=(2, 3, 1)) prediction_values = np.zeros_like(label_values) @@ -311,8 +328,8 @@ class RemoveSqueezableDimensionsTest(test.TestCase): labels_placeholder, predictions_placeholder, expected_rank_diff=0)) with self.cached_session(): - self.assertAllEqual(label_values, static_labels.eval()) - self.assertAllEqual(prediction_values, static_predictions.eval()) + self.assertAllEqual(label_values, self.evaluate(static_labels)) + self.assertAllEqual(prediction_values, self.evaluate(static_predictions)) feed_dict = { labels_placeholder: label_values, predictions_placeholder: prediction_values @@ -322,6 +339,7 @@ class RemoveSqueezableDimensionsTest(test.TestCase): self.assertAllEqual( prediction_values, dynamic_predictions.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testSqueezableLabels(self): label_values = np.ones(shape=(2, 3, 1)) prediction_values = np.zeros(shape=(2, 3)) @@ -337,8 +355,8 @@ class RemoveSqueezableDimensionsTest(test.TestCase): expected_label_values = np.reshape(label_values, newshape=(2, 3)) with self.cached_session(): - self.assertAllEqual(expected_label_values, static_labels.eval()) - self.assertAllEqual(prediction_values, static_predictions.eval()) + self.assertAllEqual(expected_label_values, self.evaluate(static_labels)) + self.assertAllEqual(prediction_values, self.evaluate(static_predictions)) feed_dict = { labels_placeholder: label_values, predictions_placeholder: prediction_values @@ -348,6 +366,7 @@ class RemoveSqueezableDimensionsTest(test.TestCase): self.assertAllEqual( prediction_values, dynamic_predictions.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testSqueezableLabelsExpectedRankDiffPlus1(self): label_values = np.ones(shape=(2, 3, 1)) prediction_values = np.zeros(shape=(2, 3, 5)) @@ -363,8 +382,8 @@ class RemoveSqueezableDimensionsTest(test.TestCase): expected_label_values = np.reshape(label_values, newshape=(2, 3)) with self.cached_session(): - self.assertAllEqual(expected_label_values, static_labels.eval()) - self.assertAllEqual(prediction_values, static_predictions.eval()) + self.assertAllEqual(expected_label_values, self.evaluate(static_labels)) + self.assertAllEqual(prediction_values, self.evaluate(static_predictions)) feed_dict = { labels_placeholder: label_values, predictions_placeholder: prediction_values @@ -374,6 +393,7 @@ class RemoveSqueezableDimensionsTest(test.TestCase): self.assertAllEqual( prediction_values, dynamic_predictions.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testSqueezablePredictions(self): label_values = np.ones(shape=(2, 3)) prediction_values = np.zeros(shape=(2, 3, 1)) @@ -389,8 +409,9 @@ class RemoveSqueezableDimensionsTest(test.TestCase): expected_prediction_values = np.reshape(prediction_values, newshape=(2, 3)) with self.cached_session(): - self.assertAllEqual(label_values, static_labels.eval()) - self.assertAllEqual(expected_prediction_values, static_predictions.eval()) + self.assertAllEqual(label_values, self.evaluate(static_labels)) + self.assertAllEqual(expected_prediction_values, + self.evaluate(static_predictions)) feed_dict = { labels_placeholder: label_values, predictions_placeholder: prediction_values @@ -401,6 +422,7 @@ class RemoveSqueezableDimensionsTest(test.TestCase): expected_prediction_values, dynamic_predictions.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testSqueezablePredictionsExpectedRankDiffMinus1(self): label_values = np.ones(shape=(2, 3, 5)) prediction_values = np.zeros(shape=(2, 3, 1)) @@ -416,8 +438,9 @@ class RemoveSqueezableDimensionsTest(test.TestCase): expected_prediction_values = np.reshape(prediction_values, newshape=(2, 3)) with self.cached_session(): - self.assertAllEqual(label_values, static_labels.eval()) - self.assertAllEqual(expected_prediction_values, static_predictions.eval()) + self.assertAllEqual(label_values, self.evaluate(static_labels)) + self.assertAllEqual(expected_prediction_values, + self.evaluate(static_predictions)) feed_dict = { labels_placeholder: label_values, predictions_placeholder: prediction_values @@ -428,6 +451,7 @@ class RemoveSqueezableDimensionsTest(test.TestCase): expected_prediction_values, dynamic_predictions.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testUnsqueezableLabels(self): label_values = np.ones(shape=(2, 3, 2)) prediction_values = np.zeros(shape=(2, 3)) @@ -453,6 +477,7 @@ class RemoveSqueezableDimensionsTest(test.TestCase): self.assertAllEqual( prediction_values, dynamic_predictions.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testUnsqueezablePredictions(self): label_values = np.ones(shape=(2, 3)) prediction_values = np.zeros(shape=(2, 3, 2)) diff --git a/tensorflow/python/kernel_tests/constant_op_test.py b/tensorflow/python/kernel_tests/constant_op_test.py index 38b8c0c146..583082c2aa 100644 --- a/tensorflow/python/kernel_tests/constant_op_test.py +++ b/tensorflow/python/kernel_tests/constant_op_test.py @@ -70,6 +70,7 @@ class ConstantTest(test.TestCase): with self.assertRaises(TypeError): constant_op.constant(dtypes_lib.string, "[,]") + @test_util.run_deprecated_v1 def testBFloat16(self): bfloat16 = dtypes_lib.bfloat16.as_numpy_dtype self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(bfloat16)) @@ -77,36 +78,42 @@ class ConstantTest(test.TestCase): np.random.normal(size=30).reshape([2, 3, 5]).astype(bfloat16)) self._testAll(np.empty((2, 0, 5)).astype(bfloat16)) + @test_util.run_deprecated_v1 def testHalf(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.float16)) self._testAll( np.random.normal(size=30).reshape([2, 3, 5]).astype(np.float16)) self._testAll(np.empty((2, 0, 5)).astype(np.float16)) + @test_util.run_deprecated_v1 def testFloat(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.float32)) self._testAll( np.random.normal(size=30).reshape([2, 3, 5]).astype(np.float32)) self._testAll(np.empty((2, 0, 5)).astype(np.float32)) + @test_util.run_deprecated_v1 def testDouble(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.float64)) self._testAll( np.random.normal(size=30).reshape([2, 3, 5]).astype(np.float64)) self._testAll(np.empty((2, 0, 5)).astype(np.float64)) + @test_util.run_deprecated_v1 def testInt32(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.int32)) self._testAll((100 * np.random.normal(size=30)).reshape([2, 3, 5]).astype( np.int32)) self._testAll(np.empty((2, 0, 5)).astype(np.int32)) + @test_util.run_deprecated_v1 def testInt64(self): self._testAll(np.arange(-15, 15).reshape([2, 3, 5]).astype(np.int64)) self._testAll((100 * np.random.normal(size=30)).reshape([2, 3, 5]).astype( np.int64)) self._testAll(np.empty((2, 0, 5)).astype(np.int64)) + @test_util.run_deprecated_v1 def testComplex64(self): self._testAll( np.complex(1, 2) * @@ -116,6 +123,7 @@ class ConstantTest(test.TestCase): np.random.normal(size=30).reshape([2, 3, 5]).astype(np.complex64)) self._testAll(np.empty((2, 0, 5)).astype(np.complex64)) + @test_util.run_deprecated_v1 def testComplex128(self): self._testAll( np.complex(1, 2) * @@ -125,12 +133,14 @@ class ConstantTest(test.TestCase): np.random.normal(size=30).reshape([2, 3, 5]).astype(np.complex128)) self._testAll(np.empty((2, 0, 5)).astype(np.complex128)) + @test_util.run_deprecated_v1 def testString(self): self._testCpu( np.array([compat.as_bytes(str(x)) for x in np.arange(-15, 15)]).reshape( [2, 3, 5])) self._testCpu(np.empty((2, 0, 5)).astype(np.str_)) + @test_util.run_deprecated_v1 def testVariant(self): # TODO(ebrevdo): Re-enable use_gpu=True once non-DMA Variant # copying between CPU and GPU is supported. @@ -161,6 +171,7 @@ class ConstantTest(test.TestCase): message="Variant storing an int, decoded const value:").op logging_const_op.run() + @test_util.run_deprecated_v1 def testStringWithNulls(self): with self.cached_session(): val = ops.convert_to_tensor(b"\0\0\0\0").eval() @@ -219,16 +230,28 @@ class ConstantTest(test.TestCase): def testShapeInconsistent(self): with ops.Graph().as_default(): - c = constant_op.constant([1, 2, 3, 4, 5, 6, 7], shape=[10]) + c = constant_op.constant_v1([1, 2, 3, 4, 5, 6, 7], shape=[10]) + self.assertEqual(c.get_shape(), [10]) + + with ops.Graph().as_default(): + with self.assertRaisesRegexp( + TypeError, "Expected Tensor's shape"): + c = constant_op.constant([1, 2, 3, 4, 5, 6, 7], shape=[10]) + + def testPromotionShapes(self): + with ops.Graph().as_default(): + c = constant_op.constant([7], shape=[10]) + self.assertEqual(c.get_shape(), [10]) + with ops.Graph().as_default(): + c = constant_op.constant(3, shape=[10]) self.assertEqual(c.get_shape(), [10]) # pylint: disable=g-long-lambda def testShapeWrong(self): with ops.Graph().as_default(): - with self.assertRaisesWithPredicateMatch( - ValueError, - lambda e: ("Too many elements provided. Needed at most 5, " - "but received 7" == str(e))): + with self.assertRaisesRegexp(ValueError, "Too many elements provided."): + constant_op.constant_v1([1, 2, 3, 4, 5, 6, 7], shape=[5]) + with self.assertRaisesRegexp(TypeError, "Expected Tensor's shape"): constant_op.constant([1, 2, 3, 4, 5, 6, 7], shape=[5]) # pylint: enable=g-long-lambda @@ -253,6 +276,7 @@ class ConstantTest(test.TestCase): "GraphDef cannot be larger than 2GB."): g.as_graph_def() + @test_util.run_deprecated_v1 def testSparseValuesRaiseErrors(self): with self.assertRaisesRegexp(ValueError, "setting an array element with a sequence"): @@ -282,29 +306,29 @@ class AsTensorTest(test.TestCase): with self.cached_session(): x = ops.convert_to_tensor(tensor_shape.TensorShape([])) self.assertEqual(dtypes_lib.int32, x.dtype) - self.assertAllEqual([], x.eval()) + self.assertAllEqual([], self.evaluate(x)) x = ops.convert_to_tensor(tensor_shape.TensorShape([1, 2, 3])) self.assertEqual(dtypes_lib.int32, x.dtype) - self.assertAllEqual([1, 2, 3], x.eval()) + self.assertAllEqual([1, 2, 3], self.evaluate(x)) x = ops.convert_to_tensor(tensor_shape.TensorShape([2**31-1, 2, 3])) self.assertEqual(dtypes_lib.int32, x.dtype) - self.assertAllEqual([2**31-1, 2, 3], x.eval()) + self.assertAllEqual([2**31 - 1, 2, 3], self.evaluate(x)) x = ops.convert_to_tensor(tensor_shape.TensorShape([2**31-1, 2, 3]), dtype=dtypes_lib.int32) self.assertEqual(dtypes_lib.int32, x.dtype) - self.assertAllEqual([2**31-1, 2, 3], x.eval()) + self.assertAllEqual([2**31 - 1, 2, 3], self.evaluate(x)) x = ops.convert_to_tensor(tensor_shape.TensorShape([2**31, 2, 3])) self.assertEqual(dtypes_lib.int64, x.dtype) - self.assertAllEqual([2**31, 2, 3], x.eval()) + self.assertAllEqual([2**31, 2, 3], self.evaluate(x)) x = ops.convert_to_tensor(tensor_shape.TensorShape([2**31, 2, 3]), dtype=dtypes_lib.int64) self.assertEqual(dtypes_lib.int64, x.dtype) - self.assertAllEqual([2**31, 2, 3], x.eval()) + self.assertAllEqual([2**31, 2, 3], self.evaluate(x)) with self.assertRaisesRegexp( ValueError, "a dimension is too large .2147483648."): @@ -314,11 +338,11 @@ class AsTensorTest(test.TestCase): x = ops.convert_to_tensor( tensor_shape.TensorShape([1, 2, 3]), dtype=dtypes_lib.int64) self.assertEqual(dtypes_lib.int64, x.dtype) - self.assertAllEqual([1, 2, 3], x.eval()) + self.assertAllEqual([1, 2, 3], self.evaluate(x)) x = array_ops.reshape( array_ops.zeros([6]), tensor_shape.TensorShape([2, 3])) - self.assertAllEqual([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], x.eval()) + self.assertAllEqual([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], self.evaluate(x)) with self.assertRaisesRegexp(ValueError, "partially known"): ops.convert_to_tensor(tensor_shape.TensorShape(None)) @@ -330,16 +354,17 @@ class AsTensorTest(test.TestCase): ops.convert_to_tensor( tensor_shape.TensorShape([1, 2, 3]), dtype=dtypes_lib.float32) + @test_util.run_deprecated_v1 def testAsTensorForDimensionInput(self): with self.cached_session(): x = ops.convert_to_tensor(tensor_shape.TensorShape([1, 2, 3])[1]) self.assertEqual(dtypes_lib.int32, x.dtype) - self.assertAllEqual(2, x.eval()) + self.assertAllEqual(2, self.evaluate(x)) x = ops.convert_to_tensor( tensor_shape.TensorShape([1, 2, 3])[1], dtype=dtypes_lib.int64) self.assertEqual(dtypes_lib.int64, x.dtype) - self.assertAllEqual(2, x.eval()) + self.assertAllEqual(2, self.evaluate(x)) shape = tensor_shape.TensorShape(None) if shape._v2_behavior: @@ -372,7 +397,7 @@ class ZerosTest(test.TestCase): with self.cached_session(): ret = array_ops.zeros(shape) self.assertEqual(shape, ret.get_shape()) - return ret.eval() + return self.evaluate(ret) def testConst(self): self.assertTrue( @@ -383,7 +408,7 @@ class ZerosTest(test.TestCase): self.assertEqual(0, self._Zeros(())) with self.cached_session(): scalar = array_ops.zeros(constant_op.constant([], dtype=dtypes_lib.int32)) - self.assertEqual(0, scalar.eval()) + self.assertEqual(0, self.evaluate(scalar)) def testDynamicSizes(self): np_ans = np.array([[0] * 3] * 2) @@ -392,11 +417,12 @@ class ZerosTest(test.TestCase): d = array_ops.fill([2, 3], 12., name="fill") # Constructs a tensor of zeros of the same dimensions as "d". z = array_ops.zeros(array_ops.shape(d)) - out = z.eval() + out = self.evaluate(z) self.assertAllEqual(np_ans, out) self.assertShapeEqual(np_ans, d) self.assertShapeEqual(np_ans, z) + @test_util.run_deprecated_v1 def testDtype(self): with self.cached_session(): d = array_ops.fill([2, 3], 12., name="fill") @@ -420,13 +446,13 @@ class ZerosTest(test.TestCase): z = array_ops.zeros([2, 3], dtype=dtype) self.assertEqual(z.dtype, dtype) self.assertEqual([2, 3], z.get_shape()) - z_value = z.eval() + z_value = self.evaluate(z) self.assertFalse(np.any(z_value)) self.assertEqual((2, 3), z_value.shape) z = array_ops.zeros(array_ops.shape(d), dtype=dtype) self.assertEqual(z.dtype, dtype) self.assertEqual([2, 3], z.get_shape()) - z_value = z.eval() + z_value = self.evaluate(z) self.assertFalse(np.any(z_value)) self.assertEqual((2, 3), z_value.shape) @@ -465,6 +491,7 @@ class ZerosLikeTest(test.TestCase): self.assertFalse(np.any(z_value)) self.assertEqual((2, 3), z_value.shape) + @test_util.run_deprecated_v1 def testZerosLikeCPU(self): for dtype in [ dtypes_lib.half, dtypes_lib.float32, dtypes_lib.float64, @@ -475,6 +502,7 @@ class ZerosLikeTest(test.TestCase): self._compareZeros(dtype, fully_defined_shape=False, use_gpu=False) self._compareZeros(dtype, fully_defined_shape=True, use_gpu=False) + @test_util.run_deprecated_v1 def testZerosLikeGPU(self): for dtype in [ dtypes_lib.half, dtypes_lib.float32, dtypes_lib.float64, @@ -484,11 +512,13 @@ class ZerosLikeTest(test.TestCase): self._compareZeros(dtype, fully_defined_shape=False, use_gpu=True) self._compareZeros(dtype, fully_defined_shape=True, use_gpu=True) + @test_util.run_deprecated_v1 def testZerosLikePartialShape(self): d = array_ops.placeholder(dtypes_lib.float32, shape=[None, 4, None]) z = array_ops.zeros_like(d) self.assertEqual(d.get_shape().as_list(), z.get_shape().as_list()) + @test_util.run_deprecated_v1 def testZerosLikeDtype(self): # Make sure zeros_like works even for dtypes that cannot be cast between with self.cached_session(): @@ -502,6 +532,7 @@ class ZerosLikeTest(test.TestCase): self.assertEqual(y.shape, shape) self.assertAllEqual(y, np.zeros(shape, dtype=out_type)) + @test_util.run_deprecated_v1 def testZerosLikeVariant(self): # TODO(ebrevdo): Re-enable use_gpu=True once non-DMA Variant # copying between CPU and GPU is supported AND we register a @@ -538,7 +569,7 @@ class OnesTest(test.TestCase): with self.cached_session(): ret = array_ops.ones(shape) self.assertEqual(shape, ret.get_shape()) - return ret.eval() + return self.evaluate(ret) def testConst(self): self.assertTrue(np.array_equal(self._Ones([2, 3]), np.array([[1] * 3] * 2))) @@ -548,7 +579,7 @@ class OnesTest(test.TestCase): self.assertEqual(1, self._Ones(())) with self.cached_session(): scalar = array_ops.ones(constant_op.constant([], dtype=dtypes_lib.int32)) - self.assertEqual(1, scalar.eval()) + self.assertEqual(1, self.evaluate(scalar)) def testDynamicSizes(self): np_ans = np.array([[1] * 3] * 2) @@ -557,11 +588,12 @@ class OnesTest(test.TestCase): d = array_ops.fill([2, 3], 12., name="fill") # Constructs a tensor of ones of the same dimensions as "d". z = array_ops.ones(array_ops.shape(d)) - out = z.eval() + out = self.evaluate(z) self.assertAllEqual(np_ans, out) self.assertShapeEqual(np_ans, d) self.assertShapeEqual(np_ans, z) + @test_util.run_deprecated_v1 def testAutoPack(self): with self.cached_session(): h = array_ops.placeholder(dtypes_lib.int32, shape=[]) @@ -570,6 +602,7 @@ class OnesTest(test.TestCase): out = z.eval(feed_dict={h: 4, w: 16}) self.assertAllEqual(out, np.array([[1] * 16] * 4)) + @test_util.run_deprecated_v1 def testDtype(self): with self.cached_session(): d = array_ops.fill([2, 3], 12., name="fill") @@ -617,12 +650,13 @@ class OnesLikeTest(test.TestCase): z_var = array_ops.ones_like(d) # Test that the type is correct self.assertEqual(z_var.dtype, dtype) - z_value = z_var.eval() + z_value = self.evaluate(z_var) # Test that the value is correct self.assertTrue(np.array_equal(z_value, np.array([[1] * 3] * 2))) self.assertEqual([2, 3], z_var.get_shape()) + @test_util.run_deprecated_v1 def testOnesLikePartialShape(self): d = array_ops.placeholder(dtypes_lib.float32, shape=[None, 4, None]) z = array_ops.ones_like(d) @@ -634,7 +668,7 @@ class FillTest(test.TestCase): def _compare(self, dims, val, np_ans, use_gpu): with self.cached_session(use_gpu=use_gpu): tf_ans = array_ops.fill(dims, val, name="fill") - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertAllClose(np_ans, out) # Fill does not set the shape. # self.assertShapeEqual(np_ans, tf_ans) @@ -667,12 +701,14 @@ class FillTest(test.TestCase): np_ans = np.array([[0.15 + 0.3j] * 3] * 2).astype(np.complex128) self._compareAll([2, 3], np_ans[0][0], np_ans) + @test_util.run_deprecated_v1 def testFillString(self): np_ans = np.array([[b"yolo"] * 3] * 2) with self.session(use_gpu=False): tf_ans = array_ops.fill([2, 3], np_ans[0][0], name="fill").eval() self.assertAllEqual(np_ans, tf_ans) + @test_util.run_deprecated_v1 def testFillNegative(self): with self.cached_session(): for shape in (-1,), (2, -1), (-1, 2), (-2), (-3): @@ -686,6 +722,7 @@ class FillTest(test.TestCase): with self.assertRaises(errors_impl.InvalidArgumentError): fill_t.eval({dims: shape}) + @test_util.run_deprecated_v1 def testShapeFunctionEdgeCases(self): # Non-vector dimensions. with self.assertRaises(ValueError): @@ -704,6 +741,7 @@ class FillTest(test.TestCase): dtypes_lib.int32, shape=()), 17], 1.0) self.assertEqual([None, 17], f.get_shape().as_list()) + @test_util.run_deprecated_v1 def testGradient(self): with self.cached_session(): in_v = constant_op.constant(5.0) @@ -716,6 +754,7 @@ class FillTest(test.TestCase): class PlaceholderTest(test.TestCase): + @test_util.run_deprecated_v1 def testDtype(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=(10, 10), name="p") @@ -726,8 +765,9 @@ class PlaceholderTest(test.TestCase): with self.assertRaisesOpError( "must feed a value for placeholder tensor 'p' with dtype float"): - p_identity.eval() + self.evaluate(p_identity) + @test_util.run_deprecated_v1 def testShape(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=(10, 10), name="p") @@ -739,12 +779,13 @@ class PlaceholderTest(test.TestCase): with self.assertRaisesOpError( "must feed a value for placeholder tensor 'p' with dtype float and " r"shape \[10,10\]"): - p_identity.eval() + self.evaluate(p_identity) with self.assertRaisesWithPredicateMatch( ValueError, lambda e: "Cannot feed value of shape" in str(e)): p_identity.eval(feed_dict={p: feed_array[:5, :5]}) + @test_util.run_deprecated_v1 def testUnknownShape(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=None, name="p") @@ -757,12 +798,14 @@ class PlaceholderTest(test.TestCase): self.assertAllClose( p_identity.eval(feed_dict={p: feed_array}), feed_array) + @test_util.run_deprecated_v1 def testScalarShape(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=[], name="p") p_identity = array_ops.identity(p) self.assertAllClose(p_identity.eval(feed_dict={p: 5}), 5) + @test_util.run_deprecated_v1 def testPartialShape(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=[None, 3], name="p") @@ -775,6 +818,7 @@ class PlaceholderTest(test.TestCase): ValueError, lambda e: "Cannot feed value of shape" in str(e)): p_identity.eval(feed_dict={p: feed_array[:5, :2]}) + @test_util.run_deprecated_v1 def testPartialShapeWhenNotFed(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.float32, shape=[None, 3], name="p") @@ -783,8 +827,9 @@ class PlaceholderTest(test.TestCase): # Should trigger an operator error, not a shape error. with self.assertRaisesOpError( "must feed a value for placeholder tensor 'p' with dtype float"): - p_identity.eval() + self.evaluate(p_identity) + @test_util.run_deprecated_v1 def testControlDependency(self): with self.cached_session(): p = array_ops.placeholder(dtypes_lib.int32, shape=[], name="p") @@ -794,10 +839,12 @@ class PlaceholderTest(test.TestCase): val = np.array(2).astype(np.int) self.assertEqual(10, d.eval(feed_dict={p: val})) + @test_util.run_deprecated_v1 def testBadShape(self): with self.assertRaises(ValueError): array_ops.placeholder(dtypes_lib.float32, shape=(-1, 10)) + @test_util.run_deprecated_v1 def testTensorStr(self): a = array_ops.placeholder(dtypes_lib.float32, shape=None, name="a") self.assertEqual(" dtype=float32>", repr(a)) @@ -813,6 +860,7 @@ class PlaceholderTest(test.TestCase): self.assertEqual( "", repr(c)) + @test_util.run_deprecated_v1 def testOldGraph(self): # Load graph generated from earlier version of TF where # placeholder shape was not set. @@ -892,36 +940,40 @@ versions { class PlaceholderWithDefaultTest(test.TestCase): + @test_util.run_deprecated_v1 def testFullShape(self): with self.session(force_gpu=test_util.is_gpu_available()): p = array_ops.placeholder_with_default([[2, 2], [2, 2]], shape=[2, 2]) a = array_ops.identity(p) - self.assertAllEqual([[2, 2], [2, 2]], a.eval()) + self.assertAllEqual([[2, 2], [2, 2]], self.evaluate(a)) self.assertAllEqual( [[3, 3], [3, 3]], a.eval(feed_dict={p: [[3, 3], [3, 3]]})) with self.assertRaises(ValueError): a.eval(feed_dict={p: [[6, 6, 6], [6, 6, 6]]}) + @test_util.run_deprecated_v1 def testPartialShape(self): with self.session(force_gpu=test_util.is_gpu_available()): p = array_ops.placeholder_with_default([1, 2, 3], shape=[None]) a = array_ops.identity(p) - self.assertAllEqual([1, 2, 3], a.eval()) + self.assertAllEqual([1, 2, 3], self.evaluate(a)) self.assertAllEqual([3, 37], a.eval(feed_dict={p: [3, 37]})) with self.assertRaises(ValueError): a.eval(feed_dict={p: [[2, 2], [2, 2]]}) + @test_util.run_deprecated_v1 def testNoShape(self): with self.session(force_gpu=test_util.is_gpu_available()): p = array_ops.placeholder_with_default([17], shape=None) a = array_ops.identity(p) - self.assertAllEqual([17], a.eval()) + self.assertAllEqual([17], self.evaluate(a)) self.assertAllEqual([3, 37], a.eval(feed_dict={p: [3, 37]})) self.assertAllEqual( [[3, 3], [3, 3]], a.eval(feed_dict={p: [[3, 3], [3, 3]]})) + @test_util.run_deprecated_v1 def testGradient(self): with self.session(force_gpu=test_util.is_gpu_available()): x = array_ops.placeholder(dtypes_lib.float32, [5, 7]) diff --git a/tensorflow/python/kernel_tests/control_flow_ops_py_test.py b/tensorflow/python/kernel_tests/control_flow_ops_py_test.py index 19b067e449..c80c95da84 100644 --- a/tensorflow/python/kernel_tests/control_flow_ops_py_test.py +++ b/tensorflow/python/kernel_tests/control_flow_ops_py_test.py @@ -139,8 +139,9 @@ class ControlFlowTest(test.TestCase): self.assertTrue(isinstance(v2, ops.Tensor)) variables.global_variables_initializer().run() - self.assertEqual(9, v2.eval()) + self.assertEqual(9, self.evaluate(v2)) + @test_util.run_deprecated_v1 def testRefEnter(self): with self.cached_session(): v = variables.VariableV1(7) @@ -152,8 +153,9 @@ class ControlFlowTest(test.TestCase): v2 = control_flow_ops.with_dependencies([op], enter_v) v3 = control_flow_ops.exit(v2) variables.global_variables_initializer().run() - self.assertEqual(9, v3.eval()) + self.assertEqual(9, self.evaluate(v3)) + @test_util.run_deprecated_v1 def testRefSwitch(self): with self.cached_session(): v = variables.VariableV1(7) @@ -162,7 +164,7 @@ class ControlFlowTest(test.TestCase): v1 = control_flow_ops._SwitchRefOrTensor(v._ref(), p) # pylint: disable=protected-access v2 = state_ops.assign(v1[1], 9) variables.global_variables_initializer().run() - self.assertEqual(9, v2.eval()) + self.assertEqual(9, self.evaluate(v2)) def testEnterMulExit(self): with self.cached_session(): @@ -173,9 +175,10 @@ class ControlFlowTest(test.TestCase): mul_op = math_ops.multiply(enter_data, enter_five) exit_op = control_flow_ops.exit(mul_op) - result = exit_op.eval() + result = self.evaluate(exit_op) self.assertAllEqual(np.array([x * 5 for x in [1, 2, 3, 4, 5, 6]]), result) + @test_util.run_deprecated_v1 def testEnterShapePropagation(self): with self.cached_session(): v = variables.Variable([0.0, 0.0], dtype=dtypes.float32) @@ -214,7 +217,7 @@ class ControlFlowTest(test.TestCase): with self.assertRaisesWithPredicateMatch( errors_impl.InvalidArgumentError, lambda e: "Retval[0] does not have value" in str(e)): - dead_branch.eval() + self.evaluate(dead_branch) def testSwitchMergeLess(self): with self.cached_session(): @@ -225,7 +228,7 @@ class ControlFlowTest(test.TestCase): switch_op = control_flow_ops.switch(data, less_op) merge_op = control_flow_ops.merge(switch_op)[0] - result = merge_op.eval() + result = self.evaluate(merge_op) self.assertAllEqual(np.arange(1, 7), result) def testSwitchMergeAddIdentity(self): @@ -238,7 +241,7 @@ class ControlFlowTest(test.TestCase): id_op = array_ops.identity(switch_op[1]) merge_op = control_flow_ops.merge([add_op, id_op])[0] - result = merge_op.eval() + result = self.evaluate(merge_op) self.assertAllEqual(np.array([x + 1 for x in [1, 2, 3, 4, 5, 6]]), result) def testSwitchMergeAddMul(self): @@ -252,7 +255,7 @@ class ControlFlowTest(test.TestCase): mul_op = math_ops.multiply(switch_op[1], five) merge_op = control_flow_ops.merge([add_op, mul_op])[0] - result = merge_op.eval() + result = self.evaluate(merge_op) self.assertAllEqual(np.array([x * 5 for x in [1, 2, 3, 4, 5, 6]]), result) def testLoop_false(self): @@ -269,9 +272,10 @@ class ControlFlowTest(test.TestCase): next_n = control_flow_ops.next_iteration(switch_n[0]) merge_n.op._update_input(1, next_n) - result = exit_n.eval() + result = self.evaluate(exit_n) self.assertAllEqual(10, result) + @test_util.run_deprecated_v1 def testLoop_1(self): with self.cached_session(): zero = constant_op.constant(0) @@ -295,7 +299,7 @@ class ControlFlowTest(test.TestCase): merge_i.op._update_input(1, next_i) exit_i = control_flow_ops.exit(switch_i[0]) - result = exit_i.eval() + result = self.evaluate(exit_i) self.assertAllEqual(10, result) def testLoop_2(self): @@ -321,7 +325,7 @@ class ControlFlowTest(test.TestCase): merge_i.op._update_input(1, next_i) exit_i = control_flow_ops.exit(switch_i[0]) - result = exit_i.eval() + result = self.evaluate(exit_i) self.assertAllEqual(10, result) def testDifferentFrame(self): @@ -333,6 +337,7 @@ class ControlFlowTest(test.TestCase): with self.assertRaisesOpError("has inputs from different frames"): res.eval(feed_dict={data: 1.0}) + @test_util.run_deprecated_v1 def testCondBool(self): values = constant_op.constant(10) fn1 = lambda: math_ops.add(values, 1) @@ -340,6 +345,7 @@ class ControlFlowTest(test.TestCase): with self.assertRaisesRegexp(TypeError, "must not be a Python bool"): _ = control_flow_ops.cond(False, fn1, fn2) + @test_util.run_deprecated_v1 def testCondInt(self): p = array_ops.placeholder(dtypes.bool, shape=[]) v = constant_op.constant(10) @@ -389,7 +395,6 @@ class ControlFlowTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "may not be fed"): sess.run(r, feed_dict={t: 3}) - @test_util.disable_control_flow_v2("b/113296180 (IndexedSlices)") def testCondIndexedSlices(self): with self.cached_session(): values = constant_op.constant(10) @@ -405,7 +410,6 @@ class ControlFlowTest(test.TestCase): self.assertAllEqual(11, val) self.assertAllEqual(0, ind) - @test_util.disable_control_flow_v2("b/113296161 (SparseTensors)") def testCondSparseTensor(self): with self.cached_session(): values = constant_op.constant([2.0, 4.0], name="values") @@ -437,6 +441,19 @@ class ControlFlowTest(test.TestCase): self.assertEqual(1.0, control_flow_ops.cond(rv, case, lambda: t).eval()) + def testCondWithTensorArrayGrad(self): + with self.cached_session() as sess: + with ops.device(test.gpu_device_name()): + pred = array_ops.placeholder(dtypes.bool, []) + x = constant_op.constant([1.0, 2.0, 3.0]) + y = control_flow_ops.cond( + pred, lambda: functional_ops.map_fn(lambda z: z * 2.0, x), + lambda: constant_op.constant([1.0, 1.0, 1.0])) + g = gradients_impl.gradients(y, x)[0] + + self.assertAllEqual(sess.run(g, {pred: True}), [2.0, 2.0, 2.0]) + self.assertAllEqual(sess.run(g, {pred: False}), [0.0, 0.0, 0.0]) + @test_util.disable_control_flow_v2("b/113293074") def testCondIndexedSlicesDifferentTypes(self): with self.cached_session(): @@ -478,7 +495,7 @@ class ControlFlowTest(test.TestCase): fn2 = lambda: math_ops.subtract(x, 1) r = control_flow_ops.cond(pred, fn1, fn2) - result = r.eval() + result = self.evaluate(r) self.assertAllEqual(11, result) def testCond_1(self): @@ -494,7 +511,7 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.cond( math_ops.less(1, 0), lambda: math_ops.add(x, 1), lambda: math_ops.subtract(x, 1)) - result = r.eval() + result = self.evaluate(r) self.assertAllEqual(9, result) def testCond_3(self): @@ -507,7 +524,7 @@ class ControlFlowTest(test.TestCase): fn3 = lambda: math_ops.add(control_flow_ops.cond(pred, fn1, fn2), 1) r = control_flow_ops.cond(pred, fn3, fn2) - result = r.eval() + result = self.evaluate(r) self.assertAllEqual(12, result) @test_util.run_in_graph_and_eager_modes @@ -534,9 +551,9 @@ class ControlFlowTest(test.TestCase): result = f().eval() self.assertEqual(True, result) # Only second cond result was fetched, so v1 assign shouldn't run. - self.assertEqual(7, v1.eval()) - self.assertEqual(2, v2.eval()) - self.assertEqual(7, v3.eval()) + self.assertEqual(7, self.evaluate(v1)) + self.assertEqual(2, self.evaluate(v2)) + self.assertEqual(7, self.evaluate(v3)) result = f_defun() self.assertEqual(True, self.evaluate(result)) @@ -557,10 +574,9 @@ class ControlFlowTest(test.TestCase): for i in range(10): alive, count = body(i) - self.assertAllEqual(4, count.eval()) + self.assertAllEqual(4, self.evaluate(count)) def testCond_6(self): - with self.cached_session(): v1 = variables.Variable([7]) @@ -571,7 +587,7 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.cond(pred, fn1, fn2) variables.global_variables_initializer().run() - result = r.eval() + result = self.evaluate(r) self.assertAllEqual(np.array([7]), result) def testCond_7(self): @@ -582,8 +598,89 @@ class ControlFlowTest(test.TestCase): fn1 = lambda: [math_ops.add(x, 1), math_ops.add(x, 2)] fn2 = lambda: [y, y] r = control_flow_ops.cond(pred, fn1, fn2) - self.assertAllEqual([11, 12], sess.run(r)) + self.assertAllEqual([11, 12], self.evaluate(r)) + + def testCondListOutput(self): + with self.cached_session() as sess: + x = constant_op.constant(10) + y = constant_op.constant(200) + pred = math_ops.less(1, 2) + fn1 = lambda: [math_ops.add(x, y), math_ops.add(x, y)] + fn2 = lambda: [y, y] + r = control_flow_ops.cond(pred, fn1, fn2) + test_result = self.evaluate(r) + self.assertListEqual([210, 210], test_result) + + def testTupleOutput(self): + with self.cached_session() as sess: + x = constant_op.constant(10) + y = constant_op.constant(200) + pred = math_ops.less(1, 2) + fn1 = lambda: (math_ops.add(x, y), math_ops.add(x, y)) + fn2 = lambda: (y, y) + r = control_flow_ops.cond(pred, fn1, fn2) + test_result = self.evaluate(r) + self.assertTupleEqual((210, 210), test_result) + + def testDictOutput(self): + with self.cached_session() as sess: + x = constant_op.constant(10) + y = constant_op.constant(200) + pred = math_ops.less(1, 2) + fn1 = lambda: {"a": math_ops.add(x, y), "b": math_ops.add(x, y)} + fn2 = lambda: {"a": y, "b": y} + r = control_flow_ops.cond(pred, fn1, fn2) + test_result = self.evaluate(r) + self.assertDictEqual({"a": 210, "b": 210}, test_result) + + @test_util.run_deprecated_v1 + def testEmbeddedListOutput(self): + with self.cached_session() as sess: + x = constant_op.constant(10) + y = constant_op.constant(200) + pred = math_ops.less(1, 2) + fn1 = lambda: [[math_ops.add(x, y), math_ops.add(x, y)]] + fn2 = lambda: [[y, y]] + # Pass strict=True flag as cond_v2 allows for tensors to be + # in nested output structures as singletons + r = control_flow_ops.cond(pred, fn1, fn2, strict=True) + test_result = self.evaluate(r) + self.assertListEqual([[210, 210]], test_result) + + def testEmbeddedTupleOutput(self): + with self.cached_session() as sess: + x = constant_op.constant(10) + y = constant_op.constant(200) + pred = math_ops.less(1, 2) + fn1 = lambda: ((math_ops.add(x, y), math_ops.add(x, y))) + fn2 = lambda: ((y, y)) + r = control_flow_ops.cond(pred, fn1, fn2) + test_result = self.evaluate(r) + self.assertTupleEqual(((210, 210)), test_result) + + def testEmbeddedDictOutput(self): + with self.cached_session() as sess: + x = constant_op.constant(10) + y = constant_op.constant(200) + pred = math_ops.less(1, 2) + fn1 = lambda: {"a": {"c": math_ops.add(x, y)}, "b": {"d": math_ops.add(x, y)}} + fn2 = lambda: {"a": {"c": y}, "b": {"d": y}} + r = control_flow_ops.cond(pred, fn1, fn2) + test_result = self.evaluate(r) + self.assertDictEqual({"a": {"c": 210}, "b": {"d": 210}}, test_result) + + def testCheckNestedOutputStruct(self): + with self.cached_session() as sess: + x = constant_op.constant(10) + y = constant_op.constant(200) + pred = math_ops.less(1, 2) + fn1 = lambda: {"a": math_ops.add(x, y), "b": math_ops.add(x, y)} + fn2 = lambda: {"c": y, "d": y} + with self.assertRaisesRegexp(ValueError, "The two structures don't have the same nested structure"): + r = control_flow_ops.cond(pred, fn1, fn2) + self.evaluate(r) + @test_util.run_deprecated_v1 def testCondRef(self): with self.cached_session(): @@ -596,9 +693,10 @@ class ControlFlowTest(test.TestCase): true_fn = lambda: x false_fn = lambda: constant_op.constant([2.0]) r = control_flow_ops.cond(constant_op.constant(False), true_fn, false_fn) - self.assertAllEqual([2.0], r.eval()) + self.assertAllEqual([2.0], self.evaluate(r)) @test_util.disable_control_flow_v2("b/79881896 (control deps)") + @test_util.run_deprecated_v1 def testCondWithControl(self): with self.cached_session(): control_holder = array_ops.placeholder(dtypes.float32, shape=()) @@ -612,7 +710,7 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.cond( constant_op.constant(True), true_branch, lambda: constant_op.constant(1)) - self.assertEqual(5, r.eval()) + self.assertEqual(5, self.evaluate(r)) def testUninitializedRefIdentity(self): with self.cached_session() as sess: @@ -636,7 +734,7 @@ class ControlFlowTest(test.TestCase): with ops.control_dependencies([v_t_op]): orig_v = array_ops.identity(v) merged_op = control_flow_ops.merge([assign_v, orig_v]) - self.assertAllEqual([1.0], sess.run(merged_op.output)) + self.assertAllEqual([1.0], self.evaluate(merged_op.output)) def testCondSwitchIdentity(self): # Make sure the recv identity is not removed by optimization. @@ -650,7 +748,7 @@ class ControlFlowTest(test.TestCase): return control_flow_ops.Assert(False, ["Wrong branch!!!"]) r = control_flow_ops.cond(pred, fn1, fn2) - sess.run(r) + self.evaluate(r) def testCondRecvIdentity(self): # Make sure the switch identity is not removed by optimization. @@ -666,7 +764,7 @@ class ControlFlowTest(test.TestCase): return control_flow_ops.Assert(False, ["Wrong branch!!!"]) r = control_flow_ops.cond(pred, fn1, fn2) - sess.run(r) + self.evaluate(r) def testCondGrad_1(self): with self.cached_session(): @@ -677,8 +775,9 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.cond(pred, fn1, fn2) grad = gradients_impl.gradients(r, [x])[0] - self.assertAllEqual(1.0, grad.eval()) + self.assertAllEqual(1.0, self.evaluate(grad)) + @test_util.run_deprecated_v1 def testCondGrad_2(self): with self.cached_session(): c = array_ops.placeholder(dtypes.int32, shape=[]) @@ -694,6 +793,7 @@ class ControlFlowTest(test.TestCase): @test_util.disable_control_flow_v2( "b/110550782 (gradient w.r.t external variable)") + @test_util.run_deprecated_v1 def testCondGrad_3(self): with self.cached_session(): c = array_ops.placeholder(dtypes.int32, shape=[]) @@ -711,6 +811,35 @@ class ControlFlowTest(test.TestCase): self.assertAllEqual(980.0, r.eval(feed_dict={c: 1})) self.assertAllEqual(30.0, r.eval(feed_dict={c: 3})) + @test_util.run_deprecated_v1 + def testCondGradMultiDevice(self): + config = config_pb2.ConfigProto(device_count={"CPU": 2}, + allow_soft_placement=True) + with self.cached_session(use_gpu=True, config=config) as sess: + pred = array_ops.placeholder(dtypes.bool, []) + x = array_ops.placeholder(dtypes.float32) + y = array_ops.placeholder(dtypes.float32) + + with ops.device("/cpu:0"): + z = control_flow_ops.cond(pred, lambda: x * y * 2.0, lambda: 2.0) + + with ops.device("/cpu:1"): + grad = gradients_impl.gradients(z, x)[0] + + self.assertEqual(sess.run(grad, {pred: True, x: 1.0, y: 2.0}), 4.0) + self.assertEqual(sess.run(grad, {pred: False, x: 1.0, y: 2.0}), 0.0) + + with ops.device("/cpu:0"): + grad_grad = gradients_impl.gradients(grad, x)[0] + + # v1 control flow gets None second derivative for some reason. + if not control_flow_ops.ENABLE_COND_V2: + self.assertIsNone(grad_grad) + return + + self.assertEqual(sess.run(grad_grad, {pred: True, x: 1.0, y: 2.0}), 0.0) + self.assertEqual(sess.run(grad_grad, {pred: False, x: 1.0, y: 2.0}), 0.0) + def testNestedCond_Simple(self): with self.cached_session(): x = constant_op.constant(0., name="X") @@ -718,15 +847,16 @@ class ControlFlowTest(test.TestCase): constant_op.constant(True), lambda: x, lambda: control_flow_ops.cond(x < 1., lambda: x, lambda: x)) result = gradients_impl.gradients(y, x)[0] - self.assertEqual(1.0, result.eval()) + self.assertEqual(1.0, self.evaluate(result)) z = control_flow_ops.cond( constant_op.constant(False), lambda: x, lambda: control_flow_ops.cond(x < 1., lambda: x, lambda: x)) result = gradients_impl.gradients(z, x)[0] - self.assertEqual(1.0, result.eval()) + self.assertEqual(1.0, self.evaluate(result)) @test_util.disable_control_flow_v2("b/113327884") + @test_util.run_deprecated_v1 def testCondGrad_Gather(self): with self.cached_session() as sess: v1 = variables.Variable([1.0, 42.0]) @@ -740,16 +870,26 @@ class ControlFlowTest(test.TestCase): # Should just be [1, 1], but possibly a sparse representation gv, gi = sess.run([grad.values, grad.indices], feed_dict={c: 1}) dense_gv = [ - sum([y for (x, y) in zip(gi, gv) if x == i]) for i in range(2) + sum(y for (x, y) in zip(gi, gv) if x == i) for i in range(2) ] self.assertAllEqual(dense_gv, [1.0, 1.0]) # Should be [0, 2], as the else forwards v1[1] twice gv, gi = sess.run([grad.values, grad.indices], feed_dict={c: 3}) dense_gv = [ - sum([y for (x, y) in zip(gi, gv) if x == i]) for i in range(2) + sum(y for (x, y) in zip(gi, gv) if x == i) for i in range(2) ] self.assertAllEqual(dense_gv, [0.0, 2.0]) + def testCondPredicateTensor(self): + """Regression test for lowering predicate from non-first output of an op.""" + + @eager_function.defun + def foo(): + return constant_op.constant("foo"), constant_op.constant(True) + + r = control_flow_ops.cond(foo()[1], lambda: 1.0, lambda: 2.0) + self.assertEqual(self.evaluate(r), 1.0) + # TODO(b/117945658): reenable @test_util.run_in_graph_and_eager_modes def DISABLED_testCondAutoControlDeps(self): @@ -863,7 +1003,7 @@ class ControlFlowTest(test.TestCase): c = lambda x: math_ops.less(x, 10000) b = lambda x: math_ops.add(x, 1) r = control_flow_ops.while_loop(c, b, [n], parallel_iterations=20) - self.assertEqual(10000, r.eval()) + self.assertEqual(10000, self.evaluate(r)) @test_util.disable_control_flow_v2("b/79881896 (control deps)") def testWhileExternalControlDependencies(self): @@ -894,10 +1034,11 @@ class ControlFlowTest(test.TestCase): result = control_flow_ops.while_loop(cond=lambda i: i < 5, body=body_fn, loop_vars=[0]) - result.eval() + self.evaluate(result) self.assertAllEqual(v.eval(), 1.0) @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") + @test_util.run_deprecated_v1 def testWhileWithRefs_1(self): with self.cached_session() as sess: x = variables.VariableV1(0)._ref() # pylint: disable=protected-access @@ -917,7 +1058,7 @@ class ControlFlowTest(test.TestCase): self.assertEqual(r[0].dtype, dtypes.int32) self.assertEqual(r[1].dtype, dtypes.int32_ref) - value_i, value_x = sess.run(r) + value_i, value_x = self.evaluate(r) self.assertEqual(100, value_i) self.assertEqual(0, value_x) @@ -926,19 +1067,19 @@ class ControlFlowTest(test.TestCase): with self.cached_session(): s = constant_op.constant(0) r = isum(s) - self.assertAllEqual(45, r.eval()) + self.assertAllEqual(45, self.evaluate(r)) def testWhileWithMaximumIterations(self): with self.cached_session(): s = constant_op.constant([1, 2, 3, 4, 5]) r = isum(s, maximum_iterations=3) - self.assertAllEqual([1 + 3, 2 + 3, 3 + 3, 4 + 3, 5 + 3], r.eval()) + self.assertAllEqual([1 + 3, 2 + 3, 3 + 3, 4 + 3, 5 + 3], self.evaluate(r)) def testWhileWithMaximumIterationsAndSingleArgument(self): with self.cached_session(): r = control_flow_ops.while_loop( lambda i: i < 3, lambda i: i + 1, [0], maximum_iterations=1) - self.assertEqual(1, r.eval()) + self.assertEqual(1, self.evaluate(r)) @test_util.disable_control_flow_v2("b/115776323 (max_iters)") def testSingleNestedMaximumIterationsWhileLoopGradientInXLAContext(self): @@ -1137,6 +1278,7 @@ class ControlFlowTest(test.TestCase): # Have more than 10 parallel iterations and hence exercise k-bound # most of the time. + @test_util.run_deprecated_v1 def testWhile_3(self): with self.cached_session(): @@ -1157,6 +1299,7 @@ class ControlFlowTest(test.TestCase): result = r[3].eval() self.assertAllEqual(10100, result) + @test_util.run_deprecated_v1 def testWhile_4(self): with self.cached_session(): @@ -1231,7 +1374,7 @@ class ControlFlowTest(test.TestCase): c = lambda x: math_ops.less(x, 10.0) b = lambda x: math_ops.add(x, 1.0) r = control_flow_ops.while_loop(c, b, [n]) - self.assertAllClose(10.0, r.eval()) + self.assertAllClose(10.0, self.evaluate(r)) def testWhile_Gpu_1(self): self._testWhile_Gpu_1(use_gpu=False) @@ -1247,7 +1390,7 @@ class ControlFlowTest(test.TestCase): return math_ops.add(x, 1.0) r = control_flow_ops.while_loop(c, b, [n]) - self.assertAllClose(10.0, r.eval()) + self.assertAllClose(10.0, self.evaluate(r)) def testWhile_Gpu_2(self): self._testWhile_Gpu_2(use_gpu=False) @@ -1268,15 +1411,16 @@ class ControlFlowTest(test.TestCase): c, _b, [i, m], [i.get_shape(), tensor_shape.unknown_shape()]) r = r[1] * array_ops.ones([8, 8]) - self.assertAllEqual(np.ones((8, 8)), r.eval()) + self.assertAllEqual(np.ones((8, 8)), self.evaluate(r)) + @test_util.run_deprecated_v1 def testWhileWithNonTensorInput_Scalar(self): with self.cached_session(): n = 0 c = lambda x: x < 10000 b = lambda x: x + 1 r = control_flow_ops.while_loop(c, b, [n], parallel_iterations=20) - self.assertEqual(10000, r.eval()) + self.assertEqual(10000, self.evaluate(r)) def testWhileWithNonTensorInput_Vector(self): with self.cached_session(): @@ -1284,7 +1428,7 @@ class ControlFlowTest(test.TestCase): c = lambda x: x[0] < 10000 b = lambda x: array_ops.stack([x[0] + 1]) r = control_flow_ops.while_loop(c, b, [n], parallel_iterations=20) - self.assertEqual([10000], r.eval()) + self.assertEqual([10000], self.evaluate(r)) def testWhileShapeInference(self): with self.cached_session(): @@ -1344,6 +1488,7 @@ class ControlFlowTest(test.TestCase): [i.get_shape(), tensor_shape.TensorShape([5])]) @test_util.disable_control_flow_v2("b/116282023 (IndexedSlices)") + @test_util.run_deprecated_v1 def testWhileShapeInferenceIndexedSlices(self): with self.cached_session(): values = constant_op.constant([[2.0, 4.0], [3.0, 5.0]], name="values") @@ -1396,7 +1541,7 @@ class ControlFlowTest(test.TestCase): c = lambda x: math_ops.less(x, 200) b = lambda x: math_ops.add(x, cpu_sum(n)) r = control_flow_ops.while_loop(c, b, [n]) - self.assertEqual(225, r.eval()) + self.assertEqual(225, self.evaluate(r)) def testNestedWhile_1(self): self._testNestedWhile_1(use_gpu=False) @@ -1428,7 +1573,7 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop( outer_c, outer_b, [s0], parallel_iterations=1) - self.assertEqual(1048576.0, r.eval()) + self.assertEqual(1048576.0, self.evaluate(r)) def testNestedWhile_2(self): self._testNestedWhile_2(use_gpu=False) @@ -1450,6 +1595,7 @@ class ControlFlowTest(test.TestCase): condition, body, [n, r], parallel_iterations=1) self.assertAllEqual(12, res[1].eval()) + @test_util.run_deprecated_v1 def testWhileWithControl_2(self): with self.cached_session(): r = constant_op.constant(0) @@ -1462,7 +1608,7 @@ class ControlFlowTest(test.TestCase): res = control_flow_ops.while_loop( condition, body, [r], parallel_iterations=1) - self.assertAllEqual(12, res.eval()) + self.assertAllEqual(12, self.evaluate(res)) def testWhileWithControl_3(self): with self.cached_session() as sess: @@ -1509,7 +1655,7 @@ class ControlFlowTest(test.TestCase): with ops.control_dependencies([control_flow_ops.no_op()]): loop = control_flow_ops.while_loop(cond, body, (constant_op.constant(5),)) - self.assertEqual(0, sess.run(loop)) + self.assertEqual(0, self.evaluate(loop)) @test_util.disable_control_flow_v2("b/113324949 (ref vars)") def testWhileCondWithControl_1(self): @@ -1531,8 +1677,8 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop(loop_condition, loop_body, (i0,)) variables.global_variables_initializer().run() - self.assertEqual(4, r.eval()) - self.assertAllClose(65536.0, v.eval()) + self.assertEqual(4, self.evaluate(r)) + self.assertAllClose(65536.0, self.evaluate(v)) @test_util.disable_control_flow_v2("b/113324949 (ref vars)") def testWhileCondExitControl(self): @@ -1556,8 +1702,8 @@ class ControlFlowTest(test.TestCase): constant_op.constant(False), lambda: constant_op.constant(1.0), false_branch) variables.global_variables_initializer().run() - self.assertEqual(6.0, r.eval()) - self.assertEqual(99, v.eval()) + self.assertEqual(6.0, self.evaluate(r)) + self.assertEqual(99, self.evaluate(v)) def testCondWhile_1(self): @@ -1568,7 +1714,7 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.cond( math_ops.less(0, 1), lambda: control_flow_ops.while_loop(c, b, [n]), lambda: n) - self.assertAllEqual(10, r.eval()) + self.assertAllEqual(10, self.evaluate(r)) def testCondWhile_2(self): @@ -1579,7 +1725,7 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.cond( math_ops.less(1, 0), lambda: math_ops.add(n, 1), lambda: control_flow_ops.while_loop(c, b, [n])) - self.assertAllEqual(10, r.eval()) + self.assertAllEqual(10, self.evaluate(r)) def _testCondWhile_3(self, use_gpu): with self.cached_session(use_gpu=use_gpu) as sess: @@ -1604,6 +1750,7 @@ class ControlFlowTest(test.TestCase): self.assertEqual([2.0], sess.run(r1, {p: False})) @test_util.disable_control_flow_v2("b/116743589") + @test_util.run_deprecated_v1 def testCondWhile_3(self): self._testCondWhile_3(use_gpu=False) self._testCondWhile_3(use_gpu=True) @@ -1622,7 +1769,7 @@ class ControlFlowTest(test.TestCase): lambda: math_ops.add(x, one), lambda: math_ops.subtract(x, one)) # pylint: enable=undefined-variable r = control_flow_ops.while_loop(c, b, [i]) - self.assertAllEqual(10, r.eval()) + self.assertAllEqual(10, self.evaluate(r)) def testWhileCond_2(self): @@ -1631,7 +1778,7 @@ class ControlFlowTest(test.TestCase): c = lambda x: math_ops.less(x, 10) b = lambda x: control_flow_ops.cond(constant_op.constant(True), lambda: math_ops.add(x, 1), lambda: n) r = control_flow_ops.while_loop(c, b, [n]) - self.assertAllEqual(10, r.eval()) + self.assertAllEqual(10, self.evaluate(r)) def testWhileCond_3(self): @@ -1645,10 +1792,41 @@ class ControlFlowTest(test.TestCase): lambda: math_ops.subtract(x, 1)) # pylint: enable=undefined-variable r = control_flow_ops.while_loop(c, b, [n]) - self.assertAllEqual(10, r.eval()) + self.assertAllEqual(10, self.evaluate(r)) + + @test_util.run_deprecated_v1 + def testWhileCondGradMultiDevice(self): + config = config_pb2.ConfigProto(device_count={"CPU": 2}, + allow_soft_placement=True) + with self.cached_session(use_gpu=True, config=config) as sess: + pred = array_ops.placeholder(dtypes.bool, []) + x_init = constant_op.constant(1.0) + + with ops.device("/cpu:0"): + z = control_flow_ops.while_loop( + lambda i, _: i < 3, + lambda i, x: (i + 1, control_flow_ops.cond( + pred, lambda: x * 2.0, lambda: 10.0)), + [0, x_init]) + + with ops.device("/cpu:1"): + grad = gradients_impl.gradients(z, x_init)[0] + + self.assertEqual(sess.run(grad, {pred: True}), 8.0) + self.assertEqual(sess.run(grad, {pred: False}), 0.0) + + if not control_flow_ops.ENABLE_WHILE_V2: + return + + with ops.device("/cpu:0"): + grad_grad = gradients_impl.gradients(grad, x_init)[0] + + self.assertEqual(sess.run(grad_grad, {pred: True}), 0.0) + self.assertEqual(sess.run(grad_grad, {pred: False}), 0.0) # NOTE: It is ok to have parallel_iterations > 1 @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") + @test_util.run_deprecated_v1 def testWhileUpdateVariable_1(self): with self.cached_session(): select = variables.Variable([3.0, 4.0, 5.0]) @@ -1667,8 +1845,8 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop( loop_iterator, loop_body, [n], parallel_iterations=1) variables.global_variables_initializer().run() - self.assertEqual(3, r.eval()) - result = select.eval() + self.assertEqual(3, self.evaluate(r)) + result = self.evaluate(select) self.assertAllClose(np.array([10.0, 10.0, 10.0]), result) @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") @@ -1692,13 +1870,14 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop( loop_iterator, loop_body, [n], parallel_iterations=1) variables.global_variables_initializer().run() - self.assertEqual(3, r.eval()) - result1 = select1.eval() + self.assertEqual(3, self.evaluate(r)) + result1 = self.evaluate(select1) self.assertAllClose(np.array([10.0, 10.0, 10.0]), result1) - result2 = select2.eval() + result2 = self.evaluate(select2) self.assertAllClose(np.array([10.0, 10.0, 10.0]), result2) @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") + @test_util.run_deprecated_v1 def testWhileUpdateVariable_3(self): with self.cached_session(): select = variables.Variable([3.0, 4.0, 5.0]) @@ -1721,6 +1900,7 @@ class ControlFlowTest(test.TestCase): self.assertAllClose(np.array([10.0, 10.0, 10.0]), result) @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") + @test_util.run_deprecated_v1 def testWhileUpdateVariable_4(self): with self.cached_session(): var_a = variables.Variable(0, name="a") @@ -1744,11 +1924,12 @@ class ControlFlowTest(test.TestCase): lpa = control_flow_ops.while_loop( pred, loop_body, [c], parallel_iterations=1) - self.assertEqual(0, var_b.eval()) - lpa.eval() # Run the loop - self.assertEqual(10, var_b.eval()) + self.assertEqual(0, self.evaluate(var_b)) + self.evaluate(lpa) # Run the loop + self.assertEqual(10, self.evaluate(var_b)) @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") + @test_util.run_deprecated_v1 def testWhileUpdateVariable_5(self): with self.cached_session(): # Create some variables. @@ -1773,10 +1954,10 @@ class ControlFlowTest(test.TestCase): lpa = control_flow_ops.while_loop( pred, loop_body, [var_b], parallel_iterations=1, name="loop") - self.assertEqual(0, var_b.eval()) - lpa.eval() # Run the loop - self.assertEqual(10, var_a.eval()) - self.assertEqual(10, var_b.eval()) + self.assertEqual(0, self.evaluate(var_b)) + self.evaluate(lpa) # Run the loop + self.assertEqual(10, self.evaluate(var_a)) + self.assertEqual(10, self.evaluate(var_b)) @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") def testWhileUpdateVariable_6(self): @@ -1803,10 +1984,10 @@ class ControlFlowTest(test.TestCase): lpa = control_flow_ops.while_loop( pred, loop_body, [c], parallel_iterations=1, name="loop") - self.assertEqual(0, var_b.eval()) - lpa.eval() # Run the loop - self.assertEqual(55, var_b.eval()) - self.assertEqual(10, var_a.eval()) + self.assertEqual(0, self.evaluate(var_b)) + self.evaluate(lpa) # Run the loop + self.assertEqual(55, self.evaluate(var_b)) + self.assertEqual(10, self.evaluate(var_a)) def testWhileQueue_1(self): with self.cached_session(): @@ -1822,7 +2003,7 @@ class ControlFlowTest(test.TestCase): return ni r = control_flow_ops.while_loop(c, b, [i], parallel_iterations=1) - self.assertEqual([10], r.eval()) + self.assertEqual([10], self.evaluate(r)) for i in xrange(10): self.assertEqual([i], q.dequeue().eval()) @@ -1858,7 +2039,7 @@ class ControlFlowTest(test.TestCase): b1, [r, x], [r.get_shape(), tensor_shape.unknown_shape()], parallel_iterations=1) - self.assertEqual(45, rx.eval()) + self.assertEqual(45, self.evaluate(rx)) def _testWhileGrad_ColocateGradients(self, colocate): gpu_dev_name = test.gpu_device_name() if test.is_gpu_available( @@ -1893,7 +2074,7 @@ class ControlFlowTest(test.TestCase): self.assertFalse(gpu_dev_name in dev) with self.session(graph=graph) as sess: - self.assertAllClose(1024.0, sess.run(r)) + self.assertAllClose(1024.0, self.evaluate(r)) @test_util.disable_control_flow_v2("b/116351701 (colocation)") def testWhileGrad_ColocateGradients(self): @@ -1909,7 +2090,7 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.cond(math_ops.less(1, 2), lambda: r, lambda: v) r = gradients_impl.gradients(r, v)[0] - self.assertAllClose(1024.0, r.eval()) + self.assertAllClose(1024.0, self.evaluate(r)) def testWhileGrad_Shape(self): with self.cached_session(): @@ -1928,6 +2109,7 @@ class ControlFlowTest(test.TestCase): self.assertEqual([None], r.get_shape().as_list()) self.assertAllClose([810.0, 2560.0], r.eval(feed_dict={x: [3.0, 4.0]})) + @test_util.run_deprecated_v1 def testWhileGrad_BaseShape(self): with self.cached_session() as sess: x = array_ops.placeholder(dtypes.float32, [None]) @@ -1949,7 +2131,7 @@ class ControlFlowTest(test.TestCase): r = math_ops.multiply(r, r) r = gradients_impl.gradients(r, v)[0] - self.assertEqual(524288.0, r.eval()) + self.assertEqual(524288.0, self.evaluate(r)) def testWhileGrad_LoopAdd(self): with self.cached_session(): @@ -1960,7 +2142,7 @@ class ControlFlowTest(test.TestCase): r = math_ops.add(r, r) r = gradients_impl.gradients(r, v)[0] - self.assertAllClose(2048.0, r.eval()) + self.assertAllClose(2048.0, self.evaluate(r)) def _testWhileGrad_Mul(self, use_gpu, p_iters): with self.cached_session(use_gpu=use_gpu) as sess: @@ -1971,11 +2153,12 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop(c, b, [v], parallel_iterations=p_iters) grad_a, grad_v = gradients_impl.gradients(r, [a, v]) - grad_a_val, grad_v_val = sess.run([grad_a, grad_v]) + grad_a_val, grad_v_val = self.evaluate([grad_a, grad_v]) self.assertAllClose(216.0, grad_a_val) self.assertAllClose(81.0, grad_v_val) @test_util.disable_control_flow_v2("b/116630618 (parallel_iters: times out)") + @test_util.run_deprecated_v1 def testWhileGrad_Mul(self): self._testWhileGrad_Mul(use_gpu=False, p_iters=1) self._testWhileGrad_Mul(use_gpu=False, p_iters=10) @@ -2003,14 +2186,13 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop(c, b, [v]) r = gradients_impl.gradients(r, v)[0] - self.assertAllClose(512.0, r.eval()) + self.assertAllClose(512.0, self.evaluate(r)) + @test_util.run_deprecated_v1 def testNestedWhileCondWhileGrad(self): - if control_flow_ops.ENABLE_WHILE_V2 and test_util.is_gpu_available(): - self.skipTest("b/118459209") self._testNestedWhileCondWhileGrad(use_gpu=False) - @test_util.disable_control_flow_v2("b/118459209") + @test_util.run_deprecated_v1 def testNestedWhileCondWhileGradGpu(self): self._testNestedWhileCondWhileGrad(use_gpu=True) @@ -2026,6 +2208,7 @@ class ControlFlowTest(test.TestCase): variables.global_variables_initializer().run() self.assertAllClose(216.0, r[0].eval()) + @test_util.run_deprecated_v1 def testWhileGrad_ResourceVariable(self): with self.cached_session(): a = resource_variable_ops.ResourceVariable(3.0) @@ -2040,7 +2223,7 @@ class ControlFlowTest(test.TestCase): def testWhileGradInCond(self): - with self.cached_session(): + with self.cached_session() as sess: n = ops.convert_to_tensor(1.0, name="n") x = array_ops.placeholder(dtypes.float32, shape=None) c = lambda n: math_ops.less(n, 10.0) @@ -2051,10 +2234,15 @@ class ControlFlowTest(test.TestCase): [tensor_shape.unknown_shape()]) return gradients_impl.gradients(r, x) - r = control_flow_ops.cond(math_ops.less(1, 2), fn1, lambda: x) - self.assertAllClose(9.0, r.eval(feed_dict={x: 1.0})) + #placed lambda function return tensor in list and set strict flag to True + #as cond_v2 implementation preserves nested output structures even with singeltons + r = control_flow_ops.cond(math_ops.less(1, 2), fn1, lambda: [x], strict=True) + #cannot run eval() on list object so use sess.run() and save output + result = sess.run(r,feed_dict={x: 1.0}) + self.assertAllClose([9.0], result) @test_util.disable_control_flow_v2("b/116340060") + @test_util.run_deprecated_v1 def testGradInWhileWrtInitialLoopVal(self): with self.cached_session(): x = array_ops.placeholder(dtypes.float32, shape=(), name="x") @@ -2102,7 +2290,7 @@ class ControlFlowTest(test.TestCase): i, x = control_flow_ops.while_loop(lambda i, x: i < 3, outer_body, [0, 0.0]) with self.cached_session() as sess: - i_val, x_val = sess.run([i, x]) + i_val, x_val = self.evaluate([i, x]) self.assertEqual(i_val, 3) self.assertAllClose(x_val, 1.0) @@ -2131,7 +2319,7 @@ class ControlFlowTest(test.TestCase): r_flattened = nest.flatten(r) self.assertEqual([100.0, 1.0, 102.0, 3.0, 4.0 + 100 * 2.0], - sess.run(r_flattened)) + self.evaluate(r_flattened)) def testWhile_NestedBadArityFails(self): with self.cached_session(): @@ -2172,6 +2360,7 @@ class ControlFlowTest(test.TestCase): r = gradients_impl.gradients([rx], y) self.assertAllClose(120.0, r[0].eval()) + @test_util.run_deprecated_v1 def testWhileGrad_Dependency(self): with self.cached_session(): i = constant_op.constant(0, name="i") @@ -2223,6 +2412,7 @@ class ControlFlowTest(test.TestCase): variables.global_variables_initializer().run() self.assertAllClose(np.ones([2, 3]), sess.run(grad[0])) + @test_util.run_deprecated_v1 def testWhileGrad_Const(self): with self.cached_session() as sess: c0 = constant_op.constant(0.0, name="c0") @@ -2295,10 +2485,11 @@ class ControlFlowTest(test.TestCase): with ops.control_dependencies([x_f]): y_f_d = array_ops.identity(y_f, name="y_f_d") - self.assertAllClose(2.0, y_f_d.eval()) # y_f_d = 1.0 + 1.0 + self.assertAllClose(2.0, self.evaluate(y_f_d)) # y_f_d = 1.0 + 1.0 g = gradients_impl.gradients([y_f_d], [x])[0] self.assertTrue(g is not None) - self.assertAllClose(1.0, g.eval()) # y_f_d = x + 1.0, dy_f_d/dx = 1.0 + self.assertAllClose(1.0, + self.evaluate(g)) # y_f_d = x + 1.0, dy_f_d/dx = 1.0 def _testNestedWhileGrad_Simple(self, use_gpu): with self.cached_session(use_gpu=use_gpu): @@ -2314,8 +2505,9 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop(c, b, [v]) r = gradients_impl.gradients(r, v)[0] - self.assertAllClose(8.0, r.eval()) + self.assertAllClose(8.0, self.evaluate(r)) + @test_util.run_deprecated_v1 def testNestedWhileGrad_Simple(self): self._testNestedWhileGrad_Simple(use_gpu=False) self._testNestedWhileGrad_Simple(use_gpu=True) @@ -2341,8 +2533,9 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop(c, b, [v]) r = gradients_impl.gradients(r, v)[0] - self.assertAllClose(256.0, r.eval()) + self.assertAllClose(256.0, self.evaluate(r)) + @test_util.run_deprecated_v1 def testNestedWhileGrad_ParallelInner(self): with self.cached_session(): v = constant_op.constant(1.0) @@ -2364,10 +2557,8 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop(c, b, [v]) r = gradients_impl.gradients(r, v)[0] - self.assertAllClose(512.0, r.eval()) + self.assertAllClose(512.0, self.evaluate(r)) - @test_util.disable_control_flow_v2("unsupported: resource creation in body. " - "Enable with new TAs b/117675481") def testNestedWhileGrad_ParallelIterations(self): # Make sure the stack pushes and pops of an inner loop are executed in # the sequential order of the iterations of its outer loop. @@ -2386,9 +2577,9 @@ class ControlFlowTest(test.TestCase): res = outer_loop(inp) optimizer = adam.AdamOptimizer(learning_rate=0.001) train_op = optimizer.minimize(math_ops.reduce_mean(math_ops.square(res))) - sess.run(variables.global_variables_initializer()) - sess.run(train_op) - self.assertAllClose(2.999, var.eval()) + self.evaluate(variables.global_variables_initializer()) + self.evaluate(train_op) + self.assertAllClose(2.999, self.evaluate(var)) def _testWhileCondGrad_Simple(self, use_gpu): with self.cached_session(use_gpu=use_gpu): @@ -2404,14 +2595,16 @@ class ControlFlowTest(test.TestCase): # pylint: enable=undefined-variable r = control_flow_ops.while_loop(c, b, [v]) r = gradients_impl.gradients(r, v)[0] - self.assertAllClose(1024.0, r.eval()) + self.assertAllClose(1024.0, self.evaluate(r)) @test_util.disable_control_flow_v2("b/117519152") + @test_util.run_deprecated_v1 def testWhileCondGrad_Simple(self): self._testWhileCondGrad_Simple(use_gpu=False) self._testWhileCondGrad_Simple(use_gpu=True) @test_util.disable_control_flow_v2("b/117276490") + @test_util.run_deprecated_v1 def testWhileCondGrad_UnknownShape(self): with self.cached_session() as sess: v = array_ops.placeholder(dtypes.float32) @@ -2429,6 +2622,7 @@ class ControlFlowTest(test.TestCase): r = sess.run(r, feed_dict={v: 2.0}) self.assertAllClose(1024.0, r) + @test_util.run_deprecated_v1 def testWhileGrad_Concat(self): with self.cached_session() as sess: x = variable_scope.get_variable("x", initializer=[[1., 2.]]) @@ -2446,11 +2640,11 @@ class ControlFlowTest(test.TestCase): [i0.get_shape(), tensor_shape.TensorShape([None, 2])]) s = math_ops.reduce_sum(h) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) optimizer = gradient_descent.GradientDescentOptimizer(0.01) op = optimizer.minimize(s) - sess.run(op) - self.assertAllClose([[0.98000002, 1.98000002]], sess.run(x)) + self.evaluate(op) + self.assertAllClose([[0.98000002, 1.98000002]], self.evaluate(x)) @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") def testWhileWithRefsWithGradients_1(self): @@ -2501,9 +2695,10 @@ class ControlFlowTest(test.TestCase): _, r = control_flow_ops.while_loop(c, b, [i, x]) r = gradients_impl.gradients(r.values, values)[0] - self.assertAllClose(np.array([1024.0, 1024.0]), r.eval()) + self.assertAllClose(np.array([1024.0, 1024.0]), self.evaluate(r)) @test_util.disable_control_flow_v2("b/116328420 (SparseTensor)") + @test_util.run_deprecated_v1 def testWhileGrad_SparseTensor(self): with self.cached_session(): values = constant_op.constant([2.0, 4.0], name="values") @@ -2524,7 +2719,7 @@ class ControlFlowTest(test.TestCase): _, r = control_flow_ops.while_loop(c, b, [i, x]) r = gradients_impl.gradients(r.values, values)[0] - self.assertAllClose(np.array([1024.0, 1024.0]), r.eval()) + self.assertAllClose(np.array([1024.0, 1024.0]), self.evaluate(r)) @test_util.disable_control_flow_v2("b/115920078 (gradients)") def testCallGradInLoop(self): @@ -2544,10 +2739,9 @@ class ControlFlowTest(test.TestCase): output_grad = control_flow_ops.while_loop( c, b, [i0, constant_op.constant(0.0)]) - self.assertAllClose(600.0, sess.run(output_grad)[1]) + self.assertAllClose(600.0, self.evaluate(output_grad)[1]) - @test_util.disable_control_flow_v2("unsupported: resource creation in body. " - "Enable with new TAs b/117675481") + @test_util.run_deprecated_v1 def testWhileAndTensorArray(self): with self.cached_session() as sess: param = constant_op.constant(2.0) @@ -2565,8 +2759,9 @@ class ControlFlowTest(test.TestCase): r = control_flow_ops.while_loop(c, b, [n0, y0], parallel_iterations=1) r = gradients_impl.gradients(r, param)[0] - self.assertAllClose(107520.0, sess.run(r)) + self.assertAllClose(107520.0, self.evaluate(r)) + @test_util.run_deprecated_v1 def testWhileGrad_StopGrad(self): with self.cached_session(): x = constant_op.constant(3.0, name="x") @@ -2582,9 +2777,9 @@ class ControlFlowTest(test.TestCase): rx, ry = control_flow_ops.while_loop(c, b, [x, y]) r = gradients_impl.gradients(rx, y)[0] - self.assertEqual(136.0, r.eval()) + self.assertEqual(136.0, self.evaluate(r)) r = gradients_impl.gradients(ry, y)[0] - self.assertEqual(32.0, r.eval()) + self.assertEqual(32.0, self.evaluate(r)) r = gradients_impl.gradients(array_ops.stop_gradient(rx), y)[0] self.assertEqual(r, None) @@ -2602,14 +2797,15 @@ class ControlFlowTest(test.TestCase): self.assertEqual(r, None) r = gradients_impl.gradients(math_ops.add(rx, ry), y)[0] - self.assertEqual(168.0, r.eval()) + self.assertEqual(168.0, self.evaluate(r)) r = gradients_impl.gradients( math_ops.add(rx, array_ops.stop_gradient(ry)), y)[0] - self.assertEqual(136.0, r.eval()) + self.assertEqual(136.0, self.evaluate(r)) r = gradients_impl.gradients( math_ops.add(array_ops.stop_gradient(rx), ry), y)[0] - self.assertEqual(32.0, r.eval()) + self.assertEqual(32.0, self.evaluate(r)) + @test_util.run_deprecated_v1 def testWhileGrad_StopGradInside(self): with self.cached_session(): x = constant_op.constant(3.0, name="x") @@ -2625,10 +2821,11 @@ class ControlFlowTest(test.TestCase): rx, _ = control_flow_ops.while_loop(c, b, [x, y]) r = gradients_impl.gradients(rx, y)[0] - self.assertAllClose(0.0, r.eval()) + self.assertAllClose(0.0, self.evaluate(r)) r = gradients_impl.gradients(rx, x)[0] - self.assertAllClose(156.0, r.eval()) + self.assertAllClose(156.0, self.evaluate(r)) + @test_util.run_deprecated_v1 def testWhileGrad_StopGradInsideNoShape(self): with self.cached_session() as sess: x = array_ops.placeholder(dtypes.float32) @@ -2650,9 +2847,10 @@ class ControlFlowTest(test.TestCase): self.assertAllClose([156.0, 400.0], sess.run(r, feed_dict=feed_dict)) name = "gradients/while/stopped_grad" all_ops = x.graph.get_operations() - self.assertFalse(any([name in op.name for op in all_ops])) + self.assertFalse(any(name in op.name for op in all_ops)) @test_util.disable_control_flow_v2("b/117954949") + @test_util.run_deprecated_v1 def testWhileGradGradFail(self): theta = variables.Variable(initial_value=1.) @@ -2667,6 +2865,7 @@ class ControlFlowTest(test.TestCase): grad_theta_stopped = array_ops.stop_gradient(grad_theta) gradients_impl.gradients(grad_theta_stopped, theta) + @test_util.run_deprecated_v1 def testStopGradOnWhileGrad(self): with self.cached_session(): x = constant_op.constant(2.0, name="x") @@ -2681,9 +2880,10 @@ class ControlFlowTest(test.TestCase): r = math_ops.add(math_ops.square(y), rx) r = math_ops.add(r, rg) r = gradients_impl.gradients(r, y)[0] - self.assertEqual(388.0, r.eval()) + self.assertEqual(388.0, self.evaluate(r)) @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") + @test_util.run_deprecated_v1 def testWhileGradientWithNontrainablePath1(self): q = variables.Variable([7., 8.]) @@ -2698,8 +2898,8 @@ class ControlFlowTest(test.TestCase): dy_dq, = gradients_impl.gradients(y, q) self.assertIsNotNone(dy_dq) with self.cached_session() as sess: - sess.run(q.initializer) - self.assertAllClose([0., 0.], sess.run(dy_dq)) + self.evaluate(q.initializer) + self.assertAllClose([0., 0.], self.evaluate(dy_dq)) @test_util.disable_control_flow_v2("b/113324949 (RefVariable)") def testWhileGradientWithNontrainablePath2(self): @@ -2716,8 +2916,8 @@ class ControlFlowTest(test.TestCase): dy_dq, = gradients_impl.gradients(y, q) self.assertIsNotNone(dy_dq) with self.cached_session() as sess: - sess.run(q.initializer) - self.assertAllClose([1., 1.], sess.run(dy_dq)) + self.evaluate(q.initializer) + self.assertAllClose([1., 1.], self.evaluate(dy_dq)) @test_util.disable_control_flow_v2("b/115920078 (gradients)") def testIssue16504(self): @@ -2767,7 +2967,7 @@ class ControlFlowTest(test.TestCase): z = math_ops.add(r, array_ops.stop_gradient(math_ops.reduce_sum(grads))) result = gradients_impl.gradients(z, vars_)[0] variables.global_variables_initializer().run() - self.assertEqual(5.0, result.eval()) + self.assertEqual(5.0, self.evaluate(result)) def testOneValueCond(self): @@ -2785,6 +2985,7 @@ class ControlFlowTest(test.TestCase): # False case: c = 0 is not >= 1 self.assertEqual([2], i.eval(feed_dict={c: 0})) + @test_util.run_deprecated_v1 def testExampleCond(self): with self.cached_session(): @@ -2828,7 +3029,7 @@ class ControlFlowTest(test.TestCase): r4 = control_flow_ops.case( [(x < y, f1), (x < y, f2)], default=f3, exclusive=True) with self.assertRaisesOpError("Input error:"): - r4.eval() + self.evaluate(r4) # Check that the default is called if none of the others are r5 = control_flow_ops.case({x > y: f1}, default=f3) @@ -2874,19 +3075,19 @@ class ControlFlowTest(test.TestCase): ((x > y, a), (x > y, b)), default=c, exclusive=True) variables.global_variables_initializer().run() - self.assertAllEqual(sess.run([v0, v1, v2]), [-1] * 3) - self.assertEqual(2, r2.eval()) - self.assertAllEqual(sess.run([v0, v1, v2]), [-1, -1, 2]) + self.assertAllEqual(self.evaluate([v0, v1, v2]), [-1] * 3) + self.assertEqual(2, self.evaluate(r2)) + self.assertAllEqual(self.evaluate([v0, v1, v2]), [-1, -1, 2]) variables.global_variables_initializer().run() - self.assertAllEqual(sess.run([v0, v1, v2]), [-1] * 3) - self.assertEqual(1, r1.eval()) - self.assertAllEqual(sess.run([v0, v1, v2]), [-1, 1, -1]) + self.assertAllEqual(self.evaluate([v0, v1, v2]), [-1] * 3) + self.assertEqual(1, self.evaluate(r1)) + self.assertAllEqual(self.evaluate([v0, v1, v2]), [-1, 1, -1]) variables.global_variables_initializer().run() - self.assertAllEqual(sess.run([v0, v1, v2]), [-1] * 3) - self.assertEqual(0, r0.eval()) - self.assertAllEqual(sess.run([v0, v1, v2]), [0, -1, -1]) + self.assertAllEqual(self.evaluate([v0, v1, v2]), [-1] * 3) + self.assertEqual(0, self.evaluate(r0)) + self.assertAllEqual(self.evaluate([v0, v1, v2]), [0, -1, -1]) @test_util.disable_control_flow_v2("b/113324949 (ref vars)") def testOneOpCond(self): @@ -2907,15 +3108,15 @@ class ControlFlowTest(test.TestCase): self.assertTrue(isinstance(i, ops.Tensor)) variables.global_variables_initializer().run() - self.assertEqual(0, v.eval()) + self.assertEqual(0, self.evaluate(v)) # True case: c = 2 is >= 1, v is set to 1. self.assertEqual(1, i.eval(feed_dict={c.name: 2})) - self.assertEqual(1, v.eval()) + self.assertEqual(1, self.evaluate(v)) # False case: c = 0 is not >= 1, v is set to 2. self.assertEqual(2, i.eval(feed_dict={c.name: 0})) - self.assertEqual(2, v.eval()) + self.assertEqual(2, self.evaluate(v)) def testWithOpsDependencies(self): with self.cached_session() as sess: @@ -2924,7 +3125,7 @@ class ControlFlowTest(test.TestCase): # Fetching v directly will result in an uninitialized error with self.assertRaisesOpError("Attempting to use uninitialized value"): - sess.run([c, v]) + self.evaluate([c, v]) # Use a control dependency to ensure init_variable is run # while asking for c @@ -2932,7 +3133,7 @@ class ControlFlowTest(test.TestCase): name="real_tensor", output_tensor=v._ref(), # pylint: disable=protected-access dependencies=[v.initializer]) - c_val, real_v_val = sess.run([c, real_v]) + c_val, real_v_val = self.evaluate([c, real_v]) # Ensure the result of 'real_c' is the same as 'c' self.assertAllEqual(10, c_val) @@ -2957,14 +3158,14 @@ class ControlFlowTest(test.TestCase): # Fetching v directly will result in an uninitialized error with self.assertRaisesOpError("Attempting to use uninitialized value"): - v.eval() + self.evaluate(v) # Get the value of 'c2_with_c1_dep', which should cause 'v' # to be initialized. - self.assertAllEqual(20, c2_with_c1_dep.eval()) + self.assertAllEqual(20, self.evaluate(c2_with_c1_dep)) # Ensure that 'v' is initialized - self.assertAllClose(0.0, v.eval()) + self.assertAllClose(0.0, self.evaluate(v)) def testWithIndexedSlicesDependencies(self): with self.cached_session(): @@ -2979,13 +3180,15 @@ class ControlFlowTest(test.TestCase): # Fetching gather_v_at_1 will result in an uninitialized error with self.assertRaisesOpError("Attempting to use uninitialized value"): - gather_v_at_1.eval() + self.evaluate(gather_v_at_1) # Getting gather_v_at_1_after_init will work, and initialize v. - self.assertAllEqual([[10.0, 11.0]], gather_v_at_1_after_init.eval()) + self.assertAllEqual([[10.0, 11.0]], + self.evaluate(gather_v_at_1_after_init)) # Double check that 'v' is initialized - self.assertAllClose([[0.0, 1.0], [10.0, 11.0], [20.0, 21.0]], v.eval()) + self.assertAllClose([[0.0, 1.0], [10.0, 11.0], [20.0, 21.0]], + self.evaluate(v)) def testDependenciesDevice(self): with ops.Graph().as_default(): @@ -3019,11 +3222,11 @@ class ControlFlowTest(test.TestCase): init = control_flow_ops.group(v1.initializer, v2.initializer) # Fetching v1 directly will result in an uninitialized error with self.assertRaisesOpError("Attempting to use uninitialized value"): - v1.eval() + self.evaluate(v1) # Runs "init" before fetching v1 and v2. init.run() - v1_val, v2_val = sess.run([v1, v2]) + v1_val, v2_val = self.evaluate([v1, v2]) # Ensure that v1 and v2 are initialized self.assertAllClose([0.0], v1_val) @@ -3034,6 +3237,7 @@ class ControlFlowTest(test.TestCase): self.assertEqual(op.type, "NoOp") self.assertEqual(op.control_inputs, []) + @test_util.run_deprecated_v1 def testMergeShapes(self): # All inputs unknown. p1 = array_ops.placeholder(dtypes.float32) @@ -3088,6 +3292,7 @@ class ControlFlowTest(test.TestCase): self.assertEqual([None, None], m.get_shape().as_list()) self.assertEqual([], index.get_shape()) + @test_util.run_deprecated_v1 def testRefSelect(self): index = array_ops.placeholder(dtypes.int32) @@ -3121,6 +3326,7 @@ class ControlFlowTest(test.TestCase): s = control_flow_ops.ref_select(index, [v1, v2]) self.assertEqual(None, s.get_shape()) + @test_util.run_deprecated_v1 def testRunLoopTensor(self): with self.cached_session() as sess: tensor_list = [] @@ -3134,7 +3340,7 @@ class ControlFlowTest(test.TestCase): result = control_flow_ops.while_loop(condition, body, [constant_op.constant(4)]) - self.assertEqual(10, sess.run(result)) + self.assertEqual(10, self.evaluate(result)) # Ensure that we cannot run a tensor that escapes the loop body # accidentally. @@ -3184,7 +3390,7 @@ class ControlFlowTest(test.TestCase): cond = constant_op.constant(True, dtypes.bool) v_f, v_t = control_flow_ops.switch(constant_qint, cond) result = control_flow_ops.merge([v_f, v_t]) - sess.run(result) + self.evaluate(result) def testQIntRefSwitchMerge(self): with self.cached_session(use_gpu=test.is_gpu_available()) as sess: @@ -3192,13 +3398,22 @@ class ControlFlowTest(test.TestCase): shape=[1], dtype=dtypes.qint8, name="v", container="", shared_name="") assign_op = state_ops.assign( var_qint, constant_op.constant(np.array([42]), dtypes.qint8)) - sess.run(assign_op) + self.evaluate(assign_op) cond = constant_op.constant(True, dtypes.bool) v_f, v_t = control_flow_ops.ref_switch(var_qint, cond) result = control_flow_ops.ref_merge([v_f, v_t]) - sess.run(result) + self.evaluate(result) + + def testUInt64SwitchMerge(self): + with self.cached_session(force_gpu=test.is_gpu_available()) as sess: + constant_uint64 = constant_op.constant(np.array([42]), dtypes.uint64) + cond = constant_op.constant(True, dtypes.bool) + v_f, v_t = control_flow_ops.switch(constant_uint64, cond) + result = control_flow_ops.merge([v_f, v_t]) + self.evaluate(result) + @test_util.run_deprecated_v1 def testQIntArgAndRet(self): @function.Defun(dtypes.qint8) @@ -3208,7 +3423,7 @@ class ControlFlowTest(test.TestCase): with self.cached_session(force_gpu=test.is_gpu_available()) as sess: qint = constant_op.constant(np.array([42]), dtypes.qint8) result = func(qint) - sess.run(result) + self.evaluate(result) class ControlFlowContextCheckTest(test.TestCase): @@ -3246,6 +3461,7 @@ class ControlFlowContextCheckTest(test.TestCase): "is in a while loop. See info log for more details."): math_ops.add(1, while_tensor) + @test_util.run_deprecated_v1 def testInvalidContextInCond(self): # Accessing a while loop tensor in cond is illegal. while_tensor = self._getWhileTensor() @@ -3314,6 +3530,7 @@ class ControlFlowContextCheckTest(test.TestCase): control_flow_ops.while_loop(lambda i: i < 5, body, [0]) + @test_util.run_deprecated_v1 def testInvalidNestedContexts(self): # Accessing a tensor from a while context in a different while context, all # inside a cond context, is illegal. @@ -3347,21 +3564,22 @@ class TupleTest(test.TestCase): # v1 is not initialized. with self.assertRaisesOpError("Attempting to use uninitialized value"): - v1.eval() + self.evaluate(v1) # v2 is not initialized. with self.assertRaisesOpError("Attempting to use uninitialized value"): - v2.eval() + self.evaluate(v2) if v1_first: # Getting t1 initializes v2. - self.assertAllClose([3.0], t1.eval()) - self.assertAllClose([10.0], v2.eval()) + self.assertAllClose([3.0], self.evaluate(t1)) + self.assertAllClose([10.0], self.evaluate(v2)) else: # Getting t2 initializes v1. - self.assertAllClose([30.0], t2.eval()) - self.assertAllClose([1.0], v1.eval()) + self.assertAllClose([30.0], self.evaluate(t2)) + self.assertAllClose([1.0], self.evaluate(v1)) + @test_util.run_deprecated_v1 def testIndexedSlices(self): for v1_first in [True, False]: with self.cached_session(): @@ -3385,22 +3603,22 @@ class TupleTest(test.TestCase): # v1 is not initialized. with self.assertRaisesOpError("Attempting to use uninitialized value"): - v1.eval() + self.evaluate(v1) # v2 is not initialized. with self.assertRaisesOpError("Attempting to use uninitialized value"): - v2.eval() + self.evaluate(v2) if v1_first: # Getting g1 initializes v2. - self.assertAllClose([[10.0, 11.0]], g1.eval()) + self.assertAllClose([[10.0, 11.0]], self.evaluate(g1)) self.assertAllClose([[0.1, 1.1], [10.1, 11.1], [20.1, 21.1]], - v2.eval()) + self.evaluate(v2)) else: # Getting g2 initializes v1. - self.assertAllClose([[10.1, 11.1]], g2.eval()) + self.assertAllClose([[10.1, 11.1]], self.evaluate(g2)) self.assertAllClose([[0.0, 1.0], [10.0, 11.0], [20.0, 21.0]], - v1.eval()) + self.evaluate(v1)) def testAcceptTensorsAsControlInputs(self): with self.cached_session(): @@ -3410,13 +3628,14 @@ class TupleTest(test.TestCase): [constant_op.constant(0)], control_inputs=[assign]) # Should trigger the assign. - t.eval() + self.evaluate(t) - self.assertEquals(1, var.eval()) + self.assertEquals(1, self.evaluate(var)) class AssertTest(test.TestCase): + @test_util.run_deprecated_v1 def testGuardedAssertDoesNotCopyWhenTrue(self): with self.session(use_gpu=True) as sess: with ops.device(test.gpu_device_name()): @@ -3513,7 +3732,7 @@ class WhileOpBenchmark(test.Benchmark): with session.Session() as sess, ops.device(default_device): # Get the initial id i, input x, and kernel. i, x, kernel = self._getInitVariables() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) if static_unroll: for _ in xrange(steps): @@ -3532,11 +3751,11 @@ class WhileOpBenchmark(test.Benchmark): for _ in xrange(3): # exclude warm up time - sess.run(r) + self.evaluate(r) start_time = time.time() for _ in xrange(num_iters): - sess.run(r) + self.evaluate(r) return (time.time() - start_time) / num_iters def benchmarkWhileOpCrossDevicePlacement(self): diff --git a/tensorflow/python/kernel_tests/conv1d_test.py b/tensorflow/python/kernel_tests/conv1d_test.py index 8540875d75..e8463323df 100644 --- a/tensorflow/python/kernel_tests/conv1d_test.py +++ b/tensorflow/python/kernel_tests/conv1d_test.py @@ -43,7 +43,7 @@ class Conv1DTest(test.TestCase): with self.cached_session(use_gpu=test.is_gpu_available()): c = nn_ops.conv1d(x, filters, stride, padding="VALID") reduced = array_ops.squeeze(c) - output = reduced.eval() + output = self.evaluate(reduced) if stride == 1: self.assertEqual(len(output), 3) self.assertAllClose(output, @@ -69,7 +69,7 @@ class Conv1DTest(test.TestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv1d_transpose( x, f, y_shape, stride=stride, padding="VALID") - value = output.eval() + value = self.evaluate(output) cache_values = np.zeros(y_shape, dtype=np.float32) diff --git a/tensorflow/python/kernel_tests/conv2d_backprop_filter_grad_test.py b/tensorflow/python/kernel_tests/conv2d_backprop_filter_grad_test.py index af6ffc1d19..7b3b560b24 100644 --- a/tensorflow/python/kernel_tests/conv2d_backprop_filter_grad_test.py +++ b/tensorflow/python/kernel_tests/conv2d_backprop_filter_grad_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import nn_ops @@ -31,6 +32,7 @@ from tensorflow.python.platform import test class Conv2DBackpropFilterGradTest(test.TestCase): + @test_util.run_deprecated_v1 def testGradient(self): with self.cached_session(): for padding in ["SAME", "VALID"]: diff --git a/tensorflow/python/kernel_tests/conv2d_transpose_test.py b/tensorflow/python/kernel_tests/conv2d_transpose_test.py index 6f9992a317..c603c08630 100644 --- a/tensorflow/python/kernel_tests/conv2d_transpose_test.py +++ b/tensorflow/python/kernel_tests/conv2d_transpose_test.py @@ -53,7 +53,7 @@ class Conv2DTransposeTest(test.TestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv2d_transpose( x, f, y_shape, strides=strides, padding="SAME") - value = output.eval() + value = self.evaluate(output) # We count the number of cells being added at the locations in the output. # At the center, #cells=kernel_height * kernel_width @@ -91,7 +91,7 @@ class Conv2DTransposeTest(test.TestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv2d_transpose( x, f, y_shape, strides=strides, padding="SAME") - value = output.eval() + value = self.evaluate(output) for n in xrange(x_shape[0]): for k in xrange(f_shape[2]): @@ -124,7 +124,7 @@ class Conv2DTransposeTest(test.TestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv2d_transpose( x, f, y_shape, strides=strides, padding="VALID") - value = output.eval() + value = self.evaluate(output) cache_values = np.zeros(y_shape, dtype=np.float32) @@ -155,6 +155,7 @@ class Conv2DTransposeTest(test.TestCase): self.assertAllClose(cache_values, value) + @test_util.run_deprecated_v1 def testGradient(self): x_shape = [2, 6, 4, 3] f_shape = [3, 3, 2, 3] @@ -195,7 +196,7 @@ class Conv2DTransposeTest(test.TestCase): output = nn_ops.conv2d_transpose( x, f, y_shape, strides=strides, padding="SAME", data_format="NCHW") - value = output.eval() + value = self.evaluate(output) for n in xrange(x_shape[0]): for k in xrange(f_shape[2]): for w in xrange(y_shape[3]): @@ -230,7 +231,7 @@ class Conv2DTransposeTest(test.TestCase): output = nn_ops.conv2d_transpose( x, f, y_shape, strides=strides, padding="SAME", data_format="NCHW") - value = output.eval() + value = self.evaluate(output) for n in xrange(x_shape[0]): for k in xrange(f_shape[2]): for w in xrange(y_shape[3]): @@ -265,7 +266,7 @@ class Conv2DTransposeTest(test.TestCase): output = nn_ops.conv2d_transpose( x, f, y_shape, strides=strides, padding="VALID", data_format="NCHW") - value = output.eval() + value = self.evaluate(output) cache_values = np.zeros(y_shape, dtype=np.float32) # The amount of padding added pad = 1 @@ -293,7 +294,6 @@ class Conv2DTransposeTest(test.TestCase): self.assertAllClose(cache_values, value) - @test_util.enable_c_shapes def testConv2DTransposeShapeInference(self): # Test case for 8972 initializer = random_ops.truncated_normal( diff --git a/tensorflow/python/kernel_tests/conv3d_backprop_filter_v2_grad_test.py b/tensorflow/python/kernel_tests/conv3d_backprop_filter_v2_grad_test.py index 89b64068ac..7e913febed 100644 --- a/tensorflow/python/kernel_tests/conv3d_backprop_filter_v2_grad_test.py +++ b/tensorflow/python/kernel_tests/conv3d_backprop_filter_v2_grad_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import nn_ops @@ -31,6 +32,7 @@ from tensorflow.python.platform import test class Conv3DBackpropFilterV2GradTest(test.TestCase): + @test_util.run_deprecated_v1 def testGradient(self): with self.cached_session(): for padding in ["SAME", "VALID"]: diff --git a/tensorflow/python/kernel_tests/conv3d_transpose_test.py b/tensorflow/python/kernel_tests/conv3d_transpose_test.py index 2527b83769..22ba5b9037 100644 --- a/tensorflow/python/kernel_tests/conv3d_transpose_test.py +++ b/tensorflow/python/kernel_tests/conv3d_transpose_test.py @@ -23,6 +23,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import nn_ops import tensorflow.python.ops.nn_grad # pylint: disable=unused-import @@ -48,7 +49,7 @@ class Conv3DTransposeTest(test.TestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv3d_transpose( x, f, y_shape, strides=strides, padding="SAME") - value = output.eval() + value = self.evaluate(output) # We count the number of cells being added at the locations in the output. # At the center, #cells = kernel_depth * kernel_height * kernel_width @@ -98,7 +99,7 @@ class Conv3DTransposeTest(test.TestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv3d_transpose( x, f, y_shape, strides=strides, padding="SAME") - value = output.eval() + value = self.evaluate(output) for n in xrange(x_shape[0]): for k in xrange(f_shape[3]): @@ -119,6 +120,7 @@ class Conv3DTransposeTest(test.TestCase): target = 3.0 self.assertAllClose(target, value[n, d, h, w, k]) + @test_util.run_deprecated_v1 def testConv3DTransposeShapeMismatch(self): # Test case for GitHub issue 18460 x_shape = [2, 2, 3, 4, 3] @@ -146,7 +148,7 @@ class Conv3DTransposeTest(test.TestCase): output = nn_ops.conv3d_transpose( x_value, f_value, constant_op.constant(y_shape, dtype=dtype), strides=strides, padding="SAME") - output.eval() + self.evaluate(output) def testConv3DTransposeValid(self): with self.cached_session(): @@ -165,7 +167,7 @@ class Conv3DTransposeTest(test.TestCase): 1.0, shape=f_shape, name="filter", dtype=dtypes.float32) output = nn_ops.conv3d_transpose( x, f, y_shape, strides=strides, padding="VALID") - value = output.eval() + value = self.evaluate(output) cache_values = np.zeros(y_shape, dtype=np.float32) @@ -201,6 +203,7 @@ class Conv3DTransposeTest(test.TestCase): self.assertAllClose(cache_values, value) + @test_util.run_deprecated_v1 def testGradient(self): x_shape = [2, 3, 4, 3, 2] f_shape = [3, 3, 3, 2, 2] diff --git a/tensorflow/python/kernel_tests/conv_ops_3d_test.py b/tensorflow/python/kernel_tests/conv_ops_3d_test.py index c4a9cdcf8e..4a689b3fdf 100644 --- a/tensorflow/python/kernel_tests/conv_ops_3d_test.py +++ b/tensorflow/python/kernel_tests/conv_ops_3d_test.py @@ -52,11 +52,11 @@ class Conv3DTest(test.TestCase): def _DtypesToTest(self, use_gpu): if use_gpu: if not test_util.CudaSupportsHalfMatMulAndConv(): - return [dtypes.float32] + return [dtypes.float64, dtypes.float32] else: # It is important that float32 comes before float16 here, # as we will be using its gradients as reference for fp16 gradients. - return [dtypes.float32, dtypes.float16] + return [dtypes.float64, dtypes.float32, dtypes.float16] else: return [dtypes.float64, dtypes.float32, dtypes.float16] @@ -109,7 +109,7 @@ class Conv3DTest(test.TestCase): results.append(result) with self.cached_session() as sess: - values = sess.run(results) + values = self.evaluate(results) for value in values: print("expected = ", expected) print("actual = ", value) @@ -184,8 +184,8 @@ class Conv3DTest(test.TestCase): computed_results.append(computed) tolerance = 1e-2 if use_gpu else 1e-5 with self.cached_session() as sess: - expected_values = sess.run(expected_results) - computed_values = sess.run(computed_results) + expected_values = self.evaluate(expected_results) + computed_values = self.evaluate(computed_results) for e_value, c_value in zip(expected_values, computed_values): print("expected = ", e_value) print("actual = ", c_value) @@ -462,6 +462,7 @@ class Conv3DTest(test.TestCase): self._ConstructAndTestGradientForConfig(data_format=data_format, use_gpu=use_gpu, **kwargs) + @test_util.run_deprecated_v1 def testInputGradientValidPaddingStrideOne(self): self.ConstructAndTestGradient( batch=2, @@ -473,6 +474,7 @@ class Conv3DTest(test.TestCase): padding="VALID", test_input=True) + @test_util.run_deprecated_v1 def testFilterGradientValidPaddingStrideOne(self): self.ConstructAndTestGradient( batch=4, @@ -484,6 +486,7 @@ class Conv3DTest(test.TestCase): padding="VALID", test_input=False) + @test_util.run_deprecated_v1 def testInputGradientValidPaddingStrideTwo(self): self.ConstructAndTestGradient( batch=2, @@ -495,6 +498,7 @@ class Conv3DTest(test.TestCase): padding="VALID", test_input=True) + @test_util.run_deprecated_v1 def testFilterGradientValidPaddingStrideTwo(self): self.ConstructAndTestGradient( batch=2, @@ -506,6 +510,7 @@ class Conv3DTest(test.TestCase): padding="VALID", test_input=False) + @test_util.run_deprecated_v1 def testInputGradientValidPaddingStrideThree(self): self.ConstructAndTestGradient( batch=2, @@ -517,6 +522,7 @@ class Conv3DTest(test.TestCase): padding="VALID", test_input=True) + @test_util.run_deprecated_v1 def testFilterGradientValidPaddingStrideThree(self): self.ConstructAndTestGradient( batch=2, @@ -528,6 +534,7 @@ class Conv3DTest(test.TestCase): padding="VALID", test_input=False) + @test_util.run_deprecated_v1 def testInputGradientSamePaddingStrideOne(self): self.ConstructAndTestGradient( batch=2, @@ -539,6 +546,7 @@ class Conv3DTest(test.TestCase): padding="SAME", test_input=True) + @test_util.run_deprecated_v1 def testFilterGradientSamePaddingStrideOne(self): self.ConstructAndTestGradient( batch=2, @@ -550,6 +558,7 @@ class Conv3DTest(test.TestCase): padding="SAME", test_input=False) + @test_util.run_deprecated_v1 def testInputGradientSamePaddingStrideTwo(self): self.ConstructAndTestGradient( batch=2, @@ -561,6 +570,7 @@ class Conv3DTest(test.TestCase): padding="SAME", test_input=True) + @test_util.run_deprecated_v1 def testFilterGradientSamePaddingStrideTwo(self): self.ConstructAndTestGradient( batch=4, @@ -572,6 +582,7 @@ class Conv3DTest(test.TestCase): padding="SAME", test_input=False) + @test_util.run_deprecated_v1 def testInputGradientSamePaddingStrideThree(self): self.ConstructAndTestGradient( batch=2, @@ -583,6 +594,7 @@ class Conv3DTest(test.TestCase): padding="SAME", test_input=True) + @test_util.run_deprecated_v1 def testFilterGradientSamePaddingStrideThree(self): self.ConstructAndTestGradient( batch=2, @@ -594,6 +606,7 @@ class Conv3DTest(test.TestCase): padding="SAME", test_input=False) + @test_util.run_deprecated_v1 def testInputGradientSamePaddingDifferentStrides(self): self.ConstructAndTestGradient( batch=1, @@ -605,6 +618,7 @@ class Conv3DTest(test.TestCase): padding="SAME", test_input=True) + @test_util.run_deprecated_v1 def testFilterGradientKernelSizeMatchesInputSize(self): self.ConstructAndTestGradient( batch=2, @@ -616,6 +630,7 @@ class Conv3DTest(test.TestCase): padding="VALID", test_input=False) + @test_util.run_deprecated_v1 def testInputGradientKernelSizeMatchesInputSize(self): self.ConstructAndTestGradient( batch=2, @@ -640,6 +655,7 @@ class Conv3DTest(test.TestCase): # Test the fast path in gemm_pack_rhs/mkldnn_gemm_pack, when channel # dimension is a multiple of packet size. + @test_util.run_deprecated_v1 def testInputGradientValidPaddingStrideOneFastPath(self): self.ConstructAndTestGradient( batch=2, @@ -651,6 +667,7 @@ class Conv3DTest(test.TestCase): padding="VALID", test_input=True) + @test_util.run_deprecated_v1 def testFilterGradientValidPaddingStrideOneFastPath(self): self.ConstructAndTestGradient( batch=2, @@ -715,8 +732,8 @@ class Conv3DTest(test.TestCase): expected_grad = gradients_impl.gradients(expected, t1 if mode == "input" else t2)[0] # "values" consists of two tensors for two backprops - actual_value = sess.run(actual_grad) - expected_value = sess.run(expected_grad) + actual_value = self.evaluate(actual_grad) + expected_value = self.evaluate(expected_grad) self.assertShapeEqual(actual_value, actual_grad) self.assertShapeEqual(expected_value, expected_grad) print("expected = ", expected_value) diff --git a/tensorflow/python/kernel_tests/conv_ops_test.py b/tensorflow/python/kernel_tests/conv_ops_test.py index 0ccbbf155c..2f6f3bb383 100644 --- a/tensorflow/python/kernel_tests/conv_ops_test.py +++ b/tensorflow/python/kernel_tests/conv_ops_test.py @@ -908,8 +908,8 @@ class Conv2DTest(test.TestCase): conv = gradients_impl.gradients(conv_forward, t1)[0] conv_2 = gradients_impl.gradients(conv_forward_2, t1)[0] # "values" consists of two tensors for two backprops - value = sess.run(conv) - value_2 = sess.run(conv_2) + value = self.evaluate(conv) + value_2 = self.evaluate(conv_2) self.assertShapeEqual(value, conv) self.assertShapeEqual(value_2, conv_2) tf_logging.info("expected = ", value_2) @@ -961,8 +961,8 @@ class Conv2DTest(test.TestCase): conv_forward_2 = test_util.NCHWToNHWC(conv_forward_2) conv = gradients_impl.gradients(conv_forward, t2)[0] conv_2 = gradients_impl.gradients(conv_forward, t2)[0] - value = sess.run(conv) - value_2 = sess.run(conv_2) + value = self.evaluate(conv) + value_2 = self.evaluate(conv_2) self.assertShapeEqual(value, conv) self.assertShapeEqual(value_2, conv_2) tf_logging.info("expected = ", value_2) @@ -1545,7 +1545,7 @@ class DepthwiseConv2DTest(test.TestCase): t2 = constant_op.constant(x2, shape=filter_in_sizes) conv = nn_impl.depthwise_conv2d( t1, t2, strides=[1, stride, stride, 1], padding=padding) - value = sess.run(conv) + value = self.evaluate(conv) tf_logging.info("value = ", value) self.assertArrayNear(expected, np.ravel(value), 1e-5) self.assertShapeEqual(value, conv) @@ -1667,9 +1667,9 @@ class SeparableConv2DTest(test.TestCase): if data_format == "NCHW": conv = array_ops.transpose(conv, [0, 2, 3, 1]) - value = sess.run(conv) + value = self.evaluate(conv) tf_logging.info("value = ", value) - self.assertArrayNear(expected, np.ravel(value), 1e-5) + self.assertArrayNear(expected, np.ravel(value), 1e-3) self.assertShapeEqual(value, conv) def _testSeparableConv2D(self, data_format): @@ -1774,10 +1774,10 @@ class DeepConv2DTest(test.TestCase): conv = nn_ops.conv2d(t1, t2, strides=strides, padding=padding) os.environ["TF_USE_DEEP_CONV2D"] = "0" - values_expect = sess.run([conv]) + values_expect = self.evaluate([conv]) os.environ["TF_USE_DEEP_CONV2D"] = "1" - values_test = sess.run([conv]) + values_test = self.evaluate([conv]) self.assertAllClose(values_expect, values_test, rtol=1e-5, atol=1e-5) diff --git a/tensorflow/python/kernel_tests/cross_grad_test.py b/tensorflow/python/kernel_tests/cross_grad_test.py index 0bd4006d6a..b397133fd7 100644 --- a/tensorflow/python/kernel_tests/cross_grad_test.py +++ b/tensorflow/python/kernel_tests/cross_grad_test.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops @@ -26,6 +27,7 @@ from tensorflow.python.platform import test class CrossOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testGradientRandomValues(self): with self.cached_session(): us = [2, 3] diff --git a/tensorflow/python/kernel_tests/ctc_decoder_ops_test.py b/tensorflow/python/kernel_tests/ctc_decoder_ops_test.py index d818fbd75c..0d86d13c71 100644 --- a/tensorflow/python/kernel_tests/ctc_decoder_ops_test.py +++ b/tensorflow/python/kernel_tests/ctc_decoder_ops_test.py @@ -25,6 +25,7 @@ from six.moves import zip_longest from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import ctc_ops from tensorflow.python.platform import test @@ -94,6 +95,7 @@ class CTCGreedyDecoderTest(test.TestCase): with self.assertRaisesOpError(expected_err_re): sess.run(decoded_unwrapped + [log_probability]) + @test_util.run_deprecated_v1 def testCTCGreedyDecoder(self): """Test two batch entries - best path decoder.""" max_time_steps = 6 @@ -170,6 +172,7 @@ class CTCGreedyDecoderTest(test.TestCase): self._testCTCDecoder(ctc_ops.ctc_greedy_decoder, inputs, seq_lens, log_prob_truth, decode_truth) + @test_util.run_deprecated_v1 def testCTCDecoderBeamSearch(self): """Test one batch, two beams - hibernating beam search.""" # max_time_steps == 8 diff --git a/tensorflow/python/kernel_tests/ctc_loss_op_test.py b/tensorflow/python/kernel_tests/ctc_loss_op_test.py index cfc7cb98aa..e6b5835079 100644 --- a/tensorflow/python/kernel_tests/ctc_loss_op_test.py +++ b/tensorflow/python/kernel_tests/ctc_loss_op_test.py @@ -23,9 +23,16 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import ops +from tensorflow.python.framework import random_seed from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops from tensorflow.python.ops import ctc_ops from tensorflow.python.ops import gradients_impl +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import random_ops +from tensorflow.python.ops import sparse_ops from tensorflow.python.platform import test @@ -52,6 +59,24 @@ def SimpleSparseTensorFrom(x): return sparse_tensor.SparseTensor(x_ix, x_val, x_shape) +def _ctc_loss_v2(labels, inputs, sequence_length, + preprocess_collapse_repeated=False, + ctc_merge_repeated=True, + ignore_longer_outputs_than_inputs=False, + time_major=True): + """Call ctc_loss_v2 with v1 args.""" + assert not preprocess_collapse_repeated + assert ctc_merge_repeated + assert not ignore_longer_outputs_than_inputs + return ctc_ops.ctc_loss_v2( + labels=labels, + logits=inputs, + logit_length=sequence_length, + label_length=None, + blank_index=-1, + logits_time_major=time_major) + + class CTCLossTest(test.TestCase): def _testCTCLoss(self, @@ -66,7 +91,7 @@ class CTCLossTest(test.TestCase): inputs_t = constant_op.constant(inputs) with self.cached_session(use_gpu=False) as sess: - loss = ctc_ops.ctc_loss( + loss = _ctc_loss_v2( inputs=inputs_t, labels=labels, sequence_length=seq_lens) grad = gradients_impl.gradients(loss, [inputs_t])[0] @@ -74,13 +99,14 @@ class CTCLossTest(test.TestCase): self.assertShapeEqual(grad_truth, grad) if expected_err_re is None: - (tf_loss, tf_grad) = sess.run([loss, grad]) + (tf_loss, tf_grad) = self.evaluate([loss, grad]) self.assertAllClose(tf_loss, loss_truth, atol=1e-6) self.assertAllClose(tf_grad, grad_truth, atol=1e-6) else: with self.assertRaisesOpError(expected_err_re): - sess.run([loss, grad]) + self.evaluate([loss, grad]) + @test_util.run_deprecated_v1 def testBasic(self): """Test two batch entries.""" # Input and ground truth from Alex Graves' implementation. @@ -216,6 +242,7 @@ class CTCLossTest(test.TestCase): self._testCTCLoss(inputs, seq_lens, labels, loss_truth, grad_truth) + @test_util.run_deprecated_v1 def test_time_major(self): """Testing time_major param. @@ -234,17 +261,18 @@ class CTCLossTest(test.TestCase): inputs_t_transposed = constant_op.constant(inputs.transpose(1, 0, 2)) with self.session(use_gpu=False) as sess: - loss = ctc_ops.ctc_loss( + loss = _ctc_loss_v2( inputs=inputs_t, labels=labels, sequence_length=seq_lens) - loss_transposed = ctc_ops.ctc_loss( + loss_transposed = _ctc_loss_v2( inputs=inputs_t_transposed, labels=labels, sequence_length=seq_lens, time_major=False) - (tf_loss, tf_loss_transposed) = sess.run([loss, loss_transposed]) + (tf_loss, tf_loss_transposed) = self.evaluate([loss, loss_transposed]) self.assertAllEqual(tf_loss, tf_loss_transposed) + @test_util.run_deprecated_v1 def testInvalidSecondGradient(self): inputs = np.random.randn(2, 2, 3).astype(np.float32) inputs_t = constant_op.constant(inputs) @@ -253,7 +281,7 @@ class CTCLossTest(test.TestCase): v = [1.0] with self.session(use_gpu=False): - loss = ctc_ops.ctc_loss( + loss = _ctc_loss_v2( inputs=inputs_t, labels=labels, sequence_length=seq_lens) # Taking ths second gradient should fail, since it is not # yet supported. @@ -261,6 +289,7 @@ class CTCLossTest(test.TestCase): "explicitly disabled"): _ = gradients_impl._hessian_vector_product(loss, [inputs_t], v) + @test_util.run_deprecated_v1 def testEmptyBatch(self): inputs = constant_op.constant([], dtype=dtypes.float32, shape=(1, 0, 2)) sequence_lengths = constant_op.constant([], dtype=dtypes.int32) @@ -272,7 +301,546 @@ class CTCLossTest(test.TestCase): with self.session(use_gpu=False) as sess: with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, "batch_size must not be 0"): - sess.run(ctc_ops.ctc_loss(labels, inputs, sequence_lengths)) + sess.run(_ctc_loss_v2(labels, inputs, sequence_lengths)) + + +class CTCLossTestV2(test.TestCase): + + @test_util.run_deprecated_v1 + def testCtcLossV2(self): + random_seed.set_random_seed(5) + + batch_size = 8 + num_labels = 6 + max_label_length = 5 + num_frames = 12 + + labels = random_ops.random_uniform( + [batch_size, max_label_length], minval=1, maxval=num_labels, + dtype=dtypes.int64) + logits = random_ops.random_uniform([num_frames, batch_size, num_labels]) + + label_length = random_ops.random_uniform( + [batch_size], minval=2, maxval=max_label_length, dtype=dtypes.int64) + label_mask = array_ops.sequence_mask( + label_length, maxlen=max_label_length, dtype=label_length.dtype) + labels *= label_mask + logit_length = [num_frames] * batch_size + + ref_loss = ctc_ops.ctc_loss_v2( + labels=labels, + logits=logits, + label_length=label_length, + logit_length=logit_length) + ref_grad = gradients_impl.gradients(ref_loss, [logits]) + + sparse_labels = ctc_ops.dense_labels_to_sparse(labels, label_length) + + def assert_same_loss_and_grads(loss): + with self.cached_session() as sess: + self.assertAllClose(*self.evaluate([loss, ref_loss])) + grad = gradients_impl.gradients(loss, [logits]) + self.assertAllClose( + *self.evaluate([grad, ref_grad]), rtol=2e-06, atol=2e-06) + + assert_same_loss_and_grads( + ctc_ops.ctc_loss_v2( + labels=sparse_labels, + logits=logits, + label_length=label_length, + logit_length=logit_length, + blank_index=0)) + + @test_util.run_deprecated_v1 + def testCtcLossDenseIsSameAsCtcLoss(self): + with ops.device("/GPU:0" if test.is_gpu_available() else "/CPU:0"): + random_seed.set_random_seed(5) + + batch_size = 8 + num_labels = 6 + label_length = 5 + num_frames = 12 + logits = random_ops.random_uniform([num_frames, batch_size, num_labels]) + labels = random_ops.random_uniform( + [batch_size, label_length], minval=1, maxval=num_labels, + dtype=dtypes.int64) + + label_lengths = random_ops.random_uniform( + [batch_size], minval=2, maxval=label_length, dtype=dtypes.int64) + label_mask = array_ops.sequence_mask( + label_lengths, maxlen=label_length, dtype=label_lengths.dtype) + labels *= label_mask + + logit_lengths = [num_frames] * batch_size + + ctc_loss = ctc_ops.ctc_loss_dense( + labels=labels, + logits=logits, + label_length=label_lengths, + logit_length=logit_lengths) + ctc_loss_grads = gradients_impl.gradients(ctc_loss, [logits])[0] + + # Shift labels down by one (move blank from 0 to num_labels -1) + tf_ctc_loss_labels = math_ops.cast(labels, dtypes.int32) - 1 + tf_nn_ctc_logits = array_ops.concat([ + logits[:, :, 1:], + logits[:, :, 0:1], + ], axis=2) + + tf_ctc_loss_labels = ctc_ops.dense_labels_to_sparse( + tf_ctc_loss_labels, label_lengths) + + tf_nn_ctc_loss = ctc_ops.ctc_loss( + labels=tf_ctc_loss_labels, + inputs=tf_nn_ctc_logits, + sequence_length=logit_lengths, + time_major=True) + tf_nn_ctc_grads = gradients_impl.gradients(tf_nn_ctc_loss, [logits])[0] + + with self.cached_session() as sess: + for _ in range(32): + self.assertAllClose(*self.evaluate([ctc_loss, tf_nn_ctc_loss])) + self.assertAllClose( + *self.evaluate([ctc_loss_grads, tf_nn_ctc_grads]), + rtol=2e-06, + atol=2e-06) + + @test_util.run_deprecated_v1 + def testCtcLossDenseUniqueFastPathIsSameAsCtcLoss(self): + random_seed.set_random_seed(5) + + batch_size = 8 + num_labels = 6 + label_length = 5 + num_frames = 12 + logits = random_ops.random_uniform([num_frames, batch_size, num_labels]) + labels = random_ops.random_uniform( + [batch_size, label_length], minval=1, maxval=num_labels, + dtype=dtypes.int64) + + label_lengths = random_ops.random_uniform( + [batch_size], minval=2, maxval=label_length, dtype=dtypes.int64) + label_mask = array_ops.sequence_mask( + label_lengths, maxlen=label_length, dtype=label_lengths.dtype) + labels *= label_mask + + logit_lengths = [num_frames] * batch_size + + ctc_loss = ctc_ops.ctc_loss_dense( + labels=labels, + logits=logits, + label_length=label_lengths, + logit_length=logit_lengths, + unique=ctc_ops.ctc_unique_labels(labels)) + ctc_loss_grads = gradients_impl.gradients(ctc_loss, [logits])[0] + + # Shift labels down by one (move blank from 0 to num_labels -1) + tf_ctc_loss_labels = math_ops.cast(labels, dtypes.int32) - 1 + tf_nn_ctc_logits = array_ops.concat([ + logits[:, :, 1:], + logits[:, :, 0:1], + ], axis=2) + + tf_ctc_loss_labels = ctc_ops.dense_labels_to_sparse( + tf_ctc_loss_labels, label_lengths) + + tf_nn_ctc_loss = ctc_ops.ctc_loss( + labels=tf_ctc_loss_labels, + inputs=tf_nn_ctc_logits, + sequence_length=logit_lengths, + time_major=True) + tf_nn_ctc_grads = gradients_impl.gradients(tf_nn_ctc_loss, [logits])[0] + + with self.cached_session() as sess: + for _ in range(32): + self.assertAllClose(*self.evaluate([ctc_loss, tf_nn_ctc_loss])) + self.assertAllClose( + *self.evaluate([ctc_loss_grads, tf_nn_ctc_grads]), + rtol=2e-06, + atol=2e-06) + + @test_util.run_deprecated_v1 + def testCtcLossDenseWithBlankIndexIsSameAsCtcLoss(self): + random_seed.set_random_seed(5) + + batch_size = 8 + num_labels = 6 + label_length = 5 + num_frames = 12 + logits = random_ops.random_uniform([num_frames, batch_size, num_labels]) + labels = random_ops.random_uniform( + [batch_size, label_length], minval=0, maxval=num_labels-1, + dtype=dtypes.int64) + + label_lengths = random_ops.random_uniform( + [batch_size], minval=2, maxval=label_length, dtype=dtypes.int64) + label_mask = array_ops.sequence_mask( + label_lengths, maxlen=label_length, dtype=label_lengths.dtype) + labels *= label_mask + + logit_lengths = [num_frames] * batch_size + + tf_ctc_loss_labels = math_ops.cast(labels, dtypes.int32) + tf_ctc_loss_labels = ctc_ops.dense_labels_to_sparse( + tf_ctc_loss_labels, label_lengths) + + tf_nn_ctc_loss = ctc_ops.ctc_loss( + labels=tf_ctc_loss_labels, + inputs=logits, + sequence_length=logit_lengths, + time_major=True) + tf_nn_ctc_grads = gradients_impl.gradients(tf_nn_ctc_loss, [logits])[0] + + # Shift the blank logits/labels to be somewhere in the middle. + blank_index = 2 + shifted_logits = array_ops.concat([ + logits[:, :, :blank_index], + logits[:, :, -1:], + logits[:, :, blank_index:-1], + ], axis=2) + shifted_labels = array_ops.where(labels < blank_index, labels, labels + 1) + + ctc_loss = ctc_ops.ctc_loss_dense( + labels=shifted_labels, + logits=shifted_logits, + label_length=label_lengths, + logit_length=logit_lengths, + blank_index=blank_index) + ctc_loss_grads = gradients_impl.gradients(ctc_loss, [logits])[0] + + with self.cached_session() as sess: + for _ in range(32): + self.assertAllClose(*self.evaluate([ctc_loss, tf_nn_ctc_loss])) + self.assertAllClose( + *self.evaluate([ctc_loss_grads, tf_nn_ctc_grads]), + rtol=2e-06, + atol=2e-06) + + @test_util.run_deprecated_v1 + def testCtcLossDenseWithNegativeBlankIndexIsSameAsCtcLoss(self): + with ops.device("/GPU:0" if test.is_gpu_available() else "/CPU:0"): + random_seed.set_random_seed(5) + + batch_size = 8 + num_labels = 6 + label_length = 5 + num_frames = 12 + logits = random_ops.random_uniform([num_frames, batch_size, num_labels]) + labels = random_ops.random_uniform( + [batch_size, label_length], minval=0, maxval=num_labels-1, + dtype=dtypes.int64) + + label_lengths = random_ops.random_uniform( + [batch_size], minval=2, maxval=label_length, dtype=dtypes.int64) + label_mask = array_ops.sequence_mask( + label_lengths, maxlen=label_length, dtype=label_lengths.dtype) + labels *= label_mask + + logit_lengths = [num_frames] * batch_size + + ctc_loss = ctc_ops.ctc_loss_dense( + labels=labels, + logits=logits, + label_length=label_lengths, + logit_length=logit_lengths, + blank_index=-1) + ctc_loss_grads = gradients_impl.gradients(ctc_loss, [logits])[0] + + tf_ctc_loss_labels = math_ops.cast(labels, dtypes.int32) + tf_ctc_loss_labels = ctc_ops.dense_labels_to_sparse( + tf_ctc_loss_labels, label_lengths) + + tf_nn_ctc_loss = ctc_ops.ctc_loss( + labels=tf_ctc_loss_labels, + inputs=logits, + sequence_length=logit_lengths, + time_major=True) + tf_nn_ctc_grads = gradients_impl.gradients(tf_nn_ctc_loss, [logits])[0] + + with self.cached_session() as sess: + for _ in range(32): + self.assertAllClose(*self.evaluate([ctc_loss, tf_nn_ctc_loss])) + self.assertAllClose( + *self.evaluate([ctc_loss_grads, tf_nn_ctc_grads]), + rtol=2e-06, + atol=2e-06) + + @test_util.run_deprecated_v1 + def testCollapseRepeated(self): + collapsed, new_seq_lengths = ctc_ops.collapse_repeated( + labels=[[1, 3, 3, 3, 0], + [1, 4, 4, 4, 0], + [4, 2, 2, 9, 4]], + seq_length=[4, 5, 5]) + self.assertAllEqual(new_seq_lengths, [2, 3, 4]) + self.assertAllEqual( + collapsed, + [[1, 3, 0, 0], + [1, 4, 0, 0], + [4, 2, 9, 4]]) + + @test_util.run_deprecated_v1 + def testCollapseRepeatedPreservesDtypes(self): + collapsed, new_seq_lengths = ctc_ops.collapse_repeated( + labels=constant_op.constant( + [[1, 3, 3, 3, 0], + [1, 4, 4, 4, 0], + [4, 2, 2, 9, 4]], + dtype=dtypes.int64), + seq_length=constant_op.constant([4, 5, 5], dtype=dtypes.int64)) + self.assertEqual(new_seq_lengths.dtype, dtypes.int64) + self.assertEqual(collapsed.dtype, dtypes.int64) + self.assertAllEqual(new_seq_lengths, [2, 3, 4]) + self.assertAllEqual( + collapsed, + [[1, 3, 0, 0], + [1, 4, 0, 0], + [4, 2, 9, 4]]) + + @test_util.run_deprecated_v1 + def testCollapseRepeatedExtraPadding(self): + collapsed, new_seq_lengths = ctc_ops.collapse_repeated( + labels=[[1, 3, 3, 3, 0, 0, 0], + [1, 4, 4, 4, 0, 1, 2], + [4, 2, 2, 9, 4, 0, 0]], + seq_length=[4, 5, 5]) + self.assertAllEqual(new_seq_lengths, [2, 3, 4]) + self.assertAllEqual( + collapsed, + [[1, 3, 0, 0], + [1, 4, 0, 0], + [4, 2, 9, 4]]) + + @test_util.run_deprecated_v1 + def testCollapseRepeatedFrontRepeats(self): + collapsed, new_seq_lengths = ctc_ops.collapse_repeated( + labels=[[1, 1, 1, 2, 2], + [1, 1, 1, 2, 2], + [1, 1, 1, 2, 2]], + seq_length=[5, 4, 3]) + self.assertAllEqual(new_seq_lengths, [2, 2, 1]) + self.assertAllEqual( + collapsed, + [[1, 2], + [1, 2], + [1, 0]]) + + @test_util.run_deprecated_v1 + def testCollapseRepeatedAllLabelsTheSame(self): + collapsed, new_seq_lengths = ctc_ops.collapse_repeated( + labels=[[1, 1, 1, 1, 1], + [1, 1, 1, 1, 1], + [1, 1, 1, 1, 1]], + seq_length=[4, 5, 1]) + self.assertAllEqual(new_seq_lengths, [1, 1, 1]) + self.assertAllEqual( + collapsed, + [[1], + [1], + [1]]) + + def testDenseSequencesToSparse(self): + labels = [[1, 3, 3, 3, 0], + [1, 4, 4, 4, 0], + [4, 2, 2, 9, 4]] + length = [4, 5, 5] + sparse = ctc_ops.dense_labels_to_sparse(labels, length) + new_dense = sparse_ops.sparse_tensor_to_dense(sparse) + + self.assertAllEqual(labels, new_dense) + + padded_labels = [[1, 3, 3, 3, 0, 0, 0, 0], + [1, 4, 4, 4, 0, 0, 0, 0], + [4, 2, 2, 9, 4, 0, 0, 0]] + length = [4, 5, 5] + sparse = ctc_ops.dense_labels_to_sparse(padded_labels, length) + padded_dense = sparse_ops.sparse_tensor_to_dense(sparse) + + self.assertAllEqual(padded_dense, new_dense) + + @test_util.run_deprecated_v1 + def testUnique(self): + labels = [ + [3, 4, 4, 3], + [1, 1, 1, 0], + ] + unique, idx = ctc_ops.ctc_unique_labels(labels) + self.assertAllEqual([ + [3, 4, 0, 0], + [1, 0, 0, 0], + ], unique) + self.assertAllEqual([ + [0, 1, 1, 0], + [0, 0, 0, 1], + ], idx) + + @test_util.run_deprecated_v1 + def testSumStates(self): + idx = [ + [0, 1, 0, 1], + [0, 0, 0, 1], + ] + states = math_ops.log([ + [[1.0, 2.0, 3.0, 4.0], + [5.0, 6.0, 7.0, 8.0]], + [[0.1, 0.2, 0.3, 0.4], + [0.5, 0.6, 0.7, 0.8]], + ]) + sum_of_states = math_ops.exp(ctc_ops._sum_states(idx, states)) + self.assertAllClose([ + [[4.0, 6.0, 0.0, 0.0], + [18.0, 8.0, 0.0, 0.0]], + [[0.4, 0.6, 0.0, 0.0], + [1.8, 0.8, 0.0, 0.0]] + ], sum_of_states) + + @test_util.run_deprecated_v1 + def testStateToOlabel(self): + labels = [ + [3, 4, 3, 4], + [1, 1, 1, 0], + ] + num_labels = 8 + + # 3 frames, 2 batch, 10 states (5 label, 5 blank). + states = [ + [[0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20], + [0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30]], + [[1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0], + [2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0]], + [[11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0], + [21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0]], + ] + labels = ops.convert_to_tensor(labels) + states = math_ops.log(states) + olabel = ctc_ops._state_to_olabel(labels, num_labels, states) + olabel = math_ops.exp(olabel) + blank = olabel[:, :, 0] + self.assertAllClose(blank, [ + [0.16 + 0.17 + 0.18 + 0.19 + 0.20, + 0.26 + 0.27 + 0.28 + 0.29 + 0.30], + [1.6 + 1.7 + 1.8 + 1.9 + 2.0, + 2.6 + 2.7 + 2.8 + 2.9 + 3.0], + [16.0 + 17.0 + 18.0 + 19.0 + 20.0, + 26.0 + 27.0 + 28.0 + 29.0 + 30.0] + ]) + self.assertAllClose(olabel[:, :, 1:], [ + [[0.0, 0.0, 0.12 + 0.14, 0.13 + 0.15, 0.0, 0.0, 0.0], + [0.22 + 0.23 + 0.24, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], + [[0.0, 0.0, 1.2 + 1.4, 1.3 + 1.5, 0.0, 0.0, 0.0], + [2.2 + 2.3 + 2.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], + [[0.0, 0.0, 12.0 + 14.0, 13.0 + 15.0, 0.0, 0.0, 0.0], + [22.0 + 23.0 + 24.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], + ]) + + @test_util.run_deprecated_v1 + def testStateToOlabelUnique(self): + labels = [ + [3, 4, 3, 4], + [1, 1, 1, 0], + ] + num_labels = 8 + + # 3 frames, 2 batch, 10 states (5 label, 5 blank). + states = [ + [[0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20], + [0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30]], + [[1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0], + [2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0]], + [[11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0], + [21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0]], + ] + labels = ops.convert_to_tensor(labels) + states = math_ops.log(states) + olabel = ctc_ops._state_to_olabel_unique( + labels, num_labels, states, ctc_ops.ctc_unique_labels(labels)) + olabel = math_ops.exp(olabel) + blank = olabel[:, :, 0] + self.assertAllClose(blank, [ + [0.16 + 0.17 + 0.18 + 0.19 + 0.20, + 0.26 + 0.27 + 0.28 + 0.29 + 0.30], + [1.6 + 1.7 + 1.8 + 1.9 + 2.0, + 2.6 + 2.7 + 2.8 + 2.9 + 3.0], + [16.0 + 17.0 + 18.0 + 19.0 + 20.0, + 26.0 + 27.0 + 28.0 + 29.0 + 30.0]]) + self.assertAllClose(olabel[:, :, 1:], [ + [[0.0, 0.0, 0.12 + 0.14, 0.13 + 0.15, 0.0, 0.0, 0.0], + [0.22 + 0.23 + 0.24, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], + [[0.0, 0.0, 1.2 + 1.4, 1.3 + 1.5, 0.0, 0.0, 0.0], + [2.2 + 2.3 + 2.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], + [[0.0, 0.0, 12.0 + 14.0, 13.0 + 15.0, 0.0, 0.0, 0.0], + [22.0 + 23.0 + 24.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]], + ]) + + @test_util.run_deprecated_v1 + def testScan(self): + with ops.device("/GPU:0" if test.is_gpu_available() else "/CPU:0"): + out = ctc_ops._scan( + lambda accum, elem: accum + elem, + constant_op.constant([1.0, 2.0, 3.0]), 23.0) + self.assertAllEqual([24.0, 26.0, 29.0], out) + + out = ctc_ops._scan( + lambda a, e: a + e, + constant_op.constant([1.0, 2.0, 3.0]), 23.0, + inclusive=True) + self.assertAllEqual([23.0, 24.0, 26.0, 29.0], out) + + out = ctc_ops._scan( + lambda a, e: a + e, + constant_op.constant([1.0, 2.0, 3.0]), 23.0, + reverse=True) + self.assertAllEqual([29.0, 28.0, 26.0], out) + + out = ctc_ops._scan( + lambda a, e: a + e, + constant_op.constant([1.0, 2.0, 3.0]), 23.0, + reverse=True, + inclusive=True) + self.assertAllEqual([29.0, 28.0, 26.0, 23.0], out) + + out = ctc_ops._scan( + lambda a, e: a + e, + constant_op.constant([[0.0, 1.0], [2.0, 3.0], [4.0, 5.0]]), + constant_op.constant([23.0, 24.0])) + self.assertAllEqual([[23.0, 25.0], [25.0, 28.0], [29.0, 33.0]], out) + + @test_util.run_deprecated_v1 + def testScanCapturesVariables(self): + with self.cached_session() as sess: + x = random_ops.random_uniform([]) + fn = lambda accum, elem: accum + x * elem + out = ctc_ops._scan(fn, constant_op.constant([0.0, 1.0, 2.0]), 23.0) + self.assertAllEqual(*sess.run([ + [23.0 + x * 0.0, 23.0 + x * 1.0, 23.0 + x * 3.0], out + ])) + + @test_util.run_deprecated_v1 + def testScanMultipleAccumulators(self): + with ops.device("/GPU:0" if test.is_gpu_available() else "/CPU:0"): + def fn(accum, elem): + accum_a, accum_b = accum + return accum_a + elem, accum_b * elem + out = ctc_ops._scan( + fn, constant_op.constant([1.0, 2.0, 3.0]), + (23.0, constant_op.constant([1.0, 2.0]))) + a, b = out + self.assertAllEqual([24.0, 26.0, 29.0], a) + self.assertAllEqual([[1.0, 2.0], [2.0, 4.0], [6.0, 12.0]], b) + + @test_util.run_deprecated_v1 + def testScanMultipleElements(self): + with ops.device("/GPU:0" if test.is_gpu_available() else "/CPU:0"): + def fn(accum, elem): + elem_a, elem_b = elem + return accum + (elem_a * elem_b) + elems_a = constant_op.constant([1.0, 2.0, 3.0]) + elems_b = constant_op.constant([[1.0, 2.0], [2.0, 3.0], [3.0, 4.0]]) + out = ctc_ops._scan( + fn, (elems_a, elems_b), + initial=constant_op.constant([0.0, 0.0])) + self.assertAllEqual( + [[1.0, 2.0], [5.0, 8.0], [14.0, 20.0]], out) if __name__ == "__main__": test.main() diff --git a/tensorflow/python/kernel_tests/cwise_ops_binary_test.py b/tensorflow/python/kernel_tests/cwise_ops_binary_test.py index 8028f93a8c..49dbbb125a 100644 --- a/tensorflow/python/kernel_tests/cwise_ops_binary_test.py +++ b/tensorflow/python/kernel_tests/cwise_ops_binary_test.py @@ -77,23 +77,23 @@ class BinaryOpTest(test.TestCase): def _compareCpu(self, x, y, np_func, tf_func, also_compare_variables=False): np_ans = np_func(x, y) - with self.test_session(use_gpu=False): + with test_util.force_cpu(): inx = ops.convert_to_tensor(x) iny = ops.convert_to_tensor(y) out = tf_func(inx, iny) - tf_cpu = out.eval() + tf_cpu = self.evaluate(out) # Test that the op takes precedence over numpy operators. - np_left = tf_func(x, iny).eval() - np_right = tf_func(inx, y).eval() + np_left = self.evaluate(tf_func(x, iny)) + np_right = self.evaluate(tf_func(inx, y)) if also_compare_variables: var_x = variables.Variable(x) var_y = variables.Variable(y) - variables.global_variables_initializer().run() + self.evaluate(variables.global_variables_initializer()) print(type(x), type(y), type(var_x), type(var_y)) print(type(tf_func(x, var_y)), type(tf_func(var_x, y))) - np_var_left = tf_func(x, var_y).eval() - np_var_right = tf_func(var_x, y).eval() + np_var_left = self.evaluate(tf_func(x, var_y)) + np_var_right = self.evaluate(tf_func(var_x, y)) if np_ans.dtype != np.object: self.assertAllClose(np_ans, tf_cpu) @@ -174,11 +174,11 @@ class BinaryOpTest(test.TestCase): def _compareGpu(self, x, y, np_func, tf_func): np_ans = np_func(x, y) - with self.test_session(force_gpu=test_util.is_gpu_available()): + with test_util.use_gpu(): inx = ops.convert_to_tensor(x) iny = ops.convert_to_tensor(y) out = tf_func(inx, iny) - tf_gpu = out.eval() + tf_gpu = self.evaluate(out) self.assertAllClose(np_ans, tf_gpu) self.assertShapeEqual(np_ans, out) # TODO(zhifengc/ke): make gradient checker work on GPU. @@ -196,6 +196,7 @@ class BinaryOpTest(test.TestCase): self._compareGradientY(x, y, np_func, tf_func) self._compareGpu(x, y, np_func, tf_func) + @test_util.run_deprecated_v1 def testFloatBasic(self): x = np.linspace(-5, 20, 15).reshape(1, 3, 5).astype(np.float32) y = np.linspace(20, -5, 15).reshape(1, 3, 5).astype(np.float32) @@ -233,6 +234,7 @@ class BinaryOpTest(test.TestCase): except ImportError as e: tf_logging.warn("Cannot test special functions: %s" % str(e)) + @test_util.run_deprecated_v1 def testFloatDifferentShapes(self): x = np.array([1, 2, 3, 4]).reshape(2, 2).astype(np.float32) y = np.array([1, 2]).reshape(2, 1).astype(np.float32) @@ -252,14 +254,17 @@ class BinaryOpTest(test.TestCase): y = np.array([1, 2]).reshape(2, 1).astype(np.int32) var_x = variables.Variable(x) var_y = variables.Variable(y) + with self.cached_session() as sess: - sess.run([var_x.initializer, var_y.initializer]) - left_result = (var_x * y).eval() - right_result = (x * var_y).eval() + self.evaluate([var_x.initializer, var_y.initializer]) + left_result = self.evaluate(var_x * y) + right_result = self.evaluate(x * var_y) + np_result = x * y self.assertAllEqual(np_result, left_result) self.assertAllEqual(np_result, right_result) + @test_util.run_deprecated_v1 def testDoubleBasic(self): x = np.linspace(-5, 20, 15).reshape(1, 3, 5).astype(np.float64) y = np.linspace(20, -5, 15).reshape(1, 3, 5).astype(np.float64) @@ -351,6 +356,7 @@ class BinaryOpTest(test.TestCase): self._compareBoth(x, y, np.floor_divide, _FLOORDIV) self._compareBoth(x, y, np.mod, _MOD) + @test_util.run_deprecated_v1 def testComplex64Basic(self): x = np.complex(1, 1) * np.linspace(-10, 10, 6).reshape(1, 3, 2).astype( np.complex64) @@ -365,6 +371,7 @@ class BinaryOpTest(test.TestCase): self._compareBoth(x, y, np.multiply, _MUL) self._compareBoth(x, y + 0.1, np.true_divide, _TRUEDIV) + @test_util.run_deprecated_v1 def testComplex128Basic(self): x = np.complex(1, 1) * np.linspace(-10, 10, 6).reshape(1, 3, 2).astype( np.complex128) @@ -382,10 +389,10 @@ class BinaryOpTest(test.TestCase): def testStringComparison(self): x = np.array([["abc", "bh"], ["c", ""]]) y = np.array([["abc", "bh"], ["def", "hi"]]) - with self.test_session(use_gpu=False) as sess: + with test_util.force_cpu(): cmp_eq = math_ops.equal(x, y) cmp_not_eq = math_ops.not_equal(x, y) - values = sess.run([cmp_eq, cmp_not_eq]) + values = self.evaluate([cmp_eq, cmp_not_eq]) self.assertAllEqual([[True, True], [False, False]], values[0]) self.assertAllEqual([[False, False], [True, True]], values[1]) @@ -478,198 +485,263 @@ class BinaryOpTest(test.TestCase): ] self._testBCastByFunc(funcs, xs, ys) + @test_util.run_deprecated_v1 def testBCast_0A(self): self._testBCastA([1, 3, 2], [1]) + @test_util.run_deprecated_v1 def testBCast_0B(self): self._testBCastB([1, 3, 2], [1]) + @test_util.run_deprecated_v1 def testBCast_0C(self): self._testBCastC([1, 3, 2], [1]) + @test_util.run_deprecated_v1 def testBCast_0D(self): self._testBCastD([1, 3, 2], [1]) + @test_util.run_deprecated_v1 def testBCast_1A(self): self._testBCastA([1, 3, 2], [2]) + @test_util.run_deprecated_v1 def testBCast_1B(self): self._testBCastB([1, 3, 2], [2]) + @test_util.run_deprecated_v1 def testBCast_1C(self): self._testBCastC([1, 3, 2], [2]) + @test_util.run_deprecated_v1 def testBCast_1D(self): self._testBCastD([1, 3, 2], [2]) + @test_util.run_deprecated_v1 def testBCast_2A(self): self._testBCastA([1, 3, 2], [3, 2]) + @test_util.run_deprecated_v1 def testBCast_2B(self): self._testBCastB([1, 3, 2], [3, 2]) + @test_util.run_deprecated_v1 def testBCast_2C(self): self._testBCastC([1, 3, 2], [3, 2]) + @test_util.run_deprecated_v1 def testBCast_2D(self): self._testBCastD([1, 3, 2], [3, 2]) + @test_util.run_deprecated_v1 def testBCast_3A(self): self._testBCastA([1, 3, 2], [3, 1]) + @test_util.run_deprecated_v1 def testBCast_3B(self): self._testBCastB([1, 3, 2], [3, 1]) + @test_util.run_deprecated_v1 def testBCast_3C(self): self._testBCastC([1, 3, 2], [3, 1]) + @test_util.run_deprecated_v1 def testBCast_3D(self): self._testBCastD([1, 3, 2], [3, 1]) + @test_util.run_deprecated_v1 def testBCast_4A(self): self._testBCastA([1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_4B(self): self._testBCastB([1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_4C(self): self._testBCastC([1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_4D(self): self._testBCastD([1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_5A(self): self._testBCastA([1, 3, 2], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_5B(self): self._testBCastB([1, 3, 2], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_5C(self): self._testBCastC([1, 3, 2], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_5D(self): self._testBCastD([1, 3, 2], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_6A(self): self._testBCastA([1, 3, 2], [2, 1, 1]) + @test_util.run_deprecated_v1 def testBCast_6B(self): self._testBCastB([1, 3, 2], [2, 1, 1]) + @test_util.run_deprecated_v1 def testBCast_6C(self): self._testBCastC([1, 3, 2], [2, 1, 1]) + @test_util.run_deprecated_v1 def testBCast_6D(self): self._testBCastD([1, 3, 2], [2, 1, 1]) + @test_util.run_deprecated_v1 def testBCast_7A(self): self._testBCastA([1, 3, 2], [1, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_7B(self): self._testBCastB([1, 3, 2], [1, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_7C(self): self._testBCastC([1, 3, 2], [1, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_7D(self): self._testBCastD([1, 3, 2], [1, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_8A(self): self._testBCastA([2, 1, 5], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_8B(self): self._testBCastB([2, 1, 5], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_8C(self): self._testBCastC([2, 1, 5], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_8D(self): self._testBCastD([2, 1, 5], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_9A(self): self._testBCastA([2, 0, 5], [2, 0, 1]) + @test_util.run_deprecated_v1 def testBCast_9B(self): self._testBCastB([2, 0, 5], [2, 0, 1]) + @test_util.run_deprecated_v1 def testBCast_9C(self): self._testBCastC([2, 0, 5], [2, 0, 1]) + @test_util.run_deprecated_v1 def testBCast_9D(self): self._testBCastD([2, 0, 5], [2, 0, 1]) + @test_util.run_deprecated_v1 def testBCast_10A(self): self._testBCastA([2, 3, 0], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_10B(self): self._testBCastB([2, 3, 0], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_10C(self): self._testBCastC([2, 3, 0], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_10D(self): self._testBCastD([2, 3, 0], [2, 3, 1]) + @test_util.run_deprecated_v1 def testBCast_11A(self): self._testBCastA([1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_11B(self): self._testBCastB([1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_11C(self): self._testBCastC([1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_11D(self): self._testBCastD([1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_12A(self): self._testBCastA([1, 1, 1, 1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_12B(self): self._testBCastB([1, 1, 1, 1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_12C(self): self._testBCastC([1, 1, 1, 1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_12D(self): self._testBCastD([1, 1, 1, 1, 3, 2], [1, 3, 2]) + @test_util.run_deprecated_v1 def testBCast_13A(self): self._testBCastA([1, 3, 2, 1, 1], [1]) + @test_util.run_deprecated_v1 def testBCast_13B(self): self._testBCastB([1, 3, 2, 1, 1], [1]) + @test_util.run_deprecated_v1 def testBCast_13C(self): self._testBCastC([1, 3, 2, 1, 1], [1]) + @test_util.run_deprecated_v1 def testBCast_13D(self): self._testBCastD([1, 3, 2, 1, 1], [1]) + @test_util.run_deprecated_v1 def testBCast_14A(self): self._testBCastA([2, 3, 1, 1, 5], [1]) + @test_util.run_deprecated_v1 def testBCast_14B(self): self._testBCastB([2, 3, 1, 1, 5], [1]) + @test_util.run_deprecated_v1 def testBCast_14C(self): self._testBCastC([2, 3, 1, 1, 5], [1]) + @test_util.run_deprecated_v1 def testBCast_14D(self): self._testBCastD([2, 3, 1, 1, 5], [1]) + @test_util.run_deprecated_v1 def testBCast_15A(self): self._testBCastA([10, 3, 1, 2], [3, 1, 2]) + @test_util.run_deprecated_v1 def testBCast_15B(self): self._testBCastB([10, 3, 1, 2], [3, 1, 2]) + @test_util.run_deprecated_v1 def testBCast_15C(self): self._testBCastC([10, 3, 1, 2], [3, 1, 2]) + @test_util.run_deprecated_v1 def testBCast_15D(self): self._testBCastD([10, 3, 1, 2], [3, 1, 2]) + @test_util.run_deprecated_v1 def testMismatchedDimensions(self): for func in [ math_ops.add, math_ops.subtract, math_ops.multiply, math_ops.div, _ADD, @@ -681,6 +753,7 @@ class BinaryOpTest(test.TestCase): ops.convert_to_tensor([10.0, 20.0, 30.0]), ops.convert_to_tensor([[40.0, 50.0], [60.0, 70.0]])) + @test_util.run_deprecated_v1 def testZeroPowGrad(self): with self.cached_session(): for dtype in (np.float16, np.float32, np.float64, np.complex64, @@ -691,6 +764,7 @@ class BinaryOpTest(test.TestCase): error = gradient_checker.compute_gradient_error(y, [], z, []) self.assertEqual(error, 0) + @test_util.run_deprecated_v1 def testComplexPowGrad(self): with self.cached_session(): for dtype in np.complex64, np.complex128: @@ -716,39 +790,39 @@ class BinaryOpTest(test.TestCase): def testPowNegativeExponent(self): for dtype in [np.int32, np.int64]: - with self.test_session(use_gpu=False) as sess: + with test_util.force_cpu(): with self.assertRaisesRegexp( errors_impl.InvalidArgumentError, "Integers to negative integer powers are not allowed"): x = np.array([5, 2]).astype(dtype) y = np.array([-2, 3]).astype(dtype) - sess.run(math_ops.pow(x, y)) + self.evaluate(math_ops.pow(x, y)) - with self.test_session(use_gpu=False) as sess: + with test_util.force_cpu(): with self.assertRaisesRegexp( errors_impl.InvalidArgumentError, "Integers to negative integer powers are not allowed"): x = np.array([5, 2]).astype(dtype) y = np.array([2, -3]).astype(dtype) - sess.run(math_ops.pow(x, y)) + self.evaluate(math_ops.pow(x, y)) - with self.test_session(use_gpu=False) as sess: + with test_util.force_cpu(): with self.assertRaisesRegexp( errors_impl.InvalidArgumentError, "Integers to negative integer powers are not allowed"): x = np.array([5, 2]).astype(dtype) y = -3 - sess.run(math_ops.pow(x, y)) + self.evaluate(math_ops.pow(x, y)) class ComparisonOpTest(test.TestCase): def _compareScalar(self, func, x, y, dtype): - with self.test_session(force_gpu=test_util.is_gpu_available()): + with test_util.use_gpu(): out = func( ops.convert_to_tensor(np.array([x]).astype(dtype)), ops.convert_to_tensor(np.array([y]).astype(dtype))) - ret = out.eval() + ret = self.evaluate(out) return ret[0] def testScalarCompareScalar(self): @@ -777,9 +851,9 @@ class ComparisonOpTest(test.TestCase): def _compare(self, x, y, np_func, tf_func): np_ans = np_func(x, y) - with self.test_session(force_gpu=test_util.is_gpu_available()): + with test_util.use_gpu(): out = tf_func(ops.convert_to_tensor(x), ops.convert_to_tensor(y)) - tf_ans = out.eval() + tf_ans = self.evaluate(out) self.assertAllEqual(np_ans, tf_ans) def testTensorCompareTensor(self): @@ -859,6 +933,7 @@ class ComparisonOpTest(test.TestCase): self._testBCastByFunc( np.not_equal, math_ops.not_equal, include_complex=True) + @test_util.run_deprecated_v1 def testShapeMismatch(self): dtypes = [np.float16, np.float32, np.float64, np.int32, np.int64] funcs = [ diff --git a/tensorflow/python/kernel_tests/cwise_ops_test.py b/tensorflow/python/kernel_tests/cwise_ops_test.py index c5311ad834..9bb7d8b8b1 100644 --- a/tensorflow/python/kernel_tests/cwise_ops_test.py +++ b/tensorflow/python/kernel_tests/cwise_ops_test.py @@ -84,11 +84,11 @@ def _default_tolerance(dtype): class ComparisonOpTest(test.TestCase): def _compareScalar(self, func, x, y, dtype): - with self.test_session(force_gpu=test_util.is_gpu_available()): + with test_util.use_gpu(): out = func( ops.convert_to_tensor(np.array([x]).astype(dtype)), ops.convert_to_tensor(np.array([y]).astype(dtype))) - ret = out.eval() + ret = self.evaluate(out) return ret[0] def testScalarCompareScalar(self): @@ -117,9 +117,9 @@ class ComparisonOpTest(test.TestCase): def _compare(self, x, y, np_func, tf_func): np_ans = np_func(x, y) - with self.test_session(force_gpu=test_util.is_gpu_available()): + with test_util.use_gpu(): out = tf_func(ops.convert_to_tensor(x), ops.convert_to_tensor(y)) - tf_ans = out.eval() + tf_ans = self.evaluate(out) self.assertAllEqual(np_ans, tf_ans) def testTensorCompareTensor(self): @@ -199,6 +199,7 @@ class ComparisonOpTest(test.TestCase): self._testBCastByFunc( np.not_equal, math_ops.not_equal, include_complex=True) + @test_util.run_deprecated_v1 def testShapeMismatch(self): dtypes = [np.float16, np.float32, np.float64, np.int32, np.int64] funcs = [ @@ -218,22 +219,20 @@ class LogicalOpTest(test.TestCase): def _compareBinary(self, x, y, np_func, tf_func, use_gpu=False): np_ans = np_func(x, y) - with self.test_session(use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()): + with test_util.device(use_gpu=use_gpu): inx = ops.convert_to_tensor(x) iny = ops.convert_to_tensor(y) out = tf_func(inx, iny) - tf_val = out.eval() + tf_val = self.evaluate(out) self.assertEqual(out.dtype, dtypes_lib.bool) self.assertAllEqual(np_ans, tf_val) self.assertShapeEqual(np_ans, out) def _not(self, x, use_gpu=False): np_ans = np.logical_not(x) - with self.test_session(use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()): + with test_util.device(use_gpu=use_gpu): out = math_ops.logical_not(ops.convert_to_tensor(x)) - tf_val = out.eval() + tf_val = self.evaluate(out) self.assertEqual(out.dtype, dtypes_lib.bool) self.assertAllEqual(np_ans, tf_val) self.assertShapeEqual(np_ans, out) @@ -282,6 +281,7 @@ class LogicalOpTest(test.TestCase): self._compareBinary(x, y, np.logical_or, math_ops.logical_or, use_gpu) self._compareBinary(x, y, np.logical_xor, math_ops.logical_xor, use_gpu) + @test_util.run_deprecated_v1 def testShapeMismatch(self): x = np.random.randint(0, 2, 6).astype(np.bool).reshape(1, 3, 2) y = np.random.randint(0, 2, 6).astype(np.bool).reshape(3, 2, 1) @@ -290,6 +290,7 @@ class LogicalOpTest(test.TestCase): ValueError, lambda e: "Dimensions must" in str(e)): f(x, y) + @test_util.run_deprecated_v1 def testUsingAsPythonValueFails(self): # Ensure that we raise an error when the user attempts to treat a # `Tensor` as a Python `bool`. @@ -316,10 +317,9 @@ class SelectOpTest(test.TestCase): def _compare(self, c, x, y, use_gpu): np_ans = np.where(c, x, y) - with self.test_session(use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()): + with test_util.device(use_gpu=use_gpu): out = array_ops.where(c, x, y) - tf_ans = out.eval() + tf_ans = self.evaluate(out) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, out) @@ -399,6 +399,7 @@ class SelectOpTest(test.TestCase): if t in [np.float16, np.float32, np.float64]: self._compare(c, xt, yt, use_gpu=True) + @test_util.run_deprecated_v1 def testGradients(self): c = np.random.randint(0, 2, 6).astype(np.bool).reshape(1, 3, 2) x = np.random.rand(1, 3, 2) * 100 @@ -418,6 +419,7 @@ class SelectOpTest(test.TestCase): self._compareGradientX(c, xt, yt) self._compareGradientY(c, xt, yt) + @test_util.run_deprecated_v1 def testShapeMismatch(self): c = np.random.randint(0, 2, 6).astype(np.bool).reshape(1, 3, 2) x = np.random.rand(1, 3, 2) * 100 @@ -431,6 +433,7 @@ class SelectOpTest(test.TestCase): with self.assertRaises(ValueError): array_ops.where(c, xt, yt) + @test_util.run_deprecated_v1 def testEmptyTensor(self): c = np.random.randint(0, 3, 0).astype(np.bool).reshape(1, 3, 0) x = np.random.rand(1, 3, 0) * 100 @@ -442,6 +445,7 @@ class SelectOpTest(test.TestCase): z = array_ops.where(c, xt, yt).eval() self.assertAllEqual(z_expected, z) + @test_util.run_deprecated_v1 def testNan(self): """Verify that nans don't propagate where they shouldn't.""" with self.cached_session(): @@ -460,10 +464,9 @@ class BatchSelectOpTest(test.TestCase): np_ans = np.dstack( [x_i if c_i else y_i for c_i, x_i, y_i in zip(c, x, y)]).transpose( [2, 0, 1]) - with self.test_session(use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()): + with test_util.device(use_gpu=use_gpu): out = array_ops.where(c, x, y) - tf_ans = out.eval() + tf_ans = self.evaluate(out) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, out) @@ -529,6 +532,7 @@ class BatchSelectOpTest(test.TestCase): if t in [np.float16, np.float32, np.float64]: self._compare(c, xt, yt, use_gpu=True) + @test_util.run_deprecated_v1 def testGradients(self): c = np.random.randint(0, 2, 16).astype(np.bool) x = np.random.rand(16, 2, 8) * 100 @@ -548,6 +552,7 @@ class BatchSelectOpTest(test.TestCase): self._compareGradientX(c, xt, yt) self._compareGradientY(c, xt, yt) + @test_util.run_deprecated_v1 def testShapeMismatch(self): c = np.random.randint(0, 2, 8).astype(np.bool) x = np.random.rand(16, 3, 2) * 100 @@ -566,13 +571,11 @@ class MinMaxOpTest(test.TestCase): def _compare(self, x, y, use_gpu): np_min, np_max = np.minimum(x, y), np.maximum(x, y) - with self.test_session( - use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()) as sess: + with test_util.device(use_gpu=use_gpu): inx = ops.convert_to_tensor(x) iny = ops.convert_to_tensor(y) omin, omax = math_ops.minimum(inx, iny), math_ops.maximum(inx, iny) - tf_min, tf_max = sess.run([omin, omax]) + tf_min, tf_max = self.evaluate([omin, omax]) self.assertAllEqual(np_min, tf_min) self.assertAllEqual(np_max, tf_max) @@ -628,6 +631,7 @@ class MinMaxOpTest(test.TestCase): elif x.dtype == np.float64: self.assertAllClose(jacob_t, jacob_n, rtol=1e-5, atol=1e-5) + @test_util.run_deprecated_v1 def testGradients(self): x = np.random.rand(1, 3, 2) * 100. # ensure x != y @@ -641,16 +645,16 @@ class MinMaxOpTest(test.TestCase): class MathOpsOverloadTest(test.TestCase): def _computeTensorAndLiteral(self, x, y, dtype, func): - with self.test_session(use_gpu=False): + with test_util.force_cpu(): inx = ops.convert_to_tensor(x, dtype=dtype) z = func(inx, y) # Should use __add__, __sub__, etc. - return z.eval() + return self.evaluate(z) def _computeLiteralAndTensor(self, x, y, dtype, func): - with self.test_session(use_gpu=False): + with test_util.force_cpu(): iny = ops.convert_to_tensor(y, dtype=dtype) z = func(x, iny) # Should use __radd__, __rsub__, etc. - return z.eval() + return self.evaluate(z) def _compareBinary(self, x, y, dtype, np_func, tf_func): np_ans = np_func(x, y).astype(dtype.as_numpy_dtype) @@ -661,9 +665,9 @@ class MathOpsOverloadTest(test.TestCase): def _compareUnary(self, x, dtype, np_func, tf_func): np_ans = np_func(x).astype(dtype.as_numpy_dtype) - with self.test_session(use_gpu=False): - self.assertAllClose(np_ans, - tf_func(ops.convert_to_tensor(x, dtype=dtype)).eval()) + with test_util.force_cpu(): + self.assertAllClose( + np_ans, self.evaluate(tf_func(ops.convert_to_tensor(x, dtype=dtype)))) def testOverload(self): dtypes = [ @@ -730,13 +734,11 @@ class IsFiniteInfNanTest(test.TestCase): def _compare(self, x, use_gpu): np_finite, np_inf, np_nan = np.isfinite(x), np.isinf(x), np.isnan(x) - with self.test_session( - use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()) as sess: + with test_util.device(use_gpu=use_gpu): inx = ops.convert_to_tensor(x) ofinite, oinf, onan = math_ops.is_finite(inx), math_ops.is_inf( inx), math_ops.is_nan(inx) - tf_finite, tf_inf, tf_nan = sess.run([ofinite, oinf, onan]) + tf_finite, tf_inf, tf_nan = self.evaluate([ofinite, oinf, onan]) self.assertAllEqual(np_inf, tf_inf) self.assertAllEqual(np_nan, tf_nan) self.assertAllEqual(np_finite, tf_finite) @@ -773,31 +775,33 @@ class IsFiniteInfNanTest(test.TestCase): x = np.full((size,), value, dtype=dtype) np_y = np.sqrt(x) np_nan = np.isnan(np_y) - with self.test_session(force_gpu=test_util.is_gpu_available()): + with test_util.use_gpu(): tf_y = math_ops.sqrt(x) tf_nan = math_ops.is_nan(tf_y) if value < 0: - self.assertAllEqual(np_nan, tf_nan.eval()) + self.assertAllEqual(np_nan, self.evaluate(tf_nan)) else: - self.assertAllCloseAccordingToType(np_y, tf_y.eval()) + self.assertAllCloseAccordingToType(np_y, self.evaluate(tf_y)) class RoundingTest(test.TestCase): def _compare_values(self, x, y=None): y = np.rint(x) if y is None else np.asarray(y) - with self.cached_session() as sess: - tf_rint = math_ops.rint(x) - np_rint = sess.run(tf_rint) + + tf_rint = math_ops.rint(x) + np_rint = self.evaluate(tf_rint) + self.assertAllEqual(y, np_rint) self.assertShapeEqual(y, tf_rint) def _compare(self, x): np_floor, np_ceil = np.floor(x), np.ceil(x) - with self.cached_session() as sess: - inx = ops.convert_to_tensor(x) - ofloor, oceil = math_ops.floor(inx), math_ops.ceil(inx) - tf_floor, tf_ceil = sess.run([ofloor, oceil]) + + inx = ops.convert_to_tensor(x) + ofloor, oceil = math_ops.floor(inx), math_ops.ceil(inx) + tf_floor, tf_ceil = self.evaluate([ofloor, oceil]) + self.assertAllEqual(np_floor, tf_floor) self.assertAllEqual(np_ceil, tf_ceil) self.assertShapeEqual(np_floor, ofloor) @@ -828,12 +832,13 @@ class ComplexMakeRealImagTest(test.TestCase): def _compareMake(self, real, imag, use_gpu): np_ans = real + (1j) * imag - with self.test_session(use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()): + + with test_util.device(use_gpu=use_gpu): real = ops.convert_to_tensor(real) imag = ops.convert_to_tensor(imag) tf_ans = math_ops.complex(real, imag) - out = tf_ans.eval() + out = self.evaluate(tf_ans) + self.assertAllEqual(np_ans, out) self.assertShapeEqual(np_ans, tf_ans) @@ -848,17 +853,17 @@ class ComplexMakeRealImagTest(test.TestCase): def _compareRealImag(self, cplx, use_gpu): np_real, np_imag = np.real(cplx), np.imag(cplx) np_zeros = np_real * 0 - with self.test_session(use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()): + + with test_util.device(use_gpu=use_gpu): inx = ops.convert_to_tensor(cplx) tf_real = math_ops.real(inx) tf_imag = math_ops.imag(inx) tf_real_real = math_ops.real(tf_real) tf_imag_real = math_ops.imag(tf_real) - self.assertAllEqual(np_real, tf_real.eval()) - self.assertAllEqual(np_imag, tf_imag.eval()) - self.assertAllEqual(np_real, tf_real_real.eval()) - self.assertAllEqual(np_zeros, tf_imag_real.eval()) + self.assertAllEqual(np_real, self.evaluate(tf_real)) + self.assertAllEqual(np_imag, self.evaluate(tf_imag)) + self.assertAllEqual(np_real, self.evaluate(tf_real_real)) + self.assertAllEqual(np_zeros, self.evaluate(tf_imag_real)) def testRealImag64(self): real = (np.arange(-3, 3) / 4.).reshape([1, 3, 2]).astype(np.float32) @@ -876,12 +881,12 @@ class ComplexMakeRealImagTest(test.TestCase): def _compareAngle(self, cplx, use_gpu): np_angle = np.angle(cplx) - with self.test_session( - use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()) as sess: + + with test_util.device(use_gpu=use_gpu): inx = ops.convert_to_tensor(cplx) tf_angle = math_ops.angle(inx) - tf_angle_val = sess.run(tf_angle) + tf_angle_val = self.evaluate(tf_angle) + self.assertAllEqual(np_angle, tf_angle_val) self.assertShapeEqual(np_angle, tf_angle) @@ -903,6 +908,7 @@ class ComplexMakeRealImagTest(test.TestCase): # build failures on GPU (See #10643 for context). # self._compareAngle(cplx, use_gpu=True) + @test_util.run_deprecated_v1 def testRealReal(self): for dtype in (dtypes_lib.int32, dtypes_lib.int64, dtypes_lib.float32, dtypes_lib.float64): @@ -912,11 +918,10 @@ class ComplexMakeRealImagTest(test.TestCase): def _compareConj(self, cplx, use_gpu): np_ans = np.conj(cplx) - with self.test_session(use_gpu=use_gpu, - force_gpu=use_gpu and test_util.is_gpu_available()): + with test_util.device(use_gpu=use_gpu): inx = ops.convert_to_tensor(cplx) tf_conj = math_ops.conj(inx) - tf_ans = tf_conj.eval() + tf_ans = self.evaluate(tf_conj) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, tf_conj) @@ -934,6 +939,7 @@ class ComplexMakeRealImagTest(test.TestCase): self._compareConj(cplx, use_gpu=False) self._compareConj(cplx, use_gpu=True) + @test_util.run_deprecated_v1 def testConjReal(self): for dtype in (dtypes_lib.int32, dtypes_lib.int64, dtypes_lib.float16, dtypes_lib.float32, dtypes_lib.float64): @@ -941,6 +947,7 @@ class ComplexMakeRealImagTest(test.TestCase): y = math_ops.conj(x) self.assertEqual(x, y) + @test_util.run_deprecated_v1 def testConjString(self): x = array_ops.placeholder(dtypes_lib.string) with self.assertRaisesRegexp(TypeError, @@ -977,6 +984,7 @@ class ComplexMakeRealImagTest(test.TestCase): x_, list(x.shape), z, [1], x_init_value=x, delta=epsilon) self.assertAllClose(jacob_t, jacob_n, rtol=epsilon, atol=epsilon) + @test_util.run_deprecated_v1 def testGradient(self): # complex64 data = np.arange(1, 2, 0.10).reshape([5, 2]).astype(np.float32) @@ -1012,6 +1020,7 @@ class ComplexMakeRealImagTest(test.TestCase): inp, list(data.shape), loss, [1], x_init_value=data, delta=epsilon) self.assertAllClose(jacob_t, jacob_n, rtol=epsilon, atol=epsilon) + @test_util.run_deprecated_v1 def testMulGradient(self): data = np.arange(1, 2, 0.125).reshape([2, 4]).astype(np.float32) self._compareMulGradient(data) @@ -1032,13 +1041,13 @@ class AccumulateTest(test.TestCase): np_val = random_arrays[0] for random_array in random_arrays[1:]: np_val += random_array - self.assertAllClose(np_val, tf_val.eval()) + self.assertAllClose(np_val, self.evaluate(tf_val)) def testZeroArgs(self): with self.cached_session(): with self.assertRaises(ValueError): tf_val = math_ops.accumulate_n([]) - tf_val.eval() + self.evaluate(tf_val) def testWrongShape(self): with self.cached_session(): @@ -1070,7 +1079,7 @@ class PolyvalTest(test.TestCase): np_val = np.polyval(coeffs, x) with self.cached_session(): tf_val = math_ops.polyval(coeffs, x) - self.assertAllClose(np_val, tf_val.eval()) + self.assertAllClose(np_val, self.evaluate(tf_val)) def testSimple(self): for dtype in [ @@ -1093,7 +1102,7 @@ class PolyvalTest(test.TestCase): np_val = np.polyval(coeffs, x) with self.cached_session(): tf_val = math_ops.polyval(coeffs, x) - self.assertAllClose(np_val, tf_val.eval()) + self.assertAllClose(np_val, self.evaluate(tf_val)) def testEmpty(self): x = np.random.rand(2, 2).astype(np.float32) @@ -1101,7 +1110,7 @@ class PolyvalTest(test.TestCase): np_val = np.polyval(coeffs, x) with self.cached_session(): tf_val = math_ops.polyval(coeffs, x) - self.assertAllClose(np_val, tf_val.eval()) + self.assertAllClose(np_val, self.evaluate(tf_val)) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/cwise_ops_unary_test.py b/tensorflow/python/kernel_tests/cwise_ops_unary_test.py index 77f182784e..709a20f3d0 100644 --- a/tensorflow/python/kernel_tests/cwise_ops_unary_test.py +++ b/tensorflow/python/kernel_tests/cwise_ops_unary_test.py @@ -76,7 +76,7 @@ class UnaryOpTest(test.TestCase): if grad_atol is None: grad_atol = _default_tolerance(x.dtype) np_ans = np_func(x) - with self.test_session(use_gpu=False): + with self.cached_session(use_gpu=False): inx = ops.convert_to_tensor(x) if x.dtype in (np.float32, np.float64, dtypes_lib.bfloat16.as_numpy_dtype): @@ -84,7 +84,7 @@ class UnaryOpTest(test.TestCase): np_ans *= 1.1 else: y = tf_func(inx) - tf_cpu = y.eval() + tf_cpu = self.evaluate(y) self.assertShapeEqual(np_ans, y) if x.dtype == np.float16: self.assertAllClose(np_ans, tf_cpu, rtol=1e-3, atol=1e-3) @@ -121,26 +121,24 @@ class UnaryOpTest(test.TestCase): def _check(self, result_tensor, result_np, input_sp_t, tol): self.assertTrue(isinstance(result_tensor, sparse_tensor.SparseTensor)) self.assertTrue(isinstance(input_sp_t, sparse_tensor.SparseTensor)) - self.assertAllEqual(input_sp_t.indices.eval(), result_tensor.indices.eval()) - self.assertAllEqual(input_sp_t.dense_shape.eval(), - result_tensor.dense_shape.eval()) + self.assertAllEqual(input_sp_t.indices, result_tensor.indices) + self.assertAllEqual(input_sp_t.dense_shape, result_tensor.dense_shape) if tol is None: - self.assertAllClose(result_np, result_tensor.values.eval()) + self.assertAllClose(result_np, result_tensor.values) else: - self.assertAllClose( - result_np, result_tensor.values.eval(), rtol=tol, atol=tol) + self.assertAllClose(result_np, result_tensor.values, rtol=tol, atol=tol) def _compareSparseCpu(self, x, np_func, tf_func, tol): x_sp, x_sp_vals = _sparsify(x) res_np = np_func(x_sp_vals) - with self.test_session(use_gpu=False): + with test_util.force_cpu(): self._check(tf_func(x_sp), res_np, x_sp, tol) def _compareGpu(self, x, np_func, tf_func): np_ans = np_func(x) - with self.test_session(force_gpu=test_util.is_gpu_available()): + with test_util.use_gpu(): result = tf_func(ops.convert_to_tensor(x)) - tf_gpu = result.eval() + tf_gpu = self.evaluate(result) if x.dtype == np.float16: self.assertAllClose(np_ans, tf_gpu, rtol=1e-3, atol=1e-3) else: @@ -150,7 +148,7 @@ class UnaryOpTest(test.TestCase): def _compareSparseGpu(self, x, np_func, tf_func, tol): x_sp, x_sp_vals = _sparsify(x) res_np = np_func(x_sp_vals) - with self.test_session(force_gpu=test_util.is_gpu_available()): + with test_util.use_gpu(): self._check(tf_func(x_sp), res_np, x_sp, tol) def _compareBoth(self, x, np_func, tf_func): @@ -186,6 +184,7 @@ class UnaryOpTest(test.TestCase): return func + @test_util.run_deprecated_v1 def testFloatBasic(self): x = np.arange(-3, 3).reshape(1, 3, 2).astype(np.float32) w = x - x.min() + 1.02 # all greater than 1 @@ -240,12 +239,14 @@ class UnaryOpTest(test.TestCase): self._compareBothSparse(y, np.sign, math_ops.sign) self._compareBothSparse(x, np.vectorize(math.erf), math_ops.erf) + @test_util.run_deprecated_v1 def testFloatTanhEdge(self): x = np.arange(40, 40 + 6).reshape(6).astype(np.float32) self._compareBoth(x, np.tanh, math_ops.tanh) x = np.arange(-40, -40 + 6).reshape(6).astype(np.float32) self._compareBoth(x, np.tanh, math_ops.tanh) + @test_util.run_deprecated_v1 def testFloatEmpty(self): x = np.empty((2, 0, 5), dtype=np.float32) self._compareBoth(x, np.abs, math_ops.abs) @@ -291,6 +292,7 @@ class UnaryOpTest(test.TestCase): self._compareBothSparse(x, np.sign, math_ops.sign) self._compareBothSparse(x, np.sign, math_ops.erf) + @test_util.run_deprecated_v1 def testDoubleBasic(self): x = np.arange(-3, 3).reshape(1, 3, 2).astype(np.float64) w = x - x.min() + 1.02 # all greater than 1 @@ -344,6 +346,7 @@ class UnaryOpTest(test.TestCase): self._compareBothSparse(y, np.sign, math_ops.sign) self._compareBothSparse(x, np.vectorize(math.erf), math_ops.erf) + @test_util.run_deprecated_v1 def testHalfBasic(self): x = np.arange(-3, 3).reshape(1, 3, 2).astype(np.float16) y = (x + .5).astype(np.float16) # no zero @@ -416,6 +419,7 @@ class UnaryOpTest(test.TestCase): self._compareCpu(x, np.square, math_ops.square) self._compareBothSparse(x, np.square, math_ops.square) + @test_util.run_deprecated_v1 def testComplex64Basic(self): x = np.complex(1, 1) * np.arange(-3, 3).reshape(1, 3, 2).astype( np.complex64) @@ -460,6 +464,7 @@ class UnaryOpTest(test.TestCase): self._compareBoth(y, complex_sign, math_ops.sign) self._compareBothSparse(y, complex_sign, math_ops.sign) + @test_util.run_deprecated_v1 def testComplex128Basic(self): x = np.complex(1, 1) * np.arange(-3, 3).reshape(1, 3, 2).astype( np.complex128) @@ -499,6 +504,7 @@ class UnaryOpTest(test.TestCase): self._compareBoth(y, complex_sign, math_ops.sign) self._compareBothSparse(y, complex_sign, math_ops.sign) + @test_util.run_deprecated_v1 def testGradGrad(self): np.random.seed(7) shape = (5,) diff --git a/tensorflow/python/kernel_tests/decode_bmp_op_test.py b/tensorflow/python/kernel_tests/decode_bmp_op_test.py index eebaffbe13..5e7991382e 100644 --- a/tensorflow/python/kernel_tests/decode_bmp_op_test.py +++ b/tensorflow/python/kernel_tests/decode_bmp_op_test.py @@ -61,7 +61,7 @@ class DecodeBmpOpTest(test.TestCase): decode = array_ops.squeeze(image_ops.decode_bmp(img_in)) with self.cached_session(): - decoded = decode.eval() + decoded = self.evaluate(decode) self.assertAllEqual(decoded, img_bytes) def testGrayscale(self): @@ -136,7 +136,7 @@ class DecodeBmpOpTest(test.TestCase): decode = image_ops.decode_bmp(img_in) with self.cached_session(): - decoded = decode.eval() + decoded = self.evaluate(decode) self.assertAllEqual(decoded, img_bytes) diff --git a/tensorflow/python/kernel_tests/decode_compressed_op_test.py b/tensorflow/python/kernel_tests/decode_compressed_op_test.py index 1cc1c7da30..fd871c0090 100644 --- a/tensorflow/python/kernel_tests/decode_compressed_op_test.py +++ b/tensorflow/python/kernel_tests/decode_compressed_op_test.py @@ -24,6 +24,7 @@ import zlib from six import BytesIO from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import parsing_ops from tensorflow.python.platform import test @@ -42,6 +43,7 @@ class DecodeCompressedOpTest(test.TestCase): f.write(bytes_in) return out.getvalue() + @test_util.run_deprecated_v1 def testDecompress(self): for compression_type in ["ZLIB", "GZIP", ""]: with self.cached_session(): @@ -55,6 +57,7 @@ class DecodeCompressedOpTest(test.TestCase): self._compress(b"bBbb", compression_type)]}) self.assertAllEqual([b"AaAA", b"bBbb"], result) + @test_util.run_deprecated_v1 def testDecompressWithRaw(self): for compression_type in ["ZLIB", "GZIP", ""]: with self.cached_session(): diff --git a/tensorflow/python/kernel_tests/decode_image_op_test.py b/tensorflow/python/kernel_tests/decode_image_op_test.py index 0975f964b5..ba5770001a 100644 --- a/tensorflow/python/kernel_tests/decode_image_op_test.py +++ b/tensorflow/python/kernel_tests/decode_image_op_test.py @@ -23,6 +23,7 @@ import os.path import numpy as np from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import image_ops from tensorflow.python.ops import io_ops import tensorflow.python.ops.nn_grad # pylint: disable=unused-import @@ -40,10 +41,11 @@ class DecodeImageOpTest(test.TestCase): bmp0 = io_ops.read_file(path) image0 = image_ops.decode_image(bmp0) image1 = image_ops.decode_bmp(bmp0) - bmp0, image0, image1 = sess.run([bmp0, image0, image1]) + bmp0, image0, image1 = self.evaluate([bmp0, image0, image1]) self.assertEqual(len(bmp0), 4194) self.assertAllEqual(image0, image1) + @test_util.run_deprecated_v1 def testGif(self): # Read some real GIFs path = os.path.join(prefix_path, "gif", "testdata", "scan.gif") @@ -56,7 +58,7 @@ class DecodeImageOpTest(test.TestCase): gif0 = io_ops.read_file(path) image0 = image_ops.decode_image(gif0) image1 = image_ops.decode_gif(gif0) - gif0, image0, image1 = sess.run([gif0, image0, image1]) + gif0, image0, image1 = self.evaluate([gif0, image0, image1]) self.assertEqual(image0.shape, shape) self.assertAllEqual(image0, image1) @@ -76,8 +78,9 @@ class DecodeImageOpTest(test.TestCase): bad_channels = image_ops.decode_image(gif0, channels=1) with self.assertRaises(errors_impl.InvalidArgumentError): - bad_channels.eval() + self.evaluate(bad_channels) + @test_util.run_deprecated_v1 def testJpeg(self): # Read a real jpeg and verify shape path = os.path.join(prefix_path, "jpeg", "testdata", "jpeg_merge_test1.jpg") @@ -85,14 +88,14 @@ class DecodeImageOpTest(test.TestCase): jpeg0 = io_ops.read_file(path) image0 = image_ops.decode_image(jpeg0) image1 = image_ops.decode_jpeg(jpeg0) - jpeg0, image0, image1 = sess.run([jpeg0, image0, image1]) + jpeg0, image0, image1 = self.evaluate([jpeg0, image0, image1]) self.assertEqual(len(jpeg0), 3771) self.assertEqual(image0.shape, (256, 128, 3)) self.assertAllEqual(image0, image1) bad_channels = image_ops.decode_image(jpeg0, channels=4) with self.assertRaises(errors_impl.InvalidArgumentError): - bad_channels.eval() + self.evaluate(bad_channels) def testPng(self): # Read some real PNGs, converting to different channel numbers @@ -104,16 +107,17 @@ class DecodeImageOpTest(test.TestCase): png0 = io_ops.read_file(path) image0 = image_ops.decode_image(png0, channels=channels) image1 = image_ops.decode_png(png0, channels=channels) - png0, image0, image1 = sess.run([png0, image0, image1]) + png0, image0, image1 = self.evaluate([png0, image0, image1]) self.assertEqual(image0.shape, (26, 51, channels or channels_in)) self.assertAllEqual(image0, image1) + @test_util.run_deprecated_v1 def testInvalidBytes(self): image_bytes = b"ThisIsNotAnImage!" decode = image_ops.decode_image(image_bytes) with self.cached_session(): with self.assertRaises(errors_impl.InvalidArgumentError): - decode.eval() + self.evaluate(decode) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/decode_jpeg_op_test.py b/tensorflow/python/kernel_tests/decode_jpeg_op_test.py index 66b3e0f22f..f8fc28062f 100644 --- a/tensorflow/python/kernel_tests/decode_jpeg_op_test.py +++ b/tensorflow/python/kernel_tests/decode_jpeg_op_test.py @@ -80,7 +80,7 @@ class DecodeJpegBenchmark(test.Benchmark): initializer=image_ops.encode_jpeg(tiled_image)) with session.Session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) images = [] for _ in xrange(parallelism): if crop_window is None: @@ -105,11 +105,11 @@ class DecodeJpegBenchmark(test.Benchmark): for _ in xrange(3): # Skip warm up time. - sess.run(r) + self.evaluate(r) start_time = time.time() for _ in xrange(num_iters): - sess.run(r) + self.evaluate(r) end_time = time.time() return end_time - start_time diff --git a/tensorflow/python/kernel_tests/decode_png_op_test.py b/tensorflow/python/kernel_tests/decode_png_op_test.py index 8f36343667..5a0b742a6a 100644 --- a/tensorflow/python/kernel_tests/decode_png_op_test.py +++ b/tensorflow/python/kernel_tests/decode_png_op_test.py @@ -47,7 +47,7 @@ class DecodePngOpTest(test.TestCase): img_in, dtype=dtypes.uint16)) with self.cached_session(): - decoded = decode.eval() + decoded = self.evaluate(decode) self.assertAllEqual(decoded, img_bytes) diff --git a/tensorflow/python/kernel_tests/decode_raw_op_test.py b/tensorflow/python/kernel_tests/decode_raw_op_test.py index dcc984811c..008e59ba3e 100644 --- a/tensorflow/python/kernel_tests/decode_raw_op_test.py +++ b/tensorflow/python/kernel_tests/decode_raw_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import parsing_ops from tensorflow.python.platform import test @@ -28,6 +29,7 @@ from tensorflow.python.platform import test class DecodeRawOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testToUint8(self): with self.cached_session(): in_bytes = array_ops.placeholder(dtypes.string, shape=[2]) @@ -46,6 +48,7 @@ class DecodeRawOpTest(test.TestCase): "element 1 has size 5 != 6"): decode.eval(feed_dict={in_bytes: ["short", "longer"]}) + @test_util.run_deprecated_v1 def testToInt16(self): with self.cached_session(): in_bytes = array_ops.placeholder(dtypes.string, shape=[None]) @@ -61,6 +64,7 @@ class DecodeRawOpTest(test.TestCase): "size of int16"): decode.eval(feed_dict={in_bytes: ["123", "456"]}) + @test_util.run_deprecated_v1 def testEndianness(self): with self.cached_session(): in_bytes = array_ops.placeholder(dtypes.string, shape=[None]) @@ -73,6 +77,7 @@ class DecodeRawOpTest(test.TestCase): result = decode_be.eval(feed_dict={in_bytes: ["\x01\x02\x03\x04"]}) self.assertAllEqual([[0x01020304]], result) + @test_util.run_deprecated_v1 def testToFloat16(self): with self.cached_session(): in_bytes = array_ops.placeholder(dtypes.string, shape=[None]) @@ -84,6 +89,7 @@ class DecodeRawOpTest(test.TestCase): self.assertAllEqual(expected_result, result) + @test_util.run_deprecated_v1 def testEmptyStringInput(self): with self.cached_session(): in_bytes = array_ops.placeholder(dtypes.string, shape=[None]) @@ -93,6 +99,7 @@ class DecodeRawOpTest(test.TestCase): result = decode.eval(feed_dict={in_bytes: [""] * num_inputs}) self.assertEqual((num_inputs, 0), result.shape) + @test_util.run_deprecated_v1 def testToUInt16(self): with self.cached_session(): in_bytes = array_ops.placeholder(dtypes.string, shape=[None]) diff --git a/tensorflow/python/kernel_tests/denormal_test.py b/tensorflow/python/kernel_tests/denormal_test.py index 71a528c4aa..80a3033ecc 100644 --- a/tensorflow/python/kernel_tests/denormal_test.py +++ b/tensorflow/python/kernel_tests/denormal_test.py @@ -22,6 +22,7 @@ import numpy as np import platform from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test @@ -50,10 +51,12 @@ class DenormalTest(test.TestCase): # Make sure the flags don't leak out self.testPythonHasDenormals() + @test_util.run_deprecated_v1 def testFlushDenormalsCPU(self): # On CPUs, the processor flags flush for both single and double precision. self._flushDenormalsTest(use_gpu=False, dtypes=(np.float32, np.float64)) + @test_util.run_deprecated_v1 def testFlushDenormalsGPU(self): # On GPUs, only single precision can flush to zero. self._flushDenormalsTest(use_gpu=True, dtypes=(np.float32,)) diff --git a/tensorflow/python/kernel_tests/dense_update_ops_no_tsan_test.py b/tensorflow/python/kernel_tests/dense_update_ops_no_tsan_test.py index affbaf159d..4f74e1e741 100644 --- a/tensorflow/python/kernel_tests/dense_update_ops_no_tsan_test.py +++ b/tensorflow/python/kernel_tests/dense_update_ops_no_tsan_test.py @@ -20,6 +20,7 @@ from __future__ import print_function import numpy as np +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import state_ops @@ -32,6 +33,7 @@ class AssignOpTest(test.TestCase): # NOTE(mrry): We exclude thess tests from the TSAN TAP target, because they # contain benign and deliberate data races when multiple threads update # the same parameters without a lock. + @test_util.run_deprecated_v1 def testParallelUpdateWithoutLocking(self): with self.cached_session() as sess: ones_t = array_ops.fill([1024, 1024], 1.0) @@ -43,7 +45,7 @@ class AssignOpTest(test.TestCase): variables.global_variables_initializer().run() def run_add(add_op): - sess.run(add_op) + self.evaluate(add_op) threads = [ self.checkedThread( @@ -54,11 +56,12 @@ class AssignOpTest(test.TestCase): for t in threads: t.join() - vals = p.eval() + vals = self.evaluate(p) ones = np.ones((1024, 1024)).astype(np.float32) self.assertTrue((vals >= ones).all()) self.assertTrue((vals <= ones * 20).all()) + @test_util.run_deprecated_v1 def testParallelAssignWithoutLocking(self): with self.cached_session() as sess: ones_t = array_ops.fill([1024, 1024], float(1)) @@ -70,7 +73,7 @@ class AssignOpTest(test.TestCase): variables.global_variables_initializer().run() def run_assign(assign_op): - sess.run(assign_op) + self.evaluate(assign_op) threads = [ self.checkedThread( @@ -81,7 +84,7 @@ class AssignOpTest(test.TestCase): for t in threads: t.join() - vals = p.eval() + vals = self.evaluate(p) # Assert every element is taken from one of the assignments. self.assertTrue((vals > 0).all()) @@ -91,6 +94,7 @@ class AssignOpTest(test.TestCase): # contain non-benign but known data races between the variable assignment and # returning the output tensors. This issue will be resolved with the new # resource variables. + @test_util.run_deprecated_v1 def testParallelUpdateWithLocking(self): with self.cached_session() as sess: zeros_t = array_ops.fill([1024, 1024], 0.0) @@ -103,7 +107,7 @@ class AssignOpTest(test.TestCase): p.initializer.run() def run_add(add_op): - sess.run(add_op) + self.evaluate(add_op) threads = [ self.checkedThread( @@ -114,10 +118,11 @@ class AssignOpTest(test.TestCase): for t in threads: t.join() - vals = p.eval() + vals = self.evaluate(p) ones = np.ones((1024, 1024)).astype(np.float32) self.assertAllEqual(vals, ones * 20) + @test_util.run_deprecated_v1 def testParallelAssignWithLocking(self): with self.cached_session() as sess: zeros_t = array_ops.fill([1024, 1024], 0.0) @@ -131,7 +136,7 @@ class AssignOpTest(test.TestCase): p.initializer.run() def run_assign(assign_op): - sess.run(assign_op) + self.evaluate(assign_op) threads = [ self.checkedThread( @@ -142,7 +147,7 @@ class AssignOpTest(test.TestCase): for t in threads: t.join() - vals = p.eval() + vals = self.evaluate(p) # Assert every element is the same, and taken from one of the assignments. self.assertTrue(vals[0, 0] > 0) diff --git a/tensorflow/python/kernel_tests/dense_update_ops_test.py b/tensorflow/python/kernel_tests/dense_update_ops_test.py index 3e0a03d634..309da88bef 100644 --- a/tensorflow/python/kernel_tests/dense_update_ops_test.py +++ b/tensorflow/python/kernel_tests/dense_update_ops_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import state_ops from tensorflow.python.ops import variables @@ -36,8 +37,8 @@ class AssignOpTest(test.TestCase): p = variables.Variable(x) assign = state_ops.assign(p, y) p.initializer.run() - new_value = assign.eval() - return p.eval(), new_value + new_value = self.evaluate(assign) + return self.evaluate(p), new_value def _initAssignAddFetch(self, x, y, use_gpu=False): """Initialize a param to init, and compute param += y.""" @@ -45,8 +46,8 @@ class AssignOpTest(test.TestCase): p = variables.Variable(x) add = state_ops.assign_add(p, y) p.initializer.run() - new_value = add.eval() - return p.eval(), new_value + new_value = self.evaluate(add) + return self.evaluate(p), new_value def _initAssignSubFetch(self, x, y, use_gpu=False): """Initialize a param to init, and compute param -= y.""" @@ -54,8 +55,8 @@ class AssignOpTest(test.TestCase): p = variables.Variable(x) sub = state_ops.assign_sub(p, y) p.initializer.run() - new_value = sub.eval() - return p.eval(), new_value + new_value = self.evaluate(sub) + return self.evaluate(p), new_value def _testTypes(self, vals): for dtype in [np.float32, np.float64, np.int32, np.int64]: @@ -81,23 +82,26 @@ class AssignOpTest(test.TestCase): self.assertAllEqual(x - y, var_value) self.assertAllEqual(x - y, op_value) + @test_util.run_deprecated_v1 def testBasic(self): self._testTypes(np.arange(0, 20).reshape([4, 5])) + @test_util.run_deprecated_v1 def testAssignNonStrictShapeChecking(self): with self.cached_session(): data = array_ops.fill([1024, 1024], 0) p = variables.VariableV1([1]) a = state_ops.assign(p, data, validate_shape=False) a.op.run() - self.assertAllEqual(p.eval(), data.eval()) + self.assertAllEqual(p.eval(), self.evaluate(data)) # Assign to yet another shape data2 = array_ops.fill([10, 10], 1) a2 = state_ops.assign(p, data2, validate_shape=False) a2.op.run() - self.assertAllEqual(p.eval(), data2.eval()) + self.assertAllEqual(p.eval(), self.evaluate(data2)) + @test_util.run_deprecated_v1 def testInitRequiredAssignAdd(self): with self.cached_session(): p = variables.VariableV1(array_ops.fill([1024, 1024], 1), dtypes.int32) @@ -105,6 +109,7 @@ class AssignOpTest(test.TestCase): with self.assertRaisesOpError("use uninitialized"): a.op.run() + @test_util.run_deprecated_v1 def testInitRequiredAssignSub(self): with self.cached_session(): p = variables.VariableV1(array_ops.fill([1024, 1024], 1), dtypes.int32) diff --git a/tensorflow/python/kernel_tests/depthtospace_op_test.py b/tensorflow/python/kernel_tests/depthtospace_op_test.py index 13a28caf1f..96c9b5258e 100644 --- a/tensorflow/python/kernel_tests/depthtospace_op_test.py +++ b/tensorflow/python/kernel_tests/depthtospace_op_test.py @@ -53,12 +53,14 @@ class DepthToSpaceTest(test.TestCase): output_nhwc = test_util.NCHWToNHWC(output_nchw) self.assertAllEqual(output_nhwc.eval(), outputs) + @test_util.run_deprecated_v1 def testBasic(self): x_np = [[[[1, 2, 3, 4]]]] block_size = 2 x_out = [[[[1], [2]], [[3], [4]]]] self._testOne(x_np, block_size, x_out) + @test_util.run_deprecated_v1 def testBasicFloat16(self): x_np = [[[[1, 2, 3, 4]]]] block_size = 2 @@ -67,6 +69,7 @@ class DepthToSpaceTest(test.TestCase): # Tests for larger input dimensions. To make sure elements are # correctly ordered spatially. + @test_util.run_deprecated_v1 def testBlockSize2(self): x_np = [[[[1, 2, 3, 4], [5, 6, 7, 8]], @@ -79,6 +82,7 @@ class DepthToSpaceTest(test.TestCase): [[11], [12], [15], [16]]]] self._testOne(x_np, block_size, x_out) + @test_util.run_deprecated_v1 def testBlockSize2Batch10(self): block_size = 2 def batch_input_elt(i): @@ -106,15 +110,16 @@ class DepthToSpaceTest(test.TestCase): # test NHWC (default) on CPU x_tf = array_ops.depth_to_space(input_nhwc, block_size) self.assertAllEqual(x_tf.shape, x_out.shape) - x_tf.eval() + self.evaluate(x_tf) if test.is_gpu_available(): with self.cached_session(use_gpu=True): # test NHWC (default) on GPU x_tf = array_ops.depth_to_space(input_nhwc, block_size) self.assertAllEqual(x_tf.shape, x_out.shape) - x_tf.eval() + self.evaluate(x_tf) # Tests for different width and height. + @test_util.run_deprecated_v1 def testNonSquare(self): x_np = [[[[1, 10, 2, 20, 3, 30, 4, 40]], [[5, 50, 6, 60, 7, 70, 8, 80]], @@ -130,6 +135,7 @@ class DepthToSpaceTest(test.TestCase): # Tests for larger input dimensions. To make sure elements are # correctly ordered spatially. + @test_util.run_deprecated_v1 def testBlockSize4FlatInput(self): x_np = [[[[1, 2, 5, 6, 3, 4, 7, 8, 9, 10, 13, 14, 11, 12, 15, 16]]]] block_size = 4 @@ -141,6 +147,7 @@ class DepthToSpaceTest(test.TestCase): # Tests for larger input depths. # To make sure elements are properly interleaved in depth. + @test_util.run_deprecated_v1 def testDepthInterleaved(self): x_np = [[[[1, 10, 2, 20, 3, 30, 4, 40]]]] block_size = 2 @@ -150,6 +157,7 @@ class DepthToSpaceTest(test.TestCase): # Tests for larger input depths. Here an odd depth. # To make sure elements are properly interleaved in depth. + @test_util.run_deprecated_v1 def testDepthInterleavedDepth3(self): x_np = [[[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]]]] block_size = 2 @@ -159,6 +167,7 @@ class DepthToSpaceTest(test.TestCase): # Tests for larger input depths. # To make sure elements are properly interleaved in depth. + @test_util.run_deprecated_v1 def testDepthInterleavedLarger(self): x_np = [[[[1, 10, 2, 20, 3, 30, 4, 40], [5, 50, 6, 60, 7, 70, 8, 80]], @@ -175,6 +184,7 @@ class DepthToSpaceTest(test.TestCase): # Tests for a block larger for the depth. In this case should raise an # exception. + @test_util.run_deprecated_v1 def testBlockSizeTooLarge(self): x_np = [[[[1, 2, 3, 4], [5, 6, 7, 8]], @@ -185,18 +195,20 @@ class DepthToSpaceTest(test.TestCase): # divisible by 16. with self.assertRaises(ValueError): out_tf = array_ops.depth_to_space(x_np, block_size) - out_tf.eval() + self.evaluate(out_tf) # Test when the block size is 0. + @test_util.run_deprecated_v1 def testBlockSize0(self): x_np = [[[[1], [2]], [[3], [4]]]] block_size = 0 with self.assertRaises(ValueError): out_tf = array_ops.depth_to_space(x_np, block_size) - out_tf.eval() + self.evaluate(out_tf) # Test when the block size is 1. The block size should be > 1. + @test_util.run_deprecated_v1 def testBlockSizeOne(self): x_np = [[[[1, 1, 1, 1], [2, 2, 2, 2]], @@ -205,8 +217,9 @@ class DepthToSpaceTest(test.TestCase): block_size = 1 with self.assertRaises(ValueError): out_tf = array_ops.depth_to_space(x_np, block_size) - out_tf.eval() + self.evaluate(out_tf) + @test_util.run_deprecated_v1 def testBlockSizeLargerThanInput(self): # The block size is too large for this input. x_np = [[[[1], [2]], @@ -214,8 +227,9 @@ class DepthToSpaceTest(test.TestCase): block_size = 10 with self.assertRaises(ValueError): out_tf = array_ops.space_to_depth(x_np, block_size) - out_tf.eval() + self.evaluate(out_tf) + @test_util.run_deprecated_v1 def testBlockSizeNotDivisibleDepth(self): # The depth is not divisible by the square of the block size. x_np = [[[[1, 1, 1, 1], @@ -226,6 +240,7 @@ class DepthToSpaceTest(test.TestCase): with self.assertRaises(ValueError): _ = array_ops.space_to_depth(x_np, block_size) + @test_util.run_deprecated_v1 def testUnknownShape(self): t = array_ops.depth_to_space( array_ops.placeholder(dtypes.float32), block_size=4) @@ -277,7 +292,7 @@ class DepthToSpaceTest(test.TestCase): actual = array_ops.depth_to_space(t, block_size, data_format=data_format) with self.session(use_gpu=use_gpu) as sess: - actual_vals, expected_vals = sess.run([actual, expected]) + actual_vals, expected_vals = self.evaluate([actual, expected]) self.assertTrue(np.array_equal(actual_vals, expected_vals)) def testAgainstTranspose(self): @@ -343,11 +358,13 @@ class DepthToSpaceGradientTest(test.TestCase): # Don't use very large numbers as dimensions here, as the result is tensor # with cartesian product of the dimensions. + @test_util.run_deprecated_v1 def testSmall(self): block_size = 2 self._compare(3, 2, 5, 3, block_size, "NHWC") self._compare(3, 2, 5, 3, block_size, "NCHW") + @test_util.run_deprecated_v1 def testSmall2(self): block_size = 3 self._compare(1, 2, 3, 2, block_size, "NHWC") diff --git a/tensorflow/python/kernel_tests/depthwise_conv_op_test.py b/tensorflow/python/kernel_tests/depthwise_conv_op_test.py index 77b27c6c7e..f6d834c2f8 100644 --- a/tensorflow/python/kernel_tests/depthwise_conv_op_test.py +++ b/tensorflow/python/kernel_tests/depthwise_conv_op_test.py @@ -162,7 +162,7 @@ class DepthwiseConv2DTest(test.TestCase): conv_native = array_ops.transpose(conv_native, [0, 2, 3, 1]) try: - native_result = sess.run(conv_native) + native_result = self.evaluate(conv_native) except errors.InvalidArgumentError as e: # Grouped convolution kernel is only registered for cuDNN 7. Silently # return when we are running on an earlier version or without GPU. @@ -174,7 +174,7 @@ class DepthwiseConv2DTest(test.TestCase): conv_interface = nn_impl.depthwise_conv2d( t1, t2, strides=[1, stride, stride, 1], padding=padding) - interface_result = sess.run(conv_interface) + interface_result = self.evaluate(conv_interface) tf_logging.info( "data_type: %r, use_gpu: %r, grouped_conv: %r, max diff = %f", @@ -269,7 +269,7 @@ class DepthwiseConv2DTest(test.TestCase): t2 = constant_op.constant(x2, shape=filter_in_sizes) conv = nn_ops.depthwise_conv2d_native( t1, t2, strides=[1, stride, stride, 1], padding=padding) - value = sess.run(conv) + value = self.evaluate(conv) tf_logging.info("value = %r", value) self.assertArrayNear(expected, np.ravel(value), 1e-5) self.assertShapeEqual(value, conv) @@ -528,7 +528,7 @@ class DepthwiseConv2DTest(test.TestCase): t2 = constant_op.constant(x2, shape=output_sizes) backprop = nn_ops.depthwise_conv2d_native_backprop_input( t0, t1, t2, strides=[1, stride, stride, 1], padding=padding) - ret = backprop.eval() + ret = self.evaluate(backprop) self.assertShapeEqual(ret, backprop) return ret @@ -548,7 +548,7 @@ class DepthwiseConv2DTest(test.TestCase): t2 = constant_op.constant(x2, shape=output_sizes) backprop = nn_ops.depthwise_conv2d_native_backprop_input( t0, t1, t2, strides=[1, stride, stride, 1], padding=padding) - ret = backprop.eval() + ret = self.evaluate(backprop) self.assertShapeEqual(ret, backprop) return ret @@ -580,7 +580,7 @@ class DepthwiseConv2DTest(test.TestCase): t2 = constant_op.constant(x2, shape=output_sizes) backprop = nn_ops.depthwise_conv2d_native_backprop_filter( t0, t1, t2, strides=[1, stride, stride, 1], padding=padding) - ret = backprop.eval() + ret = self.evaluate(backprop) self.assertShapeEqual(ret, backprop) return ret @@ -600,7 +600,7 @@ class DepthwiseConv2DTest(test.TestCase): t2 = constant_op.constant(x2, shape=output_sizes) backprop = nn_ops.depthwise_conv2d_native_backprop_filter( t0, t1, t2, strides=[1, stride, stride, 1], padding=padding) - ret = backprop.eval() + ret = self.evaluate(backprop) self.assertShapeEqual(ret, backprop) return ret diff --git a/tensorflow/python/kernel_tests/determinant_op_test.py b/tensorflow/python/kernel_tests/determinant_op_test.py index da33b2848b..d6ef9e70b8 100644 --- a/tensorflow/python/kernel_tests/determinant_op_test.py +++ b/tensorflow/python/kernel_tests/determinant_op_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_linalg_ops from tensorflow.python.ops import linalg_ops @@ -35,7 +36,7 @@ from tensorflow.python.platform import test class DeterminantOpTest(test.TestCase): def _compareDeterminantBase(self, matrix_x, tf_ans): - out = tf_ans.eval() + out = self.evaluate(tf_ans) shape = matrix_x.shape if shape[-1] == 0 and shape[-2] == 0: np_ans = np.ones(shape[:-2]).astype(matrix_x.dtype) @@ -54,15 +55,15 @@ class DeterminantOpTest(test.TestCase): np_ans = np_ans.astype(matrix_x.dtype) self.assertShapeEqual(np_ans, abs_log_det_tf) - sign_tf_val = sign_tf.eval() - abs_log_det_tf_val = abs_log_det_tf.eval() + sign_tf_val = self.evaluate(sign_tf) + abs_log_det_tf_val = self.evaluate(abs_log_det_tf) self.assertAllClose( sign_tf_val * np.exp(abs_log_det_tf_val), np_sign * np.exp(np_ans), atol=5e-5) def _compareDeterminant(self, matrix_x): - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): self._compareDeterminantBase(matrix_x, linalg_ops.matrix_determinant(matrix_x)) self._compareLogDeterminantBase( @@ -155,7 +156,7 @@ class DeterminantOpTest(test.TestCase): matrix2 = random_ops.random_normal([5, 5], seed=42) det1 = linalg_ops.matrix_determinant(matrix1) det2 = linalg_ops.matrix_determinant(matrix2) - det1_val, det2_val = sess.run([det1, det2]) + det1_val, det2_val = self.evaluate([det1, det2]) self.assertEqual(det1_val, det2_val) diff --git a/tensorflow/python/kernel_tests/diag_op_test.py b/tensorflow/python/kernel_tests/diag_op_test.py index 9e43258fa2..ed2a9e8e47 100644 --- a/tensorflow/python/kernel_tests/diag_op_test.py +++ b/tensorflow/python/kernel_tests/diag_op_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes as dtypes_lib from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl @@ -31,6 +32,7 @@ from tensorflow.python.platform import tf_logging class MatrixDiagTest(test.TestCase): + @test_util.run_deprecated_v1 def testVector(self): with self.session(use_gpu=True): v = np.array([1.0, 2.0, 3.0]) @@ -49,6 +51,7 @@ class MatrixDiagTest(test.TestCase): self.assertEqual((2, 3, 3), v_batch_diag.get_shape()) self.assertAllEqual(v_batch_diag.eval(), mat_batch) + @test_util.run_deprecated_v1 def testBatchVector(self): self._testBatchVector(np.float32) self._testBatchVector(np.float64) @@ -56,16 +59,19 @@ class MatrixDiagTest(test.TestCase): self._testBatchVector(np.int64) self._testBatchVector(np.bool) + @test_util.run_deprecated_v1 def testInvalidShape(self): with self.assertRaisesRegexp(ValueError, "must be at least rank 1"): array_ops.matrix_diag(0) + @test_util.run_deprecated_v1 def testInvalidShapeAtEval(self): with self.session(use_gpu=True): v = array_ops.placeholder(dtype=dtypes_lib.float32) with self.assertRaisesOpError("input must be at least 1-dim"): array_ops.matrix_diag(v).eval(feed_dict={v: 0.0}) + @test_util.run_deprecated_v1 def testGrad(self): shapes = ((3,), (7, 4)) with self.session(use_gpu=True): @@ -81,6 +87,7 @@ class MatrixDiagTest(test.TestCase): class MatrixSetDiagTest(test.TestCase): + @test_util.run_deprecated_v1 def testSquare(self): with self.session(use_gpu=True): v = np.array([1.0, 2.0, 3.0]) @@ -89,8 +96,9 @@ class MatrixSetDiagTest(test.TestCase): [1.0, 1.0, 3.0]]) output = array_ops.matrix_set_diag(mat, v) self.assertEqual((3, 3), output.get_shape()) - self.assertAllEqual(mat_set_diag, output.eval()) + self.assertAllEqual(mat_set_diag, self.evaluate(output)) + @test_util.run_deprecated_v1 def testRectangular(self): with self.session(use_gpu=True): v = np.array([3.0, 4.0]) @@ -98,14 +106,14 @@ class MatrixSetDiagTest(test.TestCase): expected = np.array([[3.0, 1.0, 0.0], [1.0, 4.0, 1.0]]) output = array_ops.matrix_set_diag(mat, v) self.assertEqual((2, 3), output.get_shape()) - self.assertAllEqual(expected, output.eval()) + self.assertAllEqual(expected, self.evaluate(output)) v = np.array([3.0, 4.0]) mat = np.array([[0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]) expected = np.array([[3.0, 1.0], [1.0, 4.0], [1.0, 1.0]]) output = array_ops.matrix_set_diag(mat, v) self.assertEqual((3, 2), output.get_shape()) - self.assertAllEqual(expected, output.eval()) + self.assertAllEqual(expected, self.evaluate(output)) def _testSquareBatch(self, dtype): with self.cached_session(use_gpu=True): @@ -121,8 +129,9 @@ class MatrixSetDiagTest(test.TestCase): output = array_ops.matrix_set_diag(mat_batch, v_batch) self.assertEqual((2, 3, 3), output.get_shape()) - self.assertAllEqual(mat_set_diag_batch, output.eval()) + self.assertAllEqual(mat_set_diag_batch, self.evaluate(output)) + @test_util.run_deprecated_v1 def testSquareBatch(self): self._testSquareBatch(np.float32) self._testSquareBatch(np.float64) @@ -130,6 +139,7 @@ class MatrixSetDiagTest(test.TestCase): self._testSquareBatch(np.int64) self._testSquareBatch(np.bool) + @test_util.run_deprecated_v1 def testRectangularBatch(self): with self.session(use_gpu=True): v_batch = np.array([[-1.0, -2.0], [-4.0, -5.0]]) @@ -140,14 +150,16 @@ class MatrixSetDiagTest(test.TestCase): [[-4.0, 0.0, 4.0], [0.0, -5.0, 0.0]]]) output = array_ops.matrix_set_diag(mat_batch, v_batch) self.assertEqual((2, 2, 3), output.get_shape()) - self.assertAllEqual(mat_set_diag_batch, output.eval()) + self.assertAllEqual(mat_set_diag_batch, self.evaluate(output)) + @test_util.run_deprecated_v1 def testInvalidShape(self): with self.assertRaisesRegexp(ValueError, "must be at least rank 2"): array_ops.matrix_set_diag(0, [0]) with self.assertRaisesRegexp(ValueError, "must be at least rank 1"): array_ops.matrix_set_diag([[0]], 0) + @test_util.run_deprecated_v1 def testInvalidShapeAtEval(self): with self.session(use_gpu=True): v = array_ops.placeholder(dtype=dtypes_lib.float32) @@ -157,6 +169,7 @@ class MatrixSetDiagTest(test.TestCase): r"but received input shape: \[1,1\] and diagonal shape: \[\]"): array_ops.matrix_set_diag([[v]], v).eval(feed_dict={v: 0.0}) + @test_util.run_deprecated_v1 def testGrad(self): shapes = ((3, 4, 4), (3, 3, 4), (3, 4, 3), (7, 4, 8, 8)) with self.session(use_gpu=True): @@ -178,6 +191,7 @@ class MatrixSetDiagTest(test.TestCase): y.get_shape().as_list()) self.assertLess(error_x_diag, 1e-4) + @test_util.run_deprecated_v1 def testGradWithNoShapeInformation(self): with self.session(use_gpu=True) as sess: v = array_ops.placeholder(dtype=dtypes_lib.float32) @@ -200,6 +214,7 @@ class MatrixSetDiagTest(test.TestCase): class MatrixDiagPartTest(test.TestCase): + @test_util.run_deprecated_v1 def testSquare(self): with self.session(use_gpu=True): v = np.array([1.0, 2.0, 3.0]) @@ -208,6 +223,7 @@ class MatrixDiagPartTest(test.TestCase): self.assertEqual((3,), mat_diag.get_shape()) self.assertAllEqual(mat_diag.eval(), v) + @test_util.run_deprecated_v1 def testRectangular(self): with self.session(use_gpu=True): mat = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) @@ -228,6 +244,7 @@ class MatrixDiagPartTest(test.TestCase): self.assertEqual((2, 3), mat_batch_diag.get_shape()) self.assertAllEqual(mat_batch_diag.eval(), v_batch) + @test_util.run_deprecated_v1 def testSquareBatch(self): self._testSquareBatch(np.float32) self._testSquareBatch(np.float64) @@ -235,6 +252,7 @@ class MatrixDiagPartTest(test.TestCase): self._testSquareBatch(np.int64) self._testSquareBatch(np.bool) + @test_util.run_deprecated_v1 def testRectangularBatch(self): with self.session(use_gpu=True): v_batch = np.array([[1.0, 2.0], [4.0, 5.0]]) @@ -245,16 +263,19 @@ class MatrixDiagPartTest(test.TestCase): self.assertEqual((2, 2), mat_batch_diag.get_shape()) self.assertAllEqual(mat_batch_diag.eval(), v_batch) + @test_util.run_deprecated_v1 def testInvalidShape(self): with self.assertRaisesRegexp(ValueError, "must be at least rank 2"): array_ops.matrix_diag_part(0) + @test_util.run_deprecated_v1 def testInvalidShapeAtEval(self): with self.session(use_gpu=True): v = array_ops.placeholder(dtype=dtypes_lib.float32) with self.assertRaisesOpError("input must be at least 2-dim"): array_ops.matrix_diag_part(v).eval(feed_dict={v: 0.0}) + @test_util.run_deprecated_v1 def testGrad(self): shapes = ((3, 3), (2, 3), (3, 2), (5, 3, 3)) with self.session(use_gpu=True): @@ -273,9 +294,9 @@ class DiagTest(test.TestCase): def _diagOp(self, diag, dtype, expected_ans, use_gpu): with self.cached_session(use_gpu=use_gpu): tf_ans = array_ops.diag(ops.convert_to_tensor(diag.astype(dtype))) - out = tf_ans.eval() + out = self.evaluate(tf_ans) tf_ans_inv = array_ops.diag_part(expected_ans) - inv_out = tf_ans_inv.eval() + inv_out = self.evaluate(tf_ans_inv) self.assertAllClose(out, expected_ans) self.assertAllClose(inv_out, diag) self.assertShapeEqual(expected_ans, tf_ans) @@ -407,6 +428,7 @@ class DiagTest(test.TestCase): dtype=dtype) self.diagOp(x, dtype, expected_ans) + @test_util.run_deprecated_v1 def testInvalidRank(self): with self.assertRaisesRegexp(ValueError, "must be at least rank 1"): array_ops.diag(0.0) @@ -421,7 +443,7 @@ class DiagPartOpTest(test.TestCase): with self.cached_session(use_gpu=use_gpu): tensor = ops.convert_to_tensor(tensor.astype(dtype)) tf_ans_inv = array_ops.diag_part(tensor) - inv_out = tf_ans_inv.eval() + inv_out = self.evaluate(tf_ans_inv) self.assertAllClose(inv_out, expected_ans) self.assertShapeEqual(expected_ans, tf_ans_inv) @@ -445,7 +467,7 @@ class DiagPartOpTest(test.TestCase): t = ops.convert_to_tensor(x.astype(np.float32)) t.set_shape(shape) tf_ans = array_ops.diag_part(t) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertAllClose(out, expected_ans) self.assertShapeEqual(expected_ans, tf_ans) @@ -476,6 +498,7 @@ class DiagPartOpTest(test.TestCase): self.diagPartOp(x, np.complex64, expected_ans) self.diagPartOp(x, np.complex128, expected_ans) + @test_util.run_deprecated_v1 def testOddRank(self): w = np.random.rand(2) x = np.random.rand(2, 2, 2) @@ -484,6 +507,7 @@ class DiagPartOpTest(test.TestCase): with self.assertRaises(ValueError): array_ops.diag_part(0.0) + @test_util.run_deprecated_v1 def testUnevenDimensions(self): w = np.random.rand(2, 5) x = np.random.rand(2, 1, 2, 3) @@ -493,6 +517,7 @@ class DiagPartOpTest(test.TestCase): class DiagGradOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testDiagGrad(self): np.random.seed(0) shapes = ((3,), (3, 3), (3, 3, 3)) @@ -513,6 +538,7 @@ class DiagGradOpTest(test.TestCase): class DiagGradPartOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testDiagPartGrad(self): np.random.seed(0) shapes = ((3, 3), (3, 3, 3, 3)) diff --git a/tensorflow/python/kernel_tests/distributions/bernoulli_test.py b/tensorflow/python/kernel_tests/distributions/bernoulli_test.py index 37b35ba51a..e6d560b4bc 100644 --- a/tensorflow/python/kernel_tests/distributions/bernoulli_test.py +++ b/tensorflow/python/kernel_tests/distributions/bernoulli_test.py @@ -151,6 +151,7 @@ class BernoulliTest(test.TestCase): self.assertAllClose(self.evaluate(dist.prob(x)), expected_pmf) self.assertAllClose(self.evaluate(dist.log_prob(x)), np.log(expected_pmf)) + @test_util.run_deprecated_v1 def testPmfCorrectBroadcastDynamicShape(self): with self.cached_session(): p = array_ops.placeholder(dtype=dtypes.float32) @@ -167,6 +168,7 @@ class BernoulliTest(test.TestCase): }), [[0.2, 0.7, 0.4]]) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testPmfInvalid(self): p = [0.1, 0.2, 0.7] dist = bernoulli.Bernoulli(probs=p, validate_args=True) @@ -193,6 +195,7 @@ class BernoulliTest(test.TestCase): self.evaluate( bernoulli.Bernoulli(probs=p, validate_args=False).log_prob(samps))) + @test_util.run_deprecated_v1 def testBroadcasting(self): with self.cached_session(): p = array_ops.placeholder(dtypes.float32) @@ -207,6 +210,7 @@ class BernoulliTest(test.TestCase): p: [0.5, 0.5, 0.5] })) + @test_util.run_deprecated_v1 def testPmfShapes(self): with self.cached_session(): p = array_ops.placeholder(dtypes.float32, shape=[None, 1]) @@ -276,6 +280,7 @@ class BernoulliTest(test.TestCase): grad_p = tape.gradient(samples, p) self.assertIsNone(grad_p) + @test_util.run_deprecated_v1 def testSampleActsLikeSampleN(self): with self.cached_session() as sess: p = [0.2, 0.6] diff --git a/tensorflow/python/kernel_tests/distributions/bijector_test.py b/tensorflow/python/kernel_tests/distributions/bijector_test.py index e20f59f48a..a0e0a36fec 100644 --- a/tensorflow/python/kernel_tests/distributions/bijector_test.py +++ b/tensorflow/python/kernel_tests/distributions/bijector_test.py @@ -132,6 +132,7 @@ class BijectorTestEventNdims(test.TestCase): with self.assertRaisesRegexp(ValueError, "Expected scalar"): bij.inverse_log_det_jacobian(1., event_ndims=(1, 2)) + @test_util.run_deprecated_v1 def testBijectorDynamicEventNdims(self): bij = BrokenBijector(validate_args=True) event_ndims = array_ops.placeholder(dtype=np.int32, shape=None) @@ -301,6 +302,7 @@ class BijectorReduceEventDimsTest(test.TestCase): 8., self.evaluate(bij.inverse_log_det_jacobian(x, event_ndims=2))) + @test_util.run_deprecated_v1 def testHandlesNonStaticEventNdims(self): x_ = [[[1., 2.], [3., 4.]]] x = array_ops.placeholder_with_default(x_, shape=None) diff --git a/tensorflow/python/kernel_tests/distributions/categorical_test.py b/tensorflow/python/kernel_tests/distributions/categorical_test.py index c6bb06eab3..ec1d4ed207 100644 --- a/tensorflow/python/kernel_tests/distributions/categorical_test.py +++ b/tensorflow/python/kernel_tests/distributions/categorical_test.py @@ -25,6 +25,7 @@ from tensorflow.python.eager import backprop from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import tensor_util +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import math_ops @@ -44,6 +45,7 @@ def make_categorical(batch_shape, num_classes, dtype=dtypes.int32): class CategoricalTest(test.TestCase, parameterized.TestCase): + @test_util.run_deprecated_v1 def testP(self): p = [0.2, 0.8] dist = categorical.Categorical(probs=p) @@ -51,6 +53,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): self.assertAllClose(p, dist.probs.eval()) self.assertAllEqual([2], dist.logits.get_shape()) + @test_util.run_deprecated_v1 def testLogits(self): p = np.array([0.2, 0.8], dtype=np.float32) logits = np.log(p) - 50. @@ -61,6 +64,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): self.assertAllClose(dist.probs.eval(), p) self.assertAllClose(dist.logits.eval(), logits) + @test_util.run_deprecated_v1 def testShapes(self): with self.cached_session(): for batch_shape in ([], [1], [2, 3, 4]): @@ -107,6 +111,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): self.assertEqual(dist.dtype, dtype) self.assertEqual(dist.dtype, dist.sample(5).dtype) + @test_util.run_deprecated_v1 def testUnknownShape(self): with self.cached_session(): logits = array_ops.placeholder(dtype=dtypes.float32) @@ -121,18 +126,21 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): feed_dict={logits: [[-1000.0, 1000.0], [1000.0, -1000.0]]}) self.assertAllEqual([1, 0], sample_value_batch) + @test_util.run_deprecated_v1 def testPMFWithBatch(self): histograms = [[0.2, 0.8], [0.6, 0.4]] dist = categorical.Categorical(math_ops.log(histograms) - 50.) with self.cached_session(): self.assertAllClose(dist.prob([0, 1]).eval(), [0.2, 0.4]) + @test_util.run_deprecated_v1 def testPMFNoBatch(self): histograms = [0.2, 0.8] dist = categorical.Categorical(math_ops.log(histograms) - 50.) with self.cached_session(): self.assertAllClose(dist.prob(0).eval(), 0.2) + @test_util.run_deprecated_v1 def testCDFWithDynamicEventShapeKnownNdims(self): """Test that dynamically-sized events with unknown shape work.""" batch_size = 2 @@ -184,6 +192,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): actual_cdf = self.evaluate(cdf_op) self.assertAllClose(actual_cdf, expected_cdf) + @test_util.run_deprecated_v1 def testCDFWithBatch(self): histograms = [[0.1, 0.2, 0.3, 0.25, 0.15], [0.0, 0.75, 0.2, 0.05, 0.0]] @@ -195,6 +204,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): with self.cached_session(): self.assertAllClose(cdf_op.eval(), expected_cdf) + @test_util.run_deprecated_v1 def testCDFNoBatch(self): histogram = [0.1, 0.2, 0.3, 0.4] event = 2 @@ -205,6 +215,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): with self.cached_session(): self.assertAlmostEqual(cdf_op.eval(), expected_cdf) + @test_util.run_deprecated_v1 def testCDFBroadcasting(self): # shape: [batch=2, n_bins=3] histograms = [[0.2, 0.1, 0.7], @@ -287,7 +298,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): } with self.cached_session() as sess: - run_result = sess.run(to_run) + run_result = self.evaluate(to_run) self.assertAllEqual(run_result["cat_prob"].shape, run_result["norm_prob"].shape) @@ -298,6 +309,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): self.assertAllEqual(run_result["cat_log_cdf"].shape, run_result["norm_log_cdf"].shape) + @test_util.run_deprecated_v1 def testLogPMF(self): logits = np.log([[0.2, 0.8], [0.6, 0.4]]) - 50. dist = categorical.Categorical(logits) @@ -305,6 +317,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): self.assertAllClose(dist.log_prob([0, 1]).eval(), np.log([0.2, 0.4])) self.assertAllClose(dist.log_prob([0.0, 1.0]).eval(), np.log([0.2, 0.4])) + @test_util.run_deprecated_v1 def testEntropyNoBatch(self): logits = np.log([0.2, 0.8]) - 50. dist = categorical.Categorical(logits) @@ -312,6 +325,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): self.assertAllClose(dist.entropy().eval(), -(0.2 * np.log(0.2) + 0.8 * np.log(0.8))) + @test_util.run_deprecated_v1 def testEntropyWithBatch(self): logits = np.log([[0.2, 0.8], [0.6, 0.4]]) - 50. dist = categorical.Categorical(logits) @@ -321,6 +335,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): -(0.6 * np.log(0.6) + 0.4 * np.log(0.4)) ]) + @test_util.run_deprecated_v1 def testEntropyGradient(self): with self.cached_session() as sess: logits = constant_op.constant([[1., 2., 3.], [2., 5., 1.]]) @@ -355,7 +370,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): samples = dist.sample(n, seed=123) samples.set_shape([n, 1, 2]) self.assertEqual(samples.dtype, dtypes.int32) - sample_values = samples.eval() + sample_values = self.evaluate(samples) self.assertFalse(np.any(sample_values < 0)) self.assertFalse(np.any(sample_values > 1)) self.assertAllClose( @@ -371,7 +386,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): dist = categorical.Categorical(math_ops.log(histograms) - 50.) samples = dist.sample((100, 100), seed=123) prob = dist.prob(samples) - prob_val = prob.eval() + prob_val = self.evaluate(prob) self.assertAllClose( [0.2**2 + 0.8**2], [prob_val[:, :, :, 0].mean()], atol=1e-2) self.assertAllClose( @@ -393,26 +408,26 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): dist = categorical.Categorical(math_ops.log(histograms) - 50.) prob = dist.prob(1) - self.assertAllClose([[0.8, 0.6]], prob.eval()) + self.assertAllClose([[0.8, 0.6]], self.evaluate(prob)) prob = dist.prob([1]) - self.assertAllClose([[0.8, 0.6]], prob.eval()) + self.assertAllClose([[0.8, 0.6]], self.evaluate(prob)) prob = dist.prob([0, 1]) - self.assertAllClose([[0.2, 0.6]], prob.eval()) + self.assertAllClose([[0.2, 0.6]], self.evaluate(prob)) prob = dist.prob([[0, 1]]) - self.assertAllClose([[0.2, 0.6]], prob.eval()) + self.assertAllClose([[0.2, 0.6]], self.evaluate(prob)) prob = dist.prob([[[0, 1]]]) - self.assertAllClose([[[0.2, 0.6]]], prob.eval()) + self.assertAllClose([[[0.2, 0.6]]], self.evaluate(prob)) prob = dist.prob([[1, 0], [0, 1]]) - self.assertAllClose([[0.8, 0.4], [0.2, 0.6]], prob.eval()) + self.assertAllClose([[0.8, 0.4], [0.2, 0.6]], self.evaluate(prob)) prob = dist.prob([[[1, 1], [1, 0]], [[1, 0], [0, 1]]]) self.assertAllClose([[[0.8, 0.6], [0.8, 0.4]], [[0.8, 0.4], [0.2, 0.6]]], - prob.eval()) + self.evaluate(prob)) def testLogPMFShape(self): with self.cached_session(): @@ -440,12 +455,14 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): self.assertEqual(3, log_prob.get_shape().ndims) self.assertAllEqual([2, 2, 2], log_prob.get_shape()) + @test_util.run_deprecated_v1 def testMode(self): with self.cached_session(): histograms = [[[0.2, 0.8], [0.6, 0.4]]] dist = categorical.Categorical(math_ops.log(histograms) - 50.) self.assertAllEqual(dist.mode().eval(), [[1, 0]]) + @test_util.run_deprecated_v1 def testCategoricalCategoricalKL(self): def np_softmax(logits): @@ -462,7 +479,7 @@ class CategoricalTest(test.TestCase, parameterized.TestCase): b = categorical.Categorical(logits=b_logits) kl = kullback_leibler.kl_divergence(a, b) - kl_val = sess.run(kl) + kl_val = self.evaluate(kl) # Make sure KL(a||a) is 0 kl_same = sess.run(kullback_leibler.kl_divergence(a, a)) diff --git a/tensorflow/python/kernel_tests/distributions/dirichlet_multinomial_test.py b/tensorflow/python/kernel_tests/distributions/dirichlet_multinomial_test.py index d558ca09cc..c530037e1e 100644 --- a/tensorflow/python/kernel_tests/distributions/dirichlet_multinomial_test.py +++ b/tensorflow/python/kernel_tests/distributions/dirichlet_multinomial_test.py @@ -22,6 +22,7 @@ from tensorflow.python.eager import backprop from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops.distributions import dirichlet_multinomial @@ -36,6 +37,7 @@ class DirichletMultinomialTest(test.TestCase): def setUp(self): self._rng = np.random.RandomState(42) + @test_util.run_deprecated_v1 def testSimpleShapes(self): with self.cached_session(): alpha = np.random.rand(3) @@ -45,6 +47,7 @@ class DirichletMultinomialTest(test.TestCase): self.assertEqual(tensor_shape.TensorShape([3]), dist.event_shape) self.assertEqual(tensor_shape.TensorShape([]), dist.batch_shape) + @test_util.run_deprecated_v1 def testComplexShapes(self): with self.cached_session(): alpha = np.random.rand(3, 2, 2) @@ -55,6 +58,7 @@ class DirichletMultinomialTest(test.TestCase): self.assertEqual(tensor_shape.TensorShape([2]), dist.event_shape) self.assertEqual(tensor_shape.TensorShape([3, 2]), dist.batch_shape) + @test_util.run_deprecated_v1 def testNproperty(self): alpha = [[1., 2, 3]] n = [[5.]] @@ -63,6 +67,7 @@ class DirichletMultinomialTest(test.TestCase): self.assertEqual([1, 1], dist.total_count.get_shape()) self.assertAllClose(n, dist.total_count.eval()) + @test_util.run_deprecated_v1 def testAlphaProperty(self): alpha = [[1., 2, 3]] with self.cached_session(): @@ -70,6 +75,7 @@ class DirichletMultinomialTest(test.TestCase): self.assertEqual([1, 3], dist.concentration.get_shape()) self.assertAllClose(alpha, dist.concentration.eval()) + @test_util.run_deprecated_v1 def testPmfNandCountsAgree(self): alpha = [[1., 2, 3]] n = [[5.]] @@ -83,6 +89,7 @@ class DirichletMultinomialTest(test.TestCase): "last-dimension must sum to `self.total_count`"): dist.prob([3., 3, 0]).eval() + @test_util.run_deprecated_v1 def testPmfNonIntegerCounts(self): alpha = [[1., 2, 3]] n = [[5.]] @@ -110,7 +117,7 @@ class DirichletMultinomialTest(test.TestCase): counts = [1., 0] dist = ds.DirichletMultinomial(1., alpha) pmf = dist.prob(counts) - self.assertAllClose(1 / 3., pmf.eval()) + self.assertAllClose(1 / 3., self.evaluate(pmf)) self.assertEqual((), pmf.get_shape()) def testPmfBothZeroBatchesNontrivialN(self): @@ -122,7 +129,7 @@ class DirichletMultinomialTest(test.TestCase): counts = [3., 2] dist = ds.DirichletMultinomial(5., alpha) pmf = dist.prob(counts) - self.assertAllClose(1 / 7., pmf.eval()) + self.assertAllClose(1 / 7., self.evaluate(pmf)) self.assertEqual((), pmf.get_shape()) def testPmfBothZeroBatchesMultidimensionalN(self): @@ -134,7 +141,7 @@ class DirichletMultinomialTest(test.TestCase): n = np.full([4, 3], 5., dtype=np.float32) dist = ds.DirichletMultinomial(n, alpha) pmf = dist.prob(counts) - self.assertAllClose([[1 / 7., 1 / 7., 1 / 7.]] * 4, pmf.eval()) + self.assertAllClose([[1 / 7., 1 / 7., 1 / 7.]] * 4, self.evaluate(pmf)) self.assertEqual((4, 3), pmf.get_shape()) def testPmfAlphaStretchedInBroadcastWhenSameRank(self): @@ -145,7 +152,7 @@ class DirichletMultinomialTest(test.TestCase): counts = [[1., 0], [0., 1]] dist = ds.DirichletMultinomial([1.], alpha) pmf = dist.prob(counts) - self.assertAllClose([1 / 3., 2 / 3.], pmf.eval()) + self.assertAllClose([1 / 3., 2 / 3.], self.evaluate(pmf)) self.assertAllEqual([2], pmf.get_shape()) def testPmfAlphaStretchedInBroadcastWhenLowerRank(self): @@ -155,7 +162,7 @@ class DirichletMultinomialTest(test.TestCase): alpha = [1., 2] counts = [[1., 0], [0., 1]] pmf = ds.DirichletMultinomial(1., alpha).prob(counts) - self.assertAllClose([1 / 3., 2 / 3.], pmf.eval()) + self.assertAllClose([1 / 3., 2 / 3.], self.evaluate(pmf)) self.assertAllEqual([2], pmf.get_shape()) def testPmfCountsStretchedInBroadcastWhenSameRank(self): @@ -165,7 +172,7 @@ class DirichletMultinomialTest(test.TestCase): alpha = [[1., 2], [2., 3]] counts = [[1., 0]] pmf = ds.DirichletMultinomial([1., 1.], alpha).prob(counts) - self.assertAllClose([1 / 3., 2 / 5.], pmf.eval()) + self.assertAllClose([1 / 3., 2 / 5.], self.evaluate(pmf)) self.assertAllEqual([2], pmf.get_shape()) def testPmfCountsStretchedInBroadcastWhenLowerRank(self): @@ -175,9 +182,10 @@ class DirichletMultinomialTest(test.TestCase): alpha = [[1., 2], [2., 3]] counts = [1., 0] pmf = ds.DirichletMultinomial(1., alpha).prob(counts) - self.assertAllClose([1 / 3., 2 / 5.], pmf.eval()) + self.assertAllClose([1 / 3., 2 / 5.], self.evaluate(pmf)) self.assertAllEqual([2], pmf.get_shape()) + @test_util.run_deprecated_v1 def testPmfForOneVoteIsTheMeanWithOneRecordInput(self): # The probabilities of one vote falling into class k is the mean for class # k. @@ -194,6 +202,7 @@ class DirichletMultinomialTest(test.TestCase): self.assertAllEqual([3], mean.shape) self.assertAllEqual([], pmf.shape) + @test_util.run_deprecated_v1 def testMeanDoubleTwoVotes(self): # The probabilities of two votes falling into class k for # DirichletMultinomial(2, alpha) is twice as much as the probability of one @@ -215,6 +224,7 @@ class DirichletMultinomialTest(test.TestCase): self.assertAllClose(mean2[class_num], 2 * mean1[class_num]) self.assertAllEqual([3], mean1.shape) + @test_util.run_deprecated_v1 def testCovarianceFromSampling(self): # We will test mean, cov, var, stddev on a DirichletMultinomial constructed # via broadcast between alpha, n. @@ -289,7 +299,7 @@ class DirichletMultinomialTest(test.TestCase): expected_covariance = n * (n + alpha_0) / (1 + alpha_0) * shared_matrix self.assertEqual([2, 2], covariance.get_shape()) - self.assertAllClose(expected_covariance, covariance.eval()) + self.assertAllClose(expected_covariance, self.evaluate(covariance)) def testCovarianceNAlphaBroadcast(self): alpha_v = [1., 2, 3] @@ -327,7 +337,7 @@ class DirichletMultinomialTest(test.TestCase): ns * (ns + alpha_0) / (1 + alpha_0))[..., array_ops.newaxis] self.assertEqual([4, 3, 3], covariance.get_shape()) - self.assertAllClose(expected_covariance, covariance.eval()) + self.assertAllClose(expected_covariance, self.evaluate(covariance)) def testCovarianceMultidimensional(self): alpha = np.random.rand(3, 5, 4).astype(np.float32) @@ -353,7 +363,7 @@ class DirichletMultinomialTest(test.TestCase): with self.cached_session(): dist = ds.DirichletMultinomial(0., alpha) pmf = dist.prob(counts) - self.assertAllClose(1.0, pmf.eval()) + self.assertAllClose(1.0, self.evaluate(pmf)) self.assertEqual((), pmf.get_shape()) def testLargeTauGivesPreciseProbabilities(self): @@ -368,7 +378,7 @@ class DirichletMultinomialTest(test.TestCase): with self.cached_session(): dist = ds.DirichletMultinomial(1., alpha) pmf = dist.prob(counts) - self.assertAllClose(0.8, pmf.eval(), atol=1e-4) + self.assertAllClose(0.8, self.evaluate(pmf), atol=1e-4) self.assertEqual((), pmf.get_shape()) # Two (three sided) coin flips. Prob[coin 3] = 0.8. @@ -376,7 +386,7 @@ class DirichletMultinomialTest(test.TestCase): with self.cached_session(): dist = ds.DirichletMultinomial(2., alpha) pmf = dist.prob(counts) - self.assertAllClose(0.8**2, pmf.eval(), atol=1e-2) + self.assertAllClose(0.8**2, self.evaluate(pmf), atol=1e-2) self.assertEqual((), pmf.get_shape()) # Three (three sided) coin flips. @@ -384,7 +394,7 @@ class DirichletMultinomialTest(test.TestCase): with self.cached_session(): dist = ds.DirichletMultinomial(3., alpha) pmf = dist.prob(counts) - self.assertAllClose(3 * 0.1 * 0.8 * 0.8, pmf.eval(), atol=1e-2) + self.assertAllClose(3 * 0.1 * 0.8 * 0.8, self.evaluate(pmf), atol=1e-2) self.assertEqual((), pmf.get_shape()) def testSmallTauPrefersCorrelatedResults(self): @@ -399,7 +409,7 @@ class DirichletMultinomialTest(test.TestCase): with self.cached_session(): dist = ds.DirichletMultinomial(1., alpha) pmf = dist.prob(counts) - self.assertAllClose(0.5, pmf.eval()) + self.assertAllClose(0.5, self.evaluate(pmf)) self.assertEqual((), pmf.get_shape()) # If there are two draws, it is much more likely that they are the same. @@ -409,9 +419,10 @@ class DirichletMultinomialTest(test.TestCase): dist = ds.DirichletMultinomial(2., alpha) pmf_same = dist.prob(counts_same) pmf_different = dist.prob(counts_different) - self.assertLess(5 * pmf_different.eval(), pmf_same.eval()) + self.assertLess(5 * self.evaluate(pmf_different), self.evaluate(pmf_same)) self.assertEqual((), pmf_same.get_shape()) + @test_util.run_deprecated_v1 def testNonStrictTurnsOffAllChecks(self): # Make totally invalid input. with self.cached_session(): @@ -421,6 +432,7 @@ class DirichletMultinomialTest(test.TestCase): dist = ds.DirichletMultinomial(n, alpha, validate_args=False) dist.prob(counts).eval() # Should not raise. + @test_util.run_deprecated_v1 def testSampleUnbiasedNonScalarBatch(self): with self.cached_session() as sess: dist = ds.DirichletMultinomial( @@ -450,6 +462,7 @@ class DirichletMultinomialTest(test.TestCase): self.assertAllClose( actual_covariance_, sample_covariance_, atol=0., rtol=0.20) + @test_util.run_deprecated_v1 def testSampleUnbiasedScalarBatch(self): with self.cached_session() as sess: dist = ds.DirichletMultinomial( diff --git a/tensorflow/python/kernel_tests/distributions/identity_bijector_test.py b/tensorflow/python/kernel_tests/distributions/identity_bijector_test.py index e35a8e1cdd..62b562387d 100644 --- a/tensorflow/python/kernel_tests/distributions/identity_bijector_test.py +++ b/tensorflow/python/kernel_tests/distributions/identity_bijector_test.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import test_util from tensorflow.python.ops.distributions import bijector_test_util from tensorflow.python.ops.distributions import identity_bijector from tensorflow.python.platform import test @@ -41,6 +42,7 @@ class IdentityBijectorTest(test.TestCase): self.evaluate( bijector.forward_log_det_jacobian(x, event_ndims=3))) + @test_util.run_deprecated_v1 def testScalarCongruency(self): with self.cached_session(): bijector = identity_bijector.Identity() diff --git a/tensorflow/python/kernel_tests/distributions/kullback_leibler_test.py b/tensorflow/python/kernel_tests/distributions/kullback_leibler_test.py index e77e1117d4..1e967de570 100644 --- a/tensorflow/python/kernel_tests/distributions/kullback_leibler_test.py +++ b/tensorflow/python/kernel_tests/distributions/kullback_leibler_test.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops.distributions import kullback_leibler from tensorflow.python.ops.distributions import normal @@ -45,6 +46,7 @@ class KLTest(test.TestCase): a = MyDist(loc=0.0, scale=1.0) self.assertEqual("OK", kullback_leibler.kl_divergence(a, a, name="OK")) + @test_util.run_deprecated_v1 def testDomainErrorExceptions(self): class MyDistException(normal.Normal): @@ -63,17 +65,17 @@ class KLTest(test.TestCase): kl = kullback_leibler.kl_divergence(a, a, allow_nan_stats=False) with self.assertRaisesOpError( "KL calculation between .* and .* returned NaN values"): - kl.eval() + self.evaluate(kl) with self.assertRaisesOpError( "KL calculation between .* and .* returned NaN values"): a.kl_divergence(a).eval() a = MyDistException(loc=0.0, scale=1.0, allow_nan_stats=True) kl_ok = kullback_leibler.kl_divergence(a, a) - self.assertAllEqual([float("nan")], kl_ok.eval()) + self.assertAllEqual([float("nan")], self.evaluate(kl_ok)) self_kl_ok = a.kl_divergence(a) - self.assertAllEqual([float("nan")], self_kl_ok.eval()) + self.assertAllEqual([float("nan")], self.evaluate(self_kl_ok)) cross_ok = a.cross_entropy(a) - self.assertAllEqual([float("nan")], cross_ok.eval()) + self.assertAllEqual([float("nan")], self.evaluate(cross_ok)) def testRegistrationFailures(self): diff --git a/tensorflow/python/kernel_tests/distributions/multinomial_test.py b/tensorflow/python/kernel_tests/distributions/multinomial_test.py index 3840d7331c..b3f3416a52 100644 --- a/tensorflow/python/kernel_tests/distributions/multinomial_test.py +++ b/tensorflow/python/kernel_tests/distributions/multinomial_test.py @@ -127,7 +127,7 @@ class MultinomialTest(test.TestCase): p = [0.5, 0.5] counts = [1., 0] pmf = multinomial.Multinomial(total_count=1., probs=p).prob(counts) - self.assertAllClose(0.5, pmf.eval()) + self.assertAllClose(0.5, self.evaluate(pmf)) self.assertEqual((), pmf.get_shape()) def testPmfBothZeroBatchesNontrivialN(self): @@ -138,7 +138,7 @@ class MultinomialTest(test.TestCase): dist = multinomial.Multinomial(total_count=5., probs=p) pmf = dist.prob(counts) # 5 choose 3 = 5 choose 2 = 10. 10 * (.9)^2 * (.1)^3 = 81/10000. - self.assertAllClose(81. / 10000, pmf.eval()) + self.assertAllClose(81. / 10000, self.evaluate(pmf)) self.assertEqual((), pmf.get_shape()) def testPmfPStretchedInBroadcastWhenSameRank(self): @@ -146,7 +146,7 @@ class MultinomialTest(test.TestCase): p = [[0.1, 0.9]] counts = [[1., 0], [0, 1]] pmf = multinomial.Multinomial(total_count=1., probs=p).prob(counts) - self.assertAllClose([0.1, 0.9], pmf.eval()) + self.assertAllClose([0.1, 0.9], self.evaluate(pmf)) self.assertEqual((2), pmf.get_shape()) def testPmfPStretchedInBroadcastWhenLowerRank(self): @@ -154,7 +154,7 @@ class MultinomialTest(test.TestCase): p = [0.1, 0.9] counts = [[1., 0], [0, 1]] pmf = multinomial.Multinomial(total_count=1., probs=p).prob(counts) - self.assertAllClose([0.1, 0.9], pmf.eval()) + self.assertAllClose([0.1, 0.9], self.evaluate(pmf)) self.assertEqual((2), pmf.get_shape()) def testPmfCountsStretchedInBroadcastWhenSameRank(self): @@ -182,7 +182,7 @@ class MultinomialTest(test.TestCase): # [2] counts = [2., 1] pmf = multinomial.Multinomial(total_count=n, probs=p).prob(counts) - pmf.eval() + self.evaluate(pmf) self.assertEqual(pmf.get_shape(), (2, 2)) def testPmfShapeCountsPStretchedN(self): @@ -191,7 +191,7 @@ class MultinomialTest(test.TestCase): counts = [3., 2] n = np.full([4, 3], 5., dtype=np.float32) pmf = multinomial.Multinomial(total_count=n, probs=p).prob(counts) - pmf.eval() + self.evaluate(pmf) self.assertEqual((4, 3), pmf.get_shape()) def testMultinomialMean(self): diff --git a/tensorflow/python/kernel_tests/distributions/normal_test.py b/tensorflow/python/kernel_tests/distributions/normal_test.py index 6625a88843..f2a193e69b 100644 --- a/tensorflow/python/kernel_tests/distributions/normal_test.py +++ b/tensorflow/python/kernel_tests/distributions/normal_test.py @@ -511,6 +511,7 @@ class NormalTest(test.TestCase): self.assertAllEqual(self.evaluate(normal.event_shape_tensor()), []) self.assertEqual(normal.event_shape, tensor_shape.TensorShape([])) + @test_util.run_deprecated_v1 def testNormalShapeWithPlaceholders(self): mu = array_ops.placeholder(dtype=dtypes.float32) sigma = array_ops.placeholder(dtype=dtypes.float32) diff --git a/tensorflow/python/kernel_tests/distributions/special_math_test.py b/tensorflow/python/kernel_tests/distributions/special_math_test.py index cc43e12168..d97fcfa655 100644 --- a/tensorflow/python/kernel_tests/distributions/special_math_test.py +++ b/tensorflow/python/kernel_tests/distributions/special_math_test.py @@ -104,6 +104,7 @@ class NdtriTest(test.TestCase): x = special_math.ndtri(p) self.assertAllClose(expected_x, self.evaluate(x), atol=0.) + @test_util.run_deprecated_v1 def testNdtriDynamicShape(self): """Verifies that ndtri computation is correct.""" with self.cached_session() as sess: @@ -213,9 +214,11 @@ class NdtrTest(test.TestCase): rtol=error_spec.rtol, atol=error_spec.atol) + @test_util.run_deprecated_v1 def test_float32(self): self._test_grid(np.float32, self._grid32, self._error32) + @test_util.run_deprecated_v1 def test_float64(self): self._test_grid(np.float64, self._grid64, self._error64) @@ -338,10 +341,12 @@ class NdtrGradientTest(test.TestCase): rtol=error_spec.rtol, atol=error_spec.atol) + @test_util.run_deprecated_v1 def test_float32(self): self._test_grad_accuracy(np.float32, self._grid, self._error32) self._test_grad_finite(np.float32) + @test_util.run_deprecated_v1 def test_float64(self): self._test_grad_accuracy(np.float64, self._grid, self._error64) self._test_grad_finite(np.float64) @@ -362,7 +367,7 @@ class ErfInvTest(test.TestCase): expected_x = special.erfinv(x) x = special_math.erfinv(x) - self.assertAllClose(expected_x, x.eval(), atol=0.) + self.assertAllClose(expected_x, self.evaluate(x), atol=0.) def testErfInvIntegerInput(self): with self.cached_session(): @@ -418,6 +423,7 @@ class LogCDFLaplaceTest(test.TestCase): rtol=error_spec.rtol, atol=error_spec.atol) + @test_util.run_deprecated_v1 def test_float32_lower_and_mid_segment_scipy_float32_ok(self): # Choose values mild enough that we can use scipy in float32, which will # allow for a high accuracy match to scipy (since we both use float32). @@ -427,6 +433,7 @@ class LogCDFLaplaceTest(test.TestCase): GridSpec(min=-10, max=self.CUTOFF_FLOAT32_UPPER - 5, shape=[100]), ErrorSpec(rtol=5e-4, atol=0)) + @test_util.run_deprecated_v1 def test_float32_all_segments_with_scipy_float64_ok(self): # Choose values outside the range where scipy float32 works. # Let scipy use float64. This means we @@ -437,6 +444,7 @@ class LogCDFLaplaceTest(test.TestCase): GridSpec(min=-50, max=self.CUTOFF_FLOAT32_UPPER + 5, shape=[100]), ErrorSpec(rtol=0.05, atol=0)) + @test_util.run_deprecated_v1 def test_float32_extreme_values_result_and_gradient_finite_and_nonzero(self): with self.cached_session() as sess: # On the lower branch, log_cdf_laplace(x) = x, so we know this will be @@ -448,7 +456,7 @@ class LogCDFLaplaceTest(test.TestCase): actual = sm.log_cdf_laplace(grid) grad = gradients_impl.gradients(actual, grid)[0] - actual_, grad_ = sess.run([actual, grad]) + actual_, grad_ = self.evaluate([actual, grad]) # isfinite checks for NaN and Inf. self.assertAllTrue(np.isfinite(actual_)) @@ -456,6 +464,7 @@ class LogCDFLaplaceTest(test.TestCase): self.assertFalse(np.any(actual_ == 0)) self.assertFalse(np.any(grad_ == 0)) + @test_util.run_deprecated_v1 def test_float64_extreme_values_result_and_gradient_finite_and_nonzero(self): with self.cached_session() as sess: # On the lower branch, log_cdf_laplace(x) = x, so we know this will be @@ -467,7 +476,7 @@ class LogCDFLaplaceTest(test.TestCase): actual = sm.log_cdf_laplace(grid) grad = gradients_impl.gradients(actual, grid)[0] - actual_, grad_ = sess.run([actual, grad]) + actual_, grad_ = self.evaluate([actual, grad]) # isfinite checks for NaN and Inf. self.assertAllTrue(np.isfinite(actual_)) diff --git a/tensorflow/python/kernel_tests/distributions/util_test.py b/tensorflow/python/kernel_tests/distributions/util_test.py index f4e651b25b..030ad601bf 100644 --- a/tensorflow/python/kernel_tests/distributions/util_test.py +++ b/tensorflow/python/kernel_tests/distributions/util_test.py @@ -59,6 +59,7 @@ def _logit(x): class AssertCloseTest(test.TestCase): + @test_util.run_deprecated_v1 def testAssertIntegerForm(self): # This should only be detected as an integer. x = array_ops.placeholder(dtypes.float32) @@ -112,6 +113,7 @@ class MaybeGetStaticTest(test.TestCase): self.assertAllClose( np.array(2.), du.maybe_get_static_value(x, dtype=np.float64)) + @test_util.run_deprecated_v1 def testGetStaticPlaceholder(self): x = array_ops.placeholder(dtype=dtypes.int32, shape=[1]) self.assertEqual(None, du.maybe_get_static_value(x)) @@ -235,6 +237,7 @@ class GetLogitsAndProbsTest(test.TestCase): probs=p4, multidimensional=True, validate_args=False) self.evaluate(prob) + @test_util.run_deprecated_v1 def testProbsMultidimShape(self): with self.cached_session(): with self.assertRaises(ValueError): @@ -249,6 +252,7 @@ class GetLogitsAndProbsTest(test.TestCase): probs=p, multidimensional=True, validate_args=True) prob.eval(feed_dict={p: np.ones([int(2**11+1)])}) + @test_util.run_deprecated_v1 def testLogitsMultidimShape(self): with self.cached_session(): with self.assertRaises(ValueError): @@ -266,6 +270,7 @@ class GetLogitsAndProbsTest(test.TestCase): class EmbedCheckCategoricalEventShapeTest(test.TestCase): + @test_util.run_deprecated_v1 def testTooSmall(self): with self.cached_session(): with self.assertRaises(ValueError): @@ -280,6 +285,7 @@ class EmbedCheckCategoricalEventShapeTest(test.TestCase): param) checked_param.eval(feed_dict={param: np.ones([1])}) + @test_util.run_deprecated_v1 def testTooLarge(self): with self.cached_session(): with self.assertRaises(ValueError): @@ -305,6 +311,7 @@ class EmbedCheckCategoricalEventShapeTest(test.TestCase): class EmbedCheckIntegerCastingClosedTest(test.TestCase): + @test_util.run_deprecated_v1 def testCorrectlyAssertsNonnegative(self): with self.cached_session(): with self.assertRaisesOpError("Elements must be non-negative"): @@ -313,6 +320,7 @@ class EmbedCheckIntegerCastingClosedTest(test.TestCase): x, target_dtype=dtypes.int16) x_checked.eval(feed_dict={x: np.array([1, -1], dtype=np.float16)}) + @test_util.run_deprecated_v1 def testCorrectlyAssersIntegerForm(self): with self.cached_session(): with self.assertRaisesOpError("Elements must be int16-equivalent."): @@ -321,6 +329,7 @@ class EmbedCheckIntegerCastingClosedTest(test.TestCase): x, target_dtype=dtypes.int16) x_checked.eval(feed_dict={x: np.array([1, 1.5], dtype=np.float16)}) + @test_util.run_deprecated_v1 def testCorrectlyAssertsLargestPossibleInteger(self): with self.cached_session(): with self.assertRaisesOpError("Elements cannot exceed 32767."): @@ -329,6 +338,7 @@ class EmbedCheckIntegerCastingClosedTest(test.TestCase): x, target_dtype=dtypes.int16) x_checked.eval(feed_dict={x: np.array([1, 2**15], dtype=np.int32)}) + @test_util.run_deprecated_v1 def testCorrectlyAssertsSmallestPossibleInteger(self): with self.cached_session(): with self.assertRaisesOpError("Elements cannot be smaller than 0."): @@ -369,6 +379,7 @@ class LogCombinationsTest(test.TestCase): class DynamicShapeTest(test.TestCase): + @test_util.run_deprecated_v1 def testSameDynamicShape(self): with self.cached_session(): scalar = constant_op.constant(2.0) @@ -493,6 +504,7 @@ class RotateTransposeTest(test.TestCase): self._np_rotate_transpose(x, shift), self.evaluate(y)) self.assertAllEqual(np.roll(x.shape, shift), y.get_shape().as_list()) + @test_util.run_deprecated_v1 def testRollDynamic(self): with self.cached_session() as sess: x = array_ops.placeholder(dtypes.float32) @@ -511,6 +523,7 @@ class RotateTransposeTest(test.TestCase): class PickVectorTest(test.TestCase): + @test_util.run_deprecated_v1 def testCorrectlyPicksVector(self): with self.cached_session(): x = np.arange(10, 12) @@ -529,36 +542,42 @@ class PickVectorTest(test.TestCase): class PreferStaticRankTest(test.TestCase): + @test_util.run_deprecated_v1 def testNonEmptyConstantTensor(self): x = array_ops.zeros((2, 3, 4)) rank = du.prefer_static_rank(x) self.assertIsInstance(rank, np.ndarray) self.assertEqual(3, rank) + @test_util.run_deprecated_v1 def testEmptyConstantTensor(self): x = constant_op.constant([]) rank = du.prefer_static_rank(x) self.assertIsInstance(rank, np.ndarray) self.assertEqual(1, rank) + @test_util.run_deprecated_v1 def testScalarTensor(self): x = constant_op.constant(1.) rank = du.prefer_static_rank(x) self.assertIsInstance(rank, np.ndarray) self.assertEqual(0, rank) + @test_util.run_deprecated_v1 def testDynamicRankEndsUpBeingNonEmpty(self): x = array_ops.placeholder(np.float64, shape=None) rank = du.prefer_static_rank(x) with self.cached_session(): self.assertAllEqual(2, rank.eval(feed_dict={x: np.zeros((2, 3))})) + @test_util.run_deprecated_v1 def testDynamicRankEndsUpBeingEmpty(self): x = array_ops.placeholder(np.int32, shape=None) rank = du.prefer_static_rank(x) with self.cached_session(): self.assertAllEqual(1, rank.eval(feed_dict={x: []})) + @test_util.run_deprecated_v1 def testDynamicRankEndsUpBeingScalar(self): x = array_ops.placeholder(np.int32, shape=None) rank = du.prefer_static_rank(x) @@ -568,36 +587,42 @@ class PreferStaticRankTest(test.TestCase): class PreferStaticShapeTest(test.TestCase): + @test_util.run_deprecated_v1 def testNonEmptyConstantTensor(self): x = array_ops.zeros((2, 3, 4)) shape = du.prefer_static_shape(x) self.assertIsInstance(shape, np.ndarray) self.assertAllEqual(np.array([2, 3, 4]), shape) + @test_util.run_deprecated_v1 def testEmptyConstantTensor(self): x = constant_op.constant([]) shape = du.prefer_static_shape(x) self.assertIsInstance(shape, np.ndarray) self.assertAllEqual(np.array([0]), shape) + @test_util.run_deprecated_v1 def testScalarTensor(self): x = constant_op.constant(1.) shape = du.prefer_static_shape(x) self.assertIsInstance(shape, np.ndarray) self.assertAllEqual(np.array([]), shape) + @test_util.run_deprecated_v1 def testDynamicShapeEndsUpBeingNonEmpty(self): x = array_ops.placeholder(np.float64, shape=None) shape = du.prefer_static_shape(x) with self.cached_session(): self.assertAllEqual((2, 3), shape.eval(feed_dict={x: np.zeros((2, 3))})) + @test_util.run_deprecated_v1 def testDynamicShapeEndsUpBeingEmpty(self): x = array_ops.placeholder(np.int32, shape=None) shape = du.prefer_static_shape(x) with self.cached_session(): self.assertAllEqual(np.array([0]), shape.eval(feed_dict={x: []})) + @test_util.run_deprecated_v1 def testDynamicShapeEndsUpBeingScalar(self): x = array_ops.placeholder(np.int32, shape=None) shape = du.prefer_static_shape(x) @@ -607,24 +632,28 @@ class PreferStaticShapeTest(test.TestCase): class PreferStaticValueTest(test.TestCase): + @test_util.run_deprecated_v1 def testNonEmptyConstantTensor(self): x = array_ops.zeros((2, 3, 4)) value = du.prefer_static_value(x) self.assertIsInstance(value, np.ndarray) self.assertAllEqual(np.zeros((2, 3, 4)), value) + @test_util.run_deprecated_v1 def testEmptyConstantTensor(self): x = constant_op.constant([]) value = du.prefer_static_value(x) self.assertIsInstance(value, np.ndarray) self.assertAllEqual(np.array([]), value) + @test_util.run_deprecated_v1 def testScalarTensor(self): x = constant_op.constant(1.) value = du.prefer_static_value(x) self.assertIsInstance(value, np.ndarray) self.assertAllEqual(np.array(1.), value) + @test_util.run_deprecated_v1 def testDynamicValueEndsUpBeingNonEmpty(self): x = array_ops.placeholder(np.float64, shape=None) value = du.prefer_static_value(x) @@ -632,12 +661,14 @@ class PreferStaticValueTest(test.TestCase): self.assertAllEqual(np.zeros((2, 3)), value.eval(feed_dict={x: np.zeros((2, 3))})) + @test_util.run_deprecated_v1 def testDynamicValueEndsUpBeingEmpty(self): x = array_ops.placeholder(np.int32, shape=None) value = du.prefer_static_value(x) with self.cached_session(): self.assertAllEqual(np.array([]), value.eval(feed_dict={x: []})) + @test_util.run_deprecated_v1 def testDynamicValueEndsUpBeingScalar(self): x = array_ops.placeholder(np.int32, shape=None) value = du.prefer_static_value(x) @@ -698,43 +729,55 @@ class FillTriangularTest(test.TestCase): self.assertAllClose(expected, actual_, rtol=1e-8, atol=1e-9) self.assertAllClose(x_, grad_actual_, rtol=1e-8, atol=1e-9) + @test_util.run_deprecated_v1 def testCorrectlyMakes1x1TriLower(self): self._run_test(self._rng.randn(3, int(1*2/2))) + @test_util.run_deprecated_v1 def testCorrectlyMakesNoBatchTriLower(self): self._run_test(self._rng.randn(int(4*5/2))) + @test_util.run_deprecated_v1 def testCorrectlyMakesBatchTriLower(self): self._run_test(self._rng.randn(2, 3, int(3*4/2))) + @test_util.run_deprecated_v1 def testCorrectlyMakesBatchTriLowerUnknownShape(self): self._run_test(self._rng.randn(2, 3, int(3*4/2)), use_deferred_shape=True) + @test_util.run_deprecated_v1 def testCorrectlyMakesBatch7x7TriLowerUnknownShape(self): self._run_test(self._rng.randn(2, 3, int(7*8/2)), use_deferred_shape=True) + @test_util.run_deprecated_v1 def testCorrectlyMakesBatch7x7TriLower(self): self._run_test(self._rng.randn(2, 3, int(7*8/2))) + @test_util.run_deprecated_v1 def testCorrectlyMakes1x1TriUpper(self): self._run_test(self._rng.randn(3, int(1*2/2)), upper=True) + @test_util.run_deprecated_v1 def testCorrectlyMakesNoBatchTriUpper(self): self._run_test(self._rng.randn(int(4*5/2)), upper=True) + @test_util.run_deprecated_v1 def testCorrectlyMakesBatchTriUpper(self): self._run_test(self._rng.randn(2, 2, int(3*4/2)), upper=True) + @test_util.run_deprecated_v1 def testCorrectlyMakesBatchTriUpperUnknownShape(self): self._run_test(self._rng.randn(2, 2, int(3*4/2)), use_deferred_shape=True, upper=True) + @test_util.run_deprecated_v1 def testCorrectlyMakesBatch7x7TriUpperUnknownShape(self): self._run_test(self._rng.randn(2, 3, int(7*8/2)), use_deferred_shape=True, upper=True) + @test_util.run_deprecated_v1 def testCorrectlyMakesBatch7x7TriUpper(self): self._run_test(self._rng.randn(2, 3, int(7*8/2)), upper=True) @@ -773,6 +816,7 @@ class ReduceWeightedLogSumExp(test.TestCase): m = np.squeeze(m, axis=axis) return m + np.log(sgn * sum_), sgn + @test_util.run_deprecated_v1 def testNoWeights(self): logx_ = np.array([[0., -1, 1000.], [0, 1, -1000.], @@ -805,7 +849,7 @@ class ReduceWeightedLogSumExp(test.TestCase): w = constant_op.constant(w_) actual, actual_sgn = du.reduce_weighted_logsumexp( logx, w, axis=-1, return_sign=True) - [actual_, actual_sgn_] = sess.run([actual, actual_sgn]) + [actual_, actual_sgn_] = self.evaluate([actual, actual_sgn]) self.assertAllEqual(expected, actual_) self.assertAllEqual([-1., -1, 1], actual_sgn_) @@ -823,7 +867,7 @@ class ReduceWeightedLogSumExp(test.TestCase): w = constant_op.constant(w_) actual, actual_sgn = du.reduce_weighted_logsumexp( logx, w, axis=-1, return_sign=True, keep_dims=True) - [actual_, actual_sgn_] = sess.run([actual, actual_sgn]) + [actual_, actual_sgn_] = self.evaluate([actual, actual_sgn]) self.assertAllEqual(expected, actual_) self.assertAllEqual([[-1.], [-1], [1]], actual_sgn_) @@ -903,6 +947,7 @@ class SoftplusTest(test.TestCase): self.assertAllEqual(np.ones_like(tf_softplus_inverse).astype(np.bool), np.isfinite(tf_softplus_inverse)) + @test_util.run_deprecated_v1 def testNumbers(self): for t in [np.float16, np.float32, np.float64]: lower = {np.float16: -15, np.float32: -50, np.float64: -50}.get(t, -100) @@ -933,6 +978,7 @@ class SoftplusTest(test.TestCase): ], use_gpu=True) + @test_util.run_deprecated_v1 def testGradient(self): with self.cached_session(): x = constant_op.constant( @@ -949,6 +995,7 @@ class SoftplusTest(test.TestCase): tf_logging.vlog(2, "softplus (float) gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testInverseSoftplusGradientNeverNan(self): with self.cached_session(): # Note that this range contains both zero and inf. @@ -958,6 +1005,7 @@ class SoftplusTest(test.TestCase): # Equivalent to `assertAllFalse` (if it existed). self.assertAllEqual(np.zeros_like(grads).astype(np.bool), np.isnan(grads)) + @test_util.run_deprecated_v1 def testInverseSoftplusGradientFinite(self): with self.cached_session(): # This range of x is all finite, and so is 1 / x. So the diff --git a/tensorflow/python/kernel_tests/division_future_test.py b/tensorflow/python/kernel_tests/division_future_test.py index e477bdc73b..85c85809d3 100644 --- a/tensorflow/python/kernel_tests/division_future_test.py +++ b/tensorflow/python/kernel_tests/division_future_test.py @@ -65,7 +65,7 @@ class DivisionTestCase(test.TestCase): tf_floordiv = tf_x // tf_y check(floordiv, tf_floordiv) # Do only one sess.run for speed - for f, (x, y) in zip(checks, sess.run(tensors)): + for f, (x, y) in zip(checks, self.evaluate(tensors)): f(x, y) diff --git a/tensorflow/python/kernel_tests/division_past_test.py b/tensorflow/python/kernel_tests/division_past_test.py index 63951b5b38..38bb18631a 100644 --- a/tensorflow/python/kernel_tests/division_past_test.py +++ b/tensorflow/python/kernel_tests/division_past_test.py @@ -64,7 +64,7 @@ class DivisionTestCase(test.TestCase): tf_floordiv = tf_x // tf_y check(floordiv, tf_floordiv) # Do only one sess.run for speed - for f, (x, y) in zip(checks, sess.run(tensors)): + for f, (x, y) in zip(checks, self.evaluate(tensors)): f(x, y) diff --git a/tensorflow/python/kernel_tests/draw_bounding_box_op_test.py b/tensorflow/python/kernel_tests/draw_bounding_box_op_test.py index c655876280..6aa757e293 100644 --- a/tensorflow/python/kernel_tests/draw_bounding_box_op_test.py +++ b/tensorflow/python/kernel_tests/draw_bounding_box_op_test.py @@ -87,7 +87,7 @@ class DrawBoundingBoxOpTest(test.TestCase): image = array_ops.expand_dims(image, 0) image = image_ops.draw_bounding_boxes(image, bboxes) with self.cached_session(use_gpu=False) as sess: - op_drawn_image = np.squeeze(sess.run(image), 0) + op_drawn_image = np.squeeze(self.evaluate(image), 0) self.assertAllEqual(test_drawn_image, op_drawn_image) def testDrawBoundingBoxRGBColorCycling(self): diff --git a/tensorflow/python/kernel_tests/duplicate_op_test.py b/tensorflow/python/kernel_tests/duplicate_op_test.py index 654267a582..fef3127d4a 100644 --- a/tensorflow/python/kernel_tests/duplicate_op_test.py +++ b/tensorflow/python/kernel_tests/duplicate_op_test.py @@ -20,6 +20,7 @@ from __future__ import print_function import os from tensorflow.python.framework import load_library +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.platform import resource_loader from tensorflow.python.platform import test @@ -27,6 +28,7 @@ from tensorflow.python.platform import test class DuplicateOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): library_filename = os.path.join(resource_loader.get_data_files_path(), 'duplicate_op.so') diff --git a/tensorflow/python/kernel_tests/dynamic_partition_op_test.py b/tensorflow/python/kernel_tests/dynamic_partition_op_test.py index 07da855a01..8c44819407 100644 --- a/tensorflow/python/kernel_tests/dynamic_partition_op_test.py +++ b/tensorflow/python/kernel_tests/dynamic_partition_op_test.py @@ -25,6 +25,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import gradients_impl @@ -34,13 +35,14 @@ from tensorflow.python.platform import test class DynamicPartitionTest(test.TestCase): + @test_util.run_deprecated_v1 def testSimpleOneDimensional(self): with self.session(use_gpu=True) as sess: data = constant_op.constant([0, 13, 2, 39, 4, 17], dtype=dtypes.float32) indices = constant_op.constant([0, 0, 2, 3, 2, 1]) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=4) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(4, len(partition_vals)) self.assertAllEqual([0, 13], partition_vals[0]) @@ -54,6 +56,7 @@ class DynamicPartitionTest(test.TestCase): self.assertEqual([None], partitions[2].get_shape().as_list()) self.assertEqual([None], partitions[3].get_shape().as_list()) + @test_util.run_deprecated_v1 def testSimpleTwoDimensional(self): with self.session(use_gpu=True) as sess: data = constant_op.constant([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], @@ -62,7 +65,7 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant([0, 0, 2, 3, 2, 1]) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=4) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(4, len(partition_vals)) self.assertAllEqual([[0, 1, 2], [3, 4, 5]], partition_vals[0]) @@ -87,7 +90,7 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant(indices_list, dtype=dtypes.int32) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=2) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(2, len(partition_vals)) self.assertAllEqual(part1, partition_vals[0]) @@ -109,7 +112,7 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant(indices_list, dtype=dtypes.int32) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=num_partitions) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(num_partitions, len(partition_vals)) for i in range(num_partitions): @@ -125,7 +128,7 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant(indices_list, dtype=dtypes.int32) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=2) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(2, len(partition_vals)) self.assertAllEqual([3 + 4j, 7 + 8j], partition_vals[0]) @@ -138,7 +141,7 @@ class DynamicPartitionTest(test.TestCase): indices = 3 partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=4) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(4, len(partition_vals)) self.assertAllEqual(np.array([], dtype=np.float64).reshape(-1, 4), @@ -151,6 +154,7 @@ class DynamicPartitionTest(test.TestCase): dtype=np.float64).reshape(-1, 4), partition_vals[3]) + @test_util.run_deprecated_v1 def testHigherRank(self): np.random.seed(7) with self.session(use_gpu=True) as sess: @@ -164,7 +168,7 @@ class DynamicPartitionTest(test.TestCase): outputs = data_flow_ops.dynamic_partition( data_t, partitions_t, num_partitions=n) self.assertEqual(n, len(outputs)) - outputs_val = sess.run(outputs) + outputs_val = self.evaluate(outputs) for i, output in enumerate(outputs_val): self.assertAllEqual(output, data[partitions == i]) @@ -183,7 +187,7 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant(indices_list, dtype=dtypes.int32) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=4) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(4, len(partition_vals)) self.assertAllEqual([], partition_vals[0]) @@ -199,7 +203,7 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant(indices_list, dtype=dtypes.int32) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=3) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(3, len(partition_vals)) self.assertAllEqual([[]], partition_vals[0]) @@ -215,7 +219,7 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant(indices_list, dtype=dtypes.int32) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=2) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(2, len(partition_vals)) self.assertAllEqual([], partition_vals[0]) @@ -236,7 +240,7 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant(indices_list, dtype=dtypes.int32) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=2) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(2, len(partition_vals)) self.assertAllEqual([6], partition_vals[0]) @@ -257,7 +261,7 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant(indices_list, dtype=dtypes.int32) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=5) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(5, len(partition_vals)) self.assertAllEqual([5], partition_vals[0]) @@ -281,12 +285,13 @@ class DynamicPartitionTest(test.TestCase): indices = constant_op.constant(indices_list, dtype=dtypes.int32) partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=40) - partition_vals = sess.run(partitions) + partition_vals = self.evaluate(partitions) self.assertEqual(40, len(partition_vals)) for i in range(40): self.assertAllEqual([], partition_vals[i]) + @test_util.run_deprecated_v1 def testErrorIndexOutOfRange(self): with self.cached_session() as sess: data = constant_op.constant([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], @@ -295,16 +300,18 @@ class DynamicPartitionTest(test.TestCase): partitions = data_flow_ops.dynamic_partition( data, indices, num_partitions=4) with self.assertRaisesOpError(r"partitions\[2\] = 99 is not in \[0, 4\)"): - sess.run(partitions) + self.evaluate(partitions) + @test_util.run_deprecated_v1 def testScalarIndexOutOfRange(self): with self.cached_session() as sess: bad = 17 data = np.zeros(5) partitions = data_flow_ops.dynamic_partition(data, bad, num_partitions=7) with self.assertRaisesOpError(r"partitions = 17 is not in \[0, 7\)"): - sess.run(partitions) + self.evaluate(partitions) + @test_util.run_deprecated_v1 def testHigherRankIndexOutOfRange(self): with self.cached_session() as sess: shape = (2, 3) @@ -320,6 +327,7 @@ class DynamicPartitionTest(test.TestCase): r"partitions\[%d,%d\] = 17 is not in \[0, 7\)" % (i, j)): sess.run(partitions, feed_dict={indices: bad}) + @test_util.run_deprecated_v1 def testErrorWrongDimsIndices(self): data = constant_op.constant([[0], [1], [2]]) indices = constant_op.constant([[0], [0]]) @@ -335,7 +343,7 @@ class DynamicPartitionTest(test.TestCase): self.assertEqual(len(inds), x.shape[0]) partitioned = data_flow_ops.dynamic_partition(x, inds, 16) with self.cached_session() as sess: - res = sess.run(partitioned) + res = self.evaluate(partitioned) self.assertEqual(res[-1].shape[0], 192) diff --git a/tensorflow/python/kernel_tests/dynamic_stitch_op_test.py b/tensorflow/python/kernel_tests/dynamic_stitch_op_test.py index c3f67d29aa..4f338880aa 100644 --- a/tensorflow/python/kernel_tests/dynamic_stitch_op_test.py +++ b/tensorflow/python/kernel_tests/dynamic_stitch_op_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import math_ops @@ -36,18 +37,19 @@ class DynamicStitchTestBase(object): self.stitch_op = stitch_op def testScalar(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): indices = [constant_op.constant(0), constant_op.constant(1)] data = [constant_op.constant(40), constant_op.constant(60)] for step in -1, 1: stitched_t = self.stitch_op(indices[::step], data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) self.assertAllEqual([40, 60][::step], stitched_val) # Dimension 0 is max(flatten(indices))+1. self.assertEqual([2], stitched_t.get_shape().as_list()) + @test_util.run_deprecated_v1 def testShapeInferenceForScalarWithNonConstantIndices(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): indices = [ array_ops.placeholder(dtype=dtypes.int32), constant_op.constant(1) @@ -61,7 +63,7 @@ class DynamicStitchTestBase(object): self.assertEqual([None], stitched_t.get_shape().as_list()) def testSimpleOneDimensional(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): # Test various datatypes in the simple case to ensure that the op was # registered under those types. dtypes_to_test = [ @@ -78,23 +80,23 @@ class DynamicStitchTestBase(object): constant_op.constant([10, 60, 20, 30, 50]), dtype=dtype) ] stitched_t = self.stitch_op(indices, data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) self.assertAllEqual([0, 10, 20, 30, 40, 50, 60, 70], stitched_val) # Dimension 0 is max(flatten(indices))+1. self.assertEqual([8], stitched_t.get_shape().as_list()) def testOneListOneDimensional(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): indices = [constant_op.constant([1, 6, 2, 3, 5, 0, 4, 7])] data = [constant_op.constant([10, 60, 20, 30, 50, 0, 40, 70])] stitched_t = self.stitch_op(indices, data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) self.assertAllEqual([0, 10, 20, 30, 40, 50, 60, 70], stitched_val) # Dimension 0 is max(flatten(indices))+1. self.assertEqual([8], stitched_t.get_shape().as_list()) def testSimpleTwoDimensional(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): indices = [ constant_op.constant([0, 4, 7]), constant_op.constant([1, 6]), @@ -106,14 +108,14 @@ class DynamicStitchTestBase(object): constant_op.constant([[20, 21], [30, 31], [50, 51]]) ] stitched_t = self.stitch_op(indices, data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) self.assertAllEqual([[0, 1], [10, 11], [20, 21], [30, 31], [40, 41], [50, 51], [60, 61], [70, 71]], stitched_val) # Dimension 0 is max(flatten(indices))+1. self.assertEqual([8, 2], stitched_t.get_shape().as_list()) def testZeroSizeTensor(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): indices = [ constant_op.constant([0, 4, 7]), constant_op.constant([1, 6]), @@ -127,12 +129,13 @@ class DynamicStitchTestBase(object): array_ops.zeros([0, 2], dtype=dtypes.int32) ] stitched_t = self.stitch_op(indices, data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) self.assertAllEqual([[0, 1], [10, 11], [20, 21], [30, 31], [40, 41], [50, 51], [60, 61], [70, 71]], stitched_val) # Dimension 0 is max(flatten(indices))+1. self.assertEqual([8, 2], stitched_t.get_shape().as_list()) + @test_util.run_deprecated_v1 def testHigherRank(self): with self.session(use_gpu=True) as sess: indices = [ @@ -147,7 +150,7 @@ class DynamicStitchTestBase(object): [[1., 2.], [31., 32.]]]) ] stitched_t = self.stitch_op(indices, data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) correct = 10. * np.arange(7)[:, None] + [1., 2.] self.assertAllEqual(correct, stitched_val) self.assertEqual([7, 2], stitched_t.get_shape().as_list()) @@ -157,8 +160,9 @@ class DynamicStitchTestBase(object): stitched_grad) self.assertEqual(grads[:3], [None] * 3) # Indices have no gradients for datum, grad in zip(data, sess.run(grads[3:])): - self.assertAllEqual(7. * datum.eval(), grad) + self.assertAllEqual(7. * self.evaluate(datum), grad) + @test_util.run_deprecated_v1 def testErrorIndicesMultiDimensional(self): indices = [ constant_op.constant([0, 4, 7]), @@ -171,6 +175,7 @@ class DynamicStitchTestBase(object): with self.assertRaises(ValueError): self.stitch_op(indices, data) + @test_util.run_deprecated_v1 def testErrorDataNumDimsMismatch(self): indices = [ constant_op.constant([0, 4, 7]), @@ -183,6 +188,7 @@ class DynamicStitchTestBase(object): with self.assertRaises(ValueError): self.stitch_op(indices, data) + @test_util.run_deprecated_v1 def testErrorDataDimSizeMismatch(self): indices = [ constant_op.constant([0, 4, 5]), @@ -195,6 +201,7 @@ class DynamicStitchTestBase(object): with self.assertRaises(ValueError): self.stitch_op(indices, data) + @test_util.run_deprecated_v1 def testErrorDataAndIndicesSizeMismatch(self): indices = [ constant_op.constant([0, 4, 7]), @@ -222,16 +229,17 @@ class ParallelDynamicStitchTest(DynamicStitchTestBase, test.TestCase): DynamicStitchTestBase.__init__(self, data_flow_ops.parallel_dynamic_stitch) def testScalar(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): indices = [constant_op.constant(0), constant_op.constant(1)] data = [constant_op.constant(40.0), constant_op.constant(60.0)] for step in -1, 1: stitched_t = data_flow_ops.dynamic_stitch(indices[::step], data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) self.assertAllEqual([40.0, 60.0][::step], stitched_val) # Dimension 0 is max(flatten(indices))+1. self.assertEqual([2], stitched_t.get_shape().as_list()) + @test_util.run_deprecated_v1 def testHigherRank(self): with self.session(use_gpu=True) as sess: indices = [ @@ -246,7 +254,7 @@ class ParallelDynamicStitchTest(DynamicStitchTestBase, test.TestCase): [[[51, 52], [21, 22]], [[1, 2], [31, 32]]], dtype=dtypes.float32) ] stitched_t = data_flow_ops.dynamic_stitch(indices, data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) correct = 10 * np.arange(7)[:, None] + [1.0, 2.0] self.assertAllEqual(correct, stitched_val) self.assertEqual([7, 2], stitched_t.get_shape().as_list()) @@ -256,7 +264,7 @@ class ParallelDynamicStitchTest(DynamicStitchTestBase, test.TestCase): stitched_grad) self.assertEqual(grads[:3], [None] * 3) # Indices have no gradients for datum, grad in zip(data, sess.run(grads[3:])): - self.assertAllEqual(7.0 * datum.eval(), grad) + self.assertAllEqual(7.0 * self.evaluate(datum), grad) # GPU version unit tests def testScalarGPU(self): @@ -265,11 +273,12 @@ class ParallelDynamicStitchTest(DynamicStitchTestBase, test.TestCase): data = [constant_op.constant(40.0), constant_op.constant(60.0)] for step in -1, 1: stitched_t = data_flow_ops.dynamic_stitch(indices[::step], data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) self.assertAllEqual([40.0, 60.0][::step], stitched_val) # Dimension 0 is max(flatten(indices))+1. self.assertEqual([2], stitched_t.get_shape().as_list()) + @test_util.run_deprecated_v1 def testHigherRankGPU(self): with self.cached_session() as sess: indices = [ @@ -284,7 +293,7 @@ class ParallelDynamicStitchTest(DynamicStitchTestBase, test.TestCase): [[[51, 52], [21, 22]], [[1, 2], [31, 32]]], dtype=dtypes.float32) ] stitched_t = data_flow_ops.dynamic_stitch(indices, data) - stitched_val = stitched_t.eval() + stitched_val = self.evaluate(stitched_t) correct = 10 * np.arange(7)[:, None] + [1.0, 2.0] self.assertAllEqual(correct, stitched_val) self.assertEqual([7, 2], stitched_t.get_shape().as_list()) @@ -294,7 +303,7 @@ class ParallelDynamicStitchTest(DynamicStitchTestBase, test.TestCase): stitched_grad) self.assertEqual(grads[:3], [None] * 3) # Indices have no gradients for datum, grad in zip(data, sess.run(grads[3:])): - self.assertAllEqual(7.0 * datum.eval(), grad) + self.assertAllEqual(7.0 * self.evaluate(datum), grad) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/edit_distance_op_test.py b/tensorflow/python/kernel_tests/edit_distance_op_test.py index dab5eee7f5..4a06ab770a 100644 --- a/tensorflow/python/kernel_tests/edit_distance_op_test.py +++ b/tensorflow/python/kernel_tests/edit_distance_op_test.py @@ -49,11 +49,11 @@ class EditDistanceTest(test.TestCase): if expected_err_re is None: self.assertEqual(edit_distance.get_shape(), expected_shape) - output = edit_distance.eval() + output = self.evaluate(edit_distance) self.assertAllClose(output, expected_output) else: with self.assertRaisesOpError(expected_err_re): - edit_distance.eval() + self.evaluate(edit_distance) def _testEditDistance(self, hypothesis, diff --git a/tensorflow/python/kernel_tests/embedding_ops_test.py b/tensorflow/python/kernel_tests/embedding_ops_test.py index 008d6fbf57..6019245d0f 100644 --- a/tensorflow/python/kernel_tests/embedding_ops_test.py +++ b/tensorflow/python/kernel_tests/embedding_ops_test.py @@ -28,6 +28,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import embedding_ops @@ -76,7 +77,7 @@ class ScatterAddSubTest(test.TestCase): # p = init variables.global_variables_initializer().run() # p += vals - result = p2.eval() + result = self.evaluate(p2) # Compute the expected 'p' using numpy operations. for i, ind in enumerate(indices): if scatter_op == state_ops.scatter_add: @@ -87,16 +88,19 @@ class ScatterAddSubTest(test.TestCase): vals_shape[0], -1)[i, :]) self.assertTrue(all((p_init == result).ravel())) + @test_util.run_deprecated_v1 def testNoRepetitions(self): self._TestCase([2, 2], [1]) self._TestCase([4, 4, 4], [2, 0]) self._TestCase([43, 20, 10, 10], [42, 5, 6, 1, 3, 5, 7, 9]) + @test_util.run_deprecated_v1 def testWithRepetitions(self): self._TestCase([2, 2], [1, 1]) self._TestCase([5, 3, 9, 5], [2, 0, 4, 1, 3, 1, 4, 0, 4, 3]) self._TestCase([32, 4, 4], [31] * 8) + @test_util.run_deprecated_v1 def testRandom(self): # Random shapes of rank 4, random indices for _ in range(5): @@ -104,6 +108,7 @@ class ScatterAddSubTest(test.TestCase): indices = np.random.randint(shape[0], size=2 * shape[0]) self._TestCase(_AsLong(list(shape)), list(indices)) + @test_util.run_deprecated_v1 def testSubRandom(self): # Random shapes of rank 4, random indices for _ in range(5): @@ -111,6 +116,7 @@ class ScatterAddSubTest(test.TestCase): indices = np.random.randint(shape[0], size=2 * shape[0]) self._TestCase(_AsLong(list(shape)), list(indices), state_ops.scatter_sub) + @test_util.run_deprecated_v1 def testWrongShape(self): # Indices and values mismatch. var = variables.Variable( @@ -241,6 +247,7 @@ class EmbeddingLookupTest(test.TestCase): # both the ids are in the first shard, one of the resulting lookup # vector is going to be empty. The subsequent DivOp fails because of that. # TODO(keveman): Disabling the test until the underlying problem is fixed. + @test_util.run_deprecated_v1 def testSimpleSharded(self): with self.cached_session(): num_shards = 2 @@ -257,6 +264,7 @@ class EmbeddingLookupTest(test.TestCase): self.assertAllEqual(np_result, tf_result) self.assertShapeEqual(np_result, embedding) + @test_util.run_deprecated_v1 def testMaxNorm(self): with self.cached_session(): embeddings = constant_op.constant([[2.0]]) @@ -267,6 +275,7 @@ class EmbeddingLookupTest(test.TestCase): self.assertAllEqual(embedding.eval(), [[1.0]]) + @test_util.run_deprecated_v1 def testMaxNormNontrivial(self): with self.cached_session(): embeddings = constant_op.constant([[2.0, 4.0], [3.0, 1.0]]) @@ -278,8 +287,9 @@ class EmbeddingLookupTest(test.TestCase): norms = math_ops.sqrt( math_ops.reduce_sum(embeddings * embeddings, axis=1)) normalized = embeddings / array_ops.stack([norms, norms], axis=1) - self.assertAllEqual(embedding.eval(), 2 * normalized.eval()) + self.assertAllEqual(embedding.eval(), 2 * self.evaluate(normalized)) + @test_util.run_deprecated_v1 def testSimpleShardedPartitionedVariable(self): with self.cached_session() as sess: num_shards = 2 @@ -294,7 +304,7 @@ class EmbeddingLookupTest(test.TestCase): variables.global_variables_initializer().run() params_values = [params[p_i.name] for p_i in p] # Test that the PartitionedVariable components equal the list in p - p_var_val = sess.run(list(p_variable)) + p_var_val = self.evaluate(list(p_variable)) # Actual test tf_result = embedding.eval(feed_dict=feed_dict) np_result, _, _ = _EmbeddingResult(params, id_vals, num_shards, vocab_size) @@ -302,6 +312,7 @@ class EmbeddingLookupTest(test.TestCase): self.assertAllEqual(np_result, tf_result) self.assertShapeEqual(np_result, embedding) + @test_util.run_deprecated_v1 def testSimpleShardedPartitionedResourceVariable(self): with self.cached_session() as sess: num_shards = 2 @@ -316,15 +327,16 @@ class EmbeddingLookupTest(test.TestCase): variables.global_variables_initializer().run() params_values = [params[p_i.name] for p_i in p] # Test that the PartitionedVariable components equal the list in p - p_var_val = sess.run(list(p_variable)) + p_var_val = self.evaluate(list(p_variable)) # Actual test print(ops.get_default_graph().as_graph_def()) - tf_result = embedding.eval() + tf_result = self.evaluate(embedding) np_result, _, _ = _EmbeddingResult(params, id_vals, num_shards, vocab_size) self.assertAllEqual(params_values, p_var_val) self.assertAllEqual(np_result, tf_result) self.assertShapeEqual(np_result, embedding) + @test_util.run_deprecated_v1 def testShardedModPartitioningInt32Ids(self): with self.cached_session(): num_shards = 5 @@ -347,6 +359,7 @@ class EmbeddingLookupTest(test.TestCase): self.assertAllEqual(np_result, tf_result) self.assertShapeEqual(np_result, embedding) + @test_util.run_deprecated_v1 def testShardedModPartitioningInt64Ids(self): with self.cached_session(): num_shards = 5 @@ -369,6 +382,7 @@ class EmbeddingLookupTest(test.TestCase): self.assertAllEqual(np_result, tf_result) self.assertShapeEqual(np_result, embedding) + @test_util.run_deprecated_v1 def testShardedDivPartitioningInt32Ids(self): with self.cached_session(): num_shards = 5 @@ -393,6 +407,7 @@ class EmbeddingLookupTest(test.TestCase): self.assertAllEqual(np_result, tf_result) self.assertShapeEqual(np_result, embedding) + @test_util.run_deprecated_v1 def testShardedDivPartitioningInt32IdsPartitionedVariable(self): with self.cached_session(): num_shards = 5 @@ -418,6 +433,7 @@ class EmbeddingLookupTest(test.TestCase): self.assertAllEqual(np_result, tf_result) self.assertShapeEqual(np_result, embedding) + @test_util.run_deprecated_v1 def testShardedDivPartitioningInt64Ids(self): with self.cached_session(): num_shards = 5 @@ -442,6 +458,7 @@ class EmbeddingLookupTest(test.TestCase): self.assertAllEqual(np_result, tf_result) self.assertShapeEqual(np_result, embedding) + @test_util.run_deprecated_v1 def testShardedDivPartitioningUnknownParamShape(self): with self.cached_session(): num_shards = 5 @@ -468,6 +485,7 @@ class EmbeddingLookupTest(test.TestCase): params, id_vals, num_shards, vocab_size, partition_strategy="div") self.assertAllEqual(np_result, tf_result) + @test_util.run_deprecated_v1 def testGradientsEmbeddingLookup(self): vocab_size = 9 num_ids = 10 @@ -488,6 +506,7 @@ class EmbeddingLookupTest(test.TestCase): x, x_shape, y, y_shape, x_init_value=x_init_value) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradientsEmbeddingLookupWithComputedParams(self): vocab_size = 9 num_ids = 5 @@ -526,6 +545,7 @@ class EmbeddingLookupTest(test.TestCase): ids = constant_op.constant([0, 1, 1, 17], dtype=dtypes.int32) embedding_ops.embedding_lookup(p, ids) + @test_util.run_deprecated_v1 def testHigherRank(self): np.random.seed(8) with self.cached_session(): @@ -546,6 +566,7 @@ class EmbeddingLookupTest(test.TestCase): sharded = embedding_ops.embedding_lookup(split_params, ids).eval() self.assertAllEqual(simple, sharded) + @test_util.run_deprecated_v1 def testHigherRankMaxNorm(self): np.random.seed(8) with self.cached_session(): @@ -574,6 +595,7 @@ class EmbeddingLookupTest(test.TestCase): split_params, ids, max_norm=1.0).eval() self.assertAllEqual(simple, sharded) + @test_util.run_deprecated_v1 def testTransform(self): # This tests all combinations of: # - ids rank 0, 1, >1 @@ -648,6 +670,7 @@ class EmbeddingLookupSparseTest(test.TestCase): index += num_val return grouped_vals + @test_util.run_deprecated_v1 def testEmbeddingLookupSparse(self): vocab_size = 13 batch_size = 10 @@ -706,6 +729,7 @@ class EmbeddingLookupSparseTest(test.TestCase): atol = rtol self.assertAllClose(np_embedding_sum, tf_embedding_sum, rtol, atol) + @test_util.run_deprecated_v1 def testGradientsEmbeddingLookupSparse(self): vocab_size = 12 batch_size = 4 @@ -733,6 +757,7 @@ class EmbeddingLookupSparseTest(test.TestCase): x, x_shape, y, y_shape, x_init_value=x_init_value) self.assertLess(err, 1e-5 if dtype == dtypes.float64 else 2e-3) + @test_util.run_deprecated_v1 def testIncompatibleShapes(self): with self.cached_session(): x, _, _ = _EmbeddingParams(1, 10, dtype=dtypes.float32) @@ -758,11 +783,13 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): assert num_shards > 0 assert num_shards <= vocab_size - embedding_weights = partitioned_variables.create_partitioned_variables( + initializer = init_ops.truncated_normal_initializer( + mean=0.0, stddev=1.0 / math.sqrt(vocab_size), dtype=dtypes.float32) + embedding_weights = list(variable_scope.get_variable( + name="embedding_weights", shape=[vocab_size, embed_dim], - slicing=[num_shards, 1], - initializer=init_ops.truncated_normal_initializer( - mean=0.0, stddev=1.0 / math.sqrt(vocab_size), dtype=dtypes.float32)) + partitioner=partitioned_variables.fixed_size_partitioner(num_shards), + initializer=initializer)) for w in embedding_weights: w.initializer.run() embedding_weights = [w.eval() for w in embedding_weights] @@ -818,6 +845,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): return sparse_ids, sparse_weights + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_return_zero_vector(self): with self.cached_session(): embedding_weights = self._random_weights() @@ -831,6 +859,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): [(1.0 * embedding_weights[0][0] + 2.0 * embedding_weights[0][1]) / 3.0, [0] * 4, [0] * 4, embedding_weights[0][2], [0] * 4]) + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_return_special_vector(self): with self.cached_session(): embedding_weights = self._random_weights() @@ -845,6 +874,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): 3.0, embedding_weights[0][3], embedding_weights[0][3], embedding_weights[0][2], embedding_weights[0][3]]) + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_no_weights(self): with self.cached_session(): embedding_weights = self._random_weights() @@ -859,6 +889,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): [0] * 4, embedding_weights[0][2], ( embedding_weights[0][0] + embedding_weights[0][1]) / 2.0]) + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_partitioned(self): with self.cached_session(): embedding_weights = self._random_weights(num_shards=3) @@ -873,6 +904,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): [0] * 4, [0] * 4, embedding_weights[2], (embedding_weights[0] + embedding_weights[1]) / 2.0]) + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_partitioned_inconsistent_weights(self): with self.cached_session(): embedding_weights = self._random_weights(num_shards=3) @@ -888,6 +920,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): self.assertRaises(ValueError, embedding_ops.safe_embedding_lookup_sparse, embedding_weights, sparse_ids, sparse_weights) + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_3d_return_zero_vector(self): with self.cached_session(): embedding_weights = self._random_weights() @@ -901,6 +934,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): [0] * 4, [0] * 4 ], [embedding_weights[0][2], [0] * 4, [0] * 4]]) + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_3d_return_special_vector(self): with self.cached_session(): embedding_weights = self._random_weights() @@ -917,6 +951,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): embedding_weights[0][3] ]]) + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_3d_no_weights(self): with self.cached_session(): embedding_weights = self._random_weights() @@ -933,6 +968,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): (embedding_weights[0][0] + embedding_weights[0][1]) / 2.0, [0] * 4 ]]) + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_3d_partitioned(self): with self.cached_session(): embedding_weights = self._random_weights(num_shards=3) @@ -949,6 +985,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): (embedding_weights[0] + embedding_weights[1]) / 2.0, [0] * 4 ]]) + @test_util.run_deprecated_v1 def test_safe_embedding_lookup_sparse_3d_partitioned_inconsistent_weights( self): with self.cached_session(): @@ -968,6 +1005,7 @@ class SafeEmbeddingLookupSparseTest(test.TestCase): class DynamicStitchOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testCint32Cpu(self): with self.session(use_gpu=False): indices = [ @@ -981,6 +1019,7 @@ class DynamicStitchOpTest(test.TestCase): self.assertAllEqual( data_flow_ops.dynamic_stitch(indices, values).eval(), [12, 23, 1, 2]) + @test_util.run_deprecated_v1 def testCint32Gpu(self): with self.session(use_gpu=True): indices = [ @@ -994,6 +1033,7 @@ class DynamicStitchOpTest(test.TestCase): self.assertAllEqual( data_flow_ops.dynamic_stitch(indices, values).eval(), [12, 23, 1, 2]) + @test_util.run_deprecated_v1 def testInt32Cpu(self): with self.session(use_gpu=False): indices = [ @@ -1007,6 +1047,7 @@ class DynamicStitchOpTest(test.TestCase): self.assertAllEqual( data_flow_ops.dynamic_stitch(indices, values).eval(), [12, 23, 1, 2]) + @test_util.run_deprecated_v1 def testInt32Gpu(self): with self.session(use_gpu=True): indices = [ @@ -1020,6 +1061,7 @@ class DynamicStitchOpTest(test.TestCase): self.assertAllEqual( data_flow_ops.dynamic_stitch(indices, values).eval(), [12, 23, 1, 2]) + @test_util.run_deprecated_v1 def testSumGradArgs(self): with self.session(use_gpu=False): indices = [ @@ -1034,6 +1076,7 @@ class DynamicStitchOpTest(test.TestCase): data_flow_ops.dynamic_stitch(indices, values).eval(), [2, 3, 1, 1]) # We expect that the values are merged in order. + @test_util.run_deprecated_v1 def testStitchOrder(self): with self.cached_session(): indices = [] @@ -1049,6 +1092,7 @@ class DynamicStitchOpTest(test.TestCase): class ParallelDynamicStitchOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testCint32Cpu(self): with self.session(use_gpu=False): indices = [ @@ -1063,6 +1107,7 @@ class ParallelDynamicStitchOpTest(test.TestCase): data_flow_ops.parallel_dynamic_stitch(indices, values).eval(), [12, 23, 1, 2, 34, 3, 45]) + @test_util.run_deprecated_v1 def testInt32Cpu(self): with self.session(use_gpu=False): indices = [ @@ -1077,6 +1122,7 @@ class ParallelDynamicStitchOpTest(test.TestCase): data_flow_ops.parallel_dynamic_stitch(indices, values).eval(), [12, 23, 1, 2, 3, 34, 45, 56]) + @test_util.run_deprecated_v1 def testSimple(self): with self.session(use_gpu=False): indices = [ops.convert_to_tensor([0, 1]), ops.convert_to_tensor([2, 3])] diff --git a/tensorflow/python/kernel_tests/extract_image_patches_grad_test.py b/tensorflow/python/kernel_tests/extract_image_patches_grad_test.py index 7d9d4e5175..7ba2dc6c20 100644 --- a/tensorflow/python/kernel_tests/extract_image_patches_grad_test.py +++ b/tensorflow/python/kernel_tests/extract_image_patches_grad_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import random_seed as random_seed_lib +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl @@ -78,6 +79,7 @@ class ExtractImagePatchesGradTest(test.TestCase): }, ] + @test_util.run_deprecated_v1 def testGradient(self): # Set graph seed for determinism. random_seed = 42 @@ -102,6 +104,7 @@ class ExtractImagePatchesGradTest(test.TestCase): print('extract_image_patches gradient err: %.4e' % err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testConstructGradientWithLargeImages(self): batch_size = 4 height = 1024 diff --git a/tensorflow/python/kernel_tests/extract_image_patches_op_test.py b/tensorflow/python/kernel_tests/extract_image_patches_op_test.py index 61436f24cf..bb3c0ae806 100644 --- a/tensorflow/python/kernel_tests/extract_image_patches_op_test.py +++ b/tensorflow/python/kernel_tests/extract_image_patches_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test @@ -43,7 +44,7 @@ class ExtractImagePatches(test.TestCase): strides = [1] + strides + [1] rates = [1] + rates + [1] - with self.session(use_gpu=True): + with test_util.use_gpu(): out_tensor = array_ops.extract_image_patches( constant_op.constant(image), ksizes=ksizes, @@ -51,7 +52,7 @@ class ExtractImagePatches(test.TestCase): rates=rates, padding=padding, name="im2col") - self.assertAllClose(patches, out_tensor.eval()) + self.assertAllClose(patches, self.evaluate(out_tensor)) def testKsize1x1Stride1x1Rate1x1(self): """Verifies that for 1x1 kernel the output equals the input.""" diff --git a/tensorflow/python/kernel_tests/extract_volume_patches_op_test.py b/tensorflow/python/kernel_tests/extract_volume_patches_op_test.py index bbb3fef85b..88f7df8fbb 100644 --- a/tensorflow/python/kernel_tests/extract_volume_patches_op_test.py +++ b/tensorflow/python/kernel_tests/extract_volume_patches_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test @@ -45,14 +46,14 @@ class ExtractVolumePatches(test.TestCase): ksizes = [1] + ksizes + [1] strides = [1] + strides + [1] - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): out_tensor = array_ops.extract_volume_patches( constant_op.constant(image), ksizes=ksizes, strides=strides, padding=padding, name="im2col_3d") - self.assertAllClose(patches, out_tensor.eval()) + self.assertAllClose(patches, self.evaluate(out_tensor)) # pylint: disable=bad-whitespace def testKsize1x1x1Stride1x1x1(self): diff --git a/tensorflow/python/kernel_tests/fifo_queue_test.py b/tensorflow/python/kernel_tests/fifo_queue_test.py index 8961c4b13c..9655351a01 100644 --- a/tensorflow/python/kernel_tests/fifo_queue_test.py +++ b/tensorflow/python/kernel_tests/fifo_queue_test.py @@ -159,7 +159,7 @@ class FIFOQueueTest(test.TestCase): # Run one producer thread for each element in elems. def enqueue(enqueue_op): - sess.run(enqueue_op) + self.evaluate(enqueue_op) threads = [ self.checkedThread( @@ -191,7 +191,7 @@ class FIFOQueueTest(test.TestCase): results = [] def dequeue(): - results.append(sess.run(dequeued_t)) + results.append(self.evaluate(dequeued_t)) threads = [self.checkedThread(target=dequeue) for _ in enqueue_ops] for thread in threads: @@ -211,7 +211,7 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() for i in xrange(len(elems)): - vals = dequeued_t.eval() + vals = self.evaluate(dequeued_t) self.assertEqual([elems[i]], vals) def testDequeueHalf(self): @@ -225,7 +225,7 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() for i in xrange(len(elems)): - vals = dequeued_t.eval() + vals = self.evaluate(dequeued_t) self.assertEqual([elems[i]], vals) def testEnqueueAndBlockingDequeue(self): @@ -240,13 +240,13 @@ class FIFOQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) for enqueue_op in enqueue_ops: - sess.run(enqueue_op) + self.evaluate(enqueue_op) results = [] def dequeue(): for _ in xrange(len(elems)): - results.append(sess.run(dequeued_t)) + results.append(self.evaluate(dequeued_t)) enqueue_thread = self.checkedThread(target=enqueue) dequeue_thread = self.checkedThread(target=dequeue) @@ -269,7 +269,7 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() for i in xrange(len(elems)): - x_val, y_val = sess.run(dequeued_t) + x_val, y_val = self.evaluate(dequeued_t) x, y = elems[i] self.assertEqual([x], x_val) self.assertEqual([y], y_val) @@ -288,9 +288,9 @@ class FIFOQueueTest(test.TestCase): self.assertEqual([], size.get_shape()) enqueue_op.run() - self.assertEqual(1, size.eval()) + self.assertEqual(1, self.evaluate(size)) dequeued_t.op.run() - self.assertEqual(0, size.eval()) + self.assertEqual(0, self.evaluate(size)) def testEnqueueMany(self): with self.cached_session(): @@ -302,7 +302,7 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() for i in range(8): - vals = dequeued_t.eval() + vals = self.evaluate(dequeued_t) self.assertEqual([elems[i % 4]], vals) def testEmptyEnqueueMany(self): @@ -313,9 +313,9 @@ class FIFOQueueTest(test.TestCase): enqueue_op = q.enqueue_many((empty_t,)) size_t = q.size() - self.assertEqual([0], size_t.eval()) + self.assertEqual([0], self.evaluate(size_t)) enqueue_op.run() - self.assertEqual([0], size_t.eval()) + self.assertEqual([0], self.evaluate(size_t)) def testEmptyDequeueMany(self): with self.cached_session(): @@ -323,9 +323,9 @@ class FIFOQueueTest(test.TestCase): enqueue_op = q.enqueue((10.0,)) dequeued_t = q.dequeue_many(0) - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) enqueue_op.run() - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) def testEmptyDequeueUpTo(self): with self.cached_session(): @@ -333,9 +333,9 @@ class FIFOQueueTest(test.TestCase): enqueue_op = q.enqueue((10.0,)) dequeued_t = q.dequeue_up_to(0) - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) enqueue_op.run() - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) def testEmptyDequeueManyWithNoShape(self): with self.cached_session(): @@ -356,7 +356,7 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() for i in range(8): - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertEqual(float_elems[i % 4], float_val) self.assertAllEqual(int_elems[i % 4], int_val) @@ -369,8 +369,8 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() - self.assertAllEqual(elems[0:4], dequeued_t.eval()) - self.assertAllEqual(elems[4:8], dequeued_t.eval()) + self.assertAllEqual(elems[0:4], self.evaluate(dequeued_t)) + self.assertAllEqual(elems[4:8], self.evaluate(dequeued_t)) def testDequeueUpToNoBlocking(self): with self.cached_session(): @@ -381,8 +381,8 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() - self.assertAllEqual(elems[0:4], dequeued_t.eval()) - self.assertAllEqual(elems[4:8], dequeued_t.eval()) + self.assertAllEqual(elems[0:4], self.evaluate(dequeued_t)) + self.assertAllEqual(elems[4:8], self.evaluate(dequeued_t)) def testMultiDequeueMany(self): with self.cached_session() as sess: @@ -399,17 +399,17 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual(float_elems[0:4], float_val) self.assertAllEqual(int_elems[0:4], int_val) self.assertEqual(float_val.shape, dequeued_t[0].get_shape()) self.assertEqual(int_val.shape, dequeued_t[1].get_shape()) - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual(float_elems[4:8], float_val) self.assertAllEqual(int_elems[4:8], int_val) - float_val, int_val = sess.run(dequeued_single_t) + float_val, int_val = self.evaluate(dequeued_single_t) self.assertAllEqual(float_elems[8], float_val) self.assertAllEqual(int_elems[8], int_val) self.assertEqual(float_val.shape, dequeued_single_t[0].get_shape()) @@ -429,13 +429,13 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual(float_elems[0:4], float_val) self.assertAllEqual(int_elems[0:4], int_val) self.assertEqual([None], dequeued_t[0].get_shape().as_list()) self.assertEqual([None, 2], dequeued_t[1].get_shape().as_list()) - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual(float_elems[4:8], float_val) self.assertAllEqual(int_elems[4:8], int_val) @@ -518,7 +518,7 @@ class FIFOQueueTest(test.TestCase): r"Expected \[2,3,3\], got \[2,3,4\]"): sess.run([enqueue_op], feed_dict={elems_bad: np.array([1] * 24).reshape((2, 3, 4))}) - dequeued_t.eval() + self.evaluate(dequeued_t) def testParallelEnqueueMany(self): with self.cached_session() as sess: @@ -529,7 +529,7 @@ class FIFOQueueTest(test.TestCase): # Enqueue 100 items in parallel on 10 threads. def enqueue(): - sess.run(enqueue_op) + self.evaluate(enqueue_op) threads = [self.checkedThread(target=enqueue) for _ in range(10)] for thread in threads: @@ -552,7 +552,7 @@ class FIFOQueueTest(test.TestCase): dequeued_elems = [] def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t)) + dequeued_elems.extend(self.evaluate(dequeued_t)) threads = [self.checkedThread(target=dequeue) for _ in range(10)] for thread in threads: @@ -576,7 +576,7 @@ class FIFOQueueTest(test.TestCase): dequeued_elems = [] def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t)) + dequeued_elems.extend(self.evaluate(dequeued_t)) threads = [self.checkedThread(target=dequeue) for _ in range(10)] for thread in threads: @@ -596,11 +596,11 @@ class FIFOQueueTest(test.TestCase): def enqueue(): for _ in xrange(100): - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): for _ in xrange(100): - self.assertTrue(sess.run(dequeued_t) in (10.0, 20.0)) + self.assertTrue(self.evaluate(dequeued_t) in (10.0, 20.0)) enqueue_threads = [self.checkedThread(target=enqueue) for _ in range(10)] dequeue_threads = [self.checkedThread(target=dequeue) for _ in range(10)] @@ -632,7 +632,7 @@ class FIFOQueueTest(test.TestCase): def dequeue(): for i in xrange(250): - self.assertEqual(i, sess.run(dequeued_t)) + self.assertEqual(i, self.evaluate(dequeued_t)) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -663,7 +663,7 @@ class FIFOQueueTest(test.TestCase): dequeuemany_t = q.dequeue_many(count_placeholder) def enqueue(): - sess.run(enqueue_op) + self.evaluate(enqueue_op) enqueue_thread = self.checkedThread(target=enqueue) enqueue_thread.start() @@ -672,7 +672,7 @@ class FIFOQueueTest(test.TestCase): while elements_dequeued < 250: # With equal probability, run Dequeue or dequeue_many. if random.random() > 0.5: - self.assertEqual(elements_dequeued, dequeued_t.eval()) + self.assertEqual(elements_dequeued, self.evaluate(dequeued_t)) elements_dequeued += 1 else: count = random.randint(0, min(20, 250 - elements_dequeued)) @@ -701,10 +701,10 @@ class FIFOQueueTest(test.TestCase): # The enqueue_op should run after the dequeue op has blocked. # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t).tolist()) + dequeued_elems.extend(self.evaluate(dequeued_t).tolist()) enqueue_thread = self.checkedThread(target=enqueue) dequeue_thread = self.checkedThread(target=dequeue) @@ -728,10 +728,10 @@ class FIFOQueueTest(test.TestCase): # The enqueue_op should run after the dequeue op has blocked. # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t).tolist()) + dequeued_elems.extend(self.evaluate(dequeued_t).tolist()) enqueue_thread = self.checkedThread(target=enqueue) dequeue_thread = self.checkedThread(target=dequeue) @@ -778,12 +778,12 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() close_op.run() for elem in elems: - self.assertEqual([elem], dequeued_t.eval()) + self.assertEqual([elem], self.evaluate(dequeued_t)) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - dequeued_t.eval() + self.evaluate(dequeued_t) def testBlockingDequeueFromClosedQueue(self): with self.cached_session() as sess: @@ -797,11 +797,11 @@ class FIFOQueueTest(test.TestCase): def dequeue(): for elem in elems: - self.assertEqual([elem], sess.run(dequeued_t)) + self.assertEqual([elem], self.evaluate(dequeued_t)) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -821,7 +821,7 @@ class FIFOQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -842,11 +842,11 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() def dequeue(): - self.assertAllEqual(elems, sess.run(dequeued_t)) + self.assertAllEqual(elems, self.evaluate(dequeued_t)) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -867,11 +867,11 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() def dequeue(): - self.assertAllEqual(elems[:3], sess.run(dequeued_t)) + self.assertAllEqual(elems[:3], self.evaluate(dequeued_t)) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -892,8 +892,8 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() def dequeue(): - self.assertAllEqual(elems[:3], sess.run(dequeued_t)) - self.assertAllEqual(elems[3:], sess.run(dequeued_t)) + self.assertAllEqual(elems[:3], self.evaluate(dequeued_t)) + self.assertAllEqual(elems[3:], self.evaluate(dequeued_t)) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -913,16 +913,16 @@ class FIFOQueueTest(test.TestCase): cleanup_dequeue_t = q.dequeue() def enqueue(): - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): - self.assertAllEqual(elems[0:3], sess.run(dequeued_t)) + self.assertAllEqual(elems[0:3], self.evaluate(dequeued_t)) with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(dequeued_t) - self.assertEqual(elems[3], sess.run(cleanup_dequeue_t)) + self.evaluate(dequeued_t) + self.assertEqual(elems[3], self.evaluate(cleanup_dequeue_t)) def close(): - sess.run(close_op) + self.evaluate(close_op) enqueue_thread = self.checkedThread(target=enqueue) enqueue_thread.start() @@ -955,7 +955,7 @@ class FIFOQueueTest(test.TestCase): def dequeue(): with self.assertRaises(errors_impl.OutOfRangeError): - sess.run([dequeued_a_t, dequeued_b_t]) + self.evaluate([dequeued_a_t, dequeued_b_t]) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -968,7 +968,7 @@ class FIFOQueueTest(test.TestCase): # Test that the elements in the partially-dequeued batch are # restored in the correct order. for elem_a, elem_b in zip(elems_a, elems_b): - val_a, val_b = sess.run([cleanup_dequeue_a_t, cleanup_dequeue_b_t]) + val_a, val_b = self.evaluate([cleanup_dequeue_a_t, cleanup_dequeue_b_t]) self.assertEqual(elem_a, val_a) self.assertEqual(elem_b, val_b) self.assertEqual(0, q.size().eval()) @@ -983,7 +983,7 @@ class FIFOQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -1003,7 +1003,7 @@ class FIFOQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -1051,7 +1051,7 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() def blocking_enqueue(): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) thread = self.checkedThread(target=blocking_enqueue) thread.start() @@ -1059,8 +1059,8 @@ class FIFOQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) for elem in elems: - self.assertEqual([elem], dequeued_t.eval()) - self.assertEqual([50.0], dequeued_t.eval()) + self.assertEqual([elem], self.evaluate(dequeued_t)) + self.assertEqual([50.0], self.evaluate(dequeued_t)) thread.join() def testBlockingEnqueueManyToFullQueue(self): @@ -1074,7 +1074,7 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() def blocking_enqueue(): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) thread = self.checkedThread(target=blocking_enqueue) thread.start() @@ -1082,10 +1082,10 @@ class FIFOQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) for elem in elems: - self.assertEqual([elem], dequeued_t.eval()) + self.assertEqual([elem], self.evaluate(dequeued_t)) time.sleep(0.01) - self.assertEqual([50.0], dequeued_t.eval()) - self.assertEqual([60.0], dequeued_t.eval()) + self.assertEqual([50.0], self.evaluate(dequeued_t)) + self.assertEqual([60.0], self.evaluate(dequeued_t)) # Make sure the thread finishes before exiting. thread.join() @@ -1103,7 +1103,7 @@ class FIFOQueueTest(test.TestCase): def blocking_enqueue(): # Expect the operation to succeed once the dequeue op runs. - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) enqueue_thread = self.checkedThread(target=blocking_enqueue) enqueue_thread.start() @@ -1113,18 +1113,18 @@ class FIFOQueueTest(test.TestCase): time.sleep(0.1) def close(): - sess.run(close_op) + self.evaluate(close_op) close_thread = self.checkedThread(target=close) close_thread.start() # The dequeue will unblock both threads. - self.assertEqual(10.0, dequeued_t.eval()) + self.assertEqual(10.0, self.evaluate(dequeued_t)) enqueue_thread.join() close_thread.join() for elem in [20.0, 30.0, 40.0, 50.0]: - self.assertEqual(elem, dequeued_t.eval()) + self.assertEqual(elem, self.evaluate(dequeued_t)) self.assertEqual(0, q.size().eval()) def testBlockingEnqueueManyBeforeClose(self): @@ -1138,7 +1138,7 @@ class FIFOQueueTest(test.TestCase): enqueue_op.run() def blocking_enqueue(): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) enqueue_thread = self.checkedThread(target=blocking_enqueue) enqueue_thread.start() @@ -1148,17 +1148,17 @@ class FIFOQueueTest(test.TestCase): time.sleep(0.1) def close(): - sess.run(close_op) + self.evaluate(close_op) close_thread = self.checkedThread(target=close) close_thread.start() # The dequeue will unblock both threads. - self.assertEqual(10.0, dequeued_t.eval()) + self.assertEqual(10.0, self.evaluate(dequeued_t)) enqueue_thread.join() close_thread.join() for elem in [20.0, 30.0, 50.0, 60.0]: - self.assertEqual(elem, dequeued_t.eval()) + self.assertEqual(elem, self.evaluate(dequeued_t)) def testDoesNotLoseValue(self): with self.cached_session(): @@ -1266,19 +1266,19 @@ class FIFOQueueTest(test.TestCase): def _blockingDequeue(self, sess, dequeue_op): with self.assertRaisesOpError("was cancelled"): - sess.run(dequeue_op) + self.evaluate(dequeue_op) def _blockingDequeueMany(self, sess, dequeue_many_op): with self.assertRaisesOpError("was cancelled"): - sess.run(dequeue_many_op) + self.evaluate(dequeue_many_op) def _blockingEnqueue(self, sess, enqueue_op): with self.assertRaisesOpError("was cancelled"): - sess.run(enqueue_op) + self.evaluate(enqueue_op) def _blockingEnqueueMany(self, sess, enqueue_many_op): with self.assertRaisesOpError("was cancelled"): - sess.run(enqueue_many_op) + self.evaluate(enqueue_many_op) def testResetOfBlockingOperation(self): with self.cached_session() as sess: @@ -1321,7 +1321,7 @@ class FIFOQueueTest(test.TestCase): def blocking_enqueue(): enq_done.append(False) # This will fill the queue and then block until enough dequeues happen. - sess.run(enq) + self.evaluate(enq) enq_done.append(True) thread = self.checkedThread(target=blocking_enqueue) @@ -1331,14 +1331,14 @@ class FIFOQueueTest(test.TestCase): results = [] results.append(deq.eval()) # Will only complete after the enqueue starts. self.assertEqual(len(enq_done), 1) - self.assertEqual(sess.run(size_op), 5) + self.assertEqual(self.evaluate(size_op), 5) for _ in range(3): results.append(deq.eval()) time.sleep(0.1) self.assertEqual(len(enq_done), 1) - self.assertEqual(sess.run(size_op), 5) + self.assertEqual(self.evaluate(size_op), 5) # This dequeue will unblock the thread. results.append(deq.eval()) @@ -1364,7 +1364,7 @@ class FIFOQueueTest(test.TestCase): def blocking_dequeue(): # Will only complete after 4 enqueues complete. - results.extend(sess.run(deq)) + results.extend(self.evaluate(deq)) thread = self.checkedThread(target=blocking_dequeue) thread.start() @@ -1373,7 +1373,7 @@ class FIFOQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) self.assertEqual(len(results), 0) - sess.run(enq) + self.evaluate(enq) # Enough enqueued to unblock the dequeue thread.join() @@ -1405,7 +1405,7 @@ class FIFOQueueTest(test.TestCase): q.enqueue_many(input_tuple).run() output_tuple_t = q.dequeue_many(32) - output_tuple = sess.run(output_tuple_t) + output_tuple = self.evaluate(output_tuple_t) for (input_elem, output_elem) in zip(input_tuple, output_tuple): self.assertAllEqual(input_elem, output_elem) @@ -1507,10 +1507,10 @@ class FIFOQueueDictTest(test.TestCase): enqueue_op4 = q.enqueue_many({"f": [40.0, 50.0]}) dequeue = q.dequeue() dequeue_2 = q.dequeue_many(2) - sess.run(enqueue_op) - sess.run(enqueue_op2) - sess.run(enqueue_op3) - sess.run(enqueue_op4) + self.evaluate(enqueue_op) + self.evaluate(enqueue_op2) + self.evaluate(enqueue_op3) + self.evaluate(enqueue_op4) f = sess.run(dequeue["f"]) self.assertEqual(10.0, f) f = sess.run(dequeue_2["f"]) @@ -1565,10 +1565,10 @@ class FIFOQueueDictTest(test.TestCase): }) dequeue = q.dequeue() dequeue_2 = q.dequeue_many(2) - sess.run(enqueue_op) - sess.run(enqueue_op2) - sess.run(enqueue_op3) - sess.run(enqueue_op4) + self.evaluate(enqueue_op) + self.evaluate(enqueue_op2) + self.evaluate(enqueue_op3) + self.evaluate(enqueue_op4) i, f, s = sess.run([dequeue["i"], dequeue["f"], dequeue["s"]]) self.assertEqual(123, i) self.assertEqual(10.0, f) @@ -1597,7 +1597,7 @@ class FIFOQueueWithTimeoutTest(test.TestCase): # until operation_timeout_in_ms. with self.assertRaisesRegexp(errors_impl.DeadlineExceededError, "Timed out waiting for notification"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) def testReusableAfterTimeout(self): with self.cached_session() as sess: @@ -1613,8 +1613,8 @@ class FIFOQueueWithTimeoutTest(test.TestCase): "Timed out waiting for notification"): sess.run(dequeued_t, options=config_pb2.RunOptions(timeout_in_ms=10)) - sess.run(enqueue_op) - self.assertEqual(37, sess.run(dequeued_t)) + self.evaluate(enqueue_op) + self.assertEqual(37, self.evaluate(dequeued_t)) class QueueContainerTest(test.TestCase): diff --git a/tensorflow/python/kernel_tests/fractional_avg_pool_op_test.py b/tensorflow/python/kernel_tests/fractional_avg_pool_op_test.py index f89d2062f1..0d5928aefa 100644 --- a/tensorflow/python/kernel_tests/fractional_avg_pool_op_test.py +++ b/tensorflow/python/kernel_tests/fractional_avg_pool_op_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_nn_ops from tensorflow.python.ops import gradient_checker @@ -37,7 +38,6 @@ class FractionalAvgTest(test.TestCase): # Random number generate with seed. _PRNG = np.random.RandomState(341261000) _SEED = 341261001 - _SEED2 = 341261002 def _AvgPoolAlongRows(self, input_matrix, row_seq, overlapping): """Perform average pool along row of a 2-D matrix based on row_seq. @@ -128,15 +128,13 @@ class FractionalAvgTest(test.TestCase): None """ with self.cached_session() as sess: - p, r, c = nn_ops.fractional_avg_pool( + p, r, c = nn_ops.fractional_avg_pool_v2( input_tensor, pooling_ratio, pseudo_random, overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) - actual, row_seq, col_seq = sess.run([p, r, c]) + seed=self._SEED) + actual, row_seq, col_seq = self.evaluate([p, r, c]) expected = self._GetExpectedFractionalAvgPoolResult(input_tensor, row_seq, col_seq, overlapping) self.assertShapeEqual(expected, p) @@ -161,15 +159,13 @@ class FractionalAvgTest(test.TestCase): rand_mat = self._PRNG.randint(10, size=tensor_shape) pooling_ratio = [1, math.sqrt(2), math.sqrt(2), 1] with self.cached_session() as sess: - p, r, c = nn_ops.fractional_avg_pool( + p, r, c = nn_ops.fractional_avg_pool_v2( rand_mat.astype(np.float32), pooling_ratio, pseudo_random, overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) - tensor_output, row_seq, col_seq = sess.run([p, r, c]) + seed=self._SEED) + tensor_output, row_seq, col_seq = self.evaluate([p, r, c]) expected_result = self._GetExpectedFractionalAvgPoolResult( rand_mat.astype(np.float32), row_seq, col_seq, overlapping) print("row sequence:") @@ -214,12 +210,6 @@ class FractionalAvgTest(test.TestCase): def testIntegerTensorInput(self): """Test FractionalAvgPool works fine when input tensor is integer type. - - I would have used _ValidateFractionalAvgPoolResult function to automate this - process, however, there's rounding issue. It is caused by numpy.mean cast - integer input to numpy.float64 for intermediate use. While for - fractional_avg_pool, the mean operation is integer division (trucated). So, - for this test case, I will hard code a simple matrix. """ pseudo_random = True overlapping = True @@ -234,29 +224,9 @@ class FractionalAvgTest(test.TestCase): [4, 4, 5, 9, 7, 2] ]) # pyformat: enable - with self.cached_session() as sess: - # Since deterministic = True, seed and seed2 are fixed. Therefore r, and c - # are the same each time. We can have an expected result precomputed. - # r = [0, 2, 4, 6] - # c = [0, 1, 3, 4, 6] - - # pyformat: disable - expected = np.array([ - [6, 5, 3, 5], - [5, 5, 4, 5], - [5, 4, 7, 5] - ]).reshape((1, 3, 4, 1)) - # pyformat: enable - p, unused_r, unused_c = nn_ops.fractional_avg_pool( - mat.reshape(tensor_shape), [1, math.sqrt(3), math.sqrt(2), 1], - pseudo_random, - overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) - actual = sess.run(p) - self.assertShapeEqual(expected, p) - self.assertAllClose(expected, actual) + self._ValidateFractionalAvgPoolResult(mat.reshape(tensor_shape), + [1, math.sqrt(3), math.sqrt(2), 1], + pseudo_random, overlapping) def testDifferentTensorShapes(self): """Test different shapes of input tensor. @@ -312,6 +282,7 @@ class FractionalAvgTest(test.TestCase): self._ValidateFractionalAvgPoolResult(rand_mat, [1, 2, 2, 1], pseudo_random, overlapping) + @test_util.run_deprecated_v1 def testDifferentInputTensorShape(self): """Runs the operation in one session with different input tensor shapes.""" with self.cached_session() as sess: @@ -320,14 +291,12 @@ class FractionalAvgTest(test.TestCase): pooling_ratio = [1, 1.5, 1.5, 1] pseudo_random = False overlapping = False - p, r, c = nn_ops.fractional_avg_pool( + p, r, c = nn_ops.fractional_avg_pool_v2( input_holder, pooling_ratio, pseudo_random, overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) + seed=self._SEED) # First run. input_a = np.zeros([3, 32, 32, 3]) actual, row_seq, col_seq = sess.run([p, r, c], {input_holder: input_a}) @@ -372,7 +341,6 @@ class FractionalAvgPoolGradTest(test.TestCase): """ _PRNG = np.random.RandomState(341261004) _SEED = 341261005 - _SEED2 = 341261006 def _GenerateRandomInputTensor(self, shape): num_elements = 1 @@ -398,7 +366,7 @@ class FractionalAvgPoolGradTest(test.TestCase): padding = "VALID" output_tensor = nn_ops.avg_pool(input_tensor, window_size, stride_size, padding) - output_data = output_tensor.eval() + output_data = self.evaluate(output_tensor) num_elements = 1 for dim_size in output_data.shape: num_elements *= dim_size @@ -407,7 +375,7 @@ class FractionalAvgPoolGradTest(test.TestCase): input_backprop_tensor = gen_nn_ops.avg_pool_grad( input_tensor.get_shape(), output_backprop, window_size, stride_size, padding) - input_backprop = input_backprop_tensor.eval() + input_backprop = self.evaluate(input_backprop_tensor) row_seq = list(range(0, num_rows + 1, row_window_size)) col_seq = list(range(0, num_cols + 1, col_window_size)) fap_input_backprop_tensor = gen_nn_ops.fractional_avg_pool_grad( @@ -416,7 +384,7 @@ class FractionalAvgPoolGradTest(test.TestCase): row_seq, col_seq, overlapping=False) - fap_input_backprop = fap_input_backprop_tensor.eval() + fap_input_backprop = self.evaluate(fap_input_backprop_tensor) self.assertShapeEqual(input_backprop, fap_input_backprop_tensor) self.assertAllClose(input_backprop, fap_input_backprop) @@ -437,7 +405,7 @@ class FractionalAvgPoolGradTest(test.TestCase): padding = "VALID" output_tensor = nn_ops.avg_pool(input_tensor, window_size, stride_size, padding) - output_data = output_tensor.eval() + output_data = self.evaluate(output_tensor) num_elements = 1 for dim_size in output_data.shape: num_elements *= dim_size @@ -446,7 +414,7 @@ class FractionalAvgPoolGradTest(test.TestCase): input_backprop_tensor = gen_nn_ops.avg_pool_grad( input_tensor.get_shape(), output_backprop, window_size, stride_size, padding) - input_backprop = input_backprop_tensor.eval() + input_backprop = self.evaluate(input_backprop_tensor) row_seq = list(range(0, num_rows, row_window_size - 1)) col_seq = list(range(0, num_cols, col_window_size - 1)) row_seq[-1] += 1 @@ -457,10 +425,11 @@ class FractionalAvgPoolGradTest(test.TestCase): row_seq, col_seq, overlapping=True) - fap_input_backprop = fap_input_backprop_tensor.eval() + fap_input_backprop = self.evaluate(fap_input_backprop_tensor) self.assertShapeEqual(input_backprop, fap_input_backprop_tensor) self.assertAllClose(input_backprop, fap_input_backprop) + @test_util.run_deprecated_v1 def testAllInputOptionsThroughGradientError(self): input_shape = (1, 7, 13, 1) input_data = self._GenerateRandomInputTensor(input_shape) @@ -470,15 +439,13 @@ class FractionalAvgPoolGradTest(test.TestCase): for overlapping in True, False: with self.cached_session() as _: input_tensor = constant_op.constant(input_data, shape=input_shape) - output_tensor, unused_a, unused_b = nn_ops.fractional_avg_pool( + output_tensor, unused_a, unused_b = nn_ops.fractional_avg_pool_v2( input_tensor, pooling_ratio, pseudo_random=pseudo_random, overlapping=overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) - output_data = output_tensor.eval() + seed=self._SEED) + output_data = self.evaluate(output_tensor) output_shape = output_data.shape # error_margin and delta setting is similar to avg_pool_grad. error_margin = 1e-4 @@ -491,6 +458,7 @@ class FractionalAvgPoolGradTest(test.TestCase): delta=1e-2) self.assertLess(gradient_error, error_margin) + @test_util.run_deprecated_v1 def testDifferentTensorShapesThroughGradientError(self): pseudo_random = True overlapping = True @@ -503,15 +471,13 @@ class FractionalAvgPoolGradTest(test.TestCase): input_data = self._GenerateRandomInputTensor(input_shape) with self.cached_session() as _: input_tensor = constant_op.constant(input_data, shape=input_shape) - output_tensor, unused_a, unused_b = nn_ops.fractional_avg_pool( + output_tensor, unused_a, unused_b = nn_ops.fractional_avg_pool_v2( input_tensor, pooling_ratio, pseudo_random=pseudo_random, overlapping=overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) - output_data = output_tensor.eval() + seed=self._SEED) + output_data = self.evaluate(output_tensor) output_shape = output_data.shape # error_margin and delta setting is similar to avg_pool_grad. error_margin = 1e-4 @@ -524,6 +490,7 @@ class FractionalAvgPoolGradTest(test.TestCase): delta=1e-2) self.assertLess(gradient_error, error_margin) + @test_util.run_deprecated_v1 def testLargePoolingRatioThroughGradientError(self): input_shape = (1, 17, 23, 1) input_data = self._GenerateRandomInputTensor(input_shape) @@ -534,14 +501,12 @@ class FractionalAvgPoolGradTest(test.TestCase): with self.cached_session() as _: input_tensor = constant_op.constant(input_data, shape=input_shape) - output_tensor, unused_a, unused_b = nn_ops.fractional_avg_pool( + output_tensor, unused_a, unused_b = nn_ops.fractional_avg_pool_v2( input_tensor, pooling_ratio, pseudo_random=pseudo_random, overlapping=overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) + seed=self._SEED) # error_margin and delta setting is similar to avg_pool_grad. error_margin = 1e-4 gradient_error = gradient_checker.compute_gradient_error( diff --git a/tensorflow/python/kernel_tests/fractional_max_pool_op_test.py b/tensorflow/python/kernel_tests/fractional_max_pool_op_test.py index 9b94ca8554..fa886cc215 100644 --- a/tensorflow/python/kernel_tests/fractional_max_pool_op_test.py +++ b/tensorflow/python/kernel_tests/fractional_max_pool_op_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_nn_ops from tensorflow.python.ops import gradient_checker @@ -37,7 +38,6 @@ class FractionalMaxPoolTest(test.TestCase): # Random number generate with seed. _PRNG = np.random.RandomState(341261) _SEED = 123456 - _SEED2 = 654321 def _MaxPoolAlongRows(self, input_matrix, row_seq, overlapping): """Perform max pool along row of a 2-D matrix based on row_seq. @@ -128,15 +128,13 @@ class FractionalMaxPoolTest(test.TestCase): None """ with self.cached_session() as sess: - p, r, c = nn_ops.fractional_max_pool( + p, r, c = nn_ops.fractional_max_pool_v2( input_tensor, pooling_ratio, pseudo_random, overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) - actual, row_seq, col_seq = sess.run([p, r, c]) + seed=self._SEED) + actual, row_seq, col_seq = self.evaluate([p, r, c]) expected = self._GetExpectedFractionalMaxPoolResult(input_tensor, row_seq, col_seq, overlapping) self.assertShapeEqual(expected, p) @@ -161,15 +159,13 @@ class FractionalMaxPoolTest(test.TestCase): rand_mat = self._PRNG.randint(10, size=tensor_shape) pooling_ratio = [1, math.sqrt(2), math.sqrt(2), 1] with self.cached_session() as sess: - p, r, c = nn_ops.fractional_max_pool( + p, r, c = nn_ops.fractional_max_pool_v2( rand_mat, pooling_ratio, pseudo_random, overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) - tensor_output, row_seq, col_seq = sess.run([p, r, c]) + seed=self._SEED) + tensor_output, row_seq, col_seq = self.evaluate([p, r, c]) expected_result = self._GetExpectedFractionalMaxPoolResult(rand_mat, row_seq, col_seq, @@ -283,6 +279,7 @@ class FractionalMaxPoolTest(test.TestCase): self._ValidateFractionalMaxPoolResult(rand_mat, [1, 2, 2, 1], pseudo_random, overlapping) + @test_util.run_deprecated_v1 def testDifferentInputTensorShape(self): """Runs the operation in one session with different input tensor shapes.""" with self.cached_session() as sess: @@ -291,14 +288,12 @@ class FractionalMaxPoolTest(test.TestCase): pooling_ratio = [1, 1.5, 1.5, 1] pseudo_random = False overlapping = False - p, r, c = nn_ops.fractional_max_pool( + p, r, c = nn_ops.fractional_max_pool_v2( input_holder, pooling_ratio, pseudo_random, overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) + seed=self._SEED) # First run. input_a = np.zeros([3, 32, 32, 3]) actual, row_seq, col_seq = sess.run([p, r, c], {input_holder: input_a}) @@ -344,7 +339,6 @@ class FractionalMaxPoolGradTest(test.TestCase): _PRNG = np.random.RandomState(341261) _SEED = 123456 - _SEED2 = 654321 def _GenerateUniqueRandomInputTensor(self, shape): """Generate 'unqiue' random input tensor. @@ -382,12 +376,12 @@ class FractionalMaxPoolGradTest(test.TestCase): padding = "VALID" output_tensor = nn_ops.max_pool(input_tensor, window_size, stride_size, padding) - output_data = output_tensor.eval() + output_data = self.evaluate(output_tensor) output_backprop = self._PRNG.randint(100, size=output_data.shape) input_backprop_tensor = gen_nn_ops.max_pool_grad( input_tensor, output_tensor, output_backprop, window_size, stride_size, padding) - input_backprop = input_backprop_tensor.eval() + input_backprop = self.evaluate(input_backprop_tensor) row_seq = list(range(0, num_rows + 1, row_window_size)) col_seq = list(range(0, num_cols + 1, col_window_size)) fmp_input_backprop_tensor = gen_nn_ops.fractional_max_pool_grad( @@ -397,7 +391,7 @@ class FractionalMaxPoolGradTest(test.TestCase): row_seq, col_seq, overlapping=False) - fmp_input_backprop = fmp_input_backprop_tensor.eval() + fmp_input_backprop = self.evaluate(fmp_input_backprop_tensor) self.assertShapeEqual(input_backprop, fmp_input_backprop_tensor) self.assertAllClose(input_backprop, fmp_input_backprop) @@ -417,12 +411,12 @@ class FractionalMaxPoolGradTest(test.TestCase): padding = "VALID" output_tensor = nn_ops.max_pool(input_tensor, window_size, stride_size, padding) - output_data = output_tensor.eval() + output_data = self.evaluate(output_tensor) output_backprop = self._PRNG.randint(100, size=output_data.shape) input_backprop_tensor = gen_nn_ops.max_pool_grad( input_tensor, output_tensor, output_backprop, window_size, stride_size, padding) - input_backprop = input_backprop_tensor.eval() + input_backprop = self.evaluate(input_backprop_tensor) row_seq = list(range(0, num_rows, row_window_size - 1)) col_seq = list(range(0, num_cols, col_window_size - 1)) row_seq[-1] += 1 @@ -434,10 +428,11 @@ class FractionalMaxPoolGradTest(test.TestCase): row_seq, col_seq, overlapping=True) - fmp_input_backprop = fmp_input_backprop_tensor.eval() + fmp_input_backprop = self.evaluate(fmp_input_backprop_tensor) self.assertShapeEqual(input_backprop, fmp_input_backprop_tensor) self.assertAllClose(input_backprop, fmp_input_backprop) + @test_util.run_deprecated_v1 def testAllInputOptionsThroughGradientError(self): input_shape = (1, 7, 13, 1) input_data = self._GenerateUniqueRandomInputTensor(input_shape) @@ -449,15 +444,13 @@ class FractionalMaxPoolGradTest(test.TestCase): for overlapping in True, False: with self.cached_session() as _: input_tensor = constant_op.constant(input_data, shape=input_shape) - output_tensor, unused_a, unused_b = nn_ops.fractional_max_pool( + output_tensor, unused_a, unused_b = nn_ops.fractional_max_pool_v2( input_tensor, pooling_ratio, pseudo_random=pseudo_random, overlapping=overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) - output_data = output_tensor.eval() + seed=self._SEED) + output_data = self.evaluate(output_tensor) output_shape = output_data.shape # error_margin and delta setting is similar to max_pool_grad. error_margin = 1e-3 @@ -470,6 +463,7 @@ class FractionalMaxPoolGradTest(test.TestCase): delta=1e-2) self.assertLess(gradient_error, error_margin) + @test_util.run_deprecated_v1 def testDifferentTensorShapesThroughGradientError(self): pseudo_random = True overlapping = True @@ -484,15 +478,13 @@ class FractionalMaxPoolGradTest(test.TestCase): input_data += self._PRNG.random_sample(input_shape) with self.cached_session() as _: input_tensor = constant_op.constant(input_data, shape=input_shape) - output_tensor, unused_a, unused_b = nn_ops.fractional_max_pool( + output_tensor, unused_a, unused_b = nn_ops.fractional_max_pool_v2( input_tensor, pooling_ratio, pseudo_random=pseudo_random, overlapping=overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) - output_data = output_tensor.eval() + seed=self._SEED) + output_data = self.evaluate(output_tensor) output_shape = output_data.shape # error_margin and delta setting is similar to max_pool_grad. error_margin = 1e-3 @@ -505,6 +497,7 @@ class FractionalMaxPoolGradTest(test.TestCase): delta=1e-2) self.assertLess(gradient_error, error_margin) + @test_util.run_deprecated_v1 def testLargePoolingRatioThroughGradientError(self): input_shape = (1, 17, 23, 1) input_data = self._GenerateUniqueRandomInputTensor(input_shape) @@ -517,14 +510,12 @@ class FractionalMaxPoolGradTest(test.TestCase): with self.cached_session() as _: input_tensor = constant_op.constant(input_data, shape=input_shape) - output_tensor, unused_a, unused_b = nn_ops.fractional_max_pool( + output_tensor, unused_a, unused_b = nn_ops.fractional_max_pool_v2( input_tensor, pooling_ratio, pseudo_random=pseudo_random, overlapping=overlapping, - deterministic=True, - seed=self._SEED, - seed2=self._SEED2) + seed=self._SEED) # error_margin and delta setting is similar to max_pool_grad. error_margin = 1e-3 gradient_error = gradient_checker.compute_gradient_error( @@ -592,7 +583,7 @@ class FractionalMaxPoolGradTest(test.TestCase): row_seq, col_seq, overlapping=False) - input_backprop_not_overlapping = r.eval() + input_backprop_not_overlapping = self.evaluate(r) self.assertShapeEqual( np.reshape(expected_input_backprop_not_overlapping, input_size), r) self.assertAllClose(expected_input_backprop_not_overlapping, @@ -602,7 +593,7 @@ class FractionalMaxPoolGradTest(test.TestCase): output_data_overlapping, shape=output_size) r = gen_nn_ops.fractional_max_pool_grad( input_tensor, output_tensor, grad, row_seq, col_seq, overlapping=True) - input_backprop_overlapping = r.eval() + input_backprop_overlapping = self.evaluate(r) self.assertShapeEqual( np.reshape(expected_input_backprop_overlapping, input_size), r) self.assertAllClose(expected_input_backprop_overlapping, diff --git a/tensorflow/python/kernel_tests/functional_ops_test.py b/tensorflow/python/kernel_tests/functional_ops_test.py index 04c1032722..c489623fe5 100644 --- a/tensorflow/python/kernel_tests/functional_ops_test.py +++ b/tensorflow/python/kernel_tests/functional_ops_test.py @@ -56,6 +56,7 @@ def simple_scoped_fn(a, x): return math_ops.multiply(math_ops.add(a, x), two) +@test_util.with_control_flow_v2 class FunctionalOpsTest(test.TestCase): @test_util.run_in_graph_and_eager_modes @@ -100,6 +101,7 @@ class FunctionalOpsTest(test.TestCase): (elems, other_elems), initializer) self.assertAllEqual([1.0, 2.0, 3.0], self.evaluate(r)) + @test_util.run_deprecated_v1 def testFoldl_Scoped(self): with self.cached_session() as sess: with variable_scope.variable_scope("root") as varscope: @@ -152,6 +154,7 @@ class FunctionalOpsTest(test.TestCase): initializer) self.assertAllEqual(1, self.evaluate(r)) + @test_util.run_deprecated_v1 def testFoldr_Scoped(self): with self.cached_session() as sess: with variable_scope.variable_scope("root") as varscope: @@ -172,6 +175,7 @@ class FunctionalOpsTest(test.TestCase): self.assertAllEqual(1282, self.evaluate(r)) # pylint: disable=unnecessary-lambda + @test_util.run_deprecated_v1 def testFold_Grad(self): with self.cached_session(): elems = constant_op.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], name="data") @@ -213,6 +217,7 @@ class FunctionalOpsTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "not a scalar"): functional_ops.map_fn(lambda x: x, 1) + @test_util.run_deprecated_v1 def testMap_Scoped(self): with self.cached_session() as sess: @@ -244,6 +249,7 @@ class FunctionalOpsTest(test.TestCase): self.assertEqual(len(variables.trainable_variables()), 1) self.assertAllEqual(doubles, self.evaluate(r)) + @test_util.run_deprecated_v1 def testMap_Grad(self): with self.cached_session(): param = constant_op.constant(2.0) @@ -380,6 +386,7 @@ class FunctionalOpsTest(test.TestCase): ValueError, "two structures don't have the same nested structure"): functional_ops.scan(lambda a, x: (a, -a), elems, initializer) + @test_util.run_deprecated_v1 def testScan_Scoped(self): with self.cached_session() as sess: with variable_scope.variable_scope("root") as varscope: @@ -424,6 +431,7 @@ class FunctionalOpsTest(test.TestCase): # t_1 == 1, b == 4.5, y == 0.5, returns b * y * x = 9 self.assertAllClose([1., 1., 2.25, 9.], self.evaluate(r)) + @test_util.run_deprecated_v1 def testScan_Control(self): with self.cached_session() as sess: s = array_ops.placeholder(dtypes.float32, shape=[None]) @@ -435,6 +443,7 @@ class FunctionalOpsTest(test.TestCase): np.array([1.0, 3.0, 9.0]), sess.run(c, {s: [1, 3, 3], b: True})) + @test_util.run_deprecated_v1 def testScan_Grad(self): with self.cached_session(): elems = constant_op.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], name="data") @@ -447,6 +456,7 @@ class FunctionalOpsTest(test.TestCase): r = gradients_impl.gradients(r, v)[0] self.assertAllEqual(873.0, self.evaluate(r)) + @test_util.run_deprecated_v1 def testScanGradientWithPartStopGradient(self): a = variables.Variable(0.0, name="a") b = variables.Variable(0.0, name="b") @@ -457,7 +467,7 @@ class FunctionalOpsTest(test.TestCase): grad = gradients_impl.gradients(ys=[loss], xs=[a, b]) with self.test_session(use_gpu=True) as sess: variables.global_variables_initializer().run() - sess.run(grad) + self.evaluate(grad) @test_util.run_in_graph_and_eager_modes def testFoldShape(self): @@ -476,12 +486,15 @@ class FunctionalOpsTest(test.TestCase): y = functional_ops.map_fn(lambda e: e, x) self.assertAllEqual(y.get_shape(), self.evaluate(y).shape) + @test_util.run_deprecated_v1 def testMapUnknownShape(self): x = array_ops.placeholder(dtypes.float32) y = functional_ops.map_fn(lambda e: e, x) self.assertIs(None, y.get_shape().dims) + @test_util.disable_control_flow_v2("b/119323354") @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testMapEmptyScalar(self): map_return = functional_ops.map_fn(lambda x: 1, constant_op.constant([])) self.assertAllEqual([0], map_return.get_shape().dims) @@ -489,6 +502,8 @@ class FunctionalOpsTest(test.TestCase): # TODO(akshayka): this test fails in eager: the iterable is of length 0 so # so the body of the while loop never executes + @test_util.disable_control_flow_v2("b/119323354") + @test_util.run_deprecated_v1 def testMapEmptyTensor(self): with self.cached_session(): map_return = functional_ops.map_fn(lambda x: array_ops.zeros([3, 2]), @@ -509,6 +524,7 @@ class FunctionalOpsTest(test.TestCase): # TODO(akshayka): this test fails in eager: the iterable is of length 0 so # so the body of the while loop never executes + @test_util.run_deprecated_v1 def testScanEmptyTensor(self): with self.cached_session(): x = functional_ops.scan( @@ -516,6 +532,7 @@ class FunctionalOpsTest(test.TestCase): self.assertAllEqual([0, 2, 4], x.get_shape()) self.assertAllEqual(x.get_shape(), self.evaluate(x).shape) + @test_util.run_deprecated_v1 def testScanUnknownShape(self): x = array_ops.placeholder(dtypes.float32) initializer = array_ops.placeholder(dtypes.float32) @@ -526,6 +543,7 @@ class FunctionalOpsTest(test.TestCase): y = functional_ops.scan(fn, x, initializer=initializer) self.assertIs(None, y.get_shape().dims) + @test_util.run_deprecated_v1 def testScanVaryingShape(self): with self.cached_session() as sess: x = array_ops.placeholder(dtype=dtypes.float32, shape=[None, 2]) @@ -542,6 +560,7 @@ class FunctionalOpsTest(test.TestCase): sess.run([result, result_t, result_grad, result_t_grad], feed_dict={x: [[1.0, 2.0]]}) + @test_util.run_deprecated_v1 def testRemoteFunction(self): worker_config = config_pb2.ConfigProto() worker_config.device_count["CPU"] = 2 @@ -564,10 +583,11 @@ class FunctionalOpsTest(test.TestCase): target="/job:worker/replica:0/task:0/cpu:1") with session.Session(worker[0].target) as sess: - sess.run(variables.global_variables_initializer()) - mul = sess.run(remote_op) + self.evaluate(variables.global_variables_initializer()) + mul = self.evaluate(remote_op) self.assertEqual(mul, [6]) + @test_util.run_deprecated_v1 def testRemoteFunctionDirectSession(self): worker_config = config_pb2.ConfigProto() worker_config.device_count["CPU"] = 2 @@ -588,10 +608,11 @@ class FunctionalOpsTest(test.TestCase): target="/job:localhost/replica:0/task:0/cpu:1") with self.test_session(config=worker_config) as sess: - sess.run(variables.global_variables_initializer()) - mul = sess.run(remote_op) + self.evaluate(variables.global_variables_initializer()) + mul = self.evaluate(remote_op) self.assertEqual(mul, [6]) + @test_util.run_deprecated_v1 def testRemoteFunctionSameDeviceDirectSession(self): @function.Defun(dtypes.int32, dtypes.int32) @@ -607,8 +628,8 @@ class FunctionalOpsTest(test.TestCase): args=[a, b], Tout=[dtypes.int32], f=_remote_fn, target="/cpu:0") with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - mul = sess.run(remote_op) + self.evaluate(variables.global_variables_initializer()) + mul = self.evaluate(remote_op) self.assertEqual(mul, [6]) def testRemoteFunctionCPUGPU(self): @@ -631,8 +652,8 @@ class FunctionalOpsTest(test.TestCase): target="/job:localhost/replica:0/task:0/device:GPU:0")[0] + 3.0 with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - mul = sess.run(remote_op) + self.evaluate(variables.global_variables_initializer()) + mul = self.evaluate(remote_op) self.assertEqual(mul, 9.0) def testRemoteFunctionGPUCPU(self): @@ -655,8 +676,8 @@ class FunctionalOpsTest(test.TestCase): target="/job:localhost/replica:0/task:0/cpu:0")[0] + 3.0 with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - mul = sess.run(remote_op) + self.evaluate(variables.global_variables_initializer()) + mul = self.evaluate(remote_op) self.assertEqual(mul, 9.0) def testRemoteFunctionGPUCPUStrings(self): @@ -674,9 +695,10 @@ class FunctionalOpsTest(test.TestCase): args=[a], Tout=[dtypes.string], f=_remote_fn, target="/cpu:0") with self.cached_session() as sess: - ret = sess.run(remote_op) + ret = self.evaluate(remote_op) self.assertAllEqual(ret, [b"a"]) + @test_util.run_deprecated_v1 def testRemoteFunctionCrossProcess(self): workers, _ = test_util.create_local_cluster(2, 1) @@ -696,10 +718,11 @@ class FunctionalOpsTest(test.TestCase): target="/job:worker/replica:0/task:1/cpu:0")[0] + 3.0 with session.Session(workers[0].target) as sess: - sess.run(variables.global_variables_initializer()) - mul = sess.run(remote_op) + self.evaluate(variables.global_variables_initializer()) + mul = self.evaluate(remote_op) self.assertEqual(mul, 9) + @test_util.run_deprecated_v1 def testIf(self): @function.Defun(dtypes.float32) @@ -739,6 +762,7 @@ class FunctionalOpsTest(test.TestCase): self.assertAllEqual(Run(sess, 20.), 210.) self.assertAllEqual(Run(sess, 100.), 5050.) + @test_util.run_deprecated_v1 def testWhileLowering(self): def Run(n, fetch_by_name): @@ -766,13 +790,14 @@ class FunctionalOpsTest(test.TestCase): else: fetch = "my_while:1" with self.session(graph=g, use_gpu=use_gpu) as sess: - return sess.run(fetch) + return self.evaluate(fetch) self.assertAllEqual(Run(20., False), 210.) self.assertAllEqual(Run(20., True), 210.) self.assertAllEqual(Run(100., False), 5050.) self.assertAllEqual(Run(100., True), 5050.) + @test_util.run_deprecated_v1 def testWhileError(self): for use_gpu in (True, False): with ops.Graph().as_default() as g: @@ -854,11 +879,11 @@ class FunctionalOpsTest(test.TestCase): result_binary = functional_ops.While( [1.0, 0., 0.], function.Defun(*[dtypes.float32] * 3)(TestCond), TestBinary) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) assert len(result_unary) == 2 - self.assertEqual([10.0, 54.0], sess.run(result_unary)) + self.assertEqual([10.0, 54.0], self.evaluate(result_unary)) assert len(result_binary) == 3 - self.assertEqual([10.0, 54.0, 9.0], sess.run(result_binary)) + self.assertEqual([10.0, 54.0, 9.0], self.evaluate(result_binary)) def TestCondCapture(n, *args): del args @@ -889,7 +914,7 @@ class FunctionalOpsTest(test.TestCase): 100, 0, -1, [0.], Body, rewrite_with_while=rewrite_with_while) [0], ] - xvals = sess.run(xs) + xvals = self.evaluate(xs) self.assertAllEqual(210, xvals[0]) self.assertAllEqual(5050, xvals[1]) @@ -919,6 +944,7 @@ class FunctionalOpsTest(test.TestCase): self.assertTrue("TestBody_Cond" in names) self.assertTrue("TestBody_Body" in names) + @test_util.run_deprecated_v1 def testForCapturedInputs(self): v = variables.Variable(1.0) @@ -946,16 +972,16 @@ class FunctionalOpsTest(test.TestCase): result_binary = functional_ops.For( 1, 10, 1, [0., 0.], TestBinary, rewrite_with_while=rewrite_with_while) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) assert not result_nullary # The nullary variant doesn't return anything so we can't easily run it. # As a total hack, fetch the operation by name and run it. sess.run(ops.get_default_graph().get_operation_by_name( "While" if rewrite_with_while else "For")) assert len(result_unary) == 1 - self.assertEqual([54.0], sess.run(result_unary)) + self.assertEqual([54.0], self.evaluate(result_unary)) assert len(result_binary) == 2 - self.assertEqual([54.0, 9.0], sess.run(result_binary)) + self.assertEqual([54.0, 9.0], self.evaluate(result_binary)) def _tfMLP(self, xval, wsval, bsval, rewrite_with_while): # On GPU, don't rewrite using a while loop. @@ -974,7 +1000,7 @@ class FunctionalOpsTest(test.TestCase): MLP, rewrite_with_while=rewrite_with_while)[0] - return ret.eval() + return self.evaluate(ret) def _npMLP(self, xval, wsval, bsval): for i in range(wsval.shape[0]): @@ -993,12 +1019,15 @@ class FunctionalOpsTest(test.TestCase): tf_for_ans = self._tfMLP(xval, wsval, bsval, rewrite_with_while) self.assertAllClose(np_ans, tf_for_ans) + @test_util.run_deprecated_v1 def testForMLP(self): self._testForMLP(False) + @test_util.run_deprecated_v1 def testForMLPWhile(self): self._testForMLP(True) + @test_util.run_deprecated_v1 def testForError(self): @function.Defun(dtypes.int32, dtypes.float32) @@ -1021,6 +1050,7 @@ class FunctionalOpsTest(test.TestCase): "For loop body returned 2 arguments. Expected: 1"): functional_ops.For(0, 10, 1, [0.0], ReturnsTooManyArgs)[0].eval() + @test_util.run_deprecated_v1 def testGradient(self): @function.Defun(dtypes.float32) @@ -1038,14 +1068,15 @@ class FunctionalOpsTest(test.TestCase): avals = [Poly(a), Grad(a)] b = constant_op.constant(1.) bvals = [Poly(b), Grad(b)] - self.assertAllEqual(sess.run(avals), [8., 4.]) - self.assertAllEqual(sess.run(bvals), [17., 16.]) + self.assertAllEqual(self.evaluate(avals), [8., 4.]) + self.assertAllEqual(self.evaluate(bvals), [17., 16.]) # TODO(akshayka): Replace `function.Defun` with tf.contrib.eager.defun` in the # below test cases. class PartitionedCallTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasicSingleDevice(self): @function.Defun(*[dtypes.float32] * 2) @@ -1061,6 +1092,7 @@ class PartitionedCallTest(test.TestCase): constant_op.constant(2.)], f=Body)) self.assertEqual(output, 6.) + @test_util.run_deprecated_v1 def testBasicMultiDevice(self): config = config_pb2.ConfigProto(device_count={"CPU": 3}) @@ -1104,6 +1136,7 @@ class PartitionedCallTest(test.TestCase): constant_op.constant(2.)], f=Body)) self.assertEqual(output, 6.) + @test_util.run_deprecated_v1 def testBasicNoDeviceAnnotations(self): @function.Defun(*[dtypes.float32] * 2) @@ -1118,6 +1151,7 @@ class PartitionedCallTest(test.TestCase): constant_op.constant(2.)], f=Body)) self.assertEqual(output, 6.) + @test_util.run_deprecated_v1 def testShardsRunOnRequestedDevices(self): config = config_pb2.ConfigProto(device_count={"CPU": 4}) @@ -1147,6 +1181,7 @@ class PartitionedCallTest(test.TestCase): self.assertIn(compat.as_bytes("CPU:1"), outputs[1]) self.assertIn(compat.as_bytes("CPU:2"), outputs[2]) + @test_util.run_deprecated_v1 def testAssignAddResourceVariable(self): v = resource_variable_ops.ResourceVariable(1.0) @@ -1190,14 +1225,15 @@ class PartitionedCallTest(test.TestCase): allow_soft_placement=False, log_device_placement=True, device_count={"CPU": 2})) as sess: - sess.run(variables.global_variables_initializer()) - expected = sess.run(sum_gather()) + self.evaluate(variables.global_variables_initializer()) + expected = self.evaluate(sum_gather()) result = sess.run( functional_ops.partitioned_call( args=defined.captured_inputs, f=defined)) self.assertAllEqual(expected, result) # Use an invalid executor name to test the plumbing of the executor_type attr. + @test_util.run_deprecated_v1 def testExecutorTypeAttrExecutorNotFound(self): @function.Defun(dtypes.int32) def AddFive(x): diff --git a/tensorflow/python/kernel_tests/gather_nd_op_test.py b/tensorflow/python/kernel_tests/gather_nd_op_test.py index ee761435d8..320ffc9674 100644 --- a/tensorflow/python/kernel_tests/gather_nd_op_test.py +++ b/tensorflow/python/kernel_tests/gather_nd_op_test.py @@ -27,6 +27,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import variables @@ -40,7 +41,7 @@ class GatherNdTest(test.TestCase): params = constant_op.constant(np.array([8, 1, 2, 3, 7, 5], dtype=dtype)) indices = constant_op.constant([[4], [4], [0]]) gather_nd_t = array_ops.gather_nd(params, indices) - gather_nd_val = gather_nd_t.eval() + gather_nd_val = self.evaluate(gather_nd_t) self.assertAllEqual(np.array([7, 7, 8], dtype=dtype), gather_nd_val) self.assertEqual([3], gather_nd_t.get_shape()) @@ -54,26 +55,27 @@ class GatherNdTest(test.TestCase): self._testSimpleDtype(np.complex128) self._testSimpleDtype("|S") # byte strings in python2 + 3 + @test_util.run_deprecated_v1 def testEmptyIndicesAndParamsOKButJustEmptyParamsFails(self): with self.session(use_gpu=True): params = np.ones((3, 3), dtype=np.float32) indices_empty = np.empty((0, 2), dtype=np.int32) gather_nd_ok_t = array_ops.gather_nd(params, indices_empty) - gather_nd_ok_val = gather_nd_ok_t.eval() + gather_nd_ok_val = self.evaluate(gather_nd_ok_t) self.assertEqual([0], gather_nd_ok_t.get_shape()) self.assertAllClose(np.empty((0,), dtype=np.float32), gather_nd_ok_val) indices_empty = np.empty((0, 1), dtype=np.int32) gather_nd_ok_t = array_ops.gather_nd(params, indices_empty) - gather_nd_ok_val = gather_nd_ok_t.eval() + gather_nd_ok_val = self.evaluate(gather_nd_ok_t) self.assertEqual([0, 3], gather_nd_ok_t.get_shape()) self.assertAllClose(np.empty((0, 3), dtype=np.float32), gather_nd_ok_val) params_empty = np.empty((0, 3), dtype=np.float32) indices_empty = np.empty((0, 2), dtype=np.int32) gather_nd_ok_t = array_ops.gather_nd(params_empty, indices_empty) - gather_nd_ok_val = gather_nd_ok_t.eval() + gather_nd_ok_val = self.evaluate(gather_nd_ok_t) self.assertEqual([0], gather_nd_ok_t.get_shape()) self.assertAllClose(np.empty((0,), dtype=np.float32), gather_nd_ok_val) @@ -82,7 +84,7 @@ class GatherNdTest(test.TestCase): gather_nd_break_t = array_ops.gather_nd(params_empty, indices_nonempty) with self.assertRaisesOpError( r"Requested more than 0 entries, but params is empty."): - gather_nd_break_t.eval() + self.evaluate(gather_nd_break_t) self.assertAllClose(np.empty((0,), dtype=np.float32), gather_nd_ok_val) def testIndexScalar(self): @@ -91,7 +93,7 @@ class GatherNdTest(test.TestCase): [[-8, -1, -2, -3, -7, -5], [8, 1, 2, 3, 7, 5]], dtype=np.float32).T indices = constant_op.constant([4, 1]) gather_nd_t = array_ops.gather_nd(params, indices) - gather_nd_val = gather_nd_t.eval() + gather_nd_val = self.evaluate(gather_nd_t) self.assertEqual([], gather_nd_t.get_shape()) self.assertAllEqual(np.array(7), gather_nd_val) @@ -101,7 +103,7 @@ class GatherNdTest(test.TestCase): [[-8, -1, -2, -3, -7, -5], [8, 1, 2, 3, 7, 5]], dtype=np.float32).T indices = constant_op.constant([4]) gather_nd_t = array_ops.gather_nd(params, indices) - gather_nd_val = gather_nd_t.eval() + gather_nd_val = self.evaluate(gather_nd_t) self.assertEqual([2], gather_nd_t.get_shape()) self.assertAllEqual(np.array([-7, 7]), gather_nd_val) @@ -111,7 +113,7 @@ class GatherNdTest(test.TestCase): [[-8, -1, -2, -3, -7, -5], [8, 1, 2, 3, 7, 5]], dtype=np.float32).T indices = constant_op.constant([[4], [4], [0]]) gather_nd_t = array_ops.gather_nd(params, indices) - gather_nd_val = gather_nd_t.eval() + gather_nd_val = self.evaluate(gather_nd_t) self.assertEqual([3, 2], gather_nd_t.get_shape()) self.assertAllEqual(np.array([[-7, 7], [-7, 7], [-8, 8]]), gather_nd_val) @@ -125,7 +127,7 @@ class GatherNdTest(test.TestCase): params_t = constant_op.constant(params) indices = constant_op.constant([[4], [4], [0]]) gather_nd_t = array_ops.gather_nd(params_t, indices) - gather_nd_val = gather_nd_t.eval() + gather_nd_val = self.evaluate(gather_nd_t) self.assertEqual([3, 2, 2], gather_nd_t.get_shape()) self.assertAllEqual(params[[4, 4, 0]], gather_nd_val) @@ -140,7 +142,7 @@ class GatherNdTest(test.TestCase): indices = constant_op.constant( [[], []], dtype=dtypes.int32) # Size (2, 0) gather_nd_t = array_ops.gather_nd(params_t, indices) - gather_nd_val = gather_nd_t.eval() + gather_nd_val = self.evaluate(gather_nd_t) self.assertEqual([2, 6, 2, 2], gather_nd_t.get_shape()) self.assertAllEqual( @@ -156,7 +158,7 @@ class GatherNdTest(test.TestCase): params_t = constant_op.constant(params) indices = constant_op.constant([[[3], [2], [1]], [[4], [4], [0]]]) gather_nd_t = array_ops.gather_nd(params_t, indices) - gather_nd_val = gather_nd_t.eval() + gather_nd_val = self.evaluate(gather_nd_t) self.assertEqual([2, 3, 2, 2], gather_nd_t.get_shape()) self.assertAllEqual(params[[3, 2, 1, 4, 4, 0]].reshape(2, 3, 2, 2), @@ -168,7 +170,7 @@ class GatherNdTest(test.TestCase): params = np.random.rand(*shape) indices = np.vstack([np.random.randint(0, s, size=2000) for s in shape]).T gather_nd_t = array_ops.gather_nd(params, indices) - gather_nd_val = gather_nd_t.eval() + gather_nd_val = self.evaluate(gather_nd_t) expected = params[tuple(indices.T)] self.assertAllEqual(expected, gather_nd_val) @@ -181,7 +183,7 @@ class GatherNdTest(test.TestCase): indices = np.vstack([np.random.randint(0, s, size=2000) for s in shape]).T indices_reshaped = indices.reshape([10, 10, 20, 5]) gather_nd_t = array_ops.gather_nd(params, indices_reshaped) - gather_nd_val = gather_nd_t.eval() + gather_nd_val = self.evaluate(gather_nd_t) expected = params[tuple(indices.T)] self.assertAllEqual(expected.reshape([10, 10, 20]), gather_nd_val) @@ -190,6 +192,7 @@ class GatherNdTest(test.TestCase): def assertIndexedSlices(self, t): self.assertIsInstance(t, ops.IndexedSlices) + @test_util.run_deprecated_v1 def testUnknownIndices(self): params = constant_op.constant([[0, 1, 2]]) indices = array_ops.placeholder(dtypes.int32) @@ -198,6 +201,7 @@ class GatherNdTest(test.TestCase): self.assertEqual(None, shape.ndims) self.assertEqual(None, tensor_shape.dimension_value(shape[0])) + @test_util.run_deprecated_v1 def testBadIndicesCPU(self): with self.session(use_gpu=False): params = [0, 1, 2] @@ -205,7 +209,7 @@ class GatherNdTest(test.TestCase): gather_nd = array_ops.gather_nd(params, indices) with self.assertRaisesOpError( r"indices\[0,1\] = \[7\] does not index into param shape \[3\]"): - gather_nd.eval() + self.evaluate(gather_nd) def _disabledTestBadIndicesGPU(self): # TODO disabled due to different behavior on GPU and CPU @@ -218,8 +222,9 @@ class GatherNdTest(test.TestCase): gather_nd = array_ops.gather_nd(params, indices) with self.assertRaisesOpError( r"indices\[0,1\] = \[7\] does not index into param shape \[3\]"): - gather_nd.eval() + self.evaluate(gather_nd) + @test_util.run_deprecated_v1 def testBadIndicesWithSlicesCPU(self): with self.session(use_gpu=False): params = [[0, 1, 2]] @@ -227,7 +232,7 @@ class GatherNdTest(test.TestCase): gather_nd = array_ops.gather_nd(params, indices) with self.assertRaisesOpError( r"indices\[0,2\] = \[1\] does not index into param shape \[1,3\]"): - gather_nd.eval() + self.evaluate(gather_nd) def _disabledTestBadIndicesWithSlicesGPU(self): # TODO disabled due to different behavior on GPU and CPU @@ -240,8 +245,9 @@ class GatherNdTest(test.TestCase): gather_nd = array_ops.gather_nd(params, indices) with self.assertRaisesOpError( r"indices\[0,2\] = \[1\] does not index into param shape \[1,3\]"): - gather_nd.eval() + self.evaluate(gather_nd) + @test_util.run_deprecated_v1 def testGradientsRank2Elements(self): indices = constant_op.constant([[0, 0], [1, 1]], dtype=dtypes.int32) inputs = constant_op.constant([[1, 2], [3, 4]], dtype=dtypes.float64) @@ -251,8 +257,9 @@ class GatherNdTest(test.TestCase): grads = gradients_impl.gradients([outputs], [inputs], [grad_vals])[0] expected_grads = np.array([[1, 0], [0, 2]], dtype=np.float64) with self.session(use_gpu=True): - assert np.array_equal(expected_grads, grads.eval()) + assert np.array_equal(expected_grads, self.evaluate(grads)) + @test_util.run_deprecated_v1 def testGradientsRank2Slices(self): indices = constant_op.constant([[1], [0]], dtype=dtypes.int32) inputs = constant_op.constant([[1, 2], [3, 4]], dtype=dtypes.float64) @@ -265,6 +272,7 @@ class GatherNdTest(test.TestCase): self.assertIndexedSlices(grads) self.assertAllEqual(expected_grads, ops.convert_to_tensor(grads).eval()) + @test_util.run_deprecated_v1 def testGradientsRank3Elements(self): indices = constant_op.constant( [[[0, 1], [1, 0]], [[0, 0], [1, 1]]], dtype=dtypes.int32) @@ -278,8 +286,9 @@ class GatherNdTest(test.TestCase): expected_grads = np.array( [[[5, 6], [1, 2]], [[3, 4], [7, 8]]], dtype=np.float64) with self.session(use_gpu=True): - self.assertAllEqual(expected_grads, grads.eval()) + self.assertAllEqual(expected_grads, self.evaluate(grads)) + @test_util.run_deprecated_v1 def testGradientsRank7Elements(self): # Shape [1,1,2,1,1,2,2] indices = constant_op.constant( @@ -307,8 +316,9 @@ class GatherNdTest(test.TestCase): [[[[3, 4], [7, 8]]]] ]]], dtype=np.float64) with self.session(use_gpu=True): - self.assertAllEqual(expected_grads, grads.eval()) + self.assertAllEqual(expected_grads, self.evaluate(grads)) + @test_util.run_deprecated_v1 def testGradientsInt64Indices(self): indices = constant_op.constant( [[[0, 1], [1, 0]], [[0, 0], [1, 1]]], dtype=dtypes.int64) @@ -322,8 +332,9 @@ class GatherNdTest(test.TestCase): expected_grads = np.array( [[[5, 6], [1, 2]], [[3, 4], [7, 8]]], dtype=np.float64) with self.session(use_gpu=True): - self.assertAllEqual(expected_grads, grads.eval()) + self.assertAllEqual(expected_grads, self.evaluate(grads)) + @test_util.run_deprecated_v1 def testGradientsRank2SlicesWithEmptySpace(self): indices = constant_op.constant([[2], [0], [5]], dtype=dtypes.int32) inputs = constant_op.constant( @@ -361,10 +372,10 @@ class GatherNdOpBenchmark(test.Benchmark): gather_op = array_ops.gather_nd(t_params, t_indices) variables.global_variables_initializer().run() for _ in range(10): - gather_op.eval() + self.evaluate(gather_op) t1 = time.time() for _ in range(1000): - gather_op.eval() + self.evaluate(gather_op) t2 = time.time() self.report_benchmark(iters=1000, wall_time=(t2 - t1) / 1000.0) diff --git a/tensorflow/python/kernel_tests/gather_op_test.py b/tensorflow/python/kernel_tests/gather_op_test.py index bdafc52ab5..fc86068c3f 100644 --- a/tensorflow/python/kernel_tests/gather_op_test.py +++ b/tensorflow/python/kernel_tests/gather_op_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.platform import test @@ -50,7 +51,7 @@ class GatherTest(test.TestCase): params = constant_op.constant(params_np) indices_tf = constant_op.constant(indices) gather_t = array_ops.gather(params, indices_tf) - gather_val = gather_t.eval() + gather_val = self.evaluate(gather_t) np_val = params_np[indices] self.assertAllEqual(np_val, gather_val) self.assertEqual(np_val.shape, gather_t.get_shape()) @@ -65,7 +66,7 @@ class GatherTest(test.TestCase): params = constant_op.constant(params_np) indices = constant_op.constant(2) gather_t = array_ops.gather(params, indices, axis=axis) - gather_val = gather_t.eval() + gather_val = self.evaluate(gather_t) self.assertAllEqual(np.take(params_np, 2, axis=axis), gather_val) expected_shape = data.shape[:axis] + data.shape[axis + 1:] self.assertEqual(expected_shape, gather_t.get_shape()) @@ -81,12 +82,13 @@ class GatherTest(test.TestCase): # The indices must be in bounds for any axis. indices = constant_op.constant([0, 1, 0, 2]) gather_t = array_ops.gather(params, indices, axis=axis) - gather_val = gather_t.eval() + gather_val = self.evaluate(gather_t) self.assertAllEqual(np.take(params_np, [0, 1, 0, 2], axis=axis), gather_val) expected_shape = data.shape[:axis] + (4,) + data.shape[axis + 1:] self.assertEqual(expected_shape, gather_t.get_shape()) + @test_util.run_deprecated_v1 def testHigherRank(self): # We check that scalar and empty indices shapes work as well shape = (2, 1, 3, 2) @@ -142,9 +144,13 @@ class GatherTest(test.TestCase): source_slice = ((slice(None),) * outer_dims + (source_index,) + (slice(None),) * inner_dims) correct_params_grad[dest_slice] += gather_grad[source_slice] - self.assertAllClose(correct_params_grad, params_grad.eval(), - atol=2e-6, rtol=2e-6) + self.assertAllClose( + correct_params_grad, + self.evaluate(params_grad), + atol=2e-6, + rtol=2e-6) + @test_util.run_deprecated_v1 def testString(self): params = np.array([[b"asdf", b"zxcv"], [b"qwer", b"uiop"]]) with self.cached_session(): @@ -153,6 +159,7 @@ class GatherTest(test.TestCase): self.assertAllEqual([b"asdf", b"qwer"], array_ops.gather(params, 0, axis=1).eval()) + @test_util.run_deprecated_v1 def testUInt32AndUInt64(self): for unsigned_type in (dtypes.uint32, dtypes.uint64): params = self._buildParams( @@ -162,12 +169,14 @@ class GatherTest(test.TestCase): array_ops.gather(params, 1, axis=0).eval()) self.assertAllEqual([1, 7], array_ops.gather(params, 0, axis=1).eval()) + @test_util.run_deprecated_v1 def testUnknownIndices(self): params = constant_op.constant([[0, 1, 2]]) indices = array_ops.placeholder(dtypes.int32) gather_t = array_ops.gather(params, indices) self.assertEqual(None, gather_t.get_shape()) + @test_util.run_deprecated_v1 def testUnknownAxis(self): params = constant_op.constant([[0, 1, 2]]) indices = constant_op.constant([[0, 0], [0, 0]]) @@ -201,6 +210,7 @@ class GatherTest(test.TestCase): with self.assertRaisesOpError(r"indices\[0,0\] = 7 is not in \[0, 3\)"): array_ops.gather(params, [[7]], axis=1).eval() + @test_util.run_deprecated_v1 def testBadAxis(self): with self.session(use_gpu=True): params = [0, 1, 2] @@ -217,6 +227,7 @@ class GatherTest(test.TestCase): array_ops.gather(params_ph, indices, axis=bad_axis).eval( feed_dict={params_ph: params}) + @test_util.run_deprecated_v1 def testEmptySlices(self): with self.session(use_gpu=True): for dtype in _TEST_TYPES: diff --git a/tensorflow/python/kernel_tests/gradient_correctness_test.py b/tensorflow/python/kernel_tests/gradient_correctness_test.py index 291a69ebac..0148de5047 100644 --- a/tensorflow/python/kernel_tests/gradient_correctness_test.py +++ b/tensorflow/python/kernel_tests/gradient_correctness_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -29,37 +30,42 @@ from tensorflow.python.platform import test class GradientCorrectnessTest(test.TestCase): + @test_util.run_deprecated_v1 def testMultipleOutputChainedGradients(self): with self.cached_session() as sess: x = constant_op.constant(1.0, dtype=dtypes.float32) yexp = math_ops.exp(x) yexplog = math_ops.log(yexp) grads = gradients_impl.gradients([yexp, yexplog], [x]) - grad_vals = sess.run(grads) + grad_vals = self.evaluate(grads) exp1_plus_one = (1.0 + np.exp(1.0)).astype(np.float32) # [dexp(x)/dx + d(log(exp(x)))/dx] @ x=1 == exp(1) + 1 self.assertAllClose(grad_vals[0], exp1_plus_one) + @test_util.run_deprecated_v1 def testIdentityGradient(self): x = constant_op.constant(3.) dx_dx, = gradients_impl.gradients(x, x) with self.cached_session() as sess: - self.assertAllClose(1., sess.run(dx_dx)) + self.assertAllClose(1., self.evaluate(dx_dx)) + @test_util.run_deprecated_v1 def testIntegerIdentityGradient(self): x = constant_op.constant(3) dx_dx, = gradients_impl.gradients(x, x) with self.cached_session() as sess: - self.assertAllClose(1, sess.run(dx_dx)) + self.assertAllClose(1, self.evaluate(dx_dx)) + @test_util.run_deprecated_v1 def testGradientWithIntegerPath(self): x = constant_op.constant([3.9, 4.1]) k = math_ops.to_float(math_ops.to_int32(x)) y = x * k dy_dx, = gradients_impl.gradients(y, x) with self.cached_session() as sess: - self.assertAllClose([3., 4.], sess.run(dy_dx)) + self.assertAllClose([3., 4.], self.evaluate(dy_dx)) + @test_util.run_deprecated_v1 def testNoIntegerGradient1(self): x = constant_op.constant([3.9, 4.1]) k = math_ops.to_float(math_ops.to_int32(x)) @@ -67,6 +73,7 @@ class GradientCorrectnessTest(test.TestCase): dy_dx, = gradients_impl.gradients(y, x) self.assertIsNone(dy_dx) + @test_util.run_deprecated_v1 def testNoIntegerGradient2(self): k = constant_op.constant([3, 4]) x = math_ops.to_float(k) @@ -74,18 +81,21 @@ class GradientCorrectnessTest(test.TestCase): dy_dk, = gradients_impl.gradients(y, k) self.assertIsNone(dy_dk) + @test_util.run_deprecated_v1 def testNoIntegerGradient3(self): k = constant_op.constant([3, 4]) m = k * k dm_dk, = gradients_impl.gradients(m, k) self.assertIsNone(dm_dk) + @test_util.run_deprecated_v1 def testNoIntegerGradient4(self): k = constant_op.constant([3, 4]) m = k * k * k dm_dk, = gradients_impl.gradients(m, k) self.assertIsNone(dm_dk) + @test_util.run_deprecated_v1 def testNoIntegerGradient5(self): k = constant_op.constant([3, 4]) m = k * k @@ -93,6 +103,7 @@ class GradientCorrectnessTest(test.TestCase): dn_dk, = gradients_impl.gradients(n, k) self.assertIsNone(dn_dk) + @test_util.run_deprecated_v1 def testNoIntegerGradient6(self): k = constant_op.constant(3) x = math_ops.to_float(k) diff --git a/tensorflow/python/kernel_tests/huge_slice_op_test.py b/tensorflow/python/kernel_tests/huge_slice_op_test.py index 8646d74c96..4074946350 100644 --- a/tensorflow/python/kernel_tests/huge_slice_op_test.py +++ b/tensorflow/python/kernel_tests/huge_slice_op_test.py @@ -33,11 +33,11 @@ class SliceTest(test.TestCase): a_large = array_ops.tile( constant_op.constant(np.array([False, True] * 4)), [2**29 + 3]) slice_t = array_ops.slice(a_large, np.asarray([3]).astype(np.int64), [3]) - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual([True, False, True], slice_val) slice_t = array_ops.slice( a_large, constant_op.constant([long(2)**32 + 3], dtype=dtypes.int64), [3]) - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual([True, False, True], slice_val) diff --git a/tensorflow/python/kernel_tests/identity_n_op_py_test.py b/tensorflow/python/kernel_tests/identity_n_op_py_test.py index 518733cd8e..a1110d640f 100644 --- a/tensorflow/python/kernel_tests/identity_n_op_py_test.py +++ b/tensorflow/python/kernel_tests/identity_n_op_py_test.py @@ -21,12 +21,14 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test class IdentityNOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testInt32String_6(self): with self.cached_session() as sess: [value0, value1] = sess.run( @@ -36,6 +38,7 @@ class IdentityNOpTest(test.TestCase): self.assertAllEqual( np.array([b"a", b"b", b"C", b"d", b"E", b"f", b"g"]), value1) + @test_util.run_deprecated_v1 def testInt32_shapes(self): with self.cached_session() as sess: inp0 = constant_op.constant([10, 20, 30, 40, 50, 60], shape=[2, 3]) @@ -50,6 +53,7 @@ class IdentityNOpTest(test.TestCase): np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]), value2) + @test_util.run_deprecated_v1 def testString(self): source = [b"A", b"b", b"C", b"d", b"E", b"f"] with self.cached_session() as sess: diff --git a/tensorflow/python/kernel_tests/identity_op_py_test.py b/tensorflow/python/kernel_tests/identity_op_py_test.py index 88ea10c22a..1a6794e896 100644 --- a/tensorflow/python/kernel_tests/identity_op_py_test.py +++ b/tensorflow/python/kernel_tests/identity_op_py_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_array_ops from tensorflow.python.ops import variables @@ -30,17 +31,20 @@ from tensorflow.python.platform import test class IdentityOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testInt32_6(self): with self.cached_session(): value = array_ops.identity([1, 2, 3, 4, 5, 6]).eval() self.assertAllEqual(np.array([1, 2, 3, 4, 5, 6]), value) + @test_util.run_deprecated_v1 def testInt32_2_3(self): with self.cached_session(): inp = constant_op.constant([10, 20, 30, 40, 50, 60], shape=[2, 3]) value = array_ops.identity(inp).eval() self.assertAllEqual(np.array([[10, 20, 30], [40, 50, 60]]), value) + @test_util.run_deprecated_v1 def testString(self): source = [b"A", b"b", b"C", b"d", b"E", b"f"] with self.cached_session(): @@ -58,6 +62,7 @@ class IdentityOpTest(test.TestCase): self.assertEquals(shape, array_ops.identity(np.array(array_2x3)).get_shape()) + @test_util.run_deprecated_v1 def testRefIdentityShape(self): with self.cached_session(): shape = [2, 3] diff --git a/tensorflow/python/kernel_tests/in_topk_op_test.py b/tensorflow/python/kernel_tests/in_topk_op_test.py index 6fdb497bc6..507822b314 100644 --- a/tensorflow/python/kernel_tests/in_topk_op_test.py +++ b/tensorflow/python/kernel_tests/in_topk_op_test.py @@ -32,7 +32,7 @@ class InTopKTest(test.TestCase): np_ans = np.array(expected) with self.cached_session(): precision = nn_ops.in_top_k(predictions, target, k) - out = precision.eval() + out = self.evaluate(precision) self.assertAllClose(np_ans, out) self.assertShapeEqual(np_ans, precision) @@ -77,7 +77,7 @@ class InTopKTest(test.TestCase): np_ans = np.array([False, True]) with self.cached_session(): precision = nn_ops.in_top_k(predictions, target, k) - out = precision.eval() + out = self.evaluate(precision) self.assertAllClose(np_ans, out) self.assertShapeEqual(np_ans, precision) diff --git a/tensorflow/python/kernel_tests/init_ops_test.py b/tensorflow/python/kernel_tests/init_ops_test.py index 70bfbf8544..09b9944baa 100644 --- a/tensorflow/python/kernel_tests/init_ops_test.py +++ b/tensorflow/python/kernel_tests/init_ops_test.py @@ -25,6 +25,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util from tensorflow.python.layers import convolutional from tensorflow.python.ops import array_ops from tensorflow.python.ops import init_ops @@ -106,6 +107,7 @@ def _init_sampler(tc, init, num): class ConstantInitializersTest(test.TestCase): + @test_util.run_deprecated_v1 def testZerosInitializer(self): with self.session(use_gpu=True): shape = [2, 3] @@ -114,6 +116,7 @@ class ConstantInitializersTest(test.TestCase): x.initializer.run() self.assertAllEqual(x.eval(), np.zeros(shape)) + @test_util.run_deprecated_v1 def testOnesInitializer(self): with self.session(use_gpu=True): shape = [2, 3] @@ -122,6 +125,7 @@ class ConstantInitializersTest(test.TestCase): x.initializer.run() self.assertAllEqual(x.eval(), np.ones(shape)) + @test_util.run_deprecated_v1 def testConstantZeroInitializer(self): with self.session(use_gpu=True): shape = [2, 3] @@ -130,6 +134,7 @@ class ConstantInitializersTest(test.TestCase): x.initializer.run() self.assertAllEqual(x.eval(), np.zeros(shape)) + @test_util.run_deprecated_v1 def testConstantOneInitializer(self): with self.session(use_gpu=True): shape = [2, 3] @@ -138,6 +143,7 @@ class ConstantInitializersTest(test.TestCase): x.initializer.run() self.assertAllEqual(x.eval(), np.ones(shape)) + @test_util.run_deprecated_v1 def testConstantIntInitializer(self): with self.session(use_gpu=True): shape = [2, 3] @@ -150,6 +156,7 @@ class ConstantInitializersTest(test.TestCase): self.assertEqual(x.dtype.base_dtype, dtypes.int32) self.assertAllEqual(x.eval(), 7 * np.ones(shape, dtype=np.int32)) + @test_util.run_deprecated_v1 def testConstantTupleInitializer(self): with self.session(use_gpu=True): shape = [3] @@ -173,6 +180,7 @@ class ConstantInitializersTest(test.TestCase): for a, e in zip(actual, expected): self.assertEqual(a, e) + @test_util.run_deprecated_v1 def testNDimConstantInitializer(self): value = [0, 1, 2, 3, 4, 5] shape = [2, 3] @@ -199,6 +207,7 @@ class ConstantInitializersTest(test.TestCase): e = expected[i] if i < len(expected) else expected[-1] self.assertEqual(a, e) + @test_util.run_deprecated_v1 def testNDimConstantInitializerLessValues(self): value = [0, 1, 2, 3, 4, 5] shape = [2, 4] @@ -222,6 +231,7 @@ class ConstantInitializersTest(test.TestCase): shape=shape, initializer=init) + @test_util.run_deprecated_v1 def testNDimConstantInitializerMoreValues(self): value = [0, 1, 2, 3, 4, 5, 6, 7] shape = [2, 3] @@ -243,18 +253,21 @@ class ConstantInitializersTest(test.TestCase): class RandomNormalInitializationTest(test.TestCase): + @test_util.run_deprecated_v1 def testInitializerIdentical(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.random_normal_initializer(0.0, 1.0, seed=1, dtype=dtype) init2 = init_ops.random_normal_initializer(0.0, 1.0, seed=1, dtype=dtype) self.assertTrue(identicaltest(self, init1, init2)) + @test_util.run_deprecated_v1 def testInitializerDifferent(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.random_normal_initializer(0.0, 1.0, seed=1, dtype=dtype) init2 = init_ops.random_normal_initializer(0.0, 1.0, seed=2, dtype=dtype) self.assertFalse(identicaltest(self, init1, init2)) + @test_util.run_deprecated_v1 def testDuplicatedInitializer(self): init = init_ops.random_normal_initializer(0.0, 1.0) self.assertFalse(duplicated_initializer(self, init, 1)) @@ -270,6 +283,7 @@ class RandomNormalInitializationTest(test.TestCase): class TruncatedNormalInitializationTest(test.TestCase): + @test_util.run_deprecated_v1 def testInitializerIdentical(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.truncated_normal_initializer( @@ -278,6 +292,7 @@ class TruncatedNormalInitializationTest(test.TestCase): 0.0, 1.0, seed=1, dtype=dtype) self.assertTrue(identicaltest(self, init1, init2)) + @test_util.run_deprecated_v1 def testInitializerDifferent(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.truncated_normal_initializer( @@ -286,6 +301,7 @@ class TruncatedNormalInitializationTest(test.TestCase): 0.0, 1.0, seed=2, dtype=dtype) self.assertFalse(identicaltest(self, init1, init2)) + @test_util.run_deprecated_v1 def testDuplicatedInitializer(self): init = init_ops.truncated_normal_initializer(0.0, 1.0) self.assertFalse(duplicated_initializer(self, init, 1)) @@ -301,18 +317,21 @@ class TruncatedNormalInitializationTest(test.TestCase): class RandomUniformInitializationTest(test.TestCase): + @test_util.run_deprecated_v1 def testInitializerIdentical(self): for dtype in [dtypes.float32, dtypes.float64, dtypes.int64]: init1 = init_ops.random_uniform_initializer(0, 7, seed=1, dtype=dtype) init2 = init_ops.random_uniform_initializer(0, 7, seed=1, dtype=dtype) self.assertTrue(identicaltest(self, init1, init2)) + @test_util.run_deprecated_v1 def testInitializerDifferent(self): for dtype in [dtypes.float32, dtypes.float64, dtypes.int32, dtypes.int64]: init1 = init_ops.random_uniform_initializer(0, 7, seed=1, dtype=dtype) init2 = init_ops.random_uniform_initializer(0, 7, seed=2, dtype=dtype) self.assertFalse(identicaltest(self, init1, init2)) + @test_util.run_deprecated_v1 def testDuplicatedInitializer(self): init = init_ops.random_uniform_initializer(0.0, 1.0) self.assertFalse(duplicated_initializer(self, init, 1)) @@ -320,6 +339,7 @@ class RandomUniformInitializationTest(test.TestCase): class UniformUnitScalingInitializationTest(test.TestCase): + @test_util.run_deprecated_v1 def testInitializerIdentical(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.uniform_unit_scaling_initializer(seed=1, dtype=dtype) @@ -331,6 +351,7 @@ class UniformUnitScalingInitializationTest(test.TestCase): 1.5, seed=1, dtype=dtype) self.assertTrue(identicaltest(self, init3, init4)) + @test_util.run_deprecated_v1 def testInitializerDifferent(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.uniform_unit_scaling_initializer(seed=1, dtype=dtype) @@ -341,6 +362,7 @@ class UniformUnitScalingInitializationTest(test.TestCase): self.assertFalse(identicaltest(self, init1, init3)) self.assertFalse(identicaltest(self, init2, init3)) + @test_util.run_deprecated_v1 def testZeroSize(self): shape = [0, 2] with self.cached_session(): @@ -349,8 +371,9 @@ class UniformUnitScalingInitializationTest(test.TestCase): shape=shape, initializer=init_ops.uniform_unit_scaling_initializer()) variables.global_variables_initializer().run() - self.assertAllEqual(shape, x.eval().shape) + self.assertAllEqual(shape, self.evaluate(x).shape) + @test_util.run_deprecated_v1 def testDuplicatedInitializer(self): init = init_ops.uniform_unit_scaling_initializer() self.assertFalse(duplicated_initializer(self, init, 1)) @@ -364,6 +387,7 @@ class UniformUnitScalingInitializationTest(test.TestCase): class VarianceScalingInitializationTest(test.TestCase): + @test_util.run_deprecated_v1 def testTruncatedNormalDistribution(self): shape = [100, 100] expect_mean = 0. @@ -381,6 +405,7 @@ class VarianceScalingInitializationTest(test.TestCase): self.assertNear(np.mean(x), expect_mean, err=1e-2) self.assertNear(np.var(x), expect_var, err=1e-2) + @test_util.run_deprecated_v1 def testNormalDistribution(self): shape = [100, 100] expect_mean = 0. @@ -397,6 +422,7 @@ class VarianceScalingInitializationTest(test.TestCase): self.assertNear(np.mean(x), expect_mean, err=1e-2) self.assertNear(np.var(x), expect_var, err=1e-2) + @test_util.run_deprecated_v1 def testUntruncatedNormalDistribution(self): shape = [100, 100] expect_mean = 0. @@ -414,6 +440,7 @@ class VarianceScalingInitializationTest(test.TestCase): self.assertNear(np.mean(x), expect_mean, err=1e-2) self.assertNear(np.var(x), expect_var, err=1e-2) + @test_util.run_deprecated_v1 def testUniformDistribution(self): shape = [100, 100] expect_mean = 0. @@ -435,7 +462,7 @@ class RangeTest(test.TestCase): tf_ans = math_ops.range(start, limit, delta, name="range") self.assertEqual([len(np.arange(start, limit, delta))], tf_ans.get_shape()) - return tf_ans.eval() + return self.evaluate(tf_ans) def testBasic(self): self.assertTrue( @@ -449,6 +476,7 @@ class RangeTest(test.TestCase): self._Range(100, 500, 100), np.array([100, 200, 300, 400]))) self.assertEqual(math_ops.range(0, 5, 1).dtype, dtypes.int32) + @test_util.run_deprecated_v1 def testLimitOnly(self): with self.session(use_gpu=True): self.assertAllEqual(np.arange(5), math_ops.range(5).eval()) @@ -524,7 +552,7 @@ class LinSpaceTest(test.TestCase): with self.session(graph=graph, force_gpu=self.force_gpu): tf_ans = math_ops.linspace(start, stop, num, name="linspace") self.assertEqual([num], tf_ans.get_shape()) - return tf_ans.eval() + return self.evaluate(tf_ans) def testPositive(self): for self.force_gpu in self._gpu_modes(): @@ -583,18 +611,21 @@ class DeviceTest(test.TestCase): class OrthogonalInitializerTest(test.TestCase): + @test_util.run_deprecated_v1 def testInitializerIdentical(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.orthogonal_initializer(seed=1, dtype=dtype) init2 = init_ops.orthogonal_initializer(seed=1, dtype=dtype) self.assertTrue(identicaltest(self, init1, init2, (10, 10))) + @test_util.run_deprecated_v1 def testInitializerDifferent(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.orthogonal_initializer(seed=1, dtype=dtype) init2 = init_ops.orthogonal_initializer(seed=2, dtype=dtype) self.assertFalse(identicaltest(self, init1, init2, (10, 10))) + @test_util.run_deprecated_v1 def testDuplicatedInitializer(self): init = init_ops.orthogonal_initializer() self.assertFalse(duplicated_initializer(self, init, 1, (10, 10))) @@ -608,6 +639,7 @@ class OrthogonalInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): self.assertRaises(ValueError, init1, shape=[5]) + @test_util.run_deprecated_v1 def testGain(self): shape = (10, 10) for dtype in [dtypes.float32, dtypes.float64]: @@ -616,8 +648,9 @@ class OrthogonalInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): t1 = init1(shape).eval() t2 = init2(shape).eval() - return np.allclose(t1, t2 / 3.14, rtol=1e-15, atol=1e-15) + self.assertAllClose(t1, t2 / 3.14) + @test_util.run_deprecated_v1 def testShapesValues(self): for dtype in [dtypes.float32, dtypes.float64]: for shape in [(10, 10), (10, 9, 8), (100, 5, 5), (50, 40), (40, 50)]: @@ -639,18 +672,21 @@ class OrthogonalInitializerTest(test.TestCase): class ConvolutionDeltaOrthogonalInitializerTest(test.TestCase): + @test_util.run_deprecated_v1 def testInitializerIdentical(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.convolutional_delta_orthogonal(seed=1, dtype=dtype) init2 = init_ops.convolutional_delta_orthogonal(seed=1, dtype=dtype) self.assertTrue(identicaltest(self, init1, init2, (3, 3, 10, 10))) + @test_util.run_deprecated_v1 def testInitializerDifferent(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.convolutional_delta_orthogonal(seed=1, dtype=dtype) init2 = init_ops.convolutional_delta_orthogonal(seed=2, dtype=dtype) self.assertFalse(identicaltest(self, init1, init2, (3, 3, 10, 10))) + @test_util.run_deprecated_v1 def testDuplicatedInitializer(self): init = init_ops.convolutional_delta_orthogonal() self.assertFalse(duplicated_initializer(self, init, 1, (3, 3, 10, 10))) @@ -665,6 +701,7 @@ class ConvolutionDeltaOrthogonalInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): self.assertRaises(ValueError, init1, shape=[3, 3, 6, 5]) + @test_util.run_deprecated_v1 def testGain(self): shape = (3, 3, 10, 10) for dtype in [dtypes.float32, dtypes.float64]: @@ -674,8 +711,9 @@ class ConvolutionDeltaOrthogonalInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): t1 = init1(shape).eval() t2 = init2(shape).eval() - return np.allclose(t1, t2 / 3.14, rtol=1e-15, atol=1e-15) + self.assertAllClose(t1, t2 / 3.14) + @test_util.run_deprecated_v1 def testShapesValues(self): gain = 3.14 for dtype in [dtypes.float32]: @@ -704,14 +742,14 @@ class ConvolutionDeltaOrthogonalInitializerTest(test.TestCase): ratio = outputs_2norm / inputs_2norm my_ops = variables.global_variables_initializer() with self.session(use_gpu=True) as sess: - sess.run(my_ops) + self.evaluate(my_ops) # Check the shape of the outputs - t = outputs.eval() + t = self.evaluate(outputs) self.assertAllEqual(t.shape, outputs_shape) # Check isometry of the delta-orthogonal kernel. - self.assertAllClose(sess.run(ratio), np.sqrt(gain), - rtol=tol, atol=tol) + self.assertAllClose(self.evaluate(ratio), gain, rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testNonuniformity(self): value = 0 abs_value = 0 @@ -724,7 +762,7 @@ class ConvolutionDeltaOrthogonalInitializerTest(test.TestCase): initializer= init_ops.convolutional_delta_orthogonal) x.initializer.run() - y = x.eval()[1, 1, :, :] + y = self.evaluate(x)[1, 1, :, :] determinant = np.linalg.det(y) value += determinant abs_value += np.abs(determinant) @@ -739,18 +777,21 @@ class ConvolutionDeltaOrthogonalInitializerTest(test.TestCase): class ConvolutionOrthogonal1dInitializerTest(test.TestCase): + @test_util.run_deprecated_v1 def testInitializerIdentical(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.convolutional_orthogonal_1d(seed=1, dtype=dtype) init2 = init_ops.convolutional_orthogonal_1d(seed=1, dtype=dtype) self.assertTrue(identicaltest(self, init1, init2, (3, 10, 10))) + @test_util.run_deprecated_v1 def testInitializerDifferent(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.convolutional_orthogonal_1d(seed=1, dtype=dtype) init2 = init_ops.convolutional_orthogonal_1d(seed=2, dtype=dtype) self.assertFalse(identicaltest(self, init1, init2, (3, 10, 10))) + @test_util.run_deprecated_v1 def testDuplicatedInitializer(self): init = init_ops.convolutional_orthogonal_1d() self.assertFalse(duplicated_initializer(self, init, 1, (3, 10, 10))) @@ -765,6 +806,7 @@ class ConvolutionOrthogonal1dInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): self.assertRaises(ValueError, init1, shape=[3, 6, 5]) + @test_util.run_deprecated_v1 def testGain(self): shape = (3, 10, 10) for dtype in [dtypes.float32, dtypes.float64]: @@ -774,8 +816,9 @@ class ConvolutionOrthogonal1dInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): t1 = init1(shape).eval() t2 = init2(shape).eval() - return np.allclose(t1, t2 / 3.14, rtol=1e-15, atol=1e-15) + self.assertAllClose(t1, t2 / 3.14) + @test_util.run_deprecated_v1 def testNonuniformity(self): value = 0 abs_value = 0 @@ -800,6 +843,7 @@ class ConvolutionOrthogonal1dInitializerTest(test.TestCase): # Compute the sum of the absolute values of 'count' determinants self.assertAllClose(abs_value, count, rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testShapesValues(self): def circular_pad(input_, width, kernel_size): """Pad input_ for computing (circular) convolution. @@ -843,28 +887,31 @@ class ConvolutionOrthogonal1dInitializerTest(test.TestCase): ratio = outputs_2norm / inputs_2norm my_ops = variables.global_variables_initializer() with self.session(use_gpu=True) as sess: - sess.run(my_ops) + self.evaluate(my_ops) # Check the shape of the outputs - t = outputs.eval() + t = self.evaluate(outputs) self.assertAllEqual(t.shape, outputs_shape) # Check isometry of the orthogonal kernel. - self.assertAllClose(sess.run(ratio), np.sqrt(gain), rtol=tol, atol=tol) + self.assertAllClose(self.evaluate(ratio), gain, rtol=tol, atol=tol) class ConvolutionOrthogonal2dInitializerTest(test.TestCase): + @test_util.run_deprecated_v1 def testInitializerIdentical(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.convolutional_orthogonal_2d(seed=1, dtype=dtype) init2 = init_ops.convolutional_orthogonal_2d(seed=1, dtype=dtype) self.assertTrue(identicaltest(self, init1, init2, (3, 3, 10, 10))) + @test_util.run_deprecated_v1 def testInitializerDifferent(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.convolutional_orthogonal_2d(seed=1, dtype=dtype) init2 = init_ops.convolutional_orthogonal_2d(seed=2, dtype=dtype) self.assertFalse(identicaltest(self, init1, init2, (3, 3, 10, 10))) + @test_util.run_deprecated_v1 def testDuplicatedInitializer(self): init = init_ops.convolutional_orthogonal_2d() self.assertFalse(duplicated_initializer(self, init, 1, (3, 3, 10, 10))) @@ -879,6 +926,7 @@ class ConvolutionOrthogonal2dInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): self.assertRaises(ValueError, init1, shape=[3, 3, 6, 5]) + @test_util.run_deprecated_v1 def testGain(self): shape = (3, 3, 10, 10) for dtype in [dtypes.float32, dtypes.float64]: @@ -888,8 +936,9 @@ class ConvolutionOrthogonal2dInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): t1 = init1(shape).eval() t2 = init2(shape).eval() - return np.allclose(t1, t2 / 3.14, rtol=1e-15, atol=1e-15) + self.assertAllClose(t1, t2 / 3.14) + @test_util.run_deprecated_v1 def testShapesValues(self): def circular_pad(input_, width, kernel_size): """Pad input_ for computing (circular) convolution. @@ -938,28 +987,31 @@ class ConvolutionOrthogonal2dInitializerTest(test.TestCase): ratio = outputs_2norm / inputs_2norm my_ops = variables.global_variables_initializer() with self.session(use_gpu=True) as sess: - sess.run(my_ops) + self.evaluate(my_ops) # Check the shape of the outputs - t = outputs.eval() + t = self.evaluate(outputs) self.assertAllEqual(t.shape, outputs_shape) # Check isometry of the orthogonal kernel. - self.assertAllClose(sess.run(ratio), np.sqrt(gain), rtol=tol, atol=tol) + self.assertAllClose(self.evaluate(ratio), gain, rtol=tol, atol=tol) class ConvolutionOrthogonal3dInitializerTest(test.TestCase): + @test_util.run_deprecated_v1 def testInitializerIdentical(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.convolutional_orthogonal_3d(seed=1, dtype=dtype) init2 = init_ops.convolutional_orthogonal_3d(seed=1, dtype=dtype) self.assertTrue(identicaltest(self, init1, init2, (3, 3, 3, 10, 10))) + @test_util.run_deprecated_v1 def testInitializerDifferent(self): for dtype in [dtypes.float32, dtypes.float64]: init1 = init_ops.convolutional_orthogonal_3d(seed=1, dtype=dtype) init2 = init_ops.convolutional_orthogonal_3d(seed=2, dtype=dtype) self.assertFalse(identicaltest(self, init1, init2, (3, 3, 3, 10, 10))) + @test_util.run_deprecated_v1 def testDuplicatedInitializer(self): init = init_ops.convolutional_orthogonal_3d() self.assertFalse(duplicated_initializer(self, init, 1, (3, 3, 3, 10, 10))) @@ -974,6 +1026,7 @@ class ConvolutionOrthogonal3dInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): self.assertRaises(ValueError, init1, shape=[3, 3, 3, 6, 5]) + @test_util.run_deprecated_v1 def testGain(self): shape = (3, 3, 3, 10, 10) for dtype in [dtypes.float32, dtypes.float64]: @@ -983,8 +1036,9 @@ class ConvolutionOrthogonal3dInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): t1 = init1(shape).eval() t2 = init2(shape).eval() - return np.allclose(t1, t2 / 3.14, rtol=1e-15, atol=1e-15) + self.assertAllClose(t1, t2 / 3.14) + @test_util.run_deprecated_v1 def testNonuniformity(self): value = 0 abs_value = 0 @@ -1009,6 +1063,7 @@ class ConvolutionOrthogonal3dInitializerTest(test.TestCase): # Compute the sum of the absolute values of 'count' determinants self.assertAllClose(abs_value, count, rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testShapesValues(self): def circular_pad(input_, width, kernel_size): """Padding input_ for computing circular convolution. @@ -1063,12 +1118,12 @@ class ConvolutionOrthogonal3dInitializerTest(test.TestCase): ratio = outputs_2norm / inputs_2norm my_ops = variables.global_variables_initializer() with self.cached_session(use_gpu=True) as sess: - sess.run(my_ops) + self.evaluate(my_ops) # Check the shape of the outputs - t = outputs.eval() + t = self.evaluate(outputs) self.assertAllEqual(t.shape, outputs_shape) # Check isometry of the orthogonal kernel. - self.assertAllClose(sess.run(ratio), np.sqrt(gain), rtol=tol, atol=tol) + self.assertAllClose(self.evaluate(ratio), gain, rtol=tol, atol=tol) class IdentityInitializerTest(test.TestCase): @@ -1084,12 +1139,14 @@ class IdentityInitializerTest(test.TestCase): self.assertRaises(ValueError, init, shape=[5]) self.assertRaises(ValueError, init, shape=[]) + @test_util.run_deprecated_v1 def testNonSquare(self): init = init_ops.identity_initializer() shape = (10, 5) with self.session(graph=ops.Graph(), use_gpu=True): self.assertAllClose(init(shape).eval(), np.eye(*shape)) + @test_util.run_deprecated_v1 def testGain(self): shape = (10, 10) for dtype in [dtypes.float32, dtypes.float64]: @@ -1100,6 +1157,7 @@ class IdentityInitializerTest(test.TestCase): with self.session(graph=ops.Graph(), use_gpu=True): self.assertAllClose(init_custom(shape).eval(), np.eye(*shape) * 0.9) + @test_util.run_deprecated_v1 def testPartitions(self): shape = (10, 10) init = init_ops.identity_initializer() diff --git a/tensorflow/python/kernel_tests/inplace_ops_test.py b/tensorflow/python/kernel_tests/inplace_ops_test.py index 51d16861dd..9eaaac7a24 100644 --- a/tensorflow/python/kernel_tests/inplace_ops_test.py +++ b/tensorflow/python/kernel_tests/inplace_ops_test.py @@ -31,6 +31,7 @@ from tensorflow.python.platform import test as test_lib class InplaceOpsTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testBasicUpdate(self): for dtype in [dtypes.float32, dtypes.int32, dtypes.int64]: with self.session(use_gpu=True): @@ -48,6 +49,7 @@ class InplaceOpsTest(test_util.TensorFlowTestCase): y[5, :] = 7 self.assertAllClose(x.eval(), y) + @test_util.run_deprecated_v1 def testBasicUpdateBool(self): with self.session(use_gpu=True): x = array_ops.ones([7, 3], dtypes.bool) @@ -65,6 +67,7 @@ class InplaceOpsTest(test_util.TensorFlowTestCase): y[5, :] = False self.assertAllClose(x.eval(), y) + @test_util.run_deprecated_v1 def testBasicAdd(self): for dtype in [dtypes.float32, dtypes.int32, dtypes.int64]: with self.cached_session(use_gpu=True): @@ -84,6 +87,7 @@ class InplaceOpsTest(test_util.TensorFlowTestCase): y[:, :] += 99 self.assertAllClose(x.eval(), y) + @test_util.run_deprecated_v1 def testBasicSub(self): for dtype in [dtypes.float32, dtypes.int32, dtypes.int64]: with self.cached_session(use_gpu=True): @@ -103,6 +107,7 @@ class InplaceOpsTest(test_util.TensorFlowTestCase): y[:, :] -= 99 self.assertAllClose(x.eval(), y) + @test_util.run_deprecated_v1 def testRandom(self): with self.session(use_gpu=True): d0, d1, d2 = 100, 3, 5 @@ -123,6 +128,7 @@ class InplaceOpsTest(test_util.TensorFlowTestCase): y[idx, :] -= val self.assertAllClose(x.eval(), y) + @test_util.run_deprecated_v1 def testRandom1D(self): with self.session(use_gpu=True): d0 = 100 @@ -149,7 +155,7 @@ class InplaceOpsTest(test_util.TensorFlowTestCase): y = inplace_ops.alias_inplace_add(x, [0], [[1, 2, 3]]) with ops.control_dependencies([y]): z = array_ops.identity(x) - _, vy, vz = sess.run([x, y, z]) + _, vy, vz = self.evaluate([x, y, z]) self.assertAllClose(vy, vz) def testError(self): @@ -164,6 +170,7 @@ class InplaceOpsTest(test_util.TensorFlowTestCase): "i and x shape doesn't match"): _ = inplace_ops.inplace_update([[1.]], [0, 1], [[10]]).eval() + @test_util.run_deprecated_v1 def testEmpty(self): for dtype in [ dtypes.float32, dtypes.float64, dtypes.int32, dtypes.int64, dtypes.bool, diff --git a/tensorflow/python/kernel_tests/io_ops_test.py b/tensorflow/python/kernel_tests/io_ops_test.py index afa24195cb..c5df5231bf 100644 --- a/tensorflow/python/kernel_tests/io_ops_test.py +++ b/tensorflow/python/kernel_tests/io_ops_test.py @@ -23,6 +23,7 @@ import os import shutil import tempfile +from tensorflow.python.framework import test_util from tensorflow.python.ops import io_ops from tensorflow.python.platform import test from tensorflow.python.util import compat @@ -30,6 +31,7 @@ from tensorflow.python.util import compat class IoOpsTest(test.TestCase): + @test_util.run_deprecated_v1 def testReadFile(self): cases = ['', 'Some contents', 'Неки садржаји на српском'] for contents in cases: @@ -53,7 +55,7 @@ class IoOpsTest(test.TestCase): pass with self.cached_session() as sess: w = io_ops.write_file(temp.name, contents) - sess.run(w) + self.evaluate(w) with open(temp.name, 'rb') as f: file_contents = f.read() self.assertEqual(file_contents, contents) @@ -67,7 +69,7 @@ class IoOpsTest(test.TestCase): filepath = os.path.join(subdir, 'subdir2', 'filename') with self.cached_session() as sess: w = io_ops.write_file(filepath, contents) - sess.run(w) + self.evaluate(w) with open(filepath, 'rb') as f: file_contents = f.read() self.assertEqual(file_contents, contents) @@ -78,6 +80,7 @@ class IoOpsTest(test.TestCase): compat.as_bytes(files[i].name) for i in range(len(files)) if i in indices) + @test_util.run_deprecated_v1 def testMatchingFiles(self): cases = [ 'ABcDEF.GH', 'ABzDEF.GH', 'ABasdfjklDEF.GH', 'AB3DEF.GH', 'AB4DEF.GH', diff --git a/tensorflow/python/kernel_tests/large_concat_op_test.py b/tensorflow/python/kernel_tests/large_concat_op_test.py index 1b23e74776..bf6fa9ea71 100644 --- a/tensorflow/python/kernel_tests/large_concat_op_test.py +++ b/tensorflow/python/kernel_tests/large_concat_op_test.py @@ -35,7 +35,7 @@ class LargeConcatOpTest(test.TestCase): with self.session(use_gpu=False): # TODO(dga): Add more depth to this test to validate correctness, # not just non-crashingness, once other large tensor fixes have gone in. - _ = onezeros.eval() + _ = self.evaluate(onezeros) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/linalg/BUILD b/tensorflow/python/kernel_tests/linalg/BUILD index be2e31cb5a..ba9e64979a 100644 --- a/tensorflow/python/kernel_tests/linalg/BUILD +++ b/tensorflow/python/kernel_tests/linalg/BUILD @@ -40,6 +40,44 @@ cuda_py_test( ], ) +cuda_py_test( + name = "linear_operator_adjoint_test", + size = "medium", + srcs = ["linear_operator_adjoint_test.py"], + additional_deps = [ + "//tensorflow/python/ops/linalg", + "//third_party/py/numpy", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:math_ops", + "//tensorflow/python:platform_test", + ], + shard_count = 5, + tags = [ + "noasan", # times out, b/63678675 + "optonly", # times out + ], +) + +cuda_py_test( + name = "linear_operator_algebra_test", + size = "small", + srcs = ["linear_operator_algebra_test.py"], + additional_deps = [ + "//tensorflow/python/ops/linalg", + "//third_party/py/numpy", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:math_ops", + "//tensorflow/python:platform_test", + ], +) + cuda_py_test( name = "linear_operator_block_diag_test", size = "medium", @@ -89,7 +127,6 @@ cuda_py_test( size = "medium", srcs = ["linear_operator_circulant_test.py"], additional_deps = [ - "//tensorflow/python/ops/linalg", "//third_party/py/numpy", "//tensorflow/python:array_ops", "//tensorflow/python:spectral_ops_test_util", @@ -99,6 +136,8 @@ cuda_py_test( "//tensorflow/python:framework_test_lib", "//tensorflow/python:math_ops", "//tensorflow/python:platform_test", + "//tensorflow/python/ops/linalg", + "//tensorflow/python/ops/signal", ], shard_count = 5, tags = [ @@ -150,6 +189,28 @@ cuda_py_test( ], ) +cuda_py_test( + name = "linear_operator_inversion_test", + size = "medium", + srcs = ["linear_operator_inversion_test.py"], + additional_deps = [ + "//tensorflow/python/ops/linalg", + "//third_party/py/numpy", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:math_ops", + "//tensorflow/python:platform_test", + ], + shard_count = 5, + tags = [ + "noasan", # times out, b/63678675 + "optonly", # times out + ], +) + cuda_py_test( name = "linear_operator_full_matrix_test", size = "medium", diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_addition_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_addition_test.py index 628ed998c5..627349c69b 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_addition_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_addition_test.py @@ -19,6 +19,7 @@ from __future__ import print_function import numpy as np +from tensorflow.python.framework import test_util from tensorflow.python.ops import linalg_ops from tensorflow.python.ops.linalg import linalg as linalg_lib from tensorflow.python.ops.linalg import linear_operator_addition @@ -69,6 +70,7 @@ class LinearOperatorAdditionCorrectnessTest(test.TestCase): with self.assertRaisesRegexp(TypeError, "contain only LinearOperator"): add_operators([1, 2]) + @test_util.run_deprecated_v1 def test_two_diag_operators(self): op_a = linalg.LinearOperatorDiag( [1., 1.], is_positive_definite=True, name="A") @@ -89,6 +91,7 @@ class LinearOperatorAdditionCorrectnessTest(test.TestCase): # Enforce particular name for this simple case self.assertEqual("Add/B__A/", op.name) + @test_util.run_deprecated_v1 def test_three_diag_operators(self): op1 = linalg.LinearOperatorDiag( [1., 1.], is_positive_definite=True, name="op1") @@ -109,6 +112,7 @@ class LinearOperatorAdditionCorrectnessTest(test.TestCase): # Positive definite ==> non-singular self.assertTrue(op.is_non_singular) + @test_util.run_deprecated_v1 def test_diag_tril_diag(self): op1 = linalg.LinearOperatorDiag( [1., 1.], is_non_singular=True, name="diag_a") @@ -134,6 +138,7 @@ class LinearOperatorAdditionCorrectnessTest(test.TestCase): # Since no custom hint was provided, we default to None (unknown). self.assertEqual(None, op.is_non_singular) + @test_util.run_deprecated_v1 def test_matrix_diag_tril_diag_uses_custom_name(self): op0 = linalg.LinearOperatorFullMatrix( [[-1., -1.], [-1., -1.]], name="matrix") @@ -217,6 +222,7 @@ class LinearOperatorOrderOfAdditionTest(test.TestCase): self.assertEqual(1, len(op_sum)) self.assertIsInstance(op_sum[0], linalg.LinearOperatorLowerTriangular) + @test_util.run_deprecated_v1 def test_cannot_add_everything_so_return_more_than_one_operator(self): diag1 = linalg.LinearOperatorDiag([1.]) diag2 = linalg.LinearOperatorDiag([2.]) @@ -261,6 +267,7 @@ class AddAndReturnScaledIdentityTest(test.TestCase): def setUp(self): self._adder = linear_operator_addition._AddAndReturnScaledIdentity() + @test_util.run_deprecated_v1 def test_identity_plus_identity(self): id1 = linalg.LinearOperatorIdentity(num_rows=2) id2 = linalg.LinearOperatorIdentity(num_rows=2, batch_shape=[3]) @@ -279,6 +286,7 @@ class AddAndReturnScaledIdentityTest(test.TestCase): self.assertTrue(operator.is_non_singular) self.assertEqual("my_operator", operator.name) + @test_util.run_deprecated_v1 def test_identity_plus_scaled_identity(self): id1 = linalg.LinearOperatorIdentity(num_rows=2, batch_shape=[3]) id2 = linalg.LinearOperatorScaledIdentity(num_rows=2, multiplier=2.2) @@ -297,6 +305,7 @@ class AddAndReturnScaledIdentityTest(test.TestCase): self.assertTrue(operator.is_non_singular) self.assertEqual("my_operator", operator.name) + @test_util.run_deprecated_v1 def test_scaled_identity_plus_scaled_identity(self): id1 = linalg.LinearOperatorScaledIdentity( num_rows=2, multiplier=[2.2, 2.2, 2.2]) @@ -322,6 +331,7 @@ class AddAndReturnDiagTest(test.TestCase): def setUp(self): self._adder = linear_operator_addition._AddAndReturnDiag() + @test_util.run_deprecated_v1 def test_identity_plus_identity_returns_diag(self): id1 = linalg.LinearOperatorIdentity(num_rows=2) id2 = linalg.LinearOperatorIdentity(num_rows=2, batch_shape=[3]) @@ -340,6 +350,7 @@ class AddAndReturnDiagTest(test.TestCase): self.assertTrue(operator.is_non_singular) self.assertEqual("my_operator", operator.name) + @test_util.run_deprecated_v1 def test_diag_plus_diag(self): diag1 = rng.rand(2, 3, 4) diag2 = rng.rand(4) @@ -366,6 +377,7 @@ class AddAndReturnTriLTest(test.TestCase): def setUp(self): self._adder = linear_operator_addition._AddAndReturnTriL() + @test_util.run_deprecated_v1 def test_diag_plus_tril(self): diag = linalg.LinearOperatorDiag([1., 2.]) tril = linalg.LinearOperatorLowerTriangular([[10., 0.], [30., 0.]]) @@ -389,6 +401,7 @@ class AddAndReturnMatrixTest(test.TestCase): def setUp(self): self._adder = linear_operator_addition._AddAndReturnMatrix() + @test_util.run_deprecated_v1 def test_diag_plus_diag(self): diag1 = linalg.LinearOperatorDiag([1., 2.]) diag2 = linalg.LinearOperatorDiag([-1., 3.]) diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_adjoint_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_adjoint_test.py new file mode 100644 index 0000000000..1bed4b5268 --- /dev/null +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_adjoint_test.py @@ -0,0 +1,118 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import dtypes +from tensorflow.python.ops import array_ops +from tensorflow.python.ops.linalg import linalg as linalg_lib +from tensorflow.python.ops.linalg import linear_operator_adjoint +from tensorflow.python.ops.linalg import linear_operator_test_util +from tensorflow.python.platform import test + +linalg = linalg_lib + +LinearOperatorAdjoint = linear_operator_adjoint.LinearOperatorAdjoint # pylint: disable=invalid-name + + +class LinearOperatorAdjointTest( + linear_operator_test_util.SquareLinearOperatorDerivedClassTest): + """Most tests done in the base class LinearOperatorDerivedClassTest.""" + + def setUp(self): + self._atol[dtypes.complex64] = 1e-5 + self._rtol[dtypes.complex64] = 1e-5 + + def _operator_and_matrix(self, + build_info, + dtype, + use_placeholder, + ensure_self_adjoint_and_pd=False): + shape = list(build_info.shape) + + if ensure_self_adjoint_and_pd: + matrix = linear_operator_test_util.random_positive_definite_matrix( + shape, dtype, force_well_conditioned=True) + else: + matrix = linear_operator_test_util.random_tril_matrix( + shape, dtype, force_well_conditioned=True, remove_upper=True) + + lin_op_matrix = matrix + + if use_placeholder: + lin_op_matrix = array_ops.placeholder_with_default(matrix, shape=None) + + if ensure_self_adjoint_and_pd: + operator = LinearOperatorAdjoint( + linalg.LinearOperatorFullMatrix( + lin_op_matrix, is_positive_definite=True, is_self_adjoint=True)) + else: + operator = LinearOperatorAdjoint( + linalg.LinearOperatorLowerTriangular(lin_op_matrix)) + + return operator, linalg.adjoint(matrix) + + def test_base_operator_hint_used(self): + # The matrix values do not effect auto-setting of the flags. + matrix = [[1., 0.], [1., 1.]] + operator = linalg.LinearOperatorFullMatrix( + matrix, + is_positive_definite=True, + is_non_singular=True, + is_self_adjoint=False) + operator_adjoint = LinearOperatorAdjoint(operator) + self.assertTrue(operator_adjoint.is_positive_definite) + self.assertTrue(operator_adjoint.is_non_singular) + self.assertFalse(operator_adjoint.is_self_adjoint) + + def test_supplied_hint_used(self): + # The matrix values do not effect auto-setting of the flags. + matrix = [[1., 0.], [1., 1.]] + operator = linalg.LinearOperatorFullMatrix(matrix) + operator_adjoint = LinearOperatorAdjoint( + operator, + is_positive_definite=True, + is_non_singular=True, + is_self_adjoint=False) + self.assertTrue(operator_adjoint.is_positive_definite) + self.assertTrue(operator_adjoint.is_non_singular) + self.assertFalse(operator_adjoint.is_self_adjoint) + + def test_contradicting_hints_raise(self): + # The matrix values do not effect auto-setting of the flags. + matrix = [[1., 0.], [1., 1.]] + operator = linalg.LinearOperatorFullMatrix( + matrix, is_positive_definite=False) + with self.assertRaisesRegexp(ValueError, "positive-definite"): + LinearOperatorAdjoint(operator, is_positive_definite=True) + + operator = linalg.LinearOperatorFullMatrix(matrix, is_self_adjoint=False) + with self.assertRaisesRegexp(ValueError, "self-adjoint"): + LinearOperatorAdjoint(operator, is_self_adjoint=True) + + def test_name(self): + matrix = [[11., 0.], [1., 8.]] + operator = linalg.LinearOperatorFullMatrix( + matrix, name="my_operator", is_non_singular=True) + + operator = LinearOperatorAdjoint(operator) + + self.assertEqual("my_operator_adjoint", operator.name) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_algebra_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_algebra_test.py new file mode 100644 index 0000000000..8e296c026c --- /dev/null +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_algebra_test.py @@ -0,0 +1,133 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for registration mechanisms.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import tensor_shape +from tensorflow.python.ops.linalg import cholesky_registrations # pylint: disable=unused-import +from tensorflow.python.ops.linalg import linear_operator +from tensorflow.python.ops.linalg import linear_operator_algebra +from tensorflow.python.ops.linalg import matmul_registrations # pylint: disable=unused-import +from tensorflow.python.platform import test + +# pylint: disable=protected-access +_CHOLESKY_DECOMPS = linear_operator_algebra._CHOLESKY_DECOMPS +_MATMUL = linear_operator_algebra._MATMUL +_registered_cholesky = linear_operator_algebra._registered_cholesky +_registered_matmul = linear_operator_algebra._registered_matmul +# pylint: enable=protected-access + + +class CholeskyTest(test.TestCase): + + def testRegistration(self): + + class CustomLinOp(linear_operator.LinearOperator): + + def _matmul(self, a): + pass + + def _shape(self): + return tensor_shape.TensorShape([1, 1]) + + def _shape_tensor(self): + pass + + # Register Cholesky to a lambda that spits out the name parameter + @linear_operator_algebra.RegisterCholesky(CustomLinOp) + def _cholesky(a): # pylint: disable=unused-argument,unused-variable + return "OK" + + with self.assertRaisesRegexp(ValueError, "positive definite"): + CustomLinOp(dtype=None, is_self_adjoint=True).cholesky() + + with self.assertRaisesRegexp(ValueError, "self adjoint"): + CustomLinOp(dtype=None, is_positive_definite=True).cholesky() + + custom_linop = CustomLinOp( + dtype=None, is_self_adjoint=True, is_positive_definite=True) + self.assertEqual("OK", custom_linop.cholesky()) + + def testRegistrationFailures(self): + + class CustomLinOp(linear_operator.LinearOperator): + pass + + with self.assertRaisesRegexp(TypeError, "must be callable"): + linear_operator_algebra.RegisterCholesky(CustomLinOp)("blah") + + # First registration is OK + linear_operator_algebra.RegisterCholesky(CustomLinOp)(lambda a: None) + + # Second registration fails + with self.assertRaisesRegexp(ValueError, "has already been registered"): + linear_operator_algebra.RegisterCholesky(CustomLinOp)(lambda a: None) + + def testExactCholeskyRegistrationsAllMatch(self): + for (k, v) in _CHOLESKY_DECOMPS.items(): + self.assertEqual(v, _registered_cholesky(k[0])) + + +class MatmulTest(test.TestCase): + + def testRegistration(self): + + class CustomLinOp(linear_operator.LinearOperator): + + def _matmul(self, a): + pass + + def _shape(self): + return tensor_shape.TensorShape([1, 1]) + + def _shape_tensor(self): + pass + + # Register Matmul to a lambda that spits out the name parameter + @linear_operator_algebra.RegisterMatmul(CustomLinOp, CustomLinOp) + def _matmul(a, b): # pylint: disable=unused-argument,unused-variable + return "OK" + + custom_linop = CustomLinOp( + dtype=None, is_self_adjoint=True, is_positive_definite=True) + self.assertEqual("OK", custom_linop.matmul(custom_linop)) + + def testRegistrationFailures(self): + + class CustomLinOp(linear_operator.LinearOperator): + pass + + with self.assertRaisesRegexp(TypeError, "must be callable"): + linear_operator_algebra.RegisterMatmul(CustomLinOp, CustomLinOp)("blah") + + # First registration is OK + linear_operator_algebra.RegisterMatmul( + CustomLinOp, CustomLinOp)(lambda a: None) + + # Second registration fails + with self.assertRaisesRegexp(ValueError, "has already been registered"): + linear_operator_algebra.RegisterMatmul( + CustomLinOp, CustomLinOp)(lambda a: None) + + def testExactMatmulRegistrationsAllMatch(self): + for (k, v) in _MATMUL.items(): + self.assertEqual(v, _registered_matmul(k[0], k[1])) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_block_diag_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_block_diag_test.py index 30951b1b0e..f0cc5d709f 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_block_diag_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_block_diag_test.py @@ -23,6 +23,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.ops import array_ops from tensorflow.python.ops.linalg import linalg as linalg_lib from tensorflow.python.ops.linalg import linear_operator_block_diag as block_diag +from tensorflow.python.ops.linalg import linear_operator_lower_triangular as lower_triangular from tensorflow.python.ops.linalg import linear_operator_test_util from tensorflow.python.ops.linalg import linear_operator_util from tensorflow.python.platform import test @@ -78,7 +79,9 @@ class SquareLinearOperatorBlockDiagTest( build_info((2, 1, 5, 5), blocks=[(2, 1, 2, 2), (1, 3, 3)]), ] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): shape = list(build_info.shape) expected_blocks = ( build_info.__dict__["blocks"] if "blocks" in build_info.__dict__ @@ -98,7 +101,11 @@ class SquareLinearOperatorBlockDiagTest( operator = block_diag.LinearOperatorBlockDiag( [linalg.LinearOperatorFullMatrix( - l, is_square=True) for l in lin_op_matrices]) + l, + is_square=True, + is_self_adjoint=True if ensure_self_adjoint_and_pd else None, + is_positive_definite=True if ensure_self_adjoint_and_pd else None) + for l in lin_op_matrices]) # Should be auto-set. self.assertTrue(operator.is_square) @@ -129,6 +136,40 @@ class SquareLinearOperatorBlockDiagTest( self.assertTrue(operator.is_non_singular) self.assertFalse(operator.is_self_adjoint) + def test_block_diag_cholesky_type(self): + matrix = [[1., 0.], [0., 1.]] + operator = block_diag.LinearOperatorBlockDiag( + [ + linalg.LinearOperatorFullMatrix( + matrix, + is_positive_definite=True, + is_self_adjoint=True, + ), + linalg.LinearOperatorFullMatrix( + matrix, + is_positive_definite=True, + is_self_adjoint=True, + ), + ], + is_positive_definite=True, + is_self_adjoint=True, + ) + cholesky_factor = operator.cholesky() + self.assertTrue(isinstance( + cholesky_factor, + block_diag.LinearOperatorBlockDiag)) + self.assertEqual(2, len(cholesky_factor.operators)) + self.assertTrue( + isinstance( + cholesky_factor.operators[0], + lower_triangular.LinearOperatorLowerTriangular) + ) + self.assertTrue( + isinstance( + cholesky_factor.operators[1], + lower_triangular.LinearOperatorLowerTriangular) + ) + def test_is_non_singular_auto_set(self): # Matrix with two positive eigenvalues, 11 and 8. # The matrix values do not effect auto-setting of the flags. diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_circulant_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_circulant_test.py index f1e151ebd8..6366083ac5 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_circulant_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_circulant_test.py @@ -21,12 +21,14 @@ import contextlib import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import spectral_ops_test_util from tensorflow.python.ops.linalg import linalg from tensorflow.python.ops.linalg import linear_operator_circulant from tensorflow.python.ops.linalg import linear_operator_test_util +from tensorflow.python.ops.signal import fft_ops from tensorflow.python.platform import test rng = np.random.RandomState(0) @@ -75,8 +77,8 @@ class LinearOperatorCirculantBaseTest(object): x = np.zeros([domain_dimension]) # x is a basis vector. x[m] = 1.0 - fft_x = math_ops.fft(x.astype(np.complex64)) - h_convolve_x = math_ops.ifft(spectrum * fft_x) + fft_x = fft_ops.fft(x.astype(np.complex64)) + h_convolve_x = fft_ops.ifft(spectrum * fft_x) matrix_rows.append(h_convolve_x) matrix = array_ops.stack(matrix_rows, axis=-1) return math_ops.cast(matrix, dtype) @@ -97,7 +99,9 @@ class LinearOperatorCirculantTestSelfAdjointOperator( # real, the matrix will not be real. return [dtypes.complex64] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): shape = build_info.shape # For this test class, we are creating real spectrums. # We also want the spectrum to have eigenvalues bounded away from zero. @@ -105,6 +109,8 @@ class LinearOperatorCirculantTestSelfAdjointOperator( # spectrum is bounded away from zero. spectrum = linear_operator_test_util.random_sign_uniform( shape=self._shape_to_spectrum_shape(shape), minval=1., maxval=2.) + if ensure_self_adjoint_and_pd: + spectrum = math_ops.abs(spectrum) # If dtype is complex, cast spectrum to complex. The imaginary part will be # zero, so the operator will still be self-adjoint. spectrum = math_ops.cast(spectrum, dtype) @@ -115,12 +121,16 @@ class LinearOperatorCirculantTestSelfAdjointOperator( lin_op_spectrum = array_ops.placeholder_with_default(spectrum, shape=None) operator = linalg.LinearOperatorCirculant( - lin_op_spectrum, is_self_adjoint=True, input_output_dtype=dtype) + lin_op_spectrum, + is_self_adjoint=True, + is_positive_definite=True if ensure_self_adjoint_and_pd else None, + input_output_dtype=dtype) mat = self._spectrum_to_circulant_1d(spectrum, shape, dtype=dtype) return operator, mat + @test_util.run_deprecated_v1 def test_simple_hermitian_spectrum_gives_operator_with_zero_imag_part(self): with self.cached_session(): spectrum = math_ops.cast([1., 1j, -1j], dtypes.complex64) @@ -129,7 +139,8 @@ class LinearOperatorCirculantTestSelfAdjointOperator( matrix = operator.to_dense() imag_matrix = math_ops.imag(matrix) eps = np.finfo(np.float32).eps - np.testing.assert_allclose(0, imag_matrix.eval(), rtol=0, atol=eps * 3) + np.testing.assert_allclose( + 0, self.evaluate(imag_matrix), rtol=0, atol=eps * 3) class LinearOperatorCirculantTestHermitianSpectrum( @@ -146,7 +157,9 @@ class LinearOperatorCirculantTestHermitianSpectrum( def _dtypes_to_test(self): return [dtypes.float32, dtypes.complex64] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): shape = build_info.shape # For this test class, we are creating Hermitian spectrums. # We also want the spectrum to have eigenvalues bounded away from zero. @@ -160,14 +173,14 @@ class LinearOperatorCirculantTestHermitianSpectrum( # = IFFT[EvenPartOf[pre_spectrum]] # is the IFFT of something that is also bounded away from zero. # Therefore, FFT[pre_h] would be a well-conditioned spectrum. - pre_h = math_ops.ifft(pre_spectrum_c) + pre_h = fft_ops.ifft(pre_spectrum_c) # A spectrum is Hermitian iff it is the DFT of a real convolution kernel. # So we will make spectrum = FFT[h], for real valued h. h = math_ops.real(pre_h) h_c = _to_complex(h) - spectrum = math_ops.fft(h_c) + spectrum = fft_ops.fft(h_c) lin_op_spectrum = spectrum @@ -175,12 +188,17 @@ class LinearOperatorCirculantTestHermitianSpectrum( lin_op_spectrum = array_ops.placeholder_with_default(spectrum, shape=None) operator = linalg.LinearOperatorCirculant( - lin_op_spectrum, input_output_dtype=dtype) + lin_op_spectrum, + input_output_dtype=dtype, + is_positive_definite=True if ensure_self_adjoint_and_pd else None, + is_self_adjoint=True if ensure_self_adjoint_and_pd else None, + ) mat = self._spectrum_to_circulant_1d(spectrum, shape, dtype=dtype) return operator, mat + @test_util.run_deprecated_v1 def test_simple_hermitian_spectrum_gives_operator_with_zero_imag_part(self): with self.cached_session(): spectrum = math_ops.cast([1., 1j, -1j], dtypes.complex64) @@ -189,7 +207,8 @@ class LinearOperatorCirculantTestHermitianSpectrum( matrix = operator.to_dense() imag_matrix = math_ops.imag(matrix) eps = np.finfo(np.float32).eps - np.testing.assert_allclose(0, imag_matrix.eval(), rtol=0, atol=eps * 3) + np.testing.assert_allclose( + 0, self.evaluate(imag_matrix), rtol=0, atol=eps * 3) class LinearOperatorCirculantTestNonHermitianSpectrum( @@ -205,7 +224,16 @@ class LinearOperatorCirculantTestNonHermitianSpectrum( def _dtypes_to_test(self): return [dtypes.complex64] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + # Skip Cholesky since we are explicitly testing non-hermitian + # spectra. + @property + def _tests_to_skip(self): + return ["cholesky"] + + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): + del ensure_self_adjoint_and_pd shape = build_info.shape # Will be well conditioned enough to get accurate solves. spectrum = linear_operator_test_util.random_sign_uniform( @@ -226,6 +254,7 @@ class LinearOperatorCirculantTestNonHermitianSpectrum( return operator, mat + @test_util.run_deprecated_v1 def test_simple_hermitian_spectrum_gives_operator_with_zero_imag_part(self): with self.cached_session(): spectrum = math_ops.cast([1., 1j, -1j], dtypes.complex64) @@ -234,8 +263,10 @@ class LinearOperatorCirculantTestNonHermitianSpectrum( matrix = operator.to_dense() imag_matrix = math_ops.imag(matrix) eps = np.finfo(np.float32).eps - np.testing.assert_allclose(0, imag_matrix.eval(), rtol=0, atol=eps * 3) + np.testing.assert_allclose( + 0, self.evaluate(imag_matrix), rtol=0, atol=eps * 3) + @test_util.run_deprecated_v1 def test_simple_positive_real_spectrum_gives_self_adjoint_pos_def_oper(self): with self.cached_session() as sess: spectrum = math_ops.cast([6., 4, 2], dtypes.complex64) @@ -248,10 +279,11 @@ class LinearOperatorCirculantTestNonHermitianSpectrum( operator.assert_positive_definite().run() # Should not fail operator.assert_self_adjoint().run() # Should not fail + @test_util.run_deprecated_v1 def test_defining_operator_using_real_convolution_kernel(self): with self.cached_session(): convolution_kernel = [1., 2., 1.] - spectrum = math_ops.fft( + spectrum = fft_ops.fft( math_ops.cast(convolution_kernel, dtypes.complex64)) # spectrum is shape [3] ==> operator is shape [3, 3] @@ -269,15 +301,16 @@ class LinearOperatorCirculantTestNonHermitianSpectrum( # Make spectrum the FFT of a real convolution kernel h. This ensures that # spectrum is Hermitian. h = linear_operator_test_util.random_normal(shape=(3, 4)) - spectrum = math_ops.fft(math_ops.cast(h, dtypes.complex64)) + spectrum = fft_ops.fft(math_ops.cast(h, dtypes.complex64)) operator = linalg.LinearOperatorCirculant( spectrum, input_output_dtype=dtypes.complex64) matrix = operator.to_dense() imag_matrix = math_ops.imag(matrix) eps = np.finfo(np.float32).eps np.testing.assert_allclose( - 0, imag_matrix.eval(), rtol=0, atol=eps * 3 * 4) + 0, self.evaluate(imag_matrix), rtol=0, atol=eps * 3 * 4) + @test_util.run_deprecated_v1 def test_convolution_kernel_same_as_first_row_of_to_dense(self): spectrum = [[3., 2., 1.], [2., 1.5, 1.]] with self.cached_session(): @@ -287,8 +320,9 @@ class LinearOperatorCirculantTestNonHermitianSpectrum( self.assertAllEqual((2, 3), h.get_shape()) self.assertAllEqual((2, 3, 3), c.get_shape()) - self.assertAllClose(h.eval(), c.eval()[:, :, 0]) + self.assertAllClose(h.eval(), self.evaluate(c)[:, :, 0]) + @test_util.run_deprecated_v1 def test_assert_non_singular_fails_for_singular_operator(self): spectrum = math_ops.cast([0, 4, 2j + 2], dtypes.complex64) operator = linalg.LinearOperatorCirculant(spectrum) @@ -296,12 +330,14 @@ class LinearOperatorCirculantTestNonHermitianSpectrum( with self.assertRaisesOpError("Singular operator"): operator.assert_non_singular().run() + @test_util.run_deprecated_v1 def test_assert_non_singular_does_not_fail_for_non_singular_operator(self): spectrum = math_ops.cast([-3j, 4, 2j + 2], dtypes.complex64) operator = linalg.LinearOperatorCirculant(spectrum) with self.cached_session(): operator.assert_non_singular().run() # Should not fail + @test_util.run_deprecated_v1 def test_assert_positive_definite_fails_for_non_positive_definite(self): spectrum = math_ops.cast([6., 4, 2j], dtypes.complex64) operator = linalg.LinearOperatorCirculant(spectrum) @@ -309,6 +345,7 @@ class LinearOperatorCirculantTestNonHermitianSpectrum( with self.assertRaisesOpError("Not positive definite"): operator.assert_positive_definite().run() + @test_util.run_deprecated_v1 def test_assert_positive_definite_does_not_fail_when_pos_def(self): spectrum = math_ops.cast([6., 4, 2j + 2], dtypes.complex64) operator = linalg.LinearOperatorCirculant(spectrum) @@ -397,8 +434,8 @@ class LinearOperatorCirculant2DBaseTest(object): x = np.zeros(block_shape) # x is a basis vector. x[n0, n1] = 1.0 - fft_x = math_ops.fft2d(x.astype(np.complex64)) - h_convolve_x = math_ops.ifft2d(spectrum * fft_x) + fft_x = fft_ops.fft2d(x.astype(np.complex64)) + h_convolve_x = fft_ops.ifft2d(spectrum * fft_x) # We want the flat version of the action of the operator on a basis # vector, not the block version. h_convolve_x = array_ops.reshape(h_convolve_x, shape[:-1]) @@ -421,7 +458,9 @@ class LinearOperatorCirculant2DTestHermitianSpectrum( def _dtypes_to_test(self): return [dtypes.float32, dtypes.complex64] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): shape = build_info.shape # For this test class, we are creating Hermitian spectrums. # We also want the spectrum to have eigenvalues bounded away from zero. @@ -435,14 +474,14 @@ class LinearOperatorCirculant2DTestHermitianSpectrum( # = IFFT[EvenPartOf[pre_spectrum]] # is the IFFT of something that is also bounded away from zero. # Therefore, FFT[pre_h] would be a well-conditioned spectrum. - pre_h = math_ops.ifft2d(pre_spectrum_c) + pre_h = fft_ops.ifft2d(pre_spectrum_c) # A spectrum is Hermitian iff it is the DFT of a real convolution kernel. # So we will make spectrum = FFT[h], for real valued h. h = math_ops.real(pre_h) h_c = _to_complex(h) - spectrum = math_ops.fft2d(h_c) + spectrum = fft_ops.fft2d(h_c) lin_op_spectrum = spectrum @@ -450,7 +489,10 @@ class LinearOperatorCirculant2DTestHermitianSpectrum( lin_op_spectrum = array_ops.placeholder_with_default(spectrum, shape=None) operator = linalg.LinearOperatorCirculant2D( - lin_op_spectrum, input_output_dtype=dtype) + lin_op_spectrum, + is_positive_definite=True if ensure_self_adjoint_and_pd else None, + is_self_adjoint=True if ensure_self_adjoint_and_pd else None, + input_output_dtype=dtype) mat = self._spectrum_to_circulant_2d(spectrum, shape, dtype=dtype) @@ -470,7 +512,14 @@ class LinearOperatorCirculant2DTestNonHermitianSpectrum( def _dtypes_to_test(self): return [dtypes.complex64] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + @property + def _tests_to_skip(self): + return ["cholesky"] + + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): + del ensure_self_adjoint_and_pd shape = build_info.shape # Will be well conditioned enough to get accurate solves. spectrum = linear_operator_test_util.random_sign_uniform( @@ -491,6 +540,7 @@ class LinearOperatorCirculant2DTestNonHermitianSpectrum( return operator, mat + @test_util.run_deprecated_v1 def test_real_hermitian_spectrum_gives_real_symmetric_operator(self): with self.cached_session() as sess: # This is a real and hermitian spectrum. @@ -508,6 +558,7 @@ class LinearOperatorCirculant2DTestNonHermitianSpectrum( np.testing.assert_allclose(0, imag_matrix, atol=1e-6) self.assertAllClose(matrix, matrix_transpose, atol=0) + @test_util.run_deprecated_v1 def test_real_spectrum_gives_self_adjoint_operator(self): with self.cached_session() as sess: # This is a real and hermitian spectrum. @@ -519,9 +570,10 @@ class LinearOperatorCirculant2DTestNonHermitianSpectrum( self.assertEqual(matrix_tensor.dtype, linear_operator_circulant._DTYPE_COMPLEX) matrix_h = linalg.adjoint(matrix_tensor) - matrix, matrix_h = sess.run([matrix_tensor, matrix_h]) + matrix, matrix_h = self.evaluate([matrix_tensor, matrix_h]) self.assertAllClose(matrix, matrix_h, atol=0) + @test_util.run_deprecated_v1 def test_assert_non_singular_fails_for_singular_operator(self): spectrum = math_ops.cast([[0, 4], [2j + 2, 3.]], dtypes.complex64) operator = linalg.LinearOperatorCirculant2D(spectrum) @@ -529,12 +581,14 @@ class LinearOperatorCirculant2DTestNonHermitianSpectrum( with self.assertRaisesOpError("Singular operator"): operator.assert_non_singular().run() + @test_util.run_deprecated_v1 def test_assert_non_singular_does_not_fail_for_non_singular_operator(self): spectrum = math_ops.cast([[-3j, 4], [2j + 2, 3.]], dtypes.complex64) operator = linalg.LinearOperatorCirculant2D(spectrum) with self.cached_session(): operator.assert_non_singular().run() # Should not fail + @test_util.run_deprecated_v1 def test_assert_positive_definite_fails_for_non_positive_definite(self): spectrum = math_ops.cast([[6., 4], [2j, 3.]], dtypes.complex64) operator = linalg.LinearOperatorCirculant2D(spectrum) @@ -542,6 +596,7 @@ class LinearOperatorCirculant2DTestNonHermitianSpectrum( with self.assertRaisesOpError("Not positive definite"): operator.assert_positive_definite().run() + @test_util.run_deprecated_v1 def test_assert_positive_definite_does_not_fail_when_pos_def(self): spectrum = math_ops.cast([[6., 4], [2j + 2, 3.]], dtypes.complex64) operator = linalg.LinearOperatorCirculant2D(spectrum) @@ -580,6 +635,7 @@ class LinearOperatorCirculant3DTest(test.TestCase): with spectral_ops_test_util.fft_kernel_label_map(): yield sess + @test_util.run_deprecated_v1 def test_real_spectrum_gives_self_adjoint_operator(self): with self.cached_session() as sess: # This is a real and hermitian spectrum. @@ -593,16 +649,17 @@ class LinearOperatorCirculant3DTest(test.TestCase): linear_operator_circulant._DTYPE_COMPLEX) matrix_h = linalg.adjoint(matrix_tensor) - matrix, matrix_h = sess.run([matrix_tensor, matrix_h]) + matrix, matrix_h = self.evaluate([matrix_tensor, matrix_h]) self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), matrix.shape) self.assertAllClose(matrix, matrix_h) + @test_util.run_deprecated_v1 def test_defining_operator_using_real_convolution_kernel(self): with self.cached_session(): convolution_kernel = linear_operator_test_util.random_normal( shape=(2, 2, 3, 5), dtype=dtypes.float32) # Convolution kernel is real ==> spectrum is Hermitian. - spectrum = math_ops.fft3d( + spectrum = fft_ops.fft3d( math_ops.cast(convolution_kernel, dtypes.complex64)) # spectrum is Hermitian ==> operator is real. @@ -615,6 +672,7 @@ class LinearOperatorCirculant3DTest(test.TestCase): self.assertAllEqual((2, 2 * 3 * 5, 2 * 3 * 5), matrix.shape) np.testing.assert_allclose(0, np.imag(matrix), atol=1e-6) + @test_util.run_deprecated_v1 def test_defining_spd_operator_by_taking_real_part(self): with self.cached_session() as sess: # S is real and positive. @@ -634,7 +692,7 @@ class LinearOperatorCirculant3DTest(test.TestCase): # = H1 + H2 # where H1 is real since it is Hermitian, # and H2 is imaginary since it is anti-Hermitian. - ifft_s = math_ops.ifft3d(math_ops.cast(s, dtypes.complex64)) + ifft_s = fft_ops.ifft3d(math_ops.cast(s, dtypes.complex64)) # Throw away H2, keep H1. real_ifft_s = math_ops.real(ifft_s) @@ -642,7 +700,7 @@ class LinearOperatorCirculant3DTest(test.TestCase): # This is the perfect spectrum! # spectrum = DFT[H1] # = S1, - fft_real_ifft_s = math_ops.fft3d( + fft_real_ifft_s = fft_ops.fft3d( math_ops.cast(real_ifft_s, dtypes.complex64)) # S1 is Hermitian ==> operator is real. @@ -665,7 +723,7 @@ class LinearOperatorCirculant3DTest(test.TestCase): # S2 is anti-Hermitian ==> operator is imaginary. # S2 is real ==> operator is self-adjoint. imag_ifft_s = math_ops.imag(ifft_s) - fft_imag_ifft_s = math_ops.fft3d( + fft_imag_ifft_s = fft_ops.fft3d( 1j * math_ops.cast(imag_ifft_s, dtypes.complex64)) operator_imag = linalg.LinearOperatorCirculant3D(fft_imag_ifft_s) diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_composition_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_composition_test.py index 02f56db596..214b73aa2f 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_composition_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_composition_test.py @@ -21,6 +21,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops.linalg import linalg as linalg_lib @@ -42,8 +43,12 @@ class SquareLinearOperatorCompositionTest( self._rtol[dtypes.float32] = 1e-4 self._rtol[dtypes.complex64] = 1e-4 + @property + def _tests_to_skip(self): + # Cholesky not implemented. + return ["cholesky"] + def _operator_and_matrix(self, build_info, dtype, use_placeholder): - sess = ops.get_default_session() shape = list(build_info.shape) # Either 1 or 2 matrices, depending. @@ -175,6 +180,7 @@ class NonSquareLinearOperatorCompositionTest( return operator, mat + @test_util.run_deprecated_v1 def test_static_shapes(self): operators = [ linalg.LinearOperatorFullMatrix(rng.rand(2, 3, 4)), @@ -183,6 +189,7 @@ class NonSquareLinearOperatorCompositionTest( operator = linalg.LinearOperatorComposition(operators) self.assertAllEqual((2, 3, 5), operator.shape) + @test_util.run_deprecated_v1 def test_shape_tensors_when_statically_available(self): operators = [ linalg.LinearOperatorFullMatrix(rng.rand(2, 3, 4)), @@ -192,6 +199,7 @@ class NonSquareLinearOperatorCompositionTest( with self.cached_session(): self.assertAllEqual((2, 3, 5), operator.shape_tensor().eval()) + @test_util.run_deprecated_v1 def test_shape_tensors_when_only_dynamically_available(self): mat_1 = rng.rand(1, 2, 3, 4) mat_2 = rng.rand(1, 2, 4, 5) diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_diag_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_diag_test.py index 0758349531..dcbc0dd7c9 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_diag_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_diag_test.py @@ -17,6 +17,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import linalg_ops from tensorflow.python.ops import math_ops @@ -32,17 +33,26 @@ class LinearOperatorDiagTest( linear_operator_test_util.SquareLinearOperatorDerivedClassTest): """Most tests done in the base class LinearOperatorDerivedClassTest.""" - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): shape = list(build_info.shape) diag = linear_operator_test_util.random_sign_uniform( shape[:-1], minval=1., maxval=2., dtype=dtype) + if ensure_self_adjoint_and_pd: + # Abs on complex64 will result in a float32, so we cast back up. + diag = math_ops.cast(math_ops.abs(diag), dtype=dtype) + lin_op_diag = diag if use_placeholder: lin_op_diag = array_ops.placeholder_with_default(diag, shape=None) - operator = linalg.LinearOperatorDiag(lin_op_diag) + operator = linalg.LinearOperatorDiag( + lin_op_diag, + is_self_adjoint=True if ensure_self_adjoint_and_pd else None, + is_positive_definite=True if ensure_self_adjoint_and_pd else None) matrix = array_ops.matrix_diag(diag) @@ -71,6 +81,7 @@ class LinearOperatorDiagTest( with self.assertRaisesOpError("non-positive real.*not positive definite"): operator.assert_positive_definite().run() + @test_util.run_deprecated_v1 def test_assert_positive_definite_does_not_raise_if_pd_and_complex(self): with self.cached_session(): x = [1., 2.] @@ -87,6 +98,7 @@ class LinearOperatorDiagTest( with self.assertRaisesOpError("Singular operator"): operator.assert_non_singular().run() + @test_util.run_deprecated_v1 def test_assert_non_singular_does_not_raise_for_complex_nonsingular(self): with self.cached_session(): x = [1., 0.] @@ -104,6 +116,7 @@ class LinearOperatorDiagTest( with self.assertRaisesOpError("imaginary.*not self-adjoint"): operator.assert_self_adjoint().run() + @test_util.run_deprecated_v1 def test_assert_self_adjoint_does_not_raise_for_diag_with_zero_imag(self): with self.cached_session(): x = [1., 0.] @@ -138,12 +151,52 @@ class LinearOperatorDiagTest( operator_matmul = operator.matmul(x) mat_matmul = math_ops.matmul(mat, x) self.assertAllEqual(operator_matmul.get_shape(), mat_matmul.get_shape()) - self.assertAllClose(*sess.run([operator_matmul, mat_matmul])) + self.assertAllClose(*self.evaluate([operator_matmul, mat_matmul])) operator_solve = operator.solve(x) mat_solve = linalg_ops.matrix_solve(mat, x) self.assertAllEqual(operator_solve.get_shape(), mat_solve.get_shape()) - self.assertAllClose(*sess.run([operator_solve, mat_solve])) + self.assertAllClose(*self.evaluate([operator_solve, mat_solve])) + + def test_diag_matmul(self): + operator1 = linalg_lib.LinearOperatorDiag([2., 3.]) + operator2 = linalg_lib.LinearOperatorDiag([1., 2.]) + operator3 = linalg_lib.LinearOperatorScaledIdentity( + num_rows=2, multiplier=3.) + operator_matmul = operator1.matmul(operator2) + self.assertTrue(isinstance( + operator_matmul, + linalg_lib.LinearOperatorDiag)) + self.assertAllClose([2., 6.], self.evaluate(operator_matmul.diag)) + + operator_matmul = operator2.matmul(operator1) + self.assertTrue(isinstance( + operator_matmul, + linalg_lib.LinearOperatorDiag)) + self.assertAllClose([2., 6.], self.evaluate(operator_matmul.diag)) + + operator_matmul = operator1.matmul(operator3) + self.assertTrue(isinstance( + operator_matmul, + linalg_lib.LinearOperatorDiag)) + self.assertAllClose([6., 9.], self.evaluate(operator_matmul.diag)) + + operator_matmul = operator3.matmul(operator1) + self.assertTrue(isinstance( + operator_matmul, + linalg_lib.LinearOperatorDiag)) + self.assertAllClose([6., 9.], self.evaluate(operator_matmul.diag)) + + def test_diag_cholesky_type(self): + diag = [1., 3., 5., 8.] + operator = linalg.LinearOperatorDiag( + diag, + is_positive_definite=True, + is_self_adjoint=True, + ) + self.assertTrue(isinstance( + operator.cholesky(), + linalg.LinearOperatorDiag)) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_full_matrix_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_full_matrix_test.py index 8c2d2cf077..aff0b1ae14 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_full_matrix_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_full_matrix_test.py @@ -20,6 +20,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops.linalg import linalg as linalg_lib @@ -33,7 +34,9 @@ class SquareLinearOperatorFullMatrixTest( linear_operator_test_util.SquareLinearOperatorDerivedClassTest): """Most tests done in the base class LinearOperatorDerivedClassTest.""" - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): shape = list(build_info.shape) matrix = linear_operator_test_util.random_positive_definite_matrix( @@ -44,7 +47,12 @@ class SquareLinearOperatorFullMatrixTest( if use_placeholder: lin_op_matrix = array_ops.placeholder_with_default(matrix, shape=None) - operator = linalg.LinearOperatorFullMatrix(lin_op_matrix, is_square=True) + # Set the hints to none to test non-symmetric PD code paths. + operator = linalg.LinearOperatorFullMatrix( + lin_op_matrix, + is_square=True, + is_self_adjoint=True if ensure_self_adjoint_and_pd else None, + is_positive_definite=True if ensure_self_adjoint_and_pd else None) return operator, matrix @@ -62,6 +70,7 @@ class SquareLinearOperatorFullMatrixTest( # Auto-detected. self.assertTrue(operator.is_square) + @test_util.run_deprecated_v1 def test_assert_non_singular_raises_if_cond_too_big_but_finite(self): with self.cached_session(): tril = linear_operator_test_util.random_tril_matrix( @@ -123,7 +132,13 @@ class SquareLinearOperatorFullMatrixSymmetricPositiveDefiniteTest( def _dtypes_to_test(self): return [dtypes.float32, dtypes.float64] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): + + # Matrix is always symmetric and positive definite in this class. + del ensure_self_adjoint_and_pd + shape = list(build_info.shape) matrix = linear_operator_test_util.random_positive_definite_matrix( @@ -134,7 +149,11 @@ class SquareLinearOperatorFullMatrixSymmetricPositiveDefiniteTest( if use_placeholder: lin_op_matrix = array_ops.placeholder_with_default(matrix, shape=None) - operator = linalg.LinearOperatorFullMatrix(lin_op_matrix, is_square=True) + operator = linalg.LinearOperatorFullMatrix( + lin_op_matrix, + is_square=True, + is_self_adjoint=True, + is_positive_definite=True) return operator, matrix diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_identity_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_identity_test.py index 465a8194dd..2da5e712d7 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_identity_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_identity_test.py @@ -20,8 +20,10 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import linalg_ops +from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops.linalg import linalg as linalg_lib from tensorflow.python.ops.linalg import linear_operator_test_util @@ -41,7 +43,12 @@ class LinearOperatorIdentityTest( # 16bit. return [dtypes.float32, dtypes.float64, dtypes.complex64, dtypes.complex128] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): + # Identity matrix is already Hermitian Positive Definite. + del ensure_self_adjoint_and_pd + shape = list(build_info.shape) assert shape[-1] == shape[-2] @@ -54,16 +61,19 @@ class LinearOperatorIdentityTest( return operator, mat + @test_util.run_deprecated_v1 def test_assert_positive_definite(self): with self.cached_session(): operator = linalg_lib.LinearOperatorIdentity(num_rows=2) operator.assert_positive_definite().run() # Should not fail + @test_util.run_deprecated_v1 def test_assert_non_singular(self): with self.cached_session(): operator = linalg_lib.LinearOperatorIdentity(num_rows=2) operator.assert_non_singular().run() # Should not fail + @test_util.run_deprecated_v1 def test_assert_self_adjoint(self): with self.cached_session(): operator = linalg_lib.LinearOperatorIdentity(num_rows=2) @@ -77,7 +87,7 @@ class LinearOperatorIdentityTest( num_rows=2, dtype=dtypes.float16) x = rng.randn(2, 3).astype(np.float16) y = operator.matmul(x) - self.assertAllClose(x, y.eval()) + self.assertAllClose(x, self.evaluate(y)) def test_non_scalar_num_rows_raises_static(self): with self.assertRaisesRegexp(ValueError, "must be a 0-D Tensor"): @@ -103,6 +113,7 @@ class LinearOperatorIdentityTest( with self.assertRaisesRegexp(ValueError, "must be non-negative"): linalg_lib.LinearOperatorIdentity(num_rows=2, batch_shape=[-2]) + @test_util.run_deprecated_v1 def test_non_scalar_num_rows_raises_dynamic(self): with self.cached_session(): num_rows = array_ops.placeholder(dtypes.int32) @@ -111,6 +122,7 @@ class LinearOperatorIdentityTest( with self.assertRaisesOpError("must be a 0-D Tensor"): operator.to_dense().eval(feed_dict={num_rows: [2]}) + @test_util.run_deprecated_v1 def test_negative_num_rows_raises_dynamic(self): with self.cached_session(): num_rows = array_ops.placeholder(dtypes.int32) @@ -119,6 +131,7 @@ class LinearOperatorIdentityTest( with self.assertRaisesOpError("must be non-negative"): operator.to_dense().eval(feed_dict={num_rows: -2}) + @test_util.run_deprecated_v1 def test_non_1d_batch_shape_raises_dynamic(self): with self.cached_session(): batch_shape = array_ops.placeholder(dtypes.int32) @@ -127,6 +140,7 @@ class LinearOperatorIdentityTest( with self.assertRaisesOpError("must be a 1-D"): operator.to_dense().eval(feed_dict={batch_shape: 2}) + @test_util.run_deprecated_v1 def test_negative_batch_shape_raises_dynamic(self): with self.cached_session(): batch_shape = array_ops.placeholder(dtypes.int32) @@ -141,6 +155,7 @@ class LinearOperatorIdentityTest( with self.assertRaisesRegexp(ValueError, "Dimensions.*not compatible"): operator.matmul(x) + @test_util.run_deprecated_v1 def test_wrong_matrix_dimensions_raises_dynamic(self): num_rows = array_ops.placeholder(dtypes.int32) x = array_ops.placeholder(dtypes.float32) @@ -164,8 +179,9 @@ class LinearOperatorIdentityTest( expected = x self.assertAllEqual(operator_matmul.get_shape(), expected.get_shape()) - self.assertAllClose(*sess.run([operator_matmul, expected])) + self.assertAllClose(*self.evaluate([operator_matmul, expected])) + @test_util.run_deprecated_v1 def test_default_batch_shape_broadcasts_with_everything_dynamic(self): # These cannot be done in the automated (base test class) tests since they # test shapes that tf.batch_matmul cannot handle. @@ -201,8 +217,9 @@ class LinearOperatorIdentityTest( operator_matmul = operator.matmul(x) self.assertAllEqual(operator_matmul.get_shape(), expected.get_shape()) - self.assertAllClose(*sess.run([operator_matmul, expected])) + self.assertAllClose(*self.evaluate([operator_matmul, expected])) + @test_util.run_deprecated_v1 def test_broadcast_matmul_dynamic_shapes(self): # These cannot be done in the automated (base test class) tests since they # test shapes that tf.batch_matmul cannot handle. @@ -242,6 +259,16 @@ class LinearOperatorIdentityTest( is_non_singular=None, ) + def test_identity_cholesky_type(self): + operator = linalg_lib.LinearOperatorIdentity( + num_rows=2, + is_positive_definite=True, + is_self_adjoint=True, + ) + self.assertTrue(isinstance( + operator.cholesky(), + linalg_lib.LinearOperatorIdentity)) + class LinearOperatorScaledIdentityTest( linear_operator_test_util.SquareLinearOperatorDerivedClassTest): @@ -253,7 +280,10 @@ class LinearOperatorScaledIdentityTest( # 16bit. return [dtypes.float32, dtypes.float64, dtypes.complex64, dtypes.complex128] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): + shape = list(build_info.shape) assert shape[-1] == shape[-2] @@ -266,6 +296,9 @@ class LinearOperatorScaledIdentityTest( multiplier = linear_operator_test_util.random_sign_uniform( shape=batch_shape, minval=1., maxval=2., dtype=dtype) + if ensure_self_adjoint_and_pd: + # Abs on complex64 will result in a float32, so we cast back up. + multiplier = math_ops.cast(math_ops.abs(multiplier), dtype=dtype) # Nothing to feed since LinearOperatorScaledIdentity takes no Tensor args. lin_op_multiplier = multiplier @@ -275,7 +308,10 @@ class LinearOperatorScaledIdentityTest( multiplier, shape=None) operator = linalg_lib.LinearOperatorScaledIdentity( - num_rows, lin_op_multiplier) + num_rows, + lin_op_multiplier, + is_self_adjoint=True if ensure_self_adjoint_and_pd else None, + is_positive_definite=True if ensure_self_adjoint_and_pd else None) multiplier_matrix = array_ops.expand_dims( array_ops.expand_dims(multiplier, -1), -1) @@ -284,6 +320,7 @@ class LinearOperatorScaledIdentityTest( return operator, matrix + @test_util.run_deprecated_v1 def test_assert_positive_definite_does_not_raise_when_positive(self): with self.cached_session(): operator = linalg_lib.LinearOperatorScaledIdentity( @@ -297,6 +334,7 @@ class LinearOperatorScaledIdentityTest( with self.assertRaisesOpError("not positive definite"): operator.assert_positive_definite().run() + @test_util.run_deprecated_v1 def test_assert_non_singular_does_not_raise_when_non_singular(self): with self.cached_session(): operator = linalg_lib.LinearOperatorScaledIdentity( @@ -310,6 +348,7 @@ class LinearOperatorScaledIdentityTest( with self.assertRaisesOpError("was singular"): operator.assert_non_singular().run() + @test_util.run_deprecated_v1 def test_assert_self_adjoint_does_not_raise_when_self_adjoint(self): with self.cached_session(): operator = linalg_lib.LinearOperatorScaledIdentity( @@ -332,7 +371,7 @@ class LinearOperatorScaledIdentityTest( num_rows=2, multiplier=multiplier) x = rng.randn(2, 3).astype(np.float16) y = operator.matmul(x) - self.assertAllClose(multiplier[..., None, None] * x, y.eval()) + self.assertAllClose(multiplier[..., None, None] * x, self.evaluate(y)) def test_non_scalar_num_rows_raises_static(self): # Many "test_...num_rows" tests are performed in LinearOperatorIdentity. @@ -347,6 +386,7 @@ class LinearOperatorScaledIdentityTest( with self.assertRaisesRegexp(ValueError, "Dimensions.*not compatible"): operator.matmul(x) + @test_util.run_deprecated_v1 def test_wrong_matrix_dimensions_raises_dynamic(self): num_rows = array_ops.placeholder(dtypes.int32) x = array_ops.placeholder(dtypes.float32) @@ -378,13 +418,13 @@ class LinearOperatorScaledIdentityTest( expected = x * 2.2 + zeros operator_matmul = operator.matmul(x) self.assertAllEqual(operator_matmul.get_shape(), expected.get_shape()) - self.assertAllClose(*sess.run([operator_matmul, expected])) + self.assertAllClose(*self.evaluate([operator_matmul, expected])) # Test solve expected = x / 2.2 + zeros operator_solve = operator.solve(x) self.assertAllEqual(operator_solve.get_shape(), expected.get_shape()) - self.assertAllClose(*sess.run([operator_solve, expected])) + self.assertAllClose(*self.evaluate([operator_solve, expected])) def test_broadcast_matmul_and_solve_scalar_scale_multiplier(self): # These cannot be done in the automated (base test class) tests since they @@ -404,13 +444,13 @@ class LinearOperatorScaledIdentityTest( expected = x * 2.2 operator_matmul = operator.matmul(x) self.assertAllEqual(operator_matmul.get_shape(), expected.get_shape()) - self.assertAllClose(*sess.run([operator_matmul, expected])) + self.assertAllClose(*self.evaluate([operator_matmul, expected])) # Test solve expected = x / 2.2 operator_solve = operator.solve(x) self.assertAllEqual(operator_solve.get_shape(), expected.get_shape()) - self.assertAllClose(*sess.run([operator_solve, expected])) + self.assertAllClose(*self.evaluate([operator_solve, expected])) def test_is_x_flags(self): operator = linalg_lib.LinearOperatorScaledIdentity( @@ -420,6 +460,41 @@ class LinearOperatorScaledIdentityTest( self.assertTrue(operator.is_non_singular) self.assertTrue(operator.is_self_adjoint is None) + def test_identity_matmul(self): + operator1 = linalg_lib.LinearOperatorIdentity(num_rows=2) + operator2 = linalg_lib.LinearOperatorScaledIdentity( + num_rows=2, multiplier=3.) + self.assertTrue(isinstance( + operator1.matmul(operator1), + linalg_lib.LinearOperatorIdentity)) + + self.assertTrue(isinstance( + operator1.matmul(operator1), + linalg_lib.LinearOperatorIdentity)) + + operator_matmul = operator1.matmul(operator2) + self.assertTrue(isinstance( + operator_matmul, + linalg_lib.LinearOperatorScaledIdentity)) + self.assertAllClose(3., self.evaluate(operator_matmul.multiplier)) + + operator_matmul = operator2.matmul(operator1) + self.assertTrue(isinstance( + operator_matmul, + linalg_lib.LinearOperatorScaledIdentity)) + self.assertAllClose(3., self.evaluate(operator_matmul.multiplier)) + + def test_scaled_identity_cholesky_type(self): + operator = linalg_lib.LinearOperatorScaledIdentity( + num_rows=2, + multiplier=3., + is_positive_definite=True, + is_self_adjoint=True, + ) + self.assertTrue(isinstance( + operator.cholesky(), + linalg_lib.LinearOperatorScaledIdentity)) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_inversion_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_inversion_test.py new file mode 100644 index 0000000000..9344c526ee --- /dev/null +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_inversion_test.py @@ -0,0 +1,130 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import dtypes +from tensorflow.python.ops import array_ops +from tensorflow.python.ops.linalg import linalg as linalg_lib +from tensorflow.python.ops.linalg import linear_operator_inversion +from tensorflow.python.ops.linalg import linear_operator_test_util +from tensorflow.python.platform import test + +linalg = linalg_lib + +LinearOperatorInversion = linear_operator_inversion.LinearOperatorInversion # pylint: disable=invalid-name + + +class LinearOperatorInversionTest( + linear_operator_test_util.SquareLinearOperatorDerivedClassTest): + """Most tests done in the base class LinearOperatorDerivedClassTest.""" + + def setUp(self): + self._atol[dtypes.complex64] = 1e-5 + self._rtol[dtypes.complex64] = 1e-5 + + def _operator_and_matrix(self, + build_info, + dtype, + use_placeholder, + ensure_self_adjoint_and_pd=False): + shape = list(build_info.shape) + + if ensure_self_adjoint_and_pd: + matrix = linear_operator_test_util.random_positive_definite_matrix( + shape, dtype, force_well_conditioned=True) + else: + matrix = linear_operator_test_util.random_tril_matrix( + shape, dtype, force_well_conditioned=True, remove_upper=True) + + lin_op_matrix = matrix + + if use_placeholder: + lin_op_matrix = array_ops.placeholder_with_default(matrix, shape=None) + + if ensure_self_adjoint_and_pd: + operator = LinearOperatorInversion( + linalg.LinearOperatorFullMatrix( + lin_op_matrix, is_positive_definite=True, is_self_adjoint=True)) + else: + operator = LinearOperatorInversion( + linalg.LinearOperatorLowerTriangular(lin_op_matrix)) + + return operator, linalg.inv(matrix) + + def test_base_operator_hint_used(self): + # The matrix values do not effect auto-setting of the flags. + matrix = [[1., 0.], [1., 1.]] + operator = linalg.LinearOperatorFullMatrix( + matrix, + is_positive_definite=True, + is_non_singular=True, + is_self_adjoint=False) + operator_inv = LinearOperatorInversion(operator) + self.assertTrue(operator_inv.is_positive_definite) + self.assertTrue(operator_inv.is_non_singular) + self.assertFalse(operator_inv.is_self_adjoint) + + def test_supplied_hint_used(self): + # The matrix values do not effect auto-setting of the flags. + matrix = [[1., 0.], [1., 1.]] + operator = linalg.LinearOperatorFullMatrix(matrix) + operator_inv = LinearOperatorInversion( + operator, + is_positive_definite=True, + is_non_singular=True, + is_self_adjoint=False) + self.assertTrue(operator_inv.is_positive_definite) + self.assertTrue(operator_inv.is_non_singular) + self.assertFalse(operator_inv.is_self_adjoint) + + def test_contradicting_hints_raise(self): + # The matrix values do not effect auto-setting of the flags. + matrix = [[1., 0.], [1., 1.]] + operator = linalg.LinearOperatorFullMatrix( + matrix, is_positive_definite=False) + with self.assertRaisesRegexp(ValueError, "positive-definite"): + LinearOperatorInversion(operator, is_positive_definite=True) + + operator = linalg.LinearOperatorFullMatrix(matrix, is_self_adjoint=False) + with self.assertRaisesRegexp(ValueError, "self-adjoint"): + LinearOperatorInversion(operator, is_self_adjoint=True) + + def test_singular_raises(self): + # The matrix values do not effect auto-setting of the flags. + matrix = [[1., 1.], [1., 1.]] + + operator = linalg.LinearOperatorFullMatrix(matrix, is_non_singular=False) + with self.assertRaisesRegexp(ValueError, "is_non_singular"): + LinearOperatorInversion(operator) + + operator = linalg.LinearOperatorFullMatrix(matrix) + with self.assertRaisesRegexp(ValueError, "is_non_singular"): + LinearOperatorInversion(operator, is_non_singular=False) + + def test_name(self): + matrix = [[11., 0.], [1., 8.]] + operator = linalg.LinearOperatorFullMatrix( + matrix, name="my_operator", is_non_singular=True) + + operator = LinearOperatorInversion(operator) + + self.assertEqual("my_operator_inv", operator.name) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_kronecker_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_kronecker_test.py index f039b60f64..513b246803 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_kronecker_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_kronecker_test.py @@ -21,9 +21,11 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops.linalg import linalg as linalg_lib from tensorflow.python.ops.linalg import linear_operator_kronecker as kronecker +from tensorflow.python.ops.linalg import linear_operator_lower_triangular as lower_triangular from tensorflow.python.ops.linalg import linear_operator_test_util from tensorflow.python.ops.linalg import linear_operator_util from tensorflow.python.platform import test @@ -52,6 +54,7 @@ def _kronecker_dense(factors): class KroneckerDenseTest(test.TestCase): + @test_util.run_deprecated_v1 def testKroneckerDenseMatrix(self): x = ops.convert_to_tensor([[2., 3.], [1., 2.]], dtype=dtypes.float32) y = ops.convert_to_tensor([[1., 2.], [5., -1.]], dtype=dtypes.float32) @@ -69,8 +72,8 @@ class KroneckerDenseTest(test.TestCase): [5., 10., -1., -2.]], dtype=dtypes.float32) with self.cached_session(): - self.assertAllClose(_kronecker_dense([x, y]).eval(), z.eval()) - self.assertAllClose(_kronecker_dense([y, x]).eval(), w.eval()) + self.assertAllClose(_kronecker_dense([x, y]).eval(), self.evaluate(z)) + self.assertAllClose(_kronecker_dense([y, x]).eval(), self.evaluate(w)) class SquareLinearOperatorKroneckerTest( @@ -99,7 +102,12 @@ class SquareLinearOperatorKroneckerTest( def _tests_to_skip(self): return ["det", "solve", "solve_with_broadcast"] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): + # Kronecker products constructed below will be from symmetric + # positive-definite matrices. + del ensure_self_adjoint_and_pd shape = list(build_info.shape) expected_factors = build_info.__dict__["factors"] matrices = [ @@ -116,7 +124,11 @@ class SquareLinearOperatorKroneckerTest( operator = kronecker.LinearOperatorKronecker( [linalg.LinearOperatorFullMatrix( - l, is_square=True) for l in lin_op_matrices]) + l, + is_square=True, + is_self_adjoint=True, + is_positive_definite=True) + for l in lin_op_matrices]) matrices = linear_operator_util.broadcast_matrix_batch_dims(matrices) @@ -180,6 +192,40 @@ class SquareLinearOperatorKroneckerTest( with self.assertRaisesRegexp(ValueError, ">=1 operators"): kronecker.LinearOperatorKronecker([]) + def test_kronecker_cholesky_type(self): + matrix = [[1., 0.], [0., 1.]] + operator = kronecker.LinearOperatorKronecker( + [ + linalg.LinearOperatorFullMatrix( + matrix, + is_positive_definite=True, + is_self_adjoint=True, + ), + linalg.LinearOperatorFullMatrix( + matrix, + is_positive_definite=True, + is_self_adjoint=True, + ), + ], + is_positive_definite=True, + is_self_adjoint=True, + ) + cholesky_factor = operator.cholesky() + self.assertTrue(isinstance( + cholesky_factor, + kronecker.LinearOperatorKronecker)) + self.assertEqual(2, len(cholesky_factor.operators)) + self.assertTrue( + isinstance( + cholesky_factor.operators[0], + lower_triangular.LinearOperatorLowerTriangular) + ) + self.assertTrue( + isinstance( + cholesky_factor.operators[1], + lower_triangular.LinearOperatorLowerTriangular) + ) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_low_rank_update_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_low_rank_update_test.py index 207e5edf81..2920f3ae7e 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_low_rank_update_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_low_rank_update_test.py @@ -69,7 +69,8 @@ class BaseLinearOperatorLowRankUpdatetest(object): return linear_operator_test_util.random_uniform( diag_shape, minval=1e-4, maxval=1., dtype=dtype) - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix(self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): # Recall A = L + UDV^H shape = list(build_info.shape) diag_shape = shape[:-1] @@ -93,7 +94,7 @@ class BaseLinearOperatorLowRankUpdatetest(object): lin_op_v = v # D - if self._is_diag_update_positive: + if self._is_diag_update_positive or ensure_self_adjoint_and_pd: diag_update = self._gen_positive_diag(dtype, diag_update_shape) else: diag_update = linear_operator_test_util.random_normal( @@ -178,6 +179,10 @@ class LinearOperatorLowRankUpdatetestWithDiagCannotUseCholesky( linear_operator_test_util.SquareLinearOperatorDerivedClassTest): """A = L + UDU^H, D !> 0, L > 0 ==> A !> 0 and we cannot use a Cholesky.""" + @property + def _tests_to_skip(self): + return ["cholesky"] + _use_diag_update = True _is_diag_update_positive = False _use_v = False @@ -217,6 +222,10 @@ class LinearOperatorLowRankUpdatetestNoDiagCannotUseCholesky( linear_operator_test_util.SquareLinearOperatorDerivedClassTest): """A = L + UV^H, L > 0 ==> A is not symmetric and we cannot use a Cholesky.""" + @property + def _tests_to_skip(self): + return ["cholesky"] + _use_diag_update = False _is_diag_update_positive = None _use_v = True diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_lower_triangular_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_lower_triangular_test.py index e3c8f5cb68..bd41f9ed9d 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_lower_triangular_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_lower_triangular_test.py @@ -18,6 +18,7 @@ from __future__ import division from __future__ import print_function from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops from tensorflow.python.ops.linalg import linalg as linalg_lib from tensorflow.python.ops.linalg import linear_operator_test_util from tensorflow.python.platform import test @@ -29,6 +30,11 @@ class LinearOperatorLowerTriangularTest( linear_operator_test_util.SquareLinearOperatorDerivedClassTest): """Most tests done in the base class LinearOperatorDerivedClassTest.""" + @property + def _tests_to_skip(self): + # Cholesky does not make sense for triangular matrices. + return ["cholesky"] + def _operator_and_matrix(self, build_info, dtype, use_placeholder): shape = list(build_info.shape) # Upper triangle will be nonzero, but ignored. @@ -71,6 +77,30 @@ class LinearOperatorLowerTriangularTest( with self.assertRaisesRegexp(ValueError, "at least 2 dimensions"): linalg.LinearOperatorLowerTriangular([1.]) + def test_triangular_diag_matmul(self): + operator1 = linalg_lib.LinearOperatorLowerTriangular( + [[1., 0., 0.], [2., 1., 0.], [2., 3., 3.]]) + operator2 = linalg_lib.LinearOperatorDiag([2., 2., 3.]) + operator_matmul = operator1.matmul(operator2) + self.assertTrue(isinstance( + operator_matmul, + linalg_lib.LinearOperatorLowerTriangular)) + self.assertAllClose( + math_ops.matmul( + operator1.to_dense(), + operator2.to_dense()), + self.evaluate(operator_matmul.to_dense())) + + operator_matmul = operator2.matmul(operator1) + self.assertTrue(isinstance( + operator_matmul, + linalg_lib.LinearOperatorLowerTriangular)) + self.assertAllClose( + math_ops.matmul( + operator2.to_dense(), + operator1.to_dense()), + self.evaluate(operator_matmul.to_dense())) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_test.py index 819347343b..8f8b15e8ed 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_test.py @@ -22,6 +22,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import linalg_ops from tensorflow.python.ops import math_ops @@ -107,6 +108,7 @@ class LinearOperatorTest(test.TestCase): self.assertAllEqual(4, operator.domain_dimension) self.assertAllEqual(3, operator.range_dimension) + @test_util.run_deprecated_v1 def test_all_shape_methods_defined_by_the_one_method_shape(self): with self.cached_session(): shape = (1, 2, 3, 4) @@ -134,8 +136,9 @@ class LinearOperatorTest(test.TestCase): with self.cached_session(): operator_dense = operator.to_dense() self.assertAllEqual((2, 3, 4), operator_dense.get_shape()) - self.assertAllClose(matrix, operator_dense.eval()) + self.assertAllClose(matrix, self.evaluate(operator_dense)) + @test_util.run_deprecated_v1 def test_generic_to_dense_method_non_square_matrix_tensor(self): matrix = rng.randn(2, 3, 4) matrix_ph = array_ops.placeholder(dtypes.float64) @@ -152,7 +155,7 @@ class LinearOperatorTest(test.TestCase): with self.cached_session(): y = operator.matvec(x) self.assertAllEqual((2,), y.get_shape()) - self.assertAllClose([1., 2.], y.eval()) + self.assertAllClose([1., 2.], self.evaluate(y)) def test_solvevec(self): matrix = [[1., 0], [0., 2.]] @@ -161,7 +164,7 @@ class LinearOperatorTest(test.TestCase): with self.cached_session(): x = operator.solvevec(y) self.assertAllEqual((2,), x.get_shape()) - self.assertAllClose([1., 1 / 2.], x.eval()) + self.assertAllClose([1., 1 / 2.], self.evaluate(x)) def test_is_square_set_to_true_for_square_static_shapes(self): operator = LinearOperatorShape(shape=(2, 4, 4)) @@ -175,6 +178,7 @@ class LinearOperatorTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "but.*was square"): _ = LinearOperatorShape(shape=(2, 4, 4), is_square=False).is_square + @test_util.run_deprecated_v1 def test_is_square_set_inconsistent_with_other_hints_raises(self): with self.assertRaisesRegexp(ValueError, "is always square"): matrix = array_ops.placeholder(dtypes.float32) @@ -185,6 +189,7 @@ class LinearOperatorTest(test.TestCase): LinearOperatorMatmulSolve( matrix, is_positive_definite=True, is_square=False) + @test_util.run_deprecated_v1 def test_non_square_operators_raise_on_determinant_and_solve(self): operator = LinearOperatorShape((2, 3)) with self.assertRaisesRegexp(NotImplementedError, "not be square"): @@ -199,6 +204,7 @@ class LinearOperatorTest(test.TestCase): LinearOperatorMatmulSolve( matrix, is_positive_definite=True, is_square=False) + @test_util.run_deprecated_v1 def test_is_square_manual_set_works(self): matrix = array_ops.placeholder(dtypes.float32) # Default is None. @@ -208,6 +214,80 @@ class LinearOperatorTest(test.TestCase): operator = LinearOperatorMatmulSolve(matrix, is_square=True) self.assertTrue(operator.is_square) + @test_util.run_deprecated_v1 + def test_linear_operator_matmul_hints_closed(self): + matrix = array_ops.placeholder(dtypes.float32) + operator1 = LinearOperatorMatmulSolve(matrix) + + operator_matmul = operator1.matmul(operator1) + + self.assertEqual(None, operator_matmul.is_square) + self.assertEqual(None, operator_matmul.is_non_singular) + self.assertEqual(None, operator_matmul.is_self_adjoint) + self.assertEqual(None, operator_matmul.is_positive_definite) + + operator2 = LinearOperatorMatmulSolve( + matrix, + is_non_singular=True, + is_self_adjoint=True, + is_positive_definite=True, + is_square=True, + ) + + operator_matmul = operator2.matmul(operator2) + + self.assertTrue(operator_matmul.is_square) + self.assertTrue(operator_matmul.is_non_singular) + self.assertTrue(operator_matmul.is_self_adjoint) + self.assertEqual(None, operator_matmul.is_positive_definite) + + @test_util.run_deprecated_v1 + def test_linear_operator_matmul_hints_false(self): + matrix = array_ops.placeholder(dtypes.float32) + operator1 = LinearOperatorMatmulSolve( + matrix, + is_non_singular=False, + is_self_adjoint=False, + is_positive_definite=False, + is_square=True, + ) + + operator_matmul = operator1.matmul(operator1) + + self.assertTrue(operator_matmul.is_square) + self.assertFalse(operator_matmul.is_non_singular) + self.assertEqual(None, operator_matmul.is_self_adjoint) + self.assertEqual(None, operator_matmul.is_positive_definite) + + operator2 = LinearOperatorMatmulSolve( + matrix, + is_non_singular=False, + is_self_adjoint=False, + is_positive_definite=False, + is_square=False, + ) + + operator_matmul = operator2.matmul(operator2) + + self.assertEqual(None, operator_matmul.is_square) + self.assertEqual(None, operator_matmul.is_non_singular) + self.assertEqual(None, operator_matmul.is_self_adjoint) + self.assertEqual(None, operator_matmul.is_positive_definite) + + @test_util.run_deprecated_v1 + def test_linear_operator_matmul_hint_infer_square(self): + matrix1 = array_ops.placeholder(shape=[2, 3], dtype=dtypes.float32) + matrix2 = array_ops.placeholder(shape=[3, 2], dtype=dtypes.float32) + matrix3 = array_ops.placeholder(shape=[3, 4], dtype=dtypes.float32) + + operator1 = LinearOperatorMatmulSolve(matrix1, is_square=False) + operator2 = LinearOperatorMatmulSolve(matrix2, is_square=False) + operator3 = LinearOperatorMatmulSolve(matrix3, is_square=False) + + self.assertTrue(operator1.matmul(operator2).is_square) + self.assertTrue(operator2.matmul(operator1).is_square) + self.assertFalse(operator1.matmul(operator3).is_square) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_util_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_util_test.py index 31fb19e4a6..d1e6c37e35 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_util_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_util_test.py @@ -21,6 +21,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import linalg_ops from tensorflow.python.ops import math_ops @@ -32,12 +33,14 @@ rng = np.random.RandomState(0) class AssertZeroImagPartTest(test.TestCase): + @test_util.run_deprecated_v1 def test_real_tensor_doesnt_raise(self): x = ops.convert_to_tensor([0., 2, 3]) with self.cached_session(): # Should not raise. linear_operator_util.assert_zero_imag_part(x, message="ABC123").run() + @test_util.run_deprecated_v1 def test_complex_tensor_with_imag_zero_doesnt_raise(self): x = ops.convert_to_tensor([1., 0, 3]) y = ops.convert_to_tensor([0., 0, 0]) @@ -57,6 +60,7 @@ class AssertZeroImagPartTest(test.TestCase): class AssertNoEntriesWithModulusZeroTest(test.TestCase): + @test_util.run_deprecated_v1 def test_nonzero_real_tensor_doesnt_raise(self): x = ops.convert_to_tensor([1., 2, 3]) with self.cached_session(): @@ -64,6 +68,7 @@ class AssertNoEntriesWithModulusZeroTest(test.TestCase): linear_operator_util.assert_no_entries_with_modulus_zero( x, message="ABC123").run() + @test_util.run_deprecated_v1 def test_nonzero_complex_tensor_doesnt_raise(self): x = ops.convert_to_tensor([1., 0, 3]) y = ops.convert_to_tensor([1., 2, 0]) @@ -102,8 +107,9 @@ class BroadcastMatrixBatchDimsTest(test.TestCase): self.assertTrue(isinstance(tensor, ops.Tensor)) with self.cached_session(): - self.assertAllClose(arr, tensor.eval()) + self.assertAllClose(arr, self.evaluate(tensor)) + @test_util.run_deprecated_v1 def test_static_dims_broadcast(self): # x.batch_shape = [3, 1, 2] # y.batch_shape = [4, 1] @@ -119,7 +125,7 @@ class BroadcastMatrixBatchDimsTest(test.TestCase): with self.cached_session() as sess: self.assertAllEqual(x_bc_expected.shape, x_bc.get_shape()) self.assertAllEqual(y_bc_expected.shape, y_bc.get_shape()) - x_bc_, y_bc_ = sess.run([x_bc, y_bc]) + x_bc_, y_bc_ = self.evaluate([x_bc, y_bc]) self.assertAllClose(x_bc_expected, x_bc_) self.assertAllClose(y_bc_expected, y_bc_) @@ -138,10 +144,11 @@ class BroadcastMatrixBatchDimsTest(test.TestCase): with self.cached_session() as sess: self.assertAllEqual(x_bc_expected.shape, x_bc.get_shape()) self.assertAllEqual(y_bc_expected.shape, y_bc.get_shape()) - x_bc_, y_bc_ = sess.run([x_bc, y_bc]) + x_bc_, y_bc_ = self.evaluate([x_bc, y_bc]) self.assertAllClose(x_bc_expected, x_bc_) self.assertAllClose(y_bc_expected, y_bc_) + @test_util.run_deprecated_v1 def test_dynamic_dims_broadcast_32bit(self): # x.batch_shape = [3, 1, 2] # y.batch_shape = [4, 1] @@ -162,6 +169,7 @@ class BroadcastMatrixBatchDimsTest(test.TestCase): self.assertAllClose(x_bc_expected, x_bc_) self.assertAllClose(y_bc_expected, y_bc_) + @test_util.run_deprecated_v1 def test_dynamic_dims_broadcast_32bit_second_arg_higher_rank(self): # x.batch_shape = [1, 2] # y.batch_shape = [3, 4, 1] @@ -195,6 +203,7 @@ class BroadcastMatrixBatchDimsTest(test.TestCase): class CholeskySolveWithBroadcastTest(test.TestCase): + @test_util.run_deprecated_v1 def test_static_dims_broadcast(self): # batch_shape = [2] chol = rng.rand(3, 3) @@ -205,8 +214,9 @@ class CholeskySolveWithBroadcastTest(test.TestCase): result = linear_operator_util.cholesky_solve_with_broadcast(chol, rhs) self.assertAllEqual((2, 3, 7), result.get_shape()) expected = linalg_ops.cholesky_solve(chol_broadcast, rhs) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_dynamic_dims_broadcast_64bit(self): # batch_shape = [2, 2] chol = rng.rand(2, 3, 3) @@ -233,6 +243,7 @@ class CholeskySolveWithBroadcastTest(test.TestCase): class MatmulWithBroadcastTest(test.TestCase): + @test_util.run_deprecated_v1 def test_static_dims_broadcast_x_has_extra_dims(self): # batch_shape = [2] # for each batch member, we have a 1x3 matrix times a 3x7 matrix ==> 1x7 @@ -244,8 +255,9 @@ class MatmulWithBroadcastTest(test.TestCase): result = linear_operator_util.matmul_with_broadcast(x, y) self.assertAllEqual((2, 1, 7), result.get_shape()) expected = math_ops.matmul(x, y_broadcast) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_static_dims_broadcast_y_has_extra_dims(self): # Since the second arg has extra dims, and the domain dim of the first arg # is larger than the number of linear equations, code will "flip" the extra @@ -261,8 +273,9 @@ class MatmulWithBroadcastTest(test.TestCase): result = linear_operator_util.matmul_with_broadcast(x, y) self.assertAllEqual((2, 3, 5, 5), result.get_shape()) expected = math_ops.matmul(x_broadcast, y) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_static_dims_broadcast_y_has_extra_dims_transpose_a_and_b(self): # Since the second arg has extra dims, and the domain dim of the first arg # is larger than the number of linear equations, code will "flip" the extra @@ -280,8 +293,9 @@ class MatmulWithBroadcastTest(test.TestCase): self.assertAllEqual((2, 3, 5, 1), result.get_shape()) expected = math_ops.matmul( x_broadcast, y, transpose_a=True, transpose_b=True) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_static_dims_broadcast_y_has_extra_dims_transpose_dynamic(self): # Since the second arg has extra dims, and the domain dim of the first arg # is larger than the number of linear equations, code will "flip" the extra @@ -308,6 +322,7 @@ class MatmulWithBroadcastTest(test.TestCase): y_ph: y })) + @test_util.run_deprecated_v1 def test_dynamic_dims_broadcast_64bit(self): # batch_shape = [2] # for each batch member, we have a 1x3 matrix times a 3x7 matrix ==> 1x7 @@ -333,6 +348,7 @@ class MatmulWithBroadcastTest(test.TestCase): class MatrixSolveWithBroadcastTest(test.TestCase): + @test_util.run_deprecated_v1 def test_static_dims_broadcast_matrix_has_extra_dims(self): # batch_shape = [2] matrix = rng.rand(2, 3, 3) @@ -344,8 +360,9 @@ class MatrixSolveWithBroadcastTest(test.TestCase): matrix, rhs) self.assertAllEqual((2, 3, 7), result.get_shape()) expected = linalg_ops.matrix_solve(matrix, rhs_broadcast) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_static_dims_broadcast_rhs_has_extra_dims(self): # Since the second arg has extra dims, and the domain dim of the first arg # is larger than the number of linear equations, code will "flip" the extra @@ -362,8 +379,9 @@ class MatrixSolveWithBroadcastTest(test.TestCase): result = linear_operator_util.matrix_solve_with_broadcast(matrix, rhs) self.assertAllEqual((2, 3, 2), result.get_shape()) expected = linalg_ops.matrix_solve(matrix_broadcast, rhs) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_static_dims_broadcast_rhs_has_extra_dims_dynamic(self): # Since the second arg has extra dims, and the domain dim of the first arg # is larger than the number of linear equations, code will "flip" the extra @@ -385,12 +403,13 @@ class MatrixSolveWithBroadcastTest(test.TestCase): self.assertAllEqual(3, result.shape.ndims) expected = linalg_ops.matrix_solve(matrix_broadcast, rhs) self.assertAllClose( - expected.eval(), + self.evaluate(expected), result.eval(feed_dict={ matrix_ph: matrix, rhs_ph: rhs })) + @test_util.run_deprecated_v1 def test_static_dims_broadcast_rhs_has_extra_dims_and_adjoint(self): # Since the second arg has extra dims, and the domain dim of the first arg # is larger than the number of linear equations, code will "flip" the extra @@ -408,8 +427,9 @@ class MatrixSolveWithBroadcastTest(test.TestCase): matrix, rhs, adjoint=True) self.assertAllEqual((2, 3, 2), result.get_shape()) expected = linalg_ops.matrix_solve(matrix_broadcast, rhs, adjoint=True) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_dynamic_dims_broadcast_64bit(self): # batch_shape = [2, 2] matrix = rng.rand(2, 3, 3) @@ -436,6 +456,7 @@ class MatrixSolveWithBroadcastTest(test.TestCase): class MatrixTriangularSolveWithBroadcastTest(test.TestCase): + @test_util.run_deprecated_v1 def test_static_dims_broadcast_matrix_has_extra_dims(self): # batch_shape = [2] matrix = rng.rand(2, 3, 3) @@ -447,8 +468,9 @@ class MatrixTriangularSolveWithBroadcastTest(test.TestCase): matrix, rhs) self.assertAllEqual((2, 3, 7), result.get_shape()) expected = linalg_ops.matrix_triangular_solve(matrix, rhs_broadcast) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_static_dims_broadcast_rhs_has_extra_dims(self): # Since the second arg has extra dims, and the domain dim of the first arg # is larger than the number of linear equations, code will "flip" the extra @@ -466,8 +488,9 @@ class MatrixTriangularSolveWithBroadcastTest(test.TestCase): matrix, rhs) self.assertAllEqual((2, 3, 2), result.get_shape()) expected = linalg_ops.matrix_triangular_solve(matrix_broadcast, rhs) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_static_dims_broadcast_rhs_has_extra_dims_and_adjoint(self): # Since the second arg has extra dims, and the domain dim of the first arg # is larger than the number of linear equations, code will "flip" the extra @@ -486,8 +509,9 @@ class MatrixTriangularSolveWithBroadcastTest(test.TestCase): self.assertAllEqual((2, 3, 2), result.get_shape()) expected = linalg_ops.matrix_triangular_solve( matrix_broadcast, rhs, adjoint=True) - self.assertAllClose(expected.eval(), result.eval()) + self.assertAllClose(expected.eval(), self.evaluate(result)) + @test_util.run_deprecated_v1 def test_dynamic_dims_broadcast_64bit(self): # batch_shape = [2] matrix = rng.rand(2, 3, 3) @@ -522,6 +546,7 @@ class DomainDimensionStubOperator(object): class AssertCompatibleMatrixDimensionsTest(test.TestCase): + @test_util.run_deprecated_v1 def test_compatible_dimensions_do_not_raise(self): with self.cached_session(): x = ops.convert_to_tensor(rng.rand(2, 3, 4)) diff --git a/tensorflow/python/kernel_tests/linalg/linear_operator_zeros_test.py b/tensorflow/python/kernel_tests/linalg/linear_operator_zeros_test.py index ad97d1a93e..eb0b8ef127 100644 --- a/tensorflow/python/kernel_tests/linalg/linear_operator_zeros_test.py +++ b/tensorflow/python/kernel_tests/linalg/linear_operator_zeros_test.py @@ -20,6 +20,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops.linalg import linalg as linalg_lib from tensorflow.python.ops.linalg import linear_operator_test_util @@ -35,7 +36,7 @@ class LinearOperatorZerosTest( @property def _tests_to_skip(self): - return ["log_abs_det", "solve", "solve_with_broadcast"] + return ["cholesky", "log_abs_det", "solve", "solve_with_broadcast"] @property def _operator_build_infos(self): @@ -46,7 +47,10 @@ class LinearOperatorZerosTest( build_info((3, 4, 4)), build_info((2, 1, 4, 4))] - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): + del ensure_self_adjoint_and_pd del use_placeholder shape = list(build_info.shape) assert shape[-1] == shape[-2] @@ -70,6 +74,7 @@ class LinearOperatorZerosTest( operator = linalg_lib.LinearOperatorZeros(num_rows=2) operator.assert_non_singular() + @test_util.run_deprecated_v1 def test_assert_self_adjoint(self): with self.cached_session(): operator = linalg_lib.LinearOperatorZeros(num_rows=2) @@ -105,6 +110,7 @@ class LinearOperatorZerosTest( with self.assertRaisesRegexp(ValueError, "must be non-negative"): linalg_lib.LinearOperatorZeros(num_rows=2, batch_shape=[-2]) + @test_util.run_deprecated_v1 def test_non_scalar_num_rows_raises_dynamic(self): with self.cached_session(): num_rows = array_ops.placeholder(dtypes.int32) @@ -113,6 +119,7 @@ class LinearOperatorZerosTest( with self.assertRaisesOpError("must be a 0-D Tensor"): operator.to_dense().eval(feed_dict={num_rows: [2]}) + @test_util.run_deprecated_v1 def test_negative_num_rows_raises_dynamic(self): with self.cached_session(): n = array_ops.placeholder(dtypes.int32) @@ -126,6 +133,7 @@ class LinearOperatorZerosTest( with self.assertRaisesOpError("must be non-negative"): operator.to_dense().eval(feed_dict={n: -2}) + @test_util.run_deprecated_v1 def test_non_1d_batch_shape_raises_dynamic(self): with self.cached_session(): batch_shape = array_ops.placeholder(dtypes.int32) @@ -134,6 +142,7 @@ class LinearOperatorZerosTest( with self.assertRaisesOpError("must be a 1-D"): operator.to_dense().eval(feed_dict={batch_shape: 2}) + @test_util.run_deprecated_v1 def test_negative_batch_shape_raises_dynamic(self): with self.cached_session(): batch_shape = array_ops.placeholder(dtypes.int32) @@ -148,6 +157,7 @@ class LinearOperatorZerosTest( with self.assertRaisesRegexp(ValueError, "Dimensions.*not compatible"): operator.matmul(x) + @test_util.run_deprecated_v1 def test_wrong_matrix_dimensions_raises_dynamic(self): num_rows = array_ops.placeholder(dtypes.int32) x = array_ops.placeholder(dtypes.float32) @@ -166,6 +176,17 @@ class LinearOperatorZerosTest( self.assertFalse(operator.is_non_singular) self.assertTrue(operator.is_self_adjoint) + def test_zeros_matmul(self): + operator1 = linalg_lib.LinearOperatorIdentity(num_rows=2) + operator2 = linalg_lib.LinearOperatorZeros(num_rows=2) + self.assertTrue(isinstance( + operator1.matmul(operator2), + linalg_lib.LinearOperatorZeros)) + + self.assertTrue(isinstance( + operator2.matmul(operator1), + linalg_lib.LinearOperatorZeros)) + class LinearOperatorZerosNotSquareTest( linear_operator_test_util.NonSquareLinearOperatorDerivedClassTest): diff --git a/tensorflow/python/kernel_tests/linalg_grad_test.py b/tensorflow/python/kernel_tests/linalg_grad_test.py index 03b640a85a..28e1d7e168 100644 --- a/tensorflow/python/kernel_tests/linalg_grad_test.py +++ b/tensorflow/python/kernel_tests/linalg_grad_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl @@ -39,6 +40,7 @@ def _AddTest(test, op_name, testcase_name, fn): class ShapeTest(test_lib.TestCase): + @test_util.run_deprecated_v1 def testBatchGradientUnknownSize(self): with self.cached_session(): batch_size = constant_op.constant(3) @@ -50,7 +52,7 @@ class ShapeTest(test_lib.TestCase): determinants = linalg_ops.matrix_determinant(batch_identity) reduced = math_ops.reduce_sum(determinants) sum_grad = gradients_impl.gradients(reduced, batch_identity)[0] - self.assertAllClose(batch_identity.eval(), sum_grad.eval()) + self.assertAllClose(batch_identity.eval(), self.evaluate(sum_grad)) class MatrixUnaryFunctorGradientTest(test_lib.TestCase): @@ -69,7 +71,7 @@ def _GetMatrixUnaryFunctorGradientTest(functor_, dtype_, shape_, **kwargs_): if functor_.__name__ == 'matrix_square_root': # Square the input matrix to ensure that its matrix square root exists a = math_ops.matmul(a, a) - a_np = a.eval() + a_np = self.evaluate(a) b = functor_(a, **kwargs_) # Optimal stepsize for central difference is O(epsilon^{1/3}). diff --git a/tensorflow/python/kernel_tests/linalg_ops_test.py b/tensorflow/python/kernel_tests/linalg_ops_test.py index 28391aaa87..028167a786 100644 --- a/tensorflow/python/kernel_tests/linalg_ops_test.py +++ b/tensorflow/python/kernel_tests/linalg_ops_test.py @@ -25,6 +25,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import linalg_ops from tensorflow.python.ops import math_ops @@ -52,6 +53,7 @@ class CholeskySolveTest(test.TestCase): def setUp(self): self.rng = np.random.RandomState(0) + @test_util.run_deprecated_v1 def test_works_with_five_different_random_pos_def_matrices(self): for n in range(1, 6): for np_type, atol in [(np.float32, 0.05), (np.float64, 1e-5)]: @@ -73,6 +75,7 @@ class LogdetTest(test.TestCase): def setUp(self): self.rng = np.random.RandomState(42) + @test_util.run_deprecated_v1 def test_works_with_five_different_random_pos_def_matrices(self): for n in range(1, 6): for np_dtype, atol in [(np.float32, 0.05), (np.float64, 1e-5), @@ -85,7 +88,7 @@ class LogdetTest(test.TestCase): # [_RandomPDMatrix(n, self.rng, np_dtype), # _RandomPDMatrix(n, self.rng, np_dtype)]).astype(np_dtype) logdet_tf = linalg.logdet(matrix) - self.assertAllClose(logdet_np, logdet_tf.eval(), atol=atol) + self.assertAllClose(logdet_np, self.evaluate(logdet_tf), atol=atol) def test_works_with_underflow_case(self): for np_dtype, atol in [(np.float32, 0.05), (np.float64, 1e-5), @@ -94,7 +97,7 @@ class LogdetTest(test.TestCase): _, logdet_np = np.linalg.slogdet(matrix) with self.session(use_gpu=True): logdet_tf = linalg.logdet(matrix) - self.assertAllClose(logdet_np, logdet_tf.eval(), atol=atol) + self.assertAllClose(logdet_np, self.evaluate(logdet_tf), atol=atol) class SlogdetTest(test.TestCase): @@ -102,6 +105,7 @@ class SlogdetTest(test.TestCase): def setUp(self): self.rng = np.random.RandomState(42) + @test_util.run_deprecated_v1 def test_works_with_five_different_random_pos_def_matrices(self): for n in range(1, 6): for np_dtype, atol in [(np.float32, 0.05), (np.float64, 1e-5), @@ -110,8 +114,9 @@ class SlogdetTest(test.TestCase): sign_np, log_abs_det_np = np.linalg.slogdet(matrix) with self.session(use_gpu=True): sign_tf, log_abs_det_tf = linalg.slogdet(matrix) - self.assertAllClose(log_abs_det_np, log_abs_det_tf.eval(), atol=atol) - self.assertAllClose(sign_np, sign_tf.eval(), atol=atol) + self.assertAllClose( + log_abs_det_np, self.evaluate(log_abs_det_tf), atol=atol) + self.assertAllClose(sign_np, self.evaluate(sign_tf), atol=atol) def test_works_with_underflow_case(self): for np_dtype, atol in [(np.float32, 0.05), (np.float64, 1e-5), @@ -120,8 +125,9 @@ class SlogdetTest(test.TestCase): sign_np, log_abs_det_np = np.linalg.slogdet(matrix) with self.session(use_gpu=True): sign_tf, log_abs_det_tf = linalg.slogdet(matrix) - self.assertAllClose(log_abs_det_np, log_abs_det_tf.eval(), atol=atol) - self.assertAllClose(sign_np, sign_tf.eval(), atol=atol) + self.assertAllClose( + log_abs_det_np, self.evaluate(log_abs_det_tf), atol=atol) + self.assertAllClose(sign_np, self.evaluate(sign_tf), atol=atol) class AdjointTest(test.TestCase): @@ -135,7 +141,7 @@ class AdjointTest(test.TestCase): matrix = ops.convert_to_tensor(matrix_np) transposed = linalg.adjoint(matrix) self.assertEqual((3, 2), transposed.get_shape()) - self.assertAllEqual(expected_transposed, transposed.eval()) + self.assertAllEqual(expected_transposed, self.evaluate(transposed)) class EyeTest(parameterized.TestCase, test.TestCase): @@ -230,6 +236,7 @@ class EyeTest(parameterized.TestCase, test.TestCase): dtypes.complex128 ]) ) + @test_util.run_deprecated_v1 def test_eye_with_placeholder( self, num_rows, num_columns, batch_shape, dtype): eye_np = np.eye(num_rows, M=num_columns, dtype=dtype.as_numpy_dtype) diff --git a/tensorflow/python/kernel_tests/list_ops_test.py b/tensorflow/python/kernel_tests/list_ops_test.py index 92552854aa..489f6c9b00 100644 --- a/tensorflow/python/kernel_tests/list_ops_test.py +++ b/tensorflow/python/kernel_tests/list_ops_test.py @@ -29,9 +29,11 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import list_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import state_ops @@ -39,17 +41,13 @@ from tensorflow.python.ops import variable_scope as vs from tensorflow.python.platform import test -def scalar_shape(): - return ops.convert_to_tensor([], dtype=dtypes.int32) - - @test_util.run_all_in_graph_and_eager_modes class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def _testPushPop(self, max_num_elements): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=scalar_shape(), + element_shape=[], max_num_elements=max_num_elements) l = list_ops.tensor_list_push_back(l, constant_op.constant(1.0)) l, e = list_ops.tensor_list_pop_back(l, element_dtype=dtypes.float32) @@ -68,11 +66,10 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with context.device("gpu:0"): self._testPushPop(max_num_elements) + @test_util.run_deprecated_v1 def testPushInFullListFails(self): l = list_ops.empty_tensor_list( - element_dtype=dtypes.float32, - element_shape=scalar_shape(), - max_num_elements=1) + element_dtype=dtypes.float32, element_shape=[], max_num_elements=1) l = list_ops.tensor_list_push_back(l, constant_op.constant(1.0)) with self.assertRaisesRegexp(errors.InvalidArgumentError, "Tried to push item into a full list"): @@ -81,10 +78,11 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): @parameterized.named_parameters(("NoMaxNumElements", None), ("WithMaxNumElements", 2)) + @test_util.run_deprecated_v1 def testPopFromEmptyTensorListFails(self, max_num_elements): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=scalar_shape(), + element_shape=[], max_num_elements=max_num_elements) with self.assertRaisesRegexp(errors.InvalidArgumentError, "Trying to pop from an empty list"): @@ -94,11 +92,13 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def _testStack(self, max_num_elements): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=scalar_shape(), + element_shape=[], max_num_elements=max_num_elements) l = list_ops.tensor_list_push_back(l, constant_op.constant(1.0)) l = list_ops.tensor_list_push_back(l, constant_op.constant(2.0)) t = list_ops.tensor_list_stack(l, element_dtype=dtypes.float32) + if not context.executing_eagerly(): + self.assertAllEqual(t.shape.as_list(), [None]) self.assertAllEqual(self.evaluate(t), [1.0, 2.0]) @parameterized.named_parameters(("NoMaxNumElements", None), @@ -116,10 +116,11 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): @parameterized.named_parameters(("NoMaxNumElements", None), ("WithMaxNumElements", 3)) + @test_util.run_deprecated_v1 def testStackWithUnknownElementShape(self, max_num_elements): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=-1, + element_shape=None, max_num_elements=max_num_elements) l = list_ops.tensor_list_push_back(l, constant_op.constant(1.0)) l = list_ops.tensor_list_push_back(l, constant_op.constant(2.0)) @@ -136,10 +137,11 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): @parameterized.named_parameters(("NoMaxNumElements", None), ("WithMaxNumElements", 3)) + @test_util.run_deprecated_v1 def testStackWithPartiallyDefinedElementShape(self, max_num_elements): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=[-1], + element_shape=[None], max_num_elements=max_num_elements) l = list_ops.tensor_list_push_back(l, constant_op.constant([1.0])) l = list_ops.tensor_list_push_back(l, constant_op.constant([2.0])) @@ -156,6 +158,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): @parameterized.named_parameters(("NoMaxNumElements", None), ("WithMaxNumElements", 2)) + @test_util.run_deprecated_v1 def testStackEmptyList(self, max_num_elements): # Should be able to stack empty lists with fully defined element_shape. l = list_ops.empty_tensor_list( @@ -171,7 +174,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): "non-fully-defined"): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=[-1, 2], + element_shape=[None, 2], max_num_elements=max_num_elements) t = list_ops.tensor_list_stack(l, element_dtype=dtypes.float32) self.evaluate(t) @@ -181,7 +184,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): "non-fully-defined"): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=-1, + element_shape=None, max_num_elements=max_num_elements) t = list_ops.tensor_list_stack(l, element_dtype=dtypes.float32) self.evaluate(t) @@ -192,7 +195,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with backprop.GradientTape() as tape: l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=scalar_shape(), + element_shape=[], max_num_elements=max_num_elements) c0 = constant_op.constant(1.0) tape.watch(c0) @@ -206,10 +209,11 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): @parameterized.named_parameters(("NoMaxNumElements", None), ("WithMaxNumElements", 3)) + @test_util.run_deprecated_v1 def testGatherWithUnknownElementShape(self, max_num_elements): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=-1, + element_shape=None, max_num_elements=max_num_elements) l = list_ops.tensor_list_push_back(l, constant_op.constant(1.0)) l = list_ops.tensor_list_push_back(l, constant_op.constant(2.0)) @@ -229,10 +233,11 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): @parameterized.named_parameters(("NoMaxNumElements", None), ("WithMaxNumElements", 3)) + @test_util.run_deprecated_v1 def testGatherWithPartiallyDefinedElementShape(self, max_num_elements): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=[-1], + element_shape=[None], max_num_elements=max_num_elements) l = list_ops.tensor_list_push_back(l, constant_op.constant([1.0])) l = list_ops.tensor_list_push_back(l, constant_op.constant([2.0, 3.0])) @@ -252,6 +257,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): @parameterized.named_parameters(("NoMaxNumElements", None), ("WithMaxNumElements", 3)) + @test_util.run_deprecated_v1 def testGatherEmptyList(self, max_num_elements): # Should be able to gather from empty lists with fully defined # element_shape. @@ -268,7 +274,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): "non-fully-defined"): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=[-1, 2], + element_shape=[None, 2], max_num_elements=max_num_elements) t = list_ops.tensor_list_gather(l, [], element_dtype=dtypes.float32) self.evaluate(t) @@ -279,7 +285,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): "non-fully-defined"): l = list_ops.empty_tensor_list( element_dtype=dtypes.float32, - element_shape=-1, + element_shape=None, max_num_elements=max_num_elements) t = list_ops.tensor_list_gather(l, [], element_dtype=dtypes.float32) self.evaluate(t) @@ -300,7 +306,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def testTensorListFromTensor(self): t = constant_op.constant([1.0, 2.0]) - l = list_ops.tensor_list_from_tensor(t, element_shape=scalar_shape()) + l = list_ops.tensor_list_from_tensor(t, element_shape=[]) l, e = list_ops.tensor_list_pop_back(l, element_dtype=dtypes.float32) self.assertAllEqual(self.evaluate(e), 2.0) l, e = list_ops.tensor_list_pop_back(l, element_dtype=dtypes.float32) @@ -315,7 +321,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def testGetSetItem(self): t = constant_op.constant([1.0, 2.0]) - l = list_ops.tensor_list_from_tensor(t, element_shape=scalar_shape()) + l = list_ops.tensor_list_from_tensor(t, element_shape=[]) e0 = list_ops.tensor_list_get_item(l, 0, element_dtype=dtypes.float32) self.assertAllEqual(self.evaluate(e0), 1.0) l = list_ops.tensor_list_set_item(l, 0, 3.0) @@ -333,19 +339,16 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): t = constant_op.constant(5.) tape.watch(t) l = list_ops.tensor_list_reserve( - element_dtype=dtypes.float32, - element_shape=scalar_shape(), - num_elements=3) + element_dtype=dtypes.float32, element_shape=[], num_elements=3) l = list_ops.tensor_list_set_item(l, 1, 2. * t) e = list_ops.tensor_list_get_item(l, 1, element_dtype=dtypes.float32) self.assertAllEqual(self.evaluate(e), 10.0) self.assertAllEqual(self.evaluate(tape.gradient(e, t)), 2.0) + @test_util.run_deprecated_v1 def testSetOnEmptyListWithMaxNumElementsFails(self): l = list_ops.empty_tensor_list( - element_dtype=dtypes.float32, - element_shape=scalar_shape(), - max_num_elements=3) + element_dtype=dtypes.float32, element_shape=[], max_num_elements=3) with self.assertRaisesRegexp( errors.InvalidArgumentError, "Trying to modify element 0 in a list with 0 elements."): @@ -354,7 +357,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def testUnknownShape(self): l = list_ops.empty_tensor_list( - element_dtype=dtypes.float32, element_shape=-1) + element_dtype=dtypes.float32, element_shape=None) l = list_ops.tensor_list_push_back(l, constant_op.constant(1.0)) l = list_ops.tensor_list_push_back(l, constant_op.constant([1.0, 2.0])) l, e = list_ops.tensor_list_pop_back(l, element_dtype=dtypes.float32) @@ -366,7 +369,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): if not context.num_gpus(): return t = constant_op.constant([1.0, 2.0]) - l = list_ops.tensor_list_from_tensor(t, element_shape=scalar_shape()) + l = list_ops.tensor_list_from_tensor(t, element_shape=[]) with context.device("gpu:0"): l_gpu = array_ops.identity(l) self.assertAllEqual( @@ -383,7 +386,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): if not context.num_gpus(): return t = constant_op.constant([1.0, 2.0]) - child_l = list_ops.tensor_list_from_tensor(t, element_shape=scalar_shape()) + child_l = list_ops.tensor_list_from_tensor(t, element_shape=[]) l = list_ops.empty_tensor_list( element_shape=constant_op.constant([], dtype=dtypes.int32), element_dtype=dtypes.variant) @@ -495,9 +498,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with ops.Graph().as_default(), session.Session(target=worker.target): with ops.device("/job:worker"): l = list_ops.tensor_list_reserve( - element_dtype=dtypes.float32, - element_shape=scalar_shape(), - num_elements=2) + element_dtype=dtypes.float32, element_shape=[], num_elements=2) l = list_ops.tensor_list_set_item(l, 0, 1.) with ops.device("/job:ps"): l_ps = array_ops.identity(l) @@ -512,7 +513,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with ops.Graph().as_default(), session.Session(target=worker.target): with ops.device("/job:worker"): t = constant_op.constant([[1.0], [2.0]]) - l = list_ops.tensor_list_from_tensor(t, element_shape=-1) + l = list_ops.tensor_list_from_tensor(t, element_shape=None) with ops.device("/job:ps"): l_ps = array_ops.identity(l) element_shape = list_ops.tensor_list_element_shape( @@ -529,7 +530,9 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with ops.Graph().as_default(), session.Session(target=worker.target): with ops.device("/job:worker"): l = list_ops.empty_tensor_list( - element_shape=-1, element_dtype=dtypes.float32, max_num_elements=2) + element_shape=None, + element_dtype=dtypes.float32, + max_num_elements=2) l = list_ops.tensor_list_push_back(l, 1.) with ops.device("/job:ps"): l_ps = array_ops.identity(l) @@ -543,8 +546,8 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def testPushPopGradients(self): with backprop.GradientTape() as tape: - l = list_ops.empty_tensor_list(element_dtype=dtypes.float32, - element_shape=scalar_shape()) + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=[]) c = constant_op.constant(1.0) tape.watch(c) l = list_ops.tensor_list_push_back(l, c) @@ -556,7 +559,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with backprop.GradientTape() as tape: c = constant_op.constant([1.0, 2.0]) tape.watch(c) - l = list_ops.tensor_list_from_tensor(c, element_shape=scalar_shape()) + l = list_ops.tensor_list_from_tensor(c, element_shape=[]) c2 = list_ops.tensor_list_stack( l, element_dtype=dtypes.float32, num_elements=2) result = c2 * 2.0 @@ -567,7 +570,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with backprop.GradientTape() as tape: c = constant_op.constant([1.0, 2.0]) tape.watch(c) - l = list_ops.tensor_list_from_tensor(c, element_shape=scalar_shape()) + l = list_ops.tensor_list_from_tensor(c, element_shape=[]) c2 = constant_op.constant(3.0) tape.watch(c2) l = list_ops.tensor_list_set_item(l, 0, c2) @@ -578,17 +581,19 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertAllEqual(self.evaluate(grad_c), [0.0, 4.0]) self.assertAllEqual(self.evaluate(grad_c2), 6.0) + @test_util.run_deprecated_v1 def testSetOutOfBounds(self): c = constant_op.constant([1.0, 2.0]) - l = list_ops.tensor_list_from_tensor(c, element_shape=scalar_shape()) + l = list_ops.tensor_list_from_tensor(c, element_shape=[]) with self.assertRaises(errors.InvalidArgumentError): self.evaluate(list_ops.tensor_list_set_item(l, 20, 3.0)) + @test_util.run_deprecated_v1 def testSkipEagerSetItemWithMismatchedShapeFails(self): with self.cached_session() as sess: ph = array_ops.placeholder(dtypes.float32) c = constant_op.constant([1.0, 2.0]) - l = list_ops.tensor_list_from_tensor(c, element_shape=scalar_shape()) + l = list_ops.tensor_list_from_tensor(c, element_shape=[]) # Set a placeholder with unknown shape to satisfy the shape inference # at graph building time. l = list_ops.tensor_list_set_item(l, 0, ph) @@ -599,7 +604,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def testResourceVariableScatterGather(self): c = constant_op.constant([1.0, 2.0], dtype=dtypes.float32) - l = list_ops.tensor_list_from_tensor(c, element_shape=scalar_shape()) + l = list_ops.tensor_list_from_tensor(c, element_shape=[]) v = vs.get_variable("var", initializer=[l] * 10, use_resource=True) v_r_0_stacked = list_ops.tensor_list_stack(v[0], dtypes.float32) self.evaluate(v.initializer) @@ -607,10 +612,8 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): v_r_sparse_stacked = list_ops.tensor_list_stack( v.sparse_read(0), dtypes.float32) self.assertAllEqual([1.0, 2.0], self.evaluate(v_r_sparse_stacked)) - l_new_0 = list_ops.tensor_list_from_tensor( - [3.0, 4.0], element_shape=scalar_shape()) - l_new_1 = list_ops.tensor_list_from_tensor( - [5.0, 6.0], element_shape=scalar_shape()) + l_new_0 = list_ops.tensor_list_from_tensor([3.0, 4.0], element_shape=[]) + l_new_1 = list_ops.tensor_list_from_tensor([5.0, 6.0], element_shape=[]) updated_v = state_ops.scatter_update(v, [3, 5], [l_new_0, l_new_1]) updated_v_elems = array_ops.unstack(updated_v) updated_v_stacked = [ @@ -620,10 +623,11 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): [[1.0, 2.0]] * 4) self.assertAllEqual(self.evaluate(updated_v_stacked), expected) + @test_util.run_deprecated_v1 def testConcat(self): c = constant_op.constant([1.0, 2.0], dtype=dtypes.float32) - l0 = list_ops.tensor_list_from_tensor(c, element_shape=scalar_shape()) - l1 = list_ops.tensor_list_from_tensor([-1.0], element_shape=scalar_shape()) + l0 = list_ops.tensor_list_from_tensor(c, element_shape=[]) + l1 = list_ops.tensor_list_from_tensor([-1.0], element_shape=[]) l_batch_0 = array_ops.stack([l0, l1]) l_batch_1 = array_ops.stack([l1, l0]) @@ -659,7 +663,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.evaluate( list_ops.tensor_list_concat_lists( l_batch_0, - list_ops.empty_tensor_list(scalar_shape(), dtypes.float32), + list_ops.empty_tensor_list([], dtypes.float32), element_dtype=dtypes.float32)) with self.assertRaisesRegexp(errors.InvalidArgumentError, @@ -673,16 +677,16 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with self.assertRaisesRegexp(errors.InvalidArgumentError, r"input_b\[0\].dtype != element_dtype."): l_batch_of_int_tls = array_ops.stack( - [list_ops.tensor_list_from_tensor([1], element_shape=scalar_shape())] - * 2) + [list_ops.tensor_list_from_tensor([1], element_shape=[])] * 2) self.evaluate( list_ops.tensor_list_concat_lists(l_batch_0, l_batch_of_int_tls, element_dtype=dtypes.float32)) + @test_util.run_deprecated_v1 def testPushBackBatch(self): c = constant_op.constant([1.0, 2.0], dtype=dtypes.float32) - l0 = list_ops.tensor_list_from_tensor(c, element_shape=scalar_shape()) - l1 = list_ops.tensor_list_from_tensor([-1.0], element_shape=scalar_shape()) + l0 = list_ops.tensor_list_from_tensor(c, element_shape=[]) + l1 = list_ops.tensor_list_from_tensor([-1.0], element_shape=[]) l_batch = array_ops.stack([l0, l1]) l_push = list_ops.tensor_list_push_back_batch(l_batch, [3.0, 4.0]) l_unstack = array_ops.unstack(l_push) @@ -726,7 +730,7 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): dtypes.float64, dtypes.complex64, dtypes.complex128, dtypes.bool): l_empty = list_ops.empty_tensor_list( - element_dtype=dtype, element_shape=scalar_shape()) + element_dtype=dtype, element_shape=[]) l_empty_zeros = array_ops.zeros_like(l_empty) t_empty_zeros = list_ops.tensor_list_stack( l_empty_zeros, element_dtype=dtype) @@ -750,10 +754,9 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): dtypes.float64, dtypes.complex64, dtypes.complex128, dtypes.bool): l = list_ops.empty_tensor_list( - element_dtype=dtypes.variant, element_shape=scalar_shape()) + element_dtype=dtypes.variant, element_shape=[]) - sub_l = list_ops.empty_tensor_list( - element_dtype=dtype, element_shape=scalar_shape()) + sub_l = list_ops.empty_tensor_list(element_dtype=dtype, element_shape=[]) l = list_ops.tensor_list_push_back(l, sub_l) sub_l = list_ops.tensor_list_push_back(sub_l, math_ops.cast( 1, dtype=dtype)) @@ -786,13 +789,12 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def testElementShape(self): l = list_ops.empty_tensor_list( - element_dtype=dtypes.float32, element_shape=-1) + element_dtype=dtypes.float32, element_shape=None) shape = list_ops.tensor_list_element_shape(l, shape_type=dtypes.int32) self.assertEqual(self.evaluate(shape), -1) def testZerosLikeUninitialized(self): - l0 = list_ops.tensor_list_reserve( - scalar_shape(), 3, element_dtype=dtypes.float32) + l0 = list_ops.tensor_list_reserve([], 3, element_dtype=dtypes.float32) l1 = list_ops.tensor_list_set_item(l0, 0, 1.) # [1., _, _] zeros_1 = array_ops.zeros_like(l1) # [0., _, _] l2 = list_ops.tensor_list_set_item(l1, 2, 2.) # [1., _, 2.] @@ -808,6 +810,292 @@ class ListOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertAllEqual(self.evaluate(res_1), [0.]) self.assertAllEqual(self.evaluate(res_2), [0., 0.]) + @test_util.run_deprecated_v1 + def testSkipEagerTensorListGetItemGradAggregation(self): + l = list_ops.tensor_list_reserve( + element_shape=[], num_elements=1, element_dtype=dtypes.float32) + x = constant_op.constant(1.0) + l = list_ops.tensor_list_set_item(l, 0, x) + l_read1 = list_ops.tensor_list_get_item(l, 0, element_dtype=dtypes.float32) + l_read2 = list_ops.tensor_list_get_item(l, 0, element_dtype=dtypes.float32) + grad = gradients_impl.gradients([l_read1, l_read2], [x]) + with self.cached_session() as sess: + self.assertSequenceEqual(self.evaluate(grad), [2.]) + + @test_util.run_deprecated_v1 + def testSkipEagerBuildElementShape(self): + fn = list_ops._build_element_shape + # Unknown shape -> -1. + self.assertEqual(fn(None), -1) + self.assertEqual(fn(tensor_shape.unknown_shape()), -1) + # Scalar shape -> [] with type int32. + self.assertEqual(fn([]).dtype, dtypes.int32) + self.assertEqual(fn(tensor_shape.scalar()).dtype, dtypes.int32) + self.assertAllEqual(self.evaluate(fn([])), np.array([], np.int32)) + self.assertAllEqual( + self.evaluate(fn(tensor_shape.scalar())), np.array([], np.int32)) + # Tensor -> Tensor + shape = constant_op.constant(1) + self.assertIs(fn(shape), shape) + # Shape with unknown dims -> shape list with -1's. + shape = [None, 5] + self.assertAllEqual(fn(shape), [-1, 5]) + self.assertAllEqual(fn(tensor_shape.TensorShape(shape)), [-1, 5]) + # Shape with unknown dims and tensor dims -> shape list with -1's and tensor + # dims. + t = array_ops.placeholder(dtypes.int32) + shape = [None, 5, t] + result = fn(shape) + self.assertAllEqual(result[:2], [-1, 5]) + self.assertIs(result[2], t) + + def testAddN(self): + l1 = list_ops.tensor_list_from_tensor([1.0, 2.0], element_shape=[]) + l2 = list_ops.tensor_list_from_tensor([3.0, 4.0], element_shape=[]) + l3 = list_ops.tensor_list_from_tensor([5.0, 6.0], element_shape=[]) + result = math_ops.add_n((l1, l2, l3)) + result_t = list_ops.tensor_list_stack(result, element_dtype=dtypes.float32) + self.assertAllEqual(self.evaluate(result_t), [9., 12.]) + + def testAddNNestedList(self): + l1 = list_ops.tensor_list_from_tensor([1.0, 2.0], element_shape=[]) + l2 = list_ops.tensor_list_from_tensor([3.0, 4.0], element_shape=[]) + l3 = list_ops.tensor_list_from_tensor([5.0, 6.0], element_shape=[]) + l4 = list_ops.tensor_list_from_tensor([7.0, 8.0], element_shape=[]) + a = list_ops.empty_tensor_list( + element_dtype=dtypes.variant, element_shape=[]) + a = list_ops.tensor_list_push_back(a, l1) + a = list_ops.tensor_list_push_back(a, l2) + b = list_ops.empty_tensor_list( + element_dtype=dtypes.variant, element_shape=[]) + b = list_ops.tensor_list_push_back(b, l3) + b = list_ops.tensor_list_push_back(b, l4) + result = math_ops.add_n((a, b)) + result_0 = list_ops.tensor_list_stack( + list_ops.tensor_list_get_item(result, 0, element_dtype=dtypes.variant), + element_dtype=dtypes.float32) + result_1 = list_ops.tensor_list_stack( + list_ops.tensor_list_get_item(result, 1, element_dtype=dtypes.variant), + element_dtype=dtypes.float32) + self.assertAllEqual(self.evaluate(result_0), [6., 8.]) + self.assertAllEqual(self.evaluate(result_1), [10., 12.]) + + @test_util.run_deprecated_v1 + def testSkipEagerConcatShapeInference(self): + + def BuildTensor(element_shape): + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=element_shape) + return list_ops.tensor_list_concat(l, element_dtype=dtypes.float32) + + self.assertIsNone(BuildTensor(None).shape.rank) + self.assertAllEqual(BuildTensor([None, 2, 3]).shape.as_list(), [None, 2, 3]) + self.assertAllEqual( + BuildTensor([None, 2, None]).shape.as_list(), [None, 2, None]) + self.assertAllEqual(BuildTensor([1, 2, 3]).shape.as_list(), [None, 2, 3]) + + def testConcatWithFullyDefinedElementShape(self): + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=[2, 2]) + l = list_ops.tensor_list_push_back(l, [[0., 1.], [2., 3.]]) + l = list_ops.tensor_list_push_back(l, [[4., 5.], [6., 7.]]) + t = list_ops.tensor_list_concat(l, element_dtype=dtypes.float32) + self.assertAllEqual( + self.evaluate(t), [[0., 1.], [2., 3.], [4., 5.], [6., 7.]]) + + def testConcatWithNonFullyDefinedElementShape(self): + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=[None, 2]) + l = list_ops.tensor_list_push_back(l, [[0., 1.]]) + l = list_ops.tensor_list_push_back(l, [[2., 3.], [4., 5.]]) + t = list_ops.tensor_list_concat(l, element_dtype=dtypes.float32) + self.assertAllEqual(self.evaluate(t), [[0., 1.], [2., 3.], [4., 5.]]) + + def testConcatWithMismatchingTensorShapesFails(self): + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=None) + l = list_ops.tensor_list_push_back(l, [[0., 1.]]) + l = list_ops.tensor_list_push_back(l, [[2.], [4.]]) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + r"Tried to concat tensors with unequal shapes: " + r"\[2\] vs \[1\]"): + t = list_ops.tensor_list_concat(l, element_dtype=dtypes.float32) + self.evaluate(t) + + def testConcatEmptyListWithFullyDefinedElementShape(self): + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=[5, 2]) + t = list_ops.tensor_list_concat(l, element_dtype=dtypes.float32) + self.assertAllEqual(self.evaluate(t).shape, (0, 2)) + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=[None, 2]) + t = list_ops.tensor_list_concat(l, element_dtype=dtypes.float32) + self.assertAllEqual(self.evaluate(t).shape, (0, 2)) + + def testConcatEmptyListWithUnknownElementShapeFails(self): + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=None) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + "All except the first dimension must be fully" + " defined when concating an empty tensor list"): + t = list_ops.tensor_list_concat(l, element_dtype=dtypes.float32) + self.evaluate(t) + + def testConcatEmptyListWithPartiallyDefinedElementShapeFails(self): + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=[2, None]) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + "All except the first dimension must be fully" + " defined when concating an empty tensor list"): + t = list_ops.tensor_list_concat(l, element_dtype=dtypes.float32) + self.evaluate(t) + + def testConcatListWithScalarElementShapeFails(self): + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=tensor_shape.scalar()) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + "Concat requires elements to be at least vectors, " + "found scalars instead"): + t = list_ops.tensor_list_concat(l, element_dtype=dtypes.float32) + self.evaluate(t) + + def testConcatListWithScalarElementsFails(self): + l = list_ops.empty_tensor_list( + element_dtype=dtypes.float32, element_shape=None) + l1 = list_ops.tensor_list_push_back(l, 1.) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, "Concat saw a scalar shape at index 0" + " but requires at least vectors"): + t = list_ops.tensor_list_concat(l1, element_dtype=dtypes.float32) + self.evaluate(t) + l1 = list_ops.tensor_list_push_back(l, [1.]) + l1 = list_ops.tensor_list_push_back(l1, 2.) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, "Concat saw a scalar shape at index 1" + " but requires at least vectors"): + t = list_ops.tensor_list_concat(l1, element_dtype=dtypes.float32) + self.evaluate(t) + + def testEvenSplit(self): + + def RunTest(input_tensor, lengths, expected_stacked_output): + l = list_ops.tensor_list_split( + input_tensor, element_shape=None, lengths=lengths) + self.assertAllEqual( + list_ops.tensor_list_stack(l, element_dtype=dtypes.float32), + expected_stacked_output) + + RunTest([1., 2., 3.], [1, 1, 1], [[1.], [2.], [3.]]) + RunTest([1., 2., 3., 4.], [2, 2], [[1., 2.], [3., 4.]]) + RunTest([[1., 2.], [3., 4.]], [1, 1], [[[1., 2.]], [[3., 4.]]]) + + def testUnevenSplit(self): + l = list_ops.tensor_list_split([1., 2., 3., 4., 5], + element_shape=None, + lengths=[3, 2]) + self.assertAllEqual(list_ops.tensor_list_length(l), 2) + self.assertAllEqual( + list_ops.tensor_list_get_item(l, 0, element_dtype=dtypes.float32), + [1., 2., 3.]) + self.assertAllEqual( + list_ops.tensor_list_get_item(l, 1, element_dtype=dtypes.float32), + [4., 5.]) + + @test_util.run_deprecated_v1 + def testSkipEagerSplitWithInvalidTensorShapeFails(self): + with self.cached_session(): + tensor = array_ops.placeholder(dtype=dtypes.float32) + l = list_ops.tensor_list_split(tensor, element_shape=None, lengths=[1]) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + r"Tensor must be at least a vector, but saw shape: \[\]"): + l.eval({tensor: 1}) + + @test_util.run_deprecated_v1 + def testSkipEagerSplitWithInvalidLengthsShapeFails(self): + with self.cached_session(): + lengths = array_ops.placeholder(dtype=dtypes.int64) + l = list_ops.tensor_list_split([1., 2.], + element_shape=None, + lengths=lengths) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + r"Expected lengths to be a vector, received shape: \[\]"): + l.eval({lengths: 1}) + + def testSplitWithInvalidLengthsFails(self): + with self.assertRaisesRegexp(errors.InvalidArgumentError, + r"Invalid value in lengths: -1"): + l = list_ops.tensor_list_split([1., 2.], + element_shape=None, + lengths=[1, -1]) + self.evaluate(l) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + r"Attempting to slice \[0, 3\] from tensor with length 2"): + l = list_ops.tensor_list_split([1., 2.], element_shape=None, lengths=[3]) + self.evaluate(l) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + r"Unused values in tensor. Length of tensor: 2 Values used: 1"): + l = list_ops.tensor_list_split([1., 2.], element_shape=None, lengths=[1]) + self.evaluate(l) + + @test_util.run_deprecated_v1 + def testSkipEagerSplitWithScalarElementShapeFails(self): + with self.assertRaisesRegexp(ValueError, + r"Shapes must be equal rank, but are 1 and 0"): + l = list_ops.tensor_list_split([1., 2.], element_shape=[], lengths=[1, 1]) + with self.cached_session(): + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + r"TensorListSplit requires element_shape to be at least of rank 1, " + r"but saw: \[\]"): + element_shape = array_ops.placeholder(dtype=dtypes.int32) + l = list_ops.tensor_list_split([1., 2.], + element_shape=element_shape, + lengths=[1, 1]) + l.eval({element_shape: []}) + + def testEagerOnlySplitWithScalarElementShapeFails(self): + if context.executing_eagerly(): + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + r"TensorListSplit requires element_shape to be at least of rank 1, " + r"but saw: \[\]"): + list_ops.tensor_list_split([1., 2.], element_shape=[], lengths=[1, 1]) + + @test_util.run_deprecated_v1 + def testSkipEagerSplitWithIncompatibleTensorShapeAndElementShapeFails(self): + with self.assertRaisesRegexp(ValueError, + r"Shapes must be equal rank, but are 2 and 1"): + l = list_ops.tensor_list_split([[1.], [2.]], + element_shape=[1], + lengths=[1, 1]) + + with self.cached_session(): + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + r"tensor shape \[2,1\] is not compatible with element_shape \[1\]"): + element_shape = array_ops.placeholder(dtype=dtypes.int32) + l = list_ops.tensor_list_split([[1.], [2.]], + element_shape=element_shape, + lengths=[1, 1]) + l.eval({element_shape: [1]}) + + def testEagerOnlySplitWithIncompatibleTensorShapeAndElementShapeFails(self): + if context.executing_eagerly(): + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + r"tensor shape \[2,1\] is not compatible with element_shape \[1\]"): + list_ops.tensor_list_split([[1.], [2.]], + element_shape=[1], + lengths=[1, 1]) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/kernel_tests/listdiff_op_test.py b/tensorflow/python/kernel_tests/listdiff_op_test.py index baeb40dd63..2865710798 100644 --- a/tensorflow/python/kernel_tests/listdiff_op_test.py +++ b/tensorflow/python/kernel_tests/listdiff_op_test.py @@ -47,7 +47,7 @@ class ListDiffTest(test.TestCase): y_tensor = ops.convert_to_tensor(y, dtype=dtype) out_tensor, idx_tensor = diff_func(x_tensor, y_tensor, index_dtype=index_dtype) - tf_out, tf_idx = sess.run([out_tensor, idx_tensor]) + tf_out, tf_idx = self.evaluate([out_tensor, idx_tensor]) self.assertAllEqual(tf_out, out) self.assertAllEqual(tf_idx, idx) self.assertEqual(1, out_tensor.get_shape().ndims) diff --git a/tensorflow/python/kernel_tests/logging_ops_test.py b/tensorflow/python/kernel_tests/logging_ops_test.py index 8e9b87f651..85035e5f7d 100644 --- a/tensorflow/python/kernel_tests/logging_ops_test.py +++ b/tensorflow/python/kernel_tests/logging_ops_test.py @@ -39,6 +39,7 @@ from tensorflow.python.platform import test class LoggingOpsTest(test.TestCase): + @test_util.run_deprecated_v1 def testAssertDivideByZero(self): with self.cached_session() as sess: epsilon = ops.convert_to_tensor(1e-20) @@ -52,7 +53,7 @@ class LoggingOpsTest(test.TestCase): math_ops.less(epsilon, y), ["Divide-by-zero"]) ]): out = math_ops.div(z, y) - self.assertAllEqual(2.0, out.eval()) + self.assertAllEqual(2.0, self.evaluate(out)) # assert(epsilon < x) # z / x # @@ -63,7 +64,7 @@ class LoggingOpsTest(test.TestCase): ]): out = math_ops.div(z, x) with self.assertRaisesOpError("less than x"): - out.eval() + self.evaluate(out) class PrintV2Test(test.TestCase): @@ -305,12 +306,14 @@ class PrintV2Test(test.TestCase): tensor, output_stream="unknown") self.evaluate(print_op) + @test_util.run_deprecated_v1 def testPrintOpName(self): with self.cached_session(): tensor = math_ops.range(10) print_op = logging_ops.print_v2(tensor, name="print_name") self.assertEqual(print_op.name, "print_name") + @test_util.run_deprecated_v1 def testNoDuplicateFormatOpGraphModeAfterExplicitFormat(self): with self.cached_session(): tensor = math_ops.range(10) @@ -379,6 +382,7 @@ class PrintGradientTest(test.TestCase): inp_printed = logging_ops.Print(inp, ["hello"]) self.assertEqual(inp.get_shape(), inp_printed.get_shape()) + @test_util.run_deprecated_v1 def testPrintGradient(self): with self.cached_session(): inp = constant_op.constant(2.0, shape=[100, 32], name="in") @@ -387,8 +391,8 @@ class PrintGradientTest(test.TestCase): wx_print = logging_ops.Print(wx, [w, w, w]) wx_grad = gradients_impl.gradients(wx, w)[0] wx_print_grad = gradients_impl.gradients(wx_print, w)[0] - wxg = wx_grad.eval() - wxpg = wx_print_grad.eval() + wxg = self.evaluate(wx_grad) + wxpg = self.evaluate(wx_print_grad) self.assertAllEqual(wxg, wxpg) diff --git a/tensorflow/python/kernel_tests/lookup_ops_test.py b/tensorflow/python/kernel_tests/lookup_ops_test.py index bd93942efb..ad81e0be64 100644 --- a/tensorflow/python/kernel_tests/lookup_ops_test.py +++ b/tensorflow/python/kernel_tests/lookup_ops_test.py @@ -37,6 +37,7 @@ from tensorflow.python.training import server_lib class HashTableOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testHashTable(self): with self.cached_session(): default_val = -1 @@ -52,15 +53,16 @@ class HashTableOpTest(test.TestCase): output = table.lookup(input_string) self.assertAllEqual([3], output.get_shape()) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([0, 1, -1], result) exported_keys_tensor, exported_values_tensor = table.export() self.assertItemsEqual([b"brain", b"salad", b"surgery"], - exported_keys_tensor.eval()) - self.assertItemsEqual([0, 1, 2], exported_values_tensor.eval()) + self.evaluate(exported_keys_tensor)) + self.assertItemsEqual([0, 1, 2], self.evaluate(exported_values_tensor)) + @test_util.run_deprecated_v1 def testHashTableFindHighRank(self): with self.cached_session(): default_val = -1 @@ -76,9 +78,10 @@ class HashTableOpTest(test.TestCase): [["brain", "salad"], ["tank", "tarkus"]]) output = table.lookup(input_string) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([[0, 1], [-1, -1]], result) + @test_util.run_deprecated_v1 def testHashTableInitWithPythonArrays(self): with self.cached_session(): default_val = -1 @@ -94,9 +97,10 @@ class HashTableOpTest(test.TestCase): input_string = constant_op.constant(["brain", "salad", "tank"]) output = table.lookup(input_string) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([0, 1, -1], result) + @test_util.run_deprecated_v1 def testHashTableInitWithNumPyArrays(self): with self.cached_session(): default_val = -1 @@ -111,9 +115,10 @@ class HashTableOpTest(test.TestCase): input_string = constant_op.constant(["brain", "salad", "tank"]) output = table.lookup(input_string) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([0, 1, -1], result) + @test_util.run_deprecated_v1 def testMultipleHashTables(self): with self.cached_session() as sess: default_val = -1 @@ -137,11 +142,12 @@ class HashTableOpTest(test.TestCase): output2 = table2.lookup(input_string) output3 = table3.lookup(input_string) - out1, out2, out3 = sess.run([output1, output2, output3]) + out1, out2, out3 = self.evaluate([output1, output2, output3]) self.assertAllEqual([0, 1, -1], out1) self.assertAllEqual([0, 1, -1], out2) self.assertAllEqual([0, 1, -1], out3) + @test_util.run_deprecated_v1 def testHashTableWithTensorDefault(self): with self.cached_session(): default_val = constant_op.constant(-1, dtypes.int64) @@ -154,9 +160,10 @@ class HashTableOpTest(test.TestCase): input_string = constant_op.constant(["brain", "salad", "tank"]) output = table.lookup(input_string) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([0, 1, -1], result) + @test_util.run_deprecated_v1 def testHashTableWithSparseTensorInput(self): with self.cached_session() as sess: default_val = constant_op.constant(-1, dtypes.int64) @@ -174,12 +181,13 @@ class HashTableOpTest(test.TestCase): constant_op.constant(sp_shape, dtypes.int64)) output = table.lookup(input_tensor) - out_indices, out_values, out_shape = sess.run(output) + out_indices, out_values, out_shape = self.evaluate(output) self.assertAllEqual([0, 1, -1], out_values) self.assertAllEqual(sp_indices, out_indices) self.assertAllEqual(sp_shape, out_shape) + @test_util.run_deprecated_v1 def testSignatureMismatch(self): with self.cached_session(): default_val = -1 @@ -210,6 +218,7 @@ class HashTableOpTest(test.TestCase): lookup_ops.KeyValueTensorInitializer(["a"], [1], [dtypes.string], dtypes.int64), default_val) + @test_util.run_deprecated_v1 def testNotInitialized(self): with self.cached_session(): default_val = -1 @@ -221,8 +230,9 @@ class HashTableOpTest(test.TestCase): output = table.lookup(input_string) with self.assertRaisesOpError("Table not initialized"): - output.eval() + self.evaluate(output) + @test_util.run_deprecated_v1 def testInitializeTwice(self): with self.cached_session(): default_val = -1 @@ -235,6 +245,7 @@ class HashTableOpTest(test.TestCase): with self.assertRaisesOpError("Table already initialized"): table.initializer.run() + @test_util.run_deprecated_v1 def testInitializationWithInvalidDimensions(self): with self.cached_session(): default_val = -1 @@ -245,6 +256,7 @@ class HashTableOpTest(test.TestCase): lookup_ops.HashTable( lookup_ops.KeyValueTensorInitializer(keys, values), default_val) + @test_util.run_deprecated_v1 def testMultipleSessions(self): # Start a server server = server_lib.Server( @@ -274,6 +286,7 @@ class HashTableOpTest(test.TestCase): table.initializer.run() self.assertAllEqual(3, table.size().eval()) + @test_util.run_deprecated_v1 def testHashTableInt32String(self): with self.cached_session(): default_val = "n/a" @@ -286,7 +299,7 @@ class HashTableOpTest(test.TestCase): input_tensor = constant_op.constant([0, 1, -1]) output = table.lookup(input_tensor) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([b"brain", b"salad", b"n/a"], result) @@ -298,6 +311,7 @@ class IndexTableFromFile(test.TestCase): f.write("\n".join(values) + "\n") return vocabulary_file + @test_util.run_deprecated_v1 def test_string_index_table_from_file(self): vocabulary_file = self._createVocabFile("f2i_vocab1.txt") with self.cached_session(): @@ -306,10 +320,11 @@ class IndexTableFromFile(test.TestCase): ids = table.lookup(constant_op.constant(["salad", "surgery", "tarkus"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, 3), ids.eval()) + self.assertAllEqual((1, 2, 3), self.evaluate(ids)) + @test_util.run_deprecated_v1 def test_string_index_table_from_multicolumn_file(self): vocabulary_file = self._createVocabFile( "f2i_vocab1.txt", values=("brain\t300", "salad\t20", "surgery\t1")) @@ -322,10 +337,11 @@ class IndexTableFromFile(test.TestCase): ids = table.lookup(constant_op.constant(["salad", "surgery", "tarkus"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, 3), ids.eval()) + self.assertAllEqual((1, 2, 3), self.evaluate(ids)) + @test_util.run_deprecated_v1 def test_string_index_table_from_multicolumn_file_custom_delimiter(self): vocabulary_file = self._createVocabFile( "f2i_vocab1.txt", values=("brain 300", "salad 20", "surgery 1")) @@ -339,10 +355,11 @@ class IndexTableFromFile(test.TestCase): ids = table.lookup(constant_op.constant(["salad", "surgery", "tarkus"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, 3), ids.eval()) + self.assertAllEqual((1, 2, 3), self.evaluate(ids)) + @test_util.run_deprecated_v1 def test_string_index_table_from_file_tensor_filename(self): vocabulary_file = self._createVocabFile("f2i_vocab1.txt") with self.cached_session(): @@ -352,12 +369,13 @@ class IndexTableFromFile(test.TestCase): ids = table.lookup(constant_op.constant(["salad", "surgery", "tarkus"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, 3), ids.eval()) + self.assertAllEqual((1, 2, 3), self.evaluate(ids)) self.assertEqual(1, len(ops.get_collection(ops.GraphKeys.ASSET_FILEPATHS))) + @test_util.run_deprecated_v1 def test_string_index_table_from_file_placeholder_filename(self): vocabulary_file = self._createVocabFile("f2i_vocab1.txt") with self.cached_session(): @@ -367,14 +385,15 @@ class IndexTableFromFile(test.TestCase): ids = table.lookup(constant_op.constant(["salad", "surgery", "tarkus"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) feed_dict = {vocabulary_placeholder.name: vocabulary_file} lookup_ops.tables_initializer().run(feed_dict=feed_dict) - self.assertAllEqual((1, 2, 3), ids.eval()) + self.assertAllEqual((1, 2, 3), self.evaluate(ids)) self.assertEqual(0, len(ops.get_collection(ops.GraphKeys.ASSET_FILEPATHS))) + @test_util.run_deprecated_v1 def test_int32_index_table_from_file(self): vocabulary_file = self._createVocabFile( "f2i_vocab2.txt", values=("42", "1", "-1000")) @@ -387,10 +406,11 @@ class IndexTableFromFile(test.TestCase): constant_op.constant((1, -1000, 11), dtype=dtypes.int32)) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, 3), ids.eval()) + self.assertAllEqual((1, 2, 3), self.evaluate(ids)) + @test_util.run_deprecated_v1 def test_int64_index_table_from_file(self): vocabulary_file = self._createVocabFile( "f2i_vocab3.txt", values=("42", "1", "-1000")) @@ -403,10 +423,11 @@ class IndexTableFromFile(test.TestCase): constant_op.constant((1, -1000, 11), dtype=dtypes.int64)) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, 3), ids.eval()) + self.assertAllEqual((1, 2, 3), self.evaluate(ids)) + @test_util.run_deprecated_v1 def test_index_table_from_file_with_default_value(self): default_value = -42 vocabulary_file = self._createVocabFile("f2i_vocab4.txt") @@ -416,10 +437,11 @@ class IndexTableFromFile(test.TestCase): ids = table.lookup(constant_op.constant(["salad", "surgery", "tarkus"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, default_value), ids.eval()) + self.assertAllEqual((1, 2, default_value), self.evaluate(ids)) + @test_util.run_deprecated_v1 def test_index_table_from_file_with_oov_buckets(self): vocabulary_file = self._createVocabFile("f2i_vocab5.txt") with self.cached_session(): @@ -429,7 +451,7 @@ class IndexTableFromFile(test.TestCase): constant_op.constant(["salad", "surgery", "tarkus", "toccata"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() self.assertAllEqual( ( @@ -437,7 +459,7 @@ class IndexTableFromFile(test.TestCase): 2, # From vocabulary file. 867, # 3 + fingerprint("tarkus") mod 300. 860), # 3 + fingerprint("toccata") mod 300. - ids.eval()) + self.evaluate(ids)) def test_index_table_from_file_fails_with_empty_vocabulary_file_name(self): self.assertRaises( @@ -468,6 +490,7 @@ class IndexTableFromFile(test.TestCase): vocabulary_file=vocabulary_file, vocab_size=0) + @test_util.run_deprecated_v1 def test_index_table_from_file_with_vocab_size_too_small(self): vocabulary_file = self._createVocabFile("f2i_vocab6.txt") with self.cached_session(): @@ -476,11 +499,12 @@ class IndexTableFromFile(test.TestCase): ids = table.lookup(constant_op.constant(["salad", "surgery", "tarkus"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, -1, -1), ids.eval()) + self.assertAllEqual((1, -1, -1), self.evaluate(ids)) self.assertEqual(2, table.size().eval()) + @test_util.run_deprecated_v1 def test_index_table_from_file_with_vocab_size_too_large(self): vocabulary_file = self._createVocabFile("f2i_vocab7.txt") with self.cached_session(): @@ -489,6 +513,7 @@ class IndexTableFromFile(test.TestCase): self.assertRaisesRegexp(errors_impl.InvalidArgumentError, "Invalid vocab_size", table.initializer.run) + @test_util.run_deprecated_v1 def test_index_table_from_file_with_vocab_size(self): vocabulary_file = self._createVocabFile("f2i_vocab8.txt") @@ -504,9 +529,9 @@ class IndexTableFromFile(test.TestCase): ids = table.lookup(constant_op.constant(["salad", "surgery", "tarkus"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, -1), ids.eval()) + self.assertAllEqual((1, 2, -1), self.evaluate(ids)) self.assertEqual(3, table.size().eval()) def test_index_table_from_file_with_invalid_hashers(self): @@ -577,6 +602,7 @@ class KeyValueTensorInitializerTest(test.TestCase): table = lookup_ops.HashTable(init, default_value=-1) table.initializer.run() + @test_util.run_deprecated_v1 def test_int32(self): with ops.Graph().as_default(), self.cached_session(): init = lookup_ops.KeyValueTensorInitializer((42, 1, -1000), (0, 1, 2), @@ -590,6 +616,7 @@ class KeyValueTensorInitializerTest(test.TestCase): class IndexTableFromTensor(test.TestCase): @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def test_index_table_from_tensor_with_tensor_init(self): table = lookup_ops.index_table_from_tensor( vocabulary_list=("brain", "salad", "surgery"), num_oov_buckets=1) @@ -606,6 +633,7 @@ class IndexTableFromTensor(test.TestCase): ids = table.lookup(constant_op.constant(("salad", "surgery", "tarkus"))) self.assertAllEqual((1, 2, 3), self.evaluate(ids)) + @test_util.run_deprecated_v1 def test_int32_index_table_from_tensor_with_tensor_init(self): with self.cached_session(): table = lookup_ops.index_table_from_tensor( @@ -614,10 +642,11 @@ class IndexTableFromTensor(test.TestCase): constant_op.constant((1, -1000, 11), dtype=dtypes.int32)) with self.assertRaises(errors_impl.FailedPreconditionError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, 3), ids.eval()) + self.assertAllEqual((1, 2, 3), self.evaluate(ids)) + @test_util.run_deprecated_v1 def test_int64_index_table_from_tensor_with_tensor_init(self): with self.cached_session(): table = lookup_ops.index_table_from_tensor( @@ -626,10 +655,11 @@ class IndexTableFromTensor(test.TestCase): constant_op.constant((1, -1000, 11), dtype=dtypes.int64)) with self.assertRaises(errors_impl.FailedPreconditionError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, 3), ids.eval()) + self.assertAllEqual((1, 2, 3), self.evaluate(ids)) + @test_util.run_deprecated_v1 def test_index_table_from_tensor_with_default_value(self): default_value = -42 with self.cached_session(): @@ -639,9 +669,9 @@ class IndexTableFromTensor(test.TestCase): ids = table.lookup(constant_op.constant(["salad", "surgery", "tarkus"])) with self.assertRaises(errors_impl.FailedPreconditionError): - ids.eval() + self.evaluate(ids) lookup_ops.tables_initializer().run() - self.assertAllEqual((1, 2, default_value), ids.eval()) + self.assertAllEqual((1, 2, default_value), self.evaluate(ids)) def test_index_table_from_tensor_missing_vocabulary_list(self): with self.cached_session(): @@ -650,13 +680,14 @@ class IndexTableFromTensor(test.TestCase): lookup_ops.index_table_from_tensor( vocabulary_list=None, num_oov_buckets=1) + @test_util.run_deprecated_v1 def test_index_table_from_tensor_empty_vocabulary_list(self): with self.cached_session(): table = lookup_ops.index_table_from_tensor( vocabulary_list=np.array([], dtype=np.str_), num_oov_buckets=1) ids = table.lookup(constant_op.constant(["salad", "surgery", "brain"])) with self.assertRaises(errors_impl.OpError): - ids.eval() + self.evaluate(ids) with self.assertRaisesRegexp( errors_impl.OpError, "keys and values cannot be empty"): lookup_ops.tables_initializer().run() @@ -686,6 +717,7 @@ class IndexToStringTableFromFileTest(test.TestCase): f.write("\n".join(values) + "\n") return vocabulary_file + @test_util.run_deprecated_v1 def test_index_to_string_table(self): vocabulary_path = self._createVocabFile("i2f_vocab1.txt") # vocabulary_file supports string and tensor @@ -698,11 +730,12 @@ class IndexToStringTableFromFileTest(test.TestCase): features = table.lookup( constant_op.constant([0, 1, 2, 3], dtypes.int64)) with self.assertRaises(errors_impl.OpError): - features.eval() + self.evaluate(features) lookup_ops.tables_initializer().run() self.assertAllEqual((b"brain", b"salad", b"surgery", b"UNK"), - features.eval()) + self.evaluate(features)) + @test_util.run_deprecated_v1 def test_index_to_string_table_from_multicolumn_file(self): vocabulary_file = self._createVocabFile( "f2i_vocab1.txt", values=("brain\t300", "salad\t20", "surgery\t1")) @@ -713,11 +746,12 @@ class IndexToStringTableFromFileTest(test.TestCase): value_column_index=0) features = table.lookup(constant_op.constant([0, 1, 2, 3], dtypes.int64)) with self.assertRaises(errors_impl.OpError): - features.eval() + self.evaluate(features) lookup_ops.tables_initializer().run() self.assertAllEqual((b"brain", b"salad", b"surgery", b"UNK"), - features.eval()) + self.evaluate(features)) + @test_util.run_deprecated_v1 def test_index_to_string_table_from_multicolumn_file_custom_delimiter(self): vocabulary_file = self._createVocabFile( "f2i_vocab1.txt", values=("brain 300", "salad 20", "surgery 1")) @@ -729,11 +763,12 @@ class IndexToStringTableFromFileTest(test.TestCase): delimiter=" ") features = table.lookup(constant_op.constant([0, 1, 2, 3], dtypes.int64)) with self.assertRaises(errors_impl.OpError): - features.eval() + self.evaluate(features) lookup_ops.tables_initializer().run() self.assertAllEqual((b"brain", b"salad", b"surgery", b"UNK"), - features.eval()) + self.evaluate(features)) + @test_util.run_deprecated_v1 def test_index_to_string_table_with_default_value(self): default_value = b"NONE" vocabulary_file = self._createVocabFile("f2i_vocab2.txt") @@ -742,11 +777,12 @@ class IndexToStringTableFromFileTest(test.TestCase): vocabulary_file=vocabulary_file, default_value=default_value) features = table.lookup(constant_op.constant([1, 2, 4], dtypes.int64)) with self.assertRaises(errors_impl.OpError): - features.eval() + self.evaluate(features) lookup_ops.tables_initializer().run() self.assertAllEqual((b"salad", b"surgery", default_value), - features.eval()) + self.evaluate(features)) + @test_util.run_deprecated_v1 def test_index_to_string_table_with_vocab_size_too_small(self): default_value = b"NONE" vocabulary_file = self._createVocabFile("f2i_vocab2.txt") @@ -757,11 +793,12 @@ class IndexToStringTableFromFileTest(test.TestCase): default_value=default_value) features = table.lookup(constant_op.constant([1, 2, 4], dtypes.int64)) with self.assertRaises(errors_impl.OpError): - features.eval() + self.evaluate(features) lookup_ops.tables_initializer().run() self.assertAllEqual((b"salad", default_value, default_value), - features.eval()) + self.evaluate(features)) + @test_util.run_deprecated_v1 def test_index_to_string_table_with_vocab_size_too_large(self): vocabulary_file = self._createVocabFile("f2i_vocab6.txt") with self.cached_session(): @@ -770,11 +807,12 @@ class IndexToStringTableFromFileTest(test.TestCase): features = table.lookup(constant_op.constant([1, 2, 4], dtypes.int64)) with self.assertRaises(errors_impl.OpError): - features.eval() + self.evaluate(features) init = lookup_ops.tables_initializer() self.assertRaisesRegexp(errors_impl.InvalidArgumentError, "Invalid vocab_size", init.run) + @test_util.run_deprecated_v1 def test_index_to_string_table_with_vocab_size(self): vocabulary_file = self._createVocabFile("f2i_vocab7.txt") with self.cached_session(): @@ -783,13 +821,15 @@ class IndexToStringTableFromFileTest(test.TestCase): features = table.lookup(constant_op.constant([1, 2, 4], dtypes.int64)) with self.assertRaises(errors_impl.OpError): - features.eval() + self.evaluate(features) lookup_ops.tables_initializer().run() - self.assertAllEqual((b"salad", b"surgery", b"UNK"), features.eval()) + self.assertAllEqual((b"salad", b"surgery", b"UNK"), + self.evaluate(features)) class IndexToStringTableFromTensorTest(test.TestCase): + @test_util.run_deprecated_v1 def test_index_to_string_table_from_tensor(self): with self.cached_session(): vocabulary_list = constant_op.constant(["brain", "salad", "surgery"]) @@ -799,12 +839,13 @@ class IndexToStringTableFromTensorTest(test.TestCase): indices = constant_op.constant([0, 1, 2, 3], dtypes.int64) features = table.lookup(indices) with self.assertRaises(errors_impl.OpError): - features.eval() + self.evaluate(features) lookup_ops.tables_initializer().run() self.assertAllEqual((b"brain", b"salad", b"surgery", b"UNK"), - features.eval()) + self.evaluate(features)) + @test_util.run_deprecated_v1 def test_duplicate_entries(self): with self.cached_session(): vocabulary_list = constant_op.constant(["hello", "hello"]) @@ -813,8 +854,9 @@ class IndexToStringTableFromTensorTest(test.TestCase): indices = constant_op.constant([0, 1, 4], dtypes.int64) features = table.lookup(indices) lookup_ops.tables_initializer().run() - self.assertAllEqual((b"hello", b"hello", b"UNK"), features.eval()) + self.assertAllEqual((b"hello", b"hello", b"UNK"), self.evaluate(features)) + @test_util.run_deprecated_v1 def test_index_to_string_with_default_value(self): default_value = b"NONE" with self.cached_session(): @@ -824,11 +866,11 @@ class IndexToStringTableFromTensorTest(test.TestCase): indices = constant_op.constant([1, 2, 4], dtypes.int64) features = table.lookup(indices) with self.assertRaises(errors_impl.OpError): - features.eval() + self.evaluate(features) lookup_ops.tables_initializer().run() self.assertAllEqual((b"salad", b"surgery", default_value), - features.eval()) + self.evaluate(features)) class InitializeTableFromFileOpTest(test.TestCase): @@ -854,6 +896,7 @@ class InitializeTableFromFileOpTest(test.TestCase): result = self.evaluate(output) self.assertAllEqual([0, 1, -1], result) + @test_util.run_deprecated_v1 def testInitializeInt64Table(self): vocabulary_file = self._createVocabFile( "one_column_int64.txt", values=("42", "1", "-1000")) @@ -870,9 +913,10 @@ class InitializeTableFromFileOpTest(test.TestCase): output = table.lookup( constant_op.constant((42, 1, 11), dtype=dtypes.int64)) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([0, 1, -1], result) + @test_util.run_deprecated_v1 def testInitializeIndexTable(self): vocabulary_file = self._createVocabFile("one_column_2.txt") @@ -889,9 +933,10 @@ class InitializeTableFromFileOpTest(test.TestCase): input_values = constant_op.constant([0, 1, 2, 3], dtypes.int64) output = table.lookup(input_values) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([b"brain", b"salad", b"surgery", b"UNK"], result) + @test_util.run_deprecated_v1 def testMultiColumn(self): vocabulary_file = os.path.join(self.get_temp_dir(), "three_columns.txt") with open(vocabulary_file, "w") as f: @@ -911,9 +956,10 @@ class InitializeTableFromFileOpTest(test.TestCase): input_string = constant_op.constant(["brain", "salad", "surgery"]) output = table.lookup(input_string) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([1, 5, 6], result) + @test_util.run_deprecated_v1 def testInvalidDataTypeInMultiColumn(self): vocabulary_file = os.path.join(self.get_temp_dir(), "three_columns.txt") with open(vocabulary_file, "w") as f: @@ -944,6 +990,7 @@ class InitializeTableFromFileOpTest(test.TestCase): key_index, dtypes.string, value_index), default_value) + @test_util.run_deprecated_v1 def testInvalidIndex(self): vocabulary_file = self._createVocabFile("one_column_4.txt") with self.cached_session(): @@ -958,6 +1005,7 @@ class InitializeTableFromFileOpTest(test.TestCase): with self.assertRaisesOpError("Invalid number of columns"): table.initializer.run() + @test_util.run_deprecated_v1 def testInitializeSameTableWithMultipleNodes(self): vocabulary_file = self._createVocabFile("one_column_5.txt") @@ -994,7 +1042,7 @@ class InitializeTableFromFileOpTest(test.TestCase): output2 = table2.lookup(input_string) output3 = table3.lookup(input_string) - out1, out2, out3 = sess.run([output1, output2, output3]) + out1, out2, out3 = self.evaluate([output1, output2, output3]) self.assertAllEqual([0, 1, -1], out1) self.assertAllEqual([0, 1, -1], out2) self.assertAllEqual([0, 1, -1], out3) @@ -1009,6 +1057,7 @@ class InitializeTableFromFileOpTest(test.TestCase): dtypes.int64, lookup_ops.TextFileIndex.LINE_NUMBER), default_value) + @test_util.run_deprecated_v1 def testInitializeWithVocabSize(self): with self.cached_session(): default_value = -1 @@ -1055,6 +1104,7 @@ class InitializeTableFromFileOpTest(test.TestCase): table3.initializer.run() self.assertEquals(vocab_size, table3.size().eval()) + @test_util.run_deprecated_v1 def testFeedVocabularyName(self): vocabulary_file = self._createVocabFile("feed_vocabulary.txt") @@ -1078,9 +1128,10 @@ class InitializeTableFromFileOpTest(test.TestCase): input_string = constant_op.constant(["brain", "salad", "tank"]) output = table.lookup(input_string) - result = output.eval() + result = self.evaluate(output) self.assertAllEqual([0, 1, -1], result) + @test_util.run_deprecated_v1 def testInvalidFilenames(self): vocabulary_file = self._createVocabFile("filename_shape.txt") @@ -1105,6 +1156,7 @@ class InitializeTableFromFileOpTest(test.TestCase): dtypes.int64, lookup_ops.TextFileIndex.LINE_NUMBER), default_value) + @test_util.run_deprecated_v1 def testIdToStringTable(self): vocab_file = self._createVocabFile("feat_to_id_1.txt") with self.cached_session(): @@ -1119,9 +1171,11 @@ class InitializeTableFromFileOpTest(test.TestCase): input_values = constant_op.constant([0, 1, 2, 3], dtypes.int64) out = table.lookup(input_values) - self.assertAllEqual([b"brain", b"salad", b"surgery", b"UNK"], out.eval()) + self.assertAllEqual([b"brain", b"salad", b"surgery", b"UNK"], + self.evaluate(out)) self.assertEquals(vocab_size, table.size().eval()) + @test_util.run_deprecated_v1 def testStringToIdTable(self): vocab_file = self._createVocabFile("feat_to_id_2.txt") with self.cached_session(): @@ -1135,9 +1189,10 @@ class InitializeTableFromFileOpTest(test.TestCase): input_string = constant_op.constant(["brain", "salad", "surgery", "UNK"]) out = table.lookup(input_string) - self.assertAllEqual([0, 1, 2, -1], out.eval()) + self.assertAllEqual([0, 1, 2, -1], self.evaluate(out)) self.assertEquals(vocab_size, table.size().eval()) + @test_util.run_deprecated_v1 def testInt64ToIdTable(self): vocab_file = self._createVocabFile( "feat_to_id_3.txt", values=("42", "1", "-1000")) @@ -1152,7 +1207,7 @@ class InitializeTableFromFileOpTest(test.TestCase): out = table.lookup( constant_op.constant((42, 1, -1000, 11), dtype=dtypes.int64)) - self.assertAllEqual((0, 1, 2, -1), out.eval()) + self.assertAllEqual((0, 1, 2, -1), self.evaluate(out)) self.assertEquals(vocab_size, table.size().eval()) @@ -1164,6 +1219,7 @@ class IdTableWithHashBucketsTest(test.TestCase): f.write("\n".join(values) + "\n") return vocabulary_file + @test_util.run_deprecated_v1 def testStringIdTableWithHashBuckets(self): vocab_file = self._createVocabFile("feat_to_id_1.txt") with self.cached_session(): @@ -1181,9 +1237,10 @@ class IdTableWithHashBucketsTest(test.TestCase): input_string = constant_op.constant(["brain", "salad", "surgery", "UNK"]) out = table.lookup(input_string) - self.assertAllEqual([0, 1, 2, 3], out.eval()) + self.assertAllEqual([0, 1, 2, 3], self.evaluate(out)) self.assertEquals(vocab_size + oov_buckets, table.size().eval()) + @test_util.run_deprecated_v1 def testInt32IdTableWithHashBuckets(self): vocab_file = self._createVocabFile("feat_to_id_2.txt", ("42", "1", "-1000")) with self.cached_session(): @@ -1203,9 +1260,10 @@ class IdTableWithHashBucketsTest(test.TestCase): values = constant_op.constant((42, 1, -1000, 11), dtype=dtypes.int32) out = table.lookup(values) - self.assertAllEqual([0, 1, 2, 3], out.eval()) + self.assertAllEqual([0, 1, 2, 3], self.evaluate(out)) self.assertEquals(vocab_size + oov_buckets, table.size().eval()) + @test_util.run_deprecated_v1 def testInt64IdTableWithHashBuckets(self): vocab_file = self._createVocabFile("feat_to_id_3.txt", ("42", "1", "-1000")) with self.cached_session(): @@ -1223,9 +1281,10 @@ class IdTableWithHashBucketsTest(test.TestCase): values = constant_op.constant((42, 1, -1000, 11), dtype=dtypes.int64) out = table.lookup(values) - self.assertAllEqual([0, 1, 2, 3], out.eval()) + self.assertAllEqual([0, 1, 2, 3], self.evaluate(out)) self.assertEquals(vocab_size + oov_buckets, table.size().eval()) + @test_util.run_deprecated_v1 def testStringIdTableWithOnlyHashBucket(self): with self.cached_session(): oov_buckets = 5 @@ -1244,9 +1303,10 @@ class IdTableWithHashBucketsTest(test.TestCase): 1, # fingerprint("salad") mod 5. 4 # fingerprint("surgery") mod 5 ], - out.eval()) + self.evaluate(out)) self.assertEquals(oov_buckets, table.size().eval()) + @test_util.run_deprecated_v1 def testInt32IdTableWithOnlyHashBucket(self): with self.cached_session(): oov_buckets = 5 @@ -1266,7 +1326,7 @@ class IdTableWithHashBucketsTest(test.TestCase): 4, # fingerprint("1") mod 5. 2 # fingerprint("-1000") mod 5 ], - out.eval()) + self.evaluate(out)) self.assertEquals(oov_buckets, table.size().eval()) def testFloat64IdTableWithOnlyHashBucket(self): @@ -1281,6 +1341,7 @@ class IdTableWithHashBucketsTest(test.TestCase): lookup_ops.IdTableWithHashBuckets( None, num_oov_buckets=5, key_dtype=dtypes.bool) + @test_util.run_deprecated_v1 def testIdTableWithHashBucketsWithMultipleInitializers(self): vocab_file = self._createVocabFile("feat_to_id_4.txt") with self.cached_session() as sess: @@ -1311,7 +1372,7 @@ class IdTableWithHashBucketsTest(test.TestCase): out1 = table1.lookup(input_string) out2 = table2.lookup(input_string) - out1, out2 = sess.run([out1, out2]) + out1, out2 = self.evaluate([out1, out2]) self.assertAllEqual([5, 0, 1, 2, 5], out1) self.assertAllEqual([5, 0, 1, 2, 3], out2) self.assertEquals(vocab_size + oov_buckets, table1.size().eval()) @@ -1321,6 +1382,7 @@ class IdTableWithHashBucketsTest(test.TestCase): "table2_Lookup/hash_bucket": "StringToHashBucketStrong", }, sess.graph) + @test_util.run_deprecated_v1 def testIdTableWithHashBucketsInitializationAcrossSessions(self): vocab_file = self._createVocabFile("feat_to_id_5.txt") shared_name = "across-sessions" @@ -1342,7 +1404,7 @@ class IdTableWithHashBucketsTest(test.TestCase): out1 = table1.lookup(input_string_1) - self.assertAllEqual([0, 1, 2, 3], out1.eval()) + self.assertAllEqual([0, 1, 2, 3], self.evaluate(out1)) self.assertEquals(vocab_size + oov_buckets, table1.size().eval()) with self.cached_session(): @@ -1363,9 +1425,10 @@ class IdTableWithHashBucketsTest(test.TestCase): out2 = table2.lookup(input_string_2) - self.assertAllEqual([3, 1, 3], out2.eval()) + self.assertAllEqual([3, 1, 3], self.evaluate(out2)) self.assertEquals(vocab_size + oov_buckets, table2.size().eval()) + @test_util.run_deprecated_v1 def testIdTableWithHashBucketsWithMultipleInitializersDifferentDefault(self): vocab_file = self._createVocabFile("feat_to_id_6.txt") with self.cached_session() as sess: @@ -1394,12 +1457,13 @@ class IdTableWithHashBucketsTest(test.TestCase): out1 = table1.lookup(input_string_1) out2 = table2.lookup(input_string_2) - out1, out2 = sess.run([out1, out2]) + out1, out2 = self.evaluate([out1, out2]) self.assertAllEqual([0, 1, 2, -1], out1) self.assertAllEqual([-2, 1, -2], out2) self.assertEquals(vocab_size + oov_buckets, table1.size().eval()) self.assertEquals(vocab_size + oov_buckets, table2.size().eval()) + @test_util.run_deprecated_v1 def testSparseTensor(self): vocab_file = self._createVocabFile("feat_to_id_7.txt") input_indices = [[0, 0], [0, 1], [2, 0], [2, 2], [3, 0]] @@ -1428,6 +1492,7 @@ class IdTableWithHashBucketsTest(test.TestCase): self.assertAllEqual([0, 1, 0, 2, 3], sp_ids_val) self.assertAllEqual(input_shape, sp_ids_shape) + @test_util.run_deprecated_v1 def testInt32SparseTensor(self): input_indices = [[0, 0], [0, 1], [2, 0], [2, 2], [3, 0]] input_shape = [4, 4] @@ -1456,6 +1521,7 @@ class IdTableWithHashBucketsTest(test.TestCase): self.assertAllEqual([0, 1, 0, 2, 3], sp_ids_val) self.assertAllEqual(input_shape, sp_ids_shape) + @test_util.run_deprecated_v1 def testInt64SparseTensor(self): input_indices = [[0, 0], [0, 1], [2, 0], [2, 2], [3, 0]] input_shape = [4, 4] diff --git a/tensorflow/python/kernel_tests/losses_test.py b/tensorflow/python/kernel_tests/losses_test.py index b04996f788..abff61f81b 100644 --- a/tensorflow/python/kernel_tests/losses_test.py +++ b/tensorflow/python/kernel_tests/losses_test.py @@ -51,58 +51,62 @@ class AbsoluteDifferenceLossTest(test.TestCase): losses.absolute_difference( self._predictions, self._predictions, weights=None) + @test_util.run_deprecated_v1 def testAllCorrectNoLossWeight(self): loss = losses.absolute_difference(self._predictions, self._predictions) with self.cached_session(): - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLoss(self): loss = losses.absolute_difference(self._labels, self._predictions) with self.cached_session(): - self.assertAlmostEqual(5.5, loss.eval(), 3) + self.assertAlmostEqual(5.5, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithPythonScalarWeight(self): weights = 2.3 loss = losses.absolute_difference(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(5.5 * weights, loss.eval(), 3) + self.assertAlmostEqual(5.5 * weights, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithScalarTensorWeight(self): weights = 2.3 loss = losses.absolute_difference(self._labels, self._predictions, constant_op.constant(weights)) with self.cached_session(): - self.assertAlmostEqual(5.5 * weights, loss.eval(), 3) + self.assertAlmostEqual(5.5 * weights, self.evaluate(loss), 3) def testNonZeroLossWithOneDimBatchSpecificWeights(self): weights = constant_op.constant((1.2, 0.0), shape=(2, 1)) loss = losses.absolute_difference(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(5.6, loss.eval(), 3) + self.assertAlmostEqual(5.6, self.evaluate(loss), 3) def testNonZeroLossWithTwoDimBatchSpecificWeights(self): weights = constant_op.constant([1.2, 0.0], shape=[2, 1]) loss = losses.absolute_difference(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(5.6, loss.eval(), 3) + self.assertAlmostEqual(5.6, self.evaluate(loss), 3) def testNonZeroLossWithSampleSpecificWeights(self): weights = constant_op.constant([3, 6, 5, 0, 4, 2], shape=[2, 3]) loss = losses.absolute_difference(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(16.6, loss.eval(), 3) + self.assertAlmostEqual(16.6, self.evaluate(loss), 3) def testNonZeroLossWithSampleSpecificWeightsMostZero(self): weights = constant_op.constant([0, 0, 0, 0, 0, 2], shape=[2, 3]) loss = losses.absolute_difference(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(6.0, loss.eval(), 3) + self.assertAlmostEqual(6.0, self.evaluate(loss), 3) def testLossWithSampleSpecificWeightsAllZero(self): weights = array_ops.zeros((2, 3)) loss = losses.absolute_difference(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) @test_util.assert_no_new_pyobjects_executing_eagerly def testEagerNoMemoryLeaked(self): @@ -123,6 +127,7 @@ class SoftmaxCrossEntropyLossTest(test.TestCase): with self.assertRaises(ValueError): losses.softmax_cross_entropy(labels, logits, weights=None) + @test_util.run_deprecated_v1 def testAllCorrect(self): with self.cached_session(): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -132,6 +137,7 @@ class SoftmaxCrossEntropyLossTest(test.TestCase): self.assertEquals('softmax_cross_entropy_loss/value', loss.op.name) self.assertAlmostEqual(loss.eval(), 0.0, 3) + @test_util.run_deprecated_v1 def testAllWrong(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]) @@ -142,6 +148,7 @@ class SoftmaxCrossEntropyLossTest(test.TestCase): self.assertEquals(loss.op.name, 'softmax_cross_entropy_loss/value') self.assertAlmostEqual(loss.eval(), 10.0, 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithPythonScalarWeight(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]) @@ -149,8 +156,9 @@ class SoftmaxCrossEntropyLossTest(test.TestCase): weights = 2.3 with self.cached_session(): loss = losses.softmax_cross_entropy(labels, logits, weights) - self.assertAlmostEqual(weights * 10.0, loss.eval(), 3) + self.assertAlmostEqual(weights * 10.0, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithScalarTensorWeight(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]) @@ -159,7 +167,7 @@ class SoftmaxCrossEntropyLossTest(test.TestCase): with self.cached_session(): loss = losses.softmax_cross_entropy(labels, logits, constant_op.constant(weights)) - self.assertAlmostEqual(weights * 10.0, loss.eval(), 3) + self.assertAlmostEqual(weights * 10.0, self.evaluate(loss), 3) def testNonZeroLossWithOneDimBatchSpecificWeights(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -168,7 +176,8 @@ class SoftmaxCrossEntropyLossTest(test.TestCase): weights = constant_op.constant((1.2, 3.4, 5.6)) with self.cached_session(): loss = losses.softmax_cross_entropy(labels, logits, weights) - self.assertAlmostEqual((1.2 + 3.4 + 5.6) * 10.0 / 3.0, loss.eval(), 3) + self.assertAlmostEqual((1.2 + 3.4 + 5.6) * 10.0 / 3.0, + self.evaluate(loss), 3) def testAllWrongAllWeightsMissing(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -177,7 +186,7 @@ class SoftmaxCrossEntropyLossTest(test.TestCase): weights = constant_op.constant([0, 0, 0], shape=[3]) with self.cached_session(): loss = losses.softmax_cross_entropy(labels, logits, weights) - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) def testSomeWeightsMissing(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -186,7 +195,7 @@ class SoftmaxCrossEntropyLossTest(test.TestCase): weights = constant_op.constant([1.2, 0, 0], shape=[3]) with self.cached_session(): loss = losses.softmax_cross_entropy(labels, logits, weights) - self.assertAlmostEqual(12.0, loss.eval(), 3) + self.assertAlmostEqual(12.0, self.evaluate(loss), 3) def testSoftmaxWithMeasurementSpecificWeightsRaisesException(self): with self.cached_session(): @@ -199,6 +208,7 @@ class SoftmaxCrossEntropyLossTest(test.TestCase): with self.assertRaises(ValueError): losses.softmax_cross_entropy(labels, logits, weights=weights).eval() + @test_util.run_deprecated_v1 def testSoftmaxLabelSmoothing(self): with self.cached_session(): # Softmax Cross Entropy Loss is: @@ -231,6 +241,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): with self.assertRaises(ValueError): losses.sparse_softmax_cross_entropy(labels, logits, weights=None) + @test_util.run_deprecated_v1 def testAllCorrectInt32Labels(self): with self.cached_session(): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -247,6 +258,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): labels = constant_op.constant([[0], [1], [2]], dtype=dtypes.int32) losses.sparse_softmax_cross_entropy(labels, logits) + @test_util.run_deprecated_v1 def testAllCorrectInt64Labels(self): with self.cached_session(): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -256,6 +268,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): self.assertEquals(loss.op.name, 'sparse_softmax_cross_entropy_loss/value') self.assertAlmostEqual(loss.eval(), 0.0, 3) + @test_util.run_deprecated_v1 def testAllCorrectNonColumnLabels(self): with self.cached_session(): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -265,6 +278,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): self.assertEquals(loss.op.name, 'sparse_softmax_cross_entropy_loss/value') self.assertAlmostEqual(loss.eval(), 0.0, 3) + @test_util.run_deprecated_v1 def testAllWrongInt32Labels(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]) @@ -275,6 +289,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): self.assertEquals(loss.op.name, 'sparse_softmax_cross_entropy_loss/value') self.assertAlmostEqual(loss.eval(), 10.0, 3) + @test_util.run_deprecated_v1 def testAllWrongInt64Labels(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]) @@ -285,6 +300,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): self.assertEquals(loss.op.name, 'sparse_softmax_cross_entropy_loss/value') self.assertAlmostEqual(loss.eval(), 10.0, 3) + @test_util.run_deprecated_v1 def testAllWrongNonColumnLabels(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]) @@ -295,6 +311,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): self.assertEquals(loss.op.name, 'sparse_softmax_cross_entropy_loss/value') self.assertAlmostEqual(loss.eval(), 10.0, 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithPythonScalarWeight(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]) @@ -302,8 +319,9 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): weights = 2.3 with self.cached_session(): loss = losses.sparse_softmax_cross_entropy(labels, logits, weights) - self.assertAlmostEqual(weights * 10.0, loss.eval(), 3) + self.assertAlmostEqual(weights * 10.0, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithScalarTensorWeight(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]]) @@ -312,7 +330,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): with self.cached_session(): loss = losses.sparse_softmax_cross_entropy(labels, logits, constant_op.constant(weights)) - self.assertAlmostEqual(weights * 10.0, loss.eval(), 3) + self.assertAlmostEqual(weights * 10.0, self.evaluate(loss), 3) def testNonZeroLossWith1DTensorWeight(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -322,8 +340,9 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): with self.cached_session(): loss = losses.sparse_softmax_cross_entropy( labels, logits, constant_op.constant((weights,))) - self.assertAlmostEqual(weights * 10.0, loss.eval(), 3) + self.assertAlmostEqual(weights * 10.0, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithPlaceholderForWeights(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -336,6 +355,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): feed_dict={weights: ((1.2,), (3.4,), (5.6,))}) self.assertAlmostEqual((1.2 + 3.4 + 5.6) * 10.0 / 3.0, loss_val, 3) + @test_util.run_deprecated_v1 def testUnknownShapePlaceholderForLogitsLabelsButScalarWeights(self): logits = array_ops.placeholder(dtypes.float32) labels = array_ops.placeholder(dtypes.int32) @@ -351,6 +371,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): }) self.assertAlmostEqual((1.0 + 1.0 + 1.0) * 10.0 / 3.0, loss_val, 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithPlaceholderForLogitsLabelsAndWeights(self): logits = array_ops.placeholder(dtypes.float32, shape=(None, 3)) labels = array_ops.placeholder(dtypes.int32, shape=(None, 1)) @@ -374,7 +395,8 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): weights = constant_op.constant([1.2, 3.4, 5.6], shape=(3, 1)) with self.cached_session(): loss = losses.sparse_softmax_cross_entropy(labels, logits, weights) - self.assertAlmostEqual((1.2 + 3.4 + 5.6) * 10.0 / 3.0, loss.eval(), 3) + self.assertAlmostEqual((1.2 + 3.4 + 5.6) * 10.0 / 3.0, + self.evaluate(loss), 3) def testNonZeroLossWithColumnWeights(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -383,7 +405,8 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): weights = constant_op.constant([[1.2], [3.4], [5.6]]) with self.cached_session(): loss = losses.sparse_softmax_cross_entropy(labels, logits, weights) - self.assertAlmostEqual((1.2 + 3.4 + 5.6) * 10.0 / 3.0, loss.eval(), 3) + self.assertAlmostEqual((1.2 + 3.4 + 5.6) * 10.0 / 3.0, + self.evaluate(loss), 3) def testAllWrongAllWeightsMissing(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -392,7 +415,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): weights = constant_op.constant([0, 0, 0], shape=(3, 1)) with self.cached_session(): loss = losses.sparse_softmax_cross_entropy(labels, logits, weights) - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) def testSomeWeightsMissing(self): logits = constant_op.constant([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], @@ -401,8 +424,9 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): weights = constant_op.constant([1.2, 0, 0], shape=(3, 1)) with self.cached_session(): loss = losses.sparse_softmax_cross_entropy(labels, logits, weights) - self.assertAlmostEqual(12.0, loss.eval(), 3) + self.assertAlmostEqual(12.0, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testMeasurementSpecificWeightsRaisesException(self): with self.cached_session(): logits = constant_op.constant([[100.0, -100.0, -100.0], @@ -441,6 +465,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): losses.sparse_softmax_cross_entropy( labels, logits, weights=weights).eval() + @test_util.run_deprecated_v1 def testInconsistentWeightShapeRaisesException(self): """The weight tensor has incorrect shape.""" with self.cached_session(): @@ -455,6 +480,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): losses.sparse_softmax_cross_entropy( labels, logits, weights=weights).eval() + @test_util.run_deprecated_v1 def testInconsistentLabelShapeRaisesException(self): """The label tensor has incorrect shape.""" with self.cached_session(): @@ -472,6 +498,7 @@ class SparseSoftmaxCrossEntropyLossTest(test.TestCase): class SigmoidCrossEntropyLossTest(test.TestCase): + @test_util.run_deprecated_v1 def testAllCorrectSigmoid(self): with self.cached_session(): logits = constant_op.constant([[100.0, -100.0, -100.0], @@ -481,8 +508,9 @@ class SigmoidCrossEntropyLossTest(test.TestCase): loss = losses.sigmoid_cross_entropy(labels, logits) self.assertEquals(logits.dtype, loss.dtype) self.assertEquals('sigmoid_cross_entropy_loss/value', loss.op.name) - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testLossWithSingleDimPlaceholderForLogitsAndWeights1(self): logits = array_ops.placeholder(dtypes.float32, shape=(None, 1)) labels = array_ops.placeholder(dtypes.float32, shape=(None, 1)) @@ -499,6 +527,7 @@ class SigmoidCrossEntropyLossTest(test.TestCase): }) self.assertAlmostEqual(0.313, loss, 3) + @test_util.run_deprecated_v1 def testLossWithSingleDimPlaceholderForLogitsAndWeights2(self): logits = array_ops.placeholder(dtypes.float32, shape=(None, 2)) labels = array_ops.placeholder(dtypes.float32, shape=(None, 2)) @@ -515,6 +544,7 @@ class SigmoidCrossEntropyLossTest(test.TestCase): }) self.assertAlmostEqual(0.313, loss, 3) + @test_util.run_deprecated_v1 def testAllWrongSigmoid(self): with self.cached_session(): logits = constant_op.constant([[100.0, -100.0, -100.0], @@ -526,6 +556,7 @@ class SigmoidCrossEntropyLossTest(test.TestCase): self.assertEquals('sigmoid_cross_entropy_loss/value', loss.op.name) self.assertAlmostEqual(loss.eval(), 600.0 / 9.0, 3) + @test_util.run_deprecated_v1 def testAllWrongSigmoidWithMeasurementSpecificWeights(self): with self.cached_session(): logits = constant_op.constant([[100.0, -100.0, -100.0], @@ -536,8 +567,9 @@ class SigmoidCrossEntropyLossTest(test.TestCase): loss = losses.sigmoid_cross_entropy(labels, logits, weights) self.assertEquals(logits.dtype, loss.dtype) self.assertEquals('sigmoid_cross_entropy_loss/value', loss.op.name) - self.assertAlmostEqual(1700.0 / 7.0, loss.eval(), 3) + self.assertAlmostEqual(1700.0 / 7.0, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testMultiCorrectSigmoid(self): logits = constant_op.constant([[100.0, -100.0, 100.0], [100.0, 100.0, -100.0], @@ -548,7 +580,7 @@ class SigmoidCrossEntropyLossTest(test.TestCase): self.assertEquals('sigmoid_cross_entropy_loss/value', loss.op.name) with self.cached_session(): - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) def testSigmoidFloat64(self): logits = constant_op.constant(( @@ -563,7 +595,7 @@ class SigmoidCrossEntropyLossTest(test.TestCase): self.assertEquals(logits.dtype, loss.dtype) with self.cached_session(): - self.assertAlmostEqual(44.444, loss.eval(), 3) + self.assertAlmostEqual(44.444, self.evaluate(loss), 3) def testSigmoidNoReduction(self): logits = constant_op.constant(( @@ -576,12 +608,10 @@ class SigmoidCrossEntropyLossTest(test.TestCase): self.assertEquals(logits.dtype, loss.dtype) with self.cached_session(): - self.assertAllClose(( - (0., 0., 0.), - (0., 100., 100.), - (100., 0., 100.) - ), loss.eval(), 3) + self.assertAllClose(((0., 0., 0.), (0., 100., 100.), (100., 0., 100.)), + self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testSigmoidLabelSmoothingCorrect(self): with self.cached_session(): logits = constant_op.constant([[100.0, -100.0, -100.0]]) @@ -605,6 +635,7 @@ class SigmoidCrossEntropyLossTest(test.TestCase): expected_value = (100.0 + 50.0 * label_smoothing) / 3.0 self.assertAlmostEqual(loss.eval(), expected_value, 3) + @test_util.run_deprecated_v1 def testSigmoidLabelSmoothingEqualsSoftmaxTwoLabel(self): with self.cached_session(): label_smoothing = 0.1 @@ -619,7 +650,8 @@ class SigmoidCrossEntropyLossTest(test.TestCase): softmax_labels = constant_op.constant([[0, 1], [1, 0], [0, 1]]) softmax_loss = losses.softmax_cross_entropy( softmax_labels, softmax_logits, label_smoothing=label_smoothing) - self.assertAlmostEqual(sigmoid_loss.eval(), softmax_loss.eval(), 3) + self.assertAlmostEqual(sigmoid_loss.eval(), self.evaluate(softmax_loss), + 3) class LogLossTest(test.TestCase): @@ -645,11 +677,13 @@ class LogLossTest(test.TestCase): with self.assertRaises(ValueError): losses.log_loss(self._labels, self._labels, weights=None) + @test_util.run_deprecated_v1 def testAllCorrectNoLossWeight(self): loss = losses.log_loss(self._labels, self._labels) with self.cached_session(): - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testAllCorrectNoLossWeightWithPlaceholder(self): tf_predictions = array_ops.placeholder( dtypes.float32, shape=self._np_labels.shape) @@ -658,27 +692,31 @@ class LogLossTest(test.TestCase): self.assertAlmostEqual( 0.0, loss.eval(feed_dict={tf_predictions: self._np_labels}), 3) + @test_util.run_deprecated_v1 def testNonZeroLoss(self): loss = losses.log_loss(self._labels, self._predictions) with self.cached_session(): self.assertAlmostEqual(-np.sum(self._expected_losses) / 6.0, - loss.eval(), 3) + self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithPythonScalarWeight(self): weights = 2.3 loss = losses.log_loss(self._labels, self._predictions, weights) with self.cached_session(): self.assertAlmostEqual(weights * -np.sum(self._expected_losses) / 6.0, - loss.eval(), 3) + self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithScalarTensorWeight(self): weights = 2.3 loss = losses.log_loss(self._labels, self._predictions, constant_op.constant(weights)) with self.cached_session(): self.assertAlmostEqual(weights * -np.sum(self._expected_losses) / 6.0, - loss.eval(), 3) + self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithScalarTensorWeightAndPlaceholder(self): tf_predictions = array_ops.placeholder( dtypes.float32, shape=self._np_predictions.shape) @@ -690,6 +728,7 @@ class LogLossTest(test.TestCase): self.assertAlmostEqual(weights * -np.sum(self._expected_losses) / 6.0, loss, 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithScalarTensorWeightAndPlaceholderWithRankOnly(self): tf_predictions = array_ops.placeholder(dtypes.float32, shape=[None, None]) weights = 2.3 @@ -707,7 +746,8 @@ class LogLossTest(test.TestCase): np.asarray([1.2, 1.2, 1.2, 3.4, 3.4, 3.4]).reshape((2, 3))) loss = losses.log_loss(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(-np.sum(expected_losses) / 6.0, loss.eval(), 3) + self.assertAlmostEqual(-np.sum(expected_losses) / 6.0, + self.evaluate(loss), 3) def testNonZeroLossWithOneDimBatchSpecificWeightsSomeZero(self): weights = constant_op.constant((1.2, 0), shape=(2, 1)) @@ -716,7 +756,8 @@ class LogLossTest(test.TestCase): (2, 3))) loss = losses.log_loss(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(-np.sum(expected_losses) / 3.0, loss.eval(), 3) + self.assertAlmostEqual(-np.sum(expected_losses) / 3.0, + self.evaluate(loss), 3) def testNonZeroLossWithTwoDimBatchSpecificWeightsSomeZero(self): weights = constant_op.constant([1.2, 0], shape=[2, 1]) @@ -725,7 +766,8 @@ class LogLossTest(test.TestCase): (2, 3))) loss = losses.log_loss(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(-np.sum(expected_losses) / 3.0, loss.eval(), 3) + self.assertAlmostEqual(-np.sum(expected_losses) / 3.0, + self.evaluate(loss), 3) def testWeightsWithSameNumDimsButWrongShapeThrowsException(self): weights = constant_op.constant(np.random.normal(size=(2, 4)), shape=[2, 4]) @@ -743,8 +785,10 @@ class LogLossTest(test.TestCase): constant_op.constant( weights, shape=(2, 3))) with self.cached_session(): - self.assertAlmostEqual(-np.sum(expected_losses) / 5.0, loss.eval(), 3) + self.assertAlmostEqual(-np.sum(expected_losses) / 5.0, + self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithMeasurementSpecificWeightsWithPlaceholder(self): weights = np.array([3, 6, 5, 0, 4, 2]).reshape((2, 3)) expected_losses = np.multiply(self._expected_losses, weights) @@ -770,8 +814,9 @@ class LogLossTest(test.TestCase): constant_op.constant( weights, shape=(2, 3))) with self.cached_session(): - self.assertAlmostEqual(-np.sum(expected_losses), loss.eval(), 3) + self.assertAlmostEqual(-np.sum(expected_losses), self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithSampleSpecificWeightsMostZeroWithPlaceholder(self): weights = np.array([0, 0, 0, 0, 0, 2]).reshape((2, 3)) expected_losses = np.multiply(self._expected_losses, weights) @@ -788,7 +833,7 @@ class LogLossTest(test.TestCase): tf_weights = array_ops.zeros(shape=(2, 3)) loss = losses.log_loss(self._labels, self._predictions, tf_weights) with self.cached_session(): - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) class HingeLossTest(test.TestCase): @@ -800,6 +845,7 @@ class HingeLossTest(test.TestCase): with self.assertRaises(ValueError): _ = losses.hinge_loss(labels, logits).eval() + @test_util.run_deprecated_v1 def testAllOutsideMargin(self): with self.cached_session(): logits = constant_op.constant([1.2, -1.4, -1.0, 2.1]) @@ -807,6 +853,7 @@ class HingeLossTest(test.TestCase): loss = losses.hinge_loss(labels, logits) self.assertAllClose(loss.eval(), 0.0, atol=1e-3) + @test_util.run_deprecated_v1 def testSomeInsideMargin(self): with self.cached_session(): logits = constant_op.constant([[-0.7], [-1.4], [1.4], [0.6]]) @@ -816,6 +863,7 @@ class HingeLossTest(test.TestCase): # the margin so they incur some (small) loss. self.assertAllClose(loss.eval(), 0.175, atol=1e-3) + @test_util.run_deprecated_v1 def testSomeMisclassified(self): with self.cached_session(): logits = constant_op.constant([[[1.2], [0.4], [-1.0], [-1.1]]]) @@ -835,6 +883,7 @@ class HuberLossTest(test.TestCase): with self.assertRaises(ValueError): _ = losses.huber_loss(labels, predictions).eval() + @test_util.run_deprecated_v1 def testAllQuadratic(self): with self.cached_session(): predictions = constant_op.constant([1.5, -1.4, -1.0, 0.0]) @@ -843,6 +892,7 @@ class HuberLossTest(test.TestCase): self.assertAllClose(loss.eval(), 0.5 * (0.25 + 0.16 + 1.0 + 0.25) / 4., atol=1e-5) + @test_util.run_deprecated_v1 def testAllLinear(self): with self.cached_session(): predictions = constant_op.constant([1.5, -1.4, -1.0, 0.0]) @@ -851,6 +901,7 @@ class HuberLossTest(test.TestCase): self.assertAllClose(loss.eval(), (1.5 + 2.4 + 1.0 + 1.5) / 4. - 0.5, atol=1e-5) + @test_util.run_deprecated_v1 def testMixedQuadraticLinear(self): with self.cached_session(): predictions = constant_op.constant([[1.5, -1.4, -1.0, 0.0], @@ -870,7 +921,7 @@ class HuberLossTest(test.TestCase): labels = constant_op.constant([1.0, -1.0, 0.0, 0.5]) expected = 0.5 * np.array([0.5**2, 0.4**2, 0.5**2, 0.5**2]).mean() loss = losses.huber_loss(labels, predictions, delta=delta) - self.assertAllClose(expected, loss.eval(), atol=1e-5) + self.assertAllClose(expected, self.evaluate(loss), atol=1e-5) def testAllLinearDelta(self): delta = 0.5 @@ -880,7 +931,7 @@ class HuberLossTest(test.TestCase): expected -= 0.5 * delta**2 loss = losses.huber_loss(labels, predictions, delta=delta) with self.cached_session(): - self.assertAllClose(expected, loss.eval(), atol=1e-5) + self.assertAllClose(expected, self.evaluate(loss), atol=1e-5) class MeanSquaredErrorTest(test.TestCase): @@ -896,6 +947,7 @@ class MeanSquaredErrorTest(test.TestCase): losses.mean_squared_error( self._predictions, self._predictions, weights=None) + @test_util.run_deprecated_v1 def testScalar(self): with self.cached_session(): self.assertEqual( @@ -903,58 +955,62 @@ class MeanSquaredErrorTest(test.TestCase): losses.mean_squared_error(predictions=constant_op.constant(0), labels=constant_op.constant(0)).eval()) + @test_util.run_deprecated_v1 def testAllCorrectNoLossWeight(self): loss = losses.mean_squared_error(self._predictions, self._predictions) with self.cached_session(): - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLoss(self): loss = losses.mean_squared_error(self._labels, self._predictions) with self.cached_session(): - self.assertAlmostEqual(49.5, loss.eval(), 3) + self.assertAlmostEqual(49.5, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithPythonScalarWeight(self): weights = 2.3 loss = losses.mean_squared_error(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(49.5 * weights, loss.eval(), 3) + self.assertAlmostEqual(49.5 * weights, self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithScalarTensorWeight(self): weights = 2.3 loss = losses.mean_squared_error(self._labels, self._predictions, constant_op.constant(weights)) with self.cached_session(): - self.assertAlmostEqual(49.5 * weights, loss.eval(), 3) + self.assertAlmostEqual(49.5 * weights, self.evaluate(loss), 3) def testNonZeroLossWithOneDimBatchSpecificWeights(self): weights = constant_op.constant([1.2, 3.4], shape=(2, 1)) loss = losses.mean_squared_error(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(767.8 / 6.0, loss.eval(), 3) + self.assertAlmostEqual(767.8 / 6.0, self.evaluate(loss), 3) def testNonZeroLossWithTwoDimBatchSpecificWeights(self): weights = constant_op.constant([1.2, 3.4], shape=[2, 1]) loss = losses.mean_squared_error(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(767.8 / 6.0, loss.eval(), 3) + self.assertAlmostEqual(767.8 / 6.0, self.evaluate(loss), 3) def testNonZeroLossWithSampleSpecificWeights(self): weights = constant_op.constant([3, 6, 5, 0, 4, 2], shape=[2, 3]) loss = losses.mean_squared_error(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(587 / 5.0, loss.eval(), 3) + self.assertAlmostEqual(587 / 5.0, self.evaluate(loss), 3) def testNonZeroLossWithSampleSpecificWeightsMostZero(self): weights = constant_op.constant([0, 0, 0, 0, 0, 2], shape=[2, 3]) loss = losses.mean_squared_error(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(18.0, loss.eval(), 3) + self.assertAlmostEqual(18.0, self.evaluate(loss), 3) def testLossWithSampleSpecificWeightsAllZero(self): weights = array_ops.zeros((2, 3)) loss = losses.mean_squared_error(self._labels, self._predictions, weights) with self.cached_session(): - self.assertAlmostEqual(0.0, loss.eval(), 3) + self.assertAlmostEqual(0.0, self.evaluate(loss), 3) class MeanPairwiseSquaredErrorTest(test.TestCase): @@ -991,7 +1047,8 @@ class MeanPairwiseSquaredErrorTest(test.TestCase): with self.cached_session(): static_inputs_op = losses.mean_pairwise_squared_error( predictions=predictions, labels=labels, weights=weights) - self.assertAlmostEqual(expected_loss, static_inputs_op.eval(), places=3) + self.assertAlmostEqual( + expected_loss, self.evaluate(static_inputs_op), places=3) predictions_placeholder = array_ops.placeholder( dtypes.float32, shape=np.asarray(predictions.shape)) @@ -1011,10 +1068,12 @@ class MeanPairwiseSquaredErrorTest(test.TestCase): self.assertAlmostEqual( expected_loss, dynamic_inputs_op.eval(feed_dict=feed_dict), places=3) + @test_util.run_deprecated_v1 def testAllCorrectNoLossWeight(self): self._test_valid_weights( self._labels, self._labels, expected_loss=0.0) + @test_util.run_deprecated_v1 def testNonZeroLoss(self): self._test_valid_weights( self._labels, self._predictions, @@ -1040,11 +1099,12 @@ class MeanPairwiseSquaredErrorTest(test.TestCase): init_op = variables.global_variables_initializer() with self.cached_session() as sess: - sess.run(init_op) + self.evaluate(init_op) for grad, _ in gradients_to_variables: - np_grad = sess.run(grad) + np_grad = self.evaluate(grad) self.assertFalse(np.isnan(np_grad).any()) + @test_util.run_deprecated_v1 def testNonZeroLossWithPythonScalarWeight(self): weight = 2.3 self._test_valid_weights( @@ -1052,6 +1112,7 @@ class MeanPairwiseSquaredErrorTest(test.TestCase): expected_loss=weight * np.sum(self._expected_losses), weights=weight) + @test_util.run_deprecated_v1 def testNonZeroLossWithScalarTensorWeight(self): weights = 2.3 loss = losses.mean_pairwise_squared_error( @@ -1060,12 +1121,14 @@ class MeanPairwiseSquaredErrorTest(test.TestCase): weights=constant_op.constant(weights)) with self.cached_session(): self.assertAlmostEqual(weights * np.sum(self._expected_losses), - loss.eval(), 3) + self.evaluate(loss), 3) + @test_util.run_deprecated_v1 def testNonZeroLossWithScalarZeroWeight(self): self._test_valid_weights( self._labels, self._predictions, expected_loss=0.0, weights=0.0) + @test_util.run_deprecated_v1 def test3d(self): labels = np.array([ [[1, 9, 2], [12, 11, 10], [9, 8, 7]], @@ -1077,6 +1140,7 @@ class MeanPairwiseSquaredErrorTest(test.TestCase): ]) self._test_valid_weights(labels, predictions, expected_loss=137.5) + @test_util.run_deprecated_v1 def test3dWeightedScalar(self): labels = np.array([ [[1, 9, 2], [12, 11, 10], [9, 8, 7]], @@ -1115,6 +1179,7 @@ class MeanPairwiseSquaredErrorTest(test.TestCase): weights_placeholder: weights, }) + @test_util.run_deprecated_v1 def testInvalid3dWeighted2x0(self): labels = np.array([ [[1, 9, 2], [12, 11, 10], [9, 8, 7]], @@ -1127,6 +1192,7 @@ class MeanPairwiseSquaredErrorTest(test.TestCase): self._test_invalid_weights( labels, predictions, weights=np.asarray((1.2, 3.4))) + @test_util.run_deprecated_v1 def test3dWeighted2x3x3(self): labels = np.array([ [[1, 9, 2], [12, 11, 10], [9, 8, 7]], @@ -1143,6 +1209,7 @@ class MeanPairwiseSquaredErrorTest(test.TestCase): expected_loss=9 * 137.5, weights=np.ones((2, 3, 3))) + @test_util.run_deprecated_v1 def testLossWithAllZeroBatchSpecificWeights(self): self._test_valid_weights( self._labels, self._predictions, expected_loss=0.0, @@ -1215,7 +1282,7 @@ class CosineDistanceLossTest(test.TestCase): labels=constant_op.constant(self._labels), dim=2) with self.cached_session(): - self.assertAlmostEqual(0, loss.eval(), 5) + self.assertAlmostEqual(0, self.evaluate(loss), 5) def testPartiallyCorrectWithIntegerValues(self): loss = losses.cosine_distance( @@ -1223,7 +1290,7 @@ class CosineDistanceLossTest(test.TestCase): labels=constant_op.constant(self._labels), dim=2) with self.cached_session(): - self.assertAlmostEqual(1, loss.eval(), 5) + self.assertAlmostEqual(1, self.evaluate(loss), 5) def testPartiallyCorrectFloatingPointValues(self): predictions = np.matrix( @@ -1241,7 +1308,7 @@ class CosineDistanceLossTest(test.TestCase): loss = losses.cosine_distance(tf_labels, tf_preds, dim=2) with self.cached_session(): - self.assertAlmostEqual(1.0, loss.eval(), 5) + self.assertAlmostEqual(1.0, self.evaluate(loss), 5) def testSampleSpecificWeights(self): loss = losses.cosine_distance( @@ -1250,7 +1317,7 @@ class CosineDistanceLossTest(test.TestCase): dim=2, weights=np.asarray((1, 0, 0)).reshape((3, 1, 1))) with self.cached_session(): - self.assertEqual(1.0, loss.eval()) + self.assertEqual(1.0, self.evaluate(loss)) def testMeasurementSpecificWeights(self): loss = losses.cosine_distance( @@ -1260,8 +1327,9 @@ class CosineDistanceLossTest(test.TestCase): weights=constant_op.constant( [1, 0, 0, 1, 1, 1], shape=(3, 2, 1))) with self.cached_session(): - self.assertEqual(3.0 / 4.0, loss.eval()) + self.assertEqual(3.0 / 4.0, self.evaluate(loss)) + @test_util.run_deprecated_v1 def testMeasurementSpecificWeightsWithPlaceholderWithShape(self): tf_predictions = array_ops.placeholder( dtypes.float32, shape=self._labels.shape) @@ -1282,7 +1350,7 @@ class CosineDistanceLossTest(test.TestCase): dim=2, weights=array_ops.zeros((3, 1, 1))) with self.cached_session(): - self.assertEqual(0, loss.eval()) + self.assertEqual(0, self.evaluate(loss)) def testZeroLossWhenAllMeasurementSpecificWeightsAreZero(self): loss = losses.cosine_distance( @@ -1291,7 +1359,7 @@ class CosineDistanceLossTest(test.TestCase): dim=2, weights=array_ops.zeros((3, 2, 1))) with self.cached_session(): - self.assertEqual(0, loss.eval()) + self.assertEqual(0, self.evaluate(loss)) class AddLossTest(test.TestCase): @@ -1351,15 +1419,16 @@ class ComputeWeightedLossTest(test.TestCase): with self.session(g): for unweighted_loss in unweighted_losses: if reduction == losses.Reduction.NONE: - self.assertAllClose(self._raw_losses, unweighted_loss.eval()) + self.assertAllClose(self._raw_losses, + self.evaluate(unweighted_loss)) elif reduction == losses.Reduction.SUM: self.assertAllClose( - np.sum(self._raw_losses), unweighted_loss.eval()) + np.sum(self._raw_losses), self.evaluate(unweighted_loss)) else: # reduction one of MEAN, SUM_OVER_NONZERO_WEIGHTS, # SUM_BY_NONZERO_WEIGHTS or SUM_OVER_BATCH_SIZE. self.assertAllClose( - np.mean(self._raw_losses), unweighted_loss.eval()) + np.mean(self._raw_losses), self.evaluate(unweighted_loss)) def testUnweightedFromPlaceholder(self): for reduction in losses.Reduction.all(): @@ -1398,7 +1467,7 @@ class ComputeWeightedLossTest(test.TestCase): self.assertEqual(1, len(util.get_losses())) with self.cached_session(): self.assertAllClose( - np.mean(weight * self._raw_losses), weighted_loss.eval()) + np.mean(weight * self._raw_losses), self.evaluate(weighted_loss)) def _test_invalid_weights(self, weights): with ops.Graph().as_default(): @@ -1470,24 +1539,22 @@ class ComputeWeightedLossTest(test.TestCase): weighted_losses = weights * self._raw_losses weighted_sum = np.sum(weighted_losses) if reduction == losses.Reduction.NONE: - self.assertAllClose(weighted_losses, weighted_loss.eval()) + self.assertAllClose(weighted_losses, self.evaluate(weighted_loss)) elif reduction == losses.Reduction.SUM: - self.assertAllClose(weighted_sum, weighted_loss.eval()) + self.assertAllClose(weighted_sum, self.evaluate(weighted_loss)) else: broadcast_weights = weights * np.ones_like(self._raw_losses) if reduction == losses.Reduction.MEAN: - self.assertAllClose( - weighted_sum / np.sum(broadcast_weights), - weighted_loss.eval()) + self.assertAllClose(weighted_sum / np.sum(broadcast_weights), + self.evaluate(weighted_loss)) elif (reduction == losses.Reduction.SUM_OVER_NONZERO_WEIGHTS or reduction == losses.Reduction.SUM_BY_NONZERO_WEIGHTS): self.assertAllClose( weighted_sum / np.count_nonzero(broadcast_weights), - weighted_loss.eval()) + self.evaluate(weighted_loss)) elif reduction == losses.Reduction.SUM_OVER_BATCH_SIZE: - self.assertAllClose( - weighted_sum / self._raw_losses.size, - weighted_loss.eval()) + self.assertAllClose(weighted_sum / self._raw_losses.size, + self.evaluate(weighted_loss)) def test1x1x1Weight(self): self._test_valid_weights((((17.0,),),)) diff --git a/tensorflow/python/kernel_tests/lrn_op_test.py b/tensorflow/python/kernel_tests/lrn_op_test.py index 7ebeb91d90..fbe628c394 100644 --- a/tensorflow/python/kernel_tests/lrn_op_test.py +++ b/tensorflow/python/kernel_tests/lrn_op_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl @@ -92,6 +93,7 @@ class LRNOpTest(test.TestCase): self.assertTrue(err < 1e-2) self.assertShapeEqual(expected, lrn_t) + @test_util.run_deprecated_v1 def testCompute(self): for _ in range(2): self._RunAndVerify(dtypes.float32) @@ -99,6 +101,7 @@ class LRNOpTest(test.TestCase): if not test.is_gpu_available(): self._RunAndVerify(dtypes.float16) + @test_util.run_deprecated_v1 def testGradientsZeroInput(self): with self.session(use_gpu=True): shape = [4, 4, 4, 4] @@ -147,6 +150,7 @@ class LRNOpTest(test.TestCase): else: self.assertLess(err, 1.0) + @test_util.run_deprecated_v1 def testGradients(self): for _ in range(2): self._RunAndVerifyGradients(dtypes.float32) diff --git a/tensorflow/python/kernel_tests/manip_ops_test.py b/tensorflow/python/kernel_tests/manip_ops_test.py index f71857a3cb..5700db4b95 100644 --- a/tensorflow/python/kernel_tests/manip_ops_test.py +++ b/tensorflow/python/kernel_tests/manip_ops_test.py @@ -62,6 +62,7 @@ class RollTest(test_util.TensorFlowTestCase): if np_input.dtype == np.float32: self._testGradient(np_input, shift, axis) + @test_util.run_deprecated_v1 def testIntTypes(self): for t in [np.int32, np.int64]: self._testAll(np.random.randint(-100, 100, (5)).astype(t), 3, 0) @@ -73,6 +74,7 @@ class RollTest(test_util.TensorFlowTestCase): np.random.randint(-100, 100, (4, 2, 1, 3)).astype(t), [0, 1, -2], [1, 2, 3]) + @test_util.run_deprecated_v1 def testFloatTypes(self): for t in [np.float32, np.float64]: self._testAll(np.random.rand(5).astype(t), 2, 0) @@ -80,6 +82,7 @@ class RollTest(test_util.TensorFlowTestCase): self._testAll(np.random.rand(3, 4).astype(t), [1, 2], [1, 0]) self._testAll(np.random.rand(1, 3, 4).astype(t), [1, 0, -3], [0, 1, 2]) + @test_util.run_deprecated_v1 def testComplexTypes(self): for t in [np.complex64, np.complex128]: x = np.random.rand(4, 4).astype(t) @@ -90,6 +93,7 @@ class RollTest(test_util.TensorFlowTestCase): x = np.random.rand(3, 2, 1, 1).astype(t) self._testAll(x + 1j * x, [2, 1, 1, 0], [0, 3, 1, 2]) + @test_util.run_deprecated_v1 def testNegativeAxis(self): self._testAll(np.random.randint(-100, 100, (5)).astype(np.int32), 3, -1) self._testAll(np.random.randint(-100, 100, (4, 4)).astype(np.int32), 3, -2) @@ -100,12 +104,14 @@ class RollTest(test_util.TensorFlowTestCase): manip_ops.roll(np.random.randint(-100, 100, (4, 4)).astype(np.int32), 3, -10).eval() + @test_util.run_deprecated_v1 def testInvalidInputShape(self): # The input should be 1-D or higher, checked in shape function. with self.assertRaisesRegexp( ValueError, "Shape must be at least rank 1 but is rank 0"): manip_ops.roll(7, 1, 0) + @test_util.run_deprecated_v1 def testRollInputMustVectorHigherRaises(self): # The input should be 1-D or higher, checked in kernel. tensor = array_ops.placeholder(dtype=dtypes.int32) @@ -116,12 +122,14 @@ class RollTest(test_util.TensorFlowTestCase): "input must be 1-D or higher"): manip_ops.roll(tensor, shift, axis).eval(feed_dict={tensor: 7}) + @test_util.run_deprecated_v1 def testInvalidAxisShape(self): # The axis should be a scalar or 1-D, checked in shape function. with self.assertRaisesRegexp( ValueError, "Shape must be at most rank 1 but is rank 2"): manip_ops.roll([[1, 2], [3, 4]], 1, [[0, 1]]) + @test_util.run_deprecated_v1 def testRollAxisMustBeScalarOrVectorRaises(self): # The axis should be a scalar or 1-D, checked in kernel. tensor = [[1, 2], [3, 4]] @@ -132,12 +140,14 @@ class RollTest(test_util.TensorFlowTestCase): "axis must be a scalar or a 1-D vector"): manip_ops.roll(tensor, shift, axis).eval(feed_dict={axis: [[0, 1]]}) + @test_util.run_deprecated_v1 def testInvalidShiftShape(self): # The shift should be a scalar or 1-D, checked in shape function. with self.assertRaisesRegexp( ValueError, "Shape must be at most rank 1 but is rank 2"): manip_ops.roll([[1, 2], [3, 4]], [[0, 1]], 1) + @test_util.run_deprecated_v1 def testRollShiftMustBeScalarOrVectorRaises(self): # The shift should be a scalar or 1-D, checked in kernel. tensor = [[1, 2], [3, 4]] @@ -148,11 +158,13 @@ class RollTest(test_util.TensorFlowTestCase): "shift must be a scalar or a 1-D vector"): manip_ops.roll(tensor, shift, axis).eval(feed_dict={shift: [[0, 1]]}) + @test_util.run_deprecated_v1 def testInvalidShiftAndAxisNotEqualShape(self): # The shift and axis must be same size, checked in shape function. with self.assertRaisesRegexp(ValueError, "both shapes must be equal"): manip_ops.roll([[1, 2], [3, 4]], [1], [0, 1]) + @test_util.run_deprecated_v1 def testRollShiftAndAxisMustBeSameSizeRaises(self): # The shift and axis must be same size, checked in kernel. tensor = [[1, 2], [3, 4]] diff --git a/tensorflow/python/kernel_tests/map_stage_op_test.py b/tensorflow/python/kernel_tests/map_stage_op_test.py index d503f3d7c9..dd16fad690 100644 --- a/tensorflow/python/kernel_tests/map_stage_op_test.py +++ b/tensorflow/python/kernel_tests/map_stage_op_test.py @@ -19,6 +19,7 @@ from __future__ import print_function from tensorflow.python.framework import errors from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import math_ops @@ -29,6 +30,7 @@ TIMEOUT = 1 class MapStageTest(test.TestCase): + @test_util.run_deprecated_v1 def testSimple(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -50,6 +52,7 @@ class MapStageTest(test.TestCase): _, yval = sess.run([stage, y], feed_dict={x: i, pi: i + 1, gi: i}) self.assertAllClose(4 * (i - 1) * (i - 1) * 128, yval, rtol=1e-4) + @test_util.run_deprecated_v1 def testMultiple(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -72,6 +75,7 @@ class MapStageTest(test.TestCase): self.assertAllClose( 4 * (i - 1) * (i - 1) * (i - 1) * 128, yval, rtol=1e-4) + @test_util.run_deprecated_v1 def testDictionary(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -121,6 +125,7 @@ class MapStageTest(test.TestCase): G.finalize() + @test_util.run_deprecated_v1 def testPeek(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -150,6 +155,7 @@ class MapStageTest(test.TestCase): self.assertTrue(sess.run(size) == 10) + @test_util.run_deprecated_v1 def testSizeAndClear(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -176,6 +182,7 @@ class MapStageTest(test.TestCase): sess.run(clear) self.assertEqual(sess.run(size), 0) + @test_util.run_deprecated_v1 def testCapacity(self): capacity = 3 @@ -239,6 +246,7 @@ class MapStageTest(test.TestCase): self.assertTrue(sess.run(size) == 0) + @test_util.run_deprecated_v1 def testMemoryLimit(self): memory_limit = 512 * 1024 # 512K chunk = 200 * 1024 # 256K @@ -303,6 +311,7 @@ class MapStageTest(test.TestCase): self.assertTrue(sess.run(size) == 0) + @test_util.run_deprecated_v1 def testOrdering(self): import six import random @@ -341,6 +350,7 @@ class MapStageTest(test.TestCase): self.assertTrue(sess.run(size) == 0) + @test_util.run_deprecated_v1 def testPartialDictInsert(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -400,6 +410,7 @@ class MapStageTest(test.TestCase): 'v': 3 }]) + @test_util.run_deprecated_v1 def testPartialIndexInsert(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -443,6 +454,7 @@ class MapStageTest(test.TestCase): # We can now obtain tuple associated with key 1 self.assertTrue(sess.run([key, ret], feed_dict={gi: 1}) == [1, [1, 3, 2]]) + @test_util.run_deprecated_v1 def testPartialDictGetsAndPeeks(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -540,6 +552,7 @@ class MapStageTest(test.TestCase): # Nothing is left self.assertTrue(sess.run([size, isize]) == [0, 0]) + @test_util.run_deprecated_v1 def testPartialIndexGets(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): diff --git a/tensorflow/python/kernel_tests/matmul_op_test.py b/tensorflow/python/kernel_tests/matmul_op_test.py index 1c2822180a..983f463f5e 100644 --- a/tensorflow/python/kernel_tests/matmul_op_test.py +++ b/tensorflow/python/kernel_tests/matmul_op_test.py @@ -44,7 +44,7 @@ class MatVecTest(test_lib.TestCase): with self.cached_session(): c = math_ops.matvec(a, b) self.assertAllEqual((2,), c.shape) - c_ = c.eval() + c_ = self.evaluate(c) self.assertAllEqual([5 + 2 * 6, 3 * 5 + 4 * 6], c_) @@ -90,7 +90,7 @@ def _GetMatMulTest(a_np_, b_np_, use_static_shape_, **kwargs_): a = constant_op.constant(effective_a_np) b = constant_op.constant(effective_b_np) res = math_ops.matmul(a, b, **kwargs_) - tf_val = res.eval() + tf_val = self.evaluate(res) else: a = array_ops.placeholder(a_np_.dtype) b = array_ops.placeholder(b_np_.dtype) @@ -194,6 +194,7 @@ except AttributeError: class MatMulInfixOperatorTest(test_lib.TestCase): + @test_util.run_deprecated_v1 def testMismatchedShape(self): with self.assertRaisesWithPredicateMatch(ValueError, lambda e: "Shape must" in str(e)): @@ -201,6 +202,7 @@ class MatMulInfixOperatorTest(test_lib.TestCase): ops.convert_to_tensor([10.0, 20.0, 30.0]), ops.convert_to_tensor([[40.0, 50.0], [60.0, 70.0]])) + @test_util.run_deprecated_v1 def testMismatchedDimensions(self): with self.assertRaisesWithPredicateMatch( ValueError, lambda e: "Dimensions must" in str(e)): @@ -208,19 +210,21 @@ class MatMulInfixOperatorTest(test_lib.TestCase): ops.convert_to_tensor([[10.0, 20.0, 30.0]]), ops.convert_to_tensor([[40.0, 50.0], [60.0, 70.0]])) + @test_util.run_deprecated_v1 def testInfixMatmulIsTfMatmul(self): a = ops.convert_to_tensor([[10.0, 20.0, 30.0]]) b = ops.convert_to_tensor([[40.0, 50.0], [60.0, 70.0], [80.0, 90.0]]) c = infix_matmul(a, b) self.assertEqual(c.op.type, "MatMul") + @test_util.run_deprecated_v1 def testInfixMatmulDoesDotProduct(self): a = ops.convert_to_tensor([[10.0, 20.0, 30.0]]) b = ops.convert_to_tensor([[40.0, 50.0], [60.0, 70.0], [80.0, 90.0]]) c = infix_matmul(a, b) d = math_ops.matmul(a, b) with self.cached_session(): - self.assertAllEqual(c.eval(), d.eval()) + self.assertAllEqual(c.eval(), self.evaluate(d)) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/matrix_band_part_op_test.py b/tensorflow/python/kernel_tests/matrix_band_part_op_test.py index 93a668f125..129ea40dfe 100644 --- a/tensorflow/python/kernel_tests/matrix_band_part_op_test.py +++ b/tensorflow/python/kernel_tests/matrix_band_part_op_test.py @@ -62,7 +62,7 @@ def _GetMatrixBandPartTest(dtype_, batch_shape_, shape_): batch_mat, constant_op.constant(lower, index_dtype), constant_op.constant(upper, index_dtype)) - self.assertAllEqual(band_np, band.eval()) + self.assertAllEqual(band_np, self.evaluate(band)) return Test diff --git a/tensorflow/python/kernel_tests/matrix_exponential_op_test.py b/tensorflow/python/kernel_tests/matrix_exponential_op_test.py index 3abdf50ece..372b6dc17f 100644 --- a/tensorflow/python/kernel_tests/matrix_exponential_op_test.py +++ b/tensorflow/python/kernel_tests/matrix_exponential_op_test.py @@ -25,6 +25,7 @@ import numpy as np from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import random_ops @@ -50,7 +51,7 @@ class ExponentialOpTest(test.TestCase): def _verifyExponential(self, x, np_type): inp = x.astype(np_type) - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): tf_ans = linalg_impl.matrix_exponential(inp) if x.size == 0: np_ans = np.empty(x.shape, dtype=np_type) @@ -61,7 +62,7 @@ class ExponentialOpTest(test.TestCase): np_ans[i] = np_expm(inp[i]) else: np_ans = np_expm(inp) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertAllClose(np_ans, out, rtol=1e-4, atol=1e-3) def _verifyExponentialReal(self, x): @@ -121,12 +122,14 @@ class ExponentialOpTest(test.TestCase): # Complex batch self._verifyExponentialComplex(self._makeBatch(matrix1, matrix2)) + @test_util.run_deprecated_v1 def testNonSquareMatrix(self): # When the exponential of a non-square matrix is attempted we should return # an error with self.assertRaises(ValueError): linalg_impl.matrix_exponential(np.array([[1., 2., 3.], [3., 4., 5.]])) + @test_util.run_deprecated_v1 def testWrongDimensions(self): # The input to the exponential should be at least a 2-dimensional tensor. tensor3 = constant_op.constant([1., 2.]) @@ -137,6 +140,7 @@ class ExponentialOpTest(test.TestCase): self._verifyExponentialReal(np.empty([0, 2, 2])) self._verifyExponentialReal(np.empty([2, 0, 0])) + @test_util.run_deprecated_v1 def testDynamic(self): with self.session(use_gpu=True) as sess: inp = array_ops.placeholder(ops.dtypes.float32) @@ -144,13 +148,14 @@ class ExponentialOpTest(test.TestCase): matrix = np.array([[1., 2.], [3., 4.]]) sess.run(expm, feed_dict={inp: matrix}) + @test_util.run_deprecated_v1 def testConcurrentExecutesWithoutError(self): with self.session(use_gpu=True) as sess: matrix1 = random_ops.random_normal([5, 5], seed=42) matrix2 = random_ops.random_normal([5, 5], seed=42) expm1 = linalg_impl.matrix_exponential(matrix1) expm2 = linalg_impl.matrix_exponential(matrix2) - expm = sess.run([expm1, expm2]) + expm = self.evaluate([expm1, expm2]) self.assertAllEqual(expm[0], expm[1]) diff --git a/tensorflow/python/kernel_tests/matrix_inverse_op_test.py b/tensorflow/python/kernel_tests/matrix_inverse_op_test.py index 2247f1541e..5cef4b79a3 100644 --- a/tensorflow/python/kernel_tests/matrix_inverse_op_test.py +++ b/tensorflow/python/kernel_tests/matrix_inverse_op_test.py @@ -46,7 +46,7 @@ class InverseOpTest(test.TestCase): tiling = list(y.shape) tiling[-2:] = [1, 1] np_ans = np.tile(np_ans, tiling) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertAllClose(np_ans, out, rtol=1e-4, atol=1e-3) self.assertShapeEqual(y, tf_ans) @@ -146,7 +146,7 @@ class InverseOpTest(test.TestCase): inv1 = linalg_ops.matrix_inverse(matrix1, adjoint=adjoint_) inv2 = linalg_ops.matrix_inverse(matrix2, adjoint=adjoint_) all_ops += [inv1, inv2] - inv = sess.run(all_ops) + inv = self.evaluate(all_ops) self.assertAllEqual(inv[0], inv[1]) self.assertAllEqual(inv[2], inv[3]) diff --git a/tensorflow/python/kernel_tests/matrix_logarithm_op_test.py b/tensorflow/python/kernel_tests/matrix_logarithm_op_test.py index 2010a4b2a8..b0bce6a1b9 100644 --- a/tensorflow/python/kernel_tests/matrix_logarithm_op_test.py +++ b/tensorflow/python/kernel_tests/matrix_logarithm_op_test.py @@ -25,6 +25,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_linalg_ops from tensorflow.python.ops import math_ops @@ -39,11 +40,11 @@ class LogarithmOpTest(test.TestCase): def _verifyLogarithm(self, x, np_type): inp = x.astype(np_type) - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): # Verify that expm(logm(A)) == A. tf_ans = linalg_impl.matrix_exponential( gen_linalg_ops.matrix_logarithm(inp)) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertAllClose(inp, out, rtol=1e-4, atol=1e-3) def _verifyLogarithmComplex(self, x): @@ -128,7 +129,7 @@ class LogarithmOpTest(test.TestCase): random_ops.random_normal([5, 5], seed=42), dtypes.complex64) logm1 = gen_linalg_ops.matrix_logarithm(matrix1) logm2 = gen_linalg_ops.matrix_logarithm(matrix2) - logm = sess.run([logm1, logm2]) + logm = self.evaluate([logm1, logm2]) self.assertAllEqual(logm[0], logm[1]) diff --git a/tensorflow/python/kernel_tests/matrix_solve_ls_op_test.py b/tensorflow/python/kernel_tests/matrix_solve_ls_op_test.py index 13a7df7f95..a6f5da9d3d 100644 --- a/tensorflow/python/kernel_tests/matrix_solve_ls_op_test.py +++ b/tensorflow/python/kernel_tests/matrix_solve_ls_op_test.py @@ -24,6 +24,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import linalg_ops @@ -133,6 +134,7 @@ class MatrixSolveLsOpTest(test_lib.TestCase): self.assertEqual(np_ans.shape, tf_ans_val.shape) self.assertAllClose(np_ans, tf_ans_val, atol=2 * tol, rtol=2 * tol) + @test_util.run_deprecated_v1 def testWrongDimensions(self): # The matrix and right-hand sides should have the same number of rows. with self.session(use_gpu=True): @@ -141,6 +143,7 @@ class MatrixSolveLsOpTest(test_lib.TestCase): with self.assertRaises(ValueError): linalg_ops.matrix_solve_ls(matrix, rhs) + @test_util.run_deprecated_v1 def testEmpty(self): full = np.array([[1., 2.], [3., 4.], [5., 6.]]) empty0 = np.empty([3, 0]) @@ -156,6 +159,7 @@ class MatrixSolveLsOpTest(test_lib.TestCase): tf_ans = linalg_ops.matrix_solve_ls(empty1, empty1, fast=fast).eval() self.assertEqual(tf_ans.shape, (2, 2)) + @test_util.run_deprecated_v1 def testBatchResultSize(self): # 3x3x3 matrices, 3x3x1 right-hand sides. matrix = np.array([1., 2., 3., 4., 5., 6., 7., 8., 9.] * 3).reshape(3, 3, 3) diff --git a/tensorflow/python/kernel_tests/matrix_solve_op_test.py b/tensorflow/python/kernel_tests/matrix_solve_op_test.py index 9e30ae1628..db7c4802f6 100644 --- a/tensorflow/python/kernel_tests/matrix_solve_op_test.py +++ b/tensorflow/python/kernel_tests/matrix_solve_op_test.py @@ -24,6 +24,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import linalg_ops @@ -63,7 +64,7 @@ class MatrixSolveOpTest(test.TestCase): out = sess.run(tf_ans, {a_ph: a, b_ph: b}) else: tf_ans = linalg_ops.matrix_solve(a, b, adjoint=adjoint) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertEqual(tf_ans.get_shape(), out.shape) self.assertEqual(np_ans.shape, out.shape) self.assertAllClose(np_ans, out, atol=tol, rtol=tol) @@ -75,6 +76,7 @@ class MatrixSolveOpTest(test.TestCase): [m, n])) return matrix + @test_util.run_deprecated_v1 def testSolve(self): for n in 1, 2, 4, 9: matrix = self._generateMatrix(n, n) @@ -82,6 +84,7 @@ class MatrixSolveOpTest(test.TestCase): rhs = self._generateMatrix(n, nrhs) self._verifySolve(matrix, rhs) + @test_util.run_deprecated_v1 def testSolveBatch(self): for n in 2, 5: matrix = self._generateMatrix(n, n) @@ -90,6 +93,7 @@ class MatrixSolveOpTest(test.TestCase): for batch_dims in [[2], [2, 2], [7, 4]]: self._verifySolve(matrix, rhs, batch_dims=batch_dims) + @test_util.run_deprecated_v1 def testNonSquareMatrix(self): # When the solve of a non-square matrix is attempted we should return # an error @@ -98,6 +102,7 @@ class MatrixSolveOpTest(test.TestCase): matrix = constant_op.constant([[1., 2., 3.], [3., 4., 5.]]) linalg_ops.matrix_solve(matrix, matrix) + @test_util.run_deprecated_v1 def testWrongDimensions(self): # The matrix and right-hand sides should have the same number of rows. with self.session(use_gpu=True): @@ -115,6 +120,7 @@ class MatrixSolveOpTest(test.TestCase): [0., -1., 1.]]) linalg_ops.matrix_solve(matrix, matrix).eval() + @test_util.run_deprecated_v1 def testConcurrent(self): with self.session(use_gpu=True) as sess: all_ops = [] @@ -126,7 +132,7 @@ class MatrixSolveOpTest(test.TestCase): s1 = linalg_ops.matrix_solve(lhs1, rhs1, adjoint=adjoint_) s2 = linalg_ops.matrix_solve(lhs2, rhs2, adjoint=adjoint_) all_ops += [s1, s2] - val = sess.run(all_ops) + val = self.evaluate(all_ops) self.assertAllEqual(val[0], val[1]) self.assertAllEqual(val[2], val[3]) diff --git a/tensorflow/python/kernel_tests/matrix_square_root_op_test.py b/tensorflow/python/kernel_tests/matrix_square_root_op_test.py index 9212580313..1e2109b8c4 100644 --- a/tensorflow/python/kernel_tests/matrix_square_root_op_test.py +++ b/tensorflow/python/kernel_tests/matrix_square_root_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import gen_linalg_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops @@ -31,7 +32,7 @@ class SquareRootOpTest(test.TestCase): def _verifySquareRoot(self, matrix, np_type): matrix = matrix.astype(np_type) - with self.test_session(use_gpu=True): + with test_util.use_gpu(): # Verify that matmul(sqrtm(A), sqrtm(A)) = A sqrt = gen_linalg_ops.matrix_square_root(matrix) square = math_ops.matmul(sqrt, sqrt) @@ -96,19 +97,20 @@ class SquareRootOpTest(test.TestCase): gen_linalg_ops.matrix_square_root(tensor) def testNotSquare(self): - with self.test_session(): - with self.assertRaises(ValueError): - tensor = constant_op.constant([[1., 0., -1.], [-1., 1., 0.]]) - gen_linalg_ops.matrix_square_root(tensor).eval() + with self.assertRaises(ValueError): + tensor = constant_op.constant([[1., 0., -1.], [-1., 1., 0.]]) + self.evaluate(gen_linalg_ops.matrix_square_root(tensor)) def testConcurrentExecutesWithoutError(self): - with self.test_session(use_gpu=True) as sess: + with test_util.use_gpu(): matrix1 = random_ops.random_normal([5, 5], seed=42) matrix2 = random_ops.random_normal([5, 5], seed=42) - sqrt1 = gen_linalg_ops.matrix_square_root(matrix1) - sqrt2 = gen_linalg_ops.matrix_square_root(matrix2) + square1 = math_ops.matmul(matrix1, matrix1) + square2 = math_ops.matmul(matrix2, matrix2) + sqrt1 = gen_linalg_ops.matrix_square_root(square1) + sqrt2 = gen_linalg_ops.matrix_square_root(square2) all_ops = [sqrt1, sqrt2] - sqrt = sess.run(all_ops) + sqrt = self.evaluate(all_ops) self.assertAllEqual(sqrt[0], sqrt[1]) diff --git a/tensorflow/python/kernel_tests/matrix_triangular_solve_op_test.py b/tensorflow/python/kernel_tests/matrix_triangular_solve_op_test.py index 445faca3ee..dde83f12f3 100644 --- a/tensorflow/python/kernel_tests/matrix_triangular_solve_op_test.py +++ b/tensorflow/python/kernel_tests/matrix_triangular_solve_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import linalg_ops from tensorflow.python.platform import test @@ -87,12 +88,13 @@ class MatrixTriangularSolveOpTest(test.TestCase): b_tf = constant_op.constant(b) tf_ans = linalg_ops.matrix_triangular_solve( a_tf, b_tf, lower=lower, adjoint=adjoint) - tf_val = tf_ans.eval() + tf_val = self.evaluate(tf_ans) np_ans = np.linalg.solve(a_np, b) self.assertEqual(np_ans.shape, tf_ans.get_shape()) self.assertEqual(np_ans.shape, tf_val.shape) self.assertAllClose(np_ans, tf_val) + @test_util.run_deprecated_v1 def testSolve(self): # 1x1 matrix, single rhs. matrix = np.array([[0.1]]) @@ -106,6 +108,7 @@ class MatrixTriangularSolveOpTest(test.TestCase): rhs1 = np.array([[1., 0., 1.], [0., 1., 1.]]) self._verifySolveAllWaysReal(matrix, rhs1) + @test_util.run_deprecated_v1 def testSolveComplex(self): # 1x1 matrix, single rhs. matrix = np.array([[0.1 + 1j * 0.1]]) @@ -122,6 +125,7 @@ class MatrixTriangularSolveOpTest(test.TestCase): rhs1 += 1j * rhs1 self._verifySolveAllWaysComplex(matrix, rhs1) + @test_util.run_deprecated_v1 def testSolveBatch(self): matrix = np.array([[1., 2.], [3., 4.]]) rhs = np.array([[1., 0., 1.], [0., 1., 1.]]) @@ -130,6 +134,7 @@ class MatrixTriangularSolveOpTest(test.TestCase): # Batch of 3x2x2x2 matrices, 3x2x2x3 right-hand sides. self._verifySolveAllWaysReal(matrix, rhs, batch_dims=[3, 2]) + @test_util.run_deprecated_v1 def testSolveBatchComplex(self): matrix = np.array([[1., 2.], [3., 4.]]).astype(np.complex64) matrix += 1j * matrix @@ -140,6 +145,7 @@ class MatrixTriangularSolveOpTest(test.TestCase): # Batch of 3x2x2x2 matrices, 3x2x2x3 right-hand sides. self._verifySolveAllWaysComplex(matrix, rhs, batch_dims=[3, 2]) + @test_util.run_deprecated_v1 def testNonSquareMatrix(self): # A non-square matrix should cause an error. matrix = np.array([[1., 2., 3.], [3., 4., 5.]]) @@ -149,6 +155,7 @@ class MatrixTriangularSolveOpTest(test.TestCase): with self.assertRaises(ValueError): self._verifySolve(matrix, matrix, batch_dims=[2, 3]) + @test_util.run_deprecated_v1 def testWrongDimensions(self): # The matrix should have the same number of rows as the # right-hand sides. diff --git a/tensorflow/python/kernel_tests/metrics_test.py b/tensorflow/python/kernel_tests/metrics_test.py index 5dcdb9e420..64dd591455 100644 --- a/tensorflow/python/kernel_tests/metrics_test.py +++ b/tensorflow/python/kernel_tests/metrics_test.py @@ -29,6 +29,7 @@ from tensorflow.python.framework import dtypes as dtypes_lib from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import math_ops @@ -175,22 +176,26 @@ class MeanTest(test.TestCase): def setUp(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.mean(array_ops.ones([4, 3])) _assert_metric_variables(self, ('mean/count:0', 'mean/total:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.mean( array_ops.ones([4, 3]), metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.mean( array_ops.ones([4, 3]), updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testBasic(self): with self.cached_session() as sess: values_queue = data_flow_ops.FIFOQueue( @@ -203,11 +208,12 @@ class MeanTest(test.TestCase): mean, update_op = metrics.mean(values) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(4): - sess.run(update_op) - self.assertAlmostEqual(1.65, sess.run(mean), 5) + self.evaluate(update_op) + self.assertAlmostEqual(1.65, self.evaluate(mean), 5) + @test_util.run_deprecated_v1 def testUpdateOpsReturnsCurrentValue(self): with self.cached_session() as sess: values_queue = data_flow_ops.FIFOQueue( @@ -220,15 +226,16 @@ class MeanTest(test.TestCase): mean, update_op = metrics.mean(values) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) - self.assertAlmostEqual(0.5, sess.run(update_op), 5) - self.assertAlmostEqual(1.475, sess.run(update_op), 5) - self.assertAlmostEqual(12.4 / 6.0, sess.run(update_op), 5) - self.assertAlmostEqual(1.65, sess.run(update_op), 5) + self.assertAlmostEqual(0.5, self.evaluate(update_op), 5) + self.assertAlmostEqual(1.475, self.evaluate(update_op), 5) + self.assertAlmostEqual(12.4 / 6.0, self.evaluate(update_op), 5) + self.assertAlmostEqual(1.65, self.evaluate(update_op), 5) - self.assertAlmostEqual(1.65, sess.run(mean), 5) + self.assertAlmostEqual(1.65, self.evaluate(mean), 5) + @test_util.run_deprecated_v1 def testUnweighted(self): values = _test_values((3, 2, 4, 1)) mean_results = ( @@ -271,37 +278,44 @@ class MeanTest(test.TestCase): self.assertAlmostEqual(expected, update_op.eval(), places=5) self.assertAlmostEqual(expected, mean.eval(), places=5) + @test_util.run_deprecated_v1 def test1x1x1Weighted(self): self._test_3d_weighted( _test_values((3, 2, 4)), weights=np.asarray((5,)).reshape((1, 1, 1))) + @test_util.run_deprecated_v1 def test1x1xNWeighted(self): self._test_3d_weighted( _test_values((3, 2, 4)), weights=np.asarray((5, 7, 11, 3)).reshape((1, 1, 4))) + @test_util.run_deprecated_v1 def test1xNx1Weighted(self): self._test_3d_weighted( _test_values((3, 2, 4)), weights=np.asarray((5, 11)).reshape((1, 2, 1))) + @test_util.run_deprecated_v1 def test1xNxNWeighted(self): self._test_3d_weighted( _test_values((3, 2, 4)), weights=np.asarray((5, 7, 11, 3, 2, 13, 7, 5)).reshape((1, 2, 4))) + @test_util.run_deprecated_v1 def testNx1x1Weighted(self): self._test_3d_weighted( _test_values((3, 2, 4)), weights=np.asarray((5, 7, 11)).reshape((3, 1, 1))) + @test_util.run_deprecated_v1 def testNx1xNWeighted(self): self._test_3d_weighted( _test_values((3, 2, 4)), weights=np.asarray(( 5, 7, 11, 3, 2, 12, 7, 5, 2, 17, 11, 3)).reshape((3, 1, 4))) + @test_util.run_deprecated_v1 def testNxNxNWeighted(self): self._test_3d_weighted( _test_values((3, 2, 4)), @@ -309,6 +323,7 @@ class MeanTest(test.TestCase): 5, 7, 11, 3, 2, 12, 7, 5, 2, 17, 11, 3, 2, 17, 11, 3, 5, 7, 11, 3, 2, 12, 7, 5)).reshape((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidWeights(self): values_placeholder = array_ops.placeholder(dtype=dtypes_lib.float32) values = _test_values((3, 2, 4, 1)) @@ -341,23 +356,27 @@ class MeanTensorTest(test.TestCase): def setUp(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.mean_tensor(array_ops.ones([4, 3])) _assert_metric_variables(self, ('mean/total_tensor:0', 'mean/count_tensor:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.mean_tensor( array_ops.ones([4, 3]), metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.mean_tensor( array_ops.ones([4, 3]), updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testBasic(self): with self.cached_session() as sess: values_queue = data_flow_ops.FIFOQueue( @@ -370,11 +389,12 @@ class MeanTensorTest(test.TestCase): mean, update_op = metrics.mean_tensor(values) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(4): - sess.run(update_op) - self.assertAllClose([[-0.9 / 4., 3.525]], sess.run(mean)) + self.evaluate(update_op) + self.assertAllClose([[-0.9 / 4., 3.525]], self.evaluate(mean)) + @test_util.run_deprecated_v1 def testMultiDimensional(self): with self.cached_session() as sess: values_queue = data_flow_ops.FIFOQueue( @@ -391,11 +411,13 @@ class MeanTensorTest(test.TestCase): mean, update_op = metrics.mean_tensor(values) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(2): - sess.run(update_op) - self.assertAllClose([[[1, 2], [1, 2]], [[2, 3], [5, 6]]], sess.run(mean)) + self.evaluate(update_op) + self.assertAllClose([[[1, 2], [1, 2]], [[2, 3], [5, 6]]], + self.evaluate(mean)) + @test_util.run_deprecated_v1 def testUpdateOpsReturnsCurrentValue(self): with self.cached_session() as sess: values_queue = data_flow_ops.FIFOQueue( @@ -408,15 +430,16 @@ class MeanTensorTest(test.TestCase): mean, update_op = metrics.mean_tensor(values) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) - self.assertAllClose([[0, 1]], sess.run(update_op), 5) - self.assertAllClose([[-2.1, 5.05]], sess.run(update_op), 5) - self.assertAllClose([[2.3 / 3., 10.1 / 3.]], sess.run(update_op), 5) - self.assertAllClose([[-0.9 / 4., 3.525]], sess.run(update_op), 5) + self.assertAllClose([[0, 1]], self.evaluate(update_op), 5) + self.assertAllClose([[-2.1, 5.05]], self.evaluate(update_op), 5) + self.assertAllClose([[2.3 / 3., 10.1 / 3.]], self.evaluate(update_op), 5) + self.assertAllClose([[-0.9 / 4., 3.525]], self.evaluate(update_op), 5) - self.assertAllClose([[-0.9 / 4., 3.525]], sess.run(mean), 5) + self.assertAllClose([[-0.9 / 4., 3.525]], self.evaluate(mean), 5) + @test_util.run_deprecated_v1 def testBinaryWeighted1d(self): with self.cached_session() as sess: # Create the queue that populates the values. @@ -439,11 +462,12 @@ class MeanTensorTest(test.TestCase): mean, update_op = metrics.mean_tensor(values, weights) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(4): - sess.run(update_op) - self.assertAllClose([[3.25, 0.5]], sess.run(mean), 5) + self.evaluate(update_op) + self.assertAllClose([[3.25, 0.5]], self.evaluate(mean), 5) + @test_util.run_deprecated_v1 def testWeighted1d(self): with self.cached_session() as sess: # Create the queue that populates the values. @@ -466,11 +490,12 @@ class MeanTensorTest(test.TestCase): mean, update_op = metrics.mean_tensor(values, weights) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(4): - sess.run(update_op) - self.assertAllClose([[0.8, 3.52]], sess.run(mean), 5) + self.evaluate(update_op) + self.assertAllClose([[0.8, 3.52]], self.evaluate(mean), 5) + @test_util.run_deprecated_v1 def testWeighted2d_1(self): with self.cached_session() as sess: # Create the queue that populates the values. @@ -493,11 +518,12 @@ class MeanTensorTest(test.TestCase): mean, update_op = metrics.mean_tensor(values, weights) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(4): - sess.run(update_op) - self.assertAllClose([[-2.1, 0.5]], sess.run(mean), 5) + self.evaluate(update_op) + self.assertAllClose([[-2.1, 0.5]], self.evaluate(mean), 5) + @test_util.run_deprecated_v1 def testWeighted2d_2(self): with self.cached_session() as sess: # Create the queue that populates the values. @@ -520,10 +546,10 @@ class MeanTensorTest(test.TestCase): mean, update_op = metrics.mean_tensor(values, weights) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(4): - sess.run(update_op) - self.assertAllClose([[0, 0.5]], sess.run(mean), 5) + self.evaluate(update_op) + self.assertAllClose([[0, 0.5]], self.evaluate(mean), 5) class AccuracyTest(test.TestCase): @@ -531,6 +557,7 @@ class AccuracyTest(test.TestCase): def setUp(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.accuracy( predictions=array_ops.ones((10, 1)), @@ -539,6 +566,7 @@ class AccuracyTest(test.TestCase): _assert_metric_variables(self, ('my_accuracy/count:0', 'my_accuracy/total:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.accuracy( @@ -547,6 +575,7 @@ class AccuracyTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.accuracy( @@ -555,12 +584,14 @@ class AccuracyTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testPredictionsAndLabelsOfDifferentSizeRaisesValueError(self): predictions = array_ops.ones((10, 3)) labels = array_ops.ones((10, 4)) with self.assertRaises(ValueError): metrics.accuracy(labels, predictions) + @test_util.run_deprecated_v1 def testPredictionsAndWeightsOfDifferentSizeRaisesValueError(self): predictions = array_ops.ones((10, 3)) labels = array_ops.ones((10, 3)) @@ -568,6 +599,7 @@ class AccuracyTest(test.TestCase): with self.assertRaises(ValueError): metrics.accuracy(labels, predictions, weights) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_uniform( (10, 3), maxval=3, dtype=dtypes_lib.int64, seed=1) @@ -576,17 +608,18 @@ class AccuracyTest(test.TestCase): accuracy, update_op = metrics.accuracy(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_accuracy = accuracy.eval() for _ in range(10): self.assertEqual(initial_accuracy, accuracy.eval()) + @test_util.run_deprecated_v1 def testMultipleUpdates(self): with self.cached_session() as sess: # Create the queue that populates the predictions. @@ -609,32 +642,35 @@ class AccuracyTest(test.TestCase): accuracy, update_op = metrics.accuracy(labels, predictions) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in xrange(3): - sess.run(update_op) - self.assertEqual(0.5, sess.run(update_op)) + self.evaluate(update_op) + self.assertEqual(0.5, self.evaluate(update_op)) self.assertEqual(0.5, accuracy.eval()) + @test_util.run_deprecated_v1 def testEffectivelyEquivalentSizes(self): predictions = array_ops.ones((40, 1)) labels = array_ops.ones((40,)) with self.cached_session() as sess: accuracy, update_op = metrics.accuracy(labels, predictions) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertEqual(1.0, update_op.eval()) self.assertEqual(1.0, accuracy.eval()) + @test_util.run_deprecated_v1 def testEffectivelyEquivalentSizesWithScalarWeight(self): predictions = array_ops.ones((40, 1)) labels = array_ops.ones((40,)) with self.cached_session() as sess: accuracy, update_op = metrics.accuracy(labels, predictions, weights=2.0) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertEqual(1.0, update_op.eval()) self.assertEqual(1.0, accuracy.eval()) + @test_util.run_deprecated_v1 def testEffectivelyEquivalentSizesWithStaticShapedWeight(self): predictions = ops.convert_to_tensor([1, 1, 1]) # shape 3, labels = array_ops.expand_dims(ops.convert_to_tensor([1, 0, 0]), @@ -645,13 +681,14 @@ class AccuracyTest(test.TestCase): with self.cached_session() as sess: accuracy, update_op = metrics.accuracy(labels, predictions, weights) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # if streaming_accuracy does not flatten the weight, accuracy would be # 0.33333334 due to an intended broadcast of weight. Due to flattening, # it will be higher than .95 self.assertGreater(update_op.eval(), .95) self.assertGreater(accuracy.eval(), .95) + @test_util.run_deprecated_v1 def testEffectivelyEquivalentSizesWithDynamicallyShapedWeight(self): predictions = ops.convert_to_tensor([1, 1, 1]) # shape 3, labels = array_ops.expand_dims(ops.convert_to_tensor([1, 0, 0]), @@ -666,13 +703,14 @@ class AccuracyTest(test.TestCase): accuracy, update_op = metrics.accuracy(labels, predictions, weights_placeholder) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # if streaming_accuracy does not flatten the weight, accuracy would be # 0.33333334 due to an intended broadcast of weight. Due to flattening, # it will be higher than .95 self.assertGreater(update_op.eval(feed_dict=feed_dict), .95) self.assertGreater(accuracy.eval(feed_dict=feed_dict), .95) + @test_util.run_deprecated_v1 def testMultipleUpdatesWithWeightedValues(self): with self.cached_session() as sess: # Create the queue that populates the predictions. @@ -704,10 +742,10 @@ class AccuracyTest(test.TestCase): accuracy, update_op = metrics.accuracy(labels, predictions, weights) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in xrange(3): - sess.run(update_op) - self.assertEqual(1.0, sess.run(update_op)) + self.evaluate(update_op) + self.assertEqual(1.0, self.evaluate(update_op)) self.assertEqual(1.0, accuracy.eval()) @@ -717,12 +755,14 @@ class PrecisionTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.precision( predictions=array_ops.ones((10, 1)), labels=array_ops.ones((10, 1))) _assert_metric_variables(self, ('precision/false_positives/count:0', 'precision/true_positives/count:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.precision( @@ -731,6 +771,7 @@ class PrecisionTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.precision( @@ -739,6 +780,7 @@ class PrecisionTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_uniform( (10, 3), maxval=1, dtype=dtypes_lib.int64, seed=1) @@ -747,17 +789,18 @@ class PrecisionTest(test.TestCase): precision, update_op = metrics.precision(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_precision = precision.eval() for _ in range(10): self.assertEqual(initial_precision, precision.eval()) + @test_util.run_deprecated_v1 def testAllCorrect(self): inputs = np.random.randint(0, 2, size=(100, 1)) @@ -766,10 +809,11 @@ class PrecisionTest(test.TestCase): precision, update_op = metrics.precision(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(1, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(1, self.evaluate(update_op)) self.assertAlmostEqual(1, precision.eval()) + @test_util.run_deprecated_v1 def testSomeCorrect_multipleInputDtypes(self): for dtype in (dtypes_lib.bool, dtypes_lib.int32, dtypes_lib.float32): predictions = math_ops.cast( @@ -779,10 +823,11 @@ class PrecisionTest(test.TestCase): precision, update_op = metrics.precision(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAlmostEqual(0.5, update_op.eval()) self.assertAlmostEqual(0.5, precision.eval()) + @test_util.run_deprecated_v1 def testWeighted1d(self): predictions = constant_op.constant([[1, 0, 1, 0], [1, 0, 1, 0]]) labels = constant_op.constant([[0, 1, 1, 0], [1, 0, 0, 1]]) @@ -797,6 +842,7 @@ class PrecisionTest(test.TestCase): self.assertAlmostEqual(expected_precision, update_op.eval()) self.assertAlmostEqual(expected_precision, precision.eval()) + @test_util.run_deprecated_v1 def testWeightedScalar_placeholders(self): predictions = array_ops.placeholder(dtype=dtypes_lib.float32) labels = array_ops.placeholder(dtype=dtypes_lib.float32) @@ -816,6 +862,7 @@ class PrecisionTest(test.TestCase): self.assertAlmostEqual( expected_precision, precision.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testWeighted1d_placeholders(self): predictions = array_ops.placeholder(dtype=dtypes_lib.float32) labels = array_ops.placeholder(dtype=dtypes_lib.float32) @@ -836,6 +883,7 @@ class PrecisionTest(test.TestCase): self.assertAlmostEqual( expected_precision, precision.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testWeighted2d(self): predictions = constant_op.constant([[1, 0, 1, 0], [1, 0, 1, 0]]) labels = constant_op.constant([[0, 1, 1, 0], [1, 0, 0, 1]]) @@ -852,6 +900,7 @@ class PrecisionTest(test.TestCase): self.assertAlmostEqual(expected_precision, update_op.eval()) self.assertAlmostEqual(expected_precision, precision.eval()) + @test_util.run_deprecated_v1 def testWeighted2d_placeholders(self): predictions = array_ops.placeholder(dtype=dtypes_lib.float32) labels = array_ops.placeholder(dtype=dtypes_lib.float32) @@ -874,6 +923,7 @@ class PrecisionTest(test.TestCase): self.assertAlmostEqual( expected_precision, precision.eval(feed_dict=feed_dict)) + @test_util.run_deprecated_v1 def testAllIncorrect(self): inputs = np.random.randint(0, 2, size=(100, 1)) @@ -882,18 +932,19 @@ class PrecisionTest(test.TestCase): precision, update_op = metrics.precision(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - sess.run(update_op) + self.evaluate(variables.local_variables_initializer()) + self.evaluate(update_op) self.assertAlmostEqual(0, precision.eval()) + @test_util.run_deprecated_v1 def testZeroTrueAndFalsePositivesGivesZeroPrecision(self): predictions = constant_op.constant([0, 0, 0, 0]) labels = constant_op.constant([0, 0, 0, 0]) precision, update_op = metrics.precision(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - sess.run(update_op) + self.evaluate(variables.local_variables_initializer()) + self.evaluate(update_op) self.assertEqual(0.0, precision.eval()) @@ -903,6 +954,7 @@ class RecallTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.recall( predictions=array_ops.ones((10, 1)), labels=array_ops.ones((10, 1))) @@ -910,6 +962,7 @@ class RecallTest(test.TestCase): self, ('recall/false_negatives/count:0', 'recall/true_positives/count:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.recall( @@ -918,6 +971,7 @@ class RecallTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.recall( @@ -926,6 +980,7 @@ class RecallTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_uniform( (10, 3), maxval=1, dtype=dtypes_lib.int64, seed=1) @@ -934,17 +989,18 @@ class RecallTest(test.TestCase): recall, update_op = metrics.recall(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_recall = recall.eval() for _ in range(10): self.assertEqual(initial_recall, recall.eval()) + @test_util.run_deprecated_v1 def testAllCorrect(self): np_inputs = np.random.randint(0, 2, size=(100, 1)) @@ -953,10 +1009,11 @@ class RecallTest(test.TestCase): recall, update_op = metrics.recall(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - sess.run(update_op) + self.evaluate(variables.local_variables_initializer()) + self.evaluate(update_op) self.assertEqual(1, recall.eval()) + @test_util.run_deprecated_v1 def testSomeCorrect_multipleInputDtypes(self): for dtype in (dtypes_lib.bool, dtypes_lib.int32, dtypes_lib.float32): predictions = math_ops.cast( @@ -966,10 +1023,11 @@ class RecallTest(test.TestCase): recall, update_op = metrics.recall(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAlmostEqual(0.5, update_op.eval()) self.assertAlmostEqual(0.5, recall.eval()) + @test_util.run_deprecated_v1 def testWeighted1d(self): predictions = constant_op.constant([[1, 0, 1, 0], [0, 1, 0, 1]]) labels = constant_op.constant([[0, 1, 1, 0], [1, 0, 0, 1]]) @@ -977,13 +1035,14 @@ class RecallTest(test.TestCase): recall, update_op = metrics.recall(labels, predictions, weights=weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) weighted_tp = 2.0 + 5.0 weighted_t = (2.0 + 2.0) + (5.0 + 5.0) expected_precision = weighted_tp / weighted_t self.assertAlmostEqual(expected_precision, update_op.eval()) self.assertAlmostEqual(expected_precision, recall.eval()) + @test_util.run_deprecated_v1 def testWeighted2d(self): predictions = constant_op.constant([[1, 0, 1, 0], [0, 1, 0, 1]]) labels = constant_op.constant([[0, 1, 1, 0], [1, 0, 0, 1]]) @@ -991,13 +1050,14 @@ class RecallTest(test.TestCase): recall, update_op = metrics.recall(labels, predictions, weights=weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) weighted_tp = 3.0 + 1.0 weighted_t = (2.0 + 3.0) + (4.0 + 1.0) expected_precision = weighted_tp / weighted_t self.assertAlmostEqual(expected_precision, update_op.eval()) self.assertAlmostEqual(expected_precision, recall.eval()) + @test_util.run_deprecated_v1 def testAllIncorrect(self): np_inputs = np.random.randint(0, 2, size=(100, 1)) @@ -1006,18 +1066,19 @@ class RecallTest(test.TestCase): recall, update_op = metrics.recall(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - sess.run(update_op) + self.evaluate(variables.local_variables_initializer()) + self.evaluate(update_op) self.assertEqual(0, recall.eval()) + @test_util.run_deprecated_v1 def testZeroTruePositivesAndFalseNegativesGivesZeroRecall(self): predictions = array_ops.zeros((1, 4)) labels = array_ops.zeros((1, 4)) recall, update_op = metrics.recall(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - sess.run(update_op) + self.evaluate(variables.local_variables_initializer()) + self.evaluate(update_op) self.assertEqual(0, recall.eval()) @@ -1027,6 +1088,7 @@ class AUCTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.auc(predictions=array_ops.ones((10, 1)), labels=array_ops.ones((10, 1))) @@ -1034,6 +1096,7 @@ class AUCTest(test.TestCase): ('auc/true_positives:0', 'auc/false_negatives:0', 'auc/false_positives:0', 'auc/true_negatives:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.auc(predictions=array_ops.ones((10, 1)), @@ -1041,6 +1104,7 @@ class AUCTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.auc(predictions=array_ops.ones((10, 1)), @@ -1048,6 +1112,7 @@ class AUCTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_uniform( (10, 3), maxval=1, dtype=dtypes_lib.float32, seed=1) @@ -1056,17 +1121,18 @@ class AUCTest(test.TestCase): auc, update_op = metrics.auc(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_auc = auc.eval() for _ in range(10): self.assertAlmostEqual(initial_auc, auc.eval(), 5) + @test_util.run_deprecated_v1 def testAllCorrect(self): self.allCorrectAsExpected('ROC') @@ -1078,11 +1144,12 @@ class AUCTest(test.TestCase): labels = constant_op.constant(inputs) auc, update_op = metrics.auc(labels, predictions, curve=curve) - sess.run(variables.local_variables_initializer()) - self.assertEqual(1, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(1, self.evaluate(update_op)) self.assertEqual(1, auc.eval()) + @test_util.run_deprecated_v1 def testSomeCorrect_multipleLabelDtypes(self): with self.cached_session() as sess: for label_dtype in ( @@ -1093,11 +1160,12 @@ class AUCTest(test.TestCase): constant_op.constant([0, 1, 1, 0], shape=(1, 4)), dtype=label_dtype) auc, update_op = metrics.auc(labels, predictions) - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0.5, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0.5, self.evaluate(update_op)) self.assertAlmostEqual(0.5, auc.eval()) + @test_util.run_deprecated_v1 def testWeighted1d(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1106,11 +1174,12 @@ class AUCTest(test.TestCase): weights = constant_op.constant([2], shape=(1, 1)) auc, update_op = metrics.auc(labels, predictions, weights=weights) - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0.5, sess.run(update_op), 5) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0.5, self.evaluate(update_op), 5) self.assertAlmostEqual(0.5, auc.eval(), 5) + @test_util.run_deprecated_v1 def testWeighted2d(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1119,13 +1188,14 @@ class AUCTest(test.TestCase): weights = constant_op.constant([1, 2, 3, 4], shape=(1, 4)) auc, update_op = metrics.auc(labels, predictions, weights=weights) - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0.7, sess.run(update_op), 5) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0.7, self.evaluate(update_op), 5) self.assertAlmostEqual(0.7, auc.eval(), 5) # Regarding the AUC-PR tests: note that the preferred method when # calculating AUC-PR is summation_method='careful_interpolation'. + @test_util.run_deprecated_v1 def testCorrectAUCPRSpecialCase(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1134,12 +1204,13 @@ class AUCTest(test.TestCase): auc, update_op = metrics.auc(labels, predictions, curve='PR', summation_method='careful_interpolation') - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # expected ~= 0.79726744594 expected = 1 - math.log(1.5) / 2 - self.assertAlmostEqual(expected, sess.run(update_op), delta=1e-3) + self.assertAlmostEqual(expected, self.evaluate(update_op), delta=1e-3) self.assertAlmostEqual(expected, auc.eval(), delta=1e-3) + @test_util.run_deprecated_v1 def testCorrectAnotherAUCPRSpecialCase(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1150,12 +1221,13 @@ class AUCTest(test.TestCase): auc, update_op = metrics.auc(labels, predictions, curve='PR', summation_method='careful_interpolation') - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # expected ~= 0.61350593198 expected = (2.5 - 2 * math.log(4./3) - 0.25 * math.log(7./5)) / 3 - self.assertAlmostEqual(expected, sess.run(update_op), delta=1e-3) + self.assertAlmostEqual(expected, self.evaluate(update_op), delta=1e-3) self.assertAlmostEqual(expected, auc.eval(), delta=1e-3) + @test_util.run_deprecated_v1 def testThirdCorrectAUCPRSpecialCase(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1166,12 +1238,13 @@ class AUCTest(test.TestCase): auc, update_op = metrics.auc(labels, predictions, curve='PR', summation_method='careful_interpolation') - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # expected ~= 0.90410597584 expected = 1 - math.log(4./3) / 3 - self.assertAlmostEqual(expected, sess.run(update_op), delta=1e-3) + self.assertAlmostEqual(expected, self.evaluate(update_op), delta=1e-3) self.assertAlmostEqual(expected, auc.eval(), delta=1e-3) + @test_util.run_deprecated_v1 def testIncorrectAUCPRSpecialCase(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1180,11 +1253,12 @@ class AUCTest(test.TestCase): auc, update_op = metrics.auc(labels, predictions, curve='PR', summation_method='trapezoidal') - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0.79166, sess.run(update_op), delta=1e-3) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0.79166, self.evaluate(update_op), delta=1e-3) self.assertAlmostEqual(0.79166, auc.eval(), delta=1e-3) + @test_util.run_deprecated_v1 def testAnotherIncorrectAUCPRSpecialCase(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1195,11 +1269,12 @@ class AUCTest(test.TestCase): auc, update_op = metrics.auc(labels, predictions, curve='PR', summation_method='trapezoidal') - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0.610317, sess.run(update_op), delta=1e-3) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0.610317, self.evaluate(update_op), delta=1e-3) self.assertAlmostEqual(0.610317, auc.eval(), delta=1e-3) + @test_util.run_deprecated_v1 def testThirdIncorrectAUCPRSpecialCase(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1210,11 +1285,12 @@ class AUCTest(test.TestCase): auc, update_op = metrics.auc(labels, predictions, curve='PR', summation_method='trapezoidal') - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0.90277, sess.run(update_op), delta=1e-3) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0.90277, self.evaluate(update_op), delta=1e-3) self.assertAlmostEqual(0.90277, auc.eval(), delta=1e-3) + @test_util.run_deprecated_v1 def testAllIncorrect(self): inputs = np.random.randint(0, 2, size=(100, 1)) @@ -1223,30 +1299,32 @@ class AUCTest(test.TestCase): labels = constant_op.constant(1 - inputs, dtype=dtypes_lib.float32) auc, update_op = metrics.auc(labels, predictions) - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0, self.evaluate(update_op)) self.assertAlmostEqual(0, auc.eval()) + @test_util.run_deprecated_v1 def testZeroTruePositivesAndFalseNegativesGivesOneAUC(self): with self.cached_session() as sess: predictions = array_ops.zeros([4], dtype=dtypes_lib.float32) labels = array_ops.zeros([4]) auc, update_op = metrics.auc(labels, predictions) - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(1, sess.run(update_op), 6) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(1, self.evaluate(update_op), 6) self.assertAlmostEqual(1, auc.eval(), 6) + @test_util.run_deprecated_v1 def testRecallOneAndPrecisionOneGivesOnePRAUC(self): with self.cached_session() as sess: predictions = array_ops.ones([4], dtype=dtypes_lib.float32) labels = array_ops.ones([4]) auc, update_op = metrics.auc(labels, predictions, curve='PR') - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(1, sess.run(update_op), 6) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(1, self.evaluate(update_op), 6) self.assertAlmostEqual(1, auc.eval(), 6) @@ -1277,6 +1355,7 @@ class AUCTest(test.TestCase): tp = np.cumsum(sorted_weights * is_positive) / num_positives return np.sum((sorted_weights * tp)[~is_positive]) / num_negatives + @test_util.run_deprecated_v1 def testWithMultipleUpdates(self): num_samples = 1000 batch_size = 10 @@ -1317,9 +1396,9 @@ class AUCTest(test.TestCase): num_thresholds=500, weights=tf_weights) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for i in range(num_batches): - sess.run(update_op) + self.evaluate(update_op) # Since this is only approximate, we can't expect a 6 digits match. # Although with higher number of samples/thresholds we should see the @@ -1333,6 +1412,7 @@ class SpecificityAtSensitivityTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.specificity_at_sensitivity( predictions=array_ops.ones((10, 1)), @@ -1344,6 +1424,7 @@ class SpecificityAtSensitivityTest(test.TestCase): 'specificity_at_sensitivity/false_positives:0', 'specificity_at_sensitivity/true_negatives:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.specificity_at_sensitivity( @@ -1353,6 +1434,7 @@ class SpecificityAtSensitivityTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.specificity_at_sensitivity( @@ -1362,6 +1444,7 @@ class SpecificityAtSensitivityTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_uniform( (10, 3), maxval=1, dtype=dtypes_lib.float32, seed=1) @@ -1371,17 +1454,18 @@ class SpecificityAtSensitivityTest(test.TestCase): labels, predictions, sensitivity=0.7) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_specificity = specificity.eval() for _ in range(10): self.assertAlmostEqual(initial_specificity, specificity.eval(), 5) + @test_util.run_deprecated_v1 def testAllCorrect(self): inputs = np.random.randint(0, 2, size=(100, 1)) @@ -1391,10 +1475,11 @@ class SpecificityAtSensitivityTest(test.TestCase): labels, predictions, sensitivity=0.7) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(1, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(1, self.evaluate(update_op)) self.assertEqual(1, specificity.eval()) + @test_util.run_deprecated_v1 def testSomeCorrectHighSensitivity(self): predictions_values = [0.1, 0.2, 0.4, 0.3, 0.0, 0.1, 0.45, 0.5, 0.8, 0.9] labels_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] @@ -1406,10 +1491,11 @@ class SpecificityAtSensitivityTest(test.TestCase): labels, predictions, sensitivity=0.8) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(1.0, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(1.0, self.evaluate(update_op)) self.assertAlmostEqual(1.0, specificity.eval()) + @test_util.run_deprecated_v1 def testSomeCorrectLowSensitivity(self): predictions_values = [0.1, 0.2, 0.4, 0.3, 0.0, 0.1, 0.2, 0.2, 0.26, 0.26] labels_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] @@ -1421,11 +1507,12 @@ class SpecificityAtSensitivityTest(test.TestCase): labels, predictions, sensitivity=0.4) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) - self.assertAlmostEqual(0.6, sess.run(update_op)) + self.assertAlmostEqual(0.6, self.evaluate(update_op)) self.assertAlmostEqual(0.6, specificity.eval()) + @test_util.run_deprecated_v1 def testWeighted1d_multipleLabelDtypes(self): for label_dtype in (dtypes_lib.bool, dtypes_lib.int32, dtypes_lib.float32): predictions_values = [0.1, 0.2, 0.4, 0.3, 0.0, 0.1, 0.2, 0.2, 0.26, 0.26] @@ -1440,11 +1527,12 @@ class SpecificityAtSensitivityTest(test.TestCase): labels, predictions, weights=weights, sensitivity=0.4) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) - self.assertAlmostEqual(0.6, sess.run(update_op)) + self.assertAlmostEqual(0.6, self.evaluate(update_op)) self.assertAlmostEqual(0.6, specificity.eval()) + @test_util.run_deprecated_v1 def testWeighted2d(self): predictions_values = [0.1, 0.2, 0.4, 0.3, 0.0, 0.1, 0.2, 0.2, 0.26, 0.26] labels_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] @@ -1458,9 +1546,9 @@ class SpecificityAtSensitivityTest(test.TestCase): labels, predictions, weights=weights, sensitivity=0.4) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) - self.assertAlmostEqual(8.0 / 15.0, sess.run(update_op)) + self.assertAlmostEqual(8.0 / 15.0, self.evaluate(update_op)) self.assertAlmostEqual(8.0 / 15.0, specificity.eval()) @@ -1470,6 +1558,7 @@ class SensitivityAtSpecificityTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.sensitivity_at_specificity( predictions=array_ops.ones((10, 1)), @@ -1481,6 +1570,7 @@ class SensitivityAtSpecificityTest(test.TestCase): 'sensitivity_at_specificity/false_positives:0', 'sensitivity_at_specificity/true_negatives:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.sensitivity_at_specificity( @@ -1490,6 +1580,7 @@ class SensitivityAtSpecificityTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.sensitivity_at_specificity( @@ -1499,6 +1590,7 @@ class SensitivityAtSpecificityTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_uniform( (10, 3), maxval=1, dtype=dtypes_lib.float32, seed=1) @@ -1508,17 +1600,18 @@ class SensitivityAtSpecificityTest(test.TestCase): labels, predictions, specificity=0.7) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_sensitivity = sensitivity.eval() for _ in range(10): self.assertAlmostEqual(initial_sensitivity, sensitivity.eval(), 5) + @test_util.run_deprecated_v1 def testAllCorrect(self): inputs = np.random.randint(0, 2, size=(100, 1)) @@ -1528,10 +1621,11 @@ class SensitivityAtSpecificityTest(test.TestCase): labels, predictions, specificity=0.7) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(1, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(1, self.evaluate(update_op)) self.assertEqual(1, specificity.eval()) + @test_util.run_deprecated_v1 def testSomeCorrectHighSpecificity(self): predictions_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.1, 0.45, 0.5, 0.8, 0.9] labels_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] @@ -1543,10 +1637,11 @@ class SensitivityAtSpecificityTest(test.TestCase): labels, predictions, specificity=0.8) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0.8, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0.8, self.evaluate(update_op)) self.assertAlmostEqual(0.8, specificity.eval()) + @test_util.run_deprecated_v1 def testSomeCorrectLowSpecificity(self): predictions_values = [0.0, 0.1, 0.2, 0.3, 0.4, 0.01, 0.02, 0.25, 0.26, 0.26] labels_values = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1] @@ -1558,10 +1653,11 @@ class SensitivityAtSpecificityTest(test.TestCase): labels, predictions, specificity=0.4) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0.6, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0.6, self.evaluate(update_op)) self.assertAlmostEqual(0.6, specificity.eval()) + @test_util.run_deprecated_v1 def testWeighted_multipleLabelDtypes(self): for label_dtype in (dtypes_lib.bool, dtypes_lib.int32, dtypes_lib.float32): predictions_values = [ @@ -1577,8 +1673,8 @@ class SensitivityAtSpecificityTest(test.TestCase): labels, predictions, weights=weights, specificity=0.4) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(0.675, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(0.675, self.evaluate(update_op)) self.assertAlmostEqual(0.675, specificity.eval()) @@ -1589,6 +1685,7 @@ class PrecisionRecallThresholdsTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.precision_at_thresholds( predictions=array_ops.ones((10, 1)), @@ -1599,6 +1696,7 @@ class PrecisionRecallThresholdsTest(test.TestCase): 'precision_at_thresholds/false_positives:0', )) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' prec, _ = metrics.precision_at_thresholds( @@ -1613,6 +1711,7 @@ class PrecisionRecallThresholdsTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [prec, rec]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, precision_op = metrics.precision_at_thresholds( @@ -1628,6 +1727,7 @@ class PrecisionRecallThresholdsTest(test.TestCase): self.assertListEqual( ops.get_collection(my_collection_name), [precision_op, recall_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_uniform( (10, 3), maxval=1, dtype=dtypes_lib.float32, seed=1) @@ -1639,18 +1739,19 @@ class PrecisionRecallThresholdsTest(test.TestCase): rec, rec_op = metrics.recall_at_thresholds(labels, predictions, thresholds) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates, then verify idempotency. - sess.run([prec_op, rec_op]) + self.evaluate([prec_op, rec_op]) initial_prec = prec.eval() initial_rec = rec.eval() for _ in range(10): - sess.run([prec_op, rec_op]) + self.evaluate([prec_op, rec_op]) self.assertAllClose(initial_prec, prec.eval()) self.assertAllClose(initial_rec, rec.eval()) # TODO(nsilberman): fix tests (passing but incorrect). + @test_util.run_deprecated_v1 def testAllCorrect(self): inputs = np.random.randint(0, 2, size=(100, 1)) @@ -1663,12 +1764,13 @@ class PrecisionRecallThresholdsTest(test.TestCase): rec, rec_op = metrics.recall_at_thresholds(labels, predictions, thresholds) - sess.run(variables.local_variables_initializer()) - sess.run([prec_op, rec_op]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([prec_op, rec_op]) self.assertEqual(1, prec.eval()) self.assertEqual(1, rec.eval()) + @test_util.run_deprecated_v1 def testSomeCorrect_multipleLabelDtypes(self): with self.cached_session() as sess: for label_dtype in ( @@ -1683,12 +1785,13 @@ class PrecisionRecallThresholdsTest(test.TestCase): rec, rec_op = metrics.recall_at_thresholds(labels, predictions, thresholds) - sess.run(variables.local_variables_initializer()) - sess.run([prec_op, rec_op]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([prec_op, rec_op]) self.assertAlmostEqual(0.5, prec.eval()) self.assertAlmostEqual(0.5, rec.eval()) + @test_util.run_deprecated_v1 def testAllIncorrect(self): inputs = np.random.randint(0, 2, size=(100, 1)) @@ -1701,12 +1804,13 @@ class PrecisionRecallThresholdsTest(test.TestCase): rec, rec_op = metrics.recall_at_thresholds(labels, predictions, thresholds) - sess.run(variables.local_variables_initializer()) - sess.run([prec_op, rec_op]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([prec_op, rec_op]) self.assertAlmostEqual(0, prec.eval()) self.assertAlmostEqual(0, rec.eval()) + @test_util.run_deprecated_v1 def testWeights1d(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1729,14 +1833,15 @@ class PrecisionRecallThresholdsTest(test.TestCase): rec_low = array_ops.reshape(rec_low, shape=()) rec_high = array_ops.reshape(rec_high, shape=()) - sess.run(variables.local_variables_initializer()) - sess.run([prec_op, rec_op]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([prec_op, rec_op]) self.assertAlmostEqual(1.0, prec_low.eval(), places=5) self.assertAlmostEqual(0.0, prec_high.eval(), places=5) self.assertAlmostEqual(1.0, rec_low.eval(), places=5) self.assertAlmostEqual(0.0, rec_high.eval(), places=5) + @test_util.run_deprecated_v1 def testWeights2d(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1759,14 +1864,15 @@ class PrecisionRecallThresholdsTest(test.TestCase): rec_low = array_ops.reshape(rec_low, shape=()) rec_high = array_ops.reshape(rec_high, shape=()) - sess.run(variables.local_variables_initializer()) - sess.run([prec_op, rec_op]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([prec_op, rec_op]) self.assertAlmostEqual(1.0, prec_low.eval(), places=5) self.assertAlmostEqual(0.0, prec_high.eval(), places=5) self.assertAlmostEqual(1.0, rec_low.eval(), places=5) self.assertAlmostEqual(0.0, rec_high.eval(), places=5) + @test_util.run_deprecated_v1 def testExtremeThresholds(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -1783,14 +1889,15 @@ class PrecisionRecallThresholdsTest(test.TestCase): [rec_low, rec_high] = array_ops.split( value=rec, num_or_size_splits=2, axis=0) - sess.run(variables.local_variables_initializer()) - sess.run([prec_op, rec_op]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([prec_op, rec_op]) self.assertAlmostEqual(0.75, prec_low.eval()) self.assertAlmostEqual(0.0, prec_high.eval()) self.assertAlmostEqual(1.0, rec_low.eval()) self.assertAlmostEqual(0.0, rec_high.eval()) + @test_util.run_deprecated_v1 def testZeroLabelsPredictions(self): with self.cached_session() as sess: predictions = array_ops.zeros([4], dtype=dtypes_lib.float32) @@ -1801,12 +1908,13 @@ class PrecisionRecallThresholdsTest(test.TestCase): rec, rec_op = metrics.recall_at_thresholds(labels, predictions, thresholds) - sess.run(variables.local_variables_initializer()) - sess.run([prec_op, rec_op]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([prec_op, rec_op]) self.assertAlmostEqual(0, prec.eval(), 6) self.assertAlmostEqual(0, rec.eval(), 6) + @test_util.run_deprecated_v1 def testWithMultipleUpdates(self): num_samples = 1000 batch_size = 10 @@ -1869,9 +1977,9 @@ class PrecisionRecallThresholdsTest(test.TestCase): rec, rec_op = metrics.recall_at_thresholds(tf_labels, tf_predictions, thresholds) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(int(num_samples / batch_size)): - sess.run([prec_op, rec_op]) + self.evaluate([prec_op, rec_op]) # Since this is only approximate, we can't expect a 6 digits match. # Although with higher number of samples/thresholds we should see the # accuracy improving @@ -1989,6 +2097,7 @@ class SingleLabelPrecisionAtKTest(test.TestCase): self._test_average_precision_at_k = functools.partial( _test_average_precision_at_k, test_case=self) + @test_util.run_deprecated_v1 def test_at_k1_nan(self): for labels in self._labels: # Classes 0,1,2 have 0 predictions, classes -1 and 4 are out of range. @@ -1998,6 +2107,7 @@ class SingleLabelPrecisionAtKTest(test.TestCase): self._test_precision_at_top_k( self._predictions_idx, labels, k=1, expected=NAN, class_id=class_id) + @test_util.run_deprecated_v1 def test_at_k1(self): for labels in self._labels: # Class 3: 1 label, 2 predictions, 1 correct. @@ -2025,6 +2135,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): self._test_average_precision_at_k = functools.partial( _test_average_precision_at_k, test_case=self) + @test_util.run_deprecated_v1 def test_average_precision(self): # Example 1. # Matches example here: @@ -2100,6 +2211,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): expected=streaming_average_precision[i], weights=weights) + @test_util.run_deprecated_v1 def test_average_precision_some_labels_out_of_range(self): """Tests that labels outside the [0, n_classes) range are ignored.""" labels_ex1 = (-1, 0, 1, 2, 3, 4, 7) @@ -2119,6 +2231,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): self._test_average_precision_at_k( predictions, labels, k, expected=avg_precision_ex1[i]) + @test_util.run_deprecated_v1 def test_three_labels_at_k5_no_predictions(self): predictions = [[0.5, 0.1, 0.6, 0.3, 0.8, 0.0, 0.7, 0.2, 0.4, 0.9], [0.3, 0.0, 0.7, 0.2, 0.4, 0.9, 0.5, 0.8, 0.1, 0.6]] @@ -2135,6 +2248,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): self._test_precision_at_top_k( predictions_idx, labels, k=5, expected=NAN, class_id=class_id) + @test_util.run_deprecated_v1 def test_three_labels_at_k5_no_labels(self): predictions = [[0.5, 0.1, 0.6, 0.3, 0.8, 0.0, 0.7, 0.2, 0.4, 0.9], [0.3, 0.0, 0.7, 0.2, 0.4, 0.9, 0.5, 0.8, 0.1, 0.6]] @@ -2151,6 +2265,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): self._test_precision_at_top_k( predictions_idx, labels, k=5, expected=0.0, class_id=class_id) + @test_util.run_deprecated_v1 def test_three_labels_at_k5(self): predictions = [[0.5, 0.1, 0.6, 0.3, 0.8, 0.0, 0.7, 0.2, 0.4, 0.9], [0.3, 0.0, 0.7, 0.2, 0.4, 0.9, 0.5, 0.8, 0.1, 0.6]] @@ -2184,6 +2299,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): self._test_precision_at_top_k( predictions_idx, labels, k=5, expected=3.0 / 10) + @test_util.run_deprecated_v1 def test_three_labels_at_k5_some_out_of_range(self): """Tests that labels outside the [0, n_classes) range are ignored.""" predictions = [[0.5, 0.1, 0.6, 0.3, 0.8, 0.0, 0.7, 0.2, 0.4, 0.9], @@ -2220,6 +2336,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): self._test_precision_at_top_k( predictions_idx, sp_labels, k=5, expected=3.0 / 10) + @test_util.run_deprecated_v1 def test_3d_nan(self): predictions = [[[0.5, 0.1, 0.6, 0.3, 0.8, 0.0, 0.7, 0.2, 0.4, 0.9], [0.3, 0.0, 0.7, 0.2, 0.4, 0.9, 0.5, 0.8, 0.1, 0.6]], @@ -2238,6 +2355,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): self._test_precision_at_top_k( predictions_idx, labels, k=5, expected=NAN, class_id=class_id) + @test_util.run_deprecated_v1 def test_3d_no_labels(self): predictions = [[[0.5, 0.1, 0.6, 0.3, 0.8, 0.0, 0.7, 0.2, 0.4, 0.9], [0.3, 0.0, 0.7, 0.2, 0.4, 0.9, 0.5, 0.8, 0.1, 0.6]], @@ -2256,6 +2374,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): self._test_precision_at_top_k( predictions_idx, labels, k=5, expected=0.0, class_id=class_id) + @test_util.run_deprecated_v1 def test_3d(self): predictions = [[[0.5, 0.1, 0.6, 0.3, 0.8, 0.0, 0.7, 0.2, 0.4, 0.9], [0.3, 0.0, 0.7, 0.2, 0.4, 0.9, 0.5, 0.8, 0.1, 0.6]], @@ -2291,6 +2410,7 @@ class MultiLabelPrecisionAtKTest(test.TestCase): self._test_precision_at_top_k( predictions_idx, labels, k=5, expected=7.0 / 20) + @test_util.run_deprecated_v1 def test_3d_ignore_some(self): predictions = [[[0.5, 0.1, 0.6, 0.3, 0.8, 0.0, 0.7, 0.2, 0.4, 0.9], [0.3, 0.0, 0.7, 0.2, 0.4, 0.9, 0.5, 0.8, 0.1, 0.6]], @@ -2432,6 +2552,7 @@ class SingleLabelRecallAtKTest(test.TestCase): self._test_recall_at_top_k = functools.partial( _test_recall_at_top_k, test_case=self) + @test_util.run_deprecated_v1 def test_at_k1_nan(self): # Classes 0,1 have 0 labels, 0 predictions, classes -1 and 4 are out of # range. @@ -2442,6 +2563,7 @@ class SingleLabelRecallAtKTest(test.TestCase): self._test_recall_at_top_k( self._predictions_idx, labels, k=1, expected=NAN, class_id=class_id) + @test_util.run_deprecated_v1 def test_at_k1_no_predictions(self): for labels in self._labels: # Class 2: 0 predictions. @@ -2450,6 +2572,7 @@ class SingleLabelRecallAtKTest(test.TestCase): self._test_recall_at_top_k( self._predictions_idx, labels, k=1, expected=0.0, class_id=2) + @test_util.run_deprecated_v1 def test_one_label_at_k1(self): for labels in self._labels: # Class 3: 1 label, 2 predictions, 1 correct. @@ -2463,6 +2586,7 @@ class SingleLabelRecallAtKTest(test.TestCase): self._test_recall_at_top_k( self._predictions_idx, labels, k=1, expected=1.0 / 2) + @test_util.run_deprecated_v1 def test_one_label_at_k1_weighted_class_id3(self): predictions = self._predictions predictions_idx = self._predictions_idx @@ -2504,6 +2628,7 @@ class SingleLabelRecallAtKTest(test.TestCase): predictions_idx, labels, k=1, expected=2.0 / 2, class_id=3, weights=(2.0, 3.0)) + @test_util.run_deprecated_v1 def test_one_label_at_k1_weighted(self): predictions = self._predictions predictions_idx = self._predictions_idx @@ -2553,6 +2678,7 @@ class MultiLabel2dRecallAtKTest(test.TestCase): self._test_recall_at_top_k = functools.partial( _test_recall_at_top_k, test_case=self) + @test_util.run_deprecated_v1 def test_at_k5_nan(self): for labels in self._labels: # Classes 0,3,4,6,9 have 0 labels, class 10 is out of range. @@ -2562,6 +2688,7 @@ class MultiLabel2dRecallAtKTest(test.TestCase): self._test_recall_at_top_k( self._predictions_idx, labels, k=5, expected=NAN, class_id=class_id) + @test_util.run_deprecated_v1 def test_at_k5_no_predictions(self): for labels in self._labels: # Class 8: 1 label, no predictions. @@ -2570,6 +2697,7 @@ class MultiLabel2dRecallAtKTest(test.TestCase): self._test_recall_at_top_k( self._predictions_idx, labels, k=5, expected=0.0 / 1, class_id=8) + @test_util.run_deprecated_v1 def test_at_k5(self): for labels in self._labels: # Class 2: 2 labels, both correct. @@ -2595,6 +2723,7 @@ class MultiLabel2dRecallAtKTest(test.TestCase): self._test_recall_at_top_k( self._predictions_idx, labels, k=5, expected=3.0 / 6) + @test_util.run_deprecated_v1 def test_at_k5_some_out_of_range(self): """Tests that labels outside the [0, n_classes) count in denominator.""" labels = sparse_tensor.SparseTensorValue( @@ -2647,6 +2776,7 @@ class MultiLabel3dRecallAtKTest(test.TestCase): self._test_recall_at_top_k = functools.partial( _test_recall_at_top_k, test_case=self) + @test_util.run_deprecated_v1 def test_3d_nan(self): # Classes 0,3,4,6,9 have 0 labels, class 10 is out of range. for class_id in (0, 3, 4, 6, 9, 10): @@ -2656,6 +2786,7 @@ class MultiLabel3dRecallAtKTest(test.TestCase): self._predictions_idx, self._labels, k=5, expected=NAN, class_id=class_id) + @test_util.run_deprecated_v1 def test_3d_no_predictions(self): # Classes 1,8 have 0 predictions, >=1 label. for class_id in (1, 8): @@ -2665,6 +2796,7 @@ class MultiLabel3dRecallAtKTest(test.TestCase): self._predictions_idx, self._labels, k=5, expected=0.0, class_id=class_id) + @test_util.run_deprecated_v1 def test_3d(self): # Class 2: 4 labels, all correct. self._test_recall_at_k( @@ -2693,6 +2825,7 @@ class MultiLabel3dRecallAtKTest(test.TestCase): self._test_recall_at_top_k( self._predictions_idx, self._labels, k=5, expected=7.0 / 12) + @test_util.run_deprecated_v1 def test_3d_ignore_all(self): for class_id in xrange(10): self._test_recall_at_k( @@ -2719,6 +2852,7 @@ class MultiLabel3dRecallAtKTest(test.TestCase): self._predictions_idx, self._labels, k=5, expected=NAN, weights=[[0, 0], [0, 0]]) + @test_util.run_deprecated_v1 def test_3d_ignore_some(self): # Class 2: 2 labels, both correct. self._test_recall_at_k( @@ -2774,12 +2908,14 @@ class MeanAbsoluteErrorTest(test.TestCase): def setUp(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.mean_absolute_error( predictions=array_ops.ones((10, 1)), labels=array_ops.ones((10, 1))) _assert_metric_variables( self, ('mean_absolute_error/count:0', 'mean_absolute_error/total:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.mean_absolute_error( @@ -2788,6 +2924,7 @@ class MeanAbsoluteErrorTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.mean_absolute_error( @@ -2796,23 +2933,25 @@ class MeanAbsoluteErrorTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_normal((10, 3), seed=1) labels = random_ops.random_normal((10, 3), seed=2) error, update_op = metrics.mean_absolute_error(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_error = error.eval() for _ in range(10): self.assertEqual(initial_error, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateWithErrorAndWeights(self): predictions = constant_op.constant( [2, 4, 6, 8], shape=(1, 4), dtype=dtypes_lib.float32) @@ -2823,8 +2962,8 @@ class MeanAbsoluteErrorTest(test.TestCase): error, update_op = metrics.mean_absolute_error(labels, predictions, weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(3, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(3, self.evaluate(update_op)) self.assertEqual(3, error.eval()) @@ -2833,6 +2972,7 @@ class MeanRelativeErrorTest(test.TestCase): def setUp(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.mean_relative_error( predictions=array_ops.ones((10, 1)), @@ -2841,6 +2981,7 @@ class MeanRelativeErrorTest(test.TestCase): _assert_metric_variables( self, ('mean_relative_error/count:0', 'mean_relative_error/total:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.mean_relative_error( @@ -2850,6 +2991,7 @@ class MeanRelativeErrorTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.mean_relative_error( @@ -2859,6 +3001,7 @@ class MeanRelativeErrorTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_normal((10, 3), seed=1) labels = random_ops.random_normal((10, 3), seed=2) @@ -2867,17 +3010,18 @@ class MeanRelativeErrorTest(test.TestCase): normalizer) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_error = error.eval() for _ in range(10): self.assertEqual(initial_error, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateNormalizedByLabels(self): np_predictions = np.asarray([2, 4, 6, 8], dtype=np.float32) np_labels = np.asarray([1, 3, 2, 3], dtype=np.float32) @@ -2892,10 +3036,11 @@ class MeanRelativeErrorTest(test.TestCase): labels, predictions, normalizer=labels) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(expected_error, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(expected_error, self.evaluate(update_op)) self.assertEqual(expected_error, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateNormalizedByZeros(self): np_predictions = np.asarray([2, 4, 6, 8], dtype=np.float32) @@ -2908,8 +3053,8 @@ class MeanRelativeErrorTest(test.TestCase): labels, predictions, normalizer=array_ops.zeros_like(labels)) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(0.0, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(0.0, self.evaluate(update_op)) self.assertEqual(0.0, error.eval()) @@ -2918,12 +3063,14 @@ class MeanSquaredErrorTest(test.TestCase): def setUp(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.mean_squared_error( predictions=array_ops.ones((10, 1)), labels=array_ops.ones((10, 1))) _assert_metric_variables( self, ('mean_squared_error/count:0', 'mean_squared_error/total:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.mean_squared_error( @@ -2932,6 +3079,7 @@ class MeanSquaredErrorTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.mean_squared_error( @@ -2940,23 +3088,25 @@ class MeanSquaredErrorTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_normal((10, 3), seed=1) labels = random_ops.random_normal((10, 3), seed=2) error, update_op = metrics.mean_squared_error(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_error = error.eval() for _ in range(10): self.assertEqual(initial_error, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateZeroError(self): predictions = array_ops.zeros((1, 3), dtype=dtypes_lib.float32) labels = array_ops.zeros((1, 3), dtype=dtypes_lib.float32) @@ -2964,10 +3114,11 @@ class MeanSquaredErrorTest(test.TestCase): error, update_op = metrics.mean_squared_error(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(0, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(0, self.evaluate(update_op)) self.assertEqual(0, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateWithError(self): predictions = constant_op.constant( [2, 4, 6], shape=(1, 3), dtype=dtypes_lib.float32) @@ -2977,10 +3128,11 @@ class MeanSquaredErrorTest(test.TestCase): error, update_op = metrics.mean_squared_error(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(6, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(6, self.evaluate(update_op)) self.assertEqual(6, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateWithErrorAndWeights(self): predictions = constant_op.constant( [2, 4, 6, 8], shape=(1, 4), dtype=dtypes_lib.float32) @@ -2991,10 +3143,11 @@ class MeanSquaredErrorTest(test.TestCase): error, update_op = metrics.mean_squared_error(labels, predictions, weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(13, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(13, self.evaluate(update_op)) self.assertEqual(13, error.eval()) + @test_util.run_deprecated_v1 def testMultipleBatchesOfSizeOne(self): with self.cached_session() as sess: # Create the queue that populates the predictions. @@ -3013,12 +3166,13 @@ class MeanSquaredErrorTest(test.TestCase): error, update_op = metrics.mean_squared_error(labels, predictions) - sess.run(variables.local_variables_initializer()) - sess.run(update_op) - self.assertAlmostEqual(208.0 / 6, sess.run(update_op), 5) + self.evaluate(variables.local_variables_initializer()) + self.evaluate(update_op) + self.assertAlmostEqual(208.0 / 6, self.evaluate(update_op), 5) self.assertAlmostEqual(208.0 / 6, error.eval(), 5) + @test_util.run_deprecated_v1 def testMetricsComputedConcurrently(self): with self.cached_session() as sess: # Create the queue that populates one set of predictions. @@ -3054,14 +3208,15 @@ class MeanSquaredErrorTest(test.TestCase): mse1, update_op1 = metrics.mean_squared_error( labels1, predictions1, name='msd1') - sess.run(variables.local_variables_initializer()) - sess.run([update_op0, update_op1]) - sess.run([update_op0, update_op1]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([update_op0, update_op1]) + self.evaluate([update_op0, update_op1]) - mse0, mse1 = sess.run([mse0, mse1]) + mse0, mse1 = self.evaluate([mse0, mse1]) self.assertAlmostEqual(208.0 / 6, mse0, 5) self.assertAlmostEqual(79.0 / 6, mse1, 5) + @test_util.run_deprecated_v1 def testMultipleMetricsOnMultipleBatchesOfSizeOne(self): with self.cached_session() as sess: # Create the queue that populates the predictions. @@ -3081,9 +3236,9 @@ class MeanSquaredErrorTest(test.TestCase): mae, ma_update_op = metrics.mean_absolute_error(labels, predictions) mse, ms_update_op = metrics.mean_squared_error(labels, predictions) - sess.run(variables.local_variables_initializer()) - sess.run([ma_update_op, ms_update_op]) - sess.run([ma_update_op, ms_update_op]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([ma_update_op, ms_update_op]) + self.evaluate([ma_update_op, ms_update_op]) self.assertAlmostEqual(32.0 / 6, mae.eval(), 5) self.assertAlmostEqual(208.0 / 6, mse.eval(), 5) @@ -3094,6 +3249,7 @@ class RootMeanSquaredErrorTest(test.TestCase): def setUp(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.root_mean_squared_error( predictions=array_ops.ones((10, 1)), labels=array_ops.ones((10, 1))) @@ -3101,6 +3257,7 @@ class RootMeanSquaredErrorTest(test.TestCase): self, ('root_mean_squared_error/count:0', 'root_mean_squared_error/total:0')) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.root_mean_squared_error( @@ -3109,6 +3266,7 @@ class RootMeanSquaredErrorTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.root_mean_squared_error( @@ -3117,23 +3275,25 @@ class RootMeanSquaredErrorTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_normal((10, 3), seed=1) labels = random_ops.random_normal((10, 3), seed=2) error, update_op = metrics.root_mean_squared_error(labels, predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_error = error.eval() for _ in range(10): self.assertEqual(initial_error, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateZeroError(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -3142,11 +3302,12 @@ class RootMeanSquaredErrorTest(test.TestCase): rmse, update_op = metrics.root_mean_squared_error(labels, predictions) - sess.run(variables.local_variables_initializer()) - self.assertEqual(0, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(0, self.evaluate(update_op)) self.assertEqual(0, rmse.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateWithError(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -3156,10 +3317,11 @@ class RootMeanSquaredErrorTest(test.TestCase): rmse, update_op = metrics.root_mean_squared_error(labels, predictions) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAlmostEqual(math.sqrt(6), update_op.eval(), 5) self.assertAlmostEqual(math.sqrt(6), rmse.eval(), 5) + @test_util.run_deprecated_v1 def testSingleUpdateWithErrorAndWeights(self): with self.cached_session() as sess: predictions = constant_op.constant( @@ -3171,8 +3333,8 @@ class RootMeanSquaredErrorTest(test.TestCase): rmse, update_op = metrics.root_mean_squared_error(labels, predictions, weights) - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(math.sqrt(13), sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(math.sqrt(13), self.evaluate(update_op)) self.assertAlmostEqual(math.sqrt(13), rmse.eval(), 5) @@ -3187,6 +3349,7 @@ class MeanCosineDistanceTest(test.TestCase): def setUp(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.mean_cosine_distance( predictions=array_ops.ones((10, 3)), @@ -3197,6 +3360,7 @@ class MeanCosineDistanceTest(test.TestCase): 'mean_cosine_distance/total:0', )) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.mean_cosine_distance( @@ -3206,6 +3370,7 @@ class MeanCosineDistanceTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.mean_cosine_distance( @@ -3215,23 +3380,25 @@ class MeanCosineDistanceTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): predictions = random_ops.random_normal((10, 3), seed=1) labels = random_ops.random_normal((10, 3), seed=2) error, update_op = metrics.mean_cosine_distance(labels, predictions, dim=1) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_error = error.eval() for _ in range(10): self.assertEqual(initial_error, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateZeroError(self): np_labels = np.matrix(('1 0 0;' '0 0 1;' '0 1 0')) @@ -3243,10 +3410,11 @@ class MeanCosineDistanceTest(test.TestCase): error, update_op = metrics.mean_cosine_distance(labels, predictions, dim=2) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(0, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(0, self.evaluate(update_op)) self.assertEqual(0, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateWithError1(self): np_labels = np.matrix(('1 0 0;' '0 0 1;' '0 1 0')) np_predictions = np.matrix(('1 0 0;' '0 0 -1;' '1 0 0')) @@ -3259,10 +3427,11 @@ class MeanCosineDistanceTest(test.TestCase): error, update_op = metrics.mean_cosine_distance(labels, predictions, dim=2) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(1, sess.run(update_op), 5) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(1, self.evaluate(update_op), 5) self.assertAlmostEqual(1, error.eval(), 5) + @test_util.run_deprecated_v1 def testSingleUpdateWithError2(self): np_predictions = np.matrix( ('0.819031913261206 0.567041924552012 0.087465312324590;' @@ -3280,10 +3449,11 @@ class MeanCosineDistanceTest(test.TestCase): error, update_op = metrics.mean_cosine_distance(labels, predictions, dim=2) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertAlmostEqual(1.0, sess.run(update_op), 5) + self.evaluate(variables.local_variables_initializer()) + self.assertAlmostEqual(1.0, self.evaluate(update_op), 5) self.assertAlmostEqual(1.0, error.eval(), 5) + @test_util.run_deprecated_v1 def testSingleUpdateWithErrorAndWeights1(self): np_predictions = np.matrix(('1 0 0;' '0 0 -1;' '1 0 0')) np_labels = np.matrix(('1 0 0;' '0 0 1;' '0 1 0')) @@ -3299,10 +3469,11 @@ class MeanCosineDistanceTest(test.TestCase): labels, predictions, dim=2, weights=weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) - self.assertEqual(0, sess.run(update_op)) + self.evaluate(variables.local_variables_initializer()) + self.assertEqual(0, self.evaluate(update_op)) self.assertEqual(0, error.eval()) + @test_util.run_deprecated_v1 def testSingleUpdateWithErrorAndWeights2(self): np_predictions = np.matrix(('1 0 0;' '0 0 -1;' '1 0 0')) np_labels = np.matrix(('1 0 0;' '0 0 1;' '0 1 0')) @@ -3318,7 +3489,7 @@ class MeanCosineDistanceTest(test.TestCase): labels, predictions, dim=2, weights=weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertEqual(1.5, update_op.eval()) self.assertEqual(1.5, error.eval()) @@ -3328,6 +3499,7 @@ class PcntBelowThreshTest(test.TestCase): def setUp(self): ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.percentage_below(values=array_ops.ones((10,)), threshold=2) _assert_metric_variables(self, ( @@ -3335,6 +3507,7 @@ class PcntBelowThreshTest(test.TestCase): 'percentage_below_threshold/total:0', )) + @test_util.run_deprecated_v1 def testMetricsCollection(self): my_collection_name = '__metrics__' mean, _ = metrics.percentage_below( @@ -3343,6 +3516,7 @@ class PcntBelowThreshTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.percentage_below( @@ -3351,6 +3525,7 @@ class PcntBelowThreshTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testOneUpdate(self): with self.cached_session() as sess: values = constant_op.constant( @@ -3360,14 +3535,15 @@ class PcntBelowThreshTest(test.TestCase): pcnt1, update_op1 = metrics.percentage_below(values, 7, name='medium') pcnt2, update_op2 = metrics.percentage_below(values, 1, name='low') - sess.run(variables.local_variables_initializer()) - sess.run([update_op0, update_op1, update_op2]) + self.evaluate(variables.local_variables_initializer()) + self.evaluate([update_op0, update_op1, update_op2]) - pcnt0, pcnt1, pcnt2 = sess.run([pcnt0, pcnt1, pcnt2]) + pcnt0, pcnt1, pcnt2 = self.evaluate([pcnt0, pcnt1, pcnt2]) self.assertAlmostEqual(1.0, pcnt0, 5) self.assertAlmostEqual(0.75, pcnt1, 5) self.assertAlmostEqual(0.0, pcnt2, 5) + @test_util.run_deprecated_v1 def testSomePresentOneUpdate(self): with self.cached_session() as sess: values = constant_op.constant( @@ -3382,11 +3558,11 @@ class PcntBelowThreshTest(test.TestCase): pcnt2, update_op2 = metrics.percentage_below( values, 1, weights=weights, name='low') - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertListEqual([1.0, 0.5, 0.0], - sess.run([update_op0, update_op1, update_op2])) + self.evaluate([update_op0, update_op1, update_op2])) - pcnt0, pcnt1, pcnt2 = sess.run([pcnt0, pcnt1, pcnt2]) + pcnt0, pcnt1, pcnt2 = self.evaluate([pcnt0, pcnt1, pcnt2]) self.assertAlmostEqual(1.0, pcnt0, 5) self.assertAlmostEqual(0.5, pcnt1, 5) self.assertAlmostEqual(0.0, pcnt2, 5) @@ -3398,6 +3574,7 @@ class MeanIOUTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.mean_iou( predictions=array_ops.ones([10, 1]), @@ -3405,6 +3582,7 @@ class MeanIOUTest(test.TestCase): num_classes=2) _assert_metric_variables(self, ('mean_iou/total_confusion_matrix:0',)) + @test_util.run_deprecated_v1 def testMetricsCollections(self): my_collection_name = '__metrics__' mean_iou, _ = metrics.mean_iou( @@ -3414,6 +3592,7 @@ class MeanIOUTest(test.TestCase): metrics_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [mean_iou]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.mean_iou( @@ -3423,12 +3602,14 @@ class MeanIOUTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testPredictionsAndLabelsOfDifferentSizeRaisesValueError(self): predictions = array_ops.ones([10, 3]) labels = array_ops.ones([10, 4]) with self.assertRaises(ValueError): metrics.mean_iou(labels, predictions, num_classes=2) + @test_util.run_deprecated_v1 def testLabelsAndWeightsOfDifferentSizeRaisesValueError(self): predictions = array_ops.ones([10]) labels = array_ops.ones([10]) @@ -3436,6 +3617,7 @@ class MeanIOUTest(test.TestCase): with self.assertRaises(ValueError): metrics.mean_iou(labels, predictions, num_classes=2, weights=weights) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): num_classes = 3 predictions = random_ops.random_uniform( @@ -3446,17 +3628,18 @@ class MeanIOUTest(test.TestCase): labels, predictions, num_classes=num_classes) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_mean_iou = mean_iou.eval() for _ in range(10): self.assertEqual(initial_mean_iou, mean_iou.eval()) + @test_util.run_deprecated_v1 def testMultipleUpdates(self): num_classes = 3 with self.cached_session() as sess: @@ -3482,12 +3665,13 @@ class MeanIOUTest(test.TestCase): miou, update_op = metrics.mean_iou(labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(5): - sess.run(update_op) + self.evaluate(update_op) desired_output = np.mean([1.0 / 2.0, 1.0 / 4.0, 0.]) self.assertEqual(desired_output, miou.eval()) + @test_util.run_deprecated_v1 def testMultipleUpdatesWithWeights(self): num_classes = 2 with self.cached_session() as sess: @@ -3529,10 +3713,11 @@ class MeanIOUTest(test.TestCase): variables.local_variables_initializer().run() for _ in range(6): - sess.run(update_op) + self.evaluate(update_op) desired_output = np.mean([2.0 / 3.0, 1.0 / 2.0]) self.assertAlmostEqual(desired_output, mean_iou.eval()) + @test_util.run_deprecated_v1 def testMultipleUpdatesWithMissingClass(self): # Test the case where there are no predicions and labels for # one class, and thus there is one row and one column with @@ -3563,12 +3748,13 @@ class MeanIOUTest(test.TestCase): miou, update_op = metrics.mean_iou(labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(5): - sess.run(update_op) + self.evaluate(update_op) desired_output = np.mean([1.0 / 3.0, 2.0 / 4.0]) self.assertAlmostEqual(desired_output, miou.eval()) + @test_util.run_deprecated_v1 def testUpdateOpEvalIsAccumulatedConfusionMatrix(self): predictions = array_ops.concat( [ @@ -3587,32 +3773,35 @@ class MeanIOUTest(test.TestCase): num_classes = 2 with self.cached_session() as sess: miou, update_op = metrics.mean_iou(labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) confusion_matrix = update_op.eval() self.assertAllEqual([[3, 0], [2, 5]], confusion_matrix) desired_miou = np.mean([3. / 5., 5. / 7.]) self.assertAlmostEqual(desired_miou, miou.eval()) + @test_util.run_deprecated_v1 def testAllCorrect(self): predictions = array_ops.zeros([40]) labels = array_ops.zeros([40]) num_classes = 1 with self.cached_session() as sess: miou, update_op = metrics.mean_iou(labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertEqual(40, update_op.eval()[0]) self.assertEqual(1.0, miou.eval()) + @test_util.run_deprecated_v1 def testAllWrong(self): predictions = array_ops.zeros([40]) labels = array_ops.ones([40]) num_classes = 2 with self.cached_session() as sess: miou, update_op = metrics.mean_iou(labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual([[0, 0], [40, 0]], update_op.eval()) self.assertEqual(0., miou.eval()) + @test_util.run_deprecated_v1 def testResultsWithSomeMissing(self): predictions = array_ops.concat( [ @@ -3640,11 +3829,12 @@ class MeanIOUTest(test.TestCase): with self.cached_session() as sess: miou, update_op = metrics.mean_iou( labels, predictions, num_classes, weights=weights) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual([[2, 0], [2, 4]], update_op.eval()) desired_miou = np.mean([2. / 4., 4. / 6.]) self.assertAlmostEqual(desired_miou, miou.eval()) + @test_util.run_deprecated_v1 def testMissingClassInLabels(self): labels = constant_op.constant([ [[0, 0, 1, 1, 0, 0], @@ -3659,22 +3849,24 @@ class MeanIOUTest(test.TestCase): num_classes = 3 with self.cached_session() as sess: miou, update_op = metrics.mean_iou(labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual([[7, 4, 3], [3, 5, 2], [0, 0, 0]], update_op.eval()) self.assertAlmostEqual( 1 / 3 * (7 / (7 + 3 + 7) + 5 / (5 + 4 + 5) + 0 / (0 + 5 + 0)), miou.eval()) + @test_util.run_deprecated_v1 def testMissingClassOverallSmall(self): labels = constant_op.constant([0]) predictions = constant_op.constant([0]) num_classes = 2 with self.cached_session() as sess: miou, update_op = metrics.mean_iou(labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual([[1, 0], [0, 0]], update_op.eval()) self.assertAlmostEqual(1, miou.eval()) + @test_util.run_deprecated_v1 def testMissingClassOverallLarge(self): labels = constant_op.constant([ [[0, 0, 1, 1, 0, 0], @@ -3689,7 +3881,7 @@ class MeanIOUTest(test.TestCase): num_classes = 3 with self.cached_session() as sess: miou, update_op = metrics.mean_iou(labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual([[9, 5, 0], [3, 7, 0], [0, 0, 0]], update_op.eval()) self.assertAlmostEqual( 1 / 2 * (9 / (9 + 3 + 5) + 7 / (7 + 5 + 3)), miou.eval()) @@ -3701,6 +3893,7 @@ class MeanPerClassAccuracyTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.mean_per_class_accuracy( predictions=array_ops.ones([10, 1]), @@ -3709,6 +3902,7 @@ class MeanPerClassAccuracyTest(test.TestCase): _assert_metric_variables(self, ('mean_accuracy/count:0', 'mean_accuracy/total:0')) + @test_util.run_deprecated_v1 def testMetricsCollections(self): my_collection_name = '__metrics__' mean_accuracy, _ = metrics.mean_per_class_accuracy( @@ -3719,6 +3913,7 @@ class MeanPerClassAccuracyTest(test.TestCase): self.assertListEqual( ops.get_collection(my_collection_name), [mean_accuracy]) + @test_util.run_deprecated_v1 def testUpdatesCollection(self): my_collection_name = '__updates__' _, update_op = metrics.mean_per_class_accuracy( @@ -3728,12 +3923,14 @@ class MeanPerClassAccuracyTest(test.TestCase): updates_collections=[my_collection_name]) self.assertListEqual(ops.get_collection(my_collection_name), [update_op]) + @test_util.run_deprecated_v1 def testPredictionsAndLabelsOfDifferentSizeRaisesValueError(self): predictions = array_ops.ones([10, 3]) labels = array_ops.ones([10, 4]) with self.assertRaises(ValueError): metrics.mean_per_class_accuracy(labels, predictions, num_classes=2) + @test_util.run_deprecated_v1 def testLabelsAndWeightsOfDifferentSizeRaisesValueError(self): predictions = array_ops.ones([10]) labels = array_ops.ones([10]) @@ -3742,6 +3939,7 @@ class MeanPerClassAccuracyTest(test.TestCase): metrics.mean_per_class_accuracy( labels, predictions, num_classes=2, weights=weights) + @test_util.run_deprecated_v1 def testValueTensorIsIdempotent(self): num_classes = 3 predictions = random_ops.random_uniform( @@ -3752,11 +3950,11 @@ class MeanPerClassAccuracyTest(test.TestCase): labels, predictions, num_classes=num_classes) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) # Run several updates. for _ in range(10): - sess.run(update_op) + self.evaluate(update_op) # Then verify idempotency. initial_mean_accuracy = mean_accuracy.eval() @@ -3788,12 +3986,13 @@ class MeanPerClassAccuracyTest(test.TestCase): mean_accuracy, update_op = metrics.mean_per_class_accuracy( labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(5): - sess.run(update_op) + self.evaluate(update_op) desired_output = np.mean([1.0, 1.0 / 3.0, 0.0]) self.assertAlmostEqual(desired_output, mean_accuracy.eval()) + @test_util.run_deprecated_v1 def testMultipleUpdatesWithWeights(self): num_classes = 2 with self.cached_session() as sess: @@ -3835,10 +4034,11 @@ class MeanPerClassAccuracyTest(test.TestCase): variables.local_variables_initializer().run() for _ in range(6): - sess.run(update_op) + self.evaluate(update_op) desired_output = np.mean([2.0 / 2.0, 0.5 / 1.5]) self.assertAlmostEqual(desired_output, mean_accuracy.eval()) + @test_util.run_deprecated_v1 def testMultipleUpdatesWithMissingClass(self): # Test the case where there are no predicions and labels for # one class, and thus there is one row and one column with @@ -3870,12 +4070,13 @@ class MeanPerClassAccuracyTest(test.TestCase): mean_accuracy, update_op = metrics.mean_per_class_accuracy( labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) for _ in range(5): - sess.run(update_op) + self.evaluate(update_op) desired_output = np.mean([1.0 / 2.0, 2.0 / 3.0, 0.]) self.assertAlmostEqual(desired_output, mean_accuracy.eval()) + @test_util.run_deprecated_v1 def testAllCorrect(self): predictions = array_ops.zeros([40]) labels = array_ops.zeros([40]) @@ -3883,10 +4084,11 @@ class MeanPerClassAccuracyTest(test.TestCase): with self.cached_session() as sess: mean_accuracy, update_op = metrics.mean_per_class_accuracy( labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertEqual(1.0, update_op.eval()[0]) self.assertEqual(1.0, mean_accuracy.eval()) + @test_util.run_deprecated_v1 def testAllWrong(self): predictions = array_ops.zeros([40]) labels = array_ops.ones([40]) @@ -3894,10 +4096,11 @@ class MeanPerClassAccuracyTest(test.TestCase): with self.cached_session() as sess: mean_accuracy, update_op = metrics.mean_per_class_accuracy( labels, predictions, num_classes) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual([0.0, 0.0], update_op.eval()) self.assertEqual(0., mean_accuracy.eval()) + @test_util.run_deprecated_v1 def testResultsWithSomeMissing(self): predictions = array_ops.concat([ constant_op.constant(0, shape=[5]), constant_op.constant(1, shape=[5]) @@ -3913,7 +4116,7 @@ class MeanPerClassAccuracyTest(test.TestCase): with self.cached_session() as sess: mean_accuracy, update_op = metrics.mean_per_class_accuracy( labels, predictions, num_classes, weights=weights) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) desired_accuracy = np.array([2. / 2., 4. / 6.], dtype=np.float32) self.assertAllEqual(desired_accuracy, update_op.eval()) desired_mean_accuracy = np.mean(desired_accuracy) @@ -3926,12 +4129,14 @@ class FalseNegativesTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.false_negatives( labels=(0, 1, 0, 1), predictions=(0, 0, 1, 1)) _assert_metric_variables(self, ('false_negatives/count:0',)) + @test_util.run_deprecated_v1 def testUnweighted(self): labels = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), @@ -3945,11 +4150,12 @@ class FalseNegativesTest(test.TestCase): labels=labels, predictions=predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllClose(0., tn.eval()) self.assertAllClose(3., tn_update_op.eval()) self.assertAllClose(3., tn.eval()) + @test_util.run_deprecated_v1 def testWeighted(self): labels = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), @@ -3964,7 +4170,7 @@ class FalseNegativesTest(test.TestCase): labels=labels, predictions=predictions, weights=weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllClose(0., tn.eval()) self.assertAllClose(5., tn_update_op.eval()) self.assertAllClose(5., tn.eval()) @@ -3976,6 +4182,7 @@ class FalseNegativesAtThresholdsTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.false_negatives_at_thresholds( predictions=array_ops.ones((10, 1)), @@ -3983,6 +4190,7 @@ class FalseNegativesAtThresholdsTest(test.TestCase): thresholds=[0.15, 0.5, 0.85]) _assert_metric_variables(self, ('false_negatives/false_negatives:0',)) + @test_util.run_deprecated_v1 def testUnweighted(self): predictions = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), @@ -3994,11 +4202,12 @@ class FalseNegativesAtThresholdsTest(test.TestCase): predictions=predictions, labels=labels, thresholds=[0.15, 0.5, 0.85]) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual((0, 0, 0), fn.eval()) self.assertAllEqual((0, 2, 3), fn_update_op.eval()) self.assertAllEqual((0, 2, 3), fn.eval()) + @test_util.run_deprecated_v1 def testWeighted(self): predictions = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), @@ -4013,7 +4222,7 @@ class FalseNegativesAtThresholdsTest(test.TestCase): thresholds=[0.15, 0.5, 0.85]) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual((0.0, 0.0, 0.0), fn.eval()) self.assertAllEqual((0.0, 8.0, 11.0), fn_update_op.eval()) self.assertAllEqual((0.0, 8.0, 11.0), fn.eval()) @@ -4025,12 +4234,14 @@ class FalsePositivesTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.false_positives( labels=(0, 1, 0, 1), predictions=(0, 0, 1, 1)) _assert_metric_variables(self, ('false_positives/count:0',)) + @test_util.run_deprecated_v1 def testUnweighted(self): labels = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), @@ -4044,11 +4255,12 @@ class FalsePositivesTest(test.TestCase): labels=labels, predictions=predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllClose(0., tn.eval()) self.assertAllClose(7., tn_update_op.eval()) self.assertAllClose(7., tn.eval()) + @test_util.run_deprecated_v1 def testWeighted(self): labels = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), @@ -4063,7 +4275,7 @@ class FalsePositivesTest(test.TestCase): labels=labels, predictions=predictions, weights=weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllClose(0., tn.eval()) self.assertAllClose(14., tn_update_op.eval()) self.assertAllClose(14., tn.eval()) @@ -4075,6 +4287,7 @@ class FalsePositivesAtThresholdsTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.false_positives_at_thresholds( predictions=array_ops.ones((10, 1)), @@ -4082,6 +4295,7 @@ class FalsePositivesAtThresholdsTest(test.TestCase): thresholds=[0.15, 0.5, 0.85]) _assert_metric_variables(self, ('false_positives/false_positives:0',)) + @test_util.run_deprecated_v1 def testUnweighted(self): predictions = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), @@ -4093,11 +4307,12 @@ class FalsePositivesAtThresholdsTest(test.TestCase): predictions=predictions, labels=labels, thresholds=[0.15, 0.5, 0.85]) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual((0, 0, 0), fp.eval()) self.assertAllEqual((7, 4, 2), fp_update_op.eval()) self.assertAllEqual((7, 4, 2), fp.eval()) + @test_util.run_deprecated_v1 def testWeighted(self): predictions = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), @@ -4114,7 +4329,7 @@ class FalsePositivesAtThresholdsTest(test.TestCase): thresholds=[0.15, 0.5, 0.85]) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual((0.0, 0.0, 0.0), fp.eval()) self.assertAllEqual((125.0, 42.0, 12.0), fp_update_op.eval()) self.assertAllEqual((125.0, 42.0, 12.0), fp.eval()) @@ -4126,12 +4341,14 @@ class TrueNegativesTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.true_negatives( labels=(0, 1, 0, 1), predictions=(0, 0, 1, 1)) _assert_metric_variables(self, ('true_negatives/count:0',)) + @test_util.run_deprecated_v1 def testUnweighted(self): labels = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), @@ -4145,11 +4362,12 @@ class TrueNegativesTest(test.TestCase): labels=labels, predictions=predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllClose(0., tn.eval()) self.assertAllClose(3., tn_update_op.eval()) self.assertAllClose(3., tn.eval()) + @test_util.run_deprecated_v1 def testWeighted(self): labels = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), @@ -4164,7 +4382,7 @@ class TrueNegativesTest(test.TestCase): labels=labels, predictions=predictions, weights=weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllClose(0., tn.eval()) self.assertAllClose(4., tn_update_op.eval()) self.assertAllClose(4., tn.eval()) @@ -4176,6 +4394,7 @@ class TrueNegativesAtThresholdsTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.true_negatives_at_thresholds( predictions=array_ops.ones((10, 1)), @@ -4183,6 +4402,7 @@ class TrueNegativesAtThresholdsTest(test.TestCase): thresholds=[0.15, 0.5, 0.85]) _assert_metric_variables(self, ('true_negatives/true_negatives:0',)) + @test_util.run_deprecated_v1 def testUnweighted(self): predictions = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), @@ -4194,11 +4414,12 @@ class TrueNegativesAtThresholdsTest(test.TestCase): predictions=predictions, labels=labels, thresholds=[0.15, 0.5, 0.85]) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual((0, 0, 0), tn.eval()) self.assertAllEqual((2, 5, 7), tn_update_op.eval()) self.assertAllEqual((2, 5, 7), tn.eval()) + @test_util.run_deprecated_v1 def testWeighted(self): predictions = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), @@ -4213,7 +4434,7 @@ class TrueNegativesAtThresholdsTest(test.TestCase): thresholds=[0.15, 0.5, 0.85]) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual((0.0, 0.0, 0.0), tn.eval()) self.assertAllEqual((5.0, 15.0, 23.0), tn_update_op.eval()) self.assertAllEqual((5.0, 15.0, 23.0), tn.eval()) @@ -4225,12 +4446,14 @@ class TruePositivesTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.true_positives( labels=(0, 1, 0, 1), predictions=(0, 0, 1, 1)) _assert_metric_variables(self, ('true_positives/count:0',)) + @test_util.run_deprecated_v1 def testUnweighted(self): labels = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), @@ -4244,11 +4467,12 @@ class TruePositivesTest(test.TestCase): labels=labels, predictions=predictions) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllClose(0., tn.eval()) self.assertAllClose(7., tn_update_op.eval()) self.assertAllClose(7., tn.eval()) + @test_util.run_deprecated_v1 def testWeighted(self): labels = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), @@ -4263,7 +4487,7 @@ class TruePositivesTest(test.TestCase): labels=labels, predictions=predictions, weights=weights) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllClose(0., tn.eval()) self.assertAllClose(12., tn_update_op.eval()) self.assertAllClose(12., tn.eval()) @@ -4275,6 +4499,7 @@ class TruePositivesAtThresholdsTest(test.TestCase): np.random.seed(1) ops.reset_default_graph() + @test_util.run_deprecated_v1 def testVars(self): metrics.true_positives_at_thresholds( predictions=array_ops.ones((10, 1)), @@ -4282,6 +4507,7 @@ class TruePositivesAtThresholdsTest(test.TestCase): thresholds=[0.15, 0.5, 0.85]) _assert_metric_variables(self, ('true_positives/true_positives:0',)) + @test_util.run_deprecated_v1 def testUnweighted(self): predictions = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), @@ -4293,11 +4519,12 @@ class TruePositivesAtThresholdsTest(test.TestCase): predictions=predictions, labels=labels, thresholds=[0.15, 0.5, 0.85]) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual((0, 0, 0), tp.eval()) self.assertAllEqual((3, 1, 0), tp_update_op.eval()) self.assertAllEqual((3, 1, 0), tp.eval()) + @test_util.run_deprecated_v1 def testWeighted(self): predictions = constant_op.constant(((0.9, 0.2, 0.8, 0.1), (0.2, 0.9, 0.7, 0.6), @@ -4310,7 +4537,7 @@ class TruePositivesAtThresholdsTest(test.TestCase): thresholds=[0.15, 0.5, 0.85]) with self.cached_session() as sess: - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) self.assertAllEqual((0.0, 0.0, 0.0), tp.eval()) self.assertAllEqual((111.0, 37.0, 0.0), tp_update_op.eval()) self.assertAllEqual((111.0, 37.0, 0.0), tp.eval()) diff --git a/tensorflow/python/kernel_tests/morphological_ops_test.py b/tensorflow/python/kernel_tests/morphological_ops_test.py index 6d601554b8..f54aaf30d0 100644 --- a/tensorflow/python/kernel_tests/morphological_ops_test.py +++ b/tensorflow/python/kernel_tests/morphological_ops_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import nn_ops import tensorflow.python.ops.nn_grad # pylint: disable=unused-import @@ -52,7 +53,7 @@ class DilationTest(test.TestCase): rates=rates, padding=padding, name="dilation2d") - self.assertAllClose(out, out_tensor.eval()) + self.assertAllClose(out, self.evaluate(out_tensor)) def _testDilationValidPadding(self, use_gpu): # [1, 2, 2, 1] @@ -216,7 +217,7 @@ class DilationTest(test.TestCase): rates=rates, padding=padding, name="dilation2d") - out_shape = out_tensor.eval().shape + out_shape = self.evaluate(out_tensor).shape # Small delta is necessary for argmax to remain the same. err = gradient_checker.compute_gradient_error( @@ -291,6 +292,7 @@ class DilationTest(test.TestCase): padding="SAME", use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testDilationGrad(self): for use_gpu in True, False: self._testDilationGradValidPadding_1x1x1(use_gpu) @@ -327,7 +329,7 @@ class ErosionTest(test.TestCase): rates=rates, padding=padding, name="erosion2d") - self.assertAllClose(out, out_tensor.eval()) + self.assertAllClose(out, self.evaluate(out_tensor)) def _testErosionValidPadding(self, use_gpu): # [1, 2, 2, 1] @@ -491,7 +493,7 @@ class ErosionTest(test.TestCase): rates=rates, padding=padding, name="erosion2d") - out_shape = out_tensor.eval().shape + out_shape = self.evaluate(out_tensor).shape # Small delta is necessary for argmax to remain the same. err = gradient_checker.compute_gradient_error( @@ -566,6 +568,7 @@ class ErosionTest(test.TestCase): padding="SAME", use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testErosionGrad(self): for use_gpu in True, False: self._testErosionGradValidPadding_1x1x1(use_gpu) diff --git a/tensorflow/python/kernel_tests/neon_depthwise_conv_op_test.py b/tensorflow/python/kernel_tests/neon_depthwise_conv_op_test.py index 15e3826542..380d2860da 100644 --- a/tensorflow/python/kernel_tests/neon_depthwise_conv_op_test.py +++ b/tensorflow/python/kernel_tests/neon_depthwise_conv_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import nn_impl from tensorflow.python.ops import nn_ops @@ -142,8 +143,8 @@ class DepthwiseConv2DTest(test.TestCase): conv_interface = nn_impl.depthwise_conv2d( t1, t2, strides=[1, stride, stride, 1], padding=padding) - native_result = sess.run(conv_native) - interface_result = sess.run(conv_interface) + native_result = self.evaluate(conv_native) + interface_result = self.evaluate(conv_interface) print("depthwise conv_2d: ", tensor_in_sizes, "*", filter_in_sizes, ", stride:", stride, ", padding: ", padding, ", max diff: ", @@ -153,6 +154,7 @@ class DepthwiseConv2DTest(test.TestCase): self.assertShapeEqual(native_result, conv_native) self.assertShapeEqual(native_result, conv_interface) + @test_util.run_deprecated_v1 def testDepthwiseConv2D(self): for index, (input_size, filter_size, _, stride, padding) in enumerate(ConfigsToTest()): @@ -211,11 +213,12 @@ class DepthwiseConv2DTest(test.TestCase): t2 = constant_op.constant(x2, shape=filter_in_sizes) conv = nn_ops.depthwise_conv2d_native( t1, t2, strides=[1, stride, stride, 1], padding=padding) - value = sess.run(conv) + value = self.evaluate(conv) print("value = ", value) self.assertAllClose(expected, np.ravel(value), 1e-5) self.assertShapeEqual(value, conv) + @test_util.run_deprecated_v1 def testConv2D2x2Filter(self): # The inputs look like this (it's a 3 x 2 matrix, each of depth 2): # diff --git a/tensorflow/python/kernel_tests/norm_op_test.py b/tensorflow/python/kernel_tests/norm_op_test.py index e202b6e8a4..5ff0c58bf1 100644 --- a/tensorflow/python/kernel_tests/norm_op_test.py +++ b/tensorflow/python/kernel_tests/norm_op_test.py @@ -70,7 +70,7 @@ def _GetNormOpTest(dtype_, shape_, ord_, axis_, keep_dims_, use_static_shape_): tf_matrix = constant_op.constant(matrix) tf_norm = linalg_ops.norm( tf_matrix, ord=ord_, axis=axis_, keepdims=keep_dims_) - tf_norm_val = sess.run(tf_norm) + tf_norm_val = self.evaluate(tf_norm) else: tf_matrix = array_ops.placeholder(dtype_) tf_norm = linalg_ops.norm( diff --git a/tensorflow/python/kernel_tests/nth_element_op_test.py b/tensorflow/python/kernel_tests/nth_element_op_test.py index 338b6cec01..4be78b2d5c 100644 --- a/tensorflow/python/kernel_tests/nth_element_op_test.py +++ b/tensorflow/python/kernel_tests/nth_element_op_test.py @@ -22,6 +22,7 @@ import numpy as np import tensorflow.python.ops.nn_grad # pylint: disable=unused-import from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import nn_ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl @@ -35,7 +36,7 @@ class NthElementTest(test.TestCase): with self.cached_session(use_gpu=False) as sess: inputs_op = ops.convert_to_tensor(inputs, dtype=dtype) values_op = nn_ops.nth_element(inputs_op, n, reverse=reverse) - values = sess.run(values_op) + values = self.evaluate(values_op) self.assertShapeEqual(np_expected_values, values_op) self.assertAllClose(np_expected_values, values) @@ -111,17 +112,20 @@ class NthElementTest(test.TestCase): self._testEnumerateN([10, 10, 10]) self._testEnumerateN([10, 10, 10, 10]) + @test_util.run_deprecated_v1 def testInvalidInput(self): with self.assertRaisesRegexp(ValueError, "at least rank 1 but is rank 0"): nn_ops.nth_element(5, 0) + @test_util.run_deprecated_v1 def testInvalidInputAtEval(self): with self.session(use_gpu=False): v = array_ops.placeholder(dtype=dtypes.float32) with self.assertRaisesOpError("Input must be >= 1-D"): nn_ops.nth_element(v, 0).eval(feed_dict={v: 5.0}) + @test_util.run_deprecated_v1 def testInvalidN(self): with self.assertRaisesRegexp(ValueError, "non-negative but is -1"): @@ -130,6 +134,7 @@ class NthElementTest(test.TestCase): "scalar but has rank 1"): nn_ops.nth_element([5, 6, 3], [1]) + @test_util.run_deprecated_v1 def testInvalidNAtEval(self): inputs = [[0.1, 0.2], [0.3, 0.4]] with self.session(use_gpu=False): @@ -138,12 +143,14 @@ class NthElementTest(test.TestCase): with self.assertRaisesOpError("Need n >= 0, got -7"): values.eval(feed_dict={n: -7}) + @test_util.run_deprecated_v1 def testNTooLarge(self): inputs = [[0.1, 0.2], [0.3, 0.4]] with self.assertRaisesRegexp(ValueError, "must have last dimension > n = 2"): nn_ops.nth_element(inputs, 2) + @test_util.run_deprecated_v1 def testNTooLargeAtEval(self): inputs = [[0.1, 0.2], [0.3, 0.4]] with self.session(use_gpu=False): @@ -152,6 +159,7 @@ class NthElementTest(test.TestCase): with self.assertRaisesOpError(r"Input must have at least n\+1 columns"): values.eval(feed_dict={n: 2}) + @test_util.run_deprecated_v1 def testGradients(self): with self.session(use_gpu=False) as sess: inputs = array_ops.placeholder(dtypes.float32, shape=[3, 5]) diff --git a/tensorflow/python/kernel_tests/numerics_test.py b/tensorflow/python/kernel_tests/numerics_test.py index 5db591ed30..5751f3fe76 100644 --- a/tensorflow/python/kernel_tests/numerics_test.py +++ b/tensorflow/python/kernel_tests/numerics_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops @@ -35,11 +36,11 @@ class VerifyTensorAllFiniteTest(test.TestCase): def testVerifyTensorAllFiniteSucceeds(self): x_shape = [5, 4] x = np.random.random_sample(x_shape).astype(np.float32) - with self.session(use_gpu=True): + with test_util.use_gpu(): t = constant_op.constant(x, shape=x_shape, dtype=dtypes.float32) t_verified = numerics.verify_tensor_all_finite(t, "Input is not a number.") - self.assertAllClose(x, t_verified.eval()) + self.assertAllClose(x, self.evaluate(t_verified)) def testVerifyTensorAllFiniteFails(self): x_shape = [5, 4] @@ -48,23 +49,24 @@ class VerifyTensorAllFiniteTest(test.TestCase): # Test NaN. x[0] = np.nan - with self.session(use_gpu=True): + with test_util.use_gpu(): with self.assertRaisesOpError(my_msg): t = constant_op.constant(x, shape=x_shape, dtype=dtypes.float32) t_verified = numerics.verify_tensor_all_finite(t, my_msg) - t_verified.eval() + self.evaluate(t_verified) # Test Inf. x[0] = np.inf - with self.session(use_gpu=True): + with test_util.use_gpu(): with self.assertRaisesOpError(my_msg): t = constant_op.constant(x, shape=x_shape, dtype=dtypes.float32) t_verified = numerics.verify_tensor_all_finite(t, my_msg) - t_verified.eval() + self.evaluate(t_verified) class NumericsTest(test.TestCase): + @test_util.run_deprecated_v1 def testInf(self): with self.session(graph=ops.Graph()): t1 = constant_op.constant(1.0) @@ -73,8 +75,9 @@ class NumericsTest(test.TestCase): check = numerics.add_check_numerics_ops() a = control_flow_ops.with_dependencies([check], a) with self.assertRaisesOpError("Inf"): - a.eval() + self.evaluate(a) + @test_util.run_deprecated_v1 def testNaN(self): with self.session(graph=ops.Graph()): t1 = constant_op.constant(0.0) @@ -83,8 +86,9 @@ class NumericsTest(test.TestCase): check = numerics.add_check_numerics_ops() a = control_flow_ops.with_dependencies([check], a) with self.assertRaisesOpError("NaN"): - a.eval() + self.evaluate(a) + @test_util.run_deprecated_v1 def testBoth(self): with self.session(graph=ops.Graph()): t1 = constant_op.constant([1.0, 0.0]) @@ -93,16 +97,17 @@ class NumericsTest(test.TestCase): check = numerics.add_check_numerics_ops() a = control_flow_ops.with_dependencies([check], a) with self.assertRaisesOpError("Inf and NaN"): - a.eval() + self.evaluate(a) def testPassThrough(self): with self.session(graph=ops.Graph()): t1 = constant_op.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3]) checked = array_ops.check_numerics(t1, message="pass through test") - value = checked.eval() + value = self.evaluate(checked) self.assertAllEqual(np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]), value) self.assertEqual([2, 3], checked.get_shape()) + @test_util.run_deprecated_v1 def testControlFlowCond(self): predicate = array_ops.placeholder(dtypes.bool, shape=[]) _ = control_flow_ops.cond(predicate, @@ -115,6 +120,7 @@ class NumericsTest(test.TestCase): r"or `tf.while_loop\(\)`\."): numerics.add_check_numerics_ops() + @test_util.run_deprecated_v1 def testControlFlowWhile(self): predicate = array_ops.placeholder(dtypes.bool, shape=[]) _ = control_flow_ops.while_loop(lambda _: predicate, diff --git a/tensorflow/python/kernel_tests/one_hot_op_test.py b/tensorflow/python/kernel_tests/one_hot_op_test.py index 377d545c9c..856ba7bb7f 100644 --- a/tensorflow/python/kernel_tests/one_hot_op_test.py +++ b/tensorflow/python/kernel_tests/one_hot_op_test.py @@ -41,12 +41,12 @@ class OneHotTest(test.TestCase): else: ans = array_ops.one_hot(**inputs) if expected_err_re is None: - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllEqual(tf_ans, truth) self.assertEqual(tf_ans.shape, ans.get_shape()) else: with self.assertRaisesOpError(expected_err_re): - ans.eval() + self.evaluate(ans) def _testBothOneHot(self, truth, expected_err_re=None, raises=None, **inputs): self._testOneHot(truth, True, expected_err_re, raises, **inputs) diff --git a/tensorflow/python/kernel_tests/pad_op_test.py b/tensorflow/python/kernel_tests/pad_op_test.py index fc302c4141..7b1b054ae0 100644 --- a/tensorflow/python/kernel_tests/pad_op_test.py +++ b/tensorflow/python/kernel_tests/pad_op_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.platform import test @@ -88,7 +89,7 @@ class PadOpTest(test.TestCase): with self.cached_session(use_gpu=True): tf_val = array_ops.pad(np_inputs, paddings, mode=mode, constant_values=constant_values) - out = tf_val.eval() + out = self.evaluate(tf_val) self.assertAllEqual(np_val, out) self.assertShapeEqual(np_val, tf_val) @@ -116,6 +117,7 @@ class PadOpTest(test.TestCase): self._testGradient(np_inputs, paddings, mode=mode, constant_values=constant_values) + @test_util.run_deprecated_v1 def testInputDims(self): with self.session(use_gpu=True): with self.assertRaises(ValueError): @@ -124,6 +126,7 @@ class PadOpTest(test.TestCase): array_ops.reshape( [1, 2], shape=[1, 2])) + @test_util.run_deprecated_v1 def testPaddingsDim(self): with self.session(use_gpu=True): with self.assertRaises(ValueError): @@ -132,6 +135,7 @@ class PadOpTest(test.TestCase): array_ops.reshape( [1, 2], shape=[2])) + @test_util.run_deprecated_v1 def testPaddingsDim2(self): with self.session(use_gpu=True): with self.assertRaises(ValueError): @@ -140,6 +144,7 @@ class PadOpTest(test.TestCase): array_ops.reshape( [1, 2], shape=[2, 1])) + @test_util.run_deprecated_v1 def testPaddingsDim3(self): with self.session(use_gpu=True): with self.assertRaises(ValueError): @@ -148,6 +153,7 @@ class PadOpTest(test.TestCase): array_ops.reshape( [1, 2], shape=[1, 2])) + @test_util.run_deprecated_v1 def testPaddingsDim4(self): with self.session(use_gpu=True): with self.assertRaises(ValueError): @@ -156,6 +162,7 @@ class PadOpTest(test.TestCase): array_ops.reshape( [1, 2, 3, 4, 5, 6], shape=[3, 2])) + @test_util.run_deprecated_v1 def testPaddingsNonNegative(self): with self.session(use_gpu=True): with self.assertRaisesRegexp(ValueError, "must be non-negative"): @@ -164,6 +171,7 @@ class PadOpTest(test.TestCase): constant_op.constant( [-1, 0], shape=[1, 2])) + @test_util.run_deprecated_v1 def testPaddingsNonNegative2(self): with self.session(use_gpu=True): with self.assertRaisesRegexp(ValueError, "must be non-negative"): @@ -208,7 +216,7 @@ class PadOpTest(test.TestCase): constant_op.constant(paddings, padding_dtype), mode=mode, constant_values=0) - out = tf_val.eval() + out = self.evaluate(tf_val) self.assertAllEqual(np_val, out) self.assertShapeEqual(np_val, tf_val) @@ -223,6 +231,7 @@ class PadOpTest(test.TestCase): np.random.randint(-100, 100, (4, 2, 1, 3)).astype(t), [[0, 0], [0, 0], [0, 0], [0, 0]], -123) + @test_util.run_deprecated_v1 def testFloatTypes(self): for t in [np.float32, np.float64]: self._testAll(np.random.rand(2, 5).astype(t), [[1, 0], [2, 0]], 0.0) @@ -250,17 +259,18 @@ class PadOpTest(test.TestCase): symmetric = array_ops.pad(x, [[1, 0], [0, 1]], mode="SYMMETRIC", constant_values="PAD") with self.session(use_gpu=True): - self.assertAllEqual([[b"PAD", b"PAD", b"PAD"], - [b"Hello", b"World", b"PAD"], - [b"Goodnight", b"Moon", b"PAD"]], constant.eval()) + self.assertAllEqual( + [[b"PAD", b"PAD", b"PAD"], [b"Hello", b"World", b"PAD"], + [b"Goodnight", b"Moon", b"PAD"]], self.evaluate(constant)) self.assertAllEqual([[b"Goodnight", b"Moon", b"Goodnight"], [b"Hello", b"World", b"Hello"], [b"Goodnight", b"Moon", b"Goodnight"]], - reflect.eval()) - self.assertAllEqual([[b"Hello", b"World", b"World"], - [b"Hello", b"World", b"World"], - [b"Goodnight", b"Moon", b"Moon"]], symmetric.eval()) + self.evaluate(reflect)) + self.assertAllEqual( + [[b"Hello", b"World", b"World"], [b"Hello", b"World", b"World"], + [b"Goodnight", b"Moon", b"Moon"]], self.evaluate(symmetric)) + @test_util.run_deprecated_v1 def testShapeFunctionEdgeCases(self): # Unknown paddings shape. inp = constant_op.constant(0.0, shape=[4, 4, 4, 4]) @@ -277,6 +287,7 @@ class PadOpTest(test.TestCase): padded = array_ops.pad(inp, array_ops.placeholder(dtypes.int32)) self.assertAllEqual(None, padded.get_shape().ndims) + @test_util.run_deprecated_v1 def testPartialShapeInformation(self): unknown = array_ops.placeholder(dtypes.int32) @@ -327,7 +338,7 @@ class PadOpTest(test.TestCase): inp = np.asarray(7) with self.session(use_gpu=True): tf_val = array_ops.pad(inp, paddings) - out = tf_val.eval() + out = self.evaluate(tf_val) self.assertAllEqual(inp, out) self.assertShapeEqual(inp, tf_val) @@ -337,10 +348,11 @@ class PadOpTest(test.TestCase): inp = np.asarray(7) with self.cached_session(use_gpu=True): tf_val = array_ops.pad(inp, constant_op.constant(paddings, dtype=dtype)) - out = tf_val.eval() + out = self.evaluate(tf_val) self.assertAllEqual(inp, out) self.assertShapeEqual(inp, tf_val) + @test_util.run_deprecated_v1 def testCollapseAdjacentNonPaddedDimensions(self): # pyformat: disable paddings_values = [[[0, 0], [0, 0], [0, 0], [0, 1]], @@ -361,11 +373,12 @@ class PadOpTest(test.TestCase): [paddings_value[i][0] + inp.shape.dims[i].value for i in range(4)], [-1, -1, -1, -1]) with self.cached_session(use_gpu=True): - self.assertAllEqual(inp.eval(), middle.eval()) + self.assertAllEqual(inp.eval(), self.evaluate(middle)) self.assertAllEqual( - np.zeros([row[0] for row in paddings_value]), left.eval()) + np.zeros([row[0] for row in paddings_value]), self.evaluate(left)) self.assertAllEqual( - np.zeros([row[1] for row in paddings_value]), right.eval()) + np.zeros([row[1] for row in paddings_value]), + self.evaluate(right)) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/padding_fifo_queue_test.py b/tensorflow/python/kernel_tests/padding_fifo_queue_test.py index 95f3dcceea..b4818360d5 100644 --- a/tensorflow/python/kernel_tests/padding_fifo_queue_test.py +++ b/tensorflow/python/kernel_tests/padding_fifo_queue_test.py @@ -126,7 +126,7 @@ class PaddingFIFOQueueTest(test.TestCase): # Run one producer thread for each element in elems. def enqueue(enqueue_op): - sess.run(enqueue_op) + self.evaluate(enqueue_op) threads = [ self.checkedThread( @@ -158,7 +158,7 @@ class PaddingFIFOQueueTest(test.TestCase): results = [] def dequeue(): - results.append(sess.run(dequeued_t)) + results.append(self.evaluate(dequeued_t)) threads = [self.checkedThread(target=dequeue) for _ in enqueue_ops] for thread in threads: @@ -178,7 +178,7 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() for i in xrange(len(elems)): - vals = dequeued_t.eval() + vals = self.evaluate(dequeued_t) self.assertEqual([elems[i]], vals) def testEnqueueAndBlockingDequeue(self): @@ -193,13 +193,13 @@ class PaddingFIFOQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) for enqueue_op in enqueue_ops: - sess.run(enqueue_op) + self.evaluate(enqueue_op) results = [] def dequeue(): for _ in xrange(len(elems)): - results.append(sess.run(dequeued_t)) + results.append(self.evaluate(dequeued_t)) enqueue_thread = self.checkedThread(target=enqueue) dequeue_thread = self.checkedThread(target=dequeue) @@ -224,7 +224,7 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() for i in xrange(len(elems)): - x_val, y_val = sess.run(dequeued_t) + x_val, y_val = self.evaluate(dequeued_t) x, y = elems[i] self.assertEqual([x], x_val) self.assertEqual([y], y_val) @@ -243,9 +243,9 @@ class PaddingFIFOQueueTest(test.TestCase): self.assertEqual([], size.get_shape()) enqueue_op.run() - self.assertEqual(1, size.eval()) + self.assertEqual(1, self.evaluate(size)) dequeued_t.op.run() - self.assertEqual(0, size.eval()) + self.assertEqual(0, self.evaluate(size)) def testEnqueueMany(self): with self.cached_session(): @@ -257,7 +257,7 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() for i in range(8): - vals = dequeued_t.eval() + vals = self.evaluate(dequeued_t) self.assertEqual([elems[i % 4]], vals) def testEmptyEnqueueMany(self): @@ -269,9 +269,9 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op = q.enqueue_many((empty_t,)) size_t = q.size() - self.assertEqual([0], size_t.eval()) + self.assertEqual([0], self.evaluate(size_t)) enqueue_op.run() - self.assertEqual([0], size_t.eval()) + self.assertEqual([0], self.evaluate(size_t)) def testEmptyDequeueMany(self): with self.cached_session(): @@ -279,9 +279,9 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op = q.enqueue((10.0,)) dequeued_t = q.dequeue_many(0) - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) enqueue_op.run() - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) def testEmptyDequeueManyWithDynamicShape(self): with self.cached_session(): @@ -290,9 +290,9 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op = q.enqueue(([10.0],)) dequeued_t = q.dequeue_many(0) - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) enqueue_op.run() - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) def testEmptyDequeueUpToWithDynamicShape(self): with self.cached_session(): @@ -301,9 +301,9 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op = q.enqueue(([10.0],)) dequeued_t = q.dequeue_up_to(0) - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) enqueue_op.run() - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) def testConstructPaddingFIFOQueueWithNoShape(self): with self.cached_session(): @@ -327,7 +327,7 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() for i in range(8): - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertEqual(float_elems[i % 4], float_val) self.assertAllEqual(int_elems[i % 4], int_val) @@ -344,7 +344,7 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() for i in range(8): - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertEqual(float_elems[i % 4], float_val) self.assertAllEqual(int_elems[i % 4], int_val) @@ -357,8 +357,8 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() - self.assertAllEqual(elems[0:4], dequeued_t.eval()) - self.assertAllEqual(elems[4:8], dequeued_t.eval()) + self.assertAllEqual(elems[0:4], self.evaluate(dequeued_t)) + self.assertAllEqual(elems[4:8], self.evaluate(dequeued_t)) def testDequeueUpToNoBlocking(self): with self.cached_session(): @@ -369,8 +369,8 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() - self.assertAllEqual(elems[0:4], dequeued_t.eval()) - self.assertAllEqual(elems[4:8], dequeued_t.eval()) + self.assertAllEqual(elems[0:4], self.evaluate(dequeued_t)) + self.assertAllEqual(elems[4:8], self.evaluate(dequeued_t)) def testMultiDequeueMany(self): with self.cached_session() as sess: @@ -387,17 +387,17 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual(float_elems[0:4], float_val) self.assertAllEqual(int_elems[0:4], int_val) self.assertEqual(float_val.shape, dequeued_t[0].get_shape()) self.assertEqual(int_val.shape, dequeued_t[1].get_shape()) - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual(float_elems[4:8], float_val) self.assertAllEqual(int_elems[4:8], int_val) - float_val, int_val = sess.run(dequeued_single_t) + float_val, int_val = self.evaluate(dequeued_single_t) self.assertAllEqual(float_elems[8], float_val) self.assertAllEqual(int_elems[8], int_val) self.assertEqual(float_val.shape, dequeued_single_t[0].get_shape()) @@ -418,7 +418,7 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual(float_elems[0:4], float_val) self.assertAllEqual(int_elems[0:4], int_val) self.assertTrue( @@ -428,11 +428,11 @@ class PaddingFIFOQueueTest(test.TestCase): tensor_shape.TensorShape(int_val.shape).is_compatible_with(dequeued_t[ 1].get_shape())) - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual(float_elems[4:8], float_val) self.assertAllEqual(int_elems[4:8], int_val) - float_val, int_val = sess.run(dequeued_single_t) + float_val, int_val = self.evaluate(dequeued_single_t) self.assertAllEqual(float_elems[8], float_val) self.assertAllEqual(int_elems[8], int_val) self.assertTrue( @@ -459,7 +459,7 @@ class PaddingFIFOQueueTest(test.TestCase): for enqueue_op in enqueue_ops: enqueue_op.run() - string_val, int_val = sess.run(dequeued_t) + string_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual([[b"a", b"", b""], [b"ab", b"", b""], [b"abc", b"", b""], [b"abc", b"d", b""], @@ -473,7 +473,7 @@ class PaddingFIFOQueueTest(test.TestCase): tensor_shape.TensorShape(int_val.shape).is_compatible_with(dequeued_t[ 1].get_shape())) - string_val, int_val = sess.run(dequeued_single_t) + string_val, int_val = self.evaluate(dequeued_single_t) self.assertAllEqual([b"abc", b"d", b"e", b"f"], string_val) self.assertAllEqual([[1, 2, 3, 4]], int_val) self.assertTrue( @@ -500,7 +500,7 @@ class PaddingFIFOQueueTest(test.TestCase): for enqueue_op in enqueue_ops: enqueue_op.run() - string_val, int_val = sess.run(dequeued_t) + string_val, int_val = self.evaluate(dequeued_t) self.assertAllEqual([[b"a", b"", b""], [b"ab", b"", b""], [b"abc", b"", b""], [b"abc", b"d", b""], @@ -514,7 +514,7 @@ class PaddingFIFOQueueTest(test.TestCase): tensor_shape.TensorShape(int_val.shape).is_compatible_with(dequeued_t[ 1].get_shape())) - string_val, int_val = sess.run(dequeued_single_t) + string_val, int_val = self.evaluate(dequeued_single_t) self.assertAllEqual([b"abc", b"d", b"e", b"f"], string_val) self.assertAllEqual([[1, 2, 3, 4]], int_val) self.assertTrue( @@ -622,7 +622,7 @@ class PaddingFIFOQueueTest(test.TestCase): r"Expected \[2,\?,3\], got \[2,3,4\]"): sess.run([enqueue_op], feed_dict={elems_bad: np.array([1] * 24).reshape((2, 3, 4))}) - dequeued_t.eval() + self.evaluate(dequeued_t) def testParallelEnqueueMany(self): with self.cached_session() as sess: @@ -633,7 +633,7 @@ class PaddingFIFOQueueTest(test.TestCase): # Enqueue 100 items in parallel on 10 threads. def enqueue(): - sess.run(enqueue_op) + self.evaluate(enqueue_op) threads = [self.checkedThread(target=enqueue) for _ in range(10)] for thread in threads: @@ -656,7 +656,7 @@ class PaddingFIFOQueueTest(test.TestCase): dequeued_elems = [] def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t)) + dequeued_elems.extend(self.evaluate(dequeued_t)) threads = [self.checkedThread(target=dequeue) for _ in range(10)] for thread in threads: @@ -680,7 +680,7 @@ class PaddingFIFOQueueTest(test.TestCase): dequeued_elems = [] def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t)) + dequeued_elems.extend(self.evaluate(dequeued_t)) threads = [self.checkedThread(target=dequeue) for _ in range(10)] for thread in threads: @@ -700,11 +700,11 @@ class PaddingFIFOQueueTest(test.TestCase): def enqueue(): for _ in xrange(100): - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): for _ in xrange(100): - self.assertTrue(sess.run(dequeued_t) in (10.0, 20.0)) + self.assertTrue(self.evaluate(dequeued_t) in (10.0, 20.0)) enqueue_threads = [self.checkedThread(target=enqueue) for _ in range(10)] dequeue_threads = [self.checkedThread(target=dequeue) for _ in range(10)] @@ -736,7 +736,7 @@ class PaddingFIFOQueueTest(test.TestCase): def dequeue(): for i in xrange(250): - self.assertEqual(i, sess.run(dequeued_t)) + self.assertEqual(i, self.evaluate(dequeued_t)) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -767,7 +767,7 @@ class PaddingFIFOQueueTest(test.TestCase): dequeuemany_t = q.dequeue_many(count_placeholder) def enqueue(): - sess.run(enqueue_op) + self.evaluate(enqueue_op) enqueue_thread = self.checkedThread(target=enqueue) enqueue_thread.start() @@ -776,7 +776,7 @@ class PaddingFIFOQueueTest(test.TestCase): while elements_dequeued < 250: # With equal probability, run Dequeue or dequeue_many. if random.random() > 0.5: - self.assertEqual(elements_dequeued, dequeued_t.eval()) + self.assertEqual(elements_dequeued, self.evaluate(dequeued_t)) elements_dequeued += 1 else: count = random.randint(0, min(20, 250 - elements_dequeued)) @@ -805,10 +805,10 @@ class PaddingFIFOQueueTest(test.TestCase): # The enqueue_op should run after the dequeue op has blocked. # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t).tolist()) + dequeued_elems.extend(self.evaluate(dequeued_t).tolist()) enqueue_thread = self.checkedThread(target=enqueue) dequeue_thread = self.checkedThread(target=dequeue) @@ -832,10 +832,10 @@ class PaddingFIFOQueueTest(test.TestCase): # The enqueue_op should run after the dequeue op has blocked. # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t).tolist()) + dequeued_elems.extend(self.evaluate(dequeued_t).tolist()) enqueue_thread = self.checkedThread(target=enqueue) dequeue_thread = self.checkedThread(target=dequeue) @@ -882,12 +882,12 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() close_op.run() for elem in elems: - self.assertEqual([elem], dequeued_t.eval()) + self.assertEqual([elem], self.evaluate(dequeued_t)) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - dequeued_t.eval() + self.evaluate(dequeued_t) def testBlockingDequeueFromClosedQueue(self): with self.cached_session() as sess: @@ -901,11 +901,11 @@ class PaddingFIFOQueueTest(test.TestCase): def dequeue(): for elem in elems: - self.assertEqual([elem], sess.run(dequeued_t)) + self.assertEqual([elem], self.evaluate(dequeued_t)) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -926,8 +926,8 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() def dequeue(): - self.assertAllEqual(elems[:3], sess.run(dequeued_t)) - self.assertAllEqual(elems[3:], sess.run(dequeued_t)) + self.assertAllEqual(elems[:3], self.evaluate(dequeued_t)) + self.assertAllEqual(elems[3:], self.evaluate(dequeued_t)) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -947,7 +947,7 @@ class PaddingFIFOQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -968,11 +968,11 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() def dequeue(): - self.assertAllEqual(elems, sess.run(dequeued_t)) + self.assertAllEqual(elems, self.evaluate(dequeued_t)) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -993,11 +993,11 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() def dequeue(): - self.assertAllEqual(elems[:3], sess.run(dequeued_t)) + self.assertAllEqual(elems[:3], self.evaluate(dequeued_t)) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -1017,16 +1017,16 @@ class PaddingFIFOQueueTest(test.TestCase): cleanup_dequeue_t = q.dequeue() def enqueue(): - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): - self.assertAllEqual(elems[0:3], sess.run(dequeued_t)) + self.assertAllEqual(elems[0:3], self.evaluate(dequeued_t)) with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(dequeued_t) - self.assertEqual(elems[3], sess.run(cleanup_dequeue_t)) + self.evaluate(dequeued_t) + self.assertEqual(elems[3], self.evaluate(cleanup_dequeue_t)) def close(): - sess.run(close_op) + self.evaluate(close_op) enqueue_thread = self.checkedThread(target=enqueue) enqueue_thread.start() @@ -1059,7 +1059,7 @@ class PaddingFIFOQueueTest(test.TestCase): def dequeue(): with self.assertRaises(errors_impl.OutOfRangeError): - sess.run([dequeued_a_t, dequeued_b_t]) + self.evaluate([dequeued_a_t, dequeued_b_t]) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -1072,7 +1072,7 @@ class PaddingFIFOQueueTest(test.TestCase): # Test that the elements in the partially-dequeued batch are # restored in the correct order. for elem_a, elem_b in zip(elems_a, elems_b): - val_a, val_b = sess.run([cleanup_dequeue_a_t, cleanup_dequeue_b_t]) + val_a, val_b = self.evaluate([cleanup_dequeue_a_t, cleanup_dequeue_b_t]) self.assertEqual(elem_a, val_a) self.assertEqual(elem_b, val_b) self.assertEqual(0, q.size().eval()) @@ -1087,7 +1087,7 @@ class PaddingFIFOQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -1107,7 +1107,7 @@ class PaddingFIFOQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -1155,7 +1155,7 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() def blocking_enqueue(): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) thread = self.checkedThread(target=blocking_enqueue) thread.start() @@ -1163,8 +1163,8 @@ class PaddingFIFOQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) for elem in elems: - self.assertEqual([elem], dequeued_t.eval()) - self.assertEqual([50.0], dequeued_t.eval()) + self.assertEqual([elem], self.evaluate(dequeued_t)) + self.assertEqual([50.0], self.evaluate(dequeued_t)) thread.join() def testBlockingEnqueueManyToFullQueue(self): @@ -1178,7 +1178,7 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() def blocking_enqueue(): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) thread = self.checkedThread(target=blocking_enqueue) thread.start() @@ -1186,10 +1186,10 @@ class PaddingFIFOQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) for elem in elems: - self.assertEqual([elem], dequeued_t.eval()) + self.assertEqual([elem], self.evaluate(dequeued_t)) time.sleep(0.01) - self.assertEqual([50.0], dequeued_t.eval()) - self.assertEqual([60.0], dequeued_t.eval()) + self.assertEqual([50.0], self.evaluate(dequeued_t)) + self.assertEqual([60.0], self.evaluate(dequeued_t)) # Make sure the thread finishes before exiting. thread.join() @@ -1207,7 +1207,7 @@ class PaddingFIFOQueueTest(test.TestCase): def blocking_enqueue(): # Expect the operation to succeed once the dequeue op runs. - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) enqueue_thread = self.checkedThread(target=blocking_enqueue) enqueue_thread.start() @@ -1217,18 +1217,18 @@ class PaddingFIFOQueueTest(test.TestCase): time.sleep(0.1) def close(): - sess.run(close_op) + self.evaluate(close_op) close_thread = self.checkedThread(target=close) close_thread.start() # The dequeue will unblock both threads. - self.assertEqual(10.0, dequeued_t.eval()) + self.assertEqual(10.0, self.evaluate(dequeued_t)) enqueue_thread.join() close_thread.join() for elem in [20.0, 30.0, 40.0, 50.0]: - self.assertEqual(elem, dequeued_t.eval()) + self.assertEqual(elem, self.evaluate(dequeued_t)) self.assertEqual(0, q.size().eval()) def testBlockingEnqueueManyBeforeClose(self): @@ -1242,7 +1242,7 @@ class PaddingFIFOQueueTest(test.TestCase): enqueue_op.run() def blocking_enqueue(): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) enqueue_thread = self.checkedThread(target=blocking_enqueue) enqueue_thread.start() @@ -1252,17 +1252,17 @@ class PaddingFIFOQueueTest(test.TestCase): time.sleep(0.1) def close(): - sess.run(close_op) + self.evaluate(close_op) close_thread = self.checkedThread(target=close) close_thread.start() # The dequeue will unblock both threads. - self.assertEqual(10.0, dequeued_t.eval()) + self.assertEqual(10.0, self.evaluate(dequeued_t)) enqueue_thread.join() close_thread.join() for elem in [20.0, 30.0, 50.0, 60.0]: - self.assertEqual(elem, dequeued_t.eval()) + self.assertEqual(elem, self.evaluate(dequeued_t)) def testDoesNotLoseValue(self): with self.cached_session(): @@ -1379,19 +1379,19 @@ class PaddingFIFOQueueTest(test.TestCase): def _blockingDequeue(self, sess, dequeue_op): with self.assertRaisesOpError("was cancelled"): - sess.run(dequeue_op) + self.evaluate(dequeue_op) def _blockingDequeueMany(self, sess, dequeue_many_op): with self.assertRaisesOpError("was cancelled"): - sess.run(dequeue_many_op) + self.evaluate(dequeue_many_op) def _blockingEnqueue(self, sess, enqueue_op): with self.assertRaisesOpError("was cancelled"): - sess.run(enqueue_op) + self.evaluate(enqueue_op) def _blockingEnqueueMany(self, sess, enqueue_many_op): with self.assertRaisesOpError("was cancelled"): - sess.run(enqueue_many_op) + self.evaluate(enqueue_many_op) def testResetOfBlockingOperation(self): with self.cached_session() as sess: @@ -1434,7 +1434,7 @@ class PaddingFIFOQueueTest(test.TestCase): def blocking_enqueue(): enq_done.append(False) # This will fill the queue and then block until enough dequeues happen. - sess.run(enq) + self.evaluate(enq) enq_done.append(True) thread = self.checkedThread(target=blocking_enqueue) @@ -1444,14 +1444,14 @@ class PaddingFIFOQueueTest(test.TestCase): results = [] results.append(deq.eval()) # Will only complete after the enqueue starts. self.assertEqual(len(enq_done), 1) - self.assertEqual(sess.run(size_op), 5) + self.assertEqual(self.evaluate(size_op), 5) for _ in range(3): results.append(deq.eval()) time.sleep(0.1) self.assertEqual(len(enq_done), 1) - self.assertEqual(sess.run(size_op), 5) + self.assertEqual(self.evaluate(size_op), 5) # This dequeue will unblock the thread. results.append(deq.eval()) @@ -1477,7 +1477,7 @@ class PaddingFIFOQueueTest(test.TestCase): def blocking_dequeue(): # Will only complete after 4 enqueues complete. - results.extend(sess.run(deq)) + results.extend(self.evaluate(deq)) thread = self.checkedThread(target=blocking_dequeue) thread.start() @@ -1486,7 +1486,7 @@ class PaddingFIFOQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) self.assertEqual(len(results), 0) - sess.run(enq) + self.evaluate(enq) # Enough enqueued to unblock the dequeue thread.join() @@ -1517,7 +1517,7 @@ class PaddingFIFOQueueTest(test.TestCase): q.enqueue_many(input_tuple).run() output_tuple_t = q.dequeue_many(32) - output_tuple = sess.run(output_tuple_t) + output_tuple = self.evaluate(output_tuple_t) for (input_elem, output_elem) in zip(input_tuple, output_tuple): self.assertAllEqual(input_elem, output_elem) diff --git a/tensorflow/python/kernel_tests/parameterized_truncated_normal_op_test.py b/tensorflow/python/kernel_tests/parameterized_truncated_normal_op_test.py index c9221f8c20..f87f517053 100644 --- a/tensorflow/python/kernel_tests/parameterized_truncated_normal_op_test.py +++ b/tensorflow/python/kernel_tests/parameterized_truncated_normal_op_test.py @@ -29,6 +29,7 @@ from tensorflow.core.protobuf import config_pb2 from tensorflow.python.client import session from tensorflow.python.framework import ops from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import random_ops from tensorflow.python.platform import test @@ -166,30 +167,39 @@ class ParameterizedTruncatedNormalTest(test.TestCase): except ImportError as e: tf_logging.warn("Cannot test truncated normal op: %s" % str(e)) + @test_util.run_deprecated_v1 def testDefaults(self): self.validateMoments([10**5], 0.0, 1.0, -2.0, 2.0) + @test_util.run_deprecated_v1 def testShifted(self): self.validateMoments([10**5], -1.0, 1.0, -2.0, 2.0) + @test_util.run_deprecated_v1 def testRightTail(self): self.validateMoments([10**5], 0.0, 1.0, 4.0, np.infty) + @test_util.run_deprecated_v1 def testLeftTail(self): self.validateMoments([10**5], 0.0, 1.0, -np.infty, -4.0) + @test_util.run_deprecated_v1 def testLeftTailTwoSidedBounds(self): self.validateMoments([10**5], 0.0, 1.0, -6.0, -3.0) + @test_util.run_deprecated_v1 def testTwoSidedLeftTailShifted(self): self.validateKolmogorovSmirnov([10**5], 6.0, 1.0, -1.0, 1.0) + @test_util.run_deprecated_v1 def testRightTailShifted(self): self.validateMoments([10**5], -5.0, 1.0, 2.0, np.infty) + @test_util.run_deprecated_v1 def testSmallStddev(self): self.validateKolmogorovSmirnov([10**5], 0.0, 0.1, 0.05, 0.10) + @test_util.run_deprecated_v1 def testSamplingWithSmallStdDevFarFromBound(self): sample_op = random_ops.parameterized_truncated_normal( shape=(int(1e5),), means=0.8, stddevs=0.05, minvals=-1., maxvals=1.) @@ -202,6 +212,7 @@ class ParameterizedTruncatedNormalTest(test.TestCase): no_neg_samples = np.sum(samples < 0.) self.assertEqual(no_neg_samples, 0.) + @test_util.run_deprecated_v1 def testSamplingAtRandnSwitchover(self): # The randn sampler is used as the bounds are moved farther from the mean, # and the probability of accepting a sample increases the farther the diff --git a/tensorflow/python/kernel_tests/parse_single_example_op_test.py b/tensorflow/python/kernel_tests/parse_single_example_op_test.py index a84895a287..43c8fa4ab5 100644 --- a/tensorflow/python/kernel_tests/parse_single_example_op_test.py +++ b/tensorflow/python/kernel_tests/parse_single_example_op_test.py @@ -29,6 +29,7 @@ from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import parsing_ops from tensorflow.python.platform import test from tensorflow.python.platform import tf_logging @@ -107,7 +108,7 @@ class ParseExampleTest(test.TestCase): for result_dict in [out, out_with_example_name]: result = flatten_values_tensors_or_sparse(result_dict.values()) # Check values. - tf_result = sess.run(result) + tf_result = self.evaluate(result) _compare_output_to_expected(self, result_dict, expected_values, tf_result) @@ -121,6 +122,7 @@ class ParseExampleTest(test.TestCase): self.assertEqual( tuple(out[k].dense_shape.get_shape().as_list()), (1,)) + @test_util.run_deprecated_v1 def testEmptySerializedWithAllDefaults(self): sparse_name = "st_a" a_name = "a" @@ -229,6 +231,7 @@ class ParseExampleTest(test.TestCase): }, expected_err=(ValueError, "Missing shape for feature a")) + @test_util.run_deprecated_v1 def testSerializedContainingSparse(self): original = [ example(features=features({ @@ -552,6 +555,7 @@ class ParseExampleTest(test.TestCase): } }, expected_output) + @test_util.run_deprecated_v1 def testSerializedContainingSparseAndSparseFeatureAndDenseWithNoDefault(self): original = [ example(features=features({ @@ -618,6 +622,7 @@ class ParseExampleTest(test.TestCase): }, expected_output) + @test_util.run_deprecated_v1 def testSerializedContainingSparseAndSparseFeatureWithReuse(self): original = [ example(features=features({ @@ -658,6 +663,7 @@ class ParseExampleTest(test.TestCase): } }, expected_output) + @test_util.run_deprecated_v1 def testSerializedContainingVarLenDense(self): aname = "a" bname = "b" @@ -869,6 +875,7 @@ class ParseSingleExampleTest(test.TestCase): self.assertEqual( tuple(out[k].dense_shape.get_shape().as_list()), (1,)) + @test_util.run_deprecated_v1 def testSingleExampleWithSparseAndSparseFeatureAndDense(self): original = example(features=features({ "c": float_feature([3, 4]), diff --git a/tensorflow/python/kernel_tests/parsing_ops_test.py b/tensorflow/python/kernel_tests/parsing_ops_test.py index 71d8b60d3c..af76e09f39 100644 --- a/tensorflow/python/kernel_tests/parsing_ops_test.py +++ b/tensorflow/python/kernel_tests/parsing_ops_test.py @@ -33,6 +33,7 @@ from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import parsing_ops @@ -101,15 +102,15 @@ class ParseExampleTest(test.TestCase): out = parsing_ops.parse_example(**kwargs) result = flatten_values_tensors_or_sparse(out.values()) # Check values. - tf_result = sess.run(result) + tf_result = self.evaluate(result) _compare_output_to_expected(self, out, expected_values, tf_result) # Check shapes; if serialized is a Tensor we need its size to # properly check. serialized = kwargs["serialized"] batch_size = ( - serialized.eval().size if isinstance(serialized, ops.Tensor) else - np.asarray(serialized).size) + self.evaluate(serialized).size if isinstance(serialized, ops.Tensor) + else np.asarray(serialized).size) for k, f in kwargs["features"].items(): if isinstance(f, parsing_ops.FixedLenFeature) and f.shape is not None: self.assertEqual( @@ -121,6 +122,7 @@ class ParseExampleTest(test.TestCase): self.assertEqual( tuple(out[k].dense_shape.get_shape().as_list()), (2,)) + @test_util.run_deprecated_v1 def testEmptySerializedWithAllDefaults(self): sparse_name = "st_a" a_name = "a" @@ -243,6 +245,7 @@ class ParseExampleTest(test.TestCase): }, expected_err=(ValueError, "Missing shape for feature a")) + @test_util.run_deprecated_v1 def testSerializedContainingSparse(self): original = [ example(features=features({ @@ -571,6 +574,7 @@ class ParseExampleTest(test.TestCase): } }, expected_output) + @test_util.run_deprecated_v1 def testSerializedContainingSparseAndSparseFeatureAndDenseWithNoDefault(self): expected_st_a = ( # indices, values, shape np.empty((0, 2), dtype=np.int64), # indices @@ -631,6 +635,7 @@ class ParseExampleTest(test.TestCase): }, expected_output) + @test_util.run_deprecated_v1 def testSerializedContainingSparseAndSparseFeatureWithReuse(self): expected_idx = ( # indices, values, shape np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=np.int64), @@ -740,6 +745,7 @@ class ParseExampleTest(test.TestCase): for batch_size in (1, 10, 20, 100, 256): self._testSerializedContainingVarLenDenseLargerBatch(batch_size) + @test_util.run_deprecated_v1 def testSerializedContainingVarLenDense(self): aname = "a" bname = "b" @@ -962,6 +968,7 @@ class ParseSingleExampleTest(test.TestCase): self.assertEqual( tuple(out[k].dense_shape.get_shape().as_list()), (1,)) + @test_util.run_deprecated_v1 def testSingleExampleWithSparseAndSparseFeatureAndDense(self): original = example( features=features({ @@ -1180,6 +1187,7 @@ class ParseSequenceExampleTest(test.TestCase): expected_err=expected_err, batch=True) + @test_util.run_deprecated_v1 def testSequenceExampleWithSparseAndDenseContext(self): original = sequence_example( context=features({ @@ -1223,6 +1231,7 @@ class ParseSequenceExampleTest(test.TestCase): }, expected_context_values=expected_context_output) + @test_util.run_deprecated_v1 def testSequenceExampleWithMultipleSizeFeatureLists(self): original = sequence_example( feature_lists=feature_lists({ @@ -1286,6 +1295,7 @@ class ParseSequenceExampleTest(test.TestCase): }, expected_feat_list_values=expected_feature_list_output) + @test_util.run_deprecated_v1 def testSequenceExampleWithoutDebugName(self): original = sequence_example( feature_lists=feature_lists({ @@ -1343,6 +1353,7 @@ class ParseSequenceExampleTest(test.TestCase): }, expected_feat_list_values=expected_feature_list_output) + @test_util.run_deprecated_v1 def testSequenceExampleWithSparseAndDenseFeatureLists(self): original = sequence_example( feature_lists=feature_lists({ @@ -1401,6 +1412,7 @@ class ParseSequenceExampleTest(test.TestCase): }, expected_feat_list_values=expected_feature_list_output) + @test_util.run_deprecated_v1 def testSequenceExampleWithEmptyFeatureInFeatureLists(self): original = sequence_example( feature_lists=feature_lists({ @@ -1541,6 +1553,7 @@ class ParseSequenceExampleTest(test.TestCase): " feature_list_dense_missing_assumed_empty or" " feature_list_dense_defaults?")) + @test_util.run_deprecated_v1 def testSequenceExampleBatch(self): first = sequence_example( feature_lists=feature_lists({ @@ -1614,7 +1627,7 @@ class DecodeJSONExampleTest(test.TestCase): shape=examples.shape, dtype=dtypes.string) binary_tensor = parsing_ops.decode_json_example(json_tensor) - binary_val = sess.run(binary_tensor) + binary_val = self.evaluate(binary_tensor) if examples.shape: self.assertShapeEqual(binary_val, json_tensor) @@ -1695,16 +1708,18 @@ class DecodeJSONExampleTest(test.TestCase): })), ]) + @test_util.run_deprecated_v1 def testInvalidSyntax(self): with self.cached_session() as sess: json_tensor = constant_op.constant(["{]"]) binary_tensor = parsing_ops.decode_json_example(json_tensor) with self.assertRaisesOpError("Error while parsing JSON"): - sess.run(binary_tensor) + self.evaluate(binary_tensor) class ParseTensorOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testToFloat32(self): with self.cached_session(): expected = np.random.rand(3, 4, 5).astype(np.float32) @@ -1718,6 +1733,7 @@ class ParseTensorOpTest(test.TestCase): self.assertAllEqual(expected, result) + @test_util.run_deprecated_v1 def testToUint8(self): with self.cached_session(): expected = np.random.rand(3, 4, 5).astype(np.uint8) @@ -1731,6 +1747,7 @@ class ParseTensorOpTest(test.TestCase): self.assertAllEqual(expected, result) + @test_util.run_deprecated_v1 def testTypeMismatch(self): with self.cached_session(): expected = np.random.rand(3, 4, 5).astype(np.uint8) @@ -1744,6 +1761,7 @@ class ParseTensorOpTest(test.TestCase): r"\(uint16\)"): tensor.eval(feed_dict={serialized: tensor_proto.SerializeToString()}) + @test_util.run_deprecated_v1 def testInvalidInput(self): with self.cached_session(): serialized = array_ops.placeholder(dtypes.string) diff --git a/tensorflow/python/kernel_tests/partitioned_variables_test.py b/tensorflow/python/kernel_tests/partitioned_variables_test.py index d1f0c6c2a0..48655391fa 100644 --- a/tensorflow/python/kernel_tests/partitioned_variables_test.py +++ b/tensorflow/python/kernel_tests/partitioned_variables_test.py @@ -26,6 +26,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import init_ops from tensorflow.python.ops import partitioned_variables @@ -322,17 +323,19 @@ class PartitionedVariablesTestCase(test.TestCase): for i in xrange(len(expected_specs)): self.assertEquals(expected_specs[i], slices[i]._save_slice_info.spec) + @test_util.run_deprecated_v1 def testVecConstantInit(self): with self.cached_session(): rnd_par = constant_op.constant([1, 2, 3, 4]) vs = partitioned_variables.create_partitioned_variables([4], [4], rnd_par) variables.global_variables_initializer().run() val = array_ops.concat(vs, 0).eval() - rnd = rnd_par.eval() + rnd = self.evaluate(rnd_par) self.assertAllClose(rnd, val) self.assertEqual([dtypes.int32] * 4, [v.dtype.base_dtype for v in vs]) self._TestSaveSpec(vs, ["4 0,1", "4 1,1", "4 2,1", "4 3,1"]) + @test_util.run_deprecated_v1 def testConstantInit(self): with self.cached_session(): rnd_par = constant_op.constant([[1, 2, 3, 4], [5, 6, 7, 8]]) @@ -340,7 +343,7 @@ class PartitionedVariablesTestCase(test.TestCase): rnd_par) variables.global_variables_initializer().run() val = array_ops.concat(vs, 1).eval() - rnd = rnd_par.eval() + rnd = self.evaluate(rnd_par) self.assertAllClose(rnd, val) self.assertEqual([dtypes.int32] * 2, [v.dtype.base_dtype for v in vs]) self._TestSaveSpec(vs, ["2 4 0,2:0,2", "2 4 0,2:2,2"]) @@ -401,12 +404,15 @@ class PartitionedVariablesTestCase(test.TestCase): self.assertEqual(var2_name + "/part_0:0", vs2[0].name) self.assertEqual(var2_name + "/part_1:0", vs2[1].name) + @test_util.run_deprecated_v1 def testName(self): self._testNameHelper(use_resource=False) + @test_util.run_deprecated_v1 def testResourceName(self): self._testNameHelper(use_resource=True) + @test_util.run_deprecated_v1 def testRandomInitValue(self): with self.cached_session(): rnd = variables.Variable(random_ops.random_uniform([200, 40])) @@ -414,7 +420,7 @@ class PartitionedVariablesTestCase(test.TestCase): rnd.get_shape(), [1, 10], rnd.initialized_value()) variables.global_variables_initializer().run() val = array_ops.concat(vs, 1).eval() - rnd = rnd.eval() + rnd = self.evaluate(rnd) self.assertAllClose(rnd, val) self.assertEqual([dtypes.float32] * 10, [v.dtype.base_dtype for v in vs]) self._TestSaveSpec(vs, [ @@ -424,6 +430,7 @@ class PartitionedVariablesTestCase(test.TestCase): "200 40 0,200:36,4" ]) + @test_util.run_deprecated_v1 def testRandomInitUnevenPartitions(self): with self.cached_session(): rnd = variables.Variable( @@ -434,7 +441,7 @@ class PartitionedVariablesTestCase(test.TestCase): for i in xrange(1, 10) ] variables.global_variables_initializer().run() - rnd_val = rnd.eval() + rnd_val = self.evaluate(rnd) # Only check the slice save specs for the first 5 tf. save_specs = [ # One slice @@ -462,6 +469,7 @@ class PartitionedVariablesTestCase(test.TestCase): if i < len(save_specs): self._TestSaveSpec(vs, save_specs[i]) + @test_util.run_deprecated_v1 def testDegenerate(self): with self.cached_session(): rnd = variables.Variable(random_ops.random_uniform([10, 43])) @@ -469,10 +477,11 @@ class PartitionedVariablesTestCase(test.TestCase): rnd.get_shape(), [1, 1], rnd.initialized_value()) variables.global_variables_initializer().run() val = array_ops.concat(vs, 0).eval() - rnd = rnd.eval() + rnd = self.evaluate(rnd) self.assertAllClose(rnd, val) self._TestSaveSpec(vs, ["10 43 0,10:0,43"]) + @test_util.run_deprecated_v1 def testSliceSizeOne(self): with self.cached_session(): rnd = variables.Variable(random_ops.random_uniform([10, 43])) @@ -480,7 +489,7 @@ class PartitionedVariablesTestCase(test.TestCase): rnd.get_shape(), [10, 1], rnd.initialized_value()) variables.global_variables_initializer().run() val = array_ops.concat(vs, 0).eval() - rnd = rnd.eval() + rnd = self.evaluate(rnd) self.assertAllClose(rnd, val) self._TestSaveSpec(vs, [ "10 43 0,1:0,43", "10 43 1,1:0,43", "10 43 2,1:0,43", @@ -488,6 +497,7 @@ class PartitionedVariablesTestCase(test.TestCase): "10 43 6,1:0,43", "10 43 7,1:0,43", "10 43 8,1:0,43", "10 43 9,1:0,43" ]) + @test_util.run_deprecated_v1 def testIotaInitializer(self): self.assertAllClose([0., 1., 2., 3.], _IotaInitializer([4])) self.assertAllClose([[0., 1.], [0., 10.], [0., 100.], [0., 1000.]], @@ -503,6 +513,7 @@ class PartitionedVariablesTestCase(test.TestCase): self.assertAllClose(slice0 + slice1 + slice2, val) self._TestSaveSpec(vs, ["13 5 0,5:0,5", "13 5 5,4:0,5", "13 5 9,4:0,5"]) + @test_util.run_deprecated_v1 def testRandomInitializer(self): # Sanity check that the slices uses a different seed when using a random # initializer function. @@ -510,7 +521,7 @@ class PartitionedVariablesTestCase(test.TestCase): var0, var1 = partitioned_variables.create_partitioned_variables( [20, 12], [1, 2], init_ops.random_uniform_initializer()) variables.global_variables_initializer().run() - val0, val1 = var0.eval().flatten(), var1.eval().flatten() + val0, val1 = self.evaluate(var0).flatten(), self.evaluate(var1).flatten() self.assertTrue(np.linalg.norm(val0 - val1) > 1e-6) # Negative test that proves that slices have the same values if # the random initializer uses a seed. @@ -518,7 +529,7 @@ class PartitionedVariablesTestCase(test.TestCase): var0, var1 = partitioned_variables.create_partitioned_variables( [20, 12], [1, 2], init_ops.random_uniform_initializer(seed=201)) variables.global_variables_initializer().run() - val0, val1 = var0.eval().flatten(), var1.eval().flatten() + val0, val1 = self.evaluate(var0).flatten(), self.evaluate(var1).flatten() self.assertAllClose(val0, val1) def testSomeErrors(self): @@ -546,6 +557,7 @@ class PartitionedVariablesTestCase(test.TestCase): partitioned_variables.create_partitioned_variables( [10, 43], [1, 50], rnd.initialized_value()) + @test_util.run_deprecated_v1 def testControlDepsNone(self): with self.cached_session() as session: c = constant_op.constant(1.0) @@ -572,6 +584,7 @@ class PartitionedVariablesTestCase(test.TestCase): for op in reading_ops: self.assertEqual([], op.control_inputs) + @test_util.run_deprecated_v1 def testConcat(self): with self.cached_session() as session: var_x = variable_scope.get_variable( diff --git a/tensorflow/python/kernel_tests/pool_test.py b/tensorflow/python/kernel_tests/pool_test.py index 372861297f..78e786f01c 100644 --- a/tensorflow/python/kernel_tests/pool_test.py +++ b/tensorflow/python/kernel_tests/pool_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import nn_ops import tensorflow.python.ops.nn_grad # pylint: disable=unused-import @@ -151,7 +152,7 @@ class PoolingTest(test.TestCase): np.prod(input_shape), dtype=np.float32).reshape(input_shape) - 1 y1 = pool_direct(input=x, **kwargs) y2 = nn_ops.pool(input=x, **kwargs) - self.assertAllClose(y1, y2.eval(), rtol=1e-2, atol=1e-2) + self.assertAllClose(y1, self.evaluate(y2), rtol=1e-2, atol=1e-2) def testPoolSimple(self): with self.session(use_gpu=test.is_gpu_available()): @@ -301,6 +302,7 @@ class PoolingTest(test.TestCase): err_tolerance = 1e-2 self.assertLess(err, err_tolerance) + @test_util.run_deprecated_v1 def testGradient1D(self): with self.session(use_gpu=test.is_gpu_available()): for padding in ["SAME", "VALID"]: @@ -327,6 +329,7 @@ class PoolingTest(test.TestCase): dilation_rate=[1], strides=strides) + @test_util.run_deprecated_v1 def testGradient2D(self): with self.session(use_gpu=test.is_gpu_available()): for padding in ["SAME", "VALID"]: @@ -353,6 +356,7 @@ class PoolingTest(test.TestCase): dilation_rate=[1, 1], strides=strides) + @test_util.run_deprecated_v1 def testGradient3D(self): with self.session(use_gpu=test.is_gpu_available()): for padding in ["SAME", "VALID"]: diff --git a/tensorflow/python/kernel_tests/pooling_ops_3d_test.py b/tensorflow/python/kernel_tests/pooling_ops_3d_test.py index e393c7a022..347e092dee 100644 --- a/tensorflow/python/kernel_tests/pooling_ops_3d_test.py +++ b/tensorflow/python/kernel_tests/pooling_ops_3d_test.py @@ -81,7 +81,7 @@ class PoolingTest(test.TestCase): data_format=data_format) if data_format == "NCDHW": t = test_util.NCHWToNHWC(t) - vals = sess.run(t) + vals = self.evaluate(t) # Verifies values. actual = vals.flatten() self.assertAllClose(expected, actual) @@ -253,6 +253,7 @@ class PoolingTest(test.TestCase): ksize = test_util.NHWCToNCHW(ksize) strides = test_util.NHWCToNCHW(strides) t = test_util.NHWCToNCHW(t) + output_sizes = test_util.NHWCToNCHW(output_sizes) t = pool_func( t, @@ -294,6 +295,7 @@ class PoolingTest(test.TestCase): use_gpu=use_gpu, **kwargs) + @test_util.run_deprecated_v1 def testMaxPoolGradValidPadding1_1_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -303,6 +305,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="VALID") + @test_util.run_deprecated_v1 def testMaxPoolGradValidPadding2_1_6_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -312,6 +315,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="VALID") + @test_util.run_deprecated_v1 def testMaxPoolGradValidPadding2_1_7_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -321,6 +325,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="VALID") + @test_util.run_deprecated_v1 def testMaxPoolGradValidPadding1_2_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -330,6 +335,7 @@ class PoolingTest(test.TestCase): strides=(2, 2, 2), padding="VALID") + @test_util.run_deprecated_v1 def testMaxPoolGradValidPadding2_2_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -339,6 +345,7 @@ class PoolingTest(test.TestCase): strides=(2, 2, 2), padding="VALID") + @test_util.run_deprecated_v1 def testMaxPoolGradSamePadding1_1_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -348,6 +355,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="SAME") + @test_util.run_deprecated_v1 def testMaxPoolGradSamePadding1_2_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -357,6 +365,7 @@ class PoolingTest(test.TestCase): strides=(2, 2, 2), padding="SAME") + @test_util.run_deprecated_v1 def testMaxPoolGradSamePadding2_1_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -366,6 +375,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="SAME") + @test_util.run_deprecated_v1 def testMaxPoolGradSamePadding2_2_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -375,6 +385,7 @@ class PoolingTest(test.TestCase): strides=(2, 2, 2), padding="SAME") + @test_util.run_deprecated_v1 def testMaxPoolGradSamePadding3_1_3d(self): self._ConstructAndTestGradient( nn_ops.max_pool3d, @@ -384,6 +395,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="SAME") + @test_util.run_deprecated_v1 def testAvgPoolGradValidPadding1_1_3d(self): self._ConstructAndTestGradient( nn_ops.avg_pool3d, @@ -393,6 +405,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="VALID") + @test_util.run_deprecated_v1 def testAvgPoolGradValidPadding1_2_3d(self): self._ConstructAndTestGradient( nn_ops.avg_pool3d, @@ -402,6 +415,7 @@ class PoolingTest(test.TestCase): strides=(2, 2, 2), padding="VALID") + @test_util.run_deprecated_v1 def testAvgPoolGradValidPadding2_1_3d(self): self._ConstructAndTestGradient( nn_ops.avg_pool3d, @@ -411,6 +425,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="VALID") + @test_util.run_deprecated_v1 def testAvgPoolGradValidPadding2_2_3d(self): self._ConstructAndTestGradient( nn_ops.avg_pool3d, @@ -420,6 +435,7 @@ class PoolingTest(test.TestCase): strides=(2, 2, 2), padding="VALID") + @test_util.run_deprecated_v1 def testAvgPoolGradSamePadding1_1_3d(self): self._ConstructAndTestGradient( nn_ops.avg_pool3d, @@ -429,6 +445,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="SAME") + @test_util.run_deprecated_v1 def testAvgPoolGradSamePadding1_2_3d(self): self._ConstructAndTestGradient( nn_ops.avg_pool3d, @@ -438,6 +455,7 @@ class PoolingTest(test.TestCase): strides=(2, 2, 2), padding="SAME") + @test_util.run_deprecated_v1 def testAvgPoolGradSamePadding2_1_3d(self): self._ConstructAndTestGradient( nn_ops.avg_pool3d, @@ -447,6 +465,7 @@ class PoolingTest(test.TestCase): strides=(1, 1, 1), padding="SAME") + @test_util.run_deprecated_v1 def testAvgPoolGradSamePadding2_2_3d(self): self._ConstructAndTestGradient( nn_ops.avg_pool3d, @@ -456,6 +475,7 @@ class PoolingTest(test.TestCase): strides=(2, 2, 2), padding="SAME") + @test_util.run_deprecated_v1 def testAvgPoolGradSamePadding3_1_3d(self): self._ConstructAndTestGradient( nn_ops.avg_pool3d, diff --git a/tensorflow/python/kernel_tests/pooling_ops_test.py b/tensorflow/python/kernel_tests/pooling_ops_test.py index 53003a7f28..c33b59bb99 100644 --- a/tensorflow/python/kernel_tests/pooling_ops_test.py +++ b/tensorflow/python/kernel_tests/pooling_ops_test.py @@ -166,7 +166,7 @@ class PoolingTest(test.TestCase): strides_placeholder: strides }) else: - actual = t.eval() + actual = self.evaluate(t) self.assertShapeEqual(actual, t) self.assertAllCloseAccordingToType(expected, actual.flatten()) @@ -384,6 +384,7 @@ class PoolingTest(test.TestCase): expected=[], use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testAvgPooling(self): for use_gpu in True, False: self._testAvgPoolValidPadding(use_gpu) @@ -577,6 +578,7 @@ class PoolingTest(test.TestCase): expected=[], use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testMaxPooling(self): for use_gpu in True, False: self._testMaxPoolValidPadding(use_gpu) @@ -588,6 +590,7 @@ class PoolingTest(test.TestCase): self._testMaxPoolEmptyInput(use_gpu) # Tests for DepthwiseMaxPooling on CPU only. + @test_util.run_deprecated_v1 def testDepthwiseMaxPool1x1DepthWindow1(self): # input is: # [1.0, ..., 10.0] along depth, @@ -613,6 +616,7 @@ class PoolingTest(test.TestCase): use_gpu=False, v2=v2) + @test_util.run_deprecated_v1 def testDepthwiseMaxPool2x2DepthWindow3(self): # input is: # @@ -639,6 +643,7 @@ class PoolingTest(test.TestCase): use_gpu=False, v2=v2) + @test_util.run_deprecated_v1 def testKernelSmallerThanStrideValid(self): for use_gpu in [True, False]: self._VerifyValues( @@ -670,6 +675,7 @@ class PoolingTest(test.TestCase): expected=[5, 8, 26, 29], use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testKernelSmallerThanStrideSame(self): for use_gpu in [True, False]: for pool_func in [nn_ops.max_pool, nn_ops.avg_pool]: @@ -750,11 +756,11 @@ class PoolingTest(test.TestCase): with self.cached_session(use_gpu=True): t = constant_op.constant(tensor_input, shape=input_shape) out_op, _ = nn_ops.max_pool_with_argmax(t, ksize, strides, padding) - gpu_val = out_op.eval() + gpu_val = self.evaluate(out_op) with self.cached_session(use_gpu=False): t = constant_op.constant(tensor_input, shape=input_shape) out_op = nn_ops.max_pool(t, ksize, strides, padding) - cpu_val = out_op.eval() + cpu_val = self.evaluate(out_op) self.assertAllCloseAccordingToType(cpu_val, gpu_val) def _CompareMaxPoolingBk(self, input_shape, output_shape, ksize, strides, @@ -767,20 +773,20 @@ class PoolingTest(test.TestCase): with self.cached_session(use_gpu=True): t = constant_op.constant(tensor_input, shape=input_shape) _, argmax_op = nn_ops.max_pool_with_argmax(t, ksize, strides, padding) - argmax = argmax_op.eval() + argmax = self.evaluate(argmax_op) grad_in = constant_op.constant(tensor_output, shape=output_shape) out_op = gen_nn_ops.max_pool_grad_with_argmax(t, grad_in, argmax, ksize, strides, padding) - gpu_val = out_op.eval() + gpu_val = self.evaluate(out_op) self.assertShapeEqual(gpu_val, out_op) with self.cached_session(use_gpu=False): t = constant_op.constant(tensor_input, shape=input_shape) out_op = nn_ops.max_pool(t, ksize, strides, padding) - orig_out = out_op.eval() + orig_out = self.evaluate(out_op) grad_in = constant_op.constant(tensor_output, shape=output_shape) out_op = gen_nn_ops.max_pool_grad(t, orig_out, grad_in, ksize, strides, padding) - cpu_val = out_op.eval() + cpu_val = self.evaluate(out_op) self.assertShapeEqual(cpu_val, out_op) # The CPU version accumulates its gradient on fp16, so it's less # accurate than the GPU version that does the accumulation on fp32 @@ -796,20 +802,20 @@ class PoolingTest(test.TestCase): with self.cached_session(use_gpu=True): t = constant_op.constant(tensor_input, shape=input_shape) _, argmax_op = nn_ops.max_pool_with_argmax(t, ksize, strides, padding) - argmax = argmax_op.eval() + argmax = self.evaluate(argmax_op) grad_in = constant_op.constant(tensor_input, shape=input_shape) out_op = gen_nn_ops.max_pool_grad_grad_with_argmax( t, grad_in, argmax, ksize, strides, padding) - gpu_val = out_op.eval() + gpu_val = self.evaluate(out_op) self.assertShapeEqual(gpu_val, out_op) with self.cached_session(use_gpu=False): t = constant_op.constant(tensor_input, shape=input_shape) out_op = nn_ops.max_pool(t, ksize, strides, padding) - orig_out = out_op.eval() + orig_out = self.evaluate(out_op) grad_in = constant_op.constant(tensor_input, shape=input_shape) out_op = gen_nn_ops.max_pool_grad_grad(t, orig_out, grad_in, ksize, strides, padding) - cpu_val = out_op.eval() + cpu_val = self.evaluate(out_op) self.assertShapeEqual(cpu_val, out_op) # The CPU version accumulates its gradient on fp16, so it's less # accurate than the GPU version that does the accumulation on fp32 @@ -826,7 +832,7 @@ class PoolingTest(test.TestCase): strides=[1, 1, 1, 1], Targmax=dtypes.int64, padding="VALID") - out, argmax = sess.run([out_op, argmax_op]) + out, argmax = self.evaluate([out_op, argmax_op]) self.assertShapeEqual(out, out_op) self.assertShapeEqual(argmax, argmax_op) self.assertAllClose(out.ravel(), [1.0, 1.0, 1.0, 1.0]) @@ -848,7 +854,7 @@ class PoolingTest(test.TestCase): ksize=[1, 2, 2, 1], strides=[1, 1, 1, 1], padding="VALID") - out = out_op.eval().flatten() + out = self.evaluate(out_op).flatten() self.assertAllClose(out, [11.0, 12.0, 0.0, 13.0, 0.0, 14.0, 0.0, 0.0, 0.0]) @@ -871,7 +877,7 @@ class PoolingTest(test.TestCase): ksize=[1, 2, 2, 1], strides=[1, 1, 1, 1], padding="VALID") - out = out_op.eval().flatten() + out = self.evaluate(out_op).flatten() self.assertAllClose(out, [11.0, 12.0, 14.0, 16.0]) def _ConstructAndTestGradient(self, @@ -1167,6 +1173,7 @@ class PoolingTest(test.TestCase): data_format=data_format, use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testMaxPoolGrad(self): for (data_format, use_gpu) in GetTestConfigs(): self._testMaxPoolGradValidPadding1_1(data_format, use_gpu) @@ -1221,12 +1228,12 @@ class PoolingTest(test.TestCase): input_tensor, output_tensor, output_backprop_tensor, window_rows, window_cols, row_stride, col_stride, padding, v2) - actual_input_backprop = input_backprop_tensor.eval() + actual_input_backprop = self.evaluate(input_backprop_tensor) self.assertShapeEqual(actual_input_backprop, input_backprop_tensor) actual_input_backprop = actual_input_backprop.flatten() actual_input_backprop = self._GetNdArray(actual_input_backprop) - actual_output = output_tensor.eval().flatten() + actual_output = self.evaluate(output_tensor).flatten() actual_output = self._GetNdArray(actual_output) self.assertAllClose( @@ -1497,6 +1504,7 @@ class PoolingTest(test.TestCase): else: del os.environ["TF_ENABLE_MAXPOOL_NANPROP"] + @test_util.run_deprecated_v1 def testMaxPoolGradDirect(self): self._testMaxPoolGradDirect1_1() self._testMaxPoolGradDirect1_2() @@ -1616,6 +1624,7 @@ class PoolingTest(test.TestCase): data_format=data_format, use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testMaxPoolGradGrad(self): for (data_format, use_gpu) in GetTestConfigs(): self._testMaxPoolGradGradValidPadding1_1(data_format, use_gpu) @@ -1649,6 +1658,7 @@ class PoolingTest(test.TestCase): orig_input, orig_output, grad, [1, window_rows, window_cols, 1], [1, row_stride, col_stride, 1], padding) + @test_util.run_deprecated_v1 def testAvgPoolGrad(self): for (data_format, use_gpu) in GetTestConfigs(): self._testAvgPoolGradValidPadding1_1(data_format, use_gpu) @@ -1778,6 +1788,7 @@ class PoolingTest(test.TestCase): data_format=data_format, use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testShapeFunctionEdgeCases(self): # All shapes unknown. for pool_func in [nn_ops.max_pool, nn_ops.avg_pool]: @@ -1806,6 +1817,7 @@ class PoolingTest(test.TestCase): strides=[1, 1, 1, 1], padding="SAME") + @test_util.run_deprecated_v1 def testOpEdgeCases(self): with self.session(use_gpu=test.is_gpu_available()) as sess: pool_funcs = [nn_ops.max_pool, nn_ops.avg_pool] diff --git a/tensorflow/python/kernel_tests/priority_queue_test.py b/tensorflow/python/kernel_tests/priority_queue_test.py index 73a9c81638..9be682ea52 100644 --- a/tensorflow/python/kernel_tests/priority_queue_test.py +++ b/tensorflow/python/kernel_tests/priority_queue_test.py @@ -50,7 +50,7 @@ class PriorityQueueTest(test.TestCase): enq.run() deq = q.dequeue_many(100) - deq_elem, deq_value_0, deq_value_1 = sess.run(deq) + deq_elem, deq_value_0, deq_value_1 = self.evaluate(deq) allowed = {} missed = set() @@ -81,7 +81,7 @@ class PriorityQueueTest(test.TestCase): # Run one producer thread for each element in elems. def enqueue(enqueue_op): - sess.run(enqueue_op) + self.evaluate(enqueue_op) dequeue_op = q.dequeue_many(100) @@ -93,7 +93,7 @@ class PriorityQueueTest(test.TestCase): for t in enqueue_threads: t.start() - deq_elem, deq_value_0, deq_value_1 = sess.run(dequeue_op) + deq_elem, deq_value_0, deq_value_1 = self.evaluate(dequeue_op) for t in enqueue_threads: t.join() @@ -132,12 +132,12 @@ class PriorityQueueTest(test.TestCase): # Run one producer thread for each element in elems. def enqueue(enqueue_op): - sess.run(enqueue_op) + self.evaluate(enqueue_op) dequeued = [] def dequeue(dequeue_op): - (dequeue_indices, dequeue_values) = sess.run(dequeue_op) + (dequeue_indices, dequeue_values) = self.evaluate(dequeue_op) self.assertAllEqual(dequeue_indices, dequeue_values) dequeued.extend(dequeue_indices) @@ -184,10 +184,10 @@ class PriorityQueueTest(test.TestCase): # Run one producer thread for each element in elems. def enqueue(enqueue_op): - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(dequeue_op, dequeued): - (dequeue_indices, dequeue_values) = sess.run(dequeue_op) + (dequeue_indices, dequeue_values) = self.evaluate(dequeue_op) self.assertAllEqual(dequeue_indices, dequeue_values) dequeue_wait.acquire() dequeued.extend(dequeue_indices) @@ -215,7 +215,7 @@ class PriorityQueueTest(test.TestCase): # We can't guarantee full sorting because we can't guarantee # that the dequeued.extend() call runs immediately after the - # sess.run() call. Here we're just happy everything came out. + # self.evaluate() call. Here we're just happy everything came out. self.assertAllEqual(set(dequeued), set(all_enqueued_values)) def testRoundTripInsertManyMultiThreadedReadOnceSorts(self): @@ -236,7 +236,7 @@ class PriorityQueueTest(test.TestCase): # Run one producer thread for each element in elems. def enqueue(enqueue_op): - sess.run(enqueue_op) + self.evaluate(enqueue_op) dequeue_op = q.dequeue_many(100) @@ -248,7 +248,7 @@ class PriorityQueueTest(test.TestCase): for t in enqueue_threads: t.start() - deq_elem, deq_value_0, deq_value_1 = sess.run(dequeue_op) + deq_elem, deq_value_0, deq_value_1 = self.evaluate(dequeue_op) for t in enqueue_threads: t.join() @@ -276,7 +276,7 @@ class PriorityQueueTest(test.TestCase): side_value_1 = np.random.rand(1000).astype(bytes) q.enqueue_many((elem, side_value_0, side_value_1)).run() deq = q.dequeue_many(1000) - deq_elem, deq_value_0, deq_value_1 = sess.run(deq) + deq_elem, deq_value_0, deq_value_1 = self.evaluate(deq) allowed = {} for e, v0, v1 in zip(elem, side_value_0, side_value_1): diff --git a/tensorflow/python/kernel_tests/py_func_test.py b/tensorflow/python/kernel_tests/py_func_test.py index 837f1ec054..1f3f02a9f0 100644 --- a/tensorflow/python/kernel_tests/py_func_test.py +++ b/tensorflow/python/kernel_tests/py_func_test.py @@ -272,7 +272,7 @@ class PyFuncTest(test.TestCase): with self.assertRaisesRegexp(errors.UnimplementedError, "Unsupported numpy type"): - y.eval() + self.evaluate(y) def testBadReturnType(self): with self.cached_session(): @@ -285,7 +285,7 @@ class PyFuncTest(test.TestCase): with self.assertRaisesRegexp(errors.UnimplementedError, "Unsupported object type"): - z.eval() + self.evaluate(z) def testReturnInput(self): with self.cached_session(): @@ -307,9 +307,9 @@ class PyFuncTest(test.TestCase): with session_lib.Session() as sess: producer = iter(range(3)) x, = script_ops.py_func(lambda: next(producer), [], [dtypes.int64]) - self.assertEqual(sess.run(x), 0) - self.assertEqual(sess.run(x), 1) - self.assertEqual(sess.run(x), 2) + self.assertEqual(self.evaluate(x), 0) + self.assertEqual(self.evaluate(x), 1) + self.assertEqual(self.evaluate(x), 2) def testStateless(self): # Not using self.cached_session(), which disables optimization. @@ -317,9 +317,9 @@ class PyFuncTest(test.TestCase): producer = iter(range(3)) x, = script_ops.py_func( lambda: next(producer), [], [dtypes.int64], stateful=False) - self.assertEqual(sess.run(x), 0) - self.assertEqual(sess.run(x), 0) - self.assertEqual(sess.run(x), 0) + self.assertEqual(self.evaluate(x), 0) + self.assertEqual(self.evaluate(x), 0) + self.assertEqual(self.evaluate(x), 0) def testGradientFunction(self): # Input to tf.py_func is necessary, otherwise get_gradient_function() @@ -335,7 +335,7 @@ class PyFuncTest(test.TestCase): val = [[1, 2], [3, 4]] x, = script_ops.py_func(lambda: np.array(val, order="F"), [], [dtypes.int64]) - self.assertAllEqual(val, x.eval()) + self.assertAllEqual(val, self.evaluate(x)) def testParallel(self): # Tests that tf.py_func's can run in parallel if they release the GIL. @@ -390,7 +390,7 @@ class PyFuncTest(test.TestCase): f = script_ops.py_func( do_nothing, [constant_op.constant(3, dtypes.int64)], [], stateful=False) with self.cached_session() as sess: - self.assertEqual(sess.run(f), []) + self.assertEqual(self.evaluate(f), []) def _testExceptionHandling(self, py_exp, tf_exp, eager=False): @@ -514,6 +514,7 @@ class PyFuncTest(test.TestCase): self.assertAllEqual(ret, [[3.0], [3.0], [3.0]]) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testEagerExceptionHandling(self): with test_util.device(use_gpu=True): self._testExceptionHandling( @@ -533,6 +534,7 @@ class PyFuncTest(test.TestCase): self._testExceptionHandling(WeirdError, errors.UnknownError, eager=True) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testEagerReturningVariableRaisesError(self): def return_variable(): return resource_variable_ops.ResourceVariable(0.0) diff --git a/tensorflow/python/kernel_tests/qr_op_test.py b/tensorflow/python/kernel_tests/qr_op_test.py index a60237fb25..0f2537b371 100644 --- a/tensorflow/python/kernel_tests/qr_op_test.py +++ b/tensorflow/python/kernel_tests/qr_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import linalg_ops @@ -49,6 +50,7 @@ class QrOpTest(test.TestCase): "Shape must be at least rank 2 but is rank 1"): linalg_ops.qr(vector) + @test_util.run_deprecated_v1 def testConcurrentExecutesWithoutError(self): with self.session(use_gpu=True) as sess: all_ops = [] @@ -60,7 +62,7 @@ class QrOpTest(test.TestCase): q1, r1 = linalg_ops.qr(matrix1, full_matrices=full_matrices_) q2, r2 = linalg_ops.qr(matrix2, full_matrices=full_matrices_) all_ops += [q1, r1, q2, r2] - val = sess.run(all_ops) + val = self.evaluate(all_ops) for i in range(8): q = 4 * i self.assertAllEqual(val[q], val[q + 2]) # q1 == q2 @@ -110,7 +112,7 @@ def _GetQrOpTest(dtype_, shape_, full_matrices_, use_static_shape_): tol = 1e-5 else: tol = 1e-14 - self.assertAllClose(identity.eval(), xx.eval(), atol=tol) + self.assertAllClose(identity.eval(), self.evaluate(xx), atol=tol) def Test(self): np.random.seed(1) @@ -129,7 +131,7 @@ def _GetQrOpTest(dtype_, shape_, full_matrices_, use_static_shape_): q_tf, r_tf = linalg_ops.qr(x_tf, full_matrices=full_matrices_) if use_static_shape_: - q_tf_val, r_tf_val = sess.run([q_tf, r_tf]) + q_tf_val, r_tf_val = self.evaluate([q_tf, r_tf]) else: q_tf_val, r_tf_val = sess.run([q_tf, r_tf], feed_dict={x_tf: x_np}) diff --git a/tensorflow/python/kernel_tests/random/multinomial_op_big_test.py b/tensorflow/python/kernel_tests/random/multinomial_op_big_test.py index 0023506b77..576720528e 100644 --- a/tensorflow/python/kernel_tests/random/multinomial_op_big_test.py +++ b/tensorflow/python/kernel_tests/random/multinomial_op_big_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util from tensorflow.python.ops import random_ops from tensorflow.python.platform import test @@ -39,7 +40,7 @@ class MultinomialTest(test.TestCase): num_samples=1000000, seed=15) for _ in range(100): - x = sess.run(samples) + x = self.evaluate(samples) indices, counts = np.unique(x, return_counts=True) for index, count in zip(indices, counts): if index in counts_by_indices.keys(): @@ -57,7 +58,7 @@ class MultinomialTest(test.TestCase): num_samples=1000000, seed=15) for _ in range(100): - x = sess.run(samples) + x = self.evaluate(samples) indices, counts = np.unique(x, return_counts=True) for index, count in zip(indices, counts): if index in counts_by_indices.keys(): @@ -66,6 +67,7 @@ class MultinomialTest(test.TestCase): counts_by_indices[index] = count self.assertEqual(counts_by_indices[0], 100000000) + @test_util.run_deprecated_v1 def testLargeDynamicRange3(self): random_seed.set_random_seed(10) counts_by_indices = {} @@ -79,7 +81,7 @@ class MultinomialTest(test.TestCase): # we'll run out of memory if we try to draw 1e9 samples directly # really should fit in 12GB of memory... for _ in range(100): - x = sess.run(samples) + x = self.evaluate(samples) indices, counts = np.unique(x, return_counts=True) for index, count in zip(indices, counts): if index in counts_by_indices.keys(): diff --git a/tensorflow/python/kernel_tests/random/multinomial_op_test.py b/tensorflow/python/kernel_tests/random/multinomial_op_test.py index bd64d61af8..5d123307a8 100644 --- a/tensorflow/python/kernel_tests/random/multinomial_op_test.py +++ b/tensorflow/python/kernel_tests/random/multinomial_op_test.py @@ -66,12 +66,13 @@ class MultinomialTest(test.TestCase): logits, num_samples, output_dtype=output_dtype)) self.assertAllEqual([[1] * num_samples, [2] * num_samples], samples) + @test_util.run_deprecated_v1 def testOneOpMultipleStepsIndependent(self): - with self.test_session(use_gpu=True) as sess: + with test_util.use_gpu(): sample_op1, _ = self._make_ops(10) # Consecutive runs shouldn't yield identical output. - sample1a = sess.run(sample_op1) - sample1b = sess.run(sample_op1) + sample1a = self.evaluate(sample_op1) + sample1b = self.evaluate(sample_op1) self.assertFalse(np.equal(sample1a, sample1b).all()) def testEagerOneOpMultipleStepsIndependent(self): @@ -81,26 +82,27 @@ class MultinomialTest(test.TestCase): self.assertFalse(np.equal(sample1.numpy(), sample2.numpy()).all()) def testTwoOpsIndependent(self): - with self.test_session(use_gpu=True) as sess: + with test_util.use_gpu(): sample_op1, sample_op2 = self._make_ops(32) - sample1, sample2 = sess.run([sample_op1, sample_op2]) + sample1, sample2 = self.evaluate([sample_op1, sample_op2]) # We expect sample1 and sample2 to be independent. # 1 in 2^32 chance of this assertion failing. self.assertFalse(np.equal(sample1, sample2).all()) + @test_util.run_deprecated_v1 def testTwoOpsSameSeedDrawSameSequences(self): - with self.test_session(use_gpu=True) as sess: + with test_util.use_gpu(): sample_op1, sample_op2 = self._make_ops(1000, seed=1) - sample1, sample2 = sess.run([sample_op1, sample_op2]) + sample1, sample2 = self.evaluate([sample_op1, sample_op2]) self.assertAllEqual(sample1, sample2) def testLargeLogits(self): for neg in [True, False]: - with self.test_session(use_gpu=True): + with test_util.use_gpu(): logits = np.array([[1000.] * 5]) if neg: logits *= -1 - samples = random_ops.multinomial(logits, 10).eval() + samples = self.evaluate(random_ops.multinomial(logits, 10)) # Sampled classes should be in-range. self.assertTrue((samples >= 0).all()) self.assertTrue((samples < 5).all()) @@ -157,10 +159,10 @@ class MultinomialTest(test.TestCase): Returns: Frequencies from sampled classes; shape [batch_size, num_classes]. """ - with self.test_session(use_gpu=True) as sess: + with test_util.use_gpu(): random_seed.set_random_seed(1618) op = sampler(constant_op.constant(logits), num_samples) - d = sess.run(op) + d = self.evaluate(op) batch_size, num_classes = logits.shape freqs_mat = [] @@ -186,25 +188,27 @@ class MultinomialTest(test.TestCase): def testEmpty(self): classes = 5 - with self.test_session(use_gpu=True): + with test_util.use_gpu(): for batch in 0, 3: for samples in 0, 7: - x = random_ops.multinomial( - array_ops.zeros([batch, classes]), samples).eval() + x = self.evaluate( + random_ops.multinomial( + array_ops.zeros([batch, classes]), samples)) self.assertEqual(x.shape, (batch, samples)) + @test_util.run_deprecated_v1 def testEmptyClasses(self): - with self.test_session(use_gpu=True): + with test_util.use_gpu(): x = random_ops.multinomial(array_ops.zeros([5, 0]), 7) with self.assertRaisesOpError("num_classes should be positive"): - x.eval() + self.evaluate(x) def testNegativeMinLogits(self): random_seed.set_random_seed(78844) - with self.test_session(use_gpu=True): + with test_util.use_gpu(): logits = constant_op.constant([[np.finfo(np.float32).min] * 1023 + [0]]) num_samples = 1000 - samples = random_ops.multinomial(logits, num_samples).eval() + samples = self.evaluate(random_ops.multinomial(logits, num_samples)) self.assertAllEqual([[1023] * num_samples], samples) diff --git a/tensorflow/python/kernel_tests/random/random_crop_test.py b/tensorflow/python/kernel_tests/random/random_crop_test.py index 8ded522320..724bee0715 100644 --- a/tensorflow/python/kernel_tests/random/random_crop_test.py +++ b/tensorflow/python/kernel_tests/random/random_crop_test.py @@ -20,12 +20,14 @@ from __future__ import print_function import numpy as np +from tensorflow.python.framework import test_util from tensorflow.python.ops import random_ops from tensorflow.python.platform import test class RandomCropTest(test.TestCase): + @test_util.run_deprecated_v1 def testNoOp(self): # No random cropping is performed since the size is value.shape. for shape in (2, 1, 1), (2, 1, 3), (4, 5, 3): @@ -44,10 +46,11 @@ class RandomCropTest(test.TestCase): for i in range(2) for j in range(3) for k in range(4)) crop = random_ops.random_crop(value, size=target) for _ in range(20): - y = crop.eval() + y = self.evaluate(crop) self.assertAllEqual(y.shape, target) self.assertTrue(tuple(y.ravel()) in value_set) + @test_util.run_deprecated_v1 def testRandomization(self): # Run 1x1 crop num_samples times in an image and ensure that one finds each # pixel 1/size of the time. @@ -61,7 +64,7 @@ class RandomCropTest(test.TestCase): crop = random_ops.random_crop(value, single, seed=7) counts = np.zeros(size, dtype=np.int32) for _ in range(num_samples): - y = crop.eval() + y = self.evaluate(crop) self.assertAllEqual(y.shape, single) counts[y] += 1 diff --git a/tensorflow/python/kernel_tests/random/random_gamma_test.py b/tensorflow/python/kernel_tests/random/random_gamma_test.py index 606e8862c4..a5952a2196 100644 --- a/tensorflow/python/kernel_tests/random/random_gamma_test.py +++ b/tensorflow/python/kernel_tests/random/random_gamma_test.py @@ -26,6 +26,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops @@ -48,14 +49,16 @@ class RandomGammaTest(test.TestCase): [num], alpha, beta=beta, dtype=dtype, seed=seed) ret = np.empty([10, num]) for i in xrange(10): - ret[i, :] = sess.run(rng) + ret[i, :] = self.evaluate(rng) return ret return func + @test_util.run_deprecated_v1 def testMomentsFloat32(self): self._testMoments(dtypes.float32) + @test_util.run_deprecated_v1 def testMomentsFloat64(self): self._testMoments(dtypes.float64) @@ -208,6 +211,7 @@ class RandomGammaTest(test.TestCase): sy = self._Sampler(1000, 0.0, 1.0, dt, use_gpu=use_gpu, seed=345) self.assertAllEqual(sx(), sy()) + @test_util.run_deprecated_v1 def testNoCSE(self): """CSE = constant subexpression eliminator. @@ -222,6 +226,7 @@ class RandomGammaTest(test.TestCase): diff = rnd2 - rnd1 self.assertGreater(np.linalg.norm(diff.eval()), 0.1) + @test_util.run_deprecated_v1 def testShape(self): # Fully known shape. rnd = random_ops.random_gamma([150], 2.0) @@ -253,6 +258,7 @@ class RandomGammaTest(test.TestCase): rnd = random_ops.random_gamma([50], array_ops.placeholder(dtypes.float32)) self.assertIs(None, rnd.get_shape().ndims) + @test_util.run_deprecated_v1 def testPositive(self): n = int(10e3) for dt in [dtypes.float16, dtypes.float32, dtypes.float64]: diff --git a/tensorflow/python/kernel_tests/random/random_grad_test.py b/tensorflow/python/kernel_tests/random/random_grad_test.py index d89056c485..aac6eeac06 100644 --- a/tensorflow/python/kernel_tests/random/random_grad_test.py +++ b/tensorflow/python/kernel_tests/random/random_grad_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import math_ops @@ -45,6 +46,7 @@ class AddLeadingUnitDimensionsTest(test.TestCase): ret = random_grad.add_leading_unit_dimensions(1.0, 2) self.assertAllEqual(ret.shape, [1, 1]) + @test_util.run_deprecated_v1 def testUnknownShape(self): x = array_ops.placeholder(dtypes.float32) num_dimensions = array_ops.placeholder(dtypes.int32) @@ -72,6 +74,7 @@ class RandomGammaGradTest(test.TestCase): some statistical properties of the derivative. """ + @test_util.run_deprecated_v1 def testGradientsShape(self): shape = [2, 3] alpha = array_ops.ones([2, 2]) @@ -81,6 +84,7 @@ class RandomGammaGradTest(test.TestCase): self.assertAllEqual(grads_alpha.shape, alpha.shape) self.assertAllEqual(grads_beta.shape, beta.shape) + @test_util.run_deprecated_v1 def testGradientsShapeWithOneSamplePerParameter(self): shape = [] alpha = array_ops.ones([2, 2]) @@ -90,6 +94,7 @@ class RandomGammaGradTest(test.TestCase): self.assertAllEqual(grads_alpha.shape, alpha.shape) self.assertAllEqual(grads_beta.shape, beta.shape) + @test_util.run_deprecated_v1 def testGradientsUnknownShape(self): shape = array_ops.placeholder(dtypes.int32) alpha = array_ops.placeholder(dtypes.float32) @@ -138,9 +143,11 @@ class RandomGammaGradTest(test.TestCase): except ImportError as e: tf_logging.warn("Cannot use special functions in a test: %s" % str(e)) + @test_util.run_deprecated_v1 def testCompareToExplicitDerivativeFloat(self): self._testCompareToExplicitDerivative(dtypes.float32) + @test_util.run_deprecated_v1 def testCompareToExplicitDerivativeDouble(self): self._testCompareToExplicitDerivative(dtypes.float64) @@ -182,12 +189,15 @@ class RandomGammaGradTest(test.TestCase): self.assertAllClose(actual_val, expected_val, rtol=1e-3, atol=1e-3) + @test_util.run_deprecated_v1 def testCompareToImplicitDerivativeFloat(self): self._testCompareToImplicitDerivative(dtypes.float32) + @test_util.run_deprecated_v1 def testCompareToImplicitDerivativeDouble(self): self._testCompareToImplicitDerivative(dtypes.float64) + @test_util.run_deprecated_v1 def testAverageAlphaGradient(self): """Statistical test for the gradient. @@ -207,6 +217,7 @@ class RandomGammaGradTest(test.TestCase): dsample_dalpha_val = self.evaluate(dsample_dalpha) self.assertAllClose(dsample_dalpha_val, [1.0] * 3, atol=1e-1, rtol=1e-1) + @test_util.run_deprecated_v1 def testQuadraticLoss(self): """Statistical test for the gradient. diff --git a/tensorflow/python/kernel_tests/random/random_ops_test.py b/tensorflow/python/kernel_tests/random/random_ops_test.py index 6de894846b..1384c3f446 100644 --- a/tensorflow/python/kernel_tests/random/random_ops_test.py +++ b/tensorflow/python/kernel_tests/random/random_ops_test.py @@ -25,6 +25,7 @@ from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import variables @@ -49,9 +50,9 @@ class RandomOpTestCommon(test.TestCase): random_seed.set_random_seed(graph_seed) x = rng_func([num], min_or_mean, max_or_stddev, dtype=dtype, seed=op_seed) - y = sess.run(x) - z = sess.run(x) - w = sess.run(x) + y = self.evaluate(x) + z = self.evaluate(x) + w = self.evaluate(x) # We use exact equality here. If the random-number generator is producing # the same output, all three outputs will be bitwise identical. @@ -69,7 +70,7 @@ class RandomNormalTest(RandomOpTestCommon): [num], mean=mu, stddev=sigma, dtype=dtype, seed=seed) ret = np.empty([10, num]) for i in xrange(10): - ret[i, :] = sess.run(rng) + ret[i, :] = self.evaluate(rng) return ret return func @@ -92,6 +93,7 @@ class RandomNormalTest(RandomOpTestCommon): # Checks that the CPU and GPU implementation returns the same results, # given the same random seed + @test_util.run_deprecated_v1 def testCPUGPUMatch(self): for dt in dtypes.float16, dtypes.float32, dtypes.float64: results = {} @@ -104,12 +106,14 @@ class RandomNormalTest(RandomOpTestCommon): else: self.assertAllClose(results[False], results[True], rtol=1e-6, atol=1e-6) + @test_util.run_deprecated_v1 def testSeed(self): for dt in dtypes.float16, dtypes.float32, dtypes.float64: sx = self._Sampler(1000, 0.0, 1.0, dt, use_gpu=True, seed=345) sy = self._Sampler(1000, 0.0, 1.0, dt, use_gpu=True, seed=345) self.assertAllEqual(sx(), sy()) + @test_util.run_deprecated_v1 def testNoCSE(self): for use_gpu in [False, True]: with self.session(use_gpu=use_gpu): @@ -119,12 +123,14 @@ class RandomNormalTest(RandomOpTestCommon): diff = rnd2 - rnd1 self.assertTrue(np.linalg.norm(diff.eval()) > 0.1) + @test_util.run_deprecated_v1 def testSingleSessionNotConstant(self): for use_gpu in [False, True]: for dt in dtypes.float16, dtypes.float32, dtypes.float64: self._testSingleSessionNotConstant( random_ops.random_normal, 100, dt, 0.0, 1.0, use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testSingleSessionOpSeedNotConstant(self): for use_gpu in [False, True]: for dt in dtypes.float16, dtypes.float32, dtypes.float64: @@ -137,6 +143,7 @@ class RandomNormalTest(RandomOpTestCommon): use_gpu=use_gpu, op_seed=1345) + @test_util.run_deprecated_v1 def testSingleSessionGraphSeedNotConstant(self): for use_gpu in [False, True]: for dt in dtypes.float16, dtypes.float32, dtypes.float64: @@ -160,7 +167,7 @@ class TruncatedNormalTest(test.TestCase): [num], mean=mu, stddev=sigma, dtype=dtype, seed=seed) ret = np.empty([10, num]) for i in xrange(10): - ret[i, :] = sess.run(rng) + ret[i, :] = self.evaluate(rng) return ret return func @@ -185,6 +192,7 @@ class TruncatedNormalTest(test.TestCase): # Checks that the CPU and GPU implementation returns the same results, # given the same random seed + @test_util.run_deprecated_v1 def testCPUGPUMatch(self): # Skip the test if there is no GPU. if not test.is_gpu_available(): @@ -203,6 +211,7 @@ class TruncatedNormalTest(test.TestCase): else: self.assertAllClose(results[False], results[True], rtol=1e-6, atol=1e-6) + @test_util.run_deprecated_v1 def testSeed(self): for dt in dtypes.float16, dtypes.float32, dtypes.float64: sx = self._Sampler(1000, 0.0, 1.0, dt, use_gpu=True, seed=345) @@ -219,6 +228,7 @@ class TruncatedNormalTest(test.TestCase): print("std(x)", np.std(x), abs(np.std(x) / stddev - 0.85)) self.assertTrue(abs(np.std(x) / stddev - 0.85) < 0.04) + @test_util.run_deprecated_v1 def testLargeShape(self): with self.session(use_gpu=True): v = variables.Variable( @@ -226,6 +236,7 @@ class TruncatedNormalTest(test.TestCase): n = random_ops.truncated_normal(v.shape) self.assertEqual([8589934592, 1], n.shape.as_list()) + @test_util.run_deprecated_v1 def testNoCSE(self): with self.session(use_gpu=True): shape = [2, 3, 4] @@ -256,7 +267,7 @@ class RandomUniformTest(RandomOpTestCommon): [num], minval=minv, maxval=maxv, dtype=dtype, seed=seed) ret = np.empty([10, num]) for i in xrange(10): - ret[i, :] = sess.run(rng) + ret[i, :] = self.evaluate(rng) return ret return func @@ -287,6 +298,7 @@ class RandomUniformTest(RandomOpTestCommon): print("count = ", count) self.assertTrue(count < count_limit) + @test_util.run_deprecated_v1 def testUniformIntsWithInvalidShape(self): for dtype in dtypes.int32, dtypes.int64: with self.assertRaisesRegexp( @@ -299,6 +311,7 @@ class RandomUniformTest(RandomOpTestCommon): [1000], minval=1, maxval=[2, 3], dtype=dtype) # Check that uniform ints actually follow a uniform distribution. + @test_util.run_deprecated_v1 def testUniformInts(self): minv = -2 maxv = 15 @@ -331,6 +344,7 @@ class RandomUniformTest(RandomOpTestCommon): # Checks that the CPU and GPU implementation returns the same results, # given the same random seed + @test_util.run_deprecated_v1 def testCPUGPUMatch(self): for dt in (dtypes.float16, dtypes.float32, dtypes.float64, dtypes.int32, dtypes.int64): @@ -342,6 +356,7 @@ class RandomUniformTest(RandomOpTestCommon): results[use_gpu] = sampler() self.assertAllEqual(results[False], results[True]) + @test_util.run_deprecated_v1 def testSeed(self): for dt in (dtypes.float16, dtypes.float32, dtypes.float64, dtypes.int32, dtypes.int64): @@ -350,6 +365,7 @@ class RandomUniformTest(RandomOpTestCommon): sy = self._Sampler(1000, 0, 17, dtype=dt, use_gpu=True, seed=seed) self.assertAllEqual(sx(), sy()) + @test_util.run_deprecated_v1 def testNoCSE(self): shape = [2, 3, 4] for dtype in dtypes.float16, dtypes.float32, dtypes.int32: @@ -359,6 +375,7 @@ class RandomUniformTest(RandomOpTestCommon): diff = (rnd2 - rnd1).eval() self.assertTrue(np.linalg.norm(diff) > 0.1) + @test_util.run_deprecated_v1 def testSingleSessionNotConstant(self): for use_gpu in [False, True]: for dt in (dtypes.float16, dtypes.float32, dtypes.float64, dtypes.int32, @@ -366,6 +383,7 @@ class RandomUniformTest(RandomOpTestCommon): self._testSingleSessionNotConstant( random_ops.random_uniform, 100, dt, 0, 17, use_gpu=use_gpu) + @test_util.run_deprecated_v1 def testSingleSessionOpSeedNotConstant(self): for use_gpu in [False, True]: for dt in (dtypes.float16, dtypes.float32, dtypes.float64, dtypes.int32, @@ -379,6 +397,7 @@ class RandomUniformTest(RandomOpTestCommon): use_gpu=use_gpu, op_seed=1345) + @test_util.run_deprecated_v1 def testSingleSessionGraphSeedNotConstant(self): for use_gpu in [False, True]: for dt in (dtypes.float16, dtypes.float32, dtypes.float64, dtypes.int32, @@ -395,6 +414,7 @@ class RandomUniformTest(RandomOpTestCommon): class RandomShapeTest(test.TestCase): + @test_util.run_deprecated_v1 def testTruncatedNormal(self): # Fully known shape. rnd1 = random_ops.truncated_normal([1, 2, 3]) @@ -407,6 +427,7 @@ class RandomShapeTest(test.TestCase): rnd3 = random_ops.truncated_normal(array_ops.placeholder(dtypes.int32)) self.assertIs(None, rnd3.get_shape().ndims) + @test_util.run_deprecated_v1 def testRandomNormal(self): # Fully known shape. rnd1 = random_ops.random_normal([1, 2, 3]) @@ -419,6 +440,7 @@ class RandomShapeTest(test.TestCase): rnd3 = random_ops.random_normal(array_ops.placeholder(dtypes.int32)) self.assertIs(None, rnd3.get_shape().ndims) + @test_util.run_deprecated_v1 def testRandomUniform(self): # Fully known shape. rnd1 = random_ops.random_uniform([1, 2, 3]) diff --git a/tensorflow/python/kernel_tests/random/random_poisson_test.py b/tensorflow/python/kernel_tests/random/random_poisson_test.py index 417588f8a3..0a6b004d68 100644 --- a/tensorflow/python/kernel_tests/random/random_poisson_test.py +++ b/tensorflow/python/kernel_tests/random/random_poisson_test.py @@ -23,6 +23,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops from tensorflow.python.platform import test @@ -43,7 +44,7 @@ class RandomPoissonTest(test.TestCase): rng = random_ops.random_poisson(lam, [num], dtype=dtype, seed=seed) ret = np.empty([10, num]) for i in xrange(10): - ret[i, :] = sess.run(rng) + ret[i, :] = self.evaluate(rng) return ret return func @@ -104,6 +105,7 @@ class RandomPoissonTest(test.TestCase): # Checks that the CPU and GPU implementation returns the same results, # given the same random seed + @test_util.run_deprecated_v1 def testCPUGPUMatch(self): for dt in _SUPPORTED_DTYPES: results = {} @@ -115,12 +117,14 @@ class RandomPoissonTest(test.TestCase): else: self.assertAllClose(results[False], results[True], rtol=1e-6, atol=1e-6) + @test_util.run_deprecated_v1 def testSeed(self): for dt in dtypes.float16, dtypes.float32, dtypes.float64: sx = self._Sampler(1000, 1.0, dt, use_gpu=True, seed=345) sy = self._Sampler(1000, 1.0, dt, use_gpu=True, seed=345) self.assertAllEqual(sx(), sy()) + @test_util.run_deprecated_v1 def testNoCSE(self): """CSE = constant subexpression eliminator. @@ -140,8 +144,9 @@ class RandomPoissonTest(test.TestCase): with self.cached_session(): rnd = random_ops.random_poisson([], [], seed=12345) self.assertEqual([0], rnd.get_shape().as_list()) - self.assertAllClose(np.array([], dtype=np.float32), rnd.eval()) + self.assertAllClose(np.array([], dtype=np.float32), self.evaluate(rnd)) + @test_util.run_deprecated_v1 def testShape(self): # Fully known shape rnd = random_ops.random_poisson(2.0, [150], seed=12345) @@ -184,6 +189,7 @@ class RandomPoissonTest(test.TestCase): seed=12345) self.assertIs(None, rnd.get_shape().ndims) + @test_util.run_deprecated_v1 def testDTypeCombinationsV2(self): """Tests random_poisson_v2() for all supported dtype combinations.""" with self.cached_session(): diff --git a/tensorflow/python/kernel_tests/random/random_shuffle_queue_test.py b/tensorflow/python/kernel_tests/random/random_shuffle_queue_test.py index 0d85a072d4..ed4f5434d9 100644 --- a/tensorflow/python/kernel_tests/random/random_shuffle_queue_test.py +++ b/tensorflow/python/kernel_tests/random/random_shuffle_queue_test.py @@ -84,9 +84,9 @@ class RandomShuffleQueueTest(test.TestCase): dequeue_t = q.dequeue() results = [] for _ in range(2): - a, b = sess.run(dequeue_t) + a, b = self.evaluate(dequeue_t) results.append((a, b)) - a, b = sess.run(q.dequeue_many(3)) + a, b = self.evaluate(q.dequeue_many(3)) for i in range(3): results.append((a[i], b[i])) self.assertItemsEqual([(1, [5]), (2, [6]), (3, [7]), (4, [8]), (9, [10])], @@ -101,7 +101,7 @@ class RandomShuffleQueueTest(test.TestCase): # Run one producer thread for each element in elems. def enqueue(enqueue_op): - sess.run(enqueue_op) + self.evaluate(enqueue_op) threads = [ self.checkedThread( @@ -133,7 +133,7 @@ class RandomShuffleQueueTest(test.TestCase): results = [] def dequeue(): - results.append(sess.run(dequeued_t)) + results.append(self.evaluate(dequeued_t)) threads = [self.checkedThread(target=dequeue) for _ in enqueue_ops] for thread in threads: @@ -167,13 +167,13 @@ class RandomShuffleQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) for enqueue_op in enqueue_ops: - sess.run(enqueue_op) + self.evaluate(enqueue_op) results = [] def dequeue(): for _ in xrange(len(elems)): - results.append(sess.run(dequeued_t)) + results.append(self.evaluate(dequeued_t)) enqueue_thread = self.checkedThread(target=enqueue) dequeue_thread = self.checkedThread(target=dequeue) @@ -197,7 +197,7 @@ class RandomShuffleQueueTest(test.TestCase): results = [] for _ in xrange(len(elems)): - x, y = sess.run(dequeued_t) + x, y = self.evaluate(dequeued_t) results.append((x, y)) self.assertItemsEqual(elems, results) @@ -215,9 +215,9 @@ class RandomShuffleQueueTest(test.TestCase): self.assertEqual([], size.get_shape()) enqueue_op.run() - self.assertEqual([1], size.eval()) + self.assertEqual([1], self.evaluate(size)) dequeued_t.op.run() - self.assertEqual([0], size.eval()) + self.assertEqual([0], self.evaluate(size)) def testEnqueueMany(self): with self.cached_session(): @@ -241,9 +241,9 @@ class RandomShuffleQueueTest(test.TestCase): enqueue_op = q.enqueue_many((empty_t,)) size_t = q.size() - self.assertEqual(0, size_t.eval()) + self.assertEqual(0, self.evaluate(size_t)) enqueue_op.run() - self.assertEqual(0, size_t.eval()) + self.assertEqual(0, self.evaluate(size_t)) def testEmptyDequeueMany(self): with self.cached_session(): @@ -251,9 +251,9 @@ class RandomShuffleQueueTest(test.TestCase): enqueue_op = q.enqueue((10.0,)) dequeued_t = q.dequeue_many(0) - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) enqueue_op.run() - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) def testEmptyDequeueUpTo(self): with self.cached_session(): @@ -261,9 +261,9 @@ class RandomShuffleQueueTest(test.TestCase): enqueue_op = q.enqueue((10.0,)) dequeued_t = q.dequeue_up_to(0) - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) enqueue_op.run() - self.assertEqual([], dequeued_t.eval().tolist()) + self.assertEqual([], self.evaluate(dequeued_t).tolist()) def testEmptyDequeueManyWithNoShape(self): with self.cached_session(): @@ -275,7 +275,7 @@ class RandomShuffleQueueTest(test.TestCase): # Expect the operation to fail due to the shape not being constrained. with self.assertRaisesOpError( "require the components to have specified shapes"): - dequeued_t.eval() + self.evaluate(dequeued_t) enqueue_op.run() @@ -284,7 +284,7 @@ class RandomShuffleQueueTest(test.TestCase): # elements enqueued. with self.assertRaisesOpError( "require the components to have specified shapes"): - dequeued_t.eval() + self.evaluate(dequeued_t) def testEmptyDequeueUpToWithNoShape(self): with self.cached_session(): @@ -296,7 +296,7 @@ class RandomShuffleQueueTest(test.TestCase): # Expect the operation to fail due to the shape not being constrained. with self.assertRaisesOpError( "require the components to have specified shapes"): - dequeued_t.eval() + self.evaluate(dequeued_t) enqueue_op.run() @@ -305,7 +305,7 @@ class RandomShuffleQueueTest(test.TestCase): # elements enqueued. with self.assertRaisesOpError( "require the components to have specified shapes"): - dequeued_t.eval() + self.evaluate(dequeued_t) def testMultiEnqueueMany(self): with self.cached_session() as sess: @@ -321,7 +321,7 @@ class RandomShuffleQueueTest(test.TestCase): results = [] for _ in range(8): - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) results.append((float_val, [int_val[0], int_val[1]])) expected = list(zip(float_elems, int_elems)) * 2 self.assertItemsEqual(expected, results) @@ -335,7 +335,7 @@ class RandomShuffleQueueTest(test.TestCase): enqueue_op.run() - results = dequeued_t.eval().tolist() + results = self.evaluate(dequeued_t).tolist() results.extend(dequeued_t.eval()) self.assertItemsEqual(elems, results) @@ -348,7 +348,7 @@ class RandomShuffleQueueTest(test.TestCase): enqueue_op.run() - results = dequeued_t.eval().tolist() + results = self.evaluate(dequeued_t).tolist() results.extend(dequeued_t.eval()) self.assertItemsEqual(elems, results) @@ -368,20 +368,20 @@ class RandomShuffleQueueTest(test.TestCase): enqueue_op.run() results = [] - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) self.assertEqual(float_val.shape, dequeued_t[0].get_shape()) self.assertEqual(int_val.shape, dequeued_t[1].get_shape()) results.extend(zip(float_val, int_val.tolist())) - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) results.extend(zip(float_val, int_val.tolist())) - float_val, int_val = sess.run(dequeued_single_t) + float_val, int_val = self.evaluate(dequeued_single_t) self.assertEqual(float_val.shape, dequeued_single_t[0].get_shape()) self.assertEqual(int_val.shape, dequeued_single_t[1].get_shape()) results.append((float_val, int_val.tolist())) - float_val, int_val = sess.run(dequeued_single_t) + float_val, int_val = self.evaluate(dequeued_single_t) results.append((float_val, int_val.tolist())) self.assertItemsEqual(zip(float_elems, int_elems), results) @@ -402,21 +402,21 @@ class RandomShuffleQueueTest(test.TestCase): enqueue_op.run() results = [] - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) # dequeue_up_to has undefined shape. self.assertEqual([None], dequeued_t[0].get_shape().as_list()) self.assertEqual([None, 2], dequeued_t[1].get_shape().as_list()) results.extend(zip(float_val, int_val.tolist())) - float_val, int_val = sess.run(dequeued_t) + float_val, int_val = self.evaluate(dequeued_t) results.extend(zip(float_val, int_val.tolist())) - float_val, int_val = sess.run(dequeued_single_t) + float_val, int_val = self.evaluate(dequeued_single_t) self.assertEqual(float_val.shape, dequeued_single_t[0].get_shape()) self.assertEqual(int_val.shape, dequeued_single_t[1].get_shape()) results.append((float_val, int_val.tolist())) - float_val, int_val = sess.run(dequeued_single_t) + float_val, int_val = self.evaluate(dequeued_single_t) results.append((float_val, int_val.tolist())) self.assertItemsEqual(zip(float_elems, int_elems), results) @@ -442,7 +442,7 @@ class RandomShuffleQueueTest(test.TestCase): # Enqueue 100 items in parallel on 10 threads. def enqueue(): - sess.run(enqueue_op) + self.evaluate(enqueue_op) threads = [self.checkedThread(target=enqueue) for _ in range(10)] for thread in threads: @@ -466,7 +466,7 @@ class RandomShuffleQueueTest(test.TestCase): dequeued_elems = [] def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t)) + dequeued_elems.extend(self.evaluate(dequeued_t)) threads = [self.checkedThread(target=dequeue) for _ in range(10)] for thread in threads: @@ -489,7 +489,7 @@ class RandomShuffleQueueTest(test.TestCase): dequeued_elems = [] def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t)) + dequeued_elems.extend(self.evaluate(dequeued_t)) threads = [self.checkedThread(target=dequeue) for _ in range(10)] for thread in threads: @@ -515,7 +515,7 @@ class RandomShuffleQueueTest(test.TestCase): dequeued_elems = [] def dequeue(dequeue_op): - dequeued_elems.extend(sess.run(dequeue_op)) + dequeued_elems.extend(self.evaluate(dequeue_op)) threads = [] for dequeue_op in dequeue_ops: @@ -539,10 +539,10 @@ class RandomShuffleQueueTest(test.TestCase): # The enqueue_op should run after the dequeue op has blocked. # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t).tolist()) + dequeued_elems.extend(self.evaluate(dequeued_t).tolist()) enqueue_thread = self.checkedThread(target=enqueue) dequeue_thread = self.checkedThread(target=dequeue) @@ -566,10 +566,10 @@ class RandomShuffleQueueTest(test.TestCase): # The enqueue_op should run after the dequeue op has blocked. # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) - sess.run(enqueue_op) + self.evaluate(enqueue_op) def dequeue(): - dequeued_elems.extend(sess.run(dequeued_t).tolist()) + dequeued_elems.extend(self.evaluate(dequeued_t).tolist()) enqueue_thread = self.checkedThread(target=enqueue) dequeue_thread = self.checkedThread(target=dequeue) @@ -649,7 +649,7 @@ class RandomShuffleQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - dequeued_t.eval() + self.evaluate(dequeued_t) def testBlockingDequeueFromClosedQueue(self): with self.cached_session() as sess: @@ -665,18 +665,18 @@ class RandomShuffleQueueTest(test.TestCase): results = [] # Manually dequeue until we hit min_size. - results.append(sess.run(dequeued_t)) - results.append(sess.run(dequeued_t)) + results.append(self.evaluate(dequeued_t)) + results.append(self.evaluate(dequeued_t)) def blocking_dequeue(): - results.append(sess.run(dequeued_t)) - results.append(sess.run(dequeued_t)) + results.append(self.evaluate(dequeued_t)) + results.append(self.evaluate(dequeued_t)) self.assertItemsEqual(elems, results) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=blocking_dequeue) dequeue_thread.start() @@ -701,7 +701,7 @@ class RandomShuffleQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) finished.append(True) dequeue_thread = self.checkedThread(target=dequeue) @@ -727,12 +727,12 @@ class RandomShuffleQueueTest(test.TestCase): progress = [] # Must be mutable def dequeue(): - self.assertItemsEqual(elems, sess.run(dequeued_t)) + self.assertItemsEqual(elems, self.evaluate(dequeued_t)) progress.append(1) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) progress.append(2) self.assertEqual(len(progress), 0) @@ -763,9 +763,9 @@ class RandomShuffleQueueTest(test.TestCase): results = [] def dequeue(): - results.extend(sess.run(dequeued_t)) + results.extend(self.evaluate(dequeued_t)) self.assertEquals(3, len(results)) - results.extend(sess.run(dequeued_t)) + results.extend(self.evaluate(dequeued_t)) self.assertEquals(4, len(results)) dequeue_thread = self.checkedThread(target=dequeue) @@ -794,11 +794,11 @@ class RandomShuffleQueueTest(test.TestCase): results = [] def dequeue(): - results.extend(sess.run(dequeued_t)) + results.extend(self.evaluate(dequeued_t)) self.assertEquals(3, len(results)) # min_after_dequeue is 2, we ask for 3 elements, and we end up only # getting the remaining 1. - results.extend(sess.run(dequeued_t)) + results.extend(self.evaluate(dequeued_t)) self.assertEquals(4, len(results)) dequeue_thread = self.checkedThread(target=dequeue) @@ -824,16 +824,16 @@ class RandomShuffleQueueTest(test.TestCase): results = [] def dequeue(): - results.extend(sess.run(dequeued_t)) + results.extend(self.evaluate(dequeued_t)) self.assertEqual(len(results), 3) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) # While the last dequeue failed, we want to insure that it returns # any elements that it potentially reserved to dequeue. Thus the # next cleanup should return a single element. - results.extend(sess.run(cleanup_dequeue_t)) + results.extend(self.evaluate(cleanup_dequeue_t)) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -854,7 +854,7 @@ class RandomShuffleQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -874,7 +874,7 @@ class RandomShuffleQueueTest(test.TestCase): # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed and has insufficient"): - sess.run(dequeued_t) + self.evaluate(dequeued_t) dequeue_thread = self.checkedThread(target=dequeue) dequeue_thread.start() @@ -922,7 +922,7 @@ class RandomShuffleQueueTest(test.TestCase): enqueue_op.run() def blocking_enqueue(): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) thread = self.checkedThread(target=blocking_enqueue) thread.start() @@ -950,7 +950,7 @@ class RandomShuffleQueueTest(test.TestCase): enqueue_op.run() def blocking_enqueue(): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) thread = self.checkedThread(target=blocking_enqueue) thread.start() @@ -987,11 +987,11 @@ class RandomShuffleQueueTest(test.TestCase): def blocking_enqueue(): # Expect the operation to succeed since it will complete # before the queue is closed. - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) # Expect the operation to fail due to the queue being closed. with self.assertRaisesRegexp(errors_impl.CancelledError, "closed"): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) thread1 = self.checkedThread(target=blocking_enqueue) thread1.start() @@ -1001,7 +1001,7 @@ class RandomShuffleQueueTest(test.TestCase): time.sleep(0.1) def blocking_close(): - sess.run(close_op) + self.evaluate(close_op) thread2 = self.checkedThread(target=blocking_close) thread2.start() @@ -1032,7 +1032,7 @@ class RandomShuffleQueueTest(test.TestCase): def blocking_enqueue(): # This will block until the dequeue after the close. - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) thread1 = self.checkedThread(target=blocking_enqueue) thread1.start() @@ -1040,7 +1040,7 @@ class RandomShuffleQueueTest(test.TestCase): # First blocking_enqueue_op of blocking_enqueue has enqueued 1 of 2 # elements, and is blocked waiting for one more element to be dequeue. for i in range(50): - queue_size = size_t.eval() + queue_size = self.evaluate(size_t) if queue_size == 4: break elif i == 49: @@ -1050,7 +1050,7 @@ class RandomShuffleQueueTest(test.TestCase): time.sleep(0.1) def blocking_close(): - sess.run(close_op) + self.evaluate(close_op) thread2 = self.checkedThread(target=blocking_close) thread2.start() @@ -1064,7 +1064,7 @@ class RandomShuffleQueueTest(test.TestCase): # At this point the close operation will complete, so the next enqueue # will fail. with self.assertRaisesRegexp(errors_impl.CancelledError, "closed"): - sess.run(blocking_enqueue_op) + self.evaluate(blocking_enqueue_op) def testSharedQueueSameSession(self): with self.cached_session(): @@ -1216,23 +1216,23 @@ class RandomShuffleQueueTest(test.TestCase): def _blockingDequeue(self, sess, dequeue_op): with self.assertRaisesOpError("was cancelled"): - sess.run(dequeue_op) + self.evaluate(dequeue_op) def _blockingDequeueMany(self, sess, dequeue_many_op): with self.assertRaisesOpError("was cancelled"): - sess.run(dequeue_many_op) + self.evaluate(dequeue_many_op) def _blockingDequeueUpTo(self, sess, dequeue_up_to_op): with self.assertRaisesOpError("was cancelled"): - sess.run(dequeue_up_to_op) + self.evaluate(dequeue_up_to_op) def _blockingEnqueue(self, sess, enqueue_op): with self.assertRaisesOpError("was cancelled"): - sess.run(enqueue_op) + self.evaluate(enqueue_op) def _blockingEnqueueMany(self, sess, enqueue_many_op): with self.assertRaisesOpError("was cancelled"): - sess.run(enqueue_many_op) + self.evaluate(enqueue_many_op) def testResetOfBlockingOperation(self): with self.cached_session() as sess: @@ -1383,7 +1383,7 @@ class RandomShuffleQueueTest(test.TestCase): def blocking_enqueue(): enq_done.append(False) # This will fill the queue and then block until enough dequeues happen. - sess.run(enq) + self.evaluate(enq) enq_done.append(True) thread = self.checkedThread(target=blocking_enqueue) @@ -1393,14 +1393,14 @@ class RandomShuffleQueueTest(test.TestCase): results = [] results.append(deq.eval()) # Will only complete after the enqueue starts. self.assertEqual(len(enq_done), 1) - self.assertEqual(sess.run(size_op), 5) + self.assertEqual(self.evaluate(size_op), 5) for _ in range(3): results.append(deq.eval()) time.sleep(0.1) self.assertEqual(len(enq_done), 1) - self.assertEqual(sess.run(size_op), 5) + self.assertEqual(self.evaluate(size_op), 5) # This dequeue will unblock the thread. results.append(deq.eval()) @@ -1426,7 +1426,7 @@ class RandomShuffleQueueTest(test.TestCase): def blocking_dequeue(): # Will only complete after 4 enqueues complete. - results.extend(sess.run(deq)) + results.extend(self.evaluate(deq)) thread = self.checkedThread(target=blocking_dequeue) thread.start() @@ -1435,7 +1435,7 @@ class RandomShuffleQueueTest(test.TestCase): # TODO(mrry): Figure out how to do this without sleeping. time.sleep(0.1) self.assertEqual(len(results), 0) - sess.run(enq) + self.evaluate(enq) # Enough enqueued to unblock the dequeue thread.join() diff --git a/tensorflow/python/kernel_tests/random/stateless_random_ops_test.py b/tensorflow/python/kernel_tests/random/stateless_random_ops_test.py index d57db3c512..898f38444b 100644 --- a/tensorflow/python/kernel_tests/random/stateless_random_ops_test.py +++ b/tensorflow/python/kernel_tests/random/stateless_random_ops_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import random_seed +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import stateless_random_ops as stateless @@ -58,11 +59,11 @@ class StatelessOpsTest(test.TestCase): preseed = invert_philox(key, (seed[0], 0, seed[1], 0)).astype(np.uint64) preseed = preseed[::2] | preseed[1::2] << 32 random_seed.set_random_seed(seed[0]) - with self.test_session(use_gpu=True): + with test_util.use_gpu(): for stateless_op, stateful_op in cases: stateful = stateful_op(seed=seed[1]) pure = stateless_op(seed=preseed) - self.assertAllEqual(stateful.eval(), pure.eval()) + self.assertAllEqual(self.evaluate(stateful), self.evaluate(pure)) def _test_determinism(self, cases): # Stateless values should be equal iff the seeds are equal (roughly) @@ -128,23 +129,29 @@ class StatelessOpsTest(test.TestCase): yield (functools.partial(stateless.stateless_multinomial, **kwds), functools.partial(random_ops.multinomial, **kwds)) + @test_util.run_deprecated_v1 def testMatchFloat(self): self._test_match(self._float_cases()) + @test_util.run_deprecated_v1 def testMatchInt(self): self._test_match(self._int_cases()) + @test_util.run_deprecated_v1 def testMatchMultinomial(self): self._test_match(self._multinomial_cases()) + @test_util.run_deprecated_v1 def testDeterminismFloat(self): self._test_determinism( self._float_cases(shape_dtypes=(dtypes.int32, dtypes.int64))) + @test_util.run_deprecated_v1 def testDeterminismInt(self): self._test_determinism( self._int_cases(shape_dtypes=(dtypes.int32, dtypes.int64))) + @test_util.run_deprecated_v1 def testDeterminismMultinomial(self): self._test_determinism(self._multinomial_cases()) diff --git a/tensorflow/python/kernel_tests/reader_ops_test.py b/tensorflow/python/kernel_tests/reader_ops_test.py index ac9be56d63..43d15817e9 100644 --- a/tensorflow/python/kernel_tests/reader_ops_test.py +++ b/tensorflow/python/kernel_tests/reader_ops_test.py @@ -28,6 +28,7 @@ import zlib from tensorflow.core.protobuf import config_pb2 from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.lib.io import tf_record from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import io_ops @@ -140,147 +141,147 @@ class TFCompressionTestCase(test.TestCase): class IdentityReaderTest(test.TestCase): - def _ExpectRead(self, sess, key, value, expected): - k, v = sess.run([key, value]) + def _ExpectRead(self, key, value, expected): + k, v = self.evaluate([key, value]) self.assertAllEqual(expected, k) self.assertAllEqual(expected, v) + @test_util.run_deprecated_v1 def testOneEpoch(self): - with self.cached_session() as sess: - reader = io_ops.IdentityReader("test_reader") - work_completed = reader.num_work_units_completed() - produced = reader.num_records_produced() - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - queued_length = queue.size() - key, value = reader.read(queue) + reader = io_ops.IdentityReader("test_reader") + work_completed = reader.num_work_units_completed() + produced = reader.num_records_produced() + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + queued_length = queue.size() + key, value = reader.read(queue) - self.assertAllEqual(0, work_completed.eval()) - self.assertAllEqual(0, produced.eval()) - self.assertAllEqual(0, queued_length.eval()) + self.assertAllEqual(0, self.evaluate(work_completed)) + self.assertAllEqual(0, self.evaluate(produced)) + self.assertAllEqual(0, self.evaluate(queued_length)) - queue.enqueue_many([["A", "B", "C"]]).run() - queue.close().run() - self.assertAllEqual(3, queued_length.eval()) + self.evaluate(queue.enqueue_many([["A", "B", "C"]])) + self.evaluate(queue.close()) + self.assertAllEqual(3, self.evaluate(queued_length)) - self._ExpectRead(sess, key, value, b"A") - self.assertAllEqual(1, produced.eval()) + self._ExpectRead(key, value, b"A") + self.assertAllEqual(1, self.evaluate(produced)) - self._ExpectRead(sess, key, value, b"B") + self._ExpectRead(key, value, b"B") - self._ExpectRead(sess, key, value, b"C") - self.assertAllEqual(3, produced.eval()) - self.assertAllEqual(0, queued_length.eval()) + self._ExpectRead(key, value, b"C") + self.assertAllEqual(3, self.evaluate(produced)) + self.assertAllEqual(0, self.evaluate(queued_length)) - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - sess.run([key, value]) + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + self.evaluate([key, value]) - self.assertAllEqual(3, work_completed.eval()) - self.assertAllEqual(3, produced.eval()) - self.assertAllEqual(0, queued_length.eval()) + self.assertAllEqual(3, self.evaluate(work_completed)) + self.assertAllEqual(3, self.evaluate(produced)) + self.assertAllEqual(0, self.evaluate(queued_length)) + @test_util.run_deprecated_v1 def testMultipleEpochs(self): - with self.cached_session() as sess: - reader = io_ops.IdentityReader("test_reader") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - enqueue = queue.enqueue_many([["DD", "EE"]]) - key, value = reader.read(queue) - - enqueue.run() - self._ExpectRead(sess, key, value, b"DD") - self._ExpectRead(sess, key, value, b"EE") - enqueue.run() - self._ExpectRead(sess, key, value, b"DD") - self._ExpectRead(sess, key, value, b"EE") - enqueue.run() - self._ExpectRead(sess, key, value, b"DD") - self._ExpectRead(sess, key, value, b"EE") - queue.close().run() - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - sess.run([key, value]) - + reader = io_ops.IdentityReader("test_reader") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + enqueue = queue.enqueue_many([["DD", "EE"]]) + key, value = reader.read(queue) + + self.evaluate(enqueue) + self._ExpectRead(key, value, b"DD") + self._ExpectRead(key, value, b"EE") + self.evaluate(enqueue) + self._ExpectRead(key, value, b"DD") + self._ExpectRead(key, value, b"EE") + self.evaluate(enqueue) + self._ExpectRead(key, value, b"DD") + self._ExpectRead(key, value, b"EE") + self.evaluate(queue.close()) + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + self.evaluate([key, value]) + + @test_util.run_deprecated_v1 def testSerializeRestore(self): - with self.cached_session() as sess: - reader = io_ops.IdentityReader("test_reader") - produced = reader.num_records_produced() - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - queue.enqueue_many([["X", "Y", "Z"]]).run() - key, value = reader.read(queue) - - self._ExpectRead(sess, key, value, b"X") - self.assertAllEqual(1, produced.eval()) - state = reader.serialize_state().eval() - - self._ExpectRead(sess, key, value, b"Y") - self._ExpectRead(sess, key, value, b"Z") - self.assertAllEqual(3, produced.eval()) - - queue.enqueue_many([["Y", "Z"]]).run() - queue.close().run() - reader.restore_state(state).run() - self.assertAllEqual(1, produced.eval()) - self._ExpectRead(sess, key, value, b"Y") - self._ExpectRead(sess, key, value, b"Z") - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - sess.run([key, value]) - self.assertAllEqual(3, produced.eval()) - - self.assertEqual(bytes, type(state)) - - with self.assertRaises(ValueError): - reader.restore_state([]) - - with self.assertRaises(ValueError): - reader.restore_state([state, state]) - - with self.assertRaisesOpError( - "Could not parse state for IdentityReader 'test_reader'"): - reader.restore_state(state[1:]).run() - - with self.assertRaisesOpError( - "Could not parse state for IdentityReader 'test_reader'"): - reader.restore_state(state[:-1]).run() - - with self.assertRaisesOpError( - "Could not parse state for IdentityReader 'test_reader'"): - reader.restore_state(state + b"ExtraJunk").run() - - with self.assertRaisesOpError( - "Could not parse state for IdentityReader 'test_reader'"): - reader.restore_state(b"PREFIX" + state).run() - - with self.assertRaisesOpError( - "Could not parse state for IdentityReader 'test_reader'"): - reader.restore_state(b"BOGUS" + state[5:]).run() - + reader = io_ops.IdentityReader("test_reader") + produced = reader.num_records_produced() + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + self.evaluate(queue.enqueue_many([["X", "Y", "Z"]])) + key, value = reader.read(queue) + + self._ExpectRead(key, value, b"X") + self.assertAllEqual(1, self.evaluate(produced)) + state = self.evaluate(reader.serialize_state()) + + self._ExpectRead(key, value, b"Y") + self._ExpectRead(key, value, b"Z") + self.assertAllEqual(3, self.evaluate(produced)) + + self.evaluate(queue.enqueue_many([["Y", "Z"]])) + self.evaluate(queue.close()) + self.evaluate(reader.restore_state(state)) + self.assertAllEqual(1, self.evaluate(produced)) + self._ExpectRead(key, value, b"Y") + self._ExpectRead(key, value, b"Z") + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + self.evaluate([key, value]) + self.assertAllEqual(3, self.evaluate(produced)) + + self.assertEqual(bytes, type(state)) + + with self.assertRaises(ValueError): + reader.restore_state([]) + + with self.assertRaises(ValueError): + reader.restore_state([state, state]) + + with self.assertRaisesOpError( + "Could not parse state for IdentityReader 'test_reader'"): + self.evaluate(reader.restore_state(state[1:])) + + with self.assertRaisesOpError( + "Could not parse state for IdentityReader 'test_reader'"): + self.evaluate(reader.restore_state(state[:-1])) + + with self.assertRaisesOpError( + "Could not parse state for IdentityReader 'test_reader'"): + self.evaluate(reader.restore_state(state + b"ExtraJunk")) + + with self.assertRaisesOpError( + "Could not parse state for IdentityReader 'test_reader'"): + self.evaluate(reader.restore_state(b"PREFIX" + state)) + + with self.assertRaisesOpError( + "Could not parse state for IdentityReader 'test_reader'"): + self.evaluate(reader.restore_state(b"BOGUS" + state[5:])) + + @test_util.run_deprecated_v1 def testReset(self): - with self.cached_session() as sess: - reader = io_ops.IdentityReader("test_reader") - work_completed = reader.num_work_units_completed() - produced = reader.num_records_produced() - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - queued_length = queue.size() - key, value = reader.read(queue) + reader = io_ops.IdentityReader("test_reader") + work_completed = reader.num_work_units_completed() + produced = reader.num_records_produced() + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + queued_length = queue.size() + key, value = reader.read(queue) - queue.enqueue_many([["X", "Y", "Z"]]).run() - self._ExpectRead(sess, key, value, b"X") - self.assertLess(0, queued_length.eval()) - self.assertAllEqual(1, produced.eval()) + self.evaluate(queue.enqueue_many([["X", "Y", "Z"]])) + self._ExpectRead(key, value, b"X") + self.assertLess(0, self.evaluate(queued_length)) + self.assertAllEqual(1, self.evaluate(produced)) - self._ExpectRead(sess, key, value, b"Y") - self.assertLess(0, work_completed.eval()) - self.assertAllEqual(2, produced.eval()) + self._ExpectRead(key, value, b"Y") + self.assertLess(0, self.evaluate(work_completed)) + self.assertAllEqual(2, self.evaluate(produced)) - reader.reset().run() - self.assertAllEqual(0, work_completed.eval()) - self.assertAllEqual(0, produced.eval()) - self.assertAllEqual(1, queued_length.eval()) - self._ExpectRead(sess, key, value, b"Z") + self.evaluate(reader.reset()) + self.assertAllEqual(0, self.evaluate(work_completed)) + self.assertAllEqual(0, self.evaluate(produced)) + self.assertAllEqual(1, self.evaluate(queued_length)) + self._ExpectRead(key, value, b"Z") - queue.enqueue_many([["K", "L"]]).run() - self._ExpectRead(sess, key, value, b"K") + self.evaluate(queue.enqueue_many([["K", "L"]])) + self._ExpectRead(key, value, b"K") class WholeFileReaderTest(test.TestCase): @@ -301,44 +302,44 @@ class WholeFileReaderTest(test.TestCase): os.remove(fn) super(WholeFileReaderTest, self).tearDown() - def _ExpectRead(self, sess, key, value, index): - k, v = sess.run([key, value]) + def _ExpectRead(self, key, value, index): + k, v = self.evaluate([key, value]) self.assertAllEqual(compat.as_bytes(self._filenames[index]), k) self.assertAllEqual(self._content[index], v) + @test_util.run_deprecated_v1 def testOneEpoch(self): - with self.cached_session() as sess: - reader = io_ops.WholeFileReader("test_reader") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - queue.enqueue_many([self._filenames]).run() - queue.close().run() - key, value = reader.read(queue) + reader = io_ops.WholeFileReader("test_reader") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + self.evaluate(queue.enqueue_many([self._filenames])) + self.evaluate(queue.close()) + key, value = reader.read(queue) - self._ExpectRead(sess, key, value, 0) - self._ExpectRead(sess, key, value, 1) - self._ExpectRead(sess, key, value, 2) + self._ExpectRead(key, value, 0) + self._ExpectRead(key, value, 1) + self._ExpectRead(key, value, 2) - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - sess.run([key, value]) + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + self.evaluate([key, value]) + @test_util.run_deprecated_v1 def testInfiniteEpochs(self): - with self.cached_session() as sess: - reader = io_ops.WholeFileReader("test_reader") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - enqueue = queue.enqueue_many([self._filenames]) - key, value = reader.read(queue) - - enqueue.run() - self._ExpectRead(sess, key, value, 0) - self._ExpectRead(sess, key, value, 1) - enqueue.run() - self._ExpectRead(sess, key, value, 2) - self._ExpectRead(sess, key, value, 0) - self._ExpectRead(sess, key, value, 1) - enqueue.run() - self._ExpectRead(sess, key, value, 2) - self._ExpectRead(sess, key, value, 0) + reader = io_ops.WholeFileReader("test_reader") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + enqueue = queue.enqueue_many([self._filenames]) + key, value = reader.read(queue) + + self.evaluate(enqueue) + self._ExpectRead(key, value, 0) + self._ExpectRead(key, value, 1) + self.evaluate(enqueue) + self._ExpectRead(key, value, 2) + self._ExpectRead(key, value, 0) + self._ExpectRead(key, value, 1) + self.evaluate(enqueue) + self._ExpectRead(key, value, 2) + self._ExpectRead(key, value, 0) class TextLineReaderTest(test.TestCase): @@ -366,47 +367,48 @@ class TextLineReaderTest(test.TestCase): return filenames def _testOneEpoch(self, files): - with self.cached_session() as sess: - reader = io_ops.TextLineReader(name="test_reader") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - key, value = reader.read(queue) + reader = io_ops.TextLineReader(name="test_reader") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + key, value = reader.read(queue) - queue.enqueue_many([files]).run() - queue.close().run() - for i in range(self._num_files): - for j in range(self._num_lines): - k, v = sess.run([key, value]) - self.assertAllEqual("%s:%d" % (files[i], j + 1), compat.as_text(k)) - self.assertAllEqual(self._LineText(i, j), v) + self.evaluate(queue.enqueue_many([files])) + self.evaluate(queue.close()) + for i in range(self._num_files): + for j in range(self._num_lines): + k, v = self.evaluate([key, value]) + self.assertAllEqual("%s:%d" % (files[i], j + 1), compat.as_text(k)) + self.assertAllEqual(self._LineText(i, j), v) - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - k, v = sess.run([key, value]) + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + k, v = self.evaluate([key, value]) + @test_util.run_deprecated_v1 def testOneEpochLF(self): self._testOneEpoch(self._CreateFiles(crlf=False)) + @test_util.run_deprecated_v1 def testOneEpochCRLF(self): self._testOneEpoch(self._CreateFiles(crlf=True)) + @test_util.run_deprecated_v1 def testSkipHeaderLines(self): files = self._CreateFiles() - with self.cached_session() as sess: - reader = io_ops.TextLineReader(skip_header_lines=1, name="test_reader") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - key, value = reader.read(queue) + reader = io_ops.TextLineReader(skip_header_lines=1, name="test_reader") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + key, value = reader.read(queue) - queue.enqueue_many([files]).run() - queue.close().run() - for i in range(self._num_files): - for j in range(self._num_lines - 1): - k, v = sess.run([key, value]) - self.assertAllEqual("%s:%d" % (files[i], j + 2), compat.as_text(k)) - self.assertAllEqual(self._LineText(i, j + 1), v) + self.evaluate(queue.enqueue_many([files])) + self.evaluate(queue.close()) + for i in range(self._num_files): + for j in range(self._num_lines - 1): + k, v = self.evaluate([key, value]) + self.assertAllEqual("%s:%d" % (files[i], j + 2), compat.as_text(k)) + self.assertAllEqual(self._LineText(i, j + 1), v) - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - k, v = sess.run([key, value]) + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + k, v = self.evaluate([key, value]) class FixedLengthRecordReaderTest(TFCompressionTestCase): @@ -522,56 +524,55 @@ class FixedLengthRecordReaderTest(TFCompressionTestCase): # gap_bytes=hop_bytes-record_bytes def _TestOneEpoch(self, files, num_records, gap_bytes, encoding=None): hop_bytes = 0 if gap_bytes == 0 else self._record_bytes + gap_bytes - with self.cached_session() as sess: - reader = io_ops.FixedLengthRecordReader( - header_bytes=self._header_bytes, - record_bytes=self._record_bytes, - footer_bytes=self._footer_bytes, - hop_bytes=hop_bytes, - encoding=encoding, - name="test_reader") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - key, value = reader.read(queue) - - queue.enqueue_many([files]).run() - queue.close().run() - for i in range(self._num_files): - for j in range(num_records): - k, v = sess.run([key, value]) - self.assertAllEqual("%s:%d" % (files[i], j), compat.as_text(k)) - self.assertAllEqual(self._Record(i, j), v) - - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - k, v = sess.run([key, value]) + reader = io_ops.FixedLengthRecordReader( + header_bytes=self._header_bytes, + record_bytes=self._record_bytes, + footer_bytes=self._footer_bytes, + hop_bytes=hop_bytes, + encoding=encoding, + name="test_reader") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + key, value = reader.read(queue) + + self.evaluate(queue.enqueue_many([files])) + self.evaluate(queue.close()) + for i in range(self._num_files): + for j in range(num_records): + k, v = self.evaluate([key, value]) + self.assertAllEqual("%s:%d" % (files[i], j), compat.as_text(k)) + self.assertAllEqual(self._Record(i, j), v) + + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + k, v = self.evaluate([key, value]) def _TestOneEpochWithHopBytes(self, files, num_overlapped_records, encoding=None): - with self.cached_session() as sess: - reader = io_ops.FixedLengthRecordReader( - header_bytes=self._header_bytes, - record_bytes=self._record_bytes, - footer_bytes=self._footer_bytes, - hop_bytes=self._hop_bytes, - encoding=encoding, - name="test_reader") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - key, value = reader.read(queue) - - queue.enqueue_many([files]).run() - queue.close().run() - for i in range(self._num_files): - for j in range(num_overlapped_records): - k, v = sess.run([key, value]) - self.assertAllEqual("%s:%d" % (files[i], j), compat.as_text(k)) - self.assertAllEqual(self._OverlappedRecord(i, j), v) - - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - k, v = sess.run([key, value]) + reader = io_ops.FixedLengthRecordReader( + header_bytes=self._header_bytes, + record_bytes=self._record_bytes, + footer_bytes=self._footer_bytes, + hop_bytes=self._hop_bytes, + encoding=encoding, + name="test_reader") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + key, value = reader.read(queue) + + self.evaluate(queue.enqueue_many([files])) + self.evaluate(queue.close()) + for i in range(self._num_files): + for j in range(num_overlapped_records): + k, v = self.evaluate([key, value]) + self.assertAllEqual("%s:%d" % (files[i], j), compat.as_text(k)) + self.assertAllEqual(self._OverlappedRecord(i, j), v) + + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + k, v = self.evaluate([key, value]) + @test_util.run_deprecated_v1 def testOneEpoch(self): for num_records in [0, 7]: # gap_bytes=0: hop_bytes=0 @@ -580,6 +581,7 @@ class FixedLengthRecordReaderTest(TFCompressionTestCase): files = self._CreateFiles(num_records, gap_bytes) self._TestOneEpoch(files, num_records, gap_bytes) + @test_util.run_deprecated_v1 def testGzipOneEpoch(self): for num_records in [0, 7]: # gap_bytes=0: hop_bytes=0 @@ -588,6 +590,7 @@ class FixedLengthRecordReaderTest(TFCompressionTestCase): files = self._CreateGzipFiles(num_records, gap_bytes) self._TestOneEpoch(files, num_records, gap_bytes, encoding="GZIP") + @test_util.run_deprecated_v1 def testZlibOneEpoch(self): for num_records in [0, 7]: # gap_bytes=0: hop_bytes=0 @@ -596,17 +599,20 @@ class FixedLengthRecordReaderTest(TFCompressionTestCase): files = self._CreateZlibFiles(num_records, gap_bytes) self._TestOneEpoch(files, num_records, gap_bytes, encoding="ZLIB") + @test_util.run_deprecated_v1 def testOneEpochWithHopBytes(self): for num_overlapped_records in [0, 2]: files = self._CreateOverlappedRecordFiles(num_overlapped_records) self._TestOneEpochWithHopBytes(files, num_overlapped_records) + @test_util.run_deprecated_v1 def testGzipOneEpochWithHopBytes(self): for num_overlapped_records in [0, 2]: files = self._CreateGzipOverlappedRecordFiles(num_overlapped_records,) self._TestOneEpochWithHopBytes( files, num_overlapped_records, encoding="GZIP") + @test_util.run_deprecated_v1 def testZlibOneEpochWithHopBytes(self): for num_overlapped_records in [0, 2]: files = self._CreateZlibOverlappedRecordFiles(num_overlapped_records) @@ -619,90 +625,91 @@ class TFRecordReaderTest(TFCompressionTestCase): def setUp(self): super(TFRecordReaderTest, self).setUp() + @test_util.run_deprecated_v1 def testOneEpoch(self): files = self._CreateFiles() - with self.cached_session() as sess: - reader = io_ops.TFRecordReader(name="test_reader") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - key, value = reader.read(queue) - - queue.enqueue_many([files]).run() - queue.close().run() - for i in range(self._num_files): - for j in range(self._num_records): - k, v = sess.run([key, value]) - self.assertTrue(compat.as_text(k).startswith("%s:" % files[i])) - self.assertAllEqual(self._Record(i, j), v) - - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - k, v = sess.run([key, value]) + reader = io_ops.TFRecordReader(name="test_reader") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + key, value = reader.read(queue) + + self.evaluate(queue.enqueue_many([files])) + self.evaluate(queue.close()) + for i in range(self._num_files): + for j in range(self._num_records): + k, v = self.evaluate([key, value]) + self.assertTrue(compat.as_text(k).startswith("%s:" % files[i])) + self.assertAllEqual(self._Record(i, j), v) + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + k, v = self.evaluate([key, value]) + + @test_util.run_deprecated_v1 def testReadUpTo(self): files = self._CreateFiles() - with self.cached_session() as sess: - reader = io_ops.TFRecordReader(name="test_reader") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - batch_size = 3 - key, value = reader.read_up_to(queue, batch_size) - - queue.enqueue_many([files]).run() - queue.close().run() - num_k = 0 - num_v = 0 - - while True: - try: - k, v = sess.run([key, value]) - # Test reading *up to* batch_size records - self.assertLessEqual(len(k), batch_size) - self.assertLessEqual(len(v), batch_size) - num_k += len(k) - num_v += len(v) - except errors_impl.OutOfRangeError: - break - - # Test that we have read everything - self.assertEqual(self._num_files * self._num_records, num_k) - self.assertEqual(self._num_files * self._num_records, num_v) - + reader = io_ops.TFRecordReader(name="test_reader") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + batch_size = 3 + key, value = reader.read_up_to(queue, batch_size) + + self.evaluate(queue.enqueue_many([files])) + self.evaluate(queue.close()) + num_k = 0 + num_v = 0 + + while True: + try: + k, v = self.evaluate([key, value]) + # Test reading *up to* batch_size records + self.assertLessEqual(len(k), batch_size) + self.assertLessEqual(len(v), batch_size) + num_k += len(k) + num_v += len(v) + except errors_impl.OutOfRangeError: + break + + # Test that we have read everything + self.assertEqual(self._num_files * self._num_records, num_k) + self.assertEqual(self._num_files * self._num_records, num_v) + + @test_util.run_deprecated_v1 def testReadZlibFiles(self): options = tf_record.TFRecordOptions(TFRecordCompressionType.ZLIB) files = self._CreateFiles(options) - with self.cached_session() as sess: - reader = io_ops.TFRecordReader(name="test_reader", options=options) - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - key, value = reader.read(queue) - - queue.enqueue_many([files]).run() - queue.close().run() - for i in range(self._num_files): - for j in range(self._num_records): - k, v = sess.run([key, value]) - self.assertTrue(compat.as_text(k).startswith("%s:" % files[i])) - self.assertAllEqual(self._Record(i, j), v) + reader = io_ops.TFRecordReader(name="test_reader", options=options) + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + key, value = reader.read(queue) + self.evaluate(queue.enqueue_many([files])) + self.evaluate(queue.close()) + for i in range(self._num_files): + for j in range(self._num_records): + k, v = self.evaluate([key, value]) + self.assertTrue(compat.as_text(k).startswith("%s:" % files[i])) + self.assertAllEqual(self._Record(i, j), v) + + @test_util.run_deprecated_v1 def testReadGzipFiles(self): options = tf_record.TFRecordOptions(TFRecordCompressionType.GZIP) files = self._CreateFiles(options) - with self.cached_session() as sess: - reader = io_ops.TFRecordReader(name="test_reader", options=options) - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - key, value = reader.read(queue) + reader = io_ops.TFRecordReader(name="test_reader", options=options) + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + key, value = reader.read(queue) - queue.enqueue_many([files]).run() - queue.close().run() - for i in range(self._num_files): - for j in range(self._num_records): - k, v = sess.run([key, value]) - self.assertTrue(compat.as_text(k).startswith("%s:" % files[i])) - self.assertAllEqual(self._Record(i, j), v) + self.evaluate(queue.enqueue_many([files])) + self.evaluate(queue.close()) + for i in range(self._num_files): + for j in range(self._num_records): + k, v = self.evaluate([key, value]) + self.assertTrue(compat.as_text(k).startswith("%s:" % files[i])) + self.assertAllEqual(self._Record(i, j), v) class AsyncReaderTest(test.TestCase): + @test_util.run_deprecated_v1 def testNoDeadlockFromQueue(self): """Tests that reading does not block main execution threads.""" config = config_pb2.ConfigProto( @@ -724,7 +731,7 @@ class AsyncReaderTest(test.TestCase): thread_data.append(thread_data_t(t, queue, output)) # Start all readers. They are all blocked waiting for queue entries. - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for d in thread_data: d.thread.start() @@ -733,7 +740,7 @@ class AsyncReaderTest(test.TestCase): fname = os.path.join(self.get_temp_dir(), "deadlock.%s.txt" % i) with open(fname, "wb") as f: f.write(("file-%s" % i).encode()) - d.queue.enqueue_many([[fname]]).run() + self.evaluate(d.queue.enqueue_many([[fname]])) d.thread.join() self.assertEqual([[("file-%s" % i).encode()]], d.output) @@ -751,24 +758,25 @@ class LMDBReaderTest(test.TestCase): self.db_path = os.path.join(self.get_temp_dir(), "data.mdb") shutil.copy(path, self.db_path) + @test_util.run_deprecated_v1 def testReadFromFile(self): - with self.cached_session() as sess: - reader = io_ops.LMDBReader(name="test_read_from_file") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - key, value = reader.read(queue) - - queue.enqueue([self.db_path]).run() - queue.close().run() - for i in range(10): - k, v = sess.run([key, value]) - self.assertAllEqual(compat.as_bytes(k), compat.as_bytes(str(i))) - self.assertAllEqual( - compat.as_bytes(v), compat.as_bytes(str(chr(ord("a") + i)))) - - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - k, v = sess.run([key, value]) - + reader = io_ops.LMDBReader(name="test_read_from_file") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + key, value = reader.read(queue) + + self.evaluate(queue.enqueue([self.db_path])) + self.evaluate(queue.close()) + for i in range(10): + k, v = self.evaluate([key, value]) + self.assertAllEqual(compat.as_bytes(k), compat.as_bytes(str(i))) + self.assertAllEqual( + compat.as_bytes(v), compat.as_bytes(str(chr(ord("a") + i)))) + + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + k, v = self.evaluate([key, value]) + + @test_util.run_deprecated_v1 def testReadFromSameFile(self): with self.cached_session() as sess: reader1 = io_ops.LMDBReader(name="test_read_from_same_file1") @@ -782,30 +790,31 @@ class LMDBReaderTest(test.TestCase): threads = queue_runner_impl.start_queue_runners(sess, coord=coord) for _ in range(3): for _ in range(10): - k1, v1, k2, v2 = sess.run([key1, value1, key2, value2]) + k1, v1, k2, v2 = self.evaluate([key1, value1, key2, value2]) self.assertAllEqual(compat.as_bytes(k1), compat.as_bytes(k2)) self.assertAllEqual(compat.as_bytes(v1), compat.as_bytes(v2)) coord.request_stop() coord.join(threads) + @test_util.run_deprecated_v1 def testReadFromFolder(self): - with self.cached_session() as sess: - reader = io_ops.LMDBReader(name="test_read_from_folder") - queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) - key, value = reader.read(queue) - - queue.enqueue([self.db_path]).run() - queue.close().run() - for i in range(10): - k, v = sess.run([key, value]) - self.assertAllEqual(compat.as_bytes(k), compat.as_bytes(str(i))) - self.assertAllEqual( - compat.as_bytes(v), compat.as_bytes(str(chr(ord("a") + i)))) - - with self.assertRaisesOpError("is closed and has insufficient elements " - "\\(requested 1, current size 0\\)"): - k, v = sess.run([key, value]) - + reader = io_ops.LMDBReader(name="test_read_from_folder") + queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=()) + key, value = reader.read(queue) + + self.evaluate(queue.enqueue([self.db_path])) + self.evaluate(queue.close()) + for i in range(10): + k, v = self.evaluate([key, value]) + self.assertAllEqual(compat.as_bytes(k), compat.as_bytes(str(i))) + self.assertAllEqual( + compat.as_bytes(v), compat.as_bytes(str(chr(ord("a") + i)))) + + with self.assertRaisesOpError("is closed and has insufficient elements " + "\\(requested 1, current size 0\\)"): + k, v = self.evaluate([key, value]) + + @test_util.run_deprecated_v1 def testReadFromFileRepeatedly(self): with self.cached_session() as sess: reader = io_ops.LMDBReader(name="test_read_from_file_repeated") @@ -819,7 +828,7 @@ class LMDBReaderTest(test.TestCase): for _ in range(3): # Go over all 10 records each time. for j in range(10): - k, v = sess.run([key, value]) + k, v = self.evaluate([key, value]) self.assertAllEqual(compat.as_bytes(k), compat.as_bytes(str(j))) self.assertAllEqual( compat.as_bytes(v), compat.as_bytes(str(chr(ord("a") + j)))) diff --git a/tensorflow/python/kernel_tests/record_input_test.py b/tensorflow/python/kernel_tests/record_input_test.py index ebb9872f22..ad8188b372 100644 --- a/tensorflow/python/kernel_tests/record_input_test.py +++ b/tensorflow/python/kernel_tests/record_input_test.py @@ -20,6 +20,7 @@ from __future__ import print_function import os +from tensorflow.python.framework import test_util from tensorflow.python.framework.errors_impl import NotFoundError from tensorflow.python.lib.io import tf_record from tensorflow.python.ops import data_flow_ops @@ -54,7 +55,7 @@ class RecordInputOpTest(test.TestCase): batch_size=1, name="record_input").get_yield_op() - self.assertEqual(sess.run(yield_op), b"0000000000") + self.assertEqual(self.evaluate(yield_op), b"0000000000") def testRecordInputSimpleGzip(self): with self.cached_session() as sess: @@ -73,7 +74,7 @@ class RecordInputOpTest(test.TestCase): compression_type=tf_record.TFRecordCompressionType.GZIP).get_yield_op( ) - self.assertEqual(sess.run(yield_op), b"0000000000") + self.assertEqual(self.evaluate(yield_op), b"0000000000") def testRecordInputSimpleZlib(self): with self.cached_session() as sess: @@ -92,8 +93,9 @@ class RecordInputOpTest(test.TestCase): compression_type=tf_record.TFRecordCompressionType.ZLIB).get_yield_op( ) - self.assertEqual(sess.run(yield_op), b"0000000000") + self.assertEqual(self.evaluate(yield_op), b"0000000000") + @test_util.run_deprecated_v1 def testRecordInputEpochs(self): files = 100 records_per_file = 100 @@ -117,7 +119,7 @@ class RecordInputOpTest(test.TestCase): for _ in range(3): epoch_set = set() for _ in range(int(files * records_per_file / batches)): - op_list = sess.run(yield_op) + op_list = self.evaluate(yield_op) self.assertTrue(len(op_list) is batches) for r in op_list: self.assertTrue(r[0] not in epoch_set) @@ -138,16 +140,18 @@ class RecordInputOpTest(test.TestCase): yield_op = records.get_yield_op() for _ in range(50): - sess.run(yield_op) + self.evaluate(yield_op) + @test_util.run_deprecated_v1 def testEmptyGlob(self): with self.cached_session() as sess: record_input = data_flow_ops.RecordInput(file_pattern="foo") yield_op = record_input.get_yield_op() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) with self.assertRaises(NotFoundError): - sess.run(yield_op) + self.evaluate(yield_op) + @test_util.run_deprecated_v1 def testBufferTooSmall(self): files = 10 records_per_file = 10 @@ -171,7 +175,7 @@ class RecordInputOpTest(test.TestCase): for _ in range(3): epoch_set = set() for _ in range(int(files * records_per_file / batches)): - op_list = sess.run(yield_op) + op_list = self.evaluate(yield_op) self.assertTrue(len(op_list) is batches) for r in op_list: self.assertTrue(r[0] not in epoch_set) diff --git a/tensorflow/python/kernel_tests/reduce_benchmark_test.py b/tensorflow/python/kernel_tests/reduce_benchmark_test.py index 3a2fb81157..ef9c4c350f 100644 --- a/tensorflow/python/kernel_tests/reduce_benchmark_test.py +++ b/tensorflow/python/kernel_tests/reduce_benchmark_test.py @@ -81,7 +81,7 @@ class ReduceBenchmarks(test.Benchmark): grad, = gradients_impl.gradients(reduction, tensor) def fn(): - sess.run(grad.op) + self.evaluate(grad.op) self._run(fn, 10000) @@ -98,7 +98,7 @@ class ReduceBenchmarks(test.Benchmark): grad, = gradients_impl.gradients(reduction, tensor) def fn(): - sess.run(grad.op) + self.evaluate(grad.op) self._run(fn, 10000) diff --git a/tensorflow/python/kernel_tests/reduce_join_op_test.py b/tensorflow/python/kernel_tests/reduce_join_op_test.py index 3bb4986313..49b6620779 100644 --- a/tensorflow/python/kernel_tests/reduce_join_op_test.py +++ b/tensorflow/python/kernel_tests/reduce_join_op_test.py @@ -25,6 +25,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import string_ops from tensorflow.python.platform import test @@ -119,7 +120,7 @@ class ReduceJoinTest(UnicodeTestCase): axis=axis, keep_dims=keep_dims, separator=separator) - output_array = output.eval() + output_array = self.evaluate(output) self.assertAllEqualUnicode(truth, output_array) self.assertAllEqual(truth_shape, output.get_shape()) @@ -149,10 +150,10 @@ class ReduceJoinTest(UnicodeTestCase): if not axis: truth = constant_op.constant(truth) truth_squeezed = array_ops.squeeze(truth, axis=axis) - output_array = output.eval() - output_keep_dims_array = output_keep_dims.eval() - truth_array = truth.eval() - truth_squeezed_array = truth_squeezed.eval() + output_array = self.evaluate(output) + output_keep_dims_array = self.evaluate(output_keep_dims) + truth_array = self.evaluate(truth) + truth_squeezed_array = self.evaluate(truth_squeezed) self.assertAllEqualUnicode(truth_array, output_keep_dims_array) self.assertAllEqualUnicode(truth_squeezed_array, output_array) self.assertAllEqual(truth.get_shape(), output_keep_dims.get_shape()) @@ -230,6 +231,7 @@ class ReduceJoinTest(UnicodeTestCase): axis=1, separator=" ") + @test_util.run_deprecated_v1 def testUnknownShape(self): input_array = [["a"], ["b"]] truth = ["ab"] @@ -241,6 +243,7 @@ class ReduceJoinTest(UnicodeTestCase): self.assertAllEqualUnicode(truth, output_array) self.assertAllEqual(truth_shape, reduced.get_shape()) + @test_util.run_deprecated_v1 def testUnknownIndices(self): input_array = [["this", "is", "a", "test"], ["please", "do", "not", "panic"]] @@ -297,6 +300,7 @@ class ReduceJoinTest(UnicodeTestCase): for permutation in itertools.permutations(xrange(num_dims), i): self._testMultipleReduceJoin(input_array, axis=permutation) + @test_util.run_deprecated_v1 def testInvalidReductionIndices(self): with self.cached_session(): with self.assertRaisesRegexp(ValueError, "Invalid reduction dim"): @@ -318,13 +322,14 @@ class ReduceJoinTest(UnicodeTestCase): # Reduction that drops the dim of size 0. output = string_ops.reduce_join(inputs=inputs, axis=0) - self.assertAllEqualUnicode([""], output.eval()) + self.assertAllEqualUnicode([""], self.evaluate(output)) # Reduction that keeps the dim of size 0. output = string_ops.reduce_join(inputs=inputs, axis=1) - output_shape = output.eval().shape + output_shape = self.evaluate(output).shape self.assertAllEqual([0], output_shape) + @test_util.run_deprecated_v1 def testInvalidArgsUnknownShape(self): with self.cached_session(): placeholder = array_ops.placeholder(dtypes.string, name="placeholder") @@ -335,6 +340,7 @@ class ReduceJoinTest(UnicodeTestCase): with self.assertRaisesOpError("Duplicate reduction dimension 1"): duplicate_index.eval(feed_dict={placeholder.name: [[""]]}) + @test_util.run_deprecated_v1 def testInvalidArgsUnknownIndices(self): with self.cached_session(): placeholder = array_ops.placeholder(dtypes.int32, name="placeholder") diff --git a/tensorflow/python/kernel_tests/reduction_ops_test.py b/tensorflow/python/kernel_tests/reduction_ops_test.py index 2ac3996e25..67a89461f3 100644 --- a/tensorflow/python/kernel_tests/reduction_ops_test.py +++ b/tensorflow/python/kernel_tests/reduction_ops_test.py @@ -27,6 +27,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops @@ -60,6 +61,7 @@ class ReducedShapeTest(test.TestCase): output = math_ops.reduced_shape(shape, axes=axes) self.assertAllEqual(output.eval(), result) + @test_util.run_deprecated_v1 def testSimple(self): with self.cached_session(): self._check([3], [], [3]) @@ -69,6 +71,7 @@ class ReducedShapeTest(test.TestCase): self._check([5, 3], [1], [5, 1]) self._check([5, 3], [0, 1], [1, 1]) + @test_util.run_deprecated_v1 def testZeros(self): """Check that reduced_shape does the right thing with zero dimensions.""" with self.cached_session(): @@ -83,6 +86,7 @@ class ReducedShapeTest(test.TestCase): self._check([3, 0], [1], [3, 1]) self._check([3, 0], [0, 1], [1, 1]) + @test_util.run_deprecated_v1 def testNegAxes(self): with self.cached_session(): self._check([10, 10, 10], [-1], [10, 10, 1]) @@ -94,6 +98,7 @@ class ReducedShapeTest(test.TestCase): class ReductionUnknownShape(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): with self.cached_session(): for dtype, reductions in [(dtypes.float32, @@ -185,9 +190,10 @@ class SumReductionTest(BaseReductionTest): for dtype in [dtypes.int64, dtypes.int32]: with self.cached_session(use_gpu=True) as sess: v = math_ops.reduce_sum([0, 0], constant_op.constant(0, dtype=dtype)) - tf_v = sess.run(v) + tf_v = self.evaluate(v) self.assertAllEqual(tf_v, 0) + @test_util.run_deprecated_v1 def testInfinity(self): for dtype in [np.float32, np.float64]: for special_value_x in [-np.inf, np.inf]: @@ -195,11 +201,13 @@ class SumReductionTest(BaseReductionTest): np_arr = np.array([special_value_x, special_value_y]).astype(dtype) self._compareAll(np_arr, None) + @test_util.run_deprecated_v1 def testInt32(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.int32) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testFloat16(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.float16) @@ -216,9 +224,10 @@ class SumReductionTest(BaseReductionTest): tf_arr = variables.Variable(arr) variables.global_variables_initializer().run() tf_mean = math_ops.reduce_mean(tf_arr, 0, False) - tf_out_mean = sess.run(tf_mean) + tf_out_mean = self.evaluate(tf_mean) self.assertAllClose(tf_out_mean, 1.) + @test_util.run_deprecated_v1 def testFloat32(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.float32) @@ -238,7 +247,7 @@ class SumReductionTest(BaseReductionTest): with self.session(graph=ops.Graph(), use_gpu=True) as sess: tf_row_sum = self._tf_reduce(arr, 1, False) tf_col_sum = self._tf_reduce(arr, 0, False) - tf_out_row, tf_out_col = sess.run([tf_row_sum, tf_col_sum]) + tf_out_row, tf_out_col = self.evaluate([tf_row_sum, tf_col_sum]) self.assertAllClose(col_sum, tf_out_col) self.assertAllClose(row_sum, tf_out_row) @@ -252,25 +261,29 @@ class SumReductionTest(BaseReductionTest): with self.session(graph=ops.Graph(), use_gpu=True) as sess: tf_sum_xz = self._tf_reduce(arr, [0, 2], False) tf_sum_y = self._tf_reduce(arr, 1, False) - tf_out_sum_xz, tf_out_sum_y = sess.run([tf_sum_xz, tf_sum_y]) + tf_out_sum_xz, tf_out_sum_y = self.evaluate([tf_sum_xz, tf_sum_y]) self.assertAllClose(sum_y, tf_out_sum_y) self.assertAllClose(sum_xz, tf_out_sum_xz) + @test_util.run_deprecated_v1 def testFloat64(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.float64) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testComplex64(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.complex64) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testComplex128(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.complex128) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testInvalidIndex(self): np_arr = np.arange(0, 10).reshape([2, 5]).astype(np.float32) input_tensor = ops.convert_to_tensor(np_arr) @@ -284,6 +297,7 @@ class SumReductionTest(BaseReductionTest): ValueError, lambda e: "Invalid reduction dimension" in str(e)): math_ops.reduce_sum(input_tensor, [0, 2]) + @test_util.run_deprecated_v1 def testPartialShapes(self): np.random.seed(1618) @@ -317,6 +331,7 @@ class SumReductionTest(BaseReductionTest): c_unknown_indices, unknown_indices, keepdims=True) self.assertEqual(2, s_unknown_indices_keep.get_shape().rank) + @test_util.run_deprecated_v1 def testWrongShapeForReductionIndices(self): reduction_axes = [[1], [2]] c_unknown = array_ops.placeholder(dtypes.float32) @@ -326,6 +341,7 @@ class SumReductionTest(BaseReductionTest): # Int64?? + @test_util.run_deprecated_v1 def testGradient(self): for dtype in [ dtypes.float32, dtypes.float64, dtypes.complex64, dtypes.complex128 @@ -333,6 +349,7 @@ class SumReductionTest(BaseReductionTest): x = self._makeIncremental([2, 3, 4, 2], dtype) self._compareGradientAxes(x) + @test_util.run_deprecated_v1 def testHighRank(self): # Do a bunch of random high dimensional reductions np.random.seed(42) @@ -350,11 +367,13 @@ class SumReductionTest(BaseReductionTest): np.arange(1, rank, 2)): self._compareAll(data, axes) + @test_util.run_deprecated_v1 def testExpand(self): # Reduce an empty tensor to a nonempty tensor x = np.zeros((5, 0)) self._compareAll(x, [1]) + @test_util.run_deprecated_v1 def testEmptyGradients(self): with self.session(use_gpu=True): x = array_ops.zeros([0, 3]) @@ -362,6 +381,7 @@ class SumReductionTest(BaseReductionTest): error = gradient_checker.compute_gradient_error(x, [0, 3], y, [0]) self.assertEqual(error, 0) + @test_util.run_deprecated_v1 def testDegenerate(self): with self.session(use_gpu=True): for dtype in (dtypes.float16, dtypes.float32, dtypes.float64, @@ -400,9 +420,10 @@ class MeanReductionTest(BaseReductionTest): for dtype in [dtypes.int64, dtypes.int32]: with self.cached_session(use_gpu=True) as sess: v = math_ops.reduce_mean([0, 0], constant_op.constant(0, dtype=dtype)) - tf_v = sess.run(v) + tf_v = self.evaluate(v) self.assertAllEqual(tf_v, 0) + @test_util.run_deprecated_v1 def testInfinity(self): for dtype in [np.float32, np.float64]: for special_value_x in [-np.inf, np.inf]: @@ -410,37 +431,44 @@ class MeanReductionTest(BaseReductionTest): np_arr = np.array([special_value_x, special_value_y]).astype(dtype) self._compareAll(np_arr, None) + @test_util.run_deprecated_v1 def testInt32(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.int32) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testFloat32(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.float32) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testFloat64(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.float64) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testComplex64(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.complex64) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testComplex128(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.complex128) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testGradient(self): s = [2, 3, 4, 2] for dtype in [dtypes.float32, dtypes.float64]: x = self._makeIncremental(s, dtype) self._compareGradientAxes(x, rtol=1e-3, atol=1e-3) + @test_util.run_deprecated_v1 def testEmptyGradients(self): with self.session(use_gpu=True): x = array_ops.zeros([0, 3]) @@ -448,6 +476,7 @@ class MeanReductionTest(BaseReductionTest): error = gradient_checker.compute_gradient_error(x, [0, 3], y, [0]) self.assertEqual(error, 0) + @test_util.run_deprecated_v1 def testDegenerate(self): with self.session(use_gpu=True): for dtype in (dtypes.float16, dtypes.float32, dtypes.float64): @@ -473,9 +502,10 @@ class ProdReductionTest(BaseReductionTest): for dtype in [dtypes.int64, dtypes.int32]: with self.cached_session(use_gpu=True) as sess: v = math_ops.reduce_prod([0, 0], constant_op.constant(0, dtype=dtype)) - tf_v = sess.run(v) + tf_v = self.evaluate(v) self.assertAllEqual(tf_v, 0) + @test_util.run_deprecated_v1 def testInfinity(self): for dtype in [np.float32, np.float64]: for special_value_x in [-np.inf, np.inf]: @@ -483,6 +513,7 @@ class ProdReductionTest(BaseReductionTest): np_arr = np.array([special_value_x, special_value_y]).astype(dtype) self._compareAll(np_arr, None) + @test_util.run_deprecated_v1 def testInt32(self): # Numpy automatically upgrades the type of np.prod from int32 to int64, so # Numpy does not overflow an int32 np.prod while TensorFlow does. To avoid @@ -491,26 +522,31 @@ class ProdReductionTest(BaseReductionTest): np_arr = self._makeIncremental((2,) * rank, dtypes.int32) / 2 self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testFloat32(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.float32) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testFloat64(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.float64) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testComplex64(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.complex64) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testComplex128(self): for rank in range(1, _MAX_RANK + 1): np_arr = self._makeIncremental((2,) * rank, dtypes.complex128) self._compareAllAxes(np_arr) + @test_util.run_deprecated_v1 def testGradientWithZeros(self): s = [2, 3, 4, 2] x = self._makeIncremental(s, dtypes.float32) / 20. @@ -533,6 +569,7 @@ class ProdReductionTest(BaseReductionTest): x4[:, :, :, :] = 0 self._compareGradientAxes(x4, rtol=1e-3, atol=1e-3) + @test_util.run_deprecated_v1 def testEmptyGradients(self): with self.session(use_gpu=True): x = array_ops.zeros([0, 3]) @@ -540,6 +577,7 @@ class ProdReductionTest(BaseReductionTest): error = gradient_checker.compute_gradient_error(x, [0, 3], y, [0]) self.assertEqual(error, 0) + @test_util.run_deprecated_v1 def testDegenerate(self): with self.session(use_gpu=True): for dtype in (dtypes.float16, dtypes.float32, dtypes.float64): @@ -562,7 +600,7 @@ class MinReductionTest(test.TestCase): if reduction_axes is not None: reduction_axes = np.array(reduction_axes).astype(np.int32) tf_ans = math_ops.reduce_min(x, reduction_axes, keepdims) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertAllClose(np_ans, out) self.assertShapeEqual(np_ans, tf_ans) @@ -576,9 +614,10 @@ class MinReductionTest(test.TestCase): for dtype in [dtypes.int64, dtypes.int32]: with self.cached_session(use_gpu=True) as sess: v = math_ops.reduce_min([0, 0], constant_op.constant(0, dtype=dtype)) - tf_v = sess.run(v) + tf_v = self.evaluate(v) self.assertAllEqual(tf_v, 0) + @test_util.run_deprecated_v1 def testInfinity(self): for dtype in [np.float32, np.float64]: for special_value_x in [-np.inf, np.inf]: @@ -614,6 +653,7 @@ class MinReductionTest(test.TestCase): self._compareAll(np_arr, [0, 2]) self._compareAll(np_arr, [0, 1, 2]) + @test_util.run_deprecated_v1 def testGradient(self): s = [2, 3, 4, 2] x = np.arange(1.0, 49.0).reshape(s).astype(np.float64) @@ -624,6 +664,7 @@ class MinReductionTest(test.TestCase): t, s, su, [2, 2], x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testGradient2(self): s = [2, 3, 4, 2] x = np.arange(1.0, 49.0).reshape(s).astype(np.float64) @@ -634,6 +675,7 @@ class MinReductionTest(test.TestCase): t, s, su, [2, 4, 2], x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testGradient3(self): s = [2, 3, 4, 2] x = np.arange(1.0, 49.0).reshape(s).astype(np.float64) @@ -644,6 +686,7 @@ class MinReductionTest(test.TestCase): t, s, su, [2, 3, 2], x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testGradient4(self): s = [2, 3, 4, 2] x = np.arange(1.0, 49.0).reshape(s).astype(np.float64) @@ -654,6 +697,7 @@ class MinReductionTest(test.TestCase): t, s, su, [1], x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testEmptyGradients(self): with self.cached_session(): x = array_ops.zeros([0, 3]) @@ -675,7 +719,7 @@ class MaxReductionTest(test.TestCase): if reduction_axes is not None: reduction_axes = np.array(reduction_axes).astype(np.int32) tf_ans = math_ops.reduce_max(x, reduction_axes, keepdims) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertAllClose(np_ans, out) self.assertShapeEqual(np_ans, tf_ans) @@ -689,9 +733,10 @@ class MaxReductionTest(test.TestCase): for dtype in [dtypes.int64, dtypes.int32]: with self.cached_session(use_gpu=True) as sess: v = math_ops.reduce_max([0, 0], constant_op.constant(0, dtype=dtype)) - tf_v = sess.run(v) + tf_v = self.evaluate(v) self.assertAllEqual(tf_v, 0) + @test_util.run_deprecated_v1 def testInfinity(self): for dtype in [np.float32, np.float64]: for special_value_x in [-np.inf, np.inf]: @@ -741,6 +786,7 @@ class MaxReductionTest(test.TestCase): self._compareAll(np_arr, [0, 2]) self._compareAll(np_arr, [0, 1, 2]) + @test_util.run_deprecated_v1 def testGradient(self): s = [2, 3, 4, 2] x = np.arange(-49.0, -1.0).reshape(s).astype(np.float64) @@ -751,6 +797,7 @@ class MaxReductionTest(test.TestCase): t, s, su, [2, 2], x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testGradient2(self): s = [2, 3, 4, 2] x = np.arange(-49.0, -1.0).reshape(s).astype(np.float64) @@ -761,6 +808,7 @@ class MaxReductionTest(test.TestCase): t, s, su, [2, 4, 2], x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testGradient3(self): s = [2, 3, 4, 2] x = np.arange(-49.0, -1.0).reshape(s).astype(np.float64) @@ -771,6 +819,7 @@ class MaxReductionTest(test.TestCase): t, s, su, [2, 3, 2], x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testGradient4(self): s = [2, 3, 4, 2] x = np.arange(-49.0, -1.0).reshape(s).astype(np.float64) @@ -781,6 +830,7 @@ class MaxReductionTest(test.TestCase): t, s, su, [1], x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testEmptyGradients(self): with self.cached_session(): x = array_ops.zeros([0, 3]) @@ -802,7 +852,7 @@ class AllReductionTest(test.TestCase): if reduction_axes is not None: reduction_axes = np.array(reduction_axes).astype(np.int32) tf_ans = math_ops.reduce_all(x, reduction_axes, keepdims) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertAllEqual(np_ans, out) self.assertShapeEqual(np_ans, tf_ans) @@ -817,7 +867,7 @@ class AllReductionTest(test.TestCase): with self.session(use_gpu=True) as sess: v = math_ops.reduce_all([True, True], constant_op.constant(0, dtype=dtype)) - tf_v = sess.run(v) + tf_v = self.evaluate(v) self.assertAllEqual(tf_v, True) def testAll3D(self): @@ -851,7 +901,7 @@ class AnyReductionTest(test.TestCase): if reduction_axes is not None: reduction_axes = np.array(reduction_axes).astype(np.int32) tf_ans = math_ops.reduce_any(x, reduction_axes, keepdims) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertAllEqual(np_ans, out) self.assertShapeEqual(np_ans, tf_ans) @@ -866,7 +916,7 @@ class AnyReductionTest(test.TestCase): with self.session(use_gpu=True) as sess: v = math_ops.reduce_any([True, True], constant_op.constant(0, dtype=dtype)) - tf_v = sess.run(v) + tf_v = self.evaluate(v) self.assertAllEqual(tf_v, True) def testAll3D(self): @@ -913,6 +963,7 @@ class CountNonzeroReductionTest(test.TestCase): self._compare(x, reduction_axes, True, use_gpu=True, feed_dict=feed_dict) self._compare(x, reduction_axes, True, use_gpu=False, feed_dict=feed_dict) + @test_util.run_deprecated_v1 def testBoolReduce1D(self): # Create a 1D array of floats np_arr = np.asarray([False, False, True, False, False, True]) @@ -920,11 +971,13 @@ class CountNonzeroReductionTest(test.TestCase): self._compareAll(np_arr, []) self._compareAll(np_arr, [0]) + @test_util.run_deprecated_v1 def testFloatReduce1D(self): # Create a 1D array of floats np_arr = np.asarray([0.0, 1.0, -1.0, 0.0, 0.0, 3.0]).astype(np.float32) self._compareAll(np_arr, [0]) + @test_util.run_deprecated_v1 def testFloatReduce4D(self): # Create a 4D array of floats and reduce across some # dimensions @@ -944,11 +997,13 @@ class CountNonzeroReductionTest(test.TestCase): self._compareAll(np_arr, [1, 2, 3]) self._compareAll(np_arr, [0, 1, 2, 3]) + @test_util.run_deprecated_v1 def testExpand(self): # Reduce an empty tensor to a nonempty tensor x = np.zeros((5, 0)) self._compareAll(x, [1]) + @test_util.run_deprecated_v1 def testDegenerate(self): for use_gpu in False, True: with self.cached_session(use_gpu=use_gpu): @@ -962,8 +1017,9 @@ class CountNonzeroReductionTest(test.TestCase): # Test case for GitHub issue 18712 with self.cached_session() as sess: v = math_ops.count_nonzero(constant_op.constant(["test"])) - self.assertAllClose(sess.run(v), 1) + self.assertAllClose(self.evaluate(v), 1) + @test_util.run_deprecated_v1 def testStringReduce1D(self): # Create a 1D array of strings x = np.asarray(["", "", "a", "", "", "b"]) @@ -974,6 +1030,7 @@ class CountNonzeroReductionTest(test.TestCase): self._compare(x, [], keepdims=True, zero=np.str("")) self._compare(x, [0], keepdims=True, zero=np.str("")) + @test_util.run_deprecated_v1 def testStringReduce2D(self): # Create a 2D array of strings x = np.asarray([["", "", "a", "", "", "b"], diff --git a/tensorflow/python/kernel_tests/regex_full_match_op_test.py b/tensorflow/python/kernel_tests/regex_full_match_op_test.py index 98746e7d9b..488ec85ab2 100644 --- a/tensorflow/python/kernel_tests/regex_full_match_op_test.py +++ b/tensorflow/python/kernel_tests/regex_full_match_op_test.py @@ -23,6 +23,7 @@ from absl.testing import parameterized from tensorflow.python.compat import compat from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import gen_string_ops from tensorflow.python.ops import string_ops from tensorflow.python.platform import test @@ -33,6 +34,7 @@ from tensorflow.python.platform import test (gen_string_ops.static_regex_full_match)) class RegexFullMatchOpVariantsTest(test.TestCase, parameterized.TestCase): + @test_util.run_deprecated_v1 def testRegexFullMatch(self, op): values = ["abaaba", "abcdabcde"] with self.cached_session(): @@ -40,6 +42,7 @@ class RegexFullMatchOpVariantsTest(test.TestCase, parameterized.TestCase): matched = op(input_tensor, "a.*a").eval() self.assertAllEqual([True, False], matched) + @test_util.run_deprecated_v1 def testRegexFullMatchTwoDims(self, op): values = [["abaaba", "abcdabcde"], ["acdcba", "ebcda"]] with self.cached_session(): @@ -47,6 +50,7 @@ class RegexFullMatchOpVariantsTest(test.TestCase, parameterized.TestCase): matched = op(input_tensor, "a.*a").eval() self.assertAllEqual([[True, False], [True, False]], matched) + @test_util.run_deprecated_v1 def testEmptyMatch(self, op): values = ["abc", "1"] with self.cached_session(): @@ -54,6 +58,7 @@ class RegexFullMatchOpVariantsTest(test.TestCase, parameterized.TestCase): matched = op(input_tensor, "").eval() self.assertAllEqual([False, False], matched) + @test_util.run_deprecated_v1 def testInvalidPattern(self, op): values = ["abc", "1"] with self.cached_session(): @@ -61,11 +66,12 @@ class RegexFullMatchOpVariantsTest(test.TestCase, parameterized.TestCase): invalid_pattern = "A[" matched = op(input_tensor, invalid_pattern) with self.assertRaisesOpError("Invalid pattern"): - matched.eval() + self.evaluate(matched) class RegexFullMatchOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testRegexFullMatchDelegation(self): with compat.forward_compatibility_horizon(2018, 11, 1): with self.cached_session(): @@ -78,6 +84,7 @@ class RegexFullMatchOpTest(test.TestCase): op_tensor = string_ops.regex_full_match(input_tensor, pattern_tensor) self.assertTrue(op_tensor.name.startswith("RegexFullMatch"), op.name) + @test_util.run_deprecated_v1 def testStaticRegexFullMatchDelegation(self): with compat.forward_compatibility_horizon(2018, 11, 20): with self.cached_session(): diff --git a/tensorflow/python/kernel_tests/regex_replace_op_test.py b/tensorflow/python/kernel_tests/regex_replace_op_test.py index d9b7ed28d2..6c7dfee7b4 100644 --- a/tensorflow/python/kernel_tests/regex_replace_op_test.py +++ b/tensorflow/python/kernel_tests/regex_replace_op_test.py @@ -22,6 +22,7 @@ from absl.testing import parameterized from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import gen_string_ops from tensorflow.python.ops import string_ops from tensorflow.python.platform import test @@ -32,6 +33,7 @@ from tensorflow.python.platform import test (gen_string_ops.static_regex_replace)) class RegexReplaceOpVariantsTest(test.TestCase, parameterized.TestCase): + @test_util.run_deprecated_v1 def testForwarding(self, op): with self.cached_session(): # Generate an input that is uniquely consumed by the regex op. @@ -45,6 +47,7 @@ class RegexReplaceOpVariantsTest(test.TestCase, parameterized.TestCase): stripped = op(inp, "\\p{Ll}", ".").eval() self.assertAllEqual([b"A.C.E", b"H.J.L"], stripped) + @test_util.run_deprecated_v1 def testRemovePrefix(self, op): values = ["a:foo", "a:bar", "a:foo", "b:baz", "b:qux", "ca:b"] with self.cached_session(): @@ -53,6 +56,7 @@ class RegexReplaceOpVariantsTest(test.TestCase, parameterized.TestCase): self.assertAllEqual([b"foo", b"bar", b"foo", b"baz", b"qux", b"ca:b"], stripped) + @test_util.run_deprecated_v1 def testRegexReplace(self, op): values = ["aba\naba", "abcdabcde"] with self.cached_session(): @@ -60,6 +64,7 @@ class RegexReplaceOpVariantsTest(test.TestCase, parameterized.TestCase): stripped = op(input_vector, "a.*a", "(\\0)").eval() self.assertAllEqual([b"(aba)\n(aba)", b"(abcda)bcde"], stripped) + @test_util.run_deprecated_v1 def testEmptyMatch(self, op): values = ["abc", "1"] with self.cached_session(): @@ -67,6 +72,7 @@ class RegexReplaceOpVariantsTest(test.TestCase, parameterized.TestCase): stripped = op(input_vector, "", "x").eval() self.assertAllEqual([b"xaxbxcx", b"x1x"], stripped) + @test_util.run_deprecated_v1 def testInvalidPattern(self, op): values = ["abc", "1"] with self.cached_session(): @@ -74,8 +80,9 @@ class RegexReplaceOpVariantsTest(test.TestCase, parameterized.TestCase): invalid_pattern = "A[" replace = op(input_vector, invalid_pattern, "x") with self.assertRaisesOpError("Invalid pattern"): - replace.eval() + self.evaluate(replace) + @test_util.run_deprecated_v1 def testGlobal(self, op): values = ["ababababab", "abcabcabc", ""] with self.cached_session(): @@ -98,6 +105,7 @@ class RegexReplaceTest(test.TestCase, parameterized.TestCase): (as_string, as_tensor), (as_tensor, as_string), (as_tensor, as_tensor)) + @test_util.run_deprecated_v1 def testRegexReplaceDelegation(self, pattern_fn, rewrite_fn): with self.cached_session(): input_vector = constant_op.constant("foo", dtypes.string) @@ -106,6 +114,7 @@ class RegexReplaceTest(test.TestCase, parameterized.TestCase): op = string_ops.regex_replace(input_vector, pattern, replace) self.assertTrue(op.name.startswith("RegexReplace")) + @test_util.run_deprecated_v1 def testStaticRegexReplaceDelegation(self): with self.cached_session(): input_vector = constant_op.constant("foo", dtypes.string) diff --git a/tensorflow/python/kernel_tests/relu_op_test.py b/tensorflow/python/kernel_tests/relu_op_test.py index b0f2796ede..55e68f4884 100644 --- a/tensorflow/python/kernel_tests/relu_op_test.py +++ b/tensorflow/python/kernel_tests/relu_op_test.py @@ -25,6 +25,8 @@ from tensorflow.python.compat import compat from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl @@ -55,55 +57,56 @@ class ReluTest(test.TestCase): np.array([[-0.9, 0.7, -0.5, 0.3, -0.1], [0.1, -0.3, 0.5, -0.7, 0.9]]))) - def _testRelu(self, np_features, use_gpu=False): + def _testRelu(self, np_features): np_relu = self._npRelu(np_features) - with self.cached_session(use_gpu=use_gpu): - relu = nn_ops.relu(np_features) - tf_relu = relu.eval() + tf_relu = nn_ops.relu(np_features) self.assertAllClose(np_relu, tf_relu) - self.assertShapeEqual(np_relu, relu) + self.assertShapeEqual(np_relu, tf_relu) - def testNumbers(self): + def testNumbersCPU(self): for t in [np.int32, np.int64, np.float16, np.float32, np.float64]: - self._testRelu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=False) - if t in [np.float16, np.float32, np.float64]: + # Force execution on CPU even if a GPU kernel is available for the type. + with ops.device("/device:CPU:0"): self._testRelu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=True) + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) - def _testReluInt8x4(self, np_inputs): - if not test.is_gpu_available(cuda_only=True): - return - np_relu = self._npRelu(np_inputs) - with self.cached_session(use_gpu=True): - relu = nn_ops.relu(constant_op.constant(np_inputs, dtypes.qint8)) - if np_inputs.size % 4 == 0: - tf_relu = relu.eval() - self.assertAllClose(np_relu, tf_relu) - self.assertShapeEqual(np_relu, relu) - else: - with self.assertRaisesRegexp( - errors.InvalidArgumentError, - "Tensor size must be a multiple of 4 for Relu. Got %d" % - np_inputs.size): - tf_relu = relu.eval() + def testNumbersGPU(self): + if not test.is_gpu_available(): + self.skipTest("No GPU available") + for t in [np.float16, np.float32, np.float64]: + self._testRelu( + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) def testReluInt8x4GoodShape(self): - self._testReluInt8x4(np.array([[-50, 7, 23, 0], [-1, -5, 6, 11]])) + if not test.is_gpu_available(cuda_only=True): + self.skipTest("No GPU available") + inputs = np.array([[-50, 7, 23, 0], [-1, -5, 6, 11]]) + np_relu = self._npRelu(inputs) + tf_relu = nn_ops.relu(constant_op.constant(inputs, dtypes.qint8)) + self.assertAllClose(np_relu, tf_relu) + self.assertShapeEqual(np_relu, tf_relu) def testReluInt8x4BadShape(self): - np_inputs = np.array([[-50, 7, 23], [0, 1, -5], [6, -2, 11]]) - self.assertEqual(np_inputs.size, 9) - self._testReluInt8x4(np_inputs) - np_inputs = np.array( - [1, -2, 3, -4, 5, -6, 7, -8, 9, -8, 7, -6, 5, -4, 3, -2, 1]) - self.assertEqual(np_inputs.size, 17) - self._testReluInt8x4(np_inputs) + if not test.is_gpu_available(cuda_only=True): + self.skipTest("No GPU available") + inputs = constant_op.constant( + np.array([[-50, 7, 23], [0, 1, -5], [6, -2, 11]]), dtypes.qint8) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + "Tensor size must be a multiple of 4 for Relu. Got 9"): + self.evaluate(nn_ops.relu(inputs)) + + inputs = constant_op.constant( + np.array([1, -2, 3, -4, 5, -6, 7, -8, 9, -8, 7, -6, 5, -4, 3, -2, 1]), + dtypes.qint8) + with self.assertRaisesRegexp( + errors.InvalidArgumentError, + "Tensor size must be a multiple of 4 for Relu. Got 17"): + self.evaluate(nn_ops.relu(inputs)) # The gradient test for ReLU is a bit tricky as the derivative is not well # defined at around zero and we want to avoid that in terms of input values. + @test_util.run_deprecated_v1 def testGradientFloat32(self): with self.cached_session(): x = constant_op.constant( @@ -123,6 +126,7 @@ class ReluTest(test.TestCase): # The gradient for fp16 is inaccurate due to the low-precision. # Instead of relying on compute_gradient_error, we compare the fp16 analytical # gradient against their fp32 counterpart. + @test_util.run_deprecated_v1 def testGradientFloat16(self): with self.session(use_gpu=True) as sess: # Randomly construct a 1D shape from [1, 40) @@ -146,9 +150,10 @@ class ReluTest(test.TestCase): # Repeat the experiment for 100 times. All tensor shapes and its tensor # values are randomly generated for each run. for _ in xrange(100): - dx_f32_v, dx_f16_v = sess.run([dx_f32, dx_f16]) + dx_f32_v, dx_f16_v = self.evaluate([dx_f32, dx_f16]) self.assertAllClose(dx_f32_v, dx_f16_v, atol=3e-4) + @test_util.run_deprecated_v1 def testGradientFloat64(self): with self.cached_session(): x = constant_op.constant( @@ -166,6 +171,7 @@ class ReluTest(test.TestCase): print("relu (float64) gradient err = ", err) self.assertLess(err, 1e-10) + @test_util.run_deprecated_v1 def testGradGradFloat32(self): with self.cached_session(): x = constant_op.constant( @@ -183,6 +189,7 @@ class ReluTest(test.TestCase): print("relu (float32) gradient of gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradGradFloat64(self): with self.cached_session(): x = constant_op.constant( @@ -202,15 +209,15 @@ class ReluTest(test.TestCase): self.assertLess(err, 1e-10) def testGradientScalar(self): - with self.cached_session() as sess: - x = variables.Variable(100.) - y = nn_ops.relu(x) - loss = y**2 - optimizer = gradient_descent.GradientDescentOptimizer(learning_rate=0.25) - train_op = optimizer.minimize(loss) - sess.run(variables.global_variables_initializer()) - sess.run(train_op) - self.assertAllClose(x.eval(), 50.0) + x = variables.Variable(100.) + + def loss(): + return nn_ops.relu(x)**2 + + optimizer = gradient_descent.GradientDescentOptimizer(learning_rate=0.25) + self.evaluate(variables.global_variables_initializer()) + self.evaluate(optimizer.minimize(loss)) + self.assertAllClose(x.read_value(), 50.0) class Relu6Test(test.TestCase): @@ -228,27 +235,30 @@ class Relu6Test(test.TestCase): np.array([[-0.9, 0.7, -0.5, 0.3, 6.0], [0.1, -0.3, 6.5, -0.7, 0.9]]))) - def _testRelu6(self, np_features, use_gpu=False): + def _testRelu6(self, np_features): np_relu6 = self._npRelu6(np_features) - with self.cached_session(use_gpu=use_gpu): - relu6 = nn_ops.relu6(np_features) - tf_relu6 = relu6.eval() + tf_relu6 = nn_ops.relu6(np_features) self.assertAllClose(np_relu6, tf_relu6) - self.assertShapeEqual(np_relu6, relu6) + self.assertShapeEqual(np_relu6, tf_relu6) - def testNumbers(self): + def testNumbersCPU(self): for t in [np.int32, np.int64, np.float16, np.float32, np.float64]: - self._testRelu6( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=False) - if t in [np.float16, np.float, np.double]: + # Force execution on CPU even if a GPU kernel is available for the type. + with ops.device("/device:CPU:0"): self._testRelu6( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=True) + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) + + def testNumbersGPU(self): + if not test.is_gpu_available(): + self.skipTest("No GPU available") + for t in [np.float16, np.float, np.double]: + self._testRelu6( + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) # The gradient test for ReLU6 is a bit tricky as the derivative is # not well defined at around zero and six and we want to avoid that # in terms of input values. + @test_util.run_deprecated_v1 def testGradientFloat32(self): with self.cached_session(): x = constant_op.constant( @@ -265,6 +275,7 @@ class Relu6Test(test.TestCase): print("relu6 (float32) gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradientFloat64(self): with self.cached_session(): x = constant_op.constant( @@ -297,29 +308,32 @@ class LeakyReluTest(test.TestCase): 0.9]]), alpha=0.1)) - def _testLeakyRelu(self, np_features, alpha, use_gpu=False): + def _testLeakyRelu(self, np_features, alpha): np_leaky_relu = self._npLeakyRelu(np_features, alpha) - with self.test_session(use_gpu=use_gpu): - leaky_relu = nn_ops.leaky_relu(np_features, alpha) - tf_leaky_relu = leaky_relu.eval() + tf_leaky_relu = nn_ops.leaky_relu(np_features, alpha) self.assertAllClose(np_leaky_relu, tf_leaky_relu) - self.assertShapeEqual(np_leaky_relu, leaky_relu) + self.assertShapeEqual(np_leaky_relu, tf_leaky_relu) - def testNumbers(self): + def testNumbersCPU(self): for t in [np.int32, np.int64, np.float16, np.float32, np.float64]: - self._testLeakyRelu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - alpha=0.2, - use_gpu=False) - if t in [np.float16, np.float32, np.float64]: + # Force execution on CPU even if a GPU kernel is available for the type. + with ops.device("/device:CPU:0"): self._testLeakyRelu( np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - alpha=0.1, - use_gpu=True) + alpha=0.2) + + def testNumbersGPU(self): + if not test.is_gpu_available(): + self.skipTest("No GPU available") + for t in [np.float16, np.float32, np.float64]: + self._testLeakyRelu( + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), + alpha=0.1) # The gradient test for Leaky ReLU is a bit tricky as the derivative is not # well defined at around zero and we want to avoid that in terms of input # values. + @test_util.run_deprecated_v1 def testGradientFloat32(self): with self.test_session(): x = constant_op.constant( @@ -336,6 +350,7 @@ class LeakyReluTest(test.TestCase): print("leaky_relu (float32) gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradientFloat64(self): with self.test_session(): x = constant_op.constant( @@ -353,6 +368,7 @@ class LeakyReluTest(test.TestCase): print("leaky_relu (float64) gradient err = ", err) self.assertLess(err, 1e-10) + @test_util.run_deprecated_v1 def testGradGradFloat32(self): with compat.forward_compatibility_horizon(2018, 11, 2): with self.test_session(): @@ -371,6 +387,7 @@ class LeakyReluTest(test.TestCase): print("leaky_relu (float32) gradient of gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradGradFloat64(self): with compat.forward_compatibility_horizon(2018, 11, 2): with self.test_session(): @@ -391,15 +408,15 @@ class LeakyReluTest(test.TestCase): self.assertLess(err, 1e-10) def testGradientScalar(self): - with self.test_session() as sess: - x = variables.Variable(-100.) - y = nn_ops.leaky_relu(x, 0.05) - loss = y**2 - optimizer = gradient_descent.GradientDescentOptimizer(learning_rate=0.2) - train_op = optimizer.minimize(loss) - sess.run(variables.global_variables_initializer()) - sess.run(train_op) - self.assertAllClose(x.eval(), -99.9) + x = variables.Variable(-100.) + + def loss(): + return nn_ops.leaky_relu(x, 0.05)**2 + + optimizer = gradient_descent.GradientDescentOptimizer(learning_rate=0.2) + self.evaluate(variables.global_variables_initializer()) + self.evaluate(optimizer.minimize(loss)) + self.assertAllClose(x.read_value(), -99.9) class EluTest(test.TestCase): @@ -415,23 +432,26 @@ class EluTest(test.TestCase): np.array([[-0.9, 0.7, -0.5, 0.3, -0.1], [0.1, -0.3, 0.5, -0.7, 0.9]]))) - def _testElu(self, np_features, use_gpu=False): + def _testElu(self, np_features): np_elu = self._npElu(np_features) - with self.cached_session(use_gpu=use_gpu): - elu = nn_ops.elu(np_features) - tf_elu = elu.eval() + tf_elu = nn_ops.elu(np_features) self.assertAllClose(np_elu, tf_elu) - self.assertShapeEqual(np_elu, elu) + self.assertShapeEqual(np_elu, tf_elu) - def testNumbers(self): + def testNumbersCPU(self): for t in [np.float16, np.float32, np.float64]: - self._testElu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=False) - self._testElu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=True) + # Force execution on CPU even if a GPU kernel is available for the type. + with ops.device("/device:CPU:0"): + self._testElu( + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) + + def testNumbersGPU(self): + if not test.is_gpu_available(): + self.skipTest("No GPU available") + for t in [np.float16, np.float32, np.float64]: + self._testElu(np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) + @test_util.run_deprecated_v1 def testGradientFloat32(self): with self.cached_session(): x_val = [[-0.9, -0.7, -0.5, -0.3, -0.1], [0.1, 0.3, 0.5, 0.7, 0.9]] @@ -443,6 +463,7 @@ class EluTest(test.TestCase): print("elu (float32) gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradientFloat64(self): with self.cached_session(): x_val = [[-0.9, -0.7, -0.5, -0.3, -0.1], [0.1, 0.3, 0.5, 0.7, 0.9]] @@ -454,6 +475,7 @@ class EluTest(test.TestCase): print("elu (float64) gradient err = ", err) self.assertLess(err, 1e-6) + @test_util.run_deprecated_v1 def testGradGrad(self): with self.cached_session(): x = array_ops.placeholder(dtype=dtypes.float32) @@ -465,6 +487,7 @@ class EluTest(test.TestCase): err = np.abs(gg.eval(feed_dict={x: x_val}) - _elu_grad_grad(x_val)) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradGradFloat32(self): with self.cached_session(): x = constant_op.constant( @@ -482,6 +505,7 @@ class EluTest(test.TestCase): print("elu (float32) gradient of gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradGradFloat64(self): with self.cached_session(): x = constant_op.constant( @@ -517,23 +541,22 @@ class SeluTest(test.TestCase): np.array([[-0.9, 0.7, -0.5, 0.3, -0.1], [0.1, -0.3, 0.5, -0.7, 0.9]]))) - def _testSelu(self, np_features, use_gpu=False): + def _testSelu(self, np_features): np_selu = self._npSelu(np_features) - with self.cached_session(use_gpu=use_gpu): - selu = nn_ops.selu(np_features) - tf_selu = selu.eval() + tf_selu = nn_ops.selu(np_features) self.assertAllClose(np_selu, tf_selu) - self.assertShapeEqual(np_selu, selu) + self.assertShapeEqual(np_selu, tf_selu) def testNumbers(self): for t in [np.float16, np.float32, np.float64]: self._testSelu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=False) - self._testSelu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=True) + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) + # Force executed on CPU in case GPU kernels are avaiable. + with ops.device("/device:CPU:0"): + self._testSelu( + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) + @test_util.run_deprecated_v1 def testGradientFloat32(self): with self.cached_session(): x_val = [[-0.9, -0.7, -0.5, -0.3, -0.1], [0.1, 0.3, 0.5, 0.7, 0.9]] @@ -545,6 +568,7 @@ class SeluTest(test.TestCase): print("selu (float32) gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradientFloat64(self): with self.cached_session(): x_val = [[-0.9, -0.7, -0.5, -0.3, -0.1], [0.1, 0.3, 0.5, 0.7, 0.9]] @@ -556,6 +580,7 @@ class SeluTest(test.TestCase): print("selu (float64) gradient err = ", err) self.assertLess(err, 1e-6) + @test_util.run_deprecated_v1 def testGradGradFloat32(self): with self.cached_session(): x = constant_op.constant( @@ -573,6 +598,7 @@ class SeluTest(test.TestCase): print("selu (float32) gradient of gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradGradFloat64(self): with self.cached_session(): x = constant_op.constant( @@ -599,46 +625,44 @@ class CreluTest(test.TestCase): t = nn_ops.crelu(f) self.assertEqual([50, 5, 7, 20], t.get_shape()) - def _testCrelu(self, np_features, use_gpu=False): + def _testCrelu(self, np_features): np_relu = np.maximum(np_features, np.zeros_like(np_features)) np_neg_relu = np.maximum(-np_features, np.zeros_like(np_features)) np_crelu = np.concatenate((np_relu, np_neg_relu), len(np_features.shape) - 1) - with self.cached_session(use_gpu=use_gpu): - crelu = nn_ops.crelu(np_features) - tf_relu = crelu.eval() + tf_crelu = nn_ops.crelu(np_features) - self.assertAllClose(np_crelu, tf_relu) - self.assertShapeEqual(np_crelu, crelu) + self.assertAllClose(np_crelu, tf_crelu) + self.assertShapeEqual(np_crelu, tf_crelu) - def testNumbers(self): + def testNumbersCPU(self): for t in [np.int32, np.int64, np.float16, np.float32, np.float64]: - self._testCrelu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=False) - if t in [np.float16, np.float32, np.float64]: + # Force execution on CPU even if a GPU kernel is available for the type. + with ops.device("/device:CPU:0"): self._testCrelu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), - use_gpu=True) + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) + + def testNumbersGPU(self): + if not test.is_gpu_available(): + self.skipTest("No GPU available") + for t in [np.float16, np.float32, np.float64]: + self._testCrelu( + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t)) def testNumbersWithAxis0(self): - with self.cached_session(): - crelu = nn_ops.crelu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]), axis=0) - tf_relu = crelu.eval() - np_crelu = np.array([[0, 7, 0, 3, 0], [1, 0, 5, 0, 9], [9, 0, 5, 0, 1], - [0, 3, 0, 7, 0]]) - self.assertAllEqual(np_crelu, tf_relu) + tf_crelu = nn_ops.crelu( + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]), axis=0) + np_crelu = np.array([[0, 7, 0, 3, 0], [1, 0, 5, 0, 9], [9, 0, 5, 0, 1], + [0, 3, 0, 7, 0]]) + self.assertAllEqual(np_crelu, tf_crelu) def testNumbersWithAxis1(self): - with self.cached_session(): - crelu = nn_ops.crelu( - np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]), axis=1) - tf_relu = crelu.eval() - np_crelu = np.array([[0, 7, 0, 3, 0, 9, 0, 5, 0, 1], - [1, 0, 5, 0, 9, 0, 3, 0, 7, 0]]) - self.assertAllEqual(np_crelu, tf_relu) + tf_crelu = nn_ops.crelu( + np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]), axis=1) + np_crelu = np.array([[0, 7, 0, 3, 0, 9, 0, 5, 0, 1], + [1, 0, 5, 0, 9, 0, 3, 0, 7, 0]]) + self.assertAllEqual(np_crelu, tf_crelu) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/reshape_op_test.py b/tensorflow/python/kernel_tests/reshape_op_test.py index 14cdae1837..db3e88a104 100644 --- a/tensorflow/python/kernel_tests/reshape_op_test.py +++ b/tensorflow/python/kernel_tests/reshape_op_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.platform import test @@ -33,14 +34,14 @@ class ReshapeTest(test.TestCase): with self.cached_session(use_gpu=use_gpu): np_ans = x.reshape(y) tf_ans = array_ops.reshape(x, y) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertEqual(tf_ans.get_shape(), out.shape) self.assertShapeEqual(np_ans, tf_ans) # Repeat with an int64 shape tensor. y64 = constant_op.constant(y, dtype=dtypes.int64) tf_ans = array_ops.reshape(x, y64) - out = tf_ans.eval() + out = self.evaluate(tf_ans) self.assertEqual(tf_ans.get_shape(), out.shape) self.assertShapeEqual(np_ans, tf_ans) @@ -91,6 +92,7 @@ class ReshapeTest(test.TestCase): # TODO(vrv): Add tests for failure conditions once python test_util # reports errors. + @test_util.run_deprecated_v1 def testFloatReshapeGradThreeDimensions(self): x = np.arange(1., 25.).reshape([2, 3, 4]).astype(np.float32) s = list(np.shape(x)) @@ -111,6 +113,7 @@ class ReshapeTest(test.TestCase): self._testBothReshape(x, [0, 0, 0]) self._testBothReshape(x, [1, -1, 5]) + @test_util.run_deprecated_v1 def testErrors(self): y = constant_op.constant(0.0, shape=[23, 29, 31]) with self.assertRaisesRegexp(ValueError, "must be evenly divisible by 17"): @@ -121,6 +124,7 @@ class ReshapeTest(test.TestCase): "Cannot reshape a tensor with 4096 elements"): array_ops.reshape(z, [4095]) + @test_util.run_deprecated_v1 def testPartialShapes(self): x = array_ops.placeholder(dtypes.float32) diff --git a/tensorflow/python/kernel_tests/resource_variable_ops_test.py b/tensorflow/python/kernel_tests/resource_variable_ops_test.py index c8227dc117..b57d9d47aa 100644 --- a/tensorflow/python/kernel_tests/resource_variable_ops_test.py +++ b/tensorflow/python/kernel_tests/resource_variable_ops_test.py @@ -29,6 +29,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_util from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops @@ -53,6 +54,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): # involving objects with __del__ defined. self.assertEqual(0, len(gc.garbage)) + @test_util.run_deprecated_v1 def testHandleDtypeShapeMatch(self): with self.cached_session(): handle = resource_variable_ops.var_handle_op(dtype=dtypes.int32, shape=[]) @@ -122,6 +124,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): # values. self.assertFalse(np.allclose(variable.numpy(), copied_variable.numpy())) + @test_util.run_deprecated_v1 def testGraphDeepCopy(self): with self.cached_session(): init_value = np.ones((4, 4, 4)) @@ -137,6 +140,15 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): self.evaluate(v[0].assign(2.0)) self.assertAllEqual(self.evaluate(v), [2.0, 2.0]) + @test_util.run_in_graph_and_eager_modes + def testVariableShape(self): + v = resource_variable_ops.ResourceVariable([1., 1.]) + self.assertAllEqual( + tensor_util.constant_value( + resource_variable_ops.variable_shape(v.handle)), + [2]) + + @test_util.run_deprecated_v1 def testDifferentAssignGraph(self): with ops.Graph().as_default(): v = resource_variable_ops.ResourceVariable(1.0) @@ -144,16 +156,18 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): v.assign(2.0) # Note: this fails if we run convert_to_tensor on not the # variable graph. + @test_util.run_deprecated_v1 def testFetchHandle(self): with self.cached_session(): handle = resource_variable_ops.var_handle_op( dtype=dtypes.int32, shape=[1], name="foo") self.assertGreater(len(handle.eval()), 0) + @test_util.run_deprecated_v1 def testCachedValueReadBeforeWrite(self): with self.cached_session() as sess: v = resource_variable_ops.ResourceVariable(0.0, caching_device="cpu:0") - sess.run(v.initializer) + self.evaluate(v.initializer) value, _ = sess.run([v, v.assign_add(1.0)]) self.assertAllEqual(value, 0.0) @@ -426,6 +440,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): read = resource_variable_ops.read_variable_op(handle, dtype=dtypes.int32) self.assertEqual(self.evaluate(read), [[6]]) + @test_util.run_deprecated_v1 def testScatterUpdateString(self): handle = resource_variable_ops.var_handle_op( dtype=dtypes.string, shape=[1, 1]) @@ -437,6 +452,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): self.assertEqual(compat.as_bytes(self.evaluate(read)[0][0]), compat.as_bytes("b")) + @test_util.run_deprecated_v1 def testScatterUpdateStringScalar(self): handle = resource_variable_ops.var_handle_op( dtype=dtypes.string, shape=[1, 1]) @@ -456,7 +472,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): # TODO(alive): get this to work in Eager mode. def testGPU(self): - with self.test_session(use_gpu=True): + with test_util.use_gpu(): abc = variable_scope.get_variable( "abc", shape=[1], @@ -491,6 +507,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): initial_value=lambda: 1, constraint=constraint, name="var1") # TODO(alive): how should this work in Eager mode? + @test_util.run_deprecated_v1 def testInitFn(self): with self.cached_session(): v = resource_variable_ops.ResourceVariable( @@ -568,6 +585,21 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): v.load(2.0) self.assertEqual(2.0, self.evaluate(v.value())) + def testToFromProtoCachedValue(self): + with ops.Graph().as_default(): + v_def = resource_variable_ops.ResourceVariable( + initial_value=constant_op.constant(3.0)).to_proto() + v_prime = resource_variable_ops.ResourceVariable(variable_def=v_def) + self.assertTrue(getattr(v_prime, "_cached_value", None) is None) + + other_v_def = resource_variable_ops.ResourceVariable( + caching_device="cpu:0", + initial_value=constant_op.constant(3.0)).to_proto() + other_v_prime = resource_variable_ops.ResourceVariable( + variable_def=other_v_def) + self.assertTrue(other_v_prime._cached_value is not None) + + @test_util.run_deprecated_v1 def testVariableDefInitializedInstances(self): with ops.Graph().as_default(), self.cached_session() as sess: v_def = resource_variable_ops.ResourceVariable( @@ -576,11 +608,11 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): with ops.Graph().as_default(), self.cached_session() as sess: # v describes a VariableDef-based variable without an initial value. v = resource_variable_ops.ResourceVariable(variable_def=v_def) - self.assertEqual(3.0, sess.run(v.initialized_value())) + self.assertEqual(3.0, self.evaluate(v.initialized_value())) # initialized_value should not rerun the initializer_op if the variable # has already been initialized elsewhere. - sess.run(v.assign(1.0)) + self.evaluate(v.assign(1.0)) self.assertEqual(1.0, v.initialized_value().eval()) v_def.ClearField("initial_value_name") @@ -592,7 +624,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): self.assertProtoEquals(v_def, v.to_proto()) # But attempts to use initialized_value will result in errors. with self.assertRaises(ValueError): - sess.run(v.initialized_value()) + self.evaluate(v.initialized_value()) def testTrainableInProto(self): with ops.Graph().as_default(): @@ -623,6 +655,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): value = self.evaluate(v.sparse_read([0, 3, 1, 2])) self.assertAllEqual(init_value[[0, 3, 1, 2], ...], value) + @test_util.run_deprecated_v1 def testToFromProto(self): with self.cached_session(): v = resource_variable_ops.ResourceVariable(1.0) @@ -671,6 +704,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): self.assertEqual(0.0, self.evaluate(v.value())) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testDestroyResource(self): v = resource_variable_ops.ResourceVariable(3.0, name="var0") self.evaluate(variables.global_variables_initializer()) @@ -684,6 +718,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): self.evaluate(resource_variable_ops.destroy_resource_op( handle, ignore_lookup_error=True)) + @test_util.run_deprecated_v1 def testAssignDifferentShapes(self): with self.cached_session() as sess, variable_scope.variable_scope( "foo", use_resource=True): @@ -704,6 +739,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): assign = var.assign(np.zeros(shape=[2, 2])) self.evaluate(assign) + @test_util.run_deprecated_v1 def testDtypeAfterFromProto(self): v = resource_variable_ops.ResourceVariable(2.0) w = resource_variable_ops.ResourceVariable.from_proto(v.to_proto()) @@ -711,6 +747,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): self.assertEqual(v.dtype, w.dtype) # TODO(alive): get caching to work in eager mode. + @test_util.run_deprecated_v1 def testCachingDevice(self): with ops.device("/job:server/task:1"): v = resource_variable_ops.ResourceVariable( @@ -726,6 +763,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): with self.assertRaises(ValueError): _ = w.value().op.get_attr("_class") + @test_util.run_deprecated_v1 def testSharedName(self): with self.cached_session(): v = resource_variable_ops.ResourceVariable(300.0, name="var4") @@ -736,7 +774,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): # Needed in Eager since we get a unique container name by default. container=ops.get_default_graph()._container) w_read = resource_variable_ops.read_variable_op(w, v.dtype.base_dtype) - self.assertEqual(300.0, w_read.eval()) + self.assertEqual(300.0, self.evaluate(w_read)) x = resource_variable_ops.var_handle_op( dtype=v.dtype.base_dtype, shape=v.get_shape(), shared_name="var5", @@ -744,6 +782,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): with self.assertRaisesOpError("Resource .*/var5/.* does not exist"): resource_variable_ops.read_variable_op(x, v.dtype.base_dtype).eval() + @test_util.run_deprecated_v1 def testSharedNameWithNamescope(self): with self.cached_session(): with ops.name_scope("foo"): @@ -772,6 +811,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): "", str(v.sparse_read(array_ops.placeholder(dtypes.int32)).shape)) + @test_util.run_deprecated_v1 def testSetInitialValue(self): with self.cached_session(): # Initialize variable with a value different from the initial value passed @@ -780,6 +820,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): v.initializer.run(feed_dict={v.initial_value: 3.0}) self.assertEqual(3.0, v.value().eval()) + @test_util.run_deprecated_v1 def testControlFlowInitialization(self): """Expects an error if an initializer is in a control-flow scope.""" @@ -916,6 +957,7 @@ class ResourceVariableOpsTest(test_util.TensorFlowTestCase): self.assertAllEqual(self.evaluate(v.assign_add(1)), [1, 2, 3, 4]) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testCopyToGraphUninitialized(self): v = resource_variable_ops.ResourceVariable([0, 1, 2, 3]) copy_to_graph = ops.Graph() diff --git a/tensorflow/python/kernel_tests/reverse_sequence_op_test.py b/tensorflow/python/kernel_tests/reverse_sequence_op_test.py index 56609bd0a5..05307c9834 100644 --- a/tensorflow/python/kernel_tests/reverse_sequence_op_test.py +++ b/tensorflow/python/kernel_tests/reverse_sequence_op_test.py @@ -23,6 +23,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.platform import test @@ -42,12 +43,12 @@ class ReverseSequenceTest(test.TestCase): ans = array_ops.reverse_sequence( x, batch_axis=batch_axis, seq_axis=seq_axis, seq_lengths=seq_lengths) if expected_err_re is None: - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(tf_ans, truth, atol=1e-10) self.assertShapeEqual(truth, ans) else: with self.assertRaisesOpError(expected_err_re): - ans.eval() + self.evaluate(ans) def _testBothReverseSequence(self, x, @@ -107,6 +108,7 @@ class ReverseSequenceTest(test.TestCase): def testComplex128Basic(self): self._testBasic(np.complex128) + @test_util.run_deprecated_v1 def testFloatReverseSequenceGrad(self): x = np.asarray( [[[1, 2, 3, 4], [5, 6, 7, 8]], [[9, 10, 11, 12], [13, 14, 15, 16]], @@ -133,6 +135,7 @@ class ReverseSequenceTest(test.TestCase): print("ReverseSequence gradient error = %g" % err) self.assertLess(err, 1e-8) + @test_util.run_deprecated_v1 def testShapeFunctionEdgeCases(self): t = array_ops.reverse_sequence( array_ops.placeholder( diff --git a/tensorflow/python/kernel_tests/rnn_test.py b/tensorflow/python/kernel_tests/rnn_test.py index 0090b7332f..3bc457f8fb 100644 --- a/tensorflow/python/kernel_tests/rnn_test.py +++ b/tensorflow/python/kernel_tests/rnn_test.py @@ -262,6 +262,7 @@ class RNNTest(test.TestCase): rnn.dynamic_rnn(cell, inputs, dtype=dtypes.float32, sequence_length=[4]) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testTensorArrayStateIsAccepted(self): cell = TensorArrayStateRNNCell() in_eager_mode = context.executing_eagerly() @@ -285,6 +286,7 @@ class RNNTest(test.TestCase): self.assertAllEqual(4, state[0]) self.assertAllEqual([[[1]], [[2]], [[3]], [[4]]], state[1]) + @test_util.run_deprecated_v1 def testCellGetInitialState(self): cell = rnn_cell_impl.BasicRNNCell(5) with self.assertRaisesRegexp( @@ -345,6 +347,7 @@ class RNNTest(test.TestCase): self._assert_cell_builds(contrib_rnn.IndyLSTMCell, f32, 5, 7, 3) self._assert_cell_builds(contrib_rnn.IndyLSTMCell, f64, 5, 7, 3) + @test_util.run_deprecated_v1 def testRNNWithKerasSimpleRNNCell(self): with self.cached_session() as sess: input_shape = 10 @@ -378,6 +381,7 @@ class RNNTest(test.TestCase): self.assertEqual(len(outputs), batch) self.assertEqual(len(state), batch) + @test_util.run_deprecated_v1 def testRNNWithKerasGRUCell(self): with self.cached_session() as sess: input_shape = 10 @@ -411,6 +415,7 @@ class RNNTest(test.TestCase): self.assertEqual(len(outputs), batch) self.assertEqual(len(state), batch) + @test_util.run_deprecated_v1 def testRNNWithKerasLSTMCell(self): with self.cached_session() as sess: input_shape = 10 @@ -448,6 +453,7 @@ class RNNTest(test.TestCase): self.assertEqual(len(state[0]), batch) self.assertEqual(len(state[1]), batch) + @test_util.run_deprecated_v1 def testRNNWithStackKerasCell(self): with self.cached_session() as sess: input_shape = 10 @@ -491,6 +497,7 @@ class RNNTest(test.TestCase): for s in state: self.assertEqual(len(s), batch) + @test_util.run_deprecated_v1 def testStaticRNNWithKerasSimpleRNNCell(self): with self.cached_session() as sess: input_shape = 10 @@ -529,6 +536,7 @@ class RNNTest(test.TestCase): self.assertEqual(len(outputs[0]), batch) self.assertEqual(len(state), batch) + @test_util.run_deprecated_v1 def testKerasAndTFRNNLayerOutputComparison(self): input_shape = 10 output_shape = 5 @@ -562,6 +570,7 @@ class RNNTest(test.TestCase): self.assertAllClose(tf_out, k_out) self.assertAllClose(tf_state, k_state) + @test_util.run_deprecated_v1 def testSimpleRNNCellAndBasicRNNCellComparison(self): input_shape = 10 output_shape = 5 @@ -601,6 +610,7 @@ class RNNTest(test.TestCase): self.assertAllClose(tf_out, k_out, atol=1e-5) self.assertAllClose(tf_state, k_state, atol=1e-5) + @test_util.run_deprecated_v1 def testBasicLSTMCellInterchangeWithLSTMCell(self): with self.session(graph=ops_lib.Graph()) as sess: basic_cell = rnn_cell_impl.BasicLSTMCell(1) diff --git a/tensorflow/python/kernel_tests/save_restore_ops_test.py b/tensorflow/python/kernel_tests/save_restore_ops_test.py index cb9aa1e34d..fecc9a3800 100644 --- a/tensorflow/python/kernel_tests/save_restore_ops_test.py +++ b/tensorflow/python/kernel_tests/save_restore_ops_test.py @@ -17,14 +17,30 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import os + from tensorflow.core.protobuf import config_pb2 from tensorflow.python.client import session +from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import gen_io_ops from tensorflow.python.ops import io_ops from tensorflow.python.platform import test +class SaveTest(test.TestCase): + + @test_util.run_in_graph_and_eager_modes + def testRelativePath(self): + os.chdir(self.get_temp_dir()) + self.evaluate(io_ops.save_v2( + "ckpt", ["x"], [""], [constant_op.constant(100.)])) + self.assertAllEqual([100.], + self.evaluate(io_ops.restore_v2( + "ckpt", ["x"], [""], [dtypes.float32]))) + + class ShardedFileOpsTest(test.TestCase): def testShardedFileName(self): @@ -39,6 +55,7 @@ class ShardedFileOpsTest(test.TestCase): class ShapeInferenceTest(test.TestCase): + @test_util.run_deprecated_v1 def testRestoreV2WithSliceInput(self): op = io_ops.restore_v2("model", ["var1", "var2"], ["", "3 4 0,1:-"], [dtypes.float32, dtypes.float32]) @@ -46,11 +63,13 @@ class ShapeInferenceTest(test.TestCase): self.assertFalse(op[0].get_shape().is_fully_defined()) self.assertEqual([1, 4], op[1].get_shape()) + @test_util.run_deprecated_v1 def testRestoreV2NumSlicesNotMatch(self): with self.assertRaises(ValueError): io_ops.restore_v2("model", ["var1", "var2", "var3"], ["", "3 4 0,1:-"], [dtypes.float32, dtypes.float32]) + @test_util.run_deprecated_v1 def testRestoreSlice(self): op = gen_io_ops.restore_slice("model", "var", "3 4 0,1:-", dtypes.float32) self.assertEqual([1, 4], op.get_shape()) diff --git a/tensorflow/python/kernel_tests/scan_ops_test.py b/tensorflow/python/kernel_tests/scan_ops_test.py index b369222565..33e491fee1 100644 --- a/tensorflow/python/kernel_tests/scan_ops_test.py +++ b/tensorflow/python/kernel_tests/scan_ops_test.py @@ -24,6 +24,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -88,12 +89,14 @@ class CumsumTest(test.TestCase): for reverse in [True, False]: self._compare(x, axis, exclusive, reverse) + @test_util.run_deprecated_v1 def testEmpty(self): for dtype in self.valid_dtypes: x = np.zeros([0]).astype(dtype) for axis in (-1, 0): self._compareAll(x, axis) + @test_util.run_deprecated_v1 def testAxisType(self): for dtype in self.valid_dtypes: x = np.arange(1, 6).reshape([5]).astype(dtype) @@ -102,30 +105,40 @@ class CumsumTest(test.TestCase): axis = constant_op.constant(0, axis_dtype) tf_out = math_ops.cumsum(x, axis).eval() + @test_util.run_deprecated_v1 def test1D(self): for dtype in self.valid_dtypes: x = np.arange(1, 6).reshape([5]).astype(dtype) for axis in (-1, 0): self._compareAll(x, axis) + @test_util.run_deprecated_v1 def test2D(self): for dtype in self.valid_dtypes: x = np.arange(0, 10).reshape([2, 5]).astype(dtype) for axis in (-2, -1, 0, 1): self._compareAll(x, axis) + @test_util.run_deprecated_v1 def test3D(self): for dtype in self.valid_dtypes: x = np.arange(0, 20).reshape([2, 2, 5]).astype(dtype) for axis in (-3, -2, -1, 0, 1, 2): self._compareAll(x, axis) + @test_util.run_deprecated_v1 def test6D(self): for dtype in self.valid_dtypes: x = np.arange(1, 145).reshape([2, 2, 3, 3, 2, 2]).astype(dtype) for axis in range(-6, 6, 3): self._compareAll(x, axis) + @test_util.run_deprecated_v1 + def testLarge(self): + for dtype in self.valid_dtypes: + x = np.ones([1000000], dtype=dtype) / 1024 + self._compareAll(x, 0) + def testInvalidAxis(self): x = np.arange(0, 10).reshape([2, 5]).astype(np.float32) input_tensor = ops.convert_to_tensor(x) @@ -152,22 +165,27 @@ class CumsumTest(test.TestCase): t, shape, result, shape, x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testGradient(self): for axis in (-1, 0): self._compareGradient([50], axis, False, False) + @test_util.run_deprecated_v1 def testGradientReverse(self): for axis in (-1, 0): self._compareGradient([50], axis, False, True) + @test_util.run_deprecated_v1 def testGradientExclusive(self): for axis in (-1, 0): self._compareGradient([50], axis, True, False) + @test_util.run_deprecated_v1 def testGradientExclusiveReverse(self): for axis in (-1, 0): self._compareGradient([50], axis, True, True) + @test_util.run_deprecated_v1 def testGradient2D(self): for axis in (-1, 0, 1): for exclusive in [True, False]: @@ -194,12 +212,14 @@ class CumprodTest(test.TestCase): for reverse in [True, False]: self._compare(x, axis, exclusive, reverse) + @test_util.run_deprecated_v1 def testEmpty(self): for dtype in self.valid_dtypes: x = np.zeros([0]).astype(dtype) for axis in (-1, 0): self._compareAll(x, axis) + @test_util.run_deprecated_v1 def testAxisType(self): for dtype in self.valid_dtypes: x = np.arange(1, 6).reshape([5]).astype(dtype) @@ -208,24 +228,28 @@ class CumprodTest(test.TestCase): axis = constant_op.constant(0, axis_dtype) tf_out = math_ops.cumprod(x, axis).eval() + @test_util.run_deprecated_v1 def test1D(self): for dtype in self.valid_dtypes: x = np.arange(1, 6).reshape([5]).astype(dtype) for axis in (-1, 0): self._compareAll(x, axis) + @test_util.run_deprecated_v1 def test2D(self): for dtype in self.valid_dtypes: x = np.arange(1, 11).reshape([2, 5]).astype(dtype) for axis in (-2, -1, 0, 1): self._compareAll(x, axis) + @test_util.run_deprecated_v1 def test3D(self): for dtype in self.valid_dtypes: x = np.arange(1, 21).reshape([2, 2, 5]).astype(dtype) for axis in (-3, -2, -1, 0, 1, 2): self._compareAll(x, axis) + @test_util.run_deprecated_v1 def test6D(self): for dtype in self.valid_dtypes: x = np.arange(1, 145).reshape([2, 2, 3, 3, 2, 2]).astype(dtype) @@ -258,22 +282,27 @@ class CumprodTest(test.TestCase): t, shape, result, shape, x_init_value=x, delta=1) self.assertAllClose(jacob_t, jacob_n, rtol=1e-8, atol=1e-8) + @test_util.run_deprecated_v1 def testGradient(self): for axis in (-1, 0): self._compareGradient([8], axis, False, False) + @test_util.run_deprecated_v1 def testGradientReverse(self): for axis in (-1, 0): self._compareGradient([8], axis, False, True) + @test_util.run_deprecated_v1 def testGradientExclusive(self): for axis in (-1, 0): self._compareGradient([8], axis, True, False) + @test_util.run_deprecated_v1 def testGradientExclusiveReverse(self): for axis in (-1, 0): self._compareGradient([8], axis, True, True) + @test_util.run_deprecated_v1 def testGradient2D(self): for axis in (-2, -1, 0, 1): for exclusive in [True, False]: diff --git a/tensorflow/python/kernel_tests/scatter_nd_ops_test.py b/tensorflow/python/kernel_tests/scatter_nd_ops_test.py index 0ed508b9fe..c1241ba87e 100644 --- a/tensorflow/python/kernel_tests/scatter_nd_ops_test.py +++ b/tensorflow/python/kernel_tests/scatter_nd_ops_test.py @@ -29,6 +29,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import state_ops @@ -144,7 +145,7 @@ class StatefulScatterNdTest(test.TestCase): tf_scatter(ref_var, indices, updates).eval() # Compare - self.assertAllClose(new, ref_var.eval()) + self.assertAllClose(new, self.evaluate(ref_var)) def _VariableRankTests(self, np_scatter, tf_scatter): for vtype in (np.int32, np.float16, np.float32, np.float64, np.complex64, @@ -161,10 +162,11 @@ class StatefulScatterNdTest(test.TestCase): init = variables.global_variables_initializer() with self.session(use_gpu=True) as sess: - sess.run(init) - result = sess.run(scatter) + self.evaluate(init) + result = self.evaluate(scatter) self.assertAllClose(result, expected) + @test_util.run_deprecated_v1 def testSimpleResource(self): indices = constant_op.constant([[4], [3], [1], [7]], dtype=dtypes.int32) updates = constant_op.constant([9, 10, 11, 12], dtype=dtypes.float32) @@ -175,8 +177,8 @@ class StatefulScatterNdTest(test.TestCase): init = variables.global_variables_initializer() with self.session(use_gpu=True) as sess: - sess.run(init) - sess.run(scatter) + self.evaluate(init) + self.evaluate(scatter) self.assertAllClose(ref.eval(), expected) def testSimple2(self): @@ -189,8 +191,8 @@ class StatefulScatterNdTest(test.TestCase): init = variables.global_variables_initializer() with self.session(use_gpu=True) as sess: - sess.run(init) - result = sess.run(scatter) + self.evaluate(init) + result = self.evaluate(scatter) self.assertAllClose(result, expected) def testSimple3(self): @@ -203,16 +205,19 @@ class StatefulScatterNdTest(test.TestCase): init = variables.global_variables_initializer() with self.session(use_gpu=True) as sess: - sess.run(init) - result = sess.run(scatter) + self.evaluate(init) + result = self.evaluate(scatter) self.assertAllClose(result, expected) + @test_util.run_deprecated_v1 def testVariableRankUpdate(self): self._VariableRankTests(_NumpyUpdate, state_ops.scatter_nd_update) + @test_util.run_deprecated_v1 def testVariableRankAdd(self): self._VariableRankTests(_NumpyAdd, state_ops.scatter_nd_add) + @test_util.run_deprecated_v1 def testVariableRankSub(self): self._VariableRankTests(_NumpySub, state_ops.scatter_nd_sub) @@ -230,6 +235,7 @@ class StatefulScatterNdTest(test.TestCase): self._VariableRankTest( np_scatter, tf_scatter, vtype, itype, repeat_indices=True) + @test_util.run_deprecated_v1 def testScatterRepeatIndices(self): """This tests scatter_add using indices that repeat.""" self._ScatterRepeatIndicesTest(_NumpyAdd, state_ops.scatter_nd_add) @@ -249,8 +255,9 @@ class StatefulScatterNdTest(test.TestCase): # [[0]], dtype=tf.int64), [False]) # var.initializer.run() # session.run([update0, update1]) - # self.assertAllEqual([False, True], var.eval()) + # self.assertAllEqual([False, True], self.evaluate(var)) + @test_util.run_deprecated_v1 def testScatterOutOfRangeCpu(self): # TODO(simister): Re-enable once binary size increase due to # scatter_nd ops is under control. @@ -287,6 +294,7 @@ class StatefulScatterNdTest(test.TestCase): state_ops.scatter_nd_update(ref, indices, updates).get_shape().as_list(), shape) + @test_util.run_deprecated_v1 def testResVarInvalidOutputShape(self): res = variables.Variable( initial_value=lambda: array_ops.zeros(shape=[], dtype=dtypes.float32), @@ -296,6 +304,7 @@ class StatefulScatterNdTest(test.TestCase): with self.assertRaisesOpError("Output must be at least 1-D"): state_ops.scatter_nd_update(res, [[0]], [0.22]).eval() + @test_util.run_deprecated_v1 def testExtraIndicesDimensions(self): indices = array_ops.zeros([1, 1, 2], dtypes.int32) updates = array_ops.zeros([1, 1], dtypes.int32) @@ -307,8 +316,9 @@ class StatefulScatterNdTest(test.TestCase): expected_result = np.zeros([2, 2], dtype=np.int32) with self.cached_session(): ref.initializer.run() - self.assertAllEqual(expected_result, scatter_update.eval()) + self.assertAllEqual(expected_result, self.evaluate(scatter_update)) + @test_util.run_deprecated_v1 def testRank3InvalidShape1(self): indices = array_ops.zeros([3, 2, 2], dtypes.int32) updates = array_ops.zeros([2, 2, 2], dtypes.int32) @@ -318,6 +328,7 @@ class StatefulScatterNdTest(test.TestCase): ValueError, "The outer \\d+ dimensions of indices\\.shape="): state_ops.scatter_nd_update(ref, indices, updates) + @test_util.run_deprecated_v1 def testRank3InvalidShape2(self): indices = array_ops.zeros([2, 2, 1], dtypes.int32) updates = array_ops.zeros([2, 2], dtypes.int32) @@ -327,6 +338,7 @@ class StatefulScatterNdTest(test.TestCase): ValueError, "The inner \\d+ dimensions of input\\.shape="): state_ops.scatter_nd_update(ref, indices, updates) + @test_util.run_deprecated_v1 def testConcurrentUpdates(self): num_updates = 10000 update_values = np.random.rand(num_updates) @@ -341,8 +353,8 @@ class StatefulScatterNdTest(test.TestCase): init = variables.global_variables_initializer() with session.Session() as sess: - sess.run(init) - result = sess.run(scatter) + self.evaluate(init) + result = self.evaluate(scatter) assert np.allclose(result, expected_result) # TODO(fpmc): Re-enable this test when gpu_pip test actually runs on a GPU. @@ -421,7 +433,7 @@ class ScatterNdTest(test.TestCase): b"", b"", b"seven"]) scatter = self.scatter_nd(indices, updates, shape=(8,)) with self.cached_session() as sess: - result = sess.run(scatter) + result = self.evaluate(scatter) self.assertAllEqual(expected, result) # Same indice is updated twice by same value. @@ -432,7 +444,7 @@ class ScatterNdTest(test.TestCase): expected = np.array([b"", b"", b"", b"bb", b"a", b"", b"", b"c"]) scatter = self.scatter_nd(indices, updates, shape=(8,)) with self.cached_session() as sess: - result = sess.run(scatter) + result = self.evaluate(scatter) self.assertAllEqual(expected, result) # Same indice is updated twice by different value. @@ -444,7 +456,7 @@ class ScatterNdTest(test.TestCase): np.array([b"", b"", b"", b"cb", b"a", b"", b"", b"d"])] scatter = self.scatter_nd(indices, updates, shape=(8,)) with self.cached_session() as sess: - result = sess.run(scatter) + result = self.evaluate(scatter) self.assertTrue(np.array_equal(result, expected[0]) or np.array_equal(result, expected[1])) @@ -455,6 +467,7 @@ class ScatterNdTest(test.TestCase): self.assertAllEqual( self.scatter_nd(indices, updates, shape).get_shape().as_list(), shape) + @test_util.run_deprecated_v1 def testExtraIndicesDimensions(self): indices = array_ops.zeros([1, 1, 2], dtypes.int32) updates = array_ops.zeros([1, 1], dtypes.int32) @@ -463,26 +476,30 @@ class ScatterNdTest(test.TestCase): self.assertAllEqual(scatter.get_shape().as_list(), shape) expected_result = np.zeros([2, 2], dtype=np.int32) with self.cached_session(): - self.assertAllEqual(expected_result, scatter.eval()) + self.assertAllEqual(expected_result, self.evaluate(scatter)) + @test_util.run_deprecated_v1 def testUndefinedIndicesShape(self): indices = array_ops.placeholder(dtypes.int32, shape=None) updates = array_ops.placeholder(dtypes.int32, shape=[2, 2, 2]) shape = constant_op.constant([2, 2, 2], dtypes.int32) self.scatter_nd(indices, updates, shape) + @test_util.run_deprecated_v1 def testUndefinedUpdatesShape(self): indices = array_ops.placeholder(dtypes.int32, shape=[2, 2, 2]) updates = array_ops.placeholder(dtypes.int32, shape=None) shape = constant_op.constant([2, 2, 2], dtypes.int32) self.scatter_nd(indices, updates, shape) + @test_util.run_deprecated_v1 def testUndefinedOutputShape(self): indices = array_ops.placeholder(dtypes.int32, shape=[2, 2, 2]) updates = array_ops.placeholder(dtypes.int32, shape=[2, 2, 2]) shape = array_ops.placeholder(dtypes.int32, shape=[None]) self.scatter_nd(indices, updates, shape) + @test_util.run_deprecated_v1 def testEmptyOutputShape1(self): indices = array_ops.zeros([2, 2, 2], dtypes.int32) updates = array_ops.zeros([2, 2, 2], dtypes.int32) @@ -492,6 +509,7 @@ class ScatterNdTest(test.TestCase): ValueError, "Indices and updates specified for empty output shape"): self.scatter_nd(indices, updates, shape) + @test_util.run_deprecated_v1 def testEmptyOutputShape2(self): indices = array_ops.placeholder(dtypes.int32, shape=None) updates = array_ops.placeholder(dtypes.int32, shape=None) @@ -505,6 +523,7 @@ class ScatterNdTest(test.TestCase): updates: np.zeros([2, 2, 2], dtype=np.int32) }) + @test_util.run_deprecated_v1 def testEmptyOutputShape3(self): indices = array_ops.zeros([0], dtypes.int32) updates = array_ops.zeros([0], dtypes.int32) @@ -514,6 +533,7 @@ class ScatterNdTest(test.TestCase): with self.cached_session(): self.assertEqual(scatter.eval().size, 0) + @test_util.run_deprecated_v1 def testRank3InvalidShape1(self): indices = array_ops.zeros([3, 2, 2], dtypes.int32) updates = array_ops.zeros([2, 2, 2], dtypes.int32) @@ -522,6 +542,7 @@ class ScatterNdTest(test.TestCase): ValueError, "The outer \\d+ dimensions of indices\\.shape="): self.scatter_nd(indices, updates, shape) + @test_util.run_deprecated_v1 def testRank3InvalidShape2(self): indices = array_ops.zeros([2, 2, 1], dtypes.int32) updates = array_ops.zeros([2, 2], dtypes.int32) @@ -530,6 +551,7 @@ class ScatterNdTest(test.TestCase): ValueError, "The inner \\d+ dimensions of (input|output)\\.shape="): self.scatter_nd(indices, updates, shape) + @test_util.run_deprecated_v1 def testGradientsRank2ElementUpdate(self): for dtype in GRADIENT_TESTS_DTYPES: indices = constant_op.constant([[0, 0], [1, 1]], dtype=dtypes.int32) @@ -545,10 +567,11 @@ class ScatterNdTest(test.TestCase): expected_input_grad = np.array([[1, 2], [3, 4]], dtype=dtype.as_numpy_dtype()) with self.cached_session(): - self.assertAllEqual(expected_updates_grad, updates_grad.eval()) + self.assertAllEqual(expected_updates_grad, self.evaluate(updates_grad)) if self.non_aliasing_add_test: - self.assertAllEqual(expected_input_grad, input_grad.eval()) + self.assertAllEqual(expected_input_grad, self.evaluate(input_grad)) + @test_util.run_deprecated_v1 def testGradientsRank2SliceUpdate(self): for dtype in GRADIENT_TESTS_DTYPES: indices = constant_op.constant([[1], [0]], dtype=dtypes.int32) @@ -565,10 +588,11 @@ class ScatterNdTest(test.TestCase): expected_input_grad = np.array([[3, 4], [1, 2]], dtype=dtype.as_numpy_dtype()) with self.cached_session(): - self.assertAllEqual(expected_updates_grad, updates_grad.eval()) + self.assertAllEqual(expected_updates_grad, self.evaluate(updates_grad)) if self.non_aliasing_add_test: - self.assertAllEqual(expected_input_grad, input_grad.eval()) + self.assertAllEqual(expected_input_grad, self.evaluate(input_grad)) + @test_util.run_deprecated_v1 def testGradientsRank3SliceUpdate(self): for dtype in GRADIENT_TESTS_DTYPES: indices = constant_op.constant([[[0, 1], [1, 0]], [[0, 0], [1, 1]]], @@ -588,10 +612,11 @@ class ScatterNdTest(test.TestCase): expected_input_grad = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]], dtype=dtype.as_numpy_dtype()) with self.cached_session(): - self.assertAllEqual(expected_updates_grad, updates_grad.eval()) + self.assertAllEqual(expected_updates_grad, self.evaluate(updates_grad)) if self.non_aliasing_add_test: - self.assertAllEqual(expected_input_grad, input_grad.eval()) + self.assertAllEqual(expected_input_grad, self.evaluate(input_grad)) + @test_util.run_deprecated_v1 def testGradientsRank7SliceUpdate(self): for dtype in GRADIENT_TESTS_DTYPES: indices = constant_op.constant( @@ -615,10 +640,11 @@ class ScatterNdTest(test.TestCase): [[[[[[[1, 2], [3, 4]]]], [[[[5, 6], [7, 8]]]]]]], dtype=dtype.as_numpy_dtype()) with self.cached_session(): - self.assertAllEqual(expected_updates_grad, updates_grad.eval()) + self.assertAllEqual(expected_updates_grad, self.evaluate(updates_grad)) if self.non_aliasing_add_test: - self.assertAllEqual(expected_input_grad, input_grad.eval()) + self.assertAllEqual(expected_input_grad, self.evaluate(input_grad)) + @test_util.run_deprecated_v1 def testScatterNdRepatedIndicesAdd(self): indices = array_ops.zeros([100000, 1], dtypes.int32) values = np.random.randn(100000) @@ -627,6 +653,7 @@ class ScatterNdTest(test.TestCase): val = self.scatter_nd(indices, values, shape).eval() self.assertAllClose([np.sum(values)], val) + @test_util.run_deprecated_v1 def testSmokeScatterNdBatch2DSliceDim2(self): with self.cached_session(): indices = array_ops.zeros([3, 5, 2], dtype=dtypes.int32) @@ -634,6 +661,7 @@ class ScatterNdTest(test.TestCase): shape = [4, 6, 7] self.scatter_nd(indices, values, shape).eval() + @test_util.run_deprecated_v1 def testSmokeScatterNdBatch1DSliceDim2(self): with self.cached_session(): indices = array_ops.zeros([0, 2], dtype=dtypes.int32) @@ -641,6 +669,7 @@ class ScatterNdTest(test.TestCase): shape = [4, 6, 7] self.scatter_nd(indices, values, shape).eval() + @test_util.run_deprecated_v1 def testSmokeScatterNdBatch1DSliceDim3ShapeRank7(self): with self.cached_session(): indices = array_ops.zeros([1, 3], dtype=dtypes.int32) @@ -648,6 +677,7 @@ class ScatterNdTest(test.TestCase): shape = [3, 4, 5, 6, 7, 8, 9] self.scatter_nd(indices, values, shape).eval() + @test_util.run_deprecated_v1 def testSmokeScatterNdBatch2DSliceDim3ShapeRank7(self): with self.cached_session(): indices = array_ops.zeros([1, 2, 3], dtype=dtypes.int32) @@ -669,5 +699,55 @@ class ScatterNdNonAliasingAddTest(ScatterNdTest): pass +class ScatterNdTensorTest(test.TestCase): + + @test_util.run_in_graph_and_eager_modes + def testUpdateAddSub(self): + indices = constant_op.constant([[4], [3], [1], [7]]) + updates = constant_op.constant([9, 10, 11, 12], dtype=dtypes.float32) + t = array_ops.ones([8], dtype=dtypes.float32) + assigned = array_ops.tensor_scatter_update(t, indices, updates) + added = array_ops.tensor_scatter_add(t, indices, updates) + subbed = array_ops.tensor_scatter_sub(t, indices, updates) + + self.assertAllEqual(assigned, + constant_op.constant([1, 11, 1, 10, 9, 1, 1, 12])) + self.assertAllEqual(added, + constant_op.constant([1, 12, 1, 11, 10, 1, 1, 13])) + self.assertAllEqual(subbed, + constant_op.constant([1, -10, 1, -9, -8, 1, 1, -11])) + + def testUpdateAddSubGradients(self): + + with self.cached_session(): + indices = constant_op.constant([[3], [1]]) + updates = constant_op.constant([9, 10], dtype=dtypes.float32) + x = array_ops.ones([4], dtype=dtypes.float32) + + assigned = array_ops.tensor_scatter_update(x, indices, updates) + added = array_ops.tensor_scatter_add(x, indices, updates) + subbed = array_ops.tensor_scatter_sub(x, indices, updates) + + err_assigned = gradient_checker.compute_gradient_error( + x, [4], assigned, [4]) + err_added = gradient_checker.compute_gradient_error(x, [4], added, [4]) + err_subbed = gradient_checker.compute_gradient_error(x, [4], subbed, [4]) + + self.assertLess(err_assigned, 2e-4) + self.assertLess(err_added, 2e-4) + self.assertLess(err_subbed, 2e-4) + + err_assigned_wrt_updates = gradient_checker.compute_gradient_error( + updates, [2], assigned, [4]) + err_added_wrt_updates = gradient_checker.compute_gradient_error( + updates, [2], added, [4]) + err_subbed_wrt_updates = gradient_checker.compute_gradient_error( + updates, [2], subbed, [4]) + + self.assertLess(err_assigned_wrt_updates, 2e-4) + self.assertLess(err_added_wrt_updates, 2e-4) + self.assertLess(err_subbed_wrt_updates, 2e-4) + + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/kernel_tests/scatter_ops_test.py b/tensorflow/python/kernel_tests/scatter_ops_test.py index 87c345245c..623c17d373 100644 --- a/tensorflow/python/kernel_tests/scatter_ops_test.py +++ b/tensorflow/python/kernel_tests/scatter_ops_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import state_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test @@ -196,84 +197,111 @@ class ScatterTest(test.TestCase): self._VariableRankTest(tf_scatter, vtype, itype, repeat_indices, updates_are_scalar) + @test_util.run_deprecated_v1 def testVariableRankUpdate(self): self._VariableRankTests(state_ops.scatter_update, False) + @test_util.run_deprecated_v1 def testVariableRankAdd(self): self._VariableRankTests(state_ops.scatter_add, False) + @test_util.run_deprecated_v1 def testVariableRankSub(self): self._VariableRankTests(state_ops.scatter_sub, False) + @test_util.run_deprecated_v1 def testVariableRankMul(self): self._VariableRankTests(state_ops.scatter_mul, False) + @test_util.run_deprecated_v1 def testVariableRankDiv(self): self._VariableRankTests(state_ops.scatter_div, False) + @test_util.run_deprecated_v1 def testVariableRankMin(self): self._VariableRankTests(state_ops.scatter_min, False) + @test_util.run_deprecated_v1 def testVariableRankMax(self): self._VariableRankTests(state_ops.scatter_max, False) + @test_util.run_deprecated_v1 def testRepeatIndicesAdd(self): self._VariableRankTests(state_ops.scatter_add, True) + @test_util.run_deprecated_v1 def testRepeatIndicesSub(self): self._VariableRankTests(state_ops.scatter_sub, True) + @test_util.run_deprecated_v1 def testRepeatIndicesMul(self): self._VariableRankTests(state_ops.scatter_mul, True) + @test_util.run_deprecated_v1 def testRepeatIndicesDiv(self): self._VariableRankTests(state_ops.scatter_div, True) + @test_util.run_deprecated_v1 def testRepeatIndicesMin(self): self._VariableRankTests(state_ops.scatter_min, True) + @test_util.run_deprecated_v1 def testRepeatIndicesMax(self): self._VariableRankTests(state_ops.scatter_max, True) + @test_util.run_deprecated_v1 def testVariableRankUpdateScalar(self): self._VariableRankTests(state_ops.scatter_update, False, True) + @test_util.run_deprecated_v1 def testVariableRankAddScalar(self): self._VariableRankTests(state_ops.scatter_add, False, True) + @test_util.run_deprecated_v1 def testVariableRankSubScalar(self): self._VariableRankTests(state_ops.scatter_sub, False, True) + @test_util.run_deprecated_v1 def testVariableRankMulScalar(self): self._VariableRankTests(state_ops.scatter_mul, False, True) + @test_util.run_deprecated_v1 def testVariableRankDivScalar(self): self._VariableRankTests(state_ops.scatter_div, False, True) + @test_util.run_deprecated_v1 def testVariableRankMinScalar(self): self._VariableRankTests(state_ops.scatter_min, False, True) + @test_util.run_deprecated_v1 def testVariableRankMaxScalar(self): self._VariableRankTests(state_ops.scatter_max, False, True) + @test_util.run_deprecated_v1 def testRepeatIndicesAddScalar(self): self._VariableRankTests(state_ops.scatter_add, True, True) + @test_util.run_deprecated_v1 def testRepeatIndicesSubScalar(self): self._VariableRankTests(state_ops.scatter_sub, True, True) + @test_util.run_deprecated_v1 def testRepeatIndicesMulScalar(self): self._VariableRankTests(state_ops.scatter_mul, True, True) + @test_util.run_deprecated_v1 def testRepeatIndicesDivScalar(self): self._VariableRankTests(state_ops.scatter_div, True, True) + @test_util.run_deprecated_v1 def testRepeatIndicesMinScalar(self): self._VariableRankTests(state_ops.scatter_min, True, True) + @test_util.run_deprecated_v1 def testRepeatIndicesMaxScalar(self): self._VariableRankTests(state_ops.scatter_max, True, True) + @test_util.run_deprecated_v1 def testBooleanScatterUpdate(self): if not test.is_gpu_available(): with self.session(use_gpu=False) as session: @@ -286,8 +314,9 @@ class ScatterTest(test.TestCase): session.run([update0, update1]) - self.assertAllEqual([False, True], var.eval()) + self.assertAllEqual([False, True], self.evaluate(var)) + @test_util.run_deprecated_v1 def testScatterOutOfRangeCpu(self): for op, _ in _TF_OPS_TO_NUMPY.items(): params = np.array([1, 2, 3, 4, 5, 6]).astype(np.float32) @@ -320,19 +349,19 @@ class ScatterTest(test.TestCase): updates = np.array([-3, -4, -5]).astype(np.float32) # With GPU, the code ignores indices that are out of range. # We don't test the implementation; just test there's no failures. - with self.cached_session(force_gpu=True): + with test_util.force_gpu(): ref = variables.Variable(params) ref.initializer.run() # Indices all in range, no problem. indices = np.array([2, 0, 5]) - op(ref, indices, updates).eval() + self.evaluate(op(ref, indices, updates)) # Indicies out of range should not fail. indices = np.array([-1, 0, 5]) - op(ref, indices, updates).eval() + self.evaluate(op(ref, indices, updates)) indices = np.array([2, 0, 6]) - op(ref, indices, updates).eval() + self.evaluate(op(ref, indices, updates)) if __name__ == '__main__': diff --git a/tensorflow/python/kernel_tests/segment_reduction_ops_test.py b/tensorflow/python/kernel_tests/segment_reduction_ops_test.py index 3f7e43b533..8af1b47e83 100644 --- a/tensorflow/python/kernel_tests/segment_reduction_ops_test.py +++ b/tensorflow/python/kernel_tests/segment_reduction_ops_test.py @@ -26,6 +26,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes as dtypes_lib from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables @@ -118,7 +119,7 @@ class SegmentReductionOpTest(SegmentReductionHelper): for np_op1, np_op2, tf_op in curr_ops_list: np_ans = self._segmentReduce(indices, np_x, np_op1, np_op2) s = tf_op(data=tf_x, segment_ids=indices) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np_ans, tf_ans) # NOTE(mrry): The static shape inference that computes # `tf_ans.shape` can only infer that sizes from dimension 1 @@ -126,6 +127,7 @@ class SegmentReductionOpTest(SegmentReductionHelper): # and may therefore vary dynamically. self.assertAllEqual(np_ans.shape[1:], tf_ans.shape[1:]) + @test_util.run_deprecated_v1 def testSegmentIdsShape(self): shape = [4, 4] tf_x, _ = self._input(shape) @@ -133,6 +135,7 @@ class SegmentReductionOpTest(SegmentReductionHelper): with self.assertRaises(ValueError): math_ops.segment_sum(data=tf_x, segment_ids=indices) + @test_util.run_deprecated_v1 def testSegmentIdsSize(self): shape = [4, 4] for use_gpu in [True, False]: @@ -141,8 +144,9 @@ class SegmentReductionOpTest(SegmentReductionHelper): indices = [0, 1] s = math_ops.segment_sum(data=tf_x, segment_ids=indices) with self.assertRaisesOpError("segment_ids should be the same size"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentIdsValid(self): # This is a baseline for the following SegmentIdsInvalid* tests. shape = [4, 4] @@ -161,7 +165,7 @@ class SegmentReductionOpTest(SegmentReductionHelper): indices = [1, 1, 2, 2] np_ans = self._segmentReduce(indices, np_x, np.add) s = math_ops.segment_sum(data=tf_x, segment_ids=indices) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np_ans, tf_ans) def testSegmentIdsHole(self): @@ -172,9 +176,10 @@ class SegmentReductionOpTest(SegmentReductionHelper): indices = [0, 0, 3, 3] np_ans = self._segmentReduce(indices, np_x, np.add) s = math_ops.segment_sum(data=tf_x, segment_ids=indices) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np_ans, tf_ans) + @test_util.run_deprecated_v1 def testSegmentIdsInvalid1(self): shape = [4, 4] with self.cached_session(): @@ -184,8 +189,9 @@ class SegmentReductionOpTest(SegmentReductionHelper): with self.assertRaisesOpError( r"Segment id -1 out of range \[0, 1\), possibly because " "'segment_ids' input is not sorted."): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentIdsInvalid2(self): shape = [4, 4] with self.cached_session(): @@ -193,8 +199,9 @@ class SegmentReductionOpTest(SegmentReductionHelper): indices = [0, 1, 0, 1] s = math_ops.segment_sum(data=tf_x, segment_ids=indices) with self.assertRaisesOpError("segment ids are not increasing"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentIdsInvalid3(self): shape = [4, 4] with self.cached_session(): @@ -204,8 +211,9 @@ class SegmentReductionOpTest(SegmentReductionHelper): with self.assertRaisesOpError( r"Segment id 1 out of range \[0, 1\), possibly " "because 'segment_ids' input is not sorted."): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentIdsInvalid4(self): shape = [4, 4] for use_gpu in [True, False]: @@ -214,8 +222,9 @@ class SegmentReductionOpTest(SegmentReductionHelper): indices = [0, 0, 0, -1] s = math_ops.segment_sum(data=tf_x, segment_ids=indices) with self.assertRaisesOpError("segment ids must be >= 0"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentIdsInvalid5(self): shape = [4, 4] for use_gpu in [True, False]: @@ -224,8 +233,9 @@ class SegmentReductionOpTest(SegmentReductionHelper): indices = [0, 0, 0, -2] s = math_ops.segment_sum(data=tf_x, segment_ids=indices) with self.assertRaisesOpError("segment ids must be >= 0"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testGradient(self): shape = [4, 4] indices = [0, 1, 2, 2] @@ -297,7 +307,7 @@ class UnsortedSegmentTest(SegmentReductionHelper): indices, np_x, np_op1, np_op2, num_segments=num_segments, initial_value=init_op(dtype)) s = tf_op(tf_x, segment_ids=indices, num_segments=num_segments) - tf_ans = s.eval() + tf_ans = self.evaluate(s) if dtype is dtypes_lib.bfloat16: tf_ans = tf_ans.astype(np.float32) self.assertAllCloseAccordingToType(np_ans, tf_ans) @@ -320,10 +330,11 @@ class UnsortedSegmentTest(SegmentReductionHelper): data=tf_x, segment_ids=indices, num_segments=num_segments_constant) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np_ans, tf_ans) self.assertShapeEqual(np_ans, s) + @test_util.run_deprecated_v1 def testGradients(self): num_cols = 2 indices_flat = np.array([0, 4, 0, -1, 3, -1, 4, 7, 7, 3]) @@ -346,6 +357,7 @@ class UnsortedSegmentTest(SegmentReductionHelper): delta=1) self.assertAllClose(jacob_t, jacob_n) + @test_util.run_deprecated_v1 def testProdGrad(self): # additional test for the prod gradient to ensure correct handling of zeros values = np.array([0, 0, 1, 0, 2, 2, 3, 3, 3], dtype=np.float32) @@ -370,6 +382,7 @@ class UnsortedSegmentTest(SegmentReductionHelper): self.assertAllClose(jacob_t, jacob_n) self.assertAllClose(jacob_t, grad_gt) + @test_util.run_deprecated_v1 def testGradientMatchesSegmentSum(self): # Strategy: compute the gradient for UnsortedSegmentSum and SegmentSum # and compare the outputs, which should be identical. @@ -403,6 +416,7 @@ class UnsortedSegmentTest(SegmentReductionHelper): self.assertAllClose(unsorted_jacob_t, sorted_jacob_t) self.assertAllClose(unsorted_jacob_n, sorted_jacob_n) + @test_util.run_deprecated_v1 def testBadIndices(self): # Note: GPU kernel does not return the out-of-range error needed for this # test, so this test is marked as cpu-only. @@ -412,8 +426,9 @@ class UnsortedSegmentTest(SegmentReductionHelper): unsorted = math_ops.unsorted_segment_sum([[17]], bad, num_segments=2) with self.assertRaisesOpError( r"segment_ids\[0,0\] = %d is out of range \[0, 2\)" % bad[0][0]): - unsorted.eval() + self.evaluate(unsorted) + @test_util.run_deprecated_v1 def testEmptySecondDimension(self): dtypes = [np.float16, np.float32, np.float64, np.int64, np.int32, np.complex64, np.complex128] @@ -443,7 +458,7 @@ class UnsortedSegmentTest(SegmentReductionHelper): np.place(indices, indices == 8, [-1]) s = math_ops.unsorted_segment_sum( data=tf_x, segment_ids=indices, num_segments=num_segments) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np_ans, tf_ans) self.assertShapeEqual(np_ans, s) @@ -499,7 +514,7 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): np_ans = self._sparseSegmentReduce(np_x, np_indices, segment_indices, np_op1, np_op2) s = tf_op(data=tf_x, indices=tf_indices, segment_ids=segment_indices) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np_ans, tf_ans) # NOTE(mrry): The static shape inference that computes # `tf_ans.shape` can only infer that sizes from dimension 1 @@ -518,7 +533,7 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): np_ans = self._sparseSegmentReduce(np_x, tf_indices, segment_indices, np_op1, np_op2) s = tf_op(data=tf_x, indices=tf_indices, segment_ids=segment_indices) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np_ans, tf_ans) def testWithNumSegments(self): @@ -543,7 +558,7 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): indices=tf_indices, segment_ids=segment_indices, num_segments=num_segments) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np_ans, tf_ans) def testWithEmptySegments(self): @@ -562,7 +577,7 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): indices=tf_indices, segment_ids=segment_indices, num_segments=num_segments) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np.zeros([5, 4]), tf_ans) def testSegmentIdsGreaterThanZero(self): @@ -576,7 +591,7 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): np_ans = self._sparseSegmentReduce(np_x, tf_indices, segment_indices, np_op1, np_op2) s = tf_op(data=tf_x, indices=tf_indices, segment_ids=segment_indices) - tf_ans = s.eval() + tf_ans = self.evaluate(s) self.assertAllClose(np_ans, tf_ans) def testValid(self): @@ -588,8 +603,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): with self.session(use_gpu=False): for tf_op in ops_list: s = tf_op(data=tf_x, indices=tf_indices, segment_ids=segment_indices) - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testIndicesInvalid1(self): tf_x, _ = self._input([10, 4], dtype=dtypes_lib.float32) ops_list = [math_ops.sparse_segment_sum, math_ops.sparse_segment_mean] @@ -600,8 +616,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): s = tf_op(data=tf_x, indices=tf_indices, segment_ids=segment_indices) with self.assertRaisesOpError( r"indices\[1\] == -1 out of range \[0, 10\)"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testIndicesInvalid2(self): tf_x, _ = self._input([10, 4], dtype=dtypes_lib.float32) ops_list = [math_ops.sparse_segment_sum, math_ops.sparse_segment_mean] @@ -612,8 +629,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): s = tf_op(data=tf_x, indices=tf_indices, segment_ids=segment_indices) with self.assertRaisesOpError( r"indices\[3\] == 10 out of range \[0, 10\)"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentsInvalid2(self): tf_x, _ = self._input([10, 4], dtype=dtypes_lib.float32) ops_list = [math_ops.sparse_segment_sum, math_ops.sparse_segment_mean] @@ -623,8 +641,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): for tf_op in ops_list: s = tf_op(data=tf_x, indices=tf_indices, segment_ids=segment_indices) with self.assertRaisesOpError("segment ids are not increasing"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentsInvalid3(self): tf_x, _ = self._input([10, 4], dtype=dtypes_lib.float32) ops_list = [math_ops.sparse_segment_sum, math_ops.sparse_segment_mean] @@ -636,8 +655,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): with self.assertRaisesOpError( r"Segment id 1 out of range \[0, 1\), possibly because " "'segment_ids' input is not sorted"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentsInvalid4(self): tf_x, _ = self._input([10, 4], dtype=dtypes_lib.float32) ops_list = [math_ops.sparse_segment_sum, math_ops.sparse_segment_mean] @@ -649,8 +669,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): with self.assertRaisesOpError( r"Segment id -1 out of range \[0, 2\), possibly because " "'segment_ids' input is not sorted"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentsInvalid6(self): tf_x, _ = self._input([10, 4], dtype=dtypes_lib.float32) ops_list = [math_ops.sparse_segment_sum, math_ops.sparse_segment_mean] @@ -660,8 +681,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): for tf_op in ops_list: s = tf_op(data=tf_x, indices=tf_indices, segment_ids=segment_indices) with self.assertRaisesOpError("segment ids must be >= 0"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentsInvalid7(self): tf_x, _ = self._input([10, 4], dtype=dtypes_lib.float32) ops_list = [math_ops.sparse_segment_sum, math_ops.sparse_segment_mean] @@ -671,7 +693,7 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): for tf_op in ops_list: s = tf_op(data=tf_x, indices=tf_indices, segment_ids=segment_indices) with self.assertRaisesOpError("segment ids must be >= 0"): - s.eval() + self.evaluate(s) def testSegmentWithNumSegmentsValid(self): # Baseline for the test*WithNumSegmentsInvalid* methods below. @@ -690,8 +712,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): indices=tf_indices, segment_ids=segment_indices, num_segments=num_segments) - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentWithNumSegmentsInvalid1(self): tf_x, _ = self._input([10, 4], dtype=dtypes_lib.float32) ops_list = [ @@ -709,8 +732,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): segment_ids=segment_indices, num_segments=num_segments) with self.assertRaisesOpError("segment ids must be < num_segments"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testSegmentWithNumSegmentsInvalid2(self): tf_x, _ = self._input([10, 4], dtype=dtypes_lib.float32) ops_list = [ @@ -730,6 +754,7 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): segment_ids=segment_indices, num_segments=num_segments) + @test_util.run_deprecated_v1 def testGradient(self): shape = [10, 4] @@ -748,6 +773,7 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): delta=1) self.assertAllClose(jacob_t, jacob_n) + @test_util.run_deprecated_v1 def testGradientWithEmptySegmentsAtEnd(self): shape = [10, 4] @@ -785,8 +811,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): with self.session(use_gpu=False): for tf_op in ops_list: s = tf_op(tf_x, tf_indices, segment_indices, 10) - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testGradientIndicesInvalid1(self): tf_x, _ = self._input([3, 4], dtype=dtypes_lib.float32) ops_list = [ @@ -798,8 +825,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): for tf_op in ops_list: s = tf_op(tf_x, tf_indices, segment_indices, 10) with self.assertRaisesOpError(r"Index 10 out of range \[0, 10\)"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testGradientIndicesInvalid2(self): tf_x, _ = self._input([3, 4], dtype=dtypes_lib.float32) ops_list = [ @@ -811,8 +839,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): for tf_op in ops_list: s = tf_op(tf_x, tf_indices, segment_indices, 10) with self.assertRaisesOpError(r"Index -1 out of range \[0, 10\)"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testGradientSegmentsInvalid1(self): tf_x, _ = self._input( [3, 4], dtype=dtypes_lib.float32) # expecting 3 segments @@ -825,8 +854,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): for tf_op in ops_list: s = tf_op(tf_x, tf_indices, segment_indices, 10) with self.assertRaisesOpError("Invalid number of segments"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testGradientSegmentsInvalid2(self): tf_x, _ = self._input([1, 4], dtype=dtypes_lib.float32) ops_list = [ @@ -838,8 +868,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): for tf_op in ops_list: s = tf_op(tf_x, tf_indices, segment_indices, 10) with self.assertRaisesOpError(r"Segment id 1 out of range \[0, 1\)"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testGradientSegmentsInvalid3(self): tf_x, _ = self._input([2, 4], dtype=dtypes_lib.float32) ops_list = [ @@ -851,8 +882,9 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): for tf_op in ops_list: s = tf_op(tf_x, tf_indices, segment_indices, 10) with self.assertRaisesOpError(r"Segment id -1 out of range \[0, 2\)"): - s.eval() + self.evaluate(s) + @test_util.run_deprecated_v1 def testGradientSegmentsInvalid4(self): tf_x, _ = self._input([0, 4], dtype=dtypes_lib.float32) ops_list = [ @@ -864,7 +896,8 @@ class SparseSegmentReductionOpTest(SparseSegmentReductionHelper): for tf_op in ops_list: s = tf_op(tf_x, tf_indices, segment_indices, 10) with self.assertRaisesOpError(r"Segment id 0 out of range \[0, 0\)"): - s.eval() + self.evaluate(s) + class SegmentReductionOpBenchmark(test.Benchmark): outer_dim_options = [2**x for x in range(9, 14, 2)] diff --git a/tensorflow/python/kernel_tests/self_adjoint_eig_op_test.py b/tensorflow/python/kernel_tests/self_adjoint_eig_op_test.py index 1b4aff8c9c..42577f7e42 100644 --- a/tensorflow/python/kernel_tests/self_adjoint_eig_op_test.py +++ b/tensorflow/python/kernel_tests/self_adjoint_eig_op_test.py @@ -63,7 +63,7 @@ class SelfAdjointEigTest(test.TestCase): e1 = linalg_ops.self_adjoint_eigvals(matrix1) e2 = linalg_ops.self_adjoint_eigvals(matrix2) all_ops += [e1, e2] - val = sess.run(all_ops) + val = self.evaluate(all_ops) self.assertAllEqual(val[0], val[2]) # The algorithm is slightly different for compute_v being True and False, # so require approximate equality only here. @@ -81,7 +81,7 @@ class SelfAdjointEigTest(test.TestCase): self.assertEqual(matrix.shape, (32, 32)) matrix_tensor = constant_op.constant(matrix) with self.session(use_gpu=True) as sess: - (e, v) = sess.run(linalg_ops.self_adjoint_eig(matrix_tensor)) + (e, v) = self.evaluate(linalg_ops.self_adjoint_eig(matrix_tensor)) self.assertEqual(e.size, 32) self.assertAllClose( np.matmul(v, v.transpose()), np.eye(32, dtype=np.float32), atol=2e-3) @@ -164,8 +164,8 @@ def _GetSelfAdjointEigTest(dtype_, shape_, compute_v_): self.assertAllClose(a_ev.eval(), a, atol=atol) # Compare to numpy.linalg.eigh. - CompareEigenDecompositions(self, np_e, np_v, - tf_e.eval(), tf_v.eval(), atol) + CompareEigenDecompositions(self, np_e, np_v, self.evaluate(tf_e), + self.evaluate(tf_v), atol) else: tf_e = linalg_ops.self_adjoint_eigvals(constant_op.constant(a)) self.assertAllClose( diff --git a/tensorflow/python/kernel_tests/session_ops_test.py b/tensorflow/python/kernel_tests/session_ops_test.py index 03e1ae852f..dc663cb091 100644 --- a/tensorflow/python/kernel_tests/session_ops_test.py +++ b/tensorflow/python/kernel_tests/session_ops_test.py @@ -37,7 +37,7 @@ class SessionOpsTest(test.TestCase): b = constant_op.constant(5) c = math_ops.multiply(a, b) h = session_ops.get_session_handle(c) - h = sess.run(h) + h = self.evaluate(h) # Feed a tensor handle. f, x = session_ops.get_session_tensor(h.handle, dtypes.int32) @@ -51,7 +51,7 @@ class SessionOpsTest(test.TestCase): b = constant_op.constant(5) c = math_ops.multiply(a, b) h = session_ops.get_session_handle(c) - h = sess.run(h) + h = self.evaluate(h) # Get the tensor from its handle. self.assertEqual(50, h.eval()) @@ -64,7 +64,7 @@ class SessionOpsTest(test.TestCase): c = math_ops.multiply(a, b) h = session_ops.get_session_handle(c) v = math_ops.multiply(a, c) - h, v = sess.run([h, v]) + h, v = self.evaluate([h, v]) self.assertEqual(50, h.eval()) self.assertEqual(500, v) @@ -77,7 +77,7 @@ class SessionOpsTest(test.TestCase): p = math_ops.less(a, b) c = math_ops.multiply(a, b) h = session_ops.get_session_handle(c) - p, h = sess.run([p, h]) + p, h = self.evaluate([p, h]) # Run by feeding a tensor handle. f, x = session_ops.get_session_tensor(h.handle, dtypes.int32) @@ -94,7 +94,7 @@ class SessionOpsTest(test.TestCase): # Initialize a handle. a = constant_op.constant(0) h = session_ops.get_session_handle(a) - h = sess.run(h) + h = self.evaluate(h) # Do some computation. f, x = session_ops.get_session_tensor(h.handle, dtypes.int32) @@ -111,7 +111,7 @@ class SessionOpsTest(test.TestCase): # Initialize a handle. a = constant_op.constant(0) h = session_ops.get_session_handle(a) - h = sess.run(h) + h = self.evaluate(h) # Do some computation. f, x = session_ops.get_session_tensor(h.handle, dtypes.int32) @@ -133,7 +133,7 @@ class SessionOpsTest(test.TestCase): b = constant_op.constant(5) c = math_ops.multiply(a, b) h = session_ops.get_session_handle(c) - h = sess.run(h) + h = self.evaluate(h) # Feed a tensor handle. f, x = session_ops.get_session_tensor(h.handle, dtypes.int32) @@ -144,7 +144,7 @@ class SessionOpsTest(test.TestCase): with ops.device(test.gpu_device_name()): a = constant_op.constant(10) h = session_ops.get_session_handle(a) - h = sess.run(h) + h = self.evaluate(h) self.assertEqual(100, sess.run(y, feed_dict={f: h.handle})) def testHandleDelete(self): @@ -154,7 +154,7 @@ class SessionOpsTest(test.TestCase): b = constant_op.constant(5) c = math_ops.multiply(a, b) h = session_ops.get_session_handle(c) - sess.run(h).delete() + self.evaluate(h).delete() def testHandleDeleteRaw(self): with self.cached_session() as sess: @@ -163,7 +163,7 @@ class SessionOpsTest(test.TestCase): b = constant_op.constant(5) c = math_ops.multiply(a, b) h = session_ops.get_session_handle(c) - h = sess.run(h) + h = self.evaluate(h) # Delete using a raw tensor handle. raw_h = h.get_raw_handle() @@ -174,10 +174,10 @@ class SessionOpsTest(test.TestCase): with self.cached_session() as sess: with ops.device(test.gpu_device_name()): a = constant_op.constant(1.0) - a_handle = sess.run(session_ops.get_session_handle(a)) + a_handle = self.evaluate(session_ops.get_session_handle(a)) with ops.device("/cpu:0"): b = constant_op.constant(2.0) - b_handle = sess.run(session_ops.get_session_handle(b)) + b_handle = self.evaluate(session_ops.get_session_handle(b)) a_p, a_t = session_ops.get_session_tensor(a_handle.handle, dtypes.float32) b_p, b_t = session_ops.get_session_tensor(b_handle.handle, dtypes.float32) @@ -193,8 +193,8 @@ class SessionOpsTest(test.TestCase): # initial values live on CPU with ops.device("/cpu:0"): one = constant_op.constant(1, dtype=dtypes.float32) - one_handle = sess.run(session_ops.get_session_handle(one)) - x_handle = sess.run(session_ops.get_session_handle(one)) + one_handle = self.evaluate(session_ops.get_session_handle(one)) + x_handle = self.evaluate(session_ops.get_session_handle(one)) # addition lives on GPU with ops.device(test.gpu_device_name()): @@ -219,8 +219,8 @@ class SessionOpsTest(test.TestCase): b = constant_op.constant(2.0) b_handle_op = session_ops.get_session_handle(b) - a_handle = sess.run(a_handle_op) - b_handle = sess.run(b_handle_op) + a_handle = self.evaluate(a_handle_op) + b_handle = self.evaluate(b_handle_op) a_p, a_t = session_ops.get_session_tensor(a_handle.handle, dtypes.float32) b_p, b_t = session_ops.get_session_tensor(b_handle.handle, dtypes.float32) @@ -239,7 +239,7 @@ class SessionOpsTest(test.TestCase): c = math_ops.multiply(a, b) d = math_ops.multiply(c, c) - h_c = sess.run(session_ops.get_session_handle(c)) + h_c = self.evaluate(session_ops.get_session_handle(c)) self.assertAllClose(2500.0, sess.run(d, feed_dict={c: h_c})) @@ -248,7 +248,7 @@ class SessionOpsTest(test.TestCase): a = constant_op.constant(10.0) b = constant_op.constant(5.0) c = math_ops.multiply(a, b) - h_c = sess.run(session_ops.get_session_handle(c)) + h_c = self.evaluate(session_ops.get_session_handle(c)) d = array_ops.identity(c) c_val = sess.run(c, feed_dict={c: h_c}) @@ -277,8 +277,8 @@ class SessionOpsTest(test.TestCase): d = math_ops.div(a, b) e = math_ops.subtract(c, d) - h_c = sess.run(session_ops.get_session_handle(c)) - h_d = sess.run(session_ops.get_session_handle(d)) + h_c = self.evaluate(session_ops.get_session_handle(c)) + h_d = self.evaluate(session_ops.get_session_handle(d)) self.assertAllClose(48.0, sess.run(e, feed_dict={c: h_c, d: h_d})) self.assertAllClose(-48.0, sess.run(e, feed_dict={c: h_d, d: h_c})) @@ -288,13 +288,13 @@ class SessionOpsTest(test.TestCase): a = variables.Variable(12.0) inc_a = state_ops.assign_add(a, 2.0) b = math_ops.add(a, 5.0) - sess.run(a.initializer) + self.evaluate(a.initializer) h_a_read = sess.run(session_ops.get_session_handle(a.read_value())) - self.assertAllClose(12.0, sess.run(a)) + self.assertAllClose(12.0, self.evaluate(a)) self.assertAllClose(17.0, sess.run(b, feed_dict={a: h_a_read})) - sess.run(inc_a) + self.evaluate(inc_a) self.assertAllClose(19.0, sess.run(b, feed_dict={a: h_a_read})) diff --git a/tensorflow/python/kernel_tests/sets_test.py b/tensorflow/python/kernel_tests/sets_test.py index 8335e9c139..b4f2322934 100644 --- a/tensorflow/python/kernel_tests/sets_test.py +++ b/tensorflow/python/kernel_tests/sets_test.py @@ -70,6 +70,7 @@ def _dense_to_sparse(dense, dtype): class SetOpsTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def test_set_size_2d(self): for dtype in _DTYPES: self._test_set_size_2d(dtype) @@ -83,6 +84,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): self.assertAllEqual( [0, 3], self._set_size(_dense_to_sparse([[], [1, 9, 2]], dtype))) + @test_util.run_deprecated_v1 def test_set_size_duplicates_2d(self): for dtype in _DTYPES: self._test_set_size_duplicates_2d(dtype) @@ -96,6 +98,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): 6, 7, 8, 8, 6, 7, 5, 3, 3, 0, 6, 6, 9, 0, 0, 0 ], [999, 1, -1000], [], [-1]], dtype))) + @test_util.run_deprecated_v1 def test_set_size_3d(self): for dtype in _DTYPES: self._test_set_size_3d(dtype) @@ -159,10 +162,11 @@ class SetOpsTest(test_util.TensorFlowTestCase): self.assertEqual(None, op.get_shape().dims) self.assertEqual(dtypes.int32, op.dtype) with self.cached_session() as sess: - results = sess.run(ops) + results = self.evaluate(ops) self.assertAllEqual(results[0], results[1]) return results[0] + @test_util.run_deprecated_v1 def test_set_intersection_multirow_2d(self): for dtype in _DTYPES: self._test_set_intersection_multirow_2d(dtype) @@ -199,6 +203,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): self.assertAllEqual(expected_counts, self._set_intersection_count(sp_a, sp_b)) + @test_util.run_deprecated_v1 def test_dense_set_intersection_multirow_2d(self): for dtype in _DTYPES: self._test_dense_set_intersection_multirow_2d(dtype) @@ -223,6 +228,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): dtype=dtype) self.assertAllEqual(expected_counts, self._set_intersection_count(a, b)) + @test_util.run_deprecated_v1 def test_set_intersection_duplicates_2d(self): for dtype in _DTYPES: self._test_set_intersection_duplicates_2d(dtype) @@ -270,6 +276,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): self.assertAllEqual(expected_counts, self._set_intersection_count(sp_a, sp_b)) + @test_util.run_deprecated_v1 def test_set_intersection_3d(self): for dtype in _DTYPES: self._test_set_intersection_3d(dtype=dtype) @@ -534,8 +541,9 @@ class SetOpsTest(test_util.TensorFlowTestCase): def _set_intersection_count(self, a, b): op = sets.set_size(sets.set_intersection(a, b)) with self.cached_session() as sess: - return sess.run(op) + return self.evaluate(op) + @test_util.run_deprecated_v1 def test_set_difference_multirow_2d(self): for dtype in _DTYPES: self._test_set_difference_multirow_2d(dtype) @@ -604,6 +612,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): self.assertAllEqual(expected_counts, self._set_difference_count(sp_a, sp_b, False)) + @test_util.run_deprecated_v1 def test_dense_set_difference_multirow_2d(self): for dtype in _DTYPES: self._test_dense_set_difference_multirow_2d(dtype) @@ -647,6 +656,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): self.assertAllEqual(expected_counts, self._set_difference_count(a, b, False)) + @test_util.run_deprecated_v1 def test_sparse_set_difference_multirow_2d(self): for dtype in _DTYPES: self._test_sparse_set_difference_multirow_2d(dtype) @@ -688,6 +698,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): self.assertAllEqual(expected_counts, self._set_difference_count(sp_a, sp_b, False)) + @test_util.run_deprecated_v1 def test_set_difference_duplicates_2d(self): for dtype in _DTYPES: self._test_set_difference_duplicates_2d(dtype) @@ -755,6 +766,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): self.assertAllEqual(expected_counts, self._set_difference_count(a, sp_b, False)) + @test_util.run_deprecated_v1 def test_sparse_set_difference_3d(self): for dtype in _DTYPES: self._test_sparse_set_difference_3d(dtype) @@ -972,8 +984,9 @@ class SetOpsTest(test_util.TensorFlowTestCase): def _set_difference_count(self, a, b, aminusb=True): op = sets.set_size(sets.set_difference(a, b, aminusb)) with self.cached_session() as sess: - return sess.run(op) + return self.evaluate(op) + @test_util.run_deprecated_v1 def test_set_union_multirow_2d(self): for dtype in _DTYPES: self._test_set_union_multirow_2d(dtype) @@ -1001,6 +1014,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): expected_indices, expected_values, expected_shape, union, dtype=dtype) self.assertAllEqual(expected_counts, self._set_union_count(sp_a, sp_b)) + @test_util.run_deprecated_v1 def test_dense_set_union_multirow_2d(self): for dtype in _DTYPES: self._test_dense_set_union_multirow_2d(dtype) @@ -1021,6 +1035,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): expected_indices, expected_values, expected_shape, union, dtype=dtype) self.assertAllEqual(expected_counts, self._set_union_count(a, b)) + @test_util.run_deprecated_v1 def test_set_union_duplicates_2d(self): for dtype in _DTYPES: self._test_set_union_duplicates_2d(dtype) @@ -1047,6 +1062,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): expected_indices, expected_values, expected_shape, union, dtype=dtype) self.assertAllEqual([2], self._set_union_count(sp_a, sp_b)) + @test_util.run_deprecated_v1 def test_sparse_set_union_3d(self): for dtype in _DTYPES: self._test_sparse_set_union_3d(dtype) @@ -1221,7 +1237,7 @@ class SetOpsTest(test_util.TensorFlowTestCase): def _set_union_count(self, a, b): op = sets.set_size(sets.set_union(a, b)) with self.cached_session() as sess: - return sess.run(op) + return self.evaluate(op) def _assert_set_operation(self, expected_indices, expected_values, expected_shape, sparse_tensor_value, dtype): diff --git a/tensorflow/python/kernel_tests/shape_ops_test.py b/tensorflow/python/kernel_tests/shape_ops_test.py index ee813e5ffd..c8e7c143ad 100644 --- a/tensorflow/python/kernel_tests/shape_ops_test.py +++ b/tensorflow/python/kernel_tests/shape_ops_test.py @@ -26,6 +26,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import importer from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl @@ -53,8 +54,8 @@ class ShapeOpsTest(test.TestCase): with self.cached_session(use_gpu=use_gpu): tf_ans = array_ops.shape(x) tf_ans_64 = array_ops.shape(x, out_type=dtypes.int64) - result = tf_ans.eval() - result_64 = tf_ans_64.eval() + result = self.evaluate(tf_ans) + result_64 = self.evaluate(tf_ans_64) self.assertAllEqual(np_ans, result) self.assertAllEqual(np_ans, result_64) self.assertShapeEqual(np_ans, tf_ans) @@ -64,7 +65,7 @@ class ShapeOpsTest(test.TestCase): x_tf, unused_nnz = _sparsify(x_np) with self.cached_session(use_gpu=use_gpu): tf_ans = array_ops.shape(x_tf) - result = tf_ans.eval() + result = self.evaluate(tf_ans) self.assertAllEqual(np_ans, result) self.assertShapeEqual(np_ans, tf_ans) @@ -73,8 +74,8 @@ class ShapeOpsTest(test.TestCase): with self.cached_session(use_gpu=use_gpu) as sess: tf_ans = array_ops.shape_n([x, x, x]) tf_ans_64 = array_ops.shape_n([x, x, x], out_type=dtypes.int64) - result = sess.run(tf_ans) - result_64 = sess.run(tf_ans_64) + result = self.evaluate(tf_ans) + result_64 = self.evaluate(tf_ans_64) for i in range(3): self.assertAllEqual(np_ans, result[i]) self.assertAllEqual(np_ans, result_64[i]) @@ -84,7 +85,7 @@ class ShapeOpsTest(test.TestCase): np_ans = np.asarray(np.ndim(x)) with self.cached_session(use_gpu=use_gpu): tf_ans = array_ops.rank(x) - result = tf_ans.eval() + result = self.evaluate(tf_ans) self.assertAllEqual(np_ans, result) self.assertShapeEqual(np_ans, tf_ans) @@ -93,7 +94,7 @@ class ShapeOpsTest(test.TestCase): x_tf, unused_nnz = _sparsify(x_np) with self.cached_session(use_gpu=use_gpu): tf_ans = array_ops.rank(x_tf) - result = tf_ans.eval() + result = self.evaluate(tf_ans) self.assertAllEqual(np_ans, result) self.assertShapeEqual(np_ans, tf_ans) @@ -101,9 +102,9 @@ class ShapeOpsTest(test.TestCase): np_ans = np.asarray(np.size(x)) with self.cached_session(use_gpu=use_gpu): tf_ans = array_ops.size(x) - result = tf_ans.eval() + result = self.evaluate(tf_ans) tf_ans_64 = array_ops.size(x, out_type=dtypes.int64) - result_64 = tf_ans_64.eval() + result_64 = self.evaluate(tf_ans_64) self.assertAllEqual(np_ans, result) self.assertAllEqual(np_ans, result_64) self.assertShapeEqual(np_ans, tf_ans) @@ -113,7 +114,7 @@ class ShapeOpsTest(test.TestCase): x_tf, unused_nnz = _sparsify(x_np) with self.cached_session(use_gpu=use_gpu): tf_ans = array_ops.size(x_tf) - result = tf_ans.eval() + result = self.evaluate(tf_ans) self.assertAllEqual(np_ans, result) self.assertShapeEqual(np_ans, tf_ans) @@ -162,7 +163,7 @@ class ShapeOpsTest(test.TestCase): inp = array_ops.zeros([2**31]) num_elements = array_ops.size_internal( inp, optimize=False, out_type=dtypes.int64) - self.assertEqual(2**31, num_elements.eval()) + self.assertEqual(2**31, self.evaluate(num_elements)) # Too large for tf.int32 output. with self.assertRaises(errors_impl.InvalidArgumentError): @@ -170,13 +171,13 @@ class ShapeOpsTest(test.TestCase): inp = array_ops.zeros([2**31]) num_elements = array_ops.size_internal( inp, optimize=False, out_type=dtypes.int32) - self.assertEqual(2**31, num_elements.eval()) + self.assertEqual(2**31, self.evaluate(num_elements)) def _compareExpandDims(self, x, dim, use_gpu): np_ans = np.expand_dims(x, axis=dim) with self.cached_session(use_gpu=use_gpu): tensor = array_ops.expand_dims(x, dim) - tf_ans = tensor.eval() + tf_ans = self.evaluate(tensor) self.assertShapeEqual(np_ans, tensor) self.assertAllEqual(np_ans, tf_ans) @@ -227,6 +228,7 @@ class ShapeOpsTest(test.TestCase): self._compareExpandDimsAll(choice([2, 3, 5]), -3) self._compareExpandDimsAll(choice([2, 3, 5]), -4) + @test_util.run_deprecated_v1 def testExpandDimsErrors(self): with self.cached_session(): self.assertRaises(ValueError, array_ops.expand_dims, @@ -238,6 +240,7 @@ class ShapeOpsTest(test.TestCase): self.assertRaises(ValueError, array_ops.expand_dims, [False, True, True], 4) + @test_util.run_deprecated_v1 def testExpandDimsGradient(self): with self.cached_session(): inp = constant_op.constant( @@ -248,6 +251,7 @@ class ShapeOpsTest(test.TestCase): [4, 1, 2]) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testExpandDimsScalar(self): with self.cached_session(): inp = constant_op.constant(7) @@ -264,7 +268,7 @@ class ShapeOpsTest(test.TestCase): np_ans = np.expand_dims(x, axis=0) with self.cached_session(use_gpu=True): tensor = array_ops.expand_dims(x, constant_op.constant(0, dtype)) - tf_ans = tensor.eval() + tf_ans = self.evaluate(tensor) self.assertShapeEqual(np_ans, tensor) self.assertAllEqual(np_ans, tf_ans) @@ -273,11 +277,11 @@ class ShapeOpsTest(test.TestCase): if squeeze_dims: np_ans = np.squeeze(x, axis=tuple(squeeze_dims)) tensor = array_ops.squeeze(x, squeeze_dims) - tf_ans = tensor.eval() + tf_ans = self.evaluate(tensor) else: np_ans = np.squeeze(x) tensor = array_ops.squeeze(x) - tf_ans = tensor.eval() + tf_ans = self.evaluate(tensor) self.assertShapeEqual(np_ans, tensor) self.assertAllEqual(np_ans, tf_ans) @@ -340,7 +344,7 @@ class ShapeOpsTest(test.TestCase): with self.cached_session(use_gpu=use_gpu): tensor = array_ops.squeeze(np.zeros([1, 1, 1]), []) self.assertEqual(np.shape(1), tensor.get_shape()) - tf_ans = tensor.eval() + tf_ans = self.evaluate(tensor) self.assertEqual(np.shape(1), tf_ans.shape) def testSqueezeAllOnesBool(self): @@ -350,9 +354,10 @@ class ShapeOpsTest(test.TestCase): with self.cached_session(use_gpu=use_gpu): tensor = array_ops.squeeze([[[False]]], []) self.assertEqual(np.shape(1), tensor.get_shape()) - tf_ans = tensor.eval() + tf_ans = self.evaluate(tensor) self.assertEqual(np.shape(1), tf_ans.shape) + @test_util.run_deprecated_v1 def testSqueezeOnlyOnes(self): for use_gpu in [False, True]: with self.cached_session(use_gpu=use_gpu): @@ -362,6 +367,7 @@ class ShapeOpsTest(test.TestCase): self._compareSqueezeAll(input_1x1x3, [1]) self.assertRaises(ValueError, array_ops.squeeze, input_1x1x3, [2]) + @test_util.run_deprecated_v1 def testSqueezeErrors(self): for use_gpu in [False, True]: with self.cached_session(use_gpu=use_gpu): @@ -374,6 +380,7 @@ class ShapeOpsTest(test.TestCase): self.assertRaises(ValueError, array_ops.squeeze, np.zeros([1, 2, 1]), [2, 3]) + @test_util.run_deprecated_v1 def testSqueezeGradient(self): with self.cached_session(): inp = np.random.rand(4, 2).astype("f") @@ -384,6 +391,7 @@ class ShapeOpsTest(test.TestCase): [4, 2]) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testSqueezeGradientWithSqueezeDims(self): with self.cached_session(): inp = np.random.rand(4, 2).astype("f") @@ -394,6 +402,7 @@ class ShapeOpsTest(test.TestCase): [4, 2, 1]) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testSqueezeWithUnknownShape(self): with self.cached_session(): a = array_ops.placeholder(dtypes.float32, shape=[2, None]) @@ -415,7 +424,7 @@ class TileTest(test.TestCase): with self.cached_session(use_gpu=use_gpu): a = constant_op.constant(7, shape=[], dtype=dtypes.float32) tiled = array_ops.tile(a, []) - result = tiled.eval() + result = self.evaluate(tiled) self.assertEqual(result.shape, ()) self.assertEqual([], tiled.get_shape()) self.assertEqual(7, result) @@ -427,7 +436,7 @@ class TileTest(test.TestCase): inp = np.random.rand(4, 1).astype(np.float32) a = constant_op.constant(inp) tiled = array_ops.tile(a, constant_op.constant([1, 4], dtype=dtype)) - result = tiled.eval() + result = self.evaluate(tiled) self.assertEqual(result.shape, (4, 4)) self.assertEqual([4, 4], tiled.get_shape()) self.assertTrue((result == np.tile(inp, (1, 4))).all()) @@ -437,7 +446,7 @@ class TileTest(test.TestCase): inp = np.random.rand(4, 1).astype(np.float32) a = constant_op.constant(inp) tiled = array_ops.tile(a, [1, 1]) - result = tiled.eval() + result = self.evaluate(tiled) self.assertEqual(result.shape, (4, 1)) self.assertEqual([4, 1], tiled.get_shape()) self.assertTrue((result == np.tile(inp, (1, 1))).all()) @@ -447,10 +456,11 @@ class TileTest(test.TestCase): inp = np.random.rand(2, 3).astype(np.float32) a = constant_op.constant(inp) tiled = array_ops.tile(a, [5, 0]) - result = tiled.eval() + result = self.evaluate(tiled) self.assertEqual(result.shape, (10, 0)) self.assertEqual([10, 0], tiled.get_shape()) + @test_util.run_deprecated_v1 def testUnknownInputShape(self): """Importing can call _TileShape without shape of known.""" with self.cached_session(): @@ -497,11 +507,12 @@ class TileTest(test.TestCase): shape=[4, 1], dtype=dtype_tf) tiled = array_ops.tile(a, [1, 4]) - result = tiled.eval() + result = self.evaluate(tiled) self.assertEqual(result.shape, (4, 4)) self.assertEqual([4, 4], tiled.get_shape()) self.assertAllEqual(result, np.tile(inp, (1, 4))) + @test_util.run_deprecated_v1 def testInvalidDim(self): with self.cached_session(): inp = np.random.rand(4, 1).astype("f") @@ -527,7 +538,7 @@ class TileTest(test.TestCase): dtype=dtypes.float32) multiples = np.random.randint(1, 4, size=rank).astype(np.int32) tiled = array_ops.tile(a, multiples) - result = tiled.eval() + result = self.evaluate(tiled) self.assertTrue((np.array(multiples) * np.array(inp.shape) == np.array( result.shape)).all()) self.assertAllEqual(result, np.tile(inp, tuple(multiples))) @@ -545,6 +556,7 @@ class TileTest(test.TestCase): for _ in range(5): self._RunAndVerifyResult(10, use_gpu=True) + @test_util.run_deprecated_v1 def testGradientSimpleReduction(self): with self.cached_session(): inp = np.random.rand(4, 1).astype("f") @@ -557,9 +569,10 @@ class TileTest(test.TestCase): [float(x) for x in grad_inp.flatten()], shape=grad_shape) grad = gradients_impl.gradients([tiled], [a], [grad_tensor])[0] self.assertShapeEqual(inp, grad) - result = grad.eval() + result = self.evaluate(grad) self.assertAllClose(np.sum(grad_inp, axis=1).reshape(4, 1), result, 1e-3) + @test_util.run_deprecated_v1 def testGradientStridedReduction(self): with self.cached_session(): inp = np.random.rand(4, 2).astype("f") @@ -572,13 +585,14 @@ class TileTest(test.TestCase): [float(x) for x in grad_inp.flatten()], shape=grad_shape) grad = gradients_impl.gradients([tiled], [a], [grad_tensor])[0] self.assertShapeEqual(inp, grad) - result = grad.eval() + result = self.evaluate(grad) expected_shape = [4, 2] expected = np.zeros(expected_shape) expected[:, 0] = grad_inp[:, 0] + grad_inp[:, 2] expected[:, 1] = grad_inp[:, 1] + grad_inp[:, 3] self.assertTrue((np.abs(expected - result) < 1e-3).all()) + @test_util.run_deprecated_v1 def testGradientSimpleReductionOnGPU(self): with self.session(use_gpu=True): inp = np.random.rand(4, 1).astype("f") @@ -590,9 +604,10 @@ class TileTest(test.TestCase): grad_tensor = constant_op.constant( [float(x) for x in grad_inp.flatten()], shape=grad_shape) grad = gradients_impl.gradients([tiled], [a], [grad_tensor])[0] - result = grad.eval() + result = self.evaluate(grad) self.assertAllClose(np.sum(grad_inp, axis=1).reshape(4, 1), result, 1e-3) + @test_util.run_deprecated_v1 def testGradientStridedReductionOnGPU(self): with self.session(use_gpu=True): inp = np.random.rand(4, 2).astype("f") @@ -604,7 +619,7 @@ class TileTest(test.TestCase): grad_tensor = constant_op.constant( [float(x) for x in grad_inp.flatten()], shape=grad_shape) grad = gradients_impl.gradients([tiled], [a], [grad_tensor])[0] - result = grad.eval() + result = self.evaluate(grad) expected_shape = [4, 2] expected = np.zeros(expected_shape) expected[:, 0] = grad_inp[:, 0] + grad_inp[:, 2] @@ -624,15 +639,18 @@ class TileTest(test.TestCase): print("tile(float) error = ", err) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testGradientRandomScalar(self): self._RunAndVerifyGradientResult([], []) + @test_util.run_deprecated_v1 def testGradientRandom(self): self._RunAndVerifyGradientResult([2, 2, 1, 1, 3], [1, 1, 1, 1, 1]) self._RunAndVerifyGradientResult([2, 2, 1, 1, 3], [1, 2, 1, 3, 1]) self._RunAndVerifyGradientResult([2, 3, 1, 1, 3], [3, 1, 1, 2, 2]) self._RunAndVerifyGradientResult([2, 1, 3, 3, 2], [1, 3, 3, 1, 2]) + @test_util.run_deprecated_v1 def testGradientStridedReductionGC(self): with self.cached_session(): inp = np.random.rand(4, 2).astype("f") @@ -642,6 +660,7 @@ class TileTest(test.TestCase): err = gradient_checker.compute_gradient_error(a, [4, 2], tiled, [4, 4]) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testGradientWithSparseGradWithRank1(self): inputs = constant_op.constant([1.0, 2.0, 3.0, 4.0], dtype=dtypes.float32) @@ -653,6 +672,7 @@ class TileTest(test.TestCase): outputs, outputs.get_shape().as_list()) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testGradientWithSparseGradWithRank3(self): inputs = constant_op.constant([1.0, 2.0, 3.0, 4.0], dtype=dtypes.float32) @@ -665,6 +685,7 @@ class TileTest(test.TestCase): outputs, outputs.get_shape().as_list()) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testShapeFunctionEdgeCases(self): # Unknown multiples shape. inp = constant_op.constant(0.0, shape=[4, 4, 4, 4]) diff --git a/tensorflow/python/kernel_tests/signal/BUILD b/tensorflow/python/kernel_tests/signal/BUILD index 56d4d46d46..8f4e31abe3 100644 --- a/tensorflow/python/kernel_tests/signal/BUILD +++ b/tensorflow/python/kernel_tests/signal/BUILD @@ -18,6 +18,35 @@ py_library( ], ) +cuda_py_tests( + name = "dct_ops_test", + srcs = ["dct_ops_test.py"], + additional_deps = [ + "@absl_py//absl/testing:parameterized", + "//third_party/py/numpy", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:spectral_ops_test_util", + "//tensorflow/python/ops/signal", + ], +) + +cuda_py_tests( + name = "fft_ops_test", + size = "medium", + srcs = ["fft_ops_test.py"], + additional_deps = [ + "//third_party/py/numpy", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:math_ops", + "//tensorflow/python:spectral_ops_test_util", + "//tensorflow/python/ops/signal", + ], + shard_count = 4, + tags = ["optonly"], +) + cuda_py_tests( name = "mel_ops_test", srcs = ["mel_ops_test.py"], @@ -91,9 +120,9 @@ cuda_py_tests( "//tensorflow/python:framework", "//tensorflow/python:framework_for_generated_wrappers", "//tensorflow/python:framework_test_lib", - "//tensorflow/python/ops/signal", "//tensorflow/python:platform_test", "//tensorflow/python:spectral_ops_test_util", + "//tensorflow/python/ops/signal", ], tags = ["nomac"], ) diff --git a/tensorflow/python/kernel_tests/dct_ops_test.py b/tensorflow/python/kernel_tests/signal/dct_ops_test.py similarity index 67% rename from tensorflow/python/kernel_tests/dct_ops_test.py rename to tensorflow/python/kernel_tests/signal/dct_ops_test.py index c9d0167608..a3ac15bab8 100644 --- a/tensorflow/python/kernel_tests/dct_ops_test.py +++ b/tensorflow/python/kernel_tests/signal/dct_ops_test.py @@ -20,10 +20,12 @@ from __future__ import print_function import importlib +from absl.testing import parameterized import numpy as np -from tensorflow.python.ops import spectral_ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import spectral_ops_test_util +from tensorflow.python.ops.signal import dct_ops from tensorflow.python.platform import test from tensorflow.python.platform import tf_logging @@ -40,6 +42,20 @@ def try_import(name): # pylint: disable=invalid-name fftpack = try_import("scipy.fftpack") +def _np_dct1(signals, norm=None): + """Computes the DCT-I manually with NumPy.""" + # X_k = (x_0 + (-1)**k * x_{N-1} + + # 2 * sum_{n=0}^{N-2} x_n * cos(\frac{pi}{N-1} * n * k) k=0,...,N-1 + del norm + dct_size = signals.shape[-1] + dct = np.zeros_like(signals) + for k in range(dct_size): + phi = np.cos(np.pi * np.arange(1, dct_size - 1) * k / (dct_size - 1)) + dct[..., k] = 2 * np.sum(signals[..., 1:-1] * phi, axis=-1) + ( + signals[..., 0] + (-1) ** k * signals[..., -1]) + return dct + + def _np_dct2(signals, norm=None): """Computes the DCT-II manually with NumPy.""" # X_k = sum_{n=0}^{N-1} x_n * cos(\frac{pi}{N} * (n + 0.5) * k) k=0,...,N-1 @@ -81,19 +97,19 @@ def _np_dct3(signals, norm=None): return dct -NP_DCT = {2: _np_dct2, 3: _np_dct3} -NP_IDCT = {2: _np_dct3, 3: _np_dct2} +NP_DCT = {1: _np_dct1, 2: _np_dct2, 3: _np_dct3} +NP_IDCT = {1: _np_dct1, 2: _np_dct3, 3: _np_dct2} -class DCTOpsTest(test.TestCase): +class DCTOpsTest(parameterized.TestCase, test.TestCase): def _compare(self, signals, norm, dct_type, atol=5e-4, rtol=5e-4): """Compares (I)DCT to SciPy (if available) and a NumPy implementation.""" np_dct = NP_DCT[dct_type](signals, norm) - tf_dct = spectral_ops.dct(signals, type=dct_type, norm=norm).eval() + tf_dct = dct_ops.dct(signals, type=dct_type, norm=norm).eval() self.assertAllClose(np_dct, tf_dct, atol=atol, rtol=rtol) np_idct = NP_IDCT[dct_type](signals, norm) - tf_idct = spectral_ops.idct(signals, type=dct_type, norm=norm).eval() + tf_idct = dct_ops.idct(signals, type=dct_type, norm=norm).eval() self.assertAllClose(np_idct, tf_idct, atol=atol, rtol=rtol) if fftpack: scipy_dct = fftpack.dct(signals, type=dct_type, norm=norm) @@ -101,38 +117,52 @@ class DCTOpsTest(test.TestCase): scipy_idct = fftpack.idct(signals, type=dct_type, norm=norm) self.assertAllClose(scipy_idct, tf_idct, atol=atol, rtol=rtol) # Verify inverse(forward(s)) == s, up to a normalization factor. - tf_idct_dct = spectral_ops.idct( + tf_idct_dct = dct_ops.idct( tf_dct, type=dct_type, norm=norm).eval() - tf_dct_idct = spectral_ops.dct( + tf_dct_idct = dct_ops.dct( tf_idct, type=dct_type, norm=norm).eval() if norm is None: - tf_idct_dct *= 0.5 / signals.shape[-1] - tf_dct_idct *= 0.5 / signals.shape[-1] + if dct_type == 1: + tf_idct_dct *= 0.5 / (signals.shape[-1] - 1) + tf_dct_idct *= 0.5 / (signals.shape[-1] - 1) + else: + tf_idct_dct *= 0.5 / signals.shape[-1] + tf_dct_idct *= 0.5 / signals.shape[-1] self.assertAllClose(signals, tf_idct_dct, atol=atol, rtol=rtol) self.assertAllClose(signals, tf_dct_idct, atol=atol, rtol=rtol) - def test_random(self): + @parameterized.parameters([ + [[2]], [[3]], [[10]], [[2, 20]], [[2, 3, 25]]]) + @test_util.run_deprecated_v1 + def test_random(self, shape): """Test randomly generated batches of data.""" with spectral_ops_test_util.fft_kernel_label_map(): with self.session(use_gpu=True): - for shape in ([1], [2], [3], [10], [2, 20], [2, 3, 25]): - signals = np.random.rand(*shape).astype(np.float32) - for norm in (None, "ortho"): - self._compare(signals, norm, 2) - self._compare(signals, norm, 3) + signals = np.random.rand(*shape).astype(np.float32) + # Normalization not implemented for orthonormal. + self._compare(signals, norm=None, dct_type=1) + for norm in (None, "ortho"): + self._compare(signals, norm, 2) + self._compare(signals, norm, 3) def test_error(self): signals = np.random.rand(10) # Unsupported type. with self.assertRaises(ValueError): - spectral_ops.dct(signals, type=1) + dct_ops.dct(signals, type=5) + # DCT-I normalization not implemented. + with self.assertRaises(ValueError): + dct_ops.dct(signals, type=1, norm="ortho") + # DCT-I requires at least two inputs. + with self.assertRaises(ValueError): + dct_ops.dct(np.random.rand(1), type=1) # Unknown normalization. with self.assertRaises(ValueError): - spectral_ops.dct(signals, norm="bad") + dct_ops.dct(signals, norm="bad") with self.assertRaises(NotImplementedError): - spectral_ops.dct(signals, n=10) + dct_ops.dct(signals, n=10) with self.assertRaises(NotImplementedError): - spectral_ops.dct(signals, axis=0) + dct_ops.dct(signals, axis=0) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/fft_ops_test.py b/tensorflow/python/kernel_tests/signal/fft_ops_test.py similarity index 96% rename from tensorflow/python/kernel_tests/fft_ops_test.py rename to tensorflow/python/kernel_tests/signal/fft_ops_test.py index 8592550f99..5b1053428c 100644 --- a/tensorflow/python/kernel_tests/fft_ops_test.py +++ b/tensorflow/python/kernel_tests/signal/fft_ops_test.py @@ -25,12 +25,13 @@ from tensorflow.core.protobuf import config_pb2 from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_spectral_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops -from tensorflow.python.ops import spectral_ops from tensorflow.python.ops import spectral_ops_test_util +from tensorflow.python.ops.signal import fft_ops from tensorflow.python.platform import test VALID_FFT_RANKS = (1, 2, 3) @@ -139,24 +140,25 @@ class FFTOpsTest(BaseFFTOpsTest): def _tfFFTForRank(self, rank): if rank == 1: - return spectral_ops.fft + return fft_ops.fft elif rank == 2: - return spectral_ops.fft2d + return fft_ops.fft2d elif rank == 3: - return spectral_ops.fft3d + return fft_ops.fft3d else: raise ValueError("invalid rank") def _tfIFFTForRank(self, rank): if rank == 1: - return spectral_ops.ifft + return fft_ops.ifft elif rank == 2: - return spectral_ops.ifft2d + return fft_ops.ifft2d elif rank == 3: - return spectral_ops.ifft3d + return fft_ops.ifft3d else: raise ValueError("invalid rank") + @test_util.run_deprecated_v1 def testEmpty(self): with spectral_ops_test_util.fft_kernel_label_map(): for np_type in (np.complex64, np.complex128): @@ -166,6 +168,7 @@ class FFTOpsTest(BaseFFTOpsTest): self.assertEqual(x.shape, self._tfFFT(x, rank).shape) self.assertEqual(x.shape, self._tfIFFT(x, rank).shape) + @test_util.run_deprecated_v1 def testBasic(self): with spectral_ops_test_util.fft_kernel_label_map(): for np_type, tol in ((np.complex64, 1e-4), (np.complex128, 1e-8)): @@ -194,6 +197,7 @@ class FFTOpsTest(BaseFFTOpsTest): # np.mod(np.arange(np.power(128, dims)), 64).reshape( # (128,) * dims).astype(np.complex64), rank) + @test_util.run_deprecated_v1 def testBasicPlaceholder(self): with spectral_ops_test_util.fft_kernel_label_map(): for np_type, tol in ((np.complex64, 1e-4), (np.complex128, 1e-8)): @@ -204,6 +208,7 @@ class FFTOpsTest(BaseFFTOpsTest): (4,) * dims).astype(np_type), rank, use_placeholder=True, rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testRandom(self): with spectral_ops_test_util.fft_kernel_label_map(): for np_type, tol in ((np.complex64, 1e-4), (np.complex128, 5e-6)): @@ -218,6 +223,7 @@ class FFTOpsTest(BaseFFTOpsTest): self._compare(gen((4,) * dims).astype(np_type), rank, rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testRandom1D(self): with spectral_ops_test_util.fft_kernel_label_map(): for np_type in (np.complex64, np.complex128): @@ -240,6 +246,7 @@ class FFTOpsTest(BaseFFTOpsTest): for dim in (127, 255, 511, 1023): self._compare(gen((dim,)).astype(np_type), 1, rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testError(self): for rank in VALID_FFT_RANKS: for dims in xrange(0, rank): @@ -251,6 +258,7 @@ class FFTOpsTest(BaseFFTOpsTest): ValueError, "Shape must be .*rank {}.*".format(rank)): self._tfIFFT(x, rank) + @test_util.run_deprecated_v1 def testGrad_Simple(self): with spectral_ops_test_util.fft_kernel_label_map(): for np_type, tol in ((np.float32, 1e-4), (np.float64, 1e-10)): @@ -263,6 +271,7 @@ class FFTOpsTest(BaseFFTOpsTest): self._checkGradComplex(self._tfIFFTForRank(rank), re, im, rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testGrad_Random(self): with spectral_ops_test_util.fft_kernel_label_map(): for np_type, tol in ((np.float32, 1e-2), (np.float64, 1e-10)): @@ -312,24 +321,25 @@ class RFFTOpsTest(BaseFFTOpsTest): def _tfFFTForRank(self, rank): if rank == 1: - return spectral_ops.rfft + return fft_ops.rfft elif rank == 2: - return spectral_ops.rfft2d + return fft_ops.rfft2d elif rank == 3: - return spectral_ops.rfft3d + return fft_ops.rfft3d else: raise ValueError("invalid rank") def _tfIFFTForRank(self, rank): if rank == 1: - return spectral_ops.irfft + return fft_ops.irfft elif rank == 2: - return spectral_ops.irfft2d + return fft_ops.irfft2d elif rank == 3: - return spectral_ops.irfft3d + return fft_ops.irfft3d else: raise ValueError("invalid rank") + @test_util.run_deprecated_v1 def testEmpty(self): with spectral_ops_test_util.fft_kernel_label_map(): for rank in VALID_FFT_RANKS: @@ -339,6 +349,7 @@ class RFFTOpsTest(BaseFFTOpsTest): x = np.zeros((0,) * dims).astype(np.complex64) self.assertEqual(x.shape, self._tfIFFT(x, rank).shape) + @test_util.run_deprecated_v1 def testBasic(self): with spectral_ops_test_util.fft_kernel_label_map(): for rank in VALID_FFT_RANKS: @@ -366,6 +377,7 @@ class RFFTOpsTest(BaseFFTOpsTest): 10).reshape((size,) * (dims - 1) + (inner_dim,)) self._compareBackward(c2r.astype(np.complex64), rank, (size,) * rank) + @test_util.run_deprecated_v1 def testBasicPlaceholder(self): with spectral_ops_test_util.fft_kernel_label_map(): for rank in VALID_FFT_RANKS: @@ -427,6 +439,7 @@ class RFFTOpsTest(BaseFFTOpsTest): fft_length, use_placeholder=True) + @test_util.run_deprecated_v1 def testRandom(self): with spectral_ops_test_util.fft_kernel_label_map(): def gen_real(shape): @@ -451,6 +464,7 @@ class RFFTOpsTest(BaseFFTOpsTest): self._compareBackward( gen_complex(complex_dims), rank, (size,) * rank) + @test_util.run_deprecated_v1 def testError(self): with spectral_ops_test_util.fft_kernel_label_map(): for rank in VALID_FFT_RANKS: @@ -507,6 +521,7 @@ class RFFTOpsTest(BaseFFTOpsTest): with self.cached_session(): irfft_fn(x, fft_length).eval() + @test_util.run_deprecated_v1 def testGrad_Simple(self): with spectral_ops_test_util.fft_kernel_label_map(): for rank in VALID_FFT_RANKS: @@ -521,6 +536,7 @@ class RFFTOpsTest(BaseFFTOpsTest): self._checkGradComplex( self._tfIFFTForRank(rank), re, im, result_is_complex=False) + @test_util.run_deprecated_v1 def testGrad_Random(self): with spectral_ops_test_util.fft_kernel_label_map(): for rank in VALID_FFT_RANKS: diff --git a/tensorflow/python/kernel_tests/signal/mel_ops_test.py b/tensorflow/python/kernel_tests/signal/mel_ops_test.py index 1ed4429b42..3134503dae 100644 --- a/tensorflow/python/kernel_tests/signal/mel_ops_test.py +++ b/tensorflow/python/kernel_tests/signal/mel_ops_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util as tf_test_util from tensorflow.python.kernel_tests.signal import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops.signal import mel_ops @@ -141,14 +142,16 @@ class LinearToMelTest(test.TestCase): for config in configs: mel_matrix_np = spectrogram_to_mel_matrix(*config) mel_matrix = mel_ops.linear_to_mel_weight_matrix(*config) - self.assertAllClose(mel_matrix_np, mel_matrix.eval(), atol=3e-6) + self.assertAllClose(mel_matrix_np, self.evaluate(mel_matrix), atol=3e-6) + @tf_test_util.run_deprecated_v1 def test_dtypes(self): # LinSpace is not supported for tf.float16. for dtype in (dtypes.bfloat16, dtypes.float32, dtypes.float64): self.assertEqual(dtype, mel_ops.linear_to_mel_weight_matrix(dtype=dtype).dtype) + @tf_test_util.run_deprecated_v1 def test_error(self): with self.assertRaises(ValueError): mel_ops.linear_to_mel_weight_matrix(num_mel_bins=0) @@ -177,6 +180,7 @@ class LinearToMelTest(test.TestCase): rewritten_graph = test_util.grappler_optimize(g, [mel_matrix]) self.assertEqual(1, len(rewritten_graph.node)) + @tf_test_util.run_deprecated_v1 def test_num_spectrogram_bins_dynamic(self): with self.session(use_gpu=True): num_spectrogram_bins = array_ops.placeholder(shape=(), diff --git a/tensorflow/python/kernel_tests/signal/mfcc_ops_test.py b/tensorflow/python/kernel_tests/signal/mfcc_ops_test.py index 79d23d77d1..935922657c 100644 --- a/tensorflow/python/kernel_tests/signal/mfcc_ops_test.py +++ b/tensorflow/python/kernel_tests/signal/mfcc_ops_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python.framework import dtypes from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import spectral_ops_test_util @@ -32,6 +33,7 @@ from tensorflow.python.platform import test # HTK conventions. class MFCCTest(test.TestCase): + @test_util.run_deprecated_v1 def test_error(self): # num_mel_bins must be positive. with self.assertRaises(ValueError): @@ -43,6 +45,7 @@ class MFCCTest(test.TestCase): signal = array_ops.zeros((2, 3, 5), dtype=dtypes.float64) mfcc_ops.mfccs_from_log_mel_spectrograms(signal) + @test_util.run_deprecated_v1 def test_basic(self): """A basic test that the op runs on random input.""" with spectral_ops_test_util.fft_kernel_label_map(): @@ -50,6 +53,7 @@ class MFCCTest(test.TestCase): signal = random_ops.random_normal((2, 3, 5)) mfcc_ops.mfccs_from_log_mel_spectrograms(signal).eval() + @test_util.run_deprecated_v1 def test_unknown_shape(self): """A test that the op runs when shape and rank are unknown.""" with spectral_ops_test_util.fft_kernel_label_map(): diff --git a/tensorflow/python/kernel_tests/signal/reconstruction_ops_test.py b/tensorflow/python/kernel_tests/signal/reconstruction_ops_test.py index c4e5b6f674..4cb6cedee9 100644 --- a/tensorflow/python/kernel_tests/signal/reconstruction_ops_test.py +++ b/tensorflow/python/kernel_tests/signal/reconstruction_ops_test.py @@ -20,8 +20,10 @@ from __future__ import print_function import numpy as np +from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import math_ops @@ -52,16 +54,75 @@ class ReconstructionOpsTest(test.TestCase): "100000000000000"] def test_all_ones(self): - signal = constant_op.constant(np.ones((3, 5)), dtype=dtypes.int64) + signal = array_ops.ones([3, 5]) reconstruction = reconstruction_ops.overlap_and_add(signal, 2) - with self.session(use_gpu=True) as sess: - output = sess.run(reconstruction) + self.assertEqual(reconstruction.shape.as_list(), [9]) + + with self.session(use_gpu=True): + output = self.evaluate(reconstruction) expected_output = np.array([1, 1, 2, 2, 3, 2, 2, 1, 1]) self.assertAllClose(output, expected_output) + def test_unknown_shapes(self): + # This test uses placeholders and does not work in eager mode. + if context.executing_eagerly(): + return + + signal = array_ops.placeholder(dtype=dtypes.int32, shape=[None, None, None]) + frame_step = array_ops.placeholder(dtype=dtypes.int32, shape=[]) + reconstruction = reconstruction_ops.overlap_and_add(signal, frame_step) + + self.assertEqual(reconstruction.shape.as_list(), [None, None]) + + with self.session(use_gpu=True) as sess: + output = sess.run(reconstruction, + feed_dict={signal: np.ones([4, 3, 5]), frame_step: 2}) + + expected_output = np.array([[1, 1, 2, 2, 3, 2, 2, 1, 1]] * 4) + + self.assertAllClose(output, expected_output) + + def test_unknown_rank(self): + # This test uses placeholders and does not work in eager mode. + if context.executing_eagerly(): + return + + signal = array_ops.placeholder(dtype=dtypes.int32, shape=None) + frame_step = array_ops.placeholder(dtype=dtypes.int32, shape=[]) + reconstruction = reconstruction_ops.overlap_and_add(signal, frame_step) + + self.assertEqual(reconstruction.shape, None) + + with self.session(use_gpu=True) as sess: + output = sess.run(reconstruction, + feed_dict={signal: np.ones([4, 3, 5]), frame_step: 2}) + + expected_output = np.array([[1, 1, 2, 2, 3, 2, 2, 1, 1]] * 4) + + self.assertAllClose(output, expected_output) + + def test_fast_path(self): + # This test uses tensor names and does not work in eager mode. + if context.executing_eagerly(): + return + + signal = array_ops.ones([3, 5]) + frame_step = 5 + reconstruction = reconstruction_ops.overlap_and_add(signal, frame_step) + + self.assertEqual(reconstruction.name, "overlap_and_add/fast_path:0") + + with self.session(use_gpu=True) as sess: + output = self.evaluate(reconstruction) + + expected_output = np.ones([15]) + + self.assertAllClose(output, expected_output) + + @test_util.run_deprecated_v1 def test_simple(self): def make_input(frame_length, num_frames=3): """Generate a tensor of num_frames frames of frame_length.""" @@ -98,8 +159,8 @@ class ReconstructionOpsTest(test.TestCase): dtype=dtypes.int64) reconstruction = reconstruction_ops.overlap_and_add(signal, self.frame_hop) - with self.session(use_gpu=True) as sess: - output = sess.run(reconstruction) + with self.session(use_gpu=True): + output = self.evaluate(reconstruction) string_output = [np.base_repr(x, self.bases[0]) for x in output] self.assertEqual(string_output, self.expected_string) @@ -108,8 +169,8 @@ class ReconstructionOpsTest(test.TestCase): signal = constant_op.constant(self.powers, dtype=dtypes.int64) reconstruction = reconstruction_ops.overlap_and_add(signal, self.frame_hop) - with self.session(use_gpu=True) as sess: - output = sess.run(reconstruction) + with self.session(use_gpu=True): + output = self.evaluate(reconstruction) accumulator = True for i in range(self.batch_size): @@ -124,8 +185,8 @@ class ReconstructionOpsTest(test.TestCase): signal = constant_op.constant(input_matrix, dtype=dtypes.float32) reconstruction = reconstruction_ops.overlap_and_add(signal, self.frame_hop) - with self.session(use_gpu=True) as sess: - output = sess.run(reconstruction) + with self.session(use_gpu=True): + output = self.evaluate(reconstruction) string_output = [np.base_repr(int(x), self.bases[0]) for x in np.squeeze(output)] @@ -133,6 +194,7 @@ class ReconstructionOpsTest(test.TestCase): self.assertEqual(output.shape, (1, 9)) self.assertEqual(string_output, self.expected_string) + @test_util.run_deprecated_v1 def test_gradient(self): configurations = [ ((1, 128), 1), @@ -154,6 +216,7 @@ class ReconstructionOpsTest(test.TestCase): gradient = sess.run(gradients_impl.gradients([loss], [signal])[0]) self.assertTrue((gradient == 1.0).all()) + @test_util.run_deprecated_v1 def test_gradient_batch(self): with self.session(use_gpu=True) as sess: signal = array_ops.zeros((2, 10, 10)) @@ -176,6 +239,7 @@ class ReconstructionOpsTest(test.TestCase): np.reshape(np.arange(100).astype(np.float32), (10, 10))]) self.assertAllEqual(expected_gradient, gradient) + @test_util.run_deprecated_v1 def test_gradient_numerical(self): with self.session(use_gpu=True): shape = (2, 10, 10) diff --git a/tensorflow/python/kernel_tests/signal/shape_ops_test.py b/tensorflow/python/kernel_tests/signal/shape_ops_test.py index 398fba8b6d..32ac76e80d 100644 --- a/tensorflow/python/kernel_tests/signal/shape_ops_test.py +++ b/tensorflow/python/kernel_tests/signal/shape_ops_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util as tf_test_util from tensorflow.python.kernel_tests.signal import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops @@ -32,6 +33,7 @@ from tensorflow.python.platform import test class FrameTest(test.TestCase): + @tf_test_util.run_deprecated_v1 def test_mapping_of_indices_without_padding(self): with self.session(use_gpu=True): tensor = constant_op.constant(np.arange(9152), dtypes.int32) @@ -47,6 +49,7 @@ class FrameTest(test.TestCase): self.assertAllEqual(expected, result) + @tf_test_util.run_deprecated_v1 def test_mapping_of_indices_with_padding(self): with self.session(use_gpu=True): tensor = constant_op.constant(np.arange(10000), dtypes.int32) @@ -64,6 +67,7 @@ class FrameTest(test.TestCase): self.assertAllEqual(expected, result) + @tf_test_util.run_deprecated_v1 def test_invalid_inputs(self): # Rank 0 input signal. with self.assertRaises(ValueError): @@ -84,6 +88,7 @@ class FrameTest(test.TestCase): with self.assertRaises(ValueError): shape_ops.frame([1], 1, 1, pad_end=True, pad_value=[1]) + @tf_test_util.run_deprecated_v1 def test_length_zero(self): signal = constant_op.constant([], dtype=dtypes.float32) frame_length = 2 @@ -98,6 +103,7 @@ class FrameTest(test.TestCase): pad_end=False).eval() self.assertEqual((0, 2), result.shape) + @tf_test_util.run_deprecated_v1 def test_shape_inference(self): signal = array_ops.placeholder(dtypes.int32, shape=[1, 1]) frame_length = 2 @@ -150,9 +156,10 @@ class FrameTest(test.TestCase): op = shape_ops.frame(signal, frame_length, frame_step, pad_end=pad_end, pad_value=99) with self.cached_session(use_gpu=True): - result = op.eval() + result = self.evaluate(op) self.assertEqual(op.shape.as_list(), list(result.shape)) + @tf_test_util.run_deprecated_v1 def test_basic_mono(self): signal = np.arange(6) frame_length = 3 @@ -178,6 +185,7 @@ class FrameTest(test.TestCase): pad_end=False).eval() self.assertAllEqual(expected, result) + @tf_test_util.run_deprecated_v1 def test_basic_stereo(self): signal = np.vstack([np.arange(6), np.arange(6) + 10]) @@ -207,6 +215,7 @@ class FrameTest(test.TestCase): pad_end=False).eval() self.assertAllEqual(expected, result) + @tf_test_util.run_deprecated_v1 def test_complex_shape(self): signal = np.vstack([np.arange(6), np.arange(6) + 10, @@ -248,7 +257,7 @@ class FrameTest(test.TestCase): result = shape_ops.frame(signal, frame_length=2, frame_step=2, pad_end=True, axis=1) expected = np.reshape(np.arange(16), (2, 2, 2, 2)) - self.assertAllEqual(expected, result.eval()) + self.assertAllEqual(expected, self.evaluate(result)) result = shape_ops.frame(signal, frame_length=2, frame_step=1, pad_end=True, axis=1) @@ -260,7 +269,7 @@ class FrameTest(test.TestCase): [[10, 11], [12, 13]], [[12, 13], [14, 15]], [[14, 15], [0, 0]]]] - self.assertAllEqual(expected, result.eval()) + self.assertAllEqual(expected, self.evaluate(result)) result = shape_ops.frame(signal, frame_length=3, frame_step=1, pad_end=True, axis=1) @@ -272,8 +281,9 @@ class FrameTest(test.TestCase): [[10, 11], [12, 13], [14, 15]], [[12, 13], [14, 15], [0, 0]], [[14, 15], [0, 0], [0, 0]]]] - self.assertAllEqual(expected, result.eval()) + self.assertAllEqual(expected, self.evaluate(result)) + @tf_test_util.run_deprecated_v1 def test_window_larger_than_signal(self): signal = constant_op.constant([[1, 2], [11, 12]], dtype=dtypes.float32) frame_length = 4 @@ -307,6 +317,7 @@ class FrameTest(test.TestCase): result = shape_ops.frame(signal, frame_length, frame_step) self.assertEqual(result.dtype, signal.dtype) + @tf_test_util.run_deprecated_v1 def test_dynamic_tensor(self): # Show that frame works even when the dimensions of its input are # not known at graph creation time. @@ -325,6 +336,7 @@ class FrameTest(test.TestCase): [[10, 11], [12, 13]], [[20, 21], [22, 23]]], result) + @tf_test_util.run_deprecated_v1 def test_gradient_numerical(self): with self.session(use_gpu=True): signal_shape = (2, 128) diff --git a/tensorflow/python/kernel_tests/signal/spectral_ops_test.py b/tensorflow/python/kernel_tests/signal/spectral_ops_test.py index 26cb127063..7b9748c7f2 100644 --- a/tensorflow/python/kernel_tests/signal/spectral_ops_test.py +++ b/tensorflow/python/kernel_tests/signal/spectral_ops_test.py @@ -125,22 +125,22 @@ class SpectralOpsTest(test.TestCase): stft = spectral_ops.stft(signal, frame_length=7, frame_step=8, pad_end=True) self.assertAllEqual([64, 5], stft.shape.as_list()) - self.assertAllEqual([64, 5], stft.eval().shape) + self.assertAllEqual([64, 5], self.evaluate(stft).shape) stft = spectral_ops.stft(signal, frame_length=8, frame_step=8, pad_end=True) self.assertAllEqual([64, 5], stft.shape.as_list()) - self.assertAllEqual([64, 5], stft.eval().shape) + self.assertAllEqual([64, 5], self.evaluate(stft).shape) stft = spectral_ops.stft(signal, frame_length=8, frame_step=8, fft_length=16, pad_end=True) self.assertAllEqual([64, 9], stft.shape.as_list()) - self.assertAllEqual([64, 9], stft.eval().shape) + self.assertAllEqual([64, 9], self.evaluate(stft).shape) stft = spectral_ops.stft(signal, frame_length=16, frame_step=8, fft_length=8, pad_end=True) self.assertAllEqual([64, 5], stft.shape.as_list()) - self.assertAllEqual([64, 5], stft.eval().shape) + self.assertAllEqual([64, 5], self.evaluate(stft).shape) stft = np.zeros((32, 9)).astype(np.complex64) @@ -148,7 +148,7 @@ class SpectralOpsTest(test.TestCase): fft_length=16, frame_step=8) expected_length = (stft.shape[0] - 1) * 8 + 8 self.assertAllEqual([256], inverse_stft.shape.as_list()) - self.assertAllEqual([expected_length], inverse_stft.eval().shape) + self.assertAllEqual([expected_length], self.evaluate(inverse_stft).shape) def test_stft_and_inverse_stft(self): """Test that spectral_ops.stft/inverse_stft match a NumPy implementation.""" @@ -235,7 +235,8 @@ class SpectralOpsTest(test.TestCase): inverse_window = inverse_window_fn(frame_length, dtype=dtypes.float32) with self.cached_session(use_gpu=True) as sess: - hann_window, inverse_window = sess.run([hann_window, inverse_window]) + hann_window, inverse_window = self.evaluate( + [hann_window, inverse_window]) # Expect unit gain at each phase of the window. product_window = hann_window * inverse_window @@ -263,7 +264,8 @@ class SpectralOpsTest(test.TestCase): inverse_window = inverse_window_fn(frame_length, dtype=dtypes.float32) with self.cached_session(use_gpu=True) as sess: - hann_window, inverse_window = sess.run([hann_window, inverse_window]) + hann_window, inverse_window = self.evaluate( + [hann_window, inverse_window]) self.assertAllClose(hann_window, inverse_window * 1.5) @@ -293,7 +295,7 @@ class SpectralOpsTest(test.TestCase): # the sum of the magnitude STFT. sinusoid = math_ops.sin( 2 * np.pi * math_ops.linspace(0.0, 1.0, signal_length)) - sinusoid_gradient = sess.run(self._compute_stft_gradient(sinusoid)) + sinusoid_gradient = self.evaluate(self._compute_stft_gradient(sinusoid)) self.assertFalse((sinusoid_gradient == 0.0).all()) def test_gradients_numerical(self): diff --git a/tensorflow/python/kernel_tests/signal/test_util.py b/tensorflow/python/kernel_tests/signal/test_util.py index f2c4d0dc8f..0a8a621c3e 100644 --- a/tensorflow/python/kernel_tests/signal/test_util.py +++ b/tensorflow/python/kernel_tests/signal/test_util.py @@ -18,12 +18,12 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.core.protobuf import rewriter_config_pb2 +from tensorflow.core.protobuf import config_pb2 from tensorflow.python.grappler import tf_optimizer from tensorflow.python.training import saver -def grappler_optimize(graph, fetches=None, rewriter_config=None): +def grappler_optimize(graph, fetches=None, config_proto=None): """Tries to optimize the provided graph using grappler. Args: @@ -31,17 +31,17 @@ def grappler_optimize(graph, fetches=None, rewriter_config=None): fetches: An optional list of `Tensor`s to fetch (i.e. not optimize away). Grappler uses the 'train_op' collection to look for fetches, so if not provided this collection should be non-empty. - rewriter_config: An optional `tf.RewriterConfig` to use when rewriting the + config_proto: An optional `tf.ConfigProto` to use when rewriting the graph. Returns: A `tf.GraphDef` containing the rewritten graph. """ - if rewriter_config is None: - rewriter_config = rewriter_config_pb2.RewriterConfig() - rewriter_config.min_graph_nodes = -1 + if config_proto is None: + config_proto = config_pb2.ConfigProto() + config_proto.graph_options.rewrite_options.min_graph_nodes = -1 if fetches is not None: for fetch in fetches: graph.add_to_collection('train_op', fetch) metagraph = saver.export_meta_graph(graph_def=graph.as_graph_def()) - return tf_optimizer.OptimizeGraph(rewriter_config, metagraph) + return tf_optimizer.OptimizeGraph(config_proto, metagraph) diff --git a/tensorflow/python/kernel_tests/signal/window_ops_test.py b/tensorflow/python/kernel_tests/signal/window_ops_test.py index 2f19134f5a..a72cdb288b 100644 --- a/tensorflow/python/kernel_tests/signal/window_ops_test.py +++ b/tensorflow/python/kernel_tests/signal/window_ops_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util as tf_test_util from tensorflow.python.kernel_tests.signal import test_util from tensorflow.python.ops.signal import window_ops from tensorflow.python.platform import test @@ -75,6 +76,7 @@ class WindowOpsTest(test.TestCase): dtype=tf_dtype).eval() self.assertAllClose(expected, actual, tol, tol) + @tf_test_util.run_deprecated_v1 def test_hann_window(self): """Check that hann_window matches scipy.signal.hann behavior.""" # The Hann window is a raised cosine window with parameters alpha=0.5 and @@ -84,6 +86,7 @@ class WindowOpsTest(test.TestCase): functools.partial(_scipy_raised_cosine, a=0.5, b=0.5), window_ops.hann_window) + @tf_test_util.run_deprecated_v1 def test_hamming_window(self): """Check that hamming_window matches scipy.signal.hamming's behavior.""" # The Hamming window is a raised cosine window with parameters alpha=0.54 diff --git a/tensorflow/python/kernel_tests/slice_op_test.py b/tensorflow/python/kernel_tests/slice_op_test.py index 41f040ab73..8f7245214a 100644 --- a/tensorflow/python/kernel_tests/slice_op_test.py +++ b/tensorflow/python/kernel_tests/slice_op_test.py @@ -24,6 +24,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import math_ops @@ -38,7 +39,7 @@ class SliceTest(test.TestCase): with self.cached_session(use_gpu=True): a = constant_op.constant(inp, shape=[4, 4], dtype=dtypes.float32) slice_t = a[2, k:k] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual(slice_val, inp[2, k:k]) def testInt32(self): @@ -47,7 +48,7 @@ class SliceTest(test.TestCase): with self.cached_session(use_gpu=True): a = constant_op.constant(inp, shape=[4, 4], dtype=dtypes.int32) slice_t = a[2, k:k] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual(slice_val, inp[2, k:k]) def testSlicingWithInt64Index(self): @@ -57,33 +58,33 @@ class SliceTest(test.TestCase): # Slice using int64 Tensor. i = constant_op.constant(1, dtype=dtypes.int64) slice_t = a[i] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual(1, slice_val) slice_t = a[i:i+1] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual([1], slice_val) # Slice using int64 integer. i = np.asarray(1).astype(np.int64) slice_t = a[i] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual(1, slice_val) slice_t = a[i:i+1] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual([1], slice_val) a_int32 = constant_op.constant([0, 1, 2], dtype=dtypes.int32) slice_t = array_ops.slice(a_int32, np.asarray([1]).astype(np.int64), np.asarray([2]).astype(np.int64)) - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual([1, 2], slice_val) a_float32 = constant_op.constant([0, 1, 2], dtype=dtypes.float32) slice_t = array_ops.slice(a_float32, np.asarray([1]).astype(np.int64), np.asarray([2]).astype(np.int64)) - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual([1, 2], slice_val) def testSlicingInt64Tensor(self): @@ -93,23 +94,23 @@ class SliceTest(test.TestCase): # Slice using int32 Tensor. i = constant_op.constant(1, dtype=dtypes.int32) slice_t = a[i] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual(1, slice_val) slice_t = a[i:i + 1] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual([1], slice_val) # Slice using int32 integer. i = np.asarray(1).astype(np.int32) slice_t = a[i] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual(1, slice_val) slice_t = a[i:i + 1] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual([1], slice_val) slice_t = array_ops.slice(a, [1], [2]) - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual([1, 2], slice_val) def testSelectAll(self): @@ -121,8 +122,8 @@ class SliceTest(test.TestCase): slice_explicit_t = array_ops.slice(a, [0, 0, 0, 0], [-1, -1, -1, -1]) slice_implicit_t = a[:, :, :, :] - self.assertAllEqual(inp, slice_explicit_t.eval()) - self.assertAllEqual(inp, slice_implicit_t.eval()) + self.assertAllEqual(inp, self.evaluate(slice_explicit_t)) + self.assertAllEqual(inp, self.evaluate(slice_implicit_t)) self.assertEqual(inp.shape, slice_explicit_t.get_shape()) self.assertEqual(inp.shape, slice_implicit_t.get_shape()) @@ -134,7 +135,7 @@ class SliceTest(test.TestCase): hi = np.random.randint(0, 9) scalar_t = a[hi] - scalar_val = scalar_t.eval() + scalar_val = self.evaluate(scalar_t) self.assertAllEqual(scalar_val, inp[hi]) if hi > 0: @@ -142,9 +143,10 @@ class SliceTest(test.TestCase): else: lo = 0 slice_t = a[lo:hi] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual(slice_val, inp[lo:hi]) + @test_util.run_deprecated_v1 def testScalarInput(self): input_val = 0 with self.cached_session() as sess: @@ -159,6 +161,7 @@ class SliceTest(test.TestCase): "out of range"): sess.run([slice_t], feed_dict={input_t: input_val}) + @test_util.run_deprecated_v1 def testInvalidIndex(self): input_val = [1, 2] with self.cached_session() as sess: @@ -179,6 +182,7 @@ class SliceTest(test.TestCase): np_ans = x[begin:begin + size, :] self.assertAllEqual(tf_ans, np_ans) + @test_util.run_deprecated_v1 def testSliceMatrixDim0(self): x = np.random.rand(8, 4).astype("f") self._testSliceMatrixDim0(x, 1, 2) @@ -195,7 +199,7 @@ class SliceTest(test.TestCase): x, y = np.random.randint(0, 3, size=2).tolist() slice_t = a[x, 0:y] - slice_val = slice_t.eval() + slice_val = self.evaluate(slice_t) self.assertAllEqual(slice_val, inp[x, 0:y]) def testSimple(self): @@ -207,12 +211,13 @@ class SliceTest(test.TestCase): dtype=dtypes.float32) slice_t = array_ops.slice(a, [0, 0], [2, 2]) slice2_t = a[:2, :2] - slice_val, slice2_val = sess.run([slice_t, slice2_t]) + slice_val, slice2_val = self.evaluate([slice_t, slice2_t]) self.assertAllEqual(slice_val, inp[:2, :2]) self.assertAllEqual(slice2_val, inp[:2, :2]) self.assertEqual(slice_val.shape, slice_t.get_shape()) self.assertEqual(slice2_val.shape, slice2_t.get_shape()) + @test_util.run_deprecated_v1 def testComplex(self): with self.session(use_gpu=True): inp = np.random.rand(4, 10, 10, 4).astype("f") @@ -247,7 +252,7 @@ class SliceTest(test.TestCase): + sizes[3], indices[4]:indices[4] + sizes[4], indices[5]: indices[5] + sizes[5]] - slice_val, slice2_val = sess.run([slice_t, slice2_t]) + slice_val, slice2_val = self.evaluate([slice_t, slice2_t]) expected_val = inp[indices[0]:indices[0] + sizes[0], indices[1]:indices[ 1] + sizes[1], indices[2]:indices[2] + sizes[2], indices[3]:indices[ @@ -282,7 +287,7 @@ class SliceTest(test.TestCase): grads = np.random.rand(num_grads).astype("f").reshape(slice_size) grad_tensor = constant_op.constant(grads) grad = gradients_impl.gradients(slice_t, [a], grad_tensor)[0] - result = grad.eval() + result = self.evaluate(grad) # Create a zero tensor of the input shape ane place # the grads into the right location to compare against TensorFlow. @@ -313,9 +318,10 @@ class SliceTest(test.TestCase): g1 = gradients_impl.gradients(loss1, x)[0] g2 = gradients_impl.gradients(loss2, x)[0] - g1_val, g2_val = sess.run([g1, g2]) + g1_val, g2_val = self.evaluate([g1, g2]) self.assertAllEqual(g1_val, g2_val) + @test_util.run_deprecated_v1 def testGradientsAll(self): # Slice the middle square out of a 4x4 input self._testGradientSlice([4, 4], [1, 1], [2, 2]) @@ -335,6 +341,7 @@ class SliceTest(test.TestCase): # Use -1 as a slice dimension on a 2D tensor. self._testGradientVariableSize2D() + @test_util.run_deprecated_v1 def testNotIterable(self): # NOTE(mrry): If we register __getitem__ as an overloaded # operator, Python will valiantly attempt to iterate over the @@ -346,6 +353,7 @@ class SliceTest(test.TestCase): for _ in c: pass + @test_util.run_deprecated_v1 def testComputedShape(self): # NOTE(mrry): We cannot currently handle partially-known values, # because `tf.slice()` uses -1 to specify a wildcard size, and @@ -368,7 +376,7 @@ class SliceTest(test.TestCase): c = b[:-1, :] d = c[1, :] res = 2 * d - c[1, :] + a[2, :] - 2 * b[-2, :] - self.assertAllEqual([0, 0, 0], res.eval()) + self.assertAllEqual([0, 0, 0], self.evaluate(res)) if __name__ == "__main__": diff --git a/tensorflow/python/kernel_tests/softmax_op_test.py b/tensorflow/python/kernel_tests/softmax_op_test.py index ef9301d4e3..707b8a429f 100644 --- a/tensorflow/python/kernel_tests/softmax_op_test.py +++ b/tensorflow/python/kernel_tests/softmax_op_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import nn_ops from tensorflow.python.platform import test @@ -64,7 +65,7 @@ class SoftmaxTest(test.TestCase): tf_softmax = nn_ops.log_softmax(np_features, axis=dim, name=name) else: tf_softmax = nn_ops.softmax(np_features, axis=dim, name=name) - out = tf_softmax.eval() + out = self.evaluate(tf_softmax) self.assertAllCloseAccordingToType(np_softmax, out) self.assertShapeEqual(np_softmax, tf_softmax) if not log: @@ -113,7 +114,7 @@ class SoftmaxTest(test.TestCase): features = np.array([[1., 1., 1., 1.], [max, 1., 2., 3.]]).astype(type) with self.cached_session(use_gpu=use_gpu): tf_log_softmax = nn_ops.log_softmax(features) - out = tf_log_softmax.eval() + out = self.evaluate(tf_log_softmax) self.assertAllClose( np.array([[-1.386294, -1.386294, -1.386294, -1.386294], [0, -max, -max, -max]]), @@ -206,6 +207,7 @@ class SoftmaxTest(test.TestCase): [[5., 4., 3., 2.], [1., 2., 3., 4.]]]) self.assertEqual([3, 2, 4], op.get_shape()) + @test_util.run_deprecated_v1 def testEmptyInput(self): with self.cached_session(): x = array_ops.placeholder(dtypes.float32, shape=[0, 3]) @@ -229,6 +231,7 @@ class SoftmaxTest(test.TestCase): with self.assertRaises(errors_impl.InvalidArgumentError): nn_ops.softmax(ones, axis=2).eval() + @test_util.run_deprecated_v1 def testLargeDims(self): # Make sure that we properly handle large inputs. See # https://github.com/tensorflow/tensorflow/issues/4425 for details diff --git a/tensorflow/python/kernel_tests/softplus_op_test.py b/tensorflow/python/kernel_tests/softplus_op_test.py index 50a8291ea8..5273dd7ffc 100644 --- a/tensorflow/python/kernel_tests/softplus_op_test.py +++ b/tensorflow/python/kernel_tests/softplus_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import nn_ops @@ -39,7 +40,7 @@ class SoftplusTest(test.TestCase): np_softplus = self._npSoftplus(np_features) with self.cached_session(use_gpu=use_gpu): softplus = nn_ops.softplus(np_features) - tf_softplus = softplus.eval() + tf_softplus = self.evaluate(softplus) self.assertAllCloseAccordingToType(np_softplus, tf_softplus) self.assertTrue(np.all(tf_softplus > 0)) self.assertShapeEqual(np_softplus, softplus) @@ -70,6 +71,7 @@ class SoftplusTest(test.TestCase): ], use_gpu=True) + @test_util.run_deprecated_v1 def testGradient(self): with self.cached_session(): x = constant_op.constant( @@ -86,6 +88,7 @@ class SoftplusTest(test.TestCase): print("softplus (float) gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testGradGrad(self): with self.cached_session(): x = constant_op.constant( @@ -103,6 +106,7 @@ class SoftplusTest(test.TestCase): print("softplus (float) gradient of gradient err = ", err) self.assertLess(err, 5e-5) + @test_util.run_deprecated_v1 def testGradGradGrad(self): with self.cached_session(): x = constant_op.constant( @@ -121,6 +125,7 @@ class SoftplusTest(test.TestCase): print("softplus (float) third-order gradient err = ", err) self.assertLess(err, 5e-5) + @test_util.run_deprecated_v1 def testNoInts(self): with self.cached_session(): with self.assertRaisesRegexp( diff --git a/tensorflow/python/kernel_tests/softsign_op_test.py b/tensorflow/python/kernel_tests/softsign_op_test.py index ee2e2e0303..5554240c82 100644 --- a/tensorflow/python/kernel_tests/softsign_op_test.py +++ b/tensorflow/python/kernel_tests/softsign_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import nn_ops import tensorflow.python.ops.nn_grad # pylint: disable=unused-import @@ -36,7 +37,7 @@ class SoftsignTest(test.TestCase): np_softsign = self._npSoftsign(np_features) with self.cached_session(use_gpu=use_gpu): softsign = nn_ops.softsign(np_features) - tf_softsign = softsign.eval() + tf_softsign = self.evaluate(softsign) self.assertAllClose(np_softsign, tf_softsign) self.assertShapeEqual(np_softsign, softsign) @@ -49,6 +50,7 @@ class SoftsignTest(test.TestCase): np.array([[-9, 7, -5, 3, -1], [1, -3, 5, -7, 9]]).astype(t), use_gpu=True) + @test_util.run_deprecated_v1 def testGradient(self): with self.cached_session(): x = constant_op.constant( @@ -65,6 +67,7 @@ class SoftsignTest(test.TestCase): print("softsign (float) gradient err = ", err) self.assertLess(err, 1e-4) + @test_util.run_deprecated_v1 def testNoInts(self): with self.cached_session(): with self.assertRaisesRegexp( diff --git a/tensorflow/python/kernel_tests/spacetobatch_op_test.py b/tensorflow/python/kernel_tests/spacetobatch_op_test.py index 21134adf2c..8641156604 100644 --- a/tensorflow/python/kernel_tests/spacetobatch_op_test.py +++ b/tensorflow/python/kernel_tests/spacetobatch_op_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_array_ops from tensorflow.python.ops import gradient_checker @@ -115,6 +116,7 @@ class SpaceToBatchTest(test.TestCase, PythonOpImpl): self._testPad(inputs, paddings, block_size, outputs) # [1, 2, 2, 1] <-> [4, 1, 1, 1] + @test_util.run_deprecated_v1 def testSmallInput2x2(self): x_np = [[[[1], [2]], [[3], [4]]]] block_size = 2 @@ -122,6 +124,7 @@ class SpaceToBatchTest(test.TestCase, PythonOpImpl): self._testOne(x_np, block_size, x_out) # [1, 2, 2, 1] <-> [1, 3, 3, 1] (padding) <-> [9, 1, 1, 1] + @test_util.run_deprecated_v1 def testSmallInput2x2Pad1x0(self): x_np = [[[[1], [2]], [[3], [4]]]] paddings = np.array([[1, 0], [1, 0]], dtype=np.int32) @@ -132,6 +135,7 @@ class SpaceToBatchTest(test.TestCase, PythonOpImpl): # Test with depth larger than 1. # [1, 2, 2, 3] <-> [4, 1, 1, 3] + @test_util.run_deprecated_v1 def testDepthInput2x2(self): x_np = [[[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]] block_size = 2 @@ -140,6 +144,7 @@ class SpaceToBatchTest(test.TestCase, PythonOpImpl): # Test for larger input dimensions. # [1, 4, 4, 1] <-> [4, 2, 2, 1] + @test_util.run_deprecated_v1 def testLargerInput2x2(self): x_np = [[[[1], [2], [3], [4]], [[5], [6], [7], [8]], [[9], [10], [11], [12]], [[13], [14], [15], [16]]]] @@ -150,6 +155,7 @@ class SpaceToBatchTest(test.TestCase, PythonOpImpl): # Test with batch larger than 1. # [2, 2, 4, 1] <-> [8, 1, 2, 1] + @test_util.run_deprecated_v1 def testBatchInput2x2(self): x_np = [[[[1], [2], [3], [4]], [[5], [6], [7], [8]]], [[[9], [10], [11], [12]], [[13], [14], [15], [16]]]] @@ -162,6 +168,7 @@ class SpaceToBatchTest(test.TestCase, PythonOpImpl): # that elements are correctly laid out spatially and properly interleaved # along the batch dimension. # [2, 4, 4, 1] <-> [8, 2, 2, 1] + @test_util.run_deprecated_v1 def testLargerInputBatch2x2(self): x_np = [[[[1], [2], [3], [4]], [[5], [6], [7], [8]], [[9], [10], [11], [12]], [[13], [14], [15], [16]]], @@ -206,6 +213,7 @@ class SpaceToBatchNDTest(test.TestCase): self._testPad(inputs, block_shape, paddings, space_to_batch_direct(inputs, block_shape, paddings)) + @test_util.run_deprecated_v1 def testZeroBlockDimsZeroRemainingDims(self): self._testPad( inputs=[1, 2], @@ -213,6 +221,7 @@ class SpaceToBatchNDTest(test.TestCase): paddings=[], outputs=[1, 2],) + @test_util.run_deprecated_v1 def testZeroBlockDimsOneRemainingDim(self): self._testPad( inputs=[[1, 2], [3, 4]], @@ -227,6 +236,7 @@ class SpaceToBatchNDTest(test.TestCase): paddings=[[0, 0]], outputs=[[1, 2], [3, 4]]) + @test_util.run_deprecated_v1 def testZeroBlockDimsTwoRemainingDims(self): self._testPad( inputs=[[[1, 2], [3, 4]], [[5, 6], [7, 8]]], @@ -248,6 +258,7 @@ class SpaceToBatchNDTest(test.TestCase): paddings=[[0, 0], [0, 0]], outputs=[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) + @test_util.run_deprecated_v1 def testOneBlockDimZeroRemainingDims(self): self._testPad( inputs=[[1, 2, 3], [4, 5, 6]], @@ -255,6 +266,7 @@ class SpaceToBatchNDTest(test.TestCase): paddings=[1, 0], outputs=[[0, 2], [0, 5], [1, 3], [4, 6]]) + @test_util.run_deprecated_v1 def testOneBlockDimOneRemainingDim(self): self._testPad( inputs=[[[1, 11], [2, 21], [3, 31]], [[4, 41], [5, 51], [6, 61]]], @@ -263,6 +275,7 @@ class SpaceToBatchNDTest(test.TestCase): outputs=[[[0, 0], [2, 21]], [[0, 0], [5, 51]], [[1, 11], [3, 31]], [[4, 41], [6, 61]]]) + @test_util.run_deprecated_v1 def testDirect(self): # Test with zero-size remaining dimension. self._testDirect( @@ -300,6 +313,7 @@ class SpaceToBatchNDTest(test.TestCase): class SpaceToBatchSpaceToDepth(test.TestCase, PythonOpImpl): # Verifies that: space_to_batch(x) = transpose(space_to_depth(transpose(x))) + @test_util.run_deprecated_v1 def testSpaceToDepthTranspose(self): x = np.arange(5 * 10 * 16 * 7, dtype=np.float32).reshape([5, 10, 16, 7]) block_size = 2 @@ -319,6 +333,7 @@ class SpaceToBatchSpaceToDepthCpp(SpaceToBatchSpaceToDepth, CppOpImpl): class SpaceToBatchErrorHandlingTest(test.TestCase, PythonOpImpl): + @test_util.run_deprecated_v1 def testInputWrongDimMissingBatch(self): # The input is missing the first dimension ("batch") x_np = [[[1], [2]], [[3], [4]]] @@ -327,6 +342,7 @@ class SpaceToBatchErrorHandlingTest(test.TestCase, PythonOpImpl): with self.assertRaises(ValueError): _ = self.space_to_batch(x_np, paddings, block_size) + @test_util.run_deprecated_v1 def testBlockSize0(self): # The block size is 0. x_np = [[[[1], [2]], [[3], [4]]]] @@ -336,6 +352,7 @@ class SpaceToBatchErrorHandlingTest(test.TestCase, PythonOpImpl): out_tf = self.space_to_batch(x_np, paddings, block_size) out_tf.eval() + @test_util.run_deprecated_v1 def testBlockSizeOne(self): # The block size is 1. The block size needs to be > 1. x_np = [[[[1], [2]], [[3], [4]]]] @@ -345,6 +362,7 @@ class SpaceToBatchErrorHandlingTest(test.TestCase, PythonOpImpl): out_tf = self.space_to_batch(x_np, paddings, block_size) out_tf.eval() + @test_util.run_deprecated_v1 def testBlockSizeLarger(self): # The block size is too large for this input. x_np = [[[[1], [2]], [[3], [4]]]] @@ -354,6 +372,7 @@ class SpaceToBatchErrorHandlingTest(test.TestCase, PythonOpImpl): out_tf = self.space_to_batch(x_np, paddings, block_size) out_tf.eval() + @test_util.run_deprecated_v1 def testBlockSizeNotDivisibleWidth(self): # The block size divides width but not height. x_np = [[[[1], [2], [3]], [[3], [4], [7]]]] @@ -362,6 +381,7 @@ class SpaceToBatchErrorHandlingTest(test.TestCase, PythonOpImpl): with self.assertRaises(ValueError): _ = self.space_to_batch(x_np, paddings, block_size) + @test_util.run_deprecated_v1 def testBlockSizeNotDivisibleHeight(self): # The block size divides height but not width. x_np = [[[[1], [2]], [[3], [4]], [[5], [6]]]] @@ -370,6 +390,7 @@ class SpaceToBatchErrorHandlingTest(test.TestCase, PythonOpImpl): with self.assertRaises(ValueError): _ = self.space_to_batch(x_np, paddings, block_size) + @test_util.run_deprecated_v1 def testBlockSizeNotDivisibleBoth(self): # The block size does not divide neither width or height. x_np = [[[[1], [2]], [[3], [4]]]] @@ -378,6 +399,7 @@ class SpaceToBatchErrorHandlingTest(test.TestCase, PythonOpImpl): with self.assertRaises(ValueError): _ = self.space_to_batch(x_np, paddings, block_size) + @test_util.run_deprecated_v1 def testUnknownShape(self): t = self.space_to_batch( array_ops.placeholder(dtypes.float32), @@ -424,25 +446,31 @@ class SpaceToBatchNDErrorHandlingTest(test.TestCase): self._testStaticShape(input_shape, block_shape, paddings, error) self._testDynamicShape(input_shape, block_shape, paddings) + @test_util.run_deprecated_v1 def testBlockSize0(self): # The block size is 0. self._testShape([1, 2, 2], [0, 2], [[0, 0], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testBlockSizeNegative(self): self._testShape([1, 2, 2], [-1, 2], [[0, 0], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testNegativePadding(self): # The padding is negative. self._testShape([1, 2, 2], [1, 1], [[0, -1], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testBlockSizeNotDivisible(self): # The padded size is not divisible by the block size. self._testShape([1, 2, 3, 1], [3, 3], [[0, 0], [0, 0]], ValueError) + @test_util.run_deprecated_v1 def testBlockDimsMismatch(self): # Shape of block_shape does not match shape of paddings. self._testStaticShape([1, 3, 3, 1], [3, 3], [[0, 0]], ValueError) + @test_util.run_deprecated_v1 def testUnknown(self): # Verify that input shape and paddings shape can be unknown. _ = array_ops.space_to_batch_nd( @@ -522,18 +550,21 @@ class SpaceToBatchGradientTest(test.TestCase, PythonOpImpl): # Don't use very large numbers as dimensions here as the result is tensor # with cartesian product of the dimensions. + @test_util.run_deprecated_v1 def testSmall(self): block_size = 2 pad_beg = 0 pad_end = 0 self._compare(1, 2, 3, 5, block_size, pad_beg, pad_end) + @test_util.run_deprecated_v1 def testSmall2(self): block_size = 2 pad_beg = 0 pad_end = 0 self._compare(2, 4, 3, 2, block_size, pad_beg, pad_end) + @test_util.run_deprecated_v1 def testSmallPad1x1(self): block_size = 2 pad_beg = 1 @@ -572,15 +603,19 @@ class SpaceToBatchNDGradientTest(test.TestCase): # Don't use very large numbers as dimensions here as the result is tensor # with cartesian product of the dimensions. + @test_util.run_deprecated_v1 def testSmall(self): self._compare([1, 4, 6, 5], [2, 2], [[0, 0], [0, 0]]) + @test_util.run_deprecated_v1 def testSmall2(self): self._compare([2, 8, 6, 2], [2, 2], [[0, 0], [0, 0]]) + @test_util.run_deprecated_v1 def testSmallPad1(self): self._compare([2, 4, 6, 2], [2, 2], [[1, 1], [1, 1]]) + @test_util.run_deprecated_v1 def testSmallPadThreeBlockDims(self): self._compare([2, 2, 4, 3, 2], [2, 2, 2], [[1, 1], [1, 1], [1, 0]]) @@ -644,6 +679,7 @@ class RequiredSpaceToBatchPaddingsTest(test.TestCase): self.assertAllEqual(paddings_result, paddings_const) self.assertAllEqual(crops_result, crops_const) + @test_util.run_deprecated_v1 def testSimple(self): self._test( input_shape=np.zeros((0,), np.int32), diff --git a/tensorflow/python/kernel_tests/spacetodepth_op_test.py b/tensorflow/python/kernel_tests/spacetodepth_op_test.py index b05f14f738..e96bc09f36 100644 --- a/tensorflow/python/kernel_tests/spacetodepth_op_test.py +++ b/tensorflow/python/kernel_tests/spacetodepth_op_test.py @@ -36,21 +36,22 @@ class SpaceToDepthTest(test.TestCase): def _testOne(self, inputs, block_size, outputs, dtype=dtypes.float32): input_nhwc = math_ops.cast(inputs, dtype) - with self.session(use_gpu=False): + with test_util.force_cpu(): # test NHWC (default) on CPU x_tf = array_ops.space_to_depth(input_nhwc, block_size) - self.assertAllEqual(x_tf.eval(), outputs) - if test.is_gpu_available(): - with self.session(force_gpu=True): + self.assertAllEqual(self.evaluate(x_tf), outputs) + + if test_util.is_gpu_available(): + with test_util.force_gpu(): # test NHWC (default) on GPU x_tf = array_ops.space_to_depth(input_nhwc, block_size) - self.assertAllEqual(x_tf.eval(), outputs) + self.assertAllEqual(self.evaluate(x_tf), outputs) # test NCHW on GPU input_nchw = test_util.NHWCToNCHW(input_nhwc) output_nchw = array_ops.space_to_depth( input_nchw, block_size, data_format="NCHW") output_nhwc = test_util.NCHWToNHWC(output_nchw) - self.assertAllEqual(output_nhwc.eval(), outputs) + self.assertAllEqual(self.evaluate(output_nhwc), outputs) def testBasic(self): x_np = [[[[1], [2]], [[3], [4]]]] @@ -134,17 +135,18 @@ class SpaceToDepthTest(test.TestCase): input_nhwc = array_ops.ones([batch_size, 4, 6, 3]) x_out = array_ops.ones([batch_size, 2, 3, 12]) - with self.session(use_gpu=False): + with test_util.force_cpu(): # test NHWC (default) on CPU x_tf = array_ops.space_to_depth(input_nhwc, block_size) self.assertAllEqual(x_tf.shape, x_out.shape) - x_tf.eval() + self.evaluate(x_tf) + if test.is_gpu_available(): - with self.session(use_gpu=True): + with test_util.use_gpu(): # test NHWC (default) on GPU x_tf = array_ops.space_to_depth(input_nhwc, block_size) self.assertAllEqual(x_tf.shape, x_out.shape) - x_tf.eval() + self.evaluate(x_tf) # Tests for different width and height. def testNonSquare(self): @@ -157,14 +159,16 @@ class SpaceToDepthTest(test.TestCase): # Error handling: + @test_util.run_deprecated_v1 def testInputWrongDimMissingDepth(self): # The input is missing the last dimension ("depth") x_np = [[[1, 2], [3, 4]]] block_size = 2 with self.assertRaises(ValueError): out_tf = array_ops.space_to_depth(x_np, block_size) - out_tf.eval() + self.evaluate(out_tf) + @test_util.run_deprecated_v1 def testInputWrongDimMissingBatch(self): # The input is missing the first dimension ("batch") x_np = [[[1], [2]], [[3], [4]]] @@ -172,30 +176,34 @@ class SpaceToDepthTest(test.TestCase): with self.assertRaises(ValueError): _ = array_ops.space_to_depth(x_np, block_size) + @test_util.run_deprecated_v1 def testBlockSize0(self): # The block size is 0. x_np = [[[[1], [2]], [[3], [4]]]] block_size = 0 with self.assertRaises(ValueError): out_tf = array_ops.space_to_depth(x_np, block_size) - out_tf.eval() + self.evaluate(out_tf) + @test_util.run_deprecated_v1 def testBlockSizeOne(self): # The block size is 1. The block size needs to be > 1. x_np = [[[[1], [2]], [[3], [4]]]] block_size = 1 with self.assertRaises(ValueError): out_tf = array_ops.space_to_depth(x_np, block_size) - out_tf.eval() + self.evaluate(out_tf) + @test_util.run_deprecated_v1 def testBlockSizeLarger(self): # The block size is too large for this input. x_np = [[[[1], [2]], [[3], [4]]]] block_size = 10 with self.assertRaises(ValueError): out_tf = array_ops.space_to_depth(x_np, block_size) - out_tf.eval() + self.evaluate(out_tf) + @test_util.run_deprecated_v1 def testBlockSizeNotDivisibleWidth(self): # The block size divides width but not height. x_np = [[[[1], [2], [3]], [[3], [4], [7]]]] @@ -203,6 +211,7 @@ class SpaceToDepthTest(test.TestCase): with self.assertRaises(ValueError): _ = array_ops.space_to_depth(x_np, block_size) + @test_util.run_deprecated_v1 def testBlockSizeNotDivisibleHeight(self): # The block size divides height but not width. x_np = [[[[1], [2]], [[3], [4]], [[5], [6]]]] @@ -210,6 +219,7 @@ class SpaceToDepthTest(test.TestCase): with self.assertRaises(ValueError): _ = array_ops.space_to_depth(x_np, block_size) + @test_util.run_deprecated_v1 def testBlockSizeNotDivisibleBoth(self): # The block size does not divide neither width or height. x_np = [[[[1], [2]], [[3], [4]]]] @@ -217,6 +227,7 @@ class SpaceToDepthTest(test.TestCase): with self.assertRaises(ValueError): _ = array_ops.space_to_depth(x_np, block_size) + @test_util.run_deprecated_v1 def testUnknownShape(self): t = array_ops.space_to_depth( array_ops.placeholder(dtypes.float32), block_size=4) @@ -271,7 +282,7 @@ class SpaceToDepthTest(test.TestCase): actual = array_ops.space_to_depth(t, block_size, data_format=data_format) with self.cached_session(use_gpu=use_gpu) as sess: - actual_vals, expected_vals = sess.run([actual, expected]) + actual_vals, expected_vals = self.evaluate([actual, expected]) self.assertTrue(np.array_equal(actual_vals, expected_vals)) def testAgainstTranspose(self): @@ -332,11 +343,13 @@ class SpaceToDepthGradientTest(test.TestCase): # Don't use very large numbers as dimensions here as the result is tensor # with cartesian product of the dimensions. + @test_util.run_deprecated_v1 def testSmall(self): block_size = 2 self._compare(1, 2, 3, 5, block_size, "NHWC") self._compare(1, 2, 3, 5, block_size, "NCHW") + @test_util.run_deprecated_v1 def testSmall2(self): block_size = 2 self._compare(2, 4, 3, 2, block_size, "NHWC") diff --git a/tensorflow/python/kernel_tests/sparse_add_op_test.py b/tensorflow/python/kernel_tests/sparse_add_op_test.py index a746830afb..00eff54077 100644 --- a/tensorflow/python/kernel_tests/sparse_add_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_add_op_test.py @@ -28,6 +28,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops from tensorflow.python.ops import sparse_ops @@ -85,13 +86,13 @@ class SparseAddTest(test.TestCase): constant_op.constant(shape, dtypes.int64)) def testAddSelf(self): - with self.session(use_gpu=False) as sess: + with test_util.force_cpu(): for sp_a in (self._SparseTensorValue_3x3(), self._SparseTensor_3x3()): for sp_b in (self._SparseTensorValue_3x3(), self._SparseTensor_3x3()): sp_sum = sparse_ops.sparse_add(sp_a, sp_b) self.assertAllEqual((3, 3), sp_sum.get_shape()) - sum_out = sess.run(sp_sum) + sum_out = self.evaluate(sp_sum) self.assertEqual(sp_sum.dense_shape.get_shape(), [2]) self.assertAllEqual(sum_out.indices, [[0, 1], [1, 0], [2, 0], [2, 1]]) @@ -99,12 +100,12 @@ class SparseAddTest(test.TestCase): self.assertAllEqual(sum_out.dense_shape, [3, 3]) def testAddSelfAndNegation(self): - with self.session(use_gpu=False) as sess: + with test_util.force_cpu(): sp_a = self._SparseTensor_3x3() sp_b = self._SparseTensor_3x3(negate=True) sp_sum = sparse_ops.sparse_add(sp_a, sp_b, 0.1) - sum_out = sess.run(sp_sum) + sum_out = self.evaluate(sp_sum) self.assertEqual(sp_sum.dense_shape.get_shape(), [2]) self.assertAllEqual(sum_out.indices, np.empty([0, 2])) @@ -112,7 +113,7 @@ class SparseAddTest(test.TestCase): self.assertAllEqual(sum_out.dense_shape, [3, 3]) def testSmallValuesShouldVanish(self): - with self.session(use_gpu=False) as sess: + with test_util.force_cpu(): sp_a = self._SparseTensor_3x3() sp_b = self._SparseTensor_3x3_v2() @@ -123,7 +124,7 @@ class SparseAddTest(test.TestCase): # two values should vanish: |.1| < .21, and |-.2| < .21 sp_sum = sparse_ops.sparse_add(sp_a, sp_b, thresh=0.21) - sum_out = sess.run(sp_sum) + sum_out = self.evaluate(sp_sum) self.assertEqual(sp_sum.dense_shape.get_shape(), [2]) self.assertAllEqual(sum_out.indices, [[0, 1], [2, 0]]) @@ -132,13 +133,14 @@ class SparseAddTest(test.TestCase): # only .1 vanishes sp_sum = sparse_ops.sparse_add(sp_a, sp_b, thresh=0.11) - sum_out = sess.run(sp_sum) + sum_out = self.evaluate(sp_sum) self.assertEqual(sp_sum.dense_shape.get_shape(), [2]) self.assertAllEqual(sum_out.indices, [[0, 1], [2, 0], [2, 1]]) self.assertAllClose(sum_out.values, [2, 6, -.2]) self.assertAllEqual(sum_out.dense_shape, [3, 3]) + @test_util.run_deprecated_v1 def testGradients(self): np.random.seed(1618) # Make it reproducible. with self.session(use_gpu=False): @@ -147,7 +149,7 @@ class SparseAddTest(test.TestCase): sp_a, nnz_a = self._randomTensor([n, m], np.float32) sp_b, nnz_b = self._randomTensor([n, m], np.float32) sp_sum = sparse_ops.sparse_add(sp_a, sp_b) - nnz_sum = len(sp_sum.values.eval()) + nnz_sum = len(self.evaluate(sp_sum.values)) err = gradient_checker.compute_gradient_error( [sp_a.values, sp_b.values], [(nnz_a,), (nnz_b,)], sp_sum.values, @@ -162,19 +164,20 @@ class SparseAddTest(test.TestCase): rand_vals_np = np.random.randn(n, m).astype(dtype) dense_np = np.random.randn(n, m).astype(dtype) - with self.cached_session(use_gpu=False): + with test_util.force_cpu(): sparse, unused_nnz = _sparsify(rand_vals_np, index_dtype=index_dtype) - s = sparse_ops.sparse_add(sparse, - constant_op.constant(dense_np)).eval() + s = self.evaluate( + sparse_ops.sparse_add(sparse, constant_op.constant(dense_np))) self.assertAllEqual(dense_np + rand_vals_np, s) self.assertTrue(s.dtype == dtype) # check commutativity - s = sparse_ops.sparse_add(constant_op.constant(dense_np), - sparse).eval() + s = self.evaluate( + sparse_ops.sparse_add(constant_op.constant(dense_np), sparse)) self.assertAllEqual(dense_np + rand_vals_np, s) self.assertTrue(s.dtype == dtype) + @test_util.run_deprecated_v1 def testSparseTensorDenseAddGradients(self): np.random.seed(1618) # Make it reproducible. n, m = np.random.randint(30, size=2) @@ -190,8 +193,9 @@ class SparseAddTest(test.TestCase): [(nnz,), (n, m)], s, (n, m)) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testInvalidSparseTensor(self): - with self.session(use_gpu=False) as sess: + with test_util.force_cpu(): shape = [2, 2] val = [0] dense = constant_op.constant(np.zeros(shape, dtype=np.int32)) @@ -205,7 +209,7 @@ class SparseAddTest(test.TestCase): with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, "invalid index"): - sess.run(s) + self.evaluate(s) ######################## Benchmarking code diff --git a/tensorflow/python/kernel_tests/sparse_concat_op_test.py b/tensorflow/python/kernel_tests/sparse_concat_op_test.py index 402c5eb4ea..04b6b9b8d2 100644 --- a/tensorflow/python/kernel_tests/sparse_concat_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_concat_op_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.platform import test @@ -147,7 +148,7 @@ class SparseConcatTest(test.TestCase): self.assertEqual(sp_concat.values.get_shape(), [4]) self.assertEqual(sp_concat.dense_shape.get_shape(), [2]) - concat_out = sess.run(sp_concat) + concat_out = self.evaluate(sp_concat) self.assertAllEqual(concat_out.indices, [[0, 2], [1, 0], [2, 0], [2, 2]]) @@ -169,7 +170,7 @@ class SparseConcatTest(test.TestCase): self.assertEqual(sp_concat.values.get_shape(), [8]) self.assertEqual(sp_concat.dense_shape.get_shape(), [2]) - concat_out = sess.run(sp_concat) + concat_out = self.evaluate(sp_concat) self.assertAllEqual(concat_out.indices, [[0, 2], [1, 0], [1, 4], [2, 0], [2, 2], [2, 3], @@ -195,7 +196,7 @@ class SparseConcatTest(test.TestCase): self.assertEqual(sp_concat.values.get_shape(), [7]) self.assertEqual(sp_concat.dense_shape.get_shape(), [2]) - concat_out = sess.run(sp_concat) + concat_out = self.evaluate(sp_concat) self.assertAllEqual( concat_out.indices, @@ -220,7 +221,7 @@ class SparseConcatTest(test.TestCase): self.assertEqual(sp_concat.values.get_shape(), [10]) self.assertEqual(sp_concat.dense_shape.get_shape(), [2]) - concat_out = sess.run(sp_concat) + concat_out = self.evaluate(sp_concat) self.assertAllEqual(concat_out.indices, [[0, 2], [1, 0], [1, 4], [1, 8], [2, 0], [2, 2], [2, 3], [2, 6], @@ -244,7 +245,7 @@ class SparseConcatTest(test.TestCase): self.assertEqual(sp_concat.values.get_shape(), [8]) self.assertEqual(sp_concat.dense_shape.get_shape(), [2]) - concat_out = sess.run(sp_concat) + concat_out = self.evaluate(sp_concat) self.assertAllEqual( concat_out.indices, @@ -253,6 +254,7 @@ class SparseConcatTest(test.TestCase): [b"a", b"b", b"e", b"c", b"d", b"f", b"g", b"h"]) self.assertAllEqual(concat_out.dense_shape, [3, 8]) + @test_util.run_deprecated_v1 def testMismatchedRank(self): with self.session(use_gpu=False): sp_a = self._SparseTensor_3x3() @@ -263,6 +265,7 @@ class SparseConcatTest(test.TestCase): with self.assertRaises(ValueError): sparse_ops.sparse_concat(concat_dim, [sp_a, sp_e]) + @test_util.run_deprecated_v1 def testMismatchedRankExpandNonconcatDim(self): with self.session(use_gpu=False): sp_a = self._SparseTensor_3x3() @@ -275,6 +278,7 @@ class SparseConcatTest(test.TestCase): sparse_ops.sparse_concat( concat_dim, [sp_a, sp_e], expand_nonconcat_dim=True) + @test_util.run_deprecated_v1 def testMismatchedShapes(self): with self.session(use_gpu=False) as sess: sp_a = self._SparseTensor_3x3() @@ -287,7 +291,7 @@ class SparseConcatTest(test.TestCase): # Shape mismatches can only be caught when the op is run with self.assertRaisesOpError("Input shapes must match"): - sess.run(sp_concat) + self.evaluate(sp_concat) def testMismatchedShapesExpandNonconcatDim(self): with self.session(use_gpu=False) as sess: @@ -302,8 +306,8 @@ class SparseConcatTest(test.TestCase): sp_concat_dim1 = sparse_ops.sparse_concat( concat_dim1, [sp_a, sp_b, sp_c, sp_d], expand_nonconcat_dim=True) - sp_concat_dim0_out = sess.run(sp_concat_dim0) - sp_concat_dim1_out = sess.run(sp_concat_dim1) + sp_concat_dim0_out = self.evaluate(sp_concat_dim0) + sp_concat_dim1_out = self.evaluate(sp_concat_dim1) self.assertAllEqual(sp_concat_dim0_out.indices, [[0, 2], [1, 0], [2, 0], [2, 2], [4, 1], [5, 0], @@ -321,6 +325,7 @@ class SparseConcatTest(test.TestCase): [1, 1, 2, 1, 1, 1, 2, 3, 4, 2, 1, 0, 2]) self.assertAllEqual(sp_concat_dim1_out.dense_shape, [3, 13]) + @test_util.run_deprecated_v1 def testShapeInferenceUnknownShapes(self): with self.session(use_gpu=False): sp_inputs = [ diff --git a/tensorflow/python/kernel_tests/sparse_conditional_accumulator_test.py b/tensorflow/python/kernel_tests/sparse_conditional_accumulator_test.py index a824d5c826..275c86e534 100644 --- a/tensorflow/python/kernel_tests/sparse_conditional_accumulator_test.py +++ b/tensorflow/python/kernel_tests/sparse_conditional_accumulator_test.py @@ -26,6 +26,7 @@ from tensorflow.python.framework import dtypes as dtypes_lib from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.platform import test @@ -98,12 +99,14 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): attr { key: 'reduction_type' value {s: 'MEAN'} } """, q.accumulator_ref.op.node_def) + @test_util.run_deprecated_v1 def testAccumulatorSizeEmpty(self): with self.cached_session(): q = data_flow_ops.SparseConditionalAccumulator( dtypes_lib.float32, name="Q") self.assertEqual(q.num_accumulated().eval(), 0) + @test_util.run_deprecated_v1 def testAccumulatorSetGlobalStep(self): with self.cached_session(): q = data_flow_ops.SparseConditionalAccumulator( @@ -111,6 +114,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): set_global_step_op = q.set_global_step(1) set_global_step_op.run() + @test_util.run_deprecated_v1 def testAccumulatorApplyGradFloat32(self): with self.cached_session(): q = data_flow_ops.SparseConditionalAccumulator( @@ -122,6 +126,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): accum_op.run() self.assertEqual(q.num_accumulated().eval(), 1) + @test_util.run_deprecated_v1 def testDtypes(self): with self.cached_session() as sess: dtypes = [dtypes_lib.float16, dtypes_lib.float32, dtypes_lib.float64] @@ -140,10 +145,11 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): t = _indexedslice(mat_to_add) q.apply_indexed_slices_grad(t).run() - result = sess.run(q.take_indexed_slices_grad(1)) + result = self.evaluate(q.take_indexed_slices_grad(1)) self._assertEqual_nparray(sum_elems / len(elems), result, sess) + @test_util.run_deprecated_v1 def testAccumulatorMultipleAccumulators(self): with self.cached_session() as sess: q_f32_0 = data_flow_ops.SparseConditionalAccumulator( @@ -174,6 +180,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): result = sess.run(accums[i].take_indexed_slices_grad(1)) self._assertEqual_indexedslices(expected_tensors[i], result) + @test_util.run_deprecated_v1 def testAccumulatorTakeGradMean(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -189,11 +196,12 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): accum_op.run() takeg_t = q.take_indexed_slices_grad(1) - val = sess.run(takeg_t) + val = self.evaluate(takeg_t) self.assertAllEqual([0, 1, 2], val.indices) self.assertAllEqual([[0.5, 0.5], [0, 2], [3, 0]], val.values) self.assertAllEqual([-1, 2], val.dense_shape) + @test_util.run_deprecated_v1 def testAccumulatorTakeGradSum(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -209,16 +217,18 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): accum_op.run() takeg_t = q.take_indexed_slices_grad(1) - val = sess.run(takeg_t) + val = self.evaluate(takeg_t) self.assertAllEqual([0, 1, 2], val.indices) self.assertAllEqual([[1, 1], [0, 2], [3, 0]], val.values) self.assertAllEqual([-1, 2], val.dense_shape) + @test_util.run_deprecated_v1 def testAccumulatorTakeGradInvalidReductionType(self): with self.assertRaises(ValueError): data_flow_ops.SparseConditionalAccumulator( dtypes_lib.float32, name="Q", shape=(), reduction_type="Invalid") + @test_util.run_deprecated_v1 def testAccumulatorRepeatedTakeGrad(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -235,7 +245,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): accum_op.run() takeg_t = q.take_indexed_slices_grad(1) - val = sess.run(takeg_t) + val = self.evaluate(takeg_t) self.assertAllEqual(val.indices, [0, 1, 2]) self.assertAllEqual(val.values, [[0.5, 0.5], [0, 2], [3, 0]]) self.assertAllEqual(val.dense_shape, [-1, 2]) @@ -252,11 +262,12 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): accum_op.run() takeg_t = q.take_indexed_slices_grad(1) - val = sess.run(takeg_t) + val = self.evaluate(takeg_t) self.assertAllEqual(val.indices, [0, 1, 2]) self.assertAllEqual(val.values, [[5, 5], [0, 20], [30, 0]]) self.assertAllEqual(val.dense_shape, [-1, 2]) + @test_util.run_deprecated_v1 def testParallelApplyGradMean(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -269,7 +280,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): takeg_t = q.take_indexed_slices_grad(1) def apply_indexed_slices_grad(accum_op): - sess.run(accum_op) + self.evaluate(accum_op) threads = [ self.checkedThread( @@ -281,13 +292,14 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): for thread in threads: thread.join() - val = sess.run(takeg_t) + val = self.evaluate(takeg_t) expected_val = sum(elems) / len(elems) self._assertEqual_nparray( np.array([[expected_val, 0], [0, expected_val]]).astype(np.float32), val, sess) + @test_util.run_deprecated_v1 def testParallelApplyGradSum(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -303,7 +315,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): takeg_t = q.take_indexed_slices_grad(1) def apply_indexed_slices_grad(accum_op): - sess.run(accum_op) + self.evaluate(accum_op) threads = [ self.checkedThread(target=apply_indexed_slices_grad, args=(o,)) @@ -315,13 +327,14 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): for thread in threads: thread.join() - val = sess.run(takeg_t) + val = self.evaluate(takeg_t) expected_val = 550.0 self._assertEqual_nparray( np.array([[expected_val, 0], [0, expected_val]]).astype(np.float32), val, sess) + @test_util.run_deprecated_v1 def testParallelTakeGrad(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -338,13 +351,13 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): def apply_indexed_slices_grad(): for accum_op in accum_ops: time.sleep(1.0) - sess.run(accum_op) + self.evaluate(accum_op) apply_indexed_slices_grad_thread = self.checkedThread( target=apply_indexed_slices_grad) def take_grad(): - t = sess.run(takeg_t) + t = self.evaluate(takeg_t) results.append(t) threads = [self.checkedThread(target=take_grad) for _ in range(10)] @@ -361,6 +374,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): self._assertEqual_nparray( np.array([[0, 0], [elems[i], 0]]), results[i], sess) + @test_util.run_deprecated_v1 def testAccumulatorApplyAndBlockingTake(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -378,10 +392,10 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): def apply_indexed_slices_grad(): for accum_op in accum_ops: - sess.run(accum_op) + self.evaluate(accum_op) def take_grad(): - results.append(sess.run(takeg_t)) + results.append(self.evaluate(takeg_t)) accum_thread = self.checkedThread(target=apply_indexed_slices_grad) takeg_thread = self.checkedThread(target=take_grad) @@ -394,8 +408,9 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): def _blocking_takeg(self, sess, takeg_op): with self.assertRaisesOpError("was cancelled"): - sess.run(takeg_op) + self.evaluate(takeg_op) + @test_util.run_deprecated_v1 def testAccumulatorCancel(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -415,6 +430,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): takeg_thread.join() + @test_util.run_deprecated_v1 def testNonVectorIndices(self): with self.cached_session(): q = data_flow_ops.SparseConditionalAccumulator( @@ -427,6 +443,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): grad_indices=[[0, 1], [1, 0]], grad_values=np.array([1, 2]).astype(np.float32)).run() + @test_util.run_deprecated_v1 def testZeroDimensionValues(self): with self.cached_session(): q = data_flow_ops.SparseConditionalAccumulator( @@ -437,6 +454,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): q.apply_grad( grad_indices=[0], grad_values=np.array(1).astype(np.float32)).run() + @test_util.run_deprecated_v1 def testWrongNonEmptyInputValues(self): with self.cached_session(): q = data_flow_ops.SparseConditionalAccumulator( @@ -448,6 +466,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): grad_indices=[0, 1], grad_values=np.array([[0, 1, 1]]).astype(np.float32)).run() + @test_util.run_deprecated_v1 def testDynamicNonVectorIndices(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -467,6 +486,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): x_values: np.array([1, 2]).astype(np.float32) }) + @test_util.run_deprecated_v1 def testDynamicWrongNonEmptyInputValues(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -485,6 +505,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): x_values: np.array([[0, 1, 1]]).astype(np.float32) }) + @test_util.run_deprecated_v1 def testEmptyShapeApply(self): with self.cached_session(): q = data_flow_ops.SparseConditionalAccumulator( @@ -510,6 +531,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): q.apply_grad(grad_indices=[0], grad_values=[1.0], grad_shape=[]).run() q.apply_grad(grad_indices=[0], grad_values=[1.0]).run() + @test_util.run_deprecated_v1 def testValidateShape(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -585,7 +607,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): np.float32)).run() # After take grad, constraints on accumulated gradient are removed - sess.run(q.take_grad(1)) + self.evaluate(q.take_grad(1)) # First successful gradient imposes new constraints. # Hereafter, shape will additionally constrained to [None,2,2,3] @@ -605,6 +627,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): [[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]]).astype(np.float32), local_step=1).run() + @test_util.run_deprecated_v1 def testReturnShape(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -615,7 +638,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): grad_values=np.array( [[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]]).astype(np.float32)).run() - val = sess.run(q.take_indexed_slices_grad(1)) + val = self.evaluate(q.take_indexed_slices_grad(1)) self.assertAllEqual(val.dense_shape, [2, 2, 2, 2]) q = data_flow_ops.SparseConditionalAccumulator( @@ -627,9 +650,10 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): [[[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]]).astype( np.float32)).run() - val = sess.run(q.take_indexed_slices_grad(1)) + val = self.evaluate(q.take_indexed_slices_grad(1)) self.assertAllEqual(val.dense_shape, [-1, 2, 2, 3]) + @test_util.run_deprecated_v1 def testApplyGradtInt32IndicesAndShape(self): with self.cached_session() as sess: q = data_flow_ops.SparseConditionalAccumulator( @@ -653,7 +677,7 @@ class IndexedSlicesConditionalAccumulatorTest(test.TestCase): accum_op.run() self.assertEqual(q.num_accumulated().eval(), 2) - val = sess.run(q.take_indexed_slices_grad(1)) + val = self.evaluate(q.take_indexed_slices_grad(1)) self.assertAllEqual(val.indices, [0, 2]) self.assertAllEqual(val.values, [[0, 0, 1], [3, 0, 4]]) self.assertAllEqual(val.dense_shape, [3, 3]) diff --git a/tensorflow/python/kernel_tests/sparse_cross_op_test.py b/tensorflow/python/kernel_tests/sparse_cross_op_test.py index 6e0714da70..566bbb56f0 100644 --- a/tensorflow/python/kernel_tests/sparse_cross_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_cross_op_test.py @@ -24,12 +24,14 @@ from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import sparse_ops from tensorflow.python.platform import test class SparseCrossOpTest(test.TestCase): + @test_util.run_deprecated_v1 def test_simple(self): """Tests a simple scenario.""" op = sparse_ops.sparse_cross([ @@ -43,8 +45,9 @@ class SparseCrossOpTest(test.TestCase): 'batch2-FC1-F2_X_batch2-FC2-F1', 'batch2-FC1-F2_X_batch2-FC2-F2' ]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_dense(self): """Tests only dense inputs.""" op = sparse_ops.sparse_cross([ @@ -63,8 +66,9 @@ class SparseCrossOpTest(test.TestCase): 'batch2-FC1-F2_X_batch2-FC2-F1', 'batch2-FC1-F2_X_batch2-FC2-F2' ]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_integer_mixed_string_sparse(self): """Tests mixed type.""" op = sparse_ops.sparse_cross([ @@ -77,8 +81,9 @@ class SparseCrossOpTest(test.TestCase): '55555_X_batch2-FC2-F2' ]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_integer_mixed_string_dense(self): """Tests mixed dense inputs.""" op = sparse_ops.sparse_cross([ @@ -95,8 +100,9 @@ class SparseCrossOpTest(test.TestCase): '999999_X_batch2-FC2-F1', '999999_X_batch2-FC2-F2' ]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_sparse_cross_dense(self): """Tests sparse and dense inputs.""" op = sparse_ops.sparse_cross([ @@ -112,8 +118,9 @@ class SparseCrossOpTest(test.TestCase): 'batch2-FC1-F2_X_batch2-FC2-F1', 'batch2-FC1-F2_X_batch2-FC2-F2' ]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_integer_sparse_input(self): """Tests mixed type sparse and dense inputs.""" op = sparse_ops.sparse_cross([ @@ -128,8 +135,9 @@ class SparseCrossOpTest(test.TestCase): '5555_X_batch2-FC2-F1', '5555_X_batch2-FC2-F2' ]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_permutation_3x3x3(self): """Tests 3x3x3 permutation.""" op = sparse_ops.sparse_cross([ @@ -170,8 +178,9 @@ class SparseCrossOpTest(test.TestCase): 'batch1-FC1-F3_X_batch1-FC2-F3_X_batch1-FC3-F3' ]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_permutation_3x1x2(self): """Tests 3x1x2 permutation.""" op = sparse_ops.sparse_cross([ @@ -189,8 +198,9 @@ class SparseCrossOpTest(test.TestCase): 'batch1-FC1-F3_X_batch1-FC2-F1_X_batch1-FC3-F2' ]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_large_batch(self): """Tests with large batch size to force multithreading.""" batch_size = 5000 @@ -222,8 +232,9 @@ class SparseCrossOpTest(test.TestCase): expected_out = self._sparse_tensor(col_out) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_one_column_empty(self): """Tests when one column is empty. @@ -235,8 +246,9 @@ class SparseCrossOpTest(test.TestCase): self._sparse_tensor([['batch1-FC3-F1', 'batch1-FC3-F2']]) ]) with self.cached_session() as sess: - self._assert_sparse_tensor_empty(sess.run(op)) + self._assert_sparse_tensor_empty(self.evaluate(op)) + @test_util.run_deprecated_v1 def test_some_columns_empty(self): """Tests when more than one columns are empty. @@ -254,8 +266,9 @@ class SparseCrossOpTest(test.TestCase): 'batch1-FC1-F2_X_batch1-FC2-F1_X_batch1-FC3-F2' ]], 2) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_all_columns_empty(self): """Tests when all columns are empty. @@ -267,8 +280,9 @@ class SparseCrossOpTest(test.TestCase): self._sparse_tensor([]) ]) with self.cached_session() as sess: - self._assert_sparse_tensor_empty(sess.run(op)) + self._assert_sparse_tensor_empty(self.evaluate(op)) + @test_util.run_deprecated_v1 def test_hashed_zero_bucket_no_hash_key(self): op = sparse_ops.sparse_cross_hashed([ self._sparse_tensor([['batch1-FC1-F1']]), @@ -278,8 +292,9 @@ class SparseCrossOpTest(test.TestCase): # Check actual hashed output to prevent unintentional hashing changes. expected_out = self._sparse_tensor([[1971693436396284976]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_hashed_zero_bucket(self): op = sparse_ops.sparse_cross_hashed( [ @@ -291,9 +306,10 @@ class SparseCrossOpTest(test.TestCase): # Check actual hashed output to prevent unintentional hashing changes. expected_out = self._sparse_tensor([[4847552627144134031]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) # TODO(sibyl-Aix6ihai): Add benchmark to compare Hashed vs Non-hashed. + @test_util.run_deprecated_v1 def test_hashed_no_hash_key(self): op = sparse_ops.sparse_cross_hashed( [ @@ -305,8 +321,9 @@ class SparseCrossOpTest(test.TestCase): # Check actual hashed output to prevent unintentional hashing changes. expected_out = self._sparse_tensor([[83]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_hashed_output(self): op = sparse_ops.sparse_cross_hashed( [ @@ -319,8 +336,9 @@ class SparseCrossOpTest(test.TestCase): # Check actual hashed output to prevent unintentional hashing changes. expected_out = self._sparse_tensor([[31]]) with self.cached_session() as sess: - self._assert_sparse_tensor_equals(expected_out, sess.run(op)) + self._assert_sparse_tensor_equals(expected_out, self.evaluate(op)) + @test_util.run_deprecated_v1 def test_hashed__has_no_collision(self): """Tests that fingerprint concatenation has no collisions.""" # Although the last 10 bits of 359 and 1024+359 are identical. @@ -331,7 +349,7 @@ class SparseCrossOpTest(test.TestCase): [t2, t1], num_buckets=1024, hash_key=sparse_ops._DEFAULT_HASH_KEY + 1) cross_dense = sparse_ops.sparse_tensor_to_dense(cross) with session.Session(): - values = cross_dense.eval() + values = self.evaluate(cross_dense) self.assertTrue(numpy.not_equal(values[0], values[1]).all()) def test_hashed_3x1x2(self): @@ -345,7 +363,7 @@ class SparseCrossOpTest(test.TestCase): ], num_buckets=1000) with self.cached_session() as sess: - out = sess.run(op) + out = self.evaluate(op) self.assertEqual(6, len(out.values)) self.assertAllEqual([[0, i] for i in range(6)], out.indices) self.assertTrue(all(x < 1000 and x >= 0 for x in out.values)) diff --git a/tensorflow/python/kernel_tests/sparse_matmul_op_test.py b/tensorflow/python/kernel_tests/sparse_matmul_op_test.py index 541463e76b..2e17a9c608 100644 --- a/tensorflow/python/kernel_tests/sparse_matmul_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_matmul_op_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -58,7 +59,7 @@ class SparseMatMulTest(test.TestCase): transpose_b=tr_b, a_is_sparse=sp_a, b_is_sparse=sp_b) - out = tf_ans.eval() + out = self.evaluate(tf_ans) np_x = math_ops.cast(tf_x, dtypes.float32).eval() np_y = math_ops.cast(tf_y, dtypes.float32).eval() @@ -71,6 +72,7 @@ class SparseMatMulTest(test.TestCase): self.assertShapeEqual(np_ans, tf_ans) self.assertAllCloseAccordingToType(np_ans, out, rtol=1e-4, atol=1e-4) + @test_util.run_deprecated_v1 def testBasic(self): x = np.arange(0., 4.).reshape([4, 1]).astype(np.float32) y = np.arange(-1., 1.).reshape([1, 2]).astype(np.float32) @@ -78,6 +80,7 @@ class SparseMatMulTest(test.TestCase): for y_dtype in (dtypes.float32, dtypes.bfloat16): self._testCpuMatmul(x, y, x_dtype=x_dtype, y_dtype=y_dtype) + @test_util.run_deprecated_v1 def testZeroDim(self): x = np.ones((4, 0)).astype(np.float32) y = np.ones((0, 3)).astype(np.float32) @@ -85,6 +88,7 @@ class SparseMatMulTest(test.TestCase): for y_dtype in (dtypes.float32, dtypes.bfloat16): self._testCpuMatmul(x, y, x_dtype=x_dtype, y_dtype=y_dtype) + @test_util.run_deprecated_v1 def testEmpty(self): x = np.ones((0, 0)).astype(np.float32) y = np.ones((0, 0)).astype(np.float32) @@ -93,6 +97,7 @@ class SparseMatMulTest(test.TestCase): self._testCpuMatmul(x, y, x_dtype=x_dtype, y_dtype=y_dtype) # Tests setting one dimension to be a high value. + @test_util.run_deprecated_v1 def testLarge(self): r1 = np.random.randint(6000, 20000) r2 = np.random.randint(1, 10) @@ -105,6 +110,7 @@ class SparseMatMulTest(test.TestCase): self._testCpuMatmul(x, y, x_dtype=x_dtype, y_dtype=y_dtype) # Tests random sized matrices. + @test_util.run_deprecated_v1 def testRandom(self): for tr_a in [True, False]: for tr_b in [True, False]: @@ -159,6 +165,7 @@ class MatMulGradientTest(test.TestCase): delta=delta)) self.assertLessEqual(err, delta / 2.) + @test_util.run_deprecated_v1 def testGradientInput(self): for tr_a in [True, False]: for tr_b in [True, False]: diff --git a/tensorflow/python/kernel_tests/sparse_ops_test.py b/tensorflow/python/kernel_tests/sparse_ops_test.py index a45ce2e13b..75f65e6251 100644 --- a/tensorflow/python/kernel_tests/sparse_ops_test.py +++ b/tensorflow/python/kernel_tests/sparse_ops_test.py @@ -71,6 +71,7 @@ class SparseToIndicatorTest(test_util.TensorFlowTestCase): constant_op.constant(val, dtype), constant_op.constant(shape, dtypes.int64)) + @test_util.run_deprecated_v1 def testInt32(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_5x6(dtypes.int32) @@ -83,6 +84,7 @@ class SparseToIndicatorTest(test_util.TensorFlowTestCase): self.assertAllEqual(output, expected_output) + @test_util.run_deprecated_v1 def testInt64(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_5x6(dtypes.int64) @@ -95,6 +97,7 @@ class SparseToIndicatorTest(test_util.TensorFlowTestCase): self.assertAllEqual(output, expected_output) + @test_util.run_deprecated_v1 def testHigherRank(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_2x3x4(dtypes.int64) @@ -154,7 +157,7 @@ class SparseMergeTest(test_util.TensorFlowTestCase): sparse_tensor.SparseTensor.from_value(values_v)): sp_output = sparse_ops.sparse_merge(indices, values, vocab_size) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self._AssertResultsSorted(output, vocab_size) def testInt64AndFloat32(self): @@ -163,7 +166,7 @@ class SparseMergeTest(test_util.TensorFlowTestCase): indices, values = self._SparseTensor_3x50(np.int64, np.float32) sp_output = sparse_ops.sparse_merge(indices, values, vocab_size) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self._AssertResultsSorted(output, vocab_size) def testInt64AndFloat64(self): @@ -172,7 +175,7 @@ class SparseMergeTest(test_util.TensorFlowTestCase): indices, values = self._SparseTensor_3x50(np.int64, np.float64) sp_output = sparse_ops.sparse_merge(indices, values, vocab_size) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self._AssertResultsSorted(output, vocab_size) def testInt32AndFloat32NonCanonicalOrder(self): @@ -182,7 +185,7 @@ class SparseMergeTest(test_util.TensorFlowTestCase): sp_output = sparse_ops.sparse_merge( indices, values, vocab_size, already_sorted=True) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self._AssertResultsNotSorted(output, vocab_size) def testInt64AndFloat32NonCanonicalOrder(self): @@ -192,7 +195,7 @@ class SparseMergeTest(test_util.TensorFlowTestCase): sp_output = sparse_ops.sparse_merge( indices, values, vocab_size, already_sorted=True) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self._AssertResultsNotSorted(output, vocab_size) def testInt64AndFloat64NonCanonicalOrder(self): @@ -203,7 +206,7 @@ class SparseMergeTest(test_util.TensorFlowTestCase): sp_output = sparse_ops.sparse_merge( indices, values, vocab_size_tensor, already_sorted=True) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self._AssertResultsNotSorted(output, vocab_size) def testShouldSetLastDimensionInDynamicShape(self): @@ -261,7 +264,7 @@ class SparseMergeHighDimTest(test_util.TensorFlowTestCase): indices, values = self._SparseTensor_3x50(np.int64, np.float32) sp_output = sparse_ops.sparse_merge(indices, values, vocab_size) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self._AssertResultsSorted(output, vocab_size) def testInt64AndFloat64(self): @@ -270,7 +273,7 @@ class SparseMergeHighDimTest(test_util.TensorFlowTestCase): indices, values = self._SparseTensor_3x50(np.int64, np.float64) sp_output = sparse_ops.sparse_merge(indices, values, vocab_size) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self._AssertResultsSorted(output, vocab_size) def testInt64AndFloat64Shape(self): @@ -279,7 +282,7 @@ class SparseMergeHighDimTest(test_util.TensorFlowTestCase): indices, values = self._SparseTensor_3x50(np.int64, np.float64) sp_output = sparse_ops.sparse_merge(indices, values, vocab_size) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self._AssertResultsSorted(output, vocab_size) @@ -296,13 +299,14 @@ class SparseRetainTest(test_util.TensorFlowTestCase): def _SparseTensor_5x6(self): return sparse_tensor.SparseTensor.from_value(self._SparseTensorValue_5x6()) + @test_util.run_deprecated_v1 def testBasic(self): with self.session(use_gpu=False) as sess: for sp_input in (self._SparseTensorValue_5x6(), self._SparseTensor_5x6()): to_retain = np.array([1, 0, 0, 1, 1, 0], dtype=np.bool) sp_output = sparse_ops.sparse_retain(sp_input, to_retain) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self.assertAllEqual(output.indices, [[0, 0], [1, 4], [3, 2]]) self.assertAllEqual(output.values, [0, 14, 32]) @@ -314,7 +318,7 @@ class SparseRetainTest(test_util.TensorFlowTestCase): to_retain = np.zeros((6,), dtype=np.bool) sp_output = sparse_ops.sparse_retain(sp_input, to_retain) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self.assertAllEqual(output.indices, np.array([]).reshape((0, 2))) self.assertAllEqual(output.values, []) @@ -353,38 +357,42 @@ class SparseResetShapeTest(test_util.TensorFlowTestCase): return sparse_tensor.SparseTensorValue(self._IND_2_5_6, self._VAL_2_5_6, self._SHP_2_5_6) + @test_util.run_deprecated_v1 def testStaticShapeInfoPreservedWhenNewShapeIsProvidedAndStatic(self): sp_input = self._SparseTensor_2x5x6() new_shape = np.array([3, 6, 7], dtype=np.int64) sp_output = sparse_ops.sparse_reset_shape(sp_input, new_shape) self.assertAllEqual([3, 6, 7], sp_output.get_shape()) + @test_util.run_deprecated_v1 def testBasic(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensor_2x5x6() new_shape = np.array([3, 6, 7], dtype=np.int64) sp_output = sparse_ops.sparse_reset_shape(sp_input, new_shape) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self.assertAllEqual(output.indices, [[0, 0, 0], [0, 1, 0], [0, 1, 3], [1, 1, 4], [1, 3, 2], [1, 3, 3]]) self.assertAllEqual(output.values, [0, 10, 13, 14, 32, 33]) self.assertAllEqual(output.dense_shape, [3, 6, 7]) + @test_util.run_deprecated_v1 def testInputUnavailableInGraphConstructionOk(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorValue_2x5x6() new_shape = np.array([3, 6, 7], dtype=np.int64) sp_output = sparse_ops.sparse_reset_shape(sp_input, new_shape) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self.assertAllEqual(output.indices, [[0, 0, 0], [0, 1, 0], [0, 1, 3], [1, 1, 4], [1, 3, 2], [1, 3, 3]]) self.assertAllEqual(output.values, [0, 10, 13, 14, 32, 33]) self.assertAllEqual(output.dense_shape, [3, 6, 7]) + @test_util.run_deprecated_v1 def testFeedInputUnavailableInGraphConstructionOk(self): with self.session(use_gpu=False) as sess: sp_input = array_ops.sparse_placeholder(dtype=dtypes.int32) @@ -404,7 +412,7 @@ class SparseResetShapeTest(test_util.TensorFlowTestCase): sp_input = self._SparseTensor_2x5x6() sp_output = sparse_ops.sparse_reset_shape(sp_input) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self.assertAllEqual(output.indices, [[0, 0, 0], [0, 1, 0], [0, 1, 3], [1, 1, 4], [1, 3, 2], [1, 3, 3]]) @@ -416,12 +424,13 @@ class SparseResetShapeTest(test_util.TensorFlowTestCase): sp_input = self._SparseTensor_2x5x6_Empty() sp_output = sparse_ops.sparse_reset_shape(sp_input) - output = sess.run(sp_output) + output = self.evaluate(sp_output) self.assertAllEqual(output.indices.shape, [0, 3]) self.assertAllEqual(output.values.shape, [0]) self.assertAllEqual(output.dense_shape, [0, 0, 0]) + @test_util.run_deprecated_v1 def testInvalidRank(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_2x5x6() @@ -430,6 +439,7 @@ class SparseResetShapeTest(test_util.TensorFlowTestCase): with self.assertRaises(ValueError): sparse_ops.sparse_reset_shape(sp_input, new_shape) + @test_util.run_deprecated_v1 def testInvalidRankNewShapeUnavailableInGraphConstruction(self): with self.session(use_gpu=False) as sess: new_shape = array_ops.placeholder(dtype=dtypes.int64) @@ -439,6 +449,7 @@ class SparseResetShapeTest(test_util.TensorFlowTestCase): with self.assertRaisesOpError("x == y did not hold element-wise"): sess.run(out, feed_dict={new_shape: np.array([3, 7], dtype=np.int64)}) + @test_util.run_deprecated_v1 def testInvalidDimensionSizeStatic(self): sp_input = self._SparseTensor_2x5x6() new_shape = np.array([3, 7, 5], dtype=np.int64) @@ -446,6 +457,7 @@ class SparseResetShapeTest(test_util.TensorFlowTestCase): with self.assertRaisesRegexp(ValueError, "should have dimension sizes"): sparse_ops.sparse_reset_shape(sp_input, new_shape) + @test_util.run_deprecated_v1 def testInvalidDimensionSizeDynamic(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensor_2x5x6() @@ -455,6 +467,7 @@ class SparseResetShapeTest(test_util.TensorFlowTestCase): with self.assertRaisesOpError("x <= y did not hold element-wise"): sess.run(out, feed_dict={new_shape: [3, 7, 5]}) + @test_util.run_deprecated_v1 def testInvalidDimensionSizeInputUnavailableInGraphConstruction(self): sp_input = array_ops.sparse_placeholder(dtype=dtypes.int32) with self.session(use_gpu=False) as sess: @@ -496,6 +509,7 @@ class SparseFillEmptyRowsTest(test_util.TensorFlowTestCase): constant_op.constant(val, dtypes.int32), constant_op.constant(shape, dtypes.int64)) + @test_util.run_deprecated_v1 def testFillNumber(self): with self.session(use_gpu=False) as sess: for sp_input in (self._SparseTensorValue_5x6(), self._SparseTensor_5x6()): @@ -513,6 +527,7 @@ class SparseFillEmptyRowsTest(test_util.TensorFlowTestCase): self.assertAllEqual(empty_row_indicator_out, np.array([0, 0, 1, 0, 1]).astype(np.bool)) + @test_util.run_deprecated_v1 def testFillFloat(self): with self.session(use_gpu=False) as sess: values = constant_op.constant( @@ -547,6 +562,7 @@ class SparseFillEmptyRowsTest(test_util.TensorFlowTestCase): self.assertGreater(default_value_grad_err, 0) self.assertLess(default_value_grad_err, 1e-8) + @test_util.run_deprecated_v1 def testFillString(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensor_String5x6() @@ -565,6 +581,7 @@ class SparseFillEmptyRowsTest(test_util.TensorFlowTestCase): self.assertAllEqual(empty_row_indicator_out, np.array([0, 0, 1, 0, 1]).astype(np.bool)) + @test_util.run_deprecated_v1 def testNoEmptyRows(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensor_2x6() @@ -582,6 +599,7 @@ class SparseFillEmptyRowsTest(test_util.TensorFlowTestCase): class SparseAddTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testValuesInVariable(self): indices = constant_op.constant([[1]], dtype=dtypes.int64) values = variables.Variable([1], trainable=False, dtype=dtypes.float32) @@ -591,8 +609,8 @@ class SparseAddTest(test_util.TensorFlowTestCase): sp_output = sparse_ops.sparse_add(sp_input, sp_input) with self.session(use_gpu=False) as sess: - sess.run(variables.global_variables_initializer()) - output = sess.run(sp_output) + self.evaluate(variables.global_variables_initializer()) + output = self.evaluate(sp_output) self.assertAllEqual(output.values, [2]) @@ -635,7 +653,7 @@ class SparseReduceTest(test_util.TensorFlowTestCase): else: tf_dense_ans = sparse_ops.sparse_reduce_max(sp_t, reduction_axes, keep_dims) - out_dense = tf_dense_ans.eval() + out_dense = self.evaluate(tf_dense_ans) if do_sum: tf_sparse_ans = sparse_ops.sparse_reduce_sum_sparse(sp_t, @@ -657,6 +675,7 @@ class SparseReduceTest(test_util.TensorFlowTestCase): self._compare(sp_t, reduction_axes, ndims, True, False) self._compare(sp_t, reduction_axes, ndims, True, True) + @test_util.run_deprecated_v1 def testSimpleAndRandomInputs(self): if np.__version__ == "1.13.0": self.skipTest("numpy 1.13.0 bug") @@ -696,6 +715,7 @@ class SparseReduceTest(test_util.TensorFlowTestCase): with self.assertRaisesOpError("Invalid reduction dimension 2"): sparse_ops.sparse_reduce_max(sp_t, 2).eval() + @test_util.run_deprecated_v1 def testGradient(self): if np.__version__ == "1.13.0": self.skipTest("numpy 1.13.0 bug") @@ -710,18 +730,59 @@ class SparseReduceTest(test_util.TensorFlowTestCase): axes = np.random.choice(len(dims), size=d, replace=False).tolist() reduced = sparse_ops.sparse_reduce_sum(sp_t, axes) - err = gradient_checker.compute_gradient_error(sp_t.values, (nnz,), - reduced, - reduced.eval().shape) + err = gradient_checker.compute_gradient_error( + sp_t.values, (nnz,), reduced, + self.evaluate(reduced).shape) self.assertLess(err, 1e-3) # Tests for negative axes. reduced = sparse_ops.sparse_reduce_sum(sp_t, -1) - err = gradient_checker.compute_gradient_error(sp_t.values, (nnz,), - reduced, - reduced.eval().shape) + err = gradient_checker.compute_gradient_error( + sp_t.values, (nnz,), reduced, + self.evaluate(reduced).shape) self.assertLess(err, 1e-3) + def _testSparseReduceShape(self, sp_t, reduction_axes, ndims, keep_dims, + do_sum): + densified = sparse_ops.sparse_tensor_to_dense(sp_t).eval() + + np_op = np.sum + tf_op = sparse_ops.sparse_reduce_sum + if not do_sum: + np_op = np.max + tf_op = sparse_ops.sparse_reduce_max + + np_ans = densified + if reduction_axes is None: + np_ans = np_op(np_ans, keepdims=keep_dims) + else: + if not isinstance(reduction_axes, list): # Single scalar. + reduction_axes = [reduction_axes] + reduction_axes = np.array(reduction_axes).astype(np.int32) + # Handles negative axes. + reduction_axes = (reduction_axes + ndims) % ndims + # Loop below depends on sorted. + reduction_axes.sort() + for ra in reduction_axes.ravel()[::-1]: + np_ans = np_op(np_ans, axis=ra, keepdims=keep_dims) + + tf_ans = tf_op(sp_t, reduction_axes, keep_dims) + self.assertAllEqual(np_ans.shape, tf_ans.get_shape().as_list()) + + def testSparseReduceSumOrMaxShape(self): + sp_t = sparse_tensor.SparseTensor(self.ind, self.vals, self.dense_shape) + + with self.session(use_gpu=False): + for do_sum in [True, False]: + for keep_dims in [True, False]: + self._testSparseReduceShape(sp_t, None, 2, keep_dims, do_sum) + self._testSparseReduceShape(sp_t, 0, 2, keep_dims, do_sum) + self._testSparseReduceShape(sp_t, [1], 2, keep_dims, do_sum) + self._testSparseReduceShape(sp_t, [0, 1], 2, keep_dims, do_sum) + self._testSparseReduceShape(sp_t, [1, 0], 2, keep_dims, do_sum) + self._testSparseReduceShape(sp_t, [-1], 2, keep_dims, do_sum) + self._testSparseReduceShape(sp_t, [1, -2], 2, keep_dims, do_sum) + class SparseMathOpsTest(test_util.TensorFlowTestCase): @@ -737,6 +798,7 @@ class SparseMathOpsTest(test_util.TensorFlowTestCase): result_tensor.values).eval() self.assertAllEqual(result_np, res_densified) + @test_util.run_deprecated_v1 def testCwiseDivAndMul(self): np.random.seed(1618) sp_shapes = [(10, 10, 10), (5, 5), (1618,), (3, 3, 7)] @@ -760,6 +822,7 @@ class SparseMathOpsTest(test_util.TensorFlowTestCase): res = sp_t / dense_t # should invoke "__truediv__" self.assertEqual(res.values.eval().dtype, np.float64) + @test_util.run_deprecated_v1 def testCwiseAdd(self): with self.session(use_gpu=False): # Identity(2) + AllOnes(2,2). Should be equal to 2 * Identity(2). @@ -779,6 +842,7 @@ class SparseMathOpsTest(test_util.TensorFlowTestCase): sparse_ops.sparse_dense_cwise_add(sp_t, dense_t), np.identity(2) * 2, sp_t) + @test_util.run_deprecated_v1 def testGradients(self): np.random.seed(1618) sp_shapes = [(10, 10, 10), (5, 5), (1618,), (3, 3, 7)] @@ -812,6 +876,7 @@ class SparseMathOpsTest(test_util.TensorFlowTestCase): class SparseSoftmaxTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testEquivalentToDensified(self): np.random.seed(1618) n, m = np.random.choice(20, size=2) @@ -831,6 +896,7 @@ class SparseSoftmaxTest(test_util.TensorFlowTestCase): self.assertAllClose(dense_result.eval(), sp_result) + @test_util.run_deprecated_v1 def testHigherRanks(self): # For the first shape: # First batch: @@ -860,6 +926,7 @@ class SparseSoftmaxTest(test_util.TensorFlowTestCase): self.assertAllEqual(sp_t.indices.eval(), result.indices) self.assertAllEqual(shape, result.dense_shape) + @test_util.run_deprecated_v1 def testGradient(self): x_shape = [2, 5, 10] with self.cached_session(use_gpu=False): @@ -879,6 +946,7 @@ class SparseMinimumMaximumTest(test_util.TensorFlowTestCase): self.assertAllEqual(a.values, b.values) self.assertAllEqual(a.dense_shape, b.dense_shape) + @test_util.run_deprecated_v1 def testBasic(self): with self.cached_session(use_gpu=False): # 1-D, values at index 0. @@ -898,6 +966,7 @@ class SparseMinimumMaximumTest(test_util.TensorFlowTestCase): self._assertSparseTensorValueEqual(expected.eval(), max_tf) self._assertSparseTensorValueEqual(expected.eval(), min_tf) + @test_util.run_deprecated_v1 def testRandom(self): np.random.seed(1618) shapes = [(13,), (6, 8), (1, 7, 1)] @@ -939,6 +1008,7 @@ class SparseMinimumMaximumTest(test_util.TensorFlowTestCase): class SparseTransposeTest(test.TestCase): + @test_util.run_deprecated_v1 def testTranspose(self): if np.__version__ == "1.13.0": self.skipTest("numpy 1.13.0 bug") @@ -961,16 +1031,19 @@ class SparseTransposeTest(test.TestCase): class SparsePlaceholderTest(test.TestCase): + @test_util.run_deprecated_v1 def testPlaceholder(self): foo = array_ops.sparse_placeholder(dtypes.float32, shape=(10, 47)) self.assertAllEqual([10, 47], foo.get_shape()) self.assertAllEqual([None, 2], foo.indices.get_shape().as_list()) + @test_util.run_deprecated_v1 def testPartialShapePlaceholder(self): foo = array_ops.sparse_placeholder(dtypes.float32, shape=(None, 47)) self.assertAllEqual([None, None], foo.get_shape().as_list()) self.assertAllEqual([None, 2], foo.indices.get_shape().as_list()) + @test_util.run_deprecated_v1 def testNoShapePlaceholder(self): foo = array_ops.sparse_placeholder(dtypes.float32, shape=None) self.assertAllEqual(None, foo.get_shape()) diff --git a/tensorflow/python/kernel_tests/sparse_reorder_op_test.py b/tensorflow/python/kernel_tests/sparse_reorder_op_test.py index 7b83ae5177..93fcc6a18e 100644 --- a/tensorflow/python/kernel_tests/sparse_reorder_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_reorder_op_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import sparse_ops @@ -60,11 +61,12 @@ class SparseReorderTest(test.TestCase): input_val = self._SparseTensorValue_5x6(np.arange(6)) sp_output = sparse_ops.sparse_reorder(input_val) - output_val = sess.run(sp_output) + output_val = self.evaluate(sp_output) self.assertAllEqual(output_val.indices, input_val.indices) self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, input_val.dense_shape) + @test_util.run_deprecated_v1 def testFeedAlreadyInOrder(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -83,12 +85,13 @@ class SparseReorderTest(test.TestCase): input_val = self._SparseTensorValue_5x6(np.random.permutation(6)) sp_output = sparse_ops.sparse_reorder(input_val) - output_val = sess.run(sp_output) + output_val = self.evaluate(sp_output) self.assertAllEqual(output_val.indices, expected_output_val.indices) self.assertAllEqual(output_val.values, expected_output_val.values) self.assertAllEqual(output_val.dense_shape, expected_output_val.dense_shape) + @test_util.run_deprecated_v1 def testFeedOutOfOrder(self): expected_output_val = self._SparseTensorValue_5x6(np.arange(6)) with self.session(use_gpu=False) as sess: @@ -103,6 +106,7 @@ class SparseReorderTest(test.TestCase): self.assertAllEqual(output_val.dense_shape, expected_output_val.dense_shape) + @test_util.run_deprecated_v1 def testGradients(self): with self.session(use_gpu=False): for _ in range(5): # To test various random permutations diff --git a/tensorflow/python/kernel_tests/sparse_reshape_op_test.py b/tensorflow/python/kernel_tests/sparse_reshape_op_test.py index f7be397c33..9341228d57 100644 --- a/tensorflow/python/kernel_tests/sparse_reshape_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_reshape_op_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.platform import test @@ -64,12 +65,14 @@ class SparseReshapeTest(test.TestCase): sp_output = sparse_ops.sparse_reshape(sp_input, shape=(2, -1)) self.assertAllEqual((2, 3 * 4), sp_output.get_shape()) + @test_util.run_deprecated_v1 def testRaisesIfMoreThanOneInferredDim(self): sp_input = sparse_tensor.SparseTensor.from_value( self._SparseTensorValue_2x3x4()) with self.assertRaisesRegexp(ValueError, "At most one dimension can"): sparse_ops.sparse_reshape(sp_input, shape=(-1, 2, -1)) + @test_util.run_deprecated_v1 def testRaisesIfInferredShapeNotPossible(self): sp_input = sparse_tensor.SparseTensor.from_value( self._SparseTensorValue_2x3x4()) @@ -81,11 +84,12 @@ class SparseReshapeTest(test.TestCase): input_val = self._SparseTensorValue_5x6() sp_output = sparse_ops.sparse_reshape(input_val, [5, 6]) - output_val = sess.run(sp_output) + output_val = self.evaluate(sp_output) self.assertAllEqual(output_val.indices, input_val.indices) self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, input_val.dense_shape) + @test_util.run_deprecated_v1 def testFeedSameShape(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -97,6 +101,7 @@ class SparseReshapeTest(test.TestCase): self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, input_val.dense_shape) + @test_util.run_deprecated_v1 def testWorksWellWithTfShape(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -109,6 +114,7 @@ class SparseReshapeTest(test.TestCase): self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, input_val.dense_shape) + @test_util.run_deprecated_v1 def testFeedSameShapeWithInferredDim(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -120,6 +126,7 @@ class SparseReshapeTest(test.TestCase): self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, input_val.dense_shape) + @test_util.run_deprecated_v1 def testFeedNewShapeSameRank(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -133,6 +140,7 @@ class SparseReshapeTest(test.TestCase): self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, [3, 10]) + @test_util.run_deprecated_v1 def testFeedNewShapeSameRankWithInferredDim(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -151,13 +159,14 @@ class SparseReshapeTest(test.TestCase): input_val = self._SparseTensorValue_5x6() sp_output = sparse_ops.sparse_reshape(input_val, [2, 3, 5]) - output_val = sess.run(sp_output) + output_val = self.evaluate(sp_output) self.assertAllEqual(output_val.indices, np.array([[0, 0, 0], [0, 1, 1], [0, 1, 4], [0, 2, 0], [1, 1, 0], [1, 1, 1]])) self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, [2, 3, 5]) + @test_util.run_deprecated_v1 def testFeedUpRank(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -171,6 +180,7 @@ class SparseReshapeTest(test.TestCase): self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, [2, 3, 5]) + @test_util.run_deprecated_v1 def testFeedUpRankWithInferredDim(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -184,6 +194,7 @@ class SparseReshapeTest(test.TestCase): self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, [2, 3, 5]) + @test_util.run_deprecated_v1 def testFeedDownRank(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -197,6 +208,7 @@ class SparseReshapeTest(test.TestCase): self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, [6, 4]) + @test_util.run_deprecated_v1 def testFeedDownRankWithInferredDim(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -210,6 +222,7 @@ class SparseReshapeTest(test.TestCase): self.assertAllEqual(output_val.values, input_val.values) self.assertAllEqual(output_val.dense_shape, [6, 4]) + @test_util.run_deprecated_v1 def testFeedMultipleInferredDims(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -218,12 +231,14 @@ class SparseReshapeTest(test.TestCase): with self.assertRaisesOpError("only one output dimension may be -1"): sess.run(sp_output, {sp_input: input_val}) + @test_util.run_deprecated_v1 def testProvideStaticallyMismatchedSizes(self): input_val = self._SparseTensorValue_5x6() sp_input = sparse_tensor.SparseTensor.from_value(input_val) with self.assertRaisesRegexp(ValueError, "Cannot reshape"): sparse_ops.sparse_reshape(sp_input, [4, 7]) + @test_util.run_deprecated_v1 def testFeedMismatchedSizes(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -233,6 +248,7 @@ class SparseReshapeTest(test.TestCase): "Input to reshape is a tensor with 30 dense values"): sess.run(sp_output, {sp_input: input_val}) + @test_util.run_deprecated_v1 def testFeedMismatchedSizesWithInferredDim(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -241,6 +257,7 @@ class SparseReshapeTest(test.TestCase): with self.assertRaisesOpError("requested shape requires a multiple"): sess.run(sp_output, {sp_input: input_val}) + @test_util.run_deprecated_v1 def testFeedPartialShapes(self): with self.session(use_gpu=False): # Incorporate new rank into shape information if known @@ -266,6 +283,7 @@ class SparseReshapeTest(test.TestCase): self.assertListEqual(sp_output.indices.get_shape().as_list(), [5, None]) self.assertListEqual(sp_output.dense_shape.get_shape().as_list(), [None]) + @test_util.run_deprecated_v1 def testFeedDenseReshapeSemantics(self): with self.session(use_gpu=False) as sess: # Compute a random rank-5 initial shape and new shape, randomly sparsify diff --git a/tensorflow/python/kernel_tests/sparse_serialization_ops_test.py b/tensorflow/python/kernel_tests/sparse_serialization_ops_test.py index b24a086969..5a48eb825d 100644 --- a/tensorflow/python/kernel_tests/sparse_serialization_ops_test.py +++ b/tensorflow/python/kernel_tests/sparse_serialization_ops_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor as sparse_tensor_lib +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.platform import test @@ -73,7 +74,7 @@ class SerializeSparseTest(test.TestCase): serialized = serialize_fn(sp_input, out_type=out_type) sp_deserialized = deserialize_fn(serialized, dtype=dtypes.int32) - indices, values, shape = sess.run(sp_deserialized) + indices, values, shape = self.evaluate(sp_deserialized) self.assertAllEqual(indices, sp_input[0]) self.assertAllEqual(values, sp_input[1]) @@ -110,14 +111,17 @@ class SerializeSparseTest(test.TestCase): self.assertAllEqual(combined_values[6:], sp_input[1]) self.assertAllEqual(combined_shape, [2, 5, 6]) + @test_util.run_deprecated_v1 def testSerializeDeserializeBatch(self): self._testSerializeDeserializeBatchHelper(sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse) + @test_util.run_deprecated_v1 def testSerializeDeserializeManyBatch(self): self._testSerializeDeserializeBatchHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_many_sparse) + @test_util.run_deprecated_v1 def testVariantSerializeDeserializeBatch(self): self._testSerializeDeserializeBatchHelper(sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse, @@ -145,10 +149,12 @@ class SerializeSparseTest(test.TestCase): self.assertAllEqual(combined_values[6:], sp_input1[1]) self.assertAllEqual(combined_shape, [2, 5, 6]) + @test_util.run_deprecated_v1 def testSerializeDeserializeBatchInconsistentShape(self): self._testSerializeDeserializeBatchInconsistentShapeHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse) + @test_util.run_deprecated_v1 def testVariantSerializeDeserializeBatchInconsistentShape(self): self._testSerializeDeserializeBatchInconsistentShapeHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse, @@ -188,10 +194,12 @@ class SerializeSparseTest(test.TestCase): self.assertAllEqual(combined_shape, [2, 2, 5, 6]) + @test_util.run_deprecated_v1 def testSerializeDeserializeNestedBatch(self): self._testSerializeDeserializeNestedBatchHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse) + @test_util.run_deprecated_v1 def testVariantSerializeDeserializeNestedBatch(self): self._testSerializeDeserializeNestedBatchHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse, @@ -224,14 +232,17 @@ class SerializeSparseTest(test.TestCase): self.assertAllEqual(combined_values[6:], input1_val[1]) self.assertAllEqual(combined_shape, [2, 5, 6]) + @test_util.run_deprecated_v1 def testFeedSerializeDeserializeBatch(self): self._testFeedSerializeDeserializeBatchHelper(sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse) + @test_util.run_deprecated_v1 def testFeedSerializeDeserializeManyBatch(self): self._testFeedSerializeDeserializeBatchHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_many_sparse) + @test_util.run_deprecated_v1 def testFeedVariantSerializeDeserializeBatch(self): self._testFeedSerializeDeserializeBatchHelper(sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse, @@ -256,6 +267,7 @@ class SerializeSparseTest(test.TestCase): }) self.assertEqual(serialized_value.shape, (4, 3)) + @test_util.run_deprecated_v1 def testSerializeManyShape(self): self._testSerializeManyShapeHelper(sparse_ops.serialize_many_sparse) @@ -287,19 +299,23 @@ class SerializeSparseTest(test.TestCase): self.assertAllEqual(deserialized_value.values, values_value) self.assertAllEqual(deserialized_value.dense_shape, shape_value) + @test_util.run_deprecated_v1 def testSerializeManyDeserializeBatch(self): self._testSerializeManyDeserializeBatchHelper( sparse_ops.serialize_many_sparse, sparse_ops.deserialize_sparse) + @test_util.run_deprecated_v1 def testSerializeManyDeserializeManyBatch(self): self._testSerializeManyDeserializeBatchHelper( sparse_ops.serialize_many_sparse, sparse_ops.deserialize_many_sparse) + @test_util.run_deprecated_v1 def testVariantSerializeManyDeserializeBatch(self): self._testSerializeManyDeserializeBatchHelper( sparse_ops.serialize_many_sparse, sparse_ops.deserialize_sparse, dtypes.variant) + @test_util.run_deprecated_v1 def testVariantSerializeDeserializeScalar(self): with self.session(use_gpu=False) as sess: indices_value = np.array([[]], dtype=np.int64) @@ -321,6 +337,7 @@ class SerializeSparseTest(test.TestCase): self.assertAllEqual(deserialized_value.values, values_value) self.assertAllEqual(deserialized_value.dense_shape, shape_value) + @test_util.run_deprecated_v1 def testVariantSerializeDeserializeScalarBatch(self): with self.session(use_gpu=False) as sess: indices_value = np.array([[]], dtype=np.int64) @@ -367,14 +384,17 @@ class SerializeSparseTest(test.TestCase): {sp_input0: input0_val, sp_input1: input1_val}) + @test_util.run_deprecated_v1 def testDeserializeFailsWrongType(self): self._testDeserializeFailsWrongTypeHelper(sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse) + @test_util.run_deprecated_v1 def testDeserializeManyFailsWrongType(self): self._testDeserializeFailsWrongTypeHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_many_sparse) + @test_util.run_deprecated_v1 def testVariantDeserializeFailsWrongType(self): self._testDeserializeFailsWrongTypeHelper(sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse, @@ -402,14 +422,17 @@ class SerializeSparseTest(test.TestCase): {sp_input0: input0_val, sp_input1: input1_val}) + @test_util.run_deprecated_v1 def testDeserializeFailsInconsistentRank(self): self._testDeserializeFailsInconsistentRankHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse) + @test_util.run_deprecated_v1 def testDeserializeManyFailsInconsistentRank(self): self._testDeserializeFailsInconsistentRankHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_many_sparse) + @test_util.run_deprecated_v1 def testVariantDeserializeFailsInconsistentRank(self): self._testDeserializeFailsInconsistentRankHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse, @@ -431,10 +454,12 @@ class SerializeSparseTest(test.TestCase): with self.assertRaisesOpError(r"Could not parse serialized proto"): sess.run(sp_deserialized, {sp_input0: input0_val}) + @test_util.run_deprecated_v1 def testDeserializeFailsInvalidProto(self): self._testDeserializeFailsInvalidProtoHelper(sparse_ops.serialize_sparse, sparse_ops.deserialize_sparse) + @test_util.run_deprecated_v1 def testDeserializeManyFailsInvalidProto(self): self._testDeserializeFailsInvalidProtoHelper( sparse_ops.serialize_sparse, sparse_ops.deserialize_many_sparse) diff --git a/tensorflow/python/kernel_tests/sparse_slice_op_test.py b/tensorflow/python/kernel_tests/sparse_slice_op_test.py index 098353741f..7f8c91bde6 100644 --- a/tensorflow/python/kernel_tests/sparse_slice_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_slice_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import sparse_ops import tensorflow.python.ops.sparse_grad # pylint: disable=unused-import @@ -79,6 +80,7 @@ class SparseSliceOpTest(test.TestCase): return sparse_tensor.SparseTensor.from_value( self._SparseTensorValue_3x4x2()) + @test_util.run_deprecated_v1 def testSliceMatrixRows(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_4x6() @@ -96,6 +98,7 @@ class SparseSliceOpTest(test.TestCase): [20, 23, 25, 30, 32, 33, 35]) self.assertAllEqual(sp_tensor1.dense_shape.eval(), [2, 6]) + @test_util.run_deprecated_v1 def testSliceMatrixUnevenCols(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_5x7() @@ -137,6 +140,7 @@ class SparseSliceOpTest(test.TestCase): self.assertAllEqual(sp_tensor3.values.eval(), [16, 46]) self.assertAllEqual(sp_tensor3.dense_shape.eval(), [5, 1]) + @test_util.run_deprecated_v1 def testSliceMatrixUnevenRows(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_5x7() @@ -173,6 +177,7 @@ class SparseSliceOpTest(test.TestCase): self.assertAllEqual(sp_tensor2.dense_shape.eval(), [1, 7]) return + @test_util.run_deprecated_v1 def testSliceAllRows(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_4x6() @@ -195,6 +200,7 @@ class SparseSliceOpTest(test.TestCase): self.assertAllEqual(sp_tensor3.values.eval(), [30, 32, 33, 35]) self.assertAllEqual(sp_tensor3.dense_shape.eval(), [1, 6]) + @test_util.run_deprecated_v1 def testSliceColumns(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_4x6() @@ -215,6 +221,7 @@ class SparseSliceOpTest(test.TestCase): self.assertAllEqual(sparse_tensor2.values.eval(), [4, 5, 14, 25, 35]) self.assertAllEqual(sparse_tensor2.dense_shape.eval(), [4, 2]) + @test_util.run_deprecated_v1 def testSliceAllColumns(self): with self.session(use_gpu=False): sp_input = self._SparseTensor_4x6() @@ -246,6 +253,7 @@ class SparseSliceOpTest(test.TestCase): self.assertAllEqual(sparse_tensor5.values.eval(), [5, 25, 35]) self.assertAllEqual(sparse_tensor5.dense_shape.eval(), [4, 1]) + @test_util.run_deprecated_v1 def testGradients(self): sp_input = self._SparseTensor_4x6(val_dtype=np.float32) start_and_size = [([0, 0], [4, 2]), diff --git a/tensorflow/python/kernel_tests/sparse_split_op_test.py b/tensorflow/python/kernel_tests/sparse_split_op_test.py index 95661ded4b..f4bb7498b0 100644 --- a/tensorflow/python/kernel_tests/sparse_split_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_split_op_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import sparse_ops from tensorflow.python.platform import test @@ -75,6 +76,7 @@ class SparseSplitOpTest(test.TestCase): return sparse_tensor.SparseTensor.from_value(self._SparseTensorValue_3x4x2( )) + @test_util.run_deprecated_v1 def testSplitMatrixRows(self): with self.session(use_gpu=False): sp_tensors = sparse_ops.sparse_split( @@ -92,6 +94,7 @@ class SparseSplitOpTest(test.TestCase): [20, 23, 25, 30, 32, 33, 35]) self.assertAllEqual(sp_tensors[1].dense_shape.eval(), [2, 6]) + @test_util.run_deprecated_v1 def testSplitMatrixUnevenCols(self): with self.session(use_gpu=False): sp_tensors_3 = sparse_ops.sparse_split( @@ -131,6 +134,7 @@ class SparseSplitOpTest(test.TestCase): self.assertAllEqual(sp_tensors_4[3].values.eval(), [16, 46]) self.assertAllEqual(sp_tensors_4[3].dense_shape.eval(), [5, 1]) + @test_util.run_deprecated_v1 def testSplitMatrixUnevenRows(self): with self.session(use_gpu=False): sp_tensors_2 = sparse_ops.sparse_split( @@ -167,6 +171,7 @@ class SparseSplitOpTest(test.TestCase): self.assertAllEqual(sp_tensors_3[2].dense_shape.eval(), [1, 7]) return + @test_util.run_deprecated_v1 def testSplitAllRows(self): with self.session(use_gpu=False): sp_tensors = sparse_ops.sparse_split( @@ -189,6 +194,7 @@ class SparseSplitOpTest(test.TestCase): self.assertAllEqual(sp_tensors[3].values.eval(), [30, 32, 33, 35]) self.assertAllEqual(sp_tensors[3].dense_shape.eval(), [1, 6]) + @test_util.run_deprecated_v1 def testSplitColumns(self): with self.session(use_gpu=False): sparse_tensors = sparse_ops.sparse_split( @@ -207,6 +213,7 @@ class SparseSplitOpTest(test.TestCase): self.assertAllEqual(sparse_tensors[2].values.eval(), [4, 5, 14, 25, 35]) self.assertAllEqual(sparse_tensors[2].dense_shape.eval(), [4, 2]) + @test_util.run_deprecated_v1 def testSplitAllColumns(self): with self.session(use_gpu=False): sparse_tensors = sparse_ops.sparse_split( @@ -234,6 +241,7 @@ class SparseSplitOpTest(test.TestCase): self.assertAllEqual(sparse_tensors[5].values.eval(), [5, 25, 35]) self.assertAllEqual(sparse_tensors[5].dense_shape.eval(), [4, 1]) + @test_util.run_deprecated_v1 def testSliceConcat(self): for sp_input in (self._SparseTensorValue_3x4x2(), self._SparseTensor_3x4x2()): diff --git a/tensorflow/python/kernel_tests/sparse_tensor_dense_matmul_grad_test.py b/tensorflow/python/kernel_tests/sparse_tensor_dense_matmul_grad_test.py index b8f33d6a81..fa2bab1fca 100644 --- a/tensorflow/python/kernel_tests/sparse_tensor_dense_matmul_grad_test.py +++ b/tensorflow/python/kernel_tests/sparse_tensor_dense_matmul_grad_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import sparse_ops import tensorflow.python.ops.sparse_grad # pylint: disable=unused-import @@ -89,6 +90,7 @@ class SparseTensorDenseMatMulGradientTest(test.TestCase): self._testGradients(adjoint_a, adjoint_b, name, values_dtype, indices_dtype) + @test_util.run_deprecated_v1 def testGradients(self): np.random.seed(5) # Fix seed to avoid flakiness self._testGradientsType(np.float32, np.int64) diff --git a/tensorflow/python/kernel_tests/sparse_tensor_dense_matmul_op_test.py b/tensorflow/python/kernel_tests/sparse_tensor_dense_matmul_op_test.py index fe334045af..637cfaec99 100644 --- a/tensorflow/python/kernel_tests/sparse_tensor_dense_matmul_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_tensor_dense_matmul_op_test.py @@ -30,6 +30,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops @@ -80,7 +81,7 @@ class SparseTensorDenseMatMulTest(test.TestCase): self.assertEqual(tf_value_ans.get_shape()[1], np_ans.shape[1]) self.assertEqual(tf_tensor_ans.get_shape()[1], np_ans.shape[1]) - for out in (tf_value_ans.eval(), tf_tensor_ans.eval()): + for out in (tf_value_ans.eval(), self.evaluate(tf_tensor_ans)): if x.dtype == np.float32: self.assertAllClose(np_ans, out, rtol=1e-4, atol=1e-4) elif x.dtype == np.float64: @@ -96,6 +97,7 @@ class SparseTensorDenseMatMulTest(test.TestCase): self._testMatmul(x, y, indices_dtype=indices_dtype) + @test_util.run_deprecated_v1 def testBasic(self): np.random.seed(127) # Repeatable results self._testBasic(np.int32) @@ -106,6 +108,7 @@ class SparseTensorDenseMatMulTest(test.TestCase): self._testBasic(np.int32, indices_dtype=np.int32) self._testBasic(np.float32, indices_dtype=np.int32) + @test_util.run_deprecated_v1 def testShapeInference(self): x = np.random.rand(10, 10) x[np.abs(x) < 0.5] = 0 # Make it sparse @@ -229,6 +232,7 @@ class SparseTensorDenseMatMulTest(test.TestCase): self._testLarge(np.complex128) # Tests random sized matrices. + @test_util.run_deprecated_v1 def testFloatRandom(self): np.random.seed(127) # Repeatable results for _ in range(8): diff --git a/tensorflow/python/kernel_tests/sparse_tensors_map_ops_test.py b/tensorflow/python/kernel_tests/sparse_tensors_map_ops_test.py index e08464a701..6039ff1afa 100644 --- a/tensorflow/python/kernel_tests/sparse_tensors_map_ops_test.py +++ b/tensorflow/python/kernel_tests/sparse_tensors_map_ops_test.py @@ -24,6 +24,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor as sparse_tensor_lib +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.ops import variables @@ -76,6 +77,7 @@ class SparseTensorsMapTest(test.TestCase): shape = np.array([3, 4, 5]).astype(np.int64) return sparse_tensor_lib.SparseTensorValue(ind, val, shape) + @test_util.run_deprecated_v1 def testAddTakeMany(self): with self.session(graph=ops.Graph(), use_gpu=False) as sess: sp_input0 = self._SparseTensorValue_5x6(np.arange(6)) @@ -88,7 +90,7 @@ class SparseTensorsMapTest(test.TestCase): sp_out = take_many_sparse_from_tensors_map( sparse_map_op=handle0.op, sparse_handles=handles_concat) - combined_indices, combined_values, combined_shape = sess.run(sp_out) + combined_indices, combined_values, combined_shape = self.evaluate(sp_out) self.assertAllEqual(combined_indices[:6, 0], [0] * 6) # minibatch 0 self.assertAllEqual(combined_indices[:6, 1:], sp_input0[0]) @@ -98,6 +100,7 @@ class SparseTensorsMapTest(test.TestCase): self.assertAllEqual(combined_values[6:], sp_input1[1]) self.assertAllEqual(combined_shape, [2, 5, 6]) + @test_util.run_deprecated_v1 def testFeedAddTakeMany(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -114,7 +117,8 @@ class SparseTensorsMapTest(test.TestCase): sp_roundtrip = take_many_sparse_from_tensors_map( sparse_map_op=handle.op, sparse_handles=sparse_handles) - combined_indices, combined_values, combined_shape = sess.run(sp_roundtrip) + combined_indices, combined_values, combined_shape = self.evaluate( + sp_roundtrip) self.assertAllEqual(combined_indices[:6, 0], [0] * 6) # minibatch 0 self.assertAllEqual(combined_indices[:6, 1:], input0_val[0]) @@ -124,6 +128,7 @@ class SparseTensorsMapTest(test.TestCase): self.assertAllEqual(combined_values[6:], input1_val[1]) self.assertAllEqual(combined_shape, [2, 5, 6]) + @test_util.run_deprecated_v1 def testAddManyTakeManyRoundTrip(self): with self.session(use_gpu=False) as sess: # N == 4 because shape_value == [4, 5] @@ -146,6 +151,7 @@ class SparseTensorsMapTest(test.TestCase): self.assertAllEqual(roundtrip_value.values, values_value) self.assertAllEqual(roundtrip_value.dense_shape, shape_value) + @test_util.run_deprecated_v1 def testDeserializeFailsInconsistentRank(self): with self.session(use_gpu=False) as sess: sp_input = self._SparseTensorPlaceholder() @@ -165,19 +171,20 @@ class SparseTensorsMapTest(test.TestCase): with self.assertRaisesOpError( r"Inconsistent rank across SparseTensors: rank prior to " r"SparseTensor\[1\] was: 3 but rank of SparseTensor\[1\] is: 4"): - sess.run(sp_roundtrip) + self.evaluate(sp_roundtrip) + @test_util.run_deprecated_v1 def testTakeManyFailsWrongInputOp(self): with self.session(use_gpu=False) as sess: input_val = self._SparseTensorValue_5x6(np.arange(6)) handle = add_sparse_to_tensors_map(input_val) - handle_value = sess.run(handle) + handle_value = self.evaluate(handle) bad_handle = handle_value + 10 sp_roundtrip = take_many_sparse_from_tensors_map( sparse_map_op=handle.op, sparse_handles=[handle_value, bad_handle]) with self.assertRaisesOpError(r"Unable to find SparseTensor: 10"): - sess.run(sp_roundtrip) + self.evaluate(sp_roundtrip) class BenchmarkSparseTensorsMapVsSerialization(test.Benchmark): @@ -212,8 +219,8 @@ class BenchmarkSparseTensorsMapVsSerialization(test.Benchmark): variables.global_variables_initializer().run() - st_roundtrip_values = sess.run(st_roundtrip) - st_deserialized_values = sess.run(st_deserialized) + st_roundtrip_values = self.evaluate(st_roundtrip) + st_deserialized_values = self.evaluate(st_deserialized) np.testing.assert_equal(st_roundtrip_values.values, st_deserialized_values.values) np.testing.assert_equal(st_roundtrip_values.indices, diff --git a/tensorflow/python/kernel_tests/sparse_to_dense_op_py_test.py b/tensorflow/python/kernel_tests/sparse_to_dense_op_py_test.py index 7f63532e10..c6c45db4f9 100644 --- a/tensorflow/python/kernel_tests/sparse_to_dense_op_py_test.py +++ b/tensorflow/python/kernel_tests/sparse_to_dense_op_py_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.platform import test @@ -41,36 +42,42 @@ def _SparseToDense(sparse_indices, class SparseToDenseTest(test.TestCase): + @test_util.run_deprecated_v1 def testInt(self): with self.session(use_gpu=False): tf_ans = _SparseToDense([1, 3], [5], 1, 0).eval() np_ans = np.array([0, 1, 0, 1, 0]).astype(np.int32) self.assertAllClose(np_ans, tf_ans) + @test_util.run_deprecated_v1 def testFloat(self): with self.session(use_gpu=False): tf_ans = _SparseToDense([1, 3], [5], 1.0, 0.0).eval() np_ans = np.array([0, 1, 0, 1, 0]).astype(np.float32) self.assertAllClose(np_ans, tf_ans) + @test_util.run_deprecated_v1 def testString(self): with self.session(use_gpu=False): tf_ans = _SparseToDense([1, 3], [5], "a", "b").eval() np_ans = np.array(["b", "a", "b", "a", "b"]).astype(np.string_) self.assertAllEqual(np_ans, tf_ans) + @test_util.run_deprecated_v1 def testSetValue(self): with self.session(use_gpu=False): tf_ans = _SparseToDense([1, 3], [5], [1, 2], -1).eval() np_ans = np.array([-1, 1, -1, 2, -1]).astype(np.int32) self.assertAllClose(np_ans, tf_ans) + @test_util.run_deprecated_v1 def testSetSingleValue(self): with self.session(use_gpu=False): tf_ans = _SparseToDense([1, 3], [5], 1, -1).eval() np_ans = np.array([-1, 1, -1, 1, -1]).astype(np.int32) self.assertAllClose(np_ans, tf_ans) + @test_util.run_deprecated_v1 def test2d(self): # pylint: disable=bad-whitespace with self.session(use_gpu=False): @@ -80,11 +87,13 @@ class SparseToDenseTest(test.TestCase): [ 1, -1, -1, -1]]).astype(np.int32) self.assertAllClose(np_ans, tf_ans) + @test_util.run_deprecated_v1 def testZeroDefault(self): with self.cached_session(): x = sparse_ops.sparse_to_dense(2, [4], 7).eval() self.assertAllEqual(x, [0, 0, 7, 0]) + @test_util.run_deprecated_v1 def test3d(self): with self.session(use_gpu=False): tf_ans = _SparseToDense([[1, 3, 0], [2, 0, 1]], [3, 4, 2], 1, -1).eval() @@ -93,32 +102,37 @@ class SparseToDenseTest(test.TestCase): np_ans[2, 0, 1] = 1 self.assertAllClose(np_ans, tf_ans) + @test_util.run_deprecated_v1 def testBadShape(self): with self.cached_session(): with self.assertRaisesWithPredicateMatch(ValueError, "must be rank 1"): _SparseToDense([1, 3], [[5], [3]], 1, -1) + @test_util.run_deprecated_v1 def testBadValue(self): with self.cached_session(): dense = _SparseToDense([1, 3], [5], [[5], [3]], -1) with self.assertRaisesOpError( r"sparse_values has incorrect shape \[2,1\], " r"should be \[\] or \[2\]"): - dense.eval() + self.evaluate(dense) + @test_util.run_deprecated_v1 def testBadNumValues(self): with self.cached_session(): dense = _SparseToDense([1, 3], [5], [1, 2, 3], -1) with self.assertRaisesOpError( r"sparse_values has incorrect shape \[3\], should be \[\] or \[2\]"): - dense.eval() + self.evaluate(dense) + @test_util.run_deprecated_v1 def testBadDefault(self): with self.cached_session(): dense = _SparseToDense([1, 3], [5], [1, 2], [0]) with self.assertRaisesOpError("default_value should be a scalar"): - dense.eval() + self.evaluate(dense) + @test_util.run_deprecated_v1 def testOutOfBoundsIndicesWithWithoutValidation(self): with self.cached_session(): dense = _SparseToDense( @@ -128,7 +142,7 @@ class SparseToDenseTest(test.TestCase): default_value=0.0) with self.assertRaisesOpError( r"indices\[1\] = \[10\] is out of bounds: need 0 <= index < \[5\]"): - dense.eval() + self.evaluate(dense) # Disable checks, the allocation should still fail. with self.assertRaisesOpError("out of bounds"): dense_without_validation = _SparseToDense( @@ -137,8 +151,9 @@ class SparseToDenseTest(test.TestCase): sparse_values=[-1.0, 1.0], default_value=0.0, validate_indices=False) - dense_without_validation.eval() + self.evaluate(dense_without_validation) + @test_util.run_deprecated_v1 def testRepeatingIndicesWithWithoutValidation(self): with self.cached_session(): dense = _SparseToDense( @@ -147,7 +162,7 @@ class SparseToDenseTest(test.TestCase): sparse_values=[-1.0, 1.0], default_value=0.0) with self.assertRaisesOpError(r"indices\[1\] = \[1\] is repeated"): - dense.eval() + self.evaluate(dense) # Disable checks dense_without_validation = _SparseToDense( sparse_indices=[[1], [1]], @@ -155,8 +170,9 @@ class SparseToDenseTest(test.TestCase): sparse_values=[-1.0, 1.0], default_value=0.0, validate_indices=False) - dense_without_validation.eval() + self.evaluate(dense_without_validation) + @test_util.run_deprecated_v1 def testUnsortedIndicesWithWithoutValidation(self): with self.cached_session(): dense = _SparseToDense( @@ -165,7 +181,7 @@ class SparseToDenseTest(test.TestCase): sparse_values=[-1.0, 1.0], default_value=0.0) with self.assertRaisesOpError(r"indices\[1\] = \[1\] is out of order"): - dense.eval() + self.evaluate(dense) # Disable checks dense_without_validation = _SparseToDense( sparse_indices=[[2], [1]], @@ -173,8 +189,9 @@ class SparseToDenseTest(test.TestCase): sparse_values=[-1.0, 1.0], default_value=0.0, validate_indices=False) - dense_without_validation.eval() + self.evaluate(dense_without_validation) + @test_util.run_deprecated_v1 def testShapeInferenceKnownShape(self): with self.session(use_gpu=False): indices = array_ops.placeholder(dtypes.int64) @@ -187,6 +204,7 @@ class SparseToDenseTest(test.TestCase): output = sparse_ops.sparse_to_dense(indices, shape, 1, 0) self.assertEqual(output.get_shape().as_list(), [None, None, None]) + @test_util.run_deprecated_v1 def testShapeInferenceUnknownShape(self): with self.session(use_gpu=False): indices = array_ops.placeholder(dtypes.int64) diff --git a/tensorflow/python/kernel_tests/sparse_xent_op_test.py b/tensorflow/python/kernel_tests/sparse_xent_op_test.py index 0510bc5321..8f0842f7f5 100644 --- a/tensorflow/python/kernel_tests/sparse_xent_op_test.py +++ b/tensorflow/python/kernel_tests/sparse_xent_op_test.py @@ -29,6 +29,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops as ops_lib +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_nn_ops from tensorflow.python.ops import gradient_checker @@ -66,7 +67,7 @@ class SparseXentTest(test.TestCase): with self.cached_session(use_gpu=True) as sess: loss, backprop = gen_nn_ops.sparse_softmax_cross_entropy_with_logits( np_features, np_labels) - tf_loss, tf_backprop = sess.run([loss, backprop]) + tf_loss, tf_backprop = self.evaluate([loss, backprop]) self.assertAllCloseAccordingToType(np_loss, tf_loss) self.assertAllCloseAccordingToType(np_backprop, tf_backprop) @@ -76,10 +77,11 @@ class SparseXentTest(test.TestCase): loss, backprop = gen_nn_ops.sparse_softmax_cross_entropy_with_logits( np.array([[1.], [-1.], [0.]]).astype(np.float32), np.array([0, 0, 0]).astype(label_dtype)) - tf_loss, tf_backprop = sess.run([loss, backprop]) + tf_loss, tf_backprop = self.evaluate([loss, backprop]) self.assertAllClose([0.0, 0.0, 0.0], tf_loss) self.assertAllClose([[0.0], [0.0], [0.0]], tf_backprop) + @test_util.run_deprecated_v1 def testInvalidLabel(self): features = [[1., 1., 1., 1.], [1., 1., 1., 1.], [1., 2., 3., 4.], [1., 2., 3., 4.]] @@ -90,7 +92,7 @@ class SparseXentTest(test.TestCase): loss, backprop = ( gen_nn_ops.sparse_softmax_cross_entropy_with_logits( features, labels)) - tf_loss, tf_backprop = sess.run([loss, backprop]) + tf_loss, tf_backprop = self.evaluate([loss, backprop]) self.assertAllClose( [[np.nan] * 4, [0.25, 0.25, 0.25, -0.75], [-0.968, 0.087, 0.237, 0.6439], [np.nan] * 4], @@ -104,7 +106,7 @@ class SparseXentTest(test.TestCase): loss, backprop = ( gen_nn_ops.sparse_softmax_cross_entropy_with_logits(features, labels)) with self.assertRaisesOpError("Received a label value of"): - sess.run([loss, backprop]) + self.evaluate([loss, backprop]) def testNpXent(self): # We create 2 batches of logits for testing. @@ -152,6 +154,7 @@ class SparseXentTest(test.TestCase): nn_ops.sparse_softmax_cross_entropy_with_logits( labels=constant_op.constant(0), logits=constant_op.constant(1.0)) + @test_util.run_deprecated_v1 def testLabelsPlaceholderScalar(self): with self.session(use_gpu=True): labels = array_ops.placeholder(np.int32) @@ -164,7 +167,7 @@ class SparseXentTest(test.TestCase): with self.session(use_gpu=True): loss = nn_ops.sparse_softmax_cross_entropy_with_logits( labels=constant_op.constant(0), logits=constant_op.constant([1.0])) - self.assertAllClose(0.0, loss.eval()) + self.assertAllClose(0.0, self.evaluate(loss)) def testFloat(self): for label_dtype in np.int32, np.int64: @@ -187,6 +190,7 @@ class SparseXentTest(test.TestCase): def testEmpty(self): self._testXent(np.zeros((0, 3)), np.zeros((0,), dtype=np.int32)) + @test_util.run_deprecated_v1 def testGradient(self): with self.session(use_gpu=True): l = constant_op.constant([3, 0, 1], name="l") @@ -201,6 +205,7 @@ class SparseXentTest(test.TestCase): print("cross entropy gradient err = ", err) self.assertLess(err, 5e-8) + @test_util.run_deprecated_v1 def testSecondGradient(self): images_placeholder = array_ops.placeholder(dtypes.float32, shape=(3, 2)) labels_placeholder = array_ops.placeholder(dtypes.int32, shape=(3)) @@ -226,21 +231,24 @@ class SparseXentTest(test.TestCase): loss = nn_ops.sparse_softmax_cross_entropy_with_logits( labels=labels, logits=features) backprop = loss.op.inputs[0].op.outputs[1] - tf_loss, tf_backprop = sess.run([loss, backprop]) + tf_loss, tf_backprop = self.evaluate([loss, backprop]) self.assertAllCloseAccordingToType(np_loss, tf_loss) self.assertAllCloseAccordingToType(np_backprop, tf_backprop) + @test_util.run_deprecated_v1 def testHighDim(self): features = [[[1., 1., 1., 1.]], [[1., 2., 3., 4.]]] labels = [[3], [0]] self._testHighDim(features, labels) + @test_util.run_deprecated_v1 def testHighDim2(self): features = [[[1., 1., 1., 1.], [2., 2., 2., 2.]], [[1., 2., 3., 4.], [5., 6., 7., 8.]]] labels = [[3, 2], [0, 3]] self._testHighDim(features, labels) + @test_util.run_deprecated_v1 def testScalarHandling(self): with self.session(use_gpu=False) as sess: with self.assertRaisesRegexp(errors_impl.InvalidArgumentError, @@ -318,7 +326,7 @@ def sparse_vs_dense_xent_benchmark(batch_size, num_entries, use_gpu): # Using sparse_softmax_cross_entropy_with_logits with session.Session(config=config) as sess: if not use_gpu: - with ops_lib.device("/cpu:0"): + with test_util.device("/cpu:0"): ops = _sparse_vs_dense_xent_benchmark_sparse(labels, logits) else: ops = _sparse_vs_dense_xent_benchmark_sparse(labels, logits) diff --git a/tensorflow/python/kernel_tests/sparsemask_op_test.py b/tensorflow/python/kernel_tests/sparsemask_op_test.py index 6f5dd45b61..b1cd0227bc 100644 --- a/tensorflow/python/kernel_tests/sparsemask_op_test.py +++ b/tensorflow/python/kernel_tests/sparsemask_op_test.py @@ -20,12 +20,14 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.platform import test class SparseMaskTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): values = np.random.rand(4, 4).astype(np.single) indices = np.array([0, 2, 3, 4], dtype=np.int32) diff --git a/tensorflow/python/kernel_tests/split_op_test.py b/tensorflow/python/kernel_tests/split_op_test.py index 944b0e59b1..517db3450f 100644 --- a/tensorflow/python/kernel_tests/split_op_test.py +++ b/tensorflow/python/kernel_tests/split_op_test.py @@ -42,6 +42,7 @@ class SplitOpTest(test.TestCase): data -= 1j * data return data + @test_util.run_deprecated_v1 def testShapeInference(self): model_input = array_ops.placeholder(dtypes.float32, shape=(1, 10)) @@ -85,6 +86,7 @@ class SplitOpTest(test.TestCase): with self.cached_session(use_gpu=True) as sess: sess.run(result, feed_dict={model_input2: np.ones([4, 2])}) + @test_util.run_deprecated_v1 def testFailWithoutExplicitNum(self): size_splits = array_ops.placeholder(dtype=dtypes.int32, shape=[None]) @@ -209,6 +211,7 @@ class SplitOpTest(test.TestCase): self.assertAllEqual(result[:, 0:1], inp_grads[0]) self.assertAllEqual(result[:, 1:4], inp_grads[1]) + @test_util.run_deprecated_v1 def testOutputShape(self): for axis in [1, -1]: with self.cached_session(use_gpu=True): @@ -318,15 +321,17 @@ class SplitOpTest(test.TestCase): inp_grads = [self._makeData((4, 1), dtype)for _ in range(4)] grad_tensors = [constant_op.constant(x) for x in inp_grads] grad = gradients_impl.gradients(s, [inp_tensor], grad_tensors)[0] - result = grad.eval() + result = self.evaluate(grad) for i in range(4): self.assertAllEqual(result[:, i:i + 1], inp_grads[i]) + @test_util.run_deprecated_v1 def testGradientsAll(self): for dtype in _TEST_DTYPES: self._testGradientsSimple(dtype) self._testGradientsSimpleVariable(dtype) + @test_util.run_deprecated_v1 def testShapeFunctionEdgeCases(self): # split_dim greater than rank of input. with self.assertRaises(ValueError): @@ -356,6 +361,7 @@ class SplitOpTest(test.TestCase): for s in splits: self.assertEqual(None, s.get_shape().ndims) + @test_util.run_deprecated_v1 def testVariableShapeFunction(self): # size_splits too big with self.assertRaises(ValueError): @@ -366,6 +372,7 @@ class SplitOpTest(test.TestCase): assert s0.shape.as_list() == [2] assert s1.shape.as_list() == [1] + @test_util.run_deprecated_v1 def testNonexistentDimTensor(self): x = array_ops.placeholder(dtypes.int32) values = np.zeros([5, 30]) diff --git a/tensorflow/python/kernel_tests/stack_op_test.py b/tensorflow/python/kernel_tests/stack_op_test.py index 4b355620bf..ca3357a0ed 100644 --- a/tensorflow/python/kernel_tests/stack_op_test.py +++ b/tensorflow/python/kernel_tests/stack_op_test.py @@ -24,6 +24,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import variables @@ -41,6 +42,7 @@ def np_split_squeeze(array, axis): class StackOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testSimple(self): np.random.seed(7) with self.session(use_gpu=True): @@ -54,6 +56,7 @@ class StackOpTest(test.TestCase): c = array_ops.stack(xs) self.assertAllEqual(c.eval(), data) + @test_util.run_deprecated_v1 def testSimpleParallelCPU(self): np.random.seed(7) with self.session(use_gpu=False): @@ -63,6 +66,7 @@ class StackOpTest(test.TestCase): c = array_ops.parallel_stack(xs) self.assertAllEqual(c.eval(), data) + @test_util.run_deprecated_v1 def testSimpleParallelGPU(self): np.random.seed(7) with self.session(use_gpu=True): @@ -72,6 +76,7 @@ class StackOpTest(test.TestCase): c = array_ops.parallel_stack(xs) self.assertAllEqual(c.eval(), data) + @test_util.run_deprecated_v1 def testConst(self): np.random.seed(7) with self.session(use_gpu=True): @@ -96,6 +101,7 @@ class StackOpTest(test.TestCase): b = array_ops.reshape(a, array_ops.stack([2, 3])) self.assertAllEqual(b.get_shape(), [2, 3]) + @test_util.run_deprecated_v1 def testConstParallelCPU(self): np.random.seed(7) with self.session(use_gpu=False): @@ -110,6 +116,7 @@ class StackOpTest(test.TestCase): c = array_ops.parallel_stack(data) self.assertAllEqual(c.eval(), data) + @test_util.run_deprecated_v1 def testConstParallelGPU(self): np.random.seed(7) with self.session(use_gpu=True): @@ -124,6 +131,7 @@ class StackOpTest(test.TestCase): c = array_ops.parallel_stack(data) self.assertAllEqual(c.eval(), data) + @test_util.run_deprecated_v1 def testGradientsAxis0(self): np.random.seed(7) for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2): @@ -136,6 +144,7 @@ class StackOpTest(test.TestCase): err = gradient_checker.compute_gradient_error(xs, shapes, c, shape) self.assertLess(err, 1e-6) + @test_util.run_deprecated_v1 def testGradientsAxis1(self): np.random.seed(7) for shape in (2, 3), (3, 2), (4, 3, 2): @@ -150,6 +159,7 @@ class StackOpTest(test.TestCase): err = gradient_checker.compute_gradient_error(xs, shapes, c, out_shape) self.assertLess(err, 1e-6) + @test_util.run_deprecated_v1 def testZeroSizeCPU(self): # Verify that stack doesn't crash for zero size inputs with self.session(use_gpu=False): @@ -161,6 +171,7 @@ class StackOpTest(test.TestCase): p = array_ops.parallel_stack(list(x)).eval() self.assertAllEqual(p, x) + @test_util.run_deprecated_v1 def testZeroSizeGPU(self): # Verify that stack doesn't crash for zero size inputs with self.session(use_gpu=True): @@ -172,6 +183,7 @@ class StackOpTest(test.TestCase): p = array_ops.parallel_stack(list(x)).eval() self.assertAllEqual(p, x) + @test_util.run_deprecated_v1 def testAxis0DefaultCPU(self): with self.session(use_gpu=False): t = [constant_op.constant([1, 2, 3]), constant_op.constant([4, 5, 6])] @@ -182,6 +194,7 @@ class StackOpTest(test.TestCase): self.assertAllEqual(stacked, expected) self.assertAllEqual(parallel_stacked, expected) + @test_util.run_deprecated_v1 def testAxis0DefaultGPU(self): with self.session(use_gpu=True): t = [constant_op.constant([1, 2, 3]), constant_op.constant([4, 5, 6])] @@ -204,11 +217,11 @@ class StackOpTest(test.TestCase): with self.cached_session(use_gpu=True): actual_pack = array_ops.stack(test_arrays, axis=j) self.assertEqual(expected.shape, actual_pack.get_shape()) - actual_pack = actual_pack.eval() + actual_pack = self.evaluate(actual_pack) actual_stack = array_ops.stack(test_arrays, axis=j) self.assertEqual(expected.shape, actual_stack.get_shape()) - actual_stack = actual_stack.eval() + actual_stack = self.evaluate(actual_stack) self.assertNDArrayNear(expected, actual_stack, 1e-6) @@ -225,6 +238,7 @@ class StackOpTest(test.TestCase): class AutomaticStackingTest(test.TestCase): + @test_util.run_deprecated_v1 def testSimple(self): with self.session(use_gpu=True): self.assertAllEqual( @@ -253,17 +267,20 @@ class AutomaticStackingTest(test.TestCase): [[2., 2.], [3., 3.]], dtype=np.float32)]) self.assertAllEqual([[[0., 0.], [1., 1.]], [[2., 2.], [3., 3.]]], - result.eval()) + self.evaluate(result)) + @test_util.run_deprecated_v1 def testVariable(self): with self.session(use_gpu=True): v = variables.Variable(17) result = ops.convert_to_tensor([[0, 0, 0], [0, v, 0], [0, 0, 0]]) v.initializer.run() - self.assertAllEqual([[0, 0, 0], [0, 17, 0], [0, 0, 0]], result.eval()) + self.assertAllEqual([[0, 0, 0], [0, 17, 0], [0, 0, 0]], + self.evaluate(result)) v.assign(38).op.run() - self.assertAllEqual([[0, 0, 0], [0, 38, 0], [0, 0, 0]], result.eval()) + self.assertAllEqual([[0, 0, 0], [0, 38, 0], [0, 0, 0]], + self.evaluate(result)) def testDtype(self): t_0 = ops.convert_to_tensor([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) @@ -306,6 +323,7 @@ class AutomaticStackingTest(test.TestCase): t_2 = ops.convert_to_tensor([t_0, t_0, t_1], dtype=dtypes.float64) self.assertEqual(dtypes.float64, t_2.dtype) + @test_util.run_deprecated_v1 def testPlaceholder(self): with self.session(use_gpu=True): # Test using placeholder with a defined shape. @@ -324,6 +342,7 @@ class AutomaticStackingTest(test.TestCase): self.assertAllEqual( [[0, 0, 0], [0, 2, 0], [0, 0, 0]], result_1.eval(feed_dict={ph_1: 2})) + @test_util.run_deprecated_v1 def testShapeErrors(self): # Static shape error. ph_0 = array_ops.placeholder(dtypes.int32, shape=[1]) diff --git a/tensorflow/python/kernel_tests/stack_ops_test.py b/tensorflow/python/kernel_tests/stack_ops_test.py index 1aa12009ea..d50f3f4680 100644 --- a/tensorflow/python/kernel_tests/stack_ops_test.py +++ b/tensorflow/python/kernel_tests/stack_ops_test.py @@ -24,6 +24,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_data_flow_ops from tensorflow.python.ops import math_ops @@ -39,8 +40,9 @@ class StackOpTest(test.TestCase): c = gen_data_flow_ops.stack_push_v2(h, [[4.0, 5.0]]) with ops.control_dependencies([c]): c1 = gen_data_flow_ops.stack_pop_v2(h, dtypes.float32) - self.assertAllClose([[4.0, 5.0]], c1.eval()) + self.assertAllClose([[4.0, 5.0]], self.evaluate(c1)) + @test_util.run_deprecated_v1 def testStackPushPop(self): self._testStackPushPop(use_gpu=False) self._testStackPushPop(use_gpu=True) @@ -54,8 +56,9 @@ class StackOpTest(test.TestCase): c = gen_data_flow_ops.stack_push_v2(h, x, swap_memory=True) with ops.control_dependencies([c]): c1 = gen_data_flow_ops.stack_pop_v2(h, dtypes.float32) - self.assertAllClose(a, c1.eval()) + self.assertAllClose(a, self.evaluate(c1)) + @test_util.run_deprecated_v1 def testStackPushPopSwap(self): self._testStackPushPopSwap(use_gpu=False) self._testStackPushPopSwap(use_gpu=True) @@ -91,8 +94,9 @@ class StackOpTest(test.TestCase): _, ry = control_flow_ops.while_loop( c1, b1, [r, v], [r.get_shape(), tensor_shape.unknown_shape()]) - self.assertAllClose(np.ones(2000) * 10.0, ry.eval()) + self.assertAllClose(np.ones(2000) * 10.0, self.evaluate(ry)) + @test_util.run_deprecated_v1 def testStackWhileSwap(self): self._testStackWhileSwap(use_gpu=False) self._testStackWhileSwap(use_gpu=True) @@ -110,8 +114,9 @@ class StackOpTest(test.TestCase): with ops.control_dependencies([c2]): c2 = gen_data_flow_ops.stack_pop_v2(h2, dtypes.float32) r = c1 + c2 - self.assertAllClose(9.0, r.eval()) + self.assertAllClose(9.0, self.evaluate(r)) + @test_util.run_deprecated_v1 def testMultiStack(self): self._testMultiStack(use_gpu=False) self._testMultiStack(use_gpu=True) @@ -131,10 +136,11 @@ class StackOpTest(test.TestCase): pop1 = gen_data_flow_ops.stack_pop_v2(h1, dtypes.float32) pop2 = gen_data_flow_ops.stack_pop_v2(h2, dtypes.float32) - out1, out2 = sess.run([pop1, pop2]) + out1, out2 = self.evaluate([pop1, pop2]) self.assertAllClose(out1, 4.0) self.assertAllClose(out2, 5.0) + @test_util.run_deprecated_v1 def testSameNameStacks(self): self._testSameNameStacks(use_gpu=False) self._testSameNameStacks(use_gpu=True) @@ -144,8 +150,9 @@ class StackOpTest(test.TestCase): h = gen_data_flow_ops.stack_v2( -1, elem_type=dtypes.float32, stack_name="foo") c1 = gen_data_flow_ops.stack_close_v2(h) - sess.run(c1) + self.evaluate(c1) + @test_util.run_deprecated_v1 def testCloseStack(self): self._testCloseStack(use_gpu=False) self._testCloseStack(use_gpu=True) @@ -157,8 +164,9 @@ class StackOpTest(test.TestCase): c = gen_data_flow_ops.stack_push_v2(h, [[4.0, 5.0]]) with ops.control_dependencies([c]): c1 = gen_data_flow_ops.stack_close_v2(h) - sess.run(c1) + self.evaluate(c1) + @test_util.run_deprecated_v1 def testPushCloseStack(self): self._testPushCloseStack(use_gpu=False) self._testPushCloseStack(use_gpu=True) @@ -173,8 +181,9 @@ class StackOpRefTest(test.TestCase): c = gen_data_flow_ops.stack_push(h, [[4.0, 5.0]]) with ops.control_dependencies([c]): c1 = gen_data_flow_ops.stack_pop(h, dtypes.float32) - self.assertAllClose([[4.0, 5.0]], c1.eval()) + self.assertAllClose([[4.0, 5.0]], self.evaluate(c1)) + @test_util.run_deprecated_v1 def testStackPushPop(self): self._testStackPushPop(use_gpu=False) self._testStackPushPop(use_gpu=True) @@ -187,8 +196,9 @@ class StackOpRefTest(test.TestCase): c = gen_data_flow_ops.stack_push(h, x, swap_memory=True) with ops.control_dependencies([c]): c1 = gen_data_flow_ops.stack_pop(h, dtypes.float32) - self.assertAllClose(a, c1.eval()) + self.assertAllClose(a, self.evaluate(c1)) + @test_util.run_deprecated_v1 def testStackPushPopSwap(self): self._testStackPushPopSwap(use_gpu=False) self._testStackPushPopSwap(use_gpu=True) @@ -204,7 +214,7 @@ class StackOpRefTest(test.TestCase): with ops.control_dependencies([c2]): c2 = gen_data_flow_ops.stack_pop(h2, dtypes.float32) r = c1 + c2 - self.assertAllClose(9.0, r.eval()) + self.assertAllClose(9.0, self.evaluate(r)) def _testStackWhileSwap(self, use_gpu): with self.cached_session(use_gpu=use_gpu): @@ -236,12 +246,14 @@ class StackOpRefTest(test.TestCase): _, ry = control_flow_ops.while_loop( c1, b1, [r, v], [r.get_shape(), tensor_shape.unknown_shape()]) - self.assertAllClose(np.ones(2000) * 10.0, ry.eval()) + self.assertAllClose(np.ones(2000) * 10.0, self.evaluate(ry)) + @test_util.run_deprecated_v1 def testStackWhileSwap(self): self._testStackWhileSwap(use_gpu=False) self._testStackWhileSwap(use_gpu=True) + @test_util.run_deprecated_v1 def testMultiStack(self): self._testMultiStack(use_gpu=False) self._testMultiStack(use_gpu=True) @@ -253,8 +265,9 @@ class StackOpRefTest(test.TestCase): h2 = gen_data_flow_ops._stack(dtypes.float32, stack_name="foo") c2 = gen_data_flow_ops.stack_push(h2, 5.0) _ = c1 + c2 - self.assertNotEqual(h1.eval()[1], h2.eval()[1]) + self.assertNotEqual(h1.eval()[1], self.evaluate(h2)[1]) + @test_util.run_deprecated_v1 def testSameNameStacks(self): self._testSameNameStacks(use_gpu=False) self._testSameNameStacks(use_gpu=True) @@ -263,8 +276,9 @@ class StackOpRefTest(test.TestCase): with self.cached_session(use_gpu=use_gpu) as sess: h = gen_data_flow_ops._stack(dtypes.float32, stack_name="foo") c1 = gen_data_flow_ops.stack_close(h) - sess.run(c1) + self.evaluate(c1) + @test_util.run_deprecated_v1 def testCloseStack(self): self._testCloseStack(use_gpu=False) self._testCloseStack(use_gpu=True) @@ -275,8 +289,9 @@ class StackOpRefTest(test.TestCase): c = gen_data_flow_ops.stack_push(h, [[4.0, 5.0]]) with ops.control_dependencies([c]): c1 = gen_data_flow_ops.stack_close(h) - sess.run(c1) + self.evaluate(c1) + @test_util.run_deprecated_v1 def testPushCloseStack(self): self._testPushCloseStack(use_gpu=False) self._testPushCloseStack(use_gpu=True) diff --git a/tensorflow/python/kernel_tests/stage_op_test.py b/tensorflow/python/kernel_tests/stage_op_test.py index b814843b86..83e06ba48b 100644 --- a/tensorflow/python/kernel_tests/stage_op_test.py +++ b/tensorflow/python/kernel_tests/stage_op_test.py @@ -18,6 +18,7 @@ from __future__ import print_function from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import math_ops @@ -28,6 +29,7 @@ TIMEOUT = 1 class StageTest(test.TestCase): + @test_util.run_deprecated_v1 def testSimple(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -47,6 +49,7 @@ class StageTest(test.TestCase): _, yval = sess.run([stage, y], feed_dict={x: i}) self.assertAllClose(4 * (i - 1) * (i - 1) * 128, yval, rtol=1e-4) + @test_util.run_deprecated_v1 def testMultiple(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -67,6 +70,7 @@ class StageTest(test.TestCase): self.assertAllClose( 4 * (i - 1) * (i - 1) * (i - 1) * 128, yval, rtol=1e-4) + @test_util.run_deprecated_v1 def testDictionary(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -110,6 +114,7 @@ class StageTest(test.TestCase): G.finalize() + @test_util.run_deprecated_v1 def testPeek(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -133,6 +138,7 @@ class StageTest(test.TestCase): for i in range(10): self.assertTrue(sess.run(peek, feed_dict={p: i}) == [i]) + @test_util.run_deprecated_v1 def testSizeAndClear(self): with ops.Graph().as_default() as G: with ops.device('/cpu:0'): @@ -158,6 +164,7 @@ class StageTest(test.TestCase): sess.run(clear) self.assertEqual(sess.run(size), 0) + @test_util.run_deprecated_v1 def testCapacity(self): capacity = 3 @@ -219,6 +226,7 @@ class StageTest(test.TestCase): # It should now be empty self.assertTrue(sess.run(size) == 0) + @test_util.run_deprecated_v1 def testMemoryLimit(self): memory_limit = 512 * 1024 # 512K chunk = 200 * 1024 # 256K diff --git a/tensorflow/python/kernel_tests/string_join_op_test.py b/tensorflow/python/kernel_tests/string_join_op_test.py index e4371ab5b9..2548e8695f 100644 --- a/tensorflow/python/kernel_tests/string_join_op_test.py +++ b/tensorflow/python/kernel_tests/string_join_op_test.py @@ -17,12 +17,14 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import test_util from tensorflow.python.ops import string_ops from tensorflow.python.platform import test class StringJoinOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testStringJoin(self): input0 = ["a", "b"] input1 = "a" diff --git a/tensorflow/python/kernel_tests/string_length_op_test.py b/tensorflow/python/kernel_tests/string_length_op_test.py index 57db7302b1..bfa6ac2454 100644 --- a/tensorflow/python/kernel_tests/string_length_op_test.py +++ b/tensorflow/python/kernel_tests/string_length_op_test.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import test_util from tensorflow.python.ops import string_ops from tensorflow.python.platform import test @@ -29,9 +30,10 @@ class StringLengthOpTest(test.TestCase): with self.cached_session() as sess: lengths = string_ops.string_length(strings) - values = sess.run(lengths) + values = self.evaluate(lengths) self.assertAllEqual(values, [[[1, 2], [3, 4], [5, 6]]]) + @test_util.run_deprecated_v1 def testUnit(self): unicode_strings = [u"H\xc3llo", u"\U0001f604"] utf8_strings = [s.encode("utf-8") for s in unicode_strings] @@ -43,14 +45,15 @@ class StringLengthOpTest(test.TestCase): utf8_char_lengths = string_ops.string_length( utf8_strings, unit="UTF8_CHAR") self.assertAllEqual( - sess.run(utf8_byte_lengths), expected_utf8_byte_lengths) + self.evaluate(utf8_byte_lengths), expected_utf8_byte_lengths) self.assertAllEqual( - sess.run(utf8_char_lengths), expected_utf8_char_lengths) + self.evaluate(utf8_char_lengths), expected_utf8_char_lengths) with self.assertRaisesRegexp( ValueError, "Attr 'unit' of 'StringLength' Op passed string 'XYZ' " 'not in: "BYTE", "UTF8_CHAR"'): string_ops.string_length(utf8_strings, unit="XYZ") + @test_util.run_deprecated_v1 def testLegacyPositionalName(self): # Code that predates the 'unit' parameter may have used a positional # argument for the 'name' parameter. Check that we don't break such code. diff --git a/tensorflow/python/kernel_tests/string_split_op_test.py b/tensorflow/python/kernel_tests/string_split_op_test.py index b968e885ed..0c91deb522 100644 --- a/tensorflow/python/kernel_tests/string_split_op_test.py +++ b/tensorflow/python/kernel_tests/string_split_op_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import string_ops from tensorflow.python.platform import test @@ -34,17 +35,18 @@ class StringSplitOpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split(strings) - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [0, 2], [0, 3], [1, 0]]) self.assertAllEqual(values, [b"pigs", b"on", b"the", b"wing", b"animals"]) self.assertAllEqual(shape, [2, 4]) + @test_util.run_deprecated_v1 def testStringSplitEmptyDelimiter(self): strings = ["hello", "hola", b"\xF0\x9F\x98\x8E"] # Last string is U+1F60E with self.cached_session() as sess: tokens = string_ops.string_split(strings, delimiter="") - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [1, 0], [1, 1], [1, 2], [1, 3], [2, 0], [2, 1], [2, 2], [2, 3]]) @@ -62,7 +64,7 @@ class StringSplitOpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split(strings) - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual( indices, [[1, 0], [2, 0], [3, 0], [5, 0], [6, 0], [7, 0], [8, 0]]) @@ -74,13 +76,14 @@ class StringSplitOpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split(strings, delimiter=" .") - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual( indices, [[1, 0], [2, 0], [3, 0], [5, 0], [6, 0], [7, 0], [8, 0]]) self.assertAllEqual(values, [b"a", b"b", b"c", b"d", b"e", b"f", b"g"]) self.assertAllEqual(shape, [10, 1]) + @test_util.run_deprecated_v1 def testStringSplitWithDelimiter(self): strings = ["hello|world", "hello world"] @@ -92,17 +95,18 @@ class StringSplitOpTest(test.TestCase): ValueError, string_ops.string_split, strings, delimiter=["a"]) tokens = string_ops.string_split(strings, delimiter="|") - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [1, 0]]) self.assertAllEqual(values, [b"hello", b"world", b"hello world"]) self.assertAllEqual(shape, [2, 2]) tokens = string_ops.string_split(strings, delimiter="| ") - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [1, 0], [1, 1]]) self.assertAllEqual(values, [b"hello", b"world", b"hello", b"world"]) self.assertAllEqual(shape, [2, 2]) + @test_util.run_deprecated_v1 def testStringSplitWithDelimiterTensor(self): strings = ["hello|world", "hello world"] @@ -121,6 +125,7 @@ class StringSplitOpTest(test.TestCase): self.assertAllEqual(values, [b"hello", b"world", b"hello world"]) self.assertAllEqual(shape, [2, 2]) + @test_util.run_deprecated_v1 def testStringSplitWithDelimitersTensor(self): strings = ["hello.cruel,world", "hello cruel world"] @@ -145,7 +150,7 @@ class StringSplitOpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split(strings, "#", skip_empty=False) - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [1, 0], [1, 1], [2, 0], [2, 1], [2, 2]]) @@ -154,7 +159,7 @@ class StringSplitOpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split(strings, "#") - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(values, [b"a", b"b", b"c"]) self.assertAllEqual(indices, [[0, 0], [1, 0], [2, 0]]) self.assertAllEqual(shape, [3, 1]) @@ -167,7 +172,7 @@ class StringSplitV2OpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split_v2(strings) - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [0, 2], [0, 3], [1, 0]]) self.assertAllEqual(values, [b"pigs", b"on", b"the", b"wing", b"animals"]) self.assertAllEqual(shape, [2, 4]) @@ -182,7 +187,7 @@ class StringSplitV2OpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split_v2(strings, sep="<>") - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual( indices, [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6]]) @@ -200,7 +205,7 @@ class StringSplitV2OpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split_v2(strings, sep=',') - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [1, 3], [1, 4]]) self.assertAllEqual(values, [b"1", b"2", b"3", @@ -217,7 +222,7 @@ class StringSplitV2OpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split_v2(strings) - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2]]) self.assertAllEqual(values, [b"1", b"2", b"3", b"4", b"5", b"6"]) @@ -233,7 +238,7 @@ class StringSplitV2OpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split_v2(strings, sep=',', maxsplit=1) - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [1, 0], [1, 1]]) self.assertAllEqual(values, [b"1", b"2,3", b"4", b"5,,6,"]) @@ -249,7 +254,7 @@ class StringSplitV2OpTest(test.TestCase): with self.cached_session() as sess: tokens = string_ops.string_split_v2(strings, maxsplit=1) - indices, values, shape = sess.run(tokens) + indices, values, shape = self.evaluate(tokens) self.assertAllEqual(indices, [[0, 0], [0, 1], [1, 0], [1, 1]]) self.assertAllEqual(values, [b"1", b"2 3", b"4", b"5 6 "]) diff --git a/tensorflow/python/kernel_tests/string_strip_op_test.py b/tensorflow/python/kernel_tests/string_strip_op_test.py index 1e404b7146..edff3862ff 100644 --- a/tensorflow/python/kernel_tests/string_strip_op_test.py +++ b/tensorflow/python/kernel_tests/string_strip_op_test.py @@ -30,7 +30,7 @@ class StringStripOpTest(test.TestCase): with self.cached_session() as sess: output = string_ops.string_strip(strings) - output = sess.run(output) + output = self.evaluate(output) self.assertAllEqual(output, [b"pigs on the wing", b"animals"]) def test_string_strip_2d(self): @@ -39,7 +39,7 @@ class StringStripOpTest(test.TestCase): with self.cached_session() as sess: output = string_ops.string_strip(strings) - output = sess.run(output) + output = self.evaluate(output) self.assertAllEqual(output, [[b"pigs on the wing", b"animals"], [b"hello", b"world"]]) @@ -48,7 +48,7 @@ class StringStripOpTest(test.TestCase): with self.cached_session() as sess: output = string_ops.string_strip(strings) - output = sess.run(output) + output = self.evaluate(output) self.assertAllEqual(output, [b"hello", b"", b"world", b""]) diff --git a/tensorflow/python/kernel_tests/string_to_hash_bucket_op_test.py b/tensorflow/python/kernel_tests/string_to_hash_bucket_op_test.py index 9cb0c9d18f..25f573fc14 100644 --- a/tensorflow/python/kernel_tests/string_to_hash_bucket_op_test.py +++ b/tensorflow/python/kernel_tests/string_to_hash_bucket_op_test.py @@ -19,6 +19,7 @@ from __future__ import print_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import string_ops from tensorflow.python.platform import test @@ -26,6 +27,7 @@ from tensorflow.python.platform import test class StringToHashBucketOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testStringToOneHashBucketFast(self): with self.cached_session(): input_string = array_ops.placeholder(dtypes.string) @@ -34,6 +36,7 @@ class StringToHashBucketOpTest(test.TestCase): self.assertAllEqual([0, 0, 0], result) + @test_util.run_deprecated_v1 def testStringToHashBucketsFast(self): with self.cached_session(): input_string = array_ops.placeholder(dtypes.string) @@ -46,6 +49,7 @@ class StringToHashBucketOpTest(test.TestCase): # Fingerprint64('d') -> 4470636696479570465 -> mod 10 -> 5 self.assertAllEqual([9, 2, 2, 5], result) + @test_util.run_deprecated_v1 def testStringToOneHashBucketLegacyHash(self): with self.cached_session(): input_string = array_ops.placeholder(dtypes.string) @@ -54,6 +58,7 @@ class StringToHashBucketOpTest(test.TestCase): self.assertAllEqual([0, 0, 0], result) + @test_util.run_deprecated_v1 def testStringToHashBucketsLegacyHash(self): with self.cached_session(): input_string = array_ops.placeholder(dtypes.string) @@ -70,7 +75,7 @@ class StringToHashBucketOpTest(test.TestCase): input_string = constant_op.constant(['a', 'b', 'c']) output = string_ops.string_to_hash_bucket_strong( input_string, 1, key=[123, 345]) - self.assertAllEqual([0, 0, 0], output.eval()) + self.assertAllEqual([0, 0, 0], self.evaluate(output)) def testStringToHashBucketsStrong(self): with self.cached_session(): @@ -81,7 +86,7 @@ class StringToHashBucketOpTest(test.TestCase): # StrongKeyedHash(key, 'a') -> 7157389809176466784 -> mod 10 -> 4 # StrongKeyedHash(key, 'b') -> 15805638358933211562 -> mod 10 -> 2 # StrongKeyedHash(key, 'c') -> 18100027895074076528 -> mod 10 -> 8 - self.assertAllEqual([4, 2, 8], output.eval()) + self.assertAllEqual([4, 2, 8], self.evaluate(output)) def testStringToHashBucketsStrongInvalidKey(self): with self.cached_session(): diff --git a/tensorflow/python/kernel_tests/string_to_number_op_test.py b/tensorflow/python/kernel_tests/string_to_number_op_test.py index 99ee25e125..49ccfd1028 100644 --- a/tensorflow/python/kernel_tests/string_to_number_op_test.py +++ b/tensorflow/python/kernel_tests/string_to_number_op_test.py @@ -19,6 +19,7 @@ from __future__ import division from __future__ import print_function from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import parsing_ops from tensorflow.python.platform import test @@ -45,6 +46,7 @@ class StringToNumberOpTest(test.TestCase): with self.assertRaisesOpError(outstr): output.eval(feed_dict={input_string: [instr]}) + @test_util.run_deprecated_v1 def testToFloat(self): self._test(dtypes.float32, [("0", 0), ("3", 3), ("-1", -1), @@ -58,6 +60,7 @@ class StringToNumberOpTest(test.TestCase): ("INF", float("INF"))], [("10foobar", _ERROR_MESSAGE + "10foobar")]) + @test_util.run_deprecated_v1 def testToDouble(self): self._test(dtypes.float64, [("0", 0), ("3", 3), ("-1", -1), @@ -71,6 +74,7 @@ class StringToNumberOpTest(test.TestCase): ("INF", float("INF"))], [("10foobar", _ERROR_MESSAGE + "10foobar")]) + @test_util.run_deprecated_v1 def testToInt32(self): self._test(dtypes.int32, [("0", 0), ("3", 3), ("-1", -1), @@ -84,6 +88,7 @@ class StringToNumberOpTest(test.TestCase): ("2.9", _ERROR_MESSAGE + "2.9"), ("10foobar", _ERROR_MESSAGE + "10foobar")]) + @test_util.run_deprecated_v1 def testToInt64(self): self._test(dtypes.int64, [("0", 0), ("3", 3), ("-1", -1), diff --git a/tensorflow/python/kernel_tests/substr_op_test.py b/tensorflow/python/kernel_tests/substr_op_test.py index 37aa624b07..9302152e82 100644 --- a/tensorflow/python/kernel_tests/substr_op_test.py +++ b/tensorflow/python/kernel_tests/substr_op_test.py @@ -22,6 +22,7 @@ from absl.testing import parameterized import numpy as np from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import string_ops from tensorflow.python.platform import test @@ -51,7 +52,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): length = np.array(3, dtype) substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_value) @parameterized.parameters( @@ -71,7 +72,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): length = np.array(3, dtype) substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_value) # Full string @@ -83,7 +84,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): length = np.array(5, dtype) substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, test_string) # Full string (Negative) @@ -95,7 +96,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): length = np.array(5, dtype) substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, test_string) # Length is larger in magnitude than a negative position @@ -111,7 +112,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): length = np.array(5, dtype) substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_string) @parameterized.parameters( @@ -138,7 +139,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): length = np.array(3, dtype) substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_value) @parameterized.parameters( @@ -173,7 +174,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): }[unit] substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_value) position = np.array(-3, dtype) @@ -188,7 +189,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): }[unit] substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_value) @parameterized.parameters( @@ -229,7 +230,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): }[unit] substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_value) @parameterized.parameters( @@ -271,7 +272,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): }[unit] substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_value) # Broadcast input string onto pos/len @@ -294,7 +295,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): }[unit] substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_value) # Test 1D broadcast @@ -310,7 +311,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): }[unit] substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): - substr = substr_op.eval() + substr = self.evaluate(substr_op) self.assertAllEqual(substr, expected_value) @parameterized.parameters( @@ -319,6 +320,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): (np.int32, "UTF8_CHAR"), (np.int64, "UTF8_CHAR"), ) + @test_util.run_deprecated_v1 def testBadBroadcast(self, dtype, unit): test_string = [[b"ten", b"eleven", b"twelve"], [b"thirteen", b"fourteen", b"fifteen"], @@ -338,6 +340,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): (np.int32, -6, "UTF8_CHAR"), (np.int64, -6, "UTF8_CHAR"), ) + @test_util.run_deprecated_v1 def testOutOfRangeError_Scalar(self, dtype, pos, unit): # Scalar/Scalar test_string = { @@ -349,7 +352,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): with self.assertRaises(errors_impl.InvalidArgumentError): - substr_op.eval() + self.evaluate(substr_op) @parameterized.parameters( (np.int32, 4, "BYTE"), @@ -361,6 +364,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): (np.int32, -4, "UTF8_CHAR"), (np.int64, -4, "UTF8_CHAR"), ) + @test_util.run_deprecated_v1 def testOutOfRangeError_VectorScalar(self, dtype, pos, unit): # Vector/Scalar test_string = { @@ -373,7 +377,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): with self.assertRaises(errors_impl.InvalidArgumentError): - substr_op.eval() + self.evaluate(substr_op) @parameterized.parameters( (np.int32, "BYTE"), @@ -381,6 +385,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): (np.int32, "UTF8_CHAR"), (np.int64, "UTF8_CHAR"), ) + @test_util.run_deprecated_v1 def testOutOfRangeError_MatrixMatrix(self, dtype, unit): # Matrix/Matrix test_string = { @@ -398,7 +403,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): with self.assertRaises(errors_impl.InvalidArgumentError): - substr_op.eval() + self.evaluate(substr_op) # Matrix/Matrix (with negative) position = np.array([[1, 2, -3], [1, 2, -4], [1, 2, -3]], dtype) @@ -406,7 +411,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): with self.assertRaises(errors_impl.InvalidArgumentError): - substr_op.eval() + self.evaluate(substr_op) @parameterized.parameters( (np.int32, "BYTE"), @@ -414,6 +419,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): (np.int32, "UTF8_CHAR"), (np.int64, "UTF8_CHAR"), ) + @test_util.run_deprecated_v1 def testOutOfRangeError_Broadcast(self, dtype, unit): # Broadcast test_string = { @@ -428,7 +434,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): with self.assertRaises(errors_impl.InvalidArgumentError): - substr_op.eval() + self.evaluate(substr_op) # Broadcast (with negative) position = np.array([-1, -2, -4], dtype) @@ -436,7 +442,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): substr_op = string_ops.substr(test_string, position, length, unit=unit) with self.cached_session(): with self.assertRaises(errors_impl.InvalidArgumentError): - substr_op.eval() + self.evaluate(substr_op) @parameterized.parameters( (np.int32, "BYTE"), @@ -444,6 +450,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): (np.int32, "UTF8_CHAR"), (np.int64, "UTF8_CHAR"), ) + @test_util.run_deprecated_v1 def testMismatchPosLenShapes(self, dtype, unit): test_string = { "BYTE": [[b"ten", b"eleven", b"twelve"], @@ -471,6 +478,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): with self.assertRaises(ValueError): string_ops.substr(test_string, position, length) + @test_util.run_deprecated_v1 def testWrongDtype(self): with self.cached_session(): with self.assertRaises(TypeError): @@ -478,6 +486,7 @@ class SubstrOpTest(test.TestCase, parameterized.TestCase): with self.assertRaises(TypeError): string_ops.substr(b"test", 3, 1.0) + @test_util.run_deprecated_v1 def testInvalidUnit(self): with self.cached_session(): with self.assertRaises(ValueError): diff --git a/tensorflow/python/kernel_tests/summary_v1_audio_op_test.py b/tensorflow/python/kernel_tests/summary_v1_audio_op_test.py index 63ce77b9d5..1547c55f8b 100644 --- a/tensorflow/python/kernel_tests/summary_v1_audio_op_test.py +++ b/tensorflow/python/kernel_tests/summary_v1_audio_op_test.py @@ -60,7 +60,7 @@ class SummaryV1AudioOpTest(test.TestCase): sample_rate = 8000 summ = summary.audio( "snd", const, max_outputs=3, sample_rate=sample_rate) - value = sess.run(summ) + value = self.evaluate(summ) self.assertEqual([], summ.get_shape()) audio_summ = self._AsSummary(value) diff --git a/tensorflow/python/kernel_tests/summary_v1_image_op_test.py b/tensorflow/python/kernel_tests/summary_v1_image_op_test.py index 094606944f..56de2e933d 100644 --- a/tensorflow/python/kernel_tests/summary_v1_image_op_test.py +++ b/tensorflow/python/kernel_tests/summary_v1_image_op_test.py @@ -24,6 +24,7 @@ from six.moves import xrange # pylint: disable=redefined-builtin from tensorflow.core.framework import summary_pb2 from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import image_ops import tensorflow.python.ops.nn_grad # pylint: disable=unused-import from tensorflow.python.platform import test @@ -49,6 +50,7 @@ class SummaryV1ImageOpTest(test.TestCase): }""" % ((i,) + shape[1:]) for i in xrange(3)) self.assertProtoEquals(expected, image_summ) + @test_util.run_deprecated_v1 def testImageSummary(self): for depth in (1, 3, 4): for positive in False, True: @@ -70,7 +72,7 @@ class SummaryV1ImageOpTest(test.TestCase): # Summarize summ = summary.image("img", const) - value = sess.run(summ) + value = self.evaluate(summ) self.assertEqual([], summ.get_shape()) image_summ = self._AsSummary(value) @@ -84,6 +86,7 @@ class SummaryV1ImageOpTest(test.TestCase): # Check the rest of the proto self._CheckProto(image_summ, shape) + @test_util.run_deprecated_v1 def testImageSummaryUint8(self): np.random.seed(7) for depth in (1, 3, 4): @@ -97,7 +100,7 @@ class SummaryV1ImageOpTest(test.TestCase): # Summarize summ = summary.image("img", tf_images) - value = sess.run(summ) + value = self.evaluate(summ) self.assertEqual([], summ.get_shape()) image_summ = self._AsSummary(value) diff --git a/tensorflow/python/kernel_tests/summary_v1_ops_test.py b/tensorflow/python/kernel_tests/summary_v1_ops_test.py index 6c4e106b11..e070f5bf6f 100644 --- a/tensorflow/python/kernel_tests/summary_v1_ops_test.py +++ b/tensorflow/python/kernel_tests/summary_v1_ops_test.py @@ -26,6 +26,7 @@ from __future__ import print_function from tensorflow.core.framework import summary_pb2 from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import logging_ops from tensorflow.python.platform import test from tensorflow.python.summary import summary @@ -42,7 +43,7 @@ class SummaryV1OpsTest(test.TestCase): with self.cached_session() as sess: const = constant_op.constant([10.0, 20.0]) summ = logging_ops.scalar_summary(["c1", "c2"], const, name="mysumm") - value = sess.run(summ) + value = self.evaluate(summ) self.assertEqual([], summ.get_shape()) self.assertProtoEquals(""" value { tag: "c1" simple_value: 10.0 } @@ -53,20 +54,21 @@ class SummaryV1OpsTest(test.TestCase): with self.cached_session() as sess: const = constant_op.constant([10.0, 20.0]) summ = logging_ops.scalar_summary(["c1", "c2"], const) - value = sess.run(summ) + value = self.evaluate(summ) self.assertEqual([], summ.get_shape()) self.assertProtoEquals(""" value { tag: "c1" simple_value: 10.0 } value { tag: "c2" simple_value: 20.0 } """, self._AsSummary(value)) + @test_util.run_deprecated_v1 def testMergeSummary(self): with self.cached_session() as sess: const = constant_op.constant(10.0) summ1 = summary.histogram("h", const) summ2 = logging_ops.scalar_summary("c", const) merge = summary.merge([summ1, summ2]) - value = sess.run(merge) + value = self.evaluate(merge) self.assertEqual([], merge.get_shape()) self.assertProtoEquals(""" value { diff --git a/tensorflow/python/kernel_tests/summary_v1_tensor_op_test.py b/tensorflow/python/kernel_tests/summary_v1_tensor_op_test.py index 34f771679a..b8e5b5b882 100644 --- a/tensorflow/python/kernel_tests/summary_v1_tensor_op_test.py +++ b/tensorflow/python/kernel_tests/summary_v1_tensor_op_test.py @@ -50,7 +50,7 @@ class SummaryV1TensorOpTest(test.TestCase): with ops.name_scope("zod"): s3 = summary_lib.tensor_summary("s3", c) s4 = summary_lib.tensor_summary("TensorSummary", c) - summ1, summ2, summ3, summ4 = sess.run([s1, s2, s3, s4]) + summ1, summ2, summ3, summ4 = self.evaluate([s1, s2, s3, s4]) v1 = self._SummarySingleValue(summ1) self.assertEqual(v1.tag, "s1") @@ -68,7 +68,7 @@ class SummaryV1TensorOpTest(test.TestCase): with self.cached_session() as sess: const = constant_op.constant(10.0) summ = summary_lib.tensor_summary("foo", const) - result = sess.run(summ) + result = self.evaluate(summ) value = self._SummarySingleValue(result) n = tensor_util.MakeNdarray(value.tensor) @@ -79,7 +79,7 @@ class SummaryV1TensorOpTest(test.TestCase): with self.cached_session() as sess: const = constant_op.constant(s) summ = summary_lib.tensor_summary("foo", const) - result = sess.run(summ) + result = self.evaluate(summ) value = self._SummarySingleValue(result) n = tensor_util.MakeNdarray(value.tensor) @@ -89,7 +89,7 @@ class SummaryV1TensorOpTest(test.TestCase): with self.cached_session() as sess: const = array_ops.ones([5, 5, 5]) summ = summary_lib.tensor_summary("foo", const) - result = sess.run(summ) + result = self.evaluate(summ) value = self._SummarySingleValue(result) n = tensor_util.MakeNdarray(value.tensor) self._AssertNumpyEq(n, np.ones([5, 5, 5])) @@ -99,7 +99,7 @@ class SummaryV1TensorOpTest(test.TestCase): with self.cached_session() as sess: const = constant_op.constant(strings) summ = summary_lib.tensor_summary("foo", const) - result = sess.run(summ) + result = self.evaluate(summ) value = self._SummarySingleValue(result) n = tensor_util.MakeNdarray(value.tensor) self._AssertNumpyEq(n, strings) @@ -109,7 +109,7 @@ class SummaryV1TensorOpTest(test.TestCase): with self.cached_session() as sess: const = constant_op.constant(bools) summ = summary_lib.tensor_summary("foo", const) - result = sess.run(summ) + result = self.evaluate(summ) value = self._SummarySingleValue(result) n = tensor_util.MakeNdarray(value.tensor) @@ -119,7 +119,7 @@ class SummaryV1TensorOpTest(test.TestCase): with self.cached_session() as sess: def get_description(summary_op): - summ_str = sess.run(summary_op) + summ_str = self.evaluate(summary_op) summ = summary_pb2.Summary() summ.ParseFromString(summ_str) return summ.value[0].metadata diff --git a/tensorflow/python/kernel_tests/svd_op_test.py b/tensorflow/python/kernel_tests/svd_op_test.py index 57298c0fec..97a280ef51 100644 --- a/tensorflow/python/kernel_tests/svd_op_test.py +++ b/tensorflow/python/kernel_tests/svd_op_test.py @@ -68,7 +68,7 @@ class SvdOpTest(test.TestCase): s2 = linalg_ops.svd( matrix2, compute_uv=compute_uv_, full_matrices=full_matrices_) all_ops += [s1, s2] - val = sess.run(all_ops) + val = self.evaluate(all_ops) for i in range(2): s = 6 * i self.assertAllEqual(val[s], val[s + 3]) # s1 == s2 @@ -123,7 +123,7 @@ def _GetSvdOpTest(dtype_, shape_, use_static_shape_, compute_uv_, # Tests that x[...,:,:]^H * x[...,:,:] is close to the identity. xx = math_ops.matmul(x, x, adjoint_a=True) identity = array_ops.matrix_band_part(array_ops.ones_like(xx), 0, 0) - self.assertAllClose(identity.eval(), xx.eval(), atol=tol) + self.assertAllClose(identity.eval(), self.evaluate(xx), atol=tol) def Test(self): is_complex = dtype_ in (np.complex64, np.complex128) @@ -150,7 +150,7 @@ def _GetSvdOpTest(dtype_, shape_, use_static_shape_, compute_uv_, s_tf, u_tf, v_tf = linalg_ops.svd( x_tf, compute_uv=compute_uv_, full_matrices=full_matrices_) if use_static_shape_: - s_tf_val, u_tf_val, v_tf_val = sess.run([s_tf, u_tf, v_tf]) + s_tf_val, u_tf_val, v_tf_val = self.evaluate([s_tf, u_tf, v_tf]) else: s_tf_val, u_tf_val, v_tf_val = sess.run( [s_tf, u_tf, v_tf], feed_dict={x_tf: x_np}) @@ -158,7 +158,7 @@ def _GetSvdOpTest(dtype_, shape_, use_static_shape_, compute_uv_, s_tf = linalg_ops.svd( x_tf, compute_uv=compute_uv_, full_matrices=full_matrices_) if use_static_shape_: - s_tf_val = sess.run(s_tf) + s_tf_val = self.evaluate(s_tf) else: s_tf_val = sess.run(s_tf, feed_dict={x_tf: x_np}) diff --git a/tensorflow/python/kernel_tests/template_test.py b/tensorflow/python/kernel_tests/template_test.py index 9dcdaa61ed..3b2a56bd1f 100644 --- a/tensorflow/python/kernel_tests/template_test.py +++ b/tensorflow/python/kernel_tests/template_test.py @@ -72,6 +72,7 @@ def variable_scoped_function_with_local_variable(): class TemplateTest(test.TestCase): + @test_util.run_deprecated_v1 def test_end_to_end(self): """This test shows a very simple line model with test_loss. @@ -104,10 +105,10 @@ class TemplateTest(test.TestCase): train_op = optimizer.minimize(train_loss) with session.Session() as sess: - sess.run(variables.global_variables_initializer()) - initial_test_loss = sess.run(test_loss) - sess.run(train_op) - final_test_loss = sess.run(test_loss) + self.evaluate(variables.global_variables_initializer()) + initial_test_loss = self.evaluate(test_loss) + self.evaluate(train_op) + final_test_loss = self.evaluate(test_loss) # Parameters are tied, so the loss should have gone down when we trained it. self.assertLess(final_test_loss, initial_test_loss) @@ -172,6 +173,7 @@ class TemplateTest(test.TestCase): self.assertEqual("s1/dummy:0", v1.name) self.assertEqual("s1_1/dummy:0", v3.name) + @test_util.run_deprecated_v1 def test_same_unique_name_raise_error(self): tmpl1 = template.make_template( "_", variable_scoped_function, unique_name_="s1") @@ -190,6 +192,7 @@ class TemplateTest(test.TestCase): template.make_template( "_", variable_scoped_function, unique_name_="s1") + @test_util.run_deprecated_v1 def test_unique_name_and_reuse(self): tmpl1 = template.make_template( "_", variable_scoped_function, unique_name_="s1") @@ -260,6 +263,7 @@ class TemplateTest(test.TestCase): self.assertEqual("s1/test/dummy:0", v1.name) self.assertEqual("s1_1/test/dummy:0", v3.name) + @test_util.run_deprecated_v1 def test_enforces_no_extra_trainable_variables(self): tmpl = template.make_template("s", function_with_create, trainable=True) @@ -675,6 +679,7 @@ class TemplateTest(test.TestCase): self.assertEqual(1, len(tb.variables)) # TODO(apassos) handle local variables in Eager + @test_util.run_deprecated_v1 def test_local_variables(self): # Make sure trainable_variables are created. with variable_scope.variable_scope("foo3"): diff --git a/tensorflow/python/kernel_tests/tensor_array_ops_test.py b/tensorflow/python/kernel_tests/tensor_array_ops_test.py index 0188eb246f..884c04eb7a 100644 --- a/tensorflow/python/kernel_tests/tensor_array_ops_test.py +++ b/tensorflow/python/kernel_tests/tensor_array_ops_test.py @@ -63,6 +63,8 @@ def _make_ta(size, name, dtype=dtypes.float32, infer_shape=False): dtype=dtype, tensor_array_name=name, size=size, infer_shape=infer_shape) +@test_util.run_all_in_graph_and_eager_modes +@test_util.with_control_flow_v2 class TensorArrayTest(test.TestCase): @classmethod @@ -123,11 +125,9 @@ class TensorArrayTest(test.TestCase): self._testTensorArrayWritePack(dtypes.complex128) self._testTensorArrayWritePack(dtypes.string) - @test_util.run_in_graph_and_eager_modes def testTensorArrayWritePack(self): self._testTensorArrayWritePackMaybeLegacy() - @test_util.run_in_graph_and_eager_modes def testEmptyTensorArrayPack(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( @@ -161,7 +161,7 @@ class TensorArrayTest(test.TestCase): convert([[4.0, 5.0], [104.0, 105.0], [204.0, 205.0], [6.0, 7.0], [106.0, 107.0], [8.0, 9.0]]), c0) - @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testTensorArrayWriteConcat(self): self._testTensorArrayWriteConcat(dtypes.float32) self._testTensorArrayWriteConcat(dtypes.float64) @@ -184,7 +184,8 @@ class TensorArrayTest(test.TestCase): self.assertAllEqual([[0.0, 0.0], [4.0, 5.0], [0.0, 0.0]], self.evaluate(ta.write(1, [[4.0, 5.0]]).concat())) - @test_util.run_in_graph_and_eager_modes + @test_util.disable_control_flow_v2("b/118890905") + @test_util.run_v1_only("b/118890905") def testTensorArrayReadOrPackNotAllValuesAvailableFillsZeros(self): self._testTensorArrayReadOrPackNotAllValuesAvailableFillsZeros() @@ -200,7 +201,8 @@ class TensorArrayTest(test.TestCase): self.assertAllEqual([[0.0, 0.0], [4.0, 5.0], [0.0, 0.0]], self.evaluate(ta.write(1, [[4.0, 5.0]]).concat())) - @test_util.run_in_graph_and_eager_modes + @test_util.disable_control_flow_v2("b/118890905") + @test_util.run_v1_only("b/118890905") def testTensorArrayReadOrPackNotAllValuesAvailableInferShapeFillsZeros(self): self._testTensorArrayReadOrPackNotAllValuesAvailableInferShapeFillsZeros() @@ -251,7 +253,6 @@ class TensorArrayTest(test.TestCase): self._testTensorArrayUnpackRead(dtypes.complex128) self._testTensorArrayUnpackRead(dtypes.string) - @test_util.run_in_graph_and_eager_modes def testTensorArrayUnpackRead(self): self._testTensorArrayUnpackReadMaybeLegacy() @@ -297,7 +298,7 @@ class TensorArrayTest(test.TestCase): self.assertAllEqual(convert([]).reshape(0, 2), d1) self.assertAllEqual(convert([[3.0, 301.0]]), d2) - @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testTensorArraySplitRead(self): self._testTensorArraySplitRead(dtypes.float32) self._testTensorArraySplitRead(dtypes.float64) @@ -307,7 +308,9 @@ class TensorArrayTest(test.TestCase): self._testTensorArraySplitRead(dtypes.complex128) self._testTensorArraySplitRead(dtypes.string) - def testTensorGradArrayWriteRead(self): + @test_util.disable_control_flow_v2("v2 does not support TensorArray.grad.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorGradArrayWriteRead(self): with self.session(use_gpu=True) as session: ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, @@ -340,7 +343,29 @@ class TensorArrayTest(test.TestCase): self.assertAllEqual([[2.0]], g_d1) self.assertAllEqual(-2.0, g_d2) - def testTensorGradArrayDynamicWriteRead(self): + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGradGrad(self): + if not tensor_array_ops.ENABLE_TENSOR_ARRAY_V2: + self.skipTest("Legacy TensorArray does not support double derivatives.") + with self.test_session(use_gpu=True) as session: + x = constant_op.constant(4.0) + + ta = tensor_array_ops.TensorArray( + dtype=dtypes.float32, + tensor_array_name="foo", + size=1, + infer_shape=False) + w0 = ta.write(0, x) + r0 = w0.read(0) + y = r0 * r0 + + g1 = gradients_impl.gradients(ys=[y], xs=[x]) + g2 = gradients_impl.gradients(ys=[g1], xs=[x]) + self.assertAllEqual([2.0], session.run(g2)) + + @test_util.disable_control_flow_v2("v2 does not support TensorArray.grad.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorGradArrayDynamicWriteRead(self): with self.session(use_gpu=True) as session: ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, @@ -381,7 +406,9 @@ class TensorArrayTest(test.TestCase): self.assertAllEqual(3, vs) self.assertAllEqual(3, g_vs) - def testTensorGradAccessTwiceReceiveSameObject(self): + @test_util.disable_control_flow_v2("v2 does not support TensorArray.grad.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorGradAccessTwiceReceiveSameObject(self): with self.session(use_gpu=True) as session: ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, tensor_array_name="foo", size=3) @@ -397,26 +424,41 @@ class TensorArrayTest(test.TestCase): self.assertAllEqual(t_g_ta_0, t_g_ta_1) self.assertAllEqual([[4.0, 5.0]], d_r1_0) - @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testTensorArrayWriteWrongIndexOrDataTypeFails(self): with self.session(use_gpu=True): ta = _make_ta(3, "foo", dtype=dtypes.float32) # Test writing the wrong datatype - with self.assertRaisesOpError( - "TensorArray dtype is (float|float32) but Op is trying to write " - "dtype string"): + if (tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 and + not context.executing_eagerly()): + error_msg = ("Invalid data types; op elements string but list elements " + "float") + else: + error_msg = ( + "TensorArray dtype is (float|float32) but Op is trying to write " + "dtype string") + with self.assertRaisesOpError(error_msg): self.evaluate(ta.write(0, "wrong_type_scalar").flow) - with self.assertRaisesOpError("index -1"): + if (tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 and + not context.executing_eagerly()): + error_msg = "Trying to modify element -1 in a list with 3 elements." + else: + error_msg = "index -1" + with self.assertRaisesOpError(error_msg): self.evaluate(ta.write(-1, 3.0).flow) + if (tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 and + not context.executing_eagerly()): + error_msg = "Trying to modify element 3 in a list with 3 elements" + else: + error_msg = ("Tried to write to index 3 but array is not " + "resizeable and size is: 3") # Test reading from too large an index - with self.assertRaisesOpError( - "Tried to write to index 3 but array is not " - "resizeable and size is: 3"): + with self.assertRaisesOpError(error_msg): self.evaluate(ta.write(3, 3.0).flow) - @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testTensorArrayReadWrongIndexOrDataTypeFails(self): with self.session(use_gpu=True): ta = _make_ta(3, "foo", dtype=dtypes.float32) @@ -424,23 +466,35 @@ class TensorArrayTest(test.TestCase): w0 = ta.write(0, [[4.0, 5.0]]) # Test reading wrong datatype (only possible when constructing graphs). - if not context.executing_eagerly(): + if (not context.executing_eagerly() and + not tensor_array_ops.ENABLE_TENSOR_ARRAY_V2): r0_bad = gen_data_flow_ops.tensor_array_read_v3( handle=w0.handle, index=0, dtype=dtypes.float64, flow_in=w0.flow) with self.assertRaisesOpError( "TensorArray dtype is float but Op requested dtype double."): - r0_bad.eval() + self.evaluate(r0_bad) + if (tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 and + not context.executing_eagerly()): + error_msg = "Trying to access element -1 in a list with 3 elements." + else: + error_msg = "index -1" # Test reading from a negative index, which is not allowed - with self.assertRaisesOpError("index -1"): + with self.assertRaisesOpError(error_msg): self.evaluate(ta.read(-1)) + if (tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 and + not context.executing_eagerly()): + error_msg = "Trying to access element 3 in a list with 3 elements." + else: + error_msg = "Tried to read from index 3 but array size is: 3" # Test reading from too large an index - with self.assertRaisesOpError( - "Tried to read from index 3 but array size is: 3"): + with self.assertRaisesOpError(error_msg): self.evaluate(ta.read(3)) - def testTensorArrayWriteMultipleFails(self): + @test_util.disable_control_flow_v2("v2 allows multiple writes.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayWriteMultipleFails(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, tensor_array_name="foo", size=3) @@ -450,7 +504,7 @@ class TensorArrayTest(test.TestCase): "it has already been written to."): self.evaluate(ta.write(2, 3.0).write(2, 3.0).flow) - @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testTensorArrayConcatIncompatibleShapesFails(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( @@ -482,7 +536,7 @@ class TensorArrayTest(test.TestCase): with self.assertRaisesOpError("shape"): self.evaluate(w3.concat()) - @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testTensorArraySplitIncompatibleShapesFails(self): with self.session(use_gpu=True): in_eager_mode = context.executing_eagerly() @@ -495,22 +549,32 @@ class TensorArrayTest(test.TestCase): lengths = array_ops.placeholder(dtypes.int64) ta.split([1.0, 2.0, 3.0], lengths).flow.eval(feed_dict={lengths: 1}) - with self.assertRaisesOpError( - r"Expected sum of lengths to be equal to values.shape\[0\], " - r"but sum of lengths is 1 and value's shape is: \[3\]"): + error_msg = ("Unused values in tensor. Length of tensor: 3 Values used: 1" + if tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 and + not in_eager_mode else + r"Expected sum of lengths to be equal to values.shape\[0\], " + r"but sum of lengths is 1 and value's shape is: \[3\]") + with self.assertRaisesOpError(error_msg): self.evaluate(ta.split([1.0, 2.0, 3.0], [1]).flow) ta = _make_ta(1, "baz") - with self.assertRaisesOpError( - r"Expected value to be at least a vector, but received shape: \[\]"): - self.evaluate(ta.split(1.0, [1]).flow) + if tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 and not in_eager_mode: + with self.assertRaisesRegexp( + ValueError, "Shape must be at least rank 1 but is rank 0"): + self.evaluate(ta.split(1.0, [1]).flow) + else: + with self.assertRaisesOpError( + r"Expected value to be at least a vector, but received shape: \[\]" + ): + self.evaluate(ta.split(1.0, [1]).flow) - ta = _make_ta(2, "buz") - with self.assertRaisesOpError( - r"TensorArray's size is not equal to the size of lengths " - r"\(2 vs. 1\), and the TensorArray is not marked as " - r"dynamically resizeable"): - self.evaluate(ta.split([1.0], [1]).flow) + if not tensor_array_ops.ENABLE_TENSOR_ARRAY_V2 or in_eager_mode: + ta = _make_ta(2, "buz") + with self.assertRaisesOpError( + r"TensorArray's size is not equal to the size of lengths " + r"\(2 vs. 1\), and the TensorArray is not marked as " + r"dynamically resizeable"): + self.evaluate(ta.split([1.0], [1]).flow) def _testTensorArrayWriteGradientAddMultipleAdds(self, dtype): with self.cached_session(use_gpu=True): @@ -546,12 +610,16 @@ class TensorArrayTest(test.TestCase): r"existing shape is \[\] but the new input shape is \[1\]"): wb1_grad.flow.eval() - def testTensorArrayWriteGradientAddMultipleAdds(self): + @test_util.disable_control_flow_v2("v2 does not support TensorArray.grad.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayWriteGradientAddMultipleAdds(self): for dtype in (dtypes.int32, dtypes.int64, dtypes.float32, dtypes.float64, dtypes.complex64, dtypes.complex128): self._testTensorArrayWriteGradientAddMultipleAdds(dtype) - def testTensorArrayGradWithShapeKnownElementShape(self): + @test_util.disable_control_flow_v2("Low level legacy TA op test.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGradWithShapeKnownElementShape(self): with self.session(use_gpu=True) as sess: ta = tensor_array_ops.TensorArray( size=3, @@ -580,7 +648,9 @@ class TensorArrayTest(test.TestCase): self.assertAllClose(fed_value, sess.run(read_value, feed_dict={value: fed_value})) - def testTensorArrayGradWithShapeUnknownElementShape(self): + @test_util.disable_control_flow_v2("Low level legacy TA op test.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGradWithShapeUnknownElementShape(self): with self.session(use_gpu=True) as sess: ta = tensor_array_ops.TensorArray( size=3, dtype=dtypes.float32, @@ -603,7 +673,6 @@ class TensorArrayTest(test.TestCase): self.assertAllClose(fed_value, sess.run(read_value, feed_dict={value: fed_value})) - @test_util.run_in_graph_and_eager_modes def testMultiTensorArray(self): with self.session(use_gpu=True): h1 = tensor_array_ops.TensorArray( @@ -667,7 +736,8 @@ class TensorArrayTest(test.TestCase): self.assertAllEqual(c([[3.0, 2.0]]), grad_vals[0]) self.assertAllEqual(c(-2.0), grad_vals[1]) - def testTensorArrayGradientWriteRead(self): + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGradientWriteRead(self): for dtype in (np.float32, np.float64, np.complex64, np.complex128): self._testTensorArrayGradientWriteReadType(dtype) @@ -698,15 +768,17 @@ class TensorArrayTest(test.TestCase): [-0.5, 1.5], # read(0) gradient [20.0, 30.0, 40.0, 50.0] ]) # concat gradient - grad_vals = sess.run(grad_r) # 2 + 2 entries + grad_vals = self.evaluate(grad_r) # 2 + 2 entries self.assertAllClose([2.0 - 0.5 + 20.0, 3.0 + 1.5 + 30.0], grad_vals[0]) self.assertAllEqual([4.0 + 40.0, 5.0 + 50.0], grad_vals[1]) - def testTensorArrayGradientWritePackConcatAndRead(self): + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGradientWritePackConcatAndRead(self): self._testTensorArrayGradientWritePackConcatAndRead() - @test_util.run_in_graph_and_eager_modes + @test_util.disable_control_flow_v2("v2 does not support clear_after_read.") + @test_util.run_deprecated_v1 def testTensorArrayReadTwice(self): with self.session(use_gpu=True): value = constant_op.constant([[1.0, -1.0], [10.0, -10.0]]) @@ -760,10 +832,12 @@ class TensorArrayTest(test.TestCase): self.assertEqual(len(grad_vals), 1) self.assertAllEqual([[2.0 - 1.5, 3.0 + 1.5], [4.0, 5.0]], grad_vals[0]) - def testTensorArrayGradientUnpackRead(self): + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGradientUnpackRead(self): self._testTensorArrayGradientUnpackRead() - def testTensorArrayGradientSplitConcat(self): + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGradientSplitConcat(self): with self.session(use_gpu=True) as session: ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, tensor_array_name="foo", size=2, @@ -808,17 +882,16 @@ class TensorArrayTest(test.TestCase): self.assertEqual(len(grad_vals), 1) self.assertAllEqual([[2.0, 3.0], [4.0, 5.0]], grad_vals[0]) - def testTensorArrayGradientDynamicUnpackRead(self): + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGradientDynamicUnpackRead(self): self._testTensorArrayGradientDynamicUnpackRead() - @test_util.run_in_graph_and_eager_modes def testCloseTensorArray(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, tensor_array_name="foo", size=3) self.evaluate(ta.close()) - @test_util.run_in_graph_and_eager_modes def testSizeTensorArray(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( @@ -826,7 +899,6 @@ class TensorArrayTest(test.TestCase): s = ta.size() self.assertAllEqual(3, self.evaluate(s)) - @test_util.run_in_graph_and_eager_modes def testWriteCloseTensorArray(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( @@ -924,7 +996,6 @@ class TensorArrayTest(test.TestCase): self.assertAllClose(grad_val.sum(axis=0), var_grad_t) self.assertAllClose(grad_val.sum(axis=0), state0_grad_t) - @test_util.run_in_graph_and_eager_modes def testWhileLoopWritePackGradients(self): self._testWhileLoopWritePackGradients( dynamic_size=False, dtype=dtypes.float32) @@ -932,11 +1003,28 @@ class TensorArrayTest(test.TestCase): # self._testWhileLoopWritePackGradients( # dynamic_size=False, dtype=tf.int64) - def testWhileLoopDynamicWritePackGradients(self): + @test_util.disable_control_flow_v2("Testing v1 while_loop with v2 TA") + @test_util.enable_tensor_array_v2 + def testWhileLoopV1WithTensorArrayV2(self): + size = 3 + ta = tensor_array_ops.TensorArray( + dtype=dtypes.int32, size=size, element_shape=tensor_shape.scalar()) + + def Body(counter, ta): + return counter + 1, ta.write(counter, counter) + + _, ta = control_flow_ops.while_loop(lambda i, _: i < size, Body, [0, ta]) + + for i in range(size): + self.assertEqual(self.evaluate(ta.read(i)), i) + + @test_util.disable_control_flow_v2("b/117943489 (dynamic_size)") + @test_util.run_v1_only("b/117943489") + def testSkipEagerWhileLoopDynamicWritePackGradients(self): self._testWhileLoopWritePackGradients( dynamic_size=True, dtype=dtypes.float32) - @test_util.run_in_graph_and_eager_modes + @test_util.disable_control_flow_v2("b/119323158") def testGradSerialTwoLoops(self): with self.session(use_gpu=True): def loop(x): @@ -976,7 +1064,8 @@ class TensorArrayTest(test.TestCase): grad = gradients_impl.gradients(loop(x), [x])[0] self.assertAllClose(31.0, self.evaluate(grad)) - def testSumOfTwoReadVariablesWithoutRepeatGrad(self): + @test_util.run_deprecated_v1 + def testSkipEagerSumOfTwoReadVariablesWithoutRepeatGrad(self): with self.session(use_gpu=True) as session: a = array_ops.identity( np.arange( @@ -1011,7 +1100,8 @@ class TensorArrayTest(test.TestCase): def _grad_source_for_name(self, name): return tensor_array_grad._GetGradSource(constant_op.constant(0, name=name)) - def testGetGradSource_Invalid(self): + @test_util.run_deprecated_v1 + def testSkipEagerGetGradSource_Invalid(self): with self.assertRaises(ValueError): self._grad_source_for_name("") with self.assertRaises(ValueError): @@ -1019,7 +1109,8 @@ class TensorArrayTest(test.TestCase): with self.assertRaises(ValueError): self._grad_source_for_name("foo/bar") - def testGetGradSource_NoEnclosingScope(self): + @test_util.run_deprecated_v1 + def testSkipEagerGetGradSource_NoEnclosingScope(self): self.assertEqual("gradients:0", self._grad_source_for_name("gradients")) self.assertEqual("gradients_0:0", self._grad_source_for_name("gradients_0")) self.assertEqual("gradients", self._grad_source_for_name("gradients/foo")) @@ -1030,7 +1121,8 @@ class TensorArrayTest(test.TestCase): self.assertEqual("gradients_0", self._grad_source_for_name("gradients_0/foo/bar")) - def testGetGradSource_EnclosingScope(self): + @test_util.run_deprecated_v1 + def testSkipEagerGetGradSource_EnclosingScope(self): self.assertEqual("foo/gradients:0", self._grad_source_for_name("foo/gradients")) self.assertEqual("foo/gradients_0:0", @@ -1044,12 +1136,14 @@ class TensorArrayTest(test.TestCase): self.assertEqual("foo/bar/gradients_0", self._grad_source_for_name("foo/bar/gradients_0/baz")) - def testGetGradSource_NestedUsesInnermost(self): + @test_util.run_deprecated_v1 + def testSkipEagerGetGradSource_NestedUsesInnermost(self): self.assertEqual( "foo/gradients/bar/gradients_0", self._grad_source_for_name("foo/gradients/bar/gradients_0/baz")) - def testWriteShape(self): + @test_util.run_deprecated_v1 + def testSkipEagerWriteShape(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, tensor_array_name="foo", size=3) @@ -1073,7 +1167,8 @@ class TensorArrayTest(test.TestCase): with self.assertRaises(ValueError): w0.write(0, c2) - def testPartlyUnknownShape(self): + @test_util.run_deprecated_v1 + def testSkipEagerPartlyUnknownShape(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, tensor_array_name="foo", size=6) @@ -1113,7 +1208,6 @@ class TensorArrayTest(test.TestCase): r5 = w5.read(0) self.assertAllEqual([5, 4, 2, 3], r5.get_shape().as_list()) - @test_util.run_in_graph_and_eager_modes def _testUnpackShape(self): with self.cached_session(use_gpu=True): ta = tensor_array_ops.TensorArray( @@ -1144,10 +1238,12 @@ class TensorArrayTest(test.TestCase): with self.assertRaises(ValueError): w1.write(4, c2) + @test_util.disable_control_flow_v2("b/117943489 (dynamic_size)") + @test_util.run_v1_only("b/117943489") def testUnpackShape(self): self._testUnpackShape() - @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testSplitShape(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( @@ -1174,11 +1270,13 @@ class TensorArrayTest(test.TestCase): self.assertEqual((2, 2), w0.read(1).get_shape()) else: self.assertEqual(r0.get_shape().ndims, None) - self.assertEqual( - tensor_shape.TensorShape( - ta1.handle.op.get_attr("element_shape")).ndims, None) + if not tensor_array_ops.ENABLE_TENSOR_ARRAY_V2: + self.assertEqual( + tensor_shape.TensorShape( + ta1.handle.op.get_attr("element_shape")).ndims, None) - def testWriteUnknownShape(self): + @test_util.run_deprecated_v1 + def testSkipEagerWriteUnknownShape(self): with self.session(use_gpu=True): ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, @@ -1201,7 +1299,11 @@ class TensorArrayTest(test.TestCase): grad_r0_vals = session.run(grad_r0)[0] self.assertAllEqual(grad_r0_vals, [1.0, 0.0]) - def testGradientWhenNotAllComponentsRead(self): + # TODO(srbs): Figure out how to enable this. This is probably failing + # because we are trying to stack a TensorList with invalid tensors. + # That is because we do not receive gradients for all list indices. + # Figure out how TensorArray handles this. + def disabletestGradientWhenNotAllComponentsRead(self): self._testGradientWhenNotAllComponentsRead() def _testTensorArrayUnpackDynamic(self): @@ -1212,14 +1314,18 @@ class TensorArrayTest(test.TestCase): w0 = ta.unstack(x) w1 = w0.write(3, 4.0) r = w1.stack() - self.assertAllEqual(np.array([1.0, 2.0, 3.0, 4.0]), r.eval()) + self.assertAllEqual(np.array([1.0, 2.0, 3.0, 4.0]), self.evaluate(r)) grad = gradients_impl.gradients(ys=[r], xs=[x]) - self.assertAllEqual(np.array([1.0, 1.0, 1.0]), sess.run(grad)[0]) + self.assertAllEqual(np.array([1.0, 1.0, 1.0]), self.evaluate(grad)[0]) - def testTensorArrayUnpackDynamic(self): + @test_util.disable_control_flow_v2("b/117943489") + @test_util.run_v1_only("b/117943489") + def testSkipEagerTensorArrayUnpackDynamic(self): self._testTensorArrayUnpackDynamic() - def testTensorArraySplitDynamic(self): + @test_util.disable_control_flow_v2("b/117943489") + @test_util.run_v1_only("b/117943489") + def testSkipEagerTensorArraySplitDynamic(self): with self.session(use_gpu=True) as sess: ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, size=3, dynamic_size=True) @@ -1227,21 +1333,26 @@ class TensorArrayTest(test.TestCase): w0 = ta.split(x, [1, 1, 1]) w1 = w0.write(3, [4.0]) r = w1.concat() - self.assertAllEqual(np.array([1.0, 2.0, 3.0, 4.0]), r.eval()) + self.assertAllEqual(np.array([1.0, 2.0, 3.0, 4.0]), self.evaluate(r)) grad = gradients_impl.gradients(ys=[r], xs=[x]) - self.assertAllEqual(np.array([1.0, 1.0, 1.0]), sess.run(grad)[0]) + self.assertAllEqual(np.array([1.0, 1.0, 1.0]), self.evaluate(grad)[0]) def _testTensorArrayEvalEmpty(self): with self.cached_session(use_gpu=True): ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, size=0, dynamic_size=False, infer_shape=False) - with self.assertRaisesOpError( - "TensorArray has size zero, but element shape is not fully " - "defined. Currently only static shapes are supported when packing " - "zero-size TensorArrays."): + v2_msg = ("Tried to stack elements of a empty list with " + "non-fully-defined shape") + v1_msg = ( + "TensorArray has size zero, but element shape is not " + "fully defined. Currently only static shapes are supported when " + "packing zero-size TensorArrays.") + with self.assertRaisesOpError(v2_msg if tensor_array_ops + .ENABLE_TENSOR_ARRAY_V2 else v1_msg): ta.stack().eval() - def testTensorArrayEvalEmpty(self): + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayEvalEmpty(self): self._testTensorArrayEvalEmpty() # this test is ill-defined for Eager mode --- unpacking an empty tensor @@ -1255,15 +1366,19 @@ class TensorArrayTest(test.TestCase): ta.unstack(array_ops.zeros([0, 3, 5])).mark_used() packed = ta.stack() concatenated = ta.concat() - self.assertAllEqual([0, 3, 5], packed.eval().shape) + self.assertAllEqual([0, 3, 5], self.evaluate(packed).shape) # Concatenating zero tensors along their first dimension gives a # first dimension of zero - self.assertAllEqual([0, 5], concatenated.eval().shape) + self.assertAllEqual([0, 5], self.evaluate(concatenated).shape) - def testTensorArrayEvalEmptyWithDefault(self): + @test_util.disable_control_flow_v2("b/117943489") + @test_util.run_v1_only("b/117943489") + def testSkipEagerTensorArrayEvalEmptyWithDefault(self): self._testTensorArrayEvalEmptyWithDefault() - def testTensorArrayScatterReadAndGradients(self): + @test_util.disable_control_flow_v2("b/117943489") + @test_util.run_v1_only("b/117943489") + def testSkipEagerTensorArrayScatterReadAndGradients(self): with self.session(use_gpu=True) as session: ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, @@ -1289,7 +1404,8 @@ class TensorArrayTest(test.TestCase): self.assertAllEqual([10.0, -10.0], read_vals[1]) self.assertAllEqual([[2.0, 3.0], [4.0, 5.0]], grad_vals[0]) - @test_util.run_in_graph_and_eager_modes + @test_util.disable_control_flow_v2("b/117943286") + @test_util.run_v1_only("b/117943286") def testTensorArrayWriteGatherAndGradients(self): with self.session(use_gpu=True) as session: ta = tensor_array_ops.TensorArray( @@ -1326,7 +1442,9 @@ class TensorArrayTest(test.TestCase): self.assertAllEqual([[1.0, -1.0], [8.0, -8.0]], g_vals[0]) self.assertAllEqual(expected_grad, grad_vals[0]) - def testTensorArrayGetsDeviceFromFirstWrite(self): + @test_util.disable_control_flow_v2("colocate_with not supported in v2.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGetsDeviceFromFirstWrite(self): with ops.device("/job:worker/task:0/cpu:0"): # this initial device will be ignored. ta = tensor_array_ops.TensorArray(dtype=dtypes.float32, size=2) @@ -1374,7 +1492,9 @@ class TensorArrayTest(test.TestCase): self.assertFalse( [s for s in dev_stats[d] if "/TensorArray" in s.node_name]) - def testTensorArrayGetsDeviceFromFirstWriteInWhileLoop(self): + @test_util.disable_control_flow_v2("colocate_with not supported in v2.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGetsDeviceFromFirstWriteInWhileLoop(self): with ops.device("/job:worker/task:0/cpu:0"): ta = tensor_array_ops.TensorArray(dtype=dtypes.float32, size=2) @@ -1403,7 +1523,9 @@ class TensorArrayTest(test.TestCase): self.assertFalse( [s for s in dev_stats[d] if "TensorArray" == s.node_name]) - def testTensorArrayDisabledColocateWithFirstWriteCall(self): + @test_util.disable_control_flow_v2("colocate_with not supported in v2.") + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayDisabledColocateWithFirstWriteCall(self): with ops.device("/job:worker/task:0/cpu:0"): ta = tensor_array_ops.TensorArray( dtype=dtypes.float32, size=2, colocate_with_first_write_call=False) @@ -1433,7 +1555,6 @@ class TensorArrayTest(test.TestCase): self.assertFalse( [s for s in dev_stats[d] if "TensorArray" == s.node_name]) - @test_util.run_in_graph_and_eager_modes def testTensorArrayIdentity(self): with self.session(use_gpu=True): ta0 = tensor_array_ops.TensorArray(dtype=dtypes.float32, size=2, @@ -1486,7 +1607,8 @@ class TensorArrayTest(test.TestCase): self.assertEqual(size0_v, 2) self.assertEqual(size1_v, 4) - def testTensorArrayGradYsInCorrectScope(self): + @test_util.run_deprecated_v1 + def testSkipEagerTensorArrayGradYsInCorrectScope(self): n_time = 1 n_dim = 1 x = constant_op.constant([[1.42]]) @@ -1501,10 +1623,10 @@ class TensorArrayTest(test.TestCase): # wrap it in the correct name scope. dx, = gradients_impl.gradients(ys=[y], xs=[x], grad_ys=[dy]) with self.cached_session(use_gpu=True) as sess: - vdx, vdy = sess.run([dx, dy]) + vdx, vdy = self.evaluate([dx, dy]) self.assertAllClose(vdx, vdy) - def testTensorArrayInt64GPU(self): + def testSkipEagerTensorArrayInt64GPU(self): if not test.is_gpu_available(): return with self.session(use_gpu=True, force_gpu=True) as sess: diff --git a/tensorflow/python/kernel_tests/topk_op_test.py b/tensorflow/python/kernel_tests/topk_op_test.py index d9f340de6b..5d46176bce 100644 --- a/tensorflow/python/kernel_tests/topk_op_test.py +++ b/tensorflow/python/kernel_tests/topk_op_test.py @@ -27,6 +27,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import nn_ops @@ -48,7 +49,7 @@ class TopKTest(test.TestCase): np_expected_indices = np.array(expected_indices) with self.cached_session(use_gpu=True) as sess: values_op, indices_op = nn_ops.top_k(inputs, k, sorted=sorted) - values, indices = sess.run([values_op, indices_op]) + values, indices = self.evaluate([values_op, indices_op]) self.assertShapeEqual(np_expected_values, values_op) self.assertShapeEqual(np_expected_indices, indices_op) @@ -181,6 +182,7 @@ class TopKTest(test.TestCase): k = constant_op.constant(3) self._validateTopK(inputs, k, [19, 18, 17], [11, 3, 7]) + @test_util.run_deprecated_v1 def testKNegative(self): inputs = [[0.1, 0.2], [0.3, 0.4]] with self.session(use_gpu=True): @@ -189,12 +191,14 @@ class TopKTest(test.TestCase): with self.assertRaisesOpError("Need k >= 0, got -7"): values.eval(feed_dict={k: -7}) + @test_util.run_deprecated_v1 def testKTooLarge(self): inputs = [[0.1, 0.2], [0.3, 0.4]] with self.assertRaisesRegexp(ValueError, r"must have last dimension >= k = 4"): nn_ops.top_k(inputs, 4) + @test_util.run_deprecated_v1 def testTopKGradients(self): with self.session(use_gpu=True) as sess: inputs = array_ops.placeholder(dtypes.float32, shape=[2, 5]) diff --git a/tensorflow/python/kernel_tests/trace_op_test.py b/tensorflow/python/kernel_tests/trace_op_test.py index f1abaefb66..52640c02c2 100644 --- a/tensorflow/python/kernel_tests/trace_op_test.py +++ b/tensorflow/python/kernel_tests/trace_op_test.py @@ -19,6 +19,7 @@ from __future__ import print_function import numpy as np +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -34,6 +35,7 @@ class TraceTest(test.TestCase): tf_ans = math_ops.trace(x).eval() self.assertAllClose(tf_ans, np_ans) + @test_util.run_deprecated_v1 def testTrace(self): for dtype in [np.int32, np.float32, np.float64]: for shape in [[2, 2], [2, 3], [3, 2], [2, 3, 2], [2, 2, 2, 3]]: diff --git a/tensorflow/python/kernel_tests/transpose_op_test.py b/tensorflow/python/kernel_tests/transpose_op_test.py index 8c11c20709..76e1002ee1 100644 --- a/tensorflow/python/kernel_tests/transpose_op_test.py +++ b/tensorflow/python/kernel_tests/transpose_op_test.py @@ -50,7 +50,7 @@ class TransposeTest(test.TestCase): with self.cached_session(use_gpu=False): inx = ops.convert_to_tensor(x) y = array_ops.transpose(inx, p, conjugate=conjugate) - tf_ans = y.eval() + tf_ans = self.evaluate(y) self.assertShapeEqual(np_ans, y) self.assertAllEqual(np_ans, tf_ans) @@ -81,7 +81,7 @@ class TransposeTest(test.TestCase): with self.cached_session(use_gpu=True): inx = ops.convert_to_tensor(x) y = array_ops.transpose(inx, p, conjugate=conjugate) - tf_ans = y.eval() + tf_ans = self.evaluate(y) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, y) @@ -168,7 +168,7 @@ class TransposeTest(test.TestCase): with self.cached_session(use_gpu=True): inx = ops.convert_to_tensor(inp) y = array_ops.transpose(inx, perm) - tf_ans = y.eval() + tf_ans = self.evaluate(y) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, y) @@ -189,7 +189,7 @@ class TransposeTest(test.TestCase): with self.cached_session(use_gpu=True): inx = ops.convert_to_tensor(inp) y = array_ops.transpose(inx, perm) - tf_ans = y.eval() + tf_ans = self.evaluate(y) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, y) @@ -224,7 +224,7 @@ class TransposeTest(test.TestCase): with self.cached_session(use_gpu=True): inx = ops.convert_to_tensor(inp) y = array_ops.transpose(inx, perm) - tf_ans = y.eval() + tf_ans = self.evaluate(y) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, y) @@ -246,7 +246,7 @@ class TransposeTest(test.TestCase): with self.cached_session(use_gpu=True): inx = ops.convert_to_tensor(inp) y = array_ops.transpose(inx, perm) - tf_ans = y.eval() + tf_ans = self.evaluate(y) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, y) @@ -267,7 +267,7 @@ class TransposeTest(test.TestCase): with self.cached_session(use_gpu=True): inx = ops.convert_to_tensor(inp) y = array_ops.transpose(inx, perm) - tf_ans = y.eval() + tf_ans = self.evaluate(y) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, y) @@ -319,7 +319,7 @@ class TransposeTest(test.TestCase): with self.cached_session(use_gpu=True): inx = ops.convert_to_tensor(inp) y = array_ops.transpose(inx, perm) - tf_ans = y.eval() + tf_ans = self.evaluate(y) self.assertAllEqual(np_ans, tf_ans) self.assertShapeEqual(np_ans, y) self._ClearCachedSession() @@ -341,7 +341,7 @@ class TransposeTest(test.TestCase): inx = ops.convert_to_tensor(x) inp = constant_op.constant(p) y = array_ops.transpose(inx, inp) - tf_ans = y.eval() + tf_ans = self.evaluate(y) self.assertShapeEqual(np_ans, y) self.assertAllEqual(np_ans, tf_ans) diff --git a/tensorflow/python/kernel_tests/unicode_decode_op_test.py b/tensorflow/python/kernel_tests/unicode_decode_op_test.py new file mode 100644 index 0000000000..c165021eea --- /dev/null +++ b/tensorflow/python/kernel_tests/unicode_decode_op_test.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for unicode_decode and unicode_decode_with_splits.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import errors_impl as errors +from tensorflow.python.framework import test_util +from tensorflow.python.ops import gen_string_ops +from tensorflow.python.platform import test + + +# Account for python2 and python3 execution of the test. +def codepoint(s): + if isinstance(s, bytes): + return ord(s.decode("utf-8")) + elif isinstance(s, str): + return ord(s) + + +class UnicodeDecodeTest(test.TestCase): + + def testBatchDecode(self): + text = constant_op.constant( + ["仅今年前", "分享介面終於迎來更新"]) + row_splits, utf8_text, offsets = gen_string_ops.unicode_decode_with_offsets( + text, "utf-8") + + with self.test_session(): + self.assertAllEqual([ + codepoint("仅"), + codepoint("今"), + codepoint("年"), + codepoint("前"), + codepoint("分"), + codepoint("享"), + codepoint("介"), + codepoint("面"), + codepoint("終"), + codepoint("於"), + codepoint("迎"), + codepoint("來"), + codepoint("更"), + codepoint("新") + ], + self.evaluate(utf8_text).tolist()) + self.assertAllEqual([0, 4, 14], self.evaluate(row_splits).tolist()) + self.assertAllEqual([0, 3, 6, 9, 0, 3, 6, 9, 12, 15, 18, 21, 24, 27], + self.evaluate(offsets).tolist()) + + def testBasicDecodeWithOffset(self): + text = constant_op.constant(["仅今年前"]) + row_splits, utf8_text, starts = gen_string_ops.unicode_decode_with_offsets( + text, "utf-8") + + with self.test_session(): + self.assertAllEqual([ + codepoint("仅"), + codepoint("今"), + codepoint("年"), + codepoint("前"), + ], + self.evaluate(utf8_text).tolist()) + self.assertAllEqual(self.evaluate(row_splits).tolist(), [0, 4]) + self.assertAllEqual(self.evaluate(starts).tolist(), [0, 3, 6, 9]) + + @test_util.run_deprecated_v1 + def testStrictError(self): + text = constant_op.constant([b"\xFEED"]) + _, error, _ = gen_string_ops.unicode_decode_with_offsets( + text, "utf-8", errors="strict") + + with self.assertRaises(errors.InvalidArgumentError): + with self.test_session(): + self.evaluate(error) + + def testReplaceOnError(self): + text = constant_op.constant([b"\xFE"]) + + _, utf8_text, _ = gen_string_ops.unicode_decode_with_offsets( + text, "utf-8", errors="replace") + + with self.test_session(): + self.assertAllEqual(self.evaluate(utf8_text).tolist(), [65533]) + + @test_util.run_deprecated_v1 + def testBadReplacementChar(self): + text = constant_op.constant([b"\xFE"]) + _, error, _ = gen_string_ops.unicode_decode_with_offsets( + text, "utf-8", errors="replace", replacement_char=11141111) + + with self.assertRaises(errors.InvalidArgumentError): + with self.test_session(): + self.evaluate(error) + + def testIgnoreOnError(self): + text = constant_op.constant([b"\xFEhello"]) + + _, utf8_text, _ = gen_string_ops.unicode_decode_with_offsets( + text, "utf-8", errors="ignore") + + with self.test_session(): + self.assertAllEqual(self.evaluate(utf8_text).tolist(), [ + codepoint("h"), + codepoint("e"), + codepoint("l"), + codepoint("l"), + codepoint("o") + ]) + + @test_util.run_deprecated_v1 + def testBadErrorPolicy(self): + text = constant_op.constant(["hippopotamus"]) + + with self.assertRaises(ValueError): + _, _, _ = gen_string_ops.unicode_decode_with_offsets( + text, "utf-8", errors="oranguatan") + + def testReplaceControlChars(self): + text = constant_op.constant(["\x02仅今年前"]) + row_splits, utf8_text, _ = gen_string_ops.unicode_decode_with_offsets( + text, "utf-8", replace_control_characters=True) + + with self.test_session(): + self.assertAllEqual([ + 65533, + codepoint("仅"), + codepoint("今"), + codepoint("年"), + codepoint("前"), + ], + self.evaluate(utf8_text).tolist()) + self.assertAllEqual([0, 5], self.evaluate(row_splits).tolist()) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/kernel_tests/unicode_encode_op_test.py b/tensorflow/python/kernel_tests/unicode_encode_op_test.py new file mode 100644 index 0000000000..a5a5c2017c --- /dev/null +++ b/tensorflow/python/kernel_tests/unicode_encode_op_test.py @@ -0,0 +1,301 @@ +# Copyright 2016 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for UnicodeEncode op from ragged_string_ops.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from absl.testing import parameterized +import numpy as np + +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import errors_impl as errors +from tensorflow.python.framework import ops +from tensorflow.python.ops.ragged import ragged_factory_ops +from tensorflow.python.ops.ragged import ragged_string_ops +from tensorflow.python.platform import test + + +class UnicodeEncodeOpTest(test.TestCase, parameterized.TestCase): + + def testScalar(self): + with self.cached_session(): + with self.assertRaises(ValueError): + ragged_string_ops.unicode_encode(72, "UTF-8") + with self.cached_session(): + with self.assertRaises(ValueError): + ragged_string_ops.unicode_encode(constant_op.constant(72), "UTF-8") + + def testRequireParams(self): + with self.cached_session(): + with self.assertRaises(TypeError): + ragged_string_ops.unicode_encode() + with self.cached_session(): + with self.assertRaises(TypeError): + ragged_string_ops.unicode_encode(72) + with self.cached_session(): + with self.assertRaises(TypeError): + ragged_string_ops.unicode_encode(encoding="UTF-8") + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def testStrictErrors(self, encoding): + test_value = np.array([72, 101, 2147483647, -1, 111], np.int32) + with self.cached_session(): + with self.assertRaises(errors.InvalidArgumentError): + ragged_string_ops.unicode_encode(test_value, encoding, "strict").eval() + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def testIgnoreErrors(self, encoding): + test_value = np.array([72, 101, 2147483647, -1, 111], np.int32) + expected_value = u"Heo".encode(encoding) + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding, + "ignore") + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(result, bytes) + self.assertAllEqual(result, expected_value) + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def testReplaceErrors(self, encoding): + test_value = np.array([72, 101, 2147483647, -1, 111], np.int32) + expected_value = u"He\U0000fffd\U0000fffdo".encode(encoding) + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding, + "replace") + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(result, bytes) + self.assertAllEqual(result, expected_value) + + # Test custom replacement character + test_value = np.array([72, 101, 2147483647, -1, 111], np.int32) + expected_value = u"Heooo".encode(encoding) + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding, + "replace", 111) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(result, bytes) + self.assertAllEqual(result, expected_value) + + # Verify "replace" is default + test_value = np.array([72, 101, 2147483647, -1, 111], np.int32) + expected_value = u"He\U0000fffd\U0000fffdo".encode(encoding) + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(result, bytes) + self.assertAllEqual(result, expected_value) + + # Replacement_char must be within range + test_value = np.array([72, 101, 2147483647, -1, 111], np.int32) + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding, + "replace", 1114112) + with self.cached_session(): + with self.assertRaises(errors.InvalidArgumentError): + unicode_encode_op.eval() + + # -- regular Tensor tests -- # + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def testVector(self, encoding): + test_value = np.array([72, 101, 108, 108, 111], np.int32) + expected_value = u"Hello".encode(encoding) + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(result, bytes) + self.assertAllEqual(result, expected_value) + + test_value = np.array([72, 101, 195, 195, 128516], np.int32) + expected_value = u"He\xc3\xc3\U0001f604".encode(encoding) + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(result, bytes) + self.assertAllEqual(result, expected_value) + + # Single character string + test_value = np.array([72], np.int32) + expected_value = u"H".encode(encoding) + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(result, bytes) + self.assertAllEqual(result, expected_value) + + test_value = np.array([128516], np.int32) + expected_value = u"\U0001f604".encode(encoding) + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(result, bytes) + self.assertAllEqual(result, expected_value) + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def testMatrix(self, encoding): + test_value = np.array( + [[72, 128516, 108, 108, 111], [87, 128516, 114, 108, 100]], np.int32) + expected_value = [ + u"H\U0001f604llo".encode(encoding), u"W\U0001f604rld".encode(encoding) + ] + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(unicode_encode_op, ops.Tensor) + self.assertAllEqual(result, expected_value) + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def test3DimMatrix(self, encoding): + test_value = constant_op.constant( + [[[72, 101, 108, 108, 111], [87, 111, 114, 108, 100]], + [[102, 105, 120, 101, 100], [119, 111, 114, 100, 115]], + [[72, 121, 112, 101, 114], [99, 117, 98, 101, 46]]], np.int32) + expected_value = [[u"Hello".encode(encoding), u"World".encode(encoding)], + [u"fixed".encode(encoding), u"words".encode(encoding)], + [u"Hyper".encode(encoding), u"cube.".encode(encoding)]] + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(unicode_encode_op, ops.Tensor) + self.assertAllEqual(result, expected_value) + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def test4DimMatrix(self, encoding): + test_value = constant_op.constant( + [[[[72, 101, 108, 108, 111]], [[87, 111, 114, 108, 100]]], + [[[102, 105, 120, 101, 100]], [[119, 111, 114, 100, 115]]], + [[[72, 121, 112, 101, 114]], [[99, 117, 98, 101, 46]]]], np.int32) + expected_value = [[[u"Hello".encode(encoding)], + [u"World".encode(encoding)]], + [[u"fixed".encode(encoding)], + [u"words".encode(encoding)]], + [[u"Hyper".encode(encoding)], + [u"cube.".encode(encoding)]]] + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(unicode_encode_op, ops.Tensor) + self.assertAllEqual(result, expected_value) + + # -- Ragged Tensor tests -- # + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def testRaggedMatrix(self, encoding): + test_value = ragged_factory_ops.constant( + [[72, 195, 108, 108, 111], [87, 128516, 114, 108, 100, 46]], np.int32) + expected_value = [ + u"H\xc3llo".encode(encoding), u"W\U0001f604rld.".encode(encoding) + ] + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertIsInstance(unicode_encode_op, ops.Tensor) + self.assertAllEqual(result, expected_value) + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def test3DimMatrixWithRagged2ndDim(self, encoding): + test_value = ragged_factory_ops.constant( + [[[72, 101, 108, 108, 111], [87, 111, 114, 108, 100]], + [[102, 105, 120, 101, 100]], + [[72, 121, 112, 101, 114], [119, 111, 114, 100, 115], + [99, 117, 98, 101, 46]]], np.int32) + expected_value = [[u"Hello".encode(encoding), u"World".encode(encoding)], + [u"fixed".encode(encoding)], + [ + u"Hyper".encode(encoding), u"words".encode(encoding), + u"cube.".encode(encoding) + ]] + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertEqual(unicode_encode_op.ragged_rank, 1) + self.assertAllEqual(result.tolist(), expected_value) + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def test3DimMatrixWithRagged3rdDim(self, encoding): + test_value = ragged_factory_ops.constant( + [[[72, 101, 108, 108, 111], [87, 111, 114, 108, 100, 46]], + [[68, 111, 110, 39, 116], [119, 195, 114, 114, 121, 44, 32, 98, 101]], + [[128516], []]], np.int32) + expected_value = [[u"Hello".encode(encoding), u"World.".encode(encoding)], + [ + u"Don't".encode(encoding), + u"w\xc3rry, be".encode(encoding) + ], [u"\U0001f604".encode(encoding), u"".encode(encoding)]] + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertEqual(unicode_encode_op.ragged_rank, 1) + self.assertAllEqual(result.tolist(), expected_value) + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def test3DimMatrixWithRagged2ndAnd3rdDim(self, encoding): + test_value = ragged_factory_ops.constant( + [[[72, 101, 108, 108, 111], [87, 111, 114, 108, 100, 46]], [], + [[128516]]], np.int32) + expected_value = [[u"Hello".encode(encoding), u"World.".encode(encoding)], + [], [u"\U0001f604".encode(encoding)]] + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertEqual(unicode_encode_op.ragged_rank, 1) + self.assertAllEqual(result.tolist(), expected_value) + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def test4DimRaggedMatrix(self, encoding): + test_value = ragged_factory_ops.constant( + [[[[72, 101, 108, 108, 111], [87, 111, 114, 108, 100]]], + [[[]], [[72, 121, 112, 101]]]], np.int32) + expected_value = [[[u"Hello".encode(encoding), u"World".encode(encoding)]], + [[u"".encode(encoding)], [u"Hype".encode(encoding)]]] + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertEqual(unicode_encode_op.ragged_rank, 2) + self.assertAllEqual(result.tolist(), expected_value) + + @parameterized.parameters("UTF-8", "UTF-16-BE", "UTF-32-BE") + def testRaggedMatrixWithMultiDimensionInnerValues(self, encoding): + test_inner_values = constant_op.constant([[[72, 101, 108, 108, 111], + [87, 111, 114, 108, 100]], + [[102, 105, 120, 101, 100], + [119, 111, 114, 100, 115]], + [[72, 121, 112, 101, 114], + [99, 117, 98, 101, 46]]]) + test_row_splits = [ + constant_op.constant([0, 2, 3], dtype=np.int64), + constant_op.constant([0, 1, 1, 3], dtype=np.int64) + ] + test_value = ragged_factory_ops.from_nested_row_splits(test_inner_values, + test_row_splits) + expected_value = [[[[u"Hello".encode(encoding), u"World".encode(encoding)]], + []], + [[[u"fixed".encode(encoding), u"words".encode(encoding)], + [u"Hyper".encode(encoding), + u"cube.".encode(encoding)]]]] + unicode_encode_op = ragged_string_ops.unicode_encode(test_value, encoding) + with self.cached_session(): + result = unicode_encode_op.eval() + self.assertEqual(unicode_encode_op.ragged_rank, 2) + self.assertAllEqual(result.tolist(), expected_value) + # These next two assertions don't necessarily need to be here as they test + # internal representations and we already verified the value is correct. + self.assertAllEqual(len(result.nested_row_splits), len(test_row_splits)) + self.assertEqual(unicode_encode_op.inner_values.shape.ndims, + test_inner_values.shape.ndims - 1) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/kernel_tests/unicode_script_op_test.py b/tensorflow/python/kernel_tests/unicode_script_op_test.py index 927e5459ed..83cfeb2021 100644 --- a/tensorflow/python/kernel_tests/unicode_script_op_test.py +++ b/tensorflow/python/kernel_tests/unicode_script_op_test.py @@ -20,12 +20,14 @@ from __future__ import print_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import string_ops from tensorflow.python.platform import test class UnicodeScriptOpTest(test.TestCase): + @test_util.run_deprecated_v1 def testValidScripts(self): inputs = [ ord("a"), @@ -45,6 +47,7 @@ class UnicodeScriptOpTest(test.TestCase): 0 # USCRIPT_COMMON (ZYYY) ]) + @test_util.run_deprecated_v1 def testInvalidScript(self): inputs = [-100, 0xffffff] with self.cached_session(): diff --git a/tensorflow/python/kernel_tests/unicode_transcode_op_test.py b/tensorflow/python/kernel_tests/unicode_transcode_op_test.py index 2908e2bfc5..a3b4fd0347 100644 --- a/tensorflow/python/kernel_tests/unicode_transcode_op_test.py +++ b/tensorflow/python/kernel_tests/unicode_transcode_op_test.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for string_length_op.""" +"""Tests for unicode_transcode op.""" from __future__ import absolute_import from __future__ import division @@ -22,6 +22,7 @@ from absl.testing import parameterized from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import string_ops from tensorflow.python.platform import test @@ -42,7 +43,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="replace", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, strings) outputs = string_ops.unicode_transcode( @@ -52,7 +53,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="replace", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, strings) outputs = string_ops.unicode_transcode( @@ -62,7 +63,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="replace", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, strings) def test_transcode_utf16_to_utf8(self): @@ -77,7 +78,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="replace", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, expected) def test_transcode_bad_utf8(self): @@ -90,7 +91,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="replace", replacement_char=ord(" "), replace_control_characters=True) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b" ") outputs = string_ops.unicode_transcode( @@ -100,7 +101,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="replace", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b"\x00 ") def test_transcode_bad_utf8_with_some_good(self): @@ -113,7 +114,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="replace", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b"abc abcdefg") def test_transcode_bad_utf8_with_defaults(self): @@ -121,7 +122,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): with self.cached_session() as sess: outputs = string_ops.unicode_transcode( bad_string, input_encoding="UTF-8", output_encoding="UTF-8") - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b"\x00\xef\xbf\xbd") def test_transcode_bad_utf8_with_space_replacement(self): @@ -130,9 +131,10 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): outputs = string_ops.unicode_transcode( bad_string, input_encoding="UTF-8", output_encoding="UTF-8", replacement_char=ord(" ")) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b"\x00 ") + @test_util.run_deprecated_v1 def test_transcode_bad_utf8_with_strict_errors(self): bad_string = b"\x00\xff" with self.cached_session() as sess: @@ -143,8 +145,9 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="strict") with self.assertRaisesOpError( "Invalid formatting on input string"): - sess.run(outputs) + self.evaluate(outputs) + @test_util.run_deprecated_v1 def test_transcode_bad_utf8_start_with_strict_errors(self): bad_string = b"\xffabcd" with self.cached_session() as sess: @@ -155,7 +158,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="strict") with self.assertRaisesOpError( "Invalid formatting on input string"): - sess.run(outputs) + self.evaluate(outputs) def test_transcode_bad_utf8_with_elision_of_malformatting(self): bad_string = b"\x00\xff" @@ -165,7 +168,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): input_encoding="UTF-8", output_encoding="UTF-8", errors="ignore") - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b"\x00") def test_transcode_bad_utf8_with_elision_including_control_chars(self): @@ -177,7 +180,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): output_encoding="UTF-8", errors="ignore", replace_control_characters=True) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b"") def test_transcode_bad_utf8_termination_with_defaults(self): @@ -185,7 +188,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): with self.cached_session() as sess: outputs = string_ops.unicode_transcode( bad_string, input_encoding="UTF-8", output_encoding="UTF-8") - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b"a\xef\xbf\xbd") # 0xFFFD def test_transcode_utf8_with_replacement_char(self): @@ -194,13 +197,13 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): outputs = string_ops.unicode_transcode( strings, input_encoding="UTF-8", output_encoding="UTF-8", errors="strict") - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, [b"a\xef\xbf\xbd"]) outputs = string_ops.unicode_transcode( strings, input_encoding="UTF-8", output_encoding="UTF-8", errors="replace", replacement_char=ord("?")) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, [b"a\xef\xbf\xbd"]) def test_transcode_utf8_to_utf16(self): @@ -214,7 +217,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): output_encoding="UTF-16-BE", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) print("values=", values) self.assertAllEqual(values, expected) @@ -230,7 +233,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): output_encoding="UTF-8", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, expected) def test_transcode_utf8_to_utf32(self): @@ -243,7 +246,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): output_encoding="UTF-32-BE", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, expected) # Documentation in ICU suggests that getNextUChar may produce a different @@ -258,7 +261,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): output_encoding="UTF-8", replacement_char=ord(" "), replace_control_characters=False) - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, strings) def test_transcode_utf8_with_bom(self): @@ -266,12 +269,12 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): with self.cached_session() as sess: outputs = string_ops.unicode_transcode( bom_string, input_encoding="UTF-8", output_encoding="UTF-8") - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b"\xef\xbb\xbfabcdefg") # BOM preserved outputs = string_ops.unicode_transcode( bom_string, input_encoding="UTF-8", output_encoding="UTF-16-BE") - values = sess.run(outputs) + values = self.evaluate(outputs) utf16expected = bom_string.decode("UTF-8").encode("UTF-16-BE") self.assertAllEqual(values, utf16expected) @@ -280,20 +283,20 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): with self.cached_session() as sess: outputs = string_ops.unicode_transcode( bom_string, input_encoding="UTF-16-BE", output_encoding="UTF-8") - values = sess.run(outputs) + values = self.evaluate(outputs) # BOM is preserved in output self.assertAllEqual(values, b"\xef\xbb\xbfa") outputs = string_ops.unicode_transcode( bom_string, input_encoding="UTF-16-LE", output_encoding="UTF-8") - values = sess.run(outputs) + values = self.evaluate(outputs) # mangled BOM and value from (incorrect) LE encoding self.assertAllEqual(values, b"\xef\xbf\xbe\xe6\x84\x80") bom_string = b"\xff\xfe\x61\x00" # Little-endian BOM with 'a' encoded outputs = string_ops.unicode_transcode( bom_string, input_encoding="UTF-16-LE", output_encoding="UTF-8") - values = sess.run(outputs) + values = self.evaluate(outputs) self.assertAllEqual(values, b"\xef\xbb\xbfa") @parameterized.parameters( @@ -317,12 +320,14 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): (b"\xfe\xff\x00<\xfe\xff\x00>", "UTF-16", b"<\xef\xbb\xbf>"), (b"\xff\xfe<\x00\xff\xfe>\x00", "UTF-16", b"<\xef\xbb\xbf>"), ) + @test_util.run_deprecated_v1 def test_bom_handling(self, string, input_encoding, expected): with self.test_session(): output = string_ops.unicode_transcode( string, input_encoding=input_encoding, output_encoding="UTF-8") self.assertAllEqual(output.eval(), expected) + @test_util.run_deprecated_v1 def test_invalid_encoding_causes_errors(self): strings = [[b"a", b"abc"], [b"ABC", b"DEF"]] @@ -336,7 +341,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): replace_control_characters=False) with self.assertRaisesOpError( "Could not create converter for input encoding: invalid"): - sess.run(outputs) + self.evaluate(outputs) with self.assertRaisesRegexp(ValueError, "Op passed string 'invalid'"): with self.cached_session() as sess: @@ -347,8 +352,9 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="replace", replacement_char=ord(" "), replace_control_characters=False) - sess.run(outputs) + self.evaluate(outputs) + @test_util.run_deprecated_v1 def test_invalid_error_policy_causes_errors(self): strings = [[b"a", b"abc"], [b"ABC", b"DEF"]] @@ -362,7 +368,7 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): errors="invalid", replacement_char=ord(" "), replace_control_characters=False) - sess.run(outputs) + self.evaluate(outputs) def test_forwarding(self): with self.cached_session(): @@ -378,6 +384,61 @@ class UnicodeTranscodeOpTest(test.TestCase, parameterized.TestCase): self.assertAllEqual([b"AbCdE", b"HiJkL"], transcoded) + @test_util.run_deprecated_v1 + def test_cjk_encodings(self): + strings_ja = [ + b"\x5c\x5c", # Yen sign + b"\x8f\x70", # kanji character "waza" + b"\x83\x4f" + ] # katakana character "gu" + strings_zh_cn = [b"\xca\xf5"] # simplified "shu4" + strings_zh_tw = [b"\xb3\x4e"] # traditional "shu4" + strings_ko = [b"\xc7\xd1\xb9\xce"] # hangul "hanmin" + + expected_ja = [s.decode("shift_jis").encode("UTF-8") for s in strings_ja] + expected_zh_cn = [ + s.decode("gb18030").encode("UTF-8") for s in strings_zh_cn + ] + expected_zh_tw = [s.decode("big5").encode("UTF-8") for s in strings_zh_tw] + expected_ko = [s.decode("euc_kr").encode("UTF-8") for s in strings_ko] + + with self.cached_session() as sess: + outputs_ja = string_ops.unicode_transcode( + strings_ja, + input_encoding="shift_jis", + output_encoding="UTF-8", + replacement_char=ord(" "), + replace_control_characters=False) + + outputs_zh_cn = string_ops.unicode_transcode( + strings_zh_cn, + input_encoding="gb18030", + output_encoding="UTF-8", + replacement_char=ord(" "), + replace_control_characters=False) + + outputs_zh_tw = string_ops.unicode_transcode( + strings_zh_tw, + input_encoding="big5", + output_encoding="UTF-8", + replacement_char=ord(" "), + replace_control_characters=False) + + outputs_ko = string_ops.unicode_transcode( + strings_ko, + input_encoding="euc_kr", + output_encoding="UTF-8", + replacement_char=ord(" "), + replace_control_characters=False) + + result_ja, result_zh_cn, result_zh_tw, result_ko = sess.run( + [outputs_ja, outputs_zh_cn, outputs_zh_tw, outputs_ko]) + + self.assertAllEqual(result_ja, expected_ja) + self.assertAllEqual(result_zh_cn, expected_zh_cn) + self.assertAllEqual(result_zh_tw, expected_zh_tw) + self.assertAllEqual(result_ko, expected_ko) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/kernel_tests/unique_op_test.py b/tensorflow/python/kernel_tests/unique_op_test.py index 316570e13e..f203263e0c 100644 --- a/tensorflow/python/kernel_tests/unique_op_test.py +++ b/tensorflow/python/kernel_tests/unique_op_test.py @@ -32,7 +32,7 @@ class UniqueTest(test.TestCase): x = np.random.randint(2, high=10, size=7000) with self.cached_session() as sess: y, idx = array_ops.unique(x) - tf_y, tf_idx = sess.run([y, idx]) + tf_y, tf_idx = self.evaluate([y, idx]) self.assertEqual(len(x), len(tf_idx)) self.assertEqual(len(tf_y), len(np.unique(x))) @@ -43,7 +43,7 @@ class UniqueTest(test.TestCase): x = np.random.randint(2, high=10, size=7000) with self.cached_session() as sess: y, idx = array_ops.unique(x, out_idx=dtypes.int64) - tf_y, tf_idx = sess.run([y, idx]) + tf_y, tf_idx = self.evaluate([y, idx]) self.assertEqual(len(x), len(tf_idx)) self.assertEqual(len(tf_y), len(np.unique(x))) @@ -55,7 +55,7 @@ class UniqueTest(test.TestCase): x = [chr(i) for i in indx] with self.cached_session() as sess: y, idx = array_ops.unique(x) - tf_y, tf_idx = sess.run([y, idx]) + tf_y, tf_idx = self.evaluate([y, idx]) self.assertEqual(len(x), len(tf_idx)) self.assertEqual(len(tf_y), len(np.unique(x))) @@ -67,9 +67,9 @@ class UniqueTest(test.TestCase): x = np.array([[1, 0, 0], [1, 0, 0], [2, 0, 0]]) with self.cached_session() as sess: y0, idx0 = gen_array_ops.unique_v2(x, axis=np.array([0], dtype)) - tf_y0, tf_idx0 = sess.run([y0, idx0]) + tf_y0, tf_idx0 = self.evaluate([y0, idx0]) y1, idx1 = gen_array_ops.unique_v2(x, axis=np.array([1], dtype)) - tf_y1, tf_idx1 = sess.run([y1, idx1]) + tf_y1, tf_idx1 = self.evaluate([y1, idx1]) self.assertAllEqual(tf_y0, np.array([[1, 0, 0], [2, 0, 0]])) self.assertAllEqual(tf_idx0, np.array([0, 0, 1])) self.assertAllEqual(tf_y1, np.array([[1, 0], [1, 0], [2, 0]])) @@ -81,7 +81,7 @@ class UniqueTest(test.TestCase): x = np.random.randint(2, high=10, size=7000) with self.cached_session() as sess: y, idx = gen_array_ops.unique_v2(x, axis=np.array([], np.int32)) - tf_y, tf_idx = sess.run([y, idx]) + tf_y, tf_idx = self.evaluate([y, idx]) self.assertEqual(len(x), len(tf_idx)) self.assertEqual(len(tf_y), len(np.unique(x))) @@ -95,7 +95,7 @@ class UniqueWithCountsTest(test.TestCase): x = np.random.randint(2, high=10, size=7000) with self.cached_session() as sess: y, idx, count = array_ops.unique_with_counts(x) - tf_y, tf_idx, tf_count = sess.run([y, idx, count]) + tf_y, tf_idx, tf_count = self.evaluate([y, idx, count]) self.assertEqual(len(x), len(tf_idx)) self.assertEqual(len(tf_y), len(np.unique(x))) @@ -108,7 +108,7 @@ class UniqueWithCountsTest(test.TestCase): x = np.random.randint(2, high=10, size=7000) with self.cached_session() as sess: y, idx, count = array_ops.unique_with_counts(x, out_idx=dtypes.int64) - tf_y, tf_idx, tf_count = sess.run([y, idx, count]) + tf_y, tf_idx, tf_count = self.evaluate([y, idx, count]) self.assertEqual(len(x), len(tf_idx)) self.assertEqual(len(tf_y), len(np.unique(x))) @@ -123,7 +123,7 @@ class UniqueWithCountsTest(test.TestCase): with self.cached_session() as sess: y, idx, count = array_ops.unique_with_counts(x) - tf_y, tf_idx, tf_count = sess.run([y, idx, count]) + tf_y, tf_idx, tf_count = self.evaluate([y, idx, count]) self.assertEqual(len(x), len(tf_idx)) self.assertEqual(len(tf_y), len(np.unique(x))) @@ -139,10 +139,10 @@ class UniqueWithCountsTest(test.TestCase): with self.cached_session() as sess: y0, idx0, count0 = gen_array_ops.unique_with_counts_v2( x, axis=np.array([0], dtype)) - tf_y0, tf_idx0, tf_count0 = sess.run([y0, idx0, count0]) + tf_y0, tf_idx0, tf_count0 = self.evaluate([y0, idx0, count0]) y1, idx1, count1 = gen_array_ops.unique_with_counts_v2( x, axis=np.array([1], dtype)) - tf_y1, tf_idx1, tf_count1 = sess.run([y1, idx1, count1]) + tf_y1, tf_idx1, tf_count1 = self.evaluate([y1, idx1, count1]) self.assertAllEqual(tf_y0, np.array([[1, 0, 0], [2, 0, 0]])) self.assertAllEqual(tf_idx0, np.array([0, 0, 1])) self.assertAllEqual(tf_count0, np.array([2, 1])) @@ -157,7 +157,7 @@ class UniqueWithCountsTest(test.TestCase): with self.cached_session() as sess: y, idx, count = gen_array_ops.unique_with_counts_v2( x, axis=np.array([], np.int32)) - tf_y, tf_idx, tf_count = sess.run([y, idx, count]) + tf_y, tf_idx, tf_count = self.evaluate([y, idx, count]) self.assertEqual(len(x), len(tf_idx)) self.assertEqual(len(tf_y), len(np.unique(x))) diff --git a/tensorflow/python/kernel_tests/unstack_op_test.py b/tensorflow/python/kernel_tests/unstack_op_test.py index 6aea42990a..f5ba475e7a 100644 --- a/tensorflow/python/kernel_tests/unstack_op_test.py +++ b/tensorflow/python/kernel_tests/unstack_op_test.py @@ -41,7 +41,7 @@ class UnstackOpTest(test.TestCase): def testSimple(self): np.random.seed(7) - with self.session(use_gpu=True): + with test_util.use_gpu(): for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2): for dtype in [ np.bool, np.float16, np.float32, np.float64, np.int32, np.int64 @@ -53,14 +53,15 @@ class UnstackOpTest(test.TestCase): cs = array_ops.unstack(x, num=shape[0]) self.assertEqual(type(cs), list) self.assertEqual(len(cs), shape[0]) - cs = [c.eval() for c in cs] + cs = [self.evaluate(c) for c in cs] self.assertAllEqual(cs, data) def testSimpleGpu(self): if not test_util.is_gpu_available(): self.skipTest('No GPU available') + np.random.seed(7) - with self.session(use_gpu=True, force_gpu=True): + with test_util.force_gpu(): for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2): for dtype in [np.float16, np.float32, np.float64, np.int32, np.int64]: data = np.random.randn(*shape).astype(dtype) @@ -70,9 +71,10 @@ class UnstackOpTest(test.TestCase): cs = array_ops.unstack(x, num=shape[0]) self.assertEqual(type(cs), list) self.assertEqual(len(cs), shape[0]) - cs = [c.eval() for c in cs] + cs = [self.evaluate(c) for c in cs] self.assertAllEqual(cs, data) + @test_util.run_deprecated_v1 def testGradientsAxis0(self): for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2): data = np.random.randn(*shape) @@ -85,6 +87,7 @@ class UnstackOpTest(test.TestCase): shapes[i]) self.assertLess(err, 1e-6) + @test_util.run_deprecated_v1 def testGradientsAxis1(self): for shape in (2, 3), (3, 2), (4, 3, 2): data = np.random.randn(*shape) @@ -98,6 +101,7 @@ class UnstackOpTest(test.TestCase): out_shape) self.assertLess(err, 1e-6) + @test_util.run_deprecated_v1 def testInferNum(self): with self.cached_session(): for shape in (2,), (3,), (2, 3), (3, 2), (4, 3, 2): @@ -106,16 +110,19 @@ class UnstackOpTest(test.TestCase): self.assertEqual(type(cs), list) self.assertEqual(len(cs), shape[0]) + @test_util.run_deprecated_v1 def testCannotInferNumFromUnknownShape(self): x = array_ops.placeholder(np.float32) with self.assertRaisesRegexp(ValueError, r'Cannot infer num from shape '): array_ops.unstack(x) + @test_util.run_deprecated_v1 def testUnknownShapeOkWithNum(self): x = array_ops.placeholder(np.float32) array_ops.unstack(x, num=2) + @test_util.run_deprecated_v1 def testCannotInferNumFromNoneShape(self): x = array_ops.placeholder(np.float32, shape=(None,)) with self.assertRaisesRegexp(ValueError, @@ -131,15 +138,13 @@ class UnstackOpTest(test.TestCase): for j in range(-i, i): expected = np_split_squeeze(a, j) - with self.cached_session() as sess: - actual_unstack = sess.run(array_ops.unstack(a, axis=j)) + actual_unstack = self.evaluate(array_ops.unstack(a, axis=j)) self.assertAllEqual(expected, actual_unstack) def testAxis0Default(self): - with self.cached_session() as sess: - a = constant_op.constant([[1, 2, 3], [4, 5, 6]], name='a') - unstacked = sess.run(array_ops.unstack(a)) + a = constant_op.constant([[1, 2, 3], [4, 5, 6]], name='a') + unstacked = self.evaluate(array_ops.unstack(a)) self.assertEqual(len(unstacked), 2) self.assertAllEqual(unstacked[0], [1, 2, 3]) @@ -156,10 +161,9 @@ class UnstackOpTest(test.TestCase): array_ops.unstack(a, axis=-3) def testZeroLengthDim(self): - with self.cached_session(): - x = array_ops.zeros(shape=(0, 1, 2)) - y = array_ops.unstack(x, axis=1)[0].eval() - self.assertEqual(y.shape, (0, 2)) + x = array_ops.zeros(shape=(0, 1, 2)) + y = self.evaluate(array_ops.unstack(x, axis=1)[0]) + self.assertEqual(y.shape, (0, 2)) if __name__ == '__main__': diff --git a/tensorflow/python/kernel_tests/variable_ops_test.py b/tensorflow/python/kernel_tests/variable_ops_test.py index 3d2f8b6155..0f3e261992 100644 --- a/tensorflow/python/kernel_tests/variable_ops_test.py +++ b/tensorflow/python/kernel_tests/variable_ops_test.py @@ -24,6 +24,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_state_ops from tensorflow.python.ops import math_ops @@ -46,7 +47,7 @@ class VariableOpTest(test.TestCase): p = state_ops.variable_op(x.shape, tftype) op = state_ops.assign(p, x) op.op.run() - return p.eval() + return self.evaluate(p) def _testTypes(self, vals): for dtype in [np.float32, np.float64, np.int32, np.int64]: @@ -59,15 +60,18 @@ class VariableOpTest(test.TestCase): # that Variable and Assign have GPU implementations for matching tf. self.assertAllEqual(x, self._initFetch(x, tftype, use_gpu=True)) + @test_util.run_deprecated_v1 def testBasic(self): self._testTypes(np.arange(0, 20).reshape([4, 5])) + @test_util.run_deprecated_v1 def testset_shape(self): p = state_ops.variable_op([1, 2], dtypes.float32) self.assertEqual([1, 2], p.get_shape()) p = state_ops.variable_op([1, 2], dtypes.float32, set_shape=False) self.assertEqual(tensor_shape.unknown_shape(), p.get_shape()) + @test_util.run_deprecated_v1 def testAssign(self): value = np.array([[42.0, 43.0]]) var = state_ops.variable_op(value.shape, dtypes.float32) @@ -75,6 +79,7 @@ class VariableOpTest(test.TestCase): assigned = state_ops.assign(var, value) self.assertShapeEqual(value, assigned) + @test_util.run_deprecated_v1 def testAssignNoValidateShape(self): value = np.array([[42.0, 43.0]]) var = state_ops.variable_op(value.shape, dtypes.float32) @@ -82,6 +87,7 @@ class VariableOpTest(test.TestCase): assigned = state_ops.assign(var, value, validate_shape=False) self.assertShapeEqual(value, assigned) + @test_util.run_deprecated_v1 def testAssignNoVarShape(self): value = np.array([[42.0, 43.0]]) var = state_ops.variable_op(value.shape, dtypes.float32, set_shape=False) @@ -89,6 +95,7 @@ class VariableOpTest(test.TestCase): assigned = state_ops.assign(var, value) self.assertShapeEqual(value, assigned) + @test_util.run_deprecated_v1 def testAssignNoVarShapeNoValidateShape(self): value = np.array([[42.0, 43.0]]) var = state_ops.variable_op(value.shape, dtypes.float32, set_shape=False) @@ -101,6 +108,7 @@ class VariableOpTest(test.TestCase): self.assertEqual(tensor_shape.unknown_shape(), tensor.get_shape()) return tensor + @test_util.run_deprecated_v1 def testAssignNoValueShape(self): value = self._NewShapelessTensor() shape = [1, 2] @@ -109,6 +117,7 @@ class VariableOpTest(test.TestCase): self.assertEqual(shape, var.get_shape()) self.assertEqual(shape, assigned.get_shape()) + @test_util.run_deprecated_v1 def testAssignNoValueShapeNoValidateShape(self): value = self._NewShapelessTensor() shape = [1, 2] @@ -117,6 +126,7 @@ class VariableOpTest(test.TestCase): assigned = state_ops.assign(var, value, validate_shape=False) self.assertEqual(tensor_shape.unknown_shape(), assigned.get_shape()) + @test_util.run_deprecated_v1 def testAssignNoShape(self): with self.cached_session(): value = self._NewShapelessTensor() @@ -125,6 +135,7 @@ class VariableOpTest(test.TestCase): self.assertEqual(tensor_shape.unknown_shape(), state_ops.assign(var, value).get_shape()) + @test_util.run_deprecated_v1 def testAssignNoShapeNoValidateShape(self): with self.cached_session(): value = self._NewShapelessTensor() @@ -135,6 +146,7 @@ class VariableOpTest(test.TestCase): state_ops.assign( var, value, validate_shape=False).get_shape()) + @test_util.run_deprecated_v1 def testAssignUpdate(self): var = state_ops.variable_op([1, 2], dtypes.float32) added = state_ops.assign_add(var, [[2.0, 3.0]]) @@ -142,6 +154,7 @@ class VariableOpTest(test.TestCase): subbed = state_ops.assign_sub(var, [[12.0, 13.0]]) self.assertEqual([1, 2], subbed.get_shape()) + @test_util.run_deprecated_v1 def testAssignUpdateNoVarShape(self): var = state_ops.variable_op([1, 2], dtypes.float32, set_shape=False) added = state_ops.assign_add(var, [[2.0, 3.0]]) @@ -149,6 +162,7 @@ class VariableOpTest(test.TestCase): subbed = state_ops.assign_sub(var, [[12.0, 13.0]]) self.assertEqual([1, 2], subbed.get_shape()) + @test_util.run_deprecated_v1 def testAssignUpdateNoValueShape(self): var = state_ops.variable_op([1, 2], dtypes.float32) added = state_ops.assign_add(var, self._NewShapelessTensor()) @@ -156,6 +170,7 @@ class VariableOpTest(test.TestCase): subbed = state_ops.assign_sub(var, self._NewShapelessTensor()) self.assertEqual([1, 2], subbed.get_shape()) + @test_util.run_deprecated_v1 def testAssignUpdateNoShape(self): var = state_ops.variable_op([1, 2], dtypes.float32, set_shape=False) added = state_ops.assign_add(var, self._NewShapelessTensor()) @@ -163,24 +178,27 @@ class VariableOpTest(test.TestCase): subbed = state_ops.assign_sub(var, self._NewShapelessTensor()) self.assertEqual(tensor_shape.unknown_shape(), subbed.get_shape()) + @test_util.run_deprecated_v1 def testTemporaryVariable(self): - with self.test_session(use_gpu=True): + with test_util.use_gpu(): var = gen_state_ops.temporary_variable( [1, 2], dtypes.float32, var_name="foo") var = state_ops.assign(var, [[4.0, 5.0]]) var = state_ops.assign_add(var, [[6.0, 7.0]]) final = gen_state_ops.destroy_temporary_variable(var, var_name="foo") - self.assertAllClose([[10.0, 12.0]], final.eval()) + self.assertAllClose([[10.0, 12.0]], self.evaluate(final)) + @test_util.run_deprecated_v1 def testDestroyNonexistentTemporaryVariable(self): - with self.test_session(use_gpu=True): + with test_util.use_gpu(): var = gen_state_ops.temporary_variable([1, 2], dtypes.float32) final = gen_state_ops.destroy_temporary_variable(var, var_name="bad") with self.assertRaises(errors.NotFoundError): - final.eval() + self.evaluate(final) + @test_util.run_deprecated_v1 def testDuplicateTemporaryVariable(self): - with self.test_session(use_gpu=True): + with test_util.use_gpu(): var1 = gen_state_ops.temporary_variable( [1, 2], dtypes.float32, var_name="dup") var1 = state_ops.assign(var1, [[1.0, 2.0]]) @@ -189,48 +207,53 @@ class VariableOpTest(test.TestCase): var2 = state_ops.assign(var2, [[3.0, 4.0]]) final = var1 + var2 with self.assertRaises(errors.AlreadyExistsError): - final.eval() + self.evaluate(final) + @test_util.run_deprecated_v1 def testDestroyTemporaryVariableTwice(self): - with self.test_session(use_gpu=True): + with test_util.use_gpu(): var = gen_state_ops.temporary_variable([1, 2], dtypes.float32) val1 = gen_state_ops.destroy_temporary_variable(var, var_name="dup") val2 = gen_state_ops.destroy_temporary_variable(var, var_name="dup") final = val1 + val2 with self.assertRaises(errors.NotFoundError): - final.eval() + self.evaluate(final) + @test_util.run_deprecated_v1 def testTemporaryVariableNoLeak(self): - with self.test_session(use_gpu=True): + with test_util.use_gpu(): var = gen_state_ops.temporary_variable( [1, 2], dtypes.float32, var_name="bar") final = array_ops.identity(var) - final.eval() + self.evaluate(final) + @test_util.run_deprecated_v1 def testTwoTemporaryVariablesNoLeaks(self): - with self.test_session(use_gpu=True): + with test_util.use_gpu(): var1 = gen_state_ops.temporary_variable( [1, 2], dtypes.float32, var_name="var1") var2 = gen_state_ops.temporary_variable( [1, 2], dtypes.float32, var_name="var2") final = var1 + var2 - final.eval() + self.evaluate(final) + @test_util.run_deprecated_v1 def testAssignDependencyAcrossDevices(self): - with self.test_session(use_gpu=True): + with test_util.use_gpu(): # The variable and an op to increment it are on the GPU. var = state_ops.variable_op([1], dtypes.float32) - state_ops.assign(var, [1.0]).eval() + self.evaluate(state_ops.assign(var, [1.0])) increment = state_ops.assign_add(var, [1.0]) with ops.control_dependencies([increment]): - with ops.device("/cpu:0"): + with test_util.force_cpu(): # This mul op is pinned to the CPU, but reads the variable from the # GPU. The test ensures that the dependency on 'increment' is still # honored, i.e., the Send and Recv from GPU to CPU should take place # only after the increment. result = math_ops.multiply(var, var) - self.assertAllClose([4.0], result.eval()) + self.assertAllClose([4.0], self.evaluate(result)) + @test_util.run_deprecated_v1 def testIsVariableInitialized(self): for use_gpu in [True, False]: with self.test_session(use_gpu=use_gpu): diff --git a/tensorflow/python/kernel_tests/variable_scope_test.py b/tensorflow/python/kernel_tests/variable_scope_test.py index 2ba064f8a5..44d4bd5e30 100644 --- a/tensorflow/python/kernel_tests/variable_scope_test.py +++ b/tensorflow/python/kernel_tests/variable_scope_test.py @@ -152,6 +152,7 @@ class VariableScopeTest(test.TestCase): # TypeError: Fetch argument # has invalid type , must be a string or Tensor. # (Can not convert a ResourceVariable into a Tensor or Operation.) + @test_util.run_deprecated_v1 def testStringDefaultInitializer(self): with self.cached_session(): v = variable_scope.get_variable("string", shape=[], dtype=dtypes.string) @@ -308,9 +309,9 @@ class VariableScopeTest(test.TestCase): self.evaluate(variables_lib.global_variables_initializer()) self.assertAllEqual(self.evaluate(x.value()), self.evaluate(y.value())) - # TODO(alive): support variable partitioning/caching in eager mode. # TODO(mihaimaruseac): Not converted to use wrap_function because of # InvalidArgumentError: /job:moo/replica:0/task:0/device:CPU:0 unknown device. + @test_util.run_deprecated_v1 def testVarScopeCachingDevice(self): with self.cached_session(): caching_device = "/job:moo" @@ -425,6 +426,7 @@ class VariableScopeTest(test.TestCase): # invalid type , must # be a string or Tensor. (Can not convert a ResourceVariable into a Tensor or # Operation.) + @test_util.run_deprecated_v1 def testControlDeps(self): with self.cached_session() as sess: v0 = variable_scope.get_variable( @@ -435,22 +437,23 @@ class VariableScopeTest(test.TestCase): add = v1 + v0 # v0 should be uninitialized. with self.assertRaisesRegexp(errors.OpError, "uninitialized"): - sess.run(v0) + self.evaluate(v0) # We should be able to initialize and run v1 without initializing # v0, even if the variable was created with a control dep on v0. - sess.run(v1.initializer) - self.assertEqual(1, sess.run(v1)) + self.evaluate(v1.initializer) + self.assertEqual(1, self.evaluate(v1)) # v0 should still be uninitialized. with self.assertRaisesRegexp(errors.OpError, "uninitialized"): - sess.run(v0) + self.evaluate(v0) with self.assertRaisesRegexp(errors.OpError, "uninitialized"): - sess.run(add) + self.evaluate(add) # If we initialize v0 we should be able to run 'add'. - sess.run(v0.initializer) - sess.run(add) + self.evaluate(v0.initializer) + self.evaluate(add) # TODO(mihaimaruseac): Not converted to use wrap_function because of # AssertionError: True is not false (last assertFalse) + @test_util.run_deprecated_v1 def testEnableResourceVariables(self): old = variable_scope._DEFAULT_USE_RESOURCE try: @@ -465,6 +468,7 @@ class VariableScopeTest(test.TestCase): # TODO(mihaimaruseac): Not converted to use wrap_function because of # TypeError: Fetch argument None has invalid type + @test_util.run_deprecated_v1 def testControlFlow(self): with self.cached_session() as sess: v0 = variable_scope.get_variable( @@ -490,19 +494,19 @@ class VariableScopeTest(test.TestCase): v2 = var_dict["v2"] # We should be able to initialize and run v1 and v2 without initializing # v0, even if the variable was created with a control dep on v0. - sess.run(v1.initializer) - self.assertEqual([1], sess.run(v1)) - sess.run(v2.initializer) - self.assertEqual([2], sess.run(v2)) + self.evaluate(v1.initializer) + self.assertEqual([1], self.evaluate(v1)) + self.evaluate(v2.initializer) + self.assertEqual([2], self.evaluate(v2)) # v0 should still be uninitialized. with self.assertRaisesRegexp(errors.OpError, "uninitialized"): - sess.run(v0) + self.evaluate(v0) # We should not be able to run 'add' yet. with self.assertRaisesRegexp(errors.OpError, "uninitialized"): - sess.run(add) + self.evaluate(add) # If we initialize v0 we should be able to run 'add'. - sess.run(v0.initializer) - sess.run(add) + self.evaluate(v0.initializer) + self.evaluate(add) # TODO(mihaimaruseac): Not converted to use wrap_function because of # TypeError: Expected tf.group() expected Tensor arguments not 'None' with @@ -649,7 +653,7 @@ class VariableScopeTest(test.TestCase): "testVarScopeGetOrCreateReuse_bar", reuse=variable_scope.AUTO_REUSE): _ = variable_scope.get_variable("var", []) - self.assertEqual(value, x.eval()) + self.assertEqual(value, self.evaluate(x)) test_value(42.) # Variable is created. test_value(13.) # Variable is reused hereafter. @@ -1149,6 +1153,7 @@ class VariableScopeTest(test.TestCase): # TODO(mihaimaruseac): Not converted to use wrap_function because of # obtaining different results in the eager case compared to the graph one + @test_util.run_deprecated_v1 def testGetCollection(self): with self.cached_session(): _ = variable_scope.get_variable("testGetCollection_a", []) @@ -1205,6 +1210,7 @@ class VariableScopeTest(test.TestCase): # TODO(mihaimaruseac): Not converted to use wrap_function because of # obtaining different results in the eager case compared to the graph one + @test_util.run_deprecated_v1 def testGetTrainableVariablesWithGetVariable(self): with self.cached_session(): _ = variable_scope.get_variable("testGetTrainableVariables_a", []) @@ -1243,6 +1249,7 @@ class VariableScopeTest(test.TestCase): # TODO(mihaimaruseac): Not converted to use wrap_function because of # obtaining different results in the eager case compared to the graph one + @test_util.run_deprecated_v1 def testGetTrainableVariablesWithVariable(self): with self.cached_session(): _ = variable_scope.variable(1.0, name="testGetTrainableVariables_a") @@ -1284,6 +1291,7 @@ class VariableScopeTest(test.TestCase): # TODO(mihaimaruseac): Not converted to use wrap_function because of # obtaining different results in the eager case compared to the graph one + @test_util.run_deprecated_v1 def testGetGlobalVariables(self): with self.cached_session(): _ = variable_scope.get_variable("testGetGlobalVariables_a", []) @@ -1296,6 +1304,7 @@ class VariableScopeTest(test.TestCase): # TODO(mihaimaruseac): Not converted to use wrap_function because of # obtaining different results in the eager case compared to the graph one + @test_util.run_deprecated_v1 def testGetLocalVariables(self): with self.cached_session(): _ = variable_scope.get_variable( @@ -1313,6 +1322,28 @@ class VariableScopeTest(test.TestCase): # Ensure it is possible to do get_variable with a _ref dtype passed in. _ = variable_scope.get_variable("w", shape=[5, 6], dtype=v.dtype) + @test_util.run_in_graph_and_eager_modes + @run_inside_wrap_function_in_eager_mode + def testGetVariableWithInitializerWhichTakesNoArgs(self): + v = variable_scope.get_variable("foo", initializer=lambda: [2]) + self.assertEqual(v.name, "foo:0") + + @test_util.run_in_graph_and_eager_modes + @run_inside_wrap_function_in_eager_mode + def testGetVariableWithInitializerWhichTakesOptionalArgs(self): + v = variable_scope.get_variable("foo", initializer=lambda x=True: [2]) + self.assertEqual(v.name, "foo:0") + + @test_util.run_in_graph_and_eager_modes + @run_inside_wrap_function_in_eager_mode + def testGetVariableWithInitializerWhichTakesUnprovidedArgsAndNoShape(self): + with self.assertRaisesRegexp( + ValueError, + "The initializer passed is not valid. It should be a callable with no " + "arguments and the shape should not be provided or an instance of " + "`tf.keras.initializers.*' and `shape` should be fully defined."): + variable_scope.get_variable("foo", initializer=lambda x: [2]) + @test_util.run_in_graph_and_eager_modes @run_inside_wrap_function_in_eager_mode def testTwoGraphs(self): @@ -1349,6 +1380,7 @@ class VariableScopeWithPartitioningTest(test.TestCase): # TODO(mihaimaruseac): Not converted to use wrap_function because of # obtaining different results in the eager case compared to the graph one + @test_util.run_deprecated_v1 def testResultNameMatchesRequested(self): with variable_scope.variable_scope( "scope0", partitioner=axis0_into2_partitioner): @@ -1404,6 +1436,14 @@ class VariableScopeWithPartitioningTest(test.TestCase): v_reused = variable_scope.get_variable("name0") self.assertEqual(v, v_reused) + def testNoReuseInEagerByDefault(self): + with context.eager_mode(): + with variable_scope.variable_scope( + "scope0", partitioner=axis0_into2_partitioner): + v1 = variable_scope.get_variable("name0", shape=(3, 1, 1)) + v2 = variable_scope.get_variable("name0", shape=(3, 1, 1)) + self.assertIsNot(v1, v2) + @test_util.run_in_graph_and_eager_modes @run_inside_wrap_function_in_eager_mode def testPropagatePartitionerOnReopening(self): @@ -1415,6 +1455,7 @@ class VariableScopeWithPartitioningTest(test.TestCase): # TODO(mihaimaruseac): Not converted to use wrap_function because of # obtaining different results in the eager case compared to the graph one + @test_util.run_deprecated_v1 def testScalarIgnoresPartitioner(self): with variable_scope.variable_scope( "scope0", partitioner=axis0_into2_partitioner): @@ -1459,6 +1500,10 @@ class VariableScopeWithPartitioningTest(test.TestCase): def testPartitionConcatenatesAlongCorrectAxisResource(self): self._testPartitionConcatenatesAlongCorrectAxis(use_resource=True) + def testPartitionConcatenatesAlongCorrectAxisResourceInEager(self): + with context.eager_mode(): + self._testPartitionConcatenatesAlongCorrectAxis(use_resource=True) + class VariableScopeWithCustomGetterTest(test.TestCase): @@ -1550,6 +1595,7 @@ class VariableScopeWithCustomGetterTest(test.TestCase): # dtype=float32> cannot be interpreted as a Tensor. (Tensor # Tensor("custom_getter/add:0", shape=(1, 2, 3), dtype=float32) is not an # element of this graph.) + @test_util.run_deprecated_v1 def testGetterThatCreatesTwoVariablesAndSumsThem(self): def custom_getter(getter, name, *args, **kwargs): @@ -1569,7 +1615,7 @@ class VariableScopeWithCustomGetterTest(test.TestCase): self.assertEqual("custom_getter/add:0", v.name) with self.cached_session() as sess: variables_lib.global_variables_initializer().run() - np_vars, np_v = sess.run([true_vars, v]) + np_vars, np_v = self.evaluate([true_vars, v]) self.assertAllClose(np_v, sum(np_vars)) # TODO(mihaimaruseac): Not converted to use wrap_function because of @@ -1577,6 +1623,7 @@ class VariableScopeWithCustomGetterTest(test.TestCase): # dtype=float32> cannot be interpreted as a Tensor. (Tensor # Tensor("sum_getter_2/add:0", shape=(1, 2, 3), dtype=float32) is not an # element of this graph.) + @test_util.run_deprecated_v1 def testNestedCustomGetters(self): def sum_getter(getter, name, *args, **kwargs): @@ -1614,7 +1661,7 @@ class VariableScopeWithCustomGetterTest(test.TestCase): with self.cached_session() as sess: variables_lib.global_variables_initializer().run() - np_vars, np_v = sess.run([true_vars, v]) + np_vars, np_v = self.evaluate([true_vars, v]) # take products of sums of products self.assertAllClose( np_v, (((np_vars[0] * np_vars[1]) + (np_vars[2] * np_vars[3])) + ( diff --git a/tensorflow/python/kernel_tests/variables_test.py b/tensorflow/python/kernel_tests/variables_test.py index b3eebf8316..08d885e8a8 100644 --- a/tensorflow/python/kernel_tests/variables_test.py +++ b/tensorflow/python/kernel_tests/variables_test.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import functools import operator import numpy as np @@ -27,6 +28,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gen_state_ops @@ -41,6 +43,7 @@ from tensorflow.python.util import compat class VariablesTestCase(test.TestCase): + @test_util.run_deprecated_v1 def testInitialization(self): with self.cached_session(): var0 = variables.VariableV1(0.0) @@ -58,16 +61,17 @@ class VariablesTestCase(test.TestCase): self.assertEqual([], var1.shape) with self.assertRaisesOpError("Attempting to use uninitialized value"): - var0.eval() + self.evaluate(var0) with self.assertRaisesOpError("Attempting to use uninitialized value"): - var1.eval() + self.evaluate(var1) variables.global_variables_initializer().run() - self.assertAllClose(0.0, var0.eval()) - self.assertAllClose(1.1, var1.eval()) + self.assertAllClose(0.0, self.evaluate(var0)) + self.assertAllClose(1.1, self.evaluate(var1)) + @test_util.run_deprecated_v1 def testInitializationOrder(self): with self.cached_session(): rnd = variables.Variable(random_ops.random_uniform([3, 6]), name="rnd") @@ -94,8 +98,9 @@ class VariablesTestCase(test.TestCase): variables.global_variables_initializer().run() - self.assertAllClose(rnd.eval(), dep.eval()) - self.assertAllClose(rnd.eval() + dep.eval() + 2.0, depdep.eval()) + self.assertAllClose(rnd.eval(), self.evaluate(dep)) + self.assertAllClose(rnd.eval() + self.evaluate(dep) + 2.0, + self.evaluate(depdep)) def testIterable(self): with self.assertRaisesRegexp(TypeError, "not iterable"): @@ -105,6 +110,7 @@ class VariablesTestCase(test.TestCase): for _ in variables.Variable([0.0, 1.0]): pass + @test_util.run_deprecated_v1 def testAssignments(self): with self.cached_session(): var = variables.Variable(0.0) @@ -112,17 +118,18 @@ class VariablesTestCase(test.TestCase): minus_one = var.assign_sub(2.0) four = var.assign(4.0) variables.global_variables_initializer().run() - self.assertAllClose(0.0, var.eval()) + self.assertAllClose(0.0, self.evaluate(var)) - self.assertAllClose(1.0, plus_one.eval()) - self.assertAllClose(1.0, var.eval()) + self.assertAllClose(1.0, self.evaluate(plus_one)) + self.assertAllClose(1.0, self.evaluate(var)) - self.assertAllClose(-1.0, minus_one.eval()) - self.assertAllClose(-1.0, var.eval()) + self.assertAllClose(-1.0, self.evaluate(minus_one)) + self.assertAllClose(-1.0, self.evaluate(var)) - self.assertAllClose(4.0, four.eval()) - self.assertAllClose(4.0, var.eval()) + self.assertAllClose(4.0, self.evaluate(four)) + self.assertAllClose(4.0, self.evaluate(var)) + @test_util.run_deprecated_v1 def testResourceAssignments(self): with self.session(use_gpu=True): var = resource_variable_ops.ResourceVariable(0.0) @@ -130,16 +137,16 @@ class VariablesTestCase(test.TestCase): minus_one = var.assign_sub(2.0) four = var.assign(4.0) variables.global_variables_initializer().run() - self.assertAllClose(0.0, var.eval()) + self.assertAllClose(0.0, self.evaluate(var)) - plus_one.eval() - self.assertAllClose(1.0, var.eval()) + self.evaluate(plus_one) + self.assertAllClose(1.0, self.evaluate(var)) - minus_one.eval() - self.assertAllClose(-1.0, var.eval()) + self.evaluate(minus_one) + self.assertAllClose(-1.0, self.evaluate(var)) - four.eval() - self.assertAllClose(4.0, var.eval()) + self.evaluate(four) + self.assertAllClose(4.0, self.evaluate(var)) def testZeroSizeStringAssign(self): with self.cached_session() as sess: @@ -148,10 +155,10 @@ class VariablesTestCase(test.TestCase): name="foo", trainable=False, collections=[ops.GraphKeys.LOCAL_VARIABLES]) - sess.run(variables.local_variables_initializer()) + self.evaluate(variables.local_variables_initializer()) old_value = array.value() copy_op = array.assign(old_value) - self.assertEqual([], list(sess.run(copy_op))) + self.assertEqual([], list(self.evaluate(copy_op))) def _countUpToTest(self, dtype): with self.cached_session(): @@ -160,31 +167,34 @@ class VariablesTestCase(test.TestCase): count_up_to = var.count_up_to(3) variables.global_variables_initializer().run() - self.assertEqual(0, var.eval()) + self.assertEqual(0, self.evaluate(var)) - self.assertEqual(0, count_up_to.eval()) - self.assertEqual(1, var.eval()) + self.assertEqual(0, self.evaluate(count_up_to)) + self.assertEqual(1, self.evaluate(var)) - self.assertEqual(1, count_up_to.eval()) - self.assertEqual(2, var.eval()) + self.assertEqual(1, self.evaluate(count_up_to)) + self.assertEqual(2, self.evaluate(var)) - self.assertEqual(2, count_up_to.eval()) - self.assertEqual(3, var.eval()) + self.assertEqual(2, self.evaluate(count_up_to)) + self.assertEqual(3, self.evaluate(var)) with self.assertRaisesOpError("Reached limit of 3"): - count_up_to.eval() - self.assertEqual(3, var.eval()) + self.evaluate(count_up_to) + self.assertEqual(3, self.evaluate(var)) with self.assertRaisesOpError("Reached limit of 3"): - count_up_to.eval() - self.assertEqual(3, var.eval()) + self.evaluate(count_up_to) + self.assertEqual(3, self.evaluate(var)) + @test_util.run_deprecated_v1 def testCountUpToInt32(self): self._countUpToTest(dtypes.int32) + @test_util.run_deprecated_v1 def testCountUpToInt64(self): self._countUpToTest(dtypes.int64) + @test_util.run_deprecated_v1 def testControlDepsNone(self): with self.cached_session(): c = constant_op.constant(1.0) @@ -198,6 +208,7 @@ class VariablesTestCase(test.TestCase): self.assertEqual([], var_x.value().op.control_inputs) self.assertEqual([], var_x._ref().op.control_inputs) # pylint: disable=protected-access + @test_util.run_deprecated_v1 def testControlFlow(self): with self.cached_session() as sess: v0 = variables.Variable(0, name="v0") @@ -220,20 +231,21 @@ class VariablesTestCase(test.TestCase): v2 = var_dict["v2"] # We should be able to initialize and run v1 and v2 without initializing # v0, even if the variable was created with a control dep on v0. - sess.run(v1.initializer) - self.assertEqual([1], sess.run(v1)) - sess.run(v2.initializer) - self.assertEqual([2], sess.run(v2)) + self.evaluate(v1.initializer) + self.assertEqual([1], self.evaluate(v1)) + self.evaluate(v2.initializer) + self.assertEqual([2], self.evaluate(v2)) # v0 should still be uninitialized. with self.assertRaisesRegexp(errors_impl.OpError, "uninitialized"): - sess.run(v0) + self.evaluate(v0) # We should not be able to run 'add' yet. with self.assertRaisesRegexp(errors_impl.OpError, "uninitialized"): - sess.run(add) + self.evaluate(add) # If we initialize v0 we should be able to run 'add'. - sess.run(v0.initializer) - sess.run(add) + self.evaluate(v0.initializer) + self.evaluate(add) + @test_util.run_deprecated_v1 def testControlFlowInitialization(self): """Expects an error if an initializer is in a control-flow scope.""" def cond(i, _): @@ -247,15 +259,17 @@ class VariablesTestCase(test.TestCase): with self.assertRaisesRegexp(ValueError, "inside a control-flow"): control_flow_ops.while_loop(cond, body, [0, 0]) + @test_util.run_deprecated_v1 def testUseVariableAsTensor(self): with self.cached_session(): var_x = variables.Variable(2.0) var_y = variables.Variable(3.0) variables.global_variables_initializer().run() - self.assertAllClose(2.0, var_x.eval()) - self.assertAllClose(3.0, var_y.eval()) + self.assertAllClose(2.0, self.evaluate(var_x)) + self.assertAllClose(3.0, self.evaluate(var_y)) self.assertAllClose(5.0, math_ops.add(var_x, var_y).eval()) + @test_util.run_deprecated_v1 def testZeroSizeVarSameAsConst(self): with self.cached_session(): zero_size_var = variables.Variable(array_ops.zeros([0, 2])) @@ -264,10 +278,11 @@ class VariablesTestCase(test.TestCase): const_mul = math_ops.matmul( zero_size_const, zero_size_const, transpose_b=True) variables.global_variables_initializer().run() - variable_output = variable_mul.eval() + variable_output = self.evaluate(variable_mul) self.assertAllClose(const_mul.eval(), variable_output) self.assertAllClose([[0., 0.], [0., 0.]], variable_output) + @test_util.run_deprecated_v1 def testCachingDevice(self): with self.cached_session(): var = variables.Variable(2.0) @@ -278,6 +293,7 @@ class VariablesTestCase(test.TestCase): self.assertFalse(var_cached.device.startswith("/job:foo")) self.assertTrue(var_cached.value().device.startswith("/job:foo")) + @test_util.run_deprecated_v1 def testCollections(self): with self.cached_session(): var_x = variables.VariableV1(2.0) @@ -293,6 +309,7 @@ class VariablesTestCase(test.TestCase): variables.global_variables()) self.assertEqual([var_x, var_z, var_t], variables.trainable_variables()) + @test_util.run_deprecated_v1 def testCollectionsWithScope(self): with self.cached_session(): with ops.name_scope("scope_1"): @@ -308,6 +325,13 @@ class VariablesTestCase(test.TestCase): self.assertEqual([var_x], variables.trainable_variables("scope_1")) self.assertEqual([var_y], variables.trainable_variables("scope_2")) + def testOperatorWrapping(self): + for attr in functools.WRAPPER_ASSIGNMENTS: + self.assertEqual( + getattr(variables.Variable.__add__, attr), + getattr(ops.Tensor.__add__, attr)) + + @test_util.run_deprecated_v1 def testOperators(self): with self.cached_session(): var_f = variables.Variable([2.0]) @@ -349,54 +373,46 @@ class VariablesTestCase(test.TestCase): rmatmul = var_m.__rmatmul__([[10.0], [20.0]]) variables.global_variables_initializer().run() - self.assertAllClose([2.0], add.eval()) - self.assertAllClose([3.0], radd.eval()) - self.assertAllClose([1.0], sub.eval()) - self.assertAllClose([-1.0], rsub.eval()) - self.assertAllClose([20.0], mul.eval()) - self.assertAllClose([20.0], rmul.eval()) - self.assertAllClose([0.2], div.eval()) - self.assertAllClose([5.0], rdiv.eval()) - self.assertAllClose([-2.0], neg.eval()) - self.assertAllClose([2.0], abs_v.eval()) - self.assertAllClose([True], lt.eval()) - self.assertAllClose([False], rlt.eval()) - self.assertAllClose([True], le.eval()) - self.assertAllClose([True], rle.eval()) - self.assertAllClose([False], gt.eval()) - self.assertAllClose([True], rgt.eval()) - self.assertAllClose([True], ge.eval()) - self.assertAllClose([True], rge.eval()) - - self.assertAllClose([6], mod.eval()) - self.assertAllClose([3], rmod.eval()) - - self.assertAllClose([True, False], and_v.eval()) - self.assertAllClose([True, True], or_v.eval()) - self.assertAllClose([True, False], xor_v.eval()) - self.assertAllClose([False, True], invert_v.eval()) - - self.assertAllClose(rnd[2, 0:0], slice_v.eval()) - - self.assertAllClose([[80.0]], matmul.eval()) - self.assertAllClose([[20.0, 30.0], [40.0, 60.0]], rmatmul.eval()) - + self.assertAllClose([2.0], self.evaluate(add)) + self.assertAllClose([3.0], self.evaluate(radd)) + self.assertAllClose([1.0], self.evaluate(sub)) + self.assertAllClose([-1.0], self.evaluate(rsub)) + self.assertAllClose([20.0], self.evaluate(mul)) + self.assertAllClose([20.0], self.evaluate(rmul)) + self.assertAllClose([0.2], self.evaluate(div)) + self.assertAllClose([5.0], self.evaluate(rdiv)) + self.assertAllClose([-2.0], self.evaluate(neg)) + self.assertAllClose([2.0], self.evaluate(abs_v)) + self.assertAllClose([True], self.evaluate(lt)) + self.assertAllClose([False], self.evaluate(rlt)) + self.assertAllClose([True], self.evaluate(le)) + self.assertAllClose([True], self.evaluate(rle)) + self.assertAllClose([False], self.evaluate(gt)) + self.assertAllClose([True], self.evaluate(rgt)) + self.assertAllClose([True], self.evaluate(ge)) + self.assertAllClose([True], self.evaluate(rge)) + + self.assertAllClose([6], self.evaluate(mod)) + self.assertAllClose([3], self.evaluate(rmod)) + + self.assertAllClose([True, False], self.evaluate(and_v)) + self.assertAllClose([True, True], self.evaluate(or_v)) + self.assertAllClose([True, False], self.evaluate(xor_v)) + self.assertAllClose([False, True], self.evaluate(invert_v)) + + self.assertAllClose(rnd[2, 0:0], self.evaluate(slice_v)) + + self.assertAllClose([[80.0]], self.evaluate(matmul)) + self.assertAllClose([[20.0, 30.0], [40.0, 60.0]], self.evaluate(rmatmul)) + + @test_util.run_deprecated_v1 def testSession(self): with self.cached_session() as sess: var = variables.Variable([1, 12]) variables.global_variables_initializer().run() - self.assertAllClose([1, 12], sess.run(var)) - - def testDevicePlacement(self): - with self.cached_session() as sess: - with ops.device("/cpu:0"): - var = variables.Variable([1, 12]) - init_value = var.initialized_value() - init_op = variables.global_variables_initializer() - self.assertEqual(var.op.device, init_value.device) - self.assertEqual(var.op.device, init_op.device) - sess.run(init_op) + self.assertAllClose([1, 12], self.evaluate(var)) + @test_util.run_deprecated_v1 def testColocation(self): with ops.device("/job:ps"): var = variables.VariableV1(0, name="v") @@ -405,6 +421,7 @@ class VariablesTestCase(test.TestCase): self.assertDeviceEqual("/job:ps", assign_op.device) self.assertEqual([b"loc:@v"], assign_op.op.colocation_groups()) + @test_util.run_deprecated_v1 def testInitializerFunction(self): value = [[-42], [133.7]] shape = [2, 1] @@ -416,7 +433,7 @@ class VariablesTestCase(test.TestCase): self.assertEqual(shape, v1.shape) self.assertAllClose(value, v1.initial_value.eval()) with self.assertRaises(errors_impl.FailedPreconditionError): - v1.eval() + self.evaluate(v1) v2 = variables.Variable( math_ops.negative(v1.initialized_value()), dtype=dtypes.float32) @@ -425,9 +442,9 @@ class VariablesTestCase(test.TestCase): self.assertAllClose(np.negative(value), v2.initial_value.eval()) with self.assertRaises(errors_impl.FailedPreconditionError): - v2.eval() + self.evaluate(v2) variables.global_variables_initializer().run() - self.assertAllClose(np.negative(value), v2.eval()) + self.assertAllClose(np.negative(value), self.evaluate(v2)) def testConstraintArg(self): constraint = lambda x: x @@ -442,6 +459,7 @@ class VariablesTestCase(test.TestCase): lambda: constant_op.constant(1.), constraint=constraint) + @test_util.run_deprecated_v1 def testNoRefDataRace(self): with self.cached_session(): a = variables.Variable([1, 2, 3], dtype=dtypes.float32) @@ -452,6 +470,7 @@ class VariablesTestCase(test.TestCase): self.assertAllEqual(b.eval(), [3, 4, 5]) self.assertAllEqual(c.eval(), [5, 6, 7]) + @test_util.run_deprecated_v1 def testInitializerFunctionDevicePlacement(self): with self.cached_session(): initializer = lambda: constant_op.constant(42.0) @@ -470,6 +489,7 @@ class VariablesTestCase(test.TestCase): for i in v2.initializer.inputs: self.assertEqual(expected_group_v2, i.op.colocation_groups()) + @test_util.run_deprecated_v1 def testVariableDefInitializedInstances(self): with ops.Graph().as_default(), self.cached_session() as sess: v_def = variables.Variable( @@ -478,11 +498,11 @@ class VariablesTestCase(test.TestCase): with ops.Graph().as_default(), self.cached_session() as sess: # v describes a VariableDef-based variable without an initial value. v = variables.Variable(variable_def=v_def) - self.assertEqual(3.0, sess.run(v.initialized_value())) + self.assertEqual(3.0, self.evaluate(v.initialized_value())) # initialized_value should not rerun the initializer_op if the variable # has already been initialized elsewhere. - sess.run(v.assign(1.0)) + self.evaluate(v.assign(1.0)) self.assertEqual(1.0, v.initialized_value().eval()) v_def.ClearField("initial_value_name") @@ -494,7 +514,7 @@ class VariablesTestCase(test.TestCase): self.assertProtoEquals(v_def, v.to_proto()) # But attempts to use initialized_value will result in errors. with self.assertRaises(ValueError): - sess.run(v.initialized_value()) + self.evaluate(v.initialized_value()) def testTrainableInProto(self): with ops.Graph().as_default(): @@ -513,14 +533,16 @@ class VariablesTestCase(test.TestCase): variables.Variable(variable_def=trainable_variable.to_proto()) .trainable) + @test_util.run_deprecated_v1 def testLoad(self): with self.cached_session(): var = variables.Variable(np.zeros((5, 5), np.float32)) variables.global_variables_initializer().run() var.load(np.ones((5, 5), np.float32)) - self.assertAllClose(np.ones((5, 5), np.float32), var.eval()) + self.assertAllClose(np.ones((5, 5), np.float32), self.evaluate(var)) + @test_util.run_deprecated_v1 def testRepr(self): var = variables.VariableV1(np.zeros((5, 5), np.float32), name="noop") self.assertEqual( @@ -542,7 +564,7 @@ class IsInitializedTest(test.TestCase): def testNoVars(self): with ops.Graph().as_default(), self.cached_session() as sess: uninited = variables.report_uninitialized_variables() - self.assertEqual(0, sess.run(uninited).size) + self.assertEqual(0, self.evaluate(uninited).size) def testAssertVariablesInitialized(self): with ops.Graph().as_default(), self.cached_session() as sess: @@ -550,27 +572,28 @@ class IsInitializedTest(test.TestCase): w = variables.Variable([3, 4], name="w") _ = v, w uninited = variables.report_uninitialized_variables() - self.assertAllEqual(np.array([b"v", b"w"]), sess.run(uninited)) + self.assertAllEqual(np.array([b"v", b"w"]), self.evaluate(uninited)) variables.global_variables_initializer().run() - self.assertEqual(0, sess.run(uninited).size) + self.assertEqual(0, self.evaluate(uninited).size) + @test_util.run_deprecated_v1 def testVariableList(self): with ops.Graph().as_default(), self.cached_session() as sess: v = variables.VariableV1([1, 2], name="v") w = variables.VariableV1([3, 4], name="w") uninited = variables.report_uninitialized_variables() - self.assertAllEqual(np.array([b"v", b"w"]), sess.run(uninited)) - sess.run(w.initializer) - self.assertAllEqual(np.array([b"v"]), sess.run(uninited)) + self.assertAllEqual(np.array([b"v", b"w"]), self.evaluate(uninited)) + self.evaluate(w.initializer) + self.assertAllEqual(np.array([b"v"]), self.evaluate(uninited)) v.initializer.run() - self.assertEqual(0, sess.run(uninited).size) + self.assertEqual(0, self.evaluate(uninited).size) def testZeroSizeVarInitialized(self): with ops.Graph().as_default(), self.cached_session() as sess: v = variables.Variable(array_ops.zeros([0, 2]), name="v") uninited = variables.report_uninitialized_variables() v.initializer.run() # not strictly necessary - self.assertEqual(0, sess.run(uninited).size) + self.assertEqual(0, self.evaluate(uninited).size) def testTrainingWithZeroSizeVar(self): with ops.Graph().as_default(), self.cached_session() as sess: @@ -581,8 +604,8 @@ class IsInitializedTest(test.TestCase): variables.global_variables_initializer().run() do_opt = gradient_descent.GradientDescentOptimizer(0.1).minimize( objective) - sess.run([do_opt]) - self.assertAllClose([[0.9, 0.9], [0.9, 0.9]], b.eval()) + self.evaluate([do_opt]) + self.assertAllClose([[0.9, 0.9], [0.9, 0.9]], self.evaluate(b)) class ObsoleteIsInitializedTest(test.TestCase): @@ -591,6 +614,7 @@ class ObsoleteIsInitializedTest(test.TestCase): with ops.Graph().as_default(): self.assertEqual(None, variables.assert_variables_initialized()) + @test_util.run_deprecated_v1 def testVariables(self): with ops.Graph().as_default(), self.cached_session() as sess: v = variables.VariableV1([1, 2]) @@ -598,10 +622,11 @@ class ObsoleteIsInitializedTest(test.TestCase): _ = v, w inited = variables.assert_variables_initialized() with self.assertRaisesOpError("Attempting to use uninitialized value"): - sess.run(inited) + self.evaluate(inited) variables.global_variables_initializer().run() - sess.run(inited) + self.evaluate(inited) + @test_util.run_deprecated_v1 def testVariableList(self): with ops.Graph().as_default(), self.cached_session() as sess: v = variables.VariableV1([1, 2]) @@ -609,7 +634,7 @@ class ObsoleteIsInitializedTest(test.TestCase): inited = variables.assert_variables_initialized([v]) with self.assertRaisesOpError("Attempting to use uninitialized value"): inited.op.run() - sess.run(w.initializer) + self.evaluate(w.initializer) with self.assertRaisesOpError("Attempting to use uninitialized value"): inited.op.run() v.initializer.run() @@ -744,34 +769,34 @@ class PartitionedVariableTest(test.TestCase): variables.global_variables_initializer().run() self.assertEqual([1.0], plus_delta[0].eval()) - self.assertEqual([1.0], v0.eval()) + self.assertEqual([1.0], self.evaluate(v0)) self.assertEqual([3.0], plus_delta[1].eval()) - self.assertEqual([3.0], v1.eval()) + self.assertEqual([3.0], self.evaluate(v1)) self.assertEqual([-2.0], minus_delta[0].eval()) - self.assertEqual([-2.0], v0.eval()) + self.assertEqual([-2.0], self.evaluate(v0)) self.assertEqual([-1.0], minus_delta[1].eval()) - self.assertEqual([-1.0], v1.eval()) + self.assertEqual([-1.0], self.evaluate(v1)) self.assertEqual([1.0], assign_ones[0].eval()) - self.assertEqual([1.0], v0.eval()) + self.assertEqual([1.0], self.evaluate(v0)) self.assertEqual([1.0], assign_ones[1].eval()) - self.assertEqual([1.0], v1.eval()) + self.assertEqual([1.0], self.evaluate(v1)) self.assertEqual([2.0], assign_list[0].eval()) - self.assertEqual([2.0], v2.eval()) + self.assertEqual([2.0], self.evaluate(v2)) self.assertEqual([3.0], assign_list[1].eval()) - self.assertEqual([3.0], v3.eval()) + self.assertEqual([3.0], self.evaluate(v3)) self.assertEqual([3.0], assign_part_value[0].eval()) - self.assertEqual([3.0], v2.eval()) + self.assertEqual([3.0], self.evaluate(v2)) self.assertEqual([4.0], assign_part_value[1].eval()) - self.assertEqual([4.0], v3.eval()) + self.assertEqual([4.0], self.evaluate(v3)) self.assertEqual([2.0], assign_part_var[0].eval()) - self.assertEqual([2.0], v2.eval()) + self.assertEqual([2.0], self.evaluate(v2)) self.assertEqual([3.0], assign_part_var[1].eval()) - self.assertEqual([3.0], v3.eval()) + self.assertEqual([3.0], self.evaluate(v3)) class VariableContainerTest(test.TestCase): diff --git a/tensorflow/python/kernel_tests/weights_broadcast_test.py b/tensorflow/python/kernel_tests/weights_broadcast_test.py index 85f9abc69f..677d8f2f22 100644 --- a/tensorflow/python/kernel_tests/weights_broadcast_test.py +++ b/tensorflow/python/kernel_tests/weights_broadcast_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import dtypes as dtypes_lib from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import weights_broadcast_ops from tensorflow.python.platform import test @@ -51,40 +52,48 @@ class AssertBroadcastableTest(test.TestCase): values_placeholder: values, }) + @test_util.run_deprecated_v1 def testScalar(self): self._test_valid(weights=5, values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def test1x1x1(self): self._test_valid( weights=np.asarray((5,)).reshape((1, 1, 1)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def test1x1xN(self): self._test_valid( weights=np.asarray((5, 7, 11, 3)).reshape((1, 1, 4)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def test1xNx1(self): self._test_valid( weights=np.asarray((5, 11)).reshape((1, 2, 1)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def test1xNxN(self): self._test_valid( weights=np.asarray((5, 7, 11, 3, 2, 13, 7, 5)).reshape((1, 2, 4)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testNx1x1(self): self._test_valid( weights=np.asarray((5, 7, 11)).reshape((3, 1, 1)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testNx1xN(self): self._test_valid( weights=np.asarray(( 5, 7, 11, 3, 2, 12, 7, 5, 2, 17, 11, 3)).reshape((3, 1, 4)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testNxNxN(self): self._test_valid( weights=np.asarray(( @@ -107,29 +116,35 @@ class AssertBroadcastableTest(test.TestCase): values_placeholder: values, }) + @test_util.run_deprecated_v1 def testInvalid1(self): self._test_invalid(weights=np.asarray((5,)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalid1x1(self): self._test_invalid( weights=np.asarray((5,)).reshape((1, 1)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidPrefixMatch(self): self._test_invalid( weights=np.asarray((5, 7, 11, 3, 2, 12)).reshape((3, 2)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidSuffixMatch(self): self._test_invalid( weights=np.asarray((5, 7, 11, 3, 2, 12, 7, 5)).reshape((2, 4)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidOnesExtraDim(self): self._test_invalid( weights=np.asarray((5,)).reshape((1, 1, 1, 1)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidPrefixMatchExtraDim(self): self._test_invalid( weights=np.asarray(( @@ -137,6 +152,7 @@ class AssertBroadcastableTest(test.TestCase): 2, 17, 11, 3, 5, 7, 11, 3, 2, 12, 7, 5)).reshape((3, 2, 4, 1)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidSuffixMatchExtraDim(self): self._test_invalid( weights=np.asarray(( @@ -158,24 +174,27 @@ class BroadcastWeightsTest(test.TestCase): dynamic_op = weights_broadcast_ops.broadcast_weights( weights=weights_placeholder, values=values_placeholder) with self.cached_session(): - self.assertAllEqual(expected, static_op.eval()) + self.assertAllEqual(expected, self.evaluate(static_op)) self.assertAllEqual(expected, dynamic_op.eval(feed_dict={ weights_placeholder: weights, values_placeholder: values, })) + @test_util.run_deprecated_v1 def testScalar(self): self._test_valid( weights=5, values=_test_values((3, 2, 4)), expected=5 * np.ones((3, 2, 4))) + @test_util.run_deprecated_v1 def test1x1x1(self): self._test_valid( weights=np.asarray((5,)).reshape((1, 1, 1)), values=_test_values((3, 2, 4)), expected=5 * np.ones((3, 2, 4))) + @test_util.run_deprecated_v1 def test1x1xN(self): weights = np.asarray((5, 7, 11, 3)).reshape((1, 1, 4)) self._test_valid( @@ -183,6 +202,7 @@ class BroadcastWeightsTest(test.TestCase): values=_test_values((3, 2, 4)), expected=np.tile(weights, reps=(3, 2, 1))) + @test_util.run_deprecated_v1 def test1xNx1(self): weights = np.asarray((5, 11)).reshape((1, 2, 1)) self._test_valid( @@ -190,6 +210,7 @@ class BroadcastWeightsTest(test.TestCase): values=_test_values((3, 2, 4)), expected=np.tile(weights, reps=(3, 1, 4))) + @test_util.run_deprecated_v1 def test1xNxN(self): weights = np.asarray((5, 7, 11, 3, 2, 13, 7, 5)).reshape((1, 2, 4)) self._test_valid( @@ -197,6 +218,7 @@ class BroadcastWeightsTest(test.TestCase): values=_test_values((3, 2, 4)), expected=np.tile(weights, reps=(3, 1, 1))) + @test_util.run_deprecated_v1 def testNx1x1(self): weights = np.asarray((5, 7, 11)).reshape((3, 1, 1)) self._test_valid( @@ -204,6 +226,7 @@ class BroadcastWeightsTest(test.TestCase): values=_test_values((3, 2, 4)), expected=np.tile(weights, reps=(1, 2, 4))) + @test_util.run_deprecated_v1 def testNx1xN(self): weights = np.asarray(( 5, 7, 11, 3, 2, 12, 7, 5, 2, 17, 11, 3)).reshape((3, 1, 4)) @@ -212,6 +235,7 @@ class BroadcastWeightsTest(test.TestCase): values=_test_values((3, 2, 4)), expected=np.tile(weights, reps=(1, 2, 1))) + @test_util.run_deprecated_v1 def testNxNxN(self): weights = np.asarray(( 5, 7, 11, 3, 2, 12, 7, 5, 2, 17, 11, 3, @@ -234,29 +258,35 @@ class BroadcastWeightsTest(test.TestCase): values_placeholder: values, }) + @test_util.run_deprecated_v1 def testInvalid1(self): self._test_invalid(weights=np.asarray((5,)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalid1x1(self): self._test_invalid( weights=np.asarray((5,)).reshape((1, 1)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidPrefixMatch(self): self._test_invalid( weights=np.asarray((5, 7, 11, 3, 2, 12)).reshape((3, 2)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidSuffixMatch(self): self._test_invalid( weights=np.asarray((5, 7, 11, 3, 2, 12, 7, 5)).reshape((2, 4)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidOnesExtraDim(self): self._test_invalid( weights=np.asarray((5,)).reshape((1, 1, 1, 1)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidPrefixMatchExtraDim(self): self._test_invalid( weights=np.asarray(( @@ -264,6 +294,7 @@ class BroadcastWeightsTest(test.TestCase): 2, 17, 11, 3, 5, 7, 11, 3, 2, 12, 7, 5)).reshape((3, 2, 4, 1)), values=_test_values((3, 2, 4))) + @test_util.run_deprecated_v1 def testInvalidSuffixMatchExtraDim(self): self._test_invalid( weights=np.asarray(( diff --git a/tensorflow/python/kernel_tests/where_op_test.py b/tensorflow/python/kernel_tests/where_op_test.py index fca45c3ece..56c1390411 100644 --- a/tensorflow/python/kernel_tests/where_op_test.py +++ b/tensorflow/python/kernel_tests/where_op_test.py @@ -27,6 +27,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import resource_variable_ops @@ -41,11 +42,11 @@ class WhereOpTest(test.TestCase): ans = array_ops.where(x) self.assertEqual([None, x.ndim], ans.get_shape().as_list()) if expected_err_re is None: - tf_ans = ans.eval() + tf_ans = self.evaluate(ans) self.assertAllClose(tf_ans, truth, atol=1e-10) else: with self.assertRaisesOpError(expected_err_re): - ans.eval() + self.evaluate(ans) def testWrongNumbers(self): with self.session(use_gpu=True): @@ -54,6 +55,7 @@ class WhereOpTest(test.TestCase): with self.assertRaises(ValueError): array_ops.where([False, True], None, [1, 2]) + @test_util.run_deprecated_v1 def testBasicVec(self): x = np.asarray([True, False]) truth = np.asarray([[0]], dtype=np.int64) @@ -67,11 +69,13 @@ class WhereOpTest(test.TestCase): truth = np.asarray([[2], [4]], dtype=np.int64) self._testWhere(x, truth) + @test_util.run_deprecated_v1 def testRandomVec(self): x = np.random.rand(1000000) > 0.5 truth = np.vstack([np.where(x)[0].astype(np.int64)]).T self._testWhere(x, truth) + @test_util.run_deprecated_v1 def testBasicMat(self): x = np.asarray([[True, False], [True, False]]) @@ -80,6 +84,7 @@ class WhereOpTest(test.TestCase): self._testWhere(x, truth) + @test_util.run_deprecated_v1 def testBasic3Tensor(self): x = np.asarray([[[True, False], [True, False]], [[False, True], [False, True]], @@ -99,36 +104,47 @@ class WhereOpTest(test.TestCase): truth = np.vstack(truth).T # Convert to [num_true, indices]. self._testWhere(x, truth, expected_err_re) + @test_util.run_deprecated_v1 def testRandomBool(self): self._testRandom(np.bool) + @test_util.run_deprecated_v1 def testRandomInt32(self): self._testRandom(np.int32) + @test_util.run_deprecated_v1 def testRandomInt64(self): self._testRandom(np.int64) + @test_util.run_deprecated_v1 def testRandomFloat(self): self._testRandom(np.float32) + @test_util.run_deprecated_v1 def testRandomDouble(self): self._testRandom(np.float64) + @test_util.run_deprecated_v1 def testRandomComplex64(self): self._testRandom(np.complex64) + @test_util.run_deprecated_v1 def testRandomComplex128(self): self._testRandom(np.complex128) + @test_util.run_deprecated_v1 def testRandomUint8(self): self._testRandom(np.uint8) + @test_util.run_deprecated_v1 def testRandomInt8(self): self._testRandom(np.int8) + @test_util.run_deprecated_v1 def testRandomInt16(self): self._testRandom(np.int16) + @test_util.run_deprecated_v1 def testThreeArgument(self): x = np.array([[-2, 3, -1], [1, -3, -3]]) np_val = np.where(x > 0, x * x, -x) @@ -136,6 +152,7 @@ class WhereOpTest(test.TestCase): tf_val = array_ops.where(constant_op.constant(x) > 0, x * x, -x).eval() self.assertAllEqual(tf_val, np_val) + @test_util.run_deprecated_v1 def testBatchSelect(self): x = np.array([[-2, 3, -1] * 64, [1, -3, -3] * 64] * 8192) # [16384, 192] c_mat = np.array([[False] * 192, [True] * 192] * 8192) # [16384, 192] diff --git a/tensorflow/python/kernel_tests/while_v2_test.py b/tensorflow/python/kernel_tests/while_v2_test.py index dc1bcb78b8..09cbeb1a0d 100644 --- a/tensorflow/python/kernel_tests/while_v2_test.py +++ b/tensorflow/python/kernel_tests/while_v2_test.py @@ -20,14 +20,15 @@ from __future__ import print_function from absl.testing import parameterized +from tensorflow.core.protobuf import config_pb2 from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import meta_graph from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.grappler import tf_optimizer from tensorflow.python.ops import array_ops -from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import functional_ops from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import list_ops @@ -42,14 +43,29 @@ from tensorflow.python.platform import test class WhileV2Test(test.TestCase, parameterized.TestCase): + @test_util.run_deprecated_v1 def testSingleLoopVar(self): x = constant_op.constant(2.) - ret = while_loop_v2(lambda v: v < 8., lambda v: v * v, [x]) + ret = while_loop_v2( + lambda v: v < 8., lambda v: v * v, [x], return_same_structure=False) grad = gradients_impl.gradients(ret, [x]) with self.cached_session() as sess: - self.assertEqual(sess.run(ret), 16.) + self.assertEqual(self.evaluate(ret), 16.) + self.assertSequenceEqual(self.evaluate(grad), [32.]) + + def testReturnSameStructureTrue(self): + x = constant_op.constant(2.) + ret = while_loop_v2( + lambda v: v < 8., lambda v: v * v, [x], return_same_structure=True) + grad = gradients_impl.gradients(ret, [x]) + with self.cached_session() as sess: + eval_result = sess.run(ret) + self.assertIsInstance(eval_result, list) + self.assertLen(eval_result, 1) + self.assertEqual(16., eval_result[0]) self.assertSequenceEqual(sess.run(grad), [32.]) + @test_util.run_deprecated_v1 def testMultipleLoopVarsBasic(self): x = constant_op.constant(5.) y = constant_op.constant(3.) @@ -58,15 +74,19 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): # y = 3. # while x < 45.: # x = x * y - ret = while_loop_v2(lambda v, _: v < 45., lambda v, w: (v * w, w), [x, y]) + ret = while_loop_v2( + lambda v, _: v < 45., + lambda v, w: (v * w, w), [x, y], + return_same_structure=False) # ret = [x*y^2, y] # Note: This is simply d_ret[0]/d_x since d_ret[1]/d_x is 0. grad = gradients_impl.gradients(ret, [x]) # [2*x*y] with self.cached_session() as sess: - self.assertSequenceEqual(sess.run(ret), [45., 3.]) - self.assertSequenceEqual(sess.run(grad), [9.]) + self.assertSequenceEqual(self.evaluate(ret), [45., 3.]) + self.assertSequenceEqual(self.evaluate(grad), [9.]) + @test_util.run_deprecated_v1 def testMultipleLoopVars(self): x = constant_op.constant(5.) y = constant_op.constant(3.) @@ -76,8 +96,10 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): # while x < 45.: # x = x * y # y = x + y - ret = while_loop_v2(lambda v, _: v < 45., lambda v, w: (v * w, v + w), - [x, y]) + ret = while_loop_v2( + lambda v, _: v < 45., + lambda v, w: (v * w, v + w), [x, y], + return_same_structure=False) # ret = [y*x**2 + x*y**2, x*y + x + y] gradx_0 = gradients_impl.gradients(ret[0], [x]) # [2*x*y + y**2] @@ -87,34 +109,43 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): grady_1 = gradients_impl.gradients(ret[1], [y]) # [x + 1] grady_2 = gradients_impl.gradients(ret, [y]) # [2*x*y + x**2 + x + 1] with self.cached_session() as sess: - self.assertSequenceEqual(sess.run(ret), [120., 23.]) - self.assertSequenceEqual(sess.run(gradx_0), [39.]) - self.assertSequenceEqual(sess.run(gradx_1), [4.]) - self.assertSequenceEqual(sess.run(gradx_2), [43.]) - self.assertSequenceEqual(sess.run(grady_0), [55.]) - self.assertSequenceEqual(sess.run(grady_1), [6.]) - self.assertSequenceEqual(sess.run(grady_2), [61.]) - + self.assertSequenceEqual(self.evaluate(ret), [120., 23.]) + self.assertSequenceEqual(self.evaluate(gradx_0), [39.]) + self.assertSequenceEqual(self.evaluate(gradx_1), [4.]) + self.assertSequenceEqual(self.evaluate(gradx_2), [43.]) + self.assertSequenceEqual(self.evaluate(grady_0), [55.]) + self.assertSequenceEqual(self.evaluate(grady_1), [6.]) + self.assertSequenceEqual(self.evaluate(grady_2), [61.]) + + @test_util.run_deprecated_v1 def testMultipleWhileLoops(self): x = constant_op.constant(2.) - ret1 = while_loop_v2(lambda v: v < 4., lambda v: v * v, [x]) # x**2 - ret2 = while_loop_v2(lambda v: v < 16., lambda v: v * v, [ret1]) # x**4 + ret1 = while_loop_v2( + lambda v: v < 4., lambda v: v * v, [x], + return_same_structure=False) # x**2 + ret2 = while_loop_v2( + lambda v: v < 16., lambda v: v * v, [ret1], + return_same_structure=False) # x**4 grad = gradients_impl.gradients(ret2, [x]) # 4x**3 grad_grad = gradients_impl.gradients(grad, [x]) # 12x**2 with self.cached_session() as sess: - self.assertSequenceEqual(sess.run(grad), [32.]) - self.assertSequenceEqual(sess.run(grad_grad), [48.]) + self.assertSequenceEqual(self.evaluate(grad), [32.]) + self.assertSequenceEqual(self.evaluate(grad_grad), [48.]) + @test_util.run_deprecated_v1 def testDoubleDerivative(self): x = constant_op.constant(2.) - ret = while_loop_v2(lambda v: v < 8., lambda v: v**2, [x]) # x**4 + ret = while_loop_v2( + lambda v: v < 8., lambda v: v**2, [x], + return_same_structure=False) # x**4 grad = gradients_impl.gradients(ret, [x]) # 4x**3 grad_grad = gradients_impl.gradients(grad, [x]) # 12x**2 with self.cached_session() as sess: - self.assertEqual(sess.run(ret), 16.) - self.assertSequenceEqual(sess.run(grad), [32.]) - self.assertSequenceEqual(sess.run(grad_grad), [48.]) + self.assertEqual(self.evaluate(ret), 16.) + self.assertSequenceEqual(self.evaluate(grad), [32.]) + self.assertSequenceEqual(self.evaluate(grad_grad), [48.]) + @test_util.run_deprecated_v1 def testPruning(self): x = constant_op.constant(1) @@ -135,10 +166,12 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): def GetOptimizedGraph(): mg = meta_graph.create_meta_graph_def(graph=ops.get_default_graph()) - rewriter_config = rewriter_config_pb2.RewriterConfig( - constant_folding=rewriter_config_pb2.RewriterConfig.OFF, - memory_optimization=rewriter_config_pb2.RewriterConfig.MANUAL) - return tf_optimizer.OptimizeGraph(rewriter_config, mg) + config = config_pb2.ConfigProto() + config.graph_options.rewrite_options.CopyFrom( + rewriter_config_pb2.RewriterConfig( + constant_folding=rewriter_config_pb2.RewriterConfig.OFF, + memory_optimization=rewriter_config_pb2.RewriterConfig.MANUAL)) + return tf_optimizer.OptimizeGraph(config, mg) g = GetOptimizedGraph() self.assertEqual(len([n for n in g.node if n.op == "Enter"]), 1) @@ -148,24 +181,31 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): g = GetOptimizedGraph() self.assertEqual(len([n for n in g.node if n.op == "Enter"]), 2) + @test_util.run_deprecated_v1 def testCaptureExternalTensorInCond(self): x = constant_op.constant(2.) y = constant_op.constant(1.) - ret = while_loop_v2(lambda v: v + y < 9., lambda v: v * 3., [x]) + ret = while_loop_v2( + lambda v: v + y < 9., + lambda v: v * 3., [x], + return_same_structure=False) grad = gradients_impl.gradients(ret, [x]) with self.cached_session() as sess: - self.assertEqual(sess.run(ret), 18.) - self.assertSequenceEqual(sess.run(grad), [9.]) + self.assertEqual(self.evaluate(ret), 18.) + self.assertSequenceEqual(self.evaluate(grad), [9.]) + @test_util.run_deprecated_v1 def testCaptureExternalTensorInBody(self): x = constant_op.constant(2.) y = constant_op.constant(3.) - ret = while_loop_v2(lambda v: v < 8., lambda v: v * y, [x]) + ret = while_loop_v2( + lambda v: v < 8., lambda v: v * y, [x], return_same_structure=False) grad = gradients_impl.gradients(ret, [x]) with self.cached_session() as sess: - self.assertEqual(sess.run(ret), 18.) - self.assertSequenceEqual(sess.run(grad), [9.]) + self.assertEqual(self.evaluate(ret), 18.) + self.assertSequenceEqual(self.evaluate(grad), [9.]) + @test_util.run_deprecated_v1 def testLoopWithTensorListPushBack(self): x = constant_op.constant(2.) @@ -181,12 +221,14 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): tl = list_ops.tensor_list_push_back(tl, constant_op.constant(100.)) return x**2., tl - ret = while_loop_v2(Cond, Body, [x, tensor_list]) + ret = while_loop_v2( + Cond, Body, [x, tensor_list], return_same_structure=False) grad = gradients_impl.gradients(ret[0], x) with self.cached_session() as sess: self.assertEqual(sess.run(ret[0]), 16.) - self.assertSequenceEqual(sess.run(grad), [32.]) + self.assertSequenceEqual(self.evaluate(grad), [32.]) + @test_util.run_deprecated_v1 def testDuplicateAccumulator(self): x = constant_op.constant(2.) @@ -203,7 +245,8 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): tl = list_ops.tensor_list_push_back(tl, x) return x**2., tl - ret = while_loop_v2(Cond, Body, [x, tensor_list]) + ret = while_loop_v2( + Cond, Body, [x, tensor_list], return_same_structure=False) for op in ops.get_default_graph().get_operations(): if op.type == "While": @@ -219,13 +262,14 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): grad = gradients_impl.gradients(ret[0], x) with self.cached_session() as sess: self.assertEqual(sess.run(ret[0]), 16.) - self.assertSequenceEqual(sess.run(grad), [32.]) + self.assertSequenceEqual(self.evaluate(grad), [32.]) @parameterized.named_parameters( ("UnknownShape", None), ("PartiallyDefinedShape", [None, 2]), ("FullyDefinedShape", [1, 2]), ) + @test_util.run_deprecated_v1 def testAccumulatorElementShape(self, shape): def MatchShape(actual_tensor_shape): @@ -250,7 +294,10 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): y = array_ops.placeholder(dtype=dtypes.float32, shape=shape) # Forward pass. - ret = while_loop_v2(lambda v, u: v < 8., lambda v, u: (v * v, u), [x, y]) + ret = while_loop_v2( + lambda v, u: v < 8., + lambda v, u: (v * v, u), [x, y], + return_same_structure=False) while_op = ret[0].op.inputs[0].op # Get the TensorList output of While op containing the accumulated values # of y. @@ -262,7 +309,7 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): # Gradient pass. grad = gradients_impl.gradients(ret[1], y) - grad_while_op = grad[0].op + grad_while_op = grad[0].op.inputs[0].op # Get the TensorList output of gradient While op containing the accumulated # values of grad_y. # grad_while_op.inputs: @@ -274,8 +321,10 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): def _createWhile(self, name): """Helper function testDefaultName.""" - output = while_v2.while_loop(lambda i: i < 3, lambda i: i + 1, - [constant_op.constant(0)]) + output = while_v2.while_loop( + lambda i: i < 3, + lambda i: i + 1, [constant_op.constant(0)], + return_same_structure=False) while_op = output.op.inputs[0].op self.assertEqual(while_op.type, "While") return while_op @@ -305,19 +354,19 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): self.assertRegexpMatches( while2_op.get_attr("body").name, r"foo_while_1_body_\d*") + @test_util.enable_control_flow_v2 + @test_util.run_deprecated_v1 def testWhileAndTensorArray(self): - old_enable_while_v2 = control_flow_ops.ENABLE_WHILE_V2 - control_flow_ops.ENABLE_WHILE_V2 = True with self.cached_session() as sess: param = constant_op.constant(2.0) y0 = constant_op.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], name="elems") # map_fn uses TensorArray internally. r = functional_ops.map_fn(lambda x: math_ops.multiply(x, param), y0) - self.assertAllClose([2.0, 4.0, 6.0, 8.0, 10.0, 12.0], sess.run(r)) + self.assertAllClose([2.0, 4.0, 6.0, 8.0, 10.0, 12.0], self.evaluate(r)) r = gradients_impl.gradients(r, param)[0] - self.assertAllClose(21.0, sess.run(r)) - control_flow_ops.ENABLE_WHILE_V2 = old_enable_while_v2 + self.assertAllClose(21.0, self.evaluate(r)) + @test_util.run_deprecated_v1 def testNestedWhile(self): # Compute sum of geometric progression: n^0 + n^1 + ... + n^m # We compute the pow using a while loop. @@ -328,14 +377,20 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): def Body(i, previous_sum): prod = constant_op.constant(1.) return i - 1., previous_sum + while_loop_v2( - lambda c, _: c > 0, lambda c, v: (c - 1., v * n), [i, prod])[1] - - result = while_loop_v2(lambda i, _: i >= 0, Body, [m, sum_of_powers])[1] + lambda c, _: c > 0, + lambda c, v: (c - 1., v * n), [i, prod], + return_same_structure=False)[1] + + result = while_loop_v2( + lambda i, _: i >= 0, + Body, [m, sum_of_powers], + return_same_structure=False)[1] grad = gradients_impl.gradients(result, [n]) with self.cached_session() as sess: - self.assertEqual(sess.run(result), 364.) - self.assertSequenceEqual(sess.run(grad), [547.]) + self.assertEqual(self.evaluate(result), 364.) + self.assertSequenceEqual(self.evaluate(grad), [547.]) + @test_util.run_deprecated_v1 def testIdentityNodeInBody(self): def Body(v): @@ -344,12 +399,14 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): return v * v x = constant_op.constant(2.) - ret = while_loop_v2(lambda v: v < 8., Body, [x]) + ret = while_loop_v2( + lambda v: v < 8., Body, [x], return_same_structure=False) grad = gradients_impl.gradients(ret, [x]) with self.cached_session() as sess: - self.assertEqual(sess.run(ret), 16.) - self.assertSequenceEqual(sess.run(grad), [32.]) + self.assertEqual(self.evaluate(ret), 16.) + self.assertSequenceEqual(self.evaluate(grad), [32.]) + @test_util.run_deprecated_v1 def testNestedWhileAndTensorArray(self): n = constant_op.constant(3.0) @@ -362,13 +419,17 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): return row, col + 1., ta, n # TODO(b/118457764): Remove n from loop_vars from both loops once fixed. - ta = while_loop_v2(lambda _, col, _1, n: col <= n, InnerBody, - [row, constant_op.constant(1.), ta, n])[2] + ta = while_loop_v2( + lambda _, col, _1, n: col <= n, + InnerBody, [row, constant_op.constant(1.), ta, n], + return_same_structure=False)[2] return row + 1., ta, n ta = tensor_array_ops.TensorArray(dtype=dtypes.float32, size=9) - ta = while_loop_v2(lambda row, _, _1: row <= n, Body, - [constant_op.constant(1.), ta, n])[1] + ta = while_loop_v2( + lambda row, _, _1: row <= n, + Body, [constant_op.constant(1.), ta, n], + return_same_structure=False)[1] output = array_ops.reshape(ta.stack(), [3, 3]) self.assertAllEqual( diff --git a/tensorflow/python/kernel_tests/xent_op_test.py b/tensorflow/python/kernel_tests/xent_op_test.py index c3c7f867a1..f5d03c2370 100644 --- a/tensorflow/python/kernel_tests/xent_op_test.py +++ b/tensorflow/python/kernel_tests/xent_op_test.py @@ -27,6 +27,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_nn_ops from tensorflow.python.ops import gradient_checker @@ -56,7 +57,7 @@ class XentTest(test.TestCase): with self.cached_session(use_gpu=use_gpu) as sess: loss, backprop = gen_nn_ops.softmax_cross_entropy_with_logits( np_features, np_labels) - tf_loss, tf_backprop = sess.run([loss, backprop]) + tf_loss, tf_backprop = self.evaluate([loss, backprop]) self.assertAllCloseAccordingToType(np_loss, tf_loss) self.assertAllCloseAccordingToType(np_backprop, tf_backprop) @@ -65,7 +66,7 @@ class XentTest(test.TestCase): with self.cached_session(use_gpu=use_gpu) as sess: loss = nn_ops.softmax_cross_entropy_with_logits( labels=np_labels, logits=np_features, dim=dim) - tf_loss = sess.run(loss) + tf_loss = self.evaluate(loss) print("np_loss:", np_loss) print("tf_loss:", tf_loss) self.assertAllCloseAccordingToType(np_loss, tf_loss) @@ -80,7 +81,7 @@ class XentTest(test.TestCase): loss, backprop = gen_nn_ops.softmax_cross_entropy_with_logits( np.array([[1.], [-1.], [0.]]).astype(dtype), np.array([[-1.], [0.], [1.]]).astype(dtype)) - tf_loss, tf_backprop = sess.run([loss, backprop]) + tf_loss, tf_backprop = self.evaluate([loss, backprop]) self.assertAllClose([0.0, 0.0, 0.0], tf_loss) self.assertAllClose([[2.0], [1.0], [0.0]], tf_backprop) @@ -88,6 +89,7 @@ class XentTest(test.TestCase): self._testSingleClass(True) self._testSingleClass(False) + @test_util.run_deprecated_v1 def testRankTooLarge(self): for dtype in np.float16, np.float32: np_features = np.array([[[1., 1., 1., 1.]], [[1., 2., 3., @@ -148,16 +150,18 @@ class XentTest(test.TestCase): with self.cached_session(use_gpu=use_gpu) as sess: loss, backprop = gen_nn_ops.softmax_cross_entropy_with_logits( tf_f, tf_l) - tf_loss, tf_backprop = sess.run([loss, backprop]) + tf_loss, tf_backprop = self.evaluate([loss, backprop]) self.assertAllCloseAccordingToType(np_loss, tf_loss) self.assertAllCloseAccordingToType(np_backprop, tf_backprop) + @test_util.run_deprecated_v1 def testShapeMismatch(self): with self.cached_session(): with self.assertRaises(ValueError): gen_nn_ops.softmax_cross_entropy_with_logits( [[0., 1.], [2., 3.]], [[0., 1., 0.], [1., 0., 0.]]) + @test_util.run_deprecated_v1 def testNotMatrix(self): with self.cached_session(): with self.assertRaises(ValueError): @@ -179,6 +183,7 @@ class XentTest(test.TestCase): np.array([[1., 1., 1., 1.], [1., 2., 3., 4.]]).astype(np.float64), np.array([[0., 0., 0., 1.], [0., .5, .5, 0.]]).astype(np.float64)) + @test_util.run_deprecated_v1 def testGradient(self): with self.cached_session() as sess: l = constant_op.constant( @@ -206,6 +211,7 @@ class XentTest(test.TestCase): print("cross entropy gradient err = ", err) self.assertLess(err, 5e-8) + @test_util.run_deprecated_v1 def testGradientLabelWithV2(self): with self.cached_session(): l = constant_op.constant( @@ -224,6 +230,7 @@ class XentTest(test.TestCase): self.assertLess(err, 5e-8) + @test_util.run_deprecated_v1 def testSecondGradient(self): with self.cached_session() as sess: l = constant_op.constant( @@ -280,7 +287,7 @@ class XentTest(test.TestCase): with self.session(use_gpu=True) as sess: loss = nn_ops.softmax_cross_entropy_with_logits( labels=labels, logits=features) - tf_loss = sess.run(loss) + tf_loss = self.evaluate(loss) self.assertAllEqual(np_loss, tf_loss) diff --git a/tensorflow/python/kernel_tests/zero_division_test.py b/tensorflow/python/kernel_tests/zero_division_test.py index e68b96e670..3dd9ec4ba9 100644 --- a/tensorflow/python/kernel_tests/zero_division_test.py +++ b/tensorflow/python/kernel_tests/zero_division_test.py @@ -21,13 +21,15 @@ from __future__ import print_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.platform import test class ZeroDivisionTest(test.TestCase): + @test_util.run_deprecated_v1 def testZeros(self): - with self.session(use_gpu=True): + with test_util.use_gpu(): for dtype in dtypes.uint8, dtypes.int16, dtypes.int32, dtypes.int64: zero = constant_op.constant(0, dtype=dtype) one = constant_op.constant(1, dtype=dtype) @@ -36,7 +38,7 @@ class ZeroDivisionTest(test.TestCase): bads.append(one % zero) for bad in bads: try: - result = bad.eval() + result = self.evaluate(bad) except errors_impl.OpError as e: # Ideally, we'd get a nice exception. In theory, this should only # happen on CPU, but 32 bit integer GPU division is actually on diff --git a/tensorflow/python/layers/base.py b/tensorflow/python/layers/base.py index fccea484b0..bfe591f875 100644 --- a/tensorflow/python/layers/base.py +++ b/tensorflow/python/layers/base.py @@ -23,6 +23,7 @@ from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.keras.engine import base_layer +from tensorflow.python.keras.engine import base_layer_utils from tensorflow.python.ops import variable_scope as vs from tensorflow.python.ops import variables as tf_variables from tensorflow.python.util import function_utils @@ -30,10 +31,10 @@ from tensorflow.python.util import nest from tensorflow.python.util import tf_contextlib from tensorflow.python.util.tf_export import tf_export - +# Avoid breaking users who directly import this symbol from this file. +# TODO(fchollet): remove this. InputSpec = base_layer.InputSpec # pylint: disable=invalid-name - _KERAS_STYLE_SCOPE = False @@ -242,11 +243,11 @@ class Layer(base_layer.Layer): def _make_unique_name(self, name_uid_map=None, avoid_names=None, namespace='', zero_based=False): base_name = base_layer.to_snake_case(self.__class__.__name__) - name = base_layer.unique_layer_name(base_name, - name_uid_map=name_uid_map, - avoid_names=avoid_names, - namespace=namespace, - zero_based=zero_based) + name = base_layer_utils.unique_layer_name(base_name, + name_uid_map=name_uid_map, + avoid_names=avoid_names, + namespace=namespace, + zero_based=zero_based) return (name, base_name) @property diff --git a/tensorflow/python/layers/base_test.py b/tensorflow/python/layers/base_test.py index 90abf35e87..d0ec4f4425 100644 --- a/tensorflow/python/layers/base_test.py +++ b/tensorflow/python/layers/base_test.py @@ -26,6 +26,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import test_util from tensorflow.python.keras.engine import base_layer as keras_base_layer +from tensorflow.python.keras.engine import input_spec from tensorflow.python.layers import base as base_layers from tensorflow.python.layers import core as core_layers from tensorflow.python.ops import array_ops @@ -142,6 +143,7 @@ class BaseLayerTest(test.TestCase): synchronization=variable_scope.VariableSynchronization.ON_READ, trainable=True) + @test_util.run_deprecated_v1 def testReusePartitionedVaraiblesAndRegularizers(self): regularizer = lambda x: math_ops.reduce_sum(x) * 1e-3 partitioner = partitioned_variables.fixed_size_partitioner(3) @@ -251,7 +253,7 @@ class BaseLayerTest(test.TestCase): def __init__(self): super(CustomerLayer, self).__init__() - self.input_spec = base_layers.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) def call(self, inputs): return inputs @@ -278,7 +280,7 @@ class BaseLayerTest(test.TestCase): def __init__(self): super(CustomerLayer, self).__init__() - self.input_spec = base_layers.InputSpec(min_ndim=2) + self.input_spec = input_spec.InputSpec(min_ndim=2) def call(self, inputs): return inputs @@ -306,7 +308,7 @@ class BaseLayerTest(test.TestCase): def __init__(self): super(CustomerLayer, self).__init__() - self.input_spec = base_layers.InputSpec(max_ndim=2) + self.input_spec = input_spec.InputSpec(max_ndim=2) def call(self, inputs): return inputs @@ -334,7 +336,7 @@ class BaseLayerTest(test.TestCase): def __init__(self): super(CustomerLayer, self).__init__() - self.input_spec = base_layers.InputSpec(dtype='float32') + self.input_spec = input_spec.InputSpec(dtype='float32') def call(self, inputs): return inputs @@ -354,7 +356,7 @@ class BaseLayerTest(test.TestCase): def __init__(self): super(CustomerLayer, self).__init__() - self.input_spec = base_layers.InputSpec(axes={-1: 2}) + self.input_spec = input_spec.InputSpec(axes={-1: 2}) def call(self, inputs): return inputs @@ -376,7 +378,7 @@ class BaseLayerTest(test.TestCase): def __init__(self): super(CustomerLayer, self).__init__() - self.input_spec = base_layers.InputSpec(shape=(None, 3)) + self.input_spec = input_spec.InputSpec(shape=(None, 3)) def call(self, inputs): return inputs @@ -444,6 +446,7 @@ class BaseLayerTest(test.TestCase): self.assertTrue(isinstance(result, dict)) self.assertEqual(set(['label', 'logits']), set(result.keys())) + @test_util.run_deprecated_v1 def testActivityRegularizer(self): regularizer = math_ops.reduce_sum layer = base_layers.Layer(activity_regularizer=regularizer) @@ -532,6 +535,7 @@ class BaseLayerTest(test.TestCase): self.assertEqual(len(layer.trainable_variables), 1) self.assertEqual(layer.variables[0].graph, outer_graph) + @test_util.run_deprecated_v1 def testGetUpdateFor(self): class MyLayer(base_layers.Layer): @@ -576,6 +580,7 @@ class BaseLayerTest(test.TestCase): self.assertEqual(len(layer.get_updates_for([intermediate_inputs])), 1) self.assertEqual(len(layer.get_updates_for([outputs])), 0) + @test_util.run_deprecated_v1 def testGetLossesFor(self): class MyLayer(base_layers.Layer): diff --git a/tensorflow/python/layers/convolutional_test.py b/tensorflow/python/layers/convolutional_test.py index 257fa27156..a3e493edfe 100644 --- a/tensorflow/python/layers/convolutional_test.py +++ b/tensorflow/python/layers/convolutional_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.layers import convolutional as conv_layers from tensorflow.python.ops import array_ops from tensorflow.python.ops import init_ops @@ -59,6 +60,7 @@ class ConvTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'kernel_size'): conv_layers.conv2d(images, 32, None) + @test_util.run_deprecated_v1 def testCreateConv2D(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -87,6 +89,7 @@ class ConvTest(test.TestCase): self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 4, 32]) self.assertListEqual(layer.bias.get_shape().as_list(), [32]) + @test_util.run_deprecated_v1 def testCreateConv2DChannelsFirst(self): height, width = 7, 9 images = random_ops.random_uniform((5, 4, height, width)) @@ -97,6 +100,7 @@ class ConvTest(test.TestCase): self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 4, 32]) self.assertListEqual(layer.bias.get_shape().as_list(), [32]) + @test_util.run_deprecated_v1 def testUnknownInputChannels(self): images = array_ops.placeholder(dtypes.float32, (5, 7, 9, None)) layer = conv_layers.Conv2D(32, [3, 3], activation=nn_ops.relu) @@ -140,6 +144,7 @@ class ConvTest(test.TestCase): self.assertListEqual(output.get_shape().as_list(), [5, height / 2, width, 32]) + @test_util.run_deprecated_v1 def testCreateConv1D(self): width = 7 data = random_ops.random_uniform((5, width, 4)) @@ -156,6 +161,7 @@ class ConvTest(test.TestCase): output = conv_layers.conv1d(data, 32, 3, activation=nn_ops.relu) self.assertListEqual(output.get_shape().as_list(), [5, width - 2, 32]) + @test_util.run_deprecated_v1 def testCreateConv1DChannelsFirst(self): width = 7 data = random_ops.random_uniform((5, 4, width)) @@ -165,6 +171,7 @@ class ConvTest(test.TestCase): self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 4, 32]) self.assertListEqual(layer.bias.get_shape().as_list(), [32]) + @test_util.run_deprecated_v1 def testUnknownInputChannelsConv1D(self): data = array_ops.placeholder(dtypes.float32, (5, 4, None)) layer = conv_layers.Conv1D(32, 3, activation=nn_ops.relu) @@ -180,6 +187,7 @@ class ConvTest(test.TestCase): 'should be defined. Found `None`.'): _ = layer.apply(data) + @test_util.run_deprecated_v1 def testCreateConv3D(self): depth, height, width = 6, 7, 9 volumes = random_ops.random_uniform((5, depth, height, width, 4)) @@ -191,6 +199,7 @@ class ConvTest(test.TestCase): self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32]) self.assertListEqual(layer.bias.get_shape().as_list(), [32]) + @test_util.run_deprecated_v1 def testUnknownInputChannelsConv3D(self): volumes = array_ops.placeholder(dtypes.float32, (5, 6, 7, 9, None)) layer = conv_layers.Conv3D(32, [3, 3, 3], activation=nn_ops.relu) @@ -199,6 +208,7 @@ class ConvTest(test.TestCase): 'should be defined. Found `None`.'): _ = layer.apply(volumes) + @test_util.run_deprecated_v1 def testConv2DKernelRegularizer(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -210,6 +220,7 @@ class ConvTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testConv2DBiasRegularizer(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -221,6 +232,7 @@ class ConvTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testConv2DNoBias(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -247,6 +259,7 @@ class ConvTest(test.TestCase): output = layer.apply(images) self.assertListEqual(output.get_shape().as_list(), [5, height - 2, 3, 32]) + @test_util.run_deprecated_v1 def testFunctionalConv2DReuse(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 3), seed=1) @@ -255,6 +268,7 @@ class ConvTest(test.TestCase): conv_layers.conv2d(images, 32, [3, 3], name='conv1', reuse=True) self.assertEqual(len(variables.trainable_variables()), 2) + @test_util.run_deprecated_v1 def testFunctionalConv2DReuseFromScope(self): with variable_scope.variable_scope('scope'): height, width = 7, 9 @@ -265,6 +279,7 @@ class ConvTest(test.TestCase): conv_layers.conv2d(images, 32, [3, 3], name='conv1') self.assertEqual(len(variables.trainable_variables()), 2) + @test_util.run_deprecated_v1 def testFunctionalConv2DInitializerFromScope(self): with self.cached_session() as sess: with variable_scope.variable_scope( @@ -276,13 +291,14 @@ class ConvTest(test.TestCase): # Check the names of weights in order. self.assertTrue('kernel' in weights[0].name) self.assertTrue('bias' in weights[1].name) - sess.run(variables.global_variables_initializer()) - weights = sess.run(weights) + self.evaluate(variables.global_variables_initializer()) + weights = self.evaluate(weights) # Check that the kernel weights got initialized to ones (from scope) self.assertAllClose(weights[0], np.ones((3, 3, 3, 32))) # Check that the bias still got initialized to zeros. self.assertAllClose(weights[1], np.zeros((32))) + @test_util.run_deprecated_v1 def testFunctionalConv2DNoReuse(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 3), seed=1) @@ -325,6 +341,7 @@ class ConvTest(test.TestCase): self.assertEqual(conv3d.kernel_constraint, k_constraint) self.assertEqual(conv3d.bias_constraint, b_constraint) + @test_util.run_deprecated_v1 def testConv3DChannelsFirst(self): # Test case for GitHub issue 15655 images = array_ops.placeholder( @@ -358,6 +375,7 @@ class SeparableConv1DTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'kernel_size'): conv_layers.separable_conv1d(data, 32, None) + @test_util.run_deprecated_v1 def testCreateSeparableConv1D(self): length = 9 data = random_ops.random_uniform((5, length, 4)) @@ -379,6 +397,7 @@ class SeparableConv1DTest(test.TestCase): self.assertEqual(layer.pointwise_kernel.get_shape().as_list(), [1, 8, 32]) self.assertEqual(layer.bias.get_shape().as_list(), [32]) + @test_util.run_deprecated_v1 def testCreateSeparableConv1DChannelsFirst(self): length = 9 data = random_ops.random_uniform((5, 4, length)) @@ -404,6 +423,7 @@ class SeparableConv1DTest(test.TestCase): output = layer.apply(data) self.assertEqual(output.get_shape().as_list(), [5, length // 2, 32]) + @test_util.run_deprecated_v1 def testCreateSeparableConv1DWithStridesChannelsFirst(self): data_format = 'channels_first' length = 10 @@ -413,6 +433,7 @@ class SeparableConv1DTest(test.TestCase): output = layer.apply(data) self.assertEqual(output.get_shape().as_list(), [5, 32, length // 2]) + @test_util.run_deprecated_v1 def testFunctionalConv1DReuse(self): length = 10 data = random_ops.random_uniform((5, length, 3), seed=1) @@ -421,6 +442,7 @@ class SeparableConv1DTest(test.TestCase): conv_layers.separable_conv1d(data, 32, 3, name='sepconv1', reuse=True) self.assertEqual(len(variables.trainable_variables()), 3) + @test_util.run_deprecated_v1 def testFunctionalConv1DReuseFromScope(self): with variable_scope.variable_scope('scope'): length = 10 @@ -431,6 +453,7 @@ class SeparableConv1DTest(test.TestCase): conv_layers.separable_conv1d(data, 32, 3, name='sepconv1') self.assertEqual(len(variables.trainable_variables()), 3) + @test_util.run_deprecated_v1 def testFunctionalConv1DNoReuse(self): length = 10 data = random_ops.random_uniform((5, length, 3), seed=1) @@ -439,6 +462,7 @@ class SeparableConv1DTest(test.TestCase): conv_layers.separable_conv1d(data, 32, 3) self.assertEqual(len(variables.trainable_variables()), 6) + @test_util.run_deprecated_v1 def testSeparableConv1DDepthwiseRegularizer(self): length = 9 data = random_ops.random_uniform((5, length, 4)) @@ -450,6 +474,7 @@ class SeparableConv1DTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testSeparableConv1DPointwiseRegularizer(self): length = 9 data = random_ops.random_uniform((5, length, 4)) @@ -461,6 +486,7 @@ class SeparableConv1DTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testSeparableConv1DBiasRegularizer(self): length = 9 data = random_ops.random_uniform((5, length, 4)) @@ -472,6 +498,7 @@ class SeparableConv1DTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testSeparableConv1DNoBias(self): length = 9 data = random_ops.random_uniform((5, length, 4)) @@ -522,6 +549,7 @@ class SeparableConv2DTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'kernel_size'): conv_layers.separable_conv2d(images, 32, None) + @test_util.run_deprecated_v1 def testCreateSeparableConv2D(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -562,6 +590,7 @@ class SeparableConv2DTest(test.TestCase): [1, 1, 4, 32]) self.assertListEqual(layer.bias.get_shape().as_list(), [32]) + @test_util.run_deprecated_v1 def testCreateSeparableConv2DChannelsFirst(self): height, width = 7, 9 images = random_ops.random_uniform((5, 4, height, width)) @@ -584,6 +613,7 @@ class SeparableConv2DTest(test.TestCase): output = layer.apply(images) self.assertListEqual(output.get_shape().as_list(), [5, height, width, 64]) + @test_util.run_deprecated_v1 def testCreateSeparableConvWithStrides(self): height, width = 6, 8 # Test strides tuple @@ -607,6 +637,7 @@ class SeparableConv2DTest(test.TestCase): self.assertListEqual(output.get_shape().as_list(), [5, height / 2, width, 32]) + @test_util.run_deprecated_v1 def testCreateSeparableConvWithStridesChannelsFirst(self): data_format = 'channels_first' height, width = 6, 8 @@ -632,6 +663,7 @@ class SeparableConv2DTest(test.TestCase): self.assertListEqual(output.get_shape().as_list(), [5, 32, height / 2, width]) + @test_util.run_deprecated_v1 def testFunctionalConv2DReuse(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 3), seed=1) @@ -641,6 +673,7 @@ class SeparableConv2DTest(test.TestCase): images, 32, [3, 3], name='sepconv1', reuse=True) self.assertEqual(len(variables.trainable_variables()), 3) + @test_util.run_deprecated_v1 def testFunctionalConv2DReuseFromScope(self): with variable_scope.variable_scope('scope'): height, width = 7, 9 @@ -651,6 +684,7 @@ class SeparableConv2DTest(test.TestCase): conv_layers.separable_conv2d(images, 32, [3, 3], name='sepconv1') self.assertEqual(len(variables.trainable_variables()), 3) + @test_util.run_deprecated_v1 def testFunctionalConv2DInitializerFromScope(self): with self.cached_session() as sess: with variable_scope.variable_scope( @@ -663,14 +697,15 @@ class SeparableConv2DTest(test.TestCase): self.assertTrue('depthwise_kernel' in weights[0].name) self.assertTrue('pointwise_kernel' in weights[1].name) self.assertTrue('bias' in weights[2].name) - sess.run(variables.global_variables_initializer()) - weights = sess.run(weights) + self.evaluate(variables.global_variables_initializer()) + weights = self.evaluate(weights) # Check that the kernel weights got initialized to ones (from scope) self.assertAllClose(weights[0], np.ones((3, 3, 3, 1))) self.assertAllClose(weights[1], np.ones((1, 1, 3, 32))) # Check that the bias still got initialized to zeros. self.assertAllClose(weights[2], np.zeros((32))) + @test_util.run_deprecated_v1 def testFunctionalConv2DNoReuse(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 3), seed=1) @@ -679,6 +714,7 @@ class SeparableConv2DTest(test.TestCase): conv_layers.separable_conv2d(images, 32, [3, 3]) self.assertEqual(len(variables.trainable_variables()), 6) + @test_util.run_deprecated_v1 def testSeparableConv2DDepthwiseRegularizer(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -690,6 +726,7 @@ class SeparableConv2DTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testSeparableConv2DPointwiseRegularizer(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -701,6 +738,7 @@ class SeparableConv2DTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testSeparableConv2DBiasRegularizer(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -712,6 +750,7 @@ class SeparableConv2DTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testSeparableConv2DNoBias(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -768,6 +807,7 @@ class Conv2DTransposeTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'kernel_size'): conv_layers.conv2d_transpose(images, 32, None) + @test_util.run_deprecated_v1 def testCreateConv2DTranspose(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -839,6 +879,7 @@ class Conv2DTransposeTest(test.TestCase): self.assertListEqual(output.get_shape().as_list(), [5, height * 2, width, 32]) + @test_util.run_deprecated_v1 def testConv2DTransposeKernelRegularizer(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -850,6 +891,7 @@ class Conv2DTransposeTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testConv2DTransposeBiasRegularizer(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -861,6 +903,7 @@ class Conv2DTransposeTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testConv2DTransposeNoBias(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 4)) @@ -873,6 +916,7 @@ class Conv2DTransposeTest(test.TestCase): self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 32, 4]) self.assertEqual(layer.bias, None) + @test_util.run_deprecated_v1 def testFunctionalConv2DTransposeReuse(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 3), seed=1) @@ -881,6 +925,7 @@ class Conv2DTransposeTest(test.TestCase): conv_layers.conv2d_transpose(images, 32, [3, 3], name='deconv1', reuse=True) self.assertEqual(len(variables.trainable_variables()), 2) + @test_util.run_deprecated_v1 def testFunctionalConv2DTransposeReuseFromScope(self): with variable_scope.variable_scope('scope'): height, width = 7, 9 @@ -891,6 +936,7 @@ class Conv2DTransposeTest(test.TestCase): conv_layers.conv2d_transpose(images, 32, [3, 3], name='deconv1') self.assertEqual(len(variables.trainable_variables()), 2) + @test_util.run_deprecated_v1 def testFunctionalConv2DTransposeInitializerFromScope(self): with self.cached_session() as sess: with variable_scope.variable_scope( @@ -902,13 +948,14 @@ class Conv2DTransposeTest(test.TestCase): # Check the names of weights in order. self.assertTrue('kernel' in weights[0].name) self.assertTrue('bias' in weights[1].name) - sess.run(variables.global_variables_initializer()) - weights = sess.run(weights) + self.evaluate(variables.global_variables_initializer()) + weights = self.evaluate(weights) # Check that the kernel weights got initialized to ones (from scope) self.assertAllClose(weights[0], np.ones((3, 3, 32, 3))) # Check that the bias still got initialized to zeros. self.assertAllClose(weights[1], np.zeros((32))) + @test_util.run_deprecated_v1 def testFunctionalConv2DTransposeNoReuse(self): height, width = 7, 9 images = random_ops.random_uniform((5, height, width, 3), seed=1) @@ -955,6 +1002,7 @@ class Conv3DTransposeTest(test.TestCase): with self.assertRaisesRegexp(ValueError, 'kernel_size'): conv_layers.conv3d_transpose(volumes, 4, None) + @test_util.run_deprecated_v1 def testCreateConv3DTranspose(self): depth, height, width = 5, 7, 9 volumes = random_ops.random_uniform((5, depth, height, width, 32)) @@ -976,6 +1024,7 @@ class Conv3DTransposeTest(test.TestCase): self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32]) self.assertListEqual(layer.bias.get_shape().as_list(), [4]) + @test_util.run_deprecated_v1 def testCreateConv3DTransposeChannelsFirst(self): depth, height, width = 5, 7, 9 volumes = random_ops.random_uniform((5, 32, depth, height, width)) @@ -1019,6 +1068,7 @@ class Conv3DTransposeTest(test.TestCase): self.assertListEqual(output.get_shape().as_list(), [5, depth * 2, height, width, 4]) + @test_util.run_deprecated_v1 def testConv3DTransposeKernelRegularizer(self): depth, height, width = 5, 7, 9 volumes = random_ops.random_uniform((5, depth, height, width, 32)) @@ -1030,6 +1080,7 @@ class Conv3DTransposeTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testConv3DTransposeBiasRegularizer(self): depth, height, width = 5, 7, 9 volumes = random_ops.random_uniform((5, depth, height, width, 32)) @@ -1041,6 +1092,7 @@ class Conv3DTransposeTest(test.TestCase): self.evaluate([v.initializer for v in layer.variables]) self.assertListEqual(self.evaluate(layer.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testConv3DTransposeNoBias(self): depth, height, width = 5, 7, 9 volumes = random_ops.random_uniform((5, depth, height, width, 32)) @@ -1053,6 +1105,7 @@ class Conv3DTransposeTest(test.TestCase): self.assertListEqual(layer.kernel.get_shape().as_list(), [3, 3, 3, 4, 32]) self.assertEqual(layer.bias, None) + @test_util.run_deprecated_v1 def testFunctionalConv3DTransposeReuse(self): depth, height, width = 5, 7, 9 volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1) @@ -1062,6 +1115,7 @@ class Conv3DTransposeTest(test.TestCase): volumes, 4, [3, 3, 3], name='deconv1', reuse=True) self.assertEqual(len(variables.trainable_variables()), 2) + @test_util.run_deprecated_v1 def testFunctionalConv3DTransposeReuseFromScope(self): with variable_scope.variable_scope('scope'): depth, height, width = 5, 7, 9 @@ -1072,6 +1126,7 @@ class Conv3DTransposeTest(test.TestCase): conv_layers.conv3d_transpose(volumes, 4, [3, 3, 3], name='deconv1') self.assertEqual(len(variables.trainable_variables()), 2) + @test_util.run_deprecated_v1 def testFunctionalConv3DTransposeInitializerFromScope(self): with self.cached_session() as sess: with variable_scope.variable_scope( @@ -1084,13 +1139,14 @@ class Conv3DTransposeTest(test.TestCase): # Check the names of weights in order. self.assertTrue('kernel' in weights[0].name) self.assertTrue('bias' in weights[1].name) - sess.run(variables.global_variables_initializer()) - weights = sess.run(weights) + self.evaluate(variables.global_variables_initializer()) + weights = self.evaluate(weights) # Check that the kernel weights got initialized to ones (from scope) self.assertAllClose(weights[0], np.ones((3, 3, 3, 4, 32))) # Check that the bias still got initialized to zeros. self.assertAllClose(weights[1], np.zeros((4))) + @test_util.run_deprecated_v1 def testFunctionalConv3DTransposeNoReuse(self): depth, height, width = 5, 7, 9 volumes = random_ops.random_uniform((5, depth, height, width, 32), seed=1) diff --git a/tensorflow/python/layers/core_test.py b/tensorflow/python/layers/core_test.py index 0343bfa8bd..cf6f0fbb70 100644 --- a/tensorflow/python/layers/core_test.py +++ b/tensorflow/python/layers/core_test.py @@ -59,6 +59,7 @@ class DenseTest(test.TestCase): dense.apply(random_ops.random_uniform((5, 2))) self.assertEqual(dense.name, 'dense_2') + @test_util.run_deprecated_v1 def testVariableInput(self): with self.cached_session(): v = variable_scope.get_variable( @@ -140,6 +141,7 @@ class DenseTest(test.TestCase): outputs = dense.apply(inputs) self.assertEqual(outputs.get_shape().as_list(), [1, 2, 4, 7]) + @test_util.run_deprecated_v1 def testCallOnPlaceHolder(self): inputs = array_ops.placeholder(dtype=dtypes.float32) dense = core_layers.Dense(4, name='my_dense') @@ -179,6 +181,7 @@ class DenseTest(test.TestCase): if not context.executing_eagerly(): self.assertEqual(outputs.op.name, 'dense2/BiasAdd') + @test_util.run_deprecated_v1 def testActivityRegularizer(self): regularizer = lambda x: math_ops.reduce_sum(x) * 1e-3 dense = core_layers.Dense( @@ -189,6 +192,7 @@ class DenseTest(test.TestCase): self.assertEqual(len(loss_keys), 1) self.assertListEqual(dense.losses, loss_keys) + @test_util.run_deprecated_v1 def testKernelRegularizer(self): regularizer = lambda x: math_ops.reduce_sum(x) * 1e-3 dense = core_layers.Dense( @@ -200,6 +204,7 @@ class DenseTest(test.TestCase): self.evaluate([v.initializer for v in dense.variables]) self.assertAllEqual(self.evaluate(dense.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testKernelRegularizerWithReuse(self): regularizer = lambda x: math_ops.reduce_sum(x) * 1e-3 inputs = random_ops.random_uniform((5, 3), seed=1) @@ -212,6 +217,7 @@ class DenseTest(test.TestCase): self.assertEqual( len(ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES)), 1) + @test_util.run_deprecated_v1 def testBiasRegularizer(self): regularizer = lambda x: math_ops.reduce_sum(x) * 1e-3 dense = core_layers.Dense(2, name='my_dense', bias_regularizer=regularizer) @@ -222,6 +228,7 @@ class DenseTest(test.TestCase): self.evaluate([v.initializer for v in dense.variables]) self.assertAllEqual(self.evaluate(dense.losses), self.evaluate(loss_keys)) + @test_util.run_deprecated_v1 def testFunctionalDense(self): with self.cached_session(): inputs = random_ops.random_uniform((5, 3), seed=1) @@ -231,6 +238,7 @@ class DenseTest(test.TestCase): len(ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES)), 2) self.assertEqual(outputs.op.name, 'my_dense/Relu') + @test_util.run_deprecated_v1 def testFunctionalDenseTwice(self): inputs = random_ops.random_uniform((5, 3), seed=1) core_layers.dense(inputs, 2) @@ -262,6 +270,7 @@ class DenseTest(test.TestCase): vars2 = variables.trainable_variables() self.assertEqual(vars1, vars2) + @test_util.run_deprecated_v1 def testFunctionalDenseInitializerFromScope(self): with variable_scope.variable_scope( 'scope', @@ -307,6 +316,7 @@ class DenseTest(test.TestCase): core_layers.dense(inputs, 2) self.assertEqual(called[0], 2) + @test_util.run_deprecated_v1 def testFunctionalDenseInScope(self): with self.cached_session(): with variable_scope.variable_scope('test'): @@ -393,6 +403,7 @@ class DropoutTest(test.TestCase): np_output = self.evaluate(dropped) self.assertAllClose(np.ones((5, 3)), np_output) + @test_util.run_deprecated_v1 def testDynamicLearningPhase(self): with self.cached_session() as sess: dp = core_layers.Dropout(0.5, seed=1) @@ -426,6 +437,7 @@ class DropoutTest(test.TestCase): self.assertAlmostEqual(0., np_output.min()) self.assertAllClose(np_output[:, 0, :], np_output[:, 1, :]) + @test_util.run_deprecated_v1 def testFunctionalDropout(self): with self.cached_session(): inputs = array_ops.ones((5, 5)) @@ -437,13 +449,14 @@ class DropoutTest(test.TestCase): np_output = self.evaluate(dropped) self.assertAllClose(np.ones((5, 5)), np_output) + @test_util.run_deprecated_v1 def testDynamicRate(self): with self.cached_session() as sess: rate = array_ops.placeholder(dtype='float32', name='rate') dp = core_layers.Dropout(rate, name='dropout') inputs = array_ops.ones((5, 5)) dropped = dp.apply(inputs, training=True) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) np_output = sess.run(dropped, feed_dict={rate: 0.5}) self.assertAlmostEqual(0., np_output.min()) np_output = sess.run(dropped, feed_dict={rate: 0.0}) @@ -452,6 +465,7 @@ class DropoutTest(test.TestCase): class FlattenTest(test.TestCase): + @test_util.run_deprecated_v1 def testCreateFlatten(self): with self.cached_session() as sess: x = array_ops.placeholder(shape=(None, 2, 3), dtype='float32') @@ -476,6 +490,7 @@ class FlattenTest(test.TestCase): shape = core_layers.Flatten().compute_output_shape((None, 3, None)) self.assertEqual(shape.as_list(), [None, None]) + @test_util.run_deprecated_v1 def testDataFormat5d(self): np_input_channels_last = np.arange( 120, dtype='float32').reshape([1, 5, 4, 3, 2]) @@ -493,6 +508,7 @@ class FlattenTest(test.TestCase): self.assertAllEqual(np_output_cl, np_output_cf) + @test_util.run_deprecated_v1 def testDataFormat4d(self): np_input_channels_last = np.arange( 24, dtype='float32').reshape([1, 4, 3, 2]) @@ -510,16 +526,19 @@ class FlattenTest(test.TestCase): self.assertAllEqual(np_output_cl, np_output_cf) + @test_util.run_deprecated_v1 def testFunctionalFlatten(self): x = array_ops.placeholder(shape=(None, 2, 3), dtype='float32') y = core_layers.flatten(x, name='flatten') self.assertEqual(y.get_shape().as_list(), [None, 6]) + @test_util.run_deprecated_v1 def testFlattenValueError(self): x = array_ops.placeholder(shape=(None,), dtype='float32') with self.assertRaises(ValueError): core_layers.Flatten()(x) + @test_util.run_deprecated_v1 def testFlattenUnknownAxes(self): with self.cached_session() as sess: x = array_ops.placeholder(shape=(5, None, None), dtype='float32') diff --git a/tensorflow/python/layers/layers.py b/tensorflow/python/layers/layers.py index 11a2ebc040..93eec38a08 100644 --- a/tensorflow/python/layers/layers.py +++ b/tensorflow/python/layers/layers.py @@ -24,7 +24,7 @@ from __future__ import print_function # Base objects. from tensorflow.python.layers.base import Layer -from tensorflow.python.layers.base import InputSpec +from tensorflow.python.keras.engine.input_spec import InputSpec # Core layers. from tensorflow.python.layers.core import Dense diff --git a/tensorflow/python/layers/normalization_test.py b/tensorflow/python/layers/normalization_test.py index ba2bf10cf3..07d8e40b75 100644 --- a/tensorflow/python/layers/normalization_test.py +++ b/tensorflow/python/layers/normalization_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.core.protobuf import saver_pb2 from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.layers import convolutional as conv_layers from tensorflow.python.layers import normalization as normalization_layers from tensorflow.python.ops import array_ops @@ -78,7 +79,7 @@ class BNTest(test.TestCase): if restore: saver.restore(sess, checkpoint_path) else: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) np.random.seed(0) for _ in range(2): image_val = np.random.rand(*shape).astype(dtype.as_numpy_dtype) @@ -143,6 +144,7 @@ class BNTest(test.TestCase): return train_vars, loss_val + @test_util.run_deprecated_v1 def testHalfPrecision(self): ref_vars, ref_loss = self._trainEvalSequence( dtype=dtypes.float32, @@ -228,33 +230,43 @@ class BNTest(test.TestCase): ckpt_b_use_gpu, use_gpu_test_a, use_gpu_test_b, freeze_mode) + @test_util.run_deprecated_v1 def testCheckpointFusedCPUAndFusedGPU(self): self._testCheckpointCrossDevice(True, False, True, True) + @test_util.run_deprecated_v1 def testCheckpointFusedCPUAndFusedCPU(self): self._testCheckpointCrossDevice(True, False, True, False) + @test_util.run_deprecated_v1 def testCheckpointFusedGPUAndFusedGPU(self): self._testCheckpointCrossDevice(True, True, True, True) + @test_util.run_deprecated_v1 def testCheckpointNonFusedCPUAndNonFusedGPU(self): self._testCheckpointCrossDevice(False, False, False, True) + @test_util.run_deprecated_v1 def testCheckpointNonFusedCPUAndNonFusedCPU(self): self._testCheckpointCrossDevice(False, False, False, False) + @test_util.run_deprecated_v1 def testCheckpointNonFusedGPUAndNonFusedGPU(self): self._testCheckpointCrossDevice(False, True, False, True) + @test_util.run_deprecated_v1 def testCheckpointNonFusedGPUAndFusedGPU(self): self._testCheckpointCrossDevice(False, True, True, True) + @test_util.run_deprecated_v1 def testCheckpointNonFusedGPUAndFusedCPU(self): self._testCheckpointCrossDevice(False, True, True, False) + @test_util.run_deprecated_v1 def testCheckpointNonFusedCPUAndFusedCPU(self): self._testCheckpointCrossDevice(False, False, True, False) + @test_util.run_deprecated_v1 def testCreateBN(self): # Call layer. bn = normalization_layers.BatchNormalization(axis=1) @@ -281,6 +293,7 @@ class BNTest(test.TestCase): ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES), bn.trainable_variables) + @test_util.run_deprecated_v1 def testCreateFusedBNFloat16(self): # Call layer. bn = normalization_layers.BatchNormalization(axis=1, fused=True) @@ -310,6 +323,7 @@ class BNTest(test.TestCase): ops.get_collection(ops.GraphKeys.TRAINABLE_VARIABLES), bn.trainable_variables) + @test_util.run_deprecated_v1 def test3DInputAxis1(self): epsilon = 1e-3 bn = normalization_layers.BatchNormalization( @@ -321,9 +335,9 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) np_gamma = np.reshape(np_gamma, (1, 4, 1)) np_beta = np.reshape(np_beta, (1, 4, 1)) @@ -336,8 +350,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 2)) std = np.std(np_inputs, axis=(0, 2)) variance = np.square(std) @@ -352,6 +367,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def test3DInputAxis2(self): epsilon = 1e-3 bn = normalization_layers.BatchNormalization( @@ -363,8 +379,8 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + self.evaluate(variables.global_variables_initializer()) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) np_gamma = np.reshape(np_gamma, (1, 1, 3)) np_beta = np.reshape(np_beta, (1, 1, 3)) for _ in range(100): @@ -376,8 +392,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 1)) std = np.std(np_inputs, axis=(0, 1)) variance = np.square(std) @@ -404,8 +421,8 @@ class BNTest(test.TestCase): with self.session(use_gpu=True) as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + self.evaluate(variables.global_variables_initializer()) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) np_gamma = np.reshape(np_gamma, (1, 4, 1, 1)) np_beta = np.reshape(np_beta, (1, 4, 1, 1)) for _ in range(100): @@ -417,8 +434,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 2, 3)) std = np.std(np_inputs, axis=(0, 2, 3)) variance = np.square(std) @@ -433,6 +451,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def test4DInputAxis2(self): epsilon = 1e-3 bn = normalization_layers.BatchNormalization( @@ -444,8 +463,8 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + self.evaluate(variables.global_variables_initializer()) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) np_gamma = np.reshape(np_gamma, (1, 1, 3, 1)) np_beta = np.reshape(np_beta, (1, 1, 3, 1)) for _ in range(100): @@ -457,8 +476,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 1, 3)) std = np.std(np_inputs, axis=(0, 1, 3)) variance = np.square(std) @@ -473,6 +493,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def test4DInputAxis3(self): epsilon = 1e-3 bn = normalization_layers.BatchNormalization( @@ -484,8 +505,8 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + self.evaluate(variables.global_variables_initializer()) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) np_gamma = np.reshape(np_gamma, (1, 1, 1, 6)) np_beta = np.reshape(np_beta, (1, 1, 1, 6)) for _ in range(100): @@ -497,8 +518,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 1, 2)) std = np.std(np_inputs, axis=(0, 1, 2)) variance = np.square(std) @@ -513,6 +535,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def test4DInputAxis3Fused(self): epsilon = 1e-3 bn = normalization_layers.BatchNormalization( @@ -524,8 +547,8 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + self.evaluate(variables.global_variables_initializer()) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) np_gamma = np.reshape(np_gamma, (1, 1, 1, 6)) np_beta = np.reshape(np_beta, (1, 1, 1, 6)) for _ in range(100): @@ -537,8 +560,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 1, 2)) std = np.std(np_inputs, axis=(0, 1, 2)) variance = np.square(std) @@ -565,8 +589,8 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + self.evaluate(variables.global_variables_initializer()) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) np_gamma = np.reshape(np_gamma, (1, 4, 1, 1)) np_beta = np.reshape(np_beta, (1, 4, 1, 1)) for _ in range(100): @@ -578,8 +602,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 2, 3)) std = np.std(np_inputs, axis=(0, 2, 3)) variance = np.square(std) @@ -594,6 +619,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def testNegativeAxis(self): epsilon = 1e-3 bn = normalization_layers.BatchNormalization( @@ -605,8 +631,8 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + self.evaluate(variables.global_variables_initializer()) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) np_gamma = np.reshape(np_gamma, (1, 1, 1, 6)) np_beta = np.reshape(np_beta, (1, 1, 1, 6)) for _ in range(100): @@ -619,8 +645,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 1, 2)) std = np.std(np_inputs, axis=(0, 1, 2)) variance = np.square(std) @@ -635,6 +662,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def testBooleanLearningPhase(self): epsilon = 1e-3 bn = normalization_layers.BatchNormalization( @@ -646,8 +674,8 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + self.evaluate(variables.global_variables_initializer()) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) np_gamma = np.reshape(np_gamma, (1, 1, 1, 6)) np_beta = np.reshape(np_beta, (1, 1, 1, 6)) for _ in range(100): @@ -658,8 +686,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 1, 2)) std = np.std(np_inputs, axis=(0, 1, 2)) variance = np.square(std) @@ -667,13 +696,14 @@ class BNTest(test.TestCase): self.assertAllClose(variance, moving_var, atol=1e-2) # Test inference with placeholder learning phase. - np_output = sess.run(outputs_infer) + np_output = self.evaluate(outputs_infer) # Verify that the axis is normalized during inference. normed_np_output = ((np_output - epsilon) * np_gamma) + np_beta self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def testFunctionalNoReuse(self): inputs = variables.Variable( np.random.random((5, 4, 3, 6)), dtype=dtypes.float32) @@ -696,8 +726,8 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([gamma, beta]) + self.evaluate(variables.global_variables_initializer()) + np_gamma, np_beta = self.evaluate([gamma, beta]) np_gamma = np.reshape(np_gamma, (1, 1, 1, 6)) np_beta = np.reshape(np_beta, (1, 1, 1, 6)) for _ in range(100): @@ -709,8 +739,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - np_moving_mean, np_moving_var = sess.run([moving_mean, moving_variance]) - np_inputs = sess.run(inputs) + np_moving_mean, np_moving_var = self.evaluate( + [moving_mean, moving_variance]) + np_inputs = self.evaluate(inputs) np_mean = np.mean(np_inputs, axis=(0, 1, 2)) np_std = np.std(np_inputs, axis=(0, 1, 2)) np_variance = np.square(np_std) @@ -725,6 +756,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def testFunctionalReuse(self): inputs1 = variables.Variable( np.random.random((5, 4, 3, 6)), dtype=dtypes.float32) @@ -758,14 +790,15 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(100): np_output, _, _ = sess.run([outputs2] + updates, feed_dict={training: True}) # Verify that the statistics are updated during training. - np_moving_mean, np_moving_var = sess.run([moving_mean, moving_variance]) - np_inputs = sess.run(inputs2) + np_moving_mean, np_moving_var = self.evaluate( + [moving_mean, moving_variance]) + np_inputs = self.evaluate(inputs2) np_mean = np.mean(np_inputs, axis=(0, 1, 2)) np_std = np.std(np_inputs, axis=(0, 1, 2)) np_variance = np.square(np_std) @@ -773,7 +806,7 @@ class BNTest(test.TestCase): self.assertAllClose(np_variance, np_moving_var, atol=1e-2) # Verify that the axis is normalized during training. - np_gamma, np_beta = sess.run([gamma, beta]) + np_gamma, np_beta = self.evaluate([gamma, beta]) np_gamma = np.reshape(np_gamma, (1, 1, 1, 6)) np_beta = np.reshape(np_beta, (1, 1, 1, 6)) normed_np_output = ((np_output - epsilon) * np_gamma) + np_beta @@ -788,6 +821,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=2) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def testFunctionalReuseFromScope(self): inputs = variables.Variable( np.random.random((5, 4, 3, 6)), dtype=dtypes.float32) @@ -802,6 +836,7 @@ class BNTest(test.TestCase): inputs, axis=-1, momentum=0.9, epsilon=epsilon, training=training) self.assertEqual(len(variables.global_variables()), 5) + @test_util.run_deprecated_v1 def testNoCenter(self): bn = normalization_layers.BatchNormalization(axis=1, center=False) inputs = random_ops.random_uniform((5, 4, 3), seed=1) @@ -817,6 +852,7 @@ class BNTest(test.TestCase): self.assertEqual(len(bn.trainable_variables), 1) self.assertEqual(len(bn.non_trainable_variables), 2) + @test_util.run_deprecated_v1 def testNoScale(self): bn = normalization_layers.BatchNormalization(axis=1, scale=False) inputs = random_ops.random_uniform((5, 4, 3), seed=1) @@ -832,6 +868,7 @@ class BNTest(test.TestCase): self.assertEqual(len(bn.trainable_variables), 1) self.assertEqual(len(bn.non_trainable_variables), 2) + @test_util.run_deprecated_v1 def testRegularizers(self): reg = lambda x: 0.1 * math_ops.reduce_sum(x) bn = normalization_layers.BatchNormalization(axis=1, beta_regularizer=reg) @@ -857,6 +894,7 @@ class BNTest(test.TestCase): self.assertEqual(bn.gamma_constraint, g_constraint) self.assertEqual(bn.beta_constraint, b_constraint) + @test_util.run_deprecated_v1 def testRenorm(self): shape = (4, 3) xt = array_ops.placeholder(dtypes.float32, shape) @@ -885,7 +923,7 @@ class BNTest(test.TestCase): renorm_mean = renorm_stddev = 0. renorm_weight = 0. with self.session(use_gpu=True) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(5): x = np.random.random(shape) @@ -915,6 +953,7 @@ class BNTest(test.TestCase): self.assertAllClose(y_train, yt_val_train, atol=1e-5) self.assertAllClose(y_test, yt_val_test, atol=1e-5) + @test_util.run_deprecated_v1 def testAdjustment(self): shape = (4, 3) xt = array_ops.placeholder(dtypes.float32, shape) @@ -937,7 +976,7 @@ class BNTest(test.TestCase): moving_mean = 0. moving_variance = 1. with self.session(use_gpu=True) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(5): x = np.random.random(shape) yt_val_train, adj_scale_val, adj_bias_val = sess.run( @@ -959,6 +998,7 @@ class BNTest(test.TestCase): self.assertAllClose(y_train, yt_val_train, atol=1e-5) self.assertAllClose(y_test, yt_val_test, atol=1e-5) + @test_util.run_deprecated_v1 def testRenormWithAdjustment(self): shape = (4, 3) xt = array_ops.placeholder(dtypes.float32, shape) @@ -990,7 +1030,7 @@ class BNTest(test.TestCase): renorm_mean = renorm_stddev = 0. renorm_weight = 0. with self.session(use_gpu=True) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(5): x = np.random.random(shape) yt_val_train, adj_scale_val, adj_bias_val = sess.run( @@ -1029,6 +1069,7 @@ class BNTest(test.TestCase): normalization_layers.batch_normalization( inp, virtual_batch_size=-1) + @test_util.run_deprecated_v1 def testGhostBNVirtualBatchFull(self): shape = [6, 5, 4, 3] inp = random_ops.random_uniform(shape, seed=1) @@ -1040,7 +1081,7 @@ class BNTest(test.TestCase): out1.shape.as_list(), out2.shape.as_list()) with self.session(use_gpu=True) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) x = np.random.random(shape) y1, y2 = sess.run([out1, out2], feed_dict={inp: x}) @@ -1054,6 +1095,7 @@ class BNTest(test.TestCase): inp, virtual_batch_size=3) self.assertListEqual(out.shape.as_list(), shape) + @test_util.run_deprecated_v1 def testGhostBNUnknownBatchSize(self): np_shape = [10, 5, 4] tf_shape = [None, 5, 4] @@ -1062,13 +1104,14 @@ class BNTest(test.TestCase): inp, virtual_batch_size=2) with self.session(use_gpu=True) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) x = np.random.random(np_shape) y = sess.run(out, feed_dict={inp: x}) self.assertListEqual(list(y.shape), np_shape) + @test_util.run_deprecated_v1 def testGhostBN2Dims(self): shape = [6, 2] virtual_batch_size = 3 @@ -1093,7 +1136,7 @@ class BNTest(test.TestCase): shape[1]]) with self.session(use_gpu=True) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(5): x = np.random.random(shape) @@ -1122,6 +1165,7 @@ class BNTest(test.TestCase): self.assertAllClose(y_train, y_val_train, atol=1e-5) self.assertAllClose(y_test, y_val_test, atol=1e-5) + @test_util.run_deprecated_v1 def testGhostBN4DimsAxis3(self): shape = [6, 10, 10, 3] virtual_batch_size = 2 @@ -1146,7 +1190,7 @@ class BNTest(test.TestCase): shape[1:]) with self.session(use_gpu=True) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(5): x = np.random.random(shape) @@ -1175,6 +1219,7 @@ class BNTest(test.TestCase): self.assertAllClose(y_train, y_val_train, atol=1e-2) self.assertAllClose(y_test, y_val_test, atol=1e-2) + @test_util.run_deprecated_v1 def testGhostBN4DimsAxis1(self): shape = [6, 3, 10, 10] virtual_batch_size = 2 @@ -1200,7 +1245,7 @@ class BNTest(test.TestCase): shape[1:]) with self.session(use_gpu=True) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(5): x = np.random.random(shape) @@ -1245,6 +1290,7 @@ class BNTest(test.TestCase): normalization_layers.batch_normalization( inp, axis=[1, 2, 1]) # duplicate + @test_util.run_deprecated_v1 def test3DInputMultiAxis12(self): epsilon = 1e-3 bn = normalization_layers.BatchNormalization( @@ -1256,9 +1302,9 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) for _ in range(100): np_output, _, _ = sess.run([outputs] + bn.updates, @@ -1269,8 +1315,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=0, keepdims=True) std = np.std(np_inputs, axis=0, keepdims=True) variance = np.square(std) @@ -1285,6 +1332,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def test5DInputMultiAxis123(self): epsilon = 1e-3 bn = normalization_layers.BatchNormalization( @@ -1296,9 +1344,9 @@ class BNTest(test.TestCase): with self.cached_session() as sess: # Test training with placeholder learning phase. - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) - np_gamma, np_beta = sess.run([bn.gamma, bn.beta]) + np_gamma, np_beta = self.evaluate([bn.gamma, bn.beta]) for _ in range(100): np_output, _, _ = sess.run([outputs] + bn.updates, @@ -1309,8 +1357,9 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) # Verify that the statistics are updated during training. - moving_mean, moving_var = sess.run([bn.moving_mean, bn.moving_variance]) - np_inputs = sess.run(inputs) + moving_mean, moving_var = self.evaluate( + [bn.moving_mean, bn.moving_variance]) + np_inputs = self.evaluate(inputs) mean = np.mean(np_inputs, axis=(0, 4), keepdims=True) std = np.std(np_inputs, axis=(0, 4), keepdims=True) variance = np.square(std) @@ -1325,6 +1374,7 @@ class BNTest(test.TestCase): self.assertAlmostEqual(np.mean(normed_np_output), 0., places=1) self.assertAlmostEqual(np.std(normed_np_output), 1., places=1) + @test_util.run_deprecated_v1 def testGhostBN5DimsMultiAxis14(self): shape = [6, 3, 10, 10, 4] virtual_batch_size = 3 @@ -1350,7 +1400,7 @@ class BNTest(test.TestCase): shape[1:]) with self.session(use_gpu=True) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(5): x = np.random.random(shape) diff --git a/tensorflow/python/layers/pooling_test.py b/tensorflow/python/layers/pooling_test.py index 7533674e5a..cf1fa1e691 100644 --- a/tensorflow/python/layers/pooling_test.py +++ b/tensorflow/python/layers/pooling_test.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import test_util from tensorflow.python.layers import pooling as pooling_layers from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops @@ -64,6 +65,7 @@ class PoolingTest(test.TestCase): output = layer.apply(images) self.assertListEqual(output.get_shape().as_list(), [5, 3, 4, 4]) + @test_util.run_deprecated_v1 def testCreateMaxPooling2DChannelsFirst(self): height, width = 7, 9 images = random_ops.random_uniform((5, 2, height, width)) @@ -73,6 +75,7 @@ class PoolingTest(test.TestCase): output = layer.apply(images) self.assertListEqual(output.get_shape().as_list(), [5, 2, 6, 8]) + @test_util.run_deprecated_v1 def testCreateAveragePooling2DChannelsFirst(self): height, width = 5, 6 images = random_ops.random_uniform((3, 4, height, width)) @@ -83,6 +86,7 @@ class PoolingTest(test.TestCase): output = layer.apply(images) self.assertListEqual(output.get_shape().as_list(), [3, 4, 4, 5]) + @test_util.run_deprecated_v1 def testCreateAveragePooling2DChannelsFirstWithNoneBatch(self): height, width = 5, 6 images = array_ops.placeholder(dtype='float32', diff --git a/tensorflow/python/lib/io/file_io.py b/tensorflow/python/lib/io/file_io.py index f22fb253e4..4caa5750bf 100644 --- a/tensorflow/python/lib/io/file_io.py +++ b/tensorflow/python/lib/io/file_io.py @@ -241,7 +241,7 @@ class FileIO(object): self._writable_file = None -@tf_export("gfile.Exists") +@tf_export(v1=["gfile.Exists"]) def file_exists(filename): """Determines whether a path exists or not. @@ -252,18 +252,35 @@ def file_exists(filename): True if the path exists, whether its a file or a directory. False if the path does not exist and there are no filesystem errors. + Raises: + errors.OpError: Propagates any errors reported by the FileSystem API. + """ + return file_exists_v2(filename) + + +@tf_export("io.gfile.exists") +def file_exists_v2(path): + """Determines whether a path exists or not. + + Args: + path: string, a path + + Returns: + True if the path exists, whether its a file or a directory. + False if the path does not exist and there are no filesystem errors. + Raises: errors.OpError: Propagates any errors reported by the FileSystem API. """ try: with errors.raise_exception_on_not_ok_status() as status: - pywrap_tensorflow.FileExists(compat.as_bytes(filename), status) + pywrap_tensorflow.FileExists(compat.as_bytes(path), status) except errors.NotFoundError: return False return True -@tf_export("gfile.Remove") +@tf_export(v1=["gfile.Remove"]) def delete_file(filename): """Deletes the file located at 'filename'. @@ -274,8 +291,22 @@ def delete_file(filename): errors.OpError: Propagates any errors reported by the FileSystem API. E.g., NotFoundError if the file does not exist. """ + delete_file_v2(filename) + + +@tf_export("io.gfile.remove") +def delete_file_v2(path): + """Deletes the path located at 'path'. + + Args: + path: string, a path + + Raises: + errors.OpError: Propagates any errors reported by the FileSystem API. E.g., + NotFoundError if the path does not exist. + """ with errors.raise_exception_on_not_ok_status() as status: - pywrap_tensorflow.DeleteFile(compat.as_bytes(filename), status) + pywrap_tensorflow.DeleteFile(compat.as_bytes(path), status) def read_file_to_string(filename, binary_mode=False): @@ -314,7 +345,7 @@ def write_string_to_file(filename, file_content): f.write(file_content) -@tf_export("gfile.Glob") +@tf_export(v1=["gfile.Glob"]) def get_matching_files(filename): """Returns a list of files that match the given pattern(s). @@ -324,28 +355,44 @@ def get_matching_files(filename): Returns: A list of strings containing filenames that match the given pattern(s). + Raises: + errors.OpError: If there are filesystem / directory listing errors. + """ + return get_matching_files_v2(filename) + + +@tf_export("io.gfile.glob") +def get_matching_files_v2(pattern): + """Returns a list of files that match the given pattern(s). + + Args: + pattern: string or iterable of strings. The glob pattern(s). + + Returns: + A list of strings containing filenames that match the given pattern(s). + Raises: errors.OpError: If there are filesystem / directory listing errors. """ with errors.raise_exception_on_not_ok_status() as status: - if isinstance(filename, six.string_types): + if isinstance(pattern, six.string_types): return [ # Convert the filenames to string from bytes. compat.as_str_any(matching_filename) for matching_filename in pywrap_tensorflow.GetMatchingFiles( - compat.as_bytes(filename), status) + compat.as_bytes(pattern), status) ] else: return [ # Convert the filenames to string from bytes. compat.as_str_any(matching_filename) - for single_filename in filename + for single_filename in pattern for matching_filename in pywrap_tensorflow.GetMatchingFiles( compat.as_bytes(single_filename), status) ] -@tf_export("gfile.MkDir") +@tf_export(v1=["gfile.MkDir"]) def create_dir(dirname): """Creates a directory with the name 'dirname'. @@ -356,14 +403,31 @@ def create_dir(dirname): The parent directories need to exist. Use recursive_create_dir instead if there is the possibility that the parent dirs don't exist. + Raises: + errors.OpError: If the operation fails. + """ + create_dir_v2(dirname) + + +@tf_export("io.gfile.mkdir") +def create_dir_v2(path): + """Creates a directory with the name given by 'path'. + + Args: + path: string, name of the directory to be created + + Notes: + The parent directories need to exist. Use recursive_create_dir instead if + there is the possibility that the parent dirs don't exist. + Raises: errors.OpError: If the operation fails. """ with errors.raise_exception_on_not_ok_status() as status: - pywrap_tensorflow.CreateDir(compat.as_bytes(dirname), status) + pywrap_tensorflow.CreateDir(compat.as_bytes(path), status) -@tf_export("gfile.MakeDirs") +@tf_export(v1=["gfile.MakeDirs"]) def recursive_create_dir(dirname): """Creates a directory and all parent/intermediate directories. @@ -372,14 +436,29 @@ def recursive_create_dir(dirname): Args: dirname: string, name of the directory to be created + Raises: + errors.OpError: If the operation fails. + """ + recursive_create_dir_v2(dirname) + + +@tf_export("io.gfile.makedirs") +def recursive_create_dir_v2(path): + """Creates a directory and all parent/intermediate directories. + + It succeeds if path already exists and is writable. + + Args: + path: string, name of the directory to be created + Raises: errors.OpError: If the operation fails. """ with errors.raise_exception_on_not_ok_status() as status: - pywrap_tensorflow.RecursivelyCreateDir(compat.as_bytes(dirname), status) + pywrap_tensorflow.RecursivelyCreateDir(compat.as_bytes(path), status) -@tf_export("gfile.Copy") +@tf_export(v1=["gfile.Copy"]) def copy(oldpath, newpath, overwrite=False): """Copies data from oldpath to newpath. @@ -389,15 +468,31 @@ def copy(oldpath, newpath, overwrite=False): overwrite: boolean, if false its an error for newpath to be occupied by an existing file. + Raises: + errors.OpError: If the operation fails. + """ + copy_v2(oldpath, newpath, overwrite) + + +@tf_export("io.gfile.copy") +def copy_v2(src, dst, overwrite=False): + """Copies data from src to dst. + + Args: + src: string, name of the file whose contents need to be copied + dst: string, name of the file to which to copy to + overwrite: boolean, if false its an error for newpath to be occupied by an + existing file. + Raises: errors.OpError: If the operation fails. """ with errors.raise_exception_on_not_ok_status() as status: pywrap_tensorflow.CopyFile( - compat.as_bytes(oldpath), compat.as_bytes(newpath), overwrite, status) + compat.as_bytes(src), compat.as_bytes(dst), overwrite, status) -@tf_export("gfile.Rename") +@tf_export(v1=["gfile.Rename"]) def rename(oldname, newname, overwrite=False): """Rename or move a file / directory. @@ -407,12 +502,28 @@ def rename(oldname, newname, overwrite=False): overwrite: boolean, if false it's an error for `newname` to be occupied by an existing file. + Raises: + errors.OpError: If the operation fails. + """ + rename_v2(oldname, newname, overwrite) + + +@tf_export("io.gfile.rename") +def rename_v2(src, dst, overwrite=False): + """Rename or move a file / directory. + + Args: + src: string, pathname for a file + dst: string, pathname to which the file needs to be moved + overwrite: boolean, if false it's an error for `dst` to be occupied by + an existing file. + Raises: errors.OpError: If the operation fails. """ with errors.raise_exception_on_not_ok_status() as status: pywrap_tensorflow.RenameFile( - compat.as_bytes(oldname), compat.as_bytes(newname), overwrite, status) + compat.as_bytes(src), compat.as_bytes(dst), overwrite, status) def atomic_write_string_to_file(filename, contents, overwrite=True): @@ -439,35 +550,61 @@ def atomic_write_string_to_file(filename, contents, overwrite=True): raise -@tf_export("gfile.DeleteRecursively") +@tf_export(v1=["gfile.DeleteRecursively"]) def delete_recursively(dirname): """Deletes everything under dirname recursively. Args: dirname: string, a path to a directory + Raises: + errors.OpError: If the operation fails. + """ + delete_recursively_v2(dirname) + + +@tf_export("io.gfile.rmtree") +def delete_recursively_v2(path): + """Deletes everything under path recursively. + + Args: + path: string, a path + Raises: errors.OpError: If the operation fails. """ with errors.raise_exception_on_not_ok_status() as status: - pywrap_tensorflow.DeleteRecursively(compat.as_bytes(dirname), status) + pywrap_tensorflow.DeleteRecursively(compat.as_bytes(path), status) -@tf_export("gfile.IsDirectory") +@tf_export(v1=["gfile.IsDirectory"]) def is_directory(dirname): """Returns whether the path is a directory or not. Args: dirname: string, path to a potential directory + Returns: + True, if the path is a directory; False otherwise + """ + return is_directory_v2(dirname) + + +@tf_export("io.gfile.isdir") +def is_directory_v2(path): + """Returns whether the path is a directory or not. + + Args: + path: string, path to a potential directory + Returns: True, if the path is a directory; False otherwise """ status = c_api_util.ScopedTFStatus() - return pywrap_tensorflow.IsDirectory(compat.as_bytes(dirname), status) + return pywrap_tensorflow.IsDirectory(compat.as_bytes(path), status) -@tf_export("gfile.ListDirectory") +@tf_export(v1=["gfile.ListDirectory"]) def list_directory(dirname): """Returns a list of entries contained within a directory. @@ -483,7 +620,26 @@ def list_directory(dirname): Raises: errors.NotFoundError if directory doesn't exist """ - if not is_directory(dirname): + return list_directory_v2(dirname) + + +@tf_export("io.gfile.listdir") +def list_directory_v2(path): + """Returns a list of entries contained within a directory. + + The list is in arbitrary order. It does not contain the special entries "." + and "..". + + Args: + path: string, path to a directory + + Returns: + [filename1, filename2, ... filenameN] as strings + + Raises: + errors.NotFoundError if directory doesn't exist + """ + if not is_directory(path): raise errors.NotFoundError(None, None, "Could not find directory") with errors.raise_exception_on_not_ok_status() as status: # Convert each element to string, since the return values of the @@ -491,11 +647,11 @@ def list_directory(dirname): return [ compat.as_str_any(filename) for filename in pywrap_tensorflow.GetChildren( - compat.as_bytes(dirname), status) + compat.as_bytes(path), status) ] -@tf_export("gfile.Walk") +@tf_export(v1=["gfile.Walk"]) def walk(top, in_order=True): """Recursive directory tree generator for directories. @@ -505,6 +661,27 @@ def walk(top, in_order=True): Errors that happen while listing directories are ignored. + Yields: + Each yield is a 3-tuple: the pathname of a directory, followed by lists of + all its subdirectories and leaf files. + (dirname, [subdirname, subdirname, ...], [filename, filename, ...]) + as strings + """ + return walk_v2(top, in_order) + + +@tf_export("io.gfile.walk") +def walk_v2(top, topdown, onerror=None): + """Recursive directory tree generator for directories. + + Args: + top: string, a Directory name + topdown: bool, Traverse pre order if True, post order if False. + onerror: optional handler for errors. Should be a function, it will be + called with the error as argument. Rethrowing the error aborts the walk. + + Errors that happen while listing directories are ignored. + Yields: Each yield is a 3-tuple: the pathname of a directory, followed by lists of all its subdirectories and leaf files. @@ -514,8 +691,11 @@ def walk(top, in_order=True): top = compat.as_str_any(top) try: listing = list_directory(top) - except errors.NotFoundError: - return + except errors.NotFoundError as err: + if onerror: + onerror(err) + else: + return files = [] subdirs = [] @@ -528,18 +708,18 @@ def walk(top, in_order=True): here = (top, subdirs, files) - if in_order: + if topdown: yield here for subdir in subdirs: - for subitem in walk(os.path.join(top, subdir), in_order): + for subitem in walk_v2(os.path.join(top, subdir), topdown, onerror=onerror): yield subitem - if not in_order: + if not topdown: yield here -@tf_export("gfile.Stat") +@tf_export(v1=["gfile.Stat"]) def stat(filename): """Returns file statistics for a given path. @@ -549,12 +729,28 @@ def stat(filename): Returns: FileStatistics struct that contains information about the path + Raises: + errors.OpError: If the operation fails. + """ + return stat_v2(filename) + + +@tf_export("io.gfile.stat") +def stat_v2(path): + """Returns file statistics for a given path. + + Args: + path: string, path to a file + + Returns: + FileStatistics struct that contains information about the path + Raises: errors.OpError: If the operation fails. """ file_statistics = pywrap_tensorflow.FileStatistics() with errors.raise_exception_on_not_ok_status() as status: - pywrap_tensorflow.Stat(compat.as_bytes(filename), file_statistics, status) + pywrap_tensorflow.Stat(compat.as_bytes(path), file_statistics, status) return file_statistics diff --git a/tensorflow/python/lib/io/tf_record.py b/tensorflow/python/lib/io/tf_record.py index b7fae85295..43086ab18d 100644 --- a/tensorflow/python/lib/io/tf_record.py +++ b/tensorflow/python/lib/io/tf_record.py @@ -150,10 +150,11 @@ class TFRecordOptions(object): return options -@tf_export( - "io.tf_record_iterator", - v1=["io.tf_record_iterator", "python_io.tf_record_iterator"]) -@deprecation.deprecated_endpoints("python_io.tf_record_iterator") +@tf_export(v1=["io.tf_record_iterator", "python_io.tf_record_iterator"]) +@deprecation.deprecated( + date=None, + instructions=("Use eager execution and: \n" + "`tf.data.TFRecordDataset(path)`")) def tf_record_iterator(path, options=None): """An iterator that read the records from a TFRecords file. diff --git a/tensorflow/python/ops/array_grad.py b/tensorflow/python/ops/array_grad.py index 68c392bf28..45e741ef22 100644 --- a/tensorflow/python/ops/array_grad.py +++ b/tensorflow/python/ops/array_grad.py @@ -489,10 +489,12 @@ def _GatherNdGrad(op, grad): @ops.RegisterGradient("CheckNumerics") -def _CheckNumericsGrad(_, grad): +def _CheckNumericsGrad(op, grad): """Gradient for check_numerics op.""" return array_ops.check_numerics( - grad, "Not a number (NaN) or infinity (Inf) values detected in gradient.") + grad, + "Not a number (NaN) or infinity (Inf) values detected in gradient. %s" % + op.get_attr("message")) @ops.RegisterGradient("PlaceholderWithDefault") @@ -800,6 +802,32 @@ def _ScatterNdGrad(op, grad): return [None, updates_grad, None] +@ops.RegisterGradient("TensorScatterUpdate") +def _TensorScatterUpdateGrad(op, grad): + indices = op.inputs[1] + updates_grad = array_ops.gather_nd(grad, indices) + tensor_grad = array_ops.tensor_scatter_update( + array_ops.identity(grad), indices, + array_ops.zeros_like(op.inputs[2], dtype=grad.dtype)) + return [tensor_grad, None, updates_grad] + + +@ops.RegisterGradient("TensorScatterAdd") +def _TensorScatterAddGrad(op, grad): + indices = op.inputs[1] + updates_grad = array_ops.gather_nd(grad, indices) + tensor_grad = array_ops.identity(grad) + return [tensor_grad, None, updates_grad] + + +@ops.RegisterGradient("TensorScatterSub") +def _TensorScatterSubGrad(op, grad): + indices = op.inputs[1] + updates_grad = array_ops.gather_nd(grad, indices) + tensor_grad = array_ops.identity(grad) + return [tensor_grad, None, -updates_grad] + + @ops.RegisterGradient("ScatterNdNonAliasingAdd") def _ScatterNdNonAliasingAddGrad(op, grad): indices = op.inputs[1] diff --git a/tensorflow/python/ops/array_ops.py b/tensorflow/python/ops/array_ops.py index bbf7d166bf..7b6242b1cd 100644 --- a/tensorflow/python/ops/array_ops.py +++ b/tensorflow/python/ops/array_ops.py @@ -22,6 +22,7 @@ from __future__ import print_function import sys import numpy as np +import six from tensorflow.python.eager import context from tensorflow.python.framework import common_shapes @@ -40,6 +41,7 @@ from tensorflow.python.ops import gen_math_ops from tensorflow.python.ops.gen_array_ops import * from tensorflow.python.ops.gen_array_ops import reverse_v2 as reverse # pylint: disable=unused-import from tensorflow.python.util import deprecation +from tensorflow.python.util import dispatch from tensorflow.python.util import nest from tensorflow.python.util.tf_export import tf_export # pylint: enable=wildcard-import @@ -79,7 +81,7 @@ def identity(input, name=None): # pylint: disable=redefined-builtin # pylint: disable=redefined-builtin,protected-access -@tf_export("expand_dims") +@tf_export(v1=["expand_dims"]) @deprecation.deprecated_args(None, "Use the `axis` argument instead", "dim") def expand_dims(input, axis=None, name=None, dim=None): """Inserts a dimension of 1 into a tensor's shape. @@ -133,6 +135,55 @@ def expand_dims(input, axis=None, name=None, dim=None): axis = deprecation.deprecated_argument_lookup("axis", axis, "dim", dim) if axis is None: raise ValueError("Must specify an axis argument to tf.expand_dims()") + return expand_dims_v2(input, axis, name) + + +@tf_export("expand_dims", v1=[]) +def expand_dims_v2(input, axis, name=None): + """Inserts a dimension of 1 into a tensor's shape. + + Given a tensor `input`, this operation inserts a dimension of 1 at the + dimension index `axis` of `input`'s shape. The dimension index `axis` starts + at zero; if you specify a negative number for `axis` it is counted backward + from the end. + + This operation is useful if you want to add a batch dimension to a single + element. For example, if you have a single image of shape `[height, width, + channels]`, you can make it a batch of 1 image with `expand_dims(image, 0)`, + which will make the shape `[1, height, width, channels]`. + + Other examples: + + ```python + # 't' is a tensor of shape [2] + tf.shape(tf.expand_dims(t, 0)) # [1, 2] + tf.shape(tf.expand_dims(t, 1)) # [2, 1] + tf.shape(tf.expand_dims(t, -1)) # [2, 1] + + # 't2' is a tensor of shape [2, 3, 5] + tf.shape(tf.expand_dims(t2, 0)) # [1, 2, 3, 5] + tf.shape(tf.expand_dims(t2, 2)) # [2, 3, 1, 5] + tf.shape(tf.expand_dims(t2, 3)) # [2, 3, 5, 1] + ``` + + This operation requires that: + + `-1-input.dims() <= dim <= input.dims()` + + This operation is related to `squeeze()`, which removes dimensions of + size 1. + + Args: + input: A `Tensor`. + axis: 0-D (scalar). Specifies the dimension index at which to + expand the shape of `input`. Must be in the range + `[-rank(input) - 1, rank(input)]`. + name: The name of the output `Tensor` (optional). + + Returns: + A `Tensor` with the same data as `input`, but its shape has an additional + dimension of size 1 added. + """ return gen_array_ops.expand_dims(input, axis, name) @@ -219,7 +270,13 @@ def broadcast_static_shape(shape_x, shape_y): return common_shapes.broadcast_shape(shape_x, shape_y) -@tf_export("shape") +@tf_export("shape", v1=[]) +def shape_v2(input, out_type=dtypes.int32, name=None): + # pylint: disable=redefined-builtin + return shape(input, name, out_type) + + +@tf_export(v1=["shape"]) def shape(input, name=None, out_type=dtypes.int32): # pylint: disable=redefined-builtin """Returns the shape of a tensor. @@ -292,7 +349,13 @@ def shape_n(input, out_type=dtypes.int32, name=None): return gen_array_ops.shape_n(input, out_type=out_type, name=name) -@tf_export("size") +@tf_export("size", v1=[]) +def size_v2(input, out_type=dtypes.int32, name=None): + # pylint: disable=redefined-builtin + return size(input, name, out_type) + + +@tf_export(v1=["size"]) def size(input, name=None, out_type=dtypes.int32): # pylint: disable=redefined-builtin """Returns the size of a tensor. @@ -341,7 +404,7 @@ def size_internal(input, name=None, optimize=True, out_type=dtypes.int32): input, (sparse_tensor.SparseTensor, sparse_tensor.SparseTensorValue)): input = ops.convert_to_tensor(input) np_out_type = out_type.as_numpy_dtype - num_elements = np.prod(input._shape_tuple(), dtype=np_out_type) # pylint: disable=protected-acces: + num_elements = np.prod(input._shape_tuple(), dtype=np_out_type) # pylint: disable=protected-access return ops.convert_to_tensor(num_elements, dtype=out_type) with ops.name_scope(name, "Size", [input]) as name: if isinstance(input, (sparse_tensor.SparseTensor, @@ -431,7 +494,7 @@ _SUPPORTED_SLICE_DTYPES = ( def _check_index(idx): """Check if a given value is a valid index into a tensor.""" - if isinstance(idx, (int, tensor_shape.Dimension)): + if isinstance(idx, (six.integer_types, tensor_shape.Dimension)): return # Optimistic check. Assumptions: @@ -1445,7 +1508,75 @@ def split(value, num_or_size_splits, axis=0, num=None, name="split"): value=value, size_splits=size_splits, axis=axis, num_split=num, name=name) -@tf_export("transpose") +@tf_export("transpose", v1=[]) +def transpose_v2(a, perm=None, conjugate=False, name="transpose"): + """Transposes `a`. Permutes the dimensions according to `perm`. + + The returned tensor's dimension i will correspond to the input dimension + `perm[i]`. If `perm` is not given, it is set to (n-1...0), where n is + the rank of the input tensor. Hence by default, this operation performs a + regular matrix transpose on 2-D input Tensors. If conjugate is True and + `a.dtype` is either `complex64` or `complex128` then the values of `a` + are conjugated and transposed. + + @compatibility(numpy) + In `numpy` transposes are memory-efficient constant time operations as they + simply return a new view of the same data with adjusted `strides`. + + TensorFlow does not support strides, so `transpose` returns a new tensor with + the items permuted. + @end_compatibility + + For example: + + ```python + x = tf.constant([[1, 2, 3], [4, 5, 6]]) + tf.transpose(x) # [[1, 4] + # [2, 5] + # [3, 6]] + + # Equivalently + tf.transpose(x, perm=[1, 0]) # [[1, 4] + # [2, 5] + # [3, 6]] + + # If x is complex, setting conjugate=True gives the conjugate transpose + x = tf.constant([[1 + 1j, 2 + 2j, 3 + 3j], + [4 + 4j, 5 + 5j, 6 + 6j]]) + tf.transpose(x, conjugate=True) # [[1 - 1j, 4 - 4j], + # [2 - 2j, 5 - 5j], + # [3 - 3j, 6 - 6j]] + + # 'perm' is more useful for n-dimensional tensors, for n > 2 + x = tf.constant([[[ 1, 2, 3], + [ 4, 5, 6]], + [[ 7, 8, 9], + [10, 11, 12]]]) + + # Take the transpose of the matrices in dimension-0 + # (this common operation has a shorthand `linalg.transpose`) + tf.transpose(x, perm=[0, 2, 1]) # [[[1, 4], + # [2, 5], + # [3, 6]], + # [[7, 10], + # [8, 11], + # [9, 12]]] + ``` + + Args: + a: A `Tensor`. + perm: A permutation of the dimensions of `a`. + conjugate: Optional bool. Setting it to `True` is mathematically equivalent + to tf.conj(tf.transpose(input)). + name: A name for the operation (optional). + + Returns: + A transposed `Tensor`. + """ + return transpose(a=a, perm=perm, name=name, conjugate=conjugate) + + +@tf_export(v1=["transpose"]) def transpose(a, perm=None, name="transpose", conjugate=False): """Transposes `a`. Permutes the dimensions according to `perm`. @@ -1678,7 +1809,7 @@ def zeros(shape, dtype=dtypes.float32, name=None): return output -@tf_export("zeros_like") +@tf_export(v1=["zeros_like"]) def zeros_like(tensor, dtype=None, name=None, optimize=True): """Creates a tensor with all elements set to zero. @@ -1705,6 +1836,42 @@ def zeros_like(tensor, dtype=None, name=None, optimize=True): Returns: A `Tensor` with all elements set to zero. """ + return zeros_like_impl(tensor, dtype, name, optimize) + + +@tf_export("zeros_like", v1=[]) +def zeros_like_v2( + input, # pylint: disable=redefined-builtin + dtype=None, + name=None): + """Creates a tensor with all elements set to zero. + + Given a single tensor (`tensor`), this operation returns a tensor of the + same type and shape as `tensor` with all elements set to zero. Optionally, + you can use `dtype` to specify a new type for the returned tensor. + + For example: + + ```python + tensor = tf.constant([[1, 2, 3], [4, 5, 6]]) + tf.zeros_like(tensor) # [[0, 0, 0], [0, 0, 0]] + ``` + + Args: + input: A `Tensor`. + dtype: A type for the returned `Tensor`. Must be `float16`, `float32`, + `float64`, `int8`, `uint8`, `int16`, `uint16`, `int32`, `int64`, + `complex64`, `complex128`, `bool` or `string`. + name: A name for the operation (optional). + + Returns: + A `Tensor` with all elements set to zero. + """ + return zeros_like_impl(input, dtype, name, optimize=True) + + +def zeros_like_impl(tensor, dtype, name, optimize=True): + """Internal implementation for the v1/v2 zeros_like API calls.""" with ops.name_scope(name, "zeros_like", [tensor]) as name: tensor = ops.convert_to_tensor(tensor, name="tensor") @@ -1731,7 +1898,7 @@ def zeros_like(tensor, dtype=None, name=None, optimize=True): return gen_array_ops.zeros_like(tensor, name=name) -@tf_export("ones_like") +@tf_export(v1=["ones_like"]) def ones_like(tensor, dtype=None, name=None, optimize=True): """Creates a tensor with all elements set to 1. @@ -1758,6 +1925,42 @@ def ones_like(tensor, dtype=None, name=None, optimize=True): Returns: A `Tensor` with all elements set to 1. """ + return ones_like_impl(tensor, dtype, name, optimize) + + +@tf_export("ones_like", v1=[]) +def ones_like_v2( + input, # pylint: disable=redefined-builtin + dtype=None, + name=None): + """Creates a tensor with all elements set to zero. + + Given a single tensor (`tensor`), this operation returns a tensor of the + same type and shape as `tensor` with all elements set to zero. Optionally, + you can use `dtype` to specify a new type for the returned tensor. + + For example: + + ```python + tensor = tf.constant([[1, 2, 3], [4, 5, 6]]) + tf.ones_like(tensor) # [[1, 1, 1], [1, 1, 1]] + ``` + + Args: + input: A `Tensor`. + dtype: A type for the returned `Tensor`. Must be `float16`, `float32`, + `float64`, `int8`, `uint8`, `int16`, `uint16`, `int32`, `int64`, + `complex64`, `complex128`, `bool` or `string`. + name: A name for the operation (optional). + + Returns: + A `Tensor` with all elements set to zero. + """ + return ones_like_impl(input, dtype, name, optimize=True) + + +def ones_like_impl(tensor, dtype, name, optimize=True): + """Internal implementation for the v1/v2 ones_like API calls.""" with ops.name_scope(name, "ones_like", [tensor]) as name: tensor = ops.convert_to_tensor(tensor, name="tensor") ones_shape = shape_internal(tensor, optimize=optimize) @@ -1955,7 +2158,65 @@ def sparse_placeholder(dtype, shape=None, name=None): # pylint: enable=redefined-outer-name -@tf_export("pad") +@tf_export("pad", v1=[]) +def pad_v2(tensor, paddings, mode="CONSTANT", constant_values=0, name=None): + """Pads a tensor. + + This operation pads a `tensor` according to the `paddings` you specify. + `paddings` is an integer tensor with shape `[n, 2]`, where n is the rank of + `tensor`. For each dimension D of `input`, `paddings[D, 0]` indicates how + many values to add before the contents of `tensor` in that dimension, and + `paddings[D, 1]` indicates how many values to add after the contents of + `tensor` in that dimension. If `mode` is "REFLECT" then both `paddings[D, 0]` + and `paddings[D, 1]` must be no greater than `tensor.dim_size(D) - 1`. If + `mode` is "SYMMETRIC" then both `paddings[D, 0]` and `paddings[D, 1]` must be + no greater than `tensor.dim_size(D)`. + + The padded size of each dimension D of the output is: + + `paddings[D, 0] + tensor.dim_size(D) + paddings[D, 1]` + + For example: + + ```python + t = tf.constant([[1, 2, 3], [4, 5, 6]]) + paddings = tf.constant([[1, 1,], [2, 2]]) + # 'constant_values' is 0. + # rank of 't' is 2. + tf.pad(t, paddings, "CONSTANT") # [[0, 0, 0, 0, 0, 0, 0], + # [0, 0, 1, 2, 3, 0, 0], + # [0, 0, 4, 5, 6, 0, 0], + # [0, 0, 0, 0, 0, 0, 0]] + + tf.pad(t, paddings, "REFLECT") # [[6, 5, 4, 5, 6, 5, 4], + # [3, 2, 1, 2, 3, 2, 1], + # [6, 5, 4, 5, 6, 5, 4], + # [3, 2, 1, 2, 3, 2, 1]] + + tf.pad(t, paddings, "SYMMETRIC") # [[2, 1, 1, 2, 3, 3, 2], + # [2, 1, 1, 2, 3, 3, 2], + # [5, 4, 4, 5, 6, 6, 5], + # [5, 4, 4, 5, 6, 6, 5]] + ``` + + Args: + tensor: A `Tensor`. + paddings: A `Tensor` of type `int32`. + mode: One of "CONSTANT", "REFLECT", or "SYMMETRIC" (case-insensitive) + constant_values: In "CONSTANT" mode, the scalar pad value to use. Must be + same type as `tensor`. + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type as `tensor`. + + Raises: + ValueError: When mode is not one of "CONSTANT", "REFLECT", or "SYMMETRIC". + """ + return pad(tensor, paddings, mode, name, constant_values) + + +@tf_export(v1=["pad"]) def pad(tensor, paddings, mode="CONSTANT", name=None, constant_values=0): # pylint: disable=invalid-name """Pads a tensor. @@ -2415,7 +2676,7 @@ def depth_to_space(input, block_size, name=None, data_format="NHWC"): # pylint: depth_to_space.__doc__ = gen_array_ops.depth_to_space.__doc__ -@tf_export("batch_to_space") +@tf_export(v1=["batch_to_space"]) def batch_to_space(input, crops, block_size, name=None): # pylint: disable=redefined-builtin result = batch_to_space_nd( input, @@ -2429,6 +2690,151 @@ def batch_to_space(input, crops, block_size, name=None): # pylint: disable=rede batch_to_space.__doc__ = gen_array_ops.batch_to_space.__doc__ +@tf_export("batch_to_space", v1=[]) +def batch_to_space_v2(input, block_shape, crops, name=None): # pylint: disable=redefined-builtin + """BatchToSpace for N-D tensors of type T. + + This operation reshapes the "batch" dimension 0 into `M + 1` dimensions of + shape `block_shape + [batch]`, interleaves these blocks back into the grid + defined by the spatial dimensions `[1, ..., M]`, to obtain a result with the + same rank as the input. The spatial dimensions of this intermediate result + are then optionally cropped according to `crops` to produce the output. This + is the reverse of SpaceToBatch. See below for a precise description. + + Args: + input: A `Tensor`. + N-D with shape `input_shape = [batch] + spatial_shape + remaining_shape`, + where spatial_shape has M dimensions. + block_shape: A `Tensor`. Must be one of the following types: + `int32`, `int64`. 1-D with shape `[M]`, all values must be >= 1. + For backwards compatibility with TF 1.0, this parameter may be an int, in + which case it is converted to + `numpy.array([block_shape, block_shape], dtype=numpy.int64)`. + crops: A `Tensor`. Must be one of the following types: `int32`, `int64`. + 2-D with shape `[M, 2]`, all values must be >= 0. + `crops[i] = [crop_start, crop_end]` specifies the amount to crop from + input dimension `i + 1`, which corresponds to spatial dimension `i`. It + is required that + `crop_start[i] + crop_end[i] <= block_shape[i] * input_shape[i + 1]`. + + This operation is equivalent to the following steps: + + 1. Reshape `input` to `reshaped` of shape: + [block_shape[0], ..., block_shape[M-1], + batch / prod(block_shape), + input_shape[1], ..., input_shape[N-1]] + + 2. Permute dimensions of `reshaped` to produce `permuted` of shape + [batch / prod(block_shape), + + input_shape[1], block_shape[0], + ..., + input_shape[M], block_shape[M-1], + + input_shape[M+1], ..., input_shape[N-1]] + + 3. Reshape `permuted` to produce `reshaped_permuted` of shape + [batch / prod(block_shape), + + input_shape[1] * block_shape[0], + ..., + input_shape[M] * block_shape[M-1], + + input_shape[M+1], + ..., + input_shape[N-1]] + + 4. Crop the start and end of dimensions `[1, ..., M]` of + `reshaped_permuted` according to `crops` to produce the + output of shape: + [batch / prod(block_shape), + + input_shape[1] * block_shape[0] - crops[0,0] - crops[0,1], + ..., + input_shape[M] * block_shape[M-1] - crops[M-1,0] - crops[M-1,1], + + input_shape[M+1], ..., input_shape[N-1]] + + Some examples: + + (1) For the following input of shape `[4, 1, 1, 1]`, + `block_shape = [2, 2]`, and `crops = [[0, 0], [0, 0]]`: + + ``` + [[[[1]]], [[[2]]], [[[3]]], [[[4]]]] + ``` + + The output tensor has shape `[1, 2, 2, 1]` and value: + + ``` + x = [[[[1], [2]], [[3], [4]]]] + ``` + + (2) For the following input of shape `[4, 1, 1, 3]`, + `block_shape = [2, 2]`, and `crops = [[0, 0], [0, 0]]`: + + ``` + [[[1, 2, 3]], [[4, 5, 6]], [[7, 8, 9]], [[10, 11, 12]]] + ``` + + The output tensor has shape `[1, 2, 2, 3]` and value: + + ``` + x = [[[[1, 2, 3], [4, 5, 6]], + [[7, 8, 9], [10, 11, 12]]]] + ``` + + (3) For the following input of shape `[4, 2, 2, 1]`, + `block_shape = [2, 2]`, and `crops = [[0, 0], [0, 0]]`: + + ``` + x = [[[[1], [3]], [[9], [11]]], + [[[2], [4]], [[10], [12]]], + [[[5], [7]], [[13], [15]]], + [[[6], [8]], [[14], [16]]]] + ``` + + The output tensor has shape `[1, 4, 4, 1]` and value: + + ``` + x = [[[1], [2], [3], [4]], + [[5], [6], [7], [8]], + [[9], [10], [11], [12]], + [[13], [14], [15], [16]]] + ``` + + (4) For the following input of shape `[8, 1, 3, 1]`, + `block_shape = [2, 2]`, and `crops = [[0, 0], [2, 0]]`: + + ``` + x = [[[[0], [1], [3]]], [[[0], [9], [11]]], + [[[0], [2], [4]]], [[[0], [10], [12]]], + [[[0], [5], [7]]], [[[0], [13], [15]]], + [[[0], [6], [8]]], [[[0], [14], [16]]]] + ``` + + The output tensor has shape `[2, 2, 4, 1]` and value: + + ``` + x = [[[[1], [2], [3], [4]], + [[5], [6], [7], [8]]], + [[[9], [10], [11], [12]], + [[13], [14], [15], [16]]]] + ``` + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type as `input`. + """ + if isinstance(block_shape, int): + block_shape = np.array([block_shape, block_shape], dtype=np.int64) + + return batch_to_space_nd(input=input, + block_shape=block_shape, + crops=crops, + name=name) + + @tf_export("one_hot") def one_hot(indices, depth, @@ -2652,7 +3058,7 @@ def sequence_mask(lengths, maxlen=None, dtype=dtypes.bool, name=None): return gen_math_ops.cast(result, dtype) -@tf_export("squeeze") +@tf_export(v1=["squeeze"]) @deprecation.deprecated_args(None, "Use the `axis` argument instead", "squeeze_dims") def squeeze(input, axis=None, name=None, squeeze_dims=None): @@ -2702,6 +3108,12 @@ def squeeze(input, axis=None, name=None, squeeze_dims=None): return gen_array_ops.squeeze(input, axis, name) +@tf_export("squeeze", v1=[]) +def squeeze_v2(input, axis=None, name=None): + # pylint: disable=redefined-builtin + return squeeze(input, axis, name) + + @tf_export("where") def where(condition, x=None, y=None, name=None): """Return the elements, either from `x` or `y`, depending on the `condition`. @@ -2756,7 +3168,7 @@ def where(condition, x=None, y=None, name=None): # pylint: disable=redefined-builtin -@tf_export("reverse_sequence") +@tf_export(v1=["reverse_sequence"]) @deprecation.deprecated_args( None, "seq_dim is deprecated, use seq_axis instead", "seq_dim") @deprecation.deprecated_args( @@ -2780,15 +3192,32 @@ def reverse_sequence(input, name=name) -# pylint: enable=redefined-builtin - reverse_sequence.__doc__ = deprecation.rewrite_argument_docstring( deprecation.rewrite_argument_docstring( gen_array_ops.reverse_sequence.__doc__, "batch_dim", "batch_axis"), "seq_dim", "seq_axis") -@tf_export("gather") +@tf_export("reverse_sequence", v1=[]) +def reverse_sequence_v2( + input, seq_lengths, seq_axis=None, batch_axis=None, name=None): + return gen_array_ops.reverse_sequence( + input=input, + seq_lengths=seq_lengths, + seq_dim=seq_axis, + batch_dim=batch_axis, + name=name) + + +reverse_sequence_v2.__doc__ = deprecation.rewrite_argument_docstring( + deprecation.rewrite_argument_docstring( + gen_array_ops.reverse_sequence.__doc__, "batch_dim", "batch_axis"), + "seq_dim", "seq_axis") + +# pylint: enable=redefined-builtin + + +@tf_export(v1=["gather"]) def gather(params, indices, validate_indices=None, name=None, axis=0): del validate_indices if axis != 0: @@ -2804,10 +3233,18 @@ def gather(params, indices, validate_indices=None, name=None, axis=0): return gen_array_ops.gather_v2(params, indices, axis, name=name) -gather.__doc__ = gen_array_ops.gather_v2.__doc__ +@tf_export("gather", v1=[]) +def gather_v2(params, indices, validate_indices=None, axis=0, name=None): + return gather(params, indices, validate_indices=validate_indices, name=name, + axis=axis) + + +gather.__doc__ = gather_v2.__doc__ = gen_array_ops.gather_v2.__doc__ + @tf_export("batch_gather") +@dispatch.add_dispatch_support def batch_gather(params, indices, name=None): """Gather slices from `params` according to `indices` with leading batch dims. @@ -2885,7 +3322,7 @@ def batch_gather(params, indices, name=None): # Define quantize_v2 here in order to make name the second-to-last attribute, # because round_mode was added later. -@tf_export("quantize_v2") +@tf_export(v1=["quantize_v2"]) @deprecation.deprecated( "2017-10-25", "`tf.quantize_v2` is deprecated, please use `tf.quantization.quantize` " @@ -2906,7 +3343,7 @@ def quantize_v2(input, # pylint: disable=redefined-builtin round_mode=round_mode) -quantize_v2.__doc__ = """Please use `tf.quantize` instead.""" +quantize_v2.__doc__ = """Please use `tf.quantization.quantize` instead.""" # We want to expose tf.quantize instead of tf.quantize_v2; we can deprecate @@ -2992,3 +3429,48 @@ def searchsorted(sorted_sequence, quantize.__doc__ = gen_array_ops.quantize_v2.__doc__ + + +@tf_export("image.extract_image_patches", v1=[]) +def extract_image_patches_v2( + images, + sizes, + strides, + rates, + padding, + name=None): + # pylint: disable=line-too-long + r"""Extract `patches` from `images` and put them in the \"depth\" output dimension. + + Args: + images: A 4-D Tensor with shape `[batch, in_rows, in_cols, depth] + sizes: The size of the sliding window for each dimension of `images`. + strides: A 1-D Tensor of length 4. How far the centers of two consecutive + patches are in the images. Must be: `[1, stride_rows, stride_cols, 1]`. + rates: A 1-D Tensor of length 4. Must be: `[1, rate_rows, rate_cols, 1]`. + This is the input stride, specifying how far two consecutive patch samples + are in the input. Equivalent to extracting patches with `patch_sizes_eff = + patch_sizes + (patch_sizes - 1) * (rates - 1)`, followed by subsampling + them spatially by a factor of `rates`. This is equivalent to `rate` in + dilated (a.k.a. Atrous) convolutions. + padding: The type of padding algorithm to use. + We specify the size-related attributes as: ```python ksizes = [1, + ksize_rows, ksize_cols, 1] strides = [1, strides_rows, strides_cols, 1] + rates = [1, rates_rows, rates_cols, 1] + name: A name for the operation (optional). + + Returns: + A 4-D Tensor. Has the same type as `images`, and with shape `[batch, + out_rows, out_cols, ksize_rows * ksize_cols * depth]` containing image + patches with size `ksize_rows x ksize_cols x depth` vectorized in the + \"depth\" dimension. Note `out_rows` and `out_cols` are the dimensions of + the output patches. + """ + # pylint: enable=line-too-long + return gen_array_ops.extract_image_patches( + images, sizes, strides, rates, padding, name) + +extract_image_patches_deprecation = deprecation.deprecated_args( + None, "ksizes is deprecated, use sizes instead", "ksizes") +tf_export(v1=["image.extract_image_patches", "extract_image_patches"])( + extract_image_patches_deprecation(gen_array_ops.extract_image_patches)) diff --git a/tensorflow/python/ops/bitwise_ops_test.py b/tensorflow/python/ops/bitwise_ops_test.py index dfb40db2d5..d154b6759b 100644 --- a/tensorflow/python/ops/bitwise_ops_test.py +++ b/tensorflow/python/ops/bitwise_ops_test.py @@ -34,6 +34,7 @@ class BitwiseOpTest(test_util.TensorFlowTestCase): def __init__(self, method_name="runTest"): super(BitwiseOpTest, self).__init__(method_name) + @test_util.run_deprecated_v1 def testBinaryOps(self): dtype_list = [dtypes.int8, dtypes.int16, dtypes.int32, dtypes.int64, dtypes.uint8, dtypes.uint16, dtypes.uint32, dtypes.uint64] @@ -59,16 +60,18 @@ class BitwiseOpTest(test_util.TensorFlowTestCase): 2**31 - 1, 2**31, 2**32 - 1, 2**32, -2**32 + 1, -2**32, -2**63 + 1, 2**63 - 1] def count_bits(x): - return sum([bin(z).count("1") for z in six.iterbytes(x.tobytes())]) + return sum(bin(z).count("1") for z in six.iterbytes(x.tobytes())) for dtype in dtype_list: with self.cached_session(use_gpu=True) as sess: print("PopulationCount test: ", dtype) inputs = np.array(raw_inputs, dtype=dtype.as_numpy_dtype) truth = [count_bits(x) for x in inputs] input_tensor = constant_op.constant(inputs, dtype=dtype) - popcnt_result = sess.run(gen_bitwise_ops.population_count(input_tensor)) + popcnt_result = self.evaluate( + gen_bitwise_ops.population_count(input_tensor)) self.assertAllEqual(truth, popcnt_result) + @test_util.run_deprecated_v1 def testInvertOp(self): dtype_list = [dtypes.int8, dtypes.int16, dtypes.int32, dtypes.int64, dtypes.uint8, dtypes.uint16, dtypes.uint32, dtypes.uint64] @@ -89,10 +92,11 @@ class BitwiseOpTest(test_util.TensorFlowTestCase): self.assertAllEqual(not_a_or_a, [not_0] * 4) # For unsigned dtypes let's also check the result directly. if dtype.is_unsigned: - inverted = sess.run(bitwise_ops.invert(input_tensor)) + inverted = self.evaluate(bitwise_ops.invert(input_tensor)) expected = [dtype.max - x for x in inputs] self.assertAllEqual(inverted, expected) + @test_util.run_deprecated_v1 def testShiftsWithPositiveLHS(self): dtype_list = [np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64] @@ -107,6 +111,7 @@ class BitwiseOpTest(test_util.TensorFlowTestCase): self.assertAllEqual(left_shift_result, np.left_shift(lhs, rhs)) self.assertAllEqual(right_shift_result, np.right_shift(lhs, rhs)) + @test_util.run_deprecated_v1 def testShiftsWithNegativeLHS(self): dtype_list = [np.int8, np.int16, np.int32, np.int64] @@ -120,6 +125,7 @@ class BitwiseOpTest(test_util.TensorFlowTestCase): self.assertAllEqual(left_shift_result, np.left_shift(lhs, rhs)) self.assertAllEqual(right_shift_result, np.right_shift(lhs, rhs)) + @test_util.run_deprecated_v1 def testImplementationDefinedShiftsDoNotCrash(self): dtype_list = [np.int8, np.int16, np.int32, np.int64] @@ -135,6 +141,7 @@ class BitwiseOpTest(test_util.TensorFlowTestCase): bitwise_ops.right_shift(lhs, rhs)]) + @test_util.run_deprecated_v1 def testShapeInference(self): dtype_list = [dtypes.int8, dtypes.int16, dtypes.int32, dtypes.int64, dtypes.uint8, dtypes.uint16] diff --git a/tensorflow/python/ops/candidate_sampling_ops.py b/tensorflow/python/ops/candidate_sampling_ops.py index f0bfdb2b7a..c64000b65d 100644 --- a/tensorflow/python/ops/candidate_sampling_ops.py +++ b/tensorflow/python/ops/candidate_sampling_ops.py @@ -208,7 +208,9 @@ def learned_unigram_candidate_sampler(true_classes, num_true, num_sampled, seed2=seed2, name=name) -@tf_export('nn.fixed_unigram_candidate_sampler') +@tf_export('random.fixed_unigram_candidate_sampler', + 'nn.fixed_unigram_candidate_sampler', + v1=['nn.fixed_unigram_candidate_sampler']) def fixed_unigram_candidate_sampler(true_classes, num_true, num_sampled, @@ -300,7 +302,8 @@ def fixed_unigram_candidate_sampler(true_classes, unigrams=unigrams, seed=seed1, seed2=seed2, name=name) -@tf_export('nn.all_candidate_sampler') +@tf_export('random.all_candidate_sampler', 'nn.all_candidate_sampler', + v1=['nn.all_candidate_sampler']) def all_candidate_sampler(true_classes, num_true, num_sampled, unique, seed=None, name=None): """Generate the set of all classes. diff --git a/tensorflow/python/ops/check_ops.py b/tensorflow/python/ops/check_ops.py index 5589bbc848..f1f36269cf 100644 --- a/tensorflow/python/ops/check_ops.py +++ b/tensorflow/python/ops/check_ops.py @@ -119,9 +119,31 @@ def assert_proper_iterable(values): 'Expected argument "values" to be iterable. Found: %s' % type(values)) -@tf_export( - 'debugging.assert_negative', - v1=['debugging.assert_negative', 'assert_negative']) +@tf_export('debugging.assert_negative', v1=[]) +def assert_negative_v2(x, message=None, summarize=None, name=None): + """Assert the condition `x < 0` holds element-wise. + + This Op checks that `x[i] < 0` holds for every element of `x`. If `x` is + empty, this is trivially satisfied. + + If `x` is not negative everywhere, `message`, as well as the first `summarize` + entries of `x` are printed, and `InvalidArgumentError` is raised. + + Args: + x: Numeric `Tensor`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to "assert_negative". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x[i] < 0` is False. The check can be performed immediately during eager + execution or if `x` is statically known. + """ + assert_negative(x=x, message=message, summarize=summarize, name=name) + + +@tf_export(v1=['debugging.assert_negative', 'assert_negative']) @deprecation.deprecated_endpoints('assert_negative') def assert_negative(x, data=None, summarize=None, message=None, name=None): """Assert the condition `x < 0` holds element-wise. @@ -163,9 +185,31 @@ def assert_negative(x, data=None, summarize=None, message=None, name=None): return assert_less(x, zero, data=data, summarize=summarize) -@tf_export( - 'debugging.assert_positive', - v1=['debugging.assert_positive', 'assert_positive']) +@tf_export('debugging.assert_positive', v1=[]) +def assert_positive_v2(x, message=None, summarize=None, name=None): + """Assert the condition `x > 0` holds element-wise. + + This Op checks that `x[i] > 0` holds for every element of `x`. If `x` is + empty, this is trivially satisfied. + + If `x` is not positive everywhere, `message`, as well as the first `summarize` + entries of `x` are printed, and `InvalidArgumentError` is raised. + + Args: + x: Numeric `Tensor`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to "assert_positive". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x[i] > 0` is False. The check can be performed immediately during eager + execution or if `x` is statically known. + """ + assert_positive(x=x, summarize=summarize, message=message, name=name) + + +@tf_export(v1=['debugging.assert_positive', 'assert_positive']) @deprecation.deprecated_endpoints('assert_positive') def assert_positive(x, data=None, summarize=None, message=None, name=None): """Assert the condition `x > 0` holds element-wise. @@ -206,9 +250,32 @@ def assert_positive(x, data=None, summarize=None, message=None, name=None): return assert_less(zero, x, data=data, summarize=summarize) -@tf_export( - 'debugging.assert_non_negative', - v1=['debugging.assert_non_negative', 'assert_non_negative']) +@tf_export('debugging.assert_non_negative', v1=[]) +def assert_non_negative_v2(x, message=None, summarize=None, name=None): + """Assert the condition `x >= 0` holds element-wise. + + This Op checks that `x[i] >= 0` holds for every element of `x`. If `x` is + empty, this is trivially satisfied. + + If `x` is not >= 0 everywhere, `message`, as well as the first `summarize` + entries of `x` are printed, and `InvalidArgumentError` is raised. + + Args: + x: Numeric `Tensor`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to + "assert_non_negative". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x[i] >= 0` is False. The check can be performed immediately during eager + execution or if `x` is statically known. + """ + assert_non_negative(x=x, summarize=summarize, message=message, name=name) + + +@tf_export(v1=['debugging.assert_non_negative', 'assert_non_negative']) @deprecation.deprecated_endpoints('assert_non_negative') def assert_non_negative(x, data=None, summarize=None, message=None, name=None): """Assert the condition `x >= 0` holds element-wise. @@ -251,9 +318,32 @@ def assert_non_negative(x, data=None, summarize=None, message=None, name=None): return assert_less_equal(zero, x, data=data, summarize=summarize) -@tf_export( - 'debugging.assert_non_positive', - v1=['debugging.assert_non_positive', 'assert_non_positive']) +@tf_export('debugging.assert_non_positive', v1=[]) +def assert_non_positive_v2(x, message=None, summarize=None, name=None): + """Assert the condition `x <= 0` holds element-wise. + + This Op checks that `x[i] <= 0` holds for every element of `x`. If `x` is + empty, this is trivially satisfied. + + If `x` is not <= 0 everywhere, `message`, as well as the first `summarize` + entries of `x` are printed, and `InvalidArgumentError` is raised. + + Args: + x: Numeric `Tensor`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to + "assert_non_positive". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x[i] <= 0` is False. The check can be performed immediately during eager + execution or if `x` is statically known. + """ + assert_non_positive(x=x, summarize=summarize, message=message, name=name) + + +@tf_export(v1=['debugging.assert_non_positive', 'assert_non_positive']) @deprecation.deprecated_endpoints('assert_non_positive') def assert_non_positive(x, data=None, summarize=None, message=None, name=None): """Assert the condition `x <= 0` holds element-wise. @@ -296,7 +386,33 @@ def assert_non_positive(x, data=None, summarize=None, message=None, name=None): return assert_less_equal(x, zero, data=data, summarize=summarize) -@tf_export('debugging.assert_equal', 'assert_equal') +@tf_export('debugging.assert_equal', 'assert_equal', v1=[]) +def assert_equal_v2(x, y, message=None, summarize=None, name=None): + """Assert the condition `x == y` holds element-wise. + + This Op checks that `x[i] == y[i]` holds for every pair of (possibly + broadcast) elements of `x` and `y`. If both `x` and `y` are empty, this is + trivially satisfied. + + If `x` and `y` are not equal, `message`, as well as the first `summarize` + entries of `x` and `y` are printed, and `InvalidArgumentError` is raised. + + Args: + x: Numeric `Tensor`. + y: Numeric `Tensor`, same dtype as and broadcastable to `x`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to "assert_equal". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x == y` is False. The check can be performed immediately during eager + execution or if `x` and `y` are statically known. + """ + assert_equal(x=x, y=y, summarize=summarize, message=message, name=name) + + +@tf_export(v1=['debugging.assert_equal', 'assert_equal']) def assert_equal(x, y, data=None, summarize=None, message=None, name=None): """Assert the condition `x == y` holds element-wise. @@ -396,9 +512,36 @@ def assert_equal(x, y, data=None, summarize=None, message=None, name=None): return control_flow_ops.Assert(condition, data, summarize=summarize) -@tf_export( - 'debugging.assert_none_equal', - v1=['debugging.assert_none_equal', 'assert_none_equal']) +@tf_export('debugging.assert_none_equal', v1=[]) +def assert_none_equal_v2(x, y, summarize=None, message=None, name=None): + """Assert the condition `x != y` holds for all elements. + + This Op checks that `x[i] != y[i]` holds for every pair of (possibly + broadcast) elements of `x` and `y`. If both `x` and `y` are empty, this is + trivially satisfied. + + If any elements of `x` and `y` are equal, `message`, as well as the first + `summarize` entries of `x` and `y` are printed, and `InvalidArgumentError` + is raised. + + Args: + x: Numeric `Tensor`. + y: Numeric `Tensor`, same dtype as and broadcastable to `x`. + summarize: Print this many entries of each tensor. + message: A string to prefix to the default message. + name: A name for this operation (optional). Defaults to + "assert_none_equal". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x != y` is False for any pair of elements in `x` and `y`. The check can + be performed immediately during eager execution or if `x` and `y` are + statically known. + """ + assert_none_equal(x=x, y=y, summarize=summarize, message=message, name=name) + + +@tf_export(v1=['debugging.assert_none_equal', 'assert_none_equal']) @deprecation.deprecated_endpoints('assert_none_equal') def assert_none_equal( x, y, data=None, summarize=None, message=None, name=None): @@ -450,7 +593,52 @@ def assert_none_equal( return control_flow_ops.Assert(condition, data, summarize=summarize) -@tf_export('debugging.assert_near', v1=['debugging.assert_near', 'assert_near']) +@tf_export('debugging.assert_near', v1=[]) +def assert_near_v2(x, y, rtol=None, atol=None, message=None, summarize=None, + name=None): + """Assert the condition `x` and `y` are close element-wise. + + This Op checks that `x[i] - y[i] < atol + rtol * tf.abs(y[i])` holds for every + pair of (possibly broadcast) elements of `x` and `y`. If both `x` and `y` are + empty, this is trivially satisfied. + + If any elements of `x` and `y` are not close, `message`, as well as the first + `summarize` entries of `x` and `y` are printed, and `InvalidArgumentError` + is raised. + + The default `atol` and `rtol` is `10 * eps`, where `eps` is the smallest + representable positive number such that `1 + eps != 1`. This is about + `1.2e-6` in `32bit`, `2.22e-15` in `64bit`, and `0.00977` in `16bit`. + See `numpy.finfo`. + + Args: + x: Float or complex `Tensor`. + y: Float or complex `Tensor`, same dtype as and broadcastable to `x`. + rtol: `Tensor`. Same `dtype` as, and broadcastable to, `x`. + The relative tolerance. Default is `10 * eps`. + atol: `Tensor`. Same `dtype` as, and broadcastable to, `x`. + The absolute tolerance. Default is `10 * eps`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to "assert_near". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x != y` is False for any pair of elements in `x` and `y`. The check can + be performed immediately during eager execution or if `x` and `y` are + statically known. + + @compatibility(numpy) + Similar to `numpy.assert_allclose`, except tolerance depends on data type. + This is due to the fact that `TensorFlow` is often used with `32bit`, `64bit`, + and even `16bit` data. + @end_compatibility + """ + assert_near(x=x, y=y, rtol=rtol, atol=atol, summarize=summarize, + message=message, name=name) + + +@tf_export(v1=['debugging.assert_near', 'assert_near']) @deprecation.deprecated_endpoints('assert_near') def assert_near( x, y, rtol=None, atol=None, data=None, summarize=None, message=None, @@ -529,7 +717,34 @@ def assert_near( return control_flow_ops.Assert(condition, data, summarize=summarize) -@tf_export('debugging.assert_less', 'assert_less') +@tf_export('debugging.assert_less', 'assert_less', v1=[]) +def assert_less_v2(x, y, message=None, summarize=None, name=None): + """Assert the condition `x < y` holds element-wise. + + This Op checks that `x[i] < y[i]` holds for every pair of (possibly + broadcast) elements of `x` and `y`. If both `x` and `y` are empty, this is + trivially satisfied. + + If `x` is not less than `y` element-wise, `message`, as well as the first + `summarize` entries of `x` and `y` are printed, and `InvalidArgumentError` is + raised. + + Args: + x: Numeric `Tensor`. + y: Numeric `Tensor`, same dtype as and broadcastable to `x`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to "assert_less". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x < y` is False. The check can be performed immediately during eager + execution or if `x` and `y` are statically known. + """ + assert_less(x=x, y=y, summarize=summarize, message=message, name=name) + + +@tf_export(v1=['debugging.assert_less', 'assert_less']) def assert_less(x, y, data=None, summarize=None, message=None, name=None): """Assert the condition `x < y` holds element-wise. @@ -577,9 +792,34 @@ def assert_less(x, y, data=None, summarize=None, message=None, name=None): return control_flow_ops.Assert(condition, data, summarize=summarize) -@tf_export( - 'debugging.assert_less_equal', - v1=['debugging.assert_less_equal', 'assert_less_equal']) +@tf_export('debugging.assert_less_equal', v1=[]) +def assert_less_equal_v2(x, y, message=None, summarize=None, name=None): + """Assert the condition `x <= y` holds element-wise. + + This Op checks that `x[i] <= y[i]` holds for every pair of (possibly + broadcast) elements of `x` and `y`. If both `x` and `y` are empty, this is + trivially satisfied. + + If `x` is not less or equal than `y` element-wise, `message`, as well as the + first `summarize` entries of `x` and `y` are printed, and + `InvalidArgumentError` is raised. + + Args: + x: Numeric `Tensor`. + y: Numeric `Tensor`, same dtype as and broadcastable to `x`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to "assert_less_equal". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x <= y` is False. The check can be performed immediately during eager + execution or if `x` and `y` are statically known. + """ + assert_less_equal(x=x, y=y, summarize=summarize, message=message, name=name) + + +@tf_export(v1=['debugging.assert_less_equal', 'assert_less_equal']) @deprecation.deprecated_endpoints('assert_less_equal') def assert_less_equal(x, y, data=None, summarize=None, message=None, name=None): """Assert the condition `x <= y` holds element-wise. @@ -628,7 +868,34 @@ def assert_less_equal(x, y, data=None, summarize=None, message=None, name=None): return control_flow_ops.Assert(condition, data, summarize=summarize) -@tf_export('debugging.assert_greater', 'assert_greater') +@tf_export('debugging.assert_greater', 'assert_greater', v1=[]) +def assert_greater_v2(x, y, message=None, summarize=None, name=None): + """Assert the condition `x > y` holds element-wise. + + This Op checks that `x[i] > y[i]` holds for every pair of (possibly + broadcast) elements of `x` and `y`. If both `x` and `y` are empty, this is + trivially satisfied. + + If `x` is not greater than `y` element-wise, `message`, as well as the first + `summarize` entries of `x` and `y` are printed, and `InvalidArgumentError` is + raised. + + Args: + x: Numeric `Tensor`. + y: Numeric `Tensor`, same dtype as and broadcastable to `x`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to "assert_greater". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x > y` is False. The check can be performed immediately during eager + execution or if `x` and `y` are statically known. + """ + assert_greater(x=x, y=y, summarize=summarize, message=message, name=name) + + +@tf_export(v1=['debugging.assert_greater', 'assert_greater']) def assert_greater(x, y, data=None, summarize=None, message=None, name=None): """Assert the condition `x > y` holds element-wise. @@ -676,9 +943,36 @@ def assert_greater(x, y, data=None, summarize=None, message=None, name=None): return control_flow_ops.Assert(condition, data, summarize=summarize) -@tf_export( - 'debugging.assert_greater_equal', - v1=['debugging.assert_greater_equal', 'assert_greater_equal']) +@tf_export('debugging.assert_greater_equal', v1=[]) +def assert_greater_equal_v2(x, y, message=None, summarize=None, name=None): + """Assert the condition `x >= y` holds element-wise. + + This Op checks that `x[i] >= y[i]` holds for every pair of (possibly + broadcast) elements of `x` and `y`. If both `x` and `y` are empty, this is + trivially satisfied. + + If `x` is not greater or equal to `y` element-wise, `message`, as well as the + first `summarize` entries of `x` and `y` are printed, and + `InvalidArgumentError` is raised. + + Args: + x: Numeric `Tensor`. + y: Numeric `Tensor`, same dtype as and broadcastable to `x`. + message: A string to prefix to the default message. + summarize: Print this many entries of each tensor. + name: A name for this operation (optional). Defaults to + "assert_greater_equal". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x >= y` is False. The check can be performed immediately during eager + execution or if `x` and `y` are statically known. + """ + assert_greater_equal(x=x, y=y, summarize=summarize, message=message, + name=name) + + +@tf_export(v1=['debugging.assert_greater_equal', 'assert_greater_equal']) @deprecation.deprecated_endpoints('assert_greater_equal') def assert_greater_equal(x, y, data=None, summarize=None, message=None, name=None): @@ -777,7 +1071,31 @@ def _assert_rank_condition( return control_flow_ops.Assert(condition, data, summarize=summarize) -@tf_export('debugging.assert_rank', 'assert_rank') +@tf_export('debugging.assert_rank', 'assert_rank', v1=[]) +def assert_rank_v2(x, rank, message=None, name=None): + """Assert that `x` has rank equal to `rank`. + + This Op checks that the rank of `x` is equal to `rank`. + + If `x` has a different rank, `message`, as well as the shape of `x` are + printed, and `InvalidArgumentError` is raised. + + Args: + x: `Tensor`. + rank: Scalar integer `Tensor`. + message: A string to prefix to the default message. + name: A name for this operation (optional). Defaults to + "assert_rank". + + Raises: + InvalidArgumentError: if the check can be performed immediately and + `x` does not have rank `rank`. The check can be performed immediately + during eager execution or if the shape of `x` is statically known. + """ + assert_rank(x=x, rank=rank, message=message, name=name) + + +@tf_export(v1=['debugging.assert_rank', 'assert_rank']) def assert_rank(x, rank, data=None, summarize=None, message=None, name=None): """Assert `x` has rank equal to `rank`. @@ -792,7 +1110,7 @@ def assert_rank(x, rank, data=None, summarize=None, message=None, name=None): x: Numeric `Tensor`. rank: Scalar integer `Tensor`. data: The tensors to print out if the condition is False. Defaults to - error message and first few entries of `x`. + error message and the shape of `x`. summarize: Print this many entries of each tensor. message: A string to prefix to the default message. name: A name for this operation (optional). Defaults to "assert_rank". @@ -839,9 +1157,31 @@ def assert_rank(x, rank, data=None, summarize=None, message=None, name=None): return assert_op -@tf_export( - 'debugging.assert_rank_at_least', - v1=['debugging.assert_rank_at_least', 'assert_rank_at_least']) +@tf_export('debugging.assert_rank_at_least', v1=[]) +def assert_rank_at_least_v2(x, rank, message=None, name=None): + """Assert that `x` has rank of at least `rank`. + + This Op checks that the rank of `x` is greater or equal to `rank`. + + If `x` has a rank lower than `rank`, `message`, as well as the shape of `x` + are printed, and `InvalidArgumentError` is raised. + + Args: + x: `Tensor`. + rank: Scalar integer `Tensor`. + message: A string to prefix to the default message. + name: A name for this operation (optional). Defaults to + "assert_rank_at_least". + + Raises: + InvalidArgumentError: `x` does not have rank at least `rank`, but the rank + cannot be statically determined. + ValueError: If static checks determine `x` has mismatched rank. + """ + assert_rank_at_least(x=x, rank=rank, message=message, name=name) + + +@tf_export(v1=['debugging.assert_rank_at_least', 'assert_rank_at_least']) @deprecation.deprecated_endpoints('assert_rank_at_least') def assert_rank_at_least( x, rank, data=None, summarize=None, message=None, name=None): @@ -973,9 +1313,30 @@ def _assert_ranks_condition( return control_flow_ops.Assert(condition, data, summarize=summarize) -@tf_export( - 'debugging.assert_rank_in', - v1=['debugging.assert_rank_in', 'assert_rank_in']) +@tf_export('debugging.assert_rank_in', v1=[]) +def assert_rank_in_v2(x, ranks, message=None, name=None): + """Assert that `x` has a rank in `ranks`. + + This Op checks that the rank of `x` is in `ranks`. + + If `x` has a different rank, `message`, as well as the shape of `x` are + printed, and `InvalidArgumentError` is raised. + + Args: + x: `Tensor`. + ranks: `Iterable` of scalar `Tensor` objects. + message: A string to prefix to the default message. + name: A name for this operation (optional). Defaults to "assert_rank_in". + + Raises: + InvalidArgumentError: `x` does not have rank in `ranks`, but the rank cannot + be statically determined. + ValueError: If static checks determine `x` has mismatched rank. + """ + assert_rank_in(x=x, ranks=ranks, message=message, name=name) + + +@tf_export(v1=['debugging.assert_rank_in', 'assert_rank_in']) @deprecation.deprecated_endpoints('assert_rank_in') def assert_rank_in( x, ranks, data=None, summarize=None, message=None, name=None): @@ -1038,9 +1399,25 @@ def assert_rank_in( return assert_op -@tf_export( - 'debugging.assert_integer', - v1=['debugging.assert_integer', 'assert_integer']) +@tf_export('debugging.assert_integer', v1=[]) +def assert_integer_v2(x, message=None, name=None): + """Assert that `x` is of integer dtype. + + If `x` has a non-integer type, `message`, as well as the dtype of `x` are + printed, and `InvalidArgumentError` is raised. + + Args: + x: A `Tensor`. + message: A string to prefix to the default message. + name: A name for this operation (optional). Defaults to "assert_integer". + + Raises: + TypeError: If `x.dtype` is not a non-quantized integer type. + """ + assert_integer(x=x, message=message, name=name) + + +@tf_export(v1=['debugging.assert_integer', 'assert_integer']) @deprecation.deprecated_endpoints('assert_integer') def assert_integer(x, message=None, name=None): """Assert that `x` is of integer dtype. @@ -1079,13 +1456,30 @@ def assert_integer(x, message=None, name=None): return control_flow_ops.no_op('statically_determined_was_integer') -@tf_export('debugging.assert_type', v1=['debugging.assert_type', 'assert_type']) +@tf_export('debugging.assert_type', v1=[]) +def assert_type_v2(tensor, tf_type, message=None, name=None): + """Asserts that the given `Tensor` is of the specified type. + + Args: + tensor: A `Tensor`. + tf_type: A tensorflow type (`dtypes.float32`, `tf.int64`, `dtypes.bool`, + etc). + message: A string to prefix to the default message. + name: A name for this operation. Defaults to "assert_type" + + Raises: + TypeError: If the tensor's data type doesn't match `tf_type`. + """ + assert_type(tensor=tensor, tf_type=tf_type, message=message, name=name) + + +@tf_export(v1=['debugging.assert_type', 'assert_type']) @deprecation.deprecated_endpoints('assert_type') def assert_type(tensor, tf_type, message=None, name=None): """Statically asserts that the given `Tensor` is of the specified type. Args: - tensor: A tensorflow `Tensor`. + tensor: A `Tensor`. tf_type: A tensorflow type (`dtypes.float32`, `tf.int64`, `dtypes.bool`, etc). message: A string to prefix to the default message. @@ -1136,9 +1530,13 @@ def is_numeric_tensor(tensor): @tf_export( - 'debugging.is_non_decreasing', - v1=['debugging.is_non_decreasing', 'is_non_decreasing']) -@deprecation.deprecated_endpoints('is_non_decreasing') + 'math.is_non_decreasing', + v1=[ + 'math.is_non_decreasing', 'debugging.is_non_decreasing', + 'is_non_decreasing' + ]) +@deprecation.deprecated_endpoints('debugging.is_non_decreasing', + 'is_non_decreasing') def is_non_decreasing(x, name=None): """Returns `True` if `x` is non-decreasing. @@ -1166,9 +1564,13 @@ def is_non_decreasing(x, name=None): @tf_export( - 'debugging.is_strictly_increasing', - v1=['debugging.is_strictly_increasing', 'is_strictly_increasing']) -@deprecation.deprecated_endpoints('is_strictly_increasing') + 'math.is_strictly_increasing', + v1=[ + 'math.is_strictly_increasing', 'debugging.is_strictly_increasing', + 'is_strictly_increasing' + ]) +@deprecation.deprecated_endpoints('debugging.is_strictly_increasing', + 'is_strictly_increasing') def is_strictly_increasing(x, name=None): """Returns `True` if `x` is strictly increasing. @@ -1260,8 +1662,10 @@ def assert_same_float_dtype(tensors=None, dtype=None): tensors: Tensors of input values. Can include `None` elements, which will be ignored. dtype: Expected type. + Returns: Validated type. + Raises: ValueError: if neither `tensors` nor `dtype` is supplied, or result is not float, or the common type of the inputs is not a floating point type. @@ -1275,20 +1679,57 @@ def assert_same_float_dtype(tensors=None, dtype=None): return dtype -@tf_export( - 'debugging.assert_scalar', v1=['debugging.assert_scalar', 'assert_scalar']) +@tf_export('debugging.assert_scalar', v1=[]) +def assert_scalar_v2(tensor, message=None, name=None): + """Asserts that the given `tensor` is a scalar. + + This function raises `ValueError` unless it can be certain that the given + `tensor` is a scalar. `ValueError` is also raised if the shape of `tensor` is + unknown. + + Args: + tensor: A `Tensor`. + message: A string to prefix to the default message. + name: A name for this operation. Defaults to "assert_scalar" + + Raises: + ValueError: If the tensor is not scalar (rank 0), or if its shape is + unknown. + """ + assert_scalar(tensor=tensor, message=message, name=name) + + +@tf_export(v1=['debugging.assert_scalar', 'assert_scalar']) @deprecation.deprecated_endpoints('assert_scalar') -def assert_scalar(tensor, name=None): +def assert_scalar(tensor, name=None, message=None): + """Asserts that the given `tensor` is a scalar. + + This function raises `ValueError` unless it can be certain that the given + `tensor` is a scalar. `ValueError` is also raised if the shape of `tensor` is + unknown. + + Args: + tensor: A `Tensor`. + name: A name for this operation. Defaults to "assert_scalar" + message: A string to prefix to the default message. + + Returns: + The input tensor (potentially converted to a `Tensor`). + + Raises: + ValueError: If the tensor is not scalar (rank 0), or if its shape is + unknown. + """ with ops.name_scope(name, 'assert_scalar', [tensor]) as name_scope: tensor = ops.convert_to_tensor(tensor, name=name_scope) shape = tensor.get_shape() if shape.ndims != 0: if context.executing_eagerly(): - raise ValueError('Expected scalar shape, saw shape: %s.' - % (shape,)) + raise ValueError('%sExpected scalar shape, saw shape: %s.' + % (message or '', shape,)) else: - raise ValueError('Expected scalar shape for %s, saw shape: %s.' - % (tensor.name, shape)) + raise ValueError('%sExpected scalar shape for %s, saw shape: %s.' + % (message or '', tensor.name, shape)) return tensor diff --git a/tensorflow/python/ops/clip_ops.py b/tensorflow/python/ops/clip_ops.py index 5cd626b92d..82803ac351 100644 --- a/tensorflow/python/ops/clip_ops.py +++ b/tensorflow/python/ops/clip_ops.py @@ -300,7 +300,12 @@ def clip_by_global_norm(t_list, clip_norm, use_norm=None, name=None): return list_clipped, use_norm -@tf_export("clip_by_average_norm") +@deprecation.deprecated( + date=None, + instructions= + "clip_by_average_norm is deprecated in TensorFlow 2.0. Please use " + "clip_by_norm(t, clip_norm * tf.to_float(tf.size(t), name)) instead.") +@tf_export(v1=["clip_by_average_norm"]) def clip_by_average_norm(t, clip_norm, name=None): """Clips tensor values to a maximum average L2-norm. diff --git a/tensorflow/python/ops/clip_ops_test.py b/tensorflow/python/ops/clip_ops_test.py index 8aa9c4ffb3..a59a0c22d4 100644 --- a/tensorflow/python/ops/clip_ops_test.py +++ b/tensorflow/python/ops/clip_ops_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import clip_ops from tensorflow.python.ops import numerics from tensorflow.python.platform import test @@ -35,7 +36,7 @@ class ClipOpsTest(test.TestCase): input_op = constant_op.constant(inputs) clipped = clip_ops.clip_by_norm(input_op, max_norm) check_op = numerics.add_check_numerics_ops() - result, _ = sess.run([clipped, check_op]) + result, _ = self.evaluate([clipped, check_op]) self.assertAllClose(result, expected) def _testClipIndexedSlicesByNorm(self, values, indices, shape, max_norm, @@ -54,9 +55,10 @@ class ClipOpsTest(test.TestCase): # Tensor mode dense_tensor = ops.convert_to_tensor(indixed_slices) dense_clipped = clip_ops.clip_by_norm(dense_tensor, max_norm, axes) - result, expected = sess.run([clipped, dense_clipped]) + result, expected = self.evaluate([clipped, dense_clipped]) self.assertAllClose(result, expected) + @test_util.run_deprecated_v1 def testClipTensorByNorm(self): # Simple example self._testClipTensorByNorm([[-3.0, 0.0, 0.0], [4.0, 0.0, 0.0]], 4.0, diff --git a/tensorflow/python/ops/collective_ops_test.py b/tensorflow/python/ops/collective_ops_test.py index 9c772a9354..0fd9368d21 100644 --- a/tensorflow/python/ops/collective_ops_test.py +++ b/tensorflow/python/ops/collective_ops_test.py @@ -21,6 +21,7 @@ from __future__ import print_function from tensorflow.core.protobuf import config_pb2 from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import collective_ops from tensorflow.python.platform import test @@ -49,16 +50,19 @@ class CollectiveOpTest(test.TestCase): self.assertAllClose(results[0], expected, rtol=1e-5, atol=1e-5) self.assertAllClose(results[1], expected, rtol=1e-5, atol=1e-5) + @test_util.run_deprecated_v1 def testCollectiveReduce(self): self._testCollectiveReduce([0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1], [0.3, 1.3, 2.3, 3.3, 4.3, 5.3, 6.3, 7.3], [0.2, 1.2, 2.2, 3.2, 4.2, 5.2, 6.2, 7.2], True) + @test_util.run_deprecated_v1 def testCollectiveAutoGraphKey(self): self._testCollectiveReduce([0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1], [0.3, 1.3, 2.3, 3.3, 4.3, 5.3, 6.3, 7.3], [0.2, 1.2, 2.2, 3.2, 4.2, 5.2, 6.2, 7.2], False) + @test_util.run_deprecated_v1 def testCollectiveReduceScalar(self): self._testCollectiveReduce(0.1, 0.3, 0.2, True) @@ -81,6 +85,7 @@ class CollectiveOpTest(test.TestCase): self.assertAllClose(results[0], t0, rtol=1e-5, atol=1e-5) self.assertAllClose(results[1], t0, rtol=1e-5, atol=1e-5) + @test_util.run_deprecated_v1 def testCollectiveBroadcast(self): self._testCollectiveBroadcast([0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1]) diff --git a/tensorflow/python/ops/cond_v2.py b/tensorflow/python/ops/cond_v2.py index 998c3e08f6..e882a270c8 100644 --- a/tensorflow/python/ops/cond_v2.py +++ b/tensorflow/python/ops/cond_v2.py @@ -25,15 +25,19 @@ from __future__ import print_function import collections -from tensorflow.core.framework import attr_value_pb2 +from tensorflow.python.framework import dtypes from tensorflow.python.framework import func_graph as func_graph_module from tensorflow.python.framework import function_def_to_graph from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_util from tensorflow.python.ops import control_flow_util_v2 as util +from tensorflow.python.ops import gen_dataset_ops from tensorflow.python.ops import gen_functional_ops +from tensorflow.python.ops import gen_resource_variable_ops from tensorflow.python.ops import gradients_impl +from tensorflow.python.util import nest + # NOTE(skyewm): TensorFlow uses protected class methods and fields to signify # that they aren't part of the official public API. These protected members @@ -74,73 +78,17 @@ def cond_v2(pred, true_fn, false_fn, name="cond"): false_name, read_only_collections=False), add_control_dependencies=add_control_dependencies, op_return_value=pred) - _check_same_outputs(true_graph, false_graph) - - # Add inputs to true_graph and false_graph to make them match. Note that - # this modifies true_graph and false_graph. - cond_inputs = _make_inputs_match(true_graph, false_graph, - true_graph.external_captures, - false_graph.external_captures) - - # Add all intermediate tensors as function outputs so they're available for - # the gradient computation. - true_intermediates = _get_intermediates(true_graph) - false_intermediates = _get_intermediates(false_graph) - - # Save the original number of outputs to return to the caller. - num_cond_outputs = len(true_graph.outputs) - - # Make the number/type of new intermediate outputs match. - extra_true_outputs, extra_false_outputs = _pad_params( - true_graph, false_graph, true_intermediates, false_intermediates) + outputs = _build_cond(pred, true_graph, false_graph, + true_graph.external_captures, + false_graph.external_captures, + name=scope) - true_graph.outputs.extend(extra_true_outputs) - false_graph.outputs.extend(extra_false_outputs) - - # Create the If op. - tensors = gen_functional_ops._if( # pylint: disable=protected-access - pred, - cond_inputs, [t.dtype for t in true_graph.outputs], - util.create_new_tf_function(true_graph), - util.create_new_tf_function(false_graph), - output_shapes=_get_output_shapes(true_graph.outputs, - false_graph.outputs), - name=scope) - - # Set the flag to enable lowering on the `if` op if necessary - # Lowering allows cond_v2 to avoid some of the limitations of Functions, - # allowing users to specify devices & colocation inside of cond_v2 branches, - # and enabling non-strict evaluation & partial pruning of cond_v2 branches. - # This brings cond_v2 closer to feature parity with tf.cond. - # - # However, we do not lower `If` in the XLA context because it is easier for - # XLA to apply its own optimizations when dealing with un-lowered `If` - # operators than with lowered switch/merge control flow. - # - # TODO(b/110167197) this approach requires cond_v2 to have at least 1 output - if_op = tensors[0].op - if not control_flow_util.IsInXLAContext(if_op): - # pylint: disable=protected-access - if_op._set_attr("_lower_using_switch_merge", - attr_value_pb2.AttrValue(b=True)) - # pylint: enable=protected-access - - # Return identities for each output of the If op, rather than the output of - # the If op directly. This makes pruning work if the output of cond() is - # fetched: the lowering pass converts the If outputs into IdentityN outputs, - # which if fetched will cause all ops in the taken branch to be run (since - # it takes all merge ops as input). After lowering, each output identity op - # will end up with only the appropriate merge op as input. - # TODO(b/79984175): this doesn't have to be a tuple once we covert to the - # correct output structure - tensors = tuple(array_ops.identity(t) for t in tensors) - - result = tuple(tensors[:num_cond_outputs]) - if len(result) == 1: - return result[0] - else: - return result + # Packing output tensors in the same nested structure as the true and false + # functions return + result = nest.pack_sequence_as(structure=true_graph.structured_outputs, + flat_sequence=tensors[:num_cond_outputs]) + return result @ops.RegisterGradient("If") @@ -168,39 +116,105 @@ def _IfGrad(op, *grads): # pylint: disable=invalid-name true_grad_inputs = _resolve_grad_inputs(true_graph, true_grad_graph) false_grad_inputs = _resolve_grad_inputs(false_graph, false_grad_graph) - # Make the inputs to true_grad_graph and false_grad_graph match. Note that - # this modifies true_grad_graph and false_grad_graph. - grad_inputs = _make_inputs_match(true_grad_graph, false_grad_graph, - true_grad_inputs, false_grad_inputs) + outputs = _build_cond(op.inputs[0], true_grad_graph, false_grad_graph, + true_grad_inputs, false_grad_inputs) - # Add all intermediate tensors as function outputs so they're available for - # higher-order gradient computations. + # The predicate has no gradient. + return [None] + outputs - true_grad_intermediates = _get_intermediates(true_grad_graph) - false_grad_intermediates = _get_intermediates(false_grad_graph) - # Save the original number of gradient outputs to return. - num_grad_outputs = len(true_grad_graph.outputs) +def _build_cond(pred, true_graph, false_graph, true_inputs, false_inputs, + name=None): + """Creates an If op from the specified predicate, branch functions and inputs. - # Make the number/type of new intermediate outputs match. - extra_true_grad_outputs, extra_false_grad_outputs = _pad_params( - true_grad_graph, false_grad_graph, - true_grad_intermediates, false_grad_intermediates) + Note that this modifies true_graph and false_graph to make the inputs match, + and to output all intermediates values so they're available for the gradient + computation. - true_grad_graph.outputs.extend(extra_true_grad_outputs) - false_grad_graph.outputs.extend(extra_false_grad_outputs) + true_graph and false_graph need not have the same input types, but they must + have the same outpute types. - # Create the gradient If op. - tensors = gen_functional_ops._if( - op.inputs[0], - grad_inputs, [t.dtype for t in true_grad_graph.outputs], - util.create_new_tf_function(true_grad_graph), - util.create_new_tf_function(false_grad_graph), - output_shapes=_get_output_shapes(true_grad_graph.outputs, - false_grad_graph.outputs)) + Args: + pred: boolean Tensor + true_graph: FuncGraph + false_graph: FuncGraph + true_inputs: a list of Tensors to be passed to true_graph as input. + false_inputs: a list of Tensors to be passed to false_graph as input. + name: the name for the If op. - # The predicate has no gradient. - return [None] + tensors[:num_grad_outputs] + Returns: + A list of Tensors which are the outputs of the If op. Does not include added + intermediate outputs. + """ + _check_same_outputs(true_graph, false_graph) + + # Add inputs to true_graph and false_graph to make them match. Note that + # this modifies true_graph and false_graph. + cond_inputs = _make_inputs_match(true_graph, false_graph, + true_inputs, false_inputs) + + # Add all intermediate tensors as function outputs so they're available for + # the gradient computation. Since the outputs of the two functions must match, + # we wrap all the intermediates in optionals. Each intermediate output will + # have a value iff its corresponding branch is taken. + + true_intermediates = _get_intermediates(true_graph) + false_intermediates = _get_intermediates(false_graph) + + # Save the original number of outputs to return to the caller. + num_cond_outputs = len(true_graph.outputs) + + if control_flow_util.InXlaContext(ops.get_default_graph()): + # XLA does not yet support optionals, so output intermediates directly and + # make them match via FakeParams, which can be converted to zeros in XLA. + # TODO(skyewm,jpienaar): can XLA support optionals? + extra_true_outputs, extra_false_outputs = _make_intermediates_match_xla( + true_graph, false_graph, true_intermediates, false_intermediates) + else: + # Wrap intermediates in optionals. + wrapped_true_intermediates = _wrap_intermediates(true_graph, + true_intermediates) + wrapped_false_intermediates = _wrap_intermediates(false_graph, + false_intermediates) + + # Make outputs match by adding none optionals. + extra_true_outputs, extra_false_outputs = _make_intermediates_match( + true_graph, false_graph, + wrapped_true_intermediates, wrapped_false_intermediates) + + true_graph.outputs.extend(extra_true_outputs) + false_graph.outputs.extend(extra_false_outputs) + # TODO(skyewm): somehow indicate it's a bug if this fails. + _check_same_outputs(true_graph, false_graph) + + # Create the If op. + tensors = gen_functional_ops._if( # pylint: disable=protected-access + pred, + cond_inputs, [t.dtype for t in true_graph.outputs], + util.create_new_tf_function(true_graph), + util.create_new_tf_function(false_graph), + output_shapes=_get_output_shapes(true_graph.outputs, + false_graph.outputs), + name=name) + + # TODO(b/110167197) this approach requires cond_v2 to have at least 1 output + if_op = tensors[0].op + util.maybe_set_lowering_attr(if_op) + + # Return identities for each output of the If op, rather than the output of + # the If op directly. This makes pruning work if the output of cond() is + # fetched: the lowering pass converts the If outputs into IdentityN outputs, + # which if fetched will cause all ops in the taken branch to be run (since + # it takes all merge ops as input). After lowering, each output identity op + # will end up with only the appropriate merge op as input. + # TODO(b/79984175): this doesn't have to be a tuple once we covert to the + # correct output structure + tensors = [array_ops.identity(t) for t in tensors] + + # Prevent fetching since the variant outputs can't be fetched directly. + if_op.graph.prevent_fetching(if_op) + + return tensors[:num_cond_outputs] def _get_func_graphs(if_op): @@ -277,7 +291,11 @@ def _grad_fn(func_graph, grads): # both branches have zero gradient. for i in range(len(result)): if result[i] is None: - result[i] = array_ops.zeros_like(func_graph.inputs[i]) + if func_graph.inputs[i].dtype == dtypes.resource: + result[i] = array_ops.zeros( + gen_resource_variable_ops.variable_shape(func_graph.inputs[i])) + else: + result[i] = array_ops.zeros_like(func_graph.inputs[i]) return result @@ -287,7 +305,7 @@ def _create_grad_func(func_graph, grads, name): return func_graph_module.func_graph_from_py_func( name, lambda: _grad_fn(func_graph, grads), [], {}, - func_graph=util.CondBranchFuncGraph(name, read_only_collections=False)) + func_graph=_CondGradFuncGraph(name, func_graph)) def _resolve_grad_inputs(cond_graph, grad_graph): @@ -369,28 +387,39 @@ def _separate_unique_inputs(true_inputs, false_inputs): return list(shared_inputs), list(true_only_inputs), list(false_only_inputs) -def _pad_params(true_graph, false_graph, true_params, false_params): - """Returns new param lists that have matching signatures. +def _make_intermediates_match(true_graph, false_graph, + true_optionals, false_optionals): + """Returns new optionals lists that have matching signatures. - This is done by mirroring each param list in the other using dummy params. - There is no merging of params. + This is done by mirroring each list in the other using none optionals. + There is no merging of like optionals. Args: true_graph: FuncGraph false_graph: FuncGraph - true_params: a list of Tensors from true_graph - false_params: a list of Tensors from false_graph + true_optionals: a list of optional Tensors from true_graph + false_optionals: a list of optional Tensors from false_graph Returns: A new list of Tensors in true_graph and a new list of Tensors in - false_graph. The two lists have the same number of Tensors, with matching - types and shapes across the lists. + false_graph. The two lists have the same number of Tensors, all of which + will be optionals of the same shape/type. """ - new_true_params = (true_params + - _create_dummy_params(true_graph, false_params)) - new_false_inputs = (_create_dummy_params(false_graph, true_params) - + false_params) - return new_true_params, new_false_inputs + new_true_optionals = (true_optionals + + _create_none_optionals(true_graph, false_optionals)) + new_false_optionals = (_create_none_optionals(false_graph, true_optionals) + + false_optionals) + return new_true_optionals, new_false_optionals + + +def _make_intermediates_match_xla(true_graph, false_graph, true_intermediates, + false_intermediates): + """Like _make_intermediates_match but for the XLA case.""" + new_true_intermediates = (true_intermediates + + _create_fakeparams(true_graph, false_intermediates)) + new_false_intermediates = (_create_fakeparams(false_graph, true_intermediates) + + false_intermediates) + return new_true_intermediates, new_false_intermediates def _make_inputs_match(true_graph, false_graph, true_inputs, false_inputs): @@ -425,11 +454,11 @@ def _make_inputs_match(true_graph, false_graph, true_inputs, false_inputs): true_graph.inputs = ( [true_input_to_param[t] for t in shared_inputs] + [true_input_to_param[t] for t in true_only_inputs] + - _create_dummy_params(true_graph, false_only_inputs)) + _create_dummy_inputs(true_graph, false_only_inputs)) false_graph.inputs = ( [false_input_to_param[t] for t in shared_inputs] + - _create_dummy_params(false_graph, true_only_inputs) + + _create_dummy_inputs(false_graph, true_only_inputs) + [false_input_to_param[t] for t in false_only_inputs]) # Rewrite the FuncGraphs' state to reflect the new inputs. @@ -441,7 +470,12 @@ def _make_inputs_match(true_graph, false_graph, true_inputs, false_inputs): return new_inputs -def _create_dummy_params(func_graph, template_tensors): +def _wrap_intermediates(func_graph, intermediates): + with func_graph.as_default(): + return [gen_dataset_ops.optional_from_value([t]) for t in intermediates] + + +def _create_dummy_inputs(func_graph, template_tensors): """Creates tensors in func_graph to represent template_tensors. Args: @@ -451,6 +485,27 @@ def _create_dummy_params(func_graph, template_tensors): Returns: A list of tensors in func_graph. """ + with func_graph.as_default(): + return [array_ops.placeholder(t.dtype, shape=t.shape) + for t in template_tensors] + + +def _create_none_optionals(func_graph, template_tensors): + """Creates none optionals in func_graph to represent template_tensors. + + Args: + func_graph: FuncGraph. + template_tensors: a list of tensors in func_graph. + + Returns: + A list of tensors in func_graph. + """ + with func_graph.as_default(): + return [gen_dataset_ops.optional_none() for _ in template_tensors] + + +def _create_fakeparams(func_graph, template_tensors): + """Create FakeParams for the XLA case.""" with func_graph.as_default(): return [gen_functional_ops.fake_param(dtype=t.dtype, shape=t.shape) for t in template_tensors] @@ -462,12 +517,16 @@ def _check_same_outputs(true_graph, false_graph): false_output_types = [t.dtype for t in false_graph.outputs] if (len(true_graph.outputs) != len(false_graph.outputs) or true_output_types != false_output_types): - raise ValueError( + raise TypeError( "true_fn() and false_fn() must return the same number and type of " "arguments, got:\n" " true_fn: %s\n" " false_fn: %s" % (true_output_types, false_output_types)) + # Make sure both structured outputs for both graphs have the same structure + nest.assert_same_structure(true_graph.structured_outputs, + false_graph.structured_outputs) + def _get_output_shapes(true_graph_outputs, false_graph_outputs): output_shapes = [ @@ -475,3 +534,38 @@ def _get_output_shapes(true_graph_outputs, false_graph_outputs): for t_out, f_out in zip(true_graph_outputs, false_graph_outputs) ] return output_shapes + + +class _CondGradFuncGraph(util.CondBranchFuncGraph): + """FuncGraph for the gradient function of the branch of an If op. + + Handles unwrapping optional intermediate values that are captured by the + gradient computation. + """ + + def __init__(self, name, forward_graph): + super(_CondGradFuncGraph, self).__init__(name, read_only_collections=False) + self._forward_graph = forward_graph + + def _capture_helper(self, tensor, name): + if (tensor.graph is not self._forward_graph or + tensor in self._forward_graph.inputs or + tensor in self._forward_graph.outputs): + return super(_CondGradFuncGraph, self)._capture_helper(tensor, name) + + # 'tensor' is an intermediate in the forward graph. We find the corresonding + # optional tensor, which is output from the If op, and capture it as + # normal. We then unwrap the captured optional value to get the raw + # intermediate value. + for consumer in tensor.consumers(): + if (consumer.type == "OptionalFromValue" + and consumer.outputs[0] in self._forward_graph.outputs): + optional = consumer.outputs[0] + captured_optional = super(_CondGradFuncGraph, self)._capture_helper( + optional, name) + return gen_dataset_ops.optional_get_value( + captured_optional, [tensor.dtype], [tensor.shape])[0] + raise ValueError( + "Couldn't find OptionalFromValue consumer for tensor '%s'.\n" + "This is an internal bug, please report at " + "https://github.com/tensorflow/tensorflow/issues." % tensor.name) diff --git a/tensorflow/python/ops/confusion_matrix.py b/tensorflow/python/ops/confusion_matrix.py index b86b174afe..ccfe3b65c2 100644 --- a/tensorflow/python/ops/confusion_matrix.py +++ b/tensorflow/python/ops/confusion_matrix.py @@ -90,12 +90,13 @@ def remove_squeezable_dimensions( return labels, predictions -@tf_export( - 'math.confusion_matrix', - v1=['math.confusion_matrix', 'confusion_matrix']) -@deprecation.deprecated_endpoints('confusion_matrix', 'train.confusion_matrix') -def confusion_matrix(labels, predictions, num_classes=None, dtype=dtypes.int32, - name=None, weights=None): +@tf_export('math.confusion_matrix', v1=[]) +def confusion_matrix(labels, + predictions, + num_classes=None, + weights=None, + dtype=dtypes.int32, + name=None): """Computes the confusion matrix from predictions and labels. The matrix columns represent the prediction labels and the rows represent the @@ -132,9 +133,9 @@ def confusion_matrix(labels, predictions, num_classes=None, dtype=dtypes.int32, num_classes: The possible number of labels the classification task can have. If this value is not provided, it will be calculated using both predictions and labels array. + weights: An optional `Tensor` whose shape matches `predictions`. dtype: Data type of the confusion matrix. name: Scope name. - weights: An optional `Tensor` whose shape matches `predictions`. Returns: A `Tensor` of type `dtype` with shape `[n, n]` representing the confusion @@ -193,3 +194,65 @@ def confusion_matrix(labels, predictions, num_classes=None, dtype=dtypes.int32, zero_matrix = array_ops.zeros(math_ops.to_int32(shape), dtype) return sparse_ops.sparse_add(zero_matrix, cm_sparse) + + +@tf_export(v1=['math.confusion_matrix', 'confusion_matrix']) +@deprecation.deprecated_endpoints('confusion_matrix', 'train.confusion_matrix') +def confusion_matrix_v1(labels, + predictions, + num_classes=None, + dtype=dtypes.int32, + name=None, + weights=None): + """Computes the confusion matrix from predictions and labels. + + The matrix columns represent the prediction labels and the rows represent the + real labels. The confusion matrix is always a 2-D array of shape `[n, n]`, + where `n` is the number of valid labels for a given classification task. Both + prediction and labels must be 1-D arrays of the same shape in order for this + function to work. + + If `num_classes` is `None`, then `num_classes` will be set to one plus the + maximum value in either predictions or labels. Class labels are expected to + start at 0. For example, if `num_classes` is 3, then the possible labels + would be `[0, 1, 2]`. + + If `weights` is not `None`, then each prediction contributes its + corresponding weight to the total value of the confusion matrix cell. + + For example: + + ```python + tf.confusion_matrix([1, 2, 4], [2, 2, 4]) ==> + [[0 0 0 0 0] + [0 0 1 0 0] + [0 0 1 0 0] + [0 0 0 0 0] + [0 0 0 0 1]] + ``` + + Note that the possible labels are assumed to be `[0, 1, 2, 3, 4]`, + resulting in a 5x5 confusion matrix. + + Args: + labels: 1-D `Tensor` of real labels for the classification task. + predictions: 1-D `Tensor` of predictions for a given classification. + num_classes: The possible number of labels the classification task can have. + If this value is not provided, it will be calculated using both + predictions and labels array. + dtype: Data type of the confusion matrix. + name: Scope name. + weights: An optional `Tensor` whose shape matches `predictions`. + + Returns: + A `Tensor` of type `dtype` with shape `[n, n]` representing the confusion + matrix, where `n` is the number of possible labels in the classification + task. + + Raises: + ValueError: If both predictions and labels are not 1-D vectors and have + mismatched shapes, or if `weights` is not `None` and its shape doesn't + match `predictions`. + """ + return confusion_matrix(labels, predictions, num_classes, weights, dtype, + name) diff --git a/tensorflow/python/ops/control_flow_ops.py b/tensorflow/python/ops/control_flow_ops.py index 0d04f0697d..b7e50c1dae 100644 --- a/tensorflow/python/ops/control_flow_ops.py +++ b/tensorflow/python/ops/control_flow_ops.py @@ -158,7 +158,7 @@ def Assert(condition, data, summarize=None, name=None): with ops.name_scope(name, "Assert", [condition, data]) as name: xs = ops.convert_n_to_tensor(data) - if all([x.dtype in {dtypes.string, dtypes.int32} for x in xs]): + if all(x.dtype in {dtypes.string, dtypes.int32} for x in xs): # As a simple heuristic, we assume that string and int32 are # on host to avoid the need to use cond. If it is not case, # we will pay the price copying the tensor to host memory. @@ -457,19 +457,19 @@ def merge(inputs, name=None): ValueError: If any of the inputs is None, or inputs are IndexedSlices and some but not all have a dense_shape property. """ - if any([inp is None for inp in inputs]): + if any(inp is None for inp in inputs): raise ValueError("At least one of the merge inputs is None: %s" % inputs) with ops.name_scope(name, "Merge", inputs) as name: inputs = [ ops.internal_convert_to_tensor_or_indexed_slices(inp, as_ref=True) for inp in inputs ] - if all([isinstance(v, ops.Tensor) for v in inputs]): - if all([v.dtype._is_ref_dtype for v in inputs]): # pylint: disable=protected-access + if all(isinstance(v, ops.Tensor) for v in inputs): + if all(v.dtype._is_ref_dtype for v in inputs): # pylint: disable=protected-access return gen_control_flow_ops.ref_merge(inputs, name) else: return gen_control_flow_ops.merge(inputs, name) - elif all([isinstance(v, sparse_tensor.SparseTensor) for v in inputs]): + elif all(isinstance(v, sparse_tensor.SparseTensor) for v in inputs): # Only handle the case when all inputs are SparseTensor. values, _ = merge([inp.values for inp in inputs], name=name) indices, chosen_index = gen_control_flow_ops.merge( @@ -557,7 +557,7 @@ def _SetShapeInvariants(input_vars, enter_vars, shapes): if shapes is None: return flat_shapes = nest.flatten(shapes) - if not all([isinstance(s, tensor_shape.TensorShape) for s in flat_shapes]): + if not all(isinstance(s, tensor_shape.TensorShape) for s in flat_shapes): raise ValueError("`shapes` must be a (possibly nested) list of shapes.") # Check that the shapes of the inputs are less than the shape invariants, # and set the shapes of `enter_vars` to the shape invariants. @@ -1976,7 +1976,7 @@ def _UnpackIfSingleton(res): # pylint: disable=redefined-outer-name # pylint: disable=g-doc-args -@tf_export("cond") +@tf_export(v1=["cond"]) @deprecation.deprecated_args( None, "fn1/fn2 are deprecated in favor of the true_fn/false_fn arguments.", "fn1", "fn2") @@ -2173,6 +2173,77 @@ def cond(pred, # pylint: enable=redefined-outer-name +@tf_export("cond", v1=[]) +def cond_for_tf_v2(pred, + true_fn=None, + false_fn=None, + name=None): + """Return `true_fn()` if the predicate `pred` is true else `false_fn()`. + + `true_fn` and `false_fn` both return lists of output tensors. `true_fn` and + `false_fn` must have the same non-zero number and type of outputs. + + **WARNING**: Any Tensors or Operations created outside of `true_fn` and + `false_fn` will be executed regardless of which branch is selected at runtime. + + Although this behavior is consistent with the dataflow model of TensorFlow, + it has frequently surprised users who expected a lazier semantics. + Consider the following simple program: + + ```python + z = tf.multiply(a, b) + result = tf.cond(x < y, lambda: tf.add(x, z), lambda: tf.square(y)) + ``` + + If `x < y`, the `tf.add` operation will be executed and `tf.square` + operation will not be executed. Since `z` is needed for at least one + branch of the `cond`, the `tf.multiply` operation is always executed, + unconditionally. + + Note that `cond` calls `true_fn` and `false_fn` *exactly once* (inside the + call to `cond`, and not at all during `Session.run()`). `cond` + stitches together the graph fragments created during the `true_fn` and + `false_fn` calls with some additional graph nodes to ensure that the right + branch gets executed depending on the value of `pred`. + + `tf.cond` supports nested structures as implemented in + `tensorflow.python.util.nest`. Both `true_fn` and `false_fn` must return the + same (possibly nested) value structure of lists, tuples, and/or named tuples. + Singleton lists and tuples form the only exceptions to this: when returned by + `true_fn` and/or `false_fn`, they are implicitly unpacked to single values. + + Args: + pred: A scalar determining whether to return the result of `true_fn` or + `false_fn`. + true_fn: The callable to be performed if pred is true. + false_fn: The callable to be performed if pred is false. + name: Optional name prefix for the returned tensors. + + Returns: + Tensors returned by the call to either `true_fn` or `false_fn`. If the + callables return a singleton list, the element is extracted from the list. + + Raises: + TypeError: if `true_fn` or `false_fn` is not callable. + ValueError: if `true_fn` and `false_fn` do not return the same number of + tensors, or return tensors of different types. + + Example: + + ```python + x = tf.constant(2) + y = tf.constant(5) + def f1(): return tf.multiply(x, 17) + def f2(): return tf.add(y, 23) + r = tf.cond(tf.less(x, y), f1, f2) + # r is set to f1(). + # Operations in f2 (e.g., tf.add) are not executed. + ``` + + """ + return cond(pred, true_fn=true_fn, false_fn=false_fn, strict=True, name=name) + + def _resource_safe_shape(t): """Returns the shape of t or the variable it points to.""" if t.dtype == dtypes.resource: @@ -3065,7 +3136,186 @@ class WhileContext(ControlFlowContext): # pylint: disable=redefined-outer-name -@tf_export("while_loop") +@tf_export("while_loop", v1=[]) +def while_loop_v2(cond, + body, + loop_vars, + shape_invariants=None, + parallel_iterations=10, + back_prop=True, + swap_memory=False, + maximum_iterations=None, + name=None): + """Repeat `body` while the condition `cond` is true. + + `cond` is a callable returning a boolean scalar tensor. `body` is a callable + returning a (possibly nested) tuple, namedtuple or list of tensors of the same + arity (length and structure) and types as `loop_vars`. `loop_vars` is a + (possibly nested) tuple, namedtuple or list of tensors that is passed to both + `cond` and `body`. `cond` and `body` both take as many arguments as there are + `loop_vars`. + + In addition to regular Tensors or IndexedSlices, the body may accept and + return TensorArray objects. The flows of the TensorArray objects will + be appropriately forwarded between loops and during gradient calculations. + + Note that `while_loop` calls `cond` and `body` *exactly once* (inside the + call to `while_loop`, and not at all during `Session.run()`). `while_loop` + stitches together the graph fragments created during the `cond` and `body` + calls with some additional graph nodes to create the graph flow that + repeats `body` until `cond` returns false. + + For correctness, `tf.while_loop()` strictly enforces shape invariants for + the loop variables. A shape invariant is a (possibly partial) shape that + is unchanged across the iterations of the loop. An error will be raised + if the shape of a loop variable after an iteration is determined to be more + general than or incompatible with its shape invariant. For example, a shape + of [11, None] is more general than a shape of [11, 17], and [11, 21] is not + compatible with [11, 17]. By default (if the argument `shape_invariants` is + not specified), it is assumed that the initial shape of each tensor in + `loop_vars` is the same in every iteration. The `shape_invariants` argument + allows the caller to specify a less specific shape invariant for each loop + variable, which is needed if the shape varies between iterations. The + `tf.Tensor.set_shape` + function may also be used in the `body` function to indicate that + the output loop variable has a particular shape. The shape invariant for + SparseTensor and IndexedSlices are treated specially as follows: + + a) If a loop variable is a SparseTensor, the shape invariant must be + TensorShape([r]) where r is the rank of the dense tensor represented + by the sparse tensor. It means the shapes of the three tensors of the + SparseTensor are ([None], [None, r], [r]). NOTE: The shape invariant here + is the shape of the SparseTensor.dense_shape property. It must be the shape of + a vector. + + b) If a loop variable is an IndexedSlices, the shape invariant must be + a shape invariant of the values tensor of the IndexedSlices. It means + the shapes of the three tensors of the IndexedSlices are (shape, [shape[0]], + [shape.ndims]). + + `while_loop` implements non-strict semantics, enabling multiple iterations + to run in parallel. The maximum number of parallel iterations can be + controlled by `parallel_iterations`, which gives users some control over + memory consumption and execution order. For correct programs, `while_loop` + should return the same result for any parallel_iterations > 0. + + For training, TensorFlow stores the tensors that are produced in the + forward inference and are needed in back propagation. These tensors are a + main source of memory consumption and often cause OOM errors when training + on GPUs. When the flag swap_memory is true, we swap out these tensors from + GPU to CPU. This for example allows us to train RNN models with very long + sequences and large batches. + + Args: + cond: A callable that represents the termination condition of the loop. + body: A callable that represents the loop body. + loop_vars: A (possibly nested) tuple, namedtuple or list of numpy array, + `Tensor`, and `TensorArray` objects. + shape_invariants: The shape invariants for the loop variables. + parallel_iterations: The number of iterations allowed to run in parallel. It + must be a positive integer. + back_prop: Whether backprop is enabled for this while loop. + swap_memory: Whether GPU-CPU memory swap is enabled for this loop. + maximum_iterations: Optional maximum number of iterations of the while loop + to run. If provided, the `cond` output is AND-ed with an additional + condition ensuring the number of iterations executed is no greater than + `maximum_iterations`. + name: Optional name prefix for the returned tensors. + + Returns: + The output tensors for the loop variables after the loop. The return value + has the same structure as `loop_vars`. + + Raises: + TypeError: if `cond` or `body` is not callable. + ValueError: if `loop_vars` is empty. + + Example: + + ```python + i = tf.constant(0) + c = lambda i: tf.less(i, 10) + b = lambda i: tf.add(i, 1) + r = tf.while_loop(c, b, [i]) + ``` + + Example with nesting and a namedtuple: + + ```python + import collections + Pair = collections.namedtuple('Pair', 'j, k') + ijk_0 = (tf.constant(0), Pair(tf.constant(1), tf.constant(2))) + c = lambda i, p: i < 10 + b = lambda i, p: (i + 1, Pair((p.j + p.k), (p.j - p.k))) + ijk_final = tf.while_loop(c, b, ijk_0) + ``` + + Example using shape_invariants: + + ```python + i0 = tf.constant(0) + m0 = tf.ones([2, 2]) + c = lambda i, m: i < 10 + b = lambda i, m: [i+1, tf.concat([m, m], axis=0)] + tf.while_loop( + c, b, loop_vars=[i0, m0], + shape_invariants=[i0.get_shape(), tf.TensorShape([None, 2])]) + ``` + + Example which demonstrates non-strict semantics: In the following + example, the final value of the counter `i` does not depend on `x`. So + the `while_loop` can increment the counter parallel to updates of `x`. + However, because the loop counter at one loop iteration depends + on the value at the previous iteration, the loop counter itself cannot + be incremented in parallel. Hence if we just want the final value of the + counter (which we print on the line `print(sess.run(i))`), then + `x` will never be incremented, but the counter will be updated on a + single thread. Conversely, if we want the value of the output (which we + print on the line `print(sess.run(out).shape)`), then the counter may be + incremented on its own thread, while `x` can be incremented in + parallel on a separate thread. In the extreme case, it is conceivable + that the thread incrementing the counter runs until completion before + `x` is incremented even a single time. The only thing that can never + happen is that the thread updating `x` can never get ahead of the + counter thread because the thread incrementing `x` depends on the value + of the counter. + + ```python + import tensorflow as tf + + n = 10000 + x = tf.constant(list(range(n))) + c = lambda i, x: i < n + b = lambda i, x: (tf.Print(i + 1, [i]), tf.Print(x + 1, [i], "x:")) + i, out = tf.while_loop(c, b, (0, x)) + with tf.Session() as sess: + print(sess.run(i)) # prints [0] ... [9999] + + # The following line may increment the counter and x in parallel. + # The counter thread may get ahead of the other thread, but not the + # other way around. So you may see things like + # [9996] x:[9987] + # meaning that the counter thread is on iteration 9996, + # while the other thread is on iteration 9987 + print(sess.run(out).shape) + ``` + + """ + return while_loop( + cond=cond, + body=body, + loop_vars=loop_vars, + shape_invariants=shape_invariants, + parallel_iterations=parallel_iterations, + back_prop=back_prop, + swap_memory=swap_memory, + name=name, + maximum_iterations=maximum_iterations, + return_same_structure=True) + + +# pylint: disable=redefined-outer-name +@tf_export(v1=["while_loop"]) def while_loop(cond, body, loop_vars, @@ -3244,7 +3494,8 @@ def while_loop(cond, loop_vars, shape_invariants=shape_invariants, maximum_iterations=maximum_iterations, - name=name) + name=name, + return_same_structure=return_same_structure) with ops.name_scope(name, "while", loop_vars): if not loop_vars: @@ -3465,7 +3716,43 @@ def group(*inputs, **kwargs): return no_op(name=name) -@tf_export("tuple") +@tf_export("tuple", v1=[]) +def tuple_v2(tensors, control_inputs=None, name=None): + """Group tensors together. + + This creates a tuple of tensors with the same values as the `tensors` + argument, except that the value of each tensor is only returned after the + values of all tensors have been computed. + + `control_inputs` contains additional ops that have to finish before this op + finishes, but whose outputs are not returned. + + This can be used as a "join" mechanism for parallel computations: all the + argument tensors can be computed in parallel, but the values of any tensor + returned by `tuple` are only available after all the parallel computations + are done. + + See also `tf.group` and + `tf.control_dependencies`. + + Args: + tensors: A list of `Tensor`s or `IndexedSlices`, some entries can be `None`. + control_inputs: List of additional ops to finish before returning. + name: (optional) A name to use as a `name_scope` for the operation. + + Returns: + Same as `tensors`. + + Raises: + ValueError: If `tensors` does not contain any `Tensor` or `IndexedSlices`. + TypeError: If `control_inputs` is not a list of `Operation` or `Tensor` + objects. + + """ + return tuple(tensors=tensors, name=name, control_inputs=control_inputs) # pylint: disable=redefined-builtin + + +@tf_export(v1=["tuple"]) def tuple(tensors, name=None, control_inputs=None): # pylint: disable=redefined-builtin """Group tensors together. diff --git a/tensorflow/python/ops/control_flow_ops_test.py b/tensorflow/python/ops/control_flow_ops_test.py index c3514c183c..c020189ad6 100644 --- a/tensorflow/python/ops/control_flow_ops_test.py +++ b/tensorflow/python/ops/control_flow_ops_test.py @@ -155,9 +155,9 @@ class WithDependenciesTestCase(test_util.TensorFlowTestCase): constant_op.constant(7)) with self.cached_session(): variables.global_variables_initializer().run() - self.assertEquals(0, counter.eval()) - self.assertEquals(7, const_with_dep.eval()) - self.assertEquals(1, counter.eval()) + self.assertEquals(0, self.evaluate(counter)) + self.assertEquals(7, self.evaluate(const_with_dep)) + self.assertEquals(1, self.evaluate(counter)) def testListDependencies(self): with ops.Graph().as_default(): @@ -169,9 +169,9 @@ class WithDependenciesTestCase(test_util.TensorFlowTestCase): constant_op.constant(7)) with self.cached_session(): variables.global_variables_initializer().run() - self.assertEquals(0, counter.eval()) - self.assertEquals(7, const_with_dep.eval()) - self.assertEquals(1, counter.eval()) + self.assertEquals(0, self.evaluate(counter)) + self.assertEquals(7, self.evaluate(const_with_dep)) + self.assertEquals(1, self.evaluate(counter)) class SwitchTestCase(test_util.TensorFlowTestCase): @@ -209,9 +209,9 @@ class SwitchTestCase(test_util.TensorFlowTestCase): optimizer = momentum.MomentumOptimizer(0.1, 0.9) train_op = optimizer.minimize(cost) with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(10): - sess.run([train_op]) + self.evaluate([train_op]) def testResourceReadInLoop(self): with ops.Graph().as_default(): @@ -232,8 +232,8 @@ class SwitchTestCase(test_util.TensorFlowTestCase): cond, body, [constant_op.constant(0), constant_op.constant(0.0)]) with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - self.assertAllEqual(10.0, cost.eval()) + self.evaluate(variables.global_variables_initializer()) + self.assertAllEqual(10.0, self.evaluate(cost)) def doTestIndexedSlicesGradientInCondInWhileLoop(self, use_resource=False): with ops.Graph().as_default(): @@ -269,8 +269,8 @@ class SwitchTestCase(test_util.TensorFlowTestCase): static_grads.indices) with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - self.assertAllEqual(*sess.run([static_grads, dynamic_grads])) + self.evaluate(variables.global_variables_initializer()) + self.assertAllEqual(*self.evaluate([static_grads, dynamic_grads])) def testIndexedSlicesGradientInCondInWhileLoop(self): self.doTestIndexedSlicesGradientInCondInWhileLoop(use_resource=False) @@ -398,9 +398,9 @@ class CondTest(test_util.TensorFlowTestCase): pred=bool_var, true_fn=lambda: state_ops.assign(bool_var, False), false_fn=lambda: True) - sess.run(bool_var.initializer) - self.assertEquals(sess.run(cond_on_bool_var), False) - self.assertEquals(sess.run(cond_on_bool_var), True) + self.evaluate(bool_var.initializer) + self.assertEquals(self.evaluate(cond_on_bool_var), False) + self.assertEquals(self.evaluate(cond_on_bool_var), True) def testCondMissingArg1(self): with ops.Graph().as_default(): diff --git a/tensorflow/python/ops/control_flow_util.py b/tensorflow/python/ops/control_flow_util.py index 72c074ed1a..cb628f4aa6 100644 --- a/tensorflow/python/ops/control_flow_util.py +++ b/tensorflow/python/ops/control_flow_util.py @@ -38,6 +38,11 @@ def IsInXLAContext(op): return GetContainingXLAContext(ctxt) is not None +def InXlaContext(graph): + ctxt = graph._get_control_flow_context() # pylint: disable=protected-access + return GetContainingXLAContext(ctxt) is not None + + def IsInWhileLoop(op): ctxt = op._get_control_flow_context() # pylint: disable=protected-access return GetContainingWhileContext(ctxt) is not None diff --git a/tensorflow/python/ops/control_flow_util_v2.py b/tensorflow/python/ops/control_flow_util_v2.py index cab1d7b02e..5f56850884 100644 --- a/tensorflow/python/ops/control_flow_util_v2.py +++ b/tensorflow/python/ops/control_flow_util_v2.py @@ -19,10 +19,12 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.core.framework import attr_value_pb2 from tensorflow.python.eager import context from tensorflow.python.eager import function from tensorflow.python.framework import ops from tensorflow.python.framework.func_graph import FuncGraph +from tensorflow.python.ops import control_flow_util class CondBranchFuncGraph(FuncGraph): @@ -90,3 +92,31 @@ def unique_fn_name(scope, name): def unique_grad_fn_name(forward_name): return "%s_grad_%s" % (forward_name, ops.uid()) + + +def maybe_set_lowering_attr(op): + """Sets the flag to enable lowering on `op` if necessary. + + Lowering allows cond_v2 and while_v2 to avoid some of the limitations of + Functions, allowing users to specify devices & colocation inside of cond_v2 + and while_v2 input functions, and enabling non-strict evaluation & partial + pruning. This brings v2 control flow closer to feature parity with v1 control + flow. + + However, we do not lower in the following cases: + - When the `If` or `While` ops are in the XLA context. Because it is easier + for XLA to apply its own optimizations when dealing with un-lowered + control flow operators than with low-level control flow primitives. + - When the eager execution context specifies the executor of functions to + be the single threaded executor (see context.function_executor_type()). + Because the single threaded executor does not support v1 control flow ops. + + Args: + op: An `If` or `While` Operation. + """ + if (not control_flow_util.IsInXLAContext(op) and + context.context().get_function_call_options().executor_type + != "SINGLE_THREADED_EXECUTOR"): + # pylint: disable=protected-access + op._set_attr("_lower_using_switch_merge", attr_value_pb2.AttrValue(b=True)) + # pylint: enable=protected-access diff --git a/tensorflow/python/ops/ctc_ops.py b/tensorflow/python/ops/ctc_ops.py index e1071afd8e..3a7eb9355a 100644 --- a/tensorflow/python/ops/ctc_ops.py +++ b/tensorflow/python/ops/ctc_ops.py @@ -19,17 +19,27 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import function from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.ops import array_ops +from tensorflow.python.ops import functional_ops from tensorflow.python.ops import gen_ctc_ops +from tensorflow.python.ops import inplace_ops +from tensorflow.python.ops import linalg_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import nn_ops +from tensorflow.python.ops import sparse_ops from tensorflow.python.ops.nn_grad import _BroadcastMul +from tensorflow.python.util import nest from tensorflow.python.util.tf_export import tf_export # pylint: disable=protected-access, invalid-name -@tf_export("nn.ctc_loss") +@tf_export(v1=["nn.ctc_loss"]) def ctc_loss(labels, inputs, sequence_length, preprocess_collapse_repeated=False, ctc_merge_repeated=True, @@ -336,6 +346,785 @@ def ctc_beam_search_decoder_v2(inputs, sequence_length, beam_width=100, ops.NotDifferentiable("CTCGreedyDecoder") +ops.NotDifferentiable("CTCBeamSearchDecoder") -ops.NotDifferentiable("CTCBeamSearchDecoder") +def _ctc_state_trans(label_seq): + """Compute CTC alignment model transition matrix. + + Args: + label_seq: tensor of shape [batch_size, max_seq_length] + + Returns: + tensor of shape [batch_size, states, states] with a state transition matrix + computed for each sequence of the batch. + """ + + with ops.name_scope("ctc_state_trans"): + label_seq = ops.convert_to_tensor(label_seq, name="label_seq") + batch_size = _get_dim(label_seq, 0) + num_labels = _get_dim(label_seq, 1) + + num_label_states = num_labels + 1 + num_states = 2 * num_label_states + + label_states = math_ops.range(num_label_states) + blank_states = label_states + num_label_states + + # Start state to first label. + start_to_label = [[1, 0]] + + # Blank to label transitions. + blank_to_label = array_ops.stack([label_states[1:], blank_states[:-1]], 1) + + # Label to blank transitions. + label_to_blank = array_ops.stack([blank_states, label_states], 1) + + # Scatter transitions that don't depend on sequence. + indices = array_ops.concat( + [start_to_label, blank_to_label, label_to_blank], 0) + values = array_ops.ones([_get_dim(indices, 0)]) + trans = array_ops.scatter_nd( + indices, values, shape=[num_states, num_states]) + trans += linalg_ops.eye(num_states) # Self-loops. + + # Label to label transitions. Disallow transitions between repeated labels + # with no blank state in between. + batch_idx = array_ops.zeros_like(label_states[2:]) + indices = array_ops.stack( + [batch_idx, label_states[2:], label_states[1:-1]], 1) + indices = array_ops.tile( + array_ops.expand_dims(indices, 0), [batch_size, 1, 1]) + batch_idx = array_ops.expand_dims(math_ops.range(batch_size), 1) * [1, 0, 0] + indices += array_ops.expand_dims(batch_idx, 1) + repeats = math_ops.equal(label_seq[:, :-1], label_seq[:, 1:]) + values = 1.0 - math_ops.cast(repeats, dtypes.float32) + batched_shape = [batch_size, num_states, num_states] + label_to_label = array_ops.scatter_nd(indices, values, batched_shape) + + return array_ops.expand_dims(trans, 0) + label_to_label + + +def ctc_state_log_probs(seq_lengths, max_seq_length): + """Computes CTC alignment initial and final state log probabilities. + + Create the initial/final state values directly as log values to avoid + having to take a float64 log on tpu (which does not exist). + + Args: + seq_lengths: int tensor of shape [batch_size], seq lengths in the batch. + max_seq_length: int, max sequence length possible. + + Returns: + initial_state_log_probs, final_state_log_probs + """ + + batch_size = _get_dim(seq_lengths, 0) + num_label_states = max_seq_length + 1 + num_duration_states = 2 + num_states = num_duration_states * num_label_states + log_0 = math_ops.cast( + math_ops.log(math_ops.cast(0, dtypes.float64) + 1e-307), + dtypes.float32) + + initial_state_log_probs = array_ops.one_hot( + indices=array_ops.zeros([batch_size], dtype=dtypes.int32), + depth=num_states, + on_value=0.0, + off_value=log_0, axis=1) + + label_final_state_mask = array_ops.one_hot( + seq_lengths, depth=num_label_states, axis=0) + duration_final_state_mask = array_ops.ones( + [num_duration_states, 1, batch_size]) + final_state_mask = duration_final_state_mask * label_final_state_mask + final_state_log_probs = (1.0 - final_state_mask) * log_0 + final_state_log_probs = array_ops.reshape( + final_state_log_probs, [num_states, batch_size]) + + return initial_state_log_probs, array_ops.transpose(final_state_log_probs) + + +def _ilabel_to_state(labels, num_labels, ilabel_log_probs): + """Project ilabel log probs to state log probs.""" + + num_label_states = _get_dim(labels, 1) + blank = ilabel_log_probs[:, :, :1] + blank = array_ops.tile(blank, [1, 1, num_label_states + 1]) + one_hot = array_ops.one_hot(labels, depth=num_labels) + one_hot = array_ops.expand_dims(one_hot, axis=0) + ilabel_log_probs = array_ops.expand_dims(ilabel_log_probs, axis=2) + state_log_probs = math_ops.reduce_sum(ilabel_log_probs * one_hot, axis=3) + state_log_probs = array_ops.concat([state_log_probs, blank], axis=2) + return array_ops.pad( + state_log_probs, [[0, 0], [0, 0], [1, 0]], + constant_values=math_ops.log(0.0)) + + +def _state_to_olabel(labels, num_labels, states): + """Sum state log probs to ilabel log probs.""" + + num_label_states = _get_dim(labels, 1) + 1 + label_states = states[:, :, 1:num_label_states] + blank_states = states[:, :, num_label_states:] + one_hot = array_ops.one_hot( + labels - 1, depth=(num_labels - 1), + on_value=0.0, off_value=math_ops.log(0.0)) + one_hot = array_ops.expand_dims(one_hot, axis=0) + label_states = array_ops.expand_dims(label_states, axis=3) + label_olabels = math_ops.reduce_logsumexp(label_states + one_hot, axis=2) + blank_olabels = math_ops.reduce_logsumexp( + blank_states, axis=2, keepdims=True) + return array_ops.concat([blank_olabels, label_olabels], axis=-1) + + +# pylint: disable=redefined-outer-name +def _state_to_olabel_unique(labels, num_labels, states, unique): + """Sum state log probs to ilabel log probs using unique label indices.""" + + num_label_states = _get_dim(labels, 1) + 1 + label_states = states[:, :, 1:num_label_states] + blank_states = states[:, :, num_label_states:] + + unique_y, unique_idx = unique + mul_reduce = _sum_states(unique_idx, label_states) + + num_frames = states.shape[0] + batch_size = states.shape[1] + num_states = num_label_states - 1 + batch_state_major = array_ops.transpose(mul_reduce, perm=[1, 2, 0]) + batch_state_major = array_ops.reshape( + batch_state_major, [batch_size * num_states, num_frames]) + batch_offset = math_ops.range(batch_size, dtype=unique_y.dtype) * num_labels + indices = unique_y + array_ops.expand_dims(batch_offset, axis=-1) + indices = array_ops.reshape(indices, [-1, 1]) + scatter = array_ops.scatter_nd( + indices=indices, + updates=batch_state_major, + shape=[batch_size * num_labels, num_frames]) + scatter = array_ops.reshape(scatter, [batch_size, num_labels, num_frames]) + scatter = array_ops.where( + math_ops.equal(scatter, 0.0), + array_ops.fill(array_ops.shape(scatter), math_ops.log(0.0)), + scatter) + label_olabels = array_ops.transpose(scatter, [2, 0, 1]) + label_olabels = label_olabels[:, :, 1:] + + blank_olabels = math_ops.reduce_logsumexp( + blank_states, axis=2, keepdims=True) + + return array_ops.concat([blank_olabels, label_olabels], axis=-1) + + +def ctc_loss_and_grad(logits, labels, label_length, logit_length, unique=None): + """Computes the CTC loss and gradients. + + Most users will want fwd_bwd.ctc_loss + + This function returns the computed gradient, it does not have a gradient + of its own defined. + + Args: + logits: tensor of shape [frames, batch_size, num_labels] + labels: tensor of shape [batch_size, max_label_seq_length] + label_length: tensor of shape [batch_size] + Length of reference label sequence in labels. + logit_length: tensor of shape [batch_size] + Length of input sequence in logits. + unique: (optional) unique label indices as computed by unique(labels) + If supplied, enables an implementation that is faster and more memory + efficient on TPU. + + Returns: + loss: tensor of shape [batch_size] + gradient: tensor of shape [frames, batch_size, num_labels] + """ + + num_labels = _get_dim(logits, 2) + max_label_seq_length = _get_dim(labels, 1) + + ilabel_log_probs = nn_ops.log_softmax(logits) + state_log_probs = _ilabel_to_state(labels, num_labels, ilabel_log_probs) + state_trans_probs = _ctc_state_trans(labels) + initial_state_log_probs, final_state_log_probs = ctc_state_log_probs( + label_length, max_label_seq_length) + fwd_bwd_log_probs, log_likelihood = _forward_backward_log( + state_trans_log_probs=math_ops.log(state_trans_probs), + initial_state_log_probs=initial_state_log_probs, + final_state_log_probs=final_state_log_probs, + observed_log_probs=state_log_probs, + sequence_length=logit_length) + + if unique: + olabel_log_probs = _state_to_olabel_unique( + labels, num_labels, fwd_bwd_log_probs, unique) + else: + olabel_log_probs = _state_to_olabel(labels, num_labels, fwd_bwd_log_probs) + + grad = math_ops.exp(ilabel_log_probs) - math_ops.exp(olabel_log_probs) + loss = -log_likelihood + return loss, grad + + +def _ctc_loss_grad(op, grad_loss, _): + grad = op.outputs[1] + grad = [array_ops.reshape(grad_loss, [1, -1, 1]) * grad] + grad += [None] * (len(op.inputs) - len(grad)) + return grad + + +def _ctc_loss_shape(op): + return [op.inputs[2].get_shape(), op.inputs[0].get_shape()] + + +@tf_export("nn.ctc_loss", v1=["nn.ctc_loss_v2"]) +def ctc_loss_v2(labels, logits, label_length, logit_length, + logits_time_major=True, unique=None, + blank_index=None, name=None): + """Computes CTC (Connectionist Temporal Classification) loss. + + This op implements the CTC loss as presented in the article: + + [A. Graves, S. Fernandez, F. Gomez, J. Schmidhuber. + Connectionist Temporal Classification: Labeling Unsegmented Sequence Data + with Recurrent Neural Networks. ICML 2006, Pittsburgh, USA, + pp. 369-376.](http://www.cs.toronto.edu/~graves/icml_2006.pdf) + + Notes: + - Same as the "Classic CTC" in TensorFlow 1.x's tf.nn.ctc_loss setting of + preprocess_collapse_repeated=False, ctc_merge_repeated=True + - Labels may be supplied as either a dense, zero-padded tensor with a + vector of label sequence lengths OR as a SparseTensor. + - On TPU and GPU: + - Only dense padded labels are supported. + - On CPU: + - Caller may use SparseTensor or dense padded labels but calling with + a SparseTensor will be significantly faster. + - Default blank label is 0 rather num_classes - 1, unless overridden by + blank_index. + + Args: + labels: tensor of shape [batch_size, max_label_seq_length] or SparseTensor + logits: tensor of shape [frames, batch_size, num_labels], + if logits_time_major == False, shape is [batch_size, frames, num_labels]. + label_length: tensor of shape [batch_size], None if labels is SparseTensor + Length of reference label sequence in labels. + logit_length: tensor of shape [batch_size] + Length of input sequence in logits. + logits_time_major: (optional) If True (default), logits is shaped + [time, batch, logits]. If False, shape is [batch, time, logits] + unique: (optional) Unique label indices as computed by + ctc_unique_labels(labels). If supplied, enable a faster, memory + efficient implementation on TPU. + blank_index: (optional) Set the class index to use for the blank label. + Negative values will start from num_classes, ie, -1 will reproduce the + ctc_loss behavior of using num_classes - 1 for the blank symbol. + There is some memory/performance overhead to switching from the default + of 0 as an additional shifted copy of the logits may be created. + name: A name for this `Op`. Defaults to "ctc_loss_dense". + + Returns: + loss: tensor of shape [batch_size], negative log probabilities. + """ + if isinstance(labels, sparse_tensor.SparseTensor): + if blank_index is None: + raise ValueError( + "blank_index must be given when using SparseTensor labels.") + + if blank_index < 0: + blank_index += _get_dim(logits, 2) + + if blank_index != _get_dim(logits, 2) - 1: + logits = array_ops.concat([ + logits[:, :, :blank_index], + logits[:, :, blank_index+1:], + logits[:, :, blank_index:blank_index+1], + ], axis=2) + labels = sparse_tensor.SparseTensor( + labels.indices, + array_ops.where(labels.values < blank_index, + labels.values, + labels.values - 1), + labels.dense_shape) + + return ctc_loss(labels=labels, + inputs=logits, + sequence_length=logit_length, + time_major=logits_time_major) + + if blank_index is None: + blank_index = 0 + + return ctc_loss_dense(labels=labels, + logits=logits, + label_length=label_length, + logit_length=logit_length, + logits_time_major=logits_time_major, + unique=unique, + blank_index=blank_index, + name=name) + + +def ctc_loss_dense(labels, logits, label_length, logit_length, + logits_time_major=True, unique=None, + blank_index=0, name=None): + """Computes CTC (Connectionist Temporal Classification) loss. + + This op implements the CTC loss as presented in the article: + + [A. Graves, S. Fernandez, F. Gomez, J. Schmidhuber. + Connectionist Temporal Classification: Labeling Unsegmented Sequence Data + with Recurrent Neural Networks. ICML 2006, Pittsburgh, USA, + pp. 369-376.](http://www.cs.toronto.edu/~graves/icml_2006.pdf) + + Using the batched forward backward algorithm described in: + + [Sim, K. C., Narayanan, A., Bagby, T., Sainath, T. N., & Bacchiani, M. + Improving the efficiency of forward-backward algorithm using batched + computation in TensorFlow. + Automatic Speech Recognition and Understanding Workshop (ASRU), + 2017 IEEE (pp. 258-264). + ](https://ieeexplore.ieee.org/iel7/8260578/8268903/08268944.pdf) + + Notes: + Significant differences from tf.nn.ctc_loss: + Supports GPU and TPU (tf.nn.ctc_loss supports CPU only): + For batched operations, GPU and TPU are significantly faster than using + ctc_loss on CPU. + This implementation runs on CPU, but significantly slower than ctc_loss. + Blank label is 0 rather num_classes - 1, unless overridden by blank_index. + Logits and labels are dense arrays with padding rather than SparseTensor. + The only mode supported is the same as: + preprocess_collapse_repeated=False, ctc_merge_repeated=True + To collapse labels, the caller can preprocess label sequence first. + + The dense implementation supports both CPU, GPU and TPU. A fast path is + provided that significantly improves memory use for large vocabulary if the + caller preprocesses label sequences to get unique label indices on the CPU + (eg. in the data input pipeline) using ctc_ops.unique and simplies this in + the optional "unique" kwarg. This is especially useful for TPU and GPU but + also works with if used on CPU. + + Args: + labels: tensor of shape [batch_size, max_label_seq_length] + logits: tensor of shape [frames, batch_size, num_labels], + if logits_time_major == False, shape is [batch_size, frames, num_labels]. + label_length: tensor of shape [batch_size] + Length of reference label sequence in labels. + logit_length: tensor of shape [batch_size] + Length of input sequence in logits. + logits_time_major: (optional) If True (default), logits is shaped + [time, batch, logits]. If False, shape is [batch, time, logits] + unique: (optional) Unique label indices as computed by unique(labels). + If supplied, enable a faster, memory efficient implementation on TPU. + blank_index: (optional) Set the class index to use for the blank label. + Negative values will start from num_classes, ie, -1 will reproduce the + ctc_loss behavior of using num_classes - 1 for the blank symbol. + There is some memory/performance overhead to switching from the default + of 0 as an additional shifted copy of the logits may be created. + name: A name for this `Op`. Defaults to "ctc_loss_dense". + + Returns: + loss: tensor of shape [batch_size], negative log probabilities. + """ + + with ops.name_scope(name, "ctc_loss_dense", + [logits, labels, label_length, logit_length]): + logits = ops.convert_to_tensor(logits, name="logits") + labels = ops.convert_to_tensor(labels, name="labels") + label_length = ops.convert_to_tensor(label_length, name="label_length") + logit_length = ops.convert_to_tensor(logit_length, name="logit_length") + + if not logits_time_major: + logits = array_ops.transpose(logits, perm=[1, 0, 2]) + + if blank_index != 0: + if blank_index < 0: + blank_index += _get_dim(logits, 2) + logits = array_ops.concat([ + logits[:, :, blank_index:blank_index+1], + logits[:, :, :blank_index], + logits[:, :, blank_index+1:], + ], axis=2) + labels = array_ops.where(labels < blank_index, labels + 1, labels) + + args = [logits, labels, label_length, logit_length] + + if unique: + unique_y, unique_idx = unique + args.extend([unique_y, unique_idx]) + + # TODO(tombagby): Update to tfe.defun + @function.Defun(*[x.dtype for x in args], + python_grad_func=_ctc_loss_grad, + shape_func=_ctc_loss_shape) + def compute_ctc_loss(logits_t, labels_t, label_length_t, logit_length_t, + *unique_t): + """Compute CTC loss.""" + logits_t.set_shape(logits.shape) + labels_t.set_shape(labels.shape) + label_length_t.set_shape(label_length.shape) + logit_length_t.set_shape(logit_length.shape) + kwargs = dict( + logits=logits_t, + labels=labels_t, + label_length=label_length_t, + logit_length=logit_length_t) + if unique_t: + kwargs["unique"] = unique_t + return ctc_loss_and_grad(**kwargs) + + return compute_ctc_loss(*args)[0] + + +@tf_export("nn.collapse_repeated") +def collapse_repeated(labels, seq_length, name=None): + """Merge repeated labels into single labels. + + Args: + labels: Tensor of shape (batch, max value in seq_length) + seq_length: Tensor of shape (batch), sequence length of each batch element. + name: A name for this `Op`. Defaults to "collapse_repeated_labels". + + Returns: + tuple of Tensor of shape (batch, max_seq_length) with repeated labels + collapsed and padded to max_seq_length, eg: + [[A, A, B, B, A], + [A, B, C, D, E]] => [[A, B, A, 0, 0], + [A, B, C, D, E]] + and int tensor of shape [batch] with new sequence lengths. + """ + + with ops.name_scope(name, "collapse_repeated_labels", + [labels, seq_length]): + labels = ops.convert_to_tensor(labels, name="labels") + seq_length = ops.convert_to_tensor(seq_length, name="seq_length") + + # Mask labels that don't equal previous label. + label_mask = array_ops.concat( + [array_ops.ones_like(labels[:, :1], dtypes.bool), + math_ops.not_equal(labels[:, 1:], labels[:, :-1])], + axis=1) + + # Filter labels that aren't in the original sequence. + maxlen = _get_dim(labels, 1) + seq_mask = array_ops.sequence_mask(seq_length, maxlen=maxlen) + label_mask = math_ops.logical_and(label_mask, seq_mask) + + # Count masks for new sequence lengths. + new_seq_len = math_ops.reduce_sum( + math_ops.cast(label_mask, dtypes.int32), axis=1) + + # Mask indexes based on sequence length mask. + new_maxlen = math_ops.reduce_max(new_seq_len) + idx_mask = array_ops.sequence_mask(new_seq_len, maxlen=new_maxlen) + + # Flatten everything and mask out labels to keep and sparse indices. + flat_labels = array_ops.reshape(labels, [-1]) + flat_label_mask = array_ops.reshape(label_mask, [-1]) + flat_idx_mask = array_ops.reshape(idx_mask, [-1]) + idx = math_ops.range(_get_dim(flat_idx_mask, 0)) + + # Scatter to flat shape. + flat = array_ops.scatter_nd( + indices=array_ops.expand_dims( + array_ops.boolean_mask(idx, flat_idx_mask), axis=1), + updates=array_ops.boolean_mask(flat_labels, flat_label_mask), + shape=array_ops.shape(flat_idx_mask)) + + # Reshape back to square batch. + batch_size = _get_dim(labels, 0) + new_shape = [batch_size, new_maxlen] + return (array_ops.reshape(flat, new_shape), + math_ops.cast(new_seq_len, seq_length.dtype)) + + +def dense_labels_to_sparse(dense, length): + """Convert dense labels with sequence lengths to sparse tensor. + + Args: + dense: tensor of shape [batch, max_length] + length: int tensor of shape [batch] + The length of each sequence in dense. + + Returns: + tf.SparseTensor with values only for the valid elements of sequences. + """ + + flat_values = array_ops.reshape(dense, [-1]) + flat_indices = math_ops.range( + array_ops.shape(flat_values, out_type=dtypes.int64)[0]) + mask = array_ops.sequence_mask(length, maxlen=array_ops.shape(dense)[1]) + flat_mask = array_ops.reshape(mask, [-1]) + indices = array_ops.expand_dims( + array_ops.boolean_mask(flat_indices, flat_mask), 1) + values = array_ops.boolean_mask(flat_values, flat_mask) + sparse = sparse_tensor.SparseTensor( + indices=indices, values=math_ops.cast(values, dtypes.int32), + dense_shape=array_ops.shape(flat_values, out_type=dtypes.int64)) + reshaped = sparse_ops.sparse_reshape(sparse, array_ops.shape(dense)) + max_length = math_ops.reduce_max(length) + return sparse_tensor.SparseTensor( + indices=reshaped.indices, + values=reshaped.values, + dense_shape=[ + math_ops.cast(reshaped.dense_shape[0], dtypes.int64), + math_ops.cast(max_length, dtypes.int64)]) + + +@tf_export("nn.ctc_unique_labels") +def ctc_unique_labels(labels, name=None): + """Get unique labels and indices for batched labels for tf.nn.ctc_loss. + + For use with tf.nn.ctc_loss_v2 optional argument `unique`: This op can be + used to preprocess labels in input pipeline to for better speed/memory use + computing the ctc loss on TPU. + + Example: + ctc_unique_labels([[3, 4, 4, 3]]) -> + unique labels padded with 0: [[3, 4, 0, 0]] + indices of original labels in unique: [0, 1, 1, 0] + + Args: + labels: tensor of shape [batch_size, max_label_length] padded with 0. + name: A name for this `Op`. Defaults to "ctc_unique_labels". + + Returns: + tuple of + - unique labels, tensor of shape `[batch_size, max_label_length]` + - indices into unique labels, shape `[batch_size, max_label_length]` + """ + + with ops.name_scope(name, "ctc_unique_labels", [labels]): + labels = ops.convert_to_tensor(labels, name="labels") + def _unique(x): + u = array_ops.unique(x) + y = array_ops.pad( + u.y, [[0, _get_dim(u.idx, 0) - _get_dim(u.y, 0)]]) + y = math_ops.cast(y, dtypes.int64) + return [y, u.idx] + return functional_ops.map_fn( + _unique, labels, dtype=[dtypes.int64, dtypes.int32]) + + +def _sum_states(idx, states): + """Take logsumexp for each unique state out of all label states. + + Args: + idx: tensor of shape [batch, label_length] + For each sequence, indices into a set of unique labels as computed by + calling unique. + states: tensor of shape [frames, batch, label_length] + Log probabilities for each label state. + + Returns: + tensor of shape [frames, batch_size, label_length], log probabilites summed + for each unique label of the sequence. + """ + + with ops.name_scope("sum_states"): + idx = ops.convert_to_tensor(idx, name="idx") + num_states = _get_dim(states, 2) + states = array_ops.expand_dims(states, axis=2) + one_hot = array_ops.one_hot( + idx, depth=num_states, on_value=0.0, off_value=math_ops.log(0.0), + axis=1) + return math_ops.reduce_logsumexp(states + one_hot, axis=-1) + + +def _forward_backward_log(state_trans_log_probs, initial_state_log_probs, + final_state_log_probs, observed_log_probs, + sequence_length): + """Forward-backward algorithm computed in log domain. + + Args: + state_trans_log_probs: tensor of shape [states, states] or + if different transition matrix per batch [batch_size, states, states] + initial_state_log_probs: tensor of shape [batch_size, states] + final_state_log_probs: tensor of shape [batch_size, states] + observed_log_probs: tensor of shape [frames, batch_size, states] + sequence_length: tensor of shape [batch_size] + + Returns: + forward backward log probabilites: tensor of shape [frames, batch, states] + log_likelihood: tensor of shape [batch_size] + + Raises: + ValueError: If state_trans_log_probs has unknown or incorrect rank. + """ + + if state_trans_log_probs.shape.ndims == 2: + perm = [1, 0] + elif state_trans_log_probs.shape.ndims == 3: + perm = [0, 2, 1] + else: + raise ValueError( + "state_trans_log_probs rank must be known and == 2 or 3, is: %s" % + state_trans_log_probs.shape.ndims) + + bwd_state_trans_log_probs = array_ops.transpose(state_trans_log_probs, perm) + batch_size = _get_dim(observed_log_probs, 1) + + def _forward(state_log_prob, obs_log_prob): + state_log_prob = array_ops.expand_dims(state_log_prob, axis=1) # Broadcast. + state_log_prob += state_trans_log_probs + state_log_prob = math_ops.reduce_logsumexp(state_log_prob, axis=-1) + state_log_prob += obs_log_prob + log_prob_sum = math_ops.reduce_logsumexp( + state_log_prob, axis=-1, keepdims=True) + state_log_prob -= log_prob_sum + return state_log_prob + + fwd = _scan(_forward, observed_log_probs, initial_state_log_probs, + inclusive=True) + + def _backward(accs, elems): + """Calculate log probs and cumulative sum masked for sequence length.""" + state_log_prob, cum_log_sum = accs + obs_log_prob, mask = elems + state_log_prob += obs_log_prob + state_log_prob = array_ops.expand_dims(state_log_prob, axis=1) # Broadcast. + state_log_prob += bwd_state_trans_log_probs + state_log_prob = math_ops.reduce_logsumexp(state_log_prob, axis=-1) + + log_prob_sum = math_ops.reduce_logsumexp( + state_log_prob, axis=-1, keepdims=True) + state_log_prob -= log_prob_sum + + cum_log_sum += array_ops.squeeze(log_prob_sum) * mask + batched_mask = array_ops.expand_dims(mask, axis=1) + out = state_log_prob * batched_mask + out += final_state_log_probs * (1.0 - batched_mask) + return out, cum_log_sum + + zero_log_sum = array_ops.zeros([batch_size]) + maxlen = _get_dim(observed_log_probs, 0) + mask = array_ops.sequence_mask(sequence_length, maxlen, dtypes.float32) + mask = array_ops.transpose(mask, perm=[1, 0]) + + bwd, cum_log_sum = _scan(_backward, (observed_log_probs, mask), + (final_state_log_probs, zero_log_sum), + reverse=True, inclusive=True) + + fwd_bwd_log_probs = fwd[1:] + bwd[1:] + fwd_bwd_log_probs_sum = math_ops.reduce_logsumexp( + fwd_bwd_log_probs, axis=2, keepdims=True) + fwd_bwd_log_probs -= fwd_bwd_log_probs_sum + fwd_bwd_log_probs += math_ops.log(array_ops.expand_dims(mask, axis=2)) + + log_likelihood = bwd[0, :, 0] + cum_log_sum[0] + + return fwd_bwd_log_probs, log_likelihood + + +# TODO(tombagby): This is currently faster for the ctc implementation than using +# functional_ops.scan, but could be replaced by that or something similar if +# things change. +def _scan(fn, elems, initial, reverse=False, inclusive=False, final_only=False): + """Repeatedly applies callable `fn` to a sequence of elements. + + Implemented by functional_ops.While, tpu friendly, no gradient. + + This is similar to functional_ops.scan but significantly faster on tpu/gpu + for the forward backward use case. + + Examples: + scan(lambda a, e: a + e, [1.0, 2.0, 3.0], 1.0) => [2.0, 3.0, 4.0] + + Multiple accumulators: + scan(lambda a, e: (a[0] + e, a[1] * e), [1.0, 2.0, 3.0], (0.0, 1.0)) + + Multiple inputs: + scan(lambda a, e: a + (e[0] * e[1]), (elems1, elems2), 0.0) + + Args: + fn: callable, fn(accumulators, element) return new accumulator values. + The (possibly nested) sequence of accumulators is the same as `initial` + and the return value must have the same structure. + elems: A (possibly nested) tensor which will be unpacked along the first + dimension. The resulting slices will be the second argument to fn. The + first dimension of all nested input tensors must be the same. + initial: A tensor or (possibly nested) sequence of tensors with initial + values for the accumulators. + reverse: (optional) True enables scan and output elems in reverse order. + inclusive: (optional) True includes the initial accumulator values in the + output. Length of output will be len(elem sequence) + 1. Not meaningful + if final_only is True. + final_only: (optional) When True, return only the final accumulated values, + not the concatenation of accumulated values for each input. + + Returns: + A (possibly nested) sequence of tensors with the results of applying fn + to tensors unpacked from elems and previous accumulator values. + """ + + flat_elems = [ops.convert_to_tensor(x) for x in nest.flatten(elems)] + num_elems = array_ops.shape(flat_elems[0])[0] + pack_elems = lambda x: nest.pack_sequence_as(structure=elems, flat_sequence=x) + flat_initial = [ops.convert_to_tensor(x) for x in nest.flatten(initial)] + pack = lambda x: nest.pack_sequence_as(structure=initial, flat_sequence=x) + accum_dtypes = [x.dtype for x in flat_initial] + num_accums = len(flat_initial) + + # Types for counter, [outputs], [accumulators] loop arguments. + if final_only: + loop_dtypes = [dtypes.int32, dtypes.int32] + accum_dtypes + else: + loop_dtypes = [dtypes.int32, dtypes.int32] + accum_dtypes + accum_dtypes + + # TODO(tombagby): Update to tfe.defun + @function.Defun(*loop_dtypes) + def cond(i, num_elems, *args): + del args + return i >= 0 if reverse else i < num_elems + + # The loop *args are [output tensors] + [accumulator tensors] which must + # be paired. Each output corresponds to one accumulator. + @function.Defun(*loop_dtypes) + def body(i, num_elems, *args): + """Loop body.""" + i.set_shape([]) + if final_only: + accum = args + else: + out, accum = args[:num_accums], args[num_accums:] + slices = [array_ops.gather(e, i) for e in flat_elems] + accum = fn(pack(accum), pack_elems(slices)) + flat_accum = nest.flatten(accum) + if final_only: + new_out = [] + else: + update_i = i + 1 if inclusive and not reverse else i + new_out = [inplace_ops.alias_inplace_update(x, update_i, y) + for x, y in zip(out, flat_accum)] + i = i - 1 if reverse else i + 1 + return [i, num_elems] + new_out + flat_accum + + init_i = (array_ops.shape(flat_elems[0])[0] - 1 if reverse + else constant_op.constant(0, dtype=dtypes.int32)) + outputs = [] + if not final_only: + num_outputs = array_ops.shape(flat_elems[0])[0] + (1 if inclusive else 0) + for initial_accum in flat_initial: + out_shape = array_ops.concat( + [[num_outputs], array_ops.shape(initial_accum)], 0) + out = inplace_ops.empty(out_shape, dtype=initial_accum.dtype, init=True) + if inclusive: + out = inplace_ops.alias_inplace_add( + out, init_i + (1 if reverse else 0), initial_accum) + outputs.append(out) + loop_in = [init_i, num_elems] + outputs + flat_initial + hostmem = [ + i for i, x in enumerate(loop_in) + if x.dtype.base_dtype in (dtypes.int32, dtypes.int64) + ] + + # TODO(tombagby): Update to while_v2. + loop_results = functional_ops.While(loop_in, cond, body, hostmem=hostmem) + out = loop_results[2:num_accums + 2] + return pack(out) + + +def _get_dim(tensor, i): + """Get value of tensor shape[i] preferring static value if available.""" + return tensor.shape[i].value or array_ops.shape(tensor)[i] diff --git a/tensorflow/python/ops/data_flow_ops.py b/tensorflow/python/ops/data_flow_ops.py index cca8e12b43..2030332e4e 100644 --- a/tensorflow/python/ops/data_flow_ops.py +++ b/tensorflow/python/ops/data_flow_ops.py @@ -79,7 +79,7 @@ def _as_shape_list(shapes, shapes = [shapes] shapes = [tensor_shape.as_shape(shape) for shape in shapes] if not unknown_dim_allowed: - if any([not shape.is_fully_defined() for shape in shapes]): + if any(not shape.is_fully_defined() for shape in shapes): raise ValueError("All shapes must be fully defined: %s" % shapes) if not unknown_rank_allowed: if any([shape.dims is None for shape in shapes]): @@ -171,7 +171,10 @@ class QueueBase(object): self._names = None self._queue_ref = queue_ref if context.executing_eagerly(): - self._name = context.context().scope_name + if context.context().scope_name: + self._name = context.context().scope_name + else: + self._name = "Empty" self._resource_deleter = resource_variable_ops.EagerResourceDeleter( queue_ref, None) else: @@ -198,11 +201,11 @@ class QueueBase(object): raise TypeError("A list of queues expected") dtypes = queues[0].dtypes - if not all([dtypes == q.dtypes for q in queues[1:]]): + if not all(dtypes == q.dtypes for q in queues[1:]): raise TypeError("Queues do not have matching component dtypes.") names = queues[0].names - if not all([names == q.names for q in queues[1:]]): + if not all(names == q.names for q in queues[1:]): raise TypeError("Queues do not have matching component names.") queue_shapes = [q.shapes for q in queues] @@ -1148,7 +1151,7 @@ class Barrier(object): self._barrier_ref, name=name) -@tf_export("ConditionalAccumulatorBase") +@tf_export(v1=["ConditionalAccumulatorBase"]) class ConditionalAccumulatorBase(object): """A conditional accumulator for aggregating gradients. @@ -1227,7 +1230,7 @@ class ConditionalAccumulatorBase(object): name=name) -@tf_export("ConditionalAccumulator") +@tf_export(v1=["ConditionalAccumulator"]) class ConditionalAccumulator(ConditionalAccumulatorBase): """A conditional accumulator for aggregating gradients. diff --git a/tensorflow/python/ops/dequantize_op_test.py b/tensorflow/python/ops/dequantize_op_test.py index 13e50273d8..794985b2db 100644 --- a/tensorflow/python/ops/dequantize_op_test.py +++ b/tensorflow/python/ops/dequantize_op_test.py @@ -35,7 +35,7 @@ class DequantizeOpTest(test.TestCase): with self.cached_session(): input_op = constant_op.constant(inputs, shape=[len(inputs)], dtype=dtype) dequantized = array_ops.dequantize(input_op, min_range, max_range) - tf_ans = dequantized.eval() + tf_ans = self.evaluate(dequantized) # TODO(vrv): Add support for DT_QINT32 quantization if needed. type_dict = { diff --git a/tensorflow/python/ops/distributions/util.py b/tensorflow/python/ops/distributions/util.py index 760e7a8a84..24314e8fc9 100644 --- a/tensorflow/python/ops/distributions/util.py +++ b/tensorflow/python/ops/distributions/util.py @@ -343,7 +343,7 @@ def embed_check_categorical_event_shape( x_dtype = x.dtype.base_dtype max_event_size = (_largest_integer_by_dtype(x_dtype) if x_dtype.is_floating else 0) - if max_event_size is 0: + if max_event_size == 0: raise TypeError("Unable to validate size of unrecognized dtype " "({}).".format(x_dtype.name)) try: diff --git a/tensorflow/python/ops/embedding_ops.py b/tensorflow/python/ops/embedding_ops.py index 9ce024ad96..b398601e6f 100644 --- a/tensorflow/python/ops/embedding_ops.py +++ b/tensorflow/python/ops/embedding_ops.py @@ -554,7 +554,10 @@ def safe_embedding_lookup_sparse(embedding_weights, dtype = sparse_weights.dtype if sparse_weights is not None else None embedding_weights = [ - ops.convert_to_tensor(w, dtype=dtype) for w in embedding_weights + w if (isinstance(w, resource_variable_ops.ResourceVariable) + and dtype in (None, w.dtype)) + else ops.convert_to_tensor(w, dtype=dtype) + for w in embedding_weights ] with ops.name_scope(name, 'embedding_lookup', diff --git a/tensorflow/python/ops/functional_ops.py b/tensorflow/python/ops/functional_ops.py index fecd7ddbf9..57542e3c7b 100644 --- a/tensorflow/python/ops/functional_ops.py +++ b/tensorflow/python/ops/functional_ops.py @@ -19,7 +19,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.core.protobuf import rewriter_config_pb2 +from tensorflow.core.protobuf import config_pb2 from tensorflow.core.framework import attr_value_pb2 from tensorflow.python.eager import context from tensorflow.python.framework import constant_op @@ -1027,9 +1027,10 @@ _rewriter_config_optimizer_disabled = None def _get_disabled_rewriter_config(): global _rewriter_config_optimizer_disabled if _rewriter_config_optimizer_disabled is None: - rewriter_config = rewriter_config_pb2.RewriterConfig() + config = config_pb2.ConfigProto() + rewriter_config = config.graph_options.rewrite_options rewriter_config.disable_meta_optimizer = True - _rewriter_config_optimizer_disabled = rewriter_config.SerializeToString() + _rewriter_config_optimizer_disabled = config.SerializeToString() return _rewriter_config_optimizer_disabled @@ -1048,7 +1049,7 @@ def partitioned_call(args, f, tout=None, executing_eagerly=None, config=None, the signature of `f`. executing_eagerly: (Optional) A boolean indicating whether the context is executing eagerly. If `None`, fetched from the global context. - config: (Optional) A tensorflow::RewriterConfig proto, serialized. If + config: (Optional) A `tensorflow::ConfigProto` proto, serialized. If `None`, all optimizations are disabled. Currently only handled for eager defined functions. executor_type: (Optional) A string for the name of the executor to be used @@ -1076,10 +1077,12 @@ def partitioned_call(args, f, tout=None, executing_eagerly=None, config=None, if executing_eagerly or len(tout): if f.stateful_ops: outputs = gen_functional_ops.stateful_partitioned_call( - args=args, Tout=tout, f=f, config=config, executor_type=executor_type) + args=args, Tout=tout, f=f, config_proto=config, + executor_type=executor_type) else: outputs = gen_functional_ops.partitioned_call( - args=args, Tout=tout, f=f, config=config, executor_type=executor_type) + args=args, Tout=tout, f=f, config_proto=config, + executor_type=executor_type) return outputs if outputs else None # The generated binding returns an empty list for functions that don't @@ -1098,7 +1101,7 @@ def partitioned_call(args, f, tout=None, executing_eagerly=None, config=None, # When running in graph mode, the graph and function graphs are optimized # (i.e. run through grappler) per the session options, so we can disable any # eager-specific rewriting. - rewriter_config = attr_value_pb2.AttrValue(s=_get_disabled_rewriter_config()) + config_proto = attr_value_pb2.AttrValue(s=_get_disabled_rewriter_config()) graph = ops.get_default_graph() f.add_to_graph(graph) @@ -1113,7 +1116,7 @@ def partitioned_call(args, f, tout=None, executing_eagerly=None, config=None, "Tin": tin_attr, "Tout": tout_attr, "f": func_attr, - "config": rewriter_config, + "config_proto": config_proto, "executor_type": executor_type_attr, }) outputs = op.outputs diff --git a/tensorflow/python/ops/gradient_checker.py b/tensorflow/python/ops/gradient_checker.py index 1665219c80..683f78ce9b 100644 --- a/tensorflow/python/ops/gradient_checker.py +++ b/tensorflow/python/ops/gradient_checker.py @@ -31,7 +31,6 @@ from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients from tensorflow.python.ops import math_ops from tensorflow.python.platform import tf_logging as logging -from tensorflow.python.util import deprecation from tensorflow.python.util.tf_export import tf_export @@ -158,7 +157,8 @@ def _compute_numeric_jacobian(x, x_shape, x_data, y, y_shape, delta, # as delta. Convert to float32 here. Since numeric_jacobian is expected to # be the groundtruth to compare against, it shouldn't lose any information. if x.dtype == dtypes.bfloat16: - x = math_ops.cast(x, dtypes.float32) + x = math_ops.cast(x, dtypes.float32) # TODO(wangpeng): Now that the new x + # is an output of the old x, isn't feeding to the new x a mistake? if y.dtype == dtypes.bfloat16: y = math_ops.cast(y, dtypes.float32) if x_data.dtype == dtypes.bfloat16.as_numpy_dtype: @@ -266,7 +266,7 @@ def _compute_gradient_list(x, return ret -@tf_export("test.compute_gradient") +@tf_export(v1=["test.compute_gradient"]) def compute_gradient(x, x_shape, y, @@ -301,7 +301,6 @@ def compute_gradient(x, as the initial value. delta: (optional) the amount of perturbation. init_targets: list of targets to run to initialize model params. - TODO(mrry): remove this argument. extra_feed_dict: dict that allows fixing specified tensor values during the Jacobian calculation. @@ -311,6 +310,7 @@ def compute_gradient(x, where "x_size" is the number of elements in x and "y_size" is the number of elements in y. If x is a list, returns a list of two numpy arrays. """ + # TODO(mrry): remove argument `init_targets` if extra_feed_dict is None: extra_feed_dict = {} @@ -328,10 +328,17 @@ def compute_gradient(x, return ret +def _compute_error(grad): + if isinstance(grad, tuple): + grad = [grad] + error = 0 + for j_t, j_n in grad: + if j_t.size or j_n.size: # Handle zero size tensors correctly + error = np.maximum(error, np.fabs(j_t - j_n).max()) + return error + + @tf_export(v1=["test.compute_gradient_error"]) -@deprecation.deprecated_args( - None, "init_targets will be deprecated in TensorFlow 2.0", - ("init_targets", None)) # Do not trigger warning in V2 def compute_gradient_error(x, x_shape, y, @@ -373,59 +380,4 @@ def compute_gradient_error(x, """ grad = compute_gradient(x, x_shape, y, y_shape, x_init_value, delta, init_targets, extra_feed_dict=extra_feed_dict) - if isinstance(grad, tuple): - grad = [grad] - error = 0 - for j_t, j_n in grad: - if j_t.size or j_n.size: # Handle zero size tensors correctly - error = np.maximum(error, np.fabs(j_t - j_n).max()) - return error - - -@tf_export("test.compute_gradient_error", v1=[]) -def compute_gradient_error_v2(x, - x_shape, - y, - y_shape, - x_init_value=None, - delta=1e-3, - extra_feed_dict=None): - """Computes the gradient error. - - Computes the maximum error for dy/dx between the computed Jacobian and the - numerically estimated Jacobian. - - This function will modify the tensors passed in as it adds more operations - and hence changing the consumers of the operations of the input tensors. - - This function adds operations to the current session. To compute the error - using a particular device, such as a GPU, use the standard methods for - setting a device (e.g. using with sess.graph.device() or setting a device - function in the session constructor). - - Args: - x: a tensor or list of tensors - x_shape: the dimensions of x as a tuple or an array of ints. If x is a list, - then this is the list of shapes. - y: a tensor - y_shape: the dimensions of y as a tuple or an array of ints. - x_init_value: (optional) a numpy array of the same shape as "x" representing - the initial value of x. If x is a list, this should be a list of numpy - arrays. If this is none, the function will pick a random tensor as the - initial value. - delta: (optional) the amount of perturbation. - extra_feed_dict: dict that allows fixing specified tensor values during the - Jacobian calculation. - - Returns: - The maximum error in between the two Jacobians. - """ - return compute_gradient_error( - x, - x_shape, - y, - y_shape, - x_init_value=x_init_value, - delta=delta, - init_targets=None, - extra_feed_dict=extra_feed_dict) + return _compute_error(grad) diff --git a/tensorflow/python/ops/gradient_checker_test.py b/tensorflow/python/ops/gradient_checker_test.py index 66c7b9a71b..4d2b5efac7 100644 --- a/tensorflow/python/ops/gradient_checker_test.py +++ b/tensorflow/python/ops/gradient_checker_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import math_ops @@ -46,6 +47,7 @@ def _nan_grad(unused_op, grad): class GradientCheckerTest(test.TestCase): + @test_util.run_deprecated_v1 def testAddSimple(self): np.random.seed(1) # Fix seed to avoid flakiness with self.session(use_gpu=False): @@ -60,6 +62,7 @@ class GradientCheckerTest(test.TestCase): tf_logging.info("x1 error = %f", error) assert error < 1e-4 + @test_util.run_deprecated_v1 def testAddSimpleGPU(self): np.random.seed(2) # Fix seed to avoid flakiness with self.session(use_gpu=True): @@ -74,6 +77,7 @@ class GradientCheckerTest(test.TestCase): tf_logging.info("x1 error = %f", error) assert error < 1e-4 + @test_util.run_deprecated_v1 def testAddCustomized(self): np.random.seed(3) # Fix seed to avoid flakiness with self.cached_session(): @@ -92,6 +96,7 @@ class GradientCheckerTest(test.TestCase): tf_logging.info("x2 error = %f", error) assert error < 1e-10 + @test_util.run_deprecated_v1 def testGather(self): np.random.seed(4) # Fix seed to avoid flakiness with self.cached_session(): @@ -109,6 +114,7 @@ class GradientCheckerTest(test.TestCase): tf_logging.info("gather error = %f", error) assert error < 1e-4 + @test_util.run_deprecated_v1 def testNestedGather(self): np.random.seed(5) # Fix seed to avoid flakiness with self.cached_session(): @@ -130,6 +136,7 @@ class GradientCheckerTest(test.TestCase): tf_logging.info("nested gather error = %f", error) assert error < 1e-4 + @test_util.run_deprecated_v1 def testComplexMul(self): with self.cached_session(): size = () @@ -144,6 +151,7 @@ class GradientCheckerTest(test.TestCase): self.assertLess( gradient_checker.compute_gradient_error(x, size, y, size), 2e-4) + @test_util.run_deprecated_v1 def testComplexConj(self): with self.cached_session(): size = () @@ -157,6 +165,7 @@ class GradientCheckerTest(test.TestCase): self.assertLess( gradient_checker.compute_gradient_error(x, size, y, size), 2e-5) + @test_util.run_deprecated_v1 def testEmptySucceeds(self): with self.cached_session(): x = array_ops.placeholder(dtypes.float32) @@ -279,18 +288,23 @@ class MiniMNISTTest(test.TestCase): tf_logging.info("Mini MNIST: %s gradient error = %g", tag, err) return err + @test_util.run_deprecated_v1 def testInputGradient(self): self.assertLess(self._BuildAndTestMiniMNIST(0, "input"), 1e-8) + @test_util.run_deprecated_v1 def testHiddenWeightGradient(self): self.assertLess(self._BuildAndTestMiniMNIST(1, "hidden_weight"), 1e-8) + @test_util.run_deprecated_v1 def testHiddenBiasGradient(self): self.assertLess(self._BuildAndTestMiniMNIST(2, "hidden_bias"), 1e-8) + @test_util.run_deprecated_v1 def testSoftmaxWeightGradient(self): self.assertLess(self._BuildAndTestMiniMNIST(3, "softmax_weight"), 1e-8) + @test_util.run_deprecated_v1 def testSoftmaxBiasGradient(self): self.assertLess(self._BuildAndTestMiniMNIST(4, "softmax_bias"), 1e-8) diff --git a/tensorflow/python/ops/gradient_checker_v2.py b/tensorflow/python/ops/gradient_checker_v2.py new file mode 100644 index 0000000000..cf84484112 --- /dev/null +++ b/tensorflow/python/ops/gradient_checker_v2.py @@ -0,0 +1,318 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Gradient checker for functions. + +The gradient checker verifies numerically that an function properly +computes the gradients +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.eager import backprop +from tensorflow.python.eager import context +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.util.tf_export import tf_export + + +def _product(t): + if isinstance(t, int): + return t + else: + y = 1 + for x in t: + y *= x + return y + + +def _to_numpy(a): + """Converts tensors to numpy arrays. + + Converts Tensors and EagerTensors to numpy arrays. + When eager execution is enabled, converts IndexedSlices + to IndexedSlicesValue with numpy indices/values + + Args: + a: any value. + + Returns: + If a is EagerTensor or Tensor, returns the evaluation of a by calling + numpy() or run(). + If a is IndexedSlices and eager execution is enabled, calls numpy() on a's + fields. Otherwise returns a unchanged. + """ + if isinstance(a, ops.EagerTensor): + return a.numpy() + if isinstance(a, ops.Tensor): + sess = ops.get_default_session() + return sess.run(a) + if isinstance(a, ops.IndexedSlices) and context.executing_eagerly(): + return ops.IndexedSlicesValue( + indices=[x.numpy() for x in a.indices], + values=[x.numpy() for x in a.values], + dense_shape=a.dense_shape) + return a + + +def _prepare(f, xs_dtypes): + """Return a function that executes 'f'. + + In TF 2.x, this is the same as `f`. + In TF 1.x, returns a Python function that executes the graph defined by `f` + in a Session. + + Args: + f: the function. + xs_dtypes: dtypes of f's arguments. + + Returns: + a function that will be evaluated in both graph and eager mode + """ + if context.executing_eagerly(): + + def decorated_eager(*xs_data): + return f(*map(ops.convert_to_tensor, xs_data)) + + return decorated_eager + xs = [array_ops.placeholder(x_dtype) for x_dtype in xs_dtypes] + y = f(*xs) + sess = ops.get_default_session() + def decorated_graph(*xs_data): + xs_data = [_to_numpy(a) for a in xs_data] + return sess.run(y, feed_dict=dict(zip(xs, xs_data))) + return decorated_graph + + +def _compute_theoretical_jacobian(f, y_shape, y_dtype, xs, param): + """Computes the theoretical Jacobian for f regarding xs[param]. + + One can think of the relation among f, xs and y as y = f(xs). + + Args: + f: the function. + y_shape: the shape of the result. + y_dtype: the dtype of the result. + xs: a list of tensors. + param: the index of the target parameter. + + Returns: + A 2-d numpy array representing the Jacobian. It has "x_size" rows + and "y_size" columns where "x_size" is the number of elements in xs[param] + and "y_size" is the number of elements in the result. + + Raises: + ValueError: If result is empty but the gradient is nonzero. + """ + x = xs[param] + # Complex vectors are treated as vectors of twice as many reals. + x_shape = tuple(x.shape) + (2,) if x.dtype.is_complex else x.shape + y_factor = 2 if y_dtype.is_complex else 1 + + # To compute the jacobian, we treat x and y as one-dimensional vectors. + x_size = _product(x_shape) + x_val_size = _product(x_shape[1:]) # This is used for sparse gradients + y_size = _product(y_shape) * y_factor + + # Allocate 2-D Jacobian, with x dimensions smashed into the first + # dimension and y dimensions smashed into the second. + jacobian = np.zeros((x_size, y_size), dtype=x.dtype.real_dtype.as_numpy_dtype) + + # For each of the entry of dy, we set this to be 1 and + # everything else to be 0 and compute the gradients -- this will give us one + # one column of the Jacobian matrix. + dy_data = np.zeros(y_shape, dtype=y_dtype.as_numpy_dtype) + dy_data_flat = dy_data.ravel().view(y_dtype.real_dtype.as_numpy_dtype) + grad_fn_unprep = backprop.gradients_function(f, [param]) + grad_fn = _prepare(lambda dy, *xs: grad_fn_unprep(*xs, dy=dy), + [y_dtype] + [x.dtype for x in xs]) + for col in range(y_size): + dy_data_flat[col] = 1 + grad = _to_numpy(grad_fn(dy_data, *xs)[0]) + dy_data_flat[col] = 0 + if isinstance(grad, ops.IndexedSlicesValue): + for i, v in zip(grad.indices, grad.values): + r_begin = i * x_val_size + r_end = r_begin + x_val_size + jacobian[r_begin:r_end, col] += v.flat + else: + jacobian[:, col] = grad.ravel().view(jacobian.dtype) + + # If the output is empty, run the gradients at least once and make sure + # they produce zeros. + if y_size == 0: # don't use 'not y_size', because y_size may not be an int + grad = _to_numpy(grad_fn(dy_data, *xs)[0]) + if grad.shape != x.shape: + raise ValueError("Empty gradient has wrong shape: expected %s, got %s" % + (x.shape, grad.shape)) + if np.any(grad): + raise ValueError("Empty tensor with nonzero gradients") + + logging.vlog(1, "Theoretical Jacobian =\n%s", jacobian) + return jacobian + + +def _compute_numeric_jacobian(f, y_size, y_dtype, xs, param, + delta): + """Computes the numeric Jacobian for f regarding xs[param]. + + One can think of the relation among f, xs and y as y = f(xs). + + Args: + f: the function. + y_size: the number of elements of the result. + y_dtype: the dtype of the result. + xs: a list of tensors. + param: the index of the target parameter. + delta: the amount of perturbation we give to the input. + + Returns: + A 2-d numpy array representing the Jacobian. It has "x_size" rows + and "y_size" columns where "x_size" is the number of elements in xs[param] + and "y_size" is the number of elements in the result. + """ + # bfloat16 doesn't have enough bits to represent high precision numbers such + # as delta. Convert to float32 here. Since numeric_jacobian is expected to + # be the groundtruth to compare against, it shouldn't lose any information. + x_shape = xs[param].shape + x_dtype = xs[param].dtype + if y_dtype == dtypes.bfloat16: + f = lambda *xs: math_ops.cast(f(*xs), dtypes.float32) + y_dtype = dtypes.float32 + + # To compute the jacobian, we treat x and y as one-dimensional vectors + x_size = _product(x_shape) * (2 if x_dtype.is_complex else 1) + y_size = y_size * (2 if y_dtype.is_complex else 1) + x_dtype = x_dtype.real_dtype.as_numpy_dtype + y_dtype = y_dtype.real_dtype.as_numpy_dtype + + xs_dtypes = [x.dtype for x in xs] + # Converts xs to numpy arrays to do in-place perturbation. + # Calls asarray() to avoid copying in ravel() later. + xs = [np.asarray(_to_numpy(x)) for x in xs] + x = xs[param] + + # Make sure we have the right types + scale = np.asarray(2 * delta, dtype=y_dtype)[()] + + jacobian = np.zeros((x_size, y_size), dtype=x_dtype) + # For each of the entry of x, we slightly perturbs this by adding and + # subtracting a delta and then compute difference between the outputs. This + # will give us one row of the Jacobian matrix. + + f = _prepare(f, xs_dtypes) + for row in range(x_size): + original = x.ravel().view(x_dtype)[row] + x.ravel().view(x_dtype)[row] += delta + y_pos = _to_numpy(f(*xs)) + x.ravel().view(x_dtype)[row] = original + x.ravel().view(x_dtype)[row] -= delta + y_neg = _to_numpy(f(*xs)) + x.ravel().view(x_dtype)[row] = original + diff = (y_pos - y_neg) / scale + jacobian[row, :] = diff.ravel().view(y_dtype) + + logging.vlog(1, "Numeric Jacobian =\n%s", jacobian) + return jacobian + + +def _compute_gradient(f, + y_shape, + y_dtype, + xs, + param, + delta): + """Computes the theoretical and numerical jacobian.""" + x = xs[param] + t = x.dtype + allowed_types = [dtypes.float16, dtypes.bfloat16, dtypes.float32, + dtypes.float64, dtypes.complex64, dtypes.complex128] + assert t.base_dtype in allowed_types, ("Cannot compute gradient for" + "unsupported type %s of argument %s" % + (t.name, param)) + t2 = y_dtype + assert t2.base_dtype in allowed_types, ("Cannot compute gradient for" + "unsupported type %s of y" % t2.name) + y_size = _product(y_shape) + jacob_t = _compute_theoretical_jacobian(f, y_shape, y_dtype, + xs, param) + jacob_n = _compute_numeric_jacobian(f, y_size, y_dtype, xs, + param, delta) + return jacob_t, jacob_n + + +def _compute_gradient_list(f, xs, delta): + """Compute gradients for a list of x values.""" + # convert xs to tensors so that dtype and shape have uniform types + xs = list(map(ops.convert_to_tensor, xs)) + # run the function to get info of the result + xs_dtypes = [x.dtype for x in xs] + f_temp = _prepare(f, xs_dtypes) + y = f_temp(*xs) + return zip(*[_compute_gradient(f, y.shape, dtypes.as_dtype(y.dtype), + xs, i, delta) for i in range(len(xs))]) + + +@tf_export("test.compute_gradient", v1=[]) +def compute_gradient(f, x, delta=1e-3): + """Computes the theoretical and numeric Jacobian of f. + + With y = f(x), computes the theoretical and numeric Jacobian dy/dx. + + Args: + f: the function. + x: a list of tensors. + delta: (optional) perturbation used to compute numeric Jacobian. + + Returns: + A pair of lists, where the first is a list of 2-d numpy arrays representing + the theoretical Jacobians for each argument, and the second list is the + numerical ones. Each 2-d array has "x_size" rows + and "y_size" columns where "x_size" is the number of elements in the + corresponding argument and "y_size" is the number of elements in f(x). + + Raises: + ValueError: If result is empty but the gradient is nonzero. + """ + if not isinstance(x, list): + raise ValueError( + "`x` must be a list of Tensors (arguments to `f`), not a %s" % type(x)) + return _compute_gradient_list(f, x, delta) + + +def max_error(grad1, grad2): + """Computes maximum elementwise gap. + + Computes the maximum elementwise gap between two lists of tensors of the same + shape. + + Args: + grad1: a lists of tensors. + grad2: a lists of tensors with the same shape as grad1. + + Returns: + The maximum elementwise gap between the two. + """ + error = 0 + for j_t, j_n in zip(grad1, grad2): + if j_t.size or j_n.size: # Handle zero size tensors correctly + error = np.maximum(error, np.fabs(j_t - j_n).max()) + return error diff --git a/tensorflow/python/ops/gradient_checker_v2_test.py b/tensorflow/python/ops/gradient_checker_v2_test.py new file mode 100644 index 0000000000..ce9ff47d61 --- /dev/null +++ b/tensorflow/python/ops/gradient_checker_v2_test.py @@ -0,0 +1,300 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for compute_gradient. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.eager import backprop +from tensorflow.python.eager import context +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import custom_gradient +from tensorflow.python.ops import \ +gradient_checker_v2 as gradient_checker +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import nn_ops +# needs this to register gradient for SoftmaxCrossEntropyWithLogits: +import tensorflow.python.ops.nn_grad # pylint: disable=unused-import +from tensorflow.python.platform import test +from tensorflow.python.platform import tf_logging + + +@test_util.run_all_in_graph_and_eager_modes +class GradientCheckerTest(test.TestCase): + + def testAddSimple(self): + # if context.executing_eagerly(): + # return + np.random.seed(1) # Fix seed to avoid flakiness + size = (2, 3) + x1 = constant_op.constant(2.0, shape=size, name="x1") + x2 = constant_op.constant(3.0, shape=size, name="x2") + error = gradient_checker.max_error(*gradient_checker.compute_gradient( + lambda x1: math_ops.add(x1, x2), [x1])) + tf_logging.info("x1 error = %f", error) + assert error < 1e-4 + + def testAddCustomized(self): + np.random.seed(3) # Fix seed to avoid flakiness + size = (2, 3) + x1 = constant_op.constant( + 2.0, shape=size, dtype=dtypes.float64, name="x1") + x2 = np.asarray(np.arange(6, dtype=np.float64).reshape(2, 3)) + # checkint gradients for x2 using a special delta + error = gradient_checker.max_error(*gradient_checker.compute_gradient( + lambda x2: math_ops.add(x1, x2), + [x2], delta=1e-2)) + tf_logging.info("x2 error = %f", error) + assert error < 1e-10 + + def testGather(self): + np.random.seed(4) # Fix seed to avoid flakiness + def f(params): + index_values = [1, 3] + indices = constant_op.constant(index_values, name="i") + return array_ops.gather(params, indices, name="y") + p_shape = (4, 2) + p_size = 8 + params = constant_op.constant( + np.arange(p_size).astype(np.float), shape=p_shape, name="p") + error = gradient_checker.max_error(*gradient_checker.compute_gradient( + f, [params])) + tf_logging.info("gather error = %f", error) + assert error < 1e-4 + + def testNestedGather(self): + np.random.seed(5) # Fix seed to avoid flakiness + def f(params): + index_values = [1, 3, 5, 6] + indices = constant_op.constant(index_values, name="i") + y = array_ops.gather(params, indices, name="y") + index_values2 = [0, 2] + indices2 = constant_op.constant(index_values2, name="i2") + return array_ops.gather(y, indices2, name="y2") + p_shape = (8, 2) + p_size = 16 + params = constant_op.constant( + np.arange(p_size).astype(np.float), shape=p_shape, name="p") + error = gradient_checker.max_error(*gradient_checker.compute_gradient( + f, [params])) + tf_logging.info("nested gather error = %f", error) + assert error < 1e-4 + + def testComplexMul(self): + if not context.executing_eagerly(): + return + c = constant_op.constant(5 + 7j, dtype=dtypes.complex64) + def f(x): + return c * x + x = constant_op.constant(11 - 13j, dtype=dtypes.complex64) + analytical, numerical = gradient_checker.compute_gradient( + f, [x], delta=0.1) + correct = np.array([[5, 7], [-7, 5]]) + self.assertAllEqual(correct, analytical[0]) + self.assertAllClose(correct, numerical[0], rtol=1e-4) + self.assertLess( + gradient_checker.max_error(*gradient_checker.compute_gradient( + f, [x], delta=0.1)), 2e-4) + + def testComplexConj(self): + def f(x): + return math_ops.conj(x) + x = constant_op.constant(11 - 13j, dtype=dtypes.complex64) + analytical, numerical = gradient_checker.compute_gradient( + f, [x], delta=0.1) + correct = np.array([[1, 0], [0, -1]]) + self.assertAllEqual(correct, analytical[0]) + self.assertAllClose(correct, numerical[0], rtol=2e-5) + self.assertLess( + gradient_checker.max_error(*gradient_checker.compute_gradient( + f, [x], delta=0.1)), 2e-5) + + def testEmptySucceeds(self): + def f(x): + return array_ops.identity(x) + x = constant_op.constant(np.random.random_sample((0, 3)), + dtype=dtypes.float32) + for grad in gradient_checker.compute_gradient(f, [x]): + self.assertEqual(grad[0].shape, (0, 0)) + error = gradient_checker.max_error(*gradient_checker.compute_gradient( + f, [x])) + self.assertEqual(error, 0) + + def testEmptyFails(self): + # if not context.executing_eagerly(): + # return + @custom_gradient.custom_gradient + def id_bad_grad(x): + y = array_ops.identity(x) + def grad_fn(dy): + # dx = constant_op.constant(np.zeros((1, 4)), dtype=dtypes.float32) + dx = array_ops.transpose(dy) + return dx + return y, grad_fn + def f(x): + return id_bad_grad(x) + x = constant_op.constant(np.random.random_sample((0, 3)), + dtype=dtypes.float32) + bad = r"Empty gradient has wrong shape: expected \(0, 3\), got \(3, 0\)" + with self.assertRaisesRegexp(ValueError, bad): + gradient_checker.compute_gradient(f, [x]) + + def testNaNGradFails(self): + @custom_gradient.custom_gradient + def id_nan_grad(x): + y = array_ops.identity(x) + def grad_fn(dy): + dx = np.nan * dy + # dx = dy + return dx + return y, grad_fn + def f(x): + return id_nan_grad(x) + x = constant_op.constant(np.random.random_sample((1, 1)), + dtype=dtypes.float32) + error = gradient_checker.max_error(*gradient_checker.compute_gradient( + f, [x])) + # Typical test would assert error < max_err, so assert this test would + # raise AssertionError, since NaN is not < 1.0. + with self.assertRaisesRegexp(AssertionError, "False is not true"): + self.assertTrue(error < 1.0) + + def testGradGrad(self): + + def f(x): + with backprop.GradientTape() as tape: + tape.watch(x) + y = math_ops.square(x) + z = math_ops.square(y) + return tape.gradient(z, x) + + analytical, numerical = gradient_checker.compute_gradient(f, [2.0]) + self.assertAllEqual([[[48.]]], analytical) + self.assertAllClose([[[48.]]], numerical, rtol=1e-4) + + +@test_util.run_all_in_graph_and_eager_modes +class MiniMNISTTest(test.TestCase): + + # Gradient checker for MNIST. + def _BuildAndTestMiniMNIST(self, param_index, tag): + # Fix seed to avoid occasional flakiness + np.random.seed(6) + + # Hyperparameters + batch = 3 + inputs = 16 + features = 32 + classes = 10 + + # Define the parameters + inp_data = np.random.random_sample(inputs * batch) + hidden_weight_data = np.random.randn(inputs * features) / np.sqrt(inputs) + hidden_bias_data = np.random.random_sample(features) + sm_weight_data = np.random.randn(features * classes) / np.sqrt(features) + sm_bias_data = np.random.random_sample(classes) + + # special care for labels since they need to be normalized per batch + label_data = np.random.random(batch * classes).reshape((batch, classes)) + s = label_data.sum(axis=1) + label_data /= s[:, None] + + # We treat the inputs as "parameters" here + inp = constant_op.constant( + inp_data.tolist(), + shape=[batch, inputs], + dtype=dtypes.float64, + name="inp") + hidden_weight = constant_op.constant( + hidden_weight_data.tolist(), + shape=[inputs, features], + dtype=dtypes.float64, + name="hidden_weight") + hidden_bias = constant_op.constant( + hidden_bias_data.tolist(), + shape=[features], + dtype=dtypes.float64, + name="hidden_bias") + softmax_weight = constant_op.constant( + sm_weight_data.tolist(), + shape=[features, classes], + dtype=dtypes.float64, + name="softmax_weight") + softmax_bias = constant_op.constant( + sm_bias_data.tolist(), + shape=[classes], + dtype=dtypes.float64, + name="softmax_bias") + + # List all the parameter so that we can test them one at a time + all_params = [ + inp, hidden_weight, hidden_bias, softmax_weight, softmax_bias + ] + + # Now, Building MNIST + def f(inp, hidden_weight, hidden_bias, softmax_weight, softmax_bias): + features = nn_ops.relu( + nn_ops.xw_plus_b(inp, hidden_weight, hidden_bias), name="features") + logits = nn_ops.xw_plus_b( + features, softmax_weight, softmax_bias, name="logits") + labels = constant_op.constant( + label_data.tolist(), + shape=[batch, classes], + dtype=dtypes.float64, + name="labels") + cost = nn_ops.softmax_cross_entropy_with_logits( + labels=labels, logits=logits, name="cost") + return cost + + def f_restricted(x): + xs = all_params + i = param_index + # use x for the i-th parameter + xs = xs[0:i]+[x]+xs[i+1:] + return f(*xs) + # Test the gradients. + err = gradient_checker.max_error(*gradient_checker.compute_gradient( + f_restricted, [all_params[param_index]], delta=1e-5)) + + tf_logging.info("Mini MNIST: %s gradient error = %g", tag, err) + return err + + def testInputGradient(self): + # if context.executing_eagerly(): + # return + self.assertLess(self._BuildAndTestMiniMNIST(0, "input"), 1e-8) + + def testHiddenWeightGradient(self): + self.assertLess(self._BuildAndTestMiniMNIST(1, "hidden_weight"), 1e-8) + + def testHiddenBiasGradient(self): + self.assertLess(self._BuildAndTestMiniMNIST(2, "hidden_bias"), 1e-8) + + def testSoftmaxWeightGradient(self): + self.assertLess(self._BuildAndTestMiniMNIST(3, "softmax_weight"), 1e-8) + + def testSoftmaxBiasGradient(self): + self.assertLess(self._BuildAndTestMiniMNIST(4, "softmax_bias"), 1e-8) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/ops/gradients_impl.py b/tensorflow/python/ops/gradients_impl.py index 4f0fb54dca..8cc4d926c7 100644 --- a/tensorflow/python/ops/gradients_impl.py +++ b/tensorflow/python/ops/gradients_impl.py @@ -49,9 +49,9 @@ from tensorflow.python.ops import logging_ops # pylint: disable=unused-import from tensorflow.python.ops import manip_grad # pylint: disable=unused-import from tensorflow.python.ops import math_grad # pylint: disable=unused-import from tensorflow.python.ops import math_ops +from tensorflow.python.ops import optional_grad # pylint: disable=unused-import from tensorflow.python.ops import random_grad # pylint: disable=unused-import from tensorflow.python.ops import resource_variable_ops -from tensorflow.python.ops import spectral_grad # pylint: disable=unused-import from tensorflow.python.ops import tensor_array_ops from tensorflow.python.ops.unconnected_gradients import UnconnectedGradients from tensorflow.python.platform import tf_logging as logging @@ -540,7 +540,7 @@ def _Consumers(t, func_graphs): return consumers -@tf_export("gradients") +@tf_export(v1=["gradients"]) def gradients(ys, xs, grad_ys=None, @@ -656,6 +656,119 @@ def gradients(ys, unconnected_gradients) +@tf_export("gradients", v1=[]) +def gradients_v2(ys, # pylint: disable=invalid-name + xs, + grad_ys=None, + name="gradients", + gate_gradients=False, + aggregation_method=None, + stop_gradients=None, + unconnected_gradients=UnconnectedGradients.NONE): + """Constructs symbolic derivatives of sum of `ys` w.r.t. x in `xs`. + + `ys` and `xs` are each a `Tensor` or a list of tensors. `grad_ys` + is a list of `Tensor`, holding the gradients received by the + `ys`. The list must be the same length as `ys`. + + `gradients()` adds ops to the graph to output the derivatives of `ys` with + respect to `xs`. It returns a list of `Tensor` of length `len(xs)` where + each tensor is the `sum(dy/dx)` for y in `ys`. + + `grad_ys` is a list of tensors of the same length as `ys` that holds + the initial gradients for each y in `ys`. When `grad_ys` is None, + we fill in a tensor of '1's of the shape of y for each y in `ys`. A + user can provide their own initial `grad_ys` to compute the + derivatives using a different initial gradient for each y (e.g., if + one wanted to weight the gradient differently for each value in + each y). + + `stop_gradients` is a `Tensor` or a list of tensors to be considered constant + with respect to all `xs`. These tensors will not be backpropagated through, + as though they had been explicitly disconnected using `stop_gradient`. Among + other things, this allows computation of partial derivatives as opposed to + total derivatives. For example: + + ```python + a = tf.constant(0.) + b = 2 * a + g = tf.gradients(a + b, [a, b], stop_gradients=[a, b]) + ``` + + Here the partial derivatives `g` evaluate to `[1.0, 1.0]`, compared to the + total derivatives `tf.gradients(a + b, [a, b])`, which take into account the + influence of `a` on `b` and evaluate to `[3.0, 1.0]`. Note that the above is + equivalent to: + + ```python + a = tf.stop_gradient(tf.constant(0.)) + b = tf.stop_gradient(2 * a) + g = tf.gradients(a + b, [a, b]) + ``` + + `stop_gradients` provides a way of stopping gradient after the graph has + already been constructed, as compared to `tf.stop_gradient` which is used + during graph construction. When the two approaches are combined, + backpropagation stops at both `tf.stop_gradient` nodes and nodes in + `stop_gradients`, whichever is encountered first. + + All integer tensors are considered constant with respect to all `xs`, as if + they were included in `stop_gradients`. + + `unconnected_gradients` determines the value returned for each x in xs if it + is unconnected in the graph to ys. By default this is None to safeguard + against errors. MAthematically these gradients are zero which can be requested + using the `'zero'` option. `tf.UnconnectedGradients` provides the + following options and behaviors: + + ```python + a = tf.ones([1, 2]) + b = tf.ones([3, 1]) + g1 = tf.gradients([b], [a], unnconnected_gradients='none') + sess.run(g1) # [None] + + g2 = tf.gradients([b], [a], unconnected_gradients='zero') + sess.run(g2) # [array([[0., 0.]], dtype=float32)] + ``` + + + Args: + ys: A `Tensor` or list of tensors to be differentiated. + xs: A `Tensor` or list of tensors to be used for differentiation. + grad_ys: Optional. A `Tensor` or list of tensors the same size as + `ys` and holding the gradients computed for each y in `ys`. + name: Optional name to use for grouping all the gradient ops together. + defaults to 'gradients'. + gate_gradients: If True, add a tuple around the gradients returned + for an operations. This avoids some race conditions. + aggregation_method: Specifies the method used to combine gradient terms. + Accepted values are constants defined in the class `AggregationMethod`. + stop_gradients: Optional. A `Tensor` or list of tensors not to differentiate + through. + unconnected_gradients: Optional. Specifies the gradient value returned when + the given input tensors are unconnected. Accepted values are constants + defined in the class `tf.UnconnectedGradients` and the default value is + `none`. + + Returns: + A list of `sum(dy/dx)` for each x in `xs`. + + Raises: + LookupError: if one of the operations between `x` and `y` does not + have a registered gradient function. + ValueError: if the arguments are invalid. + RuntimeError: if called in Eager mode. + + """ + # Creating the gradient graph for control flow mutates Operations. + # _mutation_lock ensures a Session.run call cannot occur between creating and + # mutating new ops. + with ops.get_default_graph()._mutation_lock(): # pylint: disable=protected-access + return _GradientsHelper(ys, xs, grad_ys, name, True, gate_gradients, + aggregation_method, stop_gradients, + unconnected_gradients) + + def _GradientsHelper(ys, xs, grad_ys=None, @@ -896,7 +1009,7 @@ def _HasAnyNotNoneGrads(grads, op): if isinstance(out_grad, (ops.Tensor, ops.IndexedSlices)): return True if out_grad and isinstance(out_grad, collections.Sequence): - if any([g is not None for g in out_grad]): + if any(g is not None for g in out_grad): return True return False @@ -1111,11 +1224,11 @@ def _AggregatedGrads(grads, assert control_flow_util.IsLoopSwitch(op) continue # Grads have to be Tensors or IndexedSlices - if (isinstance(out_grad, collections.Sequence) and not all([ + if (isinstance(out_grad, collections.Sequence) and not all( isinstance(g, (ops.Tensor, ops.IndexedSlices)) for g in out_grad if g is not None - ])): + )): raise TypeError("gradients have to be either all Tensors " "or all IndexedSlices") # Aggregate multiple gradients, and convert [] to None. @@ -1123,7 +1236,7 @@ def _AggregatedGrads(grads, if len(out_grad) < 2: used = "nop" out_grads[i] = out_grad[0] - elif all([isinstance(g, ops.Tensor) for g in out_grad if g is not None]): + elif all(isinstance(g, ops.Tensor) for g in out_grad if g is not None): tensor_shape = _AccumulatorShape(out_grad) if (aggregation_method == AggregationMethod.EXPERIMENTAL_ACCUMULATE_N and len(out_grad) > 2 and tensor_shape.is_fully_defined()): @@ -1240,7 +1353,7 @@ def _hessian_vector_product(ys, xs, v): return gradients(elemwise_products, xs) -@tf_export("hessians") +@tf_export(v1=["hessians"]) def hessians(ys, xs, name="hessians", @@ -1305,3 +1418,16 @@ def hessians(ys, array_ops.concat((_shape, _shape), 0)) hessians.append(_reshaped_hessian) return hessians + + +@tf_export("hessians", v1=[]) +def HessiansV2(ys, + xs, + gate_gradients=False, + aggregation_method=None, + name="hessians"): + return hessians(ys, xs, name=name, gate_gradients=gate_gradients, + aggregation_method=aggregation_method) + + +HessiansV2.__doc__ = hessians.__doc__ diff --git a/tensorflow/python/ops/gradients_test.py b/tensorflow/python/ops/gradients_test.py index 103e3902b6..a9058c4a34 100644 --- a/tensorflow/python/ops/gradients_test.py +++ b/tensorflow/python/ops/gradients_test.py @@ -144,7 +144,7 @@ class GradientsTest(test_util.TensorFlowTestCase): gate_gradients=True)[0] with session.Session(): # Make sure the placer doesn't complain. - gz_x.eval() + self.evaluate(gz_x) def testBoundaryStop(self): # Test that we don't differentiate 'x'. The gradient function for 'x' is @@ -365,7 +365,7 @@ class GradientsTest(test_util.TensorFlowTestCase): grads = gradients.gradients( [y], [x], unconnected_gradients="zero") with self.cached_session() as sess: - self.assertAllEqual([[0.0, 0.0], [0.0, 0.0]], sess.run(grads)[0]) + self.assertAllEqual([[0.0, 0.0], [0.0, 0.0]], self.evaluate(grads)[0]) def testUnconnectedGradientsZeroConnectedGradients(self): with ops.Graph().as_default(): @@ -374,7 +374,7 @@ class GradientsTest(test_util.TensorFlowTestCase): grad = gradients.gradients( [y], [x], unconnected_gradients="zero") with self.cached_session() as sess: - self.assertEquals(3.0, sess.run(grad)[0]) + self.assertEquals(3.0, self.evaluate(grad)[0]) def testUnknownUnconnectedGradientsValueGiven(self): with ops.Graph().as_default(): @@ -438,8 +438,8 @@ class FunctionGradientsTest(test_util.TensorFlowTestCase): grads = gradients.gradients(y, [x, b1]) with self.cached_session() as sess: - self.assertAllEqual([40.0], sess.run(grads)[0]) - self.assertAllEqual([10.0], sess.run(grads)[1]) + self.assertAllEqual([40.0], self.evaluate(grads)[0]) + self.assertAllEqual([10.0], self.evaluate(grads)[1]) def testFunctionGradientsWithGradFunc(self): g = ops.Graph() @@ -487,7 +487,7 @@ class FunctionGradientsTest(test_util.TensorFlowTestCase): f = Foo() with self.cached_session() as sess: - self.assertEqual(sess.run(f), 2.0) + self.assertEqual(self.evaluate(f), 2.0) def testGradientOfCaptured(self): with ops.Graph().as_default(): @@ -501,7 +501,7 @@ class FunctionGradientsTest(test_util.TensorFlowTestCase): f = Foo() with self.cached_session() as sess: - self.assertEqual(sess.run(f), 2.0) + self.assertEqual(self.evaluate(f), 2.0) def testCapturedResourceVariable(self): with ops.Graph().as_default(): @@ -515,8 +515,8 @@ class FunctionGradientsTest(test_util.TensorFlowTestCase): f = Foo() with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) - self.assertEqual(sess.run(f), 2.0) + self.evaluate(variables.global_variables_initializer()) + self.assertEqual(self.evaluate(f), 2.0) def testCapturedNested(self): with ops.Graph().as_default(): @@ -541,9 +541,9 @@ class FunctionGradientsTest(test_util.TensorFlowTestCase): x1_grad, x2_grad = Outer() with self.cached_session() as sess: # 1.0 + None + 2.0 + 1.0 = 4.0 - self.assertEqual(sess.run(x1_grad), 4.0) + self.assertEqual(self.evaluate(x1_grad), 4.0) # None + 1.0 + 1.0 + None = 2.0 - self.assertEqual(sess.run(x2_grad), 2.0) + self.assertEqual(self.evaluate(x2_grad), 2.0) def testCapturedFromFunction(self): with ops.Graph().as_default(): @@ -563,7 +563,7 @@ class FunctionGradientsTest(test_util.TensorFlowTestCase): z_grad = Outer() with self.cached_session() as sess: - self.assertEqual(sess.run(z_grad), 3.0) + self.assertEqual(self.evaluate(z_grad), 3.0) def testCapturedEagerTensors(self): # Test that we can handle captured eager tensors unrelated to the gradient @@ -628,7 +628,7 @@ class HessianVectorProductTest(test_util.TensorFlowTestCase): mat_x = math_ops.matmul(mat, x, name="Ax") x_mat_x = math_ops.matmul(array_ops.transpose(x), mat_x, name="xAx") hess_v = gradients_impl._hessian_vector_product(x_mat_x, [x], [v])[0] - hess_v_actual = hess_v.eval() + hess_v_actual = self.evaluate(hess_v) self.assertAllClose(hess_v_value, hess_v_actual) @@ -648,7 +648,7 @@ class HessianTest(test_util.TensorFlowTestCase): x = constant_op.constant(x_value) x_mat_x = math_ops.reduce_sum(x[:, None] * mat * x[None, :]) hess = gradients.hessians(x_mat_x, x)[0] - hess_actual = hess.eval() + hess_actual = self.evaluate(hess) self.assertAllClose(hess_value, hess_actual) def testHessian1D_multi(self): @@ -692,7 +692,7 @@ class HessianTest(test_util.TensorFlowTestCase): math_ops.matmul(array_ops.transpose(x), x) * 0.5 ) hess = gradients.hessians(x_square, x)[0] - hess_actual = hess.eval() + hess_actual = self.evaluate(hess) hess_value = np.bmat([ [elem*np.ones((m, m)) for elem in vec] for vec in np.eye(m) @@ -711,7 +711,7 @@ class HessianTest(test_util.TensorFlowTestCase): math_ops.matmul(array_ops.transpose(x), x) * 0.5 ) hess = gradients.hessians(x_square, x)[0] - hess_actual = hess.eval() + hess_actual = self.evaluate(hess) hess_value = np.bmat([ [elem*np.ones((n, n)) for elem in vec] for vec in np.eye(m) @@ -729,7 +729,7 @@ class IndexedSlicesToTensorTest(test_util.TensorFlowTestCase): c_sparse = math_ops._as_indexed_slices(c) self.assertAllEqual(np_val.shape, c_sparse.dense_shape.eval()) c_dense = math_ops.multiply(c_sparse, 1.0) - self.assertAllClose(np_val, c_dense.eval()) + self.assertAllClose(np_val, self.evaluate(c_dense)) def testIndexedSlicesToTensorList(self): with self.cached_session(): @@ -745,7 +745,7 @@ class IndexedSlicesToTensorTest(test_util.TensorFlowTestCase): sparse_list.append(c_sparse) packed_dense = array_ops.stack(dense_list) packed_sparse = array_ops.stack(sparse_list) - self.assertAllClose(packed_dense.eval(), packed_sparse.eval()) + self.assertAllClose(packed_dense.eval(), self.evaluate(packed_sparse)) def testInt64Indices(self): with self.cached_session(): @@ -757,7 +757,7 @@ class IndexedSlicesToTensorTest(test_util.TensorFlowTestCase): math_ops.cast(c_sparse.indices, dtypes.int64), c_sparse.dense_shape) self.assertAllEqual(np_val.shape, c_sparse.dense_shape.eval()) c_dense = math_ops.multiply(c_sparse, 1.0) - self.assertAllClose(np_val, c_dense.eval()) + self.assertAllClose(np_val, self.evaluate(c_dense)) def testWarnings(self): # TODO(gunan) Reenable after this issue is fixed: @@ -853,7 +853,7 @@ class CustomGradientTest(test_util.TensorFlowTestCase): y = MyIdentity(MyIdentity(x)) dy = gradients.gradients(y, x)[0] with session.Session(): - self.assertEqual(9., dy.eval()) + self.assertEqual(9., self.evaluate(dy)) def testCustomGradient(self): @@ -873,7 +873,7 @@ class CustomGradientTest(test_util.TensorFlowTestCase): y = MyMultiply(x1, x2) dy = gradients.gradients(y, [x1, x2]) with session.Session() as sess: - self.assertAllEqual([3., 5.], sess.run(dy)) + self.assertAllEqual([3., 5.], self.evaluate(dy)) def testCustomGradientErrors(self): @@ -914,7 +914,7 @@ class CustomGradientTest(test_util.TensorFlowTestCase): for g in grads: self.assertTrue(g is not None) with session.Session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) dw = sess.run(math_ops.reduce_sum(grads[1])) self.assertEqual(12., dw) @@ -1074,7 +1074,7 @@ class TensorListGradientsTest(test_util.TensorFlowTestCase): grad = gradients.gradients(tl, a, grad_ys=grad_tl)[0] with self.cached_session() as sess: - self.assertEquals(sess.run(grad), 5.) + self.assertEquals(self.evaluate(grad), 5.) if __name__ == "__main__": diff --git a/tensorflow/python/ops/histogram_ops_test.py b/tensorflow/python/ops/histogram_ops_test.py index e7fe0efba4..b48ef67196 100644 --- a/tensorflow/python/ops/histogram_ops_test.py +++ b/tensorflow/python/ops/histogram_ops_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.framework import constant_op from tensorflow.python.ops import array_ops from tensorflow.python.ops import histogram_ops @@ -39,7 +40,7 @@ class BinValuesFixedWidth(test.TestCase): bins = histogram_ops.histogram_fixed_width_bins( values, value_range, nbins=5) self.assertEqual(dtypes.int32, bins.dtype) - self.assertAllClose(expected_bins, bins.eval()) + self.assertAllClose(expected_bins, self.evaluate(bins)) def test_1d_values_int32_output(self): # Bins will be: @@ -51,7 +52,7 @@ class BinValuesFixedWidth(test.TestCase): bins = histogram_ops.histogram_fixed_width_bins( values, value_range, nbins=5, dtype=dtypes.int64) self.assertEqual(dtypes.int32, bins.dtype) - self.assertAllClose(expected_bins, bins.eval()) + self.assertAllClose(expected_bins, self.evaluate(bins)) def test_1d_float64_values_int32_output(self): # Bins will be: @@ -63,7 +64,7 @@ class BinValuesFixedWidth(test.TestCase): bins = histogram_ops.histogram_fixed_width_bins( values, value_range, nbins=5) self.assertEqual(dtypes.int32, bins.dtype) - self.assertAllClose(expected_bins, bins.eval()) + self.assertAllClose(expected_bins, self.evaluate(bins)) def test_2d_values(self): # Bins will be: @@ -76,7 +77,7 @@ class BinValuesFixedWidth(test.TestCase): bins = histogram_ops.histogram_fixed_width_bins( values, value_range, nbins=5) self.assertEqual(dtypes.int32, bins.dtype) - self.assertAllClose(expected_bins, bins.eval()) + self.assertAllClose(expected_bins, self.evaluate(bins)) class HistogramFixedWidthTest(test.TestCase): @@ -84,6 +85,7 @@ class HistogramFixedWidthTest(test.TestCase): def setUp(self): self.rng = np.random.RandomState(0) + @test_util.run_deprecated_v1 def test_with_invalid_value_range(self): values = [-1.0, 0.0, 1.5, 2.0, 5.0, 15] with self.assertRaisesRegexp( @@ -92,6 +94,7 @@ class HistogramFixedWidthTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "Dimension must be 2 but is 3"): histogram_ops.histogram_fixed_width(values, [1.0, 2.0, 3.0]) + @test_util.run_deprecated_v1 def test_with_invalid_nbins(self): values = [-1.0, 0.0, 1.5, 2.0, 5.0, 15] with self.assertRaisesRegexp( @@ -110,7 +113,7 @@ class HistogramFixedWidthTest(test.TestCase): with self.session(use_gpu=True): hist = histogram_ops.histogram_fixed_width(values, value_range, nbins=5) self.assertEqual(dtypes.int32, hist.dtype) - self.assertAllClose(expected_bin_counts, hist.eval()) + self.assertAllClose(expected_bin_counts, self.evaluate(hist)) def test_1d_values_int64_output(self): # Bins will be: @@ -122,7 +125,7 @@ class HistogramFixedWidthTest(test.TestCase): hist = histogram_ops.histogram_fixed_width( values, value_range, nbins=5, dtype=dtypes.int64) self.assertEqual(dtypes.int64, hist.dtype) - self.assertAllClose(expected_bin_counts, hist.eval()) + self.assertAllClose(expected_bin_counts, self.evaluate(hist)) def test_1d_float64_values(self): # Bins will be: @@ -133,7 +136,7 @@ class HistogramFixedWidthTest(test.TestCase): with self.session(use_gpu=True): hist = histogram_ops.histogram_fixed_width(values, value_range, nbins=5) self.assertEqual(dtypes.int32, hist.dtype) - self.assertAllClose(expected_bin_counts, hist.eval()) + self.assertAllClose(expected_bin_counts, self.evaluate(hist)) def test_2d_values(self): # Bins will be: @@ -144,8 +147,9 @@ class HistogramFixedWidthTest(test.TestCase): with self.session(use_gpu=True): hist = histogram_ops.histogram_fixed_width(values, value_range, nbins=5) self.assertEqual(dtypes.int32, hist.dtype) - self.assertAllClose(expected_bin_counts, hist.eval()) + self.assertAllClose(expected_bin_counts, self.evaluate(hist)) + @test_util.run_deprecated_v1 def test_shape_inference(self): value_range = [0.0, 5.0] values = [[-1.0, 0.0, 1.5], [2.0, 5.0, 15]] @@ -155,7 +159,7 @@ class HistogramFixedWidthTest(test.TestCase): hist = histogram_ops.histogram_fixed_width(values, value_range, nbins=5) self.assertAllEqual(hist.shape.as_list(), (5,)) self.assertEqual(dtypes.int32, hist.dtype) - self.assertAllClose(expected_bin_counts, hist.eval()) + self.assertAllClose(expected_bin_counts, self.evaluate(hist)) hist = histogram_ops.histogram_fixed_width( values, value_range, nbins=placeholder) diff --git a/tensorflow/python/ops/image_grad_test.py b/tensorflow/python/ops/image_grad_test.py index 32c2f37c0b..c481266dd7 100644 --- a/tensorflow/python/ops/image_grad_test.py +++ b/tensorflow/python/ops/image_grad_test.py @@ -21,6 +21,7 @@ from __future__ import print_function import numpy as np from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import image_ops @@ -44,9 +45,10 @@ class ResizeNearestNeighborOpTest(test.TestCase): out_shape[1:3]) self.assertEqual(out_shape, list(resize_out.get_shape())) - resize_out = sess.run(resize_out) + resize_out = self.evaluate(resize_out) self.assertEqual(out_shape, list(resize_out.shape)) + @test_util.run_deprecated_v1 def testGradFromResizeToLargerInBothDims(self): in_shape = [1, 2, 3, 1] out_shape = [1, 4, 6, 1] @@ -62,6 +64,7 @@ class ResizeNearestNeighborOpTest(test.TestCase): input_tensor, in_shape, resize_out, out_shape, x_init_value=x) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testGradFromResizeToSmallerInBothDims(self): in_shape = [1, 4, 6, 1] out_shape = [1, 2, 3, 1] @@ -77,6 +80,7 @@ class ResizeNearestNeighborOpTest(test.TestCase): input_tensor, in_shape, resize_out, out_shape, x_init_value=x) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testCompareGpuVsCpu(self): in_shape = [1, 4, 6, 3] out_shape = [1, 8, 16, 3] @@ -113,9 +117,10 @@ class ResizeBilinearOpTest(test.TestCase): resize_out = image_ops.resize_bilinear(input_tensor, out_shape[1:3]) self.assertEqual(out_shape, list(resize_out.get_shape())) - resize_out = sess.run(resize_out) + resize_out = self.evaluate(resize_out) self.assertEqual(out_shape, list(resize_out.shape)) + @test_util.run_deprecated_v1 def testGradFromResizeToLargerInBothDims(self): in_shape = [1, 2, 3, 1] out_shape = [1, 4, 6, 1] @@ -129,6 +134,7 @@ class ResizeBilinearOpTest(test.TestCase): input_tensor, in_shape, resize_out, out_shape, x_init_value=x) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testGradFromResizeToSmallerInBothDims(self): in_shape = [1, 4, 6, 1] out_shape = [1, 2, 3, 1] @@ -142,6 +148,7 @@ class ResizeBilinearOpTest(test.TestCase): input_tensor, in_shape, resize_out, out_shape, x_init_value=x) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testCompareGpuVsCpu(self): in_shape = [2, 4, 6, 3] out_shape = [2, 8, 16, 3] @@ -160,6 +167,7 @@ class ResizeBilinearOpTest(test.TestCase): self.assertAllClose(grad[False], grad[True], rtol=1e-4, atol=1e-4) + @test_util.run_deprecated_v1 def testTypes(self): in_shape = [1, 4, 6, 1] out_shape = [1, 2, 3, 1] @@ -196,9 +204,10 @@ class ResizeBicubicOpTest(test.TestCase): align_corners=align_corners) self.assertEqual(out_shape, list(resize_out.get_shape())) - resize_out = sess.run(resize_out) + resize_out = self.evaluate(resize_out) self.assertEqual(out_shape, list(resize_out.shape)) + @test_util.run_deprecated_v1 def testGradFromResizeToLargerInBothDims(self): in_shape = [1, 2, 3, 1] out_shape = [1, 4, 6, 1] @@ -214,6 +223,7 @@ class ResizeBicubicOpTest(test.TestCase): input_tensor, in_shape, resize_out, out_shape, x_init_value=x) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testGradFromResizeToSmallerInBothDims(self): in_shape = [1, 4, 6, 1] out_shape = [1, 2, 3, 1] @@ -229,6 +239,7 @@ class ResizeBicubicOpTest(test.TestCase): input_tensor, in_shape, resize_out, out_shape, x_init_value=x) self.assertLess(err, 1e-3) + @test_util.run_deprecated_v1 def testGradOnUnsupportedType(self): in_shape = [1, 4, 6, 1] out_shape = [1, 2, 3, 1] @@ -273,7 +284,7 @@ class CropAndResizeOpTest(test.TestCase): constant_op.constant( crop_size, shape=[2])) self.assertEqual(crops_shape, list(crops.get_shape())) - crops = sess.run(crops) + crops = self.evaluate(crops) self.assertEqual(crops_shape, list(crops.shape)) def _randomUniformAvoidAnchors(self, low, high, anchors, radius, num_samples): @@ -306,6 +317,7 @@ class CropAndResizeOpTest(test.TestCase): samples.append(sample) return samples + @test_util.run_deprecated_v1 def testGradRandomBoxes(self): """Test that the gradient is correct for randomly generated boxes. diff --git a/tensorflow/python/ops/image_ops_impl.py b/tensorflow/python/ops/image_ops_impl.py index 3ab3695a03..229393c970 100644 --- a/tensorflow/python/ops/image_ops_impl.py +++ b/tensorflow/python/ops/image_ops_impl.py @@ -24,6 +24,7 @@ from tensorflow.python.compat import compat from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import random_seed from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops @@ -37,6 +38,7 @@ from tensorflow.python.ops import nn_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import string_ops from tensorflow.python.ops import variables +from tensorflow.python.util import deprecation from tensorflow.python.util.tf_export import tf_export ops.NotDifferentiable('RandomCrop') @@ -511,15 +513,20 @@ def _rot90_4D(images, k, name_scope): result.set_shape([shape[0], None, None, shape[3]]) return result -@tf_export('image.transpose_image') + +@tf_export(v1=['image.transpose', 'image.transpose_image']) def transpose_image(image): - """Transpose image(s) by swapping the height and width dimension. + return transpose(image=image, name=None) - See also `transpose()`. + +@tf_export('image.transpose', v1=[]) +def transpose(image, name=None): + """Transpose image(s) by swapping the height and width dimension. Args: image: 4-D Tensor of shape `[batch, height, width, channels]` or 3-D Tensor of shape `[height, width, channels]`. + name: A name for this operation (optional). Returns: If `image` was 4-D, a 4-D float Tensor of shape @@ -530,14 +537,14 @@ def transpose_image(image): Raises: ValueError: if the shape of `image` not supported. """ - with ops.name_scope(None, 'transpose_image', [image]): + with ops.name_scope(name, 'transpose', [image]): image = ops.convert_to_tensor(image, name='image') image = _AssertAtLeast3DImage(image) shape = image.get_shape() if shape.ndims == 3 or shape.ndims is None: - return array_ops.transpose(image, [1, 0, 2], name='transpose_image') + return array_ops.transpose(image, [1, 0, 2], name=name) elif shape.ndims == 4: - return array_ops.transpose(image, [0, 2, 1, 3], name='transpose_image') + return array_ops.transpose(image, [0, 2, 1, 3], name=name) else: raise ValueError('\'image\' must have either 3 or 4 dimensions.') @@ -938,12 +945,28 @@ class ResizeMethod(object): AREA = 3 -@tf_export('image.resize_images') +@tf_export(v1=['image.resize_images', 'image.resize']) def resize_images(images, size, method=ResizeMethod.BILINEAR, align_corners=False, preserve_aspect_ratio=False): + return resize_images_v2( + images=images, + size=size, + method=method, + align_corners=align_corners, + preserve_aspect_ratio=preserve_aspect_ratio, + name=None) + + +@tf_export('image.resize', v1=[]) +def resize_images_v2(images, + size, + method=ResizeMethod.BILINEAR, + align_corners=False, + preserve_aspect_ratio=False, + name=None): """Resize `images` to `size` using the specified `method`. Resized images will be distorted if their original aspect ratio is not @@ -979,6 +1002,7 @@ def resize_images(images, then `images` will be resized to a size that fits in `size` while preserving the aspect ratio of the original image. Scales up the image if `size` is bigger than the current size of the `image`. Defaults to False. + name: A name for this operation (optional). Raises: ValueError: if the shape of `images` is incompatible with the @@ -992,7 +1016,7 @@ def resize_images(images, If `images` was 3-D, a 3-D float Tensor of shape `[new_height, new_width, channels]`. """ - with ops.name_scope(None, 'resize_images', [images, size]): + with ops.name_scope(name, 'resize', [images, size]): images = ops.convert_to_tensor(images, name='images') if images.get_shape().ndims is None: raise ValueError('\'images\' contains no shape.') @@ -1736,7 +1760,7 @@ def adjust_saturation(image, saturation_factor, name=None): orig_dtype) -@tf_export('image.is_jpeg') +@tf_export('io.is_jpeg', 'image.is_jpeg', v1=['io.is_jpeg', 'image.is_jpeg']) def is_jpeg(contents, name=None): r"""Convenience function to check if the 'contents' encodes a JPEG image. @@ -1771,8 +1795,28 @@ def _is_png(contents, name=None): substr = string_ops.substr(contents, 0, 3) return math_ops.equal(substr, b'\211PN', name=name) +tf_export('io.decode_and_crop_jpeg', 'image.decode_and_crop_jpeg', + v1=['io.decode_and_crop_jpeg', 'image.decode_and_crop_jpeg'])( + gen_image_ops.decode_and_crop_jpeg) + +tf_export('io.decode_bmp', 'image.decode_bmp', + v1=['io.decode_bmp', 'image.decode_bmp'])(gen_image_ops.decode_bmp) +tf_export('io.decode_gif', 'image.decode_gif', + v1=['io.decode_gif', 'image.decode_gif'])(gen_image_ops.decode_gif) +tf_export('io.decode_jpeg', 'image.decode_jpeg', + v1=['io.decode_jpeg', 'image.decode_jpeg'])(gen_image_ops.decode_jpeg) +tf_export('io.decode_png', 'image.decode_png', + v1=['io.decode_png', 'image.decode_png'])(gen_image_ops.decode_png) -@tf_export('image.decode_image') +tf_export('io.encode_jpeg', 'image.encode_jpeg', + v1=['io.encode_jpeg', 'image.encode_jpeg'])(gen_image_ops.encode_jpeg) +tf_export('io.extract_jpeg_shape', 'image.extract_jpeg_shape', + v1=['io.extract_jpeg_shape', 'image.extract_jpeg_shape'])( + gen_image_ops.extract_jpeg_shape) + + +@tf_export('io.decode_image', 'image.decode_image', + v1=['io.decode_image', 'image.decode_image']) def decode_image(contents, channels=None, dtype=dtypes.uint8, name=None): """Convenience function for `decode_bmp`, `decode_gif`, `decode_jpeg`, and `decode_png`. @@ -1942,7 +1986,114 @@ def total_variation(images, name=None): return tot_var -@tf_export('image.sample_distorted_bounding_box') +@tf_export('image.sample_distorted_bounding_box', v1=[]) +def sample_distorted_bounding_box_v2(image_size, + bounding_boxes, + seed=0, + min_object_covered=0.1, + aspect_ratio_range=None, + area_range=None, + max_attempts=None, + use_image_if_no_bounding_boxes=None, + name=None): + """Generate a single randomly distorted bounding box for an image. + + Bounding box annotations are often supplied in addition to ground-truth labels + in image recognition or object localization tasks. A common technique for + training such a system is to randomly distort an image while preserving + its content, i.e. *data augmentation*. This Op outputs a randomly distorted + localization of an object, i.e. bounding box, given an `image_size`, + `bounding_boxes` and a series of constraints. + + The output of this Op is a single bounding box that may be used to crop the + original image. The output is returned as 3 tensors: `begin`, `size` and + `bboxes`. The first 2 tensors can be fed directly into `tf.slice` to crop the + image. The latter may be supplied to `tf.image.draw_bounding_boxes` to + visualize what the bounding box looks like. + + Bounding boxes are supplied and returned as `[y_min, x_min, y_max, x_max]`. + The bounding box coordinates are floats in `[0.0, 1.0]` relative to the width + and height of the underlying image. + + For example, + + ```python + # Generate a single distorted bounding box. + begin, size, bbox_for_draw = tf.image.sample_distorted_bounding_box( + tf.shape(image), + bounding_boxes=bounding_boxes, + min_object_covered=0.1) + + # Draw the bounding box in an image summary. + image_with_box = tf.image.draw_bounding_boxes(tf.expand_dims(image, 0), + bbox_for_draw) + tf.summary.image('images_with_box', image_with_box) + + # Employ the bounding box to distort the image. + distorted_image = tf.slice(image, begin, size) + ``` + + Note that if no bounding box information is available, setting + `use_image_if_no_bounding_boxes = true` will assume there is a single implicit + bounding box covering the whole image. If `use_image_if_no_bounding_boxes` is + false and no bounding boxes are supplied, an error is raised. + + Args: + image_size: A `Tensor`. Must be one of the following types: `uint8`, `int8`, + `int16`, `int32`, `int64`. + 1-D, containing `[height, width, channels]`. + bounding_boxes: A `Tensor` of type `float32`. + 3-D with shape `[batch, N, 4]` describing the N bounding boxes + associated with the image. + seed: An optional `int`. Defaults to `0`. + If either `seed` or `seed2` are set to non-zero, the random number + generator is seeded by the given `seed`. Otherwise, it is seeded by a + random seed. + min_object_covered: A Tensor of type `float32`. Defaults to `0.1`. + The cropped area of the image must contain at least this + fraction of any bounding box supplied. The value of this parameter should + be non-negative. In the case of 0, the cropped area does not need to + overlap any of the bounding boxes supplied. + aspect_ratio_range: An optional list of `floats`. Defaults to `[0.75, + 1.33]`. + The cropped area of the image must have an aspect `ratio = + width / height` within this range. + area_range: An optional list of `floats`. Defaults to `[0.05, 1]`. + The cropped area of the image must contain a fraction of the + supplied image within this range. + max_attempts: An optional `int`. Defaults to `100`. + Number of attempts at generating a cropped region of the image + of the specified constraints. After `max_attempts` failures, return the + entire image. + use_image_if_no_bounding_boxes: An optional `bool`. Defaults to `False`. + Controls behavior if no bounding boxes supplied. + If true, assume an implicit bounding box covering the whole input. If + false, raise an error. + name: A name for the operation (optional). + + Returns: + A tuple of `Tensor` objects (begin, size, bboxes). + + begin: A `Tensor`. Has the same type as `image_size`. 1-D, containing + `[offset_height, offset_width, 0]`. Provide as input to + `tf.slice`. + size: A `Tensor`. Has the same type as `image_size`. 1-D, containing + `[target_height, target_width, -1]`. Provide as input to + `tf.slice`. + bboxes: A `Tensor` of type `float32`. 3-D with shape `[1, 1, 4]` containing + the distorted bounding box. + Provide as input to `tf.image.draw_bounding_boxes`. + """ + seed1, seed2 = random_seed.get_seed(seed) if seed else (0, 0) + return sample_distorted_bounding_box( + image_size, bounding_boxes, seed1, seed2, min_object_covered, + aspect_ratio_range, area_range, max_attempts, + use_image_if_no_bounding_boxes, name) + + +@tf_export(v1=['image.sample_distorted_bounding_box']) +@deprecation.deprecated(date=None, instructions='`seed2` arg is deprecated.' + 'Use sample_distorted_bounding_box_v2 instead.') def sample_distorted_bounding_box(image_size, bounding_boxes, seed=None, @@ -2808,3 +2959,102 @@ def sobel_edges(image): output = array_ops.reshape(output, shape=shape) output.set_shape(static_image_shape.concatenate([num_kernels])) return output + + +resize_area_deprecation = deprecation.deprecated( + date=None, + instructions=( + 'Use `tf.image.resize(...method=ResizeMethod.AREA...)` instead.')) +tf_export(v1=['image.resize_area'])( + resize_area_deprecation(gen_image_ops.resize_area)) + +resize_bicubic_deprecation = deprecation.deprecated( + date=None, + instructions=( + 'Use `tf.image.resize(...method=ResizeMethod.BICUBIC...)` instead.')) +tf_export(v1=['image.resize_bicubic'])( + resize_bicubic_deprecation(gen_image_ops.resize_bicubic)) + +resize_bilinear_deprecation = deprecation.deprecated( + date=None, + instructions=( + 'Use `tf.image.resize(...method=ResizeMethod.BILINEAR...)` instead.')) +tf_export(v1=['image.resize_bilinear'])( + resize_bilinear_deprecation(gen_image_ops.resize_bilinear)) + +resize_nearest_neighbor_deprecation = deprecation.deprecated( + date=None, + instructions=( + 'Use `tf.image.resize(...method=ResizeMethod.NEAREST_NEIGHBOR...)` ' + 'instead.')) +tf_export(v1=['image.resize_nearest_neighbor'])( + resize_nearest_neighbor_deprecation(gen_image_ops.resize_nearest_neighbor)) + + +@tf_export('image.crop_and_resize', v1=[]) +def crop_and_resize_v2( + image, + boxes, + box_indices, + crop_size, + method='bilinear', + extrapolation_value=0, + name=None): + """Extracts crops from the input image tensor and resizes them. + + Extracts crops from the input image tensor and resizes them using bilinear + sampling or nearest neighbor sampling (possibly with aspect ratio change) to a + common output size specified by `crop_size`. This is more general than the + `crop_to_bounding_box` op which extracts a fixed size slice from the input + image and does not allow resizing or aspect ratio change. + + Returns a tensor with `crops` from the input `image` at positions defined at + the bounding box locations in `boxes`. The cropped boxes are all resized (with + bilinear or nearest neighbor interpolation) to a fixed + `size = [crop_height, crop_width]`. The result is a 4-D tensor + `[num_boxes, crop_height, crop_width, depth]`. The resizing is corner aligned. + In particular, if `boxes = [[0, 0, 1, 1]]`, the method will give identical + results to using `tf.image.resize_bilinear()` or + `tf.image.resize_nearest_neighbor()`(depends on the `method` argument) with + `align_corners=True`. + + Args: + image: A 4-D tensor of shape `[batch, image_height, image_width, depth]`. + Both `image_height` and `image_width` need to be positive. + boxes: A 2-D tensor of shape `[num_boxes, 4]`. The `i`-th row of the tensor + specifies the coordinates of a box in the `box_ind[i]` image and is + specified in normalized coordinates `[y1, x1, y2, x2]`. A normalized + coordinate value of `y` is mapped to the image coordinate at `y * + (image_height - 1)`, so as the `[0, 1]` interval of normalized image + height is mapped to `[0, image_height - 1]` in image height coordinates. + We do allow `y1` > `y2`, in which case the sampled crop is an up-down + flipped version of the original image. The width dimension is treated + similarly. Normalized coordinates outside the `[0, 1]` range are allowed, + in which case we use `extrapolation_value` to extrapolate the input image + values. + box_indices: A 1-D tensor of shape `[num_boxes]` with int32 values in `[0, + batch)`. The value of `box_ind[i]` specifies the image that the `i`-th box + refers to. + crop_size: A 1-D tensor of 2 elements, `size = [crop_height, crop_width]`. + All cropped image patches are resized to this size. The aspect ratio of + the image content is not preserved. Both `crop_height` and `crop_width` + need to be positive. + method: An optional string specifying the sampling method for resizing. It + can be either `"bilinear"` or `"nearest"` and default to `"bilinear"`. + Currently two sampling methods are supported: Bilinear and Nearest + Neighbor. + extrapolation_value: An optional `float`. Defaults to `0`. Value used for + extrapolation, when applicable. + name: A name for the operation (optional). + + Returns: + A 4-D tensor of shape `[num_boxes, crop_height, crop_width, depth]`. + """ + return gen_image_ops.crop_and_resize( + image, boxes, box_indices, crop_size, method, extrapolation_value, name) + + +crop_and_resize_deprecation = deprecation.deprecated_args( + None, 'box_ind is deprecated, use box_indices instead', 'box_ind') +tf_export(v1=['image.crop_and_resize'])( + crop_and_resize_deprecation(gen_image_ops.crop_and_resize)) diff --git a/tensorflow/python/ops/image_ops_test.py b/tensorflow/python/ops/image_ops_test.py index a3aeb79586..e7249333bd 100644 --- a/tensorflow/python/ops/image_ops_test.py +++ b/tensorflow/python/ops/image_ops_test.py @@ -70,7 +70,8 @@ class RGBToHSVTest(test_util.TensorFlowTestCase): split2 = list(map(image_ops.hsv_to_rgb, split1)) join1 = array_ops.stack(split1) join2 = array_ops.stack(split2) - batch1, batch2, join1, join2 = sess.run([batch1, batch2, join1, join2]) + batch1, batch2, join1, join2 = self.evaluate( + [batch1, batch2, join1, join2]) # Verify that processing batch elements together is the same as separate self.assertAllClose(batch1, join1) @@ -84,7 +85,7 @@ class RGBToHSVTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): hsv = image_ops.rgb_to_hsv(rgb_np) rgb = image_ops.hsv_to_rgb(hsv) - rgb_tf = rgb.eval() + rgb_tf = self.evaluate(rgb) self.assertAllClose(rgb_tf, rgb_np) @@ -109,7 +110,8 @@ class RGBToYIQTest(test_util.TensorFlowTestCase): split2 = list(map(image_ops.yiq_to_rgb, split1)) join1 = array_ops.stack(split1) join2 = array_ops.stack(split2) - batch1, batch2, join1, join2 = sess.run([batch1, batch2, join1, join2]) + batch1, batch2, join1, join2 = self.evaluate( + [batch1, batch2, join1, join2]) # Verify that processing batch elements together is the same as separate self.assertAllClose(batch1, join1, rtol=1e-4, atol=1e-4) @@ -138,7 +140,8 @@ class RGBToYUVTest(test_util.TensorFlowTestCase): split2 = list(map(image_ops.yuv_to_rgb, split1)) join1 = array_ops.stack(split1) join2 = array_ops.stack(split2) - batch1, batch2, join1, join2 = sess.run([batch1, batch2, join1, join2]) + batch1, batch2, join1, join2 = self.evaluate( + [batch1, batch2, join1, join2]) # Verify that processing batch elements together is the same as separate self.assertAllClose(batch1, join1, rtol=1e-4, atol=1e-4) @@ -173,7 +176,7 @@ class GrayscaleToRGBTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.rgb_to_grayscale(x_tf) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def testBasicRGBToGrayscale(self): @@ -195,7 +198,7 @@ class GrayscaleToRGBTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.grayscale_to_rgb(x_tf) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) # 3-D input with no batch dimension. @@ -205,9 +208,10 @@ class GrayscaleToRGBTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.grayscale_to_rgb(x_tf) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) + @test_util.run_deprecated_v1 def testShapeInference(self): # Shape inference works and produces expected output where possible rgb_shape = [7, None, 19, 3] @@ -245,7 +249,7 @@ class AdjustGamma(test_util.TensorFlowTestCase): x = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.adjust_gamma(x, gamma=1) - y_tf = y.eval() + y_tf = self.evaluate(y) y_np = x_np self.assertAllClose(y_tf, y_np, 1e-6) @@ -268,6 +272,7 @@ class AdjustGamma(test_util.TensorFlowTestCase): else: raise AssertionError("Exception not raised: %s" % err_msg) + @test_util.run_deprecated_v1 def test_adjust_gamma_less_zero_tensor(self): """White image should be returned for gamma equal to zero""" with self.cached_session(): @@ -281,7 +286,7 @@ class AdjustGamma(test_util.TensorFlowTestCase): err_msg = "Gamma should be a non-negative real number." try: - image.eval() + self.evaluate(image) except Exception as e: if err_msg not in str(e): raise @@ -297,7 +302,7 @@ class AdjustGamma(test_util.TensorFlowTestCase): x = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.adjust_gamma(x, gamma=0) - y_tf = y.eval() + y_tf = self.evaluate(y) dtype = x.dtype.as_numpy_dtype y_np = np.array([dtypes.dtype_range[dtype][1]] * x_np.size) @@ -305,6 +310,7 @@ class AdjustGamma(test_util.TensorFlowTestCase): self.assertAllClose(y_tf, y_np, 1e-6) + @test_util.run_deprecated_v1 def test_adjust_gamma_less_one(self): """Verifying the output with expected results for gamma correction with gamma equal to half""" @@ -326,6 +332,7 @@ class AdjustGamma(test_util.TensorFlowTestCase): self.assertAllClose(y_tf, y_np, 1e-6) + @test_util.run_deprecated_v1 def test_adjust_gamma_greater_one(self): """Verifying the output with expected results for gamma correction with gamma equal to two""" @@ -360,7 +367,7 @@ class AdjustHueTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.adjust_hue(x, delta) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def testAdjustPositiveHue(self): @@ -375,7 +382,7 @@ class AdjustHueTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.adjust_hue(x, delta) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def testBatchAdjustHue(self): @@ -390,7 +397,7 @@ class AdjustHueTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.adjust_hue(x, delta) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def _adjustHueNp(self, x_np, delta_h): @@ -415,7 +422,7 @@ class AdjustHueTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np) y = image_ops.adjust_hue(x, delta_h) - y_tf = y.eval() + y_tf = self.evaluate(y) return y_tf def testAdjustRandomHue(self): @@ -488,11 +495,11 @@ class FlipImageBenchmark(test.Benchmark): trainable=False, dtype=dtypes.float32) run_op = image_ops.flip_left_right(inputs) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for i in xrange(warmup_rounds + benchmark_rounds): if i == warmup_rounds: start = time.time() - sess.run(run_op) + self.evaluate(run_op) end = time.time() step_time = (end - start) / benchmark_rounds tag = device + "_%s" % (cpu_count if cpu_count is not None else "_all") @@ -518,11 +525,11 @@ class FlipImageBenchmark(test.Benchmark): trainable=False, dtype=dtypes.float32) run_op = image_ops.random_flip_left_right(inputs) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for i in xrange(warmup_rounds + benchmark_rounds): if i == warmup_rounds: start = time.time() - sess.run(run_op) + self.evaluate(run_op) end = time.time() step_time = (end - start) / benchmark_rounds tag = device + "_%s" % (cpu_count if cpu_count is not None else "_all") @@ -548,11 +555,11 @@ class FlipImageBenchmark(test.Benchmark): trainable=False, dtype=dtypes.float32) run_op = image_ops.random_flip_left_right(inputs) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for i in xrange(warmup_rounds + benchmark_rounds): if i == warmup_rounds: start = time.time() - sess.run(run_op) + self.evaluate(run_op) end = time.time() step_time = (end - start) / benchmark_rounds tag = device + "_%s" % (cpu_count if cpu_count is not None else "_all") @@ -610,11 +617,11 @@ class AdjustHueBenchmark(test.Benchmark): delta = constant_op.constant(0.1, dtype=dtypes.float32) outputs = image_ops.adjust_hue(inputs, delta) run_op = control_flow_ops.group(outputs) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for i in xrange(warmup_rounds + benchmark_rounds): if i == warmup_rounds: start = time.time() - sess.run(run_op) + self.evaluate(run_op) end = time.time() step_time = (end - start) / benchmark_rounds tag = device + "_%s" % (cpu_count if cpu_count is not None else "_all") @@ -653,12 +660,12 @@ class AdjustSaturationBenchmark(test.Benchmark): delta = constant_op.constant(0.1, dtype=dtypes.float32) outputs = image_ops.adjust_saturation(inputs, delta) run_op = control_flow_ops.group(outputs) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in xrange(warmup_rounds): - sess.run(run_op) + self.evaluate(run_op) start = time.time() for _ in xrange(benchmark_rounds): - sess.run(run_op) + self.evaluate(run_op) end = time.time() step_time = (end - start) / benchmark_rounds tag = device + "_%s" % (cpu_count if cpu_count is not None else "_all") @@ -698,7 +705,7 @@ class ResizeBilinearBenchmark(test.Benchmark): benchmark_op = control_flow_ops.group(*deps) with self.benchmark_session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) results = self.run_op_benchmark( sess, benchmark_op, @@ -746,7 +753,7 @@ class ResizeBicubicBenchmark(test.Benchmark): benchmark_op = control_flow_ops.group(*deps) with self.benchmark_session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) results = self.run_op_benchmark( sess, benchmark_op, @@ -803,7 +810,7 @@ class ResizeAreaBenchmark(test.Benchmark): benchmark_op = control_flow_ops.group(*deps) with self.benchmark_session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) results = self.run_op_benchmark( sess, benchmark_op, @@ -846,7 +853,7 @@ class AdjustSaturationTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.adjust_saturation(x, saturation_factor) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def testTwiceSaturation(self): @@ -861,7 +868,7 @@ class AdjustSaturationTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.adjust_saturation(x, saturation_factor) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def testBatchSaturation(self): @@ -876,7 +883,7 @@ class AdjustSaturationTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.adjust_saturation(x, saturation_factor) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def _adjust_saturation(self, image, saturation_factor): @@ -899,7 +906,7 @@ class AdjustSaturationTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_shape) y = self._adjust_saturation(x, saturation_factor) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def testTwiceSaturationFused(self): @@ -914,7 +921,7 @@ class AdjustSaturationTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_shape) y = self._adjust_saturation(x, saturation_factor) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def _adjustSaturationNp(self, x_np, scale): @@ -935,6 +942,7 @@ class AdjustSaturationTest(test_util.TensorFlowTestCase): y_v[i][2] = b return y_v.reshape(x_np.shape) + @test_util.run_deprecated_v1 def testAdjustRandomSaturation(self): x_shapes = [ [2, 2, 3], @@ -980,7 +988,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.flip_left_right(image_ops.flip_left_right(x_tf)) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, x_np) def testInvolutionLeftRightWithBatch(self): @@ -990,9 +998,10 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.flip_left_right(image_ops.flip_left_right(x_tf)) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, x_np) + @test_util.run_deprecated_v1 def testLeftRight(self): x_np = np.array([[1, 2, 3], [1, 2, 3]], dtype=np.uint8).reshape([2, 3, 1]) y_np = np.array([[3, 2, 1], [3, 2, 1]], dtype=np.uint8).reshape([2, 3, 1]) @@ -1001,7 +1010,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.flip_left_right(x_tf) self.assertTrue(y.op.name.startswith("flip_left_right")) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def testLeftRightWithBatch(self): @@ -1015,9 +1024,10 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.flip_left_right(x_tf) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) + @test_util.run_deprecated_v1 def testRandomFlipLeftRight(self): x_np = np.array([[1, 2, 3], [1, 2, 3]], dtype=np.uint8).reshape([2, 3, 1]) y_np = np.array([[3, 2, 1], [3, 2, 1]], dtype=np.uint8).reshape([2, 3, 1]) @@ -1031,7 +1041,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): count_flipped = 0 count_unflipped = 0 for _ in range(100): - y_tf = y.eval() + y_tf = self.evaluate(y) if y_tf[0][0] == 1: self.assertAllEqual(y_tf, x_np) count_unflipped += 1 @@ -1046,6 +1056,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): self.assertGreaterEqual(count_flipped, 20) self.assertGreaterEqual(count_unflipped, 20) + @test_util.run_deprecated_v1 def testRandomFlipLeftRightWithBatch(self): batch_size = 16 seed = 42 @@ -1070,7 +1081,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): count_flipped = 0 count_unflipped = 0 for _ in range(100): - y_tf = y.eval() + y_tf = self.evaluate(y) # check every element of the batch for i in range(batch_size): @@ -1096,7 +1107,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.flip_up_down(image_ops.flip_up_down(x_tf)) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, x_np) def testInvolutionUpDownWithBatch(self): @@ -1107,9 +1118,10 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.flip_up_down(image_ops.flip_up_down(x_tf)) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, x_np) + @test_util.run_deprecated_v1 def testUpDown(self): x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint8).reshape([2, 3, 1]) y_np = np.array([[4, 5, 6], [1, 2, 3]], dtype=np.uint8).reshape([2, 3, 1]) @@ -1118,7 +1130,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.flip_up_down(x_tf) self.assertTrue(y.op.name.startswith("flip_up_down")) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def testUpDownWithBatch(self): @@ -1132,9 +1144,10 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.flip_up_down(x_tf) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) + @test_util.run_deprecated_v1 def testRandomFlipUpDown(self): x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint8).reshape([2, 3, 1]) y_np = np.array([[4, 5, 6], [1, 2, 3]], dtype=np.uint8).reshape([2, 3, 1]) @@ -1148,7 +1161,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): count_flipped = 0 count_unflipped = 0 for _ in range(100): - y_tf = y.eval() + y_tf = self.evaluate(y) if y_tf[0][0] == 1: self.assertAllEqual(y_tf, x_np) count_unflipped += 1 @@ -1163,6 +1176,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): self.assertGreaterEqual(count_flipped, 20) self.assertGreaterEqual(count_unflipped, 20) + @test_util.run_deprecated_v1 def testRandomFlipUpDownWithBatch(self): batch_size = 16 seed = 42 @@ -1187,7 +1201,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): count_flipped = 0 count_unflipped = 0 for _ in range(100): - y_tf = y.eval() + y_tf = self.evaluate(y) # check every element of the batch for i in range(batch_size): @@ -1213,7 +1227,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.transpose_image(image_ops.transpose_image(x_tf)) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, x_np) def testInvolutionTransposeWithBatch(self): @@ -1224,9 +1238,10 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.transpose_image(image_ops.transpose_image(x_tf)) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, x_np) + @test_util.run_deprecated_v1 def testTranspose(self): x_np = np.array([[1, 2, 3], [4, 5, 6]], dtype=np.uint8).reshape([2, 3, 1]) y_np = np.array([[1, 4], [2, 5], [3, 6]], dtype=np.uint8).reshape([3, 2, 1]) @@ -1234,8 +1249,8 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.transpose_image(x_tf) - self.assertTrue(y.op.name.startswith("transpose_image")) - y_tf = y.eval() + self.assertTrue(y.op.name.startswith("transpose")) + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) def testTransposeWithBatch(self): @@ -1250,9 +1265,10 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.transpose_image(x_tf) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) + @test_util.run_deprecated_v1 def testPartialShapes(self): p_unknown_rank = array_ops.placeholder(dtypes.uint8) p_unknown_dims_3 = array_ops.placeholder( @@ -1301,7 +1317,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): rotated = image for _ in xrange(4): rotated = image_ops.rot90(rotated) - self.assertAllEqual(image, rotated.eval()) + self.assertAllEqual(image, self.evaluate(rotated)) def testRot90GroupOrderWithBatch(self): image = np.arange(48, dtype=np.uint8).reshape([2, 2, 4, 3]) @@ -1309,8 +1325,9 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): rotated = image for _ in xrange(4): rotated = image_ops.rot90(rotated) - self.assertAllEqual(image, rotated.eval()) + self.assertAllEqual(image, self.evaluate(rotated)) + @test_util.run_deprecated_v1 def testRot90NumpyEquivalence(self): image = np.arange(24, dtype=np.uint8).reshape([2, 4, 3]) with self.test_session(use_gpu=True): @@ -1320,6 +1337,7 @@ class FlipTransposeRotateTest(test_util.TensorFlowTestCase): y_np = np.rot90(image, k=k) self.assertAllEqual(y_np, y_tf.eval({k_placeholder: k})) + @test_util.run_deprecated_v1 def testRot90NumpyEquivalenceWithBatch(self): image = np.arange(48, dtype=np.uint8).reshape([2, 2, 4, 3]) with self.test_session(use_gpu=True): @@ -1335,7 +1353,7 @@ class AdjustContrastTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.adjust_contrast(x, contrast_factor) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllClose(y_tf, y_np, 1e-6) def testDoubleContrastUint8(self): @@ -1390,7 +1408,7 @@ class AdjustContrastTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np) y = image_ops.adjust_contrast(x, contrast_factor) - y_tf = y.eval() + y_tf = self.evaluate(y) return y_tf def testRandomContrast(self): @@ -1408,6 +1426,7 @@ class AdjustContrastTest(test_util.TensorFlowTestCase): y_tf = self._adjustContrastTf(x_np, contrast_factor) self.assertAllClose(y_tf, y_np, rtol=1e-5, atol=1e-5) + @test_util.run_deprecated_v1 def testContrastFactorShape(self): x_shape = [1, 2, 2, 3] x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] @@ -1423,7 +1442,7 @@ class AdjustBrightnessTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_np.shape) y = image_ops.adjust_brightness(x, delta) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllClose(y_tf, y_np, 1e-6) def testPositiveDeltaUint8(self): @@ -1471,6 +1490,7 @@ class PerImageWhiteningTest(test_util.TensorFlowTestCase): y /= stddev return y + @test_util.run_deprecated_v1 def testBasic(self): x_shape = [13, 9, 3] x_np = np.arange(0, np.prod(x_shape), dtype=np.int32).reshape(x_shape) @@ -1480,7 +1500,7 @@ class PerImageWhiteningTest(test_util.TensorFlowTestCase): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.per_image_standardization(x) self.assertTrue(y.op.name.startswith("per_image_standardization")) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllClose(y_tf, y_np, atol=1e-4) def testUniformImage(self): @@ -1488,7 +1508,7 @@ class PerImageWhiteningTest(test_util.TensorFlowTestCase): im = constant_op.constant(im_np) whiten = image_ops.per_image_standardization(im) with self.test_session(use_gpu=True): - whiten_np = whiten.eval() + whiten_np = self.evaluate(whiten) self.assertFalse(np.any(np.isnan(whiten_np))) def testBatchWhitening(self): @@ -1497,7 +1517,7 @@ class PerImageWhiteningTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): imgs = constant_op.constant(imgs_np) whiten = image_ops.per_image_standardization(imgs) - whiten_tf = whiten.eval() + whiten_tf = self.evaluate(whiten) for w_tf, w_np in zip(whiten_tf, whiten_np): self.assertAllClose(w_tf, w_np, atol=1e-4) @@ -1571,11 +1591,13 @@ class CropToBoundingBoxTest(test_util.TensorFlowTestCase): y = image_ops.crop_to_bounding_box(image, 0, 0, height, width) self.assertEqual(y.get_shape().as_list(), post_shape) + @test_util.run_deprecated_v1 def testNoOp(self): x_shape = [10, 10, 10] x = np.random.uniform(size=x_shape) self._assertReturns(x, x_shape, 0, 0, x, x_shape) + @test_util.run_deprecated_v1 def testCrop(self): x = [1, 2, 3, 4, 5, 6, 7, 8, 9] x_shape = [3, 3, 1] @@ -1600,6 +1622,7 @@ class CropToBoundingBoxTest(test_util.TensorFlowTestCase): y = [1, 2, 4, 5, 7, 8] self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) + @test_util.run_deprecated_v1 def testShapeInference(self): self._assertShapeInference([55, 66, 3], 55, 66, [55, 66, 3]) self._assertShapeInference([59, 69, 3], 55, 66, [55, 66, 3]) @@ -1613,6 +1636,7 @@ class CropToBoundingBoxTest(test_util.TensorFlowTestCase): self._assertShapeInference([None, None, None], 55, 66, [55, 66, None]) self._assertShapeInference(None, 55, 66, [55, 66, None]) + @test_util.run_deprecated_v1 def testNon3DInput(self): # Input image is not 3D x = [0] * 15 @@ -1624,6 +1648,7 @@ class CropToBoundingBoxTest(test_util.TensorFlowTestCase): target_width, "'image' must have either 3 or 4 dimensions.") + @test_util.run_deprecated_v1 def testZeroLengthInput(self): # Input image has 0-length dimension(s). # Each line is a test configuration: @@ -1655,6 +1680,7 @@ class CropToBoundingBoxTest(test_util.TensorFlowTestCase): "assertion failed:", use_tensor_inputs_options=[True]) + @test_util.run_deprecated_v1 def testBadParams(self): x_shape = [4, 4, 1] x = np.zeros(x_shape) @@ -1672,6 +1698,7 @@ class CropToBoundingBoxTest(test_util.TensorFlowTestCase): for params, err_msg in test_config: self._assertRaises(x, x_shape, *params, err_msg=err_msg) + @test_util.run_deprecated_v1 def testNameScope(self): image = array_ops.placeholder(dtypes.float32, shape=[55, 66, 3]) y = image_ops.crop_to_bounding_box(image, 0, 0, 55, 66) @@ -1688,6 +1715,7 @@ class CentralCropTest(test_util.TensorFlowTestCase): else: self.assertEqual(y.get_shape().as_list(), post_shape) + @test_util.run_deprecated_v1 def testNoOp(self): x_shapes = [[13, 9, 3], [5, 13, 9, 3]] for x_shape in x_shapes: @@ -1696,7 +1724,7 @@ class CentralCropTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=use_gpu): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.central_crop(x, 1.0) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, x_np) self.assertEqual(y.op.name, x.op.name) @@ -1711,7 +1739,7 @@ class CentralCropTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=use_gpu): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.central_crop(x, 0.5) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) self.assertAllEqual(y_tf.shape, y_np.shape) @@ -1727,10 +1755,11 @@ class CentralCropTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): x = constant_op.constant(x_np, shape=x_shape) y = image_ops.central_crop(x, 0.5) - y_tf = y.eval() + y_tf = self.evaluate(y) self.assertAllEqual(y_tf, y_np) self.assertAllEqual(y_tf.shape, y_np.shape) + @test_util.run_deprecated_v1 def testCropping2(self): # Test case for 10315 x_shapes = [[240, 320, 3], [5, 240, 320, 3]] @@ -1747,6 +1776,7 @@ class CentralCropTest(test_util.TensorFlowTestCase): self.assertAllEqual(y_tf, y_np) self.assertAllEqual(y_tf.shape, y_np.shape) + @test_util.run_deprecated_v1 def testShapeInference(self): # Test no-op fraction=1.0, with 3-D tensors. self._assertShapeInference([50, 60, 3], 1.0, [50, 60, 3]) @@ -1807,6 +1837,7 @@ class CentralCropTest(test_util.TensorFlowTestCase): with self.assertRaises(ValueError): _ = image_ops.central_crop(x, 0.5) + @test_util.run_deprecated_v1 def testNameScope(self): x_shape = [13, 9, 3] x_np = np.ones(x_shape, dtype=np.float32) @@ -1897,14 +1928,16 @@ class PadToBoundingBoxTest(test_util.TensorFlowTestCase): i = constant_op.constant([1, 0, 4, 3], dtype=dtypes.int64) y_tf = image_ops.pad_to_bounding_box(x, i[0], i[1], i[2], i[3]) with self.test_session(use_gpu=True): - self.assertAllClose(y, y_tf.eval()) + self.assertAllClose(y, self.evaluate(y_tf)) + @test_util.run_deprecated_v1 def testNoOp(self): x_shape = [10, 10, 10] x = np.random.uniform(size=x_shape) offset_height, offset_width = [0, 0] self._assertReturns(x, x_shape, offset_height, offset_width, x, x_shape) + @test_util.run_deprecated_v1 def testPadding(self): x = [1, 2, 3, 4, 5, 6, 7, 8, 9] x_shape = [3, 3, 1] @@ -1929,6 +1962,7 @@ class PadToBoundingBoxTest(test_util.TensorFlowTestCase): y_shape = [3, 4, 1] self._assertReturns(x, x_shape, offset_height, offset_width, y, y_shape) + @test_util.run_deprecated_v1 def testShapeInference(self): self._assertShapeInference([55, 66, 3], 55, 66, [55, 66, 3]) self._assertShapeInference([50, 60, 3], 55, 66, [55, 66, 3]) @@ -1942,6 +1976,7 @@ class PadToBoundingBoxTest(test_util.TensorFlowTestCase): self._assertShapeInference([None, None, None], 55, 66, [55, 66, None]) self._assertShapeInference(None, 55, 66, [55, 66, None]) + @test_util.run_deprecated_v1 def testNon3DInput(self): # Input image is not 3D x = [0] * 15 @@ -1953,6 +1988,7 @@ class PadToBoundingBoxTest(test_util.TensorFlowTestCase): target_width, "'image' must have either 3 or 4 dimensions.") + @test_util.run_deprecated_v1 def testZeroLengthInput(self): # Input image has 0-length dimension(s). # Each line is a test configuration: @@ -1985,6 +2021,7 @@ class PadToBoundingBoxTest(test_util.TensorFlowTestCase): "all dims of \\'image.shape\\' must be > 0", use_tensor_inputs_options=[True]) + @test_util.run_deprecated_v1 def testBadParams(self): x_shape = [3, 3, 1] x = np.zeros(x_shape) @@ -1999,6 +2036,7 @@ class PadToBoundingBoxTest(test_util.TensorFlowTestCase): for config_item in test_config: self._assertRaises(x, x_shape, *config_item) + @test_util.run_deprecated_v1 def testNameScope(self): image = array_ops.placeholder(dtypes.float32, shape=[55, 66, 3]) y = image_ops.pad_to_bounding_box(image, 0, 0, 55, 66) @@ -2040,7 +2078,7 @@ class SelectDistortedCropBoxTest(test_util.TensorFlowTestCase): y = array_ops.strided_slice(image_tf, begin, begin + size) for _ in xrange(num_iter): - y_tf = y.eval() + y_tf = self.evaluate(y) crop_height = y_tf.shape[0] crop_width = y_tf.shape[1] aspect_ratio = float(crop_width) / float(crop_height) @@ -2106,6 +2144,7 @@ class SelectDistortedCropBoxTest(test_util.TensorFlowTestCase): # TODO(wicke, shlens, dga): Restore this test so that it is no longer flaky. # self.assertGreaterEqual(min(fraction_object_covered), min_object_covered) + @test_util.run_deprecated_v1 def testWholeImageBoundingBox(self): height = 40 width = 50 @@ -2120,6 +2159,7 @@ class SelectDistortedCropBoxTest(test_util.TensorFlowTestCase): aspect_ratio_range=(0.75, 1.33), area_range=(0.05, 1.0)) + @test_util.run_deprecated_v1 def testWithBoundingBox(self): height = 40 width = 50 @@ -2150,6 +2190,7 @@ class SelectDistortedCropBoxTest(test_util.TensorFlowTestCase): aspect_ratio_range=(0.75, 1.33), area_range=(0.05, 1.0)) + @test_util.run_deprecated_v1 def testSampleDistortedBoundingBoxShape(self): with self.test_session(use_gpu=True): image_size = constant_op.constant( @@ -2171,9 +2212,9 @@ class SelectDistortedCropBoxTest(test_util.TensorFlowTestCase): self.assertAllEqual([3], end.get_shape().as_list()) self.assertAllEqual([1, 1, 4], bbox_for_drawing.get_shape().as_list()) # Actual run to make sure shape is correct inside Compute(). - begin = begin.eval() - end = end.eval() - bbox_for_drawing = bbox_for_drawing.eval() + begin = self.evaluate(begin) + end = self.evaluate(end) + bbox_for_drawing = self.evaluate(bbox_for_drawing) begin, end, bbox_for_drawing = image_ops.sample_distorted_bounding_box( image_size=image_size, @@ -2207,9 +2248,9 @@ class SelectDistortedCropBoxTest(test_util.TensorFlowTestCase): self.assertAllEqual([3], end.get_shape().as_list()) self.assertAllEqual([1, 1, 4], bbox_for_drawing.get_shape().as_list()) # Actual run to make sure shape is correct inside Compute(). - begin = begin.eval() - end = end.eval() - bbox_for_drawing = bbox_for_drawing.eval() + begin = self.evaluate(begin) + end = self.evaluate(end) + bbox_for_drawing = self.evaluate(bbox_for_drawing) class ResizeImagesTest(test_util.TensorFlowTestCase): @@ -2245,6 +2286,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): else: return False + @test_util.run_deprecated_v1 def testNoOp(self): img_shape = [1, 6, 4, 1] single_shape = [6, 4, 1] @@ -2265,7 +2307,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): image = constant_op.constant(img_np, shape=img_shape) y = image_ops.resize_images(image, [target_height, target_width], opt) yshape = array_ops.shape(y) - resized, newshape = sess.run([y, yshape]) + resized, newshape = self.evaluate([y, yshape]) self.assertAllEqual(img_shape, newshape) self.assertAllClose(resized, img_np, atol=1e-5) @@ -2276,9 +2318,10 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): y = image_ops.resize_images(image, [target_height, target_width], self.OPTIONS[0]) yshape = array_ops.shape(y) - newshape = yshape.eval() + newshape = self.evaluate(yshape) self.assertAllEqual(single_shape, newshape) + @test_util.run_deprecated_v1 def testTensorArguments(self): img_shape = [1, 6, 4, 1] single_shape = [6, 4, 1] @@ -2340,6 +2383,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): _ = image_ops.resize_images(image, [6, None], image_ops.ResizeMethod.BILINEAR) + @test_util.run_deprecated_v1 def testReturnDtype(self): target_shapes = [[6, 4], [3, 2], [ array_ops.placeholder(dtypes.int32), @@ -2379,7 +2423,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): image = constant_op.constant(img_np, shape=img_shape) y = image_ops.resize_images(image, [height, width], opt) yshape = array_ops.shape(y) - resized, newshape = sess.run([y, yshape]) + resized, newshape = self.evaluate([y, yshape]) self.assertAllEqual(img_shape, newshape) self.assertAllClose(resized, img_np, atol=1e-5) @@ -2411,7 +2455,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): y = image_ops.resize_images(image, [target_height, target_width], opt) expected = np.array(expected_data).reshape(target_shape) - resized = y.eval() + resized = self.evaluate(y) self.assertAllClose(resized, expected, atol=1e-5) def testResizeUpAlignCornersFalse(self): @@ -2446,7 +2490,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): image = constant_op.constant(img_np, shape=img_shape) y = image_ops.resize_images( image, [target_height, target_width], opt, align_corners=False) - resized = y.eval() + resized = self.evaluate(y) expected = np.array(expected_data[opt]).reshape( [1, target_height, target_width, 1]) self.assertAllClose(resized, expected, atol=1e-05) @@ -2482,7 +2526,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): image = constant_op.constant(img_np, shape=img_shape) y = image_ops.resize_images( image, [target_height, target_width], opt, align_corners=True) - resized = y.eval() + resized = self.evaluate(y) expected = np.array(expected_data[opt]).reshape( [1, target_height, target_width, 1]) self.assertAllClose(resized, expected, atol=1e-05) @@ -2509,7 +2553,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): image = constant_op.constant(img_np, shape=img_shape) y = image_ops.resize_images(image, [target_height, target_width], image_ops.ResizeMethod.BICUBIC) - resized = y.eval() + resized = self.evaluate(y) expected = np.array(expected_data).reshape( [1, target_height, target_width, 1]) self.assertAllClose(resized, expected, atol=1) @@ -2534,7 +2578,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): image_ops.ResizeMethod.AREA) expected = np.array(expected_data).reshape( [1, target_height, target_width, 1]) - resized = y.eval() + resized = self.evaluate(y) self.assertAllClose(resized, expected, atol=1) def testCompareNearestNeighbor(self): @@ -2554,7 +2598,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): new_size, image_ops.ResizeMethod.NEAREST_NEIGHBOR, align_corners=align_corners) - gpu_val = out_op.eval() + gpu_val = self.evaluate(out_op) with self.test_session(use_gpu=False): image = constant_op.constant(img_np, shape=input_shape) new_size = constant_op.constant([target_height, target_width]) @@ -2563,7 +2607,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): new_size, image_ops.ResizeMethod.NEAREST_NEIGHBOR, align_corners=align_corners) - cpu_val = out_op.eval() + cpu_val = self.evaluate(out_op) self.assertAllClose(cpu_val, gpu_val, rtol=1e-5, atol=1e-5) def testCompareBilinear(self): @@ -2585,9 +2629,10 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): new_size, image_ops.ResizeMethod.BILINEAR, align_corners=align_corners) - value[use_gpu] = out_op.eval() + value[use_gpu] = self.evaluate(out_op) self.assertAllClose(value[True], value[False], rtol=1e-5, atol=1e-5) + @test_util.run_deprecated_v1 def testShapeInference(self): self._assertShapeInference([50, 60, 3], [55, 66], [55, 66, 3]) self._assertShapeInference([55, 66, 3], [55, 66], [55, 66, 3]) @@ -2608,12 +2653,13 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): self._assertShapeInference([59, 60, None], [55, 66], [55, 66, None]) self._assertShapeInference([None, None, None], [55, 66], [55, 66, None]) + @test_util.run_deprecated_v1 def testNameScope(self): img_shape = [1, 3, 2, 1] with self.test_session(use_gpu=True): single_image = array_ops.placeholder(dtypes.float32, shape=[50, 60, 3]) y = image_ops.resize_images(single_image, [55, 66]) - self.assertTrue(y.op.name.startswith("resize_images")) + self.assertTrue(y.op.name.startswith("resize")) def _ResizeImageCall(self, x, max_h, max_w, preserve_aspect_ratio, use_tensor_inputs): @@ -2658,6 +2704,7 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): preserve_aspect_ratio, use_tensor_inputs) self.assertShapeEqual(y, ops.convert_to_tensor(y_tf)) + @test_util.run_deprecated_v1 def testPreserveAspectRatioMultipleImages(self): x_shape = [10, 100, 100, 10] x = np.random.uniform(size=x_shape) @@ -2665,36 +2712,42 @@ class ResizeImagesTest(test_util.TensorFlowTestCase): self._assertResizeCheckShape(x, x_shape, [250, 250], [10, 250, 250, 10], preserve_aspect_ratio=False) + @test_util.run_deprecated_v1 def testPreserveAspectRatioNoOp(self): x_shape = [10, 10, 10] x = np.random.uniform(size=x_shape) self._assertResizeEqual(x, x_shape, x, x_shape) + @test_util.run_deprecated_v1 def testPreserveAspectRatioSmaller(self): x_shape = [100, 100, 10] x = np.random.uniform(size=x_shape) self._assertResizeCheckShape(x, x_shape, [75, 50], [50, 50, 10]) + @test_util.run_deprecated_v1 def testPreserveAspectRatioSmallerMultipleImages(self): x_shape = [10, 100, 100, 10] x = np.random.uniform(size=x_shape) self._assertResizeCheckShape(x, x_shape, [75, 50], [10, 50, 50, 10]) + @test_util.run_deprecated_v1 def testPreserveAspectRatioLarger(self): x_shape = [100, 100, 10] x = np.random.uniform(size=x_shape) self._assertResizeCheckShape(x, x_shape, [150, 200], [150, 150, 10]) + @test_util.run_deprecated_v1 def testPreserveAspectRatioSameRatio(self): x_shape = [1920, 1080, 3] x = np.random.uniform(size=x_shape) self._assertResizeCheckShape(x, x_shape, [3840, 2160], [3840, 2160, 3]) + @test_util.run_deprecated_v1 def testPreserveAspectRatioSquare(self): x_shape = [299, 299, 3] x = np.random.uniform(size=x_shape) @@ -2764,12 +2817,14 @@ class ResizeImageWithPadTest(test_util.TensorFlowTestCase): y = image_ops.resize_image_with_pad(image, height, width) self.assertEqual(y.get_shape().as_list(), post_shape) + @test_util.run_deprecated_v1 def testNoOp(self): x_shape = [10, 10, 10] x = np.random.uniform(size=x_shape) self._assertReturns(x, x_shape, x, x_shape) + @test_util.run_deprecated_v1 def testPad(self): # Reduce vertical dimension x = [1, 2, 3, 4, 5, 6, 7, 8] @@ -2860,12 +2915,14 @@ class ResizeImageWithCropOrPadTest(test_util.TensorFlowTestCase): y = image_ops.resize_image_with_crop_or_pad(image, height, width) self.assertEqual(y.get_shape().as_list(), post_shape) + @test_util.run_deprecated_v1 def testNoOp(self): x_shape = [10, 10, 10] x = np.random.uniform(size=x_shape) self._assertReturns(x, x_shape, x, x_shape) + @test_util.run_deprecated_v1 def testPad(self): # Pad even along col. x = [1, 2, 3, 4, 5, 6, 7, 8] @@ -2903,6 +2960,7 @@ class ResizeImageWithCropOrPadTest(test_util.TensorFlowTestCase): self._assertReturns(x, x_shape, y, y_shape) + @test_util.run_deprecated_v1 def testCrop(self): # Crop even along col. x = [1, 2, 3, 4, 5, 6, 7, 8] @@ -2940,6 +2998,7 @@ class ResizeImageWithCropOrPadTest(test_util.TensorFlowTestCase): self._assertReturns(x, x_shape, y, y_shape) + @test_util.run_deprecated_v1 def testCropAndPad(self): # Pad along row but crop along col. x = [1, 2, 3, 4, 5, 6, 7, 8] @@ -2959,6 +3018,7 @@ class ResizeImageWithCropOrPadTest(test_util.TensorFlowTestCase): self._assertReturns(x, x_shape, y, y_shape) + @test_util.run_deprecated_v1 def testShapeInference(self): self._assertShapeInference([50, 60, 3], 55, 66, [55, 66, 3]) self._assertShapeInference([55, 66, 3], 55, 66, [55, 66, 3]) @@ -2980,6 +3040,7 @@ class ResizeImageWithCropOrPadTest(test_util.TensorFlowTestCase): self._assertShapeInference([None, None, None], 55, 66, [55, 66, None]) self._assertShapeInference(None, 55, 66, [55, 66, None]) + @test_util.run_deprecated_v1 def testNon3DInput(self): # Input image is not 3D x = [0] * 15 @@ -2993,6 +3054,7 @@ class ResizeImageWithCropOrPadTest(test_util.TensorFlowTestCase): self._assertRaises(x, x_shape, target_height, target_width, "'image' must have either 3 or 4 dimensions.") + @test_util.run_deprecated_v1 def testZeroLengthInput(self): # Input image has 0-length dimension(s). target_height, target_width = [1, 1] @@ -3018,6 +3080,7 @@ class ResizeImageWithCropOrPadTest(test_util.TensorFlowTestCase): "all dims of \\'image.shape\\' must be > 0", use_tensor_inputs_options=[True]) + @test_util.run_deprecated_v1 def testBadParams(self): x_shape = [4, 4, 1] x = np.zeros(x_shape) @@ -3032,6 +3095,7 @@ class ResizeImageWithCropOrPadTest(test_util.TensorFlowTestCase): self._assertRaises(x, x_shape, target_height, target_width, "target_width must be > 0") + @test_util.run_deprecated_v1 def testNameScope(self): image = array_ops.placeholder(dtypes.float32, shape=[50, 60, 3]) y = image_ops.resize_image_with_crop_or_pad(image, 55, 66) @@ -3066,7 +3130,7 @@ class JpegTest(test_util.TensorFlowTestCase): jpeg0 = io_ops.read_file(path) image0 = image_ops.decode_jpeg(jpeg0) image1 = image_ops.decode_jpeg(image_ops.encode_jpeg(image0)) - jpeg0, image0, image1 = sess.run([jpeg0, image0, image1]) + jpeg0, image0, image1 = self.evaluate([jpeg0, image0, image1]) self.assertEqual(len(jpeg0), 3771) self.assertEqual(image0.shape, (256, 128, 3)) self.assertLess(self.averageError(image0, image1), 1.4) @@ -3083,7 +3147,7 @@ class JpegTest(test_util.TensorFlowTestCase): io_ops.read_file(rgb_path), channels=channels) cmyk = image_ops.decode_jpeg( io_ops.read_file(cmyk_path), channels=channels) - rgb, cmyk = sess.run([rgb, cmyk]) + rgb, cmyk = self.evaluate([rgb, cmyk]) self.assertEqual(rgb.shape, shape) self.assertEqual(cmyk.shape, shape) error = self.averageError(rgb, cmyk) @@ -3112,9 +3176,10 @@ class JpegTest(test_util.TensorFlowTestCase): image2.get_shape().as_list()) # CropAndDecode should be equal to DecodeJpeg+Crop. - image1_crop, image2 = sess.run([image1_crop, image2]) + image1_crop, image2 = self.evaluate([image1_crop, image2]) self.assertAllEqual(image1_crop, image2) + @test_util.run_deprecated_v1 def testCropAndDecodeJpegWithInvalidCropWindow(self): with self.cached_session() as sess: # Encode it, then decode it, then encode it @@ -3131,7 +3196,7 @@ class JpegTest(test_util.TensorFlowTestCase): with self.assertRaisesWithPredicateMatch( errors.InvalidArgumentError, lambda e: "Invalid JPEG data or crop window" in str(e)): - sess.run(result) + self.evaluate(result) def testSynthetic(self): with self.test_session(use_gpu=True) as sess: @@ -3141,7 +3206,8 @@ class JpegTest(test_util.TensorFlowTestCase): image1 = image_ops.decode_jpeg(jpeg0, dct_method="INTEGER_ACCURATE") image2 = image_ops.decode_jpeg( image_ops.encode_jpeg(image1), dct_method="INTEGER_ACCURATE") - jpeg0, image0, image1, image2 = sess.run([jpeg0, image0, image1, image2]) + jpeg0, image0, image1, image2 = self.evaluate( + [jpeg0, image0, image1, image2]) # The decoded-encoded image should be similar to the input self.assertLess(self.averageError(image0, image1), 0.6) @@ -3161,7 +3227,8 @@ class JpegTest(test_util.TensorFlowTestCase): image1 = image_ops.decode_jpeg(jpeg0, dct_method="INTEGER_FAST") image2 = image_ops.decode_jpeg( image_ops.encode_jpeg(image1), dct_method="INTEGER_FAST") - jpeg0, image0, image1, image2 = sess.run([jpeg0, image0, image1, image2]) + jpeg0, image0, image1, image2 = self.evaluate( + [jpeg0, image0, image1, image2]) # The decoded-encoded image should be similar to the input, but # note this is worse than the slower algorithm because it is @@ -3184,11 +3251,12 @@ class JpegTest(test_util.TensorFlowTestCase): jpeg0 = image_ops.encode_jpeg(image0) image1 = image_ops.decode_jpeg(jpeg0, dct_method="INTEGER_FAST") image2 = image_ops.decode_jpeg(jpeg0) - image1, image2 = sess.run([image1, image2]) + image1, image2 = self.evaluate([image1, image2]) # The images should be the same. self.assertAllClose(image1, image2) + @test_util.run_deprecated_v1 def testShape(self): with self.test_session(use_gpu=True) as sess: jpeg = constant_op.constant("nonsense") @@ -3197,6 +3265,7 @@ class JpegTest(test_util.TensorFlowTestCase): self.assertEqual(image.get_shape().as_list(), [None, None, channels or None]) + @test_util.run_deprecated_v1 def testExtractJpegShape(self): # Read a real jpeg and verify shape. path = ("tensorflow/core/lib/jpeg/testdata/" @@ -3207,6 +3276,7 @@ class JpegTest(test_util.TensorFlowTestCase): [image_shape] = sess.run([image_ops.extract_jpeg_shape(jpeg)]) self.assertEqual(image_shape.tolist(), [256, 128, 3]) + @test_util.run_deprecated_v1 def testExtractJpegShapeforCmyk(self): # Read a cmyk jpeg image, and verify its shape. path = ("tensorflow/core/lib/jpeg/testdata/" @@ -3230,11 +3300,11 @@ class PngTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True) as sess: png0 = io_ops.read_file(prefix + filename) image0 = image_ops.decode_png(png0, channels=channels) - png0, image0 = sess.run([png0, image0]) + png0, image0 = self.evaluate([png0, image0]) self.assertEqual(image0.shape, (26, 51, channels or channels_in)) if channels == channels_in: image1 = image_ops.decode_png(image_ops.encode_png(image0)) - self.assertAllEqual(image0, image1.eval()) + self.assertAllEqual(image0, self.evaluate(image1)) def testSynthetic(self): with self.test_session(use_gpu=True) as sess: @@ -3242,7 +3312,7 @@ class PngTest(test_util.TensorFlowTestCase): image0 = constant_op.constant(_SimpleColorRamp()) png0 = image_ops.encode_png(image0, compression=7) image1 = image_ops.decode_png(png0) - png0, image0, image1 = sess.run([png0, image0, image1]) + png0, image0, image1 = self.evaluate([png0, image0, image1]) # PNG is lossless self.assertAllEqual(image0, image1) @@ -3257,7 +3327,7 @@ class PngTest(test_util.TensorFlowTestCase): image0 = constant_op.constant(_SimpleColorRamp(), dtype=dtypes.uint16) png0 = image_ops.encode_png(image0, compression=7) image1 = image_ops.decode_png(png0, dtype=dtypes.uint16) - png0, image0, image1 = sess.run([png0, image0, image1]) + png0, image0, image1 = self.evaluate([png0, image0, image1]) # PNG is lossless self.assertAllEqual(image0, image1) @@ -3273,7 +3343,7 @@ class PngTest(test_util.TensorFlowTestCase): image0 = constant_op.constant(gray_alpha) png0 = image_ops.encode_png(image0, compression=7) image1 = image_ops.decode_png(png0) - png0, image0, image1 = sess.run([png0, image0, image1]) + png0, image0, image1 = self.evaluate([png0, image0, image1]) self.assertEqual(2, image0.shape[-1]) self.assertAllEqual(image0, image1) @@ -3284,10 +3354,11 @@ class PngTest(test_util.TensorFlowTestCase): image0 = constant_op.constant(gray_alpha, dtype=dtypes.uint16) png0 = image_ops.encode_png(image0, compression=7) image1 = image_ops.decode_png(png0, dtype=dtypes.uint16) - png0, image0, image1 = sess.run([png0, image0, image1]) + png0, image0, image1 = self.evaluate([png0, image0, image1]) self.assertEqual(2, image0.shape[-1]) self.assertAllEqual(image0, image1) + @test_util.run_deprecated_v1 def testShape(self): with self.test_session(use_gpu=True): png = constant_op.constant("nonsense") @@ -3310,7 +3381,7 @@ class GifTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True) as sess: gif0 = io_ops.read_file(prefix + filename) image0 = image_ops.decode_gif(gif0) - gif0, image0 = sess.run([gif0, image0]) + gif0, image0 = self.evaluate([gif0, image0]) self.assertEqual(image0.shape, shape) @@ -3332,6 +3403,7 @@ class GifTest(test_util.TensorFlowTestCase): self._testValid("scan.gif") self._testValid("optimized.gif") + @test_util.run_deprecated_v1 def testShape(self): with self.test_session(use_gpu=True) as sess: gif = constant_op.constant("nonsense") @@ -3358,6 +3430,7 @@ class ConvertImageTest(test_util.TensorFlowTestCase): self.assertTrue(y_saturate.dtype == output_dtype) self.assertAllClose(y_saturate.eval(), y_np, atol=1e-5) + @test_util.run_deprecated_v1 def testNoConvert(self): # Make sure converting to the same data type creates only an identity op with self.test_session(use_gpu=True): @@ -3367,6 +3440,7 @@ class ConvertImageTest(test_util.TensorFlowTestCase): self.assertEquals(y.op.type, "Identity") self.assertEquals(y.op.inputs[0], image) + @test_util.run_deprecated_v1 def testConvertBetweenInteger(self): # Make sure converting to between integer types scales appropriately with self.test_session(use_gpu=True): @@ -3375,6 +3449,7 @@ class ConvertImageTest(test_util.TensorFlowTestCase): self._convert([0, 2**32], dtypes.int64, dtypes.int32, [0, 1]) self._convert([0, 1], dtypes.int32, dtypes.int64, [0, 2**32]) + @test_util.run_deprecated_v1 def testConvertBetweenFloat(self): # Make sure converting to between float types does nothing interesting with self.test_session(use_gpu=True): @@ -3383,6 +3458,7 @@ class ConvertImageTest(test_util.TensorFlowTestCase): self._convert([-1.0, 0, 1.0, 200000], dtypes.float64, dtypes.float32, [-1.0, 0, 1.0, 200000]) + @test_util.run_deprecated_v1 def testConvertBetweenIntegerAndFloat(self): # Make sure converting from and to a float type scales appropriately with self.test_session(use_gpu=True): @@ -3391,6 +3467,7 @@ class ConvertImageTest(test_util.TensorFlowTestCase): self._convert([0, 1.1 / 255.0, 1], dtypes.float32, dtypes.uint8, [0, 1, 255]) + @test_util.run_deprecated_v1 def testConvertBetweenInt16AndInt8(self): with self.test_session(use_gpu=True): # uint8, uint16 @@ -3431,7 +3508,7 @@ class TotalVariationTest(test_util.TensorFlowTestCase): y = image_ops.total_variation(images=x_tf) # Run the TensorFlow session to calculate the result. - y_tf = y.eval() + y_tf = self.evaluate(y) # Assert that the results are as expected within # some small error-bound in case they are float-values. @@ -3582,6 +3659,7 @@ class TotalVariationTest(test_util.TensorFlowTestCase): class FormatTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testFormats(self): prefix = "tensorflow/core/lib" paths = ("png/testdata/lena_gray.png", "jpeg/testdata/jpeg_merge_test1.jpg", @@ -3614,6 +3692,7 @@ class FormatTest(test_util.TensorFlowTestCase): class NonMaxSuppressionTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testSelectFromThreeClusters(self): boxes_np = [[0, 0, 1, 1], [0, 0.1, 1, 1.1], [0, -0.1, 1, 0.9], [0, 10, 1, 11], [0, 10.1, 1, 11.1], [0, 100, 1, 101]] @@ -3629,6 +3708,7 @@ class NonMaxSuppressionTest(test_util.TensorFlowTestCase): boxes, scores, max_output_size, iou_threshold).eval() self.assertAllClose(selected_indices, [3, 0, 5]) + @test_util.run_deprecated_v1 def testInvalidShape(self): # The boxes should be 2D of shape [num_boxes, 4]. with self.assertRaisesRegexp(ValueError, @@ -3671,6 +3751,7 @@ class NonMaxSuppressionTest(test_util.TensorFlowTestCase): scores = constant_op.constant([0.9]) image_ops.non_max_suppression(boxes, scores, 3, [[0.5]]) + @test_util.run_deprecated_v1 def testDataTypes(self): # Test case for GitHub issue 20199. boxes_np = [[0, 0, 1, 1], [0, 0.1, 1, 1.1], [0, -0.1, 1, 0.9], @@ -3709,12 +3790,13 @@ class NonMaxSuppressionTest(test_util.TensorFlowTestCase): iou_threshold = constant_op.constant(iou_threshold_np) selected_indices, _ = gen_image_ops.non_max_suppression_v4( boxes, scores, max_output_size, iou_threshold, score_threshold) - selected_indices = selected_indices.eval() + selected_indices = self.evaluate(selected_indices) self.assertAllClose(selected_indices, [3, 0, 5]) class NonMaxSuppressionPaddedTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testSelectFromThreeClusters(self): boxes_np = [[0, 0, 1, 1], [0, 0.1, 1, 1.1], [0, -0.1, 1, 0.9], [0, 10, 1, 11], [0, 10.1, 1, 11.1], [0, 100, 1, 101]] @@ -3747,6 +3829,7 @@ class NonMaxSuppressionPaddedTest(test_util.TensorFlowTestCase): self.assertAllClose(selected_indices.eval(), [3, 0, 5]) self.assertEqual(num_valid.eval(), 3) + @test_util.run_deprecated_v1 def testSelectFromContinuousOverLap(self): boxes_np = [[0, 0, 1, 1], [0, 0.2, 1, 1.2], [0, 0.4, 1, 1.4], [0, 0.6, 1, 1.6], [0, 0.8, 1, 1.8], [0, 2, 1, 2]] @@ -3774,6 +3857,7 @@ class NonMaxSuppressionPaddedTest(test_util.TensorFlowTestCase): class NonMaxSuppressionWithOverlapsTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testSelectOneFromThree(self): overlaps_np = [ [1.0, 0.7, 0.2], @@ -3799,6 +3883,7 @@ class NonMaxSuppressionWithOverlapsTest(test_util.TensorFlowTestCase): class VerifyCompatibleImageShapesTest(test_util.TensorFlowTestCase): """Tests utility function used by ssim() and psnr().""" + @test_util.run_deprecated_v1 def testWrongDims(self): img = array_ops.placeholder(dtype=dtypes.float32) img_np = np.array((2, 2)) @@ -3808,6 +3893,7 @@ class VerifyCompatibleImageShapesTest(test_util.TensorFlowTestCase): with self.assertRaises(errors.InvalidArgumentError): sess.run(checks, {img: img_np}) + @test_util.run_deprecated_v1 def testShapeMismatch(self): img1 = array_ops.placeholder(dtype=dtypes.float32) img2 = array_ops.placeholder(dtype=dtypes.float32) @@ -3829,7 +3915,7 @@ class PSNRTest(test_util.TensorFlowTestCase): "tensorflow/core/lib/psnr/testdata", filename)) im = image_ops.decode_jpeg(content, dct_method="INTEGER_ACCURATE") im = image_ops.convert_image_dtype(im, dtypes.float32) - im, = sess.run([im]) + im, = self.evaluate([im]) return np.expand_dims(im, axis=0) def _LoadTestImages(self): @@ -3848,6 +3934,7 @@ class PSNRTest(test_util.TensorFlowTestCase): """Returns an image or image batch with given shape.""" return np.random.rand(*shape).astype(np.float32) * max_val + @test_util.run_deprecated_v1 def testPSNRSingleImage(self): image1 = self._RandomImage((8, 8, 1), 1) image2 = self._RandomImage((8, 8, 1), 1) @@ -3861,6 +3948,7 @@ class PSNRTest(test_util.TensorFlowTestCase): tf_psnr = image_ops.psnr(tf_image1, tf_image2, 1.0, "psnr").eval() self.assertAllClose(psnr, tf_psnr, atol=0.001) + @test_util.run_deprecated_v1 def testPSNRMultiImage(self): image1 = self._RandomImage((10, 8, 8, 1), 1) image2 = self._RandomImage((10, 8, 8, 1), 1) @@ -3874,6 +3962,7 @@ class PSNRTest(test_util.TensorFlowTestCase): tf_psnr = image_ops.psnr(tf_image1, tf_image2, 1, "psnr").eval() self.assertAllClose(psnr, tf_psnr, atol=0.001) + @test_util.run_deprecated_v1 def testGoldenPSNR(self): q20, q72, q95 = self._LoadTestImages() @@ -3898,6 +3987,7 @@ class PSNRTest(test_util.TensorFlowTestCase): self.assertAllClose(psnr2, tf_psnr2, atol=0.001) self.assertAllClose(psnr3, tf_psnr3, atol=0.001) + @test_util.run_deprecated_v1 def testInfinity(self): q20, _, _ = self._LoadTestImages() psnr = self._PSNR_NumPy(q20, q20, 1) @@ -3906,6 +3996,7 @@ class PSNRTest(test_util.TensorFlowTestCase): tf_psnr = image_ops.psnr(tf_q20, tf_q20, 1, "psnr").eval() self.assertAllClose(psnr, tf_psnr, atol=0.001) + @test_util.run_deprecated_v1 def testInt(self): img1 = self._RandomImage((10, 8, 8, 1), 255) img2 = self._RandomImage((10, 8, 8, 1), 255) @@ -3916,7 +4007,8 @@ class PSNRTest(test_util.TensorFlowTestCase): img2 = image_ops.convert_image_dtype(img2, dtypes.float32) psnr_float32 = image_ops.psnr(img1, img2, 1.0) with self.test_session(use_gpu=True): - self.assertAllClose(psnr_uint8.eval(), psnr_float32.eval(), atol=0.001) + self.assertAllClose( + psnr_uint8.eval(), self.evaluate(psnr_float32), atol=0.001) class SSIMTest(test_util.TensorFlowTestCase): @@ -3935,7 +4027,7 @@ class SSIMTest(test_util.TensorFlowTestCase): "tensorflow/core/lib/ssim/testdata", filename)) im = image_ops.decode_png(content) im = image_ops.convert_image_dtype(im, dtypes.float32) - im, = sess.run([im]) + im, = self.evaluate([im]) return np.expand_dims(im, axis=0) def _LoadTestImages(self): @@ -3946,6 +4038,7 @@ class SSIMTest(test_util.TensorFlowTestCase): """Returns an image or image batch with given shape.""" return np.random.rand(*shape).astype(np.float32) * max_val + @test_util.run_deprecated_v1 def testAgainstMatlab(self): """Tests against values produced by Matlab.""" img = self._LoadTestImages() @@ -3969,7 +4062,7 @@ class SSIMTest(test_util.TensorFlowTestCase): ssim = image_ops.ssim(constant_op.constant(img1), constant_op.constant(img2), 1.0) with self.test_session(use_gpu=True): - self.assertAllClose(expected, ssim.eval(), atol=1e-4) + self.assertAllClose(expected, self.evaluate(ssim), atol=1e-4) def testBroadcast(self): img = self._LoadTestImages()[:2] @@ -3981,8 +4074,9 @@ class SSIMTest(test_util.TensorFlowTestCase): ssim = image_ops.ssim(img1, img2, 1.0) with self.test_session(use_gpu=True): - self.assertAllClose(expected, ssim.eval(), atol=1e-4) + self.assertAllClose(expected, self.evaluate(ssim), atol=1e-4) + @test_util.run_deprecated_v1 def testNegative(self): """Tests against negative SSIM index.""" step = np.expand_dims(np.arange(0, 256, 16, dtype=np.uint8), axis=0) @@ -3997,6 +4091,7 @@ class SSIMTest(test_util.TensorFlowTestCase): with self.test_session(use_gpu=True): self.assertLess(ssim.eval(), 0) + @test_util.run_deprecated_v1 def testInt(self): img1 = self._RandomImage((1, 16, 16, 3), 255) img2 = self._RandomImage((1, 16, 16, 3), 255) @@ -4007,7 +4102,8 @@ class SSIMTest(test_util.TensorFlowTestCase): img2 = image_ops.convert_image_dtype(img2, dtypes.float32) ssim_float32 = image_ops.ssim(img1, img2, 1.0) with self.test_session(use_gpu=True): - self.assertAllClose(ssim_uint8.eval(), ssim_float32.eval(), atol=0.001) + self.assertAllClose( + ssim_uint8.eval(), self.evaluate(ssim_float32), atol=0.001) class MultiscaleSSIMTest(test_util.TensorFlowTestCase): @@ -4026,7 +4122,7 @@ class MultiscaleSSIMTest(test_util.TensorFlowTestCase): "tensorflow/core/lib/ssim/testdata", filename)) im = image_ops.decode_png(content) im = image_ops.convert_image_dtype(im, dtypes.float32) - im, = sess.run([im]) + im, = self.evaluate([im]) return np.expand_dims(im, axis=0) def _LoadTestImages(self): @@ -4037,6 +4133,7 @@ class MultiscaleSSIMTest(test_util.TensorFlowTestCase): """Returns an image or image batch with given shape.""" return np.random.rand(*shape).astype(np.float32) * max_val + @test_util.run_deprecated_v1 def testAgainstMatlab(self): """Tests against MS-SSIM computed with Matlab implementation. @@ -4053,6 +4150,7 @@ class MultiscaleSSIMTest(test_util.TensorFlowTestCase): self.assertAllClose(expected, np.squeeze(scores), atol=1e-4) + @test_util.run_deprecated_v1 def testUnweightedIsDifferentiable(self): img = self._LoadTestImages() ph = [array_ops.placeholder(dtype=dtypes.float32) for _ in range(2)] @@ -4077,7 +4175,7 @@ class MultiscaleSSIMTest(test_util.TensorFlowTestCase): msssim = image_ops.ssim_multiscale(constant_op.constant(img1), constant_op.constant(img2), 1.0) with self.test_session(use_gpu=True): - self.assertAllClose(expected, msssim.eval(), 1e-4) + self.assertAllClose(expected, self.evaluate(msssim), 1e-4) def testBroadcast(self): """Tests MS-SSIM broadcasting.""" @@ -4090,7 +4188,7 @@ class MultiscaleSSIMTest(test_util.TensorFlowTestCase): score_tensor = image_ops.ssim_multiscale(img1, img2, 1.0) with self.test_session(use_gpu=True): - self.assertAllClose(expected, score_tensor.eval(), 1e-4) + self.assertAllClose(expected, self.evaluate(score_tensor), 1e-4) def testRange(self): """Tests against low MS-SSIM score. @@ -4108,12 +4206,13 @@ class MultiscaleSSIMTest(test_util.TensorFlowTestCase): images = [ops.convert_to_tensor(x, dtype=dtypes.float32) for x in images] msssim_ops = [image_ops.ssim_multiscale(x, y, 1.0) for x, y in itertools.combinations(images, 2)] - msssim = sess.run(msssim_ops) + msssim = self.evaluate(msssim_ops) msssim = np.squeeze(msssim) self.assertTrue(np.all(msssim >= 0.0)) self.assertTrue(np.all(msssim <= 1.0)) + @test_util.run_deprecated_v1 def testInt(self): img1 = self._RandomImage((1, 180, 240, 3), 255) img2 = self._RandomImage((1, 180, 240, 3), 255) @@ -4124,7 +4223,8 @@ class MultiscaleSSIMTest(test_util.TensorFlowTestCase): img2 = image_ops.convert_image_dtype(img2, dtypes.float32) ssim_float32 = image_ops.ssim_multiscale(img1, img2, 1.0) with self.test_session(use_gpu=True): - self.assertAllClose(ssim_uint8.eval(), ssim_float32.eval(), atol=0.001) + self.assertAllClose( + ssim_uint8.eval(), self.evaluate(ssim_float32), atol=0.001) class ImageGradientsTest(test_util.TensorFlowTestCase): @@ -4139,8 +4239,8 @@ class ImageGradientsTest(test_util.TensorFlowTestCase): dy, dx = image_ops.image_gradients(img) with self.cached_session(): - actual_dy = dy.eval() - actual_dx = dx.eval() + actual_dy = self.evaluate(dy) + actual_dx = self.evaluate(dx) self.assertAllClose(expected_dy, actual_dy) self.assertAllClose(expected_dx, actual_dx) @@ -4164,8 +4264,8 @@ class ImageGradientsTest(test_util.TensorFlowTestCase): assert batch.get_shape().as_list() == [2, 2, 3, 2] dy, dx = image_ops.image_gradients(batch) with self.test_session(use_gpu=True): - actual_dy = dy.eval() - actual_dx = dx.eval() + actual_dy = self.evaluate(dy) + actual_dx = self.evaluate(dx) self.assertAllClose(expected_dy, actual_dy) self.assertAllClose(expected_dx, actual_dx) @@ -4185,7 +4285,7 @@ class SobelEdgesTest(test_util.TensorFlowTestCase): [[0, 0], [0, 12], [0, 0]]], [1, 2, 3, 1, 2]) sobel = image_ops.sobel_edges(img) with self.test_session(use_gpu=True): - actual_sobel = sobel.eval() + actual_sobel = self.evaluate(sobel) self.assertAllClose(expected, actual_sobel) def testSobelEdges5x3x4x2(self): @@ -4207,7 +4307,7 @@ class SobelEdgesTest(test_util.TensorFlowTestCase): sobel = image_ops.sobel_edges(img) with self.test_session(use_gpu=True): - actual_sobel = sobel.eval() + actual_sobel = self.evaluate(sobel) self.assertAllClose(expected_batch, actual_sobel) @@ -4220,7 +4320,7 @@ class DecodeImageTest(test_util.TensorFlowTestCase): image0 = image_ops.decode_image(jpeg0, dtype=dtypes.uint16) image1 = image_ops.convert_image_dtype(image_ops.decode_jpeg(jpeg0), dtypes.uint16) - image0, image1 = sess.run([image0, image1]) + image0, image1 = self.evaluate([image0, image1]) self.assertAllEqual(image0, image1) def testPngUint16(self): @@ -4230,7 +4330,7 @@ class DecodeImageTest(test_util.TensorFlowTestCase): image0 = image_ops.decode_image(png0, dtype=dtypes.uint16) image1 = image_ops.convert_image_dtype( image_ops.decode_png(png0, dtype=dtypes.uint16), dtypes.uint16) - image0, image1 = sess.run([image0, image1]) + image0, image1 = self.evaluate([image0, image1]) self.assertAllEqual(image0, image1) def testGifUint16(self): @@ -4240,7 +4340,7 @@ class DecodeImageTest(test_util.TensorFlowTestCase): image0 = image_ops.decode_image(gif0, dtype=dtypes.uint16) image1 = image_ops.convert_image_dtype(image_ops.decode_gif(gif0), dtypes.uint16) - image0, image1 = sess.run([image0, image1]) + image0, image1 = self.evaluate([image0, image1]) self.assertAllEqual(image0, image1) def testBmpUint16(self): @@ -4250,7 +4350,7 @@ class DecodeImageTest(test_util.TensorFlowTestCase): image0 = image_ops.decode_image(bmp0, dtype=dtypes.uint16) image1 = image_ops.convert_image_dtype(image_ops.decode_bmp(bmp0), dtypes.uint16) - image0, image1 = sess.run([image0, image1]) + image0, image1 = self.evaluate([image0, image1]) self.assertAllEqual(image0, image1) def testJpegFloat32(self): @@ -4260,7 +4360,7 @@ class DecodeImageTest(test_util.TensorFlowTestCase): image0 = image_ops.decode_image(jpeg0, dtype=dtypes.float32) image1 = image_ops.convert_image_dtype(image_ops.decode_jpeg(jpeg0), dtypes.float32) - image0, image1 = sess.run([image0, image1]) + image0, image1 = self.evaluate([image0, image1]) self.assertAllEqual(image0, image1) def testPngFloat32(self): @@ -4270,7 +4370,7 @@ class DecodeImageTest(test_util.TensorFlowTestCase): image0 = image_ops.decode_image(png0, dtype=dtypes.float32) image1 = image_ops.convert_image_dtype( image_ops.decode_png(png0, dtype=dtypes.uint16), dtypes.float32) - image0, image1 = sess.run([image0, image1]) + image0, image1 = self.evaluate([image0, image1]) self.assertAllEqual(image0, image1) def testGifFloat32(self): @@ -4280,7 +4380,7 @@ class DecodeImageTest(test_util.TensorFlowTestCase): image0 = image_ops.decode_image(gif0, dtype=dtypes.float32) image1 = image_ops.convert_image_dtype(image_ops.decode_gif(gif0), dtypes.float32) - image0, image1 = sess.run([image0, image1]) + image0, image1 = self.evaluate([image0, image1]) self.assertAllEqual(image0, image1) def testBmpFloat32(self): @@ -4290,7 +4390,7 @@ class DecodeImageTest(test_util.TensorFlowTestCase): image0 = image_ops.decode_image(bmp0, dtype=dtypes.float32) image1 = image_ops.convert_image_dtype(image_ops.decode_bmp(bmp0), dtypes.float32) - image0, image1 = sess.run([image0, image1]) + image0, image1 = self.evaluate([image0, image1]) self.assertAllEqual(image0, image1) diff --git a/tensorflow/python/ops/init_ops.py b/tensorflow/python/ops/init_ops.py index 4fe6d05620..c0a4bcd51d 100644 --- a/tensorflow/python/ops/init_ops.py +++ b/tensorflow/python/ops/init_ops.py @@ -55,6 +55,15 @@ class Initializer(object): """ def __call__(self, shape, dtype=None, partition_info=None): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. If not provided use the initializer + dtype. + partition_info: Optional information about the possible partitioning of a + tensor. + """ raise NotImplementedError def get_config(self): @@ -143,7 +152,8 @@ class Constant(Initializer): value: A Python scalar, list or tuple of values, or a N-dimensional numpy array. All elements of the initialized variable will be set to the corresponding value in the `value` argument. - dtype: The data type. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. verify_shape: Boolean that enables verification of the shape of `value`. If `True`, the initializer will throw an error if the shape of `value` is not compatible with the shape of the initialized tensor. @@ -216,7 +226,7 @@ class Constant(Initializer): dtype = self.dtype if verify_shape is None: verify_shape = self._verify_shape - return constant_op.constant( + return constant_op.constant_v1( self.value, dtype=dtype, shape=shape, verify_shape=verify_shape) def get_config(self): @@ -239,7 +249,8 @@ class RandomUniform(Initializer): seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. """ def __init__(self, minval=0, maxval=None, seed=None, dtype=dtypes.float32): @@ -275,7 +286,8 @@ class RandomNormal(Initializer): seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. Only floating point types are supported. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. """ def __init__(self, mean=0.0, stddev=1.0, seed=None, dtype=dtypes.float32): @@ -316,7 +328,8 @@ class TruncatedNormal(Initializer): seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. Only floating point types are supported. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. """ def __init__(self, mean=0.0, stddev=1.0, seed=None, dtype=dtypes.float32): @@ -360,8 +373,7 @@ class UniformUnitScaling(Initializer): A similar calculation for convolutional networks gives an analogous result with `dim` equal to the product of the first 3 dimensions. When nonlinearities are present, we need to multiply this by a constant `factor`. - See [Sussillo et al., 2014](https://arxiv.org/abs/1412.6558) - ([pdf](http://arxiv.org/pdf/1412.6558.pdf)) for deeper motivation, experiments + See (Sussillo et al., 2014) for deeper motivation, experiments and the calculation of constants. In section 2.3 there, the constants were numerically computed: for a linear layer it's 1.0, relu: ~1.43, tanh: ~1.15. @@ -370,7 +382,12 @@ class UniformUnitScaling(Initializer): seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. Only floating point types are supported. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. + + References: + [Sussillo et al., 2014](https://arxiv.org/abs/1412.6558) + ([pdf](http://arxiv.org/pdf/1412.6558.pdf)) """ @deprecated(None, @@ -434,7 +451,8 @@ class VarianceScaling(Initializer): seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. Only floating point types are supported. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. Raises: ValueError: In case of an invalid value for the "scale", mode" or @@ -480,7 +498,7 @@ class VarianceScaling(Initializer): else: scale /= max(1., (fan_in + fan_out) / 2.) if self.distribution == "normal" or self.distribution == "truncated_normal": - # constant taken from scipy.stats.truncnorm.std(a=-2, b=2, loc=0., scale=1.) + # constant taken from scipy.stats.truncnorm.std(a=-2, b=2, loc=0., scale=1.) stddev = math.sqrt(scale) / .87962566103423978 return random_ops.truncated_normal( shape, 0.0, stddev, dtype, seed=self.seed) @@ -531,7 +549,12 @@ class Orthogonal(Initializer): seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. + + References: + [Saxe et al., 2014](https://openreview.net/forum?id=_wzZwKpTDF_9C) + ([pdf](https://arxiv.org/pdf/1312.6120.pdf)) """ def __init__(self, gain=1.0, seed=None, dtype=dtypes.float32): @@ -576,16 +599,21 @@ class ConvolutionDeltaOrthogonal(Initializer): The shape of the tensor must have length 3, 4 or 5. The number of input filters must not exceed the number of output filters. The center pixels of the tensor form an orthogonal matrix. Other pixels are set to be zero. See - algorithm 2 in [Xiao et al., 2018]: https://arxiv.org/abs/1806.05393 + algorithm 2 in (Xiao et al., 2018). Args: - gain: Multiplicative factor to apply to the orthogonal matrix. Default is 1. - The 2-norm of an input is multiplied by a factor of 'sqrt(gain)' after - applying this convolution. + gain: Multiplicative factor to apply to the orthogonal + matrix. Default is 1. The 2-norm of an input is multiplied by a factor of + `gain` after applying this convolution. seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. + + References: + [Xiao et al., 2018](http://proceedings.mlr.press/v80/xiao18a.html) + ([pdf](http://proceedings.mlr.press/v80/xiao18a/xiao18a.pdf)) """ def __init__(self, gain=1.0, seed=None, dtype=dtypes.float32): @@ -613,7 +641,7 @@ class ConvolutionDeltaOrthogonal(Initializer): d = array_ops.diag_part(r) q *= math_ops.sign(d) q = q[:shape[-2], :] - q *= math_ops.sqrt(math_ops.cast(self.gain, dtype=dtype)) + q *= math_ops.cast(self.gain, dtype=dtype) if len(shape) == 3: weight = array_ops.scatter_nd([[(shape[0]-1)//2]], array_ops.expand_dims(q, 0), shape) @@ -636,12 +664,17 @@ class ConvolutionOrthogonal(Initializer): Base class used to construct 1D, 2D and 3D orthogonal kernels for convolution. Args: - gain: multiplicative factor to apply to the orthogonal matrix. Default is 1. - The 2-norm of an input is multiplied by a factor of 'sqrt(gain)' after - applying this convolution. + gain: multiplicative factor to apply to the orthogonal + matrix. Default is 1. The 2-norm of an input is multiplied by a factor of + `gain` after applying this convolution. seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. + + References: + [Xiao et al., 2018](http://proceedings.mlr.press/v80/xiao18a.html) + ([pdf](http://proceedings.mlr.press/v80/xiao18a/xiao18a.pdf)) """ def __init__(self, gain=1.0, seed=None, dtype=dtypes.float32): @@ -698,15 +731,20 @@ class ConvolutionOrthogonal2D(ConvolutionOrthogonal): filters must not exceed the number of output filters. The orthogonality(==isometry) is exact when the inputs are circular padded. There are finite-width effects with non-circular padding (e.g. zero padding). - See algorithm 1 in [Xiao et al., 2018]: https://arxiv.org/abs/1806.05393 + See algorithm 1 in (Xiao et al., 2018). Args: - gain: Multiplicative factor to apply to the orthogonal matrix. Default is 1. - This has the effect of scaling the output 2-norm by a factor of - `sqrt(gain)`. + gain: Multiplicative factor to apply to the orthogonal + matrix. Default is 1. This has the effect of scaling the output 2-norm by + a factor of `gain`. seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. + + References: + [Xiao et al., 2018](http://proceedings.mlr.press/v80/xiao18a.html) + ([pdf](http://proceedings.mlr.press/v80/xiao18a/xiao18a.pdf)) """ def __call__(self, shape, dtype=None, partition_info=None): @@ -722,7 +760,7 @@ class ConvolutionOrthogonal2D(ConvolutionOrthogonal): raise ValueError("Kernel sizes must be equal.") kernel = self._orthogonal_kernel(shape[0], shape[2], shape[3]) - kernel *= math_ops.sqrt(math_ops.cast(self.gain, dtype=dtype)) + kernel *= math_ops.cast(self.gain, dtype=dtype) return kernel def _dict_to_tensor(self, x, k1, k2): @@ -834,16 +872,21 @@ class ConvolutionOrthogonal1D(ConvolutionOrthogonal): filters must not exceed the number of output filters. The orthogonality(==isometry) is exact when the inputs are circular padded. There are finite-width effects with non-circular padding (e.g. zero padding). - See algorithm 1 in [Xiao et al., 2018]: https://arxiv.org/abs/1806.05393 + See algorithm 1 in (Xiao et al., 2018). Args: - gain: Multiplicative factor to apply to the orthogonal matrix. Default is 1. - The 2-norm of an input is multiplied by a factor of 'sqrt(gain)' after - applying this convolution. + gain: Multiplicative factor to apply to the orthogonal + matrix. Default is 1. The 2-norm of an input is multiplied by a factor of + `gain` after applying this convolution. seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. + + References: + [Xiao et al., 2018](http://proceedings.mlr.press/v80/xiao18a.html) + ([pdf](http://proceedings.mlr.press/v80/xiao18a/xiao18a.pdf)) """ def __call__(self, shape, dtype=None, partition_info=None): @@ -856,7 +899,7 @@ class ConvolutionOrthogonal1D(ConvolutionOrthogonal): raise ValueError("In_filters cannot be greater than out_filters.") kernel = self._orthogonal_kernel(shape[0], shape[-2], shape[-1]) - kernel *= math_ops.sqrt(math_ops.cast(self.gain, dtype=dtype)) + kernel *= math_ops.cast(self.gain, dtype=dtype) return kernel def _dict_to_tensor(self, x, k): @@ -951,15 +994,20 @@ class ConvolutionOrthogonal3D(ConvolutionOrthogonal): filters must not exceed the number of output filters. The orthogonality(==isometry) is exact when the inputs are circular padded. There are finite-width effects with non-circular padding (e.g. zero padding). - See algorithm 1 [Xiao et al., 2018] in: https://arxiv.org/abs/1806.05393 + See algorithm 1 (Xiao et al., 2018). Args: - gain: Multiplicative factor to apply to the orthogonal matrix. Default is 1. - The 2-norm of an input is multiplied by a factor of 'sqrt(gain)' after - applying this convolution. + gain: Multiplicative factor to apply to the orthogonal + matrix. Default is 1. The 2-norm of an input is multiplied by a factor of + `gain` after applying this convolution. seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. + + References: + [Xiao et al., 2018](http://proceedings.mlr.press/v80/xiao18a.html) + ([pdf](http://proceedings.mlr.press/v80/xiao18a/xiao18a.pdf)) """ def __call__(self, shape, dtype=None, partition_info=None): @@ -975,7 +1023,7 @@ class ConvolutionOrthogonal3D(ConvolutionOrthogonal): raise ValueError("Kernel sizes must be equal.") kernel = self._orthogonal_kernel(shape[0], shape[-2], shape[-1]) - kernel *= math_ops.sqrt(math_ops.cast(self.gain, dtype=dtype)) + kernel *= math_ops.cast(self.gain, dtype=dtype) return kernel def _dict_to_tensor(self, x, k1, k2, k3): @@ -1105,7 +1153,8 @@ class Identity(Initializer): Args: gain: Multiplicative factor to apply to the identity matrix. - dtype: The type of the output. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. """ def __init__(self, gain=1.0, dtype=dtypes.float32): @@ -1139,18 +1188,19 @@ class GlorotUniform(VarianceScaling): where `fan_in` is the number of input units in the weight tensor and `fan_out` is the number of output units in the weight tensor. - Reference: http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf - Args: seed: A Python integer. Used to create random seeds. See `tf.set_random_seed` for behavior. - dtype: The data type. Only floating point types are supported. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. + + References: + [Glorot et al., 2010](http://proceedings.mlr.press/v9/glorot10a.html) + ([pdf](http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf)) """ - def __init__(self, - seed=None, - dtype=dtypes.float32): + def __init__(self, seed=None, dtype=dtypes.float32): super(GlorotUniform, self).__init__( scale=1.0, mode="fan_avg", @@ -1159,10 +1209,7 @@ class GlorotUniform(VarianceScaling): dtype=dtype) def get_config(self): - return { - "seed": self.seed, - "dtype": self.dtype.name - } + return {"seed": self.seed, "dtype": self.dtype.name} @tf_export( @@ -1181,18 +1228,18 @@ class GlorotNormal(VarianceScaling): where `fan_in` is the number of input units in the weight tensor and `fan_out` is the number of output units in the weight tensor. - Reference: http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf - Args: seed: A Python integer. Used to create random seeds. See - `tf.set_random_seed` - for behavior. - dtype: The data type. Only floating point types are supported. + `tf.set_random_seed` for behavior. + dtype: Default data type, used if no `dtype` argument is provided when + calling the initializer. Only floating point types are supported. + + References: + [Glorot et al., 2010](http://proceedings.mlr.press/v9/glorot10a.html) + ([pdf](http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf)) """ - def __init__(self, - seed=None, - dtype=dtypes.float32): + def __init__(self, seed=None, dtype=dtypes.float32): super(GlorotNormal, self).__init__( scale=1.0, mode="fan_avg", @@ -1201,10 +1248,7 @@ class GlorotNormal(VarianceScaling): dtype=dtype) def get_config(self): - return { - "seed": self.seed, - "dtype": self.dtype.name - } + return {"seed": self.seed, "dtype": self.dtype.name} # Aliases. @@ -1244,9 +1288,11 @@ def lecun_normal(seed=None): An initializer. References: - - [Self-Normalizing Neural Networks](https://arxiv.org/abs/1706.02515) - - [Efficient - Backprop](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf) + - Self-Normalizing Neural Networks, + [Klambauer et al., 2017](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks) + ([pdf](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks.pdf)) + - Efficient Backprop, + [Lecun et al., 1998](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf) """ return VarianceScaling( scale=1., mode="fan_in", distribution="truncated_normal", seed=seed) @@ -1267,8 +1313,11 @@ def lecun_uniform(seed=None): An initializer. References: - LeCun 98, Efficient Backprop, - http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf + - Self-Normalizing Neural Networks, + [Klambauer et al., 2017](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks) + ([pdf](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks.pdf)) + - Efficient Backprop, + [Lecun et al., 1998](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf) """ return VarianceScaling( scale=1., mode="fan_in", distribution="uniform", seed=seed) @@ -1289,7 +1338,8 @@ def he_normal(seed=None): An initializer. References: - He et al., http://arxiv.org/abs/1502.01852 + [He et al., 2015](https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) + ([pdf](https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/He_Delving_Deep_into_ICCV_2015_paper.pdf)) """ return VarianceScaling( scale=2., mode="fan_in", distribution="truncated_normal", seed=seed) @@ -1310,7 +1360,8 @@ def he_uniform(seed=None): An initializer. References: - He et al., http://arxiv.org/abs/1502.01852 + [He et al., 2015](https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) + ([pdf](https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/He_Delving_Deep_into_ICCV_2015_paper.pdf)) """ return VarianceScaling( scale=2., mode="fan_in", distribution="uniform", seed=seed) diff --git a/tensorflow/python/ops/init_ops_test.py b/tensorflow/python/ops/init_ops_test.py index 5693c3caaf..1f22248004 100644 --- a/tensorflow/python/ops/init_ops_test.py +++ b/tensorflow/python/ops/init_ops_test.py @@ -45,8 +45,8 @@ class InitializersTest(test.TestCase): output = variable.numpy() else: sess = ops.get_default_session() - sess.run(variable.initializer) - output = sess.run(variable) + self.evaluate(variable.initializer) + output = self.evaluate(variable) lim = 3e-2 if target_std is not None: self.assertGreater(lim, abs(output.std() - target_std)) diff --git a/tensorflow/python/ops/linalg/BUILD b/tensorflow/python/ops/linalg/BUILD index c7314d7774..5df2d6b838 100644 --- a/tensorflow/python/ops/linalg/BUILD +++ b/tensorflow/python/ops/linalg/BUILD @@ -18,6 +18,7 @@ py_library( "//tensorflow/python:random_ops", "//tensorflow/python:tensor_util", "//tensorflow/python:util", + "//tensorflow/python/ops/signal", "//third_party/py/numpy", "@six_archive//:six", ], diff --git a/tensorflow/python/ops/linalg/cholesky_registrations.py b/tensorflow/python/ops/linalg/cholesky_registrations.py new file mode 100644 index 0000000000..e5284cf22a --- /dev/null +++ b/tensorflow/python/ops/linalg/cholesky_registrations.py @@ -0,0 +1,101 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Registrations for LinearOperator.cholesky.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.ops import linalg_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops.linalg import linear_operator +from tensorflow.python.ops.linalg import linear_operator_algebra +from tensorflow.python.ops.linalg import linear_operator_block_diag +from tensorflow.python.ops.linalg import linear_operator_diag +from tensorflow.python.ops.linalg import linear_operator_identity +from tensorflow.python.ops.linalg import linear_operator_kronecker +from tensorflow.python.ops.linalg import linear_operator_lower_triangular + + +# By default, compute the Cholesky of the dense matrix, and return a +# LowerTriangular operator. Methods below specialize this registration. +@linear_operator_algebra.RegisterCholesky(linear_operator.LinearOperator) +def _cholesky_linear_operator(linop): + return linear_operator_lower_triangular.LinearOperatorLowerTriangular( + linalg_ops.cholesky(linop.to_dense()), + is_non_singular=True, + is_self_adjoint=False, + is_square=True) + + +@linear_operator_algebra.RegisterCholesky( + linear_operator_diag.LinearOperatorDiag) +def _cholesky_diag(diag_operator): + return linear_operator_diag.LinearOperatorDiag( + math_ops.sqrt(diag_operator.diag), + is_non_singular=True, + is_self_adjoint=True, + is_positive_definite=True, + is_square=True) + + +@linear_operator_algebra.RegisterCholesky( + linear_operator_identity.LinearOperatorIdentity) +def _cholesky_identity(identity_operator): + return linear_operator_identity.LinearOperatorIdentity( + num_rows=identity_operator._num_rows, # pylint: disable=protected-access + batch_shape=identity_operator.batch_shape, + dtype=identity_operator.dtype, + is_non_singular=True, + is_self_adjoint=True, + is_positive_definite=True, + is_square=True) + + +@linear_operator_algebra.RegisterCholesky( + linear_operator_identity.LinearOperatorScaledIdentity) +def _cholesky_scaled_identity(identity_operator): + return linear_operator_identity.LinearOperatorScaledIdentity( + num_rows=identity_operator._num_rows, # pylint: disable=protected-access + multiplier=math_ops.sqrt(identity_operator.multiplier), + is_non_singular=True, + is_self_adjoint=True, + is_positive_definite=True, + is_square=True) + + +@linear_operator_algebra.RegisterCholesky( + linear_operator_block_diag.LinearOperatorBlockDiag) +def _cholesky_block_diag(block_diag_operator): + # We take the cholesky of each block on the diagonal. + return linear_operator_block_diag.LinearOperatorBlockDiag( + operators=[ + operator.cholesky() for operator in block_diag_operator.operators], + is_non_singular=True, + is_self_adjoint=False, + is_square=True) + + +@linear_operator_algebra.RegisterCholesky( + linear_operator_kronecker.LinearOperatorKronecker) +def _cholesky_kronecker(kronecker_operator): + # Cholesky decomposition of a Kronecker product is the Kronecker product + # of cholesky decompositions. + return linear_operator_kronecker.LinearOperatorKronecker( + operators=[ + operator.cholesky() for operator in kronecker_operator.operators], + is_non_singular=True, + is_self_adjoint=False, + is_square=True) diff --git a/tensorflow/python/ops/linalg/linalg.py b/tensorflow/python/ops/linalg/linalg.py index c29b5033bb..ac4fd4ebc6 100644 --- a/tensorflow/python/ops/linalg/linalg.py +++ b/tensorflow/python/ops/linalg/linalg.py @@ -20,6 +20,9 @@ from __future__ import print_function # go/tf-wildcard-import # pylint: disable=wildcard-import,unused-import +from tensorflow.python.ops.linalg import cholesky_registrations as _cholesky_registrations +from tensorflow.python.ops.linalg import linear_operator_algebra as _linear_operator_algebra +from tensorflow.python.ops.linalg import matmul_registrations as _matmul_registrations from tensorflow.python.ops.linalg.linalg_impl import * from tensorflow.python.ops.linalg.linear_operator import * from tensorflow.python.ops.linalg.linear_operator_block_diag import * diff --git a/tensorflow/python/ops/linalg/linalg_impl.py b/tensorflow/python/ops/linalg/linalg_impl.py index 08d50ce622..2c9476a9bd 100644 --- a/tensorflow/python/ops/linalg/linalg_impl.py +++ b/tensorflow/python/ops/linalg/linalg_impl.py @@ -88,7 +88,7 @@ def logdet(matrix, name=None): chol = gen_linalg_ops.cholesky(matrix) return 2.0 * math_ops.reduce_sum( math_ops.log(math_ops.real(array_ops.matrix_diag_part(chol))), - reduction_indices=[-1]) + axis=[-1]) @tf_export('linalg.adjoint') diff --git a/tensorflow/python/ops/linalg/linear_operator.py b/tensorflow/python/ops/linalg/linear_operator.py index 9ef6c42b04..8efafda3a1 100644 --- a/tensorflow/python/ops/linalg/linear_operator.py +++ b/tensorflow/python/ops/linalg/linear_operator.py @@ -32,6 +32,7 @@ from tensorflow.python.ops import check_ops from tensorflow.python.ops import linalg_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops.linalg import linalg_impl as linalg +from tensorflow.python.ops.linalg import linear_operator_algebra from tensorflow.python.ops.linalg import linear_operator_util from tensorflow.python.platform import tf_logging as logging from tensorflow.python.util.tf_export import tf_export @@ -284,7 +285,7 @@ class LinearOperator(object): `[B1,...,Bb, M, N]`, equivalent to `tf.shape(A)`. Args: - name: A name for this `Op. + name: A name for this `Op`. Returns: `int32` `Tensor` @@ -318,7 +319,7 @@ class LinearOperator(object): `[B1,...,Bb]`. Args: - name: A name for this `Op. + name: A name for this `Op`. Returns: `int32` `Tensor` @@ -340,7 +341,7 @@ class LinearOperator(object): `A.shape = [B1,...,Bb, M, N]`, then this returns `b + 2`. Args: - name: A name for this `Op. + name: A name for this `Op`. Returns: Python integer, or None if the tensor rank is undefined. @@ -356,7 +357,7 @@ class LinearOperator(object): `A.shape = [B1,...,Bb, M, N]`, then this returns `b + 2`. Args: - name: A name for this `Op. + name: A name for this `Op`. Returns: `int32` `Tensor`, determined at runtime. @@ -581,16 +582,29 @@ class LinearOperator(object): ``` Args: - x: `Tensor` with compatible shape and same `dtype` as `self`. - See class docstring for definition of compatibility. + x: `LinearOperator` or `Tensor` with compatible shape and same `dtype` as + `self`. See class docstring for definition of compatibility. adjoint: Python `bool`. If `True`, left multiply by the adjoint: `A^H x`. adjoint_arg: Python `bool`. If `True`, compute `A x^H` where `x^H` is the hermitian transpose (transposition and complex conjugation). - name: A name for this `Op. + name: A name for this `Op`. Returns: - A `Tensor` with shape `[..., M, R]` and same `dtype` as `self`. + A `LinearOperator` or `Tensor` with shape `[..., M, R]` and same `dtype` + as `self`. """ + if isinstance(x, LinearOperator): + if adjoint or adjoint_arg: + raise ValueError(".matmul not supported with adjoints.") + if (x.range_dimension is not None and + self.domain_dimension is not None and + x.range_dimension != self.domain_dimension): + raise ValueError( + "Operators are incompatible. Expected `x` to have dimension" + " {} but got {}.".format(self.domain_dimension, x.range_dimension)) + with self._name_scope(name): + return linear_operator_algebra.matmul(self, x) + with self._name_scope(name, values=[x]): x = ops.convert_to_tensor(x, name="x") self._check_input_dtype(x) @@ -630,7 +644,7 @@ class LinearOperator(object): dimensions, the last dimension defines a vector. See class docstring for definition of compatibility. adjoint: Python `bool`. If `True`, left multiply by the adjoint: `A^H x`. - name: A name for this `Op. + name: A name for this `Op`. Returns: A `Tensor` with shape `[..., M]` and same `dtype` as `self`. @@ -655,7 +669,7 @@ class LinearOperator(object): """Determinant for every batch member. Args: - name: A name for this `Op. + name: A name for this `Op`. Returns: `Tensor` with shape `self.batch_shape` and same `dtype` as `self`. @@ -676,7 +690,7 @@ class LinearOperator(object): " Requires conversion to a dense matrix and O(N^3) operations.") if self._can_use_cholesky(): diag = array_ops.matrix_diag_part(linalg_ops.cholesky(self.to_dense())) - return 2 * math_ops.reduce_sum(math_ops.log(diag), reduction_indices=[-1]) + return 2 * math_ops.reduce_sum(math_ops.log(diag), axis=[-1]) _, log_abs_det = linalg.slogdet(self.to_dense()) return log_abs_det @@ -684,7 +698,7 @@ class LinearOperator(object): """Log absolute value of determinant for every batch member. Args: - name: A name for this `Op. + name: A name for this `Op`. Returns: `Tensor` with shape `self.batch_shape` and same `dtype` as `self`. @@ -830,6 +844,31 @@ class LinearOperator(object): return self._solvevec(rhs, adjoint=adjoint) + def cholesky(self, name="cholesky"): + """Returns a Cholesky factor as a `LinearOperator`. + + Given `A` representing this `LinearOperator`, if `A` is positive definite + self-adjoint, return `L`, where `A = L L^T`, i.e. the cholesky + decomposition. + + Args: + name: A name for this `Op`. + + Returns: + `LinearOperator` which represents the lower triangular matrix + in the Cholesky decomposition. + + Raises: + ValueError: When the `LinearOperator` is not hinted to be positive + definite and self adjoint. + """ + + if not self._can_use_cholesky(): + raise ValueError("Cannot take the Cholesky decomposition: " + "Not a positive definite self adjoint matrix.") + with self._name_scope(name): + return linear_operator_algebra.cholesky(self) + def _to_dense(self): """Generic and often inefficient implementation. Override often.""" logging.warn("Using (possibly slow) default implementation of to_dense." @@ -922,6 +961,4 @@ class LinearOperator(object): return self._add_to_tensor(x) def _can_use_cholesky(self): - # TODO(langmore) Add complex types when tf.cholesky can use them. - return (not self.dtype.is_complex and self.is_self_adjoint and - self.is_positive_definite) + return self.is_self_adjoint and self.is_positive_definite diff --git a/tensorflow/python/ops/linalg/linear_operator_adjoint.py b/tensorflow/python/ops/linalg/linear_operator_adjoint.py new file mode 100644 index 0000000000..858e224b9a --- /dev/null +++ b/tensorflow/python/ops/linalg/linear_operator_adjoint.py @@ -0,0 +1,207 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Takes the adjoint of a `LinearOperator`.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops.linalg import linalg_impl as linalg +from tensorflow.python.ops.linalg import linear_operator +from tensorflow.python.util.tf_export import tf_export + +__all__ = [] + + +@tf_export("linalg.LinearOperatorAdjoint") +class LinearOperatorAdjoint(linear_operator.LinearOperator): + """`LinearOperator` representing the adjoint of another operator. + + This operator represents the adjoint of another operator. + + ```python + # Create a 2 x 2 linear operator. + operator = LinearOperatorFullMatrix([[1 - i., 3.], [0., 1. + i]]) + operator_adjoint = LinearOperatorAdjoint(operator) + + operator_adjoint.to_dense() + ==> [[1. + i, 0.] + [3., 1 - i]] + + operator_adjoint.shape + ==> [2, 2] + + operator_adjoint.log_abs_determinant() + ==> - log(2) + + x = ... Shape [2, 4] Tensor + operator_adjoint.matmul(x) + ==> Shape [2, 4] Tensor, equal to operator.matmul(x, adjoint=True) + ``` + + #### Performance + + The performance of `LinearOperatorAdjoint` depends on the underlying + operators performance. + + #### Matrix property hints + + This `LinearOperator` is initialized with boolean flags of the form `is_X`, + for `X = non_singular, self_adjoint, positive_definite, square`. + These have the following meaning: + + * If `is_X == True`, callers should expect the operator to have the + property `X`. This is a promise that should be fulfilled, but is *not* a + runtime assert. For example, finite floating point precision may result + in these promises being violated. + * If `is_X == False`, callers should expect the operator to not have `X`. + * If `is_X == None` (the default), callers should have no expectation either + way. + """ + + def __init__(self, + operator, + is_non_singular=None, + is_self_adjoint=None, + is_positive_definite=None, + is_square=None, + name=None): + r"""Initialize a `LinearOperatorAdjoint`. + + `LinearOperatorAdjoint` is initialized with an operator `A`. The `solve` + and `matmul` methods effectively flip the `adjoint` argument. E.g. + + ``` + A = MyLinearOperator(...) + B = LinearOperatorAdjoint(A) + x = [....] # a vector + + assert A.matvec(x, adjoint=True) == B.matvec(x, adjoint=False) + ``` + + Args: + operator: `LinearOperator` object. + is_non_singular: Expect that this operator is non-singular. + is_self_adjoint: Expect that this operator is equal to its hermitian + transpose. + is_positive_definite: Expect that this operator is positive definite, + meaning the quadratic form `x^H A x` has positive real part for all + nonzero `x`. Note that we do not require the operator to be + self-adjoint to be positive-definite. See: + https://en.wikipedia.org/wiki/Positive-definite_matrix#Extension_for_non-symmetric_matrices + is_square: Expect that this operator acts like square [batch] matrices. + name: A name for this `LinearOperator`. Default is `operator.name + + "_adjoint"`. + + Raises: + ValueError: If `operator.is_non_singular` is False. + """ + + self._operator = operator + + # The congruency of is_non_singular and is_self_adjoint was checked in the + # base operator. + def _combined_hint(hint_str, provided_hint_value, message): + """Get combined hint in the case where operator.hint should equal hint.""" + op_hint = getattr(operator, hint_str) + if op_hint is False and provided_hint_value: + raise ValueError(message) + if op_hint and provided_hint_value is False: + raise ValueError(message) + return (op_hint or provided_hint_value) or None + + is_square = _combined_hint( + "is_square", is_square, + "An operator is square if and only if its adjoint is square.") + + is_non_singular = _combined_hint( + "is_non_singular", is_non_singular, + "An operator is non-singular if and only if its adjoint is " + "non-singular.") + + is_self_adjoint = _combined_hint( + "is_self_adjoint", is_self_adjoint, + "An operator is self-adjoint if and only if its adjoint is " + "self-adjoint.") + + is_positive_definite = _combined_hint( + "is_positive_definite", is_positive_definite, + "An operator is positive-definite if and only if its adjoint is " + "positive-definite.") + + is_square = _combined_hint( + "is_square", is_square, + "An operator is square if and only if its adjoint is square.") + + # Initialization. + if name is None: + name = operator.name + "_adjoint" + with ops.name_scope(name, values=operator.graph_parents): + super(LinearOperatorAdjoint, self).__init__( + dtype=operator.dtype, + graph_parents=operator.graph_parents, + is_non_singular=is_non_singular, + is_self_adjoint=is_self_adjoint, + is_positive_definite=is_positive_definite, + is_square=is_square, + name=name) + + @property + def operator(self): + """The operator before taking the adjoint.""" + return self._operator + + def _assert_non_singular(self): + return self.operator.assert_non_singular() + + def _assert_positive_definite(self): + return self.operator.assert_positive_definite() + + def _assert_self_adjoint(self): + return self.operator.assert_self_adjoint() + + def _shape(self): + return self.operator.shape + + def _shape_tensor(self): + return self.operator.shape_tensor() + + def _matmul(self, x, adjoint=False, adjoint_arg=False): + return self.operator.matmul( + x, adjoint=(not adjoint), adjoint_arg=adjoint_arg) + + def _determinant(self): + if self.is_self_adjoint: + return self.operator.determinant() + return math_ops.conj(self.operator.determinant()) + + def _log_abs_determinant(self): + return self.operator.log_abs_determinant() + + def _trace(self): + if self.is_self_adjoint: + return self.operator.trace() + return math_ops.conj(self.operator.trace()) + + def _solve(self, rhs, adjoint=False, adjoint_arg=False): + return self.operator.solve( + rhs, adjoint=(not adjoint), adjoint_arg=adjoint_arg) + + def _to_dense(self): + if self.is_self_adjoint: + return self.operator.to_dense() + return linalg.adjoint(self.operator.to_dense()) diff --git a/tensorflow/python/ops/linalg/linear_operator_algebra.py b/tensorflow/python/ops/linalg/linear_operator_algebra.py new file mode 100644 index 0000000000..7b99066e4c --- /dev/null +++ b/tensorflow/python/ops/linalg/linear_operator_algebra.py @@ -0,0 +1,191 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Registration mechanisms for various n-ary operations on LinearOperators.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import itertools + +from tensorflow.python.framework import ops +from tensorflow.python.util import tf_inspect + + +_CHOLESKY_DECOMPS = {} +_MATMUL = {} + + +def _registered_function(type_list, registry): + """Given a list of classes, finds the most specific function registered.""" + enumerated_hierarchies = [enumerate(tf_inspect.getmro(t)) for t in type_list] + # Get all possible combinations of hierarchies. + cls_combinations = list(itertools.product(*enumerated_hierarchies)) + + def hierarchy_distance(cls_combination): + candidate_distance = sum(c[0] for c in cls_combination) + if tuple(c[1] for c in cls_combination) in registry: + return candidate_distance + return 10000 + + registered_combination = min(cls_combinations, key=hierarchy_distance) + return registry.get(tuple(r[1] for r in registered_combination), None) + + +def _registered_cholesky(type_a): + """Get the Cholesky function registered for class a.""" + return _registered_function([type_a], _CHOLESKY_DECOMPS) + + +def _registered_matmul(type_a, type_b): + """Get the Matmul function registered for classes a and b.""" + return _registered_function([type_a, type_b], _MATMUL) + + +def cholesky(lin_op_a, name=None): + """Get the Cholesky factor associated to lin_op_a. + + Args: + lin_op_a: The LinearOperator to decompose. + name: Name to use for this operation. + + Returns: + A LinearOperator that represents the lower Cholesky factor of `lin_op_a`. + + Raises: + NotImplementedError: If no Cholesky method is defined for the LinearOperator + type of `lin_op_a`. + """ + cholesky_fn = _registered_cholesky(type(lin_op_a)) + if cholesky_fn is None: + raise ValueError("No cholesky decomposition registered for {}".format( + type(lin_op_a))) + + with ops.name_scope(name, "Cholesky"): + return cholesky_fn(lin_op_a) + + +def matmul(lin_op_a, lin_op_b, name=None): + """Compute lin_op_a.matmul(lin_op_b). + + Args: + lin_op_a: The LinearOperator on the left. + lin_op_b: The LinearOperator on the right. + name: Name to use for this operation. + + Returns: + A LinearOperator that represents the matmul between `lin_op_a` and + `lin_op_b`. + + Raises: + NotImplementedError: If no matmul method is defined between types of + `lin_op_a` and `lin_op_b`. + """ + matmul_fn = _registered_matmul(type(lin_op_a), type(lin_op_b)) + if matmul_fn is None: + raise ValueError("No matmul registered for {}.matmul({})".format( + type(lin_op_a), type(lin_op_b))) + + with ops.name_scope(name, "Matmul"): + return matmul_fn(lin_op_a, lin_op_b) + + +class RegisterCholesky(object): + """Decorator to register a Cholesky implementation function. + + Usage: + + @linear_operator_algebra.RegisterCholesky(lin_op.LinearOperatorIdentity) + def _cholesky_identity(lin_op_a): + # Return the identity matrix. + """ + + def __init__(self, lin_op_cls_a): + """Initialize the LinearOperator registrar. + + Args: + lin_op_cls_a: the class of the LinearOperator to decompose. + """ + self._key = (lin_op_cls_a,) + + def __call__(self, cholesky_fn): + """Perform the Cholesky registration. + + Args: + cholesky_fn: The function to use for the Cholesky. + + Returns: + cholesky_fn + + Raises: + TypeError: if cholesky_fn is not a callable. + ValueError: if a Cholesky function has already been registered for + the given argument classes. + """ + if not callable(cholesky_fn): + raise TypeError( + "cholesky_fn must be callable, received: {}".format(cholesky_fn)) + if self._key in _CHOLESKY_DECOMPS: + raise ValueError("Cholesky({}) has already been registered to: {}".format( + self._key[0].__name__, _CHOLESKY_DECOMPS[self._key])) + _CHOLESKY_DECOMPS[self._key] = cholesky_fn + return cholesky_fn + + +class RegisterMatmul(object): + """Decorator to register a Matmul implementation function. + + Usage: + + @linear_operator_algebra.RegisterMatmul( + lin_op.LinearOperatorIdentity, + lin_op.LinearOperatorIdentity) + def _matmul_identity(a, b): + # Return the identity matrix. + """ + + def __init__(self, lin_op_cls_a, lin_op_cls_b): + """Initialize the LinearOperator registrar. + + Args: + lin_op_cls_a: the class of the LinearOperator to multiply. + lin_op_cls_b: the class of the second LinearOperator to multiply. + """ + self._key = (lin_op_cls_a, lin_op_cls_b) + + def __call__(self, matmul_fn): + """Perform the Matmul registration. + + Args: + matmul_fn: The function to use for the Matmul. + + Returns: + matmul_fn + + Raises: + TypeError: if matmul_fn is not a callable. + ValueError: if a Matmul function has already been registered for + the given argument classes. + """ + if not callable(matmul_fn): + raise TypeError( + "matmul_fn must be callable, received: {}".format(matmul_fn)) + if self._key in _MATMUL: + raise ValueError("Matmul({}, {}) has already been registered.".format( + self._key[0].__name__, + self._key[1].__name__)) + _MATMUL[self._key] = matmul_fn + return matmul_fn diff --git a/tensorflow/python/ops/linalg/linear_operator_block_diag.py b/tensorflow/python/ops/linalg/linear_operator_block_diag.py index 438c3496bd..b0b418c997 100644 --- a/tensorflow/python/ops/linalg/linear_operator_block_diag.py +++ b/tensorflow/python/ops/linalg/linear_operator_block_diag.py @@ -29,9 +29,7 @@ from tensorflow.python.ops.linalg import linear_operator from tensorflow.python.ops.linalg import linear_operator_util from tensorflow.python.util.tf_export import tf_export -__all__ = [ - "LinearOperatorBlockDiag", -] +__all__ = ["LinearOperatorBlockDiag"] @tf_export("linalg.LinearOperatorBlockDiag") diff --git a/tensorflow/python/ops/linalg/linear_operator_circulant.py b/tensorflow/python/ops/linalg/linear_operator_circulant.py index 021ef47383..b74baa5dfd 100644 --- a/tensorflow/python/ops/linalg/linear_operator_circulant.py +++ b/tensorflow/python/ops/linalg/linear_operator_circulant.py @@ -30,6 +30,7 @@ from tensorflow.python.ops.distributions import util as distribution_util from tensorflow.python.ops.linalg import linalg_impl as linalg from tensorflow.python.ops.linalg import linear_operator from tensorflow.python.ops.linalg import linear_operator_util +from tensorflow.python.ops.signal import fft_ops from tensorflow.python.util.tf_export import tf_export __all__ = [ @@ -39,8 +40,8 @@ __all__ = [ ] # Different FFT Ops will be used for different block depths. -_FFT_OP = {1: math_ops.fft, 2: math_ops.fft2d, 3: math_ops.fft3d} -_IFFT_OP = {1: math_ops.ifft, 2: math_ops.ifft2d, 3: math_ops.ifft3d} +_FFT_OP = {1: fft_ops.fft, 2: fft_ops.fft2d, 3: fft_ops.fft3d} +_IFFT_OP = {1: fft_ops.ifft, 2: fft_ops.ifft2d, 3: fft_ops.ifft3d} # This is the only dtype allowed with fft ops. # TODO(langmore) Add other types once available. @@ -417,15 +418,13 @@ class _BaseLinearOperatorCirculant(linear_operator.LinearOperator): return math_ops.cast(y, self.dtype) def _determinant(self): - reduction_indices = [-(i + 1) for i in range(self.block_depth)] - det = math_ops.reduce_prod( - self.spectrum, reduction_indices=reduction_indices) + axis = [-(i + 1) for i in range(self.block_depth)] + det = math_ops.reduce_prod(self.spectrum, axis=axis) return math_ops.cast(det, self.dtype) def _log_abs_determinant(self): - reduction_indices = [-(i + 1) for i in range(self.block_depth)] - lad = math_ops.reduce_sum( - math_ops.log(self._abs_spectrum), reduction_indices=reduction_indices) + axis = [-(i + 1) for i in range(self.block_depth)] + lad = math_ops.reduce_sum(math_ops.log(self._abs_spectrum), axis=axis) return math_ops.cast(lad, self.dtype) def _solve(self, rhs, adjoint=False, adjoint_arg=False): diff --git a/tensorflow/python/ops/linalg/linear_operator_composition.py b/tensorflow/python/ops/linalg/linear_operator_composition.py index 0292bc51dc..f499b30661 100644 --- a/tensorflow/python/ops/linalg/linear_operator_composition.py +++ b/tensorflow/python/ops/linalg/linear_operator_composition.py @@ -275,6 +275,3 @@ class LinearOperatorComposition(linear_operator.LinearOperator): for operator in solve_order_list[1:]: solution = operator.solve(solution, adjoint=adjoint) return solution - - def _add_to_tensor(self, x): - return self.to_dense() + x diff --git a/tensorflow/python/ops/linalg/linear_operator_diag.py b/tensorflow/python/ops/linalg/linear_operator_diag.py index ed53decc00..be893c705c 100644 --- a/tensorflow/python/ops/linalg/linear_operator_diag.py +++ b/tensorflow/python/ops/linalg/linear_operator_diag.py @@ -228,11 +228,11 @@ class LinearOperatorDiag(linear_operator.LinearOperator): return diag_mat * x def _determinant(self): - return math_ops.reduce_prod(self._diag, reduction_indices=[-1]) + return math_ops.reduce_prod(self._diag, axis=[-1]) def _log_abs_determinant(self): log_det = math_ops.reduce_sum( - math_ops.log(math_ops.abs(self._diag)), reduction_indices=[-1]) + math_ops.log(math_ops.abs(self._diag)), axis=[-1]) if self.dtype.is_complex: log_det = math_ops.cast(log_det, dtype=self.dtype) return log_det diff --git a/tensorflow/python/ops/linalg/linear_operator_inversion.py b/tensorflow/python/ops/linalg/linear_operator_inversion.py new file mode 100644 index 0000000000..7aa4b40e16 --- /dev/null +++ b/tensorflow/python/ops/linalg/linear_operator_inversion.py @@ -0,0 +1,207 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Inverts a non-singular `LinearOperator`.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import ops +from tensorflow.python.ops.linalg import linear_operator +from tensorflow.python.util.tf_export import tf_export + +__all__ = [] + + +@tf_export("linalg.LinearOperatorInversion") +class LinearOperatorInversion(linear_operator.LinearOperator): + """`LinearOperator` representing the inverse of another operator. + + This operator represents the inverse of another operator. + + ```python + # Create a 2 x 2 linear operator. + operator = LinearOperatorFullMatrix([[1., 0.], [0., 2.]]) + operator_inv = LinearOperatorInversion(operator) + + operator_inv.to_dense() + ==> [[1., 0.] + [0., 0.5]] + + operator_inv.shape + ==> [2, 2] + + operator_inv.log_abs_determinant() + ==> - log(2) + + x = ... Shape [2, 4] Tensor + operator_inv.matmul(x) + ==> Shape [2, 4] Tensor, equal to operator.solve(x) + ``` + + #### Performance + + The performance of `LinearOperatorInversion` depends on the underlying + operators performance: `solve` and `matmul` are swapped, and determinant is + inverted. + + #### Matrix property hints + + This `LinearOperator` is initialized with boolean flags of the form `is_X`, + for `X = non_singular, self_adjoint, positive_definite, square`. + These have the following meaning: + + * If `is_X == True`, callers should expect the operator to have the + property `X`. This is a promise that should be fulfilled, but is *not* a + runtime assert. For example, finite floating point precision may result + in these promises being violated. + * If `is_X == False`, callers should expect the operator to not have `X`. + * If `is_X == None` (the default), callers should have no expectation either + way. + """ + + def __init__(self, + operator, + is_non_singular=None, + is_self_adjoint=None, + is_positive_definite=None, + is_square=None, + name=None): + r"""Initialize a `LinearOperatorInversion`. + + `LinearOperatorInversion` is initialized with an operator `A`. The `solve` + and `matmul` methods are effectively swapped. E.g. + + ``` + A = MyLinearOperator(...) + B = LinearOperatorInversion(A) + x = [....] # a vector + + assert A.matvec(x) == B.solvevec(x) + ``` + + Args: + operator: `LinearOperator` object. If `operator.is_non_singular == False`, + an exception is raised. We do allow `operator.is_non_singular == None`, + in which case this operator will have `is_non_singular == None`. + Similarly for `is_self_adjoint` and `is_positive_definite`. + is_non_singular: Expect that this operator is non-singular. + is_self_adjoint: Expect that this operator is equal to its hermitian + transpose. + is_positive_definite: Expect that this operator is positive definite, + meaning the quadratic form `x^H A x` has positive real part for all + nonzero `x`. Note that we do not require the operator to be + self-adjoint to be positive-definite. See: + https://en.wikipedia.org/wiki/Positive-definite_matrix#Extension_for_non-symmetric_matrices + is_square: Expect that this operator acts like square [batch] matrices. + name: A name for this `LinearOperator`. Default is `operator.name + + "_inv"`. + + Raises: + ValueError: If `operator.is_non_singular` is False. + """ + + self._operator = operator + + # Auto-set and check hints. + if operator.is_non_singular is False or is_non_singular is False: + raise ValueError( + "operator and supplied hints must have `is_non_singular` equal to " + "`True` or `None`. Found %s, %s" % (operator.is_non_singular, + is_non_singular)) + if operator.is_square is False or is_square is False: + raise ValueError( + "operator and supplied hints must have `is_square` equal to " + "`True` or `None`. Found %s, %s" % (operator.is_square, is_square)) + + # The congruency of is_non_singular and is_self_adjoint was checked in the + # base operator. Other hints are, in this special case of inversion, ones + # that must be the same for base/derived operator. + def _combined_hint(hint_str, provided_hint_value, message): + """Get combined hint in the case where operator.hint should equal hint.""" + op_hint = getattr(operator, hint_str) + if op_hint is False and provided_hint_value: + raise ValueError(message) + if op_hint and provided_hint_value is False: + raise ValueError(message) + return (op_hint or provided_hint_value) or None + + is_square = _combined_hint( + "is_square", is_square, + "An operator is square if and only if its inverse is square.") + + is_non_singular = _combined_hint( + "is_non_singular", is_non_singular, + "An operator is non-singular if and only if its inverse is " + "non-singular.") + + is_self_adjoint = _combined_hint( + "is_self_adjoint", is_self_adjoint, + "An operator is self-adjoint if and only if its inverse is " + "self-adjoint.") + + is_positive_definite = _combined_hint( + "is_positive_definite", is_positive_definite, + "An operator is positive-definite if and only if its inverse is " + "positive-definite.") + + is_square = _combined_hint( + "is_square", is_square, + "An operator is square if and only if its inverse is square.") + + # Initialization. + if name is None: + name = operator.name + "_inv" + with ops.name_scope(name, values=operator.graph_parents): + super(LinearOperatorInversion, self).__init__( + dtype=operator.dtype, + graph_parents=operator.graph_parents, + is_non_singular=is_non_singular, + is_self_adjoint=is_self_adjoint, + is_positive_definite=is_positive_definite, + is_square=is_square, + name=name) + + @property + def operator(self): + """The operator before inversion.""" + return self._operator + + def _assert_non_singular(self): + return self.operator.assert_non_singular() + + def _assert_positive_definite(self): + return self.operator.assert_positive_definite() + + def _assert_self_adjoint(self): + return self.operator.assert_self_adjoint() + + def _shape(self): + return self.operator.shape + + def _shape_tensor(self): + return self.operator.shape_tensor() + + def _matmul(self, x, adjoint=False, adjoint_arg=False): + return self.operator.solve(x, adjoint=adjoint, adjoint_arg=adjoint_arg) + + def _determinant(self): + return 1. / self.operator.determinant() + + def _log_abs_determinant(self): + return -1. * self.operator.log_abs_determinant() + + def _solve(self, rhs, adjoint=False, adjoint_arg=False): + return self.operator.matmul(rhs, adjoint=adjoint, adjoint_arg=adjoint_arg) diff --git a/tensorflow/python/ops/linalg/linear_operator_kronecker.py b/tensorflow/python/ops/linalg/linear_operator_kronecker.py index 1fd5073c17..f7e785caa5 100644 --- a/tensorflow/python/ops/linalg/linear_operator_kronecker.py +++ b/tensorflow/python/ops/linalg/linear_operator_kronecker.py @@ -30,9 +30,7 @@ from tensorflow.python.ops.linalg import linalg_impl as linalg from tensorflow.python.ops.linalg import linear_operator from tensorflow.python.util.tf_export import tf_export -__all__ = [ - "LinearOperatorKronecker", -] +__all__ = ["LinearOperatorKronecker"] def _vec(x): diff --git a/tensorflow/python/ops/linalg/linear_operator_low_rank_update.py b/tensorflow/python/ops/linalg/linear_operator_low_rank_update.py index c4288ff8f8..aa0500aff0 100644 --- a/tensorflow/python/ops/linalg/linear_operator_low_rank_update.py +++ b/tensorflow/python/ops/linalg/linear_operator_low_rank_update.py @@ -391,7 +391,7 @@ class LinearOperatorLowRankUpdate(linear_operator.LinearOperator): if self._use_cholesky: chol_cap_diag = array_ops.matrix_diag_part(self._chol_capacitance) log_abs_det_c = 2 * math_ops.reduce_sum( - math_ops.log(chol_cap_diag), reduction_indices=[-1]) + math_ops.log(chol_cap_diag), axis=[-1]) else: det_c = linalg_ops.matrix_determinant(self._capacitance) log_abs_det_c = math_ops.log(math_ops.abs(det_c)) diff --git a/tensorflow/python/ops/linalg/linear_operator_lower_triangular.py b/tensorflow/python/ops/linalg/linear_operator_lower_triangular.py index ca6d3f5405..d33fe17e04 100644 --- a/tensorflow/python/ops/linalg/linear_operator_lower_triangular.py +++ b/tensorflow/python/ops/linalg/linear_operator_lower_triangular.py @@ -195,11 +195,11 @@ class LinearOperatorLowerTriangular(linear_operator.LinearOperator): self._tril, x, adjoint_a=adjoint, adjoint_b=adjoint_arg) def _determinant(self): - return math_ops.reduce_prod(self._diag, reduction_indices=[-1]) + return math_ops.reduce_prod(self._diag, axis=[-1]) def _log_abs_determinant(self): return math_ops.reduce_sum( - math_ops.log(math_ops.abs(self._diag)), reduction_indices=[-1]) + math_ops.log(math_ops.abs(self._diag)), axis=[-1]) def _solve(self, rhs, adjoint=False, adjoint_arg=False): rhs = linalg.adjoint(rhs) if adjoint_arg else rhs diff --git a/tensorflow/python/ops/linalg/linear_operator_test_util.py b/tensorflow/python/ops/linalg/linear_operator_test_util.py index 76d659f109..e50f572b5f 100644 --- a/tensorflow/python/ops/linalg/linear_operator_test_util.py +++ b/tensorflow/python/ops/linalg/linear_operator_test_util.py @@ -102,7 +102,9 @@ class LinearOperatorDerivedClassTest(test.TestCase): raise NotImplementedError("operator_build_infos has not been implemented.") @abc.abstractmethod - def _operator_and_matrix(self, build_info, dtype, use_placeholder): + def _operator_and_matrix( + self, build_info, dtype, use_placeholder, + ensure_self_adjoint_and_pd=False): """Build a batch matrix and an Operator that should have similar behavior. Every operator acts like a (batch) matrix. This method returns both @@ -114,6 +116,11 @@ class LinearOperatorDerivedClassTest(test.TestCase): dtype: Numpy dtype. Data type of returned array/operator. use_placeholder: Python bool. If True, initialize the operator with a placeholder of undefined shape and correct dtype. + ensure_self_adjoint_and_pd: If `True`, + construct this operator to be Hermitian Positive Definite, as well + as ensuring the hints `is_positive_definite` and `is_self_adjoint` + are set. + This is useful for testing methods such as `cholesky`. Returns: operator: `LinearOperator` subclass instance. @@ -271,6 +278,21 @@ class LinearOperatorDerivedClassTest(test.TestCase): self._skip_if_tests_to_skip_contains("matmul_with_broadcast") self._test_matmul(with_batch=False) + def test_cholesky(self): + self._skip_if_tests_to_skip_contains("cholesky") + for use_placeholder in self._use_placeholder_options: + for build_info in self._operator_build_infos: + for dtype in self._dtypes_to_test: + with self.test_session(graph=ops.Graph()) as sess: + sess.graph.seed = random_seed.DEFAULT_GRAPH_SEED + operator, mat = self._operator_and_matrix( + build_info, dtype, use_placeholder=use_placeholder, + ensure_self_adjoint_and_pd=True) + op_chol = operator.cholesky().to_dense() + mat_chol = linalg_ops.cholesky(mat) + op_chol_v, mat_chol_v = sess.run([op_chol, mat_chol]) + self.assertAC(mat_chol_v, op_chol_v) + def _test_solve(self, with_batch): for use_placeholder in self._use_placeholder_options: for build_info in self._operator_build_infos: @@ -441,7 +463,7 @@ class NonSquareLinearOperatorDerivedClassTest(LinearOperatorDerivedClassTest): @property def _tests_to_skip(self): """List of test names to skip.""" - return ["solve", "solve_with_broadcast", "det", "log_abs_det"] + return ["cholesky", "solve", "solve_with_broadcast", "det", "log_abs_det"] @property def _operator_build_infos(self): diff --git a/tensorflow/python/ops/linalg/matmul_registrations.py b/tensorflow/python/ops/linalg/matmul_registrations.py new file mode 100644 index 0000000000..e0ac988ba2 --- /dev/null +++ b/tensorflow/python/ops/linalg/matmul_registrations.py @@ -0,0 +1,252 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Registrations for LinearOperator.matmul.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.ops.linalg import linear_operator +from tensorflow.python.ops.linalg import linear_operator_algebra +from tensorflow.python.ops.linalg import linear_operator_circulant +from tensorflow.python.ops.linalg import linear_operator_composition +from tensorflow.python.ops.linalg import linear_operator_diag +from tensorflow.python.ops.linalg import linear_operator_identity +from tensorflow.python.ops.linalg import linear_operator_lower_triangular +from tensorflow.python.ops.linalg import linear_operator_zeros + + +def _combined_self_adjoint_hint(operator_a, operator_b): + """Get combined hint for self-adjoint-ness.""" + # Note: only use this method in the commuting case. + # The property is preserved under composition when the operators commute. + if operator_a.is_self_adjoint and operator_b.is_self_adjoint: + return True + + # The property is not preserved when an operator with the property is composed + # with an operator without the property. + if ((operator_a.is_self_adjoint is True and + operator_b.is_self_adjoint is False) or + (operator_a.is_self_adjoint is False and + operator_b.is_self_adjoint is True)): + return False + + # The property is not known when operators are not known to have the property + # or both operators don't have the property (the property for the complement + # class is not closed under composition). + return None + + +def _is_square(operator_a, operator_b): + """Return a hint to whether the composition is square.""" + if operator_a.is_square and operator_b.is_square: + return True + if operator_a.is_square is False and operator_b.is_square is False: + # Let A have shape [B, M, N], B have shape [B, N, L]. + m = operator_a.range_dimension + l = operator_b.domain_dimension + if m is not None and l is not None: + return m == l + + return None + + +def _combined_positive_definite_hint(operator_a, operator_b): + """Get combined PD hint for compositions.""" + # Note: Positive definiteness is only guaranteed to be preserved + # when the operators commute and are symmetric. Only use this method in + # commuting cases. + + if (operator_a.is_positive_definite is True and + operator_a.is_self_adjoint is True and + operator_b.is_positive_definite is True and + operator_b.is_self_adjoint is True): + return True + + return None + + +def _combined_non_singular_hint(operator_a, operator_b): + """Get combined hint for when .""" + # If either operator is not-invertible the composition isn't. + if (operator_a.is_non_singular is False or + operator_b.is_non_singular is False): + return False + + return operator_a.is_non_singular and operator_b.is_non_singular + + +# By default, use a LinearOperatorComposition to delay the computation. +@linear_operator_algebra.RegisterMatmul( + linear_operator.LinearOperator, linear_operator.LinearOperator) +def _matmul_linear_operator(linop_a, linop_b): + """Generic matmul of two `LinearOperator`s.""" + is_square = _is_square(linop_a, linop_b) + is_non_singular = None + is_self_adjoint = None + is_positive_definite = None + + if is_square: + is_non_singular = _combined_non_singular_hint(linop_a, linop_b) + is_self_adjoint = _combined_self_adjoint_hint(linop_a, linop_b) + elif is_square is False: + is_non_singular = False + is_self_adjoint = False + is_positive_definite = False + + return linear_operator_composition.LinearOperatorComposition( + operators=[linop_a, linop_b], + is_non_singular=is_non_singular, + is_self_adjoint=is_self_adjoint, + is_positive_definite=is_positive_definite, + is_square=is_square, + ) + +# Identity + + +@linear_operator_algebra.RegisterMatmul( + linear_operator_identity.LinearOperatorIdentity, + linear_operator.LinearOperator) +def _matmul_linear_operator_identity_left(identity, linop): + del identity + return linop + + +@linear_operator_algebra.RegisterMatmul( + linear_operator.LinearOperator, + linear_operator_identity.LinearOperatorIdentity) +def _matmul_linear_operator_identity_right(linop, identity): + del identity + return linop + + +# Zeros + + +@linear_operator_algebra.RegisterMatmul( + linear_operator.LinearOperator, + linear_operator_zeros.LinearOperatorZeros) +def _matmul_linear_operator_zeros_right(linop, zeros): + if not zeros.is_square or not linop.is_square: + raise ValueError("Matmul with non-square `LinearOperator`s or non-square " + "`LinearOperatorZeros` not supported at this time.") + return zeros + + +@linear_operator_algebra.RegisterMatmul( + linear_operator_zeros.LinearOperatorZeros, + linear_operator.LinearOperator) +def _matmul_linear_operator_zeros_left(zeros, linop): + if not zeros.is_square or not linop.is_square: + raise ValueError("Matmul with non-square `LinearOperator`s or non-square " + "`LinearOperatorZeros` not supported at this time.") + return zeros + + +# Diag. + + +@linear_operator_algebra.RegisterMatmul( + linear_operator_diag.LinearOperatorDiag, + linear_operator_diag.LinearOperatorDiag) +def _matmul_linear_operator_diag(linop_a, linop_b): + return linear_operator_diag.LinearOperatorDiag( + diag=linop_a.diag * linop_b.diag, + is_non_singular=_combined_non_singular_hint(linop_a, linop_b), + is_self_adjoint=_combined_self_adjoint_hint( + linop_a, linop_b), + is_positive_definite=_combined_positive_definite_hint( + linop_a, linop_b), + is_square=True) + + +@linear_operator_algebra.RegisterMatmul( + linear_operator_diag.LinearOperatorDiag, + linear_operator_identity.LinearOperatorScaledIdentity) +def _matmul_linear_operator_diag_scaled_identity_right( + linop_diag, linop_scaled_identity): + return linear_operator_diag.LinearOperatorDiag( + diag=linop_diag.diag * linop_scaled_identity.multiplier, + is_non_singular=_combined_non_singular_hint( + linop_diag, linop_scaled_identity), + is_self_adjoint=_combined_self_adjoint_hint( + linop_diag, linop_scaled_identity), + is_positive_definite=_combined_positive_definite_hint( + linop_diag, linop_scaled_identity), + is_square=True) + + +@linear_operator_algebra.RegisterMatmul( + linear_operator_identity.LinearOperatorScaledIdentity, + linear_operator_diag.LinearOperatorDiag) +def _matmul_linear_operator_diag_scaled_identity_left( + linop_scaled_identity, linop_diag): + return linear_operator_diag.LinearOperatorDiag( + diag=linop_diag.diag * linop_scaled_identity.multiplier, + is_non_singular=_combined_non_singular_hint( + linop_diag, linop_scaled_identity), + is_self_adjoint=_combined_self_adjoint_hint( + linop_diag, linop_scaled_identity), + is_positive_definite=_combined_positive_definite_hint( + linop_diag, linop_scaled_identity), + is_square=True) + + +@linear_operator_algebra.RegisterMatmul( + linear_operator_diag.LinearOperatorDiag, + linear_operator_lower_triangular.LinearOperatorLowerTriangular) +def _matmul_linear_operator_diag_tril(linop_diag, linop_triangular): + return linear_operator_lower_triangular.LinearOperatorLowerTriangular( + tril=linop_diag.diag[..., None] * linop_triangular.to_dense(), + is_non_singular=_combined_non_singular_hint( + linop_diag, linop_triangular), + # This is safe to do since the Triangular matrix is only self-adjoint + # when it is a diagonal matrix, and hence commutes. + is_self_adjoint=_combined_self_adjoint_hint( + linop_diag, linop_triangular), + is_positive_definite=None, + is_square=True) + + +@linear_operator_algebra.RegisterMatmul( + linear_operator_lower_triangular.LinearOperatorLowerTriangular, + linear_operator_diag.LinearOperatorDiag) +def _matmul_linear_operator_tril_diag(linop_triangular, linop_diag): + return linear_operator_lower_triangular.LinearOperatorLowerTriangular( + tril=linop_triangular.to_dense() * linop_diag.diag, + is_non_singular=_combined_non_singular_hint( + linop_diag, linop_triangular), + # This is safe to do since the Triangular matrix is only self-adjoint + # when it is a diagonal matrix, and hence commutes. + is_self_adjoint=_combined_self_adjoint_hint( + linop_diag, linop_triangular), + is_positive_definite=None, + is_square=True) + +# Circulant. + + +@linear_operator_algebra.RegisterMatmul( + linear_operator_circulant.LinearOperatorCirculant, + linear_operator_circulant.LinearOperatorCirculant) +def _matmul_linear_operator_circulant_circulant(linop_a, linop_b): + return linear_operator_circulant.LinearOperatorCirculant( + spectrum=linop_a.spectrum * linop_b.spectrum, + is_non_singular=_combined_non_singular_hint(linop_a, linop_b), + is_self_adjoint=_combined_self_adjoint_hint(linop_a, linop_b), + is_positive_definite=_combined_positive_definite_hint( + linop_a, linop_b), + is_square=True) diff --git a/tensorflow/python/ops/linalg_ops.py b/tensorflow/python/ops/linalg_ops.py index bbccc7e036..1a9e7112b4 100644 --- a/tensorflow/python/ops/linalg_ops.py +++ b/tensorflow/python/ops/linalg_ops.py @@ -423,7 +423,78 @@ def svd(tensor, full_matrices=False, compute_uv=True, name=None): # pylint: disable=redefined-builtin -@tf_export('norm', 'linalg.norm') +@tf_export('norm', 'linalg.norm', v1=[]) +def norm_v2(tensor, + ord='euclidean', + axis=None, + keepdims=None, + name=None): + r"""Computes the norm of vectors, matrices, and tensors. + + This function can compute several different vector norms (the 1-norm, the + Euclidean or 2-norm, the inf-norm, and in general the p-norm for p > 0) and + matrix norms (Frobenius, 1-norm, 2-norm and inf-norm). + + Args: + tensor: `Tensor` of types `float32`, `float64`, `complex64`, `complex128` + ord: Order of the norm. Supported values are 'fro', 'euclidean', + `1`, `2`, `np.inf` and any positive real number yielding the corresponding + p-norm. Default is 'euclidean' which is equivalent to Frobenius norm if + `tensor` is a matrix and equivalent to 2-norm for vectors. + Some restrictions apply: + a) The Frobenius norm `fro` is not defined for vectors, + b) If axis is a 2-tuple (matrix norm), only 'euclidean', 'fro', `1`, + `2`, `np.inf` are supported. + See the description of `axis` on how to compute norms for a batch of + vectors or matrices stored in a tensor. + axis: If `axis` is `None` (the default), the input is considered a vector + and a single vector norm is computed over the entire set of values in the + tensor, i.e. `norm(tensor, ord=ord)` is equivalent to + `norm(reshape(tensor, [-1]), ord=ord)`. + If `axis` is a Python integer, the input is considered a batch of vectors, + and `axis` determines the axis in `tensor` over which to compute vector + norms. + If `axis` is a 2-tuple of Python integers it is considered a batch of + matrices and `axis` determines the axes in `tensor` over which to compute + a matrix norm. + Negative indices are supported. Example: If you are passing a tensor that + can be either a matrix or a batch of matrices at runtime, pass + `axis=[-2,-1]` instead of `axis=None` to make sure that matrix norms are + computed. + keepdims: If True, the axis indicated in `axis` are kept with size 1. + Otherwise, the dimensions in `axis` are removed from the output shape. + name: The name of the op. + + Returns: + output: A `Tensor` of the same type as tensor, containing the vector or + matrix norms. If `keepdims` is True then the rank of output is equal to + the rank of `tensor`. Otherwise, if `axis` is none the output is a scalar, + if `axis` is an integer, the rank of `output` is one less than the rank + of `tensor`, if `axis` is a 2-tuple the rank of `output` is two less + than the rank of `tensor`. + + Raises: + ValueError: If `ord` or `axis` is invalid. + + @compatibility(numpy) + Mostly equivalent to numpy.linalg.norm. + Not supported: ord <= 0, 2-norm for matrices, nuclear norm. + Other differences: + a) If axis is `None`, treats the flattened `tensor` as a vector + regardless of rank. + b) Explicitly supports 'euclidean' norm as the default, including for + higher order tensors. + @end_compatibility + """ + return norm(tensor=tensor, + ord=ord, + axis=axis, + keepdims=keepdims, + name=name) + + +# pylint: disable=redefined-builtin +@tf_export(v1=['norm', 'linalg.norm']) @deprecation.deprecated_args( None, 'keep_dims is deprecated, use keepdims instead', 'keep_dims') def norm(tensor, diff --git a/tensorflow/python/ops/list_ops.py b/tensorflow/python/ops/list_ops.py index b4a1fc6af6..dbaae886d4 100644 --- a/tensorflow/python/ops/list_ops.py +++ b/tensorflow/python/ops/list_ops.py @@ -21,6 +21,7 @@ from __future__ import print_function from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_shape from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_list_ops # go/tf-wildcard-import @@ -29,7 +30,9 @@ from tensorflow.python.ops.gen_list_ops import * # pylint: enable=wildcard-import -ops.NotDifferentiable("TensorListConcat") +ops.NotDifferentiable("TensorListConcatLists") +ops.NotDifferentiable("TensorListElementShape") +ops.NotDifferentiable("TensorListLength") ops.NotDifferentiable("TensorListPushBackBatch") @@ -41,12 +44,42 @@ def empty_tensor_list(element_shape, max_num_elements = -1 return gen_list_ops.empty_tensor_list( - element_shape=element_shape, + element_shape=_build_element_shape(element_shape), element_dtype=element_dtype, max_num_elements=max_num_elements, name=name) +def tensor_list_reserve(element_shape, num_elements, element_dtype, name=None): + return gen_list_ops.tensor_list_reserve( + element_shape=_build_element_shape(element_shape), + num_elements=num_elements, + element_dtype=element_dtype, + name=name) + + +def tensor_list_from_tensor(tensor, element_shape, name=None): + return gen_list_ops.tensor_list_from_tensor( + tensor=tensor, + element_shape=_build_element_shape(element_shape), + name=name) + + +def tensor_list_concat(input_handle, element_dtype, name=None): + # Ignore the lengths output of TensorListConcat. It is only used during + # gradient computation. + return gen_list_ops.tensor_list_concat( + input_handle=input_handle, element_dtype=element_dtype, name=name)[0] + + +def tensor_list_split(tensor, element_shape, lengths, name=None): + return gen_list_ops.tensor_list_split( + tensor=tensor, + element_shape=_build_element_shape(element_shape), + lengths=lengths, + name=name) + + @ops.RegisterGradient("TensorListPushBack") def _PushBackGrad(op, dresult): return gen_list_ops.tensor_list_pop_back( @@ -65,14 +98,32 @@ def _PopBackGrad(op, dlist, delement): @ops.RegisterGradient("TensorListStack") def _TensorListStackGrad(unused_op, dtensor): - return gen_list_ops.tensor_list_from_tensor(dtensor, - element_shape=dtensor.shape[1:]) + return tensor_list_from_tensor(dtensor, element_shape=dtensor.shape[1:]) + + +@ops.RegisterGradient("TensorListConcat") +def _TensorListConcatGrad(op, dtensor, unused_dlengths): + # TODO(srbs): We lose the element_shape information in tensor_list_concat. + # Consider providing that as an output of TensorListConcat? + if dtensor.shape.rank is None: + element_shape = None + else: + element_shape = [None] + dtensor.shape.as_list()[1:] + return tensor_list_split( + dtensor, + element_shape=_build_element_shape(element_shape), + lengths=op.outputs[1]) + + +@ops.RegisterGradient("TensorListSplit") +def _TensorListSplitGrad(op, dlist): + return tensor_list_concat(dlist, element_dtype=op.inputs[0].dtype), None, None @ops.RegisterGradient("TensorListFromTensor") def _TensorListFromTensorGrad(op, dlist): """Gradient for TensorListFromTensor.""" - if op.inputs[0].shape.dims[0].value is not None: + if op.inputs[0].shape.dims and op.inputs[0].shape.dims[0].value is not None: num_elements = op.inputs[0].shape.dims[0].value else: num_elements = None @@ -126,3 +177,40 @@ def _TensorListScatterGrad(op, dlist): t, indices, _ = op.inputs return gen_list_ops.tensor_list_gather( dlist, indices, element_dtype=t.dtype), None + + +def _build_element_shape(shape): + """Converts shape to a format understood by list_ops for element_shape. + + If `shape` is already a `Tensor` it is returned as-is. We do not perform a + type check here. + + If shape is None or a TensorShape with unknown rank, -1 is returned. + + If shape is a scalar, an int32 tensor with empty list is returned. Note we + do directly return an empty list since ops.convert_to_tensor would conver it + to a float32 which is not a valid type for element_shape. + + If shape is a sequence of dims, None's in the list are replaced with -1. We + do not check the dtype of the other dims. + + Args: + shape: Could be None, Tensor, TensorShape or a list of dims (each dim could + be a None, scalar or Tensor). + + Returns: + A None-free shape that can be converted to a tensor. + """ + if isinstance(shape, ops.Tensor): + return shape + if isinstance(shape, tensor_shape.TensorShape): + # `TensorShape.as_list` requires rank to be known. + shape = shape.as_list() if shape else None + # Shape is unknown. + if shape is None: + return -1 + # Shape is a scalar. + if not shape: + return ops.convert_to_tensor(shape, dtype=dtypes.int32) + # Shape is a sequence of dimensions. Convert None dims to -1. + return [d if d is not None else -1 for d in shape] diff --git a/tensorflow/python/ops/lookup_ops.py b/tensorflow/python/ops/lookup_ops.py index 397d56ef40..758cb8041d 100644 --- a/tensorflow/python/ops/lookup_ops.py +++ b/tensorflow/python/ops/lookup_ops.py @@ -39,6 +39,7 @@ from tensorflow.python.ops import string_ops # pylint: disable=wildcard-import from tensorflow.python.ops.gen_lookup_ops import * # pylint: enable=wildcard-import +from tensorflow.python.training.checkpointable import base as checkpointable_base from tensorflow.python.training.checkpointable import tracking as checkpointable from tensorflow.python.util import compat from tensorflow.python.util.deprecation import deprecated @@ -160,7 +161,9 @@ class InitializableLookupTableBase(LookupInterface): self._default_value = ops.convert_to_tensor( default_value, dtype=self._value_dtype) self._default_value.get_shape().merge_with(tensor_shape.scalar()) - self._initializer = initializer + if isinstance(initializer, checkpointable_base.CheckpointableBase): + self._initializer = self._track_checkpointable( + initializer, "_initializer") self._resource_handle = self.create_resource() self._init_op = self.initialize() @@ -309,7 +312,7 @@ class HashTable(InitializableLookupTableBase): return exported_keys, exported_values -class TableInitializerBase(object): +class TableInitializerBase(checkpointable_base.CheckpointableBase): """Base class for lookup table initializers.""" def __init__(self, key_dtype, value_dtype): @@ -522,12 +525,14 @@ class TextFileInitializer(TableInitializerBase): if (vocab_size is not None) and (vocab_size <= 0): raise ValueError("Invalid vocab_size %s." % vocab_size) - self._filename = filename self._key_index = key_index self._value_index = value_index self._vocab_size = vocab_size self._delimiter = delimiter self._name = name + self._filename = self._track_checkpointable( + checkpointable.TrackableAsset(filename), + "_filename") super(TextFileInitializer, self).__init__(key_dtype, value_dtype) diff --git a/tensorflow/python/ops/losses/losses_impl.py b/tensorflow/python/ops/losses/losses_impl.py index 53c09ee8dd..9e9de62e6c 100644 --- a/tensorflow/python/ops/losses/losses_impl.py +++ b/tensorflow/python/ops/losses/losses_impl.py @@ -18,7 +18,6 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.python.compat import compat from tensorflow.python.eager import context from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops @@ -34,28 +33,48 @@ from tensorflow.python.util.deprecation import deprecated_argument_lookup from tensorflow.python.util.tf_export import tf_export -@tf_export("losses.Reduction") +@tf_export("losses.Reduction", "keras.losses.Reduction", v1=[]) +class ReductionV2(object): + """Types of loss reduction. + + Contains the following values: + `NONE`: Un-reduced weighted losses with the same shape as input. + `SUM`: Scalar sum of weighted losses. + `SUM_OVER_BATCH_SIZE`: Scalar `SUM` divided by number of elements in losses. + """ + + NONE = "none" + SUM = "sum" + SUM_OVER_BATCH_SIZE = "sum_over_batch_size" + + @classmethod + def all(cls): + return (cls.NONE, cls.SUM, cls.SUM_OVER_BATCH_SIZE) + + @classmethod + def validate(cls, key): + if key not in cls.all(): + raise ValueError("Invalid Reduction Key %s." % key) + + +@tf_export(v1=["losses.Reduction"]) class Reduction(object): """Types of loss reduction. Contains the following values: `NONE`: Un-reduced weighted losses with the same shape as input. `SUM`: Scalar sum of weighted losses. - `MEAN`: Scalar `SUM` divided by sum of weights. + `MEAN`: Scalar `SUM` divided by sum of weights. DEPRECATED. `SUM_OVER_BATCH_SIZE`: Scalar `SUM` divided by number of elements in losses. `SUM_OVER_NONZERO_WEIGHTS`: Scalar `SUM` divided by number of non-zero - weights. + weights. DEPRECATED. `SUM_BY_NONZERO_WEIGHTS`: Same as `SUM_OVER_NONZERO_WEIGHTS`. """ NONE = "none" - SUM = "weighted_sum" - - MEAN = "weighted_mean" - SUM_OVER_BATCH_SIZE = "weighted_sum_over_batch_size" - + MEAN = "weighted_mean" SUM_BY_NONZERO_WEIGHTS = "weighted_sum_by_nonzero_weights" SUM_OVER_NONZERO_WEIGHTS = SUM_BY_NONZERO_WEIGHTS @@ -72,35 +91,7 @@ class Reduction(object): @classmethod def validate(cls, key): if key not in cls.all(): - raise ValueError("Invalid ReductionKey %s." % key) - - -def _safe_div(numerator, denominator, name="value"): - """Computes a safe divide which returns 0 if the denominator is zero. - - Note that the function contains an additional conditional check that is - necessary for avoiding situations where the loss is zero causing NaNs to - creep into the gradient computation. - - Args: - numerator: An arbitrary `Tensor`. - denominator: A `Tensor` whose shape matches `numerator` and whose values are - assumed to be non-negative. - name: An optional name for the returned op. - - Returns: - The element-wise value of the numerator divided by the denominator. - """ - if compat.forward_compatible(2018, 11, 1): - return math_ops.div_no_nan(numerator, denominator, name=name) - return array_ops.where( - math_ops.greater(denominator, 0), - math_ops.div(numerator, - array_ops.where( - math_ops.equal(denominator, 0), - array_ops.ones_like(denominator), denominator)), - array_ops.zeros_like(numerator), - name=name) + raise ValueError("Invalid Reduction Key %s." % key) def _safe_mean(losses, num_present): @@ -115,7 +106,7 @@ def _safe_mean(losses, num_present): then zero is returned. """ total_loss = math_ops.reduce_sum(losses) - return _safe_div(total_loss, num_present) + return math_ops.div_no_nan(total_loss, num_present, name="value") def _num_present(losses, weights, per_batch=False): @@ -166,7 +157,7 @@ def _num_elements(losses): return math_ops.cast(array_ops.size(losses, name=scope), dtype=losses.dtype) -@tf_export("losses.compute_weighted_loss") +@tf_export(v1=["losses.compute_weighted_loss"]) def compute_weighted_loss( losses, weights=1.0, scope=None, loss_collection=ops.GraphKeys.LOSSES, reduction=Reduction.SUM_BY_NONZERO_WEIGHTS): @@ -236,7 +227,7 @@ def compute_weighted_loss( return loss -@tf_export("losses.absolute_difference") +@tf_export(v1=["losses.absolute_difference"]) def absolute_difference( labels, predictions, weights=1.0, scope=None, loss_collection=ops.GraphKeys.LOSSES, @@ -289,7 +280,7 @@ def absolute_difference( losses, weights, scope, loss_collection, reduction=reduction) -@tf_export("losses.cosine_distance") +@tf_export(v1=["losses.cosine_distance"]) @deprecated_args(None, "dim is deprecated, use axis instead", "dim") def cosine_distance( labels, predictions, axis=None, weights=1.0, scope=None, @@ -345,7 +336,7 @@ def cosine_distance( losses, weights, scope, loss_collection, reduction=reduction) -@tf_export("losses.hinge_loss") +@tf_export(v1=["losses.hinge_loss"]) def hinge_loss(labels, logits, weights=1.0, scope=None, loss_collection=ops.GraphKeys.LOSSES, reduction=Reduction.SUM_BY_NONZERO_WEIGHTS): @@ -395,7 +386,7 @@ def hinge_loss(labels, logits, weights=1.0, scope=None, losses, weights, scope, loss_collection, reduction=reduction) -@tf_export("losses.huber_loss") +@tf_export(v1=["losses.huber_loss"]) def huber_loss(labels, predictions, weights=1.0, delta=1.0, scope=None, loss_collection=ops.GraphKeys.LOSSES, reduction=Reduction.SUM_BY_NONZERO_WEIGHTS): @@ -473,7 +464,7 @@ def huber_loss(labels, predictions, weights=1.0, delta=1.0, scope=None, losses, weights, scope, loss_collection, reduction=reduction) -@tf_export("losses.log_loss") +@tf_export(v1=["losses.log_loss"]) def log_loss(labels, predictions, weights=1.0, epsilon=1e-7, scope=None, loss_collection=ops.GraphKeys.LOSSES, reduction=Reduction.SUM_BY_NONZERO_WEIGHTS): @@ -530,7 +521,7 @@ def log_loss(labels, predictions, weights=1.0, epsilon=1e-7, scope=None, # TODO(b/37208492): Add reduction arg. -@tf_export("losses.mean_pairwise_squared_error") +@tf_export(v1=["losses.mean_pairwise_squared_error"]) def mean_pairwise_squared_error( labels, predictions, weights=1.0, scope=None, loss_collection=ops.GraphKeys.LOSSES): @@ -595,26 +586,24 @@ def mean_pairwise_squared_error( diffs = math_ops.subtract(predictions, labels) - reduction_indices = math_ops.range(1, array_ops.rank(diffs)) + axis = math_ops.range(1, array_ops.rank(diffs)) sum_squares_diff_per_batch = math_ops.reduce_sum( - math_ops.square(diffs), - reduction_indices=reduction_indices, - keepdims=True) + math_ops.square(diffs), axis=axis, keepdims=True) num_present_per_batch = _num_present(diffs, weights, per_batch=True) - term1 = 2.0 * _safe_div( + term1 = 2.0 * math_ops.div_no_nan( sum_squares_diff_per_batch, - math_ops.maximum(num_present_per_batch - 1, 0)) + math_ops.maximum(num_present_per_batch - 1, 0), + name="value") - sum_diff = math_ops.reduce_sum( - diffs, reduction_indices=reduction_indices, keepdims=True) - term2 = 2.0 * _safe_div( + sum_diff = math_ops.reduce_sum(diffs, axis=axis, keepdims=True) + term2 = 2.0 * math_ops.div_no_nan( math_ops.square(sum_diff), math_ops.maximum( math_ops.multiply(num_present_per_batch, - num_present_per_batch - 1), - 0)) + num_present_per_batch - 1), 0), + name="value") weighted_losses = math_ops.multiply(term1 - term2, weights) loss = math_ops.reduce_sum(weighted_losses) @@ -628,7 +617,7 @@ def mean_pairwise_squared_error( return mean_loss -@tf_export("losses.mean_squared_error") +@tf_export(v1=["losses.mean_squared_error"]) def mean_squared_error( labels, predictions, weights=1.0, scope=None, loss_collection=ops.GraphKeys.LOSSES, @@ -681,7 +670,7 @@ def mean_squared_error( losses, weights, scope, loss_collection, reduction=reduction) -@tf_export("losses.sigmoid_cross_entropy") +@tf_export(v1=["losses.sigmoid_cross_entropy"]) def sigmoid_cross_entropy( multi_class_labels, logits, weights=1.0, label_smoothing=0, scope=None, loss_collection=ops.GraphKeys.LOSSES, @@ -745,7 +734,7 @@ def sigmoid_cross_entropy( losses, weights, scope, loss_collection, reduction=reduction) -@tf_export("losses.softmax_cross_entropy") +@tf_export(v1=["losses.softmax_cross_entropy"]) def softmax_cross_entropy( onehot_labels, logits, weights=1.0, label_smoothing=0, scope=None, loss_collection=ops.GraphKeys.LOSSES, @@ -867,7 +856,7 @@ def _remove_squeezable_dimensions( return labels, predictions, weights -@tf_export("losses.sparse_softmax_cross_entropy") +@tf_export(v1=["losses.sparse_softmax_cross_entropy"]) def sparse_softmax_cross_entropy( labels, logits, weights=1.0, scope=None, loss_collection=ops.GraphKeys.LOSSES, diff --git a/tensorflow/python/ops/losses/util_test.py b/tensorflow/python/ops/losses/util_test.py index df2e60e2e4..22a8eaae26 100644 --- a/tensorflow/python/ops/losses/util_test.py +++ b/tensorflow/python/ops/losses/util_test.py @@ -20,12 +20,14 @@ from __future__ import print_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops.losses import util from tensorflow.python.platform import test class LossesUtilTest(test.TestCase): + @test_util.run_deprecated_v1 def testGetRegularizationLoss(self): # Empty regularization collection should evaluate to 0.0. with self.cached_session(): diff --git a/tensorflow/python/ops/math_grad.py b/tensorflow/python/ops/math_grad.py index 35278d9680..c7ec1c57d1 100644 --- a/tensorflow/python/ops/math_grad.py +++ b/tensorflow/python/ops/math_grad.py @@ -1041,11 +1041,12 @@ def _PowGrad(op, grad): # Avoid false singularity at x = 0 if x.dtype.is_complex: # real(x) < 0 is fine for the complex case - log_x = array_ops.where( - math_ops.not_equal(x, 0), math_ops.log(x), array_ops.zeros_like(x)) + mask = math_ops.not_equal(x, 0) else: # There's no sensible real value to return if x < 0, so return 0 - log_x = array_ops.where(x > 0, math_ops.log(x), array_ops.zeros_like(x)) + mask = x > 0 + safe_x = array_ops.where(mask, x, array_ops.ones_like(x)) + log_x = array_ops.where(mask, math_ops.log(safe_x), array_ops.zeros_like(x)) gy = array_ops.reshape(math_ops.reduce_sum(grad * z * log_x, ry), sy) return gx, gy diff --git a/tensorflow/python/ops/math_grad_test.py b/tensorflow/python/ops/math_grad_test.py index d1fe834fc7..822f89768c 100644 --- a/tensorflow/python/ops/math_grad_test.py +++ b/tensorflow/python/ops/math_grad_test.py @@ -20,9 +20,13 @@ from __future__ import print_function import numpy as np +from tensorflow.python.eager import backprop +from tensorflow.python.eager import context +from tensorflow.python.eager import execution_callbacks from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients @@ -52,6 +56,7 @@ class SquaredDifferenceOpTest(test.TestCase): self.assertLess(left_err, 1e-10) self.assertLess(right_err, 1e-10) + @test_util.run_deprecated_v1 def testGrad(self): self._testGrad([1, 2, 3, 2], [3, 2]) self._testGrad([2, 4], [3, 2, 4]) @@ -83,6 +88,7 @@ class AbsOpTest(test.TestCase): value, shape, output, output.get_shape().as_list()) self.assertLess(error, max_error) + @test_util.run_deprecated_v1 def testComplexAbs(self): # Bias random test values away from zero to avoid numeric instabilities. self._testGrad( @@ -99,6 +105,7 @@ class AbsOpTest(test.TestCase): class MinOrMaxGradientTest(test.TestCase): + @test_util.run_deprecated_v1 def testMinGradient(self): inputs = constant_op.constant([1.0], dtype=dtypes.float32) outputs = math_ops.reduce_min(array_ops.concat([inputs, inputs], 0)) @@ -106,6 +113,7 @@ class MinOrMaxGradientTest(test.TestCase): error = gradient_checker.compute_gradient_error(inputs, [1], outputs, []) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testMaxGradient(self): inputs = constant_op.constant([1.0], dtype=dtypes.float32) outputs = math_ops.reduce_max(array_ops.concat([inputs, inputs], 0)) @@ -116,6 +124,7 @@ class MinOrMaxGradientTest(test.TestCase): class MaximumOrMinimumGradientTest(test.TestCase): + @test_util.run_deprecated_v1 def testMaximumGradient(self): inputs = constant_op.constant([1.0, 2.0, 3.0, 4.0], dtype=dtypes.float32) outputs = math_ops.maximum(inputs, 3.0) @@ -123,6 +132,7 @@ class MaximumOrMinimumGradientTest(test.TestCase): error = gradient_checker.compute_gradient_error(inputs, [4], outputs, [4]) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testMinimumGradient(self): inputs = constant_op.constant([1.0, 2.0, 3.0, 4.0], dtype=dtypes.float32) outputs = math_ops.minimum(inputs, 2.0) @@ -133,6 +143,7 @@ class MaximumOrMinimumGradientTest(test.TestCase): class ProdGradientTest(test.TestCase): + @test_util.run_deprecated_v1 def testProdGradient(self): inputs = constant_op.constant([[1., 2.], [3., 4.]], dtype=dtypes.float32) @@ -143,6 +154,7 @@ class ProdGradientTest(test.TestCase): outputs, outputs.get_shape().as_list()) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testProdGradientForNegativeAxis(self): inputs = constant_op.constant([[1., 2.], [3., 4.]], dtype=dtypes.float32) @@ -153,6 +165,7 @@ class ProdGradientTest(test.TestCase): outputs, outputs.get_shape().as_list()) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testProdGradientComplex(self): for dtype in dtypes.complex64, dtypes.complex128: inputs = constant_op.constant([[1 + 3j, 2 - 1j], [3j, 4]], @@ -164,6 +177,7 @@ class ProdGradientTest(test.TestCase): outputs, outputs.get_shape().as_list()) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testProdGradientForNegativeAxisComplex(self): for dtype in dtypes.complex64, dtypes.complex128: inputs = constant_op.constant([[1 + 3j, 2 - 1j], [3j, 4]], @@ -178,6 +192,7 @@ class ProdGradientTest(test.TestCase): class SegmentMinOrMaxGradientTest(test.TestCase): + @test_util.run_deprecated_v1 def testSegmentMinGradient(self): data = constant_op.constant([1.0, 2.0, 3.0], dtype=dtypes.float32) segment_ids = constant_op.constant([0, 0, 1], dtype=dtypes.int64) @@ -187,6 +202,7 @@ class SegmentMinOrMaxGradientTest(test.TestCase): [2]) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testSegmentMaxGradient(self): data = constant_op.constant([1.0, 2.0, 3.0], dtype=dtypes.float32) segment_ids = constant_op.constant([0, 0, 1], dtype=dtypes.int64) @@ -196,6 +212,7 @@ class SegmentMinOrMaxGradientTest(test.TestCase): [2]) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testSegmentMinGradientWithTies(self): inputs = constant_op.constant([1.0], dtype=dtypes.float32) data = array_ops.concat([inputs, inputs], 0) @@ -206,6 +223,7 @@ class SegmentMinOrMaxGradientTest(test.TestCase): [1]) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testSegmentMaxGradientWithTies(self): inputs = constant_op.constant([1.0], dtype=dtypes.float32) data = array_ops.concat([inputs, inputs], 0) @@ -219,6 +237,7 @@ class SegmentMinOrMaxGradientTest(test.TestCase): class FloorModGradientTest(test.TestCase): + @test_util.run_deprecated_v1 def testFloorModGradient(self): # Making sure the input is not near the discontinuity point where # x/y == floor(x/y) @@ -233,6 +252,7 @@ class FloorModGradientTest(test.TestCase): class DivNoNanGradientTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasicGradient(self): inputs = constant_op.constant(np.arange(-3, 3), dtype=dtypes.float32) @@ -244,6 +264,7 @@ class DivNoNanGradientTest(test.TestCase): outputs.get_shape().as_list()) self.assertLess(error, 1e-4) + @test_util.run_deprecated_v1 def testGradientWithDenominatorIsZero(self): x = constant_op.constant(np.arange(-3, 3), dtype=dtypes.float32) @@ -263,6 +284,7 @@ class XlogyTest(test.TestCase): xlogy_ygrad = self.evaluate(gradients.gradients(math_ops.xlogy(x, y), y)[0]) return xlogy_xgrad, xlogy_ygrad + @test_util.run_deprecated_v1 def testNonZeroValuesGrad(self): for dtype in [dtypes.float16, dtypes.float32, dtypes.float64]: x = constant_op.constant(0.1, dtype=dtype) @@ -273,6 +295,7 @@ class XlogyTest(test.TestCase): self.assertAllClose(xlogy_expected_xgrad, xlogy_xgrad) self.assertAllClose(xlogy_expected_ygrad, xlogy_ygrad) + @test_util.run_deprecated_v1 def testZeroXGrad(self): for dtype in [dtypes.float16, dtypes.float32, dtypes.float64]: x = constant_op.constant(0., dtype=dtype) @@ -282,6 +305,7 @@ class XlogyTest(test.TestCase): self.assertAllClose(zero, xlogy_xgrad) self.assertAllClose(zero, xlogy_ygrad) + @test_util.run_deprecated_v1 def testZeroYGrad(self): for dtype in [dtypes.float16, dtypes.float32, dtypes.float64]: x = constant_op.constant(0.1, dtype=dtype) @@ -290,6 +314,7 @@ class XlogyTest(test.TestCase): self.assertAllClose(-np.inf, xlogy_xgrad) self.assertAllClose(np.inf, xlogy_ygrad) + @test_util.run_deprecated_v1 def testZeroXYGrad(self): for dtype in [dtypes.float16, dtypes.float32, dtypes.float64]: x = constant_op.constant(0., dtype=dtype) @@ -307,6 +332,7 @@ class XdivyTest(test.TestCase): xdivy_ygrad = self.evaluate(gradients.gradients(math_ops.xdivy(x, y), y)[0]) return xdivy_xgrad, xdivy_ygrad + @test_util.run_deprecated_v1 def testNonZeroValuesGrad(self): for dtype in [dtypes.float16, dtypes.float32, dtypes.float64]: x = constant_op.constant(0.1, dtype=dtype) @@ -317,6 +343,7 @@ class XdivyTest(test.TestCase): self.assertAllClose(xdivy_expected_xgrad, xdivy_xgrad) self.assertAllClose(xdivy_expected_ygrad, xdivy_ygrad) + @test_util.run_deprecated_v1 def testZeroXGrad(self): for dtype in [dtypes.float16, dtypes.float32, dtypes.float64]: x = constant_op.constant(0., dtype=dtype) @@ -326,6 +353,7 @@ class XdivyTest(test.TestCase): self.assertAllClose(zero, xdivy_xgrad) self.assertAllClose(zero, xdivy_ygrad) + @test_util.run_deprecated_v1 def testZeroYGrad(self): for dtype in [dtypes.float16, dtypes.float32, dtypes.float64]: x = constant_op.constant(0.1, dtype=dtype) @@ -334,6 +362,7 @@ class XdivyTest(test.TestCase): self.assertAllClose(np.inf, xdivy_xgrad) self.assertAllClose(-np.inf, xdivy_ygrad) + @test_util.run_deprecated_v1 def testZeroXYGrad(self): for dtype in [dtypes.float16, dtypes.float32, dtypes.float64]: x = constant_op.constant(0., dtype=dtype) @@ -344,5 +373,25 @@ class XdivyTest(test.TestCase): self.assertAllClose(zero, xdivy_ygrad) +@test_util.run_all_in_graph_and_eager_modes +class PowGradTest(test.TestCase): + + def test_zero_grad_tf_gradients(self): + if context.executing_eagerly(): + self.skipTest("tf.gradients not supported in eager.") + + x = constant_op.constant([-1., 0., 1.]) + g = self.evaluate(gradients.gradients(math_ops.pow(x, 2), x)[0]) + self.assertAllClose([-2., 0., 2.], g) + + def test_zero_grad_tape(self): + with execution_callbacks.errstate(inf_or_nan=execution_callbacks.RAISE): + x = constant_op.constant([-1, 0., 1.]) + with backprop.GradientTape() as tape: + tape.watch(x) + g = tape.gradient(math_ops.pow(x, 2), x) + g = self.evaluate(g) + self.assertAllClose([-2., 0., 2.], g) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/ops/math_ops.py b/tensorflow/python/ops/math_ops.py index 39b1ca8993..f0d8bed508 100644 --- a/tensorflow/python/ops/math_ops.py +++ b/tensorflow/python/ops/math_ops.py @@ -36,7 +36,6 @@ from tensorflow.python.ops import gen_data_flow_ops from tensorflow.python.ops import gen_math_ops from tensorflow.python.ops import gen_nn_ops from tensorflow.python.ops import gen_sparse_ops -from tensorflow.python.ops import gen_spectral_ops # go/tf-wildcard-import # pylint: disable=wildcard-import from tensorflow.python.ops.gen_math_ops import * @@ -44,6 +43,7 @@ from tensorflow.python.ops.gen_math_ops import * from tensorflow.python.platform import tf_logging as logging from tensorflow.python.util import compat from tensorflow.python.util import deprecation +from tensorflow.python.util import dispatch from tensorflow.python.util import nest from tensorflow.python.util.tf_export import tf_export @@ -52,8 +52,8 @@ linspace = gen_math_ops.lin_space arg_max = deprecation.deprecated(None, "Use `tf.math.argmax` instead")(arg_max) # pylint: disable=used-before-assignment arg_min = deprecation.deprecated(None, "Use `tf.math.argmin` instead")(arg_min) # pylint: disable=used-before-assignment -tf_export("arg_max")(arg_max) -tf_export("arg_min")(arg_min) +tf_export(v1=["arg_max"])(arg_max) +tf_export(v1=["arg_min"])(arg_min) # This is set by resource_variable_ops.py. It is included in this way since # there is a circular dependency between math_ops and resource_variable_ops @@ -83,8 +83,6 @@ def argmax(input, output_type=dtypes.int64): axis = deprecation.deprecated_argument_lookup( "axis", axis, "dimension", dimension) - if axis is None: - axis = 0 return argmax_v2(input, axis, output_type, name) @@ -112,6 +110,8 @@ def argmax_v2(input, Returns: A `Tensor` of type `output_type`. """ + if axis is None: + axis = 0 return gen_math_ops.arg_max(input, axis, name=name, output_type=output_type) @@ -128,8 +128,6 @@ def argmin(input, output_type=dtypes.int64): axis = deprecation.deprecated_argument_lookup( "axis", axis, "dimension", dimension) - if axis is None: - axis = 0 return argmin_v2(input, axis, output_type, name) @@ -157,6 +155,8 @@ def argmin_v2(input, Returns: A `Tensor` of type `output_type`. """ + if axis is None: + axis = 0 return gen_math_ops.arg_min(input, axis, name=name, output_type=output_type) @@ -166,6 +166,7 @@ def argmin_v2(input, # pylint: disable=anomalous-backslash-in-string,protected-access # pylint: disable=g-docstring-has-escape @tf_export("math.abs", "abs") +@dispatch.add_dispatch_support def abs(x, name=None): # pylint: disable=redefined-builtin r"""Computes the absolute value of a tensor. @@ -190,22 +191,10 @@ def abs(x, name=None): # pylint: disable=redefined-builtin of type `float32` or `float64`, respectively. """ with ops.name_scope(name, "Abs", [x]) as name: - if isinstance(x, sparse_tensor.SparseTensor): - if x.values.dtype.is_complex: - x_abs = gen_math_ops.complex_abs( - x.values, Tout=x.values.dtype.real_dtype, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_abs, dense_shape=x.dense_shape) - x_abs = gen_math_ops._abs(x.values, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_abs, dense_shape=x.dense_shape) - else: - x = ops.convert_to_tensor(x, name="x") - if x.dtype.is_complex: - return gen_math_ops.complex_abs(x, Tout=x.dtype.real_dtype, name=name) - return gen_math_ops._abs(x, name=name) - - + x = ops.convert_to_tensor(x, name="x") + if x.dtype.is_complex: + return gen_math_ops.complex_abs(x, Tout=x.dtype.real_dtype, name=name) + return gen_math_ops._abs(x, name=name) # pylint: enable=g-docstring-has-escape @@ -292,31 +281,7 @@ _sub.__doc__ = ( gen_math_ops.sub.__doc__ + ("" if _sub.__doc__ is None else _sub.__doc__)) -# pylint: disable=g-docstring-has-escape -@tf_export("math.negative", "negative") -def negative(x, name=None): - """Computes numerical negative value element-wise. - - I.e., \\(y = -x\\). - - Args: - x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`, - `float32`, `float64`, `int32`, `int64`, `complex64`, `complex128`. - name: A name for the operation (optional). - - Returns: - A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`. - """ - with ops.name_scope(name, "Neg", [x]) as name: - if isinstance(x, sparse_tensor.SparseTensor): - x_neg = gen_math_ops.neg(x.values, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_neg, dense_shape=x.dense_shape) - else: - return gen_math_ops.neg(x, name=name) - - -# pylint: enable=g-docstring-has-escape +negative = gen_math_ops.neg # pylint: disable=g-docstring-has-escape @@ -342,107 +307,8 @@ def _neg(x, name=None): # pylint: enable=g-docstring-has-escape -@tf_export("math.sign", "sign") -def sign(x, name=None): - """Returns an element-wise indication of the sign of a number. - - `y = sign(x) = -1` if `x < 0`; 0 if `x == 0` or `tf.is_nan(x)`; 1 if `x > 0`. - - Zero is returned for NaN inputs. - - For complex numbers, `y = sign(x) = x / |x|` if `x != 0`, otherwise `y = 0`. - - Args: - x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`, - `float32`, `float64`, `int32`, `int64`, `complex64`, `complex128`. - name: A name for the operation (optional). - - Returns: - A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`. - - @compatibility(numpy) - Equivalent to numpy.sign except for the behavior for input values of NaN. - @end_compatibility - """ - with ops.name_scope(name, "Sign", [x]) as name: - if isinstance(x, sparse_tensor.SparseTensor): - x_sign = gen_math_ops.sign(x.values, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_sign, dense_shape=x.dense_shape) - else: - return gen_math_ops.sign(x, name=name) - - -@tf_export("math.square", "square") -def square(x, name=None): - r"""Computes square of x element-wise. - - I.e., \\(y = x * x = x^2\\). - - Args: - x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`, - `float32`, `float64`, `int32`, `int64`, `complex64`, `complex128`. - name: A name for the operation (optional). - - Returns: - A `Tensor` or `SparseTensor`. Has the same type as `x`. - """ - with ops.name_scope(name, "Square", [x]) as name: - if isinstance(x, sparse_tensor.SparseTensor): - x_square = gen_math_ops.square(x.values, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_square, dense_shape=x.dense_shape) - else: - return gen_math_ops.square(x, name=name) - - -@tf_export("math.sqrt", "sqrt") -def sqrt(x, name=None): - r"""Computes square root of x element-wise. - - I.e., \\(y = \sqrt{x} = x^{1/2}\\). - - Args: - x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`, - `float32`, `float64`, `complex64`, `complex128`. - name: A name for the operation (optional). - - Returns: - A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`. - """ - with ops.name_scope(name, "Sqrt", [x]) as name: - if isinstance(x, sparse_tensor.SparseTensor): - x_sqrt = gen_math_ops.sqrt(x.values, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_sqrt, dense_shape=x.dense_shape) - else: - return gen_math_ops.sqrt(x, name=name) - - -@tf_export("math.erf", v1=["math.erf", "erf"]) -@deprecation.deprecated_endpoints("erf") -def erf(x, name=None): - """Computes the Gauss error function of `x` element-wise. - - Args: - x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`, - `float32`, `float64`. - name: A name for the operation (optional). - - Returns: - A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`. - """ - with ops.name_scope(name, "Erf", [x]) as name: - if isinstance(x, sparse_tensor.SparseTensor): - x_erf = gen_math_ops.erf(x.values, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_erf, dense_shape=x.dense_shape) - else: - return gen_math_ops.erf(x, name=name) - - -@tf_export("math.scalar_mul", "scalar_mul") -def scalar_mul(scalar, x): +@tf_export(v1=["math.scalar_mul", "scalar_mul"]) +def scalar_mul(scalar, x, name=None): """Multiplies a scalar times a `Tensor` or `IndexedSlices` object. Intended for use in gradient code which might deal with `IndexedSlices` @@ -452,6 +318,7 @@ def scalar_mul(scalar, x): Args: scalar: A 0-D scalar `Tensor`. Must have known shape. x: A `Tensor` or `IndexedSlices` to be scaled. + name: A name for the operation (optional). Returns: `scalar * x` of the same type (`Tensor` or `IndexedSlices`) as `x`. @@ -464,13 +331,21 @@ def scalar_mul(scalar, x): shape = scalar.get_shape() if shape.ndims == 0: if isinstance(x, ops.IndexedSlices): - return ops.IndexedSlices(scalar * x.values, x.indices, x.dense_shape) + return ops.IndexedSlices(gen_math_ops.mul(scalar, x.values, name), + x.indices, x.dense_shape) else: - return scalar * x + return gen_math_ops.mul(scalar, x, name) else: raise ValueError("Only scalar multiply works, got shape %s" % shape) +@tf_export("math.scalar_mul", "scalar_mul", v1=[]) +@_set_doc(scalar_mul.__doc__) +def scalar_mul_v2(scalar, x, name=None): + with ops.name_scope(name, "scalar_mul", [x]) as name: + return scalar_mul(scalar, x, name) + + @tf_export("math.pow", "pow") def pow(x, y, name=None): # pylint: disable=redefined-builtin r"""Computes the power of one value to another. @@ -1091,7 +966,10 @@ def truediv(x, y, name=None): return _truediv_python3(x, y, name) -@tf_export("div") +@deprecation.deprecated( + date=None, + instructions="Deprecated in favor of operator or tf.math.divide.") +@tf_export(v1=["div"]) def div(x, y, name=None): """Divides x / y elementwise (using Python 2 division operator semantics). @@ -1312,7 +1190,7 @@ def range(start, limit=None, delta=1, dtype=None, name="range"): # pylint: disa # Reduction operations -def _ReductionDims(x, axis, reduction_indices): +def _ReductionDims(x, axis, reduction_indices=None): # pylint: disable=invalid-name """Returns range(0, rank(x)) if reduction_indices is None.""" # TODO(aselle): Remove this after deprecation if reduction_indices is not None: @@ -1335,23 +1213,23 @@ def _ReductionDims(x, axis, reduction_indices): return range(0, array_ops.rank(x)) -def _may_reduce_to_scalar(keepdims, axis, reduction_indices, output): +def _may_reduce_to_scalar(keepdims, axis, output): """Set a reduction's output shape to be a scalar if we are certain.""" if not common_shapes.has_fully_defined_shape(output) and (not keepdims) and ( - axis is None) and (reduction_indices is None): + axis is None): output.set_shape(()) return output -@tf_export("math.reduce_sum", "reduce_sum") +@tf_export(v1=["math.reduce_sum", "reduce_sum"]) @deprecation.deprecated_args( None, "keep_dims is deprecated, use keepdims instead", "keep_dims") -def reduce_sum(input_tensor, - axis=None, - keepdims=None, - name=None, - reduction_indices=None, - keep_dims=None): +def reduce_sum_v1(input_tensor, + axis=None, + keepdims=None, + name=None, + reduction_indices=None, + keep_dims=None): """Computes the sum of elements across dimensions of a tensor. Reduces `input_tensor` along the dimensions given in `axis`. @@ -1391,21 +1269,61 @@ def reduce_sum(input_tensor, int64 while tensorflow returns the same dtype as the input. @end_compatibility """ + axis = deprecation.deprecated_argument_lookup( + "axis", axis, "reduction_indices", reduction_indices) keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, "keep_dims", keep_dims) - if keepdims is None: - keepdims = False + return reduce_sum(input_tensor, axis, keepdims, name) + + +@tf_export("math.reduce_sum", "reduce_sum", v1=[]) +def reduce_sum(input_tensor, axis=None, keepdims=False, name=None): + """Computes the sum of elements across dimensions of a tensor. + + Reduces `input_tensor` along the dimensions given in `axis`. + Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each + entry in `axis`. If `keepdims` is true, the reduced dimensions + are retained with length 1. - return _may_reduce_to_scalar(keepdims, axis, reduction_indices, - gen_math_ops._sum( - input_tensor, - _ReductionDims(input_tensor, axis, - reduction_indices), - keepdims, - name=name)) + If `axis` is None, all dimensions are reduced, and a + tensor with a single element is returned. + For example: -@tf_export("math.count_nonzero", "count_nonzero") + ```python + x = tf.constant([[1, 1, 1], [1, 1, 1]]) + tf.reduce_sum(x) # 6 + tf.reduce_sum(x, 0) # [2, 2, 2] + tf.reduce_sum(x, 1) # [3, 3] + tf.reduce_sum(x, 1, keepdims=True) # [[3], [3]] + tf.reduce_sum(x, [0, 1]) # 6 + ``` + + Args: + input_tensor: The tensor to reduce. Should have numeric type. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. + keepdims: If true, retains reduced dimensions with length 1. + name: A name for the operation (optional). + + Returns: + The reduced tensor, of the same dtype as the input_tensor. + + @compatibility(numpy) + Equivalent to np.sum apart the fact that numpy upcast uint8 and int32 to + int64 while tensorflow returns the same dtype as the input. + @end_compatibility + """ + keepdims = False if keepdims is None else keepdims + return _may_reduce_to_scalar( + keepdims, axis, + gen_math_ops._sum( + input_tensor, _ReductionDims(input_tensor, axis), keepdims, + name=name)) + + +@tf_export(v1=["math.count_nonzero", "count_nonzero"]) @deprecation.deprecated_args( None, "keep_dims is deprecated, use keepdims instead", "keep_dims") def count_nonzero(input_tensor, @@ -1466,32 +1384,89 @@ def count_nonzero(input_tensor, """ keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, "keep_dims", keep_dims) + axis = deprecation.deprecated_argument_lookup( + "axis", axis, + "reduction_indices", reduction_indices + ) + + return count_nonzero_v2(input_tensor, axis, keepdims, dtype, name) + + +@tf_export("math.count_nonzero", v1=[]) +def count_nonzero_v2(input, # pylint: disable=redefined-builtin + axis=None, + keepdims=None, + dtype=dtypes.int64, + name=None): + """Computes number of nonzero elements across dimensions of a tensor. + + Reduces `input` along the dimensions given in `axis`. + Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each + entry in `axis`. If `keepdims` is true, the reduced dimensions + are retained with length 1. + + If `axis` has no entries, all dimensions are reduced, and a + tensor with a single element is returned. + + **NOTE** Floating point comparison to zero is done by exact floating point + equality check. Small values are **not** rounded to zero for purposes of + the nonzero check. + + For example: + + ```python + x = tf.constant([[0, 1, 0], [1, 1, 0]]) + tf.count_nonzero(x) # 3 + tf.count_nonzero(x, 0) # [1, 2, 0] + tf.count_nonzero(x, 1) # [1, 2] + tf.count_nonzero(x, 1, keepdims=True) # [[1], [2]] + tf.count_nonzero(x, [0, 1]) # 3 + ``` + + **NOTE** Strings are compared against zero-length empty string `""`. Any + string with a size greater than zero is already considered as nonzero. + + For example: + ```python + x = tf.constant(["", "a", " ", "b", ""]) + tf.count_nonzero(x) # 3, with "a", " ", and "b" as nonzero strings. + ``` + + Args: + input: The tensor to reduce. Should be of numeric type, `bool`, + or `string`. + axis: The dimensions to reduce. If `None` (the default), + reduces all dimensions. Must be in the range + `[-rank(input), rank(input))`. + keepdims: If true, retains reduced dimensions with length 1. + dtype: The output dtype; defaults to `tf.int64`. + name: A name for the operation (optional). + + Returns: + The reduced tensor (number of nonzero values). + """ if keepdims is None: keepdims = False - - with ops.name_scope(name, "count_nonzero", [input_tensor]): - input_tensor = ops.convert_to_tensor(input_tensor, name="input_tensor") + with ops.name_scope(name, "count_nonzero", [input]): + input = ops.convert_to_tensor(input, name="input") # A scalar of 'zero' is enough as `not_equal` will broadcast. - zero = array_ops.zeros([], dtype=input_tensor.dtype) + zero = array_ops.zeros([], dtype=input.dtype) return cast( reduce_sum( # int64 reduction happens on GPU - to_int64(gen_math_ops.not_equal(input_tensor, zero)), + to_int64(gen_math_ops.not_equal(input, zero)), axis=axis, - keepdims=keepdims, - reduction_indices=reduction_indices), + keepdims=keepdims), dtype=dtype) -@tf_export("math.reduce_mean", "reduce_mean") -@deprecation.deprecated_args( - None, "keep_dims is deprecated, use keepdims instead", "keep_dims") -def reduce_mean(input_tensor, - axis=None, - keepdims=None, - name=None, - reduction_indices=None, - keep_dims=None): +@tf_export(v1=["math.reduce_mean", "reduce_mean"]) +def reduce_mean_v1(input_tensor, + axis=None, + keepdims=None, + name=None, + reduction_indices=None, + keep_dims=None): """Computes the mean of elements across dimensions of a tensor. Reduces `input_tensor` along the dimensions given in `axis`. @@ -1541,22 +1516,72 @@ def reduce_mean(input_tensor, @end_compatibility """ + axis = deprecation.deprecated_argument_lookup( + "axis", axis, "reduction_indices", reduction_indices) keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, "keep_dims", keep_dims) + return reduce_mean(input_tensor, axis, keepdims, name) - if keepdims is None: - keepdims = False - return _may_reduce_to_scalar(keepdims, axis, reduction_indices, - gen_math_ops.mean( - input_tensor, - _ReductionDims(input_tensor, axis, - reduction_indices), - keepdims, - name=name)) + +@tf_export("math.reduce_mean", "reduce_mean", v1=[]) +def reduce_mean(input_tensor, axis=None, keepdims=False, name=None): + """Computes the mean of elements across dimensions of a tensor. + + Reduces `input_tensor` along the dimensions given in `axis`. + Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each + entry in `axis`. If `keepdims` is true, the reduced dimensions + are retained with length 1. + + If `axis` is None, all dimensions are reduced, and a + tensor with a single element is returned. + + For example: + + ```python + x = tf.constant([[1., 1.], [2., 2.]]) + tf.reduce_mean(x) # 1.5 + tf.reduce_mean(x, 0) # [1.5, 1.5] + tf.reduce_mean(x, 1) # [1., 2.] + ``` + + Args: + input_tensor: The tensor to reduce. Should have numeric type. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. + keepdims: If true, retains reduced dimensions with length 1. + name: A name for the operation (optional). + + Returns: + The reduced tensor. + + @compatibility(numpy) + Equivalent to np.mean + + Please note that `np.mean` has a `dtype` parameter that could be used to + specify the output type. By default this is `dtype=float64`. On the other + hand, `tf.reduce_mean` has an aggressive type inference from `input_tensor`, + for example: + + ```python + x = tf.constant([1, 0, 1, 0]) + tf.reduce_mean(x) # 0 + y = tf.constant([1., 0., 1., 0.]) + tf.reduce_mean(y) # 0.5 + ``` + + @end_compatibility + """ + keepdims = False if keepdims is None else keepdims + return _may_reduce_to_scalar( + keepdims, axis, + gen_math_ops.mean( + input_tensor, _ReductionDims(input_tensor, axis), keepdims, + name=name)) @tf_export("math.reduce_variance") -def reduce_variance(input_tensor, axis=None, keepdims=None, name=None): +def reduce_variance(input_tensor, axis=None, keepdims=False, name=None): """Computes the variance of elements across dimensions of a tensor. Reduces `input_tensor` along the dimensions given in `axis`. @@ -1599,12 +1624,12 @@ def reduce_variance(input_tensor, axis=None, keepdims=None, name=None): name = name if name else "reduce_variance" with ops.name_scope(name): means = reduce_mean(input_tensor, axis=axis, keepdims=True) - squared_deviations = square(input_tensor - means) + squared_deviations = gen_math_ops.square(input_tensor - means) return reduce_mean(squared_deviations, axis=axis, keepdims=keepdims) @tf_export("math.reduce_std") -def reduce_std(input_tensor, axis=None, keepdims=None, name=None): +def reduce_std(input_tensor, axis=None, keepdims=False, name=None): """Computes the standard deviation of elements across dimensions of a tensor. Reduces `input_tensor` along the dimensions given in `axis`. @@ -1646,18 +1671,53 @@ def reduce_std(input_tensor, axis=None, keepdims=None, name=None): name = name if name else "reduce_std" with ops.name_scope(name): variance = reduce_variance(input_tensor, axis=axis, keepdims=keepdims) - return sqrt(variance) + return gen_math_ops.sqrt(variance) + + +@tf_export("math.reduce_prod", "reduce_prod", v1=[]) +def reduce_prod(input_tensor, axis=None, keepdims=False, name=None): + """Computes the product of elements across dimensions of a tensor. + + Reduces `input_tensor` along the dimensions given in `axis`. + Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each + entry in `axis`. If `keepdims` is true, the reduced dimensions + are retained with length 1. + If `axis` is None, all dimensions are reduced, and a + tensor with a single element is returned. -@tf_export("math.reduce_prod", "reduce_prod") + Args: + input_tensor: The tensor to reduce. Should have numeric type. + axis: The dimensions to reduce. If `None` (the default), + reduces all dimensions. Must be in the range + `[-rank(input_tensor), rank(input_tensor))`. + keepdims: If true, retains reduced dimensions with length 1. + name: A name for the operation (optional). + + Returns: + The reduced tensor. + + @compatibility(numpy) + Equivalent to np.prod + @end_compatibility + """ + keepdims = False if keepdims is None else keepdims + return _may_reduce_to_scalar( + keepdims, axis, + gen_math_ops.prod( + input_tensor, _ReductionDims(input_tensor, axis), keepdims, + name=name)) + + +@tf_export(v1=["math.reduce_prod", "reduce_prod"]) @deprecation.deprecated_args( None, "keep_dims is deprecated, use keepdims instead", "keep_dims") -def reduce_prod(input_tensor, - axis=None, - keepdims=None, - name=None, - reduction_indices=None, - keep_dims=None): +def reduce_prod_v1(input_tensor, + axis=None, + keepdims=None, + name=None, + reduction_indices=None, + keep_dims=None): """Computes the product of elements across dimensions of a tensor. Reduces `input_tensor` along the dimensions given in `axis`. @@ -1670,6 +1730,127 @@ def reduce_prod(input_tensor, Args: input_tensor: The tensor to reduce. Should have numeric type. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. + keepdims: If true, retains reduced dimensions with length 1. + name: A name for the operation (optional). + reduction_indices: The old (deprecated) name for axis. + keep_dims: Deprecated alias for `keepdims`. + + Returns: + The reduced tensor. + + @compatibility(numpy) + Equivalent to np.prod + @end_compatibility + """ + axis = deprecation.deprecated_argument_lookup( + "axis", axis, "reduction_indices", reduction_indices) + keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, + "keep_dims", keep_dims) + return reduce_prod(input_tensor, axis, keepdims, name) + + +@tf_export(v1=["math.reduce_min", "reduce_min"]) +@deprecation.deprecated_args( + None, "keep_dims is deprecated, use keepdims instead", "keep_dims") +def reduce_min_v1(input_tensor, + axis=None, + keepdims=None, + name=None, + reduction_indices=None, + keep_dims=None): + """Computes the minimum of elements across dimensions of a tensor. + + Reduces `input_tensor` along the dimensions given in `axis`. + Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each + entry in `axis`. If `keepdims` is true, the reduced dimensions + are retained with length 1. + + If `axis` is None, all dimensions are reduced, and a + tensor with a single element is returned. + + Args: + input_tensor: The tensor to reduce. Should have real numeric type. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. + keepdims: If true, retains reduced dimensions with length 1. + name: A name for the operation (optional). + reduction_indices: The old (deprecated) name for axis. + keep_dims: Deprecated alias for `keepdims`. + + Returns: + The reduced tensor. + + @compatibility(numpy) + Equivalent to np.min + @end_compatibility + """ + axis = deprecation.deprecated_argument_lookup( + "axis", axis, "reduction_indices", reduction_indices) + keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, + "keep_dims", keep_dims) + return reduce_min(input_tensor, axis, keepdims, name) + + +@tf_export("math.reduce_min", "reduce_min", v1=[]) +def reduce_min(input_tensor, axis=None, keepdims=False, name=None): + """Computes the minimum of elements across dimensions of a tensor. + + Reduces `input_tensor` along the dimensions given in `axis`. + Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each + entry in `axis`. If `keepdims` is true, the reduced dimensions + are retained with length 1. + + If `axis` is None, all dimensions are reduced, and a + tensor with a single element is returned. + + Args: + input_tensor: The tensor to reduce. Should have real numeric type. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. + keepdims: If true, retains reduced dimensions with length 1. + name: A name for the operation (optional). + + Returns: + The reduced tensor. + + @compatibility(numpy) + Equivalent to np.min + @end_compatibility + """ + keepdims = False if keepdims is None else keepdims + return _may_reduce_to_scalar( + keepdims, axis, + gen_math_ops._min( + input_tensor, _ReductionDims(input_tensor, axis), keepdims, + name=name)) + + +@tf_export(v1=["math.reduce_max", "reduce_max"]) +@deprecation.deprecated_args( + None, "keep_dims is deprecated, use keepdims instead", "keep_dims") +def reduce_max_v1(input_tensor, + axis=None, + keepdims=None, + name=None, + reduction_indices=None, + keep_dims=None): + """Computes the maximum of elements across dimensions of a tensor. + + Reduces `input_tensor` along the dimensions given in `axis`. + Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each + entry in `axis`. If `keepdims` is true, the reduced dimensions + are retained with length 1. + + If `axis` is None, all dimensions are reduced, and a + tensor with a single element is returned. + + Args: + input_tensor: The tensor to reduce. Should have real numeric type. axis: The dimensions to reduce. If `None` (the default), reduces all dimensions. Must be in the range `[-rank(input_tensor), rank(input_tensor))`. @@ -1682,33 +1863,106 @@ def reduce_prod(input_tensor, The reduced tensor. @compatibility(numpy) - Equivalent to np.prod + Equivalent to np.max + @end_compatibility + """ + axis = deprecation.deprecated_argument_lookup( + "axis", axis, "reduction_indices", reduction_indices) + keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, + "keep_dims", keep_dims) + return reduce_max(input_tensor, axis, keepdims, name) + + +@tf_export("math.reduce_max", "reduce_max", v1=[]) +def reduce_max(input_tensor, axis=None, keepdims=False, name=None): + """Computes the maximum of elements across dimensions of a tensor. + + Reduces `input_tensor` along the dimensions given in `axis`. + Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each + entry in `axis`. If `keepdims` is true, the reduced dimensions + are retained with length 1. + + If `axis` is None, all dimensions are reduced, and a + tensor with a single element is returned. + + Args: + input_tensor: The tensor to reduce. Should have real numeric type. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. + keepdims: If true, retains reduced dimensions with length 1. + name: A name for the operation (optional). + + Returns: + The reduced tensor. + + @compatibility(numpy) + Equivalent to np.max + @end_compatibility + """ + keepdims = False if keepdims is None else keepdims + return _may_reduce_to_scalar( + keepdims, axis, + gen_math_ops._max( + input_tensor, _ReductionDims(input_tensor, axis), keepdims, + name=name)) + + +@tf_export(v1=["math.reduce_all", "reduce_all"]) +@deprecation.deprecated_args( + None, "keep_dims is deprecated, use keepdims instead", "keep_dims") +def reduce_all_v1(input_tensor, + axis=None, + keepdims=None, + name=None, + reduction_indices=None, + keep_dims=None): + """Computes the "logical and" of elements across dimensions of a tensor. + + Reduces `input_tensor` along the dimensions given in `axis`. + Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each + entry in `axis`. If `keepdims` is true, the reduced dimensions + are retained with length 1. + + If `axis` is None, all dimensions are reduced, and a + tensor with a single element is returned. + + For example: + + ```python + x = tf.constant([[True, True], [False, False]]) + tf.reduce_all(x) # False + tf.reduce_all(x, 0) # [False, False] + tf.reduce_all(x, 1) # [True, False] + ``` + + Args: + input_tensor: The boolean tensor to reduce. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. + keepdims: If true, retains reduced dimensions with length 1. + name: A name for the operation (optional). + reduction_indices: The old (deprecated) name for axis. + keep_dims: Deprecated alias for `keepdims`. + + Returns: + The reduced tensor. + + @compatibility(numpy) + Equivalent to np.all @end_compatibility """ + axis = deprecation.deprecated_argument_lookup( + "axis", axis, "reduction_indices", reduction_indices) keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, "keep_dims", keep_dims) - - if keepdims is None: - keepdims = False - return _may_reduce_to_scalar(keepdims, axis, reduction_indices, - gen_math_ops.prod( - input_tensor, - _ReductionDims(input_tensor, axis, - reduction_indices), - keepdims, - name=name)) + return reduce_all(input_tensor, axis, keepdims, name) -@tf_export("math.reduce_min", "reduce_min") -@deprecation.deprecated_args( - None, "keep_dims is deprecated, use keepdims instead", "keep_dims") -def reduce_min(input_tensor, - axis=None, - keepdims=None, - name=None, - reduction_indices=None, - keep_dims=None): - """Computes the minimum of elements across dimensions of a tensor. +@tf_export("reduce_all", "math.reduce_all", v1=[]) +def reduce_all(input_tensor, axis=None, keepdims=False, name=None): + """Computes the "logical and" of elements across dimensions of a tensor. Reduces `input_tensor` along the dimensions given in `axis`. Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each @@ -1718,46 +1972,48 @@ def reduce_min(input_tensor, If `axis` is None, all dimensions are reduced, and a tensor with a single element is returned. + For example: + + ```python + x = tf.constant([[True, True], [False, False]]) + tf.reduce_all(x) # False + tf.reduce_all(x, 0) # [False, False] + tf.reduce_all(x, 1) # [True, False] + ``` + Args: - input_tensor: The tensor to reduce. Should have real numeric type. - axis: The dimensions to reduce. If `None` (the default), - reduces all dimensions. Must be in the range - `[-rank(input_tensor), rank(input_tensor))`. + input_tensor: The boolean tensor to reduce. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. keepdims: If true, retains reduced dimensions with length 1. name: A name for the operation (optional). - reduction_indices: The old (deprecated) name for axis. - keep_dims: Deprecated alias for `keepdims`. Returns: The reduced tensor. @compatibility(numpy) - Equivalent to np.min + Equivalent to np.all @end_compatibility """ - keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, - "keep_dims", keep_dims) - if keepdims is None: - keepdims = False - return _may_reduce_to_scalar(keepdims, axis, reduction_indices, - gen_math_ops._min( - input_tensor, - _ReductionDims(input_tensor, axis, - reduction_indices), - keepdims, - name=name)) + keepdims = False if keepdims is None else keepdims + return _may_reduce_to_scalar( + keepdims, axis, + gen_math_ops._all( + input_tensor, _ReductionDims(input_tensor, axis), keepdims, + name=name)) -@tf_export("math.reduce_max", "reduce_max") +@tf_export(v1=["math.reduce_any", "reduce_any"]) @deprecation.deprecated_args( None, "keep_dims is deprecated, use keepdims instead", "keep_dims") -def reduce_max(input_tensor, - axis=None, - keepdims=None, - name=None, - reduction_indices=None, - keep_dims=None): - """Computes the maximum of elements across dimensions of a tensor. +def reduce_any_v1(input_tensor, + axis=None, + keepdims=None, + name=None, + reduction_indices=None, + keep_dims=None): + """Computes the "logical or" of elements across dimensions of a tensor. Reduces `input_tensor` along the dimensions given in `axis`. Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each @@ -1767,11 +2023,20 @@ def reduce_max(input_tensor, If `axis` is None, all dimensions are reduced, and a tensor with a single element is returned. + For example: + + ```python + x = tf.constant([[True, True], [False, False]]) + tf.reduce_any(x) # True + tf.reduce_any(x, 0) # [True, True] + tf.reduce_any(x, 1) # [True, False] + ``` + Args: - input_tensor: The tensor to reduce. Should have real numeric type. - axis: The dimensions to reduce. If `None` (the default), - reduces all dimensions. Must be in the range - `[-rank(input_tensor), rank(input_tensor))`. + input_tensor: The boolean tensor to reduce. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. keepdims: If true, retains reduced dimensions with length 1. name: A name for the operation (optional). reduction_indices: The old (deprecated) name for axis. @@ -1781,32 +2046,19 @@ def reduce_max(input_tensor, The reduced tensor. @compatibility(numpy) - Equivalent to np.max + Equivalent to np.any @end_compatibility """ + axis = deprecation.deprecated_argument_lookup( + "axis", axis, "reduction_indices", reduction_indices) keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, "keep_dims", keep_dims) - if keepdims is None: - keepdims = False - return _may_reduce_to_scalar(keepdims, axis, reduction_indices, - gen_math_ops._max( - input_tensor, - _ReductionDims(input_tensor, axis, - reduction_indices), - keepdims, - name=name)) + return reduce_any(input_tensor, axis, keepdims, name) -@tf_export("math.reduce_all", "reduce_all") -@deprecation.deprecated_args( - None, "keep_dims is deprecated, use keepdims instead", "keep_dims") -def reduce_all(input_tensor, - axis=None, - keepdims=None, - name=None, - reduction_indices=None, - keep_dims=None): - """Computes the "logical and" of elements across dimensions of a tensor. +@tf_export("math.reduce_any", "reduce_any", v1=[]) +def reduce_any(input_tensor, axis=None, keepdims=False, name=None): + """Computes the "logical or" of elements across dimensions of a tensor. Reduces `input_tensor` along the dimensions given in `axis`. Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each @@ -1820,74 +2072,73 @@ def reduce_all(input_tensor, ```python x = tf.constant([[True, True], [False, False]]) - tf.reduce_all(x) # False - tf.reduce_all(x, 0) # [False, False] - tf.reduce_all(x, 1) # [True, False] + tf.reduce_any(x) # True + tf.reduce_any(x, 0) # [True, True] + tf.reduce_any(x, 1) # [True, False] ``` Args: input_tensor: The boolean tensor to reduce. - axis: The dimensions to reduce. If `None` (the default), - reduces all dimensions. Must be in the range - `[-rank(input_tensor), rank(input_tensor))`. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. keepdims: If true, retains reduced dimensions with length 1. name: A name for the operation (optional). - reduction_indices: The old (deprecated) name for axis. - keep_dims: Deprecated alias for `keepdims`. Returns: The reduced tensor. @compatibility(numpy) - Equivalent to np.all + Equivalent to np.any @end_compatibility """ - keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, - "keep_dims", keep_dims) - if keepdims is None: - keepdims = False - return _may_reduce_to_scalar(keepdims, axis, reduction_indices, - gen_math_ops._all( - input_tensor, - _ReductionDims(input_tensor, axis, - reduction_indices), - keepdims, - name=name)) + keepdims = False if keepdims is None else keepdims + return _may_reduce_to_scalar( + keepdims, axis, + gen_math_ops._any( + input_tensor, _ReductionDims(input_tensor, axis), keepdims, + name=name)) -@tf_export("math.reduce_any", "reduce_any") +@tf_export(v1=["math.reduce_logsumexp", "reduce_logsumexp"]) @deprecation.deprecated_args( None, "keep_dims is deprecated, use keepdims instead", "keep_dims") -def reduce_any(input_tensor, - axis=None, - keepdims=None, - name=None, - reduction_indices=None, - keep_dims=None): - """Computes the "logical or" of elements across dimensions of a tensor. +def reduce_logsumexp_v1(input_tensor, + axis=None, + keepdims=None, + name=None, + reduction_indices=None, + keep_dims=None): + """Computes log(sum(exp(elements across dimensions of a tensor))). Reduces `input_tensor` along the dimensions given in `axis`. Unless `keepdims` is true, the rank of the tensor is reduced by 1 for each entry in `axis`. If `keepdims` is true, the reduced dimensions are retained with length 1. - If `axis` is None, all dimensions are reduced, and a + If `axis` has no entries, all dimensions are reduced, and a tensor with a single element is returned. + This function is more numerically stable than log(sum(exp(input))). It avoids + overflows caused by taking the exp of large inputs and underflows caused by + taking the log of small inputs. + For example: ```python - x = tf.constant([[True, True], [False, False]]) - tf.reduce_any(x) # True - tf.reduce_any(x, 0) # [True, True] - tf.reduce_any(x, 1) # [True, False] + x = tf.constant([[0., 0., 0.], [0., 0., 0.]]) + tf.reduce_logsumexp(x) # log(6) + tf.reduce_logsumexp(x, 0) # [log(2), log(2), log(2)] + tf.reduce_logsumexp(x, 1) # [log(3), log(3)] + tf.reduce_logsumexp(x, 1, keepdims=True) # [[log(3)], [log(3)]] + tf.reduce_logsumexp(x, [0, 1]) # log(6) ``` Args: - input_tensor: The boolean tensor to reduce. - axis: The dimensions to reduce. If `None` (the default), - reduces all dimensions. Must be in the range - `[-rank(input_tensor), rank(input_tensor))`. + input_tensor: The tensor to reduce. Should have numeric type. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. keepdims: If true, retains reduced dimensions with length 1. name: A name for the operation (optional). reduction_indices: The old (deprecated) name for axis. @@ -1895,33 +2146,16 @@ def reduce_any(input_tensor, Returns: The reduced tensor. - - @compatibility(numpy) - Equivalent to np.any - @end_compatibility """ + axis = deprecation.deprecated_argument_lookup( + "axis", axis, "reduction_indices", reduction_indices) keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, "keep_dims", keep_dims) - if keepdims is None: - keepdims = False - return _may_reduce_to_scalar(keepdims, axis, reduction_indices, - gen_math_ops._any( - input_tensor, - _ReductionDims(input_tensor, axis, - reduction_indices), - keepdims, - name=name)) + return reduce_logsumexp(input_tensor, axis, keepdims, name) -@tf_export("math.reduce_logsumexp", "reduce_logsumexp") -@deprecation.deprecated_args( - None, "keep_dims is deprecated, use keepdims instead", "keep_dims") -def reduce_logsumexp(input_tensor, - axis=None, - keepdims=None, - name=None, - reduction_indices=None, - keep_dims=None): +@tf_export("math.reduce_logsumexp", "reduce_logsumexp", v1=[]) +def reduce_logsumexp(input_tensor, axis=None, keepdims=False, name=None): """Computes log(sum(exp(elements across dimensions of a tensor))). Reduces `input_tensor` along the dimensions given in `axis`. @@ -1949,27 +2183,21 @@ def reduce_logsumexp(input_tensor, Args: input_tensor: The tensor to reduce. Should have numeric type. - axis: The dimensions to reduce. If `None` (the default), - reduces all dimensions. Must be in the range - `[-rank(input_tensor), rank(input_tensor))`. + axis: The dimensions to reduce. If `None` (the default), reduces all + dimensions. Must be in the range `[-rank(input_tensor), + rank(input_tensor))`. keepdims: If true, retains reduced dimensions with length 1. name: A name for the operation (optional). - reduction_indices: The old (deprecated) name for axis. - keep_dims: Deprecated alias for `keepdims`. Returns: The reduced tensor. """ - keepdims = deprecation.deprecated_argument_lookup("keepdims", keepdims, - "keep_dims", keep_dims) - if keepdims is None: - keepdims = False + keepdims = False if keepdims is None else keepdims input_tensor = ops.convert_to_tensor(input_tensor) with ops.name_scope(name, "ReduceLogSumExp", [input_tensor]) as name: raw_max = reduce_max( input_tensor, axis=axis, - reduction_indices=reduction_indices, keepdims=True) my_max = array_ops.stop_gradient( array_ops.where( @@ -1979,12 +2207,11 @@ def reduce_logsumexp(input_tensor, reduce_sum( gen_math_ops.exp(gen_math_ops.sub(input_tensor, my_max)), axis, - keepdims=keepdims, - reduction_indices=reduction_indices)) + keepdims=keepdims)) if not keepdims: my_max = array_ops.reshape(my_max, array_ops.shape(result)) result = gen_math_ops.add(result, my_max) - return _may_reduce_to_scalar(keepdims, axis, reduction_indices, result) + return _may_reduce_to_scalar(keepdims, axis, result) @tf_export("linalg.trace", v1=["linalg.trace", "trace"]) @@ -2311,7 +2538,8 @@ def matvec(a, _OverrideBinaryOperatorHelper(matmul, "matmul") -sparse_matmul = gen_math_ops.sparse_mat_mul +sparse_matmul = deprecation.deprecated(None, "Use `tf.linalg.matmul` instead")( + gen_math_ops.sparse_mat_mul) tf_export(v1=["sparse_matmul"])(sparse_matmul) @@ -2555,34 +2783,64 @@ def log_sigmoid(x, name=None): return gen_math_ops.neg(gen_nn_ops.softplus(-x), name=name) -@tf_export("math.tanh", "nn.tanh", "tanh") -def tanh(x, name=None): - """Computes hyperbolic tangent of `x` element-wise. +@tf_export("math.bincount", v1=[]) +def bincount(arr, + weights=None, + minlength=None, + maxlength=None, + dtype=dtypes.int32, + name=None): + """Counts the number of occurrences of each value in an integer array. + + If `minlength` and `maxlength` are not given, returns a vector with length + `tf.reduce_max(arr) + 1` if `arr` is non-empty, and length 0 otherwise. + If `weights` are non-None, then index `i` of the output stores the sum of the + value in `weights` at each index where the corresponding value in `arr` is + `i`. Args: - x: A Tensor or SparseTensor with type `float16`, `float32`, `double`, - `complex64`, or `complex128`. - name: A name for the operation (optional). + arr: An int32 tensor of non-negative values. + weights: If non-None, must be the same shape as arr. For each value in + `arr`, the bin will be incremented by the corresponding weight instead of + 1. + minlength: If given, ensures the output has length at least `minlength`, + padding with zeros at the end if necessary. + maxlength: If given, skips values in `arr` that are equal or greater than + `maxlength`, ensuring that the output has length at most `maxlength`. + dtype: If `weights` is None, determines the type of the output bins. + name: A name scope for the associated operations (optional). Returns: - A Tensor or SparseTensor respectively with the same type as `x`. + A vector with the same dtype as `weights` or the given `dtype`. The bin + values. """ - with ops.name_scope(name, "Tanh", [x]) as name: - if isinstance(x, sparse_tensor.SparseTensor): - x_tanh = gen_math_ops.tanh(x.values, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_tanh, dense_shape=x.dense_shape) - else: - return gen_math_ops.tanh(x, name=name) - - -@tf_export("math.bincount", v1=["math.bincount", "bincount"]) + name = "bincount" if name is None else name + with ops.name_scope(name): + arr = ops.convert_to_tensor(arr, name="arr", dtype=dtypes.int32) + array_is_nonempty = reduce_prod(array_ops.shape(arr)) > 0 + output_size = cast(array_is_nonempty, dtypes.int32) * (reduce_max(arr) + 1) + if minlength is not None: + minlength = ops.convert_to_tensor( + minlength, name="minlength", dtype=dtypes.int32) + output_size = gen_math_ops.maximum(minlength, output_size) + if maxlength is not None: + maxlength = ops.convert_to_tensor( + maxlength, name="maxlength", dtype=dtypes.int32) + output_size = gen_math_ops.minimum(maxlength, output_size) + if weights is not None: + weights = ops.convert_to_tensor(weights, name="weights") + return gen_math_ops.unsorted_segment_sum(weights, arr, output_size) + weights = constant_op.constant([], dtype) + return gen_math_ops.bincount(arr, output_size, weights) + + +@tf_export(v1=["math.bincount", "bincount"]) @deprecation.deprecated_endpoints("bincount") -def bincount(arr, - weights=None, - minlength=None, - maxlength=None, - dtype=dtypes.int32): +def bincount_v1(arr, + weights=None, + minlength=None, + maxlength=None, + dtype=dtypes.int32): """Counts the number of occurrences of each value in an integer array. If `minlength` and `maxlength` are not given, returns a vector with length @@ -2594,34 +2852,19 @@ def bincount(arr, Args: arr: An int32 tensor of non-negative values. weights: If non-None, must be the same shape as arr. For each value in - `arr`, the bin will be incremented by the corresponding weight instead - of 1. + `arr`, the bin will be incremented by the corresponding weight instead of + 1. minlength: If given, ensures the output has length at least `minlength`, - padding with zeros at the end if necessary. + padding with zeros at the end if necessary. maxlength: If given, skips values in `arr` that are equal or greater than - `maxlength`, ensuring that the output has length at most `maxlength`. + `maxlength`, ensuring that the output has length at most `maxlength`. dtype: If `weights` is None, determines the type of the output bins. Returns: A vector with the same dtype as `weights` or the given `dtype`. The bin values. """ - arr = ops.convert_to_tensor(arr, name="arr", dtype=dtypes.int32) - array_is_nonempty = reduce_prod(array_ops.shape(arr)) > 0 - output_size = cast(array_is_nonempty, dtypes.int32) * (reduce_max(arr) + 1) - if minlength is not None: - minlength = ops.convert_to_tensor( - minlength, name="minlength", dtype=dtypes.int32) - output_size = gen_math_ops.maximum(minlength, output_size) - if maxlength is not None: - maxlength = ops.convert_to_tensor( - maxlength, name="maxlength", dtype=dtypes.int32) - output_size = gen_math_ops.minimum(maxlength, output_size) - if weights is not None: - weights = ops.convert_to_tensor(weights, name="weights") - return gen_math_ops.unsorted_segment_sum(weights, arr, output_size) - weights = constant_op.constant([], dtype) - return gen_math_ops.bincount(arr, output_size, weights) + return bincount(arr, weights, minlength, maxlength, dtype) @tf_export("math.cumsum", "cumsum") @@ -2923,8 +3166,7 @@ def unsorted_segment_sqrt_n(data, segment_ids, num_segments, name=None): return summed / gen_math_ops.sqrt(N) -@tf_export( - "sparse.segment_sum", v1=["sparse.segment_sum", "sparse_segment_sum"]) +@tf_export(v1=["sparse.segment_sum", "sparse_segment_sum"]) @deprecation.deprecated_endpoints("sparse_segment_sum") def sparse_segment_sum(data, indices, segment_ids, name=None, num_segments=None): @@ -2998,8 +3240,17 @@ def sparse_segment_sum(data, indices, segment_ids, name=None, data=data, indices=indices, segment_ids=segment_ids, name=name) -@tf_export( - "sparse.segment_mean", v1=["sparse.segment_mean", "sparse_segment_mean"]) +@tf_export("sparse.segment_sum", v1=[]) +def sparse_segment_sum_v2(data, + indices, + segment_ids, + num_segments=None, + name=None): + return sparse_segment_mean( + data, indices, segment_ids, name=name, num_segments=num_segments) + + +@tf_export(v1=["sparse.segment_mean", "sparse_segment_mean"]) @deprecation.deprecated_endpoints("sparse_segment_mean") def sparse_segment_mean(data, indices, @@ -3045,9 +3296,44 @@ def sparse_segment_mean(data, data=data, indices=indices, segment_ids=segment_ids, name=name) -@tf_export( - "sparse.segment_sqrt_n", - v1=["sparse.segment_sqrt_n", "sparse_segment_sqrt_n"]) +@tf_export("sparse.segment_mean", v1=[]) +def sparse_segment_mean_v2(data, + indices, + segment_ids, + num_segments=None, + name=None): + r"""Computes the mean along sparse segments of a tensor. + + Read [the section on + segmentation](https://tensorflow.org/api_guides/python/math_ops#Segmentation) + for an explanation of segments. + + Like `SegmentMean`, but `segment_ids` can have rank less than `data`'s first + dimension, selecting a subset of dimension 0, specified by `indices`. + `segment_ids` is allowed to have missing ids, in which case the output will + be zeros at those indices. In those cases `num_segments` is used to determine + the size of the output. + + Args: + data: A `Tensor` with data that will be assembled in the output. + indices: A 1-D `Tensor` with indices into `data`. Has same rank as + `segment_ids`. + segment_ids: A 1-D `Tensor` with indices into the output `Tensor`. Values + should be sorted and can be repeated. + num_segments: An optional int32 scalar. Indicates the size of the output + `Tensor`. + name: A name for the operation (optional). + + Returns: + A `tensor` of the shape as data, except for dimension 0 which + has size `k`, the number of segments specified via `num_segments` or + inferred for the last element in `segments_ids`. + """ + return sparse_segment_mean( + data, indices, segment_ids, name=name, num_segments=num_segments) + + +@tf_export(v1=["sparse.segment_sqrt_n", "sparse_segment_sqrt_n"]) @deprecation.deprecated_endpoints("sparse_segment_sqrt_n") def sparse_segment_sqrt_n(data, indices, @@ -3085,6 +3371,35 @@ def sparse_segment_sqrt_n(data, data=data, indices=indices, segment_ids=segment_ids, name=name) +@tf_export("sparse.segment_sqrt_n", v1=[]) +def sparse_segment_sqrt_n_v2(data, + indices, + segment_ids, + num_segments=None, + name=None): + r"""Computes the sum along sparse segments of a tensor divided by the sqrt(N). + + `N` is the size of the segment being reduced. + + Args: + data: A `Tensor` with data that will be assembled in the output. + indices: A 1-D `Tensor` with indices into `data`. Has same rank as + `segment_ids`. + segment_ids: A 1-D `Tensor` with indices into the output `Tensor`. Values + should be sorted and can be repeated. + num_segments: An optional int32 scalar. Indicates the size of the output + `Tensor`. + name: A name for the operation (optional). + + Returns: + A `tensor` of the shape as data, except for dimension 0 which + has size `k`, the number of segments specified via `num_segments` or + inferred for the last element in `segments_ids`. + """ + return sparse_segment_sqrt_n( + data, indices, segment_ids, name=name, num_segments=num_segments) + + @tf_export("tensordot", "linalg.tensordot") def tensordot(a, b, axes, name=None): r"""Tensor contraction of a and b along specified axes. @@ -3118,12 +3433,11 @@ def tensordot(a, b, axes, name=None): a: `Tensor` of type `float32` or `float64`. b: `Tensor` with the same type as `a`. axes: Either a scalar `N`, or a list or an `int32` `Tensor` of shape [2, k]. - If axes is a scalar, sum over the last N axes of a and the first N axes - of b in order. - If axes is a list or `Tensor` the first and second row contain the set of - unique integers specifying axes along which the contraction is computed, - for `a` and `b`, respectively. The number of axes for `a` and `b` must - be equal. + If axes is a scalar, sum over the last N axes of a and the first N axes of + b in order. If axes is a list or `Tensor` the first and second row contain + the set of unique integers specifying axes along which the contraction is + computed, for `a` and `b`, respectively. The number of axes for `a` and + `b` must be equal. name: A name for the operation (optional). Returns: @@ -3295,73 +3609,3 @@ def polyval(coeffs, x, name=None): for c in coeffs[1:]: p = c + p * x return p - - -@tf_export("math.bessel_i0e") -def bessel_i0e(x, name=None): - """Computes the Bessel i0e function of `x` element-wise. - - Exponentially scaled modified Bessel function of order 0 defined as - `bessel_i0e(x) = exp(-abs(x)) bessel_i0(x)`. - - This function is faster and numerically stabler than `bessel_i0(x)`. - - Args: - x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`, - `float32`, `float64`. - name: A name for the operation (optional). - - Returns: - A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`. - - @compatibility(scipy) - Equivalent to scipy.special.i0e - @end_compatibility - """ - with ops.name_scope(name, "bessel_i0e", [x]) as name: - if isinstance(x, sparse_tensor.SparseTensor): - x_i0e = gen_math_ops.bessel_i0e(x.values, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_i0e, dense_shape=x.dense_shape) - else: - return gen_math_ops.bessel_i0e(x, name=name) - - -@tf_export("math.bessel_i1e") -def bessel_i1e(x, name=None): - """Computes the Bessel i1e function of `x` element-wise. - - Exponentially scaled modified Bessel function of order 1 defined as - `bessel_i1e(x) = exp(-abs(x)) bessel_i1(x)`. - - This function is faster and numerically stabler than `bessel_i1(x)`. - - Args: - x: A `Tensor` or `SparseTensor`. Must be one of the following types: `half`, - `float32`, `float64`. - name: A name for the operation (optional). - - Returns: - A `Tensor` or `SparseTensor`, respectively. Has the same type as `x`. - - @compatibility(scipy) - Equivalent to scipy.special.i1e - @end_compatibility - """ - with ops.name_scope(name, "bessel_i1e", [x]) as name: - if isinstance(x, sparse_tensor.SparseTensor): - x_i1e = gen_math_ops.bessel_i1e(x.values, name=name) - return sparse_tensor.SparseTensor( - indices=x.indices, values=x_i1e, dense_shape=x.dense_shape) - else: - return gen_math_ops.bessel_i1e(x, name=name) - - -# FFT ops were moved to tf.spectral. tf.fft symbols were part of the TensorFlow -# 1.0 API so we leave these here for backwards compatibility. -fft = gen_spectral_ops.fft -ifft = gen_spectral_ops.ifft -fft2d = gen_spectral_ops.fft2d -ifft2d = gen_spectral_ops.ifft2d -fft3d = gen_spectral_ops.fft3d -ifft3d = gen_spectral_ops.ifft3d diff --git a/tensorflow/python/ops/math_ops_test.py b/tensorflow/python/ops/math_ops_test.py index a4da0c6c33..add1621a56 100644 --- a/tensorflow/python/ops/math_ops_test.py +++ b/tensorflow/python/ops/math_ops_test.py @@ -92,6 +92,7 @@ class ReduceTest(test_util.TensorFlowTestCase): class LogSumExpTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testReduceLogSumExp(self): for dtype in [np.float16, np.float32, np.double]: x_np = np.random.rand(5, 5).astype(dtype) @@ -104,22 +105,23 @@ class LogSumExpTest(test_util.TensorFlowTestCase): for dtype in [np.float16, np.float32, np.double]: x_np = np.random.rand(5, 5).astype(dtype) with self.cached_session(use_gpu=True): - y_tf = math_ops.reduce_logsumexp(x_np, reduction_indices=[0]) + y_tf = math_ops.reduce_logsumexp(x_np, axis=[0]) y_np = log(np.sum(exp(x_np), axis=0)) self.assertShapeEqual(y_np, y_tf) - y_tf_np = y_tf.eval() + y_tf_np = self.evaluate(y_tf) self.assertAllClose(y_tf_np, y_np) def testReductionIndices2(self): for dtype in [np.float16, np.float32, np.double]: x_np = np.random.rand(5, 5).astype(dtype) with self.cached_session(use_gpu=True): - y_tf = math_ops.reduce_logsumexp(x_np, reduction_indices=0) + y_tf = math_ops.reduce_logsumexp(x_np, axis=0) y_np = log(np.sum(exp(x_np), axis=0)) self.assertShapeEqual(y_np, y_tf) - y_tf_np = y_tf.eval() + y_tf_np = self.evaluate(y_tf) self.assertAllClose(y_tf_np, y_np) + @test_util.run_deprecated_v1 def testKeepDims(self): for dtype in [np.float16, np.float32, np.double]: x_np = np.random.rand(5, 5).astype(dtype) @@ -129,6 +131,7 @@ class LogSumExpTest(test_util.TensorFlowTestCase): y_np = log(np.sum(exp(x_np), keepdims=True)) self.assertAllClose(y_tf_np, y_np) + @test_util.run_deprecated_v1 def testOverflow(self): x = [1000, 1001, 1002, 1003] for dtype in [np.float16, np.float32, np.double]: @@ -146,6 +149,7 @@ class LogSumExpTest(test_util.TensorFlowTestCase): y_np = log(np.sum(exp(x_np - max_np))) + max_np self.assertAllClose(y_tf_np, y_np) + @test_util.run_deprecated_v1 def testUnderflow(self): x = [-1000, -1001, -1002, -1003] for dtype in [np.float16, np.float32, np.double]: @@ -163,6 +167,7 @@ class LogSumExpTest(test_util.TensorFlowTestCase): y_np = log(np.sum(exp(x_np - max_np))) + max_np self.assertAllClose(y_tf_np, y_np) + @test_util.run_deprecated_v1 def testInfinity(self): with self.session(use_gpu=True): res = math_ops.reduce_logsumexp(-np.inf).eval() @@ -186,6 +191,7 @@ class RoundTest(test_util.TensorFlowTestCase): class ModTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testFloat(self): x = [0.5, 0.7, 0.3] for dtype in [np.float32, np.double]: @@ -195,7 +201,7 @@ class ModTest(test_util.TensorFlowTestCase): with self.cached_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y_tf = math_ops.mod(x_tf, denom) - y_tf_np = y_tf.eval() + y_tf_np = self.evaluate(y_tf) y_np = np.fmod(x_np, denom) self.assertAllClose(y_tf_np, y_np, atol=1e-2) @@ -208,7 +214,7 @@ class ModTest(test_util.TensorFlowTestCase): with self.cached_session(use_gpu=True): x_tf = constant_op.constant(x_np, shape=x_np.shape) y_tf = math_ops.mod(x_tf, denom) - y_tf_np = y_tf.eval() + y_tf_np = self.evaluate(y_tf) y_np = np.mod(x_np, denom) self.assertAllClose(y_tf_np, y_np) @@ -256,6 +262,7 @@ class ApproximateEqualTest(test_util.TensorFlowTestCase): z_tf = self.evaluate(math_ops.approximate_equal(x, y, tolerance=0.0001)) self.assertAllEqual(z, z_tf) + @test_util.run_deprecated_v1 def testApproximateEqualShape(self): for dtype in [np.float32, np.double]: x = np.array([1, 2], dtype=dtype) @@ -309,6 +316,7 @@ class ScalarMulTest(test_util.TensorFlowTestCase): class AccumulateNTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testFloat(self): np.random.seed(12345) x = [np.random.random((1, 2, 3, 4, 5)) - 0.5 for _ in range(5)] @@ -317,6 +325,7 @@ class AccumulateNTest(test_util.TensorFlowTestCase): self.assertAllClose(sum(x), math_ops.accumulate_n(tf_x).eval()) self.assertAllClose(x[0] * 5, math_ops.accumulate_n([tf_x[0]] * 5).eval()) + @test_util.run_deprecated_v1 def testInt(self): np.random.seed(54321) x = [np.random.randint(-128, 128, (5, 4, 3, 2, 1)) for _ in range(6)] @@ -328,6 +337,7 @@ class AccumulateNTest(test_util.TensorFlowTestCase): class AddNTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testPartials(self): """Test that previously revealed a bug in buffer forwarding for AddN.""" partials = [] @@ -341,6 +351,7 @@ class AddNTest(test_util.TensorFlowTestCase): with self.session(use_gpu=True): self.assertAllEqual(res.eval(), 100) + @test_util.run_deprecated_v1 def testFloat(self): np.random.seed(12345) for num_inputs in range(1, 10): @@ -351,6 +362,7 @@ class AddNTest(test_util.TensorFlowTestCase): self.assertAllClose(x[0] * num_inputs, math_ops.add_n([tf_x[0]] * num_inputs).eval()) + @test_util.run_deprecated_v1 def testInt(self): np.random.seed(54321) for num_inputs in range(1, 10): @@ -364,6 +376,7 @@ class AddNTest(test_util.TensorFlowTestCase): self.assertAllEqual(x[0] * num_inputs, math_ops.add_n([tf_x[0]] * num_inputs).eval()) + @test_util.run_deprecated_v1 def testGrad(self): np.random.seed(42) for num_inputs in range(1, 10): @@ -373,7 +386,7 @@ class AddNTest(test_util.TensorFlowTestCase): for i in range(0, num_inputs) ] addn = math_ops.add_n(input_vars) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) add_n_grad = gradients.gradients(addn, input_vars) self.assertAllEqual(np.repeat(1.0, num_inputs), # d/dx (x + y + ...) = 1 [g.eval() for g in add_n_grad]) @@ -392,6 +405,7 @@ class DivAndModTest(test_util.TensorFlowTestCase): divs = np.arange(-3, 0, .25).reshape(1, 12) return nums, divs + @test_util.run_deprecated_v1 def testFloorModInt(self): nums, divs = self.intTestData() with self.cached_session(): @@ -401,6 +415,7 @@ class DivAndModTest(test_util.TensorFlowTestCase): np_result = nums % divs self.assertAllEqual(tf_result, np_result) + @test_util.run_deprecated_v1 def testFloorModFloat(self): nums, divs = self.floatTestData() with self.cached_session(): @@ -412,6 +427,7 @@ class DivAndModTest(test_util.TensorFlowTestCase): # % array_ops.constant(divs)).eval() # self.assertAllEqual(tf2_result, tf_result) + @test_util.run_deprecated_v1 def testTruncateModInt(self): nums, divs = self.intTestData() with self.cached_session(): @@ -419,6 +435,7 @@ class DivAndModTest(test_util.TensorFlowTestCase): np_result = np.fmod(nums, divs) self.assertAllEqual(tf_result, np_result) + @test_util.run_deprecated_v1 def testTruncateModFloat(self): nums, divs = self.floatTestData() with self.cached_session(): @@ -426,6 +443,7 @@ class DivAndModTest(test_util.TensorFlowTestCase): np_result = np.fmod(nums, divs) self.assertAllEqual(tf_result, np_result) + @test_util.run_deprecated_v1 def testDivideInt(self): nums, divs = self.intTestData() with self.cached_session(): @@ -437,12 +455,14 @@ class DivAndModTest(test_util.TensorFlowTestCase): # // array_ops.constant(divs)).eval() # self.assertAllEqual(tf2_result, tf_result) + @test_util.run_deprecated_v1 def testDivideName(self): with self.cached_session(): op = math_ops.divide( array_ops.constant(3), array_ops.constant(4), name="my_cool_divide") self.assertEqual(op.name, "my_cool_divide:0") + @test_util.run_deprecated_v1 def testRealDiv(self): nums, divs = self.floatTestData() with self.cached_session(): @@ -450,26 +470,30 @@ class DivAndModTest(test_util.TensorFlowTestCase): np_result = np.divide(nums, divs) self.assertAllEqual(tf_result, np_result) + @test_util.run_deprecated_v1 def testComplexDiv(self): foo = array_ops.constant([1. + 3.j]) with self.cached_session(): _ = math_ops.divide(foo, 1.).eval() _ = math_ops.div(foo, 2.).eval() + @test_util.run_deprecated_v1 def testFloorDivGrad(self): with self.cached_session(): a = variables.Variable(2.) b = variables.Variable(4.) with self.cached_session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) c_grad = gradients.gradients(math_ops.divide(a, b), [a, b]) self.assertAllEqual([x.eval() for x in c_grad], [.25, -.125]) c_grad = gradients.gradients(math_ops.div(a, b), [a, b]) self.assertAllEqual([x.eval() for x in c_grad], [.25, -.125]) c_grad = gradients.gradients(math_ops.floordiv(a, b), [a, b]) - self.assertAllEqual([None if x is None else x.eval() - for x in c_grad], [None, None]) + self.assertAllEqual( + [None if x is None else self.evaluate(x) for x in c_grad], + [None, None]) + @test_util.run_deprecated_v1 def testConsistent(self): nums, divs = self.intTestData() with self.cached_session(): @@ -496,6 +520,7 @@ class DivAndModTest(test_util.TensorFlowTestCase): class DivNoNanTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testBasic(self): for dtype in [np.float32, np.float64]: nums = np.arange(-10, 10, .25, dtype=dtype).reshape(80, 1) diff --git a/tensorflow/python/ops/metrics_impl.py b/tensorflow/python/ops/metrics_impl.py index e86a3b8536..cb42199011 100644 --- a/tensorflow/python/ops/metrics_impl.py +++ b/tensorflow/python/ops/metrics_impl.py @@ -18,7 +18,6 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.python.compat import compat from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops @@ -213,26 +212,6 @@ def _maybe_expand_labels(labels, predictions): lambda: array_ops.expand_dims(labels, -1, name=scope), lambda: labels) -def _safe_div(numerator, denominator, name): - """Divides two tensors element-wise, returning 0 if the denominator is <= 0. - - Args: - numerator: A real `Tensor`. - denominator: A real `Tensor`, with dtype matching `numerator`. - name: Name for the returned op. - - Returns: - 0 if `denominator` <= 0, else `numerator` / `denominator` - """ - if compat.forward_compatible(2018, 11, 1): - return math_ops.div_no_nan(numerator, denominator, name=name) - t = math_ops.truediv(numerator, denominator) - zero = array_ops.zeros_like(t, dtype=denominator.dtype) - condition = math_ops.greater(denominator, zero) - zero = math_ops.cast(zero, t.dtype) - return array_ops.where(condition, t, zero, name=name) - - def _safe_scalar_div(numerator, denominator, name): """Divides two values, returning 0 if the denominator is 0. @@ -246,7 +225,7 @@ def _safe_scalar_div(numerator, denominator, name): """ numerator.get_shape().with_rank_at_most(1) denominator.get_shape().with_rank_at_most(1) - return _safe_div(numerator, denominator, name=name) + return math_ops.div_no_nan(numerator, denominator, name=name) def _streaming_confusion_matrix(labels, predictions, num_classes, weights=None): @@ -302,7 +281,7 @@ def _aggregate_across_replicas(metrics_collections, metric_value_fn, *args): """Aggregate metric value across replicas.""" def fn(distribution, *a): """Call `metric_value_fn` in the correct control flow context.""" - if hasattr(distribution, '_outer_control_flow_context'): + if hasattr(distribution.extended, '_outer_control_flow_context'): # If there was an outer context captured before this method was called, # then we enter that context to create the metric value op. If the # caputred context is `None`, ops.control_dependencies(None) gives the @@ -315,13 +294,13 @@ def _aggregate_across_replicas(metrics_collections, metric_value_fn, *args): # once the update ops have been evaluted. # pylint: disable=protected-access - if distribution._outer_control_flow_context is None: + if distribution.extended._outer_control_flow_context is None: with ops.control_dependencies(None): metric_value = metric_value_fn(distribution, *a) else: - distribution._outer_control_flow_context.Enter() + distribution.extended._outer_control_flow_context.Enter() metric_value = metric_value_fn(distribution, *a) - distribution._outer_control_flow_context.Exit() + distribution.extended._outer_control_flow_context.Exit() # pylint: enable=protected-access else: metric_value = metric_value_fn(distribution, *a) @@ -330,10 +309,10 @@ def _aggregate_across_replicas(metrics_collections, metric_value_fn, *args): return metric_value return distribution_strategy_context.get_replica_context().merge_call( - fn, *args) + fn, args=args) -@tf_export('metrics.mean') +@tf_export(v1=['metrics.mean']) def mean(values, weights=None, metrics_collections=None, @@ -401,13 +380,12 @@ def mean(values, update_count_op = state_ops.assign_add(count, num_values) def compute_mean(_, t, c): - return _safe_div(t, math_ops.maximum(c, 0), name='value') + return math_ops.div_no_nan(t, math_ops.maximum(c, 0), name='value') mean_t = _aggregate_across_replicas( metrics_collections, compute_mean, total, count) - update_op = _safe_div(update_total_op, - math_ops.maximum(update_count_op, 0), - name='update_op') + update_op = math_ops.div_no_nan( + update_total_op, math_ops.maximum(update_count_op, 0), name='update_op') if updates_collections: ops.add_to_collections(updates_collections, update_op) @@ -415,7 +393,7 @@ def mean(values, return mean_t, update_op -@tf_export('metrics.accuracy') +@tf_export(v1=['metrics.accuracy']) def accuracy(labels, predictions, weights=None, @@ -647,7 +625,7 @@ def _aggregate_variable(v, collections): return _aggregate_across_replicas(collections, f, v) -@tf_export('metrics.auc') +@tf_export(v1=['metrics.auc']) def auc(labels, predictions, weights=None, @@ -779,19 +757,19 @@ def auc(labels, """ dtp = tp[:num_thresholds - 1] - tp[1:] p = tp + fp - prec_slope = _safe_div( + prec_slope = math_ops.div_no_nan( dtp, math_ops.maximum(p[:num_thresholds - 1] - p[1:], 0), name='prec_slope') intercept = tp[1:] - math_ops.multiply(prec_slope, p[1:]) safe_p_ratio = array_ops.where( math_ops.logical_and(p[:num_thresholds - 1] > 0, p[1:] > 0), - _safe_div(p[:num_thresholds - 1], - math_ops.maximum(p[1:], 0), - name='recall_relative_ratio'), - array_ops.ones_like(p[1:])) + math_ops.div_no_nan( + p[:num_thresholds - 1], + math_ops.maximum(p[1:], 0), + name='recall_relative_ratio'), array_ops.ones_like(p[1:])) return math_ops.reduce_sum( - _safe_div( + math_ops.div_no_nan( prec_slope * (dtp + intercept * math_ops.log(safe_p_ratio)), math_ops.maximum(tp[1:] + fn[1:], 0), name='pr_auc_increment'), @@ -852,7 +830,7 @@ def auc(labels, return auc_value, update_op -@tf_export('metrics.mean_absolute_error') +@tf_export(v1=['metrics.mean_absolute_error']) def mean_absolute_error(labels, predictions, weights=None, @@ -913,7 +891,7 @@ def mean_absolute_error(labels, updates_collections, name or 'mean_absolute_error') -@tf_export('metrics.mean_cosine_distance') +@tf_export(v1=['metrics.mean_cosine_distance']) def mean_cosine_distance(labels, predictions, dim, @@ -970,7 +948,7 @@ def mean_cosine_distance(labels, predictions=predictions, labels=labels, weights=weights) radial_diffs = math_ops.multiply(predictions, labels) radial_diffs = math_ops.reduce_sum( - radial_diffs, reduction_indices=[ + radial_diffs, axis=[ dim, ], keepdims=True) mean_distance, update_op = mean(radial_diffs, weights, None, None, name or @@ -987,7 +965,7 @@ def mean_cosine_distance(labels, return mean_distance, update_op -@tf_export('metrics.mean_per_class_accuracy') +@tf_export(v1=['metrics.mean_per_class_accuracy']) def mean_per_class_accuracy(labels, predictions, num_classes, @@ -1074,7 +1052,7 @@ def mean_per_class_accuracy(labels, update_count_op = state_ops.scatter_add(count, labels, is_correct) def compute_mean_accuracy(_, count, total): - per_class_accuracy = _safe_div( + per_class_accuracy = math_ops.div_no_nan( count, math_ops.maximum(total, 0), name=None) mean_accuracy_v = math_ops.reduce_mean( per_class_accuracy, name='mean_accuracy') @@ -1083,16 +1061,15 @@ def mean_per_class_accuracy(labels, mean_accuracy_v = _aggregate_across_replicas( metrics_collections, compute_mean_accuracy, count, total) - update_op = _safe_div(update_count_op, - math_ops.maximum(update_total_op, 0), - name='update_op') + update_op = math_ops.div_no_nan( + update_count_op, math_ops.maximum(update_total_op, 0), name='update_op') if updates_collections: ops.add_to_collections(updates_collections, update_op) return mean_accuracy_v, update_op -@tf_export('metrics.mean_iou') +@tf_export(v1=['metrics.mean_iou']) def mean_iou(labels, predictions, num_classes, @@ -1193,7 +1170,7 @@ def mean_iou(labels, return mean_iou_v, update_op -@tf_export('metrics.mean_relative_error') +@tf_export(v1=['metrics.mean_relative_error']) def mean_relative_error(labels, predictions, normalizer, @@ -1262,7 +1239,7 @@ def mean_relative_error(labels, updates_collections, name or 'mean_relative_error') -@tf_export('metrics.mean_squared_error') +@tf_export(v1=['metrics.mean_squared_error']) def mean_squared_error(labels, predictions, weights=None, @@ -1323,7 +1300,7 @@ def mean_squared_error(labels, name or 'mean_squared_error') -@tf_export('metrics.mean_tensor') +@tf_export(v1=['metrics.mean_tensor']) def mean_tensor(values, weights=None, metrics_collections=None, @@ -1394,22 +1371,21 @@ def mean_tensor(values, with ops.control_dependencies([values]): update_count_op = state_ops.assign_add(count, num_values) - compute_mean = lambda _, t, c: _safe_div( + compute_mean = lambda _, t, c: math_ops.div_no_nan( # pylint: disable=g-long-lambda t, math_ops.maximum(c, 0), name='value') mean_t = _aggregate_across_replicas( metrics_collections, compute_mean, total, count) - update_op = _safe_div(update_total_op, - math_ops.maximum(update_count_op, 0), - name='update_op') + update_op = math_ops.div_no_nan( + update_total_op, math_ops.maximum(update_count_op, 0), name='update_op') if updates_collections: ops.add_to_collections(updates_collections, update_op) return mean_t, update_op -@tf_export('metrics.percentage_below') +@tf_export(v1=['metrics.percentage_below']) def percentage_below(values, threshold, weights=None, @@ -1509,7 +1485,7 @@ def _count_condition(values, return value_tensor, update_op -@tf_export('metrics.false_negatives') +@tf_export(v1=['metrics.false_negatives']) def false_negatives(labels, predictions, weights=None, @@ -1561,7 +1537,7 @@ def false_negatives(labels, updates_collections) -@tf_export('metrics.false_negatives_at_thresholds') +@tf_export(v1=['metrics.false_negatives_at_thresholds']) def false_negatives_at_thresholds(labels, predictions, thresholds, @@ -1617,7 +1593,7 @@ def false_negatives_at_thresholds(labels, return fn_value, update_ops['fn'] -@tf_export('metrics.false_positives') +@tf_export(v1=['metrics.false_positives']) def false_positives(labels, predictions, weights=None, @@ -1670,7 +1646,7 @@ def false_positives(labels, updates_collections) -@tf_export('metrics.false_positives_at_thresholds') +@tf_export(v1=['metrics.false_positives_at_thresholds']) def false_positives_at_thresholds(labels, predictions, thresholds, @@ -1726,7 +1702,7 @@ def false_positives_at_thresholds(labels, return fp_value, update_ops['fp'] -@tf_export('metrics.true_negatives') +@tf_export(v1=['metrics.true_negatives']) def true_negatives(labels, predictions, weights=None, @@ -1779,7 +1755,7 @@ def true_negatives(labels, updates_collections) -@tf_export('metrics.true_negatives_at_thresholds') +@tf_export(v1=['metrics.true_negatives_at_thresholds']) def true_negatives_at_thresholds(labels, predictions, thresholds, @@ -1835,7 +1811,7 @@ def true_negatives_at_thresholds(labels, return tn_value, update_ops['tn'] -@tf_export('metrics.true_positives') +@tf_export(v1=['metrics.true_positives']) def true_positives(labels, predictions, weights=None, @@ -1888,7 +1864,7 @@ def true_positives(labels, updates_collections) -@tf_export('metrics.true_positives_at_thresholds') +@tf_export(v1=['metrics.true_positives_at_thresholds']) def true_positives_at_thresholds(labels, predictions, thresholds, @@ -1944,7 +1920,7 @@ def true_positives_at_thresholds(labels, return tp_value, update_ops['tp'] -@tf_export('metrics.precision') +@tf_export(v1=['metrics.precision']) def precision(labels, predictions, weights=None, @@ -2039,7 +2015,7 @@ def precision(labels, return p, update_op -@tf_export('metrics.precision_at_thresholds') +@tf_export(v1=['metrics.precision_at_thresholds']) def precision_at_thresholds(labels, predictions, thresholds, @@ -2120,7 +2096,7 @@ def precision_at_thresholds(labels, return prec, update_op -@tf_export('metrics.recall') +@tf_export(v1=['metrics.recall']) def recall(labels, predictions, weights=None, @@ -2471,7 +2447,7 @@ def _streaming_sparse_false_negative_at_k(labels, return var, state_ops.assign_add(var, batch_total_fn, name='update') -@tf_export('metrics.recall_at_k') +@tf_export(v1=['metrics.recall_at_k']) def recall_at_k(labels, predictions, k, @@ -2564,7 +2540,7 @@ def recall_at_k(labels, name=scope) -@tf_export('metrics.recall_at_top_k') +@tf_export(v1=['metrics.recall_at_top_k']) def recall_at_top_k(labels, predictions_idx, k=None, @@ -2648,7 +2624,7 @@ def recall_at_top_k(labels, return metric, update -@tf_export('metrics.recall_at_thresholds') +@tf_export(v1=['metrics.recall_at_thresholds']) def recall_at_thresholds(labels, predictions, thresholds, @@ -2726,7 +2702,7 @@ def recall_at_thresholds(labels, return rec, update_op -@tf_export('metrics.root_mean_squared_error') +@tf_export(v1=['metrics.root_mean_squared_error']) def root_mean_squared_error(labels, predictions, weights=None, @@ -2797,7 +2773,7 @@ def root_mean_squared_error(labels, return rmse, update_rmse_op -@tf_export('metrics.sensitivity_at_specificity') +@tf_export(v1=['metrics.sensitivity_at_specificity']) def sensitivity_at_specificity(labels, predictions, specificity, @@ -3069,7 +3045,7 @@ def _sparse_average_precision_at_top_k(labels, predictions_idx): # Reduce along k dimension to get the sum, yielding a [D1, ... DN] tensor. precision_sum = math_ops.reduce_sum( - relevant_precision_per_k, reduction_indices=(-1,), name='precision_sum') + relevant_precision_per_k, axis=(-1,), name='precision_sum') # Divide by number of relevant items to get average precision. These are # the "num_relevant_items" and "AveP" terms from the formula above. @@ -3170,7 +3146,7 @@ def _streaming_sparse_average_precision_at_top_k(labels, return mean_average_precision, update -@tf_export('metrics.sparse_average_precision_at_k') +@tf_export(v1=['metrics.sparse_average_precision_at_k']) @deprecated(None, 'Use average_precision_at_k instead') def sparse_average_precision_at_k(labels, predictions, @@ -3190,7 +3166,7 @@ def sparse_average_precision_at_k(labels, name=name) -@tf_export('metrics.average_precision_at_k') +@tf_export(v1=['metrics.average_precision_at_k']) def average_precision_at_k(labels, predictions, k, @@ -3364,7 +3340,7 @@ def _streaming_sparse_false_positive_at_k(labels, return var, state_ops.assign_add(var, batch_total_fp, name='update') -@tf_export('metrics.precision_at_top_k') +@tf_export(v1=['metrics.precision_at_top_k']) def precision_at_top_k(labels, predictions_idx, k=None, @@ -3453,7 +3429,7 @@ def precision_at_top_k(labels, return metric, update -@tf_export('metrics.sparse_precision_at_k') +@tf_export(v1=['metrics.sparse_precision_at_k']) @deprecated(None, 'Use precision_at_k instead') def sparse_precision_at_k(labels, predictions, @@ -3475,7 +3451,7 @@ def sparse_precision_at_k(labels, name=name) -@tf_export('metrics.precision_at_k') +@tf_export(v1=['metrics.precision_at_k']) def precision_at_k(labels, predictions, k, @@ -3569,7 +3545,7 @@ def precision_at_k(labels, name=scope) -@tf_export('metrics.specificity_at_sensitivity') +@tf_export(v1=['metrics.specificity_at_sensitivity']) def specificity_at_sensitivity(labels, predictions, sensitivity, diff --git a/tensorflow/python/ops/nccl_ops_test.py b/tensorflow/python/ops/nccl_ops_test.py index 1b496fec47..3b2e2b0175 100644 --- a/tensorflow/python/ops/nccl_ops_test.py +++ b/tensorflow/python/ops/nccl_ops_test.py @@ -102,7 +102,7 @@ class NcclTestCase(test.TestCase): continue # Test execution and results. - for t in sess.run(result_tensors): + for t in self.evaluate(result_tensors): self.assertAllClose(t, np_ans) def _TestGradient(self, nccl_reduce, numpy_fn): diff --git a/tensorflow/python/ops/nn_batchnorm_test.py b/tensorflow/python/ops/nn_batchnorm_test.py index c8a5b58e45..e978f1d326 100644 --- a/tensorflow/python/ops/nn_batchnorm_test.py +++ b/tensorflow/python/ops/nn_batchnorm_test.py @@ -71,6 +71,7 @@ class BatchNormalizationTest(test.TestCase): gamma if scale_after_normalization else None, epsilon) + @test_util.run_deprecated_v1 def testBatchNorm(self): x_shape = [3, 5, 4, 2] param_shape = [2] @@ -169,16 +170,20 @@ class BatchNormalizationTest(test.TestCase): shift_after_normalization, v, err_tolerance) + @test_util.run_deprecated_v1 def testBatchNormInputGradient(self): self._testBatchNormGradientInAllNeedConfigs(0, "x") + @test_util.run_deprecated_v1 def testBatchNormMeanGradient(self): self._testBatchNormGradientInAllNeedConfigs(1, "mean") + @test_util.run_deprecated_v1 def testBatchNormVarianceGradient(self): self._testBatchNormGradientInAllNeedConfigs( 2, "variance", err_tolerance=1e-03) + @test_util.run_deprecated_v1 def testBatchNormBetaGradient(self): # Since beta does not exist when scale_after_normalization=False, we only # test for scale_after_normalization=True. @@ -187,6 +192,7 @@ class BatchNormalizationTest(test.TestCase): self._testBatchNormGradient(3, "beta", scale_after_normalization, True, v) + @test_util.run_deprecated_v1 def testBatchNormGammaGradient(self): # If scale_after_normalization is False, backprop for gamma in v1 # will be 0. In version 2 of the API, if scale_after_normalization is False, @@ -199,6 +205,7 @@ class BatchNormalizationTest(test.TestCase): self._testBatchNormGradient(4, "gamma", True, shift_after_normalization, 2) + @test_util.run_deprecated_v1 def testBatchNormGradImpl(self): x_shape = [7, 5, 4, 6] param_shape = [6] @@ -235,15 +242,17 @@ class BatchNormalizationTest(test.TestCase): odx, odm, odv, odb, odg = gradients_impl.gradients( [on], [x, m, v, beta, gamma], [backprop]) if scale_after_normalization: - all_grads = sess.run([dx, dm, dv, db, dg, odx, odm, odv, odb, odg]) + all_grads = self.evaluate( + [dx, dm, dv, db, dg, odx, odm, odv, odb, odg]) to_check = ["dx", "dm", "dv", "db", "dg"] else: - all_grads = sess.run([dx, dm, dv, db, odx, odm, odv, odb]) + all_grads = self.evaluate([dx, dm, dv, db, odx, odm, odv, odb]) to_check = ["dx", "dm", "dv", "db"] for i, _ in enumerate(to_check): self.assertAllClose( all_grads[i + len(to_check)], all_grads[i], atol=0.000001) + @test_util.run_deprecated_v1 def testBatchNormKeepDims(self): """Test for tf.nn.moments(..., keep_dims=True / False). @@ -318,7 +327,7 @@ class BatchNormalizationTest(test.TestCase): gamma_val, epsilon, scale_after_normalization, shift_after_normalization) - [tf_batch_norm] = sess.run([bn]) + [tf_batch_norm] = self.evaluate([bn]) self.assertEquals(x_shape, np_batch_norm.shape) self.assertEquals(x_shape, tf_batch_norm.shape) self.assertAllClose(np_batch_norm, tf_batch_norm, atol=atol) @@ -371,9 +380,9 @@ class SufficientStatisticsTest(test.TestCase): x.set_shape(x_shape) op_c, op_m, op_v, op_s = self._opSuffStats(x, axes, shift, keep_dims) if shift: - tf_c, tf_m, tf_v, tf_s = sess.run([op_c, op_m, op_v, op_s]) + tf_c, tf_m, tf_v, tf_s = self.evaluate([op_c, op_m, op_v, op_s]) else: - tf_c, tf_m, tf_v = sess.run([op_c, op_m, op_v]) + tf_c, tf_m, tf_v = self.evaluate([op_c, op_m, op_v]) else: x = array_ops.placeholder( dtype=dtypes.float32, shape=[None] * len(x_shape), name="x") @@ -390,6 +399,7 @@ class SufficientStatisticsTest(test.TestCase): if shift: self.assertAllClose(np_s, tf_s, atol=0.000001) + @test_util.run_deprecated_v1 def testSuffStats(self): for has_shape in [True, False]: for keep_dims in [True, False]: @@ -432,7 +442,7 @@ class NormalizeMomentsTest(test.TestCase): tf_shift_v = None opm, opv = self._opNormalizeMoments(tf_counts, tf_mean_ss, tf_variance_ss, tf_shift_v) - tfm, tfv = sess.run([opm, opv]) + tfm, tfv = self.evaluate([opm, opv]) self.assertAllClose(npm, tfm, atol=0.000001) self.assertAllClose(npv, tfv, atol=0.000001) @@ -507,9 +517,10 @@ class MomentsTest(test.TestCase): expected_variance = expected_x_squared - expected_mean_squared # Check that the moments are correct. - self.assertAllCloseAccordingToType(expected_mean, mean.eval()) - self.assertAllCloseAccordingToType(expected_variance, var.eval()) + self.assertAllCloseAccordingToType(expected_mean, self.evaluate(mean)) + self.assertAllCloseAccordingToType(expected_variance, self.evaluate(var)) + @test_util.run_deprecated_v1 def testBasic(self): for keep_dims in [False, True]: for dtype in [dtypes.float32, dtypes.float16]: @@ -518,6 +529,7 @@ class MomentsTest(test.TestCase): self.RunMomentTestWithDynamicShape( shape=[2, 3, 5, 4], axes=[0], keep_dims=keep_dims, dtype=dtype) + @test_util.run_deprecated_v1 def testGlobalNormalization(self): for keep_dims in [False, True]: for dtype in [dtypes.float32, dtypes.float16]: @@ -532,6 +544,7 @@ class MomentsTest(test.TestCase): keep_dims=keep_dims, dtype=dtype) + @test_util.run_deprecated_v1 def testAxes(self): for keep_dims in [False, True]: for dtype in [dtypes.float32, dtypes.float16]: @@ -572,9 +585,11 @@ class MomentsTest(test.TestCase): print("Moments %s gradient err vs input %d = %g" % (from_y, i, err)) self.assertLess(err, 1e-11) + @test_util.run_deprecated_v1 def testMeanGlobalGradient(self): self._testGlobalGradient(from_y="mean") + @test_util.run_deprecated_v1 def testVarGlobalGradient(self): self._testGlobalGradient(from_y="var") diff --git a/tensorflow/python/ops/nn_fused_batchnorm_test.py b/tensorflow/python/ops/nn_fused_batchnorm_test.py index 5ac8eba6f7..4bc33ff8bd 100644 --- a/tensorflow/python/ops/nn_fused_batchnorm_test.py +++ b/tensorflow/python/ops/nn_fused_batchnorm_test.py @@ -50,7 +50,7 @@ class BatchNormalizationTest(test.TestCase): y = self._batch_norm(x, mean, var, offset, scale, epsilon) if data_format == 'NCHW': y = array_ops.transpose(y, [0, 3, 1, 2]) - return y.eval() + return self.evaluate(y) def _test_inference(self, x_shape, @@ -82,7 +82,7 @@ class BatchNormalizationTest(test.TestCase): epsilon=epsilon, data_format=data_format, is_training=False) - y_val = sess.run(y) + y_val = self.evaluate(y) y_ref = self._inference_ref(x, scale, offset, mean, var, epsilon, data_format) # An atol value of 1e-3 is too small for float16's, because some adjacent @@ -102,7 +102,7 @@ class BatchNormalizationTest(test.TestCase): y = self._batch_norm(x, mean, var, offset, scale, epsilon) if data_format == 'NCHW': y = array_ops.transpose(y, [0, 3, 1, 2]) - return y.eval(), mean.eval(), var.eval() + return self.evaluate(y), self.evaluate(mean), self.evaluate(var) def _test_training(self, x_shape, @@ -127,7 +127,7 @@ class BatchNormalizationTest(test.TestCase): epsilon=epsilon, data_format=data_format, is_training=True) - y_val, mean_val, var_val = sess.run([y, mean, var]) + y_val, mean_val, var_val = self.evaluate([y, mean, var]) y_ref, mean_ref, var_ref = self._training_ref(x, scale, offset, epsilon, data_format) y_atol = 2e-3 if x_dtype == np.float16 else 1e-3 @@ -277,10 +277,10 @@ class BatchNormalizationTest(test.TestCase): if is_training: epsilon = y.op.get_attr('epsilon') data_format = y.op.get_attr('data_format') - grad_vals = sess.run([grad_x, grad_scale, grad_offset]) + grad_vals = self.evaluate([grad_x, grad_scale, grad_offset]) grad_internal = nn_grad._BatchNormGrad(grad_y, x, scale, pop_mean, pop_var, epsilon, data_format) - grad_internal_vals = sess.run(list(grad_internal)) + grad_internal_vals = self.evaluate(list(grad_internal)) for grad_val, grad_internal_val in zip(grad_vals, grad_internal_vals): self.assertAllClose(grad_val, grad_internal_val, atol=err_tolerance) diff --git a/tensorflow/python/ops/nn_grad.py b/tensorflow/python/ops/nn_grad.py index 902653befc..34404edc9a 100644 --- a/tensorflow/python/ops/nn_grad.py +++ b/tensorflow/python/ops/nn_grad.py @@ -18,13 +18,13 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.eager import backprop from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_nn_ops -from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import math_ops from tensorflow.python.ops import nn_ops @@ -948,10 +948,14 @@ def _FusedBatchNormGradGrad(op, *grad): grad_grad_x = grad[0] grad_grad_scale = grad[1] grad_grad_offset = grad[2] - grad_x, grad_scale, grad_offset = _BatchNormGrad( - grad_y, x, scale, pop_mean, pop_var, epsilon, data_format, is_training) - grad_initial = [grad_grad_x, grad_grad_scale, grad_grad_offset] - grad_grad_y, grad_x, grad_scale = gradients_impl.gradients( + with backprop.GradientTape() as tape: + tape.watch(grad_y) + tape.watch(x) + tape.watch(scale) + grad_x, grad_scale, grad_offset = _BatchNormGrad( + grad_y, x, scale, pop_mean, pop_var, epsilon, data_format, is_training) + grad_initial = [grad_grad_x, grad_grad_scale, grad_grad_offset] + grad_grad_y, grad_x, grad_scale = tape.gradient( [grad_x, grad_scale, grad_offset], [grad_y, x, scale], grad_initial) return grad_grad_y, grad_x, grad_scale, None, None diff --git a/tensorflow/python/ops/nn_grad_test.py b/tensorflow/python/ops/nn_grad_test.py index 8065df4b16..95e05a977b 100644 --- a/tensorflow/python/ops/nn_grad_test.py +++ b/tensorflow/python/ops/nn_grad_test.py @@ -22,6 +22,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import nn_grad # pylint: disable=unused-import @@ -31,6 +32,7 @@ from tensorflow.python.platform import test class Relu6OpTest(test.TestCase): + @test_util.run_deprecated_v1 def testRelu6GradGrad(self): inputs = constant_op.constant( [[-2, -1, 1, 3], [5, 7, 8, 9]], dtype=dtypes.float32) diff --git a/tensorflow/python/ops/nn_impl.py b/tensorflow/python/ops/nn_impl.py index ef763a4b61..8f74f831c1 100644 --- a/tensorflow/python/ops/nn_impl.py +++ b/tensorflow/python/ops/nn_impl.py @@ -329,7 +329,7 @@ def swish(features): return features * math_ops.sigmoid(features) -@tf_export("math.l2_normalize", "linalg.l2_normalize", "nn.l2_normalize") +@tf_export(v1=["math.l2_normalize", "linalg.l2_normalize", "nn.l2_normalize"]) @deprecated_args(None, "dim is deprecated, use axis instead", "dim") def l2_normalize(x, axis=None, epsilon=1e-12, name=None, dim=None): """Normalizes along dimension `axis` using an L2 norm. @@ -350,11 +350,36 @@ def l2_normalize(x, axis=None, epsilon=1e-12, name=None, dim=None): name: A name for this operation (optional). dim: Deprecated alias for axis. + Returns: + A `Tensor` with the same shape as `x`. + """ + axis = deprecated_argument_lookup("axis", axis, "dim", dim) + return l2_normalize_v2(x, axis, epsilon, name) + + +@tf_export("math.l2_normalize", "linalg.l2_normalize", "nn.l2_normalize", v1=[]) +def l2_normalize_v2(x, axis=None, epsilon=1e-12, name=None): + """Normalizes along dimension `axis` using an L2 norm. + + For a 1-D tensor with `axis = 0`, computes + + output = x / sqrt(max(sum(x**2), epsilon)) + + For `x` with more dimensions, independently normalizes each 1-D slice along + dimension `axis`. + + Args: + x: A `Tensor`. + axis: Dimension along which to normalize. A scalar or a vector of + integers. + epsilon: A lower bound value for the norm. Will use `sqrt(epsilon)` as the + divisor if `norm < sqrt(epsilon)`. + name: A name for this operation (optional). + Returns: A `Tensor` with the same shape as `x`. """ with ops.name_scope(name, "l2_normalize", [x]) as name: - axis = deprecated_argument_lookup("axis", axis, "dim", dim) x = ops.convert_to_tensor(x, name="x") square_sum = math_ops.reduce_sum(math_ops.square(x), axis, keepdims=True) x_inv_norm = math_ops.rsqrt(math_ops.maximum(square_sum, epsilon)) @@ -424,7 +449,7 @@ def zero_fraction(value, name=None): # pylint: disable=redefined-builtin -@tf_export("nn.depthwise_conv2d") +@tf_export(v1=["nn.depthwise_conv2d"]) def depthwise_conv2d(input, filter, strides, @@ -497,11 +522,68 @@ def depthwise_conv2d(input, op=op) +@tf_export("nn.depthwise_conv2d", v1=[]) +def depthwise_conv2d_v2(input, + filter, + strides, + padding, + data_format=None, + dilations=None, + name=None): + """Depthwise 2-D convolution. + + Given a 4D input tensor ('NHWC' or 'NCHW' data formats) + and a filter tensor of shape + `[filter_height, filter_width, in_channels, channel_multiplier]` + containing `in_channels` convolutional filters of depth 1, `depthwise_conv2d` + applies a different filter to each input channel (expanding from 1 channel + to `channel_multiplier` channels for each), then concatenates the results + together. The output has `in_channels * channel_multiplier` channels. + + In detail, + + output[b, i, j, k * channel_multiplier + q] = sum_{di, dj} + filter[di, dj, k, q] * input[b, strides[1] * i + rate[0] * di, + strides[2] * j + rate[1] * dj, k] + + Must have `strides[0] = strides[3] = 1`. For the most common case of the + same horizontal and vertical strides, `strides = [1, stride, stride, 1]`. + If any value in `rate` is greater than 1, we perform atrous depthwise + convolution, in which case all values in the `strides` tensor must be equal + to 1. + + Args: + input: 4-D with shape according to `data_format`. + filter: 4-D with shape + `[filter_height, filter_width, in_channels, channel_multiplier]`. + strides: 1-D of size 4. The stride of the sliding window for each + dimension of `input`. + padding: A string, either `'VALID'` or `'SAME'`. The padding algorithm. + See the "returns" section of `tf.nn.convolution` for details. + data_format: The data format for input. Either "NHWC" (default) or "NCHW". + dilations: 1-D of size 2. The dilation rate in which we sample input values + across the `height` and `width` dimensions in atrous convolution. If it is + greater than 1, then all values of strides must be 1. + name: A name for this operation (optional). + + Returns: + A 4-D `Tensor` with shape according to `data_format`. E.g., for + "NHWC" format, shape is + `[batch, out_height, out_width, in_channels * channel_multiplier].` + """ + return depthwise_conv2d(input=input, + filter=filter, + strides=strides, + padding=padding, + rate=dilations, + name=name, + data_format=data_format) + # pylint: enable=redefined-builtin # pylint: disable=redefined-builtin,line-too-long -@tf_export("nn.separable_conv2d") +@tf_export(v1=["nn.separable_conv2d"]) def separable_conv2d(input, depthwise_filter, pointwise_filter, @@ -599,10 +681,76 @@ def separable_conv2d(input, name=name) +@tf_export("nn.separable_conv2d", v1=[]) +def separable_conv2d_v2( + input, + depthwise_filter, + pointwise_filter, + strides, + padding, + data_format=None, + dilations=None, + name=None, +): + """2-D convolution with separable filters. + + Performs a depthwise convolution that acts separately on channels followed by + a pointwise convolution that mixes channels. Note that this is separability + between dimensions `[1, 2]` and `3`, not spatial separability between + dimensions `1` and `2`. + + In detail, + + output[b, i, j, k] = sum_{di, dj, q, r} + input[b, strides[1] * i + di, strides[2] * j + dj, q] * + depthwise_filter[di, dj, q, r] * + pointwise_filter[0, 0, q * channel_multiplier + r, k] + + `strides` controls the strides for the depthwise convolution only, since + the pointwise convolution has implicit strides of `[1, 1, 1, 1]`. Must have + `strides[0] = strides[3] = 1`. For the most common case of the same + horizontal and vertical strides, `strides = [1, stride, stride, 1]`. + If any value in `rate` is greater than 1, we perform atrous depthwise + convolution, in which case all values in the `strides` tensor must be equal + to 1. + + Args: + input: 4-D `Tensor` with shape according to `data_format`. + depthwise_filter: 4-D `Tensor` with shape `[filter_height, filter_width, + in_channels, channel_multiplier]`. Contains `in_channels` convolutional + filters of depth 1. + pointwise_filter: 4-D `Tensor` with shape `[1, 1, channel_multiplier * + in_channels, out_channels]`. Pointwise filter to mix channels after + `depthwise_filter` has convolved spatially. + strides: 1-D of size 4. The strides for the depthwise convolution for each + dimension of `input`. + padding: A string, either `'VALID'` or `'SAME'`. The padding algorithm. See + the "returns" section of `tf.nn.convolution` for details. + data_format: The data format for input. Either "NHWC" (default) or "NCHW". + dilations: 1-D of size 2. The dilation rate in which we sample input values + across the `height` and `width` dimensions in atrous convolution. If it is + greater than 1, then all values of strides must be 1. + name: A name for this operation (optional). + + Returns: + A 4-D `Tensor` with shape according to 'data_format'. For + example, with data_format="NHWC", shape is [batch, out_height, + out_width, out_channels]. + """ + return separable_conv2d( + input, + depthwise_filter, + pointwise_filter, + strides, + padding, + rate=dilations, + name=name, + data_format=data_format) + # pylint: enable=redefined-builtin,line-too-long -@tf_export("nn.sufficient_statistics") +@tf_export(v1=["nn.sufficient_statistics"]) def sufficient_statistics(x, axes, shift=None, keep_dims=False, name=None): """Calculate the sufficient statistics for the mean and variance of `x`. @@ -652,6 +800,35 @@ def sufficient_statistics(x, axes, shift=None, keep_dims=False, name=None): return counts, m_ss, v_ss, shift +@tf_export("nn.sufficient_statistics", v1=[]) +def sufficient_statistics_v2(x, axes, shift=None, keepdims=False, name=None): + """Calculate the sufficient statistics for the mean and variance of `x`. + + These sufficient statistics are computed using the one pass algorithm on + an input that's optionally shifted. See: + https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Computing_shifted_data + + Args: + x: A `Tensor`. + axes: Array of ints. Axes along which to compute mean and variance. + shift: A `Tensor` containing the value by which to shift the data for + numerical stability, or `None` if no shift is to be performed. A shift + close to the true mean provides the most numerically stable results. + keepdims: produce statistics with the same dimensionality as the input. + name: Name used to scope the operations that compute the sufficient stats. + + Returns: + Four `Tensor` objects of the same type as `x`: + + * the count (number of elements to average over). + * the (possibly shifted) sum of the elements in the array. + * the (possibly shifted) sum of squares of the elements in the array. + * the shift by which the mean must be corrected or None if `shift` is None. + """ + return sufficient_statistics( + x=x, axes=axes, shift=shift, keep_dims=keepdims, name=name) + + @tf_export("nn.normalize_moments") def normalize_moments(counts, mean_ss, variance_ss, shift, name=None): """Calculate the mean and variance of based on the sufficient statistics. @@ -684,7 +861,7 @@ def normalize_moments(counts, mean_ss, variance_ss, shift, name=None): return (mean, variance) -@tf_export("nn.moments") +@tf_export(v1=["nn.moments"]) def moments( x, axes, @@ -743,7 +920,43 @@ def moments( return (mean, variance) -@tf_export("nn.weighted_moments") +@tf_export("nn.moments", v1=[]) +def moments_v2( + x, + axes, + shift=None, + keepdims=False, + name=None): + """Calculates the mean and variance of `x`. + + The mean and variance are calculated by aggregating the contents of `x` + across `axes`. If `x` is 1-D and `axes = [0]` this is just the mean + and variance of a vector. + + Note: shift is currently not used; the true mean is computed and used. + + When using these moments for batch normalization (see + `tf.nn.batch_normalization`): + + * for so-called "global normalization", used with convolutional filters with + shape `[batch, height, width, depth]`, pass `axes=[0, 1, 2]`. + * for simple batch normalization pass `axes=[0]` (batch only). + + Args: + x: A `Tensor`. + axes: Array of ints. Axes along which to compute mean and + variance. + shift: Not used in the current implementation. + keepdims: produce moments with the same dimensionality as the input. + name: Name used to scope the operations that compute the moments. + + Returns: + Two `Tensor` objects: `mean` and `variance`. + """ + return moments(x=x, axes=axes, shift=shift, name=name, keep_dims=keepdims) + + +@tf_export(v1=["nn.weighted_moments"]) def weighted_moments(x, axes, frequency_weights, name=None, keep_dims=False): """Returns the frequency-weighted mean and variance of `x`. @@ -815,6 +1028,30 @@ def weighted_moments(x, axes, frequency_weights, name=None, keep_dims=False): return weighted_mean, weighted_variance +@tf_export("nn.weighted_moments", v1=[]) +def weighted_moments_v2(x, axes, frequency_weights, keepdims=False, name=None): + """Returns the frequency-weighted mean and variance of `x`. + + Args: + x: A tensor. + axes: 1-d tensor of int32 values; these are the axes along which + to compute mean and variance. + frequency_weights: A tensor of positive weights which can be + broadcast with x. + keepdims: Produce moments with the same dimensionality as the input. + name: Name used to scope the operation. + + Returns: + Two tensors: `weighted_mean` and `weighted_variance`. + """ + return weighted_moments( + x=x, + axes=axes, + frequency_weights=frequency_weights, + name=name, + keep_dims=keepdims) + + @tf_export("nn.batch_normalization") def batch_normalization(x, mean, @@ -875,7 +1112,7 @@ def batch_normalization(x, offset - mean * inv if offset is not None else -mean * inv, x.dtype) -@tf_export("nn.fused_batch_norm") +@tf_export(v1=["nn.fused_batch_norm"]) def fused_batch_norm( x, scale, @@ -946,7 +1183,7 @@ def fused_batch_norm( return y, batch_mean, batch_var -@tf_export("nn.batch_norm_with_global_normalization") +@tf_export(v1=["nn.batch_norm_with_global_normalization"]) def batch_norm_with_global_normalization(t, m, v, @@ -984,6 +1221,53 @@ def batch_norm_with_global_normalization(t, else None, variance_epsilon, name) +# pylint: disable=redefined-builtin,line-too-long +@tf_export("nn.batch_norm_with_global_normalization", v1=[]) +def batch_norm_with_global_normalization_v2(input, + mean, + variance, + beta, + gamma, + variance_epsilon, + scale_after_normalization, + name=None): + """Batch normalization. + + This op is deprecated. See `tf.nn.batch_normalization`. + + Args: + input: A 4D input Tensor. + mean: A 1D mean Tensor with size matching the last dimension of t. + This is the first output from tf.nn.moments, + or a saved moving average thereof. + variance: A 1D variance Tensor with size matching the last dimension of t. + This is the second output from tf.nn.moments, + or a saved moving average thereof. + beta: A 1D beta Tensor with size matching the last dimension of t. + An offset to be added to the normalized tensor. + gamma: A 1D gamma Tensor with size matching the last dimension of t. + If "scale_after_normalization" is true, this tensor will be multiplied + with the normalized tensor. + variance_epsilon: A small float number to avoid dividing by 0. + scale_after_normalization: A bool indicating whether the resulted tensor + needs to be multiplied with gamma. + name: A name for this operation (optional). + + Returns: + A batch-normalized `t`. + """ + return batch_norm_with_global_normalization(t=input, + m=mean, + v=variance, + beta=beta, + gamma=gamma, + variance_epsilon=variance_epsilon, + scale_after_normalization=scale_after_normalization, + name=name) + +# pylint: enable=redefined-builtin,line-too-long + + def _sum_rows(x): """Returns a vector summing up each row of the matrix x.""" # _sum_rows(x) is equivalent to math_ops.reduce_sum(x, 1) when x is @@ -1178,7 +1462,111 @@ def _compute_sampled_logits(weights, return out_logits, out_labels -@tf_export("nn.nce_loss") +@tf_export("nn.nce_loss", v1=[]) +def nce_loss_v2(weights, + biases, + labels, + inputs, + num_sampled, + num_classes, + num_true=1, + sampled_values=None, + remove_accidental_hits=False, + name="nce_loss"): + """Computes and returns the noise-contrastive estimation training loss. + + See [Noise-contrastive estimation: A new estimation principle for + unnormalized statistical + models](http://www.jmlr.org/proceedings/papers/v9/gutmann10a/gutmann10a.pdf). + Also see our [Candidate Sampling Algorithms + Reference](https://www.tensorflow.org/extras/candidate_sampling.pdf) + + A common use case is to use this method for training, and calculate the full + sigmoid loss for evaluation or inference as in the following example: + + ```python + if mode == "train": + loss = tf.nn.nce_loss( + weights=weights, + biases=biases, + labels=labels, + inputs=inputs, + ...) + elif mode == "eval": + logits = tf.matmul(inputs, tf.transpose(weights)) + logits = tf.nn.bias_add(logits, biases) + labels_one_hot = tf.one_hot(labels, n_classes) + loss = tf.nn.sigmoid_cross_entropy_with_logits( + labels=labels_one_hot, + logits=logits) + loss = tf.reduce_sum(loss, axis=1) + ``` + + Note: when doing embedding lookup on `weights` and `bias`, "div" partition + strategy will be used. Support for other partition strategy will be added + later. + + Note: By default this uses a log-uniform (Zipfian) distribution for sampling, + so your labels must be sorted in order of decreasing frequency to achieve + good results. For more details, see + `tf.nn.log_uniform_candidate_sampler`. + + Note: In the case where `num_true` > 1, we assign to each target class + the target probability 1 / `num_true` so that the target probabilities + sum to 1 per-example. + + Note: It would be useful to allow a variable number of target classes per + example. We hope to provide this functionality in a future release. + For now, if you have a variable number of target classes, you can pad them + out to a constant number by either repeating them or by padding + with an otherwise unused class. + + Args: + weights: A `Tensor` of shape `[num_classes, dim]`, or a list of `Tensor` + objects whose concatenation along dimension 0 has shape [num_classes, + dim]. The (possibly-partitioned) class embeddings. + biases: A `Tensor` of shape `[num_classes]`. The class biases. + labels: A `Tensor` of type `int64` and shape `[batch_size, num_true]`. The + target classes. + inputs: A `Tensor` of shape `[batch_size, dim]`. The forward activations of + the input network. + num_sampled: An `int`. The number of negative classes to randomly sample + per batch. This single sample of negative classes is evaluated for each + element in the batch. + num_classes: An `int`. The number of possible classes. + num_true: An `int`. The number of target classes per training example. + sampled_values: a tuple of (`sampled_candidates`, `true_expected_count`, + `sampled_expected_count`) returned by a `*_candidate_sampler` function. + (if None, we default to `log_uniform_candidate_sampler`) + remove_accidental_hits: A `bool`. Whether to remove "accidental hits" + where a sampled class equals one of the target classes. If set to `True`, + this is a "Sampled Logistic" loss instead of NCE, and we are learning to + generate log-odds instead of log probabilities. See our [Candidate + Sampling Algorithms Reference] + (https://www.tensorflow.org/extras/candidate_sampling.pdf). Default is + False. + name: A name for the operation (optional). + + Returns: + A `batch_size` 1-D tensor of per-example NCE losses. + """ + # TODO(yuefengz): get partition_strategy from either variables or distribution + # strategies. + return nce_loss( + weights, + biases, + labels, + inputs, + num_sampled, + num_classes, + num_true=num_true, + sampled_values=sampled_values, + remove_accidental_hits=remove_accidental_hits, + partition_strategy="div", + name=name) + + +@tf_export(v1=["nn.nce_loss"]) def nce_loss(weights, biases, labels, diff --git a/tensorflow/python/ops/nn_ops.py b/tensorflow/python/ops/nn_ops.py index bc195993c2..225904854f 100644 --- a/tensorflow/python/ops/nn_ops.py +++ b/tensorflow/python/ops/nn_ops.py @@ -28,6 +28,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import graph_util from tensorflow.python.framework import ops +from tensorflow.python.framework import random_seed from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops @@ -35,13 +36,14 @@ from tensorflow.python.ops import check_ops from tensorflow.python.ops import gen_nn_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops - # go/tf-wildcard-import # pylint: disable=wildcard-import from tensorflow.python.ops.gen_nn_ops import * # pylint: enable=wildcard-import - from tensorflow.python.util import deprecation +from tensorflow.python.util.deprecation import deprecated_args +from tensorflow.python.util.deprecation import deprecated_argument_lookup + from tensorflow.python.util.tf_export import tf_export # Aliases for some automatically-generated names. @@ -206,6 +208,73 @@ class _NonAtrousConvolution(object): name=self.name) +@tf_export("nn.dilation2d", v1=[]) +def dilation2d_v2( + input, # pylint: disable=redefined-builtin + filters, # pylint: disable=redefined-builtin + strides, + padding, + data_format, + dilations, + name=None): + """Computes the grayscale dilation of 4-D `input` and 3-D `filters` tensors. + + The `input` tensor has shape `[batch, in_height, in_width, depth]` and the + `filters` tensor has shape `[filter_height, filter_width, depth]`, i.e., each + input channel is processed independently of the others with its own + structuring function. The `output` tensor has shape + `[batch, out_height, out_width, depth]`. The spatial dimensions of the output + tensor depend on the `padding` algorithm. We currently only support the + default "NHWC" `data_format`. + + In detail, the grayscale morphological 2-D dilation is the max-sum correlation + (for consistency with `conv2d`, we use unmirrored filters): + + output[b, y, x, c] = + max_{dy, dx} input[b, + strides[1] * y + rates[1] * dy, + strides[2] * x + rates[2] * dx, + c] + + filters[dy, dx, c] + + Max-pooling is a special case when the filter has size equal to the pooling + kernel size and contains all zeros. + + Note on duality: The dilation of `input` by the `filters` is equal to the + negation of the erosion of `-input` by the reflected `filters`. + + Args: + input: A `Tensor`. Must be one of the following types: `float32`, `float64`, + `int32`, `uint8`, `int16`, `int8`, `int64`, `bfloat16`, `uint16`, `half`, + `uint32`, `uint64`. + 4-D with shape `[batch, in_height, in_width, depth]`. + filters: A `Tensor`. Must have the same type as `input`. + 3-D with shape `[filter_height, filter_width, depth]`. + strides: A list of `ints` that has length `>= 4`. + The stride of the sliding window for each dimension of the input + tensor. Must be: `[1, stride_height, stride_width, 1]`. + padding: A `string` from: `"SAME", "VALID"`. + The type of padding algorithm to use. + data_format: A `string`, only `"NCHW"` is currently supported. + dilations: A list of `ints` that has length `>= 4`. + The input stride for atrous morphological dilation. Must be: + `[1, rate_height, rate_width, 1]`. + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type as `input`. + """ + if data_format != "NCHW": + raise ValueError("Data formats other than NCHW are not yet supported") + + return gen_nn_ops.dilation2d(input=input, + filter=filters, + strides=strides, + rates=dilations, + padding=padding, + name=name) + + @tf_export("nn.with_space_to_batch") def with_space_to_batch( input, # pylint: disable=redefined-builtin @@ -644,7 +713,7 @@ def _get_strides_and_dilation_rate(num_spatial_dims, strides, dilation_rate): return strides, dilation_rate -@tf_export("nn.convolution") +@tf_export(v1=["nn.convolution"]) def convolution( input, # pylint: disable=redefined-builtin filter, # pylint: disable=redefined-builtin @@ -782,6 +851,30 @@ def convolution( return op(input, filter) +@tf_export("nn.convolution", v1=[]) +def convolution_v2( + input, # pylint: disable=redefined-builtin + filters, + strides=None, + padding="VALID", + data_format=None, + dilations=None, + name=None): + return convolution( + input, # pylint: disable=redefined-builtin + filters, + padding=padding, + strides=strides, + dilation_rate=dilations, + name=name, + data_format=data_format) + +convolution_v2.__doc__ = deprecation.rewrite_argument_docstring( + deprecation.rewrite_argument_docstring( + convolution.__doc__, "dilation_rate", "dilations"), + "filter", "filters") + + class Convolution(object): """Helper class for convolution. @@ -873,7 +966,7 @@ class Convolution(object): return self.conv_op(inp, filter) -@tf_export("nn.pool") +@tf_export(v1=["nn.pool"]) def pool( input, # pylint: disable=redefined-builtin window_shape, @@ -1044,6 +1137,105 @@ def pool( filter_shape=window_shape) +@tf_export("nn.pool", v1=[]) +def pool_v2( + input, # pylint: disable=redefined-builtin + window_shape, + pooling_type, + strides=None, + padding="VALID", + data_format=None, + dilations=None, + name=None): + # pylint: disable=line-too-long + """Performs an N-D pooling operation. + + In the case that `data_format` does not start with "NC", computes for + 0 <= b < batch_size, + 0 <= x[i] < output_spatial_shape[i], + 0 <= c < num_channels: + + ``` + output[b, x[0], ..., x[N-1], c] = + REDUCE_{z[0], ..., z[N-1]} + input[b, + x[0] * strides[0] - pad_before[0] + dilation_rate[0]*z[0], + ... + x[N-1]*strides[N-1] - pad_before[N-1] + dilation_rate[N-1]*z[N-1], + c], + ``` + + where the reduction function REDUCE depends on the value of `pooling_type`, + and pad_before is defined based on the value of `padding` as described in + the "returns" section of `tf.nn.convolution` for details. + The reduction never includes out-of-bounds positions. + + In the case that `data_format` starts with `"NC"`, the `input` and output are + simply transposed as follows: + + ``` + pool(input, data_format, **kwargs) = + tf.transpose(pool(tf.transpose(input, [0] + range(2,N+2) + [1]), + **kwargs), + [0, N+1] + range(1, N+1)) + ``` + + Args: + input: Tensor of rank N+2, of shape `[batch_size] + input_spatial_shape + + [num_channels]` if data_format does not start with "NC" (default), or + `[batch_size, num_channels] + input_spatial_shape` if data_format starts + with "NC". Pooling happens over the spatial dimensions only. + window_shape: Sequence of N ints >= 1. + pooling_type: Specifies pooling operation, must be "AVG" or "MAX". + strides: Optional. Sequence of N ints >= 1. Defaults to [1]*N. If any value of + strides is > 1, then all values of dilation_rate must be 1. + padding: The padding algorithm, must be "SAME" or "VALID". Defaults to "SAME". + See the "returns" section of `tf.nn.convolution` for details. + data_format: A string or None. Specifies whether the channel dimension of + the `input` and output is the last dimension (default, or if `data_format` + does not start with "NC"), or the second dimension (if `data_format` + starts with "NC"). For N=1, the valid values are "NWC" (default) and + "NCW". For N=2, the valid values are "NHWC" (default) and "NCHW". For + N=3, the valid values are "NDHWC" (default) and "NCDHW". + dilations: Optional. Dilation rate. List of N ints >= 1. Defaults to + [1]*N. If any value of dilation_rate is > 1, then all values of strides + must be 1. + name: Optional. Name of the op. + + Returns: + Tensor of rank N+2, of shape + [batch_size] + output_spatial_shape + [num_channels] + + if data_format is None or does not start with "NC", or + + [batch_size, num_channels] + output_spatial_shape + + if data_format starts with "NC", + where `output_spatial_shape` depends on the value of padding: + + If padding = "SAME": + output_spatial_shape[i] = ceil(input_spatial_shape[i] / strides[i]) + + If padding = "VALID": + output_spatial_shape[i] = + ceil((input_spatial_shape[i] - (window_shape[i] - 1) * dilation_rate[i]) + / strides[i]). + + Raises: + ValueError: if arguments are invalid. + + """ + return pool( + input=input, + window_shape=window_shape, + pooling_type=pooling_type, + padding=padding, + dilation_rate=dilations, + strides=strides, + name=name, + data_format=data_format) + + @tf_export("nn.atrous_conv2d") def atrous_conv2d(value, filters, rate, padding, name=None): """Atrous convolution (a.k.a. convolution with holes or dilated convolution). @@ -1181,7 +1373,208 @@ def atrous_conv2d(value, filters, rate, padding, name=None): name=name) -@tf_export("nn.conv2d_transpose") +@tf_export("nn.conv2d", v1=[]) +def conv2d_v2(input, # pylint: disable=redefined-builtin + filters, + strides, + padding, + data_format="NHWC", + dilations=None, + name=None): + # pylint: disable=line-too-long + r"""Computes a 2-D convolution given 4-D `input` and `filters` tensors. + + Given an input tensor of shape `[batch, in_height, in_width, in_channels]` + and a filter / kernel tensor of shape + `[filter_height, filter_width, in_channels, out_channels]`, this op + performs the following: + + 1. Flattens the filter to a 2-D matrix with shape + `[filter_height * filter_width * in_channels, output_channels]`. + 2. Extracts image patches from the input tensor to form a *virtual* + tensor of shape `[batch, out_height, out_width, + filter_height * filter_width * in_channels]`. + 3. For each patch, right-multiplies the filter matrix and the image patch + vector. + + In detail, with the default NHWC format, + + output[b, i, j, k] = + sum_{di, dj, q} input[b, strides[1] * i + di, strides[2] * j + dj, q] * + filter[di, dj, q, k] + + Must have `strides[0] = strides[3] = 1`. For the most common case of the same + horizontal and vertices strides, `strides = [1, stride, stride, 1]`. + + Args: + input: A `Tensor`. Must be one of the following types: + `half`, `bfloat16`, `float32`, `float64`. + A 4-D tensor. The dimension order is interpreted according to the value + of `data_format`, see below for details. + filters: A `Tensor`. Must have the same type as `input`. + A 4-D tensor of shape + `[filter_height, filter_width, in_channels, out_channels]` + strides: A list of `ints`. + 1-D tensor of length 4. The stride of the sliding window for each + dimension of `input`. The dimension order is determined by the value of + `data_format`, see below for details. + padding: A `string` from: `"SAME", "VALID"`. + The type of padding algorithm to use. + data_format: An optional `string` from: `"NHWC", "NCHW"`. + Defaults to `"NHWC"`. + Specify the data format of the input and output data. With the + default format "NHWC", the data is stored in the order of: + [batch, height, width, channels]. + Alternatively, the format could be "NCHW", the data storage order of: + [batch, channels, height, width]. + dilations: An optional list of `ints`. Defaults to `[1, 1, 1, 1]`. + 1-D tensor of length 4. The dilation factor for each dimension of + `input`. If set to k > 1, there will be k-1 skipped cells between each + filter element on that dimension. The dimension order is determined by the + value of `data_format`, see above for details. Dilations in the batch and + depth dimensions must be 1. + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type as `input`. + """ + # pylint: enable=line-too-long + if dilations is None: + dilations = [1, 1, 1, 1] + return gen_nn_ops.conv2d(input, # pylint: disable=redefined-builtin + filters, + strides, + padding, + use_cudnn_on_gpu=True, + data_format=data_format, + dilations=dilations, + name=name) +tf_export(v1=["nn.conv2d"])(gen_nn_ops.conv2d) + + +@tf_export("nn.conv2d_backprop_filter", v1=[]) +def conv2d_backprop_filter_v2(input, # pylint: disable=redefined-builtin + filter_sizes, + out_backprop, + strides, + padding, + data_format="NHWC", + dilations=None, + name=None): + r"""Computes the gradients of convolution with respect to the filter. + + Args: + input: A `Tensor`. Must be one of the following types: + `half`, `bfloat16`, `float32`, `float64`. + 4-D with shape `[batch, in_height, in_width, in_channels]`. + filter_sizes: A `Tensor` of type `int32`. + An integer vector representing the tensor shape of `filter`, + where `filter` is a 4-D + `[filter_height, filter_width, in_channels, out_channels]` tensor. + out_backprop: A `Tensor`. Must have the same type as `input`. + 4-D with shape `[batch, out_height, out_width, out_channels]`. + Gradients w.r.t. the output of the convolution. + strides: A list of `ints`. + The stride of the sliding window for each dimension of the input + of the convolution. Must be in the same order as the dimension specified + with format. + padding: A `string` from: `"SAME", "VALID"`. + The type of padding algorithm to use. + data_format: An optional `string` from: `"NHWC", "NCHW"`. + Defaults to `"NHWC"`. + Specify the data format of the input and output data. With the + default format "NHWC", the data is stored in the order of: + [batch, in_height, in_width, in_channels]. + Alternatively, the format could be "NCHW", the data storage order of: + [batch, in_channels, in_height, in_width]. + dilations: An optional list of `ints`. Defaults to `[1, 1, 1, 1]`. + 1-D tensor of length 4. The dilation factor for each dimension of + `input`. If set to k > 1, there will be k-1 skipped cells between each + filter element on that dimension. The dimension order is determined by + the value of `data_format`, see above for details. Dilations in the batch + and depth dimensions must be 1. + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type as `input`. + """ + if dilations is None: + dilations = [1, 1, 1, 1] + return gen_nn_ops.conv2d_backprop_filter(input, # pylint: disable=redefined-builtin + filter_sizes, + out_backprop, + strides, + padding, + use_cudnn_on_gpu=True, + data_format=data_format, + dilations=dilations, + name=name) +tf_export(v1=["nn.conv2d_backprop_filter"])( + gen_nn_ops.conv2d_backprop_filter) + + +@tf_export("nn.conv2d_backprop_input", v1=[]) +def conv2d_backprop_input_v2(input_sizes, + filters, + out_backprop, + strides, + padding, + data_format="NHWC", + dilations=None, + name=None): + r"""Computes the gradients of convolution with respect to the input. + + Args: + input_sizes: A `Tensor` of type `int32`. + An integer vector representing the shape of `input`, + where `input` is a 4-D `[batch, height, width, channels]` tensor. + filters: A `Tensor`. Must be one of the following types: + `half`, `bfloat16`, `float32`, `float64`. + 4-D with shape + `[filter_height, filter_width, in_channels, out_channels]`. + out_backprop: A `Tensor`. Must have the same type as `filters`. + 4-D with shape `[batch, out_height, out_width, out_channels]`. + Gradients w.r.t. the output of the convolution. + strides: A list of `ints`. + The stride of the sliding window for each dimension of the input + of the convolution. Must be in the same order as the dimension specified + with format. + padding: A `string` from: `"SAME", "VALID"`. + The type of padding algorithm to use. + data_format: An optional `string` from: `"NHWC", "NCHW"`. + Defaults to `"NHWC"`. + Specify the data format of the input and output data. With the + default format "NHWC", the data is stored in the order of: + [batch, in_height, in_width, in_channels]. + Alternatively, the format could be "NCHW", the data storage order of: + [batch, in_channels, in_height, in_width]. + dilations: An optional list of `ints`. Defaults to `[1, 1, 1, 1]`. + 1-D tensor of length 4. The dilation factor for each dimension of + `input`. If set to k > 1, there will be k-1 skipped cells between each + filter element on that dimension. The dimension order is determined by + the value of `data_format`, see above for details. Dilations in the batch + and depth dimensions must be 1. + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type as `filters`. + """ + if dilations is None: + dilations = [1, 1, 1, 1] + return gen_nn_ops.conv2d_backprop_input(input_sizes, + filters, + out_backprop, + strides, + padding, + use_cudnn_on_gpu=True, + data_format=data_format, + dilations=dilations, + name=name) +tf_export(v1=["nn.conv2d_backprop_input"])( + gen_nn_ops.conv2d_backprop_input) + + +@tf_export(v1=["nn.conv2d_transpose"]) def conv2d_transpose( value, filter, # pylint: disable=redefined-builtin @@ -1261,6 +1654,31 @@ def conv2d_transpose( name=name) +# pylint: disable=redefined-builtin +@tf_export("nn.conv2d_transpose", v1=[]) +def conv2d_transpose_v2( + input, + filters, # pylint: disable=redefined-builtin + output_shape, + strides, + padding="SAME", + data_format="NHWC", + name=None): + return conv2d_transpose( + input, + filters, + output_shape, + strides, + padding=padding, + data_format=data_format, + name=name) +# pylint: enable=redefined-builtin +conv2d_transpose_v2.__doc__ = deprecation.rewrite_argument_docstring( + deprecation.rewrite_argument_docstring( + conv2d_transpose.__doc__, "filter", "filters"), + "value", "input") + + @tf_export("nn.atrous_conv2d_transpose") def atrous_conv2d_transpose(value, filters, @@ -1409,7 +1827,29 @@ def atrous_conv2d_transpose(value, input=value, crops=batch_to_space_crop, block_size=rate) -@tf_export("nn.conv3d_transpose") +@tf_export("nn.conv3d", v1=[]) +def conv3d_v2(input, # pylint: disable=redefined-builtin,missing-docstring + filters, + strides, + padding, + data_format="NDHWC", + dilations=None, + name=None): + if dilations is None: + dilations = [1, 1, 1, 1, 1] + return gen_nn_ops.conv3d(input, # pylint: disable=redefined-builtin + filters, + strides, + padding, + data_format=data_format, + dilations=dilations, + name=name) +tf_export(v1=["nn.conv3d"])(gen_nn_ops.conv3d) +conv3d_v2.__doc__ = deprecation.rewrite_argument_docstring( + gen_nn_ops.conv3d.__doc__, "filter", "filters") + + +@tf_export(v1=["nn.conv3d_transpose"]) def conv3d_transpose( value, filter, # pylint: disable=redefined-builtin @@ -1487,6 +1927,31 @@ def conv3d_transpose( name=name) +# pylint: disable=redefined-builtin +@tf_export("nn.conv3d_transpose", v1=[]) +def conv3d_transpose_v2( + input, + filters, + output_shape, + strides, + padding="SAME", + data_format="NDHWC", + name=None): + return conv3d_transpose( + input, + filters, + output_shape, + strides, + padding=padding, + data_format=data_format, + name=name) +# pylint: enable=redefined-builtin +conv3d_transpose_v2.__doc__ = deprecation.rewrite_argument_docstring( + deprecation.rewrite_argument_docstring( + conv3d_transpose.__doc__, "filter", "filters"), + "value", "input") + + @tf_export("nn.bias_add") def bias_add(value, bias, data_format=None, name=None): """Adds `bias` to `value`. @@ -1542,7 +2007,7 @@ def bias_add_v1(value, bias, name=None): return gen_nn_ops.bias_add_v1(value, bias, name=name) -@tf_export("nn.crelu") +@tf_export(v1=["nn.crelu"]) def crelu(features, name=None, axis=-1): """Computes Concatenated ReLU. @@ -1568,6 +2033,12 @@ def crelu(features, name=None, axis=-1): return gen_nn_ops.relu(c) +@tf_export("nn.crelu", v1=[]) +def crelu_v2(features, axis=-1, name=None): + return crelu(features, name=name, axis=axis) +crelu_v2.__doc__ = crelu.__doc__ + + @tf_export("nn.relu6") def relu6(features, name=None): """Computes Rectified Linear 6: `min(max(features, 0), 6)`. @@ -1715,7 +2186,7 @@ def _softmax(logits, compute_op, dim=-1, name=None): return output -@tf_export("nn.softmax", "math.softmax") +@tf_export(v1=["nn.softmax", "math.softmax"]) @deprecation.deprecated_args(None, "dim is deprecated, use axis instead", "dim") def softmax(logits, axis=None, name=None, dim=None): """Computes softmax activations. @@ -1745,7 +2216,34 @@ def softmax(logits, axis=None, name=None, dim=None): return _softmax(logits, gen_nn_ops.softmax, axis, name) -@tf_export("nn.log_softmax", "math.log_softmax") +@tf_export("nn.softmax", "math.softmax", v1=[]) +def softmax_v2(logits, axis=None, name=None): + """Computes softmax activations. + + This function performs the equivalent of + + softmax = tf.exp(logits) / tf.reduce_sum(tf.exp(logits), axis) + + Args: + logits: A non-empty `Tensor`. Must be one of the following types: `half`, + `float32`, `float64`. + axis: The dimension softmax would be performed on. The default is -1 which + indicates the last dimension. + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type and shape as `logits`. + + Raises: + InvalidArgumentError: if `logits` is empty or `axis` is beyond the last + dimension of `logits`. + """ + if axis is None: + axis = -1 + return _softmax(logits, gen_nn_ops.softmax, axis, name) + + +@tf_export(v1=["nn.log_softmax", "math.log_softmax"]) @deprecation.deprecated_args(None, "dim is deprecated, use axis instead", "dim") def log_softmax(logits, axis=None, name=None, dim=None): """Computes log softmax activations. @@ -1775,6 +2273,33 @@ def log_softmax(logits, axis=None, name=None, dim=None): return _softmax(logits, gen_nn_ops.log_softmax, axis, name) +@tf_export("nn.log_softmax", "math.log_softmax", v1=[]) +def log_softmax_v2(logits, axis=None, name=None): + """Computes log softmax activations. + + For each batch `i` and class `j` we have + + logsoftmax = logits - log(reduce_sum(exp(logits), axis)) + + Args: + logits: A non-empty `Tensor`. Must be one of the following types: `half`, + `float32`, `float64`. + axis: The dimension softmax would be performed on. The default is -1 which + indicates the last dimension. + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type as `logits`. Same shape as `logits`. + + Raises: + InvalidArgumentError: if `logits` is empty or `axis` is beyond the last + dimension of `logits`. + """ + if axis is None: + axis = -1 + return _softmax(logits, gen_nn_ops.log_softmax, axis, name) + + def _ensure_xent_args(name, sentinel, labels, logits): # Make sure that all arguments were passed as named arguments. if sentinel is not None: @@ -1784,9 +2309,8 @@ def _ensure_xent_args(name, sentinel, labels, logits): raise ValueError("Both labels and logits must be provided.") -@tf_export("nn.softmax_cross_entropy_with_logits", - v1=["nn.softmax_cross_entropy_with_logits_v2"]) -def softmax_cross_entropy_with_logits_v2(labels, logits, dim=-1, name=None): +@tf_export("nn.softmax_cross_entropy_with_logits", v1=[]) +def softmax_cross_entropy_with_logits_v2(labels, logits, axis=-1, name=None): """Computes softmax cross entropy between `logits` and `labels`. Measures the probability error in discrete classification tasks in which the @@ -1808,7 +2332,7 @@ def softmax_cross_entropy_with_logits_v2(labels, logits, dim=-1, name=None): A common use case is to have logits and labels of shape `[batch_size, num_classes]`, but higher dimensions are supported, with - the `dim` argument specifying the class dimension. + the `axis` argument specifying the class dimension. `logits` and `labels` must have the same dtype (either `float16`, `float32`, or `float64`). @@ -1826,8 +2350,64 @@ def softmax_cross_entropy_with_logits_v2(labels, logits, dim=-1, name=None): `[batch_size, num_classes]`, each row of `labels[i]` must be a valid probability distribution. logits: Unscaled log probabilities. - dim: The class dimension. Defaulted to -1 which is the last dimension. + axis: The class dimension. Defaulted to -1 which is the last dimension. + name: A name for the operation (optional). + + Returns: + A `Tensor` that contains the softmax cross entropy loss. Its type is the + same as `logits` and its shape is the same as `labels` except that it does + not have the last dimension of `labels`. + """ + return softmax_cross_entropy_with_logits_v2_helper( + labels=labels, logits=logits, axis=axis, name=name) + + +@tf_export(v1=["nn.softmax_cross_entropy_with_logits_v2"]) +@deprecated_args(None, "dim is deprecated, use axis instead", "dim") +def softmax_cross_entropy_with_logits_v2_helper( + labels, logits, axis=None, name=None, dim=None): + """Computes softmax cross entropy between `logits` and `labels`. + + Measures the probability error in discrete classification tasks in which the + classes are mutually exclusive (each entry is in exactly one class). For + example, each CIFAR-10 image is labeled with one and only one label: an image + can be a dog or a truck, but not both. + + **NOTE:** While the classes are mutually exclusive, their probabilities + need not be. All that is required is that each row of `labels` is + a valid probability distribution. If they are not, the computation of the + gradient will be incorrect. + + If using exclusive `labels` (wherein one and only + one class is true at a time), see `sparse_softmax_cross_entropy_with_logits`. + + **WARNING:** This op expects unscaled logits, since it performs a `softmax` + on `logits` internally for efficiency. Do not call this op with the + output of `softmax`, as it will produce incorrect results. + + A common use case is to have logits and labels of shape + `[batch_size, num_classes]`, but higher dimensions are supported, with + the `axis` argument specifying the class dimension. + + `logits` and `labels` must have the same dtype (either `float16`, `float32`, + or `float64`). + + Backpropagation will happen into both `logits` and `labels`. To disallow + backpropagation into `labels`, pass label tensors through `tf.stop_gradient` + before feeding it to this function. + + **Note that to avoid confusion, it is required to pass only named arguments to + this function.** + + Args: + labels: Each vector along the class dimension should hold a valid + probability distribution e.g. for the case in which labels are of shape + `[batch_size, num_classes]`, each row of `labels[i]` must be a valid + probability distribution. + logits: Unscaled log probabilities. + axis: The class dimension. Defaulted to -1 which is the last dimension. name: A name for the operation (optional). + dim: Deprecated alias for axis. Returns: A `Tensor` that contains the softmax cross entropy loss. Its type is the @@ -1837,6 +2417,10 @@ def softmax_cross_entropy_with_logits_v2(labels, logits, dim=-1, name=None): # TODO(pcmurray) Raise an error when the labels do not sum to 1. Note: This # could break users who call this with bad labels, but disregard the bad # results. + axis = deprecated_argument_lookup("axis", axis, "dim", dim) + del dim + if axis is None: + axis = -1 with ops.name_scope(name, "softmax_cross_entropy_with_logits", [logits, labels]) as name: @@ -1853,7 +2437,7 @@ def softmax_cross_entropy_with_logits_v2(labels, logits, dim=-1, name=None): shape = logits.get_shape() # Move the dim to the end if dim is not the last dimension. - if dim is not -1: + if axis != -1: def _move_dim_to_end(tensor, dim_index, rank): return array_ops.transpose( @@ -1863,8 +2447,8 @@ def softmax_cross_entropy_with_logits_v2(labels, logits, dim=-1, name=None): math_ops.range(dim_index + 1, rank), [dim_index] ], 0)) - precise_logits = _move_dim_to_end(precise_logits, dim, input_rank) - labels = _move_dim_to_end(labels, dim, input_rank) + precise_logits = _move_dim_to_end(precise_logits, axis, input_rank) + labels = _move_dim_to_end(labels, axis, input_rank) input_shape = array_ops.shape(precise_logits) @@ -1878,7 +2462,7 @@ def softmax_cross_entropy_with_logits_v2(labels, logits, dim=-1, name=None): cost, unused_backprop = gen_nn_ops.softmax_cross_entropy_with_logits( precise_logits, labels, name=name) - # The output cost shape should be the input minus dim. + # The output cost shape should be the input minus axis. output_shape = array_ops.slice(input_shape, [0], [math_ops.subtract(input_rank, 1)]) cost = array_ops.reshape(cost, output_shape) @@ -1888,7 +2472,7 @@ def softmax_cross_entropy_with_logits_v2(labels, logits, dim=-1, name=None): if not context.executing_eagerly( ) and shape is not None and shape.dims is not None: shape = shape.as_list() - del shape[dim] + del shape[axis] cost.set_shape(shape) if convert_to_float32: @@ -1966,7 +2550,7 @@ def softmax_cross_entropy_with_logits( labels = array_ops.stop_gradient(labels, name="labels_stop_gradient") return softmax_cross_entropy_with_logits_v2( - labels=labels, logits=logits, dim=dim, name=name) + labels=labels, logits=logits, axis=dim, name=name) @tf_export("nn.sparse_softmax_cross_entropy_with_logits") @@ -2155,6 +2739,67 @@ def max_pool(value, ksize, strides, padding, data_format="NHWC", name=None): name=name) +# pylint: disable=redefined-builtin +@tf_export("nn.max_pool_with_argmax", v1=[]) +def max_pool_with_argmax_v2(input, + ksize, + strides, + padding, + data_format="NHWC", + output_dtype=dtypes.int64, + name=None): + """Performs max pooling on the input and outputs both max values and indices. + + The indices in `argmax` are flattened, so that a maximum value at position + `[b, y, x, c]` becomes flattened index + `((b * height + y) * width + x) * channels + c`. + + The indices returned are always in `[0, height) x [0, width)` before + flattening, even if padding is involved and the mathematically correct answer + is outside (either negative or too large). This is a bug, but fixing it is + difficult to do in a safe backwards compatible way, especially due to + flattening. + + Args: + input: A `Tensor`. Must be one of the following types: `float32`, `float64`, + `int32`, `uint8`, `int16`, `int8`, `int64`, `bfloat16`, `uint16`, `half`, + `uint32`, `uint64`. + 4-D with shape `[batch, height, width, channels]`. Input to pool over. + ksize: A list of `ints` that has length `>= 4`. + The size of the window for each dimension of the input tensor. + strides: A list of `ints` that has length `>= 4`. + The stride of the sliding window for each dimension of the + input tensor. + padding: A `string` from: `"SAME", "VALID"`. + The type of padding algorithm to use. + data_format: An optional `string`, must be set to `"NHWC"`. Defaults to + `"NHWC"`. + Specify the data format of the input and output data. + output_dtype: An optional `tf.DType` from: `tf.int32, tf.int64`. + Defaults to `tf.int64`. + The dtype of the returned argmax tensor. + name: A name for the operation (optional). + + Returns: + A tuple of `Tensor` objects (output, argmax). + + output: A `Tensor`. Has the same type as `input`. + argmax: A `Tensor` of type `output_dtype`. + """ + + if data_format != "NHWC": + raise ValueError("Data formats other than 'NHWC' are not yet supported") + + return gen_nn_ops.max_pool_with_argmax(input=input, + ksize=ksize, + strides=strides, + padding=padding, + Targmax=output_dtype, + name=name) + +# pylint: enable=redefined-builtin + + @ops.RegisterStatistics("Conv2D", "flops") def _calc_conv_flops(graph, node): """Calculates the compute resources needed for Conv2D.""" @@ -2199,7 +2844,7 @@ def _calc_bias_add_flops(graph, node): return ops.OpStats("flops", input_count) -@tf_export("nn.xw_plus_b") +@tf_export(v1=["nn.xw_plus_b"]) def xw_plus_b(x, weights, biases, name=None): # pylint: disable=invalid-name """Computes matmul(x, weights) + biases. @@ -2271,12 +2916,16 @@ def _get_noise_shape(x, noise_shape): return noise_shape -@tf_export("nn.dropout") -def dropout(x, keep_prob, noise_shape=None, seed=None, name=None): # pylint: disable=invalid-name +@tf_export(v1=["nn.dropout"]) +@deprecation.deprecated_args(None, "Please use `rate` instead of `keep_prob`. " + "Rate should be set to `rate = 1 - keep_prob`.", + "keep_prob") +def dropout(x, keep_prob=None, noise_shape=None, seed=None, name=None, + rate=None): # pylint: disable=invalid-name """Computes dropout. - With probability `keep_prob`, outputs the input element scaled up by - `1 / keep_prob`, otherwise outputs `0`. The scaling is so that the expected + For each element of `x`, with probability `rate`, outputs `0`, and otherwise + scales up the input by `1 / (1-rate)`. The scaling is such that the expected sum is unchanged. By default, each element is kept or dropped independently. If `noise_shape` @@ -2289,8 +2938,59 @@ def dropout(x, keep_prob, noise_shape=None, seed=None, name=None): # pylint: di Args: x: A floating point tensor. - keep_prob: A scalar `Tensor` with the same type as x. The probability - that each element is kept. + keep_prob: (deprecated) A deprecated alias for `(1-rate)`. + noise_shape: A 1-D `Tensor` of type `int32`, representing the + shape for randomly generated keep/drop flags. + seed: A Python integer. Used to create random seeds. See + `tf.set_random_seed` for behavior. + name: A name for this operation (optional). + rate: A scalar `Tensor` with the same type as `x`. The probability that each + element of `x` is discarded. + + Returns: + A Tensor of the same shape of `x`. + + Raises: + ValueError: If `rate` is not in `[0, 1)` or if `x` is not a floating + point tensor. + """ + try: + keep = 1. - keep_prob if keep_prob is not None else None + except TypeError: + raise ValueError("keep_prob must be a floating point number or Tensor " + "(got %r)" % keep_prob) + + rate = deprecation.deprecated_argument_lookup( + "rate", rate, + "keep_prob", keep) + + if rate is None: + raise ValueError("You must provide a rate to dropout.") + + return dropout_v2(x, rate, noise_shape=noise_shape, seed=seed, name=name) + + +@tf_export("nn.dropout", v1=[]) +def dropout_v2(x, rate, noise_shape=None, seed=None, name=None): # pylint: disable=invalid-name + """Computes dropout. + + With probability `rate`, drops elements of `x`. Input that are kept are + scaled up by `1 / (1 - rate)`, otherwise outputs `0`. The scaling is so that + the expected sum is unchanged. + + By default, each element is kept or dropped independently. If `noise_shape` + is specified, it must be + [broadcastable](http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html) + to the shape of `x`, and only dimensions with `noise_shape[i] == shape(x)[i]` + will make independent decisions. For example, if `shape(x) = [k, l, m, n]` + and `noise_shape = [k, 1, 1, n]`, each batch and channel component will be + kept independently and each row and column will be kept or not kept together. + + Args: + x: A floating point tensor. + rate: A scalar `Tensor` with the same type as x. The probability + that each element is dropped. For example, setting rate=0.1 would drop + 10% of input elements. noise_shape: A 1-D `Tensor` of type `int32`, representing the shape for randomly generated keep/drop flags. seed: A Python integer. Used to create random seeds. See @@ -2310,28 +3010,29 @@ def dropout(x, keep_prob, noise_shape=None, seed=None, name=None): # pylint: di if not x.dtype.is_floating: raise ValueError("x has to be a floating point tensor since it's going to" " be scaled. Got a %s tensor instead." % x.dtype) - if isinstance(keep_prob, numbers.Real) and not 0 < keep_prob <= 1: - raise ValueError("keep_prob must be a scalar tensor or a float in the " - "range (0, 1], got %g" % keep_prob) + if isinstance(rate, numbers.Real) and not (rate >= 0 and rate < 1): + raise ValueError("rate must be a scalar tensor or a float in the " + "range [0, 1), got %g" % rate) # Early return if nothing needs to be dropped. - if isinstance(keep_prob, float) and keep_prob == 1: + if isinstance(rate, numbers.Real) and rate == 0: return x if context.executing_eagerly(): - if isinstance(keep_prob, ops.EagerTensor): - if keep_prob.numpy() == 1: + if isinstance(rate, ops.EagerTensor): + if rate.numpy() == 0: return x else: - keep_prob = ops.convert_to_tensor( - keep_prob, dtype=x.dtype, name="keep_prob") - keep_prob.get_shape().assert_is_compatible_with(tensor_shape.scalar()) + rate = ops.convert_to_tensor( + rate, dtype=x.dtype, name="rate") + rate.get_shape().assert_is_compatible_with(tensor_shape.scalar()) - # Do nothing if we know keep_prob == 1 - if tensor_util.constant_value(keep_prob) == 1: + # Do nothing if we know rate == 0 + if tensor_util.constant_value(rate) == 0: return x noise_shape = _get_noise_shape(x, noise_shape) + keep_prob = 1 - rate # uniform [keep_prob, 1.0 + keep_prob) random_tensor = keep_prob random_tensor += random_ops.random_uniform( @@ -2402,7 +3103,293 @@ def nth_element(input, n, reverse=False, name=None): # pylint: disable=redefine return gen_nn_ops.nth_element(input, n, reverse=reverse, name=name) -@tf_export("nn.conv1d") +@tf_export(v1=["nn.fractional_max_pool"]) +@deprecation.deprecated(date=None, instructions="`seed2` and `deterministic` " + "args are deprecated. Use fractional_max_pool_v2.") +def fractional_max_pool(value, + pooling_ratio, + pseudo_random=False, + overlapping=False, + deterministic=False, + seed=0, + seed2=0, + name=None): # pylint: disable=redefined-builtin + r"""Performs fractional max pooling on the input. + + This is a deprecated version of `fractional_max_pool`. + + Fractional max pooling is slightly different than regular max pooling. In + regular max pooling, you downsize an input set by taking the maximum value of + smaller N x N subsections of the set (often 2x2), and try to reduce the set by + a factor of N, where N is an integer. Fractional max pooling, as you might + expect from the word "fractional", means that the overall reduction ratio N + does not have to be an integer. + + The sizes of the pooling regions are generated randomly but are fairly + uniform. For example, let's look at the height dimension, and the constraints + on the list of rows that will be pool boundaries. + + First we define the following: + + 1. input_row_length : the number of rows from the input set + 2. output_row_length : which will be smaller than the input + 3. alpha = input_row_length / output_row_length : our reduction ratio + 4. K = floor(alpha) + 5. row_pooling_sequence : this is the result list of pool boundary rows + + Then, row_pooling_sequence should satisfy: + + 1. a[0] = 0 : the first value of the sequence is 0 + 2. a[end] = input_row_length : the last value of the sequence is the size + 3. K <= (a[i+1] - a[i]) <= K+1 : all intervals are K or K+1 size + 4. length(row_pooling_sequence) = output_row_length+1 + + For more details on fractional max pooling, see this paper: [Benjamin Graham, + Fractional Max-Pooling](http://arxiv.org/abs/1412.6071) + + Args: + value: A `Tensor`. 4-D with shape `[batch, height, width, channels]`. + pooling_ratio: A list of `floats` that has length >= 4. Pooling ratio for + each dimension of `value`, currently only supports row and col dimension + and should be >= 1.0. For example, a valid pooling ratio looks like [1.0, + 1.44, 1.73, 1.0]. The first and last elements must be 1.0 because we don't + allow pooling on batch and channels dimensions. 1.44 and 1.73 are pooling + ratio on height and width dimensions respectively. + pseudo_random: An optional `bool`. Defaults to `False`. When set to `True`, + generates the pooling sequence in a pseudorandom fashion, otherwise, in a + random fashion. Check paper [Benjamin Graham, Fractional + Max-Pooling](http://arxiv.org/abs/1412.6071) for difference between + pseudorandom and random. + overlapping: An optional `bool`. Defaults to `False`. When set to `True`, + it means when pooling, the values at the boundary of adjacent pooling + cells are used by both cells. For example: + `index 0 1 2 3 4` + `value 20 5 16 3 7` + If the pooling sequence is [0, 2, 4], then 16, at index 2 will be used + twice. The result would be [20, 16] for fractional max pooling. + deterministic: An optional `bool`. Deprecated; use `fractional_max_pool_v2` + instead. + seed: An optional `int`. Defaults to `0`. If set to be non-zero, the + random number generator is seeded by the given seed. Otherwise it is + seeded by a random seed. + seed2: An optional `int`. Deprecated; use `fractional_max_pool_v2` instead. + name: A name for the operation (optional). + + Returns: + A tuple of `Tensor` objects (`output`, `row_pooling_sequence`, + `col_pooling_sequence`). + output: Output `Tensor` after fractional max pooling. Has the same type as + `value`. + row_pooling_sequence: A `Tensor` of type `int64`. + col_pooling_sequence: A `Tensor` of type `int64`. + """ + return gen_nn_ops.fractional_max_pool(value, pooling_ratio, pseudo_random, + overlapping, deterministic, seed, seed2, + name) + + +@tf_export("nn.fractional_max_pool", v1=[]) +def fractional_max_pool_v2(value, + pooling_ratio, + pseudo_random=False, + overlapping=False, + seed=0, + name=None): # pylint: disable=redefined-builtin + r"""Performs fractional max pooling on the input. + + Fractional max pooling is slightly different than regular max pooling. In + regular max pooling, you downsize an input set by taking the maximum value of + smaller N x N subsections of the set (often 2x2), and try to reduce the set by + a factor of N, where N is an integer. Fractional max pooling, as you might + expect from the word "fractional", means that the overall reduction ratio N + does not have to be an integer. + + The sizes of the pooling regions are generated randomly but are fairly + uniform. For example, let's look at the height dimension, and the constraints + on the list of rows that will be pool boundaries. + + First we define the following: + + 1. input_row_length : the number of rows from the input set + 2. output_row_length : which will be smaller than the input + 3. alpha = input_row_length / output_row_length : our reduction ratio + 4. K = floor(alpha) + 5. row_pooling_sequence : this is the result list of pool boundary rows + + Then, row_pooling_sequence should satisfy: + + 1. a[0] = 0 : the first value of the sequence is 0 + 2. a[end] = input_row_length : the last value of the sequence is the size + 3. K <= (a[i+1] - a[i]) <= K+1 : all intervals are K or K+1 size + 4. length(row_pooling_sequence) = output_row_length+1 + + For more details on fractional max pooling, see this paper: [Benjamin Graham, + Fractional Max-Pooling](http://arxiv.org/abs/1412.6071) + + Args: + value: A `Tensor`. 4-D with shape `[batch, height, width, channels]`. + pooling_ratio: A list of `floats` that has length >= 4. Pooling ratio for + each dimension of `value`, currently only supports row and col dimension + and should be >= 1.0. For example, a valid pooling ratio looks like [1.0, + 1.44, 1.73, 1.0]. The first and last elements must be 1.0 because we don't + allow pooling on batch and channels dimensions. 1.44 and 1.73 are pooling + ratio on height and width dimensions respectively. + pseudo_random: An optional `bool`. Defaults to `False`. When set to `True`, + generates the pooling sequence in a pseudorandom fashion, otherwise, in a + random fashion. Check paper [Benjamin Graham, Fractional + Max-Pooling](http://arxiv.org/abs/1412.6071) for difference between + pseudorandom and random. + overlapping: An optional `bool`. Defaults to `False`. When set to `True`, + it means when pooling, the values at the boundary of adjacent pooling + cells are used by both cells. For example: + `index 0 1 2 3 4` + `value 20 5 16 3 7` + If the pooling sequence is [0, 2, 4], then 16, at index 2 will be used + twice. The result would be [20, 16] for fractional max pooling. + seed: An optional `int`. Defaults to `0`. If set to be non-zero, the + random number generator is seeded by the given seed. Otherwise it is + seeded by a random seed. + name: A name for the operation (optional). + + Returns: + A tuple of `Tensor` objects (`output`, `row_pooling_sequence`, + `col_pooling_sequence`). + output: Output `Tensor` after fractional max pooling. Has the same type as + `value`. + row_pooling_sequence: A `Tensor` of type `int64`. + col_pooling_sequence: A `Tensor` of type `int64`. + """ + if seed == 0: + return gen_nn_ops.fractional_max_pool(value, pooling_ratio, pseudo_random, + overlapping, deterministic=False, + seed=0, seed2=0, name=name) + else: + seed1, seed2 = random_seed.get_seed(seed) + return gen_nn_ops.fractional_max_pool(value, pooling_ratio, pseudo_random, + overlapping, deterministic=True, + seed=seed1, seed2=seed2, name=name) + + +@tf_export(v1=["nn.fractional_avg_pool"]) +@deprecation.deprecated(date=None, instructions="`seed2` and `deterministic` " + "args are deprecated. Use fractional_avg_pool_v2.") +def fractional_avg_pool(value, + pooling_ratio, + pseudo_random=False, + overlapping=False, + deterministic=False, + seed=0, + seed2=0, + name=None): # pylint: disable=redefined-builtin + r"""Performs fractional average pooling on the input. + + This is a deprecated version of `fractional_avg_pool`. + + Fractional average pooling is similar to Fractional max pooling in the pooling + region generation step. The only difference is that after pooling regions are + generated, a mean operation is performed instead of a max operation in each + pooling region. + + Args: + value: A `Tensor`. 4-D with shape `[batch, height, width, channels]`. + pooling_ratio: A list of `floats` that has length >= 4. Pooling ratio for + each dimension of `value`, currently only supports row and col dimension + and should be >= 1.0. For example, a valid pooling ratio looks like [1.0, + 1.44, 1.73, 1.0]. The first and last elements must be 1.0 because we don't + allow pooling on batch and channels dimensions. 1.44 and 1.73 are pooling + ratio on height and width dimensions respectively. + pseudo_random: An optional `bool`. Defaults to `False`. When set to `True`, + generates the pooling sequence in a pseudorandom fashion, otherwise, in a + random fashion. Check paper [Benjamin Graham, Fractional + Max-Pooling](http://arxiv.org/abs/1412.6071) for difference between + pseudorandom and random. + overlapping: An optional `bool`. Defaults to `False`. When set to `True`, + it means when pooling, the values at the boundary of adjacent pooling + cells are used by both cells. For example: + `index 0 1 2 3 4` + `value 20 5 16 3 7` + If the pooling sequence is [0, 2, 4], then 16, at index 2 will be used + twice. The result would be [20, 16] for fractional avg pooling. + deterministic: An optional `bool`. Deprecated; use `fractional_avg_pool_v2` + instead. + seed: An optional `int`. Defaults to `0`. If set to be non-zero, the + random number generator is seeded by the given seed. Otherwise it is + seeded by a random seed. + seed2: An optional `int`. Deprecated; use `fractional_avg_pool_v2` instead. + name: A name for the operation (optional). + + Returns: + A tuple of `Tensor` objects (`output`, `row_pooling_sequence`, + `col_pooling_sequence`). + output: Output `Tensor` after fractional avg pooling. Has the same type as + `value`. + row_pooling_sequence: A `Tensor` of type `int64`. + col_pooling_sequence: A `Tensor` of type `int64`. + """ + return gen_nn_ops.fractional_avg_pool(value, pooling_ratio, pseudo_random, + overlapping, deterministic, seed, seed2, + name=name) + + +@tf_export("nn.fractional_avg_pool", v1=[]) +def fractional_avg_pool_v2(value, + pooling_ratio, + pseudo_random=False, + overlapping=False, + seed=0, + name=None): # pylint: disable=redefined-builtin + r"""Performs fractional average pooling on the input. + + Fractional average pooling is similar to Fractional max pooling in the pooling + region generation step. The only difference is that after pooling regions are + generated, a mean operation is performed instead of a max operation in each + pooling region. + + Args: + value: A `Tensor`. 4-D with shape `[batch, height, width, channels]`. + pooling_ratio: A list of `floats` that has length >= 4. Pooling ratio for + each dimension of `value`, currently only supports row and col dimension + and should be >= 1.0. For example, a valid pooling ratio looks like [1.0, + 1.44, 1.73, 1.0]. The first and last elements must be 1.0 because we don't + allow pooling on batch and channels dimensions. 1.44 and 1.73 are pooling + ratio on height and width dimensions respectively. + pseudo_random: An optional `bool`. Defaults to `False`. When set to `True`, + generates the pooling sequence in a pseudorandom fashion, otherwise, in a + random fashion. Check paper [Benjamin Graham, Fractional + Max-Pooling](http://arxiv.org/abs/1412.6071) for difference between + pseudorandom and random. + overlapping: An optional `bool`. Defaults to `False`. When set to `True`, + it means when pooling, the values at the boundary of adjacent pooling + cells are used by both cells. For example: + `index 0 1 2 3 4` + `value 20 5 16 3 7` + If the pooling sequence is [0, 2, 4], then 16, at index 2 will be used + twice. The result would be [20, 16] for fractional avg pooling. + seed: An optional `int`. Defaults to `0`. If set to be non-zero, the + random number generator is seeded by the given seed. Otherwise it is + seeded by a random seed. + name: A name for the operation (optional). + + Returns: + A tuple of `Tensor` objects (`output`, `row_pooling_sequence`, + `col_pooling_sequence`). + output: Output `Tensor` after fractional avg pooling. Has the same type as + `value`. + row_pooling_sequence: A `Tensor` of type `int64`. + col_pooling_sequence: A `Tensor` of type `int64`. + """ + if seed == 0: + return gen_nn_ops.fractional_avg_pool(value, pooling_ratio, pseudo_random, + overlapping, deterministic=False, + seed=0, seed2=0, name=name) + else: + seed1, seed2 = random_seed.get_seed(seed) + return gen_nn_ops.fractional_avg_pool(value, pooling_ratio, pseudo_random, + overlapping, deterministic=True, + seed=seed1, seed2=seed2, name=name) + + +@tf_export(v1=["nn.conv1d"]) @deprecation.deprecated_arg_values( None, "`NCHW` for data_format is deprecated, use `NCW` instead", @@ -2487,6 +3474,64 @@ def conv1d(value, return array_ops.squeeze(result, [spatial_start_dim]) +@tf_export("nn.conv1d", v1=[]) +def conv1d_v2(input, # pylint: disable=redefined-builtin + filters, + stride, + padding, + data_format=None, + name=None): + r"""Computes a 1-D convolution given 3-D input and filter tensors. + + Given an input tensor of shape + [batch, in_width, in_channels] + if data_format is "NWC", or + [batch, in_channels, in_width] + if data_format is "NCW", + and a filter / kernel tensor of shape + [filter_width, in_channels, out_channels], this op reshapes + the arguments to pass them to conv2d to perform the equivalent + convolution operation. + + Internally, this op reshapes the input tensors and invokes `tf.nn.conv2d`. + For example, if `data_format` does not start with "NC", a tensor of shape + [batch, in_width, in_channels] + is reshaped to + [batch, 1, in_width, in_channels], + and the filter is reshaped to + [1, filter_width, in_channels, out_channels]. + The result is then reshaped back to + [batch, out_width, out_channels] + \(where out_width is a function of the stride and padding as in conv2d\) and + returned to the caller. + + Args: + input: A 3D `Tensor`. Must be of type `float16`, `float32`, or `float64`. + filters: A 3D `Tensor`. Must have the same type as `input`. + stride: An `integer`. The number of entries by which + the filter is moved right at each step. + padding: 'SAME' or 'VALID' + data_format: An optional `string` from `"NWC", "NCW"`. Defaults + to `"NWC"`, the data is stored in the order of + [batch, in_width, in_channels]. The `"NCW"` format stores + data as [batch, in_channels, in_width]. + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type as input. + + Raises: + ValueError: if `data_format` is invalid. + """ + return conv1d(input, # pylint: disable=redefined-builtin + filters, + stride, + padding, + use_cudnn_on_gpu=True, + data_format=data_format, + name=name) + + def conv1d_transpose( value, filter, # pylint: disable=redefined-builtin @@ -2602,7 +3647,7 @@ def _calc_dilation2d_flops(graph, node): return ops.OpStats("flops", (output_count * filter_height * filter_width * 2)) -@tf_export("nn.erosion2d") +@tf_export(v1=["nn.erosion2d"]) def erosion2d(value, kernel, strides, rates, padding, name=None): """Computes the grayscale erosion of 4-D `value` and 3-D `kernel` tensors. @@ -2661,6 +3706,75 @@ def erosion2d(value, kernel, strides, rates, padding, name=None): name=name)) +@tf_export("nn.erosion2d", v1=[]) +def erosion2d_v2(value, + filters, + strides, + padding, + data_format, + dilations, + name=None): + """Computes the grayscale erosion of 4-D `value` and 3-D `filters` tensors. + + The `value` tensor has shape `[batch, in_height, in_width, depth]` and the + `filters` tensor has shape `[filters_height, filters_width, depth]`, i.e., + each input channel is processed independently of the others with its own + structuring function. The `output` tensor has shape + `[batch, out_height, out_width, depth]`. The spatial dimensions of the + output tensor depend on the `padding` algorithm. We currently only support the + default "NHWC" `data_format`. + + In detail, the grayscale morphological 2-D erosion is given by: + + output[b, y, x, c] = + min_{dy, dx} value[b, + strides[1] * y - dilations[1] * dy, + strides[2] * x - dilations[2] * dx, + c] - + filters[dy, dx, c] + + Duality: The erosion of `value` by the `filters` is equal to the negation of + the dilation of `-value` by the reflected `filters`. + + Args: + value: A `Tensor`. 4-D with shape `[batch, in_height, in_width, depth]`. + filters: A `Tensor`. Must have the same type as `value`. + 3-D with shape `[filters_height, filters_width, depth]`. + strides: A list of `ints` that has length `>= 4`. + 1-D of length 4. The stride of the sliding window for each dimension of + the input tensor. Must be: `[1, stride_height, stride_width, 1]`. + padding: A `string` from: `"SAME", "VALID"`. + The type of padding algorithm to use. + data_format: A `string`, only `"NHWC"` is currently supported. + dilations: A list of `ints` that has length `>= 4`. + 1-D of length 4. The input stride for atrous morphological dilation. + Must be: `[1, rate_height, rate_width, 1]`. + name: A name for the operation (optional). If not specified "erosion2d" + is used. + + Returns: + A `Tensor`. Has the same type as `value`. + 4-D with shape `[batch, out_height, out_width, depth]`. + + Raises: + ValueError: If the `value` depth does not match `filters`' shape, or if + padding is other than `'VALID'` or `'SAME'`. + """ + if data_format != "NHWC": + raise ValueError("Data formats other than NHWC are not yet supported") + + with ops.name_scope(name, "erosion2d", [value, filters]) as name: + # Reduce erosion to dilation by duality. + return math_ops.negative( + gen_nn_ops.dilation2d( + input=math_ops.negative(value), + filter=array_ops.reverse_v2(filters, [0, 1]), + strides=strides, + rates=dilations, + padding=padding, + name=name)) + + @tf_export("math.in_top_k", "nn.in_top_k") def in_top_k(predictions, targets, k, name=None): r"""Says whether the targets are in the top `K` predictions. @@ -2693,3 +3807,10 @@ def in_top_k(predictions, targets, k, name=None): """ with ops.name_scope(name, "in_top_k"): return gen_nn_ops.in_top_kv2(predictions, targets, k, name=name) + + +tf_export(v1=["nn.quantized_avg_pool"])(gen_nn_ops.quantized_avg_pool) +tf_export(v1=["nn.quantized_conv2d"])(gen_nn_ops.quantized_conv2d) +tf_export(v1=["nn.quantized_relu_x"])(gen_nn_ops.quantized_relu_x) +tf_export(v1=["nn.quantized_max_pool"])(gen_nn_ops.quantized_max_pool) + diff --git a/tensorflow/python/ops/nn_test.py b/tensorflow/python/ops/nn_test.py index 152b2020eb..0336d0d27c 100644 --- a/tensorflow/python/ops/nn_test.py +++ b/tensorflow/python/ops/nn_test.py @@ -49,36 +49,39 @@ class ZeroFractionTest(test_lib.TestCase): nonzeros = np.count_nonzero(x.flatten()) return 1.0 - nonzeros / total_elements + @test_util.run_deprecated_v1 def testZeroFraction(self): x_shape = [5, 17] x_np = np.random.randint(0, 2, size=x_shape).astype(np.float32) y_np = self._ZeroFraction(x_np) - with self.cached_session(): - x_tf = constant_op.constant(x_np) - x_tf.set_shape(x_shape) - y_tf = nn_impl.zero_fraction(x_tf) - y_tf_np = y_tf.eval() + + x_tf = constant_op.constant(x_np) + x_tf.set_shape(x_shape) + y_tf = nn_impl.zero_fraction(x_tf) + y_tf_np = self.evaluate(y_tf) + eps = 1e-8 self.assertAllClose(y_tf_np, y_np, eps) + @test_util.run_deprecated_v1 def testZeroFractionEmpty(self): - with self.cached_session(): - x = np.zeros(0) - y = nn_impl.zero_fraction(x).eval() - self.assertTrue(np.isnan(y)) + x = np.zeros(0) + y = self.evaluate(nn_impl.zero_fraction(x)) + self.assertTrue(np.isnan(y)) + @test_util.run_deprecated_v1 def testZeroFraction2_27Zeros(self): sparsity = nn_impl.zero_fraction( array_ops.zeros([int(2**27 * 1.01)], dtype=dtypes.int8)) - with self.cached_session(): - self.assertAllClose(1.0, sparsity.eval()) + self.assertAllClose(1.0, self.evaluate(sparsity)) + @test_util.run_deprecated_v1 def testZeroFraction2_27Ones(self): sparsity = nn_impl.zero_fraction( array_ops.ones([int(2**27 * 1.01)], dtype=dtypes.int8)) - with self.cached_session(): - self.assertAllClose(0.0, sparsity.eval()) + self.assertAllClose(0.0, self.evaluate(sparsity)) + @test_util.run_deprecated_v1 def testUnknownSize(self): value = array_ops.placeholder(dtype=dtypes.float32) sparsity = nn_impl.zero_fraction(value) @@ -103,8 +106,8 @@ class SoftmaxTest(test_lib.TestCase, parameterized.TestCase): x_np = np.random.randn(*x_shape).astype(np.float32) y_np = self._softmax(x_np) x_tf = constant_op.constant(x_np) - y_tf = nn_ops.softmax(x_tf) - y_tf_last_dim = nn_ops.softmax(x_tf, 1) + y_tf = nn_ops.softmax_v2(x_tf) + y_tf_last_dim = nn_ops.softmax_v2(x_tf, 1) y_tf_np = self.evaluate(y_tf) y_tf_last_dim_np = self.evaluate(y_tf_last_dim) eps = 1e-3 @@ -113,9 +116,9 @@ class SoftmaxTest(test_lib.TestCase, parameterized.TestCase): def testSoftmaxAxes(self): arr = np.linspace(0., 1, 12).reshape(3, 4) - x_neg_axis = nn_ops.softmax(arr, axis=-2) - y_pos_axis = nn_ops.softmax(arr, axis=0) - z_gt_axis = nn_ops.softmax(arr, axis=0) + x_neg_axis = nn_ops.softmax_v2(arr, axis=-2) + y_pos_axis = nn_ops.softmax_v2(arr, axis=0) + z_gt_axis = nn_ops.softmax_v2(arr, axis=0) x_neg_axis_tf = self.evaluate(x_neg_axis) y_pos_axis_tf = self.evaluate(y_pos_axis) z_gt_axis_tf = self.evaluate(z_gt_axis) @@ -124,11 +127,12 @@ class SoftmaxTest(test_lib.TestCase, parameterized.TestCase): self.assertAllClose(y_pos_axis_tf, z_gt_axis_tf, eps) @parameterized.parameters(((5, 10),), ((2, 3, 4),)) + @test_util.run_deprecated_v1 def testGradient(self, x_shape): x_np = np.random.randn(*x_shape).astype(np.float64) with self.cached_session(): x_tf = constant_op.constant(x_np) - y_tf = nn_ops.softmax(x_tf) + y_tf = nn_ops.softmax_v2(x_tf) err = gradient_checker.compute_gradient_error(x_tf, x_shape, y_tf, x_shape) eps = 2e-8 @@ -159,6 +163,7 @@ class LogPoissonLossTest(test_lib.TestCase): self.assertAllClose(y_tf_np, y_np, eps) self.assertAllClose(y_tf_np_stirling, y_np_stirling, eps) + @test_util.run_deprecated_v1 def testGradient(self): x_shape = [5, 10] x_np = np.random.randn(*x_shape).astype(np.float64) @@ -191,16 +196,16 @@ class LogSoftmaxTest(test_lib.TestCase, parameterized.TestCase): x_np = np.random.randn(*x_shape).astype(np.float32) y_np = self._log_softmax(x_np) x_tf = constant_op.constant(x_np) - y_tf = nn_ops.log_softmax(x_tf) + y_tf = nn_ops.log_softmax_v2(x_tf) y_tf_np = self.evaluate(y_tf) eps = 1e-3 self.assertAllClose(y_tf_np, y_np, eps) def testLogSoftmaxAxes(self): arr = np.linspace(0., 1, 12).reshape(3, 4) - x_neg_axis = nn_ops.log_softmax(arr, axis=-2) - y_pos_axis = nn_ops.log_softmax(arr, axis=0) - z_gt_axis = nn_ops.log_softmax(arr, axis=0) + x_neg_axis = nn_ops.log_softmax_v2(arr, axis=-2) + y_pos_axis = nn_ops.log_softmax_v2(arr, axis=0) + z_gt_axis = nn_ops.log_softmax_v2(arr, axis=0) x_neg_axis_tf = self.evaluate(x_neg_axis) y_pos_axis_tf = self.evaluate(y_pos_axis) z_gt_axis_tf = self.evaluate(z_gt_axis) @@ -209,11 +214,12 @@ class LogSoftmaxTest(test_lib.TestCase, parameterized.TestCase): self.assertAllClose(y_pos_axis_tf, z_gt_axis_tf, eps) @parameterized.parameters(((5, 10),), ((2, 3, 4),)) + @test_util.run_deprecated_v1 def testGradient(self, x_shape): x_np = np.random.randn(*x_shape).astype(np.float64) with self.cached_session(): x_tf = constant_op.constant(x_np) - y_tf = nn_ops.log_softmax(x_tf) + y_tf = nn_ops.log_softmax_v2(x_tf) err = gradient_checker.compute_gradient_error(x_tf, x_shape, y_tf, x_shape) eps = 1e-7 @@ -231,6 +237,7 @@ class L2LossTest(test_lib.TestCase): value = self.evaluate(l2loss) self.assertAllClose(7.0, value) + @test_util.run_deprecated_v1 def testGradient(self): x_shape = [20, 7, 3] np.random.seed(1) # Make it reproducible. @@ -264,7 +271,7 @@ class L2NormalizeTest(test_lib.TestCase): for dim in range(len(x_shape)): y_np = self._l2Normalize(x_np, dim) x_tf = constant_op.constant(x_np, name="x") - y_tf = nn_impl.l2_normalize(x_tf, dim) + y_tf = nn_impl.l2_normalize_v2(x_tf, dim) self.assertAllClose(y_np, self.evaluate(y_tf)) @test_util.run_in_graph_and_eager_modes @@ -275,9 +282,10 @@ class L2NormalizeTest(test_lib.TestCase): dim = [1, 2] y_np = self._l2Normalize(x_np, dim) x_tf = constant_op.constant(x_np, name="x") - y_tf = nn_impl.l2_normalize(x_tf, dim) + y_tf = nn_impl.l2_normalize_v2(x_tf, dim) self.assertAllClose(y_np, self.evaluate(y_tf)) + @test_util.run_deprecated_v1 def testL2NormalizeGradient(self): x_shape = [20, 7, 3] np.random.seed(1) @@ -285,7 +293,7 @@ class L2NormalizeTest(test_lib.TestCase): for dim in range(len(x_shape)): with self.cached_session(): x_tf = constant_op.constant(x_np, name="x") - y_tf = nn_impl.l2_normalize(x_tf, dim) + y_tf = nn_impl.l2_normalize_v2(x_tf, dim) err = gradient_checker.compute_gradient_error(x_tf, x_shape, y_tf, x_shape) print("L2Normalize gradient err = %g " % err) @@ -302,19 +310,18 @@ class DropoutTest(test_lib.TestCase): y_dim = 30 num_iter = 10 for keep_prob in [0.1, 0.5, 0.8]: - with self.cached_session(): - t = constant_op.constant( - 1.0, shape=[x_dim, y_dim], dtype=dtypes.float32) - dropout = nn_ops.dropout(t, keep_prob) - final_count = 0 - self.assertEqual([x_dim, y_dim], dropout.get_shape()) - for _ in xrange(0, num_iter): - value = dropout.eval() - final_count += np.count_nonzero(value) - # Verifies that there are only two values: 0 and 1/keep_prob. - sorted_value = np.unique(np.sort(value)) - self.assertEqual(0, sorted_value[0]) - self.assertAllClose(1 / keep_prob, sorted_value[1]) + t = constant_op.constant(1.0, shape=[x_dim, y_dim], dtype=dtypes.float32) + dropout = nn_ops.dropout(t, keep_prob) + final_count = 0 + self.assertEqual([x_dim, y_dim], dropout.get_shape()) + for _ in xrange(0, num_iter): + value = self.evaluate(dropout) + final_count += np.count_nonzero(value) + # Verifies that there are only two values: 0 and 1/keep_prob. + sorted_value = np.unique(np.sort(value)) + self.assertEqual(0, sorted_value[0]) + self.assertAllClose(1 / keep_prob, sorted_value[1]) + # Check that we are in the 15% error range expected_count = x_dim * y_dim * keep_prob * num_iter rel_error = math.fabs(final_count - expected_count) / expected_count @@ -330,19 +337,18 @@ class DropoutTest(test_lib.TestCase): y_dim = 3 num_iter = 10 for keep_prob in [0.1, 0.5, 0.8]: - with self.cached_session(): - t = constant_op.constant( - 1.0, shape=[x_dim, y_dim], dtype=dtypes.float32) - dropout = nn_ops.dropout(t, keep_prob, noise_shape=[x_dim, 1]) - self.assertEqual([x_dim, y_dim], dropout.get_shape()) - final_count = 0 - for _ in xrange(0, num_iter): - value = dropout.eval() - final_count += np.count_nonzero(value) - # Verifies that there are only two values: 0 and 1/keep_prob. - sorted_value = np.unique(np.sort(value)) - self.assertEqual(0, sorted_value[0]) - self.assertAllClose(1 / keep_prob, sorted_value[1]) + t = constant_op.constant(1.0, shape=[x_dim, y_dim], dtype=dtypes.float32) + dropout = nn_ops.dropout(t, keep_prob, noise_shape=[x_dim, 1]) + self.assertEqual([x_dim, y_dim], dropout.get_shape()) + final_count = 0 + for _ in xrange(0, num_iter): + value = self.evaluate(dropout) + final_count += np.count_nonzero(value) + # Verifies that there are only two values: 0 and 1/keep_prob. + sorted_value = np.unique(np.sort(value)) + self.assertEqual(0, sorted_value[0]) + self.assertAllClose(1 / keep_prob, sorted_value[1]) + # Check that we are in the 15% error range expected_count = x_dim * y_dim * keep_prob * num_iter rel_error = math.fabs(final_count - expected_count) / expected_count @@ -355,18 +361,17 @@ class DropoutTest(test_lib.TestCase): y_dim = 30 num_iter = 10 for keep_prob in [0.1, 0.5, 0.8]: - with self.cached_session(): - t = constant_op.constant( - 1.0, shape=[x_dim, y_dim], dtype=dtypes.float32) - dropout = nn_ops.dropout(t, keep_prob, noise_shape=[x_dim, 1]) - self.assertEqual([x_dim, y_dim], dropout.get_shape()) - for _ in xrange(0, num_iter): - value = dropout.eval() - # Verifies that each y column as only one type of activation. - for i in xrange(x_dim): - sorted_value = np.unique(np.sort(value[i, :])) - self.assertEqual(sorted_value.size, 1) - + t = constant_op.constant(1.0, shape=[x_dim, y_dim], dtype=dtypes.float32) + dropout = nn_ops.dropout(t, keep_prob, noise_shape=[x_dim, 1]) + self.assertEqual([x_dim, y_dim], dropout.get_shape()) + for _ in xrange(0, num_iter): + value = self.evaluate(dropout) + # Verifies that each y column as only one type of activation. + for i in xrange(x_dim): + sorted_value = np.unique(np.sort(value[i, :])) + self.assertEqual(sorted_value.size, 1) + + @test_util.run_deprecated_v1 def testDropoutPlaceholderKeepProb(self): # Runs dropout with 0-1 tensor 10 times, sum the number of ones and validate # that it is producing approximately the right number of ones over a large @@ -395,6 +400,7 @@ class DropoutTest(test_lib.TestCase): print(rel_error) self.assertTrue(rel_error < 0.15) + @test_util.run_deprecated_v1 def testShapedDropoutUnknownShape(self): x_dim = 40 y_dim = 30 @@ -409,26 +415,26 @@ class DropoutTest(test_lib.TestCase): y_dim = 3 num_iter = 10 for keep_prob in [0.1, 0.5, 0.8]: - with self.cached_session(): - t = constant_op.constant( - 1.0, shape=[x_dim, y_dim], dtype=dtypes.float32) - # Set noise_shape=[None, 1] which means [x_dim, 1]. - dropout = nn_ops.dropout(t, keep_prob, noise_shape=[None, 1]) - self.assertEqual([x_dim, y_dim], dropout.get_shape()) - final_count = 0 - for _ in xrange(0, num_iter): - value = dropout.eval() - final_count += np.count_nonzero(value) - # Verifies that there are only two values: 0 and 1/keep_prob. - sorted_value = np.unique(np.sort(value)) - self.assertEqual(0, sorted_value[0]) - self.assertAllClose(1 / keep_prob, sorted_value[1]) + t = constant_op.constant(1.0, shape=[x_dim, y_dim], dtype=dtypes.float32) + # Set noise_shape=[None, 1] which means [x_dim, 1]. + dropout = nn_ops.dropout(t, keep_prob, noise_shape=[None, 1]) + self.assertEqual([x_dim, y_dim], dropout.get_shape()) + final_count = 0 + for _ in xrange(0, num_iter): + value = self.evaluate(dropout) + final_count += np.count_nonzero(value) + # Verifies that there are only two values: 0 and 1/keep_prob. + sorted_value = np.unique(np.sort(value)) + self.assertEqual(0, sorted_value[0]) + self.assertAllClose(1 / keep_prob, sorted_value[1]) + # Check that we are in the 15% error range expected_count = x_dim * y_dim * keep_prob * num_iter rel_error = math.fabs(final_count - expected_count) / expected_count print(rel_error) self.assertTrue(rel_error < 0.15) + @test_util.run_deprecated_v1 def testInvalidKeepProb(self): x_dim = 40 y_dim = 30 @@ -444,6 +450,18 @@ class DropoutTest(test_lib.TestCase): with self.assertRaises(ValueError): nn_ops.dropout(t, array_ops.placeholder(dtypes.float32, shape=[2])) + def testInvalidRate(self): + x_dim = 40 + y_dim = 30 + t = constant_op.constant(1.0, shape=[x_dim, y_dim], dtype=dtypes.float32) + with self.assertRaises(ValueError): + nn_ops.dropout_v2(t, -1.0) + with self.assertRaises(ValueError): + nn_ops.dropout_v2(t, 1.1) + with self.assertRaises(ValueError): + nn_ops.dropout_v2(t, [0.0, 1.0]) + + @test_util.run_deprecated_v1 def testShapedDropoutShapeError(self): # Runs shaped dropout and verifies an error is thrown on misshapen noise. x_dim = 40 @@ -466,9 +484,11 @@ class DropoutTest(test_lib.TestCase): def testNoDropoutFast(self): x = array_ops.zeros((5,)) - for p in 1, constant_op.constant(1.0): - y = nn_ops.dropout(x, keep_prob=p) - self.assertTrue(x is y) + y = nn_ops.dropout(x, keep_prob=1) + self.assertTrue(x is y) + + y = nn_ops.dropout_v2(x, rate=0) + self.assertTrue(x is y) def testDropoutWithIntegerInputs(self): x = constant_op.constant([1, 1, 1, 1, 1]) @@ -563,78 +583,78 @@ class ComputeSampledLogitsTest(test_lib.TestCase): initializer=constant_op.constant(biases)) with self.session(graph=g) as sess: variables.global_variables_initializer().run() - return sess.run([list(sharded_weights), list(sharded_biases)]) + return self.evaluate([list(sharded_weights), list(sharded_biases)]) def testShapes(self): np.random.seed(0) num_classes = 5 batch_size = 3 - with self.cached_session() as sess: - for num_true in range(1, 5): - labels = np.random.randint( - low=0, high=num_classes, size=batch_size * num_true) - (weights, biases, hidden_acts, sampled_vals, exp_logits, - exp_labels) = self._GenerateTestData( - num_classes=num_classes, - dim=10, - batch_size=batch_size, - num_true=num_true, - labels=labels, - sampled=[1, 0, 2, 3], - subtract_log_q=False) - logits_tensor, labels_tensor = _compute_sampled_logits( - weights=constant_op.constant(weights), - biases=constant_op.constant(biases), - labels=constant_op.constant( - labels, dtype=dtypes.int64, shape=(batch_size, num_true)), - inputs=constant_op.constant(hidden_acts), - num_sampled=4, - num_classes=num_classes, - num_true=num_true, - sampled_values=sampled_vals, - subtract_log_q=False, - remove_accidental_hits=False, - partition_strategy="div", - name="sampled_logits_basic_num_true_%d" % num_true) - got_logits, got_labels = sess.run([logits_tensor, labels_tensor]) - self.assertEqual(exp_logits.shape, got_logits.shape, self._eps) - self.assertEqual(exp_labels.shape, got_labels.shape, self._eps) + + for num_true in range(1, 5): + labels = np.random.randint( + low=0, high=num_classes, size=batch_size * num_true) + (weights, biases, hidden_acts, sampled_vals, exp_logits, + exp_labels) = self._GenerateTestData( + num_classes=num_classes, + dim=10, + batch_size=batch_size, + num_true=num_true, + labels=labels, + sampled=[1, 0, 2, 3], + subtract_log_q=False) + logits_tensor, labels_tensor = _compute_sampled_logits( + weights=constant_op.constant(weights), + biases=constant_op.constant(biases), + labels=constant_op.constant( + labels, dtype=dtypes.int64, shape=(batch_size, num_true)), + inputs=constant_op.constant(hidden_acts), + num_sampled=4, + num_classes=num_classes, + num_true=num_true, + sampled_values=sampled_vals, + subtract_log_q=False, + remove_accidental_hits=False, + partition_strategy="div", + name="sampled_logits_basic_num_true_%d" % num_true) + got_logits, got_labels = self.evaluate([logits_tensor, labels_tensor]) + self.assertEqual(exp_logits.shape, got_logits.shape, self._eps) + self.assertEqual(exp_labels.shape, got_labels.shape, self._eps) def testBasic(self): """Without accidental hit removal or subtract_log_q.""" np.random.seed(0) num_classes = 5 batch_size = 3 - with self.cached_session() as sess: - for num_true in range(1, 5): - labels = np.random.randint( - low=0, high=num_classes, size=batch_size * num_true) - (weights, biases, hidden_acts, sampled_vals, exp_logits, - exp_labels) = self._GenerateTestData( - num_classes=num_classes, - dim=10, - batch_size=batch_size, - num_true=num_true, - labels=labels, - sampled=[1, 0, 2, 3], - subtract_log_q=False) - logits_tensor, labels_tensor = _compute_sampled_logits( - weights=constant_op.constant(weights), - biases=constant_op.constant(biases), - labels=constant_op.constant( - labels, dtype=dtypes.int64, shape=(batch_size, num_true)), - inputs=constant_op.constant(hidden_acts), - num_sampled=4, - num_classes=num_classes, - num_true=num_true, - sampled_values=sampled_vals, - subtract_log_q=False, - remove_accidental_hits=False, - partition_strategy="div", - name="sampled_logits_basic_num_true_%d" % num_true) - got_logits, got_labels = sess.run([logits_tensor, labels_tensor]) - self.assertAllClose(exp_logits, got_logits, self._eps) - self.assertAllClose(exp_labels, got_labels, self._eps) + + for num_true in range(1, 5): + labels = np.random.randint( + low=0, high=num_classes, size=batch_size * num_true) + (weights, biases, hidden_acts, sampled_vals, exp_logits, + exp_labels) = self._GenerateTestData( + num_classes=num_classes, + dim=10, + batch_size=batch_size, + num_true=num_true, + labels=labels, + sampled=[1, 0, 2, 3], + subtract_log_q=False) + logits_tensor, labels_tensor = _compute_sampled_logits( + weights=constant_op.constant(weights), + biases=constant_op.constant(biases), + labels=constant_op.constant( + labels, dtype=dtypes.int64, shape=(batch_size, num_true)), + inputs=constant_op.constant(hidden_acts), + num_sampled=4, + num_classes=num_classes, + num_true=num_true, + sampled_values=sampled_vals, + subtract_log_q=False, + remove_accidental_hits=False, + partition_strategy="div", + name="sampled_logits_basic_num_true_%d" % num_true) + got_logits, got_labels = self.evaluate([logits_tensor, labels_tensor]) + self.assertAllClose(exp_logits, got_logits, self._eps) + self.assertAllClose(exp_labels, got_labels, self._eps) def testAccidentalHitRemoval(self): """With accidental hit removal, no subtract_log_q.""" @@ -642,118 +662,118 @@ class ComputeSampledLogitsTest(test_lib.TestCase): num_classes = 5 batch_size = 3 sampled = [1, 0, 2, 3] - with self.cached_session(): - for num_true in range(1, 5): - labels = np.random.randint( - low=0, high=num_classes, size=batch_size * num_true) - (weights, biases, hidden_acts, sampled_vals, _, - _) = self._GenerateTestData( - num_classes=num_classes, - dim=10, - batch_size=batch_size, - num_true=num_true, - labels=labels, - sampled=sampled, - subtract_log_q=False) - logits_tensor, _ = _compute_sampled_logits( - weights=constant_op.constant(weights), - biases=constant_op.constant(biases), - labels=constant_op.constant( - labels, dtype=dtypes.int64, shape=(batch_size, num_true)), - inputs=constant_op.constant(hidden_acts), - num_sampled=len(sampled), - num_classes=num_classes, - num_true=num_true, - sampled_values=sampled_vals, - subtract_log_q=False, - remove_accidental_hits=True, - partition_strategy="div", - name="sampled_logits_accidental_hit_removal_num_true_%d" % num_true) - # Test that the exponentiated logits of accidental hits are near 0. - # First we need to find the hits in this random test run: - labels_reshape = labels.reshape((batch_size, num_true)) - got_logits = logits_tensor.eval() - for row in xrange(batch_size): - row_labels = labels_reshape[row, :] - for col in xrange(len(sampled)): - if sampled[col] in row_labels: - # We need to add the num_true_test offset into logits_* - self.assertNear( - np.exp(got_logits[row, col + num_true]), 0., self._eps) + + for num_true in range(1, 5): + labels = np.random.randint( + low=0, high=num_classes, size=batch_size * num_true) + (weights, biases, hidden_acts, sampled_vals, _, + _) = self._GenerateTestData( + num_classes=num_classes, + dim=10, + batch_size=batch_size, + num_true=num_true, + labels=labels, + sampled=sampled, + subtract_log_q=False) + logits_tensor, _ = _compute_sampled_logits( + weights=constant_op.constant(weights), + biases=constant_op.constant(biases), + labels=constant_op.constant( + labels, dtype=dtypes.int64, shape=(batch_size, num_true)), + inputs=constant_op.constant(hidden_acts), + num_sampled=len(sampled), + num_classes=num_classes, + num_true=num_true, + sampled_values=sampled_vals, + subtract_log_q=False, + remove_accidental_hits=True, + partition_strategy="div", + name="sampled_logits_accidental_hit_removal_num_true_%d" % num_true) + # Test that the exponentiated logits of accidental hits are near 0. + # First we need to find the hits in this random test run: + labels_reshape = labels.reshape((batch_size, num_true)) + got_logits = self.evaluate(logits_tensor) + for row in xrange(batch_size): + row_labels = labels_reshape[row, :] + for col in xrange(len(sampled)): + if sampled[col] in row_labels: + # We need to add the num_true_test offset into logits_* + self.assertNear( + np.exp(got_logits[row, col + num_true]), 0., self._eps) def testSubtractLogQ(self): """With subtract_log_q, no accidental hit removal.""" np.random.seed(0) num_classes = 5 batch_size = 3 - with self.cached_session() as sess: - for num_true in range(1, 5): - labels = np.random.randint( - low=0, high=num_classes, size=batch_size * num_true) - (weights, biases, hidden_acts, sampled_vals, exp_logits, - exp_labels) = self._GenerateTestData( - num_classes=num_classes, - dim=10, - batch_size=batch_size, - num_true=num_true, - labels=labels, - sampled=[1, 0, 2, 3], - subtract_log_q=True) - logits_tensor, labels_tensor = _compute_sampled_logits( - weights=constant_op.constant(weights), - biases=constant_op.constant(biases), - labels=constant_op.constant( - labels, dtype=dtypes.int64, shape=(batch_size, num_true)), - inputs=constant_op.constant(hidden_acts), - num_sampled=4, - num_classes=num_classes, - num_true=num_true, - sampled_values=sampled_vals, - subtract_log_q=True, - remove_accidental_hits=False, - partition_strategy="div", - name="sampled_logits_subtract_log_q_num_true_%d" % num_true) - got_logits, got_labels = sess.run([logits_tensor, labels_tensor]) - self.assertAllClose(exp_logits, got_logits, self._eps) - self.assertAllClose(exp_labels, got_labels, self._eps) + + for num_true in range(1, 5): + labels = np.random.randint( + low=0, high=num_classes, size=batch_size * num_true) + (weights, biases, hidden_acts, sampled_vals, exp_logits, + exp_labels) = self._GenerateTestData( + num_classes=num_classes, + dim=10, + batch_size=batch_size, + num_true=num_true, + labels=labels, + sampled=[1, 0, 2, 3], + subtract_log_q=True) + logits_tensor, labels_tensor = _compute_sampled_logits( + weights=constant_op.constant(weights), + biases=constant_op.constant(biases), + labels=constant_op.constant( + labels, dtype=dtypes.int64, shape=(batch_size, num_true)), + inputs=constant_op.constant(hidden_acts), + num_sampled=4, + num_classes=num_classes, + num_true=num_true, + sampled_values=sampled_vals, + subtract_log_q=True, + remove_accidental_hits=False, + partition_strategy="div", + name="sampled_logits_subtract_log_q_num_true_%d" % num_true) + got_logits, got_labels = self.evaluate([logits_tensor, labels_tensor]) + self.assertAllClose(exp_logits, got_logits, self._eps) + self.assertAllClose(exp_labels, got_labels, self._eps) def testSharded(self): """With sharded weights and sharded biases.""" np.random.seed(0) num_classes = 5 batch_size = 3 - with self.cached_session() as sess: - for num_true in range(1, 5): - labels = np.random.randint( - low=0, high=num_classes, size=batch_size * num_true) - (weights, biases, hidden_acts, sampled_vals, exp_logits, - exp_labels) = self._GenerateTestData( - num_classes=num_classes, - dim=10, - batch_size=batch_size, - num_true=num_true, - labels=labels, - sampled=[1, 0, 2, 3], - subtract_log_q=False) - weight_shards, bias_shards = self._ShardTestEmbeddings( - weights, biases, num_shards=3) - logits_tensor, labels_tensor = _compute_sampled_logits( - weights=[constant_op.constant(shard) for shard in weight_shards], - biases=[constant_op.constant(shard) for shard in bias_shards], - labels=constant_op.constant( - labels, dtype=dtypes.int64, shape=(batch_size, num_true)), - inputs=constant_op.constant(hidden_acts), - num_sampled=4, - num_classes=num_classes, - num_true=num_true, - sampled_values=sampled_vals, - subtract_log_q=False, - remove_accidental_hits=False, - partition_strategy="div", - name="sampled_logits_sharded_num_true_%d" % num_true) - got_logits, got_labels = sess.run([logits_tensor, labels_tensor]) - self.assertAllClose(exp_logits, got_logits, self._eps) - self.assertAllClose(exp_labels, got_labels, self._eps) + + for num_true in range(1, 5): + labels = np.random.randint( + low=0, high=num_classes, size=batch_size * num_true) + (weights, biases, hidden_acts, sampled_vals, exp_logits, + exp_labels) = self._GenerateTestData( + num_classes=num_classes, + dim=10, + batch_size=batch_size, + num_true=num_true, + labels=labels, + sampled=[1, 0, 2, 3], + subtract_log_q=False) + weight_shards, bias_shards = self._ShardTestEmbeddings( + weights, biases, num_shards=3) + logits_tensor, labels_tensor = _compute_sampled_logits( + weights=[constant_op.constant(shard) for shard in weight_shards], + biases=[constant_op.constant(shard) for shard in bias_shards], + labels=constant_op.constant( + labels, dtype=dtypes.int64, shape=(batch_size, num_true)), + inputs=constant_op.constant(hidden_acts), + num_sampled=4, + num_classes=num_classes, + num_true=num_true, + sampled_values=sampled_vals, + subtract_log_q=False, + remove_accidental_hits=False, + partition_strategy="div", + name="sampled_logits_sharded_num_true_%d" % num_true) + got_logits, got_labels = self.evaluate([logits_tensor, labels_tensor]) + self.assertAllClose(exp_logits, got_logits, self._eps) + self.assertAllClose(exp_labels, got_labels, self._eps) def testNCELoss(self): # A simple test to verify the numerics. @@ -782,35 +802,32 @@ class ComputeSampledLogitsTest(test_lib.TestCase): exp_nce_loss = np.sum( _SigmoidCrossEntropyWithLogits(exp_logits, exp_labels), 1) - with self.cached_session(): - got_nce_loss = nn_impl.nce_loss( - weights=constant_op.constant(weights), - biases=constant_op.constant(biases), - labels=constant_op.constant(labels, shape=(batch_size, 1)), - inputs=constant_op.constant(hidden_acts), - num_sampled=4, - num_classes=num_classes, - num_true=1, - sampled_values=sampled_vals, - partition_strategy="div") - - self.assertAllClose(exp_nce_loss, got_nce_loss.eval(), 1e-4) - - # Test with sharded weights and sharded biases. - weight_shards, bias_shards = self._ShardTestEmbeddings( - weights, biases, num_shards=3) - got_nce_loss = nn_impl.nce_loss( - weights=[constant_op.constant(shard) for shard in weight_shards], - biases=[constant_op.constant(shard) for shard in bias_shards], - labels=constant_op.constant(labels, shape=(batch_size, 1)), - inputs=constant_op.constant(hidden_acts), - num_sampled=4, - num_classes=num_classes, - num_true=1, - sampled_values=sampled_vals, - partition_strategy="div") - - self.assertAllClose(exp_nce_loss, got_nce_loss.eval(), 1e-4) + got_nce_loss = nn_impl.nce_loss_v2( + weights=constant_op.constant(weights), + biases=constant_op.constant(biases), + labels=constant_op.constant(labels, shape=(batch_size, 1)), + inputs=constant_op.constant(hidden_acts), + num_sampled=4, + num_classes=num_classes, + num_true=1, + sampled_values=sampled_vals) + + self.assertAllClose(exp_nce_loss, self.evaluate(got_nce_loss), 1e-4) + + # Test with sharded weights and sharded biases. + weight_shards, bias_shards = self._ShardTestEmbeddings( + weights, biases, num_shards=3) + got_nce_loss = nn_impl.nce_loss_v2( + weights=[constant_op.constant(shard) for shard in weight_shards], + biases=[constant_op.constant(shard) for shard in bias_shards], + labels=constant_op.constant(labels, shape=(batch_size, 1)), + inputs=constant_op.constant(hidden_acts), + num_sampled=4, + num_classes=num_classes, + num_true=1, + sampled_values=sampled_vals) + + self.assertAllClose(exp_nce_loss, self.evaluate(got_nce_loss), 1e-4) def testSampledSoftmaxLoss(self): # A simple test to verify the numerics. @@ -839,39 +856,38 @@ class ComputeSampledLogitsTest(test_lib.TestCase): exp_sampled_softmax_loss = _SoftmaxCrossEntropyWithLogits( exp_logits, exp_labels) - with self.cached_session(): - got_sampled_softmax_loss = nn_impl.sampled_softmax_loss( - weights=constant_op.constant(weights), - biases=constant_op.constant(biases), - labels=constant_op.constant(labels, shape=(batch_size, 1)), - inputs=constant_op.constant(hidden_acts), - num_sampled=4, - num_classes=num_classes, - num_true=1, - sampled_values=sampled_vals, - remove_accidental_hits=False, - partition_strategy="div") - - self.assertAllClose(exp_sampled_softmax_loss, - got_sampled_softmax_loss.eval(), 1e-4) - - # Test with sharded weights and sharded biases. - weight_shards, bias_shards = self._ShardTestEmbeddings( - weights, biases, num_shards=3) - got_sampled_softmax_loss = nn_impl.sampled_softmax_loss( - weights=[constant_op.constant(shard) for shard in weight_shards], - biases=[constant_op.constant(shard) for shard in bias_shards], - labels=constant_op.constant(labels, shape=(batch_size, 1)), - inputs=constant_op.constant(hidden_acts), - num_sampled=4, - num_classes=num_classes, - num_true=1, - sampled_values=sampled_vals, - remove_accidental_hits=False, - partition_strategy="div") - - self.assertAllClose(exp_sampled_softmax_loss, - got_sampled_softmax_loss.eval(), 1e-4) + got_sampled_softmax_loss = nn_impl.sampled_softmax_loss( + weights=constant_op.constant(weights), + biases=constant_op.constant(biases), + labels=constant_op.constant(labels, shape=(batch_size, 1)), + inputs=constant_op.constant(hidden_acts), + num_sampled=4, + num_classes=num_classes, + num_true=1, + sampled_values=sampled_vals, + remove_accidental_hits=False, + partition_strategy="div") + + self.assertAllClose(exp_sampled_softmax_loss, + self.evaluate(got_sampled_softmax_loss), 1e-4) + + # Test with sharded weights and sharded biases. + weight_shards, bias_shards = self._ShardTestEmbeddings( + weights, biases, num_shards=3) + got_sampled_softmax_loss = nn_impl.sampled_softmax_loss( + weights=[constant_op.constant(shard) for shard in weight_shards], + biases=[constant_op.constant(shard) for shard in bias_shards], + labels=constant_op.constant(labels, shape=(batch_size, 1)), + inputs=constant_op.constant(hidden_acts), + num_sampled=4, + num_classes=num_classes, + num_true=1, + sampled_values=sampled_vals, + remove_accidental_hits=False, + partition_strategy="div") + + self.assertAllClose(exp_sampled_softmax_loss, + self.evaluate(got_sampled_softmax_loss), 1e-4) def testSampledSoftmaxLossBf16(self): # A simple test to verify the numerics for bfloat16. @@ -900,29 +916,30 @@ class ComputeSampledLogitsTest(test_lib.TestCase): exp_sampled_softmax_loss = _SoftmaxCrossEntropyWithLogits( exp_logits, exp_labels) - with self.cached_session(): - true_exp_bf16 = np.full( - [batch_size, 1], fill_value=0.5, dtype=dtypes.bfloat16.as_numpy_dtype) - sampled_exp_bf16 = np.full( - [len(sampled)], fill_value=0.5, dtype=dtypes.bfloat16.as_numpy_dtype) - sampled_vals_bf16 = (sampled, true_exp_bf16, sampled_exp_bf16) - - got_sampled_softmax_loss = math_ops.cast( - nn_impl.sampled_softmax_loss( - weights=constant_op.constant(weights, dtype=dtypes.bfloat16), - biases=constant_op.constant(biases, dtype=dtypes.bfloat16), - labels=constant_op.constant( - labels, shape=(batch_size, 1), dtype=dtypes.bfloat16), - inputs=constant_op.constant(hidden_acts, dtype=dtypes.bfloat16), - num_sampled=4, - num_classes=num_classes, - num_true=1, - sampled_values=sampled_vals_bf16, - remove_accidental_hits=False, - partition_strategy="div"), dtypes.float32) - - self.assertAllClose(exp_sampled_softmax_loss, - got_sampled_softmax_loss.eval(), 1e-1) + true_exp_bf16 = np.full([batch_size, 1], + fill_value=0.5, + dtype=dtypes.bfloat16.as_numpy_dtype) + sampled_exp_bf16 = np.full([len(sampled)], + fill_value=0.5, + dtype=dtypes.bfloat16.as_numpy_dtype) + sampled_vals_bf16 = (sampled, true_exp_bf16, sampled_exp_bf16) + + got_sampled_softmax_loss = math_ops.cast( + nn_impl.sampled_softmax_loss( + weights=constant_op.constant(weights, dtype=dtypes.bfloat16), + biases=constant_op.constant(biases, dtype=dtypes.bfloat16), + labels=constant_op.constant( + labels, shape=(batch_size, 1), dtype=dtypes.bfloat16), + inputs=constant_op.constant(hidden_acts, dtype=dtypes.bfloat16), + num_sampled=4, + num_classes=num_classes, + num_true=1, + sampled_values=sampled_vals_bf16, + remove_accidental_hits=False, + partition_strategy="div"), dtypes.float32) + + self.assertAllClose(exp_sampled_softmax_loss, + self.evaluate(got_sampled_softmax_loss), 1e-1) class CReluTest(test_lib.TestCase): @@ -931,9 +948,9 @@ class CReluTest(test_lib.TestCase): np.random.seed(1) # Make it reproducible. x = np.random.randn(3, 4).astype(np.float32) y = np.concatenate([x * (x > 0), -x * (x < 0)], axis=1) - with self.cached_session(): - z = nn_ops.crelu(constant_op.constant(x)).eval() - self.assertAllClose(y, z, 1e-4) + + z = self.evaluate(nn_ops.crelu(constant_op.constant(x))) + self.assertAllClose(y, z, 1e-4) class ReluTest(test_lib.TestCase): @@ -942,10 +959,11 @@ class ReluTest(test_lib.TestCase): np.random.seed(1) # Make it reproducible. x = np.random.randn(3, 4).astype(np.float32) y = np.maximum(x, 0.0) - with self.cached_session(): - z = nn_ops.relu(constant_op.constant(x)).eval() - self.assertAllEqual(y, z) + z = self.evaluate(nn_ops.relu(constant_op.constant(x))) + self.assertAllEqual(y, z) + + @test_util.run_deprecated_v1 def testNaNs(self): # Test that relu(nan) = nan for various sizes. for i in range(18): @@ -967,22 +985,26 @@ class LeakyReluTest(test_lib.TestCase): outputs = nn_ops.leaky_relu(inputs) self.assertEquals(inputs.shape, outputs.shape) - with self.cached_session() as sess: - inputs, outputs = sess.run([inputs, outputs]) + + inputs, outputs = self.evaluate([inputs, outputs]) + self.assertGreaterEqual(outputs.min(), 0.0) self.assertLessEqual(outputs.max(), 1.0) self.assertAllClose(inputs, outputs) + @test_util.run_deprecated_v1 def testValues(self): for dtype in [np.int32, np.int64, np.float16, np.float32, np.float64]: np_values = np.array([-2, -1, 0, 1, 2], dtype=dtype) outputs = nn_ops.leaky_relu(constant_op.constant(np_values)) - with self.cached_session() as sess: - outputs = sess.run(outputs) + + outputs = self.evaluate(outputs) + tol = 2e-3 if dtype == np.float16 else 1e-6 self.assertAllClose( outputs, [-0.4, -0.2, 0.0, 1.0, 2.0], rtol=tol, atol=tol) + @test_util.run_deprecated_v1 def testName(self): np_values = np.array([-2, -1, 0, 1, 2], dtype=np.float64) outputs_with_name_set = nn_ops.leaky_relu( @@ -996,6 +1018,7 @@ class LeakyReluTest(test_lib.TestCase): class SwishTest(test_lib.TestCase): + @test_util.run_deprecated_v1 def testValues(self): np_values = np.array( [np.linspace(-10.0, 0.0, 100), @@ -1004,11 +1027,13 @@ class SwishTest(test_lib.TestCase): tf_values = constant_op.constant(np_values) actual_tf_outputs = nn_impl.swish(tf_values) expected_tf_outputs = tf_values * math_ops.sigmoid(tf_values) - with self.cached_session() as sess: - actual_outputs, expected_outputs = sess.run( - [actual_tf_outputs, expected_tf_outputs]) + + actual_outputs, expected_outputs = self.evaluate( + [actual_tf_outputs, expected_tf_outputs]) + self.assertAllClose(actual_outputs, expected_outputs) + @test_util.run_deprecated_v1 def testGradients(self): shape = [5, 3, 4] sigma = 5 @@ -1039,8 +1064,8 @@ class MomentsTest(test_lib.TestCase): with self.session(graph=g) as sess: inputs = constant_op.constant( input_values, shape=input_shape, dtype=dtypes.float32) - mean, variance = nn_impl.moments( - inputs, moments_axes, keep_dims=keep_dims) + mean, variance = nn_impl.moments_v2( + inputs, moments_axes, keepdims=keep_dims) if check_gradients: err = gradient_checker.compute_gradient_error( @@ -1051,7 +1076,7 @@ class MomentsTest(test_lib.TestCase): self.assertLess(err, 1e-3) # Evaluate. - [mean, variance] = sess.run([mean, variance]) + [mean, variance] = self.evaluate([mean, variance]) # Make sure that there are no NaNs self.assertFalse(np.isnan(mean).any()) self.assertFalse(np.isnan(variance).any()) @@ -1094,9 +1119,9 @@ class DataFormatDimMapTest(test_lib.TestCase): def _test(self, x_val, y_val_expected): x = constant_op.constant(x_val) y = nn_ops.data_format_dim_map(x) - with self.cached_session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) - self.assertAllEqual(y_val, y_val_expected) + + y_val = self.evaluate(y) + self.assertAllEqual(y_val, y_val_expected) def test(self): self._test(0, 0) @@ -1117,8 +1142,8 @@ class DataFormatDimMapTest(test_lib.TestCase): y_val_expected = [2, 2, 3] x = constant_op.constant(x_val) y = nn_ops.data_format_dim_map(x, src_format="NHWC", dst_format="NCHW") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, y_val_expected) def testNHWCtoHWNC(self): @@ -1126,8 +1151,8 @@ class DataFormatDimMapTest(test_lib.TestCase): y_val_expected = [2, 0, 1, 3, 2, 0, 1, 3] x = constant_op.constant(x_val) y = nn_ops.data_format_dim_map(x, src_format="NHWC", dst_format="HWNC") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, y_val_expected) def testNHWCtoWHCN(self): @@ -1135,8 +1160,8 @@ class DataFormatDimMapTest(test_lib.TestCase): y_val_expected = [3, 1, 0, 2, 3, 1, 0, 2] x = constant_op.constant(x_val) y = nn_ops.data_format_dim_map(x, src_format="NHWC", dst_format="WHCN") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, y_val_expected) def testArbitraryASCII(self): @@ -1144,8 +1169,8 @@ class DataFormatDimMapTest(test_lib.TestCase): y_val_expected = [3, 2, 1, 0, 3, 2, 1, 0] x = constant_op.constant(x_val) y = nn_ops.data_format_dim_map(x, src_format="qwer", dst_format="rewq") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, y_val_expected) @@ -1155,64 +1180,64 @@ class DataFormatVectorPermuteTest(test_lib.TestCase): x_val = [7, 4, 9, 3] x = constant_op.constant(x_val) y = nn_ops.data_format_vec_permute(x) - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, [7, 3, 4, 9]) def testNCHWToNHWC(self): x_val = [7, 4, 9, 3] x = constant_op.constant(x_val) y = nn_ops.data_format_vec_permute(x, src_format="NCHW", dst_format="NHWC") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, [7, 9, 3, 4]) def testNHWCToHWNC(self): x_val = [7, 4, 9, 3] x = constant_op.constant(x_val) y = nn_ops.data_format_vec_permute(x, src_format="NHWC", dst_format="HWNC") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, [4, 9, 7, 3]) def testHWNCToNHWC(self): x_val = [7, 4, 9, 3] x = constant_op.constant(x_val) y = nn_ops.data_format_vec_permute(x, src_format="HWNC", dst_format="NHWC") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, [9, 7, 4, 3]) def testNHWCToNCHW2D(self): x_val = [[7, 4], [9, 3], [4, 5], [5, 1]] x = constant_op.constant(x_val) y = nn_ops.data_format_vec_permute(x) - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, [[7, 4], [5, 1], [9, 3], [4, 5]]) def testNHWCToHWNC2D(self): x_val = [[7, 4], [9, 3], [4, 5], [5, 1]] x = constant_op.constant(x_val) y = nn_ops.data_format_vec_permute(x, src_format="NHWC", dst_format="HWNC") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, [[9, 3], [4, 5], [7, 4], [5, 1]]) def testHWNCToNHWC2D(self): x_val = [[7, 4], [9, 3], [4, 5], [5, 1]] x = constant_op.constant(x_val) y = nn_ops.data_format_vec_permute(x, src_format="HWNC", dst_format="NHWC") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, [[4, 5], [7, 4], [9, 3], [5, 1]]) def testNCHWToNHWC2D(self): x_val = [[7, 4], [9, 3], [4, 5], [5, 1]] x = constant_op.constant(x_val) y = nn_ops.data_format_vec_permute(x, src_format="NCHW", dst_format="NHWC") - with self.session(use_gpu=test_lib.is_gpu_available()) as sess: - y_val = sess.run(y) + with test_util.use_gpu(): + y_val = self.evaluate(y) self.assertAllEqual(y_val, [[7, 4], [4, 5], [5, 1], [9, 3]]) diff --git a/tensorflow/python/ops/nn_xent_test.py b/tensorflow/python/ops/nn_xent_test.py index 57ce4fd0a9..3e5c198fc6 100644 --- a/tensorflow/python/ops/nn_xent_test.py +++ b/tensorflow/python/ops/nn_xent_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.ops import gradient_checker from tensorflow.python.ops import gradients_impl from tensorflow.python.ops import nn_impl @@ -53,6 +54,7 @@ class SigmoidCrossEntropyWithLogitsTest(test.TestCase): losses = np.array(self._SigmoidCrossEntropyWithLogits(x, y)).reshape(*sizes) return logits, targets, losses + @test_util.run_deprecated_v1 def testConstructionNamed(self): with self.cached_session(): logits, targets, _ = self._Inputs() @@ -68,7 +70,7 @@ class SigmoidCrossEntropyWithLogitsTest(test.TestCase): loss = nn_impl.sigmoid_cross_entropy_with_logits( labels=targets, logits=logits) np_loss = np.array(losses).astype(np.float32) - tf_loss = loss.eval() + tf_loss = self.evaluate(loss) self.assertAllClose(np_loss, tf_loss, atol=0.001) def testLogisticOutputMultiDim(self): @@ -79,9 +81,10 @@ class SigmoidCrossEntropyWithLogitsTest(test.TestCase): loss = nn_impl.sigmoid_cross_entropy_with_logits( labels=targets, logits=logits) np_loss = np.array(losses).astype(np.float32) - tf_loss = loss.eval() + tf_loss = self.evaluate(loss) self.assertAllClose(np_loss, tf_loss, atol=0.001) + @test_util.run_deprecated_v1 def testGradient(self): sizes = [4, 2] with self.cached_session(): @@ -92,6 +95,7 @@ class SigmoidCrossEntropyWithLogitsTest(test.TestCase): print("logistic loss gradient err = ", err) self.assertLess(err, 1e-7) + @test_util.run_deprecated_v1 def testGradientAtZero(self): with self.cached_session(): logits = constant_op.constant([0.0, 0.0], dtype=dtypes.float64) @@ -129,6 +133,7 @@ class WeightedCrossEntropyTest(test.TestCase): losses = np.array(self._WeightedCrossEntropy(x, y, q)).reshape(*sizes) return logits, targets, q, losses + @test_util.run_deprecated_v1 def testConstructionNamed(self): with self.cached_session(): logits, targets, pos_weight, _ = self._Inputs() @@ -143,7 +148,7 @@ class WeightedCrossEntropyTest(test.TestCase): loss = nn_impl.weighted_cross_entropy_with_logits( targets=targets, logits=logits, pos_weight=pos_weight) np_loss = np.array(losses).astype(np.float32) - tf_loss = loss.eval() + tf_loss = self.evaluate(loss) self.assertAllClose(np_loss, tf_loss, atol=0.001) def testOutputMultiDim(self): @@ -154,9 +159,10 @@ class WeightedCrossEntropyTest(test.TestCase): loss = nn_impl.weighted_cross_entropy_with_logits( targets=targets, logits=logits, pos_weight=pos_weight) np_loss = np.array(losses).astype(np.float32) - tf_loss = loss.eval() + tf_loss = self.evaluate(loss) self.assertAllClose(np_loss, tf_loss, atol=0.001) + @test_util.run_deprecated_v1 def testGradient(self): sizes = [4, 2] with self.cached_session(): diff --git a/tensorflow/python/ops/numerics.py b/tensorflow/python/ops/numerics.py index 1a235de90c..0ab39ad0a8 100644 --- a/tensorflow/python/ops/numerics.py +++ b/tensorflow/python/ops/numerics.py @@ -28,9 +28,7 @@ from tensorflow.python.util import deprecation from tensorflow.python.util.tf_export import tf_export -@tf_export( - "debugging.assert_all_finite", - v1=["debugging.assert_all_finite", "verify_tensor_all_finite"]) +@tf_export(v1=["debugging.assert_all_finite", "verify_tensor_all_finite"]) @deprecation.deprecated_endpoints("verify_tensor_all_finite") def verify_tensor_all_finite(t, msg, name=None): """Assert that the tensor does not contain any NaN's or Inf's. @@ -43,11 +41,26 @@ def verify_tensor_all_finite(t, msg, name=None): Returns: Same tensor as `t`. """ - with ops.name_scope(name, "VerifyFinite", [t]) as name: - t = ops.convert_to_tensor(t, name="t") - with ops.colocate_with(t): - verify_input = array_ops.check_numerics(t, message=msg) - out = control_flow_ops.with_dependencies([verify_input], t) + return verify_tensor_all_finite_v2(t, msg, name) + + +@tf_export("debugging.assert_all_finite", v1=[]) +def verify_tensor_all_finite_v2(x, message, name=None): + """Assert that the tensor does not contain any NaN's or Inf's. + + Args: + x: Tensor to check. + message: Message to log on failure. + name: A name for this operation (optional). + + Returns: + Same tensor as `x`. + """ + with ops.name_scope(name, "VerifyFinite", [x]) as name: + x = ops.convert_to_tensor(x, name="x") + with ops.colocate_with(x): + verify_input = array_ops.check_numerics(x, message=message) + out = control_flow_ops.with_dependencies([verify_input], x) return out diff --git a/tensorflow/tools/compatibility/testdata/test_file_v1_10.py b/tensorflow/python/ops/optional_grad.py similarity index 62% rename from tensorflow/tools/compatibility/testdata/test_file_v1_10.py rename to tensorflow/python/ops/optional_grad.py index e5ca8d3e2e..0d1eae3cda 100644 --- a/tensorflow/tools/compatibility/testdata/test_file_v1_10.py +++ b/tensorflow/python/ops/optional_grad.py @@ -12,23 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for tf upgrader.""" +"""Gradient functions for optional ops.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import tensorflow as tf -from tensorflow.python.framework import test_util -from tensorflow.python.platform import test as test_lib +from tensorflow.python.framework import ops +from tensorflow.python.ops import gen_dataset_ops -class TestUpgrade(test_util.TensorFlowTestCase): - """Test various APIs that have been changed in 2.0.""" - def testRenames(self): - with self.cached_session(): - self.assertAllClose(1.04719755, tf.acos(0.5).eval()) - self.assertAllClose(0.5, tf.rsqrt(4.0).eval()) +@ops.RegisterGradient("OptionalFromValue") +def _OptionalFromValueGrad(op, grad): + return gen_dataset_ops.optional_get_value( + grad, [t.dtype for t in op.inputs], [t.shape for t in op.inputs]) -if __name__ == "__main__": - test_lib.main() + +@ops.RegisterGradient("OptionalGetValue") +def _OptionalGetValueGrad(unused_op, *grads): + return gen_dataset_ops.optional_from_value(grads) diff --git a/tensorflow/python/ops/parallel_for/control_flow_ops.py b/tensorflow/python/ops/parallel_for/control_flow_ops.py index ead7ae5478..8f652e9c50 100644 --- a/tensorflow/python/ops/parallel_for/control_flow_ops.py +++ b/tensorflow/python/ops/parallel_for/control_flow_ops.py @@ -17,16 +17,20 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.eager import context +from tensorflow.python.eager import function from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import math_ops from tensorflow.python.ops import tensor_array_ops from tensorflow.python.ops.parallel_for.pfor import PFor from tensorflow.python.util import nest -def for_loop(loop_fn, loop_fn_dtypes, iters): +def for_loop(loop_fn, loop_fn_dtypes, iters, parallel_iterations=None): """Runs `loop_fn` `iters` times and stacks the outputs. @@ -39,6 +43,8 @@ def for_loop(loop_fn, loop_fn_dtypes, iters): objects. The shape of these outputs should not depend on the input. loop_fn_dtypes: dtypes for the outputs of loop_fn. iters: Number of iterations for which to run loop_fn. + parallel_iterations: The number of iterations that can be dispatched in + parallel. This knob can be used to control the total memory usage. Returns: Returns a nested structure of stacked output tensor objects with the same @@ -66,11 +72,16 @@ def for_loop(loop_fn, loop_fn_dtypes, iters): outputs.append(ta) return tuple([i + 1] + outputs) + if parallel_iterations is not None: + extra_args = {"parallel_iterations": parallel_iterations} + else: + extra_args = {} ta_list = control_flow_ops.while_loop( - lambda i, *ta: i < iters, while_body, [0] + [ - tensor_array_ops.TensorArray(dtype, iters) - for dtype in flat_loop_fn_dtypes - ])[1:] + lambda i, *ta: i < iters, + while_body, + [0] + [tensor_array_ops.TensorArray(dtype, iters) + for dtype in flat_loop_fn_dtypes], + **extra_args)[1:] # TODO(rachelim): enable this for sparse tensors @@ -79,7 +90,15 @@ def for_loop(loop_fn, loop_fn_dtypes, iters): return nest.pack_sequence_as(loop_fn_dtypes, output) -def pfor(loop_fn, iters): +def _flatten_first_two_dims(x): + """Flattens the first two dimensions of x into a single dimension.""" + old_shape = array_ops.shape(x) + new_shape = array_ops.concat([[old_shape[0] * old_shape[1]], old_shape[2:]], + axis=0) + return array_ops.reshape(x, new_shape) + + +def pfor(loop_fn, iters, parallel_iterations=None): """Equivalent to running `loop_fn` `iters` times and stacking the outputs. `pfor` has functionality similar to `for_loop`, i.e. running `loop_fn` `iters` @@ -99,8 +118,8 @@ def pfor(loop_fn, iters): reads, etc). - Conversion works only on a limited set of kernels for which a converter has been registered. - - loop_fn cannot currently contain control flow operations like - tf.while_loop or tf.cond. + - loop_fn has limited support for control flow operations. tf.cond in + particular is not supported. - `loop_fn` should return nested structure of Tensors or Operations. However if an Operation is returned, it should have zero outputs. - The shape and dtype of `loop_fn` outputs should not depend on the input @@ -109,22 +128,92 @@ def pfor(loop_fn, iters): Args: loop_fn: A function that takes an int32 scalar tf.Tensor object representing the iteration number, and returns a possibly nested structure of Tensor or - Operation objects. + Operation objects. Note that if setting `parallel_iterations` argument to + something other than None, `loop_fn` may be called more than once during + graph construction. So it may need to avoid mutating global state. iters: Number of iterations for which to run loop_fn. + parallel_iterations: A knob to control how many iterations are vectorized + and dispatched in parallel. The default value of None corresponds to + vectorizing all the iterations. If `parallel_iterations` is smaller than + `iters`, then chunks of at most that many iterations are dispatched in + sequence. This knob can be used to control the total memory usage. Returns: Returns a nested structure of stacked tensor objects with the same nested structure as the output of `loop_fn`. + Raises: + ValueError: If parallel_iterations is not None and not an integer > 1. """ + def f(): + return _pfor_impl(loop_fn, iters, parallel_iterations=parallel_iterations) + if context.executing_eagerly(): + f = function.defun(f) + return f() + + +def _pfor_impl(loop_fn, iters, parallel_iterations=None): + """Implementation of pfor.""" existing_ops = set(ops.get_default_graph().get_operations()) with ops.name_scope("loop_body"): loop_var = array_ops.placeholder(dtypes.int32, shape=[]) loop_fn_outputs = loop_fn(loop_var) new_ops = set(ops.get_default_graph().get_operations()) - existing_ops iters = ops.convert_to_tensor(iters) - with ops.name_scope("pfor"): - converter = PFor(loop_var, iters, new_ops) - outputs = [] - for loop_fn_output in nest.flatten(loop_fn_outputs): - outputs.append(converter.convert(loop_fn_output)) - return nest.pack_sequence_as(loop_fn_outputs, outputs) + if parallel_iterations is not None: + if parallel_iterations < 1: + raise ValueError("parallel_iterations must be None or a positive integer") + if parallel_iterations == 1: + raise ValueError("Found parallel_iterations == 1. Use for_loop instead.") + iters_value = tensor_util.constant_value(iters) + if iters_value is not None and iters_value < parallel_iterations: + parallel_iterations = None + if parallel_iterations is None: + with ops.name_scope("pfor"): + converter = PFor(loop_var, iters, new_ops) + outputs = [] + for loop_fn_output in nest.flatten(loop_fn_outputs): + outputs.append(converter.convert(loop_fn_output)) + return nest.pack_sequence_as(loop_fn_outputs, outputs) + else: + num_tiled_iterations = iters // parallel_iterations + num_remaining_iterations = iters % parallel_iterations + # TODO(agarwal): Avoid calling loop_fn twice. Generate the loop body inside + # a tf.function and extract the graph from there to vectorize it. + with ops.name_scope("pfor_untiled"): + converter = PFor(loop_var, num_remaining_iterations, new_ops) + remaining_outputs = [] + flattened_loop_fn_outputs = nest.flatten(loop_fn_outputs) + for loop_fn_output in flattened_loop_fn_outputs: + remaining_outputs.append(converter.convert(loop_fn_output)) + + with ops.name_scope("pfor_tiled"): + loop_fn_dtypes = [ops.convert_to_tensor(x).dtype + for x in flattened_loop_fn_outputs] + + def tiled_loop_body(j): + offset = j * parallel_iterations + num_remaining_iterations + + def tiled_loop_fn(i): + return nest.flatten(loop_fn(i + offset)) + + return pfor(tiled_loop_fn, parallel_iterations) + + tiled_outputs = for_loop(tiled_loop_body, loop_fn_dtypes, + num_tiled_iterations, parallel_iterations=1) + tiled_outputs = [_flatten_first_two_dims(y) for y in tiled_outputs] + + with ops.name_scope("pfor"): + iters_value = tensor_util.constant_value(iters) + if iters_value is None or iters_value % parallel_iterations: + outputs = control_flow_ops.cond( + math_ops.equal(num_remaining_iterations, 0), + lambda: tiled_outputs, + lambda: [array_ops.concat([x, y], axis=0) + for x, y in zip(remaining_outputs, tiled_outputs)]) + else: + outputs = tiled_outputs + return nest.pack_sequence_as(loop_fn_outputs, nest.flatten(outputs)) + + + + diff --git a/tensorflow/python/ops/parallel_for/control_flow_ops_test.py b/tensorflow/python/ops/parallel_for/control_flow_ops_test.py index 171369b724..cc20d7ca6a 100644 --- a/tensorflow/python/ops/parallel_for/control_flow_ops_test.py +++ b/tensorflow/python/ops/parallel_for/control_flow_ops_test.py @@ -26,10 +26,12 @@ import numpy as np from tensorflow.core.example import example_pb2 from tensorflow.core.example import feature_pb2 from tensorflow.python.client import session +from tensorflow.python.eager import backprop from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import bitwise_ops from tensorflow.python.ops import clip_ops @@ -52,6 +54,7 @@ from tensorflow.python.platform import test from tensorflow.python.util import nest +@test_util.run_all_in_graph_and_eager_modes class PForTest(test.TestCase): def _run_targets(self, targets1, targets2=None, run_init=True): @@ -73,9 +76,13 @@ class PForTest(test.TestCase): else: self.assertAllEqual(outputs[i + n], outputs[i]) - def _test_loop_fn(self, loop_fn, iters, loop_fn_dtypes=dtypes.float32): - t1 = pfor_control_flow_ops.pfor(loop_fn, iters=iters) - t2 = pfor_control_flow_ops.for_loop(loop_fn, loop_fn_dtypes, iters=iters) + def _test_loop_fn(self, loop_fn, iters, + loop_fn_dtypes=dtypes.float32, + parallel_iterations=None): + t1 = pfor_control_flow_ops.pfor(loop_fn, iters=iters, + parallel_iterations=parallel_iterations) + t2 = pfor_control_flow_ops.for_loop(loop_fn, loop_fn_dtypes, iters=iters, + parallel_iterations=parallel_iterations) self.run_and_assert_equal(t1, t2) def test_op_conversion_fallback_to_while_loop(self): @@ -96,7 +103,32 @@ class PForTest(test.TestCase): loop_fn, 3, loop_fn_dtypes=[dtypes.float32, dtypes.int32]) flags.FLAGS.op_conversion_fallback_to_while_loop = False + def test_parallel_iterations(self): + for parallel_iterations in [2, 3, 8, 10]: + x = random_ops.random_uniform([8, 3]) + # pylint: disable=cell-var-from-loop + def loop_fn(i): + return array_ops.gather(x, i) + # pylint: enable=cell-var-from-loop + + self._test_loop_fn(loop_fn, 8, parallel_iterations=parallel_iterations) + self._test_loop_fn(loop_fn, 4 * constant_op.constant(2), + parallel_iterations=parallel_iterations) + + def test_parallel_iterations_zero(self): + with self.assertRaisesRegexp(ValueError, "positive integer"): + pfor_control_flow_ops.pfor(lambda i: 1, 8, parallel_iterations=0) + with self.assertRaisesRegexp(TypeError, "positive integer"): + pfor_control_flow_ops.for_loop(lambda i: 1, dtypes.int32, 8, + parallel_iterations=0) + + def test_parallel_iterations_one(self): + with self.assertRaisesRegexp(ValueError, "Use for_loop instead"): + pfor_control_flow_ops.pfor(lambda i: 1, 8, parallel_iterations=1) + + +@test_util.run_all_in_graph_and_eager_modes class ArrayTest(PForTest): def test_gather(self): @@ -288,14 +320,17 @@ class ArrayTest(PForTest): def test_unary_cwise_ops(self): for op in [array_ops.identity, array_ops.stop_gradient]: - x = random_ops.random_uniform([3, 5]) + with backprop.GradientTape(persistent=True) as g: + x = random_ops.random_uniform([3, 5]) + g.watch(x) # pylint: disable=cell-var-from-loop def loop_fn(i): - x1 = array_ops.gather(x, i) - y = op(x1) + x1 - loss = nn.l2_loss(y) - return op(x), y, gradient_ops.gradients(loss, x1) + with g: + x1 = array_ops.gather(x, i) + y = op(x1) + x1 + loss = nn.l2_loss(y) + return op(x), y, g.gradient(loss, x1) # pylint: enable=cell-var-from-loop @@ -318,17 +353,21 @@ class ArrayTest(PForTest): self._test_loop_fn(loop_fn, 3, loop_fn_dtypes=[dtypes.float32]) def test_strided_slice(self): - x = random_ops.random_uniform([3, 3, 4, 4, 2, 2, 2]) + with backprop.GradientTape(persistent=True) as g: + x = random_ops.random_uniform([3, 3, 4, 4, 2, 2, 2]) + g.watch(x) def loop_fn(i): - x_i = array_ops.gather(x, i) - y = x_i[:2, ::2, 1::3, ..., array_ops.newaxis, 1] - loss = nn.l2_loss(y) - return y, gradient_ops.gradients(loss, x_i) + with g: + x_i = array_ops.gather(x, i) + y = x_i[:2, ::2, 1::3, ..., array_ops.newaxis, 1] + loss = nn.l2_loss(y) + return y, g.gradient(loss, x_i) self._test_loop_fn(loop_fn, 3, loop_fn_dtypes=[dtypes.float32] * 2) +@test_util.run_all_in_graph_and_eager_modes class BitwiseTest(PForTest): def test_unary_cwise(self): @@ -368,6 +407,7 @@ class BitwiseTest(PForTest): self._test_loop_fn(loop_fn, 3, loop_fn_dtypes=output_dtypes) +@test_util.run_all_in_graph_and_eager_modes class MathTest(PForTest): def test_unary_cwise_ops(self): @@ -424,22 +464,29 @@ class MathTest(PForTest): nn.softsign, ] for op in complex_ops + real_ops: - x = random_ops.random_uniform([3, 5]) - if op in complex_ops: - y = random_ops.random_uniform([3, 5]) - x = math_ops.complex(x, y) + with backprop.GradientTape(persistent=True) as g: + x = random_ops.random_uniform([3, 5]) + g.watch(x) + if op in complex_ops: + y = random_ops.random_uniform([3, 5]) + g.watch(y) + x = math_ops.complex(x, y) # pylint: disable=cell-var-from-loop output_dtypes = [] def loop_fn(i): - x1 = array_ops.gather(x, i) - y1 = op(x1) - outputs = [op(x), y1] - if y1.dtype == dtypes.float32: - loss = math_ops.reduce_sum(y1 * y1) - grad = gradient_ops.gradients(loss, x1) - if grad and grad[0] is not None: - outputs.extend(grad) + with g: + x1 = array_ops.gather(x, i) + y1 = op(x1) + outputs = [op(x), y1] + if y1.dtype == dtypes.float32: + loss = math_ops.reduce_sum(y1 * y1) + else: + loss = None + if loss is not None: + grad = g.gradient(loss, x1) + if grad is not None: + outputs.append(grad) del output_dtypes[:] output_dtypes.extend([t.dtype for t in outputs]) return outputs @@ -656,17 +703,19 @@ class MathTest(PForTest): x_shape = [2, 3, 4, 5, 6] x = random_ops.random_uniform(x_shape) for data_format in ("NCHW", "NHWC"): - bias_dim = 2 if data_format == "NCHW" else -1 - bias_shape = x_shape[bias_dim] - bias = random_ops.random_uniform([bias_shape]) + with backprop.GradientTape(persistent=True) as g: + bias_dim = 2 if data_format == "NCHW" else -1 + bias_shape = x_shape[bias_dim] + bias = random_ops.random_uniform([bias_shape]) + g.watch(bias) # pylint: disable=cell-var-from-loop def loop_fn(i): - a = array_ops.gather(x, i) - y = nn.bias_add(a, bias, data_format=data_format) - loss = math_ops.reduce_sum(y * y) - return y, gradient_ops.gradients(loss, bias) - + with g: + a = array_ops.gather(x, i) + y = nn.bias_add(a, bias, data_format=data_format) + loss = math_ops.reduce_sum(y * y) + return y, g.gradient(loss, bias) # pylint: enable=cell-var-from-loop self._test_loop_fn( @@ -727,6 +776,7 @@ class MathTest(PForTest): self._test_loop_fn(loop_fn, 2) +@test_util.run_all_in_graph_and_eager_modes class NNTest(PForTest): def test_conv2d(self): @@ -779,30 +829,60 @@ class NNTest(PForTest): self._test_loop_fn(loop_fn, 3, loop_fn_dtypes=[dtypes.float32] * 2) def test_avg_pool(self): - x = random_ops.random_uniform([3, 2, 12, 12, 3]) - ksize = [1, 3, 3, 1] + with backprop.GradientTape(persistent=True) as g: + x = random_ops.random_uniform([3, 2, 12, 12, 3]) + g.watch(x) + ksize = [1, 3, 3, 1] def loop_fn(i): - x1 = array_ops.gather(x, i) - output = nn.avg_pool( - x1, ksize, strides=[1, 2, 2, 1], padding="VALID", data_format="NHWC") - loss = nn.l2_loss(output) - return output, gradient_ops.gradients(loss, x1) + with g: + x1 = array_ops.gather(x, i) + output = nn.avg_pool( + x1, ksize, strides=[1, 2, 2, 1], padding="VALID", + data_format="NHWC") + loss = nn.l2_loss(output) + return output, g.gradient(loss, x1) self._test_loop_fn(loop_fn, 3, loop_fn_dtypes=[dtypes.float32] * 2) def test_max_pool(self): - x = random_ops.random_uniform([3, 2, 12, 12, 3]) - ksize = [1, 3, 3, 1] + with backprop.GradientTape(persistent=True) as g: + x = random_ops.random_uniform([3, 2, 12, 12, 3]) + g.watch(x) + ksize = [1, 3, 3, 1] + strides = [1, 2, 2, 1] def loop_fn(i): - x1 = array_ops.gather(x, i) - output = nn.max_pool( - x1, ksize, strides=[1, 2, 2, 1], padding="VALID", data_format="NHWC") - loss = nn.l2_loss(output) - ones = array_ops.ones_like(output) - grad = gradient_ops.gradients(loss, x1, grad_ys=ones) - grad_grad = gradient_ops.gradients(grad, ones) + with g: + x1 = array_ops.gather(x, i) + output = nn.max_pool( + x1, ksize, strides=strides, padding="VALID", data_format="NHWC") + loss = nn.l2_loss(output) + ones = array_ops.ones_like(output) + g.watch(ones) + grad = g.gradient(loss, x1, output_gradients=ones) + grad_grad = g.gradient(grad, ones) + return output, grad, grad_grad + + self._test_loop_fn(loop_fn, 3, loop_fn_dtypes=[dtypes.float32] * 3) + + def test_max_pool3d(self): + with backprop.GradientTape(persistent=True) as g: + x = random_ops.random_uniform([3, 3, 2, 12, 12, 3]) + g.watch(x) + ksize = [1, 1, 3, 3, 1] + strides = [1, 1, 2, 2, 1] + + def loop_fn(i): + with g: + x1 = array_ops.gather(x, i) + output = nn.max_pool3d( + x1, ksize, strides=strides, padding="VALID", data_format="NDHWC") + loss = nn.l2_loss(output) + ones = array_ops.ones_like(output) + g.watch(ones) + grad = g.gradient(loss, x1, output_gradients=ones) + grad_grad = g.gradient(grad, ones) return output, grad, grad_grad self._test_loop_fn(loop_fn, 3, loop_fn_dtypes=[dtypes.float32] * 3) @@ -813,36 +893,41 @@ class NNTest(PForTest): data_formats.append("NCHW") for is_training in (True, False): for data_format in data_formats: - if data_format == "NCHW": - x = random_ops.random_uniform([3, 1, 2, 5, 5]) - else: - x = random_ops.random_uniform([3, 1, 5, 5, 2]) - scale = random_ops.random_uniform([2]) - offset = random_ops.random_uniform([2]) - mean = None if is_training else random_ops.random_uniform([2]) - variance = None if is_training else random_ops.random_uniform([2]) + with backprop.GradientTape(persistent=True) as g: + if data_format == "NCHW": + x = random_ops.random_uniform([3, 1, 2, 5, 5]) + else: + x = random_ops.random_uniform([3, 1, 5, 5, 2]) + g.watch(x) + scale = random_ops.random_uniform([2]) + g.watch(scale) + offset = random_ops.random_uniform([2]) + g.watch(offset) + mean = None if is_training else random_ops.random_uniform([2]) + variance = None if is_training else random_ops.random_uniform([2]) # pylint: disable=cell-var-from-loop def loop_fn(i): - x1 = array_ops.gather(x, i) - outputs = nn.fused_batch_norm( - x1, - scale, - offset, - mean=mean, - variance=variance, - epsilon=0.01, - data_format=data_format, - is_training=is_training) - outputs = list(outputs) - # We only test the first value of outputs when is_training is False. - # It looks like CPU and GPU have different outputs for batch_mean and - # batch_variance for this case. - if not is_training: - outputs[1] = constant_op.constant(0.) - outputs[2] = constant_op.constant(0.) - loss = nn.l2_loss(outputs[0]) - gradients = gradient_ops.gradients(loss, [x1, scale, offset]) + with g: + x1 = array_ops.gather(x, i) + outputs = nn.fused_batch_norm( + x1, + scale, + offset, + mean=mean, + variance=variance, + epsilon=0.01, + data_format=data_format, + is_training=is_training) + outputs = list(outputs) + # We only test the first value of outputs when is_training is False. + # It looks like CPU and GPU have different outputs for batch_mean + # and batch_variance for this case. + if not is_training: + outputs[1] = constant_op.constant(0.) + outputs[2] = constant_op.constant(0.) + loss = nn.l2_loss(outputs[0]) + gradients = g.gradient(loss, [x1, scale, offset]) return outputs + gradients # pylint: enable=cell-var-from-loop @@ -850,16 +935,20 @@ class NNTest(PForTest): self._test_loop_fn(loop_fn, 3, loop_fn_dtypes=[dtypes.float32] * 6) def test_softmax_cross_entropy_with_logits(self): - logits = random_ops.random_uniform([3, 2, 4]) - labels = random_ops.random_uniform([3, 2, 4]) - labels /= math_ops.reduce_sum(labels, axis=[2], keepdims=True) + with backprop.GradientTape(persistent=True) as g: + logits = random_ops.random_uniform([3, 2, 4]) + g.watch(logits) + labels = random_ops.random_uniform([3, 2, 4]) + labels /= math_ops.reduce_sum(labels, axis=[2], keepdims=True) def loop_fn(i): - logits_i = array_ops.gather(logits, i) - labels_i = array_ops.gather(labels, i) - loss = nn.softmax_cross_entropy_with_logits( - labels=labels_i, logits=logits_i) - return loss, gradient_ops.gradients(math_ops.reduce_sum(loss), logits_i) + with g: + logits_i = array_ops.gather(logits, i) + labels_i = array_ops.gather(labels, i) + loss = nn.softmax_cross_entropy_with_logits( + labels=labels_i, logits=logits_i) + total_loss = math_ops.reduce_sum(loss) + return loss, g.gradient(total_loss, logits_i) self._test_loop_fn(loop_fn, 3, loop_fn_dtypes=[dtypes.float32] * 2) @@ -1278,13 +1367,12 @@ class ControlFlowTest(PForTest): pfor_out, pfor_out_grad = pfor_control_flow_ops.pfor(loop_fn, 4) # Note that tf.while_loop does not work in the setup above. So we manually # construct the equivalent computation of the above loops here. - real_out = math_ops.reduce_sum(inp, reduction_indices=[0]) - real_out = math_ops.reduce_prod(real_out, reduction_indices=[1]) + real_out = math_ops.reduce_sum(inp, axis=[0]) + real_out = math_ops.reduce_prod(real_out, axis=[1]) # Note that gradients of real_out will accumulate the gradients across the # output value. Hence we do the same aggregation on pfor_out_grad. real_out_grad = gradient_ops.gradients(real_out, inp)[0] - sum_pfor_out_grad = math_ops.reduce_sum( - pfor_out_grad, reduction_indices=[0]) + sum_pfor_out_grad = math_ops.reduce_sum(pfor_out_grad, axis=[0]) with session.Session() as sess: v1, v2, v1_grad, v2_grad = sess.run( diff --git a/tensorflow/python/ops/parallel_for/gradients.py b/tensorflow/python/ops/parallel_for/gradients.py index 1f026b3660..3ba1bde347 100644 --- a/tensorflow/python/ops/parallel_for/gradients.py +++ b/tensorflow/python/ops/parallel_for/gradients.py @@ -25,7 +25,7 @@ from tensorflow.python.ops.parallel_for import control_flow_ops from tensorflow.python.util import nest -def jacobian(output, inputs, use_pfor=True): +def jacobian(output, inputs, use_pfor=True, parallel_iterations=None): """Computes jacobian of `output` w.r.t. `inputs`. Args: @@ -33,6 +33,8 @@ def jacobian(output, inputs, use_pfor=True): inputs: A tensor or a nested structure of tensor objects. use_pfor: If true, uses pfor for computing the jacobian. Else uses tf.while_loop. + parallel_iterations: A knob to control how many iterations and dispatched in + parallel. This knob can be used to control the total memory usage. Returns: A tensor or a nested strucutre of tensors with the same structure as @@ -56,10 +58,14 @@ def jacobian(output, inputs, use_pfor=True): output_size = array_ops.shape(output)[0] if use_pfor: - pfor_outputs = control_flow_ops.pfor(loop_fn, output_size) + pfor_outputs = control_flow_ops.pfor( + loop_fn, output_size, parallel_iterations=parallel_iterations) else: pfor_outputs = control_flow_ops.for_loop( - loop_fn, [output.dtype] * len(flat_inputs), output_size) + loop_fn, + [output.dtype] * len(flat_inputs), + output_size, + parallel_iterations=parallel_iterations) for i, out in enumerate(pfor_outputs): if out is not None: @@ -72,7 +78,7 @@ def jacobian(output, inputs, use_pfor=True): return nest.pack_sequence_as(inputs, pfor_outputs) -def batch_jacobian(output, inp, use_pfor=True): +def batch_jacobian(output, inp, use_pfor=True, parallel_iterations=None): """Computes and stacks jacobians of `output[i,...]` w.r.t. `input[i,...]`. e.g. @@ -87,6 +93,8 @@ def batch_jacobian(output, inp, use_pfor=True): inp: A tensor with shape [b, x1, ..., x_m] use_pfor: If true, uses pfor for computing the Jacobian. Else uses a tf.while_loop. + parallel_iterations: A knob to control how many iterations and dispatched in + parallel. This knob can be used to control the total memory usage. Returns: A tensor `t` with shape [b, y_1, ..., y_n, x1, ..., x_m] where `t[i, ...]` @@ -118,10 +126,13 @@ def batch_jacobian(output, inp, use_pfor=True): return gradient_ops.gradients(y, inp)[0] if use_pfor: - pfor_output = control_flow_ops.pfor(loop_fn, output_row_size) + pfor_output = control_flow_ops.pfor(loop_fn, output_row_size, + parallel_iterations=parallel_iterations) else: - pfor_output = control_flow_ops.for_loop(loop_fn, output.dtype, - output_row_size) + pfor_output = control_flow_ops.for_loop( + loop_fn, output.dtype, + output_row_size, + parallel_iterations=parallel_iterations) if pfor_output is None: return None pfor_output = array_ops.reshape(pfor_output, diff --git a/tensorflow/python/ops/parallel_for/gradients_test.py b/tensorflow/python/ops/parallel_for/gradients_test.py index 5a058bae82..4342833e3e 100644 --- a/tensorflow/python/ops/parallel_for/gradients_test.py +++ b/tensorflow/python/ops/parallel_for/gradients_test.py @@ -416,6 +416,12 @@ class GradientsTest(test.TestCase): self.assertAllClose(ans, pfor_value) self.assertAllClose(ans, while_value) + def test_jacobian_parallel_iterations(self): + x = constant_op.constant([[1., 2], [3, 4]]) + y = math_ops.matmul(x, x) + self.assertAllClose(gradients.jacobian(y, x, parallel_iterations=2), + gradients.jacobian(y, x, parallel_iterations=3)) + def test_batch_jacobian_bad_shapes(self): x = random_ops.random_uniform([2, 2]) y = random_ops.random_uniform([3, 2]) @@ -459,6 +465,13 @@ class GradientsTest(test.TestCase): self.assertAllClose(ans, pfor_value) self.assertAllClose(ans, while_value) + def test_batch_jacobian_parallel_iterations(self): + x = constant_op.constant([[1., 2], [3, 4]]) + w = constant_op.constant([[1., 2, 3, 4], [5, 6, 7, 8]]) + y = math_ops.matmul(x, w) + self.assertAllClose(gradients.batch_jacobian(y, x, parallel_iterations=2), + gradients.batch_jacobian(y, x, parallel_iterations=3)) + def test_fc_batch_jacobian(self): pfor_jacobian, while_jacobian = create_fc_batch_jacobian(8, 4, 2) self.run_and_assert_equal(pfor_jacobian, while_jacobian) @@ -471,8 +484,8 @@ class GradientsTest(test.TestCase): pfor_jacobian, while_gradients = create_dynamic_lstm_batch_jacobian(8, 4, 3) with session.Session() as sess: init = variables.global_variables_initializer() - sess.run(init) - pfor = sess.run(pfor_jacobian) + self.evaluate(init) + pfor = self.evaluate(pfor_jacobian) for i in range(4): while_i = sess.run(while_gradients[i]) self.assertAllClose(while_i, pfor[:, i, ...]) @@ -547,11 +560,11 @@ class GradientsBenchmarks(test.Benchmark): sess = session.Session() with sess: init = variables.global_variables_initializer() - sess.run(init) - sess.run(targets) + self.evaluate(init) + self.evaluate(targets) begin = time.time() for _ in range(iters): - sess.run(targets) + self.evaluate(targets) end = time.time() avg_time_ms = 1000 * (end - begin) / iters self.report_benchmark(iters=iters, wall_time=avg_time_ms, name=name) diff --git a/tensorflow/python/ops/parallel_for/pfor.py b/tensorflow/python/ops/parallel_for/pfor.py index e6f140a941..a22c1126c9 100644 --- a/tensorflow/python/ops/parallel_for/pfor.py +++ b/tensorflow/python/ops/parallel_for/pfor.py @@ -1152,9 +1152,8 @@ class PFor(object): continue converted_inputs = [self._conversion_map[inp] for inp in y_op.inputs] - some_input_converted = any( - [self._was_converted(x) for x in y_op.inputs]) - some_input_stacked = any([x.is_stacked for x in converted_inputs]) + some_input_converted = any(self._was_converted(x) for x in y_op.inputs) + some_input_stacked = any(x.is_stacked for x in converted_inputs) converted_control_ops = set() some_control_input_converted = False @@ -1198,7 +1197,7 @@ class PFor(object): # All inputs are unstacked or uncoverted but some control inputs are # converted. # TODO(rachelim): Handle the case where some inputs are sparsely - # stacked (i.e. any([x.is_sparse_stacked for x in converted_inputs])) + # stacked (i.e. any(x.is_sparse_stacked for x in converted_inputs)) new_op = _create_op(y_op.type, [x.t for x in converted_inputs], [x.dtype for x in y_op.outputs], y_op.node_def.attr) @@ -1303,7 +1302,10 @@ def _inputs_with_flattening(pfor_input, input_indices): @RegisterPForWithArgs("Conv2D", dims=[0]) @RegisterPForWithArgs("AvgPool", dims=[0]) @RegisterPForWithArgs("MaxPool", dims=[0]) +@RegisterPForWithArgs("MaxPool3D", dims=[0]) +@RegisterPForWithArgs("MaxPool3DGrad", dims=[0, 1, 2]) @RegisterPForWithArgs("MaxPoolGrad", dims=[0, 1, 2]) +@RegisterPForWithArgs("MaxPool3DGradGrad", dims=[0, 1, 2]) @RegisterPForWithArgs("MaxPoolGradGrad", dims=[0, 1, 2]) @RegisterPForWithArgs("SoftmaxCrossEntropyWithLogits", dims=[0, 1]) def _convert_flatten_batch(pfor_input, op_type, dims): diff --git a/tensorflow/python/ops/parsing_ops.py b/tensorflow/python/ops/parsing_ops.py index 484caf0179..a84af6c5cf 100644 --- a/tensorflow/python/ops/parsing_ops.py +++ b/tensorflow/python/ops/parsing_ops.py @@ -363,7 +363,7 @@ def _prepend_none_dimension(features): return features -@tf_export("io.parse_example", v1=["io.parse_example", "parse_example"]) +@tf_export(v1=["io.parse_example", "parse_example"]) def parse_example(serialized, features, name=None, example_names=None): # pylint: disable=line-too-long """Parses `Example` protos into a `dict` of tensors. @@ -574,6 +574,223 @@ def parse_example(serialized, features, name=None, example_names=None): Returns: A `dict` mapping feature keys to `Tensor` and `SparseTensor` values. + Raises: + ValueError: if any feature is invalid. + """ + return parse_example_v2(serialized, features, example_names, name) + + +@tf_export("io.parse_example", v1=[]) +def parse_example_v2(serialized, features, example_names=None, name=None): + # pylint: disable=line-too-long + """Parses `Example` protos into a `dict` of tensors. + + Parses a number of serialized [`Example`](https://www.tensorflow.org/code/tensorflow/core/example/example.proto) + protos given in `serialized`. We refer to `serialized` as a batch with + `batch_size` many entries of individual `Example` protos. + + `example_names` may contain descriptive names for the corresponding serialized + protos. These may be useful for debugging purposes, but they have no effect on + the output. If not `None`, `example_names` must be the same length as + `serialized`. + + This op parses serialized examples into a dictionary mapping keys to `Tensor` + and `SparseTensor` objects. `features` is a dict from keys to `VarLenFeature`, + `SparseFeature`, and `FixedLenFeature` objects. Each `VarLenFeature` + and `SparseFeature` is mapped to a `SparseTensor`, and each + `FixedLenFeature` is mapped to a `Tensor`. + + Each `VarLenFeature` maps to a `SparseTensor` of the specified type + representing a ragged matrix. Its indices are `[batch, index]` where `batch` + identifies the example in `serialized`, and `index` is the value's index in + the list of values associated with that feature and example. + + Each `SparseFeature` maps to a `SparseTensor` of the specified type + representing a Tensor of `dense_shape` `[batch_size] + SparseFeature.size`. + Its `values` come from the feature in the examples with key `value_key`. + A `values[i]` comes from a position `k` in the feature of an example at batch + entry `batch`. This positional information is recorded in `indices[i]` as + `[batch, index_0, index_1, ...]` where `index_j` is the `k-th` value of + the feature in the example at with key `SparseFeature.index_key[j]`. + In other words, we split the indices (except the first index indicating the + batch entry) of a `SparseTensor` by dimension into different features of the + `Example`. Due to its complexity a `VarLenFeature` should be preferred over a + `SparseFeature` whenever possible. + + Each `FixedLenFeature` `df` maps to a `Tensor` of the specified type (or + `tf.float32` if not specified) and shape `(serialized.size(),) + df.shape`. + + `FixedLenFeature` entries with a `default_value` are optional. With no default + value, we will fail if that `Feature` is missing from any example in + `serialized`. + + Each `FixedLenSequenceFeature` `df` maps to a `Tensor` of the specified type + (or `tf.float32` if not specified) and shape + `(serialized.size(), None) + df.shape`. + All examples in `serialized` will be padded with `default_value` along the + second dimension. + + Examples: + + For example, if one expects a `tf.float32` `VarLenFeature` `ft` and three + serialized `Example`s are provided: + + ``` + serialized = [ + features + { feature { key: "ft" value { float_list { value: [1.0, 2.0] } } } }, + features + { feature []}, + features + { feature { key: "ft" value { float_list { value: [3.0] } } } + ] + ``` + + then the output will look like: + + ```python + {"ft": SparseTensor(indices=[[0, 0], [0, 1], [2, 0]], + values=[1.0, 2.0, 3.0], + dense_shape=(3, 2)) } + ``` + + If instead a `FixedLenSequenceFeature` with `default_value = -1.0` and + `shape=[]` is used then the output will look like: + + ```python + {"ft": [[1.0, 2.0], [3.0, -1.0]]} + ``` + + Given two `Example` input protos in `serialized`: + + ``` + [ + features { + feature { key: "kw" value { bytes_list { value: [ "knit", "big" ] } } } + feature { key: "gps" value { float_list { value: [] } } } + }, + features { + feature { key: "kw" value { bytes_list { value: [ "emmy" ] } } } + feature { key: "dank" value { int64_list { value: [ 42 ] } } } + feature { key: "gps" value { } } + } + ] + ``` + + And arguments + + ``` + example_names: ["input0", "input1"], + features: { + "kw": VarLenFeature(tf.string), + "dank": VarLenFeature(tf.int64), + "gps": VarLenFeature(tf.float32), + } + ``` + + Then the output is a dictionary: + + ```python + { + "kw": SparseTensor( + indices=[[0, 0], [0, 1], [1, 0]], + values=["knit", "big", "emmy"] + dense_shape=[2, 2]), + "dank": SparseTensor( + indices=[[1, 0]], + values=[42], + dense_shape=[2, 1]), + "gps": SparseTensor( + indices=[], + values=[], + dense_shape=[2, 0]), + } + ``` + + For dense results in two serialized `Example`s: + + ``` + [ + features { + feature { key: "age" value { int64_list { value: [ 0 ] } } } + feature { key: "gender" value { bytes_list { value: [ "f" ] } } } + }, + features { + feature { key: "age" value { int64_list { value: [] } } } + feature { key: "gender" value { bytes_list { value: [ "f" ] } } } + } + ] + ``` + + We can use arguments: + + ``` + example_names: ["input0", "input1"], + features: { + "age": FixedLenFeature([], dtype=tf.int64, default_value=-1), + "gender": FixedLenFeature([], dtype=tf.string), + } + ``` + + And the expected output is: + + ```python + { + "age": [[0], [-1]], + "gender": [["f"], ["f"]], + } + ``` + + An alternative to `VarLenFeature` to obtain a `SparseTensor` is + `SparseFeature`. For example, given two `Example` input protos in + `serialized`: + + ``` + [ + features { + feature { key: "val" value { float_list { value: [ 0.5, -1.0 ] } } } + feature { key: "ix" value { int64_list { value: [ 3, 20 ] } } } + }, + features { + feature { key: "val" value { float_list { value: [ 0.0 ] } } } + feature { key: "ix" value { int64_list { value: [ 42 ] } } } + } + ] + ``` + + And arguments + + ``` + example_names: ["input0", "input1"], + features: { + "sparse": SparseFeature( + index_key="ix", value_key="val", dtype=tf.float32, size=100), + } + ``` + + Then the output is a dictionary: + + ```python + { + "sparse": SparseTensor( + indices=[[0, 3], [0, 20], [1, 42]], + values=[0.5, -1.0, 0.0] + dense_shape=[2, 100]), + } + ``` + + Args: + serialized: A vector (1-D Tensor) of strings, a batch of binary + serialized `Example` protos. + features: A `dict` mapping feature keys to `FixedLenFeature`, + `VarLenFeature`, and `SparseFeature` values. + example_names: A vector (1-D Tensor) of strings (optional), the names of + the serialized protos in the batch. + name: A name for this operation (optional). + + Returns: + A `dict` mapping feature keys to `Tensor` and `SparseTensor` values. + Raises: ValueError: if any feature is invalid. """ @@ -764,8 +981,7 @@ def _process_raw_parameters(names, dense_defaults, sparse_keys, sparse_types, dense_shapes_as_proto, dense_shapes) -@tf_export("io.parse_single_example", - v1=["io.parse_single_example", "parse_single_example"]) +@tf_export(v1=["io.parse_single_example", "parse_single_example"]) def parse_single_example(serialized, features, name=None, example_names=None): """Parses a single `Example` proto. @@ -795,6 +1011,48 @@ def parse_single_example(serialized, features, name=None, example_names=None): Returns: A `dict` mapping feature keys to `Tensor` and `SparseTensor` values. + Raises: + ValueError: if any feature is invalid. + """ + return parse_single_example_v2_unoptimized( + serialized, features, example_names, name + ) + + +# TODO(b/70890287): Combine the implementation of this op and +# `parse_single_example_v2()` after 1/10/2018. +@tf_export("io.parse_single_example", v1=[]) +def parse_single_example_v2_unoptimized( + serialized, features, example_names=None, name=None + ): + """Parses a single `Example` proto. + + Similar to `parse_example`, except: + + For dense tensors, the returned `Tensor` is identical to the output of + `parse_example`, except there is no batch dimension, the output shape is the + same as the shape given in `dense_shape`. + + For `SparseTensor`s, the first (batch) column of the indices matrix is removed + (the indices matrix is a column vector), the values vector is unchanged, and + the first (`batch_size`) entry of the shape vector is removed (it is now a + single element vector). + + One might see performance advantages by batching `Example` protos with + `parse_example` instead of using this function directly. + + Args: + serialized: A scalar string Tensor, a single serialized Example. + See `_parse_single_example_raw` documentation for more details. + features: A `dict` mapping feature keys to `FixedLenFeature` or + `VarLenFeature` values. + example_names: (Optional) A scalar string Tensor, the associated name. + See `_parse_single_example_raw` documentation for more details. + name: A name for this operation (optional). + + Returns: + A `dict` mapping feature keys to `Tensor` and `SparseTensor` values. + Raises: ValueError: if any feature is invalid. """ @@ -1570,7 +1828,7 @@ def _parse_single_sequence_example_raw(serialized, # Swap `name` and `na_value` for backward compatibility. -@tf_export("io.decode_csv", v1=["io.decode_csv", "decode_csv"]) +@tf_export(v1=["io.decode_csv", "decode_csv"]) @deprecation.deprecated_endpoints("decode_csv") def decode_csv(records, record_defaults, @@ -1609,6 +1867,54 @@ def decode_csv(records, A list of `Tensor` objects. Has the same type as `record_defaults`. Each tensor will have the same shape as records. + Raises: + ValueError: If any of the arguments is malformed. + """ + return decode_csv_v2( + records, record_defaults, + field_delim, use_quote_delim, + na_value, select_cols, name + ) + + +@tf_export("io.decode_csv", v1=[]) +def decode_csv_v2(records, + record_defaults, + field_delim=",", + use_quote_delim=True, + na_value="", + select_cols=None, + name=None): + """Convert CSV records to tensors. Each column maps to one tensor. + + RFC 4180 format is expected for the CSV records. + (https://tools.ietf.org/html/rfc4180) + Note that we allow leading and trailing spaces with int or float field. + + Args: + records: A `Tensor` of type `string`. + Each string is a record/row in the csv and all records should have + the same format. + record_defaults: A list of `Tensor` objects with specific types. + Acceptable types are `float32`, `float64`, `int32`, `int64`, `string`. + One tensor per column of the input record, with either a + scalar default value for that column or an empty vector if the column is + required. + field_delim: An optional `string`. Defaults to `","`. + char delimiter to separate fields in a record. + use_quote_delim: An optional `bool`. Defaults to `True`. + If false, treats double quotation marks as regular + characters inside of the string fields (ignoring RFC 4180, Section 2, + Bullet 5). + na_value: Additional string to recognize as NA/NaN. + select_cols: Optional sorted list of column indices to select. If specified, + only this subset of columns will be parsed and returned. + name: A name for the operation (optional). + + Returns: + A list of `Tensor` objects. Has the same type as `record_defaults`. + Each tensor will have the same shape as records. + Raises: ValueError: If any of the arguments is malformed. """ diff --git a/tensorflow/python/ops/partitioned_variables.py b/tensorflow/python/ops/partitioned_variables.py index 7743b634e8..c1084c2559 100644 --- a/tensorflow/python/ops/partitioned_variables.py +++ b/tensorflow/python/ops/partitioned_variables.py @@ -57,7 +57,7 @@ import math from tensorflow.python.framework import dtypes from tensorflow.python.framework import tensor_shape from tensorflow.python.ops import variable_scope -from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.util import deprecation from tensorflow.python.util.tf_export import tf_export __all__ = [ @@ -68,7 +68,7 @@ __all__ = [ ] -@tf_export("variable_axis_size_partitioner") +@tf_export(v1=["variable_axis_size_partitioner"]) def variable_axis_size_partitioner( max_shard_bytes, axis=0, bytes_per_string_element=16, max_shards=None): """Get a partitioner for VariableScope to keep shards below `max_shard_bytes`. @@ -96,7 +96,7 @@ def variable_axis_size_partitioner( Returns: A partition function usable as the `partitioner` argument to - `variable_scope`, `get_variable`, and `get_partitioned_variable_list`. + `variable_scope` and `get_variable`. Raises: ValueError: If any of the byte counts are non-positive. @@ -154,7 +154,7 @@ def variable_axis_size_partitioner( return _partitioner -@tf_export("min_max_variable_partitioner") +@tf_export(v1=["min_max_variable_partitioner"]) def min_max_variable_partitioner(max_partitions=1, axis=0, min_slice_size=256 << 10, bytes_per_string_element=16): @@ -175,7 +175,7 @@ def min_max_variable_partitioner(max_partitions=1, axis=0, Returns: A partition function usable as the `partitioner` argument to - `variable_scope`, `get_variable`, and `get_partitioned_variable_list`. + `variable_scope` and `get_variable`. """ def _partitioner(shape, dtype): @@ -218,7 +218,7 @@ def min_max_variable_partitioner(max_partitions=1, axis=0, return _partitioner -@tf_export("fixed_size_partitioner") +@tf_export(v1=["fixed_size_partitioner"]) def fixed_size_partitioner(num_shards, axis=0): """Partitioner to specify a fixed number of shards along given axis. @@ -228,7 +228,7 @@ def fixed_size_partitioner(num_shards, axis=0): Returns: A partition function usable as the `partitioner` argument to - `variable_scope`, `get_variable`, and `get_partitioned_variable_list`. + `variable_scope` and `get_variable`. """ def _partitioner(shape, **unused_args): partitions_list = [1] * len(shape) @@ -237,7 +237,10 @@ def fixed_size_partitioner(num_shards, axis=0): return _partitioner -@tf_export("create_partitioned_variables") +@tf_export(v1=["create_partitioned_variables"]) +@deprecation.deprecated( + date=None, + instructions="Use tf.get_variable with a partitioner set.") def create_partitioned_variables( shape, slicing, initializer, dtype=dtypes.float32, trainable=True, collections=None, name=None, reuse=None): @@ -282,11 +285,6 @@ def create_partitioned_variables( Raises: ValueError: If any of the arguments is malformed. """ - logging.warn( - "create_partitioned_variables is deprecated. Use " - "tf.get_variable with a partitioner set, or " - "tf.get_partitioned_variable_list, instead.") - if len(shape) != len(slicing): raise ValueError("The 'shape' and 'slicing' of a partitioned Variable " "must have the length: shape: %s, slicing: %s" % diff --git a/tensorflow/python/ops/quantized_conv_ops_test.py b/tensorflow/python/ops/quantized_conv_ops_test.py index f7fa264461..6b469a954f 100644 --- a/tensorflow/python/ops/quantized_conv_ops_test.py +++ b/tensorflow/python/ops/quantized_conv_ops_test.py @@ -73,7 +73,7 @@ class Conv2DTest(test.TestCase): max_input=x1_max, min_filter=x2_min, max_filter=x2_max) - value = sess.run(conv) + value = self.evaluate(conv) quantized_output = value[0] output_min = value[1] output_max = value[2] diff --git a/tensorflow/python/ops/quantized_ops_test.py b/tensorflow/python/ops/quantized_ops_test.py index 0f3b04e4ad..b81843d174 100644 --- a/tensorflow/python/ops/quantized_ops_test.py +++ b/tensorflow/python/ops/quantized_ops_test.py @@ -41,7 +41,7 @@ class QuantizedOpsTest(test.TestCase): x_min = 0.0 x_max = 255.0 op = array_ops.quantize(x, x_min, x_max, dtypes.quint8, mode="MIN_FIRST") - value = sess.run(op) + value = self.evaluate(op) self.assertArrayNear(expected_output, value.output, 0.1) def testDequantizeOp(self): @@ -52,7 +52,7 @@ class QuantizedOpsTest(test.TestCase): x_min = 0.0 x_max = 255.0 op = array_ops.dequantize(x, x_min, x_max, mode="MIN_FIRST") - value = sess.run(op) + value = self.evaluate(op) self.assertArrayNear(expected_output, value, 0.1) diff --git a/tensorflow/python/ops/ragged/BUILD b/tensorflow/python/ops/ragged/BUILD index 152c6dc841..e335c5cb6f 100644 --- a/tensorflow/python/ops/ragged/BUILD +++ b/tensorflow/python/ops/ragged/BUILD @@ -32,7 +32,9 @@ py_library( ":ragged_map_ops", ":ragged_math_ops", ":ragged_operators", + ":ragged_string_ops", ":ragged_tensor", + ":ragged_tensor_shape", ":ragged_tensor_value", ":ragged_util", ":segment_id_ops", @@ -155,6 +157,7 @@ py_library( deps = [ ":ragged_factory_ops", ":ragged_tensor", + ":ragged_tensor_shape", ":ragged_util", "//tensorflow/python:array_ops", "//tensorflow/python:clip_ops", @@ -178,6 +181,21 @@ py_library( ], ) +py_library( + name = "ragged_string_ops", + srcs = ["ragged_string_ops.py"], + srcs_version = "PY2AND3", + deps = [ + ":ragged_array_ops", + ":ragged_conversion_ops", + ":ragged_factory_ops", + ":ragged_tensor", + "//tensorflow/python:array_ops", + "//tensorflow/python:math_ops", + "//tensorflow/python:util", + ], +) + py_library( name = "ragged_tensor", srcs = ["ragged_tensor.py"], @@ -190,6 +208,25 @@ py_library( ], ) +py_library( + name = "ragged_tensor_shape", + srcs = ["ragged_tensor_shape.py"], + srcs_version = "PY2AND3", + deps = [ + ":ragged_array_ops", + ":ragged_conversion_ops", + ":ragged_factory_ops", + ":ragged_tensor", + ":ragged_util", + "//tensorflow/python:array_ops", + "//tensorflow/python:dtypes", + "//tensorflow/python:framework_ops", + "//tensorflow/python:math_ops", + "//tensorflow/python:tensor_shape", + "//tensorflow/python:tensor_util", + ], +) + py_library( name = "ragged_tensor_value", srcs = ["ragged_tensor_value.py"], @@ -207,6 +244,7 @@ py_library( "//tensorflow/python:dtypes", "//tensorflow/python:framework_ops", "//tensorflow/python:math_ops", + "//tensorflow/python:ragged_math_ops_gen", ], ) @@ -256,6 +294,9 @@ py_test( size = "medium", srcs = ["ragged_tensor_test.py"], srcs_version = "PY2AND3", + tags = [ + "no_windows", + ], deps = [ ":ragged", "//tensorflow/python:array_ops", @@ -407,6 +448,9 @@ py_test( name = "ragged_to_sparse_op_test", srcs = ["ragged_to_sparse_op_test.py"], srcs_version = "PY2AND3", + tags = [ + "no_windows", + ], deps = [ ":ragged", "//tensorflow/python:array_ops", @@ -513,6 +557,9 @@ py_test( name = "ragged_constant_value_op_test", srcs = ["ragged_constant_value_op_test.py"], srcs_version = "PY2AND3", + tags = [ + "no_windows", + ], deps = [ ":ragged", "//tensorflow/python:framework_test_lib", @@ -681,3 +728,15 @@ py_test( "@absl_py//absl/testing:parameterized", ], ) + +py_test( + name = "ragged_tensor_shape_test", + srcs = ["ragged_tensor_shape_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":ragged", + "//tensorflow/python:framework_test_lib", + "//tensorflow/python:platform_test", + "@absl_py//absl/testing:parameterized", + ], +) diff --git a/tensorflow/python/ops/ragged/__init__.py b/tensorflow/python/ops/ragged/__init__.py index 3a28848545..1b2a7be95f 100644 --- a/tensorflow/python/ops/ragged/__init__.py +++ b/tensorflow/python/ops/ragged/__init__.py @@ -143,6 +143,11 @@ The following operations are specific to ragged tensors: @@make_elementwise_op + +@@RaggedTensorDynamicShape +@@broadcast_to +@@broadcast_dynamic_shape + """ @@ -151,6 +156,7 @@ from __future__ import division from __future__ import print_function from tensorflow.python.ops.ragged import ragged_operators +from tensorflow.python.ops.ragged import ragged_string_ops from tensorflow.python.ops.ragged.ragged_array_ops import batch_gather from tensorflow.python.ops.ragged.ragged_array_ops import boolean_mask @@ -214,6 +220,10 @@ from tensorflow.python.ops.ragged.ragged_tensor import is_ragged from tensorflow.python.ops.ragged.ragged_tensor import RaggedTensor from tensorflow.python.ops.ragged.ragged_tensor import RaggedTensorType +from tensorflow.python.ops.ragged.ragged_tensor_shape import broadcast_dynamic_shape +from tensorflow.python.ops.ragged.ragged_tensor_shape import broadcast_to +from tensorflow.python.ops.ragged.ragged_tensor_shape import RaggedTensorDynamicShape + from tensorflow.python.ops.ragged.ragged_tensor_value import RaggedTensorValue from tensorflow.python.ops.ragged.segment_id_ops import row_splits_to_segment_ids diff --git a/tensorflow/python/ops/ragged/convert_to_tensor_or_ragged_tensor_op_test.py b/tensorflow/python/ops/ragged/convert_to_tensor_or_ragged_tensor_op_test.py index b43470dfa1..ef3464f243 100644 --- a/tensorflow/python/ops/ragged/convert_to_tensor_or_ragged_tensor_op_test.py +++ b/tensorflow/python/ops/ragged/convert_to_tensor_or_ragged_tensor_op_test.py @@ -90,6 +90,7 @@ class RaggedConvertToTensorOrRaggedTensorTest(test_util.TensorFlowTestCase, preferred_dtype=dtypes.string, expected_dtype=dtypes.int32), ]) + @test_util.run_deprecated_v1 def testConvertRaggedTensorValue(self, value, dtype=None, @@ -102,7 +103,7 @@ class RaggedConvertToTensorOrRaggedTensorTest(test_util.TensorFlowTestCase, self.assertEqual(value.ragged_rank, converted.ragged_rank) self.assertEqual(dtypes.as_dtype(expected_dtype), converted.dtype) with self.test_session(): - self.assertEqual(value.tolist(), converted.eval().tolist()) + self.assertEqual(value.tolist(), self.evaluate(converted).tolist()) @parameterized.parameters([ dict( @@ -145,6 +146,7 @@ class RaggedConvertToTensorOrRaggedTensorTest(test_util.TensorFlowTestCase, message=('Tensor conversion requested dtype string for ' 'Tensor with dtype int32')), ]) + @test_util.run_deprecated_v1 def testConvertTensorError(self, pylist, message, diff --git a/tensorflow/python/ops/ragged/ragged_array_ops.py b/tensorflow/python/ops/ragged/ragged_array_ops.py index 425f3957c3..603e39d1dc 100644 --- a/tensorflow/python/ops/ragged/ragged_array_ops.py +++ b/tensorflow/python/ops/ragged/ragged_array_ops.py @@ -225,6 +225,28 @@ def row_lengths(rt_input, axis=1, name=None): return array_ops.ones(shape[:axis], dtypes.int64) * shape[axis] +def nested_row_lengths(rt_input, name=None): + """Returns a tuple containing the row_lengths for all ragged dimensions. + + `nested_row_lengths(rt)` is a tuple containing the `row_lengths` tensors for + all ragged dimensions in `rt`, ordered from outermost to innermost. + + Args: + rt_input: A potentially ragged tensor. + name: A name prefix for the returned tensors (optional). + + Returns: + A `tuple` of 1-D `int64` `Tensors`. The length of the tuple is equal to + `rt_input.ragged_rank`. + """ + with ops.name_scope(name, 'RaggedNestedRowLengths', [rt_input]): + rt_nested_row_lengths = [] + while isinstance(rt_input, ragged_tensor.RaggedTensor): + rt_nested_row_lengths.append(row_lengths(rt_input)) + rt_input = rt_input.values + return tuple(rt_nested_row_lengths) + + #=============================================================================== # Bounding Shape #=============================================================================== @@ -451,8 +473,7 @@ def batch_gather(params, indices, name=None): adjusted_indices = math_ops.to_int64(indices) + adjustments return gather(params.values, adjusted_indices) else: - raise ValueError( - 'batch shape from indices does not match params shape') + raise ValueError('batch shape from indices does not match params shape') #=============================================================================== @@ -719,7 +740,7 @@ def boolean_mask(data, mask, keepdims=False, name=None): int_mask = ragged_functional_ops.map_inner_values( math_ops.cast, mask, dtype=dtypes.int64) masked_row_lengths = ragged_math_ops.reduce_sum(int_mask, axis=1) - splits.append(_lengths_to_splits(masked_row_lengths)) + splits.append(ragged_util.lengths_to_splits(masked_row_lengths)) mask = mask.values data = data.values @@ -741,7 +762,7 @@ def boolean_mask(data, mask, keepdims=False, name=None): # masks back to a splits tensor. lengths = row_lengths(data) masked_lengths = array_ops.boolean_mask(lengths, mask) - masked_splits = _lengths_to_splits(masked_lengths) + masked_splits = ragged_util.lengths_to_splits(masked_lengths) # Get the masked values: first get row ids corresponding to each # value, then use tf.gather to build a boolean mask that's false for @@ -977,7 +998,7 @@ def _ragged_stack_concat_axis_0(rt_inputs, stack_values): # If we are performing a stack operation, then add another splits. if stack_values: stack_lengths = array_ops.stack([nrows(rt) for rt in rt_inputs]) - stack_splits = _lengths_to_splits(stack_lengths) + stack_splits = ragged_util.lengths_to_splits(stack_lengths) concatenated_nested_splits.insert(0, stack_splits) return ragged_factory_ops.from_nested_row_splits(concatenated_inner_values, @@ -1131,7 +1152,8 @@ def _tile_ragged_values(rt_input, multiples, const_multiples=None): # Repeat each element in this ragged dimension `multiples[axis]` times. if const_multiples is None or const_multiples[axis] != 1: - inner_value_ids = _repeat_ranges(inner_value_ids, splits, multiples[axis]) + inner_value_ids = ragged_util.repeat_ranges(inner_value_ids, splits, + multiples[axis]) prev_splits = splits @@ -1172,6 +1194,17 @@ def _tile_ragged_splits(rt_input, multiples, const_multiples=None): ragged_rank = rt_input.ragged_rank nested_splits = rt_input.nested_row_splits + # projected_splits[src_axis, dst_axis] contains the split points that divide + # the rows from src_axis in the list of dst_axis values. E.g., + # projected_splits[i, i] = nested_splits[i], and + # projected_splits[i, i+1] = gather(nested_splits[i+1], nested_splits[i]). + projected_splits = [{i: nested_splits[i]} for i in range(ragged_rank)] + for src_axis in range(ragged_rank): + for dst_axis in range(src_axis + 1, ragged_rank - 1): + projected_splits[src_axis][dst_axis] = array_ops.gather( + nested_splits[dst_axis], + projected_splits[src_axis][dst_axis - 1]) + # For each ragged dimension: nested_splits[axis] -> result_splits[axis]. result_splits = [] for axis in range(ragged_rank): @@ -1188,16 +1221,16 @@ def _tile_ragged_splits(rt_input, multiples, const_multiples=None): repeats = 1 for d in range(axis - 1, -1, -1): if const_multiples is None or const_multiples[d + 1] != 1: - splits = nested_splits[d] * repeats - output_lengths = _repeat_ranges(output_lengths, splits, - multiples[d + 1]) + splits = projected_splits[d][axis - 1] * repeats + output_lengths = ragged_util.repeat_ranges(output_lengths, splits, + multiples[d + 1]) repeats *= multiples[d + 1] # Tile splits for the outermost (uniform) dimension. output_lengths = array_ops.tile(output_lengths, multiples[:1]) # Convert to splits. - result_splits.append(_lengths_to_splits(output_lengths)) + result_splits.append(ragged_util.lengths_to_splits(output_lengths)) return result_splits @@ -1425,11 +1458,6 @@ def _coordinate_where(condition): #=============================================================================== -def _lengths_to_splits(lengths): - """Returns splits corresponding to the given lengths.""" - return array_ops.concat([[0], math_ops.cumsum(lengths)], axis=0) - - def _increase_ragged_rank_to(rt_input, ragged_rank): """Adds ragged dimensions to `rt_input` so it has the desired ragged rank.""" if ragged_rank > 0: @@ -1449,45 +1477,3 @@ def _concat_ragged_splits(splits_list): pieces.append(splits[1:] + splits_offset) splits_offset += splits[-1] return array_ops.concat(pieces, axis=0) - - -def _repeat_ranges(params, splits, multiple): - """Repeats each range of `params` (as specified by `splits`) `multiple` times. - - Let the `i`th range of `params` be defined as - `params[splits[i]:splits[i + 1]]`. Then this function returns a tensor - containing range 0 repeated `multiple` times, followed by range 1 repeated - `multiple`, ..., followed by the last range repeated `multiple` times. - - Args: - params: The `Tensor` whose values should be repeated. - splits: A splits tensor indicating the ranges of `params` that should be - repeated. - multiple: The number of times each range should be repeated. - - Returns: - A `Tensor` with the same rank and type as `params`. - - #### Example: - ```python - >>> _repeat_ranges(['a', 'b', 'c'], [0, 2, 3], 3) - ['a', 'b', 'a', 'b', 'a', 'b', 'c', 'c', 'c'] - ``` - """ - # Repeat each split value `multiple` times. E.g., if `splits=[0 3 4]` and - # `multiples=3`, then `repeated_splits=[0 0 0 3 3 3 4 4 4]`. - repeated_splits = array_ops.tile( - array_ops.expand_dims(splits, axis=1), array_ops.stack([1, multiple])) - repeated_splits = array_ops.reshape(repeated_splits, [-1]) - - # Divide the splits into repeated starts & repeated limits. E.g., if - # `repeated_splits=[0 0 0 3 3 3 4 4 4]` then `repeated_starts=[0 0 0 3 3 3]` - # and `repeated_limits=[3 3 3 4 4 4]`. - n_splits = array_ops.shape(repeated_splits, out_type=dtypes.int64)[0] - repeated_starts = repeated_splits[:n_splits - multiple] - repeated_limits = repeated_splits[multiple:] - - # Get indices for each range from starts to limits, and use those to gather - # the values in the desired repetition pattern. - offsets = ragged_math_ops.range(repeated_starts, repeated_limits).values - return array_ops.gather(params, offsets) diff --git a/tensorflow/python/ops/ragged/ragged_batch_gather_op_test.py b/tensorflow/python/ops/ragged/ragged_batch_gather_op_test.py index 79a2ecd87a..d9d840500c 100644 --- a/tensorflow/python/ops/ragged/ragged_batch_gather_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_batch_gather_op_test.py @@ -135,6 +135,7 @@ class RaggedBatchGatherOpTest(test_util.TensorFlowTestCase, expected=ragged.constant_value( [[[[b'c', b'a'], [b'd', b'd']], [[b'f', b'e']]]], ragged_rank=2)), ]) + @test_util.run_deprecated_v1 def testRaggedBatchGather(self, descr, params, indices, expected): result = ragged.batch_gather(params, indices) self.assertEqual( @@ -144,6 +145,7 @@ class RaggedBatchGatherOpTest(test_util.TensorFlowTestCase, expected = expected.tolist() self.assertEqual(result.eval().tolist(), expected) + @test_util.run_deprecated_v1 def testRaggedBatchGatherUnknownRankError(self): params = [['a', 'b'], ['c', 'd']] indices = array_ops.placeholder(dtypes.int32, shape=None) @@ -186,6 +188,7 @@ class RaggedBatchGatherOpTest(test_util.TensorFlowTestCase, indices=[[[0]]], message='batch shape from indices does not match params shape'), ]) + @test_util.run_deprecated_v1 def testRaggedBatchGatherStaticError(self, params, indices, diff --git a/tensorflow/python/ops/ragged/ragged_boolean_mask_op_test.py b/tensorflow/python/ops/ragged/ragged_boolean_mask_op_test.py index b3279c1e84..d939d9d634 100644 --- a/tensorflow/python/ops/ragged/ragged_boolean_mask_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_boolean_mask_op_test.py @@ -298,6 +298,7 @@ class RaggedBooleanMaskOpTest(test_util.TensorFlowTestCase, keepdims=True, expected=ragged.constant_value([[[1], [4, 6]], [[7, 9], []]])), ]) # pyformat: disable + @test_util.run_deprecated_v1 def testBooleanMask(self, descr, data, mask, keepdims, expected): actual = ragged.boolean_mask(data, mask, keepdims=keepdims) self.assertEqual( @@ -307,6 +308,7 @@ class RaggedBooleanMaskOpTest(test_util.TensorFlowTestCase, expected = expected.tolist() self.assertEqual(actual.eval().tolist(), expected) + @test_util.run_deprecated_v1 def testErrors(self): self.assertRaisesRegexp(ValueError, r'mask\.shape\.ndims must be kown statically', diff --git a/tensorflow/python/ops/ragged/ragged_concat_op_test.py b/tensorflow/python/ops/ragged/ragged_concat_op_test.py index 6b1a602d04..3699f90f46 100644 --- a/tensorflow/python/ops/ragged/ragged_concat_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_concat_op_test.py @@ -41,6 +41,11 @@ class RaggedConcatOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): ] @parameterized.parameters( + dict( + descr='Two rank-2 inputs with empty value axis=1', + rt_inputs=([[]], [[]]), + axis=1, + expected=[[]]), dict( descr='Two rank-2 inputs (ragged_rank=1), axis=0', rt_inputs=( @@ -216,6 +221,7 @@ class RaggedConcatOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): axis=0, expected=[[b'a00', b'a01'], [], [b'a20', b'a21']]), ) # pyformat: disable + @test_util.run_deprecated_v1 def testRaggedConcat(self, descr, rt_inputs, @@ -261,6 +267,7 @@ class RaggedConcatOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): error=ValueError, message='Dimension 0 in both shapes must be equal'), ) + @test_util.run_deprecated_v1 def testStaticError(self, rt_inputs, axis, error, message, ragged_ranks=None): rt_inputs = self._rt_inputs_to_tensors(rt_inputs, ragged_ranks) self.assertRaisesRegexp(error, message, ragged.concat, rt_inputs, axis) @@ -273,6 +280,7 @@ class RaggedConcatOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): error=errors.InvalidArgumentError, message='Input tensors have incompatible shapes'), ]) + @test_util.run_deprecated_v1 def testRuntimeError(self, rt_inputs, axis, error, message, ragged_ranks=None): rt_inputs = [ @@ -282,6 +290,7 @@ class RaggedConcatOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): with self.test_session(): self.assertRaisesRegexp(error, message, concatenated.eval) + @test_util.run_deprecated_v1 def testNegativeAxisWithUnknownRankError(self): rt_inputs = [ array_ops.placeholder(dtypes.int64), @@ -291,6 +300,7 @@ class RaggedConcatOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): ValueError, r'axis may only be negative if ndims is statically known.', ragged.concat, rt_inputs, -1) + @test_util.run_deprecated_v1 def testSingleTensorInput(self): """Tests ragged_concat with a single tensor input. diff --git a/tensorflow/python/ops/ragged/ragged_const_op_test.py b/tensorflow/python/ops/ragged/ragged_const_op_test.py index 13f79c5729..2505b23912 100644 --- a/tensorflow/python/ops/ragged/ragged_const_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_const_op_test.py @@ -133,6 +133,7 @@ class RaggedConstOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): dict(pylist=[[b'a', b'b'], [b'c'], [b'd', b'e', b'f']], dtype=dtypes.string), ) + @test_util.run_deprecated_v1 def testRaggedConst(self, pylist, dtype=None, @@ -183,7 +184,7 @@ class RaggedConstOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertEqual(tuple(rt.shape.as_list()), expected_shape) with self.test_session(): - result = rt.eval() + result = self.evaluate(rt) if rt.shape.ndims > 0: self.assertEqual(result.tolist(), pylist) if expected_shape is not None: @@ -238,8 +239,8 @@ class RaggedConstOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): dict( pylist=[1, 2, 3], inner_shape=(1, 1), - exception=ValueError, - message='Too many elements provided.'), + exception=TypeError, + message='Expected Tensor\'s shape'), dict( pylist=[[[1, 2], [3, 4]], [[5, 6], [7, 8]]], inner_shape=(2, 2), @@ -258,6 +259,7 @@ class RaggedConstOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): exception=ValueError, message='inner values have inconsistent shape'), ) + @test_util.run_deprecated_v1 def testRaggedConstError(self, pylist, dtype=None, diff --git a/tensorflow/python/ops/ragged/ragged_conversion_ops.py b/tensorflow/python/ops/ragged/ragged_conversion_ops.py index 3ec246ccaf..83212e49cf 100644 --- a/tensorflow/python/ops/ragged/ragged_conversion_ops.py +++ b/tensorflow/python/ops/ragged/ragged_conversion_ops.py @@ -196,7 +196,7 @@ def to_tensor(rt_input, default_value=None, name=None): Args: rt_input: The input `RaggedTensor`. default_value: Value to set for indices not specified in `rt_input`. - Defaults to zero. `default_value.shape` must be equal to + Defaults to zero. `default_value` must be broadcastable to `rt_input.shape[rt_input.ragged_rank + 1:]`. name: A name prefix for the returned tensors (optional). @@ -210,6 +210,9 @@ def to_tensor(rt_input, default_value=None, name=None): rt_input, name='rt_input') if not ragged_tensor.is_ragged(rt_input): return rt_input # already dense + if default_value is not None: + default_value = ops.convert_to_tensor( + default_value, name='default_value', dtype=rt_input.dtype) # If ragged_rank > 1, then recursively convert the ragged values into a # `Tensor` before we proceed. @@ -217,6 +220,16 @@ def to_tensor(rt_input, default_value=None, name=None): if ragged_tensor.is_ragged(values): values = to_tensor(values, default_value) + # Tile the default value, if necessary. + if default_value is not None: + if values.shape.ndims is not None: + default_value.shape.with_rank_at_most(values.shape.ndims - 1) + if (values.shape.ndims is None or default_value.shape.ndims is None or + values.shape.ndims != default_value.shape.ndims + 1): + value_shape = array_ops.shape(values)[1:] + default_value = array_ops.broadcast_to(default_value, value_shape) + default_value.shape.assert_is_compatible_with(values.shape[1:]) + # Get the expected dense shape ([nrows, ncols] + value_shape). rt_row_lengths = [rt_input.row_splits[1:] - rt_input.row_splits[:-1]] nrows = array_ops.shape(rt_input.row_splits, out_type=dtypes.int64)[0] - 1 @@ -228,9 +241,6 @@ def to_tensor(rt_input, default_value=None, name=None): # Build a default value if none was supplied. if default_value is None: default_value = array_ops.zeros(value_shape, dtype=values.dtype) - else: - default_value = ops.convert_to_tensor( - default_value, name='default_value', dtype=values.dtype) default_value.shape.assert_is_compatible_with(values.shape[1:]) default_value.set_shape(values.shape[1:]) @@ -351,9 +361,14 @@ def from_sparse(st_input, name=None): st_input = sparse_tensor.convert_to_tensor_or_sparse_tensor( st_input, name='rt_input') - if (st_input.dense_shape.shape.ndims != 2 and - st_input.indices.shape.ndims is None or - st_input.indices.shape.dims[1].value != 2): + static_rank_from_dense_shape = ( + None if st_input.dense_shape.shape.ndims is None + else st_input.dense_shape.shape.dims[0].value) + static_rank_from_indices = ( + None if st_input.indices.shape.ndims is None + else st_input.indices.shape.dims[1].value) + + if static_rank_from_dense_shape != 2 and static_rank_from_indices != 2: raise ValueError('rank(st_input) must be 2') with ops.control_dependencies( diff --git a/tensorflow/python/ops/ragged/ragged_elementwise_ops.py b/tensorflow/python/ops/ragged/ragged_elementwise_ops.py index 23d0e8b5fc..59b7dd1661 100644 --- a/tensorflow/python/ops/ragged/ragged_elementwise_ops.py +++ b/tensorflow/python/ops/ragged/ragged_elementwise_ops.py @@ -28,7 +28,7 @@ from tensorflow.python.ops import parsing_ops from tensorflow.python.ops import string_ops from tensorflow.python.ops.ragged import ragged_factory_ops from tensorflow.python.ops.ragged import ragged_tensor -from tensorflow.python.ops.ragged import ragged_util +from tensorflow.python.ops.ragged import ragged_tensor_shape from tensorflow.python.util import tf_decorator from tensorflow.python.util import tf_export from tensorflow.python.util import tf_inspect @@ -209,28 +209,45 @@ def _broadcast_elementwise_args(elementwise_args): if not any(is_ragged): return elementwise_args, (), () - # Support limited broadcasting (namely, scalar + ragged). Full - # broadcasting support will be added later. - if all((ragged_tensor.is_ragged(t) or t.shape.ndims == 0) - for t in elementwise_args.values()): + # If we have a single ragged tensor plus a set of scalars, then we can + # rely on the underlying elementwise op to do broadcasting. + if (sum(is_ragged) == 1 and + all((ragged_tensor.is_ragged(t) or t.shape.ndims == 0) + for t in elementwise_args.values())): nested_splits_lists = [ t.nested_row_splits for t in elementwise_args.values() - if ragged_tensor.is_ragged(t) - ] - if len(nested_splits_lists) == 1: - checks = () - else: - if any(t.shape.ndims is None for t in elementwise_args.values()): - raise ValueError('Ragged elementwise ops require that rank (number ' - 'of dimensions) be statically known.') - if len(set(t.shape.ndims for t in elementwise_args.values())) != 1: - raise ValueError('Ragged elementwise ops do not support ' - 'broadcasting yet') - checks = ragged_util.assert_splits_match(nested_splits_lists) - return (elementwise_args, nested_splits_lists[0], checks) + if ragged_tensor.is_ragged(t)][0] + return elementwise_args, nested_splits_lists, () + else: - raise ValueError('Ragged elementwise ops do not support broadcasting yet') + # Get the shapes of all the elementwise arguments. + shapes = [ragged_tensor_shape.RaggedTensorDynamicShape.from_tensor(t) + for t in elementwise_args.values()] + + # Broadcast the shapes to all have the same rank (the max rank). + ranks = [t.shape.ndims for t in elementwise_args.values()] + if any(rank is None for rank in ranks): + raise ValueError('Unable to broadcast: unknown rank') + broadcast_rank = max(ranks) + shapes = [shape.broadcast_to_rank(broadcast_rank) for shape in shapes] + + # For each dimension, broadcast the shapes to be compatible. + for axis in range(broadcast_rank): + # For each i, broadcast shape[i+1] to be compatible with shape[i]; and + # then finally broadcast shape[0] to be compatible with shape[-1]. + for i in range(len(shapes)): + j = (i + 1) % len(shapes) + dim_size = shapes[i].dimension_size(axis) + shapes[j] = shapes[j].broadcast_dimension(axis, dim_size) + broadcast_shape = shapes[0] + + # Broadcast every elementwise arg to the shape that we calculated. + elementwise_args = dict([ + (key, ragged_tensor_shape.broadcast_to(t, broadcast_shape, False)) + for (key, t) in elementwise_args.items()]) + nested_splits_lists = list(elementwise_args.values())[0].nested_row_splits + return elementwise_args, nested_splits_lists, () # A list of symbols that should be exported in the "ragged" package. @@ -252,6 +269,10 @@ def _add_elementwise_ops_to_this_module(specs, verbose=False): op_name = canonical_name else: op_name = original_op.__name__ + + # Temporary hack (will be removed once dispatch is added for RaggedTensors): + if op_name == 'neg': op_name = 'negative' + if verbose: print('Adding ragged_elementwise_op: tf.ragged.%s (based on tf.%s)' % (op_name, canonical_name)) @@ -348,7 +369,7 @@ _TF_ELEMENTWISE_OPS = [ (string_ops.regex_replace, 'input'), (string_ops.string_join, '[inputs]'), (string_ops.string_strip, 'input'), - (string_ops.string_to_hash_bucket, 'string_tensor'), + (string_ops.string_to_hash_bucket, 'input'), (string_ops.string_to_hash_bucket_fast, 'input'), (string_ops.string_to_hash_bucket_strong, 'input'), (string_ops.substr, 'input'), @@ -365,3 +386,4 @@ _TF_ELEMENTWISE_OPS = [ (parsing_ops.string_to_number, 'string_tensor'), ] _add_elementwise_ops_to_this_module(_TF_ELEMENTWISE_OPS) + diff --git a/tensorflow/python/ops/ragged/ragged_elementwise_ops_test.py b/tensorflow/python/ops/ragged/ragged_elementwise_ops_test.py index 5dfa5cff45..305a96df9c 100644 --- a/tensorflow/python/ops/ragged/ragged_elementwise_ops_test.py +++ b/tensorflow/python/ops/ragged/ragged_elementwise_ops_test.py @@ -394,49 +394,43 @@ class RaggedElementwiseOpsTest(test_util.TensorFlowTestCase, result_flat_values = array_ops.reshape(result, [-1]) self.assertAllEqual(expected_flat_values, result_flat_values) + @test_util.run_deprecated_v1 def testUnknownRankError(self): x = ragged.constant([[1, 2], [3]]) y = ragged.from_row_splits( array_ops.placeholder_with_default([1, 2, 3], shape=None), x.row_splits) with self.assertRaisesRegexp( - ValueError, r'Ragged elementwise ops require that rank \(number ' - r'of dimensions\) be statically known.'): + ValueError, r'Unable to broadcast: unknown rank'): ragged.add(x, y) - def testBroadcastError1(self): - x = ragged.constant([[1, 2], [3]]) - y = [[12]] - with self.assertRaisesRegexp( - ValueError, 'Ragged elementwise ops do not support broadcasting yet'): - ragged.add(x, y) - - def testBroadcastError2(self): - x = ragged.constant([[[1, 2], [3, 4]], [[5]]], ragged_rank=2) - y = ragged.constant([[[8], [3]], [[2]]], ragged_rank=1) - with self.assertRaisesRegexp(ValueError, - 'Inputs must have identical ragged splits'): - ragged.add(x, y) - - def testBroadcastError3(self): - x = ragged.constant([[[1, 2], [3]], [[4, 5], [6]]], ragged_rank=2) - y = ragged.constant([[7, 8], [9]], ragged_rank=1) - with self.assertRaisesRegexp( - ValueError, 'Ragged elementwise ops do not support broadcasting yet'): - ragged.add(x, y) - - def testBroadcastError4(self): - x = ragged.constant([[[1]]]) - y = ragged.constant([[1]]) - with self.assertRaisesRegexp( - ValueError, 'Ragged elementwise ops do not support broadcasting yet'): - ragged.add(x, y) + @parameterized.parameters([ + dict( + x=ragged.constant_value([[1, 2], [3]]), + y=[[10]], + expected=[[11, 12], [13]]), + dict( + x=ragged.constant_value([[[1, 2], [3, 4]], [[5]]], ragged_rank=2), + y=ragged.constant_value([[[10], [20]], [[30]]], ragged_rank=1), + expected=[[[11, 12], [23, 24]], [[35]]]), + dict( + x=ragged.constant_value([[[1]]]), + y=ragged.constant_value([[1]]), + expected=[[[2]]]), + ]) + def testBroadcastAdd(self, x, y, expected): + x = ragged.convert_to_tensor_or_ragged_tensor(x, dtype=dtypes.int32) + y = ragged.convert_to_tensor_or_ragged_tensor(y, dtype=dtypes.int32) + result = x + y + with self.cached_session(): + self.assertEqual(result.eval().tolist(), expected) def testShapeMismatch(self): x = ragged.constant([[1, 2, 3], [4, 5]]) y = ragged.constant([[1, 2, 3], [4, 5, 6]]) with self.assertRaisesRegexp(errors.InvalidArgumentError, - 'Inputs must have identical ragged splits'): - ragged.add(x, y) + 'Incompatible shapes'): + with self.cached_session(): + ragged.add(x, y).eval() def testDocstring(self): self.assertRegexpMatches( diff --git a/tensorflow/python/ops/ragged/ragged_expand_dims_op_test.py b/tensorflow/python/ops/ragged/ragged_expand_dims_op_test.py index 0c4fd458c2..3ff66973b6 100644 --- a/tensorflow/python/ops/ragged/ragged_expand_dims_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_expand_dims_op_test.py @@ -105,6 +105,7 @@ class RaggedExpandDimsOpTest(test_util.TensorFlowTestCase, expected=EXAMPLE4D_EXPAND_AXIS[4], expected_shape=[3, None, None, 2, 1]), ]) # pyformat: disable + @test_util.run_deprecated_v1 def testRaggedExpandDims(self, rt_input, axis, diff --git a/tensorflow/python/ops/ragged/ragged_factory_ops.py b/tensorflow/python/ops/ragged/ragged_factory_ops.py index de3a2d5b10..d1f301bc58 100644 --- a/tensorflow/python/ops/ragged/ragged_factory_ops.py +++ b/tensorflow/python/ops/ragged/ragged_factory_ops.py @@ -676,3 +676,33 @@ def from_nested_row_splits(inner_values, nested_row_splits, name=None): for splits in reversed(nested_row_splits): result = from_row_splits(result, splits) return result + + +def from_nested_row_lengths(inner_values, nested_row_lengths, name=None): + """Creates a `RaggedTensor` from a nested list of `row_lengths` tensors. + + Equivalent to: + + ```python + result = inner_values + for row_lengths in reversed(nested_row_lengths): + result = from_row_lengths(result, row_lengths) + ``` + + Args: + inner_values: A potentially ragged tensor. + nested_row_lengths: A list of 1-D int64 tensors. The `i`th tensor is used + as the `row_lengths` for the `i`th ragged dimension. + name: A name prefix for the RaggedTensor (optional). + + Returns: + A `RaggedTensor` (or `inner_values` if `nested_row_lengths` is empty). + """ + if isinstance(nested_row_lengths, ops.Tensor): + raise TypeError('nested_row_lengths must be a list of Tensors') + with ops.name_scope(name, 'RaggedFromNestedRowlengths', + [inner_values] + list(nested_row_lengths)): + result = inner_values + for lengths in reversed(nested_row_lengths): + result = from_row_lengths(result, lengths) + return result diff --git a/tensorflow/python/ops/ragged/ragged_from_sparse_op_test.py b/tensorflow/python/ops/ragged/ragged_from_sparse_op_test.py index ff19ddedeb..3c0db9e8fb 100644 --- a/tensorflow/python/ops/ragged/ragged_from_sparse_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_from_sparse_op_test.py @@ -29,6 +29,7 @@ from tensorflow.python.platform import googletest class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testDocStringExample(self): st = sparse_tensor.SparseTensor( indices=[[0, 0], [0, 1], [0, 2], [1, 0], [3, 0]], @@ -39,6 +40,7 @@ class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): with self.test_session(): self.assertEqual(rt.eval().tolist(), [[1, 2, 3], [4], [], [5]]) + @test_util.run_deprecated_v1 def testEmpty(self): st = sparse_tensor.SparseTensor( indices=array_ops.zeros([0, 2], dtype=dtypes.int64), @@ -49,6 +51,7 @@ class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): with self.test_session(): self.assertEqual(rt.eval().tolist(), [[], [], [], []]) + @test_util.run_deprecated_v1 def testBadSparseTensorRank(self): st1 = sparse_tensor.SparseTensor(indices=[[0]], values=[0], dense_shape=[3]) st2 = sparse_tensor.SparseTensor( @@ -64,6 +67,22 @@ class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): self.assertRaisesRegexp(ValueError, r'rank\(st_input\) must be 2', ragged.from_sparse, st3) + @test_util.run_deprecated_v1 + def testGoodPartialSparseTensorRank(self): + st1 = sparse_tensor.SparseTensor( + indices=[[0, 0]], + values=[0], + dense_shape=array_ops.placeholder(dtypes.int64)) + st2 = sparse_tensor.SparseTensor( + indices=array_ops.placeholder(dtypes.int64), + values=[0], + dense_shape=[4, 3]) + + # Shouldn't throw ValueError + ragged.from_sparse(st1) + ragged.from_sparse(st2) + + @test_util.run_deprecated_v1 def testNonRaggedSparseTensor(self): # "index_suffix" means the value of the innermost dimension of the index # (i.e., indices[i][-1]). diff --git a/tensorflow/python/ops/ragged/ragged_from_tensor_op_test.py b/tensorflow/python/ops/ragged/ragged_from_tensor_op_test.py index eb237f4c95..1d8a00cc18 100644 --- a/tensorflow/python/ops/ragged/ragged_from_tensor_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_from_tensor_op_test.py @@ -31,6 +31,7 @@ from tensorflow.python.platform import googletest class RaggedFromTensorOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): + @test_util.run_deprecated_v1 def testDocStringExamples(self): # The examples from ragged.from_tensor.__doc__. dt = constant_op.constant([[5, 7, 0], [0, 3, 0], [6, 0, 0]]) @@ -262,6 +263,7 @@ class RaggedFromTensorOpTest(test_util.TensorFlowTestCase, [[[5, 6], [7]], [[0, 8], []]]] }, ) # pyformat: disable + @test_util.run_deprecated_v1 def testRaggedFromTensor(self, tensor, expected, @@ -278,6 +280,7 @@ class RaggedFromTensorOpTest(test_util.TensorFlowTestCase, with self.test_session(): self.assertEqual(rt.eval().tolist(), expected) + @test_util.run_deprecated_v1 def testHighDimensions(self): # Use distinct prime numbers for all dimension shapes in this test, so # we can see any errors that are caused by mixing up dimension sizes. @@ -291,7 +294,7 @@ class RaggedFromTensorOpTest(test_util.TensorFlowTestCase, dt.shape.is_compatible_with(rt.shape), '%s is incompatible with %s' % (dt.shape, rt.shape)) with self.test_session(): - self.assertEqual(rt.eval().tolist(), dt.eval().tolist()) + self.assertEqual(rt.eval().tolist(), self.evaluate(dt).tolist()) @parameterized.parameters( # With no padding or lengths @@ -395,6 +398,7 @@ class RaggedFromTensorOpTest(test_util.TensorFlowTestCase, 'expected': [[], []] }, ) + @test_util.run_deprecated_v1 def testEmpty(self, dt_shape, expected, lengths=None, padding=None): dt = array_ops.zeros(dt_shape) rt = ragged.from_tensor(dt, lengths, padding) @@ -447,6 +451,7 @@ class RaggedFromTensorOpTest(test_util.TensorFlowTestCase, 'error': (ValueError, r'ragged_rank must be greater than 0; got -1') }, ) + @test_util.run_deprecated_v1 def testErrors(self, tensor, lengths=None, diff --git a/tensorflow/python/ops/ragged/ragged_gather_nd_op_test.py b/tensorflow/python/ops/ragged/ragged_gather_nd_op_test.py index dcf1feaa69..62c6819374 100644 --- a/tensorflow/python/ops/ragged/ragged_gather_nd_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_gather_nd_op_test.py @@ -183,6 +183,7 @@ class RaggedGatherNdOpTest(test_util.TensorFlowTestCase, indices=[[0, 0, 1], [0, 0, 0], [0, 1, 0]], expected=[[b'c', b'd'], [b'a', b'b'], [b'e', b'f']]), ]) # pyformat: disable + @test_util.run_deprecated_v1 def testRaggedGatherNd(self, descr, params, indices, expected): result = ragged.gather_nd(params, indices) self.assertEqual( @@ -190,8 +191,9 @@ class RaggedGatherNdOpTest(test_util.TensorFlowTestCase, with self.test_session() as sess: if hasattr(expected, 'tolist'): expected = expected.tolist() - self.assertEqual(sess.run(result).tolist(), expected) + self.assertEqual(self.evaluate(result).tolist(), expected) + @test_util.run_deprecated_v1 def testRaggedGatherNdUnknownRankError(self): params = ragged.constant([['a', 'b'], ['c', 'd']]) indices1 = array_ops.placeholder(dtypes.int32, shape=None) @@ -219,6 +221,7 @@ class RaggedGatherNdOpTest(test_util.TensorFlowTestCase, indices=ragged.constant([[0]]), message='The innermost dimension of indices may not be ragged'), ]) + @test_util.run_deprecated_v1 def testRaggedGatherNdStaticError(self, params, indices, diff --git a/tensorflow/python/ops/ragged/ragged_gather_op_test.py b/tensorflow/python/ops/ragged/ragged_gather_op_test.py index bb52d05c32..76c90cdfee 100644 --- a/tensorflow/python/ops/ragged/ragged_gather_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_gather_op_test.py @@ -30,6 +30,7 @@ from tensorflow.python.platform import googletest class RaggedTensorOpsTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testDocStringExamples(self): params = constant_op.constant(['a', 'b', 'c', 'd', 'e']) indices = constant_op.constant([3, 1, 2, 1, 0]) @@ -46,6 +47,7 @@ class RaggedTensorOpsTest(test_util.TensorFlowTestCase): ragged.gather(ragged_params, ragged_indices).eval().tolist(), [[[b'e'], [b'd'], []], [[b'd']], [], [[b'a', b'b', b'c']]]) + @test_util.run_deprecated_v1 def testTensorParamsAndTensorIndices(self): params = ['a', 'b', 'c', 'd', 'e'] indices = [2, 0, 2, 1] @@ -55,6 +57,7 @@ class RaggedTensorOpsTest(test_util.TensorFlowTestCase): [b'c', b'a', b'c', b'b']) self.assertEqual(type(ragged.gather(params, indices)), ops.Tensor) + @test_util.run_deprecated_v1 def testRaggedParamsAndTensorIndices(self): params = ragged.constant([['a', 'b'], ['c', 'd', 'e'], ['f'], [], ['g']]) indices = [2, 0, 2, 1] @@ -63,6 +66,7 @@ class RaggedTensorOpsTest(test_util.TensorFlowTestCase): ragged.gather(params, indices).eval().tolist(), [[b'f'], [b'a', b'b'], [b'f'], [b'c', b'd', b'e']]) + @test_util.run_deprecated_v1 def testTensorParamsAndRaggedIndices(self): params = ['a', 'b', 'c', 'd', 'e'] indices = ragged.constant([[2, 1], [1, 2, 0], [3]]) @@ -71,6 +75,7 @@ class RaggedTensorOpsTest(test_util.TensorFlowTestCase): ragged.gather(params, indices).eval().tolist(), [[b'c', b'b'], [b'b', b'c', b'a'], [b'd']]) + @test_util.run_deprecated_v1 def testRaggedParamsAndRaggedIndices(self): params = ragged.constant([['a', 'b'], ['c', 'd', 'e'], ['f'], [], ['g']]) indices = ragged.constant([[2, 1], [1, 2, 0], [3]]) @@ -82,6 +87,7 @@ class RaggedTensorOpsTest(test_util.TensorFlowTestCase): [[]]] # [p[3] ]] ) # pyformat: disable + @test_util.run_deprecated_v1 def testRaggedParamsAndScalarIndices(self): params = ragged.constant([['a', 'b'], ['c', 'd', 'e'], ['f'], [], ['g']]) indices = 1 @@ -89,6 +95,7 @@ class RaggedTensorOpsTest(test_util.TensorFlowTestCase): self.assertEqual( ragged.gather(params, indices).eval().tolist(), [b'c', b'd', b'e']) + @test_util.run_deprecated_v1 def test3DRaggedParamsAnd2DTensorIndices(self): params = ragged.constant([[['a', 'b'], []], [['c', 'd'], ['e'], ['f']], [['g']]]) @@ -101,6 +108,7 @@ class RaggedTensorOpsTest(test_util.TensorFlowTestCase): [[[b'g']], [[b'g']]]] # [p2, p2]] ) # pyformat: disable + @test_util.run_deprecated_v1 def testTensorParamsAnd4DRaggedIndices(self): indices = ragged.constant( [[[[3, 4], [0, 6]], []], [[[2, 1], [1, 0]], [[2, 5]], [[2, 3]]], @@ -115,6 +123,7 @@ class RaggedTensorOpsTest(test_util.TensorFlowTestCase): [[[b'c', b'b'], [b'b', b'a']], [[b'c', b'f']], [[b'c', b'd']]], [[[b'b', b'a']]]]) # pyformat: disable + @test_util.run_deprecated_v1 def testOutOfBoundsError(self): tensor_params = ['a', 'b', 'c'] tensor_indices = [0, 1, 2] @@ -131,6 +140,7 @@ class RaggedTensorOpsTest(test_util.TensorFlowTestCase): r'indices\[1\] = 3 is not in \[0, 2\)', ragged.gather(ragged_params, ragged_indices).eval) + @test_util.run_deprecated_v1 def testUnknownIndicesRankError(self): params = ragged.constant([], ragged_rank=1) indices = constant_op.constant([0], dtype=dtypes.int64) diff --git a/tensorflow/python/ops/ragged/ragged_map_fn_op_test.py b/tensorflow/python/ops/ragged/ragged_map_fn_op_test.py index 6f3f33b444..7a8603c949 100644 --- a/tensorflow/python/ops/ragged/ragged_map_fn_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_map_fn_op_test.py @@ -140,6 +140,7 @@ class RaggedMapOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): ), ]) + @test_util.run_deprecated_v1 def testRaggedMap( self, fn, @@ -161,9 +162,10 @@ class RaggedMapOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): with self.test_session(): if ragged.is_ragged(expected_output): self.assertEqual(output.ragged_rank, expected_rt.ragged_rank) - output_values = output.eval() + output_values = self.evaluate(output) self.assertAllEqual(expected_output, output_values.tolist()) + @test_util.run_deprecated_v1 def testRaggedMapOnStructure(self): batman = ragged.constant([[1, 2, 3], [4], [5, 6, 7]]) # [[10, 20, 30], [40], [50, 60, 70]] @@ -184,6 +186,7 @@ class RaggedMapOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertAllEqual(output.eval().tolist(), [66, 44, 198]) # Test mapping over a dict of RTs can produce a dict of RTs. + @test_util.run_deprecated_v1 def testRaggedMapOnStructure_RaggedOutputs(self): batman = ragged.constant([[1, 2, 3], [4], [5, 6, 7]]) # [[10, 20, 30], [40], [50, 60, 70]] @@ -215,6 +218,7 @@ class RaggedMapOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertAllEqual(output['robin'].eval().tolist(), [[11, 21, 31], [41], [51, 61, 71]]) + @test_util.run_deprecated_v1 def testZip(self): x = ragged.constant([[10, 20], [30, 40], [50, 60], [70], [80, 90, 100]], dtypes.int64) @@ -232,11 +236,12 @@ class RaggedMapOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): infer_shape=False) with self.test_session(): - result = output.eval().tolist() + result = self.evaluate(output).tolist() self.assertAllEqual( result, [[[0, 10], [0, 20]], [[1, 30], [1, 40]], [[2, 50], [2, 60]], [[3, 70]], [[4, 80], [4, 90], [4, 100]]]) + @test_util.run_deprecated_v1 def testBatchGather(self): tokens = ragged.constant([['hello', '.', 'there'], ['merhaba'], ['bonjour', '.', 'ca va', '?']]) @@ -255,7 +260,7 @@ class RaggedMapOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): with self.test_session(): self.assertAllEqual( - out.eval().tolist(), + self.evaluate(out).tolist(), [[b'hello', b'there'], [b'merhaba'], [b'bonjour', b'ca va']]) def testMismatchRaggedRank(self): diff --git a/tensorflow/python/ops/ragged/ragged_map_inner_values_op_test.py b/tensorflow/python/ops/ragged/ragged_map_inner_values_op_test.py index 798d7c3ce8..b5802cb82d 100644 --- a/tensorflow/python/ops/ragged/ragged_map_inner_values_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_map_inner_values_op_test.py @@ -43,6 +43,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, with self.test_session(): self.assertEqual(result.eval().tolist(), expected) + @test_util.run_deprecated_v1 def testDocStringExamples(self): """Test the examples in apply_op_to_ragged_values.__doc__.""" rt = ragged.constant([[1, 2, 3], [], [4, 5], [6]]) @@ -54,6 +55,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, self.assertEqual(v2.eval().tolist(), [[1, 4, 9], [], [16, 25], [36]]) self.assertEqual(v3.eval().tolist(), [[6, 7, 8], [], [9, 10], [11]]) + @test_util.run_deprecated_v1 def testOpWithSingleRaggedTensorArg(self): tensor = ragged.constant([[1, 2, 3], [], [4, 5]]) self.assertRaggedMapInnerValuesReturns( @@ -61,17 +63,20 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, args=(tensor,), expected=[[0, 0, 0], [], [0, 0]]) + @test_util.run_deprecated_v1 def testOpWithTwoRaggedTensorArgs(self): x = ragged.constant([[3, 1, 4], [], [1, 5]]) y = ragged.constant([[1, 2, 3], [], [4, 5]]) self.assertRaggedMapInnerValuesReturns( op=math_ops.multiply, args=(x, y), expected=[[3, 2, 12], [], [4, 25]]) + @test_util.run_deprecated_v1 def testOpWithRaggedTensorAndScalarArgs(self): y = ragged.constant([[1, 2, 3], [], [4, 5]]) self.assertRaggedMapInnerValuesReturns( op=math_ops.multiply, args=(5, y), expected=[[5, 10, 15], [], [20, 25]]) + @test_util.run_deprecated_v1 def testOpWithThreeRaggedTensorArgs(self): condition = ragged.constant( [[True, True, False], [], [True, False]]) # pyformat: disable @@ -82,6 +87,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, args=(condition, x, y), expected=[[b'a', b'b', b'C'], [], [b'd', b'E']]) + @test_util.run_deprecated_v1 def testOpWithRaggedTensorListArg(self): x = ragged.constant([[1, 2, 3], [], [4, 5]]) y = ragged.constant([[10, 20, 30], [], [40, 50]]) @@ -90,6 +96,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, args=([x, y, x],), expected=[[12, 24, 36], [], [48, 60]]) + @test_util.run_deprecated_v1 def testOpWithKeywordArgs(self): x = ragged.constant([[3, 1, 4], [], [1, 5]]) y = ragged.constant([[1, 2, 3], [], [4, 5]]) @@ -98,6 +105,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, kwargs=dict(x=x, y=y), expected=[[3, 2, 12], [], [4, 25]]) + @test_util.run_deprecated_v1 def testOpWithMixedPositionalAndKeywordArgs(self): x = ragged.constant([[3, 1, 4], [], [1, 5]]) y = ragged.constant([[1, 2, 3], [], [4, 5]]) @@ -107,6 +115,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, kwargs=dict(y=y), expected=[[3, 2, 12], [], [4, 25]]) + @test_util.run_deprecated_v1 def testNonElementWiseOp(self): x = ragged.constant( [[[3, 1, 4], [1, 5, 9], [2, 6, 5]], [], [[3, 5, 8], [9, 7, 9]]], @@ -119,6 +128,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, }, expected=[[8, 15, 13], [], [16, 25]]) + @test_util.run_deprecated_v1 def testOpWithRaggedRankGreaterThanOne(self): # ragged_rank=0 x0 = [3, 1, 4, 1, 5, 9, 2, 6, 5] @@ -163,6 +173,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, [[[54, 14], [48, 45]]] # row 3 ]) # pyformat: disable + @test_util.run_deprecated_v1 def testOpWithRaggedRankThree(self): x = ragged.constant([[[3, 1, 4]], [], [[], [1, 5]]]) y = ragged.constant([[[1, 2, 3]], [], [[], [4, 5]]]) @@ -171,6 +182,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, args=(x, y), expected=[[[3, 2, 12]], [], [[], [4, 25]]]) + @test_util.run_deprecated_v1 def testOpWithInnerValuesOnly(self): x = constant_op.constant([[1, 2], [3, 4], [5, 6]]) y = constant_op.constant(2) @@ -191,6 +203,7 @@ class RaggedMapInnerValuesOpTest(test_util.TensorFlowTestCase, r'Inputs must have identical ragged splits.*', ragged.map_inner_values, math_ops.add, x, y) + @test_util.run_deprecated_v1 def testRaggedTensorSplitsMismatchErrorAtRuntime(self): splits1 = array_ops.placeholder_with_default( constant_op.constant([0, 3, 3, 5], dtypes.int64), None) diff --git a/tensorflow/python/ops/ragged/ragged_operators_test.py b/tensorflow/python/ops/ragged/ragged_operators_test.py index a99d788ef7..7fe8159d82 100644 --- a/tensorflow/python/ops/ragged/ragged_operators_test.py +++ b/tensorflow/python/ops/ragged/ragged_operators_test.py @@ -27,6 +27,7 @@ class RaggedElementwiseOpsTest(test_util.TensorFlowTestCase): # @TODO(edloper): Test right-handed versions of operators once we add # broadcasting support for elementwise ops. + @test_util.run_deprecated_v1 def testOrderingOperators(self): x = ragged.constant([[1, 5], [3]]) y = ragged.constant([[4, 5], [1]]) @@ -40,6 +41,7 @@ class RaggedElementwiseOpsTest(test_util.TensorFlowTestCase): if a != b: print('%30s %s' % (b, a)) + @test_util.run_deprecated_v1 def testArithmeticOperators(self): x = ragged.constant([[1.0, -2.0], [8.0]]) y = ragged.constant([[4.0, 4.0], [2.0]]) @@ -75,6 +77,7 @@ class RaggedElementwiseOpsTest(test_util.TensorFlowTestCase): self.assertEqual((2.0 % y).eval().tolist(), [[2.0, 2.0], [0.0]]) self.assertEqual((x % 2.0).eval().tolist(), [[1.0, 0.0], [0.0]]) + @test_util.run_deprecated_v1 def testLogicalOperators(self): a = ragged.constant([[True, True], [False]]) b = ragged.constant([[True, False], [False]]) diff --git a/tensorflow/python/ops/ragged/ragged_range_op_test.py b/tensorflow/python/ops/ragged/ragged_range_op_test.py index 3c6a6fb75c..644423ecb7 100644 --- a/tensorflow/python/ops/ragged/ragged_range_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_range_op_test.py @@ -26,6 +26,7 @@ from tensorflow.python.platform import googletest class RaggedRangeOpTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testDocStringExamples(self): """Examples from ragged_range.__doc__.""" with self.test_session(): @@ -38,6 +39,7 @@ class RaggedRangeOpTest(test_util.TensorFlowTestCase): rt3 = ragged.range([0, 5, 8], [3, 3, 12], 2).eval().tolist() self.assertEqual(rt3, [[0, 2], [], [8, 10]]) + @test_util.run_deprecated_v1 def testBasicRanges(self): with self.test_session(): # Specify limits only. @@ -56,6 +58,7 @@ class RaggedRangeOpTest(test_util.TensorFlowTestCase): [list(range(0, 4, 2)), list(range(3, 4, 3)), list(range(5, 15, 4))]) + @test_util.run_deprecated_v1 def testFloatRanges(self): with self.test_session(): expected = [[0.0, 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 2.8, 3.2, 3.6], [3.0], @@ -64,6 +67,7 @@ class RaggedRangeOpTest(test_util.TensorFlowTestCase): [0.4, 1.5, 2.2]).eval().tolist() self.assertEqual(expected, [[round(v, 5) for v in row] for row in actual]) + @test_util.run_deprecated_v1 def testNegativeDeltas(self): with self.test_session(): self.assertEqual( @@ -77,6 +81,7 @@ class RaggedRangeOpTest(test_util.TensorFlowTestCase): [list(range(0, 0, -1)), list(range(-3, 0, 1)), list(range(5, 0, -2))]) + @test_util.run_deprecated_v1 def testBroadcast(self): with self.test_session(): # Specify starts and limits, broadcast deltas. @@ -89,6 +94,7 @@ class RaggedRangeOpTest(test_util.TensorFlowTestCase): self.assertEqual( ragged.range(0, 5, 1).eval().tolist(), [list(range(0, 5, 1))]) + @test_util.run_deprecated_v1 def testEmptyRanges(self): rt1 = ragged.range([0, 5, 3], [0, 3, 5]) rt2 = ragged.range([0, 5, 5], [0, 3, 5], -1) @@ -96,6 +102,7 @@ class RaggedRangeOpTest(test_util.TensorFlowTestCase): self.assertEqual(rt1.eval().tolist(), [[], [], [3, 4]]) self.assertEqual(rt2.eval().tolist(), [[], [5, 4], []]) + @test_util.run_deprecated_v1 def testShapeFnErrors(self): with self.test_session(): self.assertRaisesRegexp(ValueError, r'Shape must be at most rank 1.*', @@ -107,12 +114,14 @@ class RaggedRangeOpTest(test_util.TensorFlowTestCase): self.assertRaisesRegexp(ValueError, r'Dimensions must be equal.*', ragged.range, [0], [1, 2]) + @test_util.run_deprecated_v1 def testKernelErrors(self): with self.test_session(): self.assertRaisesRegexp(errors.InvalidArgumentError, r'Requires delta != 0', ragged.range(0, 0, 0).eval) + @test_util.run_deprecated_v1 def testShape(self): self.assertEqual(ragged.range(0, 0, 0).shape.as_list(), [1, None]) self.assertEqual(ragged.range([1, 2, 3]).shape.as_list(), [3, None]) diff --git a/tensorflow/python/ops/ragged/ragged_reduce_op_test.py b/tensorflow/python/ops/ragged/ragged_reduce_op_test.py index 93176c738d..9f51d59ba3 100644 --- a/tensorflow/python/ops/ragged/ragged_reduce_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_reduce_op_test.py @@ -300,6 +300,7 @@ class RaggedReduceOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): axis=2, expected=[[mean(1, 2), mean(3, 4, 5)], [mean(6, 7), 8], [9]]), ) + @test_util.run_deprecated_v1 def testReduce(self, ragged_reduce_op, rt_input, axis, expected): rt_input = ragged.constant(rt_input) reduced = ragged_reduce_op(rt_input, axis) @@ -311,6 +312,7 @@ class RaggedReduceOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertTrue( ((actual == expected) | (np.isnan(actual) & np.isnan(expected))).all()) + @test_util.run_deprecated_v1 def testMeanNan(self): rt_as_list = [[0, 1, 2, 3], [4], [], [5, 6], [7], [8, 9]] expected = ( @@ -321,6 +323,7 @@ class RaggedReduceOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with self.test_session(): self.assertEqualWithNan(reduced.eval(), expected) + @test_util.run_deprecated_v1 def testMeanWithTensorInputs(self): tensor = [[1.0, 2.0, 3.0], [10.0, 20.0, 30.0]] expected = [2.0, 20.0] @@ -328,6 +331,7 @@ class RaggedReduceOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): with self.test_session(): self.assertAllEqual(reduced.eval(), expected) + @test_util.run_deprecated_v1 def testErrors(self): rt_input = ragged.constant([[1, 2, 3], [4, 5]]) axis = array_ops.placeholder_with_default(constant_op.constant([0]), None) diff --git a/tensorflow/python/ops/ragged/ragged_row_lengths_op_test.py b/tensorflow/python/ops/ragged/ragged_row_lengths_op_test.py index 4d5a0a5d11..4a705be484 100644 --- a/tensorflow/python/ops/ragged/ragged_row_lengths_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_row_lengths_op_test.py @@ -143,6 +143,7 @@ class RaggedRowLengthsOp(test_util.TensorFlowTestCase, parameterized.TestCase): expected=[[2, 3, 0], [4, 1]], expected_ragged_rank=1), ]) # pyformat: disable + @test_util.run_deprecated_v1 def testRowLengths(self, rt_input, expected, diff --git a/tensorflow/python/ops/ragged/ragged_row_splits_to_segment_ids_op_test.py b/tensorflow/python/ops/ragged/ragged_row_splits_to_segment_ids_op_test.py index f246bf3552..7f5f4e91bd 100644 --- a/tensorflow/python/ops/ragged/ragged_row_splits_to_segment_ids_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_row_splits_to_segment_ids_op_test.py @@ -26,6 +26,7 @@ from tensorflow.python.platform import googletest class RaggedSplitsToSegmentIdsOpTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testDocStringExample(self): splits = [0, 3, 3, 5, 6, 9] expected = [0, 0, 0, 2, 2, 3, 4, 4, 4] @@ -33,12 +34,14 @@ class RaggedSplitsToSegmentIdsOpTest(test_util.TensorFlowTestCase): with self.test_session(): self.assertEqual(segment_ids.eval().tolist(), expected) + @test_util.run_deprecated_v1 def testEmptySplits(self): # Note: the splits for an empty ragged tensor contains a single zero. segment_ids = ragged.row_splits_to_segment_ids([0]) with self.test_session(): self.assertEqual(segment_ids.eval().tolist(), []) + @test_util.run_deprecated_v1 def testErrors(self): self.assertRaisesRegexp(ValueError, r'Invalid row_splits: \[\]', ragged.row_splits_to_segment_ids, []) diff --git a/tensorflow/python/ops/ragged/ragged_segment_ids_to_row_splits_op_test.py b/tensorflow/python/ops/ragged/ragged_segment_ids_to_row_splits_op_test.py index fa7adf66b0..7e52f2d844 100644 --- a/tensorflow/python/ops/ragged/ragged_segment_ids_to_row_splits_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_segment_ids_to_row_splits_op_test.py @@ -26,6 +26,7 @@ from tensorflow.python.platform import googletest class RaggedSplitsToSegmentIdsOpTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testDocStringExample(self): segment_ids = [0, 0, 0, 2, 2, 3, 4, 4, 4] expected = [0, 3, 3, 5, 6, 9] @@ -33,6 +34,7 @@ class RaggedSplitsToSegmentIdsOpTest(test_util.TensorFlowTestCase): with self.test_session(): self.assertEqual(splits.eval().tolist(), expected) + @test_util.run_deprecated_v1 def testEmptySegmentIds(self): # Note: the splits for an empty ragged tensor contains a single zero. segment_ids = ragged.segment_ids_to_row_splits([]) @@ -49,6 +51,7 @@ class RaggedSplitsToSegmentIdsOpTest(test_util.TensorFlowTestCase): self.assertRaisesRegexp(ValueError, r'Shape \(1, 1\) must have rank 1', ragged.segment_ids_to_row_splits, [[0]]) + @test_util.run_deprecated_v1 def testNumSegments(self): segment_ids = [0, 0, 0, 2, 2, 3, 4, 4, 4] num_segments = 7 @@ -57,6 +60,7 @@ class RaggedSplitsToSegmentIdsOpTest(test_util.TensorFlowTestCase): with self.test_session(): self.assertEqual(splits.eval().tolist(), expected) + @test_util.run_deprecated_v1 def testUnsortedSegmentIds(self): # Segment ids are not required to be sorted. segment_ids = [0, 4, 3, 2, 4, 4, 2, 0, 0] diff --git a/tensorflow/python/ops/ragged/ragged_segment_op_test.py b/tensorflow/python/ops/ragged/ragged_segment_op_test.py index 7d41eb7f75..9e4877ae3e 100644 --- a/tensorflow/python/ops/ragged/ragged_segment_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_segment_op_test.py @@ -110,6 +110,7 @@ class RaggedSegmentOpsTest(test_util.TensorFlowTestCase, (ragged.segment_mean, mean, [5, 4, 3, 2, 1, 0]), (ragged.segment_mean, mean, [0, 0, 0, 10, 10, 10]), ) + @test_util.run_deprecated_v1 def testRaggedSegment_Int(self, segment_op, combiner, segment_ids): rt_as_list = [[0, 1, 2, 3], [4], [], [5, 6], [7], [8, 9]] rt = ragged.constant(rt_as_list) @@ -118,8 +119,7 @@ class RaggedSegmentOpsTest(test_util.TensorFlowTestCase, combiner) segmented = segment_op(rt, segment_ids, num_segments) - with self.test_session(): - self.assertListEqual(segmented.eval().tolist(), expected) + self.assertListEqual(self.evaluate(segmented).tolist(), expected) @parameterized.parameters( (ragged.segment_sum, sum, [0, 0, 1, 1, 2, 2]), @@ -147,6 +147,7 @@ class RaggedSegmentOpsTest(test_util.TensorFlowTestCase, (ragged.segment_sqrt_n, sqrt_n, [5, 4, 3, 2, 1, 0]), (ragged.segment_sqrt_n, sqrt_n, [0, 0, 0, 10, 10, 10]), ) + @test_util.run_deprecated_v1 def testRaggedSegment_Float(self, segment_op, combiner, segment_ids): rt_as_list = [[0., 1., 2., 3.], [4.], [], [5., 6.], [7.], [8., 9.]] rt = ragged.constant(rt_as_list) @@ -155,10 +156,10 @@ class RaggedSegmentOpsTest(test_util.TensorFlowTestCase, combiner) segmented = segment_op(rt, segment_ids, num_segments) - with self.test_session(): - self.assertNestedListAmostEqual( - segmented.eval().tolist(), expected, places=5) + self.assertNestedListAmostEqual( + self.evaluate(segmented).tolist(), expected, places=5) + @test_util.run_deprecated_v1 def testRaggedRankTwo(self): rt = ragged.constant([ [[111, 112, 113, 114], [121],], # row 0 @@ -172,17 +173,16 @@ class RaggedSegmentOpsTest(test_util.TensorFlowTestCase, [], # row 1 [[411, 412], [321, 322], [331]] # row 2 ] # pyformat: disable - with self.test_session(): - self.assertEqual(segmented1.eval().tolist(), expected1) + self.assertEqual(self.evaluate(segmented1).tolist(), expected1) segment_ids2 = [1, 2, 1, 1] segmented2 = ragged.segment_sum(rt, segment_ids2, 3) expected2 = [[], [[111+411, 112+412, 113, 114], [121+321, 322], [331]], []] # pyformat: disable - with self.test_session(): - self.assertEqual(segmented2.eval().tolist(), expected2) + self.assertEqual(self.evaluate(segmented2).tolist(), expected2) + @test_util.run_deprecated_v1 def testRaggedSegmentIds(self): rt = ragged.constant([ [[111, 112, 113, 114], [121],], # row 0 @@ -195,8 +195,7 @@ class RaggedSegmentOpsTest(test_util.TensorFlowTestCase, expected = [[], [111+321, 112+322, 113, 114], [121+331+411, 412]] # pyformat: disable - with self.test_session(): - self.assertEqual(segmented.eval().tolist(), expected) + self.assertEqual(self.evaluate(segmented).tolist(), expected) def testShapeMismatchError1(self): dt = constant_op.constant([1, 2, 3, 4, 5, 6]) @@ -206,6 +205,7 @@ class RaggedSegmentOpsTest(test_util.TensorFlowTestCase, 'but segment_ids is ragged and data is not.', ragged.segment_sum, dt, segment_ids, 3) + @test_util.run_deprecated_v1 def testShapeMismatchError2(self): rt = ragged.constant([ [[111, 112, 113, 114], [121]], # row 0 @@ -226,7 +226,7 @@ class RaggedSegmentOpsTest(test_util.TensorFlowTestCase, array_ops.placeholder_with_default(segment_ids.values, None), array_ops.placeholder_with_default(segment_ids.row_splits, None)) segmented2 = ragged.segment_sum(rt, segment_ids2, 3) - with self.test_session(): + with self.cached_session(): self.assertRaisesRegexp( errors.InvalidArgumentError, 'segment_ids.shape must be a prefix of data.shape.*', segmented2.eval) diff --git a/tensorflow/python/ops/ragged/ragged_stack_op_test.py b/tensorflow/python/ops/ragged/ragged_stack_op_test.py index d474a749f0..4343471694 100644 --- a/tensorflow/python/ops/ragged/ragged_stack_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_stack_op_test.py @@ -265,6 +265,7 @@ class RaggedStackOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): axis=0, expected=[[[b'a00', b'a01'], [], [b'a20', b'a21']]]), ) # pyformat: disable + @test_util.run_deprecated_v1 def testRaggedStack(self, descr, rt_inputs, @@ -313,6 +314,7 @@ class RaggedStackOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): def testError(self, rt_inputs, axis, error, message): self.assertRaisesRegexp(error, message, ragged.stack, rt_inputs, axis) + @test_util.run_deprecated_v1 def testSingleTensorInput(self): """Tests ragged_stack with a single tensor input. diff --git a/tensorflow/python/ops/ragged/ragged_string_ops.py b/tensorflow/python/ops/ragged/ragged_string_ops.py new file mode 100644 index 0000000000..cdcdbdff07 --- /dev/null +++ b/tensorflow/python/ops/ragged/ragged_string_ops.py @@ -0,0 +1,119 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Ragged operations for working with string Tensors.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gen_string_ops +from tensorflow.python.ops.ragged import ragged_conversion_ops +from tensorflow.python.ops.ragged import ragged_factory_ops +from tensorflow.python.ops.ragged import ragged_tensor +from tensorflow.python.util.tf_export import tf_export + + +# pylint: disable=redefined-builtin +@tf_export("strings.unicode_encode") +def unicode_encode(input, output_encoding, errors="replace", + replacement_char=65533, name=None): + r"""Encodes each sequence of Unicode code points in `input` into a string. + + `result[i1...iN]` is the string formed by concatenating the Unicode + codepoints `input[1...iN, :]`, encoded using `output_encoding`. + + Args: + input: An `N+1` dimensional potentially ragged integer tensor with + shape `[D1...DN, num_chars]`. + output_encoding: Unicode encoding that should be used to encode each + codepoint sequence. Can be `"UTF-8"`, `"UTF-16-BE"`, or `"UTF-32-BE"`. + errors: Specifies the response when an invalid codepoint is encountered + (optional). One of: + * `'replace'`: Replace invalid codepoint with the + `replacement_char`. (default) + * `'ignore'`: Skip invalid codepoints. + * `'strict'`: Raise an exception for any invalid codepoint. + replacement_char: The replacement character codepoint to be used in place of + any invalid input when `errors='replace'`. Any valid unicode codepoint may + be used. The default value is the default unicode replacement character + which is 0xFFFD (U+65533). + name: A name for the operation (optional). + + Returns: + A `N` dimensional `string` tensor with shape `[D1...DN]`. + + #### Example: + ```python + >>> input = [[71, 246, 246, 100, 110, 105, 103, 104, 116], [128522]] + >>> unicode_encode(input, 'UTF8') + ['G\xc3\xb6\xc3\xb6dnight', '\xf0\x9f\x98\x8a'] + ``` + """ + with ops.name_scope(name, "UnicodeEncode", [input]): + input_tensor = ragged_factory_ops.convert_to_tensor_or_ragged_tensor(input) + if input_tensor.shape.ndims is None: + raise ValueError("Rank of input_tensor must be statically known.") + if ragged_tensor.is_ragged(input_tensor): + if input_tensor.inner_values.shape.ndims > 1: + # If the inner_values of our ragged tensor is multi-dimensional, we can + # process it separately and our output will have the same nested splits + # as our input. + return input_tensor.with_inner_values( + unicode_encode(input_tensor.inner_values, output_encoding, errors, + replacement_char)) + elif input_tensor.ragged_rank > 1: + # Recursively process the values of the ragged tensor. + return input_tensor.with_values( + unicode_encode(input_tensor.values, output_encoding, errors, + replacement_char)) + else: + # Our ragged tensor is of the correct shape (rank 1 inner_values tensor + # with ragged_rank of 1) so we can process it as normal. + return gen_string_ops.unicode_encode( + input_values=input_tensor.values, + input_splits=input_tensor.row_splits, + output_encoding=output_encoding, + errors=errors, + replacement_char=replacement_char) + else: + if input_tensor.shape.ndims == 2: + # The input tensor is of the correct 2-D shape, it's just not ragged. + return unicode_encode(ragged_conversion_ops.from_tensor(input_tensor), + output_encoding, errors, replacement_char) + elif input_tensor.shape.ndims > 2: + # We need to initially flatten the input tensor to 2-D, and then can + # reshape the output of our processed flattened tensor. + flat_input_tensor = array_ops.reshape( + input_tensor, + array_ops.stack([-1, array_ops.shape(input_tensor)[-1]])) + flat_output_tensor = unicode_encode(flat_input_tensor, output_encoding, + errors, replacement_char) + return array_ops.reshape(flat_output_tensor, input_tensor.shape[:-1]) + elif input_tensor.shape.ndims == 0: + raise ValueError("input_tensor's rank must be at least 1.") + else: + # Our input tensor is rank 1, so we create a ragged tensor with an added + # dimension to create the correct input shape & type, and then remove + # the additional dimension from the output and return the string scalar. + ragged_input_tensor = ragged_factory_ops.from_row_splits( + input_tensor, + array_ops.stack([0, array_ops.shape(input_tensor, + out_type=dtypes.int64)[0]])) + output_tensor = unicode_encode(ragged_input_tensor, output_encoding, + errors, replacement_char) + return array_ops.reshape(output_tensor, []) diff --git a/tensorflow/python/ops/ragged/ragged_tensor.py b/tensorflow/python/ops/ragged/ragged_tensor.py index abb27fc3c0..ddeabfb464 100644 --- a/tensorflow/python/ops/ragged/ragged_tensor.py +++ b/tensorflow/python/ops/ragged/ragged_tensor.py @@ -64,7 +64,7 @@ class RaggedTensor(object): a 3-D `RaggedTensor` that stores the fixed-size word embedding for each word in a sentence, for each sentence in a batch, could be written as `[num_sentences, (num_words), embedding_size]`. The parentheses around - `(num_words)` indicate that that dimension is ragged, and that the length + `(num_words)` indicate that dimension is ragged, and that the length of each element list in that dimension may vary for each item. ### Component Tensors @@ -257,6 +257,7 @@ class RaggedTensor(object): raise TypeError("Row-partitioning argument must be a Tensor.") values.shape.with_rank_at_least(1) row_splits.shape.assert_has_rank(1) + row_splits.set_shape([None]) self._values = values self._row_splits = row_splits diff --git a/tensorflow/python/ops/ragged/ragged_tensor_bounding_shape_op_test.py b/tensorflow/python/ops/ragged/ragged_tensor_bounding_shape_op_test.py index a1c10aff9d..befe30f0e1 100644 --- a/tensorflow/python/ops/ragged/ragged_tensor_bounding_shape_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_tensor_bounding_shape_op_test.py @@ -28,41 +28,39 @@ class RaggedTensorBoundingShapeOp(test_util.TensorFlowTestCase): def testDocStringExample(self): # This is the example from ragged.bounding_shape.__doc__. rt = ragged.constant([[1, 2, 3, 4], [5], [], [6, 7, 8, 9], [10]]) - with self.test_session(): - self.assertEqual(ragged.bounding_shape(rt).eval().tolist(), [5, 4]) + self.assertEqual(self.evaluate(ragged.bounding_shape(rt)).tolist(), [5, 4]) def test2DRaggedTensorWithOneRaggedDimension(self): values = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] rt1 = ragged.from_row_splits(values, [0, 2, 5, 6, 6, 7]) rt2 = ragged.from_row_splits(values, [0, 7]) rt3 = ragged.from_row_splits(values, [0, 0, 7, 7]) - with self.test_session(): - self.assertEqual(ragged.bounding_shape(rt1).eval().tolist(), [5, 3]) - self.assertEqual(ragged.bounding_shape(rt2).eval().tolist(), [1, 7]) - self.assertEqual(ragged.bounding_shape(rt3).eval().tolist(), [3, 7]) + self.assertEqual(self.evaluate(ragged.bounding_shape(rt1)).tolist(), [5, 3]) + self.assertEqual(self.evaluate(ragged.bounding_shape(rt2)).tolist(), [1, 7]) + self.assertEqual(self.evaluate(ragged.bounding_shape(rt3)).tolist(), [3, 7]) def test3DRaggedTensorWithOneRaggedDimension(self): values = [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]] rt1 = ragged.from_row_splits(values, [0, 2, 5, 6, 6, 7]) rt2 = ragged.from_row_splits(values, [0, 7]) rt3 = ragged.from_row_splits(values, [0, 0, 7, 7]) - with self.test_session(): - self.assertEqual(ragged.bounding_shape(rt1).eval().tolist(), [5, 3, 2]) - self.assertEqual(ragged.bounding_shape(rt2).eval().tolist(), [1, 7, 2]) - self.assertEqual(ragged.bounding_shape(rt3).eval().tolist(), [3, 7, 2]) + self.assertEqual( + self.evaluate(ragged.bounding_shape(rt1)).tolist(), [5, 3, 2]) + self.assertEqual( + self.evaluate(ragged.bounding_shape(rt2)).tolist(), [1, 7, 2]) + self.assertEqual( + self.evaluate(ragged.bounding_shape(rt3)).tolist(), [3, 7, 2]) def testNonRaggedTensor(self): dt = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]] - with self.test_session(): - self.assertEqual(ragged.bounding_shape(dt).eval().tolist(), [4, 3]) + self.assertEqual(self.evaluate(ragged.bounding_shape(dt)).tolist(), [4, 3]) def testExplicitAxisOptimizations(self): rt = ragged.from_row_splits(b'a b c d e f g'.split(), [0, 2, 5, 6, 6, 7]) - with self.test_session(): - self.assertEqual(ragged.bounding_shape(rt, 0).eval().tolist(), 5) - self.assertEqual(ragged.bounding_shape(rt, 1).eval().tolist(), 3) - self.assertEqual( - ragged.bounding_shape(rt, [1, 0]).eval().tolist(), [3, 5]) + self.assertEqual(self.evaluate(ragged.bounding_shape(rt, 0)).tolist(), 5) + self.assertEqual(self.evaluate(ragged.bounding_shape(rt, 1)).tolist(), 3) + self.assertEqual( + self.evaluate(ragged.bounding_shape(rt, [1, 0])).tolist(), [3, 5]) if __name__ == '__main__': diff --git a/tensorflow/python/ops/ragged/ragged_tensor_shape.py b/tensorflow/python/ops/ragged/ragged_tensor_shape.py new file mode 100644 index 0000000000..9129b4b10b --- /dev/null +++ b/tensorflow/python/ops/ragged/ragged_tensor_shape.py @@ -0,0 +1,570 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Shapes & broadcasting for RaggedTensors.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops.ragged import ragged_array_ops +from tensorflow.python.ops.ragged import ragged_conversion_ops +from tensorflow.python.ops.ragged import ragged_factory_ops +from tensorflow.python.ops.ragged import ragged_tensor +from tensorflow.python.ops.ragged import ragged_util + + +class RaggedTensorDynamicShape(object): + """A collection of tensors encoding the shape of a potentially ragged tensor. + + Each `RaggedTensorDynamicShape` consists of an ordered list of dimension + sizes. There are two dimension types: + + * "Uniform dimensions" are dimenisons where all slices have the same + length. `RaggedTensorDynamicShape` records the size of each uniform + dimension using a single scalar integer. + + * "Ragged dimensions" are dimensions whose slices may have different + lengths. `RaggedTensorDynamicShape` records the size of each ragged + dimension using an integer vector containing the slice lengths for all + the slices across that dimension. + + Furthermore, there are two ways a dimension might be encoded: + + * "Partitioned dimensions" are dimensions that are encoded using a + `RaggedTensor`'s `nested_row_splits`. The outermostmost partitioned + dimension must be uniform, and the innermost partitioned dimension must + be ragged. + + * "Inner dimensions" are dimensions that are encoded using a + `RaggedTensor`'s `inner_values`. Inner dimensions are always uniform. + + The sizes of partitioned dimensions are recorded using `partitioned_dim_sizes` + and `inner_dim_sizes`: + + * `paritioned_dim_sizes` is a list of tensors (one for each partitioned + dimension). + + * For uniform dimensions, the tensor is an integer scalar specifying the + size of all slices across that dimension. + * For ragged dimensions, the tensor is an integer vector specifying the + size of each slice across that dimension. + + * `inner_dim_sizes` is a single integer vector, where each element + specifies the size of a single inner dimension. + + Examples: + + Tensor | Ragged | Partitioned Dim Sizes | Inner Dim + : Rank : : Sizes + ------------------------------ | ------ | ---------------------- | ---------- + `[[1, 2, 3], [4, 5, 6]]` | 0 | | `2, 3` + `[[1, 2], [], [3, 4, 5]]` | 1 | `3, (2, 0, 3)` | + `[[[1, 2], [3, 4]], [[5, 6]]]` | 1 | `2, (2, 1)` | 2 + `[[[1, 2], [3]], [[4, 5]]]` | 2 | `2, (2, 1), (2, 1, 2)` | + """ + + def __init__(self, partitioned_dim_sizes, inner_dim_sizes): + """Creates a RaggedTensorDynamicShape. + + Args: + partitioned_dim_sizes: A `list` of 0-D or 1-D integer `Tensor`, one for + each partitioned dimension. If dimension `d` is uniform, then + `partitioned_dim_sizes[d]` must be an integer scalar, specifying the + size of all slices across dimension `d`. If dimension `d` is ragged, + then `partitioned_dim_sizes[d]` must be an integer vector, specifying + the size of each slice across dimension `d`. + inner_dim_sizes: A 1-D integer `Tensor`, whose length is equal to the + number of inner dimensions. `inner_dim_sizes[n]` is the size of all + slices across the `n`th inner dimension (which is the + `(len(partitioned_dim_sizes)+n)`th dimension in the overall tensor. + """ + assert isinstance(partitioned_dim_sizes, (list, tuple)) + with ops.name_scope(None, 'RaggedTensorDynamicShape', + (partitioned_dim_sizes, inner_dim_sizes)): + partitioned_dim_sizes = tuple( + ragged_util.convert_to_int_tensor( + size, dtype=dtypes.int64, name='partitioned_dimension_size') + for size in partitioned_dim_sizes) + inner_dim_sizes = ragged_util.convert_to_int_tensor( + inner_dim_sizes, dtype=dtypes.int64, name='inner_dim_sizes') + + # Validate shapes. + if partitioned_dim_sizes: + for axis, dimension_size in enumerate(partitioned_dim_sizes): + if dimension_size.shape.ndims is None: + raise ValueError( + 'rank of partitioned_dim_sizes[%d] is unknown' % axis) + dimension_size.shape.with_rank_at_most(1) + if partitioned_dim_sizes[0].shape.ndims == 1: + raise ValueError('outermost partitioned dimension must be uniform') + if partitioned_dim_sizes[-1].shape.ndims == 0: + raise ValueError('innermost partitioned dimension must be ragged') + inner_dim_sizes.shape.assert_has_rank(1) + + self._partitioned_dim_sizes = partitioned_dim_sizes + self._inner_dim_sizes = inner_dim_sizes + + def __repr__(self): + return ('RaggedTensorDynamicShape' + '(partitioned_dim_sizes=%r, inner_dim_sizes=%r)' % + (self._partitioned_dim_sizes, self._inner_dim_sizes)) + + @staticmethod + def from_dim_sizes(dim_sizes): + """Constructs a ragged shape from a list of dimension sizes. + + This list contains a single tensor for each dimension, where the tensor + is a scalar if the dimension is uniform, or a vector if the dimension is + ragged. + + Args: + dim_sizes: List of int64 scalars or vectors. + + Returns: + A RaggedTensorDynamicShape. + """ + with ops.name_scope(None, 'RaggedTensorDynamicShapeFromDimensionSizes', + [dim_sizes]): + dim_sizes = tuple( + ragged_util.convert_to_int_tensor( + size, dtype=dtypes.int64, name='dim_sizes') for size in dim_sizes) + # Split the dimensions into partitioned & inner dimensions. + inner_split = 0 + for dim, dim_size in enumerate(dim_sizes): + if dim_size.shape.ndims == 1: + inner_split = dim + 1 + elif dim_size.shape.ndims != 0: + raise ValueError('Each dim_size must be a scalar or a vector') + return RaggedTensorDynamicShape(dim_sizes[:inner_split], + dim_sizes[inner_split:]) + + @classmethod + def from_tensor(cls, rt_input): + """Constructs a ragged shape for a potentially ragged tensor.""" + with ops.name_scope(None, 'RaggedTensorDynamicShapeFromTensor', [rt_input]): + rt_input = ragged_factory_ops.convert_to_tensor_or_ragged_tensor(rt_input) + if not ragged_tensor.is_ragged(rt_input): + return cls([], array_ops.shape(rt_input)) + else: + partitioned_dim_sizes = ((ragged_array_ops.nrows(rt_input),) + + ragged_array_ops.nested_row_lengths(rt_input)) + return RaggedTensorDynamicShape( + partitioned_dim_sizes, + array_ops.shape(rt_input.inner_values)[1:]) + + def dimension_size(self, axis): + """Returns the size of slices across the specified dimension.""" + if not isinstance(axis, int): + raise TypeError('axis must be an integer') + partitioned_ndims = len(self._partitioned_dim_sizes) + if axis < partitioned_ndims: + return self._partitioned_dim_sizes[axis] + else: + return self._inner_dim_sizes[axis - partitioned_ndims] + + def is_ragged(self, axis): + """Returns true if the indicated dimension is ragged.""" + if not isinstance(axis, int): + raise TypeError('axis must be an integer') + rank = self.rank + if axis < 0: + raise ValueError('Negative axis values are not supported') + elif rank is not None and axis >= rank: + raise ValueError('Expected axis=%s < rank=%s' % (axis, rank)) + else: + return (axis > 0 and axis < len(self._partitioned_dim_sizes) and + self._partitioned_dim_sizes[axis].shape.ndims == 1) + + @property + def rank(self): + """The number of dimensions in this shape, or None if unknown.""" + inner_ndims = self._inner_dim_sizes.shape[0].value + if inner_ndims is None: + return None + else: + return len(self._partitioned_dim_sizes) + inner_ndims + + @property + def partitioned_dim_sizes(self): + """The partitioned dimension sizes for this shape. + + Returns: + A `list` of 0-D or 1-D integer `Tensor`. + """ + return self._partitioned_dim_sizes + + @property + def inner_dim_sizes(self): + """The inner dimension sizes for this shape. + + Returns: + A 1-D integer `Tensor`. + """ + return self._inner_dim_sizes + + @property + def num_partitioned_dimensions(self): + """The number of partitioned dimensions in this shape.""" + return len(self._partitioned_dim_sizes) + + @property + def num_inner_dimensions(self): + """The number of inner dimensions, or `None` if not statically known.""" + return self._inner_dim_sizes.shape[0].value + + def broadcast_to_rank(self, rank): + """Adds leading size-1 dimensions to broadcast `self` to the given rank. + + E.g., if `shape1` is `[3, (D2), 4]`, then `shape1.broadcast_to_rank(5)` + is `[1, 1, 3, (D2), 4]`. + + Args: + rank: The rank for the returned shape. + + Returns: + A RaggedTensorDynamicShape with `rank` dimensions, whose inner dimensions + have the same size as `self` and whose outer dimensions have size `1`. + + Raises: + ValueError: If `self.rank` is unknown or greater than `rank`. + """ + if self.rank is None: + raise ValueError('Unable to broadcast: self.rank is unknown') + dims_to_add = rank - self.rank + if dims_to_add < 0: + raise ValueError('Unable to broadcast: rank=%d must be greater than ' + 'self.rank=%d.' % (rank, self.rank)) + elif dims_to_add == 0: + return self + elif self._partitioned_dim_sizes: + partitioned_dims = (1,) * dims_to_add + self._partitioned_dim_sizes + return RaggedTensorDynamicShape(partitioned_dims, self._inner_dim_sizes) + else: + inner_dims = array_ops.concat( + [array_ops.ones([dims_to_add], dtypes.int64), self.inner_dim_sizes], + axis=0) + return RaggedTensorDynamicShape([], inner_dims) + + def broadcast_dimension(self, axis, lengths): + """Returns a shape that is broadcast-compatible with self & lengths. + + * If dimension[axis] is uniform and lengths is a scalar, the check + that either lengths==1 or axis==1 or lengths==axis, and tile + dimension[axis] with tf.where(lengths==axis, 1, axis) repeats. + + * If dimension[axis] is uniform and lengths is a vector, then check + that dimension[axis]==1, and raggedly tile dimension[axis] with + lengths repeats. (we can skip tiling if we statically know that + slice_lengths == 1??) + + * If dimension[axis] is ragged and lengths is a scalar, then check + that lengths==1. + + * If dimension[axis] is ragged and lengths is a vector, then check + that self.dimension_size(axis) == lengths. + + Args: + axis: `int`. The dimension to broadcast. + lengths: 0-D or 1-D integer `Tensor`. + + Returns: + A `RaggedTensorDynamicShape`. + """ + lengths = ragged_util.convert_to_int_tensor( + lengths, name='lengths', dtype=dtypes.int64) + # Check whether lengths is a scalar (for uniform dimensions) or + # vector (for ragged dimensions). + if lengths.shape.ndims is None: + raise ValueError('lengths must have a known rank.') + elif lengths.shape.ndims > 1: + raise ValueError('lengths must be a scalar or vector') + else: + lengths_is_scalar = (lengths.shape.ndims == 0) + + # Verify that the shapes are compatible. + if self.is_ragged(axis): + if lengths_is_scalar: + condition = math_ops.equal(lengths, 1) + else: + condition = math_ops.reduce_all( + math_ops.equal(lengths, self.dimension_size(axis))) + else: + axis_dim_size = self.dimension_size(axis) + if lengths_is_scalar: + condition = ( + math_ops.equal(lengths, 1) | math_ops.equal(axis_dim_size, 1) + | math_ops.equal(axis_dim_size, lengths)) + else: + condition = math_ops.equal(axis_dim_size, 1) + broadcast_err = [ + 'Unable to broadcast: dimension size mismatch in dimension', axis, + 'lengths=', lengths, 'dim_size=', + self.dimension_size(axis) + ] + broadcast_check = control_flow_ops.Assert( + condition, data=broadcast_err, summarize=10) + + with ops.control_dependencies([broadcast_check]): + # Partitioned dimensions: + if axis < self.num_partitioned_dimensions: + if self.is_ragged(axis): + # Use an identity op to make sure the check actually gets run. + return RaggedTensorDynamicShape( + self._partitioned_dim_sizes, + array_ops.identity(self.inner_dim_sizes)) + else: + return self._broadcast_uniform_partitioned_dimension(axis, lengths) + + # Inner dimensions: + else: + if lengths_is_scalar: + return self._broadcast_inner_dimension_to_uniform(axis, lengths) + else: + if axis == 0: + raise ValueError('Unable to broadcast: ' + 'outermost dimension must be uniform.') + return self._broadcast_inner_dimension_to_ragged(axis, lengths) + + def num_slices_in_dimension(self, axis): + """Returns the total number of slices across the indicated dimension.""" + if axis < 0: + return constant_op.constant(1, dtype=dtypes.int64) + elif self.is_ragged(axis): + return math_ops.reduce_sum(self._partitioned_dim_sizes[axis]) + else: + return self.dimension_size(axis) * self.num_slices_in_dimension(axis - 1) + + def _broadcast_uniform_partitioned_dimension(self, axis, lengths): + """Broadcasts the partitioned dimension `axis` to match `lengths`.""" + axis_dim_size = self.dimension_size(axis) + partitioned_sizes = list(self._partitioned_dim_sizes[:axis]) + + if lengths.shape.ndims == 0: + lengths = array_ops.where( + math_ops.equal(axis_dim_size, 1), lengths, axis_dim_size) + repeats = array_ops.where(math_ops.equal(axis_dim_size, 1), lengths, 1) + splits = array_ops.stack([0, self.num_slices_in_dimension(axis)]) + else: + splits = math_ops.range( + array_ops.size(lengths, out_type=dtypes.int64) + 1) + repeats = lengths + + partitioned_sizes.append(lengths) + + for dim_size in self._partitioned_dim_sizes[axis + 1:]: + if dim_size.shape.ndims == 0: + partitioned_sizes.append(dim_size) + splits *= dim_size + else: + partitioned_sizes.append( + ragged_util.repeat_ranges(dim_size, splits, repeats)) + splits = array_ops.gather( + ragged_util.lengths_to_splits(dim_size), splits) + inner_sizes = self._inner_dim_sizes + return RaggedTensorDynamicShape(partitioned_sizes, inner_sizes) + + def _broadcast_inner_dimension_to_uniform(self, axis, length): + """Broadcasts the inner dimension `axis` to match `lengths`.""" + dim_size = self.dimension_size(axis) + axis_in_inner_dims = axis - self.num_partitioned_dimensions + partitioned_sizes = self._partitioned_dim_sizes + inner_sizes = array_ops.concat([ + self._inner_dim_sizes[:axis_in_inner_dims], + [array_ops.where(math_ops.equal(dim_size, 1), length, dim_size)], + self._inner_dim_sizes[axis_in_inner_dims + 1:] + ], + axis=0) + return RaggedTensorDynamicShape(partitioned_sizes, inner_sizes) + + def _broadcast_inner_dimension_to_ragged(self, axis, lengths): + axis_in_inner_dims = axis - self.num_partitioned_dimensions + partitioned_sizes = ( + self._partitioned_dim_sizes + tuple([ + self._inner_dim_sizes[i] for i in range(axis_in_inner_dims) + ]) + (lengths,)) + inner_sizes = self._inner_dim_sizes[axis_in_inner_dims + 1:] + return RaggedTensorDynamicShape(partitioned_sizes, inner_sizes) + + +def broadcast_dynamic_shape(shape_x, shape_y): + """Returns the shape formed by broadcasting two shapes to be compatible. + + Args: + shape_x: A `RaggedTensorDynamicShape` + shape_y: A `RaggedTensorDynamicShape` + + Returns: + A `RaggedTensorDynamicShape`. + Raises: + ValueError: If `shape_x` and `shape_y` are not broadcast-compatible. + """ + if not isinstance(shape_x, RaggedTensorDynamicShape): + raise TypeError('shape_x must be a RaggedTensorDynamicShape') + if not isinstance(shape_y, RaggedTensorDynamicShape): + raise TypeError('shape_y must be a RaggedTensorDynamicShape') + + # Broadcast both shapes to have the same rank. + if shape_x.rank is None or shape_y.rank is None: + raise ValueError('Unable to broadcast: unknown rank') + broadcast_rank = max(shape_x.rank, shape_y.rank) + shape_x = shape_x.broadcast_to_rank(broadcast_rank) + shape_y = shape_y.broadcast_to_rank(broadcast_rank) + + # Broadcast dimensions one at a time, starting from the outermost dimension. + for axis in range(broadcast_rank): + shape_x = shape_x.broadcast_dimension(axis, shape_y.dimension_size(axis)) + shape_y = shape_y.broadcast_dimension(axis, shape_x.dimension_size(axis)) + + return shape_x + + +def broadcast_to(rt_input, shape, broadcast_inner_dimensions=True): + """Broadcasts a potentially ragged tensor to a ragged shape. + + Tiles `rt_input` as necessary to match the given shape. + + Behavior is undefined if `rt_input` is not broadcast-compatible with `shape`. + + Args: + rt_input: The potentially ragged tensor to broadcast. + shape: A `RaggedTensorDynamicShape` + broadcast_inner_dimensions: If false, then inner dimensions will not be + tiled. + + Returns: + A potentially ragged tensor whose values are taken from + `rt_input`, and whose shape matches `shape`. + """ + if not isinstance(shape, RaggedTensorDynamicShape): + raise TypeError('shape must be a RaggedTensorDynamicShape') + rt_input = ragged_factory_ops.convert_to_tensor_or_ragged_tensor(rt_input) + + # Broadcasting to a uniform shape. + if shape.num_partitioned_dimensions == 0: + return _broadcast_to_uniform_shape(rt_input, shape, + broadcast_inner_dimensions) + else: + return _broadcast_to_ragged_shape(rt_input, shape, + broadcast_inner_dimensions) + + +def _broadcast_to_uniform_shape(rt_input, shape, broadcast_inner_dimensions): + """Broadcasts rt_input to the uniform shape `shape`.""" + if isinstance(rt_input, ragged_tensor.RaggedTensor): + raise ValueError('Incompatible with shape: ragged rank mismatch') + if broadcast_inner_dimensions: + return array_ops.broadcast_to(rt_input, shape.inner_dim_sizes) + else: + return rt_input + + +def _broadcast_to_ragged_shape(rt_input, dst_shape, broadcast_inner_dimensions): + """Broadcasts rt_input to the ragged shape `dst_shape`.""" + # dst_shape's rank and ragged_rank must be greater than or equal to rt_input's + if rt_input.shape.ndims is None or dst_shape.rank is None: + raise ValueError('Unable to broadcast: unknown rank') + if rt_input.shape.ndims > dst_shape.rank: + raise ValueError('Incompatible with shape: rank mismatch') + if (isinstance(rt_input, ragged_tensor.RaggedTensor) and + rt_input.ragged_rank >= dst_shape.num_partitioned_dimensions): + raise ValueError('Incompatible with shape: ragged rank mismatch') + + src_shape = RaggedTensorDynamicShape.from_tensor(rt_input) + src_shape = src_shape.broadcast_to_rank(dst_shape.rank) + + # Add dimensions to rt_input so its rank and ragged_rank matches dst_shape. + if dst_shape.rank > rt_input.shape.ndims: + if rt_input.shape.ndims < dst_shape.num_inner_dimensions + 1: + rt_input = array_ops.reshape( + rt_input, array_ops.concat([[-1], dst_shape.inner_dim_sizes], axis=0)) + for _ in range(dst_shape.rank - rt_input.shape.ndims): + rt_input = ragged_factory_ops.from_row_lengths( + rt_input, [ragged_array_ops.nrows(rt_input)]) + + # Add ragged dimensions to match dst_shape. + if ragged_tensor.is_ragged(rt_input): + inner_rank_diff = ( + rt_input.inner_values.shape.ndims - 1 - dst_shape.num_inner_dimensions) + if inner_rank_diff > 0: + rt_input = rt_input.with_inner_values( + ragged_conversion_ops.from_tensor( + rt_input.inner_values, ragged_rank=inner_rank_diff)) + else: + rt_input = ragged_conversion_ops.from_tensor( + rt_input, ragged_rank=dst_shape.num_partitioned_dimensions - 1) + + # Do broadcasting for any dimensions that will remain uniform. We can do + # these all at once, since they're independent of one another. + multiples = [1] * dst_shape.rank + for axis in range(dst_shape.num_partitioned_dimensions): + if not src_shape.is_ragged(axis) and not dst_shape.is_ragged(axis): + src_size = src_shape.dimension_size(axis) + dst_size = dst_shape.dimension_size(axis) + if ((tensor_util.constant_value(src_size) in (1, None)) and + (tensor_util.constant_value(dst_size) != 1)): + multiples[axis] = array_ops.where( + math_ops.equal(src_size, 1), dst_size, 1) + if not all(isinstance(v, int) and v == 1 for v in multiples): + multiples = array_ops.stack(multiples, axis=0) + rt_input = ragged_array_ops.tile(rt_input, multiples) + + if broadcast_inner_dimensions: + rt_input = rt_input.with_inner_values( + array_ops.reshape( + rt_input.inner_values, + array_ops.concat([[-1], dst_shape.inner_dim_sizes], axis=0))) + + # Do broadcasting for dimensions that become ragged. We must do these from + # outermost to innermost. + for axis in range(dst_shape.num_partitioned_dimensions): + if not src_shape.is_ragged(axis) and dst_shape.is_ragged(axis): + dst_size = dst_shape.dimension_size(axis) + rt_input = _ragged_tile_axis(rt_input, axis, dst_size) + + return rt_input + + +def _ragged_tile_axis(rt_input, axis, repeats): + """Tile a dimension of a RaggedTensor to match a ragged shape.""" + assert axis > 0 # Outermost dimension may not be ragged. + + if not ragged_tensor.is_ragged(rt_input): + rt_input = ragged_conversion_ops.from_tensor(rt_input, ragged_rank=1) + + if axis > 1: + return rt_input.with_values( + _ragged_tile_axis(rt_input.values, axis - 1, repeats)) + else: + src_row_splits = rt_input.nested_row_splits + src_row_lengths = ragged_array_ops.nested_row_lengths(rt_input) + splits = src_row_splits[0] + + dst_row_lengths = [repeats] + for i in range(1, len(src_row_lengths)): + dst_row_lengths.append( + ragged_util.repeat_ranges(src_row_lengths[i], splits, repeats)) + splits = array_ops.gather(src_row_splits[i], splits) + dst_values = ragged_util.repeat_ranges(rt_input.inner_values, splits, + repeats) + return ragged_factory_ops.from_nested_row_lengths(dst_values, + dst_row_lengths) + diff --git a/tensorflow/python/ops/ragged/ragged_tensor_shape_test.py b/tensorflow/python/ops/ragged/ragged_tensor_shape_test.py new file mode 100644 index 0000000000..9c2dd26050 --- /dev/null +++ b/tensorflow/python/ops/ragged/ragged_tensor_shape_test.py @@ -0,0 +1,487 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for tf.ragged.ragged_tensor_shape.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from absl.testing import parameterized +import numpy as np + +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util +from tensorflow.python.ops import ragged +from tensorflow.python.platform import googletest + + +class RaggedTensorShapeTest(test_util.TensorFlowTestCase, + parameterized.TestCase): + + def assertShapeEq(self, x, y): + assert isinstance(x, ragged.RaggedTensorDynamicShape) + assert isinstance(y, ragged.RaggedTensorDynamicShape) + x_partitioned_dim_sizes = [ + splits.eval().tolist() # + for splits in x.partitioned_dim_sizes + ] + y_partitioned_dim_sizes = [ + splits.eval().tolist() # + for splits in y.partitioned_dim_sizes + ] + self.assertEqual(x_partitioned_dim_sizes, y_partitioned_dim_sizes) + self.assertEqual(x.inner_dim_sizes.eval().tolist(), + y.inner_dim_sizes.eval().tolist()) + + @parameterized.parameters([ + dict(value='x', expected_dim_sizes=[]), + dict(value=['a', 'b', 'c'], expected_dim_sizes=[3]), + dict(value=[['a', 'b', 'c'], ['d', 'e', 'f']], expected_dim_sizes=[2, 3]), + dict( + value=[[['a', 'b', 'c'], ['d', 'e', 'f']]], + expected_dim_sizes=[1, 2, 3]), + dict( + value=ragged.constant_value([['a', 'b', 'c'], ['d', 'e']]), + expected_dim_sizes=[2, [3, 2]]), + dict( + value=ragged.constant_value([[['a', 'b', 'c'], ['d', 'e']]]), + expected_dim_sizes=[1, [2], [3, 2]]), + dict( + value=ragged.constant_value([[['a', 'b', 'c'], ['d', 'e', 'f']]], + ragged_rank=1), + expected_dim_sizes=[1, [2], 3]), + dict( + value=ragged.constant_value([[[[1], [2]], [[3], [4]]], + [[[5], [6]]]], ragged_rank=1), + expected_dim_sizes=[2, [2, 1], 2, 1]), + dict( + value=ragged.constant_value([[10, 20], [30]]), + expected_dim_sizes=[2, [2, 1]]), + # Docstring examples: + dict(value=[[1, 2, 3], [4, 5, 6]], expected_dim_sizes=[2, 3]), + dict( + value=ragged.constant_value([[1, 2], [], [3, 4, 5]]), + expected_dim_sizes=[3, [2, 0, 3]]), + dict( + value=ragged.constant_value([[[1, 2], [3, 4]], [[5, 6]]], + ragged_rank=1), + expected_dim_sizes=[2, [2, 1], 2]), + dict( + value=ragged.constant_value([[[1, 2], [3]], [[4, 5]]]), + expected_dim_sizes=[2, [2, 1], [2, 1, 2]]), + ]) + def testFromTensor(self, value, expected_dim_sizes): + shape = ragged.RaggedTensorDynamicShape.from_tensor(value) + expected = ragged.RaggedTensorDynamicShape.from_dim_sizes( + expected_dim_sizes) + with self.cached_session(): + self.assertShapeEq(shape, expected) + + @parameterized.parameters([ + dict(dim_sizes=[], rank=0, expected_dim_sizes=[]), + dict(dim_sizes=[], rank=3, expected_dim_sizes=[1, 1, 1]), + dict(dim_sizes=[3], rank=1, expected_dim_sizes=[3]), + dict(dim_sizes=[3], rank=3, expected_dim_sizes=[1, 1, 3]), + dict(dim_sizes=[2, 3], rank=3, expected_dim_sizes=[1, 2, 3]), + dict(dim_sizes=[3, [3, 2, 4]], rank=2, expected_dim_sizes=[3, [3, 2, 4]]), + dict( + dim_sizes=[3, [3, 2, 4]], + rank=4, + expected_dim_sizes=[1, 1, 3, [3, 2, 4]]), + dict( + dim_sizes=[3, [3, 2, 4], 2, 3], + rank=5, + expected_dim_sizes=[1, 3, [3, 2, 4], 2, 3]), + ]) + def testBroadcastToRank(self, dim_sizes, rank, expected_dim_sizes): + shape = ragged.RaggedTensorDynamicShape.from_dim_sizes(dim_sizes) + expected = ragged.RaggedTensorDynamicShape.from_dim_sizes( + expected_dim_sizes) + broadcasted_shape = shape.broadcast_to_rank(rank) + with self.cached_session(): + self.assertShapeEq(broadcasted_shape, expected) + self.assertEqual(broadcasted_shape.rank, rank) + + @parameterized.parameters([ + #========================================================================= + # dimension[axis] is uniform inner; and row_lengths is a scalar + #========================================================================= + # shape: [BROADCAST(UNIFORM), UNIFORM, UNIFORM] + dict(axis=0, + row_length=3, + original_dim_sizes=[1, 4, 5], + broadcast_dim_sizes=[3, 4, 5]), + + # shape: [UNIFORM, UNIFORM, BROADCAST(UNIFORM)] + dict(axis=2, + row_length=5, + original_dim_sizes=[3, 4, 1], + broadcast_dim_sizes=[3, 4, 5]), + + # shape: [UNIFORM, RAGGED, BROADCAST(UNIFORM)] + dict(axis=2, + row_length=5, + original_dim_sizes=[3, [3, 2, 8], 1], + broadcast_dim_sizes=[3, [3, 2, 8], 5]), + + # shape: [UNIFORM, RAGGED, RAGGED, UNIFORM, UNIFORM, BROADCAST(UNIFORM)] + dict(axis=5, + row_length=5, + original_dim_sizes=[2, [2, 1], [3, 2, 8], 3, 4, 1], + broadcast_dim_sizes=[2, [2, 1], [3, 2, 8], 3, 4, 5]), + + #========================================================================= + # dimension[axis] is uniform inner; and row_lengths is a vector + #========================================================================= + # shape: [UNIFORM, BROADCAST(UNIFORM)] + dict(axis=1, + row_length=[2, 0, 1], + original_dim_sizes=[3, 1], + broadcast_dim_sizes=[3, [2, 0, 1]]), + # shape: [UNIFORM, BROADCAST(UNIFORM), UNIFORM] + dict(axis=1, + row_length=[2, 0, 1], + original_dim_sizes=[3, 1, 5], + broadcast_dim_sizes=[3, [2, 0, 1], 5]), + + # shape: [UNIFORM, UNIFORM, BROADCAST(UNIFORM)] + dict(axis=2, + row_length=[2, 0, 1, 3, 8, 2, 3, 4, 1, 8, 7, 0], + original_dim_sizes=[4, 3, 1], + broadcast_dim_sizes=[4, 3, [2, 0, 1, 3, 8, 2, 3, 4, 1, 8, 7, 0]]), + + # shape: [UNIFORM, RAGGED, BROADCAST(UNIFORM)] + dict(axis=2, + row_length=[2, 5, 3], + original_dim_sizes=[2, [2, 1], 1], + broadcast_dim_sizes=[2, [2, 1], [2, 5, 3]]), + + # shape: [UNIFORM, RAGGED, UNIFORM, UNIFORM, BROADCAST(UNIFORM), UNIFORM] + dict(axis=4, + row_length=list(range(18)), + original_dim_sizes=[2, [2, 1], 3, 2, 1, 8], + broadcast_dim_sizes=[2, [2, 1], 3, 2, list(range(18)), 8]), + + #========================================================================= + # dimension[axis] is uniform partitioned; and row_lengths is a scalar + #========================================================================= + # shape: [BROADCAST(UNIFORM), RAGGED] + dict(axis=0, + row_length=3, + original_dim_sizes=[1, [5]], + broadcast_dim_sizes=[3, [5, 5, 5]]), + + # shape: [BROADCAST(UNIFORM), UNIFORM, RAGGED] + dict(axis=0, + row_length=2, + original_dim_sizes=[1, 3, [3, 0, 2]], + broadcast_dim_sizes=[2, 3, [3, 0, 2, 3, 0, 2]]), + + # shape: [BROADCAST(UNIFORM), RAGGED, RAGGED, UNIFORM, UNIFORM] + dict(axis=0, + row_length=3, + original_dim_sizes=[1, [3], [3, 5, 2], 9, 4, 5], + broadcast_dim_sizes=[3, [3, 3, 3], [3, 5, 2, 3, 5, 2, 3, 5, 2], + 9, 4, 5]), + + # shape: [BROADCAST(UNIFORM), UNIFORM, RAGGED, UNIFORM] + dict(axis=0, + row_length=2, + original_dim_sizes=[1, 2, [2, 1], [3, 5, 2], 2], + broadcast_dim_sizes=[2, 2, [2, 1, 2, 1], [3, 5, 2, 3, 5, 2], 2]), + + # shape: [UNIFORM, BROADCAST(UNIFORM), RAGGED, UNIFORM] + dict(axis=1, + row_length=2, + original_dim_sizes=[3, 1, [4, 0, 2], 5], + broadcast_dim_sizes=[3, 2, [4, 0, 2, 4, 0, 2], 5]), + + # shape: [UNIFORM, BROADCAST(UNIFORM), RAGGED] + dict(axis=1, + row_length=1, + original_dim_sizes=[2, 3, (1, 2, 3, 4, 5, 6)], + broadcast_dim_sizes=[2, 3, (1, 2, 3, 4, 5, 6)]), + + #========================================================================= + # dimension[axis] is uniform partitioned; and row_lengths is a vector + #========================================================================= + # shape: [UNIFORM, BROADCAST(UNIFORM), RAGGED, UNIFORM] + dict(axis=1, + row_length=[4, 1, 2], + original_dim_sizes=[ + 3, # axis=0 + 1, # axis=1 (broadcast) + [3, 1, 2], # axis=2 + 5], # axis=3 + broadcast_dim_sizes=[ + 3, # axis=0 + [4, 1, 2], # axis=1 (broadcast) + [3, 3, 3, 3, 1, 2, 2], # axis=2 + 5]), # axis=3 + + # shape: [UNIFORM, BROADCAST(UNIFORM), RAGGED, RAGGED] + dict(axis=1, + row_length=[2, 0, 3], + original_dim_sizes=[ + 3, # axis=0 + 1, # axis=1 (broadcast) + [3, 1, 2], # axis=2 + [3, 1, 4, 1, 5, 9]], # axis=3 + broadcast_dim_sizes=[ + 3, # axis=0 + [2, 0, 3], # axis=1 (broadcast) + [3, 3, 2, 2, 2], # axis=2 + [3, 1, 4, 3, 1, 4, 5, 9, 5, 9, 5, 9]]), # axis=3 + + # shape: [UNIFORM, RAGGED, BROADCAST(UNIFORM), RAGGED, RAGGED, UNIFORM] + dict(axis=2, + row_length=[4, 1, 2], + original_dim_sizes=[ + 3, # axis=0 + [2, 0, 1], # axis=1 + 1, # axis=2 (broadcast) + [3, 2, 1], # axis=3 + [1, 0, 1, 0, 2, 3], # axis=4 + 5], # axis=5 + broadcast_dim_sizes=[ + 3, # axis=0 + [2, 0, 1], # axis=2 + [4, 1, 2], # axis=2 (broadcast) + [3, 3, 3, 3, 2, 1, 1], # axis=3 + [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, # axis=4 + 2, 3, 3], + 5]), # axis=5 + + dict(axis=0, + row_length=2, + original_dim_sizes=[1, 1, 2, (2, 1)], + broadcast_dim_sizes=[2, 1, 2, (2, 1, 2, 1)]), + dict(axis=1, + row_length=(2, 1), + original_dim_sizes=[2, 1, 2, (2, 1, 2, 1)], + broadcast_dim_sizes=[2, (2, 1), 2, (2, 1, 2, 1, 2, 1)]), + dict(axis=2, + row_length=2, + original_dim_sizes=[2, (2, 1), 2, (2, 1, 2, 1, 2, 1)], + broadcast_dim_sizes=[2, (2, 1), 2, (2, 1, 2, 1, 2, 1)]), + dict(axis=3, + row_length=(2, 1, 2, 1, 2, 1), + original_dim_sizes=[2, (2, 1), 2, 1], + broadcast_dim_sizes=[2, (2, 1), 2, (2, 1, 2, 1, 2, 1)]), + ]) # pyformat: disable + def testBroadcastDimension(self, axis, row_length, original_dim_sizes, + broadcast_dim_sizes): + """Tests for the broadcast_dimension method. + + Verifies that: + + * `original.broadcast_dimension(axis, row_length) == broadcast` + * `broadcast.broadcast_dimension(axis, row_length) == broadcast` + * `broadcast.broadcast_dimension(axis, 1) == broadcast` + + Args: + axis: The axis to broadcast + row_length: The slice lengths to broadcast to. + original_dim_sizes: The dimension sizes before broadcasting. + original_dim_sizes[axis] should be equal to `1` or `row_length`. + broadcast_dim_sizes: THe dimension sizes after broadcasting. + """ + original_shape = ragged.RaggedTensorDynamicShape.from_dim_sizes( + original_dim_sizes) + broadcast_shape = ragged.RaggedTensorDynamicShape.from_dim_sizes( + broadcast_dim_sizes) + self.assertEqual(original_shape.rank, broadcast_shape.rank) + with self.cached_session(): + # shape[axis].value == 1 and row_length > 1: + bcast1 = original_shape.broadcast_dimension(axis, row_length) + # shape[axis].value > 1 and row_length == shape[axis].value: + bcast2 = broadcast_shape.broadcast_dimension(axis, row_length) + # shape[axis].value > 1 and row_length == 1: + bcast3 = broadcast_shape.broadcast_dimension(axis, 1) + + self.assertShapeEq(bcast1, broadcast_shape) + self.assertShapeEq(bcast2, broadcast_shape) + self.assertShapeEq(bcast3, broadcast_shape) + + @parameterized.parameters( + [ + # Broadcast scalar + dict(x_dims=[], y_dims=[], expected_dims=[]), + dict(x_dims=[], y_dims=[2], expected_dims=[2]), + dict(x_dims=[], y_dims=[2, 3], expected_dims=[2, 3]), + dict( + x_dims=[], + y_dims=[2, (2, 3), (5, 7, 2, 0, 9)], + expected_dims=[2, (2, 3), (5, 7, 2, 0, 9)]), + # Broadcast vector + dict(x_dims=[3], y_dims=[4, 2, 3], expected_dims=[4, 2, 3]), + dict(x_dims=[1], y_dims=[4, 2, 3], expected_dims=[4, 2, 3]), + dict(x_dims=[3], y_dims=[4, 2, 1], expected_dims=[4, 2, 3]), + dict( + x_dims=[3], + y_dims=[3, (2, 3, 1), 1], + expected_dims=[3, (2, 3, 1), 3]), + dict(x_dims=[1], y_dims=[3, (2, 1, 3)], expected_dims=[3, (2, 1, 3)]), + dict( + x_dims=[1], + y_dims=[3, (2, 1, 3), 8], + expected_dims=[3, (2, 1, 3), 8]), + dict( + x_dims=[1], + y_dims=[2, (2, 3), (5, 7, 2, 0, 9)], + expected_dims=[2, (2, 3), (5, 7, 2, 0, 9)]), + # Mixed broadcasting + dict( + x_dims=[ + 1, # axis=0 + 3, # axis=1 + (3, 0, 2), # axis=2 + 1, # axis=3 + 2, # axis=4 + ], + y_dims=[ + 2, # axis=0 + 1, # axis=1 + 1, # axis=2 + (7, 2), # axis=3 + 1, # axis=4 + ], + expected_dims=[ + 2, # axis=0 + 3, # axis=1 + (3, 0, 2, 3, 0, 2), # axis=2 + (7, 7, 7, 7, 7, 2, 2, 2, 2, 2), # axis=3 + 2, # axis=4 + ]), + dict( + x_dims=[2, (2, 1), 2, 1], + y_dims=[1, 1, 2, (2, 1)], + expected_dims=[2, (2, 1), 2, (2, 1, 2, 1, 2, 1)]), + ]) + def testBroadcastDynamicShape(self, x_dims, y_dims, expected_dims): + x_shape = ragged.RaggedTensorDynamicShape.from_dim_sizes(x_dims) + y_shape = ragged.RaggedTensorDynamicShape.from_dim_sizes(y_dims) + expected = ragged.RaggedTensorDynamicShape.from_dim_sizes(expected_dims) + result1 = ragged.broadcast_dynamic_shape(x_shape, y_shape) + result2 = ragged.broadcast_dynamic_shape(y_shape, x_shape) + with self.cached_session(): + self.assertShapeEq(expected, result1) + self.assertShapeEq(expected, result2) + + def testRepr(self): + shape = ragged.RaggedTensorDynamicShape.from_dim_sizes([2, (2, 1), 2, 1]) + self.assertRegexpMatches( + repr(shape), + r'RaggedTensorDynamicShape\(' + r'partitioned_dim_sizes=\(<[^>]+>, <[^>]+>\), ' + r'inner_dim_sizes=<[^>]+>\)') + + @parameterized.parameters([ + dict( + x=[[10], [20], [30]], # shape=[3, 1] + dim_sizes=[3, 2], + expected=[[10, 10], [20, 20], [30, 30]]), + dict( + x=[[10], [20], [30]], # shape=[3, 1] + dim_sizes=[3, [3, 0, 2]], + expected=ragged.constant_value([[10, 10, 10], [], [30, 30]], + dtype=np.int32)), + dict( + x=[[[1, 2, 3]], [[4, 5, 6]]], # shape = [2, 1, 3] + dim_sizes=[2, [2, 3], 3], + expected=ragged.constant_value( + [[[1, 2, 3], [1, 2, 3]], [[4, 5, 6], [4, 5, 6], [4, 5, 6]]], + dtype=np.int32, + ragged_rank=1)), + dict( + x=[[[1]], [[2]]], # shape = [2, 1, 1] + dim_sizes=[2, [2, 3], [0, 2, 1, 2, 0]], + expected=ragged.constant_value([[[], [1, 1]], [[2], [2, 2], []]], + dtype=np.int32, + ragged_rank=2)), + dict( + x=10, + dim_sizes=[3, [3, 0, 2]], + expected=ragged.constant_value([[10, 10, 10], [], [10, 10]])), + ]) + def testRaggedBroadcastTo(self, x, dim_sizes, expected): + shape = ragged.RaggedTensorDynamicShape.from_dim_sizes(dim_sizes) + result = ragged.broadcast_to(x, shape) + with self.cached_session(): + self.assertEqual( + getattr(result, 'ragged_rank', 0), getattr(expected, 'ragged_rank', + 0)) + if hasattr(expected, 'tolist'): + expected = expected.tolist() + self.assertEqual(result.eval().tolist(), expected) + + @parameterized.parameters([ + dict( + doc='x.shape=[3, (D1)]; y.shape=[3, 1]; bcast.shape=[3, (D1)]', + x=ragged.constant_value([[1, 2, 3], [], [4, 5]], dtype=np.int32), + y=[[10], [20], [30]], + expected=ragged.constant_value([[11, 12, 13], [], [34, 35]])), + dict( + doc='x.shape=[3, (D1)]; y.shape=[]; bcast.shape=[3, (D1)]', + x=ragged.constant_value([[1, 2, 3], [], [4, 5]], dtype=np.int32), + y=10, + expected=ragged.constant_value([[11, 12, 13], [], [14, 15]])), + dict( + doc='x.shape=[1, (D1)]; y.shape=[3, 1]; bcast.shape=[3, (D1)]', + x=ragged.constant_value([[1, 2, 3]], dtype=np.int32), + y=[[10], [20], [30]], + expected=ragged.constant_value( + [[11, 12, 13], [21, 22, 23], [31, 32, 33]], dtype=np.int32)), + dict( + doc=('x.shape=[2, (D1), 1]; y.shape=[1, (D2)]; ' + 'bcast.shape=[2, (D1), (D2)]'), + x=ragged.constant_value([[[1], [2], [3]], [[4]]], ragged_rank=1), + y=ragged.constant_value([[10, 20, 30]]), + expected=ragged.constant_value([[[11, 21, 31], [12, 22, 32], + [13, 23, 33]], [[14, 24, 34]]])), + dict( + doc=('x.shape=[2, (D1), 1]; y.shape=[1, 1, 4]; ' + 'bcast.shape=[2, (D1), 4]'), + x=ragged.constant_value([[[10], [20]], [[30]]], ragged_rank=1), + y=[[[1, 2, 3, 4]]], + expected=ragged.constant_value( + [[[11, 12, 13, 14], [21, 22, 23, 24]], [[31, 32, 33, 34]]], + ragged_rank=1)), + dict( + doc=('x.shape=[2, (D1), 2, 1]; y.shape=[2, (D2)]; ' + 'bcast.shape=[2, (D1), (2), (D2)'), + x=ragged.constant_value([[[[1], [2]], [[3], [4]]], + [[[5], [6]]]], + ragged_rank=1), + y=ragged.constant_value([[10, 20], [30]]), + expected=ragged.constant_value( + [[[[11, 21], [32]], [[13, 23], [34]]], + [[[15, 25], [36]]]])), + ]) + def testRaggedAddWithBroadcasting(self, x, y, expected, doc): + expected_rrank = getattr(expected, 'ragged_rank', 0) + x = ragged.convert_to_tensor_or_ragged_tensor(x, dtype=dtypes.int32) + y = ragged.convert_to_tensor_or_ragged_tensor(y, dtype=dtypes.int32) + result = x + y + result_rrank = getattr(result, 'ragged_rank', 0) + self.assertEqual(expected_rrank, result_rrank) + if hasattr(expected, 'tolist'): + expected = expected.tolist() + with self.cached_session(): + self.assertEqual(result.eval().tolist(), expected) + + +if __name__ == '__main__': + googletest.main() diff --git a/tensorflow/python/ops/ragged/ragged_tensor_test.py b/tensorflow/python/ops/ragged/ragged_tensor_test.py index 61bfcb6809..608fbd6e5b 100644 --- a/tensorflow/python/ops/ragged/ragged_tensor_test.py +++ b/tensorflow/python/ops/ragged/ragged_tensor_test.py @@ -114,13 +114,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): # RaggedTensor class docstring examples #============================================================================= + @test_util.run_deprecated_v1 def testClassDocStringExamples(self): # From section: "Component Tensors" rt = ragged.from_row_splits( values=[3, 1, 4, 1, 5, 9, 2, 6], row_splits=[0, 4, 4, 7, 8, 8]) - with self.test_session(): - self.assertEqual(rt.tolist(), - [[3, 1, 4, 1], [], [5, 9, 2], [6], []]) + self.assertEqual( + self.evaluate(rt).tolist(), [[3, 1, 4, 1], [], [5, 9, 2], [6], []]) del rt # From section: "Alternative Row-Partitioning Schemes" @@ -132,9 +132,8 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt4 = ragged.from_row_starts(values, row_starts=[0, 4, 4, 7, 8]) rt5 = ragged.from_row_limits(values, row_limits=[4, 4, 7, 8, 8]) for rt in (rt1, rt2, rt3, rt4, rt5): - with self.test_session(): - self.assertEqual(rt.tolist(), - [[3, 1, 4, 1], [], [5, 9, 2], [6], []]) + self.assertEqual( + self.evaluate(rt).tolist(), [[3, 1, 4, 1], [], [5, 9, 2], [6], []]) del rt1, rt2, rt3, rt4, rt5 # From section: "Multiple Ragged Dimensions" @@ -142,28 +141,27 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): values=[3, 1, 4, 1, 5, 9, 2, 6], row_splits=[0, 4, 4, 7, 8, 8]) outer_rt = ragged.from_row_splits(values=inner_rt, row_splits=[0, 3, 3, 5]) self.assertEqual(outer_rt.ragged_rank, 2) - with self.test_session(): - self.assertEqual(outer_rt.tolist(), - [[[3, 1, 4, 1], [], [5, 9, 2]], [], [[6], []]]) + self.assertEqual( + self.evaluate(outer_rt).tolist(), + [[[3, 1, 4, 1], [], [5, 9, 2]], [], [[6], []]]) del inner_rt, outer_rt # From section: "Multiple Ragged Dimensions" rt = ragged.from_nested_row_splits( inner_values=[3, 1, 4, 1, 5, 9, 2, 6], nested_row_splits=([0, 3, 3, 5], [0, 4, 4, 7, 8, 8])) - with self.test_session(): - self.assertEqual(rt.tolist(), - [[[3, 1, 4, 1], [], [5, 9, 2]], [], [[6], []]]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[[3, 1, 4, 1], [], [5, 9, 2]], [], [[6], []]]) del rt # From section: "Uniform Inner Dimensions" rt = ragged.from_row_splits( values=array_ops.ones([5, 3]), row_splits=[0, 2, 5]) - with self.test_session(): - self.assertEqual( - rt.tolist(), - [[[1, 1, 1], [1, 1, 1]], [[1, 1, 1], [1, 1, 1], [1, 1, 1]]]) - self.assertEqual(rt.shape.as_list(), [2, None, 3]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[[1, 1, 1], [1, 1, 1]], [[1, 1, 1], [1, 1, 1], [1, 1, 1]]]) + self.assertEqual(rt.shape.as_list(), [2, None, 3]) del rt #============================================================================= @@ -202,15 +200,16 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): # RaggedTensor Constructor (private) #============================================================================= + @test_util.run_deprecated_v1 def testRaggedTensorConstruction(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) row_splits = constant_op.constant([0, 2, 2, 5, 6, 7], dtypes.int64) rt = ragged.RaggedTensor( values=values, row_splits=row_splits, internal=True) - with self.test_session(): - self.assertEqual(rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) def testRaggedTensorConstructionErrors(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) @@ -246,6 +245,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): # RaggedTensor Factory Ops #============================================================================= + @test_util.run_deprecated_v1 def testFromValueRowIdsWithDerivedNRows(self): # nrows is known at graph creation time. values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) @@ -262,12 +262,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertIs(rt_values, values) self.assertIs(rt_value_rowids, value_rowids) # cached_value_rowids - with self.test_session(): - self.assertAllEqual(rt_value_rowids, value_rowids) - self.assertEqual(rt_nrows.eval(), 5) - self.assertEqual(rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertAllEqual(rt_value_rowids, value_rowids) + self.assertEqual(self.evaluate(rt_nrows), 5) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + @test_util.run_deprecated_v1 def testFromValueRowIdsWithDerivedNRowsDynamic(self): # nrows is not known at graph creation time. values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) @@ -285,12 +286,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertIs(rt_values, values) self.assertIs(rt_value_rowids, value_rowids) # cached_value_rowids - with self.test_session(): - self.assertAllEqual(rt_value_rowids, value_rowids) - self.assertEqual(rt_nrows.eval(), 5) - self.assertEqual(rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertAllEqual(rt_value_rowids, value_rowids) + self.assertEqual(self.evaluate(rt_nrows), 5) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + @test_util.run_deprecated_v1 def testFromValueRowIdsWithExplicitNRows(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) value_rowids = constant_op.constant([0, 0, 2, 2, 2, 3, 4], dtypes.int64) @@ -308,11 +310,11 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertIs(rt_values, values) self.assertIs(rt_value_rowids, value_rowids) # cached_value_rowids self.assertIs(rt_nrows, nrows) # cached_nrows - with self.test_session(): - self.assertEqual( - rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g'], [], []]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g'], [], []]) + @test_util.run_deprecated_v1 def testFromValueRowIdsWithExplicitNRowsEqualToDefault(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) value_rowids = constant_op.constant([0, 0, 2, 2, 2, 3, 4], dtypes.int64) @@ -330,12 +332,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertIs(rt_values, values) self.assertIs(rt_value_rowids, value_rowids) # cached_value_rowids self.assertIs(rt_nrows, nrows) # cached_nrows - with self.test_session(): - self.assertAllEqual(rt_value_rowids, value_rowids) - self.assertAllEqual(rt_nrows, nrows) - self.assertEqual(rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertAllEqual(rt_value_rowids, value_rowids) + self.assertAllEqual(rt_nrows, nrows) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + @test_util.run_deprecated_v1 def testFromValueRowIdsWithEmptyValues(self): rt = ragged.from_value_rowids([], []) rt_nrows = ragged.nrows(rt) @@ -344,10 +347,10 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertEqual(rt.ragged_rank, 1) self.assertEqual(rt.values.shape.as_list(), [0]) self.assertEqual(ragged.value_rowids(rt).shape.as_list(), [0]) - with self.test_session(): - self.assertEqual(rt_nrows.eval().tolist(), 0) - self.assertEqual(rt.tolist(), []) + self.assertEqual(self.evaluate(rt_nrows).tolist(), 0) + self.assertEqual(self.evaluate(rt).tolist(), []) + @test_util.run_deprecated_v1 def testFromRowSplits(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) row_splits = constant_op.constant([0, 2, 2, 5, 6, 7], dtypes.int64) @@ -363,16 +366,17 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertIs(rt_values, values) self.assertIs(rt_row_splits, row_splits) - with self.test_session(): - self.assertEqual(rt_nrows.eval(), 5) - self.assertEqual(rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertEqual(self.evaluate(rt_nrows), 5) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) def testFromRowSplitsWithEmptySplits(self): err_msg = 'row_splits tensor may not be empty' with self.assertRaisesRegexp(ValueError, err_msg): ragged.from_row_splits([], []) + @test_util.run_deprecated_v1 def testFromRowStarts(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) row_starts = constant_op.constant([0, 2, 2, 5, 6], dtypes.int64) @@ -387,12 +391,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt_nrows = ragged.nrows(rt) self.assertIs(rt_values, values) - with self.test_session(): - self.assertEqual(rt_nrows.eval(), 5) - self.assertAllEqual(rt_row_starts, row_starts) - self.assertEqual(rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertEqual(self.evaluate(rt_nrows), 5) + self.assertAllEqual(rt_row_starts, row_starts) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + @test_util.run_deprecated_v1 def testFromRowLimits(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) row_limits = constant_op.constant([2, 2, 5, 6, 7], dtypes.int64) @@ -407,12 +412,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt_nrows = ragged.nrows(rt) self.assertIs(rt_values, values) - with self.test_session(): - self.assertEqual(rt_nrows.eval(), 5) - self.assertAllEqual(rt_row_limits, row_limits) - self.assertEqual(rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertEqual(self.evaluate(rt_nrows), 5) + self.assertAllEqual(rt_row_limits, row_limits) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + @test_util.run_deprecated_v1 def testFromRowLengths(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) row_lengths = constant_op.constant([2, 0, 3, 1, 1], dtypes.int64) @@ -428,12 +434,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertIs(rt_values, values) self.assertIs(rt_row_lengths, row_lengths) # cached_nrows - with self.test_session(): - self.assertEqual(rt_nrows.eval(), 5) - self.assertAllEqual(rt_row_lengths, row_lengths) - self.assertEqual(rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertEqual(self.evaluate(rt_nrows), 5) + self.assertAllEqual(rt_row_lengths, row_lengths) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + @test_util.run_deprecated_v1 def testFromNestedValueRowIdsWithDerivedNRows(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) nested_value_rowids = [ @@ -452,13 +459,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt_values_value_rowids = ragged.value_rowids(rt_values) self.assertIs(rt_values_values, values) - with self.test_session(): - self.assertAllEqual(rt_value_rowids, nested_value_rowids[0]) - self.assertAllEqual(rt_values_value_rowids, nested_value_rowids[1]) - self.assertEqual( - rt.tolist(), - [[[b'a', b'b'], []], [[b'c', b'd', b'e']], [], [[b'f'], [b'g']]]) + self.assertAllEqual(rt_value_rowids, nested_value_rowids[0]) + self.assertAllEqual(rt_values_value_rowids, nested_value_rowids[1]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[[b'a', b'b'], []], [[b'c', b'd', b'e']], [], [[b'f'], [b'g']]]) + @test_util.run_deprecated_v1 def testFromNestedValueRowIdsWithExplicitNRows(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) nested_value_rowids = [ @@ -483,14 +490,14 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt_values_nrows = ragged.nrows(rt_values) self.assertIs(rt_values_values, values) - with self.test_session(): - self.assertAllEqual(rt_value_rowids, nested_value_rowids[0]) - self.assertAllEqual(rt_values_value_rowids, nested_value_rowids[1]) - self.assertAllEqual(rt_nrows, nrows[0]) - self.assertAllEqual(rt_values_nrows, nrows[1]) - self.assertEqual(rt.tolist(), - [[[b'a', b'b'], []], [[b'c', b'd', b'e']], [], - [[b'f'], [b'g'], []], [], []]) + self.assertAllEqual(rt_value_rowids, nested_value_rowids[0]) + self.assertAllEqual(rt_values_value_rowids, nested_value_rowids[1]) + self.assertAllEqual(rt_nrows, nrows[0]) + self.assertAllEqual(rt_values_nrows, nrows[1]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[[b'a', b'b'], []], [[b'c', b'd', b'e']], [], [[b'f'], [b'g'], []], [], + []]) def testFromNestedValueRowIdsWithExplicitNRowsMismatch(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) @@ -515,6 +522,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): ragged.from_nested_value_rowids([1, 2, 3], [[0, 1, 2], [0, 1, 2]], constant_op.constant([3, 3])) + @test_util.run_deprecated_v1 def testFromNestedRowSplits(self): inner_values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) nested_row_splits = [ @@ -535,10 +543,9 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertIs(rt_values_values, inner_values) self.assertIs(rt_row_splits, nested_row_splits[0]) self.assertIs(rt_values_row_splits, nested_row_splits[1]) - with self.test_session(): - self.assertEqual( - rt.tolist(), - [[[b'a', b'b'], []], [[b'c', b'd', b'e']], [], [[b'f'], [b'g']]]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[[b'a', b'b'], []], [[b'c', b'd', b'e']], [], [[b'f'], [b'g']]]) def testFromNestedRowSplitsWithNonListInput(self): with self.assertRaisesRegexp(TypeError, @@ -583,6 +590,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): value_rowids=value_rowids, nrows=array_ops.expand_dims(nrows, 0)) + @test_util.run_deprecated_v1 def testGraphMismatch(self): with ops.Graph().as_default(): values = constant_op.constant([1, 2, 3]) @@ -595,6 +603,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): # Ragged Value & Row-Partitioning Tensor Accessors #============================================================================= + @test_util.run_deprecated_v1 def testRaggedTensorAccessors_2d(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) row_splits = constant_op.constant([0, 2, 2, 5, 6, 7], dtypes.int64) @@ -603,25 +612,33 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt2 = ragged.from_value_rowids(values, value_rowids) for rt in [rt1, rt2]: - with self.test_session(): - self.assertEqual(rt.tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) - self.assertEqual(rt.values.eval().tolist(), - [b'a', b'b', b'c', b'd', b'e', b'f', b'g']) - self.assertEqual(rt.values.shape.dims[0].value, 7) - self.assertEqual( - ragged.value_rowids(rt).eval().tolist(), [0, 0, 2, 2, 2, 3, 4]) - self.assertEqual(ragged.nrows(rt).eval().tolist(), 5) - self.assertEqual(rt.row_splits.eval().tolist(), [0, 2, 2, 5, 6, 7]) - self.assertEqual(ragged.row_starts(rt).eval().tolist(), [0, 2, 2, 5, 6]) - self.assertEqual(ragged.row_limits(rt).eval().tolist(), [2, 2, 5, 6, 7]) - self.assertEqual( - ragged.row_lengths(rt).eval().tolist(), [2, 0, 3, 1, 1]) - self.assertEqual(rt.inner_values.eval().tolist(), - [b'a', b'b', b'c', b'd', b'e', b'f', b'g']) - self.assertEqual([s.eval().tolist() for s in rt.nested_row_splits], - [[0, 2, 2, 5, 6, 7]]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertEqual( + self.evaluate(rt.values).tolist(), + [b'a', b'b', b'c', b'd', b'e', b'f', b'g']) + self.assertEqual(rt.values.shape.dims[0].value, 7) + self.assertEqual( + self.evaluate(ragged.value_rowids(rt)).tolist(), + [0, 0, 2, 2, 2, 3, 4]) + self.assertEqual(self.evaluate(ragged.nrows(rt)).tolist(), 5) + self.assertEqual( + self.evaluate(rt.row_splits).tolist(), [0, 2, 2, 5, 6, 7]) + self.assertEqual( + self.evaluate(ragged.row_starts(rt)).tolist(), [0, 2, 2, 5, 6]) + self.assertEqual( + self.evaluate(ragged.row_limits(rt)).tolist(), [2, 2, 5, 6, 7]) + self.assertEqual( + self.evaluate(ragged.row_lengths(rt)).tolist(), [2, 0, 3, 1, 1]) + self.assertEqual( + self.evaluate(rt.inner_values).tolist(), + [b'a', b'b', b'c', b'd', b'e', b'f', b'g']) + self.assertEqual( + [self.evaluate(s).tolist() for s in rt.nested_row_splits], + [[0, 2, 2, 5, 6, 7]]) + @test_util.run_deprecated_v1 def testRaggedTensorAccessors_3d_with_ragged_rank_1(self): values = [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]] row_splits = constant_op.constant([0, 2, 2, 5, 6, 7], dtypes.int64) @@ -630,28 +647,34 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt2 = ragged.from_value_rowids(values, value_rowids) for rt in [rt1, rt2]: - with self.test_session(): - self.assertEqual(rt.tolist(), - [[[0, 1], [2, 3]], [], [[4, 5], [6, 7], [8, 9]], - [[10, 11]], [[12, 13]]]) - self.assertEqual( - rt.values.eval().tolist(), - [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]]) - self.assertEqual(rt.values.shape.dims[0].value, 7) - self.assertEqual( - ragged.value_rowids(rt).eval().tolist(), [0, 0, 2, 2, 2, 3, 4]) - self.assertEqual(ragged.nrows(rt).eval().tolist(), 5) - self.assertEqual(rt.row_splits.eval().tolist(), [0, 2, 2, 5, 6, 7]) - self.assertEqual(ragged.row_starts(rt).eval().tolist(), [0, 2, 2, 5, 6]) - self.assertEqual(ragged.row_limits(rt).eval().tolist(), [2, 2, 5, 6, 7]) - self.assertEqual( - ragged.row_lengths(rt).eval().tolist(), [2, 0, 3, 1, 1]) - self.assertEqual( - rt.inner_values.eval().tolist(), - [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]]) - self.assertEqual([s.eval().tolist() for s in rt.nested_row_splits], - [[0, 2, 2, 5, 6, 7]]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[[0, 1], [2, 3]], [], [[4, 5], [6, 7], [8, 9]], [[10, 11]], + [[12, 13]]]) + self.assertEqual( + self.evaluate(rt.values).tolist(), + [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]]) + self.assertEqual(rt.values.shape.dims[0].value, 7) + self.assertEqual( + self.evaluate(ragged.value_rowids(rt)).tolist(), + [0, 0, 2, 2, 2, 3, 4]) + self.assertEqual(self.evaluate(ragged.nrows(rt)).tolist(), 5) + self.assertEqual( + self.evaluate(rt.row_splits).tolist(), [0, 2, 2, 5, 6, 7]) + self.assertEqual( + self.evaluate(ragged.row_starts(rt)).tolist(), [0, 2, 2, 5, 6]) + self.assertEqual( + self.evaluate(ragged.row_limits(rt)).tolist(), [2, 2, 5, 6, 7]) + self.assertEqual( + self.evaluate(ragged.row_lengths(rt)).tolist(), [2, 0, 3, 1, 1]) + self.assertEqual( + self.evaluate(rt.inner_values).tolist(), + [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13]]) + self.assertEqual( + [self.evaluate(s).tolist() for s in rt.nested_row_splits], + [[0, 2, 2, 5, 6, 7]]) + @test_util.run_deprecated_v1 def testRaggedTensorAccessors_3d_with_ragged_rank_2(self): values = constant_op.constant(['a', 'b', 'c', 'd', 'e', 'f', 'g']) nested_row_splits = [ @@ -666,41 +689,45 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt2 = ragged.from_nested_value_rowids(values, nested_value_rowids) for rt in [rt1, rt2]: - with self.test_session(): - self.assertEqual( - rt.tolist(), - [[[b'a', b'b'], []], [[b'c', b'd', b'e']], [], [[b'f'], [b'g']]]) - self.assertEqual(rt.values.eval().tolist(), - [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) - self.assertEqual(rt.values.shape.dims[0].value, 5) - self.assertEqual( - ragged.value_rowids(rt).eval().tolist(), [0, 0, 1, 3, 3]) - self.assertEqual(ragged.nrows(rt).eval().tolist(), 4) - self.assertEqual(rt.row_splits.eval().tolist(), [0, 2, 3, 3, 5]) - self.assertEqual(ragged.row_starts(rt).eval().tolist(), [0, 2, 3, 3]) - self.assertEqual(ragged.row_limits(rt).eval().tolist(), [2, 3, 3, 5]) - self.assertEqual(ragged.row_lengths(rt).eval().tolist(), [2, 1, 0, 2]) - self.assertEqual(rt.inner_values.eval().tolist(), - [b'a', b'b', b'c', b'd', b'e', b'f', b'g']) - self.assertEqual([s.eval().tolist() for s in rt.nested_row_splits], - [[0, 2, 3, 3, 5], [0, 2, 2, 5, 6, 7]]) + self.assertEqual( + self.evaluate(rt).tolist(), + [[[b'a', b'b'], []], [[b'c', b'd', b'e']], [], [[b'f'], [b'g']]]) + self.assertEqual( + self.evaluate(rt.values).tolist(), + [[b'a', b'b'], [], [b'c', b'd', b'e'], [b'f'], [b'g']]) + self.assertEqual(rt.values.shape.dims[0].value, 5) + self.assertEqual( + self.evaluate(ragged.value_rowids(rt)).tolist(), [0, 0, 1, 3, 3]) + self.assertEqual(self.evaluate(ragged.nrows(rt)).tolist(), 4) + self.assertEqual(self.evaluate(rt.row_splits).tolist(), [0, 2, 3, 3, 5]) + self.assertEqual( + self.evaluate(ragged.row_starts(rt)).tolist(), [0, 2, 3, 3]) + self.assertEqual( + self.evaluate(ragged.row_limits(rt)).tolist(), [2, 3, 3, 5]) + self.assertEqual( + self.evaluate(ragged.row_lengths(rt)).tolist(), [2, 1, 0, 2]) + self.assertEqual( + self.evaluate(rt.inner_values).tolist(), + [b'a', b'b', b'c', b'd', b'e', b'f', b'g']) + self.assertEqual( + [self.evaluate(s).tolist() for s in rt.nested_row_splits], + [[0, 2, 3, 3, 5], [0, 2, 2, 5, 6, 7]]) def testNRowsWithTensorInput(self): dt = constant_op.constant([[1, 2, 3], [4, 5, 6]]) nrows = ragged.nrows(dt) - with self.test_session(): - self.assertEqual(nrows.eval(), 2) + self.assertEqual(self.evaluate(nrows), 2) def testRowLengthsWithTensorInput(self): dt = constant_op.constant([[1, 2, 3], [4, 5, 6]]) row_lengths = ragged.row_lengths(dt) - with self.test_session(): - self.assertEqual(row_lengths.eval().tolist(), [3, 3]) + self.assertEqual(self.evaluate(row_lengths).tolist(), [3, 3]) #============================================================================= # RaggedTensor.shape #============================================================================= + @test_util.run_deprecated_v1 def testShape(self): """Tests for RaggedTensor.shape.""" rt1 = ragged.from_row_splits(b'a b c d e f g'.split(), [0, 2, 5, 6, 6, 7]) @@ -748,29 +775,27 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): expected: The expected value of rt.__getitem__(slice_spec), as a python list; or an exception class. """ - with self.test_session(): - tensor_slice_spec1 = _make_tensor_slice_spec(slice_spec, True) - tensor_slice_spec2 = _make_tensor_slice_spec(slice_spec, False) - value1 = rt.__getitem__(slice_spec).eval() - value2 = rt.__getitem__(tensor_slice_spec1).eval() - value3 = rt.__getitem__(tensor_slice_spec2).eval() - if hasattr(value1, 'tolist'): - value1 = value1.tolist() - if hasattr(value2, 'tolist'): - value2 = value2.tolist() - if hasattr(value3, 'tolist'): - value3 = value3.tolist() - self.assertEqual(value1, expected, 'slice_spec=%s' % (slice_spec,)) - self.assertEqual(value2, expected, 'slice_spec=%s' % (slice_spec,)) - self.assertEqual(value3, expected, 'slice_spec=%s' % (slice_spec,)) + tensor_slice_spec1 = _make_tensor_slice_spec(slice_spec, True) + tensor_slice_spec2 = _make_tensor_slice_spec(slice_spec, False) + value1 = self.evaluate(rt.__getitem__(slice_spec)) + value2 = self.evaluate(rt.__getitem__(tensor_slice_spec1)) + value3 = self.evaluate(rt.__getitem__(tensor_slice_spec2)) + if hasattr(value1, 'tolist'): + value1 = value1.tolist() + if hasattr(value2, 'tolist'): + value2 = value2.tolist() + if hasattr(value3, 'tolist'): + value3 = value3.tolist() + self.assertEqual(value1, expected, 'slice_spec=%s' % (slice_spec,)) + self.assertEqual(value2, expected, 'slice_spec=%s' % (slice_spec,)) + self.assertEqual(value3, expected, 'slice_spec=%s' % (slice_spec,)) def _TestGetItemException(self, rt, slice_spec, expected, message): """Helper function for testing RaggedTensor.__getitem__ exceptions.""" - with self.test_session(): - tensor_slice_spec1 = _make_tensor_slice_spec(slice_spec, True) - self.assertRaisesRegexp(expected, message, rt.__getitem__, slice_spec) - self.assertRaisesRegexp(expected, message, rt.__getitem__, - tensor_slice_spec1) + tensor_slice_spec1 = _make_tensor_slice_spec(slice_spec, True) + self.assertRaisesRegexp(expected, message, rt.__getitem__, slice_spec) + self.assertRaisesRegexp(expected, message, rt.__getitem__, + tensor_slice_spec1) @parameterized.parameters( # Tests for rt[i] @@ -836,14 +861,14 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): (SLICE_BUILDER[:, -2:], [row[-2:] for row in EXAMPLE_RAGGED_TENSOR_2D]), # TODO(edloper): Add tests for strided slices, once support is added. ) + @test_util.run_deprecated_v1 def testRaggedTensorGetItemWithRaggedRank1(self, slice_spec, expected): """Test that rt.__getitem__(slice_spec) == expected.""" # Ragged tensor rt = ragged.from_row_splits(EXAMPLE_RAGGED_TENSOR_2D_VALUES, EXAMPLE_RAGGED_TENSOR_2D_SPLITS) - with self.test_session(): - self.assertEqual(rt.tolist(), EXAMPLE_RAGGED_TENSOR_2D) + self.assertEqual(self.evaluate(rt).tolist(), EXAMPLE_RAGGED_TENSOR_2D) self._TestGetItem(rt, slice_spec, expected) # pylint: disable=invalid-slice-index @@ -878,6 +903,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): (SLICE_BUILDER[..., 0, 0, 0], IndexError, 'Too many indices for RaggedTensor'), ) + @test_util.run_deprecated_v1 def testRaggedTensorGetItemErrorsWithRaggedRank1(self, slice_spec, expected, message): """Test that rt.__getitem__(slice_spec) == expected.""" @@ -887,8 +913,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): # if sys.version_info[0] == 3: # message = 'must be str, not int' - with self.test_session(): - self.assertEqual(rt.tolist(), EXAMPLE_RAGGED_TENSOR_2D) + self.assertEqual(self.evaluate(rt).tolist(), EXAMPLE_RAGGED_TENSOR_2D) self._TestGetItemException(rt, slice_spec, expected, message) @parameterized.parameters( @@ -957,13 +982,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): # TODO(edloper): Add tests slicing inner ragged dimensions, one support # is added. ) + @test_util.run_deprecated_v1 def testRaggedTensorGetItemWithRaggedRank2(self, slice_spec, expected): """Test that rt.__getitem__(slice_spec) == expected.""" rt = ragged.from_nested_row_splits( EXAMPLE_RAGGED_TENSOR_4D_VALUES, [EXAMPLE_RAGGED_TENSOR_4D_SPLITS1, EXAMPLE_RAGGED_TENSOR_4D_SPLITS2]) - with self.test_session(): - self.assertEqual(rt.tolist(), EXAMPLE_RAGGED_TENSOR_4D) + self.assertEqual(self.evaluate(rt).tolist(), EXAMPLE_RAGGED_TENSOR_4D) self._TestGetItem(rt, slice_spec, expected) @parameterized.parameters( @@ -979,14 +1004,14 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): (SLICE_BUILDER[5], ValueError, '.*out of bounds.*'), (SLICE_BUILDER[0, 5], ValueError, '.*out of bounds.*'), ) + @test_util.run_deprecated_v1 def testRaggedTensorGetItemErrorsWithRaggedRank2(self, slice_spec, expected, message): """Test that rt.__getitem__(slice_spec) == expected.""" rt = ragged.from_nested_row_splits( EXAMPLE_RAGGED_TENSOR_4D_VALUES, [EXAMPLE_RAGGED_TENSOR_4D_SPLITS1, EXAMPLE_RAGGED_TENSOR_4D_SPLITS2]) - with self.test_session(): - self.assertEqual(rt.tolist(), EXAMPLE_RAGGED_TENSOR_4D) + self.assertEqual(self.evaluate(rt).tolist(), EXAMPLE_RAGGED_TENSOR_4D) self._TestGetItemException(rt, slice_spec, expected, message) @parameterized.parameters( @@ -994,6 +1019,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): (SLICE_BUILDER[2:], []), (SLICE_BUILDER[:-3], []), ) + @test_util.run_deprecated_v1 def testRaggedTensorGetItemWithEmptyTensor(self, slice_spec, expected): """Test that rt.__getitem__(slice_spec) == expected.""" rt = ragged.from_row_splits([], [0]) @@ -1003,6 +1029,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): (SLICE_BUILDER[0], ValueError, '.*out of bounds.*'), (SLICE_BUILDER[-1], ValueError, '.*out of bounds.*'), ) + @test_util.run_deprecated_v1 def testRaggedTensorGetItemErrorsWithEmptyTensor(self, slice_spec, expected, message): """Test that rt.__getitem__(slice_spec) == expected.""" @@ -1018,6 +1045,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): (SLICE_BUILDER[0, 1], EXAMPLE_RAGGED_TENSOR_2D[0][1]), (SLICE_BUILDER[-3, 0], EXAMPLE_RAGGED_TENSOR_2D[-3][0]), ) + @test_util.run_deprecated_v1 def testRaggedTensorGetItemWithPlaceholderShapes(self, slice_spec, expected): """Test that rt.__getitem__(slice_spec) == expected.""" # Intentionally use an unknown shape for `splits`, to force the code path @@ -1026,13 +1054,13 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): EXAMPLE_RAGGED_TENSOR_2D_SPLITS, dtype=dtypes.int64) splits = array_ops.placeholder_with_default(splits, None) rt = ragged.from_row_splits(EXAMPLE_RAGGED_TENSOR_2D_VALUES, splits) - with self.test_session(): - self.assertEqual(rt.tolist(), EXAMPLE_RAGGED_TENSOR_2D) + self.assertEqual(self.evaluate(rt).tolist(), EXAMPLE_RAGGED_TENSOR_2D) self._TestGetItem(rt, slice_spec, expected) @parameterized.parameters( (SLICE_BUILDER[..., 2], ValueError, 'Ellipsis not supported for unknown shape RaggedTensors'),) + @test_util.run_deprecated_v1 def testRaggedTensorGetItemErrorsWithPlaceholderShapes( self, slice_spec, expected, message): """Test that rt.__getitem__(slice_spec) == expected.""" @@ -1041,55 +1069,55 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt = ragged.from_row_splits(values, [0, 1]) self._TestGetItemException(rt, slice_spec, expected, message) - # TODO(edloper): Remove this decorator once c shapes become the default. - @test_util.enable_c_shapes + @test_util.run_deprecated_v1 def testGetItemNewAxis(self): # rt: [[[['a', 'b'], ['c', 'd']], [], [['e', 'f']]], []] splits1 = [0, 3, 3] splits2 = [0, 2, 2, 3] values = constant_op.constant([['a', 'b'], ['c', 'd'], ['e', 'f']]) rt = ragged.from_nested_row_splits(values, [splits1, splits2]) - with self.test_session(): - rt_newaxis0 = rt[array_ops.newaxis] - rt_newaxis1 = rt[:, array_ops.newaxis] - rt_newaxis2 = rt[:, :, array_ops.newaxis] - rt_newaxis3 = rt[:, :, :, array_ops.newaxis] - rt_newaxis4 = rt[:, :, :, :, array_ops.newaxis] - - self.assertEqual(rt.tolist(), - [[[[b'a', b'b'], [b'c', b'd']], [], [[b'e', b'f']]], []]) - self.assertEqual( - rt_newaxis0.tolist(), - [[[[[b'a', b'b'], [b'c', b'd']], [], [[b'e', b'f']]], []]]) - self.assertEqual( - rt_newaxis1.tolist(), - [[[[[b'a', b'b'], [b'c', b'd']], [], [[b'e', b'f']]]], [[]]]) - self.assertEqual( - rt_newaxis2.tolist(), - [[[[[b'a', b'b'], [b'c', b'd']]], [[]], [[[b'e', b'f']]]], []]) - self.assertEqual( - rt_newaxis3.tolist(), - [[[[[b'a', b'b']], [[b'c', b'd']]], [], [[[b'e', b'f']]]], []]) - self.assertEqual( - rt_newaxis4.tolist(), - [[[[[b'a'], [b'b']], [[b'c'], [b'd']]], [], [[[b'e'], [b'f']]]], []]) - - self.assertEqual(rt.ragged_rank, 2) - self.assertEqual(rt_newaxis0.ragged_rank, 3) - self.assertEqual(rt_newaxis1.ragged_rank, 3) - self.assertEqual(rt_newaxis2.ragged_rank, 3) - self.assertEqual(rt_newaxis3.ragged_rank, 2) - self.assertEqual(rt_newaxis4.ragged_rank, 2) - - self.assertEqual(rt_newaxis0.shape.as_list(), [1, None, None, None, 2]) - self.assertEqual(rt_newaxis1.shape.as_list(), [2, None, None, None, 2]) - self.assertEqual(rt_newaxis2.shape.as_list(), [2, None, None, None, 2]) - self.assertEqual(rt_newaxis3.shape.as_list(), [2, None, None, 1, 2]) - self.assertEqual(rt_newaxis4.shape.as_list(), [2, None, None, 2, 1]) + rt_newaxis0 = rt[array_ops.newaxis] + rt_newaxis1 = rt[:, array_ops.newaxis] + rt_newaxis2 = rt[:, :, array_ops.newaxis] + rt_newaxis3 = rt[:, :, :, array_ops.newaxis] + rt_newaxis4 = rt[:, :, :, :, array_ops.newaxis] + + self.assertEqual( + self.evaluate(rt).tolist(), + [[[[b'a', b'b'], [b'c', b'd']], [], [[b'e', b'f']]], []]) + self.assertEqual( + self.evaluate(rt_newaxis0).tolist(), + [[[[[b'a', b'b'], [b'c', b'd']], [], [[b'e', b'f']]], []]]) + self.assertEqual( + self.evaluate(rt_newaxis1).tolist(), + [[[[[b'a', b'b'], [b'c', b'd']], [], [[b'e', b'f']]]], [[]]]) + self.assertEqual( + self.evaluate(rt_newaxis2).tolist(), + [[[[[b'a', b'b'], [b'c', b'd']]], [[]], [[[b'e', b'f']]]], []]) + self.assertEqual( + self.evaluate(rt_newaxis3).tolist(), + [[[[[b'a', b'b']], [[b'c', b'd']]], [], [[[b'e', b'f']]]], []]) + self.assertEqual( + self.evaluate(rt_newaxis4).tolist(), + [[[[[b'a'], [b'b']], [[b'c'], [b'd']]], [], [[[b'e'], [b'f']]]], []]) + + self.assertEqual(rt.ragged_rank, 2) + self.assertEqual(rt_newaxis0.ragged_rank, 3) + self.assertEqual(rt_newaxis1.ragged_rank, 3) + self.assertEqual(rt_newaxis2.ragged_rank, 3) + self.assertEqual(rt_newaxis3.ragged_rank, 2) + self.assertEqual(rt_newaxis4.ragged_rank, 2) + + self.assertEqual(rt_newaxis0.shape.as_list(), [1, None, None, None, 2]) + self.assertEqual(rt_newaxis1.shape.as_list(), [2, None, None, None, 2]) + self.assertEqual(rt_newaxis2.shape.as_list(), [2, None, None, None, 2]) + self.assertEqual(rt_newaxis3.shape.as_list(), [2, None, None, 1, 2]) + self.assertEqual(rt_newaxis4.shape.as_list(), [2, None, None, 2, 1]) #============================================================================= # RaggedTensor.__str__ #============================================================================= + @test_util.run_deprecated_v1 def testRaggedTensorStr(self): rt1 = ragged.from_row_splits(b'a b c d e f g'.split(), [0, 2, 5, 6, 6, 7]) expected1 = ('RaggedTensor(values=Tensor("RaggedFromRowSplits/values:0", ' @@ -1127,6 +1155,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): # RaggedTensor.with_values() and RaggedTensor.with_inner_values(). #============================================================================= + @test_util.run_deprecated_v1 def testWithValues(self): rt1 = ragged.constant([[1, 2], [3, 4, 5], [6], [], [7]]) rt2 = ragged.constant([[[1, 2], [3, 4, 5]], [[6]], [], [[], [7]]]) @@ -1135,17 +1164,20 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt2_times_10 = rt2.with_inner_values(rt2.inner_values * 10) rt1_expanded = rt1.with_values(array_ops.expand_dims(rt1.values, axis=1)) - with self.test_session(): - self.assertEqual(rt1_plus_10.tolist(), - [[11, 12], [13, 14, 15], [16], [], [17]]) - self.assertEqual(rt2_times_10.tolist(), - [[[10, 20], [30, 40, 50]], [[60]], [], [[], [70]]]) - self.assertEqual(rt1_expanded.tolist(), - [[[1], [2]], [[3], [4], [5]], [[6]], [], [[7]]]) + self.assertEqual( + self.evaluate(rt1_plus_10).tolist(), + [[11, 12], [13, 14, 15], [16], [], [17]]) + self.assertEqual( + self.evaluate(rt2_times_10).tolist(), + [[[10, 20], [30, 40, 50]], [[60]], [], [[], [70]]]) + self.assertEqual( + self.evaluate(rt1_expanded).tolist(), + [[[1], [2]], [[3], [4], [5]], [[6]], [], [[7]]]) #============================================================================= # Session.run #============================================================================= + @test_util.run_deprecated_v1 def testSessionRun(self): rt1 = ragged.constant([[1, 2, 3], [4]]) rt2 = ragged.constant([[[], [1, 2]], [[3]]]) @@ -1155,6 +1187,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertEqual(result['rt1'].tolist(), [[1, 2, 3], [4]]) self.assertEqual(result['rt2'].tolist(), [[[], [1, 2]], [[3]]]) + @test_util.run_deprecated_v1 def testSessionRunFeed(self): rt1 = ragged.from_row_splits( array_ops.placeholder(dtypes.int32), @@ -1175,6 +1208,7 @@ class RaggedTensorTest(test_util.TensorFlowTestCase, parameterized.TestCase): self.assertEqual(result['rt1'].tolist(), [[1, 2, 3], [4]]) self.assertEqual(result['rt2'].tolist(), [[[], [1, 2]], [[3]]]) + @test_util.run_deprecated_v1 def testSessionPartialRunFeed(self): # Placeholder inputs. a = ragged.from_row_splits( diff --git a/tensorflow/python/ops/ragged/ragged_tile_op_test.py b/tensorflow/python/ops/ragged/ragged_tile_op_test.py index bf62d96e7a..f335b15dd1 100644 --- a/tensorflow/python/ops/ragged/ragged_tile_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_tile_op_test.py @@ -170,8 +170,18 @@ class RaggedTileOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): rt_input=[[[[1], [2]], [[3]]], [[]], [[[4, 5]]]], multiples=[1, 1, 1, 0], expected=[[[[], []], [[]]], [[]], [[[]]]]), + #========================================================================= + # multiple=1 + #========================================================================= + dict( + descr='rank=4, multiples=1 (no repeats)', + rt_input=[[[[1], [2]], [[3], [4]]], [[[5], [6]]]], + multiples=[1, 1, 1, 1], + expected=[[[[1], [2]], [[3], [4]]], + [[[5], [6]]]]), ]) # pyformat: disable + @test_util.run_deprecated_v1 def testRaggedTile(self, descr, rt_input, @@ -200,6 +210,7 @@ class RaggedTileOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): with self.test_session(): self.assertEqual(tiled.eval().tolist(), expected) + @test_util.run_deprecated_v1 def testRaggedTileWithTensorInput(self): # When the input is a `Tensor`, ragged_tile just delegates to tf.tile. dt = constant_op.constant([[1, 2], [3, 4]]) diff --git a/tensorflow/python/ops/ragged/ragged_to_sparse_op_test.py b/tensorflow/python/ops/ragged/ragged_to_sparse_op_test.py index 2fd31837c6..69b31ad0e9 100644 --- a/tensorflow/python/ops/ragged/ragged_to_sparse_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_to_sparse_op_test.py @@ -23,12 +23,14 @@ from tensorflow.python.framework import errors from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import gradients_impl +from tensorflow.python.ops import math_ops from tensorflow.python.ops import ragged from tensorflow.python.platform import googletest class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): + @test_util.run_deprecated_v1 def testDocStringExample(self): rt = ragged.constant([[1, 2, 3], [4], [], [5, 6]]) st = ragged.to_sparse(rt) @@ -39,6 +41,7 @@ class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): with self.test_session(): self.assertEqual(' '.join(repr(st.eval()).split()), expected) + @test_util.run_deprecated_v1 def test2DRaggedTensorWithOneRaggedDimension(self): rt = ragged.constant([['a', 'b'], ['c', 'd', 'e'], ['f'], [], ['g']]) with self.test_session(): @@ -48,6 +51,7 @@ class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): self.assertAllEqual(st.values, b'a b c d e f g'.split()) self.assertAllEqual(st.dense_shape, [5, 3]) + @test_util.run_deprecated_v1 def test3DRaggedTensorWithOneRaggedDimension(self): rt = ragged.constant([[[1, 2], [3, 4]], [[5, 6], [7, 8], [9, 10]], [[11, 12]], [], [[13, 14]]], @@ -62,6 +66,7 @@ class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]) self.assertAllEqual(st.dense_shape, [5, 3, 2]) + @test_util.run_deprecated_v1 def test4DRaggedTensorWithOneRaggedDimension(self): rt = ragged.constant( [[[[1, 2], [3, 4]], [[5, 6], [7, 8]]], [], [[[9, 10], [11, 12]]]], @@ -87,6 +92,7 @@ class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): ]) self.assertAllEqual(st.dense_shape, [3, 2, 2, 2]) + @test_util.run_deprecated_v1 def test4DRaggedTensorWithTwoRaggedDimensions(self): rt = ragged.constant([[[[1, 2], [3, 4]], [[5, 6], [7, 8], [9, 10]]], [[[11, 12]], [], [[13, 14]]], []], @@ -134,6 +140,7 @@ class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): self.assertEqual(st.values.shape.as_list(), [7]) self.assertEqual(st.dense_shape.shape.as_list(), [3]) + @test_util.run_deprecated_v1 def testKernelErrors(self): # An empty vector, defined using a placeholder to ensure that we can't # determine that it's invalid at graph-construction time. @@ -172,13 +179,14 @@ class RaggedTensorToSparseOpTest(test_util.TensorFlowTestCase): self.assertRaisesRegexp(errors.InvalidArgumentError, empty_splits_error, ragged.to_sparse(bad_rt5).eval) + @test_util.run_deprecated_v1 def testGradient(self): # rt1.shape == rt2.shape == [2, (D2), (D3), 2]. rt1 = ragged.constant([[[[1.0, 2.0], [3.0, 4.0]], [[5.0, 6.0]]]], ragged_rank=2) rt2 = ragged.constant([[[[9.0, 8.0], [7.0, 6.0]], [[5.0, 4.0]]]], ragged_rank=2) - rt = rt1 + rt2 * 2.0 + rt = ragged.map_inner_values(math_ops.add, rt1, rt2 * 2.0) st = ragged.to_sparse(rt) g1, g2 = gradients_impl.gradients(st.values, [rt1.inner_values, diff --git a/tensorflow/python/ops/ragged/ragged_to_tensor_op_test.py b/tensorflow/python/ops/ragged/ragged_to_tensor_op_test.py index 0ccc214a9c..77499b9cb3 100644 --- a/tensorflow/python/ops/ragged/ragged_to_tensor_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_to_tensor_op_test.py @@ -30,6 +30,7 @@ from tensorflow.python.platform import googletest class RaggedTensorToTensorOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): + @test_util.run_deprecated_v1 def testDocStringExamples(self): """Example from ragged_to_tensor.__doc__.""" rt = ragged.constant([[9, 8, 7], [], [6, 5], [4]]) @@ -71,10 +72,33 @@ class RaggedTensorToTensorOpTest(test_util.TensorFlowTestCase, [[1, 2], [0, 0], [3, 4]], # [[0, 0], [0, 0], [0, 0]], # [[5, 0], [0, 0], [0, 0]], # - [[6, 7], [8, 0], [0, 0]] - ] # + [[6, 7], [8, 0], [0, 0]], # + ] + }, + { + 'rt_input': [[[1, 2], [], [3, 4]], [], [[5]], [[6, 7], [8]]], + 'default': + 9, + 'expected': [ + [[1, 2], [9, 9], [3, 4]], # + [[9, 9], [9, 9], [9, 9]], # + [[5, 9], [9, 9], [9, 9]], # + [[6, 7], [8, 9], [9, 9]], # + ] + }, + { + 'rt_input': [[[1], [2], [3]]], + 'ragged_rank': 1, + 'default': 0, + 'expected': [[[1], [2], [3]]], + }, + { + 'rt_input': [[[[1], [2]], [], [[3]]]], + 'default': 9, + 'expected': [[[[1], [2]], [[9], [9]], [[3], [9]]]], }, ) + @test_util.run_deprecated_v1 def testRaggedTensorToTensor(self, rt_input, expected, @@ -96,17 +120,13 @@ class RaggedTensorToTensorOpTest(test_util.TensorFlowTestCase, { 'rt_input': [[1, 2, 3]], 'default': [0], - 'error': (ValueError, r'Shapes \(1,\) and \(\) are incompatible'), - }, - { - 'rt_input': [[[1], [2], [3]]], - 'default': 0, - 'error': (ValueError, r'Shapes \(\) and \(1,\) are incompatible'), + 'error': (ValueError, r'Shape \(1,\) must have rank at most 0'), }, { - 'rt_input': [[[[1], [2]], [], [[3]]]], - 'default': 0, - 'error': (ValueError, r'Shapes \(\) and \(1,\) are incompatible'), + 'rt_input': [[[1, 2], [3, 4]], [[5, 6]]], + 'ragged_rank': 1, + 'default': [7, 8, 9], + 'error': (ValueError, r'Shapes \(3,\) and \(2,\) are incompatible'), }, { 'rt_input': [[1, 2, 3]], @@ -114,9 +134,11 @@ class RaggedTensorToTensorOpTest(test_util.TensorFlowTestCase, 'error': (TypeError, "Expected int32, got 'a' of type 'str' instead"), }, ) - def testError(self, rt_input, default, error): - rt = ragged.constant(rt_input) - self.assertRaisesRegexp(error[0], error[1], ragged.to_tensor, rt, default) + @test_util.run_deprecated_v1 + def testError(self, rt_input, default, error, ragged_rank=None): + rt = ragged.constant(rt_input, ragged_rank=ragged_rank) + with self.assertRaisesRegexp(error[0], error[1]): + ragged.to_tensor(rt, default) if __name__ == '__main__': diff --git a/tensorflow/python/ops/ragged/ragged_util.py b/tensorflow/python/ops/ragged/ragged_util.py index 03f050de51..a832f937d1 100644 --- a/tensorflow/python/ops/ragged/ragged_util.py +++ b/tensorflow/python/ops/ragged/ragged_util.py @@ -25,6 +25,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import check_ops +from tensorflow.python.ops import gen_ragged_math_ops from tensorflow.python.ops import math_ops @@ -229,3 +230,51 @@ def _with_nonzero_rank(data): return array_ops.reshape( data, array_ops.concat([[1], data_shape], axis=0)[-data_ndims:]) + + +def lengths_to_splits(lengths): + """Returns splits corresponding to the given lengths.""" + return array_ops.concat([[0], math_ops.cumsum(lengths)], axis=-1) + + +def repeat_ranges(params, splits, repeats): + """Repeats each range of `params` (as specified by `splits`) `repeats` times. + + Let the `i`th range of `params` be defined as + `params[splits[i]:splits[i + 1]]`. Then this function returns a tensor + containing range 0 repeated `repeats[0]` times, followed by range 1 repeated + `repeats[1]`, ..., followed by the last range repeated `repeats[-1]` times. + + Args: + params: The `Tensor` whose values should be repeated. + splits: A splits tensor indicating the ranges of `params` that should be + repeated. + repeats: The number of times each range should be repeated. Supports + broadcasting from a scalar value. + + Returns: + A `Tensor` with the same rank and type as `params`. + + #### Example: + ```python + >>> repeat_ranges(['a', 'b', 'c'], [0, 2, 3], 3) + ['a', 'b', 'a', 'b', 'a', 'b', 'c', 'c', 'c'] + ``` + """ + # Divide `splits` into starts and limits, and repeat them `repeats` times. + if repeats.shape.ndims != 0: + repeated_starts = repeat(splits[:-1], repeats, axis=0) + repeated_limits = repeat(splits[1:], repeats, axis=0) + else: + # Optimization: we can just call repeat once, and then slice the result. + repeated_splits = repeat(splits, repeats, axis=0) + n_splits = array_ops.shape(repeated_splits, out_type=dtypes.int64)[0] + repeated_starts = repeated_splits[:n_splits - repeats] + repeated_limits = repeated_splits[repeats:] + + # Get indices for each range from starts to limits, and use those to gather + # the values in the desired repetition pattern. + one = array_ops.ones((), repeated_starts.dtype) + offsets = gen_ragged_math_ops.ragged_range( + repeated_starts, repeated_limits, one) + return array_ops.gather(params, offsets.rt_dense_values) diff --git a/tensorflow/python/ops/ragged/ragged_where_op_test.py b/tensorflow/python/ops/ragged/ragged_where_op_test.py index 755333de39..de83a54977 100644 --- a/tensorflow/python/ops/ragged/ragged_where_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_where_op_test.py @@ -165,12 +165,13 @@ class RaggedWhereOpTest(test_util.TensorFlowTestCase, parameterized.TestCase): y=ragged.constant_value([[[['a']]], [[['b']]]]), expected=ragged.constant_value([[[[], [b'A']]], [[[b'b']]]])), ]) # pyformat: disable + @test_util.run_deprecated_v1 def testRaggedWhere(self, condition, expected, x=None, y=None): result = ragged.where(condition, x, y) self.assertEqual( getattr(result, 'ragged_rank', 0), getattr(expected, 'ragged_rank', 0)) with self.test_session(): - result_value = result.eval() + result_value = self.evaluate(result) if hasattr(result_value, 'tolist'): result_value = result_value.tolist() if hasattr(expected, 'tolist'): diff --git a/tensorflow/python/ops/random_ops.py b/tensorflow/python/ops/random_ops.py index 1f7db0af61..62e2f6d102 100644 --- a/tensorflow/python/ops/random_ops.py +++ b/tensorflow/python/ops/random_ops.py @@ -138,7 +138,9 @@ def parameterized_truncated_normal(shape, return rnd -@tf_export("random.truncated_normal", "truncated_normal") +@tf_export("random.truncated_normal", + v1=["random.truncated_normal", "truncated_normal"]) +@deprecation.deprecated_endpoints("truncated_normal") def truncated_normal(shape, mean=0.0, stddev=1.0, @@ -325,7 +327,9 @@ def random_crop(value, size, seed=None, name=None): return array_ops.slice(value, offset, size, name=name) -@tf_export("random.multinomial", "multinomial") +@tf_export(v1=["random.multinomial", "multinomial"]) +@deprecation.deprecated( + date=None, instructions="Use tf.random.categorical instead.") def multinomial(logits, num_samples, seed=None, name=None, output_dtype=None): """Draws samples from a multinomial distribution. @@ -342,9 +346,7 @@ def multinomial(logits, num_samples, seed=None, name=None, output_dtype=None): `[i, :]` represents the unnormalized log-probabilities for all classes. num_samples: 0-D. Number of independent samples to draw for each row slice. seed: A Python integer. Used to create a random seed for the distribution. - See - `tf.set_random_seed` - for behavior. + See `tf.set_random_seed` for behavior. name: Optional name for the operation. output_dtype: integer type to use for the output. Defaults to int64. @@ -352,10 +354,43 @@ def multinomial(logits, num_samples, seed=None, name=None, output_dtype=None): The drawn samples of shape `[batch_size, num_samples]`. """ with ops.name_scope(name, "multinomial", [logits]): - logits = ops.convert_to_tensor(logits, name="logits") - seed1, seed2 = random_seed.get_seed(seed) - return gen_random_ops.multinomial( - logits, num_samples, seed=seed1, seed2=seed2, output_dtype=output_dtype) + return multinomial_categorical_impl(logits, num_samples, output_dtype, seed) + + +@tf_export("random.categorical") +def categorical(logits, num_samples, dtype=None, seed=None, name=None): + """Draws samples from a categorical distribution. + + Example: + + ```python + # samples has shape [1, 5], where each value is either 0 or 1 with equal + # probability. + samples = tf.random.categorical(tf.log([[10., 10.]]), 5) + ``` + + Args: + logits: 2-D Tensor with shape `[batch_size, num_classes]`. Each slice + `[i, :]` represents the unnormalized log-probabilities for all classes. + num_samples: 0-D. Number of independent samples to draw for each row slice. + dtype: integer type to use for the output. Defaults to int64. + seed: A Python integer. Used to create a random seed for the distribution. + See `tf.set_random_seed` for behavior. + name: Optional name for the operation. + + Returns: + The drawn samples of shape `[batch_size, num_samples]`. + """ + with ops.name_scope(name, "categorical", [logits]): + return multinomial_categorical_impl(logits, num_samples, dtype, seed) + + +def multinomial_categorical_impl(logits, num_samples, dtype, seed): + """Implementation for random.multinomial (v1) and random.categorical (v2).""" + logits = ops.convert_to_tensor(logits, name="logits") + seed1, seed2 = random_seed.get_seed(seed) + return gen_random_ops.multinomial( + logits, num_samples, seed=seed1, seed2=seed2, output_dtype=dtype) ops.NotDifferentiable("Multinomial") @@ -445,7 +480,7 @@ def random_gamma(shape, shape, alpha_broadcast, seed=seed1, seed2=seed2) / beta) -@tf_export("random.poisson", v1=["random.poisson", "random_poisson"]) +@tf_export(v1=["random.poisson", "random_poisson"]) @deprecation.deprecated_endpoints("random_poisson") def random_poisson(lam, shape, dtype=dtypes.float32, seed=None, name=None): """Draws `shape` samples from each of the given Poisson distribution(s). @@ -478,6 +513,45 @@ def random_poisson(lam, shape, dtype=dtypes.float32, seed=None, name=None): for behavior. name: Optional name for the operation. + Returns: + samples: a `Tensor` of shape `tf.concat([shape, tf.shape(lam)], axis=0)` + with values of type `dtype`. + """ + return random_poisson_v2(shape, lam, dtype, seed, name) + + +@tf_export("random.poisson", v1=[]) +def random_poisson_v2(shape, lam, dtype=dtypes.float32, seed=None, name=None): + """Draws `shape` samples from each of the given Poisson distribution(s). + + `lam` is the rate parameter describing the distribution(s). + + Example: + + ```python + samples = tf.random_poisson([10], [0.5, 1.5]) + # samples has shape [10, 2], where each slice [:, 0] and [:, 1] represents + # the samples drawn from each distribution + + samples = tf.random_poisson([7, 5], [12.2, 3.3]) + # samples has shape [7, 5, 2], where each slice [:, :, 0] and [:, :, 1] + # represents the 7x5 samples drawn from each of the two distributions + ``` + + Args: + shape: A 1-D integer Tensor or Python array. The shape of the output samples + to be drawn per "rate"-parameterized distribution. + lam: A Tensor or Python value or N-D array of type `dtype`. + `lam` provides the rate parameter(s) describing the poisson + distribution(s) to sample. + dtype: The type of the output: `float16`, `float32`, `float64`, `int32` or + `int64`. + seed: A Python integer. Used to create a random seed for the distributions. + See + `tf.set_random_seed` + for behavior. + name: Optional name for the operation. + Returns: samples: a `Tensor` of shape `tf.concat([shape, tf.shape(lam)], axis=0)` with values of type `dtype`. diff --git a/tensorflow/python/ops/resource_variable_ops.py b/tensorflow/python/ops/resource_variable_ops.py index 488b6fcbcd..1066b357b4 100644 --- a/tensorflow/python/ops/resource_variable_ops.py +++ b/tensorflow/python/ops/resource_variable_ops.py @@ -26,6 +26,7 @@ from tensorflow.core.framework import variable_pb2 from tensorflow.python import pywrap_tensorflow from tensorflow.python.eager import context from tensorflow.python.eager import tape +from tensorflow.python.framework import constant_op from tensorflow.python.framework import cpp_shape_inference_pb2 from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops @@ -64,6 +65,7 @@ def eager_safe_variable_handle(shape, dtype, shared_name, name, graph_mode): name=name, container=container) if graph_mode: + handle._handle_data = get_resource_handle_data(handle) # pylint: disable=protected-access return handle # We do not want two distinct ResourceVariable objects for the same @@ -519,7 +521,10 @@ class ResourceVariable(variables.RefVariable): snapshot = g.as_graph_element( ops.prepend_name_scope( variable_def.snapshot_name, import_scope=import_scope)) - self._cached_value = snapshot + if snapshot.op.type != "ReadVariableOp": + self._cached_value = snapshot + else: + self._cached_value = None while snapshot.op.type != "ReadVariableOp": snapshot = snapshot.op.inputs[0] self._graph_element = snapshot @@ -802,16 +807,6 @@ class ResourceVariable(variables.RefVariable): return ResourceVariable( variable_def=variable_def, import_scope=import_scope) - @staticmethod - def _OverloadAllOperators(): # pylint: disable=invalid-name - """Register overloads for all operators.""" - for operator in ops.Tensor.OVERLOADABLE_OPERATORS: - ResourceVariable._OverloadOperator(operator) - # For slicing, bind getitem differently than a tensor (use SliceHelperVar - # instead) - # pylint: disable=protected-access - setattr(ResourceVariable, "__getitem__", array_ops._SliceHelperVar) - def _AsTensor(self): return self.value() @@ -823,30 +818,6 @@ class ResourceVariable(variables.RefVariable): """Unsupported.""" raise NotImplementedError("ResourceVariable does not implement set_shape()") - @staticmethod - def _OverloadOperator(operator): # pylint: disable=invalid-name - """Defer an operator overload to `ops.Tensor`. - - We pull the operator out of ops.Tensor dynamically to avoid ordering issues. - - Args: - operator: string. The operator name. - """ - - tensor_oper = getattr(ops.Tensor, operator) - def _run_op(a, *args): - # pylint: disable=protected-access - value = a._AsTensor() - return tensor_oper(value, *args) - - # Propagate __doc__ to wrapper - try: - _run_op.__doc__ = tensor_oper.__doc__ - except AttributeError: - pass - - setattr(ResourceVariable, operator, _run_op) - __array_priority__ = 100 def is_initialized(self, name=None): @@ -1432,7 +1403,6 @@ ops.register_tensor_conversion_function( variables.Variable, variables.Variable._TensorConversionFunction) # pylint: disable=protected-access # pylint: disable=protected-access -ResourceVariable._OverloadAllOperators() ops.register_dense_tensor_like_type(ResourceVariable) @@ -1442,13 +1412,23 @@ def _ReadGrad(_, grad): return grad +def variable_shape(handle, out_type=dtypes.int32): + if getattr( + handle, "_handle_data", None) is None or not handle._handle_data.is_set: + return gen_resource_variable_ops.variable_shape(handle, out_type=out_type) + shape_proto = handle._handle_data.shape_and_type[0].shape + if shape_proto.unknown_rank or any(x.size == -1 for x in shape_proto.dim): + return gen_resource_variable_ops.variable_shape(handle, out_type=out_type) + return constant_op.constant([x.size for x in shape_proto.dim], dtype=out_type) + + @ops.RegisterGradient("ResourceGather") def _GatherGrad(op, grad): """Gradient for gather op.""" # Build appropriately shaped IndexedSlices handle = op.inputs[0] indices = op.inputs[1] - params_shape = gen_resource_variable_ops.variable_shape(handle) + params_shape = variable_shape(handle) size = array_ops.expand_dims(array_ops.size(indices), 0) values_shape = array_ops.concat([size, params_shape[1:]], 0) values = array_ops.reshape(grad, values_shape) @@ -1522,3 +1502,6 @@ def copy_to_graph_uninitialized(var): new_variable._maybe_initialize_checkpointable() # pylint: enable=protected-access return new_variable + +ops.NotDifferentiable("VarIsInitializedOp") +ops.NotDifferentiable("VariableShape") diff --git a/tensorflow/python/ops/resources.py b/tensorflow/python/ops/resources.py index db6740643c..6cd12b7bbb 100644 --- a/tensorflow/python/ops/resources.py +++ b/tensorflow/python/ops/resources.py @@ -21,6 +21,7 @@ from __future__ import division from __future__ import print_function import collections +import os from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops @@ -86,7 +87,8 @@ def report_uninitialized_resources(resource_list=None, resource_list = shared_resources() + local_resources() with ops.name_scope(name): # Run all operations on CPU - with ops.device("/cpu:0"): + local_device = os.environ.get("TF_DEVICE_FOR_UNINITIALIZED_VARIABLE_REPORTING", "/cpu:0") + with ops.device(local_device): if not resource_list: # Return an empty tensor so we only need to check for returned tensor # size being 0 as an indication of model ready. diff --git a/tensorflow/python/ops/rnn.py b/tensorflow/python/ops/rnn.py index 57ecb50557..ec48cab91d 100644 --- a/tensorflow/python/ops/rnn.py +++ b/tensorflow/python/ops/rnn.py @@ -117,7 +117,7 @@ def _infer_state_dtype(explicit_dtype, state): inferred_dtypes = [element.dtype for element in nest.flatten(state)] if not inferred_dtypes: raise ValueError("Unable to infer dtype from empty state.") - all_same = all([x == inferred_dtypes[0] for x in inferred_dtypes]) + all_same = all(x == inferred_dtypes[0] for x in inferred_dtypes) if not all_same: raise ValueError( "State has tensors of different inferred_dtypes. Unable to infer a " @@ -348,7 +348,10 @@ def _reverse_seq(input_seq, lengths): return results -@tf_export("nn.bidirectional_dynamic_rnn") +@deprecation.deprecated(None, "Please use `keras.layers.Bidirectional(" + "keras.layers.RNN(cell))`, which is equivalent to " + "this API") +@tf_export(v1=["nn.bidirectional_dynamic_rnn"]) def bidirectional_dynamic_rnn(cell_fw, cell_bw, inputs, sequence_length=None, initial_state_fw=None, initial_state_bw=None, dtype=None, parallel_iterations=None, @@ -1490,7 +1493,10 @@ def static_state_saving_rnn(cell, return (outputs, state) -@tf_export("nn.static_bidirectional_rnn") +@deprecation.deprecated(None, "Please use `keras.layers.Bidirectional(" + "keras.layers.RNN(cell, unroll=True))`, which is " + "equivalent to this API") +@tf_export(v1=["nn.static_bidirectional_rnn"]) def static_bidirectional_rnn(cell_fw, cell_bw, inputs, diff --git a/tensorflow/python/ops/rnn_cell_impl.py b/tensorflow/python/ops/rnn_cell_impl.py index 050b486893..ffc45619a7 100644 --- a/tensorflow/python/ops/rnn_cell_impl.py +++ b/tensorflow/python/ops/rnn_cell_impl.py @@ -36,6 +36,7 @@ from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import tensor_util from tensorflow.python.keras import activations from tensorflow.python.keras import initializers +from tensorflow.python.keras.engine import input_spec from tensorflow.python.keras.utils import tf_utils from tensorflow.python.layers import base as base_layer from tensorflow.python.ops import array_ops @@ -410,7 +411,7 @@ class BasicRNNCell(LayerRNNCell): "performance on GPU.", self) # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) self._num_units = num_units if activation: @@ -507,7 +508,7 @@ class GRUCell(LayerRNNCell): "Please use tf.contrib.cudnn_rnn.CudnnGRU for better " "performance on GPU.", self) # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) self._num_units = num_units if activation: @@ -683,7 +684,7 @@ class BasicLSTMCell(LayerRNNCell): "performance on GPU.", self) # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) self._num_units = num_units self._forget_bias = forget_bias @@ -871,7 +872,7 @@ class LSTMCell(LayerRNNCell): "performance on GPU.", self) # Inputs must be 2-dimensional. - self.input_spec = base_layer.InputSpec(ndim=2) + self.input_spec = input_spec.InputSpec(ndim=2) self._num_units = num_units self._use_peepholes = use_peepholes @@ -1394,7 +1395,7 @@ class DeviceWrapper(RNNCell): return self._cell(inputs, state, scope=scope) -@tf_export("nn.rnn_cell.MultiRNNCell") +@tf_export(v1=["nn.rnn_cell.MultiRNNCell"]) class MultiRNNCell(RNNCell): """RNN cell composed sequentially of multiple simple cells. @@ -1407,6 +1408,9 @@ class MultiRNNCell(RNNCell): ``` """ + @deprecated(None, "This class is equivalent as " + "tf.keras.layers.StackedRNNCells, and will be replaced by " + "that in Tensorflow 2.0.") def __init__(self, cells, state_is_tuple=True): """Create a RNN cell composed sequentially of a number of RNNCells. @@ -1452,7 +1456,7 @@ class MultiRNNCell(RNNCell): if self._state_is_tuple: return tuple(cell.state_size for cell in self._cells) else: - return sum([cell.state_size for cell in self._cells]) + return sum(cell.state_size for cell in self._cells) @property def output_size(self): diff --git a/tensorflow/python/ops/sets_impl.py b/tensorflow/python/ops/sets_impl.py index 21e08d03d2..ee9c9b6bc0 100644 --- a/tensorflow/python/ops/sets_impl.py +++ b/tensorflow/python/ops/sets_impl.py @@ -31,7 +31,7 @@ _VALID_DTYPES = set([ dtypes.uint8, dtypes.uint16, dtypes.string]) -@tf_export("sets.set_size") +@tf_export("sets.size", v1=["sets.size", "sets.set_size"]) def set_size(a, validate_indices=True): """Compute number of unique elements along last dimension of `a`. @@ -133,7 +133,8 @@ def _set_operation(a, b, set_operation, validate_indices=True): return sparse_tensor.SparseTensor(indices, values, shape) -@tf_export("sets.set_intersection") +@tf_export( + "sets.intersection", v1=["sets.intersection", "sets.set_intersection"]) def set_intersection(a, b, validate_indices=True): """Compute set intersection of elements in last dimension of `a` and `b`. @@ -200,7 +201,8 @@ def set_intersection(a, b, validate_indices=True): return _set_operation(a, b, "intersection", validate_indices) -@tf_export("sets.set_difference") +@tf_export( + "sets.difference", v1=["sets.difference", "sets.set_difference"]) def set_difference(a, b, aminusb=True, validate_indices=True): """Compute set difference of elements in last dimension of `a` and `b`. @@ -271,7 +273,8 @@ def set_difference(a, b, aminusb=True, validate_indices=True): return _set_operation(a, b, "a-b" if aminusb else "b-a", validate_indices) -@tf_export("sets.set_union") +@tf_export( + "sets.union", v1=["sets.union", "sets.set_union"]) def set_union(a, b, validate_indices=True): """Compute set union of elements in last dimension of `a` and `b`. diff --git a/tensorflow/python/ops/signal/BUILD b/tensorflow/python/ops/signal/BUILD index 0d04dc0c1b..da2bf9c1d2 100644 --- a/tensorflow/python/ops/signal/BUILD +++ b/tensorflow/python/ops/signal/BUILD @@ -6,16 +6,29 @@ exports_files(["LICENSE"]) py_library( name = "signal", - srcs = glob(["*.py"]), + srcs = [ + "dct_ops.py", + "fft_ops.py", + "mel_ops.py", + "mfcc_ops.py", + "reconstruction_ops.py", + "shape_ops.py", + "signal.py", + "spectral_ops.py", + "util_ops.py", + "window_ops.py", + ], srcs_version = "PY2AND3", deps = [ "//tensorflow/python:array_ops", "//tensorflow/python:constant_op", "//tensorflow/python:control_flow_ops", "//tensorflow/python:dtypes", + "//tensorflow/python:framework", + "//tensorflow/python:framework_for_generated_wrappers", "//tensorflow/python:framework_ops", "//tensorflow/python:math_ops", - "//tensorflow/python:spectral_ops", + "//tensorflow/python:spectral_ops_gen", "//tensorflow/python:tensor_util", "//tensorflow/python:util", "//third_party/py/numpy", diff --git a/tensorflow/python/ops/signal/__init__.py b/tensorflow/python/ops/signal/__init__.py deleted file mode 100644 index 3fa4e94e58..0000000000 --- a/tensorflow/python/ops/signal/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Signal processing operations. - -See the [tf.signal](https://tensorflow.org/api_guides/python/contrib.signal) -guide. - -@@frame -@@hamming_window -@@hann_window -@@inverse_stft -@@inverse_stft_window_fn -@@mfccs_from_log_mel_spectrograms -@@linear_to_mel_weight_matrix -@@overlap_and_add -@@stft - -[hamming]: https://en.wikipedia.org/wiki/Window_function#Hamming_window -[hann]: https://en.wikipedia.org/wiki/Window_function#Hann_window -[mel]: https://en.wikipedia.org/wiki/Mel_scale -[mfcc]: https://en.wikipedia.org/wiki/Mel-frequency_cepstrum -[stft]: https://en.wikipedia.org/wiki/Short-time_Fourier_transform -""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -# pylint: disable=unused-import -from tensorflow.python.ops.signal.mel_ops import linear_to_mel_weight_matrix -from tensorflow.python.ops.signal.mfcc_ops import mfccs_from_log_mel_spectrograms -from tensorflow.python.ops.signal.reconstruction_ops import overlap_and_add -from tensorflow.python.ops.signal.shape_ops import frame -from tensorflow.python.ops.signal.spectral_ops import inverse_stft -from tensorflow.python.ops.signal.spectral_ops import inverse_stft_window_fn -from tensorflow.python.ops.signal.spectral_ops import stft -from tensorflow.python.ops.signal.window_ops import hamming_window -from tensorflow.python.ops.signal.window_ops import hann_window -# pylint: enable=unused-import diff --git a/tensorflow/python/ops/signal/dct_ops.py b/tensorflow/python/ops/signal/dct_ops.py new file mode 100644 index 0000000000..d042c95c04 --- /dev/null +++ b/tensorflow/python/ops/signal/dct_ops.py @@ -0,0 +1,192 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Discrete Cosine Transform ops.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import math as _math + +from tensorflow.python.framework import dtypes as _dtypes +from tensorflow.python.framework import ops as _ops +from tensorflow.python.framework import tensor_shape +from tensorflow.python.ops import array_ops as _array_ops +from tensorflow.python.ops import math_ops as _math_ops +from tensorflow.python.ops.signal import fft_ops +from tensorflow.python.util.tf_export import tf_export + + +def _validate_dct_arguments(input_tensor, dct_type, n, axis, norm): + """Checks that DCT/IDCT arguments are compatible and well formed.""" + if n is not None: + raise NotImplementedError("The DCT length argument is not implemented.") + if axis != -1: + raise NotImplementedError("axis must be -1. Got: %s" % axis) + if dct_type not in (1, 2, 3): + raise ValueError("Only Types I, II and III (I)DCT are supported.") + if dct_type == 1: + if norm == "ortho": + raise ValueError("Normalization is not supported for the Type-I DCT.") + if input_tensor.shape[-1] is not None and input_tensor.shape[-1] < 2: + raise ValueError( + "Type-I DCT requires the dimension to be greater than one.") + + if norm not in (None, "ortho"): + raise ValueError( + "Unknown normalization. Expected None or 'ortho', got: %s" % norm) + + +# TODO(rjryan): Implement `n` and `axis` parameters. +@tf_export("signal.dct", v1=["signal.dct", "spectral.dct"]) +def dct(input, type=2, n=None, axis=-1, norm=None, name=None): # pylint: disable=redefined-builtin + """Computes the 1D [Discrete Cosine Transform (DCT)][dct] of `input`. + + Currently only Types I, II and III are supported. + Type I is implemented using a length `2N` padded `tf.spectral.rfft`. + Type II is implemented using a length `2N` padded `tf.spectral.rfft`, as + described here: + https://dsp.stackexchange.com/a/10606. + Type III is a fairly straightforward inverse of Type II + (i.e. using a length `2N` padded `tf.spectral.irfft`). + + @compatibility(scipy) + Equivalent to scipy.fftpack.dct for Type-I, Type-II and Type-III DCT. + https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.fftpack.dct.html + @end_compatibility + + Args: + input: A `[..., samples]` `float32` `Tensor` containing the signals to + take the DCT of. + type: The DCT type to perform. Must be 1, 2 or 3. + n: For future expansion. The length of the transform. Must be `None`. + axis: For future expansion. The axis to compute the DCT along. Must be `-1`. + norm: The normalization to apply. `None` for no normalization or `'ortho'` + for orthonormal normalization. + name: An optional name for the operation. + + Returns: + A `[..., samples]` `float32` `Tensor` containing the DCT of `input`. + + Raises: + ValueError: If `type` is not `1`, `2` or `3`, `n` is not `None, `axis` is + not `-1`, or `norm` is not `None` or `'ortho'`. + ValueError: If `type` is `1` and `norm` is `ortho`. + + [dct]: https://en.wikipedia.org/wiki/Discrete_cosine_transform + """ + _validate_dct_arguments(input, type, n, axis, norm) + with _ops.name_scope(name, "dct", [input]): + # We use the RFFT to compute the DCT and TensorFlow only supports float32 + # for FFTs at the moment. + input = _ops.convert_to_tensor(input, dtype=_dtypes.float32) + + axis_dim = (tensor_shape.dimension_value(input.shape[-1]) + or _array_ops.shape(input)[-1]) + axis_dim_float = _math_ops.to_float(axis_dim) + + if type == 1: + dct1_input = _array_ops.concat([input, input[..., -2:0:-1]], axis=-1) + dct1 = _math_ops.real(fft_ops.rfft(dct1_input)) + return dct1 + + if type == 2: + scale = 2.0 * _math_ops.exp( + _math_ops.complex( + 0.0, -_math_ops.range(axis_dim_float) * _math.pi * 0.5 / + axis_dim_float)) + + # TODO(rjryan): Benchmark performance and memory usage of the various + # approaches to computing a DCT via the RFFT. + dct2 = _math_ops.real( + fft_ops.rfft( + input, fft_length=[2 * axis_dim])[..., :axis_dim] * scale) + + if norm == "ortho": + n1 = 0.5 * _math_ops.rsqrt(axis_dim_float) + n2 = n1 * _math_ops.sqrt(2.0) + # Use tf.pad to make a vector of [n1, n2, n2, n2, ...]. + weights = _array_ops.pad( + _array_ops.expand_dims(n1, 0), [[0, axis_dim - 1]], + constant_values=n2) + dct2 *= weights + + return dct2 + + elif type == 3: + if norm == "ortho": + n1 = _math_ops.sqrt(axis_dim_float) + n2 = n1 * _math_ops.sqrt(0.5) + # Use tf.pad to make a vector of [n1, n2, n2, n2, ...]. + weights = _array_ops.pad( + _array_ops.expand_dims(n1, 0), [[0, axis_dim - 1]], + constant_values=n2) + input *= weights + else: + input *= axis_dim_float + scale = 2.0 * _math_ops.exp( + _math_ops.complex( + 0.0, + _math_ops.range(axis_dim_float) * _math.pi * 0.5 / + axis_dim_float)) + dct3 = _math_ops.real( + fft_ops.irfft( + scale * _math_ops.complex(input, 0.0), + fft_length=[2 * axis_dim]))[..., :axis_dim] + + return dct3 + + +# TODO(rjryan): Implement `n` and `axis` parameters. +@tf_export("signal.idct", v1=["signal.idct", "spectral.idct"]) +def idct(input, type=2, n=None, axis=-1, norm=None, name=None): # pylint: disable=redefined-builtin + """Computes the 1D [Inverse Discrete Cosine Transform (DCT)][idct] of `input`. + + Currently only Types I, II and III are supported. Type III is the inverse of + Type II, and vice versa. + + Note that you must re-normalize by 1/(2n) to obtain an inverse if `norm` is + not `'ortho'`. That is: + `signal == idct(dct(signal)) * 0.5 / signal.shape[-1]`. + When `norm='ortho'`, we have: + `signal == idct(dct(signal, norm='ortho'), norm='ortho')`. + + @compatibility(scipy) + Equivalent to scipy.fftpack.idct for Type-I, Type-II and Type-III DCT. + https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.fftpack.idct.html + @end_compatibility + + Args: + input: A `[..., samples]` `float32` `Tensor` containing the signals to take + the DCT of. + type: The IDCT type to perform. Must be 1, 2 or 3. + n: For future expansion. The length of the transform. Must be `None`. + axis: For future expansion. The axis to compute the DCT along. Must be `-1`. + norm: The normalization to apply. `None` for no normalization or `'ortho'` + for orthonormal normalization. + name: An optional name for the operation. + + Returns: + A `[..., samples]` `float32` `Tensor` containing the IDCT of `input`. + + Raises: + ValueError: If `type` is not `1`, `2` or `3`, `n` is not `None, `axis` is + not `-1`, or `norm` is not `None` or `'ortho'`. + + [idct]: + https://en.wikipedia.org/wiki/Discrete_cosine_transform#Inverse_transforms + """ + _validate_dct_arguments(input, type, n, axis, norm) + inverse_type = {1: 1, 2: 3, 3: 2}[type] + return dct(input, type=inverse_type, n=n, axis=axis, norm=norm, name=name) diff --git a/tensorflow/python/ops/spectral_ops.py b/tensorflow/python/ops/signal/fft_ops.py similarity index 51% rename from tensorflow/python/ops/spectral_ops.py rename to tensorflow/python/ops/signal/fft_ops.py index 4dcc90aefa..2d14b2bbd7 100644 --- a/tensorflow/python/ops/spectral_ops.py +++ b/tensorflow/python/ops/signal/fft_ops.py @@ -12,16 +12,15 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Spectral operators (e.g. DCT, FFT, RFFT).""" +"""Fast-Fourier Transform ops.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import math as _math +import numpy as np from tensorflow.python.framework import dtypes as _dtypes from tensorflow.python.framework import ops as _ops -from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import tensor_util as _tensor_util from tensorflow.python.ops import array_ops as _array_ops from tensorflow.python.ops import gen_spectral_ops @@ -112,6 +111,7 @@ def _rfft_wrapper(fft_fn, fft_rank, default_name): """Wrapper around gen_spectral_ops.rfft* that infers fft_length argument.""" def _rfft(input_tensor, fft_length=None, name=None): + """Wrapper around gen_spectral_ops.rfft* that infers fft_length argument.""" with _ops.name_scope(name, default_name, [input_tensor, fft_length]) as name: input_tensor = _ops.convert_to_tensor(input_tensor, _dtypes.float32) @@ -130,6 +130,7 @@ def _irfft_wrapper(ifft_fn, fft_rank, default_name): """Wrapper around gen_spectral_ops.irfft* that infers fft_length argument.""" def _irfft(input_tensor, fft_length=None, name=None): + """Wrapper irfft* that infers fft_length argument.""" with _ops.name_scope(name, default_name, [input_tensor, fft_length]) as name: input_tensor = _ops.convert_to_tensor(input_tensor, _dtypes.complex64) @@ -145,6 +146,8 @@ def _irfft_wrapper(ifft_fn, fft_rank, default_name): return _irfft +# FFT/IFFT 1/2/3D are exported via +# third_party/tensorflow/core/api_def/python_api/ fft = gen_spectral_ops.fft ifft = gen_spectral_ops.ifft fft2d = gen_spectral_ops.fft2d @@ -152,159 +155,176 @@ ifft2d = gen_spectral_ops.ifft2d fft3d = gen_spectral_ops.fft3d ifft3d = gen_spectral_ops.ifft3d rfft = _rfft_wrapper(gen_spectral_ops.rfft, 1, "rfft") -tf_export("spectral.rfft")(rfft) +tf_export("signal.rfft", v1=["signal.rfft", "spectral.rfft"])(rfft) irfft = _irfft_wrapper(gen_spectral_ops.irfft, 1, "irfft") -tf_export("spectral.irfft")(irfft) +tf_export("signal.irfft", v1=["signal.irfft", "spectral.irfft"])(irfft) rfft2d = _rfft_wrapper(gen_spectral_ops.rfft2d, 2, "rfft2d") -tf_export("spectral.rfft2d")(rfft2d) +tf_export("signal.rfft2d", v1=["signal.rfft2d", "spectral.rfft2d"])(rfft2d) irfft2d = _irfft_wrapper(gen_spectral_ops.irfft2d, 2, "irfft2d") -tf_export("spectral.irfft2d")(irfft2d) +tf_export("signal.irfft2d", v1=["signal.irfft2d", "spectral.irfft2d"])(irfft2d) rfft3d = _rfft_wrapper(gen_spectral_ops.rfft3d, 3, "rfft3d") -tf_export("spectral.rfft3d")(rfft3d) +tf_export("signal.rfft3d", v1=["signal.rfft3d", "spectral.rfft3d"])(rfft3d) irfft3d = _irfft_wrapper(gen_spectral_ops.irfft3d, 3, "irfft3d") -tf_export("spectral.irfft3d")(irfft3d) - - -def _validate_dct_arguments(dct_type, n, axis, norm): - if n is not None: - raise NotImplementedError("The DCT length argument is not implemented.") - if axis != -1: - raise NotImplementedError("axis must be -1. Got: %s" % axis) - if dct_type not in (2, 3): - raise ValueError("Only Types II and III (I)DCT are supported.") - if norm not in (None, "ortho"): - raise ValueError( - "Unknown normalization. Expected None or 'ortho', got: %s" % norm) - - -# TODO(rjryan): Implement `type`, `n` and `axis` parameters. -@tf_export("spectral.dct") -def dct(input, type=2, n=None, axis=-1, norm=None, name=None): # pylint: disable=redefined-builtin - """Computes the 1D [Discrete Cosine Transform (DCT)][dct] of `input`. - - Currently only Types II and III are supported. Type II is implemented using a - length `2N` padded `tf.spectral.rfft`, as described here: - https://dsp.stackexchange.com/a/10606. Type III is a fairly straightforward - inverse of Type II (i.e. using a length `2N` padded `tf.spectral.irfft`). - - @compatibility(scipy) - Equivalent to scipy.fftpack.dct for Type-II and Type-III DCT. - https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.fftpack.dct.html - @end_compatibility - - Args: - input: A `[..., samples]` `float32` `Tensor` containing the signals to - take the DCT of. - type: The DCT type to perform. Must be 2 or 3. - n: For future expansion. The length of the transform. Must be `None`. - axis: For future expansion. The axis to compute the DCT along. Must be `-1`. - norm: The normalization to apply. `None` for no normalization or `'ortho'` - for orthonormal normalization. - name: An optional name for the operation. - - Returns: - A `[..., samples]` `float32` `Tensor` containing the DCT of `input`. - - Raises: - ValueError: If `type` is not `2` or `3`, `n` is not `None, `axis` is not - `-1`, or `norm` is not `None` or `'ortho'`. - - [dct]: https://en.wikipedia.org/wiki/Discrete_cosine_transform - """ - _validate_dct_arguments(type, n, axis, norm) - with _ops.name_scope(name, "dct", [input]): - # We use the RFFT to compute the DCT and TensorFlow only supports float32 - # for FFTs at the moment. - input = _ops.convert_to_tensor(input, dtype=_dtypes.float32) - - axis_dim = (tensor_shape.dimension_value(input.shape[-1]) - or _array_ops.shape(input)[-1]) - axis_dim_float = _math_ops.to_float(axis_dim) - if type == 2: - scale = 2.0 * _math_ops.exp( - _math_ops.complex( - 0.0, -_math_ops.range(axis_dim_float) * _math.pi * 0.5 / - axis_dim_float)) - - # TODO(rjryan): Benchmark performance and memory usage of the various - # approaches to computing a DCT via the RFFT. - dct2 = _math_ops.real( - rfft(input, fft_length=[2 * axis_dim])[..., :axis_dim] * scale) - - if norm == "ortho": - n1 = 0.5 * _math_ops.rsqrt(axis_dim_float) - n2 = n1 * _math_ops.sqrt(2.0) - # Use tf.pad to make a vector of [n1, n2, n2, n2, ...]. - weights = _array_ops.pad( - _array_ops.expand_dims(n1, 0), [[0, axis_dim - 1]], - constant_values=n2) - dct2 *= weights - - return dct2 - - elif type == 3: - if norm == "ortho": - n1 = _math_ops.sqrt(axis_dim_float) - n2 = n1 * _math_ops.sqrt(0.5) - # Use tf.pad to make a vector of [n1, n2, n2, n2, ...]. - weights = _array_ops.pad( - _array_ops.expand_dims(n1, 0), [[0, axis_dim - 1]], - constant_values=n2) - input *= weights - else: - input *= axis_dim_float - scale = 2.0 * _math_ops.exp( - _math_ops.complex( - 0.0, - _math_ops.range(axis_dim_float) * _math.pi * 0.5 / - axis_dim_float)) - dct3 = _math_ops.real( - irfft( - scale * _math_ops.complex(input, 0.0), - fft_length=[2 * axis_dim]))[..., :axis_dim] - - return dct3 - - -# TODO(rjryan): Implement `type`, `n` and `axis` parameters. -@tf_export("spectral.idct") -def idct(input, type=2, n=None, axis=-1, norm=None, name=None): # pylint: disable=redefined-builtin - """Computes the 1D [Inverse Discrete Cosine Transform (DCT)][idct] of `input`. - - Currently only Types II and III are supported. Type III is the inverse of - Type II, and vice versa. - - Note that you must re-normalize by 1/(2n) to obtain an inverse if `norm` is - not `'ortho'`. That is: - `signal == idct(dct(signal)) * 0.5 / signal.shape[-1]`. - When `norm='ortho'`, we have: - `signal == idct(dct(signal, norm='ortho'), norm='ortho')`. - - @compatibility(scipy) - Equivalent to scipy.fftpack.idct for Type-II and Type-III DCT. - https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.fftpack.idct.html - @end_compatibility - - Args: - input: A `[..., samples]` `float32` `Tensor` containing the signals to take - the DCT of. - type: The IDCT type to perform. Must be 2 or 3. - n: For future expansion. The length of the transform. Must be `None`. - axis: For future expansion. The axis to compute the DCT along. Must be `-1`. - norm: The normalization to apply. `None` for no normalization or `'ortho'` - for orthonormal normalization. - name: An optional name for the operation. - - Returns: - A `[..., samples]` `float32` `Tensor` containing the IDCT of `input`. - - Raises: - ValueError: If `type` is not `2` or `3`, `n` is not `None, `axis` is not - `-1`, or `norm` is not `None` or `'ortho'`. - - [idct]: - https://en.wikipedia.org/wiki/Discrete_cosine_transform#Inverse_transforms - """ - _validate_dct_arguments(type, n, axis, norm) - inverse_type = {2: 3, 3: 2}[type] - return dct(input, type=inverse_type, n=n, axis=axis, norm=norm, name=name) +tf_export("signal.irfft3d", v1=["signal.irfft3d", "spectral.irfft3d"])(irfft3d) + + +def _fft_size_for_grad(grad, rank): + return _math_ops.reduce_prod(_array_ops.shape(grad)[-rank:]) + + +@_ops.RegisterGradient("FFT") +def _fft_grad(_, grad): + size = _math_ops.cast(_fft_size_for_grad(grad, 1), grad.dtype) + return ifft(grad) * size + + +@_ops.RegisterGradient("IFFT") +def _ifft_grad(_, grad): + rsize = _math_ops.cast( + 1. / _math_ops.cast(_fft_size_for_grad(grad, 1), grad.dtype.real_dtype), + grad.dtype) + return fft(grad) * rsize + + +@_ops.RegisterGradient("FFT2D") +def _fft2d_grad(_, grad): + size = _math_ops.cast(_fft_size_for_grad(grad, 2), grad.dtype) + return ifft2d(grad) * size + + +@_ops.RegisterGradient("IFFT2D") +def _ifft2d_grad(_, grad): + rsize = _math_ops.cast( + 1. / _math_ops.cast(_fft_size_for_grad(grad, 2), grad.dtype.real_dtype), + grad.dtype) + return fft2d(grad) * rsize + + +@_ops.RegisterGradient("FFT3D") +def _fft3d_grad(_, grad): + size = _math_ops.cast(_fft_size_for_grad(grad, 3), grad.dtype) + return ifft3d(grad) * size + + +@_ops.RegisterGradient("IFFT3D") +def _ifft3d_grad(_, grad): + rsize = _math_ops.cast( + 1. / _math_ops.cast(_fft_size_for_grad(grad, 3), grad.dtype.real_dtype), + grad.dtype) + return fft3d(grad) * rsize + + +def _rfft_grad_helper(rank, irfft_fn): + """Returns a gradient function for an RFFT of the provided rank.""" + # Can't happen because we don't register a gradient for RFFT3D. + assert rank in (1, 2), "Gradient for RFFT3D is not implemented." + + def _grad(op, grad): + """A gradient function for RFFT with the provided `rank` and `irfft_fn`.""" + fft_length = op.inputs[1] + input_shape = _array_ops.shape(op.inputs[0]) + is_even = _math_ops.cast(1 - (fft_length[-1] % 2), _dtypes.complex64) + + def _tile_for_broadcasting(matrix, t): + expanded = _array_ops.reshape( + matrix, + _array_ops.concat([ + _array_ops.ones([_array_ops.rank(t) - 2], _dtypes.int32), + _array_ops.shape(matrix) + ], 0)) + return _array_ops.tile( + expanded, _array_ops.concat([_array_ops.shape(t)[:-2], [1, 1]], 0)) + + def _mask_matrix(length): + """Computes t_n = exp(sqrt(-1) * pi * n^2 / line_len).""" + # TODO(rjryan): Speed up computation of twiddle factors using the + # following recurrence relation and cache them across invocations of RFFT. + # + # t_n = exp(sqrt(-1) * pi * n^2 / line_len) + # for n = 0, 1,..., line_len-1. + # For n > 2, use t_n = t_{n-1}^2 / t_{n-2} * t_1^2 + a = _array_ops.tile( + _array_ops.expand_dims(_math_ops.range(length), 0), (length, 1)) + b = _array_ops.transpose(a, [1, 0]) + return _math_ops.exp( + -2j * np.pi * _math_ops.cast(a * b, _dtypes.complex64) / + _math_ops.cast(length, _dtypes.complex64)) + + def _ymask(length): + """A sequence of [1+0j, -1+0j, 1+0j, -1+0j, ...] with length `length`.""" + return _math_ops.cast(1 - 2 * (_math_ops.range(length) % 2), + _dtypes.complex64) + + y0 = grad[..., 0:1] + if rank == 1: + ym = grad[..., -1:] + extra_terms = y0 + is_even * ym * _ymask(input_shape[-1]) + elif rank == 2: + # Create a mask matrix for y0 and ym. + base_mask = _mask_matrix(input_shape[-2]) + + # Tile base_mask to match y0 in shape so that we can batch-matmul the + # inner 2 dimensions. + tiled_mask = _tile_for_broadcasting(base_mask, y0) + + y0_term = _math_ops.matmul(tiled_mask, _math_ops.conj(y0)) + extra_terms = y0_term + + ym = grad[..., -1:] + ym_term = _math_ops.matmul(tiled_mask, _math_ops.conj(ym)) + + inner_dim = input_shape[-1] + ym_term = _array_ops.tile( + ym_term, + _array_ops.concat([ + _array_ops.ones([_array_ops.rank(grad) - 1], _dtypes.int32), + [inner_dim] + ], 0)) * _ymask(inner_dim) + + extra_terms += is_even * ym_term + + # The gradient of RFFT is the IRFFT of the incoming gradient times a scaling + # factor, plus some additional terms to make up for the components dropped + # due to Hermitian symmetry. + input_size = _math_ops.to_float(_fft_size_for_grad(op.inputs[0], rank)) + the_irfft = irfft_fn(grad, fft_length) + return 0.5 * (the_irfft * input_size + _math_ops.real(extra_terms)), None + + return _grad + + +def _irfft_grad_helper(rank, rfft_fn): + """Returns a gradient function for an IRFFT of the provided rank.""" + # Can't happen because we don't register a gradient for IRFFT3D. + assert rank in (1, 2), "Gradient for IRFFT3D is not implemented." + + def _grad(op, grad): + """A gradient function for IRFFT with the provided `rank` and `rfft_fn`.""" + # Generate a simple mask like [1.0, 2.0, ..., 2.0, 1.0] for even-length FFTs + # and [1.0, 2.0, ..., 2.0] for odd-length FFTs. To reduce extra ops in the + # graph we special-case the situation where the FFT length and last + # dimension of the input are known at graph construction time. + fft_length = op.inputs[1] + is_odd = _math_ops.mod(fft_length[-1], 2) + input_last_dimension = _array_ops.shape(op.inputs[0])[-1] + mask = _array_ops.concat( + [[1.0], 2.0 * _array_ops.ones([input_last_dimension - 2 + is_odd]), + _array_ops.ones([1 - is_odd])], 0) + + rsize = _math_ops.reciprocal(_math_ops.to_float( + _fft_size_for_grad(grad, rank))) + + # The gradient of IRFFT is the RFFT of the incoming gradient times a scaling + # factor and a mask. The mask scales the gradient for the Hermitian + # symmetric components of the RFFT by a factor of two, since these + # components are de-duplicated in the RFFT. + the_rfft = rfft_fn(grad, fft_length) + return the_rfft * _math_ops.cast(rsize * mask, _dtypes.complex64), None + + return _grad + + +_ops.RegisterGradient("RFFT")(_rfft_grad_helper(1, irfft)) +_ops.RegisterGradient("IRFFT")(_irfft_grad_helper(1, rfft)) +_ops.RegisterGradient("RFFT2D")(_rfft_grad_helper(2, irfft2d)) +_ops.RegisterGradient("IRFFT2D")(_irfft_grad_helper(2, rfft2d)) diff --git a/tensorflow/python/ops/signal/mfcc_ops.py b/tensorflow/python/ops/signal/mfcc_ops.py index 6ae3b222ba..601409dea9 100644 --- a/tensorflow/python/ops/signal/mfcc_ops.py +++ b/tensorflow/python/ops/signal/mfcc_ops.py @@ -22,7 +22,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops -from tensorflow.python.ops import spectral_ops +from tensorflow.python.ops.signal import dct_ops from tensorflow.python.util.tf_export import tf_export @@ -106,5 +106,5 @@ def mfccs_from_log_mel_spectrograms(log_mel_spectrograms, name=None): else: num_mel_bins = array_ops.shape(log_mel_spectrograms)[-1] - dct2 = spectral_ops.dct(log_mel_spectrograms) + dct2 = dct_ops.dct(log_mel_spectrograms, type=2) return dct2 * math_ops.rsqrt(math_ops.to_float(num_mel_bins) * 2.0) diff --git a/tensorflow/python/ops/signal/reconstruction_ops.py b/tensorflow/python/ops/signal/reconstruction_ops.py index 0fc7fec239..4eaab4e0a0 100644 --- a/tensorflow/python/ops/signal/reconstruction_ops.py +++ b/tensorflow/python/ops/signal/reconstruction_ops.py @@ -18,46 +18,14 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops -from tensorflow.python.ops.signal import shape_ops -from tensorflow.python.ops.signal import util_ops from tensorflow.python.util.tf_export import tf_export -def _shuffle_to_front(input_tensor, k): - """Shuffles the last `k` indices of `input_tensor` to the front. - - Transposes `input_tensor` to have the last `k` indices at the front. The input - may have arbitrary rank and unknown shape. - - Args: - input_tensor: A `Tensor` of arbitrary rank and unknown shape. - k: A scalar `Tensor` specifying how many indices to shuffle. - - Returns: - A transposed version of `input_tensor` with `k` indices shuffled to the - front. - - Raises: - ValueError: If `input_tensor` is not at least rank `k` or `k` is not scalar. - """ - k = ops.convert_to_tensor(k, name="k") - k.shape.with_rank(0) - k_static = tensor_util.constant_value(k) - if k_static is not None: - input_tensor.shape.with_rank_at_least(k_static) - - rank = array_ops.rank(input_tensor) - outer_indices, inner_indices = array_ops.split(math_ops.range(rank), - [rank - k, k]) - permutation = array_ops.concat([inner_indices, outer_indices], 0) - - return array_ops.transpose(input_tensor, perm=permutation) - - @tf_export("signal.overlap_and_add") def overlap_and_add(signal, frame_step, name=None): """Reconstructs a signal from a framed representation. @@ -80,8 +48,8 @@ def overlap_and_add(signal, frame_step, name=None): frames of `signal`'s inner-most two dimensions. Raises: - ValueError: If `signal`'s rank is less than 2, `frame_step` is not a scalar - integer or `frame_step` is greater than `frame_length`. + ValueError: If `signal`'s rank is less than 2, or `frame_step` is not a + scalar integer. """ with ops.name_scope(name, "overlap_and_add", [signal, frame_step]): signal = ops.convert_to_tensor(signal, name="signal") @@ -97,56 +65,91 @@ def overlap_and_add(signal, frame_step, name=None): # All dimensions that are not part of the overlap-and-add. Can be empty for # rank 2 inputs. outer_dimensions = signal_shape[:-2] + outer_rank = array_ops.size(outer_dimensions) + + def full_shape(inner_shape): + return array_ops.concat([outer_dimensions, inner_shape], 0) - # If frame_length and frame_step are known at graph construction time, check - # frame_step is less than or equal to frame_length. - frame_step_static = tensor_util.constant_value(frame_step) - if (frame_step_static is not None and signal.shape.ndims is not None and - signal.shape.dims[-1].value is not None): - if frame_step_static > signal.shape.dims[-1].value: - raise ValueError( - "frame_step (%d) must be less than or equal to " - "frame_length (%d)" % ( - frame_step_static, signal.shape.dims[-1].value)) - # If frame_length is equal to frame_step, there's no overlap so just - # reshape the tensor. - if frame_step_static == signal.shape.dims[-1].value: - return array_ops.reshape(signal, array_ops.concat( - [outer_dimensions, [-1]], 0)) - - signal_rank = array_ops.rank(signal) - frames = signal_shape[-2] frame_length = signal_shape[-1] + frames = signal_shape[-2] - subframe_length = util_ops.gcd(frame_length, frame_step) - subframe_step = frame_step // subframe_length - subframes_per_frame = frame_length // subframe_length - output_size = frame_step * (frames - 1) + frame_length - output_subframes = output_size // subframe_length - - # To avoid overlap-adding sample-by-sample, we overlap-add at the "subframe" - # level, where a subframe is gcd(frame_length, frame_step). Reshape signal - # from [..., frames, frame_length] into [..., subframes, subframe_length]. - subframe_shape = array_ops.concat( - [outer_dimensions, [-1, subframe_length]], 0) - subframe_signal = array_ops.reshape(signal, subframe_shape) - - # Now we shuffle the last [subframes, subframe_length] dimensions to the - # front. - # TODO(rjryan): Add an axis argument to unsorted_segment_sum so we can - # avoid this pair of transposes. - subframe_signal = _shuffle_to_front(subframe_signal, 2) - - # Use unsorted_segment_sum to add overlapping subframes together. - segment_ids = array_ops.reshape(shape_ops.frame( - math_ops.range(output_subframes), subframes_per_frame, subframe_step, - pad_end=False), [-1]) - result = math_ops.unsorted_segment_sum(subframe_signal, segment_ids, - num_segments=output_subframes) - - # result is a [subframes, subframe_length, ...outer_dimensions] tensor. We - # return a [...outer_dimensions, output_size] tensor with a transpose and - # reshape. - result_shape = array_ops.concat([outer_dimensions, [output_size]], 0) - return array_ops.reshape(_shuffle_to_front(result, signal_rank - 2), - result_shape) + # Compute output length. + output_length = frame_length + frame_step * (frames - 1) + + # If frame_length is equal to frame_step, there's no overlap so just + # reshape the tensor. + frame_step_static = tensor_util.constant_value(frame_step) + if (frame_step_static is not None and signal.shape.dims is not None and + frame_step_static == signal.shape.dims[-1].value): + output_shape = full_shape([output_length]) + return array_ops.reshape(signal, output_shape, name="fast_path") + + # The following code is documented using this example: + # + # frame_step = 2 + # signal.shape = (3, 5) + # a b c d e + # f g h i j + # k l m n o + + # Compute the number of segments, per frame. + segments = -(-frame_length // frame_step) # Divide and round up. + + # Pad the frame_length dimension to a multiple of the frame step. + # Pad the frames dimension by `segments` so that signal.shape = (6, 6) + # a b c d e 0 + # f g h i j 0 + # k l m n o 0 + # 0 0 0 0 0 0 + # 0 0 0 0 0 0 + # 0 0 0 0 0 0 + paddings = [[0, segments], [0, segments * frame_step - frame_length]] + outer_paddings = array_ops.zeros([outer_rank, 2], dtypes.int32) + paddings = array_ops.concat([outer_paddings, paddings], 0) + signal = array_ops.pad(signal, paddings) + + # Reshape so that signal.shape = (3, 6, 2) + # ab cd e0 + # fg hi j0 + # kl mn o0 + # 00 00 00 + # 00 00 00 + # 00 00 00 + shape = full_shape([frames + segments, segments, frame_step]) + signal = array_ops.reshape(signal, shape) + + # Transpose dimensions so that signal.shape = (3, 6, 2) + # ab fg kl 00 00 00 + # cd hi mn 00 00 00 + # e0 j0 o0 00 00 00 + perm = array_ops.concat( + [math_ops.range(outer_rank), outer_rank + [1, 0, 2]], 0) + signal = array_ops.transpose(signal, perm) + + # Reshape so that signal.shape = (18, 2) + # ab fg kl 00 00 00 cd hi mn 00 00 00 e0 j0 o0 00 00 00 + shape = full_shape([(frames + segments) * segments, frame_step]) + signal = array_ops.reshape(signal, shape) + + # Truncate so that signal.shape = (15, 2) + # ab fg kl 00 00 00 cd hi mn 00 00 00 e0 j0 o0 + signal = signal[..., :(frames + segments - 1) * segments, :] + + # Reshape so that signal.shape = (3, 5, 2) + # ab fg kl 00 00 + # 00 cd hi mn 00 + # 00 00 e0 j0 o0 + shape = full_shape([segments, (frames + segments - 1), frame_step]) + signal = array_ops.reshape(signal, shape) + + # Now, reduce over the columns, to achieve the desired sum. + signal = math_ops.reduce_sum(signal, -3) + + # Flatten the array. + shape = full_shape([(frames + segments - 1) * frame_step]) + signal = array_ops.reshape(signal, shape) + + # Truncate to final length. + signal = signal[..., :output_length] + + return signal diff --git a/tensorflow/python/ops/signal/shape_ops.py b/tensorflow/python/ops/signal/shape_ops.py index 02dd7c97e8..ae9c2ef28e 100644 --- a/tensorflow/python/ops/signal/shape_ops.py +++ b/tensorflow/python/ops/signal/shape_ops.py @@ -71,7 +71,7 @@ def frame(signal, frame_length, frame_step, pad_end=False, pad_value=0, axis=-1, ```python pcm = tf.placeholder(tf.float32, [None, 9152]) frames = tf.signal.frame(pcm, 512, 180) - magspec = tf.abs(tf.spectral.rfft(frames, [512])) + magspec = tf.abs(tf.signal.rfft(frames, [512])) image = tf.expand_dims(magspec, 3) ``` diff --git a/tensorflow/python/ops/signal/signal.py b/tensorflow/python/ops/signal/signal.py new file mode 100644 index 0000000000..cdc4d1c191 --- /dev/null +++ b/tensorflow/python/ops/signal/signal.py @@ -0,0 +1,65 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Signal processing operations. + +See the [tf.signal](https://tensorflow.org/api_guides/python/contrib.signal) +guide. + +@@frame +@@hamming_window +@@hann_window +@@inverse_stft +@@inverse_stft_window_fn +@@mfccs_from_log_mel_spectrograms +@@linear_to_mel_weight_matrix +@@overlap_and_add +@@stft + +[hamming]: https://en.wikipedia.org/wiki/Window_function#Hamming_window +[hann]: https://en.wikipedia.org/wiki/Window_function#Hann_window +[mel]: https://en.wikipedia.org/wiki/Mel_scale +[mfcc]: https://en.wikipedia.org/wiki/Mel-frequency_cepstrum +[stft]: https://en.wikipedia.org/wiki/Short-time_Fourier_transform +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +# pylint: disable=unused-import +from tensorflow.python.ops.signal.dct_ops import dct +from tensorflow.python.ops.signal.dct_ops import idct +from tensorflow.python.ops.signal.fft_ops import fft +from tensorflow.python.ops.signal.fft_ops import fft2d +from tensorflow.python.ops.signal.fft_ops import fft3d +from tensorflow.python.ops.signal.fft_ops import ifft +from tensorflow.python.ops.signal.fft_ops import ifft2d +from tensorflow.python.ops.signal.fft_ops import ifft3d +from tensorflow.python.ops.signal.fft_ops import irfft +from tensorflow.python.ops.signal.fft_ops import irfft2d +from tensorflow.python.ops.signal.fft_ops import irfft3d +from tensorflow.python.ops.signal.fft_ops import rfft +from tensorflow.python.ops.signal.fft_ops import rfft2d +from tensorflow.python.ops.signal.fft_ops import rfft3d +from tensorflow.python.ops.signal.mel_ops import linear_to_mel_weight_matrix +from tensorflow.python.ops.signal.mfcc_ops import mfccs_from_log_mel_spectrograms +from tensorflow.python.ops.signal.reconstruction_ops import overlap_and_add +from tensorflow.python.ops.signal.shape_ops import frame +from tensorflow.python.ops.signal.spectral_ops import inverse_stft +from tensorflow.python.ops.signal.spectral_ops import inverse_stft_window_fn +from tensorflow.python.ops.signal.spectral_ops import stft +from tensorflow.python.ops.signal.window_ops import hamming_window +from tensorflow.python.ops.signal.window_ops import hann_window +# pylint: enable=unused-import diff --git a/tensorflow/python/ops/signal/spectral_ops.py b/tensorflow/python/ops/signal/spectral_ops.py index b0b7d964b9..f029e0a8b5 100644 --- a/tensorflow/python/ops/signal/spectral_ops.py +++ b/tensorflow/python/ops/signal/spectral_ops.py @@ -25,7 +25,7 @@ from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops -from tensorflow.python.ops import spectral_ops +from tensorflow.python.ops.signal import fft_ops from tensorflow.python.ops.signal import reconstruction_ops from tensorflow.python.ops.signal import shape_ops from tensorflow.python.ops.signal import window_ops @@ -86,9 +86,9 @@ def stft(signals, frame_length, frame_step, fft_length=None, window = window_fn(frame_length, dtype=framed_signals.dtype) framed_signals *= window - # spectral_ops.rfft produces the (fft_length/2 + 1) unique components of the + # fft_ops.rfft produces the (fft_length/2 + 1) unique components of the # FFT of the real windowed signals in framed_signals. - return spectral_ops.rfft(framed_signals, [fft_length]) + return fft_ops.rfft(framed_signals, [fft_length]) @tf_export('signal.inverse_stft_window_fn') @@ -232,7 +232,7 @@ def inverse_stft(stfts, fft_length = ops.convert_to_tensor(fft_length, name='fft_length') fft_length.shape.assert_has_rank(0) - real_frames = spectral_ops.irfft(stfts, [fft_length]) + real_frames = fft_ops.irfft(stfts, [fft_length]) # frame_length may be larger or smaller than fft_length, so we pad or # truncate real_frames to frame_length. diff --git a/tensorflow/python/ops/sort_ops.py b/tensorflow/python/ops/sort_ops.py new file mode 100644 index 0000000000..c3e23d701e --- /dev/null +++ b/tensorflow/python/ops/sort_ops.py @@ -0,0 +1,197 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Support for sorting tensors. + +@@argsort +@@sort +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import ops as framework_ops +from tensorflow.python.framework import tensor_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import nn_ops +from tensorflow.python.util.tf_export import tf_export + + +@tf_export('sort') +def sort(values, axis=-1, direction='ASCENDING', name=None): + """Sorts a tensor. + + Args: + values: 1-D or higher numeric `Tensor`. + axis: The axis along which to sort. The default is -1, which sorts the last + axis. + direction: The direction in which to sort the values (`'ASCENDING'` or + `'DESCENDING'`). + name: Optional name for the operation. + + Returns: + A `Tensor` with the same dtype and shape as `values`, with the elements + sorted along the given `axis`. + + Raises: + ValueError: If axis is not a constant scalar, or the direction is invalid. + """ + with framework_ops.name_scope(name, 'sort'): + return _sort_or_argsort(values, axis, direction, return_argsort=False) + + +@tf_export('argsort') +def argsort(values, axis=-1, direction='ASCENDING', stable=False, name=None): + """Returns the indices of a tensor that give its sorted order along an axis. + + For a 1D tensor, `tf.gather(values, tf.argsort(values))` is equivalent to + `tf.sort(values)`. For higher dimensions, the output has the same shape as + `values`, but along the given axis, values represent the index of the sorted + element in that slice of the tensor at the given position. + + Args: + values: 1-D or higher numeric `Tensor`. + axis: The axis along which to sort. The default is -1, which sorts the last + axis. + direction: The direction in which to sort the values (`'ASCENDING'` or + `'DESCENDING'`). + stable: If True, equal elements in the original tensor will not be + re-ordered in the returned order. Unstable sort is not yet implemented, + but will eventually be the default for performance reasons. If you require + a stable order, pass `stable=True` for forwards compatibility. + name: Optional name for the operation. + + Returns: + An int32 `Tensor` with the same shape as `values`. The indices that would + sort each slice of the given `values` along the given `axis`. + + Raises: + ValueError: If axis is not a constant scalar, or the direction is invalid. + """ + del stable # Unused. + with framework_ops.name_scope(name, 'argsort'): + return _sort_or_argsort(values, axis, direction, return_argsort=True) + + +def _sort_or_argsort(values, axis, direction, return_argsort): + """Internal sort/argsort implementation. + + Args: + values: The input values. + axis: The axis along which to sort. + direction: 'ASCENDING' or 'DESCENDING'. + return_argsort: Whether to return the argsort result. + + Returns: + Either the sorted values, or the indices of the sorted values in the + original tensor. See the `sort` and `argsort` docstrings. + + Raises: + ValueError: If axis is not a constant scalar, or the direction is invalid. + """ + if direction not in _SORT_IMPL: + raise ValueError('%s should be one of %s' % (direction, ', '.join( + sorted(_SORT_IMPL.keys())))) + # Axis must be an integer, not a Tensor. + axis = framework_ops.convert_to_tensor(axis, name='axis') + axis_static = tensor_util.constant_value(axis) + if axis.shape.ndims != 0 or axis_static is None: + raise ValueError('axis must be a constant scalar') + axis_static = int(axis_static) # Avoids NumPy casting error + + values = framework_ops.convert_to_tensor(values, name='values') + + return _SORT_IMPL[direction](values, axis_static, return_argsort) + + +def _descending_sort(values, axis, return_argsort=False): + """Sorts values in reverse using `top_k`. + + Args: + values: Tensor of numeric values. + axis: Index of the axis which values should be sorted along. + return_argsort: If False, return the sorted values. If True, return the + indices that would sort the values. + + Returns: + The sorted values. + """ + k = array_ops.shape(values)[axis] + rank = array_ops.rank(values) + static_rank = values.shape.ndims + # Fast path: sorting the last axis. + if axis == -1 or axis + 1 == values.get_shape().ndims: + top_k_input = values + transposition = None + else: + # Otherwise, transpose the array. Swap axes `axis` and `rank - 1`. + if axis < 0: + # Calculate the actual axis index if counting from the end. Use the static + # rank if available, or else make the axis back into a tensor. + axis += static_rank or rank + if static_rank is not None: + # Prefer to calculate the transposition array in NumPy and make it a + # constant. + transposition = constant_op.constant( + np.r_[ + # Axes up to axis are unchanged. + np.arange(axis), + # Swap axis and rank - 1. + [static_rank - 1], + # Axes in [axis + 1, rank - 1) are unchanged. + np.arange(axis + 1, static_rank - 1), + # Swap axis and rank - 1. + [axis]], + name='transposition') + else: + # Generate the transposition array from the tensors. + transposition = array_ops.concat( + [ + # Axes up to axis are unchanged. + math_ops.range(axis), + # Swap axis and rank - 1. + [rank - 1], + # Axes in [axis + 1, rank - 1) are unchanged. + math_ops.range(axis + 1, rank - 1), + # Swap axis and rank - 1. + [axis] + ], + axis=0) + top_k_input = array_ops.transpose(values, transposition) + + values, indices = nn_ops.top_k(top_k_input, k) + return_value = indices if return_argsort else values + if transposition is not None: + # transposition contains a single cycle of length 2 (swapping 2 elements), + # so it is an involution (it is its own inverse). + return_value = array_ops.transpose(return_value, transposition) + return return_value + + +def _ascending_sort(values, axis, return_argsort=False): + # Negate the values to get the ascending order from descending sort. + values_or_indices = _descending_sort(-values, axis, return_argsort) + # If not argsort, negate the values again. + return values_or_indices if return_argsort else -values_or_indices + + +_SORT_IMPL = { + 'ASCENDING': _ascending_sort, + 'DESCENDING': _descending_sort, +} diff --git a/tensorflow/contrib/framework/python/ops/sort_ops_test.py b/tensorflow/python/ops/sort_ops_test.py similarity index 90% rename from tensorflow/contrib/framework/python/ops/sort_ops_test.py rename to tensorflow/python/ops/sort_ops_test.py index 791b32cd1e..17ce604cbf 100644 --- a/tensorflow/contrib/framework/python/ops/sort_ops_test.py +++ b/tensorflow/python/ops/sort_ops_test.py @@ -20,22 +20,25 @@ from __future__ import print_function import numpy as np -from tensorflow.contrib.framework.python.ops import sort_ops from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops +from tensorflow.python.ops import sort_ops from tensorflow.python.platform import test class SortTest(test.TestCase): + @test_util.run_deprecated_v1 def testRandom_lowDimensionality(self): self._testRandom_lowDimensionality(negative_axis=False) + @test_util.run_deprecated_v1 def testRandom_lowDimensionality_negative(self): self._testRandom_lowDimensionality(negative_axis=True) @@ -53,6 +56,7 @@ class SortTest(test.TestCase): np.sort(arr, axis=sort_axis), sort_ops.sort(constant_op.constant(arr), axis=sort_axis).eval()) + @test_util.run_deprecated_v1 def testRandom_highDimensionality(self): np.random.seed(100) for _ in range(20): @@ -65,6 +69,7 @@ class SortTest(test.TestCase): np.sort(arr, axis=sort_axis), sort_ops.sort(constant_op.constant(arr), axis=sort_axis).eval()) + @test_util.run_deprecated_v1 def testScalar(self): # Create an empty scalar where the static shape is unknown. zeros_length_1 = array_ops.zeros( @@ -77,21 +82,22 @@ class SortTest(test.TestCase): with self.assertRaises(errors.InvalidArgumentError): sort.eval() + @test_util.run_deprecated_v1 def testNegativeOutOfBounds_staticShape(self): arr = constant_op.constant([3, 4, 5]) with self.assertRaises(ValueError): sort_ops.sort(arr, axis=-4) + @test_util.run_deprecated_v1 def testDescending(self): arr = np.random.random((10, 5, 5)) with self.cached_session(): self.assertAllEqual( np.sort(arr, axis=0)[::-1], sort_ops.sort( - constant_op.constant(arr), - axis=0, - direction='DESCENDING').eval()) + constant_op.constant(arr), axis=0, direction='DESCENDING').eval()) + @test_util.run_deprecated_v1 def testSort_staticallyKnownRank_constantTransposition(self): # The transposition array should be a constant if the rank of "values" is # statically known. @@ -109,6 +115,7 @@ class SortTest(test.TestCase): tensor_util.constant_value(transposition), [0, 4, 2, 3, 1]) + @test_util.run_deprecated_v1 def testArgsort_1d(self): arr = np.random.random(42) with self.cached_session(): @@ -116,6 +123,7 @@ class SortTest(test.TestCase): np.sort(arr), array_ops.gather(arr, sort_ops.argsort(arr)).eval()) + @test_util.run_deprecated_v1 def testArgsort(self): arr = np.random.random((5, 6, 7, 8)) for axis in range(4): diff --git a/tensorflow/python/ops/sparse_grad.py b/tensorflow/python/ops/sparse_grad.py index 1223b290ff..2ca9c0c647 100644 --- a/tensorflow/python/ops/sparse_grad.py +++ b/tensorflow/python/ops/sparse_grad.py @@ -195,7 +195,7 @@ def _SparseTensorDenseMatMulGrad(op, grad): parts_a = array_ops.gather(grad, rows if not adj_a else cols) parts_b = array_ops.gather(b if not adj_b else array_ops.transpose(b), cols if not adj_a else rows) - a_values_grad = math_ops.reduce_sum(parts_a * parts_b, reduction_indices=1) + a_values_grad = math_ops.reduce_sum(parts_a * parts_b, axis=1) # gradients w.r.t. (a_indices, a_values, a_shape, b) return (None, a_values_grad, None, b_grad) diff --git a/tensorflow/python/ops/sparse_ops.py b/tensorflow/python/ops/sparse_ops.py index b98c7f5f65..346ab9c0cb 100644 --- a/tensorflow/python/ops/sparse_ops.py +++ b/tensorflow/python/ops/sparse_ops.py @@ -44,6 +44,9 @@ from tensorflow.python.ops.gen_sparse_ops import * # pylint: enable=wildcard-import from tensorflow.python.util import compat from tensorflow.python.util import deprecation +from tensorflow.python.util import dispatch +from tensorflow.python.util import tf_inspect +from tensorflow.python.util.tf_export import get_canonical_name_for_symbol from tensorflow.python.util.tf_export import tf_export @@ -186,7 +189,7 @@ def sparse_eye(num_rows, # pylint: disable=protected-access -@tf_export("sparse.concat", "sparse_concat") +@tf_export(v1=["sparse.concat", "sparse_concat"]) @deprecation.deprecated_endpoints("sparse_concat") @deprecation.deprecated_args( None, "concat_dim is deprecated, use axis instead", "concat_dim") @@ -292,6 +295,11 @@ def sparse_concat(axis, """ axis = deprecation.deprecated_argument_lookup("axis", axis, "concat_dim", concat_dim) + return sparse_concat_v2(axis, sp_inputs, expand_nonconcat_dim, name) + + +@tf_export("sparse.concat", v1=[]) +def sparse_concat_v2(axis, sp_inputs, expand_nonconcat_dim=False, name=None): # pylint: disable=missing-docstring sp_inputs = _convert_to_sparse_tensors(sp_inputs) if len(sp_inputs) == 1: # Degenerate case of one tensor. @@ -319,9 +327,15 @@ def sparse_concat(axis, return sparse_tensor.SparseTensor(output_ind, output_val, output_shape) -@tf_export("sparse.add", v1=["sparse.add", "sparse_add"]) +sparse_concat_v2.__doc__ = sparse_concat.__doc__.replace( + " concat_dim: The old (deprecated) name for axis.\n", "") + + +@tf_export(v1=["sparse.add", "sparse_add"]) @deprecation.deprecated_endpoints("sparse_add") -def sparse_add(a, b, thresh=0): +@deprecation.deprecated_args( + None, "thresh is deprecated, use threshold instead", "thresh") +def sparse_add(a, b, threshold=None, thresh=None): """Adds two tensors, at least one of each is a `SparseTensor`. If one `SparseTensor` and one `Tensor` are passed in, returns a `Tensor`. If @@ -359,12 +373,74 @@ def sparse_add(a, b, thresh=0): Args: a: The first operand; `SparseTensor` or `Tensor`. - b: The second operand; `SparseTensor` or `Tensor`. At least one operand + b: The second operand; `SparseTensor` or `Tensor`. At least one operand must be sparse. - thresh: A 0-D `Tensor`. The magnitude threshold that determines if an - output value/index pair takes space. Its dtype should match that of the - values if they are real; if the latter are complex64/complex128, then the - dtype should be float32/float64, correspondingly. + threshold: An optional 0-D `Tensor` (defaults to `0`). The magnitude + threshold that determines if an output value/index pair takes space. Its + dtype should match that of the values if they are real; if the latter are + complex64/complex128, then the dtype should be float32/float64, + correspondingly. + thresh: Deprecated alias for `threshold`. + + Returns: + A `SparseTensor` or a `Tensor`, representing the sum. + + Raises: + TypeError: If both `a` and `b` are `Tensor`s. Use `tf.add()` instead. + """ + threshold = deprecation.deprecated_argument_lookup("threshold", threshold, + "thresh", thresh) + if threshold is None: + threshold = 0 + return sparse_add_v2(a, b, threshold) + + +@tf_export("sparse.add", v1=[]) +def sparse_add_v2(a, b, threshold=0): + """Adds two tensors, at least one of each is a `SparseTensor`. + + If one `SparseTensor` and one `Tensor` are passed in, returns a `Tensor`. If + both arguments are `SparseTensor`s, this returns a `SparseTensor`. The order + of arguments does not matter. Use vanilla `tf.add()` for adding two dense + `Tensor`s. + + The shapes of the two operands must match: broadcasting is not supported. + + The indices of any input `SparseTensor` are assumed ordered in standard + lexicographic order. If this is not the case, before this step run + `SparseReorder` to restore index ordering. + + If both arguments are sparse, we perform "clipping" as follows. By default, + if two values sum to zero at some index, the output `SparseTensor` would still + include that particular location in its index, storing a zero in the + corresponding value slot. To override this, callers can specify `threshold`, + indicating that if the sum has a magnitude strictly smaller than `threshold`, + its corresponding value and index would then not be included. In particular, + `threshold == 0.0` (default) means everything is kept and actual thresholding + happens only for a positive value. + + For example, suppose the logical sum of two sparse operands is (densified): + + [ 2] + [.1 0] + [ 6 -.2] + + Then, + + * `threshold == 0` (the default): all 5 index/value pairs will be + returned. + * `threshold == 0.11`: only .1 and 0 will vanish, and the remaining three + index/value pairs will be returned. + * `threshold == 0.21`: .1, 0, and -.2 will vanish. + + Args: + a: The first operand; `SparseTensor` or `Tensor`. + b: The second operand; `SparseTensor` or `Tensor`. At least one operand + must be sparse. + threshold: A 0-D `Tensor`. The magnitude threshold that determines if an + output value/index pair takes space. Its dtype should match that of the + values if they are real; if the latter are complex64/complex128, then the + dtype should be float32/float64, correspondingly. Returns: A `SparseTensor` or a `Tensor`, representing the sum. @@ -380,11 +456,12 @@ def sparse_add(a, b, thresh=0): if all(isinstance(inp, sparse_classes) for inp in [a, b]): a = _convert_to_sparse_tensor(a) b = _convert_to_sparse_tensor(b) - thresh = ops.convert_to_tensor( - thresh, dtype=a.values.dtype.real_dtype.base_dtype, name="thresh") + threshold = ops.convert_to_tensor( + threshold, dtype=a.values.dtype.real_dtype.base_dtype, name="threshold") output_ind, output_val, output_shape = ( gen_sparse_ops.sparse_add(a.indices, a.values, a.dense_shape, - b.indices, b.values, b.dense_shape, thresh)) + b.indices, b.values, b.dense_shape, + threshold)) # Attempt to get output_shape statically. a.get_shape().assert_is_compatible_with(b.get_shape()) @@ -705,7 +782,7 @@ class KeywordRequired(object): return "KeywordRequired()" -@tf_export("sparse.split", "sparse_split") +@tf_export(v1=["sparse.split", "sparse_split"]) @deprecation.deprecated_endpoints("sparse_split") @deprecation.deprecated_args( None, "split_dim is deprecated, use axis instead", "split_dim") @@ -779,6 +856,51 @@ def sparse_split(keyword_required=KeywordRequired(), return sparse_tensors +@tf_export("sparse.split", v1=[]) +def sparse_split_v2(sp_input=None, + num_split=None, + axis=None, + name=None): + """Split a `SparseTensor` into `num_split` tensors along `axis`. + + If the `sp_input.dense_shape[axis]` is not an integer multiple of `num_split` + each slice starting from 0:`shape[axis] % num_split` gets extra one + dimension. For example, if `axis = 1` and `num_split = 2` and the + input is: + + input_tensor = shape = [2, 7] + [ a d e ] + [b c ] + + Graphically the output tensors are: + + output_tensor[0] = + [ a ] + [b c ] + + output_tensor[1] = + [ d e ] + [ ] + + Args: + sp_input: The `SparseTensor` to split. + num_split: A Python integer. The number of ways to split. + axis: A 0-D `int32` `Tensor`. The dimension along which to split. + name: A name for the operation (optional). + + Returns: + `num_split` `SparseTensor` objects resulting from splitting `value`. + + Raises: + TypeError: If `sp_input` is not a `SparseTensor`. + """ + return sparse_split(sp_input=sp_input, + num_split=num_split, + axis=axis, + name=name, + split_dim=None) + + @tf_export("sparse.slice", v1=["sparse.slice", "sparse_slice"]) @deprecation.deprecated_endpoints("sparse_slice") def sparse_slice(sp_input, start, size, name=None): @@ -829,7 +951,7 @@ def sparse_slice(sp_input, start, size, name=None): output_shape) -@tf_export("sparse_to_dense") +@tf_export(v1=["sparse_to_dense"]) @deprecation.deprecated( None, "Create a `tf.sparse.SparseTensor` and use `tf.sparse.to_dense` instead.") @@ -888,7 +1010,86 @@ def sparse_to_dense(sparse_indices, name=name) -@tf_export("sparse.reduce_max", "sparse_reduce_max") +@tf_export("sparse.reduce_max", v1=[]) +def sparse_reduce_max_v2( + sp_input, axis=None, keepdims=None, output_is_sparse=False, name=None): + """Computes the max of elements across dimensions of a SparseTensor. + + This Op takes a SparseTensor and is the sparse counterpart to + `tf.reduce_max()`. In particular, this Op also returns a dense `Tensor` + if `output_is_sparse` is `False`, or a `SparseTensor` if `output_is_sparse` + is `True`. + + Note: A gradient is not defined for this function, so it can't be used + in training models that need gradient descent. + + Reduces `sp_input` along the dimensions given in `axis`. Unless + `keepdims` is true, the rank of the tensor is reduced by 1 for each entry in + `axis`. If `keepdims` is true, the reduced dimensions are retained + with length 1. + + If `axis` has no entries, all dimensions are reduced, and a tensor + with a single element is returned. Additionally, the axes can be negative, + similar to the indexing rules in Python. + + The values not defined in `sp_input` don't participate in the reduce max, + as opposed to be implicitly assumed 0 -- hence it can return negative values + for sparse `axis`. But, in case there are no values in + `axis`, it will reduce to 0. See second example below. + + For example: + + ```python + # 'x' represents [[1, ?, 2] + # [?, 3, ?]] + # where ? is implicitly-zero. + tf.sparse.reduce_max(x) ==> 3 + tf.sparse.reduce_max(x, 0) ==> [1, 3, 2] + tf.sparse.reduce_max(x, 1) ==> [2, 3] # Can also use -1 as the axis. + tf.sparse.reduce_max(x, 1, keepdims=True) ==> [[2], [3]] + tf.sparse.reduce_max(x, [0, 1]) ==> 3 + + # 'y' represents [[-7, ?] + # [ 4, 3] + # [ ?, ?] + tf.sparse.reduce_max(x, 1) ==> [-7, 4, 0] + ``` + + Args: + sp_input: The SparseTensor to reduce. Should have numeric type. + axis: The dimensions to reduce; list or scalar. If `None` (the + default), reduces all dimensions. + keepdims: If true, retain reduced dimensions with length 1. + output_is_sparse: If true, returns a `SparseTensor` instead of a dense + `Tensor` (the default). + name: A name for the operation (optional). + + Returns: + The reduced Tensor or the reduced SparseTensor if `output_is_sparse` is + True. + """ + if keepdims is None: + keepdims = False + + # reduction_axes is the deprecated name for axis. + reduction_axes = None + + if output_is_sparse: + output_ind, output_val, output_shape = ( + gen_sparse_ops.sparse_reduce_max_sparse( + sp_input.indices, sp_input.values, sp_input.dense_shape, + math_ops._ReductionDims(sp_input, axis, reduction_axes), keepdims, + name=name)) + + return sparse_tensor.SparseTensor(output_ind, output_val, output_shape) + + return gen_sparse_ops.sparse_reduce_max( + sp_input.indices, sp_input.values, sp_input.dense_shape, + math_ops._ReductionDims(sp_input, axis, reduction_axes), keepdims, + name=name) + + +@tf_export(v1=["sparse.reduce_max", "sparse_reduce_max"]) @deprecation.deprecated_endpoints("sparse_reduce_max") @deprecation.deprecated_args( None, "keep_dims is deprecated, use keepdims instead", "keep_dims") @@ -956,7 +1157,7 @@ def sparse_reduce_max(sp_input, axis=None, keepdims=None, math_ops._ReductionDims(sp_input, axis, reduction_axes), keepdims) -@tf_export("sparse.reduce_max_sparse", "sparse_reduce_max_sparse") +@tf_export(v1=["sparse.reduce_max_sparse", "sparse_reduce_max_sparse"]) @deprecation.deprecated_endpoints("sparse_reduce_max_sparse") @deprecation.deprecated_args( None, "keep_dims is deprecated, use keepdims instead", "keep_dims") @@ -1007,7 +1208,74 @@ def sparse_reduce_max_sparse(sp_input, return sparse_tensor.SparseTensor(output_ind, output_val, output_shape) -@tf_export("sparse.reduce_sum", "sparse_reduce_sum") +@tf_export("sparse.reduce_sum", v1=[]) +def sparse_reduce_sum_v2( + sp_input, axis=None, keepdims=None, output_is_sparse=False, name=None): + """Computes the sum of elements across dimensions of a SparseTensor. + + This Op takes a SparseTensor and is the sparse counterpart to + `tf.reduce_sum()`. In particular, this Op also returns a dense `Tensor` + if `output_is_sparse` is `False`, or a `SparseTensor` if `output_is_sparse` + is `True`. + + Note: if `output_is_sparse` is True, a gradient is not defined for this + function, so it can't be used in training models that need gradient descent. + + Reduces `sp_input` along the dimensions given in `axis`. Unless `keepdims` is + true, the rank of the tensor is reduced by 1 for each entry in `axis`. If + `keepdims` is true, the reduced dimensions are retained with length 1. + + If `axis` has no entries, all dimensions are reduced, and a tensor + with a single element is returned. Additionally, the axes can be negative, + similar to the indexing rules in Python. + + For example: + + ```python + # 'x' represents [[1, ?, 1] + # [?, 1, ?]] + # where ? is implicitly-zero. + tf.sparse.reduce_sum(x) ==> 3 + tf.sparse.reduce_sum(x, 0) ==> [1, 1, 1] + tf.sparse.reduce_sum(x, 1) ==> [2, 1] # Can also use -1 as the axis. + tf.sparse.reduce_sum(x, 1, keepdims=True) ==> [[2], [1]] + tf.sparse.reduce_sum(x, [0, 1]) ==> 3 + ``` + + Args: + sp_input: The SparseTensor to reduce. Should have numeric type. + axis: The dimensions to reduce; list or scalar. If `None` (the + default), reduces all dimensions. + keepdims: If true, retain reduced dimensions with length 1. + output_is_sparse: If true, returns a `SparseTensor` instead of a dense + `Tensor` (the default). + name: A name for the operation (optional). + + Returns: + The reduced Tensor or the reduced SparseTensor if `output_is_sparse` is + True. + """ + if keepdims is None: + keepdims = False + + # reduction_axes is the deprecated name for axis. + reduction_axes = None + + if output_is_sparse: + output_ind, output_val, output_shape = ( + gen_sparse_ops.sparse_reduce_sum_sparse( + sp_input.indices, sp_input.values, sp_input.dense_shape, + math_ops._ReductionDims(sp_input, axis, reduction_axes), keepdims, + name=name)) + return sparse_tensor.SparseTensor(output_ind, output_val, output_shape) + + return gen_sparse_ops.sparse_reduce_sum( + sp_input.indices, sp_input.values, sp_input.dense_shape, + math_ops._ReductionDims(sp_input, axis, reduction_axes), keepdims, + name=name) + + +@tf_export(v1=["sparse.reduce_sum", "sparse_reduce_sum"]) @deprecation.deprecated_endpoints("sparse_reduce_sum") @deprecation.deprecated_args( None, "keep_dims is deprecated, use keepdims instead", "keep_dims") @@ -1062,7 +1330,7 @@ def sparse_reduce_sum(sp_input, axis=None, keepdims=None, math_ops._ReductionDims(sp_input, axis, reduction_axes), keepdims) -@tf_export("sparse.reduce_sum_sparse", "sparse_reduce_sum_sparse") +@tf_export(v1=["sparse.reduce_sum_sparse", "sparse_reduce_sum_sparse"]) @deprecation.deprecated_endpoints("sparse_reduce_sum_sparse") @deprecation.deprecated_args( None, "keep_dims is deprecated, use keepdims instead", "keep_dims") @@ -1157,7 +1425,7 @@ def sparse_tensor_to_dense(sp_input, """ sp_input = _convert_to_sparse_tensor(sp_input) - return sparse_to_dense( + return gen_sparse_ops.sparse_to_dense( sp_input.indices, sp_input.dense_shape, sp_input.values, @@ -1231,8 +1499,8 @@ def sparse_to_indicator(sp_input, vocab_size, name=None): sp_new, default_value=False, validate_indices=False, name=name) -@tf_export("sparse.merge", v1=["sparse.merge", "sparse_merge"]) -@deprecation.deprecated_endpoints("sparse_merge") +@tf_export(v1=["sparse.merge", "sparse_merge"]) +@deprecation.deprecated(None, "No similar op available at this time.") def sparse_merge(sp_ids, sp_values, vocab_size, name=None, already_sorted=False): """Combines a batch of feature ids and values into a single `SparseTensor`. @@ -1593,8 +1861,7 @@ def sparse_fill_empty_rows(sp_input, default_value, name=None): dense_shape=sp_input.dense_shape), empty_row_indicator) -@tf_export( - "io.serialize_sparse", v1=["io.serialize_sparse", "serialize_sparse"]) +@tf_export(v1=["io.serialize_sparse", "serialize_sparse"]) @deprecation.deprecated_endpoints("serialize_sparse") def serialize_sparse(sp_input, name=None, out_type=dtypes.string): """Serialize a `SparseTensor` into a 3-vector (1-D `Tensor`) object. @@ -1608,6 +1875,25 @@ def serialize_sparse(sp_input, name=None, out_type=dtypes.string): A 3-vector (1-D `Tensor`), with each column representing the serialized `SparseTensor`'s indices, values, and shape (respectively). + Raises: + TypeError: If `sp_input` is not a `SparseTensor`. + """ + return serialize_sparse_v2(sp_input, out_type, name) + + +@tf_export("io.serialize_sparse", v1=[]) +def serialize_sparse_v2(sp_input, out_type=dtypes.string, name=None): + """Serialize a `SparseTensor` into a 3-vector (1-D `Tensor`) object. + + Args: + sp_input: The input `SparseTensor`. + out_type: The `dtype` to use for serialization. + name: A name prefix for the returned tensors (optional). + + Returns: + A 3-vector (1-D `Tensor`), with each column representing the serialized + `SparseTensor`'s indices, values, and shape (respectively). + Raises: TypeError: If `sp_input` is not a `SparseTensor`. """ @@ -1621,9 +1907,7 @@ def serialize_sparse(sp_input, name=None, out_type=dtypes.string): out_type=out_type) -@tf_export( - "io.serialize_many_sparse", - v1=["io.serialize_many_sparse", "serialize_many_sparse"]) +@tf_export(v1=["io.serialize_many_sparse", "serialize_many_sparse"]) @deprecation.deprecated_endpoints("serialize_many_sparse") def serialize_many_sparse(sp_input, name=None, out_type=dtypes.string): """Serialize `N`-minibatch `SparseTensor` into an `[N, 3]` `Tensor`. @@ -1646,6 +1930,34 @@ def serialize_many_sparse(sp_input, name=None, out_type=dtypes.string): represents serialized `SparseTensor`'s indices, values, and shape (respectively). + Raises: + TypeError: If `sp_input` is not a `SparseTensor`. + """ + return serialize_many_sparse_v2(sp_input, out_type, name) + + +@tf_export("io.serialize_many_sparse", v1=[]) +def serialize_many_sparse_v2(sp_input, out_type=dtypes.string, name=None): + """Serialize `N`-minibatch `SparseTensor` into an `[N, 3]` `Tensor`. + + The `SparseTensor` must have rank `R` greater than 1, and the first dimension + is treated as the minibatch dimension. Elements of the `SparseTensor` + must be sorted in increasing order of this first dimension. The serialized + `SparseTensor` objects going into each row of the output `Tensor` will have + rank `R-1`. + + The minibatch size `N` is extracted from `sparse_shape[0]`. + + Args: + sp_input: The input rank `R` `SparseTensor`. + out_type: The `dtype` to use for serialization. + name: A name prefix for the returned tensors (optional). + + Returns: + A matrix (2-D `Tensor`) with `N` rows and `3` columns. Each column + represents serialized `SparseTensor`'s indices, values, and shape + (respectively). + Raises: TypeError: If `sp_input` is not a `SparseTensor`. """ @@ -1798,7 +2110,9 @@ def deserialize_many_sparse(serialized_sparse, dtype, rank=None, name=None): return sparse_tensor.SparseTensor(output_indices, output_values, output_shape) -@tf_export("sparse.matmul", v1=["sparse.matmul", "sparse_tensor_dense_matmul"]) +@tf_export("sparse.sparse_dense_matmul", + v1=["sparse.sparse_dense_matmul", "sparse.matmul", + "sparse_tensor_dense_matmul"]) @deprecation.deprecated_endpoints("sparse_tensor_dense_matmul") def sparse_tensor_dense_matmul(sp_a, b, @@ -2362,3 +2676,47 @@ def _take_many_sparse_from_tensors_map(sparse_map_op, output_shape.set_shape([rank]) return sparse_tensor.SparseTensor(output_indices, output_values, output_shape) + + +class _UnaryMapValueDispatcher(dispatch.OpDispatcher): + """OpDispatcher for unary ops that maps base function across sparse values.""" + + def __init__(self, original_func): + self._original_func = original_func + func_name = get_canonical_name_for_symbol(original_func) + arg_names = tf_inspect.getfullargspec(original_func)[0] + self._x = arg_names[0] + original_func.__doc__ = ( + original_func.__doc__.rstrip() + "\n\n" + + (" If `{x}` is a `SparseTensor`, returns\n" + " `SparseTensor({x}.indices, tf.{func}({x}.values, ...), " + "{x}.dense_shape)`").format(x=self._x, func=func_name)) + + def handle(self, args, kwargs): + if args: + x, args = args[0], args[1:] + else: + x = kwargs.pop(self._x, None) + if isinstance(x, sparse_tensor.SparseTensor): + return sparse_tensor.SparseTensor( + indices=x.indices, + values=self._original_func(x.values, *args, **kwargs), + dense_shape=x.dense_shape) + else: + return self.NOT_SUPPORTED + + +_UNARY_OPS = [ + # TODO(b/120307967) Add dispatchers for additional TensorFlow ops. + math_ops.abs, + math_ops.negative, + math_ops.sign, + math_ops.square, + math_ops.sqrt, + math_ops.erf, + math_ops.tanh, + math_ops.bessel_i0e, + math_ops.bessel_i1e, +] +for unary_op in _UNARY_OPS: + _UnaryMapValueDispatcher(unary_op).register(unary_op) diff --git a/tensorflow/python/ops/sparse_ops_test.py b/tensorflow/python/ops/sparse_ops_test.py index 4ee1569249..031069a0f0 100644 --- a/tensorflow/python/ops/sparse_ops_test.py +++ b/tensorflow/python/ops/sparse_ops_test.py @@ -18,18 +18,20 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from absl.testing import parameterized import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import test_util +from tensorflow.python.ops import math_ops from tensorflow.python.ops import sparse_ops from tensorflow.python.platform import googletest @test_util.run_all_in_graph_and_eager_modes -class SparseOpsTest(test_util.TensorFlowTestCase): +class SparseOpsTest(test_util.TensorFlowTestCase, parameterized.TestCase): def testSparseEye(self): def test_one(n, m, as_tensors): @@ -77,5 +79,23 @@ class SparseOpsTest(test_util.TensorFlowTestCase): d = sparse_ops.sparse_to_dense(s.indices, s.dense_shape, s.values) self.assertAllEqual(self.evaluate(d), expected_after) + @parameterized.parameters([ + (math_ops.abs, [1.0, -1.0, 3.0, -4.0], [1.0, 1.0, 3.0, 4.0]), + (math_ops.negative, [1.0, -1.0, 3.0, -4.0], [-1.0, 1.0, -3.0, 4.0]), + (math_ops.sign, [3.0, -2.0, 0.0, -4.0], [1.0, -1.0, 0.0, -1.0]), + (math_ops.square, [1.0, -1.0, 3.0, -4.0], [1.0, 1.0, 9.0, 16.0]), + ]) + def testUnarySparseDispatch(self, op, values, expected): + st = sparse_tensor.SparseTensor( + indices=[[0, 0], [0, 1], [2, 0], [2, 4]], + values=values, + dense_shape=[3, 6]) + result = op(st) + result_value = self.evaluate(result) + self.assertAllEqual(result_value.indices, st.indices) + self.assertAllEqual(result_value.values, expected) + self.assertAllEqual(result_value.dense_shape, st.dense_shape) + + if __name__ == '__main__': googletest.main() diff --git a/tensorflow/python/ops/special_math_ops.py b/tensorflow/python/ops/special_math_ops.py index f44f694109..21f4996798 100644 --- a/tensorflow/python/ops/special_math_ops.py +++ b/tensorflow/python/ops/special_math_ops.py @@ -70,8 +70,7 @@ def lbeta(x, name=None): x = ops.convert_to_tensor(x, name='x') # Note reduce_sum([]) = 0. - log_prod_gamma_x = math_ops.reduce_sum( - math_ops.lgamma(x), reduction_indices=[-1]) + log_prod_gamma_x = math_ops.reduce_sum(math_ops.lgamma(x), axis=[-1]) # Note lgamma(0) = infinity, so if x = [] # log_gamma_sum_x = lgamma(0) = infinity, and @@ -264,11 +263,11 @@ def einsum(equation, *inputs, **kwargs): missing_indices = set(temp_axis_labels) - set(output_axis_labels) if missing_indices: - reduction_indices = [ + axis = [ i for i, a in enumerate(temp_axis_labels) if a not in output_axis_labels ] - temp = math_ops.reduce_sum(temp, reduction_indices=reduction_indices) + temp = math_ops.reduce_sum(temp, axis=axis) temp_axis_labels = ''.join( a for a in temp_axis_labels if a in output_axis_labels) diff --git a/tensorflow/python/ops/special_math_ops_test.py b/tensorflow/python/ops/special_math_ops_test.py index 7438cdb3f1..94aaebed95 100644 --- a/tensorflow/python/ops/special_math_ops_test.py +++ b/tensorflow/python/ops/special_math_ops_test.py @@ -46,6 +46,7 @@ class LBetaTest(test.TestCase): 0.5, self.evaluate(math_ops.exp(special_math_ops.lbeta(x_one_half)))) self.assertEqual([], special_math_ops.lbeta(x_one).get_shape()) + @test_util.run_deprecated_v1 def test_one_dimensional_arg_dynamic(self): # Should evaluate to 1 and 1/2. x_one = [1, 1.] @@ -57,6 +58,7 @@ class LBetaTest(test.TestCase): self.assertAllClose(0.5, beta_ph.eval(feed_dict={ph: x_one_half})) + @test_util.run_deprecated_v1 def test_four_dimensional_arg_with_partial_shape_dynamic(self): x_ = np.ones((3, 2, 3, 4)) # Gamma(1) = 0! = 1 @@ -81,6 +83,7 @@ class LBetaTest(test.TestCase): self.evaluate(math_ops.exp(special_math_ops.lbeta(x_one_half)))) self.assertEqual((2,), special_math_ops.lbeta(x_one_half).get_shape()) + @test_util.run_deprecated_v1 def test_two_dimensional_arg_dynamic(self): # Should evaluate to 1/2. x_one_half = [[2, 1.], [2, 1.]] @@ -288,6 +291,7 @@ class EinsumTest(test.TestCase): for case in self.long_cases: self.run_test(case) + @test_util.run_deprecated_v1 def test_invalid(self): for axes in self.invalid_cases: inputs = [ @@ -297,6 +301,7 @@ class EinsumTest(test.TestCase): with self.assertRaises(ValueError): _ = special_math_ops.einsum(axes, *inputs) + @test_util.run_deprecated_v1 def test_invalid_keyword_arguments(self): m0 = array_ops.placeholder(dtypes.int32, shape=(1, None)) m1 = array_ops.placeholder(dtypes.int32, shape=(None, 1)) @@ -311,11 +316,13 @@ class EinsumTest(test.TestCase): invalid1='value1', invalid2='value2') + @test_util.run_deprecated_v1 def test_repeated_axis_single_input(self): x = array_ops.placeholder(dtypes.float32, shape=[2, 2]) with self.assertRaises(ValueError): _ = special_math_ops.einsum('ii->', x) + @test_util.run_deprecated_v1 def test_dim_mismatch(self): for axes, input_shapes in self.dim_mismatch_cases: inputs = [ diff --git a/tensorflow/python/ops/spectral_grad.py b/tensorflow/python/ops/spectral_grad.py deleted file mode 100644 index 0af24114ac..0000000000 --- a/tensorflow/python/ops/spectral_grad.py +++ /dev/null @@ -1,185 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Gradients for operators defined in spectral_ops.py.""" -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import numpy as np - -from tensorflow.python.framework import dtypes -from tensorflow.python.framework import ops -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops -from tensorflow.python.ops import spectral_ops - - -def _FFTSizeForGrad(grad, rank): - return math_ops.reduce_prod(array_ops.shape(grad)[-rank:]) - - -@ops.RegisterGradient("FFT") -def _FFTGrad(_, grad): - size = math_ops.cast(_FFTSizeForGrad(grad, 1), grad.dtype) - return spectral_ops.ifft(grad) * size - - -@ops.RegisterGradient("IFFT") -def _IFFTGrad(_, grad): - rsize = math_ops.cast( - 1. / math_ops.cast(_FFTSizeForGrad(grad, 1), grad.dtype.real_dtype), - grad.dtype) - return spectral_ops.fft(grad) * rsize - - -@ops.RegisterGradient("FFT2D") -def _FFT2DGrad(_, grad): - size = math_ops.cast(_FFTSizeForGrad(grad, 2), grad.dtype) - return spectral_ops.ifft2d(grad) * size - - -@ops.RegisterGradient("IFFT2D") -def _IFFT2DGrad(_, grad): - rsize = math_ops.cast( - 1. / math_ops.cast(_FFTSizeForGrad(grad, 2), grad.dtype.real_dtype), - grad.dtype) - return spectral_ops.fft2d(grad) * rsize - - -@ops.RegisterGradient("FFT3D") -def _FFT3DGrad(_, grad): - size = math_ops.cast(_FFTSizeForGrad(grad, 3), grad.dtype) - return spectral_ops.ifft3d(grad) * size - - -@ops.RegisterGradient("IFFT3D") -def _IFFT3DGrad(_, grad): - rsize = math_ops.cast( - 1. / math_ops.cast(_FFTSizeForGrad(grad, 3), grad.dtype.real_dtype), - grad.dtype) - return spectral_ops.fft3d(grad) * rsize - - -def _RFFTGradHelper(rank, irfft_fn): - """Returns a gradient function for an RFFT of the provided rank.""" - # Can't happen because we don't register a gradient for RFFT3D. - assert rank in (1, 2), "Gradient for RFFT3D is not implemented." - - def _Grad(op, grad): - """A gradient function for RFFT with the provided `rank` and `irfft_fn`.""" - fft_length = op.inputs[1] - input_shape = array_ops.shape(op.inputs[0]) - is_even = math_ops.cast(1 - (fft_length[-1] % 2), dtypes.complex64) - - def _TileForBroadcasting(matrix, t): - expanded = array_ops.reshape( - matrix, - array_ops.concat([ - array_ops.ones([array_ops.rank(t) - 2], dtypes.int32), - array_ops.shape(matrix) - ], 0)) - return array_ops.tile( - expanded, array_ops.concat([array_ops.shape(t)[:-2], [1, 1]], 0)) - - def _MaskMatrix(length): - # TODO(rjryan): Speed up computation of twiddle factors using the - # following recurrence relation and cache them across invocations of RFFT. - # - # t_n = exp(sqrt(-1) * pi * n^2 / line_len) - # for n = 0, 1,..., line_len-1. - # For n > 2, use t_n = t_{n-1}^2 / t_{n-2} * t_1^2 - a = array_ops.tile( - array_ops.expand_dims(math_ops.range(length), 0), (length, 1)) - b = array_ops.transpose(a, [1, 0]) - return math_ops.exp(-2j * np.pi * math_ops.cast(a * b, dtypes.complex64) / - math_ops.cast(length, dtypes.complex64)) - - def _YMMask(length): - """A sequence of [1+0j, -1+0j, 1+0j, -1+0j, ...] with length `length`.""" - return math_ops.cast(1 - 2 * (math_ops.range(length) % 2), - dtypes.complex64) - - y0 = grad[..., 0:1] - if rank == 1: - ym = grad[..., -1:] - extra_terms = y0 + is_even * ym * _YMMask(input_shape[-1]) - elif rank == 2: - # Create a mask matrix for y0 and ym. - base_mask = _MaskMatrix(input_shape[-2]) - - # Tile base_mask to match y0 in shape so that we can batch-matmul the - # inner 2 dimensions. - tiled_mask = _TileForBroadcasting(base_mask, y0) - - y0_term = math_ops.matmul(tiled_mask, math_ops.conj(y0)) - extra_terms = y0_term - - ym = grad[..., -1:] - ym_term = math_ops.matmul(tiled_mask, math_ops.conj(ym)) - - inner_dim = input_shape[-1] - ym_term = array_ops.tile( - ym_term, - array_ops.concat([ - array_ops.ones([array_ops.rank(grad) - 1], dtypes.int32), - [inner_dim] - ], 0)) * _YMMask(inner_dim) - - extra_terms += is_even * ym_term - - # The gradient of RFFT is the IRFFT of the incoming gradient times a scaling - # factor, plus some additional terms to make up for the components dropped - # due to Hermitian symmetry. - input_size = math_ops.to_float(_FFTSizeForGrad(op.inputs[0], rank)) - irfft = irfft_fn(grad, fft_length) - return 0.5 * (irfft * input_size + math_ops.real(extra_terms)), None - - return _Grad - - -def _IRFFTGradHelper(rank, rfft_fn): - """Returns a gradient function for an IRFFT of the provided rank.""" - # Can't happen because we don't register a gradient for IRFFT3D. - assert rank in (1, 2), "Gradient for IRFFT3D is not implemented." - - def _Grad(op, grad): - """A gradient function for IRFFT with the provided `rank` and `rfft_fn`.""" - # Generate a simple mask like [1.0, 2.0, ..., 2.0, 1.0] for even-length FFTs - # and [1.0, 2.0, ..., 2.0] for odd-length FFTs. To reduce extra ops in the - # graph we special-case the situation where the FFT length and last - # dimension of the input are known at graph construction time. - fft_length = op.inputs[1] - is_odd = math_ops.mod(fft_length[-1], 2) - input_last_dimension = array_ops.shape(op.inputs[0])[-1] - mask = array_ops.concat( - [[1.0], 2.0 * array_ops.ones([input_last_dimension - 2 + is_odd]), - array_ops.ones([1 - is_odd])], 0) - - rsize = math_ops.reciprocal(math_ops.to_float(_FFTSizeForGrad(grad, rank))) - - # The gradient of IRFFT is the RFFT of the incoming gradient times a scaling - # factor and a mask. The mask scales the gradient for the Hermitian - # symmetric components of the RFFT by a factor of two, since these - # components are de-duplicated in the RFFT. - rfft = rfft_fn(grad, fft_length) - return rfft * math_ops.cast(rsize * mask, dtypes.complex64), None - - return _Grad - - -ops.RegisterGradient("RFFT")(_RFFTGradHelper(1, spectral_ops.irfft)) -ops.RegisterGradient("IRFFT")(_IRFFTGradHelper(1, spectral_ops.rfft)) -ops.RegisterGradient("RFFT2D")(_RFFTGradHelper(2, spectral_ops.irfft2d)) -ops.RegisterGradient("IRFFT2D")(_IRFFTGradHelper(2, spectral_ops.rfft2d)) diff --git a/tensorflow/python/ops/standard_ops.py b/tensorflow/python/ops/standard_ops.py index 4f1662ab08..c614d072ba 100644 --- a/tensorflow/python/ops/standard_ops.py +++ b/tensorflow/python/ops/standard_ops.py @@ -31,7 +31,6 @@ from tensorflow.python.ops import manip_grad from tensorflow.python.ops import math_grad from tensorflow.python.ops import random_grad from tensorflow.python.ops import sparse_grad -from tensorflow.python.ops import spectral_grad from tensorflow.python.ops import state_grad from tensorflow.python.ops import tensor_array_grad @@ -51,6 +50,7 @@ from tensorflow.python.ops.control_flow_ops import group from tensorflow.python.ops.control_flow_ops import no_op from tensorflow.python.ops.control_flow_ops import tuple # pylint: disable=redefined-builtin # pylint: enable=redefined-builtin +from tensorflow.python.eager import wrap_function from tensorflow.python.ops.control_flow_ops import while_loop from tensorflow.python.ops.data_flow_ops import * from tensorflow.python.ops.functional_ops import * @@ -72,6 +72,7 @@ from tensorflow.python.ops.partitioned_variables import * from tensorflow.python.ops.random_ops import * from tensorflow.python.ops.script_ops import py_func from tensorflow.python.ops.session_ops import * +from tensorflow.python.ops.sort_ops import * from tensorflow.python.ops.sparse_ops import * from tensorflow.python.ops.state_ops import assign from tensorflow.python.ops.state_ops import assign_add diff --git a/tensorflow/python/ops/stateless_random_ops.py b/tensorflow/python/ops/stateless_random_ops.py index c6defabacd..b119049b16 100644 --- a/tensorflow/python/ops/stateless_random_ops.py +++ b/tensorflow/python/ops/stateless_random_ops.py @@ -24,6 +24,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import math_ops +from tensorflow.python.util import deprecation from tensorflow.python.util.tf_export import tf_export ops.NotDifferentiable("StatelessMultinomial") @@ -179,7 +180,9 @@ def stateless_truncated_normal(shape, return math_ops.add(rnd * stddev, mean, name=name) -@tf_export("random.stateless_multinomial") +@tf_export(v1=["random.stateless_multinomial"]) +@deprecation.deprecated( + date=None, instructions="Use tf.random.stateless_categorical instead.") def stateless_multinomial(logits, num_samples, seed, @@ -207,13 +210,58 @@ def stateless_multinomial(logits, `[i, :]` represents the unnormalized log-probabilities for all classes. num_samples: 0-D. Number of independent samples to draw for each row slice. seed: A shape [2] integer Tensor of seeds to the random number generator. - name: Optional name for the operation. output_dtype: integer type to use for the output. Defaults to int64. + name: Optional name for the operation. Returns: The drawn samples of shape `[batch_size, num_samples]`. """ with ops.name_scope(name, "stateless_multinomial", [logits, seed]): - logits = ops.convert_to_tensor(logits, name="logits") - return gen_stateless_random_ops.stateless_multinomial( - logits, num_samples, seed, output_dtype=output_dtype) + return stateless_multinomial_categorical_impl(logits, num_samples, + output_dtype, seed) + + +@tf_export("random.stateless_categorical") +def stateless_categorical(logits, + num_samples, + seed, + dtype=dtypes.int64, + name=None): + """Draws deterministic pseudorandom samples from a categorical distribution. + + This is a stateless version of `tf.categorical`: if run twice with the + same seeds, it will produce the same pseudorandom numbers. The output is + consistent across multiple runs on the same hardware (and between CPU + and GPU), but may change between versions of TensorFlow or on non-CPU/GPU + hardware. + + Example: + + ```python + # samples has shape [1, 5], where each value is either 0 or 1 with equal + # probability. + samples = tf.random.stateless_categorical( + tf.log([[10., 10.]]), 5, seed=[7, 17]) + ``` + + Args: + logits: 2-D Tensor with shape `[batch_size, num_classes]`. Each slice + `[i, :]` represents the unnormalized log-probabilities for all classes. + num_samples: 0-D. Number of independent samples to draw for each row slice. + seed: A shape [2] integer Tensor of seeds to the random number generator. + dtype: integer type to use for the output. Defaults to int64. + name: Optional name for the operation. + + Returns: + The drawn samples of shape `[batch_size, num_samples]`. + """ + with ops.name_scope(name, "stateless_categorical", [logits, seed]): + return stateless_multinomial_categorical_impl(logits, num_samples, dtype, + seed) + + +def stateless_multinomial_categorical_impl(logits, num_samples, dtype, seed): + """Implementation for stateless multinomial/categorical ops (v1/v2).""" + logits = ops.convert_to_tensor(logits, name="logits") + return gen_stateless_random_ops.stateless_multinomial( + logits, num_samples, seed, output_dtype=dtype) diff --git a/tensorflow/python/ops/string_ops.py b/tensorflow/python/ops/string_ops.py index 25e86cadeb..b6b329c486 100644 --- a/tensorflow/python/ops/string_ops.py +++ b/tensorflow/python/ops/string_ops.py @@ -28,6 +28,7 @@ from tensorflow.python.framework import ops from tensorflow.python.framework import sparse_tensor from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gen_parsing_ops from tensorflow.python.ops import gen_string_ops from tensorflow.python.ops import math_ops @@ -311,7 +312,7 @@ def _reduce_join_reduction_dims(x, axis, reduction_indices): return math_ops.range(array_ops.rank(x) - 1, -1, -1) -@tf_export("strings.reduce_join", v1=["strings.reduce_join", "reduce_join"]) +@tf_export(v1=["strings.reduce_join", "reduce_join"]) @deprecation.deprecated_endpoints("reduce_join") def reduce_join(inputs, axis=None, # pylint: disable=missing-docstring keep_dims=False, @@ -329,6 +330,17 @@ def reduce_join(inputs, axis=None, # pylint: disable=missing-docstring name=name) +@tf_export("strings.reduce_join", v1=[]) +def reduce_join_v2( # pylint: disable=missing-docstring + inputs, + axis=None, + keepdims=False, + separator="", + name=None): + return reduce_join( + inputs, axis, keep_dims=keepdims, separator=separator, name=name) + + reduce_join.__doc__ = deprecation.rewrite_argument_docstring( gen_string_ops.reduce_join.__doc__, "reduction_indices", "axis") reduce_join.__doc__ = reduce_join.__doc__.replace("tf.reduce_join(", @@ -337,10 +349,14 @@ reduce_join.__doc__ = reduce_join.__doc__.replace("tf.reduce_join(", # This wrapper provides backwards compatibility for code that predates the # unit argument and that passed 'name' as a positional argument. -@tf_export("strings.length") +@tf_export(v1=["strings.length"]) def string_length(input, name=None, unit="BYTE"): return gen_string_ops.string_length(input, unit=unit, name=name) +@tf_export("strings.length", v1=[]) +def string_length_v2(input, unit="BYTE", name=None): + return string_length(input, name, unit) + string_length.__doc__ = gen_string_ops.string_length.__doc__ @@ -353,11 +369,16 @@ def substr_deprecated(input, pos, len, name=None, unit="BYTE"): substr_deprecated.__doc__ = gen_string_ops.substr.__doc__ -@tf_export("strings.substr") +@tf_export(v1=["strings.substr"]) def substr(input, pos, len, name=None, unit="BYTE"): return gen_string_ops.substr(input, pos, len, unit=unit, name=name) +@tf_export("strings.substr", v1=[]) +def substr_v2(input, pos, len, unit="BYTE", name=None): + return substr(input, pos, len, name=name, unit=unit) + + substr.__doc__ = gen_string_ops.substr.__doc__ @@ -371,3 +392,53 @@ ops.NotDifferentiable("StringSplit") ops.NotDifferentiable("AsString") ops.NotDifferentiable("EncodeBase64") ops.NotDifferentiable("DecodeBase64") + + +@tf_export("strings.to_number", v1=[]) +def string_to_number(input, out_type=dtypes.float32, name=None): + r"""Converts each string in the input Tensor to the specified numeric type. + + (Note that int32 overflow results in an error while float overflow + results in a rounded value.) + + Args: + input: A `Tensor` of type `string`. + out_type: An optional `tf.DType` from: `tf.float32, tf.float64, tf.int32, + tf.int64`. Defaults to `tf.float32`. + The numeric type to interpret each string in `string_tensor` as. + name: A name for the operation (optional). + + Returns: + A `Tensor` of type `out_type`. + """ + return gen_parsing_ops.string_to_number(input, out_type, name) +tf_export(v1=["strings.to_number", "string_to_number"])( + gen_parsing_ops.string_to_number + ) + + +@tf_export("strings.to_hash_bucket", v1=[]) +def string_to_hash_bucket(input, num_buckets, name=None): + # pylint: disable=line-too-long + r"""Converts each string in the input Tensor to its hash mod by a number of buckets. + + The hash function is deterministic on the content of the string within the + process. + + Note that the hash function may change from time to time. + This functionality will be deprecated and it's recommended to use + `tf.string_to_hash_bucket_fast()` or `tf.string_to_hash_bucket_strong()`. + + Args: + input: A `Tensor` of type `string`. + num_buckets: An `int` that is `>= 1`. The number of buckets. + name: A name for the operation (optional). + + Returns: + A `Tensor` of type `int64`. + """ + # pylint: enable=line-too-long + return gen_string_ops.string_to_hash_bucket(input, num_buckets, name) +tf_export(v1=["strings.to_hash_bucket", "string_to_hash_bucket"])( + gen_string_ops.string_to_hash_bucket + ) diff --git a/tensorflow/python/ops/summary_op_util.py b/tensorflow/python/ops/summary_op_util.py index 14aa44a920..c72a9aefc3 100644 --- a/tensorflow/python/ops/summary_op_util.py +++ b/tensorflow/python/ops/summary_op_util.py @@ -22,6 +22,7 @@ import contextlib import re from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_util from tensorflow.python.platform import tf_logging from tensorflow.python.training import distribution_strategy_context @@ -44,13 +45,27 @@ _INVALID_TAG_CHARACTERS = re.compile(r'[^-/\w\.]') def skip_summary(): - # If using multiple replicas in distributed strategy, skip summaries on all - # replicas except the first one (replica_id=0). + """Determines if summary should be skipped. + + If using multiple replicas in distributed strategy, skip summaries on all + replicas except the first one (replica_id=0). + + Returns: + True if the summary is skipped; False otherwise. + """ + # TODO(priyag): Add a new optional argument that will provide multiple # alternatives to override default behavior. (e.g. run on last replica, # compute sum or mean across replicas). replica_context = distribution_strategy_context.get_replica_context() - return replica_context and replica_context.replica_id > 0 + if not replica_context: + return False + # TODO(b/118385803): when replica_id of _TPUReplicaContext is properly + # initialized, remember to change here as well. + replica_id = replica_context.replica_id_in_sync_group + if isinstance(replica_id, ops.Tensor): + replica_id = tensor_util.constant_value(replica_id) + return replica_id and replica_id > 0 def clean_tag(name): diff --git a/tensorflow/python/ops/summary_ops_v2.py b/tensorflow/python/ops/summary_ops_v2.py index 18cefb8e1c..3f99b9f877 100644 --- a/tensorflow/python/ops/summary_ops_v2.py +++ b/tensorflow/python/ops/summary_ops_v2.py @@ -40,11 +40,14 @@ from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import summary_op_util from tensorflow.python.platform import tf_logging as logging from tensorflow.python.training import training_util +from tensorflow.python.util import deprecation from tensorflow.python.util import tf_contextlib +from tensorflow.python.util.tf_export import tf_export -# A global dictionary mapping graph keys to boolean values indicating whether -# we should record summaries for this particular graph or not. +# Dictionary mapping graph keys to a boolean Tensor (or callable returning +# a boolean Tensor) indicating whether we should record summaries for the +# graph identified by the key of the dictionary. _SHOULD_RECORD_SUMMARIES = {} # A global dictionary mapping graph keys to a list of summary writer init ops. @@ -59,58 +62,67 @@ def should_record_summaries(): """Returns boolean Tensor which is true if summaries should be recorded.""" global _SHOULD_RECORD_SUMMARIES key = ops.get_default_graph()._graph_key # pylint: disable=protected-access - return _SHOULD_RECORD_SUMMARIES.setdefault(key, False) + should = _SHOULD_RECORD_SUMMARIES.setdefault(key, False) + return should() if callable(should) else should -# TODO(apassos) consider how to handle local step here. @tf_contextlib.contextmanager -def record_summaries_every_n_global_steps(n, global_step=None): - """Sets the should_record_summaries Tensor to true if global_step % n == 0.""" - if global_step is None: - global_step = training_util.get_or_create_global_step() +def _record_summaries(boolean=True): + """Sets summary recording on or off per the provided boolean value. + + The provided value can be a python boolean, a scalar boolean Tensor, or + or a callable providing such a value; if a callable is passed it will be + invoked each time should_record_summaries() is called to determine whether + summary writing should be enabled. + + Args: + boolean: can be True, False, a bool Tensor, or a callable providing such. + Defaults to True. + + Yields: + Returns a context manager that sets this value on enter and restores the + previous value on exit. + """ + # TODO(nickfelt): make this threadlocal global _SHOULD_RECORD_SUMMARIES key = ops.get_default_graph()._graph_key # pylint: disable=protected-access old = _SHOULD_RECORD_SUMMARIES.setdefault(key, False) try: - with ops.device("cpu:0"): - _SHOULD_RECORD_SUMMARIES[key] = math_ops.equal(global_step % n, 0) + _SHOULD_RECORD_SUMMARIES[key] = boolean yield finally: _SHOULD_RECORD_SUMMARIES[key] = old -@tf_contextlib.contextmanager +# TODO(apassos) consider how to handle local step here. +def record_summaries_every_n_global_steps(n, global_step=None): + """Sets the should_record_summaries Tensor to true if global_step % n == 0.""" + if global_step is None: + global_step = training_util.get_or_create_global_step() + with ops.device("cpu:0"): + should = lambda: math_ops.equal(global_step % n, 0) + if not context.executing_eagerly(): + should = should() + return _record_summaries(should) + + def always_record_summaries(): """Sets the should_record_summaries Tensor to always true.""" - global _SHOULD_RECORD_SUMMARIES - key = ops.get_default_graph()._graph_key # pylint: disable=protected-access - old = _SHOULD_RECORD_SUMMARIES.setdefault(key, False) - try: - _SHOULD_RECORD_SUMMARIES[key] = True - yield - finally: - _SHOULD_RECORD_SUMMARIES[key] = old + return _record_summaries(True) -@tf_contextlib.contextmanager def never_record_summaries(): """Sets the should_record_summaries Tensor to always false.""" - global _SHOULD_RECORD_SUMMARIES - key = ops.get_default_graph()._graph_key # pylint: disable=protected-access - old = _SHOULD_RECORD_SUMMARIES.setdefault(key, False) - try: - _SHOULD_RECORD_SUMMARIES[key] = False - yield - finally: - _SHOULD_RECORD_SUMMARIES[key] = old + return _record_summaries(False) +@tf_export("summary.SummaryWriter", v1=[]) class SummaryWriter(object): """Encapsulates a stateful summary writer resource. See also: - - `tf.contrib.summary.create_file_writer` - - `tf.contrib.summary.create_db_writer` + - `tf.summary.create_file_writer` + - `tf.summary.create_db_writer` """ def __init__(self, resource, init_op_fn): @@ -205,6 +217,7 @@ def initialize( session.run(_graph(x, 0), feed_dict={x: data}) +@tf_export("summary.create_file_writer", v1=[]) def create_file_writer(logdir, max_queue=None, flush_millis=None, @@ -280,7 +293,7 @@ def create_db_writer(db_uri, `tf.Graph`. Returns: - A `tf.contrib.summary.SummaryWriter` instance. + A `tf.summary.SummaryWriter` instance. """ with ops.device("cpu:0"): if experiment_name is None: @@ -329,7 +342,7 @@ def _nothing(): def all_summary_ops(): """Graph-mode only. Returns all summary ops. - Please note this excludes `tf.contrib.summary.graph` ops. + Please note this excludes `tf.summary.graph` ops. Returns: The summary ops. @@ -497,7 +510,7 @@ def graph(param, step=None, name=None): """Writes a TensorFlow graph to the summary interface. The graph summary is, strictly speaking, not a summary. Conditions - like `tf.contrib.summary.never_record_summaries` do not apply. Only + like `tf.summary.should_record_summaries` do not apply. Only a single graph can be associated with a particular run. If multiple graphs are written, then only the last one will be considered by TensorBoard. @@ -541,14 +554,13 @@ def graph(param, step=None, name=None): _graph = graph # for functions with a graph parameter +@tf_export("summary.import_event", v1=[]) def import_event(tensor, name=None): """Writes a `tf.Event` binary proto. - When using create_db_writer(), this can be used alongside - `tf.TFRecordReader` to load event logs into the database. Please - note that this is lower level than the other summary functions and - will ignore any conditions set by methods like - `tf.contrib.summary.should_record_summaries`. + This can be used to import existing event logs into a new summary writer sink. + Please note that this is lower level than the other summary functions and + will ignore the `tf.summary.should_record_summaries` setting. Args: tensor: A `tf.Tensor` of type `string` containing a serialized @@ -562,13 +574,14 @@ def import_event(tensor, name=None): context.context().summary_writer_resource, tensor, name=name) +@tf_export("summary.flush", v1=[]) def flush(writer=None, name=None): """Forces summary writer to send any buffered data to storage. This operation blocks until that finishes. Args: - writer: The `tf.contrib.summary.SummaryWriter` resource to flush. + writer: The `tf.summary.SummaryWriter` resource to flush. The thread default will be used if this parameter is None. Otherwise a `tf.no_op` is returned. name: A name for the operation (optional). @@ -595,6 +608,8 @@ def eval_dir(model_dir, name=None): return os.path.join(model_dir, "eval" if not name else "eval_" + name) +@deprecation.deprecated(date=None, + instructions="Renamed to create_file_writer().") def create_summary_file_writer(*args, **kwargs): """Please use `tf.contrib.summary.create_file_writer`.""" logging.warning("Deprecation Warning: create_summary_file_writer was renamed " diff --git a/tensorflow/python/ops/tensor_array_ops.py b/tensorflow/python/ops/tensor_array_ops.py index f86dfb3527..d151694951 100644 --- a/tensorflow/python/ops/tensor_array_ops.py +++ b/tensorflow/python/ops/tensor_array_ops.py @@ -20,8 +20,10 @@ from __future__ import division from __future__ import print_function import contextlib +import os import weakref +from tensorflow.python import tf2 from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes @@ -30,12 +32,18 @@ from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape from tensorflow.python.framework import tensor_util from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gen_control_flow_ops from tensorflow.python.ops import gen_data_flow_ops +from tensorflow.python.ops import list_ops from tensorflow.python.ops import math_ops from tensorflow.python.util import tf_should_use from tensorflow.python.util.tf_export import tf_export +ENABLE_TENSOR_ARRAY_V2 = ( + tf2.enabled() or os.getenv("TF_ENABLE_TENSOR_ARRAY_V2") is not None) + + # _GraphTensorArray accesses many of the hidden generated ops, but is in # fact built to wrap these methods. # pylint: disable=protected-access @@ -393,6 +401,273 @@ class _GraphTensorArray(object): return gen_data_flow_ops.tensor_array_close_v3( handle=self._handle, name=name) + +class _GraphTensorArrayV2(object): + """Graph-mode implementation of TensorArray backed by TensorLists. + + The backing tensor of this TensorArray is a TensorList variant tensor which is + stored in the `flow`. The `handle` is always none here. The reason we use the + `flow` field and not the `handle` field is to ensure backwards compatibility + with legacy control flow. + """ + + def __init__(self, + dtype, + size=None, + dynamic_size=None, + clear_after_read=None, + tensor_array_name=None, + handle=None, + flow=None, + infer_shape=True, + element_shape=None, + colocate_with_first_write_call=True, + name=None): + """Constructs a graph mode TensorArray. + + Args: + dtype: (required) data type of the TensorArray. + size: (optional) int32 scalar `Tensor`: the size of the TensorArray. + Required if flow is not provided. + dynamic_size: (optional) Python bool: If true, writes to the TensorArray + can grow the TensorArray past its initial size. Default: False. + clear_after_read: (optional) unused. Not supported in TensorLists. + tensor_array_name: (optional) unused. + handle: (optional) Must always be None. + flow: (optional) A variant `Tensor` scalar for a TensorList. + infer_shape: (optional, default: True) If True, shape inference is + enabled. In this case, all elements must have the same shape. + element_shape: (optional, default: None) A `TensorShape` object specifying + the shape constraints of each of the elements of the TensorArray. Need + not be fully defined. + colocate_with_first_write_call: (optional). unused. + name: (optional) A name for the operation. + + Raises: + ValueError: if both handle and tensor_array_name are provided. + TypeError: if handle is provided but is not a Tensor. + """ + assert handle is None + del handle + del clear_after_read + del tensor_array_name + del colocate_with_first_write_call + + del dynamic_size # TODO(b/117943489): Unused for now. + + if (flow is not None and + (not isinstance(flow, ops.Tensor) or flow.dtype != dtypes.variant)): + raise TypeError("flow must be a variant tensor") + if flow is None and size is None: + raise ValueError("Size must be provided if flow is not provided") + if flow is not None and size is not None: + raise ValueError("Cannot provide both a flow and size " + "at the same time") + if flow is not None and element_shape is not None: + raise ValueError("Cannot provide both a flow and element_shape " + "at the same time") + + self._dtype = dtype + + # Record the current static shape for the array elements. The element + # shape is defined either by `element_shape` or the shape of the tensor + # of the first write. If `infer_shape` is true, all writes checks for + # shape equality. + if element_shape is None: + self._infer_shape = infer_shape + self._element_shape = [] + else: + self._infer_shape = True + self._element_shape = [tensor_shape.TensorShape(element_shape)] + with ops.name_scope(name, "TensorArrayV2", [size, flow]) as scope: + if flow is None: + self._flow = list_ops.tensor_list_reserve( + element_shape=element_shape, + num_elements=size, + element_dtype=dtype, + name=scope) + else: + self._flow = flow + + # For backwards compatibility. + self._colocate_with_first_write_call = None + self._colocate_with = None + + @property + def flow(self): + return self._flow + + @property + def dtype(self): + return self._dtype + + @property + def handle(self): + # We intentionally do not raise an error so that legacy while_loop does not + # complain. + return None + + def _merge_element_shape(self, shape): + """Changes the element shape of the array given a shape to merge with. + + Args: + shape: A `TensorShape` object to merge with. + + Raises: + ValueError: if the provided shape is incompatible with the current + element shape of the `TensorArray`. + """ + + if self._element_shape: + if not shape.is_compatible_with(self._element_shape[0]): + raise ValueError( + "Inconsistent shapes: saw %s but expected %s " + "(and infer_shape=True)" % (shape, self._element_shape[0])) + self._element_shape[0] = self._element_shape[0].merge_with(shape) + else: + self._element_shape.append(shape) + + def identity(self): + """See TensorArray.""" + flow = array_ops.identity(self._flow) + ta = TensorArray( + dtype=self._dtype, flow=flow, infer_shape=self._infer_shape) + ta._element_shape = self._element_shape + return ta + + def grad(self, source, flow=None, name=None): + """Not supported.""" + raise NotImplementedError() + + def read(self, index, name=None): + """See TensorArray.""" + value = list_ops.tensor_list_get_item( + input_handle=self._flow, + index=index, + element_dtype=self._dtype, + name=name) + if self._element_shape: + value.set_shape(self._element_shape[0].dims) + return value + + @tf_should_use.should_use_result + def write(self, index, value, name=None): + """See TensorArray.""" + with ops.name_scope(name, "TensorArrayV2Write", [self._flow, index, value]): + value = ops.convert_to_tensor(value, name="value") + if self._infer_shape: + self._merge_element_shape(value.shape) + flow_out = list_ops.tensor_list_set_item( + input_handle=self._flow, index=index, item=value, name=name) + ta = TensorArray(dtype=self._dtype, handle=None, flow=flow_out) + ta._infer_shape = self._infer_shape + ta._element_shape = self._element_shape + return ta + + def stack(self, name=None): + """See TensorArray.""" + with ops.name_scope(name, "TensorArrayV2Stack", [self._flow]): + value = list_ops.tensor_list_stack( + input_handle=self._flow, element_dtype=self._dtype) + if self._element_shape and self._element_shape[0].dims is not None: + value.set_shape([None] + self._element_shape[0].dims) + return value + + def gather(self, indices, name=None): + """See TensorArray.""" + value = list_ops.tensor_list_gather( + input_handle=self._flow, + indices=indices, + element_dtype=self._dtype, + name=name) + if self._element_shape and self._element_shape[0].dims is not None: + value.set_shape([None] + self._element_shape[0].dims) + return value + + def concat(self, name=None): + """See TensorArray.""" + value = list_ops.tensor_list_concat( + input_handle=self._flow, element_dtype=self._dtype, name=name) + if self._element_shape and self._element_shape[0].dims is not None: + value.set_shape([None] + self._element_shape[0].dims[1:]) + return value + + @tf_should_use.should_use_result + def unstack(self, value, name=None): + """See TensorArray.""" + with ops.name_scope(name, "TensorArrayUnstack", [self._flow, value]): + value = ops.convert_to_tensor(value, name="value") + if self._infer_shape and not context.executing_eagerly(): + self._merge_element_shape(value.shape[1:]) + flow_out = list_ops.tensor_list_from_tensor( + tensor=value, element_shape=value.shape[1:]) + ta = TensorArray( + dtype=self._dtype, + handle=self.handle, + flow=flow_out, + colocate_with_first_write_call=self._colocate_with_first_write_call) + ta._infer_shape = self._infer_shape + ta._element_shape = self._element_shape + ta._colocate_with = self._colocate_with + return ta + + @tf_should_use.should_use_result + def scatter(self, indices, value, name=None): + """See TensorArray.""" + with ops.name_scope(name, "TensorArrayScatter", + [self._flow, value, indices]): + value = ops.convert_to_tensor(value, name="value") + if self._infer_shape and not context.executing_eagerly(): + self._merge_element_shape(value.shape[1:]) + flow_out = list_ops.tensor_list_scatter( + tensor=value, indices=indices, element_shape=-1) + ta = TensorArray( + dtype=self._dtype, + handle=self.handle, + flow=flow_out, + colocate_with_first_write_call=self._colocate_with_first_write_call) + ta._infer_shape = self._infer_shape + ta._element_shape = self._element_shape + ta._colocate_with = self._colocate_with + return ta + + @tf_should_use.should_use_result + def split(self, value, lengths, name=None): + """See TensorArray.""" + with ops.name_scope(name, "TensorArraySplit", [self._flow, value, lengths]): + value = ops.convert_to_tensor(value, name="value") + lengths_64 = math_ops.to_int64(lengths) + if self._infer_shape and not context.executing_eagerly(): + clengths = tensor_util.constant_value(lengths_64) + if value.shape.dims is not None: + if clengths is not None and clengths.max() == clengths.min(): + self._merge_element_shape( + tensor_shape.TensorShape([clengths[0]]).concatenate( + value.shape[1:])) + flow_out = list_ops.tensor_list_split( + tensor=value, + lengths=lengths_64, + element_shape=self._element_shape[0] if self._element_shape else None, + name=name) + ta = TensorArray( + dtype=self._dtype, + handle=self.handle, + flow=flow_out, + colocate_with_first_write_call=self._colocate_with_first_write_call) + ta._infer_shape = self._infer_shape + ta._element_shape = self._element_shape + ta._colocate_with = self._colocate_with + return ta + + def size(self, name=None): + """See TensorArray.""" + return list_ops.tensor_list_length(input_handle=self._flow, name=name) + + @tf_should_use.should_use_result + def close(self, name=None): + """See TensorArray.""" + return gen_control_flow_ops.no_op(name=name) + # pylint: enable=protected-access @@ -738,8 +1013,10 @@ class TensorArray(object): if context.executing_eagerly(): implementation = _EagerTensorArray else: - implementation = _GraphTensorArray - + if ENABLE_TENSOR_ARRAY_V2: + implementation = _GraphTensorArrayV2 + else: + implementation = _GraphTensorArray self._implementation = implementation( dtype, size=size, @@ -768,7 +1045,7 @@ class TensorArray(object): @property def handle(self): """The reference to the TensorArray.""" - return self._implementation._handle + return self._implementation.handle @property def _infer_shape(self): @@ -953,4 +1230,16 @@ class TensorArray(object): """Close the current TensorArray.""" return self._implementation.close(name=name) + +def build_ta_with_new_flow(old_ta, flow): + ta = TensorArray( + dtype=old_ta.dtype, + handle=old_ta.handle, + flow=flow, + infer_shape=old_ta._infer_shape, + colocate_with_first_write_call=old_ta._colocate_with_first_write_call) + ta._colocate_with = old_ta._colocate_with + ta._element_shape = old_ta._element_shape + return ta + # pylint: enable=protected-access diff --git a/tensorflow/python/ops/tensor_forest_ops.py b/tensorflow/python/ops/tensor_forest_ops.py new file mode 100644 index 0000000000..42f3cdf324 --- /dev/null +++ b/tensorflow/python/ops/tensor_forest_ops.py @@ -0,0 +1,110 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Ops for tensor_forest.""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.ops import resources + +from tensorflow.python import ops +from tensorflow.python.ops import gen_tensor_forest_ops +from tensorflow.python.training import saver + + +class TreeVariableSaveable(saver.BaseSaverBuilder.SaveableObject): + + def __init__(self, type_name, name, container, config, resource_handle_func, + create_op_func, is_initialized_op_func, serialize_op_func, + deserialize_op_func): + + with ops.name_scope(name, type_name) as name: + self._resource_handle = resource_handle_func( + container, shared_name=name, name=name) + + self._is_initialized_op = is_initialized_op_func( + self._resource_handle) + tensor = serialize_op_func(self._resource_handle) + self._create_op = create_op_func( + self._resource_handle, + config) + # slice_spec is useful for saving a slice from a variable. + # It's not meaningful the tree variable. So we just pass an empty + # value. + slice_spec = "" + specs = [saver.BaseSaverBuilder.SaveSpec(tensor, slice_spec, name)] + super(TreeVariableSaveable, + self).__init__(self._resource_handle, specs, name) + + ops.add_to_collection( + ops.GraphKeys.SAVEABLE_OBJECTS, self) + + resources.register_resource( + self._resource_handle, self._create_op, self._is_initialized_op) + self._deserialize_op_func = deserialize_op_func + + def restore(self, restored_tensors, unused_restored_shapes): + """Restores the associated tree from 'restored_tensors'. + + Args: + restored_tensors: the tensors that were loaded from a checkpoint. + unused_restored_shapes: the shapes this object should conform to after + restore. Not meaningful for trees. + + Returns: + The operation that restores the state of the tree variable. + """ + with ops.control_dependencies([self._create_op]): + return self._deserialize_op_func( + self._resource_handle, + restored_tensors[0], + ) + + @property + def resource(self): + return self._resource_handle + + +def tree_variable(tree_config, name, container=None): + return TreeVariableSaveable( + "TreeVariable", + name, + container, + tree_config, + gen_tensor_forest_ops.tensor_forest_tree_resource_handle_op, + gen_tensor_forest_ops.tensor_forest_create_tree_variable, + gen_tensor_forest_ops.tensor_forest_tree_is_initialized_op, + gen_tensor_forest_ops.tensor_forest_tree_serialize, + gen_tensor_forest_ops.tensor_forest_tree_deserialize).resource + + +class ForestVariables(object): + + def __init__(self, params, + tree_configs=None): + + self._variables = [] + + for i in range(params.n_trees): + tree_config = '' + if tree_configs is not None: + tree_config = tree_configs[i] + self._variables.append(tree_variable( + tree_config, + 'tree-%s' % i, + )) + + def __getitem__(self, t): + return self._variables[t] diff --git a/tensorflow/python/ops/variable_scope.py b/tensorflow/python/ops/variable_scope.py index fe93bfb61f..ccce9e2f93 100644 --- a/tensorflow/python/ops/variable_scope.py +++ b/tensorflow/python/ops/variable_scope.py @@ -646,14 +646,8 @@ class _VariableStore(object): when violating reuse during variable creation, or if an existing sharded variable exists for the given name but with different sharding. """ - if context.executing_eagerly(): - raise NotImplementedError("Partitioned variables are not yet supported " - "when eager execution is enabled.") - initializing_from_value = initializer is not None and isinstance( initializer, ops.Tensor) - reuse_without_partition = reuse and not partitioner - if name in self._vars: raise ValueError( "A partitioner was provided, but an unpartitioned version of the " @@ -664,30 +658,9 @@ class _VariableStore(object): if initializing_from_value: shape = shape.merge_with(initializer.get_shape()) - if not reuse_without_partition: - if not shape.is_fully_defined(): - raise ValueError("Shape of a new partitioned variable (%s) must be " - "fully defined, but instead was %s." % (name, shape)) - - if shape.ndims < 1: - raise ValueError("A partitioned Variable must have rank at least 1, " - "shape: %s" % shape) - - partitions = partitioner(shape=shape, dtype=dtype) - - if not isinstance(partitions, collections_lib.Sequence): - raise ValueError("Partitioner must return a sequence, but saw: %s" - % partitions) - - if len(partitions) != shape.ndims: - raise ValueError( - "Partitioner returned a partition list that does not match the " - "Variable's rank: %s vs. %s" % (partitions, shape)) - - if any([p < 1 for p in partitions]): - raise ValueError( - "Partitioner returned zero partitions for some axes: %s" % - partitions) + partitions = None + if not reuse or partitioner: + partitions = _call_partitioner(partitioner, shape, dtype) if name in self._partitioned_vars: if reuse is False: @@ -709,7 +682,7 @@ class _VariableStore(object): % (name, dtype.name, existing_var.dtype.name)) # pylint: disable=protected-access - if (not reuse_without_partition and + if (partitions is not None and existing_var._get_partitions() != partitions): raise ValueError( "Trying to reuse partitioned variable %s, but specified partitions " @@ -724,14 +697,7 @@ class _VariableStore(object): "created with tf.get_variable(). Did you mean to set " "reuse=False or reuse=tf.AUTO_REUSE in VarScope?" % name) - slice_dim, slice_shape = _compute_slice_dim_and_shape( - shape.as_list(), partitions) - - vs = [] - num_slices = partitions[slice_dim] - num_slices_with_excess = shape.dims[slice_dim].value % num_slices - - slice_offset = [0] * shape.ndims + slice_dim, num_slices = _get_slice_dim_and_num_slices(partitions) if "%s/part_0" % name in self._vars: if "%s/part_%d" % (name, num_slices - 1) not in self._vars: @@ -747,15 +713,14 @@ class _VariableStore(object): "%s/part_0 was found, but so was the extra shard %s/part_%d." % (num_slices, name, name, num_slices)) - for i in xrange(num_slices): - var_shape = slice_shape[:] - var_offset = slice_offset[:] + vs = [] + for i, (var_offset, var_shape) in enumerate(_iter_slices( + shape.as_list(), + num_slices, + slice_dim + )): partition_info = _PartitionInfo( full_shape=shape.as_list(), var_offset=var_offset) - if i < num_slices_with_excess: - var_shape[slice_dim] += 1 - slice_offset[slice_dim] += var_shape[slice_dim] - var_full_name = "%s/part_%d" % (name, i) with ops.name_scope(var_full_name + "/PartitionedInitializer"): # Create the tensor to initialize the variable with default value. @@ -803,15 +768,13 @@ class _VariableStore(object): vs.append(var) # pylint: enable=protected-access - # pylint: disable=protected-access partitioned_var = variables.PartitionedVariable(name=name, shape=shape, dtype=dtype, variable_list=vs, partitions=partitions) - # pylint: enable=protected-access - - self._partitioned_vars[name] = partitioned_var + if not context.executing_eagerly() or self._store_eager_variables: + self._partitioned_vars[name] = partitioned_var return partitioned_var def _get_single_variable(self, @@ -913,20 +876,22 @@ class _VariableStore(object): variable_dtype = None else: # Instantiate initializer if provided initializer is a type object. - if isinstance(initializer, type(init_ops.Initializer)): + if tf_inspect.isclass(initializer): initializer = initializer(dtype=dtype) - if shape and shape.is_fully_defined(): + if shape is not None and shape.is_fully_defined(): init_val = lambda: initializer( # pylint: disable=g-long-lambda shape.as_list(), dtype=dtype, partition_info=partition_info) - elif not tf_inspect.getargspec(initializer).args: + variable_dtype = dtype.base_dtype + elif len(tf_inspect.getargspec(initializer).args) == len( + tf_inspect.getargspec(initializer).defaults or []): init_val = initializer + variable_dtype = None else: - raise ValueError("You can only pass an initializer function that " - "expects no arguments to its callable when the " - "shape is not fully defined. The given initializer " - "function expects the following args %s" % - tf_inspect.getargspec(initializer).args) - variable_dtype = dtype.base_dtype + raise ValueError("The initializer passed is not valid. It should " + "be a callable with no arguments and the " + "shape should not be provided or an instance of " + "`tf.keras.initializers.*' and `shape` should be " + "fully defined.") # Create the variable. if use_resource is None: @@ -1080,9 +1045,6 @@ class VariableScope(object): if self._caching_device is not None: raise NotImplementedError("Caching devices is not yet supported " "when eager execution is enabled.") - if self._partitioner is not None: - raise NotImplementedError("Partitioned variables are not yet supported " - "when eager execution is enabled.") self._reuse = AUTO_REUSE self._use_resource = True @@ -1162,9 +1124,6 @@ class VariableScope(object): def set_partitioner(self, partitioner): """Set partitioner for this scope.""" - if partitioner and context.executing_eagerly(): - raise NotImplementedError("Partitioned variables are not yet supported " - "when eager execution is enabled.") self._partitioner = partitioner def set_custom_getter(self, custom_getter): @@ -1277,9 +1236,6 @@ class VariableScope(object): synchronization=VariableSynchronization.AUTO, aggregation=VariableAggregation.NONE): """Gets an existing variable with this name or create a new one.""" - if context.executing_eagerly(): - raise NotImplementedError("Partitioned variables are not yet supported " - "when eager execution is enabled.") if initializer is None: initializer = self._initializer if regularizer is None: @@ -2246,8 +2202,8 @@ class variable_scope(object): try: return self._enter_scope_uncached() - except: - if not self._building_function: + except Exception: + if self._in_graph_mode and not self._building_function: if self._graph_context_manager is not None: self._graph_context_manager.__exit__(*sys.exc_info()) raise @@ -2413,34 +2369,71 @@ def variable_op_scope(values, yield scope -def _compute_slice_dim_and_shape(full_shape, slicing): - """Computes which dimension is being sliced and the typical slice shape.""" - - slice_shape = [0] * len(full_shape) - slice_dim = None - for dim, num_slices in enumerate(slicing): - dim_size = full_shape[dim] - if num_slices <= 0 or dim_size < num_slices: - raise ValueError("Cannot create %d slices for size %d. shape: %s, " - "slicing: %s" % - (num_slices, full_shape[dim], full_shape, slicing)) - if num_slices == 1: - # Not slicing in this dimension. - slice_shape[dim] = dim_size - elif slice_dim is not None: - # We only support slicing along one of the dimensions. - raise ValueError("Can only slice a variable along one dimension: " - "shape: %s, slicing: %s" % (full_shape, slicing)) - else: - # Note: We will add any extras onto the last slice, later. - slice_dim = dim - slice_shape[dim] = dim_size // num_slices +def _call_partitioner(partitioner, shape, dtype): + """Call partitioner validating its inputs/output. - # Degenerate case: If "slicing" was all ones, pretend we are slicing along - # the first dimension. - if slice_dim is None: + Args: + partitioner: a function mapping `Tensor` shape and dtype to a + list of partitions. + shape: shape of the `Tensor` to partition, must have at least two + dimensions. + dtype: dtype of the elements in the `Tensor`. + + Returns: + A list with elements >=1 and exactly one >1. The index of that + element corresponds to the partitioning axis. + """ + if not shape.is_fully_defined(): + raise ValueError("Shape of a new partitioned variable must be " + "fully defined, but instead was %s." % (shape,)) + if shape.ndims < 1: + raise ValueError("A partitioned Variable must have rank at least 1, " + "shape: %s" % shape) + + slicing = partitioner(shape=shape, dtype=dtype) + if not isinstance(slicing, collections_lib.Sequence): + raise ValueError("Partitioner must return a sequence, but saw: %s" + % slicing) + if len(slicing) != shape.ndims: + raise ValueError( + "Partitioner returned a partition list that does not match the " + "Variable's rank: %s vs. %s" % (slicing, shape)) + if any(p < 1 for p in slicing): + raise ValueError( + "Partitioner returned zero partitions for some axes: %s" % + slicing) + if sum(p > 1 for p in slicing) > 1: + raise ValueError( + "Can only slice a variable along one dimension: " + "shape: %s, partitioning: %s" % (shape, slicing)) + return slicing + + +# TODO(slebedev): could be inlined, but +# `_VariableStore._get_partitioned_variable` is too complex even +# without this logic. +def _get_slice_dim_and_num_slices(slicing): + """Get slicing dimension and number of slices from the partitioner output.""" + for slice_dim, num_slices in enumerate(slicing): + if num_slices > 1: + break + else: + # Degenerate case: no partitioning applied. slice_dim = 0 - return slice_dim, slice_shape + num_slices = 1 + return slice_dim, num_slices + + +def _iter_slices(full_shape, num_slices, slice_dim): + """Slices a given a shape along the specified dimension.""" + num_slices_with_excess = full_shape[slice_dim] % num_slices + offset = [0] * len(full_shape) + min_slice_len = full_shape[slice_dim] // num_slices + for i in xrange(num_slices): + shape = full_shape[:] + shape[slice_dim] = min_slice_len + bool(i < num_slices_with_excess) + yield offset[:], shape + offset[slice_dim] += shape[slice_dim] def _get_trainable_value(synchronization, trainable): diff --git a/tensorflow/python/ops/variables.py b/tensorflow/python/ops/variables.py index e43736069e..d809c81b98 100644 --- a/tensorflow/python/ops/variables.py +++ b/tensorflow/python/ops/variables.py @@ -18,7 +18,8 @@ from __future__ import division from __future__ import print_function import enum # pylint: disable=g-bad-import-order - +import functools +import os import six from tensorflow.core.framework import attr_value_pb2 @@ -860,18 +861,18 @@ class Variable(six.with_metaclass(VariableMetaclass, else: return v.value() - @staticmethod - def _OverloadAllOperators(): # pylint: disable=invalid-name + @classmethod + def _OverloadAllOperators(cls): # pylint: disable=invalid-name """Register overloads for all operators.""" for operator in ops.Tensor.OVERLOADABLE_OPERATORS: - Variable._OverloadOperator(operator) + cls._OverloadOperator(operator) # For slicing, bind getitem differently than a tensor (use SliceHelperVar # instead) # pylint: disable=protected-access - setattr(Variable, "__getitem__", array_ops._SliceHelperVar) + setattr(cls, "__getitem__", array_ops._SliceHelperVar) - @staticmethod - def _OverloadOperator(operator): # pylint: disable=invalid-name + @classmethod + def _OverloadOperator(cls, operator): # pylint: disable=invalid-name """Defer an operator overload to `ops.Tensor`. We pull the operator out of ops.Tensor dynamically to avoid ordering issues. @@ -879,17 +880,26 @@ class Variable(six.with_metaclass(VariableMetaclass, Args: operator: string. The operator name. """ + tensor_oper = getattr(ops.Tensor, operator) - def _run_op(a, *args): + def _run_op(a, *args, **kwargs): # pylint: disable=protected-access - return getattr(ops.Tensor, operator)(a._AsTensor(), *args) - # Propagate __doc__ to wrapper - try: - _run_op.__doc__ = getattr(ops.Tensor, operator).__doc__ - except AttributeError: - pass + return tensor_oper(a._AsTensor(), *args, **kwargs) - setattr(Variable, operator, _run_op) + functools.update_wrapper(_run_op, tensor_oper) + setattr(cls, operator, _run_op) + + def __iter__(self): + """Dummy method to prevent iteration. Do not call. + + NOTE(mrry): If we register __getitem__ as an overloaded operator, + Python will valiantly attempt to iterate over the variable's Tensor from 0 + to infinity. Declaring this method prevents this unintended behavior. + + Raises: + TypeError: when invoked. + """ + raise TypeError("'Variable' object is not iterable.") # NOTE(mrry): This enables the Variable's overloaded "right" binary # operators to run when the left operand is an ndarray, because it @@ -1045,27 +1055,6 @@ class Variable(six.with_metaclass(VariableMetaclass, else: return None - def __iadd__(self, other): - raise NotImplementedError - - def __isub__(self, other): - raise NotImplementedError - - def __imul__(self, other): - raise NotImplementedError - - def __idiv__(self, other): - raise NotImplementedError - - def __itruediv__(self, other): - raise NotImplementedError - - def __irealdiv__(self, other): - raise NotImplementedError - - def __ipow__(self, other): - raise NotImplementedError - @tf_export(v1=["Variable"]) class VariableV1(Variable): @@ -1576,18 +1565,6 @@ class RefVariable(VariableV1): """ return self._snapshot - def __iter__(self): - """Dummy method to prevent iteration. Do not call. - - NOTE(mrry): If we register __getitem__ as an overloaded operator, - Python will valiantly attempt to iterate over the variable's Tensor from 0 - to infinity. Declaring this method prevents this unintended behavior. - - Raises: - TypeError: when invoked. - """ - raise TypeError("'Variable' object is not iterable.") - def value(self): """Returns the last snapshot of this variable. @@ -2123,37 +2100,6 @@ class RefVariable(VariableV1): else: return v.value() - @staticmethod - def _OverloadAllOperators(): # pylint: disable=invalid-name - """Register overloads for all operators.""" - for operator in ops.Tensor.OVERLOADABLE_OPERATORS: - Variable._OverloadOperator(operator) # pylint: disable=protected-access - # For slicing, bind getitem differently than a tensor (use SliceHelperVar - # instead) - # pylint: disable=protected-access - setattr(Variable, "__getitem__", array_ops._SliceHelperVar) - - @staticmethod - def _OverloadOperator(operator): # pylint: disable=invalid-name - """Defer an operator overload to `ops.Tensor`. - - We pull the operator out of ops.Tensor dynamically to avoid ordering issues. - - Args: - operator: string. The operator name. - """ - - def _run_op(a, *args): - # pylint: disable=protected-access - return getattr(ops.Tensor, operator)(a._AsTensor(), *args) - # Propagate __doc__ to wrapper - try: - _run_op.__doc__ = getattr(ops.Tensor, operator).__doc__ - except AttributeError: - pass - - setattr(Variable, operator, _run_op) - def _gather_saveables_for_checkpoint(self): """For implementing `Checkpointable`. This object is saveable on its own.""" return {checkpointable.VARIABLE_VALUE_KEY: self} @@ -2457,34 +2403,6 @@ class PartitionedVariable(object): @end_compatibility """ - class PartitionedVariableIterator(object): - """An iterator that allows accessing the underlying `Variable` objects. - - This iterator is necessary to control order of access when Variables - are not partitioned in a standard way along a single axis. - - Allows e.g. `list(partitioned_variable)` to return a proper list. - """ - - def __init__(self, partitioned_variable): - self._ix = 0 - self._partitioned_variable = partitioned_variable - - def __iter__(self): - return self - - def __next__(self): # For python3 compatibility. - return self.next() - - def next(self): - # pylint: disable=protected-access - if self._ix >= len(self._partitioned_variable._variable_list): - raise StopIteration() - variable = self._partitioned_variable._variable_list[self._ix] - # pylint: enable=protected-access - self._ix += 1 - return variable - def __init__(self, name, shape, dtype, variable_list, partitions): """Creates a new partitioned variable wrapper. @@ -2504,31 +2422,27 @@ class PartitionedVariable(object): `partitions` is not a list. ValueError: If `variable_list` is empty, or the `Variable` shape information does not match `shape`, or `partitions` has invalid values. - RuntimeError: If eager execution is enabled """ - if context.executing_eagerly(): - raise RuntimeError( - "tf.PartitionedVariable not supported with eager execution enabled.") if not isinstance(variable_list, (list, tuple)): raise TypeError( "variable_list is not a list or tuple: %s" % variable_list) if not isinstance(partitions, (list, tuple)): raise TypeError("partitions is not a list or tuple: %s" % partitions) - if not all([p >= 1 for p in partitions]): + if not all(p >= 1 for p in partitions): raise ValueError("partition values must be positive: %s" % partitions) if not variable_list: raise ValueError("variable_list may not be empty") # pylint: disable=protected-access for v in variable_list: # Sort the variable_list lexicographically according to var offset value. - if not all([v._get_save_slice_info() is not None for v in variable_list]): + if not all(v._get_save_slice_info() is not None for v in variable_list): raise ValueError( "All variables must have a save_slice_info available: %s" % [v.name for v in variable_list]) if len(shape) != len(partitions): raise ValueError("len(shape) != len(partitions): %s vs. %s" % (shape, partitions)) - if not all([v._get_save_slice_info().full_shape == shape]): + if v._get_save_slice_info().full_shape != shape: raise ValueError( "All variables' full shapes must match shape: %s; " "but full shapes were: %s" @@ -2545,7 +2459,7 @@ class PartitionedVariable(object): def __iter__(self): """Return an iterable for accessing the underlying partition Variables.""" - return self.PartitionedVariableIterator(self) + return iter(self._variable_list) def __len__(self): num_partition_axes = len(self._partition_axes()) @@ -2555,7 +2469,7 @@ class PartitionedVariable(object): return len(self._variable_list) def _partition_axes(self): - if all([p == 1 for p in self._partitions]): + if all(p == 1 for p in self._partitions): return [0] else: return [i for i, p in enumerate(self._partitions) if p > 1] @@ -2995,7 +2909,8 @@ def report_uninitialized_variables(var_list=None, # Run all operations on CPU if var_list: init_vars = [state_ops.is_variable_initialized(v) for v in var_list] - with ops.device("/cpu:0"): + local_device = os.environ.get("TF_DEVICE_FOR_UNINITIALIZED_VARIABLE_REPORTING", "/cpu:0") + with ops.device(local_device): if not var_list: # Return an empty tensor so we only need to check for returned tensor # size being 0 as an indication of model ready. diff --git a/tensorflow/python/ops/while_v2.py b/tensorflow/python/ops/while_v2.py index 7b0f0ed4fc..59ca29e3ba 100644 --- a/tensorflow/python/ops/while_v2.py +++ b/tensorflow/python/ops/while_v2.py @@ -23,7 +23,6 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.core.framework import attr_value_pb2 from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import func_graph as func_graph_module @@ -65,7 +64,8 @@ def while_loop(cond, loop_vars, shape_invariants=None, maximum_iterations=None, - name=None): + name=None, + return_same_structure=True): """Like tf.while_loop, except emits a single While op.""" maximum_iterations = _validate_and_convert_to_tensor(maximum_iterations) # Keep the original loop_vars around to know which args were TensorArrays. @@ -100,7 +100,8 @@ def while_loop(cond, # Add loop counter needed for computing gradients. loop_vars = [loop_counter] + loop_vars - shape_invariants = [tensor_shape.scalar()] + shape_invariants + shape_invariants = type(shape_invariants)([tensor_shape.scalar() + ]) + shape_invariants # Automatic control dependencies are added in defuns, but not in v1 # graphs. Propagate that behavior here. @@ -133,9 +134,8 @@ def while_loop(cond, # the value of that tensor in each iteration is the same as it was at the # beginning of the loop execution. loop_vars = loop_vars + cond_graph.external_captures - shape_invariants = shape_invariants + [ - t.shape for t in cond_graph.external_captures - ] + shape_invariants = shape_invariants + type(shape_invariants)( + [t.shape for t in cond_graph.external_captures]) def wrapped_body(loop_counter, *args): """Loop body augmented with counter update. @@ -208,8 +208,7 @@ def while_loop(cond, for intermediate_tensor in intermediate_tensors: tensor_list = list_ops.empty_tensor_list( element_dtype=intermediate_tensor.dtype, - element_shape=_get_tensor_convertible_shape( - intermediate_tensor.shape), + element_shape=intermediate_tensor.shape, max_num_elements=maximum_iterations) loop_vars.append(tensor_list) with cond_graph.as_default(): @@ -245,7 +244,7 @@ def while_loop(cond, name=scope) _copy_handle_data(body_graph.outputs, outputs) - _maybe_set_lowering_attr(outputs[0].op) + util.maybe_set_lowering_attr(outputs[0].op) _maybe_set_maximum_iterations_attr(outputs[0].op, maximum_iterations) # Return identities for each output of the While op, rather than the output @@ -257,11 +256,17 @@ def while_loop(cond, outputs = tuple(array_ops.identity(t) for t in outputs) # First var is loop counter. - if num_flattened_outputs == 1: - return outputs[1] + outputs = _pack_sequence_as(orig_loop_vars, + outputs[1:1 + num_flattened_outputs]) + + if return_same_structure: + return outputs + + flattened_outputs = nest.flatten(outputs) + if len(flattened_outputs) == 1: + return flattened_outputs[0] else: - return _pack_sequence_as(orig_loop_vars, - outputs[1:1 + num_flattened_outputs]) + return outputs @ops.RegisterGradient("While") @@ -313,7 +318,7 @@ def _WhileGrad(op, *grads): # pylint: disable=invalid-name for intermediate_tensor in intermediate_tensors: tensor_list = list_ops.empty_tensor_list( element_dtype=intermediate_tensor.dtype, - element_shape=_get_tensor_convertible_shape(intermediate_tensor.shape), + element_shape=intermediate_tensor.shape, max_num_elements=maximum_iterations) with body_grad_graph.as_default(): @@ -343,9 +348,12 @@ def _WhileGrad(op, *grads): # pylint: disable=invalid-name name="%s_grad" % op.name) _copy_handle_data(body_grad_graph.outputs, outputs) - _maybe_set_lowering_attr(outputs[0].op) + util.maybe_set_lowering_attr(outputs[0].op) _maybe_set_maximum_iterations_attr(outputs[0].op, maximum_iterations) + # See comment in while_loop. + outputs = [array_ops.identity(t) for t in outputs] + # Set None as the output gradient for tensors with None input gradient # e.g. TensorArray handles. # outputs[0] is the loop counter. @@ -505,7 +513,7 @@ def _grad_fn(ys, xs, args, func_graph): # TODO(b/118712257): Handle the case when grad_outs has None's e.g. when there # is a tf.StopGradient in the loop body. - assert all([g is not None for g in grad_outs]) + assert all(g is not None for g in grad_outs) counter = args[0] total_iters = args[1] return [counter + 1, total_iters] + grad_outs @@ -792,29 +800,6 @@ def _copy_handle_data(src_tensors, tgt_tensors): custom_gradient.copy_handle_data(src_t, tgt_t) -# TODO(srbs): Move to common utils for cond_v2 and while_v2. -def _maybe_set_lowering_attr(op): - """Sets the flag to enable lowering on the `While` op if necessary. - - Lowering allows while_v2 to avoid some of the limitations of Functions, - allowing users to specify devices & colocation inside of while_v2 - branches, and enabling non-strict evaluation & partial pruning of while_v2 - branches. This brings while_v2 closer to feature parity with - tf.while_loop. - - However, we do not lower `While` in the XLA context because it is easier - for XLA to apply its own optimizations when dealing with un-lowered - `While` operators than with low-level control flow primitives. - - Args: - op: The While op. - """ - if not control_flow_util.IsInXLAContext(op): - # pylint: disable=protected-access - op._set_attr("_lower_using_switch_merge", attr_value_pb2.AttrValue(b=True)) - # pylint: enable=protected-access - - def _maybe_set_maximum_iterations_attr(op, maximum_iterations): if control_flow_util.IsInXLAContext(op): # Store the maximum_iterations to use in the gradient pass. @@ -837,18 +822,6 @@ def _is_in_xla_context(): return control_flow_util.GetContainingXLAContext(cur_ctxt) is not None -def _get_tensor_convertible_shape(shape): - assert isinstance(shape, tensor_shape.TensorShape) - if shape.is_fully_defined(): - return shape - if not shape: # Unknown shape. - return -1 - # Partially defined shape. - shape_list = shape.as_list() - shape_list = [s if s is not None else -1 for s in shape_list] - return ops.convert_to_tensor(shape_list) - - def _graph_name(graph): if isinstance(graph, func_graph_module.FuncGraph): return graph.name @@ -870,6 +843,10 @@ def _is_tensor_array_handle(tensor): # TODO(b/118452219): add test coverage for this. tensor = func_graph_module.maybe_captured(tensor) + if isinstance(tensor, ops.EagerTensor): + # Eager execution doesn't quite support legacy tensorarray + return False + return tensor.op.type in TENSOR_ARRAY_HANDLE_OPS diff --git a/tensorflow/python/platform/__init__.py b/tensorflow/python/platform/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tensorflow/python/platform/app.py b/tensorflow/python/platform/app.py index 4c91bc3652..7b917235c0 100644 --- a/tensorflow/python/platform/app.py +++ b/tensorflow/python/platform/app.py @@ -108,7 +108,7 @@ def _define_help_flags(): _define_help_flags_called = True -@tf_export('app.run') +@tf_export(v1=['app.run']) def run(main=None, argv=None): """Runs the program with an optional 'main' function and 'argv' list.""" diff --git a/tensorflow/python/platform/benchmark.py b/tensorflow/python/platform/benchmark.py index 4f7abb311a..d6773d7b81 100644 --- a/tensorflow/python/platform/benchmark.py +++ b/tensorflow/python/platform/benchmark.py @@ -30,6 +30,7 @@ from tensorflow.core.protobuf import config_pb2 from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.core.util import test_log_pb2 from tensorflow.python.client import timeline +from tensorflow.python.framework import ops from tensorflow.python.platform import app from tensorflow.python.platform import gfile from tensorflow.python.platform import tf_logging as logging @@ -299,6 +300,18 @@ class TensorFlowBenchmark(Benchmark): benchmark_values["extras"].update(unreported_extras) return benchmark_values + def evaluate(self, tensors): + """Evaluates tensors and returns numpy values. + + Args: + tensors: A Tensor or a nested list/tuple of Tensors. + + Returns: + tensors numpy values. + """ + sess = ops.get_default_session() or self.cached_session() + return sess.run(tensors) + def _run_benchmarks(regex): """Run benchmarks that match regex `regex`. diff --git a/tensorflow/python/platform/gfile.py b/tensorflow/python/platform/gfile.py index 5927bc2409..d0159e9e98 100644 --- a/tensorflow/python/platform/gfile.py +++ b/tensorflow/python/platform/gfile.py @@ -37,7 +37,7 @@ from tensorflow.python.util.deprecation import deprecated from tensorflow.python.util.tf_export import tf_export -@tf_export('gfile.GFile', 'gfile.Open') +@tf_export(v1=['gfile.GFile', 'gfile.Open'], v2=['io.gfile.GFile']) class GFile(_FileIO): """File I/O wrappers without thread locking. @@ -52,7 +52,7 @@ class GFile(_FileIO): super(GFile, self).__init__(name=name, mode=mode) -@tf_export('gfile.FastGFile') +@tf_export(v1=['gfile.FastGFile']) class FastGFile(_FileIO): """File I/O wrappers without thread locking. diff --git a/tensorflow/python/platform/googletest.py b/tensorflow/python/platform/googletest.py index 8141cf92c5..4d34c508da 100644 --- a/tensorflow/python/platform/googletest.py +++ b/tensorflow/python/platform/googletest.py @@ -104,10 +104,13 @@ def GetTempDir(): """Return a temporary directory for tests to use.""" global _googletest_temp_dir if not _googletest_temp_dir: - first_frame = tf_inspect.stack()[-1][0] - temp_dir = os.path.join(tempfile.gettempdir(), - os.path.basename(tf_inspect.getfile(first_frame))) - temp_dir = tempfile.mkdtemp(prefix=temp_dir.rstrip('.py')) + if os.environ.get('TEST_TMPDIR'): + temp_dir = tempfile.mkdtemp(prefix=os.environ['TEST_TMPDIR']) + else: + first_frame = tf_inspect.stack()[-1][0] + temp_dir = os.path.join(tempfile.gettempdir(), + os.path.basename(tf_inspect.getfile(first_frame))) + temp_dir = tempfile.mkdtemp(prefix=temp_dir.rstrip('.py')) def delete_temp_dir(dirname=temp_dir): try: diff --git a/tensorflow/python/platform/test.py b/tensorflow/python/platform/test.py index d084870b25..943832af7a 100644 --- a/tensorflow/python/platform/test.py +++ b/tensorflow/python/platform/test.py @@ -46,9 +46,9 @@ from tensorflow.python.util.tf_export import tf_export if sys.version_info.major == 2: import mock # pylint: disable=g-import-not-at-top,unused-import else: - from unittest import mock # pylint: disable=g-import-not-at-top + from unittest import mock # pylint: disable=g-import-not-at-top,g-importing-member -tf_export('test.mock')(mock) +tf_export(v1=['test.mock'])(mock) # Import Benchmark class Benchmark = _googletest.Benchmark # pylint: disable=invalid-name diff --git a/tensorflow/python/platform/tf_logging.py b/tensorflow/python/platform/tf_logging.py index 59e60856ae..813bcb89be 100644 --- a/tensorflow/python/platform/tf_logging.py +++ b/tensorflow/python/platform/tf_logging.py @@ -37,7 +37,7 @@ import six from tensorflow.python.util.tf_export import tf_export -# Don't use this directly. Use _get_logger() instead. +# Don't use this directly. Use get_logger() instead. _logger = None _logger_lock = threading.Lock() @@ -78,7 +78,8 @@ else: return '(unknown file)', 0, '(unknown function)' -def _get_logger(): +@tf_export('get_logger') +def get_logger(): """Return TF logger instance.""" global _logger @@ -130,39 +131,39 @@ def _get_logger(): _logger_lock.release() -@tf_export('logging.log') +@tf_export(v1=['logging.log']) def log(level, msg, *args, **kwargs): - _get_logger().log(level, msg, *args, **kwargs) + get_logger().log(level, msg, *args, **kwargs) -@tf_export('logging.debug') +@tf_export(v1=['logging.debug']) def debug(msg, *args, **kwargs): - _get_logger().debug(msg, *args, **kwargs) + get_logger().debug(msg, *args, **kwargs) -@tf_export('logging.error') +@tf_export(v1=['logging.error']) def error(msg, *args, **kwargs): - _get_logger().error(msg, *args, **kwargs) + get_logger().error(msg, *args, **kwargs) -@tf_export('logging.fatal') +@tf_export(v1=['logging.fatal']) def fatal(msg, *args, **kwargs): - _get_logger().fatal(msg, *args, **kwargs) + get_logger().fatal(msg, *args, **kwargs) -@tf_export('logging.info') +@tf_export(v1=['logging.info']) def info(msg, *args, **kwargs): - _get_logger().info(msg, *args, **kwargs) + get_logger().info(msg, *args, **kwargs) -@tf_export('logging.warn') +@tf_export(v1=['logging.warn']) def warn(msg, *args, **kwargs): - _get_logger().warn(msg, *args, **kwargs) + get_logger().warn(msg, *args, **kwargs) -@tf_export('logging.warning') +@tf_export(v1=['logging.warning']) def warning(msg, *args, **kwargs): - _get_logger().warning(msg, *args, **kwargs) + get_logger().warning(msg, *args, **kwargs) _level_names = { @@ -183,20 +184,20 @@ _log_prefix = None # later set to google2_log_prefix _log_counter_per_token = {} -@tf_export('logging.TaskLevelStatusMessage') +@tf_export(v1=['logging.TaskLevelStatusMessage']) def TaskLevelStatusMessage(msg): error(msg) -@tf_export('logging.flush') +@tf_export(v1=['logging.flush']) def flush(): raise NotImplementedError() # Code below is taken from pyglib/logging -@tf_export('logging.vlog') +@tf_export(v1=['logging.vlog']) def vlog(level, msg, *args, **kwargs): - _get_logger().log(level, msg, *args, **kwargs) + get_logger().log(level, msg, *args, **kwargs) def _GetNextLogCountPerToken(token): @@ -214,7 +215,7 @@ def _GetNextLogCountPerToken(token): return _log_counter_per_token[token] -@tf_export('logging.log_every_n') +@tf_export(v1=['logging.log_every_n']) def log_every_n(level, msg, n, *args): """Log 'msg % args' at level 'level' once per 'n' times. @@ -231,7 +232,7 @@ def log_every_n(level, msg, n, *args): log_if(level, msg, not (count % n), *args) -@tf_export('logging.log_first_n') +@tf_export(v1=['logging.log_first_n']) def log_first_n(level, msg, n, *args): # pylint: disable=g-bad-name """Log 'msg % args' at level 'level' only first 'n' times. @@ -247,7 +248,7 @@ def log_first_n(level, msg, n, *args): # pylint: disable=g-bad-name log_if(level, msg, count < n, *args) -@tf_export('logging.log_if') +@tf_export(v1=['logging.log_if']) def log_if(level, msg, condition, *args): """Log 'msg % args' at level 'level' only if condition is fulfilled.""" if condition: @@ -296,16 +297,16 @@ def google2_log_prefix(level, timestamp=None, file_and_line=None): return s -@tf_export('logging.get_verbosity') +@tf_export(v1=['logging.get_verbosity']) def get_verbosity(): """Return how much logging output will be produced.""" - return _get_logger().getEffectiveLevel() + return get_logger().getEffectiveLevel() -@tf_export('logging.set_verbosity') +@tf_export(v1=['logging.set_verbosity']) def set_verbosity(v): """Sets the threshold for what messages will be logged.""" - _get_logger().setLevel(v) + get_logger().setLevel(v) def _get_thread_id(): @@ -318,8 +319,8 @@ def _get_thread_id(): _log_prefix = google2_log_prefix -tf_export('logging.DEBUG').export_constant(__name__, 'DEBUG') -tf_export('logging.ERROR').export_constant(__name__, 'ERROR') -tf_export('logging.FATAL').export_constant(__name__, 'FATAL') -tf_export('logging.INFO').export_constant(__name__, 'INFO') -tf_export('logging.WARN').export_constant(__name__, 'WARN') +tf_export(v1=['logging.DEBUG']).export_constant(__name__, 'DEBUG') +tf_export(v1=['logging.ERROR']).export_constant(__name__, 'ERROR') +tf_export(v1=['logging.FATAL']).export_constant(__name__, 'FATAL') +tf_export(v1=['logging.INFO']).export_constant(__name__, 'INFO') +tf_export(v1=['logging.WARN']).export_constant(__name__, 'WARN') diff --git a/tensorflow/python/profiler/internal/run_metadata_test.py b/tensorflow/python/profiler/internal/run_metadata_test.py index 216cc3dd54..a8859f845b 100644 --- a/tensorflow/python/profiler/internal/run_metadata_test.py +++ b/tensorflow/python/profiler/internal/run_metadata_test.py @@ -26,6 +26,7 @@ from tensorflow.core.protobuf import config_pb2 from tensorflow.core.protobuf import rewriter_config_pb2 from tensorflow.python.client import session from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import variables @@ -154,6 +155,7 @@ class RunMetadataTest(test.TestCase): # deallocates the memory after matmul started. self.assertGreater(random_allocs[1].alloc_micros, mm.all_start_micros) + @test_util.run_deprecated_v1 def testCPU(self): ops.reset_default_graph() with ops.device('/cpu:0'): @@ -167,6 +169,7 @@ class RunMetadataTest(test.TestCase): ret = _extract_node(run_meta, 'MatMul:MatMul') self.assertEqual(len(ret), 0) + @test_util.run_deprecated_v1 def testLoopCPU(self): ops.reset_default_graph() with ops.device('/cpu:0'): diff --git a/tensorflow/python/profiler/model_analyzer.py b/tensorflow/python/profiler/model_analyzer.py index 5f19eac043..4b2d9052b7 100644 --- a/tensorflow/python/profiler/model_analyzer.py +++ b/tensorflow/python/profiler/model_analyzer.py @@ -122,7 +122,7 @@ def _build_advisor_options(options): return opts -@tf_export('profiler.Profiler') +@tf_export(v1=['profiler.Profiler']) class Profiler(object): """TensorFlow multi-step profiler. @@ -306,7 +306,7 @@ class Profiler(object): print_mdl.WriteProfile(filename) -@tf_export('profiler.profile') +@tf_export(v1=['profiler.profile']) def profile(graph=None, run_meta=None, op_log=None, @@ -381,7 +381,7 @@ def profile(graph=None, return tfprof_node -@tf_export('profiler.advise') +@tf_export(v1=['profiler.advise']) def advise(graph=None, run_meta=None, options=_DEFAULT_ADVISE_OPTIONS): """Auto profile and advise. diff --git a/tensorflow/python/profiler/model_analyzer_test.py b/tensorflow/python/profiler/model_analyzer_test.py index 94c685274a..8648f0b514 100644 --- a/tensorflow/python/profiler/model_analyzer_test.py +++ b/tensorflow/python/profiler/model_analyzer_test.py @@ -93,10 +93,10 @@ class PrintModelAnalysisTest(test.TestCase): config=self._no_rewrite_session_config()) as sess, ops.device(dev): x = lib.BuildSmallModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) pctx.trace_next_step() pctx.dump_next_step() - _ = sess.run(x) + _ = self.evaluate(x) pctx.profiler.profile_name_scope(options=opts) @@ -160,7 +160,7 @@ class PrintModelAnalysisTest(test.TestCase): ) as sess, ops.device('/device:CPU:0'): x = lib.BuildSmallModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) run_meta = config_pb2.RunMetadata() _ = sess.run(x, options=config_pb2.RunOptions( @@ -186,7 +186,7 @@ class PrintModelAnalysisTest(test.TestCase): with session.Session(config=self._no_rewrite_session_config()) as sess: x = lib.BuildSmallModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) run_meta = config_pb2.RunMetadata() _ = sess.run(x, options=config_pb2.RunOptions( @@ -220,9 +220,9 @@ class PrintModelAnalysisTest(test.TestCase): with session.Session(config=self._no_rewrite_session_config()) as sess: x = lib.BuildFullModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) pctx.trace_next_step() - _ = sess.run(x) + _ = self.evaluate(x) tfprof_node = pctx.profiler.profile_python(options=opts) # pylint: disable=line-too-long @@ -281,7 +281,7 @@ class PrintModelAnalysisTest(test.TestCase): with session.Session(config=self._no_rewrite_session_config()) as sess: x = lib.BuildSmallModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) run_meta = config_pb2.RunMetadata() _ = sess.run(x, options=config_pb2.RunOptions( @@ -309,7 +309,7 @@ class PrintModelAnalysisTest(test.TestCase): with session.Session(config=self._no_rewrite_session_config()) as sess: x = lib.BuildFullModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) run_meta = config_pb2.RunMetadata() _ = sess.run( x, @@ -345,7 +345,7 @@ class PrintModelAnalysisTest(test.TestCase): with session.Session(config=self._no_rewrite_session_config()) as sess: x = lib.BuildFullModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) run_meta = config_pb2.RunMetadata() _ = sess.run(x, options=config_pb2.RunOptions( @@ -391,7 +391,7 @@ class PrintModelAnalysisTest(test.TestCase): with session.Session(config=self._no_rewrite_session_config()) as sess: x = lib.BuildFullModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) run_meta = config_pb2.RunMetadata() _ = sess.run( x, @@ -424,7 +424,7 @@ class PrintModelAnalysisTest(test.TestCase): with session.Session(config=self._no_rewrite_session_config()) as sess: x = lib.BuildFullModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) run_meta = config_pb2.RunMetadata() _ = sess.run( x, @@ -490,7 +490,7 @@ class PrintModelAnalysisTest(test.TestCase): with session.Session(config=self._no_rewrite_session_config()) as sess: x = lib.BuildSmallModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) run_meta = config_pb2.RunMetadata() _ = sess.run(x, options=config_pb2.RunOptions( @@ -555,7 +555,7 @@ class PrintModelAnalysisTest(test.TestCase): with session.Session(config=self._no_rewrite_session_config()) as sess: x = lib.BuildSmallModel() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) run_meta = config_pb2.RunMetadata() _ = sess.run(x, options=config_pb2.RunOptions( @@ -587,10 +587,10 @@ class PrintModelAnalysisTest(test.TestCase): def _trainLoop(self, train_op, train_steps, time_dir, time_step, memory_dir, memory_step, profile_dir, dump_step): with session.Session(config=self._no_rewrite_session_config()) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # start from 1 because variable_initializer took one step. for i in range(1, train_steps + 1): - _ = sess.run(train_op) + _ = self.evaluate(train_op) if i in time_step: ret = gfile.ListDirectory(time_dir) self.assertEqual(len(ret), 1) diff --git a/tensorflow/python/profiler/option_builder.py b/tensorflow/python/profiler/option_builder.py index 2ad7adf769..9d8f7683a6 100644 --- a/tensorflow/python/profiler/option_builder.py +++ b/tensorflow/python/profiler/option_builder.py @@ -23,7 +23,7 @@ from tensorflow.python.profiler import tfprof_logger from tensorflow.python.util.tf_export import tf_export -@tf_export('profiler.ProfileOptionBuilder') +@tf_export(v1=['profiler.ProfileOptionBuilder']) class ProfileOptionBuilder(object): # pylint: disable=line-too-long """Option Builder for Profiling API. diff --git a/tensorflow/python/profiler/pprof_profiler_test.py b/tensorflow/python/profiler/pprof_profiler_test.py index 11a3487360..120a0d0eaa 100644 --- a/tensorflow/python/profiler/pprof_profiler_test.py +++ b/tensorflow/python/profiler/pprof_profiler_test.py @@ -24,6 +24,7 @@ from proto import profile_pb2 from tensorflow.core.framework import step_stats_pb2 from tensorflow.core.protobuf import config_pb2 from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import math_ops from tensorflow.python.platform import test @@ -135,6 +136,7 @@ comment: 9 profile.ParseFromString(profile_contents) self.assertEquals(expected_proto, str(profile)) + @test_util.run_deprecated_v1 def testProfileWithWhileLoop(self): options = config_pb2.RunOptions() options.trace_level = config_pb2.RunOptions.FULL_TRACE diff --git a/tensorflow/python/profiler/profile_context_test.py b/tensorflow/python/profiler/profile_context_test.py index 107ad443c3..885f08ca4b 100644 --- a/tensorflow/python/profiler/profile_context_test.py +++ b/tensorflow/python/profiler/profile_context_test.py @@ -21,6 +21,7 @@ import os from tensorflow.python.client import session from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import variables from tensorflow.python.platform import gfile from tensorflow.python.platform import test @@ -35,6 +36,7 @@ builder = option_builder.ProfileOptionBuilder class ProfilerContextTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasics(self): ops.reset_default_graph() outfile = os.path.join(test.get_temp_dir(), "dump") @@ -48,10 +50,10 @@ class ProfilerContextTest(test.TestCase): with profile_context.ProfileContext(test.get_temp_dir()) as pctx: pctx.add_auto_profiling("op", options=opts, profile_steps=[15, 50, 100]) with session.Session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) total_steps = 101 for i in range(total_steps): - sess.run(x) + self.evaluate(x) if i == 14 or i == 49: self.assertTrue(gfile.Exists(outfile)) gfile.Remove(outfile) @@ -69,45 +71,47 @@ class ProfilerContextTest(test.TestCase): with gfile.Open(outfile, "r") as f: self.assertEqual(profile_str, f.read()) + @test_util.run_deprecated_v1 def testAutoTracingInDeubMode(self): ops.reset_default_graph() x = lib.BuildFullModel() with profile_context.ProfileContext(test.get_temp_dir(), debug=True): with session.Session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(10): - sess.run(x) + self.evaluate(x) for f in gfile.ListDirectory(test.get_temp_dir()): # Warm up, no tracing. self.assertFalse("run_meta" in f) - sess.run(x) + self.evaluate(x) self.assertTrue( gfile.Exists(os.path.join(test.get_temp_dir(), "run_meta_11"))) gfile.Remove(os.path.join(test.get_temp_dir(), "run_meta_11")) # fetched already. - sess.run(x) + self.evaluate(x) for f in gfile.ListDirectory(test.get_temp_dir()): self.assertFalse("run_meta" in f) + @test_util.run_deprecated_v1 def testDisabled(self): ops.reset_default_graph() x = lib.BuildFullModel() with profile_context.ProfileContext(test.get_temp_dir(), enabled=False) as pctx: with session.Session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(10): - sess.run(x) + self.evaluate(x) self.assertTrue(pctx.profiler is None) self.assertTrue( getattr(session.BaseSession, "profile_context", None) is None) with profile_context.ProfileContext(test.get_temp_dir()) as pctx: with session.Session() as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for _ in range(10): - sess.run(x) + self.evaluate(x) self.assertFalse(pctx.profiler is None) self.assertFalse( getattr(session.BaseSession, "profile_context", None) is None) diff --git a/tensorflow/python/profiler/profiler.py b/tensorflow/python/profiler/profiler.py index efbdd1ba68..5f62690b54 100644 --- a/tensorflow/python/profiler/profiler.py +++ b/tensorflow/python/profiler/profiler.py @@ -49,7 +49,7 @@ _allowed_symbols.extend([ ]) # Export protos -tf_export('profiler.GraphNodeProto')(GraphNodeProto) -tf_export('profiler.MultiGraphNodeProto')(MultiGraphNodeProto) -tf_export('profiler.AdviceProto')(AdviceProto) -tf_export('profiler.OpLogProto')(OpLogProto) +tf_export(v1=['profiler.GraphNodeProto'])(GraphNodeProto) +tf_export(v1=['profiler.MultiGraphNodeProto'])(MultiGraphNodeProto) +tf_export(v1=['profiler.AdviceProto'])(AdviceProto) +tf_export(v1=['profiler.OpLogProto'])(OpLogProto) diff --git a/tensorflow/python/profiler/profiler_test.py b/tensorflow/python/profiler/profiler_test.py index eacb7d21e6..e4f7361e5d 100644 --- a/tensorflow/python/profiler/profiler_test.py +++ b/tensorflow/python/profiler/profiler_test.py @@ -21,6 +21,7 @@ import os from tensorflow.core.protobuf import config_pb2 from tensorflow.python.client import session from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import variables from tensorflow.python.platform import gfile from tensorflow.python.platform import test @@ -35,6 +36,7 @@ builder = option_builder.ProfileOptionBuilder class ProfilerTest(test.TestCase): + @test_util.run_deprecated_v1 def testProfileBasic(self): ops.reset_default_graph() outfile = os.path.join(test.get_temp_dir(), 'dump') @@ -171,6 +173,7 @@ class ProfilerTest(test.TestCase): checker = advice_pb.checkers['ExpensiveOperationChecker'] self.assertGreater(len(checker.reports), 0) + @test_util.run_deprecated_v1 def testMultipleProfilePerStep(self): ops.reset_default_graph() opts = (builder(builder.trainable_variables_parameter()) diff --git a/tensorflow/python/profiler/tfprof_logger.py b/tensorflow/python/profiler/tfprof_logger.py index e651de32ea..6ccd0e0ff3 100644 --- a/tensorflow/python/profiler/tfprof_logger.py +++ b/tensorflow/python/profiler/tfprof_logger.py @@ -188,7 +188,7 @@ def merge_default_with_oplog(graph, op_log=None, run_meta=None, return tmp_op_log -@tf_export('profiler.write_op_log') +@tf_export(v1=['profiler.write_op_log']) def write_op_log(graph, log_dir, op_log=None, run_meta=None, add_trace=True): """Log provided 'op_log', and add additional model information below. diff --git a/tensorflow/python/saved_model/BUILD b/tensorflow/python/saved_model/BUILD index e7a3b8afd5..53d0640542 100644 --- a/tensorflow/python/saved_model/BUILD +++ b/tensorflow/python/saved_model/BUILD @@ -12,6 +12,8 @@ licenses(["notice"]) # Apache 2.0 exports_files(["LICENSE"]) load("//tensorflow:tensorflow.bzl", "py_test") +load("//tensorflow/core:platform/default/build_config.bzl", "tf_proto_library") +load("//tensorflow/core:platform/default/build_config.bzl", "tf_additional_all_protos") py_library( name = "saved_model", @@ -21,6 +23,7 @@ py_library( deps = [ ":builder", ":constants", + ":load", ":loader", ":main_op", ":save", @@ -83,12 +86,13 @@ py_library( srcs_version = "PY2AND3", deps = [ ":constants", + ":signature_def_utils", ":utils", "//tensorflow/core:protos_all_py", "//tensorflow/python:framework_for_generated_wrappers", "//tensorflow/python:lib", "//tensorflow/python:platform", - "//tensorflow/python:training", + "//tensorflow/python:saver", "//tensorflow/python:util", "//tensorflow/python:variables", ], @@ -114,6 +118,7 @@ py_test( "//tensorflow/python:state_ops", "//tensorflow/python:training", "//tensorflow/python:variables", + "@absl_py//absl/testing:parameterized", ], ) @@ -166,14 +171,15 @@ py_test( ":signature_def_utils", ":tag_constants", "//tensorflow/core:protos_all_py", - "//tensorflow/python:client", "//tensorflow/python:client_testlib", "//tensorflow/python:control_flow_ops", "//tensorflow/python:errors", "//tensorflow/python:framework_for_generated_wrappers", + "//tensorflow/python:framework_test_lib", "//tensorflow/python:lib", "//tensorflow/python:math_ops", "//tensorflow/python:saver_test_utils", + "//tensorflow/python:session", "//tensorflow/python:state_ops", "//tensorflow/python:test_ops", "//tensorflow/python:training", @@ -264,6 +270,14 @@ py_test( ], ) +tf_proto_library( + name = "saved_object_graph", + srcs = ["saved_object_graph.proto"], + cc_api_version = 2, + protodeps = tf_additional_all_protos(), + visibility = ["//tensorflow:internal"], +) + py_library( name = "save", srcs = [ @@ -271,16 +285,26 @@ py_library( ], srcs_version = "PY2AND3", deps = [ + ":builder", + ":constants", ":loader", + ":saved_object_graph_py", ":signature_constants", ":signature_def_utils", + ":tag_constants", ":utils", "//tensorflow/core:protos_all_py", "//tensorflow/python:array_ops", + "//tensorflow/python:framework", "//tensorflow/python:framework_ops", + "//tensorflow/python:lib", + "//tensorflow/python:resource_variable_ops", "//tensorflow/python:util", + "//tensorflow/python/eager:context", "//tensorflow/python/eager:def_function", - "//tensorflow/python/eager:test", + "//tensorflow/python/eager:function", + "//tensorflow/python/training/checkpointable:base", + "//tensorflow/python/training/checkpointable:util", ], ) @@ -289,13 +313,42 @@ py_test( srcs = ["save_test.py"], srcs_version = "PY2AND3", deps = [ + ":loader", ":save", ":signature_constants", ":tag_constants", "//tensorflow/python/eager:def_function", + "//tensorflow/python/eager:test", "@absl_py//absl/testing:parameterized", ], ) -# ----------------------------------------------------------------------------- -# Google-internal targets. These must be at the end for syncrepo. +py_library( + name = "load", + srcs = [ + "load.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":loader", + ":saved_object_graph_py", + "//tensorflow/python:lib", + "//tensorflow/python:util", + "//tensorflow/python/training/checkpointable:tracking", + ], +) + +py_test( + name = "load_test", + srcs = ["load_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":load", + ":save", + "//tensorflow/python:dtypes", + "//tensorflow/python:tensor_spec", + "//tensorflow/python/eager:def_function", + "//tensorflow/python/eager:test", + "//tensorflow/python/training/checkpointable:tracking", + ], +) diff --git a/tensorflow/python/saved_model/builder.py b/tensorflow/python/saved_model/builder.py index be49c70c60..b929934eeb 100644 --- a/tensorflow/python/saved_model/builder.py +++ b/tensorflow/python/saved_model/builder.py @@ -24,5 +24,6 @@ from __future__ import division from __future__ import print_function # pylint: disable=unused-import +from tensorflow.python.saved_model.builder_impl import _SavedModelBuilder from tensorflow.python.saved_model.builder_impl import SavedModelBuilder # pylint: enable=unused-import diff --git a/tensorflow/python/saved_model/builder_impl.py b/tensorflow/python/saved_model/builder_impl.py index 4f68f7c5ae..f37d283a2a 100644 --- a/tensorflow/python/saved_model/builder_impl.py +++ b/tensorflow/python/saved_model/builder_impl.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import functools import os from google.protobuf.any_pb2 import Any @@ -32,6 +33,7 @@ from tensorflow.python.lib.io import file_io from tensorflow.python.ops import variables from tensorflow.python.platform import tf_logging from tensorflow.python.saved_model import constants +from tensorflow.python.saved_model import signature_def_utils from tensorflow.python.saved_model import utils_impl as saved_model_utils from tensorflow.python.training import saver as tf_saver from tensorflow.python.util import compat @@ -39,8 +41,9 @@ from tensorflow.python.util.deprecation import deprecated_args from tensorflow.python.util.tf_export import tf_export -@tf_export(v1=["saved_model.Builder", "saved_model.builder.SavedModelBuilder"]) -class SavedModelBuilder(object): +# Base class for the SavedModelBuilder that is only used by Tensorflow +# internally. Please use tf.compat.v1.saved_model.SavedModelBuilder instead. +class _SavedModelBuilder(object): """Builds the `SavedModel` protocol buffer and saves variables and assets. The `SavedModelBuilder` class provides functionality to build a `SavedModel` @@ -68,7 +71,7 @@ class SavedModelBuilder(object): builder.add_meta_graph_and_variables(sess, ["foo-tag"], signature_def_map=foo_signatures, - assets_collection=foo_assets) + assets_list=foo_assets) ... with tf.Session(graph=tf.Graph()) as sess: @@ -105,82 +108,24 @@ class SavedModelBuilder(object): # weights. self._has_saved_variables = False - def _save_and_write_assets(self, assets_collection_to_add=None): + def _save_and_write_assets(self, meta_graph_def, assets_list=None): """Saves asset to the meta graph and writes asset files to disk. Args: - assets_collection_to_add: The collection where the asset paths are setup. + meta_graph_def: The meta graph def to which the assets will be added. + assets_list: The list where the asset paths are setup. """ - asset_filename_map = _maybe_save_assets(assets_collection_to_add) + # Creates a function that adds assets into the meta graph def. + write_fn = functools.partial(_add_asset_to_metagraph, meta_graph_def) + asset_filename_map = _maybe_save_assets(write_fn, assets_list) # Return if there are no assets to write. if not asset_filename_map: tf_logging.info("No assets to write.") return - assets_destination_dir = saved_model_utils.get_or_create_assets_dir( - self._export_dir) - - # Copy each asset from source path to destination path. - for asset_basename, asset_source_filepath in asset_filename_map.items(): - asset_destination_filepath = os.path.join( - compat.as_bytes(assets_destination_dir), - compat.as_bytes(asset_basename)) - - # Only copy the asset file to the destination if it does not already - # exist. This is to ensure that an asset with the same name defined as - # part of multiple graphs is only copied the first time. - if not file_io.file_exists(asset_destination_filepath): - file_io.copy(asset_source_filepath, asset_destination_filepath) - - tf_logging.info("Assets written to: %s", - compat.as_text(assets_destination_dir)) - - def _maybe_add_main_op(self, main_op): - """Adds main op to the SavedModel. - - Args: - main_op: Main op to run as part of graph initialization. If None, no - main op will be added to the graph. - - Raises: - TypeError: if main op is provided but is not of type `Operation`. - ValueError: if the Graph already contains an init op. - """ - if main_op is None: - return - - if not isinstance(main_op, ops.Operation): - raise TypeError("main_op needs to be an Operation: %r" % main_op) - - # Validate that no other init ops have been added to this graph already. - # We check main_op and legacy_init_op for thoroughness and explicitness. - for init_op_key in (constants.MAIN_OP_KEY, constants.LEGACY_INIT_OP_KEY): - if ops.get_collection(init_op_key): - raise ValueError( - "Graph already contains one or more main ops under the " - "collection {}.".format(init_op_key)) - - ops.add_to_collection(constants.MAIN_OP_KEY, main_op) - - def _add_train_op(self, train_op): - """Add train op to the SavedModel. - - Note that this functionality is in development, and liable to be - moved elsewhere. - - Args: - train_op: Op or group of ops that are used for training. These are - stored as a collection with key TRAIN_OP_KEY, but not executed. - - Raises: - TypeError if Train op is not of type `Operation`. - """ - if train_op is not None: - if (not isinstance(train_op, ops.Tensor) and - not isinstance(train_op, ops.Operation)): - raise TypeError("train_op needs to be a Tensor or Op: %r" % train_op) - ops.add_to_collection(constants.TRAIN_OP_KEY, train_op) + # Copy assets from source path to destination path. + copy_assets_to_destination_dir(asset_filename_map, self._export_dir) def _tag_and_add_meta_graph(self, meta_graph_def, tags, signature_def_map): """Tags the meta graph def and adds it to the SavedModel. @@ -237,30 +182,32 @@ class SavedModelBuilder(object): Validation of entries in the signature def map includes ensuring that the `name` and `dtype` fields of the TensorInfo protos of the `inputs` and - `outputs` of each `SignatureDef` are populated. + `outputs` of each `SignatureDef` are populated. Also ensures that reserved + SigantureDef keys for the initialization and train ops are not used. Args: signature_def_map: The map of signature defs to be validated. - """ - if signature_def_map is not None: - for signature_def_key in signature_def_map: - signature_def = signature_def_map[signature_def_key] - inputs = signature_def.inputs - outputs = signature_def.outputs - for inputs_key in inputs: - self._validate_tensor_info(inputs[inputs_key]) - for outputs_key in outputs: - self._validate_tensor_info(outputs[outputs_key]) - - def _add_collections( - self, assets_collection, main_op, train_op): - """Add asset and op collections to be saved.""" - # Save asset files and write them to disk, if any. - self._save_and_write_assets(assets_collection) - self._maybe_add_main_op(main_op) - - self._add_train_op(train_op) + Raises: + AssertionError: If a TensorInfo is not valid. + KeyError: If a reserved signature key is used in the map. + """ + for signature_def_key in signature_def_map: + signature_def = signature_def_map[signature_def_key] + inputs = signature_def.inputs + outputs = signature_def.outputs + for inputs_key in inputs: + self._validate_tensor_info(inputs[inputs_key]) + for outputs_key in outputs: + self._validate_tensor_info(outputs[outputs_key]) + if constants.INIT_OP_SIGNATURE_KEY in signature_def_map: + raise KeyError( + "SignatureDef map key \"{}\" is reserved for initialization. Please " + "use a different key.".format(constants.INIT_OP_SIGNATURE_KEY)) + if constants.TRAIN_OP_SIGNATURE_KEY in signature_def_map: + raise KeyError( + "SignatureDef map key \"{}\" is reserved for the train op. Please " + "use a different key.".format(constants.TRAIN_OP_SIGNATURE_KEY)) def _maybe_create_saver(self, saver=None): """Creates a sharded saver if one does not already exist.""" @@ -274,19 +221,14 @@ class SavedModelBuilder(object): allow_empty=True) return saver - @deprecated_args(None, - "Pass your op to the equivalent parameter main_op instead.", - "legacy_init_op") def add_meta_graph(self, tags, signature_def_map=None, - assets_collection=None, - legacy_init_op=None, + assets_list=None, clear_devices=False, - main_op=None, - strip_default_attrs=False, + init_op=None, + train_op=None, saver=None): - # pylint: disable=line-too-long """Adds the current meta graph to the SavedModel. Creates a Saver in the current scope and uses the Saver to export the meta @@ -297,19 +239,17 @@ class SavedModelBuilder(object): tags: The set of tags to annotate the meta graph def with. signature_def_map: The map of signature defs to be added to the meta graph def. - assets_collection: Assets collection to be saved with SavedModel. Note - that this collection should be a subset of the assets saved as part of + assets_list: Assets to be saved with SavedModel. Note + that this list should be a subset of the assets saved as part of the first meta graph in the SavedModel. - legacy_init_op: Legacy support for op or group of ops to execute after the - restore op upon a load. Deprecated; please use main_op instead. clear_devices: Set to true if the device info on the default graph should be cleared. - main_op: Op or group of ops to execute when the graph is loaded. Note - that when the main_op is specified it is run after the restore op at + init_op: Op or group of ops to execute when the graph is loaded. Note + that when the init_op is specified it is run after the restore op at load-time. - strip_default_attrs: Boolean. If `True`, default-valued attributes will be - removed from the NodeDefs. For a detailed guide, see - [Stripping Default-Valued Attributes](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/saved_model/README.md#stripping-default-valued-attributes). + train_op: Op or group of opts that trains the model when run. This will + not be run automatically when the graph is loaded, instead saved in + a SignatureDef accessible through the exported MetaGraph. saver: An instance of tf.train.Saver that will be used to export the metagraph. If None, a sharded Saver that restores all variables will be used. @@ -318,7 +258,6 @@ class SavedModelBuilder(object): AssertionError: If the variables for the SavedModel have not been saved yet, or if the graph already contains one or more legacy init ops. """ - # pylint: enable=line-too-long if not self._has_saved_variables: raise AssertionError( "Graph state including variables and assets has not been saved yet. " @@ -326,14 +265,15 @@ class SavedModelBuilder(object): # Validate the signature def map to ensure all included TensorInfos are # properly populated. + signature_def_map = signature_def_map or {} self._validate_signature_def_map(signature_def_map) - # legacy_init_op is deprecated, and going away in TF 2.0. - # Re-mapping to main_op, as treatment is identical regardless. - main_op = main_op or legacy_init_op - - # Add assets and ops - self._add_collections(assets_collection, main_op, None) + # Create a SignatureDef pointing to the graph initialization op, which will + # be added to the MetaGraphDef. + _add_op_to_signature_def_map(signature_def_map, init_op, + constants.INIT_OP_SIGNATURE_KEY) + _add_op_to_signature_def_map(signature_def_map, train_op, + constants.TRAIN_OP_SIGNATURE_KEY) saver = self._maybe_create_saver(saver) @@ -345,22 +285,22 @@ class SavedModelBuilder(object): # resolved, we just leave the option set to False for now. # TODO(soergel): Reinstate clear_extraneous_savers=True when possible. meta_graph_def = saver.export_meta_graph( - clear_devices=clear_devices, strip_default_attrs=strip_default_attrs) + clear_devices=clear_devices, strip_default_attrs=True) + + # Save asset files and write them to disk, if any. + self._save_and_write_assets(meta_graph_def, assets_list) # Tag the meta graph def and add it to the SavedModel. self._tag_and_add_meta_graph(meta_graph_def, tags, signature_def_map) - @deprecated_args(None, - "Pass your op to the equivalent parameter main_op instead.", - "legacy_init_op") def add_meta_graph_and_variables(self, sess, tags, signature_def_map=None, - assets_collection=None, - legacy_init_op=None, + assets_list=None, clear_devices=False, - main_op=None, + init_op=None, + train_op=None, strip_default_attrs=False, saver=None): # pylint: disable=line-too-long @@ -378,14 +318,15 @@ class SavedModelBuilder(object): tags: The set of tags with which to save the meta graph. signature_def_map: The map of signature def map to add to the meta graph def. - assets_collection: Assets collection to be saved with SavedModel. - legacy_init_op: Legacy support for op or group of ops to execute after the - restore op upon a load. Deprecated; please use main_op instead. + assets_list: Assets to be saved with SavedModel. clear_devices: Set to true if the device info on the default graph should be cleared. - main_op: Op or group of ops to execute when the graph is loaded. Note - that when the main_op is specified it is run after the restore op at + init_op: Op or group of ops to execute when the graph is loaded. Note + that when the init_op is specified it is run after the restore op at load-time. + train_op: Op or group of ops that trains the model when run. This will + not be run automatically when the graph is loaded, instead saved in + a SignatureDef accessible through the exported MetaGraph. strip_default_attrs: Boolean. If `True`, default-valued attributes will be removed from the NodeDefs. For a detailed guide, see [Stripping Default-Valued Attributes](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/saved_model/README.md#stripping-default-valued-attributes). @@ -402,14 +343,15 @@ class SavedModelBuilder(object): # Validate the signature def map to ensure all included TensorInfos are # properly populated. + signature_def_map = signature_def_map or {} self._validate_signature_def_map(signature_def_map) - # legacy_init_op is deprecated, and going away in TF 2.0. - # Re-mapping to main_op, as treatment is identical regardless. - main_op = main_op or legacy_init_op - - # Add assets and ops - self._add_collections(assets_collection, main_op, None) + # Create a SignatureDef pointing to the graph initialization op, which will + # be added to the MetaGraphDef. + _add_op_to_signature_def_map(signature_def_map, init_op, + constants.INIT_OP_SIGNATURE_KEY) + _add_op_to_signature_def_map(signature_def_map, train_op, + constants.TRAIN_OP_SIGNATURE_KEY) saved_model_utils.get_or_create_variables_dir(self._export_dir) variables_path = saved_model_utils.get_variables_path(self._export_dir) @@ -434,6 +376,9 @@ class SavedModelBuilder(object): meta_graph_def = saver.export_meta_graph( clear_devices=clear_devices, strip_default_attrs=strip_default_attrs) + # Save asset files and write them to disk, if any. + self._save_and_write_assets(meta_graph_def, assets_list) + # Tag the meta graph def and add it to the SavedModel. self._tag_and_add_meta_graph(meta_graph_def, tags, signature_def_map) @@ -471,11 +416,205 @@ class SavedModelBuilder(object): return path -def _maybe_save_assets(assets_collection_to_add=None): +@tf_export(v1=["saved_model.Builder", "saved_model.builder.SavedModelBuilder"]) # pylint: disable=missing-docstring +class SavedModelBuilder(_SavedModelBuilder): + __doc__ = _SavedModelBuilder.__doc__.replace("assets_list", + "assets_collection") + + def __init__(self, export_dir): + super(SavedModelBuilder, self).__init__(export_dir=export_dir) + + def _add_collections(self, assets_collection, main_op, train_op): + """Add asset and op collections to be saved.""" + # Save asset files and write them to disk, if any. + self._save_and_write_assets(assets_collection) + + self._maybe_add_main_op(main_op) + + self._add_train_op(train_op) + + def _save_and_write_assets(self, assets_collection_to_add=None): + """Saves asset to the meta graph and writes asset files to disk. + + Args: + assets_collection_to_add: The collection where the asset paths are setup. + """ + # Add assets to the collection with key `constants.ASSETS_KEY`, in the + # graph. + asset_filename_map = _maybe_save_assets(_add_asset_to_collection, + assets_collection_to_add) + + # Return if there are no assets to write. + if not asset_filename_map: + tf_logging.info("No assets to write.") + return + + # Copy assets from source path to destination path. + copy_assets_to_destination_dir(asset_filename_map, self._export_dir) + + def _maybe_add_main_op(self, main_op): + """Adds main op to the SavedModel. + + Args: + main_op: Main op to run as part of graph initialization. If None, no main + op will be added to the graph. + + Raises: + TypeError: if main op is provided but is not of type `Operation`. + ValueError: if the Graph already contains an init op. + """ + if main_op is None: + return + + if not isinstance(main_op, ops.Operation): + raise TypeError("main_op needs to be an Operation: %r" % main_op) + + # Validate that no other init ops have been added to this graph already. + # We check main_op and legacy_init_op for thoroughness and explicitness. + for init_op_key in (constants.MAIN_OP_KEY, constants.LEGACY_INIT_OP_KEY): + if ops.get_collection(init_op_key): + raise ValueError( + "Graph already contains one or more main ops under the " + "collection {}.".format(init_op_key)) + + ops.add_to_collection(constants.MAIN_OP_KEY, main_op) + + def _add_train_op(self, train_op): + """Add train op to the SavedModel. + + Note that this functionality is in development, and liable to be + moved elsewhere. + + Args: + train_op: Op or group of ops that are used for training. These are stored + as a collection with key TRAIN_OP_KEY, but not executed. + + Raises: + TypeError if Train op is not of type `Operation`. + """ + if train_op is not None: + if (not isinstance(train_op, ops.Tensor) and + not isinstance(train_op, ops.Operation)): + raise TypeError("train_op needs to be a Tensor or Op: %r" % train_op) + ops.add_to_collection(constants.TRAIN_OP_KEY, train_op) + + @deprecated_args(None, + "Pass your op to the equivalent parameter main_op instead.", + "legacy_init_op") + def add_meta_graph(self, + tags, + signature_def_map=None, + assets_collection=None, + legacy_init_op=None, + clear_devices=False, + main_op=None, + strip_default_attrs=False, + saver=None): + if not self._has_saved_variables: + raise AssertionError( + "Graph state including variables and assets has not been saved yet. " + "Please invoke `add_meta_graph_and_variables()` first.") + + # Validate the signature def map to ensure all included TensorInfos are + # properly populated. + signature_def_map = signature_def_map or {} + self._validate_signature_def_map(signature_def_map) + + # legacy_init_op is deprecated, and going away in TF 2.0. + # Re-mapping to main_op, as treatment is identical regardless. + main_op = main_op or legacy_init_op + + # Add assets and ops + self._add_collections(assets_collection, main_op, None) + + saver = self._maybe_create_saver(saver) + + # The graph almost certainly previously contained at least one Saver, and + # possibly several (e.g. one for loading a pretrained embedding, and another + # for the model weights). Removing the preexisting ones was the + # motivation for the clear_extraneous_savers option, but it turns out that + # there are edge cases where that option breaks the graph. Until that is + # resolved, we just leave the option set to False for now. + # TODO(soergel): Reinstate clear_extraneous_savers=True when possible. + meta_graph_def = saver.export_meta_graph( + clear_devices=clear_devices, strip_default_attrs=strip_default_attrs) + + # Tag the meta graph def and add it to the SavedModel. + self._tag_and_add_meta_graph(meta_graph_def, tags, signature_def_map) + + @deprecated_args(None, + "Pass your op to the equivalent parameter main_op instead.", + "legacy_init_op") + def add_meta_graph_and_variables(self, + sess, + tags, + signature_def_map=None, + assets_collection=None, + legacy_init_op=None, + clear_devices=False, + main_op=None, + strip_default_attrs=False, + saver=None): + if self._has_saved_variables: + raise AssertionError("Graph state including variables and assets has " + "already been saved. Please invoke " + "`add_meta_graph()` instead.") + + # Validate the signature def map to ensure all included TensorInfos are + # properly populated. + signature_def_map = signature_def_map or {} + self._validate_signature_def_map(signature_def_map) + + # legacy_init_op is deprecated, and going away in TF 2.0. + # Re-mapping to main_op, as treatment is identical regardless. + main_op = main_op or legacy_init_op + + # Add assets and ops + self._add_collections(assets_collection, main_op, None) + + saved_model_utils.get_or_create_variables_dir(self._export_dir) + variables_path = saved_model_utils.get_variables_path(self._export_dir) + + saver = self._maybe_create_saver(saver) + + # Save the variables. Also, disable writing the checkpoint state proto. The + # file is not used during SavedModel loading. In addition, since a + # SavedModel can be copied or moved, this avoids the checkpoint state to + # become outdated. + saver.save(sess, variables_path, write_meta_graph=False, write_state=False) + + # Export the meta graph def. + + # The graph almost certainly previously contained at least one Saver, and + # possibly several (e.g. one for loading a pretrained embedding, and another + # for the model weights). Removing the preexisting ones was the + # motivation for the clear_extraneous_savers option, but it turns out that + # there are edge cases where that option breaks the graph. Until that is + # resolved, we just leave the option set to False for now. + # TODO(soergel): Reinstate clear_extraneous_savers=True when possible. + meta_graph_def = saver.export_meta_graph( + clear_devices=clear_devices, strip_default_attrs=strip_default_attrs) + + # Tag the meta graph def and add it to the SavedModel. + self._tag_and_add_meta_graph(meta_graph_def, tags, signature_def_map) + + # Mark this instance of SavedModel as having saved variables, such that + # subsequent attempts to save variables will fail. + self._has_saved_variables = True + + add_meta_graph.__doc__ = _SavedModelBuilder.add_meta_graph.__doc__.replace( + "assets_list", "assets_collection") + add_meta_graph_and_variables.__doc__ = \ + _SavedModelBuilder.add_meta_graph_and_variables.__doc__.replace( + "assets_list", "assets_collection") + + +def _maybe_save_assets(write_fn, assets_to_add=None): """Saves assets to the meta graph. Args: - assets_collection_to_add: The collection where the asset paths are setup. + write_fn: A function callback that writes asset into meta graph. + assets_to_add: The list where the asset paths are setup. Returns: A dict of asset basenames for saving to the original full path to the asset. @@ -486,25 +625,25 @@ def _maybe_save_assets(assets_collection_to_add=None): # Map of target file names to original filenames asset_filename_map = {} - if assets_collection_to_add is None: + if assets_to_add is None: tf_logging.info("No assets to save.") return asset_filename_map - # Iterate over the supplied asset collection, build the `AssetFile` proto - # and add them to the collection with key `constants.ASSETS_KEY`, in the - # graph. - for asset_tensor in assets_collection_to_add: + # Iterate over the supplied assets, build the `AssetFile` proto and add them + # to the meta graph. + for asset_tensor in assets_to_add: asset_source_filepath = _asset_path_from_tensor(asset_tensor) if not asset_source_filepath: raise ValueError("Invalid asset filepath tensor %s" % asset_tensor) - asset_filename = _get_asset_filename_to_add( + asset_filename = get_asset_filename_to_add( asset_source_filepath, asset_filename_map) - # Build `AssetFile` proto and add it to the asset collection in the graph. + # Call the passed-in function that builds AssetFileDef proto and adds it + # to either the collection or asset_file_def field of the meta graph. # Note that this should be done even when the file is a duplicate of an # already-added file, as the tensor reference should still exist. - _add_asset_to_collection(asset_filename, asset_tensor) + write_fn(asset_filename, asset_tensor) # In the cases where we are adding a duplicate, this will result in the # last of the filepaths being the one used for copying the file to the @@ -516,7 +655,7 @@ def _maybe_save_assets(assets_collection_to_add=None): return asset_filename_map -def _get_asset_filename_to_add(asset_filepath, asset_filename_map): +def get_asset_filename_to_add(asset_filepath, asset_filename_map): """Get a unique basename to add to the SavedModel if this file is unseen. Assets come from users as full paths, and we save them out to the @@ -542,7 +681,7 @@ def _get_asset_filename_to_add(asset_filepath, asset_filename_map): other_asset_filepath = asset_filename_map[asset_filename] if other_asset_filepath == asset_filepath: - # This is the same file, stored twice in the collection list. No need + # This is the same file, stored twice in the list. No need # to make unique. return asset_filename @@ -589,6 +728,41 @@ def _asset_path_from_tensor(path_tensor): return str_values[0] +def _add_asset_to_metagraph(meta_graph_def, asset_filename, asset_tensor): + """Builds an asset proto and adds it to the meta graph def. + + Args: + meta_graph_def: The meta graph def to which the asset will be added. + asset_filename: The filename of the asset to be added. + asset_tensor: The asset tensor used to populate the tensor info of the asset + proto. + """ + asset_proto = meta_graph_def.asset_file_def.add() + asset_proto.filename = asset_filename + asset_proto.tensor_info.name = asset_tensor.name + + +def copy_assets_to_destination_dir(asset_filename_map, destination_dir): + """Copy all assets from source path to destination path.""" + assets_destination_dir = saved_model_utils.get_or_create_assets_dir( + destination_dir) + + # Copy each asset from source path to destination path. + for asset_basename, asset_source_filepath in asset_filename_map.items(): + asset_destination_filepath = os.path.join( + compat.as_bytes(assets_destination_dir), + compat.as_bytes(asset_basename)) + + # Only copy the asset file to the destination if it does not already + # exist. This is to ensure that an asset with the same name defined as + # part of multiple graphs is only copied the first time. + if not file_io.file_exists(asset_destination_filepath): + file_io.copy(asset_source_filepath, asset_destination_filepath) + + tf_logging.info("Assets written to: %s", + compat.as_text(assets_destination_dir)) + + def _add_asset_to_collection(asset_filename, asset_tensor): """Builds an asset proto and adds it to the asset collection of the graph. @@ -604,3 +778,8 @@ def _add_asset_to_collection(asset_filename, asset_tensor): asset_any_proto = Any() asset_any_proto.Pack(asset_proto) ops.add_to_collection(constants.ASSETS_KEY, asset_any_proto) + + +def _add_op_to_signature_def_map(signature_def_map, op, key): + if op is not None: + signature_def_map[key] = signature_def_utils.op_signature_def(op, key) diff --git a/tensorflow/python/saved_model/constants.py b/tensorflow/python/saved_model/constants.py index 0addbdc968..90511a409e 100644 --- a/tensorflow/python/saved_model/constants.py +++ b/tensorflow/python/saved_model/constants.py @@ -29,6 +29,9 @@ tf_export( "saved_model.ASSETS_DIRECTORY", "saved_model.constants.ASSETS_DIRECTORY" ]).export_constant(__name__, "ASSETS_DIRECTORY") +# Subdirectory name containing unmanaged files from higher-level APIs. +EXTRA_ASSETS_DIRECTORY = "assets.extra" + # CollectionDef key containing SavedModel assets. ASSETS_KEY = "saved_model_assets" tf_export( @@ -40,7 +43,6 @@ tf_export( # CollectionDef key for the legacy init op. LEGACY_INIT_OP_KEY = "legacy_init_op" tf_export( - "saved_model.LEGACY_INIT_OP_KEY", v1=[ "saved_model.LEGACY_INIT_OP_KEY", "saved_model.constants.LEGACY_INIT_OP_KEY" @@ -49,13 +51,12 @@ tf_export( # CollectionDef key for the SavedModel main op. MAIN_OP_KEY = "saved_model_main_op" tf_export( - "saved_model.MAIN_OP_KEY", v1=["saved_model.MAIN_OP_KEY", "saved_model.constants.MAIN_OP_KEY"]).export_constant( __name__, "MAIN_OP_KEY") # CollectionDef key for the SavedModel train op. -# Not exported while export_all_saved_models is in contrib. +# Not exported while export_all_saved_models is experimental. TRAIN_OP_KEY = "saved_model_train_op" # Schema version for SavedModel. @@ -106,3 +107,8 @@ tf_export( "saved_model.VARIABLES_FILENAME", "saved_model.constants.VARIABLES_FILENAME" ]).export_constant(__name__, "VARIABLES_FILENAME") + +# The initialization and train ops for a MetaGraph are stored in the +# signature def map. The ops are added to the map with the following keys. +INIT_OP_SIGNATURE_KEY = "__saved_model_init_op" +TRAIN_OP_SIGNATURE_KEY = "__saved_model_train_op" diff --git a/tensorflow/python/saved_model/load.py b/tensorflow/python/saved_model/load.py new file mode 100644 index 0000000000..397086e106 --- /dev/null +++ b/tensorflow/python/saved_model/load.py @@ -0,0 +1,61 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Import a checkpointable object from a SavedModel.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os + +from tensorflow.python.lib.io import file_io +from tensorflow.python.saved_model import constants +from tensorflow.python.saved_model import saved_object_graph_pb2 +from tensorflow.python.training.checkpointable import tracking +from tensorflow.python.util import compat + + +def _recreate_object_graph(object_graph_proto): + """Recreates Python objects from an ObjectGraph proto.""" + objects = [] + for _ in object_graph_proto.nodes: + # TODO(allenl): re-create variables and other types + objects.append(tracking.Checkpointable()) + for obj, object_proto in zip(objects, object_graph_proto.nodes): + for reference in object_proto.children: + setattr(obj, reference.local_name, objects[reference.node_id]) + return objects[0] + + +def load(export_dir): + """Load a SavedModel from `export_dir`.""" + object_graph_filename = os.path.join( + compat.as_bytes(export_dir), + compat.as_bytes(constants.EXTRA_ASSETS_DIRECTORY), + compat.as_bytes("object_graph.pb")) + if file_io.file_exists(object_graph_filename): + # If there is an object graph associated with the SavedModel, we'll create a + # root object from that. + object_graph_string = file_io.FileIO(object_graph_filename, "rb").read() + object_graph_proto = ( + saved_object_graph_pb2.SavedObjectGraph()) + object_graph_proto.ParseFromString(object_graph_string) + root = _recreate_object_graph(object_graph_proto) + else: + raise NotImplementedError( + "Currently only SavedModels exported with `tf.saved_model.save` may be " + "imported. Other SavedModels may eventually be supported via load().") + # TODO(allenl): load functions from the SavedModel into the eager context + return root diff --git a/tensorflow/python/saved_model/load_test.py b/tensorflow/python/saved_model/load_test.py new file mode 100644 index 0000000000..bfa201ad63 --- /dev/null +++ b/tensorflow/python/saved_model/load_test.py @@ -0,0 +1,51 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for checkpointable object SavedModel loading.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import os + +from tensorflow.python.eager import def_function +from tensorflow.python.eager import test +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import tensor_spec +from tensorflow.python.saved_model import load +from tensorflow.python.saved_model import save +from tensorflow.python.training.checkpointable import tracking + + +class LoadTest(test.TestCase): + + def test_structure_import(self): + root = tracking.Checkpointable() + root.f = def_function.function( + lambda x: 2. * x, + input_signature=[tensor_spec.TensorSpec(None, dtypes.float32)]) + root.dep_one = tracking.Checkpointable() + root.dep_two = tracking.Checkpointable() + root.dep_two.dep = tracking.Checkpointable() + root.dep_three = root.dep_two.dep + save_dir = os.path.join(self.get_temp_dir(), "saved_model") + save.save(root, save_dir) + imported = load.load(save_dir) + self.assertIs(imported.dep_three, imported.dep_two.dep) + self.assertIsNot(imported.dep_one, imported.dep_two) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/saved_model/loader_impl.py b/tensorflow/python/saved_model/loader_impl.py index 8c8eaf038a..6bf39a2c67 100644 --- a/tensorflow/python/saved_model/loader_impl.py +++ b/tensorflow/python/saved_model/loader_impl.py @@ -31,6 +31,7 @@ from tensorflow.python.lib.io import file_io from tensorflow.python.ops import variables from tensorflow.python.platform import tf_logging from tensorflow.python.saved_model import constants +from tensorflow.python.saved_model import signature_def_utils from tensorflow.python.saved_model import utils_impl as saved_model_utils from tensorflow.python.training import saver as tf_saver from tensorflow.python.util import compat @@ -99,22 +100,29 @@ def _get_asset_tensors(export_dir, meta_graph_def_to_load, import_scope=None): collection_def = meta_graph_def_to_load.collection_def asset_tensor_dict = {} - if constants.ASSETS_KEY in collection_def: - # Location of the assets for SavedModel. - assets_directory = os.path.join( - compat.as_bytes(export_dir), - compat.as_bytes(constants.ASSETS_DIRECTORY)) + asset_protos = [] + + if meta_graph_def_to_load.asset_file_def: + asset_protos = meta_graph_def_to_load.asset_file_def + elif constants.ASSETS_KEY in collection_def: assets_any_proto = collection_def[constants.ASSETS_KEY].any_list.value - # Process each asset and add it to the asset tensor dictionary. for asset_any_proto in assets_any_proto: asset_proto = meta_graph_pb2.AssetFileDef() asset_any_proto.Unpack(asset_proto) - tensor_name = asset_proto.tensor_info.name - if import_scope: - tensor_name = "%s/%s" % (import_scope, tensor_name) - asset_tensor_dict[tensor_name] = os.path.join( - compat.as_bytes(assets_directory), - compat.as_bytes(asset_proto.filename)) + asset_protos.append(asset_proto) + + # Location of the assets for SavedModel. + assets_directory = os.path.join( + compat.as_bytes(export_dir), compat.as_bytes(constants.ASSETS_DIRECTORY)) + # Process each asset and add it to the asset tensor dictionary. + for asset_proto in asset_protos: + tensor_name = asset_proto.tensor_info.name + if import_scope: + tensor_name = "%s/%s" % (import_scope, tensor_name) + asset_tensor_dict[tensor_name] = os.path.join( + compat.as_bytes(assets_directory), + compat.as_bytes(asset_proto.filename)) + return asset_tensor_dict @@ -134,23 +142,53 @@ def _get_main_op_tensor( RuntimeError: If the collection def corresponding to the main op key has other than exactly one tensor. """ + # TODO(kathywu): Rename this method to _get_op_from_collection when + # dependency from SavedModelEstimator is removed. collection_def = meta_graph_def_to_load.collection_def - main_op_tensor = None + init_op = None if init_op_key in collection_def: - main_ops = collection_def[init_op_key].node_list.value - if len(main_ops) != 1: - raise RuntimeError("Expected exactly one SavedModel main op. " - "Found: {}".format(main_ops)) - main_op_tensor = ops.get_collection(init_op_key)[0] - return main_op_tensor + init_op_list = collection_def[init_op_key].node_list.value + if len(init_op_list) != 1: + raise RuntimeError("Expected exactly one SavedModel init op. " + "Found: {}".format(init_op_list)) + init_op = ops.get_collection(init_op_key)[0] + return init_op + + +def _get_op_from_collection(meta_graph_def, op_key): + return _get_main_op_tensor(meta_graph_def, op_key) + + +def _get_op_from_signature_def(meta_graph_def, op_signature_key, import_scope): + """Retrieve op stored in the imported meta graph's signature def.""" + if op_signature_key in meta_graph_def.signature_def: + return signature_def_utils.load_op_from_signature_def( + meta_graph_def.signature_def[op_signature_key], op_signature_key, + import_scope) + else: + return None -@tf_export( +def get_init_op(meta_graph_def, import_scope=None): + return (_get_op_from_signature_def( + meta_graph_def, constants.INIT_OP_SIGNATURE_KEY, import_scope) or + _get_op_from_collection(meta_graph_def, constants.MAIN_OP_KEY) or + _get_op_from_collection(meta_graph_def, constants.LEGACY_INIT_OP_KEY)) + + +def get_train_op(meta_graph_def, import_scope=None): + train_op = _get_op_from_signature_def( + meta_graph_def, constants.TRAIN_OP_SIGNATURE_KEY, import_scope) + if train_op is None: + train_op = _get_op_from_collection(meta_graph_def, constants.TRAIN_OP_KEY) + return train_op + + +@tf_export(v1=[ + "saved_model.contains_saved_model", "saved_model.maybe_saved_model_directory", - v1=[ - "saved_model.maybe_saved_model_directory", - "saved_model.loader.maybe_saved_model_directory" - ]) + "saved_model.loader.maybe_saved_model_directory" +]) @deprecation.deprecated_endpoints( "saved_model.loader.maybe_saved_model_directory") def maybe_saved_model_directory(export_dir): @@ -173,6 +211,25 @@ def maybe_saved_model_directory(export_dir): return file_io.file_exists(txt_path) or file_io.file_exists(pb_path) +@tf_export("saved_model.contains_saved_model", v1=[]) +def contains_saved_model(export_dir): + """Checks whether the provided export directory could contain a SavedModel. + + Note that the method does not load any data by itself. If the method returns + `false`, the export directory definitely does not contain a SavedModel. If the + method returns `true`, the export directory may contain a SavedModel but + provides no guarantee that it can be loaded. + + Args: + export_dir: Absolute string path to possible export location. For example, + '/my/foo/model'. + + Returns: + True if the export directory contains SavedModel files, False otherwise. + """ + return maybe_saved_model_directory(export_dir) + + @tf_export(v1=["saved_model.load", "saved_model.loader.load"]) @deprecation.deprecated( None, @@ -334,11 +391,9 @@ class SavedModelLoader(object): asset_tensors_dictionary = _get_asset_tensors( self._export_dir, meta_graph_def, import_scope=import_scope) - main_op_tensor = ( - _get_main_op_tensor(meta_graph_def, constants.MAIN_OP_KEY) or - _get_main_op_tensor(meta_graph_def, constants.LEGACY_INIT_OP_KEY)) - if main_op_tensor is not None: - sess.run(fetches=[main_op_tensor], feed_dict=asset_tensors_dictionary) + init_op = get_init_op(meta_graph_def, import_scope) + if init_op is not None: + sess.run(fetches=[init_op], feed_dict=asset_tensors_dictionary) def load(self, sess, tags, import_scope=None, **saver_kwargs): """Load the MetaGraphDef graph and restore variable values into the session. diff --git a/tensorflow/python/saved_model/loader_test.py b/tensorflow/python/saved_model/loader_test.py index 924b2e7c06..3b7f0b250e 100644 --- a/tensorflow/python/saved_model/loader_test.py +++ b/tensorflow/python/saved_model/loader_test.py @@ -19,11 +19,14 @@ from __future__ import division from __future__ import print_function import os +import shutil + +from absl.testing import parameterized from tensorflow.python.client import session from tensorflow.python.framework import errors from tensorflow.python.framework import ops -from tensorflow.python.lib.io import file_io +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import state_ops from tensorflow.python.ops import variables @@ -42,55 +45,74 @@ SIMPLE_ADD_SAVED_MODEL = _get_export_dir("simple_add_saved_model") SAVED_MODEL_WITH_MAIN_OP = _get_export_dir("saved_model_with_main_op") -class SavedModelLoaderTest(test.TestCase): - - def setUp(self): - """Write test SavedModels to a temp directory.""" - with session.Session(graph=ops.Graph()) as sess: - x = variables.VariableV1(5, name="x") - y = variables.VariableV1(11, name="y") - z = x + y - sess.run(variables.global_variables_initializer()) - - foo_sig_def = signature_def_utils.build_signature_def( - {"foo_input": utils.build_tensor_info(x)}, - {"foo_output": utils.build_tensor_info(z)}) - bar_sig_def = signature_def_utils.build_signature_def( - {"bar_x": utils.build_tensor_info(x), - "bar_y": utils.build_tensor_info(y)}, - {"bar_z": utils.build_tensor_info(z)}) - - builder = saved_model_builder.SavedModelBuilder(SIMPLE_ADD_SAVED_MODEL) - builder.add_meta_graph_and_variables( - sess, ["foo_graph"], {"foo": foo_sig_def, "bar": bar_sig_def}) +def build_graph_helper(): + g = ops.Graph() + with g.as_default(): + x = variables.VariableV1(5, name="x") + y = variables.VariableV1(11, name="y") + z = x + y + + foo_sig_def = signature_def_utils.build_signature_def({ + "foo_input": utils.build_tensor_info(x) + }, {"foo_output": utils.build_tensor_info(z)}) + bar_sig_def = signature_def_utils.build_signature_def({ + "bar_x": utils.build_tensor_info(x), + "bar_y": utils.build_tensor_info(y) + }, {"bar_z": utils.build_tensor_info(z)}) + return g, {"foo": foo_sig_def, "bar": bar_sig_def}, y + + +@parameterized.parameters((saved_model_builder.SavedModelBuilder,), + (saved_model_builder._SavedModelBuilder,)) +class SavedModelLoaderTest(test.TestCase, parameterized.TestCase): + + def export_simple_graph(self, builder_cls): + g, sig_def_map, _ = build_graph_helper() + with session.Session(graph=g) as sess: + self.evaluate(variables.global_variables_initializer()) + builder = builder_cls(SIMPLE_ADD_SAVED_MODEL) + builder.add_meta_graph_and_variables(sess, ["foo_graph"], sig_def_map) builder.save() - # Write SavedModel with a main_op + def export_graph_with_main_op(self, builder_cls): + g, sig_def_map, y = build_graph_helper() + with session.Session(graph=g) as sess: + self.evaluate(variables.global_variables_initializer()) assign_op = control_flow_ops.group(state_ops.assign(y, 7)) - builder = saved_model_builder.SavedModelBuilder(SAVED_MODEL_WITH_MAIN_OP) - builder.add_meta_graph_and_variables( - sess, ["foo_graph"], {"foo": foo_sig_def, "bar": bar_sig_def}, - main_op=assign_op) + builder = builder_cls(SAVED_MODEL_WITH_MAIN_OP) + + if builder_cls == saved_model_builder._SavedModelBuilder: + builder.add_meta_graph_and_variables( + sess, ["foo_graph"], sig_def_map, init_op=assign_op) + else: + builder.add_meta_graph_and_variables( + sess, ["foo_graph"], sig_def_map, main_op=assign_op) builder.save() def tearDown(self): - file_io.delete_recursively(test.get_temp_dir()) + super(SavedModelLoaderTest, self).tearDown() + shutil.rmtree(test.get_temp_dir(), ignore_errors=True) - def test_load_function(self): + @test_util.run_deprecated_v1 + def test_load_function(self, builder_cls): + self.export_simple_graph(builder_cls) loader = loader_impl.SavedModelLoader(SIMPLE_ADD_SAVED_MODEL) with self.session(graph=ops.Graph()) as sess: loader.load(sess, ["foo_graph"]) self.assertEqual(5, sess.graph.get_tensor_by_name("x:0").eval()) self.assertEqual(11, sess.graph.get_tensor_by_name("y:0").eval()) + self.export_graph_with_main_op(builder_cls) loader2 = loader_impl.SavedModelLoader(SAVED_MODEL_WITH_MAIN_OP) with self.session(graph=ops.Graph()) as sess: loader2.load(sess, ["foo_graph"]) self.assertEqual(5, sess.graph.get_tensor_by_name("x:0").eval()) self.assertEqual(7, sess.graph.get_tensor_by_name("y:0").eval()) - def test_load_graph(self): + @test_util.run_deprecated_v1 + def test_load_graph(self, builder_cls): + self.export_simple_graph(builder_cls) loader = loader_impl.SavedModelLoader(SIMPLE_ADD_SAVED_MODEL) graph = ops.Graph() loader.load_graph(graph, ["foo_graph"]) @@ -101,14 +123,16 @@ class SavedModelLoaderTest(test.TestCase): with self.assertRaises(KeyError): graph.get_tensor_by_name("z:0") - with self.session(graph=graph) as sess: + with self.session(graph=graph): # Check that x and y are not initialized with self.assertRaises(errors.FailedPreconditionError): - sess.run(x) + self.evaluate(x) with self.assertRaises(errors.FailedPreconditionError): - sess.run(y) + self.evaluate(y) - def test_load_with_import_scope(self): + @test_util.run_deprecated_v1 + def test_load_with_import_scope(self, builder_cls): + self.export_graph_with_main_op(builder_cls) loader = loader_impl.SavedModelLoader(SAVED_MODEL_WITH_MAIN_OP) with self.session(graph=ops.Graph()) as sess: saver, _ = loader.load_graph( @@ -119,7 +143,13 @@ class SavedModelLoaderTest(test.TestCase): loader.restore_variables(sess, tf_saver.Saver()) loader.restore_variables(sess, saver) - loader.run_init_ops(sess, ["foo_graph"]) + + if builder_cls == saved_model_builder._SavedModelBuilder: + with self.assertRaises(errors.NotFoundError): + loader.run_init_ops(sess, ["foo_graph"]) + loader.run_init_ops(sess, ["foo_graph"], import_scope="baz") + else: + loader.run_init_ops(sess, ["foo_graph"]) self.assertEqual(5, sess.graph.get_tensor_by_name("baz/x:0").eval()) self.assertEqual(7, sess.graph.get_tensor_by_name("baz/y:0").eval()) @@ -131,23 +161,27 @@ class SavedModelLoaderTest(test.TestCase): self.assertEqual(5, sess.graph.get_tensor_by_name("baa/x:0").eval()) self.assertEqual(7, sess.graph.get_tensor_by_name("baa/y:0").eval()) - def test_restore_variables(self): + @test_util.run_deprecated_v1 + def test_restore_variables(self, builder_cls): + self.export_graph_with_main_op(builder_cls) loader = loader_impl.SavedModelLoader(SAVED_MODEL_WITH_MAIN_OP) with self.session(graph=ops.Graph()) as sess: x = variables.VariableV1(0, name="x") y = variables.VariableV1(0, name="y") z = x * y - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # There are variables to restore, so a saver must be created. with self.assertRaises(ValueError): loader.restore_variables(sess, None) loader.restore_variables(sess, tf_saver.Saver()) - self.assertEqual(55, z.eval()) + self.assertEqual(55, self.evaluate(z)) - def test_run_init_op(self): + @test_util.run_deprecated_v1 + def test_run_init_op(self, builder_cls): + self.export_graph_with_main_op(builder_cls) loader = loader_impl.SavedModelLoader(SAVED_MODEL_WITH_MAIN_OP) graph = ops.Graph() saver, _ = loader.load_graph(graph, ["foo_graph"]) @@ -160,14 +194,16 @@ class SavedModelLoaderTest(test.TestCase): self.assertEqual(5, sess.graph.get_tensor_by_name("x:0").eval()) self.assertEqual(7, sess.graph.get_tensor_by_name("y:0").eval()) - def test_parse_saved_model(self): + def test_parse_saved_model(self, builder_cls): + self.export_simple_graph(builder_cls) loader = loader_impl.SavedModelLoader(SIMPLE_ADD_SAVED_MODEL) meta_graph = loader.get_meta_graph_def_from_tags(["foo_graph"]) self.assertIsNotNone(meta_graph) self.assertIn("foo", meta_graph.signature_def) self.assertIn("bar", meta_graph.signature_def) - def test_load_invalid_meta_graph(self): + def test_load_invalid_meta_graph(self, builder_cls): + self.export_simple_graph(builder_cls) loader = loader_impl.SavedModelLoader(SIMPLE_ADD_SAVED_MODEL) with self.assertRaises(RuntimeError): loader.get_meta_graph_def_from_tags([]) @@ -176,13 +212,17 @@ class SavedModelLoaderTest(test.TestCase): with self.assertRaises(RuntimeError): loader.get_meta_graph_def_from_tags(["not_a_graph"]) - def test_load_saved_model_with_no_variables(self): + @test_util.run_deprecated_v1 + def test_load_saved_model_with_no_variables(self, builder_cls): """Test that SavedModel runs saver when there appear to be no variables. When no variables are detected, this may mean that the variables were saved to different collections, or the collections weren't saved to the SavedModel. If the SavedModel MetaGraphDef contains a saver, it should still run in either of these cases. + + Args: + builder_cls: SavedModelBuilder or _SavedModelBuilder class """ path = _get_export_dir("no_variable_saved_model") with session.Session(graph=ops.Graph()) as sess: @@ -192,7 +232,7 @@ class SavedModelLoaderTest(test.TestCase): 11, name="y", collections=["not_global_variable"]) self.assertFalse(variables._all_saveable_objects()) z = x + y - sess.run(variables.variables_initializer([x, y])) + self.evaluate(variables.variables_initializer([x, y])) foo_sig_def = signature_def_utils.build_signature_def( {"foo_input": utils.build_tensor_info(x)}, @@ -215,8 +255,9 @@ class SavedModelLoaderTest(test.TestCase): self.assertEqual(5, sess.graph.get_tensor_by_name("x:0").eval()) self.assertEqual(11, sess.graph.get_tensor_by_name("y:0").eval()) - def test_load_saved_model_graph_with_return_elements(self): + def test_load_saved_model_graph_with_return_elements(self, builder_cls): """Ensure that the correct elements are returned.""" + self.export_simple_graph(builder_cls) loader = loader_impl.SavedModelLoader(SIMPLE_ADD_SAVED_MODEL) graph = ops.Graph() _, ret = loader.load_graph(graph, ["foo_graph"], @@ -228,5 +269,6 @@ class SavedModelLoaderTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "not found in graph"): loader.load_graph(graph, ["foo_graph"], return_elements=["z:0"]) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/saved_model/save.py b/tensorflow/python/saved_model/save.py index 63575f631e..a66e19b199 100644 --- a/tensorflow/python/saved_model/save.py +++ b/tensorflow/python/saved_model/save.py @@ -19,39 +19,82 @@ from __future__ import division from __future__ import print_function import collections +import functools import os +from tensorflow.core.protobuf import meta_graph_pb2 from tensorflow.core.protobuf import saved_model_pb2 from tensorflow.python.eager import context from tensorflow.python.eager import def_function -from tensorflow.python.eager import function +from tensorflow.python.eager import function as defun +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes from tensorflow.python.framework import meta_graph from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_spec from tensorflow.python.lib.io import file_io from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import resource_variable_ops +from tensorflow.python.saved_model import builder_impl from tensorflow.python.saved_model import constants +from tensorflow.python.saved_model import saved_object_graph_pb2 from tensorflow.python.saved_model import signature_constants from tensorflow.python.saved_model import signature_def_utils +from tensorflow.python.saved_model import tag_constants from tensorflow.python.saved_model import utils_impl from tensorflow.python.training.checkpointable import base +from tensorflow.python.training.checkpointable import tracking from tensorflow.python.training.checkpointable import util from tensorflow.python.util import compat from tensorflow.python.util import nest from tensorflow.python.util.tf_export import tf_export +def _check_for_functional_keras_model(root): + """Makes an export signature for `root` if it's a functional Keras Model.""" + # If nothing is decorated yet but this is a functional Keras Model (duck + # typed), we'll try to make a signature ourselves. + try: + inputs = root.inputs + input_names = root.input_names + except AttributeError: + return None + input_signature = [] + for input_tensor, input_name in zip(inputs, input_names): + input_signature.append(tensor_spec.TensorSpec( + shape=input_tensor.shape, dtype=input_tensor.dtype, + name=input_name)) + + @def_function.function(input_signature=input_signature) + def _wrapped_model(*args): + outputs_list = nest.flatten(root(inputs=list(args))) + return {name: output for name, output + in zip(root.output_names, outputs_list)} + return _wrapped_model + + def _find_function_to_export(root): """Iterate over `root`'s attributes, finding traced functions.""" - functions = [] - function_attribute_names = [] + exported_function = None + previous_attribute_name = None for attribute_name in dir(root): attribute_value = getattr(root, attribute_name, None) if isinstance(attribute_value, def_function.PolymorphicFunction): - functions.append(attribute_value) - function_attribute_names.append(attribute_name) - # TODO(allenl): Automatically infer signatures for Keras functional models? - if not functions: + if exported_function is not None: + raise ValueError( + ("Exporting an object with no " + "tf.saved_model.save(..., signatures=...) " + "argument specified, and with more than one " + "@tf.function-decorated method attached to it: {}. The signature " + "keys for these functions are ambiguous. Specify signature " + "functions explicitly.").format( + [previous_attribute_name, attribute_name])) + exported_function = attribute_value + previous_attribute_name = attribute_name + if exported_function is None: + exported_function = _check_for_functional_keras_model(root) + if exported_function is None: raise ValueError( ("Exporting an object with no tf.saved_model.save(..., signatures=...) " "argument specified, and with no @tf.function-decorated methods " @@ -60,14 +103,7 @@ def _find_function_to_export(root): "signatures does not make sense, as the only consumers will expect " "signatures. Either decorate a method or specify a signature function " "explicitly.")) - elif len(functions) > 1: - raise ValueError( - ("Exporting an object with no tf.saved_model.save(..., signatures=...) " - "argument specified, and with more than one @tf.function-decorated " - "method attached to it: {}. The signature keys for these functions " - "are ambiguous. Specify signature functions explicitly.").format( - function_attribute_names)) - return functions[0] + return exported_function def _canonicalize_signatures(signatures): @@ -77,7 +113,7 @@ def _canonicalize_signatures(signatures): signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY: signatures} concrete_signatures = {} for serving_key, signature_function in signatures.items(): - if isinstance(signature_function, (function.PolymorphicFunction, + if isinstance(signature_function, (defun.PolymorphicFunction, def_function.PolymorphicFunction)): input_signature = signature_function._input_signature # pylint: disable=protected-access if input_signature is None: @@ -88,7 +124,7 @@ def _canonicalize_signatures(signatures): "converted to concrete functions using " "`f.get_concrete_function(...)`.").format(signature_function)) signature_function = signature_function.get_concrete_function() - elif not isinstance(signature_function, function.Function): + elif not isinstance(signature_function, defun.Function): raise ValueError( ("Expected a TensorFlow function to generate a signature for, but " "got {}. Python functions may be decorated with " @@ -145,64 +181,65 @@ def _tensor_dict_to_tensorinfo(tensor_dict): for key, value in tensor_dict.items()} -def _map_captured_resources_to_created_resources( +def _map_captures_to_created_tensors( original_captures, resource_map): - """Maps eager resources captured by a function to Graph resources for export. + """Maps eager tensors captured by a function to Graph resources for export. Args: - original_captures: A dictionary mapping from resource tensors captured by - the function to interior placeholders for those resources (inside the - function body). + original_captures: A dictionary mapping from tensors captured by the + function to interior placeholders for those tensors (inside the function + body). resource_map: A dictionary mapping from resource tensors owned by the eager context to resource tensors in the exported graph. Returns: - A dictionary mapping from interior placeholders in the function body to - exterior stand-in resource tensors which belong to the exported graph. + A list of stand-in tensors which belong to the exported graph, corresponding + to the function's captures. Raises: AssertionError: If the function references a resource which is not part of `resource_map`. """ - export_captures = {} + export_captures = [] for exterior, interior in original_captures.items(): mapped_resource = resource_map.get(exterior, None) if mapped_resource is None: - raise AssertionError( - ("Tried to export a function which references untracked stateful " - "object {}. Stateful TensorFlow objects (e.g. tf.Variable) must " - "be tracked by the main object. Objects may be tracked by " - "assigning them to an attribute of another tracked object, or to " - "an attribute of the main object directly.") - .format(interior)) - export_captures[interior] = mapped_resource + if exterior.dtype == dtypes.resource: + raise AssertionError( + ("Tried to export a function which references untracked stateful " + "object {}. Stateful TensorFlow objects (e.g. tf.Variable) must " + "be tracked by the main object. Objects may be tracked by " + "assigning them to an attribute of another tracked object, or to " + "an attribute of the main object directly.") + .format(interior)) + else: + # This is a captured Tensor, but it's not a resource. We'll just add it + # to the graph as a constant. + mapped_resource = constant_op.constant(exterior.numpy()) + export_captures.append(mapped_resource) return export_captures -def _map_function_inputs_to_created_inputs( - function_inputs, export_captures, signature_key, function_name): - """Creates exterior placeholders in the exported graph for function inputs. +def _map_function_arguments_to_created_inputs( + function_arguments, signature_key, function_name): + """Creates exterior placeholders in the exported graph for function arguments. Functions have two types of inputs: tensors captured from the outside (eager) context, and arguments to the function which we expect to receive from the - user at each call. `_map_captured_resources_to_created_resources` replaces + user at each call. `_map_captures_to_created_tensors` replaces captured tensors with stand-ins (typically these are resource dtype tensors associated with variables). `_map_function_inputs_to_created_inputs` runs over - every input, either captured or argument. For captures, it uses the mapped - resource from `export_captures`. For arguments, it creates a new placeholder - which will belong to the exported graph rather than the function body. + every argument, creating a new placeholder for each which will belong to the + exported graph rather than the function body. Args: - function_inputs: A list of all placeholders in the function body. - export_captures: A dictionary mapping from interior placeholders in the - function body to exterior stand-in resource tensors which belong to the - exported graph (see `_map_captured_resources_to_created_resources`). + function_arguments: A list of argument placeholders in the function body. signature_key: The name of the signature being exported, for error messages. function_name: The name of the function, for error messages. Returns: A tuple of (mapped_inputs, exterior_placeholders) - mapped_inputs: A list with entries corresponding to `function_inputs` + mapped_inputs: A list with entries corresponding to `function_arguments` containing all of the inputs of the function gathered from the exported graph (both captured resources and arguments). exterior_argument_placeholders: A dictionary mapping from argument names @@ -220,12 +257,7 @@ def _map_function_inputs_to_created_inputs( # MetaGraph. exterior_argument_placeholders = {} mapped_inputs = [] - for placeholder in function_inputs: - mapped_resource_tensor = export_captures.get(placeholder, None) - if mapped_resource_tensor is not None: - # This is a captured resource. - mapped_inputs.append(mapped_resource_tensor) - continue + for placeholder in function_arguments: # `export_captures` contains an exhaustive set of captures, so if we don't # find the input there then we now know we have an argument. user_input_name = compat.as_str_any( @@ -258,6 +290,20 @@ def _map_function_inputs_to_created_inputs( return mapped_inputs, exterior_argument_placeholders +def _call_function_with_mapped_captures(function, args, resource_map): + """Calls `function` in the exported graph, using mapped resource captures.""" + export_captures = _map_captures_to_created_tensors( + function.graph.captures, resource_map) + mapped_inputs = args + export_captures + # Calls the function quite directly, since we have new captured resource + # tensors we need to feed in which weren't part of the original function + # definition. + # pylint: disable=protected-access + outputs = function._build_call_outputs( + function._inference_function.call(context.context(), mapped_inputs)) + return outputs + + def _generate_signatures(signature_functions, resource_map): """Validates and calls `signature_functions` in the default graph. @@ -287,35 +333,77 @@ def _generate_signatures(signature_functions, resource_map): SignatureDefs as part of that MetaGraph. """ signatures = {} - for signature_key, func in sorted(signature_functions.items()): - # Register the inference function for this signature in the exported - # graph. There is no direct use for the gradient of this function, so we - # don't generate/register a gradient function here (but may end up with one - # if another function relies on it). Users can still take symbolic gradients - # of the function on import, the gradient just won't be in the saved - # graph. When exporting a signature which already computes gradients, this - # stops us from taking needless second-order gradients. - func.add_to_graph(register_gradient_functions=False) - export_captures = _map_captured_resources_to_created_resources( - func.graph.captures, resource_map) + for signature_key, function in sorted(signature_functions.items()): + if function.graph.captures: + argument_inputs = function.graph.inputs[:-len(function.graph.captures)] + else: + argument_inputs = function.graph.inputs mapped_inputs, exterior_argument_placeholders = ( - _map_function_inputs_to_created_inputs( - func.inputs, export_captures, signature_key, func.name)) - # Calls the function quite directly, since we have new captured resource - # tensors we need to feed in which weren't part of the original function - # definition. - # pylint: disable=protected-access + _map_function_arguments_to_created_inputs( + argument_inputs, signature_key, function.name)) outputs = _normalize_outputs( - func._build_call_outputs( - func._inference_function.call(context.context(), mapped_inputs)), - func.name, signature_key) - # pylint: enable=protected-access + _call_function_with_mapped_captures( + function, mapped_inputs, resource_map), + function.name, signature_key) signatures[signature_key] = signature_def_utils.build_signature_def( _tensor_dict_to_tensorinfo(exterior_argument_placeholders), _tensor_dict_to_tensorinfo(outputs)) return signatures +def _trace_resource_initializers(accessible_objects): + """Create concrete functions from `TrackableResource` objects.""" + resource_initializers = [] + + def _wrap_initializer(obj): + obj.initialize() + return constant_op.constant(1.) # Dummy control output + + for obj in accessible_objects: + if isinstance(obj, tracking.TrackableResource): + resource_initializers.append(def_function.function( + functools.partial(_wrap_initializer, obj), + # All inputs are captures. + input_signature=[]).get_concrete_function()) + return resource_initializers + + +_AssetInfo = collections.namedtuple( + "_AssetInfo", [ + # List of AssetFileDef protocol buffers + "asset_defs", + # Map from asset variable resource Tensors to their init ops + "asset_initializers_by_resource", + # Map from base asset filenames to full paths + "asset_filename_map"]) + + +def _process_asset(trackable_asset, asset_info, resource_map): + """Add `trackable_asset` to `asset_info` and `resource_map`.""" + original_variable = trackable_asset.asset_path + with context.eager_mode(): + original_path = original_variable.numpy() + path = builder_impl.get_asset_filename_to_add( + asset_filepath=original_path, + asset_filename_map=asset_info.asset_filename_map) + asset_variable = asset_info.asset_filename_map.get(path, None) + if asset_variable is None: + asset_path_initializer = array_ops.placeholder( + shape=original_variable.shape, + dtype=dtypes.string, + name="asset_path_initializer") + asset_variable = resource_variable_ops.ResourceVariable( + asset_path_initializer) + asset_info.asset_filename_map[path] = original_path + asset_def = meta_graph_pb2.AssetFileDef() + asset_def.filename = path + asset_def.tensor_info.name = asset_path_initializer.name + asset_info.asset_defs.append(asset_def) + asset_info.asset_initializers_by_resource[original_variable.handle] = ( + asset_variable.initializer) + resource_map[original_variable.handle] = asset_variable.handle + + def _map_resources(accessible_objects): """Makes new resource handle ops corresponding to existing resource tensors. @@ -329,34 +417,83 @@ def _map_resources(accessible_objects): to create replacements for. Returns: - A tuple of (object_map, resource_map): + A tuple of (object_map, resource_map, asset_info): object_map: A dictionary mapping from object in `accessible_objects` to replacement objects created to hold the new resource tensors. resource_map: A dictionary mapping from resource tensors extracted from `accessible_objects` to newly created resource tensors. + asset_info: An _AssetInfo tuple describing external assets referenced from + accessible_objects. """ - # TODO(allenl, rohanj): Map generic resources rather than just variables. # TODO(allenl): Handle MirroredVariables and other types of variables which # may need special casing. object_map = {} resource_map = {} + asset_info = _AssetInfo( + asset_defs=[], + asset_initializers_by_resource={}, + asset_filename_map={}) for obj in accessible_objects: - if resource_variable_ops.is_resource_variable(obj): + if isinstance(obj, tracking.TrackableResource): + new_resource = obj.create_resource() + resource_map[obj.resource_handle] = new_resource + elif resource_variable_ops.is_resource_variable(obj): new_variable = resource_variable_ops.copy_to_graph_uninitialized(obj) object_map[obj] = new_variable resource_map[obj.handle] = new_variable.handle - return object_map, resource_map + if isinstance(obj, tracking.TrackableAsset): + _process_asset(obj, asset_info, resource_map) + return object_map, resource_map, asset_info + + +def _fill_meta_graph_def(meta_graph_def, obj, signature_functions, + object_saver): + """Generates a MetaGraph which calls `signature_functions`. + Args: + meta_graph_def: The MetaGraphDef proto to fill. + obj: The checkpointable object being exported. + signature_functions: A dictionary mapping signature keys to concrete + functions containing signatures to add to the MetaGraph. + object_saver: A CheckpointableSaver to add to the MetaGraph. -def _make_graph_def(root, signature_functions, object_saver): - """Generates and exports call ops for `signature_functions`.""" + Returns: + asset_filename_map, a dictionary mapping from asset base names to + user-specified full asset paths, which should be copied to the SavedModel's + assets/ directory. + """ signatures = {} # List objects from the eager context to make sure Optimizers give us the # right Graph-dependent variables. - accessible_objects = util.list_objects(root) + accessible_objects = util.list_objects(obj) + resource_initializer_functions = _trace_resource_initializers( + accessible_objects) exported_graph = ops.Graph() + resource_initializer_ops = [] with exported_graph.as_default(): - object_map, resource_map = _map_resources(accessible_objects) + object_map, resource_map, asset_info = _map_resources(accessible_objects) + for resource_initializer_function in resource_initializer_functions: + asset_dependencies = [] + for capture in resource_initializer_function.graph.external_captures: + asset_initializer = asset_info.asset_initializers_by_resource.get( + capture, None) + if asset_initializer is not None: + asset_dependencies.append(asset_initializer) + with ops.control_dependencies(asset_dependencies): + resource_initializer_ops.append( + _call_function_with_mapped_captures( + resource_initializer_function, [], resource_map)) + with ops.control_dependencies(resource_initializer_ops): + init_op = control_flow_ops.no_op() + # Add the same op to the main_op collection and to the init_op + # signature. The collection is for compatibility with older loader APIs; + # only one will be executed. + meta_graph_def.collection_def[constants.MAIN_OP_KEY].node_list.value.append( + init_op.name) + meta_graph_def.signature_def[constants.INIT_OP_SIGNATURE_KEY].CopyFrom( + signature_def_utils.op_signature_def( + init_op, constants.INIT_OP_SIGNATURE_KEY)) + # Saving an object-based checkpoint again gathers variables. We need to do the # gathering from the eager context so Optimizers save the right set of # variables, but want any operations associated with the save/restore to be in @@ -365,11 +502,35 @@ def _make_graph_def(root, signature_functions, object_saver): with exported_graph.as_default(): signatures = _generate_signatures(signature_functions, resource_map) saver_def = saver.to_proto() + meta_graph_def.saver_def.CopyFrom(saver_def) graph_def = exported_graph.as_graph_def(add_shapes=True) # Clean reference cycles so repeated export()s don't make work for the garbage # collector. ops.dismantle_graph(exported_graph) - return graph_def, signatures, saver_def + + meta_graph_def.graph_def.CopyFrom(graph_def) + meta_graph_def.meta_info_def.tags.append(tag_constants.SERVING) + meta_graph_def.asset_file_def.extend(asset_info.asset_defs) + for signature_key, signature in signatures.items(): + meta_graph_def.signature_def[signature_key].CopyFrom(signature) + meta_graph.strip_graph_default_valued_attrs(meta_graph_def) + return asset_info.asset_filename_map + + +def _write_object_graph(obj, export_dir): + """Save a SavedObjectGraph proto for `obj`.""" + # SavedObjectGraph is similar to the CheckpointableObjectGraph proto in the + # checkpoint. It will eventually go into the SavedModel. + object_proto = util.make_object_graph_without_attributes( + obj, proto=saved_object_graph_pb2.SavedObjectGraph()) + extra_asset_dir = os.path.join( + compat.as_bytes(export_dir), + compat.as_bytes(constants.EXTRA_ASSETS_DIRECTORY)) + file_io.recursive_create_dir(extra_asset_dir) + object_graph_filename = os.path.join( + extra_asset_dir, compat.as_bytes("object_graph.pb")) + file_io.write_string_to_file(object_graph_filename, + object_proto.SerializeToString()) @tf_export("saved_model.save", v1=["saved_model.experimental.save"]) @@ -450,6 +611,19 @@ def save(obj, export_dir, signatures=None): tf.TensorSpec(shape=[None, 3], dtype=tf.float32, name="inp"))) ``` + `tf.keras.Model` instances constructed from inputs and outputs already have a + signature and so do not require a `@tf.function` decorator or a `signatures` + argument. If neither are specified, the model's forward pass is exported. + + ```python + x = input_layer.Input((4,), name="x") + y = core.Dense(5, name="out")(x) + model = training.Model(x, y) + tf.saved_model.save(model, '/tmp/saved_model/') + # The exported SavedModel takes "x" with shape [None, 4] and returns "out" + # with shape [None, 5] + ``` + Variables must be tracked by assigning them to an attribute of a tracked object or to an attribute of `obj` directly. TensorFlow objects (e.g. layers from `tf.keras.layers`, optimizers from `tf.train`) track their variables @@ -515,26 +689,26 @@ def save(obj, export_dir, signatures=None): # Note that we run this before saving the checkpoint, since looping over # attributes may have the side effect of creating variables in some cases. signatures = _find_function_to_export(obj) - object_saver = util.CheckpointableSaver(obj) - utils_impl.get_or_create_variables_dir(export_dir) - object_saver.save(utils_impl.get_variables_path(export_dir)) signatures = _canonicalize_signatures(signatures) - graph_def, signatures, saver_def = _make_graph_def( - obj, signatures, object_saver) - saved_model = saved_model_pb2.SavedModel() - saved_model.saved_model_schema_version = ( - constants.SAVED_MODEL_SCHEMA_VERSION) - meta_graph_def = saved_model.meta_graphs.add() - meta_graph_def.saver_def.CopyFrom(saver_def) # TODO(allenl): Factor out some subset of SavedModelBuilder which is 2.x # compatible (no sessions) and share it with this export API rather than # making a SavedModel proto and writing it directly. - meta_graph_def.graph_def.MergeFrom(graph_def) - for signature_key, signature in signatures.items(): - meta_graph_def.signature_def[signature_key].MergeFrom(signature) - meta_graph.strip_graph_default_valued_attrs(meta_graph_def) + saved_model = saved_model_pb2.SavedModel() + meta_graph_def = saved_model.meta_graphs.add() + object_saver = util.CheckpointableSaver(obj) + asset_filename_map = _fill_meta_graph_def( + meta_graph_def, obj, signatures, object_saver) + saved_model.saved_model_schema_version = ( + constants.SAVED_MODEL_SCHEMA_VERSION) + # So far we've just been generating protocol buffers with no I/O. Now we write + # the checkpoint, copy assets into the assets directory, and write out the + # SavedModel proto itself. + utils_impl.get_or_create_variables_dir(export_dir) + object_saver.save(utils_impl.get_variables_path(export_dir)) + builder_impl.copy_assets_to_destination_dir(asset_filename_map, export_dir) path = os.path.join( compat.as_bytes(export_dir), compat.as_bytes(constants.SAVED_MODEL_FILENAME_PB)) file_io.write_string_to_file(path, saved_model.SerializeToString()) + _write_object_graph(obj, export_dir) diff --git a/tensorflow/python/saved_model/save_test.py b/tensorflow/python/saved_model/save_test.py index 42ff508b38..9e5b9b9717 100644 --- a/tensorflow/python/saved_model/save_test.py +++ b/tensorflow/python/saved_model/save_test.py @@ -21,6 +21,9 @@ from __future__ import print_function import os import sys +import numpy + +from tensorflow.python.client import session as session_lib from tensorflow.python.eager import backprop from tensorflow.python.eager import def_function from tensorflow.python.eager import test @@ -29,13 +32,19 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_spec from tensorflow.python.framework import test_util +from tensorflow.python.keras.engine import input_layer from tensorflow.python.keras.engine import training from tensorflow.python.keras.layers import core +from tensorflow.python.keras.layers import merge +from tensorflow.python.lib.io import file_io +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import lookup_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables from tensorflow.python.saved_model import loader from tensorflow.python.saved_model import save from tensorflow.python.saved_model import signature_constants +from tensorflow.python.saved_model import tag_constants from tensorflow.python.training import adam from tensorflow.python.training.checkpointable import tracking from tensorflow.python.training.checkpointable import util @@ -60,26 +69,27 @@ class _ModelWithOptimizer(training.Model): return {"loss": loss} -class SaveTest(test.TestCase): +def _import_and_infer( + save_dir, inputs, + signature_key=signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY): + """Import a SavedModel into a TF 1.x-style graph and run `signature_key`.""" + graph = ops.Graph() + with graph.as_default(), session_lib.Session() as session: + model = loader.load(session, [tag_constants.SERVING], save_dir) + signature = model.signature_def[signature_key] + assert set(inputs.keys()) == set(signature.inputs.keys()) + feed_dict = {} + for arg_name in inputs.keys(): + feed_dict[graph.get_tensor_by_name(signature.inputs[arg_name].name)] = ( + inputs[arg_name]) + output_dict = {} + for output_name, output_tensor_info in signature.outputs.items(): + output_dict[output_name] = graph.get_tensor_by_name( + output_tensor_info.name) + return session.run(output_dict, feed_dict=feed_dict) - def _import_and_infer( - self, save_dir, inputs, - signature_key=signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY): - """Import a SavedModel into a TF 1.x-style graph and run `signature_key`.""" - graph = ops.Graph() - with graph.as_default(), self.session(graph) as session: - model = loader.load(session, [], save_dir) - signature = model.signature_def[signature_key] - self.assertEqual(set(inputs.keys()), set(signature.inputs.keys())) - feed_dict = {} - for arg_name in inputs.keys(): - feed_dict[graph.get_tensor_by_name(signature.inputs[arg_name].name)] = ( - inputs[arg_name]) - output_dict = {} - for output_name, output_tensor_info in signature.outputs.items(): - output_dict[output_name] = graph.get_tensor_by_name( - output_tensor_info.name) - return session.run(output_dict, feed_dict=feed_dict) + +class SaveTest(test.TestCase): def test_method_save_signature(self): root = tracking.Checkpointable() @@ -91,7 +101,7 @@ class SaveTest(test.TestCase): save.save(root, save_dir, root.f) self.assertEqual( {"output_0": 2.}, - self._import_and_infer(save_dir, {"x": 1.})) + _import_and_infer(save_dir, {"x": 1.})) def test_method_save_concrete(self): root = tracking.Checkpointable() @@ -106,7 +116,7 @@ class SaveTest(test.TestCase): tensor_spec.TensorSpec(None, dtypes.float32))}) self.assertEqual( {"out": 2.}, - self._import_and_infer( + _import_and_infer( save_dir, {"z": 1.}, signature_key="non_default_key")) def test_non_concrete_error(self): @@ -163,7 +173,7 @@ class SaveTest(test.TestCase): save_dir = os.path.join(self.get_temp_dir(), "saved_model") save.save(root, save_dir, to_save) self.assertAllEqual({"output_0": 12.}, - self._import_and_infer(save_dir, {"x": 2.})) + _import_and_infer(save_dir, {"x": 2.})) def test_optimizer(self): x = constant_op.constant([[3., 4.]]) @@ -176,7 +186,7 @@ class SaveTest(test.TestCase): self.assertNotEqual(first_loss, second_loss) self.assertAllClose( second_loss, - self._import_and_infer(save_dir, {"x": [[3., 4.]], "y": [2.]})) + _import_and_infer(save_dir, {"x": [[3., 4.]], "y": [2.]})) def test_trivial_save_exception(self): save_dir = os.path.join(self.get_temp_dir(), "saved_model") @@ -191,8 +201,8 @@ class SaveTest(test.TestCase): save_dir = os.path.join(self.get_temp_dir(), "saved_model") save.save(model, save_dir) self.assertIn("loss", - self._import_and_infer(save_dir, - {"x": [[3., 4.]], "y": [2.]})) + _import_and_infer(save_dir, + {"x": [[3., 4.]], "y": [2.]})) def test_single_function_default_signature(self): model = tracking.Checkpointable() @@ -201,7 +211,7 @@ class SaveTest(test.TestCase): save_dir = os.path.join(self.get_temp_dir(), "saved_model") save.save(model, save_dir) self.assertAllClose({"output_0": 3.}, - self._import_and_infer(save_dir, {})) + _import_and_infer(save_dir, {})) def test_ambiguous_signatures(self): model = _ModelWithOptimizer() @@ -213,6 +223,19 @@ class SaveTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "call.*second_function"): save.save(model, save_dir) + def test_subclassed_no_signature(self): + + class Subclassed(training.Model): + + def call(self, inputs): + return inputs * 2. + + save_dir = os.path.join(self.get_temp_dir(), "saved_model") + model = Subclassed() + with self.assertRaisesRegexp( + ValueError, "no @tf.function-decorated methods"): + save.save(model, save_dir) + def test_docstring(self): class Adder(util.Checkpoint): @@ -227,7 +250,7 @@ class SaveTest(test.TestCase): save_dir = os.path.join(self.get_temp_dir(), "saved_model") save.save(to_save, save_dir) self.assertAllClose({"output_0": 7.}, - self._import_and_infer(save_dir, {"x": 3.})) + _import_and_infer(save_dir, {"x": 3.})) def test_default_attr_stripping(self): @@ -246,13 +269,90 @@ class SaveTest(test.TestCase): save.save(to_save, save_dir) graph = ops.Graph() with graph.as_default(), self.session(graph) as session: - loader.load(session, [], save_dir) + loader.load(session, [tag_constants.SERVING], save_dir) func, = graph._functions.values() complex_node, = [ node for node in func.definition.node_def if node.op == "Complex"] self.assertNotIn("T", complex_node.attr) self.assertNotIn("Tout", complex_node.attr) + def test_export_functional_keras_model(self): + x = input_layer.Input((4,), name="x") + y = core.Dense(4, name="out")(x) + model = training.Model(x, y) + save_dir = os.path.join(self.get_temp_dir(), "saved_model") + save.save(model, save_dir) + self.assertAllClose( + {"out": model(array_ops.ones([1, 4]))}, + _import_and_infer(save_dir, {"x": [[1., 1., 1., 1.]]})) + + @test_util.run_deprecated_v1 + def test_export_functional_keras_model_after_fit(self): + x = input_layer.Input((1,)) + y = core.Dense(1, name="y")(x) + model = training.Model(x, y) + model.compile(optimizer="sgd", loss="mse") + model.fit(x=numpy.array([[1.]]), + y=numpy.array([2.]), epochs=2) + save_dir = os.path.join(self.get_temp_dir(), "saved_model") + save.save(model, save_dir) + self.assertAllClose( + {"y": model(constant_op.constant([[1.], [2.]]))}, + _import_and_infer(save_dir, {"input_1": [[1.], [2.]]})) + + def test_export_multi_input_functional_keras_model(self): + x1 = input_layer.Input((2,), name="x1") + x2 = input_layer.Input((2,), name="x2") + y1 = core.Dense(4)(merge.Add()([x1, x2])) + y2 = core.Dense(4)(merge.Multiply()([x1, x2])) + model = training.Model([x1, x2], [y1, y2]) + save_dir = os.path.join(self.get_temp_dir(), "saved_model") + save.save(model, save_dir) + outputs = model([array_ops.ones([1, 2]), 2. * array_ops.ones([1, 2])]) + self.assertAllClose( + {"dense": outputs[0], "dense_1": outputs[1]}, + _import_and_infer( + save_dir, + {"x1": [[1., 1.]], + "x2": [[2., 2.]]})) + + +class AssetTests(test.TestCase): + + def setUp(self): + super(AssetTests, self).setUp() + self._vocab_path = os.path.join(self.get_temp_dir(), "vocab.txt") + with open(self._vocab_path, "w") as f: + f.write("alpha\nbeta\ngamma\n") + + def test_table(self): + initializer = lookup_ops.TextFileInitializer( + self._vocab_path, + key_dtype=dtypes.string, + key_index=lookup_ops.TextFileIndex.WHOLE_LINE, + value_dtype=dtypes.int64, + value_index=lookup_ops.TextFileIndex.LINE_NUMBER) + root = util.Checkpoint(table=lookup_ops.HashTable( + initializer, default_value=-1)) + root.table_user = def_function.function( + root.table.lookup, + input_signature=[tensor_spec.TensorSpec(None, dtypes.string)]) + self.assertEqual( + 2, + self.evaluate(root.table_user(constant_op.constant("gamma")))) + save_dir = os.path.join(self.get_temp_dir(), "saved_model") + save.save(root, save_dir) + file_io.delete_file(self._vocab_path) + self.assertAllClose( + {"output_0": [2, 0]}, + _import_and_infer(save_dir, {"keys": ["gamma", "alpha"]})) + second_dir = os.path.join(self.get_temp_dir(), "second_dir") + # Asset paths should track the location the SavedModel is loaded from. + file_io.rename(save_dir, second_dir) + self.assertAllClose( + {"output_0": [2, 1]}, + _import_and_infer(second_dir, {"keys": ["gamma", "beta"]})) + class MemoryTests(test.TestCase): diff --git a/tensorflow/python/saved_model/saved_model_test.py b/tensorflow/python/saved_model/saved_model_test.py index 5d6167ab38..0f18fb1a01 100644 --- a/tensorflow/python/saved_model/saved_model_test.py +++ b/tensorflow/python/saved_model/saved_model_test.py @@ -54,15 +54,15 @@ def tearDownModule(): file_io.delete_recursively(test.get_temp_dir()) -class SavedModelTest(test.TestCase): +class SavedModelTestBase(test.TestCase): def _get_export_dir(self, label): return os.path.join(test.get_temp_dir(), label) def _init_and_validate_variable(self, sess, variable_name, variable_value): v = variables.VariableV1(variable_value, name=variable_name) - sess.run(variables.global_variables_initializer()) - self.assertEqual(variable_value, v.eval()) + self.evaluate(variables.global_variables_initializer()) + self.assertEqual(variable_value, self.evaluate(v)) def _build_asset_collection(self, asset_file_name, asset_file_contents, asset_file_tensor_name, asset_subdir=""): @@ -78,14 +78,16 @@ class SavedModelTest(test.TestCase): asset_collection = ops.get_collection(ops.GraphKeys.ASSET_FILEPATHS) return asset_collection - def _validate_asset_collection(self, export_dir, graph_collection_def, - expected_asset_file_name, - expected_asset_file_contents, - expected_asset_tensor_name, - asset_id=0): - assets_any = graph_collection_def[constants.ASSETS_KEY].any_list.value - asset = meta_graph_pb2.AssetFileDef() - assets_any[asset_id].Unpack(asset) + +class SavedModelTest(SavedModelTestBase): + + def _validate_assets(self, + export_dir, + asset_file_def, + expected_asset_file_name, + expected_asset_file_contents, + expected_asset_tensor_name, + asset_id=0): assets_path = os.path.join( compat.as_bytes(export_dir), compat.as_bytes(constants.ASSETS_DIRECTORY), @@ -93,8 +95,10 @@ class SavedModelTest(test.TestCase): actual_asset_contents = file_io.read_file_to_string(assets_path) self.assertEqual(expected_asset_file_contents, compat.as_text(actual_asset_contents)) - self.assertEqual(expected_asset_file_name, asset.filename) - self.assertEqual(expected_asset_tensor_name, asset.tensor_info.name) + self.assertEqual(expected_asset_file_name, + asset_file_def[asset_id].filename) + self.assertEqual(expected_asset_tensor_name, + asset_file_def[asset_id].tensor_info.name) def _validate_inputs_tensor_info_fail(self, builder, tensor_info): with self.session(graph=ops.Graph()) as sess: @@ -142,6 +146,18 @@ class SavedModelTest(test.TestCase): sess, ["foo"], signature_def_map={"foo_key": foo_signature}) + def _validate_sig_def_keys(self, builder, valid_tensor_info, invalid_key): + with self.session(graph=ops.Graph()) as sess: + self._init_and_validate_variable(sess, "v", 42) + + foo_signature = signature_def_utils.build_signature_def( + dict(), {"foo_key": valid_tensor_info}, "foo") + self.assertRaises( + KeyError, + builder.add_meta_graph_and_variables, + sess, ["foo"], + signature_def_map={invalid_key: foo_signature}) + def testMaybeSavedModelDir(self): base_path = test.test_src_dir_path("/python/saved_model") self.assertFalse(loader.maybe_saved_model_directory(base_path)) @@ -183,9 +199,10 @@ class SavedModelTest(test.TestCase): constants.SAVED_MODEL_FILENAME_PBTXT): loader.load(sess, ["foo"], export_dir) + @test_util.run_deprecated_v1 def testVerifySessionGraphUsage(self): export_dir = self._get_export_dir("test_verify_session_graph_usage") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) @@ -203,9 +220,10 @@ class SavedModelTest(test.TestCase): self.assertEqual( 42, ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)[0].eval()) + @test_util.run_deprecated_v1 def testSequence(self): export_dir = self._get_export_dir("test_sequence") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Expect an assertion error since add_meta_graph_and_variables() should be # invoked before any add_meta_graph() calls. @@ -220,9 +238,10 @@ class SavedModelTest(test.TestCase): self.assertRaises(AssertionError, builder.add_meta_graph_and_variables, sess, ["baz"]) + @test_util.run_deprecated_v1 def testTags(self): export_dir = self._get_export_dir("test_tags") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Graph with a single variable. SavedModel invoked to: # - add with weights. @@ -309,9 +328,10 @@ class SavedModelTest(test.TestCase): self.assertRaises(RuntimeError, loader.load, sess, ["foo", "baz"], export_dir) + @test_util.run_deprecated_v1 def testVariables(self): export_dir = self._get_export_dir("test_variables") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Graph with two variables. SavedModel invoked to: # - add with weights. @@ -361,9 +381,10 @@ class SavedModelTest(test.TestCase): self.assertRaises(errors.NotFoundError, loader.load, sess, ["baz"], export_dir) + @test_util.run_deprecated_v1 def testGraphWithoutVariables(self): export_dir = self._get_export_dir("test_graph_has_variables") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Graph with no variables. with self.session(graph=ops.Graph()) as sess: @@ -385,7 +406,7 @@ class SavedModelTest(test.TestCase): a = ops.get_default_graph().get_tensor_by_name(constant_5_name) b = constant_op.constant(6.0) c = a * b - self.assertEqual(30.0, sess.run(c)) + self.assertEqual(30.0, self.evaluate(c)) # Restore the graph with tag "bar". with self.session(graph=ops.Graph()) as sess: @@ -394,11 +415,12 @@ class SavedModelTest(test.TestCase): a = ops.get_default_graph().get_tensor_by_name(constant_6_name) b = constant_op.constant(5.0) c = a * b - self.assertEqual(30.0, sess.run(c)) + self.assertEqual(30.0, self.evaluate(c)) + @test_util.run_deprecated_v1 def testNoOverwrite(self): export_dir = self._get_export_dir("test_no_overwrite") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Graph with a single variable. SavedModel invoked to: # - add with weights. @@ -417,12 +439,13 @@ class SavedModelTest(test.TestCase): # An attempt to create another builder with the same export directory should # result in an assertion error. - self.assertRaises(AssertionError, saved_model_builder.SavedModelBuilder, + self.assertRaises(AssertionError, saved_model_builder._SavedModelBuilder, export_dir) + @test_util.run_deprecated_v1 def testSaveAsText(self): export_dir = self._get_export_dir("test_astext") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Graph with a single variable. SavedModel invoked to: # - add with weights. @@ -451,17 +474,18 @@ class SavedModelTest(test.TestCase): self.assertEqual( 42, ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)[0].eval()) + @test_util.run_deprecated_v1 def testCollections(self): export_dir = self._get_export_dir("test_collections") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Graph with a single variable added to a collection. SavedModel invoked to: # - add with weights. with self.session(graph=ops.Graph()) as sess: v = variables.VariableV1(42, name="v") ops.add_to_collection("foo_vars", v) - sess.run(variables.global_variables_initializer()) - self.assertEqual(42, v.eval()) + self.evaluate(variables.global_variables_initializer()) + self.assertEqual(42, self.evaluate(v)) builder.add_meta_graph_and_variables(sess, ["foo"]) # Graph with the same single variable added to a different collection. @@ -470,8 +494,8 @@ class SavedModelTest(test.TestCase): with self.session(graph=ops.Graph()) as sess: v = variables.VariableV1(43, name="v") ops.add_to_collection("bar_vars", v) - sess.run(variables.global_variables_initializer()) - self.assertEqual(43, v.eval()) + self.evaluate(variables.global_variables_initializer()) + self.assertEqual(43, self.evaluate(v)) builder.add_meta_graph(["bar"]) # Save the SavedModel to disk. @@ -501,9 +525,10 @@ class SavedModelTest(test.TestCase): self.assertEqual(len(ops.get_collection("foo_vars")), 0) + @test_util.run_deprecated_v1 def testSignatureDefs(self): export_dir = self._get_export_dir("test_signature_defs") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Graph with a single variable and a single entry in the signature def map. # SavedModel is invoked to add with weights. @@ -563,7 +588,7 @@ class SavedModelTest(test.TestCase): def testSignatureDefValidationFails(self): export_dir = self._get_export_dir("test_signature_def_validation_fail") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) tensor_without_encoding = meta_graph_pb2.TensorInfo() tensor_without_encoding.dtype = types_pb2.DT_FLOAT @@ -579,19 +604,30 @@ class SavedModelTest(test.TestCase): self._validate_inputs_tensor_info_fail(builder, tensor_empty) self._validate_outputs_tensor_info_fail(builder, tensor_empty) + valid_tensor_info = meta_graph_pb2.TensorInfo() + valid_tensor_info.name = "foo" + valid_tensor_info.dtype = types_pb2.DT_FLOAT + + self._validate_sig_def_keys(builder, valid_tensor_info, + constants.INIT_OP_SIGNATURE_KEY) + self._validate_sig_def_keys(builder, valid_tensor_info, + constants.TRAIN_OP_SIGNATURE_KEY) + + @test_util.run_deprecated_v1 def testSignatureDefValidationSucceedsWithName(self): tensor_with_name = meta_graph_pb2.TensorInfo() tensor_with_name.name = "foo" tensor_with_name.dtype = types_pb2.DT_FLOAT export_dir = self._get_export_dir("test_signature_def_validation_name_1") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) self._validate_inputs_tensor_info_accept(builder, tensor_with_name) export_dir = self._get_export_dir("test_signature_def_validation_name_2") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) self._validate_outputs_tensor_info_accept(builder, tensor_with_name) + @test_util.run_deprecated_v1 def testSignatureDefValidationSucceedsWithCoo(self): tensor_with_coo = meta_graph_pb2.TensorInfo() # TODO(soergel) test validation of each of the fields of coo_sparse @@ -599,16 +635,17 @@ class SavedModelTest(test.TestCase): tensor_with_coo.dtype = types_pb2.DT_FLOAT export_dir = self._get_export_dir("test_signature_def_validation_coo_1") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) self._validate_inputs_tensor_info_accept(builder, tensor_with_coo) export_dir = self._get_export_dir("test_signature_def_validation_coo_2") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) self._validate_outputs_tensor_info_accept(builder, tensor_with_coo) + @test_util.run_deprecated_v1 def testAssets(self): export_dir = self._get_export_dir("test_assets") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) @@ -618,145 +655,151 @@ class SavedModelTest(test.TestCase): compat.as_bytes(test.get_temp_dir()), compat.as_bytes("ignored.txt")) file_io.write_string_to_file(ignored_filepath, "will be ignored") - asset_collection = self._build_asset_collection("hello42.txt", - "foo bar baz", - "asset_file_tensor") + asset_list = self._build_asset_collection("hello42.txt", "foo bar baz", + "asset_file_tensor") builder.add_meta_graph_and_variables( - sess, ["foo"], assets_collection=asset_collection) + sess, ["foo"], assets_list=asset_list) # Save the SavedModel to disk. builder.save() with self.session(graph=ops.Graph()) as sess: foo_graph = loader.load(sess, ["foo"], export_dir) - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "hello42.txt", "foo bar baz", - "asset_file_tensor:0") + self._validate_assets(export_dir, foo_graph.asset_file_def, "hello42.txt", + "foo bar baz", "asset_file_tensor:0") ignored_asset_path = os.path.join( compat.as_bytes(export_dir), compat.as_bytes(constants.ASSETS_DIRECTORY), compat.as_bytes("ignored.txt")) self.assertFalse(file_io.file_exists(ignored_asset_path)) + @test_util.run_deprecated_v1 def testAssetsNameCollisionDiffFile(self): export_dir = self._get_export_dir("test_assets_name_collision_diff_file") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) - asset_collection = self._build_asset_collection( - "hello42.txt", "foo bar bak", "asset_file_tensor", - asset_subdir="1") + asset_list = self._build_asset_collection( + "hello42.txt", "foo bar bak", "asset_file_tensor", asset_subdir="1") - asset_collection = self._build_asset_collection( - "hello42.txt", "foo bar baz", "asset_file_tensor_1", - asset_subdir="2") + asset_list = self._build_asset_collection( + "hello42.txt", "foo bar baz", "asset_file_tensor_1", asset_subdir="2") builder.add_meta_graph_and_variables( - sess, ["foo"], assets_collection=asset_collection) + sess, ["foo"], assets_list=asset_list) # Save the SavedModel to disk. builder.save() with self.session(graph=ops.Graph()) as sess: foo_graph = loader.load(sess, ["foo"], export_dir) - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "hello42.txt", "foo bar bak", - "asset_file_tensor:0") - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "hello42.txt_1", "foo bar baz", - "asset_file_tensor_1:0", - asset_id=1) - + self._validate_assets(export_dir, foo_graph.asset_file_def, "hello42.txt", + "foo bar bak", "asset_file_tensor:0") + self._validate_assets( + export_dir, + foo_graph.asset_file_def, + "hello42.txt_1", + "foo bar baz", + "asset_file_tensor_1:0", + asset_id=1) + + @test_util.run_deprecated_v1 def testAssetsNameCollisionSameFilepath(self): export_dir = self._get_export_dir("test_assets_name_collision_same_path") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) - asset_collection = self._build_asset_collection( - "hello42.txt", "foo bar baz", "asset_file_tensor") + asset_list = self._build_asset_collection("hello42.txt", "foo bar baz", + "asset_file_tensor") - asset_collection = self._build_asset_collection( - "hello42.txt", "foo bar baz", "asset_file_tensor_1") + asset_list = self._build_asset_collection("hello42.txt", "foo bar baz", + "asset_file_tensor_1") builder.add_meta_graph_and_variables( - sess, ["foo"], assets_collection=asset_collection) + sess, ["foo"], assets_list=asset_list) # Save the SavedModel to disk. builder.save() with self.session(graph=ops.Graph()) as sess: foo_graph = loader.load(sess, ["foo"], export_dir) - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "hello42.txt", "foo bar baz", - "asset_file_tensor:0") + self._validate_assets(export_dir, foo_graph.asset_file_def, "hello42.txt", + "foo bar baz", "asset_file_tensor:0") # The second tensor should be recorded, but the same. - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "hello42.txt", "foo bar baz", - "asset_file_tensor_1:0", - asset_id=1) + self._validate_assets( + export_dir, + foo_graph.asset_file_def, + "hello42.txt", + "foo bar baz", + "asset_file_tensor_1:0", + asset_id=1) ignored_asset_path = os.path.join( compat.as_bytes(export_dir), compat.as_bytes(constants.ASSETS_DIRECTORY), compat.as_bytes("hello42.txt_1")) self.assertFalse(file_io.file_exists(ignored_asset_path)) + @test_util.run_deprecated_v1 def testAssetsNameCollisionSameFile(self): export_dir = self._get_export_dir("test_assets_name_collision_same_file") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) - asset_collection = self._build_asset_collection( - "hello42.txt", "foo bar baz", "asset_file_tensor", - asset_subdir="1") + asset_list = self._build_asset_collection( + "hello42.txt", "foo bar baz", "asset_file_tensor", asset_subdir="1") - asset_collection = self._build_asset_collection( - "hello42.txt", "foo bar baz", "asset_file_tensor_1", - asset_subdir="2") + asset_list = self._build_asset_collection( + "hello42.txt", "foo bar baz", "asset_file_tensor_1", asset_subdir="2") builder.add_meta_graph_and_variables( - sess, ["foo"], assets_collection=asset_collection) + sess, ["foo"], assets_list=asset_list) # Save the SavedModel to disk. builder.save() with self.session(graph=ops.Graph()) as sess: foo_graph = loader.load(sess, ["foo"], export_dir) - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "hello42.txt", "foo bar baz", - "asset_file_tensor:0") + self._validate_assets(export_dir, foo_graph.asset_file_def, "hello42.txt", + "foo bar baz", "asset_file_tensor:0") # The second tensor should be recorded, but the same. - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "hello42.txt", "foo bar baz", - "asset_file_tensor_1:0", - asset_id=1) + self._validate_assets( + export_dir, + foo_graph.asset_file_def, + "hello42.txt", + "foo bar baz", + "asset_file_tensor_1:0", + asset_id=1) ignored_asset_path = os.path.join( compat.as_bytes(export_dir), compat.as_bytes(constants.ASSETS_DIRECTORY), compat.as_bytes("hello42.txt_1")) self.assertFalse(file_io.file_exists(ignored_asset_path)) + @test_util.run_deprecated_v1 def testAssetsNameCollisionManyFiles(self): export_dir = self._get_export_dir("test_assets_name_collision_many_files") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) for i in range(5): idx = str(i) - asset_collection = self._build_asset_collection( - "hello42.txt", "foo bar baz " + idx, "asset_file_tensor_" + idx, + asset_list = self._build_asset_collection( + "hello42.txt", + "foo bar baz " + idx, + "asset_file_tensor_" + idx, asset_subdir=idx) builder.add_meta_graph_and_variables( - sess, ["foo"], assets_collection=asset_collection) + sess, ["foo"], assets_list=asset_list) # Save the SavedModel to disk. builder.save() @@ -765,18 +808,20 @@ class SavedModelTest(test.TestCase): foo_graph = loader.load(sess, ["foo"], export_dir) for i in range(1, 5): idx = str(i) - self._validate_asset_collection( - export_dir, foo_graph.collection_def, "hello42.txt_" + idx, - "foo bar baz " + idx, "asset_file_tensor_{}:0".format(idx), + self._validate_assets( + export_dir, + foo_graph.asset_file_def, + "hello42.txt_" + idx, + "foo bar baz " + idx, + "asset_file_tensor_{}:0".format(idx), asset_id=i) - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "hello42.txt", "foo bar baz 0", - "asset_file_tensor_0:0") + self._validate_assets(export_dir, foo_graph.asset_file_def, "hello42.txt", + "foo bar baz 0", "asset_file_tensor_0:0") - def testCustomMainOp(self): + def testCustomInitOp(self): export_dir = self._get_export_dir("test_main_op") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: # Add `v1` and `v2` variables to the graph. @@ -792,11 +837,11 @@ class SavedModelTest(test.TestCase): # Set up an assignment op to be run as part of the main_op. with ops.control_dependencies([main_op.main_op()]): add_v1_v2 = math_ops.add(v1._ref(), v2._ref()) - custom_main_op = control_flow_ops.group(state_ops.assign(v3, add_v1_v2)) + custom_init_op = control_flow_ops.group(state_ops.assign(v3, add_v1_v2)) - sess.run(custom_main_op) + self.evaluate(custom_init_op) builder.add_meta_graph_and_variables( - sess, ["foo"], main_op=custom_main_op) + sess, ["foo"], init_op=custom_init_op) # Save the SavedModel to disk. builder.save() @@ -809,83 +854,10 @@ class SavedModelTest(test.TestCase): # the main_op, following a restore. self.assertEqual(3, ops.get_collection("v")[2].eval()) - def testLegacyInitOp(self): - export_dir = self._get_export_dir("test_legacy_init_op") - builder = saved_model_builder.SavedModelBuilder(export_dir) - - with self.session(graph=ops.Graph()) as sess: - # Add `v1` and `v2` variables to the graph. - v1 = variables.VariableV1(1, name="v1") - ops.add_to_collection("v", v1) - v2 = variables.VariableV1(2, name="v2") - ops.add_to_collection("v", v2) - - # Initialize another variable `v3` to 42. - v3 = variables.VariableV1(42, name="v3", trainable=False, collections=[]) - ops.add_to_collection("v", v3) - - # Set up an assignment op to be run as part of the legacy_init_op. - assign_v3 = state_ops.assign(v3, math_ops.add(v1, v2)) - legacy_init_op = control_flow_ops.group(assign_v3, name="legacy_init_op") - - sess.run(variables.global_variables_initializer()) - builder.add_meta_graph_and_variables( - sess, ["foo"], legacy_init_op=legacy_init_op) - - # Save the SavedModel to disk. - builder.save() - - with self.session(graph=ops.Graph()) as sess: - loader.load(sess, ["foo"], export_dir) - self.assertEqual(1, ops.get_collection("v")[0].eval()) - self.assertEqual(2, ops.get_collection("v")[1].eval()) - # Evaluates to the sum of the first two variables and assigned as part of - # the legacy_init_op, following a restore. - self.assertEqual(3, ops.get_collection("v")[2].eval()) - - def testLegacyInitOpWithNonEmptyCollection(self): - export_dir = self._get_export_dir( - "test_legacy_init_op_with_non_empty_collection") - self._testInitOpsWithNonEmptyCollection( - export_dir, constants.LEGACY_INIT_OP_KEY) - - def testMainOpWithNonEmptyCollection(self): - export_dir = self._get_export_dir( - "test_main_op_with_non_empty_collection") - self._testInitOpsWithNonEmptyCollection(export_dir, constants.MAIN_OP_KEY) - - def _testInitOpsWithNonEmptyCollection(self, export_dir, key): - builder = saved_model_builder.SavedModelBuilder(export_dir) - - g = ops.Graph() - with self.session(graph=g) as sess: - # Initialize variable `v1` to 1. - v1 = variables.VariableV1(1, name="v1") - ops.add_to_collection("v", v1) - - # Initialize another variable `v2` to 42. - v2 = variables.VariableV1(42, name="v2", trainable=False, collections=[]) - ops.add_to_collection("v", v2) - - # Set up an assignment op to be run as part of the init op. - assign_v2 = state_ops.assign(v2, v1) - init_op = control_flow_ops.group(assign_v2, name="init_op") - - sess.run(variables.global_variables_initializer()) - - ops.add_to_collection(key, control_flow_ops.no_op()) - # ValueError should be raised since the LEGACY_INIT_OP_KEY collection - # is not empty and we don't support multiple init ops. - with self.assertRaisesRegexp(ValueError, "Graph already contains"): - builder.add_meta_graph_and_variables( - sess, ["foo"], legacy_init_op=init_op) - # We shouldn't be able to add as MAIN_OP, either. - with self.assertRaisesRegexp(ValueError, "Graph already contains"): - builder.add_meta_graph_and_variables(sess, ["foo"], main_op=init_op) - + @test_util.run_deprecated_v1 def testTrainOp(self): export_dir = self._get_export_dir("test_train_op") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: # Add `v1` and `v2` variables to the graph. @@ -894,27 +866,26 @@ class SavedModelTest(test.TestCase): v2 = variables.VariableV1(2, name="v2") ops.add_to_collection("v", v2) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) train_op = state_ops.assign_add(v1, v2) - sess.run(train_op) - # TODO(karmel): remove explicit call when in the public method. - builder._add_train_op(train_op) - builder.add_meta_graph_and_variables(sess, ["foo"]) + self.evaluate(train_op) + builder.add_meta_graph_and_variables(sess, ["foo"], train_op=train_op) # Save the SavedModel to disk. builder.save() with self.session(graph=ops.Graph()) as sess: - loader.load(sess, ["foo"], export_dir) + meta_graph_def = loader.load(sess, ["foo"], export_dir) self.assertEqual(3, ops.get_collection("v")[0].eval()) self.assertEqual(2, ops.get_collection("v")[1].eval()) self.assertIsInstance( - ops.get_collection(constants.TRAIN_OP_KEY)[0], ops.Tensor) + loader_impl.get_train_op(meta_graph_def), ops.Tensor) + @test_util.run_deprecated_v1 def testTrainOpGroup(self): export_dir = self._get_export_dir("test_train_op_group") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: # Add `v1` and `v2` variables to the graph. @@ -923,27 +894,26 @@ class SavedModelTest(test.TestCase): v2 = variables.VariableV1(2, name="v2") ops.add_to_collection("v", v2) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) train_op = control_flow_ops.group() - sess.run(train_op) - # TODO(karmel): remove explicit call when in the public method. - builder._add_train_op(train_op) - builder.add_meta_graph_and_variables(sess, ["foo"]) + self.evaluate(train_op) + builder.add_meta_graph_and_variables(sess, ["foo"], train_op=train_op) # Save the SavedModel to disk. builder.save() with self.session(graph=ops.Graph()) as sess: - loader.load(sess, ["foo"], export_dir) + meta_graph_def = loader.load(sess, ["foo"], export_dir) self.assertEqual(1, ops.get_collection("v")[0].eval()) self.assertEqual(2, ops.get_collection("v")[1].eval()) self.assertIsInstance( - ops.get_collection(constants.TRAIN_OP_KEY)[0], ops.Operation) + loader_impl.get_train_op(meta_graph_def), ops.Operation) + @test_util.run_deprecated_v1 def testTrainOpAfterVariables(self): export_dir = self._get_export_dir("test_train_op_after_variables") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: # Add `v1` and `v2` variables to the graph. @@ -952,51 +922,50 @@ class SavedModelTest(test.TestCase): v2 = variables.VariableV1(2, name="v2") ops.add_to_collection("v", v2) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) builder.add_meta_graph_and_variables(sess, ["pre_foo"]) train_op = state_ops.assign_add(v1, v2) - sess.run(train_op) - # TODO(karmel): remove explicit call when in the public method. - builder._add_train_op(train_op) - builder.add_meta_graph(["foo"]) + self.evaluate(train_op) + builder.add_meta_graph(["foo"], train_op=train_op) # Save the SavedModel to disk. builder.save() with self.session(graph=ops.Graph()) as sess: - loader.load(sess, ["foo"], export_dir) + meta_graph_def = loader.load(sess, ["foo"], export_dir) self.assertIsInstance( - ops.get_collection(constants.TRAIN_OP_KEY)[0], ops.Tensor) + loader_impl.get_train_op(meta_graph_def), ops.Tensor) with self.session(graph=ops.Graph()) as sess: loader.load(sess, ["pre_foo"], export_dir) self.assertFalse(ops.get_collection(constants.TRAIN_OP_KEY)) + @test_util.run_deprecated_v1 def testMultipleAssets(self): export_dir = self._get_export_dir("test_multiple_assets") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) # Build an asset collection specific to `foo` graph. - asset_collection = self._build_asset_collection("foo.txt", "content_foo", - "asset_file_tensor") + asset_list = self._build_asset_collection("foo.txt", "content_foo", + "asset_file_tensor") # Add the asset collection as part of the graph with tag "foo". builder.add_meta_graph_and_variables( - sess, ["foo"], assets_collection=asset_collection) + sess, ["foo"], assets_list=asset_list) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) # Build an asset collection specific to `bar` graph. - asset_collection = self._build_asset_collection("bar.txt", "content_bar", - "asset_file_tensor") + asset_list = self._build_asset_collection("bar.txt", "content_bar", + "asset_file_tensor") # Add the asset collection as part of the graph with tag "bar". - builder.add_meta_graph(["bar"], assets_collection=asset_collection) + builder.add_meta_graph(["bar"], assets_list=asset_list) # Save the SavedModel to disk. builder.save() @@ -1004,43 +973,42 @@ class SavedModelTest(test.TestCase): # Check assets restored for graph with tag "foo". with self.session(graph=ops.Graph()) as sess: foo_graph = loader.load(sess, ["foo"], export_dir) - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "foo.txt", "content_foo", - "asset_file_tensor:0") + self._validate_assets(export_dir, foo_graph.asset_file_def, "foo.txt", + "content_foo", "asset_file_tensor:0") # Check assets restored for graph with tag "bar". with self.session(graph=ops.Graph()) as sess: bar_graph = loader.load(sess, ["bar"], export_dir) - self._validate_asset_collection(export_dir, bar_graph.collection_def, - "bar.txt", "content_bar", - "asset_file_tensor:0") + self._validate_assets(export_dir, bar_graph.asset_file_def, "bar.txt", + "content_bar", "asset_file_tensor:0") + @test_util.run_deprecated_v1 def testDuplicateAssets(self): export_dir = self._get_export_dir("test_duplicate_assets") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) # Build an asset collection with `foo.txt` that has `foo` specific # content. - asset_collection = self._build_asset_collection("foo.txt", "content_foo", - "asset_file_tensor") + asset_list = self._build_asset_collection("foo.txt", "content_foo", + "asset_file_tensor") # Add the asset collection as part of the graph with tag "foo". builder.add_meta_graph_and_variables( - sess, ["foo"], assets_collection=asset_collection) + sess, ["foo"], assets_list=asset_list) with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) # Build an asset collection with `foo.txt` that has `bar` specific # content. - asset_collection = self._build_asset_collection("foo.txt", "content_bar", - "asset_file_tensor") + asset_list = self._build_asset_collection("foo.txt", "content_bar", + "asset_file_tensor") # Add the asset collection as part of the graph with tag "bar". - builder.add_meta_graph(["bar"], assets_collection=asset_collection) + builder.add_meta_graph(["bar"], assets_list=asset_list) # Save the SavedModel to disk. builder.save() @@ -1048,9 +1016,8 @@ class SavedModelTest(test.TestCase): # Check assets restored for graph with tag "foo". with self.session(graph=ops.Graph()) as sess: foo_graph = loader.load(sess, ["foo"], export_dir) - self._validate_asset_collection(export_dir, foo_graph.collection_def, - "foo.txt", "content_foo", - "asset_file_tensor:0") + self._validate_assets(export_dir, foo_graph.asset_file_def, "foo.txt", + "content_foo", "asset_file_tensor:0") # Check assets restored for graph with tag "bar". with self.session(graph=ops.Graph()) as sess: @@ -1059,13 +1026,13 @@ class SavedModelTest(test.TestCase): # Validate the assets for `bar` graph. `foo.txt` should contain the # original contents corresponding to `foo` graph since an asset with the # same name across multiple graphs is only stored the first time - self._validate_asset_collection(export_dir, bar_graph.collection_def, - "foo.txt", "content_foo", - "asset_file_tensor:0") + self._validate_assets(export_dir, bar_graph.asset_file_def, "foo.txt", + "content_foo", "asset_file_tensor:0") + @test_util.run_deprecated_v1 def testOp(self): export_dir = self._get_export_dir("test_op") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with session.Session( graph=ops.Graph(), @@ -1086,7 +1053,7 @@ class SavedModelTest(test.TestCase): ops.add_to_collection("v", v3) ops.add_to_collection("init_op", init_op) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertEqual(1, ops.get_collection("v")[0].eval()) self.assertEqual(2, ops.get_collection("v")[1].eval()) @@ -1108,7 +1075,7 @@ class SavedModelTest(test.TestCase): def testCustomSaveable(self): export_dir = self._get_export_dir("custom_saveable") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with session.Session( graph=ops.Graph(), @@ -1135,13 +1102,14 @@ class SavedModelTest(test.TestCase): self.assertEqual(b"k1", v1.keys().eval()) self.assertEqual(3.0, v1.values().eval()) + @test_util.run_deprecated_v1 def testCustomSaver(self): export_dir = self._get_export_dir("test_custom_saver") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: variables.VariableV1(1, name="v1") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) custom_saver = training.Saver(name="my_saver") builder.add_meta_graph_and_variables(sess, ["tag"], saver=custom_saver) @@ -1157,13 +1125,14 @@ class SavedModelTest(test.TestCase): self.assertEqual( saved_graph.saver_def.restore_op_name, "my_saver/restore_all") + @test_util.run_deprecated_v1 def testNoCustomSaver(self): export_dir = self._get_export_dir("test_no_custom_saver") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: variables.VariableV1(1, name="v1") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) training.Saver(name="my_saver") builder.add_meta_graph_and_variables(sess, ["tag"]) @@ -1179,13 +1148,14 @@ class SavedModelTest(test.TestCase): self.assertEqual( saved_graph.saver_def.restore_op_name, "save/restore_all") + @test_util.run_deprecated_v1 def testMultipleCustomSavers(self): export_dir = self._get_export_dir("test_multiple_custom_savers") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) with self.session(graph=ops.Graph()) as sess: variables.VariableV1(1, name="v1") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) builder.add_meta_graph_and_variables(sess, ["tag_0"]) saver_1 = training.Saver() @@ -1209,21 +1179,22 @@ class SavedModelTest(test.TestCase): _validate_custom_saver("tag_1", "save_1/restore_all") _validate_custom_saver("tag_2", "save_2/restore_all") + @test_util.run_deprecated_v1 def testImportScope(self): export_dir = self._get_export_dir("test_scoped_assets") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Build a SavedModel with a variable, an asset, and a constant tensor. with self.session(graph=ops.Graph()) as sess: self._init_and_validate_variable(sess, "v", 42) - asset_collection = self._build_asset_collection("foo.txt", "content_foo", - "asset_file_tensor") + asset_list = self._build_asset_collection("foo.txt", "content_foo", + "asset_file_tensor") constant_op.constant("constant value", name="constant_tensor_name") builder.add_meta_graph_and_variables( - sess, ["tag_name"], assets_collection=asset_collection) + sess, ["tag_name"], assets_list=asset_list) # Save the asset file path for later comparison. - asset_file_path = asset_collection[0].eval() + asset_file_path = asset_list[0].eval() # Save the SavedModel to disk. builder.save() @@ -1244,16 +1215,14 @@ class SavedModelTest(test.TestCase): # The loaded asset tensor should be scoped, but the asset file path and # contents should be unchanged. - asset_collection = ops.get_collection(ops.GraphKeys.ASSET_FILEPATHS) - self.assertEqual(1, len(asset_collection)) - self.assertEqual(asset_file_path, asset_collection[0].eval()) - self.assertEqual("scope_name/asset_file_tensor:0", - asset_collection[0].name) + asset_list = ops.get_collection(ops.GraphKeys.ASSET_FILEPATHS) + self.assertEqual(1, len(asset_list)) + self.assertEqual(asset_file_path, asset_list[0].eval()) + self.assertEqual("scope_name/asset_file_tensor:0", asset_list[0].name) # The static asset data inside graph_proto.collection_def should not be # scoped. - self._validate_asset_collection(export_dir, graph_proto.collection_def, - "foo.txt", "content_foo", - "asset_file_tensor:0") + self._validate_assets(export_dir, graph_proto.asset_file_def, "foo.txt", + "content_foo", "asset_file_tensor:0") # The constant tensor should be scoped, but its contents should be # unchanged. @@ -1262,9 +1231,10 @@ class SavedModelTest(test.TestCase): ops.get_default_graph().get_tensor_by_name( "scope_name/constant_tensor_name:0").eval()) + @test_util.run_deprecated_v1 def testClearDevices(self): export_dir = self._get_export_dir("test_clear_devices") - builder = saved_model_builder.SavedModelBuilder(export_dir) + builder = saved_model_builder._SavedModelBuilder(export_dir) # Specify a device and save a variable. ops.reset_default_graph() @@ -1286,6 +1256,174 @@ class SavedModelTest(test.TestCase): self.assertEqual( 42, ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES)[0].eval()) + # Tests the behavior of loading SavedModels that having missing attrs or attrs + # with incorrect types. + def testInconsistentConsumerDefaultAttrs(self): + export_dir = self._get_export_dir( + "test_strip_default_attrs_no_consumer_defaults") + builder = saved_model_builder._SavedModelBuilder(export_dir) + + # Add a graph with a single variable and a test op with a defaultless + # float32 attr, "test_attr". + with session.Session(graph=ops.Graph()) as sess: + variables.VariableV1(1.0, dtype=dtypes.float64, name="var") + test_ops.test_attr(T=dtypes.float32, name="test_attr") + self.evaluate(variables.global_variables_initializer()) + builder.add_meta_graph_and_variables(sess, ["foo"]) + + # Save the SavedModel to disk in text format. + builder.save(as_text=True) + + # Rewrite the SavedModel to remove the T attr from "test_attr". + saved_model_file = os.path.join( + export_dir, constants.SAVED_MODEL_FILENAME_PBTXT) + with open(saved_model_file) as f: + original_saved_model = f.read() + + no_attr_saved_model = original_saved_model.replace(""" + attr { + key: "T" + value { + type: DT_FLOAT + } + }""", "") + with open(saved_model_file, "w") as f: + f.write(no_attr_saved_model) + + # Loading the SavedModel via the loader must fail because the SavedModel + # does not have any attr values for the "TestAttr" node, and there is no + # default specified in the TestAttr OpDef. + sess = session.Session(graph=ops.Graph()) + with self.assertRaisesRegexp( + ValueError, "NodeDef missing attr 'T' from Op= mtimes[0]) + @test_util.run_deprecated_v1 def testRemoveCheckpoint(self): for sharded in (False, True): for version in (saver_pb2.SaverDef.V2, saver_pb2.SaverDef.V1): diff --git a/tensorflow/python/training/checkpoint_ops_test.py b/tensorflow/python/training/checkpoint_ops_test.py index dde8431497..21ad3df1c8 100644 --- a/tensorflow/python/training/checkpoint_ops_test.py +++ b/tensorflow/python/training/checkpoint_ops_test.py @@ -47,7 +47,7 @@ class LoadAndRemapWrappersTest(test.TestCase): with variable_scope.variable_scope('some_scope'): variable_scope.get_variable(name='embeddings', shape=[5, 16], initializer=initializer) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) saver = saver_lib.Saver() saver.save(sess, checkpoint_prefix, global_step=5) self.checkpoint_file = '{}-5'.format(checkpoint_prefix) @@ -115,7 +115,8 @@ class LoadAndRemapWrappersTest(test.TestCase): axis=1) with self.cached_session(): - self.assertAllClose(expected_remapped_matrix, remapped_matrix.eval()) + self.assertAllClose(expected_remapped_matrix, + self.evaluate(remapped_matrix)) def test_load_and_remap_output_layer_weight_initializer_linear(self): """Tests for the output layer initializer in the linear multi-class case.""" diff --git a/tensorflow/python/training/checkpoint_utils.py b/tensorflow/python/training/checkpoint_utils.py index 857da431db..58166dbb68 100644 --- a/tensorflow/python/training/checkpoint_utils.py +++ b/tensorflow/python/training/checkpoint_utils.py @@ -101,7 +101,7 @@ def list_variables(ckpt_dir_or_file): return result -@tf_export("train.init_from_checkpoint") +@tf_export(v1=["train.init_from_checkpoint"]) def init_from_checkpoint(ckpt_dir_or_file, assignment_map): """Replaces `tf.Variable` initializers so they load from a checkpoint file. @@ -187,7 +187,7 @@ def init_from_checkpoint(ckpt_dir_or_file, assignment_map): _init_from_checkpoint(None, ckpt_dir_or_file, assignment_map) else: distribution_strategy_context.get_replica_context().merge_call( - _init_from_checkpoint, ckpt_dir_or_file, assignment_map) + _init_from_checkpoint, args=(ckpt_dir_or_file, assignment_map)) def _init_from_checkpoint(_, ckpt_dir_or_file, assignment_map): diff --git a/tensorflow/python/training/checkpointable/BUILD b/tensorflow/python/training/checkpointable/BUILD index d26932c1aa..f97f42a659 100644 --- a/tensorflow/python/training/checkpointable/BUILD +++ b/tensorflow/python/training/checkpointable/BUILD @@ -152,7 +152,7 @@ py_test( "//tensorflow/python:variable_scope", "//tensorflow/python/eager:backprop", "//tensorflow/python/eager:context", - "//tensorflow/python/eager:function", + "//tensorflow/python/eager:def_function", "//tensorflow/python/eager:test", "//tensorflow/python/keras:engine", "//tensorflow/python/keras:layers", diff --git a/tensorflow/python/training/checkpointable/data_structures.py b/tensorflow/python/training/checkpointable/data_structures.py index c29e5db075..817552f326 100644 --- a/tensorflow/python/training/checkpointable/data_structures.py +++ b/tensorflow/python/training/checkpointable/data_structures.py @@ -111,9 +111,6 @@ class CheckpointableDataStructure(base.CheckpointableBase): """Base class for data structures which contain checkpointable objects.""" def __init__(self): - # An append-only ordered set - self._layers = [] - self.trainable = True self._extra_variables = [] @@ -128,21 +125,30 @@ class CheckpointableDataStructure(base.CheckpointableBase): ("Only checkpointable objects (such as Layers or Optimizers) may be " "stored in a List object. Got %s, which does not inherit from " "CheckpointableBase.") % (value,)) - if (isinstance(value, CheckpointableDataStructure) - or layer_utils.is_layer(value) - or layer_utils.has_weights(value)): - # Check for object-identity rather than with __eq__ to avoid - # de-duplicating empty container types. Automatically generated list - # wrappers keep things like "[] == []" true, which means "[] in [[]]" is - # also true. This becomes not true once one of the lists is mutated. - if not any((layer is value for layer in self._layers)): - self._layers.append(value) - if hasattr(value, "_use_resource_variables"): - # In subclassed models, legacy layers (tf.layers) must always use - # resource variables. - value._use_resource_variables = True # pylint: disable=protected-access + if hasattr(value, "_use_resource_variables"): + # In subclassed models, legacy layers (tf.layers) must always use + # resource variables. + value._use_resource_variables = True # pylint: disable=protected-access return value + @property + def _values(self): + """An iterable/sequence which may contain checkpointable objects.""" + raise NotImplementedError("Abstract method") + + @property + def _layers(self): + """All Layers and Layer containers, including empty containers.""" + # Filter objects on demand so that wrapper objects use values from the thing + # they're wrapping if out of sync. + collected = [] + for obj in self._values: + if (isinstance(obj, CheckpointableDataStructure) + or layer_utils.is_layer(obj) + or layer_utils.has_weights(obj)): + collected.append(obj) + return collected + @property def layers(self): return layer_utils.filter_empty_layer_containers(self._layers) @@ -265,6 +271,10 @@ class List(CheckpointableDataStructure, collections.Sequence): def _name_element(self, index): return "%d" % (index,) + @property + def _values(self): + return self + def append(self, value): """Add a new checkpointable value.""" value = self._track_value(value, self._name_element(len(self._storage))) @@ -479,6 +489,14 @@ class Mapping(CheckpointableDataStructure, collections.Mapping): def _make_storage(self, *args, **kwargs): return dict(*args, **kwargs) + @property + def _values(self): + # Sort items deterministically by key + ordered = list(zip(*sorted(self.items(), key=lambda it: it[0]))) + if ordered: + return ordered[1] + return [] + def _name_element(self, key): if not isinstance(key, six.string_types): raise TypeError( diff --git a/tensorflow/python/training/checkpointable/data_structures_test.py b/tensorflow/python/training/checkpointable/data_structures_test.py index ff7d1f1d2d..9cefd942ac 100644 --- a/tensorflow/python/training/checkpointable/data_structures_test.py +++ b/tensorflow/python/training/checkpointable/data_structures_test.py @@ -253,6 +253,13 @@ class ListTests(test.TestCase): l.append(1) self.assertEqual([1], l_wrapper) + def testLayerCollectionWithExternalMutation(self): + l = [] + l_wrapper = data_structures._ListWrapper(l) + layer = core.Dense(1) + l.append(layer) + self.assertEqual([layer], l_wrapper.layers) + def testHashing(self): has_sequences = set([data_structures.List(), data_structures.List()]) @@ -324,6 +331,20 @@ class MappingTests(test.TestCase): with self.assertRaises(TypeError): mapping[1] = data_structures.List() + def testLayerCollectionWithExternalMutation(self): + d = {} + root = tracking.Checkpointable() + root.wrapper = d + self.assertEqual([], root.wrapper.layers) + self.assertEqual([], root.wrapper.trainable_weights) + layer1 = core.Dense(1) + layer2 = core.Dense(1) + d["a"] = layer1 + d["b"] = layer2 + self.assertEqual([layer1, layer2], root.wrapper.layers) + # The layers have still not created variables + self.assertEqual([], root.wrapper.trainable_weights) + def testHashing(self): has_mappings = set([data_structures.Mapping(), data_structures.Mapping()]) diff --git a/tensorflow/python/training/checkpointable/tracking.py b/tensorflow/python/training/checkpointable/tracking.py index c85b208d47..4e96aee0c5 100644 --- a/tensorflow/python/training/checkpointable/tracking.py +++ b/tensorflow/python/training/checkpointable/tracking.py @@ -17,6 +17,10 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.eager import context +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.ops import resource_variable_ops from tensorflow.python.training.checkpointable import base from tensorflow.python.training.checkpointable import data_structures from tensorflow.python.util import tf_contextlib @@ -145,3 +149,36 @@ class TrackableResource(base.CheckpointableBase): if self._resource_handle is None: self._resource_handle = self.create_resource() return self._resource_handle + + +class TrackableAsset(base.CheckpointableBase): + """Base class for asset files which need to be tracked.""" + + def __init__(self, path): + """Record the full path to the asset.""" + # We use a variable here so that @tf.functions do not capture a literal + # value. The init_scope prevents functions from capturing `path` in an + # initialization graph, since it is transient and should not end up in a + # serialized function body. When serialized in a SavedModel, the variable + # will be set during the loading process to its location in the assets/ + # directory. + with ops.init_scope(): + if context.executing_eagerly(): + self._path = self._no_dependency( + resource_variable_ops.ResourceVariable( + path, dtype=dtypes.string, + name="asset_path")) + else: + # Adding a variable is too disruptive when v1-style graph building, + # since things may get fed and local variable initializers would then + # need to be run. + self._path = path + + @property + def asset_path(self): + """Fetch the current asset path.""" + return self._path + +ops.register_tensor_conversion_function( + TrackableAsset, + lambda asset, **kw: ops.internal_convert_to_tensor(asset.asset_path, **kw)) diff --git a/tensorflow/python/training/checkpointable/util.py b/tensorflow/python/training/checkpointable/util.py index f45f7445f1..36d3a7bebd 100644 --- a/tensorflow/python/training/checkpointable/util.py +++ b/tensorflow/python/training/checkpointable/util.py @@ -31,6 +31,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_shape +from tensorflow.python.lib.io import file_io from tensorflow.python.ops import array_ops from tensorflow.python.ops import gen_io_ops as io_ops from tensorflow.python.ops import init_ops @@ -549,13 +550,11 @@ def _serialize_slot_variables(checkpointable_objects, node_ids, object_names): return slot_variables -def _serialize_checkpointables( - checkpointable_objects, node_ids, object_names, slot_variables, +def _add_attributes_to_object_graph( + checkpointable_objects, object_graph_proto, node_ids, object_names, saveables_cache, object_map): - """Name non-slot `Checkpointable`s and add them to `object_graph_proto`.""" - object_graph_proto = ( - checkpointable_object_graph_pb2.CheckpointableObjectGraph()) - named_saveables = [] + """Create SaveableObjects and corresponding SerializedTensor protos.""" + named_saveable_objects = [] if saveables_cache is None: # No SaveableObject caching. Either we're executing eagerly, or building a # static save which is specialized to the current Python state. @@ -564,10 +563,9 @@ def _serialize_checkpointables( # If we are caching SaveableObjects, we need to build up a feed_dict with # functions computing volatile Python state to be saved with the checkpoint. feed_additions = {} - for checkpoint_id, checkpointable in enumerate(checkpointable_objects): + for checkpoint_id, (checkpointable, object_proto) in enumerate( + zip(checkpointable_objects, object_graph_proto.nodes)): assert node_ids[checkpointable] == checkpoint_id - object_proto = object_graph_proto.nodes.add() - object_proto.slot_variables.extend(slot_variables.get(checkpointable, ())) object_name = object_names[checkpointable] if object_map: object_to_save = object_map.get(checkpointable, checkpointable) @@ -645,14 +643,26 @@ def _serialize_checkpointables( "value.") % (checkpointable, new_feed_key)) feed_additions.update(saveable_feed_dict) - named_saveables.append(saveable) + named_saveable_objects.append(saveable) + return named_saveable_objects, feed_additions + + +def _fill_object_graph_proto(checkpointable_objects, node_ids, slot_variables, + object_graph_proto=None): + """Name non-slot `Checkpointable`s and add them to `object_graph_proto`.""" + if object_graph_proto is None: + object_graph_proto = ( + checkpointable_object_graph_pb2.CheckpointableObjectGraph()) + for checkpoint_id, checkpointable in enumerate(checkpointable_objects): + assert node_ids[checkpointable] == checkpoint_id + object_proto = object_graph_proto.nodes.add() + object_proto.slot_variables.extend(slot_variables.get(checkpointable, ())) for child in checkpointable._checkpoint_dependencies: # pylint: disable=protected-access child_proto = object_proto.children.add() child_proto.node_id = node_ids[child.ref] child_proto.local_name = child.name - - return named_saveables, object_graph_proto, feed_additions + return object_graph_proto def _serialize_gathered_objects( @@ -668,13 +678,18 @@ def _serialize_gathered_objects( checkpointable_objects=checkpointable_objects, node_ids=node_ids, object_names=object_names) - return _serialize_checkpointables( + object_graph_proto = _fill_object_graph_proto( + checkpointable_objects=checkpointable_objects, + node_ids=node_ids, + slot_variables=slot_variables) + named_saveable_objects, feed_additions = _add_attributes_to_object_graph( checkpointable_objects=checkpointable_objects, + object_graph_proto=object_graph_proto, node_ids=node_ids, object_names=object_names, - slot_variables=slot_variables, saveables_cache=saveables_cache, object_map=object_map) + return named_saveable_objects, object_graph_proto, feed_additions def _serialize_object_graph(root_checkpointable, saveables_cache): @@ -716,6 +731,23 @@ def named_saveables(root_checkpointable): return _serialize_object_graph(root_checkpointable, None)[0] +def _find_objects(root_checkpointable): + """Find and number objects which are dependencies of `root_checkpointable`.""" + checkpointable_objects, path_to_root = ( + _breadth_first_checkpointable_traversal(root_checkpointable)) + object_names = _ObjectIdentityDictionary() + for obj, path in path_to_root.items(): + object_names[obj] = _object_prefix_from_path(path) + node_ids = _ObjectIdentityDictionary() + for node_id, node in enumerate(checkpointable_objects): + node_ids[node] = node_id + slot_variables = _serialize_slot_variables( + checkpointable_objects=checkpointable_objects, + node_ids=node_ids, + object_names=object_names) + return checkpointable_objects, node_ids, slot_variables + + def list_objects(root_checkpointable): """Traverse the object graph and list all accessible objects. @@ -730,23 +762,18 @@ def list_objects(root_checkpointable): Returns: A flat list of objects. """ - # TODO(allenl): Extract out gathering logic so the naming logic doesn't have - # to run. - checkpointable_objects, path_to_root = ( - _breadth_first_checkpointable_traversal(root_checkpointable)) - object_names = _ObjectIdentityDictionary() - for obj, path in path_to_root.items(): - object_names[obj] = _object_prefix_from_path(path) - node_ids = _ObjectIdentityDictionary() - for node_id, node in enumerate(checkpointable_objects): - node_ids[node] = node_id - _serialize_slot_variables( - checkpointable_objects=checkpointable_objects, - node_ids=node_ids, - object_names=object_names) + checkpointable_objects, _, _ = _find_objects(root_checkpointable) return checkpointable_objects +def make_object_graph_without_attributes(root_checkpointable, proto=None): + """Fill an object graph proto, ignoring variable values.""" + checkpointable_objects, node_ids, slot_variables = _find_objects( + root_checkpointable) + return _fill_object_graph_proto( + checkpointable_objects, node_ids, slot_variables, proto) + + def gather_initializers(root_checkpointable): """Traverse the object graph and find initialization ops. @@ -1434,6 +1461,7 @@ class CheckpointableSaver(object): elif session is None: session = ops.get_default_session() + file_io.recursive_create_dir(os.path.dirname(file_prefix)) with ops.device("/cpu:0"): save_path = saver.save( sess=_SessionWithFeedDictAdditions( @@ -1898,3 +1926,4 @@ class Checkpoint(tracking.Checkpointable): # initialization when executing eagerly. self._maybe_create_save_counter() return status + diff --git a/tensorflow/python/training/checkpointable/util_test.py b/tensorflow/python/training/checkpointable/util_test.py index 1995514012..de9cac0863 100644 --- a/tensorflow/python/training/checkpointable/util_test.py +++ b/tensorflow/python/training/checkpointable/util_test.py @@ -26,7 +26,7 @@ from tensorflow.python import pywrap_tensorflow from tensorflow.python.client import session as session_lib from tensorflow.python.eager import backprop from tensorflow.python.eager import context -from tensorflow.python.eager import function +from tensorflow.python.eager import def_function from tensorflow.python.eager import test from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes @@ -44,6 +44,7 @@ from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables from tensorflow.python.training import adam from tensorflow.python.training import checkpoint_management +from tensorflow.python.training import momentum from tensorflow.python.training import saver as saver_lib from tensorflow.python.training import training_util from tensorflow.python.training.checkpointable import base @@ -198,6 +199,17 @@ class InterfaceTests(test.TestCase): with self.assertRaises(NotImplementedError): checkpoint_reversed.save(prefix) + @test_util.run_in_graph_and_eager_modes(assert_no_eager_garbage=True) + def test_object_graph_no_attributes(self): + root = tracking.Checkpointable() + root.v = resource_variable_ops.ResourceVariable(1.) + root.opt = momentum.MomentumOptimizer(0.01, 0.5) + root.opt.minimize(root.v.read_value) + object_graph = checkpointable_utils.make_object_graph_without_attributes( + root) + # Four objects: Root, v, opt, and a slot variable for v + self.assertEqual(4, len(object_graph.nodes)) + class _MirroringSaveable(saver_lib.BaseSaverBuilder.SaveableObject): @@ -632,7 +644,7 @@ class CheckpointingTests(test.TestCase): checkpoint_directory) status = root.restore(save_path=checkpoint_path) def train_fn(): - @function.defun + @def_function.function def _call_model(x): return model(x) with backprop.GradientTape() as tape: diff --git a/tensorflow/python/training/coordinator.py b/tensorflow/python/training/coordinator.py index 0ff97d85e3..b7e5c98c78 100644 --- a/tensorflow/python/training/coordinator.py +++ b/tensorflow/python/training/coordinator.py @@ -408,7 +408,7 @@ class Coordinator(object): # Threads for the standard services. -@tf_export("train.LooperThread") +@tf_export(v1=["train.LooperThread"]) class LooperThread(threading.Thread): """A thread that runs code repeatedly, optionally on a timer. diff --git a/tensorflow/python/training/device_setter.py b/tensorflow/python/training/device_setter.py index be80c36571..5874a1ff41 100644 --- a/tensorflow/python/training/device_setter.py +++ b/tensorflow/python/training/device_setter.py @@ -130,7 +130,7 @@ class _ReplicaDeviceChooser(object): return worker_device.to_string() -@tf_export("train.replica_device_setter") +@tf_export(v1=["train.replica_device_setter"]) def replica_device_setter(ps_tasks=0, ps_device="/job:ps", worker_device="/job:worker", merge_devices=True, cluster=None, ps_ops=None, ps_strategy=None): diff --git a/tensorflow/python/training/device_setter_test.py b/tensorflow/python/training/device_setter_test.py index 85b75502ab..3cff87b326 100644 --- a/tensorflow/python/training/device_setter_test.py +++ b/tensorflow/python/training/device_setter_test.py @@ -19,6 +19,7 @@ from __future__ import division from __future__ import print_function from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test @@ -33,6 +34,7 @@ class DeviceSetterTest(test.TestCase): "worker": ["worker0:2222", "worker1:2222", "worker2:2222"] }) + @test_util.run_deprecated_v1 def testCPUOverride(self): with ops.device( device_setter.replica_device_setter(cluster=self._cluster_spec)): @@ -47,12 +49,14 @@ class DeviceSetterTest(test.TestCase): self.assertDeviceEqual("/job:ps/task:1", w.initializer.device) self.assertDeviceEqual("/job:worker/cpu:0", a.device) + @test_util.run_deprecated_v1 def testResource(self): with ops.device( device_setter.replica_device_setter(cluster=self._cluster_spec)): v = resource_variable_ops.ResourceVariable([1, 2]) self.assertDeviceEqual("/job:ps/task:0", v.device) + @test_util.run_deprecated_v1 def testPS2TasksWithClusterSpecClass(self): with ops.device( device_setter.replica_device_setter(cluster=self._cluster_spec)): @@ -65,6 +69,7 @@ class DeviceSetterTest(test.TestCase): self.assertDeviceEqual("/job:ps/task:1", w.initializer.device) self.assertDeviceEqual("/job:worker", a.device) + @test_util.run_deprecated_v1 def testPS2TasksPinVariableToJob(self): with ops.device( device_setter.replica_device_setter(cluster=self._cluster_spec)): @@ -82,6 +87,7 @@ class DeviceSetterTest(test.TestCase): self.assertDeviceEqual("/job:ps/task:1", x.initializer.device) self.assertDeviceEqual("/job:worker", a.device) + @test_util.run_deprecated_v1 def testPS2TasksUseCpuForPS(self): with ops.device( device_setter.replica_device_setter(ps_tasks=1, ps_device="/cpu:0")): @@ -95,6 +101,7 @@ class DeviceSetterTest(test.TestCase): self.assertDeviceEqual("/job:moon/cpu:0", w.initializer.device) self.assertDeviceEqual("/job:worker", a.device) + @test_util.run_deprecated_v1 def testPS2TasksNoMerging(self): with ops.device( device_setter.replica_device_setter( @@ -109,6 +116,7 @@ class DeviceSetterTest(test.TestCase): self.assertDeviceEqual("/job:ps", w.initializer.device) self.assertDeviceEqual("/job:worker", a.device) + @test_util.run_deprecated_v1 def testPS2TasksWithClusterSpecDict(self): with ops.device( device_setter.replica_device_setter(cluster=self._cluster_spec.as_dict( @@ -122,6 +130,7 @@ class DeviceSetterTest(test.TestCase): self.assertDeviceEqual("/job:ps/task:1", w.initializer.device) self.assertDeviceEqual("/job:worker", a.device) + @test_util.run_deprecated_v1 def testPS2TasksWithClusterDef(self): with ops.device( device_setter.replica_device_setter( @@ -135,6 +144,7 @@ class DeviceSetterTest(test.TestCase): self.assertDeviceEqual("/job:ps/task:1", w.initializer.device) self.assertDeviceEqual("/job:worker", a.device) + @test_util.run_deprecated_v1 def testPS2TasksWithDevice(self): cluster_spec = server_lib.ClusterSpec({ "sun": ["sun0:2222", "sun1:2222", "sun2:2222"], @@ -155,6 +165,7 @@ class DeviceSetterTest(test.TestCase): self.assertDeviceEqual("/job:moon/task:1", w.initializer.device) self.assertDeviceEqual("/job:sun", a.device) + @test_util.run_deprecated_v1 def testPS2TasksWithCPUConstraint(self): cluster_spec = server_lib.ClusterSpec({ "sun": ["sun0:2222", "sun1:2222", "sun2:2222"], diff --git a/tensorflow/python/training/distribute.py b/tensorflow/python/training/distribute.py index 95104ad577..ad27bc8a70 100644 --- a/tensorflow/python/training/distribute.py +++ b/tensorflow/python/training/distribute.py @@ -12,1234 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Class DistributionStrategy, ReplicaContext, and supporting APIs.""" +"""Deprecated, please use ../distribute/distribute_lib.py.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -import threading - -from tensorflow.python.data.ops import dataset_ops -from tensorflow.python.framework import ops -from tensorflow.python.ops import array_ops -from tensorflow.python.ops import control_flow_ops -from tensorflow.python.ops import resource_variable_ops -from tensorflow.python.ops import variable_scope -from tensorflow.python.ops.losses import losses_impl -from tensorflow.python.platform import tf_logging -from tensorflow.python.training import device_util -from tensorflow.python.training import distribution_strategy_context -from tensorflow.python.util import nest - - -# ------------------------------------------------------------------------------ -# Context tracking whether in a distribution.update() or .update_non_slot() -# call. - - -_update_device = threading.local() - - -def get_update_device(): - """Get the current device if in a `DistributionStrategy.update()` call.""" - try: - return _update_device.current - except AttributeError: - return None - - -class UpdateContext(object): - """Context manager when you are in `update()` or `update_non_slot()`.""" - - def __init__(self, device): - self._device = device - self._old_device = None - - def __enter__(self): - self._old_device = get_update_device() - _update_device.current = self._device - - def __exit__(self, exception_type, exception_value, traceback): - del exception_type, exception_value, traceback - _update_device.current = self._old_device - - -# ------------------------------------------------------------------------------ -# Public utility functions. - - -def get_loss_reduction(): - """Reduce `aggregation` corresponding to the last loss reduction.""" - loss_reduction = ops.get_default_graph()._last_loss_reduction # pylint: disable=protected-access - if loss_reduction == losses_impl.Reduction.SUM: - return variable_scope.VariableAggregation.SUM - return variable_scope.VariableAggregation.MEAN - - -# ------------------------------------------------------------------------------ -# Internal API for validating the current thread mode - - -def _require_cross_replica_context(distribution_strategy): - """Verify in cross-replica context for `distribution_strategy`.""" - context = _get_per_thread_mode() - if context.cross_replica_context is distribution_strategy: return - # We have an error to report, figure out the right message. - if context.distribution_strategy is not distribution_strategy: - if not distribution_strategy_context.has_distribution_strategy(): - raise RuntimeError( - 'Need to be inside "with distribution_strategy.scope()" for %s' % - (distribution_strategy,)) - else: - raise RuntimeError( - "Mixing different DistributionStrategy objects: %s is not %s" % - (context.distribution_strategy, distribution_strategy)) - assert context.cross_replica_context is None - raise RuntimeError("Method requires being in cross-replica context, use " - "get_replica_context().merge_call()") - - -def require_replica_context(replica_ctx): - """Verify in `replica_ctx` replica context.""" - context = _get_per_thread_mode() - if context.replica_context is replica_ctx: return - # We have an error to report, figure out the right message. - if context.replica_context is None: - raise RuntimeError("Need to be inside `call_for_each_replica()`") - if context.distribution_strategy is replica_ctx.distribution_strategy: - # Two different ReplicaContexts with the same DistributionStrategy. - raise RuntimeError("Mismatching replica context.") - raise RuntimeError( - "Mismatching DistributionStrategy objects: %s is not %s." % - (context.distribution_strategy, replica_ctx.distribution_strategy)) - - -def _require_distribution_strategy_scope(distribution_strategy): - """Verify in a `distribution_strategy.scope()` in this thread.""" - context = _get_per_thread_mode() - if context.distribution_strategy is distribution_strategy: return - # We have an error to report, figure out the right message. - if not distribution_strategy_context.has_distribution_strategy(): - raise RuntimeError( - 'Need to be inside "with distribution_strategy.scope()" for %s' % - (distribution_strategy,)) - else: - raise RuntimeError( - "Mixing different DistributionStrategy objects: %s is not %s" % - (context.distribution_strategy, distribution_strategy)) - - -# ------------------------------------------------------------------------------ -# Internal context managers used to implement the DistributionStrategy -# base class - - -class _CurrentDistributionContext(object): - """Context manager for setting the `DistributionStrategy` and var creator.""" - - def __init__(self, - distribution_strategy, - var_creator_scope, - var_scope=None, - default_device=None): - self._context = distribution_strategy_context._CrossReplicaThreadMode( # pylint: disable=protected-access - distribution_strategy) - self._var_creator_scope = var_creator_scope - self._var_scope = var_scope - if default_device: - self._device_scope = ops.device(default_device) - else: - self._device_scope = None - - def __enter__(self): - _push_per_thread_mode(self._context) - if self._var_scope: - self._var_scope.__enter__() - self._var_creator_scope.__enter__() - if self._device_scope: - self._device_scope.__enter__() - return self._context.distribution_strategy - - def __exit__(self, exception_type, exception_value, traceback): - if self._device_scope: - self._device_scope.__exit__(exception_type, exception_value, traceback) - self._var_creator_scope.__exit__(exception_type, exception_value, traceback) - if self._var_scope: - self._var_scope.__exit__(exception_type, exception_value, traceback) - _pop_per_thread_mode() - - -class _SameScopeAgainContext(object): - """Trivial context manager when you are already in `scope()`.""" - - def __init__(self, distribution_strategy): - self._distribution_strategy = distribution_strategy - - def __enter__(self): - return self._distribution_strategy - - def __exit__(self, exception_type, exception_value, traceback): - del exception_type, exception_value, traceback - - -# ------------------------------------------------------------------------------ -# Base classes for all distribution strategies. - - -class DistributionStrategy(object): - """A list of devices with a state & compute distribution policy. - - See [tensorflow/contrib/distribute/README.md]( - https://www.tensorflow.org/code/tensorflow/contrib/distribute/README.md) - for overview and examples. - - The intent is that you can write an algorithm in a stylized way and - it will be usable with a variety of different `DistributionStrategy` - implementations. Each descendant will implement a different strategy - for distributing the algorithm across multiple devices/machines. - Furthermore, these changes can be hidden inside the specific layers - and other library classes that need special treatment to run in a - distributed setting, so that most users' model definition code can - run unchanged. The `DistributionStrategy` API works the same way - with eager and graph execution. - - First let's introduce a few high-level concepts: - - * _Data parallelism_ is where we run multiple copies of the model - on different slices of the input data. This is in contrast to - _model parallelism_ where we divide up a single copy of a model - across multiple devices. - Note: we only support data parallelism for now, but - hope to add support for model parallelism in the future. - * A _replica_ is one copy of the model, running on one slice of the - input data. - * _Synchronous_, or more commonly _sync_, training is where the - updates from each replica are aggregated together before updating - the model variables. This is in contrast to _asynchronous_, or - _async_ training, where each replica updates the model variables - independently. - * Furthermore you might run your computation on multiple devices - on one machine (or "host"), or on multiple machines/hosts. - If you are running on multiple machines, you might have a - single master host that drives computation across all of them, - or you might have multiple clients driving the computation - asynchronously. - - To distribute an algorithm, we might use some of these ingredients: - - * Parameter servers: These are hosts that hold a single copy of - parameters/variables. All replicas that want to operate on a variable - retrieve it at the beginning of a step and send an update to be - applied at the end of the step. Can support either sync or async - training. - * Mirrored variables: These are variables that are copied to multiple - devices, where we keep the copies in sync by applying the same - updates to every copy. Normally would only be used with sync training. - * Reductions and Allreduce: A _reduction_ is some method of - aggregating multiple values into one value, like "sum" or - "mean". If doing sync training, we will perform a reduction on the - gradients to a parameter from all replicas before applying the - update. Allreduce is an algorithm for performing a reduction on - values from multiple devices and making the result available on - all of those devices. - * In the future we will have support for TensorFlow's partitioned - variables, where a single variable is split across multiple - devices. - - We have then a few approaches we want to support: - - * Code written (as if) with no knowledge of class `DistributionStrategy`. - This code should work as before, even if some of the layers, etc. - used by that code are written to be distribution-aware. This is done - by having a default `DistributionStrategy` that gives ordinary behavior, - and by default being in a single replica context. - * Ordinary model code that you want to run using a specific - `DistributionStrategy`. This can be as simple as: - - ``` - with my_distribution.scope(): - iterator = my_distribution.distribute_dataset( - dataset).make_one_shot_iterator() - replica_train_ops = my_distribution.call_for_each_replica( - replica_fn, args=(iterator.get_next(),)) - train_op = tf.group(my_distribution.unwrap(replica_train_ops)) - ``` - - This takes an ordinary `dataset` and `replica_fn` and runs it - distributed using a particular `DistributionStrategy` in - `my_distribution`. Any variables created in `replica_fn` are created - using `my_distribution`'s policy, and library functions called by - `replica_fn` can use the `get_replica_context()` API to get enhanced - behavior in this case. - - You can also create an initializable iterator instead of a one-shot - iterator. In that case, you will need to ensure that you initialize the - iterator before calling get_next. - ``` - iterator = my_distribution.distribute_dataset( - dataset).make_initializable_iterator()) - session.run(iterator.initializer) - ``` - - * If you want to write a distributed algorithm, you may use any of - the `DistributionStrategy` APIs inside a - `with my_distribution.scope():` block of code. - - Lower-level concepts: - - * Wrapped values: In order to represent values parallel across devices - (either replicas or the devices associated with a particular value), we - wrap them in a "PerReplica" or "Mirrored" object that contains a map - from device to values. "PerReplica" is used when the value may be - different across replicas, and "Mirrored" when the value are the same. - * Unwrapping and merging: Consider calling a function `fn` on - multiple replicas, like `call_for_each_replica(fn, args=[w])` with an - argument `w` that is a wrapped value. This means `w` will have a - map taking replica device `d0` to `w0`, replica device `d1` to `w1`, - etc. `call_for_each_replica()` unwraps `w` before calling `fn`, so - it calls `fn(w0)` on `d0`, `fn(w1)` on `d1`, etc. It then merges - the return values from `fn()`, which can possibly result in - wrapped values. For example, let's say `fn()` returns a tuple with - three components: `(x, a, v0)` from replica 0, `(x, b, v1)` on replica 1, - etc. If the first component is the same object `x` from every - replica, then the first component of the merged result will also be - `x`. If the second component is different (`a`, `b`, ...) from - each replica, then the merged value will have a wrapped map from - replica device to the different values. If the third component is - the members of a mirrored variable (`v` maps `d0` to `v0`, `d1` to - `v1`, etc.), then the merged result will be that mirrored variable - (`v`). - * Replica context vs. Cross-replica context: _replica context_ is when we - are in some function that is being called once for each replica. - Otherwise we are in cross-replica context, which is useful for - calling `DistributionStrategy` methods which operate across the - replicas (like `reduce()`). By default you start in a replica context - (the default "single replica context") and then some methods can - switch you back and forth, as described below. - * Worker devices vs. parameter devices: Most replica computations will - happen on worker devices. Since we don't yet support model - parallelism, there will be one worker device per replica. When using - parameter servers (see above), the set of devices holding - variables may be different, otherwise the parameter devices might - match the worker devices. - * Non-slot devices are some subset of the parameter devices where we - put all the non-slot variables. We need to ensure that all - non-slot variables are allocated on the same device, or mirrored - across the same set of devices. If you have some variable you want - to colocate all the non-slot variables with, you can use - `colocate_vars_with()` to get the remaining non-slot variables on - the same device. Otherwise you can use `non_slot_devices()` to - pick a consistent set of devices to pass to both - `colocate_vars_with()` and `update_non_slot()`. - - When using a `DistributionStrategy`, we have a new type dimension - called _locality_ that says what values are compatible with which - APIs: - - * T: different value for each replica (e.g. a PerReplica-wrapped value). - * M: value is "mirrored" across replicas, i.e. there are copies with the - same value on each replica (e.g. a Mirrored-wrapped value). - * V(`v`): value is "mirrored" across all the devices which have a - copy of variable `v` (also a Mirrored-wrapped value, but over - parameter devices instead of worker devices). - * N: value is "mirrored" across all the "non-slot" devices - - Rules for methods with respect to locality and single-replica vs. - cross-replica context: - - * `with d.scope()`: default single-replica context -> cross-replica context - for `d` - * `with d.colocate_vars_with(v)`: in replica/cross-replica context, variables - will be created with locality V(`v`). That is, if we write - `with d.colocate_vars_with(v1): v2 = tf.get_variable(...)`, then - `v2` will have locality V(`v1`), i.e. locality V(`v2`) will equal - V(`v1`). - * `with d.colocate_vars_with(d.non_slot_devices(...))`: in - replica/cross-replica context, variables will be created with locality N - * `v = tf.get_variable(...)`: in replica/cross-replica context, creates - a variable (which by definition will have locality V(`v`), though - will match another locality if inside a `colocate_vars_with` - scope). - * `d.distribute_dataset(dataset).make_one_shot_iterator()`: in cross-replica - context, produces an iterator with locality T - * `d.broadcast(t)`: in cross-replica context, produces a value with locality M - * `d.broadcast(t, v)`: in cross-replica context, produces a value with - locality V(`v`) - * `d.call_for_each_replica(fn, ...)`: in cross-replica context, runs - `fn()` in a replica context (and so may call `get_replica_context()` and - use its API, including `merge_call()` to get back to cross-replica - context), once for each replica. May use values with locality T or - M, and any variable. - * `d.reduce(m, t, t)`: in cross-replica context, accepts t with locality T - and produces a value with locality M. - * `d.reduce(m, t, v)`: in cross-replica context, accepts t with - locality T and produces a value with locality V(`v`). - * `d.batch_reduce(m, [(t, v)]): see `d.reduce()` - * `d.update(v, fn, ...)`: in cross-replica context, runs `fn()` once - for each device `v` is copied to, all inputs should have locality - V(`v`), output will have locality V(`v`) as well. - * `d.update_non_slot(d.non_slot_devices(), fn)`: in cross-replica - context, like `d.update()` except with locality N. - * `d.read_var(v)`: Gets the (read-only) value of the variable `v` (on - the device determined by the current device scope), aggregating - across replicas for replica-local variables. Frequently, this will be - done automatically when using `v` in an expression or fetching it in - a cross-replica context, but this function can be used to force that - conversion happens at a particular point in time (for example, to - add the result of the conversion to a graph collection). - - The standard pattern for updating variables is to: - - 1. Wrap your input dataset in `d.distribute_dataset()` and create an iterator. - 2. Define each replica `d.call_for_each_replica()` up to the point of - getting a list of gradient, variable pairs. - 3. Call `d.reduce(VariableAggregation.SUM, t, v)` or `d.batch_reduce()` to sum - the gradients (with locality T) into values with locality V(`v`). - 4. Call `d.update(v)` for each variable to update its value. - - Steps 3 and 4 are done automatically by class `Optimizer` if you call - its `apply_gradients` method in a replica context. Otherwise you can - manually call its `_distributed_apply` method in a cross-replica context. - - Another thing you might want to do in the middle of your replica function - is an all-reduce of some intermediate value, using `d.reduce()` or - `d.batch_reduce()`. You simply provide the same tensor as the input and - destination. - - Layers should expect to be called in a replica context, and can use - the `get_replica_context()` function to get a `ReplicaContext` object. The - `ReplicaContext` object has a `merge_call()` method for entering - cross-replica context where you can use `reduce()` (or - `batch_reduce()`) and then optionally `update()` to update state. - - You may use this API whether or not a `DistributionStrategy` is - being used, since there is a default implementation of - `ReplicaContext` and `DistributionStrategy`. - """ - - # TODO(josh11b): Raise an exception if variable partitioning requested before - # we add support. - # TODO(josh11b): Also `parameter_device_index` property? - # TODO(josh11b): `map()` - # TODO(josh11b): ClusterSpec/ClusterResolver - # TODO(josh11b): Partitioned computations, state; sharding - # TODO(josh11b): Model parallelism: "replicas" with multiple devices; shuffling - # TODO(josh11b): List of replicas with their worker and parameter devices - # (where the parameter devices may overlap in the ps case). - - def __init__(self): - self._default_device = None - # This property is used to determine if we should set drop_remainder=True - # when creating Datasets from numpy array inputs. - self._require_static_shapes = False - - def scope(self): - """Returns a context manager selecting this DistributionStrategy as current. - - Inside a `with distribution_strategy.scope():` code block, this thread - will use a variable creator set by `distribution_strategy`, and will - enter its "cross-replica context". - - Returns: - A context manager. - """ - if distribution_strategy_context.has_distribution_strategy(): - _require_cross_replica_context(self) - return _SameScopeAgainContext(self) - - def creator_with_resource_vars(*args, **kwargs): - _require_distribution_strategy_scope(self) - kwargs["use_resource"] = True - return self._create_variable(*args, **kwargs) - - def distributed_getter(getter, *args, **kwargs): - if not self._allow_variable_partition(): - if kwargs.pop("partitioner", None) is not None: - tf_logging.log_first_n( - tf_logging.WARN, "Partitioned variables are disabled when using " - "current DistributionStrategy.", 1) - return getter(*args, **kwargs) - - return _CurrentDistributionContext( - self, variable_scope.variable_creator_scope(creator_with_resource_vars), - variable_scope.variable_scope( - variable_scope.get_variable_scope(), - custom_getter=distributed_getter), self._default_device) - - def _allow_variable_partition(self): - return False - - def _create_variable(self, next_creator, *args, **kwargs): - # Note: should support "colocate_with" argument. - raise NotImplementedError("must be implemented in descendants") - - def read_var(self, v): - """Reads the value of a variable. - - Returns the aggregate value of a replica-local variable, or the - (read-only) value of any other variable. - - Args: - v: A variable allocated within the scope of this `DistributionStrategy`. - - Returns: - A tensor representing the value of `v`, aggregated across replicas if - necessary. - """ - raise NotImplementedError("must be implemented in descendants") - - def colocate_vars_with(self, colocate_with_variable): - """Scope that controls which devices variables will be created on. - - No operations should be added to the graph inside this scope, it - should only be used when creating variables (some implementations - work by changing variable creation, others work by using a - tf.colocate_with() scope). - - This may only be used inside `self.scope()`. - - Example usage: - - ``` - with distribution_strategy.scope(): - var1 = tf.get_variable(...) - with distribution_strategy.colocate_vars_with(v1): - # var2 and var3 will be created on the same device(s) as var1 - var2 = tf.get_variable(...) - var3 = tf.get_variable(...) - - def fn(v1, v2, v3): - # operates on v1 from var1, v2 from var2, and v3 from var3 - - # `fn` runs on every device `v1` is on, `v2` and `v3` will be there too. - distribution_strategy.update(v1, fn, v2, v3) - ``` - - Args: - colocate_with_variable: A created in `self.scope()`. Variables created - while in the returned context manager will be on the same set of - devices as `colocate_with_variable`. - - Returns: - A context manager. - """ - def create_colocated_variable(next_creator, *args, **kwargs): - _require_distribution_strategy_scope(self) - kwargs["use_resource"] = True - kwargs["colocate_with"] = colocate_with_variable - return next_creator(*args, **kwargs) - - _require_distribution_strategy_scope(self) - return variable_scope.variable_creator_scope(create_colocated_variable) - - def _call_dataset_fn(self, dataset_fn): - result = dataset_fn() - if not isinstance(result, dataset_ops.Dataset): - raise ValueError( - "dataset_fn() must return a tf.data.Dataset when using a " - "DistributionStrategy.") - return result - - # TODO(josh11b): `PerReplicaDataset` currently only implements a few methods of - # Dataset API such as make_one_shot_iterator and make_initializable_iterator. - # Extend to implement more functionality of datasets. - def distribute_dataset(self, dataset_fn): - """Return a `dataset` split across all replicas. - - Suitable for providing input to for `call_for_each_replica()` by creating an - iterator: - - ``` - def dataset_fn(): - return tf.data.Dataset.from_tensors([[1.]]).repeat() - with distribution_strategy.scope(): - distributed_dataset = distribution_strategy.distribute_dataset(dataset_fn) - iterator = distributed_dataset.make_one_shot_iterator() - replica_results = distribution_strategy.call_for_each_replica( - replica_fn, args=(iterator.get_next(),)) - ``` - - Args: - dataset_fn: A function that returns a `tf.data.Dataset`. - - Returns: - A `PerReplicaDataset` that will produce data for each replica. - """ - raise NotImplementedError("must be implemented in descendants") - - def broadcast(self, tensor, destinations=None): - """Mirror a tensor on one device to all worker devices. - - Args: - tensor: A Tensor value to broadcast. - destinations: An optional mirrored variable, device string, or - list of device strings, specifying the destination devices - to copy `tensor` to. Defaults to `self.worker_devices`. - - Returns: - A value mirrored to `destinations` devices. - """ - # TODO(josh11b): More docstring - _require_cross_replica_context(self) - return self._broadcast(tensor, destinations) - - def _broadcast(self, tensor, destinations): - raise NotImplementedError("must be implemented in descendants") - - def initialize(self): - """Any initialization to be done before running any computations. - - In eager mode, it executes any initialization as a side effect. - In graph mode, it creates the initialization ops and returns them. - - For example, TPU initialize_system ops. - - Returns: - A list of ops to execute. - """ - return [] - - def finalize(self): - """Any final actions to be done at the end of all computations. - - In eager mode, it executes any finalize actions as a side effect. - In graph mode, it creates the finalize ops and returns them. - - For example, TPU shutdown ops. - - Returns: - A list of ops to execute. - """ - return [] - - def run_steps_on_dataset(self, fn, iterator, iterations=1, - initial_loop_values=None): - """Run `fn` with input from `iterator` for `iterations` times. - - This method can be used to run a step function for training a number of - times using input from a dataset. - - Args: - fn: function to run using this distribution strategy. The function must - have the following signature: `def fn(context, *inputs)`. - `context` is an instance of `MultiStepContext` that will be passed when - `fn` is run. `context` can be used to specify the outputs to be returned - from `fn` by calling `context.set_last_step_output`. It can also be used - to capture non tensor outputs by `context.set_non_tensor_output`. - See `MultiStepContext` documentation for more information. - `inputs` will have same type/structure as `iterator.get_next()`. If the - `iterator.get_next()` returns a tuple say `return x, y` then whose will - be unpacked and passed to the `step_fn`; and step_fn signature would - look like `def step_fn(context, x, y)`. If the iterator returns a single - value say `return x` then the value is passed as is; the step_fn - signature would look like `def step_fn(context, x)`. - Typically, `fn` will use `call_for_each_replica` method of the strategy - to distribute the computation over multiple replicas. - iterator: Iterator of a dataset that represents the input for `fn`. The - caller is responsible for initializing the iterator as needed. - iterations: (Optional) Number of iterations that `fn` should be run. - Defaults to 1. - initial_loop_values: (Optional) Initial values to be passed into the - loop that runs `fn`. Defaults to `None`. # TODO(priyag): Remove - initial_loop_values argument when we have a mechanism to infer the - outputs of `fn`. - - Returns: - Returns the `MultiStepContext` object which has the following properties, - among other things: - - run_op: An op that runs `fn` `iterations` times. - - last_step_outputs: A dictionary containing tensors set using - `context.set_last_step_output`. Evaluating this returns the value of - the tensors after the last iteration. - - non_tensor_outputs: A dictionatry containing anything that was set by - `fn` by calling `context.set_non_tensor_output`. - """ - _require_cross_replica_context(self) - return self._run_steps_on_dataset(fn, iterator, iterations, - initial_loop_values) - - def _run_steps_on_dataset(self, fn, iterator, iterations, - initial_loop_values): - raise NotImplementedError("must be implemented in descendants") - - def call_for_each_replica(self, fn, *args, **kwargs): - """Run `fn` once per replica. - - `fn` may call `tf.get_replica_context()` to access methods such as - `replica_id()` and `merge_call()`. - - `merge_call()` is used to communicate between the replicas and - re-enter the cross-replica context. All replicas pause their execution - having encountered a `merge_call()` call. After that the - `merge_fn`-function is executed. Its results are then unwrapped and - given back to each replica call. After that execution resumes until - `fn` is complete or encounters another `merge_call()`. Example: - - ```python - # Called once in "cross-replica" context. - def merge_fn(distribution, three_plus_replica_id): - # sum the values across replicas - return sum(distribution.unwrap(three_plus_replica_id)) - - # Called once per replica in `distribution`, in a "replica" context. - def fn(three): - replica_ctx = tf.get_replica_context() - v = three + replica_ctx.replica_id - # Computes the sum of the `v` values across all replicas. - s = replica_ctx.merge_call(merge_fn, args=(v,)) - return s + v - - with distribution.scope(): - # in "cross-replica" context - ... - merged_results = distribution.call_for_each_replica(fn, args=[3]) - # merged_results has the values from every replica execution of `fn`. - print(distribution.unwrap(merged_results)) # Prints a list - ``` - - Args: - fn: function to run (will be run once per replica). - args: Tuple or list with positional arguments for `fn`. - kwargs: Dict with keyword arguments for `fn`. - - Returns: - Merged return value of `fn` across all replicas. - """ - _require_cross_replica_context(self) - # Handle old *args, **kwargs, and new args=(...), kwargs={...}, to - # allow transition. - a = kwargs.pop("args", None) - if a is not None: - if args: - raise ValueError( - "Can't pass *args and args=... to call_for_each_replica") - args = a - k = kwargs.pop("kwargs", None) - if k is not None: - if kwargs: - raise ValueError( - "Can't pass **kwargs and kwargs=... to call_for_each_replica") - kwargs = k - kwargs.pop("run_concurrently", None) # Ignore old option. - return self._call_for_each_replica(fn, args, kwargs) - - def _call_for_each_replica(self, fn, args, kwargs): - raise NotImplementedError("must be implemented in descendants") - - def reduce(self, aggregation, value, destinations): - """Combine (via e.g. sum or mean) values across replicas. - - Args: - aggregation: Indicates how a variable will be aggregated. Accepted values - are `tf.VariableAggregation.SUM`, `tf.VariableAggregation.MEAN`, - `tf.VariableAggregation.ONLY_FIRST_REPLICA`. - value: A per-replica value with one value per replica. - destinations: A mirrored variable, a per-replica tensor, a device string, - or list of device strings. The return value will be copied to all - destination devices (or all the devices where the `destinations` value - resides). To perform an all-reduction, pass `value` to `destinations`. - - Returns: - A value mirrored to `destinations`. - """ - # TODO(josh11b): More docstring - # TODO(josh11b): Return an unwrapped value if colocate_with is a - # single device. - _require_cross_replica_context(self) - assert aggregation in [ - variable_scope.VariableAggregation.SUM, - variable_scope.VariableAggregation.MEAN, - variable_scope.VariableAggregation.ONLY_FIRST_REPLICA - ] - return self._reduce(aggregation, value, destinations) - - def _reduce(self, aggregation, value, destinations): - raise NotImplementedError("must be implemented in descendants") - - def batch_reduce(self, aggregation, value_destination_pairs): - """Combine multiple `reduce` calls into one for faster execution. - - Args: - aggregation: Indicates how a variable will be aggregated. Accepted values - are `tf.VariableAggregation.SUM`, `tf.VariableAggregation.MEAN`, - `tf.VariableAggregation.ONLY_FIRST_REPLICA`. - value_destination_pairs: A sequence of (value, destinations) - pairs. See `reduce()` for a description. - - Returns: - A list of mirrored values, one per pair in `value_destination_pairs`. - """ - # TODO(josh11b): More docstring - _require_cross_replica_context(self) - assert aggregation in [ - variable_scope.VariableAggregation.SUM, - variable_scope.VariableAggregation.MEAN, - variable_scope.VariableAggregation.ONLY_FIRST_REPLICA - ] - return self._batch_reduce(aggregation, value_destination_pairs) - - def _batch_reduce(self, aggregation, value_destination_pairs): - return [ - self.reduce(aggregation, t, destinations=v) - for t, v in value_destination_pairs - ] - - def update(self, var, fn, *args, **kwargs): - """Run `fn` to update `var` using inputs mirrored to the same devices. - - If `var` is mirrored across multiple devices, then this implements - logic like: - - ``` - results = {} - for device, v in var: - with tf.device(device): - # *args and **kwargs will be unwrapped if they are mirrored. - results[device] = fn(v, *args, **kwargs) - return merged(results) - ``` - - Otherwise this returns `fn(var, *args, **kwargs)` colocated with `var`. - - Neither `*args` nor `**kwargs` may contain per-replica values. - If they contain mirrored values, they will be unwrapped before - calling `fn`. - - Args: - var: Variable, possibly mirrored to multiple devices, to operate on. - fn: Function to call. Should take the variable as the first argument. - *args: Additional positional arguments to pass to `fn()`. - **kwargs: Keyword arguments to pass to `fn()`. If "grouped=False" is - specified, the return value will be unwrapped. - - Returns: - By default, the merged return value of `fn` across all replicas. The - merged result has dependencies to make sure that if it is evaluated at - all, the side effects (updates) will happen on every replica. If instead - "grouped=False" is specified, this function will return a nest of lists - where each list has an element per replica, and the caller is responsible - for ensuring all elements are executed. - """ - _require_cross_replica_context(self) - options = {"grouped": kwargs.pop("grouped", True)} - return self._update(var, options, fn, *args, **kwargs) - - def _update(self, var, options, fn, *args, **kwargs): - raise NotImplementedError("must be implemented in descendants") - - def update_non_slot(self, colocate_with, fn, *args, **kwargs): - """Runs `fn(*args, **kwargs)` on `colocate_with` devices. - - Args: - colocate_with: The return value of `non_slot_devices()`. - fn: Function to execute. - *args: Positional arguments to pass to `fn()`. - **kwargs: Keyword arguments to pass to `fn()`. If "grouped=False" is - specified, the return value will be unwrapped and the caller is - responsible for ensuring all elements are executed. - - Returns: - Return value of `fn`, possibly merged across devices. - """ - _require_cross_replica_context(self) - options = {"grouped": kwargs.pop("grouped", True)} - return self._update_non_slot(colocate_with, options, fn, *args, **kwargs) - - def _update_non_slot(self, colocate_with, options, fn, *args, **kwargs): - raise NotImplementedError("must be implemented in descendants") - - def unwrap(self, value): - """Returns the list of all per-replica values contained in `value`. - - Args: - value: A value returned by `call_for_each_replica()` or a variable - created in `scope()`. - - Returns: - A list of values contained in `value`. If `value` represents a single - value, this returns `[value].` - """ - return self._unwrap(value) - - def value_container(self, value): - """Returns the container that this per-replica `value` belongs to. - - Args: - value: A value returned by `call_for_each_replica()` or a variable - created in `scope()`. - - Returns: - A container that `value` belongs to. - If value does not belong to any container (including the case of - container having been destroyed), returns the value itself. - `value in unwrap(value_container(value))` will always be true. - """ - raise NotImplementedError("must be implemented in descendants") - - def _unwrap(self, distributed_value): - raise NotImplementedError("must be implemented in descendants") - - def group(self, value, name=None): - """Shortcut for `tf.group(distribution.unwrap(value))`.""" - value = nest.flatten(self.unwrap(value)) - - if len(value) != 1 or name is not None: - return control_flow_ops.group(value, name=name) - # Special handling for the common case of one op. - v, = value - if hasattr(v, "op"): - v = v.op - return v - - @property - def require_static_shapes(self): - return self._require_static_shapes - - @property - def num_replicas(self): - """Returns number of replicas, for purposes of averaging across replicas. - - DEPRECATED: use `num_replicas_in_sync` instead. - """ - raise NotImplementedError("must be implemented in descendants") - - @property - def num_replicas_in_sync(self): - """Returns number of replicas over which gradients are aggregated.""" - raise NotImplementedError("must be implemented in descendants") - - @property - def worker_devices(self): - """Returns the list of devices used to run `call_for_each_replica()` calls. - """ - # TODO(josh11b): More docstring - raise NotImplementedError("must be implemented in descendants") - - @property - def parameter_devices(self): - """Returns the list of devices used for variable and `update` placement.""" - # TODO(josh11b): More docstring - raise NotImplementedError("must be implemented in descendants") - - def non_slot_devices(self, var_list): - """Device(s) for non-slot variables. - - Create variables on these devices in a - `with colocate_vars_with(non_slot_devices(...)):` block. - Update those using `update_non_slot()`. - - Args: - var_list: The list of variables being optimized, needed with the - default `DistributionStrategy`. - """ - raise NotImplementedError("must be implemented in descendants") - - @property - def worker_device_index(self): - """An object mapping worker device to an id. - - This might be passed as an argument to `call_for_each_replica()`, as in: - - ``` - with distribution_strategy.scope(): - - def fn(device_id): - # device_id is an integer. `fn` is being executed on device: - # distribution_strategy.worker_devices[device_id]. - - distribution_strategy.call_for_each_replica( - fn, distribution_strategy.worker_device_index) - ``` - - Returns: - An index object, or the integer 0 if there is only a single replica. - """ - _require_cross_replica_context(self) - return self._worker_device_index() - - def _worker_device_index(self): - raise NotImplementedError("must be implemented in descendants") - - @property - def between_graph(self): - """Whether the strategy uses between-graph replication or not. - - This is expected to return a constant value that will not be changed - throughout its life cycle. - """ - raise NotImplementedError("must be implemented in descendants") - - def configure(self, - session_config=None, - cluster_spec=None, - task_type=None, - task_id=None): - """Configures the strategy class.""" - del session_config, cluster_spec, task_type, task_id - - @property - def should_init(self): - """Whether initialization is needed.""" - raise NotImplementedError("must be implemented in descendants") - - @property - def should_checkpoint(self): - """Whether checkpointing is needed.""" - raise NotImplementedError("must be implemented in descendants") - - @property - def should_save_summary(self): - """Whether saving summaries is needed.""" - raise NotImplementedError("must be implemented in descendants") - - -# A note about the difference between the context managers -# `ReplicaContext` (defined here) and `_CurrentDistributionContext` -# (defined above) used by `DistributionStrategy.scope()`: -# -# * a ReplicaContext is only present during a `call_for_each_replica()` -# call (except during a `merge_run` call) and in such a scope it -# will be returned by calls to `get_replica_context()`. Implementers of new -# DistributionStrategy descendants will frequently also need to -# define a descendant of ReplicaContext, and are responsible for -# entering and exiting this context. -# -# * DistributionStrategy.scope() sets up a variable_creator scope that -# changes variable creation calls (e.g. to make mirrored -# variables). This is intended as an outer scope that users enter once -# around their model creation and graph definition. There is no -# anticipated need to define descendants of _CurrentDistributionContext. -# It sets the current DistributionStrategy for purposes of -# `get_distribution_strategy()` and `has_distribution_strategy()` -# and switches the thread mode to a "cross-replica context". -class ReplicaContext(object): - """DistributionStrategy API inside a `call_for_each_replica()` call.""" - - def __init__(self, distribution_strategy, replica_id): - self._distribution_strategy = distribution_strategy - self._thread_context = distribution_strategy_context._InReplicaThreadMode( # pylint: disable=protected-access - self) - self._replica_id = replica_id - - def __enter__(self): - _push_per_thread_mode(self._thread_context) - - def __exit__(self, exception_type, exception_value, traceback): - _pop_per_thread_mode() - - def merge_call(self, merge_fn, *args, **kwargs): - """Merge args across replicas and run `merge_fn` in a cross-replica context. - - This allows communication and coordination when there are multiple calls - to a model function triggered by a call to - `distribution.call_for_each_replica(model_fn, ...)`. - - See `MirroredDistribution.call_for_each_replica()` for an explanation. - - Otherwise, this is equivalent to: - - ``` - distribution = get_distribution_strategy() - with cross-replica-context(distribution): - return merge_fn(distribution, *args, **kwargs) - ``` - - Args: - merge_fn: function that joins arguments from threads that are given as - PerReplica. It accepts `DistributionStrategy` object as the first - argument. - args: List or tuple with positional per-thread arguments for `merge_fn` - kwargs: Dict with keyword per-thread arguments for `merge_fn`. - - Returns: - The return value of `merge_fn`, except for `PerReplica` values which are - unpacked. - """ - require_replica_context(self) - # Handle old *args, **kwargs, and new args=(...), kwargs={...}, to - # allow transition. - a = kwargs.pop("args", None) - if a is not None: - if args: - raise ValueError( - "Can't pass *args and args=... to merge_call") - args = a - k = kwargs.pop("kwargs", None) - if k is not None: - if kwargs: - raise ValueError( - "Can't pass **kwargs and kwargs=... to merge_call") - kwargs = k - return self._merge_call(merge_fn, args, kwargs) - - def _merge_call(self, merge_fn, args, kwargs): - """Default implementation for single replica.""" - _push_per_thread_mode( # thread-local, so not needed with multiple threads - distribution_strategy_context._CrossReplicaThreadMode( # pylint: disable=protected-access - self._distribution_strategy)) - try: - return merge_fn(self._distribution_strategy, *args, **kwargs) - finally: - _pop_per_thread_mode() - - @property - def num_replicas(self): - """Returns number of replicas, for purposes of averaging across replicas.""" - return self._distribution_strategy.num_replicas - - @property - def num_replicas_in_sync(self): - """Returns number of replicas over which gradients are aggregated.""" - return self._distribution_strategy.num_replicas_in_sync - - @property - def replica_id(self): - """Which replica is being defined, a number from 0 to `num_replicas - 1`.""" - require_replica_context(self) - return self._replica_id - - @property - def distribution_strategy(self): - """The current `DistributionStrategy` object.""" - return self._distribution_strategy - - @property - def device(self): - """BEING DELETED: use .devices instead.""" - raise RuntimeError("Use .devices instead") - - @property - def devices(self): - """The devices this replica is to be executed on, as a list of strings.""" - require_replica_context(self) - return [device_util.current()] - - # TODO(josh11b): Implement `start_all_reduce(method, t)` for efficient - # all-reduce. It would return a function returning the result of reducing `t` - # across all replicas. The caller would wait to call this function until they - # needed the reduce result, allowing an efficient implementation: - # * With eager execution, the reduction could be performed asynchronously - # in the background, not blocking until the result was needed. - # * When constructing a graph, it could batch up all reduction requests up - # to that point that the first result is needed. Most likely this can be - # implemented in terms of `merge_call()` and `batch_reduce()`. - -# ------------------------------------------------------------------------------ - - -class _DefaultDistributionStrategy(DistributionStrategy): - """Default `DistributionStrategy` if none is explicitly selected.""" - - def scope(self): - """Context manager setting a variable creator and `self` as current.""" - if distribution_strategy_context.has_distribution_strategy(): - raise RuntimeError("Must not nest DistributionStrategy scopes.") - - def creator(next_creator, *args, **kwargs): - _require_distribution_strategy_scope(self) - return next_creator(*args, **kwargs) - - return _CurrentDistributionContext( - self, variable_scope.variable_creator_scope(creator)) - - def colocate_vars_with(self, colocate_with_variable): - """Does not require `self.scope`.""" - _require_distribution_strategy_scope(self) - return ops.colocate_with(colocate_with_variable) - - def distribute_dataset(self, dataset_fn): - return self._call_dataset_fn(dataset_fn) - - def _broadcast(self, tensor, destinations): - if destinations is None: - return tensor - else: - raise NotImplementedError("TODO") - - def _call_for_each_replica(self, fn, args, kwargs): - with ReplicaContext(self, replica_id=0): - return fn(*args, **kwargs) - - def _reduce(self, aggregation, value, destinations): - # TODO(josh11b): Use destinations? - del aggregation, destinations - return value - - def _update(self, var, options, fn, *args, **kwargs): - # The implementations of _update() and _update_non_slot() are identical - # except _update() passes `var` as the first argument to `fn()`. - return self._update_non_slot(var, options, fn, var, *args, **kwargs) - - def _update_non_slot(self, colocate_with, options, fn, *args, **kwargs): - should_group = options.pop("grouped") - assert not options # Validate that we are processing all of the options. - # TODO(josh11b): Figure out what we should be passing to UpdateContext() - # once that value is used for something. - with ops.colocate_with(colocate_with), UpdateContext(colocate_with): - result = fn(*args, **kwargs) - if should_group: - return result - else: - return nest.map_structure(self._unwrap, result) - - def read_var(self, replica_local_var): - return array_ops.identity(replica_local_var) - - def _unwrap(self, distributed_value): - return [distributed_value] - - def value_container(self, value): - return value - - @property - def num_replicas(self): - return 1 - - @property - def num_replicas_in_sync(self): - return 1 - - @property - def worker_devices(self): - raise RuntimeError( - "worker_devices() method unsupported by _DefaultDistributionStrategy.") - - @property - def parameter_devices(self): - raise RuntimeError("parameter_devices() method unsupported by " - "_DefaultDistributionStrategy.") - - def non_slot_devices(self, var_list): - return min(var_list, key=lambda x: x.name) - - def _worker_device_index(self): - raise RuntimeError("worker_device_index() method unsupported by " - "_DefaultDistributionStrategy.") - - -# ------------------------------------------------------------------------------ -# We haven't yet implemented deserialization for DistributedVariables. -# So here we catch any attempts to deserialize variables -# when using distribution strategies. -# pylint: disable=protected-access -_original_from_proto = resource_variable_ops._from_proto_fn - - -def _from_proto_fn(v, import_scope=None): - if distribution_strategy_context.has_distribution_strategy(): - raise NotImplementedError( - "Deserialization of variables is not yet supported when using" - "distributed strategies.") - else: - return _original_from_proto(v, import_scope=import_scope) - -resource_variable_ops._from_proto_fn = _from_proto_fn -# pylint: enable=protected-access - - -#------------------------------------------------------------------------------- -# Shorthand for some methods from distribution_strategy_context. -_push_per_thread_mode = distribution_strategy_context._push_per_thread_mode # pylint: disable=protected-access -_get_per_thread_mode = distribution_strategy_context._get_per_thread_mode # pylint: disable=protected-access -_pop_per_thread_mode = distribution_strategy_context._pop_per_thread_mode # pylint: disable=protected-access +# pylint: disable=wildcard-import +from tensorflow.python.distribute.distribute_lib import * diff --git a/tensorflow/python/training/distribution_strategy_context.py b/tensorflow/python/training/distribution_strategy_context.py index 278f35b97e..7391bf3b22 100644 --- a/tensorflow/python/training/distribution_strategy_context.py +++ b/tensorflow/python/training/distribution_strategy_context.py @@ -12,195 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Utility to get distribution strategy related contexts.""" +"""Deprecated, please use ../distribute/distribution_strategy_context.py.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.python.framework import ops -from tensorflow.python.util.lazy_loader import LazyLoader - - -# There is a circular dependency between this and `distribute` module. So we -# load it lazily to workaround this. -distribute_lib = LazyLoader( - "distribute_lib", globals(), - "tensorflow.python.training.distribute") - -# ------------------------------------------------------------------------------ -# Internal API for setting the current thread mode as being either in a -# replica or cross-replica context for a particular distribution strategy. - - -class _ThreadMode(object): - - def __init__(self, dist, cross, replica): - self.distribution_strategy = dist - self.cross_replica_context = cross - self.replica_context = replica - - -class _CrossReplicaThreadMode(_ThreadMode): - - def __init__(self, distribution_strategy): - _ThreadMode.__init__( - self, distribution_strategy, distribution_strategy, None) - - -class _InReplicaThreadMode(_ThreadMode): - - def __init__(self, replica_ctx): - _ThreadMode.__init__( - self, replica_ctx.distribution_strategy, None, replica_ctx) - - -def _push_per_thread_mode(context): - ops.get_default_graph()._distribution_strategy_stack.append(context) # pylint: disable=protected-access - - -def _pop_per_thread_mode(): - ops.get_default_graph()._distribution_strategy_stack.pop(-1) # pylint: disable=protected-access - - -class _DefaultReplicaThreadMode(_ThreadMode): - """Type of default value returned by `_get_per_thread_mode()`. - - Used when the thread-local stack is empty. - """ - - def __init__(self): - _ThreadMode.__init__(self, _get_default_distribution_strategy(), None, - _get_default_replica_context()) - - -def _get_per_thread_mode(): - try: - return ops.get_default_graph()._distribution_strategy_stack[-1] # pylint: disable=protected-access - except (AttributeError, IndexError): - return _get_default_replica_mode() - - -# ------------------------------------------------------------------------------ -# Public API for accessing the current thread mode - - -def get_replica_context(): - """Returns the current ReplicaContext or None if in a cross-replica context. - - Note that execution: - - 1. starts in the default (single-replica) replica context (this function - will return the default ReplicaContext object); - 2. switches to cross-replica context (in which case this will return - None) when entering a `with DistributionStrategy.scope():` block; - 3. switches to a (non-default) replica context inside - `call_for_each_replica(fn, ...)`; - 4. if `fn` calls `get_replica_context()->merge_call(merge_fn, ...)`, then - inside `merge_fn` you are back in the cross-replica context (and again - this function will return None). - - Note that you can also go directly from step 1 to 4 to switch to a - cross-replica context for the default `DistributionStrategy`. You may - also switch from the cross-replica context of 4 to a replica context by - calling `call_for_each_replica()`, jumping back to step 3. - - Most `DistributionStrategy` methods may only be executed in - a cross-replica context, in a replica context you should use the - `ReplicaContext` API instead. - - Returns: - The current `ReplicaContext` object when in a replica context scope, - else None. - - Exactly one of `get_replica_context()` and `get_cross_replica_context()` - will return None in a particular block. - """ - return _get_per_thread_mode().replica_context - - -def get_cross_replica_context(): - """Returns the current DistributionStrategy if in a cross-replica context. - - Note that execution: - - 1. starts in the default (single-replica) replica context; - 2. switches to cross-replica context when entering a - `with DistributionStrategy.scope():` block; - 3. switches to a (non-default) replica context inside - `call_for_each_replica(fn, ...)`; - 4. if `fn` calls `get_replica_context()->merge_call(merge_fn, ...)`, then - inside `merge_fn` you are back in the cross-replica context. - - Note that you can also go directly from step 1 to 4 to switch to a - cross-replica context for the default `DistributionStrategy`. You may - also switch from the cross-replica context of 4 to a replica context by - calling `call_for_each_replica()`, jumping back to step 3. - - Most `DistributionStrategy` methods may only be executed in - a cross-replica context. - - Returns: - Returns the current `DistributionStrategy` object in a cross-replica - context, or None. - - Exactly one of `get_replica_context()` and `get_cross_replica_context()` - will return None in a particular block. - """ - return _get_per_thread_mode().cross_replica_context - - -def get_distribution_strategy(): - """Returns the current `DistributionStrategy` object. - - Prefer to use `get_replica_context()` or `get_cross_replica_context()` - instead when possible. - - Returns: - A `DistributionStrategy` object. Inside a - `with distribution_strategy.scope()` block, it returns - `distribution_strategy`, otherwise it returns the default - (single-replica) `DistributionStrategy` object. - """ - return _get_per_thread_mode().distribution_strategy - - -def has_distribution_strategy(): - """Return if there is a current non-default `DistributionStrategy`. - - Returns: - True if inside a `with distribution_strategy.scope():`. - """ - return get_distribution_strategy() is not _get_default_distribution_strategy() - - -# ------------------------------------------------------------------------------ -# Defaults that are used when no distribution strategy is explicitly created. -# We create them lazily in a function so that we can workaround the circular -# dependency on distribute_lib. See lazy loader at the top of this file. - -_defaults = { - "distribution_strategy": None, - "replica_context": None, - "replica_mode": None -} - - -def _get_default_distribution_strategy(): - if _defaults["distribution_strategy"] is None: - _defaults["distribution_strategy"] = ( - distribute_lib._DefaultDistributionStrategy()) # pylint: disable=protected-access - return _defaults["distribution_strategy"] - - -def _get_default_replica_context(): - if _defaults["replica_context"] is None: - _defaults["replica_context"] = distribute_lib.ReplicaContext( - _get_default_distribution_strategy(), replica_id=0) - return _defaults["replica_context"] - - -def _get_default_replica_mode(): - if _defaults["replica_mode"] is None: - _defaults["replica_mode"] = _DefaultReplicaThreadMode() - return _defaults["replica_mode"] +# pylint: disable=wildcard-import +from tensorflow.python.distribute.distribution_strategy_context import * diff --git a/tensorflow/python/training/evaluation.py b/tensorflow/python/training/evaluation.py index 2c4eb02d53..a10178f8cf 100644 --- a/tensorflow/python/training/evaluation.py +++ b/tensorflow/python/training/evaluation.py @@ -230,7 +230,7 @@ def _evaluate_once(checkpoint_path, hooks = list(hooks or []) if eval_ops is not None: - if any([isinstance(h, _MultiStepStopAfterNEvalsHook) for h in hooks]): + if any(isinstance(h, _MultiStepStopAfterNEvalsHook) for h in hooks): steps_per_run_variable = \ basic_session_run_hooks.get_or_create_steps_per_run_variable() update_eval_step = state_ops.assign_add( diff --git a/tensorflow/python/training/ftrl.py b/tensorflow/python/training/ftrl.py index 2fafc9a2d8..a2ef3c76b4 100644 --- a/tensorflow/python/training/ftrl.py +++ b/tensorflow/python/training/ftrl.py @@ -25,7 +25,7 @@ from tensorflow.python.training import training_ops from tensorflow.python.util.tf_export import tf_export -@tf_export("train.FtrlOptimizer") +@tf_export(v1=["train.FtrlOptimizer"]) class FtrlOptimizer(optimizer.Optimizer): """Optimizer that implements the FTRL algorithm. diff --git a/tensorflow/python/training/ftrl_test.py b/tensorflow/python/training/ftrl_test.py index 15c50bc878..39b299c64a 100644 --- a/tensorflow/python/training/ftrl_test.py +++ b/tensorflow/python/training/ftrl_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import embedding_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import resource_variable_ops @@ -54,7 +55,7 @@ class FtrlOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose([0.0, 0.0], v0_val) self.assertAllClose([0.0, 0.0], v1_val) @@ -62,18 +63,21 @@ class FtrlOptimizerTest(test.TestCase): for _ in range(3): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType( np.array([-2.60260963, -4.29698515]), v0_val) self.assertAllCloseAccordingToType( np.array([-0.28432083, -0.56694895]), v1_val) + @test_util.run_deprecated_v1 def testFtrlWithoutRegularization(self): self.doTestFtrlwithoutRegularization(use_resource=False) + @test_util.run_deprecated_v1 def testResourceFtrlWithoutRegularization(self): self.doTestFtrlwithoutRegularization(use_resource=True) + @test_util.run_deprecated_v1 def testFtrlwithoutRegularization2(self): for dtype in [dtypes.half, dtypes.float32]: with self.cached_session() as sess: @@ -90,19 +94,20 @@ class FtrlOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) self.assertAllCloseAccordingToType([4.0, 3.0], v1_val) # Run 3 steps FTRL for _ in range(3): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType( np.array([-2.55607247, -3.98729396]), v0_val) self.assertAllCloseAccordingToType( np.array([-0.28232238, -0.56096673]), v1_val) + @test_util.run_deprecated_v1 def testMinimizeSparseResourceVariable(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -113,12 +118,15 @@ class FtrlOptimizerTest(test.TestCase): sgd_op = ftrl.FtrlOptimizer(1.0).minimize(loss) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([[1.0, 2.0]], var0.eval()) + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) # Run 1 step of sgd sgd_op.run() # Validate updated params - self.assertAllCloseAccordingToType([[0, 1]], var0.eval(), atol=0.01) + self.assertAllCloseAccordingToType([[0, 1]], + self.evaluate(var0), + atol=0.01) + @test_util.run_deprecated_v1 def testFtrlWithL1(self): for dtype in [dtypes.half, dtypes.float32]: with self.cached_session() as sess: @@ -135,19 +143,20 @@ class FtrlOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) self.assertAllCloseAccordingToType([4.0, 3.0], v1_val) # Run 10 steps FTRL for _ in range(10): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType( np.array([-7.66718769, -10.91273689]), v0_val) self.assertAllCloseAccordingToType( np.array([-0.93460727, -1.86147261]), v1_val) + @test_util.run_deprecated_v1 def testFtrlWithL1_L2(self): for dtype in [dtypes.half, dtypes.float32]: with self.cached_session() as sess: @@ -164,7 +173,7 @@ class FtrlOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) self.assertAllCloseAccordingToType([4.0, 3.0], v1_val) @@ -172,12 +181,13 @@ class FtrlOptimizerTest(test.TestCase): for _ in range(10): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType( np.array([-0.24059935, -0.46829352]), v0_val) self.assertAllCloseAccordingToType( np.array([-0.02406147, -0.04830509]), v1_val) + @test_util.run_deprecated_v1 def testFtrlWithL1_L2_L2Shrinkage(self): """Test the new FTRL op with support for l2 shrinkage. @@ -201,7 +211,7 @@ class FtrlOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) self.assertAllCloseAccordingToType([4.0, 3.0], v1_val) @@ -209,12 +219,13 @@ class FtrlOptimizerTest(test.TestCase): for _ in range(10): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType( np.array([-0.22578995, -0.44345796]), v0_val) self.assertAllCloseAccordingToType( np.array([-0.14378493, -0.13229476]), v1_val) + @test_util.run_deprecated_v1 def testFtrlWithL1_L2_L2ShrinkageSparse(self): """Tests the new FTRL op with support for l2 shrinkage on sparse grads.""" for dtype in [dtypes.half, dtypes.float32]: @@ -237,7 +248,7 @@ class FtrlOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType([[1.0], [2.0]], v0_val) self.assertAllCloseAccordingToType([[4.0], [3.0]], v1_val) @@ -245,10 +256,11 @@ class FtrlOptimizerTest(test.TestCase): for _ in range(10): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType([[-0.22578995], [2.]], v0_val) self.assertAllCloseAccordingToType([[4.], [-0.13229476]], v1_val) + @test_util.run_deprecated_v1 def testFtrlWithL2ShrinkageDoesNotChangeLrSchedule(self): """Verifies that l2 shrinkage in FTRL does not change lr schedule.""" for dtype in [dtypes.half, dtypes.float32]: @@ -273,7 +285,7 @@ class FtrlOptimizerTest(test.TestCase): update1 = opt1.apply_gradients([(grads1, var1)]) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllCloseAccordingToType([1.0, 2.0], v0_val) self.assertAllCloseAccordingToType([1.0, 2.0], v1_val) @@ -282,12 +294,12 @@ class FtrlOptimizerTest(test.TestCase): update0.run() update1.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) # var0 is experiencing L2 shrinkage so it should be smaller than var1 # in magnitude. self.assertTrue((v0_val**2 < v1_val**2).all()) - accum0 = list(sess.run(opt0._slots)["accum"].values())[0] - accum1 = list(sess.run(opt1._slots)["accum"].values())[0] + accum0 = list(self.evaluate(opt0._slots)["accum"].values())[0] + accum1 = list(self.evaluate(opt1._slots)["accum"].values())[0] # L2 shrinkage should not change how we update grad accumulator. self.assertAllCloseAccordingToType(accum0, accum1) @@ -311,7 +323,7 @@ class FtrlOptimizerTest(test.TestCase): variables.global_variables_initializer().run() sess = ops.get_default_session() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) if is_sparse: self.assertAllCloseAccordingToType([[0.0], [0.0]], v0_val) self.assertAllCloseAccordingToType([[0.0], [0.0]], v1_val) @@ -323,7 +335,7 @@ class FtrlOptimizerTest(test.TestCase): for _ in range(steps): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) return v0_val, v1_val # When variables are initialized with Zero, FTRL-Proximal has two properties: @@ -333,6 +345,7 @@ class FtrlOptimizerTest(test.TestCase): # with Adagrad. # So, basing on these two properties, we test if our implementation of # FTRL-Proximal performs same updates as Adagrad or GradientDescent. + @test_util.run_deprecated_v1 def testEquivAdagradwithoutRegularization(self): for dtype in [dtypes.half, dtypes.float32]: with self.cached_session(): @@ -353,6 +366,7 @@ class FtrlOptimizerTest(test.TestCase): self.assertAllCloseAccordingToType(val0, val2) self.assertAllCloseAccordingToType(val1, val3) + @test_util.run_deprecated_v1 def testEquivSparseAdagradwithoutRegularization(self): for dtype in [dtypes.half, dtypes.float32]: with self.cached_session(): @@ -376,6 +390,7 @@ class FtrlOptimizerTest(test.TestCase): self.assertAllCloseAccordingToType(val0, val2) self.assertAllCloseAccordingToType(val1, val3) + @test_util.run_deprecated_v1 def testEquivSparseGradientDescentwithoutRegularization(self): for dtype in [dtypes.half, dtypes.float32]: with self.cached_session(): @@ -399,6 +414,7 @@ class FtrlOptimizerTest(test.TestCase): self.assertAllCloseAccordingToType(val0, val2) self.assertAllCloseAccordingToType(val1, val3) + @test_util.run_deprecated_v1 def testEquivGradientDescentwithoutRegularization(self): for dtype in [dtypes.half, dtypes.float32]: with self.cached_session(): diff --git a/tensorflow/python/training/gradient_descent.py b/tensorflow/python/training/gradient_descent.py index ef50f6315d..1a527345ef 100644 --- a/tensorflow/python/training/gradient_descent.py +++ b/tensorflow/python/training/gradient_descent.py @@ -26,7 +26,7 @@ from tensorflow.python.training import training_ops from tensorflow.python.util.tf_export import tf_export -@tf_export("train.GradientDescentOptimizer") +@tf_export(v1=["train.GradientDescentOptimizer"]) class GradientDescentOptimizer(optimizer.Optimizer): """Optimizer that implements the gradient descent algorithm. """ diff --git a/tensorflow/python/training/gradient_descent_test.py b/tensorflow/python/training/gradient_descent_test.py index 1ddea598e5..5a6c5cfa74 100644 --- a/tensorflow/python/training/gradient_descent_test.py +++ b/tensorflow/python/training/gradient_descent_test.py @@ -24,6 +24,7 @@ from tensorflow.python.eager import function from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import embedding_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import resource_variable_ops @@ -35,6 +36,7 @@ from tensorflow.python.training import gradient_descent class GradientDescentOptimizerTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -47,17 +49,18 @@ class GradientDescentOptimizerTest(test.TestCase): zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([3.0, 4.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0, 4.0], self.evaluate(var1)) # Run 1 step of sgd sgd_op.run() # Validate updated params self.assertAllCloseAccordingToType([1.0 - 3.0 * 0.1, 2.0 - 3.0 * 0.1], - var0.eval()) + self.evaluate(var0)) self.assertAllCloseAccordingToType([3.0 - 3.0 * 0.01, 4.0 - 3.0 * 0.01], - var1.eval()) + self.evaluate(var1)) self.assertEqual(0, len(optimizer.variables())) + @test_util.run_deprecated_v1 def testBasicResourceVariable(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -73,16 +76,17 @@ class GradientDescentOptimizerTest(test.TestCase): # a long-term solution for this. resources.initialize_resources([var0, var1]).run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([3.0, 4.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0, 4.0], self.evaluate(var1)) # Run 1 step of sgd sgd_op.run() # Validate updated params self.assertAllCloseAccordingToType([1.0 - 3.0 * 0.1, 2.0 - 3.0 * 0.1], - var0.eval()) + self.evaluate(var0)) self.assertAllCloseAccordingToType([3.0 - 3.0 * 0.01, 4.0 - 3.0 * 0.01], - var1.eval()) + self.evaluate(var1)) + @test_util.run_deprecated_v1 def testBasicCallableParams(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -99,16 +103,17 @@ class GradientDescentOptimizerTest(test.TestCase): # a long-term solution for this. resources.initialize_resources([var0, var1]).run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([3.0, 4.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0, 4.0], self.evaluate(var1)) # Run 1 step of sgd sgd_op.run() # Validate updated params self.assertAllCloseAccordingToType([1.0 - 3.0 * 0.1, 2.0 - 3.0 * 0.1], - var0.eval()) + self.evaluate(var0)) self.assertAllCloseAccordingToType([3.0 - 3.0 * 0.01, 4.0 - 3.0 * 0.01], - var1.eval()) + self.evaluate(var1)) + @test_util.run_deprecated_v1 def testMinimizeResourceVariable(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -124,17 +129,18 @@ class GradientDescentOptimizerTest(test.TestCase): # a long-term solution for this. resources.initialize_resources([var0, var1]).run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([[1.0, 2.0]], var0.eval()) - self.assertAllCloseAccordingToType([3.0], var1.eval()) + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0], self.evaluate(var1)) # Run 1 step of sgd sgd_op.run() # Validate updated params np_pred = 1.0 * 4.0 + 2.0 * 5.0 + 3.0 np_grad = 2 * np_pred self.assertAllCloseAccordingToType( - [[1.0 - np_grad * 4.0, 2.0 - np_grad * 5.0]], var0.eval()) - self.assertAllCloseAccordingToType([3.0 - np_grad], var1.eval()) + [[1.0 - np_grad * 4.0, 2.0 - np_grad * 5.0]], self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0 - np_grad], self.evaluate(var1)) + @test_util.run_deprecated_v1 def testMinimizeSparseResourceVariable(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -151,17 +157,18 @@ class GradientDescentOptimizerTest(test.TestCase): # a long-term solution for this. variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([[1.0, 2.0]], var0.eval()) - self.assertAllCloseAccordingToType([3.0], var1.eval()) + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0], self.evaluate(var1)) # Run 1 step of sgd sgd_op.run() # Validate updated params np_pred = 1.0 * 4.0 + 2.0 * 5.0 + 3.0 np_grad = 2 * np_pred self.assertAllCloseAccordingToType( - [[1.0 - np_grad * 4.0, 2.0 - np_grad * 5.0]], var0.eval()) - self.assertAllCloseAccordingToType([3.0 - np_grad], var1.eval()) + [[1.0 - np_grad * 4.0, 2.0 - np_grad * 5.0]], self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0 - np_grad], self.evaluate(var1)) + @test_util.run_deprecated_v1 def testTensorLearningRate(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -174,16 +181,17 @@ class GradientDescentOptimizerTest(test.TestCase): lrate).apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([3.0, 4.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0, 4.0], self.evaluate(var1)) # Run 1 step of sgd sgd_op.run() # Validate updated params self.assertAllCloseAccordingToType([1.0 - 3.0 * 0.1, 2.0 - 3.0 * 0.1], - var0.eval()) + self.evaluate(var0)) self.assertAllCloseAccordingToType([3.0 - 3.0 * 0.01, 4.0 - 3.0 * 0.01], - var1.eval()) + self.evaluate(var1)) + @test_util.run_deprecated_v1 def testGradWrtRef(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -193,8 +201,9 @@ class GradientDescentOptimizerTest(test.TestCase): grads_and_vars = opt.compute_gradients(vars_[0] + vars_[1], vars_) variables.global_variables_initializer().run() for grad, _ in grads_and_vars: - self.assertAllCloseAccordingToType([1.0], grad.eval()) + self.assertAllCloseAccordingToType([1.0], self.evaluate(grad)) + @test_util.run_deprecated_v1 def testWithGlobalStep(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -207,17 +216,18 @@ class GradientDescentOptimizerTest(test.TestCase): zip([grads0, grads1], [var0, var1]), global_step=global_step) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([1.0, 2.0], var0.eval()) - self.assertAllCloseAccordingToType([3.0, 4.0], var1.eval()) + self.assertAllCloseAccordingToType([1.0, 2.0], self.evaluate(var0)) + self.assertAllCloseAccordingToType([3.0, 4.0], self.evaluate(var1)) # Run 1 step of sgd sgd_op.run() # Validate updated params and global_step self.assertAllCloseAccordingToType([1.0 - 3.0 * 0.1, 2.0 - 3.0 * 0.1], - var0.eval()) + self.evaluate(var0)) self.assertAllCloseAccordingToType([3.0 - 3.0 * 0.01, 4.0 - 3.0 * 0.01], - var1.eval()) - self.assertAllCloseAccordingToType(1, global_step.eval()) + self.evaluate(var1)) + self.assertAllCloseAccordingToType(1, self.evaluate(global_step)) + @test_util.run_deprecated_v1 def testSparseBasic(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -237,15 +247,15 @@ class GradientDescentOptimizerTest(test.TestCase): zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([[1.0], [2.0]], var0.eval()) - self.assertAllCloseAccordingToType([[3.0], [4.0]], var1.eval()) + self.assertAllCloseAccordingToType([[1.0], [2.0]], self.evaluate(var0)) + self.assertAllCloseAccordingToType([[3.0], [4.0]], self.evaluate(var1)) # Run 1 step of sgd sgd_op.run() # Validate updated params self.assertAllCloseAccordingToType([[1.0 - 3.0 * 0.1], [2.0]], - var0.eval()) + self.evaluate(var0)) self.assertAllCloseAccordingToType([[3.0], [4.0 - 3.0 * 0.01]], - var1.eval()) + self.evaluate(var1)) def testCapturingInDefunWhileExecutingEagerly(self): with context.eager_mode(): diff --git a/tensorflow/python/training/input_test.py b/tensorflow/python/training/input_test.py index 085b77d1d6..a3d268a017 100644 --- a/tensorflow/python/training/input_test.py +++ b/tensorflow/python/training/input_test.py @@ -28,6 +28,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import sparse_tensor +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables @@ -41,6 +42,7 @@ from tensorflow.python.util import compat class MatchFilenamesOnceTest(test_lib.TestCase): + @test_util.run_deprecated_v1 def test(self): temp_dir = self.get_temp_dir() filenames = [os.path.join(temp_dir, n) for n in os.listdir(temp_dir)] @@ -58,35 +60,41 @@ class MatchFilenamesOnceTest(test_lib.TestCase): one = inp.match_filenames_once(additional[1]) variables.global_variables_initializer().run() variables.local_variables_initializer().run() - self.assertItemsEqual(map(compat.as_bytes, filenames), star.eval()) - self.assertItemsEqual(map(compat.as_bytes, additional), question.eval()) - self.assertItemsEqual([compat.as_bytes(additional[1])], one.eval()) + self.assertItemsEqual( + map(compat.as_bytes, filenames), self.evaluate(star)) + self.assertItemsEqual( + map(compat.as_bytes, additional), self.evaluate(question)) + self.assertItemsEqual([compat.as_bytes(additional[1])], + self.evaluate(one)) class LimitEpochsTest(test_lib.TestCase): + @test_util.run_deprecated_v1 def testNoLimit(self): with self.cached_session(): seven = constant_op.constant(7) seven_forever = inp.limit_epochs(seven) variables.local_variables_initializer().run() for _ in range(100): - self.assertEqual(7, seven_forever.eval()) + self.assertEqual(7, self.evaluate(seven_forever)) + @test_util.run_deprecated_v1 def testLimit(self): with self.cached_session(): love_me = constant_op.constant("Love Me") love_me_two_times = inp.limit_epochs(love_me, num_epochs=2) variables.global_variables_initializer().run() variables.local_variables_initializer().run() - self.assertEqual(b"Love Me", love_me_two_times.eval()) - self.assertEqual(b"Love Me", love_me_two_times.eval()) + self.assertEqual(b"Love Me", self.evaluate(love_me_two_times)) + self.assertEqual(b"Love Me", self.evaluate(love_me_two_times)) with self.assertRaises(errors_impl.OutOfRangeError): - love_me_two_times.eval() + self.evaluate(love_me_two_times) class InputProducerTest(test_lib.TestCase): + @test_util.run_deprecated_v1 def testNoShuffle(self): with self.cached_session(): input_tensor = [[1, 2, 3, 4], @@ -102,14 +110,16 @@ class InputProducerTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() # No randomness, so just see repeated copies of the input. - self.assertAllEqual(input_tensor * num_epochs, dequeue_many.eval()) + self.assertAllEqual(input_tensor * num_epochs, + self.evaluate(dequeue_many)) # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - dequeue.eval() + self.evaluate(dequeue) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testNoShapeInference(self): with self.cached_session(): # Disable shape inference for the input. @@ -127,14 +137,15 @@ class InputProducerTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() # No randomness, so just see repeated copies of the input. - self.assertAllEqual(input_value * num_epochs, dequeue_many.eval()) + self.assertAllEqual(input_value * num_epochs, self.evaluate(dequeue_many)) # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - dequeue.eval() + self.evaluate(dequeue) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testShapeError(self): input_tensor = array_ops.placeholder(dtypes.float32, None) with self.assertRaisesRegexp(ValueError, "fully defined shape"): @@ -143,6 +154,7 @@ class InputProducerTest(test_lib.TestCase): class StringInputProducerTest(test_lib.TestCase): + @test_util.run_deprecated_v1 def testNoShuffle(self): with self.cached_session(): strings = [b"to", b"be", b"or", b"not", b"to", b"be"] @@ -156,15 +168,16 @@ class StringInputProducerTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() # No randomness, so just see repeated copies of the input. - output = dequeue_many.eval() + output = self.evaluate(dequeue_many) self.assertAllEqual(strings * num_epochs, output) # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - dequeue.eval() + self.evaluate(dequeue) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testShuffle(self): with self.cached_session(): strings = [b"a", b"b", b"c"] @@ -184,7 +197,7 @@ class StringInputProducerTest(test_lib.TestCase): for e in expected: frequency[e] = 0 for _ in range(num_epochs): - output = dequeue_many.eval() + output = self.evaluate(dequeue_many) key = b"".join(output) self.assertIn(key, expected) frequency[key] += 1 @@ -200,7 +213,7 @@ class StringInputProducerTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - dequeue.eval() + self.evaluate(dequeue) for thread in threads: thread.join() @@ -210,6 +223,7 @@ class StringInputProducerTest(test_lib.TestCase): with self.assertRaises(ValueError): _ = inp.string_input_producer([]) + @test_util.run_deprecated_v1 def testNullString(self): # Runtime check for empty string list. This is slightly oblique: # The queue runner should die with an assertion error on the null @@ -224,11 +238,12 @@ class StringInputProducerTest(test_lib.TestCase): variables.local_variables_initializer().run() threads = queue_runner_impl.start_queue_runners(coord=coord) with self.assertRaises(errors_impl.OutOfRangeError): - dequeue.eval() + self.evaluate(dequeue) coord.request_stop() for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSharedName(self): with self.cached_session(): strings = [b"to", b"be", b"or", b"not", b"to", b"be"] @@ -237,6 +252,7 @@ class StringInputProducerTest(test_lib.TestCase): self.assertProtoEquals("s: 'SHARED_NAME_XYZ'", queue.queue_ref.op.node_def.attr["shared_name"]) + @test_util.run_deprecated_v1 def testConstructionRace(self): with self.cached_session() as sess: strings = [b"to", b"be", b"or", b"not", b"to", b"be"] @@ -252,13 +268,14 @@ class StringInputProducerTest(test_lib.TestCase): # writing of the `tf.Graph` object. However, many users # write code this way, so we include this test to ensure # that we can support it. - self.assertEquals(string, sess.run(queue.dequeue())) + self.assertEquals(string, self.evaluate(queue.dequeue())) coord.request_stop() coord.join(threads) class RangeInputProducerTest(test_lib.TestCase): + @test_util.run_deprecated_v1 def testNoShuffle(self): with self.cached_session(): num_epochs = 3 @@ -272,15 +289,16 @@ class RangeInputProducerTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() # No randomness, so just see repeated copies of the input. - output = dequeue_many.eval() + output = self.evaluate(dequeue_many) self.assertAllEqual(list(xrange(range_size)) * num_epochs, output) # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - dequeue.eval() + self.evaluate(dequeue) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testShuffle(self): with self.cached_session(): num_epochs = 200 @@ -300,7 +318,7 @@ class RangeInputProducerTest(test_lib.TestCase): for e in expected: frequency[e] = 0 for _ in range(num_epochs): - output = dequeue_many.eval() + output = self.evaluate(dequeue_many) key = 10 * (output[0] + 1) + (output[1] + 1) self.assertIn(key, expected) frequency[key] += 1 @@ -316,10 +334,11 @@ class RangeInputProducerTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - dequeue.eval() + self.evaluate(dequeue) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSharedName(self): with self.cached_session(): range_size = 5 @@ -331,6 +350,7 @@ class RangeInputProducerTest(test_lib.TestCase): class SliceInputProducerTest(test_lib.TestCase): + @test_util.run_deprecated_v1 def testNoShuffle(self): with self.cached_session() as sess: num_epochs = 3 @@ -344,17 +364,18 @@ class SliceInputProducerTest(test_lib.TestCase): # No randomness, so just see repeated copies of the input. num_items = len(source_strings) * num_epochs - output = [sess.run(slices) for _ in range(num_items)] + output = [self.evaluate(slices) for _ in range(num_items)] out_strings, out_ints = zip(*output) self.assertAllEqual(source_strings * num_epochs, out_strings) self.assertAllEqual(source_ints * num_epochs, out_ints) # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(slices) + self.evaluate(slices) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testShuffle(self): with self.cached_session() as sess: num_epochs = 1200 @@ -379,7 +400,7 @@ class SliceInputProducerTest(test_lib.TestCase): for e in expected: frequency[e] = 0 for _ in range(num_epochs): - output = [sess.run(slices) for _ in range(len(source_strings))] + output = [self.evaluate(slices) for _ in range(len(source_strings))] key = b",".join([s + compat.as_bytes(str(i)) for s, i in output]) self.assertIn(key, expected) frequency[key] += 1 @@ -395,10 +416,11 @@ class SliceInputProducerTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(slices) + self.evaluate(slices) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSharedName(self): with self.cached_session(): source_strings = ["A", "B", "D", "G"] @@ -470,7 +492,7 @@ class BatchTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() for i in range(num_batches): - results = sess.run(batched_fetch) + results = self.evaluate(batched_fetch) self.assertAllEqual(results[0], np.arange(i * batch_size, (i + 1) * batch_size)) self.assertAllEqual( @@ -487,38 +509,43 @@ class BatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched_fetch) + self.evaluate(batched_fetch) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testOneThread(self): self._testOneThreadHelper(use_dict=False) + @test_util.run_deprecated_v1 def testOneThreadDict(self): self._testOneThreadHelper(use_dict=True) + @test_util.run_deprecated_v1 def testUint32DataTypes(self): values = constant_op.constant([0, 1, 2, 3, 4, 5], dtype=dtypes.uint32) batched = inp.batch([values], batch_size=2) with self.cached_session() as sess: coord = coordinator.Coordinator() threads = queue_runner_impl.start_queue_runners(sess=sess, coord=coord) - sess.run(batched) + self.evaluate(batched) coord.request_stop() for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testUint64DataTypes(self): values = constant_op.constant([0, 1, 2, 3, 4, 5], dtype=dtypes.uint64) batched = inp.batch([values], batch_size=2) with self.cached_session() as sess: coord = coordinator.Coordinator() threads = queue_runner_impl.start_queue_runners(sess=sess, coord=coord) - sess.run(batched) + self.evaluate(batched) coord.request_stop() for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testOneThreadDynamicPad(self): with self.cached_session() as sess: batch_size = 10 @@ -535,7 +562,7 @@ class BatchTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) expected_results = np.arange(i * batch_size, (i + 1) * batch_size) max_len = expected_results[-1] self.assertAllEqual(results[0], expected_results) @@ -545,10 +572,11 @@ class BatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testOneThreadEnqueueMany(self): with self.cached_session() as sess: batch_size = 10 @@ -567,7 +595,7 @@ class BatchTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) self.assertAllEqual(results[0], np.arange(i * batch_size, (i + 1) * batch_size)) self.assertAllEqual( @@ -580,10 +608,11 @@ class BatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testManyThreads(self): with self.cached_session() as sess: batch_size = 10 @@ -606,7 +635,7 @@ class BatchTest(test_lib.TestCase): all_counts = [] for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Batch %d: %s", i, results[0]) self.assertEqual(len(results[0]), batch_size) self.assertAllEqual(results[0], results[1].values) @@ -620,10 +649,11 @@ class BatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testOneThreadSmallerBatch(self): with self.cached_session() as sess: batch_size = 10 @@ -647,7 +677,7 @@ class BatchTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) self.assertAllEqual(results[0], np.arange(i * batch_size, (i + 1) * batch_size)) self.assertAllEqual( @@ -663,7 +693,7 @@ class BatchTest(test_lib.TestCase): self.assertAllEqual(results[2], [b"string"] * batch_size) # Reached the final batch with extra_elements. - results = sess.run(batched) + results = self.evaluate(batched) self.assertAllEqual(results[0], np.arange(num_batches * batch_size, num_batches * batch_size + extra_elements)) @@ -677,10 +707,11 @@ class BatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testManyThreadsSmallerBatch(self): with self.cached_session() as sess: batch_size = 10 @@ -705,7 +736,7 @@ class BatchTest(test_lib.TestCase): all_counts = [] for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Batch %d: %s", i, results[0]) self.assertEqual(len(results[0]), batch_size) self.assertAllEqual(results[0], results[1].values) @@ -717,7 +748,7 @@ class BatchTest(test_lib.TestCase): self.assertAllEqual(results[2], [b"string"] * batch_size) # Reached the final batch with extra_elements. - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Last Batch: %s", results[0]) self.assertEqual(len(results[0]), extra_elements) self.assertAllEqual(results[0], results[1].values) @@ -732,10 +763,11 @@ class BatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSharedName(self): with self.cached_session(): batch_size = 10 @@ -753,12 +785,14 @@ class BatchTest(test_lib.TestCase): "s: 'SHARED_NAME_XYZ'", batched[0].op.inputs[0].op.node_def.attr["shared_name"]) + @test_util.run_deprecated_v1 def testCannotInferRankError(self): with self.cached_session(): x = array_ops.placeholder(dtype=dtypes.int64) with self.assertRaisesRegexp(ValueError, "Cannot infer Tensor's rank"): inp.batch([x], batch_size=2) + @test_util.run_deprecated_v1 def testBatchedSparseTensorInferredShape(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -766,6 +800,7 @@ class BatchTest(test_lib.TestCase): batched = inp.batch([sparse], batch_size=2) self.assertAllEqual((2,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testBatchedSparseTensorInferredShapeEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -773,6 +808,7 @@ class BatchTest(test_lib.TestCase): batched = inp.batch([sparse], batch_size=2, enqueue_many=True) self.assertAllEqual((1,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testBatchedSparseTensorInferredShapeUnknownRank(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -782,6 +818,7 @@ class BatchTest(test_lib.TestCase): batched = inp.batch([sparse], batch_size=2) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testBatchedSparseTensorInferredShapeUnknownRankEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -791,6 +828,7 @@ class BatchTest(test_lib.TestCase): batched = inp.batch([sparse], batch_size=2, enqueue_many=True) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testSingleElementDict(self): x = inp.batch({"c": [12, 12]}, batch_size=8) self.assertAllEqual((8, 2), x["c"].get_shape().as_list()) @@ -823,35 +861,42 @@ class BatchTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() for _ in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) self.assertAllEqual([0] * batch_size, np.mod(results[0], 2)) self.assertAllEqual([0] * batch_size, np.mod(results[1].values, 2)) self.assertAllEqual([b"string"] * batch_size, results[2]) # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSingleThreadKeepInput(self): self._testKeepInputHelper(1, False) + @test_util.run_deprecated_v1 def testSingleThreadKeepInputEnqueueMany(self): self._testKeepInputHelper(1, True) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInput(self): self._testKeepInputHelper(5, False) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInputEnqueueMany(self): self._testKeepInputHelper(5, True) + @test_util.run_deprecated_v1 def testMaybeEnqueuePerExample(self): self._testKeepInputHelper(1, True, keep_input_vector=True) + @test_util.run_deprecated_v1 def testMultipleThreadMaybeEnqueuePerExample(self): self._testKeepInputHelper(5, True, keep_input_vector=True) + @test_util.run_deprecated_v1 def testInvalidKeepInputVector(self): # Can't have vector `keep_input` with `enqueue_many=False`. with self.assertRaisesRegexp(ValueError, "`keep_input` cannot be a vector"): @@ -873,6 +918,7 @@ class BatchTest(test_lib.TestCase): batch_size=1, enqueue_many=True) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShape(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -880,6 +926,7 @@ class BatchTest(test_lib.TestCase): batched = inp.maybe_batch([sparse], keep_input=True, batch_size=2) self.assertAllEqual((2,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -888,6 +935,7 @@ class BatchTest(test_lib.TestCase): [sparse], keep_input=True, batch_size=2, enqueue_many=True) self.assertAllEqual((1,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeEnqueueManyPerExample(self): sparse = sparse_tensor.SparseTensor( indices=[[0], [0]], values=[1.0, 2.0], dense_shape=[2]) @@ -896,6 +944,7 @@ class BatchTest(test_lib.TestCase): [sparse], keep_input=[True, False], batch_size=2, enqueue_many=True) self.assertAllEqual((1,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRank(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -905,6 +954,7 @@ class BatchTest(test_lib.TestCase): batched = inp.maybe_batch([sparse], keep_input=True, batch_size=2) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRankEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -915,6 +965,7 @@ class BatchTest(test_lib.TestCase): [sparse], keep_input=True, batch_size=2, enqueue_many=True) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRankPerExample(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -925,6 +976,7 @@ class BatchTest(test_lib.TestCase): [sparse], keep_input=[True, False], batch_size=2, enqueue_many=True) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchCorrectValues(self): sparse_t = sparse_tensor.SparseTensor( indices=[[0, 1], [0, 2], [1, 0], [1, 3]], @@ -938,7 +990,7 @@ class BatchTest(test_lib.TestCase): coord = coordinator.Coordinator() threads = queue_runner_impl.start_queue_runners(coord=coord) - batched_np = batched.eval() + batched_np = self.evaluate(batched) coord.request_stop() for thread in threads: @@ -1016,7 +1068,7 @@ class BatchJoinTest(test_lib.TestCase): saw_both = 0 num_batches = (num_a + num_b) // batch_size for i in range(num_batches): - results = sess.run(batched_fetch) + results = self.evaluate(batched_fetch) self.assertEqual(3, len(results)) self.assertEqual(batch_size, len(results[0])) self.assertEqual(batch_size, len(results[2])) @@ -1047,16 +1099,19 @@ class BatchJoinTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched_fetch) + self.evaluate(batched_fetch) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testTwoThreads(self): self._testTwoThreadsHelper(use_dict=False) + @test_util.run_deprecated_v1 def testTwoThreadsDict(self): self._testTwoThreadsHelper(use_dict=True) + @test_util.run_deprecated_v1 def testMismatchedDictKeys(self): with self.assertRaisesRegexp(ValueError, "must have the same keys"): inp.batch_join( @@ -1071,6 +1126,7 @@ class BatchJoinTest(test_lib.TestCase): }], batch_size=8) + @test_util.run_deprecated_v1 def testTwoThreadsDynamicPad(self): with self.cached_session() as sess: # Two threads, the first generates (0..69, ["a"] * 1..70). @@ -1112,7 +1168,7 @@ class BatchJoinTest(test_lib.TestCase): saw_both = 0 num_batches = (num_a + num_b) // batch_size for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) self.assertEqual(2, len(results)) self.assertEqual(len(results[0]), batch_size) self.assertEqual(len(results[1]), batch_size) @@ -1144,10 +1200,11 @@ class BatchJoinTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testTwoThreadsSmallerBatch(self): with self.cached_session() as sess: extra_elements = 2 @@ -1197,7 +1254,7 @@ class BatchJoinTest(test_lib.TestCase): saw_both = 0 num_batches = (num_a + num_b) // batch_size for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Batch %d: %s", i, results[0]) self.assertEqual(len(results[0]), batch_size) self.assertEqual(len(results[2]), batch_size) @@ -1217,7 +1274,7 @@ class BatchJoinTest(test_lib.TestCase): [results[0][i] for i in which_b]) # Reached the final batch with 2 * extra_elements. - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Last Batch: %s", results[0]) self.assertEqual(len(results[0]), 2 * extra_elements) self.assertEqual(len(results[2]), 2 * extra_elements) @@ -1245,10 +1302,11 @@ class BatchJoinTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testTwoThreadsDynamicPadSmallerBatch(self): with self.cached_session() as sess: extra_elements = 2 @@ -1292,7 +1350,7 @@ class BatchJoinTest(test_lib.TestCase): saw_both = 0 num_batches = (num_a + num_b) // batch_size for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Batch %d: %s", i, results[0]) self.assertEqual(len(results[0]), batch_size) self.assertEqual(len(results[1]), batch_size) @@ -1312,7 +1370,7 @@ class BatchJoinTest(test_lib.TestCase): [results[0][i] for i in which_b]) # Reached the final batch with 2 * extra_elements. - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Last Batch: %s", results[0]) self.assertEqual(len(results[0]), 2 * extra_elements) self.assertEqual(len(results[1]), 2 * extra_elements) @@ -1343,10 +1401,11 @@ class BatchJoinTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSharedName(self): with self.cached_session(): batch_size = 10 @@ -1369,12 +1428,14 @@ class BatchJoinTest(test_lib.TestCase): "s: 'SHARED_NAME_XYZ'", batched[0].op.inputs[0].op.node_def.attr["shared_name"]) + @test_util.run_deprecated_v1 def testCannotInferRankError(self): with self.cached_session(): x = array_ops.placeholder(dtype=dtypes.int64) with self.assertRaisesRegexp(ValueError, "Cannot infer Tensor's rank"): inp.batch_join([[x]], batch_size=2) + @test_util.run_deprecated_v1 def testSingleElementDict(self): x = inp.batch_join([{"c": [12, 12]}], batch_size=8) self.assertAllEqual((8, 2), x["c"].get_shape().as_list()) @@ -1406,7 +1467,7 @@ class BatchJoinTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() for _ in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) self.assertAllEqual( [0] * batch_size, np.mod(results[0], 2),) @@ -1417,28 +1478,35 @@ class BatchJoinTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSingleThreadKeepInput(self): self._testKeepInputHelper(1, False) + @test_util.run_deprecated_v1 def testSingleThreadKeepInputEnqueueMany(self): self._testKeepInputHelper(1, True) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInput(self): self._testKeepInputHelper(5, False) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInputEnqueueMany(self): self._testKeepInputHelper(5, True) + @test_util.run_deprecated_v1 def testSingleThreadKeepInputPerExample(self): self._testKeepInputHelper(1, True, keep_input_vector=True) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInputPerExample(self): self._testKeepInputHelper(5, True, keep_input_vector=True) + @test_util.run_deprecated_v1 def testInvalidKeepInputVector(self): # Can't have vector `keep_input` with `enqueue_many=False`. with self.assertRaisesRegexp(ValueError, "`keep_input` cannot be a vector"): @@ -1460,6 +1528,7 @@ class BatchJoinTest(test_lib.TestCase): batch_size=1, enqueue_many=True) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShape(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -1467,6 +1536,7 @@ class BatchJoinTest(test_lib.TestCase): batched = inp.maybe_batch_join([[sparse]], keep_input=True, batch_size=2) self.assertAllEqual((2,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -1475,6 +1545,7 @@ class BatchJoinTest(test_lib.TestCase): [[sparse]], keep_input=True, batch_size=2, enqueue_many=True) self.assertAllEqual((1,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeEnqueueManyPerExample(self): sparse = sparse_tensor.SparseTensor( indices=[[0], [0]], values=[1.0, 2.0], dense_shape=[2]) @@ -1483,6 +1554,7 @@ class BatchJoinTest(test_lib.TestCase): [[sparse]], keep_input=[True, False], batch_size=2, enqueue_many=True) self.assertAllEqual((1,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRank(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -1492,6 +1564,7 @@ class BatchJoinTest(test_lib.TestCase): batched = inp.maybe_batch_join([[sparse]], keep_input=True, batch_size=2) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRankEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -1502,6 +1575,7 @@ class BatchJoinTest(test_lib.TestCase): [[sparse]], keep_input=True, batch_size=2, enqueue_many=True) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRankPerExample(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -1512,6 +1586,7 @@ class BatchJoinTest(test_lib.TestCase): [[sparse]], keep_input=[True, False], batch_size=2, enqueue_many=True) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchCorrectValues(self): sparse = sparse_tensor.SparseTensor( indices=[[0, 1], [0, 2], [1, 0], [1, 3]], @@ -1525,7 +1600,7 @@ class BatchJoinTest(test_lib.TestCase): coord = coordinator.Coordinator() threads = queue_runner_impl.start_queue_runners(coord=coord) - batched_np = batched.eval() + batched_np = self.evaluate(batched) coord.request_stop() for thread in threads: @@ -1575,7 +1650,7 @@ class ShuffleBatchTest(test_lib.TestCase): all_counts = [] for i in range(num_batches): - results = sess.run(batched_fetch) + results = self.evaluate(batched_fetch) self.assertEqual(len(results[0]), batch_size) all_counts.extend(results[0]) self.assertAllEqual( @@ -1593,16 +1668,19 @@ class ShuffleBatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched_fetch) + self.evaluate(batched_fetch) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testOneThread(self): self._testOneThreadHelper(use_dict=False) + @test_util.run_deprecated_v1 def testOneThreadDict(self): self._testOneThreadHelper(use_dict=True) + @test_util.run_deprecated_v1 def testOneThreadSmallerBatch(self): with self.cached_session() as sess: batch_size = 10 @@ -1630,7 +1708,7 @@ class ShuffleBatchTest(test_lib.TestCase): all_counts = [] for _ in range(num_batches): - results = sess.run(batched_fetch) + results = self.evaluate(batched_fetch) self.assertEqual(len(results[0]), batch_size) all_counts.extend(results[0]) self.assertAllEqual( @@ -1641,7 +1719,7 @@ class ShuffleBatchTest(test_lib.TestCase): self.assertAllEqual(results[2], [b"string"] * batch_size) # Reached the final batch with extra elements. - results = sess.run(batched) + results = self.evaluate(batched) self.assertAllEqual(results[1].dense_shape, [extra_elements, 1]) self.assertAllEqual(results[2], [b"string"] * extra_elements) all_counts.extend(results[0]) @@ -1655,10 +1733,11 @@ class ShuffleBatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched_fetch) + self.evaluate(batched_fetch) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testManyThreads(self): with self.cached_session() as sess: batch_size = 10 @@ -1683,7 +1762,7 @@ class ShuffleBatchTest(test_lib.TestCase): all_counts = [] for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Batch %d: %s", i, results[0]) self.assertEqual(len(results[0]), batch_size) all_counts.extend(results[0]) @@ -1702,10 +1781,11 @@ class ShuffleBatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testManyThreadsSmallerBatch(self): with self.cached_session() as sess: batch_size = 10 @@ -1733,7 +1813,7 @@ class ShuffleBatchTest(test_lib.TestCase): all_counts = [] for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Batch %d: %s", i, results[0]) self.assertEqual(len(results[0]), batch_size) all_counts.extend(results[0]) @@ -1745,7 +1825,7 @@ class ShuffleBatchTest(test_lib.TestCase): self.assertAllEqual(results[2], [b"string"] * batch_size) # Reached the final batch with extra elements. - results = sess.run(batched) + results = self.evaluate(batched) self.assertAllEqual(results[0].shape, [extra_elements]) self.assertAllEqual(results[1].dense_shape, [extra_elements, 1]) self.assertAllEqual(results[2], [b"string"] * extra_elements) @@ -1760,10 +1840,11 @@ class ShuffleBatchTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSharedName(self): with self.cached_session(): batch_size = 10 @@ -1813,35 +1894,42 @@ class ShuffleBatchTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() for _ in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) self.assertAllEqual([0] * batch_size, np.mod(results[0], 2)) self.assertAllEqual([0] * batch_size, np.mod(results[1].values, 2)) self.assertAllEqual([b"string"] * batch_size, results[2]) # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSingleThreadKeepInput(self): self._testKeepInputHelper(1, False) + @test_util.run_deprecated_v1 def testSingleThreadKeepInputEnqueueMany(self): self._testKeepInputHelper(1, True) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInput(self): self._testKeepInputHelper(5, False) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInputEnqueueMany(self): self._testKeepInputHelper(5, True) + @test_util.run_deprecated_v1 def testSingleThreadKeepInputPerExample(self): self._testKeepInputHelper(1, True, keep_input_vector=True) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInputPerExample(self): self._testKeepInputHelper(5, True, keep_input_vector=True) + @test_util.run_deprecated_v1 def testInvalidKeepInputVector(self): # Can't have vector `keep_input` with `enqueue_many=False`. with self.assertRaisesRegexp(ValueError, "`keep_input` cannot be a vector"): @@ -1860,6 +1948,7 @@ class ShuffleBatchTest(test_lib.TestCase): keep_input=array_ops.placeholder(dtypes.bool), enqueue_many=True) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShape(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -1867,6 +1956,7 @@ class ShuffleBatchTest(test_lib.TestCase): batched = inp.maybe_shuffle_batch([sparse], 2, 10, 1, True) self.assertAllEqual((2,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -1875,6 +1965,7 @@ class ShuffleBatchTest(test_lib.TestCase): [sparse], 2, 10, 1, True, enqueue_many=True) self.assertAllEqual((1,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeEnqueueManyPerExample(self): sparse = sparse_tensor.SparseTensor( indices=[[0], [0]], values=[1.0, 2.0], dense_shape=[2]) @@ -1883,6 +1974,7 @@ class ShuffleBatchTest(test_lib.TestCase): [sparse], 2, 10, 1, [True, False], enqueue_many=True) self.assertAllEqual((1,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRank(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -1892,6 +1984,7 @@ class ShuffleBatchTest(test_lib.TestCase): batched = inp.maybe_shuffle_batch([sparse], 2, 10, 1, True) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRankEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -1902,6 +1995,7 @@ class ShuffleBatchTest(test_lib.TestCase): [sparse], 2, 10, 1, True, enqueue_many=True) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRankPerExample(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -1986,7 +2080,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): saw_both = 0 num_batches = (num_a + num_b) // batch_size for i in range(num_batches): - results = sess.run(batched_fetch) + results = self.evaluate(batched_fetch) self.assertEqual(3, len(results)) self.assertEqual(len(results[0]), batch_size) self.assertEqual(len(results[2]), batch_size) @@ -2016,16 +2110,19 @@ class ShuffleBatchJoinTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched_fetch) + self.evaluate(batched_fetch) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testTwoThreads(self): self._testTwoThreadsHelper(use_dict=False) + @test_util.run_deprecated_v1 def testTwoThreadsDict(self): self._testTwoThreadsHelper(use_dict=True) + @test_util.run_deprecated_v1 def testTwoThreadsSmallerBatch(self): with self.cached_session() as sess: # Two threads, the first generates (0..26, "a"). @@ -2078,7 +2175,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): saw_both = 0 num_batches = (num_a + num_b) // batch_size for i in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) tf_logging.info("Batch %d: %s", i, results[0]) self.assertEqual(len(results[0]), batch_size) self.assertEqual(len(results[2]), batch_size) @@ -2098,7 +2195,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): [results[0][i] for i in which_b]) # Reached end with 2 * extra_elements left - results = sess.run(batched) + results = self.evaluate(batched) self.assertEqual(len(results[0]), 2 * extra_elements) self.assertAllEqual(results[1].dense_shape, [2 * extra_elements, 1]) self.assertEqual(len(results[2]), 2 * extra_elements) @@ -2125,10 +2222,11 @@ class ShuffleBatchJoinTest(test_lib.TestCase): # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testMismatchedDictKeys(self): with self.assertRaisesRegexp(ValueError, "must have the same keys"): inp.shuffle_batch_join( @@ -2146,6 +2244,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): min_after_dequeue=16, seed=223607) + @test_util.run_deprecated_v1 def testSharedName(self): with self.cached_session(): batch_size = 10 @@ -2199,35 +2298,42 @@ class ShuffleBatchJoinTest(test_lib.TestCase): threads = queue_runner_impl.start_queue_runners() for _ in range(num_batches): - results = sess.run(batched) + results = self.evaluate(batched) self.assertAllEqual([0] * batch_size, np.mod(results[0], 2)) self.assertAllEqual([0] * batch_size, np.mod(results[1].values, 2)) self.assertAllEqual([b"string"] * batch_size, results[2]) # Reached the limit. with self.assertRaises(errors_impl.OutOfRangeError): - sess.run(batched) + self.evaluate(batched) for thread in threads: thread.join() + @test_util.run_deprecated_v1 def testSingleThreadKeepInput(self): self._testKeepInputHelper(1, False) + @test_util.run_deprecated_v1 def testSingleThreadKeepInputEnqueueMany(self): self._testKeepInputHelper(1, True) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInput(self): self._testKeepInputHelper(5, False) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInputEnqueueMany(self): self._testKeepInputHelper(5, True) + @test_util.run_deprecated_v1 def testSingleThreadKeepInputPerExample(self): self._testKeepInputHelper(1, True, keep_input_vector=True) + @test_util.run_deprecated_v1 def testMultipleThreadKeepInputPerExample(self): self._testKeepInputHelper(5, True, keep_input_vector=True) + @test_util.run_deprecated_v1 def testInvalidKeepInputVector(self): # Can't have vector `keep_input` with `enqueue_many=False`. with self.assertRaisesRegexp(ValueError, "`keep_input` cannot be a vector"): @@ -2249,6 +2355,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): keep_input=array_ops.placeholder(dtypes.bool), enqueue_many=True) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShape(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -2256,6 +2363,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): batched = inp.maybe_shuffle_batch_join([[sparse]], 2, 10, 1, True) self.assertAllEqual((2,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=[[0]], values=[1.0], dense_shape=[1]) @@ -2264,6 +2372,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): [[sparse]], 2, 10, 1, True, enqueue_many=True) self.assertAllEqual((1,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeEnqueueManyPerExample(self): sparse = sparse_tensor.SparseTensor( indices=[[0], [0]], values=[1.0, 2.0], dense_shape=[2]) @@ -2272,6 +2381,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): [[sparse]], 2, 10, 1, [True, False], enqueue_many=True) self.assertAllEqual((1,), batched.dense_shape.get_shape().as_list()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRank(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -2281,6 +2391,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): batched = inp.maybe_shuffle_batch_join([[sparse]], 2, 10, 1, True) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRankEnqueueMany(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), @@ -2291,6 +2402,7 @@ class ShuffleBatchJoinTest(test_lib.TestCase): [[sparse]], 2, 10, 1, True, enqueue_many=True) self.assertIs(None, batched.dense_shape.get_shape().num_elements()) + @test_util.run_deprecated_v1 def testMaybeBatchedSparseTensorInferredShapeUnknownRankPerExample(self): sparse = sparse_tensor.SparseTensor( indices=array_ops.placeholder(dtypes.int64), diff --git a/tensorflow/python/training/learning_rate_decay.py b/tensorflow/python/training/learning_rate_decay.py index 29b5465321..c52e89db1f 100644 --- a/tensorflow/python/training/learning_rate_decay.py +++ b/tensorflow/python/training/learning_rate_decay.py @@ -100,7 +100,7 @@ def exponential_decay(learning_rate, return decayed_lr -@tf_export(v1=["train.piecewise_constant"]) +@tf_export(v1=["train.piecewise_constant_decay", "train.piecewise_constant"]) def piecewise_constant(x, boundaries, values, name=None): """Piecewise constant from boundaries and interval values. diff --git a/tensorflow/python/training/learning_rate_decay_test.py b/tensorflow/python/training/learning_rate_decay_test.py index 03a32f6ca0..9de5bc8168 100644 --- a/tensorflow/python/training/learning_rate_decay_test.py +++ b/tensorflow/python/training/learning_rate_decay_test.py @@ -61,24 +61,24 @@ class LRDecayTest(test_util.TensorFlowTestCase): self.evaluate(step.assign(100)) self.assertAllClose(self.evaluate(decayed_lr), expected, 1e-6) + @test_util.run_deprecated_v1 def testVariables(self): - with self.cached_session(): - step = variables.VariableV1(1) - assign_1 = step.assign(1) - assign_2 = step.assign(2) - assign_100 = step.assign(100) - decayed_lr = learning_rate_decay.exponential_decay(.1, step, 3, 0.96, - staircase=True) - variables.global_variables_initializer().run() - # No change to learning rate - assign_1.op.run() - self.assertAllClose(decayed_lr.eval(), .1, 1e-6) - assign_2.op.run() - self.assertAllClose(decayed_lr.eval(), .1, 1e-6) - # Decayed learning rate - assign_100.op.run() - expected = .1 * 0.96 ** (100 // 3) - self.assertAllClose(decayed_lr.eval(), expected, 1e-6) + step = variables.VariableV1(1) + assign_1 = step.assign(1) + assign_2 = step.assign(2) + assign_100 = step.assign(100) + decayed_lr = learning_rate_decay.exponential_decay( + .1, step, 3, 0.96, staircase=True) + self.evaluate(variables.global_variables_initializer()) + # No change to learning rate + self.evaluate(assign_1.op) + self.assertAllClose(self.evaluate(decayed_lr), .1, 1e-6) + self.evaluate(assign_2.op) + self.assertAllClose(self.evaluate(decayed_lr), .1, 1e-6) + # Decayed learning rate + self.evaluate(assign_100.op) + expected = .1 * 0.96**(100 // 3) + self.assertAllClose(self.evaluate(decayed_lr), expected, 1e-6) @test_util.run_in_graph_and_eager_modes def testPiecewiseConstant(self): @@ -101,6 +101,7 @@ class LRDecayTest(test_util.TensorFlowTestCase): self.assertAllClose(self.evaluate(decayed_lr), 0.001, 1e-6) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testPiecewiseConstantEdgeCases(self): x_int = resource_variable_ops.ResourceVariable( 0, dtype=variables.dtypes.int32) diff --git a/tensorflow/python/training/learning_rate_decay_v2.py b/tensorflow/python/training/learning_rate_decay_v2.py index 9c5e144be6..eb69feb17d 100644 --- a/tensorflow/python/training/learning_rate_decay_v2.py +++ b/tensorflow/python/training/learning_rate_decay_v2.py @@ -117,7 +117,7 @@ def exponential_decay(learning_rate, decay_rate, staircase, name) -@tf_export("train.piecewise_constant", v1=[]) +@tf_export("train.piecewise_constant_decay", v1=[]) def piecewise_constant(x, boundaries, values, name=None): """Piecewise constant from boundaries and interval values. diff --git a/tensorflow/python/training/learning_rate_decay_v2_test.py b/tensorflow/python/training/learning_rate_decay_v2_test.py index b2ac93f06f..cb96773e29 100644 --- a/tensorflow/python/training/learning_rate_decay_v2_test.py +++ b/tensorflow/python/training/learning_rate_decay_v2_test.py @@ -61,24 +61,24 @@ class LRDecayTestV2(test_util.TensorFlowTestCase): self.evaluate(step.assign(100)) self.assertAllClose(self.evaluate(decayed_lr()), expected, 1e-6) + @test_util.run_deprecated_v1 def testVariables(self): - with self.cached_session(): - step = variables.Variable(1) - assign_1 = step.assign(1) - assign_2 = step.assign(2) - assign_100 = step.assign(100) - decayed_lr = learning_rate_decay_v2.exponential_decay(.1, step, 3, 0.96, - staircase=True) - variables.global_variables_initializer().run() - # No change to learning rate - assign_1.op.run() - self.assertAllClose(decayed_lr().eval(), .1, 1e-6) - assign_2.op.run() - self.assertAllClose(decayed_lr().eval(), .1, 1e-6) - # Decayed learning rate - assign_100.op.run() - expected = .1 * 0.96 ** (100 // 3) - self.assertAllClose(decayed_lr().eval(), expected, 1e-6) + step = variables.Variable(1) + assign_1 = step.assign(1) + assign_2 = step.assign(2) + assign_100 = step.assign(100) + decayed_lr = learning_rate_decay_v2.exponential_decay( + .1, step, 3, 0.96, staircase=True) + self.evaluate(variables.global_variables_initializer()) + # No change to learning rate + self.evaluate(assign_1.op) + self.assertAllClose(self.evaluate(decayed_lr()), .1, 1e-6) + self.evaluate(assign_2.op) + self.assertAllClose(self.evaluate(decayed_lr()), .1, 1e-6) + # Decayed learning rate + self.evaluate(assign_100.op) + expected = .1 * 0.96**(100 // 3) + self.assertAllClose(self.evaluate(decayed_lr()), expected, 1e-6) @test_util.run_in_graph_and_eager_modes def testPiecewiseConstant(self): diff --git a/tensorflow/python/training/momentum.py b/tensorflow/python/training/momentum.py index 4a280e7c51..f3bc83bbfa 100644 --- a/tensorflow/python/training/momentum.py +++ b/tensorflow/python/training/momentum.py @@ -25,7 +25,7 @@ from tensorflow.python.training import training_ops from tensorflow.python.util.tf_export import tf_export -@tf_export("train.MomentumOptimizer") +@tf_export(v1=["train.MomentumOptimizer"]) class MomentumOptimizer(optimizer.Optimizer): """Optimizer that implements the Momentum algorithm. diff --git a/tensorflow/python/training/momentum_test.py b/tensorflow/python/training/momentum_test.py index 8a21c39d32..ba155fa6c6 100644 --- a/tensorflow/python/training/momentum_test.py +++ b/tensorflow/python/training/momentum_test.py @@ -160,6 +160,7 @@ class MomentumOptimizerTest(test.TestCase): self.assertStartsWith(optimizer_variables[1].name, "var3") self.assertEquals(2, len(optimizer_variables)) + @test_util.run_deprecated_v1 def testNesterovMomentum(self): for dtype in [dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -183,9 +184,10 @@ class MomentumOptimizerTest(test.TestCase): var1_np, accum1_np = self._update_nesterov_momentum_numpy(var1_np, accum1_np, 3, 2.0, 0.9) - self.assertAllClose(var0_np, var0.eval()) - self.assertAllClose(var1_np, var1.eval()) + self.assertAllClose(var0_np, self.evaluate(var0)) + self.assertAllClose(var1_np, self.evaluate(var1)) + @test_util.run_deprecated_v1 def testSparseNesterovMomentum(self): for dtype in [dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -224,8 +226,8 @@ class MomentumOptimizerTest(test.TestCase): var1_np, accum1_np = self._update_nesterov_momentum_numpy(var1_np, accum1_np, 3, 2.0, 0.9) - self.assertAllClose(var0_np, var0.eval()) - self.assertAllClose(var1_np, var1.eval()) + self.assertAllClose(var0_np, self.evaluate(var0)) + self.assertAllClose(var1_np, self.evaluate(var1)) @test_util.run_in_graph_and_eager_modes(reset_test=True) def testMinimizeSparseResourceVariable(self): @@ -280,6 +282,7 @@ class MomentumOptimizerTest(test.TestCase): self.evaluate(sgd_op) self.assertAllCloseAccordingToType([[1, 1], [0, 0]], self.evaluate(var0)) + @test_util.run_deprecated_v1 def testTensorLearningRateAndMomentum(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -303,37 +306,43 @@ class MomentumOptimizerTest(test.TestCase): self.assertFalse(slot1 in variables.trainable_variables()) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Step 1: the momentum accumulators where 0. So we should see a normal # update: v -= grad * learning_rate mom_update.run() # Check that the momentum accumulators have been updated. - self.assertAllCloseAccordingToType(np.array([0.1, 0.1]), slot0.eval()) - self.assertAllCloseAccordingToType(np.array([0.01, 0.01]), slot1.eval()) + self.assertAllCloseAccordingToType( + np.array([0.1, 0.1]), self.evaluate(slot0)) + self.assertAllCloseAccordingToType( + np.array([0.01, 0.01]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( - np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), var0.eval()) + np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), + self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), var1.eval()) + np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), + self.evaluate(var1)) # Step 2: the momentum accumulators contain the previous update. mom_update.run() # Check that the momentum accumulators have been updated. self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), slot0.eval()) + np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), + self.evaluate(slot0)) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), slot1.eval()) + np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), + self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( np.array([ 1.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0), 2.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ - 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), 3.98 - ( - (0.9 * 0.01 + 0.01) * 2.0) - ]), var1.eval()) + 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), + 3.98 - ((0.9 * 0.01 + 0.01) * 2.0) + ]), self.evaluate(var1)) def _dbParamsMom01(self): """Return dist-belief momentum values. @@ -434,6 +443,7 @@ class MomentumOptimizerTest(test.TestCase): # pylint: enable=line-too-long return db_grad, db_out + @test_util.run_deprecated_v1 def testLikeDistBeliefMom01(self): with self.cached_session(): db_grad, db_out = self._dbParamsMom01() @@ -445,8 +455,9 @@ class MomentumOptimizerTest(test.TestCase): variables.global_variables_initializer().run() for i in xrange(num_samples): mom_update.run(feed_dict={grads0: db_grad[i]}) - self.assertAllClose(np.array(db_out[i]), var0.eval()) + self.assertAllClose(np.array(db_out[i]), self.evaluate(var0)) + @test_util.run_deprecated_v1 def testSparse(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -476,46 +487,59 @@ class MomentumOptimizerTest(test.TestCase): self.assertEquals(slot1.get_shape(), var1.get_shape()) # Fetch params to validate initial values - self.assertAllClose([0, 0], var0.eval()[0]) - self.assertAllClose([0, 0], var0.eval()[1]) - self.assertAllClose([1, 1], var1.eval()[2]) + self.assertAllClose([0, 0], self.evaluate(var0)[0]) + self.assertAllClose([0, 0], self.evaluate(var0)[1]) + self.assertAllClose([1, 1], self.evaluate(var1)[2]) # Step 1: the momentum accumulators are 0. So we should see a normal # update: v -= grad * learning_rate mom_update.run() # Check that the momentum accumulators have been updated. - self.assertAllCloseAccordingToType(np.array([0, 0]), slot0.eval()[0]) - self.assertAllCloseAccordingToType(np.array([.1, .1]), slot0.eval()[1]) self.assertAllCloseAccordingToType( - np.array([.01, .01]), slot1.eval()[2]) + np.array([0, 0]), + self.evaluate(slot0)[0]) + self.assertAllCloseAccordingToType( + np.array([.1, .1]), + self.evaluate(slot0)[1]) + self.assertAllCloseAccordingToType( + np.array([.01, .01]), + self.evaluate(slot1)[2]) # Check that the parameters have been updated. - self.assertAllCloseAccordingToType(np.array([0, 0]), var0.eval()[0]) self.assertAllCloseAccordingToType( - np.array([-(0.1 * 2.0), -(0.1 * 2.0)]), var0.eval()[1]) + np.array([0, 0]), + self.evaluate(var0)[0]) self.assertAllCloseAccordingToType( - np.array([1.0 - (0.01 * 2.0), 1.0 - (0.01 * 2.0)]), var1.eval()[2]) + np.array([-(0.1 * 2.0), -(0.1 * 2.0)]), + self.evaluate(var0)[1]) + self.assertAllCloseAccordingToType( + np.array([1.0 - (0.01 * 2.0), 1.0 - (0.01 * 2.0)]), + self.evaluate(var1)[2]) # Step 2: the momentum accumulators contain the previous update. mom_update.run() # Check that the momentum accumulators have been updated. - self.assertAllClose(np.array([0, 0]), slot0.eval()[0]) + self.assertAllClose(np.array([0, 0]), self.evaluate(slot0)[0]) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), slot0.eval()[1]) + np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), + self.evaluate(slot0)[1]) self.assertAllCloseAccordingToType( np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), - slot1.eval()[2]) + self.evaluate(slot1)[2]) # Check that the parameters have been updated. - self.assertAllClose(np.array([0, 0]), var0.eval()[0]) + self.assertAllClose(np.array([0, 0]), self.evaluate(var0)[0]) self.assertAllCloseAccordingToType( np.array([ - -(0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0), -(0.1 * 2.0) - ( - (0.9 * 0.1 + 0.1) * 2.0) - ]), var0.eval()[1]) + -(0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0), + -(0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0) + ]), + self.evaluate(var0)[1]) self.assertAllCloseAccordingToType( np.array([ - 0.98 - ((0.9 * 0.01 + 0.01) * 2.0), 0.98 - ( - (0.9 * 0.01 + 0.01) * 2.0) - ]), var1.eval()[2]) + 0.98 - ((0.9 * 0.01 + 0.01) * 2.0), + 0.98 - ((0.9 * 0.01 + 0.01) * 2.0) + ]), + self.evaluate(var1)[2]) + @test_util.run_deprecated_v1 def testSharing(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -538,37 +562,43 @@ class MomentumOptimizerTest(test.TestCase): self.assertEquals(slot1.get_shape(), var1.get_shape()) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Step 1: the momentum accumulators where 0. So we should see a normal # update: v -= grad * learning_rate mom_update1.run() # Check that the momentum accumulators have been updated. - self.assertAllCloseAccordingToType(np.array([0.1, 0.1]), slot0.eval()) - self.assertAllCloseAccordingToType(np.array([0.01, 0.01]), slot1.eval()) + self.assertAllCloseAccordingToType( + np.array([0.1, 0.1]), self.evaluate(slot0)) + self.assertAllCloseAccordingToType( + np.array([0.01, 0.01]), self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( - np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), var0.eval()) + np.array([1.0 - (0.1 * 2.0), 2.0 - (0.1 * 2.0)]), + self.evaluate(var0)) self.assertAllCloseAccordingToType( - np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), var1.eval()) + np.array([3.0 - (0.01 * 2.0), 4.0 - (0.01 * 2.0)]), + self.evaluate(var1)) # Step 2: the second momentum accumulators contain the previous update. mom_update2.run() # Check that the momentum accumulators have been updated. self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), slot0.eval()) + np.array([(0.9 * 0.1 + 0.1), (0.9 * 0.1 + 0.1)]), + self.evaluate(slot0)) self.assertAllCloseAccordingToType( - np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), slot1.eval()) + np.array([(0.9 * 0.01 + 0.01), (0.9 * 0.01 + 0.01)]), + self.evaluate(slot1)) # Check that the parameters have been updated. self.assertAllCloseAccordingToType( np.array([ 1.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0), 2.0 - (0.1 * 2.0) - ((0.9 * 0.1 + 0.1) * 2.0) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ - 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), 3.98 - ( - (0.9 * 0.01 + 0.01) * 2.0) - ]), var1.eval()) + 2.98 - ((0.9 * 0.01 + 0.01) * 2.0), + 3.98 - ((0.9 * 0.01 + 0.01) * 2.0) + ]), self.evaluate(var1)) if __name__ == "__main__": diff --git a/tensorflow/python/training/monitored_session.py b/tensorflow/python/training/monitored_session.py index 162fef971d..6a7d27df5c 100644 --- a/tensorflow/python/training/monitored_session.py +++ b/tensorflow/python/training/monitored_session.py @@ -54,7 +54,7 @@ _PREEMPTION_ERRORS = (errors.AbortedError, errors.UnavailableError) USE_DEFAULT = object() -@tf_export('train.Scaffold') +@tf_export(v1=['train.Scaffold']) class Scaffold(object): """Structure to create or gather pieces commonly needed to train a model. @@ -508,7 +508,7 @@ def MonitoredTrainingSession(master='', # pylint: disable=invalid-name stop_grace_period_secs=stop_grace_period_secs) -@tf_export('train.SessionCreator') +@tf_export(v1=['train.SessionCreator']) @six.add_metaclass(abc.ABCMeta) class SessionCreator(object): """A factory for tf.Session.""" @@ -519,7 +519,7 @@ class SessionCreator(object): 'create_session is not implemented for {}.'.format(self)) -@tf_export('train.ChiefSessionCreator') +@tf_export(v1=['train.ChiefSessionCreator']) class ChiefSessionCreator(SessionCreator): """Creates a tf.Session for a chief.""" @@ -571,7 +571,7 @@ class ChiefSessionCreator(SessionCreator): init_fn=self._scaffold.init_fn) -@tf_export('train.WorkerSessionCreator') +@tf_export(v1=['train.WorkerSessionCreator']) class WorkerSessionCreator(SessionCreator): """Creates a tf.Session for a worker.""" @@ -840,10 +840,18 @@ class _MonitoredSession(object): return self._coordinated_creator.tf_sess is None def _tf_sess(self): + """Return underlying tf.Session object. + + Warning: accessing the returned object in user code is likely to cause races + or "flaky tests". + + Returns: + A tf.Session object. + """ return self._coordinated_creator.tf_sess -@tf_export('train.MonitoredSession') +@tf_export(v1=['train.MonitoredSession']) class MonitoredSession(_MonitoredSession): """Session-like object that handles initialization, recovery and hooks. @@ -926,7 +934,7 @@ class MonitoredSession(_MonitoredSession): stop_grace_period_secs=stop_grace_period_secs) -@tf_export('train.SingularMonitoredSession') +@tf_export(v1=['train.SingularMonitoredSession']) class SingularMonitoredSession(_MonitoredSession): """Session-like object that handles initialization, restoring, and hooks. diff --git a/tensorflow/python/training/monitored_session_test.py b/tensorflow/python/training/monitored_session_test.py index c870d99de9..9dbcfa52b7 100644 --- a/tensorflow/python/training/monitored_session_test.py +++ b/tensorflow/python/training/monitored_session_test.py @@ -37,6 +37,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import resource_variable_ops @@ -382,6 +383,16 @@ class MonitoredTrainingSessionTest(test.TestCase): self.assertEqual(0, session.run(gstep)) +class MockExtended(object): + + def __init__(self, between_graph, should_init, should_checkpoint, + should_save_summary): + self.experimental_between_graph = between_graph + self.experimental_should_init = should_init + self.should_checkpoint = should_checkpoint + self.should_save_summary = should_save_summary + + class MockStrategy(object): def __init__(self, @@ -389,26 +400,8 @@ class MockStrategy(object): should_init=True, should_checkpoint=None, should_save_summary=None): - self._between_graph = between_graph - self._should_init = should_init - self._should_checkpoint = should_checkpoint - self._should_save_summary = should_save_summary - - @property - def between_graph(self): - return self._between_graph - - @property - def should_init(self): - return self._should_init - - @property - def should_checkpoint(self): - return self._should_checkpoint - - @property - def should_save_summary(self): - return self._should_save_summary + self.extended = MockExtended(between_graph, should_init, should_checkpoint, + should_save_summary) class MonitoredTrainingSessionWithDistributeCoordinatorTest(test.TestCase): @@ -512,6 +505,7 @@ class StopAtNSession(monitored_session._WrappedSession): class WrappedSessionTest(test.TestCase): """_WrappedSession tests.""" + @test_util.run_deprecated_v1 def test_properties(self): with self.cached_session() as sess: constant_op.constant(0.0) @@ -519,6 +513,7 @@ class WrappedSessionTest(test.TestCase): self.assertEquals(sess.graph, wrapped_sess.graph) self.assertEquals(sess.sess_str, wrapped_sess.sess_str) + @test_util.run_deprecated_v1 def test_should_stop_on_close(self): with self.cached_session() as sess: wrapped_sess = monitored_session._WrappedSession(sess) @@ -526,6 +521,7 @@ class WrappedSessionTest(test.TestCase): wrapped_sess.close() self.assertTrue(wrapped_sess.should_stop()) + @test_util.run_deprecated_v1 def test_should_stop_uses_check_stop(self): with self.cached_session() as sess: wrapped_sess = StopAtNSession(sess, 3) @@ -534,6 +530,7 @@ class WrappedSessionTest(test.TestCase): self.assertFalse(wrapped_sess.should_stop()) self.assertTrue(wrapped_sess.should_stop()) + @test_util.run_deprecated_v1 def test_should_stop_delegates_to_wrapped_session(self): with self.cached_session() as sess: wrapped_sess0 = StopAtNSession(sess, 4) @@ -552,6 +549,7 @@ class WrappedSessionTest(test.TestCase): wrapped_sess.close() self.assertTrue(wrapped_sess.should_stop()) + @test_util.run_deprecated_v1 def test_run(self): with self.cached_session() as sess: c = constant_op.constant(0) @@ -569,6 +567,7 @@ def busy_wait_for_coord_stop(coord): class CoordinatedSessionTest(test.TestCase): """_CoordinatedSession tests.""" + @test_util.run_deprecated_v1 def test_properties(self): with self.cached_session() as sess: constant_op.constant(0.0) @@ -577,6 +576,7 @@ class CoordinatedSessionTest(test.TestCase): self.assertEquals(sess.graph, coord_sess.graph) self.assertEquals(sess.sess_str, coord_sess.sess_str) + @test_util.run_deprecated_v1 def test_run(self): with self.cached_session() as sess: c = constant_op.constant(0) @@ -585,6 +585,7 @@ class CoordinatedSessionTest(test.TestCase): coord_sess = monitored_session._CoordinatedSession(sess, coord) self.assertEqual(42, coord_sess.run(v, feed_dict={c: 42})) + @test_util.run_deprecated_v1 def test_should_stop_on_close(self): with self.cached_session() as sess: coord = coordinator.Coordinator() @@ -593,6 +594,7 @@ class CoordinatedSessionTest(test.TestCase): coord_sess.close() self.assertTrue(coord_sess.should_stop()) + @test_util.run_deprecated_v1 def test_should_stop_on_coord_stop(self): with self.cached_session() as sess: coord = coordinator.Coordinator() @@ -601,6 +603,7 @@ class CoordinatedSessionTest(test.TestCase): coord.request_stop() self.assertTrue(coord_sess.should_stop()) + @test_util.run_deprecated_v1 def test_dont_request_stop_on_exception_in_main_thread(self): with self.cached_session() as sess: c = constant_op.constant(0) @@ -615,6 +618,7 @@ class CoordinatedSessionTest(test.TestCase): self.assertFalse(coord.should_stop()) self.assertFalse(coord_sess.should_stop()) + @test_util.run_deprecated_v1 def test_stop_threads_on_close_after_exception(self): with self.cached_session() as sess: c = constant_op.constant(0) @@ -662,6 +666,7 @@ class CoordinatedSessionTest(test.TestCase): self.assertTrue(coord.should_stop()) self.assertTrue(coord_sess.should_stop()) + @test_util.run_deprecated_v1 def test_propagates_exception_trace(self): assertion = control_flow_ops.Assert(False, ['This should fail.']) with self.cached_session() as sess: @@ -809,6 +814,7 @@ class RecoverableSessionTest(test.TestCase): def create_session(self): return self._sess + @test_util.run_deprecated_v1 def test_properties(self): with self.cached_session() as sess: constant_op.constant(0.0) @@ -817,6 +823,7 @@ class RecoverableSessionTest(test.TestCase): self.assertEquals(sess.graph, recoverable_sess.graph) self.assertEquals(sess.sess_str, recoverable_sess.sess_str) + @test_util.run_deprecated_v1 def test_run(self): with self.cached_session() as sess: c = constant_op.constant(0) @@ -825,6 +832,7 @@ class RecoverableSessionTest(test.TestCase): self._SessionReturner(sess)) self.assertEqual(51, recoverable_sess.run(v, feed_dict={c: 51})) + @test_util.run_deprecated_v1 def test_recovery(self): with self.cached_session() as sess: @@ -871,6 +879,7 @@ class RecoverableSessionTest(test.TestCase): with self.assertRaisesRegexp(IndexError, 'pop from empty list'): recoverable_sess.run(v, feed_dict={c: -12}) + @test_util.run_deprecated_v1 def test_recovery_from_coordinator_exception(self): with self.cached_session() as test_session: session_creator = CountingSessionCreator(test_session) @@ -896,6 +905,7 @@ class RecoverableSessionTest(test.TestCase): self.assertFalse(session.should_stop()) self.assertEqual(2, session_creator.number_of_sessions_created) + @test_util.run_deprecated_v1 def test_recovery_from_non_preemption_in_coordinator(self): with self.cached_session() as test_session: session_creator = CountingSessionCreator(test_session) @@ -925,6 +935,7 @@ class RecoverableSessionTest(test.TestCase): with self.assertRaises(errors_impl.UnknownError): session.close() + @test_util.run_deprecated_v1 def test_recovery_from_session_getting_stuck(self): with self.cached_session() as test_session: session_creator = CountingSessionCreator(test_session) @@ -949,6 +960,7 @@ class RecoverableSessionTest(test.TestCase): self.assertFalse(session.should_stop()) self.assertEqual(2, session_creator.number_of_sessions_created) + @test_util.run_deprecated_v1 def test_step_fn_recovery_from_coordinator_exception_when_run_hooks(self): with self.cached_session() as test_session: session_creator = CountingSessionCreator(test_session) @@ -979,6 +991,7 @@ class RecoverableSessionTest(test.TestCase): self.assertFalse(session.should_stop()) self.assertEqual(2, session_creator.number_of_sessions_created) + @test_util.run_deprecated_v1 def test_recovery_from_non_preemption_in_coordinator_when_run_hooks(self): with self.cached_session() as test_session: session_creator = CountingSessionCreator(test_session) @@ -1013,6 +1026,7 @@ class RecoverableSessionTest(test.TestCase): with self.assertRaises(errors_impl.UnknownError): session.close() + @test_util.run_deprecated_v1 def test_recovery_from_session_getting_stuck_when_run_hooks(self): with self.cached_session() as test_session: session_creator = CountingSessionCreator(test_session) @@ -1057,6 +1071,7 @@ class RecoverableSessionTest(test.TestCase): # exception. return session + @test_util.run_deprecated_v1 def test_step_fn_recovery_from_coordinator_exception_with_raw_session(self): with self.cached_session() as test_session: session_creator = CountingSessionCreator(test_session) @@ -1089,6 +1104,7 @@ class RecoverableSessionTest(test.TestCase): self.assertFalse(session.should_stop()) self.assertEqual(2, session_creator.number_of_sessions_created) + @test_util.run_deprecated_v1 def test_recovery_from_non_preemption_in_coordinator_with_raw_session(self): with self.cached_session() as test_session: session_creator = CountingSessionCreator(test_session) @@ -1126,6 +1142,7 @@ class RecoverableSessionTest(test.TestCase): with self.assertRaises(errors_impl.UnknownError): session.close() + @test_util.run_deprecated_v1 def test_recovery_from_session_getting_stuck_with_raw_session(self): with self.cached_session() as test_session: session_creator = CountingSessionCreator(test_session) @@ -1178,7 +1195,7 @@ class HookedSessionTest(test.TestCase): mock_run = FakeSession(sess) mon_sess = monitored_session._HookedSession(sess=mock_run, hooks=[]) a_tensor = constant_op.constant([0], name='a_tensor') - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) output = mon_sess.run(fetches=a_tensor, feed_dict='a_feed', options='an_option', @@ -1197,7 +1214,7 @@ class HookedSessionTest(test.TestCase): mon_sess = monitored_session._HookedSession( sess=sess, hooks=[mock_hook, mock_hook2]) a_tensor = constant_op.constant([0], name='a_tensor') - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) mon_sess.run(a_tensor) for hook in [mock_hook, mock_hook2]: @@ -1222,7 +1239,7 @@ class HookedSessionTest(test.TestCase): mon_sess = monitored_session._HookedSession( sess=sess, hooks=[mock_hook, mock_hook2]) constant_op.constant([0], name='a_tensor') - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) mon_sess.run(fetches='a_tensor') self.assertFalse(mon_sess.should_stop()) @@ -1242,7 +1259,7 @@ class HookedSessionTest(test.TestCase): third_tensor = constant_op.constant([10], name='third_tensor') mock_hook.request = session_run_hook.SessionRunArgs([another_tensor]) mock_hook2.request = session_run_hook.SessionRunArgs([third_tensor]) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) output = mon_sess.run(fetches=a_tensor) self.assertEqual(output, [0]) @@ -1262,7 +1279,7 @@ class HookedSessionTest(test.TestCase): None, feed_dict={a_tensor: [5]}) mock_hook2.request = session_run_hook.SessionRunArgs( None, feed_dict={b_tensor: [10]}) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertEqual(mon_sess.run(fetches=add_tensor), [15]) @@ -1280,7 +1297,7 @@ class HookedSessionTest(test.TestCase): None, feed_dict={a_tensor: [5]}) mock_hook2.request = session_run_hook.SessionRunArgs( None, feed_dict={b_tensor: [10]}) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) feed_dict = {c_tensor: [20]} self.assertEqual( @@ -1301,7 +1318,7 @@ class HookedSessionTest(test.TestCase): None, feed_dict={a_tensor: [5]}) mock_hook2.request = session_run_hook.SessionRunArgs( None, feed_dict={a_tensor: [10]}) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) with self.assertRaisesRegexp(RuntimeError, 'Same tensor is fed'): mon_sess.run(fetches=add_tensor) @@ -1319,7 +1336,7 @@ class HookedSessionTest(test.TestCase): None, feed_dict={a_tensor: [5]}) mock_hook2.request = session_run_hook.SessionRunArgs( None, feed_dict={b_tensor: [10]}) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) with self.assertRaisesRegexp(RuntimeError, 'Same tensor is fed'): mon_sess.run(fetches=add_tensor, feed_dict={b_tensor: [10]}) @@ -1451,6 +1468,7 @@ class MonitoredSessionTest(test.TestCase): # This set of tests, verifies the supervised session behavior when exceptions # are raised next to the innermost session run() call. + @test_util.run_deprecated_v1 def test_recovery(self): logdir = _test_dir(self.get_temp_dir(), 'test_recovery') with ops.Graph().as_default(): @@ -1803,6 +1821,7 @@ class MonitoredSessionTest(test.TestCase): isinstance(hook.run_metadata_list[0], config_pb2.RunMetadata)) self.assertGreater(len(hook.run_metadata_list[0].partition_graphs), 0) + @test_util.run_deprecated_v1 def test_with_statement_and_close(self): # Test case for https://github.com/tensorflow/tensorflow/issues/12224 # where close() inside the with should have a better error message. diff --git a/tensorflow/python/training/moving_averages.py b/tensorflow/python/training/moving_averages.py index fc9eb479cc..8785f9a8e7 100644 --- a/tensorflow/python/training/moving_averages.py +++ b/tensorflow/python/training/moving_averages.py @@ -17,6 +17,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.distribute import reduce_util as ds_reduce_util from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import control_flow_ops @@ -95,11 +96,11 @@ def assign_moving_average(variable, value, decay, zero_debias=True, name=None): # In a replica context, we update variable using the mean of value across # replicas. def merge_fn(strategy, v, value): - value = strategy.reduce( - variable_scope.VariableAggregation.MEAN, value, v) + value = strategy.extended.reduce_to( + ds_reduce_util.ReduceOp.MEAN, value, v) return strategy.update(v, update_fn, value) - return replica_context.merge_call(merge_fn, variable, value) + return replica_context.merge_call(merge_fn, args=(variable, value)) else: strategy = distribution_strategy_context.get_cross_replica_context() return strategy.update(variable, update_fn, value) diff --git a/tensorflow/python/training/moving_averages_test.py b/tensorflow/python/training/moving_averages_test.py index bb2fca66e3..b15f7377f0 100644 --- a/tensorflow/python/training/moving_averages_test.py +++ b/tensorflow/python/training/moving_averages_test.py @@ -35,6 +35,7 @@ from tensorflow.python.training import saver as saver_lib class MovingAveragesTest(test.TestCase): + @test_util.run_deprecated_v1 def testAssignMovingAverageWithoutZeroDebias(self): with self.cached_session(): var = variables.Variable([10.0, 11.0]) @@ -43,12 +44,13 @@ class MovingAveragesTest(test.TestCase): assign = moving_averages.assign_moving_average( var, val, decay, zero_debias=False) variables.global_variables_initializer().run() - self.assertAllClose([10.0, 11.0], var.eval()) + self.assertAllClose([10.0, 11.0], self.evaluate(var)) assign.op.run() self.assertAllClose( [10.0 * 0.25 + 1.0 * (1.0 - 0.25), 11.0 * 0.25 + 2.0 * (1.0 - 0.25)], - var.eval()) + self.evaluate(var)) + @test_util.run_deprecated_v1 def testAssignMovingAverage(self): with self.cached_session(): var = variables.Variable([0.0, 0.0]) @@ -56,12 +58,13 @@ class MovingAveragesTest(test.TestCase): decay = 0.25 assign = moving_averages.assign_moving_average(var, val, decay) variables.global_variables_initializer().run() - self.assertAllClose([0.0, 0.0], var.eval()) + self.assertAllClose([0.0, 0.0], self.evaluate(var)) assign.op.run() - self.assertAllClose([ - 1.0 * (1.0 - 0.25) / (1 - 0.25), 2.0 * (1.0 - 0.25) / (1 - 0.25) - ], var.eval()) + self.assertAllClose( + [1.0 * (1.0 - 0.25) / (1 - 0.25), 2.0 * (1.0 - 0.25) / (1 - 0.25)], + self.evaluate(var)) + @test_util.run_deprecated_v1 def testAssignMovingAverageNewNamingMultipleCalls(self): with variable_scope.variable_scope("scope1") as vs1: with variable_scope.variable_scope("scope2"): @@ -76,6 +79,7 @@ class MovingAveragesTest(test.TestCase): actual_names = [v.name for v in vs1.global_variables()] self.assertSetEqual(set(expected_names), set(actual_names)) + @test_util.run_deprecated_v1 def testAssignMovingAverageNewNamingMultipleCallsWithReuse(self): with variable_scope.variable_scope("scope1") as vs1: var = variable_scope.get_variable("Var", shape=[]) @@ -86,6 +90,7 @@ class MovingAveragesTest(test.TestCase): moving_averages.assign_moving_average(var, 0.0, 0.99) moving_averages.assign_moving_average(var, 0.0, 0.99) + @test_util.run_deprecated_v1 def testWeightedMovingAverage(self): with self.cached_session() as sess: decay = 0.5 @@ -111,6 +116,7 @@ class MovingAveragesTest(test.TestCase): denominator_2 = denominator_1 * decay + weight_2 * (1.0 - decay) self.assertAllClose(numerator_2 / denominator_2, wma_array) + @test_util.run_deprecated_v1 def testWeightedMovingAverageBfloat16(self): bfloat16 = pywrap_tensorflow.TF_bfloat16_type() with self.cached_session() as sess: @@ -179,66 +185,72 @@ class ExponentialMovingAverageTest(test.TestCase): self.assertEqual("add/ExponentialMovingAverage:0", avg2.name) # Check initial values. - self.assertAllClose(tens, var0.eval()) - self.assertAllClose(thirties, var1.eval()) - self.assertAllClose(_Repeat(10.0 + 30.0, dim), tensor2.eval()) + self.assertAllClose(tens, self.evaluate(var0)) + self.assertAllClose(thirties, self.evaluate(var1)) + self.assertAllClose(_Repeat(10.0 + 30.0, dim), self.evaluate(tensor2)) # Check that averages are initialized correctly. - self.assertAllClose(tens, avg0.eval()) - self.assertAllClose(thirties, avg1.eval()) + self.assertAllClose(tens, self.evaluate(avg0)) + self.assertAllClose(thirties, self.evaluate(avg1)) # Note that averages of Tensor's initialize to zeros_like since no value # of the Tensor is known because the Op has not been run (yet). - self.assertAllClose(_Repeat(0.0, dim), avg2.eval()) + self.assertAllClose(_Repeat(0.0, dim), self.evaluate(avg2)) # Update the averages and check. update.run() dk = actual_decay expected = _Repeat(10.0 * dk + 10.0 * (1 - dk), dim) - self.assertAllClose(expected, avg0.eval()) + self.assertAllClose(expected, self.evaluate(avg0)) expected = _Repeat(30.0 * dk + 30.0 * (1 - dk), dim) - self.assertAllClose(expected, avg1.eval()) + self.assertAllClose(expected, self.evaluate(avg1)) expected = _Repeat(0.0 * dk + (10.0 + 30.0) * (1 - dk) / _Scale(dk, 1), dim) - self.assertAllClose(expected, avg2.eval()) + self.assertAllClose(expected, self.evaluate(avg2)) # Again, update the averages and check. update.run() expected = _Repeat((10.0 * dk + 10.0 * (1 - dk)) * dk + 10.0 * (1 - dk), dim) - self.assertAllClose(expected, avg0.eval()) + self.assertAllClose(expected, self.evaluate(avg0)) expected = _Repeat((30.0 * dk + 30.0 * (1 - dk)) * dk + 30.0 * (1 - dk), dim) - self.assertAllClose(expected, avg1.eval()) + self.assertAllClose(expected, self.evaluate(avg1)) expected = _Repeat(((0.0 * dk + (10.0 + 30.0) * (1 - dk)) * dk + (10.0 + 30.0) * (1 - dk)) / _Scale(dk, 2), dim) - self.assertAllClose(expected, avg2.eval()) + self.assertAllClose(expected, self.evaluate(avg2)) + @test_util.run_deprecated_v1 def testAverageVariablesNoNumUpdates_Scalar(self): with self.cached_session(): ema = moving_averages.ExponentialMovingAverage(0.25) self._CheckDecay(ema, actual_decay=0.25, dim=1) + @test_util.run_deprecated_v1 def testAverageVariablesNoNumUpdates_Scalar_Debias(self): with self.cached_session(): ema = moving_averages.ExponentialMovingAverage(0.25, zero_debias=True) self._CheckDecay(ema, actual_decay=0.25, dim=1) + @test_util.run_deprecated_v1 def testAverageVariablesNoNumUpdates_Vector(self): with self.cached_session(): ema = moving_averages.ExponentialMovingAverage(0.25) self._CheckDecay(ema, actual_decay=0.25, dim=5) + @test_util.run_deprecated_v1 def testAverageVariablesNoNumUpdates_Vector_Debias(self): with self.cached_session(): ema = moving_averages.ExponentialMovingAverage(0.25, zero_debias=True) self._CheckDecay(ema, actual_decay=0.25, dim=5) + @test_util.run_deprecated_v1 def testAverageVariablesNumUpdates_Scalar(self): with self.cached_session(): # With num_updates 1, the decay applied is 0.1818 ema = moving_averages.ExponentialMovingAverage(0.25, num_updates=1) self._CheckDecay(ema, actual_decay=0.181818, dim=1) + @test_util.run_deprecated_v1 def testAverageVariablesNumUpdates_Scalar_Debias(self): with self.cached_session(): # With num_updates 1, the decay applied is 0.1818 @@ -246,12 +258,14 @@ class ExponentialMovingAverageTest(test.TestCase): 0.25, num_updates=1, zero_debias=True) self._CheckDecay(ema, actual_decay=0.181818, dim=1) + @test_util.run_deprecated_v1 def testAverageVariablesNumUpdates_Vector(self): with self.cached_session(): # With num_updates 1, the decay applied is 0.1818 ema = moving_averages.ExponentialMovingAverage(0.25, num_updates=1) self._CheckDecay(ema, actual_decay=0.181818, dim=5) + @test_util.run_deprecated_v1 def testAverageVariablesNumUpdates_Vector_Debias(self): with self.cached_session(): # With num_updates 1, the decay applied is 0.1818 @@ -259,6 +273,7 @@ class ExponentialMovingAverageTest(test.TestCase): 0.25, num_updates=1, zero_debias=True) self._CheckDecay(ema, actual_decay=0.181818, dim=5) + @test_util.run_deprecated_v1 def testAverageVariablesWithControlDeps(self): with self.cached_session() as sess: v0 = variables.Variable(0, name="v0") @@ -274,16 +289,17 @@ class ExponentialMovingAverageTest(test.TestCase): self.assertEqual([], v1_avg.value().op.control_inputs) self.assertEqual([], v1_avg.value().op.control_inputs) # We should be able to initialize v1_avg before v0. - sess.run(v1_avg.initializer) - sess.run(v0.initializer) - self.assertEqual([10.0], sess.run(v1_avg)) + self.evaluate(v1_avg.initializer) + self.evaluate(v0.initializer) + self.assertEqual([10.0], self.evaluate(v1_avg)) # running ema_op should add to v0 (in addition to updating v1_avg) - sess.run(assign_to_v1) - sess.run(ema_op) - self.assertEqual(1, sess.run(v0)) - self.assertEqual([17.5], sess.run(v1_avg)) + self.evaluate(assign_to_v1) + self.evaluate(ema_op) + self.assertEqual(1, self.evaluate(v0)) + self.assertEqual([17.5], self.evaluate(v1_avg)) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testBasicEager(self): v0 = variables.Variable(1.0) v1 = variables.Variable(2.0) @@ -339,9 +355,11 @@ class ExponentialMovingAverageTest(test.TestCase): self.assertEqual(ema.average(v1).op.name, ema.average_name(v1)) self.assertEqual(ema.average(tensor2).op.name, ema.average_name(tensor2)) + @test_util.run_deprecated_v1 def testAverageVariablesNames(self): self.averageVariablesNamesHelper(zero_debias=True) + @test_util.run_deprecated_v1 def testAverageVariablesNamesNoDebias(self): self.averageVariablesNamesHelper(zero_debias=False) @@ -387,12 +405,15 @@ class ExponentialMovingAverageTest(test.TestCase): self.assertEqual( ema.average(tensor2).op.name, ema.average_name(tensor2)) + @test_util.run_deprecated_v1 def testAverageVariablesNamesRespectScope(self): self.averageVariablesNamesRespectScopeHelper(zero_debias=True) + @test_util.run_deprecated_v1 def testAverageVariablesNamesRespectScopeNoDebias(self): self.averageVariablesNamesRespectScopeHelper(zero_debias=False) + @test_util.run_deprecated_v1 def testSubsetAverageVariablesNames(self): with self.cached_session(): v0 = variables.Variable(10.0, name="v0") @@ -421,6 +442,7 @@ class ExponentialMovingAverageTest(test.TestCase): self.assertEqual(ema.average(v1).op.name, ema.average_name(v1)) self.assertEqual(ema.average(tensor2).op.name, ema.average_name(tensor2)) + @test_util.run_deprecated_v1 def testAverageVariablesDeviceAssignment(self): with ops.device("/job:dev_v0"): v0 = variables.Variable(10.0, name="v0") @@ -451,6 +473,7 @@ class ExponentialMovingAverageTest(test.TestCase): _ = saver_lib.import_meta_graph(meta_graph) return graph_copy + @test_util.run_deprecated_v1 def testImportedGraphVariablesToRestore(self): g = ops.Graph() with g.as_default(): diff --git a/tensorflow/python/training/optimizer.py b/tensorflow/python/training/optimizer.py index 9dfa9d2afb..a9508b862a 100644 --- a/tensorflow/python/training/optimizer.py +++ b/tensorflow/python/training/optimizer.py @@ -24,6 +24,8 @@ import abc import six +from tensorflow.python.distribute import distribute_lib +from tensorflow.python.distribute import reduce_util as ds_reduce_util from tensorflow.python.eager import backprop from tensorflow.python.eager import context from tensorflow.python.framework import dtypes @@ -36,7 +38,6 @@ from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import state_ops from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables -from tensorflow.python.training import distribute as distribute_lib from tensorflow.python.training import distribution_strategy_context as distribute_ctx from tensorflow.python.training import slot_creator from tensorflow.python.training.checkpointable import base as checkpointable @@ -200,8 +201,7 @@ def _get_processor(v): return _TensorProcessor(v) else: return _DenseResourceVariableProcessor(v) - if isinstance( - v, resource_variable_ops.ResourceVariable) and not v._in_graph_mode: # pylint: disable=protected-access + if resource_variable_ops.is_resource_variable(v) and not v._in_graph_mode: # pylint: disable=protected-access # True if and only if `v` was initialized eagerly. return _DenseResourceVariableProcessor(v) if v.op.type == "VarHandleOp": @@ -213,7 +213,7 @@ def _get_processor(v): raise NotImplementedError("Trying to optimize unsupported type ", v) -@tf_export("train.Optimizer") +@tf_export(v1=["train.Optimizer"]) class Optimizer( # Optimizers inherit from CheckpointableBase rather than Checkpointable # since they do most of their dependency management themselves (slot @@ -520,8 +520,7 @@ class Optimizer( @staticmethod def _scale_loss(loss_value): - if (distribute_lib.get_loss_reduction() == - variable_scope.VariableAggregation.MEAN): + if distribute_lib.get_loss_reduction() == ds_reduce_util.ReduceOp.MEAN: num_replicas = \ distribute_ctx.get_distribution_strategy().num_replicas_in_sync if num_replicas > 1: @@ -565,7 +564,7 @@ class Optimizer( if distribute_ctx.has_distribution_strategy(): grads_and_vars = get_filtered_grad_fn(lambda: grads_and_vars)() return distribute_ctx.get_replica_context().merge_call( - self._distributed_apply, grads_and_vars, global_step, name) + self._distributed_apply, args=(grads_and_vars, global_step, name)) # No DistributionStrategy case. grads_and_vars = tuple(grads_and_vars) # Make sure repeat iteration works. @@ -658,14 +657,16 @@ class Optimizer( Returns: An `Operation` that applies the specified gradients across all replicas. If `global_step` was not None, that operation also - increments `global_step`. + increments `global_step` """ - reduced_grads = distribution.batch_reduce( - variable_scope.VariableAggregation.SUM, grads_and_vars) + reduced_grads = distribution.extended.batch_reduce_to( + ds_reduce_util.ReduceOp.SUM, grads_and_vars) var_list = [v for _, v in grads_and_vars] grads_and_vars = zip(reduced_grads, var_list) + # Note that this is called in a cross-replica context. - self._create_slots(var_list) + with ops.init_scope(): + self._create_slots(var_list) def update(v, g): """Apply gradients to a replica variable.""" @@ -682,7 +683,13 @@ class Optimizer( "Gradient must be a Tensor, IndexedSlices, or None: %s" % g) p = _get_processor(v) - scope_name = "" if context.executing_eagerly() else v.op.name + if context.executing_eagerly() or ( + resource_variable_ops.is_resource_variable(v) and + not v._in_graph_mode): # pylint: disable=protected-access + scope_name = v.name.split(":")[0] + else: + scope_name = v.op.name + # device_policy is set because non-mirrored tensors will be read in # `update_op`. `_resource_apply_dense`, `lr_t`, `beta1_t` and `beta2_t` # is an example. @@ -695,21 +702,23 @@ class Optimizer( update_ops = [ op for grad, var in grads_and_vars - for op in distribution.update(var, update, grad, grouped=False) + for op in distribution.extended.update( + var, update, args=(grad,), group=False) ] def finish(self, update_ops): return self._finish(update_ops, "update") - non_slot_devices = distribution.non_slot_devices(var_list) - finish_updates = distribution.update_non_slot( - non_slot_devices, finish, self, update_ops, grouped=False) + non_slot_devices = distribution.extended.non_slot_devices(var_list) + finish_updates = distribution.extended.update_non_slot( + non_slot_devices, finish, args=(self, update_ops), group=False) if global_step is None: apply_updates = distribution.group(finish_updates, name=name) else: with ops.control_dependencies(finish_updates): - apply_updates = distribution.update( - global_step, state_ops.assign_add, 1, name=name) + apply_updates = distribution.extended.update( + global_step, state_ops.assign_add, args=(1,), + kwargs={"name": name}) if not context.executing_eagerly(): if isinstance(apply_updates, ops.Tensor): @@ -747,7 +756,7 @@ class Optimizer( # `_resource_apply_dense`. distributed_container = var._distributed_container() assert distributed_container is not None - if context.executing_eagerly(): + if ops.executing_eagerly_outside_functions(): key = distributed_container._unique_id else: key = (distributed_container.graph, distributed_container._shared_name) diff --git a/tensorflow/python/training/optimizer_test.py b/tensorflow/python/training/optimizer_test.py index 7a7d01d50e..e175b5a799 100644 --- a/tensorflow/python/training/optimizer_test.py +++ b/tensorflow/python/training/optimizer_test.py @@ -62,6 +62,7 @@ class OptimizerTest(test.TestCase): self.assertAllClose([-14., -13.], self.evaluate(var0)) self.assertAllClose([-6., -5.], self.evaluate(var1)) + @test_util.run_deprecated_v1 def testAggregationMethod(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -79,14 +80,15 @@ class OptimizerTest(test.TestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 1 step of sgd through optimizer opt_op.run() # Validate updated params - self.assertAllClose([-14., -13.], var0.eval()) - self.assertAllClose([-6., -5.], var1.eval()) + self.assertAllClose([-14., -13.], self.evaluate(var0)) + self.assertAllClose([-6., -5.], self.evaluate(var1)) + @test_util.run_deprecated_v1 def testPrecomputedGradient(self): for dtype in [dtypes.half, dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -102,15 +104,15 @@ class OptimizerTest(test.TestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 1 step of sgd through optimizer opt_op.run() # Validate updated params self.assertAllClose([1.0 - 3 * 5 * 42.0, 2.0 - 3 * 5 * (-42.0)], - var0.eval()) + self.evaluate(var0)) self.assertAllClose([3.0 - 3 * 3 * 42.0, 4.0 - 3 * 3 * (-42.0)], - var1.eval()) + self.evaluate(var1)) @test_util.run_in_graph_and_eager_modes def testNoVariables(self): @@ -230,6 +232,7 @@ class OptimizerTest(test.TestCase): with self.assertRaises(NotImplementedError): sgd_op.apply_gradients(grads_and_vars) + @test_util.run_deprecated_v1 def testTrainOp(self): with self.cached_session(): var0 = variables.Variable([1.0, 2.0]) @@ -241,6 +244,7 @@ class OptimizerTest(test.TestCase): opt_op = sgd_op.minimize(cost, global_step, [var0, var1]) self.assertTrue(opt_op in ops.get_collection(ops.GraphKeys.TRAIN_OP)) + @test_util.run_deprecated_v1 def testConstraint(self): constraint_01 = lambda x: clip_ops.clip_by_value(x, -0.1, 0.) constraint_0 = lambda x: clip_ops.clip_by_value(x, 0., 1.) @@ -257,13 +261,13 @@ class OptimizerTest(test.TestCase): variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 1 step of sgd through optimizer opt_op.run() # Validate updated params - self.assertAllClose([-0.1, -0.1], var0.eval()) - self.assertAllClose([0., 0.], var1.eval()) + self.assertAllClose([-0.1, -0.1], self.evaluate(var0)) + self.assertAllClose([0., 0.], self.evaluate(var1)) if __name__ == '__main__': diff --git a/tensorflow/python/training/proximal_adagrad.py b/tensorflow/python/training/proximal_adagrad.py index 9bd677b8ef..2ea628a56b 100644 --- a/tensorflow/python/training/proximal_adagrad.py +++ b/tensorflow/python/training/proximal_adagrad.py @@ -26,7 +26,7 @@ from tensorflow.python.training import training_ops from tensorflow.python.util.tf_export import tf_export -@tf_export("train.ProximalAdagradOptimizer") +@tf_export(v1=["train.ProximalAdagradOptimizer"]) class ProximalAdagradOptimizer(optimizer.Optimizer): # pylint: disable=line-too-long """Optimizer that implements the Proximal Adagrad algorithm. diff --git a/tensorflow/python/training/proximal_adagrad_test.py b/tensorflow/python/training/proximal_adagrad_test.py index 74e06a5e2e..ce214ac418 100644 --- a/tensorflow/python/training/proximal_adagrad_test.py +++ b/tensorflow/python/training/proximal_adagrad_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import embedding_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import resource_variable_ops @@ -48,7 +49,7 @@ class ProximalAdagradOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose([0.0, 0.0], v0_val) self.assertAllClose([0.0, 0.0], v1_val) @@ -56,7 +57,7 @@ class ProximalAdagradOptimizerTest(test.TestCase): for _ in range(3): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose(np.array([-2.60260963, -4.29698515]), v0_val) self.assertAllClose(np.array([-0.28432083, -0.56694895]), v1_val) opt_vars = opt.variables() @@ -64,12 +65,15 @@ class ProximalAdagradOptimizerTest(test.TestCase): self.assertStartsWith(opt_vars[1].name, var1._shared_name) self.assertEqual(2, len(opt_vars)) + @test_util.run_deprecated_v1 def testProximalAdagradwithoutRegularization(self): self.doTestProximalAdagradwithoutRegularization(use_resource=False) + @test_util.run_deprecated_v1 def testResourceProximalAdagradwithoutRegularization(self): self.doTestProximalAdagradwithoutRegularization(use_resource=True) + @test_util.run_deprecated_v1 def testProximalAdagradwithoutRegularization2(self): with self.cached_session() as sess: var0 = variables.Variable([1.0, 2.0]) @@ -85,17 +89,18 @@ class ProximalAdagradOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose([1.0, 2.0], v0_val) self.assertAllClose([4.0, 3.0], v1_val) # Run 3 steps Proximal Adagrad. for _ in range(3): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose(np.array([-1.60261, -2.296985]), v0_val) self.assertAllClose(np.array([3.715679, 2.433051]), v1_val) + @test_util.run_deprecated_v1 def testMinimizeSparseResourceVariable(self): for dtype in [dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -106,13 +111,15 @@ class ProximalAdagradOptimizerTest(test.TestCase): sgd_op = proximal_adagrad.ProximalAdagradOptimizer(1.0).minimize(loss) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([[1.0, 2.0]], var0.eval()) + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) # Run 1 step of sgd sgd_op.run() # Validate updated params - self.assertAllCloseAccordingToType( - [[0, 1]], var0.eval(), atol=0.01) + self.assertAllCloseAccordingToType([[0, 1]], + self.evaluate(var0), + atol=0.01) + @test_util.run_deprecated_v1 def testProximalAdagradWithL1(self): with self.cached_session() as sess: var0 = variables.Variable([1.0, 2.0]) @@ -128,17 +135,18 @@ class ProximalAdagradOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose([1.0, 2.0], v0_val) self.assertAllClose([4.0, 3.0], v1_val) # Run 10 steps Proximal Adagrad for _ in range(10): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose(np.array([-6.663634, -9.190331]), v0_val) self.assertAllClose(np.array([2.959304, 1.029232]), v1_val) + @test_util.run_deprecated_v1 def testProximalAdagradWithL1_L2(self): with self.cached_session() as sess: var0 = variables.Variable([1.0, 2.0]) @@ -154,7 +162,7 @@ class ProximalAdagradOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose([1.0, 2.0], v0_val) self.assertAllClose([4.0, 3.0], v1_val) @@ -162,7 +170,7 @@ class ProximalAdagradOptimizerTest(test.TestCase): for _ in range(10): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose(np.array([-0.0495, -0.0995]), v0_val) self.assertAllClose(np.array([-0.0045, -0.0095]), v1_val) @@ -190,7 +198,7 @@ class ProximalAdagradOptimizerTest(test.TestCase): variables.global_variables_initializer().run() sess = ops.get_default_session() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) if is_sparse: self.assertAllClose([[1.0], [2.0]], v0_val) self.assertAllClose([[3.0], [4.0]], v1_val) @@ -202,9 +210,10 @@ class ProximalAdagradOptimizerTest(test.TestCase): for _ in range(steps): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) return v0_val, v1_val + @test_util.run_deprecated_v1 def testEquivAdagradwithoutRegularization(self): with self.cached_session(): val0, val1 = self.applyOptimizer( @@ -222,6 +231,7 @@ class ProximalAdagradOptimizerTest(test.TestCase): self.assertAllClose(val0, val2) self.assertAllClose(val1, val3) + @test_util.run_deprecated_v1 def testEquivSparseAdagradwithoutRegularization(self): with self.cached_session(): val0, val1 = self.applyOptimizer( diff --git a/tensorflow/python/training/proximal_gradient_descent_test.py b/tensorflow/python/training/proximal_gradient_descent_test.py index f77f68b234..25b206605d 100644 --- a/tensorflow/python/training/proximal_gradient_descent_test.py +++ b/tensorflow/python/training/proximal_gradient_descent_test.py @@ -23,6 +23,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import embedding_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import resource_variable_ops @@ -50,7 +51,7 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose([0.0, 0.0], v0_val) self.assertAllClose([0.0, 0.0], v1_val) @@ -58,16 +59,19 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): for _ in range(3): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose(np.array([-0.9, -1.8]), v0_val) self.assertAllClose(np.array([-0.09, -0.18]), v1_val) + @test_util.run_deprecated_v1 def testProximalGradientDescentwithoutRegularization(self): self.doTestProximalGradientDescentwithoutRegularization(use_resource=False) + @test_util.run_deprecated_v1 def testResourceProximalGradientDescentwithoutRegularization(self): self.doTestProximalGradientDescentwithoutRegularization(use_resource=True) + @test_util.run_deprecated_v1 def testProximalGradientDescentwithoutRegularization2(self): with self.cached_session() as sess: var0 = variables.Variable([1.0, 2.0]) @@ -80,7 +84,7 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose([1.0, 2.0], v0_val) self.assertAllClose([4.0, 3.0], v1_val) @@ -88,10 +92,11 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): for _ in range(3): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose(np.array([0.1, 0.2]), v0_val) self.assertAllClose(np.array([3.91, 2.82]), v1_val) + @test_util.run_deprecated_v1 def testMinimizeSparseResourceVariable(self): for dtype in [dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -103,13 +108,15 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): 1.0).minimize(loss) variables.global_variables_initializer().run() # Fetch params to validate initial values - self.assertAllCloseAccordingToType([[1.0, 2.0]], var0.eval()) + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) # Run 1 step of sgd sgd_op.run() # Validate updated params - self.assertAllCloseAccordingToType( - [[-111, -138]], var0.eval(), atol=0.01) + self.assertAllCloseAccordingToType([[-111, -138]], + self.evaluate(var0), + atol=0.01) + @test_util.run_deprecated_v1 def testProximalGradientDescentWithL1_L2(self): with self.cached_session() as sess: var0 = variables.Variable([1.0, 2.0]) @@ -122,7 +129,7 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) variables.global_variables_initializer().run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose([1.0, 2.0], v0_val) self.assertAllClose([4.0, 3.0], v1_val) @@ -130,7 +137,7 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): for _ in range(10): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) self.assertAllClose(np.array([-0.0495, -0.0995]), v0_val) self.assertAllClose(np.array([-0.0045, -0.0095]), v1_val) @@ -158,7 +165,7 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): variables.global_variables_initializer().run() sess = ops.get_default_session() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) if is_sparse: self.assertAllClose([[1.0], [2.0]], v0_val) self.assertAllClose([[3.0], [4.0]], v1_val) @@ -170,9 +177,10 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): for _ in range(steps): update.run() - v0_val, v1_val = sess.run([var0, var1]) + v0_val, v1_val = self.evaluate([var0, var1]) return v0_val, v1_val + @test_util.run_deprecated_v1 def testEquivSparseGradientDescentwithoutRegularization(self): with self.cached_session(): val0, val1 = self.applyOptimizer( @@ -189,6 +197,7 @@ class ProximalGradientDescentOptimizerTest(test.TestCase): self.assertAllClose(val0, val2) self.assertAllClose(val1, val3) + @test_util.run_deprecated_v1 def testEquivGradientDescentwithoutRegularization(self): with self.cached_session(): val0, val1 = self.applyOptimizer( diff --git a/tensorflow/python/training/quantize_training_test.py b/tensorflow/python/training/quantize_training_test.py index 6edbf7665f..62e783f200 100644 --- a/tensorflow/python/training/quantize_training_test.py +++ b/tensorflow/python/training/quantize_training_test.py @@ -25,6 +25,7 @@ from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import importer from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test @@ -52,6 +53,7 @@ class PywrapQuantizeTrainingTest(test.TestCase): # Test that save/restoring works for EMA variables generated in the # quantized training rewrite. + @test_util.run_deprecated_v1 def testQuantizedSaveRestore(self): save_path = os.path.join(self.get_temp_dir(), 'quantized_save_restore') @@ -73,11 +75,11 @@ class PywrapQuantizeTrainingTest(test.TestCase): _ = importer.import_graph_def(result, name='') # Initialize the variable. - sess.run(g.get_operation_by_name(init_op.name)) + self.evaluate(g.get_operation_by_name(init_op.name)) # Run the graph for one step to assign values to the quantization min/max # variables. - sess.run(g.get_tensor_by_name(c.name)) + self.evaluate(g.get_tensor_by_name(c.name)) saver.save(sess, save_path) diff --git a/tensorflow/python/training/queue_runner_test.py b/tensorflow/python/training/queue_runner_test.py index 15fe42bbd8..4113cecf55 100644 --- a/tensorflow/python/training/queue_runner_test.py +++ b/tensorflow/python/training/queue_runner_test.py @@ -26,6 +26,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import data_flow_ops from tensorflow.python.ops import variables @@ -40,6 +41,7 @@ _MockOp = collections.namedtuple("MockOp", ["name"]) class QueueRunnerTest(test.TestCase): + @test_util.run_deprecated_v1 def testBasic(self): with self.cached_session() as sess: # CountUpTo will raise OUT_OF_RANGE when it reaches the count. @@ -58,8 +60,9 @@ class QueueRunnerTest(test.TestCase): t.join() self.assertEqual(0, len(qr.exceptions_raised)) # The variable should be 3. - self.assertEqual(3, var.eval()) + self.assertEqual(3, self.evaluate(var)) + @test_util.run_deprecated_v1 def testTwoOps(self): with self.cached_session() as sess: # CountUpTo will raise OUT_OF_RANGE when it reaches the count. @@ -80,9 +83,10 @@ class QueueRunnerTest(test.TestCase): for t in threads: t.join() self.assertEqual(0, len(qr.exceptions_raised)) - self.assertEqual(3, var0.eval()) - self.assertEqual(30, var1.eval()) + self.assertEqual(3, self.evaluate(var0)) + self.assertEqual(30, self.evaluate(var1)) + @test_util.run_deprecated_v1 def testExceptionsCaptured(self): with self.cached_session() as sess: queue = data_flow_ops.FIFOQueue(10, dtypes.float32) @@ -99,6 +103,7 @@ class QueueRunnerTest(test.TestCase): self.assertTrue("Operation not in the graph" in str(exceptions[0])) self.assertTrue("Operation not in the graph" in str(exceptions[1])) + @test_util.run_deprecated_v1 def testRealDequeueEnqueue(self): with self.cached_session() as sess: q0 = data_flow_ops.FIFOQueue(3, dtypes.float32) @@ -121,12 +126,13 @@ class QueueRunnerTest(test.TestCase): # It should have terminated cleanly. self.assertEqual(0, len(qr.exceptions_raised)) # The 2 values should be in queue1. - self.assertEqual(10.0, dequeue1.eval()) - self.assertEqual(10.0, dequeue1.eval()) + self.assertEqual(10.0, self.evaluate(dequeue1)) + self.assertEqual(10.0, self.evaluate(dequeue1)) # And queue1 should now be closed. with self.assertRaisesRegexp(errors_impl.OutOfRangeError, "is closed"): - dequeue1.eval() + self.evaluate(dequeue1) + @test_util.run_deprecated_v1 def testRespectCoordShouldStop(self): with self.cached_session() as sess: # CountUpTo will raise OUT_OF_RANGE when it reaches the count. @@ -149,8 +155,9 @@ class QueueRunnerTest(test.TestCase): coord.join() self.assertEqual(0, len(qr.exceptions_raised)) # The variable should be 0. - self.assertEqual(0, var.eval()) + self.assertEqual(0, self.evaluate(var)) + @test_util.run_deprecated_v1 def testRequestStopOnException(self): with self.cached_session() as sess: queue = data_flow_ops.FIFOQueue(10, dtypes.float32) @@ -163,6 +170,7 @@ class QueueRunnerTest(test.TestCase): with self.assertRaisesRegexp(ValueError, "Operation not in the graph"): coord.join() + @test_util.run_deprecated_v1 def testGracePeriod(self): with self.cached_session() as sess: # The enqueue will quickly block. @@ -180,6 +188,7 @@ class QueueRunnerTest(test.TestCase): # the queue to be closed and the enqueue to terminate. coord.join(stop_grace_period_secs=1.0) + @test_util.run_deprecated_v1 def testMultipleSessions(self): with self.cached_session() as sess: with session.Session() as other_sess: @@ -195,6 +204,7 @@ class QueueRunnerTest(test.TestCase): other_threads = qr.create_threads(other_sess, coord=coord) self.assertEqual(len(threads), len(other_threads)) + @test_util.run_deprecated_v1 def testIgnoreMultiStarts(self): with self.cached_session() as sess: # CountUpTo will raise OUT_OF_RANGE when it reaches the count. @@ -211,6 +221,7 @@ class QueueRunnerTest(test.TestCase): new_threads = qr.create_threads(sess, coord=coord) self.assertEqual([], new_threads) + @test_util.run_deprecated_v1 def testThreads(self): with self.cached_session() as sess: # CountUpTo will raise OUT_OF_RANGE when it reaches the count. @@ -238,6 +249,7 @@ class QueueRunnerTest(test.TestCase): self.assertEqual(1, len(exceptions)) self.assertTrue("Operation not in the graph" in str(exceptions[0])) + @test_util.run_deprecated_v1 def testName(self): with ops.name_scope("scope"): queue = data_flow_ops.FIFOQueue(10, dtypes.float32, name="queue") @@ -247,6 +259,7 @@ class QueueRunnerTest(test.TestCase): self.assertEqual( 1, len(ops.get_collection(ops.GraphKeys.QUEUE_RUNNERS, "scope"))) + @test_util.run_deprecated_v1 def testStartQueueRunners(self): # CountUpTo will raise OUT_OF_RANGE when it reaches the count. zero64 = constant_op.constant(0, dtype=dtypes.int64) @@ -263,8 +276,9 @@ class QueueRunnerTest(test.TestCase): t.join() self.assertEqual(0, len(qr.exceptions_raised)) # The variable should be 3. - self.assertEqual(3, var.eval()) + self.assertEqual(3, self.evaluate(var)) + @test_util.run_deprecated_v1 def testStartQueueRunnersRaisesIfNotASession(self): zero64 = constant_op.constant(0, dtype=dtypes.int64) var = variables.VariableV1(zero64) @@ -278,6 +292,7 @@ class QueueRunnerTest(test.TestCase): with self.assertRaisesRegexp(TypeError, "tf.Session"): queue_runner_impl.start_queue_runners("NotASession") + @test_util.run_deprecated_v1 def testStartQueueRunnersIgnoresMonitoredSession(self): zero64 = constant_op.constant(0, dtype=dtypes.int64) var = variables.VariableV1(zero64) @@ -292,6 +307,7 @@ class QueueRunnerTest(test.TestCase): monitored_session.MonitoredSession()) self.assertFalse(threads) + @test_util.run_deprecated_v1 def testStartQueueRunnersNonDefaultGraph(self): # CountUpTo will raise OUT_OF_RANGE when it reaches the count. graph = ops.Graph() @@ -310,7 +326,7 @@ class QueueRunnerTest(test.TestCase): t.join() self.assertEqual(0, len(qr.exceptions_raised)) # The variable should be 3. - self.assertEqual(3, var.eval()) + self.assertEqual(3, self.evaluate(var)) def testQueueRunnerSerializationRoundTrip(self): graph = ops.Graph() diff --git a/tensorflow/python/training/rmsprop.py b/tensorflow/python/training/rmsprop.py index f38c9861d6..fb53b5883f 100644 --- a/tensorflow/python/training/rmsprop.py +++ b/tensorflow/python/training/rmsprop.py @@ -50,7 +50,7 @@ from tensorflow.python.training import training_ops from tensorflow.python.util.tf_export import tf_export -@tf_export("train.RMSPropOptimizer") +@tf_export(v1=["train.RMSPropOptimizer"]) class RMSPropOptimizer(optimizer.Optimizer): """Optimizer that implements the RMSProp algorithm. diff --git a/tensorflow/python/training/rmsprop_test.py b/tensorflow/python/training/rmsprop_test.py index b63abe0529..8f029d5310 100644 --- a/tensorflow/python/training/rmsprop_test.py +++ b/tensorflow/python/training/rmsprop_test.py @@ -28,6 +28,7 @@ from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import embedding_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import resource_variable_ops @@ -88,11 +89,12 @@ class RMSPropOptimizerTest(test.TestCase): var_t[gindex] = var[gindex] - mom_t[gindex] return var_t, mg_t, rms_t, mom_t + @test_util.run_deprecated_v1 def testDense(self): # TODO(yori): Use ParameterizedTest when available for (dtype, learning_rate, decay, momentum, epsilon, centered, use_resource) in _TESTPARAMS: - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): # Initialize variables for numpy implementation. var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) grads0_np = np.array([0.1, 0.2], dtype=dtype.as_numpy_dtype) @@ -115,7 +117,7 @@ class RMSPropOptimizerTest(test.TestCase): centered=centered) update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) - variables.global_variables_initializer().run() + self.evaluate(variables.global_variables_initializer()) mg0 = opt.get_slot(var0, "mg") self.assertEqual(mg0 is not None, centered) @@ -138,12 +140,12 @@ class RMSPropOptimizerTest(test.TestCase): mom1_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 4 steps of RMSProp for _ in range(1, 5): - update.run() + self.evaluate(update) var0_np, mg0_np, rms0_np, mom0_np = self._rmsprop_update_numpy( var0_np, grads0_np, mg0_np, rms0_np, mom0_np, learning_rate, @@ -154,15 +156,16 @@ class RMSPropOptimizerTest(test.TestCase): # Validate updated params if centered: - self.assertAllCloseAccordingToType(mg0_np, mg0.eval()) - self.assertAllCloseAccordingToType(mg1_np, mg1.eval()) - self.assertAllCloseAccordingToType(rms0_np, rms0.eval()) - self.assertAllCloseAccordingToType(rms1_np, rms1.eval()) - self.assertAllCloseAccordingToType(mom0_np, mom0.eval()) - self.assertAllCloseAccordingToType(mom1_np, mom1.eval()) - self.assertAllCloseAccordingToType(var0_np, var0.eval()) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) - + self.assertAllCloseAccordingToType(mg0_np, self.evaluate(mg0)) + self.assertAllCloseAccordingToType(mg1_np, self.evaluate(mg1)) + self.assertAllCloseAccordingToType(rms0_np, self.evaluate(rms0)) + self.assertAllCloseAccordingToType(rms1_np, self.evaluate(rms1)) + self.assertAllCloseAccordingToType(mom0_np, self.evaluate(mom0)) + self.assertAllCloseAccordingToType(mom1_np, self.evaluate(mom1)) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 def testMinimizeSparseResourceVariable(self): for dtype in [dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -176,15 +179,17 @@ class RMSPropOptimizerTest(test.TestCase): momentum=0.0, epsilon=0.0, centered=False).minimize(loss) - variables.global_variables_initializer().run() + self.evaluate(variables.global_variables_initializer()) # Fetch params to validate initial values - self.assertAllCloseAccordingToType([[1.0, 2.0]], var0.eval()) + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) # Run 1 step of sgd - sgd_op.run() + self.evaluate(sgd_op) # Validate updated params - self.assertAllCloseAccordingToType( - [[0., 1.]], var0.eval(), atol=0.01) + self.assertAllCloseAccordingToType([[0., 1.]], + self.evaluate(var0), + atol=0.01) + @test_util.run_deprecated_v1 def testMinimizeSparseResourceVariableCentered(self): for dtype in [dtypes.float32, dtypes.float64]: with self.cached_session(): @@ -198,20 +203,22 @@ class RMSPropOptimizerTest(test.TestCase): momentum=0.0, epsilon=1.0, centered=True).minimize(loss) - variables.global_variables_initializer().run() + self.evaluate(variables.global_variables_initializer()) # Fetch params to validate initial values - self.assertAllCloseAccordingToType([[1.0, 2.0]], var0.eval()) + self.assertAllCloseAccordingToType([[1.0, 2.0]], self.evaluate(var0)) # Run 1 step of sgd - sgd_op.run() + self.evaluate(sgd_op) # Validate updated params - self.assertAllCloseAccordingToType( - [[-111, -138]], var0.eval(), atol=0.01) + self.assertAllCloseAccordingToType([[-111, -138]], + self.evaluate(var0), + atol=0.01) + @test_util.run_deprecated_v1 def testSparse(self): # TODO(yori): Use ParameterizedTest when available for (dtype, learning_rate, decay, momentum, epsilon, centered, _) in _TESTPARAMS: - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): # Initialize variables for numpy implementation. var0_np = np.array([1.0, 2.0], dtype=dtype.as_numpy_dtype) grads0_np = np.array([0.1], dtype=dtype.as_numpy_dtype) @@ -235,7 +242,7 @@ class RMSPropOptimizerTest(test.TestCase): epsilon=epsilon, centered=centered) update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) - variables.global_variables_initializer().run() + self.evaluate(variables.global_variables_initializer()) mg0 = opt.get_slot(var0, "mg") self.assertEqual(mg0 is not None, centered) @@ -258,12 +265,12 @@ class RMSPropOptimizerTest(test.TestCase): mom1_np = np.array([0.0, 0.0], dtype=dtype.as_numpy_dtype) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Run 4 steps of RMSProp for _ in range(1, 5): - update.run() + self.evaluate(update) var0_np, mg0_np, rms0_np, mom0_np = self._sparse_rmsprop_update_numpy( var0_np, grads0_np_indices, grads0_np, mg0_np, rms0_np, mom0_np, @@ -274,18 +281,19 @@ class RMSPropOptimizerTest(test.TestCase): # Validate updated params if centered: - self.assertAllCloseAccordingToType(mg0_np, mg0.eval()) - self.assertAllCloseAccordingToType(mg1_np, mg1.eval()) - self.assertAllCloseAccordingToType(rms0_np, rms0.eval()) - self.assertAllCloseAccordingToType(rms1_np, rms1.eval()) - self.assertAllCloseAccordingToType(mom0_np, mom0.eval()) - self.assertAllCloseAccordingToType(mom1_np, mom1.eval()) - self.assertAllCloseAccordingToType(var0_np, var0.eval()) - self.assertAllCloseAccordingToType(var1_np, var1.eval()) - + self.assertAllCloseAccordingToType(mg0_np, self.evaluate(mg0)) + self.assertAllCloseAccordingToType(mg1_np, self.evaluate(mg1)) + self.assertAllCloseAccordingToType(rms0_np, self.evaluate(rms0)) + self.assertAllCloseAccordingToType(rms1_np, self.evaluate(rms1)) + self.assertAllCloseAccordingToType(mom0_np, self.evaluate(mom0)) + self.assertAllCloseAccordingToType(mom1_np, self.evaluate(mom1)) + self.assertAllCloseAccordingToType(var0_np, self.evaluate(var0)) + self.assertAllCloseAccordingToType(var1_np, self.evaluate(var1)) + + @test_util.run_deprecated_v1 def testWithoutMomentum(self): for dtype in [dtypes.half, dtypes.float32]: - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): var0 = variables.Variable([1.0, 2.0], dtype=dtype) var1 = variables.Variable([3.0, 4.0], dtype=dtype) grads0 = constant_op.constant([0.1, 0.1], dtype=dtype) @@ -293,7 +301,7 @@ class RMSPropOptimizerTest(test.TestCase): opt = rmsprop.RMSPropOptimizer( learning_rate=2.0, decay=0.9, momentum=0.0, epsilon=1.0) update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) - variables.global_variables_initializer().run() + self.evaluate(variables.global_variables_initializer()) rms0 = opt.get_slot(var0, "rms") self.assertTrue(rms0 is not None) @@ -305,34 +313,36 @@ class RMSPropOptimizerTest(test.TestCase): self.assertTrue(mom1 is not None) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Step 1: the rms accumulators where 1. So we should see a normal # update: v -= grad * learning_rate - update.run() + self.evaluate(update) # Check the root mean square accumulators. self.assertAllCloseAccordingToType( - np.array([0.901, 0.901]), rms0.eval()) + np.array([0.901, 0.901]), self.evaluate(rms0)) self.assertAllCloseAccordingToType( - np.array([0.90001, 0.90001]), rms1.eval()) + np.array([0.90001, 0.90001]), self.evaluate(rms1)) # Check the parameters. self.assertAllCloseAccordingToType( np.array([ 1.0 - (0.1 * 2.0 / math.sqrt(0.901 + 1.0)), 2.0 - (0.1 * 2.0 / math.sqrt(0.901 + 1.0)) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ 3.0 - (0.01 * 2.0 / math.sqrt(0.90001 + 1.0)), 4.0 - (0.01 * 2.0 / math.sqrt(0.90001 + 1.0)) - ]), var1.eval()) + ]), self.evaluate(var1)) # Step 2: the root mean square accumulators contain the previous update. - update.run() + self.evaluate(update) # Check the rms accumulators. self.assertAllCloseAccordingToType( - np.array([0.901 * 0.9 + 0.001, 0.901 * 0.9 + 0.001]), rms0.eval()) + np.array([0.901 * 0.9 + 0.001, 0.901 * 0.9 + 0.001]), + self.evaluate(rms0)) self.assertAllCloseAccordingToType( - np.array([0.90001 * 0.9 + 1e-5, 0.90001 * 0.9 + 1e-5]), rms1.eval()) + np.array([0.90001 * 0.9 + 1e-5, 0.90001 * 0.9 + 1e-5]), + self.evaluate(rms1)) # Check the parameters. self.assertAllCloseAccordingToType( np.array([ @@ -340,18 +350,19 @@ class RMSPropOptimizerTest(test.TestCase): (0.1 * 2.0 / math.sqrt(0.901 * 0.9 + 0.001 + 1.0)), 2.0 - (0.1 * 2.0 / math.sqrt(0.901 + 1.0)) - (0.1 * 2.0 / math.sqrt(0.901 * 0.9 + 0.001 + 1.0)) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ 3.0 - (0.01 * 2.0 / math.sqrt(0.90001 + 1.0)) - (0.01 * 2.0 / math.sqrt(0.90001 * 0.9 + 1e-5 + 1.0)), 4.0 - (0.01 * 2.0 / math.sqrt(0.90001 + 1.0)) - (0.01 * 2.0 / math.sqrt(0.90001 * 0.9 + 1e-5 + 1.0)) - ]), var1.eval()) + ]), self.evaluate(var1)) + @test_util.run_deprecated_v1 def testWithMomentum(self): for dtype in [dtypes.half, dtypes.float32]: - with self.cached_session(use_gpu=True): + with test_util.use_gpu(): var0 = variables.Variable([1.0, 2.0], dtype=dtype) var1 = variables.Variable([3.0, 4.0], dtype=dtype) grads0 = constant_op.constant([0.1, 0.1], dtype=dtype) @@ -360,7 +371,7 @@ class RMSPropOptimizerTest(test.TestCase): opt = rmsprop.RMSPropOptimizer( learning_rate=2.0, decay=0.9, momentum=0.5, epsilon=1e-5) update = opt.apply_gradients(zip([grads0, grads1], [var0, var1])) - variables.global_variables_initializer().run() + self.evaluate(variables.global_variables_initializer()) rms0 = opt.get_slot(var0, "rms") self.assertTrue(rms0 is not None) @@ -372,57 +383,61 @@ class RMSPropOptimizerTest(test.TestCase): self.assertTrue(mom1 is not None) # Fetch params to validate initial values - self.assertAllClose([1.0, 2.0], var0.eval()) - self.assertAllClose([3.0, 4.0], var1.eval()) + self.assertAllClose([1.0, 2.0], self.evaluate(var0)) + self.assertAllClose([3.0, 4.0], self.evaluate(var1)) # Step 1: rms = 1, mom = 0. So we should see a normal # update: v -= grad * learning_rate - update.run() + self.evaluate(update) # Check the root mean square accumulators. self.assertAllCloseAccordingToType( - np.array([0.901, 0.901]), rms0.eval()) + np.array([0.901, 0.901]), self.evaluate(rms0)) self.assertAllCloseAccordingToType( - np.array([0.90001, 0.90001]), rms1.eval()) + np.array([0.90001, 0.90001]), self.evaluate(rms1)) # Check the momentum accumulators self.assertAllCloseAccordingToType( np.array([(0.1 * 2.0 / math.sqrt(0.901 + 1e-5)), - (0.1 * 2.0 / math.sqrt(0.901 + 1e-5))]), mom0.eval()) + (0.1 * 2.0 / math.sqrt(0.901 + 1e-5))]), + self.evaluate(mom0)) self.assertAllCloseAccordingToType( np.array([(0.01 * 2.0 / math.sqrt(0.90001 + 1e-5)), - (0.01 * 2.0 / math.sqrt(0.90001 + 1e-5))]), mom1.eval()) + (0.01 * 2.0 / math.sqrt(0.90001 + 1e-5))]), + self.evaluate(mom1)) # Check that the parameters. self.assertAllCloseAccordingToType( np.array([ 1.0 - (0.1 * 2.0 / math.sqrt(0.901 + 1e-5)), 2.0 - (0.1 * 2.0 / math.sqrt(0.901 + 1e-5)) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ 3.0 - (0.01 * 2.0 / math.sqrt(0.90001 + 1e-5)), 4.0 - (0.01 * 2.0 / math.sqrt(0.90001 + 1e-5)) - ]), var1.eval()) + ]), self.evaluate(var1)) # Step 2: the root mean square accumulators contain the previous update. - update.run() + self.evaluate(update) # Check the rms accumulators. self.assertAllCloseAccordingToType( - np.array([0.901 * 0.9 + 0.001, 0.901 * 0.9 + 0.001]), rms0.eval()) + np.array([0.901 * 0.9 + 0.001, 0.901 * 0.9 + 0.001]), + self.evaluate(rms0)) self.assertAllCloseAccordingToType( - np.array([0.90001 * 0.9 + 1e-5, 0.90001 * 0.9 + 1e-5]), rms1.eval()) + np.array([0.90001 * 0.9 + 1e-5, 0.90001 * 0.9 + 1e-5]), + self.evaluate(rms1)) self.assertAllCloseAccordingToType( np.array([ 0.5 * (0.1 * 2.0 / math.sqrt(0.901 + 1e-5)) + (0.1 * 2.0 / math.sqrt(0.901 * 0.9 + 0.001 + 1e-5)), 0.5 * (0.1 * 2.0 / math.sqrt(0.901 + 1e-5)) + (0.1 * 2.0 / math.sqrt(0.901 * 0.9 + 0.001 + 1e-5)) - ]), mom0.eval()) + ]), self.evaluate(mom0)) self.assertAllCloseAccordingToType( np.array([ 0.5 * (0.01 * 2.0 / math.sqrt(0.90001 + 1e-5)) + (0.01 * 2.0 / math.sqrt(0.90001 * 0.9 + 2e-5)), 0.5 * (0.01 * 2.0 / math.sqrt(0.90001 + 1e-5)) + (0.01 * 2.0 / math.sqrt(0.90001 * 0.9 + 2e-5)) - ]), mom1.eval()) + ]), self.evaluate(mom1)) # Check the parameters. self.assertAllCloseAccordingToType( @@ -433,7 +448,7 @@ class RMSPropOptimizerTest(test.TestCase): 2.0 - (0.1 * 2.0 / math.sqrt(0.901 + 1e-5)) - (0.5 * (0.1 * 2.0 / math.sqrt(0.901 + 1e-5)) + (0.1 * 2.0 / math.sqrt(0.901 * 0.9 + 0.001 + 1e-5))) - ]), var0.eval()) + ]), self.evaluate(var0)) self.assertAllCloseAccordingToType( np.array([ @@ -443,7 +458,7 @@ class RMSPropOptimizerTest(test.TestCase): 4.0 - (0.01 * 2.0 / math.sqrt(0.90001 + 1e-5)) - (0.5 * (0.01 * 2.0 / math.sqrt(0.90001 + 1e-5)) + (0.01 * 2.0 / math.sqrt(0.90001 * 0.9 + 2e-5))) - ]), var1.eval()) + ]), self.evaluate(var1)) def testCallableParams(self): with context.eager_mode(): diff --git a/tensorflow/python/training/saver.py b/tensorflow/python/training/saver.py index a29926a57d..4cd09f8a1d 100644 --- a/tensorflow/python/training/saver.py +++ b/tensorflow/python/training/saver.py @@ -1077,16 +1077,28 @@ class Saver(object): @compatibility(eager) When eager execution is enabled, `var_list` must specify a `list` or `dict` of variables to save. Otherwise, a `RuntimeError` will be raised. + + Although Saver works in some cases when executing eagerly, it is + fragile. Please switch to `tf.train.Checkpoint` or + `tf.keras.Model.save_weights`, which perform a more robust object-based + saving. These APIs will load checkpoints written by `Saver`. @end_compatibility """ if defer_build and var_list: raise ValueError( "If `var_list` is provided then build cannot be deferred. " "Either set defer_build=False or var_list=None.") - if context.executing_eagerly() and var_list is None: - raise RuntimeError( - "When eager execution is enabled, `var_list` must specify a list or " - "dict of variables to save") + if context.executing_eagerly(): + logging.warning( + "Saver is deprecated, please switch to tf.train.Checkpoint or " + "tf.keras.Model.save_weights for training checkpoints. When " + "executing eagerly variables do not necessarily have unique names, " + "and so the variable.name-based lookups Saver performs are " + "error-prone.") + if var_list is None: + raise RuntimeError( + "When eager execution is enabled, `var_list` must specify a list " + "or dict of variables to save") self._var_list = var_list self._reshape = reshape self._sharded = sharded @@ -1899,16 +1911,40 @@ def saver_from_object_based_checkpoint( builder = BulkSaverBuilder() saveables = builder._ValidateAndSliceInputs(var_list) # pylint: disable=protected-access + current_names = set() + for saveable in saveables: + for spec in saveable.specs: + current_names.add(spec.name) + previous_names = set(names_to_keys.keys()) + missing_names = current_names - previous_names + if missing_names: + extra_names = previous_names - current_names + intersecting_names = previous_names.intersection(current_names) + raise errors.NotFoundError( + None, None, + message=( + "\n\nExisting variables not in the checkpoint: %s\n\n" + "Variables names when this checkpoint was written which don't " + "exist now: %s\n\n" + "(%d variable name(s) did match)\n\n" + "Could not find some variables in the checkpoint (see names " + "above). Saver was attempting to load an object-based checkpoint " + "(saved using tf.train.Checkpoint or tf.keras.Model.save_weights) " + "using variable names. If the checkpoint was written with eager " + "execution enabled, it's possible that variable names have " + "changed (for example missing a '_1' suffix). It's also " + "possible that there are new variables which did not exist " + "when the checkpoint was written. You can construct a " + "Saver(var_list=...) with only the variables which previously " + "existed, and if variable names have changed you may need to " + "make this a dictionary with the old names as keys. If you're " + "using an Estimator, you'll need to return a tf.train.Saver " + "inside a tf.train.Scaffold from your model_fn.") + % (", ".join(sorted(missing_names)), ", ".join(sorted(extra_names)), + len(intersecting_names))) for saveable in saveables: for spec in saveable.specs: - if spec.name not in names_to_keys: - raise errors.NotFoundError( - None, None, - message=("Attempting to load an object-based checkpoint using " - "variable names, but could not find %s in the " - "checkpoint.") % spec.name) spec.name = names_to_keys[spec.name] - if cached_saver is None: return Saver(saveables) return cached_saver diff --git a/tensorflow/python/training/saver_large_partitioned_variable_test.py b/tensorflow/python/training/saver_large_partitioned_variable_test.py index 1a44511cfe..84458836d0 100644 --- a/tensorflow/python/training/saver_large_partitioned_variable_test.py +++ b/tensorflow/python/training/saver_large_partitioned_variable_test.py @@ -25,6 +25,7 @@ from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import partitioned_variables +from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables from tensorflow.python.platform import test from tensorflow.python.training import saver @@ -44,8 +45,12 @@ class SaverLargePartitionedVariableTest(test.TestCase): # split into smaller sized variables. init = lambda shape, dtype, partition_info: constant_op.constant( True, dtype, shape) - partitioned_var = partitioned_variables.create_partitioned_variables( - [1 << 31], [4], init, dtype=dtypes.bool, name=var_name) + partitioned_var = list(variable_scope.get_variable( + var_name, + shape=[1 << 31], + partitioner=partitioned_variables.fixed_size_partitioner(4), + initializer=init, + dtype=dtypes.bool)) variables.global_variables_initializer().run() save = saver.Saver(partitioned_var) val = save.save(sess, save_path) diff --git a/tensorflow/python/training/saver_test.py b/tensorflow/python/training/saver_test.py index eb2690985d..5d621ba4ff 100644 --- a/tensorflow/python/training/saver_test.py +++ b/tensorflow/python/training/saver_test.py @@ -170,6 +170,7 @@ class SaverTest(test.TestCase): def testResourceBasic(self): self.basicSaveRestore(resource_variable_ops.ResourceVariable) + @test_util.run_deprecated_v1 def testResourceColocation(self): partitioner = partitioned_variables.fixed_size_partitioner(num_shards=2) with ops_lib.device("/job:ps/device:GPU:0"): @@ -227,7 +228,7 @@ class SaverTest(test.TestCase): w1 = resource_variable_ops.ResourceVariable(1.0, name="w1") w2 = resource_variable_ops.ResourceVariable(2.0, name="w2") graph_saver = saver_module.Saver([w1, w2]) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) graph_saver.save(sess, graph_ckpt_prefix) with context.eager_mode(): @@ -260,7 +261,7 @@ class SaverTest(test.TestCase): w3 = resource_variable_ops.ResourceVariable(0.0, name="w3") w4 = resource_variable_ops.ResourceVariable(0.0, name="w4") graph_saver = saver_module.Saver([w3, w4]) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) graph_saver.restore(sess, eager_ckpt_prefix) self.assertAllEqual(w3.eval(), 3.0) self.assertAllEqual(w4.eval(), 4.0) @@ -300,6 +301,7 @@ class SaverTest(test.TestCase): not op.name.startswith("saver2/save/"))] self.assertEqual(ops_in_saver2_scope_but_not_save_scope, []) + @test_util.run_deprecated_v1 def testSaveCopyRestoreWithSaveRelativePaths(self): """Save, copy checkpoint dir and restore from copied dir. @@ -326,7 +328,7 @@ class SaverTest(test.TestCase): with self.cached_session() as sess: # Initialize all variables - sess.run(init_all_op) + self.evaluate(init_all_op) # Check that the parameter nodes have been initialized. self.assertEqual(10.0, v0.eval()) @@ -369,6 +371,7 @@ class SaverTest(test.TestCase): self.assertEqual(b"k1", v2.keys().eval()) self.assertEqual(30.0, v2.values().eval()) + @test_util.run_deprecated_v1 def testFilenameTensor(self): v0 = variables.VariableV1(0, name="v0") filename = b"somerandomfilename" @@ -376,7 +379,7 @@ class SaverTest(test.TestCase): with self.cached_session() as sess: tensor = sess.graph.get_tensor_by_name( save.saver_def.filename_tensor_name) - self.assertEqual(sess.run(tensor), filename) + self.assertEqual(self.evaluate(tensor), filename) def testInvalidPath(self): v0 = variables.VariableV1(0, name="v0") @@ -387,6 +390,7 @@ class SaverTest(test.TestCase): ValueError, "The passed save_path is not a valid checkpoint:"): save.restore(sess, "invalid path") + @test_util.run_deprecated_v1 def testInt64(self): save_path = os.path.join(self.get_temp_dir(), "int64") @@ -407,7 +411,7 @@ class SaverTest(test.TestCase): with self.assertRaisesWithPredicateMatch( errors_impl.OpError, lambda e: "uninitialized value v" in e.message): - sess.run(v) + self.evaluate(v) # Restore the saved values in the parameter nodes. save.restore(sess, save_path) @@ -462,6 +466,7 @@ class SaverTest(test.TestCase): # Verify non-duplicate names work. saver_module.Saver({"v0": v0, "v2": v2.saveable}) + @test_util.run_deprecated_v1 def testBasicsWithListOfVariables(self): save_path = os.path.join(self.get_temp_dir(), "basics_with_list") @@ -497,10 +502,10 @@ class SaverTest(test.TestCase): with self.assertRaisesWithPredicateMatch( errors_impl.OpError, lambda e: "uninitialized value v0" in e.message): - sess.run(v0) + self.evaluate(v0) with self.assertRaisesWithPredicateMatch( errors_impl.OpError, lambda e: "uninitialized value v1" in e.message): - sess.run(v1) + self.evaluate(v1) self.assertEqual(0, len(v2.keys().eval())) self.assertEqual(0, len(v2.values().eval())) @@ -557,6 +562,7 @@ class SaverTest(test.TestCase): # The cached readers should know to re-read the file. self._SaveAndLoad("var1", 1.1, 2.2, save_path) + @test_util.run_deprecated_v1 def testAllowEmpty(self): save_path = os.path.join(self.get_temp_dir(), "allow_empty") with self.cached_session() as sess: @@ -661,6 +667,7 @@ class SaverTest(test.TestCase): self.assertAllClose(1.0, one.eval()) self.assertAllClose([2.0, 2.0, 2.0], twos.eval()) + @test_util.run_deprecated_v1 def testReshape(self): save_path = os.path.join(self.get_temp_dir(), "variables_reshape") with session.Session("", graph=ops_lib.Graph()) as sess: @@ -719,6 +726,7 @@ class SaverTest(test.TestCase): def testSaveWithGlobalStepWithPadding(self): self.testSaveWithGlobalStep(pad_step_number=True) + @test_util.run_deprecated_v1 def testSaveToNonexistingPath(self): file_io.write_string_to_file( os.path.join(self.get_temp_dir(), "actually_a_file"), "") @@ -742,7 +750,7 @@ class SaverTest(test.TestCase): try: with self.cached_session() as sess: # Initialize all variables - sess.run(init_all_op) + self.evaluate(init_all_op) # Check that the parameter nodes have been initialized. self.assertEqual(10.0, v0.eval()) @@ -761,6 +769,7 @@ class SaverTest(test.TestCase): error_msg_template = "Parent directory of {} doesn't exist, can't save." self.assertEqual(error_msg_template.format(save_path), str(exc)) + @test_util.run_deprecated_v1 def testSaveToURI(self): # ParseURI functions don't work on Windows yet. # TODO(jhseu): Remove this check when it works. @@ -777,7 +786,7 @@ class SaverTest(test.TestCase): with self.cached_session() as sess: # Initialize all variables - sess.run(init_all_op) + self.evaluate(init_all_op) # Check that the parameter nodes have been initialized. self.assertEqual(10.0, v0.eval()) @@ -824,11 +833,11 @@ class SaverTest(test.TestCase): save_graph = ops_lib.Graph() with save_graph.as_default(), self.session(graph=save_graph) as sess: orig_vars = _model() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) save = saver_module.Saver(max_to_keep=1) variables.global_variables_initializer().run() save.save(sess, save_dir) - orig_vals = sess.run(orig_vars) + orig_vals = self.evaluate(orig_vars) restore_graph = ops_lib.Graph() with restore_graph.as_default(), self.session( @@ -836,7 +845,7 @@ class SaverTest(test.TestCase): restored_vars = _model() save = saver_module.Saver(max_to_keep=1) save.restore(sess, save_dir) - restored_vals = sess.run(restored_vars) + restored_vals = self.evaluate(restored_vars) for orig, restored in zip(orig_vals, restored_vals): self.assertAllEqual(orig, restored) @@ -982,6 +991,7 @@ class SaveRestoreShardedTest(test.TestCase): checkpoint_management.latest_checkpoint(self.get_temp_dir()), os.path.join(self.get_temp_dir(), "sharded_basics")) + @test_util.run_deprecated_v1 def testSaverDef(self): with self.cached_session(): v0 = variables.VariableV1(123, name="v0") @@ -998,19 +1008,12 @@ class SaveRestoreShardedTest(test.TestCase): call_saver_with_dict = False # updated by test loop below - def _save(slices=None, partitioner=None): + def _save(partitioner=None): with self.session(graph=ops_lib.Graph()) as sess: # Calls .eval() to return the ndarray that makes up the full variable. rnd = random_ops.random_uniform(var_full_shape).eval() - if slices: - assert not partitioner - # TODO(apassos): make create_partitioned_variables take use_resource - # option to make this test passable without creating a named - # variable_scope. - vs = partitioned_variables.create_partitioned_variables( - var_full_shape, slices, rnd, name=var_name) - elif partitioner: + if partitioner: vs = [ variable_scope.get_variable( var_name, @@ -1027,7 +1030,7 @@ class SaveRestoreShardedTest(test.TestCase): variables.global_variables_initializer().run() if call_saver_with_dict: - saver = saver_module.Saver({var_name: (vs if slices else vs[0])}) + saver = saver_module.Saver({var_name: vs[0]}) else: saver = saver_module.Saver(vs) actual_path = saver.save(sess, saved_path) @@ -1035,16 +1038,9 @@ class SaveRestoreShardedTest(test.TestCase): return rnd - def _restore(slices=None, partitioner=None): + def _restore(partitioner=None): with self.session(graph=ops_lib.Graph()) as sess: - if slices: - assert not partitioner - new_vs = partitioned_variables.create_partitioned_variables( - var_full_shape, - slices, - array_ops.zeros(var_full_shape), # != original contents. - name=var_name) - elif partitioner: + if partitioner: new_vs = [ variable_scope.get_variable( var_name, @@ -1063,7 +1059,7 @@ class SaveRestoreShardedTest(test.TestCase): variables.global_variables_initializer().run() if call_saver_with_dict: saver = saver_module.Saver({ - var_name: (new_vs if slices else new_vs[0]) + var_name: new_vs[0] }) else: saver = saver_module.Saver(new_vs) @@ -1071,11 +1067,7 @@ class SaveRestoreShardedTest(test.TestCase): if partitioner: return new_vs[0].as_tensor().eval() - elif slices and slices[0] != 1: - return array_ops.concat(new_vs, 0).eval() - elif slices and slices[1] != 1: - return array_ops.concat(new_vs, 1).eval() - else: # Non-sliced. + else: return new_vs[0].eval() for call_saver_with_dict in {False, True}: @@ -1086,32 +1078,30 @@ class SaveRestoreShardedTest(test.TestCase): restored_full = _restore() self.assertAllEqual(saved_full, restored_full) - # Saves 10 horizontal parts of a partitioned variable. - # Restores into a full variable, non-sliced. - saved_full = _save(slices=[10, 1]) - restored_full = _restore() - self.assertAllEqual(saved_full, restored_full) - - # Restores into a different number/orientation of slices. - restored_full = _restore(slices=[2, 1]) # 2 horizon parts. - self.assertAllEqual(saved_full, restored_full) - restored_full = _restore(slices=[1, 3]) # 3 vertical parts. + # Restores into the same number of partitions. + restored_full = _restore( + partitioner=partitioned_variables.fixed_size_partitioner( + num_shards=2)) self.assertAllEqual(saved_full, restored_full) - # Restores into a PartitionedVariable + # Restores into a different number of partitions. restored_full = _restore( partitioner=partitioned_variables.fixed_size_partitioner( - num_shards=2)) + num_shards=3)) self.assertAllEqual(saved_full, restored_full) - # Now, saves a full variable and restores in slices. + # Now, saves a full variable and restores PartitionedVariable. saved_full = _save() - restored_full = _restore(slices=[1, 3]) + restored_full = _restore( + partitioner=partitioned_variables.fixed_size_partitioner( + num_shards=3)) self.assertAllEqual(saved_full, restored_full) + @test_util.run_deprecated_v1 def testPartitionedVariable(self): self._testPartitionedVariables(use_resource=False) + @test_util.run_deprecated_v1 def testPartitionedResourceVariable(self): self._testPartitionedVariables(use_resource=True) @@ -1206,6 +1196,7 @@ class MaxToKeepTest(test.TestCase): # Deleted by the first helper. self.assertFalse(checkpoint_management.checkpoint_exists(s3)) + @test_util.run_deprecated_v1 def testNonSharded(self): save_dir = self._get_test_dir("max_to_keep_non_sharded") @@ -1443,6 +1434,7 @@ class MaxToKeepTest(test.TestCase): self.assertTrue( gfile.Exists(checkpoint_management.meta_graph_filename(s3))) + @test_util.run_deprecated_v1 def testNoMaxToKeep(self): save_dir = self._get_test_dir("no_max_to_keep") save_dir2 = self._get_test_dir("max_to_keep_0") @@ -1471,6 +1463,7 @@ class MaxToKeepTest(test.TestCase): self.assertEqual([], save2.last_checkpoints) self.assertTrue(checkpoint_management.checkpoint_exists(s2)) + @test_util.run_deprecated_v1 def testNoMetaGraph(self): save_dir = self._get_test_dir("no_meta_graph") @@ -1494,6 +1487,7 @@ class KeepCheckpointEveryNHoursTest(test.TestCase): @test_util.run_in_graph_and_eager_modes @test.mock.patch.object(saver_module, "time") + @test_util.run_deprecated_v1 def testNonSharded(self, mock_time): save_dir = self._get_test_dir("keep_checkpoint_every_n_hours") @@ -1613,6 +1607,7 @@ class SaveRestoreWithVariableNameMap(test.TestCase): self.assertEqual(20.0, self.evaluate(v1)) @test_util.run_in_graph_and_eager_modes + @test_util.run_deprecated_v1 def testNonReshapeResourceVariable(self): self._testNonReshape(resource_variable_ops.ResourceVariable) @@ -1627,6 +1622,7 @@ class MetaGraphTest(test.TestCase): gfile.MakeDirs(test_dir) return test_dir + @test_util.run_deprecated_v1 def testAddCollectionDef(self): test_dir = self._get_test_dir("good_collection") filename = os.path.join(test_dir, "metafile") @@ -1769,18 +1765,20 @@ class MetaGraphTest(test.TestCase): self.assertEqual([], v1.get_shape()) with self.assertRaisesWithPredicateMatch( errors_impl.OpError, lambda e: "uninitialized value v1" in e.message): - sess.run(v1) + self.evaluate(v1) # Retrieves saver1. Verifies that new_saver1 can restore v1. new_saver1 = savers[1] new_saver1.restore(sess, saver1_ckpt) v1 = sess.graph.get_tensor_by_name("v1:0") self.assertEqual(11.0, v1.eval()) + @test_util.run_deprecated_v1 def testMultiSaverCollection(self): test_dir = self._get_test_dir("saver_collection") self._testMultiSaverCollectionSave(test_dir) self._testMultiSaverCollectionRestore(test_dir) + @test_util.run_deprecated_v1 def testClearExtraneousSavers(self): test_dir = self._get_test_dir("clear_extraneous_savers") filename = os.path.join(test_dir, "metafile") @@ -1835,6 +1833,7 @@ class MetaGraphTest(test.TestCase): self.assertEqual(33, len(meta_graph_def0.graph_def.node)) self.assertEqual(21, len(meta_graph_def1.graph_def.node)) + @test_util.run_deprecated_v1 def testBinaryAndTextFormat(self): test_dir = self._get_test_dir("binary_and_text") filename = os.path.join(test_dir, "metafile") @@ -1867,6 +1866,7 @@ class MetaGraphTest(test.TestCase): lambda e: "does not exist"): saver_module.import_meta_graph(filename) + @test_util.run_deprecated_v1 def testSliceVariable(self): test_dir = self._get_test_dir("slice_saver") filename = os.path.join(test_dir, "metafile") @@ -1949,9 +1949,9 @@ class MetaGraphTest(test.TestCase): with self.cached_session() as sess: # Initializes all the variables. - sess.run(init_all_op) + self.evaluate(init_all_op) # Runs to logit. - sess.run(logits) + self.evaluate(logits) # Creates a saver. saver0 = saver_module.Saver() saver0.save(sess, saver0_ckpt) @@ -1991,7 +1991,7 @@ class MetaGraphTest(test.TestCase): ops_lib.add_to_collection("train_op", train_op) # Runs train_op. - sess.run(train_op) + self.evaluate(train_op) # Generates MetaGraphDef. saver_module.export_meta_graph(train_filename) @@ -2005,8 +2005,9 @@ class MetaGraphTest(test.TestCase): # Restores from checkpoint. new_saver.restore(sess, saver0_ckpt) train_op = ops_lib.get_collection("train_op")[0] - sess.run(train_op) + self.evaluate(train_op) + @test_util.run_deprecated_v1 def testGraphExtension(self): test_dir = self._get_test_dir("graph_extension") self._testGraphExtensionSave(test_dir) @@ -2037,8 +2038,8 @@ class MetaGraphTest(test.TestCase): # Generate a MetaGraphDef containing the while loop. with session.Session() as sess: - sess.run(init_op) - sess.run(output) + self.evaluate(init_op) + self.evaluate(output) saver = saver_module.Saver() saver.save(sess, saver_ckpt) saver.export_meta_graph(filename) @@ -2053,8 +2054,8 @@ class MetaGraphTest(test.TestCase): no_constfold_config.graph_options.rewrite_options.constant_folding = ( rewriter_config_pb2.RewriterConfig.OFF) with session.Session(config=no_constfold_config) as sess: - sess.run(init_op) - expected_grad_value = sess.run(grad) + self.evaluate(init_op) + expected_grad_value = self.evaluate(grad) # Restore the MetaGraphDef into a new Graph. with ops_lib.Graph().as_default(): @@ -2070,8 +2071,8 @@ class MetaGraphTest(test.TestCase): init_op = variables.global_variables_initializer() with session.Session(config=no_constfold_config) as sess: - sess.run(init_op) - actual_grad_value = sess.run(grad) + self.evaluate(init_op) + actual_grad_value = self.evaluate(grad) self.assertEqual(expected_grad_value, actual_grad_value) def _testWhileLoopAndGradientSerDes(self, outer_body_fn): @@ -2092,6 +2093,7 @@ class MetaGraphTest(test.TestCase): return i + 1, x + r self._testWhileLoopAndGradientSerDes(body) + @test_util.run_deprecated_v1 def testNestedControlFlowSerDes(self): # Test while loop in a cond in a while loop. # pylint: disable=g-long-lambda @@ -2120,6 +2122,7 @@ class MetaGraphTest(test.TestCase): lambda: math_ops.multiply(x, -1.0)))) # pylint: enable=g-long-lambda + @test_util.run_deprecated_v1 def testStrippedOpListDef(self): with self.cached_session(): # Creates a graph. @@ -2157,6 +2160,7 @@ class MetaGraphTest(test.TestCase): self.assertEqual(o.summary, "") self.assertEqual(o.description, "") + @test_util.run_deprecated_v1 def testStripDefaultValuedAttrs(self): """Verifies that default valued attrs are stripped, unless disabled.""" @@ -2193,6 +2197,7 @@ class MetaGraphTest(test.TestCase): self.assertIn("T", node_def.attr) self.assertIn("Tout", node_def.attr) + @test_util.run_deprecated_v1 def testImportIntoNamescope(self): # Test that we can import a meta graph into a namescope. test_dir = self._get_test_dir("import_into_namescope") @@ -2209,7 +2214,7 @@ class MetaGraphTest(test.TestCase): logits=logit, name="cost") adam.AdamOptimizer().minimize(cost, name="optimize") saver = saver_module.Saver() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) saver.save(sess, filename) graph = ops_lib.Graph() @@ -2246,7 +2251,7 @@ class MetaGraphTest(test.TestCase): # Create a variable in graph_2 under scope "my_scope". variables.VariableV1(array_ops.zeros([10]), name="my_scope/my_var") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Restore the checkpoint into a different scope "subgraph_2". new_saver_2 = saver_module.import_meta_graph( filename + ".meta", graph=graph_2, import_scope="subgraph_2") @@ -2263,6 +2268,7 @@ class MetaGraphTest(test.TestCase): filename + ".meta", graph=graph_2, import_scope="my_scope") self.assertIsInstance(new_saver_3, saver_module.Saver) + @test_util.run_deprecated_v1 def testImportIntoImplicitNamescope(self): # Test that we can import a meta graph into an implicit namescope. test_dir = self._get_test_dir("import_into_namescope") @@ -2279,7 +2285,7 @@ class MetaGraphTest(test.TestCase): logits=logit, name="cost") adam.AdamOptimizer().minimize(cost, name="optimize") saver = saver_module.Saver() - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) saver.save(sess, filename) graph = ops_lib.Graph() @@ -2316,12 +2322,12 @@ class MetaGraphTest(test.TestCase): meta_graph_def, clear_devices=False, import_scope="new_model") # Device refers to GPU, which is not available here. with self.assertRaises(errors_impl.InvalidArgumentError): - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) with session.Session(graph=ops_lib.Graph()) as sess: saver_module.import_meta_graph( meta_graph_def, clear_devices=True, import_scope="new_model") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) sess.run(["new_model/optimize"], { "new_model/image:0": np.random.random([1, 784]), "new_model/label:0": np.random.randint( @@ -2348,7 +2354,7 @@ class MetaGraphTest(test.TestCase): with session.Session(graph=ops_lib.Graph()) as sess: saver_module.import_meta_graph(meta_graph_def, import_scope="new_model") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) sess.run(["new_model/optimize"], { "new_model/image:0": np.random.random([1, 784]), "new_model/label:0": np.random.randint( @@ -2358,7 +2364,7 @@ class MetaGraphTest(test.TestCase): def testPreserveDatasetAndFunctions(self): with ops_lib.Graph().as_default() as g: dataset = dataset_ops.Dataset.range(10).map(lambda x: x * x) - iterator = dataset.make_one_shot_iterator() + iterator = dataset_ops.make_one_shot_iterator(dataset) next_element = iterator.get_next() _ = array_ops.identity(next_element, name="output") @@ -2374,7 +2380,7 @@ class MetaGraphTest(test.TestCase): meta_graph_def_from_graph_def]: with session.Session(graph=ops_lib.Graph()) as sess: saver_module.import_meta_graph(meta_graph_def, import_scope="new_model") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) for i in range(10): self.assertEqual(i * i, sess.run("new_model/output:0")) with self.assertRaises(errors.OutOfRangeError): @@ -2385,6 +2391,7 @@ class CheckpointReaderTest(test.TestCase): _WRITE_VERSION = saver_pb2.SaverDef.V1 + @test_util.run_deprecated_v1 def testDebugString(self): # Builds a graph. v0 = variables.VariableV1( @@ -2400,7 +2407,7 @@ class CheckpointReaderTest(test.TestCase): save_path = os.path.join(self.get_temp_dir(), "ckpt_for_debug_string" + str(self._WRITE_VERSION)) with self.cached_session() as sess: - sess.run(init_all_op) + self.evaluate(init_all_op) # Saves a checkpoint. save.save(sess, save_path) @@ -2546,7 +2553,7 @@ class ScopedGraphTest(test.TestCase): self.assertEqual(["biases:0", "weights:0"], sorted(var_list.keys())) with self.session(graph=graph) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) saver = saver_module.Saver(var_list=var_list, max_to_keep=1) saver.save(sess, os.path.join(test_dir, ckpt_filename), write_state=False) @@ -2609,13 +2616,14 @@ class ScopedGraphTest(test.TestCase): saver = saver_module.Saver(var_list=var_list, max_to_keep=1) saver.restore(sess, os.path.join(test_dir, ckpt_filename)) # Verify that we have restored weights1 and biases1. - sess.run([weights1, biases1]) + self.evaluate([weights1, biases1]) # Initialize the rest of the variables and run logits. - sess.run(init_rest_op) - sess.run(logits) + self.evaluate(init_rest_op) + self.evaluate(logits) # Verifies that we can save the subgraph under "hidden1" and restore it # into "new_hidden1" in the new graph. + @test_util.run_deprecated_v1 def testScopedSaveAndRestore(self): test_dir = self._get_test_dir("scoped_export_import") ckpt_filename = "ckpt" @@ -2625,6 +2633,7 @@ class ScopedGraphTest(test.TestCase): # Verifies that we can copy the subgraph under "hidden1" and copy it # to different name scope in the same graph or different graph. + @test_util.run_deprecated_v1 def testCopyScopedGraph(self): test_dir = self._get_test_dir("scoped_copy") saver0_ckpt = os.path.join(test_dir, "saver0.ckpt") @@ -2640,7 +2649,7 @@ class ScopedGraphTest(test.TestCase): # Run the graph and save scoped checkpoint. with self.session(graph=graph1) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) _, var_list_1 = meta_graph.export_scoped_meta_graph( export_scope="hidden1") saver = saver_module.Saver(var_list=var_list_1, max_to_keep=1) @@ -2681,6 +2690,7 @@ class ScopedGraphTest(test.TestCase): saver3.restore(sess, saver0_ckpt) self.assertAllClose(expected, sess.run("new_hidden1/relu:0")) + @test_util.run_deprecated_v1 def testExportGraphDefWithScope(self): test_dir = self._get_test_dir("export_graph_def") saver0_ckpt = os.path.join(test_dir, "saver0.ckpt") @@ -2696,7 +2706,7 @@ class ScopedGraphTest(test.TestCase): # Run the graph and save scoped checkpoint. with self.session(graph=graph1) as sess: - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) _, var_list_1 = meta_graph.export_scoped_meta_graph( graph_def=graph1.as_graph_def(), export_scope="hidden1") saver = saver_module.Saver(var_list=var_list_1, max_to_keep=1) @@ -2717,6 +2727,7 @@ class ScopedGraphTest(test.TestCase): saver3.restore(sess, saver0_ckpt) self.assertAllClose(expected, sess.run("new_hidden1/relu:0")) + @test_util.run_deprecated_v1 def testSerializeSaverWithScope(self): test_dir = self._get_test_dir("export_graph_def") saver1_ckpt = os.path.join(test_dir, "saver1.ckpt") @@ -2964,7 +2975,7 @@ class CheckpointableCompatibilityTests(test.TestCase): a_saver = saver_module.Saver([a]) b_saver = saver_module.Saver([b]) with self.cached_session() as sess: - sess.run(a.initializer) + self.evaluate(a.initializer) save_path = a_saver.save(sess=sess, save_path=checkpoint_prefix) with self.assertRaisesRegexp( errors.NotFoundError, "Key b not found in checkpoint"): @@ -2977,6 +2988,7 @@ class CheckpointableCompatibilityTests(test.TestCase): # exception" block in Python 3. self.assertNotIn("NewCheckpointReader", cs.exception.message) + @test_util.run_deprecated_v1 def testGraphChangedForRestoreErrorRaised(self): checkpoint_directory = self.get_temp_dir() checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") @@ -2986,7 +2998,7 @@ class CheckpointableCompatibilityTests(test.TestCase): a_saver = saver_module.Saver([a]) with self.session(graph=g) as sess: - sess.run(a.initializer) + self.evaluate(a.initializer) save_path = a_saver.save(sess=sess, save_path=checkpoint_prefix) with ops_lib.Graph().as_default() as g: @@ -2998,6 +3010,7 @@ class CheckpointableCompatibilityTests(test.TestCase): "a mismatch between the current graph and the graph"): a_saver.restore(sess=sess, save_path=save_path) + @test_util.run_deprecated_v1 def testLoadFromObjectBasedGraph(self): checkpoint_directory = self.get_temp_dir() checkpoint_prefix = os.path.join(checkpoint_directory, "ckpt") @@ -3029,7 +3042,7 @@ class CheckpointableCompatibilityTests(test.TestCase): self.assertEqual(before_second_restore_ops, restore_graph.get_operations()) with self.assertRaisesRegexp(errors.NotFoundError, - "could not find a_variable"): + "Could not find some variables"): saver.restore(sess=sess, save_path=second_path) def testLoadFromObjectBasedEager(self): diff --git a/tensorflow/python/training/server_lib_multiple_containers_test.py b/tensorflow/python/training/server_lib_multiple_containers_test.py index f599e9b55b..fb6118942b 100644 --- a/tensorflow/python/training/server_lib_multiple_containers_test.py +++ b/tensorflow/python/training/server_lib_multiple_containers_test.py @@ -21,6 +21,7 @@ from __future__ import print_function from tensorflow.python.client import session from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import variables from tensorflow.python.platform import test from tensorflow.python.training import server_lib @@ -33,6 +34,7 @@ class MultipleContainersTest(test.TestCase): # TODO(b/34465411): Starting multiple servers with different configurations # in the same test is flaky. Move this test case back into # "server_lib_test.py" when this is no longer the case. + @test_util.run_deprecated_v1 def testMultipleContainers(self): with ops.container("test0"): v0 = variables.Variable(1.0, name="v0") diff --git a/tensorflow/python/training/server_lib_same_variables_clear_container_test.py b/tensorflow/python/training/server_lib_same_variables_clear_container_test.py index 11e6f28ab0..e0ab21bbd9 100644 --- a/tensorflow/python/training/server_lib_same_variables_clear_container_test.py +++ b/tensorflow/python/training/server_lib_same_variables_clear_container_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python.client import session from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import variables from tensorflow.python.platform import test from tensorflow.python.training import server_lib @@ -32,6 +33,7 @@ class SameVariablesClearContainerTest(test.TestCase): # TODO(b/34465411): Starting multiple servers with different configurations # in the same test is flaky. Move this test case back into # "server_lib_test.py" when this is no longer the case. + @test_util.run_deprecated_v1 def testSameVariablesClearContainer(self): # Starts two servers with different names so they map to different # resource "containers". @@ -60,9 +62,9 @@ class SameVariablesClearContainerTest(test.TestCase): session.Session.reset(server0.target, ["local0"]) sess = session.Session(server0.target) with self.assertRaises(errors_impl.FailedPreconditionError): - sess.run(v0) + self.evaluate(v0) # Reinitializes v0 for the following test. - sess.run(v0.initializer) + self.evaluate(v0.initializer) # Verifies that v1 is still valid. self.assertAllEqual(2.0, sess_1.run(v1)) @@ -71,10 +73,10 @@ class SameVariablesClearContainerTest(test.TestCase): session.Session.reset(server1.target, ["local1"]) sess = session.Session(server1.target) with self.assertRaises(errors_impl.FailedPreconditionError): - sess.run(v1) + self.evaluate(v1) # Verifies that v0 is still valid. sess = session.Session(server0.target) - self.assertAllEqual(1.0, sess.run(v0)) + self.assertAllEqual(1.0, self.evaluate(v0)) if __name__ == "__main__": diff --git a/tensorflow/python/training/server_lib_same_variables_clear_test.py b/tensorflow/python/training/server_lib_same_variables_clear_test.py index 4682f1ab84..7b147af6c5 100644 --- a/tensorflow/python/training/server_lib_same_variables_clear_test.py +++ b/tensorflow/python/training/server_lib_same_variables_clear_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python.client import session from tensorflow.python.framework import errors_impl +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test @@ -32,6 +33,7 @@ class SameVariablesClearTest(test.TestCase): # TODO(b/34465411): Starting multiple servers with different configurations # in the same test is flaky. Move this test case back into # "server_lib_test.py" when this is no longer the case. + @test_util.run_deprecated_v1 def testSameVariablesClear(self): server = server_lib.Server.create_local_server() diff --git a/tensorflow/python/training/server_lib_same_variables_no_clear_test.py b/tensorflow/python/training/server_lib_same_variables_no_clear_test.py index 5aa7f45c2b..1b2d588f44 100644 --- a/tensorflow/python/training/server_lib_same_variables_no_clear_test.py +++ b/tensorflow/python/training/server_lib_same_variables_no_clear_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python.client import session from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables from tensorflow.python.platform import test @@ -33,6 +34,7 @@ class SameVariablesNoClearTest(test.TestCase): # TODO(b/34465411): Starting multiple servers with different configurations # in the same test is flaky. Move this test case back into # "server_lib_test.py" when this is no longer the case. + @test_util.run_deprecated_v1 def testSameVariablesNoClear(self): server = server_lib.Server.create_local_server() diff --git a/tensorflow/python/training/server_lib_sparse_job_test.py b/tensorflow/python/training/server_lib_sparse_job_test.py index 1a6b44b90e..93b06e6216 100644 --- a/tensorflow/python/training/server_lib_sparse_job_test.py +++ b/tensorflow/python/training/server_lib_sparse_job_test.py @@ -21,6 +21,7 @@ from __future__ import print_function from tensorflow.python.client import session from tensorflow.python.framework import constant_op from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.platform import test from tensorflow.python.training import server_lib @@ -30,13 +31,14 @@ class SparseJobTest(test.TestCase): # TODO(b/34465411): Starting multiple servers with different configurations # in the same test is flaky. Move this test case back into # "server_lib_test.py" when this is no longer the case. + @test_util.run_deprecated_v1 def testSparseJob(self): server = server_lib.Server({"local": {37: "localhost:0"}}) with ops.device("/job:local/task:37"): a = constant_op.constant(1.0) with session.Session(server.target) as sess: - self.assertEqual(1.0, sess.run(a)) + self.assertEqual(1.0, self.evaluate(a)) if __name__ == "__main__": diff --git a/tensorflow/python/training/server_lib_test.py b/tensorflow/python/training/server_lib_test.py index cf995707fc..323e94c257 100644 --- a/tensorflow/python/training/server_lib_test.py +++ b/tensorflow/python/training/server_lib_test.py @@ -174,7 +174,7 @@ class GrpcServerTest(test.TestCase): # is not supported, but it should successfully ignore it. sess = session.InteractiveSession(server.target) c = constant_op.constant(42.0) - self.assertEqual(42.0, c.eval()) + self.assertEqual(42.0, self.evaluate(c)) sess.close() def testSetConfiguration(self): diff --git a/tensorflow/python/training/session_manager.py b/tensorflow/python/training/session_manager.py index cd313c2ce0..14658630c5 100644 --- a/tensorflow/python/training/session_manager.py +++ b/tensorflow/python/training/session_manager.py @@ -46,7 +46,7 @@ def _maybe_name(obj): return "" % type(obj) -@tf_export("train.SessionManager") +@tf_export(v1=["train.SessionManager"]) class SessionManager(object): """Training helper that restores from checkpoint and creates session. diff --git a/tensorflow/python/training/session_manager_test.py b/tensorflow/python/training/session_manager_test.py index 2b5c3b01de..4294ffa851 100644 --- a/tensorflow/python/training/session_manager_test.py +++ b/tensorflow/python/training/session_manager_test.py @@ -25,6 +25,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import errors_impl from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import variables @@ -68,6 +69,7 @@ class SessionManagerTest(test.TestCase): "", init_fn=lambda sess: sess.run(v.initializer)) self.assertAllClose([125], sess.run(v)) + @test_util.run_deprecated_v1 def testPrepareSessionFails(self): checkpoint_dir = os.path.join(self.get_temp_dir(), "prepare_session") checkpoint_dir2 = os.path.join(self.get_temp_dir(), "prepare_session2") @@ -152,6 +154,7 @@ class SessionManagerTest(test.TestCase): sess.graph.get_tensor_by_name("v:0")).eval(session=sess)) self.assertEquals(1, sess.run(v)) + @test_util.run_deprecated_v1 def testRecoverSession(self): # Create a checkpoint. checkpoint_dir = os.path.join(self.get_temp_dir(), "recover_session") @@ -206,6 +209,7 @@ class SessionManagerTest(test.TestCase): variables.global_variables()), local_init_op=None) + @test_util.run_deprecated_v1 def testRecoverSessionWithReadyForLocalInitOp(self): # Create a checkpoint. checkpoint_dir = os.path.join(self.get_temp_dir(), @@ -259,6 +263,7 @@ class SessionManagerTest(test.TestCase): self.assertEquals(1, sess.run(v)) self.assertEquals(1, sess.run(w)) + @test_util.run_deprecated_v1 def testRecoverSessionWithReadyForLocalInitOpFailsToReadyLocal(self): # We use ready_for_local_init_op=tf.report_uninitialized_variables(), # which causes recover_session to not run local_init_op, and to return @@ -315,6 +320,7 @@ class SessionManagerTest(test.TestCase): sess.graph.get_tensor_by_name("w:0")).eval(session=sess)) self.assertEquals(1, sess.run(v)) + @test_util.run_deprecated_v1 def testRecoverSessionNoChkptStillRunsLocalInitOp(self): # This test checks for backwards compatibility. # In particular, we continue to ensure that recover_session will execute @@ -343,6 +349,7 @@ class SessionManagerTest(test.TestCase): sess.graph.get_tensor_by_name("w:0")).eval(session=sess)) self.assertEquals(1, sess.run(w)) + @test_util.run_deprecated_v1 def testRecoverSessionFailsStillRunsLocalInitOp(self): # Create a checkpoint. checkpoint_dir = os.path.join( @@ -386,6 +393,7 @@ class SessionManagerTest(test.TestCase): sess.graph.get_tensor_by_name("w:0")).eval(session=sess)) self.assertEquals(1, sess.run(w)) + @test_util.run_deprecated_v1 def testWaitForSessionLocalInit(self): server = server_lib.Server.create_local_server() with ops.Graph().as_default() as graph: @@ -437,6 +445,7 @@ class SessionManagerTest(test.TestCase): # because of overly restrictive ready_for_local_init_op sm.wait_for_session("", max_wait_secs=3) + @test_util.run_deprecated_v1 def testWaitForSessionInsufficientReadyForLocalInitCheck(self): with ops.Graph().as_default() as graph: v = variables.VariableV1(1, name="v") @@ -454,6 +463,7 @@ class SessionManagerTest(test.TestCase): "Session was not ready after waiting.*"): sm.wait_for_session("", max_wait_secs=3) + @test_util.run_deprecated_v1 def testPrepareSessionWithReadyForLocalInitOp(self): with ops.Graph().as_default(): v = variables.VariableV1(1, name="v") @@ -493,6 +503,7 @@ class SessionManagerTest(test.TestCase): self.assertEquals(1, sess.run(w)) self.assertEquals(3, sess.run(x)) + @test_util.run_deprecated_v1 def testPrepareSessionWithPartialInitOp(self): with ops.Graph().as_default(): v = variables.VariableV1(1, name="v") @@ -559,6 +570,7 @@ class SessionManagerTest(test.TestCase): self.assertEquals(1, sess.run(w_res)) self.assertEquals(3, sess.run(x_res)) + @test_util.run_deprecated_v1 def testPrepareSessionWithCyclicInitializer(self): # Regression test. Previously Variable._build_initializer_expr would enter # into an infinite recursion when the variable's initial_value involved @@ -632,6 +644,7 @@ class SessionManagerTest(test.TestCase): "Init operations did not make model ready for local_init"): sm2.prepare_session("", init_op=None) + @test_util.run_deprecated_v1 def testPrepareSessionWithInsufficientReadyForLocalInitCheck(self): with ops.Graph().as_default(): v = variables.VariableV1(1, name="v") @@ -684,6 +697,7 @@ class ObsoleteSessionManagerTest(test.TestCase): "", init_fn=lambda sess: sess.run(v.initializer)) self.assertAllClose([125], sess.run(v)) + @test_util.run_deprecated_v1 def testPrepareSessionFails(self): checkpoint_dir = os.path.join(self.get_temp_dir(), "prepare_session") checkpoint_dir2 = os.path.join(self.get_temp_dir(), "prepare_session2") @@ -745,6 +759,7 @@ class ObsoleteSessionManagerTest(test.TestCase): variables.is_variable_initialized( sess.graph.get_tensor_by_name("v:0")).eval(session=sess)) + @test_util.run_deprecated_v1 def testRecoverSession(self): # Create a checkpoint. checkpoint_dir = os.path.join(self.get_temp_dir(), "recover_session") diff --git a/tensorflow/python/training/session_run_hook.py b/tensorflow/python/training/session_run_hook.py index 5daea93128..e9a61def74 100644 --- a/tensorflow/python/training/session_run_hook.py +++ b/tensorflow/python/training/session_run_hook.py @@ -186,7 +186,7 @@ class SessionRunHook(object): pass -@tf_export("train.SessionRunArgs") +@tf_export(v1=["train.SessionRunArgs"]) class SessionRunArgs( collections.namedtuple("SessionRunArgs", ["fetches", "feed_dict", "options"])): @@ -211,7 +211,7 @@ class SessionRunArgs( return super(SessionRunArgs, cls).__new__(cls, fetches, feed_dict, options) -@tf_export("train.SessionRunContext") +@tf_export(v1=["train.SessionRunContext"]) class SessionRunContext(object): """Provides information about the `session.run()` call being made. @@ -263,7 +263,7 @@ class SessionRunContext(object): self._stop_requested = True -@tf_export("train.SessionRunValues") +@tf_export(v1=["train.SessionRunValues"]) class SessionRunValues( collections.namedtuple("SessionRunValues", ["results", "options", "run_metadata"])): diff --git a/tensorflow/python/training/slot_creator_test.py b/tensorflow/python/training/slot_creator_test.py index 6d6364169f..1f26aaa434 100644 --- a/tensorflow/python/training/slot_creator_test.py +++ b/tensorflow/python/training/slot_creator_test.py @@ -21,6 +21,7 @@ from __future__ import print_function from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import random_ops from tensorflow.python.ops import variable_scope @@ -31,6 +32,7 @@ from tensorflow.python.training import slot_creator class SlotCreatorTest(test.TestCase): + @test_util.run_deprecated_v1 def testCreateSlotFromVariable(self): with self.cached_session(): v = variables.Variable([1.0, 2.5], name="var") @@ -41,8 +43,9 @@ class SlotCreatorTest(test.TestCase): self.assertEqual("var/slot", slot.op.name) self.assertEqual([2], slot.get_shape().as_list()) self.assertEqual(dtypes.float32, slot.dtype.base_dtype) - self.assertAllEqual([1.0, 2.5], slot.eval()) + self.assertAllEqual([1.0, 2.5], self.evaluate(slot)) + @test_util.run_deprecated_v1 def testCreateSlotFromTensor(self): with self.cached_session(): v = constant_op.constant([1.0, 2.5], name="const") @@ -53,8 +56,9 @@ class SlotCreatorTest(test.TestCase): self.assertEqual("const/slot", slot.op.name) self.assertEqual([2], slot.get_shape().as_list()) self.assertEqual(dtypes.float32, slot.dtype.base_dtype) - self.assertAllEqual([2.0, 5.0], slot.eval()) + self.assertAllEqual([2.0, 5.0], self.evaluate(slot)) + @test_util.run_deprecated_v1 def testCreateZerosSlotFromVariable(self): with self.cached_session(): v = variables.Variable([1.0, 2.5], name="var") @@ -67,8 +71,9 @@ class SlotCreatorTest(test.TestCase): self.assertEqual("var/slot", slot.op.name) self.assertEqual([2], slot.get_shape().as_list()) self.assertEqual(dtypes.float64, slot.dtype.base_dtype) - self.assertAllEqual([0.0, 0.0], slot.eval()) + self.assertAllEqual([0.0, 0.0], self.evaluate(slot)) + @test_util.run_deprecated_v1 def testCreateZerosSlotFromDynamicShapedVariable(self): with self.cached_session(): dyn_shape = constant_op.constant([2], dtype=dtypes.int32) @@ -88,8 +93,9 @@ class SlotCreatorTest(test.TestCase): self.assertEqual("var/slot", slot.op.name) self.assertEqual([2], array_ops.shape(slot).eval()) self.assertEqual(dtypes.float64, slot.dtype.base_dtype) - self.assertAllEqual([0.0, 0.0], slot.eval()) + self.assertAllEqual([0.0, 0.0], self.evaluate(slot)) + @test_util.run_deprecated_v1 def testCreateZerosSlotFromTensor(self): with self.cached_session(): v = constant_op.constant([1.0, 2.5], name="const") @@ -101,8 +107,9 @@ class SlotCreatorTest(test.TestCase): self.assertEqual("const/slot", slot.op.name) self.assertEqual([2], slot.get_shape().as_list()) self.assertEqual(dtypes.float32, slot.dtype.base_dtype) - self.assertAllEqual([0.0, 0.0], slot.eval()) + self.assertAllEqual([0.0, 0.0], self.evaluate(slot)) + @test_util.run_deprecated_v1 def testCreateZerosSlotFromDynamicShapedTensor(self): with self.cached_session(): v = random_ops.random_uniform([2], dtype=dtypes.float64) @@ -116,8 +123,9 @@ class SlotCreatorTest(test.TestCase): self.assertEqual("const/slot", slot.op.name) self.assertEqual([2], array_ops.shape(slot).eval()) self.assertEqual(dtypes.float64, slot.dtype.base_dtype) - self.assertAllEqual([0.0, 0.0], slot.eval()) + self.assertAllEqual([0.0, 0.0], self.evaluate(slot)) + @test_util.run_deprecated_v1 def testCreateSlotFromVariableRespectsScope(self): # See discussion on #2740. with self.cached_session(): diff --git a/tensorflow/python/training/supervisor.py b/tensorflow/python/training/supervisor.py index a5e626d320..de60dd456f 100644 --- a/tensorflow/python/training/supervisor.py +++ b/tensorflow/python/training/supervisor.py @@ -40,7 +40,7 @@ from tensorflow.python.util import deprecation from tensorflow.python.util.tf_export import tf_export -@tf_export("train.Supervisor") +@tf_export(v1=["train.Supervisor"]) class Supervisor(object): """A training helper that checkpoints models and computes summaries. diff --git a/tensorflow/python/training/supervisor_test.py b/tensorflow/python/training/supervisor_test.py index 7cd99d8680..f6505acc9a 100644 --- a/tensorflow/python/training/supervisor_test.py +++ b/tensorflow/python/training/supervisor_test.py @@ -35,6 +35,7 @@ from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors_impl from tensorflow.python.framework import meta_graph from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import array_ops from tensorflow.python.ops import io_ops from tensorflow.python.ops import parsing_ops @@ -100,7 +101,7 @@ class SupervisorTest(test.TestCase): sv = supervisor.Supervisor(logdir=logdir) sess = sv.prepare_or_wait_for_session("") for _ in xrange(10): - sess.run(my_op) + self.evaluate(my_op) sess.close() sv.stop() @@ -111,7 +112,7 @@ class SupervisorTest(test.TestCase): sv = supervisor.Supervisor(logdir=logdir) with sv.managed_session("") as sess: for _ in xrange(10): - sess.run(my_op) + self.evaluate(my_op) # Supervisor has been stopped. self.assertTrue(sv.should_stop()) @@ -128,7 +129,7 @@ class SupervisorTest(test.TestCase): if step == 1: raise RuntimeError("failing here") else: - sess.run(my_op) + self.evaluate(my_op) # Supervisor has been stopped. self.assertTrue(sv.should_stop()) self.assertEqual(1, last_step) @@ -146,7 +147,7 @@ class SupervisorTest(test.TestCase): raise errors_impl.OutOfRangeError(my_op.op.node_def, my_op.op, "all done") else: - sess.run(my_op) + self.evaluate(my_op) # Supervisor has been stopped. OutOfRangeError was not thrown. self.assertTrue(sv.should_stop()) self.assertEqual(3, last_step) @@ -335,7 +336,7 @@ class SupervisorTest(test.TestCase): sess = sv.prepare_or_wait_for_session( "", config=config_pb2.ConfigProto(device_count={"CPU": 2})) for _ in xrange(10): - sess.run(my_op) + self.evaluate(my_op) sess.close() sv.stop() @@ -420,6 +421,7 @@ class SupervisorTest(test.TestCase): with self.assertRaisesRegexp(RuntimeError, "requires a summary writer"): sv.summary_computed(sess, sess.run(summ)) + @test_util.run_deprecated_v1 def testLogdirButExplicitlyNoSummaryWriter(self): logdir = self._test_dir("explicit_no_summary_writer") with ops.Graph().as_default(): @@ -505,6 +507,7 @@ class SupervisorTest(test.TestCase): sv = supervisor.Supervisor(logdir="", session_manager=sm) sv.prepare_or_wait_for_session("") + @test_util.run_deprecated_v1 def testInitOp(self): logdir = self._test_dir("default_init_op") with ops.Graph().as_default(): @@ -514,6 +517,7 @@ class SupervisorTest(test.TestCase): self.assertAllClose([1.0, 2.0, 3.0], sess.run(v)) sv.stop() + @test_util.run_deprecated_v1 def testInitFn(self): logdir = self._test_dir("default_init_op") with ops.Graph().as_default(): @@ -527,6 +531,7 @@ class SupervisorTest(test.TestCase): self.assertAllClose([1.0, 2.0, 3.0], sess.run(v)) sv.stop() + @test_util.run_deprecated_v1 def testInitOpWithFeedDict(self): logdir = self._test_dir("feed_dict_init_op") with ops.Graph().as_default(): @@ -540,6 +545,7 @@ class SupervisorTest(test.TestCase): self.assertAllClose([1.0, 2.0, 3.0], sess.run(v)) sv.stop() + @test_util.run_deprecated_v1 def testReadyForLocalInitOp(self): server = server_lib.Server.create_local_server() logdir = self._test_dir("default_ready_for_local_init_op") @@ -582,6 +588,7 @@ class SupervisorTest(test.TestCase): sv0.stop() sv1.stop() + @test_util.run_deprecated_v1 def testReadyForLocalInitOpRestoreFromCheckpoint(self): server = server_lib.Server.create_local_server() logdir = self._test_dir("ready_for_local_init_op_restore") @@ -713,6 +720,7 @@ class SupervisorTest(test.TestCase): "Variables not initialized: w"): sv.prepare_or_wait_for_session(server.target) + @test_util.run_deprecated_v1 def testSetupFail(self): logdir = self._test_dir("setup_fail") with ops.Graph().as_default(): @@ -723,6 +731,7 @@ class SupervisorTest(test.TestCase): variables.VariableV1([1.0, 2.0, 3.0], name="v") supervisor.Supervisor(logdir=logdir, is_chief=False) + @test_util.run_deprecated_v1 def testDefaultGlobalStep(self): logdir = self._test_dir("default_global_step") with ops.Graph().as_default(): @@ -732,6 +741,7 @@ class SupervisorTest(test.TestCase): self.assertEquals(287, sess.run(sv.global_step)) sv.stop() + @test_util.run_deprecated_v1 def testRestoreFromMetaGraph(self): logdir = self._test_dir("restore_from_meta_graph") with ops.Graph().as_default(): @@ -753,6 +763,7 @@ class SupervisorTest(test.TestCase): # This test is based on the fact that the standard services start # right away and get to run once before sv.stop() returns. # We still sleep a bit to make the test robust. + @test_util.run_deprecated_v1 def testStandardServicesWithoutGlobalStep(self): logdir = self._test_dir("standard_services_without_global_step") # Create a checkpoint. @@ -799,10 +810,11 @@ class SupervisorTest(test.TestCase): v = variables.VariableV1([10.10], name="foo") sav = saver_lib.Saver([v]) sav.restore(sess, save_path) - self.assertEqual(1.0, v.eval()[0]) + self.assertEqual(1.0, self.evaluate(v)[0]) # Same as testStandardServicesNoGlobalStep but with a global step. # We should get a summary about the step time. + @test_util.run_deprecated_v1 def testStandardServicesWithGlobalStep(self): logdir = self._test_dir("standard_services_with_global_step") # Create a checkpoint. @@ -863,7 +875,7 @@ class SupervisorTest(test.TestCase): v = variables.VariableV1([-12], name="global_step") sav = saver_lib.Saver([v]) sav.restore(sess, save_path) - self.assertEqual(123, v.eval()[0]) + self.assertEqual(123, self.evaluate(v)[0]) def testNoQueueRunners(self): with ops.Graph().as_default(), self.cached_session() as sess: diff --git a/tensorflow/python/training/sync_replicas_optimizer.py b/tensorflow/python/training/sync_replicas_optimizer.py index fbde8fe3c2..172c141150 100644 --- a/tensorflow/python/training/sync_replicas_optimizer.py +++ b/tensorflow/python/training/sync_replicas_optimizer.py @@ -44,6 +44,9 @@ from tensorflow.python.util.tf_export import tf_export class SyncReplicasOptimizer(optimizer.Optimizer): """Class to synchronize, aggregate gradients and pass them to the optimizer. + This class is deprecated. For synchrononous training, please use [Distribution + Strategies](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/distribute). + In a typical asynchronous training environment, it's common to have some stale gradients. For example, with a N-replica asynchronous training, gradients will be applied to the variables N times independently. Depending @@ -142,9 +145,9 @@ class SyncReplicasOptimizer(optimizer.Optimizer): @deprecation.deprecated( None, - "The `SyncReplicaOptimizer` is deprecated. For synchrononous training, " - "please use [Distribution Strategies](https://github.com/tensorflow/" - "tensorflow/tree/master/tensorflow/contrib/distribute).", + "The `SyncReplicaOptimizer` class is deprecated. For synchrononous " + "training, please use [Distribution Strategies](https://github.com/" + "tensorflow/tensorflow/tree/master/tensorflow/contrib/distribute).", warn_once=True) def __init__(self, opt, diff --git a/tensorflow/python/training/training_ops_test.py b/tensorflow/python/training/training_ops_test.py index 0216482825..51f49ca081 100644 --- a/tensorflow/python/training/training_ops_test.py +++ b/tensorflow/python/training/training_ops_test.py @@ -24,6 +24,7 @@ import numpy as np from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes +from tensorflow.python.framework import test_util from tensorflow.python.framework.test_util import TensorFlowTestCase # Import resource_variable_ops for the variables-to-tensor implicit conversion. from tensorflow.python.ops import resource_variable_ops # pylint: disable=unused-import @@ -53,12 +54,13 @@ class TrainingOpsTest(TensorFlowTestCase): with self.session(use_gpu=use_gpu): var = variables.VariableV1(x) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType(x, var.eval()) + self.assertAllCloseAccordingToType(x, self.evaluate(var)) apply_sgd = training_ops.apply_gradient_descent(var, alpha, delta) - out = apply_sgd.eval() + out = self.evaluate(apply_sgd) self.assertShapeEqual(out, apply_sgd) self.assertAllCloseAccordingToType(x - alpha * delta, out) + @test_util.run_deprecated_v1 def testApplyGradientDescent(self): for (dtype, use_gpu) in itertools.product( [np.float16, np.float32, np.float64], [False, True]): @@ -74,13 +76,13 @@ class TrainingOpsTest(TensorFlowTestCase): accum = variables.VariableV1(y) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType(x, var.eval()) + self.assertAllCloseAccordingToType(x, self.evaluate(var)) apply_adagrad = training_ops.apply_adagrad(var, accum, lr, grad) - out = apply_adagrad.eval() + out = self.evaluate(apply_adagrad) self.assertShapeEqual(out, apply_adagrad) self.assertAllCloseAccordingToType(x - lr * grad * (y + grad * grad)** (-0.5), out) - self.assertAllCloseAccordingToType(y + grad * grad, accum.eval()) + self.assertAllCloseAccordingToType(y + grad * grad, self.evaluate(accum)) def _testTypesForFtrl(self, x, @@ -99,10 +101,10 @@ class TrainingOpsTest(TensorFlowTestCase): linear = variables.VariableV1(z) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType(x, var.eval()) + self.assertAllCloseAccordingToType(x, self.evaluate(var)) apply_ftrl = training_ops.apply_ftrl(var, accum, linear, grad, lr, l1, l2, lr_power) - out = apply_ftrl.eval() + out = self.evaluate(apply_ftrl) self.assertShapeEqual(out, apply_ftrl) accum_update = y + grad * grad linear_update = z + grad - (accum_update**(-lr_power) - y** @@ -112,19 +114,22 @@ class TrainingOpsTest(TensorFlowTestCase): np.sign(linear_update[i]) * l1 - linear_update[i]) / (quadratic[i]) if np.abs(linear_update[i]) > l1 else 0.0 for i in range(linear_update.size)]) - self.assertAllCloseAccordingToType(accum_update, accum.eval()) + self.assertAllCloseAccordingToType(accum_update, self.evaluate(accum)) if x.dtype == np.float16: # The calculations here really are not very precise in float16. - self.assertAllClose(linear_update, linear.eval(), rtol=2e-2, atol=2e-2) + self.assertAllClose( + linear_update, self.evaluate(linear), rtol=2e-2, atol=2e-2) self.assertAllClose(expected_out, out, rtol=2e-2, atol=2e-2) elif x.dtype == np.float32: # The calculations here not sufficiently precise in float32. - self.assertAllClose(linear_update, linear.eval(), rtol=1e-5, atol=1e-5) + self.assertAllClose( + linear_update, self.evaluate(linear), rtol=1e-5, atol=1e-5) self.assertAllClose(expected_out, out, rtol=1e-5, atol=1e-5) else: - self.assertAllClose(linear_update, linear.eval()) + self.assertAllClose(linear_update, self.evaluate(linear)) self.assertAllClose(expected_out, out) + @test_util.run_deprecated_v1 def testApplyAdagrad(self): for (dtype, use_gpu) in itertools.product( [np.float16, np.float32, np.float64], [False, True]): @@ -134,6 +139,7 @@ class TrainingOpsTest(TensorFlowTestCase): grad = np.arange(100).astype(dtype) self._testTypesForAdagrad(x, y, lr, grad, use_gpu) + @test_util.run_deprecated_v1 def testApplyFtrl(self): for dtype in [np.float16, np.float32, np.float64]: x = np.arange(100).astype(dtype) @@ -152,19 +158,19 @@ class TrainingOpsTest(TensorFlowTestCase): accum = variables.VariableV1(y) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType(x, var.eval()) + self.assertAllCloseAccordingToType(x, self.evaluate(var)) sparse_apply_adagrad = training_ops.sparse_apply_adagrad( var, accum, lr, grad, constant_op.constant(indices, self._toType(indices.dtype))) - out = sparse_apply_adagrad.eval() + out = self.evaluate(sparse_apply_adagrad) self.assertShapeEqual(out, sparse_apply_adagrad) for (i, index) in enumerate(indices): self.assertAllCloseAccordingToType( x[index] - lr * grad[i] * (y[index] + grad[i] * grad[i])**(-0.5), - var.eval()[index]) + self.evaluate(var)[index]) self.assertAllCloseAccordingToType(y[index] + grad[i] * grad[i], - accum.eval()[index]) + self.evaluate(accum)[index]) def _testTypesForSparseFtrl(self, x, @@ -183,7 +189,7 @@ class TrainingOpsTest(TensorFlowTestCase): linear = variables.VariableV1(z) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType(x, var.eval()) + self.assertAllCloseAccordingToType(x, self.evaluate(var)) sparse_apply_ftrl = training_ops.sparse_apply_ftrl( var, accum, @@ -194,16 +200,18 @@ class TrainingOpsTest(TensorFlowTestCase): l1, l2, lr_power=lr_power) - out = sparse_apply_ftrl.eval() + out = self.evaluate(sparse_apply_ftrl) self.assertShapeEqual(out, sparse_apply_ftrl) for (i, index) in enumerate(indices): - self.assertAllCloseAccordingToType(x[index] - lr * grad[i] * - (y[index] + grad[i] * grad[i])** - (lr_power), var.eval()[index]) + self.assertAllCloseAccordingToType( + x[index] - lr * grad[i] * (y[index] + grad[i] * grad[i])** + (lr_power), + self.evaluate(var)[index]) self.assertAllCloseAccordingToType(y[index] + grad[i] * grad[i], - accum.eval()[index]) + self.evaluate(accum)[index]) + @test_util.run_deprecated_v1 def testSparseApplyAdagrad(self): for (dtype, index_type) in itertools.product( [np.float16, np.float32, np.float64], [np.int32, np.int64]): @@ -217,6 +225,7 @@ class TrainingOpsTest(TensorFlowTestCase): indices = np.array([0, 2]).astype(index_type) self._testTypesForSparseAdagrad(x, y, lr, grad, indices) + @test_util.run_deprecated_v1 def testSparseApplyAdagradDim1(self): for (dtype, index_type) in itertools.product( [np.float16, np.float32, np.float64], [np.int32, np.int64]): @@ -230,6 +239,7 @@ class TrainingOpsTest(TensorFlowTestCase): indices = np.array([0, 2]).astype(index_type) self._testTypesForSparseAdagrad(x, y, lr, grad, indices) + @test_util.run_deprecated_v1 def testSparseApplyFtrlDim1(self): for (dtype, index_type) in itertools.product( [np.float16, np.float32, np.float64], [np.int32, np.int64]): @@ -245,6 +255,7 @@ class TrainingOpsTest(TensorFlowTestCase): indices = np.array([0, 2]).astype(index_type) self._testTypesForSparseFtrl(x, y, z, lr, grad, indices) + @test_util.run_deprecated_v1 def testApplyAdam(self): for dtype, use_gpu in itertools.product( [np.float16, np.float32, np.float64], [False, True]): @@ -276,13 +287,13 @@ class TrainingOpsTest(TensorFlowTestCase): epsilon_t = constant_op.constant(epsilon, self._toType(var.dtype), []) variables.global_variables_initializer().run() - self.assertAllCloseAccordingToType(var, var_t.eval()) + self.assertAllCloseAccordingToType(var, self.evaluate(var_t)) new_var, _, _ = self._adamUpdateNumpy(var, grad, t, m, v, lr, beta1, beta2, epsilon) apply_adam = training_ops.apply_adam(var_t, m_t, v_t, beta1_power_t, beta2_power_t, lr_t, beta1_t, beta2_t, epsilon_t, grad) - out = apply_adam.eval() + out = self.evaluate(apply_adam) self.assertShapeEqual(out, apply_adam) self.assertAllCloseAccordingToType(new_var, out) diff --git a/tensorflow/python/training/training_util_test.py b/tensorflow/python/training/training_util_test.py index ba64e785ac..3317008fce 100644 --- a/tensorflow/python/training/training_util_test.py +++ b/tensorflow/python/training/training_util_test.py @@ -20,6 +20,7 @@ from __future__ import print_function from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import variables from tensorflow.python.platform import test from tensorflow.python.training import monitored_session @@ -46,6 +47,7 @@ class GlobalStepTest(test.TestCase): self.assertRaisesRegexp(TypeError, 'does not have integer type', training_util.get_global_step, g) + @test_util.run_deprecated_v1 def test_invalid_shape(self): with ops.Graph().as_default() as g: self.assertIsNone(training_util.get_global_step()) @@ -70,6 +72,7 @@ class GlobalStepTest(test.TestCase): training_util.create_global_step, g) self._assert_global_step(training_util.create_global_step(ops.Graph())) + @test_util.run_deprecated_v1 def test_get_global_step(self): with ops.Graph().as_default() as g: self.assertIsNone(training_util.get_global_step()) diff --git a/tensorflow/python/training/warm_starting_util.py b/tensorflow/python/training/warm_starting_util.py index 78dbb465b5..8c97f101da 100644 --- a/tensorflow/python/training/warm_starting_util.py +++ b/tensorflow/python/training/warm_starting_util.py @@ -32,7 +32,7 @@ from tensorflow.python.training import saver from tensorflow.python.util.tf_export import tf_export -@tf_export("train.VocabInfo") +@tf_export(v1=["train.VocabInfo"]) class VocabInfo( collections.namedtuple("VocabInfo", [ "new_vocab", @@ -248,7 +248,7 @@ def _warm_start_var_with_vocab(var, prev_tensor_name = _infer_var_name(var) # TODO(eddz): Fix functionality for rank-1 Variables (like FC biases). - total_v_first_axis = sum([v.get_shape().as_list()[0] for v in var]) + total_v_first_axis = sum(v.get_shape().as_list()[0] for v in var) for v in var: v_shape = v.get_shape().as_list() slice_info = v._get_save_slice_info() @@ -333,12 +333,12 @@ def _get_grouped_variables(vars_to_warm_start): ops.GraphKeys.TRAINABLE_VARIABLES, scope=vars_to_warm_start) elif isinstance(vars_to_warm_start, list): - if all([isinstance(v, str) for v in vars_to_warm_start]): + if all(isinstance(v, str) for v in vars_to_warm_start): list_of_vars = [] for v in vars_to_warm_start: list_of_vars += ops.get_collection(ops.GraphKeys.GLOBAL_VARIABLES, scope=v) - elif all([checkpoint_utils._is_variable(v) for v in vars_to_warm_start]): # pylint: disable=protected-access + elif all(checkpoint_utils._is_variable(v) for v in vars_to_warm_start): # pylint: disable=protected-access list_of_vars = vars_to_warm_start else: raise ValueError("If `vars_to_warm_start` is a list, it must be all " @@ -360,7 +360,7 @@ def _get_grouped_variables(vars_to_warm_start): return grouped_variables -@tf_export("train.warm_start") +@tf_export(v1=["train.warm_start"]) def warm_start(ckpt_to_initialize_from, vars_to_warm_start=".*", var_name_to_vocab_info=None, diff --git a/tensorflow/python/training/warm_starting_util_test.py b/tensorflow/python/training/warm_starting_util_test.py index 91a0b53b3a..fa1f370f41 100644 --- a/tensorflow/python/training/warm_starting_util_test.py +++ b/tensorflow/python/training/warm_starting_util_test.py @@ -22,7 +22,7 @@ import os import numpy as np import six -from tensorflow.python.feature_column import feature_column as fc +from tensorflow.python.feature_column import feature_column_lib as fc from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.ops import array_ops @@ -49,7 +49,7 @@ class WarmStartingUtilTest(test.TestCase): return vocab_file def _write_checkpoint(self, sess): - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) saver = saver_lib.Saver() ckpt_prefix = os.path.join(self.get_temp_dir(), "model") saver.save(sess, ckpt_prefix, global_step=0) @@ -70,7 +70,7 @@ class WarmStartingUtilTest(test.TestCase): if partitioner: self.assertTrue(isinstance(var, variables.PartitionedVariable)) var = var._get_variable_list() - return var, sess.run(var) + return var, self.evaluate(var) def _create_prev_run_vars(self, var_names, @@ -86,7 +86,7 @@ class WarmStartingUtilTest(test.TestCase): shape=shape, initializer=initializer)) self._write_checkpoint(sess) - return [sess.run(var) for var in all_vars] + return [self.evaluate(var) for var in all_vars] def _create_dummy_inputs(self): return { @@ -125,7 +125,7 @@ class WarmStartingUtilTest(test.TestCase): prev_tensor_name, var = ws_util._get_var_info(fruit_weights) checkpoint_utils.init_from_checkpoint(self.get_temp_dir(), {prev_tensor_name: var}) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertAllClose(prev_val, fruit_weights.eval(sess)) def testWarmStartVarPrevVarPartitioned(self): @@ -143,7 +143,7 @@ class WarmStartingUtilTest(test.TestCase): prev_tensor_name, var = ws_util._get_var_info(fruit_weights) checkpoint_utils.init_from_checkpoint(self.get_temp_dir(), {prev_tensor_name: var}) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertAllClose(prev_val, fruit_weights.eval(sess)) def testWarmStartVarCurrentVarPartitioned(self): @@ -162,7 +162,7 @@ class WarmStartingUtilTest(test.TestCase): prev_tensor_name, var = ws_util._get_var_info(fruit_weights) checkpoint_utils.init_from_checkpoint(self.get_temp_dir(), {prev_tensor_name: var}) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) fruit_weights = fruit_weights._get_variable_list() new_val = np.concatenate( [fruit_weights[0].eval(sess), fruit_weights[1].eval(sess)], axis=0) @@ -189,7 +189,7 @@ class WarmStartingUtilTest(test.TestCase): fruit_weights, prev_tensor_name="old_scope/fruit_weights") checkpoint_utils.init_from_checkpoint(self.get_temp_dir(), {prev_tensor_name: var}) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) fruit_weights = fruit_weights._get_variable_list() new_val = np.concatenate( [fruit_weights[0].eval(sess), fruit_weights[1].eval(sess)], axis=0) @@ -211,7 +211,7 @@ class WarmStartingUtilTest(test.TestCase): "fruit_weights", initializer=[[0.], [0.], [0.], [0.], [0.]]) ws_util._warm_start_var_with_vocab(fruit_weights, new_vocab_path, 5, self.get_temp_dir(), prev_vocab_path) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertAllClose([[2.], [1.5], [1.], [0.5], [0.]], fruit_weights.eval(sess)) @@ -236,7 +236,7 @@ class WarmStartingUtilTest(test.TestCase): prev_ckpt=self.get_temp_dir(), prev_vocab_path=prev_vocab_path, axis=1) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertAllClose([[0.3, 0.5, 0.], [0.8, 1.0, 0.], [1.2, 1.5, 0.], [2.3, 2., 0.]], fruit_output_layer.eval(sess)) @@ -261,7 +261,7 @@ class WarmStartingUtilTest(test.TestCase): self.get_temp_dir(), prev_vocab_path, previous_vocab_size=2) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Old vocabulary limited to ['apple', 'banana']. self.assertAllClose([[0.], [0.], [1.], [0.5], [0.]], fruit_weights.eval(sess)) @@ -285,7 +285,7 @@ class WarmStartingUtilTest(test.TestCase): "fruit_weights", initializer=[[0.], [0.], [0.], [0.], [0.]]) ws_util._warm_start_var_with_vocab(fruit_weights, new_vocab_path, 5, self.get_temp_dir(), prev_vocab_path) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertAllClose([[2.], [1.5], [1.], [0.5], [0.]], fruit_weights.eval(sess)) @@ -312,7 +312,7 @@ class WarmStartingUtilTest(test.TestCase): prev_ckpt=self.get_temp_dir(), prev_vocab_path=prev_vocab_path, axis=1) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertAllClose([[0.3, 0.5, 0.], [0.8, 1.0, 0.], [1.2, 1.5, 0.], [2.3, 2., 0.]], fruit_output_layer.eval(sess)) @@ -340,7 +340,7 @@ class WarmStartingUtilTest(test.TestCase): self.get_temp_dir(), prev_vocab_path, current_oov_buckets=1) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertTrue( isinstance(fruit_weights, variables.PartitionedVariable)) fruit_weights_vars = fruit_weights._get_variable_list() @@ -372,7 +372,7 @@ class WarmStartingUtilTest(test.TestCase): prev_ckpt=self.get_temp_dir(), prev_vocab_path=prev_vocab_path, axis=1) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertTrue( isinstance(fruit_output_layer, variables.PartitionedVariable)) fruit_output_layer_vars = fruit_output_layer._get_variable_list() @@ -404,7 +404,7 @@ class WarmStartingUtilTest(test.TestCase): partitioner=lambda shape, dtype: [2, 1]) ws_util._warm_start_var_with_vocab(fruit_weights, new_vocab_path, 6, self.get_temp_dir(), prev_vocab_path) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertTrue( isinstance(fruit_weights, variables.PartitionedVariable)) fruit_weights_vars = fruit_weights._get_variable_list() @@ -438,7 +438,7 @@ class WarmStartingUtilTest(test.TestCase): prev_ckpt=self.get_temp_dir(), prev_vocab_path=prev_vocab_path, axis=1) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) self.assertTrue( isinstance(fruit_output_layer, variables.PartitionedVariable)) fruit_output_layer_vars = fruit_output_layer._get_variable_list() @@ -463,7 +463,7 @@ class WarmStartingUtilTest(test.TestCase): shape=[10, 1], initializer=zeros()) ws_util.warm_start(self.get_temp_dir(), vars_to_warm_start=[var]) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started (init overridden to ones). self.assertAllEqual(var.eval(), prev_int_val) @@ -483,7 +483,7 @@ class WarmStartingUtilTest(test.TestCase): shape=[10, 1], initializer=zeros()) ws_util.warm_start(self.get_temp_dir(), vars_to_warm_start=["v1"]) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started (init overridden to ones). self.assertAllEqual(var.eval(), prev_int_val) @@ -519,7 +519,7 @@ class WarmStartingUtilTest(test.TestCase): # This warm-starts both v1 and v1/Momentum, but only # v2 (and not v2/Momentum). vars_to_warm_start=["v1", "v2[^/]"]) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify the selection of weights were correctly warm-started (init # overridden to ones). self.assertAllEqual(v1.eval(), prev_v1_val) @@ -542,7 +542,7 @@ class WarmStartingUtilTest(test.TestCase): with ops.Graph().as_default() as g: with self.session(graph=g) as sess: cols_to_vars = self._create_linear_model([sc_int], partitioner) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Without warm-starting, the weights should be initialized using default # initializer (which is init_ops.zeros_initializer). self._assert_cols_to_vars(cols_to_vars, {sc_int: [np.zeros([10, 1])]}, @@ -553,7 +553,7 @@ class WarmStartingUtilTest(test.TestCase): with self.session(graph=g) as sess: cols_to_vars = self._create_linear_model([sc_int], partitioner) ws_util.warm_start(self.get_temp_dir(), vars_to_warm_start=".*sc_int.*") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. self._assert_cols_to_vars(cols_to_vars, {sc_int: [prev_int_val]}, sess) @@ -571,7 +571,7 @@ class WarmStartingUtilTest(test.TestCase): with ops.Graph().as_default() as g: with self.session(graph=g) as sess: cols_to_vars = self._create_linear_model([sc_hash], partitioner) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Without warm-starting, the weights should be initialized using default # initializer (which is init_ops.zeros_initializer). self._assert_cols_to_vars(cols_to_vars, {sc_hash: [np.zeros([15, 1])]}, @@ -583,7 +583,7 @@ class WarmStartingUtilTest(test.TestCase): cols_to_vars = self._create_linear_model([sc_hash], partitioner) ws_util.warm_start( self.get_temp_dir(), vars_to_warm_start=".*sc_hash.*") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. self._assert_cols_to_vars(cols_to_vars, {sc_hash: [prev_hash_val]}, sess) @@ -605,7 +605,7 @@ class WarmStartingUtilTest(test.TestCase): with ops.Graph().as_default() as g: with self.session(graph=g) as sess: cols_to_vars = self._create_linear_model([sc_vocab], partitioner) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Without warm-starting, the weights should be initialized using default # initializer (which is init_ops.zeros_initializer). self._assert_cols_to_vars(cols_to_vars, {sc_vocab: [np.zeros([4, 1])]}, @@ -619,7 +619,7 @@ class WarmStartingUtilTest(test.TestCase): # vocab is assumed to be same as new vocab. ws_util.warm_start( self.get_temp_dir(), vars_to_warm_start=".*sc_vocab.*") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. self._assert_cols_to_vars(cols_to_vars, {sc_vocab: [prev_vocab_val]}, sess) @@ -641,7 +641,7 @@ class WarmStartingUtilTest(test.TestCase): with ops.Graph().as_default() as g: with self.session(graph=g) as sess: cols_to_vars = self._create_linear_model([sc_vocab], partitioner) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Without warm-starting, the weights should be initialized using default # initializer (which is init_ops.zeros_initializer). self._assert_cols_to_vars(cols_to_vars, {sc_vocab: [np.zeros([4, 1])]}, @@ -657,7 +657,7 @@ class WarmStartingUtilTest(test.TestCase): # Explicitly provide the file prefix instead of just the dir. os.path.join(self.get_temp_dir(), "model-0"), vars_to_warm_start=".*sc_vocab.*") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. self._assert_cols_to_vars(cols_to_vars, {sc_vocab: [prev_vocab_val]}, sess) @@ -686,7 +686,7 @@ class WarmStartingUtilTest(test.TestCase): with ops.Graph().as_default() as g: with self.session(graph=g) as sess: cols_to_vars = self._create_linear_model([sc_vocab], partitioner) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Without warm-starting, the weights should be initialized using default # initializer (which is init_ops.zeros_initializer). self._assert_cols_to_vars(cols_to_vars, {sc_vocab: [np.zeros([2, 1])]}, @@ -708,7 +708,7 @@ class WarmStartingUtilTest(test.TestCase): var_name_to_vocab_info={ "linear_model/sc_vocab/weights": vocab_info }) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. 'banana' isn't in the # first two entries of the old vocabulary, so it's newly initialized. self._assert_cols_to_vars(cols_to_vars, {sc_vocab: [[[1], [0]]]}, sess) @@ -729,7 +729,7 @@ class WarmStartingUtilTest(test.TestCase): with ops.Graph().as_default() as g: with self.session(graph=g) as sess: cols_to_vars = self._create_linear_model([real_bucket], partitioner) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Without warm-starting, the weights should be initialized using default # initializer (which is init_ops.zeros_initializer). self._assert_cols_to_vars(cols_to_vars, @@ -741,7 +741,7 @@ class WarmStartingUtilTest(test.TestCase): cols_to_vars = self._create_linear_model([real_bucket], partitioner) ws_util.warm_start( self.get_temp_dir(), vars_to_warm_start=".*real_bucketized.*") - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. self._assert_cols_to_vars(cols_to_vars, {real_bucket: [prev_bucket_val]}, sess) @@ -800,7 +800,7 @@ class WarmStartingUtilTest(test.TestCase): with ops.Graph().as_default() as g: with self.session(graph=g) as sess: cols_to_vars = self._create_linear_model(all_linear_cols, partitioner) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Without warm-starting, all weights should be initialized using default # initializer (which is init_ops.zeros_initializer). self._assert_cols_to_vars(cols_to_vars, { @@ -826,7 +826,7 @@ class WarmStartingUtilTest(test.TestCase): var_name_to_vocab_info={ "linear_model/sc_vocab/weights": vocab_info }) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. self._assert_cols_to_vars(cols_to_vars, { sc_int: [prev_int_val], @@ -865,7 +865,7 @@ class WarmStartingUtilTest(test.TestCase): "linear_model/sc_vocab/weights", initializer=[[0.5], [1.], [2.], [3.]]) self._write_checkpoint(sess) - prev_keys_val = sess.run(sc_keys_weights) + prev_keys_val = self.evaluate(sc_keys_weights) def _partitioner(shape, dtype): # pylint:disable=unused-argument # Partition each var into 2 equal slices. @@ -892,7 +892,7 @@ class WarmStartingUtilTest(test.TestCase): ws_util._infer_var_name(cols_to_vars[sc_keys]): "some_other_name" }) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. Var corresponding to # sc_hash should not be warm-started. Var corresponding to sc_vocab # should be correctly warm-started after vocab remapping. @@ -933,7 +933,7 @@ class WarmStartingUtilTest(test.TestCase): "linear_model/sc_vocab/weights", initializer=[[0.5], [1.], [2.], [3.]]) self._write_checkpoint(sess) - prev_keys_val = sess.run(sc_keys_weights) + prev_keys_val = self.evaluate(sc_keys_weights) # New graph, new session with warm-starting. with ops.Graph().as_default() as g: @@ -955,7 +955,7 @@ class WarmStartingUtilTest(test.TestCase): ws_util._infer_var_name(cols_to_vars[sc_keys]): "some_other_name" }) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. Var corresponding to # sc_hash should not be warm-started. Var corresponding to sc_vocab # should be correctly warm-started after vocab remapping. @@ -1024,7 +1024,7 @@ class WarmStartingUtilTest(test.TestCase): ws_util._infer_var_name(cols_to_vars[sc_keys]): "some_other_name" }) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. Var corresponding to # sc_vocab should be correctly warm-started after vocab remapping, # and neither of the other two should be warm-started.. @@ -1091,7 +1091,7 @@ class WarmStartingUtilTest(test.TestCase): ws_util._infer_var_name(cols_to_vars[emb_vocab_column]): vocab_info }) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. Var corresponding to # emb_vocab_column should be correctly warm-started after vocab # remapping. Missing values are filled in with the EmbeddingColumn's @@ -1163,7 +1163,7 @@ class WarmStartingUtilTest(test.TestCase): var_name_to_vocab_info={ "linear_model/sc_vocab_embedding/embedding_weights": vocab_info }) - sess.run(variables.global_variables_initializer()) + self.evaluate(variables.global_variables_initializer()) # Verify weights were correctly warm-started. Var corresponding to # emb_vocab should be correctly warm-started after vocab remapping. # Missing values are filled in with the EmbeddingColumn's initializer. diff --git a/tensorflow/python/util/deprecation.py b/tensorflow/python/util/deprecation.py index 4c68d1aaae..9aaf0c2de9 100644 --- a/tensorflow/python/util/deprecation.py +++ b/tensorflow/python/util/deprecation.py @@ -28,6 +28,7 @@ from tensorflow.python.util import is_in_graph_mode from tensorflow.python.util import tf_contextlib from tensorflow.python.util import tf_decorator from tensorflow.python.util import tf_inspect +from tensorflow.python.util import tf_stack # Allow deprecation warnings to be silenced temporarily with a context manager. @@ -98,21 +99,9 @@ def _validate_deprecation_args(date, instructions): def _call_location(outer=False): """Returns call location given level up from current call.""" - frame = tf_inspect.currentframe() - if frame: - # CPython internals are available, use them for performance. - # walk back two frames to get to deprecated function caller. - frame = frame.f_back - if frame.f_back: - frame = frame.f_back - if outer and frame.f_back: - frame = frame.f_back - return '%s:%d' % (frame.f_code.co_filename, frame.f_lineno) - else: - # Slow fallback path - stack = tf_inspect.stack(0) # 0 avoids generating unused context - entry = stack[3 if outer else 2] - return '%s:%d' % (entry[1], entry[2]) + stack = tf_stack.extract_stack() + frame = stack[-4 if outer else -3] + return '{filename}:{lineno}'.format(filename=frame[0], lineno=frame[1]) def _wrap_decorator(wrapped_function): diff --git a/tensorflow/python/util/deprecation_test.py b/tensorflow/python/util/deprecation_test.py index 34cbca52a1..035c416d79 100644 --- a/tensorflow/python/util/deprecation_test.py +++ b/tensorflow/python/util/deprecation_test.py @@ -19,6 +19,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from tensorflow.python.framework import test_util from tensorflow.python.platform import test from tensorflow.python.platform import tf_logging as logging from tensorflow.python.util import deprecation @@ -174,6 +175,7 @@ class DeprecationTest(test.TestCase): set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_static_fn_with_doc(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -214,6 +216,7 @@ class DeprecationTest(test.TestCase): self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_static_fn_with_one_line_doc(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -239,6 +242,7 @@ class DeprecationTest(test.TestCase): self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_static_fn_no_doc(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -488,6 +492,7 @@ class DeprecatedArgsTest(test.TestCase): deprecation.deprecated_args(date, instructions, "missing")(_fn) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_static_fn_with_doc(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -535,6 +540,7 @@ class DeprecatedArgsTest(test.TestCase): self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_static_fn_with_one_line_doc(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -565,6 +571,7 @@ class DeprecatedArgsTest(test.TestCase): self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_static_fn_no_doc(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -595,6 +602,7 @@ class DeprecatedArgsTest(test.TestCase): self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_varargs(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -615,6 +623,7 @@ class DeprecatedArgsTest(test.TestCase): self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_kwargs(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -635,6 +644,7 @@ class DeprecatedArgsTest(test.TestCase): self._assert_subset(set(["after " + date, instructions]), set(args[1:])) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_positional_and_named(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -660,6 +670,7 @@ class DeprecatedArgsTest(test.TestCase): set(args2[1:])) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_positional_and_named_with_ok_vals(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -692,6 +703,7 @@ class DeprecatedArgsTest(test.TestCase): self.assertEqual(0, mock_warning.call_count) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_deprecated_args_once(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -708,6 +720,7 @@ class DeprecatedArgsTest(test.TestCase): self.assertEqual(1, mock_warning.call_count) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_deprecated_multiple_args_once_each(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -752,6 +765,7 @@ class DeprecatedArgValuesTest(test.TestCase): deprecation.deprecated_arg_values(date, instructions) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_static_fn_with_doc(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -804,6 +818,7 @@ class DeprecatedArgValuesTest(test.TestCase): self.assertEqual(2, mock_warning.call_count) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_static_fn_with_one_line_doc(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." @@ -839,6 +854,7 @@ class DeprecatedArgValuesTest(test.TestCase): self.assertEqual(2, mock_warning.call_count) @test.mock.patch.object(logging, "warning", autospec=True) + @test_util.run_deprecated_v1 def test_static_fn_no_doc(self, mock_warning): date = "2016-07-04" instructions = "This is how you update..." diff --git a/tensorflow/python/util/dispatch.py b/tensorflow/python/util/dispatch.py new file mode 100644 index 0000000000..e7a56b5922 --- /dev/null +++ b/tensorflow/python/util/dispatch.py @@ -0,0 +1,192 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Type-based dispatch for TensorFlow ops. + +"Operation dispatchers" can be used to override the behavior for TensorFlow ops +when they are called with otherwise unsupported argument types. In particular, +when an operation is called with arguments that would cause it to raise a +TypeError, it falls back on its registered operation dispatchers. If any +registered dispatchers can handle the arguments, then its result is returned. +Otherwise, the original TypeError is raised. + +By default, dispatch support is added to the generated op wrappers for any +visible ops by default. Ops that are implemented in Python can opt in to +dispatch support using the `add_dispatch_support` decorator. +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import itertools + +from tensorflow.python.util import tf_decorator +from tensorflow.python.util import tf_inspect + +# Private function attribute used to store a list of dispatchers. +DISPATCH_ATTR = "_tf_dispatchers" + + +class OpDispatcher(object): + """Abstract base class for TensorFlow operator dispatchers. + + Each operation dispatcher acts as an override handler for a single + TensorFlow operation, and its results are used when the handler indicates + that it can handle the operation's arguments (by returning any value other + than `OpDispatcher.NOT_SUPPORTED`). + """ + + # Sentinel value that can be returned to indicate that an operation + # dispatcher does not support a given set of arguments. + NOT_SUPPORTED = object() + + def handle(self, args, kwargs): # pylint: disable=unused-argument + """Handle this dispatcher's operation with the specified arguments. + + If this operation dispatcher can handle the given arguments, then + return an appropriate value (or raise an appropriate exception). + + Args: + args: The arguments to the operation. + kwargs: They keyword arguments to the operation. + + Returns: + The result of the operation, or `OpDispatcher.NOT_SUPPORTED` if this + dispatcher can not handle the given arguments. + """ + return self.NOT_SUPPORTED + + def register(self, op): + """Register this dispatcher as a handler for `op`. + + Args: + op: Python function: the TensorFlow operation that should be handled. Must + have a dispatch list (which is added automatically for generated ops, + and can be added to Python ops using the `add_dispatch_support` + decorator). + """ + if not hasattr(op, DISPATCH_ATTR): + raise AssertionError("Dispatching not enabled for %s" % op) + getattr(op, DISPATCH_ATTR).append(self) + + +def dispatch(op, *args, **kwargs): + """Returns the result from the first successful dispatcher for a given op. + + Calls the `handle` method of each `OpDispatcher` that has been registered + to handle `op`, and returns the value from the first successful handler. + + Args: + op: Python function: the operation to dispatch for. + *args: The arguments to the operation. + **kwargs: They keyword arguments to the operation. + + Returns: + The result of the operation, or `NOT_SUPPORTED` if no registered + dispatcher can handle the given arguments. + """ + for dispatcher in getattr(op, DISPATCH_ATTR): + result = dispatcher.handle(args, kwargs) + if result is not OpDispatcher.NOT_SUPPORTED: + return result + return OpDispatcher.NOT_SUPPORTED + + +class _TypeBasedDispatcher(OpDispatcher): + """Dispatcher that handles op if any arguments have a specified type. + + Checks the types of the arguments and keyword arguments (including elements + of lists or tuples), and if any argument values have the indicated type(s), + then delegates to an override function. + """ + + def __init__(self, override_func, types): + self._types = types + self._override_func = override_func + + def _handles(self, args, kwargs): + for arg in itertools.chain(args, kwargs.values()): + if (isinstance(arg, self._types) or + (isinstance(arg, (list, tuple)) and + any(isinstance(elt, self._types) for elt in arg))): + return True + return False + + def handle(self, args, kwargs): + if self._handles(args, kwargs): + return self._override_func(*args, **kwargs) + else: + return self.NOT_SUPPORTED + + +# pylint: disable=g-doc-return-or-yield +def dispatch_for_types(op, *types): + """Decorator to declare that a Python function overrides an op for a type. + + The decorated function is used to override `op` if any of the arguments or + keyword arguments (including elements of lists or tuples) have one of the + specified types. + + Example: + + ```python + @dispatch_for_types(math_ops.add, RaggedTensor, RaggedTensorValue) + def ragged_add(x, y, name=None): ... + ``` + + Args: + op: Python function: the operation that should be overridden. + *types: The argument types for which this function should be used. + """ + + def decorator(func): + if tf_inspect.getargspec(func) != tf_inspect.getargspec(op): + raise AssertionError("The decorated function's signature must exactly " + "match the signature of the overridden op.") + _TypeBasedDispatcher(func, types).register(op) + return func + + return decorator + + +# pylint: enable=g-doc-return-or-yield + + +def add_dispatch_list(target): + """Decorator that adds a dispatch_list attribute to an op.""" + assert not hasattr(target, DISPATCH_ATTR) + setattr(target, DISPATCH_ATTR, []) + return target + + +def add_dispatch_support(target): + """Decorator that adds a dispatch handling wrapper to an op.""" + add_dispatch_list(target) + + def wrapper(*args, **kwargs): + """Call target, and fall back on dispatchers if there is a TypeError.""" + try: + return target(*args, **kwargs) + except (TypeError, ValueError): + # Note: convert_to_eager_tensor currently raises a ValueError, not a + # TypeError, when given unexpected types. So we need to catch both. + result = dispatch(wrapper, *args, **kwargs) + if result is not OpDispatcher.NOT_SUPPORTED: + return result + else: + raise + + setattr(wrapper, DISPATCH_ATTR, []) + return tf_decorator.make_decorator(target, wrapper) diff --git a/tensorflow/python/util/dispatch_test.py b/tensorflow/python/util/dispatch_test.py new file mode 100644 index 0000000000..b7c5c8eca8 --- /dev/null +++ b/tensorflow/python/util/dispatch_test.py @@ -0,0 +1,120 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for operator dispatch.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util +from tensorflow.python.ops import gen_math_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.platform import googletest +from tensorflow.python.util import dispatch +from tensorflow.python.util.tf_export import tf_export + + +class CustomTensor(object): + """A fake composite tensor class, for testing type-based dispatching.""" + + def __init__(self, tensor, score): + self.tensor = ops.convert_to_tensor(tensor) + self.score = score + + +@tf_export("test_op") +@dispatch.add_dispatch_support +def test_op(x, y, z): + """A fake op for testing dispatch of Python ops.""" + return x + (2 * y) + (3 * z) + + +@test_util.run_all_in_graph_and_eager_modes +class DispatchTest(test_util.TensorFlowTestCase): + + def testAddDispatchForTypes_With_CppOp(self): + original_handlers = gen_math_ops.add._tf_dispatchers[:] + + # Override the behavior of gen_math_ops.add. + @dispatch.dispatch_for_types(gen_math_ops.add, CustomTensor) + def custom_add(x, y, name=None): # pylint: disable=unused-variable + return CustomTensor(gen_math_ops.add(x.tensor, y.tensor, name), + (x.score+y.score) / 2.0) + self.assertEqual(len(math_ops.add._tf_dispatchers), + len(original_handlers) + 1) + + # Test that we see the overridden behavior when using CustomTensors. + x = CustomTensor([1, 2, 3], 2.0) + y = CustomTensor([7, 8, 2], 0.0) + x_plus_y = gen_math_ops.add(x, y) + self.assertAllEqual(self.evaluate(x_plus_y.tensor), [8, 10, 5]) + self.assertNear(x_plus_y.score, 1.0, 0.001) + + # Test that we still get the right behavior when using normal Tensors. + a = [1, 2, 3] + b = [4, 5, 6] + a_plus_b = gen_math_ops.add(a, b) + self.assertAllEqual(a_plus_b, [5, 7, 9]) + + # Test that we still get a TypeError or ValueError if we pass some + # type that's not supported by any dispatcher. + with self.assertRaises((TypeError, ValueError)): + gen_math_ops.add(a, None) + + # Clean up + gen_math_ops.add._tf_dispatchers = original_handlers + + def testAddDispatchForTypes_With_PythonOp(self): + original_handlers = test_op._tf_dispatchers[:] + + @dispatch.dispatch_for_types(test_op, CustomTensor) + def override_for_test_op(x, y, z): # pylint: disable=unused-variable + return CustomTensor(test_op(x.tensor, y.tensor, z.tensor), + (x.score + y.score + z.score) / 3.0) + + x = CustomTensor([1, 2, 3], 0.2) + y = CustomTensor([7, 8, 2], 0.4) + z = CustomTensor([0, 1, 2], 0.6) + + result = test_op(x, y, z) + self.assertAllEqual(self.evaluate(result.tensor), [15, 21, 13]) + self.assertNear(result.score, 0.4, 0.001) + + # Clean up + test_op._tf_dispatchers = original_handlers + + def testDispatchForTypes_SignatureMismatch(self): + with self.assertRaisesRegexp(AssertionError, "The decorated function's " + "signature must exactly match.*"): + @dispatch.dispatch_for_types(test_op, CustomTensor) + def override_for_test_op(a, b, c): # pylint: disable=unused-variable + return CustomTensor(test_op(a.tensor, b.tensor, c.tensor), + (a.score + b.score + c.score) / 3.0) + + def testDispatchForTypes_OpDoesNotSupportDispatch(self): + def some_op(x, y): + return x + y + + with self.assertRaisesRegexp(AssertionError, "Dispatching not enabled for"): + @dispatch.dispatch_for_types(some_op, CustomTensor) + def override_for_some_op(x, y): # pylint: disable=unused-variable + return x if x.score > 0 else y + + +if __name__ == "__main__": + googletest.main() + + diff --git a/tensorflow/python/util/nest_test.py b/tensorflow/python/util/nest_test.py index 997a3c5c36..d0d0c5f793 100644 --- a/tensorflow/python/util/nest_test.py +++ b/tensorflow/python/util/nest_test.py @@ -482,6 +482,7 @@ class NestTest(parameterized.TestCase, test.TestCase): self.assertEqual(nt.a[1][::-1], rev_nt.a[1]) self.assertEqual(nt.b[::-1], rev_nt.b) + @test_util.run_deprecated_v1 def testMapStructureOverPlaceholders(self): inp_a = (array_ops.placeholder(dtypes.float32, shape=[3, 4]), array_ops.placeholder(dtypes.float32, shape=[3, 7])) diff --git a/tensorflow/python/util/py_checkpoint_reader.i b/tensorflow/python/util/py_checkpoint_reader.i index 1c73f7f06f..a1b98a2a75 100644 --- a/tensorflow/python/util/py_checkpoint_reader.i +++ b/tensorflow/python/util/py_checkpoint_reader.i @@ -165,7 +165,6 @@ def NewCheckpointReader(filepattern): from tensorflow.python.util import compat return CheckpointReader(compat.as_bytes(filepattern), status) -NewCheckpointReader._tf_api_names = ['train.NewCheckpointReader'] NewCheckpointReader._tf_api_names_v1 = ['train.NewCheckpointReader'] %} diff --git a/tensorflow/python/util/tf_export.py b/tensorflow/python/util/tf_export.py index 0924b36ade..ec70cae7d2 100644 --- a/tensorflow/python/util/tf_export.py +++ b/tensorflow/python/util/tf_export.py @@ -50,6 +50,10 @@ from tensorflow.python.util import tf_decorator ESTIMATOR_API_NAME = 'estimator' TENSORFLOW_API_NAME = 'tensorflow' +# List of subpackage names used by TensorFlow components. Have to check that +# TensorFlow core repo does not export any symbols under these names. +SUBPACKAGE_NAMESPACES = [ESTIMATOR_API_NAME] + _Attributes = collections.namedtuple( 'ExportedApiAttributes', ['names', 'constants']) @@ -78,6 +82,11 @@ class SymbolAlreadyExposedError(Exception): pass +class InvalidSymbolNameError(Exception): + """Raised when trying to export symbol as an invalid or unallowed name.""" + pass + + def get_canonical_name_for_symbol( symbol, api_name=TENSORFLOW_API_NAME, add_prefix_to_v1_names=False): @@ -163,6 +172,37 @@ class api_export(object): # pylint: disable=invalid-name self._overrides = kwargs.get('overrides', []) self._allow_multiple_exports = kwargs.get('allow_multiple_exports', False) + self._validate_symbol_names() + + def _validate_symbol_names(self): + """Validate you are exporting symbols under an allowed package. + + We need to ensure things exported by tf_export, estimator_export, etc. + export symbols under disjoint top-level package names. + + For TensorFlow, we check that it does not export anything under subpackage + names used by components (estimator, keras, etc.). + + For each component, we check that it exports everything under its own + subpackage. + + Raises: + InvalidSymbolNameError: If you try to export symbol under disallowed name. + """ + all_symbol_names = set(self._names) | set(self._names_v1) + if self._api_name == TENSORFLOW_API_NAME: + for subpackage in SUBPACKAGE_NAMESPACES: + if any(n.startswith(subpackage) for n in all_symbol_names): + raise InvalidSymbolNameError( + '@tf_export is not allowed to export symbols under %s.*' % ( + subpackage)) + else: + if not all(n.startswith(self._api_name) for n in all_symbol_names): + raise InvalidSymbolNameError( + 'Can only export symbols under package name of component. ' + 'e.g. tensorflow_estimator must export all symbols under ' + 'tf.estimator') + def __call__(self, func): """Calls this decorator. diff --git a/tensorflow/python/util/tf_export_test.py b/tensorflow/python/util/tf_export_test.py index 4ae1dc55e0..a0fac8bf36 100644 --- a/tensorflow/python/util/tf_export_test.py +++ b/tensorflow/python/util/tf_export_test.py @@ -130,6 +130,26 @@ class ValidateExportTest(test.TestCase): with self.assertRaises(tf_export.SymbolAlreadyExposedError): export_decorator(_test_function) + def testRaisesExceptionIfInvalidSymbolName(self): + # TensorFlow code is not allowed to export symbols under package + # tf.estimator + with self.assertRaises(tf_export.InvalidSymbolNameError): + tf_export.tf_export('estimator.invalid') + + # All symbols exported by Estimator must be under tf.estimator package. + with self.assertRaises(tf_export.InvalidSymbolNameError): + tf_export.estimator_export('invalid') + with self.assertRaises(tf_export.InvalidSymbolNameError): + tf_export.estimator_export('Estimator.invalid') + with self.assertRaises(tf_export.InvalidSymbolNameError): + tf_export.estimator_export('invalid.estimator') + + def testRaisesExceptionIfInvalidV1SymbolName(self): + with self.assertRaises(tf_export.InvalidSymbolNameError): + tf_export.tf_export('valid', v1=['estimator.invalid']) + with self.assertRaises(tf_export.InvalidSymbolNameError): + tf_export.estimator_export('estimator.valid', v1=['invalid']) + def testOverridesFunction(self): _test_function2._tf_api_names = ['abc'] diff --git a/tensorflow/python/util/tf_should_use_test.py b/tensorflow/python/util/tf_should_use_test.py index fedbe1dff6..65d848cf2a 100644 --- a/tensorflow/python/util/tf_should_use_test.py +++ b/tensorflow/python/util/tf_should_use_test.py @@ -24,6 +24,7 @@ import gc import sys from tensorflow.python.framework import constant_op +from tensorflow.python.framework import test_util from tensorflow.python.platform import test from tensorflow.python.platform import tf_logging from tensorflow.python.util import tf_should_use @@ -39,6 +40,7 @@ def reroute_error(): class TfShouldUseTest(test.TestCase): + @test_util.run_deprecated_v1 def testAddShouldUseWarningWhenNotUsed(self): c = constant_op.constant(0, name='blah0') def in_this_function(): @@ -52,6 +54,7 @@ class TfShouldUseTest(test.TestCase): self.assertIn('in_this_function', msg) self.assertFalse(gc.garbage) + @test_util.run_deprecated_v1 def testAddShouldUseFatalWhenNotUsed(self): c = constant_op.constant(0, name='blah0') def in_this_function(): @@ -74,6 +77,7 @@ class TfShouldUseTest(test.TestCase): error.assert_not_called() fatal.assert_not_called() + @test_util.run_deprecated_v1 def testAddShouldUseWarningWhenUsedWithAdd(self): def add(h): _ = h + 1 @@ -81,6 +85,7 @@ class TfShouldUseTest(test.TestCase): gc.collect() self.assertFalse(gc.garbage) + @test_util.run_deprecated_v1 def testAddShouldUseWarningWhenUsedWithGetName(self): def get_name(h): _ = h.name @@ -88,6 +93,7 @@ class TfShouldUseTest(test.TestCase): gc.collect() self.assertFalse(gc.garbage) + @test_util.run_deprecated_v1 def testShouldUseResult(self): @tf_should_use.should_use_result def return_const(value): @@ -101,6 +107,7 @@ class TfShouldUseTest(test.TestCase): gc.collect() self.assertFalse(gc.garbage) + @test_util.run_deprecated_v1 def testShouldUseResultWhenNotReallyUsed(self): @tf_should_use.should_use_result def return_const(value): @@ -111,7 +118,7 @@ class TfShouldUseTest(test.TestCase): # Creating another op and executing it does not mark the # unused op as being "used". v = constant_op.constant(1.0, name='meh') - v.eval() + self.evaluate(v) msg = '\n'.join(error.call_args[0]) self.assertIn('Object was never used', msg) self.assertIn('blah3:0', msg) diff --git a/tensorflow/stream_executor/BUILD b/tensorflow/stream_executor/BUILD index 5c9d85acf4..4c764a7b09 100644 --- a/tensorflow/stream_executor/BUILD +++ b/tensorflow/stream_executor/BUILD @@ -1,6 +1,8 @@ licenses(["restricted"]) load("@local_config_cuda//cuda:build_defs.bzl", "if_cuda_is_configured") +load("//tensorflow/core:platform/default/build_config.bzl", "tf_proto_library") +load("//tensorflow/core:platform/default/build_config.bzl", "tf_additional_all_protos") load("//tensorflow/core:platform/default/build_config_root.bzl", "if_static") load("//tensorflow:tensorflow.bzl", "cc_header_only_library") @@ -13,6 +15,14 @@ STREAM_EXECUTOR_HEADERS = glob([ "platform/**/*.h", ]) +tf_proto_library( + name = "dnn_proto", + srcs = ["dnn.proto"], + cc_api_version = 2, + default_header = True, + protodeps = tf_additional_all_protos(), +) + cc_library( name = "stream_executor_impl", srcs = glob( @@ -35,6 +45,7 @@ cc_library( }), visibility = ["//visibility:public"], deps = [ + ":dnn_proto_cc_impl", "//tensorflow/core:lib", "//tensorflow/core:ptr_util", "@com_google_absl//absl/container:flat_hash_map", @@ -51,6 +62,7 @@ cc_library( hdrs = STREAM_EXECUTOR_HEADERS, visibility = ["//visibility:public"], deps = [ + ":dnn_proto_cc", "//tensorflow/core:lib", "//tensorflow/core:ptr_util", "@com_google_absl//absl/strings", @@ -96,11 +108,8 @@ cc_library( "@local_config_cuda//cuda:cuda_headers", ] + if_cuda_is_configured([ "//tensorflow/core:cuda", - "@local_config_cuda//cuda:cublas", "@local_config_cuda//cuda:cuda_driver", "@local_config_cuda//cuda:cudnn", - "@local_config_cuda//cuda:cufft", - "@local_config_cuda//cuda:curand", ]), alwayslink = 1, ) diff --git a/tensorflow/stream_executor/cuda/cuda_blas.cc b/tensorflow/stream_executor/cuda/cuda_blas.cc index 7fabb35e28..957f6c98da 100644 --- a/tensorflow/stream_executor/cuda/cuda_blas.cc +++ b/tensorflow/stream_executor/cuda/cuda_blas.cc @@ -58,6 +58,11 @@ limitations under the License. #include "tensorflow/stream_executor/cuda/cuda_stream.h" #include "tensorflow/stream_executor/cuda/cuda_timer.h" #include "tensorflow/stream_executor/device_memory.h" + +#ifndef PLATFORM_GOOGLE +#include "tensorflow/stream_executor/dso_loader.h" +#endif + #include "tensorflow/stream_executor/lib/env.h" #include "tensorflow/stream_executor/lib/initialize.h" #include "tensorflow/stream_executor/lib/status.h" @@ -76,21 +81,8 @@ PLUGIN_REGISTRY_DEFINE_PLUGIN_ID(kCuBlasPlugin); namespace wrap { -#define STREAM_EXECUTOR_CUBLAS_WRAP(__name) \ - struct WrapperShim__##__name { \ - static const char *kName; \ - template \ - cublasStatus_t operator()(CUDAExecutor *parent, Args... args) { \ - cuda::ScopedActivateExecutorContext sac{parent}; \ - return ::__name(args...); \ - } \ - } __name; \ - const char *WrapperShim__##__name::kName = #__name; - -#define STREAM_EXECUTOR_CUBLAS_V2_WRAP(__name) \ - STREAM_EXECUTOR_CUBLAS_WRAP(__name) - -#define CUBLAS_BLAS_ROUTINE_EACH(__macro) \ +// clang-format off +#define CUBLAS_ROUTINE_EACH(__macro) \ __macro(cublasSnrm2) \ __macro(cublasDnrm2) \ __macro(cublasScnrm2) \ @@ -262,6 +254,58 @@ namespace wrap { __macro(cublasCdgmm) \ __macro(cublasZdgmm) +// clang-format off + +#ifdef PLATFORM_GOOGLE +#define STREAM_EXECUTOR_CUBLAS_WRAP(__name) \ + struct WrapperShim__##__name { \ + static const char *kName; \ + template \ + cublasStatus_t operator()(CUDAExecutor *parent, Args... args) { \ + cuda::ScopedActivateExecutorContext sac{parent}; \ + return ::__name(args...); \ + } \ + } __name; \ + const char *WrapperShim__##__name::kName = #__name; + +#define STREAM_EXECUTOR_CUBLAS_V2_WRAP(__name) \ + STREAM_EXECUTOR_CUBLAS_WRAP(__name) + +#else + +#define STREAM_EXECUTOR_CUBLAS_WRAP(__name) \ + struct DynLoadShim__##__name { \ + static const char* kName; \ + using FuncPtrT = std::add_pointer::type; \ + static void* GetDsoHandle() { \ + auto s = internal::CachedDsoLoader::GetCublasDsoHandle(); \ + return s.ValueOrDie(); \ + } \ + static FuncPtrT LoadOrDie() { \ + void* f; \ + auto s = port::Env::Default()->GetSymbolFromLibrary(GetDsoHandle(), \ + kName, &f); \ + CHECK(s.ok()) << "could not find " << kName \ + << " in cublas DSO; dlerror: " << s.error_message(); \ + return reinterpret_cast(f); \ + } \ + static FuncPtrT DynLoad() { \ + static FuncPtrT f = LoadOrDie(); \ + return f; \ + } \ + template \ + cublasStatus_t operator()(CUDAExecutor* parent, Args... args) { \ + cuda::ScopedActivateExecutorContext sac{parent}; \ + return DynLoad()(args...); \ + } \ + } __name; \ + const char* DynLoadShim__##__name::kName = #__name; + +#define STREAM_EXECUTOR_CUBLAS_V2_WRAP(__name) \ + STREAM_EXECUTOR_CUBLAS_WRAP(__name) + +#endif + STREAM_EXECUTOR_CUBLAS_V2_WRAP(cublasCreate) STREAM_EXECUTOR_CUBLAS_V2_WRAP(cublasDestroy) STREAM_EXECUTOR_CUBLAS_V2_WRAP(cublasSetStream) @@ -271,7 +315,7 @@ STREAM_EXECUTOR_CUBLAS_WRAP(cublasSgemmBatched) STREAM_EXECUTOR_CUBLAS_WRAP(cublasDgemmBatched) STREAM_EXECUTOR_CUBLAS_WRAP(cublasCgemmBatched) STREAM_EXECUTOR_CUBLAS_WRAP(cublasZgemmBatched) -CUBLAS_BLAS_ROUTINE_EACH(STREAM_EXECUTOR_CUBLAS_V2_WRAP) +CUBLAS_ROUTINE_EACH(STREAM_EXECUTOR_CUBLAS_V2_WRAP) #if CUDA_VERSION >= 7050 STREAM_EXECUTOR_CUBLAS_WRAP(cublasSgemmEx) @@ -424,7 +468,8 @@ class ScopedCublasMathMode { // Note that when false is returned, an appropriate error has already been // logged. bool Init(cublasMath_t new_mode) { - cublasStatus_t ret = wrap::cublasGetMathMode(parent_, handle_, &old_mode_); + cublasStatus_t ret = + wrap::cublasGetMathMode(parent_, handle_, &old_mode_); if (ret != CUBLAS_STATUS_SUCCESS) { LOG(ERROR) << "failed to get old cublas math mode: " << ToString(ret); return ok_ = false; @@ -442,7 +487,8 @@ class ScopedCublasMathMode { // successful in the first place. ~ScopedCublasMathMode() { if (ok_) { - cublasStatus_t ret = wrap::cublasSetMathMode(parent_, handle_, old_mode_); + cublasStatus_t ret = + wrap::cublasSetMathMode(parent_, handle_, old_mode_); if (ret != CUBLAS_STATUS_SUCCESS) { LOG(ERROR) << "failed to set former cublas math mode: " << ToString(ret); @@ -675,16 +721,16 @@ bool CUDABlas::DoBlasAsum(Stream *stream, uint64 elem_count, const DeviceMemory> &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasScasum, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasScasum, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasAsum(Stream *stream, uint64 elem_count, const DeviceMemory> &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasDzasum, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasDzasum, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasAxpy(Stream *stream, uint64 elem_count, float alpha, @@ -835,16 +881,16 @@ bool CUDABlas::DoBlasNrm2(Stream *stream, uint64 elem_count, const DeviceMemory> &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasScnrm2, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasScnrm2, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasNrm2(Stream *stream, uint64 elem_count, const DeviceMemory> &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasDznrm2, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasDznrm2, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasRot(Stream *stream, uint64 elem_count, @@ -1060,48 +1106,48 @@ bool CUDABlas::DoBlasIamax(Stream *stream, uint64 elem_count, const DeviceMemory> &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasIcamax, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasIcamax, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasIamax(Stream *stream, uint64 elem_count, const DeviceMemory> &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasIzamax, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasIzamax, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasIamin(Stream *stream, uint64 elem_count, const DeviceMemory &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasIsamin, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasIsamin, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasIamin(Stream *stream, uint64 elem_count, const DeviceMemory &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasIdamin, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasIdamin, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasIamin(Stream *stream, uint64 elem_count, const DeviceMemory> &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasIcamin, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasIcamin, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasIamin(Stream *stream, uint64 elem_count, const DeviceMemory> &x, int incx, DeviceMemory *result) { return DoBlasInternal( - wrap::cublasIzamin, stream, false /* = pointer_mode_host */, elem_count, - CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); + wrap::cublasIzamin, stream, false /* = pointer_mode_host */, + elem_count, CUDAComplex(CUDAMemory(x)), incx, CUDAMemoryMutable(result)); } bool CUDABlas::DoBlasGbmv(Stream *stream, blas::Transpose trans, uint64 m, diff --git a/tensorflow/stream_executor/cuda/cuda_dnn.cc b/tensorflow/stream_executor/cuda/cuda_dnn.cc index 19397c7dbf..1f2e2f48bb 100644 --- a/tensorflow/stream_executor/cuda/cuda_dnn.cc +++ b/tensorflow/stream_executor/cuda/cuda_dnn.cc @@ -132,43 +132,6 @@ string ToString(cudnnStatus_t status) { } } -template -cudnnDataType_t GetCudnnDataType( - dnn::DataLayout = dnn::DataLayout::kBatchDepthYX); - -template <> -cudnnDataType_t GetCudnnDataType(dnn::DataLayout) { - return CUDNN_DATA_DOUBLE; -} - -template <> -cudnnDataType_t GetCudnnDataType(dnn::DataLayout) { - return CUDNN_DATA_FLOAT; -} - -template <> -cudnnDataType_t GetCudnnDataType(dnn::DataLayout) { - return CUDNN_DATA_HALF; -} - -template <> -cudnnDataType_t GetCudnnDataType(dnn::DataLayout layout) { - switch (layout) { - case dnn::DataLayout::kYXDepthBatch: - case dnn::DataLayout::kYXBatchDepth: - case dnn::DataLayout::kBatchYXDepth: - case dnn::DataLayout::kBatchDepthYX: - return CUDNN_DATA_INT8; - case dnn::DataLayout::kBatchDepthYX4: - return CUDNN_DATA_INT8x4; - } -} - -template <> -cudnnDataType_t GetCudnnDataType(dnn::DataLayout) { - return CUDNN_DATA_INT32; -} - // RAII wrapper for all calls to cuDNN with a cuDNN handle argument. // // See CudnnAccess::GetHandle() for details. @@ -685,10 +648,10 @@ class CudnnConvolutionDescriptor { CHECK_CUDNN_OK(cudnnSetConvolutionNdDescriptor( handle_.get(), convolution_descriptor.ndims(), padding.data(), strides.data(), dilations.data(), - // NOTE(keveman): cuDNN supports convolution and cross correlation. - // However, almost all the use cases do cross correlation, so just - // hard coding it here. - CUDNN_CROSS_CORRELATION, data_type)); + convolution_descriptor.convolution_not_crosscorr() + ? CUDNN_CONVOLUTION + : CUDNN_CROSS_CORRELATION, + data_type)); // NOTE(benbarsdell): This only applies if tensor op math is enabled // and algo selection is set to Default. @@ -861,11 +824,19 @@ cudnnDataType_t ToCudnnDataType( case dnn::DataType::kInt8: return data_layout == dnn::DataLayout::kBatchDepthYX4 ? CUDNN_DATA_INT8x4 : CUDNN_DATA_INT8; + case dnn::DataType::kInt32: + return CUDNN_DATA_INT32; default: LOG(FATAL) << "Invalid DNN data type: " << static_cast(data_type); } } +template +cudnnDataType_t GetCudnnDataType( + dnn::DataLayout data_layout = dnn::DataLayout::kBatchDepthYX) { + return ToCudnnDataType(dnn::ToDataType::value, data_layout); +} + cudnnRNNInputMode_t ToCudnnRnnInputMode(dnn::RnnInputMode input_mode) { switch (input_mode) { case dnn::RnnInputMode::kRnnLinearSkip: @@ -2345,27 +2316,6 @@ struct ConvDoFP32ComputationFP16Input { static constexpr bool kDefaultFlag = true; }; -// A group of helper functions to return the internal compute type for -// convolutions in cudnn. -template -cudnnDataType_t GetConvComputeType() { - return CUDNN_DATA_FLOAT; -} - -template <> -cudnnDataType_t GetConvComputeType() { - if (CudnnEnvVar::IsEnabled()) { - return CUDNN_DATA_FLOAT; - } else { - return CUDNN_DATA_HALF; - } -} - -template <> -cudnnDataType_t GetConvComputeType() { - return CUDNN_DATA_DOUBLE; -} - // A helper struct to decide whether to use FP32 as the internal compute type // for rnn when the input data type is FP16. At present it is turned off, // users can explicitly control them through an env-var @@ -2437,7 +2387,7 @@ port::Status CudnnSupport::DoConvolveImpl( const DeviceMemory& filter_data, const dnn::ConvolutionDescriptor& convolution_descriptor, const dnn::BatchDescriptor& output_descriptor, DeviceMemory* output_data, - ScratchAllocator* scratch_allocator, + dnn::DataType accumulator_type, ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { cudnnDataType_t cudnn_type = GetCudnnDataType(); @@ -2445,7 +2395,7 @@ port::Status CudnnSupport::DoConvolveImpl( CudnnTensorDescriptor output_nd(output_descriptor, cudnn_type); CudnnFilterDescriptor filter(filter_descriptor, cudnn_type); CudnnConvolutionDescriptor conv(convolution_descriptor, - GetConvComputeType()); + ToCudnnDataType(accumulator_type)); auto cudnn = cudnn_->GetHandle(parent_, stream); // Alpha is the scaling factor for input. @@ -2536,8 +2486,7 @@ port::Status CudnnSupport::DoConvolveImpl( return port::Status::OK(); } -template +template port::Status CudnnSupport::DoFusedConvolveImpl( Stream* stream, const dnn::BatchDescriptor& conv_input_descriptor, const DeviceMemory& conv_input_data, @@ -2548,7 +2497,8 @@ port::Status CudnnSupport::DoFusedConvolveImpl( ScaleType side_input_scale, const dnn::BatchDescriptor& bias_descriptor, const DeviceMemory& biases, dnn::ActivationMode activation_mode, const dnn::BatchDescriptor& output_descriptor, - DeviceMemory* output_data, ScratchAllocator* scratch_allocator, + DeviceMemory* output_data, dnn::DataType accumulator_type, + ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { if (activation_mode != dnn::ActivationMode::kRelu && @@ -2569,7 +2519,7 @@ port::Status CudnnSupport::DoFusedConvolveImpl( GetCudnnDataType(conv_input_descriptor.layout())); CudnnTensorDescriptor bias_nd(bias_descriptor, GetCudnnDataType()); CudnnConvolutionDescriptor conv(convolution_descriptor, - GetCudnnDataType()); + ToCudnnDataType(accumulator_type)); auto cudnn = cudnn_->GetHandle(parent_, stream); @@ -2938,10 +2888,10 @@ bool CudnnSupport::DoConvolve( const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { return IsStatusOk( - DoConvolveImpl( - stream, batch_descriptor, input_data, filter_descriptor, filter_data, - convolution_descriptor, output_descriptor, output_data, - scratch_allocator, algorithm_config, output_profile_result), + DoConvolveImpl(stream, batch_descriptor, input_data, filter_descriptor, + filter_data, convolution_descriptor, output_descriptor, + output_data, dnn::DataType::kFloat, scratch_allocator, + algorithm_config, output_profile_result), /*report_error=*/!output_profile_result); } @@ -2956,10 +2906,10 @@ bool CudnnSupport::DoConvolve( const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { return IsStatusOk( - DoConvolveImpl( - stream, batch_descriptor, input_data, filter_descriptor, filter_data, - convolution_descriptor, output_descriptor, output_data, - scratch_allocator, algorithm_config, output_profile_result), + DoConvolveImpl(stream, batch_descriptor, input_data, filter_descriptor, + filter_data, convolution_descriptor, output_descriptor, + output_data, dnn::DataType::kDouble, scratch_allocator, + algorithm_config, output_profile_result), /*report_error=*/!output_profile_result); } @@ -2973,11 +2923,15 @@ bool CudnnSupport::DoConvolve( DeviceMemory* output_data, ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { + dnn::DataType acc_type = + CudnnEnvVar::IsEnabled() + ? dnn::DataType::kFloat + : dnn::DataType::kHalf; return IsStatusOk( - DoConvolveImpl( - stream, batch_descriptor, input_data, filter_descriptor, filter_data, - convolution_descriptor, output_descriptor, output_data, - scratch_allocator, algorithm_config, output_profile_result), + DoConvolveImpl(stream, batch_descriptor, input_data, filter_descriptor, + filter_data, convolution_descriptor, output_descriptor, + output_data, acc_type, scratch_allocator, algorithm_config, + output_profile_result), /*report_error=*/!output_profile_result); } @@ -2995,12 +2949,13 @@ bool CudnnSupport::DoFusedConvolve( const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { return IsStatusOk( - DoFusedConvolveImpl( - stream, conv_input_descriptor, conv_input_data, conv_input_scale, - filter_descriptor, filter_data, convolution_descriptor, - side_input_data, side_input_scale, bias_descriptor, biases, - activation_mode, output_descriptor, output_data, scratch_allocator, - algorithm_config, output_profile_result), + DoFusedConvolveImpl(stream, conv_input_descriptor, conv_input_data, + conv_input_scale, filter_descriptor, filter_data, + convolution_descriptor, side_input_data, + side_input_scale, bias_descriptor, biases, + activation_mode, output_descriptor, output_data, + dnn::DataType::kDouble, scratch_allocator, + algorithm_config, output_profile_result), /*report_error=*/!output_profile_result); } @@ -3018,12 +2973,13 @@ bool CudnnSupport::DoFusedConvolve( const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { return IsStatusOk( - DoFusedConvolveImpl( - stream, conv_input_descriptor, conv_input_data, conv_input_scale, - filter_descriptor, filter_data, convolution_descriptor, - side_input_data, side_input_scale, bias_descriptor, biases, - activation_mode, output_descriptor, output_data, scratch_allocator, - algorithm_config, output_profile_result), + DoFusedConvolveImpl(stream, conv_input_descriptor, conv_input_data, + conv_input_scale, filter_descriptor, filter_data, + convolution_descriptor, side_input_data, + side_input_scale, bias_descriptor, biases, + activation_mode, output_descriptor, output_data, + dnn::DataType::kFloat, scratch_allocator, + algorithm_config, output_profile_result), /*report_error=*/!output_profile_result); } @@ -3041,13 +2997,17 @@ bool CudnnSupport::DoFusedConvolve( DeviceMemory* output_data, ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { + dnn::DataType acc_type = + CudnnEnvVar::IsEnabled() + ? dnn::DataType::kFloat + : dnn::DataType::kHalf; return IsStatusOk( - DoFusedConvolveImpl( + DoFusedConvolveImpl( stream, conv_input_descriptor, conv_input_data, conv_input_scale, filter_descriptor, filter_data, convolution_descriptor, side_input_data, side_input_scale, bias_descriptor, biases, - activation_mode, output_descriptor, output_data, scratch_allocator, - algorithm_config, output_profile_result), + activation_mode, output_descriptor, output_data, acc_type, + scratch_allocator, algorithm_config, output_profile_result), /*report_error=*/!output_profile_result); } @@ -3073,12 +3033,13 @@ bool CudnnSupport::DoFusedConvolve( return false; } return IsStatusOk( - DoFusedConvolveImpl( - stream, conv_input_descriptor, conv_input_data, conv_input_scale, - filter_descriptor, filter_data, convolution_descriptor, - side_input_data, side_input_scale, bias_descriptor, biases, - activation_mode, output_descriptor, output_data, scratch_allocator, - algorithm_config, output_profile_result), + DoFusedConvolveImpl(stream, conv_input_descriptor, conv_input_data, + conv_input_scale, filter_descriptor, filter_data, + convolution_descriptor, side_input_data, + side_input_scale, bias_descriptor, biases, + activation_mode, output_descriptor, output_data, + dnn::DataType::kInt32, scratch_allocator, + algorithm_config, output_profile_result), /*report_error=*/!output_profile_result); } @@ -3112,7 +3073,8 @@ port::Status CudnnSupport::DoConvolveBackwardDataImpl( DeviceMemory backward_output_data, const dnn::ConvolutionDescriptor& convolution_descriptor, const dnn::BatchDescriptor& input_descriptor, - DeviceMemory* backward_input_data, ScratchAllocator* scratch_allocator, + DeviceMemory* backward_input_data, dnn::DataType accumulator_type, + ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { cudnnDataType_t cudnn_type = GetCudnnDataType(); @@ -3133,7 +3095,7 @@ port::Status CudnnSupport::DoConvolveBackwardDataImpl( CudnnTensorDescriptor in_back_nd(input_descriptor, cudnn_type); CudnnFilterDescriptor filter(filter_descriptor, cudnn_type); CudnnConvolutionDescriptor conv(convolution_descriptor, - GetConvComputeType()); + ToCudnnDataType(accumulator_type)); const bool is_profiling = output_profile_result != nullptr; @@ -3213,11 +3175,11 @@ bool CudnnSupport::DoConvolveBackwardData( const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { return IsStatusOk( - DoConvolveBackwardDataImpl(stream, filter_descriptor, filter_data, - output_descriptor, backward_output_data, - convolution_descriptor, input_descriptor, - backward_input_data, scratch_allocator, - algorithm_config, output_profile_result), + DoConvolveBackwardDataImpl( + stream, filter_descriptor, filter_data, output_descriptor, + backward_output_data, convolution_descriptor, input_descriptor, + backward_input_data, dnn::DataType::kDouble, scratch_allocator, + algorithm_config, output_profile_result), /*report_error=*/!output_profile_result); } @@ -3233,11 +3195,11 @@ bool CudnnSupport::DoConvolveBackwardData( const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { return IsStatusOk( - DoConvolveBackwardDataImpl(stream, filter_descriptor, filter_data, - output_descriptor, backward_output_data, - convolution_descriptor, input_descriptor, - backward_input_data, scratch_allocator, - algorithm_config, output_profile_result), + DoConvolveBackwardDataImpl( + stream, filter_descriptor, filter_data, output_descriptor, + backward_output_data, convolution_descriptor, input_descriptor, + backward_input_data, dnn::DataType::kFloat, scratch_allocator, + algorithm_config, output_profile_result), /*report_error=*/!output_profile_result); } @@ -3252,12 +3214,16 @@ bool CudnnSupport::DoConvolveBackwardData( ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { + dnn::DataType acc_type = + CudnnEnvVar::IsEnabled() + ? dnn::DataType::kFloat + : dnn::DataType::kHalf; return IsStatusOk( - DoConvolveBackwardDataImpl(stream, filter_descriptor, filter_data, - output_descriptor, backward_output_data, - convolution_descriptor, input_descriptor, - backward_input_data, scratch_allocator, - algorithm_config, output_profile_result), + DoConvolveBackwardDataImpl( + stream, filter_descriptor, filter_data, output_descriptor, + backward_output_data, convolution_descriptor, input_descriptor, + backward_input_data, acc_type, scratch_allocator, algorithm_config, + output_profile_result), /*report_error=*/!output_profile_result); } @@ -3269,7 +3235,8 @@ port::Status CudnnSupport::DoConvolveBackwardFilterImpl( DeviceMemory backward_output_data, const dnn::ConvolutionDescriptor& convolution_descriptor, const dnn::FilterDescriptor& filter_descriptor, - DeviceMemory* backward_filter_data, ScratchAllocator* scratch_allocator, + DeviceMemory* backward_filter_data, dnn::DataType accumulator_type, + ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { cudnnDataType_t cudnn_type = GetCudnnDataType(); @@ -3290,7 +3257,7 @@ port::Status CudnnSupport::DoConvolveBackwardFilterImpl( CudnnTensorDescriptor input_nd(input_descriptor, cudnn_type); CudnnFilterDescriptor filter(filter_descriptor, cudnn_type); CudnnConvolutionDescriptor conv(convolution_descriptor, - GetConvComputeType()); + ToCudnnDataType(accumulator_type)); const bool is_profiling = output_profile_result != nullptr; @@ -3406,11 +3373,12 @@ bool CudnnSupport::DoConvolveBackwardFilter( const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { return IsStatusOk( - DoConvolveBackwardFilterImpl(stream, input_descriptor, input_data, - output_descriptor, backward_output_data, - convolution_descriptor, filter_descriptor, - backward_filter_data, scratch_allocator, - algorithm_config, output_profile_result), + DoConvolveBackwardFilterImpl( + stream, input_descriptor, input_data, output_descriptor, + backward_output_data, convolution_descriptor, filter_descriptor, + backward_filter_data, dnn::DataType::kDouble, + + scratch_allocator, algorithm_config, output_profile_result), /*report_error=*/!output_profile_result); } @@ -3425,13 +3393,14 @@ bool CudnnSupport::DoConvolveBackwardFilter( ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { - return IsStatusOk( - DoConvolveBackwardFilterImpl(stream, input_descriptor, input_data, - output_descriptor, backward_output_data, - convolution_descriptor, filter_descriptor, - backward_filter_data, scratch_allocator, - algorithm_config, output_profile_result), - /*report_error=*/!output_profile_result); + return IsStatusOk(DoConvolveBackwardFilterImpl( + stream, input_descriptor, input_data, output_descriptor, + backward_output_data, convolution_descriptor, + filter_descriptor, backward_filter_data, + + dnn::DataType::kFloat, scratch_allocator, + algorithm_config, output_profile_result), + /*report_error=*/!output_profile_result); } bool CudnnSupport::DoConvolveBackwardFilter( @@ -3445,12 +3414,16 @@ bool CudnnSupport::DoConvolveBackwardFilter( ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result) { + dnn::DataType acc_type = + CudnnEnvVar::IsEnabled() + ? dnn::DataType::kFloat + : dnn::DataType::kHalf; return IsStatusOk( - DoConvolveBackwardFilterImpl(stream, input_descriptor, input_data, - output_descriptor, backward_output_data, - convolution_descriptor, filter_descriptor, - backward_filter_data, scratch_allocator, - algorithm_config, output_profile_result), + DoConvolveBackwardFilterImpl( + stream, input_descriptor, input_data, output_descriptor, + backward_output_data, convolution_descriptor, filter_descriptor, + backward_filter_data, acc_type, scratch_allocator, algorithm_config, + output_profile_result), /*report_error=*/!output_profile_result); } diff --git a/tensorflow/stream_executor/cuda/cuda_dnn.h b/tensorflow/stream_executor/cuda/cuda_dnn.h index 74f6f935b8..0641be140d 100644 --- a/tensorflow/stream_executor/cuda/cuda_dnn.h +++ b/tensorflow/stream_executor/cuda/cuda_dnn.h @@ -670,12 +670,12 @@ class CudnnSupport : public dnn::DnnSupport { const DeviceMemory& filter_data, const dnn::ConvolutionDescriptor& convolution_descriptor, const dnn::BatchDescriptor& output_descriptor, - DeviceMemory* output_data, ScratchAllocator* scratch_allocator, + DeviceMemory* output_data, dnn::DataType accumulator_type, + ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result); - template + template port::Status DoFusedConvolveImpl( Stream* stream, const dnn::BatchDescriptor& conv_input_descriptor, const DeviceMemory& conv_input_data, @@ -687,7 +687,7 @@ class CudnnSupport : public dnn::DnnSupport { ScaleType side_input_scale, const dnn::BatchDescriptor& bias_descriptor, const DeviceMemory& biases, dnn::ActivationMode activation_mode, const dnn::BatchDescriptor& output_descriptor, - DeviceMemory* output_data, + DeviceMemory* output_data, dnn::DataType accumulator_type, ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result); @@ -700,7 +700,8 @@ class CudnnSupport : public dnn::DnnSupport { DeviceMemory backward_output_data, const dnn::ConvolutionDescriptor& convolution_descriptor, const dnn::BatchDescriptor& input_descriptor, - DeviceMemory* backward_input_data, ScratchAllocator* scratch_allocator, + DeviceMemory* backward_input_data, dnn::DataType accumulator_type, + ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result); @@ -712,7 +713,7 @@ class CudnnSupport : public dnn::DnnSupport { DeviceMemory backward_output_data, const dnn::ConvolutionDescriptor& convolution_descriptor, const dnn::FilterDescriptor& filter_descriptor, - DeviceMemory* backward_filter_data, + DeviceMemory* backward_filter_data, dnn::DataType accumulator_type, ScratchAllocator* scratch_allocator, const dnn::AlgorithmConfig& algorithm_config, dnn::ProfileResult* output_profile_result); diff --git a/tensorflow/stream_executor/cuda/cuda_fft.cc b/tensorflow/stream_executor/cuda/cuda_fft.cc index cbf388a0f8..acac7d6368 100644 --- a/tensorflow/stream_executor/cuda/cuda_fft.cc +++ b/tensorflow/stream_executor/cuda/cuda_fft.cc @@ -23,6 +23,11 @@ limitations under the License. #include "tensorflow/stream_executor/cuda/cuda_platform_id.h" #include "tensorflow/stream_executor/cuda/cuda_stream.h" #include "tensorflow/stream_executor/device_memory.h" + +#ifndef PLATFORM_GOOGLE +#include "tensorflow/stream_executor/dso_loader.h" +#endif + #include "tensorflow/stream_executor/lib/env.h" #include "tensorflow/stream_executor/lib/initialize.h" #include "tensorflow/stream_executor/lib/status.h" @@ -38,6 +43,7 @@ PLUGIN_REGISTRY_DEFINE_PLUGIN_ID(kCuFftPlugin); namespace wrap { +#ifdef PLATFORM_GOOGLE // This macro wraps a global identifier, given by __name, in a callable // structure that loads the DLL symbol out of the DSO handle in a thread-safe // manner on first use. This dynamic loading technique is used to avoid DSO @@ -52,22 +58,69 @@ namespace wrap { } \ } __name; -#define CUFFT_ROUTINE_EACH(__macro) \ - __macro(cufftDestroy) __macro(cufftSetStream) __macro(cufftPlan1d) \ - __macro(cufftPlan2d) __macro(cufftPlan3d) __macro(cufftPlanMany) \ - __macro(cufftExecD2Z) __macro(cufftExecZ2D) __macro(cufftExecC2C) \ - __macro(cufftExecC2R) __macro(cufftExecZ2Z) \ - __macro(cufftExecR2C) __macro(cufftCreate) \ - __macro(cufftSetAutoAllocation) \ - __macro(cufftSetWorkArea) __macro(cufftGetSize1d) \ - __macro(cufftMakePlan1d) __macro(cufftGetSize2d) \ - __macro(cufftMakePlan2d) \ - __macro(cufftGetSize3d) \ - __macro(cufftMakePlan3d) \ - __macro(cufftGetSizeMany) \ - __macro(cufftMakePlanMany) +#else + +#define STREAM_EXECUTOR_CUFFT_WRAP(__name) \ + struct DynLoadShim__##__name { \ + static const char *kName; \ + using FuncPtrT = std::add_pointer::type; \ + static void *GetDsoHandle() { \ + auto s = internal::CachedDsoLoader::GetCufftDsoHandle(); \ + return s.ValueOrDie(); \ + } \ + static FuncPtrT LoadOrDie() { \ + void *f; \ + auto s = port::Env::Default()->GetSymbolFromLibrary(GetDsoHandle(), \ + kName, &f); \ + CHECK(s.ok()) << "could not find " << kName \ + << " in cufft DSO; dlerror: " << s.error_message(); \ + return reinterpret_cast(f); \ + } \ + static FuncPtrT DynLoad() { \ + static FuncPtrT f = LoadOrDie(); \ + return f; \ + } \ + template \ + cufftResult operator()(CUDAExecutor *parent, Args... args) { \ + cuda::ScopedActivateExecutorContext sac{parent}; \ + return DynLoad()(args...); \ + } \ + } __name; \ + const char *DynLoadShim__##__name::kName = #__name; + +#endif + +// clang-format off + +#define CUFFT_ROUTINE_EACH(__macro) \ + __macro(cufftDestroy) \ + __macro(cufftSetStream) \ + __macro(cufftPlan1d) \ + __macro(cufftPlan2d) \ + __macro(cufftPlan3d) \ + __macro(cufftPlanMany) \ + __macro(cufftExecD2Z) \ + __macro(cufftExecZ2D) \ + __macro(cufftExecC2C) \ + __macro(cufftExecC2R) \ + __macro(cufftExecZ2Z) \ + __macro(cufftExecR2C) \ + __macro(cufftCreate) \ + __macro(cufftSetAutoAllocation) \ + __macro(cufftSetWorkArea) \ + __macro(cufftGetSize1d) \ + __macro(cufftMakePlan1d) \ + __macro(cufftGetSize2d) \ + __macro(cufftMakePlan2d) \ + __macro(cufftGetSize3d) \ + __macro(cufftMakePlan3d) \ + __macro(cufftGetSizeMany) \ + __macro(cufftMakePlanMany) + +// clang-format on CUFFT_ROUTINE_EACH(STREAM_EXECUTOR_CUFFT_WRAP) +#undef CUFFT_ROUTINE_EACH } // namespace wrap diff --git a/tensorflow/stream_executor/cuda/cuda_gpu_executor.cc b/tensorflow/stream_executor/cuda/cuda_gpu_executor.cc index ad9154226c..4874d096ad 100644 --- a/tensorflow/stream_executor/cuda/cuda_gpu_executor.cc +++ b/tensorflow/stream_executor/cuda/cuda_gpu_executor.cc @@ -662,8 +662,13 @@ bool CUDAExecutor::MemcpyDeviceToDevice(Stream *stream, } bool CUDAExecutor::HostCallback(Stream *stream, - std::function callback) { - auto callback_ptr = new std::function(callback); + std::function callback) { + auto callback_ptr = new std::function([callback]() { + port::Status s = callback(); + if (!s.ok()) { + LOG(WARNING) << "Host callback failed: " << s; + } + }); return CUDADriver::AddStreamCallback(context_, AsCUDAStreamValue(stream), InternalHostCallback, callback_ptr); } diff --git a/tensorflow/stream_executor/cuda/cuda_gpu_executor.h b/tensorflow/stream_executor/cuda/cuda_gpu_executor.h index 90bf1c0242..ae8e4abf92 100644 --- a/tensorflow/stream_executor/cuda/cuda_gpu_executor.h +++ b/tensorflow/stream_executor/cuda/cuda_gpu_executor.h @@ -148,7 +148,8 @@ class CUDAExecutor : public internal::StreamExecutorInterface { const DeviceMemoryBase &gpu_src, uint64 size) override; - bool HostCallback(Stream *stream, std::function callback) override; + bool HostCallback(Stream *stream, + std::function callback) override; bool AllocateStream(Stream *stream) override; diff --git a/tensorflow/stream_executor/cuda/cuda_rng.cc b/tensorflow/stream_executor/cuda/cuda_rng.cc index 88c4f15792..7f92071932 100644 --- a/tensorflow/stream_executor/cuda/cuda_rng.cc +++ b/tensorflow/stream_executor/cuda/cuda_rng.cc @@ -21,6 +21,11 @@ limitations under the License. #include "tensorflow/stream_executor/cuda/cuda_platform_id.h" #include "tensorflow/stream_executor/cuda/cuda_stream.h" #include "tensorflow/stream_executor/device_memory.h" + +#ifndef PLATFORM_GOOGLE +#include "tensorflow/stream_executor/dso_loader.h" +#endif + #include "tensorflow/stream_executor/lib/env.h" #include "tensorflow/stream_executor/lib/initialize.h" #include "tensorflow/stream_executor/lib/status.h" @@ -61,6 +66,7 @@ PLUGIN_REGISTRY_DEFINE_PLUGIN_ID(kCuRandPlugin); namespace wrap { +#ifdef PLATFORM_GOOGLE #define STREAM_EXECUTOR_CURAND_WRAP(__name) \ struct WrapperShim__##__name { \ template \ @@ -70,6 +76,36 @@ namespace wrap { } \ } __name; +#else +#define STREAM_EXECUTOR_CURAND_WRAP(__name) \ + struct DynLoadShim__##__name { \ + static const char *kName; \ + using FuncPtrT = std::add_pointer::type; \ + static void *GetDsoHandle() { \ + auto s = internal::CachedDsoLoader::GetCurandDsoHandle(); \ + return s.ValueOrDie(); \ + } \ + static FuncPtrT LoadOrDie() { \ + void *f; \ + auto s = port::Env::Default()->GetSymbolFromLibrary(GetDsoHandle(), \ + kName, &f); \ + CHECK(s.ok()) << "could not find " << kName \ + << " in curand DSO; dlerror: " << s.error_message(); \ + return reinterpret_cast(f); \ + } \ + static FuncPtrT DynLoad() { \ + static FuncPtrT f = LoadOrDie(); \ + return f; \ + } \ + template \ + curandStatus_t operator()(CUDAExecutor *parent, Args... args) { \ + cuda::ScopedActivateExecutorContext sac{parent}; \ + return DynLoad()(args...); \ + } \ + } __name; \ + const char *DynLoadShim__##__name::kName = #__name; +#endif + STREAM_EXECUTOR_CURAND_WRAP(curandCreateGenerator); STREAM_EXECUTOR_CURAND_WRAP(curandDestroyGenerator); STREAM_EXECUTOR_CURAND_WRAP(curandSetStream); diff --git a/tensorflow/stream_executor/device_description.cc b/tensorflow/stream_executor/device_description.cc index 4120e230db..0b991b7ba8 100644 --- a/tensorflow/stream_executor/device_description.cc +++ b/tensorflow/stream_executor/device_description.cc @@ -140,21 +140,11 @@ void CalculateDimensionality(const DeviceDescription &device_description, uint64 element_count, uint64 *threads_per_block, uint64 *block_count) { *threads_per_block = device_description.threads_per_block_limit(); - *block_count = DivideCeil(element_count, *threads_per_block); + *block_count = port::MathUtil::CeilOfRatio(element_count, *threads_per_block); if (*block_count == 1) { CHECK_LE(element_count, *threads_per_block); *threads_per_block = element_count; } } -// Round value up to a multiple of n. -static uint64 RoundUp(uint64 value, uint64 n) { - return port::MathUtil::CeilOfRatio(value, n) * n; -} - -// Round value down to a multiple of n. -static uint64 RoundDown(uint64 value, uint64 n) { - return port::MathUtil::FloorOfRatio(value, n) * n; -} - } // namespace stream_executor diff --git a/tensorflow/stream_executor/dnn.cc b/tensorflow/stream_executor/dnn.cc index 3d8e691ab2..faa662211e 100644 --- a/tensorflow/stream_executor/dnn.cc +++ b/tensorflow/stream_executor/dnn.cc @@ -23,7 +23,7 @@ namespace stream_executor { namespace dnn { uint64 AlgorithmDesc::hash() const { - return ::tensorflow::Hash64Combine(algo_, tensor_ops_enabled_); + return ::tensorflow::Hash64Combine(algo_id(), tensor_ops_enabled()); } bool DnnSupport::GetConvolveAlgorithms( @@ -187,6 +187,9 @@ std::tuple GetDimIndices(const DataLayout& layout, batch_idx = 0; spatial_idx = 2; break; + + default: + LOG(FATAL) << "Unknown layout " << layout; } return std::make_tuple(depth_idx, batch_idx, spatial_idx); @@ -233,28 +236,27 @@ string AlgorithmConfig::ToString() const { // -- BatchDescriptor BatchDescriptor::BatchDescriptor(int ndims) - : count_(0), - feature_map_count_(0), - spatial_size_(ndims, 0), - value_max_(0.0), + : value_max_(0.0), value_min_(0.0), - layout_(DataLayout::kYXDepthBatch), - ndims_(ndims), - quantized_activation_mode_(QuantizedActivationMode::k8Bit) {} + quantized_activation_mode_(QuantizedActivationMode::k8Bit) { + tensor_.mutable_dimensions()->Resize(ndims + 2, 0); + set_layout(DataLayout::kYXDepthBatch); +} BatchDescriptor::BatchDescriptor() : BatchDescriptor(/*ndims=*/2) {} std::vector BatchDescriptor::full_dims(const DataLayout& layout) const { - std::vector bdyx_dims(ndims_ + 2); + std::vector bdyx_dims(ndims() + 2); bdyx_dims[0] = count(); bdyx_dims[1] = feature_map_count(); - std::copy(spatial_size_.begin(), spatial_size_.end(), bdyx_dims.begin() + 2); + std::copy(spatial_size().begin(), spatial_size().end(), + bdyx_dims.begin() + 2); return ReorderDims(bdyx_dims, DataLayout::kBatchDepthYX, layout); } std::vector BatchDescriptor::full_strides( const DataLayout& layout) const { - if (layout_ == DataLayout::kBatchDepthYX4) { + if (this->layout() == DataLayout::kBatchDepthYX4) { LOG(FATAL) << "Cannot compute full strides for batch descriptor " << ToString() << ", because its layout is kBatchDepthYX4. In fact, " @@ -262,36 +264,32 @@ std::vector BatchDescriptor::full_strides( "Use cudnnSetTensor4DDescriptor to set cudnnTensorDescriptor_t " "instead."; } - std::vector phys_dims = full_dims(layout_); + std::vector phys_dims = full_dims(this->layout()); std::vector phys_strides(phys_dims.size()); - phys_strides[ndims_ + 1] = 1; - for (int i = ndims_; i >= 0; i--) { + phys_strides[ndims() + 1] = 1; + for (int i = ndims(); i >= 0; i--) { phys_strides[i] = phys_strides[i + 1] * phys_dims[i + 1]; } - return ReorderDims(phys_strides, layout_, layout); + return ReorderDims(phys_strides, this->layout(), layout); } void BatchDescriptor::CloneFrom(const BatchDescriptor& other) { - count_ = other.count_; - feature_map_count_ = other.feature_map_count_; - spatial_size_ = other.spatial_size_; + tensor_ = other.tensor_; value_max_ = other.value_max_; value_min_ = other.value_min_; - layout_ = other.layout_; - ndims_ = other.ndims_; quantized_activation_mode_ = other.quantized_activation_mode_; } string BatchDescriptor::ToString() const { string spatial; - for (int i = 0; i < ndims_; i++) { - port::Appendf(&spatial, "%lld ", spatial_size_[i]); + for (int i = 0; i < ndims(); i++) { + port::Appendf(&spatial, "%lld ", spatial_size()[i]); } return port::Printf( "{count: %lld feature_map_count: %lld spatial: %s " "value_min: %f value_max: %f layout: %s}", - count_, feature_map_count_, spatial.c_str(), value_min_, value_max_, - DataLayoutString(layout_).c_str()); + count(), feature_map_count(), spatial.c_str(), value_min_, value_max_, + DataLayoutString(layout()).c_str()); } string BatchDescriptor::ToShortString() const { @@ -302,8 +300,8 @@ string BatchDescriptor::ToShortString() const { string batch = absl::StrCat("b", count()); string spatial = "s"; - for (int i = 0; i < ndims_; i++) { - port::Appendf(&spatial, "%lld ", spatial_size_[i]); + for (int i = 0; i < ndims(); i++) { + port::Appendf(&spatial, "%lld ", spatial_size()[i]); } string suffix; @@ -333,18 +331,18 @@ string BatchDescriptor::ToShortString() const { int64 BatchDescriptor::NodesPerFeatureMap() const { int64 ret = 1; - for (int i = 0; i < ndims_; i++) { - ret *= spatial_size_[i]; + for (int i = 0; i < ndims(); i++) { + ret *= spatial_size()[i]; } return ret; } int64 BatchDescriptor::NodesAcrossFeatureMaps() const { - return NodesPerFeatureMap() * feature_map_count_; + return NodesPerFeatureMap() * feature_map_count(); } int64 BatchDescriptor::ElementCount() const { - return count_ * feature_map_count_ * NodesPerFeatureMap(); + return count() * feature_map_count() * NodesPerFeatureMap(); } int64 BatchDescriptor::FullyConnectedWeightCount( @@ -372,33 +370,27 @@ BatchDescriptor BatchDescriptor::DepthConcatenateOutputDescriptor( // -- FilterDescriptor -FilterDescriptor::FilterDescriptor(int ndims) - : output_feature_map_count_(0), - input_feature_map_count_(0), - input_filter_dims_(ndims, 0), - ndims_(ndims), - layout_(FilterLayout::kOutputInputYX) {} +FilterDescriptor::FilterDescriptor(int ndims) { + tensor_.mutable_dimensions()->Resize(ndims + 2, 0); + set_layout(FilterLayout::kOutputInputYX); +} FilterDescriptor::FilterDescriptor() : FilterDescriptor(/*ndims=*/2) {} FilterDescriptor::~FilterDescriptor() {} void FilterDescriptor::CloneFrom(const FilterDescriptor& other) { - set_output_feature_map_count(other.output_feature_map_count()) - .set_input_feature_map_count(other.input_feature_map_count()) - .set_layout(other.layout()); - input_filter_dims_ = other.input_filter_dims_; - ndims_ = other.ndims_; + tensor_ = other.tensor_; } string FilterDescriptor::ToString() const { string desc = port::Printf( "{output_feature_map_count: %lld input_feature_map_count: %lld " "layout: %s shape: ", - output_feature_map_count_, input_feature_map_count_, - FilterLayoutString(layout_).c_str()); - for (int i = 0; i < ndims_; i++) { - port::Appendf(&desc, "%lld ", input_filter_dims_[i]); + output_feature_map_count(), input_feature_map_count(), + FilterLayoutString(layout()).c_str()); + for (int i = 0; i < ndims(); i++) { + port::Appendf(&desc, "%lld ", input_filter_dims()[i]); } absl::StrAppend(&desc, "}"); @@ -409,15 +401,15 @@ string FilterDescriptor::ToShortString() const { // All the constituent strings are less than 15 characters, so the // small string optimization ensures that there will be at most one // heap memory allocation. - string od = absl::StrCat("od", output_feature_map_count_); - string id = absl::StrCat("id", input_feature_map_count_); + string od = absl::StrCat("od", output_feature_map_count()); + string id = absl::StrCat("id", input_feature_map_count()); string spatial = "s"; - for (int i = 0; i < ndims_; i++) { - port::Appendf(&spatial, "%lld ", input_filter_dims_[i]); + for (int i = 0; i < ndims(); i++) { + port::Appendf(&spatial, "%lld ", input_filter_dims()[i]); } - switch (layout_) { + switch (layout()) { case FilterLayout::kOutputInputYX: return absl::StrCat(od, id, spatial); case FilterLayout::kOutputYXInput: @@ -429,27 +421,28 @@ string FilterDescriptor::ToShortString() const { case FilterLayout::kYXInputOutput: return absl::StrCat(spatial, id, od); default: - LOG(FATAL) << "Unknown layout " << static_cast(layout_); + LOG(FATAL) << "Unknown layout " << static_cast(layout()); return ""; // Avoid return warning (unreachable) } } int64 FilterDescriptor::ComputeWeightCount() const { - int64 ret = output_feature_map_count_ * input_feature_map_count_; - for (int i = 0; i < ndims_; i++) { - ret *= input_filter_dims_[i]; + int64 ret = output_feature_map_count() * input_feature_map_count(); + for (int i = 0; i < ndims(); i++) { + ret *= input_filter_dims()[i]; } return ret; } // -- ConvolutionDescriptor -ConvolutionDescriptor::ConvolutionDescriptor(int ndims) - : zero_padding_(ndims, 0), - filter_strides_(ndims, 1), - dilation_rates_(ndims, 1), - group_count_(1), - ndims_(ndims) {} +ConvolutionDescriptor::ConvolutionDescriptor(int ndims) { + proto_.mutable_paddings()->Resize(ndims, 0); + proto_.mutable_strides()->Resize(ndims, 1); + proto_.mutable_dilations()->Resize(ndims, 1); + proto_.set_group_count(1); + proto_.set_convolution_mode(ConvolutionMode::CROSS_CORRELATION); +} ConvolutionDescriptor::ConvolutionDescriptor() : ConvolutionDescriptor(/*ndims=*/2) {} @@ -460,10 +453,10 @@ string ConvolutionDescriptor::ToString() const { string padding; string strides; string dilations; - for (int i = 0; i < ndims_; i++) { - port::Appendf(&padding, "%lld ", zero_padding_[i]); - port::Appendf(&strides, "%lld ", filter_strides_[i]); - port::Appendf(&dilations, "%lld ", dilation_rates_[i]); + for (int i = 0; i < ndims(); i++) { + port::Appendf(&padding, "%lld ", this->padding()[i]); + port::Appendf(&strides, "%lld ", this->strides()[i]); + port::Appendf(&dilations, "%lld ", this->dilations()[i]); } return port::Printf( @@ -475,15 +468,15 @@ string ConvolutionDescriptor::ToString() const { string ConvolutionDescriptor::ToShortString() const { string desc; - for (int i = 0; i < ndims_; i++) { + for (int i = 0; i < ndims(); i++) { if (i > 0) port::Appendf(&desc, "_"); - port::Appendf(&desc, "p%d:%lld", i, zero_padding_[i]); + port::Appendf(&desc, "p%d:%lld", i, padding()[i]); } - for (int i = 0; i < ndims_; i++) { - port::Appendf(&desc, "_s%d:%lld", i, filter_strides_[i]); + for (int i = 0; i < ndims(); i++) { + port::Appendf(&desc, "_s%d:%lld", i, strides()[i]); } - for (int i = 0; i < ndims_; i++) { - port::Appendf(&desc, "_d%d:%lld", i, dilation_rates_[i]); + for (int i = 0; i < ndims(); i++) { + port::Appendf(&desc, "_d%d:%lld", i, dilations()[i]); } return desc; } diff --git a/tensorflow/stream_executor/dnn.h b/tensorflow/stream_executor/dnn.h index c934301829..c044a356ef 100644 --- a/tensorflow/stream_executor/dnn.h +++ b/tensorflow/stream_executor/dnn.h @@ -29,7 +29,9 @@ limitations under the License. #include "absl/types/optional.h" #include "absl/types/span.h" +#include "tensorflow/core/platform/protobuf.h" #include "tensorflow/stream_executor/device_memory.h" +#include "tensorflow/stream_executor/dnn.pb.h" #include "tensorflow/stream_executor/lib/array_slice.h" #include "tensorflow/stream_executor/lib/status.h" #include "tensorflow/stream_executor/lib/statusor.h" @@ -48,19 +50,6 @@ class ScratchAllocator; namespace dnn { -// Describes how an input or output layer's data is formatted. -// Specify int64 so there's no padding in BatchDescriptor. -enum class DataLayout : int64 { - kYXDepthBatch = 0, // Same as dist_belief::DF_DEPTH_MAJOR. - kYXBatchDepth, // Same as dist_belief::DF_BATCH_MAJOR. - kBatchYXDepth, // Same as run_brain output, and tensorflow's layout. - kBatchDepthYX, // cuDNN's NCHW layout, data laid out as image, feature - // maps, rows, columns. - kBatchDepthYX4, // cuDNN's NCHW_VECT_C layout, data laid out the same as - // kBatchDepthYX but each element is a vector of 4 feature - // maps. -}; - // Specifies an index to use when accessing specific spatial dimensions. enum class DimIndex : int { X = 0, @@ -73,8 +62,27 @@ inline int64 GetDim(absl::Span data, DimIndex dim) { return data.rbegin()[static_cast(dim)]; } +inline void SetDim(absl::Span data, DimIndex dim, int64 value) { + data.rbegin()[static_cast(dim)] = value; +} + inline void SetDim(std::vector* data, DimIndex dim, int64 value) { - data->rbegin()[static_cast(dim)] = value; + return SetDim(absl::MakeSpan(*data), dim, value); +} + +// tensorflow::int64 is not the same type as tensorflow::protobuf_int64 in +// open-source. Wrapper function that gives an int64 array slice view of a +// repeated int64 protobuf field. +inline absl::Span AsInt64Slice( + const tensorflow::protobuf::RepeatedField& v) { + return absl::Span(reinterpret_cast(v.data()), + v.size()); +} + +inline absl::Span AsInt64Slice( + tensorflow::protobuf::RepeatedField* v) { + return absl::Span(reinterpret_cast(v->mutable_data()), + v->size()); } // Returns a string representation of the given data layout. @@ -87,14 +95,6 @@ enum class QuantizedActivationMode { k32Bit = 4, }; -// Specifies the data type used by an operation. -enum class DataType { - kFloat = 0, - kDouble = 1, - kHalf = 2, - kInt8 = 3, -}; - // A helper class to convert C/C++ types to the proper enums. template struct ToDataType; @@ -114,6 +114,10 @@ template <> struct ToDataType { static constexpr DataType value = DataType::kInt8; }; +template <> +struct ToDataType { + static constexpr DataType value = DataType::kInt32; +}; // Specifies the types of a RNN model. enum class RnnMode { @@ -245,15 +249,15 @@ class BatchDescriptor { string ToShortString() const; // Accessors. - int64 count() const { return count_; } - int64 feature_map_count() const { return feature_map_count_; } - int64 height() const { return GetDim(spatial_size_, DimIndex::Y); } - int64 width() const { return GetDim(spatial_size_, DimIndex::X); } - int64 spatial_dim(DimIndex dim) const { return GetDim(spatial_size_, dim); } - int ndims() const { return ndims_; } + int64 count() const { return tensor_.dimensions(0); } + int64 feature_map_count() const { return tensor_.dimensions(1); } + int64 height() const { return GetDim(spatial_size(), DimIndex::Y); } + int64 width() const { return GetDim(spatial_size(), DimIndex::X); } + int64 spatial_dim(DimIndex dim) const { return GetDim(spatial_size(), dim); } + int ndims() const { return spatial_size().size(); } float value_max() const { return value_max_; } float value_min() const { return value_min_; } - DataLayout layout() const { return layout_; } + DataLayout layout() const { return tensor_.data_layout(); } QuantizedActivationMode quantized_activation_mode() const { return quantized_activation_mode_; } @@ -267,23 +271,23 @@ class BatchDescriptor { // Named-argument helpers for avoiding user error during construction. BatchDescriptor& set_count(int64 value) { - count_ = value; + tensor_.set_dimensions(0, value); return *this; } BatchDescriptor& set_feature_map_count(int64 value) { - feature_map_count_ = value; + tensor_.set_dimensions(1, value); return *this; } BatchDescriptor& set_height(int64 value) { - SetDim(&spatial_size_, DimIndex::Y, value); + SetDim(spatial_size(), DimIndex::Y, value); return *this; } BatchDescriptor& set_width(int64 value) { - SetDim(&spatial_size_, DimIndex::X, value); + SetDim(spatial_size(), DimIndex::X, value); return *this; } BatchDescriptor& set_spatial_dim(DimIndex dim, int64 value) { - SetDim(&spatial_size_, dim, value); + SetDim(spatial_size(), dim, value); return *this; } BatchDescriptor& set_value_max(float value) { @@ -295,7 +299,7 @@ class BatchDescriptor { return *this; } BatchDescriptor& set_layout(DataLayout layout) { - layout_ = layout; + tensor_.set_data_layout(layout); return *this; } BatchDescriptor& set_quantized_activation_mode( @@ -334,31 +338,20 @@ class BatchDescriptor { port::ArraySlice inputs); private: - int64 count_; - int64 feature_map_count_; - // Stored as: ..., y, x. - std::vector spatial_size_; + absl::Span spatial_size() const { + return AsInt64Slice(tensor_.dimensions()).subspan(2); + } + + absl::Span spatial_size() { + return AsInt64Slice(tensor_.mutable_dimensions()).subspan(2); + } + + TensorDescriptorProto tensor_; float value_max_; float value_min_; - DataLayout layout_; - int ndims_; QuantizedActivationMode quantized_activation_mode_; }; -// Describes how a filter is laid out in the memory. -// Specify int64 so there's no padding in FilterDescriptor. -enum class FilterLayout : int64 { - kOutputInputYX = 0, // cuDNN's default filter layout, laid out as: - // (major) output feature maps >> input feature maps >> - // rows >> columns (minor). - kOutputYXInput, // major to minor: - // (output features, row, columns, input features) - kOutputInputYX4, // laid out the same as kOutputInputYX but each element is a - // vector of 4 feature maps. - kInputYXOutput, // Same as dist_belief's default filter layout. - kYXInputOutput, // Same as tensorflow's default filter layout. -}; - // Returns a string representation of the given filter layout. string FilterLayoutString(FilterLayout layout); @@ -398,30 +391,30 @@ class FilterDescriptor { // Named-argument helpers for avoiding user error during construction. FilterDescriptor& set_output_feature_map_count(int64 value) { - output_feature_map_count_ = value; + tensor_.set_dimensions(0, value); return *this; } FilterDescriptor& set_input_feature_map_count(int64 value) { - input_feature_map_count_ = value; + tensor_.set_dimensions(1, value); return *this; } FilterDescriptor& set_input_filter_height(int64 value) { - SetDim(&input_filter_dims_, DimIndex::Y, value); + SetDim(input_filter_dims(), DimIndex::Y, value); return *this; } FilterDescriptor& set_input_filter_width(int64 value) { - SetDim(&input_filter_dims_, DimIndex::X, value); + SetDim(input_filter_dims(), DimIndex::X, value); return *this; } FilterDescriptor& set_layout(FilterLayout layout) { - layout_ = layout; + tensor_.set_filter_layout(layout); return *this; } FilterDescriptor& set_spatial_dim(DimIndex dim, int64 value) { - SetDim(&input_filter_dims_, dim, value); + SetDim(input_filter_dims(), dim, value); return *this; } - int ndims() const { return ndims_; } + int ndims() const { return input_filter_dims().size(); } void CloneFrom(const FilterDescriptor& other); @@ -434,32 +427,32 @@ class FilterDescriptor { // Returns the number of biases required as parameters for a convolution // using this filter descriptor. - int64 bias_count() const { return output_feature_map_count_; } + int64 bias_count() const { return output_feature_map_count(); } - int64 output_feature_map_count() const { return output_feature_map_count_; } - int64 input_feature_map_count() const { return input_feature_map_count_; } + int64 output_feature_map_count() const { return tensor_.dimensions(0); } + int64 input_feature_map_count() const { return tensor_.dimensions(1); } int64 input_filter_height() const { - return GetDim(input_filter_dims_, DimIndex::Y); + return GetDim(input_filter_dims(), DimIndex::Y); } int64 input_filter_width() const { - return GetDim(input_filter_dims_, DimIndex::X); + return GetDim(input_filter_dims(), DimIndex::X); } int64 input_filter_dim(DimIndex dim) const { - return GetDim(input_filter_dims_, dim); + return GetDim(input_filter_dims(), dim); } - FilterLayout layout() const { return layout_; } + FilterLayout layout() const { return tensor_.filter_layout(); } + absl::Span input_filter_dims() const { - return input_filter_dims_; + return AsInt64Slice(tensor_.dimensions()).subspan(2); } private: - int64 output_feature_map_count_; - int64 input_feature_map_count_; - // Stored as: ..., y, x. - std::vector input_filter_dims_; - int ndims_; - FilterLayout layout_; + absl::Span input_filter_dims() { + return AsInt64Slice(tensor_.mutable_dimensions()).subspan(2); + } + + TensorDescriptorProto tensor_; }; // Describes how padding should be aligned when the total number of pad @@ -500,6 +493,11 @@ std::ostream& operator<<(std::ostream& str, dnn::PadAlignment alignment); // cells between each filter element in the "y dimension". // - horizontal_dilation_rate: there will be (horizontal_dilation_rate - 1) // skipped cells between each filter element in the "x dimension". +// - convolution_not_crosscor: By default (convolution_not_crosscor == false), +// we perform cross correlation rather than convolution. With the flag set, +// we perform convolution. Convolution and cross correlation are related by +// rotating the filter by 180 degrees (or equivalently flipping all spatial +// dimensions). class ConvolutionDescriptor { public: // By default construction, there is no zero-padding and the filter stride is @@ -513,84 +511,102 @@ class ConvolutionDescriptor { string ToShortString() const; ConvolutionDescriptor& set_zero_padding_height(int64 value) { - SetDim(&zero_padding_, DimIndex::Y, value); + SetDim(padding(), DimIndex::Y, value); return *this; } ConvolutionDescriptor& set_zero_padding_width(int64 value) { - SetDim(&zero_padding_, DimIndex::X, value); + SetDim(padding(), DimIndex::X, value); return *this; } ConvolutionDescriptor& set_zero_padding(DimIndex dim, int64 value) { - SetDim(&zero_padding_, dim, value); + SetDim(padding(), dim, value); return *this; } ConvolutionDescriptor& set_vertical_filter_stride(int64 value) { - SetDim(&filter_strides_, DimIndex::Y, value); + SetDim(strides(), DimIndex::Y, value); return *this; } ConvolutionDescriptor& set_horizontal_filter_stride(int64 value) { - SetDim(&filter_strides_, DimIndex::X, value); + SetDim(strides(), DimIndex::X, value); return *this; } ConvolutionDescriptor& set_filter_stride(DimIndex dim, int64 value) { - SetDim(&filter_strides_, dim, value); + SetDim(strides(), dim, value); return *this; } ConvolutionDescriptor& set_vertical_dilation_rate(int64 value) { - SetDim(&dilation_rates_, DimIndex::Y, value); + SetDim(dilations(), DimIndex::Y, value); return *this; } ConvolutionDescriptor& set_horizontal_dilation_rate(int64 value) { - SetDim(&dilation_rates_, DimIndex::X, value); + SetDim(dilations(), DimIndex::X, value); return *this; } ConvolutionDescriptor& set_dilation_rate(DimIndex dim, int64 value) { - SetDim(&dilation_rates_, dim, value); + SetDim(dilations(), dim, value); return *this; } ConvolutionDescriptor& set_group_count(int group_count) { - group_count_ = group_count; + proto_.set_group_count(group_count); return *this; } - int64 zero_padding_height() const { - return GetDim(zero_padding_, DimIndex::Y); - } - int64 zero_padding_width() const { - return GetDim(zero_padding_, DimIndex::X); + ConvolutionDescriptor& set_convolution_not_crosscorr(bool conv) { + proto_.set_convolution_mode(conv ? ConvolutionMode::CONVOLUTION + : ConvolutionMode::CROSS_CORRELATION); + return *this; } + int64 zero_padding_height() const { return GetDim(padding(), DimIndex::Y); } + int64 zero_padding_width() const { return GetDim(padding(), DimIndex::X); } int64 vertical_filter_stride() const { - return GetDim(filter_strides_, DimIndex::Y); + return GetDim(strides(), DimIndex::Y); } int64 horizontal_filter_stride() const { - return GetDim(filter_strides_, DimIndex::X); + return GetDim(strides(), DimIndex::X); } int64 vertical_dilation_rate() const { - return GetDim(dilation_rates_, DimIndex::Y); + return GetDim(dilations(), DimIndex::Y); } int64 horizontal_dilation_rate() const { - return GetDim(dilation_rates_, DimIndex::X); + return GetDim(dilations(), DimIndex::X); } - int zero_padding(DimIndex dim) const { return GetDim(zero_padding_, dim); } - int filter_stride(DimIndex dim) const { return GetDim(filter_strides_, dim); } - int dilation_rate(DimIndex dim) const { return GetDim(dilation_rates_, dim); } + int zero_padding(DimIndex dim) const { return GetDim(padding(), dim); } + int filter_stride(DimIndex dim) const { return GetDim(strides(), dim); } + int dilation_rate(DimIndex dim) const { return GetDim(dilations(), dim); } // TODO(timshen): remove this function. No users of this class is setting a // non-default pad alignment. PadAlignment pad_alignment() const { return PadAlignment::kDefault; } - int group_count() const { return group_count_; } - int ndims() const { return ndims_; } + int group_count() const { return proto_.group_count(); } + int ndims() const { return padding().size(); } + bool convolution_not_crosscorr() const { + return proto_.convolution_mode() == ConvolutionMode::CONVOLUTION; + } + + absl::Span strides() const { + return AsInt64Slice(proto_.strides()); + } - absl::Span strides() const { return filter_strides_; } - absl::Span dilations() const { return dilation_rates_; } - absl::Span padding() const { return zero_padding_; } + absl::Span dilations() const { + return AsInt64Slice(proto_.dilations()); + } + + absl::Span padding() const { + return AsInt64Slice(proto_.paddings()); + } private: - // Stored as: .. y, x. - std::vector zero_padding_; - std::vector filter_strides_; - std::vector dilation_rates_; - int group_count_; - int ndims_; + absl::Span strides() { return AsInt64Slice(proto_.mutable_strides()); } + + absl::Span dilations() { + return AsInt64Slice(proto_.mutable_dilations()); + } + + absl::Span padding() { + return AsInt64Slice(proto_.mutable_paddings()); + } + + ConvolutionDescriptorProto proto_; + // TODO(leary) cudnn provides these fields, but need to characterize what // their effect is -- they may be boolean rather than integral. // int64 upscale_input_x; @@ -714,21 +730,23 @@ class PoolingDescriptor { class AlgorithmDesc { public: typedef int64 Index; - AlgorithmDesc(Index a, bool use_tensor_ops) - : algo_(a), tensor_ops_enabled_(use_tensor_ops) { - DCHECK_NE(a, -1); + AlgorithmDesc(Index a, bool use_tensor_ops) { + proto_.set_algo_id(a); + proto_.set_math_type(use_tensor_ops ? AlgorithmProto::TENSOR_OP_MATH + : AlgorithmProto::DEFAULT_MATH); + } + bool tensor_ops_enabled() const { + return proto_.math_type() == AlgorithmProto::TENSOR_OP_MATH; } - bool tensor_ops_enabled() const { return tensor_ops_enabled_; } - Index algo_id() const { return algo_; } + Index algo_id() const { return proto_.algo_id(); } bool operator==(const AlgorithmDesc& other) const { - return this->algo_ == other.algo_ && - this->tensor_ops_enabled_ == other.tensor_ops_enabled_; + return algo_id() == other.algo_id() && + tensor_ops_enabled() == other.tensor_ops_enabled(); } uint64 hash() const; private: - Index algo_; - bool tensor_ops_enabled_; + AlgorithmProto proto_; }; // Describes the result from a perf experiment. @@ -872,24 +890,6 @@ class NormalizeDescriptor { int32 segment_size_; }; -// Describes a kind of non-linearity (threshold-like mathematical function). -enum class ActivationMode { - kNone = 0, - kSigmoid, - // Rectified linear activation: f(x) = x < 0 ? 0 : x - kRelu, - // Rectified linear activation, where upper maximum is 6.0. - kRelu6, - // Rectified linear activation, where upper maximum specified by - // BatchDescriptor::value_max(). - kReluX, - kTanh, - // Like ReluX, but passes all values in the range [-X,X]. - kBandPass, - - kNumActivationModes, // Always in the end. -}; - // Returns a string representation of the given activation mode. string ActivationModeString(ActivationMode mode); diff --git a/tensorflow/stream_executor/dnn.proto b/tensorflow/stream_executor/dnn.proto new file mode 100644 index 0000000000..56b079c3f5 --- /dev/null +++ b/tensorflow/stream_executor/dnn.proto @@ -0,0 +1,103 @@ +// LINT: LEGACY_NAMES +syntax = "proto3"; + +package stream_executor.dnn; + +// Specifies the data type used by an operation. +enum DataType { + kFloat = 0; + kDouble = 1; + kHalf = 2; + kInt8 = 3; + kInt32 = 4; +} + +// Describes how a convolution input or output layer's data is formatted. +enum DataLayout { + // Naming convention: + // Y <-> row or height + // X <-> column or width + // Batch <-> batch, or N + // Depth <-> feature, or channel + // TODO(timshen): turn them into cuDNN names, e.g. kNCHW. + kYXDepthBatch = 0; + kYXBatchDepth = 1; + kBatchYXDepth = 2; // cuDNN's NHWC layout + kBatchDepthYX = 3; // cuDNN's NCHW layout + kBatchDepthYX4 = 4; // cuDNN's NCHW_VECT_C layout +} + +// Describes how a convolution filter is laid out in the memory. +enum FilterLayout { + // Naming convention: + // Y <-> row or height + // X <-> column or width + // Output <-> output feature, or N + // Input <-> input feature, or N + // TODO(timshen): turn them into cuDNN names, e.g. kNCHW. + kOutputInputYX = 0; // cuDNN's NCHW layout + kOutputYXInput = 1; // cuDNN's NHWC layout + kOutputInputYX4 = 2; // cuDNN's NCHW_VECT_C layout + kInputYXOutput = 3; + kYXInputOutput = 4; +} + +// Describes a kind of non-linearity (threshold-like mathematical function). +enum ActivationMode { + kNone = 0; + kSigmoid = 1; + // Rectified linear activation: f(x) = x < 0 ? 0 : x + kRelu = 2; + // Rectified linear activation; where upper maximum is 6.0. + kRelu6 = 3; + // Rectified linear activation; where upper maximum specified by + // BatchDescriptor::value_max(). + kReluX = 4; + kTanh = 5; + // Like ReluX; but passes all values in the range [-X,X]. + kBandPass = 6; +} + +// Describe the math definition for the conv op. The popular behavior is +// actually called cross-correlation in math, despite the operation is often +// referred as convolution. See cuDNN cudnnConvolutionMode_t. +enum ConvolutionMode { + CROSS_CORRELATION = 0; + CONVOLUTION = 1; +} + +// Generic tensor representation. +message TensorDescriptorProto { + repeated int64 dimensions = 1; + DataType data_type = 2; + oneof layout_oneof { + DataLayout data_layout = 3; + FilterLayout filter_layout = 4; + } +} + +// Generic algorithm representation. +message AlgorithmProto { + enum MathType { + DEFAULT_MATH = 0; + // The GPU may operate 4x4 matrix FMA. + // See cuDNN's documentation for CUDNN_TENSOR_OP_MATH. + TENSOR_OP_MATH = 1; + } + int64 algo_id = 1; + MathType math_type = 2; +} + +// Convolution-specific parameters. +message ConvolutionDescriptorProto { + repeated int64 paddings = 1; + repeated int64 strides = 2; + repeated int64 dilations = 3; + // The "accumulator" type. For example, use F32 as an accumulator for F16 + // convolutions. + // See cuDNN's cudnnConvolutionMode_t. + DataType compute_mode = 4; + // See cuDNN's group count. + int32 group_count = 5; + ConvolutionMode convolution_mode = 6; +} diff --git a/tensorflow/stream_executor/host/host_gpu_executor.cc b/tensorflow/stream_executor/host/host_gpu_executor.cc index 8adf739b17..1396a83dfb 100644 --- a/tensorflow/stream_executor/host/host_gpu_executor.cc +++ b/tensorflow/stream_executor/host/host_gpu_executor.cc @@ -148,8 +148,13 @@ port::Status HostExecutor::SynchronousMemcpyDeviceToDevice( } bool HostExecutor::HostCallback(Stream *stream, - std::function callback) { - AsHostStream(stream)->EnqueueTask(callback); + std::function callback) { + AsHostStream(stream)->EnqueueTask([callback]() { + port::Status s = callback(); + if (!s.ok()) { + LOG(WARNING) << "Host callback failed: " << s; + } + }); return true; } diff --git a/tensorflow/stream_executor/host/host_gpu_executor.h b/tensorflow/stream_executor/host/host_gpu_executor.h index 7ba1f18101..56e3c2aa6a 100644 --- a/tensorflow/stream_executor/host/host_gpu_executor.h +++ b/tensorflow/stream_executor/host/host_gpu_executor.h @@ -103,7 +103,8 @@ class HostExecutor : public internal::StreamExecutorInterface { const DeviceMemoryBase &gpu_src, uint64 size) override; - bool HostCallback(Stream *stream, std::function callback) override; + bool HostCallback(Stream *stream, + std::function callback) override; port::Status AllocateEvent(Event *event) override { return port::Status(port::error::UNIMPLEMENTED, ""); diff --git a/tensorflow/stream_executor/stream.cc b/tensorflow/stream_executor/stream.cc index 5421e4f4a5..3edc66cde8 100644 --- a/tensorflow/stream_executor/stream.cc +++ b/tensorflow/stream_executor/stream.cc @@ -191,8 +191,11 @@ string ToVlogString(dnn::DataType data_type) { return "dnn::DataType::kHalf"; case dnn::DataType::kInt8: return "dnn::DataType::kInt8"; + case dnn::DataType::kInt32: + return "dnn::DataType::kInt32"; + default: + return "unknown DataType"; } - return "unknown DataType"; } // Used together with PARAM to VLOG calls made to the stream. Intended diff --git a/tensorflow/stream_executor/stream.h b/tensorflow/stream_executor/stream.h index e1629b5b30..0fc90cf83d 100644 --- a/tensorflow/stream_executor/stream.h +++ b/tensorflow/stream_executor/stream.h @@ -2033,9 +2033,20 @@ class Stream { // transferred to the caller. internal::StreamInterface *implementation() { return implementation_.get(); } + // Entrains onto the stream a callback to the host (from the device). + // Behaves as ThenDoHostCallbackWithStatus below, but the callback should + // never fail or its failure is inconsequential. + // + // This is kept for backward compatibility. Future code should use + // ThenDoHostCallbackWithStatus and explicitly return a success status. + // TODO(b/112125301): Eventually remove this method. + Stream &ThenDoHostCallback(std::function callback); + // Entrains onto the stream a callback to the host (from the device). // Host callbacks block/occupy the stream just as device functions // (execute one at a time, block later stream operations). + // Whether the callback return status affects the result of BlockHostUntilDone + // is platform-dependent. // // Behavior is undefined when synchronizing using OpenCL user events. // Behavior is undefined if host callbacks call device routines or insert @@ -2043,11 +2054,6 @@ class Stream { // // On certain platforms, ThenDoHostCallback is expected to have significant // negative effects on performance. - Stream &ThenDoHostCallback(std::function callback); - - // Entrains onto the stream a callback to the host (from the device). - // Behaves as ThenDoHostCallback above, but returns a Status instead of void. - // This overload should be preferred if the callback could fail. Stream &ThenDoHostCallbackWithStatus(std::function callback); // Returns the StreamExecutor (parent object) associated with this stream. diff --git a/tensorflow/stream_executor/stream_executor_internal.cc b/tensorflow/stream_executor/stream_executor_internal.cc index 7df6a361c6..341c6edccd 100644 --- a/tensorflow/stream_executor/stream_executor_internal.cc +++ b/tensorflow/stream_executor/stream_executor_internal.cc @@ -36,16 +36,15 @@ StreamExecutorFactory* MakeOpenCLExecutorImplementation() { StreamExecutorFactory MakeHostExecutorImplementation; -// TODO(b/112125301): Consolodate this down to one implementation of -// HostCallback, taking a callback that returns a Status. -bool StreamExecutorInterface::HostCallback( - Stream* stream, std::function callback) { - return HostCallback(stream, [callback]() { - port::Status s = callback(); - if (!s.ok()) { - LOG(WARNING) << "HostCallback failed: " << s; - } - }); +// The default implementation just calls the other HostCallback method. +// It should make all existing code that uses a void() callback still work. +bool StreamExecutorInterface::HostCallback(Stream* stream, + std::function callback) { + return HostCallback( + stream, std::function([callback]() -> port::Status { + callback(); + return port::Status::OK(); + })); } } // namespace internal diff --git a/tensorflow/stream_executor/stream_executor_internal.h b/tensorflow/stream_executor/stream_executor_internal.h index 32f75fd1bc..0c2c33cfca 100644 --- a/tensorflow/stream_executor/stream_executor_internal.h +++ b/tensorflow/stream_executor/stream_executor_internal.h @@ -237,9 +237,9 @@ class StreamExecutorInterface { virtual bool MemcpyDeviceToDevice(Stream *stream, DeviceMemoryBase *gpu_dst, const DeviceMemoryBase &gpu_src, uint64 size) = 0; - virtual bool HostCallback(Stream *stream, std::function callback) = 0; + virtual bool HostCallback(Stream *stream, std::function callback); virtual bool HostCallback(Stream *stream, - std::function callback); + std::function callback) = 0; virtual port::Status AllocateEvent(Event *event) = 0; virtual port::Status DeallocateEvent(Event *event) = 0; virtual port::Status RecordEvent(Stream *stream, Event *event) = 0; diff --git a/tensorflow/tensorflow.bzl b/tensorflow/tensorflow.bzl index 8e5ab94b53..ed1de5a31c 100644 --- a/tensorflow/tensorflow.bzl +++ b/tensorflow/tensorflow.bzl @@ -203,8 +203,12 @@ def if_override_eigen_strong_inline(a): "//conditions:default": [], }) -def if_not_tx2_llvm_or_windows_cuda(a): - return if_not_windows_cuda(a) +def if_nccl(a): + return select({ + "//tensorflow:no_nccl_support": [], + "//tensorflow:windows": [], + "//conditions:default": a, + }) def get_win_copts(is_external = False): WINDOWS_COPTS = [ @@ -1307,13 +1311,13 @@ def _py_wrap_cc_impl(ctx): ctx.outputs.py_out.dirname, ] args += ["-l" + f.path for f in ctx.files.swig_includes] - args += ["-I" + i for i in swig_include_dirs] + args += ["-I" + i for i in swig_include_dirs.to_list()] args += [src.path] outputs = [ctx.outputs.cc_out, ctx.outputs.py_out] ctx.action( executable = ctx.executable._swig, arguments = args, - inputs = list(inputs), + inputs = inputs.to_list(), outputs = outputs, mnemonic = "PythonSwig", progress_message = "SWIGing " + src.path, @@ -1493,7 +1497,7 @@ check_deps = rule( }, ) -def tf_custom_op_library(name, srcs = [], gpu_srcs = [], deps = [], linkopts = [], **kwargs): +def tf_custom_op_library(name, srcs = [], gpu_srcs = [], deps = [], linkopts = [], copts = [], **kwargs): """Helper to build a dynamic library (.so) from the sources containing implementations of custom ops and kernels. """ cuda_deps = [ @@ -1505,12 +1509,18 @@ def tf_custom_op_library(name, srcs = [], gpu_srcs = [], deps = [], linkopts = [ clean_dep("//tensorflow/core:stream_executor_headers_lib"), ] deps = deps + tf_custom_op_library_additional_deps() + + # Override EIGEN_STRONG_INLINE to inline when + # --define=override_eigen_strong_inline=true to avoid long compiling time. + # See https://github.com/tensorflow/tensorflow/issues/10521 + copts = copts + if_override_eigen_strong_inline(["/DEIGEN_STRONG_INLINE=inline"]) + if gpu_srcs: basename = name.split(".")[0] native.cc_library( name = basename + "_gpu", srcs = gpu_srcs, - copts = _cuda_copts() + if_tensorrt(["-DGOOGLE_TENSORRT=1"]), + copts = copts + _cuda_copts() + if_tensorrt(["-DGOOGLE_TENSORRT=1"]), features = if_cuda(["-use_header_modules"]), deps = deps + if_cuda_is_configured_compat(cuda_deps) + if_rocm_is_configured(rocm_deps), **kwargs @@ -1531,7 +1541,7 @@ def tf_custom_op_library(name, srcs = [], gpu_srcs = [], deps = [], linkopts = [ srcs = srcs, deps = deps + if_cuda_is_configured_compat(cuda_deps) + if_rocm_is_configured(rocm_deps), data = if_static([name + "_check_deps"]), - copts = tf_copts(is_external = True), + copts = copts + tf_copts(is_external = True), features = ["windows_export_all_symbols"], linkopts = linkopts + select({ "//conditions:default": [ @@ -2022,3 +2032,6 @@ register_extension_info( extension_name = "cc_library_with_android_deps", label_regex_for_dep = "{extension_name}", ) + +def tensorflow_opensource_extra_deps(): + return [] diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.-experimental.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.-experimental.pbtxt index f7491649c2..a1083d732a 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.-experimental.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.-experimental.pbtxt @@ -20,7 +20,13 @@ tf_proto { label: LABEL_OPTIONAL type: TYPE_INT32 } - reserved_range { + field { + name: "use_numa_affinity" + number: 5 + label: LABEL_OPTIONAL + type: TYPE_BOOL + } + reserved_range { start: 2 end: 3 } diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.pbtxt index 53b532beab..b505d81350 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.pbtxt @@ -143,6 +143,12 @@ tf_proto { label: LABEL_OPTIONAL type: TYPE_INT32 } + field { + name: "use_numa_affinity" + number: 5 + label: LABEL_OPTIONAL + type: TYPE_BOOL + } reserved_range { start: 2 end: 3 diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-gradient-tape.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-gradient-tape.pbtxt index 0a16d6ab92..2299a009d3 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.-gradient-tape.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.-gradient-tape.pbtxt @@ -6,10 +6,18 @@ tf_class { name: "__init__" argspec: "args=[\'self\', \'persistent\', \'watch_accessed_variables\'], varargs=None, keywords=None, defaults=[\'False\', \'True\'], " } + member_method { + name: "batch_jacobian" + argspec: "args=[\'self\', \'target\', \'source\', \'unconnected_gradients\', \'parallel_iterations\', \'experimental_use_pfor\'], varargs=None, keywords=None, defaults=[\'UnconnectedGradients.NONE\', \'None\', \'True\'], " + } member_method { name: "gradient" argspec: "args=[\'self\', \'target\', \'sources\', \'output_gradients\', \'unconnected_gradients\'], varargs=None, keywords=None, defaults=[\'None\', \'UnconnectedGradients.NONE\'], " } + member_method { + name: "jacobian" + argspec: "args=[\'self\', \'target\', \'sources\', \'unconnected_gradients\', \'parallel_iterations\', \'experimental_use_pfor\'], varargs=None, keywords=None, defaults=[\'UnconnectedGradients.NONE\', \'None\', \'True\'], " + } member_method { name: "reset" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-tensor-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-tensor-spec.pbtxt new file mode 100644 index 0000000000..493dcba892 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.-tensor-spec.pbtxt @@ -0,0 +1,33 @@ +path: "tensorflow.TensorSpec" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "dtype" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "shape" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'shape\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "from_spec" + argspec: "args=[\'cls\', \'spec\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "from_tensor" + argspec: "args=[\'cls\', \'tensor\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_compatible_with" + argspec: "args=[\'self\', \'spec_or_tensor\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.-dataset.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.-dataset.pbtxt index 8b7f63e43e..f59082baeb 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.-dataset.pbtxt @@ -1,6 +1,7 @@ path: "tensorflow.data.Dataset" tf_class { - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.-fixed-length-record-dataset.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.-fixed-length-record-dataset.pbtxt index 81358cecbc..d73168b070 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.-fixed-length-record-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.-fixed-length-record-dataset.pbtxt @@ -1,8 +1,9 @@ path: "tensorflow.data.FixedLengthRecordDataset" tf_class { - is_instance: "" - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.-options.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.-options.pbtxt index 9d032d43de..72fc2c3a9e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.-options.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.-options.pbtxt @@ -1,6 +1,7 @@ path: "tensorflow.data.Options" tf_class { is_instance: "" + is_instance: "" is_instance: "" member { name: "experimental_autotune" @@ -11,47 +12,19 @@ tf_class { mtype: "" } member { - name: "experimental_filter_fusion" - mtype: "" - } - member { - name: "experimental_hoist_random_uniform" - mtype: "" - } - member { - name: "experimental_map_and_batch_fusion" - mtype: "" - } - member { - name: "experimental_map_and_filter_fusion" - mtype: "" - } - member { - name: "experimental_map_fusion" - mtype: "" - } - member { - name: "experimental_map_parallelization" - mtype: "" - } - member { - name: "experimental_map_vectorization" - mtype: "" - } - member { - name: "experimental_noop_elimination" + name: "experimental_numa_aware" mtype: "" } member { - name: "experimental_numa_aware" + name: "experimental_optimization" mtype: "" } member { - name: "experimental_shuffle_and_repeat_fusion" + name: "experimental_stats" mtype: "" } member { - name: "experimental_stats" + name: "experimental_threading" mtype: "" } member_method { diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.-t-f-record-dataset.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.-t-f-record-dataset.pbtxt index 7b7a9ebaf0..51224cd6b4 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.-t-f-record-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.-t-f-record-dataset.pbtxt @@ -1,7 +1,9 @@ path: "tensorflow.data.TFRecordDataset" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.-text-line-dataset.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.-text-line-dataset.pbtxt index 1c305abf68..a10add1b7e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.-text-line-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.-text-line-dataset.pbtxt @@ -1,8 +1,9 @@ path: "tensorflow.data.TextLineDataset" tf_class { - is_instance: "" - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-csv-dataset.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-csv-dataset.pbtxt index 2520e28a3c..71b597c19c 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-csv-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-csv-dataset.pbtxt @@ -1,8 +1,9 @@ path: "tensorflow.data.experimental.CsvDataset" tf_class { - is_instance: "" - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-optimization-options.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-optimization-options.pbtxt new file mode 100644 index 0000000000..9ca75828e5 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-optimization-options.pbtxt @@ -0,0 +1,46 @@ +path: "tensorflow.data.experimental.OptimizationOptions" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "filter_fusion" + mtype: "" + } + member { + name: "hoist_random_uniform" + mtype: "" + } + member { + name: "map_and_batch_fusion" + mtype: "" + } + member { + name: "map_and_filter_fusion" + mtype: "" + } + member { + name: "map_fusion" + mtype: "" + } + member { + name: "map_parallelization" + mtype: "" + } + member { + name: "map_vectorization" + mtype: "" + } + member { + name: "noop_elimination" + mtype: "" + } + member { + name: "shuffle_and_repeat_fusion" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-random-dataset.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-random-dataset.pbtxt index 1dd53b1eab..20646e87b5 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-random-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-random-dataset.pbtxt @@ -1,8 +1,9 @@ path: "tensorflow.data.experimental.RandomDataset" tf_class { - is_instance: "" - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-sql-dataset.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-sql-dataset.pbtxt index 8fdd9dc52e..86c5ff5b0b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-sql-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-sql-dataset.pbtxt @@ -1,8 +1,9 @@ path: "tensorflow.data.experimental.SqlDataset" tf_class { - is_instance: "" - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-stats-options.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-stats-options.pbtxt index f423eed42c..892f8c1fb8 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-stats-options.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-stats-options.pbtxt @@ -1,6 +1,7 @@ path: "tensorflow.data.experimental.StatsOptions" tf_class { is_instance: "" + is_instance: "" is_instance: "" member { name: "aggregator" @@ -20,6 +21,6 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'aggregator\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } } diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-threading-options.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-threading-options.pbtxt new file mode 100644 index 0000000000..5b5ebf1080 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.-threading-options.pbtxt @@ -0,0 +1,18 @@ +path: "tensorflow.data.experimental.ThreadingOptions" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "max_intra_op_parallelism" + mtype: "" + } + member { + name: "private_threadpool_size" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.pbtxt index 4c253bb8ad..f981b1af17 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.pbtxt @@ -12,6 +12,14 @@ tf_module { name: "CsvDataset" mtype: "" } + member { + name: "INFINITE_CARDINALITY" + mtype: "" + } + member { + name: "OptimizationOptions" + mtype: "" + } member { name: "Optional" mtype: "" @@ -40,6 +48,14 @@ tf_module { name: "TFRecordWriter" mtype: "" } + member { + name: "ThreadingOptions" + mtype: "" + } + member { + name: "UNKNOWN_CARDINALITY" + mtype: "" + } member_method { name: "Counter" argspec: "args=[\'start\', \'step\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0\', \'1\', \"\"], " @@ -48,6 +64,10 @@ tf_module { name: "bucket_by_sequence_length" argspec: "args=[\'element_length_func\', \'bucket_boundaries\', \'bucket_batch_sizes\', \'padded_shapes\', \'padding_values\', \'pad_to_bucket_boundary\', \'no_padding\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'False\'], " } + member_method { + name: "cardinality" + argspec: "args=[\'dataset\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "choose_from_datasets" argspec: "args=[\'datasets\', \'choice_dataset\'], varargs=None, keywords=None, defaults=None" @@ -64,6 +84,10 @@ tf_module { name: "enumerate_dataset" argspec: "args=[\'start\'], varargs=None, keywords=None, defaults=[\'0\'], " } + member_method { + name: "filter_for_shard" + argspec: "args=[\'num_shards\', \'shard_index\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "get_next_as_optional" argspec: "args=[\'iterator\'], varargs=None, keywords=None, defaults=None" @@ -90,7 +114,7 @@ tf_module { } member_method { name: "make_batched_features_dataset" - argspec: "args=[\'file_pattern\', \'batch_size\', \'features\', \'reader\', \'label_key\', \'reader_args\', \'num_epochs\', \'shuffle\', \'shuffle_buffer_size\', \'shuffle_seed\', \'prefetch_buffer_size\', \'reader_num_threads\', \'parser_num_threads\', \'sloppy_ordering\', \'drop_final_batch\'], varargs=None, keywords=None, defaults=[\"\", \'None\', \'None\', \'None\', \'True\', \'10000\', \'None\', \'-1\', \'1\', \'2\', \'False\', \'False\'], " + argspec: "args=[\'file_pattern\', \'batch_size\', \'features\', \'reader\', \'label_key\', \'reader_args\', \'num_epochs\', \'shuffle\', \'shuffle_buffer_size\', \'shuffle_seed\', \'prefetch_buffer_size\', \'reader_num_threads\', \'parser_num_threads\', \'sloppy_ordering\', \'drop_final_batch\'], varargs=None, keywords=None, defaults=[\"\", \'None\', \'None\', \'None\', \'True\', \'10000\', \'None\', \'-1\', \'1\', \'2\', \'False\', \'False\'], " } member_method { name: "make_csv_dataset" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.pbtxt index 509bbae833..aa47468059 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.pbtxt @@ -28,4 +28,12 @@ tf_module { name: "experimental" mtype: "" } + member_method { + name: "make_initializable_iterator" + argspec: "args=[\'dataset\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "make_one_shot_iterator" + argspec: "args=[\'dataset\'], varargs=None, keywords=None, defaults=None" + } } diff --git a/tensorflow/tools/api/golden/v1/tensorflow.debugging.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.debugging.pbtxt index ab6287f8cd..8a7f1e9363 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.debugging.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.debugging.pbtxt @@ -78,7 +78,7 @@ tf_module { } member_method { name: "assert_scalar" - argspec: "args=[\'tensor\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'tensor\', \'name\', \'message\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "assert_type" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.distribute.-input-context.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-input-context.pbtxt new file mode 100644 index 0000000000..583cbc6654 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-input-context.pbtxt @@ -0,0 +1,25 @@ +path: "tensorflow.distribute.InputContext" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "input_pipeline_id" + mtype: "" + } + member { + name: "num_input_pipelines" + mtype: "" + } + member { + name: "num_replicas_in_sync" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'num_input_pipelines\', \'input_pipeline_id\', \'num_replicas_in_sync\'], varargs=None, keywords=None, defaults=[\'1\', \'0\', \'1\'], " + } + member_method { + name: "get_per_replica_batch_size" + argspec: "args=[\'self\', \'global_batch_size\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.distribute.-input-replication-mode.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-input-replication-mode.pbtxt new file mode 100644 index 0000000000..6a7a3a97aa --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-input-replication-mode.pbtxt @@ -0,0 +1,8 @@ +path: "tensorflow.distribute.InputReplicationMode" +tf_class { + is_instance: "" + member { + name: "PER_WORKER" + mtype: "" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.distribute.-reduce-op.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-reduce-op.pbtxt new file mode 100644 index 0000000000..4899f38cad --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-reduce-op.pbtxt @@ -0,0 +1,12 @@ +path: "tensorflow.distribute.ReduceOp" +tf_class { + is_instance: "" + member { + name: "MEAN" + mtype: "" + } + member { + name: "SUM" + mtype: "" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.distribute.-replica-context.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-replica-context.pbtxt new file mode 100644 index 0000000000..df707e8920 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-replica-context.pbtxt @@ -0,0 +1,33 @@ +path: "tensorflow.distribute.ReplicaContext" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "devices" + mtype: "" + } + member { + name: "distribution_strategy" + mtype: "" + } + member { + name: "num_replicas_in_sync" + mtype: "" + } + member { + name: "replica_id_in_sync_group" + mtype: "" + } + member { + name: "strategy" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'strategy\', \'replica_id_in_sync_group\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "merge_call" + argspec: "args=[\'self\', \'merge_fn\', \'args\', \'kwargs\'], varargs=None, keywords=None, defaults=[\'()\', \'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.distribute.-strategy-extended.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-strategy-extended.pbtxt new file mode 100644 index 0000000000..77706e5713 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-strategy-extended.pbtxt @@ -0,0 +1,81 @@ +path: "tensorflow.distribute.StrategyExtended" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "experimental_between_graph" + mtype: "" + } + member { + name: "experimental_require_static_shapes" + mtype: "" + } + member { + name: "experimental_should_init" + mtype: "" + } + member { + name: "parameter_devices" + mtype: "" + } + member { + name: "should_checkpoint" + mtype: "" + } + member { + name: "should_save_summary" + mtype: "" + } + member { + name: "worker_devices" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'container_strategy\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "batch_reduce_to" + argspec: "args=[\'self\', \'reduce_op\', \'value_destination_pairs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "broadcast_to" + argspec: "args=[\'self\', \'tensor\', \'destinations\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call_for_each_replica" + argspec: "args=[\'self\', \'fn\', \'args\', \'kwargs\'], varargs=None, keywords=None, defaults=[\'()\', \'None\'], " + } + member_method { + name: "colocate_vars_with" + argspec: "args=[\'self\', \'colocate_with_variable\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "experimental_run_steps_on_iterator" + argspec: "args=[\'self\', \'fn\', \'iterator\', \'iterations\', \'initial_loop_values\'], varargs=None, keywords=None, defaults=[\'1\', \'None\'], " + } + member_method { + name: "non_slot_devices" + argspec: "args=[\'self\', \'var_list\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "read_var" + argspec: "args=[\'self\', \'v\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reduce_to" + argspec: "args=[\'self\', \'reduce_op\', \'value\', \'destinations\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update" + argspec: "args=[\'self\', \'var\', \'fn\', \'args\', \'kwargs\', \'group\'], varargs=None, keywords=None, defaults=[\'()\', \'None\', \'True\'], " + } + member_method { + name: "update_non_slot" + argspec: "args=[\'self\', \'colocate_with\', \'fn\', \'args\', \'kwargs\', \'group\'], varargs=None, keywords=None, defaults=[\'()\', \'None\', \'True\'], " + } + member_method { + name: "value_container" + argspec: "args=[\'self\', \'value\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.distribute.-strategy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-strategy.pbtxt new file mode 100644 index 0000000000..9eb73d2c0d --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.distribute.-strategy.pbtxt @@ -0,0 +1,137 @@ +path: "tensorflow.distribute.Strategy" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "between_graph" + mtype: "" + } + member { + name: "extended" + mtype: "" + } + member { + name: "num_replicas_in_sync" + mtype: "" + } + member { + name: "parameter_devices" + mtype: "" + } + member { + name: "require_static_shapes" + mtype: "" + } + member { + name: "should_checkpoint" + mtype: "" + } + member { + name: "should_init" + mtype: "" + } + member { + name: "should_save_summary" + mtype: "" + } + member { + name: "worker_devices" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'extended\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "batch_reduce" + argspec: "args=[\'self\', \'aggregation\', \'value_destination_pairs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "broadcast" + argspec: "args=[\'self\', \'tensor\', \'destinations\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "call_for_each_replica" + argspec: "args=[\'self\', \'fn\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "colocate_vars_with" + argspec: "args=[\'self\', \'colocate_with_variable\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "configure" + argspec: "args=[\'self\', \'session_config\', \'cluster_spec\', \'task_type\', \'task_id\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + } + member_method { + name: "distribute_dataset" + argspec: "args=[\'self\', \'dataset_fn\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "experimental_finalize" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "experimental_initialize" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "finalize" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "group" + argspec: "args=[\'self\', \'value\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "initialize" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "make_dataset_iterator" + argspec: "args=[\'self\', \'dataset\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "make_input_fn_iterator" + argspec: "args=[\'self\', \'input_fn\', \'replication_mode\'], varargs=None, keywords=None, defaults=[\'InputReplicationMode.PER_WORKER\'], " + } + member_method { + name: "non_slot_devices" + argspec: "args=[\'self\', \'var_list\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "read_var" + argspec: "args=[\'self\', \'v\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reduce" + argspec: "args=[\'self\', \'reduce_op\', \'value\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "run_steps_on_dataset" + argspec: "args=[\'self\', \'fn\', \'iterator\', \'iterations\', \'initial_loop_values\'], varargs=None, keywords=None, defaults=[\'1\', \'None\'], " + } + member_method { + name: "scope" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "unwrap" + argspec: "args=[\'self\', \'value\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update" + argspec: "args=[\'self\', \'var\', \'fn\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "update_config_proto" + argspec: "args=[\'self\', \'config_proto\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_non_slot" + argspec: "args=[\'self\', \'colocate_with\', \'fn\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "value_container" + argspec: "args=[\'self\', \'value\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.distribute.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.distribute.pbtxt new file mode 100644 index 0000000000..4d833b54ba --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.distribute.pbtxt @@ -0,0 +1,47 @@ +path: "tensorflow.distribute" +tf_module { + member { + name: "InputContext" + mtype: "" + } + member { + name: "InputReplicationMode" + mtype: "" + } + member { + name: "ReduceOp" + mtype: "" + } + member { + name: "ReplicaContext" + mtype: "" + } + member { + name: "Strategy" + mtype: "" + } + member { + name: "StrategyExtended" + mtype: "" + } + member_method { + name: "get_loss_reduction" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_replica_context" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_strategy" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "has_strategy" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "in_cross_replica_context" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-classifier.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-classifier.pbtxt index 32b84e90ce..ee3a72bfce 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-classifier.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.BaselineClassifier" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-estimator.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-estimator.pbtxt index 94933e7ffd..38b27f735f 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-estimator.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.BaselineEstimator" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-regressor.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-regressor.pbtxt index db7776b5bf..3874b84d5a 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-baseline-regressor.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.BaselineRegressor" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-boosted-trees-classifier.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-boosted-trees-classifier.pbtxt index d530c71482..e138ce936e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-boosted-trees-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-boosted-trees-classifier.pbtxt @@ -3,6 +3,7 @@ tf_class { is_instance: "" is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -32,6 +33,10 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "experimental_feature_importances" argspec: "args=[\'self\', \'normalize\'], varargs=None, keywords=None, defaults=[\'False\'], " @@ -42,7 +47,7 @@ tf_class { } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-boosted-trees-regressor.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-boosted-trees-regressor.pbtxt index 4703c0f561..eae0a292a9 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-boosted-trees-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-boosted-trees-regressor.pbtxt @@ -3,6 +3,7 @@ tf_class { is_instance: "" is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -32,6 +33,10 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "experimental_feature_importances" argspec: "args=[\'self\', \'normalize\'], varargs=None, keywords=None, defaults=[\'False\'], " @@ -42,7 +47,7 @@ tf_class { } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-classifier.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-classifier.pbtxt index ce6040d0f2..b54133b294 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-classifier.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.DNNClassifier" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-estimator.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-estimator.pbtxt index 4635a1544c..09e0d38192 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-estimator.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.DNNEstimator" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-classifier.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-classifier.pbtxt index e85007e16e..5a1d85a9b1 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-classifier.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.DNNLinearCombinedClassifier" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-estimator.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-estimator.pbtxt index a23f5daeac..e311f96d3d 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-estimator.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.DNNLinearCombinedEstimator" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-regressor.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-regressor.pbtxt index 8a55bb835f..db4780e4c0 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-linear-combined-regressor.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.DNNLinearCombinedRegressor" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-regressor.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-regressor.pbtxt index 2c4128ec48..a44e719099 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-d-n-n-regressor.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.DNNRegressor" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-estimator.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-estimator.pbtxt index 9d270a87ab..bff6c86cd7 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-estimator.pbtxt @@ -1,6 +1,7 @@ path: "tensorflow.estimator.Estimator" tf_class { is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -30,9 +31,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-classifier.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-classifier.pbtxt index 4b5de2e245..2c8e82517b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-classifier.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.LinearClassifier" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-estimator.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-estimator.pbtxt index 3d6b03098a..2148374fde 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-estimator.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.LinearEstimator" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-regressor.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-regressor.pbtxt index 0d1510e9ab..1bdc6124fe 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.-linear-regressor.pbtxt @@ -2,6 +2,7 @@ path: "tensorflow.estimator.LinearRegressor" tf_class { is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,9 +32,13 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-profiler-hook.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.-in-memory-evaluator-hook.pbtxt similarity index 71% rename from tensorflow/tools/api/golden/v2/tensorflow.train.-profiler-hook.pbtxt rename to tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.-in-memory-evaluator-hook.pbtxt index 4df6c4156a..aba120218c 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-profiler-hook.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.-in-memory-evaluator-hook.pbtxt @@ -1,11 +1,11 @@ -path: "tensorflow.train.ProfilerHook" +path: "tensorflow.estimator.experimental.InMemoryEvaluatorHook" tf_class { - is_instance: "" + is_instance: "" is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'save_steps\', \'save_secs\', \'output_dir\', \'show_dataflow\', \'show_memory\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'\', \'True\', \'False\'], " + argspec: "args=[\'self\', \'estimator\', \'input_fn\', \'steps\', \'hooks\', \'name\', \'every_n_iter\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'100\'], " } member_method { name: "after_create_session" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.pbtxt index cabca3e883..f0fd7ce782 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.pbtxt @@ -1,9 +1,17 @@ path: "tensorflow.estimator.experimental" tf_module { + member { + name: "InMemoryEvaluatorHook" + mtype: "" + } member { name: "LinearSDCA" mtype: "" } + member_method { + name: "build_raw_supervised_input_receiver_fn" + argspec: "args=[\'features\', \'labels\', \'default_batch_size\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "call_logit_fn" argspec: "args=[\'logit_fn\', \'features\', \'mode\', \'params\', \'config\'], varargs=None, keywords=None, defaults=None" @@ -20,6 +28,10 @@ tf_module { name: "make_early_stopping_hook" argspec: "args=[\'estimator\', \'should_stop_fn\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'60\', \'None\'], " } + member_method { + name: "make_stop_at_checkpoint_step_hook" + argspec: "args=[\'estimator\', \'last_step\', \'wait_after_file_check_secs\'], varargs=None, keywords=None, defaults=[\'30\'], " + } member_method { name: "stop_if_higher_hook" argspec: "args=[\'estimator\', \'metric_name\', \'threshold\', \'eval_dir\', \'min_steps\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'60\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.image.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.image.pbtxt index 0a231f1b65..15d0e099ba 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.image.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.image.pbtxt @@ -172,6 +172,10 @@ tf_module { name: "random_saturation" argspec: "args=[\'image\', \'lower\', \'upper\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "resize" + argspec: "args=[\'images\', \'size\', \'method\', \'align_corners\', \'preserve_aspect_ratio\'], varargs=None, keywords=None, defaults=[\'0\', \'False\', \'False\'], " + } member_method { name: "resize_area" argspec: "args=[\'images\', \'size\', \'align_corners\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " @@ -240,6 +244,10 @@ tf_module { name: "total_variation" argspec: "args=[\'images\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "transpose" + argspec: "args=[\'image\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "transpose_image" argspec: "args=[\'image\'], varargs=None, keywords=None, defaults=None" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.io.gfile.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.io.gfile.pbtxt new file mode 100644 index 0000000000..93d9b0fd75 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.io.gfile.pbtxt @@ -0,0 +1,51 @@ +path: "tensorflow.io.gfile" +tf_module { + member_method { + name: "copy" + argspec: "args=[\'src\', \'dst\', \'overwrite\'], varargs=None, keywords=None, defaults=[\'False\'], " + } + member_method { + name: "exists" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "glob" + argspec: "args=[\'pattern\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "isdir" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "listdir" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "makedirs" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "mkdir" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "remove" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "rename" + argspec: "args=[\'src\', \'dst\', \'overwrite\'], varargs=None, keywords=None, defaults=[\'False\'], " + } + member_method { + name: "rmtree" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "stat" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "walk" + argspec: "args=[\'top\', \'topdown\', \'onerror\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.io.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.io.pbtxt index 64b63ed1a4..b760ec3890 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.io.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.io.pbtxt @@ -44,10 +44,22 @@ tf_module { name: "VarLenFeature" mtype: "" } + member { + name: "gfile" + mtype: "" + } + member_method { + name: "decode_and_crop_jpeg" + argspec: "args=[\'contents\', \'crop_window\', \'channels\', \'ratio\', \'fancy_upscaling\', \'try_recover_truncated\', \'acceptable_fraction\', \'dct_method\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'1\', \'True\', \'False\', \'1\', \'\', \'None\'], " + } member_method { name: "decode_base64" argspec: "args=[\'input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "decode_bmp" + argspec: "args=[\'contents\', \'channels\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'None\'], " + } member_method { name: "decode_compressed" argspec: "args=[\'bytes\', \'compression_type\', \'name\'], varargs=None, keywords=None, defaults=[\'\', \'None\'], " @@ -56,10 +68,26 @@ tf_module { name: "decode_csv" argspec: "args=[\'records\', \'record_defaults\', \'field_delim\', \'use_quote_delim\', \'name\', \'na_value\', \'select_cols\'], varargs=None, keywords=None, defaults=[\',\', \'True\', \'None\', \'\', \'None\'], " } + member_method { + name: "decode_gif" + argspec: "args=[\'contents\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "decode_image" + argspec: "args=[\'contents\', \'channels\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\'], " + } + member_method { + name: "decode_jpeg" + argspec: "args=[\'contents\', \'channels\', \'ratio\', \'fancy_upscaling\', \'try_recover_truncated\', \'acceptable_fraction\', \'dct_method\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'1\', \'True\', \'False\', \'1\', \'\', \'None\'], " + } member_method { name: "decode_json_example" argspec: "args=[\'json_examples\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "decode_png" + argspec: "args=[\'contents\', \'channels\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \"\", \'None\'], " + } member_method { name: "decode_raw" argspec: "args=[\'bytes\', \'out_type\', \'little_endian\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'None\'], " @@ -72,6 +100,18 @@ tf_module { name: "encode_base64" argspec: "args=[\'input\', \'pad\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " } + member_method { + name: "encode_jpeg" + argspec: "args=[\'image\', \'format\', \'quality\', \'progressive\', \'optimize_size\', \'chroma_downsampling\', \'density_unit\', \'x_density\', \'y_density\', \'xmp_metadata\', \'name\'], varargs=None, keywords=None, defaults=[\'\', \'95\', \'False\', \'False\', \'True\', \'in\', \'300\', \'300\', \'\', \'None\'], " + } + member_method { + name: "extract_jpeg_shape" + argspec: "args=[\'contents\', \'output_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " + } + member_method { + name: "is_jpeg" + argspec: "args=[\'contents\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "match_filenames_once" argspec: "args=[\'pattern\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.-model.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.-model.pbtxt index 8ccba990bd..a3254cbd94 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.-model.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.-model.pbtxt @@ -41,6 +41,14 @@ tf_class { name: "losses" mtype: "" } + member { + name: "metrics" + mtype: "" + } + member { + name: "metrics_names" + mtype: "" + } member { name: "name" mtype: "" @@ -69,6 +77,10 @@ tf_class { name: "output_shape" mtype: "" } + member { + name: "run_eagerly" + mtype: "" + } member { name: "state_updates" mtype: "" @@ -105,13 +117,17 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "add_variable" - argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\', \'None\'], " + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" } member_method { name: "add_weight" @@ -225,6 +241,10 @@ tf_class { name: "predict_on_batch" argspec: "args=[\'self\', \'x\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "reset_metrics" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "reset_states" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" @@ -247,7 +267,7 @@ tf_class { } member_method { name: "test_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " } member_method { name: "to_json" @@ -259,6 +279,6 @@ tf_class { } member_method { name: "train_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\'], " } } diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.-sequential.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.-sequential.pbtxt index 27aa91a645..b70e9ee98d 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.-sequential.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.-sequential.pbtxt @@ -42,6 +42,14 @@ tf_class { name: "losses" mtype: "" } + member { + name: "metrics" + mtype: "" + } + member { + name: "metrics_names" + mtype: "" + } member { name: "name" mtype: "" @@ -70,6 +78,10 @@ tf_class { name: "output_shape" mtype: "" } + member { + name: "run_eagerly" + mtype: "" + } member { name: "state_updates" mtype: "" @@ -110,13 +122,17 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "add_variable" - argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\', \'None\'], " + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" } member_method { name: "add_weight" @@ -242,6 +258,10 @@ tf_class { name: "predict_proba" argspec: "args=[\'self\', \'x\', \'batch_size\', \'verbose\'], varargs=None, keywords=None, defaults=[\'32\', \'0\'], " } + member_method { + name: "reset_metrics" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "reset_states" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" @@ -264,7 +284,7 @@ tf_class { } member_method { name: "test_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " } member_method { name: "to_json" @@ -276,6 +296,6 @@ tf_class { } member_method { name: "train_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\'], " } } diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.backend.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.backend.pbtxt index b0e5d2bde7..8cd0c6ea5f 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.backend.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.backend.pbtxt @@ -398,7 +398,7 @@ tf_module { } member_method { name: "rnn" - argspec: "args=[\'step_function\', \'inputs\', \'initial_states\', \'go_backwards\', \'mask\', \'constants\', \'unroll\', \'input_length\', \'time_major\'], varargs=None, keywords=None, defaults=[\'False\', \'None\', \'None\', \'False\', \'None\', \'False\'], " + argspec: "args=[\'step_function\', \'inputs\', \'initial_states\', \'go_backwards\', \'mask\', \'constants\', \'unroll\', \'input_length\', \'time_major\', \'zero_output_for_mask\'], varargs=None, keywords=None, defaults=[\'False\', \'None\', \'None\', \'False\', \'None\', \'False\', \'False\'], " } member_method { name: "round" @@ -512,6 +512,10 @@ tf_module { name: "temporal_padding" argspec: "args=[\'x\', \'padding\'], varargs=None, keywords=None, defaults=[\'(1, 1)\'], " } + member_method { + name: "tile" + argspec: "args=[\'x\', \'n\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "to_dense" argspec: "args=[\'tensor\'], varargs=None, keywords=None, defaults=None" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.experimental.-peephole-l-s-t-m-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.experimental.-peephole-l-s-t-m-cell.pbtxt index db69e25c5b..1d814b2c8b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.experimental.-peephole-l-s-t-m-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.experimental.-peephole-l-s-t-m-cell.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-activation.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-activation.pbtxt index 5510465d7b..b84629540e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-activation.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-activation.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-activity-regularization.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-activity-regularization.pbtxt index 38ec8a0aff..5918a13ad8 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-activity-regularization.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-activity-regularization.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-add.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-add.pbtxt index 41cb8e30bf..599da06427 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-add.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-add.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-alpha-dropout.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-alpha-dropout.pbtxt index 9a7aaa8e96..f9ff1538c8 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-alpha-dropout.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-alpha-dropout.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling1-d.pbtxt index 014f5828fa..723fc9cdb0 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling2-d.pbtxt index cc303bf7b9..957ce2f0ce 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling3-d.pbtxt index 628447ce35..a52c0af681 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average-pooling3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average.pbtxt index f03c986c22..a004db62dd 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-average.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool1-d.pbtxt index a6e4856de9..44f83d1387 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool2-d.pbtxt index a01eaf8a12..8378faf718 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool3-d.pbtxt index 0d6698f2ef..9d5655c964 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-avg-pool3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-batch-normalization.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-batch-normalization.pbtxt index f1b23be48f..b3d3c84f92 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-batch-normalization.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-batch-normalization.pbtxt @@ -1,6 +1,7 @@ path: "tensorflow.keras.layers.BatchNormalization" tf_class { - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" is_instance: "" is_instance: "" @@ -88,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-bidirectional.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-bidirectional.pbtxt index 0672cd5b7b..d37a6b4710 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-bidirectional.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-bidirectional.pbtxt @@ -97,6 +97,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-concatenate.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-concatenate.pbtxt index b25ae1e82e..1ad7a91be0 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-concatenate.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-concatenate.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv-l-s-t-m2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv-l-s-t-m2-d.pbtxt index bb1918eba6..cb9abc2539 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv-l-s-t-m2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv-l-s-t-m2-d.pbtxt @@ -178,6 +178,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv1-d.pbtxt index 16e0fd5a31..47dba1d81f 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv2-d-transpose.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv2-d-transpose.pbtxt index 381839d6de..fd64941896 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv2-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv2-d-transpose.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv2-d.pbtxt index 543bae6fa9..1b1425d531 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv3-d-transpose.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv3-d-transpose.pbtxt index 2933f9f4b3..1741063fe8 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv3-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv3-d-transpose.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv3-d.pbtxt index 072943dc2c..50feb4f458 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-conv3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution1-d.pbtxt index 222a1ef4fc..faaa535df9 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution2-d-transpose.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution2-d-transpose.pbtxt index 9c9c7461c8..4079329d1e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution2-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution2-d-transpose.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution2-d.pbtxt index f939067178..32e56696e1 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution3-d-transpose.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution3-d-transpose.pbtxt index 44ca598724..381abe7340 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution3-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution3-d-transpose.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution3-d.pbtxt index 471b18ef85..b3e4bf9689 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-convolution3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping1-d.pbtxt index 0f250a09b7..7aeff8003c 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping1-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping2-d.pbtxt index f52128483c..a1728d9d4f 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping2-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping3-d.pbtxt index 98daf3bab1..8d8fd142cc 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cropping3-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt index b207c68000..7758209adf 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt @@ -98,6 +98,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt index 2d7a09ceda..7c463ff125 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt @@ -98,6 +98,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dense.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dense.pbtxt index 3ac3825759..4960d0264e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dense.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dense.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-depthwise-conv2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-depthwise-conv2-d.pbtxt index 280ec8c25f..8fad7535f8 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-depthwise-conv2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-depthwise-conv2-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dot.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dot.pbtxt index 560f66f9c7..5b425f2d4d 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dot.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dot.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dropout.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dropout.pbtxt index c0543529c3..f6c4d0a438 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dropout.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-dropout.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-e-l-u.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-e-l-u.pbtxt index 04eb2824b9..82b761fc17 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-e-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-e-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-embedding.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-embedding.pbtxt index f400432915..c9ff323877 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-embedding.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-embedding.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-flatten.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-flatten.pbtxt index ab176b441a..9b4165d4cb 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-flatten.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-flatten.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-g-r-u-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-g-r-u-cell.pbtxt index c3895a0ac1..f225f7c430 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-g-r-u-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-g-r-u-cell.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-g-r-u.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-g-r-u.pbtxt index 9e24bb8ae6..855d001700 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-g-r-u.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-g-r-u.pbtxt @@ -161,6 +161,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-gaussian-dropout.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-gaussian-dropout.pbtxt index 55e0d7ef02..2c404c99cd 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-gaussian-dropout.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-gaussian-dropout.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-gaussian-noise.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-gaussian-noise.pbtxt index 38fbff5e4a..6f109d59d0 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-gaussian-noise.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-gaussian-noise.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling1-d.pbtxt index a8094c0bde..69f8a9031d 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling2-d.pbtxt index 929f48df23..4299f765e5 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling3-d.pbtxt index 2e6d59337f..9153a1a240 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-average-pooling3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool1-d.pbtxt index 3ebe162f57..625e81fd23 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool2-d.pbtxt index 4e3e258430..2fc769742c 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool3-d.pbtxt index fb9166316f..e307a65c7c 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-avg-pool3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool1-d.pbtxt index c0a53b847b..4394ad0364 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool2-d.pbtxt index 87b7f6797a..050ed39fe9 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool3-d.pbtxt index 98bf96fa0c..436191821e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pool3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling1-d.pbtxt index ff6c6f3ec4..4ba540aa6a 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling2-d.pbtxt index c9d4158d1c..a2e9322cb3 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling3-d.pbtxt index 9953102ff9..5d16a57fc1 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-global-max-pooling3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-input-layer.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-input-layer.pbtxt index 2617f5a95f..9dd29c1251 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-input-layer.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-input-layer.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-input-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-input-spec.pbtxt index 5fd0a47a68..bc3ceb67a4 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-input-spec.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-input-spec.pbtxt @@ -1,6 +1,6 @@ path: "tensorflow.keras.layers.InputSpec" tf_class { - is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-l-s-t-m-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-l-s-t-m-cell.pbtxt index e9f6ef45aa..0045d5775e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-l-s-t-m-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-l-s-t-m-cell.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-l-s-t-m.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-l-s-t-m.pbtxt index 1b1ccbe118..529c750f98 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-l-s-t-m.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-l-s-t-m.pbtxt @@ -161,6 +161,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-lambda.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-lambda.pbtxt index 2e0b6bac24..d4d1bc6b6b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-lambda.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-lambda.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-layer.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-layer.pbtxt index 1e93d1118a..e1f5491180 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-layer.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-layer.pbtxt @@ -87,6 +87,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-leaky-re-l-u.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-leaky-re-l-u.pbtxt index bfd36012a7..9b69d9a944 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-leaky-re-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-leaky-re-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-locally-connected1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-locally-connected1-d.pbtxt index 5ad5990d7e..fd52259432 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-locally-connected1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-locally-connected1-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-locally-connected2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-locally-connected2-d.pbtxt index 40d03369a5..5fc8af0d03 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-locally-connected2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-locally-connected2-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-masking.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-masking.pbtxt index 86666b51bb..7f8932270e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-masking.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-masking.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool1-d.pbtxt index d26da270e7..4723b99cb0 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool2-d.pbtxt index 85f23df671..173c5d4a8b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool3-d.pbtxt index 235806b965..14e1899e14 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pool3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling1-d.pbtxt index 524c5fd69e..a708e652bf 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling2-d.pbtxt index fda2562fc8..e6706b5cf9 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling3-d.pbtxt index 71d2d09a8d..a73c082d1b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-max-pooling3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-maximum.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-maximum.pbtxt index 12949b39a6..f3f195554b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-maximum.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-maximum.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-minimum.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-minimum.pbtxt index ab16d0021e..f345d1d67b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-minimum.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-minimum.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-multiply.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-multiply.pbtxt index 61ccbf5962..31cb8bc177 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-multiply.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-multiply.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-p-re-l-u.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-p-re-l-u.pbtxt index ce2320d703..44cccc92bd 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-p-re-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-p-re-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-permute.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-permute.pbtxt index 69848af8cf..b55e191ff1 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-permute.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-permute.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-r-n-n.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-r-n-n.pbtxt index 3358f26aeb..e9575436e5 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-r-n-n.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-r-n-n.pbtxt @@ -92,6 +92,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-re-l-u.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-re-l-u.pbtxt index 413f45f018..98223b207f 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-re-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-re-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-repeat-vector.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-repeat-vector.pbtxt index 9c61ff6027..2df918b16b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-repeat-vector.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-repeat-vector.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-reshape.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-reshape.pbtxt index baa91804c4..ce5f9e2129 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-reshape.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-reshape.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-conv1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-conv1-d.pbtxt index 15a5d6ac9e..a0bb917775 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-conv1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-conv1-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-conv2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-conv2-d.pbtxt index be43bd5b3c..d7942f201b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-conv2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-conv2-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-convolution1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-convolution1-d.pbtxt index 6105992c7a..f7ac9042d4 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-convolution1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-convolution1-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-convolution2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-convolution2-d.pbtxt index 1b6cf1e9ec..e5a9268822 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-convolution2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-separable-convolution2-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-simple-r-n-n-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-simple-r-n-n-cell.pbtxt index 29488a37f8..0fe2c974a7 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-simple-r-n-n-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-simple-r-n-n-cell.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-simple-r-n-n.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-simple-r-n-n.pbtxt index 3d70cf8b65..2ee5873f0f 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-simple-r-n-n.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-simple-r-n-n.pbtxt @@ -149,6 +149,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-softmax.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-softmax.pbtxt index d29731ecf9..5b8f64aa35 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-softmax.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-softmax.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout1-d.pbtxt index a6d7494ca7..240cb6e562 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout2-d.pbtxt index c36e802693..6226c469f8 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout3-d.pbtxt index 9c46cfe40f..34dabce6d8 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-spatial-dropout3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-stacked-r-n-n-cells.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-stacked-r-n-n-cells.pbtxt index 8982f78794..0ddf628ace 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-stacked-r-n-n-cells.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-stacked-r-n-n-cells.pbtxt @@ -96,6 +96,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-subtract.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-subtract.pbtxt index ec2cc50298..12eb35ad15 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-subtract.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-subtract.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-thresholded-re-l-u.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-thresholded-re-l-u.pbtxt index d7bc1980f3..c41020c2b4 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-thresholded-re-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-thresholded-re-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-time-distributed.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-time-distributed.pbtxt index fec2de6b49..479f89cf6a 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-time-distributed.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-time-distributed.pbtxt @@ -93,6 +93,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling1-d.pbtxt index 3d285e7f17..233363ce02 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling1-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling2-d.pbtxt index b05e5ec84d..cb6228ac44 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling2-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling3-d.pbtxt index 728eca415a..03bad3ccb6 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-up-sampling3-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-wrapper.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-wrapper.pbtxt index da64e77c39..158996792a 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-wrapper.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-wrapper.pbtxt @@ -92,6 +92,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding1-d.pbtxt index 2f505f9293..63a56cd3ee 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding1-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding2-d.pbtxt index f82c77072e..965a4cca04 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding2-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding3-d.pbtxt index 54e01a9917..1a62430887 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.layers.-zero-padding3-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-binary-crossentropy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-binary-crossentropy.pbtxt new file mode 100644 index 0000000000..2f7da93f6f --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-binary-crossentropy.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.BinaryCrossentropy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'from_logits\', \'label_smoothing\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'0\', \'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-categorical-crossentropy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-categorical-crossentropy.pbtxt new file mode 100644 index 0000000000..b3a7cd8097 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-categorical-crossentropy.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.CategoricalCrossentropy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'from_logits\', \'label_smoothing\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'0\', \'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-absolute-error.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-absolute-error.pbtxt new file mode 100644 index 0000000000..712bb2ecd3 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-absolute-error.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.MeanAbsoluteError" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-absolute-percentage-error.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-absolute-percentage-error.pbtxt new file mode 100644 index 0000000000..7fe362da89 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-absolute-percentage-error.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.MeanAbsolutePercentageError" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-squared-error.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-squared-error.pbtxt new file mode 100644 index 0000000000..a571853350 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-squared-error.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.MeanSquaredError" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-squared-logarithmic-error.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-squared-logarithmic-error.pbtxt new file mode 100644 index 0000000000..200006db35 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.-mean-squared-logarithmic-error.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.MeanSquaredLogarithmicError" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.pbtxt index eca6b91538..9e26ddbdca 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.losses.pbtxt @@ -1,5 +1,29 @@ path: "tensorflow.keras.losses" tf_module { + member { + name: "BinaryCrossentropy" + mtype: "" + } + member { + name: "CategoricalCrossentropy" + mtype: "" + } + member { + name: "MeanAbsoluteError" + mtype: "" + } + member { + name: "MeanAbsolutePercentageError" + mtype: "" + } + member { + name: "MeanSquaredError" + mtype: "" + } + member { + name: "MeanSquaredLogarithmicError" + mtype: "" + } member_method { name: "KLD" argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" @@ -22,11 +46,11 @@ tf_module { } member_method { name: "binary_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "categorical_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "categorical_hinge" @@ -106,7 +130,7 @@ tf_module { } member_method { name: "sparse_categorical_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "squared_hinge" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-accuracy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-accuracy.pbtxt new file mode 100644 index 0000000000..2db07df523 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.keras.metrics.Accuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-binary-accuracy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-binary-accuracy.pbtxt new file mode 100644 index 0000000000..904ad3a21a --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-binary-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.keras.metrics.BinaryAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\', \'threshold\'], varargs=None, keywords=None, defaults=[\'binary_accuracy\', \'None\', \'0.5\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-categorical-accuracy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-categorical-accuracy.pbtxt new file mode 100644 index 0000000000..17b74924fa --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-categorical-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.keras.metrics.CategoricalAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'categorical_accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-false-negatives.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-false-negatives.pbtxt new file mode 100644 index 0000000000..49f577e136 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-false-negatives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.keras.metrics.FalseNegatives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-false-positives.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-false-positives.pbtxt new file mode 100644 index 0000000000..e8baf85866 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-false-positives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.keras.metrics.FalsePositives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-mean.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-mean.pbtxt new file mode 100644 index 0000000000..40fe64bbd2 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-mean.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.keras.metrics.Mean" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'mean\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'values\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-precision.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-precision.pbtxt new file mode 100644 index 0000000000..ae6a85026d --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-precision.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.keras.metrics.Precision" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-recall.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-recall.pbtxt new file mode 100644 index 0000000000..31068a51d5 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-recall.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.keras.metrics.Recall" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-sparse-categorical-accuracy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-sparse-categorical-accuracy.pbtxt new file mode 100644 index 0000000000..0c17452292 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-sparse-categorical-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.keras.metrics.SparseCategoricalAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'sparse_categorical_accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-true-negatives.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-true-negatives.pbtxt new file mode 100644 index 0000000000..1b5eb8d0de --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-true-negatives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.keras.metrics.TrueNegatives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-true-positives.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-true-positives.pbtxt new file mode 100644 index 0000000000..5b9c470e32 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.-true-positives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.keras.metrics.TruePositives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.pbtxt index a296e13158..8cab17edc5 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.metrics.pbtxt @@ -1,5 +1,49 @@ path: "tensorflow.keras.metrics" tf_module { + member { + name: "Accuracy" + mtype: "" + } + member { + name: "BinaryAccuracy" + mtype: "" + } + member { + name: "CategoricalAccuracy" + mtype: "" + } + member { + name: "FalseNegatives" + mtype: "" + } + member { + name: "FalsePositives" + mtype: "" + } + member { + name: "Mean" + mtype: "" + } + member { + name: "Precision" + mtype: "" + } + member { + name: "Recall" + mtype: "" + } + member { + name: "SparseCategoricalAccuracy" + mtype: "" + } + member { + name: "TrueNegatives" + mtype: "" + } + member { + name: "TruePositives" + mtype: "" + } member_method { name: "KLD" argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" @@ -26,7 +70,7 @@ tf_module { } member_method { name: "binary_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "categorical_accuracy" @@ -34,7 +78,7 @@ tf_module { } member_method { name: "categorical_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "cosine" @@ -110,7 +154,7 @@ tf_module { } member_method { name: "sparse_categorical_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "sparse_top_k_categorical_accuracy" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.models.-model.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.models.-model.pbtxt index ccff809f2b..c58c7bef22 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.models.-model.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.models.-model.pbtxt @@ -41,6 +41,14 @@ tf_class { name: "losses" mtype: "" } + member { + name: "metrics" + mtype: "" + } + member { + name: "metrics_names" + mtype: "" + } member { name: "name" mtype: "" @@ -69,6 +77,10 @@ tf_class { name: "output_shape" mtype: "" } + member { + name: "run_eagerly" + mtype: "" + } member { name: "state_updates" mtype: "" @@ -105,13 +117,17 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "add_variable" - argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\', \'None\'], " + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" } member_method { name: "add_weight" @@ -225,6 +241,10 @@ tf_class { name: "predict_on_batch" argspec: "args=[\'self\', \'x\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "reset_metrics" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "reset_states" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" @@ -247,7 +267,7 @@ tf_class { } member_method { name: "test_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " } member_method { name: "to_json" @@ -259,6 +279,6 @@ tf_class { } member_method { name: "train_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\'], " } } diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.models.-sequential.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.models.-sequential.pbtxt index b0fc7f97f1..473a1c16fb 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.models.-sequential.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.models.-sequential.pbtxt @@ -42,6 +42,14 @@ tf_class { name: "losses" mtype: "" } + member { + name: "metrics" + mtype: "" + } + member { + name: "metrics_names" + mtype: "" + } member { name: "name" mtype: "" @@ -70,6 +78,10 @@ tf_class { name: "output_shape" mtype: "" } + member { + name: "run_eagerly" + mtype: "" + } member { name: "state_updates" mtype: "" @@ -110,13 +122,17 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "add_variable" - argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\', \'None\'], " + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" } member_method { name: "add_weight" @@ -242,6 +258,10 @@ tf_class { name: "predict_proba" argspec: "args=[\'self\', \'x\', \'batch_size\', \'verbose\'], varargs=None, keywords=None, defaults=[\'32\', \'0\'], " } + member_method { + name: "reset_metrics" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "reset_states" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" @@ -264,7 +284,7 @@ tf_class { } member_method { name: "test_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " } member_method { name: "to_json" @@ -276,6 +296,6 @@ tf_class { } member_method { name: "train_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\'], " } } diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.utils.-progbar.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.utils.-progbar.pbtxt index be4496e753..8177cc71ed 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.utils.-progbar.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.utils.-progbar.pbtxt @@ -4,7 +4,7 @@ tf_class { is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'target\', \'width\', \'verbose\', \'interval\', \'stateful_metrics\'], varargs=None, keywords=None, defaults=[\'30\', \'1\', \'0.05\', \'None\'], " + argspec: "args=[\'self\', \'target\', \'width\', \'verbose\', \'interval\', \'stateful_metrics\', \'unit_name\'], varargs=None, keywords=None, defaults=[\'30\', \'1\', \'0.05\', \'None\', \'step\'], " } member_method { name: "add" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling1-d.pbtxt index c82e67526b..059c91f724 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling1-d.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling2-d.pbtxt index 1d031cb5f8..d06c8e81ee 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling2-d.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling3-d.pbtxt index a8dda6655d..6be8e7c210 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-average-pooling3-d.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-batch-normalization.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-batch-normalization.pbtxt index 97f65ed894..16d9ecce10 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-batch-normalization.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-batch-normalization.pbtxt @@ -1,7 +1,8 @@ path: "tensorflow.layers.BatchNormalization" tf_class { is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" is_instance: "" is_instance: "" @@ -98,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv1-d.pbtxt index ccd9578f0d..21c695935c 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv1-d.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv2-d-transpose.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv2-d-transpose.pbtxt index 9cbb58d721..f24d030720 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv2-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv2-d-transpose.pbtxt @@ -100,6 +100,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv2-d.pbtxt index c75ea3911e..0a510ece35 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv2-d.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv3-d-transpose.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv3-d-transpose.pbtxt index 5dc834e514..d0ee44bed3 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv3-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv3-d-transpose.pbtxt @@ -100,6 +100,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv3-d.pbtxt index 96ab209874..546de3cdab 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-conv3-d.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-dense.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-dense.pbtxt index 7e9656b352..3ad311581e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-dense.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-dense.pbtxt @@ -98,6 +98,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-dropout.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-dropout.pbtxt index e9a2269a6e..9b83271350 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-dropout.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-dropout.pbtxt @@ -98,6 +98,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-flatten.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-flatten.pbtxt index 7d2eaaab2a..87a7fb3d84 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-flatten.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-flatten.pbtxt @@ -98,6 +98,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-input-spec.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-input-spec.pbtxt index fd02c919ae..80834e08f7 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-input-spec.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-input-spec.pbtxt @@ -1,6 +1,6 @@ path: "tensorflow.layers.InputSpec" tf_class { - is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-layer.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-layer.pbtxt index 8bc3eb26e9..32b17e90ad 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-layer.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-layer.pbtxt @@ -96,6 +96,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling1-d.pbtxt index 6a0dcce56a..643c469717 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling1-d.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling2-d.pbtxt index b6c84edf2a..434e25adc1 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling2-d.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling3-d.pbtxt index 062a02fa59..089fc6f924 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-max-pooling3-d.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-separable-conv1-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-separable-conv1-d.pbtxt index eaad0fb23e..bc3d58b9ca 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-separable-conv1-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-separable-conv1-d.pbtxt @@ -100,6 +100,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.layers.-separable-conv2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.layers.-separable-conv2-d.pbtxt index ece28a8ce9..fe7d71af3a 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.layers.-separable-conv2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.layers.-separable-conv2-d.pbtxt @@ -100,6 +100,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-block-diag.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-block-diag.pbtxt index 973705dae2..773c74e64d 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-block-diag.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-block-diag.pbtxt @@ -79,6 +79,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant.pbtxt index de917706d5..533544d21f 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant.pbtxt @@ -96,6 +96,10 @@ tf_class { name: "block_shape_tensor" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "convolution_kernel" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'convolution_kernel\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant2-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant2-d.pbtxt index c4e6a21c3a..e3926eb6d4 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant2-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant2-d.pbtxt @@ -96,6 +96,10 @@ tf_class { name: "block_shape_tensor" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "convolution_kernel" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'convolution_kernel\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant3-d.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant3-d.pbtxt index 2e085a8e28..ba209df782 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant3-d.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-circulant3-d.pbtxt @@ -96,6 +96,10 @@ tf_class { name: "block_shape_tensor" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "convolution_kernel" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'convolution_kernel\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-composition.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-composition.pbtxt index 42d22bce42..081fb0e08b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-composition.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-composition.pbtxt @@ -79,6 +79,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-diag.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-diag.pbtxt index d6749fdcec..2014a04301 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-diag.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-diag.pbtxt @@ -79,6 +79,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-full-matrix.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-full-matrix.pbtxt index d9f363d133..9a87ae9687 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-full-matrix.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-full-matrix.pbtxt @@ -75,6 +75,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-identity.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-identity.pbtxt index aac7ee31ed..33afb835ce 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-identity.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-identity.pbtxt @@ -76,6 +76,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-kronecker.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-kronecker.pbtxt index c11d390829..a9078c8ab5 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-kronecker.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-kronecker.pbtxt @@ -79,6 +79,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-low-rank-update.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-low-rank-update.pbtxt index 3ee800269e..4cfa3bb30d 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-low-rank-update.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-low-rank-update.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-lower-triangular.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-lower-triangular.pbtxt index 63a1bc2321..a87649133f 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-lower-triangular.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-lower-triangular.pbtxt @@ -75,6 +75,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-scaled-identity.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-scaled-identity.pbtxt index e2c5a505a7..3265646784 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-scaled-identity.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-scaled-identity.pbtxt @@ -80,6 +80,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-zeros.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-zeros.pbtxt index a1b0e06b47..49d8890c89 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-zeros.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator-zeros.pbtxt @@ -75,6 +75,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator.pbtxt index 6d849dc040..c89dc067b3 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.linalg.-linear-operator.pbtxt @@ -74,6 +74,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.lite.constants.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.lite.constants.pbtxt index 08845553e5..ef6c777665 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.lite.constants.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.lite.constants.pbtxt @@ -2,7 +2,7 @@ path: "tensorflow.lite.constants" tf_module { member { name: "FLOAT" - mtype: "" + mtype: "" } member { name: "GRAPHVIZ_DOT" @@ -10,19 +10,19 @@ tf_module { } member { name: "INT32" - mtype: "" + mtype: "" } member { name: "INT64" - mtype: "" + mtype: "" } member { name: "QUANTIZED_UINT8" - mtype: "" + mtype: "" } member { name: "STRING" - mtype: "" + mtype: "" } member { name: "TFLITE" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.math.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.math.pbtxt index a8334fdd1d..f34e2c2aa5 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.math.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.math.pbtxt @@ -176,6 +176,26 @@ tf_module { name: "invert_permutation" argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "is_finite" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_inf" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_nan" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_non_decreasing" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_strictly_increasing" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "l2_normalize" argspec: "args=[\'x\', \'axis\', \'epsilon\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'1e-12\', \'None\', \'None\'], " @@ -298,7 +318,7 @@ tf_module { } member_method { name: "reduce_std" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_sum" @@ -306,7 +326,7 @@ tf_module { } member_method { name: "reduce_variance" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "rint" @@ -322,7 +342,7 @@ tf_module { } member_method { name: "scalar_mul" - argspec: "args=[\'scalar\', \'x\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'scalar\', \'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "segment_max" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-accuracy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-accuracy.pbtxt new file mode 100644 index 0000000000..f8e12f8817 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.metrics.Accuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-binary-accuracy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-binary-accuracy.pbtxt new file mode 100644 index 0000000000..b9bc6a716a --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-binary-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.metrics.BinaryAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\', \'threshold\'], varargs=None, keywords=None, defaults=[\'binary_accuracy\', \'None\', \'0.5\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-categorical-accuracy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-categorical-accuracy.pbtxt new file mode 100644 index 0000000000..0ef75d8756 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-categorical-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.metrics.CategoricalAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'categorical_accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-false-negatives.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-false-negatives.pbtxt new file mode 100644 index 0000000000..33226a2df6 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-false-negatives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.metrics.FalseNegatives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-false-positives.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-false-positives.pbtxt new file mode 100644 index 0000000000..9953162ea3 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-false-positives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.metrics.FalsePositives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-mean.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-mean.pbtxt new file mode 100644 index 0000000000..7fe6d6fda9 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-mean.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.metrics.Mean" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'mean\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'values\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-precision.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-precision.pbtxt new file mode 100644 index 0000000000..8c3271a109 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-precision.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.metrics.Precision" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-recall.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-recall.pbtxt new file mode 100644 index 0000000000..840a68bbc7 --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-recall.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.metrics.Recall" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-sparse-categorical-accuracy.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-sparse-categorical-accuracy.pbtxt new file mode 100644 index 0000000000..7bce43fbde --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-sparse-categorical-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.metrics.SparseCategoricalAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'sparse_categorical_accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-true-negatives.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-true-negatives.pbtxt new file mode 100644 index 0000000000..83cd5b736b --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-true-negatives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.metrics.TrueNegatives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.-true-positives.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-true-positives.pbtxt new file mode 100644 index 0000000000..5b2502eafe --- /dev/null +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.-true-positives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.metrics.TruePositives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v1/tensorflow.metrics.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.metrics.pbtxt index e9b996c9f5..f5c267a166 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.metrics.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.metrics.pbtxt @@ -1,5 +1,49 @@ path: "tensorflow.metrics" tf_module { + member { + name: "Accuracy" + mtype: "" + } + member { + name: "BinaryAccuracy" + mtype: "" + } + member { + name: "CategoricalAccuracy" + mtype: "" + } + member { + name: "FalseNegatives" + mtype: "" + } + member { + name: "FalsePositives" + mtype: "" + } + member { + name: "Mean" + mtype: "" + } + member { + name: "Precision" + mtype: "" + } + member { + name: "Recall" + mtype: "" + } + member { + name: "SparseCategoricalAccuracy" + mtype: "" + } + member { + name: "TrueNegatives" + mtype: "" + } + member { + name: "TruePositives" + mtype: "" + } member_method { name: "accuracy" argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.pbtxt index 93f2fda2ac..40e20f8c91 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.pbtxt @@ -44,6 +44,10 @@ tf_module { name: "bidirectional_dynamic_rnn" argspec: "args=[\'cell_fw\', \'cell_bw\', \'inputs\', \'sequence_length\', \'initial_state_fw\', \'initial_state_bw\', \'dtype\', \'parallel_iterations\', \'swap_memory\', \'time_major\', \'scope\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'False\', \'False\', \'None\'], " } + member_method { + name: "collapse_repeated" + argspec: "args=[\'labels\', \'seq_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "compute_accidental_hits" argspec: "args=[\'true_classes\', \'sampled_candidates\', \'num_true\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " @@ -72,6 +76,10 @@ tf_module { name: "conv3d" argspec: "args=[\'input\', \'filter\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NDHWC\', \'[1, 1, 1, 1, 1]\', \'None\'], " } + member_method { + name: "conv3d_backprop_filter" + argspec: "args=[\'input\', \'filter_sizes\', \'out_backprop\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NDHWC\', \'[1, 1, 1, 1, 1]\', \'None\'], " + } member_method { name: "conv3d_backprop_filter_v2" argspec: "args=[\'input\', \'filter_sizes\', \'out_backprop\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NDHWC\', \'[1, 1, 1, 1, 1]\', \'None\'], " @@ -104,6 +112,14 @@ tf_module { name: "ctc_loss" argspec: "args=[\'labels\', \'inputs\', \'sequence_length\', \'preprocess_collapse_repeated\', \'ctc_merge_repeated\', \'ignore_longer_outputs_than_inputs\', \'time_major\'], varargs=None, keywords=None, defaults=[\'False\', \'True\', \'False\', \'True\'], " } + member_method { + name: "ctc_loss_v2" + argspec: "args=[\'labels\', \'logits\', \'label_length\', \'logit_length\', \'logits_time_major\', \'unique\', \'blank_index\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'None\', \'None\', \'None\'], " + } + member_method { + name: "ctc_unique_labels" + argspec: "args=[\'labels\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "depth_to_space" argspec: "args=[\'input\', \'block_size\', \'name\', \'data_format\'], varargs=None, keywords=None, defaults=[\'None\', \'NHWC\'], " @@ -112,6 +128,14 @@ tf_module { name: "depthwise_conv2d" argspec: "args=[\'input\', \'filter\', \'strides\', \'padding\', \'rate\', \'name\', \'data_format\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } + member_method { + name: "depthwise_conv2d_backprop_filter" + argspec: "args=[\'input\', \'filter_sizes\', \'out_backprop\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \'[1, 1, 1, 1]\', \'None\'], " + } + member_method { + name: "depthwise_conv2d_backprop_input" + argspec: "args=[\'input_sizes\', \'filter\', \'out_backprop\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \'[1, 1, 1, 1]\', \'None\'], " + } member_method { name: "depthwise_conv2d_native" argspec: "args=[\'input\', \'filter\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \'[1, 1, 1, 1]\', \'None\'], " @@ -130,7 +154,7 @@ tf_module { } member_method { name: "dropout" - argspec: "args=[\'x\', \'keep_prob\', \'noise_shape\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'keep_prob\', \'noise_shape\', \'seed\', \'name\', \'rate\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " } member_method { name: "dynamic_rnn" @@ -302,7 +326,7 @@ tf_module { } member_method { name: "softmax_cross_entropy_with_logits_v2" - argspec: "args=[\'labels\', \'logits\', \'dim\', \'name\'], varargs=None, keywords=None, defaults=[\'-1\', \'None\'], " + argspec: "args=[\'labels\', \'logits\', \'axis\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "softplus" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-basic-l-s-t-m-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-basic-l-s-t-m-cell.pbtxt index 88b8f37c4f..f7f9978c06 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-basic-l-s-t-m-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-basic-l-s-t-m-cell.pbtxt @@ -107,6 +107,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-basic-r-n-n-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-basic-r-n-n-cell.pbtxt index a4483fefa2..f9e898484b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-basic-r-n-n-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-basic-r-n-n-cell.pbtxt @@ -107,6 +107,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-device-wrapper.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-device-wrapper.pbtxt index 381c4975d7..9e52a42526 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-device-wrapper.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-device-wrapper.pbtxt @@ -106,6 +106,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-dropout-wrapper.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-dropout-wrapper.pbtxt index 912365a28b..9836433d08 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-dropout-wrapper.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-dropout-wrapper.pbtxt @@ -110,6 +110,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-g-r-u-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-g-r-u-cell.pbtxt index a4bb3219c7..5fd9b329bd 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-g-r-u-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-g-r-u-cell.pbtxt @@ -107,6 +107,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-l-s-t-m-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-l-s-t-m-cell.pbtxt index 715bfd5fc7..76c8cff22b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-l-s-t-m-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-l-s-t-m-cell.pbtxt @@ -107,6 +107,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-multi-r-n-n-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-multi-r-n-n-cell.pbtxt index b66c0f89cc..f53567af52 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-multi-r-n-n-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-multi-r-n-n-cell.pbtxt @@ -106,6 +106,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt index faeb4f3513..d3b68e4f29 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt @@ -105,6 +105,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-residual-wrapper.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-residual-wrapper.pbtxt index caa2e60080..1f7840ab91 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-residual-wrapper.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.nn.rnn_cell.-residual-wrapper.pbtxt @@ -106,6 +106,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.pbtxt index f4dce81659..584c74f99d 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.pbtxt @@ -244,6 +244,10 @@ tf_module { name: "TensorShape" mtype: "" } + member { + name: "TensorSpec" + mtype: "" + } member { name: "TextLineReader" mtype: "" @@ -320,6 +324,10 @@ tf_module { name: "debugging" mtype: "" } + member { + name: "distribute" + mtype: "" + } member { name: "distributions" mtype: "" @@ -692,6 +700,10 @@ tf_module { name: "argmin" argspec: "args=[\'input\', \'axis\', \'name\', \'dimension\', \'output_type\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \"\"], " } + member_method { + name: "argsort" + argspec: "args=[\'values\', \'axis\', \'direction\', \'stable\', \'name\'], varargs=None, keywords=None, defaults=[\'-1\', \'ASCENDING\', \'False\', \'None\'], " + } member_method { name: "as_dtype" argspec: "args=[\'type_value\'], varargs=None, keywords=None, defaults=None" @@ -778,7 +790,7 @@ tf_module { } member_method { name: "assert_scalar" - argspec: "args=[\'tensor\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'tensor\', \'name\', \'message\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "assert_type" @@ -1040,10 +1052,18 @@ tf_module { name: "dimension_value" argspec: "args=[\'dimension\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "disable_eager_execution" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } member_method { name: "disable_resource_variables" argspec: "args=[], varargs=None, keywords=None, defaults=None" } + member_method { + name: "disable_v2_behavior" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } member_method { name: "disable_v2_tensorshape" argspec: "args=[], varargs=None, keywords=None, defaults=None" @@ -1084,6 +1104,10 @@ tf_module { name: "enable_resource_variables" argspec: "args=[], varargs=None, keywords=None, defaults=None" } + member_method { + name: "enable_v2_behavior" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } member_method { name: "enable_v2_tensorshape" argspec: "args=[], varargs=None, keywords=None, defaults=None" @@ -1232,6 +1256,10 @@ tf_module { name: "get_local_variable" argspec: "args=[\'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'collections\', \'caching_device\', \'partitioner\', \'validate_shape\', \'use_resource\', \'custom_getter\', \'constraint\', \'synchronization\', \'aggregation\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'False\', \'None\', \'None\', \'None\', \'True\', \'None\', \'None\', \'None\', \'VariableSynchronization.AUTO\', \'VariableAggregation.NONE\'], " } + member_method { + name: "get_logger" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } member_method { name: "get_seed" argspec: "args=[\'op_seed\'], varargs=None, keywords=None, defaults=None" @@ -1466,7 +1494,7 @@ tf_module { } member_method { name: "make_tensor_proto" - argspec: "args=[\'values\', \'dtype\', \'shape\', \'verify_shape\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\'], " + argspec: "args=[\'values\', \'dtype\', \'shape\', \'verify_shape\', \'allow_broadcast\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'False\'], " } member_method { name: "map_fn" @@ -1810,7 +1838,7 @@ tf_module { } member_method { name: "scalar_mul" - argspec: "args=[\'scalar\', \'x\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'scalar\', \'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "scan" @@ -1948,6 +1976,10 @@ tf_module { name: "slice" argspec: "args=[\'input_\', \'begin\', \'size\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "sort" + argspec: "args=[\'values\', \'axis\', \'direction\', \'name\'], varargs=None, keywords=None, defaults=[\'-1\', \'ASCENDING\', \'None\'], " + } member_method { name: "space_to_batch" argspec: "args=[\'input\', \'paddings\', \'block_size\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -1962,7 +1994,7 @@ tf_module { } member_method { name: "sparse_add" - argspec: "args=[\'a\', \'b\', \'thresh\'], varargs=None, keywords=None, defaults=[\'0\'], " + argspec: "args=[\'a\', \'b\', \'threshold\', \'thresh\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "sparse_concat" @@ -2156,6 +2188,18 @@ tf_module { name: "tanh" argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "tensor_scatter_add" + argspec: "args=[\'tensor\', \'indices\', \'updates\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "tensor_scatter_sub" + argspec: "args=[\'tensor\', \'indices\', \'updates\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "tensor_scatter_update" + argspec: "args=[\'tensor\', \'indices\', \'updates\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "tensordot" argspec: "args=[\'a\', \'b\', \'axes\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -2296,6 +2340,10 @@ tf_module { name: "while_loop" argspec: "args=[\'cond\', \'body\', \'loop_vars\', \'shape_invariants\', \'parallel_iterations\', \'back_prop\', \'swap_memory\', \'name\', \'maximum_iterations\', \'return_same_structure\'], varargs=None, keywords=None, defaults=[\'None\', \'10\', \'True\', \'False\', \'None\', \'None\', \'False\'], " } + member_method { + name: "wrap_function" + argspec: "args=[\'fn\', \'signature\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "write_file" argspec: "args=[\'filename\', \'contents\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.quantization.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.quantization.pbtxt index 2948b7318e..632c2f8f83 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.quantization.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.quantization.pbtxt @@ -34,7 +34,7 @@ tf_module { } member_method { name: "quantize_and_dequantize" - argspec: "args=[\'input\', \'input_min\', \'input_max\', \'signed_input\', \'num_bits\', \'range_given\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'8\', \'False\', \'None\'], " + argspec: "args=[\'input\', \'input_min\', \'input_max\', \'signed_input\', \'num_bits\', \'range_given\', \'round_mode\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'8\', \'False\', \'HALF_TO_EVEN\', \'None\'], " } member_method { name: "quantized_concat" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.random.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.random.pbtxt index 160c09798d..107534e086 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.random.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.random.pbtxt @@ -1,5 +1,9 @@ path: "tensorflow.random" tf_module { + member_method { + name: "categorical" + argspec: "args=[\'logits\', \'num_samples\', \'dtype\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } member_method { name: "gamma" argspec: "args=[\'shape\', \'alpha\', \'beta\', \'dtype\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\', \'None\'], " @@ -32,6 +36,10 @@ tf_module { name: "shuffle" argspec: "args=[\'value\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } + member_method { + name: "stateless_categorical" + argspec: "args=[\'logits\', \'num_samples\', \'seed\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " + } member_method { name: "stateless_multinomial" argspec: "args=[\'logits\', \'num_samples\', \'seed\', \'output_dtype\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.saved_model.-builder.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.saved_model.-builder.pbtxt index 67457de070..e4cc0061a9 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.saved_model.-builder.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.saved_model.-builder.pbtxt @@ -1,6 +1,7 @@ path: "tensorflow.saved_model.Builder" tf_class { is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.saved_model.builder.-saved-model-builder.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.saved_model.builder.-saved-model-builder.pbtxt index 83bd703540..44860b1172 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.saved_model.builder.-saved-model-builder.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.saved_model.builder.-saved-model-builder.pbtxt @@ -1,6 +1,7 @@ path: "tensorflow.saved_model.builder.SavedModelBuilder" tf_class { is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.saved_model.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.saved_model.pbtxt index 2055bfbf06..3929003fa1 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.saved_model.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.saved_model.pbtxt @@ -148,6 +148,10 @@ tf_module { name: "classification_signature_def" argspec: "args=[\'examples\', \'classes\', \'scores\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "contains_saved_model" + argspec: "args=[\'export_dir\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "get_tensor_from_tensor_info" argspec: "args=[\'tensor_info\', \'graph\', \'import_scope\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.sets.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.sets.pbtxt index 8a196b1a55..09d6f1424b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.sets.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.sets.pbtxt @@ -1,5 +1,13 @@ path: "tensorflow.sets" tf_module { + member_method { + name: "difference" + argspec: "args=[\'a\', \'b\', \'aminusb\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\', \'True\'], " + } + member_method { + name: "intersection" + argspec: "args=[\'a\', \'b\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\'], " + } member_method { name: "set_difference" argspec: "args=[\'a\', \'b\', \'aminusb\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\', \'True\'], " @@ -16,4 +24,12 @@ tf_module { name: "set_union" argspec: "args=[\'a\', \'b\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\'], " } + member_method { + name: "size" + argspec: "args=[\'a\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\'], " + } + member_method { + name: "union" + argspec: "args=[\'a\', \'b\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\'], " + } } diff --git a/tensorflow/tools/api/golden/v1/tensorflow.signal.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.signal.pbtxt index 2c50c41f18..ea717b4d71 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.signal.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.signal.pbtxt @@ -1,5 +1,9 @@ path: "tensorflow.signal" tf_module { + member_method { + name: "dct" + argspec: "args=[\'input\', \'type\', \'n\', \'axis\', \'norm\', \'name\'], varargs=None, keywords=None, defaults=[\'2\', \'None\', \'-1\', \'None\', \'None\'], " + } member_method { name: "fft" argspec: "args=[\'input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -24,6 +28,10 @@ tf_module { name: "hann_window" argspec: "args=[\'window_length\', \'periodic\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \"\", \'None\'], " } + member_method { + name: "idct" + argspec: "args=[\'input\', \'type\', \'n\', \'axis\', \'norm\', \'name\'], varargs=None, keywords=None, defaults=[\'2\', \'None\', \'-1\', \'None\', \'None\'], " + } member_method { name: "ifft" argspec: "args=[\'input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -44,6 +52,18 @@ tf_module { name: "inverse_stft_window_fn" argspec: "args=[\'frame_step\', \'forward_window_fn\', \'name\'], varargs=None, keywords=None, defaults=[\'\', \'None\'], " } + member_method { + name: "irfft" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "irfft2d" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "irfft3d" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "linear_to_mel_weight_matrix" argspec: "args=[\'num_mel_bins\', \'num_spectrogram_bins\', \'sample_rate\', \'lower_edge_hertz\', \'upper_edge_hertz\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'20\', \'129\', \'8000\', \'125.0\', \'3800.0\', \"\", \'None\'], " @@ -56,6 +76,18 @@ tf_module { name: "overlap_and_add" argspec: "args=[\'signal\', \'frame_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "rfft" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "rfft2d" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "rfft3d" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "stft" argspec: "args=[\'signals\', \'frame_length\', \'frame_step\', \'fft_length\', \'window_fn\', \'pad_end\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'\', \'False\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.sparse.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.sparse.pbtxt index 32bd8d5f8e..33e342bc75 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.sparse.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.sparse.pbtxt @@ -10,7 +10,7 @@ tf_module { } member_method { name: "add" - argspec: "args=[\'a\', \'b\', \'thresh\'], varargs=None, keywords=None, defaults=[\'0\'], " + argspec: "args=[\'a\', \'b\', \'threshold\', \'thresh\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "concat" @@ -112,6 +112,10 @@ tf_module { name: "softmax" argspec: "args=[\'sp_input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "sparse_dense_matmul" + argspec: "args=[\'sp_a\', \'b\', \'adjoint_a\', \'adjoint_b\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'False\', \'None\'], " + } member_method { name: "split" argspec: "args=[\'keyword_required\', \'sp_input\', \'num_split\', \'axis\', \'name\', \'split_dim\'], varargs=None, keywords=None, defaults=[\'KeywordRequired()\', \'None\', \'None\', \'None\', \'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.strings.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.strings.pbtxt index 03144cbe70..a1cd581a86 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.strings.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.strings.pbtxt @@ -52,6 +52,10 @@ tf_module { name: "to_number" argspec: "args=[\'string_tensor\', \'out_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " } + member_method { + name: "unicode_encode" + argspec: "args=[\'input\', \'output_encoding\', \'errors\', \'replacement_char\', \'name\'], varargs=None, keywords=None, defaults=[\'replace\', \'65533\', \'None\'], " + } member_method { name: "unicode_script" argspec: "args=[\'input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v1/tensorflow.test.-benchmark.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.test.-benchmark.pbtxt index df528e26b6..6fc489c860 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.test.-benchmark.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.test.-benchmark.pbtxt @@ -6,6 +6,10 @@ tf_class { member_method { name: "__init__" } + member_method { + name: "evaluate" + argspec: "args=[\'self\', \'tensors\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "is_abstract" argspec: "args=[\'cls\'], varargs=None, keywords=None, defaults=None" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.train.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.train.pbtxt index 877c55c6b3..bdb3ea2197 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.train.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.train.pbtxt @@ -396,6 +396,10 @@ tf_module { name: "piecewise_constant" argspec: "args=[\'x\', \'boundaries\', \'values\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "piecewise_constant_decay" + argspec: "args=[\'x\', \'boundaries\', \'values\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "polynomial_decay" argspec: "args=[\'learning_rate\', \'global_step\', \'decay_steps\', \'end_learning_rate\', \'power\', \'cycle\', \'name\'], varargs=None, keywords=None, defaults=[\'0.0001\', \'1.0\', \'False\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-conditional-accumulator-base.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-conditional-accumulator-base.pbtxt deleted file mode 100644 index c9a32c16b3..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.-conditional-accumulator-base.pbtxt +++ /dev/null @@ -1,29 +0,0 @@ -path: "tensorflow.ConditionalAccumulatorBase" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "accumulator_ref" - mtype: "" - } - member { - name: "dtype" - mtype: "" - } - member { - name: "name" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'dtype\', \'shape\', \'accumulator_ref\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "num_accumulated" - argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "set_global_step" - argspec: "args=[\'self\', \'new_global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-conditional-accumulator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-conditional-accumulator.pbtxt deleted file mode 100644 index 15e0ab76b6..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.-conditional-accumulator.pbtxt +++ /dev/null @@ -1,38 +0,0 @@ -path: "tensorflow.ConditionalAccumulator" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "accumulator_ref" - mtype: "" - } - member { - name: "dtype" - mtype: "" - } - member { - name: "name" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'dtype\', \'shape\', \'shared_name\', \'name\', \'reduction_type\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'conditional_accumulator\', \'MEAN\'], " - } - member_method { - name: "apply_grad" - argspec: "args=[\'self\', \'grad\', \'local_step\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'None\'], " - } - member_method { - name: "num_accumulated" - argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "set_global_step" - argspec: "args=[\'self\', \'new_global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "take_grad" - argspec: "args=[\'self\', \'num_required\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-config-proto.-experimental.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-config-proto.-experimental.pbtxt index f7491649c2..caa72fe5a6 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.-config-proto.-experimental.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.-config-proto.-experimental.pbtxt @@ -20,6 +20,12 @@ tf_proto { label: LABEL_OPTIONAL type: TYPE_INT32 } + field { + name: "use_numa_affinity" + number: 5 + label: LABEL_OPTIONAL + type: TYPE_BOOL + } reserved_range { start: 2 end: 3 diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-config-proto.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-config-proto.pbtxt index 53b532beab..b505d81350 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.-config-proto.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.-config-proto.pbtxt @@ -143,6 +143,12 @@ tf_proto { label: LABEL_OPTIONAL type: TYPE_INT32 } + field { + name: "use_numa_affinity" + number: 5 + label: LABEL_OPTIONAL + type: TYPE_BOOL + } reserved_range { start: 2 end: 3 diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-device-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-device-spec.pbtxt deleted file mode 100644 index 92e535c341..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.-device-spec.pbtxt +++ /dev/null @@ -1,37 +0,0 @@ -path: "tensorflow.DeviceSpec" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "job" - mtype: "" - } - member { - name: "replica" - mtype: "" - } - member { - name: "task" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'job\', \'replica\', \'task\', \'device_type\', \'device_index\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "from_string" - argspec: "args=[\'spec\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "merge_from" - argspec: "args=[\'self\', \'dev\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "parse_from_string" - argspec: "args=[\'self\', \'spec\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "to_string" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-dimension.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-dimension.pbtxt deleted file mode 100644 index a9ab27719b..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.-dimension.pbtxt +++ /dev/null @@ -1,25 +0,0 @@ -path: "tensorflow.Dimension" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "value" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'value\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "assert_is_compatible_with" - argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "is_compatible_with" - argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "merge_with" - argspec: "args=[\'self\', \'other\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-gradient-tape.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-gradient-tape.pbtxt index 0a16d6ab92..2299a009d3 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.-gradient-tape.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.-gradient-tape.pbtxt @@ -6,10 +6,18 @@ tf_class { name: "__init__" argspec: "args=[\'self\', \'persistent\', \'watch_accessed_variables\'], varargs=None, keywords=None, defaults=[\'False\', \'True\'], " } + member_method { + name: "batch_jacobian" + argspec: "args=[\'self\', \'target\', \'source\', \'unconnected_gradients\', \'parallel_iterations\', \'experimental_use_pfor\'], varargs=None, keywords=None, defaults=[\'UnconnectedGradients.NONE\', \'None\', \'True\'], " + } member_method { name: "gradient" argspec: "args=[\'self\', \'target\', \'sources\', \'output_gradients\', \'unconnected_gradients\'], varargs=None, keywords=None, defaults=[\'None\', \'UnconnectedGradients.NONE\'], " } + member_method { + name: "jacobian" + argspec: "args=[\'self\', \'target\', \'sources\', \'unconnected_gradients\', \'parallel_iterations\', \'experimental_use_pfor\'], varargs=None, keywords=None, defaults=[\'UnconnectedGradients.NONE\', \'None\', \'True\'], " + } member_method { name: "reset" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-graph-keys.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-graph-keys.pbtxt deleted file mode 100644 index ffe4790933..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.-graph-keys.pbtxt +++ /dev/null @@ -1,140 +0,0 @@ -path: "tensorflow.GraphKeys" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "ACTIVATIONS" - mtype: "" - } - member { - name: "ASSET_FILEPATHS" - mtype: "" - } - member { - name: "BIASES" - mtype: "" - } - member { - name: "CONCATENATED_VARIABLES" - mtype: "" - } - member { - name: "COND_CONTEXT" - mtype: "" - } - member { - name: "EVAL_STEP" - mtype: "" - } - member { - name: "GLOBAL_STEP" - mtype: "" - } - member { - name: "GLOBAL_VARIABLES" - mtype: "" - } - member { - name: "INIT_OP" - mtype: "" - } - member { - name: "LOCAL_INIT_OP" - mtype: "" - } - member { - name: "LOCAL_RESOURCES" - mtype: "" - } - member { - name: "LOCAL_VARIABLES" - mtype: "" - } - member { - name: "LOSSES" - mtype: "" - } - member { - name: "METRIC_VARIABLES" - mtype: "" - } - member { - name: "MODEL_VARIABLES" - mtype: "" - } - member { - name: "MOVING_AVERAGE_VARIABLES" - mtype: "" - } - member { - name: "QUEUE_RUNNERS" - mtype: "" - } - member { - name: "READY_FOR_LOCAL_INIT_OP" - mtype: "" - } - member { - name: "READY_OP" - mtype: "" - } - member { - name: "REGULARIZATION_LOSSES" - mtype: "" - } - member { - name: "RESOURCES" - mtype: "" - } - member { - name: "SAVEABLE_OBJECTS" - mtype: "" - } - member { - name: "SAVERS" - mtype: "" - } - member { - name: "SUMMARIES" - mtype: "" - } - member { - name: "SUMMARY_OP" - mtype: "" - } - member { - name: "TABLE_INITIALIZERS" - mtype: "" - } - member { - name: "TRAINABLE_RESOURCE_VARIABLES" - mtype: "" - } - member { - name: "TRAINABLE_VARIABLES" - mtype: "" - } - member { - name: "TRAIN_OP" - mtype: "" - } - member { - name: "UPDATE_OPS" - mtype: "" - } - member { - name: "VARIABLES" - mtype: "" - } - member { - name: "WEIGHTS" - mtype: "" - } - member { - name: "WHILE_CONTEXT" - mtype: "" - } - member_method { - name: "__init__" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-tensor-info.-coo-sparse.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-tensor-info.-coo-sparse.pbtxt deleted file mode 100644 index 0064c8460c..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.-tensor-info.-coo-sparse.pbtxt +++ /dev/null @@ -1,24 +0,0 @@ -path: "tensorflow.TensorInfo.CooSparse" -tf_proto { - descriptor { - name: "CooSparse" - field { - name: "values_tensor_name" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - field { - name: "indices_tensor_name" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - field { - name: "dense_shape_tensor_name" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-tensor-info.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-tensor-info.pbtxt deleted file mode 100644 index 63566c808e..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.-tensor-info.pbtxt +++ /dev/null @@ -1,59 +0,0 @@ -path: "tensorflow.TensorInfo" -tf_proto { - descriptor { - name: "TensorInfo" - field { - name: "name" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - oneof_index: 0 - } - field { - name: "coo_sparse" - number: 4 - label: LABEL_OPTIONAL - type: TYPE_MESSAGE - type_name: ".tensorflow.TensorInfo.CooSparse" - oneof_index: 0 - } - field { - name: "dtype" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_ENUM - type_name: ".tensorflow.DataType" - } - field { - name: "tensor_shape" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_MESSAGE - type_name: ".tensorflow.TensorShapeProto" - } - nested_type { - name: "CooSparse" - field { - name: "values_tensor_name" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - field { - name: "indices_tensor_name" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - field { - name: "dense_shape_tensor_name" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - } - oneof_decl { - name: "encoding" - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-tensor-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-tensor-spec.pbtxt new file mode 100644 index 0000000000..493dcba892 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.-tensor-spec.pbtxt @@ -0,0 +1,33 @@ +path: "tensorflow.TensorSpec" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "dtype" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "shape" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'shape\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "from_spec" + argspec: "args=[\'cls\', \'spec\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "from_tensor" + argspec: "args=[\'cls\', \'tensor\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_compatible_with" + argspec: "args=[\'self\', \'spec_or_tensor\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.app.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.app.pbtxt deleted file mode 100644 index 67e1b76cab..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.app.pbtxt +++ /dev/null @@ -1,7 +0,0 @@ -path: "tensorflow.app" -tf_module { - member_method { - name: "run" - argspec: "args=[\'main\', \'argv\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.-dataset.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.-dataset.pbtxt index 8b7f63e43e..ac8dd2de7f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.-dataset.pbtxt @@ -1,6 +1,6 @@ path: "tensorflow.data.Dataset" tf_class { - is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" @@ -16,7 +16,6 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } member_method { name: "apply" @@ -46,10 +45,6 @@ tf_class { name: "from_generator" argspec: "args=[\'generator\', \'output_types\', \'output_shapes\', \'args\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "from_sparse_tensor_slices" - argspec: "args=[\'sparse_tensor\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "from_tensor_slices" argspec: "args=[\'tensors\'], varargs=None, keywords=None, defaults=None" @@ -66,14 +61,6 @@ tf_class { name: "list_files" argspec: "args=[\'file_pattern\', \'shuffle\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "make_initializable_iterator" - argspec: "args=[\'self\', \'shared_name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "make_one_shot_iterator" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "map" argspec: "args=[\'self\', \'map_func\', \'num_parallel_calls\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -102,10 +89,6 @@ tf_class { name: "repeat" argspec: "args=[\'self\', \'count\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "shard" - argspec: "args=[\'self\', \'num_shards\', \'index\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "shuffle" argspec: "args=[\'self\', \'buffer_size\', \'seed\', \'reshuffle_each_iteration\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.-fixed-length-record-dataset.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.-fixed-length-record-dataset.pbtxt index 81358cecbc..f157351243 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.-fixed-length-record-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.-fixed-length-record-dataset.pbtxt @@ -1,8 +1,8 @@ path: "tensorflow.data.FixedLengthRecordDataset" tf_class { - is_instance: "" + is_instance: "" is_instance: "" - is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" @@ -48,10 +48,6 @@ tf_class { name: "from_generator" argspec: "args=[\'generator\', \'output_types\', \'output_shapes\', \'args\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "from_sparse_tensor_slices" - argspec: "args=[\'sparse_tensor\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "from_tensor_slices" argspec: "args=[\'tensors\'], varargs=None, keywords=None, defaults=None" @@ -68,14 +64,6 @@ tf_class { name: "list_files" argspec: "args=[\'file_pattern\', \'shuffle\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "make_initializable_iterator" - argspec: "args=[\'self\', \'shared_name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "make_one_shot_iterator" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "map" argspec: "args=[\'self\', \'map_func\', \'num_parallel_calls\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -104,10 +92,6 @@ tf_class { name: "repeat" argspec: "args=[\'self\', \'count\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "shard" - argspec: "args=[\'self\', \'num_shards\', \'index\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "shuffle" argspec: "args=[\'self\', \'buffer_size\', \'seed\', \'reshuffle_each_iteration\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.-iterator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.-iterator.pbtxt deleted file mode 100644 index 4f0147a523..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.-iterator.pbtxt +++ /dev/null @@ -1,46 +0,0 @@ -path: "tensorflow.data.Iterator" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "initializer" - mtype: "" - } - member { - name: "output_classes" - mtype: "" - } - member { - name: "output_shapes" - mtype: "" - } - member { - name: "output_types" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'iterator_resource\', \'initializer\', \'output_types\', \'output_shapes\', \'output_classes\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "from_string_handle" - argspec: "args=[\'string_handle\', \'output_types\', \'output_shapes\', \'output_classes\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "from_structure" - argspec: "args=[\'output_types\', \'output_shapes\', \'shared_name\', \'output_classes\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " - } - member_method { - name: "get_next" - argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "make_initializer" - argspec: "args=[\'self\', \'dataset\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "string_handle" - argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.-options.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.-options.pbtxt index 9d032d43de..72fc2c3a9e 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.-options.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.-options.pbtxt @@ -1,6 +1,7 @@ path: "tensorflow.data.Options" tf_class { is_instance: "" + is_instance: "" is_instance: "" member { name: "experimental_autotune" @@ -11,47 +12,19 @@ tf_class { mtype: "" } member { - name: "experimental_filter_fusion" - mtype: "" - } - member { - name: "experimental_hoist_random_uniform" - mtype: "" - } - member { - name: "experimental_map_and_batch_fusion" - mtype: "" - } - member { - name: "experimental_map_and_filter_fusion" - mtype: "" - } - member { - name: "experimental_map_fusion" - mtype: "" - } - member { - name: "experimental_map_parallelization" - mtype: "" - } - member { - name: "experimental_map_vectorization" - mtype: "" - } - member { - name: "experimental_noop_elimination" + name: "experimental_numa_aware" mtype: "" } member { - name: "experimental_numa_aware" + name: "experimental_optimization" mtype: "" } member { - name: "experimental_shuffle_and_repeat_fusion" + name: "experimental_stats" mtype: "" } member { - name: "experimental_stats" + name: "experimental_threading" mtype: "" } member_method { diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.-t-f-record-dataset.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.-t-f-record-dataset.pbtxt index 7b7a9ebaf0..690da98b1a 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.-t-f-record-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.-t-f-record-dataset.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.data.TFRecordDataset" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" @@ -47,10 +47,6 @@ tf_class { name: "from_generator" argspec: "args=[\'generator\', \'output_types\', \'output_shapes\', \'args\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "from_sparse_tensor_slices" - argspec: "args=[\'sparse_tensor\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "from_tensor_slices" argspec: "args=[\'tensors\'], varargs=None, keywords=None, defaults=None" @@ -67,14 +63,6 @@ tf_class { name: "list_files" argspec: "args=[\'file_pattern\', \'shuffle\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "make_initializable_iterator" - argspec: "args=[\'self\', \'shared_name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "make_one_shot_iterator" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "map" argspec: "args=[\'self\', \'map_func\', \'num_parallel_calls\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -103,10 +91,6 @@ tf_class { name: "repeat" argspec: "args=[\'self\', \'count\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "shard" - argspec: "args=[\'self\', \'num_shards\', \'index\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "shuffle" argspec: "args=[\'self\', \'buffer_size\', \'seed\', \'reshuffle_each_iteration\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.-text-line-dataset.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.-text-line-dataset.pbtxt index 1c305abf68..fe0bc1a4db 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.-text-line-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.-text-line-dataset.pbtxt @@ -1,8 +1,8 @@ path: "tensorflow.data.TextLineDataset" tf_class { - is_instance: "" + is_instance: "" is_instance: "" - is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" @@ -48,10 +48,6 @@ tf_class { name: "from_generator" argspec: "args=[\'generator\', \'output_types\', \'output_shapes\', \'args\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "from_sparse_tensor_slices" - argspec: "args=[\'sparse_tensor\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "from_tensor_slices" argspec: "args=[\'tensors\'], varargs=None, keywords=None, defaults=None" @@ -68,14 +64,6 @@ tf_class { name: "list_files" argspec: "args=[\'file_pattern\', \'shuffle\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "make_initializable_iterator" - argspec: "args=[\'self\', \'shared_name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "make_one_shot_iterator" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "map" argspec: "args=[\'self\', \'map_func\', \'num_parallel_calls\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -104,10 +92,6 @@ tf_class { name: "repeat" argspec: "args=[\'self\', \'count\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "shard" - argspec: "args=[\'self\', \'num_shards\', \'index\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "shuffle" argspec: "args=[\'self\', \'buffer_size\', \'seed\', \'reshuffle_each_iteration\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-csv-dataset.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-csv-dataset.pbtxt index 2520e28a3c..261129b132 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-csv-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-csv-dataset.pbtxt @@ -1,8 +1,8 @@ path: "tensorflow.data.experimental.CsvDataset" tf_class { - is_instance: "" + is_instance: "" is_instance: "" - is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" @@ -48,10 +48,6 @@ tf_class { name: "from_generator" argspec: "args=[\'generator\', \'output_types\', \'output_shapes\', \'args\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "from_sparse_tensor_slices" - argspec: "args=[\'sparse_tensor\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "from_tensor_slices" argspec: "args=[\'tensors\'], varargs=None, keywords=None, defaults=None" @@ -68,14 +64,6 @@ tf_class { name: "list_files" argspec: "args=[\'file_pattern\', \'shuffle\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "make_initializable_iterator" - argspec: "args=[\'self\', \'shared_name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "make_one_shot_iterator" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "map" argspec: "args=[\'self\', \'map_func\', \'num_parallel_calls\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -104,10 +92,6 @@ tf_class { name: "repeat" argspec: "args=[\'self\', \'count\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "shard" - argspec: "args=[\'self\', \'num_shards\', \'index\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "shuffle" argspec: "args=[\'self\', \'buffer_size\', \'seed\', \'reshuffle_each_iteration\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-optimization-options.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-optimization-options.pbtxt new file mode 100644 index 0000000000..9ca75828e5 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-optimization-options.pbtxt @@ -0,0 +1,46 @@ +path: "tensorflow.data.experimental.OptimizationOptions" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "filter_fusion" + mtype: "" + } + member { + name: "hoist_random_uniform" + mtype: "" + } + member { + name: "map_and_batch_fusion" + mtype: "" + } + member { + name: "map_and_filter_fusion" + mtype: "" + } + member { + name: "map_fusion" + mtype: "" + } + member { + name: "map_parallelization" + mtype: "" + } + member { + name: "map_vectorization" + mtype: "" + } + member { + name: "noop_elimination" + mtype: "" + } + member { + name: "shuffle_and_repeat_fusion" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-random-dataset.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-random-dataset.pbtxt index 1dd53b1eab..0b34bbc942 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-random-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-random-dataset.pbtxt @@ -1,8 +1,8 @@ path: "tensorflow.data.experimental.RandomDataset" tf_class { - is_instance: "" + is_instance: "" is_instance: "" - is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" @@ -48,10 +48,6 @@ tf_class { name: "from_generator" argspec: "args=[\'generator\', \'output_types\', \'output_shapes\', \'args\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "from_sparse_tensor_slices" - argspec: "args=[\'sparse_tensor\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "from_tensor_slices" argspec: "args=[\'tensors\'], varargs=None, keywords=None, defaults=None" @@ -68,14 +64,6 @@ tf_class { name: "list_files" argspec: "args=[\'file_pattern\', \'shuffle\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "make_initializable_iterator" - argspec: "args=[\'self\', \'shared_name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "make_one_shot_iterator" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "map" argspec: "args=[\'self\', \'map_func\', \'num_parallel_calls\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -104,10 +92,6 @@ tf_class { name: "repeat" argspec: "args=[\'self\', \'count\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "shard" - argspec: "args=[\'self\', \'num_shards\', \'index\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "shuffle" argspec: "args=[\'self\', \'buffer_size\', \'seed\', \'reshuffle_each_iteration\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-sql-dataset.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-sql-dataset.pbtxt index 8fdd9dc52e..0e61890eee 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-sql-dataset.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-sql-dataset.pbtxt @@ -1,8 +1,8 @@ path: "tensorflow.data.experimental.SqlDataset" tf_class { - is_instance: "" + is_instance: "" is_instance: "" - is_instance: "" + is_instance: "" is_instance: "" member { name: "output_classes" @@ -48,10 +48,6 @@ tf_class { name: "from_generator" argspec: "args=[\'generator\', \'output_types\', \'output_shapes\', \'args\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "from_sparse_tensor_slices" - argspec: "args=[\'sparse_tensor\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "from_tensor_slices" argspec: "args=[\'tensors\'], varargs=None, keywords=None, defaults=None" @@ -68,14 +64,6 @@ tf_class { name: "list_files" argspec: "args=[\'file_pattern\', \'shuffle\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "make_initializable_iterator" - argspec: "args=[\'self\', \'shared_name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "make_one_shot_iterator" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "map" argspec: "args=[\'self\', \'map_func\', \'num_parallel_calls\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -104,10 +92,6 @@ tf_class { name: "repeat" argspec: "args=[\'self\', \'count\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "shard" - argspec: "args=[\'self\', \'num_shards\', \'index\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "shuffle" argspec: "args=[\'self\', \'buffer_size\', \'seed\', \'reshuffle_each_iteration\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-stats-options.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-stats-options.pbtxt index f423eed42c..892f8c1fb8 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-stats-options.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-stats-options.pbtxt @@ -1,6 +1,7 @@ path: "tensorflow.data.experimental.StatsOptions" tf_class { is_instance: "" + is_instance: "" is_instance: "" member { name: "aggregator" @@ -20,6 +21,6 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'aggregator\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-threading-options.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-threading-options.pbtxt new file mode 100644 index 0000000000..5b5ebf1080 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.-threading-options.pbtxt @@ -0,0 +1,18 @@ +path: "tensorflow.data.experimental.ThreadingOptions" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "max_intra_op_parallelism" + mtype: "" + } + member { + name: "private_threadpool_size" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.pbtxt index 4c253bb8ad..f981b1af17 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.pbtxt @@ -12,6 +12,14 @@ tf_module { name: "CsvDataset" mtype: "" } + member { + name: "INFINITE_CARDINALITY" + mtype: "" + } + member { + name: "OptimizationOptions" + mtype: "" + } member { name: "Optional" mtype: "" @@ -40,6 +48,14 @@ tf_module { name: "TFRecordWriter" mtype: "" } + member { + name: "ThreadingOptions" + mtype: "" + } + member { + name: "UNKNOWN_CARDINALITY" + mtype: "" + } member_method { name: "Counter" argspec: "args=[\'start\', \'step\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0\', \'1\', \"\"], " @@ -48,6 +64,10 @@ tf_module { name: "bucket_by_sequence_length" argspec: "args=[\'element_length_func\', \'bucket_boundaries\', \'bucket_batch_sizes\', \'padded_shapes\', \'padding_values\', \'pad_to_bucket_boundary\', \'no_padding\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'False\'], " } + member_method { + name: "cardinality" + argspec: "args=[\'dataset\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "choose_from_datasets" argspec: "args=[\'datasets\', \'choice_dataset\'], varargs=None, keywords=None, defaults=None" @@ -64,6 +84,10 @@ tf_module { name: "enumerate_dataset" argspec: "args=[\'start\'], varargs=None, keywords=None, defaults=[\'0\'], " } + member_method { + name: "filter_for_shard" + argspec: "args=[\'num_shards\', \'shard_index\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "get_next_as_optional" argspec: "args=[\'iterator\'], varargs=None, keywords=None, defaults=None" @@ -90,7 +114,7 @@ tf_module { } member_method { name: "make_batched_features_dataset" - argspec: "args=[\'file_pattern\', \'batch_size\', \'features\', \'reader\', \'label_key\', \'reader_args\', \'num_epochs\', \'shuffle\', \'shuffle_buffer_size\', \'shuffle_seed\', \'prefetch_buffer_size\', \'reader_num_threads\', \'parser_num_threads\', \'sloppy_ordering\', \'drop_final_batch\'], varargs=None, keywords=None, defaults=[\"\", \'None\', \'None\', \'None\', \'True\', \'10000\', \'None\', \'-1\', \'1\', \'2\', \'False\', \'False\'], " + argspec: "args=[\'file_pattern\', \'batch_size\', \'features\', \'reader\', \'label_key\', \'reader_args\', \'num_epochs\', \'shuffle\', \'shuffle_buffer_size\', \'shuffle_seed\', \'prefetch_buffer_size\', \'reader_num_threads\', \'parser_num_threads\', \'sloppy_ordering\', \'drop_final_batch\'], varargs=None, keywords=None, defaults=[\"\", \'None\', \'None\', \'None\', \'True\', \'10000\', \'None\', \'-1\', \'1\', \'2\', \'False\', \'False\'], " } member_method { name: "make_csv_dataset" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.pbtxt index 509bbae833..4c3d6ddd85 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.pbtxt @@ -8,10 +8,6 @@ tf_module { name: "FixedLengthRecordDataset" mtype: "" } - member { - name: "Iterator" - mtype: "" - } member { name: "Options" mtype: "" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.debugging.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.debugging.pbtxt index ab6287f8cd..314aedda90 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.debugging.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.debugging.pbtxt @@ -6,19 +6,19 @@ tf_module { } member_method { name: "assert_all_finite" - argspec: "args=[\'t\', \'msg\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'x\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "assert_equal" - argspec: "args=[\'x\', \'y\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_greater" - argspec: "args=[\'x\', \'y\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_greater_equal" - argspec: "args=[\'x\', \'y\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_integer" @@ -26,35 +26,35 @@ tf_module { } member_method { name: "assert_less" - argspec: "args=[\'x\', \'y\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_less_equal" - argspec: "args=[\'x\', \'y\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_near" - argspec: "args=[\'x\', \'y\', \'rtol\', \'atol\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'rtol\', \'atol\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " } member_method { name: "assert_negative" - argspec: "args=[\'x\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_non_negative" - argspec: "args=[\'x\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_non_positive" - argspec: "args=[\'x\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_none_equal" - argspec: "args=[\'x\', \'y\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_positive" - argspec: "args=[\'x\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_proper_iterable" @@ -62,15 +62,15 @@ tf_module { } member_method { name: "assert_rank" - argspec: "args=[\'x\', \'rank\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'rank\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "assert_rank_at_least" - argspec: "args=[\'x\', \'rank\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'rank\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "assert_rank_in" - argspec: "args=[\'x\', \'ranks\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'ranks\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "assert_same_float_dtype" @@ -78,7 +78,7 @@ tf_module { } member_method { name: "assert_scalar" - argspec: "args=[\'tensor\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'tensor\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "assert_type" @@ -88,28 +88,8 @@ tf_module { name: "check_numerics" argspec: "args=[\'tensor\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "is_finite" - argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "is_inf" - argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "is_nan" - argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "is_non_decreasing" - argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } member_method { name: "is_numeric_tensor" argspec: "args=[\'tensor\'], varargs=None, keywords=None, defaults=None" } - member_method { - name: "is_strictly_increasing" - argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.distribute.-input-context.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-input-context.pbtxt new file mode 100644 index 0000000000..583cbc6654 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-input-context.pbtxt @@ -0,0 +1,25 @@ +path: "tensorflow.distribute.InputContext" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "input_pipeline_id" + mtype: "" + } + member { + name: "num_input_pipelines" + mtype: "" + } + member { + name: "num_replicas_in_sync" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'num_input_pipelines\', \'input_pipeline_id\', \'num_replicas_in_sync\'], varargs=None, keywords=None, defaults=[\'1\', \'0\', \'1\'], " + } + member_method { + name: "get_per_replica_batch_size" + argspec: "args=[\'self\', \'global_batch_size\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.distribute.-input-replication-mode.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-input-replication-mode.pbtxt new file mode 100644 index 0000000000..6a7a3a97aa --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-input-replication-mode.pbtxt @@ -0,0 +1,8 @@ +path: "tensorflow.distribute.InputReplicationMode" +tf_class { + is_instance: "" + member { + name: "PER_WORKER" + mtype: "" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.distribute.-reduce-op.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-reduce-op.pbtxt new file mode 100644 index 0000000000..4899f38cad --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-reduce-op.pbtxt @@ -0,0 +1,12 @@ +path: "tensorflow.distribute.ReduceOp" +tf_class { + is_instance: "" + member { + name: "MEAN" + mtype: "" + } + member { + name: "SUM" + mtype: "" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.distribute.-replica-context.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-replica-context.pbtxt new file mode 100644 index 0000000000..df707e8920 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-replica-context.pbtxt @@ -0,0 +1,33 @@ +path: "tensorflow.distribute.ReplicaContext" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "devices" + mtype: "" + } + member { + name: "distribution_strategy" + mtype: "" + } + member { + name: "num_replicas_in_sync" + mtype: "" + } + member { + name: "replica_id_in_sync_group" + mtype: "" + } + member { + name: "strategy" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'strategy\', \'replica_id_in_sync_group\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "merge_call" + argspec: "args=[\'self\', \'merge_fn\', \'args\', \'kwargs\'], varargs=None, keywords=None, defaults=[\'()\', \'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.distribute.-strategy-extended.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-strategy-extended.pbtxt new file mode 100644 index 0000000000..77706e5713 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-strategy-extended.pbtxt @@ -0,0 +1,81 @@ +path: "tensorflow.distribute.StrategyExtended" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "experimental_between_graph" + mtype: "" + } + member { + name: "experimental_require_static_shapes" + mtype: "" + } + member { + name: "experimental_should_init" + mtype: "" + } + member { + name: "parameter_devices" + mtype: "" + } + member { + name: "should_checkpoint" + mtype: "" + } + member { + name: "should_save_summary" + mtype: "" + } + member { + name: "worker_devices" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'container_strategy\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "batch_reduce_to" + argspec: "args=[\'self\', \'reduce_op\', \'value_destination_pairs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "broadcast_to" + argspec: "args=[\'self\', \'tensor\', \'destinations\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call_for_each_replica" + argspec: "args=[\'self\', \'fn\', \'args\', \'kwargs\'], varargs=None, keywords=None, defaults=[\'()\', \'None\'], " + } + member_method { + name: "colocate_vars_with" + argspec: "args=[\'self\', \'colocate_with_variable\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "experimental_run_steps_on_iterator" + argspec: "args=[\'self\', \'fn\', \'iterator\', \'iterations\', \'initial_loop_values\'], varargs=None, keywords=None, defaults=[\'1\', \'None\'], " + } + member_method { + name: "non_slot_devices" + argspec: "args=[\'self\', \'var_list\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "read_var" + argspec: "args=[\'self\', \'v\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reduce_to" + argspec: "args=[\'self\', \'reduce_op\', \'value\', \'destinations\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update" + argspec: "args=[\'self\', \'var\', \'fn\', \'args\', \'kwargs\', \'group\'], varargs=None, keywords=None, defaults=[\'()\', \'None\', \'True\'], " + } + member_method { + name: "update_non_slot" + argspec: "args=[\'self\', \'colocate_with\', \'fn\', \'args\', \'kwargs\', \'group\'], varargs=None, keywords=None, defaults=[\'()\', \'None\', \'True\'], " + } + member_method { + name: "value_container" + argspec: "args=[\'self\', \'value\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.distribute.-strategy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-strategy.pbtxt new file mode 100644 index 0000000000..9eb73d2c0d --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.distribute.-strategy.pbtxt @@ -0,0 +1,137 @@ +path: "tensorflow.distribute.Strategy" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "between_graph" + mtype: "" + } + member { + name: "extended" + mtype: "" + } + member { + name: "num_replicas_in_sync" + mtype: "" + } + member { + name: "parameter_devices" + mtype: "" + } + member { + name: "require_static_shapes" + mtype: "" + } + member { + name: "should_checkpoint" + mtype: "" + } + member { + name: "should_init" + mtype: "" + } + member { + name: "should_save_summary" + mtype: "" + } + member { + name: "worker_devices" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'extended\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "batch_reduce" + argspec: "args=[\'self\', \'aggregation\', \'value_destination_pairs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "broadcast" + argspec: "args=[\'self\', \'tensor\', \'destinations\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "call_for_each_replica" + argspec: "args=[\'self\', \'fn\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "colocate_vars_with" + argspec: "args=[\'self\', \'colocate_with_variable\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "configure" + argspec: "args=[\'self\', \'session_config\', \'cluster_spec\', \'task_type\', \'task_id\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + } + member_method { + name: "distribute_dataset" + argspec: "args=[\'self\', \'dataset_fn\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "experimental_finalize" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "experimental_initialize" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "finalize" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "group" + argspec: "args=[\'self\', \'value\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "initialize" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "make_dataset_iterator" + argspec: "args=[\'self\', \'dataset\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "make_input_fn_iterator" + argspec: "args=[\'self\', \'input_fn\', \'replication_mode\'], varargs=None, keywords=None, defaults=[\'InputReplicationMode.PER_WORKER\'], " + } + member_method { + name: "non_slot_devices" + argspec: "args=[\'self\', \'var_list\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "read_var" + argspec: "args=[\'self\', \'v\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reduce" + argspec: "args=[\'self\', \'reduce_op\', \'value\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "run_steps_on_dataset" + argspec: "args=[\'self\', \'fn\', \'iterator\', \'iterations\', \'initial_loop_values\'], varargs=None, keywords=None, defaults=[\'1\', \'None\'], " + } + member_method { + name: "scope" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "unwrap" + argspec: "args=[\'self\', \'value\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update" + argspec: "args=[\'self\', \'var\', \'fn\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "update_config_proto" + argspec: "args=[\'self\', \'config_proto\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_non_slot" + argspec: "args=[\'self\', \'colocate_with\', \'fn\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "value_container" + argspec: "args=[\'self\', \'value\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.distribute.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.distribute.pbtxt new file mode 100644 index 0000000000..4d833b54ba --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.distribute.pbtxt @@ -0,0 +1,47 @@ +path: "tensorflow.distribute" +tf_module { + member { + name: "InputContext" + mtype: "" + } + member { + name: "InputReplicationMode" + mtype: "" + } + member { + name: "ReduceOp" + mtype: "" + } + member { + name: "ReplicaContext" + mtype: "" + } + member { + name: "Strategy" + mtype: "" + } + member { + name: "StrategyExtended" + mtype: "" + } + member_method { + name: "get_loss_reduction" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_replica_context" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_strategy" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "has_strategy" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "in_cross_replica_context" + argspec: "args=[], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-classifier.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-classifier.pbtxt index 32b84e90ce..efe9e74697 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-classifier.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.BaselineClassifier" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -21,7 +21,7 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'model_dir\', \'n_classes\', \'weight_column\', \'label_vocabulary\', \'optimizer\', \'config\', \'loss_reduction\'], varargs=None, keywords=None, defaults=[\'None\', \'2\', \'None\', \'None\', \'Ftrl\', \'None\', \'weighted_sum\'], " + argspec: "args=[\'self\', \'model_dir\', \'n_classes\', \'weight_column\', \'label_vocabulary\', \'optimizer\', \'config\', \'loss_reduction\'], varargs=None, keywords=None, defaults=[\'None\', \'2\', \'None\', \'None\', \'Ftrl\', \'None\', \'weighted_sum_over_batch_size\'], " } member_method { name: "eval_dir" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-estimator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-estimator.pbtxt index 94933e7ffd..382d392f39 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-estimator.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.BaselineEstimator" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-regressor.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-regressor.pbtxt index db7776b5bf..a7300bf06b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-baseline-regressor.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.BaselineRegressor" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -21,7 +21,7 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'model_dir\', \'label_dimension\', \'weight_column\', \'optimizer\', \'config\', \'loss_reduction\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'Ftrl\', \'None\', \'weighted_sum\'], " + argspec: "args=[\'self\', \'model_dir\', \'label_dimension\', \'weight_column\', \'optimizer\', \'config\', \'loss_reduction\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'Ftrl\', \'None\', \'weighted_sum_over_batch_size\'], " } member_method { name: "eval_dir" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-boosted-trees-classifier.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-boosted-trees-classifier.pbtxt index d530c71482..e138ce936e 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-boosted-trees-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-boosted-trees-classifier.pbtxt @@ -3,6 +3,7 @@ tf_class { is_instance: "" is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -32,6 +33,10 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "experimental_feature_importances" argspec: "args=[\'self\', \'normalize\'], varargs=None, keywords=None, defaults=[\'False\'], " @@ -42,7 +47,7 @@ tf_class { } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-boosted-trees-regressor.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-boosted-trees-regressor.pbtxt index 4703c0f561..eae0a292a9 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-boosted-trees-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-boosted-trees-regressor.pbtxt @@ -3,6 +3,7 @@ tf_class { is_instance: "" is_instance: "" is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -32,6 +33,10 @@ tf_class { name: "evaluate" argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } + member_method { + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + } member_method { name: "experimental_feature_importances" argspec: "args=[\'self\', \'normalize\'], varargs=None, keywords=None, defaults=[\'False\'], " @@ -42,7 +47,7 @@ tf_class { } member_method { name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "export_savedmodel" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-classifier.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-classifier.pbtxt index ce6040d0f2..a540085aba 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-classifier.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.DNNClassifier" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -21,7 +21,7 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'hidden_units\', \'feature_columns\', \'model_dir\', \'n_classes\', \'weight_column\', \'label_vocabulary\', \'optimizer\', \'activation_fn\', \'dropout\', \'input_layer_partitioner\', \'config\', \'warm_start_from\', \'loss_reduction\', \'batch_norm\'], varargs=None, keywords=None, defaults=[\'None\', \'2\', \'None\', \'None\', \'Adagrad\', \'\', \'None\', \'None\', \'None\', \'None\', \'weighted_sum\', \'False\'], " + argspec: "args=[\'self\', \'hidden_units\', \'feature_columns\', \'model_dir\', \'n_classes\', \'weight_column\', \'label_vocabulary\', \'optimizer\', \'activation_fn\', \'dropout\', \'input_layer_partitioner\', \'config\', \'warm_start_from\', \'loss_reduction\', \'batch_norm\'], varargs=None, keywords=None, defaults=[\'None\', \'2\', \'None\', \'None\', \'Adagrad\', \'\', \'None\', \'None\', \'None\', \'None\', \'weighted_sum_over_batch_size\', \'False\'], " } member_method { name: "eval_dir" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-estimator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-estimator.pbtxt index 4635a1544c..d1b29d670a 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-estimator.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.DNNEstimator" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-classifier.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-classifier.pbtxt index e85007e16e..f6c3910a9f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-classifier.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.DNNLinearCombinedClassifier" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -21,7 +21,7 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'model_dir\', \'linear_feature_columns\', \'linear_optimizer\', \'dnn_feature_columns\', \'dnn_optimizer\', \'dnn_hidden_units\', \'dnn_activation_fn\', \'dnn_dropout\', \'n_classes\', \'weight_column\', \'label_vocabulary\', \'input_layer_partitioner\', \'config\', \'warm_start_from\', \'loss_reduction\', \'batch_norm\', \'linear_sparse_combiner\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'Ftrl\', \'None\', \'Adagrad\', \'None\', \'\', \'None\', \'2\', \'None\', \'None\', \'None\', \'None\', \'None\', \'weighted_sum\', \'False\', \'sum\'], " + argspec: "args=[\'self\', \'model_dir\', \'linear_feature_columns\', \'linear_optimizer\', \'dnn_feature_columns\', \'dnn_optimizer\', \'dnn_hidden_units\', \'dnn_activation_fn\', \'dnn_dropout\', \'n_classes\', \'weight_column\', \'label_vocabulary\', \'input_layer_partitioner\', \'config\', \'warm_start_from\', \'loss_reduction\', \'batch_norm\', \'linear_sparse_combiner\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'Ftrl\', \'None\', \'Adagrad\', \'None\', \'\', \'None\', \'2\', \'None\', \'None\', \'None\', \'None\', \'None\', \'weighted_sum_over_batch_size\', \'False\', \'sum\'], " } member_method { name: "eval_dir" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-estimator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-estimator.pbtxt index a23f5daeac..b78527279c 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-estimator.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.DNNLinearCombinedEstimator" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-regressor.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-regressor.pbtxt index 8a55bb835f..9133f0d3b2 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-linear-combined-regressor.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.DNNLinearCombinedRegressor" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -21,7 +21,7 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'model_dir\', \'linear_feature_columns\', \'linear_optimizer\', \'dnn_feature_columns\', \'dnn_optimizer\', \'dnn_hidden_units\', \'dnn_activation_fn\', \'dnn_dropout\', \'label_dimension\', \'weight_column\', \'input_layer_partitioner\', \'config\', \'warm_start_from\', \'loss_reduction\', \'batch_norm\', \'linear_sparse_combiner\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'Ftrl\', \'None\', \'Adagrad\', \'None\', \'\', \'None\', \'1\', \'None\', \'None\', \'None\', \'None\', \'weighted_sum\', \'False\', \'sum\'], " + argspec: "args=[\'self\', \'model_dir\', \'linear_feature_columns\', \'linear_optimizer\', \'dnn_feature_columns\', \'dnn_optimizer\', \'dnn_hidden_units\', \'dnn_activation_fn\', \'dnn_dropout\', \'label_dimension\', \'weight_column\', \'input_layer_partitioner\', \'config\', \'warm_start_from\', \'loss_reduction\', \'batch_norm\', \'linear_sparse_combiner\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'Ftrl\', \'None\', \'Adagrad\', \'None\', \'\', \'None\', \'1\', \'None\', \'None\', \'None\', \'None\', \'weighted_sum_over_batch_size\', \'False\', \'sum\'], " } member_method { name: "eval_dir" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-regressor.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-regressor.pbtxt index 2c4128ec48..a58d733302 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-d-n-n-regressor.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.DNNRegressor" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -21,7 +21,7 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'hidden_units\', \'feature_columns\', \'model_dir\', \'label_dimension\', \'weight_column\', \'optimizer\', \'activation_fn\', \'dropout\', \'input_layer_partitioner\', \'config\', \'warm_start_from\', \'loss_reduction\', \'batch_norm\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'Adagrad\', \'\', \'None\', \'None\', \'None\', \'None\', \'weighted_sum\', \'False\'], " + argspec: "args=[\'self\', \'hidden_units\', \'feature_columns\', \'model_dir\', \'label_dimension\', \'weight_column\', \'optimizer\', \'activation_fn\', \'dropout\', \'input_layer_partitioner\', \'config\', \'warm_start_from\', \'loss_reduction\', \'batch_norm\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'Adagrad\', \'\', \'None\', \'None\', \'None\', \'None\', \'weighted_sum_over_batch_size\', \'False\'], " } member_method { name: "eval_dir" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-estimator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-estimator.pbtxt index 9d270a87ab..a1f0e76c8b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-estimator.pbtxt @@ -1,6 +1,6 @@ path: "tensorflow.estimator.Estimator" tf_class { - is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -31,12 +31,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-classifier.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-classifier.pbtxt index 4acbff2cff..47de660a38 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-classifier.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-classifier.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.LinearClassifier" tf_class { is_instance: "" - is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-estimator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-estimator.pbtxt index 3d6b03098a..66a127606a 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-estimator.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-estimator.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.LinearEstimator" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-regressor.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-regressor.pbtxt index 0d1510e9ab..5c094fe131 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-regressor.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.-linear-regressor.pbtxt @@ -1,7 +1,7 @@ path: "tensorflow.estimator.LinearRegressor" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member { name: "config" @@ -21,7 +21,7 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'feature_columns\', \'model_dir\', \'label_dimension\', \'weight_column\', \'optimizer\', \'config\', \'partitioner\', \'warm_start_from\', \'loss_reduction\', \'sparse_combiner\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'Ftrl\', \'None\', \'None\', \'None\', \'weighted_sum\', \'sum\'], " + argspec: "args=[\'self\', \'feature_columns\', \'model_dir\', \'label_dimension\', \'weight_column\', \'optimizer\', \'config\', \'partitioner\', \'warm_start_from\', \'loss_reduction\', \'sparse_combiner\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'Ftrl\', \'None\', \'None\', \'None\', \'weighted_sum_over_batch_size\', \'sum\'], " } member_method { name: "eval_dir" @@ -32,12 +32,12 @@ tf_class { argspec: "args=[\'self\', \'input_fn\', \'steps\', \'hooks\', \'checkpoint_path\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "export_saved_model" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + name: "experimental_export_all_saved_models" + argspec: "args=[\'self\', \'export_dir_base\', \'input_receiver_fn_map\', \'assets_extra\', \'as_text\', \'checkpoint_path\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { - name: "export_savedmodel" - argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'strip_default_attrs\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'False\'], " + name: "export_saved_model" + argspec: "args=[\'self\', \'export_dir_base\', \'serving_input_receiver_fn\', \'assets_extra\', \'as_text\', \'checkpoint_path\', \'experimental_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\', \'infer\'], " } member_method { name: "get_variable_names" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.-in-memory-evaluator-hook.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.-in-memory-evaluator-hook.pbtxt new file mode 100644 index 0000000000..aba120218c --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.-in-memory-evaluator-hook.pbtxt @@ -0,0 +1,30 @@ +path: "tensorflow.estimator.experimental.InMemoryEvaluatorHook" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'estimator\', \'input_fn\', \'steps\', \'hooks\', \'name\', \'every_n_iter\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'100\'], " + } + member_method { + name: "after_create_session" + argspec: "args=[\'self\', \'session\', \'coord\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "after_run" + argspec: "args=[\'self\', \'run_context\', \'run_values\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "before_run" + argspec: "args=[\'self\', \'run_context\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "begin" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "end" + argspec: "args=[\'self\', \'session\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.pbtxt index cabca3e883..f0fd7ce782 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.pbtxt @@ -1,9 +1,17 @@ path: "tensorflow.estimator.experimental" tf_module { + member { + name: "InMemoryEvaluatorHook" + mtype: "" + } member { name: "LinearSDCA" mtype: "" } + member_method { + name: "build_raw_supervised_input_receiver_fn" + argspec: "args=[\'features\', \'labels\', \'default_batch_size\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "call_logit_fn" argspec: "args=[\'logit_fn\', \'features\', \'mode\', \'params\', \'config\'], varargs=None, keywords=None, defaults=None" @@ -20,6 +28,10 @@ tf_module { name: "make_early_stopping_hook" argspec: "args=[\'estimator\', \'should_stop_fn\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'60\', \'None\'], " } + member_method { + name: "make_stop_at_checkpoint_step_hook" + argspec: "args=[\'estimator\', \'last_step\', \'wait_after_file_check_secs\'], varargs=None, keywords=None, defaults=[\'30\'], " + } member_method { name: "stop_if_higher_hook" argspec: "args=[\'estimator\', \'metric_name\', \'threshold\', \'eval_dir\', \'min_steps\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'60\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.feature_column.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.feature_column.pbtxt index f06e798953..3aadd7dc34 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.feature_column.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.feature_column.pbtxt @@ -14,7 +14,7 @@ tf_module { } member_method { name: "categorical_column_with_vocabulary_file" - argspec: "args=[\'key\', \'vocabulary_file\', \'vocabulary_size\', \'num_oov_buckets\', \'default_value\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'None\', \"\"], " + argspec: "args=[\'key\', \'vocabulary_file\', \'vocabulary_size\', \'dtype\', \'default_value\', \'num_oov_buckets\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\', \'0\'], " } member_method { name: "categorical_column_with_vocabulary_list" @@ -32,14 +32,6 @@ tf_module { name: "indicator_column" argspec: "args=[\'categorical_column\'], varargs=None, keywords=None, defaults=None" } - member_method { - name: "input_layer" - argspec: "args=[\'features\', \'feature_columns\', \'weight_collections\', \'trainable\', \'cols_to_vars\', \'cols_to_output_tensors\'], varargs=None, keywords=None, defaults=[\'None\', \'True\', \'None\', \'None\'], " - } - member_method { - name: "linear_model" - argspec: "args=[\'features\', \'feature_columns\', \'units\', \'sparse_combiner\', \'weight_collections\', \'trainable\', \'cols_to_vars\'], varargs=None, keywords=None, defaults=[\'1\', \'sum\', \'None\', \'True\', \'None\'], " - } member_method { name: "make_parse_example_spec" argspec: "args=[\'feature_columns\'], varargs=None, keywords=None, defaults=None" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.gfile.-fast-g-file.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.gfile.-fast-g-file.pbtxt deleted file mode 100644 index eecfaffd0a..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.gfile.-fast-g-file.pbtxt +++ /dev/null @@ -1,58 +0,0 @@ -path: "tensorflow.gfile.FastGFile" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "mode" - mtype: "" - } - member { - name: "name" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'name\', \'mode\'], varargs=None, keywords=None, defaults=[\'r\'], " - } - member_method { - name: "close" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "flush" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "next" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "read" - argspec: "args=[\'self\', \'n\'], varargs=None, keywords=None, defaults=[\'-1\'], " - } - member_method { - name: "readline" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "readlines" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "seek" - argspec: "args=[\'self\', \'offset\', \'whence\', \'position\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'None\'], " - } - member_method { - name: "size" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "tell" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "write" - argspec: "args=[\'self\', \'file_content\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.gfile.-g-file.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.gfile.-g-file.pbtxt deleted file mode 100644 index 305251059d..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.gfile.-g-file.pbtxt +++ /dev/null @@ -1,58 +0,0 @@ -path: "tensorflow.gfile.GFile" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "mode" - mtype: "" - } - member { - name: "name" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'name\', \'mode\'], varargs=None, keywords=None, defaults=[\'r\'], " - } - member_method { - name: "close" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "flush" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "next" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "read" - argspec: "args=[\'self\', \'n\'], varargs=None, keywords=None, defaults=[\'-1\'], " - } - member_method { - name: "readline" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "readlines" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "seek" - argspec: "args=[\'self\', \'offset\', \'whence\', \'position\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'None\'], " - } - member_method { - name: "size" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "tell" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "write" - argspec: "args=[\'self\', \'file_content\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.gfile.-open.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.gfile.-open.pbtxt deleted file mode 100644 index 6e8894180a..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.gfile.-open.pbtxt +++ /dev/null @@ -1,58 +0,0 @@ -path: "tensorflow.gfile.Open" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "mode" - mtype: "" - } - member { - name: "name" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'name\', \'mode\'], varargs=None, keywords=None, defaults=[\'r\'], " - } - member_method { - name: "close" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "flush" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "next" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "read" - argspec: "args=[\'self\', \'n\'], varargs=None, keywords=None, defaults=[\'-1\'], " - } - member_method { - name: "readline" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "readlines" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "seek" - argspec: "args=[\'self\', \'offset\', \'whence\', \'position\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'None\'], " - } - member_method { - name: "size" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "tell" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "write" - argspec: "args=[\'self\', \'file_content\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.gfile.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.gfile.pbtxt deleted file mode 100644 index 65b55a8b7c..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.gfile.pbtxt +++ /dev/null @@ -1,63 +0,0 @@ -path: "tensorflow.gfile" -tf_module { - member { - name: "FastGFile" - mtype: "" - } - member { - name: "GFile" - mtype: "" - } - member { - name: "Open" - mtype: "" - } - member_method { - name: "Copy" - argspec: "args=[\'oldpath\', \'newpath\', \'overwrite\'], varargs=None, keywords=None, defaults=[\'False\'], " - } - member_method { - name: "DeleteRecursively" - argspec: "args=[\'dirname\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "Exists" - argspec: "args=[\'filename\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "Glob" - argspec: "args=[\'filename\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "IsDirectory" - argspec: "args=[\'dirname\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "ListDirectory" - argspec: "args=[\'dirname\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "MakeDirs" - argspec: "args=[\'dirname\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "MkDir" - argspec: "args=[\'dirname\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "Remove" - argspec: "args=[\'filename\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "Rename" - argspec: "args=[\'oldname\', \'newname\', \'overwrite\'], varargs=None, keywords=None, defaults=[\'False\'], " - } - member_method { - name: "Stat" - argspec: "args=[\'filename\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "Walk" - argspec: "args=[\'top\', \'in_order\'], varargs=None, keywords=None, defaults=[\'True\'], " - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.image.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.image.pbtxt index 0a231f1b65..3c6ed1cfb8 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.image.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.image.pbtxt @@ -38,7 +38,7 @@ tf_module { } member_method { name: "crop_and_resize" - argspec: "args=[\'image\', \'boxes\', \'box_ind\', \'crop_size\', \'method\', \'extrapolation_value\', \'name\'], varargs=None, keywords=None, defaults=[\'bilinear\', \'0\', \'None\'], " + argspec: "args=[\'image\', \'boxes\', \'box_indices\', \'crop_size\', \'method\', \'extrapolation_value\', \'name\'], varargs=None, keywords=None, defaults=[\'bilinear\', \'0\', \'None\'], " } member_method { name: "crop_to_bounding_box" @@ -86,7 +86,7 @@ tf_module { } member_method { name: "extract_image_patches" - argspec: "args=[\'images\', \'ksizes\', \'strides\', \'rates\', \'padding\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'images\', \'sizes\', \'strides\', \'rates\', \'padding\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "extract_jpeg_shape" @@ -173,16 +173,8 @@ tf_module { argspec: "args=[\'image\', \'lower\', \'upper\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { - name: "resize_area" - argspec: "args=[\'images\', \'size\', \'align_corners\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " - } - member_method { - name: "resize_bicubic" - argspec: "args=[\'images\', \'size\', \'align_corners\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " - } - member_method { - name: "resize_bilinear" - argspec: "args=[\'images\', \'size\', \'align_corners\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " + name: "resize" + argspec: "args=[\'images\', \'size\', \'method\', \'align_corners\', \'preserve_aspect_ratio\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'False\', \'False\', \'None\'], " } member_method { name: "resize_image_with_crop_or_pad" @@ -192,14 +184,6 @@ tf_module { name: "resize_image_with_pad" argspec: "args=[\'image\', \'target_height\', \'target_width\', \'method\'], varargs=None, keywords=None, defaults=[\'0\'], " } - member_method { - name: "resize_images" - argspec: "args=[\'images\', \'size\', \'method\', \'align_corners\', \'preserve_aspect_ratio\'], varargs=None, keywords=None, defaults=[\'0\', \'False\', \'False\'], " - } - member_method { - name: "resize_nearest_neighbor" - argspec: "args=[\'images\', \'size\', \'align_corners\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " - } member_method { name: "rgb_to_grayscale" argspec: "args=[\'images\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -222,7 +206,7 @@ tf_module { } member_method { name: "sample_distorted_bounding_box" - argspec: "args=[\'image_size\', \'bounding_boxes\', \'seed\', \'seed2\', \'min_object_covered\', \'aspect_ratio_range\', \'area_range\', \'max_attempts\', \'use_image_if_no_bounding_boxes\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'0.1\', \'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'image_size\', \'bounding_boxes\', \'seed\', \'min_object_covered\', \'aspect_ratio_range\', \'area_range\', \'max_attempts\', \'use_image_if_no_bounding_boxes\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'0.1\', \'None\', \'None\', \'None\', \'None\', \'None\'], " } member_method { name: "sobel_edges" @@ -241,8 +225,8 @@ tf_module { argspec: "args=[\'images\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { - name: "transpose_image" - argspec: "args=[\'image\'], varargs=None, keywords=None, defaults=None" + name: "transpose" + argspec: "args=[\'image\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "yiq_to_rgb" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.io.gfile.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.io.gfile.pbtxt new file mode 100644 index 0000000000..93d9b0fd75 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.io.gfile.pbtxt @@ -0,0 +1,51 @@ +path: "tensorflow.io.gfile" +tf_module { + member_method { + name: "copy" + argspec: "args=[\'src\', \'dst\', \'overwrite\'], varargs=None, keywords=None, defaults=[\'False\'], " + } + member_method { + name: "exists" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "glob" + argspec: "args=[\'pattern\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "isdir" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "listdir" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "makedirs" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "mkdir" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "remove" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "rename" + argspec: "args=[\'src\', \'dst\', \'overwrite\'], varargs=None, keywords=None, defaults=[\'False\'], " + } + member_method { + name: "rmtree" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "stat" + argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "walk" + argspec: "args=[\'top\', \'topdown\', \'onerror\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.io.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.io.pbtxt index 64b63ed1a4..8906329742 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.io.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.io.pbtxt @@ -44,22 +44,50 @@ tf_module { name: "VarLenFeature" mtype: "" } + member { + name: "gfile" + mtype: "" + } + member_method { + name: "decode_and_crop_jpeg" + argspec: "args=[\'contents\', \'crop_window\', \'channels\', \'ratio\', \'fancy_upscaling\', \'try_recover_truncated\', \'acceptable_fraction\', \'dct_method\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'1\', \'True\', \'False\', \'1\', \'\', \'None\'], " + } member_method { name: "decode_base64" argspec: "args=[\'input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "decode_bmp" + argspec: "args=[\'contents\', \'channels\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'None\'], " + } member_method { name: "decode_compressed" argspec: "args=[\'bytes\', \'compression_type\', \'name\'], varargs=None, keywords=None, defaults=[\'\', \'None\'], " } member_method { name: "decode_csv" - argspec: "args=[\'records\', \'record_defaults\', \'field_delim\', \'use_quote_delim\', \'name\', \'na_value\', \'select_cols\'], varargs=None, keywords=None, defaults=[\',\', \'True\', \'None\', \'\', \'None\'], " + argspec: "args=[\'records\', \'record_defaults\', \'field_delim\', \'use_quote_delim\', \'na_value\', \'select_cols\', \'name\'], varargs=None, keywords=None, defaults=[\',\', \'True\', \'\', \'None\', \'None\'], " + } + member_method { + name: "decode_gif" + argspec: "args=[\'contents\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "decode_image" + argspec: "args=[\'contents\', \'channels\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\'], " + } + member_method { + name: "decode_jpeg" + argspec: "args=[\'contents\', \'channels\', \'ratio\', \'fancy_upscaling\', \'try_recover_truncated\', \'acceptable_fraction\', \'dct_method\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'1\', \'True\', \'False\', \'1\', \'\', \'None\'], " } member_method { name: "decode_json_example" argspec: "args=[\'json_examples\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "decode_png" + argspec: "args=[\'contents\', \'channels\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \"\", \'None\'], " + } member_method { name: "decode_raw" argspec: "args=[\'bytes\', \'out_type\', \'little_endian\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'None\'], " @@ -72,6 +100,18 @@ tf_module { name: "encode_base64" argspec: "args=[\'input\', \'pad\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " } + member_method { + name: "encode_jpeg" + argspec: "args=[\'image\', \'format\', \'quality\', \'progressive\', \'optimize_size\', \'chroma_downsampling\', \'density_unit\', \'x_density\', \'y_density\', \'xmp_metadata\', \'name\'], varargs=None, keywords=None, defaults=[\'\', \'95\', \'False\', \'False\', \'True\', \'in\', \'300\', \'300\', \'\', \'None\'], " + } + member_method { + name: "extract_jpeg_shape" + argspec: "args=[\'contents\', \'output_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " + } + member_method { + name: "is_jpeg" + argspec: "args=[\'contents\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "match_filenames_once" argspec: "args=[\'pattern\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -82,7 +122,7 @@ tf_module { } member_method { name: "parse_example" - argspec: "args=[\'serialized\', \'features\', \'name\', \'example_names\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'serialized\', \'features\', \'example_names\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "parse_sequence_example" @@ -90,7 +130,7 @@ tf_module { } member_method { name: "parse_single_example" - argspec: "args=[\'serialized\', \'features\', \'name\', \'example_names\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'serialized\', \'features\', \'example_names\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "parse_single_sequence_example" @@ -106,20 +146,16 @@ tf_module { } member_method { name: "serialize_many_sparse" - argspec: "args=[\'sp_input\', \'name\', \'out_type\'], varargs=None, keywords=None, defaults=[\'None\', \"\"], " + argspec: "args=[\'sp_input\', \'out_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " } member_method { name: "serialize_sparse" - argspec: "args=[\'sp_input\', \'name\', \'out_type\'], varargs=None, keywords=None, defaults=[\'None\', \"\"], " + argspec: "args=[\'sp_input\', \'out_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " } member_method { name: "serialize_tensor" argspec: "args=[\'tensor\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "tf_record_iterator" - argspec: "args=[\'path\', \'options\'], varargs=None, keywords=None, defaults=[\'None\'], " - } member_method { name: "write_file" argspec: "args=[\'filename\', \'contents\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.-model.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.-model.pbtxt index 8ccba990bd..a3254cbd94 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.-model.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.-model.pbtxt @@ -41,6 +41,14 @@ tf_class { name: "losses" mtype: "" } + member { + name: "metrics" + mtype: "" + } + member { + name: "metrics_names" + mtype: "" + } member { name: "name" mtype: "" @@ -69,6 +77,10 @@ tf_class { name: "output_shape" mtype: "" } + member { + name: "run_eagerly" + mtype: "" + } member { name: "state_updates" mtype: "" @@ -105,13 +117,17 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "add_variable" - argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\', \'None\'], " + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" } member_method { name: "add_weight" @@ -225,6 +241,10 @@ tf_class { name: "predict_on_batch" argspec: "args=[\'self\', \'x\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "reset_metrics" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "reset_states" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" @@ -247,7 +267,7 @@ tf_class { } member_method { name: "test_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " } member_method { name: "to_json" @@ -259,6 +279,6 @@ tf_class { } member_method { name: "train_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\'], " } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.-sequential.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.-sequential.pbtxt index 27aa91a645..b70e9ee98d 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.-sequential.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.-sequential.pbtxt @@ -42,6 +42,14 @@ tf_class { name: "losses" mtype: "" } + member { + name: "metrics" + mtype: "" + } + member { + name: "metrics_names" + mtype: "" + } member { name: "name" mtype: "" @@ -70,6 +78,10 @@ tf_class { name: "output_shape" mtype: "" } + member { + name: "run_eagerly" + mtype: "" + } member { name: "state_updates" mtype: "" @@ -110,13 +122,17 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "add_variable" - argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\', \'None\'], " + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" } member_method { name: "add_weight" @@ -242,6 +258,10 @@ tf_class { name: "predict_proba" argspec: "args=[\'self\', \'x\', \'batch_size\', \'verbose\'], varargs=None, keywords=None, defaults=[\'32\', \'0\'], " } + member_method { + name: "reset_metrics" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "reset_states" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" @@ -264,7 +284,7 @@ tf_class { } member_method { name: "test_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " } member_method { name: "to_json" @@ -276,6 +296,6 @@ tf_class { } member_method { name: "train_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\'], " } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.backend.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.backend.pbtxt index b30778b2a0..d200d3d26d 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.backend.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.backend.pbtxt @@ -394,7 +394,7 @@ tf_module { } member_method { name: "rnn" - argspec: "args=[\'step_function\', \'inputs\', \'initial_states\', \'go_backwards\', \'mask\', \'constants\', \'unroll\', \'input_length\', \'time_major\'], varargs=None, keywords=None, defaults=[\'False\', \'None\', \'None\', \'False\', \'None\', \'False\'], " + argspec: "args=[\'step_function\', \'inputs\', \'initial_states\', \'go_backwards\', \'mask\', \'constants\', \'unroll\', \'input_length\', \'time_major\', \'zero_output_for_mask\'], varargs=None, keywords=None, defaults=[\'False\', \'None\', \'None\', \'False\', \'None\', \'False\', \'False\'], " } member_method { name: "round" @@ -508,6 +508,10 @@ tf_module { name: "temporal_padding" argspec: "args=[\'x\', \'padding\'], varargs=None, keywords=None, defaults=[\'(1, 1)\'], " } + member_method { + name: "tile" + argspec: "args=[\'x\', \'n\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "to_dense" argspec: "args=[\'tensor\'], varargs=None, keywords=None, defaults=None" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.experimental.-peephole-l-s-t-m-cell.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.experimental.-peephole-l-s-t-m-cell.pbtxt index db69e25c5b..1d814b2c8b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.experimental.-peephole-l-s-t-m-cell.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.experimental.-peephole-l-s-t-m-cell.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-activation.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-activation.pbtxt index 5510465d7b..b84629540e 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-activation.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-activation.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-activity-regularization.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-activity-regularization.pbtxt index 38ec8a0aff..5918a13ad8 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-activity-regularization.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-activity-regularization.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-add.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-add.pbtxt index 41cb8e30bf..599da06427 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-add.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-add.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-alpha-dropout.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-alpha-dropout.pbtxt index 9a7aaa8e96..f9ff1538c8 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-alpha-dropout.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-alpha-dropout.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling1-d.pbtxt index 014f5828fa..723fc9cdb0 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling2-d.pbtxt index cc303bf7b9..957ce2f0ce 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling3-d.pbtxt index 628447ce35..a52c0af681 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average-pooling3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average.pbtxt index f03c986c22..a004db62dd 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-average.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool1-d.pbtxt index a6e4856de9..44f83d1387 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool2-d.pbtxt index a01eaf8a12..8378faf718 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool3-d.pbtxt index 0d6698f2ef..9d5655c964 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-avg-pool3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-batch-normalization.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-batch-normalization.pbtxt index f1b23be48f..5da7926812 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-batch-normalization.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-batch-normalization.pbtxt @@ -1,6 +1,6 @@ path: "tensorflow.keras.layers.BatchNormalization" tf_class { - is_instance: "" + is_instance: "" is_instance: "" is_instance: "" is_instance: "" @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-bidirectional.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-bidirectional.pbtxt index 0672cd5b7b..d37a6b4710 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-bidirectional.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-bidirectional.pbtxt @@ -97,6 +97,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-concatenate.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-concatenate.pbtxt index b25ae1e82e..1ad7a91be0 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-concatenate.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-concatenate.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv-l-s-t-m2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv-l-s-t-m2-d.pbtxt index bb1918eba6..cb9abc2539 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv-l-s-t-m2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv-l-s-t-m2-d.pbtxt @@ -178,6 +178,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv1-d.pbtxt index 16e0fd5a31..47dba1d81f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv2-d-transpose.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv2-d-transpose.pbtxt index 381839d6de..fd64941896 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv2-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv2-d-transpose.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv2-d.pbtxt index 543bae6fa9..1b1425d531 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv3-d-transpose.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv3-d-transpose.pbtxt index 2933f9f4b3..1741063fe8 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv3-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv3-d-transpose.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv3-d.pbtxt index 072943dc2c..50feb4f458 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-conv3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution1-d.pbtxt index 222a1ef4fc..faaa535df9 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution2-d-transpose.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution2-d-transpose.pbtxt index 9c9c7461c8..4079329d1e 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution2-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution2-d-transpose.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution2-d.pbtxt index f939067178..32e56696e1 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution3-d-transpose.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution3-d-transpose.pbtxt index 44ca598724..381abe7340 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution3-d-transpose.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution3-d-transpose.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution3-d.pbtxt index 471b18ef85..b3e4bf9689 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-convolution3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping1-d.pbtxt index 0f250a09b7..7aeff8003c 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping1-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping2-d.pbtxt index f52128483c..a1728d9d4f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping2-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping3-d.pbtxt index 98daf3bab1..8d8fd142cc 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cropping3-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt index b207c68000..7758209adf 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cu-d-n-n-g-r-u.pbtxt @@ -98,6 +98,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt index 2d7a09ceda..7c463ff125 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-cu-d-n-n-l-s-t-m.pbtxt @@ -98,6 +98,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-multi-r-n-n-cell.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dense-features.pbtxt similarity index 77% rename from tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-multi-r-n-n-cell.pbtxt rename to tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dense-features.pbtxt index b66c0f89cc..0781a93bd5 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-multi-r-n-n-cell.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dense-features.pbtxt @@ -1,8 +1,6 @@ -path: "tensorflow.nn.rnn_cell.MultiRNNCell" +path: "tensorflow.keras.layers.DenseFeatures" tf_class { - is_instance: "" - is_instance: "" - is_instance: "" + is_instance: "" is_instance: "" is_instance: "" is_instance: "" @@ -14,10 +12,6 @@ tf_class { name: "dtype" mtype: "" } - member { - name: "graph" - mtype: "" - } member { name: "inbound_nodes" mtype: "" @@ -66,18 +60,6 @@ tf_class { name: "output_shape" mtype: "" } - member { - name: "output_size" - mtype: "" - } - member { - name: "scope_name" - mtype: "" - } - member { - name: "state_size" - mtype: "" - } member { name: "trainable_variables" mtype: "" @@ -100,12 +82,16 @@ tf_class { } member_method { name: "__init__" - argspec: "args=[\'self\', \'cells\', \'state_is_tuple\'], varargs=None, keywords=None, defaults=[\'True\'], " + argspec: "args=[\'self\', \'feature_columns\', \'trainable\', \'name\'], varargs=None, keywords=kwargs, defaults=[\'True\', \'None\'], " } member_method { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -116,7 +102,7 @@ tf_class { } member_method { name: "add_weight" - argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\', \'use_resource\', \'synchronization\', \'aggregation\', \'partitioner\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'None\', \'VariableSynchronization.AUTO\', \'VariableAggregation.NONE\', \'None\'], " + argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\', \'partitioner\', \'use_resource\', \'synchronization\', \'aggregation\'], varargs=None, keywords=kwargs, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'None\', \'None\', \'VariableSynchronization.AUTO\', \'VariableAggregation.NONE\'], " } member_method { name: "apply" @@ -128,7 +114,7 @@ tf_class { } member_method { name: "call" - argspec: "args=[\'self\', \'inputs\', \'state\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'self\', \'features\', \'cols_to_output_tensors\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "compute_mask" @@ -150,10 +136,6 @@ tf_class { name: "get_config" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } - member_method { - name: "get_initial_state" - argspec: "args=[\'self\', \'inputs\', \'batch_size\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " - } member_method { name: "get_input_at" argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" @@ -194,8 +176,4 @@ tf_class { name: "set_weights" argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" } - member_method { - name: "zero_state" - argspec: "args=[\'self\', \'batch_size\', \'dtype\'], varargs=None, keywords=None, defaults=None" - } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dense.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dense.pbtxt index 3ac3825759..4960d0264e 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dense.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dense.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-depthwise-conv2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-depthwise-conv2-d.pbtxt index 280ec8c25f..8fad7535f8 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-depthwise-conv2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-depthwise-conv2-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dot.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dot.pbtxt index 560f66f9c7..5b425f2d4d 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dot.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dot.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dropout.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dropout.pbtxt index c0543529c3..f6c4d0a438 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dropout.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-dropout.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-e-l-u.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-e-l-u.pbtxt index 04eb2824b9..82b761fc17 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-e-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-e-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-embedding.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-embedding.pbtxt index f400432915..c9ff323877 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-embedding.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-embedding.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-flatten.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-flatten.pbtxt index ab176b441a..9b4165d4cb 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-flatten.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-flatten.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-g-r-u-cell.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-g-r-u-cell.pbtxt index c3895a0ac1..f225f7c430 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-g-r-u-cell.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-g-r-u-cell.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-g-r-u.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-g-r-u.pbtxt index 9e24bb8ae6..855d001700 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-g-r-u.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-g-r-u.pbtxt @@ -161,6 +161,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-gaussian-dropout.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-gaussian-dropout.pbtxt index 55e0d7ef02..2c404c99cd 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-gaussian-dropout.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-gaussian-dropout.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-gaussian-noise.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-gaussian-noise.pbtxt index 38fbff5e4a..6f109d59d0 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-gaussian-noise.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-gaussian-noise.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling1-d.pbtxt index a8094c0bde..69f8a9031d 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling2-d.pbtxt index 929f48df23..4299f765e5 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling3-d.pbtxt index 2e6d59337f..9153a1a240 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-average-pooling3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool1-d.pbtxt index 3ebe162f57..625e81fd23 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool2-d.pbtxt index 4e3e258430..2fc769742c 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool3-d.pbtxt index fb9166316f..e307a65c7c 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-avg-pool3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool1-d.pbtxt index c0a53b847b..4394ad0364 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool2-d.pbtxt index 87b7f6797a..050ed39fe9 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool3-d.pbtxt index 98bf96fa0c..436191821e 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pool3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling1-d.pbtxt index ff6c6f3ec4..4ba540aa6a 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling2-d.pbtxt index c9d4158d1c..a2e9322cb3 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling3-d.pbtxt index 9953102ff9..5d16a57fc1 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-global-max-pooling3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-input-layer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-input-layer.pbtxt index 2617f5a95f..9dd29c1251 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-input-layer.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-input-layer.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-input-spec.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-input-spec.pbtxt index 5fd0a47a68..bc3ceb67a4 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-input-spec.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-input-spec.pbtxt @@ -1,6 +1,6 @@ path: "tensorflow.keras.layers.InputSpec" tf_class { - is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-l-s-t-m-cell.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-l-s-t-m-cell.pbtxt index e9f6ef45aa..0045d5775e 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-l-s-t-m-cell.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-l-s-t-m-cell.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-l-s-t-m.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-l-s-t-m.pbtxt index 1b1ccbe118..529c750f98 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-l-s-t-m.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-l-s-t-m.pbtxt @@ -161,6 +161,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-lambda.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-lambda.pbtxt index 2e0b6bac24..d4d1bc6b6b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-lambda.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-lambda.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-layer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-layer.pbtxt index 1e93d1118a..e1f5491180 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-layer.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-layer.pbtxt @@ -87,6 +87,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-leaky-re-l-u.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-leaky-re-l-u.pbtxt index bfd36012a7..9b69d9a944 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-leaky-re-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-leaky-re-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-linear-model.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-linear-model.pbtxt new file mode 100644 index 0000000000..2b66576c96 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-linear-model.pbtxt @@ -0,0 +1,289 @@ +path: "tensorflow.keras.layers.LinearModel" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "bias" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "input_spec" + mtype: "" + } + member { + name: "layers" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "metrics" + mtype: "" + } + member { + name: "metrics_names" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "run_eagerly" + mtype: "" + } + member { + name: "state_updates" + mtype: "" + } + member { + name: "stateful" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'feature_columns\', \'units\', \'sparse_combiner\', \'trainable\', \'name\'], varargs=None, keywords=kwargs, defaults=[\'1\', \'sum\', \'True\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\', \'partitioner\', \'use_resource\', \'synchronization\', \'aggregation\'], varargs=None, keywords=kwargs, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'None\', \'None\', \'VariableSynchronization.AUTO\', \'VariableAggregation.NONE\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'features\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "compile" + argspec: "args=[\'self\', \'optimizer\', \'loss\', \'metrics\', \'loss_weights\', \'sample_weight_mode\', \'weighted_metrics\', \'target_tensors\', \'distribute\'], varargs=None, keywords=kwargs, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'None\', \'None\'], " + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "evaluate" + argspec: "args=[\'self\', \'x\', \'y\', \'batch_size\', \'verbose\', \'sample_weight\', \'steps\', \'max_queue_size\', \'workers\', \'use_multiprocessing\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'1\', \'None\', \'None\', \'10\', \'1\', \'False\'], " + } + member_method { + name: "evaluate_generator" + argspec: "args=[\'self\', \'generator\', \'steps\', \'max_queue_size\', \'workers\', \'use_multiprocessing\', \'verbose\'], varargs=None, keywords=None, defaults=[\'None\', \'10\', \'1\', \'False\', \'0\'], " + } + member_method { + name: "fit" + argspec: "args=[\'self\', \'x\', \'y\', \'batch_size\', \'epochs\', \'verbose\', \'callbacks\', \'validation_split\', \'validation_data\', \'shuffle\', \'class_weight\', \'sample_weight\', \'initial_epoch\', \'steps_per_epoch\', \'validation_steps\', \'max_queue_size\', \'workers\', \'use_multiprocessing\'], varargs=None, keywords=kwargs, defaults=[\'None\', \'None\', \'None\', \'1\', \'1\', \'None\', \'0.0\', \'None\', \'True\', \'None\', \'None\', \'0\', \'None\', \'None\', \'10\', \'1\', \'False\'], " + } + member_method { + name: "fit_generator" + argspec: "args=[\'self\', \'generator\', \'steps_per_epoch\', \'epochs\', \'verbose\', \'callbacks\', \'validation_data\', \'validation_steps\', \'class_weight\', \'max_queue_size\', \'workers\', \'use_multiprocessing\', \'shuffle\', \'initial_epoch\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'1\', \'None\', \'None\', \'None\', \'None\', \'10\', \'1\', \'False\', \'True\', \'0\'], " + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\', \'custom_objects\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_layer" + argspec: "args=[\'self\', \'name\', \'index\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "load_weights" + argspec: "args=[\'self\', \'filepath\', \'by_name\'], varargs=None, keywords=None, defaults=[\'False\'], " + } + member_method { + name: "predict" + argspec: "args=[\'self\', \'x\', \'batch_size\', \'verbose\', \'steps\', \'max_queue_size\', \'workers\', \'use_multiprocessing\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'None\', \'10\', \'1\', \'False\'], " + } + member_method { + name: "predict_generator" + argspec: "args=[\'self\', \'generator\', \'steps\', \'max_queue_size\', \'workers\', \'use_multiprocessing\', \'verbose\'], varargs=None, keywords=None, defaults=[\'None\', \'10\', \'1\', \'False\', \'0\'], " + } + member_method { + name: "predict_on_batch" + argspec: "args=[\'self\', \'x\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_metrics" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "save" + argspec: "args=[\'self\', \'filepath\', \'overwrite\', \'include_optimizer\'], varargs=None, keywords=None, defaults=[\'True\', \'True\'], " + } + member_method { + name: "save_weights" + argspec: "args=[\'self\', \'filepath\', \'overwrite\', \'save_format\'], varargs=None, keywords=None, defaults=[\'True\', \'None\'], " + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "summary" + argspec: "args=[\'self\', \'line_length\', \'positions\', \'print_fn\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "test_on_batch" + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " + } + member_method { + name: "to_json" + argspec: "args=[\'self\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "to_yaml" + argspec: "args=[\'self\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "train_on_batch" + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-locally-connected1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-locally-connected1-d.pbtxt index 5ad5990d7e..fd52259432 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-locally-connected1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-locally-connected1-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-locally-connected2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-locally-connected2-d.pbtxt index 40d03369a5..5fc8af0d03 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-locally-connected2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-locally-connected2-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-masking.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-masking.pbtxt index 86666b51bb..7f8932270e 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-masking.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-masking.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool1-d.pbtxt index d26da270e7..4723b99cb0 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool2-d.pbtxt index 85f23df671..173c5d4a8b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool3-d.pbtxt index 235806b965..14e1899e14 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pool3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling1-d.pbtxt index 524c5fd69e..a708e652bf 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling2-d.pbtxt index fda2562fc8..e6706b5cf9 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling3-d.pbtxt index 71d2d09a8d..a73c082d1b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-max-pooling3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-maximum.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-maximum.pbtxt index 12949b39a6..f3f195554b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-maximum.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-maximum.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-minimum.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-minimum.pbtxt index ab16d0021e..f345d1d67b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-minimum.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-minimum.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-multiply.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-multiply.pbtxt index 61ccbf5962..31cb8bc177 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-multiply.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-multiply.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-p-re-l-u.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-p-re-l-u.pbtxt index ce2320d703..44cccc92bd 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-p-re-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-p-re-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-permute.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-permute.pbtxt index 69848af8cf..b55e191ff1 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-permute.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-permute.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-r-n-n.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-r-n-n.pbtxt index 3358f26aeb..e9575436e5 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-r-n-n.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-r-n-n.pbtxt @@ -92,6 +92,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-re-l-u.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-re-l-u.pbtxt index 413f45f018..98223b207f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-re-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-re-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-repeat-vector.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-repeat-vector.pbtxt index 9c61ff6027..2df918b16b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-repeat-vector.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-repeat-vector.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-reshape.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-reshape.pbtxt index baa91804c4..ce5f9e2129 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-reshape.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-reshape.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-conv1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-conv1-d.pbtxt index 15a5d6ac9e..a0bb917775 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-conv1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-conv1-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-conv2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-conv2-d.pbtxt index be43bd5b3c..d7942f201b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-conv2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-conv2-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-convolution1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-convolution1-d.pbtxt index 6105992c7a..f7ac9042d4 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-convolution1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-convolution1-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-convolution2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-convolution2-d.pbtxt index 1b6cf1e9ec..e5a9268822 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-convolution2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-separable-convolution2-d.pbtxt @@ -90,6 +90,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-simple-r-n-n-cell.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-simple-r-n-n-cell.pbtxt index 29488a37f8..0fe2c974a7 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-simple-r-n-n-cell.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-simple-r-n-n-cell.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-simple-r-n-n.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-simple-r-n-n.pbtxt index 3d70cf8b65..2ee5873f0f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-simple-r-n-n.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-simple-r-n-n.pbtxt @@ -149,6 +149,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-softmax.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-softmax.pbtxt index d29731ecf9..5b8f64aa35 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-softmax.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-softmax.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout1-d.pbtxt index a6d7494ca7..240cb6e562 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout1-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout2-d.pbtxt index c36e802693..6226c469f8 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout2-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout3-d.pbtxt index 9c46cfe40f..34dabce6d8 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-spatial-dropout3-d.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-stacked-r-n-n-cells.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-stacked-r-n-n-cells.pbtxt index 8982f78794..0ddf628ace 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-stacked-r-n-n-cells.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-stacked-r-n-n-cells.pbtxt @@ -96,6 +96,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-subtract.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-subtract.pbtxt index ec2cc50298..12eb35ad15 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-subtract.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-subtract.pbtxt @@ -89,6 +89,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-thresholded-re-l-u.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-thresholded-re-l-u.pbtxt index d7bc1980f3..c41020c2b4 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-thresholded-re-l-u.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-thresholded-re-l-u.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-time-distributed.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-time-distributed.pbtxt index fec2de6b49..479f89cf6a 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-time-distributed.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-time-distributed.pbtxt @@ -93,6 +93,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling1-d.pbtxt index 3d285e7f17..233363ce02 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling1-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling2-d.pbtxt index b05e5ec84d..cb6228ac44 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling2-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling3-d.pbtxt index 728eca415a..03bad3ccb6 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-up-sampling3-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-wrapper.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-wrapper.pbtxt index da64e77c39..158996792a 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-wrapper.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-wrapper.pbtxt @@ -92,6 +92,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding1-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding1-d.pbtxt index 2f505f9293..63a56cd3ee 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding1-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding1-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding2-d.pbtxt index f82c77072e..965a4cca04 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding2-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding3-d.pbtxt index 54e01a9917..1a62430887 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.-zero-padding3-d.pbtxt @@ -88,6 +88,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.pbtxt index 9d7e5bb8c7..3b4724ef10 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.layers.pbtxt @@ -124,6 +124,10 @@ tf_module { name: "Dense" mtype: "" } + member { + name: "DenseFeatures" + mtype: "" + } member { name: "DepthwiseConv2D" mtype: "" @@ -240,6 +244,10 @@ tf_module { name: "LeakyReLU" mtype: "" } + member { + name: "LinearModel" + mtype: "" + } member { name: "LocallyConnected1D" mtype: "" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-binary-crossentropy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-binary-crossentropy.pbtxt new file mode 100644 index 0000000000..2f7da93f6f --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-binary-crossentropy.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.BinaryCrossentropy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'from_logits\', \'label_smoothing\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'0\', \'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-categorical-crossentropy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-categorical-crossentropy.pbtxt new file mode 100644 index 0000000000..b3a7cd8097 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-categorical-crossentropy.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.CategoricalCrossentropy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'from_logits\', \'label_smoothing\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'0\', \'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-absolute-error.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-absolute-error.pbtxt new file mode 100644 index 0000000000..712bb2ecd3 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-absolute-error.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.MeanAbsoluteError" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-absolute-percentage-error.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-absolute-percentage-error.pbtxt new file mode 100644 index 0000000000..7fe362da89 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-absolute-percentage-error.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.MeanAbsolutePercentageError" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-squared-error.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-squared-error.pbtxt new file mode 100644 index 0000000000..a571853350 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-squared-error.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.MeanSquaredError" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-squared-logarithmic-error.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-squared-logarithmic-error.pbtxt new file mode 100644 index 0000000000..200006db35 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-mean-squared-logarithmic-error.pbtxt @@ -0,0 +1,22 @@ +path: "tensorflow.keras.losses.MeanSquaredLogarithmicError" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'reduction\', \'name\'], varargs=None, keywords=None, defaults=[\'sum_over_batch_size\', \'None\'], " + } + member_method { + name: "call" + argspec: "args=[\'self\', \'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-reduction.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-reduction.pbtxt new file mode 100644 index 0000000000..f20ed26e2e --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.-reduction.pbtxt @@ -0,0 +1,28 @@ +path: "tensorflow.keras.losses.Reduction" +tf_class { + is_instance: "" + is_instance: "" + member { + name: "NONE" + mtype: "" + } + member { + name: "SUM" + mtype: "" + } + member { + name: "SUM_OVER_BATCH_SIZE" + mtype: "" + } + member_method { + name: "__init__" + } + member_method { + name: "all" + argspec: "args=[\'cls\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "validate" + argspec: "args=[\'cls\', \'key\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.pbtxt index eca6b91538..c198096d25 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.losses.pbtxt @@ -1,5 +1,33 @@ path: "tensorflow.keras.losses" tf_module { + member { + name: "BinaryCrossentropy" + mtype: "" + } + member { + name: "CategoricalCrossentropy" + mtype: "" + } + member { + name: "MeanAbsoluteError" + mtype: "" + } + member { + name: "MeanAbsolutePercentageError" + mtype: "" + } + member { + name: "MeanSquaredError" + mtype: "" + } + member { + name: "MeanSquaredLogarithmicError" + mtype: "" + } + member { + name: "Reduction" + mtype: "" + } member_method { name: "KLD" argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" @@ -22,11 +50,11 @@ tf_module { } member_method { name: "binary_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "categorical_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "categorical_hinge" @@ -106,7 +134,7 @@ tf_module { } member_method { name: "sparse_categorical_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "squared_hinge" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-accuracy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-accuracy.pbtxt new file mode 100644 index 0000000000..2db07df523 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.keras.metrics.Accuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-binary-accuracy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-binary-accuracy.pbtxt new file mode 100644 index 0000000000..904ad3a21a --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-binary-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.keras.metrics.BinaryAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\', \'threshold\'], varargs=None, keywords=None, defaults=[\'binary_accuracy\', \'None\', \'0.5\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-categorical-accuracy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-categorical-accuracy.pbtxt new file mode 100644 index 0000000000..17b74924fa --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-categorical-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.keras.metrics.CategoricalAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'categorical_accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-false-negatives.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-false-negatives.pbtxt new file mode 100644 index 0000000000..49f577e136 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-false-negatives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.keras.metrics.FalseNegatives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-false-positives.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-false-positives.pbtxt new file mode 100644 index 0000000000..e8baf85866 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-false-positives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.keras.metrics.FalsePositives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-mean.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-mean.pbtxt new file mode 100644 index 0000000000..40fe64bbd2 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-mean.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.keras.metrics.Mean" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'mean\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'values\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-precision.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-precision.pbtxt new file mode 100644 index 0000000000..ae6a85026d --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-precision.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.keras.metrics.Precision" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-recall.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-recall.pbtxt new file mode 100644 index 0000000000..31068a51d5 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-recall.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.keras.metrics.Recall" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-sparse-categorical-accuracy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-sparse-categorical-accuracy.pbtxt new file mode 100644 index 0000000000..0c17452292 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-sparse-categorical-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.keras.metrics.SparseCategoricalAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'sparse_categorical_accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-true-negatives.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-true-negatives.pbtxt new file mode 100644 index 0000000000..1b5eb8d0de --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-true-negatives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.keras.metrics.TrueNegatives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-true-positives.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-true-positives.pbtxt new file mode 100644 index 0000000000..5b9c470e32 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.-true-positives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.keras.metrics.TruePositives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.pbtxt index a296e13158..8cab17edc5 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.metrics.pbtxt @@ -1,5 +1,49 @@ path: "tensorflow.keras.metrics" tf_module { + member { + name: "Accuracy" + mtype: "" + } + member { + name: "BinaryAccuracy" + mtype: "" + } + member { + name: "CategoricalAccuracy" + mtype: "" + } + member { + name: "FalseNegatives" + mtype: "" + } + member { + name: "FalsePositives" + mtype: "" + } + member { + name: "Mean" + mtype: "" + } + member { + name: "Precision" + mtype: "" + } + member { + name: "Recall" + mtype: "" + } + member { + name: "SparseCategoricalAccuracy" + mtype: "" + } + member { + name: "TrueNegatives" + mtype: "" + } + member { + name: "TruePositives" + mtype: "" + } member_method { name: "KLD" argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" @@ -26,7 +70,7 @@ tf_module { } member_method { name: "binary_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "categorical_accuracy" @@ -34,7 +78,7 @@ tf_module { } member_method { name: "categorical_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "cosine" @@ -110,7 +154,7 @@ tf_module { } member_method { name: "sparse_categorical_crossentropy" - argspec: "args=[\'y_true\', \'y_pred\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'y_true\', \'y_pred\', \'from_logits\'], varargs=None, keywords=None, defaults=[\'False\'], " } member_method { name: "sparse_top_k_categorical_accuracy" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.models.-model.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.models.-model.pbtxt index ccff809f2b..c58c7bef22 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.models.-model.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.models.-model.pbtxt @@ -41,6 +41,14 @@ tf_class { name: "losses" mtype: "" } + member { + name: "metrics" + mtype: "" + } + member { + name: "metrics_names" + mtype: "" + } member { name: "name" mtype: "" @@ -69,6 +77,10 @@ tf_class { name: "output_shape" mtype: "" } + member { + name: "run_eagerly" + mtype: "" + } member { name: "state_updates" mtype: "" @@ -105,13 +117,17 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "add_variable" - argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\', \'None\'], " + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" } member_method { name: "add_weight" @@ -225,6 +241,10 @@ tf_class { name: "predict_on_batch" argspec: "args=[\'self\', \'x\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "reset_metrics" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "reset_states" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" @@ -247,7 +267,7 @@ tf_class { } member_method { name: "test_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " } member_method { name: "to_json" @@ -259,6 +279,6 @@ tf_class { } member_method { name: "train_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\'], " } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.models.-sequential.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.models.-sequential.pbtxt index b0fc7f97f1..473a1c16fb 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.models.-sequential.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.models.-sequential.pbtxt @@ -42,6 +42,14 @@ tf_class { name: "losses" mtype: "" } + member { + name: "metrics" + mtype: "" + } + member { + name: "metrics_names" + mtype: "" + } member { name: "name" mtype: "" @@ -70,6 +78,10 @@ tf_class { name: "output_shape" mtype: "" } + member { + name: "run_eagerly" + mtype: "" + } member { name: "state_updates" mtype: "" @@ -110,13 +122,17 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "add_variable" - argspec: "args=[\'self\', \'name\', \'shape\', \'dtype\', \'initializer\', \'regularizer\', \'trainable\', \'constraint\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\', \'None\'], " + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" } member_method { name: "add_weight" @@ -242,6 +258,10 @@ tf_class { name: "predict_proba" argspec: "args=[\'self\', \'x\', \'batch_size\', \'verbose\'], varargs=None, keywords=None, defaults=[\'32\', \'0\'], " } + member_method { + name: "reset_metrics" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "reset_states" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" @@ -264,7 +284,7 @@ tf_class { } member_method { name: "test_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " } member_method { name: "to_json" @@ -276,6 +296,6 @@ tf_class { } member_method { name: "train_on_batch" - argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'self\', \'x\', \'y\', \'sample_weight\', \'class_weight\', \'reset_metrics\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'True\'], " } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.utils.-progbar.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.utils.-progbar.pbtxt index be4496e753..8177cc71ed 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.utils.-progbar.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.utils.-progbar.pbtxt @@ -4,7 +4,7 @@ tf_class { is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'target\', \'width\', \'verbose\', \'interval\', \'stateful_metrics\'], varargs=None, keywords=None, defaults=[\'30\', \'1\', \'0.05\', \'None\'], " + argspec: "args=[\'self\', \'target\', \'width\', \'verbose\', \'interval\', \'stateful_metrics\', \'unit_name\'], varargs=None, keywords=None, defaults=[\'30\', \'1\', \'0.05\', \'None\', \'step\'], " } member_method { name: "add" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-block-diag.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-block-diag.pbtxt index 973705dae2..773c74e64d 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-block-diag.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-block-diag.pbtxt @@ -79,6 +79,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant.pbtxt index de917706d5..533544d21f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant.pbtxt @@ -96,6 +96,10 @@ tf_class { name: "block_shape_tensor" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "convolution_kernel" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'convolution_kernel\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant2-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant2-d.pbtxt index c4e6a21c3a..e3926eb6d4 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant2-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant2-d.pbtxt @@ -96,6 +96,10 @@ tf_class { name: "block_shape_tensor" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "convolution_kernel" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'convolution_kernel\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant3-d.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant3-d.pbtxt index 2e085a8e28..ba209df782 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant3-d.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-circulant3-d.pbtxt @@ -96,6 +96,10 @@ tf_class { name: "block_shape_tensor" argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "convolution_kernel" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'convolution_kernel\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-composition.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-composition.pbtxt index 42d22bce42..081fb0e08b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-composition.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-composition.pbtxt @@ -79,6 +79,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-diag.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-diag.pbtxt index d6749fdcec..2014a04301 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-diag.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-diag.pbtxt @@ -79,6 +79,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-full-matrix.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-full-matrix.pbtxt index d9f363d133..9a87ae9687 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-full-matrix.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-full-matrix.pbtxt @@ -75,6 +75,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-identity.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-identity.pbtxt index aac7ee31ed..33afb835ce 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-identity.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-identity.pbtxt @@ -76,6 +76,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-kronecker.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-kronecker.pbtxt index c11d390829..a9078c8ab5 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-kronecker.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-kronecker.pbtxt @@ -79,6 +79,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-low-rank-update.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-low-rank-update.pbtxt index 3ee800269e..4cfa3bb30d 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-low-rank-update.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-low-rank-update.pbtxt @@ -99,6 +99,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-lower-triangular.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-lower-triangular.pbtxt index 63a1bc2321..a87649133f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-lower-triangular.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-lower-triangular.pbtxt @@ -75,6 +75,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-scaled-identity.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-scaled-identity.pbtxt index e2c5a505a7..3265646784 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-scaled-identity.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-scaled-identity.pbtxt @@ -80,6 +80,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-zeros.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-zeros.pbtxt index a1b0e06b47..49d8890c89 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-zeros.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator-zeros.pbtxt @@ -75,6 +75,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator.pbtxt index 6d849dc040..c89dc067b3 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.-linear-operator.pbtxt @@ -74,6 +74,10 @@ tf_class { name: "batch_shape_tensor" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'batch_shape_tensor\'], " } + member_method { + name: "cholesky" + argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'cholesky\'], " + } member_method { name: "determinant" argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=[\'det\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.linalg.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.linalg.pbtxt index 1a4098d121..a3599bfa80 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.linalg.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.linalg.pbtxt @@ -118,7 +118,7 @@ tf_module { } member_method { name: "l2_normalize" - argspec: "args=[\'x\', \'axis\', \'epsilon\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'1e-12\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'axis\', \'epsilon\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'1e-12\', \'None\'], " } member_method { name: "logdet" @@ -142,7 +142,7 @@ tf_module { } member_method { name: "norm" - argspec: "args=[\'tensor\', \'ord\', \'axis\', \'keepdims\', \'name\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'euclidean\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'tensor\', \'ord\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'euclidean\', \'None\', \'None\', \'None\'], " } member_method { name: "qr" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.lite.constants.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.lite.constants.pbtxt index 08845553e5..4d5c4893b4 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.lite.constants.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.lite.constants.pbtxt @@ -1,29 +1,9 @@ path: "tensorflow.lite.constants" tf_module { - member { - name: "FLOAT" - mtype: "" - } member { name: "GRAPHVIZ_DOT" mtype: "" } - member { - name: "INT32" - mtype: "" - } - member { - name: "INT64" - mtype: "" - } - member { - name: "QUANTIZED_UINT8" - mtype: "" - } - member { - name: "STRING" - mtype: "" - } member { name: "TFLITE" mtype: "" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.logging.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.logging.pbtxt deleted file mode 100644 index 85bb15455d..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.logging.pbtxt +++ /dev/null @@ -1,83 +0,0 @@ -path: "tensorflow.logging" -tf_module { - member { - name: "DEBUG" - mtype: "" - } - member { - name: "ERROR" - mtype: "" - } - member { - name: "FATAL" - mtype: "" - } - member { - name: "INFO" - mtype: "" - } - member { - name: "WARN" - mtype: "" - } - member_method { - name: "TaskLevelStatusMessage" - argspec: "args=[\'msg\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "debug" - argspec: "args=[\'msg\'], varargs=args, keywords=kwargs, defaults=None" - } - member_method { - name: "error" - argspec: "args=[\'msg\'], varargs=args, keywords=kwargs, defaults=None" - } - member_method { - name: "fatal" - argspec: "args=[\'msg\'], varargs=args, keywords=kwargs, defaults=None" - } - member_method { - name: "flush" - argspec: "args=[], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_verbosity" - argspec: "args=[], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "info" - argspec: "args=[\'msg\'], varargs=args, keywords=kwargs, defaults=None" - } - member_method { - name: "log" - argspec: "args=[\'level\', \'msg\'], varargs=args, keywords=kwargs, defaults=None" - } - member_method { - name: "log_every_n" - argspec: "args=[\'level\', \'msg\', \'n\'], varargs=args, keywords=None, defaults=None" - } - member_method { - name: "log_first_n" - argspec: "args=[\'level\', \'msg\', \'n\'], varargs=args, keywords=None, defaults=None" - } - member_method { - name: "log_if" - argspec: "args=[\'level\', \'msg\', \'condition\'], varargs=args, keywords=None, defaults=None" - } - member_method { - name: "set_verbosity" - argspec: "args=[\'v\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "vlog" - argspec: "args=[\'level\', \'msg\'], varargs=args, keywords=kwargs, defaults=None" - } - member_method { - name: "warn" - argspec: "args=[\'msg\'], varargs=args, keywords=kwargs, defaults=None" - } - member_method { - name: "warning" - argspec: "args=[\'msg\'], varargs=args, keywords=kwargs, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.losses.-reduction.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.losses.-reduction.pbtxt index 258ad5047e..6a44e4ce66 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.losses.-reduction.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.losses.-reduction.pbtxt @@ -1,11 +1,7 @@ path: "tensorflow.losses.Reduction" tf_class { - is_instance: "" + is_instance: "" is_instance: "" - member { - name: "MEAN" - mtype: "" - } member { name: "NONE" mtype: "" @@ -14,18 +10,10 @@ tf_class { name: "SUM" mtype: "" } - member { - name: "SUM_BY_NONZERO_WEIGHTS" - mtype: "" - } member { name: "SUM_OVER_BATCH_SIZE" mtype: "" } - member { - name: "SUM_OVER_NONZERO_WEIGHTS" - mtype: "" - } member_method { name: "__init__" } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.losses.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.losses.pbtxt index c1d190ae11..233b1a0131 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.losses.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.losses.pbtxt @@ -4,22 +4,10 @@ tf_module { name: "Reduction" mtype: "" } - member_method { - name: "absolute_difference" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'scope\', \'loss_collection\', \'reduction\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\'], " - } member_method { name: "add_loss" argspec: "args=[\'loss\', \'loss_collection\'], varargs=None, keywords=None, defaults=[\'losses\'], " } - member_method { - name: "compute_weighted_loss" - argspec: "args=[\'losses\', \'weights\', \'scope\', \'loss_collection\', \'reduction\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\'], " - } - member_method { - name: "cosine_distance" - argspec: "args=[\'labels\', \'predictions\', \'axis\', \'weights\', \'scope\', \'loss_collection\', \'reduction\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'1.0\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\', \'None\'], " - } member_method { name: "get_losses" argspec: "args=[\'scope\', \'loss_collection\'], varargs=None, keywords=None, defaults=[\'None\', \'losses\'], " @@ -36,36 +24,4 @@ tf_module { name: "get_total_loss" argspec: "args=[\'add_regularization_losses\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'total_loss\'], " } - member_method { - name: "hinge_loss" - argspec: "args=[\'labels\', \'logits\', \'weights\', \'scope\', \'loss_collection\', \'reduction\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\'], " - } - member_method { - name: "huber_loss" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'delta\', \'scope\', \'loss_collection\', \'reduction\'], varargs=None, keywords=None, defaults=[\'1.0\', \'1.0\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\'], " - } - member_method { - name: "log_loss" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'epsilon\', \'scope\', \'loss_collection\', \'reduction\'], varargs=None, keywords=None, defaults=[\'1.0\', \'1e-07\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\'], " - } - member_method { - name: "mean_pairwise_squared_error" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'scope\', \'loss_collection\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \'losses\'], " - } - member_method { - name: "mean_squared_error" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'scope\', \'loss_collection\', \'reduction\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\'], " - } - member_method { - name: "sigmoid_cross_entropy" - argspec: "args=[\'multi_class_labels\', \'logits\', \'weights\', \'label_smoothing\', \'scope\', \'loss_collection\', \'reduction\'], varargs=None, keywords=None, defaults=[\'1.0\', \'0\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\'], " - } - member_method { - name: "softmax_cross_entropy" - argspec: "args=[\'onehot_labels\', \'logits\', \'weights\', \'label_smoothing\', \'scope\', \'loss_collection\', \'reduction\'], varargs=None, keywords=None, defaults=[\'1.0\', \'0\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\'], " - } - member_method { - name: "sparse_softmax_cross_entropy" - argspec: "args=[\'labels\', \'logits\', \'weights\', \'scope\', \'loss_collection\', \'reduction\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \'losses\', \'weighted_sum_by_nonzero_weights\'], " - } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.math.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.math.pbtxt index a441e42b0a..979d77ea6b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.math.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.math.pbtxt @@ -78,7 +78,7 @@ tf_module { } member_method { name: "bincount" - argspec: "args=[\'arr\', \'weights\', \'minlength\', \'maxlength\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \"\"], " + argspec: "args=[\'arr\', \'weights\', \'minlength\', \'maxlength\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \"\", \'None\'], " } member_method { name: "ceil" @@ -86,7 +86,7 @@ tf_module { } member_method { name: "confusion_matrix" - argspec: "args=[\'labels\', \'predictions\', \'num_classes\', \'dtype\', \'name\', \'weights\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\', \'None\'], " + argspec: "args=[\'labels\', \'predictions\', \'num_classes\', \'weights\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \"\", \'None\'], " } member_method { name: "conj" @@ -102,7 +102,7 @@ tf_module { } member_method { name: "count_nonzero" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'dtype\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \"\", \'None\', \'None\', \'None\'], " + argspec: "args=[\'input\', \'axis\', \'keepdims\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \"\", \'None\'], " } member_method { name: "cumprod" @@ -176,9 +176,29 @@ tf_module { name: "invert_permutation" argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "is_finite" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_inf" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_nan" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_non_decreasing" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "is_strictly_increasing" + argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "l2_normalize" - argspec: "args=[\'x\', \'axis\', \'epsilon\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'1e-12\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'axis\', \'epsilon\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'1e-12\', \'None\'], " } member_method { name: "lbeta" @@ -210,7 +230,7 @@ tf_module { } member_method { name: "log_softmax" - argspec: "args=[\'logits\', \'axis\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'logits\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "logical_and" @@ -270,43 +290,43 @@ tf_module { } member_method { name: "reduce_all" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_any" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_logsumexp" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_max" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_mean" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_min" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_prod" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_std" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_sum" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_variance" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "rint" @@ -322,7 +342,7 @@ tf_module { } member_method { name: "scalar_mul" - argspec: "args=[\'scalar\', \'x\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'scalar\', \'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "segment_max" @@ -362,7 +382,7 @@ tf_module { } member_method { name: "softmax" - argspec: "args=[\'logits\', \'axis\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'logits\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "softplus" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-accuracy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-accuracy.pbtxt new file mode 100644 index 0000000000..f8e12f8817 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.metrics.Accuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-binary-accuracy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-binary-accuracy.pbtxt new file mode 100644 index 0000000000..b9bc6a716a --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-binary-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.metrics.BinaryAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\', \'threshold\'], varargs=None, keywords=None, defaults=[\'binary_accuracy\', \'None\', \'0.5\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-categorical-accuracy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-categorical-accuracy.pbtxt new file mode 100644 index 0000000000..0ef75d8756 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-categorical-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.metrics.CategoricalAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'categorical_accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-false-negatives.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-false-negatives.pbtxt new file mode 100644 index 0000000000..33226a2df6 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-false-negatives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.metrics.FalseNegatives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-false-positives.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-false-positives.pbtxt new file mode 100644 index 0000000000..9953162ea3 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-false-positives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.metrics.FalsePositives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-mean.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-mean.pbtxt new file mode 100644 index 0000000000..7fe6d6fda9 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-mean.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.metrics.Mean" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'mean\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'values\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-precision.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-precision.pbtxt new file mode 100644 index 0000000000..8c3271a109 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-precision.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.metrics.Precision" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-recall.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-recall.pbtxt new file mode 100644 index 0000000000..840a68bbc7 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-recall.pbtxt @@ -0,0 +1,192 @@ +path: "tensorflow.metrics.Recall" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-sparse-categorical-accuracy.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-sparse-categorical-accuracy.pbtxt new file mode 100644 index 0000000000..7bce43fbde --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-sparse-categorical-accuracy.pbtxt @@ -0,0 +1,194 @@ +path: "tensorflow.metrics.SparseCategoricalAccuracy" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'sparse_categorical_accuracy\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-true-negatives.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-true-negatives.pbtxt new file mode 100644 index 0000000000..83cd5b736b --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-true-negatives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.metrics.TrueNegatives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.-true-positives.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-true-positives.pbtxt new file mode 100644 index 0000000000..5b2502eafe --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.-true-positives.pbtxt @@ -0,0 +1,193 @@ +path: "tensorflow.metrics.TruePositives" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member { + name: "activity_regularizer" + mtype: "" + } + member { + name: "dtype" + mtype: "" + } + member { + name: "inbound_nodes" + mtype: "" + } + member { + name: "input" + mtype: "" + } + member { + name: "input_mask" + mtype: "" + } + member { + name: "input_shape" + mtype: "" + } + member { + name: "losses" + mtype: "" + } + member { + name: "name" + mtype: "" + } + member { + name: "non_trainable_variables" + mtype: "" + } + member { + name: "non_trainable_weights" + mtype: "" + } + member { + name: "outbound_nodes" + mtype: "" + } + member { + name: "output" + mtype: "" + } + member { + name: "output_mask" + mtype: "" + } + member { + name: "output_shape" + mtype: "" + } + member { + name: "trainable_variables" + mtype: "" + } + member { + name: "trainable_weights" + mtype: "" + } + member { + name: "updates" + mtype: "" + } + member { + name: "variables" + mtype: "" + } + member { + name: "weights" + mtype: "" + } + member_method { + name: "__init__" + argspec: "args=[\'self\', \'thresholds\', \'name\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + } + member_method { + name: "add_loss" + argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "add_update" + argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "add_variable" + argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "add_weight" + argspec: "args=[\'self\', \'name\', \'shape\', \'aggregation\', \'synchronization\', \'initializer\'], varargs=None, keywords=None, defaults=[\'()\', \'VariableAggregation.SUM\', \'VariableSynchronization.ON_READ\', \'None\'], " + } + member_method { + name: "apply" + argspec: "args=[\'self\', \'inputs\'], varargs=args, keywords=kwargs, defaults=None" + } + member_method { + name: "build" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "call" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=kwargs, defaults=None" + } + member_method { + name: "compute_mask" + argspec: "args=[\'self\', \'inputs\', \'mask\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "compute_output_shape" + argspec: "args=[\'self\', \'input_shape\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "count_params" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_input_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_losses_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_mask_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_output_shape_at" + argspec: "args=[\'self\', \'node_index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_updates_for" + argspec: "args=[\'self\', \'inputs\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_weights" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "reset_states" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "result" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_weights" + argspec: "args=[\'self\', \'weights\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "update_state" + argspec: "args=[\'self\', \'y_true\', \'y_pred\', \'sample_weight\'], varargs=None, keywords=None, defaults=[\'None\'], " + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.metrics.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.metrics.pbtxt index e9b996c9f5..773efd03fc 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.metrics.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.metrics.pbtxt @@ -1,135 +1,47 @@ path: "tensorflow.metrics" tf_module { - member_method { - name: "accuracy" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "Accuracy" + mtype: "" } - member_method { - name: "auc" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'num_thresholds\', \'metrics_collections\', \'updates_collections\', \'curve\', \'name\', \'summation_method\'], varargs=None, keywords=None, defaults=[\'None\', \'200\', \'None\', \'None\', \'ROC\', \'None\', \'trapezoidal\'], " + member { + name: "BinaryAccuracy" + mtype: "" } - member_method { - name: "average_precision_at_k" - argspec: "args=[\'labels\', \'predictions\', \'k\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "CategoricalAccuracy" + mtype: "" } - member_method { - name: "false_negatives" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "FalseNegatives" + mtype: "" } - member_method { - name: "false_negatives_at_thresholds" - argspec: "args=[\'labels\', \'predictions\', \'thresholds\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "FalsePositives" + mtype: "" } - member_method { - name: "false_positives" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "Mean" + mtype: "" } - member_method { - name: "false_positives_at_thresholds" - argspec: "args=[\'labels\', \'predictions\', \'thresholds\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "Precision" + mtype: "" } - member_method { - name: "mean" - argspec: "args=[\'values\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "Recall" + mtype: "" } - member_method { - name: "mean_absolute_error" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "SparseCategoricalAccuracy" + mtype: "" } - member_method { - name: "mean_cosine_distance" - argspec: "args=[\'labels\', \'predictions\', \'dim\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "TrueNegatives" + mtype: "" } - member_method { - name: "mean_iou" - argspec: "args=[\'labels\', \'predictions\', \'num_classes\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "mean_per_class_accuracy" - argspec: "args=[\'labels\', \'predictions\', \'num_classes\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "mean_relative_error" - argspec: "args=[\'labels\', \'predictions\', \'normalizer\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "mean_squared_error" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "mean_tensor" - argspec: "args=[\'values\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "percentage_below" - argspec: "args=[\'values\', \'threshold\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "precision" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "precision_at_k" - argspec: "args=[\'labels\', \'predictions\', \'k\', \'class_id\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "precision_at_thresholds" - argspec: "args=[\'labels\', \'predictions\', \'thresholds\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "precision_at_top_k" - argspec: "args=[\'labels\', \'predictions_idx\', \'k\', \'class_id\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "recall" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "recall_at_k" - argspec: "args=[\'labels\', \'predictions\', \'k\', \'class_id\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "recall_at_thresholds" - argspec: "args=[\'labels\', \'predictions\', \'thresholds\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "recall_at_top_k" - argspec: "args=[\'labels\', \'predictions_idx\', \'k\', \'class_id\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "root_mean_squared_error" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "sensitivity_at_specificity" - argspec: "args=[\'labels\', \'predictions\', \'specificity\', \'weights\', \'num_thresholds\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'200\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "sparse_average_precision_at_k" - argspec: "args=[\'labels\', \'predictions\', \'k\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "sparse_precision_at_k" - argspec: "args=[\'labels\', \'predictions\', \'k\', \'class_id\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "specificity_at_sensitivity" - argspec: "args=[\'labels\', \'predictions\', \'sensitivity\', \'weights\', \'num_thresholds\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'200\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "true_negatives" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "true_negatives_at_thresholds" - argspec: "args=[\'labels\', \'predictions\', \'thresholds\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "true_positives" - argspec: "args=[\'labels\', \'predictions\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "true_positives_at_thresholds" - argspec: "args=[\'labels\', \'predictions\', \'thresholds\', \'weights\', \'metrics_collections\', \'updates_collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + member { + name: "TruePositives" + mtype: "" } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.nn.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.nn.pbtxt index 2dc5c48aa6..63bf24b5d5 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.nn.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.nn.pbtxt @@ -30,7 +30,7 @@ tf_module { } member_method { name: "batch_norm_with_global_normalization" - argspec: "args=[\'t\', \'m\', \'v\', \'beta\', \'gamma\', \'variance_epsilon\', \'scale_after_normalization\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'input\', \'mean\', \'variance\', \'beta\', \'gamma\', \'variance_epsilon\', \'scale_after_normalization\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "batch_normalization" @@ -41,8 +41,8 @@ tf_module { argspec: "args=[\'value\', \'bias\', \'data_format\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { - name: "bidirectional_dynamic_rnn" - argspec: "args=[\'cell_fw\', \'cell_bw\', \'inputs\', \'sequence_length\', \'initial_state_fw\', \'initial_state_bw\', \'dtype\', \'parallel_iterations\', \'swap_memory\', \'time_major\', \'scope\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'False\', \'False\', \'None\'], " + name: "collapse_repeated" + argspec: "args=[\'labels\', \'seq_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "compute_accidental_hits" @@ -50,43 +50,43 @@ tf_module { } member_method { name: "conv1d" - argspec: "args=[\'value\', \'filters\', \'stride\', \'padding\', \'use_cudnn_on_gpu\', \'data_format\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'input\', \'filters\', \'stride\', \'padding\', \'data_format\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "conv2d" - argspec: "args=[\'input\', \'filter\', \'strides\', \'padding\', \'use_cudnn_on_gpu\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'NHWC\', \'[1, 1, 1, 1]\', \'None\'], " + argspec: "args=[\'input\', \'filters\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \'None\', \'None\'], " } member_method { name: "conv2d_backprop_filter" - argspec: "args=[\'input\', \'filter_sizes\', \'out_backprop\', \'strides\', \'padding\', \'use_cudnn_on_gpu\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'NHWC\', \'[1, 1, 1, 1]\', \'None\'], " + argspec: "args=[\'input\', \'filter_sizes\', \'out_backprop\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \'None\', \'None\'], " } member_method { name: "conv2d_backprop_input" - argspec: "args=[\'input_sizes\', \'filter\', \'out_backprop\', \'strides\', \'padding\', \'use_cudnn_on_gpu\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'NHWC\', \'[1, 1, 1, 1]\', \'None\'], " + argspec: "args=[\'input_sizes\', \'filters\', \'out_backprop\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \'None\', \'None\'], " } member_method { name: "conv2d_transpose" - argspec: "args=[\'value\', \'filter\', \'output_shape\', \'strides\', \'padding\', \'data_format\', \'name\'], varargs=None, keywords=None, defaults=[\'SAME\', \'NHWC\', \'None\'], " + argspec: "args=[\'input\', \'filters\', \'output_shape\', \'strides\', \'padding\', \'data_format\', \'name\'], varargs=None, keywords=None, defaults=[\'SAME\', \'NHWC\', \'None\'], " } member_method { name: "conv3d" - argspec: "args=[\'input\', \'filter\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NDHWC\', \'[1, 1, 1, 1, 1]\', \'None\'], " + argspec: "args=[\'input\', \'filters\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NDHWC\', \'None\', \'None\'], " } member_method { - name: "conv3d_backprop_filter_v2" + name: "conv3d_backprop_filter" argspec: "args=[\'input\', \'filter_sizes\', \'out_backprop\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NDHWC\', \'[1, 1, 1, 1, 1]\', \'None\'], " } member_method { name: "conv3d_transpose" - argspec: "args=[\'value\', \'filter\', \'output_shape\', \'strides\', \'padding\', \'data_format\', \'name\'], varargs=None, keywords=None, defaults=[\'SAME\', \'NDHWC\', \'None\'], " + argspec: "args=[\'input\', \'filters\', \'output_shape\', \'strides\', \'padding\', \'data_format\', \'name\'], varargs=None, keywords=None, defaults=[\'SAME\', \'NDHWC\', \'None\'], " } member_method { name: "convolution" - argspec: "args=[\'input\', \'filter\', \'padding\', \'strides\', \'dilation_rate\', \'name\', \'data_format\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input\', \'filters\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'VALID\', \'None\', \'None\', \'None\'], " } member_method { name: "crelu" - argspec: "args=[\'features\', \'name\', \'axis\'], varargs=None, keywords=None, defaults=[\'None\', \'-1\'], " + argspec: "args=[\'features\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'-1\', \'None\'], " } member_method { name: "ctc_beam_search_decoder" @@ -98,7 +98,11 @@ tf_module { } member_method { name: "ctc_loss" - argspec: "args=[\'labels\', \'inputs\', \'sequence_length\', \'preprocess_collapse_repeated\', \'ctc_merge_repeated\', \'ignore_longer_outputs_than_inputs\', \'time_major\'], varargs=None, keywords=None, defaults=[\'False\', \'True\', \'False\', \'True\'], " + argspec: "args=[\'labels\', \'logits\', \'label_length\', \'logit_length\', \'logits_time_major\', \'unique\', \'blank_index\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'None\', \'None\', \'None\'], " + } + member_method { + name: "ctc_unique_labels" + argspec: "args=[\'labels\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "depth_to_space" @@ -106,27 +110,23 @@ tf_module { } member_method { name: "depthwise_conv2d" - argspec: "args=[\'input\', \'filter\', \'strides\', \'padding\', \'rate\', \'name\', \'data_format\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'input\', \'filter\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { - name: "depthwise_conv2d_native" - argspec: "args=[\'input\', \'filter\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \'[1, 1, 1, 1]\', \'None\'], " - } - member_method { - name: "depthwise_conv2d_native_backprop_filter" + name: "depthwise_conv2d_backprop_filter" argspec: "args=[\'input\', \'filter_sizes\', \'out_backprop\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \'[1, 1, 1, 1]\', \'None\'], " } member_method { - name: "depthwise_conv2d_native_backprop_input" + name: "depthwise_conv2d_backprop_input" argspec: "args=[\'input_sizes\', \'filter\', \'out_backprop\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \'[1, 1, 1, 1]\', \'None\'], " } member_method { name: "dilation2d" - argspec: "args=[\'input\', \'filter\', \'strides\', \'rates\', \'padding\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'input\', \'filters\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "dropout" - argspec: "args=[\'x\', \'keep_prob\', \'noise_shape\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'rate\', \'noise_shape\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "elu" @@ -142,7 +142,7 @@ tf_module { } member_method { name: "erosion2d" - argspec: "args=[\'value\', \'kernel\', \'strides\', \'rates\', \'padding\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'value\', \'filters\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "fixed_unigram_candidate_sampler" @@ -150,15 +150,11 @@ tf_module { } member_method { name: "fractional_avg_pool" - argspec: "args=[\'value\', \'pooling_ratio\', \'pseudo_random\', \'overlapping\', \'deterministic\', \'seed\', \'seed2\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'False\', \'False\', \'0\', \'0\', \'None\'], " + argspec: "args=[\'value\', \'pooling_ratio\', \'pseudo_random\', \'overlapping\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'False\', \'0\', \'None\'], " } member_method { name: "fractional_max_pool" - argspec: "args=[\'value\', \'pooling_ratio\', \'pseudo_random\', \'overlapping\', \'deterministic\', \'seed\', \'seed2\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'False\', \'False\', \'0\', \'0\', \'None\'], " - } - member_method { - name: "fused_batch_norm" - argspec: "args=[\'x\', \'scale\', \'offset\', \'mean\', \'variance\', \'epsilon\', \'data_format\', \'is_training\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'0.001\', \'NHWC\', \'True\', \'None\'], " + argspec: "args=[\'value\', \'pooling_ratio\', \'pseudo_random\', \'overlapping\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'False\', \'0\', \'None\'], " } member_method { name: "in_top_k" @@ -170,7 +166,7 @@ tf_module { } member_method { name: "l2_normalize" - argspec: "args=[\'x\', \'axis\', \'epsilon\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'1e-12\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'axis\', \'epsilon\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'1e-12\', \'None\'], " } member_method { name: "leaky_relu" @@ -190,7 +186,7 @@ tf_module { } member_method { name: "log_softmax" - argspec: "args=[\'logits\', \'axis\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'logits\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "lrn" @@ -206,15 +202,15 @@ tf_module { } member_method { name: "max_pool_with_argmax" - argspec: "args=[\'input\', \'ksize\', \'strides\', \'padding\', \'Targmax\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " + argspec: "args=[\'input\', \'ksize\', \'strides\', \'padding\', \'data_format\', \'output_dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'NHWC\', \"\", \'None\'], " } member_method { name: "moments" - argspec: "args=[\'x\', \'axes\', \'shift\', \'name\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\'], " + argspec: "args=[\'x\', \'axes\', \'shift\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "nce_loss" - argspec: "args=[\'weights\', \'biases\', \'labels\', \'inputs\', \'num_sampled\', \'num_classes\', \'num_true\', \'sampled_values\', \'remove_accidental_hits\', \'partition_strategy\', \'name\'], varargs=None, keywords=None, defaults=[\'1\', \'None\', \'False\', \'mod\', \'nce_loss\'], " + argspec: "args=[\'weights\', \'biases\', \'labels\', \'inputs\', \'num_sampled\', \'num_classes\', \'num_true\', \'sampled_values\', \'remove_accidental_hits\', \'name\'], varargs=None, keywords=None, defaults=[\'1\', \'None\', \'False\', \'nce_loss\'], " } member_method { name: "normalize_moments" @@ -222,23 +218,7 @@ tf_module { } member_method { name: "pool" - argspec: "args=[\'input\', \'window_shape\', \'pooling_type\', \'padding\', \'dilation_rate\', \'strides\', \'name\', \'data_format\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "quantized_avg_pool" - argspec: "args=[\'input\', \'min_input\', \'max_input\', \'ksize\', \'strides\', \'padding\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "quantized_conv2d" - argspec: "args=[\'input\', \'filter\', \'min_input\', \'max_input\', \'min_filter\', \'max_filter\', \'strides\', \'padding\', \'out_type\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'[1, 1, 1, 1]\', \'None\'], " - } - member_method { - name: "quantized_max_pool" - argspec: "args=[\'input\', \'min_input\', \'max_input\', \'ksize\', \'strides\', \'padding\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "quantized_relu_x" - argspec: "args=[\'features\', \'max_value\', \'min_features\', \'max_features\', \'out_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " + argspec: "args=[\'input\', \'window_shape\', \'pooling_type\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'VALID\', \'None\', \'None\', \'None\'], " } member_method { name: "relu" @@ -266,7 +246,7 @@ tf_module { } member_method { name: "separable_conv2d" - argspec: "args=[\'input\', \'depthwise_filter\', \'pointwise_filter\', \'strides\', \'padding\', \'rate\', \'name\', \'data_format\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'input\', \'depthwise_filter\', \'pointwise_filter\', \'strides\', \'padding\', \'data_format\', \'dilations\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "sigmoid" @@ -278,11 +258,11 @@ tf_module { } member_method { name: "softmax" - argspec: "args=[\'logits\', \'axis\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'logits\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "softmax_cross_entropy_with_logits" - argspec: "args=[\'labels\', \'logits\', \'dim\', \'name\'], varargs=None, keywords=None, defaults=[\'-1\', \'None\'], " + argspec: "args=[\'labels\', \'logits\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'-1\', \'None\'], " } member_method { name: "softplus" @@ -304,17 +284,13 @@ tf_module { name: "sparse_softmax_cross_entropy_with_logits" argspec: "args=[\'_sentinel\', \'labels\', \'logits\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } - member_method { - name: "static_bidirectional_rnn" - argspec: "args=[\'cell_fw\', \'cell_bw\', \'inputs\', \'initial_state_fw\', \'initial_state_bw\', \'dtype\', \'sequence_length\', \'scope\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " - } member_method { name: "static_state_saving_rnn" argspec: "args=[\'cell\', \'inputs\', \'state_saver\', \'state_name\', \'sequence_length\', \'scope\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "sufficient_statistics" - argspec: "args=[\'x\', \'axes\', \'shift\', \'keep_dims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'x\', \'axes\', \'shift\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "tanh" @@ -330,16 +306,12 @@ tf_module { } member_method { name: "weighted_moments" - argspec: "args=[\'x\', \'axes\', \'frequency_weights\', \'name\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'False\'], " + argspec: "args=[\'x\', \'axes\', \'frequency_weights\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " } member_method { name: "with_space_to_batch" argspec: "args=[\'input\', \'dilation_rate\', \'padding\', \'op\', \'filter_shape\', \'spatial_dims\', \'data_format\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } - member_method { - name: "xw_plus_b" - argspec: "args=[\'x\', \'weights\', \'biases\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } member_method { name: "zero_fraction" argspec: "args=[\'value\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-device-wrapper.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-device-wrapper.pbtxt index 381c4975d7..9e52a42526 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-device-wrapper.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-device-wrapper.pbtxt @@ -106,6 +106,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-dropout-wrapper.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-dropout-wrapper.pbtxt index 912365a28b..9836433d08 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-dropout-wrapper.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-dropout-wrapper.pbtxt @@ -110,6 +110,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt index faeb4f3513..d3b68e4f29 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-r-n-n-cell.pbtxt @@ -105,6 +105,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-residual-wrapper.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-residual-wrapper.pbtxt index caa2e60080..1f7840ab91 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-residual-wrapper.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.-residual-wrapper.pbtxt @@ -106,6 +106,10 @@ tf_class { name: "add_loss" argspec: "args=[\'self\', \'losses\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "add_metric" + argspec: "args=[\'self\', \'value\', \'aggregation\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "add_update" argspec: "args=[\'self\', \'updates\', \'inputs\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.pbtxt index 3c78b07b39..b1f687f529 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.nn.rnn_cell.pbtxt @@ -12,10 +12,6 @@ tf_module { name: "LSTMStateTuple" mtype: "" } - member { - name: "MultiRNNCell" - mtype: "" - } member { name: "RNNCell" mtype: "" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.pbtxt index 078b471a4c..cb38ae0b49 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.pbtxt @@ -8,14 +8,6 @@ tf_module { name: "AttrValue" mtype: "" } - member { - name: "ConditionalAccumulator" - mtype: "" - } - member { - name: "ConditionalAccumulatorBase" - mtype: "" - } member { name: "ConfigProto" mtype: "" @@ -24,14 +16,6 @@ tf_module { name: "DType" mtype: "" } - member { - name: "DeviceSpec" - mtype: "" - } - member { - name: "Dimension" - mtype: "" - } member { name: "Event" mtype: "" @@ -56,10 +40,6 @@ tf_module { name: "GraphDef" mtype: "" } - member { - name: "GraphKeys" - mtype: "" - } member { name: "GraphOptions" mtype: "" @@ -137,11 +117,11 @@ tf_module { mtype: "" } member { - name: "TensorInfo" - mtype: "" + name: "TensorShape" + mtype: "" } member { - name: "TensorShape" + name: "TensorSpec" mtype: "" } member { @@ -160,10 +140,6 @@ tf_module { name: "VariableSynchronization" mtype: "" } - member { - name: "app" - mtype: "" - } member { name: "bfloat16" mtype: "" @@ -200,6 +176,10 @@ tf_module { name: "debugging" mtype: "" } + member { + name: "distribute" + mtype: "" + } member { name: "double" mtype: "" @@ -224,10 +204,6 @@ tf_module { name: "feature_column" mtype: "" } - member { - name: "flags" - mtype: "" - } member { name: "float16" mtype: "" @@ -240,10 +216,6 @@ tf_module { name: "float64" mtype: "" } - member { - name: "gfile" - mtype: "" - } member { name: "glorot_uniform_initializer" mtype: "" @@ -296,10 +268,6 @@ tf_module { name: "lite" mtype: "" } - member { - name: "logging" - mtype: "" - } member { name: "losses" mtype: "" @@ -328,14 +296,6 @@ tf_module { name: "ones_initializer" mtype: "" } - member { - name: "profiler" - mtype: "" - } - member { - name: "pywrap_tensorflow" - mtype: "" - } member { name: "qint16" mtype: "" @@ -392,10 +352,6 @@ tf_module { name: "sparse" mtype: "" } - member { - name: "spectral" - mtype: "" - } member { name: "string" mtype: "" @@ -476,14 +432,6 @@ tf_module { name: "add_n" argspec: "args=[\'inputs\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "arg_max" - argspec: "args=[\'input\', \'dimension\', \'output_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " - } - member_method { - name: "arg_min" - argspec: "args=[\'input\', \'dimension\', \'output_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " - } member_method { name: "argmax" argspec: "args=[\'input\', \'axis\', \'output_type\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\'], " @@ -492,6 +440,10 @@ tf_module { name: "argmin" argspec: "args=[\'input\', \'axis\', \'output_type\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\'], " } + member_method { + name: "argsort" + argspec: "args=[\'values\', \'axis\', \'direction\', \'stable\', \'name\'], varargs=None, keywords=None, defaults=[\'-1\', \'ASCENDING\', \'False\', \'None\'], " + } member_method { name: "as_dtype" argspec: "args=[\'type_value\'], varargs=None, keywords=None, defaults=None" @@ -510,19 +462,19 @@ tf_module { } member_method { name: "assert_equal" - argspec: "args=[\'x\', \'y\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_greater" - argspec: "args=[\'x\', \'y\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_less" - argspec: "args=[\'x\', \'y\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'y\', \'message\', \'summarize\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "assert_rank" - argspec: "args=[\'x\', \'rank\', \'data\', \'summarize\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'x\', \'rank\', \'message\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "atan" @@ -546,10 +498,6 @@ tf_module { } member_method { name: "batch_to_space" - argspec: "args=[\'input\', \'crops\', \'block_size\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "batch_to_space_nd" argspec: "args=[\'input\', \'block_shape\', \'crops\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { @@ -580,10 +528,6 @@ tf_module { name: "cast" argspec: "args=[\'x\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "clip_by_average_norm" - argspec: "args=[\'t\', \'clip_norm\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } member_method { name: "clip_by_global_norm" argspec: "args=[\'t_list\', \'clip_norm\', \'use_norm\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " @@ -606,11 +550,11 @@ tf_module { } member_method { name: "cond" - argspec: "args=[\'pred\', \'true_fn\', \'false_fn\', \'strict\', \'name\', \'fn1\', \'fn2\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'pred\', \'true_fn\', \'false_fn\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "constant" - argspec: "args=[\'value\', \'dtype\', \'shape\', \'name\', \'verify_shape\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'Const\', \'False\'], " + argspec: "args=[\'value\', \'dtype\', \'shape\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'Const\'], " } member_method { name: "control_dependencies" @@ -628,14 +572,6 @@ tf_module { name: "cosh" argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "count_nonzero" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'dtype\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \"\", \'None\', \'None\', \'None\'], " - } - member_method { - name: "create_partitioned_variables" - argspec: "args=[\'shape\', \'slicing\', \'initializer\', \'dtype\', \'trainable\', \'collections\', \'name\', \'reuse\'], varargs=None, keywords=None, defaults=[\"\", \'True\', \'None\', \'None\', \'None\'], " - } member_method { name: "cumsum" argspec: "args=[\'x\', \'axis\', \'exclusive\', \'reverse\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'False\', \'False\', \'None\'], " @@ -648,10 +584,6 @@ tf_module { name: "device" argspec: "args=[\'device_name\'], varargs=None, keywords=None, defaults=None" } - member_method { - name: "div" - argspec: "args=[\'x\', \'y\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } member_method { name: "div_no_nan" argspec: "args=[\'x\', \'y\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -676,10 +608,6 @@ tf_module { name: "einsum" argspec: "args=[\'equation\'], varargs=inputs, keywords=kwargs, defaults=None" } - member_method { - name: "enable_eager_execution" - argspec: "args=[\'config\', \'device_policy\', \'execution_mode\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " - } member_method { name: "ensure_shape" argspec: "args=[\'x\', \'shape\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -698,7 +626,7 @@ tf_module { } member_method { name: "expand_dims" - argspec: "args=[\'input\', \'axis\', \'name\', \'dim\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'input\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "extract_volume_patches" @@ -712,10 +640,6 @@ tf_module { name: "fill" argspec: "args=[\'dims\', \'value\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "fixed_size_partitioner" - argspec: "args=[\'num_shards\', \'axis\'], varargs=None, keywords=None, defaults=[\'0\'], " - } member_method { name: "floor" argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -738,31 +662,23 @@ tf_module { } member_method { name: "function" - argspec: "args=[\'func\', \'input_signature\', \'autograph\', \'experimental_autograph_options\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'None\'], " + argspec: "args=[\'func\', \'input_signature\', \'autograph\', \'experimental_autograph_options\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\', \'None\'], " } member_method { name: "gather" - argspec: "args=[\'params\', \'indices\', \'validate_indices\', \'name\', \'axis\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'0\'], " + argspec: "args=[\'params\', \'indices\', \'validate_indices\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'None\'], " } member_method { name: "gather_nd" argspec: "args=[\'params\', \'indices\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { - name: "get_collection" - argspec: "args=[\'key\', \'scope\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "get_collection_ref" - argspec: "args=[\'key\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_default_graph" + name: "get_logger" argspec: "args=[], varargs=None, keywords=None, defaults=None" } member_method { name: "gradients" - argspec: "args=[\'ys\', \'xs\', \'grad_ys\', \'name\', \'colocate_gradients_with_ops\', \'gate_gradients\', \'aggregation_method\', \'stop_gradients\', \'unconnected_gradients\'], varargs=None, keywords=None, defaults=[\'None\', \'gradients\', \'False\', \'False\', \'None\', \'None\', \'UnconnectedGradients.NONE\'], " + argspec: "args=[\'ys\', \'xs\', \'grad_ys\', \'name\', \'gate_gradients\', \'aggregation_method\', \'stop_gradients\', \'unconnected_gradients\'], varargs=None, keywords=None, defaults=[\'None\', \'gradients\', \'False\', \'None\', \'None\', \'UnconnectedGradients.NONE\'], " } member_method { name: "greater" @@ -782,7 +698,7 @@ tf_module { } member_method { name: "hessians" - argspec: "args=[\'ys\', \'xs\', \'name\', \'colocate_gradients_with_ops\', \'gate_gradients\', \'aggregation_method\'], varargs=None, keywords=None, defaults=[\'hessians\', \'False\', \'False\', \'None\'], " + argspec: "args=[\'ys\', \'xs\', \'gate_gradients\', \'aggregation_method\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\', \'hessians\'], " } member_method { name: "histogram_fixed_width" @@ -816,18 +732,10 @@ tf_module { name: "less_equal" argspec: "args=[\'x\', \'y\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "lin_space" - argspec: "args=[\'start\', \'stop\', \'num\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } member_method { name: "linspace" argspec: "args=[\'start\', \'stop\', \'num\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "load_file_system_library" - argspec: "args=[\'library_filename\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "load_library" argspec: "args=[\'library_location\'], varargs=None, keywords=None, defaults=None" @@ -836,14 +744,6 @@ tf_module { name: "load_op_library" argspec: "args=[\'library_filename\'], varargs=None, keywords=None, defaults=None" } - member_method { - name: "log" - argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "log1p" - argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } member_method { name: "logical_and" argspec: "args=[\'x\', \'y\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -880,10 +780,6 @@ tf_module { name: "meshgrid" argspec: "args=[], varargs=args, keywords=kwargs, defaults=None" } - member_method { - name: "min_max_variable_partitioner" - argspec: "args=[\'max_partitions\', \'axis\', \'min_slice_size\', \'bytes_per_string_element\'], varargs=None, keywords=None, defaults=[\'1\', \'0\', \'262144\', \'16\'], " - } member_method { name: "minimum" argspec: "args=[\'x\', \'y\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -892,10 +788,6 @@ tf_module { name: "mod" argspec: "args=[\'x\', \'y\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "multinomial" - argspec: "args=[\'logits\', \'num_samples\', \'seed\', \'name\', \'output_dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " - } member_method { name: "multiply" argspec: "args=[\'x\', \'y\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -918,7 +810,7 @@ tf_module { } member_method { name: "norm" - argspec: "args=[\'tensor\', \'ord\', \'axis\', \'keepdims\', \'name\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'euclidean\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'tensor\', \'ord\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'euclidean\', \'None\', \'None\', \'None\'], " } member_method { name: "not_equal" @@ -934,11 +826,11 @@ tf_module { } member_method { name: "ones_like" - argspec: "args=[\'tensor\', \'dtype\', \'name\', \'optimize\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " + argspec: "args=[\'input\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "pad" - argspec: "args=[\'tensor\', \'paddings\', \'mode\', \'name\', \'constant_values\'], varargs=None, keywords=None, defaults=[\'CONSTANT\', \'None\', \'0\'], " + argspec: "args=[\'tensor\', \'paddings\', \'mode\', \'constant_values\', \'name\'], varargs=None, keywords=None, defaults=[\'CONSTANT\', \'0\', \'None\'], " } member_method { name: "parallel_stack" @@ -956,10 +848,6 @@ tf_module { name: "py_function" argspec: "args=[\'func\', \'inp\', \'Tout\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "quantize_v2" - argspec: "args=[\'input\', \'min_range\', \'max_range\', \'T\', \'mode\', \'name\', \'round_mode\'], varargs=None, keywords=None, defaults=[\'MIN_COMBINED\', \'None\', \'HALF_AWAY_FROM_ZERO\'], " - } member_method { name: "range" argspec: "args=[\'start\', \'limit\', \'delta\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'range\'], " @@ -974,35 +862,35 @@ tf_module { } member_method { name: "reduce_all" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_any" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_logsumexp" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_max" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_mean" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_min" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_prod" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "reduce_sum" - argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\', \'reduction_indices\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input_tensor\', \'axis\', \'keepdims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " } member_method { name: "register_tensor_conversion_function" @@ -1012,10 +900,6 @@ tf_module { name: "required_space_to_batch_paddings" argspec: "args=[\'input_shape\', \'block_shape\', \'base_paddings\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } - member_method { - name: "reset_default_graph" - argspec: "args=[], varargs=None, keywords=None, defaults=None" - } member_method { name: "reshape" argspec: "args=[\'tensor\', \'shape\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -1026,7 +910,7 @@ tf_module { } member_method { name: "reverse_sequence" - argspec: "args=[\'input\', \'seq_lengths\', \'seq_axis\', \'batch_axis\', \'name\', \'seq_dim\', \'batch_dim\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'input\', \'seq_lengths\', \'seq_axis\', \'batch_axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { name: "roll" @@ -1042,7 +926,7 @@ tf_module { } member_method { name: "scalar_mul" - argspec: "args=[\'scalar\', \'x\'], varargs=None, keywords=None, defaults=None" + argspec: "args=[\'scalar\', \'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "scan" @@ -1076,13 +960,9 @@ tf_module { name: "sequence_mask" argspec: "args=[\'lengths\', \'maxlen\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\'], " } - member_method { - name: "set_random_seed" - argspec: "args=[\'seed\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "shape" - argspec: "args=[\'input\', \'name\', \'out_type\'], varargs=None, keywords=None, defaults=[\'None\', \"\"], " + argspec: "args=[\'input\', \'out_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " } member_method { name: "shape_n" @@ -1106,43 +986,19 @@ tf_module { } member_method { name: "size" - argspec: "args=[\'input\', \'name\', \'out_type\'], varargs=None, keywords=None, defaults=[\'None\', \"\"], " + argspec: "args=[\'input\', \'out_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " } member_method { name: "slice" argspec: "args=[\'input_\', \'begin\', \'size\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { - name: "space_to_batch_nd" - argspec: "args=[\'input\', \'block_shape\', \'paddings\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "sparse_concat" - argspec: "args=[\'axis\', \'sp_inputs\', \'name\', \'expand_nonconcat_dim\', \'concat_dim\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " - } - member_method { - name: "sparse_reduce_max" - argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'reduction_axes\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "sparse_reduce_max_sparse" - argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'reduction_axes\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "sparse_reduce_sum" - argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'reduction_axes\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "sparse_reduce_sum_sparse" - argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'reduction_axes\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + name: "sort" + argspec: "args=[\'values\', \'axis\', \'direction\', \'name\'], varargs=None, keywords=None, defaults=[\'-1\', \'ASCENDING\', \'None\'], " } member_method { - name: "sparse_split" - argspec: "args=[\'keyword_required\', \'sp_input\', \'num_split\', \'axis\', \'name\', \'split_dim\'], varargs=None, keywords=None, defaults=[\'KeywordRequired()\', \'None\', \'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "sparse_to_dense" - argspec: "args=[\'sparse_indices\', \'output_shape\', \'sparse_values\', \'default_value\', \'validate_indices\', \'name\'], varargs=None, keywords=None, defaults=[\'0\', \'True\', \'None\'], " + name: "space_to_batch_nd" + argspec: "args=[\'input\', \'block_shape\', \'paddings\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "split" @@ -1158,7 +1014,7 @@ tf_module { } member_method { name: "squeeze" - argspec: "args=[\'input\', \'axis\', \'name\', \'squeeze_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + argspec: "args=[\'input\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "stack" @@ -1192,6 +1048,18 @@ tf_module { name: "tanh" argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "tensor_scatter_add" + argspec: "args=[\'tensor\', \'indices\', \'updates\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "tensor_scatter_sub" + argspec: "args=[\'tensor\', \'indices\', \'updates\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "tensor_scatter_update" + argspec: "args=[\'tensor\', \'indices\', \'updates\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + } member_method { name: "tensordot" argspec: "args=[\'a\', \'b\', \'axes\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -1206,16 +1074,12 @@ tf_module { } member_method { name: "transpose" - argspec: "args=[\'a\', \'perm\', \'name\', \'conjugate\'], varargs=None, keywords=None, defaults=[\'None\', \'transpose\', \'False\'], " + argspec: "args=[\'a\', \'perm\', \'conjugate\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'transpose\'], " } member_method { name: "truediv" argspec: "args=[\'x\', \'y\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "truncated_normal" - argspec: "args=[\'shape\', \'mean\', \'stddev\', \'dtype\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'0.0\', \'1.0\', \"\", \'None\', \'None\'], " - } member_method { name: "truncatediv" argspec: "args=[\'x\', \'y\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -1226,7 +1090,7 @@ tf_module { } member_method { name: "tuple" - argspec: "args=[\'tensors\', \'name\', \'control_inputs\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'tensors\', \'control_inputs\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "unique" @@ -1244,10 +1108,6 @@ tf_module { name: "unstack" argspec: "args=[\'value\', \'num\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'unstack\'], " } - member_method { - name: "variable_axis_size_partitioner" - argspec: "args=[\'max_shard_bytes\', \'axis\', \'bytes_per_string_element\', \'max_shards\'], varargs=None, keywords=None, defaults=[\'0\', \'16\', \'None\'], " - } member_method { name: "variable_creator_scope" argspec: "args=[\'variable_creator\'], varargs=None, keywords=None, defaults=None" @@ -1258,7 +1118,7 @@ tf_module { } member_method { name: "while_loop" - argspec: "args=[\'cond\', \'body\', \'loop_vars\', \'shape_invariants\', \'parallel_iterations\', \'back_prop\', \'swap_memory\', \'name\', \'maximum_iterations\', \'return_same_structure\'], varargs=None, keywords=None, defaults=[\'None\', \'10\', \'True\', \'False\', \'None\', \'None\', \'False\'], " + argspec: "args=[\'cond\', \'body\', \'loop_vars\', \'shape_invariants\', \'parallel_iterations\', \'back_prop\', \'swap_memory\', \'maximum_iterations\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'10\', \'True\', \'False\', \'None\', \'None\'], " } member_method { name: "zeros" @@ -1266,6 +1126,6 @@ tf_module { } member_method { name: "zeros_like" - argspec: "args=[\'tensor\', \'dtype\', \'name\', \'optimize\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " + argspec: "args=[\'input\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.-checker.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.-checker.pbtxt deleted file mode 100644 index e09c44cc9c..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.-checker.pbtxt +++ /dev/null @@ -1,12 +0,0 @@ -path: "tensorflow.profiler.AdviceProto.Checker" -tf_proto { - descriptor { - name: "Checker" - field { - name: "reports" - number: 2 - label: LABEL_REPEATED - type: TYPE_STRING - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.-checkers-entry.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.-checkers-entry.pbtxt deleted file mode 100644 index 8746243549..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.-checkers-entry.pbtxt +++ /dev/null @@ -1,22 +0,0 @@ -path: "tensorflow.profiler.AdviceProto.CheckersEntry" -tf_proto { - descriptor { - name: "CheckersEntry" - field { - name: "key" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - field { - name: "value" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.AdviceProto.Checker" - } - options { - map_entry: true - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.pbtxt deleted file mode 100644 index a8a8858ccd..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-advice-proto.pbtxt +++ /dev/null @@ -1,41 +0,0 @@ -path: "tensorflow.profiler.AdviceProto" -tf_proto { - descriptor { - name: "AdviceProto" - field { - name: "checkers" - number: 1 - label: LABEL_REPEATED - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.AdviceProto.CheckersEntry" - } - nested_type { - name: "CheckersEntry" - field { - name: "key" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - field { - name: "value" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.AdviceProto.Checker" - } - options { - map_entry: true - } - } - nested_type { - name: "Checker" - field { - name: "reports" - number: 2 - label: LABEL_REPEATED - type: TYPE_STRING - } - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-graph-node-proto.-input-shapes-entry.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-graph-node-proto.-input-shapes-entry.pbtxt deleted file mode 100644 index afec73f537..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-graph-node-proto.-input-shapes-entry.pbtxt +++ /dev/null @@ -1,22 +0,0 @@ -path: "tensorflow.profiler.GraphNodeProto.InputShapesEntry" -tf_proto { - descriptor { - name: "InputShapesEntry" - field { - name: "key" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_INT32 - } - field { - name: "value" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_MESSAGE - type_name: ".tensorflow.TensorShapeProto" - } - options { - map_entry: true - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-graph-node-proto.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-graph-node-proto.pbtxt deleted file mode 100644 index 3c83177005..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-graph-node-proto.pbtxt +++ /dev/null @@ -1,191 +0,0 @@ -path: "tensorflow.profiler.GraphNodeProto" -tf_proto { - descriptor { - name: "GraphNodeProto" - field { - name: "name" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - field { - name: "tensor_value" - number: 15 - label: LABEL_OPTIONAL - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.TFProfTensorProto" - } - field { - name: "run_count" - number: 21 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "exec_micros" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "accelerator_exec_micros" - number: 17 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "cpu_exec_micros" - number: 18 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "requested_bytes" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "peak_bytes" - number: 24 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "residual_bytes" - number: 25 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "output_bytes" - number: 26 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "parameters" - number: 4 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "float_ops" - number: 13 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "devices" - number: 10 - label: LABEL_REPEATED - type: TYPE_STRING - } - field { - name: "total_definition_count" - number: 23 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_run_count" - number: 22 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_exec_micros" - number: 6 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_accelerator_exec_micros" - number: 19 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_cpu_exec_micros" - number: 20 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_requested_bytes" - number: 7 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_peak_bytes" - number: 27 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_residual_bytes" - number: 28 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_output_bytes" - number: 29 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_parameters" - number: 8 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_float_ops" - number: 14 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "shapes" - number: 11 - label: LABEL_REPEATED - type: TYPE_MESSAGE - type_name: ".tensorflow.TensorShapeProto" - } - field { - name: "input_shapes" - number: 16 - label: LABEL_REPEATED - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.GraphNodeProto.InputShapesEntry" - } - field { - name: "children" - number: 12 - label: LABEL_REPEATED - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.GraphNodeProto" - } - nested_type { - name: "InputShapesEntry" - field { - name: "key" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_INT32 - } - field { - name: "value" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_MESSAGE - type_name: ".tensorflow.TensorShapeProto" - } - options { - map_entry: true - } - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-multi-graph-node-proto.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-multi-graph-node-proto.pbtxt deleted file mode 100644 index 2b08a05437..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-multi-graph-node-proto.pbtxt +++ /dev/null @@ -1,134 +0,0 @@ -path: "tensorflow.profiler.MultiGraphNodeProto" -tf_proto { - descriptor { - name: "MultiGraphNodeProto" - field { - name: "name" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - field { - name: "exec_micros" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "accelerator_exec_micros" - number: 12 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "cpu_exec_micros" - number: 13 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "requested_bytes" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "peak_bytes" - number: 16 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "residual_bytes" - number: 17 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "output_bytes" - number: 18 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "parameters" - number: 4 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "float_ops" - number: 5 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_exec_micros" - number: 6 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_accelerator_exec_micros" - number: 14 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_cpu_exec_micros" - number: 15 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_requested_bytes" - number: 7 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_peak_bytes" - number: 19 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_residual_bytes" - number: 20 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_output_bytes" - number: 21 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_parameters" - number: 8 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "total_float_ops" - number: 9 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "graph_nodes" - number: 10 - label: LABEL_REPEATED - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.GraphNodeProto" - } - field { - name: "children" - number: 11 - label: LABEL_REPEATED - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.MultiGraphNodeProto" - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-op-log-proto.-id-to-string-entry.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-op-log-proto.-id-to-string-entry.pbtxt deleted file mode 100644 index b3adc50c7e..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-op-log-proto.-id-to-string-entry.pbtxt +++ /dev/null @@ -1,21 +0,0 @@ -path: "tensorflow.profiler.OpLogProto.IdToStringEntry" -tf_proto { - descriptor { - name: "IdToStringEntry" - field { - name: "key" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "value" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - options { - map_entry: true - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-op-log-proto.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-op-log-proto.pbtxt deleted file mode 100644 index 7510c566ba..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-op-log-proto.pbtxt +++ /dev/null @@ -1,38 +0,0 @@ -path: "tensorflow.profiler.OpLogProto" -tf_proto { - descriptor { - name: "OpLogProto" - field { - name: "log_entries" - number: 1 - label: LABEL_REPEATED - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.OpLogEntry" - } - field { - name: "id_to_string" - number: 2 - label: LABEL_REPEATED - type: TYPE_MESSAGE - type_name: ".tensorflow.tfprof.OpLogProto.IdToStringEntry" - } - nested_type { - name: "IdToStringEntry" - field { - name: "key" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_INT64 - } - field { - name: "value" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_STRING - } - options { - map_entry: true - } - } - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-profile-option-builder.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-profile-option-builder.pbtxt deleted file mode 100644 index 19ff38a390..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-profile-option-builder.pbtxt +++ /dev/null @@ -1,93 +0,0 @@ -path: "tensorflow.profiler.ProfileOptionBuilder" -tf_class { - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'options\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "account_displayed_op_only" - argspec: "args=[\'self\', \'is_true\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "build" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "float_operation" - argspec: "args=[], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "order_by" - argspec: "args=[\'self\', \'attribute\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "select" - argspec: "args=[\'self\', \'attributes\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "time_and_memory" - argspec: "args=[\'min_micros\', \'min_bytes\', \'min_accelerator_micros\', \'min_cpu_micros\', \'min_peak_bytes\', \'min_residual_bytes\', \'min_output_bytes\'], varargs=None, keywords=None, defaults=[\'1\', \'1\', \'0\', \'0\', \'0\', \'0\', \'0\'], " - } - member_method { - name: "trainable_variables_parameter" - argspec: "args=[], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_accounted_types" - argspec: "args=[\'self\', \'account_type_regexes\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_empty_output" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_file_output" - argspec: "args=[\'self\', \'outfile\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_max_depth" - argspec: "args=[\'self\', \'max_depth\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_min_execution_time" - argspec: "args=[\'self\', \'min_micros\', \'min_accelerator_micros\', \'min_cpu_micros\'], varargs=None, keywords=None, defaults=[\'0\', \'0\', \'0\'], " - } - member_method { - name: "with_min_float_operations" - argspec: "args=[\'self\', \'min_float_ops\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_min_memory" - argspec: "args=[\'self\', \'min_bytes\', \'min_peak_bytes\', \'min_residual_bytes\', \'min_output_bytes\'], varargs=None, keywords=None, defaults=[\'0\', \'0\', \'0\', \'0\'], " - } - member_method { - name: "with_min_occurrence" - argspec: "args=[\'self\', \'min_occurrence\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_min_parameters" - argspec: "args=[\'self\', \'min_params\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_node_names" - argspec: "args=[\'self\', \'start_name_regexes\', \'show_name_regexes\', \'hide_name_regexes\', \'trim_name_regexes\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "with_pprof_output" - argspec: "args=[\'self\', \'pprof_file\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_stdout_output" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_step" - argspec: "args=[\'self\', \'step\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "with_timeline_output" - argspec: "args=[\'self\', \'timeline_file\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-profiler.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.-profiler.pbtxt deleted file mode 100644 index acb61dae9f..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.-profiler.pbtxt +++ /dev/null @@ -1,37 +0,0 @@ -path: "tensorflow.profiler.Profiler" -tf_class { - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'graph\', \'op_log\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "add_step" - argspec: "args=[\'self\', \'step\', \'run_meta\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "advise" - argspec: "args=[\'self\', \'options\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "profile_graph" - argspec: "args=[\'self\', \'options\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "profile_name_scope" - argspec: "args=[\'self\', \'options\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "profile_operations" - argspec: "args=[\'self\', \'options\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "profile_python" - argspec: "args=[\'self\', \'options\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "serialize_to_string" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.profiler.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.profiler.pbtxt deleted file mode 100644 index 7b4d3ac522..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.profiler.pbtxt +++ /dev/null @@ -1,39 +0,0 @@ -path: "tensorflow.profiler" -tf_module { - member { - name: "AdviceProto" - mtype: "" - } - member { - name: "GraphNodeProto" - mtype: "" - } - member { - name: "MultiGraphNodeProto" - mtype: "" - } - member { - name: "OpLogProto" - mtype: "" - } - member { - name: "ProfileOptionBuilder" - mtype: "" - } - member { - name: "Profiler" - mtype: "" - } - member_method { - name: "advise" - argspec: "args=[\'graph\', \'run_meta\', \'options\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'0\'], " - } - member_method { - name: "profile" - argspec: "args=[\'graph\', \'run_meta\', \'op_log\', \'cmd\', \'options\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'scope\', \'0\'], " - } - member_method { - name: "write_op_log" - argspec: "args=[\'graph\', \'log_dir\', \'op_log\', \'run_meta\', \'add_trace\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'True\'], " - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.quantization.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.quantization.pbtxt index 2948b7318e..632c2f8f83 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.quantization.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.quantization.pbtxt @@ -34,7 +34,7 @@ tf_module { } member_method { name: "quantize_and_dequantize" - argspec: "args=[\'input\', \'input_min\', \'input_max\', \'signed_input\', \'num_bits\', \'range_given\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'8\', \'False\', \'None\'], " + argspec: "args=[\'input\', \'input_min\', \'input_max\', \'signed_input\', \'num_bits\', \'range_given\', \'round_mode\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'8\', \'False\', \'HALF_TO_EVEN\', \'None\'], " } member_method { name: "quantized_concat" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.random.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.random.pbtxt index 160c09798d..de5cb6b717 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.random.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.random.pbtxt @@ -1,20 +1,24 @@ path: "tensorflow.random" tf_module { member_method { - name: "gamma" - argspec: "args=[\'shape\', \'alpha\', \'beta\', \'dtype\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\', \'None\'], " + name: "all_candidate_sampler" + argspec: "args=[\'true_classes\', \'num_true\', \'num_sampled\', \'unique\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { - name: "get_seed" - argspec: "args=[\'op_seed\'], varargs=None, keywords=None, defaults=None" + name: "categorical" + argspec: "args=[\'logits\', \'num_samples\', \'dtype\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " } member_method { - name: "log_uniform_candidate_sampler" - argspec: "args=[\'true_classes\', \'num_true\', \'num_sampled\', \'unique\', \'range_max\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + name: "fixed_unigram_candidate_sampler" + argspec: "args=[\'true_classes\', \'num_true\', \'num_sampled\', \'unique\', \'range_max\', \'vocab_file\', \'distortion\', \'num_reserved_ids\', \'num_shards\', \'shard\', \'unigrams\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'\', \'1.0\', \'0\', \'1\', \'0\', \'()\', \'None\', \'None\'], " + } + member_method { + name: "gamma" + argspec: "args=[\'shape\', \'alpha\', \'beta\', \'dtype\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \"\", \'None\', \'None\'], " } member_method { - name: "multinomial" - argspec: "args=[\'logits\', \'num_samples\', \'seed\', \'name\', \'output_dtype\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " + name: "log_uniform_candidate_sampler" + argspec: "args=[\'true_classes\', \'num_true\', \'num_sampled\', \'unique\', \'range_max\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "normal" @@ -22,10 +26,10 @@ tf_module { } member_method { name: "poisson" - argspec: "args=[\'lam\', \'shape\', \'dtype\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\', \'None\'], " + argspec: "args=[\'shape\', \'lam\', \'dtype\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\', \'None\'], " } member_method { - name: "set_random_seed" + name: "set_seed" argspec: "args=[\'seed\'], varargs=None, keywords=None, defaults=None" } member_method { @@ -33,8 +37,8 @@ tf_module { argspec: "args=[\'value\', \'seed\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { - name: "stateless_multinomial" - argspec: "args=[\'logits\', \'num_samples\', \'seed\', \'output_dtype\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " + name: "stateless_categorical" + argspec: "args=[\'logits\', \'num_samples\', \'seed\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " } member_method { name: "stateless_normal" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.saved_model.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.saved_model.pbtxt index d57936a2f1..63bebb20bc 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.saved_model.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.saved_model.pbtxt @@ -32,14 +32,6 @@ tf_module { name: "GPU" mtype: "" } - member { - name: "LEGACY_INIT_OP_KEY" - mtype: "" - } - member { - name: "MAIN_OP_KEY" - mtype: "" - } member { name: "PREDICT_INPUTS" mtype: "" @@ -105,12 +97,12 @@ tf_module { argspec: "args=[\'examples\', \'classes\', \'scores\'], varargs=None, keywords=None, defaults=None" } member_method { - name: "is_valid_signature" - argspec: "args=[\'signature_def\'], varargs=None, keywords=None, defaults=None" + name: "contains_saved_model" + argspec: "args=[\'export_dir\'], varargs=None, keywords=None, defaults=None" } member_method { - name: "maybe_saved_model_directory" - argspec: "args=[\'export_dir\'], varargs=None, keywords=None, defaults=None" + name: "is_valid_signature" + argspec: "args=[\'signature_def\'], varargs=None, keywords=None, defaults=None" } member_method { name: "predict_signature_def" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.sets.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.sets.pbtxt index 8a196b1a55..900d08ff47 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.sets.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.sets.pbtxt @@ -1,19 +1,19 @@ path: "tensorflow.sets" tf_module { member_method { - name: "set_difference" + name: "difference" argspec: "args=[\'a\', \'b\', \'aminusb\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\', \'True\'], " } member_method { - name: "set_intersection" + name: "intersection" argspec: "args=[\'a\', \'b\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\'], " } member_method { - name: "set_size" + name: "size" argspec: "args=[\'a\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\'], " } member_method { - name: "set_union" + name: "union" argspec: "args=[\'a\', \'b\', \'validate_indices\'], varargs=None, keywords=None, defaults=[\'True\'], " } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.signal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.signal.pbtxt index 2c50c41f18..ea717b4d71 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.signal.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.signal.pbtxt @@ -1,5 +1,9 @@ path: "tensorflow.signal" tf_module { + member_method { + name: "dct" + argspec: "args=[\'input\', \'type\', \'n\', \'axis\', \'norm\', \'name\'], varargs=None, keywords=None, defaults=[\'2\', \'None\', \'-1\', \'None\', \'None\'], " + } member_method { name: "fft" argspec: "args=[\'input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -24,6 +28,10 @@ tf_module { name: "hann_window" argspec: "args=[\'window_length\', \'periodic\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \"\", \'None\'], " } + member_method { + name: "idct" + argspec: "args=[\'input\', \'type\', \'n\', \'axis\', \'norm\', \'name\'], varargs=None, keywords=None, defaults=[\'2\', \'None\', \'-1\', \'None\', \'None\'], " + } member_method { name: "ifft" argspec: "args=[\'input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -44,6 +52,18 @@ tf_module { name: "inverse_stft_window_fn" argspec: "args=[\'frame_step\', \'forward_window_fn\', \'name\'], varargs=None, keywords=None, defaults=[\'\', \'None\'], " } + member_method { + name: "irfft" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "irfft2d" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "irfft3d" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "linear_to_mel_weight_matrix" argspec: "args=[\'num_mel_bins\', \'num_spectrogram_bins\', \'sample_rate\', \'lower_edge_hertz\', \'upper_edge_hertz\', \'dtype\', \'name\'], varargs=None, keywords=None, defaults=[\'20\', \'129\', \'8000\', \'125.0\', \'3800.0\', \"\", \'None\'], " @@ -56,6 +76,18 @@ tf_module { name: "overlap_and_add" argspec: "args=[\'signal\', \'frame_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "rfft" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "rfft2d" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } + member_method { + name: "rfft3d" + argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + } member_method { name: "stft" argspec: "args=[\'signals\', \'frame_length\', \'frame_step\', \'fft_length\', \'window_fn\', \'pad_end\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'\', \'False\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.sparse.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.sparse.pbtxt index 9c9c4d838e..9808200d72 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.sparse.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.sparse.pbtxt @@ -10,11 +10,11 @@ tf_module { } member_method { name: "add" - argspec: "args=[\'a\', \'b\', \'thresh\'], varargs=None, keywords=None, defaults=[\'0\'], " + argspec: "args=[\'a\', \'b\', \'threshold\'], varargs=None, keywords=None, defaults=[\'0\'], " } member_method { name: "concat" - argspec: "args=[\'axis\', \'sp_inputs\', \'name\', \'expand_nonconcat_dim\', \'concat_dim\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'None\'], " + argspec: "args=[\'axis\', \'sp_inputs\', \'expand_nonconcat_dim\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " } member_method { name: "cross" @@ -40,37 +40,21 @@ tf_module { name: "mask" argspec: "args=[\'a\', \'mask_indices\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "matmul" - argspec: "args=[\'sp_a\', \'b\', \'adjoint_a\', \'adjoint_b\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'False\', \'None\'], " - } member_method { name: "maximum" argspec: "args=[\'sp_a\', \'sp_b\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "merge" - argspec: "args=[\'sp_ids\', \'sp_values\', \'vocab_size\', \'name\', \'already_sorted\'], varargs=None, keywords=None, defaults=[\'None\', \'False\'], " - } member_method { name: "minimum" argspec: "args=[\'sp_a\', \'sp_b\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "reduce_max" - argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'reduction_axes\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "reduce_max_sparse" - argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'reduction_axes\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'output_is_sparse\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'None\'], " } member_method { name: "reduce_sum" - argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'reduction_axes\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "reduce_sum_sparse" - argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'reduction_axes\', \'keep_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'sp_input\', \'axis\', \'keepdims\', \'output_is_sparse\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'None\'], " } member_method { name: "reorder" @@ -90,15 +74,15 @@ tf_module { } member_method { name: "segment_mean" - argspec: "args=[\'data\', \'indices\', \'segment_ids\', \'name\', \'num_segments\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'data\', \'indices\', \'segment_ids\', \'num_segments\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "segment_sqrt_n" - argspec: "args=[\'data\', \'indices\', \'segment_ids\', \'name\', \'num_segments\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'data\', \'indices\', \'segment_ids\', \'num_segments\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "segment_sum" - argspec: "args=[\'data\', \'indices\', \'segment_ids\', \'name\', \'num_segments\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + argspec: "args=[\'data\', \'indices\', \'segment_ids\', \'num_segments\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { name: "slice" @@ -108,9 +92,13 @@ tf_module { name: "softmax" argspec: "args=[\'sp_input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } + member_method { + name: "sparse_dense_matmul" + argspec: "args=[\'sp_a\', \'b\', \'adjoint_a\', \'adjoint_b\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'False\', \'None\'], " + } member_method { name: "split" - argspec: "args=[\'keyword_required\', \'sp_input\', \'num_split\', \'axis\', \'name\', \'split_dim\'], varargs=None, keywords=None, defaults=[\'KeywordRequired()\', \'None\', \'None\', \'None\', \'None\', \'None\'], " + argspec: "args=[\'sp_input\', \'num_split\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { name: "to_dense" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.spectral.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.spectral.pbtxt deleted file mode 100644 index b0f0783e30..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.spectral.pbtxt +++ /dev/null @@ -1,35 +0,0 @@ -path: "tensorflow.spectral" -tf_module { - member_method { - name: "dct" - argspec: "args=[\'input\', \'type\', \'n\', \'axis\', \'norm\', \'name\'], varargs=None, keywords=None, defaults=[\'2\', \'None\', \'-1\', \'None\', \'None\'], " - } - member_method { - name: "idct" - argspec: "args=[\'input\', \'type\', \'n\', \'axis\', \'norm\', \'name\'], varargs=None, keywords=None, defaults=[\'2\', \'None\', \'-1\', \'None\', \'None\'], " - } - member_method { - name: "irfft" - argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "irfft2d" - argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "irfft3d" - argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "rfft" - argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "rfft2d" - argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "rfft3d" - argspec: "args=[\'input_tensor\', \'fft_length\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.strings.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.strings.pbtxt index 03144cbe70..f6e32ed08c 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.strings.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.strings.pbtxt @@ -10,11 +10,11 @@ tf_module { } member_method { name: "length" - argspec: "args=[\'input\', \'name\', \'unit\'], varargs=None, keywords=None, defaults=[\'None\', \'BYTE\'], " + argspec: "args=[\'input\', \'unit\', \'name\'], varargs=None, keywords=None, defaults=[\'BYTE\', \'None\'], " } member_method { name: "reduce_join" - argspec: "args=[\'inputs\', \'axis\', \'keep_dims\', \'separator\', \'name\', \'reduction_indices\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'\', \'None\', \'None\'], " + argspec: "args=[\'inputs\', \'axis\', \'keepdims\', \'separator\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'False\', \'\', \'None\'], " } member_method { name: "regex_full_match" @@ -34,11 +34,11 @@ tf_module { } member_method { name: "substr" - argspec: "args=[\'input\', \'pos\', \'len\', \'name\', \'unit\'], varargs=None, keywords=None, defaults=[\'None\', \'BYTE\'], " + argspec: "args=[\'input\', \'pos\', \'len\', \'unit\', \'name\'], varargs=None, keywords=None, defaults=[\'BYTE\', \'None\'], " } member_method { name: "to_hash_bucket" - argspec: "args=[\'string_tensor\', \'num_buckets\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " + argspec: "args=[\'input\', \'num_buckets\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "to_hash_bucket_fast" @@ -50,7 +50,11 @@ tf_module { } member_method { name: "to_number" - argspec: "args=[\'string_tensor\', \'out_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " + argspec: "args=[\'input\', \'out_type\', \'name\'], varargs=None, keywords=None, defaults=[\"\", \'None\'], " + } + member_method { + name: "unicode_encode" + argspec: "args=[\'input\', \'output_encoding\', \'errors\', \'replacement_char\', \'name\'], varargs=None, keywords=None, defaults=[\'replace\', \'65533\', \'None\'], " } member_method { name: "unicode_script" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.summary.-summary-writer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.summary.-summary-writer.pbtxt new file mode 100644 index 0000000000..6715c14e16 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.summary.-summary-writer.pbtxt @@ -0,0 +1,29 @@ +path: "tensorflow.summary.SummaryWriter" +tf_class { + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'resource\', \'init_op_fn\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "as_default" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "close" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "flush" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "init" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "set_as_default" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.summary.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.summary.pbtxt index 7ed9cd77a0..42a74a65fb 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.summary.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.summary.pbtxt @@ -24,44 +24,24 @@ tf_module { name: "SummaryDescription" mtype: "" } + member { + name: "SummaryWriter" + mtype: "" + } member { name: "TaggedRunMetadata" mtype: "" } member_method { - name: "audio" - argspec: "args=[\'name\', \'tensor\', \'sample_rate\', \'max_outputs\', \'collections\', \'family\'], varargs=None, keywords=None, defaults=[\'3\', \'None\', \'None\'], " - } - member_method { - name: "get_summary_description" - argspec: "args=[\'node_def\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "histogram" - argspec: "args=[\'name\', \'values\', \'collections\', \'family\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "image" - argspec: "args=[\'name\', \'tensor\', \'max_outputs\', \'collections\', \'family\'], varargs=None, keywords=None, defaults=[\'3\', \'None\', \'None\'], " - } - member_method { - name: "merge" - argspec: "args=[\'inputs\', \'collections\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "merge_all" - argspec: "args=[\'key\', \'scope\', \'name\'], varargs=None, keywords=None, defaults=[\'summaries\', \'None\', \'None\'], " - } - member_method { - name: "scalar" - argspec: "args=[\'name\', \'tensor\', \'collections\', \'family\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " + name: "create_file_writer" + argspec: "args=[\'logdir\', \'max_queue\', \'flush_millis\', \'filename_suffix\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\'], " } member_method { - name: "tensor_summary" - argspec: "args=[\'name\', \'tensor\', \'summary_description\', \'collections\', \'summary_metadata\', \'family\', \'display_name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\'], " + name: "flush" + argspec: "args=[\'writer\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " } member_method { - name: "text" - argspec: "args=[\'name\', \'tensor\', \'collections\'], varargs=None, keywords=None, defaults=[\'None\'], " + name: "import_event" + argspec: "args=[\'tensor\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.test.-benchmark.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.test.-benchmark.pbtxt index df528e26b6..6fc489c860 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.test.-benchmark.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.test.-benchmark.pbtxt @@ -6,6 +6,10 @@ tf_class { member_method { name: "__init__" } + member_method { + name: "evaluate" + argspec: "args=[\'self\', \'tensors\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "is_abstract" argspec: "args=[\'cls\'], varargs=None, keywords=None, defaults=None" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.test.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.test.pbtxt index af3f06d8de..72ce733044 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.test.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.test.pbtxt @@ -12,26 +12,14 @@ tf_module { name: "TestCase" mtype: "" } - member { - name: "mock" - mtype: "" - } member_method { name: "assert_equal_graph_def" - argspec: "args=[\'actual\', \'expected\', \'checkpoint_v2\'], varargs=None, keywords=None, defaults=[\'False\'], " + argspec: "args=[\'actual\', \'expected\'], varargs=None, keywords=None, defaults=None" } member_method { name: "benchmark_config" argspec: "args=[], varargs=None, keywords=None, defaults=None" } - member_method { - name: "compute_gradient" - argspec: "args=[\'x\', \'x_shape\', \'y\', \'y_shape\', \'x_init_value\', \'delta\', \'init_targets\', \'extra_feed_dict\'], varargs=None, keywords=None, defaults=[\'None\', \'0.001\', \'None\', \'None\'], " - } - member_method { - name: "compute_gradient_error" - argspec: "args=[\'x\', \'x_shape\', \'y\', \'y_shape\', \'x_init_value\', \'delta\', \'extra_feed_dict\'], varargs=None, keywords=None, defaults=[\'None\', \'0.001\', \'None\'], " - } member_method { name: "create_local_cluster" argspec: "args=[\'num_workers\', \'num_ps\', \'protocol\', \'worker_config\', \'ps_config\'], varargs=None, keywords=None, defaults=[\'grpc\', \'None\', \'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-adadelta-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-adadelta-optimizer.pbtxt deleted file mode 100644 index 1f1d8b6f9e..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-adadelta-optimizer.pbtxt +++ /dev/null @@ -1,51 +0,0 @@ -path: "tensorflow.train.AdadeltaOptimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'learning_rate\', \'rho\', \'epsilon\', \'use_locking\', \'name\'], varargs=None, keywords=None, defaults=[\'0.001\', \'0.95\', \'1e-08\', \'False\', \'Adadelta\'], " - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-adagrad-d-a-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-adagrad-d-a-optimizer.pbtxt deleted file mode 100644 index a7c05d4849..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-adagrad-d-a-optimizer.pbtxt +++ /dev/null @@ -1,51 +0,0 @@ -path: "tensorflow.train.AdagradDAOptimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'learning_rate\', \'global_step\', \'initial_gradient_squared_accumulator_value\', \'l1_regularization_strength\', \'l2_regularization_strength\', \'use_locking\', \'name\'], varargs=None, keywords=None, defaults=[\'0.1\', \'0.0\', \'0.0\', \'False\', \'AdagradDA\'], " - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-adagrad-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-adagrad-optimizer.pbtxt deleted file mode 100644 index bc8b92389c..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-adagrad-optimizer.pbtxt +++ /dev/null @@ -1,51 +0,0 @@ -path: "tensorflow.train.AdagradOptimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'learning_rate\', \'initial_accumulator_value\', \'use_locking\', \'name\'], varargs=None, keywords=None, defaults=[\'0.1\', \'False\', \'Adagrad\'], " - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-adam-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-adam-optimizer.pbtxt deleted file mode 100644 index 5d17be9378..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-adam-optimizer.pbtxt +++ /dev/null @@ -1,51 +0,0 @@ -path: "tensorflow.train.AdamOptimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'learning_rate\', \'beta1\', \'beta2\', \'epsilon\', \'use_locking\', \'name\'], varargs=None, keywords=None, defaults=[\'0.001\', \'0.9\', \'0.999\', \'1e-08\', \'False\', \'Adam\'], " - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-checkpoint-saver-listener.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-checkpoint-saver-listener.pbtxt deleted file mode 100644 index 9d3688e565..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-checkpoint-saver-listener.pbtxt +++ /dev/null @@ -1,24 +0,0 @@ -path: "tensorflow.train.CheckpointSaverListener" -tf_class { - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - } - member_method { - name: "after_save" - argspec: "args=[\'self\', \'session\', \'global_step_value\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "before_save" - argspec: "args=[\'self\', \'session\', \'global_step_value\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "begin" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "end" - argspec: "args=[\'self\', \'session\', \'global_step_value\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-chief-session-creator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-chief-session-creator.pbtxt deleted file mode 100644 index abbe273be3..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-chief-session-creator.pbtxt +++ /dev/null @@ -1,14 +0,0 @@ -path: "tensorflow.train.ChiefSessionCreator" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'scaffold\', \'master\', \'config\', \'checkpoint_dir\', \'checkpoint_filename_with_path\'], varargs=None, keywords=None, defaults=[\'None\', \'\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "create_session" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-ftrl-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-ftrl-optimizer.pbtxt deleted file mode 100644 index d265fdeb01..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-ftrl-optimizer.pbtxt +++ /dev/null @@ -1,51 +0,0 @@ -path: "tensorflow.train.FtrlOptimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'learning_rate\', \'learning_rate_power\', \'initial_accumulator_value\', \'l1_regularization_strength\', \'l2_regularization_strength\', \'use_locking\', \'name\', \'accum_name\', \'linear_name\', \'l2_shrinkage_regularization_strength\'], varargs=None, keywords=None, defaults=[\'-0.5\', \'0.1\', \'0.0\', \'0.0\', \'False\', \'Ftrl\', \'None\', \'None\', \'0.0\'], " - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-gradient-descent-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-gradient-descent-optimizer.pbtxt deleted file mode 100644 index c673e29cd4..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-gradient-descent-optimizer.pbtxt +++ /dev/null @@ -1,51 +0,0 @@ -path: "tensorflow.train.GradientDescentOptimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'learning_rate\', \'use_locking\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'GradientDescent\'], " - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-looper-thread.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-looper-thread.pbtxt deleted file mode 100644 index c61859004e..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-looper-thread.pbtxt +++ /dev/null @@ -1,73 +0,0 @@ -path: "tensorflow.train.LooperThread" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "daemon" - mtype: "" - } - member { - name: "ident" - mtype: "" - } - member { - name: "name" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'coord\', \'timer_interval_secs\', \'target\', \'args\', \'kwargs\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " - } - member_method { - name: "getName" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "isAlive" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "isDaemon" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "is_alive" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "join" - argspec: "args=[\'self\', \'timeout\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "loop" - argspec: "args=[\'coord\', \'timer_interval_secs\', \'target\', \'args\', \'kwargs\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "run" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "run_loop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "setDaemon" - argspec: "args=[\'self\', \'daemonic\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "setName" - argspec: "args=[\'self\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "start" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "start_loop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "stop_loop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-momentum-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-momentum-optimizer.pbtxt deleted file mode 100644 index 8199f63b9b..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-momentum-optimizer.pbtxt +++ /dev/null @@ -1,51 +0,0 @@ -path: "tensorflow.train.MomentumOptimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'learning_rate\', \'momentum\', \'use_locking\', \'name\', \'use_nesterov\'], varargs=None, keywords=None, defaults=[\'False\', \'Momentum\', \'False\'], " - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-monitored-session.-step-context.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-monitored-session.-step-context.pbtxt deleted file mode 100644 index 03efe6639e..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-monitored-session.-step-context.pbtxt +++ /dev/null @@ -1,21 +0,0 @@ -path: "tensorflow.train.MonitoredSession.StepContext" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "session" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'session\', \'run_with_hooks_fn\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "request_stop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "run_with_hooks" - argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-monitored-session.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-monitored-session.pbtxt deleted file mode 100644 index 09b7b3fb53..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-monitored-session.pbtxt +++ /dev/null @@ -1,34 +0,0 @@ -path: "tensorflow.train.MonitoredSession" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "StepContext" - mtype: "" - } - member { - name: "graph" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'session_creator\', \'hooks\', \'stop_grace_period_secs\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'120\'], " - } - member_method { - name: "close" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "run" - argspec: "args=[\'self\', \'fetches\', \'feed_dict\', \'options\', \'run_metadata\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " - } - member_method { - name: "run_step_fn" - argspec: "args=[\'self\', \'step_fn\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "should_stop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-nan-loss-during-training-error.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-nan-loss-during-training-error.pbtxt deleted file mode 100644 index e415819b3d..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-nan-loss-during-training-error.pbtxt +++ /dev/null @@ -1,12 +0,0 @@ -path: "tensorflow.train.NanLossDuringTrainingError" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "args" - mtype: "" - } - member_method { - name: "__init__" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-optimizer.pbtxt deleted file mode 100644 index 876bb35e39..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-optimizer.pbtxt +++ /dev/null @@ -1,50 +0,0 @@ -path: "tensorflow.train.Optimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'use_locking\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-proximal-adagrad-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-proximal-adagrad-optimizer.pbtxt deleted file mode 100644 index 14349a74ef..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-proximal-adagrad-optimizer.pbtxt +++ /dev/null @@ -1,51 +0,0 @@ -path: "tensorflow.train.ProximalAdagradOptimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'learning_rate\', \'initial_accumulator_value\', \'l1_regularization_strength\', \'l2_regularization_strength\', \'use_locking\', \'name\'], varargs=None, keywords=None, defaults=[\'0.1\', \'0.0\', \'0.0\', \'False\', \'ProximalAdagrad\'], " - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-r-m-s-prop-optimizer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-r-m-s-prop-optimizer.pbtxt deleted file mode 100644 index 906384a287..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-r-m-s-prop-optimizer.pbtxt +++ /dev/null @@ -1,51 +0,0 @@ -path: "tensorflow.train.RMSPropOptimizer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "GATE_GRAPH" - mtype: "" - } - member { - name: "GATE_NONE" - mtype: "" - } - member { - name: "GATE_OP" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'learning_rate\', \'decay\', \'momentum\', \'epsilon\', \'use_locking\', \'centered\', \'name\'], varargs=None, keywords=None, defaults=[\'0.9\', \'0.0\', \'1e-10\', \'False\', \'False\', \'RMSProp\'], " - } - member_method { - name: "apply_gradients" - argspec: "args=[\'self\', \'grads_and_vars\', \'global_step\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "compute_gradients" - argspec: "args=[\'self\', \'loss\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'1\', \'None\', \'False\', \'None\'], " - } - member_method { - name: "get_name" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot" - argspec: "args=[\'self\', \'var\', \'name\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_slot_names" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "minimize" - argspec: "args=[\'self\', \'loss\', \'global_step\', \'var_list\', \'gate_gradients\', \'aggregation_method\', \'colocate_gradients_with_ops\', \'name\', \'grad_loss\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'1\', \'None\', \'False\', \'None\', \'None\'], " - } - member_method { - name: "variables" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-scaffold.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-scaffold.pbtxt deleted file mode 100644 index 38cc98b48e..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-scaffold.pbtxt +++ /dev/null @@ -1,53 +0,0 @@ -path: "tensorflow.train.Scaffold" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "init_feed_dict" - mtype: "" - } - member { - name: "init_fn" - mtype: "" - } - member { - name: "init_op" - mtype: "" - } - member { - name: "local_init_op" - mtype: "" - } - member { - name: "ready_for_local_init_op" - mtype: "" - } - member { - name: "ready_op" - mtype: "" - } - member { - name: "saver" - mtype: "" - } - member { - name: "summary_op" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'init_op\', \'init_feed_dict\', \'init_fn\', \'ready_op\', \'ready_for_local_init_op\', \'local_init_op\', \'summary_op\', \'saver\', \'copy_from_scaffold\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'None\', \'None\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "default_local_init_op" - argspec: "args=[], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "finalize" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_or_default" - argspec: "args=[\'arg_name\', \'collection_key\', \'default_constructor\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-second-or-step-timer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-second-or-step-timer.pbtxt deleted file mode 100644 index 3c5a6ac13c..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-second-or-step-timer.pbtxt +++ /dev/null @@ -1,26 +0,0 @@ -path: "tensorflow.train.SecondOrStepTimer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'every_secs\', \'every_steps\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "last_triggered_step" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "reset" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "should_trigger_for_step" - argspec: "args=[\'self\', \'step\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "update_last_triggered_step" - argspec: "args=[\'self\', \'step\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-creator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-session-creator.pbtxt deleted file mode 100644 index beb232715f..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-creator.pbtxt +++ /dev/null @@ -1,12 +0,0 @@ -path: "tensorflow.train.SessionCreator" -tf_class { - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - } - member_method { - name: "create_session" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-manager.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-session-manager.pbtxt deleted file mode 100644 index 448764fe08..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-manager.pbtxt +++ /dev/null @@ -1,21 +0,0 @@ -path: "tensorflow.train.SessionManager" -tf_class { - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'local_init_op\', \'ready_op\', \'ready_for_local_init_op\', \'graph\', \'recovery_wait_secs\', \'local_init_run_options\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'30\', \'None\'], " - } - member_method { - name: "prepare_session" - argspec: "args=[\'self\', \'master\', \'init_op\', \'saver\', \'checkpoint_dir\', \'checkpoint_filename_with_path\', \'wait_for_checkpoint\', \'max_wait_secs\', \'config\', \'init_feed_dict\', \'init_fn\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'None\', \'False\', \'7200\', \'None\', \'None\', \'None\'], " - } - member_method { - name: "recover_session" - argspec: "args=[\'self\', \'master\', \'saver\', \'checkpoint_dir\', \'checkpoint_filename_with_path\', \'wait_for_checkpoint\', \'max_wait_secs\', \'config\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'False\', \'7200\', \'None\'], " - } - member_method { - name: "wait_for_session" - argspec: "args=[\'self\', \'master\', \'config\', \'max_wait_secs\'], varargs=None, keywords=None, defaults=[\'None\', \'inf\'], " - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-args.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-args.pbtxt deleted file mode 100644 index 442990893e..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-args.pbtxt +++ /dev/null @@ -1,27 +0,0 @@ -path: "tensorflow.train.SessionRunArgs" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "feed_dict" - mtype: "" - } - member { - name: "fetches" - mtype: "" - } - member { - name: "options" - mtype: "" - } - member_method { - name: "__init__" - } - member_method { - name: "count" - } - member_method { - name: "index" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-context.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-context.pbtxt deleted file mode 100644 index d5adb15c95..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-context.pbtxt +++ /dev/null @@ -1,25 +0,0 @@ -path: "tensorflow.train.SessionRunContext" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "original_args" - mtype: "" - } - member { - name: "session" - mtype: "" - } - member { - name: "stop_requested" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'original_args\', \'session\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "request_stop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-values.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-values.pbtxt deleted file mode 100644 index 0b401d59c4..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-session-run-values.pbtxt +++ /dev/null @@ -1,27 +0,0 @@ -path: "tensorflow.train.SessionRunValues" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "options" - mtype: "" - } - member { - name: "results" - mtype: "" - } - member { - name: "run_metadata" - mtype: "" - } - member_method { - name: "__init__" - } - member_method { - name: "count" - } - member_method { - name: "index" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-singular-monitored-session.-step-context.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-singular-monitored-session.-step-context.pbtxt deleted file mode 100644 index 36d8ce7ff8..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-singular-monitored-session.-step-context.pbtxt +++ /dev/null @@ -1,21 +0,0 @@ -path: "tensorflow.train.SingularMonitoredSession.StepContext" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "session" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'session\', \'run_with_hooks_fn\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "request_stop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "run_with_hooks" - argspec: "args=[\'self\'], varargs=args, keywords=kwargs, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-singular-monitored-session.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-singular-monitored-session.pbtxt deleted file mode 100644 index de0f2c1c1a..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-singular-monitored-session.pbtxt +++ /dev/null @@ -1,38 +0,0 @@ -path: "tensorflow.train.SingularMonitoredSession" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "StepContext" - mtype: "" - } - member { - name: "graph" - mtype: "" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'hooks\', \'scaffold\', \'master\', \'config\', \'checkpoint_dir\', \'stop_grace_period_secs\', \'checkpoint_filename_with_path\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'\', \'None\', \'None\', \'120\', \'None\'], " - } - member_method { - name: "close" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "raw_session" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "run" - argspec: "args=[\'self\', \'fetches\', \'feed_dict\', \'options\', \'run_metadata\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\'], " - } - member_method { - name: "run_step_fn" - argspec: "args=[\'self\', \'step_fn\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "should_stop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-supervisor.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-supervisor.pbtxt deleted file mode 100644 index 9677e5a98e..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-supervisor.pbtxt +++ /dev/null @@ -1,153 +0,0 @@ -path: "tensorflow.train.Supervisor" -tf_class { - is_instance: "" - is_instance: "" - member { - name: "USE_DEFAULT" - mtype: "" - } - member { - name: "coord" - mtype: "" - } - member { - name: "global_step" - mtype: "" - } - member { - name: "init_feed_dict" - mtype: "" - } - member { - name: "init_op" - mtype: "" - } - member { - name: "is_chief" - mtype: "" - } - member { - name: "ready_for_local_init_op" - mtype: "" - } - member { - name: "ready_op" - mtype: "" - } - member { - name: "save_model_secs" - mtype: "" - } - member { - name: "save_path" - mtype: "" - } - member { - name: "save_summaries_secs" - mtype: "" - } - member { - name: "saver" - mtype: "" - } - member { - name: "session_manager" - mtype: "" - } - member { - name: "summary_op" - mtype: "" - } - member { - name: "summary_writer" - mtype: "" - } - member_method { - name: "Loop" - argspec: "args=[\'self\', \'timer_interval_secs\', \'target\', \'args\', \'kwargs\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "PrepareSession" - argspec: "args=[\'self\', \'master\', \'config\', \'wait_for_checkpoint\', \'max_wait_secs\', \'start_standard_services\'], varargs=None, keywords=None, defaults=[\'\', \'None\', \'False\', \'7200\', \'True\'], " - } - member_method { - name: "RequestStop" - argspec: "args=[\'self\', \'ex\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "ShouldStop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "StartQueueRunners" - argspec: "args=[\'self\', \'sess\', \'queue_runners\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "StartStandardServices" - argspec: "args=[\'self\', \'sess\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "Stop" - argspec: "args=[\'self\', \'threads\', \'close_summary_writer\', \'ignore_live_threads\'], varargs=None, keywords=None, defaults=[\'None\', \'True\', \'False\'], " - } - member_method { - name: "StopOnException" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "SummaryComputed" - argspec: "args=[\'self\', \'sess\', \'summary\', \'global_step\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "WaitForStop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "__init__" - argspec: "args=[\'self\', \'graph\', \'ready_op\', \'ready_for_local_init_op\', \'is_chief\', \'init_op\', \'init_feed_dict\', \'local_init_op\', \'logdir\', \'summary_op\', \'saver\', \'global_step\', \'save_summaries_secs\', \'save_model_secs\', \'recovery_wait_secs\', \'stop_grace_secs\', \'checkpoint_basename\', \'session_manager\', \'summary_writer\', \'init_fn\', \'local_init_run_options\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'0\', \'True\', \'0\', \'None\', \'0\', \'None\', \'0\', \'0\', \'0\', \'120\', \'600\', \'30\', \'120\', \'model.ckpt\', \'None\', \'0\', \'None\', \'None\'], " - } - member_method { - name: "loop" - argspec: "args=[\'self\', \'timer_interval_secs\', \'target\', \'args\', \'kwargs\'], varargs=None, keywords=None, defaults=[\'None\', \'None\'], " - } - member_method { - name: "managed_session" - argspec: "args=[], varargs=args, keywords=kwds, defaults=None" - } - member_method { - name: "prepare_or_wait_for_session" - argspec: "args=[\'self\', \'master\', \'config\', \'wait_for_checkpoint\', \'max_wait_secs\', \'start_standard_services\'], varargs=None, keywords=None, defaults=[\'\', \'None\', \'False\', \'7200\', \'True\'], " - } - member_method { - name: "request_stop" - argspec: "args=[\'self\', \'ex\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "should_stop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "start_queue_runners" - argspec: "args=[\'self\', \'sess\', \'queue_runners\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "start_standard_services" - argspec: "args=[\'self\', \'sess\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "stop" - argspec: "args=[\'self\', \'threads\', \'close_summary_writer\', \'ignore_live_threads\'], varargs=None, keywords=None, defaults=[\'None\', \'True\', \'False\'], " - } - member_method { - name: "stop_on_exception" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "summary_computed" - argspec: "args=[\'self\', \'sess\', \'summary\', \'global_step\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "wait_for_stop" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-vocab-info.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-vocab-info.pbtxt deleted file mode 100644 index 39b946b82f..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-vocab-info.pbtxt +++ /dev/null @@ -1,43 +0,0 @@ -path: "tensorflow.train.VocabInfo" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member { - name: "axis" - mtype: "" - } - member { - name: "backup_initializer" - mtype: "" - } - member { - name: "new_vocab" - mtype: "" - } - member { - name: "new_vocab_size" - mtype: "" - } - member { - name: "num_oov_buckets" - mtype: "" - } - member { - name: "old_vocab" - mtype: "" - } - member { - name: "old_vocab_size" - mtype: "" - } - member_method { - name: "__init__" - } - member_method { - name: "count" - } - member_method { - name: "index" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.-worker-session-creator.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.-worker-session-creator.pbtxt deleted file mode 100644 index ac26358068..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.-worker-session-creator.pbtxt +++ /dev/null @@ -1,14 +0,0 @@ -path: "tensorflow.train.WorkerSessionCreator" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'scaffold\', \'master\', \'config\', \'max_wait_secs\'], varargs=None, keywords=None, defaults=[\'None\', \'\', \'None\', \'1800\'], " - } - member_method { - name: "create_session" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.train.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.train.pbtxt index a091daa298..3ff4b69d39 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.train.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.train.pbtxt @@ -1,21 +1,5 @@ path: "tensorflow.train" tf_module { - member { - name: "AdadeltaOptimizer" - mtype: "" - } - member { - name: "AdagradDAOptimizer" - mtype: "" - } - member { - name: "AdagradOptimizer" - mtype: "" - } - member { - name: "AdamOptimizer" - mtype: "" - } member { name: "BytesList" mtype: "" @@ -32,14 +16,6 @@ tf_module { name: "CheckpointSaverHook" mtype: "" } - member { - name: "CheckpointSaverListener" - mtype: "" - } - member { - name: "ChiefSessionCreator" - mtype: "" - } member { name: "ClusterDef" mtype: "" @@ -88,18 +64,10 @@ tf_module { name: "FloatList" mtype: "" } - member { - name: "FtrlOptimizer" - mtype: "" - } member { name: "GlobalStepWaiterHook" mtype: "" } - member { - name: "GradientDescentOptimizer" - mtype: "" - } member { name: "Int64List" mtype: "" @@ -112,54 +80,14 @@ tf_module { name: "LoggingTensorHook" mtype: "" } - member { - name: "LooperThread" - mtype: "" - } - member { - name: "MomentumOptimizer" - mtype: "" - } - member { - name: "MonitoredSession" - mtype: "" - } - member { - name: "NanLossDuringTrainingError" - mtype: "" - } member { name: "NanTensorHook" mtype: "" } - member { - name: "Optimizer" - mtype: "" - } - member { - name: "ProfilerHook" - mtype: "" - } - member { - name: "ProximalAdagradOptimizer" - mtype: "" - } member { name: "ProximalGradientDescentOptimizer" mtype: "" } - member { - name: "RMSPropOptimizer" - mtype: "" - } - member { - name: "Scaffold" - mtype: "" - } - member { - name: "SecondOrStepTimer" - mtype: "" - } member { name: "SequenceExample" mtype: "" @@ -172,34 +100,10 @@ tf_module { name: "ServerDef" mtype: "" } - member { - name: "SessionCreator" - mtype: "" - } - member { - name: "SessionManager" - mtype: "" - } - member { - name: "SessionRunArgs" - mtype: "" - } - member { - name: "SessionRunContext" - mtype: "" - } member { name: "SessionRunHook" mtype: "" } - member { - name: "SessionRunValues" - mtype: "" - } - member { - name: "SingularMonitoredSession" - mtype: "" - } member { name: "StepCounterHook" mtype: "" @@ -212,22 +116,6 @@ tf_module { name: "SummarySaverHook" mtype: "" } - member { - name: "Supervisor" - mtype: "" - } - member { - name: "VocabInfo" - mtype: "" - } - member { - name: "WorkerSessionCreator" - mtype: "" - } - member_method { - name: "NewCheckpointReader" - argspec: "args=[\'filepattern\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "cosine_decay" argspec: "args=[\'learning_rate\', \'global_step\', \'decay_steps\', \'alpha\', \'name\'], varargs=None, keywords=None, defaults=[\'0.0\', \'None\'], " @@ -244,10 +132,6 @@ tf_module { name: "get_checkpoint_state" argspec: "args=[\'checkpoint_dir\', \'latest_filename\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "init_from_checkpoint" - argspec: "args=[\'ckpt_dir_or_file\', \'assignment_map\'], varargs=None, keywords=None, defaults=None" - } member_method { name: "inverse_time_decay" argspec: "args=[\'learning_rate\', \'global_step\', \'decay_steps\', \'decay_rate\', \'staircase\', \'name\'], varargs=None, keywords=None, defaults=[\'False\', \'None\'], " @@ -281,17 +165,13 @@ tf_module { argspec: "args=[\'learning_rate\', \'global_step\', \'decay_steps\', \'initial_variance\', \'variance_decay\', \'num_periods\', \'alpha\', \'beta\', \'name\'], varargs=None, keywords=None, defaults=[\'1.0\', \'0.55\', \'0.5\', \'0.0\', \'0.001\', \'None\'], " } member_method { - name: "piecewise_constant" + name: "piecewise_constant_decay" argspec: "args=[\'x\', \'boundaries\', \'values\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "polynomial_decay" argspec: "args=[\'learning_rate\', \'global_step\', \'decay_steps\', \'end_learning_rate\', \'power\', \'cycle\', \'name\'], varargs=None, keywords=None, defaults=[\'0.0001\', \'1.0\', \'False\', \'None\'], " } - member_method { - name: "replica_device_setter" - argspec: "args=[\'ps_tasks\', \'ps_device\', \'worker_device\', \'merge_devices\', \'cluster\', \'ps_ops\', \'ps_strategy\'], varargs=None, keywords=None, defaults=[\'0\', \'/job:ps\', \'/job:worker\', \'True\', \'None\', \'None\', \'None\'], " - } member_method { name: "sdca_fprint" argspec: "args=[\'input\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -308,8 +188,4 @@ tf_module { name: "summary_iterator" argspec: "args=[\'path\'], varargs=None, keywords=None, defaults=None" } - member_method { - name: "warm_start" - argspec: "args=[\'ckpt_to_initialize_from\', \'vars_to_warm_start\', \'var_name_to_vocab_info\', \'var_name_to_prev_var_name\'], varargs=None, keywords=None, defaults=[\'.*\', \'None\', \'None\'], " - } } diff --git a/tensorflow/tools/api/tests/api_compatibility_test.py b/tensorflow/tools/api/tests/api_compatibility_test.py index fb489ea80f..e7f23a1174 100644 --- a/tensorflow/tools/api/tests/api_compatibility_test.py +++ b/tensorflow/tools/api/tests/api_compatibility_test.py @@ -33,12 +33,13 @@ import re import sys import tensorflow as tf -from tensorflow._api import v2 as tf_v2 +from tensorflow._api.v2 import v2 as tf_v2 from google.protobuf import message from google.protobuf import text_format from tensorflow.python.lib.io import file_io +from tensorflow.python.framework import test_util from tensorflow.python.platform import resource_loader from tensorflow.python.platform import test from tensorflow.python.platform import tf_logging as logging @@ -126,9 +127,9 @@ def _FilterNonCoreGoldenFiles(golden_file_list): filtered_file_list = [] filtered_package_prefixes = ['tensorflow.%s.' % p for p in _NON_CORE_PACKAGES] for f in golden_file_list: - if any([ + if any( f.rsplit('/')[-1].startswith(pre) for pre in filtered_package_prefixes - ]): + ): continue filtered_file_list.append(f) return filtered_file_list @@ -310,6 +311,7 @@ class ApiCompatibilityTest(test.TestCase): update_goldens=FLAGS.update_goldens, api_version=api_version) + @test_util.run_deprecated_v1 def testAPIBackwardsCompatibility(self): api_version = 1 golden_file_pattern = os.path.join( @@ -328,6 +330,7 @@ class ApiCompatibilityTest(test.TestCase): 'tensorflow.python.util.lazy_loader.LazyLoader' in str(type(tf.contrib))) + @test_util.run_deprecated_v1 def testAPIBackwardsCompatibilityV1(self): api_version = 1 golden_file_pattern = os.path.join( diff --git a/tensorflow/tools/ci_build/Dockerfile.rbe.cuda10.0-cudnn7-ubuntu14.04 b/tensorflow/tools/ci_build/Dockerfile.rbe.cuda10.0-cudnn7-ubuntu14.04 new file mode 100644 index 0000000000..03de89b717 --- /dev/null +++ b/tensorflow/tools/ci_build/Dockerfile.rbe.cuda10.0-cudnn7-ubuntu14.04 @@ -0,0 +1,75 @@ +# To push a new version, run: +# $ docker build -f Dockerfile.rbe.cuda10.0-cudnn7-ubuntu14.04 \ +# --tag "gcr.io/asci-toolchain/nosla-cuda10.0-cudnn7-ubuntu14.04" . +# $ docker push gcr.io/asci-toolchain/nosla-cuda10.0-cudnn7-ubuntu14.04 + +FROM ubuntu:14.04 +LABEL maintainer="Manuel Klimek " + +RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates apt-transport-https gnupg-curl && \ + rm -rf /var/lib/apt/lists/* && \ + NVIDIA_GPGKEY_SUM=d1be581509378368edeec8c1eb2958702feedf3bc3d17011adbf24efacce4ab5 && \ + NVIDIA_GPGKEY_FPR=ae09fe4bbd223a84b2ccfce3f60f4b3d7fa2af80 && \ + apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64/7fa2af80.pub && \ + apt-key adv --export --no-emit-version -a $NVIDIA_GPGKEY_FPR | tail -n +2 > cudasign.pub && \ + echo "$NVIDIA_GPGKEY_SUM cudasign.pub" | sha256sum -c --strict - && rm cudasign.pub && \ + echo "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/x86_64 /" > /etc/apt/sources.list.d/cuda.list && \ + echo "deb https://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1604/x86_64 /" > /etc/apt/sources.list.d/nvidia-ml.list + +ENV CUDA_VERSION 10.0.130 +ENV CUDA_PKG_VERSION 10-0=$CUDA_VERSION-1 +ENV CUDNN_VERSION 7.3.1.20 +ENV NCCL_VERSION 2.3.5 +ENV NVIDIA_DRIVER_CAPABILITIES compute,utility +ENV NVIDIA_REQUIRE_CUDA "cuda>=10.0,driver>=410" +ENV NVIDIA_VISIBLE_DEVICES all +ENV PATH /usr/local/cuda/bin:${PATH} + +# TODO(b/110903506): /usr/loca/cuda/lib64/stubs should not be needed in +# LD_LIBRARY_PATH. The stubs/libcuda.so is not meant to used at runtime. The +# correct way to pass the path to bfd-ld is to pass +# -Wl,-rpath-link=/usr/local/cuda/lib64/stubs to all binaries transitively +# depending on libcuda. Optimally, builds targeting cuda would do that +# internally. +ENV LD_LIBRARY_PATH /usr/local/cuda/lib64/stubs + +LABEL com.nvidia.cudnn.version="${CUDNN_VERSION}" + +RUN apt-get update && apt-get install -y --no-install-recommends \ + cuda-command-line-tools-$CUDA_PKG_VERSION \ + cuda-compat-10-0=410.48-1 \ + cuda-cudart-$CUDA_PKG_VERSION \ + cuda-libraries-$CUDA_PKG_VERSION \ + cuda-libraries-dev-$CUDA_PKG_VERSION \ + cuda-minimal-build-$CUDA_PKG_VERSION \ + cuda-nvml-dev-$CUDA_PKG_VERSION \ + cuda-nvtx-$CUDA_PKG_VERSION \ + libcudnn7=$CUDNN_VERSION-1+cuda10.0 \ + libcudnn7=$CUDNN_VERSION-1+cuda10.0 \ + libcudnn7-dev=$CUDNN_VERSION-1+cuda10.0 \ + libnccl2=$NCCL_VERSION-2+cuda10.0 \ + libnccl-dev=$NCCL_VERSION-2+cuda10.0 && \ + ln -s cuda-10.0 /usr/local/cuda && \ + apt-mark hold libcudnn7 && \ + apt-mark hold libnccl2 && \ + rm -rf /var/lib/apt/lists/* + +# TODO(b/110903506): Provide a link to the SONAME of libcuda.so. +# https://github.com/NVIDIA/nvidia-docker/issues/775 +RUN ln -s libcuda.so /usr/local/cuda/lib64/stubs/libcuda.so.1 + +# TODO(klimek): Once the TODO in tensorflow's configure.py to correctly find +# libnccl is resolved, delete this block. +RUN ln -s /usr/lib/x86_64-linux-gnu/libnccl.so /usr/lib/libnccl.so \ + && ln -s /usr/lib/x86_64-linux-gnu/libnccl.so /usr/lib/libnccl.so.2 + +# Copy and run the install scripts. +COPY install/*.sh /install/ +ARG DEBIAN_FRONTEND=noninteractive +RUN /install/install_bootstrap_deb_packages.sh +RUN add-apt-repository -y ppa:openjdk-r/ppa && \ + add-apt-repository -y ppa:george-edison55/cmake-3.x +RUN /install/install_deb_packages.sh +RUN /install/install_pip_packages.sh +RUN /install/install_golang.sh + diff --git a/tensorflow/tools/ci_build/builds/libtensorflow.sh b/tensorflow/tools/ci_build/builds/libtensorflow.sh index 9b3ff0cba7..44abcc309b 100755 --- a/tensorflow/tools/ci_build/builds/libtensorflow.sh +++ b/tensorflow/tools/ci_build/builds/libtensorflow.sh @@ -55,6 +55,7 @@ function build_libtensorflow_tarball() { export CC_OPT_FLAGS='-mavx' if [ "${TF_NEED_CUDA}" == "1" ]; then BAZEL_OPTS="${BAZEL_OPTS} --config=cuda" + export TF_NEED_ROCM=0 fi bazel clean --expunge yes "" | ./configure diff --git a/tensorflow/tools/ci_build/windows/cpu/pip/build_tf_windows.sh b/tensorflow/tools/ci_build/windows/cpu/pip/build_tf_windows.sh index 177ef390db..46f5bdef09 100644 --- a/tensorflow/tools/ci_build/windows/cpu/pip/build_tf_windows.sh +++ b/tensorflow/tools/ci_build/windows/cpu/pip/build_tf_windows.sh @@ -58,6 +58,8 @@ PY_TEST_DIR="py_test_dir" SKIP_TEST=0 RELEASE_BUILD=0 TEST_TARGET="//${PY_TEST_DIR}/tensorflow/python/..." +PROJECT_NAME="" +EXTRA_BUILD_FLAGS="" # --skip_test Skip running tests # --enable_remote_cache Add options to enable remote cache for build and test @@ -73,6 +75,20 @@ for ARG in "$@"; do --release_build) RELEASE_BUILD=1 ;; --test_core_only) TEST_TARGET="//${PY_TEST_DIR}/tensorflow/python/..." ;; --test_contrib_only) TEST_TARGET="//${PY_TEST_DIR}/tensorflow/contrib/..." ;; + --extra_build_flags) + shift + if [[ -z "$1" ]]; then + break + fi + EXTRA_BUILD_FLAGS="$1" + ;; + --project_name) + shift + if [[ -z "$1" ]]; then + break + fi + PROJECT_NAME="$1" + ;; *) esac done @@ -88,7 +104,11 @@ fi if [[ "$TF_NIGHTLY" == 1 ]]; then python tensorflow/tools/ci_build/update_version.py --nightly - EXTRA_PIP_FLAG="--nightly_flag" + if [ -z ${PROJECT_NAME} ]; then + EXTRA_PIP_FLAGS="--nightly_flag" + else + EXTRA_PIP_FLAGS="--project_name=${PROJECT_NAME} --nightly_flag" + fi fi # Enable short object file path to avoid long path issue on Windows. @@ -100,7 +120,8 @@ fi run_configure_for_cpu_build -bazel build --announce_rc --config=opt tensorflow/tools/pip_package:build_pip_package || exit $? +bazel build --announce_rc --config=opt ${EXTRA_BUILD_FLAGS} \ + tensorflow/tools/pip_package:build_pip_package || exit $? if [[ "$SKIP_TEST" == 1 ]]; then exit 0 @@ -109,7 +130,7 @@ fi # Create a python test directory to avoid package name conflict create_python_test_dir "${PY_TEST_DIR}" -./bazel-bin/tensorflow/tools/pip_package/build_pip_package "$PWD/${PY_TEST_DIR}" "${EXTRA_PIP_FLAG}" +./bazel-bin/tensorflow/tools/pip_package/build_pip_package "$PWD/${PY_TEST_DIR}" "${EXTRA_PIP_FLAGS}" if [[ "$TF_NIGHTLY" == 1 ]]; then exit 0 @@ -126,8 +147,8 @@ N_JOBS="${NUMBER_OF_PROCESSORS}" # which will result testing system installed tensorflow bazel test --announce_rc --config=opt -k --test_output=errors \ --define=no_tensorflow_py_deps=true --test_lang_filters=py \ - --test_tag_filters=-no_pip,-no_windows,-no_oss \ - --build_tag_filters=-no_pip,-no_windows,-no_oss --build_tests_only \ + --test_tag_filters=-no_pip,-no_windows,-no_oss,-gpu \ + --build_tag_filters=-no_pip,-no_windows,-no_oss,-gpu --build_tests_only \ --test_size_filters=small,medium \ --jobs="${N_JOBS}" --test_timeout="300,450,1200,3600" \ --flaky_test_attempts=3 \ diff --git a/tensorflow/tools/ci_build/windows/gpu/pip/build_tf_windows.sh b/tensorflow/tools/ci_build/windows/gpu/pip/build_tf_windows.sh index 6178d7794d..3aec8d6584 100644 --- a/tensorflow/tools/ci_build/windows/gpu/pip/build_tf_windows.sh +++ b/tensorflow/tools/ci_build/windows/gpu/pip/build_tf_windows.sh @@ -58,6 +58,8 @@ PY_TEST_DIR="py_test_dir" SKIP_TEST=0 RELEASE_BUILD=0 TEST_TARGET="//${PY_TEST_DIR}/tensorflow/python/..." +PROJECT_NAME="" +EXTRA_BUILD_FLAGS="" # --skip_test Skip running tests # --enable_remote_cache Add options to enable remote cache for build and test @@ -73,6 +75,20 @@ for ARG in "$@"; do --release_build) RELEASE_BUILD=1 ;; --test_core_only) TEST_TARGET="//${PY_TEST_DIR}/tensorflow/python/..." ;; --test_contrib_only) TEST_TARGET="//${PY_TEST_DIR}/tensorflow/contrib/..." ;; + --extra_build_flags) + shift + if [[ -z "$1" ]]; then + break + fi + EXTRA_BUILD_FLAGS="$1" + ;; + --project_name) + shift + if [[ -z "$1" ]]; then + break + fi + PROJECT_NAME="$1" + ;; *) esac done @@ -88,7 +104,11 @@ fi if [[ "$TF_NIGHTLY" == 1 ]]; then python tensorflow/tools/ci_build/update_version.py --nightly - EXTRA_PIP_FLAG="--nightly_flag" + if [ -z ${PROJECT_NAME} ]; then + EXTRA_PIP_FLAGS="--nightly_flag" + else + EXTRA_PIP_FLAGS="--project_name=${PROJECT_NAME} --nightly_flag" + fi fi # Enable short object file path to avoid long path issue on Windows. @@ -104,6 +124,7 @@ fi run_configure_for_gpu_build bazel build --announce_rc --config=opt --define=no_tensorflow_py_deps=true \ + ${EXTRA_BUILD_FLAGS} \ tensorflow/tools/pip_package:build_pip_package || exit $? if [[ "$SKIP_TEST" == 1 ]]; then @@ -113,7 +134,8 @@ fi # Create a python test directory to avoid package name conflict create_python_test_dir "${PY_TEST_DIR}" -./bazel-bin/tensorflow/tools/pip_package/build_pip_package "$PWD/${PY_TEST_DIR}" --gpu "${EXTRA_PIP_FLAG}" +./bazel-bin/tensorflow/tools/pip_package/build_pip_package "$PWD/${PY_TEST_DIR}" \ + --gpu "${EXTRA_PIP_FLAGS}" if [[ "$TF_NIGHTLY" == 1 ]]; then exit 0 diff --git a/tensorflow/tools/compatibility/BUILD b/tensorflow/tools/compatibility/BUILD index 5f619c4e62..05d924c092 100644 --- a/tensorflow/tools/compatibility/BUILD +++ b/tensorflow/tools/compatibility/BUILD @@ -14,6 +14,18 @@ py_library( srcs_version = "PY2AND3", ) +py_test( + name = "ast_edits_test", + srcs = ["ast_edits_test.py"], + srcs_version = "PY2AND3", + deps = [ + ":ast_edits", + "//tensorflow/python:client_testlib", + "//tensorflow/python:framework_test_lib", + "@six_archive//:six", + ], +) + py_binary( name = "tf_upgrade", srcs = ["tf_upgrade.py"], @@ -39,8 +51,8 @@ py_library( srcs_version = "PY2AND3", ) -py_binary( - name = "tf_upgrade_v2", +py_library( + name = "tf_upgrade_v2_lib", srcs = [ "renames_v2.py", "tf_upgrade_v2.py", @@ -49,14 +61,28 @@ py_binary( deps = [":ast_edits"], ) +py_binary( + name = "tf_upgrade_v2", + srcs = ["tf_upgrade_v2_main.py"], + main = "tf_upgrade_v2_main.py", + srcs_version = "PY2AND3", + deps = [ + ":ast_edits", + ":tf_upgrade_v2_lib", + ], +) + py_test( name = "tf_upgrade_v2_test", srcs = ["tf_upgrade_v2_test.py"], srcs_version = "PY2AND3", deps = [ ":tf_upgrade_v2", + "//tensorflow:tensorflow_py", "//tensorflow/python:client_testlib", "//tensorflow/python:framework_test_lib", + "//tensorflow/tools/common:public_api", + "//tensorflow/tools/common:traverse", "@six_archive//:six", ], ) @@ -100,18 +126,28 @@ py_test( genrule( name = "generate_upgraded_file_v2", testonly = 1, - srcs = ["testdata/test_file_v1_10.py"], + srcs = ["testdata/test_file_v1_12.py"], outs = [ "test_file_v2_0.py", "report_v2.txt", ], cmd = ("$(location :tf_upgrade_v2)" + - " --infile $(location testdata/test_file_v1_10.py)" + + " --infile $(location testdata/test_file_v1_12.py)" + " --outfile $(location test_file_v2_0.py)" + " --reportfile $(location report_v2.txt)"), tools = [":tf_upgrade_v2"], ) +py_test( + name = "test_file_v1_12", + size = "small", + srcs = ["testdata/test_file_v1_12.py"], + srcs_version = "PY2AND3", + deps = [ + "//tensorflow:tensorflow_py", + ], +) + py_test( name = "test_file_v2_0", size = "small", @@ -128,6 +164,6 @@ exports_files( "tf_upgrade.py", "renames_v2.py", "testdata/test_file_v0_11.py", - "testdata/test_file_v1_10.py", + "testdata/test_file_v1_12.py", ], ) diff --git a/tensorflow/tools/compatibility/README.md b/tensorflow/tools/compatibility/README.md index aabc7b253d..6ff42b1fef 100644 --- a/tensorflow/tools/compatibility/README.md +++ b/tensorflow/tools/compatibility/README.md @@ -1,60 +1,77 @@ # TensorFlow Python API Upgrade Utility This tool allows you to upgrade your existing TensorFlow Python scripts. -This script can be run on a single Python file: +Specifically: \ +`tf_upgrade_v2.py`: upgrades code from TensorFlow 1.12 to TensorFlow 2.0 preview. \ +`tf_upgrade.py`: upgrades code to TensorFlow 1.0 from TensorFlow 0.11. + +## Running the script from pip package + +First, install TensorFlow pip package. See +https://www.tensorflow.org/install/pip. + +Upgrade script can be run on a single Python file: ``` -tf_upgrade.py --infile foo.py --outfile foo-upgraded.py +tf_upgrade_v2 --infile foo.py --outfile foo-upgraded.py ``` It will print a list of errors it finds that it can't fix. You can also run it on a directory tree: ``` +# upgrade the .py files and copy all the other files to the outtree +tf_upgrade_v2 --intree coolcode --outtree coolcode-upgraded + # just upgrade the .py files -tf_upgrade.py --intree coolcode --outtree coolcode-upgraded -# after upgrade the .py files, then copy all the other files to the outtree -tf_upgrade.py --intree coolcode --outtree coolcode-upgraded --copyotherfiles True +tf_upgrade_v2 --intree coolcode --outtree coolcode-upgraded --copyotherfiles False ``` -In either case, it will also dump out a report e.g. which will detail changes + +## Report + +The script will also dump out a report e.g. which will detail changes e.g.: ``` -third_party/tensorflow/tools/compatibility/test_file_v0.11.py Line 125 +'tensorflow/tools/compatibility/testdata/test_file_v1_12.py' Line 65 +-------------------------------------------------------------------------------- + +Added keyword 'input' to reordered function 'tf.argmax' +Renamed keyword argument from 'dimension' to 'axis' -Renamed keyword argument from `dim` to `axis` -Renamed keyword argument from `squeeze_dims` to `axis` + Old: tf.argmax([[1, 3, 2]], dimension=0)) + ~~~~~~~~~~ + New: tf.argmax(input=[[1, 3, 2]], axis=0)) - Old: [[1, 2, 3]], dim=1), squeeze_dims=[1]).eval(), - ~~~~ ~~~~~~~~~~~~~ - New: [[1, 2, 3]], axis=1), axis=[1]).eval(), - ~~~~~ ~~~~~ ``` ## Caveats - Don't update parts of your code manually before running this script. In -particular, functions that have had reordered arguments like `tf.concat` -or `tf.split` will cause the script to incorrectly add keyword arguments that -mismap arguments. +particular, functions that have had reordered arguments like `tf.argmax` +or `tf.batch_to_space` will cause the script to incorrectly add keyword +arguments that mismap arguments. - This script wouldn't actually reorder arguments. Instead, the script will add keyword arguments to functions that had their arguments reordered. - This script is not able to upgrade all functions. One notable example is -`tf.reverse()` which has been changed to take a list of indices rather than -a tensor of bools. If the script detects this, it will report this to stdout +`tf.nn.conv2d` that no longer takes `use_cudnn_on_gpu` argument. +If the script detects this, it will report this to stdout (and in the report), and you can fix it manually. For example if you have -`tf.reverse(a, [False, True, True])` you will need to manually change it to -`tf.reverse(a, [1, 2])`. +`tf.nn.conv2d(inputs, filters, strides, padding, use_cudnn_on_gpu=True)` +you will need to manually change it to +`tf.nn.conv2d(input, filters, strides, padding)`. - There are some syntaxes that are not handleable with this script as this -script was designed to use only standard python packages. If the script fails -with "A necessary keyword argument failed to be inserted." or +script was designed to use only standard python packages. +There is an alternative available for TensorFlow 0.* to 1.0 upgrade script. +If the script fails with "A necessary keyword argument failed to be inserted." or "Failed to find keyword lexicographically. Fix manually.", you can try [@machrisaa's fork of this script](https://github.com/machrisaa/tf0to1). [@machrisaa](https://github.com/machrisaa) has used the [RedBaron Python refactoring engine](https://redbaron.readthedocs.io/en/latest/) which is able to localize syntactic elements more reliably than the built-in -`ast` module this script is based upon. +`ast` module this script is based upon. Note that the alternative script is not +available for TensorFlow 2.0 upgrade. diff --git a/tensorflow/tools/compatibility/ast_edits.py b/tensorflow/tools/compatibility/ast_edits.py index 56c67b8356..eac2150502 100644 --- a/tensorflow/tools/compatibility/ast_edits.py +++ b/tensorflow/tools/compatibility/ast_edits.py @@ -21,11 +21,16 @@ from __future__ import print_function import ast import collections import os +import re import shutil import sys import tempfile import traceback +# Some regular expressions we will need for parsing +FIND_OPEN = re.compile(r"^\s*(\[).*$") +FIND_STRING_CHARS = re.compile(r"['\"]") + class APIChangeSpec(object): """This class defines the transformations that need to happen. @@ -40,6 +45,10 @@ class APIChangeSpec(object): * `function_reorders`: maps functions whose argument order has changed to the list of arguments in the new order * `function_handle`: maps function names to custom handlers for the function + * `function_warnings`: maps full names of functions to warnings that will be + printed out if the function is used. (e.g. tf.nn.convolution()) + * `unrestricted_function_warnings`: maps names of functions to warnings that + will be printed out when the function is used (e.g. foo.convolution()). For an example, see `TFAPIChangeSpec`. """ @@ -53,7 +62,7 @@ class _FileEditTuple( Fields: comment: A description of the edit and why it was made. line: The line number in the file where the edit occurs (1-indexed). - start: The line number in the file where the edit occurs (0-indexed). + start: The column number in the file where the edit occurs (0-indexed). old: text string to remove (this must match what was in file). new: text string to add in place of `old`. """ @@ -195,6 +204,29 @@ class _ASTCallVisitor(ast.NodeVisitor): except KeyError: pass + def _print_warning_for_function_unrestricted(self, node): + """Print a warning when specific functions are called. + + The function _print_warning_for_function matches the full name of the called + function, e.g., tf.foo.bar(). This function matches the function name that + is called, as long as the function is an attribute. For example, + `tf.foo.bar()` and `foo.bar()` are matched, but not `bar()`. + + Args: + node: ast.Call object + """ + function_warnings = getattr( + self._api_change_spec, "unrestricted_function_warnings", {}) + if isinstance(node.func, ast.Attribute): + function_name = node.func.attr + try: + warning_message = function_warnings[function_name] + self._file_edit.add(warning_message, + node.lineno, node.col_offset, "", "", + error="%s requires manual check." % function_name) + except KeyError: + pass + def _get_attribute_full_path(self, node): """Traverse an attribute to generate a full name e.g. tf.foo.bar. @@ -209,11 +241,11 @@ class _ASTCallVisitor(ast.NodeVisitor): items = [] while not isinstance(curr, ast.Name): if not isinstance(curr, ast.Attribute): - return None + return None, None items.append(curr.attr) curr = curr.value items.append(curr.id) - return ".".join(reversed(items)) + return ".".join(reversed(items)), items[0] def _find_true_position(self, node): """Return correct line number and column offset for a given node. @@ -221,13 +253,12 @@ class _ASTCallVisitor(ast.NodeVisitor): This is necessary mainly because ListComp's location reporting reports the next token after the list comprehension list opening. + Returns: + lineno, offset for the given node + Args: node: Node for which we wish to know the lineno and col_offset """ - import re - find_open = re.compile("^\s*(\\[).*$") - find_string_chars = re.compile("['\"]") - if isinstance(node, ast.ListComp): # Strangely, ast.ListComp returns the col_offset of the first token # after the '[' token which appears to be a bug. Workaround by @@ -241,7 +272,7 @@ class _ASTCallVisitor(ast.NodeVisitor): reversed_preceding_text = text[:col][::-1] # First find if a [ can be found with only whitespace between it and # col. - m = find_open.match(reversed_preceding_text) + m = FIND_OPEN.match(reversed_preceding_text) if m: new_col_offset = col - m.start(1) - 1 return line, new_col_offset @@ -260,7 +291,7 @@ class _ASTCallVisitor(ast.NodeVisitor): comment_start = prev_line.find("#") if comment_start == -1: col = len(prev_line) - 1 - elif find_string_chars.search(prev_line[comment_start:]) is None: + elif FIND_STRING_CHARS.search(prev_line[comment_start:]) is None: col = comment_start else: return None, None @@ -276,9 +307,10 @@ class _ASTCallVisitor(ast.NodeVisitor): Args: node: Current Node """ + self._print_warning_for_function_unrestricted(node) # Find a simple attribute name path e.g. "tf.foo.bar" - full_name = self._get_attribute_full_path(node.func) + full_name, name = self._get_attribute_full_path(node.func) # Make sure the func is marked as being part of a call node.func.is_function_for_call = True @@ -286,6 +318,9 @@ class _ASTCallVisitor(ast.NodeVisitor): if full_name: # Call special handlers function_handles = self._api_change_spec.function_handle + glob_name = "*.{}".format(name) + if glob_name in function_handles: + function_handles[glob_name](self._file_edit, node) if full_name in function_handles: function_handles[full_name](self._file_edit, node) @@ -358,10 +393,11 @@ class _ASTCallVisitor(ast.NodeVisitor): Args: node: Node that is of type ast.Attribute """ - full_name = self._get_attribute_full_path(node) + full_name, _ = self._get_attribute_full_path(node) if full_name: - self._rename_functions(node, full_name) + # Make sure the warning comes first, otherwise the name may have changed self._print_warning_for_function(node, full_name) + self._rename_functions(node, full_name) if full_name in self._api_change_spec.change_to_function: if not hasattr(node, "is_function_for_call"): new_text = full_name + "()" diff --git a/tensorflow/tools/compatibility/ast_edits_test.py b/tensorflow/tools/compatibility/ast_edits_test.py new file mode 100644 index 0000000000..99f20a026f --- /dev/null +++ b/tensorflow/tools/compatibility/ast_edits_test.py @@ -0,0 +1,420 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for ast_edits which is used in tf upgraders. + +All of the tests assume that we want to change from an API containing + + def f(a, b, kw1, kw2): ... + def g(a, b, kw1, c, kw1_alias): ... + def g2(a, b, kw1, c, d, kw1_alias): ... + def h(a, kw1, kw2, kw1_alias, kw2_alias): ... + +and the changes to the API consist of renaming, reordering, and/or removing +arguments. Thus, we want to be able to generate changes to produce each of the +following new APIs: + + def f(a, b, kw1, kw3): ... + def f(a, b, kw2, kw1): ... + def f(a, b, kw3, kw1): ... + def g(a, b, kw1, c): ... + def g(a, b, c, kw1): ... + def g2(a, b, kw1, c, d): ... + def g2(a, b, c, d, kw1): ... + def h(a, kw1, kw2): ... + +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +import six +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test as test_lib +from tensorflow.tools.compatibility import ast_edits + + +class NoUpdateSpec(ast_edits.APIChangeSpec): + """A specification of an API change which doesn't change anything.""" + + def __init__(self): + self.function_handle = {} + self.function_reorders = {} + self.function_keyword_renames = {} + self.symbol_renames = {} + self.function_warnings = {} + self.unrestricted_function_warnings = {} + self.change_to_function = {} + + +class RenameKeywordSpec(NoUpdateSpec): + """A specification where kw2 gets renamed to kw3. + + The new API is + + def f(a, b, kw1, kw3): ... + + """ + + def __init__(self): + NoUpdateSpec.__init__(self) + self.update_renames() + + def update_renames(self): + self.function_keyword_renames["f"] = {"kw2": "kw3"} + + +class ReorderKeywordSpec(NoUpdateSpec): + """A specification where kw2 gets moved in front of kw1. + + The new API is + + def f(a, b, kw2, kw1): ... + + """ + + def __init__(self): + NoUpdateSpec.__init__(self) + self.update_reorders() + + def update_reorders(self): + # Note that these should be in the old order. + self.function_reorders["f"] = ["a", "b", "kw1", "kw2"] + + +class ReorderAndRenameKeywordSpec(ReorderKeywordSpec, RenameKeywordSpec): + """A specification where kw2 gets moved in front of kw1 and is changed to kw3. + + The new API is + + def f(a, b, kw3, kw1): ... + + """ + + def __init__(self): + ReorderKeywordSpec.__init__(self) + RenameKeywordSpec.__init__(self) + self.update_renames() + self.update_reorders() + + +class RemoveDeprecatedAliasKeyword(NoUpdateSpec): + """A specification where kw1_alias is removed in g. + + The new API is + + def g(a, b, kw1, c): ... + def g2(a, b, kw1, c, d): ... + + """ + + def __init__(self): + NoUpdateSpec.__init__(self) + self.function_keyword_renames["g"] = {"kw1_alias": "kw1"} + self.function_keyword_renames["g2"] = {"kw1_alias": "kw1"} + + +class RemoveDeprecatedAliasAndReorderRest(RemoveDeprecatedAliasKeyword): + """A specification where kw1_alias is removed in g. + + The new API is + + def g(a, b, c, kw1): ... + def g2(a, b, c, d, kw1): ... + + """ + + def __init__(self): + RemoveDeprecatedAliasKeyword.__init__(self) + # Note that these should be in the old order. + self.function_reorders["g"] = ["a", "b", "kw1", "c"] + self.function_reorders["g2"] = ["a", "b", "kw1", "c", "d"] + + +class RemoveMultipleKeywordArguments(NoUpdateSpec): + """A specification where both keyword aliases are removed from h. + + The new API is + + def h(a, kw1, kw2): ... + + """ + + def __init__(self): + NoUpdateSpec.__init__(self) + self.function_keyword_renames["h"] = { + "kw1_alias": "kw1", + "kw2_alias": "kw2", + } + + +class TestAstEdits(test_util.TensorFlowTestCase): + + def _upgrade(self, spec, old_file_text): + in_file = six.StringIO(old_file_text) + out_file = six.StringIO() + upgrader = ast_edits.ASTCodeUpgrader(spec) + count, report, errors = ( + upgrader.process_opened_file("test.py", in_file, + "test_out.py", out_file)) + return (count, report, errors), out_file.getvalue() + + def testNoTransformIfNothingIsSupplied(self): + text = "f(a, b, kw1=c, kw2=d)\n" + _, new_text = self._upgrade(NoUpdateSpec(), text) + self.assertEqual(new_text, text) + + text = "f(a, b, c, d)\n" + _, new_text = self._upgrade(NoUpdateSpec(), text) + self.assertEqual(new_text, text) + + def testKeywordRename(self): + """Test that we get the expected result if renaming kw2 to kw3.""" + text = "f(a, b, kw1=c, kw2=d)\n" + expected = "f(a, b, kw1=c, kw3=d)\n" + _, new_text = self._upgrade(RenameKeywordSpec(), text) + self.assertEqual(new_text, expected) + + # No keywords specified, no reordering, so we should get input as output + text = "f(a, b, c, d)\n" + _, new_text = self._upgrade(RenameKeywordSpec(), text) + self.assertEqual(new_text, text) + + def testKeywordReorder(self): + """Test that we get the expected result if kw2 is now before kw1.""" + text = "f(a, b, kw1=c, kw2=d)\n" + acceptable_outputs = [ + # No change is a valid output + text, + # Just reordering the kw.. args is also ok + "f(a, b, kw2=d, kw1=c)\n", + # Also cases where all arguments are fully specified are allowed + "f(a=a, b=b, kw1=c, kw2=d)\n", + "f(a=a, b=b, kw2=d, kw1=c)\n", + ] + _, new_text = self._upgrade(ReorderKeywordSpec(), text) + self.assertIn(new_text, acceptable_outputs) + + # Keywords are reordered, so we should reorder arguments too + text = "f(a, b, c, d)\n" + acceptable_outputs = [ + "f(a, b, d, c)\n", + "f(a=a, b=b, kw1=c, kw2=d)\n", + "f(a=a, b=b, kw2=d, kw1=c)\n", + ] + _, new_text = self._upgrade(ReorderKeywordSpec(), text) + self.assertIn(new_text, acceptable_outputs) + + def testKeywordReorderAndRename(self): + """Test that we get the expected result if kw2 is renamed and moved.""" + text = "f(a, b, kw1=c, kw2=d)\n" + acceptable_outputs = [ + "f(a, b, kw3=d, kw1=c)\n", + "f(a=a, b=b, kw1=c, kw3=d)\n", + "f(a=a, b=b, kw3=d, kw1=c)\n", + ] + _, new_text = self._upgrade(ReorderAndRenameKeywordSpec(), text) + self.assertIn(new_text, acceptable_outputs) + + # Keywords are reordered, so we should reorder arguments too + text = "f(a, b, c, d)\n" + acceptable_outputs = [ + "f(a, b, d, c)\n", + "f(a=a, b=b, kw1=c, kw3=d)\n", + "f(a=a, b=b, kw3=d, kw1=c)\n", + ] + _, new_text = self._upgrade(ReorderAndRenameKeywordSpec(), text) + self.assertIn(new_text, acceptable_outputs) + + def testRemoveDeprecatedKeywordAlias(self): + """Test that we get the expected result if a keyword alias is removed.""" + text = "g(a, b, kw1=x, c=c)\n" + acceptable_outputs = [ + # Not using deprecated alias, so original is ok + text, + "g(a=a, b=b, kw1=x, c=c)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasKeyword(), text) + self.assertIn(new_text, acceptable_outputs) + + # No keyword used, should be no change + text = "g(a, b, x, c)\n" + _, new_text = self._upgrade(RemoveDeprecatedAliasKeyword(), text) + self.assertEqual(new_text, text) + + # If we used the alias, it should get renamed + text = "g(a, b, kw1_alias=x, c=c)\n" + acceptable_outputs = [ + "g(a, b, kw1=x, c=c)\n", + "g(a, b, c=c, kw1=x)\n", + "g(a=a, b=b, kw1=x, c=c)\n", + "g(a=a, b=b, c=c, kw1=x)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasKeyword(), text) + self.assertIn(new_text, acceptable_outputs) + + # It should get renamed even if it's last + text = "g(a, b, c=c, kw1_alias=x)\n" + acceptable_outputs = [ + "g(a, b, kw1=x, c=c)\n", + "g(a, b, c=c, kw1=x)\n", + "g(a=a, b=b, kw1=x, c=c)\n", + "g(a=a, b=b, c=c, kw1=x)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasKeyword(), text) + self.assertIn(new_text, acceptable_outputs) + + def testRemoveDeprecatedKeywordAndReorder(self): + """Test for when a keyword alias is removed and args are reordered.""" + text = "g(a, b, kw1=x, c=c)\n" + acceptable_outputs = [ + "g(a, b, c=c, kw1=x)\n", + "g(a=a, b=b, kw1=x, c=c)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasAndReorderRest(), text) + self.assertIn(new_text, acceptable_outputs) + + # Keywords are reordered, so we should reorder arguments too + text = "g(a, b, x, c)\n" + # Don't accept an output which doesn't reorder c and d + acceptable_outputs = [ + "g(a, b, c, x)\n", + "g(a=a, b=b, kw1=x, c=c)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasAndReorderRest(), text) + self.assertIn(new_text, acceptable_outputs) + + # If we used the alias, it should get renamed + text = "g(a, b, kw1_alias=x, c=c)\n" + acceptable_outputs = [ + "g(a, b, kw1=x, c=c)\n", + "g(a, b, c=c, kw1=x)\n", + "g(a=a, b=b, kw1=x, c=c)\n", + "g(a=a, b=b, c=c, kw1=x)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasKeyword(), text) + self.assertIn(new_text, acceptable_outputs) + + # It should get renamed and reordered even if it's last + text = "g(a, b, c=c, kw1_alias=x)\n" + acceptable_outputs = [ + "g(a, b, kw1=x, c=c)\n", + "g(a, b, c=c, kw1=x)\n", + "g(a=a, b=b, kw1=x, c=c)\n", + "g(a=a, b=b, c=c, kw1=x)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasKeyword(), text) + self.assertIn(new_text, acceptable_outputs) + + def testRemoveDeprecatedKeywordAndReorder2(self): + """Same as testRemoveDeprecatedKeywordAndReorder but on g2 (more args).""" + text = "g2(a, b, kw1=x, c=c, d=d)\n" + acceptable_outputs = [ + "g2(a, b, c=c, d=d, kw1=x)\n", + "g2(a=a, b=b, kw1=x, c=c, d=d)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasAndReorderRest(), text) + self.assertIn(new_text, acceptable_outputs) + + # Keywords are reordered, so we should reorder arguments too + text = "g2(a, b, x, c, d)\n" + # Don't accept an output which doesn't reorder c and d + acceptable_outputs = [ + "g2(a, b, c, d, x)\n", + "g2(a=a, b=b, kw1=x, c=c, d=d)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasAndReorderRest(), text) + self.assertIn(new_text, acceptable_outputs) + + # If we used the alias, it should get renamed + text = "g2(a, b, kw1_alias=x, c=c, d=d)\n" + acceptable_outputs = [ + "g2(a, b, kw1=x, c=c, d=d)\n", + "g2(a, b, c=c, d=d, kw1=x)\n", + "g2(a=a, b=b, kw1=x, c=c, d=d)\n", + "g2(a=a, b=b, c=c, d=d, kw1=x)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasKeyword(), text) + self.assertIn(new_text, acceptable_outputs) + + # It should get renamed and reordered even if it's not in order + text = "g2(a, b, d=d, c=c, kw1_alias=x)\n" + acceptable_outputs = [ + "g2(a, b, kw1=x, c=c, d=d)\n", + "g2(a, b, c=c, d=d, kw1=x)\n", + "g2(a, b, d=d, c=c, kw1=x)\n", + "g2(a=a, b=b, kw1=x, c=c, d=d)\n", + "g2(a=a, b=b, c=c, d=d, kw1=x)\n", + "g2(a=a, b=b, d=d, c=c, kw1=x)\n", + ] + _, new_text = self._upgrade(RemoveDeprecatedAliasKeyword(), text) + self.assertIn(new_text, acceptable_outputs) + + def testRemoveMultipleKeywords(self): + """Remove multiple keywords at once.""" + # Not using deprecated keywords -> no rename + text = "h(a, kw1=x, kw2=y)\n" + _, new_text = self._upgrade(RemoveMultipleKeywordArguments(), text) + self.assertEqual(new_text, text) + + # Using positional arguments (in proper order) -> no change + text = "h(a, x, y)\n" + _, new_text = self._upgrade(RemoveMultipleKeywordArguments(), text) + self.assertEqual(new_text, text) + + # Use only the old names, in order + text = "h(a, kw1_alias=x, kw2_alias=y)\n" + acceptable_outputs = [ + "h(a, x, y)\n", + "h(a, kw1=x, kw2=y)\n", + "h(a=a, kw1=x, kw2=y)\n", + "h(a, kw2=y, kw1=x)\n", + "h(a=a, kw2=y, kw1=x)\n", + ] + _, new_text = self._upgrade(RemoveMultipleKeywordArguments(), text) + self.assertIn(new_text, acceptable_outputs) + + # Use only the old names, in reverse order, should give one of same outputs + text = "h(a, kw2_alias=y, kw1_alias=x)\n" + _, new_text = self._upgrade(RemoveMultipleKeywordArguments(), text) + self.assertIn(new_text, acceptable_outputs) + + # Mix old and new names + text = "h(a, kw1=x, kw2_alias=y)\n" + _, new_text = self._upgrade(RemoveMultipleKeywordArguments(), text) + self.assertIn(new_text, acceptable_outputs) + + def testUnrestrictedFunctionWarnings(self): + class FooWarningSpec(NoUpdateSpec): + """Usages of function attribute foo() prints out a warning.""" + + def __init__(self): + NoUpdateSpec.__init__(self) + self.unrestricted_function_warnings = {"foo": "not good"} + texts = ["object.foo()", "get_object().foo()", + "get_object().foo()", "object.foo().bar()"] + for text in texts: + (_, report, _), _ = self._upgrade(FooWarningSpec(), text) + self.assertIn("not good", report) + + # Note that foo() won't result in a warning, because in this case foo is + # not an attribute, but a name. + false_alarms = ["foo", "foo()", "foo.bar()", "obj.run_foo()", "obj.foo"] + for text in false_alarms: + (_, report, _), _ = self._upgrade(FooWarningSpec(), text) + self.assertNotIn("not good", report) + + +if __name__ == "__main__": + test_lib.main() diff --git a/tensorflow/tools/compatibility/renames_v2.py b/tensorflow/tools/compatibility/renames_v2.py index 5ea2fbcc4c..78839e36ba 100644 --- a/tensorflow/tools/compatibility/renames_v2.py +++ b/tensorflow/tools/compatibility/renames_v2.py @@ -28,6 +28,10 @@ renames = { 'tf.AUTO_REUSE': 'tf.compat.v1.AUTO_REUSE', 'tf.COMPILER_VERSION': 'tf.version.COMPILER_VERSION', 'tf.CXX11_ABI_FLAG': 'tf.sysconfig.CXX11_ABI_FLAG', + 'tf.ConditionalAccumulator': 'tf.compat.v1.ConditionalAccumulator', + 'tf.ConditionalAccumulatorBase': 'tf.compat.v1.ConditionalAccumulatorBase', + 'tf.DeviceSpec': 'tf.compat.v1.DeviceSpec', + 'tf.Dimension': 'tf.compat.v1.Dimension', 'tf.FixedLenFeature': 'tf.io.FixedLenFeature', 'tf.FixedLenSequenceFeature': 'tf.io.FixedLenSequenceFeature', 'tf.FixedLengthRecordReader': 'tf.compat.v1.FixedLengthRecordReader', @@ -35,6 +39,7 @@ renames = { 'tf.GRAPH_DEF_VERSION': 'tf.version.GRAPH_DEF_VERSION', 'tf.GRAPH_DEF_VERSION_MIN_CONSUMER': 'tf.version.GRAPH_DEF_VERSION_MIN_CONSUMER', 'tf.GRAPH_DEF_VERSION_MIN_PRODUCER': 'tf.version.GRAPH_DEF_VERSION_MIN_PRODUCER', + 'tf.GraphKeys': 'tf.compat.v1.GraphKeys', 'tf.IdentityReader': 'tf.compat.v1.IdentityReader', 'tf.InteractiveSession': 'tf.compat.v1.InteractiveSession', 'tf.LMDBReader': 'tf.compat.v1.LMDBReader', @@ -53,12 +58,10 @@ renames = { 'tf.SparseConditionalAccumulator': 'tf.sparse.SparseConditionalAccumulator', 'tf.SparseFeature': 'tf.io.SparseFeature', 'tf.TFRecordReader': 'tf.compat.v1.TFRecordReader', - 'tf.TensorShape': 'tf.compat.v1.TensorShape', + 'tf.TensorInfo': 'tf.compat.v1.TensorInfo', 'tf.TextLineReader': 'tf.compat.v1.TextLineReader', 'tf.VERSION': 'tf.version.VERSION', 'tf.VarLenFeature': 'tf.io.VarLenFeature', - 'tf.Variable': 'tf.compat.v1.Variable', - 'tf.VariableAggregation': 'tf.compat.v1.VariableAggregation', 'tf.VariableScope': 'tf.compat.v1.VariableScope', 'tf.WholeFileReader': 'tf.compat.v1.WholeFileReader', 'tf.accumulate_n': 'tf.math.accumulate_n', @@ -67,59 +70,67 @@ renames = { 'tf.add_to_collections': 'tf.compat.v1.add_to_collections', 'tf.all_variables': 'tf.compat.v1.all_variables', 'tf.angle': 'tf.math.angle', - 'tf.argmax': 'tf.compat.v1.argmax', - 'tf.argmin': 'tf.compat.v1.argmin', - 'tf.assert_greater_equal': 'tf.debugging.assert_greater_equal', - 'tf.assert_integer': 'tf.debugging.assert_integer', - 'tf.assert_less_equal': 'tf.debugging.assert_less_equal', - 'tf.assert_near': 'tf.debugging.assert_near', - 'tf.assert_negative': 'tf.debugging.assert_negative', - 'tf.assert_non_negative': 'tf.debugging.assert_non_negative', - 'tf.assert_non_positive': 'tf.debugging.assert_non_positive', - 'tf.assert_none_equal': 'tf.debugging.assert_none_equal', - 'tf.assert_positive': 'tf.debugging.assert_positive', + 'tf.app.run': 'tf.compat.v1.app.run', + 'tf.arg_max': 'tf.compat.v1.arg_max', + 'tf.arg_min': 'tf.compat.v1.arg_min', + 'tf.assert_greater_equal': 'tf.compat.v1.assert_greater_equal', + 'tf.assert_integer': 'tf.compat.v1.assert_integer', + 'tf.assert_less_equal': 'tf.compat.v1.assert_less_equal', + 'tf.assert_near': 'tf.compat.v1.assert_near', + 'tf.assert_negative': 'tf.compat.v1.assert_negative', + 'tf.assert_non_negative': 'tf.compat.v1.assert_non_negative', + 'tf.assert_non_positive': 'tf.compat.v1.assert_non_positive', + 'tf.assert_none_equal': 'tf.compat.v1.assert_none_equal', + 'tf.assert_positive': 'tf.compat.v1.assert_positive', 'tf.assert_proper_iterable': 'tf.debugging.assert_proper_iterable', - 'tf.assert_rank_at_least': 'tf.debugging.assert_rank_at_least', - 'tf.assert_rank_in': 'tf.debugging.assert_rank_in', + 'tf.assert_rank_at_least': 'tf.compat.v1.assert_rank_at_least', + 'tf.assert_rank_in': 'tf.compat.v1.assert_rank_in', 'tf.assert_same_float_dtype': 'tf.debugging.assert_same_float_dtype', - 'tf.assert_scalar': 'tf.debugging.assert_scalar', - 'tf.assert_type': 'tf.debugging.assert_type', + 'tf.assert_scalar': 'tf.compat.v1.assert_scalar', + 'tf.assert_type': 'tf.compat.v1.assert_type', 'tf.assert_variables_initialized': 'tf.compat.v1.assert_variables_initialized', 'tf.assign': 'tf.compat.v1.assign', 'tf.assign_add': 'tf.compat.v1.assign_add', 'tf.assign_sub': 'tf.compat.v1.assign_sub', 'tf.betainc': 'tf.math.betainc', - 'tf.bincount': 'tf.math.bincount', 'tf.ceil': 'tf.math.ceil', 'tf.check_numerics': 'tf.debugging.check_numerics', 'tf.cholesky': 'tf.linalg.cholesky', 'tf.cholesky_solve': 'tf.linalg.cholesky_solve', + 'tf.clip_by_average_norm': 'tf.compat.v1.clip_by_average_norm', 'tf.colocate_with': 'tf.compat.v1.colocate_with', - 'tf.confusion_matrix': 'tf.math.confusion_matrix', 'tf.conj': 'tf.math.conj', 'tf.container': 'tf.compat.v1.container', - 'tf.convert_to_tensor': 'tf.compat.v1.convert_to_tensor', 'tf.convert_to_tensor_or_indexed_slices': 'tf.compat.v1.convert_to_tensor_or_indexed_slices', 'tf.convert_to_tensor_or_sparse_tensor': 'tf.compat.v1.convert_to_tensor_or_sparse_tensor', + 'tf.count_nonzero': 'tf.compat.v1.count_nonzero', 'tf.count_up_to': 'tf.compat.v1.count_up_to', + 'tf.create_partitioned_variables': 'tf.compat.v1.create_partitioned_variables', 'tf.cross': 'tf.linalg.cross', 'tf.cumprod': 'tf.math.cumprod', + 'tf.data.make_initializable_iterator': 'tf.compat.v1.data.make_initializable_iterator', + 'tf.data.make_one_shot_iterator': 'tf.compat.v1.data.make_one_shot_iterator', + 'tf.debugging.is_finite': 'tf.math.is_finite', + 'tf.debugging.is_inf': 'tf.math.is_inf', + 'tf.debugging.is_nan': 'tf.math.is_nan', + 'tf.debugging.is_non_decreasing': 'tf.math.is_non_decreasing', + 'tf.debugging.is_strictly_increasing': 'tf.math.is_strictly_increasing', 'tf.decode_base64': 'tf.io.decode_base64', 'tf.decode_compressed': 'tf.io.decode_compressed', - 'tf.decode_csv': 'tf.io.decode_csv', 'tf.decode_json_example': 'tf.io.decode_json_example', 'tf.decode_raw': 'tf.io.decode_raw', 'tf.delete_session_tensor': 'tf.compat.v1.delete_session_tensor', 'tf.depth_to_space': 'tf.nn.depth_to_space', 'tf.dequantize': 'tf.quantization.dequantize', 'tf.deserialize_many_sparse': 'tf.io.deserialize_many_sparse', - 'tf.device': 'tf.compat.v1.device', 'tf.diag': 'tf.linalg.tensor_diag', 'tf.diag_part': 'tf.linalg.tensor_diag_part', 'tf.digamma': 'tf.math.digamma', 'tf.dimension_at_index': 'tf.compat.v1.dimension_at_index', 'tf.dimension_value': 'tf.compat.v1.dimension_value', + 'tf.disable_eager_execution': 'tf.compat.v1.disable_eager_execution', 'tf.disable_resource_variables': 'tf.compat.v1.disable_resource_variables', + 'tf.disable_v2_behavior': 'tf.compat.v1.disable_v2_behavior', 'tf.disable_v2_tensorshape': 'tf.compat.v1.disable_v2_tensorshape', 'tf.distributions.Bernoulli': 'tf.compat.v1.distributions.Bernoulli', 'tf.distributions.Beta': 'tf.compat.v1.distributions.Beta', @@ -139,30 +150,41 @@ renames = { 'tf.distributions.StudentT': 'tf.compat.v1.distributions.StudentT', 'tf.distributions.Uniform': 'tf.compat.v1.distributions.Uniform', 'tf.distributions.kl_divergence': 'tf.compat.v1.distributions.kl_divergence', + 'tf.div': 'tf.compat.v1.div', + 'tf.enable_eager_execution': 'tf.compat.v1.enable_eager_execution', 'tf.enable_resource_variables': 'tf.compat.v1.enable_resource_variables', + 'tf.enable_v2_behavior': 'tf.compat.v1.enable_v2_behavior', 'tf.enable_v2_tensorshape': 'tf.compat.v1.enable_v2_tensorshape', 'tf.encode_base64': 'tf.io.encode_base64', 'tf.erf': 'tf.math.erf', 'tf.erfc': 'tf.math.erfc', 'tf.expm1': 'tf.math.expm1', - 'tf.extract_image_patches': 'tf.image.extract_image_patches', 'tf.fake_quant_with_min_max_args': 'tf.quantization.fake_quant_with_min_max_args', 'tf.fake_quant_with_min_max_args_gradient': 'tf.quantization.fake_quant_with_min_max_args_gradient', 'tf.fake_quant_with_min_max_vars': 'tf.quantization.fake_quant_with_min_max_vars', 'tf.fake_quant_with_min_max_vars_gradient': 'tf.quantization.fake_quant_with_min_max_vars_gradient', 'tf.fake_quant_with_min_max_vars_per_channel': 'tf.quantization.fake_quant_with_min_max_vars_per_channel', 'tf.fake_quant_with_min_max_vars_per_channel_gradient': 'tf.quantization.fake_quant_with_min_max_vars_per_channel_gradient', + 'tf.feature_column.input_layer': 'tf.compat.v1.feature_column.input_layer', + 'tf.feature_column.linear_model': 'tf.compat.v1.feature_column.linear_model', 'tf.fft': 'tf.signal.fft', 'tf.fft2d': 'tf.signal.fft2d', 'tf.fft3d': 'tf.signal.fft3d', + 'tf.fixed_size_partitioner': 'tf.compat.v1.fixed_size_partitioner', 'tf.floordiv': 'tf.math.floordiv', + 'tf.get_collection': 'tf.compat.v1.get_collection', + 'tf.get_collection_ref': 'tf.compat.v1.get_collection_ref', + 'tf.get_default_graph': 'tf.compat.v1.get_default_graph', 'tf.get_default_session': 'tf.compat.v1.get_default_session', 'tf.get_local_variable': 'tf.compat.v1.get_local_variable', - 'tf.get_seed': 'tf.random.get_seed', + 'tf.get_seed': 'tf.compat.v1.get_seed', 'tf.get_session_handle': 'tf.compat.v1.get_session_handle', 'tf.get_session_tensor': 'tf.compat.v1.get_session_tensor', 'tf.get_variable': 'tf.compat.v1.get_variable', 'tf.get_variable_scope': 'tf.compat.v1.get_variable_scope', + 'tf.gfile.FastGFile': 'tf.compat.v1.gfile.FastGFile', + 'tf.gfile.GFile': 'tf.compat.v1.gfile.GFile', + 'tf.gfile.Open': 'tf.compat.v1.gfile.Open', 'tf.global_norm': 'tf.linalg.global_norm', 'tf.global_variables': 'tf.compat.v1.global_variables', 'tf.global_variables_initializer': 'tf.compat.v1.global_variables_initializer', @@ -178,6 +200,12 @@ renames = { 'tf.igamma': 'tf.math.igamma', 'tf.igammac': 'tf.math.igammac', 'tf.imag': 'tf.math.imag', + 'tf.image.resize_area': 'tf.compat.v1.image.resize_area', + 'tf.image.resize_bicubic': 'tf.compat.v1.image.resize_bicubic', + 'tf.image.resize_bilinear': 'tf.compat.v1.image.resize_bilinear', + 'tf.image.resize_images': 'tf.compat.v1.image.resize_images', + 'tf.image.resize_nearest_neighbor': 'tf.compat.v1.image.resize_nearest_neighbor', + 'tf.image.transpose_image': 'tf.compat.v1.image.transpose_image', 'tf.initialize_all_tables': 'tf.compat.v1.initialize_all_tables', 'tf.initialize_all_variables': 'tf.compat.v1.initialize_all_variables', 'tf.initialize_local_variables': 'tf.compat.v1.initialize_local_variables', @@ -187,12 +215,13 @@ renames = { 'tf.initializers.tables_initializer': 'tf.compat.v1.initializers.tables_initializer', 'tf.initializers.variables': 'tf.compat.v1.initializers.variables', 'tf.invert_permutation': 'tf.math.invert_permutation', - 'tf.is_finite': 'tf.debugging.is_finite', - 'tf.is_inf': 'tf.debugging.is_inf', - 'tf.is_nan': 'tf.debugging.is_nan', - 'tf.is_non_decreasing': 'tf.debugging.is_non_decreasing', + 'tf.io.tf_record_iterator': 'tf.compat.v1.io.tf_record_iterator', + 'tf.is_finite': 'tf.math.is_finite', + 'tf.is_inf': 'tf.math.is_inf', + 'tf.is_nan': 'tf.math.is_nan', + 'tf.is_non_decreasing': 'tf.math.is_non_decreasing', 'tf.is_numeric_tensor': 'tf.debugging.is_numeric_tensor', - 'tf.is_strictly_increasing': 'tf.debugging.is_strictly_increasing', + 'tf.is_strictly_increasing': 'tf.math.is_strictly_increasing', 'tf.is_variable_initialized': 'tf.compat.v1.is_variable_initialized', 'tf.keras.backend.get_session': 'tf.compat.v1.keras.backend.get_session', 'tf.layers.AveragePooling1D': 'tf.compat.v1.layers.AveragePooling1D', @@ -235,13 +264,46 @@ renames = { 'tf.layers.separable_conv2d': 'tf.compat.v1.layers.separable_conv2d', 'tf.lbeta': 'tf.math.lbeta', 'tf.lgamma': 'tf.math.lgamma', + 'tf.lin_space': 'tf.linspace', 'tf.local_variables': 'tf.compat.v1.local_variables', 'tf.local_variables_initializer': 'tf.compat.v1.local_variables_initializer', + 'tf.log': 'tf.math.log', + 'tf.log1p': 'tf.math.log1p', 'tf.log_sigmoid': 'tf.math.log_sigmoid', + 'tf.logging.DEBUG': 'tf.compat.v1.logging.DEBUG', + 'tf.logging.ERROR': 'tf.compat.v1.logging.ERROR', + 'tf.logging.FATAL': 'tf.compat.v1.logging.FATAL', + 'tf.logging.INFO': 'tf.compat.v1.logging.INFO', + 'tf.logging.TaskLevelStatusMessage': 'tf.compat.v1.logging.TaskLevelStatusMessage', + 'tf.logging.WARN': 'tf.compat.v1.logging.WARN', + 'tf.logging.debug': 'tf.compat.v1.logging.debug', + 'tf.logging.error': 'tf.compat.v1.logging.error', + 'tf.logging.fatal': 'tf.compat.v1.logging.fatal', + 'tf.logging.flush': 'tf.compat.v1.logging.flush', + 'tf.logging.get_verbosity': 'tf.compat.v1.logging.get_verbosity', + 'tf.logging.info': 'tf.compat.v1.logging.info', + 'tf.logging.log': 'tf.compat.v1.logging.log', + 'tf.logging.log_every_n': 'tf.compat.v1.logging.log_every_n', + 'tf.logging.log_first_n': 'tf.compat.v1.logging.log_first_n', + 'tf.logging.log_if': 'tf.compat.v1.logging.log_if', + 'tf.logging.set_verbosity': 'tf.compat.v1.logging.set_verbosity', + 'tf.logging.vlog': 'tf.compat.v1.logging.vlog', + 'tf.logging.warn': 'tf.compat.v1.logging.warn', + 'tf.logging.warning': 'tf.compat.v1.logging.warning', 'tf.logical_xor': 'tf.math.logical_xor', + 'tf.losses.absolute_difference': 'tf.compat.v1.losses.absolute_difference', + 'tf.losses.compute_weighted_loss': 'tf.compat.v1.losses.compute_weighted_loss', + 'tf.losses.cosine_distance': 'tf.compat.v1.losses.cosine_distance', + 'tf.losses.hinge_loss': 'tf.compat.v1.losses.hinge_loss', + 'tf.losses.huber_loss': 'tf.compat.v1.losses.huber_loss', + 'tf.losses.log_loss': 'tf.compat.v1.losses.log_loss', + 'tf.losses.mean_pairwise_squared_error': 'tf.compat.v1.losses.mean_pairwise_squared_error', + 'tf.losses.mean_squared_error': 'tf.compat.v1.losses.mean_squared_error', + 'tf.losses.sigmoid_cross_entropy': 'tf.compat.v1.losses.sigmoid_cross_entropy', + 'tf.losses.softmax_cross_entropy': 'tf.compat.v1.losses.softmax_cross_entropy', + 'tf.losses.sparse_softmax_cross_entropy': 'tf.compat.v1.losses.sparse_softmax_cross_entropy', 'tf.make_template': 'tf.compat.v1.make_template', 'tf.make_tensor_proto': 'tf.compat.v1.make_tensor_proto', - 'tf.manip.batch_to_space_nd': 'tf.batch_to_space_nd', 'tf.manip.gather_nd': 'tf.gather_nd', 'tf.manip.reshape': 'tf.reshape', 'tf.manip.reverse': 'tf.reverse', @@ -250,8 +312,6 @@ renames = { 'tf.manip.space_to_batch_nd': 'tf.space_to_batch_nd', 'tf.manip.tile': 'tf.tile', 'tf.matching_files': 'tf.io.matching_files', - 'tf.math.argmax': 'tf.compat.v1.math.argmax', - 'tf.math.argmin': 'tf.compat.v1.math.argmin', 'tf.matrix_band_part': 'tf.linalg.band_part', 'tf.matrix_determinant': 'tf.linalg.det', 'tf.matrix_diag': 'tf.linalg.diag', @@ -262,49 +322,105 @@ renames = { 'tf.matrix_solve_ls': 'tf.linalg.lstsq', 'tf.matrix_transpose': 'tf.linalg.transpose', 'tf.matrix_triangular_solve': 'tf.linalg.triangular_solve', + 'tf.metrics.accuracy': 'tf.compat.v1.metrics.accuracy', + 'tf.metrics.auc': 'tf.compat.v1.metrics.auc', + 'tf.metrics.average_precision_at_k': 'tf.compat.v1.metrics.average_precision_at_k', + 'tf.metrics.false_negatives': 'tf.compat.v1.metrics.false_negatives', + 'tf.metrics.false_negatives_at_thresholds': 'tf.compat.v1.metrics.false_negatives_at_thresholds', + 'tf.metrics.false_positives': 'tf.compat.v1.metrics.false_positives', + 'tf.metrics.false_positives_at_thresholds': 'tf.compat.v1.metrics.false_positives_at_thresholds', + 'tf.metrics.mean': 'tf.compat.v1.metrics.mean', + 'tf.metrics.mean_absolute_error': 'tf.compat.v1.metrics.mean_absolute_error', + 'tf.metrics.mean_cosine_distance': 'tf.compat.v1.metrics.mean_cosine_distance', + 'tf.metrics.mean_iou': 'tf.compat.v1.metrics.mean_iou', + 'tf.metrics.mean_per_class_accuracy': 'tf.compat.v1.metrics.mean_per_class_accuracy', + 'tf.metrics.mean_relative_error': 'tf.compat.v1.metrics.mean_relative_error', + 'tf.metrics.mean_squared_error': 'tf.compat.v1.metrics.mean_squared_error', + 'tf.metrics.mean_tensor': 'tf.compat.v1.metrics.mean_tensor', + 'tf.metrics.percentage_below': 'tf.compat.v1.metrics.percentage_below', + 'tf.metrics.precision': 'tf.compat.v1.metrics.precision', + 'tf.metrics.precision_at_k': 'tf.compat.v1.metrics.precision_at_k', + 'tf.metrics.precision_at_thresholds': 'tf.compat.v1.metrics.precision_at_thresholds', + 'tf.metrics.precision_at_top_k': 'tf.compat.v1.metrics.precision_at_top_k', + 'tf.metrics.recall': 'tf.compat.v1.metrics.recall', + 'tf.metrics.recall_at_k': 'tf.compat.v1.metrics.recall_at_k', + 'tf.metrics.recall_at_thresholds': 'tf.compat.v1.metrics.recall_at_thresholds', + 'tf.metrics.recall_at_top_k': 'tf.compat.v1.metrics.recall_at_top_k', + 'tf.metrics.root_mean_squared_error': 'tf.compat.v1.metrics.root_mean_squared_error', + 'tf.metrics.sensitivity_at_specificity': 'tf.compat.v1.metrics.sensitivity_at_specificity', + 'tf.metrics.sparse_average_precision_at_k': 'tf.compat.v1.metrics.sparse_average_precision_at_k', + 'tf.metrics.sparse_precision_at_k': 'tf.compat.v1.metrics.sparse_precision_at_k', + 'tf.metrics.specificity_at_sensitivity': 'tf.compat.v1.metrics.specificity_at_sensitivity', + 'tf.metrics.true_negatives': 'tf.compat.v1.metrics.true_negatives', + 'tf.metrics.true_negatives_at_thresholds': 'tf.compat.v1.metrics.true_negatives_at_thresholds', + 'tf.metrics.true_positives': 'tf.compat.v1.metrics.true_positives', + 'tf.metrics.true_positives_at_thresholds': 'tf.compat.v1.metrics.true_positives_at_thresholds', + 'tf.min_max_variable_partitioner': 'tf.compat.v1.min_max_variable_partitioner', 'tf.model_variables': 'tf.compat.v1.model_variables', 'tf.moving_average_variables': 'tf.compat.v1.moving_average_variables', - 'tf.nn.ctc_beam_search_decoder': 'tf.compat.v1.nn.ctc_beam_search_decoder', + 'tf.nn.bidirectional_dynamic_rnn': 'tf.compat.v1.nn.bidirectional_dynamic_rnn', + 'tf.nn.conv3d_backprop_filter_v2': 'tf.nn.conv3d_backprop_filter', 'tf.nn.ctc_beam_search_decoder_v2': 'tf.nn.ctc_beam_search_decoder', + 'tf.nn.ctc_loss_v2': 'tf.nn.ctc_loss', + 'tf.nn.depthwise_conv2d_native': 'tf.compat.v1.nn.depthwise_conv2d_native', + 'tf.nn.depthwise_conv2d_native_backprop_filter': 'tf.nn.depthwise_conv2d_backprop_filter', + 'tf.nn.depthwise_conv2d_native_backprop_input': 'tf.nn.depthwise_conv2d_backprop_input', 'tf.nn.dynamic_rnn': 'tf.compat.v1.nn.dynamic_rnn', 'tf.nn.log_uniform_candidate_sampler': 'tf.random.log_uniform_candidate_sampler', + 'tf.nn.quantized_avg_pool': 'tf.compat.v1.nn.quantized_avg_pool', + 'tf.nn.quantized_conv2d': 'tf.compat.v1.nn.quantized_conv2d', + 'tf.nn.quantized_max_pool': 'tf.compat.v1.nn.quantized_max_pool', + 'tf.nn.quantized_relu_x': 'tf.compat.v1.nn.quantized_relu_x', 'tf.nn.raw_rnn': 'tf.compat.v1.nn.raw_rnn', 'tf.nn.rnn_cell.BasicLSTMCell': 'tf.compat.v1.nn.rnn_cell.BasicLSTMCell', 'tf.nn.rnn_cell.BasicRNNCell': 'tf.compat.v1.nn.rnn_cell.BasicRNNCell', 'tf.nn.rnn_cell.GRUCell': 'tf.compat.v1.nn.rnn_cell.GRUCell', 'tf.nn.rnn_cell.LSTMCell': 'tf.compat.v1.nn.rnn_cell.LSTMCell', - 'tf.nn.softmax_cross_entropy_with_logits': 'tf.compat.v1.nn.softmax_cross_entropy_with_logits', - 'tf.nn.softmax_cross_entropy_with_logits_v2': 'tf.nn.softmax_cross_entropy_with_logits', + 'tf.nn.rnn_cell.MultiRNNCell': 'tf.compat.v1.nn.rnn_cell.MultiRNNCell', + 'tf.nn.static_bidirectional_rnn': 'tf.compat.v1.nn.static_bidirectional_rnn', 'tf.nn.static_rnn': 'tf.compat.v1.nn.static_rnn', 'tf.nn.uniform_candidate_sampler': 'tf.random.uniform_candidate_sampler', + 'tf.nn.xw_plus_b': 'tf.compat.v1.nn.xw_plus_b', 'tf.op_scope': 'tf.compat.v1.op_scope', 'tf.orthogonal_initializer': 'tf.keras.initializers.Orthogonal', - 'tf.parse_example': 'tf.io.parse_example', - 'tf.parse_single_example': 'tf.io.parse_single_example', + 'tf.parse_example': 'tf.compat.v1.parse_example', + 'tf.parse_single_example': 'tf.compat.v1.parse_single_example', 'tf.parse_single_sequence_example': 'tf.io.parse_single_sequence_example', 'tf.parse_tensor': 'tf.io.parse_tensor', 'tf.placeholder': 'tf.compat.v1.placeholder', 'tf.placeholder_with_default': 'tf.compat.v1.placeholder_with_default', 'tf.polygamma': 'tf.math.polygamma', + 'tf.profiler.AdviceProto': 'tf.compat.v1.profiler.AdviceProto', + 'tf.profiler.GraphNodeProto': 'tf.compat.v1.profiler.GraphNodeProto', + 'tf.profiler.MultiGraphNodeProto': 'tf.compat.v1.profiler.MultiGraphNodeProto', + 'tf.profiler.OpLogProto': 'tf.compat.v1.profiler.OpLogProto', + 'tf.profiler.ProfileOptionBuilder': 'tf.compat.v1.profiler.ProfileOptionBuilder', + 'tf.profiler.Profiler': 'tf.compat.v1.profiler.Profiler', + 'tf.profiler.advise': 'tf.compat.v1.profiler.advise', + 'tf.profiler.profile': 'tf.compat.v1.profiler.profile', + 'tf.profiler.write_op_log': 'tf.compat.v1.profiler.write_op_log', + 'tf.py_func': 'tf.compat.v1.py_func', 'tf.python_io.TFRecordCompressionType': 'tf.io.TFRecordCompressionType', 'tf.python_io.TFRecordOptions': 'tf.io.TFRecordOptions', 'tf.python_io.TFRecordWriter': 'tf.io.TFRecordWriter', - 'tf.python_io.tf_record_iterator': 'tf.io.tf_record_iterator', + 'tf.python_io.tf_record_iterator': 'tf.compat.v1.python_io.tf_record_iterator', 'tf.qr': 'tf.linalg.qr', 'tf.quantize': 'tf.quantization.quantize', 'tf.quantized_concat': 'tf.quantization.quantized_concat', + 'tf.random.get_seed': 'tf.compat.v1.random.get_seed', + 'tf.random.set_random_seed': 'tf.compat.v1.random.set_random_seed', 'tf.random_crop': 'tf.image.random_crop', 'tf.random_gamma': 'tf.random.gamma', 'tf.random_normal': 'tf.random.normal', - 'tf.random_poisson': 'tf.random.poisson', + 'tf.random_poisson': 'tf.compat.v1.random_poisson', 'tf.random_shuffle': 'tf.random.shuffle', 'tf.random_uniform': 'tf.random.uniform', 'tf.read_file': 'tf.io.read_file', 'tf.real': 'tf.math.real', 'tf.reciprocal': 'tf.math.reciprocal', - 'tf.reduce_join': 'tf.strings.reduce_join', 'tf.regex_replace': 'tf.strings.regex_replace', 'tf.report_uninitialized_variables': 'tf.compat.v1.report_uninitialized_variables', + 'tf.reset_default_graph': 'tf.compat.v1.reset_default_graph', 'tf.resource_loader.get_data_files_path': 'tf.compat.v1.resource_loader.get_data_files_path', 'tf.resource_loader.get_path_to_datafile': 'tf.compat.v1.resource_loader.get_path_to_datafile', 'tf.resource_loader.get_root_dir_with_all_resources': 'tf.compat.v1.resource_loader.get_root_dir_with_all_resources', @@ -314,13 +430,15 @@ renames = { 'tf.rint': 'tf.math.rint', 'tf.rsqrt': 'tf.math.rsqrt', 'tf.saved_model.Builder': 'tf.compat.v1.saved_model.Builder', + 'tf.saved_model.LEGACY_INIT_OP_KEY': 'tf.compat.v1.saved_model.LEGACY_INIT_OP_KEY', + 'tf.saved_model.MAIN_OP_KEY': 'tf.compat.v1.saved_model.MAIN_OP_KEY', 'tf.saved_model.TRAINING': 'tf.saved_model.TRANING', 'tf.saved_model.build_tensor_info': 'tf.compat.v1.saved_model.build_tensor_info', 'tf.saved_model.builder.SavedModelBuilder': 'tf.compat.v1.saved_model.builder.SavedModelBuilder', 'tf.saved_model.constants.ASSETS_DIRECTORY': 'tf.saved_model.ASSETS_DIRECTORY', 'tf.saved_model.constants.ASSETS_KEY': 'tf.saved_model.ASSETS_KEY', - 'tf.saved_model.constants.LEGACY_INIT_OP_KEY': 'tf.saved_model.LEGACY_INIT_OP_KEY', - 'tf.saved_model.constants.MAIN_OP_KEY': 'tf.saved_model.MAIN_OP_KEY', + 'tf.saved_model.constants.LEGACY_INIT_OP_KEY': 'tf.compat.v1.saved_model.constants.LEGACY_INIT_OP_KEY', + 'tf.saved_model.constants.MAIN_OP_KEY': 'tf.compat.v1.saved_model.constants.MAIN_OP_KEY', 'tf.saved_model.constants.SAVED_MODEL_FILENAME_PB': 'tf.saved_model.SAVED_MODEL_FILENAME_PB', 'tf.saved_model.constants.SAVED_MODEL_FILENAME_PBTXT': 'tf.saved_model.SAVED_MODEL_FILENAME_PBTXT', 'tf.saved_model.constants.SAVED_MODEL_SCHEMA_VERSION': 'tf.saved_model.SAVED_MODEL_SCHEMA_VERSION', @@ -330,10 +448,11 @@ renames = { 'tf.saved_model.get_tensor_from_tensor_info': 'tf.compat.v1.saved_model.get_tensor_from_tensor_info', 'tf.saved_model.load': 'tf.compat.v1.saved_model.load', 'tf.saved_model.loader.load': 'tf.compat.v1.saved_model.loader.load', - 'tf.saved_model.loader.maybe_saved_model_directory': 'tf.saved_model.maybe_saved_model_directory', + 'tf.saved_model.loader.maybe_saved_model_directory': 'tf.compat.v1.saved_model.loader.maybe_saved_model_directory', 'tf.saved_model.main_op.main_op': 'tf.compat.v1.saved_model.main_op.main_op', 'tf.saved_model.main_op.main_op_with_restore': 'tf.compat.v1.saved_model.main_op.main_op_with_restore', 'tf.saved_model.main_op_with_restore': 'tf.compat.v1.saved_model.main_op_with_restore', + 'tf.saved_model.maybe_saved_model_directory': 'tf.compat.v1.saved_model.maybe_saved_model_directory', 'tf.saved_model.signature_constants.CLASSIFY_INPUTS': 'tf.saved_model.CLASSIFY_INPUTS', 'tf.saved_model.signature_constants.CLASSIFY_METHOD_NAME': 'tf.saved_model.CLASSIFY_METHOD_NAME', 'tf.saved_model.signature_constants.CLASSIFY_OUTPUT_CLASSES': 'tf.saved_model.CLASSIFY_OUTPUT_CLASSES', @@ -370,51 +489,80 @@ renames = { 'tf.segment_sum': 'tf.math.segment_sum', 'tf.self_adjoint_eig': 'tf.linalg.eigh', 'tf.self_adjoint_eigvals': 'tf.linalg.eigvalsh', - 'tf.serialize_many_sparse': 'tf.io.serialize_many_sparse', - 'tf.serialize_sparse': 'tf.io.serialize_sparse', + 'tf.serialize_many_sparse': 'tf.compat.v1.serialize_many_sparse', + 'tf.serialize_sparse': 'tf.compat.v1.serialize_sparse', 'tf.serialize_tensor': 'tf.io.serialize_tensor', + 'tf.set_random_seed': 'tf.compat.v1.set_random_seed', 'tf.setdiff1d': 'tf.compat.v1.setdiff1d', + 'tf.sets.set_difference': 'tf.sets.difference', + 'tf.sets.set_intersection': 'tf.sets.intersection', + 'tf.sets.set_size': 'tf.sets.size', + 'tf.sets.set_union': 'tf.sets.union', 'tf.space_to_batch': 'tf.nn.space_to_batch', 'tf.space_to_depth': 'tf.nn.space_to_depth', + 'tf.sparse.matmul': 'tf.sparse.sparse_dense_matmul', + 'tf.sparse.merge': 'tf.compat.v1.sparse.merge', 'tf.sparse.placeholder': 'tf.compat.v1.sparse.placeholder', - 'tf.sparse_add': 'tf.sparse.add', + 'tf.sparse.reduce_max_sparse': 'tf.compat.v1.sparse.reduce_max_sparse', + 'tf.sparse.reduce_sum_sparse': 'tf.compat.v1.sparse.reduce_sum_sparse', 'tf.sparse_fill_empty_rows': 'tf.sparse.fill_empty_rows', 'tf.sparse_mask': 'tf.sparse.mask', - 'tf.sparse_matmul': 'tf.compat.v1.sparse_matmul', 'tf.sparse_maximum': 'tf.sparse.maximum', - 'tf.sparse_merge': 'tf.sparse.merge', + 'tf.sparse_merge': 'tf.compat.v1.sparse_merge', 'tf.sparse_minimum': 'tf.sparse.minimum', 'tf.sparse_placeholder': 'tf.compat.v1.sparse_placeholder', + 'tf.sparse_reduce_max': 'tf.compat.v1.sparse_reduce_max', + 'tf.sparse_reduce_max_sparse': 'tf.compat.v1.sparse_reduce_max_sparse', + 'tf.sparse_reduce_sum': 'tf.compat.v1.sparse_reduce_sum', + 'tf.sparse_reduce_sum_sparse': 'tf.compat.v1.sparse_reduce_sum_sparse', 'tf.sparse_reorder': 'tf.sparse.reorder', 'tf.sparse_reset_shape': 'tf.sparse.reset_shape', 'tf.sparse_reshape': 'tf.sparse.reshape', 'tf.sparse_retain': 'tf.sparse.retain', - 'tf.sparse_segment_mean': 'tf.sparse.segment_mean', - 'tf.sparse_segment_sqrt_n': 'tf.sparse.segment_sqrt_n', - 'tf.sparse_segment_sum': 'tf.sparse.segment_sum', + 'tf.sparse_segment_mean': 'tf.compat.v1.sparse_segment_mean', + 'tf.sparse_segment_sqrt_n': 'tf.compat.v1.sparse_segment_sqrt_n', + 'tf.sparse_segment_sum': 'tf.compat.v1.sparse_segment_sum', 'tf.sparse_slice': 'tf.sparse.slice', 'tf.sparse_softmax': 'tf.sparse.softmax', - 'tf.sparse_tensor_dense_matmul': 'tf.sparse.matmul', + 'tf.sparse_tensor_dense_matmul': 'tf.sparse.sparse_dense_matmul', 'tf.sparse_tensor_to_dense': 'tf.sparse.to_dense', + 'tf.sparse_to_dense': 'tf.compat.v1.sparse_to_dense', 'tf.sparse_to_indicator': 'tf.sparse.to_indicator', 'tf.sparse_transpose': 'tf.sparse.transpose', + 'tf.spectral.dct': 'tf.signal.dct', 'tf.spectral.fft': 'tf.signal.fft', 'tf.spectral.fft2d': 'tf.signal.fft2d', 'tf.spectral.fft3d': 'tf.signal.fft3d', + 'tf.spectral.idct': 'tf.signal.idct', 'tf.spectral.ifft': 'tf.signal.ifft', 'tf.spectral.ifft2d': 'tf.signal.ifft2d', 'tf.spectral.ifft3d': 'tf.signal.ifft3d', + 'tf.spectral.irfft': 'tf.signal.irfft', + 'tf.spectral.irfft2d': 'tf.signal.irfft2d', + 'tf.spectral.irfft3d': 'tf.signal.irfft3d', + 'tf.spectral.rfft': 'tf.signal.rfft', + 'tf.spectral.rfft2d': 'tf.signal.rfft2d', + 'tf.spectral.rfft3d': 'tf.signal.rfft3d', 'tf.squared_difference': 'tf.math.squared_difference', 'tf.string_join': 'tf.strings.join', 'tf.string_strip': 'tf.strings.strip', - 'tf.string_to_hash_bucket': 'tf.strings.to_hash_bucket', 'tf.string_to_hash_bucket_fast': 'tf.strings.to_hash_bucket_fast', 'tf.string_to_hash_bucket_strong': 'tf.strings.to_hash_bucket_strong', - 'tf.string_to_number': 'tf.strings.to_number', + 'tf.summary.audio': 'tf.compat.v1.summary.audio', + 'tf.summary.get_summary_description': 'tf.compat.v1.summary.get_summary_description', + 'tf.summary.histogram': 'tf.compat.v1.summary.histogram', + 'tf.summary.image': 'tf.compat.v1.summary.image', + 'tf.summary.merge': 'tf.compat.v1.summary.merge', + 'tf.summary.merge_all': 'tf.compat.v1.summary.merge_all', + 'tf.summary.scalar': 'tf.compat.v1.summary.scalar', + 'tf.summary.tensor_summary': 'tf.compat.v1.summary.tensor_summary', + 'tf.summary.text': 'tf.compat.v1.summary.text', 'tf.svd': 'tf.linalg.svd', 'tf.tables_initializer': 'tf.compat.v1.tables_initializer', + 'tf.test.compute_gradient': 'tf.compat.v1.test.compute_gradient', 'tf.test.compute_gradient_error': 'tf.compat.v1.test.compute_gradient_error', 'tf.test.get_temp_dir': 'tf.compat.v1.test.get_temp_dir', + 'tf.test.mock': 'tf.compat.v1.test.mock', 'tf.test.test_src_dir_path': 'tf.compat.v1.test.test_src_dir_path', 'tf.to_bfloat16': 'tf.compat.v1.to_bfloat16', 'tf.to_complex128': 'tf.compat.v1.to_complex128', @@ -424,22 +572,47 @@ renames = { 'tf.to_int32': 'tf.compat.v1.to_int32', 'tf.to_int64': 'tf.compat.v1.to_int64', 'tf.trace': 'tf.linalg.trace', + 'tf.train.AdadeltaOptimizer': 'tf.compat.v1.train.AdadeltaOptimizer', + 'tf.train.AdagradDAOptimizer': 'tf.compat.v1.train.AdagradDAOptimizer', + 'tf.train.AdagradOptimizer': 'tf.compat.v1.train.AdagradOptimizer', + 'tf.train.AdamOptimizer': 'tf.compat.v1.train.AdamOptimizer', + 'tf.train.CheckpointSaverListener': 'tf.compat.v1.train.CheckpointSaverListener', + 'tf.train.ChiefSessionCreator': 'tf.compat.v1.train.ChiefSessionCreator', + 'tf.train.FtrlOptimizer': 'tf.compat.v1.train.FtrlOptimizer', + 'tf.train.GradientDescentOptimizer': 'tf.compat.v1.train.GradientDescentOptimizer', + 'tf.train.LooperThread': 'tf.compat.v1.train.LooperThread', + 'tf.train.MomentumOptimizer': 'tf.compat.v1.train.MomentumOptimizer', + 'tf.train.MonitoredSession': 'tf.compat.v1.train.MonitoredSession', 'tf.train.MonitoredTrainingSession': 'tf.compat.v1.train.MonitoredTrainingSession', + 'tf.train.NanLossDuringTrainingError': 'tf.compat.v1.train.NanLossDuringTrainingError', + 'tf.train.NewCheckpointReader': 'tf.compat.v1.train.NewCheckpointReader', + 'tf.train.Optimizer': 'tf.compat.v1.train.Optimizer', + 'tf.train.ProfilerHook': 'tf.compat.v1.train.ProfilerHook', + 'tf.train.ProximalAdagradOptimizer': 'tf.compat.v1.train.ProximalAdagradOptimizer', 'tf.train.QueueRunner': 'tf.compat.v1.train.QueueRunner', + 'tf.train.RMSPropOptimizer': 'tf.compat.v1.train.RMSPropOptimizer', 'tf.train.Saver': 'tf.compat.v1.train.Saver', 'tf.train.SaverDef': 'tf.compat.v1.train.SaverDef', + 'tf.train.Scaffold': 'tf.compat.v1.train.Scaffold', + 'tf.train.SecondOrStepTimer': 'tf.compat.v1.train.SecondOrStepTimer', + 'tf.train.SessionCreator': 'tf.compat.v1.train.SessionCreator', + 'tf.train.SessionManager': 'tf.compat.v1.train.SessionManager', + 'tf.train.SessionRunArgs': 'tf.compat.v1.train.SessionRunArgs', + 'tf.train.SessionRunContext': 'tf.compat.v1.train.SessionRunContext', + 'tf.train.SessionRunValues': 'tf.compat.v1.train.SessionRunValues', + 'tf.train.SingularMonitoredSession': 'tf.compat.v1.train.SingularMonitoredSession', + 'tf.train.Supervisor': 'tf.compat.v1.train.Supervisor', 'tf.train.SyncReplicasOptimizer': 'tf.compat.v1.train.SyncReplicasOptimizer', + 'tf.train.VocabInfo': 'tf.estimator.VocabInfo', + 'tf.train.WorkerSessionCreator': 'tf.compat.v1.train.WorkerSessionCreator', 'tf.train.add_queue_runner': 'tf.compat.v1.train.add_queue_runner', 'tf.train.assert_global_step': 'tf.compat.v1.train.assert_global_step', 'tf.train.basic_train_loop': 'tf.compat.v1.train.basic_train_loop', 'tf.train.batch': 'tf.compat.v1.train.batch', 'tf.train.batch_join': 'tf.compat.v1.train.batch_join', 'tf.train.checkpoint_exists': 'tf.compat.v1.train.checkpoint_exists', - 'tf.train.cosine_decay': 'tf.compat.v1.train.cosine_decay', - 'tf.train.cosine_decay_restarts': 'tf.compat.v1.train.cosine_decay_restarts', 'tf.train.create_global_step': 'tf.compat.v1.train.create_global_step', 'tf.train.do_quantize_training_on_graphdef': 'tf.compat.v1.train.do_quantize_training_on_graphdef', - 'tf.train.exponential_decay': 'tf.compat.v1.train.exponential_decay', 'tf.train.export_meta_graph': 'tf.compat.v1.train.export_meta_graph', 'tf.train.generate_checkpoint_state_proto': 'tf.compat.v1.train.generate_checkpoint_state_proto', 'tf.train.get_checkpoint_mtimes': 'tf.compat.v1.train.get_checkpoint_mtimes', @@ -447,32 +620,31 @@ renames = { 'tf.train.get_or_create_global_step': 'tf.compat.v1.train.get_or_create_global_step', 'tf.train.global_step': 'tf.compat.v1.train.global_step', 'tf.train.import_meta_graph': 'tf.compat.v1.train.import_meta_graph', + 'tf.train.init_from_checkpoint': 'tf.compat.v1.train.init_from_checkpoint', 'tf.train.input_producer': 'tf.compat.v1.train.input_producer', - 'tf.train.inverse_time_decay': 'tf.compat.v1.train.inverse_time_decay', 'tf.train.limit_epochs': 'tf.compat.v1.train.limit_epochs', - 'tf.train.linear_cosine_decay': 'tf.compat.v1.train.linear_cosine_decay', 'tf.train.match_filenames_once': 'tf.io.match_filenames_once', 'tf.train.maybe_batch': 'tf.compat.v1.train.maybe_batch', 'tf.train.maybe_batch_join': 'tf.compat.v1.train.maybe_batch_join', 'tf.train.maybe_shuffle_batch': 'tf.compat.v1.train.maybe_shuffle_batch', 'tf.train.maybe_shuffle_batch_join': 'tf.compat.v1.train.maybe_shuffle_batch_join', - 'tf.train.natural_exp_decay': 'tf.compat.v1.train.natural_exp_decay', - 'tf.train.noisy_linear_cosine_decay': 'tf.compat.v1.train.noisy_linear_cosine_decay', 'tf.train.piecewise_constant': 'tf.compat.v1.train.piecewise_constant', - 'tf.train.polynomial_decay': 'tf.compat.v1.train.polynomial_decay', 'tf.train.queue_runner.QueueRunner': 'tf.compat.v1.train.queue_runner.QueueRunner', 'tf.train.queue_runner.add_queue_runner': 'tf.compat.v1.train.queue_runner.add_queue_runner', 'tf.train.queue_runner.start_queue_runners': 'tf.compat.v1.train.queue_runner.start_queue_runners', 'tf.train.range_input_producer': 'tf.compat.v1.train.range_input_producer', 'tf.train.remove_checkpoint': 'tf.compat.v1.train.remove_checkpoint', + 'tf.train.replica_device_setter': 'tf.compat.v1.train.replica_device_setter', 'tf.train.shuffle_batch': 'tf.compat.v1.train.shuffle_batch', 'tf.train.shuffle_batch_join': 'tf.compat.v1.train.shuffle_batch_join', 'tf.train.slice_input_producer': 'tf.compat.v1.train.slice_input_producer', 'tf.train.start_queue_runners': 'tf.compat.v1.train.start_queue_runners', 'tf.train.string_input_producer': 'tf.compat.v1.train.string_input_producer', 'tf.train.update_checkpoint_state': 'tf.compat.v1.train.update_checkpoint_state', + 'tf.train.warm_start': 'tf.compat.v1.train.warm_start', 'tf.train.write_graph': 'tf.io.write_graph', 'tf.trainable_variables': 'tf.compat.v1.trainable_variables', + 'tf.truncated_normal': 'tf.random.truncated_normal', 'tf.uniform_unit_scaling_initializer': 'tf.initializers.uniform_unit_scaling', 'tf.unsorted_segment_max': 'tf.math.unsorted_segment_max', 'tf.unsorted_segment_mean': 'tf.math.unsorted_segment_mean', @@ -480,12 +652,13 @@ renames = { 'tf.unsorted_segment_prod': 'tf.math.unsorted_segment_prod', 'tf.unsorted_segment_sqrt_n': 'tf.math.unsorted_segment_sqrt_n', 'tf.unsorted_segment_sum': 'tf.math.unsorted_segment_sum', - 'tf.variable_creator_scope': 'tf.compat.v1.variable_creator_scope', + 'tf.variable_axis_size_partitioner': 'tf.compat.v1.variable_axis_size_partitioner', 'tf.variable_op_scope': 'tf.compat.v1.variable_op_scope', 'tf.variable_scope': 'tf.compat.v1.variable_scope', 'tf.variables_initializer': 'tf.compat.v1.variables_initializer', 'tf.variance_scaling_initializer': 'tf.keras.initializers.VarianceScaling', - 'tf.verify_tensor_all_finite': 'tf.debugging.assert_all_finite', + 'tf.verify_tensor_all_finite': 'tf.compat.v1.verify_tensor_all_finite', + 'tf.wrap_function': 'tf.compat.v1.wrap_function', 'tf.write_file': 'tf.io.write_file', 'tf.zeta': 'tf.math.zeta' } diff --git a/tensorflow/tools/compatibility/testdata/test_file_v1_12.py b/tensorflow/tools/compatibility/testdata/test_file_v1_12.py new file mode 100644 index 0000000000..fd688781b0 --- /dev/null +++ b/tensorflow/tools/compatibility/testdata/test_file_v1_12.py @@ -0,0 +1,71 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for tf upgrader.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +import tensorflow as tf +from tensorflow.python.framework import test_util +from tensorflow.python.platform import test as test_lib + + +class TestUpgrade(test_util.TensorFlowTestCase): + """Test various APIs that have been changed in 2.0.""" + + def setUp(self): + tf.enable_eager_execution() + + def testRenames(self): + with self.cached_session(): + self.assertAllClose(1.04719755, tf.acos(0.5)) + self.assertAllClose(0.5, tf.rsqrt(4.0)) + + def testSerializeSparseTensor(self): + sp_input = tf.SparseTensor( + indices=tf.constant([[1]], dtype=tf.int64), + values=tf.constant([2], dtype=tf.int64), + dense_shape=[2]) + + with self.cached_session(): + serialized_sp = tf.serialize_sparse(sp_input, 'serialize_name', tf.string) + self.assertEqual((3,), serialized_sp.shape) + self.assertTrue(serialized_sp[0].numpy()) # check non-empty + + def testSerializeManySparse(self): + sp_input = tf.SparseTensor( + indices=tf.constant([[0, 1]], dtype=tf.int64), + values=tf.constant([2], dtype=tf.int64), + dense_shape=[1, 2]) + + with self.cached_session(): + serialized_sp = tf.serialize_many_sparse( + sp_input, 'serialize_name', tf.string) + self.assertEqual((1, 3), serialized_sp.shape) + + def testArgMaxMin(self): + self.assertAllClose( + [1], + tf.argmax([[1, 3, 2]], name='abc', dimension=1)) + self.assertAllClose( + [0, 0, 0], + tf.argmax([[1, 3, 2]], dimension=0)) + self.assertAllClose( + [0], + tf.argmin([[1, 3, 2]], name='abc', dimension=1)) + + +if __name__ == "__main__": + test_lib.main() diff --git a/tensorflow/tools/compatibility/tf_upgrade_v2.py b/tensorflow/tools/compatibility/tf_upgrade_v2.py index 0df8b0f376..655e680d5b 100644 --- a/tensorflow/tools/compatibility/tf_upgrade_v2.py +++ b/tensorflow/tools/compatibility/tf_upgrade_v2.py @@ -18,8 +18,6 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import argparse - from tensorflow.tools.compatibility import ast_edits from tensorflow.tools.compatibility import renames_v2 @@ -31,23 +29,452 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): # Maps from a function name to a dictionary that describes how to # map from an old argument keyword to the new argument keyword. self.function_keyword_renames = { + "tf.argmin": { + "dimension": "axis", + }, + "tf.argmax": { + "dimension": "axis", + }, + "tf.image.crop_and_resize": { + "box_ind": "box_indices", + }, + "tf.image.extract_image_patches": { + "ksizes": "sizes", + }, + "tf.extract_image_patches": { + "ksizes": "sizes", + }, + "tf.expand_dims": { + "dim": "axis", + }, + "tf.batch_to_space": { + "block_size": "block_shape", + }, + "tf.constant": { + "verify_shape": "verify_shape_is_now_always_true", + }, "tf.convert_to_tensor": { "preferred_dtype": "dtype_hint" }, + "tf.nn.softmax_cross_entropy_with_logits_v2": { + "dim": "axis" + }, + "tf.linalg.l2_normalize": { + "dim": "axis", + }, + "tf.math.count_nonzero": { + "input_tensor": "input", + "keep_dims": "keepdims", + "reduction_indices": "axis", + }, + "tf.nn.erosion2d": { + "kernel": "filters", + "rates": "dilations", + }, + "tf.math.l2_normalize": { + "dim": "axis", + }, + "tf.math.log_softmax": { + "dim": "axis", + }, + "tf.math.softmax": { + "dim": "axis" + }, + "tf.nn.l2_normalize": { + "dim": "axis", + }, + "tf.nn.log_softmax": { + "dim": "axis", + }, + "tf.nn.moments": { + "keep_dims": "keepdims", + }, + "tf.nn.pool": { + "dilation_rate": "dilations" + }, + "tf.nn.separable_conv2d": { + "rate": "dilations" + }, + "tf.nn.softmax": { + "dim": "axis" + }, + "tf.nn.sufficient_statistics": { + "keep_dims": "keepdims" + }, + "tf.debugging.assert_all_finite": { + "t": "x", + "msg": "message", + }, + "tf.sparse.add": { + "thresh": "threshold", + }, + "tf.sparse_add": { + "thresh": "threshold", + }, + "tf.sparse.concat": { + "concat_dim": "axis", + }, + "tf.sparse_concat": { + "concat_dim": "axis", + }, + "tf.sparse.split": { + "split_dim": "axis", + }, + "tf.max_pool_with_argmax": { + "Targmax": "output_dtype", + }, + "tf.multinomial": { + "output_dtype": "dtype", + }, + "tf.random.multinomial": { + "output_dtype": "dtype", + }, + "tf.nn.batch_norm_with_global_normalization": { + "t": "input", + "m": "mean", + "v": "variance", + }, + "tf.nn.dilation2d": { + "filter": "filters", + "rates": "dilations", + }, + "tf.nn.conv3d": { + "filter": "filters" + }, + "tf.zeros_like": { + "tensor": "input", + }, + "tf.ones_like": { + "tensor": "input", + }, + "tf.nn.conv3d_transpose": { + "value": "input", + "filter": "filters", + }, + "tf.nn.convolution": { + "filter": "filters", + "dilation_rate": "dilations", + }, + "tf.gfile.Exists": { + "filename": "path", + }, + "tf.gfile.Remove": { + "filename": "path", + }, + "tf.gfile.Stat": { + "filename": "path", + }, + "tf.gfile.Glob": { + "filename": "pattern", + }, + "tf.gfile.MkDir": { + "dirname": "path", + }, + "tf.gfile.MakeDirs": { + "dirname": "path", + }, + "tf.gfile.DeleteRecursively": { + "dirname": "path", + }, + "tf.gfile.IsDirectory": { + "dirname": "path", + }, + "tf.gfile.ListDirectory": { + "dirname": "path", + }, + "tf.gfile.Copy": { + "oldpath": "src", + "newpath": "dst", + }, + "tf.gfile.Rename": { + "oldname": "src", + "newname": "dst", + }, + "tf.gfile.Walk": { + "in_order": "topdown", + }, + "tf.random.stateless_multinomial": { + "output_dtype": "dtype", + }, + "tf.string_to_number": { + "string_tensor": "input", + }, + "tf.strings.to_number": { + "string_tensor": "input", + }, + "tf.string_to_hash_bucket": { + "string_tensor": "input", + }, + "tf.strings.to_hash_bucket": { + "string_tensor": "input", + }, + "tf.reduce_all": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.math.reduce_all": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.reduce_any": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.math.reduce_any": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.reduce_min": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.math.reduce_min": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.reduce_max": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.math.reduce_max": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.reduce_sum": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.math.reduce_sum": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.reduce_mean": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.math.reduce_mean": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.reduce_prod": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.math.reduce_prod": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.reduce_logsumexp": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.math.reduce_logsumexp": { + "reduction_indices": "axis", + "keep_dims": "keepdims", + }, + "tf.reduce_join": { + "keep_dims": "keepdims", + "reduction_indices": "axis" + }, + "tf.strings.reduce_join": { + "keep_dims": "keepdims", + "reduction_indices": "axis" + }, + "tf.squeeze": { + "squeeze_dims": "axis", + }, } - # Mapping from function to the new name of the function - self.symbol_renames = renames_v2.renames # pylint: disable=line-too-long # Add additional renames not in renames_v2.py here. - self.symbol_renames.update({ - }) + # IMPORTANT: For the renames in here, if you also need to add to + # function_reorders or function_keyword_renames, use the OLD function name. + # These renames happen after the arguments have been processed. + self.manual_symbol_renames = { + "tf.batch_to_space_nd": + "tf.batch_to_space", + "tf.extract_image_patches": + "tf.image.extract_image_patches", + "tf.gfile.Copy": + "tf.io.gfile.copy", + "tf.gfile.DeleteRecursively": + "tf.io.gfile.rmtree", + "tf.gfile.Exists": + "tf.io.gfile.exists", + "tf.gfile.Glob": + "tf.io.gfile.glob", + "tf.gfile.IsDirectory": + "tf.io.gfile.isdir", + "tf.gfile.ListDirectory": + "tf.io.gfile.listdir", + "tf.gfile.MakeDirs": + "tf.io.gfile.makedirs", + "tf.gfile.MkDir": + "tf.io.gfile.mkdir", + "tf.gfile.Remove": + "tf.io.gfile.remove", + "tf.gfile.Rename": + "tf.io.gfile.rename", + "tf.gfile.Stat": + "tf.io.gfile.stat", + "tf.gfile.Walk": + "tf.io.gfile.walk", + "tf.contrib.data.AUTOTUNE": + "tf.data.experimental.AUTOTUNE", + "tf.contrib.data.Counter": + "tf.data.experimental.Counter", + "tf.contrib.data.CheckpointInputPipelineHook": + "tf.data.experimental.CheckpointInputPipelineHook", + "tf.contrib.data.CsvDataset": + "tf.data.experimental.CsvDataset", + "tf.contrib.data.Optional": + "tf.data.experimental.Optional", + "tf.contrib.data.RandomDataset": + "tf.data.experimental.RandomDataset", + "tf.contrib.data.Reducer": + "tf.data.experimental.Reducer", + "tf.contrib.data.SqlDataset": + "tf.data.experimental.SqlDataset", + "tf.contrib.data.StatsAggregator": + "tf.data.experimental.StatsAggregator", + "tf.contrib.data.TFRecordWriter": + "tf.data.experimental.TFRecordWriter", + "tf.contrib.data.assert_element_shape": + "tf.data.experimental.assert_element_shape", + "tf.contrib.data.batch_and_drop_remainder": + "tf.compat.v1.contrib.data.batch_and_drop_remainder", + "tf.contrib.data.bucket_by_sequence_length": + "tf.data.experimental.bucket_by_sequence_length", + "tf.contrib.data.choose_from_datasets": + "tf.data.experimental.choose_from_datasets", + "tf.contrib.data.copy_to_device": + "tf.data.experimental.copy_to_device", + "tf.contrib.data.dense_to_sparse_batch": + "tf.data.experimental.dense_to_sparse_batch", + "tf.contrib.data.enumerate_dataset": + "tf.data.experimental.enumerate_dataset", + "tf.contrib.data.get_next_as_optional": + "tf.data.experimental.get_next_as_optional", + "tf.contrib.data.get_single_element": + "tf.data.experimental.get_single_element", + "tf.contrib.data.group_by_reducer": + "tf.data.experimental.group_by_reducer", + "tf.contrib.data.group_by_window": + "tf.data.experimental.group_by_window", + "tf.contrib.data.ignore_errors": + "tf.data.experimental.ignore_errors", + "tf.contrib.data.latency_stats": + "tf.data.experimental.latency_stats", + "tf.contrib.data.make_batched_features_dataset": + "tf.data.experimental.make_batched_features_dataset", + "tf.contrib.data.make_csv_dataset": + "tf.data.experimental.make_csv_dataset", + "tf.contrib.data.make_saveable_from_iterator": + "tf.data.experimental.make_saveable_from_iterator", + "tf.contrib.data.map_and_batch": + "tf.data.experimental.map_and_batch", + "tf.contrib.data.padded_batch_and_drop_remainder": + "tf.compat.v1.contrib.data.padded_batch_and_drop_remainder", + "tf.contrib.data.parallel_interleave": + "tf.data.experimental.parallel_interleave", + "tf.contrib.data.parse_example_dataset": + "tf.data.experimental.parse_example_dataset", + "tf.contrib.data.prefetch_to_device": + "tf.data.experimental.prefetch_to_device", + "tf.contrib.data.read_batch_features": + "tf.compat.v1.contrib.data.read_batch_features", + "tf.contrib.data.reduce_dataset": + "tf.compat.v1.contrib.data.reduce_dataset", + "tf.contrib.data.rejection_resample": + "tf.data.experimental.rejection_resample", + "tf.contrib.data.sample_from_datasets": + "tf.data.experimental.sample_from_datasets", + "tf.contrib.data.scan": + "tf.data.experimental.scan", + "tf.contrib.data.set_stats_aggregator": + "tf.data.experimental.set_stats_aggregator", + "tf.contrib.data.shuffle_and_repeat": + "tf.data.experimental.shuffle_and_repeat", + "tf.contrib.data.sliding_window_batch": + "tf.compat.v1.contrib.data.sliding_window_batch", + "tf.contrib.data.sloppy_interleave": + "tf.compat.v1.contrib.data.sloppy_interleave", + "tf.contrib.data.unbatch": + "tf.data.experimental.unbatch", + "tf.contrib.data.unique": + "tf.data.experimental.unique", + "tf.contrib.framework.sort": + "tf.sort", + "tf.contrib.framework.argsort": + "tf.argsort", + "tf.manip.batch_to_space_nd": + "tf.batch_to_space", + "tf.quantize_v2": + "tf.quantization.quantize", + "tf.sparse_add": + "tf.sparse.add", + "tf.sparse_concat": + "tf.sparse.concat", + "tf.sparse_split": + "tf.sparse.split", + "tf.sparse_matmul": + "tf.linalg.matmul", + "tf.random.stateless_multinomial": + "tf.random.stateless_categorical", + "tf.string_to_hash_bucket": + "tf.strings.to_hash_bucket", + "tf.string_to_number": + "tf.strings.to_number", + "tf.multinomial": + "tf.random.categorical", + "tf.random.multinomial": + "tf.random.categorical", + "tf.reduce_join": + "tf.strings.reduce_join", + "tf.load_file_system_library": + "tf.load_library", + "tf.pywrap_tensorflow": + "tf.compat.v1.pywrap_tensorflow", + "tf.bincount": + "tf.math.bincount", + "tf.confusion_matrix": + "tf.math.confusion_matrix", + "tf.train.confusion_matrix": + "tf.math.confusion_matrix", + "tf.decode_csv": + "tf.io.decode_csv", + "tf.data.Iterator": + "tf.compat.v1.data.Iterator", + "tf.parse_example": + "tf.io.parse_example", + "tf.parse_single_example": + "tf.io.parse_single_example", + "tf.nn.fused_batch_norm": + "tf.compat.v1.nn.fused_batch_norm", + "tf.nn.softmax_cross_entropy_with_logits_v2": + "tf.nn.softmax_cross_entropy_with_logits", + "tf.losses.Reduction.MEAN": + "tf.compat.v1.losses.Reduction.MEAN", + "tf.losses.Reduction.SUM_BY_NONZERO_WEIGHTS": + "tf.compat.v1.losses.Reduction.SUM_BY_NONZERO_WEIGHTS", + "tf.losses.Reduction.SUM_OVER_NONZERO_WEIGHTS": + "tf.compat.v1.losses.Reduction.SUM_OVER_NONZERO_WEIGHTS", + "tf.lite.constants.FLOAT": + "tf.float32", + "tf.lite.constants.INT32": + "tf.int32", + "tf.lite.constants.INT64": + "tf.int64", + "tf.lite.constants.STRING": + "tf.string", + "tf.lite.constants.QUANTIZED_UINT8": + "tf.uint8", + } # pylint: enable=line-too-long - # For custom behavior and if auto-generate rename in renames_v2.py - # is incorrect, add the op name here to exclude it from renames_v2.py. - excluded_renames = [ - ] + # Mapping from function to the new name of the function + self.symbol_renames = renames_v2.renames + self.symbol_renames.update(self.manual_symbol_renames) # Variables that should be changed to functions. self.change_to_function = {} @@ -55,22 +482,194 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): # Functions that were reordered should be changed to the new keyword args # for safety, if positional arguments are used. If you have reversed the # positional arguments yourself, this could do the wrong thing. + # IMPORTANT: order here should correspond to OLD argument order. + # We just prepend "arg_name=" to all arguments in function calls. self.function_reorders = { - "tf.convert_to_tensor": ["value", "dtype", "preferred_dtype", "name"], - "tf.argmin": ["input", "axis", "output_type", "name"], - "tf.argmax": ["input", "axis", "output_type", "name"], + "tf.io.serialize_sparse": ["sp_input", "name", "out_type"], + "tf.io.serialize_many_sparse": ["sp_input", "name", "out_type"], + "tf.argmax": ["input", "axis", "name", "axis", "output_type"], + "tf.argmin": ["input", "axis", "name", "axis", "output_type"], + "tf.batch_to_space": ["input", "crops", "block_size", "name"], "tf.boolean_mask": ["tensor", "mask", "name", "axis"], + "tf.convert_to_tensor": ["value", "dtype", "name", "preferred_dtype"], + "tf.nn.moments": ["x", "axes", "shift", "keepdims", "name"], + "tf.nn.convolution": [ + "input", "filter", "padding", "strides", "dilation_rate", "name", + "data_format" + ], + "tf.nn.crelu": ["features", "name", "axis"], + "tf.nn.pool": [ + "input", "window_shape", "pooling_type", "padding", "dilation_rate", + "strides", "name", "data_format" + ], + "tf.nn.depthwise_conv2d": [ + "input", "filter", "strides", "padding", "rate", "name", + "data_format" + ], + "tf.multinomial": [ + "logits", "num_samples", "seed", "name", "output_dtype" + ], + "tf.random.multinomial": [ + "logits", "num_samples", "seed", "name", "output_dtype" + ], + "tf.pad": ["tensor", "paddings", "mode", "name", "constant_values"], + "tf.quantize_v2": [ + "input", "min_range", "max_range", "T", "mode", "name", "round_mode" + ], + "tf.feature_column.categorical_column_with_vocabulary_file": [ + "key", "vocabulary_file", "vocabulary_size", "num_oov_buckets", + "default_value", "dtype" + ], + "tf.shape": ["input", "name", "out_type"], + "tf.size": ["input", "name", "out_type"], + "tf.random.poisson": ["lam", "shape", "dtype", "seed", "name"], + "tf.sparse.add": ["a", "b", "thresh"], + "tf.sparse_add": ["a", "b", "thresh"], + "tf.sparse.concat": [ + "axis", "sp_inputs", "name", "expand_nonconcat_dim", "concat_dim" + ], + "tf.sparse_concat": [ + "axis", "sp_inputs", "name", "expand_nonconcat_dim", "concat_dim" + ], + "tf.sparse.segment_mean": [ + "data", "indices", "segment_ids", "name", "num_segments" + ], + "tf.sparse.segment_sqrt_n": [ + "data", "indices", "segment_ids", "name", "num_segments" + ], + "tf.sparse.segment_sum": [ + "data", "indices", "segment_ids", "name", "num_segments" + ], + "tf.sparse_matmul": [ + "a", "b", "transpose_a", "transpose_b", "a_is_sparse", + "b_is_sparse", "name" + ], + "tf.io.decode_csv": [ + "records", + "record_defaults", + "field_delim", + "use_quote_delim", + "name", + "na_value", + "select_cols", + ], + "tf.strings.substr": ["input", "pos", "len", "name", "unit"], + "tf.strings.reduce_join": [ + "input", "axis", "keep_dims", "separator", "name", + "reduction_indices" + ], + "tf.strings.length": ["input", "name", "unit"], + "tf.transpose": ["a", "perm", "name", "conjugate"], + "tf.tuple": ["tensors", "name", "control_inputs"], + "tf.parse_example": [ + "serialized", "features", "name", "example_names" + ], + "tf.parse_single_example": [ + "serialized", "features", "name", "example_names" + ], + "tf.io.parse_example": [ + "serialized", "features", "name", "example_names" + ], + "tf.io.parse_single_example": [ + "serialized", "features", "name", "example_names" + ], + "tf.while_loop": [ + "cond", "body", "loop_vars", "shape_invariants", + "parallel_iterations", "back_prop", "swap_memory", "name", + "maximum_iterations", "return_same_structure" + ], + "tf.reduce_all": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.math.reduce_all": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.reduce_any": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.math.reduce_any": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.reduce_min": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.math.reduce_min": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.reduce_max": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.math.reduce_max": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.reduce_sum": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.math.reduce_sum": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.reduce_mean": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.math.reduce_mean": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.reduce_prod": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.math.reduce_prod": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.reduce_logsumexp": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.math.reduce_logsumexp": [ + "input_tensor", "axis", "keepdims", "name", "reduction_indices", + "keep_dims" + ], + "tf.reduce_join": [ + "input", "axis", "keep_dims", "separator", "name", + "reduction_indices" + ], + "tf.confusion_matrix": [ + "labels", "predictions", "num_classes", "dtype", "name", "weights" + ], + "tf.math.confusion_matrix": [ + "labels", "predictions", "num_classes", "dtype", "name", "weights" + ] } # Specially handled functions. - self.function_handle = {} + self.function_handle = { + "tf.nn.dropout": self._dropout_handler, + "tf.gradients": self._colocate_handler("tf.gradients"), + "*.minimize": self._colocate_handler("Optimizer.minimize"), + "*.compute_gradients": + self._colocate_handler("Optimizer.compute_gradients"), + } decay_function_comment = ( - "ERROR: has been changed to return a callable instead " - "of a tensor when graph building, but its functionality remains " + "WARNING: has been changed to return a callable instead" + " of a tensor when graph building, but its functionality remains " "unchanged during eager execution (returns a callable like " "before). The converter cannot detect and fix this reliably, so " - "you need to inspect this usage manually.\n" + "this usage has been converted to compat.v1 (even though it may already" + " be correct).\n" ) # TODO(b/118888586): add default value change to update script. @@ -79,99 +678,187 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): "SUM_OVER_BATCH_SIZE.\n" ) + assert_return_type_comment = ( + "WARNING: assert_* functions have been changed to return None, the " + "data argument has been removed, and arguments have been reordered." + "\nThe calls have been converted to compat.v1 for safety (even though " + " they may already have been correct)." + ) + + assert_rank_comment = ( + "WARNING: assert_rank_* functions have been changed to return None, and" + " the data and summarize arguments have been removed." + "\nThe calls have been converted to compat.v1 for safety (even though " + " they may already have been correct)." + ) + + tf_01s_like_no_optimize_comment = ( + "WARNING: tf.zeros_like and tf.ones_like no longer have the optimize " + "argument in TF 2.0 or after (also, `tensor' argument is renamed to " + "`input')." + "\nThe calls have been converted to compat.v1 for safety (even though " + " they may already have been correct)." + ) + # Function warnings. placeholder inside warnings will be # replaced by function name. self.function_warnings = { - "tf.train.exponential_decay": decay_function_comment, - "tf.train.piecewise_constant": decay_function_comment, - "tf.train.polynomial_decay": decay_function_comment, - "tf.train.natural_exp_decay": decay_function_comment, - "tf.train.inverse_time_decay": decay_function_comment, - "tf.train.cosine_decay": decay_function_comment, - "tf.train.cosine_decay_restarts": decay_function_comment, - "tf.train.linear_cosine_decay": decay_function_comment, - "tf.train.noisy_linear_cosine_decay": decay_function_comment, - "tf.estimator.LinearClassifier": default_loss_reduction_changed, + "tf.assert_greater": assert_return_type_comment, + "tf.assert_equal": assert_return_type_comment, + "tf.assert_less": assert_return_type_comment, + "tf.assert_rank": assert_rank_comment, + "tf.debugging.assert_equal": assert_return_type_comment, + "tf.debugging.assert_greater": assert_return_type_comment, + "tf.debugging.assert_greater_equal": assert_return_type_comment, + "tf.debugging.assert_integer": assert_return_type_comment, + "tf.debugging.assert_less": assert_return_type_comment, + "tf.debugging.assert_less_equal": assert_return_type_comment, + "tf.debugging.assert_near": assert_return_type_comment, + "tf.debugging.assert_negative": assert_return_type_comment, + "tf.debugging.assert_non_negative": assert_return_type_comment, + "tf.debugging.assert_non_positive": assert_return_type_comment, + "tf.debugging.assert_none_equal": assert_return_type_comment, + "tf.debugging.assert_positive": assert_return_type_comment, + "tf.debugging.assert_rank": assert_rank_comment, + "tf.debugging.assert_rank_at_least": assert_rank_comment, + "tf.debugging.assert_rank_in": assert_rank_comment, + "tf.flags": "tf.flags has been removed, please use the argparse or absl" + " module if you need command line parsing.", + "tf.train.exponential_decay": + decay_function_comment, + "tf.train.piecewise_constant_decay": + decay_function_comment, + "tf.train.polynomial_decay": + decay_function_comment, + "tf.train.natural_exp_decay": + decay_function_comment, + "tf.train.inverse_time_decay": + decay_function_comment, + "tf.train.cosine_decay": + decay_function_comment, + "tf.train.cosine_decay_restarts": + decay_function_comment, + "tf.train.linear_cosine_decay": + decay_function_comment, + "tf.train.noisy_linear_cosine_decay": + decay_function_comment, + "tf.estimator.LinearClassifier": + default_loss_reduction_changed, + "tf.estimator.LinearRegressor": + default_loss_reduction_changed, + "tf.estimator.DNNLinearCombinedClassifier": + default_loss_reduction_changed, + "tf.estimator.DNNLinearCombinedRegressor": + default_loss_reduction_changed, + "tf.estimator.DNNRegressor": + default_loss_reduction_changed, + "tf.estimator.DNNClassifier": + default_loss_reduction_changed, + "tf.estimator.BaselineClassifier": + default_loss_reduction_changed, + "tf.estimator.BaselineRegressor": + default_loss_reduction_changed, + "tf.nn.conv1d": + "WARNING: use_cudnn_on_gpu argument has been removed and \"value\" was " + "renamed to \"input\"", + "tf.nn.conv2d": + "WARNING: use_cudnn_on_gpu argument has been removed and \"filter\" " + "was renamed to \"filters\"", + "tf.nn.conv2d_backprop_filter": + "WARNING: use_cudnn_on_gpu argument has been removed", + "tf.nn.conv2d_backprop_input": + "WARNING: use_cudnn_on_gpu argument has been removed and \"filter\" " + "was renamed to \"filters\"", + "tf.nn.erosion2d": + "WARNING: now requires a data_format argument", + "tf.nn.nce_loss": + "WARNING: `partition_strategy` has been removed from `tf.nn.nce_loss` " + " The 'div' strategy is used by default.", + "tf.zeros_like": tf_01s_like_no_optimize_comment, + "tf.ones_like": tf_01s_like_no_optimize_comment, } - # Right now we can't have both a rename and a warning. + self.symbol_renames = { name: new_name for name, new_name in self.symbol_renames.items() - if name not in self.function_warnings and name not in excluded_renames } + export_saved_model_renamed = ( + "(Manual edit required) Please rename the method export_savedmodel() " + "to export_saved_model(). Two things to note:\n\t(1) The argument " + "strip_default_attributes has been removed. The function will always " + "strip the default attributes from ops. If this breaks your code, " + "please switch to tf.compat.v1.estimator.Estimator.\n\t(2) This change " + "only effects core estimator. If you are using " + "tf.contrib.learn.Estimator, please switch to using core estimator.") + + make_initializable_iterator_deprecation = ( + "(Manual edit required) The " + "`tf.data.Dataset.make_initializable_iterator()` method has been " + "removed. If you are using the Estimator API, you can return a dataset " + "directly from your input functions without creating an iterator. " + "As a last resort, please replace calls to that method on `dataset` " + "with a call to " + "`tf.compat.v1.data.make_initializable_iterator(dataset)`.") + + make_one_shot_iterator_deprecation = ( + "(Manual edit required) The " + "`tf.data.Dataset.make_one_shot_iterator()` method has been " + "removed. If you are using eager execution, you can iterate over " + "`dataset` using a Python `for` loop. If you are using the Estimator " + "API, you can return a dataset directly from your input functions " + "without creating an iterator. As a last resort, please replace calls " + "to that method on `dataset` with a call to " + "`tf.compat.v1.data.make_one_shot_iterator(dataset)`.") + + # Specify warnings for functions that aren't restricted to the tf.x.y.z + # format. This should only be used for methods with unique names, e.g. + # export_savedmodel, which is only defined in Estimator objects. + self.unrestricted_function_warnings = { + "export_savedmodel": export_saved_model_renamed, + "make_initializable_iterator": make_initializable_iterator_deprecation, + "make_one_shot_iterator": make_one_shot_iterator_deprecation, + } + + @staticmethod + def _dropout_handler(file_edit_recorder, node): + if len(node.args) < 2: + comment = ("ERROR: tf.nn.dropout did not take arguments, so automatic " + "transformation was disabled. tf.nn.dropout has changed " + "the semantics of the second argument.") + file_edit_recorder.add( + comment, + node.lineno, + node.col_offset, + "tf.nn.dropout", + "tf.nn.dropout", + error="tf.nn.dropout requires manual check.") + else: + comment = ("WARNING: tf.nn.dropout has changed the semantics of the " + "second argument. Please check the transformation.\n") + file_edit_recorder.add( + comment, + node.args[1].lineno, + node.args[1].col_offset, + "", + "1 - ") -if __name__ == "__main__": - parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description="""Convert a TensorFlow Python file to 2.0 - -Simple usage: - tf_convert_v2.py --infile foo.py --outfile bar.py - tf_convert_v2.py --intree ~/code/old --outtree ~/code/new -""") - parser.add_argument( - "--infile", - dest="input_file", - help="If converting a single file, the name of the file " - "to convert") - parser.add_argument( - "--outfile", - dest="output_file", - help="If converting a single file, the output filename.") - parser.add_argument( - "--intree", - dest="input_tree", - help="If converting a whole tree of files, the directory " - "to read from (relative or absolute).") - parser.add_argument( - "--outtree", - dest="output_tree", - help="If converting a whole tree of files, the output " - "directory (relative or absolute).") - parser.add_argument( - "--copyotherfiles", - dest="copy_other_files", - help=("If converting a whole tree of files, whether to " - "copy the other files."), - type=bool, - default=False) - parser.add_argument( - "--reportfile", - dest="report_filename", - help=("The name of the file where the report log is " - "stored." - "(default: %(default)s)"), - default="report.txt") - args = parser.parse_args() - - upgrade = ast_edits.ASTCodeUpgrader(TFAPIChangeSpec()) - report_text = None - report_filename = args.report_filename - files_processed = 0 - if args.input_file: - if not args.output_file: - raise ValueError( - "--outfile= argument is required when converting a " - "single file.") - files_processed, report_text, errors = upgrade.process_file( - args.input_file, args.output_file) - files_processed = 1 - elif args.input_tree: - if not args.output_tree: - raise ValueError( - "--outtree= argument is required when converting a " - "file tree.") - files_processed, report_text, errors = upgrade.process_tree( - args.input_tree, args.output_tree, args.copy_other_files) - else: - parser.print_help() - if report_text: - open(report_filename, "w").write(report_text) - print("TensorFlow 2.0 Upgrade Script") - print("-----------------------------") - print("Converted %d files\n" % files_processed) - print("Detected %d errors that require attention" % len(errors)) - print("-" * 80) - print("\n".join(errors)) - print("\nMake sure to read the detailed log %r\n" % report_filename) + @staticmethod + def _colocate_handler(name): + def _helper(file_edit_recorder, node): + for keyword in node.keywords: + if keyword.arg == "colocate_gradients_with_ops": + # TODO(jhseu): Since ast_edit.py does string replacement, there's no + # straightforward way to remove the argument. Try to fix before 2.0 is + # final. + comment = ("For tf.gradients and tf.Optimizer.minimize, " + "colocate_gradients_with_op has been removed and now " + "defaults to True.") + file_edit_recorder.add( + comment, + node.lineno, + node.col_offset, + "", + "", + error="{} requires manual check.".format(name)) + return _helper diff --git a/tensorflow/tools/compatibility/tf_upgrade_v2_main.py b/tensorflow/tools/compatibility/tf_upgrade_v2_main.py new file mode 100644 index 0000000000..543d078642 --- /dev/null +++ b/tensorflow/tools/compatibility/tf_upgrade_v2_main.py @@ -0,0 +1,104 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Upgrader for Python scripts from 1.* TensorFlow to 2.0 TensorFlow.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import argparse + +from tensorflow.tools.compatibility import ast_edits +from tensorflow.tools.compatibility import tf_upgrade_v2 + + +def main(): + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description="""Convert a TensorFlow Python file to 2.0 + +Simple usage: + tf_upgrade_v2.py --infile foo.py --outfile bar.py + tf_upgrade_v2.py --intree ~/code/old --outtree ~/code/new +""") + parser.add_argument( + "--infile", + dest="input_file", + help="If converting a single file, the name of the file " + "to convert") + parser.add_argument( + "--outfile", + dest="output_file", + help="If converting a single file, the output filename.") + parser.add_argument( + "--intree", + dest="input_tree", + help="If converting a whole tree of files, the directory " + "to read from (relative or absolute).") + parser.add_argument( + "--outtree", + dest="output_tree", + help="If converting a whole tree of files, the output " + "directory (relative or absolute).") + parser.add_argument( + "--copyotherfiles", + dest="copy_other_files", + help=("If converting a whole tree of files, whether to " + "copy the other files."), + type=bool, + default=True) + parser.add_argument( + "--reportfile", + dest="report_filename", + help=("The name of the file where the report log is " + "stored." + "(default: %(default)s)"), + default="report.txt") + args = parser.parse_args() + + upgrade = ast_edits.ASTCodeUpgrader(tf_upgrade_v2.TFAPIChangeSpec()) + report_text = None + report_filename = args.report_filename + files_processed = 0 + if args.input_file: + if not args.output_file: + raise ValueError( + "--outfile= argument is required when converting a " + "single file.") + files_processed, report_text, errors = upgrade.process_file( + args.input_file, args.output_file) + files_processed = 1 + elif args.input_tree: + if not args.output_tree: + raise ValueError( + "--outtree= argument is required when converting a " + "file tree.") + files_processed, report_text, errors = upgrade.process_tree( + args.input_tree, args.output_tree, args.copy_other_files) + else: + parser.print_help() + if report_text: + open(report_filename, "w").write(report_text) + print("TensorFlow 2.0 Upgrade Script") + print("-----------------------------") + print("Converted %d files\n" % files_processed) + print("Detected %d errors that require attention" % len(errors)) + print("-" * 80) + print("\n".join(errors)) + print("\nMake sure to read the detailed log %r\n" % report_filename) + + +if __name__ == "__main__": + main() diff --git a/tensorflow/tools/compatibility/tf_upgrade_v2_test.py b/tensorflow/tools/compatibility/tf_upgrade_v2_test.py index 9060b1c71f..b8b02c9c7f 100644 --- a/tensorflow/tools/compatibility/tf_upgrade_v2_test.py +++ b/tensorflow/tools/compatibility/tf_upgrade_v2_test.py @@ -17,15 +17,71 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function + import os import tempfile + import six +import tensorflow as tf +# OSS TF V2 import placeholder. + + from tensorflow.python.framework import test_util from tensorflow.python.platform import test as test_lib +from tensorflow.python.util import tf_decorator +from tensorflow.python.util import tf_export +from tensorflow.python.util import tf_inspect +from tensorflow.tools.common import public_api +from tensorflow.tools.common import traverse from tensorflow.tools.compatibility import ast_edits from tensorflow.tools.compatibility import tf_upgrade_v2 +_TENSORFLOW_API_ATTR_V1 = ( + tf_export.API_ATTRS_V1[tf_export.TENSORFLOW_API_NAME].names) +_TENSORFLOW_API_ATTR = tf_export.API_ATTRS[tf_export.TENSORFLOW_API_NAME].names +_ESTIMATOR_API_ATTR_V1 = ( + tf_export.API_ATTRS_V1[tf_export.ESTIMATOR_API_NAME].names) +_ESTIMATOR_API_ATTR = tf_export.API_ATTRS[tf_export.ESTIMATOR_API_NAME].names + + +def get_v1_names(symbol): + names_v1 = [] + if hasattr(symbol, _TENSORFLOW_API_ATTR_V1): + names_v1.extend(getattr(symbol, _TENSORFLOW_API_ATTR_V1)) + if hasattr(symbol, _ESTIMATOR_API_ATTR_V1): + names_v1.extend(getattr(symbol, _ESTIMATOR_API_ATTR_V1)) + return names_v1 + + +def get_v2_names(symbol): + names_v2 = set() + if hasattr(symbol, _TENSORFLOW_API_ATTR): + names_v2.update(getattr(symbol, _TENSORFLOW_API_ATTR)) + if hasattr(symbol, _ESTIMATOR_API_ATTR): + names_v2.update(getattr(symbol, _ESTIMATOR_API_ATTR)) + return list(names_v2) + + +def get_func_and_args_from_str(call_str): + """Parse call string to get function and argument names. + + Args: + call_str: Call string must be in the form: + `tf.foo(arg1=val1, arg2=val2, ...)`. + + Returns: + (function_name, list of arg names) tuple. + """ + open_paren_index = call_str.find("(") + close_paren_index = call_str.rfind(")") + + function_name = call_str[:call_str.find("(")] + args = call_str[open_paren_index+1:close_paren_index].split(",") + args = [arg.split("=")[0].strip() for arg in args] + return function_name, args + + class TestUpgrade(test_util.TensorFlowTestCase): """Test various APIs that have been changed in 2.0. @@ -34,6 +90,22 @@ class TestUpgrade(test_util.TensorFlowTestCase): work when run with current TensorFlow. """ + @classmethod + def setUpClass(cls): + cls.v2_symbols = {} + if not hasattr(tf.compat, "v2"): + return + + def symbol_collector(unused_path, unused_parent, children): + for child in children: + _, attr = tf_decorator.unwrap(child[1]) + api_names_v2 = get_v2_names(attr) + for name in api_names_v2: + cls.v2_symbols["tf." + name] = attr + + visitor = public_api.PublicAPIVisitor(symbol_collector) + traverse.traverse(tf.compat.v2, visitor) + def _upgrade(self, old_file_text): in_file = six.StringIO(old_file_text) out_file = six.StringIO() @@ -64,6 +136,85 @@ class TestUpgrade(test_util.TensorFlowTestCase): _, unused_report, unused_errors, new_text = self._upgrade(text) self.assertEqual(new_text, "tf.math.rsqrt(tf.math.log_sigmoid(3.8))\n") + def testAllAPI(self): + if not hasattr(tf.compat, "v2"): + return + + # Converts all symbols in the v1 namespace to the v2 namespace, raising + # an error if the target of the conversion is not in the v2 namespace. + def conversion_visitor(unused_path, unused_parent, children): + for child in children: + _, attr = tf_decorator.unwrap(child[1]) + api_names = get_v1_names(attr) + for name in api_names: + _, _, _, text = self._upgrade("tf." + name) + if (text and + not text.startswith("tf.compat.v1") and + text not in self.v2_symbols): + self.assertFalse( + True, "Symbol %s generated from %s not in v2 API" % ( + text, name)) + + visitor = public_api.PublicAPIVisitor(conversion_visitor) + visitor.do_not_descend_map["tf"].append("contrib") + visitor.private_map["tf.compat"] = ["v1", "v2"] + traverse.traverse(tf.compat.v1, visitor) + + def testKeywordArgNames(self): + if not hasattr(tf.compat, "v2"): + return + + all_keyword_renames = ( + tf_upgrade_v2.TFAPIChangeSpec().function_keyword_renames) + v2_name_exceptions = {"verify_shape_is_now_always_true"} + + # Visitor that verifies V1 argument names, converts to V2 and checks + # V2 argument names. + def conversion_visitor(unused_path, unused_parent, children): + for child in children: + _, attr = tf_decorator.unwrap(child[1]) + names_v1 = get_v1_names(attr) + + for name in names_v1: + name = "tf.%s" % name + if name not in all_keyword_renames: + continue + arg_names_v1 = tf_inspect.getargspec(attr)[0] + keyword_renames = all_keyword_renames[name] + self.assertEqual(type(keyword_renames), dict) + + # Assert that v1 function has valid v1 argument names. + for from_name, _ in keyword_renames.items(): + self.assertIn( + from_name, arg_names_v1, + "%s not found in %s arguments: %s" % + (from_name, name, str(arg_names_v1))) + + # Assert that arg names after converting to v2 are present in + # v2 function. + # 1. First, create an input of the form: + # tf.foo(arg1=val1, arg2=val2, ...) + args = ",".join( + ["%s=%d" % (from_name, from_index) + for from_index, from_name in enumerate(keyword_renames.keys())]) + text_input = "%s(%s)" % (name, args) + # 2. Convert the input to V2. + _, _, _, text = self._upgrade(text_input) + new_function_name, new_args = get_func_and_args_from_str(text) + # 3. Verify V2 function and arguments. + # Note: If we rename arguments, new function must be available in 2.0. + # We should not be using compat.v1 in this case. + self.assertIn(new_function_name, self.v2_symbols) + args_v2 = tf_inspect.getargspec(self.v2_symbols[new_function_name])[0] + args_v2.extend(v2_name_exceptions) + for new_arg in new_args: + self.assertIn(new_arg, args_v2) + + visitor = public_api.PublicAPIVisitor(conversion_visitor) + visitor.do_not_descend_map["tf"].append("contrib") + visitor.private_map["tf.compat"] = ["v1", "v2"] + traverse.traverse(tf.compat.v1, visitor) + def testRenameConstant(self): text = "tf.MONOLITHIC_BUILD\n" _, unused_report, unused_errors, new_text = self._upgrade(text) @@ -72,6 +223,16 @@ class TestUpgrade(test_util.TensorFlowTestCase): _, unused_report, unused_errors, new_text = self._upgrade(text) self.assertEqual(new_text, "some_call(tf.sysconfig.MONOLITHIC_BUILD)\n") + def testRenameArgs(self): + text = ("tf.nn.pool(input_a, window_shape_a, pooling_type_a, padding_a, " + "dilation_rate_a, strides_a, name_a, data_format_a)\n") + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, + ("tf.nn.pool(input=input_a, window_shape=window_shape_a," + " pooling_type=pooling_type_a, padding=padding_a, " + "dilations=dilation_rate_a, strides=strides_a, " + "name=name_a, data_format=data_format_a)\n")) + def testReorder(self): text = "tf.boolean_mask(a, b, c, d)\n" _, unused_report, unused_errors, new_text = self._upgrade(text) @@ -79,7 +240,7 @@ class TestUpgrade(test_util.TensorFlowTestCase): "tf.boolean_mask(tensor=a, mask=b, name=c, axis=d)\n") def testLearningRateDecay(self): - for decay in ["tf.train.exponential_decay", "tf.train.piecewise_constant", + for decay in ["tf.train.exponential_decay", "tf.train.polynomial_decay", "tf.train.natural_exp_decay", "tf.train.inverse_time_decay", "tf.train.cosine_decay", "tf.train.cosine_decay_restarts", @@ -87,18 +248,208 @@ class TestUpgrade(test_util.TensorFlowTestCase): "tf.train.noisy_linear_cosine_decay"]: text = "%s(a, b)\n" % decay - _, report, errors, new_text = self._upgrade(text) - self.assertEqual(text, new_text) + _, report, errors, _ = self._upgrade(text) self.assertEqual(errors, ["test.py:1: %s requires manual check." % decay]) self.assertIn("%s has been changed" % decay, report) - def testEstimatorLossReductionChangege(self): - text = "tf.estimator.LinearClassifier(a, b)\n" - _, report, errors, new_text = self._upgrade(text) + def testPiecewiseDecay(self): + text = "tf.train.piecewise_constant_decay(a, b)\n" + _, report, errors, _ = self._upgrade(text) + self.assertEqual( + errors, + ["test.py:1: tf.train.piecewise_constant_decay requires manual check."]) + self.assertIn("tf.train.piecewise_constant_decay has been changed", report) + + def testEstimatorLossReductionChange(self): + classes = [ + "LinearClassifier", "LinearRegressor", "DNNLinearCombinedClassifier", + "DNNLinearCombinedRegressor", "DNNRegressor", "DNNClassifier", + "BaselineClassifier", "BaselineRegressor" + ] + for c in classes: + ns = "tf.estimator." + c + text = ns + "(a, b)" + _, report, errors, new_text = self._upgrade(text) + self.assertEqual(text, new_text) + self.assertEqual(errors, ["test.py:1: %s requires manual check." % ns]) + self.assertIn("loss_reduction has been changed", report) + + def testDropout(self): + text = "tf.nn.dropout(x, keep_prob, name=\"foo\")\n" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual( + new_text, + "tf.nn.dropout(x, 1 - keep_prob, name=\"foo\")\n", + ) + + text = "tf.nn.dropout(x)\n" + _, unused_report, errors, new_text = self._upgrade(text) + self.assertEqual(new_text, text) + self.assertEqual( + errors, + ["test.py:1: tf.nn.dropout requires manual check."] + ) + + def testCountNonZeroChanges(self): + text = ( + "tf.math.count_nonzero(input_tensor=input, dtype=dtype, name=name, " + "reduction_indices=axis, keep_dims=keepdims)\n" + ) + _, unused_report, unused_errors, new_text = self._upgrade(text) + expected_text = ( + "tf.math.count_nonzero(input=input, dtype=dtype, name=name, " + "axis=axis, keepdims=keepdims)\n" + ) + self.assertEqual(new_text, expected_text) + + def testRandomMultinomialToRandomCategorical(self): + text = ( + "tf.random.multinomial(logits, samples, seed, name, output_dtype)\n" + ) + _, unused_report, unused_errors, new_text = self._upgrade(text) + expected_text = ( + "tf.random.categorical(logits=logits, num_samples=samples, seed=seed, " + "name=name, dtype=output_dtype)\n" + ) + self.assertEqual(new_text, expected_text) + + text = ( + "tf.multinomial(logits, samples, seed, name, output_dtype)\n" + ) + _, unused_report, unused_errors, new_text = self._upgrade(text) + expected_text = ( + "tf.random.categorical(logits=logits, num_samples=samples, seed=seed, " + "name=name, dtype=output_dtype)\n" + ) + self.assertEqual(new_text, expected_text) + + def testConvolutionOpUpdate(self): + text = ( + "tf.nn.convolution(input, filter, padding, strides, dilation_rate, " + "name, data_format)" + ) + _, unused_report, unused_errors, new_text = self._upgrade(text) + expected_text = ( + "tf.nn.convolution(input=input, filters=filter, padding=padding, " + "strides=strides, dilations=dilation_rate, name=name, " + "data_format=data_format)" + ) + self.assertEqual(new_text, expected_text) + + def testColocateGradientsWithOps(self): + text = "tf.gradients(a, foo=False)\n" + _, unused_report, errors, new_text = self._upgrade(text) + self.assertEqual(text, new_text) + self.assertEqual(errors, []) + + text = "tf.gradients(a, colocate_gradients_with_ops=False)\n" + _, unused_report, errors, new_text = self._upgrade(text) + self.assertEqual(text, new_text) + self.assertEqual(errors, ["test.py:1: tf.gradients requires manual check."]) + + text = "optimizer.minimize(a, foo=False)\n" + _, unused_report, errors, new_text = self._upgrade(text) self.assertEqual(text, new_text) - self.assertEqual(errors, ["test.py:1: %s requires manual check." - % "tf.estimator.LinearClassifier"]) - self.assertIn("loss_reduction has been changed", report) + self.assertEqual(errors, []) + + text = "optimizer.minimize(a, colocate_gradients_with_ops=False)\n" + _, unused_report, errors, new_text = self._upgrade(text) + self.assertEqual(text, new_text) + self.assertEqual(errors, + ["test.py:1: Optimizer.minimize requires manual check."]) + + text = "optimizer.compute_gradients(a, foo=False)\n" + _, unused_report, errors, new_text = self._upgrade(text) + self.assertEqual(text, new_text) + self.assertEqual(errors, []) + + text = "optimizer.compute_gradients(a, colocate_gradients_with_ops=False)\n" + _, unused_report, errors, new_text = self._upgrade(text) + self.assertEqual(text, new_text) + self.assertEqual(errors, + ["test.py:1: Optimizer.compute_gradients " + "requires manual check."]) + + def testExportSavedModelRename(self): + text = "self.est.export_savedmodel(path)" + _, report, unused_errors, unused_new_text = self._upgrade(text) + self.assertIn( + "rename the method export_savedmodel() to export_saved_model()", + report) + + def testArgmin(self): + text = "tf.argmin(input, name=n, dimension=1, output_type=type)" + expected_text = "tf.argmin(input=input, name=n, axis=1, output_type=type)" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + text = "tf.argmin(input, 0)" + expected_text = "tf.argmin(input=input, axis=0)" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + def testArgmax(self): + text = "tf.argmax(input, name=n, dimension=1, output_type=type)" + expected_text = "tf.argmax(input=input, name=n, axis=1, output_type=type)" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + text = "tf.argmax(input, 0)" + expected_text = "tf.argmax(input=input, axis=0)" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + def testBatchToSpace(self): + text = "tf.batch_to_space_nd(input, block_shape, crops, name)" + expected_text = "tf.batch_to_space(input, block_shape, crops, name)" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + text = "tf.batch_to_space(input, crops, block_size, name)" + expected_text = ( + "tf.batch_to_space(input=input, crops=crops, block_shape=block_size, " + "name=name)") + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + text = "tf.manip.batch_to_space_nd(input, block_shape, crops, name)" + expected_text = "tf.batch_to_space(input, block_shape, crops, name)" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + def testExtractImagePatches(self): + text = ( + "tf.extract_image_patches(images, ksizes=ksizes, strides=strides," + "rates=rates, padding=padding, name=name)") + expected_text = ( + "tf.image.extract_image_patches(images, sizes=ksizes, strides=strides," + "rates=rates, padding=padding, name=name)") + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + def testStatelessMultinomial(self): + text = ( + "tf.random.stateless_multinomial(logits, num_samples, seed, " + "output_dtype=dtype, name=name)") + expected_text = ( + "tf.random.stateless_categorical(logits, num_samples, seed, " + "dtype=dtype, name=name)") + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + def testSoftMaxCrossEntropyWithLogitsV2(self): + text = "tf.nn.softmax_cross_entropy_with_logits_v2(labels, logits, dim=2)" + expected_text = ( + "tf.nn.softmax_cross_entropy_with_logits(labels, logits, axis=2)") + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + def testSparseMatmul(self): + text = ("tf.sparse_matmul(a, b, c, d, e, f, g)\n") + expected_text = ("tf.linalg.matmul(a=a, b=b, transpose_a=c, transpose_b=d, " + "a_is_sparse=e, b_is_sparse=f, name=g)\n") + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) class TestUpgradeFiles(test_util.TensorFlowTestCase): diff --git a/tensorflow/tools/compatibility/update/BUILD b/tensorflow/tools/compatibility/update/BUILD index 0ee4550815..b9725a74ee 100644 --- a/tensorflow/tools/compatibility/update/BUILD +++ b/tensorflow/tools/compatibility/update/BUILD @@ -12,5 +12,6 @@ py_binary( "//tensorflow/python:no_contrib", "//tensorflow/tools/common:public_api", "//tensorflow/tools/common:traverse", + "//tensorflow/tools/compatibility:tf_upgrade_v2_lib", ], ) diff --git a/tensorflow/tools/compatibility/update/generate_v2_renames_map.py b/tensorflow/tools/compatibility/update/generate_v2_renames_map.py index 43aa8e057e..19ad6c3a2a 100644 --- a/tensorflow/tools/compatibility/update/generate_v2_renames_map.py +++ b/tensorflow/tools/compatibility/update/generate_v2_renames_map.py @@ -32,6 +32,7 @@ from tensorflow.python.util import tf_decorator from tensorflow.python.util import tf_export from tensorflow.tools.common import public_api from tensorflow.tools.common import traverse +from tensorflow.tools.compatibility import tf_upgrade_v2 _OUTPUT_FILE_PATH = 'third_party/tensorflow/tools/compatibility/renames_v2.py' @@ -71,6 +72,50 @@ _TENSORFLOW_CONSTANTS_ATTR_V1 = ( _TENSORFLOW_CONSTANTS_ATTR = ( tf_export.API_ATTRS[tf_export.TENSORFLOW_API_NAME].constants) +_ESTIMATOR_API_ATTR_V1 = ( + tf_export.API_ATTRS_V1[tf_export.ESTIMATOR_API_NAME].names) +_ESTIMATOR_API_ATTR = tf_export.API_ATTRS[tf_export.ESTIMATOR_API_NAME].names +_ESTIMATOR_CONSTANTS_ATTR_V1 = ( + tf_export.API_ATTRS_V1[tf_export.ESTIMATOR_API_NAME].constants) +_ESTIMATOR_CONSTANTS_ATTR = ( + tf_export.API_ATTRS[tf_export.ESTIMATOR_API_NAME].constants) + + +def get_v1_names(symbol): + names_v1 = [] + if hasattr(symbol, _TENSORFLOW_API_ATTR_V1): + names_v1.extend(getattr(symbol, _TENSORFLOW_API_ATTR_V1)) + if hasattr(symbol, _ESTIMATOR_API_ATTR_V1): + names_v1.extend(getattr(symbol, _ESTIMATOR_API_ATTR_V1)) + return names_v1 + + +def get_v2_names(symbol): + names_v2 = [] + if hasattr(symbol, _TENSORFLOW_API_ATTR): + names_v2.extend(getattr(symbol, _TENSORFLOW_API_ATTR)) + if hasattr(symbol, _ESTIMATOR_API_ATTR): + names_v2.extend(getattr(symbol, _ESTIMATOR_API_ATTR)) + return list(names_v2) + + +def get_v1_constants(module): + constants_v1 = [] + if hasattr(module, _TENSORFLOW_CONSTANTS_ATTR_V1): + constants_v1.extend(getattr(module, _TENSORFLOW_CONSTANTS_ATTR_V1)) + if hasattr(module, _ESTIMATOR_CONSTANTS_ATTR_V1): + constants_v1.extend(getattr(module, _ESTIMATOR_CONSTANTS_ATTR_V1)) + return constants_v1 + + +def get_v2_constants(module): + constants_v2 = [] + if hasattr(module, _TENSORFLOW_CONSTANTS_ATTR): + constants_v2.extend(getattr(module, _TENSORFLOW_CONSTANTS_ATTR)) + if hasattr(module, _ESTIMATOR_CONSTANTS_ATTR): + constants_v2.extend(getattr(module, _ESTIMATOR_CONSTANTS_ATTR)) + return constants_v2 + def get_canonical_name(v2_names, v1_name): if v2_names: @@ -78,18 +123,34 @@ def get_canonical_name(v2_names, v1_name): return 'compat.v1.%s' % v1_name +def get_all_v2_names(): + """Get a set of function/class names available in TensorFlow 2.0.""" + v2_names = set() # All op names in TensorFlow 2.0 + + def visit(unused_path, unused_parent, children): + """Visitor that collects TF 2.0 names.""" + for child in children: + _, attr = tf_decorator.unwrap(child[1]) + api_names_v2 = get_v2_names(attr) + for name in api_names_v2: + v2_names.add(name) + + visitor = public_api.PublicAPIVisitor(visit) + visitor.do_not_descend_map['tf'].append('contrib') + traverse.traverse(tf.compat.v2, visitor) + return v2_names + + def collect_constant_renames(): """Looks for constants that need to be renamed in TF 2.0. Returns: - List of tuples of the form (current name, new name). + Set of tuples of the form (current name, new name). """ renames = set() for module in sys.modules.values(): - if not hasattr(module, _TENSORFLOW_CONSTANTS_ATTR_V1): - continue - constants_v1_list = getattr(module, _TENSORFLOW_CONSTANTS_ATTR_V1) - constants_v2_list = getattr(module, _TENSORFLOW_CONSTANTS_ATTR) + constants_v1_list = get_v1_constants(module) + constants_v2_list = get_v2_constants(module) # _tf_api_constants attribute contains a list of tuples: # (api_names_list, constant_name) @@ -115,26 +176,21 @@ def collect_function_renames(): """Looks for functions/classes that need to be renamed in TF 2.0. Returns: - List of tuples of the form (current name, new name). + Set of tuples of the form (current name, new name). """ # Set of rename lines to write to output file in the form: # 'tf.deprecated_name': 'tf.canonical_name' renames = set() - v2_names = set() # All op names in TensorFlow 2.0 def visit(unused_path, unused_parent, children): """Visitor that collects rename strings to add to rename_line_set.""" for child in children: _, attr = tf_decorator.unwrap(child[1]) - if not hasattr(attr, '__dict__'): - continue - api_names_v1 = attr.__dict__.get(_TENSORFLOW_API_ATTR_V1, []) - api_names_v2 = attr.__dict__.get(_TENSORFLOW_API_ATTR, []) + api_names_v1 = get_v1_names(attr) + api_names_v2 = get_v2_names(attr) deprecated_api_names = set(api_names_v1) - set(api_names_v2) for name in deprecated_api_names: renames.add((name, get_canonical_name(api_names_v2, name))) - for name in api_names_v2: - v2_names.add(name) visitor = public_api.PublicAPIVisitor(visit) visitor.do_not_descend_map['tf'].append('contrib') @@ -144,8 +200,9 @@ def collect_function_renames(): # It is possible that a different function is exported with the # same name. For e.g. when creating a different function to # rename arguments. Exclude it from renames in this case. - renames = {name: new_name for name, new_name in renames.items() - if name not in v2_names} + v2_names = get_all_v2_names() + renames = set((name, new_name) for name, new_name in renames + if name not in v2_names) return renames @@ -163,12 +220,15 @@ def update_renames_v2(output_file_path): function_renames = collect_function_renames() constant_renames = collect_constant_renames() all_renames = function_renames.union(constant_renames) + manual_renames = set( + tf_upgrade_v2.TFAPIChangeSpec().manual_symbol_renames.keys()) # List of rename lines to write to output file in the form: # 'tf.deprecated_name': 'tf.canonical_name' rename_lines = [ get_rename_line(name, canonical_name) - for name, canonical_name in all_renames] + for name, canonical_name in all_renames + if 'tf.' + name not in manual_renames] renames_file_text = '%srenames = {\n%s\n}\n' % ( _FILE_HEADER, ',\n'.join(sorted(rename_lines))) file_io.write_string_to_file(output_file_path, renames_file_text) diff --git a/tensorflow/tools/docker/Dockerfile b/tensorflow/tools/docker/Dockerfile index 205128ad58..6676de02a4 100644 --- a/tensorflow/tools/docker/Dockerfile +++ b/tensorflow/tools/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 LABEL maintainer="Craig Citro " @@ -8,7 +8,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ libfreetype6-dev \ libhdf5-serial-dev \ - libpng12-dev \ + libpng-dev \ libzmq3-dev \ pkg-config \ python \ diff --git a/tensorflow/tools/docker/Dockerfile.devel b/tensorflow/tools/docker/Dockerfile.devel index a3893a2713..c256dd364e 100644 --- a/tensorflow/tools/docker/Dockerfile.devel +++ b/tensorflow/tools/docker/Dockerfile.devel @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 LABEL maintainer="Craig Citro " @@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libcurl3-dev \ libfreetype6-dev \ libhdf5-serial-dev \ - libpng12-dev \ + libpng-dev \ libzmq3-dev \ pkg-config \ python-dev \ diff --git a/tensorflow/tools/docker/Dockerfile.devel-mkl b/tensorflow/tools/docker/Dockerfile.devel-mkl index bd2883ddba..2341c0e8cc 100755 --- a/tensorflow/tools/docker/Dockerfile.devel-mkl +++ b/tensorflow/tools/docker/Dockerfile.devel-mkl @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 LABEL maintainer="Clayne Robison " @@ -16,7 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libcurl3-dev \ libfreetype6-dev \ libhdf5-serial-dev \ - libpng12-dev \ + libpng-dev \ libzmq3-dev \ libssl-dev \ pkg-config \ diff --git a/tensorflow/tools/docker/Dockerfile.devel-mkl-horovod b/tensorflow/tools/docker/Dockerfile.devel-mkl-horovod index df084e029c..5e24617b21 100755 --- a/tensorflow/tools/docker/Dockerfile.devel-mkl-horovod +++ b/tensorflow/tools/docker/Dockerfile.devel-mkl-horovod @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 LABEL maintainer="Cong Xu " @@ -16,7 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libcurl3-dev \ libfreetype6-dev \ libhdf5-serial-dev \ - libpng12-dev \ + libpng-dev \ libzmq3-dev \ pkg-config \ python-dev \ diff --git a/tensorflow/tools/docker/Dockerfile.mkl b/tensorflow/tools/docker/Dockerfile.mkl index ac41cffe4b..dad27697fa 100755 --- a/tensorflow/tools/docker/Dockerfile.mkl +++ b/tensorflow/tools/docker/Dockerfile.mkl @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 LABEL maintainer="Clayne Robison " @@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ libfreetype6-dev \ libhdf5-serial-dev \ - libpng12-dev \ + libpng-dev \ libzmq3-dev \ pkg-config \ ${PYTHON} \ diff --git a/tensorflow/tools/docker/Dockerfile.mkl-horovod b/tensorflow/tools/docker/Dockerfile.mkl-horovod index 0432cd5e80..19dc45c62c 100755 --- a/tensorflow/tools/docker/Dockerfile.mkl-horovod +++ b/tensorflow/tools/docker/Dockerfile.mkl-horovod @@ -1,4 +1,4 @@ -FROM ubuntu:16.04 +FROM ubuntu:18.04 LABEL maintainer="Cong Xu " @@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ libfreetype6-dev \ libhdf5-serial-dev \ - libpng12-dev \ + libpng-dev \ libzmq3-dev \ pkg-config \ python \ diff --git a/tensorflow/tools/dockerfiles/.gitignore b/tensorflow/tools/dockerfiles/.gitignore new file mode 100644 index 0000000000..d7efa472a9 --- /dev/null +++ b/tensorflow/tools/dockerfiles/.gitignore @@ -0,0 +1 @@ +dockerfiles/*.temp.Dockerfile diff --git a/tensorflow/tools/dockerfiles/README.md b/tensorflow/tools/dockerfiles/README.md index 7c8ca1d1c7..2ac68666d0 100644 --- a/tensorflow/tools/dockerfiles/README.md +++ b/tensorflow/tools/dockerfiles/README.md @@ -1,8 +1,12 @@ # TensorFlow Dockerfiles -This directory houses TensorFlow's Dockerfiles. **DO NOT EDIT THE DOCKERFILES -MANUALLY!** They are maintained by `assembler.py`, which builds Dockerfiles from -the files in `partials/` and the rules in `spec.yml`. See [the Contributing +This directory houses TensorFlow's Dockerfiles and the infrastructure used to +create and deploy them to [Docker +Hub](https://hub.docker.com/r/tensorflow/tensorflow). + +**DO NOT EDIT THE DOCKERFILES/ DIRECTORY MANUALLY!** The files within are +maintained by `assembler.py`, which builds Dockerfiles from the files in +`partials/` and the rules in `spec.yml`. See [the Contributing section](#contributing) for more information. These Dockerfiles are planned to replace the Dockerfiles used to generate @@ -20,10 +24,10 @@ $ docker build -f ./dockerfiles/cpu.Dockerfile -t tf . Each Dockerfile has its own set of available `--build-arg`s which are documented in the Dockerfile itself. -## Running +## Running Locally Built Images After building the image with the tag `tf` (for example), use `docker run` to -run the images. Examples are below. +run the images. Note for new Docker users: the `-v` and `-u` flags share directories between the Docker container and your machine, and very important. Without @@ -42,8 +46,10 @@ $ docker run -u $(id -u):$(id -g) -v $(pwd):/my-devel -it tf # GPU-based images (set up nvidia-docker2 first) $ docker run --runtime=nvidia -u $(id -u):$(id -g) -v $(pwd):/my-devel -it tf -# Images with Jupyter run on port 8888, and needs a volume for notebooks -$ docker run --user $(id -u):$(id -g) -p 8888:8888 -v $(pwd):/notebooks -it tf +# Images with Jupyter run on port 8888 and need a volume for your notebooks +# You can change $(PWD) to the full path to a directory if your notebooks +# live outside the current directory. +$ docker run --user $(id -u):$(id -g) -p 8888:8888 -v $(PWD):/tf/notebooks -it tf ``` These images do not come with the TensorFlow source code -- but the development @@ -60,11 +66,32 @@ You can use the `Dockerfile` in this directory to build an editing environment that has all of the Python dependencies you'll need: ```bash -$ docker build -t tf-assembler -f assembler.Dockerfile . +# Build the tools-helper image so you can run the assembler +$ docker build -t tf-tools -f tools.Dockerfile . # Set --user to set correct permissions on generated files -$ docker run --user $(id -u):$(id -g) -it -v $(pwd):/tf tf-assembler bash +$ docker run --user $(id -u):$(id -g) -it -v $(pwd):/tf tf-tools bash + +# Next you can make a handy alias depending on what you're doing. When building +# Docker images, you need to run as root with docker.sock mounted so that the +# container can run Docker commands. When assembling Dockerfiles, though, you'll +# want to run as your user so that new files have the right permissions. + +# If you're BUILDING OR DEPLOYING DOCKER IMAGES, run as root with docker.sock: +$ alias asm_images="docker run --rm -v $(pwd):/tf -v /var/run/docker.sock:/var/run/docker.sock tf-tools python3 assembler.py " + +# If you're REBUILDING OR ADDING DOCKERFILES, remove docker.sock and add -u: +$ alias asm_dockerfiles="docker run --rm -u $(id -u):$(id -g) -v $(pwd):/tf tf-tools python3 assembler.py " + +# Check flags +$ asm_dockerfiles --help + +# Assemble all of the Dockerfiles +$ asm_dockerfiles --release ubuntu-dockerfiles --construct_dockerfiles + +# Build all of the "nightly" images on your local machine: +$ asm_images --release nightly --build_images -# In the container... -/tf $ python3 ./assembler.py -o dockerfiles -s spec.yml +# Build version release for version 99.0, except "gpu" tags: +$ asm_images --release versioned --arg _TAG_PREFIX=99.0 --build_images --exclude_tags_matching '*.gpu.*' ``` diff --git a/tensorflow/tools/dockerfiles/assembler.py b/tensorflow/tools/dockerfiles/assembler.py index 9cdd9bb0cb..9d8a59aebc 100644 --- a/tensorflow/tools/dockerfiles/assembler.py +++ b/tensorflow/tools/dockerfiles/assembler.py @@ -11,63 +11,144 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# ============================================================================== -"""Assemble common TF Dockerfiles from many parts. +# ============================================================================ +"""Multipurpose TensorFlow Docker Helper. -This script constructs TF's Dockerfiles by aggregating partial -Dockerfiles. See README.md for usage examples. +- Assembles Dockerfiles +- Builds images (and optionally runs image tests) +- Pushes images to Docker Hub (provided with credentials) + +Read README.md (in this directory) for instructions! """ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import collections import copy import errno +import itertools +import multiprocessing import os -import os.path import re import shutil -import textwrap +import sys from absl import app from absl import flags import cerberus +import docker import yaml FLAGS = flags.FLAGS +flags.DEFINE_string('hub_username', None, + 'Dockerhub username, only used with --upload_to_hub') + +flags.DEFINE_string( + 'hub_password', None, + ('Dockerhub password, only used with --upload_to_hub. Use from an env param' + 'so your password isn\'t in your history.')) + +flags.DEFINE_integer('hub_timeout', 3600, + 'Abort Hub upload if it takes longer than this.') + +flags.DEFINE_string( + 'repository', 'tensorflow', + 'Tag local images as {repository}:tag (in addition to the ' + 'hub_repository, if uploading to hub)') + +flags.DEFINE_string( + 'hub_repository', None, + 'Push tags to this Docker Hub repository, e.g. tensorflow/tensorflow') + +flags.DEFINE_boolean( + 'upload_to_hub', + False, + ('Push built images to Docker Hub (you must also provide --hub_username, ' + '--hub_password, and --hub_repository)'), + short_name='u', +) + flags.DEFINE_boolean( - 'dry_run', False, 'Do not actually generate Dockerfiles', short_name='n') + 'construct_dockerfiles', False, 'Do not build images', short_name='d') + +flags.DEFINE_boolean( + 'keep_temp_dockerfiles', + False, + 'Retain .temp.Dockerfiles created while building images.', + short_name='k') + +flags.DEFINE_boolean( + 'build_images', False, 'Do not build images', short_name='b') flags.DEFINE_string( - 'spec_file', - './spec.yml', - 'Path to a YAML specification file', - short_name='s') + 'run_tests_path', None, + ('Execute test scripts on generated Dockerfiles before pushing them. ' + 'Flag value must be a full path to the "tests" directory, which is usually' + ' $(realpath ./tests). A failed tests counts the same as a failed build.')) + +flags.DEFINE_boolean( + 'stop_on_failure', False, + ('Stop processing tags if any one build fails. If False or not specified, ' + 'failures are reported but do not affect the other images.')) + +flags.DEFINE_boolean( + 'dry_run', + False, + 'Do not build or deploy anything at all.', + short_name='n', +) + +flags.DEFINE_string( + 'exclude_tags_matching', + None, + ('Regular expression that skips processing on any tag it matches. Must ' + 'match entire string, e.g. ".*gpu.*" ignores all GPU tags.'), + short_name='x') flags.DEFINE_string( - 'output_dir', - './dockerfiles', ('Path to an output directory for Dockerfiles. ' - 'Will be created if it doesn\'t exist.'), + 'only_tags_matching', + None, + ('Regular expression that skips processing on any tag it does not match. ' + 'Must match entire string, e.g. ".*gpu.*" includes only GPU tags.'), + short_name='i') + +flags.DEFINE_string( + 'dockerfile_dir', + './dockerfiles', 'Path to an output directory for Dockerfiles.' + ' Will be created if it doesn\'t exist.' + ' Existing files in this directory will be deleted when new Dockerfiles' + ' are made.', short_name='o') flags.DEFINE_string( 'partial_dir', './partials', - 'Path to a directory containing foo.partial.Dockerfile partial files.', + 'Path to a directory containing foo.partial.Dockerfile partial files.' + ' can have subdirectories, e.g. "bar/baz.partial.Dockerfile".', short_name='p') -flags.DEFINE_boolean( - 'quiet_dry_run', - True, - 'Do not print contents of dry run Dockerfiles.', - short_name='q') +flags.DEFINE_multi_string( + 'release', [], + 'Set of releases to build and tag. Defaults to every release type.', + short_name='r') -flags.DEFINE_boolean( - 'validate', True, 'Validate generated Dockerfiles', short_name='c') +flags.DEFINE_multi_string( + 'arg', [], + ('Extra build arguments. These are used for expanding tag names if needed ' + '(e.g. --arg _TAG_PREFIX=foo) and for using as build arguments (unused ' + 'args will print a warning).'), + short_name='a') -# Schema to verify the contents of spec.yml with Cerberus. +flags.DEFINE_string( + 'spec_file', + './spec.yml', + 'Path to the YAML specification file', + short_name='s') + +# Schema to verify the contents of tag-spec.yml with Cerberus. # Must be converted to a dict from yaml to work. # Note: can add python references with e.g. # !!python/name:builtins.str @@ -76,79 +157,76 @@ SCHEMA_TEXT = """ header: type: string -partials: +slice_sets: type: dict keyschema: type: string valueschema: - type: dict - schema: - desc: - type: string - args: + type: list + schema: type: dict - keyschema: - type: string - valueschema: - anyof: - - type: [ boolean, number, string ] - - type: dict - schema: - default: - type: [ boolean, number, string ] - desc: - type: string - options: - type: list - schema: - type: string - -images: + schema: + add_to_name: + type: string + dockerfile_exclusive_name: + type: string + partials: + type: list + schema: + type: string + ispartial: true + test_runtime: + type: string + required: false + tests: + type: list + default: [] + schema: + type: string + args: + type: list + default: [] + schema: + type: string + isfullarg: true + +releases: + type: dict keyschema: type: string valueschema: type: dict schema: - desc: - type: string - arg-defaults: - type: list - schema: - anyof: - - type: dict - keyschema: - type: string - arg_in_use: true - valueschema: - type: string - - type: string - isimage: true - create-dockerfile: + is_dockerfiles: + type: boolean + required: false + default: false + upload_images: type: boolean - partials: + required: false + default: true + tag_specs: type: list + required: true schema: - anyof: - - type: dict - keyschema: - type: string - regex: image - valueschema: - type: string - isimage: true - - type: string - ispartial: true + type: string """ -class TfDockerValidator(cerberus.Validator): - """Custom Cerberus validator for TF dockerfile spec. +class TfDockerTagValidator(cerberus.Validator): + """Custom Cerberus validator for TF tag spec. Note: Each _validate_foo function's docstring must end with a segment describing its own validation schema, e.g. "The rule's arguments are...". If you add a new validator, you can copy/paste that section. """ + def __init__(self, *args, **kwargs): + # See http://docs.python-cerberus.org/en/stable/customize.html + if 'partials' in kwargs: + self.partials = kwargs['partials'] + super(cerberus.Validator, self).__init__(*args, **kwargs) + def _validate_ispartial(self, ispartial, field, value): """Validate that a partial references an existing partial spec. @@ -156,398 +234,423 @@ class TfDockerValidator(cerberus.Validator): ispartial: Value of the rule, a bool field: The field being validated value: The field's value - The rule's arguments are validated against this schema: {'type': 'boolean'} """ - if ispartial and value not in self.root_document.get('partials', dict()): - self._error(field, '{} is not an existing partial.'.format(value)) + if ispartial and value not in self.partials: + self._error(field, + '{} is not present in the partials directory.'.format(value)) - def _validate_isimage(self, isimage, field, value): - """Validate that an image references an existing partial spec. + def _validate_isfullarg(self, isfullarg, field, value): + """Validate that a string is either a FULL=arg or NOT. Args: - isimage: Value of the rule, a bool + isfullarg: Value of the rule, a bool field: The field being validated value: The field's value - - The rule's arguments are validated against this schema: - {'type': 'boolean'} - """ - if isimage and value not in self.root_document.get('images', dict()): - self._error(field, '{} is not an existing image.'.format(value)) - - def _validate_arg_in_use(self, arg_in_use, field, value): - """Validate that an arg references an existing partial spec's args. - - Args: - arg_in_use: Value of the rule, a bool - field: The field being validated - value: The field's value - The rule's arguments are validated against this schema: {'type': 'boolean'} """ - if arg_in_use: - for partial in self.root_document.get('partials', dict()).values(): - if value in partial.get('args', tuple()): - return + if isfullarg and '=' not in value: + self._error(field, '{} should be of the form ARG=VALUE.'.format(value)) + if not isfullarg and '=' in value: + self._error(field, '{} should be of the form ARG (no =).'.format(value)) - self._error(field, '{} is not an arg used in any partial.'.format(value)) +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, flush=True, **kwargs) -def build_partial_description(partial_spec): - """Create the documentation lines for a specific partial. - Generates something like this: +def aggregate_all_slice_combinations(spec, slice_set_names): + """Figure out all of the possible slice groupings for a tag spec.""" + slice_sets = copy.deepcopy(spec['slice_sets']) - # This is the partial's description, from spec.yml. - # --build-arg ARG_NAME=argdefault - # this is one of the args. - # --build-arg ANOTHER_ARG=(some|choices) - # another arg. + for name in slice_set_names: + for slice_set in slice_sets[name]: + slice_set['set_name'] = name - Args: - partial_spec: A dict representing one of the partials from spec.yml. Doesn't - include the name of the partial; is a dict like { desc: ..., args: ... }. + slices_grouped_but_not_keyed = [slice_sets[name] for name in slice_set_names] + all_slice_combos = list(itertools.product(*slices_grouped_but_not_keyed)) + return all_slice_combos - Returns: - A commented string describing this partial. - """ - # Start from linewrapped desc field - lines = [] - wrapper = textwrap.TextWrapper( - initial_indent='# ', subsequent_indent='# ', width=80) - description = wrapper.fill(partial_spec.get('desc', '( no comments )')) - lines.extend(['#', description]) - - # Document each arg - for arg, arg_data in partial_spec.get('args', dict()).items(): - # Wrap arg description with comment lines - desc = arg_data.get('desc', '( no description )') - desc = textwrap.fill( - desc, - initial_indent='# ', - subsequent_indent='# ', - width=80, - drop_whitespace=False) - - # Document (each|option|like|this) - if 'options' in arg_data: - arg_options = ' ({})'.format('|'.join(arg_data['options'])) - else: - arg_options = '' +def build_name_from_slices(format_string, slices, args, is_dockerfile=False): + """Build the tag name (cpu-devel...) from a list of slices.""" + name_formatter = copy.deepcopy(args) + name_formatter.update({s['set_name']: s['add_to_name'] for s in slices}) + name_formatter.update({ + s['set_name']: s['dockerfile_exclusive_name'] + for s in slices + if is_dockerfile and 'dockerfile_exclusive_name' in s + }) + name = format_string.format(**name_formatter) + return name - # Add usage sample - arg_use = '# --build-arg {}={}{}'.format(arg, - arg_data.get('default', '(unset)'), - arg_options) - lines.extend([arg_use, desc]) - return '\n'.join(lines) +def update_args_dict(args_dict, updater): + """Update a dict of arg values with more values from a list or dict.""" + if isinstance(updater, list): + for arg in updater: + key, sep, value = arg.partition('=') + if sep == '=': + args_dict[key] = value + if isinstance(updater, dict): + for key, value in updater.items(): + args_dict[key] = value + return args_dict -def construct_contents(partial_specs, image_spec): - """Assemble the dockerfile contents for an image spec. +def get_slice_sets_and_required_args(slice_sets, tag_spec): + """Extract used-slice-sets and required CLI arguments from a spec string. - It assembles a concrete list of partial references into a single, large - string. - Also expands argument defaults, so that the resulting Dockerfile doesn't have - to be configured with --build-arg=... every time. That is, any ARG directive - will be updated with a new default value. + For example, {FOO}{bar}{bat} finds FOO, bar, and bat. Assuming bar and bat + are both named slice sets, FOO must be specified on the command line. Args: - partial_specs: The dict from spec.yml["partials"]. - image_spec: One of the dict values from spec.yml["images"]. + slice_sets: Dict of named slice sets + tag_spec: The tag spec string, e.g. {_FOO}{blep} Returns: - A string containing a valid Dockerfile based on the partials listed in - image_spec. + (used_slice_sets, required_args), a tuple of lists """ - processed_partial_strings = [] - for partial_name in image_spec['partials']: - # Apply image arg-defaults to existing arg defaults - partial_spec = copy.deepcopy(partial_specs[partial_name]) - args = partial_spec.get('args', dict()) - for k_v in image_spec.get('arg-defaults', []): - arg, value = list(k_v.items())[0] - if arg in args: - args[arg]['default'] = value - - # Read partial file contents - filename = partial_spec.get('file', partial_name) - partial_path = os.path.join(FLAGS.partial_dir, - '{}.partial.Dockerfile'.format(filename)) - with open(partial_path, 'r') as f_partial: - partial_contents = f_partial.read() - - # Replace ARG FOO=BAR with ARG FOO=[new-default] - for arg, arg_data in args.items(): - if 'default' in arg_data and arg_data['default']: - default = '={}'.format(arg_data['default']) - else: - default = '' - partial_contents = re.sub(r'ARG {}.*'.format(arg), 'ARG {}{}'.format( - arg, default), partial_contents) - - # Store updated partial contents - processed_partial_strings.append(partial_contents) - - # Join everything together - return '\n'.join(processed_partial_strings) - - -def mkdir_p(path): - """Create a directory and its parents, even if it already exists.""" - try: - os.makedirs(path) - except OSError as e: - if e.errno != errno.EEXIST: - raise - - -def construct_documentation(header, partial_specs, image_spec): - """Assemble all of the documentation for a single dockerfile. - - Builds explanations of included partials and available build args. - - Args: - header: The string from spec.yml["header"]; will be commented and wrapped. - partial_specs: The dict from spec.yml["partials"]. - image_spec: The spec for the dockerfile being built. - - Returns: - A string containing a commented header that documents the contents of the - dockerfile. - - """ - # Comment and wrap header and image description - commented_header = '\n'.join( - [('# ' + l).rstrip() for l in header.splitlines()]) - commented_desc = '\n'.join( - ['# ' + l for l in image_spec.get('desc', '').splitlines()]) - partial_descriptions = [] - - # Build documentation for each partial in the image - for partial in image_spec['partials']: - # Copy partial data for default args unique to this image - partial_spec = copy.deepcopy(partial_specs[partial]) - args = partial_spec.get('args', dict()) - - # Overwrite any existing arg defaults - for k_v in image_spec.get('arg-defaults', []): - arg, value = list(k_v.items())[0] - if arg in args: - args[arg]['default'] = value - - # Build the description from new args - partial_description = build_partial_description(partial_spec) - partial_descriptions.append(partial_description) - - contents = [commented_header, '#', commented_desc] + partial_descriptions - return '\n'.join(contents) + '\n' - - -def normalize_partial_args(partial_specs): - """Normalize the shorthand form of a partial's args specification. - - Turns this: - - partial: - args: - SOME_ARG: arg_value - - Into this: - - partial: - args: - SOME_ARG: - default: arg_value + required_args = [] + used_slice_sets = [] + + extract_bracketed_words = re.compile(r'\{([^}]+)\}') + possible_args_or_slice_set_names = extract_bracketed_words.findall(tag_spec) + for name in possible_args_or_slice_set_names: + if name in slice_sets: + used_slice_sets.append(name) + else: + required_args.append(name) - Args: - partial_specs: The dict from spec.yml["partials"]. This dict is modified in - place. + return (used_slice_sets, required_args) - Returns: - The modified contents of partial_specs. - """ - for _, partial in partial_specs.items(): - args = partial.get('args', dict()) - for arg, value in args.items(): - if not isinstance(value, dict): - new_value = {'default': value} - args[arg] = new_value +def gather_tag_args(slices, cli_input_args, required_args): + """Build a dictionary of all the CLI and slice-specified args for a tag.""" + args = dict() - return partial_specs + for s in slices: + args = update_args_dict(args, s['args']) + args = update_args_dict(args, cli_input_args) + for arg in required_args: + if arg not in args: + eprint(('> Error: {} is not a valid slice_set, and also isn\'t an arg ' + 'provided on the command line. If it is an arg, please specify ' + 'it with --arg. If not, check the slice_sets list.'.format(arg))) + exit(1) -def flatten_args_references(image_specs): - """Resolve all default-args in each image spec to a concrete dict. + return args - Turns this: - example-image: - arg-defaults: - - MY_ARG: ARG_VALUE +def gather_slice_list_items(slices, key): + """For a list of slices, get the flattened list of all of a certain key.""" + return list(itertools.chain(*[s[key] for s in slices if key in s])) - another-example: - arg-defaults: - - ANOTHER_ARG: ANOTHER_VALUE - - example_image - Into this: +def find_first_slice_value(slices, key): + """For a list of slices, get the first value for a certain key.""" + for s in slices: + if key in s: + return s[key] - example-image: - arg-defaults: - - MY_ARG: ARG_VALUE - another-example: - arg-defaults: - - ANOTHER_ARG: ANOTHER_VALUE - - MY_ARG: ARG_VALUE +def assemble_tags(spec, cli_args, enabled_releases, all_partials): + """Gather all the tags based on our spec. Args: - image_specs: A dict of image_spec dicts; should be the contents of the - "images" key in the global spec.yaml. This dict is modified in place and - then returned. + spec: Nested dict containing full Tag spec + cli_args: List of ARG=foo arguments to pass along to Docker build + enabled_releases: List of releases to parse. Empty list = all + all_partials: Dict of every partial, for reference Returns: - The modified contents of image_specs. + Dict of tags and how to build them """ - for _, image_spec in image_specs.items(): - too_deep = 0 - while str in map(type, image_spec.get('arg-defaults', [])) and too_deep < 5: - new_args = [] - for arg in image_spec['arg-defaults']: - if isinstance(arg, str): - new_args.extend(image_specs[arg]['arg-defaults']) - else: - new_args.append(arg) + tag_data = collections.defaultdict(list) - image_spec['arg-defaults'] = new_args - too_deep += 1 + for name, release in spec['releases'].items(): + for tag_spec in release['tag_specs']: + if enabled_releases and name not in enabled_releases: + eprint('> Skipping release {}'.format(name)) + continue - return image_specs + used_slice_sets, required_cli_args = get_slice_sets_and_required_args( + spec['slice_sets'], tag_spec) + slice_combos = aggregate_all_slice_combinations(spec, used_slice_sets) + for slices in slice_combos: -def flatten_partial_references(image_specs): - """Resolve all partial references in each image spec to a concrete list. + tag_args = gather_tag_args(slices, cli_args, required_cli_args) + tag_name = build_name_from_slices(tag_spec, slices, tag_args, + release['is_dockerfiles']) + used_partials = gather_slice_list_items(slices, 'partials') + used_tests = gather_slice_list_items(slices, 'tests') + test_runtime = find_first_slice_value(slices, 'test_runtime') + dockerfile_contents = merge_partials(spec['header'], used_partials, + all_partials) - Turns this: + tag_data[tag_name].append({ + 'release': name, + 'tag_spec': tag_spec, + 'is_dockerfiles': release['is_dockerfiles'], + 'upload_images': release['upload_images'], + 'cli_args': tag_args, + 'partials': used_partials, + 'tests': used_tests, + 'test_runtime': test_runtime, + 'dockerfile_contents': dockerfile_contents, + }) - example-image: - partials: - - foo + return tag_data - another-example: - partials: - - bar - - image: example-image - - bat - Into this: +def merge_partials(header, used_partials, all_partials): + """Merge all partial contents with their header.""" + used_partials = list(used_partials) + return '\n'.join([header] + [all_partials[u] for u in used_partials]) - example-image: - partials: - - foo - another-example: - partials: - - bar - - foo - - bat - Args: - image_specs: A dict of image_spec dicts; should be the contents of the - "images" key in the global spec.yaml. This dict is modified in place and - then returned. - - Returns: - The modified contents of image_specs. - """ - for _, image_spec in image_specs.items(): - too_deep = 0 - while dict in map(type, image_spec['partials']) and too_deep < 5: - new_partials = [] - for partial in image_spec['partials']: - if isinstance(partial, str): - new_partials.append(partial) - else: - new_partials.extend(image_specs[partial['image']]['partials']) +def upload_in_background(hub_repository, dock, image, tag): + """Upload a docker image (to be used by multiprocessing).""" + image.tag(hub_repository, tag=tag) + for line in list(dock.images.push(hub_repository, tag=tag, stream=True)): + print(line) - image_spec['partials'] = new_partials - too_deep += 1 - return image_specs +def mkdir_p(path): + """Create a directory and its parents, even if it already exists.""" + try: + os.makedirs(path) + except OSError as e: + if e.errno != errno.EEXIST: + raise -def construct_dockerfiles(tf_spec): - """Generate a mapping of {"cpu": , ...}. +def gather_existing_partials(partial_path): + """Find and read all available partials. Args: - tf_spec: The full spec.yml loaded as a python object. + partial_path (string): read partials from this directory. Returns: - A string:string dict of short names ("cpu-devel") to Dockerfile contents. + Dict[string, string] of partial short names (like "ubuntu/python" or + "bazel") to the full contents of that partial. """ - names_to_contents = dict() - image_specs = tf_spec['images'] - image_specs = flatten_partial_references(image_specs) - image_specs = flatten_args_references(image_specs) - partial_specs = tf_spec['partials'] - partial_specs = normalize_partial_args(partial_specs) - - for name, image_spec in image_specs.items(): - if not image_spec.get('create-dockerfile', True): - continue - documentation = construct_documentation(tf_spec['header'], partial_specs, - image_spec) - contents = construct_contents(partial_specs, image_spec) - names_to_contents[name] = '\n'.join([documentation, contents]) - - return names_to_contents + partials = dict() + for path, _, files in os.walk(partial_path): + for name in files: + fullpath = os.path.join(path, name) + if '.partial.Dockerfile' not in fullpath: + eprint(('> Probably not a problem: skipping {}, which is not a ' + 'partial.').format(fullpath)) + continue + # partial_dir/foo/bar.partial.Dockerfile -> foo/bar + simple_name = fullpath[len(partial_path) + 1:-len('.partial.dockerfile')] + with open(fullpath, 'r') as f: + partial_contents = f.read() + partials[simple_name] = partial_contents + return partials def main(argv): if len(argv) > 1: - raise app.UsageError('Unexpected command line args found: {}'.format(argv)) + raise app.UsageError('Too many command-line arguments.') + # Read the full spec file, used for everything with open(FLAGS.spec_file, 'r') as spec_file: - tf_spec = yaml.load(spec_file) + tag_spec = yaml.load(spec_file) + + # Get existing partial contents + partials = gather_existing_partials(FLAGS.partial_dir) # Abort if spec.yaml is invalid - if FLAGS.validate: - schema = yaml.load(SCHEMA_TEXT) - v = TfDockerValidator(schema) - if not v.validate(tf_spec): - print('>> ERROR: {} is an invalid spec! The errors are:'.format( - FLAGS.spec_file)) - print(yaml.dump(v.errors, indent=2)) + schema = yaml.load(SCHEMA_TEXT) + v = TfDockerTagValidator(schema, partials=partials) + if not v.validate(tag_spec): + eprint('> Error: {} is an invalid spec! The errors are:'.format( + FLAGS.spec_file)) + eprint(yaml.dump(v.errors, indent=2)) + exit(1) + tag_spec = v.normalized(tag_spec) + + # Assemble tags and images used to build them + all_tags = assemble_tags(tag_spec, FLAGS.arg, FLAGS.release, partials) + + # Empty Dockerfile directory if building new Dockerfiles + if FLAGS.construct_dockerfiles: + eprint('> Emptying Dockerfile dir "{}"'.format(FLAGS.dockerfile_dir)) + shutil.rmtree(FLAGS.dockerfile_dir, ignore_errors=True) + mkdir_p(FLAGS.dockerfile_dir) + + # Set up Docker helper + dock = docker.from_env() + + # Login to Docker if uploading images + if FLAGS.upload_to_hub: + if not FLAGS.hub_username: + eprint('> Error: please set --hub_username when uploading to Dockerhub.') exit(1) - else: - print('>> WARNING: Not validating {}'.format(FLAGS.spec_file)) - - # Generate mapping of { "cpu-devel": "", ... } - names_to_contents = construct_dockerfiles(tf_spec) - - # Write each completed Dockerfile - if not FLAGS.dry_run: - print('>> Emptying destination dir "{}"'.format(FLAGS.output_dir)) - shutil.rmtree(FLAGS.output_dir, ignore_errors=True) - mkdir_p(FLAGS.output_dir) - else: - print('>> Skipping creation of {} (dry run)'.format(FLAGS.output_dir)) - for name, contents in names_to_contents.items(): - path = os.path.join(FLAGS.output_dir, name + '.Dockerfile') - if FLAGS.dry_run: - print('>> Skipping writing contents of {} (dry run)'.format(path)) - print(contents) - else: - mkdir_p(FLAGS.output_dir) - print('>> Writing {}'.format(path)) - with open(path, 'w') as f: - f.write(contents) + if not FLAGS.hub_repository: + eprint( + '> Error: please set --hub_repository when uploading to Dockerhub.') + exit(1) + if not FLAGS.hub_password: + eprint('> Error: please set --hub_password when uploading to Dockerhub.') + exit(1) + dock.login( + username=FLAGS.hub_username, + password=FLAGS.hub_password, + ) + + # Each tag has a name ('tag') and a definition consisting of the contents + # of its Dockerfile, its build arg list, etc. + failed_tags = [] + for tag, tag_defs in all_tags.items(): + for tag_def in tag_defs: + eprint('> Working on {}'.format(tag)) + + if FLAGS.exclude_tags_matching and re.match(FLAGS.exclude_tags_matching, + tag): + eprint('>> Excluded due to match against "{}".'.format( + FLAGS.exclude_tags_matching)) + continue + + if FLAGS.only_tags_matching and not re.match(FLAGS.only_tags_matching, + tag): + eprint('>> Excluded due to failure to match against "{}".'.format( + FLAGS.only_tags_matching)) + continue + + # Write releases marked "is_dockerfiles" into the Dockerfile directory + if FLAGS.construct_dockerfiles: + path = os.path.join(FLAGS.dockerfile_dir, tag + '.Dockerfile') + if tag_def['is_dockerfiles']: + eprint('>> Writing {}...'.format(path)) + if not FLAGS.dry_run: + with open(path, 'w') as f: + f.write(tag_def['dockerfile_contents']) + + # Don't build any images for dockerfile-only releases + if not FLAGS.build_images: + continue + + # Generate a temporary Dockerfile to use to build, since docker-py + # needs a filepath relative to the build context (i.e. the current + # directory) + dockerfile = os.path.join(FLAGS.dockerfile_dir, tag + '.temp.Dockerfile') + if not FLAGS.dry_run: + with open(dockerfile, 'w') as f: + f.write(tag_def['dockerfile_contents']) + eprint('>> (Temporary) writing {}...'.format(dockerfile)) + + repo_tag = '{}:{}'.format(FLAGS.repository, tag) + eprint('>> Building {} using build args:'.format(repo_tag)) + for arg, value in tag_def['cli_args'].items(): + eprint('>>> {}={}'.format(arg, value)) + + # Note that we are NOT using cache_from, which appears to limit + # available cache layers to those from explicitly specified layers. Many + # of our layers are similar between local builds, so we want to use the + # implied local build cache. + tag_failed = False + image, logs = None, [] + if not FLAGS.dry_run: + try: + image, logs = dock.images.build( + timeout=FLAGS.hub_timeout, + path='.', + dockerfile=dockerfile, + buildargs=tag_def['cli_args'], + tag=repo_tag) + + # Print logs after finishing + log_lines = [l.get('stream', '') for l in logs] + eprint(''.join(log_lines)) + + # Run tests if requested, and dump output + # Could be improved by backgrounding, but would need better + # multiprocessing support to track failures properly. + if FLAGS.run_tests_path: + if not tag_def['tests']: + eprint('>>> No tests to run.') + for test in tag_def['tests']: + eprint('>> Testing {}...'.format(test)) + container, = dock.containers.run( + image, + '/tests/' + test, + working_dir='/', + log_config={'type': 'journald'}, + detach=True, + stderr=True, + stdout=True, + volumes={FLAGS.run_tests_path: + {'bind': '/tests', 'mode': 'ro'}}, + runtime=tag_def['test_runtime']), + ret = container.wait() + code = ret['StatusCode'] + out = container.logs(stdout=True, stderr=False) + err = container.logs(stdout=False, stderr=True) + container.remove() + if out: + eprint('>>> Output stdout:') + eprint(out.decode('utf-8')) + else: + eprint('>>> No test standard out.') + if err: + eprint('>>> Output stderr:') + eprint(out.decode('utf-8')) + else: + eprint('>>> No test standard err.') + if code != 0: + eprint('>> {} failed tests with status: "{}"'.format( + repo_tag, code)) + failed_tags.append(tag) + tag_failed = True + if FLAGS.stop_on_failure: + eprint('>> ABORTING due to --stop_on_failure!') + exit(1) + else: + eprint('>> Tests look good!') + + except docker.errors.BuildError as e: + eprint('>> {} failed to build with message: "{}"'.format( + repo_tag, e.msg)) + eprint('>> Build logs follow:') + log_lines = [l.get('stream', '') for l in e.build_log] + eprint(''.join(log_lines)) + failed_tags.append(tag) + tag_failed = True + if FLAGS.stop_on_failure: + eprint('>> ABORTING due to --stop_on_failure!') + exit(1) + + # Clean temporary dockerfiles if they were created earlier + if not FLAGS.keep_temp_dockerfiles: + os.remove(dockerfile) + + # Upload new images to DockerHub as long as they built + passed tests + if FLAGS.upload_to_hub: + if not tag_def['upload_images']: + continue + if tag_failed: + continue + + eprint('>> Uploading to {}:{}'.format(FLAGS.hub_repository, tag)) + if not FLAGS.dry_run: + p = multiprocessing.Process( + target=upload_in_background, + args=(FLAGS.hub_repository, dock, image, tag)) + p.start() + + if failed_tags: + eprint( + '> Some tags failed to build or failed testing, check scrollback for ' + 'errors: {}'.format( + ','.join(failed_tags))) + exit(1) if __name__ == '__main__': diff --git a/tensorflow/tools/dockerfiles/dockerfiles/cpu-devel-jupyter.Dockerfile b/tensorflow/tools/dockerfiles/dockerfiles/cpu-devel-jupyter.Dockerfile index dab7178db3..14ddf08199 100644 --- a/tensorflow/tools/dockerfiles/dockerfiles/cpu-devel-jupyter.Dockerfile +++ b/tensorflow/tools/dockerfiles/dockerfiles/cpu-devel-jupyter.Dockerfile @@ -16,27 +16,12 @@ # THIS IS A GENERATED DOCKERFILE. # # This file was assembled from multiple pieces, whose use is documented -# below. Please refer to the the TensorFlow dockerfiles documentation for -# more information. Build args are documented as their default value. -# -# Ubuntu-based, CPU-only environment for developing changes for TensorFlow, with Jupyter included. -# -# Start from Ubuntu, with TF development packages (no GPU support) -# --build-arg UBUNTU_VERSION=16.04 -# ( no description ) -# -# Python is required for TensorFlow and other libraries. -# --build-arg USE_PYTHON_3_NOT_2=True -# Install python 3 over Python 2 -# -# Install the latest version of Bazel and Python development tools. -# -# Configure TensorFlow's shell prompt and login tools. -# -# Launch Jupyter on execution instead of a bash prompt. +# throughout. Please refer to the TensorFlow dockerfiles documentation +# for more information. ARG UBUNTU_VERSION=16.04 -FROM ubuntu:${UBUNTU_VERSION} + +FROM ubuntu:${UBUNTU_VERSION} AS base RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ @@ -48,7 +33,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpng12-dev \ libzmq3-dev \ pkg-config \ - python-dev \ rsync \ software-properties-common \ unzip \ @@ -59,8 +43,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* + +ENV CI_BUILD_PYTHON python + -ARG USE_PYTHON_3_NOT_2=True +ARG USE_PYTHON_3_NOT_2 ARG _PY_SUFFIX=${USE_PYTHON_3_NOT_2:+3} ARG PYTHON=python${_PY_SUFFIX} ARG PIP=pip${_PY_SUFFIX} @@ -72,10 +59,13 @@ RUN apt-get update && apt-get install -y \ ${PYTHON} \ ${PYTHON}-pip -RUN ${PIP} install --upgrade \ +RUN ${PIP} --no-cache-dir install --upgrade \ pip \ setuptools +# Some TF tools expect a "python" binary +RUN ln -s $(which ${PYTHON}) /usr/local/bin/python + RUN apt-get update && apt-get install -y \ build-essential \ curl \ @@ -84,6 +74,20 @@ RUN apt-get update && apt-get install -y \ ${PYTHON}-dev \ swig +RUN ${PIP} --no-cache-dir install \ + Pillow \ + h5py \ + keras_applications \ + keras_preprocessing \ + matplotlib \ + mock \ + numpy \ + scipy \ + sklearn \ + pandas \ + && test "${USE_PYTHON_3_NOT_2}" -eq 1 && true || ${PIP} --no-cache-dir install \ + enum34 + # Install bazel RUN echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list && \ curl https://bazel.build/bazel-release.pub.gpg | apt-key add - && \ @@ -93,11 +97,19 @@ RUN echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8 COPY bashrc /etc/bash.bashrc RUN chmod a+rwx /etc/bash.bashrc -RUN ${PIP} install jupyter +RUN ${PIP} install jupyter matplotlib -RUN mkdir /notebooks && chmod a+rwx /notebooks +RUN mkdir -p /tf/tensorflow-tutorials && chmod -R a+rwx /tf/ RUN mkdir /.local && chmod a+rwx /.local -WORKDIR /notebooks +RUN apt-get install -y --no-install-recommends wget +WORKDIR /tf/tensorflow-tutorials +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_classification.ipynb +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_text_classification.ipynb +COPY readme-for-jupyter.md README.md +RUN apt-get autoremove -y && apt-get remove -y wget +WORKDIR /tf EXPOSE 8888 -CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/notebooks --ip 0.0.0.0 --no-browser --allow-root"] +RUN ${PYTHON} -m ipykernel.kernelspec + +CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/tf --ip 0.0.0.0 --no-browser --allow-root"] diff --git a/tensorflow/tools/dockerfiles/dockerfiles/cpu-devel.Dockerfile b/tensorflow/tools/dockerfiles/dockerfiles/cpu-devel.Dockerfile index 68566ccc8a..16973b47af 100644 --- a/tensorflow/tools/dockerfiles/dockerfiles/cpu-devel.Dockerfile +++ b/tensorflow/tools/dockerfiles/dockerfiles/cpu-devel.Dockerfile @@ -16,25 +16,12 @@ # THIS IS A GENERATED DOCKERFILE. # # This file was assembled from multiple pieces, whose use is documented -# below. Please refer to the the TensorFlow dockerfiles documentation for -# more information. Build args are documented as their default value. -# -# Ubuntu-based, CPU-only environment for developing changes for TensorFlow. -# -# Start from Ubuntu, with TF development packages (no GPU support) -# --build-arg UBUNTU_VERSION=16.04 -# ( no description ) -# -# Python is required for TensorFlow and other libraries. -# --build-arg USE_PYTHON_3_NOT_2=True -# Install python 3 over Python 2 -# -# Install the latest version of Bazel and Python development tools. -# -# Configure TensorFlow's shell prompt and login tools. +# throughout. Please refer to the TensorFlow dockerfiles documentation +# for more information. ARG UBUNTU_VERSION=16.04 -FROM ubuntu:${UBUNTU_VERSION} + +FROM ubuntu:${UBUNTU_VERSION} AS base RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ @@ -46,7 +33,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpng12-dev \ libzmq3-dev \ pkg-config \ - python-dev \ rsync \ software-properties-common \ unzip \ @@ -57,8 +43,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* + +ENV CI_BUILD_PYTHON python + -ARG USE_PYTHON_3_NOT_2=True +ARG USE_PYTHON_3_NOT_2 ARG _PY_SUFFIX=${USE_PYTHON_3_NOT_2:+3} ARG PYTHON=python${_PY_SUFFIX} ARG PIP=pip${_PY_SUFFIX} @@ -70,10 +59,13 @@ RUN apt-get update && apt-get install -y \ ${PYTHON} \ ${PYTHON}-pip -RUN ${PIP} install --upgrade \ +RUN ${PIP} --no-cache-dir install --upgrade \ pip \ setuptools +# Some TF tools expect a "python" binary +RUN ln -s $(which ${PYTHON}) /usr/local/bin/python + RUN apt-get update && apt-get install -y \ build-essential \ curl \ @@ -82,6 +74,20 @@ RUN apt-get update && apt-get install -y \ ${PYTHON}-dev \ swig +RUN ${PIP} --no-cache-dir install \ + Pillow \ + h5py \ + keras_applications \ + keras_preprocessing \ + matplotlib \ + mock \ + numpy \ + scipy \ + sklearn \ + pandas \ + && test "${USE_PYTHON_3_NOT_2}" -eq 1 && true || ${PIP} --no-cache-dir install \ + enum34 + # Install bazel RUN echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list && \ curl https://bazel.build/bazel-release.pub.gpg | apt-key add - && \ diff --git a/tensorflow/tools/dockerfiles/dockerfiles/cpu-jupyter.Dockerfile b/tensorflow/tools/dockerfiles/dockerfiles/cpu-jupyter.Dockerfile index f889ed6f91..d8fabadec2 100644 --- a/tensorflow/tools/dockerfiles/dockerfiles/cpu-jupyter.Dockerfile +++ b/tensorflow/tools/dockerfiles/dockerfiles/cpu-jupyter.Dockerfile @@ -16,31 +16,14 @@ # THIS IS A GENERATED DOCKERFILE. # # This file was assembled from multiple pieces, whose use is documented -# below. Please refer to the the TensorFlow dockerfiles documentation for -# more information. Build args are documented as their default value. -# -# Ubuntu-based, CPU-only environment for using TensorFlow, with Jupyter included. -# -# Start from Ubuntu (no GPU support) -# --build-arg UBUNTU_VERSION=16.04 -# ( no description ) -# -# Python is required for TensorFlow and other libraries. -# --build-arg USE_PYTHON_3_NOT_2=True -# Install python 3 over Python 2 -# -# Install the TensorFlow Python package. -# --build-arg TF_PACKAGE=tensorflow (tensorflow|tensorflow-gpu|tf-nightly|tf-nightly-gpu) -# The specific TensorFlow Python package to install -# -# Configure TensorFlow's shell prompt and login tools. -# -# Launch Jupyter on execution instead of a bash prompt. +# throughout. Please refer to the TensorFlow dockerfiles documentation +# for more information. ARG UBUNTU_VERSION=16.04 -FROM ubuntu:${UBUNTU_VERSION} -ARG USE_PYTHON_3_NOT_2=True +FROM ubuntu:${UBUNTU_VERSION} as base + +ARG USE_PYTHON_3_NOT_2 ARG _PY_SUFFIX=${USE_PYTHON_3_NOT_2:+3} ARG PYTHON=python${_PY_SUFFIX} ARG PIP=pip${_PY_SUFFIX} @@ -52,21 +35,37 @@ RUN apt-get update && apt-get install -y \ ${PYTHON} \ ${PYTHON}-pip -RUN ${PIP} install --upgrade \ +RUN ${PIP} --no-cache-dir install --upgrade \ pip \ setuptools +# Some TF tools expect a "python" binary +RUN ln -s $(which ${PYTHON}) /usr/local/bin/python + +# Options: +# tensorflow +# tensorflow-gpu +# tf-nightly +# tf-nightly-gpu ARG TF_PACKAGE=tensorflow RUN ${PIP} install ${TF_PACKAGE} COPY bashrc /etc/bash.bashrc RUN chmod a+rwx /etc/bash.bashrc -RUN ${PIP} install jupyter +RUN ${PIP} install jupyter matplotlib -RUN mkdir /notebooks && chmod a+rwx /notebooks +RUN mkdir -p /tf/tensorflow-tutorials && chmod -R a+rwx /tf/ RUN mkdir /.local && chmod a+rwx /.local -WORKDIR /notebooks +RUN apt-get install -y --no-install-recommends wget +WORKDIR /tf/tensorflow-tutorials +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_classification.ipynb +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_text_classification.ipynb +COPY readme-for-jupyter.md README.md +RUN apt-get autoremove -y && apt-get remove -y wget +WORKDIR /tf EXPOSE 8888 -CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/notebooks --ip 0.0.0.0 --no-browser --allow-root"] +RUN ${PYTHON} -m ipykernel.kernelspec + +CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/tf --ip 0.0.0.0 --no-browser --allow-root"] diff --git a/tensorflow/tools/dockerfiles/dockerfiles/cpu.Dockerfile b/tensorflow/tools/dockerfiles/dockerfiles/cpu.Dockerfile index 182a534bed..857b5e2047 100644 --- a/tensorflow/tools/dockerfiles/dockerfiles/cpu.Dockerfile +++ b/tensorflow/tools/dockerfiles/dockerfiles/cpu.Dockerfile @@ -16,29 +16,14 @@ # THIS IS A GENERATED DOCKERFILE. # # This file was assembled from multiple pieces, whose use is documented -# below. Please refer to the the TensorFlow dockerfiles documentation for -# more information. Build args are documented as their default value. -# -# Ubuntu-based, CPU-only environment for using TensorFlow -# -# Start from Ubuntu (no GPU support) -# --build-arg UBUNTU_VERSION=16.04 -# ( no description ) -# -# Python is required for TensorFlow and other libraries. -# --build-arg USE_PYTHON_3_NOT_2=True -# Install python 3 over Python 2 -# -# Install the TensorFlow Python package. -# --build-arg TF_PACKAGE=tensorflow (tensorflow|tensorflow-gpu|tf-nightly|tf-nightly-gpu) -# The specific TensorFlow Python package to install -# -# Configure TensorFlow's shell prompt and login tools. +# throughout. Please refer to the TensorFlow dockerfiles documentation +# for more information. ARG UBUNTU_VERSION=16.04 -FROM ubuntu:${UBUNTU_VERSION} -ARG USE_PYTHON_3_NOT_2=True +FROM ubuntu:${UBUNTU_VERSION} as base + +ARG USE_PYTHON_3_NOT_2 ARG _PY_SUFFIX=${USE_PYTHON_3_NOT_2:+3} ARG PYTHON=python${_PY_SUFFIX} ARG PIP=pip${_PY_SUFFIX} @@ -50,10 +35,18 @@ RUN apt-get update && apt-get install -y \ ${PYTHON} \ ${PYTHON}-pip -RUN ${PIP} install --upgrade \ +RUN ${PIP} --no-cache-dir install --upgrade \ pip \ setuptools +# Some TF tools expect a "python" binary +RUN ln -s $(which ${PYTHON}) /usr/local/bin/python + +# Options: +# tensorflow +# tensorflow-gpu +# tf-nightly +# tf-nightly-gpu ARG TF_PACKAGE=tensorflow RUN ${PIP} install ${TF_PACKAGE} diff --git a/tensorflow/tools/dockerfiles/dockerfiles/nvidia-devel-jupyter.Dockerfile b/tensorflow/tools/dockerfiles/dockerfiles/gpu-devel-jupyter.Dockerfile similarity index 66% rename from tensorflow/tools/dockerfiles/dockerfiles/nvidia-devel-jupyter.Dockerfile rename to tensorflow/tools/dockerfiles/dockerfiles/gpu-devel-jupyter.Dockerfile index 17faa84a68..9ecaec38c2 100644 --- a/tensorflow/tools/dockerfiles/dockerfiles/nvidia-devel-jupyter.Dockerfile +++ b/tensorflow/tools/dockerfiles/dockerfiles/gpu-devel-jupyter.Dockerfile @@ -16,28 +16,12 @@ # THIS IS A GENERATED DOCKERFILE. # # This file was assembled from multiple pieces, whose use is documented -# below. Please refer to the the TensorFlow dockerfiles documentation for -# more information. Build args are documented as their default value. -# -# Ubuntu-based, Nvidia-GPU-enabled environment for developing changes for TensorFlow, with Jupyter included. -# -# Start from Nvidia's Ubuntu base image with CUDA and CuDNN, with TF development -# packages. -# --build-arg UBUNTU_VERSION=16.04 -# ( no description ) -# -# Python is required for TensorFlow and other libraries. -# --build-arg USE_PYTHON_3_NOT_2=True -# Install python 3 over Python 2 -# -# Install the latest version of Bazel and Python development tools. -# -# Configure TensorFlow's shell prompt and login tools. -# -# Launch Jupyter on execution instead of a bash prompt. +# throughout. Please refer to the TensorFlow dockerfiles documentation +# for more information. ARG UBUNTU_VERSION=16.04 -FROM nvidia/cuda:9.0-base-ubuntu${UBUNTU_VERSION} + +FROM nvidia/cuda:9.0-base-ubuntu${UBUNTU_VERSION} as base RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ @@ -60,6 +44,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpng12-dev \ libzmq3-dev \ pkg-config \ + python-dev \ rsync \ software-properties-common \ unzip \ @@ -82,11 +67,19 @@ RUN mkdir /usr/local/cuda-9.0/lib && \ ln -s /usr/lib/x86_64-linux-gnu/libnccl.so.2 /usr/local/cuda/lib/libnccl.so.2 && \ ln -s /usr/include/nccl.h /usr/local/cuda/include/nccl.h -# TODO(tobyboyd): Remove after license is excluded from BUILD file. -RUN gunzip /usr/share/doc/libnccl2/NCCL-SLA.txt.gz && \ - cp /usr/share/doc/libnccl2/NCCL-SLA.txt /usr/local/cuda/ +# Configure the build for our CUDA configuration. +ENV CI_BUILD_PYTHON python +ENV LD_LIBRARY_PATH /usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH +ENV TF_NEED_CUDA 1 +ENV TF_NEED_TENSORRT 1 +ENV TF_CUDA_COMPUTE_CAPABILITIES=3.5,5.2,6.0,6.1,7.0 +ENV TF_CUDA_VERSION=9.0 +ENV TF_CUDNN_VERSION=7 + +# NCCL 2.x +ENV TF_NCCL_VERSION=2 -ARG USE_PYTHON_3_NOT_2=True +ARG USE_PYTHON_3_NOT_2 ARG _PY_SUFFIX=${USE_PYTHON_3_NOT_2:+3} ARG PYTHON=python${_PY_SUFFIX} ARG PIP=pip${_PY_SUFFIX} @@ -98,10 +91,13 @@ RUN apt-get update && apt-get install -y \ ${PYTHON} \ ${PYTHON}-pip -RUN ${PIP} install --upgrade \ +RUN ${PIP} --no-cache-dir install --upgrade \ pip \ setuptools +# Some TF tools expect a "python" binary +RUN ln -s $(which ${PYTHON}) /usr/local/bin/python + RUN apt-get update && apt-get install -y \ build-essential \ curl \ @@ -110,6 +106,20 @@ RUN apt-get update && apt-get install -y \ ${PYTHON}-dev \ swig +RUN ${PIP} --no-cache-dir install \ + Pillow \ + h5py \ + keras_applications \ + keras_preprocessing \ + matplotlib \ + mock \ + numpy \ + scipy \ + sklearn \ + pandas \ + && test "${USE_PYTHON_3_NOT_2}" -eq 1 && true || ${PIP} --no-cache-dir install \ + enum34 + # Install bazel RUN echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list && \ curl https://bazel.build/bazel-release.pub.gpg | apt-key add - && \ @@ -119,11 +129,19 @@ RUN echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8 COPY bashrc /etc/bash.bashrc RUN chmod a+rwx /etc/bash.bashrc -RUN ${PIP} install jupyter +RUN ${PIP} install jupyter matplotlib -RUN mkdir /notebooks && chmod a+rwx /notebooks +RUN mkdir -p /tf/tensorflow-tutorials && chmod -R a+rwx /tf/ RUN mkdir /.local && chmod a+rwx /.local -WORKDIR /notebooks +RUN apt-get install -y --no-install-recommends wget +WORKDIR /tf/tensorflow-tutorials +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_classification.ipynb +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_text_classification.ipynb +COPY readme-for-jupyter.md README.md +RUN apt-get autoremove -y && apt-get remove -y wget +WORKDIR /tf EXPOSE 8888 -CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/notebooks --ip 0.0.0.0 --no-browser --allow-root"] +RUN ${PYTHON} -m ipykernel.kernelspec + +CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/tf --ip 0.0.0.0 --no-browser --allow-root"] diff --git a/tensorflow/tools/dockerfiles/dockerfiles/nvidia-devel.Dockerfile b/tensorflow/tools/dockerfiles/dockerfiles/gpu-devel.Dockerfile similarity index 76% rename from tensorflow/tools/dockerfiles/dockerfiles/nvidia-devel.Dockerfile rename to tensorflow/tools/dockerfiles/dockerfiles/gpu-devel.Dockerfile index a3ba02a684..c79bc3cf4c 100644 --- a/tensorflow/tools/dockerfiles/dockerfiles/nvidia-devel.Dockerfile +++ b/tensorflow/tools/dockerfiles/dockerfiles/gpu-devel.Dockerfile @@ -16,26 +16,12 @@ # THIS IS A GENERATED DOCKERFILE. # # This file was assembled from multiple pieces, whose use is documented -# below. Please refer to the the TensorFlow dockerfiles documentation for -# more information. Build args are documented as their default value. -# -# Ubuntu-based, Nvidia-GPU-enabled environment for developing changes for TensorFlow. -# -# Start from Nvidia's Ubuntu base image with CUDA and CuDNN, with TF development -# packages. -# --build-arg UBUNTU_VERSION=16.04 -# ( no description ) -# -# Python is required for TensorFlow and other libraries. -# --build-arg USE_PYTHON_3_NOT_2=True -# Install python 3 over Python 2 -# -# Install the latest version of Bazel and Python development tools. -# -# Configure TensorFlow's shell prompt and login tools. +# throughout. Please refer to the TensorFlow dockerfiles documentation +# for more information. ARG UBUNTU_VERSION=16.04 -FROM nvidia/cuda:9.0-base-ubuntu${UBUNTU_VERSION} + +FROM nvidia/cuda:9.0-base-ubuntu${UBUNTU_VERSION} as base RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ @@ -58,6 +44,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpng12-dev \ libzmq3-dev \ pkg-config \ + python-dev \ rsync \ software-properties-common \ unzip \ @@ -80,11 +67,19 @@ RUN mkdir /usr/local/cuda-9.0/lib && \ ln -s /usr/lib/x86_64-linux-gnu/libnccl.so.2 /usr/local/cuda/lib/libnccl.so.2 && \ ln -s /usr/include/nccl.h /usr/local/cuda/include/nccl.h -# TODO(tobyboyd): Remove after license is excluded from BUILD file. -RUN gunzip /usr/share/doc/libnccl2/NCCL-SLA.txt.gz && \ - cp /usr/share/doc/libnccl2/NCCL-SLA.txt /usr/local/cuda/ +# Configure the build for our CUDA configuration. +ENV CI_BUILD_PYTHON python +ENV LD_LIBRARY_PATH /usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH +ENV TF_NEED_CUDA 1 +ENV TF_NEED_TENSORRT 1 +ENV TF_CUDA_COMPUTE_CAPABILITIES=3.5,5.2,6.0,6.1,7.0 +ENV TF_CUDA_VERSION=9.0 +ENV TF_CUDNN_VERSION=7 + +# NCCL 2.x +ENV TF_NCCL_VERSION=2 -ARG USE_PYTHON_3_NOT_2=True +ARG USE_PYTHON_3_NOT_2 ARG _PY_SUFFIX=${USE_PYTHON_3_NOT_2:+3} ARG PYTHON=python${_PY_SUFFIX} ARG PIP=pip${_PY_SUFFIX} @@ -96,10 +91,13 @@ RUN apt-get update && apt-get install -y \ ${PYTHON} \ ${PYTHON}-pip -RUN ${PIP} install --upgrade \ +RUN ${PIP} --no-cache-dir install --upgrade \ pip \ setuptools +# Some TF tools expect a "python" binary +RUN ln -s $(which ${PYTHON}) /usr/local/bin/python + RUN apt-get update && apt-get install -y \ build-essential \ curl \ @@ -108,6 +106,20 @@ RUN apt-get update && apt-get install -y \ ${PYTHON}-dev \ swig +RUN ${PIP} --no-cache-dir install \ + Pillow \ + h5py \ + keras_applications \ + keras_preprocessing \ + matplotlib \ + mock \ + numpy \ + scipy \ + sklearn \ + pandas \ + && test "${USE_PYTHON_3_NOT_2}" -eq 1 && true || ${PIP} --no-cache-dir install \ + enum34 + # Install bazel RUN echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list && \ curl https://bazel.build/bazel-release.pub.gpg | apt-key add - && \ diff --git a/tensorflow/tools/dockerfiles/dockerfiles/nvidia-jupyter.Dockerfile b/tensorflow/tools/dockerfiles/dockerfiles/gpu-jupyter.Dockerfile similarity index 62% rename from tensorflow/tools/dockerfiles/dockerfiles/nvidia-jupyter.Dockerfile rename to tensorflow/tools/dockerfiles/dockerfiles/gpu-jupyter.Dockerfile index fbdea4628a..acfe4d8607 100644 --- a/tensorflow/tools/dockerfiles/dockerfiles/nvidia-jupyter.Dockerfile +++ b/tensorflow/tools/dockerfiles/dockerfiles/gpu-jupyter.Dockerfile @@ -16,30 +16,13 @@ # THIS IS A GENERATED DOCKERFILE. # # This file was assembled from multiple pieces, whose use is documented -# below. Please refer to the the TensorFlow dockerfiles documentation for -# more information. Build args are documented as their default value. -# -# Ubuntu-based, Nvidia-GPU-enabled environment for using TensorFlow, with Jupyter included. -# -# NVIDIA with CUDA and CuDNN, no dev stuff -# --build-arg UBUNTU_VERSION=16.04 -# ( no description ) -# -# Python is required for TensorFlow and other libraries. -# --build-arg USE_PYTHON_3_NOT_2=True -# Install python 3 over Python 2 -# -# Install the TensorFlow Python package. -# --build-arg TF_PACKAGE=tensorflow-gpu (tensorflow|tensorflow-gpu|tf-nightly|tf-nightly-gpu) -# The specific TensorFlow Python package to install -# -# Configure TensorFlow's shell prompt and login tools. -# -# Launch Jupyter on execution instead of a bash prompt. +# throughout. Please refer to the TensorFlow dockerfiles documentation +# for more information. + +ARG UBUNTU_VERSION=16.04 -FROM nvidia/cuda:9.0-base-ubuntu16.04 +FROM nvidia/cuda:9.0-base-ubuntu${UBUNTU_VERSION} as base -# Pick up some TF dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ cuda-command-line-tools-9-0 \ @@ -48,6 +31,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cuda-curand-9-0 \ cuda-cusolver-9-0 \ cuda-cusparse-9-0 \ + curl \ libcudnn7=7.2.1.38-1+cuda9.0 \ libnccl2=2.2.13-1+cuda9.0 \ libfreetype6-dev \ @@ -55,6 +39,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpng12-dev \ libzmq3-dev \ pkg-config \ + rsync \ software-properties-common \ unzip \ && \ @@ -66,7 +51,10 @@ RUN apt-get update && \ apt-get update && \ apt-get install libnvinfer4=4.1.2-1+cuda9.0 -ARG USE_PYTHON_3_NOT_2=True +# For CUDA profiling, TensorFlow requires CUPTI. +ENV LD_LIBRARY_PATH /usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH + +ARG USE_PYTHON_3_NOT_2 ARG _PY_SUFFIX=${USE_PYTHON_3_NOT_2:+3} ARG PYTHON=python${_PY_SUFFIX} ARG PIP=pip${_PY_SUFFIX} @@ -78,21 +66,37 @@ RUN apt-get update && apt-get install -y \ ${PYTHON} \ ${PYTHON}-pip -RUN ${PIP} install --upgrade \ +RUN ${PIP} --no-cache-dir install --upgrade \ pip \ setuptools -ARG TF_PACKAGE=tensorflow-gpu +# Some TF tools expect a "python" binary +RUN ln -s $(which ${PYTHON}) /usr/local/bin/python + +# Options: +# tensorflow +# tensorflow-gpu +# tf-nightly +# tf-nightly-gpu +ARG TF_PACKAGE=tensorflow RUN ${PIP} install ${TF_PACKAGE} COPY bashrc /etc/bash.bashrc RUN chmod a+rwx /etc/bash.bashrc -RUN ${PIP} install jupyter +RUN ${PIP} install jupyter matplotlib -RUN mkdir /notebooks && chmod a+rwx /notebooks +RUN mkdir -p /tf/tensorflow-tutorials && chmod -R a+rwx /tf/ RUN mkdir /.local && chmod a+rwx /.local -WORKDIR /notebooks +RUN apt-get install -y --no-install-recommends wget +WORKDIR /tf/tensorflow-tutorials +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_classification.ipynb +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_text_classification.ipynb +COPY readme-for-jupyter.md README.md +RUN apt-get autoremove -y && apt-get remove -y wget +WORKDIR /tf EXPOSE 8888 -CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/notebooks --ip 0.0.0.0 --no-browser --allow-root"] +RUN ${PYTHON} -m ipykernel.kernelspec + +CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/tf --ip 0.0.0.0 --no-browser --allow-root"] diff --git a/tensorflow/tools/dockerfiles/dockerfiles/nvidia.Dockerfile b/tensorflow/tools/dockerfiles/dockerfiles/gpu.Dockerfile similarity index 69% rename from tensorflow/tools/dockerfiles/dockerfiles/nvidia.Dockerfile rename to tensorflow/tools/dockerfiles/dockerfiles/gpu.Dockerfile index e0312dbc29..f36a21eaf0 100644 --- a/tensorflow/tools/dockerfiles/dockerfiles/nvidia.Dockerfile +++ b/tensorflow/tools/dockerfiles/dockerfiles/gpu.Dockerfile @@ -16,28 +16,13 @@ # THIS IS A GENERATED DOCKERFILE. # # This file was assembled from multiple pieces, whose use is documented -# below. Please refer to the the TensorFlow dockerfiles documentation for -# more information. Build args are documented as their default value. -# -# Ubuntu-based, Nvidia-GPU-enabled environment for using TensorFlow. -# -# NVIDIA with CUDA and CuDNN, no dev stuff -# --build-arg UBUNTU_VERSION=16.04 -# ( no description ) -# -# Python is required for TensorFlow and other libraries. -# --build-arg USE_PYTHON_3_NOT_2=True -# Install python 3 over Python 2 -# -# Install the TensorFlow Python package. -# --build-arg TF_PACKAGE=tensorflow-gpu (tensorflow|tensorflow-gpu|tf-nightly|tf-nightly-gpu) -# The specific TensorFlow Python package to install -# -# Configure TensorFlow's shell prompt and login tools. +# throughout. Please refer to the TensorFlow dockerfiles documentation +# for more information. + +ARG UBUNTU_VERSION=16.04 -FROM nvidia/cuda:9.0-base-ubuntu16.04 +FROM nvidia/cuda:9.0-base-ubuntu${UBUNTU_VERSION} as base -# Pick up some TF dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ cuda-command-line-tools-9-0 \ @@ -46,6 +31,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cuda-curand-9-0 \ cuda-cusolver-9-0 \ cuda-cusparse-9-0 \ + curl \ libcudnn7=7.2.1.38-1+cuda9.0 \ libnccl2=2.2.13-1+cuda9.0 \ libfreetype6-dev \ @@ -53,6 +39,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpng12-dev \ libzmq3-dev \ pkg-config \ + rsync \ software-properties-common \ unzip \ && \ @@ -64,7 +51,10 @@ RUN apt-get update && \ apt-get update && \ apt-get install libnvinfer4=4.1.2-1+cuda9.0 -ARG USE_PYTHON_3_NOT_2=True +# For CUDA profiling, TensorFlow requires CUPTI. +ENV LD_LIBRARY_PATH /usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH + +ARG USE_PYTHON_3_NOT_2 ARG _PY_SUFFIX=${USE_PYTHON_3_NOT_2:+3} ARG PYTHON=python${_PY_SUFFIX} ARG PIP=pip${_PY_SUFFIX} @@ -76,11 +66,19 @@ RUN apt-get update && apt-get install -y \ ${PYTHON} \ ${PYTHON}-pip -RUN ${PIP} install --upgrade \ +RUN ${PIP} --no-cache-dir install --upgrade \ pip \ setuptools -ARG TF_PACKAGE=tensorflow-gpu +# Some TF tools expect a "python" binary +RUN ln -s $(which ${PYTHON}) /usr/local/bin/python + +# Options: +# tensorflow +# tensorflow-gpu +# tf-nightly +# tf-nightly-gpu +ARG TF_PACKAGE=tensorflow RUN ${PIP} install ${TF_PACKAGE} COPY bashrc /etc/bash.bashrc diff --git a/tensorflow/tools/dockerfiles/partials/jupyter.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/jupyter.partial.Dockerfile index 2c9b9f3f9a..c4ec6095c0 100644 --- a/tensorflow/tools/dockerfiles/partials/jupyter.partial.Dockerfile +++ b/tensorflow/tools/dockerfiles/partials/jupyter.partial.Dockerfile @@ -1,8 +1,16 @@ -RUN ${PIP} install jupyter +RUN ${PIP} install jupyter matplotlib -RUN mkdir /notebooks && chmod a+rwx /notebooks +RUN mkdir -p /tf/tensorflow-tutorials && chmod -R a+rwx /tf/ RUN mkdir /.local && chmod a+rwx /.local -WORKDIR /notebooks +RUN apt-get install -y --no-install-recommends wget +WORKDIR /tf/tensorflow-tutorials +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_classification.ipynb +RUN wget https://raw.githubusercontent.com/tensorflow/docs/master/site/en/tutorials/keras/basic_text_classification.ipynb +COPY readme-for-jupyter.md README.md +RUN apt-get autoremove -y && apt-get remove -y wget +WORKDIR /tf EXPOSE 8888 -CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/notebooks --ip 0.0.0.0 --no-browser --allow-root"] +RUN ${PYTHON} -m ipykernel.kernelspec + +CMD ["bash", "-c", "source /etc/bash.bashrc && jupyter notebook --notebook-dir=/tf --ip 0.0.0.0 --no-browser --allow-root"] diff --git a/tensorflow/tools/dockerfiles/partials/tensorflow.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/tensorflow.partial.Dockerfile index 96e79547f0..76758bd147 100644 --- a/tensorflow/tools/dockerfiles/partials/tensorflow.partial.Dockerfile +++ b/tensorflow/tools/dockerfiles/partials/tensorflow.partial.Dockerfile @@ -1,2 +1,7 @@ -ARG TF_PACKAGE +# Options: +# tensorflow +# tensorflow-gpu +# tf-nightly +# tf-nightly-gpu +ARG TF_PACKAGE=tensorflow RUN ${PIP} install ${TF_PACKAGE} diff --git a/tensorflow/tools/dockerfiles/partials/test-import.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/test-import.partial.Dockerfile new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tensorflow/tools/dockerfiles/partials/ubuntu.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/ubuntu.partial.Dockerfile deleted file mode 100644 index 0a50735bf8..0000000000 --- a/tensorflow/tools/dockerfiles/partials/ubuntu.partial.Dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -ARG UBUNTU_VERSION=16.04 -FROM ubuntu:${UBUNTU_VERSION} diff --git a/tensorflow/tools/dockerfiles/partials/bazel.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/ubuntu/bazel.partial.Dockerfile similarity index 58% rename from tensorflow/tools/dockerfiles/partials/bazel.partial.Dockerfile rename to tensorflow/tools/dockerfiles/partials/ubuntu/bazel.partial.Dockerfile index b08d8bdd14..156bb01991 100644 --- a/tensorflow/tools/dockerfiles/partials/bazel.partial.Dockerfile +++ b/tensorflow/tools/dockerfiles/partials/ubuntu/bazel.partial.Dockerfile @@ -6,6 +6,20 @@ RUN apt-get update && apt-get install -y \ ${PYTHON}-dev \ swig +RUN ${PIP} --no-cache-dir install \ + Pillow \ + h5py \ + keras_applications \ + keras_preprocessing \ + matplotlib \ + mock \ + numpy \ + scipy \ + sklearn \ + pandas \ + && test "${USE_PYTHON_3_NOT_2}" -eq 1 && true || ${PIP} --no-cache-dir install \ + enum34 + # Install bazel RUN echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list && \ curl https://bazel.build/bazel-release.pub.gpg | apt-key add - && \ diff --git a/tensorflow/tools/dockerfiles/partials/ubuntu-devel.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/ubuntu/cpu-devel.partial.Dockerfile similarity index 86% rename from tensorflow/tools/dockerfiles/partials/ubuntu-devel.partial.Dockerfile rename to tensorflow/tools/dockerfiles/partials/ubuntu/cpu-devel.partial.Dockerfile index bc79272276..901652cc28 100644 --- a/tensorflow/tools/dockerfiles/partials/ubuntu-devel.partial.Dockerfile +++ b/tensorflow/tools/dockerfiles/partials/ubuntu/cpu-devel.partial.Dockerfile @@ -1,5 +1,4 @@ -ARG UBUNTU_VERSION=16.04 -FROM ubuntu:${UBUNTU_VERSION} +FROM ubuntu:${UBUNTU_VERSION} AS base RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ @@ -11,7 +10,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpng12-dev \ libzmq3-dev \ pkg-config \ - python-dev \ rsync \ software-properties-common \ unzip \ @@ -22,3 +20,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* + +ENV CI_BUILD_PYTHON python + diff --git a/tensorflow/tools/dockerfiles/partials/ubuntu/cpu.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/ubuntu/cpu.partial.Dockerfile new file mode 100644 index 0000000000..d01b26e27f --- /dev/null +++ b/tensorflow/tools/dockerfiles/partials/ubuntu/cpu.partial.Dockerfile @@ -0,0 +1 @@ +FROM ubuntu:${UBUNTU_VERSION} as base diff --git a/tensorflow/tools/dockerfiles/partials/nvidia-devel.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/ubuntu/nvidia-devel.partial.Dockerfile similarity index 78% rename from tensorflow/tools/dockerfiles/partials/nvidia-devel.partial.Dockerfile rename to tensorflow/tools/dockerfiles/partials/ubuntu/nvidia-devel.partial.Dockerfile index 45159f711f..48d457e40c 100644 --- a/tensorflow/tools/dockerfiles/partials/nvidia-devel.partial.Dockerfile +++ b/tensorflow/tools/dockerfiles/partials/ubuntu/nvidia-devel.partial.Dockerfile @@ -1,5 +1,4 @@ -ARG UBUNTU_VERSION=16.04 -FROM nvidia/cuda:9.0-base-ubuntu${UBUNTU_VERSION} +FROM nvidia/cuda:9.0-base-ubuntu${UBUNTU_VERSION} as base RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ @@ -22,6 +21,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpng12-dev \ libzmq3-dev \ pkg-config \ + python-dev \ rsync \ software-properties-common \ unzip \ @@ -44,6 +44,14 @@ RUN mkdir /usr/local/cuda-9.0/lib && \ ln -s /usr/lib/x86_64-linux-gnu/libnccl.so.2 /usr/local/cuda/lib/libnccl.so.2 && \ ln -s /usr/include/nccl.h /usr/local/cuda/include/nccl.h -# TODO(tobyboyd): Remove after license is excluded from BUILD file. -RUN gunzip /usr/share/doc/libnccl2/NCCL-SLA.txt.gz && \ - cp /usr/share/doc/libnccl2/NCCL-SLA.txt /usr/local/cuda/ +# Configure the build for our CUDA configuration. +ENV CI_BUILD_PYTHON python +ENV LD_LIBRARY_PATH /usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH +ENV TF_NEED_CUDA 1 +ENV TF_NEED_TENSORRT 1 +ENV TF_CUDA_COMPUTE_CAPABILITIES=3.5,5.2,6.0,6.1,7.0 +ENV TF_CUDA_VERSION=9.0 +ENV TF_CUDNN_VERSION=7 + +# NCCL 2.x +ENV TF_NCCL_VERSION=2 diff --git a/tensorflow/tools/dockerfiles/partials/nvidia.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/ubuntu/nvidia.partial.Dockerfile similarity index 78% rename from tensorflow/tools/dockerfiles/partials/nvidia.partial.Dockerfile rename to tensorflow/tools/dockerfiles/partials/ubuntu/nvidia.partial.Dockerfile index 1064390af3..1dc8e43aad 100644 --- a/tensorflow/tools/dockerfiles/partials/nvidia.partial.Dockerfile +++ b/tensorflow/tools/dockerfiles/partials/ubuntu/nvidia.partial.Dockerfile @@ -1,6 +1,5 @@ -FROM nvidia/cuda:9.0-base-ubuntu16.04 +FROM nvidia/cuda:9.0-base-ubuntu${UBUNTU_VERSION} as base -# Pick up some TF dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ cuda-command-line-tools-9-0 \ @@ -9,6 +8,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cuda-curand-9-0 \ cuda-cusolver-9-0 \ cuda-cusparse-9-0 \ + curl \ libcudnn7=7.2.1.38-1+cuda9.0 \ libnccl2=2.2.13-1+cuda9.0 \ libfreetype6-dev \ @@ -16,6 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libpng12-dev \ libzmq3-dev \ pkg-config \ + rsync \ software-properties-common \ unzip \ && \ @@ -26,3 +27,6 @@ RUN apt-get update && \ apt-get install nvinfer-runtime-trt-repo-ubuntu1604-4.0.1-ga-cuda9.0 && \ apt-get update && \ apt-get install libnvinfer4=4.1.2-1+cuda9.0 + +# For CUDA profiling, TensorFlow requires CUPTI. +ENV LD_LIBRARY_PATH /usr/local/cuda/extras/CUPTI/lib64:$LD_LIBRARY_PATH diff --git a/tensorflow/tools/dockerfiles/partials/python.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/ubuntu/python.partial.Dockerfile similarity index 66% rename from tensorflow/tools/dockerfiles/partials/python.partial.Dockerfile rename to tensorflow/tools/dockerfiles/partials/ubuntu/python.partial.Dockerfile index ee08af73a8..6af4731953 100644 --- a/tensorflow/tools/dockerfiles/partials/python.partial.Dockerfile +++ b/tensorflow/tools/dockerfiles/partials/ubuntu/python.partial.Dockerfile @@ -10,6 +10,9 @@ RUN apt-get update && apt-get install -y \ ${PYTHON} \ ${PYTHON}-pip -RUN ${PIP} install --upgrade \ +RUN ${PIP} --no-cache-dir install --upgrade \ pip \ setuptools + +# Some TF tools expect a "python" binary +RUN ln -s $(which ${PYTHON}) /usr/local/bin/python diff --git a/tensorflow/tools/dockerfiles/partials/ubuntu/test-devel.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/ubuntu/test-devel.partial.Dockerfile new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tensorflow/tools/dockerfiles/partials/ubuntu/version.partial.Dockerfile b/tensorflow/tools/dockerfiles/partials/ubuntu/version.partial.Dockerfile new file mode 100644 index 0000000000..6ecd2b8b1a --- /dev/null +++ b/tensorflow/tools/dockerfiles/partials/ubuntu/version.partial.Dockerfile @@ -0,0 +1 @@ +ARG UBUNTU_VERSION=16.04 diff --git a/tensorflow/tools/dockerfiles/readme-for-jupyter.md b/tensorflow/tools/dockerfiles/readme-for-jupyter.md new file mode 100644 index 0000000000..f104a7533b --- /dev/null +++ b/tensorflow/tools/dockerfiles/readme-for-jupyter.md @@ -0,0 +1,3 @@ +Want more tutorials like these? + +Check out tensorflow.org/tutorials! diff --git a/tensorflow/tools/dockerfiles/spec.yml b/tensorflow/tools/dockerfiles/spec.yml index 28bf9a55da..4826ddd8e2 100644 --- a/tensorflow/tools/dockerfiles/spec.yml +++ b/tensorflow/tools/dockerfiles/spec.yml @@ -1,195 +1,135 @@ -# ====== -# HEADER -# ====== -# -# This is commented-out and prepended to each generated Dockerfile. header: | - Copyright 2018 The TensorFlow Authors. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ============================================================================ - - THIS IS A GENERATED DOCKERFILE. - - This file was assembled from multiple pieces, whose use is documented - below. Please refer to the the TensorFlow dockerfiles documentation for - more information. Build args are documented as their default value. - -# ======== -# PARTIALS -# ======== + # Copyright 2018 The TensorFlow Authors. All Rights Reserved. + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + # ============================================================================ + # + # THIS IS A GENERATED DOCKERFILE. + # + # This file was assembled from multiple pieces, whose use is documented + # throughout. Please refer to the TensorFlow dockerfiles documentation + # for more information. + +# A combinatorial explosion of Docker images and Dockerfiles. +# Each "release" defines all of the ways to combine related but separate chunks +# of functionality ("slices") by listing all of the "slice sets" to use when +# building. # -# Represent and document pieces of a Dockerfile. Spec: -# -# name: the name of the partial, is referenced from the images section -# desc: A description, inserted later into the Dockerfile -# file: Alternative file prefix, e.g. file.partial.Dockerfile. The default is -# the name of the partial. -# args: A dict of ARGs in the Dockerfile; each entry has the format -# ARG_NAME: VALUE where VALUE is one of: -# - a dict: -# desc: Documentation for the arg -# default: Default value for the arg; is written to the Dockerfile -# options: List of strings, part of documentation -# - a concrete value: the same as a dictionary with default: [value]. - -partials: - ubuntu: - desc: Start from Ubuntu (no GPU support) - args: - UBUNTU_VERSION: 16.04 - - ubuntu-devel: - desc: Start from Ubuntu, with TF development packages (no GPU support) - args: - UBUNTU_VERSION: 16.04 - - bazel: - desc: Install the latest version of Bazel and Python development tools. - - nvidia: - desc: NVIDIA with CUDA and CuDNN, no dev stuff - args: - UBUNTU_VERSION: 16.04 - - nvidia-devel: - desc: > - Start from Nvidia's Ubuntu base image with CUDA and CuDNN, with TF - development packages. - args: - UBUNTU_VERSION: 16.04 +# For example, a release that uses {nightly}{py} would create 4 Dockerfiles +# (which could become images or concrete Dockerfiles), because the "nightly" +# and "py" slice sets both have two entries: +# +# - nightly (no -py2 because the Python 2 slice set has add_to_name: "" +# - nightly-py3 +# - nightly-gpu (similar) +# - nightly-gpu-py3 + +releases: + nightly: + tag_specs: + - "{nightly}{py}{jupyter}" + + versioned: + tag_specs: + - "{_TAG_PREFIX}{ubuntu}{py}{jupyter}" + + ubuntu-dockerfiles: + is_dockerfiles: true + upload_images: false + tag_specs: + - "{ubuntu}{jupyter}" + +slice_sets: + + py: + - add_to_name: "" + args: + - USE_PYTHON_3_NOT_2= + - add_to_name: "-py3" + args: + - USE_PYTHON_3_NOT_2=1 - python: - desc: Python is required for TensorFlow and other libraries. - args: - USE_PYTHON_3_NOT_2: - default: true - desc: Install python 3 over Python 2 - - tensorflow: - desc: Install the TensorFlow Python package. - args: - TF_PACKAGE: - default: tensorflow - options: - - tensorflow - - tensorflow-gpu - - tf-nightly - - tf-nightly-gpu - desc: The specific TensorFlow Python package to install - shell: - desc: Configure TensorFlow's shell prompt and login tools. jupyter: - desc: Launch Jupyter on execution instead of a bash prompt. - -# ====== -# IMAGES -# ====== -# -# Represent Dockerfiles. Spec: -# -# name: the name of the image, possibly referenced by other images -# desc: A description, inserted later into the Dockerfile -# create-dockerfile: Create a dockerfile based on this. Useful for creating -# extensible base images that don't need a file. Default is true. -# partials: List of VALUEs, where a VALUE is either: -# - the name of a partial, which inserts that partial into this image -# - image: [name of another image], which inserts the partials from that -# image into this image -# arg-defaults: List of VALUEs, where a VALUE is either: -# - ARG_NAME: VALUE, which sets the ARG_NAME to VALUE wherever it appears -# in this image's partials -# - [name of another image], which loads the default args from that image -images: - - nodev: - create-dockerfile: false - partials: - - python - - tensorflow - - shell - - dev: - create-dockerfile: false - partials: - - python - - bazel - - shell - - cpu: - desc: Ubuntu-based, CPU-only environment for using TensorFlow - partials: - - ubuntu - - image: nodev - - cpu-devel: - desc: > - Ubuntu-based, CPU-only environment for developing changes for - TensorFlow. - partials: - - ubuntu-devel - - image: dev + - add_to_name: "" + - add_to_name: "-jupyter" + partials: + - jupyter - nvidia: - desc: Ubuntu-based, Nvidia-GPU-enabled environment for using TensorFlow. - arg-defaults: - - TF_PACKAGE: tensorflow-gpu - partials: - - nvidia - - image: nodev - - nvidia-devel: - desc: > - Ubuntu-based, Nvidia-GPU-enabled environment for developing changes - for TensorFlow. - arg-defaults: - - TF_PACKAGE: tensorflow-gpu - partials: - - nvidia-devel - - image: dev - - cpu-jupyter: - desc: > - Ubuntu-based, CPU-only environment for using TensorFlow, with Jupyter - included. - partials: - - image: cpu - - jupyter - - cpu-devel-jupyter: - desc: > - Ubuntu-based, CPU-only environment for developing changes for - TensorFlow, with Jupyter included. - partials: - - image: cpu-devel - - jupyter - - nvidia-jupyter: - desc: > - Ubuntu-based, Nvidia-GPU-enabled environment for using TensorFlow, with - Jupyter included. - arg-defaults: - - nvidia - partials: - - image: nvidia - - jupyter - - nvidia-devel-jupyter: - desc: > - Ubuntu-based, Nvidia-GPU-enabled environment for developing changes for - TensorFlow, with Jupyter included. - arg-defaults: - - nvidia-devel - partials: - - image: nvidia-devel - - jupyter + ubuntu: + - add_to_name: "" + dockerfile_exclusive_name: "cpu" + partials: + - ubuntu/version + - ubuntu/cpu + - ubuntu/python + - tensorflow + - shell + - add_to_name: "-gpu" + dockerfile_exclusive_name: "gpu" + args: + - TF_PACKAGE=tensorflow-gpu + partials: + - ubuntu/version + - ubuntu/nvidia + - ubuntu/python + - tensorflow + - shell + tests: + - import-gpu.sh + test_runtime: nvidia + - add_to_name: "-devel" + dockerfile_exclusive_name: "cpu-devel" + partials: + - ubuntu/version + - ubuntu/cpu-devel + - ubuntu/python + - ubuntu/bazel + - shell + tests: + - build-cpu.sh + - add_to_name: "-gpu-devel" + dockerfile_exclusive_name: "gpu-devel" + partials: + - ubuntu/version + - ubuntu/nvidia-devel + - ubuntu/python + - ubuntu/bazel + - shell + tests: + - build-gpu.sh + test_runtime: nvidia + + nightly: + - add_to_name: "nightly" + partials: + - ubuntu/version + - ubuntu/cpu + - ubuntu/python + - tensorflow + - shell + args: + - TF_PACKAGE=tf-nightly + tests: + - import.sh + - add_to_name: "nightly-gpu" + partials: + - ubuntu/version + - ubuntu/nvidia + - ubuntu/python + - tensorflow + - shell + test_runtime: nvidia + tests: + - import-gpu.sh + args: + - TF_PACKAGE=tf-nightly-gpu diff --git a/tensorflow/tools/dockerfiles/tests/build-cpu.sh b/tensorflow/tools/dockerfiles/tests/build-cpu.sh new file mode 100755 index 0000000000..bcdc4c2139 --- /dev/null +++ b/tensorflow/tools/dockerfiles/tests/build-cpu.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + +# Download and build TensorFlow. +set -euxo pipefail +git clone --branch=master --depth=1 https://github.com/tensorflow/tensorflow.git /tensorflow +cd /tensorflow + +ln -s $(which ${PYTHON}) /usr/local/bin/python + +# For optimized builds appropriate for the hardware platform of your choosing, uncomment below... +# For ivy-bridge or sandy-bridge +# --copt=-march="ivybridge" \ +# for haswell, broadwell, or skylake +# --copt=-march="haswell" \ +tensorflow/tools/ci_build/builds/configured CPU \ + bazel build -c opt --copt=-mavx --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ + tensorflow/tools/pip_package:build_pip_package && \ + bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/pip && \ + pip --no-cache-dir install --upgrade /tmp/pip/tensorflow-*.whl && \ + rm -rf /tmp/pip && \ + rm -rf /root/.cache + diff --git a/tensorflow/tools/dockerfiles/tests/build-gpu.sh b/tensorflow/tools/dockerfiles/tests/build-gpu.sh new file mode 100755 index 0000000000..76b25d5a74 --- /dev/null +++ b/tensorflow/tools/dockerfiles/tests/build-gpu.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + +# Download and build TensorFlow. +set -euxo pipefail +git clone --branch=master --depth=1 https://github.com/tensorflow/tensorflow.git /tensorflow +cd /tensorflow + +ln -s $(which ${PYTHON}) /usr/local/bin/python + +ln -s /usr/local/cuda/lib64/stubs/libcuda.so /usr/local/cuda/lib64/stubs/libcuda.so.1 + +LD_LIBRARY_PATH=/usr/local/cuda/lib64/stubs:${LD_LIBRARY_PATH} \ +tensorflow/tools/ci_build/builds/configured GPU \ +bazel build -c opt --copt=-mavx --config=cuda \ + --cxxopt="-D_GLIBCXX_USE_CXX11_ABI=0" \ + tensorflow/tools/pip_package:build_pip_package && \ +rm /usr/local/cuda/lib64/stubs/libcuda.so.1 && \ +bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/pip && \ +pip --no-cache-dir install --upgrade /tmp/pip/tensorflow-*.whl && \ +rm -rf /tmp/pip && \ +rm -rf /root/.cache diff --git a/tensorflow/tools/dockerfiles/tests/import-gpu.sh b/tensorflow/tools/dockerfiles/tests/import-gpu.sh new file mode 100755 index 0000000000..6559210dcb --- /dev/null +++ b/tensorflow/tools/dockerfiles/tests/import-gpu.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + +python -c 'import tensorflow as tf; tf.test.is_gpu_available() or exit(1)' diff --git a/tensorflow/tools/dockerfiles/tests/import.sh b/tensorflow/tools/dockerfiles/tests/import.sh new file mode 100755 index 0000000000..b73bd86a85 --- /dev/null +++ b/tensorflow/tools/dockerfiles/tests/import.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ + +set -euxo pipefail +python -c 'import tensorflow as tf' diff --git a/tensorflow/tools/dockerfiles/assembler.Dockerfile b/tensorflow/tools/dockerfiles/tools.Dockerfile similarity index 95% rename from tensorflow/tools/dockerfiles/assembler.Dockerfile rename to tensorflow/tools/dockerfiles/tools.Dockerfile index 7a8e07fced..e8929295a5 100644 --- a/tensorflow/tools/dockerfiles/assembler.Dockerfile +++ b/tensorflow/tools/dockerfiles/tools.Dockerfile @@ -20,8 +20,9 @@ FROM debian:stretch LABEL maintainer="Austin Anderson " -RUN apt-get update && apt-get install -y python3 python3-pip bash -RUN pip3 install --upgrade pip setuptools pyyaml absl-py cerberus +RUN apt-get update && apt-get install -y python3 python3-pip bash curl +RUN curl -sSL https://get.docker.com/ | sh +RUN pip3 install --upgrade pip setuptools pyyaml absl-py cerberus docker WORKDIR /tf VOLUME ["/tf"] diff --git a/tensorflow/tools/docs/BUILD b/tensorflow/tools/docs/BUILD index 1a53f24177..b072853a4e 100644 --- a/tensorflow/tools/docs/BUILD +++ b/tensorflow/tools/docs/BUILD @@ -142,17 +142,30 @@ py_test( ], ) -py_binary( - name = "generate_1_0", - srcs = ["generate_1_0.py"], +py_test( + name = "generate2_test", + srcs = ["generate2_test.py"], srcs_version = "PY2AND3", + tags = [ + "manual", + # No reason to run sanitizers or fastbuild for this test. + "noasan", + "nomsan", + "notsan", + "optonly", + ], deps = [ - ":generate_lib", - "//tensorflow:tensorflow_py", - "//tensorflow/python/debug:debug_py", + ":generate2", ], ) +py_binary( + name = "generate2", + srcs = ["generate2.py"], + srcs_version = "PY2AND3", + deps = ["//tensorflow:tensorflow_py"], +) + py_library( name = "py_guide_parser", srcs = ["py_guide_parser.py"], diff --git a/tensorflow/tools/docs/generate2.py b/tensorflow/tools/docs/generate2.py new file mode 100644 index 0000000000..fba909d26d --- /dev/null +++ b/tensorflow/tools/docs/generate2.py @@ -0,0 +1,82 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +r"""A tool to generate api_docs for TensorFlow2. + +``` +python generate2.py --output_dir=/tmp/out +``` + +Requires a local installation of: + https://github.com/tensorflow/docs/tree/master/tools + tf-nightly-2.0-preview +""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from os import path + +from absl import app +from absl import flags + +import tensorflow as tf + +from tensorflow_docs.api_generator import generate_lib + +FLAGS = flags.FLAGS + +flags.DEFINE_string( + "code_url_prefix", + "/code/stable/tensorflow/", + "A url to prepend to code paths when creating links to defining code") + +flags.DEFINE_string( + "output_dir", "/tmp/out", + "A directory, where the docs will be output to.") + +flags.DEFINE_bool("search_hints", True, + "Include meta-data search hints at the top of each file.") + + +def build_docs(output_dir, code_url_prefix, search_hints=True): + """Build api docs for tensorflow v2. + + Args: + output_dir: A string path, where to put the files. + code_url_prefix: prefix for "Defined in" links. + search_hints: Bool. Include meta-data search hints at the top of each file. + """ + base_dir = path.dirname(tf.__file__) + doc_generator = generate_lib.DocGenerator( + root_title="TensorFlow 2.0 Preview", + py_modules=[("tf", tf)], + base_dir=base_dir, + search_hints=search_hints, + code_url_prefix=code_url_prefix, + site_path="api_docs/") + + doc_generator.build(output_dir) + + +def main(argv): + del argv + build_docs(output_dir=FLAGS.output_dir, + code_url_prefix=FLAGS.code_url_prefix, + search_hints=FLAGS.search_hints) + + +if __name__ == "__main__": + app.run(main) diff --git a/tensorflow/contrib/estimator/python/estimator/linear.py b/tensorflow/tools/docs/generate2_test.py similarity index 60% rename from tensorflow/contrib/estimator/python/estimator/linear.py rename to tensorflow/tools/docs/generate2_test.py index b6a4444f66..774d45c536 100644 --- a/tensorflow/contrib/estimator/python/estimator/linear.py +++ b/tensorflow/tools/docs/generate2_test.py @@ -12,21 +12,28 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""linear python module. - -Importing from tensorflow.python.estimator is unsupported -and will soon break! -""" -# pylint: disable=unused-import,g-bad-import-order,g-import-not-at-top,wildcard-import +"""Tests for tensorflow.tools.docs.generate2.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow_estimator.contrib.estimator.python.estimator import linear +import os +import shutil + +from tensorflow.python.platform import googletest +from tensorflow.tools.docs import generate2 + + +class Generate2Test(googletest.TestCase): + + def test_end_to_end(self): + output_dir = os.path.join(googletest.GetTempDir(), 'output') + if os.path.exists(output_dir): + shutil.rmtree(output_dir) + os.makedirs(output_dir) + generate2.build_docs(output_dir=output_dir, code_url_prefix='') -# Include attrs that start with single underscore. -_HAS_DYNAMIC_ATTRIBUTES = True -linear.__all__ = [s for s in dir(linear) if not s.startswith('__')] -from tensorflow_estimator.contrib.estimator.python.estimator.linear import * +if __name__ == '__main__': + googletest.main() diff --git a/tensorflow/tools/docs/generate_1_0.py b/tensorflow/tools/docs/generate_1_0.py deleted file mode 100644 index f4384e0ced..0000000000 --- a/tensorflow/tools/docs/generate_1_0.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2015 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -"""Generate docs for the TensorFlow Python API.""" - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function - -import os -import sys - -import tensorflow as tf - -from tensorflow.python import debug as tf_debug -from tensorflow.python.util import tf_inspect -from tensorflow.tools.docs import generate_lib - -if __name__ == '__main__': - doc_generator = generate_lib.DocGenerator() - doc_generator.add_output_dir_argument() - doc_generator.add_src_dir_argument() - - # This doc generator works on the TensorFlow codebase. Since this script lives - # at tensorflow/tools/docs, and all code is defined somewhere inside - # tensorflow/, we can compute the base directory (two levels up), which is - # valid unless we're trying to apply this to a different code base, or are - # moving the script around. - script_dir = os.path.dirname(tf_inspect.getfile(tf_inspect.currentframe())) - default_base_dir = os.path.join(script_dir, '..', '..') - doc_generator.add_base_dir_argument(default_base_dir) - - flags = doc_generator.parse_known_args() - - # tf_debug is not imported with tf, it's a separate module altogether - doc_generator.set_py_modules([('tf', tf), ('tfdbg', tf_debug)]) - - doc_generator.set_do_not_descend_map({ - 'tf': ['cli', 'lib', 'wrappers'], - 'tf.contrib': [ - 'compiler', - 'factorization', - 'grid_rnn', - 'labeled_tensor', - 'quantization', - 'session_bundle', - 'slim', - 'solvers', - 'specs', - 'tensor_forest', - 'tensorboard', - 'testing', - 'training', - 'tfprof', - ], - 'tf.contrib.bayesflow': [ - 'entropy', 'monte_carlo', 'special_math', - 'stochastic_gradient_estimators', 'stochastic_graph', - 'stochastic_tensor', 'stochastic_variables', 'variational_inference' - ], - 'tf.contrib.distributions': ['bijector'], - 'tf.contrib.ffmpeg': ['ffmpeg_ops'], - 'tf.contrib.graph_editor': [ - 'edit', 'match', 'reroute', 'subgraph', 'transform', 'select', 'util' - ], - 'tf.contrib.layers': ['feature_column', 'summaries'], - 'tf.contrib.learn': [ - 'datasets', - 'head', - 'graph_actions', - 'io', - 'models', - 'monitors', - 'ops', - 'preprocessing', - 'utils', - ], - 'tf.contrib.util': ['loader'], - }) - - sys.exit(doc_generator.build(flags)) diff --git a/tensorflow/tools/docs/parser.py b/tensorflow/tools/docs/parser.py index 83b4bf8128..6dc18ee8dc 100644 --- a/tensorflow/tools/docs/parser.py +++ b/tensorflow/tools/docs/parser.py @@ -39,7 +39,7 @@ def is_free_function(py_object, full_name, index): """Check if input is a free function (and not a class- or static method). Args: - py_object: The the object in question. + py_object: The object in question. full_name: The full name of the object, like `tf.module.symbol`. index: The {full_name:py_object} dictionary for the public API. diff --git a/tensorflow/tools/lib_package/BUILD b/tensorflow/tools/lib_package/BUILD index 7aaa845ae9..1cac5ee138 100644 --- a/tensorflow/tools/lib_package/BUILD +++ b/tensorflow/tools/lib_package/BUILD @@ -112,6 +112,7 @@ pkg_tar( genrule( name = "clicenses_generate", srcs = [ + "//third_party/icu/data:LICENSE", "//third_party/hadoop:LICENSE.txt", "//third_party/eigen3:LICENSE", "//third_party/fft2d:LICENSE", @@ -180,6 +181,7 @@ genrule( genrule( name = "jnilicenses_generate", srcs = [ + "//third_party/icu/data:LICENSE", "//third_party/hadoop:LICENSE.txt", "//third_party/eigen3:LICENSE", "//third_party/fft2d:LICENSE", diff --git a/tensorflow/tools/pip_package/BUILD b/tensorflow/tools/pip_package/BUILD index 3a863d3c52..82c6bf383f 100644 --- a/tensorflow/tools/pip_package/BUILD +++ b/tensorflow/tools/pip_package/BUILD @@ -88,6 +88,9 @@ COMMON_PIP_DEPS = [ "//tensorflow/contrib/timeseries:timeseries_pip", "//tensorflow/contrib/tpu", "//tensorflow/examples/tutorials/mnist:package", + "//tensorflow/lite/python:interpreter_test_data", + "//tensorflow/lite/python:tflite_convert", + "//tensorflow/lite/toco/python:toco_from_protos", # "//tensorflow/python/autograph/converters:converters", # "//tensorflow/python/autograph/core:core", "//tensorflow/python/autograph/core:test_lib", @@ -124,7 +127,7 @@ COMMON_PIP_DEPS = [ py_binary( name = "simple_console_for_windows", srcs = ["simple_console_for_windows.py"], - data = COMMON_PIP_DEPS, + data = COMMON_PIP_DEPS + ["//tensorflow/python:pywrap_tensorflow_import_lib_file"], srcs_version = "PY2AND3", deps = ["//tensorflow:tensorflow_py"], ) @@ -132,6 +135,7 @@ py_binary( filegroup( name = "licenses", data = [ + "//third_party/icu/data:LICENSE", "//third_party/eigen3:LICENSE", "//third_party/fft2d:LICENSE", "//third_party/hadoop:LICENSE.txt", @@ -227,15 +231,9 @@ sh_binary( data = select({ "//tensorflow:windows": [ ":simple_console_for_windows", - "//tensorflow/lite/python:interpreter_test_data", - "//tensorflow/lite/python:tflite_convert", - "//tensorflow/lite/toco/python:toco_from_protos", ], "//conditions:default": COMMON_PIP_DEPS + [ ":simple_console", - "//tensorflow/lite/python:interpreter_test_data", - "//tensorflow/lite/python:tflite_convert", - "//tensorflow/lite/toco/python:toco_from_protos", ], }) + if_mkl_ml(["//third_party/mkl:intel_binary_blob"]), ) diff --git a/tensorflow/tools/pip_package/setup.py b/tensorflow/tools/pip_package/setup.py index 07475cc0c4..85c913f158 100644 --- a/tensorflow/tools/pip_package/setup.py +++ b/tensorflow/tools/pip_package/setup.py @@ -87,7 +87,8 @@ if 'tf_nightly' in project_name: for i, pkg in enumerate(REQUIRED_PACKAGES): if 'tensorboard' in pkg: REQUIRED_PACKAGES[i] = 'tb-nightly >= 1.13.0a0, < 1.14.0a0' - break + if 'tensorflow_estimator' in pkg: + REQUIRED_PACKAGES[i] = 'tf-estimator-nightly' # weakref.finalize and enum were introduced in Python 3.4 if sys.version_info < (3, 4): @@ -106,6 +107,7 @@ CONSOLE_SCRIPTS = [ # TensorBoard command, pip will inappropriately remove it during install, # even though the command is not removed, just moved to a different wheel. 'tensorboard = tensorboard.main:run_main', + 'tf_upgrade_v2 = tensorflow.tools.compatibility.tf_upgrade_v2_main:main', ] # pylint: enable=line-too-long diff --git a/tensorflow/workspace.bzl b/tensorflow/workspace.bzl index 6d3562caef..7e5f84be16 100755 --- a/tensorflow/workspace.bzl +++ b/tensorflow/workspace.bzl @@ -77,31 +77,31 @@ def tf_workspace(path_prefix = "", tf_repo_name = ""): mkl_repository( name = "mkl_linux", build_file = clean_dep("//third_party/mkl:mkl.BUILD"), - sha256 = "e2233534a9d15c387e22260997af4312a39e9f86f791768409be273b5453c4e6", - strip_prefix = "mklml_lnx_2019.0.20180710", + sha256 = "f00dc3b142a5be399bdeebd7e7ea369545a35d4fb84c86f98b6b048d72685295", + strip_prefix = "mklml_lnx_2019.0.1.20180928", urls = [ - "https://mirror.bazel.build/github.com/intel/mkl-dnn/releases/download/v0.16/mklml_lnx_2019.0.20180710.tgz", - "https://github.com/intel/mkl-dnn/releases/download/v0.16/mklml_lnx_2019.0.20180710.tgz", + "https://mirror.bazel.build/github.com/intel/mkl-dnn/releases/download/v0.17-rc/mklml_lnx_2019.0.1.20180928.tgz", + "https://github.com/intel/mkl-dnn/releases/download/v0.17-rc/mklml_lnx_2019.0.1.20180928.tgz", ], ) mkl_repository( name = "mkl_windows", build_file = clean_dep("//third_party/mkl:mkl.BUILD"), - sha256 = "3fdcff17b018a0082491adf3ba143358265336a801646e46e0191ec8d58d24a2", - strip_prefix = "mklml_win_2019.0.20180710", + sha256 = "efef90b7b9613fab10f44c8ac4ff28db613a112c64ed94826d7e44df09c44b0b", + strip_prefix = "mklml_win_2019.0.1.20180928", urls = [ - "https://mirror.bazel.build/github.com/intel/mkl-dnn/releases/download/v0.16/mklml_win_2019.0.20180710.zip", - "https://github.com/intel/mkl-dnn/releases/download/v0.16/mklml_win_2019.0.20180710.zip", + "https://mirror.bazel.build/github.com/intel/mkl-dnn/releases/download/v0.17-rc/mklml_win_2019.0.1.20180928.zip", + "https://github.com/intel/mkl-dnn/releases/download/v0.17-rc/mklml_win_2019.0.1.20180928.zip", ], ) mkl_repository( name = "mkl_darwin", build_file = clean_dep("//third_party/mkl:mkl.BUILD"), - sha256 = "411a30014a938eb83fb9f37b3dbe8e371b106fc1dd621fc23123cadc72737ce6", - strip_prefix = "mklml_mac_2019.0.20180710", + sha256 = "83f02938a0c095274db7b8b7b694157abafa3837c5cbaef740440d466c86a477", + strip_prefix = "mklml_mac_2019.0.1.20180928", urls = [ - "https://mirror.bazel.build/github.com/intel/mkl-dnn/releases/download/v0.16/mklml_mac_2019.0.20180710.tgz", - "https://github.com/intel/mkl-dnn/releases/download/v0.16/mklml_mac_2019.0.20180710.tgz", + "https://mirror.bazel.build/github.com/intel/mkl-dnn/releases/download/v0.17-rc/mklml_mac_2019.0.1.20180928.tgz", + "https://github.com/intel/mkl-dnn/releases/download/v0.17-rc/mklml_mac_2019.0.1.20180928.tgz", ], ) @@ -112,11 +112,11 @@ def tf_workspace(path_prefix = "", tf_repo_name = ""): tf_http_archive( name = "mkl_dnn", build_file = clean_dep("//third_party/mkl_dnn:mkldnn.BUILD"), - sha256 = "363cc9239eacf8e7917753c6d8c94f767e4cd049160d0654a61ef32d5e1b3049", - strip_prefix = "mkl-dnn-4e333787e0d66a1dca1218e99a891d493dbc8ef1", + sha256 = "b100f57af4a2b59a3a37a1ba38f77b644d2107d758a1a7f4e51310063cd21e73", + strip_prefix = "mkl-dnn-733fc908874c71a5285043931a1cf80aa923165c", urls = [ - "https://mirror.bazel.build/github.com/intel/mkl-dnn/archive/4e333787e0d66a1dca1218e99a891d493dbc8ef1.tar.gz", - "https://github.com/intel/mkl-dnn/archive/4e333787e0d66a1dca1218e99a891d493dbc8ef1.tar.gz", + "https://mirror.bazel.build/github.com/intel/mkl-dnn/archive/733fc908874c71a5285043931a1cf80aa923165c.tar.gz", + "https://github.com/intel/mkl-dnn/archive/733fc908874c71a5285043931a1cf80aa923165c.tar.gz", ], ) @@ -134,12 +134,11 @@ def tf_workspace(path_prefix = "", tf_repo_name = ""): tf_http_archive( name = "eigen_archive", build_file = clean_dep("//third_party:eigen.BUILD"), - patch_file = clean_dep("//third_party:eigen_reshaped.patch"), - sha256 = "d66cec3b54b3dfaa4666c1d49481a7197f93fc078cd53c54e2b4a8893a529c9f", - strip_prefix = "eigen-eigen-b4890dc6bc34", + sha256 = "37a483ec219c43219b6e0fc07e799277a4a36abb2b9f4162cfcd256aa211eae8", + strip_prefix = "eigen-eigen-2e50f4a5542a", urls = [ - "https://mirror.bazel.build/bitbucket.org/eigen/eigen/get/b4890dc6bc34.tar.gz", - "https://bitbucket.org/eigen/eigen/get/b4890dc6bc34.tar.gz", + "https://mirror.bazel.build/bitbucket.org/eigen/eigen/get/2e50f4a5542a.tar.gz", + "https://bitbucket.org/eigen/eigen/get/2e50f4a5542a.tar.gz", ], ) @@ -180,15 +179,15 @@ def tf_workspace(path_prefix = "", tf_repo_name = ""): tf_http_archive( name = "com_github_googlecloudplatform_google_cloud_cpp", - sha256 = "fdd3b3aecce60987e5525e55bf3a21d68a8695320bd5b980775af6507eec3944", - strip_prefix = "google-cloud-cpp-14760a86c4ffab9943b476305c4fe927ad95db1c", + sha256 = "3ade2072e6588ff56c0434abe6c63aa5f3f2d56be15a299bafc7e9cdf0a12c17", + strip_prefix = "google-cloud-cpp-0.3.0", system_build_file = clean_dep("//third_party/systemlibs:google_cloud_cpp.BUILD"), system_link_files = { "//third_party/systemlibs:google_cloud_cpp.google.cloud.bigtable.BUILD": "google/cloud/bigtable/BUILD", }, urls = [ - "https://mirror.bazel.build/github.com/GoogleCloudPlatform/google-cloud-cpp/archive/14760a86c4ffab9943b476305c4fe927ad95db1c.tar.gz", - "https://github.com/GoogleCloudPlatform/google-cloud-cpp/archive/14760a86c4ffab9943b476305c4fe927ad95db1c.tar.gz", + "https://mirror.bazel.build/github.com/GoogleCloudPlatform/google-cloud-cpp/archive/v0.3.0.tar.gz", + "https://github.com/GoogleCloudPlatform/google-cloud-cpp/archive/v0.3.0.tar.gz", ], ) @@ -348,11 +347,11 @@ def tf_workspace(path_prefix = "", tf_repo_name = ""): ) PROTOBUF_URLS = [ - "https://mirror.bazel.build/github.com/google/protobuf/archive/v3.6.1.tar.gz", - "https://github.com/google/protobuf/archive/v3.6.1.tar.gz", + "https://mirror.bazel.build/github.com/google/protobuf/archive/v3.6.1.1.tar.gz", + "https://github.com/google/protobuf/archive/v3.6.1.1.tar.gz", ] - PROTOBUF_SHA256 = "3d4e589d81b2006ca603c1ab712c9715a76227293032d05b26fca603f90b3f5b" - PROTOBUF_STRIP_PREFIX = "protobuf-3.6.1" + PROTOBUF_SHA256 = "1ade182f91f0fa6c6116195def5d22270e01b9d03fe91319e4c6215022d0d24b" + PROTOBUF_STRIP_PREFIX = "protobuf-3.6.1.1" tf_http_archive( name = "protobuf_archive", @@ -473,11 +472,11 @@ def tf_workspace(path_prefix = "", tf_repo_name = ""): tf_http_archive( name = "llvm", build_file = clean_dep("//third_party/llvm:llvm.autogenerated.BUILD"), - sha256 = "a22a9b4c3af50a52ba0015b6987bba7202c3ec8e1d40ae76ee7d7643638936ae", - strip_prefix = "llvm-b4ace5f3454131a3070ef7c11e19e42fc9a80b4e", + sha256 = "34170a4aa07e434dd537d98a705dcf1b3901f73820fe1d6b9370e8c1c94e9157", + strip_prefix = "llvm-0487bd8f42c8b38166ff825d56014d0ff49db604", urls = [ - "https://mirror.bazel.build/github.com/llvm-mirror/llvm/archive/b4ace5f3454131a3070ef7c11e19e42fc9a80b4e.tar.gz", - "https://github.com/llvm-mirror/llvm/archive/b4ace5f3454131a3070ef7c11e19e42fc9a80b4e.tar.gz", + "https://mirror.bazel.build/github.com/llvm-mirror/llvm/archive/0487bd8f42c8b38166ff825d56014d0ff49db604.tar.gz", + "https://github.com/llvm-mirror/llvm/archive/0487bd8f42c8b38166ff825d56014d0ff49db604.tar.gz", ], ) @@ -690,11 +689,11 @@ def tf_workspace(path_prefix = "", tf_repo_name = ""): tf_http_archive( name = "arm_neon_2_x86_sse", build_file = clean_dep("//third_party:arm_neon_2_x86_sse.BUILD"), - sha256 = "c8d90aa4357f8079d427e87a6f4c493da1fa4140aee926c05902d7ec1533d9a5", - strip_prefix = "ARM_NEON_2_x86_SSE-0f77d9d182265259b135dad949230ecbf1a2633d", + sha256 = "213733991310b904b11b053ac224fee2d4e0179e46b52fe7f8735b8831e04dcc", + strip_prefix = "ARM_NEON_2_x86_SSE-1200fe90bb174a6224a525ee60148671a786a71f", urls = [ - "https://mirror.bazel.build/github.com/intel/ARM_NEON_2_x86_SSE/archive/0f77d9d182265259b135dad949230ecbf1a2633d.tar.gz", - "https://github.com/intel/ARM_NEON_2_x86_SSE/archive/0f77d9d182265259b135dad949230ecbf1a2633d.tar.gz", + "https://mirror.bazel.build/github.com/intel/ARM_NEON_2_x86_SSE/archive/1200fe90bb174a6224a525ee60148671a786a71f.tar.gz", + "https://github.com/intel/ARM_NEON_2_x86_SSE/archive/1200fe90bb174a6224a525ee60148671a786a71f.tar.gz", ], ) diff --git a/third_party/clang_toolchain/download_clang.bzl b/third_party/clang_toolchain/download_clang.bzl index 9023e250b2..7ced902747 100644 --- a/third_party/clang_toolchain/download_clang.bzl +++ b/third_party/clang_toolchain/download_clang.bzl @@ -39,15 +39,15 @@ def download_clang(repo_ctx, out_folder): # Latest CLANG_REVISION and CLANG_SUB_REVISION of the Chromiums's release # can be found in https://chromium.googlesource.com/chromium/src/tools/clang/+/master/scripts/update.py - CLANG_REVISION = "346388" + CLANG_REVISION = "347933" CLANG_SUB_REVISION = 1 package_version = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION) checksums = { - "Linux_x64": "5e5564e4e743414c7eaec9fd9e739732ddd2a343e49bde4c88fc2530b1c598b9", - "Mac": "19271a7cc5c2bcaf9643d3dd622b5458569dc662bbc58f63b129cf6e3a4e3243", - "Win": "60b0bd1f11e53892109f4159e2aba0f803604823e07875ca98b82bd5628d7f4d", + "Linux_x64": "cae3643fdf5d46fc9bc8731212bb37573547148d90b64b083165e090133d11b0", + "Mac": "083a0e91a38c06e568652313ac7372b17a101268f7d65533d721ca30413442b4", + "Win": "43160487cfc7e88076a369a2b6e8e4a0f42e104c28d8903f3aaa62d630aba949", } platform_folder = _get_platform_folder(repo_ctx.os.name) diff --git a/third_party/eigen_reshaped.patch b/third_party/eigen_reshaped.patch deleted file mode 100644 index 7acfdcf9fe..0000000000 --- a/third_party/eigen_reshaped.patch +++ /dev/null @@ -1,48 +0,0 @@ ---- a/Eigen/src/Core/util/ReshapedHelper.h (date 1541195478000) -+++ b/Eigen/src/Core/util/ReshapedHelper.h (date 1541195478000) -@@ -39,6 +39,11 @@ - return total/other; - } - -+template -+struct get_compiletime_reshape_order { -+ enum { value = Order == AutoOrder ? Flags & RowMajorBit : Order }; -+}; -+ - } - - } // end namespace Eigen ---- a/Eigen/src/plugins/ReshapedMethods.h (date 1541195254000) -+++ b/Eigen/src/plugins/ReshapedMethods.h (date 1541195254000) -@@ -105,13 +105,13 @@ - inline Reshaped::value, - internal::get_compiletime_reshape_size::value, -- (Order==AutoOrder?Flags&RowMajorBit:Order)> -+ internal::get_compiletime_reshape_order::value> - reshaped(NRowsType nRows, NColsType nCols) EIGEN_RESHAPED_METHOD_CONST - { - return Reshaped::value, - internal::get_compiletime_reshape_size::value, -- (Order==AutoOrder?Flags&RowMajorBit:Order)> -+ internal::get_compiletime_reshape_order::value> - (derived(), - internal::get_runtime_reshape_size(nRows,internal::get_runtime_value(nCols),size()), - internal::get_runtime_reshape_size(nCols,internal::get_runtime_value(nRows),size())); -@@ -128,11 +128,13 @@ - - template - EIGEN_DEVICE_FUNC --inline Reshaped -+inline Reshaped::value> - reshaped() EIGEN_RESHAPED_METHOD_CONST - { - EIGEN_STATIC_ASSERT(Order==RowMajor || Order==ColMajor || Order==AutoOrder, INVALID_TEMPLATE_PARAMETER); -- return Reshaped -+ return Reshaped::value> - (derived(), size(), 1); - } - \ No newline at end of file diff --git a/third_party/googleapis.BUILD b/third_party/googleapis.BUILD index 95e999af18..b8871eda72 100644 --- a/third_party/googleapis.BUILD +++ b/third_party/googleapis.BUILD @@ -13,7 +13,9 @@ # limitations under the License. package(default_visibility = ["//visibility:public"]) + licenses(["notice"]) # Apache 2.0 + exports_files(["LICENSE"]) load("@protobuf_archive//:protobuf.bzl", "cc_proto_library") @@ -21,6 +23,9 @@ load("@protobuf_archive//:protobuf.bzl", "cc_proto_library") cc_proto_library( name = "bigtable_protos", srcs = [ + "google/api/annotations.proto", + "google/api/auth.proto", + "google/api/http.proto", "google/bigtable/admin/v2/bigtable_instance_admin.proto", "google/bigtable/admin/v2/bigtable_table_admin.proto", "google/bigtable/admin/v2/common.proto", @@ -31,15 +36,12 @@ cc_proto_library( "google/iam/v1/iam_policy.proto", "google/iam/v1/policy.proto", "google/longrunning/operations.proto", - "google/rpc/status.proto", "google/rpc/error_details.proto", - "google/api/annotations.proto", - "google/api/auth.proto", - "google/api/http.proto", + "google/rpc/status.proto", ], include = ".", - protoc = "@protobuf_archive//:protoc", default_runtime = "@protobuf_archive//:protobuf", - deps = ["@protobuf_archive//:cc_wkt_protos"], + protoc = "@protobuf_archive//:protoc", use_grpc_plugin = True, + deps = ["@protobuf_archive//:cc_wkt_protos"], ) diff --git a/third_party/gpus/crosstool/CROSSTOOL.tpl b/third_party/gpus/crosstool/CROSSTOOL.tpl index 3189cf8e31..921188cbb4 100644 --- a/third_party/gpus/crosstool/CROSSTOOL.tpl +++ b/third_party/gpus/crosstool/CROSSTOOL.tpl @@ -184,7 +184,8 @@ toolchain { action: "c++-link-dynamic-library" action: "c++-link-nodeps-dynamic-library" flag_group { - flag:"-no-canonical-prefixes" + flag: "-no-canonical-prefixes" + %{extra_no_canonical_prefixes_flags} } } } diff --git a/third_party/gpus/cuda_configure.bzl b/third_party/gpus/cuda_configure.bzl index 831a3067b2..03c67bcb3d 100644 --- a/third_party/gpus/cuda_configure.bzl +++ b/third_party/gpus/cuda_configure.bzl @@ -1418,6 +1418,7 @@ def _create_local_cuda_repository(repository_ctx): flag: "-Wno-invalid-partial-specialization" """ cuda_defines["%{host_compiler_includes}"] = host_compiler_includes + cuda_defines["%{extra_no_canonical_prefixes_flags}"] = "" _tpl(repository_ctx, "crosstool:BUILD", { "%{linker_files}": ":empty", "%{win_linker_files}": ":empty" @@ -1439,6 +1440,14 @@ def _create_local_cuda_repository(repository_ctx): repository_ctx, cuda_config) + "\n cxx_builtin_include_directory: \"%s\"" % cupti_header_dir + "\n cxx_builtin_include_directory: \"%s\"" % cudnn_header_dir) + + # For gcc, do not canonicalize system header paths; some versions of gcc + # pick the shortest possible path for system includes when creating the + # .d file - given that includes that are prefixed with "../" multiple + # time quickly grow longer than the root of the tree, this can lead to + # bazel's header check failing. + cuda_defines["%{extra_no_canonical_prefixes_flags}"] = ( + "flag: \"-fno-canonical-system-headers\"") nvcc_path = str( repository_ctx.path("%s/bin/nvcc%s" % ( cuda_config.cuda_toolkit_path, diff --git a/third_party/gpus/rocm_configure.bzl b/third_party/gpus/rocm_configure.bzl index 9108639b0b..6df6799bd7 100644 --- a/third_party/gpus/rocm_configure.bzl +++ b/third_party/gpus/rocm_configure.bzl @@ -105,7 +105,7 @@ def get_cxx_inc_directories(repository_ctx, cc): return includes_cpp + [ inc for inc in includes_c - if inc not in includes_cpp_set + if inc not in includes_cpp_set.to_list() ] def auto_configure_fail(msg): diff --git a/third_party/icu/data/BUILD.bazel b/third_party/icu/data/BUILD.bazel new file mode 100644 index 0000000000..7db21566e4 --- /dev/null +++ b/third_party/icu/data/BUILD.bazel @@ -0,0 +1,46 @@ +package( + default_visibility = ["//visibility:public"], +) + +licenses(["notice"]) # Apache 2.0 + +exports_files(["LICENSE"]) + +# Data for core MIME/Unix/Windows encodings: +# ISO 8859-2..9, 15; Windows-125x; EUC-CN; GBK (Windows cp936); GB 18030; +# Big5 (Windows cp950); SJIS (Windows cp932); EUC-JP; EUC-KR, KS C 5601; +# Windows cp949. Data is pre-processed for little-endian platforms. To replicate +# this pre-processing (if you want additional encodings, for example), do the +# following: +# +# First, download, build, and install ICU. This installs tools such as makeconv. +# Then, run the following from your icu4c/source directory: +# $ cd data/mappings +# $ rm *.cnv # there shouldn't be any .cnv files here to begin with +# $ grep \.ucm ucmcore.mk | \ +# sed 's/\(UCM_SOURCE_CORE=\)\?\([^ ]\+\.ucm\)\\\?/\2/g' | \ +# tr '\n' ' ' | xargs makeconv +# $ ls *.cnv > filelist.lst +# $ pkgdata -m common -p ucmcore filelist.lst +# $ genccode -f custom_conversion_data ucmcore.dat +# This creates custom_conversion_data.c. You will need to change the target +# :conversion_data to depend on your custom source instead of :conversion_data.c +filegroup( + name = "conversion_files", + srcs = glob(["icu_conversion_data.c.gz.*"]), +) + +# Data files are compressed and split to work around git performance degradation +# around large files. +genrule( + name = "merge_conversion_data", + srcs = [":conversion_files"], + outs = ["conversion_data.c"], + cmd = "cat $(locations :conversion_files) | gunzip > $@", +) + +cc_library( + name = "conversion_data", + srcs = [":conversion_data.c"], + deps = ["@icu//:headers"], +) diff --git a/third_party/icu/data/LICENSE b/third_party/icu/data/LICENSE new file mode 100644 index 0000000000..25b6eb9d34 --- /dev/null +++ b/third_party/icu/data/LICENSE @@ -0,0 +1,414 @@ +COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later) + +Copyright © 1991-2018 Unicode, Inc. All rights reserved. +Distributed under the Terms of Use in http://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Unicode data files and any associated documentation +(the "Data Files") or Unicode software and any associated documentation +(the "Software") to deal in the Data Files or Software +without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, and/or sell copies of +the Data Files or Software, and to permit persons to whom the Data Files +or Software are furnished to do so, provided that either +(a) this copyright and permission notice appear with all copies +of the Data Files or Software, or +(b) this copyright and permission notice appear in associated +Documentation. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT OF THIRD PARTY RIGHTS. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS +NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THE DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in these Data Files or Software without prior +written authorization of the copyright holder. + +--------------------- + +Third-Party Software Licenses + +This section contains third-party software notices and/or additional +terms for licensed third-party software components included within ICU +libraries. + +1. ICU License - ICU 1.8.1 to ICU 57.1 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 1995-2016 International Business Machines Corporation and others +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY +SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +All trademarks and registered trademarks mentioned herein are the +property of their respective owners. + +2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) + + # The Google Chrome software developed by Google is licensed under + # the BSD license. Other software included in this distribution is + # provided under other licenses, as set forth below. + # + # The BSD License + # http://opensource.org/licenses/bsd-license.php + # Copyright (C) 2006-2008, Google Inc. + # + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions are met: + # + # Redistributions of source code must retain the above copyright notice, + # this list of conditions and the following disclaimer. + # Redistributions in binary form must reproduce the above + # copyright notice, this list of conditions and the following + # disclaimer in the documentation and/or other materials provided with + # the distribution. + # Neither the name of Google Inc. nor the names of its + # contributors may be used to endorse or promote products derived from + # this software without specific prior written permission. + # + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + # + # + # The word list in cjdict.txt are generated by combining three word lists + # listed below with further processing for compound word breaking. The + # frequency is generated with an iterative training against Google web + # corpora. + # + # * Libtabe (Chinese) + # - https://sourceforge.net/project/?group_id=1519 + # - Its license terms and conditions are shown below. + # + # * IPADIC (Japanese) + # - http://chasen.aist-nara.ac.jp/chasen/distribution.html + # - Its license terms and conditions are shown below. + # + # ---------COPYING.libtabe ---- BEGIN-------------------- + # + # /* + # * Copyright (c) 1999 TaBE Project. + # * Copyright (c) 1999 Pai-Hsiang Hsiao. + # * All rights reserved. + # * + # * Redistribution and use in source and binary forms, with or without + # * modification, are permitted provided that the following conditions + # * are met: + # * + # * . Redistributions of source code must retain the above copyright + # * notice, this list of conditions and the following disclaimer. + # * . Redistributions in binary form must reproduce the above copyright + # * notice, this list of conditions and the following disclaimer in + # * the documentation and/or other materials provided with the + # * distribution. + # * . Neither the name of the TaBE Project nor the names of its + # * contributors may be used to endorse or promote products derived + # * from this software without specific prior written permission. + # * + # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # * OF THE POSSIBILITY OF SUCH DAMAGE. + # */ + # + # /* + # * Copyright (c) 1999 Computer Systems and Communication Lab, + # * Institute of Information Science, Academia + # * Sinica. All rights reserved. + # * + # * Redistribution and use in source and binary forms, with or without + # * modification, are permitted provided that the following conditions + # * are met: + # * + # * . Redistributions of source code must retain the above copyright + # * notice, this list of conditions and the following disclaimer. + # * . Redistributions in binary form must reproduce the above copyright + # * notice, this list of conditions and the following disclaimer in + # * the documentation and/or other materials provided with the + # * distribution. + # * . Neither the name of the Computer Systems and Communication Lab + # * nor the names of its contributors may be used to endorse or + # * promote products derived from this software without specific + # * prior written permission. + # * + # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # * OF THE POSSIBILITY OF SUCH DAMAGE. + # */ + # + # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, + # University of Illinois + # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 + # + # ---------------COPYING.libtabe-----END-------------------------------- + # + # + # ---------------COPYING.ipadic-----BEGIN------------------------------- + # + # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science + # and Technology. All Rights Reserved. + # + # Use, reproduction, and distribution of this software is permitted. + # Any copy of this software, whether in its original form or modified, + # must include both the above copyright notice and the following + # paragraphs. + # + # Nara Institute of Science and Technology (NAIST), + # the copyright holders, disclaims all warranties with regard to this + # software, including all implied warranties of merchantability and + # fitness, in no event shall NAIST be liable for + # any special, indirect or consequential damages or any damages + # whatsoever resulting from loss of use, data or profits, whether in an + # action of contract, negligence or other tortuous action, arising out + # of or in connection with the use or performance of this software. + # + # A large portion of the dictionary entries + # originate from ICOT Free Software. The following conditions for ICOT + # Free Software applies to the current dictionary as well. + # + # Each User may also freely distribute the Program, whether in its + # original form or modified, to any third party or parties, PROVIDED + # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear + # on, or be attached to, the Program, which is distributed substantially + # in the same form as set out herein and that such intended + # distribution, if actually made, will neither violate or otherwise + # contravene any of the laws and regulations of the countries having + # jurisdiction over the User or the intended distribution itself. + # + # NO WARRANTY + # + # The program was produced on an experimental basis in the course of the + # research and development conducted during the project and is provided + # to users as so produced on an experimental basis. Accordingly, the + # program is provided without any warranty whatsoever, whether express, + # implied, statutory or otherwise. The term "warranty" used herein + # includes, but is not limited to, any warranty of the quality, + # performance, merchantability and fitness for a particular purpose of + # the program and the nonexistence of any infringement or violation of + # any right of any third party. + # + # Each user of the program will agree and understand, and be deemed to + # have agreed and understood, that there is no warranty whatsoever for + # the program and, accordingly, the entire risk arising from or + # otherwise connected with the program is assumed by the user. + # + # Therefore, neither ICOT, the copyright holder, or any other + # organization that participated in or was otherwise related to the + # development of the program and their respective officials, directors, + # officers and other employees shall be held liable for any and all + # damages, including, without limitation, general, special, incidental + # and consequential damages, arising out of or otherwise in connection + # with the use or inability to use the program or any product, material + # or result produced or otherwise obtained by using the program, + # regardless of whether they have been advised of, or otherwise had + # knowledge of, the possibility of such damages at any time during the + # project or thereafter. Each user will be deemed to have agreed to the + # foregoing by his or her commencement of use of the program. The term + # "use" as used herein includes, but is not limited to, the use, + # modification, copying and distribution of the program and the + # production of secondary products from the program. + # + # In the case where the program, whether in its original form or + # modified, was distributed or delivered to or received by a user from + # any person, organization or entity other than ICOT, unless it makes or + # grants independently of ICOT any specific warranty to the user in + # writing, such person, organization or entity, will also be exempted + # from and not be held liable to the user for any such damages as noted + # above as far as the program is concerned. + # + # ---------------COPYING.ipadic-----END---------------------------------- + +3. Lao Word Break Dictionary Data (laodict.txt) + + # Copyright (c) 2013 International Business Machines Corporation + # and others. All Rights Reserved. + # + # Project: http://code.google.com/p/lao-dictionary/ + # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt + # License: http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt + # (copied below) + # + # This file is derived from the above dictionary, with slight + # modifications. + # ---------------------------------------------------------------------- + # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, + # are permitted provided that the following conditions are met: + # + # + # Redistributions of source code must retain the above copyright notice, this + # list of conditions and the following disclaimer. Redistributions in + # binary form must reproduce the above copyright notice, this list of + # conditions and the following disclaimer in the documentation and/or + # other materials provided with the distribution. + # + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + # OF THE POSSIBILITY OF SUCH DAMAGE. + # -------------------------------------------------------------------------- + +4. Burmese Word Break Dictionary Data (burmesedict.txt) + + # Copyright (c) 2014 International Business Machines Corporation + # and others. All Rights Reserved. + # + # This list is part of a project hosted at: + # github.com/kanyawtech/myanmar-karen-word-lists + # + # -------------------------------------------------------------------------- + # Copyright (c) 2013, LeRoy Benjamin Sharon + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions + # are met: Redistributions of source code must retain the above + # copyright notice, this list of conditions and the following + # disclaimer. Redistributions in binary form must reproduce the + # above copyright notice, this list of conditions and the following + # disclaimer in the documentation and/or other materials provided + # with the distribution. + # + # Neither the name Myanmar Karen Word Lists, nor the names of its + # contributors may be used to endorse or promote products derived + # from this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS + # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + # SUCH DAMAGE. + # -------------------------------------------------------------------------- + +5. Time Zone Database + + ICU uses the public domain data and code derived from Time Zone +Database for its time zone support. The ownership of the TZ database +is explained in BCP 175: Procedure for Maintaining the Time Zone +Database section 7. + + # 7. Database Ownership + # + # The TZ database itself is not an IETF Contribution or an IETF + # document. Rather it is a pre-existing and regularly updated work + # that is in the public domain, and is intended to remain in the + # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do + # not apply to the TZ Database or contributions that individuals make + # to it. Should any claims be made and substantiated against the TZ + # Database, the organization that is providing the IANA + # Considerations defined in this RFC, under the memorandum of + # understanding with the IETF, currently ICANN, may act in accordance + # with all competent court orders. No ownership claims will be made + # by ICANN or the IETF Trust on the database or the code. Any person + # making a contribution to the database or code waives all rights to + # future claims in that contribution or in the TZ Database. + +6. Google double-conversion + +Copyright 2006-2011, the V8 project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third_party/icu/data/icu_conversion_data.c.gz.aa b/third_party/icu/data/icu_conversion_data.c.gz.aa new file mode 100644 index 0000000000000000000000000000000000000000..b68a2c6516f8183e805c509a9139cf63d1ee3fa5 GIT binary patch literal 177696 zcmb2|=HOWCelD7UIWxI5J~=pPk z@n*^~%R_GQCsb}LBzQO6-j!h@)#5Wvg~>?sL&8CWKliJT{obQov~KJ7@>N=a^Phx% zeJg5g{CLX5LW#$+%kBR?zW--){ZIS<-T#l*|4;w_=ls9r_22CO-<<#Nng73|^Z(tf z|2*6NulW9-&;LKF|9AHP5B+~%&i{}9KmWM=|Bw0qzHG1me*ORL{Qs}a|Nnab?_2%f zv-|(d-v96P{=cj5|9f`+|C9KC&({CDYX4{T^Zb8j@Bho+|9AKPO56YO|GwY!3ACvEXK3@NK*Z=GFpKr@of6@Q{$p8PJ z|9{W_+x`FH`G1euP^_#{?2pzf5-oSjsN>} zf9=!%i|c>K+x~lf|KHj8zhC#){W-n=$7K7zo9%zf|9iCm_vZiq&j0`USpWaG{D1%C z>pp+~|DpWMuQ_h{-~WIAyVmCN z)_IzH>&`t_{ux*qcmMDI#jbr+birVrSo8i+jJxU4fr}PTc>m-`;7P zhwdrIQA_1br9d5={;o48|cT>aeNSDRmIU0Qwcgl*aR7|&TZzdxTR zGOy>S=_%7+b2ew6+v;|9J=^DOuHd7W=G>V4(Ddb}mtUUVUY|el`|(g^%}@K@y_-2T zCfa&)+4(K^)AWu`|@G&f#0jY*M9wN`XO?1+SwEP z+}C83?)&$xy7P_Zj^8nRmb^TceXY3sr`h~fZz{h^Eh=2UJN%<9)61^i>u0a$JaD#X zQ&vr!{_($Z-__SY(VF$F;Fk3iw_jg%U;VrG(zL7eLqYlOw+m}@7hSKnKKz*aSp`X1Le|MKbM%U|7omwIJii2wc2y>35EAMRLO z8_{o@dP;tgs#?nbIPdS)f7hJ+DXhEqSXR16zV6;-$?xUwul(N_l_ekjtN({zZheP* z?o0l!et&0Q{B5KBPoVg`?p68P<+b0xXJ?+jcSELvZWXP*y# z+d1=BW!-0^{`h-7x0jsZH~oBe!CXUbuVw#=yq*OcE0_71U3>ZV-5baLcn^U;8Q%Bb zIJ}?y;3N0(vxmR^$TNOveRhuQ*N@C4C;KO>&d&RJ$LHU{?GIDs_In#=7vGbgrD=ch z%<8Gf-(NbD_tept=bXP8bL4Mplg-oHXGhwvo_Y7w|hlqhIA$AKb26yW6e)`?O>BC$0CU z9kJH^{`thb`458j-3Hl~xorFV%V+!zy5`Sb`F+{vAFBC}r&sobAO0QduRUS z{aa{y?)4SkwLdwTf8BJs^!T~C36F2h0^NE|({Dd2c{82=?LE0~%Om4I3C>SHr+HY< z|90Tx>3^KUe-j-CM6)xn?hTAo=)mp2z2)d8?}A7Hb^7H0_t~(Jz~-C3h@;uqrynG_N9* zUw^&iR|%b8d%YK|^mR>s`trHO(-);ZjQ>CF`~B;Y&aJOK_0o5IAG6=(=4FMWUSUY-@%-=F@sXFkU_@8$1JJCzsz{&;-9N^^_mdEKdAKdp9>bBDO+YA)U3PN>*D%rHcvjQub1DywaKt_se0y;|YJ`Ov?QCqDaf zz9;JExr(3Re#hG9^{<_L`tq&6*{e5w%Jy-L*u87wU*mGi%>9&i3q@bhcM*NUR|SCi{&t_=oc`>3`-#+uAPsD7rs>{RCSN&Ew~DO&-qg|H~z}1cZ5Ke=6R8 zuw-lW^gGQh=gOxA?QzeJ{rLIgsZbji%j4(wu(JHQ^Ql2(bHTCqF~xu8hzop^J0xWv zf0=vj2c61k_0M{LeJ)=7JuYbfzq`*@H?8N|r}bmi10+U#GOO9bJNB3VexCUL{?mVv z@8`eOE#6<>|NHr#`gPmSyxeJ9RwW5C? zHs$+1-@fc~^y!~}TR%r%{s|VYtAF|FT1jR0u08#qe|t~gzU*}L<)>?(e)@Om=~|FX zZT8N6`%7xGckQcxynWj1-`>}^FMAz*`Rm%Jzy4i%yY}U`YbDj$JNND{sh%I7@4J2b zwA;VEw{Kr|JNok9wNL;3yYzSM%YWBO>a%y&&$yNE`+fVe-_fW4{#|-J`tswoFF#)U zR8jx((QrQ|6N-D_xB@c%7&*|5M%!_E+<>NOUIu}$4l-r`V+5kczylSI;4C6 zQUuN!uh%SiRb^fK_uHqBkNfv?)rIbYP+)g`j)+tw-k+9~XIhfYmcy~%sKoU!KI8`GyQO`lrbyJT{Y`V#IZ zrxmN}@~nPnZavyAA{Kp7Hhk8S1v8iQy-ezzX57bKT(pMS_EGO7B^?#Z{CgMk{oxmRZv-CV8n?|IkZ29N*6?5iVxZMz*m`-|w+(=}87+I}`I zn{-TR=AAdzl^Rz5!5#CCeqQ?grKy&ep6cZE;PY}T#UCA?@~Jt#-WGfD!QtcFO%O`*xvp>=hphH z{V&TG`&>_Y&EmGoTXceAXm4iK-o=yrg33SL2wV1hlj;)MgO)QAq`S-%huchVZ z7tFol&Am76WJD#szwPijd5A^V zC%kNf>}z*V)yy-u7HRIUUevN?YSY!LJA$q`NUjmI%{~<$s%n~A6#6>ly|qcm%2u`$ zr;>jaf3&!mQnYYMpU>Txb1OD^?>#ZIYt#CW_A^bPobRV-O#gDoe(Uppk9>cvZo0pa z>E%gp$GEPKmpbY_#N)g^tSwp;yJENZ`P$5z`fnL;3%=j?p(urY#|_4HK8M^2u10L! z9dVH}pu|Y@>!KGXI##^h)9McJ)zhwHg3FlbMoc7#YwLvE+sEZ?gy4b~~rX>$2O89U8y`Jmw!fS!g zLuP!)kX*i``gPjrwEtu`g=WBdFA0t z6W83W`X9P+T~h4PU0tQ3uf18@@=g{u`_;2@+^G+}Xvga+F2<^OhjrPj*{l2yekyrX z{O7dLzJeb6wW^P@I(I}Vy_m+aYpHNfuJe4Y#+&-k$Yy?^(v{0m<56VGRuH`wl9_V)aq z?SIRk{w@E#f8OnhyH|xA4z|DQ7P{M)_v!U#e^+hRex982b@j{jyO&1a=Kt|-npHr7 z`Rcki;WKyKy61WAD&KsAxOA7>_pX$`f3mYmuQI+)wZGDpg-!Ifp;sBp6xnl$`yB)K zObTa@uiyUr*;eMsDXv*J968E@c2<4$^R%4k`{BzQ2KCii4^F*qjbp!Aw|3*)pyda( z4Sz`q?k&73VLMBX|8CXad$k%*RBwMto*x9KtR`9o4D}c$%(&9@84^T-+P1g+jfcH=bt=YQoy;!CR8tGRu@E@3DK7edhc9HT!?93BH&n=b0S# zLYx;! z&y~=+J#|mg$|tT-A1~UQP7)3OYn^g3+xD#lyY*eaeWHm^w3cXE$J*peeVjJ+#X0Tc zi_?5Jhs#gZQB~HQ8Kb-IlEQ1g&l{Kj&pw`T_ho*P+KctqqA!a``Z(&J@?=!wzg$)x z?5U`Dz_;jXbLUje6D8-j+%TQK>)C}q(?u<-ZB@VN1$Q=H(t9S(f3w8ObMoO#-_CO; z7jsT_+d9-r&GK{RpSJ8y&^=r6WilJGyKm|JH{BdlrnT~^&-S?mn=8Dk+RP@s5}LQb zPjAwx%{~WD$%R(FxF>ci-=@0ut8DBm*FSy}cU5n`rR`Jq{cECir`gx*HMiq;X2@6f zo}KsD)%sF$`-I3ZDe7J8HvNC2xnc5}v!0Xd{^v+JuWeZ9;;8;@fv>Li+E+{cH>&4- z=elwAy}W4uuc;g^)kW`GEM&K8MxOq>$MFB<1h?{M=AP->vTe`G-uH-f`^<6y4e1Zr1Cy%GAV^x$M`4RX*O0 znNz~%eA~ZGQum2#L(korvXTznRmM6|3D$X+E;#V) zxW4MQT6stQ&Hb|bMgH~s8~@u)GD_t;cSdvL^XcpMT#4M4H!aAkt*l07KfkU+*i*hK z3yd3t7pk3WxX2m4By{Cl`AJ7a3C&Z95p?lcU6#L9CN1icC%1X#!)1pK-K~%JE?g;H?f5#S+Qgl)c*)!~!CIN@ zDzbJLjRFs8Ev%R}?b~8!ZIkuY@3w6>uyqc!uy|i{ZsRuj-!}Wcs7}#Q?aocusOi&m z!{@$?9*3sUjw?~KT3GJrpXp0X(n(!Zk#aQhB+IUw)(`IODc^P9PMFDi<-S|ms(Tjv zbNg^`uXal7pGWT$bSLUv+WRx5@6g}B-#s^6ZfDE8eg6=Y<8sE>LXTy8dT@3;2b`**It`#7-l zkN;bfVE$eI%=48;whCUrc;(OX$o&wc7Hc&~-N|^e1^uyL6-B^^-}p6|-JnwmVaHM`6jWqhe?E z=FHhV;cHY(p>ehOdzC5vy-ibhpWJ$h&E-y-_|$;R+>of7-)~-*=JEcV7e6^T$w^OR z2cx|4o|orerwM%ZEMZmLp}@lKen8>*E4>r3xj$vh1=^f5(=W$QXjoZjm$8128Y6G% z;u&>1=Pt~$RI&fgI5}&tKU-*ketM5sP3+y0AKX0k z^||RKOTv$@>y_B%k{oTats`@Xd$xIPP=xK;Eq`xnAIVE)zMa2+a$eOpqq|(I7bI)w zCQWx-k+%FKi?;H#(sh~_*7i*<`)MI<_jlI$ozv!;EuUIqF!Q@hh`N^g^mDFr6HNEs zmFSY2CE{7+|2Z}~v|{gEpLJK#_Hu-;`c!?U%xYS&QeNJggypZU$W5=cdso6A8~SA1 zOXnR=+;JsgpVjR4z9$QX=PK8PoqKb1rfsQLcFr_| zHFJ5GEaMmOWfv`dqG*!Wc=2shr}ioS>G3v;JC~}-aj$#+=*sgs`7-}_53EWR`mrdC z;mfR3sftz3?Dg$?t~kzbm}~B`W;NGimuY(^Okr5!G>xe)<)eS(7soJzd+uVk6MpQT z=(um@Bp0U3q2l4>*#P2p`z#q3+DU$`p5JhH{Kzj<*8o_x>p_i>Kz zN#};Qb?aJ0XDDO_8F?~yE^&URB(q9mzR1t0@_)}vxPI)KX_mF_f~ft1B(C<&Toz~7 zUErA0(a`O&`i}fMh2O_SZ3`}ZNYk^mHoZPi@zkW1>v=9tRo0zgae%Q#DR%a@Q_F5$ z;&^qIXJ5mn>|c|8K5Xf(T=F_(&a7p#u8K+sd$=)Q>Y8>psq6PUPl41nZn?~3+9u)= z?}{3F>y|$H{ja}I1a z^p=-BRH!TvS+r>Go7(0pKc1`YE4JIe^^w_!Nw;eQo+ZvW^5eC(so_rkeK}JiGZXX= zUr9IrWi+R3vEJn;uR69!wnnC-UHc%#}{QQ2Fp+4&8_;{WZ>PDqe80+xrj{_;UyN5!byv53!0B+TwJH& z^kVQS*HdOV_Dvd$x4cRw?qwFNGx94Wgl*@e>$o0JZt4g&r;UdoyImQ*3JDlch|7{yq_>ZcGo87@Ul%E4l>39UbXj^ z>hJD!esWx?z(`=?g@e8?L<8GeE9W;(vPwy6pVguya+O{6`;8^X)Sh~&JDy=%J3~QC zc*Deo)ogz*vzY2@Zp_`~HziI`lieb~RfO-Iif!GSxy-Y2?StCvnB2l2t@c|a)6eHP zUGc>xj?aJ9nUzx)2kr{>S!Wtp=KNhNMC!*SJM*ayOBG$FKd4ojdH>+S_uspQX)c!Nr-_Yno7e39bY|i{`I|F~nm3(VwqyZ!*U`7G(j7s^ z*{+LeHD&HtaCC-;N7qZ{WRB_IpLAz@4)JN_&sdNov`pf;)~&u3H%uNDxN6S(zCvMF z)!vDDhZ(LK@R?fh>N#t9>1LWvSn3@0q?sc`@E~{OTc;1ZB=VOCU3ZG8(v0}yXEY`E zaoX}(eqk49cA2bi>X~*WJcQBJ<*Qb~9-(!!UOs)LR%_Yw*(W&EP5(mLiD{haeXm%q zv+pqDSyy@~tLo*S&0#J^jZaU!S@g;!AvHLOjl)I!-NZSES+0Gl<kC&j;z=QKE-?C^#6!8FF3<~%y*o^6@!L(=$u_>sobw+ntjsGjGg$WF5QZlZTqV?v3VU zCJmZK|0nc(n0G2QO^!`v_R*8ilsEnC;CX%W@0${<*09=+P4{MMyt4aCgm@MjqyCD-I~+ws!7KE?*F*dpzq}>T=-~;Q_)X1*&&vYFFtx zY;P;@{`&RPSA(-Lv*dm3Ii#edBp*qw>J$;ESbx#is6R_+R<=W~pdpi&Vi&v1Ckgij zmwP(j$={r_=hv3YS?A;=_A)Pjo&3IpKkqc#ukUZZ@6Sw-@UmXbo%;W7k-go`WwqTb z&s;CG*|Cm#YZ&x3_6{?uNTtZ-jQR?5df7r^W2_65J_T(vN{lW{} zYhQVuHEFuAeU-}LcB9N!eh2z@J3Qr?r6ZGd-}R%0a_+1}ho-aa48HPH=p*mNzYaIG z7IJ9$8h#MTZu4E%a3a=I;+y=#3%pa;aUG2eygkXtleur|x(E9-JW`hK3cZ-H_WaSs zl}|Q{YKboVcyE4MbHS#0-ql@gZE0}_ww?T9a^@kvto*WZQ7|!m2{ByX zmGL5ht7-0{&C5GpRW5XiUa&S=(Q!L#X>{hgjfbW#sO>h2F6Dcv6MpgTwC8*o9}kAQ z&)dCVzP3oYX`$|n(ylpi+)NP`FGVD6W_xDXX9-+8HBn*z_ne@n622*+PS5*d0wV=W z%uWi*rcJT`1+wWf7E^8(_obKiBSbFqAf6bATcT04(=&?UCT9Vxod4&In$prl@gDJ)@ z*Y2A3d(-EM^{$5D)q!h|-qeUx5e|=G=X?A5RPl?OI>(|}HuD{u!fTo)JXzB2=~OcT zk0nR0K1nn+jJ$bqhvD2^4INjHt(@+%)HC$*lj3!1)0Lyoy=U6V`gFHKi}F zq&`*6+TyQpM6_y;Q(L%P*y5ALclZxVyUsZ*$}=f#;m4!Cn??OT1+v^=m9CTua564- zyml^BHCr`ZK3_L%+Z?8ME4E1Wyr{c3{r&IC_S_1OKcQ!qi<_*>Kc;BnwrjbQkNcP1 zr@ut_IR`W_tMT<~ zs#Yo_W#@{-PqUyTV7!x85po z37c|dN?JlLr^n7h%fklhljkjzy5?f5VaPq%;cxiHI*~W$<|ux;cGolQ>vGB2H`iYZ z$CuJtD%+(<@{UE_bQ;*w|{B) zEuZr1S&NG7#TH-ITvfDUzq+i%Bb_61xr%dIHU%+H{W~Yr%ZT*|*IvEv$~!LcJkZ}g z_an|HEslSFc_CRkcQbO8j~5uE)EQjrVh#xnw1|9_31FxbZjju9GQC zsh~?Tzt0(=Yq^hlC!EuK_#iIIU!#7(7e#MI?cL@Uf)nnr&Rf8u>7?v^+Q4RRyR4zp zYxkE+l*L}25VMN3(vp-F$csP3c`|Lq;uRMq->*BmPGzBQ(+h_v8QHl#dMo#O6&UZn zbjnyopdgNaOTmXI_l#wp`^R*z0O5}y4H===E`An z7w%9Ezp?1hjFD`p-!(CC)7dTYw!$qSbyEo8r?zU|SZ8%i@@O4Uu6JyWgQ zeAD~wPo^wh(&;=?4!xtg+L13&Dlo|W=m`K*lUO)0$$$@DV~L8j~s zr*!)+=-fA0oW7GY+#^t~!-VC{YuPCxf8QGP@!A;{3jf=N`pnMI4Ed*AP6)t>O!NaBP*q4mS;@EhCM^snz+bxx91GjQUy67QNbmsO(^o@xiB zn0IuVU1eNt`e6T>`@v^D4{j2zFqMwzoO`%W^C7!ilH!+VjQ=w*=F%pZ$``oo$31=H@3Kn&bUA6QebOJR)g&C zBE_1COLkQl>)xAsH1*~g=iPxH*Tw9aD=y*_wDDr?^Wcu3kM1{%zp7jKPJG)Ox0z?w zhAO9vS}d4#^VEkp)_JQB6o=-8-ET?X{Bmxjm*TY0FY-Azlz7W>S*p_nFLl&B&NOax zl2?7`dBF9m(ur9StFAUpn|mmBX;R+l9_i_=?MLT`%S0B5<%vaDFO<3T>3N>%dN(7T zoT9t?qT6ogY%yzZ^?mkmRpj=hYr4NHJ^k7%_teH+dv<<z5f!%uaG%emv#Ok;ExAj@J_===64V9?4y`yPEUC zK9{Pf11{E$yqjHn!nRy_u;ccp%fA|gv#Qn8-fLNU7au&T+AS%kckqs<%he+~i((g4 z=Lz`vW+m}1)s=XDa{D#kS2Vqs6)4vumn_V_>d9tq-B#sMo5HbVEq_|- zqWJj_6H=;Ujx0<+VlAB}>#@eFD&u#Wt4&F$+_DQdr8u^3bKbI5ciuIJP#@ z=k*CEm6pqJ&u%{*t-X!uWbDoxlRV~T7yR|OHq}3DWBZZjCZ*oHQZ6jF_x^ENZ5y5c z_0aq?YtN=$)z^HknOVT7(I371IhV|fNuKTAClNyS`~j zP93|^{##2~)ldAh^jtNGJuCd`k*d~)`)6ls3I&_Gh~~XM&cb|oN4L;{RKYe2$s6I) z+FkK8{BK)yvA8|iaC4$(vXHleKL_t7l?+#YV@}m>$(d)CiW#qn-|_yimS*hp_@y2* z(;9_RrM~ig?^r(7%-Y=e(As%-mswA{Gu`KC^P;iGIIMJ+ET*J2_8k zSXMg)#hfh_m$|dWBuMl53+3p&Jax%8HWf!ynd@AW7F*8y*>l=e4_6=aM_c9x$1%0mg5^0?>#7Gi|O?hU(WfGO}P2(f$Wb_f!76$V?rNGr%m<=l)LHK*j^#>)k}#*@Olhe`o=Sj5xcf`x!Q?wEHp{mogXd7WmvHES+vn~ zwxUg~-u*e}JZ*|S7Ja(BdetuVY2JlX&t#`=cHr()iQexsdDjfTYo%qo=J4~eua>y0 z&}?<@Z~d($+orOdhO{|6MoP`{H(H%$DHhI7yLyH%^+<$) z_{plHS0xtxSoHGsiHQ3@mZlV^D+`)Fe!{@UWjUkc@AXNmHn=~_)H#~9FEefBOxvo* z#oM^1uKRQ5n6_i2LTYxz+pGUf#FW_9+BatOAGPG%^ZG*k&)KV1yjF-16@71y? zvs#1VERN1Sbk3ZaWtK(S)J>Jzo83;XnbfxC=Nh5@)YCIXoJ>#Onsl}G64$)!nb(V? z)Slc7&|1T8Wd52@YI%dNvC{G@yIQVHT-!9mQRzFo)HVGr298U5E~Pp=*d%E+`(ul% zbeNdShHVpeDlQUUU-WSCQzQ1`MA0*=eRp(lI+@)JQeX4L?^LQBuY1$Z$tzs;Ui~4J zRm1x^xgtgLhGN9&u(=LDRE^Vqq^nLAy5lps$xdv-e$S@@a$!#sH+=|JF}yBz?Jcjv ziM{`YuWxlRIQz@w=(ek7zb|`y)-zf)SI>9v!zulaw#OHrI`rnLQ}=tPmT42ZRlocb zdaF|NtmF2>)jAnUndcW+ng0spXZ#d-gT<3cl&f&V4DNX)3y-Y3x%2-!^$i-#zGi`X z+>Q6=?M_PBa+vqus)Fa+i^@VTuE;p}>) ziH}y@$!a`zp- z-7j^D*-pl|a@8dT6mB~=`|q5Xwh4QD)mCp<-7tUl+=d3z!vPmobN8JQc5JDul+(_! z*{yb4YI4zEiM!X289$IZ_H=iQpOI-rE9Yy4yX$f*yBnOwe*?p`173X-m1mn)>aoaZ|2C4_eZwSKFiBu$ddwP|hm)V_tkG`I>ig;R zvM=<0ewt^NO^1nnez%aYo#jH;sc-M-F3g&Cu-dt&$t;^K;y}K#4fmd|3BTW5KUJi` zoV-aV(DQ>fhd=k1XYbw_1RFVD65?swdcR`&vvp=2lg})&{d4kzk-52s_q3Fkt9cf% z&)5<4?)HQ#zhb4d9PT-s?>IggC2zK=`j?V+-t+F(>^T=j78mi9=>=T~ILYhtD$2EJ zx$L^dMPDthJx>>YS|t*H>7wgOzu4aPe%Cnf_cy;8&CWSF;qimU71PvzKNMOY;9SRK zvwFXCz5ZX(zdL7krscVmAB{Y@$%CCSRj}c}x{}T6cXPbWH(&0x7ro;@$?TFgmkX@J3C!yD2!n{XZjjY*5A-U5Pm8TSpO-DP$T3fLE1L9m&c)f> zPpwv8{hG0DUQ+wx4_<4h`{q2-xxlNR&bTN*CuX*IR9fsAorOQd{v>XVK9$wC_12_i zw-&d*o1Je^Oi+gE4BeqZJF zlPneSmXCp@H#|a3ZfGxvcV&$I_N%~xqwqk4%hQtOV$3szvo_cWw=FyPwB&}O=E3); zd7_Wpb>x)E_-as-|3tFDyWg=^_TKWJUG2yIY*i1h;I5dHdGFZ0br0nAX4^O(ofOp< z^00EtwvxSPZr{khc5h?Pl8JtoE*Pj3@>{4pnH1d4s^eE2b(VYUqb_J)T(&T zHn}~^*J&%0eucv8**dDNj}_WKiaZN@B&>JvjnUCVJzT6ud!}A{7O(!Lm+O|s>sM18 zzBSGbWw2xYTkT5<>2Ef3UyA}Cs?Q2dOmHN zdC8TDeaeoR8*-bnPTdsq=8WGNsqVsNeM)9#(Z%zR;@?PecYm7tKwJFQd#k7=!W|oh z=WQ0wQ=V?2>LSOloqp)+Lu;*ro)2HydrnK~4BBLLZ_2%U0@YWJzU5hPRE002(?06Y zHRj60E$u01rnkI2{re}YP`^F9?o+>C9?#0(>^GWuapp-KzAO2s_r;t`ea8`}5IIvT z(reP2kH@(9tN)hCTbz{%e4Q3tWgqLZMUior=4os;oqco5hm)7zur9dS zw(q9K{bSRs;%ai;R=D%8QP<@CeD>*qJv>|X9Xa)Illju+2eZF)mRJ<#vMrmmT6wCL zO4YP^Y7cgP*SIP=(^yL^FrX<)I=t76`{`51tmlp1;tcsyyJ|hZ-h3ohzDrJ%^X{2x zUsb%#KfD$$D66!7diFs`h3L=so>#AbRR}3lR*^fkS!3ZRjhm8IVLRq?aWB!`+;Drt z+G>f5BAeCE8yL-(OO5uHZ=dpc8UNW^l_4;otoN2XnlZeRI)I;AN9Zqj9c4F(k zyyQ#bTFuu!4;3_a??~L3bI0equI~!R7t>R@?k}1m_J}P$T-g2Ul>M%vQ9D8={9Q0p z)WCbgnTtNFqkHpQF0S0$_1MxQ&3MVpO`Rf>dJ`3o7Pwv({UReeW9E#BVd4qbo(MGQ z)b|Nq;yWU3vF}z<-<>&1?;{FCU(MgHm7RT~O)l(URpj=$$4l5gi?lM$P>u<&(UyV#dRhg{TM^y1#cUFV}N{#uqcd*Y_Ftuia}vU59wrY#D2QDw&6CM8%? z;4iR=>GH|5nl9$)K8sDSO`9EewB<`f!!@~U2KDzdpP!hnzAM9Zx^DH-!gEw!|=HpEQONh%voFDUQ7EJ8V^`U(Z5A(8G!m!Yew-y{x?SPHw2d!SuheqNMP3Sw zl9-`u5+-)(M(fv^HFMLRUwpLbhC*VW(cFZ#Niu5|GW<{v+`jt8q0Eh&^%aa{f6V;T zJbP}^+|yoiCtlW`dEK?-PEnUg*NbgePJ7Li@;gfOm!;eMm zT`Y99Gib^7XYZD(n5$1XxoOjj^9S|MIsr03gszynKdD(}?7H&J0Hyc%bA2_xj zaD942J!{jnW${Xu8@xAtY@Zvfy6opgBhHo1PG9D%$vjkh`SJ7Lvo1_;P>ft^|H|X| z>gIz#+Ga33K9>@auw0g@if!(lDYt$HTQu+Lxs&XWca|wLqh$Hzl~=16ZfI{QRII$w zJGq%h^u_ZJUsJaGobY_(ui?vonCmoW-}T>XHYHf!lu(rpx&4wQy}f~F{*<4a{+((~ zag+3LjcPvdtml}0Lf$#El=J5qPPi9G&E3cRkoAyH$cNNT6*Kd;S%wx>n60>zRLxNR z`efM4({?T?ig63VHs|se&6s+-#-hD;XYPf~xhFrqR@t~-{zj9mZ|dxmt5ogRA6(jV zcxl5y{>g_~i*`ul>5_YY~^@3juyn3!-xS0tb)lDEK@aYN|u2JR`z8tVzoSND%EuK-)Wb1yB?$#U6ZmtdCRgQ zcB{X>mch?gpY0FNJ>#kf_l}&k6TI%QpJRLb{#wba z15R6y7nJrFZ}$q>zA9wA)6%jJ8dH8O$+0)!m59hs zR$IZc^k0`p&diXQfU27oIvLB)N3OmxSwG`^YEVIBzG_E!@TV7xqlKNmuW!ELXr(vd zmdvVO-%K31XSNnee%oPjMqkBqHbaiV7vmF7muv3i#+0s`CY)!-cI8n)?S$#4%|FLx zzYsq0*gWs9?{D7bg?Ep{PsqG`e(lYcOYWPN&rk9Ev(GU0fSgQAr-mtOhP=QJ0i`^H zst4B?PA1;Tsueup&Ro9heyzNfVC~B!9;=zhEWMQ6K7E_M(awF7n8lRk;&XK(`Ok7p zWW1G;Kc~0yp2ELPn(lixcjuaXOn)4tWgapi=f`Z@>zn%5PsMbI zHTIsAP4^PY)!cvbZNSff`|Y+rB7VDmk^KJl#&gD&oDx;(+>_hh-g{)TartFVhNlfY z!aG7l4*!T)C4Sn>jFbJO>8Z~a54rrZ#pBM!I%rG^bUt9kyv@p}a$kVj3Iz%N)jHxF z+OuQCgg)#}R4BNSufY~8;Bbxm1RImSY~c&diZD@kYu(FT0-sMh?(qFnmX_RhlWnfU z^dpi>175K8m`kZ&DKYyPtk`5_(-WGr*6EI7jFe7Y^Qy`Sqx^8IYes#=JN=j6VcWO5 z?e(hGWWGZSOx(E=R!qC?_<&12+}ZoM)wziBD~{qD^wuBFNNtb1Jx``oc!|GXm)0AH zr`(|$_q)FKooZG;lW3DKv48XX+S>DJ=X^4ho^Y6Si%eEI6tc-@_m=0JE0ebzZ*OpU zw?y>P(v8xl91xpbnU=&Bg?+OE5- z(qolkKkIk9migKnA9$`69J(%X{Mf5p1Cd;Zn`Y5_O=dscUMYOFw{{zss*aL>SIg^a zS>J*!C$DhNIk&*5yL8s!#5_-%c^hW4B%FBh<(c*w?ddEP>-YD)>8gpUOW0(_<*Fg{ zZrk@j)rjjp4_w??oSqXHnN`g=7%?{=Ubb=uBBHa!Z!QFCC2!u z^e8APwPpnDT$yWpaQ`Vy*93R7M^2$-JEyU-&D`_w#jY7%3ifp#pHda)e1DT8`Td^1 zWv*(E@3dvNJ|^&aE_PD(e8F0Jq3216v*Y`QzT?hE8bWOjroMTjb6ZUVgd}fiuk}&# zwA}5x{MY4wN2S7Lm7Ih;OqPBVz2a=Hdoi}DN=mhDeawUN-7@sCp5B90)Jme`~-fR->Yt+hi+TdvN4~@$5+Ky{_ zVFH|%TImH76&u$r$lSGYablInjlPSRUhCU2`G6?CkRi%G-sx{^*2hJef8Bo3I5#j?aRUhH33Dr||hE2c~Um?kJfP81X|! zPW{kHmP>APp1Y}S6xKVeN{Di`Y4Yv+u})LsgZ`YgffAQ8 z0&kk^R95vreCF!9NmHUc9&v18$)9xnfPk0P+yregzp_g?3h^QnSUyOuVhK{7*|fo; zNMeEf$(5R&2Xn+2Z%%MG@#mGaR}!a} z)>uWU$kdrnxlr3zHv8H40-g4r%pcog`iey~9YehuB8zm^vxv@WP@c?ud|5&9j5V>V znfoUj-h3$hZu+eA^Ul4SX7K#>HV(!Y2VVH?xS!%KqNyV!BP^^u>FbvIq^9}@QxpY1 z7zkAqq_J*YuCmyx!l+!=V$Sz_R&U*RGlqz=13ObRX?%e zOTvtuJTDuS?S#!1RTgib!LZ1C`mN$brOlCN-kdmIA%5Z6Ti;5zS3O6o3lrBL^|=0T zy7%TQYiH!zol?({WS#tEZ|0`#u(F#5j;)?^3ktebTm|lN>r`!2^%GhXvAOn7!l~HW zD>q(PME-7VNNek0_leq;W|AJ3u|8sXL}q$Flakrph}swp-gj$$wn^?yVdI~_&f-jh z^z41#zNsyHW;AzEZjMFll5K_hYFWE)ZhrUrpy@7K-UCY?R_txuV)9^m+xH7;2bO9+ z*?D8_Ik_8&tF>ap;!3$}lC}o9)lO^vZ)S2y`IJGr%Vwp>&1IF@*QV#?Jg63qwYk5n z@0v^i)3P;{S3c~!Jwtu{lBL3z7al&RPS$^2lspn*SLyX5zJO5cb4&d z(hAwK>lLpcpNh4X`o(Fx*3Mp^*S9d5^QxctgxM-hZg20Nj+VYH_iJXC(C*26n(Pbh zd~dW$rJ7xw&|I*6XV|vclXKMhIc^>^zG--OcAd+n6Wt0n%U1YC#^;1e{4-#V+xzN` z7w@SZo6Qxw)^cR5?k@Wg>{A&I??ZUqv)8bz(3B5HZY@437+zG|>Gt)xEnv)_n zO8nR6I~wHk(VKeu~$g)v^A+A0;F%PuB=md}6K=t7yC-B)aB_5U;*Ujk?yNRM%N6 z*4%xRQjt09#fCq>3vDcJmCD3)mfDEctnw=^4NFR+&40}+Z^PHiE`Gn6p|dvj8S8;7ZTybwkNC}!)zOdsDnGa3$%Qj7 zTZ+8g!VRv!y{07Pzq?5AM#B3p)=#@0=&UR`BEDi>rS3wxM=On{N7jCR`*>4j>(;0LPMW`+mtV2ZooRokSmGVAUFkV%CcRnoB+l<)t+LHu1r9#-RXdI` zT5$g~xxaCJ8qc=RGmo&u-DA4Rr8~iyTUoiIUswB3Q_AgSw>KI{bKYj`S^l_0;c8V9 z(<{!0hxcwO){)@cjisKatH}3QM{d_uDH6hOa79N+ar0YQJ-Yem*E z+~uBZ7@D8=_THT*Yg?XPxUu1gXmN);`wng=)jdpeYfruV^2FifA~$cZGeUgN!p&PB zzi2%9Y)w(_^$+T|KL|TdVJLZC8J_#}Y{hO-iLdA6+7=5Y=&g=g{9AI~hsh^nH`=Hv z%(8#;Y1gZJVbc|lADPLelQCg=VrjpcaCFQ@llMi}mG*>i`L&{!XXQGw`_C9O*&2l~@EvoO|&m6JZZ1;z}{&9kJb=$coMhYIWi6}YquI>G&>z6lh zY&+y+#`e>)_Rodp`LpX_+pGVa6D^skrmNV=b!=~^%@Hxzck9}lPwe~G*K%yLkSoK> zZPyqtUy5X2$CRn1-Qo3RnV0M8OP5?#ua_$Lyr;}0-s7SJa^mu z`LtECQB@=Bkw?`JZgkJct)9N_Q1z~;+dkJEIu@@!6sr93wC|pqE1iq%re9sTaN)ti zl!>M8Vb@h8ZZu})|lT*EBNAiyB4(`;C=7oks@Ztro2hTDJ*hJ=VHse z9p6~LtFuosM}g~WOI}F{nV%f?gyuR_Run7JsP#; zb{W&+YZE?meyU#@)aCf~t<&~Dhkm{=P43j4bkJtf_gUOY&nGQ*RQ+2iGf!2+%yrLp zp{~6z9?#7FZGG+7M5`47Q?*F*DWAJY2Kq}S+pP?-5Q`=9)Y<<4R$ zlKq`a)2SlYhU!Ln(ZOAeQN9L51jmSz0+## z@5o9yK7+H#k*9c5Ux}#gD!Kmm$%HEh=I$t+7%ug5@@;RQJni;r_X1`#I99wo$#q9~ zd$oGn(yeDivp36n&Yza?eBt+Zr-a@f$#}axz`*uxTgQrX(WiDLoDu&e@JO#J;ny?M zFK5gfcORM<{`K(DqHX77((bK!DSC-1_t4bzj;UAPl>Of)ZfX&;uTNtcW1)$K>)Psf zN_`XLXSU7EZEnq~n3H+PEM&rmB~Jab#ddA_wT!Rnbqhy;L-1SG9sk4Q8#jn8YGu_* z{5tb!*VdzRxT22D)p-?naN@1w^ZthETTC-$t}MHdWNo|ijr;3OvnOibRIO9WDsr4Z zUw@Cea-{GBqrXf}J8y*Pv+SDA{P&^r>rGpv)=#=svFW?~{AU&`6uo!U?k-I9j$HR4 ze0i_-P6uPJp!w=~pN?jza_3dvi#_;s)@0+DbsE#7?-WZe_j2T4*;*p}ICV!ZbZ zdv%AQ{|d8fYs%_6RU|(yu&6#_vgDnQtI+iuajLwMbyhJo4jmr%`B`n;rycd?)F^$y zF1w!P=6e0q=Ea^Vq8lGw2}}><+^lkU*W)E8qpJ$tqPIMpxaP+95<{QRUeSKRNI68~Zg*$08=g-@F~orBpOSP2vIz^NaEi*TT%Cd(Jrgv1;fE-SDI!&Hjl` zZNvw@O=b-WJ+`;h8rasS?u2)f*vqXE-t1k+X3)Wc~%sMwg zt(+yg@M7G)37cM8JQoPm39JiWE$0~3so-vvz5SDL%WI%9mTTG~(B1 zHGxU_QAa9uHZM=%-hD^OJ-E-cIGnRS#A;Q6TiRWXrf#pRJQ~jJ#_0)^0tB-b7y3-F6wMLClIvwR?S;3*}C=vQevl9 zG|7lsI4@OiJ=(w3Va4(rZ$G5IOg-`4d}hF|;K{sYo?TxV=TFFqS3E9cKR6}$5G$xZVLSF_vb)90Nda@J#E@5SKW6U)qgdw;Vo%TXxf@qhBuw#0DF z%u*TO&3;8K+c#D+Wm_y(On6+iv@fCa@UBdU^jq4qpBJbp&E6MlUcR?R_T1Fjo;#oY zKD*>LPte-gZPMp5ypMIfYH&Jsbc)`!l<+F8h`gJkCCjy=y5#nq-Bj>UX*0u2=7$Omj&>>Z3~`QoH7^IF`@r+nKL_=&W$l zD#7Ygby=(>oguelB`&ZXzIc^Q>MgUBW2K8*8gmw>RQ@C$jr}~mJHvlA)JaTGWIp5= zo>h^bE1kyRV^Fu@fammtmU$gNn42!_$O>p&>+mnqwZv&EqX0)w!>4;+X1v^&I_raH z!bQ({iV2P-eyto$sWS^qgso~f6?f##+4p))ormd#X}`6798`{%izr@K_`54PCeEfr z?!`ei)o{i42UrjKFm#9PYYn(zHd(kg)i;l^$>G!?Y0fP+A5H&z73g&z+f*aE;nvh0 z5);~E9tgdS4By8o%lU7{LAB!2gRj16U7g6#_arIA<%;5z2tHl8#rGuG(h^c;ei58k zB)FwWQ9pLZm+nc?HhcbDcq+_kzTT0ka)(p?3pXcDk*ypI`<^(aapp%0-F~-UVM&|6 zjCae2?nQQuuS;Afw5-!+l)L@>nb4c;>#z9=^gmk8Ir3~k5$|iS}o-F#8)U|VJhxqYRk3^zaChiiNQSa2UH`th$H|t|!sV=)jX4t)^ zsx6nlJB7{u7PjfZ4o1^w+>>8%Ti=^|{K#TY)5$e%xjr9mygryJyYlos-V)w*lYLJ< z4R#cmd)Z{6?LNoNk&-_)EnK2yR93rFnJrEB*Pa=twz@9m;tS7NRm!$Z6GwA2UABoR z-DWaNUa-?Y3+p-KrpQ9@7&{U$c&% zKFgRt>ufU*D=vWjpQ}jJop;=EQOIPGDznN=wNbp-=ncqCwvwE}3 zrhVM_cxQ)vp~NYr=2YV?f_7@rld{$yd*QQMY=Ozl`bPbO5AEJwv3q*KVpG&~ks~rP zH}9b9WUe%?>=*Ez&SpJ!%2%q4LAh*{UsgHmSKeyU`tl>BF|vAF#v;!UgW+wQeC-MS~b zV|hh(J50`-v+=pi4PzUvU(cuC?YfcbSg7zR>3+6W{zm0lFQ@;Vc%#%YF-V;~)%8zA zZEo+AKCMp2IySB;sd&=*y)7QGi^rLjmZmiUu zcji%qU%i~jtZot|zip}Lxt{8E34#%EXS*am&9VK?b=R&~c76VT zU9N~g&Je>x`|~*dZG5szW!Jo}t!6(}7P>1Oeyyo|PxI!Rf8EJ(kG6+jjm$OH;O%(5 z;wIB1Kc_ao><9ic-dylX>-3+w(jubzTfKqTY?e7j1}qnEd&y4UTV)`^bh`WT&(hPL z%Jbr#Bcc?aYP;0eCOw_0yEL@HA-!$#B<|a83wWAehXZvu;vh^C%1s=WYT*`9nMUmW$Wvtw)^HM@STOYY{ zqyD3Y&zk8ys}tFuI?P(WL7L^o2KA(*o$Aq-d6=?z_RP02jJ+Xqyv1B|d!4^q*DTXA zuOlmCBp&Fn9Mvp%$@Q9L|EiYR&c+NYvt0jaT~vN({Y9>ub*~Du_#B>ahW!&9`dDY^ zmCVk)y27UK_Pg1-dzf#zF5@!e3OjV9JDDN&oY*6+mP1$KOBQZl_H)vbM_;$U3{zLB zzSg{~Td^#8N6U>at+GY09fjqMmb)5=*>z;xVQt%F_BU3`W~X!h6{qlx6Ezz&UTjcq z+cLd$!?dk`WdGc)>zIBpYq#<|woSd3&R*^+U)Q;O&{0e%k0?EEFTNv2P?ULw#*tk@ z?g`@jj8nF8hXu9gu0PSlR=I0)kX`V-iPsGuukv?aw<;#Iye~`YJXg5tZdZ+OTy<;P z*ylP&|Cd^J;`nSXo-6;9XX~DD+q?NDvxM~QuP^P)SQCFvTDU=Um$uWknA0o%IVCkD zAL900^0-^=h^&_P!LK%XQ_qGme7*g!`vhOOuu4tur@W&__C)e9qE9HKDBB}`#@)G6 zvwdd%4;>G^e9ii82lWNE=dO7Wd1iIQO{K_GIUbwa>IvI^E9{xEw7_=Sf=!1vB`g>C zb8}(%rn!?l&s-{X_;7WP=jLmSM}w9$PS=m0y<(>E57zWE=Q6_7Zl}$>o?kZU%AZ?| z2h5G9Rb7}<7A_*m_~PNhUGYn#v)(gE9?7&)JAatx{)Tl&Ht4q}?(bywa6HAQ$L?;r zCWP^&YTuDgQWt#lH-7NGoQpILpHxy-F7=@YF=S0-Fh=iB9JWPUQ}!L36# z%QwyCs5E)NXZFCrOy;koKKsqILx&%k1pc%+mVViw|C#4%UANs)>X`=@m>S1i<(VZ~ zwk6=3+K)Z5{--pP#pE{Ml+J!MW2Rv6lzCt1AnB62wwUdk@5wv5 z&&_(jrsbOM)kVv)B16BX7oKqsnqk!vGxg-^YIlpbSUVJaQsd*^# zr|(XuYlob+aQJIpH+etTYh}cy6!ANqYr`K_Oj~j1%@1y?RVs^DKdVUepS}Lg?9IRO z%*5~9XQ{cmX7`R;4@DT`w;AimsD$|K$hx`ZlIWY_Vz$l4!|FDF-2SBX#LukF?9+^hto!z^X3UTi=g< zOH$k&n|%Jk_3y7Ujqmk`wu)T(^6=YQN8u3dxZNvV!dsgoqN?0E1&kjZ@qOA}FBx;( zCnm9FMZs^I85-3qLL9lJ@=e0*A2aF6l$zeDp6Z#qVtJ~M#F8}I5;OljTrFf{t{0^M0?b17$Iz36U!zpCNBAuTp(+-EUzr1qaOKqjRcx9+=U#^PCf?F3? z$-VFktPK@aJa8l>beZmNgLGMSrMgqXHLkjAx?=OC-iW#F=-*s?Bl&30iWKf0fmPWI zf*$%$zlL7B{bK*Z6KXS6^1Q^(JrR4j=%sy{D^XeWi;0tDX0cIB@5byH54EzHY;Ar^8Cmw)?uqs)@=xn%#3JzvPsi zfK*1u9;TRSJu!#hr*d`%JysE$-nQ(oQP_bBz125#x!c4aZ#`Zop|ZjItBk^-C$l&% zUEgH3V9A`5ipSTdE_}U7=GMQvWgkT^1#~-4tk7TmN4Huh&TMMLG`7ttFV1&-yZce{ zuR+zuMGp#Ib>(hocu~7iSz%YN-nQp!ZFcZT=$?M$9IR_EyWjv<_N8}wZF!$B-z%N6 z+iLZ`O>&9#`zmu;=JC!?Ur@0!L*?+q#a9CkTRzeA3iCgb6Ll>qREBGYyB9-|lYoPS zj+Loh;-5oDx($U+7dt9+rLLTC}dfTV3A8c84uaZOC4p*tj+~Y_e>fs-W8B+yho!JM=mItu}OL+O92sVGtMQ zUlXBwF{(Q(?2SsR(6=ua1m5u}v>#WIJs`yVB5A`L_6x3#HLoLf2}e9GJbtn}catS+ zbHwY)-zzqsKYQejh|$F!hY)3vs~22Lk7YerD3!6nzb;XS)%ymo?t)~^9Zu}K*3C#{ z)j71W;;pBY`@B{K!KW`d_Vt~PZq#_wyz8Kp>8gqOi+n8B3SYXuChl9=ti1=@lhO~1 zEZ_JyRdBZ#gN&8>8rk1ro5~zI9yaxzzr8YV#~$vu=PhFXPqut@P;JXUFhhai8_$_< zBGcPdPt5DAjQC;`(E5nc!kw{^;&Ckg-2SSa3qDIrR6dwsEm`C7?BQg?_LTp( z^K159oR@Or$wZ#BOXM6JM0&y(rVIBZMLpO%X(3m$rpA{rhKQwYdW#My9Mvx0s(mwy z-FH{u+=HTLPe_PL)^5BPKdW)un%8Z`R=?w4%DsA*e~tHZNwvZIYo*f`tg~!(*NnMh zB5rVNl8pMyh41A~_8sLl-R)4yZCWK{yL%qXs?~nSh1G)(r5?L1_=4+8NvqqYqcP1V zCThy8nl5@ztJ0GB;Fj&LpU57USUW*n+1M<)_J#I~He(&GCmllR`co@<&m42nd2?gk z$4z%*7cFr};GdhX(iXEO>1i`raGWQ@ada9GfOwIURlf{%$RXLItn+sJ3ziVABvTrKu z(-4DYZTpU~Zn(;^Kgu)U^#nx)kHAB|(|q_$msljfc;WQrqurU>NiV#@QiT^Ce!$}$ zD9`d{`GeoPqN%LyH*3)P`Y7}pv->tboJ7Bik&O@6YsWoJIakXz-b@Xl1 zofPpkCLF(%t3SS$cO&N7M4tHDMopn0xc8Sl@=-|;#fysFePlIli z=6`V6;C=c2%tMw7(hllfELmOXo#D$~BRI|Z%4|J_V;@(re{DR=aU=83)T#B)^^X>8 zY})j5%DeVsb5E`jsC&tB?&ShYS>0;(sLM;wa#i2p=lf!2_J0{SBj?$9E23{GJUSA> zC4cR=!5L+TWjFHIa4F6|UTG?&(pRE;UFfUC5B&?W8xP8c771;sP? z6U*citM4~mjGbYiGvfklzhu_CYmz$*7$dfIw>*sfus`d_)42}s^c`kzy`$tCyQMJD zSJg4u?y#PzfyWijmdg=KpBP!ptc{%eYyMr4534vgo)fM6$NHy$+1i$y`|z>I4bcJY>*x53uX&YP_@`A%;wFRt1($s~ z&+h*epCf7!WF|AEcPr1kxR7r%o|Lj*=J7dYYjk1rokLHx`hRu5kDjR3KCS0!%%n;i zaqYZa?k`W{83b_5-gPHw~GK6e=)jRc7B7^*~ z?ltT=?`6K74Xio3-DFY9|7d>gkJ7=Lj`hU(K6~x8W?ueM34x{U&DCP>qMVmC4LHfZOCYoC45y2fzY8kcE@uD?DY(8tcUQYM{su59*F)!*}M*SV=_ zZ29tE_?8);q8X3P!Z2foc~%D|=NNrBuwQUBqwdQY$r{|c>`u-t3wci!e{ka3Th!ox zx_I-CO8a8d$oJZn&D;#u4=*}Aym7c?;2YKqRzf28HtXkl;z~@Mf$etsHW{wj&q^>!I89R2W zB?L>{FP_)tEpp+};s;335&_;@s>b551*UvPQn4Vh&(3WF7AHCAv`9o#K&Ag*EJ zy2agrS3+-jNi=sI5nQ`%?d+Lr&8IB-w4>y5+xksYdnZj@DI26<=>BEWIgfmmjKJMr z-`-ulIkf&u?P0cOJPWV7b#ZP?Vp=-mk=8Xn%|<7Y#R6I{cvPj&Gw~Q$nEXzxXqEjr zE9mZq2y>}xw!s45i|$`9c4Kv0x@=>cfhA+ou1mcRQxbhnyYw$u{-$S|j6vLv`*)=5 zA2;|%SifJw>~oT}R&m9(eXm<=gk$$RD(Pz!{3v?QCzQ1Sr zahk1n&)(}fIVTkQ0*rt6Uatzznz2@@toXu=n8!QcUw_3VGiwo3>&=sita;3jj1HvU z(7Gd^mR{?=eGT^>?iYFoBtJ~MsCQv*L09d>@uN?rmLD#OW9Q_RB+~1?jQ+O2W5y_}ILvxwr4SV$D;no~t()zuh=ITm9_EL+A3$ zE##gUUFGDE_loOpX$p6`t-Vl3?elW({GgKJORrBREm9D8$nxE}K1ZHe*gU7|S(d?N zuLX^tezI;fQS?_^(q7}6aERrJy0Xe0xpQsb_UIW;3tmvtt-WR2m3ouYrK}1w&e~mZ z`RUkM#IxZ+pSs%?qlKsPF5YF#jX9^RYsRsH`_K!aPv$IFJlS(kEqyAo(vi&i)M(0UeepyK4cyrt7)SY}%sGnWd;Zd`m*JFV)L?80>> zLZ`(||Cs7ko{HKw|M*qTb91KmteLKpJnc=f*rr9TPu#tNEsk7e2zB#a=-YBYvP1hg zyV^M!HrbFjzf`v`@h%jVITCg7qPf+v_l}IItD4U4+9am^X+!3tH49IyXMU%@^|QW> ze7kk~*AkgGM?|82X@6k;zRCL2GUog;gH4A*%Yvp#RAj$d-#Ysd&(Sjl)74f9OU(5X zJ18C@7?V`GVh&%)s^SN4o#ZFq*5A{^9p*LVQSH4*W^3l8(}lUy1rxF)zs!}cD_CS8 zslE9z=Y{DHwtc!BcleF>-_WEExbVQaD8uMPKAO)=BKQT>`1H4 z+9giB{bBQtzkbeox=yiWJD)_y^|Jz6;eBN+PQIsqSgsos!_U<}?`@>^DgFxBAlZUg8oZb=j{3XMtS8V$l4w@)1mwi%tb2nA<|5J%Y)0zF^ z`*c^8Sg`6%e&A^pP}VVl`H^AW)E-^c#{m|iyMH`7)Y8-RaP`AY{mrM#0?M8)`MplT zV8b)6O$V2WJh=SgU8nY|!nbV4N?aSgboVz!{+GFxz_wsgpm9v7^Pj-N-tZ5++OyTF zpSg%X-_+dk+U{NZL-XcpqkNwo-d-|uA6l@nx2|MhxV5o@(|j-A!?-+=$4cLsj=!=! zClkB3F`D)5rxyOA)J1Kc%yX5RmAccJXS_bh5HhVYsoW=QhkYYo{K~oOZ>mQ#f11?g znpCS&5-8-YztL-3dZ@#?gQsS=ZC6_{Wo}8?bH)?14j43l;!CjK@l#^ThTnk~R^^qh z$(y|6!b2mIw6BUYJ5=v$#QivWeNEbxHJdgXX?@-$XqL8pm*t%|OqGlqd9|nWn*6!6 zq3C8o`j&lbj+)ekdI^DEypo_C>_! zXJNd>H^1>5)|z~JSKse*_a|#>{IOW~Cg)}wGf(j0U46fgo#jd`cqeC;D(RuPI8-~o z;?4cbHzYlo;<>rE9F66Ydu^oMTB=;EyDEe2d0)u!xx0Io-_(1XvvFZd#nSX6aYw%C zh~8hY$n;*^rTfOwA9rj}OkKT0AatW`zVOy(6LZfCFFNBDw?icJACnxPW9iieG2fa4 z6gU07wN~U2m-mzWK*xsquxFe2!gn#PUhTJh;m&tkSkuy%u6JRb!NtcTzTCa6)zxO= zszUqO)6WMSKfK}a$BtuZ{7PzUZ&z8(X$rECy!!Z`QPy^o^=v!l{1v!$JHcJ@d189Y zqZ?)=p;LUEBiNqKSUB^kK!o$jYux%7u5T_)J$`iM+=XGE^B&86iLKbUZrQ_i4&QiI z>7L@N&19dNp?7mdfJfi+&v~}5mfv%`w9>9>&fe9$t5&(a$=JOs^E}`0|2a=8S-8FK zy*xI#J#FXLS579@cXB>+TYP@XciAioLMI>@3uCc zf2F13hV}F(kIp@J=;}API@P}PNRQ~(dlTl){?4&WUS^%t0_{TPw_EJqOJe81uNHF6%AFcS*LJ&*Y#P6Cx6Tge4KT%uJp~N$4SQ*Y<#C4{$L%$ z5z8e9wcq;d2sS>Sw9Z1~_T&#|y`CAL5kGyo&qLiN&^^?5qT*fAmSd_nFabN}S{nEozoi6*=il%IrUQ$=RT>jX1wanr;O=mrm>CC#t z8GE0&btIegT(D$g@G24K-g)!%PmXW&WaRxt zs!PHdl8yxjA2TsYzuj3BdVs^Yt66gCp`3cZn*|B{E9bE0-aa>(!OY2IIiEu&&#ARJ zic!my4+?olmv8udN31M(!@D}C8A*2)_;<{EXAzaTdAmx~O#NY!Xht7Cev z`sIg^*%ZMaw$`r$mF6;hKjpdReaoo@DHZ~yr5JV~}4rwdG-~M%l^*l9nc)j0)ucu}@q4XhGtn zjTvWF+&FnipsUg`N%u#`(T$rd_KGcEw5f#4s>qL3`OHfTn+rR1cD6@dl8lvz(+&_@ zm$>A1=*2+iJG!TDV%&Fk9@g6a;g71o z4aQKhFKcZd>CQM2+Y=$md3A4V=&7YkB0u{6{E;8D?38P^prQAbxm?YL47bEy+%~$N zC?NRw=joiXisn5&dvAwuu$n743O?%VS^lYYa%Eu6#O#2IOE(sEp98P}G6y|yuh`9Mm5OC#$Y>-P3MEAdtT+$J<6-Z-TpHlgp!RfY|lHttE;p)INI z&Gv56Lz5$cXJbA;O^y`poqg`Y)|-z+MWs5TPm1bn7w}m4a8J#aN3*J*y?*xmdI9UP zmq89ihjm$dZYy(3K(CyH!<>sxUnsFIoog|}u36tIW_4}i>$b1AKWsLAlYZLb zsOYy;yW5j0=kt1su2np~?;P7}DQ#`(r=H+?w(+<7 zNjJ5S6>C&B?heVg!{VzRzO+v+wR`mw(=}UMuAK}0viFB;k)_4wyL$>sW(nhZeg{$f~BcHIdAjCFZ{Oss zdRS}OJL82{oX>M-C>(Bk|0F1h-!ts)ses0tPg1rSHCp=rQMS~bpuCbzEtEIxrou-v zj!&h=aVeMG98@Q7co>iwm7@IA=z4feoY~B&x*-{13!?sJJ~j4Nem(u+wH1i8S4kr35U z7MR>HZP)tV^(xAt3_>@(!slr@`McdIIG9vJAnVzOO&VKF{v>N|Si?2x=|rYSQn$o6@!Bz(S?_v% zlnu@dCeh^)|wEz+u`G1CYED167wcH)`?tJPK}Vx+tKhh_}%lv6M{eY zr6#+Vc~x7eG0zC)-=JxrvO%L{i_YWQ3xrQaPBRR-s1cpmwf}5O!pEiNhrOrszgu*u zbzW%oy?-k%P0pEC)W~3a=)t~ShrM#7GcG&&J4y42DVs&TtJ#0*`W?>O-wGMuy_A08 z$G1gYL2+hfS@k`qeJnQ~{$BX`3hxvN#zPS|7D!6++>uy$@w%mZ*mE21=OwEaFrRo5 z@Mu-uN|&Q;vAfWCui(F<-Lv9zl^b9TcQ>RM~22(v&(1HUT*%r;bC(L16yH_ z-GolwxXrGwuE({trY)(ntK@55Abpy3&O6^-k)@@}S?{da{I;y`m%D`wTl=={ic_xc zaW<*GnIl)9=(WIo)6v7b%Z^_RQ<}aVbiNOy}>ov%)Sa;mFA@F+qna15&xvSP)a$?SNT4hr( ztMy`<(^Kz*ooa2%gP%`Hkk@fcy=rBs_w~U9ojDiv9b94;E>)epGq-oM#LmAR_cfX| ztIq#ZPWGyt;pMS=hEey=9y{+)kdhD~4QFyV9k4wn* zNr58CM>R56em?M7D}&u9>{eEyDXU1L&XS+IthWjYw@fiA>DJ{bZBd&dy1FkydBKEj zF$Yskjy>Q#*P*}J_MV@f@P9>_FoSuS1uicfjEeJ(o*LOMdF`pyacs(sRI5zwuvn&< zyZ)^zVk*49tm18^zShkN>}ri_?s}{3WrUq~>+G>8)!U+=HJ=~U*j3t{<5KU*Qtr7nTvSW5#LX^L|FW|9k_&vRU(arf ztI)5O_X*2*)U#_w!x9Ar>)C%6#9dBS?E9|NFiE0D;%|xuvzvXS;mPOIrkb`K(Je{JZvV z&lF#%CCGT>SgEGF+hT3AgUmk-BByTgGTUUtv!x_K++j+Rz*5_O@mHK-riM>vZ~Ha- ze1~J^m!&fWatd=-EZh40;|Z;ZrELF<<}hu3Vo)U-6;v@oSzvW_Y~qJ=eofqkofnJSsY4SaiwCe#>kXJ%8DY&1r}E zZ|W`EteJGEBW?ARwET5ic`7a&Zhq)4STbpvy56*|!j7bxMIp%U%L__t-FIOo~; z`qkwpR~@;a;1Tjs+2~aLFYT#|TGrM(rytpPwaZD7`|zVQ)3(6JRt(JXQa3kv#%=rO zX~)3Ao4)$(?)NN-tn5V^Xhk7C(eEoAZ)eV*7>Ra^BXrkbbo|=n9n5I^(QR+0e82S z+WD~3qi*^gc~=gVo>_3n_3P?8&sQqzw+mNrse7$`^Zbc)<22X8@*_*v3;Ax}-Ms0~ zMW)Im=I3ksv>yv;+^|_wc=(x|+?(Fq2}h+8e@4Ua@4-fYjWPcALJ zwcvc-PcN2ay=~FDee0L@9KL>5bcS8*&6fqNg(5dybuu1oQC*;1DSGEv_>sP=OV%?8 zGxy(|P*C>gan4&=naKFEza^38$Bt~>QZlQtC2!IRjqa}pat?(Z2+cW=cH)8HyCoGF z>cJ<&^(;Jjo=B|rytDQC$|vpnGAoYzGM*J-HWM`I_FnyYWq<28?x%{}K|6M?x%#X1 z>LhRWT+3%=Z!^yahGncuFn3xgrIN}Tx#sNb*y?+6PnQeMd;0pdu;m>N{hX=%UrcMQzO~DLHPRF^K;MdODg8{oiA#>=$VK9^1#HH-G@T% zG;3Eq=;HBvDx|9?ZqRD0ykAiM?1F<%mx`5LZ*DTwwAM`y=RV@9Ss?Q6=B%YQykEtR z=3QIJc87UKvcKnn{*zH#-JA|q%(G3v#EKv_B3{zv!C_~+hWh-*xYHmB;&JR-u?~S^Akf0ezHlHDwqogpN;x` z_Dznl`mH0<`(C&z=4^}0JhpMR#yhhwM@4hqTLgZoyTfrzJ86aXNeNx;6QN>1ram-r z++#HHDaX{gZ=D!xm$mkm@A4>EU66YG^{k+In~&}5dlBkfd%w&7ai{W+9^0ftCjwr3 zxV5M_ByjqNcHKS}soej8X$HfTfbW`jHbs{(ty##s<$u`S^Sd@*Y+AZMY39f3n<^86#m&BQI}|?@&Pa^V z-@9hT z+4E2LTuQBTZ)<4On)xAaO0iCY`{X?}PvR;*TkbOuvc8?V?Zu|QJ9}PFb5yjJbr)~F zaBs^ z;IIjL+NN5`ueZvmWtvIWsoY*;XvE58Zuz8i(;cOsZ@i|ZtH}GVI`A#~WLSO$x7LRH z>=vu!jIw=I=NoGBEqr3E^5sg9vC*@a=@;$Tr!q<@hJE7XKEnJYedjczh6fyC(i^UH z3e;sT+F%k`;MbuiEVxB@*O%X`CKQDBUObbSa{L3oY*gLlr)AR}=RKW#IcL`;p$C0a zbKk7DzPY@7n`hXzw_;p8eKoW7wT(J-4PHGiIHe#p-Bdw_(R_C9i4{xl?K1X^ni*7h zQstzFZ&}pbU;iZXJ^U;tpX9qR@2uSGTPu0jZjvobj}Buj5z&rJ_uutq$1AN1bK~~i zpQHayJbXeA<4UIA#e!lcbEBqaay`~;tMVxLd}V&w5t%T(?j@6^HqF$LlvMwg?W5DF zQu*Rj-s43<2F}N`t8TpGI<23uM&wz3Wkm}+ORbvIq1Ei)rZ*|o&pWqmjbyS`)$+@C zPWtSV*Ze8x5OVrKj7Fwz{l%kvvt=h7u#4s1a`D*2BX52QnTH*HQF~BgYr?`P0TI!b zBIzeD9w< zB>7(R+IUv)l;+z?6OlK|qGoiwU(A=7dMoR?{?(RwK8w~dJkU>8JF6*lj!o_oqmvYe z8~c+9Qy=X+oyyMnQjakr$kD-ygG2COZbf*b>gt+TT8u1{{<&0I?U=QAr7F93^&PM7 zV>X98%OAg$&S?Mp+2pXKn@fQ0nzwJ`i@fR@xt%9x{BC%rq*+bl$fsED{rG6%oVSyW&ZgfM)V!BsdO6~3V4kt^t!L~1?o3~O+sUy4V zO#)&c6+QQyBPDA>F+DY%~ul{h`JEv%E&Wn|KDTfPMV;@=1a%_CIB5?J>UZG5Lo5Yz-*D{J3 zW3ys(f42IHb-c+T^R}l{C`#9BJiV7M?QXNO zu=~OU-8SVc1{wE@T3iwbI8JYtk+%HFb-<-9r#7Noc|zKB zJ41zEpN}lg*%;~nT6(5+rrXrn7n0-*>?W^lP(Kph)W1!sAlaKwq`kO_&FARdITDV3 zYO88D`wAqqS8Om_rO=ney*@P1S~C6DX3=C8SA|I{ zHYGAm)!-7@pFHy&`#0k}+u1Ho8`eektzRS+qx^5Bbl!S)4Yt?$58sy*{?jR`6?fa^ z#OU>G(h(_@nD3%VHKS*lZ(dGp(o2Zt%gNTMxbpWM*DPZZXU1pW3>i&D z5)z-PGM>7&W5=qSr}_5JUfau1o)LW~CBNo)#1XTdUd;#3>IE!bU>uRFJbefMua4I4 zNS341Ry}ji-7xX3&g;GCRg~Zv+`c^Q+8&bRyh1g zLg#hEO_8$Yi&Qt~#$6OX7q-UMWqFT5A zEZjZg=5d2%8x#)Zim$2;;hV&F{Mt>I&T&1y@jy-5 z(%Sr~Xi~ghas9{hudknTmSC|qJ}+=DiFx@=``^zU7!MV`EU}*#ZF^wZmYapsm$(Ig zunb>kpzEu6Wcv-f$hiKm4vFkS;aAVPMV{f`e`rT>ZrdtXshFq`fscE-v)^4Ts=N0t zi>oleS7o)_YVkQ4XBSSqaHpWSQAW1-ppfjlK*ui@H$1;@*y+$akG(s4)-9#d4E^o^<;WlK%ETW9w=<)|!X%1by>EX7bB!uI{hrvFm{4@47eai;KH#E1o~pi(KYVmXp3SS22Tqf-5|bLAXSiFIl)Qc=o%Y|E`GbWh zZ(PA%+v71spHrAMzo&@#?byk9-2BXygR{O?t)C&a(8B!v)6JGU*3GNUO*`!)`A%@w z)6a>1OQo;hX6`<;s{Q^yX8wuhFRpx$TK&Q!f06bMX+3tC3nhW4*1TJE-N@Q)UEyTq z<0b3(m}L5er8?M_WTmYCe=?9~vh&+kvqIHVd8%EDvh?(P-Y?77-|VhE`@GTZElu~O z(iV69T$6b7qk*c~gXKBA35ywJU0-IJYDP;qsJ%UUq4_Y^x@;@iC)+tQw$(?ltoCfo z`1bAMMA6$54wSKele(RFlIu)x>f@@AiWOZdH+tflFRnUw%4X%WTM5T5EY7)CKYRPd zWzL^Agk4*c6}B*F*O@z46J9;|wrRFoO7>FCr6!MgYY%R;t$5?1XQ3C%TC0nszQ=BGVO_T&eqF+Zi}ROBi|)2ymAW%S*I&ygwly($#xXXY zYX!S++_)=M5|b>S^QOl4om=RJ*&kQSoHw1Y<0p@^)|^=t*LY4;#qhaHw5BaMbxq2; zRAl!dwFTnGxaY9knSM!k>5VmWuk6&Cw42Sc?V!t{c}e^~o`fE`nK(@`@q3WN(l0jW zw02Kw-6FA_k8?inrLd?Sc2OC=nvM6Jj>n%fxUeK@g_%<6Q$3D?ZS^4zS8|pwzbO|u z`5n_9r`2)yCLE1iYwmYitl7(2X1c7UO1GeVN8sAdP4YU%9%AN)c9p(PSe^YTTu4<{FiEN)9TF{>PM&6O6jX|pHn@f zqUN;mrS>h}o!2+r@UD|tuG%DgL&JA_!XNKTBIkNolM|;m$F$D-S|i8bbh2ynNv^Fs zxF+u4oatxk&tRXZw69?Etdj=a2EGrRKZsX!H{Ch9F;-mV?;gH?6AO#Cy!^sBci)@? z>OL?2q#j|}ReMNCp;B_;*PQ+}H~G{yN1l*nc-&;>-taWw!cD;^vP>Dl0hgDoPE~m! zDt5X1=$9nNopsBn&D$U|MKQ>kVcLR}ZnsSf8)d{S#O~afv17&t9kaWxuJ2hGbkzd7 zJs&rfO!wdxSag$Z*G;z#mL^fUZyi#%-`qQE>nhiWQR|u-4(zk-YAz6Me-^}g_QQ7uVyV0o0^$1pUE$F!Ssf^C6k3jPi=E(KgC|6X!Tip zrNBzwPo+Q9TyonT-Yx6V78Mab5t6+4Hd|{B_bI1KcaoN0OM7%fpkLHwq5i>!$rF;KbJbdQUiz{oA#sVoiSE;^bN6U$K6B{i!|sx4=0AH< zoLRCDa!TFH*G`pzMO7Zz>0(>iOhQ@7o&^}aKc55E5K$du_w zx0qS3jZ?{mIp@-kSVv5oZ2sFPZ@O|v&LoLV+a12R^-P>NmrXb4R{4x$ty)Skk_?f!?Oy$|30KF{Fvq~_E~Wk>%`h}1c)w9NCC zr|Ap5S;6^fPiGr8rTN7!+b=L*IH=5FK3~QKR!%Dg+vi+f{$E}iJUrerZ{0E0Sf)kS zA36rkoO(h;YU)p;`6nb5Y*h^tqBoDt@Z%D@6Esdv7dcyKPX&5qe{qW1{nMHL=O2?R_8P zcj#<-ClIH0n9Y>Azc_ZTllmpjJEMhU;Wo8C+n#jpMQfkBKG>4B>taNn z#L_snV)m0kOcPTXV!nAFJ~C(Jo}A<*F-@mt`#s)w@^JEW(eu?I306kC(~`GKoQa58 z+@#+hwdB08-tjxZ8pS8cwIDOlt zLwT92zcWdv?4R<`WMXdEiFB4V=4)r9Da`w;#xI_@g(GwOOT$UWO`160n(ee+@M+oP z5)BLM_yEV?ZncykhN+jo$dts0Ph?!Vao&tSJltx>pI({pli@MTb7vJ7pN4OHj`mvm zWPbYmW3JIv^MzNJX>LC%`ecsB>ZFUI2NvzvDv+6GQc^J2dFmk#g=q%LJdrXlefa0h zdUR^x!$Q}63U}9RoVa#f6YH6V>J^7i*?;3*`djU0Scrtii>@ZeF4ORYRYuKDmkzVW zZ@$c<`pv)~;vl#7lnI(2gjz%umZ(j+lw)=B-N{X|^HZ$NA_KgHZ3-Lp{1RL_Cgfc6 z{}N);a7*ez1@nycvt!=g)x2&Lo_FL$?uS#nbye{{CC#}@rrQRbd{G?lR4J-m<|E{P zB{W~D@9NDr;*muT9)>3t<~-4leyR*Y&C1cHE&6xQB$&;9Y4*AM?6rMo=ZVbvc|2`f zfasH_(nlp@9!TtWNK?(OVfgV@gzI%-jZW*f;xabvo+SZ%n(G$)+PBq(8I2EI;Zp(|Jl-`|o2_hxcuC2^I~`e3)^#OZ29e%ubfTV}JR~u6MoE+Sir4Q0hup zE6eK%ti4Nu7tLJv>G_%|F9cG0oBGVJuMFvs$yRd>i4YX-<=0=eL^AI6HKiHX(r2*! zTNY}x?5)S8O__%`sqO!IZPL_QVUaquSDD95U#P9sGMQSd!d2~kP5R#3s4w-t%U^r) zOkhk=SK%*oSSMgBT3PA(D>m0Jzi_|knzeItPo1*5aWcyD1y9AK=b2B-na(b*U@l9u zPCisD%DlRo^(Pm@=`Gif`rdA_*Vy>wdQiukq-Et&TR5(`GcgOuuKF>5g6uMD1^EkB za??1aC3OT22o=Wti4fr0b9B*`pTbK&-uUkRH8Y;)HPmx`8GHU*xNo^z=u(u7Z6X70xMI;t9;ed#~MbMEZ@W6+l!>$P>+Bk9G5E_CdB za!R6ee(1T^51Xd$&P&;4w)64c zzZzEmSsSu3xSKP$zj=?l`zlHJ~ z+-ijz59?mprq6g-{oEX8`8D{_lF-w`o=LXEo0ea<9fMFxM41K$-bbof7WUe~=< zl|1eC<-nJRV>d(}69S`KRY@*)+LYF#OxIV><&h zFUA&B+MhpIK9gTKx&1_H_Tkx=qYegCuHF`Hk)WQt|MJR6o%j3S?7pXCwfn^eE|>Ji z^0Le4@?M4B@BSY0?pFMyt5@XPrzd_-Ic%U8v)6o+cG|Zqr{4YCFx5Zx@fPb7hn7Wk zl_%y$u{BIKjAy=_wrzIgRNJKTp83<0ytj|j6n~j$XdN&*yd+JE|KoP2 zS`MDA}h#$o!;8`rB%%yu2ycKyctoas+?#IL<)ZXM&M zc&ozk?6w5!$R8TF4)okmWv;lntGj>mX7T*gFk7F65fZ0XNy^zs|1Ww_{-)j6KvsUI zSM6Jmk0;yWxudFPR>@sB$~>#kDV?uu<-u#FH`cJtj`@Dg^u|55-;Wj~n7_^F-zveL z;>_?(?t+eMZq5Nmy&}GMEQ|6t7~XU}Vc=@<=R)Mp?B6mq%L;mqhPC`DeIF%Ub>Y*h zgK|r#i=-GzqO?{{PG|ArUUXy}` z;8|;*D@QVKw0xVr;Y;ugua>Xdyf^r*dHqdAr8nu~3;rGMlJ{=uJ(hdhxtnwTkIQ>E z3JHI?o%DD8>uGEUl^1)dROL+O@BG5jvq9rn-&c-3oZ2lO$%is-Z&_L0>U^<8tjbi_ z_mVHu#&h!D3i9S(ez-@yao_zonX?Aj=Ord6EDFh5^Zmzl{#0dA_Gy*IPm{toakokA zXD#!MzBx;Kp1;;AKT%y;RIq^y|&Ss^>SEXH#gExN@ z`N*UB@(PD;ie&eS8PnHJeBz|aG;_0?cyV>%ySA1c_cvY4S}%IH zi+(uqw6j{WPSCW{cJ20yGmnM6ZjkdiHznX*=GEv$&&}s?KAm_o<=N3Iac3^1GL_Ce zn9eujU|YuS=Z9;Yu5a9I_n`Hx;_R8{*%)WU6ny&;eb-pk!|HcElYaZZ#I}sWQ-^dH zHWV)Wp&NJ2N9W9%ZyOuGN8D+8yS6Z99&ekE@Pw5MOWhBwopwyx{ES#$%KRJ0&8`Yf z%L!#HoFZxXE@86F1P|re#-mCJ6bi<$qhVzd3R<>ZBSRUWtCs;@;BzU-}I^T_f%|jwSN+n z+^%}7P4wR%)n^Wp%lFCuezO0K?df+<%zodj|55Kdapkk~+uvEgD!pxYe4GA`AF;_> zLwe7Jb=6(F{QlSG-?c?yY=yUlO#j|krrkeH$-kR#>)nNSCoWsMrOaJUcUSTM4;N={ z4|STu)O)QiNAvHhX^!2wZof}{ty>tI_WZ4(!T0_dmtyaG=Q(bhsJQXZFaGs&=ilGB z&%J#9yW0_NyRY?qS{&;g7hg7K{}0U*F|6`#HOr-#>pBwfH7m`*WfG z&S?3ZzTe*hqP0)Ysyf0n=hf^gt7J9*V9TPFFQYd;wNLYzevKT)SiWTu0Y5L5J9HtEPYR zTf6nOn)^EYJ54|Im7Rq+H6B;$swhdDSQndeZgBrSang3{pSm1L6E39RVzyqkP>thh zT2X!TOAof+$~w2hx^&*$Y+U=I{q7`HL0@I8hY<7jGRb_`Q^`J$R>3%7#@Yzqh8W{C8mC%QD^LhZVF_ z7KB=?V3WJ+Bl327_?~;G_vvomD(dcVC?ovKSu_7o*F}Y0Yx3lG2HsEx2JcjNV(U(DynKY9P#S;mD{NwgBE-|c{K2Jr=@za(bu@Tdj@)YH#|Kx zL;aP-X|AJJnl7CBrd4^egYUcY+57}|bvc_k>sD)Dw|M7p$6{OKb=k13^Cgv>sy$+GuZ;};c+2In$Bqf#&5zt&GU83KMcN# ze-@c8;;A0gcEYclwV5|<-;Cv4XVll*r#w0P{af%yt-{2UaUY)7CT`Py;lDHvn=EInc$ng^3Bhsu_DLM|G2Tg z%=b>n$o0;FHoadxpJKP^55>IJM81tf*yY>O+V+S z@{+G$+WER&9M3ZY7CxAI;P0-2s$&+brm(q~UH)PJdE3fb#f|shYtHnpb1OLYH}6*9 zTMeaZXI;Hzf+s85PO9#>x!3u0vcPA@>fUWvJSXgmNs_-k*)H4t==>#2UReP~>@L@q z&5D?_vu*n;$ApmQm(^FCO`piNSI+4?yU?<|y9{ml_RRYp!ZXKscGe{O-)H9S+FtN` z=e{kM+V40`xiRm}rAeiiBqepd>hGm%-SeN{Rke*jm2vUWCm+7at!?H%zt*?0H-tCu zx54Lgw`a^}RF=D+cIDfzSbrH=tv#3YcGRv=%Q@1yqnF>eEZNdbcU^qgtKZv`pT3#t zr?X(qS!xs<3H|MUL}>?90h00_AKH#+Tqcc zcWBM#WcC%|-||^!U1SirvtHS*;mw=FH_O<6r_5XHozYPHbZ_6eg>pW3BzS8ZuIFgX z5uC9Ljj95DNT!aqr$h<)p4+}r(EEv9fW3+FD| z)0}}xuWvtma;4^y`z%wo+Vz`OUZ3vYzgIM)Ag;UYvZ~ZpKF0#PqsRE)bb9EuStxhB z^S!}SIpd6f$Kkh4^Edkc((>-r|90f)g>V_?&+m%D{zas}^{>g#+*3Yh_T627p9zPZ zyU2dD`B9|vJ*jnXG==L*Tz7t0Q8jnt*%+Tgi+W$bii`QgRrHek&E)t#7ZbkUzeRT+ zH4sk7m;Aj}bVYCG4B1dC<4Hx%N6b79*b4Ta-)7@EYx^zX-Mzis0`vB+sJxkF^Xk*P zs%y=A;|or`ZFc+ITl$DMjCn)MdB^1)Yu7AYZSmli@Y5gX3(xx;o_QfrBazueC2|GB zx}`IucC>jvT4wY|_)DYBlMSX$F~al34se0V_!XxinT6J>w zg?DT|X-SK7{>9}?-Fh>Aan;7z$Ctm!oE|Xy*2-C(ak;Ih(*+r1E+(Jf_HcsT&4=b& zVqbNiOFg+_g;uLf`eC03eMKq9`V{xglwE!3;Kp>Z-No-6buA|G-#u^O`zEbAvaD?F z>Bk56&3s$$EB$=k#@o|5qxpR%D^JTd%X-bTD_r{5=ZaU?pLx#UiCC^+sdxOolEJl< zxEUwCek{3Tobx@zT4NpWS(~Ffqi25eId>%O$<0GSwZ~Rxira2HyLIBT4j#+L3i@#t z{)du;c0Y6zz2Uq1b;LD?#GAsttiBv9uvOu}Qk_{TvzaUBHL&l#dgH^D zHRnWbXuQ|@l>W;^XkFQNler&MtyEV;V-N@ zE_!dV&EBK7_Maap0E7FL8Jm{jhzTYll~z%<|XHjfOiX z9k6&Tzc+7HlKqWM&wicxHhK0D%bkTyEI0m#hx5F8qk7Zq^_0C2%w8|CP+BHu6uhxR zr=9H%^F5PK)j=JG_s_o0I5WHal$yZn&2w)~Q&sqOeQiaDdex`Z>b>7~+ui+_;qPC+ z(mAvA?e>>n66%}Refv1)W_S4E1mX5$PE6JOwbyTpPm7iRsJCA8`t#2t7KAgdxiC%n`wE?{3t7#6Fa+#tmRs^Rs<`C8TEn4&p38qN-Ov2C&2zRr zF-P=sO}(){*Mg1xd)^)ht(?8%PL5mLrm*(8H|M9llY8U*UFpl&$lt-TCuTjo%x$M! zeU|-NeE6EDn)ZKx2F&*^IQzim-k;z!FI};DuARQkC!Mx8&5qn+dhgdJlb`dIF5ax1 z7O^~HF7q|b=H54QF&`OCvcfyhb}x?bn3kF&IqODGaNClp?dQJBY1BQudFO~_<*f&6 z4HmChc=yhP>QCFQf7yD}d~bgLSINR{wJB0Nw{Cyqys)GAkgaNs@ZRJ5m4)4|J~5V= zl(muno$nf@!m8@&GPa)I*eX|8<_d1CRx>-i_wE#h)+&bG#&Vh7>DD?2HDlK}H`yO= z^U&EZbN7)(LZ*{#=lj$@vcWU`Z+zTYyT3s~J#FoxD`$h#nXN9gg}x2_&Je)Q&X>2L z`crsD9OFGr=~MoX=GH`XJYTCD=d}HtTc`j-$C8V`uWk-HYs+XTx`Jbm!=s1y`OLZb zgf^esmbOt?I_0?kdjB^~S2S-kEAA8Dyi1|6@4NSI+3S6lhi5J?>q%OF<;~1rHmv_N z-=AIGRe7qc?_I2^+4d`|kH^>PZY>n5+cw|Xxla7%))``+(&^Xf5>(DwP`G`k`L*bxPq+NiZylZ&Ou2QY%on{ZaGt|(;^&10%M*3^RQAr>7U64AE0)G3SACSr+N1b3Up^F z+H}OsT4?$9T9~Ql!orKP6<>ImONFO69g^ICOrYgOmf^mf{J%|&yUb%gPJZ*^*bN>L zg|<(p%QgonEtOuV9x;*a*e2!-6&9Wq7B`Qtd&IX#mo&|g1px@dLA}vGNu5d1C z$tg~eg`U%N`tSFMRC!kCn#9eYm{s+ctLfU8UwaOxEwQP*?y%LveN&UA*nA5k1;MjB zDzDCa6x;U4UVOD5=hcR*{z*%_SWmj{neuGW5vivFk7~{P6w>S>r$_(0cE0DnO~}Tq z?xek+ynGWoyIGbpi*Y6F(H1Ga7`Z{E^3sl160ZX@h5v{2n0bB?dF}Af)uefKnb5oU zH?6;3>$_}pwW8l(;ZwYU4| zx4ypdwO_h@s*d{i6-B-?R{WkDyz2Q~6W6~d1luZRCO!<_dDHQ2-6KVFxyjSMPiGQu zHCtw}Lf$-U$5dYbmAfaDty_^zA9ZqmEoPs zRlJHV(!ag8B^)A{ugT64E7)zfZU7_sU3|Bwdvua8>#3_iXn z=sS9XV@_q+n>^RnFMIBpCe13B3{FUYyYSk~zdlZa->#*`Y`;EZqj1QQ1F@neza@6G zu=K25H@j-~ze96**D#29EOwASS0yCVyLX!-lUmtr-}UdN%YI+3X~o*LKyG7U^Vf5V zGq${R`y-mWOI3E+>v_KYCexM+TUgpErkACz2wpr*^3xV2wuEZkYpy!aD}<&W{x)m3{3`Qk zvzZTVeSK69v5RqkGW#E^FnRW@6^XB<8{gUZO}k(D`;zpggH<)fw$9EX8;b&BUN+=z zV&==+(RgrMVSi~`+FAp@>y?%(7c4d2KRHr)>h_Q)|J2_8<+k1Q@>=J?z@^_O-46F( zU^~n8Y1a8GFDz zWoumWF+0n<-*??qn|7`1`tpFY;!N`@9xlBxDKALq_QUBHRc^}`@N8JaxS`1J=G)nl z_a4fu&T9SIWOn)E`QOTWZWvxv;8@*Mv*`Jnsf)hXpURlzxvI9Ts>ggmNLbCCzq_Pr z-M6ex|4^QtRqJu<%ZlBl%J!j)=TA6&RpQU}=@V3nBO;>QdAJ$7C$_wGUZS`ETG;h{ zNopdJ=2~ZVpPTV!rrOeXj~)e`xPBvhy{=Ko7R6VuQ=|H4eyI9gW;NkxMdhPBN8igF z7Ps`%ez9Kdn|JPw=;DB@UCTa&9S}-Y>1#C%PreaWJ`!x*LF(tjtc+7RC>Cte-a^Ksjj<2~-7 zjn}kJynoGnUYjjLzia333mZCS-pqEtGoxyOasKC=x|uisyuP#R{fo=7Ig0%!_bJw{ z+4(yuB}?!8V;1J{gX_%M_xvbI2-mKzeW$lZD85>8OKsb#U&(KuaW~v}W%zj4l-IA$ z-tmp^S-ZnW+~-x?tHUOV)vEiqF8ek0e9WmMAwkED0_U$uS&{TzCNAk=#sZC^8yD=N zIp%9@ivIJkOE%oguVR+L|Cu+OooBcBZfW3B-*z!=BER%X5vi2!t4Tci4O^?uJ(+T@ zLqutLXwNQr&)JzbE?qf1X<^K~(7ie_#$2r>&pQowUz>91qL5&3YG2!){a;k~9(Z?B zE@p|mpP2hzR?k~e-kY?heGBV+D`IGUR8oO^<=x47dP_I#nz+ z-KgCYrywSGPigX+8<|Vj21i&;PcqM1Ey}&Vb?P0fWufo9PaH~GG26oUefe(YH`}Le z)AZOlJ6LD`!@E<~NQrm;?GiK6?f9L4=JrpS#I+aKNG|U+pBaDk829&G=hJfc=Ew(& z1j<~UE}^hQ_tvM!ciN|4d$)S?zGkkwuMfoqy>bwoFjG79o_o@N(XG=$w%GZeTqbwA zLi^2EvG$Ih4_oH`l9;H++Pq=Ed%9};!MPXtbxpoqv;BTEs2CWukM?;X6{%19(vp3 z^ID#U&5?~RS>n5Ue3Y_p2-~9AIY)JbBky*hk1IfaOh3x zG7jgXLSG)dU(j+n(n4(w_p8ol`CaGsD4bnlwWE4d;&!I&7qu)oF^_)hwp=c=6|zm) zeD0-8SWXFR1j`=pmO9JlY-UMP6S(ib=ZUkJ_(lF>>}8vEpJ>v-I@3UAo4 z(dC;0h>M`1-~d zRe#Jl)9{aHxuX51_1hozFL`nBm*C!824-#O)dn$?j#p%bPDrMO(oDZCo+;S)A=EP*9{7=h{9KZL-QjK-W z*^K9>)m`Jh{?X+UlAm&Vt9f&oj?}SF32!bu`eU{I+}xRd%kECq{W9Z4VB?bfxb;>l zpXK(Ql-sBhHOEKb=$iRGt}#(xbKSScpHmU5i+#8Iy!^gDYMf!;*ehc7-wLv6hvx)N zI%Vj-fJgkTGrt~N)92i3@5Ddl;gzrd=3UQ=YgT2;s~0odP-C;;?>?7f^$#U;V&^@c z{H8y6P1H(dm4er2pKe_||9kd}U*T=*dG=r9vGXgUGbe5@{#8=*uIVt}{pdpfZBOz}?*H{N(%#idukc4|yT$M4u_^Q7wd=0F z{^RvdZrk&^*VQWLthZf0dhPM`#dldecCkPHvi$!3Uq4O#|WIw$N{<=^8LYkMxAvRQlP@~Jb=!!2XyET38#H4{vHE-9QBcJ1rO>h=E$ z&;9)Naf8HBzv-GToXew6wl z|K$41u-N6&Z&PxXJHIViF_&*^)vk-@Zg2nm>Ft(Fe%iTn179tlS{L1Ki=Q+U-8(hUvqwn?|b?3QbpZ*Uzx-IGGg2R{k*pG?fHgKn|bzaPJd6O zKdzUQP2(aVZN^ul)nZje=V5* zHsnU$jfJ(|lK%?ApINp%cT{<1+5FtDS^i`3oY|lMM15R6pR2kg_1?SJ^{UMA%;7io z-}+fvu<)k+HHq!~8JpiJE6oqxRCnj?_w`x-{w_Z!&~xSco1{N)CKP{N5ZtHtfqQn( z`^)E_OP8O0yxX^b{uej-;799T{_eY6Z>s!{dGVdg??X?Q8y`7t`}l4>%bSif=^wZL zw_)s`Az*K^_&d*>dWq2aGYaqD&#zNW7MlCS;3a#~dk8W=a*rPg<#+6r@7OzEcq;^b zH< zS1;#0Up>oy@9O2{Z`GdoJ@;X(lbPyvVafN`KR5sW^Rq4ch5aAFTeXL3et&!WdrG2> zw*94)>Uc)`;tkS;OY2_Vu2l%Cs|&Vw`}{8<_~mh~7Eex8*OcYt}4o`MLYhlFPUI@1NW*@2=4p`bxg+LfyR;+b+o8 z*neuK>0_UbAOC88TdgEgr*!zITfY30&rv@_OTX`*!gJ7jssHt#;@7`SeP|!owpr<) z@|MTDPETx|QvKNXY5VHpd6nAjXBQWnottLaXLQ5n>bYVkn`Z5Q1wblLs5qwKig+rH=?8-MN3Ta3U&|CgF=%3kxp zMH+~R+&=H9)!H?ePl1VDUm34urp^rm6Ma!qTo3y{Ti@S)`tRm@_P76Tor4C zt5J0+?7vD&zRXu?c7I&BBKyqxe+9jBz4CeYhTNO=moK-6_uKl+DgPWK&)xnT(Qs}4 z&z<{eXiqg_MG^?d%tV@_4D5N)3NW^xlO)~ zyle8r6YMARhJO3DEb{l<7(NA_qW8r)Lm&)Ch4%zH4)i`?Iea^#Oe+A2W@-LrX z|B*TV@!wYU4{klj)bCEH*jp9%-sh$ArXPVb|NHBhnp$7l{p_>;nx}h0{xQ!fxO`9P zd$zFS!{R>G`|EyJh6}84|MSPB*8WB2tHsyy?YI4^b=!C^Smkc>pSL@g-@5hp^F5h0 zEh~3_KKH@4cD?b3*Twbwas%$Iy7MT)Typ2V=bxh67oBQeu~F&k^EQ>h+U* zpug^YeEQ<5BfoRQC%p~+cfLBd>UEq~`Rn_4r~k5Y{=)3@qkR8#X1!qdEk;2rH2Yil zrp(tadn($NIdS2gr>D2Cz4P{p|MlZn)Wi-&yOw|cyiaoV_jl(@?f)#fB((i?w#2Raw(6f3hWGfkRi^)*_T<9bC;wy)cU*kucr5Qw@BR3^ zAGhTew-=feyX_7)Xp{O^DrbK#W6SU8p2I5>>>h64^ZL%cuS(DF?yRx5Z@pz}GVeKm zj;-C^ir+Pl9~s|%#TzRo%SGe7jUGMgWFnom^*QYNuKI7)C*Ey5@%_j2;IGjOKV3UocfanpQU2p!zZb<`oLtV7kSF~` z(%$?3j}=e-ug5)@s{8iOneXQd|L<8Hdw%=n{8M@Ve{ZfTU%tHG{MGk@4aaY5->o^c z=HUFR-`Wzhr_cMkIPr#!*w4+!j#<2pG<^F{rMTAE;M&d^U)OY%Rh!K)^-yKfb30eU zf7UAY#q#od!sX}6p6}s)%76c3ulDS&&XP?_gTMc6U3WPl^ZoAwYYtxaw=}Sx`Xt!X zN_Ne1pZ)cFYkz&_^+~dO_kQyGe@nOTe*0KD)A>h*`ti$zBVg9e_pq~uKvnC<&qiq z6E}bV8=9YdtKzEM{##Z53ts2exn29Xky&1DTj8d=qEB{we{uho+Pck+TPk1k+b`Pp z`NVE{zl(Na-?zk>TAXN&7Zul8{;jI+Zfur)i^bZ_>}H7@_RpS?kzDZl&m!&G-PcbQ zZkFvhr%{!k{`Z~H+dsPm_mtjWQ$Dk5)t+~=-~MzH|5mo_@40V&t~nhqOTGm9hri1` ze*N_yE3?^!i|54kPJX$^!&?9SQ7zjOulN1_rgp#SXi=k}w7_ZY+NzrMk7CbDCyUtJ zJNZ5A*zU!VH}b>8DzD9bUTZjm^GuD2 z?f$x~hq(>+R!z#$-Sp-2>b<=u&Go-EGKFU-hi}ZQp18wq?`-)@{<}ZsR32OZcFi68 z<9j|&KQG!d`Sb$AGYWGWF})E5FywIqo^>)V(Ro=706Cw7ls zik~k!|9jUR$yc!tw_7}GDtvl5;XR;qf%B-00 z=KEb;{iua0KGs4S4<> zrJEL?dM_n?RN}jF-0MHHKCZ4S|I_Tb;{LT?+ve;~_xOG|>Fck5TPL{RDe5^Nu=f7y z`7@)}@mqcTc=Y$rtLLWYJu5vQGE+O@(f0R+Dx7b3yXoBDb0FYKSO41j9qY_(CGMoy z*Tnr7e9xP1W6K&|u(Gz+NzA_6`In&5zZIM6d|H?nUn@^>QHE9ppe|F_tZgnqu#b4Qk550%G`wsJcKg?Wx`0kVV+Vv}!$_LbNKl*8HU1R<$f$2fX zlg|fUhWLJW&ni^1{iR;{VC~b7C#4?querHt`R2@%=I-HNzQ%q&8@zZ+^`-hC70V+b z`wchlv%65A{_o3##F}XfuNAjl@xLAUzfaBCz9u%_-7)d#r>Pzv?upt>*r@TXZpMG} zxaw(+*4d9c_8+_b_}AR26P=t(my}DRUjMI_;vl}w)B4nu5LF@^e4w#_j$g1k+ZA+`>pex zLHli)_AOSk`}HHSS_dm#Hvh5FJvom3(ypc%H}-$}S^CL#-|9t=e4l)= z`}R8U{Nif)UpDXF-ww4cxNQ;r*J8qx7vIZDuivpNeKbMi>*VM2<$vvec5GMS@x`|n z<$iF`XT0(99pgqhMYlPxKVR>beL8K=4>!yHd;RyfCK`#B>j>#?gz3b(nuV*L9SKmx`EXt|ofZf9Kleb=|0)%F`%|75h?knj7Ex2@k_?(O83<#$j2IWghZUe2EPlNQwd zaQtJv{(beO?xz;@KT?wzuU2oY{orlI|6y^u+m1^&*IcWf@PdDD)Yru(rLxDRS92}u zKKkkHp8JNo-^X7ox)FK(xX)YbU%`uOLINASf8VqD;q4e9@N+~;%G(U{BT z|1^`#>UUdDE86^vv9mUu``u&r57+-KRCaTJ87Po_|LK9}Yp0y<(s-^lKH-SepZ z?&sgTi>ib_7wpY5{rR)AV1tn3%I7*3vzVpVNw80w!Co?heaj4XRkLaP?GNtCzbC8p z{CeioABX-v{CO(wa{jGn&F9WJ{JlN%)6H~#Ho;@ck0p}(i*Em^pR;@2(+#}k7waPW z>TYmPu9(dy`+c5;zjV9#%;)#+9z4!o+jLw1)VX_hd+(>0)ZE*DNwe-=?w-=s^{ZaW zHB_IuWg9f#r2Bd0>bmQ7{2yz#SzfL^HFt5ro!t4FvgZ3%PnL~+x%`@ZnT(wL8~1Hj z<6DA@V)o7~mzDkcugyi!;PC#-x8H7;>g#%bapmhXJN>Q1&9?R>&HrOE_qT4}$-*Zd zk7X8_Kf3$+uHo&Z{(s9RRzH{dUS>1zefodHA9CsSvg&E4U*uo7qkQIBU*pdg=`VW% zZXG;eV>dnfcZpd~@N=uhnx7BmN4~3kaeCvshnCHsew^v(Km2D+^%J{X%Zp#DC4PUt z+_Ixksr+&J*`>3RvR8FT*RHS6x-ZEmBfym(Uh}T&&`2dEYMYJZ@2Xr~mfc zk0(z2vTb^%@l3S(!@A#c*O)hc`F-7H@wK`c2g{xv_nrRj{cnk1Y1W-@_MfOcFWLB= zdBMD=X4x+;UHR9S{p;98*16BGTL~?TUTqvR^~_`MifcErUa5b|xz^ye?bdyD>H8W5 z*K4+aYi2vSb${pHU+JxPO4E1Uf0l54Be$L3x^JHCKbrq}y^V<5acK9e#az-_6TaqL z{CZ)r)O_XEx9q>a?W*Pd@9z6vuj)lex!bklnQzng?c2Dw@k;%tCo(tfE*>uY-Tv&g zzVI2>+~t>FPd@)YVeO}O$&L5i7RX&~{`^kc?!DZC=75%_I6keS@XL9&yIze>0oab@+smtAdP zDOaPupDkU?;6C-r=6u=po~!2-I;g(-?6F>|{f^!{-tw#8XPsLg;b&a7zfOBq{u`qy z`=7skWqI#M-Be>PV_C=Ry=T|G_c~_NdS!j{$@AxDo>TbR&$P~bfl1WP-No-(3xEBq zY(D0$UU_%^)1E^+M5FJX`}uTn!qouwJ2&$S5B&&J+ma>Fwwi78E|q&VH7|biTb%k= zrgZlGZJDF#)>`}XSFenD7+@v0baAA#*6M85uD#bPmu^0icl_$?Epqv$Uw=Q>-Lu8> z%-fq)+W)>q*Uh}YN$%>SkKe@H?{43|d-=<}Yt<(6w%YUjyf-V~{#N!;nYVAJNzYYY zw0*JWSGLvrA79F5T~h!1bKGkM%WT;zd92))O3bXMbP4r}InhKHpni z_k8znpDs>`wf%WA`APNqUycHsZ|*7!nQ{2mXDf5Nh?0}{UhO%|>AYzE&)|J8z6(A7 zXR$r|PTXU?KfbG9uPuN1?(W^V-^)&1??UH@sS_3^u30`Kp;`H8>!NksX|FB=u} z|MJ`JeqVP<>EDAN?uWlMiyXW?p?3b%j^&@X_gwqaV*jS= z*hL=szhO-8pQe1+X7$@WSI_oUdHb1)SI^g~-McTf>$kzXcYC*PKKD7gdcC~p*TVm+ z@;_(Q*3Ff<`7GN0b+mnbMfM%m_$z@o()QM!i(dTan%#W&=DTyw|C`$P;Ln!Z_e!r{ zul=l^qHF!#V*fME?=SL8_k4XFeJpGG?*;ew^uOZo&h5RtJ$c372<5&-rtjj8m0In8 z_5Jrh=IDvH&WEpvd()b_E7<<@+=tCO`{nkDR_?COzJJ_p%D%1VcUkvKRPFi87u+-F zT-39Jv!f30s{c2m?cvI2zTqq8%m&TeeYj-KmBe{JMpftjMVepaY^@ZvzPNo0$Q z+V-f!6Sr5KuI0CWdu!@KnIl_j=d9gv@!vM>^fhG{^Vh0vuPCpXv~JDopKt%ydnDJ{ zyuYw9DqvT!!|k8W5p^6t*O~k6Z8##M^X6LE7Soya^}iL(qU)3e8X4u7r~myS5&e5l zwz1vORS(y^WN+P_eUxwewVU6n{;$}eueG#xU*YPd#}3xzU;DoPdvkbH)VJ5S(%(cb z-LrG!V=IBelkIgOf2_|v5?dsEsmuJ-nVm^1`>Lnk$m;p3dsvWT-OsyahrHeYK3t$S z|Jbe1?{?cg@2Xhb|9SIV$@u-@sWyL9LZaU<{=Va|=^J-=#7+z5V)&`N@-OMa4c%u|<=lPpc{{P;Rke_eM_SN6p`@`;z@XvF{gp_UXo1CzF`d8&i$N9VF zI-k6!+L!-ayw=qI^^=0%y9KdP;1Xq!TZzMYNl7@{ahU6IcM$bnwO$qs!!)T)L9?>&HKM?ciW#pty`a@#X}ul z*)tdGnfd))e%4)o{wu4Q$L?%PH>0+-_reGGndWVE>}MB zU!l+AZ<*;bp2zo|?##V*_~rXK?tBH@%E#`$*>gO%R%-iu z_Jg0S|Fvw2oGoAZ-7Mdm$NG1ROceXc+B@$`AK#q2x^|tm{Di8fzw`dj(YG(PF>8o}iz1wtru| zNnY~7W8LHad2RRq$Glq4d+yzY=Ip&YGa}fZ&1DZ<#~x98<@Yo7$ulY$u9P}Fty;W3 z&TOy!|Nn3HMs9m!u}f2aKuu5LFt#BgbAxl2mwy6@jCx7OZz zwPXG6{dc>kfB%*nlsRwVjK8;!Mk-w2d#ilY)I9Yywc5;$vl&mlYQJ#OQrAJz@oJjC zX?@7&`scEp^UNl>mt>z)`)CkuxwEae=3}b(a?@>2g@@iml`&;I&e^&3c3io^-ovgD zZ}N>w*l)_@RfSyM;MtpG+R3_adKmW^5LoGq^n+ztcT8kW3nFlvX#hdBgzIkuC zWK89acC(*%zn0aT=ik_MxIn4n-|PvBjl1k$zq@DaW*uwGDtpGJv~boYx64wOWm9-Q z-dj8GqTj{uPhabv$jguC7L~bfdH6@$;jgm}cDOlTR;dS{RP*ji&I|QnRF$$ zV#@m7N%P-LnA9kpR;FpY@B8m3HOqc8-8(o#N!c*i_LJ%V? z8HOX1o=n+zo2g3e@U{%DoXbBK*!QvsJU$?J_^s;iX2Ye&`xnQywZ8uQdx~+%iu5<> z&zJu*WPSbWPQ)i!=vGneSCBK;xi|;#zFa5vZS9z=VX<-kq+0MIm z6zmE=?NQwPZh_x4<>{-6dfq3u_!JwgZvNw&{O{G{b%#zETBQ8&k@noe-#^(RvBLOb zaYfddb*Fb6xPLNC#YlU_+STmEc^B)A-<{^znK|>#N2bc+#5Z+`9Car5UpP5!^4WAM zMkap8ziX3x7NGPHohCX-k{~7qE!2;^G2x#rY4yl3!@o)*pU; z#3gL)uW+TkJpUQ_*6n>8Th5q!edC^&|18#3x!W;V7O*^<@{C2N*>M}A$E*B^g)z&R zEX~(cR69*xwyoxd`vd*m_e&cNzS-HgXXoR{>wlhH3Y=AZbKl*o@mjlUYee^ktYZ6iPx|omTA=h?nW)9hdBGaVimT>YygDW)PE{Fl705hDa)@>!KRB%kH0jk^!%Sb^X>Ie zj`U9!?E_gIrFNxWhYGLOj{w5w?pp*lk#(E{&#-6ITfE?YWA+E zvk_k{_c7G%!r9`<(eExfuIK-?`SYU8{x`S0AG1wtul-gyOG19P@n7@&w6(QcCN6%u zA*grR;bN1`*B2+x%HvyHC@(#|L1l+V{)ZhoT~%{U&%E~%zO9oNcy*u6Z+;iUPDHY*kNzosT)s!EvNt3xBp6V)f0Bd3ya^|{46-x#V(b2lJS@M;kWAy zdGjo`O{#giOmw+%_?><4gSPpv*E##vS?yw(?N4`qH%Yd$U9Z9={X}<0Z@eL)xTWD; zWh|f9Zwqs=dt1B;o>=~h3(@s_`7NXH#lfWIza#f%+$jEQIbUtJi~FXPjyxtlEL|xp z=FhXdyjtYVoS%g{Q|;;}O+R3I@K_0_;g1@%$cUt8zAN0H7HWwfFp-}WY1d=E`tr`X zc_&|Y1>N3uTQ%z6iIjxR-xPP(7dCP4-Qm1&cfAHzbl!j8Tds3N%(cWAx7fT|kbC&e#5wP7o@mh9)+>5^u}J&8a}%^H|Gjcs^d>s)#S@P=KBk^d zYf9fN>bjn|qVkGT`2@in&gk=o55gmJ*k&$q-~07x`{Bw>Zd(oO7EB8*EjpMUClq+< z#WvO(EQ?m3dK;g=O8C1`q~V=Mg)8->IwUiTCMqm&O#C**R_MEJ>i*;3YrAT{cxTx# ztei8kJ6pWIzo+?yt;z#Rb$t!ee!(n zPY2z-PaNO1=B$`{Yods$rLyqhlNZasPm&jCvHi6D*RKx_i)Xsu+`h}$r*yTs#dfnZ zlO${Bw`ZB&bTXLHRWmcr_^iXJwO8!Z_=BugJC-IkOih&EvfL!DW{vRO=U48C2X=*2 zEj#CONcN-C|7RJ@GtYGX{4aD_b;7jAnx6X$JgrPpIy1v`p1+lgRTKKG`D<;fx4`_U zl8v70CVvxNe)j;6ljrv{4l=t`tQIWUzGwI9*qifyaI@dc7p}N+dch7pnf}b+I_OS*fr(J>+Bo7yDu*}W&Ld9 zt@u~FIKnw#9^bvsu2AOABa=47(|Q_njN{OnUjvzE@N`L$z@_40Y@ z&olTcPyCux%Hh>oV{g3qTAA<6#t$XmmYz8_^Jm6s7NuWH<89s-bZg({FmC@lk>|?E zx=D%2Qn#HH8v@k#en0DeS0Y(W^Wp0ylYiMfW_pz(cl_m|w6A_S7Z;ql74fR3%$m32 zbIHS*M_+%uC6{!qSwA~RXSwcXzxR>rP2arymi7Ky>%Yt46Wadd&5wCE|FLN1Vb9ME za_n-~*3Fo9OkjiCc3(rrmeX|?GwLMb-UO|l93H!MUhGHjP3)q(`J`IY7e`Jxc`SDK zElcL7Gp+QCbyn@}5nC?GKTB7T>G{_w32~K|ZLN2ksagNYjlMO{)PB#-&Phl1oi5m< zKJkaq`d{r!iB4jFuUn9tvyoxf_0xY3ExoEQ`Stjm2gTKz56_)na_!rs-`ghd-o(CZ?ejO+ z~ zIbU;Oy_}?0=&FKQGlH8Qwj8Yx_A0XUzvm-$v`1VZK)+;roPyKdWncN{n*=1UuuDE6 zcXskrrT)K*tP3Zo2yb~*+qdb`j=yRqKX&>ZFa9Rnaw7543x&HcOl{T0-(H&|80UNI ztfcJwzI$oh?`B+naP#s3$*#@bt0(-bo6J0o>X$F77Eat3cRp7A+&O+WrZJmlzv+y`8@0^*7}71&cIhQyy} z-4MM;q|bEWGT~Ev9T`?$KmFLtug+ZNpj^jz`X^7yK`9i_+5S3xyLVkpPQ?>>Ee#{%4`c? z)^IUT@V<0jCEP96cUExTdy)QixA-pVrcIE(`th9I{oI9N%j3c$U5{#sWX8k7FIUz@$AB$b{$qg7n=Ai-z0=BXLXqJ}x` z&8xe9Uf*|OYG(BsnU|NZv>#S*VLtP8Pp0I_ur+(V)>l|OyQaqaeA%sQtInPaE~=9` zKihkYnP!D?%VeL$MgIyG$=o(teKf~)`!f;YUGX*<*H^4s{@dBmmGe-BtzUWUM;E^< z4clM+DLVJkv*p^uU-vHmX-_Z^og#6lBrTm|$x_WSw}o+{-mA)!jxEW2xAW$9mwl$L z`^Ag6VrR*$TqpfAZE0?@{@RSKTmKiyNW^@c`!aujz@x=|Uw3{=-ckB#wyYw*TV_YB zlj;uRLihBv4!>%l+y&f~b*Wux&jo)Pml^2Ax1J8)A?ppYWf0 ztfZ#+^gfT)&uc3m^{naon0sl5n2U?i{`qf@J{P#fen$MU0GHQicA*9z-lOOJcC5`Q z-0Gjg=f3;$*&-kHxdt-Zm5=lV`8?R6hm`KKeRBw74l6m2TeSUcIyEW1kMe7@?ow~^{H zf*TL97T>yd<<@jr|Ly0*&lO9iIJ+knvj5fkkPstR5fc8TrlgB?qgDSY_d<2S*IOex zEEd+JG>e(s^4|E+woriOWxks&PyN^F8sgF(dM4c0`d`W1w3xB9Lg4I^MSah9zA$*5 za{K)f)py5!-@eR$^3JzAC(TYiD_s?FyYH^A#Vq-Gi&Km1%DX}=m|UtBK6bMFInmf+ zcKOGJcX!V%n-}NzU2Uh&^o7R`?5;~KOq}*D&OlkNe$|F6>-{XYfAmW(sy=_?XLw<} zWJ7ni%A7lwrk=>FiSb#OwV^w8LqK!Z;d8rJ=X@=?zIxWJnX!9>7rs6>t@g;VHEy$} zD`~#9TDmiFozlgdJ8N^E*&P?%y?dJ6hJ3~2uUF;sF4|hRc;V}ug*Ptm)GYbtUH&)e zd*`}Rk)^-BPd_R0=JNrmZQW%TQ}goJo8m7$FV(J>l>2onTKVlciCq2Y*#81yx8)1J zvi8fKjXL|{{t*#X!`T6UyhPUizH0u`+w;pDT@`D&uWNsERn|}cz4Teo%e>#VO59$L zA1PkaJb1*~^mU%mUi;a*PDd`f@@wPiscYBnw%t>*&HFM-wP)L;_9LMH~4rDtnxYR>$K9-?_{dkyp}GX zNw0IVmmj&YqS*{alOD}cHFDa z`b;oV4GPz{WcXZF_3?_&trcGTuSmWtX{-wQ%VDhip2IRkDC6vbwv^Z{xwA6W`n>L} zePtH1+&_N%`u#c_Z@=yM&ECwxZ|v%`(TPpqeC9^k$#D*!Y&#!>vTrZ7-oMvXEhhZS zUX9b)8BcRRPCr-vz4M!lvCWdxCz~w=pLQj+i^_59S#Q3l9DI1ix|?O^PwzH1xaiq> zZt>mAZ@NlK-)#9k>tX69{w{0z_2ym2H<_r%&QrT!vA4DQ*G8kWm#@E++WF|s*U9OH z9DI*;#MpmL&2xL|(SP`Ta66OO{)5ZQqV9j)_;uYQy9ZM(&uFdk`TJLjKk&NKW^ZF@ zKmF~;e;=0H<|xZs-FNk_UZj2b>%|5+W)&ibn+k)smMcy3Wv=+#cKordsj63F{qefO z)&;%$H%&Kg-Y(Q0tD!bGVqe7}-0*^lVA189d`TPz5Irc;e^t7 zgBa6&6};ij`i=5ebKitbd($jE;rxugPaiq`mesF3T$I03zS=U_^6|lPbG!Sp-|j{o z{`7xRm%sGGjOk|o~eNCq?b;8X7>)B`#){dgX{@E9@_kt{ApwDq*Ax{a-H=% z!`Dh}a`lGaRo}Fn?U23t%VsifTZAa%%wsi1y_PAhsW~f)%Us*9Z+x9=V(Kd%eXBBS zQwqz3X-QX2%~?%5JU2!Z>VH33(bnMhE+cTxfnt`75O=-DX_3xBouI z3@rG1e&OenjA=@p>hM*o&5&o-DdBZOh?+kICzy?x7G?x?@~ zZMLMEjJ)1oC;i{YIHW#o4PRY7cSi=(s@8k_kHm|9l(FpG7{wnv?Y-ZbW~N`C+$DAR zesj1up820BFiCQ|sYUm*n3b{ovqaiXzJA8EPHe83ztBOmD=SwhYMt9^X)I};DN|kW zui3e|Q6~KH-UTIX3v~oHUuJZd{UkAQQg^n*zgpAf1}EBUA!C5_(TT5DEg#)C{PC^YFDg?iSLapC=k!}!|FbS}39X+){i8J_=lRdGxHjE!-Z|M6~GBR1(K&$0v3fsXr> z{+Qb@&{nqM{(Dbm`rG||n;*0NPQJCku)1~GLQk!?)8D<}*uF4hmiVJN->&8S2*2{K zzCu=N>g#})>+H7#OESjn;#$;dX54)5_|qBl8h_qmt-h%_-E!L(Q^7(zn(_hABe!g_^n&j1+b7w9oeQh1~=Ki|E|2a=yT(?Pj%VcZMG~Fh! zOZQ!NxOLF!l=KT1RtBGJ4%_^&xG~e`(02Rt`$RA1xW4nOjQ)IdlB(}w4sR#lWxcD< z_uHRwP z3wsw$ytKOG-g$HBGWJ-@%_ac<~1$#I|%Xm!hmDcUZS(u)NgN)HJWH*KX?C=&Fk9tM4Ygzwmx*>F4d&>UVoRY2wPN$Z3mbYrf%B zuvViza8YTL)$X5n+i$B0CK%o^Gy&q9K_8#@GzWqQ}HhZnsy9LLl@8pv{u_tbRZ^6TY9%;_m^0m?d zlN={~-Q&AGXvx{NAAPO%S0*Pfe{XsJ$P>rF^!e5&Vj2Q=n(h(jPP15j*YL=1UOt&p z_lVoGvpRT|K5*1LaN_60-UmPQs&34jdnr?E&Z}sJqlaIH_g%0^XVdlFBRa#o@~X~E zaapm-)29?>H<_2JW^cc{C;qIqNwKDkb=W$P42ud-g-;8)njFCeBG}4 z6CB2yuM|F=>vuMSP1|xiyR(G5ePn4tYo*A?3#oT>(^TKAlf5|W`L5G)zxE2*rQ0_j zer?zE)Ga6X?#&m^!jESk|o_}`TnnLR(XQh;wZESwY zO6=z=k5YZ^xKI1}BvDDWJ-Z9aq}`bne%P%F+rL2R#G7=sk2gC%o~i3!|MBCU zmOeRZq1Jxabh7JLx2fAK7Cp^ZaZ_bG9WK7u`r+w!OtE*C?$eX|)L(LEcd?~!XNUSJ z{gomrY=u#U8&)d+vDJU>2KR@YESsF?YP`(oM0enUh+v`I5dD4U zdpEs!asTBzp&sX+;|7nJKHE< ztEk=K*2nU7YBNvHbN>@o_icsI@(yJYeZ!ii^@f32tp_h%`TJtyfok6Fq+{3p7QMS8 zVSoEY`TUtLRkzRn@#2lVtgdtWgtmOcg<)x33zKyx+}(7K-AMl;$KjI^+g|?Y@z{Uf zWK*Tqwapz*O_hoaw&Yu7Dc?G;Ud#OJ+yARvbB-RJm-qg0RE}8AvQi22`7hRMry1t& zn8e|_x>L94lS`{lcjfVutn9VNSEa2!vmvTX{Fcmd(GQ1qu?MG>Y)t3R40trNq0A+H zM(QRzk8k{^*Im3A_cXeowri!BYHeQr8+q#xamiHg`>T58Y@f}R*?FjyZ>jWduHFUd zmu|c|lK6k;hWYc%Wy?Hk^1t8S5W%RcRe#>Y!Loi1r}x|Z$q(OThw5yJlzZ1-v{JI? z#vk|h4|+Uf^V9m;cV9Z#eYt6|`>oY)MP2{RSetiipBu;8=$98d(`{{EsKutJ^Iq=_ zyO)~$Vv68YPHl_ZuF~b3kKKHyudZk2n!(s_JF9WaDTx(Fb-#Jf+_CwVo0V{VDesd> zUHWHQ)~;?bd_DI;bl@vLoygjY&L1`u7x!oEp8l(sCvyIYXXTR}e1sFZy>GsXf5}+4 zv$(iP=j6dNyfynKI&%CAS$4HdXv4`9S7mLDo7vO)Z+rT!X_j5Q_fDC<1phz5(08vz z7TF(TL8H+2bdSZqD-Y)0q?l4*( ze>Q|+{Q|$@eN9zTi)H=8N}86fy5ktif5MeLYucf+k;zWMp}Z_YJN9eEX>WUUJ|oU+ z{^W%rCT!3BY&Dqj*Ycm7uXm{Z@a=`_r7dq~A1yfT$Ii%TymNi*g}3HX_21tvn%k21 znB$jV$n`^oGcK>U(9W~}c-!IFue>kePvZ=}?4454n$lZolz4SV1^(y`0Oi8&SiH(16;JYAHL!m)8m{|){=?z4v@Bz>iBs&#$*E;6-kTVsy> z>lcQSr@}YCIAFcDQ9atV_}XJ@yz5J9p}aI z@?oJ<&l=5+wkq|$Z?s44${UldQcu~Wxh6kb8K11_G`D!~P1TUTDSkPhl6g~7ZZ1Fk z)9mjrbKx|fR}(I;*ZaoDt{*C&E)pm2cRV|UQ9A#N%*498m$puJwDY$*sl0sFwi$ox zJvP-|*j@MP*oLark>{_hwz6I-qn$i&e_-98`Id#JX3g?+{E^N%!=+=rO3=)f>6OI+ z@1iEUOR_GywRNeS1UtmSu|un+eYk_*vtAYa!o;$iLNI|BCj7 z^46Go)J`y#?J~YAV{B<;w3#8{^VFJuDLLONt-d+P&QLqp$1*@ld^q9yfiv z-fT;|8}`QVPY1u_hCj33Y0qMs+smZ(T3|~0N6ub<+h-@T=2V?YD_T5(HE-@yU9H`p zG;8Lb^j`IK{%@;1g;(vlc{aY)&edkOC!f{WE*)`B?_blc@9b6G%l?<2*&?rC=6)FMK|{Y9Ghpug={Qro8o>*s!sx+WcJ0 zv$D|g&Bqe&$z%&0&v`s8N=Gf(z{g|NvfYK%?z(p$3hj>EwVVecEc4e_8gol>aa+1_3HiL0j_&?pV12t|(at?$am{>V|0^bccd+g{9{%XLu1tu~uL)V@a%G(T zSvE_y9C~?SO~SR}t%2uv`PTO5N9_`bFMgu-(8nOXEt2=B+2?rfoSK6Kwr*?-UpYnTl|7~4s+jMvI>-pDRxG&^4b>(ReXwr=WBBQL#Dl zM@#O$Z0joZ*)os&8|!7;uGn`=>uy%r@Lh?C(s8R{wN&+uh>(*)h7t$8)FNirRkuB~#(r#4U(v_`wlRr*toxSvO#@|moIckf{jAyNr<`-8kxG^=we}nk;-vz7&>01Q$IHv4i zk2E;6;gPY$@Alste&!h5y_h<)=A55V_LY;~aynO%DxZ-?`+2U3>VlIkU@@jjN`fN|H+to>%kp{^TR4 zRc~JCUcE74BG1}M&KeUq1J2#PsC&1a%Zdq~Zl*oE>b1~E7+RvDDbbiP0tPycsSI`cbQ2pQ)>xDqba1 zb1y?bW3ThNtyzL*OT4BWlRQ5A*1RRhZpW;+Vq!ffr~Vgz?=BmTo(_h)Zz#-l}ld$Oj#UB|$G_T!wa+@fO- z|J_@5X42i=e%V3W%w}g=M18)hY2oAUuztJAb05~j9kUg~~RI=PJbfa~{yn?3iYoDqxjl(ovgc=lo9 zhRZ$N`M>zzY~x>&yHc&S;?BEj!#Gu>k|W)#1w`uxuSTWHSayGqPaX}hP0#0Ni3;b?q*>84uo z%Vow9FU~(KtGae(_Jed;T}eLC_i+#BCY2b<-r;EupXB+uW4_9#RjvR2EUn+CV>C6b z^H{R4qXtJ$k$u|n%*Njy$#rWyqo1ETzv7DW#f=#$g~6ArXXMv9GaTStCZO=%@2P=G z`Gl!{CF|DOhJ|wdS~xE|q(AtTz}H8|+-HU0ybE~%C83~4|SBoyHW%B8=>`|ZYlNlbfxWCTHPf@YM{?YX{PbDKL)NsCXp7>q_519bgsXp@y54)!DecU|KaIZhmnKR-BRemQmN;&9iM<^vCKFv5<4^2VY*QT=Q{8RmO4Q_N>R< z@@&e#Zmy~{w^&-&_e5v*)BOINq7EM`)5|-yaegU@xZQT*Z0?LH1`0FgDBp20WV>=I zT|Uo2UMt^7Ry$ptoz;9JetDD8IoL&6`aBW!oi9WgkfJYz=+ufk;R z7iGz7mTlvixam9Jrz*M_pewN;Wo>1 z*IJ*$bMjLPWx^hZ{FZi|Jkvk;lL@o%vMF9E!KRarv(4e%eDIR);*3i+RX3ilk!!P^ zyD4AKYPR^Z|NG} z@&`eoo*QhGC+k)kJ=9$(B6gRds&S&z(?>U-J^emk-|EJL73}A;^hI_kiK<_F5U#W^ zZ-K~z3$NzPE&uYfGH-j^@wr!g>YiPXopD8P<-yFICs)gFuZ&u*-M^^#dRS0SX`{b- z-_6T2H8We~=Ioq0`SInj{$DOHm%fp^<^ERD%;o-6a~|K%zwVuSCAF^PtD5c=tNCkZ zuYGk;^4=ej+w7C>YJW`F(!6IXn`=#^^RMtJ1-qwZ@0_?dXqVnLk=^0fewwB>ZFS|G zlBs!1Oq}=I+rz8MvS;m`_H}mJ)F5VIIkUC*m)RbeH}%Dw|2}$hhxeYit1ISqfB9=$ zH`NH2gF74YHqSS`I4|sttiRJtjV!fGRs+KANtk4?Na;4 z{pXDtl>Cpi`W%bkS(f}}T1HLLGQ-4L`INKr=aTJfyzwspUC#&z~FRerH#6aPN0X<^llo}Z8Z zJn-5|MWwB=Y5mcIyH}K^$;kF}cucxB>3dh$k^@QSKFLVOR~JZL@etm;Q|NV6?(A=m zI{#Ldd!{Zns!mtQ4&J%@VXL>(z0V!t>1I8XN?YR=JI2m??0#{YBU|Sr&hjZf*BV@| zZszIgoos!ks+4=LN6vSNZdn10p)O zQg{51tbg@hGNf(k%G5KrGnRXm#D17DWz9qd=dZtvBm|8m+6-q{t>Ag?e*fi>cX`gL z>m`#eReJ7q`F`wG>!)9f6Rn)z9!{O(}dOpou z=grn*_g2_cv{Z;Q`5!gAYZMY9*Zbu4VNF%36<4oB$JnXN{kN8}_iirl+9Ub%l@p^S z|3%i!K9tdMZO!)|YpVA8K5hTeo|*Umyw)4@OQO3bWo?<(eZtbntK``2L)-ex?zODU z=HC1CQRb!%)ck*zmL22b+&Eqie;wVCsUPA`YzuX z=KB4}!QVV}a=$0^Tl=!t`hFD^#FTnl63#QbN7Mmr@qVgW? ztBtkhU`(&syyma8`nU7{ADT)Z6n9&D&TUy%TII~Mf(tVEOTx@2w3RK-OW(fEaJJHg z&6BS?%Jsw z_uJlnTYc-fr_m+7KOW4w`zJ;An(7~p>iyF-FPxiRe>&mc^5t6Zi(E>#o_N~hGk9&qF=-o$g-*Es&T{kN{m zn}u)2{yO_mxz_yc%h3KXvvpDbKVF>ccjw_Y%NB=oYq}36mByCl^1WUC{O!j#ZOb>_ zh|~(ZxJch*l4FSHb({Yuj=Zj!UL-R$NB61s4Yh}N{;~VNU+d^&wWl`O)3WD@W6nbF z9R{=W*O+x%L`bK9I%KxtO2H>eSWiSE;SLC;jc)wVgKC&etvpx+LsvU%ffHf6Hs( zKTFvk$5(P?A1_F`eYh>VTXxCj{b};WIj@xC@@_6s7MA|#cz4H5$FDIq`kPgr_xJyq zu`Z+d;;nPX)`rer``asZ;m@~^CHa3!nD!(uF<-q5VP_r#-}%xzTunab#9p;ZJPbpt6-ty<^h2uZ0gtJn-_e{KMX77<_`fFQs zR_hwkO-DmQc3+=n#U?9obam3Fb&X4pbzPo!q`BYip@66C?^mFO%_c`}JE!TMMU|x4uDY;sCkC^_<*?S`TjawEP<|TAnX&+foy87mt40qji zj+^UKQnatE`nTIRD9G39qED4tS9$u*yVYIVQQX}8c1KN*l^))3?UQ3j_Kp1elXI+! zjvp56x%T4ZO~dx$_`6f*Wjb<8xgFxSH#FF1_fSFqd&#^#g)j09e?Rxp``B^#!IQV` zv4U^x)}3&Z)ob4zw|2gMVLG&9UpGVx}RROx~8iC*jtOW>C0m$uYIBQf?Gnrc?vuK zY~$Gfb5tTM4!ys>^X*AlzVuHm6Amx7-#=~LluB!_)OC9O=GtZ2eC5L4_A?e5zrNmU zcgV!q^(t$r;WwYf`%^<)gZ_qhRn4s|T+S7KK6YK0^WmGiVs zmg}0{OM4$ycTDaS-^a_hu*H?Df-R3tJ&m5{}O z{|Bi~op#~I3QP4_n-$OHZLc}|d|~*V#);=I&f2cSsDC)-)#cVrfob{8UuK30sUVApRIJoZA(cw63zt+QpfCVABb{!zSD%wzhN_HE!$4LUj1tEAH6TrB%8ySr5?83e4S+W+WidA+(pK>C6relkm6&>?bS>-FxT~uoH-CG}BV)|)Iz>yW>$1n}S*G*fuMwL+WB(-ut*YSIi4!8# zS>5+5&doEJI!hsW^SPzw$IfsV{cpUnC{m$lacKTQ-}Y4&l54#>_Qvw{{1o;X zr}rFw+v@t~arL=3D@u|S>zDp#@DB*xKigJuskiIFNLQD#M^|F^op|-MK!ty@#+T^} zxsFS=?U?4&+8J!RMO#ev!&{@rUp^L2R5+)6aaGUy2k#ze7b@`DCEVd(v8;B*TvaWl zi_d1N7VcWV&8Jdo>O}w5b5~S_bUoY1abj9gj@!nUn=UNtzHPz8H|cJ~PrvU~d!8QP z7F^U)Z0Pjj^~D0MlMnZ={&7NHc2V@?{NSmlwterp`$<_$b){v-Mdj=ViAfLqQ>&bV z-bkK(bja`4YN-Xb#Y-+sR%UaYQ`!9KdCEzlT&uv#;m6Zt+t$=S-K*Y=XR#rLXTDb z%8d!ejSFuc$Zozg`$+=lbc1(y!g{`LUbSb#v1{{>&2cL&Zcbvem2AHJgzK={7mtmG zl`}V+#9GVj-FMxyyp+pIq0qv5kG16itDo7T=S-?L$*$UcJv3^?_PeK#`Oj8w+PI=r zB2(I~M*D~K-c46NQ$U;o+4W4}CWf7CX?`$7^sgky{xYzta={p<2~Ha1I}Midvc zt?A~k(34p7x@xt^+|K5Q2bJeGzF4Xtl`sCeG%M!+wh79;{}Py*g6e#mK5tS=I@)Nx zd)npNNddFn%uMg5r}RpN8AnZAC_gKAU8PCDafhXQmr8`h{E_ zIve(9TewpBbGQF?(KBwXJ)-;JMd;tBt@>G&w>Nc*<(~Igcj&>gM`k}$IHta8y?D)< z-|FU`+{ZV9`(ElU=&}-GS$thWT;OKTu2at@$`l#Ac{N|H&ElBL?K6CLcS`?ETrZ=f z^ffMI>ca!ZJ`2r#KC=h9iiLlUzxedMqsuax)DR^m?zNR-H5!d=GugSlr!HN%v?#H) zy8KPZ#;dyvE7C46d%NiM7lj9Q5)x*|PEOw^Bg@wP%0%?G>tm_eT#>Ta&t9N1b>hBJya@>zm)!2VQM%j(&9g@Rq}2mb><4g*6&K zof$6iey(kpzMi|k?CmzW6J`IC-gfcy&;54r`PU0MZ-365dA;}bDbuBwBp1fdi|EjFAo`xmu-yy%@}`e(znKJORPbT{pquCHTMr4gsMK`DKf;`?u(LMEPDb)hHbGABcCVvRQmF#5MZRz2J5EXeS()@~u0C&2QtHW6 z(FzZ1t38+Pa_vqY&H8j_W88Wzway@`t1$vk{#5j69Fedn*#F+JUWdzgzS!S~Is3B` zC8s3x8??@x>g}y^?_v8diSV$wFFxL>eem*~O5yTEUd`{aeg3AKFHST2e591^!-)e4 z8%4~dvf1X=A6KpKS6)?_ws?8|Im5`#6`Mb|7H(h2{8i?e#L3WtcY98qn-+L;oA%L7 zC!X!O?yUaxV599zX8V_q?b<7QPIXmDN7bG1uUy4)ZoTPVC5>fcXXL$EO_<@lm>F^6qHw>a~@(vLiydcrx3p9`hJp zomb`buwUs{{E(EA%7n{3yKI5`+Su> z&vDP8-zB#vCVl1pVZQ!t!mp|yZ)>-v^GG!%rD=Gdk^1>4O?vMSb<;a1Gqda7mu|N3 z>3-jHSn}4S%82j%&s?XhPd|M{>>K~WV=Plv&f1?<@X+bU=_LmbUUZy$VDjhLR&(X9 z-8C!FU%lYdJW;*4W1YD!H=5NHB;6*<-@fM`>%sg{T=P~+=T~2$tItiQO-E?*%4YtS zB{f^8^|@6n4mc#m_K~0YoxHUC{gB6#rAybQ6s?`g!lPET+?x5C<{6`#%NxaX=e}HX zC1d6cJ~PQPA097XaAUfqppU>ht&iv5Uz1(k&X{}ETiNA6TqW<7(nmdPo{a%FwDy&- zhh>`|+o^a(JF@B9Avew0=MSVAU)kz*Z2!#6N83$Tuv9(yqC4Y#+|bJ{@iVFWe*4SzyZhOHDY8zhoYn8P_-|ptil3#uPMI^!=51MbI>hfo zve3s_d~b?R-n?p=#mLFRroQvN+QRuSJzC!;zo?766SL;~>n*GMzs6?KkFK=b4HDJL2WF!__G|;KU)k5EM*e+}VIte3?Zm+mUQoQr zB)|EjEXVQ9+LsqBs`0Wo^L*p{=f^WFR^{?{T1e0PJlW1pf-~{pmgeX)OFr4Ih*>rH z1w-SEu7zb^bd~R#i~m2m#{R`do3=?Ve|PNZR`ZPCdt1BRbj89v=bL9r+~(el>0Gz^ z&%@yJ^6DRzkEC7>dLC_jCOVaGsoRl@Z{1B_np++BY%-b4zpPH-?!mcPx8AJaj`2Bu z$c}ybgeC8E@@01`Dwsx=>aP#>*zm!|w7l!S*9VD?h*c(a>kL@qw6494TiEyX?9$TQ z%U#RF-I*4hULU=3H>ck28Aps~OC5AI^*ecw@%gEHf1VbbzL>Fe&o0mBCxW#rb(SkH z`y%3=Q=BB#8WqpEW>TL(8H zPjuZ1_ODKvEB}d2ecmhIn>A@8gOKR_y72m02XC<}^OarvQmXRX_w+%RFM9LeJ(yTm zm8R9QNk)DS^J9t7vuqQERv0T)@v2KlJc~>_7iY30za(4U_Cx2RinXRO>7p+cuda2e zO^yqkd;ZV0#PF@B>u&GrRhR0zZQ6BZ<7NrN!lVdA$;9g$?vTP{wU;? zkY1ESJ}9-hVgwpWHgB+|J3rzkZ9q>Av&x;n-*U{?y#RT>NH=>G6lv^B)?y zaVy3?IIi%=;>_Xfo__CJe>Ap+mF!EN`6l?8x7C>{lVgcRS62I9QZ_nw>RZ}6$tt5; zp4=s`)>T+Ke5lyO-7czoY-RP&wb8ugv6~+~ow>An-BI12XZAc<)$=&uK;;W-kBq+T zjRL&SqAv;M9-A%Ny25I8p>}P0XRh0oOK(?9nvgrsNo03((;wx_?Q_Hy?R(>$yz9)m zPQDL)|6T>2(_86SE^%{$rqdju66Z@RlQnI9G>Z&YFVmBL z@~^+~)!V)-VUvsH%E(Tq80%waR-IcQr+jaLkIl>C=w*J>59#jm`SmBzJfi%`#^r$= zTT(>Nm>Fp*maDA}cqnV0bW}O`mQ`|9V%6FBf9BP}`IfF$R;{O`x86DwvG|XfhTyr? zmzMag|MJZ{<5c+4qPsi)mqypGSP*>ULBGq-_gvfj)eV!p^*Z~*9&9yt{k|{ZcjPt~ zxvnKk+Ao)QNV~l*+5Syp!9Z>D0gChHS$K;TUHG|RhWWm5 z<`kBtEZL!NO z&vq+Lw_UO~T=UM?XKxsqFD+75Nm~=OJlOyH%J7KZ^DE_U`|nBLD)cm1Rq39jUj9z? zBaEizGyc zI963`yeY{m^p^Xsl$ZRr<-(7HonA}CtZ=J0JUvUe;YzJ~swKm3$DaQ@9g@wLmaFXU zQcHE8yf-voqRn?!`nLw*ud2`HKeU`!d3MQ+xoh6%$-ei#v$?OL>FbNaeY&i2!c&xU zW!`pgjN-3<7%tT!KU+`b@{C<+Y3x49owF+!M^x>I^_N_xbmVYjS=5)WU*;smb3d2K z-*c~c&Ps2=oKhBXAGZfS%cjrjxi!;c>hh!JX$>XE3{P~+ac>PVoXxgVXtG;5$Lder zi`Rr$UVM7$jA)-=wB?n_Q4TzAZ`SQNDu4da+-=3b!UV6}RCLYDxS(<7a%cO#9U}VI z+Yc`-sJkaq?fU!1vbM9a-V1-LrYxU1U+B(DmqlD$p(VTSe(^l0TTyL&Buq6cxlVp! z{A$s5QPWj6fs=L4w1>=4UMVuUBF28|%3Y@>acOQ_b>m#^juT}o?YL%1?7bYl(0FeA z_k?cCm8FjkrL5Kqc3n}rE&HWr*@g`+bM9XB%{`bWBzh&q{-w&A^`U?D)eE<(2Kpt{ z72kOK_m$Dgs(XPP$#MVXbV|F*_N&+h3MNX;G1ZH&I(yStcJ8EWwwr#OU_9kEP3hG_LHK{U_zY>@^3E`G;a{cRUheL0X^~S!?;A)Rw_l*XdF~UdJDHiwL<~0M#b_@p z{LZ)CZkDOIVpq)ceG;L|MK4O?6;P4(V4C)KR@l56}Cx2hu7eBxyTGT+gleh_RqcR8kcEh(|=e- zTh&uqU6ac*;M#`umo2?DMQo>@{kMItA%9?+p5oE8*=h2;A7#=OC2Gx)o$=Sd>uuF7 z?U(oB{^q@1b$;_Axqs(gsx}_D85XCv$>eBFW$0g#W&hIeYScZfOeo%;r6RUj)3~+# z*~z@4;c04mC$|4vu%+s7iNROzud~C=&$@iSa$?TjO&j>d=6~FLc}w;=oxZb?*Q;uM zE@xVrZ*OP(c68&D*Z(X&s~TkOX;@m*)vRZ#u{%RySMnc*&!?6dt+ALpr{36%*ZEcZ z$v1}&J(+LUAAOspn)`T?!5*VsQ~J5B*RyLD1pK~N<)U~Zrs9{Y{UqH+xsOYt^|UUZ zJZR4K;+@aK%VNP@3nvR@n_d@~x@RYc$floDDx0RH?Mcfz|I704*0f!hRIYeEtTpne zE&Hl5&t;nW#HXx({tC_5Gkx;$O9zkeR|+kuiL?+2$p0~=UR5>k!;^`v&aDp58eg1U z7_5FnjPXOUr-jfF1HFvhZ{7r{871xO_;Pr=#U(?}3da6P-0GFQlkNt8E?jB;ZJV{{ z7US-Ik4FKAMBe0C%`4XWsd}~Yi?~$KBlY_2FMsAGXl{>wvi|;ZgH1k9I`4;@^2%-q z%~|h%JobA%r^yPqFp3i&!$guiss-+krhR%^yAGcm3s8*KsbR@7#l) zyh7Q2xewlV-kjriogZ$$e~sUL*~5QNY@0v3%pv36&N`me?hEfpur7{I+_vH0x70gL zDMde@>fBX3zDC6NLjTFGqqoFzL$%i(E6FWxKmL4v$(6fb?%hfH@?qnVz;h0p50o6J z{d}idv2un`0LNCJya$tyo2+fVvV{5a1Lxzn^(1Gtp7~MH_wtt8*_74k*`1am8}E7i zzpKNq_;-OG`<#TCk+;`IXgvAi-SULL;ef|8IcX8A`Zss>+zQBh-6y9WR61$)4CB>% zW_~KJ{y*jWMul^0wokoeGi~3ZkhQAITNNW#?I=(ZV+zyUzWrxej(YfBrTe+RqAxy3 zHkx|xPm$HF=gYHMUyEISbY*&u(SB*?1MQ0MlB-r_FK5Z>b3dluo4K=9>2NSx@}HEq z7yT5{?3Zcnuy@65Ru07p^yK{D0B8%6>N=t4DhO&>g{Bxh_XmbVV9{nb;CEZf| zT_oSX+@}p1KJ4yot3oF)P2#uOGb#OI#OFwxvi14ds6q#J^V2^gNI*(zw^ziulWW)(@knq_>6m)mRZa+X}f#(<(HG^ z!n5xch|Z~&*Hn`zHaJ;S#O}E_<=Vv8b!}Ba27G%K+-}(M=W5CQqdv`9pW~;ih{>y( zM7H1k8!uxrX@`hhn8ouMhnd?ZWSdNS_V4Q9uluq$EB#eEua#d{xk1oqe$4+GSHaYy z4tn=JgilF^o+v7Rdc9y%&L+<$`IqJXqTL3*t#t}34dj&FlEpgHMUFn+G*z$D?XPic z)434YdAs>-QZmk)uU!##bK7A(IrrtB4^;Q85?L;(sMgc|`1)U0V{0X4@1GX=4q9PP zKTCa$Tl4;O2^;(Md7j;eg65yie&4O)oU4&~>BEO*d;Iy|%{eKORqP`zwfBOIa95k9 ziNe$U>(ZiG>VIsh%R6~?jh(KfmFlT&{7vuK&d(KZ{~7LEFn{UU^O75vYsys`?K*sT zNyhQAug*1VnEbDH9y;1}vFnxdYnzEuoiZm%$GJf%eX|FyXKY%O^)v= z5}kSEZs$R}X2*xgv+gWwn&h336cTXkx$&~!k1~s$_qJG`O#GY_UhPsMRF^YN{P0Ki z&j<2P7?*3kyV4uF(|Zo5-ldt>T|T5Oo95GF;(zYy&1dr0o*a&T)U)o{uCT}@&d26W zI)C$D+<7+9WhN1FGEcWTXzfk?DWi5R(|vcPO!OKh<+YcNFO>{vZj0F-IBTMX;k8*V z@f=?t%`3b8&PG#iQ{}tZl<-OZUnb$L$mx}~Og>o*MUB0oh zG$Li4*42zvcfD#q@7{G{jnM4;2S4+@6LY83XIuY#krv*#Iqv0zbR{0kvu|e12s@ZF zJ*`1xd;jx_f^EB(Z}wcmxm??6>A&ciF6nAh^R+^s?NaV2bKO>6Agh1JY}s8kLx$2Q z}4Qt=twokWz?*2w4de!D5{r0<8>Fd_cd2M*}C2q?k0Y<|U96ZAZJA$fmED@x-}BwtXWN>ci?0byX1<}` z`yi&;xA4;@?PL6&7hY!GV*Yu7iE+k*4Z>?vBxGc(A3dFNk@>Rt7l#LG7xef!FYL7n zTPCkCRj$LrkoU+ZtCM`^ySHn`KHM&6BhI}!=zD?Ru6Ktc`W63e&1_vZJKtQ7Y3D{u z<;VoT%Z9giPt-M)4N{7|^RnoR*t)LwYnIQpugjl)wczgV*&@k(LH(b%8Ev^3l*Rg7 z@m|mArWY}rf6I4vE@5Tcx^jQ=c8)~LH@lQ?OW$H%eb*`Y>8a9nXVo^ket&UTd-e8y z?xjxzGSX!D-`SiD}!+J>#G{od`)@ck)QZ%r!@i+%fK)^nGu(kF7Rzm@yEgs-pkIBVam zNRtWwLv}S^c&zx}viNpc+}G?V9<2>4md3yT$UW`b>F+{6~pym8l_Jl-?)o(VMZ(;T8S(rYdnQD-J*`L;?Tz4jGI;`*nB&3RB-^`J3j&s1uHP&w ztZnl-Cn9x|;gh>hRnHv#csKfQae$9uXXO8eEsrf%9ebz8UDI$%$-*z-jNkOfGd~x% zvZ*e7Yv@sIuPQY=R%=%zXV%W>JzJ{fCm6mh*u1E(Axo#Ceq;8Z?T7ZqC4MdSSC9SW zF{L0}k8dgSTd{SirRtU?E;n_eYED)iySqAkKl6o2*WxdH-f^~G-_Tw&`QxjTrF(*AYfqlMCg^=s*qodn=N@FX zuat?gS|n$2A*nPwd1dfHqrHLRE9Y*%_C;^?q0=HWd0&MxeebHUuK#NNsbS)}M=$^W zSTCv(n|r{we_o}0(z85!i4`UitE`vZzQVpeRBgFde$S@7iaC}mQ?71r-SgXU;@uem zmm^hi4Zr`_8FX zkoV!XSTsZ5!R=bI+Ah|QZ;QRU`G&j5!Q}U|KbPDrzx%BAs43!h*lKC?{`BvRva1E@ z_BS6!ZEI*;pSt#P+@-^vJM=Fra;D9`=p^~yPodghz1i*k^tU@MCs#cQ=8=u$JrrQb z-M{PO<%$a>WxUp+yjnr-MKZ2FzhySxZ)p?$b@h3H?7b)t`?IeucT9Y?K-XI(+uM2H z_l-h#=jO7%HmjTe?%2xSvq{dMPo40odbjTFyURzDrCxTq`{?zQm0b<53Q})B*vq#0 zfNn*vsFwEQ6xzWU7Tl?SIZ z{oc3wxQ3Ta>!+jH3(mY-^KY85Y2n;8y*-cI*Q~tu>!jT88%dKQ7r8`mEWW()_if*r zZv{0okCdJwK zW^7tv`ilH>H52EBxW3bqI@>#2=*nr^`z!Ld&3ip5{{7B#rt?1UNJ;myNfCN!Gb^HN zPp9C*Jo!1d16f|LX1nG$J?Y5L3vXP1xG(Rp6aDf&xbVB3zy1Uv3Ex!-c3NLoYffCB zxJT^wl(qWz^NL@;nAo{&zm@GjgD;iSodmN|j?8_t=;ks0RyV#KkGB00Tb2>GRCy`a z_5PrpxhW|Px34b0d#-F{clPItqANabI%it`>7QT5{A)(l2Tx48+deyi_u8(){hMPe ze`trKOuWBbP5WcXPw&YyUawx)SH;gip=a&n&1)_n@!6X%D=nh3?CoX!Esy4!e3-f` zg?E+E)dO`e<5u6(>ez9wPqGzvhWZBk}t2=j#$SuC@7A~3htz7x^Y_F>;lD5A-Qyf*n?0dr{ zyy^q@zjaFr`hQ-KG7czr;WtXFF5ndYvPrye+0v;Jmt4B;r-a>pQo}UM+Tw=g<4?XB zY>qpBKm2TSYRbyD|5K%2hZiY!KF+au?6UhvM(ypNyWi>WmF7Bj;D)J2m*%G1xjT)0 zR+lH`|2?%s_iO!0?~L37*DC+req{PBqPETQ&#{E89E0o-1%C&gmMhn)q${J#ukM*Q zL-X^!l@{CPcz=FYl4YEz@bh@>$tS8GZ9dCr-Aj1!O(F5vjAy@RB-UIyylhhMYc=)_ zMm>)LY2LOt&{K^?ANRmo+0-QtJKuT+huD_U`Cx` zDWJETi_bnPl_!5G3jvEfZ652rG-udl_t` z|DDb1+L?z-Q|I!3wpy@cNztcg6EvPbO<8)_=$GqBp{qyday~!uVoGU>{cY|=*NuxO z``kbA(cj)&HmXzp-wv%@`LBC)=h<({e0u2Q+_T>MmcKRM%`Sqic>y znvaW(|VNMBFAd_7b|!*S_4yO~$3 zymoE;T&ri2vupW(_8OIM^A;wG%q--YG&g!_gWCkJ;J+cy?w*<+yZ(ytti+Vi3vPCv z$?d6&-VqAQ0*F@e_UZaH?2AhuE?DKiIyUU@_Z|k9%fm*^6p+$P3vd#Ub z-Q`(#67TA29NcnpS!h$r*?GVA`g{3rOkUf4+gl(>^vQdR0M4~L*FD%6<bgVqoeQnirpu%6TQq8ZmTLaTw|tM(x!R(;SN58$Uq9=4;_hvk7w4t+ znaqmYEqt2&@?ze^TXSc{mRLr-idHx4&dm(lG%w?g%~=yszv2YdsQBityO-9zU~xb7 z`LI`~?~`KFmr#5DNu3GVURh2UP3cs8+V$nf~ zpMQVnjW>H3c7&(U?B0QsOSAZ1Kl8gA_jb$X$%JWJJl1&y8czBndx@$Yedth6^Y zWq#F^l~(f;U3ovAI&S^icG2oXkG3>V?sjZ`;6uV9En=GVR`EH(4DFG3)5mPM2{>>l-wQ2@_)H(aelgd)h2QE z`Ood%2|n@K-uE?j_V0HWC`e%q0f+f#FD$G&$DJx#1vod3%AcTKiQ)AR5tjPBfB zhO>V!}s;(>&mJ&epwK9-}lF2cJ=pD zW9!fUPP^E3?ar}xm77fUckcUpF8V6#nhT2NcMohROyJkfOS#z~oflJ+f84g9$c0m~ z;=X799rgRmb{9-m{kuo^{i~yH{gqa$_oo|FF8_Yn_T(P+-=|NP?DF{DTv&eT=GKi% zj_q=oxV+qWmDvW>_p>+YHmmmDeY@;(#_3nv*WEg)crjBWUhM3-^o)x9=MFEIf7*Fx zmX`FYo+oz`fBQUnwS!@+ukPIKR-dcbgj2&;OIdH+6skAr*W7wd30JR-JHM5|RmltpO`%UM?{m+l$Cudy0>$dEm>FOi97EC;NdDeZ?=nH8UqQab$!+sZDdnbQ$ z?S`~injZ!x~x|%lse9icI+f`YuqUo|zn%U2W9ahy^ysOdFk=V$#3yTXNQe#ceX_-hI7bW5HuxymfzTN3M)xvh)N-{_W%F1!C(;C`Ax zewUJ*cKXvNc~Ni0u9gKVq&{~?`(GXT=Q|FSl($Ygr89pv=OS*$`LAy;+FT=6y{Yp4Ii|w= z_?(nQ=jLSj2%0=Qf9Sl@*`9BIUd_r(K61Y||ChxhhF<^m_g+7nJ8%1H$I5BNAAWM0 zukH&oDYzy2%+*ORwy47YbKo?#Rr$WD6}yje`E|da-D>Qlm14y*cTLeH$7`Rz{qPE3 zbyDEPjkBh2QgxGLyB}WPcl{36o1VnUE~nlVZ1yg@==5{>Y~{;8(x1;heptrkn%IRz z9o9a*uiBQ2`agHyG%dJwb)DOmM;o~GUadOz`d@g^EKjEx)y}JjpJgxI=cV}am|g6# z59=>n()VZVetS!L*He=A>jmm+xAsr$v)a7-%1+~nyvh0>KCTUZX&SU4b0$ym z1gq`4n`iC4*z_zaS>O20FWp9uk6l~TSoev%jcq%+cF*#ihi_Kd+3i|g(zL`y{O*(! z+h$BU8uKBn=BeqISb-H^!=FxT`sDq9!LKAd^Va3w7Y{jlT>QjS**!a1yiZ>I5T?$y z=Y;&4|FibJ-L2NFbiKGdu)@vr%#2ztzPrv#j##X-4O} zL$*by?B00vQKoly_9b)n*6Q9zQNP~SsPviMUFY*p&w2l=C%4)+?SIhyE@}1oqV(r` zC$F_wb7S2$n^ljNC-LmNXv0>M%lZ1(Jc)^X!9i!j_Eg+1*b^~zk#)45%cY}F9~C*h zn11)dA(vxqYmY0u)NKyQ+JE`6hyB%WKb5{HGc#ud$FQ$ox^CxW_7m6Ura6c$OkmcX zaNK6jPOj8&-8*}?uQK+udf(jeTQ(+&NxV&nXVbL9N4t1-*(O4so(-$zioA>uMrx(Uhiey;r=@_X6TI*(+9W0m5Iub%n7 z)Z|XSO~%RtQd7+C6+eFa?r!n2qH`j0)@Ez9n0_pFm0AWS7aTh#B**%=K72LCYydU4S$?BF>lA+H~%i3t1F*b9k;RjZRN=i<*nww9T*%dD^4($n=eqxJ4>AKQPOihCty3G{xn>Rcx%kUKrX`CQV55(XZ> zcM~a1&_&qN#+*Tu{n|8L)SJGlV_k#_tWgKak(>dRf)`%XJ(QoZOy-)wzFL)E};{spnp7PZi&I%CH?anHCvcO zlNf7w&*}aAt9oNq*4~hP@xNYGu8dg8;4WpAo_bpHhrM*Lp{5w z{Tu6^+P=x_T)NitTo&WpyZ1K>%INJ`x;4sp_nEApQ+{>Yp7ENn%_;0Q`%3PKoh#z| zSSC&j&YW+1O5oQ5zd=0GgtWCqu&eWrX_RDUo7?9<-hH|$kwGf=T&x5&E zR<-?RogyzD{(JYX(}zl)KFq50>UU@ZpRcK`Blb>>zjUM=JT-flv z%se7ts?emP86KW0%L|o4x5$(pZ9d@9u;!fiiA&;>tA2R~_HwVRXtiFr^H%u8b?gl} zR;Rxds1#05vgBF3Gf_86GV8~lo$Ry3(pW5SyJ}xt{QFUTJ&A! zyw0~To=4v?D9@KYxYxDs(bG+{m&Gmpd4226Nk5i;Dira}W4oUlzqd2{R|x+ER*~D) z(nY14TtbeS5f6rLuh}jgY)Xgg4Sy{p~yGJ#C(b2WB?>{Doa-RGm{P}g(s@WxT zR(x?@eP;T$SxXMu-?iOQoA2p;ag9rBl+ElbZ+5012;3gA{WH_ORdStq+3LNSYT8-$ zGcU)tecqz5AS}jh-So`8(~lfGGh?lQL$=Sdo2Q>is89J>K%mI==VH!pK$qpMU@T`Q7>c zn`63L_#o;@l{c;)y=#|QZ>pzOyJFtm_PpHM8SNWfc|4Q%%N9p} zl$<;_e{-m$%z?!bQg;g!RlEXWdj~a^>dY+!>xBLQ#<_RxlQi8{?HRTfuWnqOtg~Uw(bx)u)Hg? zbAsR^)jd@c_ozJz?R}`%u`WmIvUB{y6eq@0|B~)=O}(@_+BwMT^X^A)whQT8vaV&z z$ep@)nf8_axHHG-tKXhQ&ip~g`XAgBslOBK z5WewLS$Ei-X_4=rzc+h*?yyV4T(_%RZ;0RS<(nsF<HBFYU6?t<$@lrIGjem97vo z=kuUi_J9AJ9Zy=dta#kBSEla_L*B3d*RKmqG*#T~xm?XXXws`GR<9*%UG1m&#qM@* zD|N|t4DMT4+S{2SBEawe(@*x<%edTI%R4$(+gAlXdFc@4R#=huJnnL*K-9ec%2hl@ zesiQnu3u}ZT7Jtmm&as##og6Yf-FuQGX8p4cG`)z2lshT)suQ0eKE>icy*fn)M@uB zEY9~_cCWAP+#B#mQ%m}2z{Wb++sy5bvCeUyE#G_UZoO&vYJq9(zG=H=%C7$Z&s=n^ z`$?V8;YwOEZ_6$+J~~_T(NCr_K`vf5_Ua4a3%f$UiN3ggAx@_DxkcpJXBM$6K8crN z7B)u)YaTvdxYWHpe(71Qtj4o?d-rVL$`tB;c9DVKV+U=Cyng$F@CPB`kJcrfbmL~O zeA#uWWBb-eLDE^?>bGMm6}K;Tvu{k(V}1MX()+J@PSI9;DO!vCa=$RH+`PXd?ct** zpE=$YS8aV|WEOk$(W#5|`+l#=G+lo8z|m{xPFxLq?5uov)1qQY3ketb{*CJ=-!(m9 z_Vw`f6Vu++wXT>o$#%ySe(u?_C-2_LdnEU{_`-FAs~1$Sys`Qszq;%YQ%Uvv!vXDe zs)mh*H}eADN3Xbi*g(HW|N7t0LenE-wmC*Vyn)7`I^7?;+1;FGyZSC^Oi4b*W4G2)iNvJgg*ZID(?RC)!UseZv9v~Bj4zf zU?bo5X6|Q)nEhU4+*aR~lYQ-(W9uKuEsObA-I>ev^TF$KZlSx&&*{gXVLDY>%@$x- z_ww%3DSS_aHh;2SlXR>1&AY2oPvi17q|Oz(UhsW>SkAl6vMa5hysN3~&Fp~yIIPYdo3(y*)`0_Bf(IlX=fsv9J(-!eRBEbLK%s5c4v*)|YfLmc zUcIuH{IkPv_K~b($i12I;~mj?OMGW4%ybTncI7@j zXWydBhu%DXB*T92i`S=zK6@V(Z3&-|o9nmlzD=dR`U&~-%zJ7+EGmpzvFLa)+s4_6 z{fl#}H+=bWdE48bMG_~gek@}NFm)8)=EBrvS?Y4~ZB2)F(ed4Pf4Sa|oj3c4&!S9S zy=h9(cbZZ+@yxWm@w8xz)XlDM+qN7_WW48V>Nc@O_rP|Z--3Ao_T`hdPMOgZe6Fr~ z;o}Nx>rIkQQ$$uwSsWK@onvP4M9-+(YV%^V{mCy*W*yzGvAuW3)A0EVrqpgY5jTm| zG&|2DV#leY9bV^C7x2tYovJA`=Tpr2BMEx<`1^Tw8%2G5@l?XlF=wUsoe58uT(y4Q z@M4So(}|5Yx9u#tns(7`bJyW;`$y-L9-n1Bll=#HOD=D@x7Wx}wY$Q)!t10{=VaTk9_e;y7VE@#PiF}bX%K?`W1&B z>^AP$IJLVgdq&ViyJyO4yJka^`Hq6P0UCCuO)_bBAl^Nf;Qj9x9rBL;JJD7rq@Ov%L;|XTF%}bL`#>wOYR9 z<7w@Ig7dB%eV&@U;G3-P$Ndq)PTOO2V`DjeRWBZtow3$t0-ue5VMpsm_RXuFzh9Hy z@n+7RNs=1V=4RhoSH~ikZO0?K1%IXl1C4Z+)eX0KSbIb^v*iD;G z`(OP{S-c`ec6a%=gRZ}l3d292Sa9%Z=-kI_2d4gxcropd@FG!Nul_B09}gF7`BA7Q z(>~4khW0Ecm8WU(O~<~?zAvkET-4W)>+$*1GlQqw{prz^adrJrs9H72t6lr>ky8b- z8#*Qw?v$V1?P?(2onR-?IB%Yl$_o$aI2(hbOLrAaDCJvv(s9Ye3q0&=Kbn-SUAQHA z#q#Hq?>4{K^#%Z)2fwv}(~Oxu%r+(*i&`1Y3STiG{MC#L(?9NDSldHPSH^xKQi7?PzPG(8NT z|E8zBy<^F_z@j^z9-ToyKW@n0W!HXZ%AGTF%6ebld8sw~>ggPA`*r8bZst}7&5t;B z=Jf1kmp8gOPdh&Sd-Em}zO*$FQ`cDS^$1-otIqlG(&JgS&#ig=VWa8OPo6e$+qhx>akiFiS6(dAnY((~QEQ_KYHr-B-7_R_#YOcl^Xw^c z>v>|T)8j1HnmFssArqZH$#)Xv6hd~Y9{crn`i==b%AfDdD(hogfB(5tsng<_@ol@U z?o1c>sGsjS`RS|-*IR`r_>|gL-_5^qF-O-lH==)sH{XxFn|!mEO=i$6V-DT5-NUCm zcC%8ic>hP~k59HcA7wG0z_mT(z~b$~I|4RLp1}O!|AxtTyG$5-%IkvOrL{!O*>c$D z9KYr#E2HJUXA<`6M8zs=zkbK(t}}hlytf<_g3alj;e<)yw2GE+|7E`KB?84E*ttZ z7EH`vVyU#c{m0^M!nS-NR+EpGpH5spRfT<%^@_M^6*fC_BdO>T@yqU8?|n~F+OdPR zcx8@KyRM&a=&_LV5loDyyUp~aIYYMPY1NMRyM8mKb2VWE^B|yqwMs0 z)f4|}wOQM*zW!9!{m-iLoQCsrfp6tXQGF~kLO0&G6OEQQ6U`_UF*p51xA4|ppN}4f zt4=)$Vw?YchGwehEz3*$|2}KuT*z`u?eWqXJxx42wodlu43UqI^_A@BRLzmk*%rF} zkZI7id(E|5Z@$xezHWj_(XFjTi`3TcczgD2o#ne(0c$OQ zF3W}AIGVKo%(4#4iw2?Ed4fGF=Wn0*t>n91%EcqvM&2q$8!y~EU~qe$-<_(?!pkg2 z3+FCMTfyY~V%qtww~OR2;cAyU)o4 zPx%+gH{U7g=ck)@jV?GR?6*!nY3{x57K_7WkLRMZ7VLWbZ^;^Sdnsc>_5F)HY~0VZ z%&}P*^~_78y(vi}(KvLUul6pkW#7I(c*1FW$HyzP?z!H!t*e{oO=*_hHe+I4RXV>g zPg~_e)#=A9Bcz`1o%=E|{YIIg>SLL8>t8?pZ!P-GZ@I$54G%YJzq0x&b@D*#(=_Ev z6YJe;d$^f??$VIF@ISrE_NZN~>Xj9d^bO^J3QK3 zr2KA1;(DLLsP_$llDBrw-%{{2Y?;>rwaqv5-@9gWs~pvnE1PN7Zs)IBps3M!+PQJT z_w(#MF)>$H1^u`-O?P34&LRtsEVpNAPG+pt(|upOU$SqmbmH`9k>QtDU(08HdM01@ z`a~nm#*1m0fqZkt&aVH_>6Z|t{2_B{)YVSgtc(y<@w*S+*|bG9XO$fMIg5GCB;h>S zCwqVI6^LDTWoxk4~oB7&Yi4jlvVzs?e&Vx_?)O?I%(cB&6uu(Hu=t<44&aEH06b+i+Z}@j{*A}i7 zd#mQW(<)||{48=wHDNOxR?94Xm9*lh_~yhHU1A-ki@&~B+5D~g%%F#2i-%O+x7yrIi_-)avz{Wk(8FjDi)xWQm`;EKV zde5gY6)yH*@92`VJbzw<+Gn)Ke=qEJDond&7(MBx``&rm_GGVpoOf?+#)?+!h_yRn zOPAb<*uJSmHFEmfC(~26UdXI_d+PR`kXM;ucUUG|Z#;Z1;#FpW_7@p#(Rn=Q3kx6Z z%zw|6*vga7bnv=Iq_x);w_@k@cQ%?D8D6U1KB;!eC5NEJ+|#byd3-qk*lsITLErbb z8m_#5Q$lrQwPZ8eUi=X2urW5|?_A!0q-loHj^YE}8*i1iU!E6pY3+%At2?!eL?^#? z$g6$4_VUs~-tOh=_}NTV!+WloNxd|+3_2WiYSG*Kozb2G_L@FPI-E`(TZl+0xZVy9`&Z;#sHD zZ<#hL+1L8Z(ue7#Rud8|A3dwwZuv57;^EiMeSeOcZB@H8b` z*mGRH{}|aMwMFT9U*5zUnRK#sPFT76_NW=9Tcns?b)T}IH%V9Wt*e>cr|8o`NmGQs zE;}V7Wj>|kdV}RhldocVPm;V!*xVkko{{$b##brUtGp6lDy>3o^~JJ{vc9eAb3awu zy|wMki{cq^CXx>f=T>kkrml)OeW6*(e^RI6me%A8?unwBak3vzz2-T(!_)I+t;_Wn z5t?7xHf%duCC|DHpVSQJNZL|Zv}0e zCSxdk_~(b$Y5OkK>{E9*W);gHxG7Zj^4d$0`zL8Osa#n*Y0vJ7-+%hAjCAd4y!<}i z+hO*UuYP&mt0ZpAbeTqN=K4PQ3LUE8U%M-uiw;?Bml( z=~C7^>b|D-A9vxK^>K6vW#)wkDfiBJC( zdb4zMXy3b&&*oVDlwD^1-s(tG@3Dg3HDNcmUax&MedYhXdF%R?o{n|tJE`+2Z+XKV z-#ulf@%et7H$!Xu|82?7@DrNsANc+<*Z29cCdWBTkFJjiPFljO`+c_RT2t#Cf7zAy zTFp3`7@{V$KIMeOnXLv|j~B1ve>UgJEq|@n(%ohIQlGvxeS2_)`Jwu_3u|oO^myG} z8p%FKiS6(nzLbIxwO{LYmGD2C7m>S?P2r4r_C#Oj>_wTrlh6K?mel?3ULf%2+r(KD zzpQLwOaGFhk*>5q^GLzuGZmBf#2XvkcG>dw!^Y~TpX1m!nMi7EpH;d;_^d}2?LMit@f|}G;{i?xY*VE9`;C{U-;*IjmH*xFX+L$EY zrb$Ly9Xx3xbZF*H2Knk+$35-)ZSFPbB^-3SYICvT=7ZU>MiDi4Iy|q>T`j8XZuWlu z+p@G>DL3AJnZj=zCEUGw;+ub8tID=rvn#1B*1P{kkvmbMtdmbiGkSyG1wo@ZC&&g|FoQ<_|Kq>Yd)B4X^YWG_HpFh8SD&`=_ssYuT4kD1@7~n7CVKD9RPW{S zYF;;~Q@Hb*dyO;qLYqqdNv>|H@9tg-cz!1G{Q*AlH+OlC%+V8Da`)YrE*3T`R?n^B z!iMWlUT=KvuJ9*r&y%KOF4yY24$HpP`S!@_B#+TKv*5R4T-r-g?yu`~IxAK7e0F7= z{vJ!0t(D)7l(ns1e|y&N)yu@V&KAj-Zc<#kn)i3@EZMS&o6kBtPCWW7z7~j8T+uuC9`gh^`lOFy{D%))8Ip5;VZNAxMH{Cw(_~RM;?WEk6uAR)< zIde8GU$j2_-ugF^FLzgmZRNVV_2QZmo?^K=8Oz7_EY4^It-pOT+{OF7?`+4EDkn{= z;)h!n?~-3zv`NZs<$}X%ZIhW_Z;YPIV?V(u=vH9N&)y4sr#@C5cp0;wVN&$#YmbUQ zy^I*1RV_>zo!XzM|#7d;2Nppr>lQ%95^PA=BGSpRW+RH}z!iERJ)h z0+(Lt-sXSY=c_ZHe_X`dLzefde6_U>&04kGG1>2zOKeneeMVu_#?2Xx|LT+H{oj7* ze=FDP)!%-aF1*IR=5XXi-lv6+PVCvV>gCx#Hn%g=mRigy&A)!*eCPH3SH0EhWu6PH z5wkiZ9k?P)HuoX;c@;#Dtw-lMQHYyFBT9JeR3 zY%}?FuB@w&TS?-|=Qc&P5W%w>+qu68aj_>(bIko&=5gEI-)sA`&rB;HZ8JIjvQNwA z>W&Sro68ox$xq5Xxlg$1rIuf9k<>)%TfV=OHLh*3IsWn)CVH^UvyEGJUI$a=gCguyOfr_8rQ%O%2|**!H@c zZ}6%TmzIAE z6xl9ud1hMO^~H5tCo`YiV_DbadHlwT@1Kim-iIFXY0uS7j+mTP^6kxD_FH)#?4K+p zJX1crJ6}6xTfN(}woJS2uOiJw-Uq*rE-F8@bS`^tcF(!5i=&SC$&~GgD7>W{JGt)4 zmDd3eviX#@tc_d3@z(nKCA+Mc?yNa;nisXonC@)&ClqS>Cy58T&nz3OMVM5$@!-{Vi!517c@RGsvuFU-IETjtTj+7 zSfTiVPv}YBoS4YR-HVSFDfAqiXLNh&mvx@|=ZThV|K8`hOWv>j_aBYqqX#{{*{%Pu z=kLpJTdFP^YZqVkD=wOw=9#zUtl8<4CW+bU7unjYmd$#(cjBQbGnUu+cLx-`V^)dd zdEy;m^lxZ@Ufz z9PB;*s`7j6^4OL;vra^wMLG zK3W%k+2M@(OX;!)?^pg>eBEchAKP!a&<(*mZkn!N@_F&B_MZNwdmgL)j@$Ov+H5)jQJ<)g)(Qk-t8)xYb&!f+IFt|w3^}#SGHHFiM{OH=Re7|JLt$%KAp=q zH8t;CpM3aJ*?Lj!pS~KK!_}X1_%fJ^9*b5DyCU)EWXIy20W;mZ&))rOt^Vr9!m@wA zegE6`ZMc;ovn>1YVg@Frqu<{u+&K0_$XD3+^tKZUf_XWLyK^zuoJ}`dzb&DBG(=G*=%|1ByV2}C1H#&|J%?z)7pRVvlq}D|IER*8llmzuW@5@JL zw;eqqzw^>t+4v`=1{u@$E?F>V;>6o;?_6awIWXOIcYU{#$ZG?SSbfR5(!dp_hv&`m z{Wm3ZVUI{yTd+0v<)~W=R?RcJ-~GSS>A%4j^VmP%ejZ7*VNsvKZ#%oU-BOlm-*f|C z!v%WN_X|6}yC@ag{;PFseP8}g_w~!qUK2E#@!KivLRI|3uv_|OCYFJ++DG=qZ$JH3 zF?zn7ct)%B{Jio|$>Vb7Hh+%QR?e8&{;*i~|E~P4i`>>7t4cNR{i-|f$t)?W2amtL zKQ`52;;XcMR*!wMO=iZGcpl(N+HPHZ@6U|K5C2F!U*q-FCUNzd4O{Q;8$?8<*7V z+=mn5IO7_xlnj7+jn6M{R5TG?$sW(-!tlK9+m@Axmh+No#$Op-Zw^qk?1HxXvfzsx>i_d$2>+QsSL&h`ex9)2GkT=}G8t6|x( z80*us-T6`?S`J^bKA*z*`uNnZJ|EwW#^EH_L~ zQrOKgp;2m1)b!cLnyVRiSFV2ZxMtzh=L;=M3xjOuh;Ya}?^|d0e%Wm2?b7Clj_TN4 zu9fT!eb5=5DYHEJ%e{*+#X&X`*{*!_p1+HKNk!VF$$6^ZZrd&Y%9HeKPoDr&S#vUsQ~iwWl;08uH{9!;JNOu$=L_|N2qX1P<;@9@iswrPpK2XJ6lc+|qQ}ZA-=c$elL}c1o`N z>TT#V@8a8F=Ud{%UTO-*D$b<{Z9825w4l6w^?kiNv2~m7>CX;H<~QXsd>eH}x9sab zxrnWuD@`YNJiC4UYF2xTjn>qP=w*|&gW`*SJv@Bm)z@1gcNV?#cy)y}?Mklug`(2X zO`#iOoo2r52}{nlC_lGt@v`u&_HXm9*1SA{)DaSx(#cOIa*4yCTq^pd%4Z7Res5dxm`6Cy|=d{oVc_6 zxa=2Wk;ij;xmVxm*ynK2WXFTKbCxkCwlB~+Ab#1N?K1CS&xMNYXVPB0=sWcEf%Kud z%*EzwB?67bS#R#$=i77R>ZGgZ!en%e*1BwDn57iSTw8o<>amKe^UCxhKkt}1)!J$K zoLQXTjFQ%$4O_jHC#?L&pO3!znRfeThntp9)t|mu_`AU6)orUS-)^X1^Lc^!#)O)C z+n8j`#lN+??RfZZ{@HhCceMG0UrZ`4;M4Q5PM!bly~sgViGV4}Y_Ez9XE2-dOWa#C zzo_#C3kTEPH_1C%7H2pV+$mTvZS&ob`Let}G?rVRSnPPC$|&lis`F2$s+e5S@Q0sk z`&iv?d@SHzTNae6B>m-L+q+MznV)VK<|5%sHR`3 zzF_-RU%iMaMyGnK|BK4#fA;!5_j;}2tPs)Fv%YV*8awf(7=MJn^RgV}I_a%PZ>h=z zEp)zS?zT{t_mS44X-j5H-SMmWZFbUT|1T{`?Kqy}M>g(U_9k)V1pSy(=XN}Kq-9fN zb4-k(p2LFMkMm+!s)K_1WsfrNC3UB7GaWeZTm9PFoooMIN70j4a@{=Cez3kN`gZzp z!kkYTPkdcge7!C{d!o}58y0g}_h)jsahFvZW_;V3zIa2o;8$5A%fIE@8=pQAeBYj; zpkTJ@_u-gjA>DzTVl#y9Y!c&*)KAjc)4ujT$8zn<^PkJD$~&w)$<8kAm9+fxaKRV4 zGv>5>Fny*{buw3Tvg>mG;`D;YRXb!83QFdmJe>TAZR)AJc6;8e*XLws=~4}>DXCuj zPWqWbHX}pcjhn}JyDs}BG_{GZWcKElZ6AviFYY*Ix8C8%g|*Y0j_%;+jIF<+dH2`y zjfb9oc#&wZ&%OBR!&7`O6qj!6SjG3k^5y>EZ+qs6@t(J^JO1AD(cXg8<9@B{J2Xsn z9&BFmeL;@<{R>kox0PnCJoVlrKYV?9`GtetW+&1Nq&QW~1rNS{Wp!)j(jKh@rD-R1 z^cUZK^5s^WZY}S!I?1yybSL}oILL2)a=W$gUYj2e(-(c4&XQMs?p0VV`<;wTxS}iOkYQISC!RUsHdn|IfL!`?{>&<%dq}1xt3ZemuT` zZ^n)O%4Y78N_!2dy!8G8tq03zv?S?G%4M=UEPvN zi(k%q>ay>M#wDMXX)jh8wyaycz3T6k^;7TPJ^c38GnduwG0r?v0Zwy7bWi=#R(!N7 z{fC38=7PPmL$*A+&GF+R+kFl9g@2~M?DUBJSRT%_d;2~|^W`7%cCf2`{^#-c%eMnJ zH!GgJQ?yG(|HoTV-Ag$E+2xrXHDBMY{bBEMwz0PFDhcV}NU%j5T(jZ;h`0(b9wHs>O=CcdGKJ@apYSAM}?O8lr-Hx`mmt+XO z>Gu}&auT>*v*cU%N#DNq)tQgk0?L-`IiaWW$uwDZZ(ig#rR>z7mc{(5+5glYDav0d zb^UH+`$8XWzHsOL?;lqGI@~aA3-iGbim!GU-c`ynna(!l{*-vji7_|l1pE?>`Bs~2 zCZolD_FweW-Ju^+&EJce3APE?_efaky54=6^id(OI{(4{BAaLT;~ZVnibEDSe_OfV z?v?lH&G)?~%hYWbO!c_FMWB?OOI7tf-`vNWqMeQ=EJ=N=c3;ZZ{OZLJO}Qm&C7)PG zFZp*b=}d-7SxHaIw_Vu*+H7_nEXK1gUQ%7o62kSw`sI`imG!gUpH{!+lw<39po){t zSW@AUZQFJhpNIRja-*$oPJX(o(st6Jt)G7R2i;jW``*>LPOb z-8*5YZumcRoce2~R>sszm5FuC)iY8vViT55KM^jt{rS~t8M%g@du~-$dp+MP?fv(~ z+`M0pPYWz)nKkE#-@I)Vr~bro?Vs{0p>0;i(GAb1%h{`{q)nN)$Ts+|-;;uEhcDjU zx~pi5ScsJ$$JH3T+=O(X9U1nKw*s7hZr?X~!d$aPn&87SAZ(Yt3 z*EU+;ntW#VG{K5nZ|=Nn+r8;%zK^lK|LfzKbItu-Vm(&IieD?7yX2y7^qUhgbHB&r zmy~;y@!LD?d9q}su-Imc+$lcNe3z#*7@XCRoWs+%Ec#}T=2Mr9>o+4}ZZckf$2RfU z;e-{fcPw{rvcGrd=ryfwyS|6Tw*p^mUG((Hl)e{CJ!k&!tx(!vtbN*SO2lIR`+Q#~ zZpl8|FlDdY1OMj2=bx41_2dE?WuD(m+4%gmlmFyv_b*?8nk3t=RP}H4=YLE}2ys zJVD9k#woXsP47>?_;2jGzQ0H2?P=3|*?FGZUxX?>*tdP>(^Y|;u9J1^ZfMD7=D%o5 za`XIKY461%%p5;e!@@Ns@~V`+N}}ej2|jl_XLE9&Z8-F-OlZ5MT#NmtzF#NbF1z1t z>XGK28ZV!C{__@LC+9fgIuQw98Pq(O>Y40-3^Q~GH+!<0>z;f|^GF#=WNR!B^vz*O0A5wd`Bev~u z3D;gZ1I9OnIcpF1cdqX@U*qvfD%d7z*=L749sTdb*=uW8KRKLSH~;3|%+y__FK)bF zCcJj>$t54dCdVhbKW8f5S>SQGH}Oj!r>*!Qck?ffeh)6%J=gJhqBnJ_@z1Z(b~~y& zf1j@4>q(rHZM<^#&hlMPXCBWf`u69r!s)HKW!|z6zfAct)w)LBEWG2z^|x83Gh%KD zE)nPEdHq4-%EGK&A?5k+k0hO%@G!Y@_vFWsym@DRj|t8`b87;_&pSJOU)=forrUD& zOVik{&KE&_>w35SoBqr0-5cAUKpQbxW~J!DEjej!v6gLLi^|S#U--e~`z8G=H!m*T z^K|;Uvg?oDy_)}^-+Jv=5%==4m{_Yj-`BkBo^67+LQWmSTh`zrCLIonNaUd3TWBE1z}mvZW0QQ;&F-Om^+x|I=0U$EUsdFE-9& zd7*yn?s;97^A@r@lgn=1-M_j1pR(vR>;ICz>y_>mhumaac}ApurpOJ;)oR=J$b1hu z6R944E{pTznL`sctGPt&`o?B!d|5B$+}b%;m(ARKOR%`@V3~Nm|B4+sPo%e=og!Ua z#wYaK=gOp$ziwIQ)F!?@zsIDWFC=Vz&FoX_R{YEex+Zblr>e`RtZUBI|2D?A54~EN znI9OLrBkY#d+Dx@o_xPprRQVSwew>)%->q&^H^@liRb$`Rb;$`qD3#in!aP<>-`Iw zR&KI@Cv-5x6^%PT^7QHYNuwlbPM^Z&haYZ`W<*o(r1T#{k54*-CTZ&n_Oq+ z3f8!brfZ!GvAkR$ckYbJ>5DH^K6S5siE>wo zi=(?piOa-3jTaqFAVNttaMv=+oJmRg2UksZHJs9YL6B88aEbD%D_gpJKW$ZgF*{Pk z+q12sZ^eraE!n`wemolK7X(AC7A;cN0uif9T+Uj{E}G-$9`drI3#6*6Z^ey?ug}fg z5q3aTUoS>zpJl&FRz^Xw_W{GJ>sN5ashsn6{&&Fkh2X!IunDg?16X4kT5j$VeXz*+ z-vNOS9O}i*!e8eb^D?bwSmj$ZpYx096aFMtglaNE2H#yrg_TT1oKbJP=Y|%Cj%eO(T z-8+7$sJKP*N?r1w?U=M+HruYuLeD7=8&~|l{pf7H_Mh#C>a}aaJO0l9`~PJ2e9r}k zY?V%@{&&2R!mN5@v)ELP|N8UI!>_iV_|2km?RZJy5%_`lenk^A45 z*&Jtu3i%ezQ(gXdqU^sba<3~UZRVDV)Bb*```?!xI=hvgcHdm({p*h2>Ti>7?0Ql3 zy5iL9A2D8cEHlE5%eE*5f`O3^mP; z73>?(Xm8ylH2ZJg^eAPf|5A%Y?LBvWp1eSNeWjQo+p-eoIYP@lWQFfn@h)wv=Ub^> zyJHH=%K2V*#nm%J124VhEOwN%tIqD0)BE3X;neho%~w7uJWokFE#Q1=3(GXo#Cs8Ux7n@9c%E$; zxjil`>z{+RxNoe>MgA>i8w0t^6nFiRn$E=GFg^a(0-ZWfj~Rj;oA;b-`xE)iqtMDn zqVUDXzK`Z*;-~ftS$z>)y1(n(ez&i`f>T{R7}tj^aT8lwe{$KR73)qvc{}59{j+yg z0_HXi^`d`PpW46Z0n>RVrj``0S?)~?oLTc&GV1?o{dXHG&$3OaT4%q) z%5H~IXTqF>AAdhDKW)Ek%2Vg{56u|88RkYbC-CyF{FI)%{3Q_r{necDYG=+M0;GF@^O7r{n^&cH8x?A53@J5F?^HY+|a&2e#Y`2 z_dDd6G^IHiBifodSA;T!FsisDOgx&!@jG1Xb0*vMm1{Qq2yfk9%>MprLu9%yqvWzl zvo){wbUd`>Gjd?R$Z4GOuQI*=WQ5rD`I`=k|HR`!at{*p4O$GmjKi$r) zV|?IVugJG2pQfEUKP%|<{KW}TkNpL6)E}w^Iz?;>=niKrp7&MN_2{WXcXo>HZRj!P z{D104_|g5h7)~BOV88rNv91mi&%=0CWe?NSM$siMqHn^`m z#JJk?#Ock~><>=+kggaRD{xNn#4LkNsTXg2x{)Z;UnQ^VQY!K%n?p!dxyX0+i-MI? z3KLfaxySsTEO21m?(WIH^JX!sDC|>tHusamlf9}ATXmOkO17|Ul|0{hqAKD?s;s8b zBo=MIL#y?RJ+GiI+CR$K?YL2#N(vX8dHO=I4`fjlkhhjD; zF`LFJHTkR-xyV-dd=hJk(GXV~7Y|4yvin07lWS!CtM^9uwIMM;JxRoyKv z^ABP)NRbwu=`v|0$6mc8+s$iASAU9X6WgJFk4HKdOT@n`+?>Mhoa%ii?3?YxzbuiuKQ<}dRf%L~4LN+lRpZ+PPxF*@yd9S( z)pmuYbm6=|{)odNk65c|8vjwKSlU0sQ&Rvn*eJU&F1oNd|0-R+F7Yf|D z{z6nSZL4zPUZKaaLLYtQwwGUfyJNANU>QQqi)^b?6Q#+kpIf?c#+Z?oUx z)3NisJ=>&qt<-D(soPFVL{^`gm49fJl9ks)QRgQ=$!iKxD(-$u3z}Uhcdn_BqJr)-^6p!wpXRj(-smrdpn)u4xH2WKJ?0EqUf?U#o6XM0X!~CYEzE(8tJ4oD6(a3b?V{zbgn=k zrhc1@o-=1t-@5OC&!+9ztTM6iMO@p-jq4_z@95|3H;(K|v6cJrAlvN3I@RBfjeWXZ z2M!2KIlKGx^0N~TolZMHp(@sg$G^q%g@1Ubi}^ND6UC38Th^Jl_VwP#ynZQ6apKc$ zy$Qi3>tqt6eNV(rQjj~=ki9G7co)x%tI9^bu3n;ZgDQ+y>l_T7=D5*RR8sYVM^_E! znbjH*d(LcI5f&|YZ`BOfY?Iq-4ty%eIC48@|Ie@QShdWL{kavq?SD^&$oidEpG;mO z7_6Xl)U@^C&n;5HAG#t_FV20Zd0I&6QBIq!VC?;cR}|-%dx;;oW!aSXIosrXty=I? z@7>O+iT+Bhs)ki3#oIq!D_qsNNJH2*=|Jj?*Dm@J2P!i5*1Fs|z_m$bhlYChny*GF z>}LEqOx|;%svQqY-QQ-Xxm)DR)EOI6bCcg++mW!b_qIikqvghlB0H7uslV;z%($W{)<~bXY9)?VWyM?}MK=9J4=fp15FNmR+dty`~L0 zOVe^UpNbf42JN>@i<+|6ohSgu!nk_%t`Sf^Zv8BaQ zJ`7q#DRmraV%GGNVSu`tFFq8-WHK;WG=y`N?x8Z@x zaFe|r*Bd=|FnWDfzRVf(zKi*3+Nv}mj^e*3Y9ftP=J2j!?##M;@smw<6w5D>hA;r7$^uiPfK*4yO-sUzd@)nC#aO|7hNxg;fe%mp&g`%kjv% z)>bDU0r}pOcV}Ko6+i2JFz&I}7v`648?T(2(c3WDd=8g|xT2uLNyYn8w`^83&;8G{ z_1(eeHnMEFMGU`oY0BK~I(Sj&kE4whf4{r8J>%Tq3u_YHSMUY&U1anUJn*<}>b$F! zd~vJZI?P=1{YZ6!Z}87)LLbB&gcY=xFATI^c!6!{qT|ct4t~tsbmLn$>n--msFv3q zOfxqX>Sl^f2rGZ_tVAL`FDoN*{bu1~{2a$v4oz4bUFT)$qth9uRW{wq{)3EQ{Gyy? zGj*bhzf`;uHncNer?pFUno84}rUc=bv%f#{;;Zl?nqzZl<)d@!&324~DBQSO!6X?s{7o`_>9oPOcK zt*@>E%ro?Ni9dO;$5pYJ_hH@kkN;TutvlKut=x3*ziFd@-Hv}7MO7o1gi4;LGf!Ck zdQR;Ew|=i<4}001rvFw^6o}Xy=&+RE!1YUUll&}&F4u%+_Jn6KR$C*!9yulM8lk<& zR^8AmO{4Jks*Q{v6r@=~A|iB_uy4D&sH^P@l1veiC>D()rU?Z?UVUmb~GS>s; z`dtZ&7^06GoCsx6bB&Yt{kB)|#vEIL=(fYjll@G4UYni0w5ckzcPVSzcXWp$?Z+7~9%Odv;;u6x1@r?!AqPG@soBi%szft#+Q1cG48U|5g zOXjUJTt2&>y~40%+g7VnPpS=WMU_oE&bnYGV~~j5Ety#zru=U{WUn<6PCc9Uf7;$n z^%)B$)Z1pQ&^UQpJ7|&d;TLH(;vEqMc`n}F*SH#2Fm%eNy;xyTcwo2KH@+KoX3Cm9 z^1fDj!ELeG8Et>m=1r)yj#2q@$Yj%7)q+C;2c9(QAFI-d(OZ(AxM*#!o<#AC&#g5c zyO=u8*R;gC@*1AjPhRMgwD@F1%l5)FX=UMQPYmZCP3ydow!@MAazpSc$=>NsQ(IbB zon#PtzOQxl!C5+7y;4(;`Yx-vvSrUyn}`|WGdAq=EE8L#=>tCu1C7MYAa<`*iVN{`KrS? z>qV^ZwLa_A`?H%qckEYk>z}o`%3$#|iL_fnwbSMqJ~Sv_`esdB;rmiaKmCGo!54{Z z+g`m3VzFqxz;S)L+M!3vAF`*~of1%DWz%F>Ys8@XQ7lV%_DUY+oN~q}xe2`-*$ypT zv7v(Ax8=XR|Lt&q_0df`0jEV;>-;_)P!ktzn8uOy;=@Ia8;YrcRi7VKls>Ac`}U~A zLA7E2iDTWRej9ilbZ?)E?c9)K!w@ZTK!2fp+=cE3W`YrkB73zCZu-<{erZ%n zbUN)hlEj%IV!udfYU2ZO4k=fa&89N0`H}onzwCH)daLc#qmfZcI-B-v>qv-9_{8(L zox{oX+7l+u;G|f^j;0Ux&KYfgLwPt?GoQMXVd7TH=&6|SeClV}DkcSE$v3ad-*wMQ zNL0>W)3Z;a;HW{mG3URy=9S6o=iQD8FmOvrXVTwS@$EzqllX5Xwfk#7yUv)>TAr@3 ziNkDvhlTPEnUn7}C{=!rdzTV@J}J}TK}W}$OOr#Zf;@`sB92@;cYQ&KV}Zz-xI0UX zpM-YWtmjbwaUylcqYt`SkyoE8wwMT3=ZR-#hUzkuD17qVWA>oCqk^w-PFqaC-hA;t z8|zA5R>jrs@|(Wyt=zJEiM0nJ*E~4Xu45oD)b?c+PlObb6m!VzKeTctgdGb<5tqWpw7< zqgXIq=Z%=sZ--0TMu(f$boz=NHWgDza40Kjw9&d@7N&kONIkx&b=rwtdla@W*|%oG zo9QTo5>EIxA%OSh(+$scFHd~4N-(ivzHhRMykgSB3Hduer#gHV z?Ax6ibf+x!C$nJfp(v^H$;3d8@abILPExelEswfyg zx^SWK@pWDXo*9jd3zgPB;#)O&sm_6!VjrF~F!~0~SD*Ot6<-=)cBe^7MDwEA(%)SkS^=eQt%oEwy|NdaXDg}b zQ^a1#H{(Z6sKBI+s)d3=Lf_^!=sLON&Uo;=?5vK#%#s}!a}xLPiym$)>F96gIiho@ zzHNs|qq3jmT7zjmkyX2SivOHCw=0-~tzt>}jFZhZXIkDXdfBhT6O zYDzt$f(Mi9f=9RN3+_(oO%K=qlz!jCWVPO zY7XpO(K+>ipmg~AHx(8?D;(QO1g1Y=SUk^RQNbsk-;7=Ei}uM(RE?VvBKThXwt|uD zZl{Zm)2eSAVZL&{p~gCp!$4`4_MUR4jq3zOOmf~&%=J8cdYiAqA%#T&^4_tHDe^zJ zzllAxOZ{Q&q>r9Xn_B$cUrd&-jIO-7^D1La-I|`?-yXgEu^?a2MRD&RP6Khz{|B1G zs(2g4^hK|_hrZW{ZI_dc=(&AweiO%sBkfPO2|d)9ANC`N;qU3*lyuimF)x)$L}rQp zR8E{BC}32w_3HAZ`juajr~DO-){Tq5=delL#?wey=L*lO$R7;HeFZ0&%c=g=)mWc% zxoLlArF)dDYQvZN23Hm(^acJ%+;{ue-7C+RZ+rD$FsXT)N4S%tOOyGNeuu0Mi3@ix zNu)SV*$^Q8=To0&)=3kAo30JNpMRGW{J!A%mIKrOlooNsPnc6>wJJCMo&2-5Kc9C# zKep@sYnF+O8okx?wJzE1yx4qw;&0B&&nBI2Rev#$r~fS5496V58&hsL-MjH)Q%*=; z-Ied2N{gM68}~2kHvMC{d+(;{A31J_JT*>oIU#=Jcjo-{y-qp}JIp6dKKWfi-i zOyFPIV6>s_tf2DmJ!|BQt{>&mWLvv0wB_se+Ol&Dk~289nA};}9524_f9h@5xF?{k zd@D=p=?_BXPZX1GuybBAFip9Uw4!*`jXH(PL2jIFjsLU@&z-u>^0)EPhA92{&Uu~F zCoMbm{rhL>$t5@bT;YH5-MQwK?6&28Nmkpxf4hA5%<)v^TMH)YFHg5Ve=7WF#_eU> za%JwVR`N@TVYe&S?_IU|rov5a6)~Ha9&K!|YRjs>3F++ayv@IPT8em|6l(1|MOLuKc_X?Pqg=}m;2$C z;^&^T_J)0~_|?53WraU8|GfMo`D^j)JWj991NAQqb&{$zZ%38iiNEpoYTfZ`l5(zZ zn@p?ztNcs(=V5+w{STgp%RerE?SJR>H!+S?zjNPh-+jN4+b8SB{^$~piq5yDf*Ttj z@aMe!9iGB7)r6^D`O^L)dnH}I&wjhzr9}N-&gXK^Z~A}RHN{V&ikO| zpPNN}f07#S)yvKO^r`!3@c)EM>_^j{_#AhQ_Ly{^X@B3}bZ);-(G10p&TqcX^(QI* zg8ieUJ@wjFO!ac6mmY23b^lqNbv>&PkNn@c-?R@0naJJbOsPGwso}K5kv`_kI$qa5 zDt{{<9NAd+WcKO)H#(md8!d7vi4NKBT6BD!y?=|xCr;_JZYL(JDU!ciQl?{2xA?d3 zJM+)q9fcVFt_6AVHTx0d@^HPT_uFN+5_~G)8%Ri03JimDE!oCat zQ~pky&#qGZN%-sWA3;o+At5Dx87uy9t>8!r46FQm^qETik*%Eek@XLpmF+hzI`Mwf z-UsZ_to0AX!W1`gF6EsScqhMf|0m{r6ArE$F&}0t9!l8st6rpY?(}#@L+|qBljZk? zE6fX-51qd<|NX=Em%*+~yw`n~PV*=hcsc9kV}TH#sKP@pR?eu{d1c9E?~G~BJN_u| zz9<&8-A+<9H8VsrtnPjI`b+koqOI%O{)w#kyD7VQ)6K3p{VaxQ8yz0qMKA`jD9Lk{~XUpxPI^3UKe=@Vyn@3)`hedym^ zp@n~D`Fzq4GBEUg^beGlKEL^Q)2LARqvt)H7yeBOD*GSxD?V|YvoWCjtNF+8fmg3< zABf{UcI)zw-wKQ`|FzzlIpu~^efGuq$B&rG3I$$clvMrE=;XcT_{wcRL^nGwH*`F- zcfr?LuXcY}_c!?KbHSkCKPCTo{@&ygnDRt#GXEjJTU=Xqu)UGjxVkKVM%~*F>cLx< zW-r`0^IU9z`aAiHhAw=qPU`zOJ|$OKPW>G1JY7h{{_?*k?sB^OFR-l?lB-&H`RU>$ zWFXJv3}M+2cGHi6EA<*e4lM*|Ht!pKRZ83{wc_4`GWtS5F6s81^9nP%6E=4z ztmsbIaGCq7+2y;>9*Vx)A)r$Bdzn1P6qatPMgqnOrJ=109rc6H{>2`;<6IaX z!AT~Qn#$+}hqrjFyfvpUYi6ixso+Addl~G{^?Y9?zxuNH*OnLOKUaMDH{)jg_hWVE zf4ykv^)FNTxw|*fBg<~X))V(-PYQ2aYSZ(#{ML!%pGqTbp7EWuoF=a^VfoezoD$Ca zc@}w}3d{a3))H=A-jkePQDL$#NA&r#C9>aUY{-4EQ#ej@xt&`5AqkbF)QgEZ$v+LF zZalcgnXx1@N4aao?T9*qC))jS4I9iw?f5R+O!WD|Z7K5U5T~tKMuCEY=0Q!lqZ(!w z3p-j8`Q@TlOwZYv$h7A0jp!7$T-NQ6Pd%vH;IsQ)yHN73E=>()tpj1g36|o4_c|XZ zJDX`OH0zpt{{6D2(PwJ9R<-yge4ZqE#87aDK>D*Knu14veK$Bd|M{fJ>pn{IOTLi0 zakNum0{e#7;;}-~${Xb#$lk9$bp2dI=-;1({y#Fm9=jT`GqOvJBRFJZZBFXpV;bA7 zT=ZvJlq#PO&Hnf0{{F@vK@zPkpHc;*xE;3&_;ELyD4l+7_0i)@YV-x>v8yh{(+?O)E2ab>MCKsS~p{eepZ- zKKR;A%?BELE-imBuV;5Z2e*rfEz>8}41+iC&7OAq{#^Cp+PqJ5TP}L~b#wo2`m_AN z&r@x}+%pQFJY>A@yku5`#?%In`3k~*{~oM< zv!S+T`VM=aBhx#7n4F0EepAO=FjnGXyWm`jskYpIB~JGVIL_VF+*dgJZCdzu4##$v zFX=ArZY3Em{ca_hF7w?=UhU7!ajBWpv0nJM+=dFFef~$-yM8zozF~W;>{_$5Csxk@oZLm19 z;EB2B>U7mt4?rqg^rwDUDzq=;5J>U)Zyi2ALOADZDTS$YscBbb-}%UCn791uSq|=n ze4Au=jul$Rs2zEAaBjp283%W!I-UzEr@plOECa^+i|ye_v@<&@`?B-|-nH@iflc8871 z6Q?iJSj-N#DA%*?iGBLu{yg)-H`^t4$k=YMo&Gq@Vczf4k1sD47ph{Ma;)M(-woeH ze!(l7?JY#>_A zSdya^Cf{tBXmUs(;`QGjKN#J=ojb0PxaaZVj{AS@S8hnIdAi2JncMyNGgB7#1Sb1K z%Su`HUse0auykrmF_Y1ahYU&CPF=fYBXvB#O$hVf<53>r;Pj1OkP)JO1Ip@7!@lkIXIcpeL zY8L#@FUjJq{_^eJySw*yAHMi_TkwMS```8Ff4tRp_R06@Z+m{U3CbHj(muB5u-OMi z<$WnfruY1qvhht}lh%(}g7bx!v~V`+iOKXu6x~c0{&usa)~wd-`|=hYw-%KshRQoC zPk+o4ls9?QeeAF2;~UPRr5{4gr@mOWq1#&d+MUCd{pmGJTKcDam?*R_@Q}IJ4>zgf zefcd7n^fu)KCzd6J95LAdGD+Xt24i6-IB?FakVAR_r=waZ(p25zr5m`a&R7p*Cvms zvYTH|u^)_<{P;zniPh{}yz_&6{cZOBubU*Qk6byuScTQl!&YGTM&|FrO;?`gOxxVC zxxQs)((w(-P4Pxn$|pai)v`7x9X;()mZ2hYPtkeOUWt>d%#9tK?Hi01oXqt6tCP+A zLv7+_lllXZ7Eg3;q{@Hz$XoLGg21$%KaXcS=kH2Tow34bS>-{byfj^sX=XAN2B%Jx(y@>y@nznlg7^nJx-f-etNd-dy*6TC<2$nxy=S%_sSe%bD!p{S|&w z^4YsNbLa8R-IM7e{L5ltKbSC$(pflJ*edd+?1kf=>>8`yDDFC`Dr9B3aPmgwbnQoW zFP_w!Wd=Qz-TzACJEkPV^etAMDVgtP<*0Iw@2Q>kri_D6G$z<_-?2|w`t)wufg8*I zOj1^mn98}}yE}hw)rR7oTF0e39imJQd|HudtHn^kGEIWf;FSCpmXEWHcu%=c4*PQV z-@W_0zOE0ys<(Ib5%V8B86PD6^%d6bee~aD+U&EFbRLx+Y-#CU`SEjyK&$~X_mbyK z|9b0}I{%A)xL@?&_Ar6H>uauiuKdUTEbSJjLz$h-n&w5Ob^fa#=bf7Jb+1OF zn^ZR_rtQ^^f5_)Oz1Y?3!HSnZ)&|wCjSFqj2ywY}<0Q9h#HxtT=9+U0ZiQ@CX6vxl z-nX-P68C?t-HsL8bngG2*Rg#1RcRlgzWIWTKO)?(=SA4hJ}{C0_7ZRdwg$f{x@YsFGD0tv54xPHV>xaZsynF zr<{_x(!b2D6`dJ4ahAwQ$BA!)moT67*r0b|I;-T?f2&XD?mF?wyDGaNIA_+m0Il_B zm!G_Mk0o`}>Hq&u%q!|Yn=9$KcEQPMOmRkw78dSbE0p>m}2UHrag6Q|RXG?({@Z$h*ejPgL6;pI1f9vgsJE=vvT^0#jsXg)L{{0>PtH^!P}x@Vnp$U zDLG}SoKE^ddPPz_YNm%IpHw~6QlC91CurK4MMkT3xpb_1e#(B?l=8F}3=7Om_P*|q zT^YGelx$v2aN&XM zN6$xTEC-hVygpCjqiei;*LfY8=bILNe0wzO(#BKY&Yyev_xpTl$J@$HUw$wC@A%vB zhzrkqfy35EKJevkah5J+4!v^e{qwGAzl`SHk5An5t@6$sM~Qn%Yrbdi@wIcEa<|X& zzM{|id-GKmB)+>t0{(thYFnWoeha z<&$&HSsia5|NeE-eI1{yenGm0l<2|ZNs>0^i&XCm-adC=(S~2m`U+z8fx&@^mnVh) z;ePT?P*%`!ugJ%50er{h%vRVHd_41=+xB9dyIDJ<2@6Ym;pF=~J(CySF%l|JZ&6qw z9B=(gpS_0Z;TQY(gD$t7yBPj|t*_ym^t;2y+RQ9#`qDG+yd+9ztHiz2RC@h;_uo5v zn$E47c`lAOC9AMILhz4!u)rD4CbJ7SyEF?}d-`IDHRzyE&m|2D2o(&zUI9y;pw&p~6I zWIfxy_-o-)a}#%6t(TYky4E-#x9#^Foh$FGbKQ>3pQUx__Mh!9Y7!GPl62lR&V1D0 z`(OTt!%4QFL*@^w)4%;*+OV(e`uWq2mhYX9d4FNrS9+*LSp4H3&;L(&SA~85&)IwV z882(FGaK`iPgW;aT#z}bU^}@uBk6juLh$LFpl6rE<}}L9$@iV$rMhpf)=~MtRc9}~ z>yB7zu(6m|XX*a?iJ|jie*bOITF-E9M_XUUCyftrjh5?9r&=%N*`4B%9X=ycXwQ%K zbw7T~e~}NJacPrg?u-Tgyo~p44;gvoLnvcBj4RS5W>zh8NgOW-3}(_In^ zB^I1#yv^fLVo>FHI?2VTzvxf{o9YRD3jv3zO+QMGtZs;BTU=`_sURcdsHsrRc%EM) zP2gWdeZ8sZYzLjldLy2H_u~Zr<%$X~cEj9F}Qjh8$Y#Z0f`%9HFA5qc*g zuyBpH1M4QemH!z3Kb$U9)wf^KYTNnk=O6#Cx&QzDI)x)D@un>TE|0by$kY|wTCl%0 zktdCB#leE|_U*sZH%FhIQQ=Ue%f_d1ydfv?#E&;y(hfaP40!1-6p%YTD#3F@4x?F% zs^FaG-QJOho*%g@tZ8pQX=+rGf$HNgUXN66&TE-rax!gFinQmVbBB8kJZDd8NGbU2 zo#8HYo5SY&1b>E~$z|``xQV9G_I< zeo3;sJJPKrbM`ETvX>f>UzmTC9PHFS{f%9JtxopU~PTK>@E#K+E2q9?7R!!B$~QP9=qZ%SDb+xPsb zvM0|iD~*$9e|PbV%Y9eeDXh}3`H7b`QHVdN&m&FSQdH=Zc86+EQG3^S$vJslIqzKE znU_uFp-;ml<-N61tY!r+$^k{$CTi*?Eg=!u?%$3jXe1zxw#D z^ATI0TiG7ms2B2`Q8Q=JALb{oJx_Vw3cjG=SrGhmyYG{e4EywM@~PyPPWs)rsdjI% zsELT$qoYst%A?lrX4_{mojGy3$($3D6(m!{w5L2-o%?#TdCGxztItJD?>Wk>zvrd4 zq4k*!zG*3w_3ydNY~3ijEo?@VbkoH||J(%y4gpWoi%*|64lD4QJn?SAi43JUlgf>1 zkEOSrR%>zL#d+1ry zShrqw!t}nk3$C_Avj2Rwt3u|$p=Obw*sw!-r_0*g88@XU1;JP#B=k1n}l2Y8fR-~WgSE3Z3h*z4oqmR zI8nqh`OE~@%!bd29W8b#xpGZ>{E-XVPF!_nd8L?Kb>JhfnYgdgge7Y=7wJ@TT!_3B z?WAsh#NK_gms;ixzsP{6Yre!xdJy6HN=fgYu%CQ`vg+&KR*gSAJ?E;V{Fo%2^I53t zp8ChHiyq`|V#>%^aQn*PQ{rteiaM{yO;wGES;?fVBw)8=UxsJdU-zB2zd3rS&*z=k z+?9A*Yksc%FO7wl*6mPz*t$IT)&8wBz1;*9TVBZTx#?HGudGFBXAPHp=cFYY*%sco zp0s97(bwiFsu%K>w6wS$^1d|ldrG=ZXQTIm6@ILzgB=zzM(#~vbelD0?yA?#9HvX& zSGB~X_!@e)w=Q)HYwvehP&+v$;pVNiw^UQu{(Bg_aM-h5WvzqN4E`yvH~##Uvcg<) zxzTkMlbT%F69KE5^FC*v;op=V%9f=3U<+$QE4rd!?oMGeD$hfe$z)>OW&F01*wzCAjwFT~4e5vctPlYw2 zi=9*s#)@_O-(769Va6n}MB6o13dxrhcX%((@O*YzuY1ScZ`UWUUhrRS$E}?Dx%_)J z&RpWLFY5Xuv&y^^nu~diw_qj7RcB>`P|d&`N>0{ z@5k|?uG6M^lXuj3On0pLoNG{Aap*)`=tM)A?8fuLe2co2Eq9chnph~+trOK0bG*y; z?W4`XVVsKGL4CDHOs16cFy07oP!hL0__S_o&*f>%kuMzPZI|u;@HA~k&u`(TWsmQ1 zOg^X7bMFIV|M%i0eEALa2l+Xbf-cN%xG%6rRdo3!`CM|{sksJ_!%qZAuq~Swom_rQd3dm%raYya+jX@b$!z02{->vyz*{WpJMoO9w8NzDK5Jk)aPl;K65Ti{AuE+f+yTAMTh4y zuV+}@uwuh41xZKOdp?%}UpDXQ;!0;Qam?GSX~1E`$fh6@`=Li;|D}5(JhwHfuRHK0 z-nzNFp@?Cx?vB5Qj7%0UdUA8}lC@1i9=q%mM72w=P6|{xr}vnz$=G9C_~|1*Jf_(> zI;;3DQu!_XCaHH-PwC_4J1OV435!hE+Gc!QUSU%2gg0mUCYb~@3Rx=pyG`2M@lo~r z{gCO7{Iog8pW`)CPIJjVkFc47>orp=Tb77uTryN| zD0-xRpfTkwC!d|5kBUj}3pcsP{u52H2TmnVV;quOqVd^vJp z@(#DEcrPXj|(SdAh)A)v(s}ocuEZ_PlSMCcHn*WXG z&YMq1)-HWx(l<#z=)`)C3m&yka`i}cUUa}KT8SYrA> zaM6KMACZrpp*1OqVv`itDsN8{c%!OtbJLR8c})|24k<5);bsay@{B>yLGhP@%4+vV zztXeYr9T+R3humjV4Kc%A&F;<^B6DBPq1^S+gIXwV=v>Hj(Ha4QpbEdgeRVgEabo{Xzxj*69mm7cH^75VUcBLx;D-!IZlUpQnY` zeGLm#wLL#=$=~d1lQaCA61y$z>=Vx3S`sHjr(D7} zRrgg&yGXaJHMaoySsS&4L+T)RAF&tyUYGY-8y*I#5WCb?hZ@_uNu6cGfvu299(zk z+1Z3|4sy}O6eYw4DHF^k*j^H?xS0;5%1Bxa^D#y zo`1H!a!OE8oP0<7rb{_iQgfUqPsv}FFYCM_;X_=)y@_#sDy=_{_$?9 zzkKj~ylL|GJifDAtGz@8${RK?m&nd;a1AjLbZ)y-=_`tf3mZ-)2<0m<%>MFl{AX4mT|Qz-N4)+^MFyC;lqh9fxBAg zD*j@&+pANZ9BpQ#pYf5 zs!fD(1y++`tq==Q<9PLlPy5tus zoIEgDe!;~>^SGt%c7-{=dC7N8*JW;cN#V8){R&EEkNh8Xwg+zc!5kx9vzu|@MvIFZ zQWXDuz1g_N`t09xW@|jtRNNNsR=CDH(O&b@yUgQ;k9*6jz6#rmt504U;d$ldz16?| z$vc?|uDn%VZ|H0EX)|-?cLp0Lrt+>Sp|!^sDAgEBc|j&zHT4RduQE^jzwx!ZRtsd;g&b1~b$67m9QGsipRu?|Md2Q|*Z}W&sF302)tfKy&2bQ0E_(%P1^4wY--zG5_9pRUB>CAh9~D64*Ll3vl}jDopFarr||Y1HLZ53(@UHm zvzPIHX>7PCXjdL!_oRPLOhV_gmo2@%UHlug4}SS*Z#gsd;;EuN9+kE8RMzBse(7V8 ztW*5Es8mI<#>eUFj=HBml*)V-6{>K&7oJn1`0#ulN0`SJryZiLyVp1E^ZVBt_GlH; z{5wsbS^2v%B3!Dc%~P-cus-g?HAj~FETPWpq*iR0ZTfUciPbFabG;V~g)~@$n{KK& zUiY|t*sybYNYkl}yWMgak^%%z%BI|j{A#VKzA@YDsoFBemD|kDtNd~ks!g`s?71_~ zU18%v)xy4*tGnmC*(A#F5Fd~v3;s1gQ<)0Vw*)Lcq=#`4}_dsdn)C->>S=6)gf9rBU^v2*5XU;C^zDX6J`#kFYJxQlx)_&r(0_5Q!s)rD7l zFZ}b7d%5HK1p5yT5-Ut1J*Q3O>TmM882w5;dF-iJExr()*X3e+J%XNc%-Z^2;hWvVc*_Up|4sj) z+I8WA*`(0I6%YN{zh)fY|3TyC$5{(_tETqY{#bEpe&5`Td=F-Bm4B_}M?#kx?ySCh zlX+5Bf#<2!S7od;k1VRs}Rc6~mWwE6$uOUi#V)BZ3eM9N+G@${nF|F{c}=G)J0Z~s&MD7UGtWJBoByo4 zvnSGN@1`a0=N6TxoYbB0@crf*HI?0$SN%(0eRh(*Lia-D?q?Gdl_Ph|yutNNK1T3k z!p9p8>H%$+6zgZ%rDn=V8oCyV&eK09Em$WVV6)}df!b&PE*D;%Q<3Q5^n%4jb`k%l zf6aB8pY#=tPhZe7IyB({|7;PL)0@7fcDy_N-@f~=Qn%X2=jC5#TX3ZsCZsH!5HA*| zsXw#qe)fq*&HdJYL)+eM_~#N5KYP~=j{+0r&%d*Zn%1Ar3qSZ%tG?mKqlX*c+poC5 z{$i@bB-$a89UG`p5>2p4O8+n>nhT5GPSwyDB=PuH|h z3z@ln@&&t~r%Qh5J@QrA=y*s!rNPwo$@Vv_t2$22I{mFOM=;SU>G0p+SD&n(yqLAX zb<=uX>!QoM_10z{%ryMuk#l0jg*BRzQ@cX7R)owpQ-Ac3>1JAmVCoLRr<LfVv>-RHX&a7O&J4o?J-{T*C3MXT`1B@gk{U%%O zX#Q#RIkoN9AIrbl*H4@?s80MgN%Hm4kA)us*LUl6eNC|)N)gm*sVf*24 zMT!z#ciOo&Z+QM^hVA>nsT(F9`^$K3X9m-@oese-Q~wDcy_Deeddsq+OA8fWXHUPn zO8M#R8T`|hm9;LbJNV)9%MU?zxAIo?9$jVKMjtdf*BN6}E;noU z%Hk-_dnGG(hPg>~7%tAYFEzd6{VXiUa<;ta+2saXQue3tT&?Xt^PxW9K6Cw%Z?Wfj zia0M9-O|7NsCm7?sf#Vkr|JBb=~=b(R7=|Bl-&v5%j46|f4X%xto7@%Y1eyv<90_* z*syzJs@>UK9W(Y#cP?dY+qiXGQogr+YFVQ5hBHe;6<>Fn&3Sh81o-Mgh4n;XJbjec_jZH568%`%>oz9 za{d)8oxb?j@6=zFX9{!n6$EWgPH;c1wbpX^yBGJ0*3Ox7@79-R&f>GpWlOKVSzB`I zMXvuer^wmo>w>)3^v;NWR$DNs_?ha=6{*hhv7gl!JM}OdwQo}Ky|{Yi!VfpM&)@lT zp6C0^0gbBi&)VGna#yRmwi`67E`PR3&6nL>EGq5P%lKub3@ccFyY@C}=}yaeBOIo zUs!!{6jxVd1hJ!pZA})J;b~L(e{%cg(_ANf+xNqi3A%BjVwTxXdR~k2~2A?`m zYG&@~CAK3sT1l0ojromwDznvs>Y_I@`{#MJ)f-O{{`D}${^VI%nbY|hSkQq^fiX)6xaO}y!{U0L$rbi=7Ha`ZQCH|kAyNl*6n zTRUT8YerW7%%e{QFFBn)`1)Jiv8{r8qLeBPOVn=b7sm6dMiu2$9`z~gayqTEuXAqa z+w_c3iT0Mv3?J7`@lP5zZ0q}T;&jDawhTAf?Q4<}6C`=3-~V2BR9dF{WXi3uTQB1a zzq8%Dx10I?-p1{_tv3jB>+0Ws_hk3p@1NfK?eksm%EQUKuc3U6(cd!7AjvtUzUnUS zkp=he+KPFzL(tDa) z#8OuNy|wfqdtBBWVc(4t_4#Z3)91#d&rM0{wUXW(WEHOTI`WLG_tx9;JV9^Mb9(xX z*QG3esx{lTdP@I1spyb?-*2tgHWV6Edru9O*Ur0h>f#Qe&C4!pRW-ZZ+Hq5CyUek! z0R97CvnHCQNT$uYnfLtY&KGC8&uq(K(qVtw7`HoT#kLy}(>E9E88uhEO?&Aw(;&A^ z@0!p0y)!i=xl9Ut))_k-Yd>=A<&$HVbCzy4U-!Rf?qy3U@69J$jvJ&T=UXj*+k%_A)a71!COs*8j*q{u zZYg)~>V^C6epvC>r+4K|pRa#!`L5M1QF^Crwk%D1ZstvE?a9B+-!aPB_k6;?>384G zl#brqdhGg=Z?AJ?d@^&+swBXbRG)%wt36^OW#c2B>o9{EW!6%RN8-YV0!z^%$Q?0Ehp_&%?mnPc)H}9>bEP& zC+_@Ix-O}FUsCzy%`IoEjZCxeJUbR-GB0`YC!XRPH+Wv12v{U~a|vg1y7hWt>*Asx z^DO1(u6}v;*FWQLXZ9HyTyc`DFl92hQMjx8-_i1aOE;@5vvW#&)n?(jZ?jQ#dTP|} z*&_BX#>cv4zIFeS)yoT>|K!;IfYQT9b(ihGnP%FXar#!{^u(1b;-#712N-_+^o1cX zB0u1hbIz<>!8vS+nG*eO6Eg}HWo50tB#^cDv2VgmUajn3BF{DJ&ZyR$Y5QT=bG)EV zTA|I#YlCz?^8ttMehZ!ckI`L>;Wd#e)8v|;YO-`E-MDm&MbTNn^{L{bt~pkBWn@zO zx)%u_*Ph1dRHCrUonNIWYyLXtY8#fX4tqIPI?8>OdegK~kIDRXr+^-p@4*5wQLfbE z>HprK+UWk3Xvc;A?zCvonh4WT? zdG7+|Ruz{Ul$U*a_sQJ-)Qi5nFKv@|itXKJ{+XwK;@vCZuO`2kt@}^7@9IUNCo6LN z&bWA<-8&=E|J>Hs23P<6esI;>#9-&^S&=P^8}}Hx$EI$*`2JevtMzB3nQuF_Q#jhFH*e1R+E07$+^U$heo3Tm>2!l`Lq>M}%KD4< zz2C*De7N)C9jnQ7b@uhw^Za6-UHW?K>8`8E45wnf*Lkjw)r%^*ZnS#!vqh?cVb*gp zHau`+iOEP?ad^7Ty?;ptma|;X9=vO&d@aWKN9M%yufn90CjPbKy1DT3>V>}*pWKj$ zgLBiD}nOs{GFdHh1W zbaK7prDF#kzPx^LkHntUEBoK=Kf>p->IVW7aea%x}nZebL&`#{}FxL6T!RYRNSt3@>8zB ze1>9swdBWbuNjUMcKq-uV7844P-`hkb5Ps-#45h$;E}v9AH2>^>&-i5q!+Yj$)d|s z!=wZ(jm#z$q#DjtZWdFFnfR{aX7nB$Q6 zxQxCiZNJLn?!n#C$TdUhM?v0g%`?Vx)ol)cK2XTJ+%$Dbvd6ql<*NnVZf=y6e90oj znklftD1-0l>r9?$#;wN{joh}*=4iXj!90mWMSR%~bA6*HbJG~M9(Z7?GQq=6BZ`;# za*l4sr24G^CMqg@Zru@EW(J$-249i1%33@%b%vy-Qk?CyGXkz`S$!8gMcDdo9y?*E zU@mFII_Zv~56|l`5s7Y2=fhI1%PJ@CmT5Y$;o8{~XAR$QTc51Z=jq$E`S6>oG7pd5 zuf9x37n!}4NN81={D0o1PjfE?T@b!x zp|C?E+bqj`uSUVQ-XFI#O8La4d<=bjenkdn%-TOwG^0QGlE&l3NAGR0^YV4l>RxE< z!nD;v((ktal$#>o5BXGAFX8^QzFPgsvJawZVmFz?Hf%lghbPc+?XA_WOC8uhYMXg} zySCUT;sD37{uz(m1a_sIOBPf!15V{KcZ&iD_)|xmM})Uiz)7M_*a5I*nv70>z2kGI;aGv65#eL(3)#PWkXqZ;(*?7ryyYwPLOSzHq? zPK*-depp`{7rR37S=Rn1nrlC|oqVQgyUQc`!^?xNv({alU9-3{%5Jxj`z1%YkL~N~ zP6yUTS!#ZE;6A_agv|-}^2fQ~%=;FZ&bR4KRoL)F$<1Km?9(6I=0DWqBg58U*>tz_k2;AwNd5dTN^LwoZJ;S zv-0ZRvd<~Sij`oUqI-~2bbzEr%Ly;etc%8YVPy$|IAF*%dZ zC~aHtdXi(m;${9>(|wp;UN~|oc*Yk;i{7r6ei?^ew(2l%nt12Xto2N@PPZ=EGugx0 z?V!fa6<I3yJGnfM^ge#AnDkYxld*83%+jL%dpi5}ncaVS{mx>) zHNPe1S8RTrR~3+y@Xzwvhqi>nrnmFL?)Ug^1pCuwKtm43cs)KytH=n z()W*NF8a6p#nO^kA?sIc>q=(d2>P@*I3TF#agsZ8_njM;$_w2s-)T;I;m0}GDgEBz zwmfBPu7yGGYE~E@Fi5O5pY-XjL6*St^2~o_qR+jz-|U$i^+;{o#Ku=AHT(o+7~LOi zllYb|{rKO^_YwS`+8ufJOx6*2EO4){=0jy?g1TFluzKs|i$7G_W) zp(^Y=(Ok-TY9YHUf8vQ93sO8DOfYnl>b6n8#(31DOm|VcW`)G}JxMj4@w1p(X1;i? z`D1#LotDNer90vmcZB<_&*ga~y7TZKqbBihVs&;$UwINxv8z#SSCt;m zJ?RxIvF6+^Ud9bS>>tO!Jh#cUMxEUzhs93w_gkT*8m8-#9d9+e9aj)z>`3CbO)-Da zP`95&T52)R%$nC?VHv>=ir$yVuP?t*&t3fBMInjsCt`suPsGD+ zn42~9PHf}gS!69SZKM4*!yoL)^#wX9c3~H7w^{CCZ+ztZh40uI3FovAJc^%~g zHQ8V8$;3Y{pV{T_9^CmVf6lhE6PA0(eO=oAY0av)I)TqSK9tJ;l#@FAe0u)!t@+D0 z?N~J3C#W(~(C>cE{sW>d(@XlJm%r7W-xv^vh%0($!G6PZq3#DEFN{n^pLkm;Nkj-WUKT!qA$Iz~yK^S|Iu_-;G@0+-=826HKHa<*ski^ZgH509s!{g5qx&WzQ|WOd%Y`o87Q zIWwc!#xIr8wfROuKMFfc^2(c4_}IQPhOqrv)7qFP@E~D^(k-V1qwQv!S&e5)&fttb zywZHpn)0G~TLZT23yrVj4*1tBck9)f?tHEJ7fNjAclEE1z3p{T;pvfop|?5COfQ&o z?R8IKdX=et3io*jgSDT^e#_XMJ-|1aErw_Ayw3_gPSN5e8Pe>>3je+lJGfKqiIKdN zUE4v~A9vK&JzXf3pS@FpNk*wj=j6eC4MlwQ%6In6+!HZRt$+4|id*x(ReJwCt7fso zYC5k~E&q4fUD-yL58lhq-#0z&7PoiNGwy%2yvshn;coWzX$9tW_ja^Ce=l(G zs!pQmj@(~z_Q?&2syoBNSr)L)o7DbB){V0=vqk&Iq_^8<3ManqS`cXvuUNgi!EAHr z+k@2?*sh&;)qGcWVbJ^oHH~X_p1l9Q@rj(B^s@fvyL~5wCzvsP{8kWTqOf0H8hcpF?2%DZkVlaR%<(t1h0cfflE+dxjf?w@aW z9!yS-PLMa7G-s|8_njl>SLUx?7-pSYA(c}m^CPwVcjke7(;G7TZSoFho|={}rCq`F z{nypC9m{sjS@6cB>19CL+@F{3ZrnbdcX#c^TdU8Wko~&u^FyO}-g~PokNYoPsw~^& z?;<LRgk*87Cj)?maCYQ`5mFWAVnzEh1_0v$h`LzK2I{cN{l6T{FC zIYxEA2^`y;-lhq9{=R;*Uz#~;k_Sh?bNAWI$7inz(d+NdG!8qmc=DeLttttZ%_m=7 zs$Up+?n2o+mx=sHUgyypjrPg~r#CO`=>N;5wocG@dSOy+R@>>5#owRA3Gw;W9t^*enfD^Q z`qmFMg&B@HyVGYX95Fk)!86fzW zz2&7sq)&Z@^M_-dDibd)H+!VqTM((gW17WguUA`nrtXPV?l|@L_*sc9ZnrmhTyN!E z-O5>;cqm_7?L|P=<3{taBeUiNma5%9Vrp@8@wuXBE3Z7iS6pWE@x#xc&+BAv&)F1Z z=4+w3{Mg2QkGHRsdGN$k<968WKd}#IpLn{fM9E5H-D+7a;gTA*jc*kW-07-gSaX-7 zySzbEzkzi#Zvk&gk(8R?gsyw5qE;(STcI7fPT=Ii{MawI($+4Ezt3y7J-_cv#mukL z9~&wK?*93v;&LpqAC)mN88lA!@T0f?(Ir=DBB_H zHn)IF;nIbi9sVAxC#rLt-mde9k!eop16dXs?nht#PS{rdBH@fj&ITcw8CxDRUfL!) zFKhdm`_B()tYu{tzJGDOSMz?Q#*mExzqMf+L@^E=)Q5T zvj2YFeygmg>k6BD=gxFE*5Y<(XYjX6zwV`9X0!S8$4TXaqT=?+rP793?%Sul?8~xM zPEj~;)9&fcw`*QcxK(&%`nMgq9j_g;e2%auDSuIZ@u%ewds@DLobBe1*Nat;vM+cg zwOTOZ-J|_CLOSl|J=wdXsnz6vwMpmuV}Esn+pfO3pS2^uf-9na|HH{FQ{JzbdQ9s6 zvxKC{_7h@0rg}Zfw9d(>d*P`*U*+Db`R|&hyH5WjYGE&Uz4v}izx=I*Klto9CeGP@ zcjFXG+4V;Q!@6FyZhoql`{8-Si(M1SwUTzfz1&{(KCs|%dwxggBd)hM_9#7&zJ5aT z#HdEE$1$~H?67} zNnx#*Zb|tC*GZgQ-q@pCrF6pQRHoq!(G|P+if(hP=AN*a@f5>KY2W#8w!F5?{mY-s z$nSID;+Fd+8V62XUvb@Eqk1vlQ)?H8^-ug8D(8N!ZF;>uxHME&@B1%T)$_{>Hf$~3 zBzWW3fiqn{x}}cIb$$43>9cjWmc01Um*vdn#7xW z-9#cxv|??)TFj#RJqnk_lQui$?_4`~P1@F{Y!=%E4+QBf=AP+(Vp((8Rh?{0|IVCS zCONfoZIOHCnspq!a@kDy^7ZehZ;8wm{;fBqkc;_;<7+|jZmIRGt=VN0A1|m&ZwdL8 zB_5nF(H^$?Q(D55N(PvJM^EAe^3wB>Y$p2Vk%>dp=Y z!94yB8@719b`TI-9lZO2HoHQ!lHk|RQzphuRybHxE%X4{JuB+xu$vMmkqiPRj=P`+rrRisk&_1b)Ka%TMhEpXm*ObD~N12eK)&${<=kt zHw1m&vNbIgTYZ`Pi6G-BzjB+Qx9bWKHYOnD+;HpYHtN zQ5Ji7{{g0V7k?+cxqC(~$Nb-e+huASSFN#6%$pXxyu3Zm*XFkPJ-gd8z9zcl9SSpV z{pV$CCU&oCxu(S{FXPF+{PNpRhudFOHT@p*-D6eAt@744Z%o#2VmjT-yMpad^2xVW zg2t=&ICx1fb)By>H%vxy;-pN$IS10`Z1Yh3dB9HMdbRQsy+c=W1s*Ls;I{4*f&%`>NW^79>w{I;UrAn!c?;u+zd zhtEHMw#|LsXGgP5wmj!%RSDUiYpzySx+lkeJv(aG0zclp!tZQ4V~lT}nHX%?nEftj z&ugD$tcE-8b{?KMXQy|~w(Qo=eJ6LUWtLE#S@6w3*xc)R^2}|8v;0@O=Y~yQ(i5C3 zBan0A>K7@=a6UgttCbZm#ZnZfe;14iUfy`Q`DW?tC%+B%M4Y;kV>4a!@5H3Ql4q|D zFO%B;`sU)(oNw)=$&b_vdj1XU;z2P{*nipMF01+gGF8i7An*e4W?7N!m7# zePZYAJ9qSs-*YX!DR9;$Hm86nTFr3f&Em5qmzKrjc zs2^v>F>^w*O!x-T2oxd__6j(BA^YvI)D^0nXzq?Z9{cXG+bmzlN{R1H(-S+n_5N3dUaE_q z8p&}(`o{71!SAc~rOAH%8NreL)@uKnFG{B$=3KVnsb0aKe#`0h1dBg!9_{eH`1WqX zb*=THo?ChZmhu-Gl>T5%$$e&N^7V&XG0WyT@Arp4PuJcx@A~%R=~1$~!`|I<{kXnZ zJ~+OAOI-g&qu<&uy!!W6X)Bq+w9MyHBofh1B>cu^O7eoe(;q$QG1!- z#!~CM=|{|x)=5a^o;biFelsKg?c%(o6T1{Hy-PpfZqBW3E?a0@_-e_ew)wZS>bEUg zy=>c$u(&TRf=9(-Z|{8gIz#R8-`$<2yCOfZ_H56tjlX#AHuI(Z7vGz2dYLJjXHmcT z$Y}xTbN#~S?*E$D!e8F}X6td0P&eg^H&*|9R?@ec*;)S1{5j_)HRgo79nxKPXzR)a z#kZvtraR3!cR(a!!J4Jc+JU>K?q+=QX4gL6PX519Zs)FSKcD`Vsr%T`Na?pOcb@I! zmhF){cWdqRShLb#oBH#+gqK5;y$hFE5FE`yzXVs`q9=o?EMC z#62_pZ87DK^v&akkNL@;5IFQO=tWDZBhStrXDc()%hz0HRBw`e&vYT|fsAtWo{uwx zI+Y^ku|(eH@+qEfZzu2VeKc)y+r23hKGxX0xTmG~c&Cltr-W_4IbyQ!u5P`%)1o!j z@7%m&^Sc&q{-Qp6?H{(y>?d!8F%+2!?vZ}I<9*B1V+c4p~@>t762 zZhgI7`ZG#=Uf_kY;7DDrdgXOFwL7K7J=g8M#kzMYf1vL@|BvM}c9mZ|+kQp0_9j>3 z6Wb;0Iu0%Tay@p+&nH|#*8};NwpTS=;op&>^N08D<=;ZrVq=aye7{zPxv|DvKjw0~ z^TYd$$u$heP6ogI?ONHjbkRNC#vcc7RR{hkcbFsB@Z)UWvY&V6GjDXffBkdm8pV{G zr#gD=Z-3KOZm++WZmtl=CGK|QSJ|$x169s9HjMkbS`Ng;E9{&?>*L$Mf_Gdp` zTAOGQDAyElHsjlC-#sbY-KYF`{@@eiqW2c>eK%x#P5Lhrb8W?XSp~NOdzXuqc8c5M zn;t0$)k{71*gSJWvO-6g#*41W*N>dyJ(IuSYn#vumt*?p+mDO>)Dfs>jym5_QN6!4 z@9>?x$A8Wlzo?COtNA0gWga)b$G_|gSt7ND<+iPE>v#IyOzu9O*(Nw$=vv>O1-f4j z%t#k_|K$8pJ7WRf(_WP~s`H;2r}EvuZhQB=WP0_kqb>#QvFe9z{LjAHZ1PxW&l~Z_ zULTE)tI6HmWz1u*`*=xgcu9cObd!qfHz(bDp7Gct>*w=|&iGB$wIP|WBG><~W$`(^ z{!I0Di7lQL^4ALMeJ6*thc!QWFVZ&i`mz`4|G$Rs_BNmTdAD(eOX^PKG`I&`}J-`^VE?fda)<{gb!Q|^~1>|Vco zj=7#^vcLJ}bvs_%ESPxs-L&HBl;Z6(++tQAwB_gDT5>^N{nlNxGqpF(qrWfNy_7rD zu;fRSo_$_ZY>I5LjNkZy zgqr3%P0xL;{FswnH8#uC_o3pIUAGoYSKD6awO8^=O-#*ZOV*y`1uK5PG)>%H&3Pnb! zW?@qGyt~gi7L+SJQ@r1{9o>)4=SysPe&CGod;R$*rB`gx$UFPu@vp}DdcPF- z%^Ckk98yVmy=~r(*hunP~8(#hJs8v(_`U4e@mas3XHZjjywJK1u{H)zR{n&rcn7Geg)>QlK zf8%!8k6XocH+EIsxW6g>ety?G%fnu;TQ`)yPqp)wHlLREFjC7>HUD}`DF5&8Ta)tY z)AK*BD3;{rx4pCOrT@}T@*6*zEzOrL&sXf8n|)XLyQkBqCmBa~ z&AwnT!Rgxb%T4z!c2)L2s@y5b=zrmp|H7F9EcskVcS?WX_*iVy+$}|#XLWYp+r-ww zUGn+ori~W&Y*Hs09uKS9uq1D-!u(HnA01n|H}#j_X2YMKde25$%sbwdcWr&*i){YQ zHh$N?RqnfXdF$F|t9d?`&R@6otaxJ5e5dbg4F6sWteyWvtm6I0f*Z>&FXVpZA#x*B z($??ZcE-YEoVx$NGH5({Z_Hrym#Izq;RmL+;JN=(7c7{2Z`qAK+|kGD4CAxD&c4m4 z&pmtH!TSA~rP*gM&3m40v(c8Z?#;Uw@5N92IV8Vp_ulzSx8J?{?)R5X);`A*#ANC@ zZg;Ku+@BE6?f*$^_qG#i-Pz`PH`*f?v&L7lOTB;o>#u@%@n1F*fuzqOg0=HP?|cwU z+HU`H+SjbzNz=@W*sG`&PEIWAH2yl4@6>R6sOUY>!f*4j&lkL`!>6x(!DE#F;pmcl?T-1&Hca)q z$r4m7Q4u`h&C1iSuVpPe`tbY)zQPU1c8BlW+R>Nyu>R_qqsy9K+?^4w;wT=srb@x? zgS6yl6SeOaY8>oVf*(Hmye~c0?;Y^s>)v>Vgx^_aX_B2P)2FMZwVcWq>D>F=_46MF zlZUCFPPbjH-`HYu4+wFb*^_$7fhr#R3J-zoeOxSq&@3e1MU1W~b{{ESsAiJO8_2b8S`wxE=aQwgW z`t$DHfA}9*)iPfHnYrrzqT7#UBl?xz*fYF78moBSPyF?l^$V=_H)b)q*B*Mg;+}2s ziTmef>^xgE%+m%A>Vp&h`e$tFO5LIw}?jd*ngNiW+TxS$+6B1HQ-f}9e;Lhw2 zmA%JaH%-4ev)cH4m)XyJBW?ZZ%U2$=OMR|1@49ur9R|yxhM9&Im3HypNvZsZxUb4h0A@5YJ*mu zm#Nz0_UX-4<$l-WJ!iJ}N*c#}4|{!2>bBi^?mKx^&)3b)|NlmEbI-NJr{AL2_ub^& zmi{M6`D5I){@?5JmtNtU(QY~G+s(51${lyk*}0cTZr3aCj6a@uqs`K47SFoxtB!8j zV({1YEqBd^&jK-znpb{%n7Z-BarTpcFE5f0|L@^_`N_O;LpTh6|+fG5}^V0b1jZZn3 z?Ems}bJ67JF#kE*_Fn3Ex=rwGuaeKi=m{^M6$Z&kMU-|_{0&!>En}+OrI#D`;Om`$ z=g;rHlrH~h(6jT`>08g*uC$*i|5meoskLu-Q^uh>_KGom z%RJ`n>AAbYJfkpo{jnL`68qC$+HNmvoB#Sk={o%bTUWpIXLeYsE%J5C#kn?`|1O*N zbVx3()#qwO=JGx7o&x;`1$#< zCCVyO^A$9Ms~)VY^(|9g#(Gp{_pYt?*2tD`K2yt{_4(e+QUL}}_w7547nY}S?w|Rn zN1gv#_mP!%R2lo{?z|_OCCKyp{8y!QOM`w*yPojFtcm&b-Hq{i-)y`YayJ)6@4UVC zs+V+~p7NpXi~Ltl2xriGy=ivkwX^eH-i(;sy8fF_?71EH@6FG-^X+O_K>d!T`@gB) z$&1}{Ta-^;$L6N$ci#)?_a$52&8oGuE>QljtbQV_>T03=`^M~VuYd3QW|My)KHBD- z(0Rp5>0cLgFVEAF4qy1ZMPP&Q{bRE#wlTcPdV5g4#%uq+^@|qpOU{#u+%-YncyV-8 zO-}O5pYAsG>tpuCr@l`Xw&ShZE8RUav!=`Mv%!liJPVhlzC2lTzv|HDqc0Cn zdw%@;vq}ABC&GSQJG^#z{Ab;&9lVm$de5|+=X$x%Tq*WgM&^9`x3k-KOGZ6x?~Ttp z{*CF)y{L2R-iBzeTEu^B)w^vo<)#EUKTO~7dAEwX~%MC z&b~9z3)AbT=y{on`LdRGHgU?nJS??f=Jo?0**@%1-162=`0wLdrERX$Uc2yoRLQ?- zzjAJp)EB?*2@Cw0C;fQk&%65e*%zm8dQ=Oaus_(^<;_|6yQr1>a7X_vk<8hT7MN6X zP58wVZEY0$>c+mgmrU-g{mZ`W``cTuzE0W2cwpPtDZAJiW=pKf{$?)3%+>L`MCLrh zH@|~hcl(#xD3|OH6RF*u?pwZjUeN!-^WSu)Yref`{@3>R=Xp!No%yEoKI8Y(d9~}^ zer-rUEX}|@|9eiwoz01?2@jbI-b{A4oRYquwNEtvi)q1;@&khQ%vx?IE|QgKocAq(f4VI-dL%eItUCbAMa!W7!;= z*8lg!BG+vw)Jc52*O5=~xZl-k^Q*U>dz@LPsu{FnrH4u3Z60@j<^KYW@BeOjx?1e< z9J{#Xxx1YL>t>m8G~@+*x%Xz}zgg>9R;lj48NAI%{_y7+7jI`-9s29Ao&R=hmt|d? zfxmPAy=*P}FE4)fEzqsq)0rrFaP#%Q$FwJYFZrwa{ExtbmG!>wPp(Tpma`}A!NPZs z|JGF;{?hB%CpJHP;@5PMuiyNZozv2_-_JPN|IDjkmX8r4$x3(i>gUe5x|Q=uzz;R6 z8%6t4BEX5EuzKl}LK zZT^%S>+W@$>HLoc_avq3Ur22DecL-kp7~qkOY_xQJ}`Sk6|mxv#C7hL!1 z7fZkXmr+UDTR-fvfZzp-Pw@@gc^(Au-zk(X3F&xY5?ix9ZvFF1x08}L<#_Q3A)ooHr#HCM2-{Guy)$uGY)y~&#S`tO>Y z`1gD7y3M^8Y@g=2}fue>X)%~%*&+pBnZ*{}Sp!(mQ>b@nB;^Y%W!EgmcHZTm~KCLqt{XQl;f z=12Wsjz6Z~e0|?>Qag{T5p&hv`CPjb9?1sSl_$KmtyuHtR`>3MOd3Obk`%hkw-10xXTKk=UR44CTq9MLNYJTFWe*Nq2 zPj2O3J6^S^cDr5WyOZDUOl9AA?nvc-%OK9A3wBCVxg~%6J8;+T+cV*n74I+2+ID-N zBJXp_TXk18mF2gq&Z~63Sk-!dO2g*gp6mKP*tOVm9!!7zwzrzyhVSppH$RhJ1l^xs5@ery=i@0GeKy}|7vGhsG`#m0 zE>H;gkh1Qc(*+l{yJoxx?AW~bJzn&g`_3mlokYngf1V4ht+#brwD0Nyvri7`F>6%3 zpUS-s+_-tU!WRCy#r1obHDwN0$#JnAOD;88U)L1(e@~g%6Zca#v0DS(O)aN?-6Z$$ zz+BUeS94`2&YX3N{rj=^`rHzqTQ;3izk5JBI#BFbkHVi~V?*h*MCpe=E27@cs1kjB zwtErBp_j)!wwj1_h+Y4hcsK0Iv+@-iO%9)%|0q3%@1xNnIjQX3JcTQgEDu#}n;T`c zVy1}8u2zXcedE3vN6Wsa{`|aS(bAj$=gFR0`n+@6$G0*!diP{!Oz++yd5$O8P_%=i zbxXv{`CPwPrcO`NW9M7;{y*!t|0|0$_C&t)e)wZc_^UI2c2*jB@1OmZUp#ZqV(TtW zXUW_E_OlmbZ6e}%<1GXP`!!~sF<($oALmgUzc{ZfCI7>&D4}gF2R`L$KHFMn9xMN& ziQoITb_8n2C)hS&A%JKHqo4UuVkLf(_{arIqUV$HMT$37-cQ}E%=q~ z+u6Blwtnlgb}ZDMR%JKmUhkj97M}!zH-DJiR&e5j!s;CEZ|sK0cdvYTEAXKIhE1`v z{{W9>s)L8;^(XVtr6uN23vLQ=f6+;`a`9>^7;15Q@6do zCwrQ^^0$tT>e=~)^PV1abTo5$D0C)e`DXppf}QDMM_#;^oG%@5=#}~2$&oi_@6tbW z?(MUq+m-$EpIrEOaPgnpkyo#8bw0gw*=_sm&Cw6v&-irdfxfS7)su+(ABz(%|4uA< z8loM1{pRP~N9X4s+xX?^@3N-*KeitEd@$h4?OoH&uYNtRz2*PcMg|Ha_={-{Pm#e(G;z z6IW?+DVbl5U8dRje$J#v(p=j-+P?Iu+`7;It5VZ^mO{cfhUQG5NbO@5oJ{nw$J@BZ~>Hm;ou%!O1l^Bwo!E4A6nJW2o1Biq|4alZ2TW;4B; zxBbgql(c_#&~2&XF6KX1UYcdI&p!6Gu}H-F+l8ua*LhA<-CZ}m;cn0RH(8sbAFBL+ zB6y>^Wc$suuRFhd`&NB9b9Rzi9p8dN&AnXPmT$Ztd+ro#f_PhS@k{9guXg{}QH^k0 zHp}~d*qn@i-4=r1<7Q_5U3*YOP4~%n#$Qb7^#=l8KD6>&mG@q8?Y)#Z(;0G2+t0S& zNIDfX`MtlP^=z>eQMa!PG)lT;UxzQAp%qdVFtSxcSMXU^9-F896%kOO( z)9%R2mb=fM63TPzbxm$?b^MH3Ynqq+dj9NB(O1609jBjdJN|HM5w}?Wk8c4w|7KZj zE_!`*bH0D~cQ>E#X*u&=#T@(ddj7QT?-$i7M5{h!q@VxfT=(916U(3KWS)HgM~a?|Wj*igP{{&tHy+r#W)`7dvg-~1z0rtV+c)mR>T`v+Nao=t0U)N7^oSQRA>Y}0(*V!L@25oy>R>kN3`cquEH@fa~nXS2_dMm&9#+KdsRkzF)SM*PH{Iuv> zzqq;JiQ~uKPu^6keyLLK_pcp>*ROPW+RHNfzrH9^_<_;q^7_g*73RLZY?O6wLh_ECPd+_m)L2++|LlT3PYmya zUF_yNnLVmHw0_S!yS<42^M`7YS!eB28_#}{easW!vGCISjZCN4S{Yfph9&*-_&i0Y zNh*5h(-_+pJ!zG_uQg|?p19opwp#MNMdZKCt6_3mGqqK?n{ zmiBH7!z6R}EleYdgPX$Tw zE-vl#kke(V(Or?ek=q}uM9+MlX*KJ5N1bh8_71K~9sljteTewgdun~>ig_YgYm=LO zMOI#1`%z`%3BKpImgl+5I>R)fb&=?PM?j_wMuT{&A>$R+>s?)+q_Kh41@crY(&U%#4ZZc>n9XRQv4bN#@h9Z{W>a z5MgCm`uG6Ht3aovuP@%;-&P$c%jA1#$BU5PyB6&17SXgR7HeIZwsOAx{eW3-_`KJB zQGNEu#Bz`JEeD3nk=N5^Ki_px=*qf@7aoYoap&hAvlmGfFYzwR{t-1rK1X?rX7=ud z9Xp;>sycJ`?7vb=GOyu~Ce++J`P zi9h^(eQo`|xh$9Lm#3K<^;iC?u~uL5=kZ^w@4mO~${*h>ydb3b^>VJBOcRJI+UhU% z{ciC8P@F4( zSRZ*TsAH>%od1J~Zaur~)-HA4?U`{q+&M36UBQ~#$}{0*ziO7|Z{K+?{n|p0i7BSD zkMBEe?zbg5@?`yU;nm;L9z8s5voY+jqSD8x&ok^+ywoW?`}O*n$xj|x`6j;?3oQ}8 zGtYBVm(kqo(QZe8->3sO55&Rk(_Zzg)MNA2F!+aU%|8!uG{=e?fT_sgVLVE>F6xm!yPU*PFG zbFR*Ef7F(16Ri!+Uv87)-ZbUz_GNh~`R@<^+f*&kHFM7nSC#cjhu8S=?0p+1q4W9C z^|c=Jk2dc;t;GKFquIJ!Tdy!N=j5g@X&03@>;JfG_1)soe>d2EW~DFBUTsx>>zrP2 z^s1USQR+^=TYJr3JbeCpb8dZXdh$G1OCz7j_TAgwSJ=+f`2O}t-=yi!ZED~38~(4g zTHYaXedqnKo%1)YO8jZ|^PSnxzYcSa68HR4e6*DM<~4mQe!G3y-kMjuexc58d**%l#p@MrzE}Srb+>H( zu@60^VJ<=1UpcPa-czvk|GkRIt)l0z-*~ccQSOSDiLE}DEd!jqJ2+2^-qNcKJ1x|f z%DF#sTG~mOUu))sS*|P4DqD4?X8VfRG^v#0#3JFHDL2|=wzGY6HNE}&>SfD)4;q&% zo6MU1Q`#eXZb9-zewGIw`2h>Qf7V#Lc=D2`%rknA?q^(AYhygWQJe38=~H!PM?3eD zHS+CBw$nCuD_hOnIj7;_E2&oYhfiYFKXbZlm+m=s`-47j{@jv(6N(>PnQ(dkdEH0F zt<8QfFE2>QU68c=+q8AEQ6hi0B<<~*sp7fz)`zS_#gF>-OUjBBJ{uM{?7YJ3`lh&@ zwfOe-_3=f){(Gxf?pd7wcsL}c@%!SmL?*@H7{0FcYVGmg${h=3*R#&urX(u1=3U9n zHxrJ{zkOBEd(#ASlb_S7^yRzjm^Mu0dcfkaNZ_nwO;_co#Jg+Td_#LoZFKkT4w%z_ zw`M_r{O9vO9^7T=nKh?dVqt!F{(_v>s(O<%jVJ0I({=lK{Jg-{1%KMP&-|TX_Ggbk zwA#;KvKx;Ez3*IGc=%4{bpxl1-xz!H(lnX(@YK2FU$@VWIs7oWHaK1H=J%7A5+uHS z_&nJnVcq*K?_|TUBMx4HMzf#!C*MqNR!Y4YR(Y@M&LfT0GgF-Mxz@H;KF;G6-}UfM ziP83T5~pspudAt?bz;g3KK1-r_jWnFOETLsr#1Igf$*YJX0eCvr=(RTJ-D`5H(2_x z-SQb={rPORreE)($l4!$=enBND(|r_ecSXdr`lcMY4^;xf1Wc3tZP{{`ASu% zklu^um9zeQUbe&ex&Zs}SH>qTPAosn@tbk$o#f{od#Y3<_1bT4y`s(_zh>t<}}vtWUemUlMkUH-7fQ zcg=4mFAb~SyYf@JpS7@v+C=tF=2D~R%@_ID_)k>r5sTN0aJp+B@7rJh>gwmM`4hBD zcD?V~c0>TS?K$F~8y#}{R!x84_mHl~6*EoZ_U2f_jLQhpko%baqBOYoW8br zrK`WpOz{K1H@v>Xeq*=6tLbL?r!FP#syZA|Zv0dB%9~9(2OhlNXJpP%YW%3KTjb4+ zxrtfPj8{wFegF8pbp5uUyRz5oZQfz~=HKzyJ+WsqeIlP$Em_2ApLaR>{?0jXJ1^|! zNm=*hR*Hd+ZQx>m*{X)AaY-G?Z7a*uZhpy2H`B~v-W04BA$#iH+jTqtY&pJe{;56d z+s|)b%_tYXnDJSYSk=5Qxu&o0rtDkovsT8sWcACPQ{T$2xaY8W;+Gq;ePy?xtqpV^L^_fpZ%GjWj#q-zszFQHnzQaoRNF>o!Pg& zt!qNxZd)^5c-Ngfr#WR;GM)INS7E^|f9Ca(HNUs$q#?#!#{PxY6-2v1dOJ@MjGk+Sz&fxZ$hiRp=1-{bP6{oiLYsmk~mzu(d; z^zG)IoWK%`%XSx>ct7r4{!!<7sHy*rcWF(V54`^OaCg|RJzvkTb7oqyYca>j`!U1a^nBAtas?wT%PDx?3lGi-ecYDXx+~n z|3%Nds9>V|XXO%IU-L$Og*p}0dt$MNu09sXY5aY~E@kVJo%i0)ikh)D@9dgOzHS_K zjKyJ(%ijMDO-f)(`MTqijz{&4qL)wC{FxJ0ySdROeBT|@+vch3CZsQPdYpSw{L}H) z_G23_&ELj9Kl7YTWX;)U^Y^CDS7o`s-6ZMY!xbDd5p}UkLLzu0#4ScO+b&YETthav|}Kx|*!A*Z~nq?i%%nVnTP9?CA1;R$T z#+QiiU*$gYJip|yg6nTd+v)YiGtYfKxBvLWqY?8qXdhG2tC`WJwtb^-qsLs`m-deo zCQ2-I*%(=L^L%M~r_wg|wA`y_m)=qOUw7x8-8mznoYxP(?^-MRcxSD;qU`bQYkz&d zlBPUY@6luSODm7-?&13o$S{4s?BQmeZ@E{Wa^_rKVXC)%`WADp-g}wi56`dKme>8r z>iWxFyQ89ai>T}{kDgLv7++;)zb#VCxH&j#`@Xf`Z`|0s{M<%kT}{8l^S2L_ch~P% zI%s+^p8NjgNlkuR1bzwUCQEJYEp~o-YvXLrtET_=a>|Al+HE-gU!abySea`gn z+5IrF&)sD6-osO;Urm>l*47kPsAy}P$yB*vPPXgxL$9*mr~lcn+ww&I_!e7+`|Mp; zn>g0<{HWik=YPTV!LD24b*KLF+!KFs&#vh^)2{9M2Y$2NH9y!g_r<@B-SMu%1-2)a z?wHKzyH7e~-kwkIM2+r#@km>^d-jzN{~j{0IKg_?zTuRDmT}%|<8m|Wz0%vS2Co-d zYA$-G!|3-HYxRXY-8X-f{(DQm=lzY_l|pURUehm6u3#`%{`%Hy*88%{4};m?PkZco z)t=`U@AR8p=c?=17F+d%#5Wu|I_HYV=hdl4ex!OD#dP=GU%}+_a=J_N^b>F6V*T@T z-2G+h`0AKgYh^-&Z!eg=fq|)ba{kAc!OzcBzd!jrUGs6~(j7|gw_TXAxjtpb`iI^1 z>;4;^e)+X5SMS(==T`s2`7eD9ZwlMR@N->AGU~8n4}&d&X<6S@my&oMPb(^0C2nx82l=OjAST zS7uhXbTkP%h{?bG`|yJ5zwdqf5-sQTwOw`P*>qsvh5*~oA2!dN>-$)5b=f+LKf6OC zGfyAq4}QNwak}O0y6CCi$9~7;e?J*F!^2>2?t-_9C8N1pU){?hxEfu@@Z{?}0)34+t?TZy?wWwP4?waeR zKZm~`XZ?9BDfi6I7uP>-nV!G=vBk#k0lvw*=2|RHD8K){Qg87)v(NW*Ud=DK)p3dE zF#m}FK6~A`4@(c`zBnmfynVxWQ|rt3Eh8gVF8}h@NOR-k`oD7&6Mrwd#=Y(zo3vj3 z(z$kLYIWB3JDXJeH`-LY|7-QC_u6sKrRG;l{4_rM@5PF%C%-QLk}H*X`1{AL4&SA! z-X7n)UF3;Cc)Dg^v9v_<*UF6#6y_~>eUt6)&zybtMDAR0{%vr+?e%8EBQs;pd|VZ_ zQLWBg^OuwFhmco^C+aR9e-^x_X&3ACDh;EH?+bsw(t8qicWv?(6^VWJ-#*rTonlv0 zpjx-lAFsOcbi;2xNxMh? zOYU43&)jz9`0lTBxlVt3kl1(c$L9Sr7l&S1y0(7C?zz9a__h8%d;FWPJ=!_`gl$;t zqG`V}?;mY1z3HaU*?F)05tH_nF zC%ip1Nj>j@=l>Hy{OjEFkHq><+u)s@XH|M`K)HMvwP(qv+236?>~D!T$W!p&HGD*^e?liZ*|T*Pgwdg zPss0J)&C87k9oh{yT1HlK*`;`Z?&G^XMcHcQMFica$i%Ku0{F5M+@o?{<)*`BKqR@ z&AWZ?=1-`4`|p-le6EdCsPWv&Id|6|*!}&`+Fjef>VG$T_h|i(H(h%)ezkH&y^j;V zb$?m@()b^Ne$aCWYuzSZeI6h^~x-X4`#3VzdL@> z-Kx9oPxH=uOpW#Io5OjJ-08Qzx~cZf@rL~U^Ox<|KEF!!=ZTSjREya!&vcE93-M)ZLjNz~9rTDT>Rc8O#CWO5yef{KW z?{nRQR-%8;^`^W1Kfn5e%T3#3ucH*+-GBHq%Jbyir{`1;M=YINpM2VOyJ_OO(+Y{n z=R??dZs8zTW8cP1o>=L1ZR=iJghq4oI`V9HzyO{=`m27j5`$7ugFsxIV6dun>nzV}Do+UY+FUA_A7nW}^! zP1nZnynpVmU)|ETl07$a>%Id5Z%^m%+O;*7E4HUP?_XzEx+p5 za)0lK3sYZT4d1Ezx$Nyhqw7+VmaXiw4nDZFCh3yN?#@eFtln>me)o3TU&HM4mD0hp zLnoQ#AN&^Evr*Duenvv#?1xONHonVkb+k9%wf4BM{JA4X<3!%@YHiKj{deD)RR6sv ze=|JH+$mQ+!NV$r?YxuUpV@DwRqsx(KV|i#hS~9W(y{HX=I@s8TJ|JbDdCjeMd$aM z^sHnx_S@R|Z`JfWCDHOd_u8h8?YqxhDq5qlTPb~us71u)*=uhu=Bn^y-5V%TZm=Wu z){NIm4)*p1q35sEY2Pw4u3U69YL-Lt&(zKSiw|{YJleU7Z*Kou-JO%a1X|y6D^~q; zSwZbIue+Evr?BjYHs0%ZTECZdNHxS<`19u3j&-%MKfi^(-QLPP_2X5Sm>u^!yW+xq z7OyN~)D+#hPv1sIujQBMlTWdCKa1wyI%RiolijSOV!ylb*T1jM`uXkevK6<|A3i$s z$LChIq@fR?Os?{Z7mlp7ZiAIFKv2v4EO#HJ+>x8t=ZkacGjv|EArRGOVAyMcQBM zwer#RGLemPSDt=!TVKJ~9I@q~TE;^Yx1Ex2f3Mp)HS%D$U8cmooDYk`y>}bDpE zH6bao|L6RMBi$uWxjkgO_AnoJomelYb1Q7VlUAg4bJVMa)%)j|W|w(i_wWhcY<%m+ zJ)ZKcYkwlEci+yHt~nsB?9$VBf4=ysqWX<)ufBY{^7{B*>o>>sdd;3Xm@oLDJ7v3t z*?*2hM?-3vADr3US-m%|-0->76aILmjbC&2OTPMjv+lP3b*DSEI-mEj++N;y*Wm28 zg~`|K%O?l@TQ`GE(D$hGSIOyFdEw@_(0=LHTMKSvU5mcHwpjAh zx59WEo=V~TA5R-Z@|3sDIMuDCsPiJ_X!T+9)t}Ctj$OX*Nv3~I#P8dZm(mMt1vmBG ztuqz8qt(Ab3mSIMU~#s2PuDkuGC-u!1b_x|Fn zegFCGuaj(YFDvh|%U+g$(5m?AUhw>W!$pUy?N@9(UH9r-*-D`sdG&E!+aJi-mrFj{ zb^qXJnTvIi&u^B0%YSIO_P5P}&oZSivY%AhoO@_@dPhC)xmeHt2Ioa2{>jbyTs*yd zbG>&nf3tH__9vy?n+uZugzK*jedoS(_8X+%Y);m zKGpchi~rehp!+?Wi)ldghp$p`tLxufyYgmh*ZnHXZ7&#JGoFv@yK;Z&hr$ECe?G9K zt>3!;>dsD$n7Q$u_dIR8UoVzsEzJu#{UcH8LP!6$_P?3sFV?Yb zxw~rqtGBisW^M6`a}v@||8@4?&d55srbfXpz48>-!=A1Cpr&bsKFAFZaH$@gsUh#=Yh5^V)7!=Zo^&AD_1Q?3E>( zq<@*VF8iAo9I^8DG6{PgTc68%^*2P$N-e!BWHE6)|5BUQW$(9Ly0Nl4{j_{<;BN&!)x{)_c!a>7npy;_^tWt zg}GTda*LPp+UK91kbY#tuc(dgJCBQ<5Wn2}NmM0rWoOs>&co+ZdR+8e+E~*JN3_|;dW}7*X_3Zuh;3c2K>3w(=v~-z_6kHXTlkb-BM<1_$P)nx_s~S*M;97+&jEILu~PRw#c(tA1>YB_`+`8v9iBKwe=e^ zqB|9SFTdFFVfAa}sEcoJc3qg@B6)u6+Qog=e6vsA<+@X>=PX?FEilJ*`nuG^*H^yY zrJp>bq&{&)8<$l3w{*6?^5xH8Hv9TMfAKD@DfwTa^|6D0-W@);ZQGC6RE;{ny{GE`MwN|AqC2rH(VJUe8amju)2u{ah|>{*%Mz4!ca-(Lda$-8T6H+x!h7R~nAKQH-z+2kPM zYg3E&-&u0~wR!z!Pw_ujB0h@GE_oaJX!f(ziU0B@pQ^nuC4N6^xBK*!=My%jm2EqH zy*xos{-DyjK1M5nJb@&8r_heQmvBhQ8;Q?YqQJ&Yy7f->d8G$ESbk-SuI2bi~PdyIz{jOUtcY zVdJ*$w?lq^;DKq~6YbC6G)tSMu6}>=_IdxpQtrBbEZJ7eZ13D3?J`F+_RpE!xoh9t z?y@%CqPyQtq^3{l>rVIAkNxH6pP%$S=hb1>(|aFTC;jXD&&wPYTUYyN(>n1?-EOrdXqv_h#v5~*5+l=iPT`#HTP2U}0eR!vZm)>`F zzqdxE!;&S9yEop= zR$(yLy>hrAy037XhSJUOIk(tTOvPeX#PQ92-M?v>dxKo}x^`(%m7kT9cd6%?PTR|5 z(mmOH_xg#yu1w1)6|!~hzWh}7vD8`7=d+LfSv`4$=-b(;_qaZ8Dfl{l!CJPn{@*kC zU8kRz>7!F`^Kwsr=-KI;qVB13Ue2w2m#twuwM@PFR=m#*(NtGsA47(Smn)Ya_;z;c z)kk}OWL}=SrixMYx5Yw!jsst^&wnjfHk5j?`rAi=Z{{8utZiA_+v|=Ozbn6;B`**j zDYz?Nbw3x!1C!PNRQ=EFZvA7UaCN57<(*0_L2)zZ`6}$lsJZ*?uSDS4Ot;(H4{o2c zs><*CzNdxBT2jm*V}8HOTXyn|YzqSz7I} z-Mi<{n^dazCB5#xTIu|G`>*3CE8oj!D87?ecks{A>+GvT|FM63Wu>{xXnWUl_TZQ4 zyA@@{i=j9{jLO%g*V^ zh$#N>Nuu7{pjvxM^g6?ei*oYp|1~^*+Wa_oWNZ6>vZ4$`lXxJXxTO~ zdY@Q!JJ(FLqWkST4z9kJKVNr)oWsVFu=#U$9Or4?5phmy@|9Au|IB%{ur;L-`_ zJ}~K6$LiBpEA#cfq{&Zn6t3+m`>@GR;t9`oR@oh!+9#U%Z~VA?QCz(2r>Mfu{qH89 zRdD%zTItcZ-P6zd*TuWNd~)!+`?hHteYTsLh`u-+B6C>9{>;&UqmRq%tX4lgK4aaS z#W$=A*e~?EmGJKjN?fI>f ziQN{m&zjSJ9B#6E{^CrZY{cy!o7_H5GWsHVlXvsd>6Hg{-T$9asF}0l&kiNES<#UO z-vVamcfGq@7MXa~yOc#?{Y;N|Ixndr)||@_F~bsuRQ*{t{oSCUHNU- zo|MW6+rEFnYkJg|%oTGi%`=`b&$YXM%KPOVcbn(FI5naA%*J0|+S~3tPf`AHC9fzy zW#vc5zaPQ`^Ih$Eeh3}N`L(BX&W|fcTsQxcHlLBaV@KBA-K*b~d^ut+9OwCj5UR4@v1e{>&@hgHLq2o#@Brc`ACfZol0#SBV$b++Fzn zpxq94F=OM31vlntZ#($y=xJWfCC)ilD?Wz&-xIrU{VKo3y$802zhB#QS!JQZ$-DmP zyKP;BMDD6@>6Kh}c)L&XJjqU56QlJm<;Q+(ov~3gw%2lJ*k5sTy_g4jl6&`;a9jz0 zF?D;tL#^!lfQrb{O~22De%3t_UbDi=^0Anl@4;o#r2ryk{6zR zCl2$iOuV`8O!fTLCb4sa=UvOsbTRwT$M2T1diBXri@q!8OIO{K)<1Ue@#l+Kp9&8g zu(|B$ef&HdTfSRP>h-@?DeFE&-)l;>Hry?9$!K59|8HB`=JPoA+dazN_A4`f-Fxop zH$Q(b5?uQ=Uq5;4ruXVSbWixg)O2t#8mZqmq~kXskK-Vwel#}H~wtr!=JByDM|Zvom=vFiIim%jPmaL?4KyLykTWIKH2x6QvDN37RgVe0*K`&PmwP93rI)6>FO?uBHP zM)=6DKl)=L+t1s~=i=ULrVGyARebWtP3hV8Nmu%%uX^3RmeBF~i-VB)ZnYhCNKmhF1BOxitd0{pDj+PGjf3&eJb`9W3QH|6viR5?e2x7jV(>Z&t?IQ%7gXK8m+D zE9=#{$+Tvz^z1c$&;0X!l;y;Fm&%E)t&b7)&Yo1l^f+{-dH1$k{m-htZpnE4qKjQL z==6g%{wFf3!()#-Uw5rL?qTC{Z*vfTw~X9`FNzo6FAlwJJV~x=-S5fwesJ5g7;Opa zF5wcY+k1AJUtUOJhZJ!;Y12SZ@9Hb#TIujZ43a&oy~_B)GrWxcApp zmM5(b+^_2P@BH2vQ~Z2MWv^nc@1J}9bM_v5Fy)Hx)uiq2UuuJHO-&V%@3z(aY046R z|CG{=$5+<=^v(-ss#CPuvD0nqqSalGe;&M7?`V=6eDmqUsYiMK_-Q0A6kpH%KS=;JY_wU(kiJovo@&BTE_m6LR;~X!i{p`U`h0peu|M*T!+W3(#qb7Lq9jo7Im%r zc7Nu7Gx6;1dvn(Z#MQ~WUAn?0+T-taqF+4l!pG+QAC!MwPYe(G&7CXnvHV(-{mn;l z#ctvC=Ci(~%Oq}yaIL*5)}=luZ!?}T)gSU#|i4^Ce9|Ff0< z-|kPlDkScI%$mn+|2c{~y6@szT7N}0VdF!z;UmpL8DarS}W(BzV z91iN+aQVQ;yY=_eKiFIEa=OF6Ve8q||M#tb($4j_@pDW3DrG5&Wa)~+o<^>@zv69| zFFrBzSJAXvPd*xJtMcXUn7?S<-%oF^i`_bZqi*T9*DoZCe^+jcUwZxS?3*$9C%#UL z$v=5iu{i(C*K0BPXXiRUySLyy@2|v!!zXI;FMMaK%|Fk-`14-J`_fF# zZ}8>YAp?j1&5l|nQ<~>jEnc`?vdyvWUdEf=WB1Zz*d*J(zV1C{cfx|lh_880_1Ax2 zt=j${I+Qu1KIxX5dEq=Mk)GGBcPH6`-_a0oleR})Vb9)cokv_9`ug#jW zcf8N;CA@q4G_hf)dBr!j^Y`vq@_cy1J8$p7&D+cQm~Gnc-jcSdu1=Lmc*#5MUc$?_ zQxhAOnnzSMFWnyA#yCyTk*6a=-r$H`&&JsKJ^Y0~Y!f>FN^tXZB-yv$cRp>LCpAlM zQdYJW_WRtP%xYGfS>WS&&SJgunCrTg&$c9*AYK2O;~p1Q?6WlMR=ma}wQox!q8 zDmwKqGY*_Bu-`GEC0L>^_uJ>?ANYIN|J_nP#}Zx`mQ?$1dHtW4bse@by&;S`o1e+L zJD=S)|JTbpt+wEhyVhT})m{A@cUSvf-SvsqWebgB9BX^O6&Fwa)%oh?`2#n5=f9HO z{qQZz%F6l=t;x%?xR+~HTb3OS?^>dfZ5#I8&UlF}=Ow$Pd{_Q1Z7Qu_-C(8W&8nLG?4)OMd0p9V^)!Ld@0;J&^U3_Zv*FAUp5uPM&Lw_+wcNUVQdM8fe)Y5! z!s;oZ(`Vb?RXp`eJwJC5gZjPtowKw#Hvc+h{O-u&`E~!E&#YAyaLE4mW!I;!HWBT| z#|8iMD5>~1OMjTLe!`V|bq2K(_E{TGEUvA)Ul;u#pS525NA$t}v$(X@t=z=ypV?UV z>!0u^roVlE(_h*5D;B@ofBxTQo?af_pu7b6HnY1ImUSmLE{rta^17|;uBDj7tZ&Yj z>txCvP$b0;rc0!v{2nj3eBq0sNiC1A z{AI8BvO|U?PbGF0@z~z%Tc~~f!qns!rwqTOoOTZXbYZGZiE8`C0~boUsXhL{RxsF$i5NuA9{%_;IJ;$DIZXe`hMW zJ$Vj7Z=N4A5maU>0U@@M!dV@HoVzS!t&-&*nFuN?m4J{MSXgqGpyVz=>0KtiM>+)V zf{q?ZH{=|Fm|62=5 zCEG&+1g~ly^!+dS`~2G%`_KQo%*%Q=ps3h6(tJv(bE3V-y*~lB_*?%5+~9BBZZL(< z`JsUb-|>h94cYcXg)$#4o>)xjbAD(d0*cH4E8f=20Y4D{oq|etIVR<`c$WLz{xRd*$B4rm)Ajs?4V{)rJ6`VH@bZ(1 zpmNDBL7TfA^WV);OKJ%)Z(1Rpcx7s)lAA_ps*{JZoXogeFV9qR z0|~zi?0bIeiR`DL<3P0wUozF!hvpz!5-UU;EW zV{ZE)P$09{@-00N4rG}UNw4V(3naOw7hc%#@wJ07(u{^V!$BgUQwZK~58E?)`VZ6RN@}Ab|&bN6|pS@OJ(k_0#%8%nzjO*lce=e=E zZp!-iGn3E#s_wyEg=w6x%4Zz>Ar`tl{=ZE1-QWMD)@N_rmHqA7R6Do%cLIE+pPaXu zEq(DGyX5z0GF!JhR?UxEC4Fp0jenl=o!bnt@(C|Gb4xV8AF7Ei#J?h)Jyi4J@&16O;nNeZU04< z#m{P+9!|T{CiZ#tPlIQS%Xcj7GuyUne^i$Io%7es`Y+y@{x01^_v?(RJClA_erLX< zyOsZa`s$hgGxZL$L_f0Z(fj_@=Jty$d7bwg@~YQ=ejA3raQgHUzRQW%;p>ATC5AwRvx~g z74X&hn%dh8zY}%x{mnK@zF&Ns{H;;MdiL*4?^90QJ0W8qq?zZD$Ly2p@s?R8*jloT zXXWL6uTSPSB%ZP1DUjcNk*(sH;@1B6GQSNS(r>5KEeMrpbl&-QLrbEE+_eu9zwUC1 zO+T+#d7~lqMTL4)mV4DFgL6NO{ukaqDfZ*g$_4V~3+0RWAD^+URESw+7m~7GUSqmZ zh|wfH=VxZ89?Jx|cUkejlA8gH8LFea6u}jP^ptio7o~*WC_ib?Q98vxikHgVF7Q`g*CTFsIIK zJC|1J%qU%++Pk;u%BE%WDz>ay880+XS5WTfpPNndt~|aW)UA4LZ_Y%~Hp8iP3;SO; zuUfIvHSWbs|Lc?66PM1rb$qJT>|1T78`jl^6uw`%^Si>AD|Q>a__sbWGjZ8+Y1=#J zZrh8#n^Pl}JY5rgIOz6<3zLM}uNKul-i8s&qXRf!a<~7}NPma0hP0hWF?ALDY zNsidI@fP2Nxvds$p{qYGy+Ibz864?eO~R5j6Am4K2H1g;~W6 zCzCz$lDX&FS+aLb5tgvnowz;n(S{t+OdT=H!4cG7g)h>LZJ! zqvjg9e%7kZ5d9dL6~DF0AUaDv>P5!hEgKb^dY`^+=9c|E&1~C+@2M}HPa6fb9jUO< z(=C;mnKMJtC@iZrgWGf)e|MPV)M@vQhdox?_9XG{DZ3@#WuG6OVAGR7!R~GC`NXL@ z3;_65)5^?agOX~R*r^UK63SyPYCvk6jv_SyZv6SEV^YmzMf9<#b7aNhB#VSw(`mfVxM4O2Jet$dz(Q@2*);e=X+Scj&qU-;J7 zz4-31?*UKN%UaEiho;#Gr6;eh)%>3LgIQ4cm*bO11xY;0QZHtlI{y6&V@kUo-xQt& zr&MQ3xvoW}V(;N$@T-pNK2j2X`8C2YIn{Ak0hJfHW=j~h%& zwvl{1;hy;BInJL9JnTd2&e+6zzgyhGbdKd}?v&#*tYnnyJldMix+iFiuxWyj1-P8M>&x09OJVk33^L~=K zEv+%fM8#h_Q}C?2)N&(h-Mybh{>qdyPZd5q;f`Cx#FAG=&!<&dXtO)1&vky6*zwGE zi*v!%ZxM2no|nFPDf?5Qdb&;di$3S7_!IL#etFWUaU$7t?la5dPwXzl#=W*)a(=CL z+`re>N6yzC`aIztn^gPf$^|twlOBs`9%;Mg<^4_BFqpsQ@z?6@uPgIc7S5VH&8Ecq z>y?GqzwX)o#Ky1OTek4z&B^UsHFZl>lKlML?5iDj&ugh5GJAW$p!Mjp6 zny+*1ODXN#H?17EZAuSq`gZZ_Ox?o|ZtZFE&N-QzOX?>c$HZ~a28V@LGYJ9~!d@A)3I zH=x6rRp-k6`SlYo%0Ch~wxI5oNO5Cm)l|EtRmXJ8LT8Cc>MLEkx?$UKfBOkjvICY! z$nIYCk%@c3e7TFqBn@kWr<`bJ&q{pFSZ3bZYphf0`)NXTWzL0PP5e{OeAaJLI{g1< z?Aj|GzkF`-_3e0ZuyDa)4zc$ZQ~fSWJbczE&MR1N=^Gho*u17=qLP{0y>AvVwT7FQ zoZ7pg+A-uXU$)$V2$sr^pFKQQyX)9&ZL$nhJ8@2kc}uv&jXkTb8C6#oDgB&&*XoMQ za)*nWqLGWYHSA! z@Q+Pz^=qydM84&@_2+n7RqdrSK4KZ7)l0>LHmpp!T*k%1Z#Tiscw2LD<3xe0Ia?~b zKl(pg@zsc_>T%|F5tdbQOjk{AJ(;1*B;XWUm!%@|>G=Q9fG;msuGq$vzS?5j?CgpT zh6TK<^gbtk{gW;m-V@0>{jNx8*uxZ2_b|p3QHwCaWKpd!!z6Ro_Rx@s*5*)|h@Jeb zHoDHxa%G9{{&1qVW4o9j*CH_ujo5%)3kn<`HXUkZU*&gY?(rAroJ-X^H+>GdTe;?) zO?bK78f*V+e?uIvCA$~z@BPJ6DEo3oH~Z?svd@eCGUhqjWXN*GD>g`-&$3y~xkhcntb`>@uQ}iNC73o|WeF3G@J%ocoGcvapHjZagD*^Y^4x`w zZnS^?H2-+P*N%Q3?nd_AMH{r+U !EW9Gr>iU*_O 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Ǹ$xps+yyuyR;QvPb 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ξ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 literal 0 HcmV?d00001 diff --git a/third_party/icu/data/icu_conversion_data.c.gz.ad b/third_party/icu/data/icu_conversion_data.c.gz.ad new file mode 100644 index 0000000000000000000000000000000000000000..d5abb06b8ca21e1e6116ef1732c661c815b1489a GIT binary patch literal 177696 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 MR>NZ6c^el30N55?$N&HU literal 0 HcmV?d00001 diff --git a/third_party/icu/data/icu_conversion_data.c.gz.ae b/third_party/icu/data/icu_conversion_data.c.gz.ae new file mode 100644 index 0000000000000000000000000000000000000000..0e54fdb9eaffd814477460f71bc194104c1b247d GIT binary patch literal 177696 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

6i{vi;aMkMJksbp+~stC>bEu89JS#Bzt$;y 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%0D_ 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

6B9D03Qn7{P=EE3 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 Lw%fap+;#*2xAJ6r literal 0 HcmV?d00001 diff --git a/third_party/icu/data/icu_conversion_data.c.gz.ag b/third_party/icu/data/icu_conversion_data.c.gz.ag new file mode 100644 index 0000000000000000000000000000000000000000..bde20b6da6253d866f87fcadc7e6c3571bd64d44 GIT binary patch literal 177696 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%0AWYT@Dfe z6(N`EMBj#A+&8EGqX@`%47H{VO%f(YU_Z%2#^_;auGJM*^G>Rk<7lk4%Eb9oRc@u&9D%vu(bp$#6Eqwk!sY ziCgqb!INQfVAArxF7D!Xkdgyb;e1@OWB!ZYLr5k5Nu~gnjUl$6c!BsL zTckm&Bh(pEPlFTTS#Aem!~PI~OFfA8|k?@?XR zqFVJ^Ljlm@%omJ?%7Sj>mn^JN{sEwDP;tFK&LN+2H4)@^*DlZqU+OPh5U$dCZ=ZG2boL zZZ)HT%X&p{bq390DwDp=&4@RRn=Jg+`rTnuP{7Cu4i))Xl?_ysz9;k$k05&<5qa(sU@GL{FQ_?uu$R> z+`t0+Zmn^KeaE+EFmaBYOC`mg^I)5kKaiN@RNDrCu2$5 z(<#$ZxV$|BKX{fcQZWvg6sUGmVsc7}rR(kHb%+jhHKOtmkhEI@&+Dq2SS86G4H6VX%igbJj&Ry~N>aa-=*k~M24FFVzL;@{_@mBluVFU+n#QN6C=@UV4y z_vY#E=U(UEQ}S4RV0 z7+v*XJ~K<3Z}QTBb3yA;HKn@rVqJwY5`VMToR!hcHuF1BaR-|oQH#YZ)e!S89EPDCUOT8_@2I~8cO=QW+ z`>~{vX_7^ph~ZhK)v*&<7kexXy}FLeVJ*{zFU@LO^Ed0hRbM3N$`+Wk;1eT5M_^!r zz*AOV^__DvTVF`d^wgd|;j8KMIAFC?s^IXqc&1K9?GJ2(OImc)FuL-72I+M;tt<#zGY+_&fRn
  • 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 z

    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

    1kZqjdwA|M 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 PJ$Z&eM`#1LuTCrgk|N3@ literal 0 HcmV?d00001 diff --git a/third_party/icu/data/icu_conversion_data.c.gz.aj b/third_party/icu/data/icu_conversion_data.c.gz.aj new file mode 100644 index 0000000000000000000000000000000000000000..1ae6bce382a05570b46217e1a031414515439a42 GIT binary patch literal 177689 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

    eij=vVwDz!Yt+zkV_t10OG1c$| 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%0A@(&Bj4j;M|&m0$I5q{xrCzJV9bCHP; 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 literal 0 HcmV?d00001 diff --git a/third_party/icu/udata.patch b/third_party/icu/udata.patch new file mode 100644 index 0000000000..d6d59100e4 --- /dev/null +++ b/third_party/icu/udata.patch @@ -0,0 +1,53 @@ +--- /icu4c/source/common/udata.cpp.old 2018-06-19 22:34:56.000000000 -0700 ++++ /icu4c/source/common/udata.cpp 2018-10-19 14:26:09.778950855 -0700 +@@ -18,15 +18,15 @@ + + #include "unicode/utypes.h" /* U_PLATFORM etc. */ + +-#ifdef __GNUC__ +-/* if gcc +-#define ATTRIBUTE_WEAK __attribute__ ((weak)) +-might have to #include some other header +-*/ ++#if defined(__GNUC__) || defined(__SUNPRO_CC) ++# define ATTRIBUTE_WEAK __attribute__ ((weak)) ++#else ++# define ATTRIBUTE_WEAK + #endif + + #include "unicode/putil.h" + #include "unicode/udata.h" ++#include "unicode/umachine.h" + #include "unicode/uversion.h" + #include "charstr.h" + #include "cmemory.h" +@@ -641,10 +641,11 @@ + * partial-data-library access functions where each returns a pointer + * to its data package, if it is linked in. + */ +-/* +-extern const void *uprv_getICUData_collation(void) ATTRIBUTE_WEAK; +-extern const void *uprv_getICUData_conversion(void) ATTRIBUTE_WEAK; +-*/ ++ ++//extern "C" const void *uprv_getICUData_collation(void); ++U_CDECL_BEGIN ++const void *uprv_getICUData_conversion(void) ATTRIBUTE_WEAK; ++U_CDECL_END + + /*----------------------------------------------------------------------* + * * +@@ -702,10 +703,11 @@ + if (uprv_getICUData_collation) { + setCommonICUDataPointer(uprv_getICUData_collation(), FALSE, pErrorCode); + } ++ */ + if (uprv_getICUData_conversion) { +- setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorCode); ++ setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorCode); + } +- */ ++ + #if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP Platform does not support dll icu data at this time + setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT, FALSE, pErrorCode); + { diff --git a/third_party/icu/workspace.bzl b/third_party/icu/workspace.bzl index a4f653e026..f100836b41 100644 --- a/third_party/icu/workspace.bzl +++ b/third_party/icu/workspace.bzl @@ -2,6 +2,11 @@ load("//third_party:repo.bzl", "third_party_http_archive") +# Sanitize a dependency so that it works correctly from code that includes +# TensorFlow as a submodule. +def clean_dep(dep): + return str(Label(dep)) + def repo(): third_party_http_archive( name = "icu", @@ -13,4 +18,5 @@ def repo(): ], build_file = "//third_party/icu:BUILD.bazel", system_build_file = "//third_party/icu:BUILD.system", + patch_file = clean_dep("//third_party/icu:udata.patch"), ) diff --git a/third_party/libxsmm.BUILD b/third_party/libxsmm.BUILD index ee49d281ab..dc7dcc9517 100644 --- a/third_party/libxsmm.BUILD +++ b/third_party/libxsmm.BUILD @@ -38,8 +38,8 @@ genrule( ":libxsmm_interface", ], visibility = [ - "//third_party/eigen3:__pkg__", "//tensorflow/core/kernels:__pkg__", + "//third_party/eigen3:__pkg__", ], ) diff --git a/third_party/llvm/llvm.autogenerated.BUILD b/third_party/llvm/llvm.autogenerated.BUILD index 776935739a..eb468aa65f 100644 --- a/third_party/llvm/llvm.autogenerated.BUILD +++ b/third_party/llvm/llvm.autogenerated.BUILD @@ -823,6 +823,7 @@ cc_library( ]), copts = llvm_copts + ["-Iexternal/llvm/lib/Target/ARM"], deps = [ + ":arm_asm_printer", ":arm_desc", ":arm_info", ":arm_utils", @@ -2141,6 +2142,7 @@ cc_library( ":core", ":global_i_sel", ":mc", + ":profile_data", ":selection_dag", ":support", ":target", diff --git a/third_party/llvm/llvm.bzl b/third_party/llvm/llvm.bzl index 54ca86f327..5a977f82c4 100644 --- a/third_party/llvm/llvm.bzl +++ b/third_party/llvm/llvm.bzl @@ -250,6 +250,7 @@ linux_cmake_vars = { # CMake variables specific to the Darwin (Mac OS X) platform. darwin_cmake_vars = { "HAVE_MALLOC_MALLOC_H": 1, + "HAVE_MALLOC_ZONE_STATISTICS": 1, } # CMake variables specific to the Windows platform. diff --git a/third_party/mkl_dnn/mkldnn.BUILD b/third_party/mkl_dnn/mkldnn.BUILD index 597ac69e2f..7a8ed3bf43 100644 --- a/third_party/mkl_dnn/mkldnn.BUILD +++ b/third_party/mkl_dnn/mkldnn.BUILD @@ -42,8 +42,8 @@ cc_library( "src", "src/common", "src/cpu", - "src/cpu/xbyak", "src/cpu/gemm", + "src/cpu/xbyak", ], nocopts = "-fno-exceptions", visibility = ["//visibility:public"], diff --git a/third_party/nccl/archive.BUILD b/third_party/nccl/archive.BUILD index c0833828a7..7a08f97ef3 100644 --- a/third_party/nccl/archive.BUILD +++ b/third_party/nccl/archive.BUILD @@ -64,13 +64,13 @@ nccl_library( ":device_srcs", ], copts = ["-DNCCL_OP=0"] + rdc_copts(), + linkstatic = True, prefix = "sum_", deps = [ - ":src_hdrs", ":include_hdrs", + ":src_hdrs", "@local_config_cuda//cuda:cuda_headers", ], - linkstatic = True, ) nccl_library( @@ -80,13 +80,13 @@ nccl_library( ":device_srcs", ], copts = ["-DNCCL_OP=1"] + rdc_copts(), + linkstatic = True, prefix = "_prod", deps = [ - ":src_hdrs", ":include_hdrs", + ":src_hdrs", "@local_config_cuda//cuda:cuda_headers", ], - linkstatic = True, ) nccl_library( @@ -96,13 +96,13 @@ nccl_library( ":device_srcs", ], copts = ["-DNCCL_OP=2"] + rdc_copts(), + linkstatic = True, prefix = "min_", deps = [ - ":src_hdrs", ":include_hdrs", + ":src_hdrs", "@local_config_cuda//cuda:cuda_headers", ], - linkstatic = True, ) nccl_library( @@ -112,28 +112,28 @@ nccl_library( ":device_srcs", ], copts = ["-DNCCL_OP=3"] + rdc_copts(), + linkstatic = True, prefix = "max_", deps = [ - ":src_hdrs", ":include_hdrs", + ":src_hdrs", "@local_config_cuda//cuda:cuda_headers", ], - linkstatic = True, ) nccl_library( name = "functions", srcs = [ - ":device_hdrs", "src/collectives/device/functions.cu", + ":device_hdrs", ], copts = rdc_copts(), + linkstatic = True, deps = [ - ":src_hdrs", ":include_hdrs", + ":src_hdrs", "@local_config_cuda//cuda:cuda_headers", ], - linkstatic = True, ) rdc_library( @@ -162,13 +162,13 @@ nccl_library( "src/nccl.h", ], hdrs = ["src/nccl.h"], + copts = cuda_default_copts(), include_prefix = "third_party/nccl", strip_include_prefix = "src", - copts = cuda_default_copts(), + visibility = ["//visibility:public"], deps = [ ":device_code", ":include_hdrs", ":src_hdrs", ], - visibility = ["//visibility:public"], ) diff --git a/third_party/ngraph/ngraph.BUILD b/third_party/ngraph/ngraph.BUILD index f556c5279d..63e9548c53 100644 --- a/third_party/ngraph/ngraph.BUILD +++ b/third_party/ngraph/ngraph.BUILD @@ -97,13 +97,6 @@ cc_library( "src/ngraph/runtime/cpu/pass/cpu_workspace_insertion.cpp", ], hdrs = glob(["src/ngraph/runtime/cpu/**/*.hpp"]) + glob([]), - deps = [ - ":ngraph_headers", - "@eigen_archive//:eigen", - "@nlohmann_json_lib", - "@tbb", - "@mkl_dnn//:mkl_dnn", - ], copts = [ "-I external/ngraph/src", "-I external/nlohmann_json_lib/include/", @@ -113,6 +106,13 @@ cc_library( '-D PROJECT_ROOT_DIR=\\"\\"', ], visibility = ["//visibility:public"], + deps = [ + ":ngraph_headers", + "@eigen_archive//:eigen", + "@mkl_dnn", + "@nlohmann_json_lib", + "@tbb", + ], alwayslink = 1, ) @@ -138,12 +138,6 @@ cc_library( "src/ngraph/runtime/*.cpp", "src/ngraph/type/*.cpp", ]), - deps = [ - ":ngraph_headers", - ":ngraph_cpu_backend", - "@eigen_archive//:eigen", - "@nlohmann_json_lib", - ], copts = [ "-I external/ngraph/src", "-I external/nlohmann_json_lib/include/", @@ -152,5 +146,11 @@ cc_library( '-D PROJECT_ROOT_DIR=\\"\\"', ], visibility = ["//visibility:public"], + deps = [ + ":ngraph_cpu_backend", + ":ngraph_headers", + "@eigen_archive//:eigen", + "@nlohmann_json_lib", + ], alwayslink = 1, ) diff --git a/third_party/ngraph/ngraph_tf.BUILD b/third_party/ngraph/ngraph_tf.BUILD index 068e411e81..db9a66f9b5 100644 --- a/third_party/ngraph/ngraph_tf.BUILD +++ b/third_party/ngraph/ngraph_tf.BUILD @@ -10,6 +10,10 @@ load( cc_library( name = "ngraph_tf", srcs = [ + "logging/ngraph_log.cc", + "logging/ngraph_log.h", + "logging/tf_graph_writer.cc", + "logging/tf_graph_writer.h", "src/ngraph_api.cc", "src/ngraph_api.h", "src/ngraph_assign_clusters.cc", @@ -41,27 +45,23 @@ cc_library( "src/tf_deadness_analysis.h", "src/tf_graphcycles.cc", "src/tf_graphcycles.h", - "logging/ngraph_log.h", - "logging/ngraph_log.cc", - "logging/tf_graph_writer.h", - "logging/tf_graph_writer.cc", - ], - deps = [ - "@org_tensorflow//tensorflow/core:protos_all_proto_text", - "@org_tensorflow//tensorflow/core:framework_headers_lib", - "@org_tensorflow//tensorflow/core:core_cpu_headers_lib", - "@ngraph//:ngraph_core", - "@com_google_absl//absl/container:container_memory", - "@com_google_absl//absl/container:flat_hash_set", - "@com_google_absl//absl/types:variant", ], copts = [ "-I external/ngraph_tf/src", "-I external/ngraph_tf/logging", "-I external/ngraph/src", ], - alwayslink = 1, visibility = ["//visibility:public"], + deps = [ + "@com_google_absl//absl/container:container_memory", + "@com_google_absl//absl/container:flat_hash_set", + "@com_google_absl//absl/types:variant", + "@ngraph//:ngraph_core", + "@org_tensorflow//tensorflow/core:core_cpu_headers_lib", + "@org_tensorflow//tensorflow/core:framework_headers_lib", + "@org_tensorflow//tensorflow/core:protos_all_proto_text", + ], + alwayslink = 1, ) tf_cc_test( @@ -82,6 +82,12 @@ tf_cc_test( "test/test_utilities.h", "test/tf_exec.cpp", ], + extra_copts = [ + "-fexceptions ", + "-I external/ngraph_tf/src", + "-I external/ngraph_tf/logging", + "-I external/ngraph/src", + ], deps = [ ":ngraph_tf", "@com_google_googletest//:gtest", @@ -89,10 +95,4 @@ tf_cc_test( "@org_tensorflow//tensorflow/cc:client_session", "@org_tensorflow//tensorflow/core:tensorflow", ], - extra_copts = [ - "-fexceptions ", - "-I external/ngraph_tf/src", - "-I external/ngraph_tf/logging", - "-I external/ngraph/src", - ], ) diff --git a/third_party/ngraph/tbb.BUILD b/third_party/ngraph/tbb.BUILD index 04e6544ffb..c78a2d79dd 100644 --- a/third_party/ngraph/tbb.BUILD +++ b/third_party/ngraph/tbb.BUILD @@ -14,6 +14,10 @@ genrule( srcs = glob(["**"]) + [ "@local_config_cc//:toolchain", ], + outs = [ + "libtbb.a", + "libtbbmalloc.a", + ], cmd = """ set -e WORK_DIR=$$PWD @@ -45,19 +49,15 @@ genrule( cp build/build_{release,debug}/*.a $$DEST_DIR cd $$WORK_DIR """, - outs = [ - "libtbb.a", - "libtbbmalloc.a", - ], ) cc_library( name = "tbb", + srcs = ["libtbb.a"], hdrs = glob([ "include/serial/**", "include/tbb/**/**", ]), - srcs = ["libtbb.a"], includes = ["include"], visibility = ["//visibility:public"], ) diff --git a/third_party/png.BUILD b/third_party/png.BUILD index c26a289717..e82948648e 100644 --- a/third_party/png.BUILD +++ b/third_party/png.BUILD @@ -44,11 +44,11 @@ cc_library( "png.h", "pngconf.h", ], - includes = ["."], copts = select({ ":windows": ["-DPNG_INTEL_SSE_OPT=1"], "//conditions:default": [], }), + includes = ["."], linkopts = select({ ":windows": [], "//conditions:default": ["-lm"], diff --git a/third_party/repo.bzl b/third_party/repo.bzl index 07b853ff11..bad6d20a08 100644 --- a/third_party/repo.bzl +++ b/third_party/repo.bzl @@ -84,7 +84,7 @@ def _apply_delete(ctx, paths): def _tf_http_archive(ctx): if ("mirror.bazel.build" not in ctx.attr.urls[0] and (len(ctx.attr.urls) < 2 and - ctx.attr.name not in _SINGLE_URL_WHITELIST)): + ctx.attr.name not in _SINGLE_URL_WHITELIST.to_list())): fail("tf_http_archive(urls) must have redundant URLs. The " + "mirror.bazel.build URL must be present and it must come first. " + "Even if you don't have permission to mirror the file, please " + @@ -150,7 +150,7 @@ ensure best practices are followed. def _third_party_http_archive(ctx): if ("mirror.bazel.build" not in ctx.attr.urls[0] and (len(ctx.attr.urls) < 2 and - ctx.attr.name not in _SINGLE_URL_WHITELIST)): + ctx.attr.name not in _SINGLE_URL_WHITELIST.to_list())): fail("tf_http_archive(urls) must have redundant URLs. The " + "mirror.bazel.build URL must be present and it must come first. " + "Even if you don't have permission to mirror the file, please " + diff --git a/third_party/toolchains/BUILD b/third_party/toolchains/BUILD index a7b4687c02..9da417fd5f 100644 --- a/third_party/toolchains/BUILD +++ b/third_party/toolchains/BUILD @@ -35,3 +35,16 @@ platform( value:"docker://gcr.io/asci-toolchain/nosla-cuda9.0-cudnn7-ubuntu14.04@%s" }""" % container_digests["cuda9.0-cudnn7-ubuntu14.04"], ) + +platform( + name = "rbe_cuda10.0-cudnn7-ubuntu14.04", + constraint_values = [ + "@bazel_tools//platforms:x86_64", + "@bazel_tools//platforms:linux", + ], + remote_execution_properties = """ + properties: { + name: "container-image" + value:"docker://gcr.io/asci-toolchain/nosla-cuda10.0-cudnn7-ubuntu14.04@%s" + }""" % container_digests["cuda10.0-cudnn7-ubuntu14.04"], +) diff --git a/third_party/toolchains/preconfig/generate/containers.bzl b/third_party/toolchains/preconfig/generate/containers.bzl index 1f9e29d440..7099b9bf3e 100644 --- a/third_party/toolchains/preconfig/generate/containers.bzl +++ b/third_party/toolchains/preconfig/generate/containers.bzl @@ -1,4 +1,4 @@ container_digests = { "cuda9.0-cudnn7-ubuntu14.04": "sha256:c26138f4c38c754da2bad44a8a068523abf7fbd71d58a57ce92e5342c5431bf5", - "cuda10.0-cudnn7-ubuntu14.04": "sha256:34c4a55e2376b300cdc2b903775fc32e62352f6e33f927df5653743324378bfc", + "cuda10.0-cudnn7-ubuntu14.04": "sha256:66e7d592c8149291d5562a0f3093655a15b09c22e0eb30a87b3b6469b7a30ffc", } diff --git a/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/WORKSPACE b/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/WORKSPACE new file mode 100644 index 0000000000..b61f572d6d --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/WORKSPACE @@ -0,0 +1,2 @@ +# DO NOT EDIT: automatically generated WORKSPACE file for cuda_configure rule +workspace(name = "local_config_cuda") diff --git a/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/BUILD b/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/BUILD new file mode 100755 index 0000000000..c813efccf9 --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/BUILD @@ -0,0 +1,1275 @@ +licenses(["restricted"]) # MPL2, portions GPL v3, LGPL v3, BSD-like + +package(default_visibility = ["//visibility:public"]) + +config_setting( + name = "using_nvcc", + values = { + "define": "using_cuda_nvcc=true", + }, +) + +config_setting( + name = "using_clang", + values = { + "define": "using_cuda_clang=true", + }, +) + +# Equivalent to using_clang && -c opt. +config_setting( + name = "using_clang_opt", + values = { + "define": "using_cuda_clang=true", + "compilation_mode": "opt", + }, +) + +config_setting( + name = "darwin", + values = {"cpu": "darwin"}, + visibility = ["//visibility:public"], +) + +config_setting( + name = "freebsd", + values = {"cpu": "freebsd"}, + visibility = ["//visibility:public"], +) + +cc_library( + name = "cuda_headers", + hdrs = [ + "cuda/cuda_config.h", + ":cuda-include", + ":cudnn-include", + ], + includes = [ + ".", + "cuda/include", + "cuda/include/crt", + ], + visibility = ["//visibility:public"], +) + +cc_library( + name = "cudart_static", + srcs = ["cuda/lib/libcudart_static.a"], + includes = [ + ".", + "cuda/include", + ], + linkopts = select({ + ":freebsd": [], + "//conditions:default": ["-ldl"], + }) + [ + "-lpthread", + "-lrt", + ], + visibility = ["//visibility:public"], +) + +cc_library( + name = "cuda_driver", + srcs = ["cuda/lib/libcuda.so"], + includes = [ + ".", + "cuda/include", + ], + visibility = ["//visibility:public"], +) + +cc_library( + name = "cudart", + srcs = ["cuda/lib/libcudart.so.10.0"], + data = ["cuda/lib/libcudart.so.10.0"], + includes = [ + ".", + "cuda/include", + ], + linkstatic = 1, + visibility = ["//visibility:public"], +) + +cc_library( + name = "cublas", + srcs = ["cuda/lib/libcublas.so.10.0"], + data = ["cuda/lib/libcublas.so.10.0"], + includes = [ + ".", + "cuda/include", + ], + linkstatic = 1, + visibility = ["//visibility:public"], +) + +cc_library( + name = "cusolver", + srcs = ["cuda/lib/libcusolver.so.10.0"], + data = ["cuda/lib/libcusolver.so.10.0"], + includes = [ + ".", + "cuda/include", + ], + linkopts = ["-lgomp"], + linkstatic = 1, + visibility = ["//visibility:public"], +) + +cc_library( + name = "cudnn", + srcs = ["cuda/lib/libcudnn.so.7"], + data = ["cuda/lib/libcudnn.so.7"], + includes = [ + ".", + "cuda/include", + ], + linkstatic = 1, + visibility = ["//visibility:public"], +) + +cc_library( + name = "cudnn_header", + includes = [ + ".", + "cuda/include", + ], + visibility = ["//visibility:public"], +) + +cc_library( + name = "cufft", + srcs = ["cuda/lib/libcufft.so.10.0"], + data = ["cuda/lib/libcufft.so.10.0"], + includes = [ + ".", + "cuda/include", + ], + linkstatic = 1, + visibility = ["//visibility:public"], +) + +cc_library( + name = "curand", + srcs = ["cuda/lib/libcurand.so.10.0"], + data = ["cuda/lib/libcurand.so.10.0"], + includes = [ + ".", + "cuda/include", + ], + linkstatic = 1, + visibility = ["//visibility:public"], +) + +cc_library( + name = "cuda", + visibility = ["//visibility:public"], + deps = [ + ":cublas", + ":cuda_headers", + ":cudart", + ":cudnn", + ":cufft", + ":curand", + ], +) + +cc_library( + name = "cupti_headers", + hdrs = [ + "cuda/cuda_config.h", + ":cuda-extras", + ], + includes = [ + ".", + "cuda/extras/CUPTI/include/", + ], + visibility = ["//visibility:public"], +) + +cc_library( + name = "cupti_dsos", + data = ["cuda/lib/libcupti.so.10.0"], + includes = [ + ".", + "cuda/include", + ], + visibility = ["//visibility:public"], +) + +cc_library( + name = "libdevice_root", + data = [":cuda-nvvm"], + visibility = ["//visibility:public"], +) + +genrule( + name = "cuda-include", + outs = [ + "cuda/include/CL/cl.h", + "cuda/include/CL/cl.hpp", + "cuda/include/CL/cl_egl.h", + "cuda/include/CL/cl_ext.h", + "cuda/include/CL/cl_gl.h", + "cuda/include/CL/cl_gl_ext.h", + "cuda/include/CL/cl_platform.h", + "cuda/include/CL/opencl.h", + "cuda/include/builtin_types.h", + "cuda/include/channel_descriptor.h", + "cuda/include/common_functions.h", + "cuda/include/cooperative_groups.h", + "cuda/include/cooperative_groups_helpers.h", + "cuda/include/crt/common_functions.h", + "cuda/include/crt/device_double_functions.h", + "cuda/include/crt/device_double_functions.hpp", + "cuda/include/crt/device_functions.h", + "cuda/include/crt/device_functions.hpp", + "cuda/include/crt/func_macro.h", + "cuda/include/crt/host_config.h", + "cuda/include/crt/host_defines.h", + "cuda/include/crt/host_runtime.h", + "cuda/include/crt/math_functions.h", + "cuda/include/crt/math_functions.hpp", + "cuda/include/crt/mma.h", + "cuda/include/crt/mma.hpp", + "cuda/include/crt/nvfunctional", + "cuda/include/crt/sm_70_rt.h", + "cuda/include/crt/sm_70_rt.hpp", + "cuda/include/crt/storage_class.h", + "cuda/include/cuComplex.h", + "cuda/include/cublas.h", + "cuda/include/cublasXt.h", + "cuda/include/cublas_api.h", + "cuda/include/cublas_v2.h", + "cuda/include/cuda.h", + "cuda/include/cudaEGL.h", + "cuda/include/cudaGL.h", + "cuda/include/cudaProfiler.h", + "cuda/include/cudaVDPAU.h", + "cuda/include/cuda_device_runtime_api.h", + "cuda/include/cuda_egl_interop.h", + "cuda/include/cuda_fp16.h", + "cuda/include/cuda_fp16.hpp", + "cuda/include/cuda_gl_interop.h", + "cuda/include/cuda_occupancy.h", + "cuda/include/cuda_profiler_api.h", + "cuda/include/cuda_runtime.h", + "cuda/include/cuda_runtime_api.h", + "cuda/include/cuda_surface_types.h", + "cuda/include/cuda_texture_types.h", + "cuda/include/cuda_vdpau_interop.h", + "cuda/include/cudalibxt.h", + "cuda/include/cudart_platform.h", + "cuda/include/cufft.h", + "cuda/include/cufftXt.h", + "cuda/include/cufftw.h", + "cuda/include/curand.h", + "cuda/include/curand_discrete.h", + "cuda/include/curand_discrete2.h", + "cuda/include/curand_globals.h", + "cuda/include/curand_kernel.h", + "cuda/include/curand_lognormal.h", + "cuda/include/curand_mrg32k3a.h", + "cuda/include/curand_mtgp32.h", + "cuda/include/curand_mtgp32_host.h", + "cuda/include/curand_mtgp32_kernel.h", + "cuda/include/curand_mtgp32dc_p_11213.h", + "cuda/include/curand_normal.h", + "cuda/include/curand_normal_static.h", + "cuda/include/curand_philox4x32_x.h", + "cuda/include/curand_poisson.h", + "cuda/include/curand_precalc.h", + "cuda/include/curand_uniform.h", + "cuda/include/cusolverDn.h", + "cuda/include/cusolverRf.h", + "cuda/include/cusolverSp.h", + "cuda/include/cusolverSp_LOWLEVEL_PREVIEW.h", + "cuda/include/cusolver_common.h", + "cuda/include/cusparse.h", + "cuda/include/cusparse_v2.h", + "cuda/include/device_atomic_functions.h", + "cuda/include/device_atomic_functions.hpp", + "cuda/include/device_double_functions.h", + "cuda/include/device_functions.h", + "cuda/include/device_launch_parameters.h", + "cuda/include/device_types.h", + "cuda/include/driver_functions.h", + "cuda/include/driver_types.h", + "cuda/include/fatBinaryCtl.h", + "cuda/include/fatbinary.h", + "cuda/include/host_config.h", + "cuda/include/host_defines.h", + "cuda/include/library_types.h", + "cuda/include/math_constants.h", + "cuda/include/math_functions.h", + "cuda/include/mma.h", + "cuda/include/npp.h", + "cuda/include/nppcore.h", + "cuda/include/nppdefs.h", + "cuda/include/nppi.h", + "cuda/include/nppi_arithmetic_and_logical_operations.h", + "cuda/include/nppi_color_conversion.h", + "cuda/include/nppi_compression_functions.h", + "cuda/include/nppi_computer_vision.h", + "cuda/include/nppi_data_exchange_and_initialization.h", + "cuda/include/nppi_filtering_functions.h", + "cuda/include/nppi_geometry_transforms.h", + "cuda/include/nppi_linear_transforms.h", + "cuda/include/nppi_morphological_operations.h", + "cuda/include/nppi_statistics_functions.h", + "cuda/include/nppi_support_functions.h", + "cuda/include/nppi_threshold_and_compare_operations.h", + "cuda/include/npps.h", + "cuda/include/npps_arithmetic_and_logical_operations.h", + "cuda/include/npps_conversion_functions.h", + "cuda/include/npps_filtering_functions.h", + "cuda/include/npps_initialization.h", + "cuda/include/npps_statistics_functions.h", + "cuda/include/npps_support_functions.h", + "cuda/include/nppversion.h", + "cuda/include/nvToolsExt.h", + "cuda/include/nvToolsExtCuda.h", + "cuda/include/nvToolsExtCudaRt.h", + "cuda/include/nvToolsExtMeta.h", + "cuda/include/nvToolsExtSync.h", + "cuda/include/nvblas.h", + "cuda/include/nvfunctional", + "cuda/include/nvgraph.h", + "cuda/include/nvjpeg.h", + "cuda/include/nvml.h", + "cuda/include/nvrtc.h", + "cuda/include/nvtx3/nvToolsExt.h", + "cuda/include/nvtx3/nvToolsExtCuda.h", + "cuda/include/nvtx3/nvToolsExtCudaRt.h", + "cuda/include/nvtx3/nvToolsExtOpenCL.h", + "cuda/include/nvtx3/nvToolsExtSync.h", + "cuda/include/nvtx3/nvtxDetail/nvtxImpl.h", + "cuda/include/nvtx3/nvtxDetail/nvtxImplCore.h", + "cuda/include/nvtx3/nvtxDetail/nvtxImplCudaRt_v3.h", + "cuda/include/nvtx3/nvtxDetail/nvtxImplCuda_v3.h", + "cuda/include/nvtx3/nvtxDetail/nvtxImplOpenCL_v3.h", + "cuda/include/nvtx3/nvtxDetail/nvtxImplSync_v3.h", + "cuda/include/nvtx3/nvtxDetail/nvtxInit.h", + "cuda/include/nvtx3/nvtxDetail/nvtxInitDecls.h", + "cuda/include/nvtx3/nvtxDetail/nvtxInitDefs.h", + "cuda/include/nvtx3/nvtxDetail/nvtxLinkOnce.h", + "cuda/include/nvtx3/nvtxDetail/nvtxTypes.h", + "cuda/include/sm_20_atomic_functions.h", + "cuda/include/sm_20_atomic_functions.hpp", + "cuda/include/sm_20_intrinsics.h", + "cuda/include/sm_20_intrinsics.hpp", + "cuda/include/sm_30_intrinsics.h", + "cuda/include/sm_30_intrinsics.hpp", + "cuda/include/sm_32_atomic_functions.h", + "cuda/include/sm_32_atomic_functions.hpp", + "cuda/include/sm_32_intrinsics.h", + "cuda/include/sm_32_intrinsics.hpp", + "cuda/include/sm_35_atomic_functions.h", + "cuda/include/sm_35_intrinsics.h", + "cuda/include/sm_60_atomic_functions.h", + "cuda/include/sm_60_atomic_functions.hpp", + "cuda/include/sm_61_intrinsics.h", + "cuda/include/sm_61_intrinsics.hpp", + "cuda/include/sobol_direction_vectors.h", + "cuda/include/surface_functions.h", + "cuda/include/surface_functions.hpp", + "cuda/include/surface_indirect_functions.h", + "cuda/include/surface_indirect_functions.hpp", + "cuda/include/surface_types.h", + "cuda/include/texture_fetch_functions.h", + "cuda/include/texture_fetch_functions.hpp", + "cuda/include/texture_indirect_functions.h", + "cuda/include/texture_indirect_functions.hpp", + "cuda/include/texture_types.h", + "cuda/include/thrust/adjacent_difference.h", + "cuda/include/thrust/advance.h", + "cuda/include/thrust/binary_search.h", + "cuda/include/thrust/complex.h", + "cuda/include/thrust/copy.h", + "cuda/include/thrust/count.h", + "cuda/include/thrust/detail/adjacent_difference.inl", + "cuda/include/thrust/detail/advance.inl", + "cuda/include/thrust/detail/alignment.h", + "cuda/include/thrust/detail/allocator/allocator_traits.h", + "cuda/include/thrust/detail/allocator/allocator_traits.inl", + "cuda/include/thrust/detail/allocator/copy_construct_range.h", + "cuda/include/thrust/detail/allocator/copy_construct_range.inl", + "cuda/include/thrust/detail/allocator/default_construct_range.h", + "cuda/include/thrust/detail/allocator/default_construct_range.inl", + "cuda/include/thrust/detail/allocator/destroy_range.h", + "cuda/include/thrust/detail/allocator/destroy_range.inl", + "cuda/include/thrust/detail/allocator/fill_construct_range.h", + "cuda/include/thrust/detail/allocator/fill_construct_range.inl", + "cuda/include/thrust/detail/allocator/malloc_allocator.h", + "cuda/include/thrust/detail/allocator/malloc_allocator.inl", + "cuda/include/thrust/detail/allocator/no_throw_allocator.h", + "cuda/include/thrust/detail/allocator/tagged_allocator.h", + "cuda/include/thrust/detail/allocator/tagged_allocator.inl", + "cuda/include/thrust/detail/allocator/temporary_allocator.h", + "cuda/include/thrust/detail/allocator/temporary_allocator.inl", + "cuda/include/thrust/detail/binary_search.inl", + "cuda/include/thrust/detail/complex/arithmetic.h", + "cuda/include/thrust/detail/complex/c99math.h", + "cuda/include/thrust/detail/complex/catrig.h", + "cuda/include/thrust/detail/complex/catrigf.h", + "cuda/include/thrust/detail/complex/ccosh.h", + "cuda/include/thrust/detail/complex/ccoshf.h", + "cuda/include/thrust/detail/complex/cexp.h", + "cuda/include/thrust/detail/complex/cexpf.h", + "cuda/include/thrust/detail/complex/clog.h", + "cuda/include/thrust/detail/complex/clogf.h", + "cuda/include/thrust/detail/complex/complex.inl", + "cuda/include/thrust/detail/complex/cpow.h", + "cuda/include/thrust/detail/complex/cproj.h", + "cuda/include/thrust/detail/complex/csinh.h", + "cuda/include/thrust/detail/complex/csinhf.h", + "cuda/include/thrust/detail/complex/csqrt.h", + "cuda/include/thrust/detail/complex/csqrtf.h", + "cuda/include/thrust/detail/complex/ctanh.h", + "cuda/include/thrust/detail/complex/ctanhf.h", + "cuda/include/thrust/detail/complex/math_private.h", + "cuda/include/thrust/detail/complex/stream.h", + "cuda/include/thrust/detail/config.h", + "cuda/include/thrust/detail/config/compiler.h", + "cuda/include/thrust/detail/config/compiler_fence.h", + "cuda/include/thrust/detail/config/config.h", + "cuda/include/thrust/detail/config/debug.h", + "cuda/include/thrust/detail/config/device_system.h", + "cuda/include/thrust/detail/config/exec_check_disable.h", + "cuda/include/thrust/detail/config/forceinline.h", + "cuda/include/thrust/detail/config/global_workarounds.h", + "cuda/include/thrust/detail/config/host_device.h", + "cuda/include/thrust/detail/config/host_system.h", + "cuda/include/thrust/detail/config/simple_defines.h", + "cuda/include/thrust/detail/contiguous_storage.h", + "cuda/include/thrust/detail/contiguous_storage.inl", + "cuda/include/thrust/detail/copy.h", + "cuda/include/thrust/detail/copy.inl", + "cuda/include/thrust/detail/copy_if.h", + "cuda/include/thrust/detail/copy_if.inl", + "cuda/include/thrust/detail/count.inl", + "cuda/include/thrust/detail/cstdint.h", + "cuda/include/thrust/detail/device_delete.inl", + "cuda/include/thrust/detail/device_free.inl", + "cuda/include/thrust/detail/device_malloc.inl", + "cuda/include/thrust/detail/device_new.inl", + "cuda/include/thrust/detail/device_ptr.inl", + "cuda/include/thrust/detail/device_reference.inl", + "cuda/include/thrust/detail/device_vector.inl", + "cuda/include/thrust/detail/dispatch/is_trivial_copy.h", + "cuda/include/thrust/detail/distance.inl", + "cuda/include/thrust/detail/equal.inl", + "cuda/include/thrust/detail/execute_with_allocator.h", + "cuda/include/thrust/detail/execution_policy.h", + "cuda/include/thrust/detail/extrema.inl", + "cuda/include/thrust/detail/fill.inl", + "cuda/include/thrust/detail/find.inl", + "cuda/include/thrust/detail/for_each.inl", + "cuda/include/thrust/detail/function.h", + "cuda/include/thrust/detail/functional.inl", + "cuda/include/thrust/detail/functional/actor.h", + "cuda/include/thrust/detail/functional/actor.inl", + "cuda/include/thrust/detail/functional/argument.h", + "cuda/include/thrust/detail/functional/composite.h", + "cuda/include/thrust/detail/functional/operators.h", + "cuda/include/thrust/detail/functional/operators/arithmetic_operators.h", + "cuda/include/thrust/detail/functional/operators/assignment_operator.h", + "cuda/include/thrust/detail/functional/operators/bitwise_operators.h", + "cuda/include/thrust/detail/functional/operators/compound_assignment_operators.h", + "cuda/include/thrust/detail/functional/operators/logical_operators.h", + "cuda/include/thrust/detail/functional/operators/operator_adaptors.h", + "cuda/include/thrust/detail/functional/operators/relational_operators.h", + "cuda/include/thrust/detail/functional/placeholder.h", + "cuda/include/thrust/detail/functional/value.h", + "cuda/include/thrust/detail/gather.inl", + "cuda/include/thrust/detail/generate.inl", + "cuda/include/thrust/detail/get_iterator_value.h", + "cuda/include/thrust/detail/host_vector.inl", + "cuda/include/thrust/detail/inner_product.inl", + "cuda/include/thrust/detail/integer_math.h", + "cuda/include/thrust/detail/integer_traits.h", + "cuda/include/thrust/detail/internal_functional.h", + "cuda/include/thrust/detail/logical.inl", + "cuda/include/thrust/detail/malloc_and_free.h", + "cuda/include/thrust/detail/merge.inl", + "cuda/include/thrust/detail/minmax.h", + "cuda/include/thrust/detail/mismatch.inl", + "cuda/include/thrust/detail/mpl/math.h", + "cuda/include/thrust/detail/numeric_traits.h", + "cuda/include/thrust/detail/overlapped_copy.h", + "cuda/include/thrust/detail/pair.inl", + "cuda/include/thrust/detail/partition.inl", + "cuda/include/thrust/detail/pointer.h", + "cuda/include/thrust/detail/pointer.inl", + "cuda/include/thrust/detail/preprocessor.h", + "cuda/include/thrust/detail/range/head_flags.h", + "cuda/include/thrust/detail/range/tail_flags.h", + "cuda/include/thrust/detail/raw_pointer_cast.h", + "cuda/include/thrust/detail/raw_reference_cast.h", + "cuda/include/thrust/detail/reduce.inl", + "cuda/include/thrust/detail/reference.h", + "cuda/include/thrust/detail/reference.inl", + "cuda/include/thrust/detail/reference_forward_declaration.h", + "cuda/include/thrust/detail/remove.inl", + "cuda/include/thrust/detail/replace.inl", + "cuda/include/thrust/detail/reverse.inl", + "cuda/include/thrust/detail/scan.inl", + "cuda/include/thrust/detail/scatter.inl", + "cuda/include/thrust/detail/seq.h", + "cuda/include/thrust/detail/sequence.inl", + "cuda/include/thrust/detail/set_operations.inl", + "cuda/include/thrust/detail/sort.inl", + "cuda/include/thrust/detail/static_assert.h", + "cuda/include/thrust/detail/static_map.h", + "cuda/include/thrust/detail/swap.h", + "cuda/include/thrust/detail/swap.inl", + "cuda/include/thrust/detail/swap_ranges.inl", + "cuda/include/thrust/detail/tabulate.inl", + "cuda/include/thrust/detail/temporary_array.h", + "cuda/include/thrust/detail/temporary_array.inl", + "cuda/include/thrust/detail/temporary_buffer.h", + "cuda/include/thrust/detail/transform.inl", + "cuda/include/thrust/detail/transform_reduce.inl", + "cuda/include/thrust/detail/transform_scan.inl", + "cuda/include/thrust/detail/trivial_sequence.h", + "cuda/include/thrust/detail/tuple.inl", + "cuda/include/thrust/detail/tuple_meta_transform.h", + "cuda/include/thrust/detail/tuple_transform.h", + "cuda/include/thrust/detail/type_traits.h", + "cuda/include/thrust/detail/type_traits/algorithm/intermediate_type_from_function_and_iterators.h", + "cuda/include/thrust/detail/type_traits/function_traits.h", + "cuda/include/thrust/detail/type_traits/has_member_function.h", + "cuda/include/thrust/detail/type_traits/has_nested_type.h", + "cuda/include/thrust/detail/type_traits/has_trivial_assign.h", + "cuda/include/thrust/detail/type_traits/is_call_possible.h", + "cuda/include/thrust/detail/type_traits/is_metafunction_defined.h", + "cuda/include/thrust/detail/type_traits/iterator/is_discard_iterator.h", + "cuda/include/thrust/detail/type_traits/iterator/is_output_iterator.h", + "cuda/include/thrust/detail/type_traits/minimum_type.h", + "cuda/include/thrust/detail/type_traits/pointer_traits.h", + "cuda/include/thrust/detail/type_traits/result_of_adaptable_function.h", + "cuda/include/thrust/detail/uninitialized_copy.inl", + "cuda/include/thrust/detail/uninitialized_fill.inl", + "cuda/include/thrust/detail/unique.inl", + "cuda/include/thrust/detail/use_default.h", + "cuda/include/thrust/detail/util/align.h", + "cuda/include/thrust/detail/util/blocking.h", + "cuda/include/thrust/detail/vector_base.h", + "cuda/include/thrust/detail/vector_base.inl", + "cuda/include/thrust/device_allocator.h", + "cuda/include/thrust/device_delete.h", + "cuda/include/thrust/device_free.h", + "cuda/include/thrust/device_malloc.h", + "cuda/include/thrust/device_malloc_allocator.h", + "cuda/include/thrust/device_new.h", + "cuda/include/thrust/device_new_allocator.h", + "cuda/include/thrust/device_ptr.h", + "cuda/include/thrust/device_reference.h", + "cuda/include/thrust/device_vector.h", + "cuda/include/thrust/distance.h", + "cuda/include/thrust/equal.h", + "cuda/include/thrust/execution_policy.h", + "cuda/include/thrust/extrema.h", + "cuda/include/thrust/fill.h", + "cuda/include/thrust/find.h", + "cuda/include/thrust/for_each.h", + "cuda/include/thrust/functional.h", + "cuda/include/thrust/gather.h", + "cuda/include/thrust/generate.h", + "cuda/include/thrust/host_vector.h", + "cuda/include/thrust/inner_product.h", + "cuda/include/thrust/iterator/constant_iterator.h", + "cuda/include/thrust/iterator/counting_iterator.h", + "cuda/include/thrust/iterator/detail/any_assign.h", + "cuda/include/thrust/iterator/detail/any_system_tag.h", + "cuda/include/thrust/iterator/detail/constant_iterator_base.h", + "cuda/include/thrust/iterator/detail/counting_iterator.inl", + "cuda/include/thrust/iterator/detail/device_system_tag.h", + "cuda/include/thrust/iterator/detail/discard_iterator_base.h", + "cuda/include/thrust/iterator/detail/distance_from_result.h", + "cuda/include/thrust/iterator/detail/host_system_tag.h", + "cuda/include/thrust/iterator/detail/is_iterator_category.h", + "cuda/include/thrust/iterator/detail/is_trivial_iterator.h", + "cuda/include/thrust/iterator/detail/iterator_adaptor_base.h", + "cuda/include/thrust/iterator/detail/iterator_category_to_system.h", + "cuda/include/thrust/iterator/detail/iterator_category_to_traversal.h", + "cuda/include/thrust/iterator/detail/iterator_category_with_system_and_traversal.h", + "cuda/include/thrust/iterator/detail/iterator_facade_category.h", + "cuda/include/thrust/iterator/detail/iterator_traits.inl", + "cuda/include/thrust/iterator/detail/iterator_traversal_tags.h", + "cuda/include/thrust/iterator/detail/join_iterator.h", + "cuda/include/thrust/iterator/detail/minimum_category.h", + "cuda/include/thrust/iterator/detail/minimum_system.h", + "cuda/include/thrust/iterator/detail/normal_iterator.h", + "cuda/include/thrust/iterator/detail/permutation_iterator_base.h", + "cuda/include/thrust/iterator/detail/retag.h", + "cuda/include/thrust/iterator/detail/reverse_iterator.inl", + "cuda/include/thrust/iterator/detail/reverse_iterator_base.h", + "cuda/include/thrust/iterator/detail/tagged_iterator.h", + "cuda/include/thrust/iterator/detail/transform_iterator.inl", + "cuda/include/thrust/iterator/detail/transform_output_iterator.inl", + "cuda/include/thrust/iterator/detail/tuple_of_iterator_references.h", + "cuda/include/thrust/iterator/detail/universal_categories.h", + "cuda/include/thrust/iterator/detail/zip_iterator.inl", + "cuda/include/thrust/iterator/detail/zip_iterator_base.h", + "cuda/include/thrust/iterator/discard_iterator.h", + "cuda/include/thrust/iterator/iterator_adaptor.h", + "cuda/include/thrust/iterator/iterator_categories.h", + "cuda/include/thrust/iterator/iterator_facade.h", + "cuda/include/thrust/iterator/iterator_traits.h", + "cuda/include/thrust/iterator/permutation_iterator.h", + "cuda/include/thrust/iterator/retag.h", + "cuda/include/thrust/iterator/reverse_iterator.h", + "cuda/include/thrust/iterator/transform_iterator.h", + "cuda/include/thrust/iterator/transform_output_iterator.h", + "cuda/include/thrust/iterator/zip_iterator.h", + "cuda/include/thrust/logical.h", + "cuda/include/thrust/memory.h", + "cuda/include/thrust/merge.h", + "cuda/include/thrust/mismatch.h", + "cuda/include/thrust/pair.h", + "cuda/include/thrust/partition.h", + "cuda/include/thrust/random.h", + "cuda/include/thrust/random/detail/discard_block_engine.inl", + "cuda/include/thrust/random/detail/linear_congruential_engine.inl", + "cuda/include/thrust/random/detail/linear_congruential_engine_discard.h", + "cuda/include/thrust/random/detail/linear_feedback_shift_engine.inl", + "cuda/include/thrust/random/detail/linear_feedback_shift_engine_wordmask.h", + "cuda/include/thrust/random/detail/mod.h", + "cuda/include/thrust/random/detail/normal_distribution.inl", + "cuda/include/thrust/random/detail/normal_distribution_base.h", + "cuda/include/thrust/random/detail/random_core_access.h", + "cuda/include/thrust/random/detail/subtract_with_carry_engine.inl", + "cuda/include/thrust/random/detail/uniform_int_distribution.inl", + "cuda/include/thrust/random/detail/uniform_real_distribution.inl", + "cuda/include/thrust/random/detail/xor_combine_engine.inl", + "cuda/include/thrust/random/detail/xor_combine_engine_max.h", + "cuda/include/thrust/random/discard_block_engine.h", + "cuda/include/thrust/random/linear_congruential_engine.h", + "cuda/include/thrust/random/linear_feedback_shift_engine.h", + "cuda/include/thrust/random/normal_distribution.h", + "cuda/include/thrust/random/subtract_with_carry_engine.h", + "cuda/include/thrust/random/uniform_int_distribution.h", + "cuda/include/thrust/random/uniform_real_distribution.h", + "cuda/include/thrust/random/xor_combine_engine.h", + "cuda/include/thrust/reduce.h", + "cuda/include/thrust/remove.h", + "cuda/include/thrust/replace.h", + "cuda/include/thrust/reverse.h", + "cuda/include/thrust/scan.h", + "cuda/include/thrust/scatter.h", + "cuda/include/thrust/sequence.h", + "cuda/include/thrust/set_operations.h", + "cuda/include/thrust/sort.h", + "cuda/include/thrust/swap.h", + "cuda/include/thrust/system/cpp/detail/adjacent_difference.h", + "cuda/include/thrust/system/cpp/detail/assign_value.h", + "cuda/include/thrust/system/cpp/detail/binary_search.h", + "cuda/include/thrust/system/cpp/detail/copy.h", + "cuda/include/thrust/system/cpp/detail/copy_if.h", + "cuda/include/thrust/system/cpp/detail/count.h", + "cuda/include/thrust/system/cpp/detail/equal.h", + "cuda/include/thrust/system/cpp/detail/execution_policy.h", + "cuda/include/thrust/system/cpp/detail/extrema.h", + "cuda/include/thrust/system/cpp/detail/fill.h", + "cuda/include/thrust/system/cpp/detail/find.h", + "cuda/include/thrust/system/cpp/detail/for_each.h", + "cuda/include/thrust/system/cpp/detail/gather.h", + "cuda/include/thrust/system/cpp/detail/generate.h", + "cuda/include/thrust/system/cpp/detail/get_value.h", + "cuda/include/thrust/system/cpp/detail/inner_product.h", + "cuda/include/thrust/system/cpp/detail/iter_swap.h", + "cuda/include/thrust/system/cpp/detail/logical.h", + "cuda/include/thrust/system/cpp/detail/malloc_and_free.h", + "cuda/include/thrust/system/cpp/detail/memory.inl", + "cuda/include/thrust/system/cpp/detail/merge.h", + "cuda/include/thrust/system/cpp/detail/mismatch.h", + "cuda/include/thrust/system/cpp/detail/par.h", + "cuda/include/thrust/system/cpp/detail/partition.h", + "cuda/include/thrust/system/cpp/detail/reduce.h", + "cuda/include/thrust/system/cpp/detail/reduce_by_key.h", + "cuda/include/thrust/system/cpp/detail/remove.h", + "cuda/include/thrust/system/cpp/detail/replace.h", + "cuda/include/thrust/system/cpp/detail/reverse.h", + "cuda/include/thrust/system/cpp/detail/scan.h", + "cuda/include/thrust/system/cpp/detail/scan_by_key.h", + "cuda/include/thrust/system/cpp/detail/scatter.h", + "cuda/include/thrust/system/cpp/detail/sequence.h", + "cuda/include/thrust/system/cpp/detail/set_operations.h", + "cuda/include/thrust/system/cpp/detail/sort.h", + "cuda/include/thrust/system/cpp/detail/swap_ranges.h", + "cuda/include/thrust/system/cpp/detail/tabulate.h", + "cuda/include/thrust/system/cpp/detail/temporary_buffer.h", + "cuda/include/thrust/system/cpp/detail/transform.h", + "cuda/include/thrust/system/cpp/detail/transform_reduce.h", + "cuda/include/thrust/system/cpp/detail/transform_scan.h", + "cuda/include/thrust/system/cpp/detail/uninitialized_copy.h", + "cuda/include/thrust/system/cpp/detail/uninitialized_fill.h", + "cuda/include/thrust/system/cpp/detail/unique.h", + "cuda/include/thrust/system/cpp/detail/unique_by_key.h", + "cuda/include/thrust/system/cpp/detail/vector.inl", + "cuda/include/thrust/system/cpp/execution_policy.h", + "cuda/include/thrust/system/cpp/memory.h", + "cuda/include/thrust/system/cpp/vector.h", + "cuda/include/thrust/system/cuda/config.h", + "cuda/include/thrust/system/cuda/detail/adjacent_difference.h", + "cuda/include/thrust/system/cuda/detail/assign_value.h", + "cuda/include/thrust/system/cuda/detail/binary_search.h", + "cuda/include/thrust/system/cuda/detail/copy.h", + "cuda/include/thrust/system/cuda/detail/copy_if.h", + "cuda/include/thrust/system/cuda/detail/core/agent_launcher.h", + "cuda/include/thrust/system/cuda/detail/core/alignment.h", + "cuda/include/thrust/system/cuda/detail/core/triple_chevron_launch.h", + "cuda/include/thrust/system/cuda/detail/core/util.h", + "cuda/include/thrust/system/cuda/detail/count.h", + "cuda/include/thrust/system/cuda/detail/cross_system.h", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_histogram.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_downsweep.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_upsweep.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_reduce.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_reduce_by_key.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_rle.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_scan.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_segment_fixup.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_select_if.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/agent_spmv_orig.cuh", + "cuda/include/thrust/system/cuda/detail/cub/agent/single_pass_scan_operators.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_adjacent_difference.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_discontinuity.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_exchange.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_histogram.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_load.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_radix_rank.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_radix_sort.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_raking_layout.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_reduce.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_scan.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_shuffle.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/block_store.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_atomic.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_sort.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking_commutative_only.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_warp_reductions.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_raking.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans2.cuh", + "cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans3.cuh", + "cuda/include/thrust/system/cuda/detail/cub/cub.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_histogram.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_partition.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_radix_sort.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_reduce.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_run_length_encode.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_scan.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_segmented_radix_sort.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_segmented_reduce.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_select.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/device_spmv.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_histogram.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_radix_sort.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce_by_key.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_rle.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_scan.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_select_if.cuh", + "cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_orig.cuh", + "cuda/include/thrust/system/cuda/detail/cub/grid/grid_barrier.cuh", + "cuda/include/thrust/system/cuda/detail/cub/grid/grid_even_share.cuh", + "cuda/include/thrust/system/cuda/detail/cub/grid/grid_mapping.cuh", + "cuda/include/thrust/system/cuda/detail/cub/grid/grid_queue.cuh", + "cuda/include/thrust/system/cuda/detail/cub/host/mutex.cuh", + "cuda/include/thrust/system/cuda/detail/cub/iterator/arg_index_input_iterator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/iterator/cache_modified_input_iterator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/iterator/cache_modified_output_iterator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/iterator/constant_input_iterator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/iterator/counting_input_iterator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/iterator/discard_output_iterator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/iterator/tex_obj_input_iterator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/iterator/tex_ref_input_iterator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/iterator/transform_input_iterator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/thread/thread_load.cuh", + "cuda/include/thrust/system/cuda/detail/cub/thread/thread_operators.cuh", + "cuda/include/thrust/system/cuda/detail/cub/thread/thread_reduce.cuh", + "cuda/include/thrust/system/cuda/detail/cub/thread/thread_scan.cuh", + "cuda/include/thrust/system/cuda/detail/cub/thread/thread_search.cuh", + "cuda/include/thrust/system/cuda/detail/cub/thread/thread_store.cuh", + "cuda/include/thrust/system/cuda/detail/cub/util_allocator.cuh", + "cuda/include/thrust/system/cuda/detail/cub/util_arch.cuh", + "cuda/include/thrust/system/cuda/detail/cub/util_debug.cuh", + "cuda/include/thrust/system/cuda/detail/cub/util_device.cuh", + "cuda/include/thrust/system/cuda/detail/cub/util_macro.cuh", + "cuda/include/thrust/system/cuda/detail/cub/util_namespace.cuh", + "cuda/include/thrust/system/cuda/detail/cub/util_ptx.cuh", + "cuda/include/thrust/system/cuda/detail/cub/util_type.cuh", + "cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_shfl.cuh", + "cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_smem.cuh", + "cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_shfl.cuh", + "cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_smem.cuh", + "cuda/include/thrust/system/cuda/detail/cub/warp/warp_reduce.cuh", + "cuda/include/thrust/system/cuda/detail/cub/warp/warp_scan.cuh", + "cuda/include/thrust/system/cuda/detail/equal.h", + "cuda/include/thrust/system/cuda/detail/error.inl", + "cuda/include/thrust/system/cuda/detail/execution_policy.h", + "cuda/include/thrust/system/cuda/detail/extrema.h", + "cuda/include/thrust/system/cuda/detail/fill.h", + "cuda/include/thrust/system/cuda/detail/find.h", + "cuda/include/thrust/system/cuda/detail/for_each.h", + "cuda/include/thrust/system/cuda/detail/gather.h", + "cuda/include/thrust/system/cuda/detail/generate.h", + "cuda/include/thrust/system/cuda/detail/get_value.h", + "cuda/include/thrust/system/cuda/detail/guarded_cuda_runtime_api.h", + "cuda/include/thrust/system/cuda/detail/guarded_driver_types.h", + "cuda/include/thrust/system/cuda/detail/inner_product.h", + "cuda/include/thrust/system/cuda/detail/internal/copy_cross_system.h", + "cuda/include/thrust/system/cuda/detail/internal/copy_device_to_device.h", + "cuda/include/thrust/system/cuda/detail/iter_swap.h", + "cuda/include/thrust/system/cuda/detail/logical.h", + "cuda/include/thrust/system/cuda/detail/malloc_and_free.h", + "cuda/include/thrust/system/cuda/detail/memory.inl", + "cuda/include/thrust/system/cuda/detail/merge.h", + "cuda/include/thrust/system/cuda/detail/mismatch.h", + "cuda/include/thrust/system/cuda/detail/par.h", + "cuda/include/thrust/system/cuda/detail/par_to_seq.h", + "cuda/include/thrust/system/cuda/detail/parallel_for.h", + "cuda/include/thrust/system/cuda/detail/partition.h", + "cuda/include/thrust/system/cuda/detail/reduce.h", + "cuda/include/thrust/system/cuda/detail/reduce_by_key.h", + "cuda/include/thrust/system/cuda/detail/remove.h", + "cuda/include/thrust/system/cuda/detail/replace.h", + "cuda/include/thrust/system/cuda/detail/reverse.h", + "cuda/include/thrust/system/cuda/detail/scan.h", + "cuda/include/thrust/system/cuda/detail/scan_by_key.h", + "cuda/include/thrust/system/cuda/detail/scatter.h", + "cuda/include/thrust/system/cuda/detail/sequence.h", + "cuda/include/thrust/system/cuda/detail/set_operations.h", + "cuda/include/thrust/system/cuda/detail/sort.h", + "cuda/include/thrust/system/cuda/detail/swap_ranges.h", + "cuda/include/thrust/system/cuda/detail/tabulate.h", + "cuda/include/thrust/system/cuda/detail/temporary_buffer.h", + "cuda/include/thrust/system/cuda/detail/terminate.h", + "cuda/include/thrust/system/cuda/detail/transform.h", + "cuda/include/thrust/system/cuda/detail/transform_reduce.h", + "cuda/include/thrust/system/cuda/detail/transform_scan.h", + "cuda/include/thrust/system/cuda/detail/uninitialized_copy.h", + "cuda/include/thrust/system/cuda/detail/uninitialized_fill.h", + "cuda/include/thrust/system/cuda/detail/unique.h", + "cuda/include/thrust/system/cuda/detail/unique_by_key.h", + "cuda/include/thrust/system/cuda/detail/util.h", + "cuda/include/thrust/system/cuda/detail/vector.inl", + "cuda/include/thrust/system/cuda/error.h", + "cuda/include/thrust/system/cuda/execution_policy.h", + "cuda/include/thrust/system/cuda/experimental/pinned_allocator.h", + "cuda/include/thrust/system/cuda/memory.h", + "cuda/include/thrust/system/cuda/vector.h", + "cuda/include/thrust/system/detail/adl/adjacent_difference.h", + "cuda/include/thrust/system/detail/adl/assign_value.h", + "cuda/include/thrust/system/detail/adl/binary_search.h", + "cuda/include/thrust/system/detail/adl/copy.h", + "cuda/include/thrust/system/detail/adl/copy_if.h", + "cuda/include/thrust/system/detail/adl/count.h", + "cuda/include/thrust/system/detail/adl/equal.h", + "cuda/include/thrust/system/detail/adl/extrema.h", + "cuda/include/thrust/system/detail/adl/fill.h", + "cuda/include/thrust/system/detail/adl/find.h", + "cuda/include/thrust/system/detail/adl/for_each.h", + "cuda/include/thrust/system/detail/adl/gather.h", + "cuda/include/thrust/system/detail/adl/generate.h", + "cuda/include/thrust/system/detail/adl/get_value.h", + "cuda/include/thrust/system/detail/adl/inner_product.h", + "cuda/include/thrust/system/detail/adl/iter_swap.h", + "cuda/include/thrust/system/detail/adl/logical.h", + "cuda/include/thrust/system/detail/adl/malloc_and_free.h", + "cuda/include/thrust/system/detail/adl/merge.h", + "cuda/include/thrust/system/detail/adl/mismatch.h", + "cuda/include/thrust/system/detail/adl/partition.h", + "cuda/include/thrust/system/detail/adl/reduce.h", + "cuda/include/thrust/system/detail/adl/reduce_by_key.h", + "cuda/include/thrust/system/detail/adl/remove.h", + "cuda/include/thrust/system/detail/adl/replace.h", + "cuda/include/thrust/system/detail/adl/reverse.h", + "cuda/include/thrust/system/detail/adl/scan.h", + "cuda/include/thrust/system/detail/adl/scan_by_key.h", + "cuda/include/thrust/system/detail/adl/scatter.h", + "cuda/include/thrust/system/detail/adl/sequence.h", + "cuda/include/thrust/system/detail/adl/set_operations.h", + "cuda/include/thrust/system/detail/adl/sort.h", + "cuda/include/thrust/system/detail/adl/swap_ranges.h", + "cuda/include/thrust/system/detail/adl/tabulate.h", + "cuda/include/thrust/system/detail/adl/temporary_buffer.h", + "cuda/include/thrust/system/detail/adl/transform.h", + "cuda/include/thrust/system/detail/adl/transform_reduce.h", + "cuda/include/thrust/system/detail/adl/transform_scan.h", + "cuda/include/thrust/system/detail/adl/uninitialized_copy.h", + "cuda/include/thrust/system/detail/adl/uninitialized_fill.h", + "cuda/include/thrust/system/detail/adl/unique.h", + "cuda/include/thrust/system/detail/adl/unique_by_key.h", + "cuda/include/thrust/system/detail/bad_alloc.h", + "cuda/include/thrust/system/detail/errno.h", + "cuda/include/thrust/system/detail/error_category.inl", + "cuda/include/thrust/system/detail/error_code.inl", + "cuda/include/thrust/system/detail/error_condition.inl", + "cuda/include/thrust/system/detail/generic/adjacent_difference.h", + "cuda/include/thrust/system/detail/generic/adjacent_difference.inl", + "cuda/include/thrust/system/detail/generic/advance.h", + "cuda/include/thrust/system/detail/generic/advance.inl", + "cuda/include/thrust/system/detail/generic/binary_search.h", + "cuda/include/thrust/system/detail/generic/binary_search.inl", + "cuda/include/thrust/system/detail/generic/copy.h", + "cuda/include/thrust/system/detail/generic/copy.inl", + "cuda/include/thrust/system/detail/generic/copy_if.h", + "cuda/include/thrust/system/detail/generic/copy_if.inl", + "cuda/include/thrust/system/detail/generic/count.h", + "cuda/include/thrust/system/detail/generic/count.inl", + "cuda/include/thrust/system/detail/generic/distance.h", + "cuda/include/thrust/system/detail/generic/distance.inl", + "cuda/include/thrust/system/detail/generic/equal.h", + "cuda/include/thrust/system/detail/generic/equal.inl", + "cuda/include/thrust/system/detail/generic/extrema.h", + "cuda/include/thrust/system/detail/generic/extrema.inl", + "cuda/include/thrust/system/detail/generic/fill.h", + "cuda/include/thrust/system/detail/generic/find.h", + "cuda/include/thrust/system/detail/generic/find.inl", + "cuda/include/thrust/system/detail/generic/for_each.h", + "cuda/include/thrust/system/detail/generic/gather.h", + "cuda/include/thrust/system/detail/generic/gather.inl", + "cuda/include/thrust/system/detail/generic/generate.h", + "cuda/include/thrust/system/detail/generic/generate.inl", + "cuda/include/thrust/system/detail/generic/inner_product.h", + "cuda/include/thrust/system/detail/generic/inner_product.inl", + "cuda/include/thrust/system/detail/generic/logical.h", + "cuda/include/thrust/system/detail/generic/memory.h", + "cuda/include/thrust/system/detail/generic/memory.inl", + "cuda/include/thrust/system/detail/generic/merge.h", + "cuda/include/thrust/system/detail/generic/merge.inl", + "cuda/include/thrust/system/detail/generic/mismatch.h", + "cuda/include/thrust/system/detail/generic/mismatch.inl", + "cuda/include/thrust/system/detail/generic/partition.h", + "cuda/include/thrust/system/detail/generic/partition.inl", + "cuda/include/thrust/system/detail/generic/reduce.h", + "cuda/include/thrust/system/detail/generic/reduce.inl", + "cuda/include/thrust/system/detail/generic/reduce_by_key.h", + "cuda/include/thrust/system/detail/generic/reduce_by_key.inl", + "cuda/include/thrust/system/detail/generic/remove.h", + "cuda/include/thrust/system/detail/generic/remove.inl", + "cuda/include/thrust/system/detail/generic/replace.h", + "cuda/include/thrust/system/detail/generic/replace.inl", + "cuda/include/thrust/system/detail/generic/reverse.h", + "cuda/include/thrust/system/detail/generic/reverse.inl", + "cuda/include/thrust/system/detail/generic/scalar/binary_search.h", + "cuda/include/thrust/system/detail/generic/scalar/binary_search.inl", + "cuda/include/thrust/system/detail/generic/scan.h", + "cuda/include/thrust/system/detail/generic/scan.inl", + "cuda/include/thrust/system/detail/generic/scan_by_key.h", + "cuda/include/thrust/system/detail/generic/scan_by_key.inl", + "cuda/include/thrust/system/detail/generic/scatter.h", + "cuda/include/thrust/system/detail/generic/scatter.inl", + "cuda/include/thrust/system/detail/generic/select_system.h", + "cuda/include/thrust/system/detail/generic/sequence.h", + "cuda/include/thrust/system/detail/generic/sequence.inl", + "cuda/include/thrust/system/detail/generic/set_operations.h", + "cuda/include/thrust/system/detail/generic/set_operations.inl", + "cuda/include/thrust/system/detail/generic/sort.h", + "cuda/include/thrust/system/detail/generic/sort.inl", + "cuda/include/thrust/system/detail/generic/swap_ranges.h", + "cuda/include/thrust/system/detail/generic/swap_ranges.inl", + "cuda/include/thrust/system/detail/generic/tabulate.h", + "cuda/include/thrust/system/detail/generic/tabulate.inl", + "cuda/include/thrust/system/detail/generic/tag.h", + "cuda/include/thrust/system/detail/generic/temporary_buffer.h", + "cuda/include/thrust/system/detail/generic/temporary_buffer.inl", + "cuda/include/thrust/system/detail/generic/transform.h", + "cuda/include/thrust/system/detail/generic/transform.inl", + "cuda/include/thrust/system/detail/generic/transform_reduce.h", + "cuda/include/thrust/system/detail/generic/transform_reduce.inl", + "cuda/include/thrust/system/detail/generic/transform_scan.h", + "cuda/include/thrust/system/detail/generic/transform_scan.inl", + "cuda/include/thrust/system/detail/generic/type_traits.h", + "cuda/include/thrust/system/detail/generic/uninitialized_copy.h", + "cuda/include/thrust/system/detail/generic/uninitialized_copy.inl", + "cuda/include/thrust/system/detail/generic/uninitialized_fill.h", + "cuda/include/thrust/system/detail/generic/uninitialized_fill.inl", + "cuda/include/thrust/system/detail/generic/unique.h", + "cuda/include/thrust/system/detail/generic/unique.inl", + "cuda/include/thrust/system/detail/generic/unique_by_key.h", + "cuda/include/thrust/system/detail/generic/unique_by_key.inl", + "cuda/include/thrust/system/detail/internal/decompose.h", + "cuda/include/thrust/system/detail/sequential/adjacent_difference.h", + "cuda/include/thrust/system/detail/sequential/assign_value.h", + "cuda/include/thrust/system/detail/sequential/binary_search.h", + "cuda/include/thrust/system/detail/sequential/copy.h", + "cuda/include/thrust/system/detail/sequential/copy.inl", + "cuda/include/thrust/system/detail/sequential/copy_backward.h", + "cuda/include/thrust/system/detail/sequential/copy_if.h", + "cuda/include/thrust/system/detail/sequential/count.h", + "cuda/include/thrust/system/detail/sequential/equal.h", + "cuda/include/thrust/system/detail/sequential/execution_policy.h", + "cuda/include/thrust/system/detail/sequential/extrema.h", + "cuda/include/thrust/system/detail/sequential/fill.h", + "cuda/include/thrust/system/detail/sequential/find.h", + "cuda/include/thrust/system/detail/sequential/for_each.h", + "cuda/include/thrust/system/detail/sequential/gather.h", + "cuda/include/thrust/system/detail/sequential/general_copy.h", + "cuda/include/thrust/system/detail/sequential/generate.h", + "cuda/include/thrust/system/detail/sequential/get_value.h", + "cuda/include/thrust/system/detail/sequential/inner_product.h", + "cuda/include/thrust/system/detail/sequential/insertion_sort.h", + "cuda/include/thrust/system/detail/sequential/iter_swap.h", + "cuda/include/thrust/system/detail/sequential/logical.h", + "cuda/include/thrust/system/detail/sequential/malloc_and_free.h", + "cuda/include/thrust/system/detail/sequential/merge.h", + "cuda/include/thrust/system/detail/sequential/merge.inl", + "cuda/include/thrust/system/detail/sequential/mismatch.h", + "cuda/include/thrust/system/detail/sequential/partition.h", + "cuda/include/thrust/system/detail/sequential/reduce.h", + "cuda/include/thrust/system/detail/sequential/reduce_by_key.h", + "cuda/include/thrust/system/detail/sequential/remove.h", + "cuda/include/thrust/system/detail/sequential/replace.h", + "cuda/include/thrust/system/detail/sequential/reverse.h", + "cuda/include/thrust/system/detail/sequential/scan.h", + "cuda/include/thrust/system/detail/sequential/scan_by_key.h", + "cuda/include/thrust/system/detail/sequential/scatter.h", + "cuda/include/thrust/system/detail/sequential/sequence.h", + "cuda/include/thrust/system/detail/sequential/set_operations.h", + "cuda/include/thrust/system/detail/sequential/sort.h", + "cuda/include/thrust/system/detail/sequential/sort.inl", + "cuda/include/thrust/system/detail/sequential/stable_merge_sort.h", + "cuda/include/thrust/system/detail/sequential/stable_merge_sort.inl", + "cuda/include/thrust/system/detail/sequential/stable_primitive_sort.h", + "cuda/include/thrust/system/detail/sequential/stable_primitive_sort.inl", + "cuda/include/thrust/system/detail/sequential/stable_radix_sort.h", + "cuda/include/thrust/system/detail/sequential/stable_radix_sort.inl", + "cuda/include/thrust/system/detail/sequential/swap_ranges.h", + "cuda/include/thrust/system/detail/sequential/tabulate.h", + "cuda/include/thrust/system/detail/sequential/temporary_buffer.h", + "cuda/include/thrust/system/detail/sequential/transform.h", + "cuda/include/thrust/system/detail/sequential/transform_reduce.h", + "cuda/include/thrust/system/detail/sequential/transform_scan.h", + "cuda/include/thrust/system/detail/sequential/trivial_copy.h", + "cuda/include/thrust/system/detail/sequential/uninitialized_copy.h", + "cuda/include/thrust/system/detail/sequential/uninitialized_fill.h", + "cuda/include/thrust/system/detail/sequential/unique.h", + "cuda/include/thrust/system/detail/sequential/unique_by_key.h", + "cuda/include/thrust/system/detail/system_error.inl", + "cuda/include/thrust/system/error_code.h", + "cuda/include/thrust/system/omp/detail/adjacent_difference.h", + "cuda/include/thrust/system/omp/detail/assign_value.h", + "cuda/include/thrust/system/omp/detail/binary_search.h", + "cuda/include/thrust/system/omp/detail/copy.h", + "cuda/include/thrust/system/omp/detail/copy.inl", + "cuda/include/thrust/system/omp/detail/copy_if.h", + "cuda/include/thrust/system/omp/detail/copy_if.inl", + "cuda/include/thrust/system/omp/detail/count.h", + "cuda/include/thrust/system/omp/detail/default_decomposition.h", + "cuda/include/thrust/system/omp/detail/default_decomposition.inl", + "cuda/include/thrust/system/omp/detail/equal.h", + "cuda/include/thrust/system/omp/detail/execution_policy.h", + "cuda/include/thrust/system/omp/detail/extrema.h", + "cuda/include/thrust/system/omp/detail/fill.h", + "cuda/include/thrust/system/omp/detail/find.h", + "cuda/include/thrust/system/omp/detail/for_each.h", + "cuda/include/thrust/system/omp/detail/for_each.inl", + "cuda/include/thrust/system/omp/detail/gather.h", + "cuda/include/thrust/system/omp/detail/generate.h", + "cuda/include/thrust/system/omp/detail/get_value.h", + "cuda/include/thrust/system/omp/detail/inner_product.h", + "cuda/include/thrust/system/omp/detail/iter_swap.h", + "cuda/include/thrust/system/omp/detail/logical.h", + "cuda/include/thrust/system/omp/detail/malloc_and_free.h", + "cuda/include/thrust/system/omp/detail/memory.inl", + "cuda/include/thrust/system/omp/detail/merge.h", + "cuda/include/thrust/system/omp/detail/mismatch.h", + "cuda/include/thrust/system/omp/detail/par.h", + "cuda/include/thrust/system/omp/detail/partition.h", + "cuda/include/thrust/system/omp/detail/partition.inl", + "cuda/include/thrust/system/omp/detail/reduce.h", + "cuda/include/thrust/system/omp/detail/reduce.inl", + "cuda/include/thrust/system/omp/detail/reduce_by_key.h", + "cuda/include/thrust/system/omp/detail/reduce_by_key.inl", + "cuda/include/thrust/system/omp/detail/reduce_intervals.h", + "cuda/include/thrust/system/omp/detail/reduce_intervals.inl", + "cuda/include/thrust/system/omp/detail/remove.h", + "cuda/include/thrust/system/omp/detail/remove.inl", + "cuda/include/thrust/system/omp/detail/replace.h", + "cuda/include/thrust/system/omp/detail/reverse.h", + "cuda/include/thrust/system/omp/detail/scan.h", + "cuda/include/thrust/system/omp/detail/scan_by_key.h", + "cuda/include/thrust/system/omp/detail/scatter.h", + "cuda/include/thrust/system/omp/detail/sequence.h", + "cuda/include/thrust/system/omp/detail/set_operations.h", + "cuda/include/thrust/system/omp/detail/sort.h", + "cuda/include/thrust/system/omp/detail/sort.inl", + "cuda/include/thrust/system/omp/detail/swap_ranges.h", + "cuda/include/thrust/system/omp/detail/tabulate.h", + "cuda/include/thrust/system/omp/detail/temporary_buffer.h", + "cuda/include/thrust/system/omp/detail/transform.h", + "cuda/include/thrust/system/omp/detail/transform_reduce.h", + "cuda/include/thrust/system/omp/detail/transform_scan.h", + "cuda/include/thrust/system/omp/detail/uninitialized_copy.h", + "cuda/include/thrust/system/omp/detail/uninitialized_fill.h", + "cuda/include/thrust/system/omp/detail/unique.h", + "cuda/include/thrust/system/omp/detail/unique.inl", + "cuda/include/thrust/system/omp/detail/unique_by_key.h", + "cuda/include/thrust/system/omp/detail/unique_by_key.inl", + "cuda/include/thrust/system/omp/detail/vector.inl", + "cuda/include/thrust/system/omp/execution_policy.h", + "cuda/include/thrust/system/omp/memory.h", + "cuda/include/thrust/system/omp/vector.h", + "cuda/include/thrust/system/system_error.h", + "cuda/include/thrust/system/tbb/detail/adjacent_difference.h", + "cuda/include/thrust/system/tbb/detail/assign_value.h", + "cuda/include/thrust/system/tbb/detail/binary_search.h", + "cuda/include/thrust/system/tbb/detail/copy.h", + "cuda/include/thrust/system/tbb/detail/copy.inl", + "cuda/include/thrust/system/tbb/detail/copy_if.h", + "cuda/include/thrust/system/tbb/detail/copy_if.inl", + "cuda/include/thrust/system/tbb/detail/count.h", + "cuda/include/thrust/system/tbb/detail/equal.h", + "cuda/include/thrust/system/tbb/detail/execution_policy.h", + "cuda/include/thrust/system/tbb/detail/extrema.h", + "cuda/include/thrust/system/tbb/detail/fill.h", + "cuda/include/thrust/system/tbb/detail/find.h", + "cuda/include/thrust/system/tbb/detail/for_each.h", + "cuda/include/thrust/system/tbb/detail/for_each.inl", + "cuda/include/thrust/system/tbb/detail/gather.h", + "cuda/include/thrust/system/tbb/detail/generate.h", + "cuda/include/thrust/system/tbb/detail/get_value.h", + "cuda/include/thrust/system/tbb/detail/inner_product.h", + "cuda/include/thrust/system/tbb/detail/iter_swap.h", + "cuda/include/thrust/system/tbb/detail/logical.h", + "cuda/include/thrust/system/tbb/detail/malloc_and_free.h", + "cuda/include/thrust/system/tbb/detail/memory.inl", + "cuda/include/thrust/system/tbb/detail/merge.h", + "cuda/include/thrust/system/tbb/detail/merge.inl", + "cuda/include/thrust/system/tbb/detail/mismatch.h", + "cuda/include/thrust/system/tbb/detail/par.h", + "cuda/include/thrust/system/tbb/detail/partition.h", + "cuda/include/thrust/system/tbb/detail/partition.inl", + "cuda/include/thrust/system/tbb/detail/reduce.h", + "cuda/include/thrust/system/tbb/detail/reduce.inl", + "cuda/include/thrust/system/tbb/detail/reduce_by_key.h", + "cuda/include/thrust/system/tbb/detail/reduce_by_key.inl", + "cuda/include/thrust/system/tbb/detail/reduce_intervals.h", + "cuda/include/thrust/system/tbb/detail/remove.h", + "cuda/include/thrust/system/tbb/detail/remove.inl", + "cuda/include/thrust/system/tbb/detail/replace.h", + "cuda/include/thrust/system/tbb/detail/reverse.h", + "cuda/include/thrust/system/tbb/detail/scan.h", + "cuda/include/thrust/system/tbb/detail/scan.inl", + "cuda/include/thrust/system/tbb/detail/scan_by_key.h", + "cuda/include/thrust/system/tbb/detail/scatter.h", + "cuda/include/thrust/system/tbb/detail/sequence.h", + "cuda/include/thrust/system/tbb/detail/set_operations.h", + "cuda/include/thrust/system/tbb/detail/sort.h", + "cuda/include/thrust/system/tbb/detail/sort.inl", + "cuda/include/thrust/system/tbb/detail/swap_ranges.h", + "cuda/include/thrust/system/tbb/detail/tabulate.h", + "cuda/include/thrust/system/tbb/detail/temporary_buffer.h", + "cuda/include/thrust/system/tbb/detail/transform.h", + "cuda/include/thrust/system/tbb/detail/transform_reduce.h", + "cuda/include/thrust/system/tbb/detail/transform_scan.h", + "cuda/include/thrust/system/tbb/detail/uninitialized_copy.h", + "cuda/include/thrust/system/tbb/detail/uninitialized_fill.h", + "cuda/include/thrust/system/tbb/detail/unique.h", + "cuda/include/thrust/system/tbb/detail/unique.inl", + "cuda/include/thrust/system/tbb/detail/unique_by_key.h", + "cuda/include/thrust/system/tbb/detail/unique_by_key.inl", + "cuda/include/thrust/system/tbb/detail/vector.inl", + "cuda/include/thrust/system/tbb/execution_policy.h", + "cuda/include/thrust/system/tbb/memory.h", + "cuda/include/thrust/system/tbb/vector.h", + "cuda/include/thrust/system_error.h", + "cuda/include/thrust/tabulate.h", + "cuda/include/thrust/transform.h", + "cuda/include/thrust/transform_reduce.h", + "cuda/include/thrust/transform_scan.h", + "cuda/include/thrust/tuple.h", + "cuda/include/thrust/uninitialized_copy.h", + "cuda/include/thrust/uninitialized_fill.h", + "cuda/include/thrust/unique.h", + "cuda/include/thrust/version.h", + "cuda/include/vector_functions.h", + "cuda/include/vector_functions.hpp", + "cuda/include/vector_types.h", + ], + cmd = """ +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/local/cuda-10.0/include/CL/cl.h" "$(@D)/cuda/include/CL/cl.h" && cp -f "/usr/local/cuda-10.0/include/CL/cl.hpp" "$(@D)/cuda/include/CL/cl.hpp" && cp -f "/usr/local/cuda-10.0/include/CL/cl_egl.h" "$(@D)/cuda/include/CL/cl_egl.h" && cp -f "/usr/local/cuda-10.0/include/CL/cl_ext.h" "$(@D)/cuda/include/CL/cl_ext.h" && cp -f "/usr/local/cuda-10.0/include/CL/cl_gl.h" "$(@D)/cuda/include/CL/cl_gl.h" && cp -f "/usr/local/cuda-10.0/include/CL/cl_gl_ext.h" "$(@D)/cuda/include/CL/cl_gl_ext.h" && cp -f "/usr/local/cuda-10.0/include/CL/cl_platform.h" "$(@D)/cuda/include/CL/cl_platform.h" && cp -f "/usr/local/cuda-10.0/include/CL/opencl.h" "$(@D)/cuda/include/CL/opencl.h" && cp -f "/usr/local/cuda-10.0/include/builtin_types.h" "$(@D)/cuda/include/builtin_types.h" && cp -f "/usr/local/cuda-10.0/include/channel_descriptor.h" "$(@D)/cuda/include/channel_descriptor.h" && cp -f "/usr/local/cuda-10.0/include/common_functions.h" "$(@D)/cuda/include/common_functions.h" && cp -f "/usr/local/cuda-10.0/include/cooperative_groups.h" "$(@D)/cuda/include/cooperative_groups.h" && cp -f "/usr/local/cuda-10.0/include/cooperative_groups_helpers.h" "$(@D)/cuda/include/cooperative_groups_helpers.h" && cp -f "/usr/local/cuda-10.0/include/crt/common_functions.h" "$(@D)/cuda/include/crt/common_functions.h" && cp -f "/usr/local/cuda-10.0/include/crt/device_double_functions.h" "$(@D)/cuda/include/crt/device_double_functions.h" && cp -f "/usr/local/cuda-10.0/include/crt/device_double_functions.hpp" "$(@D)/cuda/include/crt/device_double_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/crt/device_functions.h" "$(@D)/cuda/include/crt/device_functions.h" && cp -f "/usr/local/cuda-10.0/include/crt/device_functions.hpp" "$(@D)/cuda/include/crt/device_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/crt/func_macro.h" "$(@D)/cuda/include/crt/func_macro.h" && cp -f "/usr/local/cuda-10.0/include/crt/host_config.h" "$(@D)/cuda/include/crt/host_config.h" && cp -f "/usr/local/cuda-10.0/include/crt/host_defines.h" "$(@D)/cuda/include/crt/host_defines.h" && cp -f "/usr/local/cuda-10.0/include/crt/host_runtime.h" "$(@D)/cuda/include/crt/host_runtime.h" && cp -f "/usr/local/cuda-10.0/include/crt/math_functions.h" "$(@D)/cuda/include/crt/math_functions.h" && cp -f "/usr/local/cuda-10.0/include/crt/math_functions.hpp" "$(@D)/cuda/include/crt/math_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/crt/mma.h" "$(@D)/cuda/include/crt/mma.h" && cp -f "/usr/local/cuda-10.0/include/crt/mma.hpp" "$(@D)/cuda/include/crt/mma.hpp" && cp -f "/usr/local/cuda-10.0/include/crt/nvfunctional" "$(@D)/cuda/include/crt/nvfunctional" && cp -f "/usr/local/cuda-10.0/include/crt/sm_70_rt.h" "$(@D)/cuda/include/crt/sm_70_rt.h" && cp -f "/usr/local/cuda-10.0/include/crt/sm_70_rt.hpp" "$(@D)/cuda/include/crt/sm_70_rt.hpp" && cp -f "/usr/local/cuda-10.0/include/crt/storage_class.h" "$(@D)/cuda/include/crt/storage_class.h" && cp -f "/usr/local/cuda-10.0/include/cuComplex.h" "$(@D)/cuda/include/cuComplex.h" && cp -f "/usr/local/cuda-10.0/include/cublas.h" "$(@D)/cuda/include/cublas.h" && cp -f "/usr/local/cuda-10.0/include/cublasXt.h" "$(@D)/cuda/include/cublasXt.h" && cp -f "/usr/local/cuda-10.0/include/cublas_api.h" "$(@D)/cuda/include/cublas_api.h" && cp -f "/usr/local/cuda-10.0/include/cublas_v2.h" "$(@D)/cuda/include/cublas_v2.h" && cp -f "/usr/local/cuda-10.0/include/cuda.h" "$(@D)/cuda/include/cuda.h" && cp -f "/usr/local/cuda-10.0/include/cudaEGL.h" "$(@D)/cuda/include/cudaEGL.h" && cp -f "/usr/local/cuda-10.0/include/cudaGL.h" "$(@D)/cuda/include/cudaGL.h" && cp -f "/usr/local/cuda-10.0/include/cudaProfiler.h" "$(@D)/cuda/include/cudaProfiler.h" && cp -f "/usr/local/cuda-10.0/include/cudaVDPAU.h" "$(@D)/cuda/include/cudaVDPAU.h" && cp -f "/usr/local/cuda-10.0/include/cuda_device_runtime_api.h" "$(@D)/cuda/include/cuda_device_runtime_api.h" && cp -f "/usr/local/cuda-10.0/include/cuda_egl_interop.h" "$(@D)/cuda/include/cuda_egl_interop.h" && cp -f "/usr/local/cuda-10.0/include/cuda_fp16.h" "$(@D)/cuda/include/cuda_fp16.h" && cp -f "/usr/local/cuda-10.0/include/cuda_fp16.hpp" "$(@D)/cuda/include/cuda_fp16.hpp" && cp -f "/usr/local/cuda-10.0/include/cuda_gl_interop.h" "$(@D)/cuda/include/cuda_gl_interop.h" && cp -f "/usr/local/cuda-10.0/include/cuda_occupancy.h" "$(@D)/cuda/include/cuda_occupancy.h" && cp -f "/usr/local/cuda-10.0/include/cuda_profiler_api.h" "$(@D)/cuda/include/cuda_profiler_api.h" && cp -f "/usr/local/cuda-10.0/include/cuda_runtime.h" "$(@D)/cuda/include/cuda_runtime.h" && cp -f "/usr/local/cuda-10.0/include/cuda_runtime_api.h" "$(@D)/cuda/include/cuda_runtime_api.h" && cp -f "/usr/local/cuda-10.0/include/cuda_surface_types.h" "$(@D)/cuda/include/cuda_surface_types.h" && cp -f "/usr/local/cuda-10.0/include/cuda_texture_types.h" "$(@D)/cuda/include/cuda_texture_types.h" && cp -f "/usr/local/cuda-10.0/include/cuda_vdpau_interop.h" "$(@D)/cuda/include/cuda_vdpau_interop.h" && cp -f "/usr/local/cuda-10.0/include/cudalibxt.h" "$(@D)/cuda/include/cudalibxt.h" && cp -f "/usr/local/cuda-10.0/include/cudart_platform.h" "$(@D)/cuda/include/cudart_platform.h" && cp -f "/usr/local/cuda-10.0/include/cufft.h" "$(@D)/cuda/include/cufft.h" && cp -f "/usr/local/cuda-10.0/include/cufftXt.h" "$(@D)/cuda/include/cufftXt.h" && cp -f "/usr/local/cuda-10.0/include/cufftw.h" "$(@D)/cuda/include/cufftw.h" && cp -f "/usr/local/cuda-10.0/include/curand.h" "$(@D)/cuda/include/curand.h" && cp -f "/usr/local/cuda-10.0/include/curand_discrete.h" "$(@D)/cuda/include/curand_discrete.h" && cp -f "/usr/local/cuda-10.0/include/curand_discrete2.h" "$(@D)/cuda/include/curand_discrete2.h" && cp -f "/usr/local/cuda-10.0/include/curand_globals.h" "$(@D)/cuda/include/curand_globals.h" && cp -f "/usr/local/cuda-10.0/include/curand_kernel.h" "$(@D)/cuda/include/curand_kernel.h" && cp -f "/usr/local/cuda-10.0/include/curand_lognormal.h" "$(@D)/cuda/include/curand_lognormal.h" && cp -f "/usr/local/cuda-10.0/include/curand_mrg32k3a.h" "$(@D)/cuda/include/curand_mrg32k3a.h" && cp -f "/usr/local/cuda-10.0/include/curand_mtgp32.h" "$(@D)/cuda/include/curand_mtgp32.h" && cp -f "/usr/local/cuda-10.0/include/curand_mtgp32_host.h" "$(@D)/cuda/include/curand_mtgp32_host.h" && cp -f "/usr/local/cuda-10.0/include/curand_mtgp32_kernel.h" "$(@D)/cuda/include/curand_mtgp32_kernel.h" && cp -f "/usr/local/cuda-10.0/include/curand_mtgp32dc_p_11213.h" "$(@D)/cuda/include/curand_mtgp32dc_p_11213.h" && cp -f "/usr/local/cuda-10.0/include/curand_normal.h" "$(@D)/cuda/include/curand_normal.h" && cp -f "/usr/local/cuda-10.0/include/curand_normal_static.h" "$(@D)/cuda/include/curand_normal_static.h" && cp -f "/usr/local/cuda-10.0/include/curand_philox4x32_x.h" "$(@D)/cuda/include/curand_philox4x32_x.h" && cp -f "/usr/local/cuda-10.0/include/curand_poisson.h" "$(@D)/cuda/include/curand_poisson.h" && cp -f "/usr/local/cuda-10.0/include/curand_precalc.h" "$(@D)/cuda/include/curand_precalc.h" && cp -f "/usr/local/cuda-10.0/include/curand_uniform.h" "$(@D)/cuda/include/curand_uniform.h" && cp -f "/usr/local/cuda-10.0/include/cusolverDn.h" "$(@D)/cuda/include/cusolverDn.h" && cp -f "/usr/local/cuda-10.0/include/cusolverRf.h" "$(@D)/cuda/include/cusolverRf.h" && cp -f "/usr/local/cuda-10.0/include/cusolverSp.h" "$(@D)/cuda/include/cusolverSp.h" && cp -f "/usr/local/cuda-10.0/include/cusolverSp_LOWLEVEL_PREVIEW.h" "$(@D)/cuda/include/cusolverSp_LOWLEVEL_PREVIEW.h" && cp -f "/usr/local/cuda-10.0/include/cusolver_common.h" "$(@D)/cuda/include/cusolver_common.h" && cp -f "/usr/local/cuda-10.0/include/cusparse.h" "$(@D)/cuda/include/cusparse.h" && cp -f "/usr/local/cuda-10.0/include/cusparse_v2.h" "$(@D)/cuda/include/cusparse_v2.h" && cp -f "/usr/local/cuda-10.0/include/device_atomic_functions.h" "$(@D)/cuda/include/device_atomic_functions.h" && cp -f "/usr/local/cuda-10.0/include/device_atomic_functions.hpp" "$(@D)/cuda/include/device_atomic_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/device_double_functions.h" "$(@D)/cuda/include/device_double_functions.h" && cp -f "/usr/local/cuda-10.0/include/device_functions.h" "$(@D)/cuda/include/device_functions.h" && cp -f "/usr/local/cuda-10.0/include/device_launch_parameters.h" "$(@D)/cuda/include/device_launch_parameters.h" && cp -f "/usr/local/cuda-10.0/include/device_types.h" "$(@D)/cuda/include/device_types.h" && cp -f "/usr/local/cuda-10.0/include/driver_functions.h" "$(@D)/cuda/include/driver_functions.h" && cp -f "/usr/local/cuda-10.0/include/driver_types.h" "$(@D)/cuda/include/driver_types.h" && cp -f "/usr/local/cuda-10.0/include/fatBinaryCtl.h" "$(@D)/cuda/include/fatBinaryCtl.h" && cp -f "/usr/local/cuda-10.0/include/fatbinary.h" "$(@D)/cuda/include/fatbinary.h" && cp -f "/usr/local/cuda-10.0/include/host_config.h" "$(@D)/cuda/include/host_config.h" && cp -f "/usr/local/cuda-10.0/include/host_defines.h" "$(@D)/cuda/include/host_defines.h" && cp -f "/usr/local/cuda-10.0/include/library_types.h" "$(@D)/cuda/include/library_types.h" && cp -f "/usr/local/cuda-10.0/include/math_constants.h" "$(@D)/cuda/include/math_constants.h" && cp -f "/usr/local/cuda-10.0/include/math_functions.h" "$(@D)/cuda/include/math_functions.h" && cp -f "/usr/local/cuda-10.0/include/mma.h" "$(@D)/cuda/include/mma.h" && cp -f "/usr/local/cuda-10.0/include/npp.h" "$(@D)/cuda/include/npp.h" && cp -f "/usr/local/cuda-10.0/include/nppcore.h" "$(@D)/cuda/include/nppcore.h" && cp -f "/usr/local/cuda-10.0/include/nppdefs.h" "$(@D)/cuda/include/nppdefs.h" && cp -f "/usr/local/cuda-10.0/include/nppi.h" "$(@D)/cuda/include/nppi.h" && cp -f "/usr/local/cuda-10.0/include/nppi_arithmetic_and_logical_operations.h" "$(@D)/cuda/include/nppi_arithmetic_and_logical_operations.h" && cp -f "/usr/local/cuda-10.0/include/nppi_color_conversion.h" "$(@D)/cuda/include/nppi_color_conversion.h" && cp -f "/usr/local/cuda-10.0/include/nppi_compression_functions.h" "$(@D)/cuda/include/nppi_compression_functions.h" && cp -f "/usr/local/cuda-10.0/include/nppi_computer_vision.h" "$(@D)/cuda/include/nppi_computer_vision.h" && cp -f "/usr/local/cuda-10.0/include/nppi_data_exchange_and_initialization.h" "$(@D)/cuda/include/nppi_data_exchange_and_initialization.h" && cp -f "/usr/local/cuda-10.0/include/nppi_filtering_functions.h" "$(@D)/cuda/include/nppi_filtering_functions.h" && cp -f "/usr/local/cuda-10.0/include/nppi_geometry_transforms.h" "$(@D)/cuda/include/nppi_geometry_transforms.h" && cp -f "/usr/local/cuda-10.0/include/nppi_linear_transforms.h" "$(@D)/cuda/include/nppi_linear_transforms.h" && cp -f "/usr/local/cuda-10.0/include/nppi_morphological_operations.h" "$(@D)/cuda/include/nppi_morphological_operations.h" && cp -f "/usr/local/cuda-10.0/include/nppi_statistics_functions.h" "$(@D)/cuda/include/nppi_statistics_functions.h" && cp -f "/usr/local/cuda-10.0/include/nppi_support_functions.h" "$(@D)/cuda/include/nppi_support_functions.h" && cp -f "/usr/local/cuda-10.0/include/nppi_threshold_and_compare_operations.h" "$(@D)/cuda/include/nppi_threshold_and_compare_operations.h" && cp -f "/usr/local/cuda-10.0/include/npps.h" "$(@D)/cuda/include/npps.h" && cp -f "/usr/local/cuda-10.0/include/npps_arithmetic_and_logical_operations.h" "$(@D)/cuda/include/npps_arithmetic_and_logical_operations.h" && cp -f "/usr/local/cuda-10.0/include/npps_conversion_functions.h" "$(@D)/cuda/include/npps_conversion_functions.h" && cp -f "/usr/local/cuda-10.0/include/npps_filtering_functions.h" "$(@D)/cuda/include/npps_filtering_functions.h" && cp -f "/usr/local/cuda-10.0/include/npps_initialization.h" "$(@D)/cuda/include/npps_initialization.h" && cp -f "/usr/local/cuda-10.0/include/npps_statistics_functions.h" "$(@D)/cuda/include/npps_statistics_functions.h" && cp -f "/usr/local/cuda-10.0/include/npps_support_functions.h" "$(@D)/cuda/include/npps_support_functions.h" && cp -f "/usr/local/cuda-10.0/include/nppversion.h" "$(@D)/cuda/include/nppversion.h" && cp -f "/usr/local/cuda-10.0/include/nvToolsExt.h" "$(@D)/cuda/include/nvToolsExt.h" && cp -f "/usr/local/cuda-10.0/include/nvToolsExtCuda.h" "$(@D)/cuda/include/nvToolsExtCuda.h" && cp -f "/usr/local/cuda-10.0/include/nvToolsExtCudaRt.h" "$(@D)/cuda/include/nvToolsExtCudaRt.h" && cp -f "/usr/local/cuda-10.0/include/nvToolsExtMeta.h" "$(@D)/cuda/include/nvToolsExtMeta.h" && cp -f "/usr/local/cuda-10.0/include/nvToolsExtSync.h" "$(@D)/cuda/include/nvToolsExtSync.h" && cp -f "/usr/local/cuda-10.0/include/nvblas.h" "$(@D)/cuda/include/nvblas.h" && cp -f "/usr/local/cuda-10.0/include/nvfunctional" "$(@D)/cuda/include/nvfunctional" && cp -f "/usr/local/cuda-10.0/include/nvgraph.h" "$(@D)/cuda/include/nvgraph.h" && cp -f "/usr/local/cuda-10.0/include/nvjpeg.h" "$(@D)/cuda/include/nvjpeg.h" && cp -f "/usr/local/cuda-10.0/include/nvml.h" "$(@D)/cuda/include/nvml.h" && cp -f "/usr/local/cuda-10.0/include/nvrtc.h" "$(@D)/cuda/include/nvrtc.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvToolsExt.h" "$(@D)/cuda/include/nvtx3/nvToolsExt.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvToolsExtCuda.h" "$(@D)/cuda/include/nvtx3/nvToolsExtCuda.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvToolsExtCudaRt.h" "$(@D)/cuda/include/nvtx3/nvToolsExtCudaRt.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvToolsExtOpenCL.h" "$(@D)/cuda/include/nvtx3/nvToolsExtOpenCL.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvToolsExtSync.h" "$(@D)/cuda/include/nvtx3/nvToolsExtSync.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxImpl.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxImpl.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxImplCore.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxImplCore.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxImplCudaRt_v3.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxImplCudaRt_v3.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxImplCuda_v3.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxImplCuda_v3.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxImplOpenCL_v3.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxImplOpenCL_v3.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxImplSync_v3.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxImplSync_v3.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxInit.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxInit.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxInitDecls.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxInitDecls.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxInitDefs.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxInitDefs.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxLinkOnce.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxLinkOnce.h" && cp -f "/usr/local/cuda-10.0/include/nvtx3/nvtxDetail/nvtxTypes.h" "$(@D)/cuda/include/nvtx3/nvtxDetail/nvtxTypes.h" && cp -f "/usr/local/cuda-10.0/include/sm_20_atomic_functions.h" "$(@D)/cuda/include/sm_20_atomic_functions.h" && cp -f "/usr/local/cuda-10.0/include/sm_20_atomic_functions.hpp" "$(@D)/cuda/include/sm_20_atomic_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/sm_20_intrinsics.h" "$(@D)/cuda/include/sm_20_intrinsics.h" && cp -f "/usr/local/cuda-10.0/include/sm_20_intrinsics.hpp" "$(@D)/cuda/include/sm_20_intrinsics.hpp" && cp -f "/usr/local/cuda-10.0/include/sm_30_intrinsics.h" "$(@D)/cuda/include/sm_30_intrinsics.h" && cp -f "/usr/local/cuda-10.0/include/sm_30_intrinsics.hpp" "$(@D)/cuda/include/sm_30_intrinsics.hpp" && cp -f "/usr/local/cuda-10.0/include/sm_32_atomic_functions.h" "$(@D)/cuda/include/sm_32_atomic_functions.h" && cp -f "/usr/local/cuda-10.0/include/sm_32_atomic_functions.hpp" "$(@D)/cuda/include/sm_32_atomic_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/sm_32_intrinsics.h" "$(@D)/cuda/include/sm_32_intrinsics.h" && cp -f "/usr/local/cuda-10.0/include/sm_32_intrinsics.hpp" "$(@D)/cuda/include/sm_32_intrinsics.hpp" && cp -f "/usr/local/cuda-10.0/include/sm_35_atomic_functions.h" "$(@D)/cuda/include/sm_35_atomic_functions.h" && cp -f "/usr/local/cuda-10.0/include/sm_35_intrinsics.h" "$(@D)/cuda/include/sm_35_intrinsics.h" && cp -f "/usr/local/cuda-10.0/include/sm_60_atomic_functions.h" "$(@D)/cuda/include/sm_60_atomic_functions.h" && cp -f "/usr/local/cuda-10.0/include/sm_60_atomic_functions.hpp" "$(@D)/cuda/include/sm_60_atomic_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/sm_61_intrinsics.h" "$(@D)/cuda/include/sm_61_intrinsics.h" && cp -f "/usr/local/cuda-10.0/include/sm_61_intrinsics.hpp" "$(@D)/cuda/include/sm_61_intrinsics.hpp" && cp -f "/usr/local/cuda-10.0/include/sobol_direction_vectors.h" "$(@D)/cuda/include/sobol_direction_vectors.h" && cp -f "/usr/local/cuda-10.0/include/surface_functions.h" "$(@D)/cuda/include/surface_functions.h" && cp -f "/usr/local/cuda-10.0/include/surface_functions.hpp" "$(@D)/cuda/include/surface_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/surface_indirect_functions.h" "$(@D)/cuda/include/surface_indirect_functions.h" && cp -f "/usr/local/cuda-10.0/include/surface_indirect_functions.hpp" "$(@D)/cuda/include/surface_indirect_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/surface_types.h" "$(@D)/cuda/include/surface_types.h" && cp -f "/usr/local/cuda-10.0/include/texture_fetch_functions.h" "$(@D)/cuda/include/texture_fetch_functions.h" && cp -f "/usr/local/cuda-10.0/include/texture_fetch_functions.hpp" "$(@D)/cuda/include/texture_fetch_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/texture_indirect_functions.h" "$(@D)/cuda/include/texture_indirect_functions.h" && cp -f "/usr/local/cuda-10.0/include/texture_indirect_functions.hpp" "$(@D)/cuda/include/texture_indirect_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/texture_types.h" "$(@D)/cuda/include/texture_types.h" && cp -f "/usr/local/cuda-10.0/include/thrust/adjacent_difference.h" "$(@D)/cuda/include/thrust/adjacent_difference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/advance.h" "$(@D)/cuda/include/thrust/advance.h" && cp -f "/usr/local/cuda-10.0/include/thrust/binary_search.h" "$(@D)/cuda/include/thrust/binary_search.h" && cp -f "/usr/local/cuda-10.0/include/thrust/complex.h" "$(@D)/cuda/include/thrust/complex.h" && cp -f "/usr/local/cuda-10.0/include/thrust/copy.h" "$(@D)/cuda/include/thrust/copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/count.h" "$(@D)/cuda/include/thrust/count.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/adjacent_difference.inl" "$(@D)/cuda/include/thrust/detail/adjacent_difference.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/advance.inl" "$(@D)/cuda/include/thrust/detail/advance.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/alignment.h" "$(@D)/cuda/include/thrust/detail/alignment.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/allocator_traits.h" "$(@D)/cuda/include/thrust/detail/allocator/allocator_traits.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/allocator_traits.inl" "$(@D)/cuda/include/thrust/detail/allocator/allocator_traits.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/copy_construct_range.h" "$(@D)/cuda/include/thrust/detail/allocator/copy_construct_range.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/copy_construct_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/copy_construct_range.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/default_construct_range.h" "$(@D)/cuda/include/thrust/detail/allocator/default_construct_range.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/default_construct_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/default_construct_range.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/destroy_range.h" "$(@D)/cuda/include/thrust/detail/allocator/destroy_range.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/destroy_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/destroy_range.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/fill_construct_range.h" "$(@D)/cuda/include/thrust/detail/allocator/fill_construct_range.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/fill_construct_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/fill_construct_range.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/malloc_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/malloc_allocator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/malloc_allocator.inl" "$(@D)/cuda/include/thrust/detail/allocator/malloc_allocator.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/no_throw_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/no_throw_allocator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/tagged_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/tagged_allocator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/tagged_allocator.inl" "$(@D)/cuda/include/thrust/detail/allocator/tagged_allocator.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/temporary_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/temporary_allocator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/allocator/temporary_allocator.inl" "$(@D)/cuda/include/thrust/detail/allocator/temporary_allocator.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/binary_search.inl" "$(@D)/cuda/include/thrust/detail/binary_search.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/arithmetic.h" "$(@D)/cuda/include/thrust/detail/complex/arithmetic.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/c99math.h" "$(@D)/cuda/include/thrust/detail/complex/c99math.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/catrig.h" "$(@D)/cuda/include/thrust/detail/complex/catrig.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/catrigf.h" "$(@D)/cuda/include/thrust/detail/complex/catrigf.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/ccosh.h" "$(@D)/cuda/include/thrust/detail/complex/ccosh.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/ccoshf.h" "$(@D)/cuda/include/thrust/detail/complex/ccoshf.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/cexp.h" "$(@D)/cuda/include/thrust/detail/complex/cexp.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/cexpf.h" "$(@D)/cuda/include/thrust/detail/complex/cexpf.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/clog.h" "$(@D)/cuda/include/thrust/detail/complex/clog.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/clogf.h" "$(@D)/cuda/include/thrust/detail/complex/clogf.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/complex.inl" "$(@D)/cuda/include/thrust/detail/complex/complex.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/cpow.h" "$(@D)/cuda/include/thrust/detail/complex/cpow.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/cproj.h" "$(@D)/cuda/include/thrust/detail/complex/cproj.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/csinh.h" "$(@D)/cuda/include/thrust/detail/complex/csinh.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/csinhf.h" "$(@D)/cuda/include/thrust/detail/complex/csinhf.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/csqrt.h" "$(@D)/cuda/include/thrust/detail/complex/csqrt.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/csqrtf.h" "$(@D)/cuda/include/thrust/detail/complex/csqrtf.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/ctanh.h" "$(@D)/cuda/include/thrust/detail/complex/ctanh.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/ctanhf.h" "$(@D)/cuda/include/thrust/detail/complex/ctanhf.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/math_private.h" "$(@D)/cuda/include/thrust/detail/complex/math_private.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/complex/stream.h" "$(@D)/cuda/include/thrust/detail/complex/stream.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config.h" "$(@D)/cuda/include/thrust/detail/config.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/compiler.h" "$(@D)/cuda/include/thrust/detail/config/compiler.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/compiler_fence.h" "$(@D)/cuda/include/thrust/detail/config/compiler_fence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/config.h" "$(@D)/cuda/include/thrust/detail/config/config.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/debug.h" "$(@D)/cuda/include/thrust/detail/config/debug.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/device_system.h" "$(@D)/cuda/include/thrust/detail/config/device_system.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/exec_check_disable.h" "$(@D)/cuda/include/thrust/detail/config/exec_check_disable.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/forceinline.h" "$(@D)/cuda/include/thrust/detail/config/forceinline.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/global_workarounds.h" "$(@D)/cuda/include/thrust/detail/config/global_workarounds.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/host_device.h" "$(@D)/cuda/include/thrust/detail/config/host_device.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/host_system.h" "$(@D)/cuda/include/thrust/detail/config/host_system.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/config/simple_defines.h" "$(@D)/cuda/include/thrust/detail/config/simple_defines.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/contiguous_storage.h" "$(@D)/cuda/include/thrust/detail/contiguous_storage.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/contiguous_storage.inl" "$(@D)/cuda/include/thrust/detail/contiguous_storage.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/copy.h" "$(@D)/cuda/include/thrust/detail/copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/copy.inl" "$(@D)/cuda/include/thrust/detail/copy.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/copy_if.h" "$(@D)/cuda/include/thrust/detail/copy_if.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/copy_if.inl" "$(@D)/cuda/include/thrust/detail/copy_if.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/count.inl" "$(@D)/cuda/include/thrust/detail/count.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/cstdint.h" "$(@D)/cuda/include/thrust/detail/cstdint.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/device_delete.inl" "$(@D)/cuda/include/thrust/detail/device_delete.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/device_free.inl" "$(@D)/cuda/include/thrust/detail/device_free.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/device_malloc.inl" "$(@D)/cuda/include/thrust/detail/device_malloc.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/device_new.inl" "$(@D)/cuda/include/thrust/detail/device_new.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/device_ptr.inl" "$(@D)/cuda/include/thrust/detail/device_ptr.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/device_reference.inl" "$(@D)/cuda/include/thrust/detail/device_reference.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/device_vector.inl" "$(@D)/cuda/include/thrust/detail/device_vector.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/dispatch/is_trivial_copy.h" "$(@D)/cuda/include/thrust/detail/dispatch/is_trivial_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/distance.inl" "$(@D)/cuda/include/thrust/detail/distance.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/equal.inl" "$(@D)/cuda/include/thrust/detail/equal.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/execute_with_allocator.h" "$(@D)/cuda/include/thrust/detail/execute_with_allocator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/execution_policy.h" "$(@D)/cuda/include/thrust/detail/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/extrema.inl" "$(@D)/cuda/include/thrust/detail/extrema.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/fill.inl" "$(@D)/cuda/include/thrust/detail/fill.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/find.inl" "$(@D)/cuda/include/thrust/detail/find.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/for_each.inl" "$(@D)/cuda/include/thrust/detail/for_each.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/function.h" "$(@D)/cuda/include/thrust/detail/function.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional.inl" "$(@D)/cuda/include/thrust/detail/functional.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/actor.h" "$(@D)/cuda/include/thrust/detail/functional/actor.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/actor.inl" "$(@D)/cuda/include/thrust/detail/functional/actor.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/argument.h" "$(@D)/cuda/include/thrust/detail/functional/argument.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/composite.h" "$(@D)/cuda/include/thrust/detail/functional/composite.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/operators/arithmetic_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/arithmetic_operators.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/operators/assignment_operator.h" "$(@D)/cuda/include/thrust/detail/functional/operators/assignment_operator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/operators/bitwise_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/bitwise_operators.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/operators/compound_assignment_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/compound_assignment_operators.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/operators/logical_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/logical_operators.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/operators/operator_adaptors.h" "$(@D)/cuda/include/thrust/detail/functional/operators/operator_adaptors.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/operators/relational_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/relational_operators.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/placeholder.h" "$(@D)/cuda/include/thrust/detail/functional/placeholder.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/functional/value.h" "$(@D)/cuda/include/thrust/detail/functional/value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/gather.inl" "$(@D)/cuda/include/thrust/detail/gather.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/generate.inl" "$(@D)/cuda/include/thrust/detail/generate.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/get_iterator_value.h" "$(@D)/cuda/include/thrust/detail/get_iterator_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/host_vector.inl" "$(@D)/cuda/include/thrust/detail/host_vector.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/inner_product.inl" "$(@D)/cuda/include/thrust/detail/inner_product.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/integer_math.h" "$(@D)/cuda/include/thrust/detail/integer_math.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/integer_traits.h" "$(@D)/cuda/include/thrust/detail/integer_traits.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/internal_functional.h" "$(@D)/cuda/include/thrust/detail/internal_functional.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/logical.inl" "$(@D)/cuda/include/thrust/detail/logical.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/merge.inl" "$(@D)/cuda/include/thrust/detail/merge.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/minmax.h" "$(@D)/cuda/include/thrust/detail/minmax.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/mismatch.inl" "$(@D)/cuda/include/thrust/detail/mismatch.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/mpl/math.h" "$(@D)/cuda/include/thrust/detail/mpl/math.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/numeric_traits.h" "$(@D)/cuda/include/thrust/detail/numeric_traits.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/overlapped_copy.h" "$(@D)/cuda/include/thrust/detail/overlapped_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/pair.inl" "$(@D)/cuda/include/thrust/detail/pair.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/partition.inl" "$(@D)/cuda/include/thrust/detail/partition.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/pointer.h" "$(@D)/cuda/include/thrust/detail/pointer.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/pointer.inl" "$(@D)/cuda/include/thrust/detail/pointer.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/preprocessor.h" "$(@D)/cuda/include/thrust/detail/preprocessor.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/range/head_flags.h" "$(@D)/cuda/include/thrust/detail/range/head_flags.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/range/tail_flags.h" "$(@D)/cuda/include/thrust/detail/range/tail_flags.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/raw_pointer_cast.h" "$(@D)/cuda/include/thrust/detail/raw_pointer_cast.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/raw_reference_cast.h" "$(@D)/cuda/include/thrust/detail/raw_reference_cast.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/reduce.inl" "$(@D)/cuda/include/thrust/detail/reduce.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/reference.h" "$(@D)/cuda/include/thrust/detail/reference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/reference.inl" "$(@D)/cuda/include/thrust/detail/reference.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/reference_forward_declaration.h" "$(@D)/cuda/include/thrust/detail/reference_forward_declaration.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/remove.inl" "$(@D)/cuda/include/thrust/detail/remove.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/replace.inl" "$(@D)/cuda/include/thrust/detail/replace.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/reverse.inl" "$(@D)/cuda/include/thrust/detail/reverse.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/scan.inl" "$(@D)/cuda/include/thrust/detail/scan.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/scatter.inl" "$(@D)/cuda/include/thrust/detail/scatter.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/seq.h" "$(@D)/cuda/include/thrust/detail/seq.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/sequence.inl" "$(@D)/cuda/include/thrust/detail/sequence.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/set_operations.inl" "$(@D)/cuda/include/thrust/detail/set_operations.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/sort.inl" "$(@D)/cuda/include/thrust/detail/sort.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/static_assert.h" "$(@D)/cuda/include/thrust/detail/static_assert.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/static_map.h" "$(@D)/cuda/include/thrust/detail/static_map.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/swap.h" "$(@D)/cuda/include/thrust/detail/swap.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/swap.inl" "$(@D)/cuda/include/thrust/detail/swap.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/swap_ranges.inl" "$(@D)/cuda/include/thrust/detail/swap_ranges.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/tabulate.inl" "$(@D)/cuda/include/thrust/detail/tabulate.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/temporary_array.h" "$(@D)/cuda/include/thrust/detail/temporary_array.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/temporary_array.inl" "$(@D)/cuda/include/thrust/detail/temporary_array.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/transform.inl" "$(@D)/cuda/include/thrust/detail/transform.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/transform_reduce.inl" "$(@D)/cuda/include/thrust/detail/transform_reduce.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/transform_scan.inl" "$(@D)/cuda/include/thrust/detail/transform_scan.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/trivial_sequence.h" "$(@D)/cuda/include/thrust/detail/trivial_sequence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/tuple.inl" "$(@D)/cuda/include/thrust/detail/tuple.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/tuple_meta_transform.h" "$(@D)/cuda/include/thrust/detail/tuple_meta_transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/tuple_transform.h" "$(@D)/cuda/include/thrust/detail/tuple_transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits.h" "$(@D)/cuda/include/thrust/detail/type_traits.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/algorithm/intermediate_type_from_function_and_iterators.h" "$(@D)/cuda/include/thrust/detail/type_traits/algorithm/intermediate_type_from_function_and_iterators.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/function_traits.h" "$(@D)/cuda/include/thrust/detail/type_traits/function_traits.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/has_member_function.h" "$(@D)/cuda/include/thrust/detail/type_traits/has_member_function.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/has_nested_type.h" "$(@D)/cuda/include/thrust/detail/type_traits/has_nested_type.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/has_trivial_assign.h" "$(@D)/cuda/include/thrust/detail/type_traits/has_trivial_assign.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/is_call_possible.h" "$(@D)/cuda/include/thrust/detail/type_traits/is_call_possible.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/is_metafunction_defined.h" "$(@D)/cuda/include/thrust/detail/type_traits/is_metafunction_defined.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/iterator/is_discard_iterator.h" "$(@D)/cuda/include/thrust/detail/type_traits/iterator/is_discard_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/iterator/is_output_iterator.h" "$(@D)/cuda/include/thrust/detail/type_traits/iterator/is_output_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/minimum_type.h" "$(@D)/cuda/include/thrust/detail/type_traits/minimum_type.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/pointer_traits.h" "$(@D)/cuda/include/thrust/detail/type_traits/pointer_traits.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/type_traits/result_of_adaptable_function.h" "$(@D)/cuda/include/thrust/detail/type_traits/result_of_adaptable_function.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/uninitialized_copy.inl" "$(@D)/cuda/include/thrust/detail/uninitialized_copy.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/uninitialized_fill.inl" "$(@D)/cuda/include/thrust/detail/uninitialized_fill.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/unique.inl" "$(@D)/cuda/include/thrust/detail/unique.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/use_default.h" "$(@D)/cuda/include/thrust/detail/use_default.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/util/align.h" "$(@D)/cuda/include/thrust/detail/util/align.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/util/blocking.h" "$(@D)/cuda/include/thrust/detail/util/blocking.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/vector_base.h" "$(@D)/cuda/include/thrust/detail/vector_base.h" && cp -f "/usr/local/cuda-10.0/include/thrust/detail/vector_base.inl" "$(@D)/cuda/include/thrust/detail/vector_base.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/device_allocator.h" "$(@D)/cuda/include/thrust/device_allocator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/device_delete.h" "$(@D)/cuda/include/thrust/device_delete.h" && cp -f "/usr/local/cuda-10.0/include/thrust/device_free.h" "$(@D)/cuda/include/thrust/device_free.h" && cp -f "/usr/local/cuda-10.0/include/thrust/device_malloc.h" "$(@D)/cuda/include/thrust/device_malloc.h" && cp -f "/usr/local/cuda-10.0/include/thrust/device_malloc_allocator.h" "$(@D)/cuda/include/thrust/device_malloc_allocator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/device_new.h" "$(@D)/cuda/include/thrust/device_new.h" && cp -f "/usr/local/cuda-10.0/include/thrust/device_new_allocator.h" "$(@D)/cuda/include/thrust/device_new_allocator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/device_ptr.h" "$(@D)/cuda/include/thrust/device_ptr.h" && cp -f "/usr/local/cuda-10.0/include/thrust/device_reference.h" "$(@D)/cuda/include/thrust/device_reference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/device_vector.h" "$(@D)/cuda/include/thrust/device_vector.h" && cp -f "/usr/local/cuda-10.0/include/thrust/distance.h" "$(@D)/cuda/include/thrust/distance.h" && cp -f "/usr/local/cuda-10.0/include/thrust/equal.h" "$(@D)/cuda/include/thrust/equal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/execution_policy.h" "$(@D)/cuda/include/thrust/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/extrema.h" "$(@D)/cuda/include/thrust/extrema.h" && cp -f "/usr/local/cuda-10.0/include/thrust/fill.h" "$(@D)/cuda/include/thrust/fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/find.h" "$(@D)/cuda/include/thrust/find.h" && cp -f "/usr/local/cuda-10.0/include/thrust/for_each.h" "$(@D)/cuda/include/thrust/for_each.h" && cp -f "/usr/local/cuda-10.0/include/thrust/functional.h" "$(@D)/cuda/include/thrust/functional.h" && cp -f "/usr/local/cuda-10.0/include/thrust/gather.h" "$(@D)/cuda/include/thrust/gather.h" && cp -f "/usr/local/cuda-10.0/include/thrust/generate.h" "$(@D)/cuda/include/thrust/generate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/host_vector.h" "$(@D)/cuda/include/thrust/host_vector.h" && cp -f "/usr/local/cuda-10.0/include/thrust/inner_product.h" "$(@D)/cuda/include/thrust/inner_product.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/constant_iterator.h" "$(@D)/cuda/include/thrust/iterator/constant_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/counting_iterator.h" "$(@D)/cuda/include/thrust/iterator/counting_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/any_assign.h" "$(@D)/cuda/include/thrust/iterator/detail/any_assign.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/any_system_tag.h" "$(@D)/cuda/include/thrust/iterator/detail/any_system_tag.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/constant_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/constant_iterator_base.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/counting_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/counting_iterator.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/device_system_tag.h" "$(@D)/cuda/include/thrust/iterator/detail/device_system_tag.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/discard_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/discard_iterator_base.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/distance_from_result.h" "$(@D)/cuda/include/thrust/iterator/detail/distance_from_result.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/host_system_tag.h" "$(@D)/cuda/include/thrust/iterator/detail/host_system_tag.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/is_iterator_category.h" "$(@D)/cuda/include/thrust/iterator/detail/is_iterator_category.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/is_trivial_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/is_trivial_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/iterator_adaptor_base.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_adaptor_base.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/iterator_category_to_system.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_category_to_system.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/iterator_category_to_traversal.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_category_to_traversal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/iterator_category_with_system_and_traversal.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_category_with_system_and_traversal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/iterator_facade_category.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_facade_category.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/iterator_traits.inl" "$(@D)/cuda/include/thrust/iterator/detail/iterator_traits.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/iterator_traversal_tags.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_traversal_tags.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/join_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/join_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/minimum_category.h" "$(@D)/cuda/include/thrust/iterator/detail/minimum_category.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/minimum_system.h" "$(@D)/cuda/include/thrust/iterator/detail/minimum_system.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/normal_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/normal_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/permutation_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/permutation_iterator_base.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/retag.h" "$(@D)/cuda/include/thrust/iterator/detail/retag.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/reverse_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/reverse_iterator.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/reverse_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/reverse_iterator_base.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/tagged_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/tagged_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/transform_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/transform_iterator.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/transform_output_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/transform_output_iterator.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/tuple_of_iterator_references.h" "$(@D)/cuda/include/thrust/iterator/detail/tuple_of_iterator_references.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/universal_categories.h" "$(@D)/cuda/include/thrust/iterator/detail/universal_categories.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/zip_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/zip_iterator.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/detail/zip_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/zip_iterator_base.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/discard_iterator.h" "$(@D)/cuda/include/thrust/iterator/discard_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/iterator_adaptor.h" "$(@D)/cuda/include/thrust/iterator/iterator_adaptor.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/iterator_categories.h" "$(@D)/cuda/include/thrust/iterator/iterator_categories.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/iterator_facade.h" "$(@D)/cuda/include/thrust/iterator/iterator_facade.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/iterator_traits.h" "$(@D)/cuda/include/thrust/iterator/iterator_traits.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/permutation_iterator.h" "$(@D)/cuda/include/thrust/iterator/permutation_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/retag.h" "$(@D)/cuda/include/thrust/iterator/retag.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/reverse_iterator.h" "$(@D)/cuda/include/thrust/iterator/reverse_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/transform_iterator.h" "$(@D)/cuda/include/thrust/iterator/transform_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/transform_output_iterator.h" "$(@D)/cuda/include/thrust/iterator/transform_output_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/iterator/zip_iterator.h" "$(@D)/cuda/include/thrust/iterator/zip_iterator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/logical.h" "$(@D)/cuda/include/thrust/logical.h" && cp -f "/usr/local/cuda-10.0/include/thrust/memory.h" "$(@D)/cuda/include/thrust/memory.h" && cp -f "/usr/local/cuda-10.0/include/thrust/merge.h" "$(@D)/cuda/include/thrust/merge.h" && cp -f "/usr/local/cuda-10.0/include/thrust/mismatch.h" "$(@D)/cuda/include/thrust/mismatch.h" && cp -f "/usr/local/cuda-10.0/include/thrust/pair.h" "$(@D)/cuda/include/thrust/pair.h" && cp -f "/usr/local/cuda-10.0/include/thrust/partition.h" "$(@D)/cuda/include/thrust/partition.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random.h" "$(@D)/cuda/include/thrust/random.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/discard_block_engine.inl" "$(@D)/cuda/include/thrust/random/detail/discard_block_engine.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/linear_congruential_engine.inl" "$(@D)/cuda/include/thrust/random/detail/linear_congruential_engine.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/linear_congruential_engine_discard.h" "$(@D)/cuda/include/thrust/random/detail/linear_congruential_engine_discard.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/linear_feedback_shift_engine.inl" "$(@D)/cuda/include/thrust/random/detail/linear_feedback_shift_engine.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/linear_feedback_shift_engine_wordmask.h" "$(@D)/cuda/include/thrust/random/detail/linear_feedback_shift_engine_wordmask.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/mod.h" "$(@D)/cuda/include/thrust/random/detail/mod.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/normal_distribution.inl" "$(@D)/cuda/include/thrust/random/detail/normal_distribution.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/normal_distribution_base.h" "$(@D)/cuda/include/thrust/random/detail/normal_distribution_base.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/random_core_access.h" "$(@D)/cuda/include/thrust/random/detail/random_core_access.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/subtract_with_carry_engine.inl" "$(@D)/cuda/include/thrust/random/detail/subtract_with_carry_engine.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/uniform_int_distribution.inl" "$(@D)/cuda/include/thrust/random/detail/uniform_int_distribution.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/uniform_real_distribution.inl" "$(@D)/cuda/include/thrust/random/detail/uniform_real_distribution.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/xor_combine_engine.inl" "$(@D)/cuda/include/thrust/random/detail/xor_combine_engine.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/random/detail/xor_combine_engine_max.h" "$(@D)/cuda/include/thrust/random/detail/xor_combine_engine_max.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/discard_block_engine.h" "$(@D)/cuda/include/thrust/random/discard_block_engine.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/linear_congruential_engine.h" "$(@D)/cuda/include/thrust/random/linear_congruential_engine.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/linear_feedback_shift_engine.h" "$(@D)/cuda/include/thrust/random/linear_feedback_shift_engine.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/normal_distribution.h" "$(@D)/cuda/include/thrust/random/normal_distribution.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/subtract_with_carry_engine.h" "$(@D)/cuda/include/thrust/random/subtract_with_carry_engine.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/uniform_int_distribution.h" "$(@D)/cuda/include/thrust/random/uniform_int_distribution.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/uniform_real_distribution.h" "$(@D)/cuda/include/thrust/random/uniform_real_distribution.h" && cp -f "/usr/local/cuda-10.0/include/thrust/random/xor_combine_engine.h" "$(@D)/cuda/include/thrust/random/xor_combine_engine.h" && cp -f "/usr/local/cuda-10.0/include/thrust/reduce.h" "$(@D)/cuda/include/thrust/reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/remove.h" "$(@D)/cuda/include/thrust/remove.h" && cp -f "/usr/local/cuda-10.0/include/thrust/replace.h" "$(@D)/cuda/include/thrust/replace.h" && cp -f "/usr/local/cuda-10.0/include/thrust/reverse.h" "$(@D)/cuda/include/thrust/reverse.h" && cp -f "/usr/local/cuda-10.0/include/thrust/scan.h" "$(@D)/cuda/include/thrust/scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/scatter.h" "$(@D)/cuda/include/thrust/scatter.h" && cp -f "/usr/local/cuda-10.0/include/thrust/sequence.h" "$(@D)/cuda/include/thrust/sequence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/set_operations.h" "$(@D)/cuda/include/thrust/set_operations.h" && cp -f "/usr/local/cuda-10.0/include/thrust/sort.h" "$(@D)/cuda/include/thrust/sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/swap.h" "$(@D)/cuda/include/thrust/swap.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/cpp/detail/adjacent_difference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/cpp/detail/assign_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/cpp/detail/binary_search.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/copy.h" "$(@D)/cuda/include/thrust/system/cpp/detail/copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/cpp/detail/copy_if.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/count.h" "$(@D)/cuda/include/thrust/system/cpp/detail/count.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/equal.h" "$(@D)/cuda/include/thrust/system/cpp/detail/equal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/cpp/detail/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/extrema.h" "$(@D)/cuda/include/thrust/system/cpp/detail/extrema.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/fill.h" "$(@D)/cuda/include/thrust/system/cpp/detail/fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/find.h" "$(@D)/cuda/include/thrust/system/cpp/detail/find.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/for_each.h" "$(@D)/cuda/include/thrust/system/cpp/detail/for_each.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/gather.h" "$(@D)/cuda/include/thrust/system/cpp/detail/gather.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/generate.h" "$(@D)/cuda/include/thrust/system/cpp/detail/generate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/get_value.h" "$(@D)/cuda/include/thrust/system/cpp/detail/get_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/cpp/detail/inner_product.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/cpp/detail/iter_swap.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/logical.h" "$(@D)/cuda/include/thrust/system/cpp/detail/logical.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/cpp/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/memory.inl" "$(@D)/cuda/include/thrust/system/cpp/detail/memory.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/merge.h" "$(@D)/cuda/include/thrust/system/cpp/detail/merge.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/cpp/detail/mismatch.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/par.h" "$(@D)/cuda/include/thrust/system/cpp/detail/par.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/partition.h" "$(@D)/cuda/include/thrust/system/cpp/detail/partition.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/reduce.h" "$(@D)/cuda/include/thrust/system/cpp/detail/reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/cpp/detail/reduce_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/remove.h" "$(@D)/cuda/include/thrust/system/cpp/detail/remove.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/replace.h" "$(@D)/cuda/include/thrust/system/cpp/detail/replace.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/reverse.h" "$(@D)/cuda/include/thrust/system/cpp/detail/reverse.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/scan.h" "$(@D)/cuda/include/thrust/system/cpp/detail/scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/cpp/detail/scan_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/scatter.h" "$(@D)/cuda/include/thrust/system/cpp/detail/scatter.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/sequence.h" "$(@D)/cuda/include/thrust/system/cpp/detail/sequence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/cpp/detail/set_operations.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/sort.h" "$(@D)/cuda/include/thrust/system/cpp/detail/sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/cpp/detail/swap_ranges.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/cpp/detail/tabulate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/cpp/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/transform.h" "$(@D)/cuda/include/thrust/system/cpp/detail/transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/cpp/detail/transform_reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/cpp/detail/transform_scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/cpp/detail/uninitialized_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/cpp/detail/uninitialized_fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/unique.h" "$(@D)/cuda/include/thrust/system/cpp/detail/unique.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/cpp/detail/unique_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/detail/vector.inl" "$(@D)/cuda/include/thrust/system/cpp/detail/vector.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/execution_policy.h" "$(@D)/cuda/include/thrust/system/cpp/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/memory.h" "$(@D)/cuda/include/thrust/system/cpp/memory.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cpp/vector.h" "$(@D)/cuda/include/thrust/system/cpp/vector.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/config.h" "$(@D)/cuda/include/thrust/system/cuda/config.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/cuda/detail/adjacent_difference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/cuda/detail/assign_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/cuda/detail/binary_search.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/copy.h" "$(@D)/cuda/include/thrust/system/cuda/detail/copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/cuda/detail/copy_if.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/core/agent_launcher.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/agent_launcher.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/core/alignment.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/alignment.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/core/triple_chevron_launch.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/triple_chevron_launch.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/core/util.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/util.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/count.h" "$(@D)/cuda/include/thrust/system/cuda/detail/count.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cross_system.h" "$(@D)/cuda/include/thrust/system/cuda/detail/cross_system.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_histogram.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_downsweep.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_downsweep.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_upsweep.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_upsweep.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_reduce.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_reduce_by_key.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_reduce_by_key.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_rle.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_rle.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_scan.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_segment_fixup.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_segment_fixup.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_select_if.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_select_if.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/agent_spmv_orig.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_spmv_orig.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/agent/single_pass_scan_operators.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/single_pass_scan_operators.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_adjacent_difference.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_adjacent_difference.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_discontinuity.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_discontinuity.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_exchange.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_exchange.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_histogram.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_load.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_load.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_radix_rank.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_radix_rank.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_radix_sort.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_raking_layout.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_raking_layout.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_reduce.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_scan.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_shuffle.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_shuffle.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/block_store.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_store.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_atomic.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_atomic.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_sort.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking_commutative_only.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking_commutative_only.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_warp_reductions.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_warp_reductions.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_raking.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_raking.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans2.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans2.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans3.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans3.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/cub.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/cub.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_histogram.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_partition.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_partition.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_radix_sort.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_reduce.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_run_length_encode.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_run_length_encode.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_scan.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_segmented_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_segmented_radix_sort.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_segmented_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_segmented_reduce.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_select.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_select.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/device_spmv.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_spmv.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_histogram.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_radix_sort.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce_by_key.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce_by_key.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_rle.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_rle.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_scan.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_select_if.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_select_if.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_orig.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_orig.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/grid/grid_barrier.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_barrier.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/grid/grid_even_share.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_even_share.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/grid/grid_mapping.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_mapping.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/grid/grid_queue.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_queue.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/host/mutex.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/host/mutex.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/iterator/arg_index_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/arg_index_input_iterator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/iterator/cache_modified_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/cache_modified_input_iterator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/iterator/cache_modified_output_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/cache_modified_output_iterator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/iterator/constant_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/constant_input_iterator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/iterator/counting_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/counting_input_iterator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/iterator/discard_output_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/discard_output_iterator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/iterator/tex_obj_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/tex_obj_input_iterator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/iterator/tex_ref_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/tex_ref_input_iterator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/iterator/transform_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/transform_input_iterator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/thread/thread_load.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_load.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/thread/thread_operators.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_operators.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/thread/thread_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_reduce.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/thread/thread_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_scan.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/thread/thread_search.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_search.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/thread/thread_store.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_store.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/util_allocator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_allocator.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/util_arch.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_arch.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/util_debug.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_debug.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/util_device.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_device.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/util_macro.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_macro.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/util_namespace.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_namespace.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/util_ptx.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_ptx.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/util_type.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_type.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_shfl.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_shfl.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_smem.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_smem.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_shfl.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_shfl.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_smem.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_smem.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/warp/warp_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/warp_reduce.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/cub/warp/warp_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/warp_scan.cuh" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/equal.h" "$(@D)/cuda/include/thrust/system/cuda/detail/equal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/error.inl" "$(@D)/cuda/include/thrust/system/cuda/detail/error.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/cuda/detail/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/extrema.h" "$(@D)/cuda/include/thrust/system/cuda/detail/extrema.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/fill.h" "$(@D)/cuda/include/thrust/system/cuda/detail/fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/find.h" "$(@D)/cuda/include/thrust/system/cuda/detail/find.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/for_each.h" "$(@D)/cuda/include/thrust/system/cuda/detail/for_each.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/gather.h" "$(@D)/cuda/include/thrust/system/cuda/detail/gather.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/generate.h" "$(@D)/cuda/include/thrust/system/cuda/detail/generate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/get_value.h" "$(@D)/cuda/include/thrust/system/cuda/detail/get_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/guarded_cuda_runtime_api.h" "$(@D)/cuda/include/thrust/system/cuda/detail/guarded_cuda_runtime_api.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/guarded_driver_types.h" "$(@D)/cuda/include/thrust/system/cuda/detail/guarded_driver_types.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/cuda/detail/inner_product.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/internal/copy_cross_system.h" "$(@D)/cuda/include/thrust/system/cuda/detail/internal/copy_cross_system.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/internal/copy_device_to_device.h" "$(@D)/cuda/include/thrust/system/cuda/detail/internal/copy_device_to_device.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/cuda/detail/iter_swap.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/logical.h" "$(@D)/cuda/include/thrust/system/cuda/detail/logical.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/cuda/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/memory.inl" "$(@D)/cuda/include/thrust/system/cuda/detail/memory.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/merge.h" "$(@D)/cuda/include/thrust/system/cuda/detail/merge.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/cuda/detail/mismatch.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/par.h" "$(@D)/cuda/include/thrust/system/cuda/detail/par.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/par_to_seq.h" "$(@D)/cuda/include/thrust/system/cuda/detail/par_to_seq.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/parallel_for.h" "$(@D)/cuda/include/thrust/system/cuda/detail/parallel_for.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/partition.h" "$(@D)/cuda/include/thrust/system/cuda/detail/partition.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/reduce.h" "$(@D)/cuda/include/thrust/system/cuda/detail/reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/cuda/detail/reduce_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/remove.h" "$(@D)/cuda/include/thrust/system/cuda/detail/remove.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/replace.h" "$(@D)/cuda/include/thrust/system/cuda/detail/replace.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/reverse.h" "$(@D)/cuda/include/thrust/system/cuda/detail/reverse.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/scan.h" "$(@D)/cuda/include/thrust/system/cuda/detail/scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/cuda/detail/scan_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/scatter.h" "$(@D)/cuda/include/thrust/system/cuda/detail/scatter.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/sequence.h" "$(@D)/cuda/include/thrust/system/cuda/detail/sequence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/cuda/detail/set_operations.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/sort.h" "$(@D)/cuda/include/thrust/system/cuda/detail/sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/cuda/detail/swap_ranges.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/cuda/detail/tabulate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/cuda/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/terminate.h" "$(@D)/cuda/include/thrust/system/cuda/detail/terminate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/transform.h" "$(@D)/cuda/include/thrust/system/cuda/detail/transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/cuda/detail/transform_reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/cuda/detail/transform_scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/cuda/detail/uninitialized_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/cuda/detail/uninitialized_fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/unique.h" "$(@D)/cuda/include/thrust/system/cuda/detail/unique.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/cuda/detail/unique_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/util.h" "$(@D)/cuda/include/thrust/system/cuda/detail/util.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/detail/vector.inl" "$(@D)/cuda/include/thrust/system/cuda/detail/vector.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/error.h" "$(@D)/cuda/include/thrust/system/cuda/error.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/execution_policy.h" "$(@D)/cuda/include/thrust/system/cuda/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/experimental/pinned_allocator.h" "$(@D)/cuda/include/thrust/system/cuda/experimental/pinned_allocator.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/memory.h" "$(@D)/cuda/include/thrust/system/cuda/memory.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/cuda/vector.h" "$(@D)/cuda/include/thrust/system/cuda/vector.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/detail/adl/adjacent_difference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/assign_value.h" "$(@D)/cuda/include/thrust/system/detail/adl/assign_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/adl/binary_search.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/copy.h" "$(@D)/cuda/include/thrust/system/detail/adl/copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/copy_if.h" "$(@D)/cuda/include/thrust/system/detail/adl/copy_if.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/count.h" "$(@D)/cuda/include/thrust/system/detail/adl/count.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/equal.h" "$(@D)/cuda/include/thrust/system/detail/adl/equal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/extrema.h" "$(@D)/cuda/include/thrust/system/detail/adl/extrema.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/fill.h" "$(@D)/cuda/include/thrust/system/detail/adl/fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/find.h" "$(@D)/cuda/include/thrust/system/detail/adl/find.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/for_each.h" "$(@D)/cuda/include/thrust/system/detail/adl/for_each.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/gather.h" "$(@D)/cuda/include/thrust/system/detail/adl/gather.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/generate.h" "$(@D)/cuda/include/thrust/system/detail/adl/generate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/get_value.h" "$(@D)/cuda/include/thrust/system/detail/adl/get_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/inner_product.h" "$(@D)/cuda/include/thrust/system/detail/adl/inner_product.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/iter_swap.h" "$(@D)/cuda/include/thrust/system/detail/adl/iter_swap.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/logical.h" "$(@D)/cuda/include/thrust/system/detail/adl/logical.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/detail/adl/malloc_and_free.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/merge.h" "$(@D)/cuda/include/thrust/system/detail/adl/merge.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/mismatch.h" "$(@D)/cuda/include/thrust/system/detail/adl/mismatch.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/partition.h" "$(@D)/cuda/include/thrust/system/detail/adl/partition.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/reduce.h" "$(@D)/cuda/include/thrust/system/detail/adl/reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/detail/adl/reduce_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/remove.h" "$(@D)/cuda/include/thrust/system/detail/adl/remove.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/replace.h" "$(@D)/cuda/include/thrust/system/detail/adl/replace.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/reverse.h" "$(@D)/cuda/include/thrust/system/detail/adl/reverse.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/scan.h" "$(@D)/cuda/include/thrust/system/detail/adl/scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/scan_by_key.h" "$(@D)/cuda/include/thrust/system/detail/adl/scan_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/scatter.h" "$(@D)/cuda/include/thrust/system/detail/adl/scatter.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/sequence.h" "$(@D)/cuda/include/thrust/system/detail/adl/sequence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/set_operations.h" "$(@D)/cuda/include/thrust/system/detail/adl/set_operations.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/sort.h" "$(@D)/cuda/include/thrust/system/detail/adl/sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/swap_ranges.h" "$(@D)/cuda/include/thrust/system/detail/adl/swap_ranges.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/tabulate.h" "$(@D)/cuda/include/thrust/system/detail/adl/tabulate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/detail/adl/temporary_buffer.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/transform.h" "$(@D)/cuda/include/thrust/system/detail/adl/transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/transform_reduce.h" "$(@D)/cuda/include/thrust/system/detail/adl/transform_reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/transform_scan.h" "$(@D)/cuda/include/thrust/system/detail/adl/transform_scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/detail/adl/uninitialized_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/detail/adl/uninitialized_fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/unique.h" "$(@D)/cuda/include/thrust/system/detail/adl/unique.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/adl/unique_by_key.h" "$(@D)/cuda/include/thrust/system/detail/adl/unique_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/bad_alloc.h" "$(@D)/cuda/include/thrust/system/detail/bad_alloc.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/errno.h" "$(@D)/cuda/include/thrust/system/detail/errno.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/error_category.inl" "$(@D)/cuda/include/thrust/system/detail/error_category.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/error_code.inl" "$(@D)/cuda/include/thrust/system/detail/error_code.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/error_condition.inl" "$(@D)/cuda/include/thrust/system/detail/error_condition.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/detail/generic/adjacent_difference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/adjacent_difference.inl" "$(@D)/cuda/include/thrust/system/detail/generic/adjacent_difference.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/advance.h" "$(@D)/cuda/include/thrust/system/detail/generic/advance.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/advance.inl" "$(@D)/cuda/include/thrust/system/detail/generic/advance.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/generic/binary_search.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/binary_search.inl" "$(@D)/cuda/include/thrust/system/detail/generic/binary_search.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/copy.h" "$(@D)/cuda/include/thrust/system/detail/generic/copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/copy.inl" "$(@D)/cuda/include/thrust/system/detail/generic/copy.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/copy_if.h" "$(@D)/cuda/include/thrust/system/detail/generic/copy_if.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/copy_if.inl" "$(@D)/cuda/include/thrust/system/detail/generic/copy_if.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/count.h" "$(@D)/cuda/include/thrust/system/detail/generic/count.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/count.inl" "$(@D)/cuda/include/thrust/system/detail/generic/count.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/distance.h" "$(@D)/cuda/include/thrust/system/detail/generic/distance.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/distance.inl" "$(@D)/cuda/include/thrust/system/detail/generic/distance.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/equal.h" "$(@D)/cuda/include/thrust/system/detail/generic/equal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/equal.inl" "$(@D)/cuda/include/thrust/system/detail/generic/equal.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/extrema.h" "$(@D)/cuda/include/thrust/system/detail/generic/extrema.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/extrema.inl" "$(@D)/cuda/include/thrust/system/detail/generic/extrema.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/fill.h" "$(@D)/cuda/include/thrust/system/detail/generic/fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/find.h" "$(@D)/cuda/include/thrust/system/detail/generic/find.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/find.inl" "$(@D)/cuda/include/thrust/system/detail/generic/find.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/for_each.h" "$(@D)/cuda/include/thrust/system/detail/generic/for_each.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/gather.h" "$(@D)/cuda/include/thrust/system/detail/generic/gather.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/gather.inl" "$(@D)/cuda/include/thrust/system/detail/generic/gather.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/generate.h" "$(@D)/cuda/include/thrust/system/detail/generic/generate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/generate.inl" "$(@D)/cuda/include/thrust/system/detail/generic/generate.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/inner_product.h" "$(@D)/cuda/include/thrust/system/detail/generic/inner_product.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/inner_product.inl" "$(@D)/cuda/include/thrust/system/detail/generic/inner_product.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/logical.h" "$(@D)/cuda/include/thrust/system/detail/generic/logical.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/memory.h" "$(@D)/cuda/include/thrust/system/detail/generic/memory.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/memory.inl" "$(@D)/cuda/include/thrust/system/detail/generic/memory.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/merge.h" "$(@D)/cuda/include/thrust/system/detail/generic/merge.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/merge.inl" "$(@D)/cuda/include/thrust/system/detail/generic/merge.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/mismatch.h" "$(@D)/cuda/include/thrust/system/detail/generic/mismatch.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/mismatch.inl" "$(@D)/cuda/include/thrust/system/detail/generic/mismatch.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/partition.h" "$(@D)/cuda/include/thrust/system/detail/generic/partition.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/partition.inl" "$(@D)/cuda/include/thrust/system/detail/generic/partition.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/reduce.h" "$(@D)/cuda/include/thrust/system/detail/generic/reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/reduce.inl" "$(@D)/cuda/include/thrust/system/detail/generic/reduce.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/detail/generic/reduce_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/reduce_by_key.inl" "$(@D)/cuda/include/thrust/system/detail/generic/reduce_by_key.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/remove.h" "$(@D)/cuda/include/thrust/system/detail/generic/remove.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/remove.inl" "$(@D)/cuda/include/thrust/system/detail/generic/remove.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/replace.h" "$(@D)/cuda/include/thrust/system/detail/generic/replace.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/replace.inl" "$(@D)/cuda/include/thrust/system/detail/generic/replace.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/reverse.h" "$(@D)/cuda/include/thrust/system/detail/generic/reverse.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/reverse.inl" "$(@D)/cuda/include/thrust/system/detail/generic/reverse.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/scalar/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/generic/scalar/binary_search.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/scalar/binary_search.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scalar/binary_search.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/scan.h" "$(@D)/cuda/include/thrust/system/detail/generic/scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/scan.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scan.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/scan_by_key.h" "$(@D)/cuda/include/thrust/system/detail/generic/scan_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/scan_by_key.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scan_by_key.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/scatter.h" "$(@D)/cuda/include/thrust/system/detail/generic/scatter.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/scatter.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scatter.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/select_system.h" "$(@D)/cuda/include/thrust/system/detail/generic/select_system.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/sequence.h" "$(@D)/cuda/include/thrust/system/detail/generic/sequence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/sequence.inl" "$(@D)/cuda/include/thrust/system/detail/generic/sequence.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/set_operations.h" "$(@D)/cuda/include/thrust/system/detail/generic/set_operations.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/set_operations.inl" "$(@D)/cuda/include/thrust/system/detail/generic/set_operations.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/sort.h" "$(@D)/cuda/include/thrust/system/detail/generic/sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/sort.inl" "$(@D)/cuda/include/thrust/system/detail/generic/sort.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/swap_ranges.h" "$(@D)/cuda/include/thrust/system/detail/generic/swap_ranges.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/swap_ranges.inl" "$(@D)/cuda/include/thrust/system/detail/generic/swap_ranges.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/tabulate.h" "$(@D)/cuda/include/thrust/system/detail/generic/tabulate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/tabulate.inl" "$(@D)/cuda/include/thrust/system/detail/generic/tabulate.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/tag.h" "$(@D)/cuda/include/thrust/system/detail/generic/tag.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/detail/generic/temporary_buffer.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/temporary_buffer.inl" "$(@D)/cuda/include/thrust/system/detail/generic/temporary_buffer.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/transform.h" "$(@D)/cuda/include/thrust/system/detail/generic/transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/transform.inl" "$(@D)/cuda/include/thrust/system/detail/generic/transform.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/transform_reduce.h" "$(@D)/cuda/include/thrust/system/detail/generic/transform_reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/transform_reduce.inl" "$(@D)/cuda/include/thrust/system/detail/generic/transform_reduce.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/transform_scan.h" "$(@D)/cuda/include/thrust/system/detail/generic/transform_scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/transform_scan.inl" "$(@D)/cuda/include/thrust/system/detail/generic/transform_scan.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/type_traits.h" "$(@D)/cuda/include/thrust/system/detail/generic/type_traits.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/uninitialized_copy.inl" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_copy.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/uninitialized_fill.inl" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_fill.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/unique.h" "$(@D)/cuda/include/thrust/system/detail/generic/unique.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/unique.inl" "$(@D)/cuda/include/thrust/system/detail/generic/unique.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/unique_by_key.h" "$(@D)/cuda/include/thrust/system/detail/generic/unique_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/generic/unique_by_key.inl" "$(@D)/cuda/include/thrust/system/detail/generic/unique_by_key.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/internal/decompose.h" "$(@D)/cuda/include/thrust/system/detail/internal/decompose.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/detail/sequential/adjacent_difference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/assign_value.h" "$(@D)/cuda/include/thrust/system/detail/sequential/assign_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/sequential/binary_search.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/copy.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/copy.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/copy_backward.h" "$(@D)/cuda/include/thrust/system/detail/sequential/copy_backward.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/copy_if.h" "$(@D)/cuda/include/thrust/system/detail/sequential/copy_if.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/count.h" "$(@D)/cuda/include/thrust/system/detail/sequential/count.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/equal.h" "$(@D)/cuda/include/thrust/system/detail/sequential/equal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/execution_policy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/extrema.h" "$(@D)/cuda/include/thrust/system/detail/sequential/extrema.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/fill.h" "$(@D)/cuda/include/thrust/system/detail/sequential/fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/find.h" "$(@D)/cuda/include/thrust/system/detail/sequential/find.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/for_each.h" "$(@D)/cuda/include/thrust/system/detail/sequential/for_each.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/gather.h" "$(@D)/cuda/include/thrust/system/detail/sequential/gather.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/general_copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/general_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/generate.h" "$(@D)/cuda/include/thrust/system/detail/sequential/generate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/get_value.h" "$(@D)/cuda/include/thrust/system/detail/sequential/get_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/inner_product.h" "$(@D)/cuda/include/thrust/system/detail/sequential/inner_product.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/insertion_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/insertion_sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/iter_swap.h" "$(@D)/cuda/include/thrust/system/detail/sequential/iter_swap.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/logical.h" "$(@D)/cuda/include/thrust/system/detail/sequential/logical.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/detail/sequential/malloc_and_free.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/merge.h" "$(@D)/cuda/include/thrust/system/detail/sequential/merge.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/merge.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/merge.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/mismatch.h" "$(@D)/cuda/include/thrust/system/detail/sequential/mismatch.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/partition.h" "$(@D)/cuda/include/thrust/system/detail/sequential/partition.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/reduce.h" "$(@D)/cuda/include/thrust/system/detail/sequential/reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/detail/sequential/reduce_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/remove.h" "$(@D)/cuda/include/thrust/system/detail/sequential/remove.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/replace.h" "$(@D)/cuda/include/thrust/system/detail/sequential/replace.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/reverse.h" "$(@D)/cuda/include/thrust/system/detail/sequential/reverse.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/scan.h" "$(@D)/cuda/include/thrust/system/detail/sequential/scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/scan_by_key.h" "$(@D)/cuda/include/thrust/system/detail/sequential/scan_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/scatter.h" "$(@D)/cuda/include/thrust/system/detail/sequential/scatter.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/sequence.h" "$(@D)/cuda/include/thrust/system/detail/sequential/sequence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/set_operations.h" "$(@D)/cuda/include/thrust/system/detail/sequential/set_operations.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/sort.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/stable_merge_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_merge_sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/stable_merge_sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_merge_sort.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/stable_primitive_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_primitive_sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/stable_primitive_sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_primitive_sort.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/stable_radix_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_radix_sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/stable_radix_sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_radix_sort.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/swap_ranges.h" "$(@D)/cuda/include/thrust/system/detail/sequential/swap_ranges.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/tabulate.h" "$(@D)/cuda/include/thrust/system/detail/sequential/tabulate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/detail/sequential/temporary_buffer.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/transform.h" "$(@D)/cuda/include/thrust/system/detail/sequential/transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/transform_reduce.h" "$(@D)/cuda/include/thrust/system/detail/sequential/transform_reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/transform_scan.h" "$(@D)/cuda/include/thrust/system/detail/sequential/transform_scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/trivial_copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/trivial_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/uninitialized_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/detail/sequential/uninitialized_fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/unique.h" "$(@D)/cuda/include/thrust/system/detail/sequential/unique.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/sequential/unique_by_key.h" "$(@D)/cuda/include/thrust/system/detail/sequential/unique_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/detail/system_error.inl" "$(@D)/cuda/include/thrust/system/detail/system_error.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/error_code.h" "$(@D)/cuda/include/thrust/system/error_code.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/omp/detail/adjacent_difference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/omp/detail/assign_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/omp/detail/binary_search.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/copy.h" "$(@D)/cuda/include/thrust/system/omp/detail/copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/copy.inl" "$(@D)/cuda/include/thrust/system/omp/detail/copy.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/omp/detail/copy_if.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/copy_if.inl" "$(@D)/cuda/include/thrust/system/omp/detail/copy_if.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/count.h" "$(@D)/cuda/include/thrust/system/omp/detail/count.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/default_decomposition.h" "$(@D)/cuda/include/thrust/system/omp/detail/default_decomposition.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/default_decomposition.inl" "$(@D)/cuda/include/thrust/system/omp/detail/default_decomposition.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/equal.h" "$(@D)/cuda/include/thrust/system/omp/detail/equal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/omp/detail/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/extrema.h" "$(@D)/cuda/include/thrust/system/omp/detail/extrema.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/fill.h" "$(@D)/cuda/include/thrust/system/omp/detail/fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/find.h" "$(@D)/cuda/include/thrust/system/omp/detail/find.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/for_each.h" "$(@D)/cuda/include/thrust/system/omp/detail/for_each.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/for_each.inl" "$(@D)/cuda/include/thrust/system/omp/detail/for_each.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/gather.h" "$(@D)/cuda/include/thrust/system/omp/detail/gather.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/generate.h" "$(@D)/cuda/include/thrust/system/omp/detail/generate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/get_value.h" "$(@D)/cuda/include/thrust/system/omp/detail/get_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/omp/detail/inner_product.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/omp/detail/iter_swap.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/logical.h" "$(@D)/cuda/include/thrust/system/omp/detail/logical.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/omp/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/memory.inl" "$(@D)/cuda/include/thrust/system/omp/detail/memory.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/merge.h" "$(@D)/cuda/include/thrust/system/omp/detail/merge.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/omp/detail/mismatch.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/par.h" "$(@D)/cuda/include/thrust/system/omp/detail/par.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/partition.h" "$(@D)/cuda/include/thrust/system/omp/detail/partition.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/partition.inl" "$(@D)/cuda/include/thrust/system/omp/detail/partition.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/reduce.h" "$(@D)/cuda/include/thrust/system/omp/detail/reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/reduce.inl" "$(@D)/cuda/include/thrust/system/omp/detail/reduce.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/reduce_by_key.inl" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_by_key.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/reduce_intervals.h" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_intervals.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/reduce_intervals.inl" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_intervals.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/remove.h" "$(@D)/cuda/include/thrust/system/omp/detail/remove.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/remove.inl" "$(@D)/cuda/include/thrust/system/omp/detail/remove.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/replace.h" "$(@D)/cuda/include/thrust/system/omp/detail/replace.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/reverse.h" "$(@D)/cuda/include/thrust/system/omp/detail/reverse.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/scan.h" "$(@D)/cuda/include/thrust/system/omp/detail/scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/omp/detail/scan_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/scatter.h" "$(@D)/cuda/include/thrust/system/omp/detail/scatter.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/sequence.h" "$(@D)/cuda/include/thrust/system/omp/detail/sequence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/omp/detail/set_operations.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/sort.h" "$(@D)/cuda/include/thrust/system/omp/detail/sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/sort.inl" "$(@D)/cuda/include/thrust/system/omp/detail/sort.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/omp/detail/swap_ranges.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/omp/detail/tabulate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/omp/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/transform.h" "$(@D)/cuda/include/thrust/system/omp/detail/transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/omp/detail/transform_reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/omp/detail/transform_scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/omp/detail/uninitialized_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/omp/detail/uninitialized_fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/unique.h" "$(@D)/cuda/include/thrust/system/omp/detail/unique.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/unique.inl" "$(@D)/cuda/include/thrust/system/omp/detail/unique.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/omp/detail/unique_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/unique_by_key.inl" "$(@D)/cuda/include/thrust/system/omp/detail/unique_by_key.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/detail/vector.inl" "$(@D)/cuda/include/thrust/system/omp/detail/vector.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/execution_policy.h" "$(@D)/cuda/include/thrust/system/omp/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/memory.h" "$(@D)/cuda/include/thrust/system/omp/memory.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/omp/vector.h" "$(@D)/cuda/include/thrust/system/omp/vector.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/system_error.h" "$(@D)/cuda/include/thrust/system/system_error.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/tbb/detail/adjacent_difference.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/tbb/detail/assign_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/tbb/detail/binary_search.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/copy.h" "$(@D)/cuda/include/thrust/system/tbb/detail/copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/copy.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/copy.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/tbb/detail/copy_if.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/copy_if.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/copy_if.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/count.h" "$(@D)/cuda/include/thrust/system/tbb/detail/count.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/equal.h" "$(@D)/cuda/include/thrust/system/tbb/detail/equal.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/tbb/detail/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/extrema.h" "$(@D)/cuda/include/thrust/system/tbb/detail/extrema.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/fill.h" "$(@D)/cuda/include/thrust/system/tbb/detail/fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/find.h" "$(@D)/cuda/include/thrust/system/tbb/detail/find.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/for_each.h" "$(@D)/cuda/include/thrust/system/tbb/detail/for_each.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/for_each.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/for_each.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/gather.h" "$(@D)/cuda/include/thrust/system/tbb/detail/gather.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/generate.h" "$(@D)/cuda/include/thrust/system/tbb/detail/generate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/get_value.h" "$(@D)/cuda/include/thrust/system/tbb/detail/get_value.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/tbb/detail/inner_product.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/tbb/detail/iter_swap.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/logical.h" "$(@D)/cuda/include/thrust/system/tbb/detail/logical.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/tbb/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/memory.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/memory.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/merge.h" "$(@D)/cuda/include/thrust/system/tbb/detail/merge.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/merge.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/merge.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/tbb/detail/mismatch.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/par.h" "$(@D)/cuda/include/thrust/system/tbb/detail/par.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/partition.h" "$(@D)/cuda/include/thrust/system/tbb/detail/partition.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/partition.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/partition.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/reduce.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/reduce.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/reduce_by_key.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce_by_key.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/reduce_intervals.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce_intervals.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/remove.h" "$(@D)/cuda/include/thrust/system/tbb/detail/remove.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/remove.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/remove.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/replace.h" "$(@D)/cuda/include/thrust/system/tbb/detail/replace.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/reverse.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reverse.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/scan.h" "$(@D)/cuda/include/thrust/system/tbb/detail/scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/scan.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/scan.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/tbb/detail/scan_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/scatter.h" "$(@D)/cuda/include/thrust/system/tbb/detail/scatter.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/sequence.h" "$(@D)/cuda/include/thrust/system/tbb/detail/sequence.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/tbb/detail/set_operations.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/sort.h" "$(@D)/cuda/include/thrust/system/tbb/detail/sort.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/sort.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/sort.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/tbb/detail/swap_ranges.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/tbb/detail/tabulate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/tbb/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/transform.h" "$(@D)/cuda/include/thrust/system/tbb/detail/transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/tbb/detail/transform_reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/tbb/detail/transform_scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/tbb/detail/uninitialized_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/tbb/detail/uninitialized_fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/unique.h" "$(@D)/cuda/include/thrust/system/tbb/detail/unique.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/unique.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/unique.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/tbb/detail/unique_by_key.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/unique_by_key.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/unique_by_key.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/detail/vector.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/vector.inl" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/execution_policy.h" "$(@D)/cuda/include/thrust/system/tbb/execution_policy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/memory.h" "$(@D)/cuda/include/thrust/system/tbb/memory.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system/tbb/vector.h" "$(@D)/cuda/include/thrust/system/tbb/vector.h" && cp -f "/usr/local/cuda-10.0/include/thrust/system_error.h" "$(@D)/cuda/include/thrust/system_error.h" && cp -f "/usr/local/cuda-10.0/include/thrust/tabulate.h" "$(@D)/cuda/include/thrust/tabulate.h" && cp -f "/usr/local/cuda-10.0/include/thrust/transform.h" "$(@D)/cuda/include/thrust/transform.h" && cp -f "/usr/local/cuda-10.0/include/thrust/transform_reduce.h" "$(@D)/cuda/include/thrust/transform_reduce.h" && cp -f "/usr/local/cuda-10.0/include/thrust/transform_scan.h" "$(@D)/cuda/include/thrust/transform_scan.h" && cp -f "/usr/local/cuda-10.0/include/thrust/tuple.h" "$(@D)/cuda/include/thrust/tuple.h" && cp -f "/usr/local/cuda-10.0/include/thrust/uninitialized_copy.h" "$(@D)/cuda/include/thrust/uninitialized_copy.h" && cp -f "/usr/local/cuda-10.0/include/thrust/uninitialized_fill.h" "$(@D)/cuda/include/thrust/uninitialized_fill.h" && cp -f "/usr/local/cuda-10.0/include/thrust/unique.h" "$(@D)/cuda/include/thrust/unique.h" && cp -f "/usr/local/cuda-10.0/include/thrust/version.h" "$(@D)/cuda/include/thrust/version.h" && cp -f "/usr/local/cuda-10.0/include/vector_functions.h" "$(@D)/cuda/include/vector_functions.h" && cp -f "/usr/local/cuda-10.0/include/vector_functions.hpp" "$(@D)/cuda/include/vector_functions.hpp" && cp -f "/usr/local/cuda-10.0/include/vector_types.h" "$(@D)/cuda/include/vector_types.h" + """, +) + +genrule( + name = "cuda-nvvm", + outs = [ + "cuda/nvvm/libdevice/libdevice.10.bc", + ], + cmd = """ +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/local/cuda-10.0/nvvm/libdevice/libdevice.10.bc" "$(@D)//libdevice.10.bc" + """, +) + +genrule( + name = "cuda-extras", + outs = [ + "cuda/extras/CUPTI/include/GL/gl.h", + "cuda/extras/CUPTI/include/GL/glew.h", + "cuda/extras/CUPTI/include/GL/glext.h", + "cuda/extras/CUPTI/include/GL/glu.h", + "cuda/extras/CUPTI/include/GL/glut.h", + "cuda/extras/CUPTI/include/GL/glx.h", + "cuda/extras/CUPTI/include/GL/glxext.h", + "cuda/extras/CUPTI/include/GL/wglew.h", + "cuda/extras/CUPTI/include/GL/wglext.h", + "cuda/extras/CUPTI/include/cuda_stdint.h", + "cuda/extras/CUPTI/include/cupti.h", + "cuda/extras/CUPTI/include/cupti_activity.h", + "cuda/extras/CUPTI/include/cupti_callbacks.h", + "cuda/extras/CUPTI/include/cupti_driver_cbid.h", + "cuda/extras/CUPTI/include/cupti_events.h", + "cuda/extras/CUPTI/include/cupti_metrics.h", + "cuda/extras/CUPTI/include/cupti_nvtx_cbid.h", + "cuda/extras/CUPTI/include/cupti_result.h", + "cuda/extras/CUPTI/include/cupti_runtime_cbid.h", + "cuda/extras/CUPTI/include/cupti_version.h", + "cuda/extras/CUPTI/include/generated_cudaGL_meta.h", + "cuda/extras/CUPTI/include/generated_cudaVDPAU_meta.h", + "cuda/extras/CUPTI/include/generated_cuda_gl_interop_meta.h", + "cuda/extras/CUPTI/include/generated_cuda_meta.h", + "cuda/extras/CUPTI/include/generated_cuda_runtime_api_meta.h", + "cuda/extras/CUPTI/include/generated_cuda_vdpau_interop_meta.h", + "cuda/extras/CUPTI/include/generated_nvtx_meta.h", + "cuda/extras/CUPTI/include/openacc/cupti_openacc.h", + "cuda/extras/CUPTI/include/openmp/cupti_openmp.h", + "cuda/extras/CUPTI/include/openmp/ompt.h", + ], + cmd = """ +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/GL/gl.h" "$(@D)/cuda/extras/CUPTI/include/GL/gl.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/GL/glew.h" "$(@D)/cuda/extras/CUPTI/include/GL/glew.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/GL/glext.h" "$(@D)/cuda/extras/CUPTI/include/GL/glext.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/GL/glu.h" "$(@D)/cuda/extras/CUPTI/include/GL/glu.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/GL/glut.h" "$(@D)/cuda/extras/CUPTI/include/GL/glut.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/GL/glx.h" "$(@D)/cuda/extras/CUPTI/include/GL/glx.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/GL/glxext.h" "$(@D)/cuda/extras/CUPTI/include/GL/glxext.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/GL/wglew.h" "$(@D)/cuda/extras/CUPTI/include/GL/wglew.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/GL/wglext.h" "$(@D)/cuda/extras/CUPTI/include/GL/wglext.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cuda_stdint.h" "$(@D)/cuda/extras/CUPTI/include/cuda_stdint.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti.h" "$(@D)/cuda/extras/CUPTI/include/cupti.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti_activity.h" "$(@D)/cuda/extras/CUPTI/include/cupti_activity.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti_callbacks.h" "$(@D)/cuda/extras/CUPTI/include/cupti_callbacks.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti_driver_cbid.h" "$(@D)/cuda/extras/CUPTI/include/cupti_driver_cbid.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti_events.h" "$(@D)/cuda/extras/CUPTI/include/cupti_events.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti_metrics.h" "$(@D)/cuda/extras/CUPTI/include/cupti_metrics.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti_nvtx_cbid.h" "$(@D)/cuda/extras/CUPTI/include/cupti_nvtx_cbid.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti_result.h" "$(@D)/cuda/extras/CUPTI/include/cupti_result.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti_runtime_cbid.h" "$(@D)/cuda/extras/CUPTI/include/cupti_runtime_cbid.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/cupti_version.h" "$(@D)/cuda/extras/CUPTI/include/cupti_version.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/generated_cudaGL_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cudaGL_meta.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/generated_cudaVDPAU_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cudaVDPAU_meta.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/generated_cuda_gl_interop_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_gl_interop_meta.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/generated_cuda_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_meta.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/generated_cuda_runtime_api_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_runtime_api_meta.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/generated_cuda_vdpau_interop_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_vdpau_interop_meta.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/generated_nvtx_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_nvtx_meta.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/openacc/cupti_openacc.h" "$(@D)/cuda/extras/CUPTI/include/openacc/cupti_openacc.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/openmp/cupti_openmp.h" "$(@D)/cuda/extras/CUPTI/include/openmp/cupti_openmp.h" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/include/openmp/ompt.h" "$(@D)/cuda/extras/CUPTI/include/openmp/ompt.h" + """, +) + +genrule( + name = "cuda-lib", + outs = [ + "cuda/lib/libcuda.so", + "cuda/lib/libcudart.so.10.0", + "cuda/lib/libcudart_static.a", + "cuda/lib/libcublas.so.10.0", + "cuda/lib/libcusolver.so.10.0", + "cuda/lib/libcurand.so.10.0", + "cuda/lib/libcufft.so.10.0", + "cuda/lib/libcudnn.so.7", + "cuda/lib/libcupti.so.10.0", + ], + cmd = """ +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/local/cuda-10.0/targets/x86_64-linux/lib/stubs/libcuda.so" "$(@D)/cuda/lib/libcuda.so" && cp -f "/usr/local/cuda-10.0/targets/x86_64-linux/lib/libcudart.so.10.0.130" "$(@D)/cuda/lib/libcudart.so.10.0" && cp -f "/usr/local/cuda-10.0/targets/x86_64-linux/lib/libcudart_static.a" "$(@D)/cuda/lib/libcudart_static.a" && cp -f "/usr/local/cuda-10.0/targets/x86_64-linux/lib/libcublas.so.10.0.130" "$(@D)/cuda/lib/libcublas.so.10.0" && cp -f "/usr/local/cuda-10.0/targets/x86_64-linux/lib/libcusolver.so.10.0.130" "$(@D)/cuda/lib/libcusolver.so.10.0" && cp -f "/usr/local/cuda-10.0/targets/x86_64-linux/lib/libcurand.so.10.0.130" "$(@D)/cuda/lib/libcurand.so.10.0" && cp -f "/usr/local/cuda-10.0/targets/x86_64-linux/lib/libcufft.so.10.0.145" "$(@D)/cuda/lib/libcufft.so.10.0" && cp -f "/usr/lib/x86_64-linux-gnu/libcudnn.so.7.3.1" "$(@D)/cuda/lib/libcudnn.so.7" && cp -f "/usr/local/cuda-10.0/extras/CUPTI/lib64/libcupti.so.10.0.130" "$(@D)/cuda/lib/libcupti.so.10.0" + """, +) + +genrule( + name = "cudnn-include", + outs = [ + "cuda/include/cudnn.h", + ], + cmd = """ +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/include/cudnn.h" "$(@D)/cudnn.h" + """, +) diff --git a/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/build_defs.bzl b/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/build_defs.bzl new file mode 100755 index 0000000000..a53c891d8b --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/build_defs.bzl @@ -0,0 +1,31 @@ +# Macros for building CUDA code. +def if_cuda(if_true, if_false = []): + """Shorthand for select()'ing on whether we're building with CUDA. + + Returns a select statement which evaluates to if_true if we're building + with CUDA enabled. Otherwise, the select statement evaluates to if_false. + + """ + return select({ + "@local_config_cuda//cuda:using_nvcc": if_true, + "@local_config_cuda//cuda:using_clang": if_true, + "//conditions:default": if_false, + }) + +def cuda_default_copts(): + """Default options for all CUDA compilations.""" + return if_cuda(["-x", "cuda", "-DGOOGLE_CUDA=1"] + []) + +def cuda_is_configured(): + """Returns true if CUDA was enabled during the configure process.""" + return True + +def if_cuda_is_configured(x): + """Tests if the CUDA was enabled during the configure process. + + Unlike if_cuda(), this does not require that we are building with + --config=cuda. Used to allow non-CUDA code to depend on CUDA libraries. + """ + if cuda_is_configured(): + return x + return [] diff --git a/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/cuda/cuda_config.h b/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/cuda/cuda_config.h new file mode 100755 index 0000000000..0934618e0b --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/cuda10.0-cudnn7/cuda/cuda/cuda_config.h @@ -0,0 +1,26 @@ +/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef CUDA_CUDA_CONFIG_H_ +#define CUDA_CUDA_CONFIG_H_ + +#define TF_CUDA_CAPABILITIES CudaVersion("3.0") + +#define TF_CUDA_VERSION "10.0" +#define TF_CUDNN_VERSION "7" + +#define TF_CUDA_TOOLKIT_PATH "/usr/local/cuda-10.0" + +#endif // CUDA_CUDA_CONFIG_H_ diff --git a/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/BUILD b/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/BUILD index 247e0ace24..c6930904b5 100755 --- a/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/BUILD +++ b/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/BUILD @@ -1188,7 +1188,7 @@ genrule( "cuda/include/vector_types.h", ], cmd = """ -if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp "/usr/local/cuda-9.0/include/CL/cl.h" "$(@D)/cuda/include/CL/cl.h" && cp "/usr/local/cuda-9.0/include/CL/cl.hpp" "$(@D)/cuda/include/CL/cl.hpp" && cp "/usr/local/cuda-9.0/include/CL/cl_egl.h" "$(@D)/cuda/include/CL/cl_egl.h" && cp "/usr/local/cuda-9.0/include/CL/cl_ext.h" "$(@D)/cuda/include/CL/cl_ext.h" && cp "/usr/local/cuda-9.0/include/CL/cl_gl.h" "$(@D)/cuda/include/CL/cl_gl.h" && cp "/usr/local/cuda-9.0/include/CL/cl_gl_ext.h" "$(@D)/cuda/include/CL/cl_gl_ext.h" && cp "/usr/local/cuda-9.0/include/CL/cl_platform.h" "$(@D)/cuda/include/CL/cl_platform.h" && cp "/usr/local/cuda-9.0/include/CL/opencl.h" "$(@D)/cuda/include/CL/opencl.h" && cp "/usr/local/cuda-9.0/include/builtin_types.h" "$(@D)/cuda/include/builtin_types.h" && cp "/usr/local/cuda-9.0/include/channel_descriptor.h" "$(@D)/cuda/include/channel_descriptor.h" && cp "/usr/local/cuda-9.0/include/common_functions.h" "$(@D)/cuda/include/common_functions.h" && cp "/usr/local/cuda-9.0/include/cooperative_groups.h" "$(@D)/cuda/include/cooperative_groups.h" && cp "/usr/local/cuda-9.0/include/cooperative_groups_helpers.h" "$(@D)/cuda/include/cooperative_groups_helpers.h" && cp "/usr/local/cuda-9.0/include/crt/common_functions.h" "$(@D)/cuda/include/crt/common_functions.h" && cp "/usr/local/cuda-9.0/include/crt/device_double_functions.h" "$(@D)/cuda/include/crt/device_double_functions.h" && cp "/usr/local/cuda-9.0/include/crt/device_double_functions.hpp" "$(@D)/cuda/include/crt/device_double_functions.hpp" && cp "/usr/local/cuda-9.0/include/crt/device_functions.h" "$(@D)/cuda/include/crt/device_functions.h" && cp "/usr/local/cuda-9.0/include/crt/device_functions.hpp" "$(@D)/cuda/include/crt/device_functions.hpp" && cp "/usr/local/cuda-9.0/include/crt/func_macro.h" "$(@D)/cuda/include/crt/func_macro.h" && cp "/usr/local/cuda-9.0/include/crt/host_config.h" "$(@D)/cuda/include/crt/host_config.h" && cp "/usr/local/cuda-9.0/include/crt/host_defines.h" "$(@D)/cuda/include/crt/host_defines.h" && cp "/usr/local/cuda-9.0/include/crt/host_runtime.h" "$(@D)/cuda/include/crt/host_runtime.h" && cp "/usr/local/cuda-9.0/include/crt/math_functions.h" "$(@D)/cuda/include/crt/math_functions.h" && cp "/usr/local/cuda-9.0/include/crt/math_functions.hpp" "$(@D)/cuda/include/crt/math_functions.hpp" && cp "/usr/local/cuda-9.0/include/crt/mma.h" "$(@D)/cuda/include/crt/mma.h" && cp "/usr/local/cuda-9.0/include/crt/mma.hpp" "$(@D)/cuda/include/crt/mma.hpp" && cp "/usr/local/cuda-9.0/include/crt/nvfunctional" "$(@D)/cuda/include/crt/nvfunctional" && cp "/usr/local/cuda-9.0/include/crt/sm_70_rt.h" "$(@D)/cuda/include/crt/sm_70_rt.h" && cp "/usr/local/cuda-9.0/include/crt/sm_70_rt.hpp" "$(@D)/cuda/include/crt/sm_70_rt.hpp" && cp "/usr/local/cuda-9.0/include/crt/storage_class.h" "$(@D)/cuda/include/crt/storage_class.h" && cp "/usr/local/cuda-9.0/include/cuComplex.h" "$(@D)/cuda/include/cuComplex.h" && cp "/usr/local/cuda-9.0/include/cublas.h" "$(@D)/cuda/include/cublas.h" && cp "/usr/local/cuda-9.0/include/cublasXt.h" "$(@D)/cuda/include/cublasXt.h" && cp "/usr/local/cuda-9.0/include/cublas_api.h" "$(@D)/cuda/include/cublas_api.h" && cp "/usr/local/cuda-9.0/include/cublas_v2.h" "$(@D)/cuda/include/cublas_v2.h" && cp "/usr/local/cuda-9.0/include/cuda.h" "$(@D)/cuda/include/cuda.h" && cp "/usr/local/cuda-9.0/include/cudaEGL.h" "$(@D)/cuda/include/cudaEGL.h" && cp "/usr/local/cuda-9.0/include/cudaGL.h" "$(@D)/cuda/include/cudaGL.h" && cp "/usr/local/cuda-9.0/include/cudaProfiler.h" "$(@D)/cuda/include/cudaProfiler.h" && cp "/usr/local/cuda-9.0/include/cudaVDPAU.h" "$(@D)/cuda/include/cudaVDPAU.h" && cp "/usr/local/cuda-9.0/include/cuda_device_runtime_api.h" "$(@D)/cuda/include/cuda_device_runtime_api.h" && cp "/usr/local/cuda-9.0/include/cuda_fp16.h" "$(@D)/cuda/include/cuda_fp16.h" && cp "/usr/local/cuda-9.0/include/cuda_fp16.hpp" "$(@D)/cuda/include/cuda_fp16.hpp" && cp "/usr/local/cuda-9.0/include/cuda_gl_interop.h" "$(@D)/cuda/include/cuda_gl_interop.h" && cp "/usr/local/cuda-9.0/include/cuda_occupancy.h" "$(@D)/cuda/include/cuda_occupancy.h" && cp "/usr/local/cuda-9.0/include/cuda_profiler_api.h" "$(@D)/cuda/include/cuda_profiler_api.h" && cp "/usr/local/cuda-9.0/include/cuda_runtime.h" "$(@D)/cuda/include/cuda_runtime.h" && cp "/usr/local/cuda-9.0/include/cuda_runtime_api.h" "$(@D)/cuda/include/cuda_runtime_api.h" && cp "/usr/local/cuda-9.0/include/cuda_surface_types.h" "$(@D)/cuda/include/cuda_surface_types.h" && cp "/usr/local/cuda-9.0/include/cuda_texture_types.h" "$(@D)/cuda/include/cuda_texture_types.h" && cp "/usr/local/cuda-9.0/include/cuda_vdpau_interop.h" "$(@D)/cuda/include/cuda_vdpau_interop.h" && cp "/usr/local/cuda-9.0/include/cudalibxt.h" "$(@D)/cuda/include/cudalibxt.h" && cp "/usr/local/cuda-9.0/include/cufft.h" "$(@D)/cuda/include/cufft.h" && cp "/usr/local/cuda-9.0/include/cufftXt.h" "$(@D)/cuda/include/cufftXt.h" && cp "/usr/local/cuda-9.0/include/cufftw.h" "$(@D)/cuda/include/cufftw.h" && cp "/usr/local/cuda-9.0/include/curand.h" "$(@D)/cuda/include/curand.h" && cp "/usr/local/cuda-9.0/include/curand_discrete.h" "$(@D)/cuda/include/curand_discrete.h" && cp "/usr/local/cuda-9.0/include/curand_discrete2.h" "$(@D)/cuda/include/curand_discrete2.h" && cp "/usr/local/cuda-9.0/include/curand_globals.h" "$(@D)/cuda/include/curand_globals.h" && cp "/usr/local/cuda-9.0/include/curand_kernel.h" "$(@D)/cuda/include/curand_kernel.h" && cp "/usr/local/cuda-9.0/include/curand_lognormal.h" "$(@D)/cuda/include/curand_lognormal.h" && cp "/usr/local/cuda-9.0/include/curand_mrg32k3a.h" "$(@D)/cuda/include/curand_mrg32k3a.h" && cp "/usr/local/cuda-9.0/include/curand_mtgp32.h" "$(@D)/cuda/include/curand_mtgp32.h" && cp "/usr/local/cuda-9.0/include/curand_mtgp32_host.h" "$(@D)/cuda/include/curand_mtgp32_host.h" && cp "/usr/local/cuda-9.0/include/curand_mtgp32_kernel.h" "$(@D)/cuda/include/curand_mtgp32_kernel.h" && cp "/usr/local/cuda-9.0/include/curand_mtgp32dc_p_11213.h" "$(@D)/cuda/include/curand_mtgp32dc_p_11213.h" && cp "/usr/local/cuda-9.0/include/curand_normal.h" "$(@D)/cuda/include/curand_normal.h" && cp "/usr/local/cuda-9.0/include/curand_normal_static.h" "$(@D)/cuda/include/curand_normal_static.h" && cp "/usr/local/cuda-9.0/include/curand_philox4x32_x.h" "$(@D)/cuda/include/curand_philox4x32_x.h" && cp "/usr/local/cuda-9.0/include/curand_poisson.h" "$(@D)/cuda/include/curand_poisson.h" && cp "/usr/local/cuda-9.0/include/curand_precalc.h" "$(@D)/cuda/include/curand_precalc.h" && cp "/usr/local/cuda-9.0/include/curand_uniform.h" "$(@D)/cuda/include/curand_uniform.h" && cp "/usr/local/cuda-9.0/include/cusolverDn.h" "$(@D)/cuda/include/cusolverDn.h" && cp "/usr/local/cuda-9.0/include/cusolverRf.h" "$(@D)/cuda/include/cusolverRf.h" && cp "/usr/local/cuda-9.0/include/cusolverSp.h" "$(@D)/cuda/include/cusolverSp.h" && cp "/usr/local/cuda-9.0/include/cusolverSp_LOWLEVEL_PREVIEW.h" "$(@D)/cuda/include/cusolverSp_LOWLEVEL_PREVIEW.h" && cp "/usr/local/cuda-9.0/include/cusolver_common.h" "$(@D)/cuda/include/cusolver_common.h" && cp "/usr/local/cuda-9.0/include/cusparse.h" "$(@D)/cuda/include/cusparse.h" && cp "/usr/local/cuda-9.0/include/cusparse_v2.h" "$(@D)/cuda/include/cusparse_v2.h" && cp "/usr/local/cuda-9.0/include/device_atomic_functions.h" "$(@D)/cuda/include/device_atomic_functions.h" && cp "/usr/local/cuda-9.0/include/device_atomic_functions.hpp" "$(@D)/cuda/include/device_atomic_functions.hpp" && cp "/usr/local/cuda-9.0/include/device_double_functions.h" "$(@D)/cuda/include/device_double_functions.h" && cp "/usr/local/cuda-9.0/include/device_double_functions.hpp" "$(@D)/cuda/include/device_double_functions.hpp" && cp "/usr/local/cuda-9.0/include/device_functions.h" "$(@D)/cuda/include/device_functions.h" && cp "/usr/local/cuda-9.0/include/device_functions.hpp" "$(@D)/cuda/include/device_functions.hpp" && cp "/usr/local/cuda-9.0/include/device_functions_decls.h" "$(@D)/cuda/include/device_functions_decls.h" && cp "/usr/local/cuda-9.0/include/device_launch_parameters.h" "$(@D)/cuda/include/device_launch_parameters.h" && cp "/usr/local/cuda-9.0/include/device_types.h" "$(@D)/cuda/include/device_types.h" && cp "/usr/local/cuda-9.0/include/driver_functions.h" "$(@D)/cuda/include/driver_functions.h" && cp "/usr/local/cuda-9.0/include/driver_types.h" "$(@D)/cuda/include/driver_types.h" && cp "/usr/local/cuda-9.0/include/dynlink_cuda.h" "$(@D)/cuda/include/dynlink_cuda.h" && cp "/usr/local/cuda-9.0/include/dynlink_cuda_cuda.h" "$(@D)/cuda/include/dynlink_cuda_cuda.h" && cp "/usr/local/cuda-9.0/include/dynlink_cuviddec.h" "$(@D)/cuda/include/dynlink_cuviddec.h" && cp "/usr/local/cuda-9.0/include/dynlink_nvcuvid.h" "$(@D)/cuda/include/dynlink_nvcuvid.h" && cp "/usr/local/cuda-9.0/include/fatBinaryCtl.h" "$(@D)/cuda/include/fatBinaryCtl.h" && cp "/usr/local/cuda-9.0/include/fatbinary.h" "$(@D)/cuda/include/fatbinary.h" && cp "/usr/local/cuda-9.0/include/host_config.h" "$(@D)/cuda/include/host_config.h" && cp "/usr/local/cuda-9.0/include/host_defines.h" "$(@D)/cuda/include/host_defines.h" && cp "/usr/local/cuda-9.0/include/library_types.h" "$(@D)/cuda/include/library_types.h" && cp "/usr/local/cuda-9.0/include/math_constants.h" "$(@D)/cuda/include/math_constants.h" && cp "/usr/local/cuda-9.0/include/math_functions.h" "$(@D)/cuda/include/math_functions.h" && cp "/usr/local/cuda-9.0/include/math_functions.hpp" "$(@D)/cuda/include/math_functions.hpp" && cp "/usr/local/cuda-9.0/include/math_functions_dbl_ptx3.h" "$(@D)/cuda/include/math_functions_dbl_ptx3.h" && cp "/usr/local/cuda-9.0/include/math_functions_dbl_ptx3.hpp" "$(@D)/cuda/include/math_functions_dbl_ptx3.hpp" && cp "/usr/local/cuda-9.0/include/mma.h" "$(@D)/cuda/include/mma.h" && cp "/usr/local/cuda-9.0/include/npp.h" "$(@D)/cuda/include/npp.h" && cp "/usr/local/cuda-9.0/include/nppcore.h" "$(@D)/cuda/include/nppcore.h" && cp "/usr/local/cuda-9.0/include/nppdefs.h" "$(@D)/cuda/include/nppdefs.h" && cp "/usr/local/cuda-9.0/include/nppi.h" "$(@D)/cuda/include/nppi.h" && cp "/usr/local/cuda-9.0/include/nppi_arithmetic_and_logical_operations.h" "$(@D)/cuda/include/nppi_arithmetic_and_logical_operations.h" && cp "/usr/local/cuda-9.0/include/nppi_color_conversion.h" "$(@D)/cuda/include/nppi_color_conversion.h" && cp "/usr/local/cuda-9.0/include/nppi_compression_functions.h" "$(@D)/cuda/include/nppi_compression_functions.h" && cp "/usr/local/cuda-9.0/include/nppi_computer_vision.h" "$(@D)/cuda/include/nppi_computer_vision.h" && cp "/usr/local/cuda-9.0/include/nppi_data_exchange_and_initialization.h" "$(@D)/cuda/include/nppi_data_exchange_and_initialization.h" && cp "/usr/local/cuda-9.0/include/nppi_filtering_functions.h" "$(@D)/cuda/include/nppi_filtering_functions.h" && cp "/usr/local/cuda-9.0/include/nppi_geometry_transforms.h" "$(@D)/cuda/include/nppi_geometry_transforms.h" && cp "/usr/local/cuda-9.0/include/nppi_linear_transforms.h" "$(@D)/cuda/include/nppi_linear_transforms.h" && cp "/usr/local/cuda-9.0/include/nppi_morphological_operations.h" "$(@D)/cuda/include/nppi_morphological_operations.h" && cp "/usr/local/cuda-9.0/include/nppi_statistics_functions.h" "$(@D)/cuda/include/nppi_statistics_functions.h" && cp "/usr/local/cuda-9.0/include/nppi_support_functions.h" "$(@D)/cuda/include/nppi_support_functions.h" && cp "/usr/local/cuda-9.0/include/nppi_threshold_and_compare_operations.h" "$(@D)/cuda/include/nppi_threshold_and_compare_operations.h" && cp "/usr/local/cuda-9.0/include/npps.h" "$(@D)/cuda/include/npps.h" && cp "/usr/local/cuda-9.0/include/npps_arithmetic_and_logical_operations.h" "$(@D)/cuda/include/npps_arithmetic_and_logical_operations.h" && cp "/usr/local/cuda-9.0/include/npps_conversion_functions.h" "$(@D)/cuda/include/npps_conversion_functions.h" && cp "/usr/local/cuda-9.0/include/npps_filtering_functions.h" "$(@D)/cuda/include/npps_filtering_functions.h" && cp "/usr/local/cuda-9.0/include/npps_initialization.h" "$(@D)/cuda/include/npps_initialization.h" && cp "/usr/local/cuda-9.0/include/npps_statistics_functions.h" "$(@D)/cuda/include/npps_statistics_functions.h" && cp "/usr/local/cuda-9.0/include/npps_support_functions.h" "$(@D)/cuda/include/npps_support_functions.h" && cp "/usr/local/cuda-9.0/include/nppversion.h" "$(@D)/cuda/include/nppversion.h" && cp "/usr/local/cuda-9.0/include/nvToolsExt.h" "$(@D)/cuda/include/nvToolsExt.h" && cp "/usr/local/cuda-9.0/include/nvToolsExtCuda.h" "$(@D)/cuda/include/nvToolsExtCuda.h" && cp "/usr/local/cuda-9.0/include/nvToolsExtCudaRt.h" "$(@D)/cuda/include/nvToolsExtCudaRt.h" && cp "/usr/local/cuda-9.0/include/nvToolsExtMeta.h" "$(@D)/cuda/include/nvToolsExtMeta.h" && cp "/usr/local/cuda-9.0/include/nvToolsExtSync.h" "$(@D)/cuda/include/nvToolsExtSync.h" && cp "/usr/local/cuda-9.0/include/nvblas.h" "$(@D)/cuda/include/nvblas.h" && cp "/usr/local/cuda-9.0/include/nvfunctional" "$(@D)/cuda/include/nvfunctional" && cp "/usr/local/cuda-9.0/include/nvgraph.h" "$(@D)/cuda/include/nvgraph.h" && cp "/usr/local/cuda-9.0/include/nvml.h" "$(@D)/cuda/include/nvml.h" && cp "/usr/local/cuda-9.0/include/nvrtc.h" "$(@D)/cuda/include/nvrtc.h" && cp "/usr/local/cuda-9.0/include/sm_20_atomic_functions.h" "$(@D)/cuda/include/sm_20_atomic_functions.h" && cp "/usr/local/cuda-9.0/include/sm_20_atomic_functions.hpp" "$(@D)/cuda/include/sm_20_atomic_functions.hpp" && cp "/usr/local/cuda-9.0/include/sm_20_intrinsics.h" "$(@D)/cuda/include/sm_20_intrinsics.h" && cp "/usr/local/cuda-9.0/include/sm_20_intrinsics.hpp" "$(@D)/cuda/include/sm_20_intrinsics.hpp" && cp "/usr/local/cuda-9.0/include/sm_30_intrinsics.h" "$(@D)/cuda/include/sm_30_intrinsics.h" && cp "/usr/local/cuda-9.0/include/sm_30_intrinsics.hpp" "$(@D)/cuda/include/sm_30_intrinsics.hpp" && cp "/usr/local/cuda-9.0/include/sm_32_atomic_functions.h" "$(@D)/cuda/include/sm_32_atomic_functions.h" && cp "/usr/local/cuda-9.0/include/sm_32_atomic_functions.hpp" "$(@D)/cuda/include/sm_32_atomic_functions.hpp" && cp "/usr/local/cuda-9.0/include/sm_32_intrinsics.h" "$(@D)/cuda/include/sm_32_intrinsics.h" && cp "/usr/local/cuda-9.0/include/sm_32_intrinsics.hpp" "$(@D)/cuda/include/sm_32_intrinsics.hpp" && cp "/usr/local/cuda-9.0/include/sm_35_atomic_functions.h" "$(@D)/cuda/include/sm_35_atomic_functions.h" && cp "/usr/local/cuda-9.0/include/sm_35_intrinsics.h" "$(@D)/cuda/include/sm_35_intrinsics.h" && cp "/usr/local/cuda-9.0/include/sm_60_atomic_functions.h" "$(@D)/cuda/include/sm_60_atomic_functions.h" && cp "/usr/local/cuda-9.0/include/sm_60_atomic_functions.hpp" "$(@D)/cuda/include/sm_60_atomic_functions.hpp" && cp "/usr/local/cuda-9.0/include/sm_61_intrinsics.h" "$(@D)/cuda/include/sm_61_intrinsics.h" && cp "/usr/local/cuda-9.0/include/sm_61_intrinsics.hpp" "$(@D)/cuda/include/sm_61_intrinsics.hpp" && cp "/usr/local/cuda-9.0/include/sobol_direction_vectors.h" "$(@D)/cuda/include/sobol_direction_vectors.h" && cp "/usr/local/cuda-9.0/include/surface_functions.h" "$(@D)/cuda/include/surface_functions.h" && cp "/usr/local/cuda-9.0/include/surface_functions.hpp" "$(@D)/cuda/include/surface_functions.hpp" && cp "/usr/local/cuda-9.0/include/surface_indirect_functions.h" "$(@D)/cuda/include/surface_indirect_functions.h" && cp "/usr/local/cuda-9.0/include/surface_indirect_functions.hpp" "$(@D)/cuda/include/surface_indirect_functions.hpp" && cp "/usr/local/cuda-9.0/include/surface_types.h" "$(@D)/cuda/include/surface_types.h" && cp "/usr/local/cuda-9.0/include/texture_fetch_functions.h" "$(@D)/cuda/include/texture_fetch_functions.h" && cp "/usr/local/cuda-9.0/include/texture_fetch_functions.hpp" "$(@D)/cuda/include/texture_fetch_functions.hpp" && cp "/usr/local/cuda-9.0/include/texture_indirect_functions.h" "$(@D)/cuda/include/texture_indirect_functions.h" && cp "/usr/local/cuda-9.0/include/texture_indirect_functions.hpp" "$(@D)/cuda/include/texture_indirect_functions.hpp" && cp "/usr/local/cuda-9.0/include/texture_types.h" "$(@D)/cuda/include/texture_types.h" && cp "/usr/local/cuda-9.0/include/thrust/adjacent_difference.h" "$(@D)/cuda/include/thrust/adjacent_difference.h" && cp "/usr/local/cuda-9.0/include/thrust/advance.h" "$(@D)/cuda/include/thrust/advance.h" && cp "/usr/local/cuda-9.0/include/thrust/binary_search.h" "$(@D)/cuda/include/thrust/binary_search.h" && cp "/usr/local/cuda-9.0/include/thrust/complex.h" "$(@D)/cuda/include/thrust/complex.h" && cp "/usr/local/cuda-9.0/include/thrust/copy.h" "$(@D)/cuda/include/thrust/copy.h" && cp "/usr/local/cuda-9.0/include/thrust/count.h" "$(@D)/cuda/include/thrust/count.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/adjacent_difference.inl" "$(@D)/cuda/include/thrust/detail/adjacent_difference.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/advance.inl" "$(@D)/cuda/include/thrust/detail/advance.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/allocator_traits.h" "$(@D)/cuda/include/thrust/detail/allocator/allocator_traits.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/allocator_traits.inl" "$(@D)/cuda/include/thrust/detail/allocator/allocator_traits.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/copy_construct_range.h" "$(@D)/cuda/include/thrust/detail/allocator/copy_construct_range.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/copy_construct_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/copy_construct_range.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/default_construct_range.h" "$(@D)/cuda/include/thrust/detail/allocator/default_construct_range.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/default_construct_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/default_construct_range.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/destroy_range.h" "$(@D)/cuda/include/thrust/detail/allocator/destroy_range.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/destroy_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/destroy_range.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/fill_construct_range.h" "$(@D)/cuda/include/thrust/detail/allocator/fill_construct_range.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/fill_construct_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/fill_construct_range.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/malloc_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/malloc_allocator.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/malloc_allocator.inl" "$(@D)/cuda/include/thrust/detail/allocator/malloc_allocator.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/no_throw_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/no_throw_allocator.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/tagged_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/tagged_allocator.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/tagged_allocator.inl" "$(@D)/cuda/include/thrust/detail/allocator/tagged_allocator.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/temporary_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/temporary_allocator.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/allocator/temporary_allocator.inl" "$(@D)/cuda/include/thrust/detail/allocator/temporary_allocator.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/binary_search.inl" "$(@D)/cuda/include/thrust/detail/binary_search.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/arithmetic.h" "$(@D)/cuda/include/thrust/detail/complex/arithmetic.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/c99math.h" "$(@D)/cuda/include/thrust/detail/complex/c99math.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/catrig.h" "$(@D)/cuda/include/thrust/detail/complex/catrig.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/catrigf.h" "$(@D)/cuda/include/thrust/detail/complex/catrigf.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/ccosh.h" "$(@D)/cuda/include/thrust/detail/complex/ccosh.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/ccoshf.h" "$(@D)/cuda/include/thrust/detail/complex/ccoshf.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/cexp.h" "$(@D)/cuda/include/thrust/detail/complex/cexp.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/cexpf.h" "$(@D)/cuda/include/thrust/detail/complex/cexpf.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/clog.h" "$(@D)/cuda/include/thrust/detail/complex/clog.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/clogf.h" "$(@D)/cuda/include/thrust/detail/complex/clogf.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/complex.inl" "$(@D)/cuda/include/thrust/detail/complex/complex.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/cpow.h" "$(@D)/cuda/include/thrust/detail/complex/cpow.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/cpowf.h" "$(@D)/cuda/include/thrust/detail/complex/cpowf.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/cproj.h" "$(@D)/cuda/include/thrust/detail/complex/cproj.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/csinh.h" "$(@D)/cuda/include/thrust/detail/complex/csinh.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/csinhf.h" "$(@D)/cuda/include/thrust/detail/complex/csinhf.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/csqrt.h" "$(@D)/cuda/include/thrust/detail/complex/csqrt.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/csqrtf.h" "$(@D)/cuda/include/thrust/detail/complex/csqrtf.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/ctanh.h" "$(@D)/cuda/include/thrust/detail/complex/ctanh.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/ctanhf.h" "$(@D)/cuda/include/thrust/detail/complex/ctanhf.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/math_private.h" "$(@D)/cuda/include/thrust/detail/complex/math_private.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/complex/stream.h" "$(@D)/cuda/include/thrust/detail/complex/stream.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config.h" "$(@D)/cuda/include/thrust/detail/config.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/compiler.h" "$(@D)/cuda/include/thrust/detail/config/compiler.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/compiler_fence.h" "$(@D)/cuda/include/thrust/detail/config/compiler_fence.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/config.h" "$(@D)/cuda/include/thrust/detail/config/config.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/debug.h" "$(@D)/cuda/include/thrust/detail/config/debug.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/device_system.h" "$(@D)/cuda/include/thrust/detail/config/device_system.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/exec_check_disable.h" "$(@D)/cuda/include/thrust/detail/config/exec_check_disable.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/forceinline.h" "$(@D)/cuda/include/thrust/detail/config/forceinline.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/global_workarounds.h" "$(@D)/cuda/include/thrust/detail/config/global_workarounds.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/host_device.h" "$(@D)/cuda/include/thrust/detail/config/host_device.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/host_system.h" "$(@D)/cuda/include/thrust/detail/config/host_system.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/config/simple_defines.h" "$(@D)/cuda/include/thrust/detail/config/simple_defines.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/contiguous_storage.h" "$(@D)/cuda/include/thrust/detail/contiguous_storage.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/contiguous_storage.inl" "$(@D)/cuda/include/thrust/detail/contiguous_storage.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/copy.h" "$(@D)/cuda/include/thrust/detail/copy.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/copy.inl" "$(@D)/cuda/include/thrust/detail/copy.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/copy_if.h" "$(@D)/cuda/include/thrust/detail/copy_if.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/copy_if.inl" "$(@D)/cuda/include/thrust/detail/copy_if.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/count.inl" "$(@D)/cuda/include/thrust/detail/count.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/cstdint.h" "$(@D)/cuda/include/thrust/detail/cstdint.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/device_delete.inl" "$(@D)/cuda/include/thrust/detail/device_delete.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/device_free.inl" "$(@D)/cuda/include/thrust/detail/device_free.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/device_malloc.inl" "$(@D)/cuda/include/thrust/detail/device_malloc.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/device_new.inl" "$(@D)/cuda/include/thrust/detail/device_new.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/device_ptr.inl" "$(@D)/cuda/include/thrust/detail/device_ptr.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/device_reference.inl" "$(@D)/cuda/include/thrust/detail/device_reference.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/device_vector.inl" "$(@D)/cuda/include/thrust/detail/device_vector.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/dispatch/is_trivial_copy.h" "$(@D)/cuda/include/thrust/detail/dispatch/is_trivial_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/distance.inl" "$(@D)/cuda/include/thrust/detail/distance.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/equal.inl" "$(@D)/cuda/include/thrust/detail/equal.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/execute_with_allocator.h" "$(@D)/cuda/include/thrust/detail/execute_with_allocator.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/execution_policy.h" "$(@D)/cuda/include/thrust/detail/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/extrema.inl" "$(@D)/cuda/include/thrust/detail/extrema.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/fill.inl" "$(@D)/cuda/include/thrust/detail/fill.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/find.inl" "$(@D)/cuda/include/thrust/detail/find.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/for_each.inl" "$(@D)/cuda/include/thrust/detail/for_each.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/function.h" "$(@D)/cuda/include/thrust/detail/function.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional.inl" "$(@D)/cuda/include/thrust/detail/functional.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/actor.h" "$(@D)/cuda/include/thrust/detail/functional/actor.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/actor.inl" "$(@D)/cuda/include/thrust/detail/functional/actor.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/argument.h" "$(@D)/cuda/include/thrust/detail/functional/argument.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/composite.h" "$(@D)/cuda/include/thrust/detail/functional/composite.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/arithmetic_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/arithmetic_operators.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/assignment_operator.h" "$(@D)/cuda/include/thrust/detail/functional/operators/assignment_operator.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/bitwise_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/bitwise_operators.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/compound_assignment_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/compound_assignment_operators.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/logical_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/logical_operators.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/operator_adaptors.h" "$(@D)/cuda/include/thrust/detail/functional/operators/operator_adaptors.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/relational_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/relational_operators.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/placeholder.h" "$(@D)/cuda/include/thrust/detail/functional/placeholder.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/functional/value.h" "$(@D)/cuda/include/thrust/detail/functional/value.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/gather.inl" "$(@D)/cuda/include/thrust/detail/gather.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/generate.inl" "$(@D)/cuda/include/thrust/detail/generate.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/get_iterator_value.h" "$(@D)/cuda/include/thrust/detail/get_iterator_value.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/host_vector.inl" "$(@D)/cuda/include/thrust/detail/host_vector.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/inner_product.inl" "$(@D)/cuda/include/thrust/detail/inner_product.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/integer_math.h" "$(@D)/cuda/include/thrust/detail/integer_math.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/integer_traits.h" "$(@D)/cuda/include/thrust/detail/integer_traits.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/internal_functional.h" "$(@D)/cuda/include/thrust/detail/internal_functional.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/logical.inl" "$(@D)/cuda/include/thrust/detail/logical.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/detail/malloc_and_free.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/merge.inl" "$(@D)/cuda/include/thrust/detail/merge.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/minmax.h" "$(@D)/cuda/include/thrust/detail/minmax.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/mismatch.inl" "$(@D)/cuda/include/thrust/detail/mismatch.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/mpl/math.h" "$(@D)/cuda/include/thrust/detail/mpl/math.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/numeric_traits.h" "$(@D)/cuda/include/thrust/detail/numeric_traits.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/overlapped_copy.h" "$(@D)/cuda/include/thrust/detail/overlapped_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/pair.inl" "$(@D)/cuda/include/thrust/detail/pair.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/partition.inl" "$(@D)/cuda/include/thrust/detail/partition.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/pointer.h" "$(@D)/cuda/include/thrust/detail/pointer.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/pointer.inl" "$(@D)/cuda/include/thrust/detail/pointer.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/range/head_flags.h" "$(@D)/cuda/include/thrust/detail/range/head_flags.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/range/tail_flags.h" "$(@D)/cuda/include/thrust/detail/range/tail_flags.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/raw_pointer_cast.h" "$(@D)/cuda/include/thrust/detail/raw_pointer_cast.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/raw_reference_cast.h" "$(@D)/cuda/include/thrust/detail/raw_reference_cast.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/reduce.inl" "$(@D)/cuda/include/thrust/detail/reduce.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/reference.h" "$(@D)/cuda/include/thrust/detail/reference.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/reference.inl" "$(@D)/cuda/include/thrust/detail/reference.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/reference_forward_declaration.h" "$(@D)/cuda/include/thrust/detail/reference_forward_declaration.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/remove.inl" "$(@D)/cuda/include/thrust/detail/remove.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/replace.inl" "$(@D)/cuda/include/thrust/detail/replace.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/reverse.inl" "$(@D)/cuda/include/thrust/detail/reverse.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/scan.inl" "$(@D)/cuda/include/thrust/detail/scan.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/scatter.inl" "$(@D)/cuda/include/thrust/detail/scatter.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/seq.h" "$(@D)/cuda/include/thrust/detail/seq.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/sequence.inl" "$(@D)/cuda/include/thrust/detail/sequence.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/set_operations.inl" "$(@D)/cuda/include/thrust/detail/set_operations.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/sort.inl" "$(@D)/cuda/include/thrust/detail/sort.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/static_assert.h" "$(@D)/cuda/include/thrust/detail/static_assert.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/static_map.h" "$(@D)/cuda/include/thrust/detail/static_map.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/swap.h" "$(@D)/cuda/include/thrust/detail/swap.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/swap.inl" "$(@D)/cuda/include/thrust/detail/swap.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/swap_ranges.inl" "$(@D)/cuda/include/thrust/detail/swap_ranges.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/tabulate.inl" "$(@D)/cuda/include/thrust/detail/tabulate.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/temporary_array.h" "$(@D)/cuda/include/thrust/detail/temporary_array.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/temporary_array.inl" "$(@D)/cuda/include/thrust/detail/temporary_array.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/detail/temporary_buffer.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/transform.inl" "$(@D)/cuda/include/thrust/detail/transform.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/transform_reduce.inl" "$(@D)/cuda/include/thrust/detail/transform_reduce.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/transform_scan.inl" "$(@D)/cuda/include/thrust/detail/transform_scan.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/trivial_sequence.h" "$(@D)/cuda/include/thrust/detail/trivial_sequence.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/tuple.inl" "$(@D)/cuda/include/thrust/detail/tuple.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/tuple_meta_transform.h" "$(@D)/cuda/include/thrust/detail/tuple_meta_transform.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/tuple_transform.h" "$(@D)/cuda/include/thrust/detail/tuple_transform.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits.h" "$(@D)/cuda/include/thrust/detail/type_traits.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/algorithm/intermediate_type_from_function_and_iterators.h" "$(@D)/cuda/include/thrust/detail/type_traits/algorithm/intermediate_type_from_function_and_iterators.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/function_traits.h" "$(@D)/cuda/include/thrust/detail/type_traits/function_traits.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/has_member_function.h" "$(@D)/cuda/include/thrust/detail/type_traits/has_member_function.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/has_nested_type.h" "$(@D)/cuda/include/thrust/detail/type_traits/has_nested_type.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/has_trivial_assign.h" "$(@D)/cuda/include/thrust/detail/type_traits/has_trivial_assign.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/is_call_possible.h" "$(@D)/cuda/include/thrust/detail/type_traits/is_call_possible.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/is_metafunction_defined.h" "$(@D)/cuda/include/thrust/detail/type_traits/is_metafunction_defined.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/iterator/is_discard_iterator.h" "$(@D)/cuda/include/thrust/detail/type_traits/iterator/is_discard_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/iterator/is_output_iterator.h" "$(@D)/cuda/include/thrust/detail/type_traits/iterator/is_output_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/minimum_type.h" "$(@D)/cuda/include/thrust/detail/type_traits/minimum_type.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/pointer_traits.h" "$(@D)/cuda/include/thrust/detail/type_traits/pointer_traits.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/type_traits/result_of_adaptable_function.h" "$(@D)/cuda/include/thrust/detail/type_traits/result_of_adaptable_function.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/uninitialized_copy.inl" "$(@D)/cuda/include/thrust/detail/uninitialized_copy.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/uninitialized_fill.inl" "$(@D)/cuda/include/thrust/detail/uninitialized_fill.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/unique.inl" "$(@D)/cuda/include/thrust/detail/unique.inl" && cp "/usr/local/cuda-9.0/include/thrust/detail/use_default.h" "$(@D)/cuda/include/thrust/detail/use_default.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/util/align.h" "$(@D)/cuda/include/thrust/detail/util/align.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/util/blocking.h" "$(@D)/cuda/include/thrust/detail/util/blocking.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/vector_base.h" "$(@D)/cuda/include/thrust/detail/vector_base.h" && cp "/usr/local/cuda-9.0/include/thrust/detail/vector_base.inl" "$(@D)/cuda/include/thrust/detail/vector_base.inl" && cp "/usr/local/cuda-9.0/include/thrust/device_allocator.h" "$(@D)/cuda/include/thrust/device_allocator.h" && cp "/usr/local/cuda-9.0/include/thrust/device_delete.h" "$(@D)/cuda/include/thrust/device_delete.h" && cp "/usr/local/cuda-9.0/include/thrust/device_free.h" "$(@D)/cuda/include/thrust/device_free.h" && cp "/usr/local/cuda-9.0/include/thrust/device_malloc.h" "$(@D)/cuda/include/thrust/device_malloc.h" && cp "/usr/local/cuda-9.0/include/thrust/device_malloc_allocator.h" "$(@D)/cuda/include/thrust/device_malloc_allocator.h" && cp "/usr/local/cuda-9.0/include/thrust/device_new.h" "$(@D)/cuda/include/thrust/device_new.h" && cp "/usr/local/cuda-9.0/include/thrust/device_new_allocator.h" "$(@D)/cuda/include/thrust/device_new_allocator.h" && cp "/usr/local/cuda-9.0/include/thrust/device_ptr.h" "$(@D)/cuda/include/thrust/device_ptr.h" && cp "/usr/local/cuda-9.0/include/thrust/device_reference.h" "$(@D)/cuda/include/thrust/device_reference.h" && cp "/usr/local/cuda-9.0/include/thrust/device_vector.h" "$(@D)/cuda/include/thrust/device_vector.h" && cp "/usr/local/cuda-9.0/include/thrust/distance.h" "$(@D)/cuda/include/thrust/distance.h" && cp "/usr/local/cuda-9.0/include/thrust/equal.h" "$(@D)/cuda/include/thrust/equal.h" && cp "/usr/local/cuda-9.0/include/thrust/execution_policy.h" "$(@D)/cuda/include/thrust/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/extrema.h" "$(@D)/cuda/include/thrust/extrema.h" && cp "/usr/local/cuda-9.0/include/thrust/fill.h" "$(@D)/cuda/include/thrust/fill.h" && cp "/usr/local/cuda-9.0/include/thrust/find.h" "$(@D)/cuda/include/thrust/find.h" && cp "/usr/local/cuda-9.0/include/thrust/for_each.h" "$(@D)/cuda/include/thrust/for_each.h" && cp "/usr/local/cuda-9.0/include/thrust/functional.h" "$(@D)/cuda/include/thrust/functional.h" && cp "/usr/local/cuda-9.0/include/thrust/gather.h" "$(@D)/cuda/include/thrust/gather.h" && cp "/usr/local/cuda-9.0/include/thrust/generate.h" "$(@D)/cuda/include/thrust/generate.h" && cp "/usr/local/cuda-9.0/include/thrust/host_vector.h" "$(@D)/cuda/include/thrust/host_vector.h" && cp "/usr/local/cuda-9.0/include/thrust/inner_product.h" "$(@D)/cuda/include/thrust/inner_product.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/constant_iterator.h" "$(@D)/cuda/include/thrust/iterator/constant_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/counting_iterator.h" "$(@D)/cuda/include/thrust/iterator/counting_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/any_assign.h" "$(@D)/cuda/include/thrust/iterator/detail/any_assign.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/any_system_tag.h" "$(@D)/cuda/include/thrust/iterator/detail/any_system_tag.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/constant_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/constant_iterator_base.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/counting_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/counting_iterator.inl" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/device_system_tag.h" "$(@D)/cuda/include/thrust/iterator/detail/device_system_tag.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/discard_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/discard_iterator_base.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/distance_from_result.h" "$(@D)/cuda/include/thrust/iterator/detail/distance_from_result.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/host_system_tag.h" "$(@D)/cuda/include/thrust/iterator/detail/host_system_tag.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/is_iterator_category.h" "$(@D)/cuda/include/thrust/iterator/detail/is_iterator_category.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/is_trivial_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/is_trivial_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_adaptor_base.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_adaptor_base.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_category_to_system.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_category_to_system.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_category_to_traversal.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_category_to_traversal.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_category_with_system_and_traversal.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_category_with_system_and_traversal.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_facade_category.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_facade_category.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_traits.inl" "$(@D)/cuda/include/thrust/iterator/detail/iterator_traits.inl" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_traversal_tags.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_traversal_tags.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/join_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/join_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/minimum_category.h" "$(@D)/cuda/include/thrust/iterator/detail/minimum_category.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/minimum_system.h" "$(@D)/cuda/include/thrust/iterator/detail/minimum_system.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/normal_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/normal_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/permutation_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/permutation_iterator_base.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/retag.h" "$(@D)/cuda/include/thrust/iterator/detail/retag.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/reverse_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/reverse_iterator.inl" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/reverse_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/reverse_iterator_base.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/tagged_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/tagged_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/transform_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/transform_iterator.inl" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/transform_output_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/transform_output_iterator.inl" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/tuple_of_iterator_references.h" "$(@D)/cuda/include/thrust/iterator/detail/tuple_of_iterator_references.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/universal_categories.h" "$(@D)/cuda/include/thrust/iterator/detail/universal_categories.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/zip_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/zip_iterator.inl" && cp "/usr/local/cuda-9.0/include/thrust/iterator/detail/zip_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/zip_iterator_base.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/discard_iterator.h" "$(@D)/cuda/include/thrust/iterator/discard_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/iterator_adaptor.h" "$(@D)/cuda/include/thrust/iterator/iterator_adaptor.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/iterator_categories.h" "$(@D)/cuda/include/thrust/iterator/iterator_categories.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/iterator_facade.h" "$(@D)/cuda/include/thrust/iterator/iterator_facade.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/iterator_traits.h" "$(@D)/cuda/include/thrust/iterator/iterator_traits.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/permutation_iterator.h" "$(@D)/cuda/include/thrust/iterator/permutation_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/retag.h" "$(@D)/cuda/include/thrust/iterator/retag.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/reverse_iterator.h" "$(@D)/cuda/include/thrust/iterator/reverse_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/transform_iterator.h" "$(@D)/cuda/include/thrust/iterator/transform_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/transform_output_iterator.h" "$(@D)/cuda/include/thrust/iterator/transform_output_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/iterator/zip_iterator.h" "$(@D)/cuda/include/thrust/iterator/zip_iterator.h" && cp "/usr/local/cuda-9.0/include/thrust/logical.h" "$(@D)/cuda/include/thrust/logical.h" && cp "/usr/local/cuda-9.0/include/thrust/memory.h" "$(@D)/cuda/include/thrust/memory.h" && cp "/usr/local/cuda-9.0/include/thrust/merge.h" "$(@D)/cuda/include/thrust/merge.h" && cp "/usr/local/cuda-9.0/include/thrust/mismatch.h" "$(@D)/cuda/include/thrust/mismatch.h" && cp "/usr/local/cuda-9.0/include/thrust/pair.h" "$(@D)/cuda/include/thrust/pair.h" && cp "/usr/local/cuda-9.0/include/thrust/partition.h" "$(@D)/cuda/include/thrust/partition.h" && cp "/usr/local/cuda-9.0/include/thrust/random.h" "$(@D)/cuda/include/thrust/random.h" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/discard_block_engine.inl" "$(@D)/cuda/include/thrust/random/detail/discard_block_engine.inl" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/linear_congruential_engine.inl" "$(@D)/cuda/include/thrust/random/detail/linear_congruential_engine.inl" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/linear_congruential_engine_discard.h" "$(@D)/cuda/include/thrust/random/detail/linear_congruential_engine_discard.h" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/linear_feedback_shift_engine.inl" "$(@D)/cuda/include/thrust/random/detail/linear_feedback_shift_engine.inl" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/linear_feedback_shift_engine_wordmask.h" "$(@D)/cuda/include/thrust/random/detail/linear_feedback_shift_engine_wordmask.h" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/mod.h" "$(@D)/cuda/include/thrust/random/detail/mod.h" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/normal_distribution.inl" "$(@D)/cuda/include/thrust/random/detail/normal_distribution.inl" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/normal_distribution_base.h" "$(@D)/cuda/include/thrust/random/detail/normal_distribution_base.h" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/random_core_access.h" "$(@D)/cuda/include/thrust/random/detail/random_core_access.h" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/subtract_with_carry_engine.inl" "$(@D)/cuda/include/thrust/random/detail/subtract_with_carry_engine.inl" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/uniform_int_distribution.inl" "$(@D)/cuda/include/thrust/random/detail/uniform_int_distribution.inl" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/uniform_real_distribution.inl" "$(@D)/cuda/include/thrust/random/detail/uniform_real_distribution.inl" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/xor_combine_engine.inl" "$(@D)/cuda/include/thrust/random/detail/xor_combine_engine.inl" && cp "/usr/local/cuda-9.0/include/thrust/random/detail/xor_combine_engine_max.h" "$(@D)/cuda/include/thrust/random/detail/xor_combine_engine_max.h" && cp "/usr/local/cuda-9.0/include/thrust/random/discard_block_engine.h" "$(@D)/cuda/include/thrust/random/discard_block_engine.h" && cp "/usr/local/cuda-9.0/include/thrust/random/linear_congruential_engine.h" "$(@D)/cuda/include/thrust/random/linear_congruential_engine.h" && cp "/usr/local/cuda-9.0/include/thrust/random/linear_feedback_shift_engine.h" "$(@D)/cuda/include/thrust/random/linear_feedback_shift_engine.h" && cp "/usr/local/cuda-9.0/include/thrust/random/normal_distribution.h" "$(@D)/cuda/include/thrust/random/normal_distribution.h" && cp "/usr/local/cuda-9.0/include/thrust/random/subtract_with_carry_engine.h" "$(@D)/cuda/include/thrust/random/subtract_with_carry_engine.h" && cp "/usr/local/cuda-9.0/include/thrust/random/uniform_int_distribution.h" "$(@D)/cuda/include/thrust/random/uniform_int_distribution.h" && cp "/usr/local/cuda-9.0/include/thrust/random/uniform_real_distribution.h" "$(@D)/cuda/include/thrust/random/uniform_real_distribution.h" && cp "/usr/local/cuda-9.0/include/thrust/random/xor_combine_engine.h" "$(@D)/cuda/include/thrust/random/xor_combine_engine.h" && cp "/usr/local/cuda-9.0/include/thrust/reduce.h" "$(@D)/cuda/include/thrust/reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/remove.h" "$(@D)/cuda/include/thrust/remove.h" && cp "/usr/local/cuda-9.0/include/thrust/replace.h" "$(@D)/cuda/include/thrust/replace.h" && cp "/usr/local/cuda-9.0/include/thrust/reverse.h" "$(@D)/cuda/include/thrust/reverse.h" && cp "/usr/local/cuda-9.0/include/thrust/scan.h" "$(@D)/cuda/include/thrust/scan.h" && cp "/usr/local/cuda-9.0/include/thrust/scatter.h" "$(@D)/cuda/include/thrust/scatter.h" && cp "/usr/local/cuda-9.0/include/thrust/sequence.h" "$(@D)/cuda/include/thrust/sequence.h" && cp "/usr/local/cuda-9.0/include/thrust/set_operations.h" "$(@D)/cuda/include/thrust/set_operations.h" && cp "/usr/local/cuda-9.0/include/thrust/sort.h" "$(@D)/cuda/include/thrust/sort.h" && cp "/usr/local/cuda-9.0/include/thrust/swap.h" "$(@D)/cuda/include/thrust/swap.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/cpp/detail/adjacent_difference.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/cpp/detail/assign_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/cpp/detail/binary_search.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/copy.h" "$(@D)/cuda/include/thrust/system/cpp/detail/copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/cpp/detail/copy_if.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/count.h" "$(@D)/cuda/include/thrust/system/cpp/detail/count.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/equal.h" "$(@D)/cuda/include/thrust/system/cpp/detail/equal.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/cpp/detail/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/extrema.h" "$(@D)/cuda/include/thrust/system/cpp/detail/extrema.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/fill.h" "$(@D)/cuda/include/thrust/system/cpp/detail/fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/find.h" "$(@D)/cuda/include/thrust/system/cpp/detail/find.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/for_each.h" "$(@D)/cuda/include/thrust/system/cpp/detail/for_each.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/gather.h" "$(@D)/cuda/include/thrust/system/cpp/detail/gather.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/generate.h" "$(@D)/cuda/include/thrust/system/cpp/detail/generate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/get_value.h" "$(@D)/cuda/include/thrust/system/cpp/detail/get_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/cpp/detail/inner_product.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/cpp/detail/iter_swap.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/logical.h" "$(@D)/cuda/include/thrust/system/cpp/detail/logical.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/cpp/detail/malloc_and_free.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/memory.inl" "$(@D)/cuda/include/thrust/system/cpp/detail/memory.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/merge.h" "$(@D)/cuda/include/thrust/system/cpp/detail/merge.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/cpp/detail/mismatch.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/par.h" "$(@D)/cuda/include/thrust/system/cpp/detail/par.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/partition.h" "$(@D)/cuda/include/thrust/system/cpp/detail/partition.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/reduce.h" "$(@D)/cuda/include/thrust/system/cpp/detail/reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/cpp/detail/reduce_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/remove.h" "$(@D)/cuda/include/thrust/system/cpp/detail/remove.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/replace.h" "$(@D)/cuda/include/thrust/system/cpp/detail/replace.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/reverse.h" "$(@D)/cuda/include/thrust/system/cpp/detail/reverse.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/scan.h" "$(@D)/cuda/include/thrust/system/cpp/detail/scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/cpp/detail/scan_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/scatter.h" "$(@D)/cuda/include/thrust/system/cpp/detail/scatter.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/sequence.h" "$(@D)/cuda/include/thrust/system/cpp/detail/sequence.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/cpp/detail/set_operations.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/sort.h" "$(@D)/cuda/include/thrust/system/cpp/detail/sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/cpp/detail/swap_ranges.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/cpp/detail/tabulate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/cpp/detail/temporary_buffer.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/transform.h" "$(@D)/cuda/include/thrust/system/cpp/detail/transform.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/cpp/detail/transform_reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/cpp/detail/transform_scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/cpp/detail/uninitialized_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/cpp/detail/uninitialized_fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/unique.h" "$(@D)/cuda/include/thrust/system/cpp/detail/unique.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/cpp/detail/unique_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/vector.inl" "$(@D)/cuda/include/thrust/system/cpp/detail/vector.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/execution_policy.h" "$(@D)/cuda/include/thrust/system/cpp/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/memory.h" "$(@D)/cuda/include/thrust/system/cpp/memory.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cpp/vector.h" "$(@D)/cuda/include/thrust/system/cpp/vector.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/config.h" "$(@D)/cuda/include/thrust/system/cuda/config.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/cuda/detail/adjacent_difference.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/cuda/detail/assign_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/cuda/detail/binary_search.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/copy.h" "$(@D)/cuda/include/thrust/system/cuda/detail/copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/cuda/detail/copy_if.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/core/agent_launcher.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/agent_launcher.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/core/alignment.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/alignment.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/core/triple_chevron_launch.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/triple_chevron_launch.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/core/util.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/util.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/count.h" "$(@D)/cuda/include/thrust/system/cuda/detail/count.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cross_system.h" "$(@D)/cuda/include/thrust/system/cuda/detail/cross_system.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_histogram.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_downsweep.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_downsweep.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_upsweep.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_upsweep.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_reduce.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_reduce_by_key.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_reduce_by_key.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_rle.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_rle.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_scan.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_segment_fixup.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_segment_fixup.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_select_if.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_select_if.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_spmv_csrt.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_spmv_csrt.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_spmv_orig.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_spmv_orig.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_spmv_row_based.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_spmv_row_based.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/single_pass_scan_operators.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/single_pass_scan_operators.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_adjacent_difference.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_adjacent_difference.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_discontinuity.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_discontinuity.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_exchange.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_exchange.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_histogram.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_load.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_load.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_radix_rank.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_radix_rank.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_radix_sort.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_raking_layout.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_raking_layout.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_reduce.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_scan.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_shuffle.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_shuffle.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_store.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_store.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_atomic.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_atomic.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_sort.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking_commutative_only.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking_commutative_only.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_warp_reductions.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_warp_reductions.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_raking.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_raking.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans2.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans2.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans3.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans3.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/cub.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/cub.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_histogram.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_partition.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_partition.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_radix_sort.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_reduce.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_run_length_encode.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_run_length_encode.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_scan.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_segmented_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_segmented_radix_sort.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_segmented_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_segmented_reduce.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_select.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_select.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_spmv.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_spmv.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_histogram.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_radix_sort.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce_by_key.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce_by_key.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_rle.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_rle.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_scan.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_select_if.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_select_if.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_csrt.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_csrt.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_orig.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_orig.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_row_based.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_row_based.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/grid/grid_barrier.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_barrier.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/grid/grid_even_share.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_even_share.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/grid/grid_mapping.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_mapping.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/grid/grid_queue.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_queue.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/host/mutex.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/host/mutex.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/arg_index_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/arg_index_input_iterator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/cache_modified_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/cache_modified_input_iterator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/cache_modified_output_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/cache_modified_output_iterator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/constant_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/constant_input_iterator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/counting_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/counting_input_iterator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/discard_output_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/discard_output_iterator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/tex_obj_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/tex_obj_input_iterator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/tex_ref_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/tex_ref_input_iterator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/transform_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/transform_input_iterator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_load.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_load.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_operators.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_operators.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_reduce.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_scan.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_search.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_search.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_store.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_store.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_allocator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_allocator.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_arch.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_arch.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_debug.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_debug.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_device.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_device.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_macro.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_macro.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_namespace.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_namespace.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_ptx.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_ptx.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_type.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_type.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_shfl.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_shfl.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_smem.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_smem.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_shfl.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_shfl.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_smem.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_smem.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/warp_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/warp_reduce.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/warp_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/warp_scan.cuh" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/equal.h" "$(@D)/cuda/include/thrust/system/cuda/detail/equal.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/error.inl" "$(@D)/cuda/include/thrust/system/cuda/detail/error.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/cuda/detail/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/extrema.h" "$(@D)/cuda/include/thrust/system/cuda/detail/extrema.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/fill.h" "$(@D)/cuda/include/thrust/system/cuda/detail/fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/find.h" "$(@D)/cuda/include/thrust/system/cuda/detail/find.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/for_each.h" "$(@D)/cuda/include/thrust/system/cuda/detail/for_each.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/gather.h" "$(@D)/cuda/include/thrust/system/cuda/detail/gather.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/generate.h" "$(@D)/cuda/include/thrust/system/cuda/detail/generate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/get_value.h" "$(@D)/cuda/include/thrust/system/cuda/detail/get_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/guarded_cuda_runtime_api.h" "$(@D)/cuda/include/thrust/system/cuda/detail/guarded_cuda_runtime_api.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/guarded_driver_types.h" "$(@D)/cuda/include/thrust/system/cuda/detail/guarded_driver_types.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/cuda/detail/inner_product.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/internal/copy_cross_system.h" "$(@D)/cuda/include/thrust/system/cuda/detail/internal/copy_cross_system.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/internal/copy_device_to_device.h" "$(@D)/cuda/include/thrust/system/cuda/detail/internal/copy_device_to_device.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/cuda/detail/iter_swap.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/logical.h" "$(@D)/cuda/include/thrust/system/cuda/detail/logical.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/cuda/detail/malloc_and_free.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/memory.inl" "$(@D)/cuda/include/thrust/system/cuda/detail/memory.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/memory_buffer.h" "$(@D)/cuda/include/thrust/system/cuda/detail/memory_buffer.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/merge.h" "$(@D)/cuda/include/thrust/system/cuda/detail/merge.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/cuda/detail/mismatch.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/par.h" "$(@D)/cuda/include/thrust/system/cuda/detail/par.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/par_to_seq.h" "$(@D)/cuda/include/thrust/system/cuda/detail/par_to_seq.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/parallel_for.h" "$(@D)/cuda/include/thrust/system/cuda/detail/parallel_for.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/partition.h" "$(@D)/cuda/include/thrust/system/cuda/detail/partition.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/reduce.h" "$(@D)/cuda/include/thrust/system/cuda/detail/reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/cuda/detail/reduce_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/remove.h" "$(@D)/cuda/include/thrust/system/cuda/detail/remove.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/replace.h" "$(@D)/cuda/include/thrust/system/cuda/detail/replace.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/reverse.h" "$(@D)/cuda/include/thrust/system/cuda/detail/reverse.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/scan.h" "$(@D)/cuda/include/thrust/system/cuda/detail/scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/cuda/detail/scan_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/scatter.h" "$(@D)/cuda/include/thrust/system/cuda/detail/scatter.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/sequence.h" "$(@D)/cuda/include/thrust/system/cuda/detail/sequence.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/cuda/detail/set_operations.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/sort.h" "$(@D)/cuda/include/thrust/system/cuda/detail/sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/cuda/detail/swap_ranges.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/cuda/detail/tabulate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/cuda/detail/temporary_buffer.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/terminate.h" "$(@D)/cuda/include/thrust/system/cuda/detail/terminate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/transform.h" "$(@D)/cuda/include/thrust/system/cuda/detail/transform.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/cuda/detail/transform_reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/cuda/detail/transform_scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/cuda/detail/uninitialized_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/cuda/detail/uninitialized_fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/unique.h" "$(@D)/cuda/include/thrust/system/cuda/detail/unique.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/cuda/detail/unique_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/util.h" "$(@D)/cuda/include/thrust/system/cuda/detail/util.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/vector.inl" "$(@D)/cuda/include/thrust/system/cuda/detail/vector.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/error.h" "$(@D)/cuda/include/thrust/system/cuda/error.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/execution_policy.h" "$(@D)/cuda/include/thrust/system/cuda/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/experimental/pinned_allocator.h" "$(@D)/cuda/include/thrust/system/cuda/experimental/pinned_allocator.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/memory.h" "$(@D)/cuda/include/thrust/system/cuda/memory.h" && cp "/usr/local/cuda-9.0/include/thrust/system/cuda/vector.h" "$(@D)/cuda/include/thrust/system/cuda/vector.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/detail/adl/adjacent_difference.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/assign_value.h" "$(@D)/cuda/include/thrust/system/detail/adl/assign_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/adl/binary_search.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/copy.h" "$(@D)/cuda/include/thrust/system/detail/adl/copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/copy_if.h" "$(@D)/cuda/include/thrust/system/detail/adl/copy_if.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/count.h" "$(@D)/cuda/include/thrust/system/detail/adl/count.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/equal.h" "$(@D)/cuda/include/thrust/system/detail/adl/equal.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/extrema.h" "$(@D)/cuda/include/thrust/system/detail/adl/extrema.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/fill.h" "$(@D)/cuda/include/thrust/system/detail/adl/fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/find.h" "$(@D)/cuda/include/thrust/system/detail/adl/find.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/for_each.h" "$(@D)/cuda/include/thrust/system/detail/adl/for_each.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/gather.h" "$(@D)/cuda/include/thrust/system/detail/adl/gather.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/generate.h" "$(@D)/cuda/include/thrust/system/detail/adl/generate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/get_value.h" "$(@D)/cuda/include/thrust/system/detail/adl/get_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/inner_product.h" "$(@D)/cuda/include/thrust/system/detail/adl/inner_product.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/iter_swap.h" "$(@D)/cuda/include/thrust/system/detail/adl/iter_swap.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/logical.h" "$(@D)/cuda/include/thrust/system/detail/adl/logical.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/detail/adl/malloc_and_free.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/merge.h" "$(@D)/cuda/include/thrust/system/detail/adl/merge.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/mismatch.h" "$(@D)/cuda/include/thrust/system/detail/adl/mismatch.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/partition.h" "$(@D)/cuda/include/thrust/system/detail/adl/partition.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/reduce.h" "$(@D)/cuda/include/thrust/system/detail/adl/reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/detail/adl/reduce_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/remove.h" "$(@D)/cuda/include/thrust/system/detail/adl/remove.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/replace.h" "$(@D)/cuda/include/thrust/system/detail/adl/replace.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/reverse.h" "$(@D)/cuda/include/thrust/system/detail/adl/reverse.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/scan.h" "$(@D)/cuda/include/thrust/system/detail/adl/scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/scan_by_key.h" "$(@D)/cuda/include/thrust/system/detail/adl/scan_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/scatter.h" "$(@D)/cuda/include/thrust/system/detail/adl/scatter.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/sequence.h" "$(@D)/cuda/include/thrust/system/detail/adl/sequence.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/set_operations.h" "$(@D)/cuda/include/thrust/system/detail/adl/set_operations.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/sort.h" "$(@D)/cuda/include/thrust/system/detail/adl/sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/swap_ranges.h" "$(@D)/cuda/include/thrust/system/detail/adl/swap_ranges.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/tabulate.h" "$(@D)/cuda/include/thrust/system/detail/adl/tabulate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/detail/adl/temporary_buffer.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/transform.h" "$(@D)/cuda/include/thrust/system/detail/adl/transform.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/transform_reduce.h" "$(@D)/cuda/include/thrust/system/detail/adl/transform_reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/transform_scan.h" "$(@D)/cuda/include/thrust/system/detail/adl/transform_scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/detail/adl/uninitialized_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/detail/adl/uninitialized_fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/unique.h" "$(@D)/cuda/include/thrust/system/detail/adl/unique.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/adl/unique_by_key.h" "$(@D)/cuda/include/thrust/system/detail/adl/unique_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/bad_alloc.h" "$(@D)/cuda/include/thrust/system/detail/bad_alloc.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/errno.h" "$(@D)/cuda/include/thrust/system/detail/errno.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/error_category.inl" "$(@D)/cuda/include/thrust/system/detail/error_category.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/error_code.inl" "$(@D)/cuda/include/thrust/system/detail/error_code.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/error_condition.inl" "$(@D)/cuda/include/thrust/system/detail/error_condition.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/detail/generic/adjacent_difference.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/adjacent_difference.inl" "$(@D)/cuda/include/thrust/system/detail/generic/adjacent_difference.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/advance.h" "$(@D)/cuda/include/thrust/system/detail/generic/advance.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/advance.inl" "$(@D)/cuda/include/thrust/system/detail/generic/advance.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/generic/binary_search.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/binary_search.inl" "$(@D)/cuda/include/thrust/system/detail/generic/binary_search.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/copy.h" "$(@D)/cuda/include/thrust/system/detail/generic/copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/copy.inl" "$(@D)/cuda/include/thrust/system/detail/generic/copy.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/copy_if.h" "$(@D)/cuda/include/thrust/system/detail/generic/copy_if.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/copy_if.inl" "$(@D)/cuda/include/thrust/system/detail/generic/copy_if.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/count.h" "$(@D)/cuda/include/thrust/system/detail/generic/count.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/count.inl" "$(@D)/cuda/include/thrust/system/detail/generic/count.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/distance.h" "$(@D)/cuda/include/thrust/system/detail/generic/distance.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/distance.inl" "$(@D)/cuda/include/thrust/system/detail/generic/distance.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/equal.h" "$(@D)/cuda/include/thrust/system/detail/generic/equal.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/equal.inl" "$(@D)/cuda/include/thrust/system/detail/generic/equal.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/extrema.h" "$(@D)/cuda/include/thrust/system/detail/generic/extrema.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/extrema.inl" "$(@D)/cuda/include/thrust/system/detail/generic/extrema.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/fill.h" "$(@D)/cuda/include/thrust/system/detail/generic/fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/find.h" "$(@D)/cuda/include/thrust/system/detail/generic/find.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/find.inl" "$(@D)/cuda/include/thrust/system/detail/generic/find.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/for_each.h" "$(@D)/cuda/include/thrust/system/detail/generic/for_each.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/gather.h" "$(@D)/cuda/include/thrust/system/detail/generic/gather.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/gather.inl" "$(@D)/cuda/include/thrust/system/detail/generic/gather.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/generate.h" "$(@D)/cuda/include/thrust/system/detail/generic/generate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/generate.inl" "$(@D)/cuda/include/thrust/system/detail/generic/generate.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/inner_product.h" "$(@D)/cuda/include/thrust/system/detail/generic/inner_product.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/inner_product.inl" "$(@D)/cuda/include/thrust/system/detail/generic/inner_product.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/logical.h" "$(@D)/cuda/include/thrust/system/detail/generic/logical.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/memory.h" "$(@D)/cuda/include/thrust/system/detail/generic/memory.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/memory.inl" "$(@D)/cuda/include/thrust/system/detail/generic/memory.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/merge.h" "$(@D)/cuda/include/thrust/system/detail/generic/merge.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/merge.inl" "$(@D)/cuda/include/thrust/system/detail/generic/merge.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/mismatch.h" "$(@D)/cuda/include/thrust/system/detail/generic/mismatch.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/mismatch.inl" "$(@D)/cuda/include/thrust/system/detail/generic/mismatch.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/partition.h" "$(@D)/cuda/include/thrust/system/detail/generic/partition.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/partition.inl" "$(@D)/cuda/include/thrust/system/detail/generic/partition.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reduce.h" "$(@D)/cuda/include/thrust/system/detail/generic/reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reduce.inl" "$(@D)/cuda/include/thrust/system/detail/generic/reduce.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/detail/generic/reduce_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reduce_by_key.inl" "$(@D)/cuda/include/thrust/system/detail/generic/reduce_by_key.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/remove.h" "$(@D)/cuda/include/thrust/system/detail/generic/remove.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/remove.inl" "$(@D)/cuda/include/thrust/system/detail/generic/remove.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/replace.h" "$(@D)/cuda/include/thrust/system/detail/generic/replace.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/replace.inl" "$(@D)/cuda/include/thrust/system/detail/generic/replace.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reverse.h" "$(@D)/cuda/include/thrust/system/detail/generic/reverse.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reverse.inl" "$(@D)/cuda/include/thrust/system/detail/generic/reverse.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scalar/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/generic/scalar/binary_search.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scalar/binary_search.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scalar/binary_search.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scan.h" "$(@D)/cuda/include/thrust/system/detail/generic/scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scan.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scan.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scan_by_key.h" "$(@D)/cuda/include/thrust/system/detail/generic/scan_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scan_by_key.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scan_by_key.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scatter.h" "$(@D)/cuda/include/thrust/system/detail/generic/scatter.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scatter.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scatter.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/select_system.h" "$(@D)/cuda/include/thrust/system/detail/generic/select_system.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/sequence.h" "$(@D)/cuda/include/thrust/system/detail/generic/sequence.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/sequence.inl" "$(@D)/cuda/include/thrust/system/detail/generic/sequence.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/set_operations.h" "$(@D)/cuda/include/thrust/system/detail/generic/set_operations.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/set_operations.inl" "$(@D)/cuda/include/thrust/system/detail/generic/set_operations.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/sort.h" "$(@D)/cuda/include/thrust/system/detail/generic/sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/sort.inl" "$(@D)/cuda/include/thrust/system/detail/generic/sort.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/swap_ranges.h" "$(@D)/cuda/include/thrust/system/detail/generic/swap_ranges.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/swap_ranges.inl" "$(@D)/cuda/include/thrust/system/detail/generic/swap_ranges.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/tabulate.h" "$(@D)/cuda/include/thrust/system/detail/generic/tabulate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/tabulate.inl" "$(@D)/cuda/include/thrust/system/detail/generic/tabulate.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/tag.h" "$(@D)/cuda/include/thrust/system/detail/generic/tag.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/detail/generic/temporary_buffer.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/temporary_buffer.inl" "$(@D)/cuda/include/thrust/system/detail/generic/temporary_buffer.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform.h" "$(@D)/cuda/include/thrust/system/detail/generic/transform.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform.inl" "$(@D)/cuda/include/thrust/system/detail/generic/transform.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform_reduce.h" "$(@D)/cuda/include/thrust/system/detail/generic/transform_reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform_reduce.inl" "$(@D)/cuda/include/thrust/system/detail/generic/transform_reduce.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform_scan.h" "$(@D)/cuda/include/thrust/system/detail/generic/transform_scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform_scan.inl" "$(@D)/cuda/include/thrust/system/detail/generic/transform_scan.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/type_traits.h" "$(@D)/cuda/include/thrust/system/detail/generic/type_traits.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/uninitialized_copy.inl" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_copy.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/uninitialized_fill.inl" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_fill.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/unique.h" "$(@D)/cuda/include/thrust/system/detail/generic/unique.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/unique.inl" "$(@D)/cuda/include/thrust/system/detail/generic/unique.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/unique_by_key.h" "$(@D)/cuda/include/thrust/system/detail/generic/unique_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/generic/unique_by_key.inl" "$(@D)/cuda/include/thrust/system/detail/generic/unique_by_key.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/internal/decompose.h" "$(@D)/cuda/include/thrust/system/detail/internal/decompose.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/detail/sequential/adjacent_difference.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/assign_value.h" "$(@D)/cuda/include/thrust/system/detail/sequential/assign_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/sequential/binary_search.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/copy.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/copy.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/copy_backward.h" "$(@D)/cuda/include/thrust/system/detail/sequential/copy_backward.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/copy_if.h" "$(@D)/cuda/include/thrust/system/detail/sequential/copy_if.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/count.h" "$(@D)/cuda/include/thrust/system/detail/sequential/count.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/equal.h" "$(@D)/cuda/include/thrust/system/detail/sequential/equal.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/execution_policy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/extrema.h" "$(@D)/cuda/include/thrust/system/detail/sequential/extrema.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/fill.h" "$(@D)/cuda/include/thrust/system/detail/sequential/fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/find.h" "$(@D)/cuda/include/thrust/system/detail/sequential/find.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/for_each.h" "$(@D)/cuda/include/thrust/system/detail/sequential/for_each.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/gather.h" "$(@D)/cuda/include/thrust/system/detail/sequential/gather.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/general_copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/general_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/generate.h" "$(@D)/cuda/include/thrust/system/detail/sequential/generate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/get_value.h" "$(@D)/cuda/include/thrust/system/detail/sequential/get_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/inner_product.h" "$(@D)/cuda/include/thrust/system/detail/sequential/inner_product.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/insertion_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/insertion_sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/iter_swap.h" "$(@D)/cuda/include/thrust/system/detail/sequential/iter_swap.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/logical.h" "$(@D)/cuda/include/thrust/system/detail/sequential/logical.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/detail/sequential/malloc_and_free.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/merge.h" "$(@D)/cuda/include/thrust/system/detail/sequential/merge.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/merge.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/merge.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/mismatch.h" "$(@D)/cuda/include/thrust/system/detail/sequential/mismatch.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/partition.h" "$(@D)/cuda/include/thrust/system/detail/sequential/partition.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/reduce.h" "$(@D)/cuda/include/thrust/system/detail/sequential/reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/detail/sequential/reduce_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/remove.h" "$(@D)/cuda/include/thrust/system/detail/sequential/remove.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/replace.h" "$(@D)/cuda/include/thrust/system/detail/sequential/replace.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/reverse.h" "$(@D)/cuda/include/thrust/system/detail/sequential/reverse.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/scan.h" "$(@D)/cuda/include/thrust/system/detail/sequential/scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/scan_by_key.h" "$(@D)/cuda/include/thrust/system/detail/sequential/scan_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/scatter.h" "$(@D)/cuda/include/thrust/system/detail/sequential/scatter.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/sequence.h" "$(@D)/cuda/include/thrust/system/detail/sequential/sequence.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/set_operations.h" "$(@D)/cuda/include/thrust/system/detail/sequential/set_operations.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/sort.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_merge_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_merge_sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_merge_sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_merge_sort.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_primitive_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_primitive_sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_primitive_sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_primitive_sort.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_radix_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_radix_sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_radix_sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_radix_sort.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/swap_ranges.h" "$(@D)/cuda/include/thrust/system/detail/sequential/swap_ranges.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/tabulate.h" "$(@D)/cuda/include/thrust/system/detail/sequential/tabulate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/detail/sequential/temporary_buffer.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/transform.h" "$(@D)/cuda/include/thrust/system/detail/sequential/transform.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/transform_reduce.h" "$(@D)/cuda/include/thrust/system/detail/sequential/transform_reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/transform_scan.h" "$(@D)/cuda/include/thrust/system/detail/sequential/transform_scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/trivial_copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/trivial_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/uninitialized_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/detail/sequential/uninitialized_fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/unique.h" "$(@D)/cuda/include/thrust/system/detail/sequential/unique.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/unique_by_key.h" "$(@D)/cuda/include/thrust/system/detail/sequential/unique_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/detail/system_error.inl" "$(@D)/cuda/include/thrust/system/detail/system_error.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/error_code.h" "$(@D)/cuda/include/thrust/system/error_code.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/omp/detail/adjacent_difference.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/omp/detail/assign_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/omp/detail/binary_search.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/copy.h" "$(@D)/cuda/include/thrust/system/omp/detail/copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/copy.inl" "$(@D)/cuda/include/thrust/system/omp/detail/copy.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/omp/detail/copy_if.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/copy_if.inl" "$(@D)/cuda/include/thrust/system/omp/detail/copy_if.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/count.h" "$(@D)/cuda/include/thrust/system/omp/detail/count.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/default_decomposition.h" "$(@D)/cuda/include/thrust/system/omp/detail/default_decomposition.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/default_decomposition.inl" "$(@D)/cuda/include/thrust/system/omp/detail/default_decomposition.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/equal.h" "$(@D)/cuda/include/thrust/system/omp/detail/equal.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/omp/detail/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/extrema.h" "$(@D)/cuda/include/thrust/system/omp/detail/extrema.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/fill.h" "$(@D)/cuda/include/thrust/system/omp/detail/fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/find.h" "$(@D)/cuda/include/thrust/system/omp/detail/find.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/for_each.h" "$(@D)/cuda/include/thrust/system/omp/detail/for_each.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/for_each.inl" "$(@D)/cuda/include/thrust/system/omp/detail/for_each.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/gather.h" "$(@D)/cuda/include/thrust/system/omp/detail/gather.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/generate.h" "$(@D)/cuda/include/thrust/system/omp/detail/generate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/get_value.h" "$(@D)/cuda/include/thrust/system/omp/detail/get_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/omp/detail/inner_product.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/omp/detail/iter_swap.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/logical.h" "$(@D)/cuda/include/thrust/system/omp/detail/logical.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/omp/detail/malloc_and_free.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/memory.inl" "$(@D)/cuda/include/thrust/system/omp/detail/memory.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/merge.h" "$(@D)/cuda/include/thrust/system/omp/detail/merge.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/omp/detail/mismatch.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/par.h" "$(@D)/cuda/include/thrust/system/omp/detail/par.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/partition.h" "$(@D)/cuda/include/thrust/system/omp/detail/partition.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/partition.inl" "$(@D)/cuda/include/thrust/system/omp/detail/partition.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce.h" "$(@D)/cuda/include/thrust/system/omp/detail/reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce.inl" "$(@D)/cuda/include/thrust/system/omp/detail/reduce.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce_by_key.inl" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_by_key.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce_intervals.h" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_intervals.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce_intervals.inl" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_intervals.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/remove.h" "$(@D)/cuda/include/thrust/system/omp/detail/remove.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/remove.inl" "$(@D)/cuda/include/thrust/system/omp/detail/remove.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/replace.h" "$(@D)/cuda/include/thrust/system/omp/detail/replace.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reverse.h" "$(@D)/cuda/include/thrust/system/omp/detail/reverse.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/scan.h" "$(@D)/cuda/include/thrust/system/omp/detail/scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/omp/detail/scan_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/scatter.h" "$(@D)/cuda/include/thrust/system/omp/detail/scatter.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/sequence.h" "$(@D)/cuda/include/thrust/system/omp/detail/sequence.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/omp/detail/set_operations.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/sort.h" "$(@D)/cuda/include/thrust/system/omp/detail/sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/sort.inl" "$(@D)/cuda/include/thrust/system/omp/detail/sort.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/omp/detail/swap_ranges.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/omp/detail/tabulate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/omp/detail/temporary_buffer.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/transform.h" "$(@D)/cuda/include/thrust/system/omp/detail/transform.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/omp/detail/transform_reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/omp/detail/transform_scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/omp/detail/uninitialized_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/omp/detail/uninitialized_fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/unique.h" "$(@D)/cuda/include/thrust/system/omp/detail/unique.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/unique.inl" "$(@D)/cuda/include/thrust/system/omp/detail/unique.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/omp/detail/unique_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/unique_by_key.inl" "$(@D)/cuda/include/thrust/system/omp/detail/unique_by_key.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/detail/vector.inl" "$(@D)/cuda/include/thrust/system/omp/detail/vector.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/execution_policy.h" "$(@D)/cuda/include/thrust/system/omp/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/memory.h" "$(@D)/cuda/include/thrust/system/omp/memory.h" && cp "/usr/local/cuda-9.0/include/thrust/system/omp/vector.h" "$(@D)/cuda/include/thrust/system/omp/vector.h" && cp "/usr/local/cuda-9.0/include/thrust/system/system_error.h" "$(@D)/cuda/include/thrust/system/system_error.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/tbb/detail/adjacent_difference.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/tbb/detail/assign_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/tbb/detail/binary_search.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/copy.h" "$(@D)/cuda/include/thrust/system/tbb/detail/copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/copy.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/copy.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/tbb/detail/copy_if.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/copy_if.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/copy_if.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/count.h" "$(@D)/cuda/include/thrust/system/tbb/detail/count.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/equal.h" "$(@D)/cuda/include/thrust/system/tbb/detail/equal.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/tbb/detail/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/extrema.h" "$(@D)/cuda/include/thrust/system/tbb/detail/extrema.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/fill.h" "$(@D)/cuda/include/thrust/system/tbb/detail/fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/find.h" "$(@D)/cuda/include/thrust/system/tbb/detail/find.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/for_each.h" "$(@D)/cuda/include/thrust/system/tbb/detail/for_each.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/for_each.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/for_each.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/gather.h" "$(@D)/cuda/include/thrust/system/tbb/detail/gather.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/generate.h" "$(@D)/cuda/include/thrust/system/tbb/detail/generate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/get_value.h" "$(@D)/cuda/include/thrust/system/tbb/detail/get_value.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/tbb/detail/inner_product.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/tbb/detail/iter_swap.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/logical.h" "$(@D)/cuda/include/thrust/system/tbb/detail/logical.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/tbb/detail/malloc_and_free.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/memory.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/memory.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/merge.h" "$(@D)/cuda/include/thrust/system/tbb/detail/merge.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/merge.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/merge.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/tbb/detail/mismatch.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/par.h" "$(@D)/cuda/include/thrust/system/tbb/detail/par.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/partition.h" "$(@D)/cuda/include/thrust/system/tbb/detail/partition.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/partition.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/partition.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce_by_key.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce_by_key.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce_intervals.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce_intervals.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/remove.h" "$(@D)/cuda/include/thrust/system/tbb/detail/remove.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/remove.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/remove.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/replace.h" "$(@D)/cuda/include/thrust/system/tbb/detail/replace.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reverse.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reverse.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/scan.h" "$(@D)/cuda/include/thrust/system/tbb/detail/scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/scan.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/scan.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/tbb/detail/scan_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/scatter.h" "$(@D)/cuda/include/thrust/system/tbb/detail/scatter.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/sequence.h" "$(@D)/cuda/include/thrust/system/tbb/detail/sequence.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/tbb/detail/set_operations.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/sort.h" "$(@D)/cuda/include/thrust/system/tbb/detail/sort.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/sort.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/sort.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/tbb/detail/swap_ranges.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/tbb/detail/tabulate.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/tbb/detail/temporary_buffer.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/transform.h" "$(@D)/cuda/include/thrust/system/tbb/detail/transform.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/tbb/detail/transform_reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/tbb/detail/transform_scan.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/tbb/detail/uninitialized_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/tbb/detail/uninitialized_fill.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/unique.h" "$(@D)/cuda/include/thrust/system/tbb/detail/unique.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/unique.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/unique.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/tbb/detail/unique_by_key.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/unique_by_key.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/unique_by_key.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/vector.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/vector.inl" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/execution_policy.h" "$(@D)/cuda/include/thrust/system/tbb/execution_policy.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/memory.h" "$(@D)/cuda/include/thrust/system/tbb/memory.h" && cp "/usr/local/cuda-9.0/include/thrust/system/tbb/vector.h" "$(@D)/cuda/include/thrust/system/tbb/vector.h" && cp "/usr/local/cuda-9.0/include/thrust/system_error.h" "$(@D)/cuda/include/thrust/system_error.h" && cp "/usr/local/cuda-9.0/include/thrust/tabulate.h" "$(@D)/cuda/include/thrust/tabulate.h" && cp "/usr/local/cuda-9.0/include/thrust/transform.h" "$(@D)/cuda/include/thrust/transform.h" && cp "/usr/local/cuda-9.0/include/thrust/transform_reduce.h" "$(@D)/cuda/include/thrust/transform_reduce.h" && cp "/usr/local/cuda-9.0/include/thrust/transform_scan.h" "$(@D)/cuda/include/thrust/transform_scan.h" && cp "/usr/local/cuda-9.0/include/thrust/tuple.h" "$(@D)/cuda/include/thrust/tuple.h" && cp "/usr/local/cuda-9.0/include/thrust/uninitialized_copy.h" "$(@D)/cuda/include/thrust/uninitialized_copy.h" && cp "/usr/local/cuda-9.0/include/thrust/uninitialized_fill.h" "$(@D)/cuda/include/thrust/uninitialized_fill.h" && cp "/usr/local/cuda-9.0/include/thrust/unique.h" "$(@D)/cuda/include/thrust/unique.h" && cp "/usr/local/cuda-9.0/include/thrust/version.h" "$(@D)/cuda/include/thrust/version.h" && cp "/usr/local/cuda-9.0/include/vector_functions.h" "$(@D)/cuda/include/vector_functions.h" && cp "/usr/local/cuda-9.0/include/vector_functions.hpp" "$(@D)/cuda/include/vector_functions.hpp" && cp "/usr/local/cuda-9.0/include/vector_types.h" "$(@D)/cuda/include/vector_types.h" +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/local/cuda-9.0/include/CL/cl.h" "$(@D)/cuda/include/CL/cl.h" && cp -f "/usr/local/cuda-9.0/include/CL/cl.hpp" "$(@D)/cuda/include/CL/cl.hpp" && cp -f "/usr/local/cuda-9.0/include/CL/cl_egl.h" "$(@D)/cuda/include/CL/cl_egl.h" && cp -f "/usr/local/cuda-9.0/include/CL/cl_ext.h" "$(@D)/cuda/include/CL/cl_ext.h" && cp -f "/usr/local/cuda-9.0/include/CL/cl_gl.h" "$(@D)/cuda/include/CL/cl_gl.h" && cp -f "/usr/local/cuda-9.0/include/CL/cl_gl_ext.h" "$(@D)/cuda/include/CL/cl_gl_ext.h" && cp -f "/usr/local/cuda-9.0/include/CL/cl_platform.h" "$(@D)/cuda/include/CL/cl_platform.h" && cp -f "/usr/local/cuda-9.0/include/CL/opencl.h" "$(@D)/cuda/include/CL/opencl.h" && cp -f "/usr/local/cuda-9.0/include/builtin_types.h" "$(@D)/cuda/include/builtin_types.h" && cp -f "/usr/local/cuda-9.0/include/channel_descriptor.h" "$(@D)/cuda/include/channel_descriptor.h" && cp -f "/usr/local/cuda-9.0/include/common_functions.h" "$(@D)/cuda/include/common_functions.h" && cp -f "/usr/local/cuda-9.0/include/cooperative_groups.h" "$(@D)/cuda/include/cooperative_groups.h" && cp -f "/usr/local/cuda-9.0/include/cooperative_groups_helpers.h" "$(@D)/cuda/include/cooperative_groups_helpers.h" && cp -f "/usr/local/cuda-9.0/include/crt/common_functions.h" "$(@D)/cuda/include/crt/common_functions.h" && cp -f "/usr/local/cuda-9.0/include/crt/device_double_functions.h" "$(@D)/cuda/include/crt/device_double_functions.h" && cp -f "/usr/local/cuda-9.0/include/crt/device_double_functions.hpp" "$(@D)/cuda/include/crt/device_double_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/crt/device_functions.h" "$(@D)/cuda/include/crt/device_functions.h" && cp -f "/usr/local/cuda-9.0/include/crt/device_functions.hpp" "$(@D)/cuda/include/crt/device_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/crt/func_macro.h" "$(@D)/cuda/include/crt/func_macro.h" && cp -f "/usr/local/cuda-9.0/include/crt/host_config.h" "$(@D)/cuda/include/crt/host_config.h" && cp -f "/usr/local/cuda-9.0/include/crt/host_defines.h" "$(@D)/cuda/include/crt/host_defines.h" && cp -f "/usr/local/cuda-9.0/include/crt/host_runtime.h" "$(@D)/cuda/include/crt/host_runtime.h" && cp -f "/usr/local/cuda-9.0/include/crt/math_functions.h" "$(@D)/cuda/include/crt/math_functions.h" && cp -f "/usr/local/cuda-9.0/include/crt/math_functions.hpp" "$(@D)/cuda/include/crt/math_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/crt/mma.h" "$(@D)/cuda/include/crt/mma.h" && cp -f "/usr/local/cuda-9.0/include/crt/mma.hpp" "$(@D)/cuda/include/crt/mma.hpp" && cp -f "/usr/local/cuda-9.0/include/crt/nvfunctional" "$(@D)/cuda/include/crt/nvfunctional" && cp -f "/usr/local/cuda-9.0/include/crt/sm_70_rt.h" "$(@D)/cuda/include/crt/sm_70_rt.h" && cp -f "/usr/local/cuda-9.0/include/crt/sm_70_rt.hpp" "$(@D)/cuda/include/crt/sm_70_rt.hpp" && cp -f "/usr/local/cuda-9.0/include/crt/storage_class.h" "$(@D)/cuda/include/crt/storage_class.h" && cp -f "/usr/local/cuda-9.0/include/cuComplex.h" "$(@D)/cuda/include/cuComplex.h" && cp -f "/usr/local/cuda-9.0/include/cublas.h" "$(@D)/cuda/include/cublas.h" && cp -f "/usr/local/cuda-9.0/include/cublasXt.h" "$(@D)/cuda/include/cublasXt.h" && cp -f "/usr/local/cuda-9.0/include/cublas_api.h" "$(@D)/cuda/include/cublas_api.h" && cp -f "/usr/local/cuda-9.0/include/cublas_v2.h" "$(@D)/cuda/include/cublas_v2.h" && cp -f "/usr/local/cuda-9.0/include/cuda.h" "$(@D)/cuda/include/cuda.h" && cp -f "/usr/local/cuda-9.0/include/cudaEGL.h" "$(@D)/cuda/include/cudaEGL.h" && cp -f "/usr/local/cuda-9.0/include/cudaGL.h" "$(@D)/cuda/include/cudaGL.h" && cp -f "/usr/local/cuda-9.0/include/cudaProfiler.h" "$(@D)/cuda/include/cudaProfiler.h" && cp -f "/usr/local/cuda-9.0/include/cudaVDPAU.h" "$(@D)/cuda/include/cudaVDPAU.h" && cp -f "/usr/local/cuda-9.0/include/cuda_device_runtime_api.h" "$(@D)/cuda/include/cuda_device_runtime_api.h" && cp -f "/usr/local/cuda-9.0/include/cuda_fp16.h" "$(@D)/cuda/include/cuda_fp16.h" && cp -f "/usr/local/cuda-9.0/include/cuda_fp16.hpp" "$(@D)/cuda/include/cuda_fp16.hpp" && cp -f "/usr/local/cuda-9.0/include/cuda_gl_interop.h" "$(@D)/cuda/include/cuda_gl_interop.h" && cp -f "/usr/local/cuda-9.0/include/cuda_occupancy.h" "$(@D)/cuda/include/cuda_occupancy.h" && cp -f "/usr/local/cuda-9.0/include/cuda_profiler_api.h" "$(@D)/cuda/include/cuda_profiler_api.h" && cp -f "/usr/local/cuda-9.0/include/cuda_runtime.h" "$(@D)/cuda/include/cuda_runtime.h" && cp -f "/usr/local/cuda-9.0/include/cuda_runtime_api.h" "$(@D)/cuda/include/cuda_runtime_api.h" && cp -f "/usr/local/cuda-9.0/include/cuda_surface_types.h" "$(@D)/cuda/include/cuda_surface_types.h" && cp -f "/usr/local/cuda-9.0/include/cuda_texture_types.h" "$(@D)/cuda/include/cuda_texture_types.h" && cp -f "/usr/local/cuda-9.0/include/cuda_vdpau_interop.h" "$(@D)/cuda/include/cuda_vdpau_interop.h" && cp -f "/usr/local/cuda-9.0/include/cudalibxt.h" "$(@D)/cuda/include/cudalibxt.h" && cp -f "/usr/local/cuda-9.0/include/cufft.h" "$(@D)/cuda/include/cufft.h" && cp -f "/usr/local/cuda-9.0/include/cufftXt.h" "$(@D)/cuda/include/cufftXt.h" && cp -f "/usr/local/cuda-9.0/include/cufftw.h" "$(@D)/cuda/include/cufftw.h" && cp -f "/usr/local/cuda-9.0/include/curand.h" "$(@D)/cuda/include/curand.h" && cp -f "/usr/local/cuda-9.0/include/curand_discrete.h" "$(@D)/cuda/include/curand_discrete.h" && cp -f "/usr/local/cuda-9.0/include/curand_discrete2.h" "$(@D)/cuda/include/curand_discrete2.h" && cp -f "/usr/local/cuda-9.0/include/curand_globals.h" "$(@D)/cuda/include/curand_globals.h" && cp -f "/usr/local/cuda-9.0/include/curand_kernel.h" "$(@D)/cuda/include/curand_kernel.h" && cp -f "/usr/local/cuda-9.0/include/curand_lognormal.h" "$(@D)/cuda/include/curand_lognormal.h" && cp -f "/usr/local/cuda-9.0/include/curand_mrg32k3a.h" "$(@D)/cuda/include/curand_mrg32k3a.h" && cp -f "/usr/local/cuda-9.0/include/curand_mtgp32.h" "$(@D)/cuda/include/curand_mtgp32.h" && cp -f "/usr/local/cuda-9.0/include/curand_mtgp32_host.h" "$(@D)/cuda/include/curand_mtgp32_host.h" && cp -f "/usr/local/cuda-9.0/include/curand_mtgp32_kernel.h" "$(@D)/cuda/include/curand_mtgp32_kernel.h" && cp -f "/usr/local/cuda-9.0/include/curand_mtgp32dc_p_11213.h" "$(@D)/cuda/include/curand_mtgp32dc_p_11213.h" && cp -f "/usr/local/cuda-9.0/include/curand_normal.h" "$(@D)/cuda/include/curand_normal.h" && cp -f "/usr/local/cuda-9.0/include/curand_normal_static.h" "$(@D)/cuda/include/curand_normal_static.h" && cp -f "/usr/local/cuda-9.0/include/curand_philox4x32_x.h" "$(@D)/cuda/include/curand_philox4x32_x.h" && cp -f "/usr/local/cuda-9.0/include/curand_poisson.h" "$(@D)/cuda/include/curand_poisson.h" && cp -f "/usr/local/cuda-9.0/include/curand_precalc.h" "$(@D)/cuda/include/curand_precalc.h" && cp -f "/usr/local/cuda-9.0/include/curand_uniform.h" "$(@D)/cuda/include/curand_uniform.h" && cp -f "/usr/local/cuda-9.0/include/cusolverDn.h" "$(@D)/cuda/include/cusolverDn.h" && cp -f "/usr/local/cuda-9.0/include/cusolverRf.h" "$(@D)/cuda/include/cusolverRf.h" && cp -f "/usr/local/cuda-9.0/include/cusolverSp.h" "$(@D)/cuda/include/cusolverSp.h" && cp -f "/usr/local/cuda-9.0/include/cusolverSp_LOWLEVEL_PREVIEW.h" "$(@D)/cuda/include/cusolverSp_LOWLEVEL_PREVIEW.h" && cp -f "/usr/local/cuda-9.0/include/cusolver_common.h" "$(@D)/cuda/include/cusolver_common.h" && cp -f "/usr/local/cuda-9.0/include/cusparse.h" "$(@D)/cuda/include/cusparse.h" && cp -f "/usr/local/cuda-9.0/include/cusparse_v2.h" "$(@D)/cuda/include/cusparse_v2.h" && cp -f "/usr/local/cuda-9.0/include/device_atomic_functions.h" "$(@D)/cuda/include/device_atomic_functions.h" && cp -f "/usr/local/cuda-9.0/include/device_atomic_functions.hpp" "$(@D)/cuda/include/device_atomic_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/device_double_functions.h" "$(@D)/cuda/include/device_double_functions.h" && cp -f "/usr/local/cuda-9.0/include/device_double_functions.hpp" "$(@D)/cuda/include/device_double_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/device_functions.h" "$(@D)/cuda/include/device_functions.h" && cp -f "/usr/local/cuda-9.0/include/device_functions.hpp" "$(@D)/cuda/include/device_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/device_functions_decls.h" "$(@D)/cuda/include/device_functions_decls.h" && cp -f "/usr/local/cuda-9.0/include/device_launch_parameters.h" "$(@D)/cuda/include/device_launch_parameters.h" && cp -f "/usr/local/cuda-9.0/include/device_types.h" "$(@D)/cuda/include/device_types.h" && cp -f "/usr/local/cuda-9.0/include/driver_functions.h" "$(@D)/cuda/include/driver_functions.h" && cp -f "/usr/local/cuda-9.0/include/driver_types.h" "$(@D)/cuda/include/driver_types.h" && cp -f "/usr/local/cuda-9.0/include/dynlink_cuda.h" "$(@D)/cuda/include/dynlink_cuda.h" && cp -f "/usr/local/cuda-9.0/include/dynlink_cuda_cuda.h" "$(@D)/cuda/include/dynlink_cuda_cuda.h" && cp -f "/usr/local/cuda-9.0/include/dynlink_cuviddec.h" "$(@D)/cuda/include/dynlink_cuviddec.h" && cp -f "/usr/local/cuda-9.0/include/dynlink_nvcuvid.h" "$(@D)/cuda/include/dynlink_nvcuvid.h" && cp -f "/usr/local/cuda-9.0/include/fatBinaryCtl.h" "$(@D)/cuda/include/fatBinaryCtl.h" && cp -f "/usr/local/cuda-9.0/include/fatbinary.h" "$(@D)/cuda/include/fatbinary.h" && cp -f "/usr/local/cuda-9.0/include/host_config.h" "$(@D)/cuda/include/host_config.h" && cp -f "/usr/local/cuda-9.0/include/host_defines.h" "$(@D)/cuda/include/host_defines.h" && cp -f "/usr/local/cuda-9.0/include/library_types.h" "$(@D)/cuda/include/library_types.h" && cp -f "/usr/local/cuda-9.0/include/math_constants.h" "$(@D)/cuda/include/math_constants.h" && cp -f "/usr/local/cuda-9.0/include/math_functions.h" "$(@D)/cuda/include/math_functions.h" && cp -f "/usr/local/cuda-9.0/include/math_functions.hpp" "$(@D)/cuda/include/math_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/math_functions_dbl_ptx3.h" "$(@D)/cuda/include/math_functions_dbl_ptx3.h" && cp -f "/usr/local/cuda-9.0/include/math_functions_dbl_ptx3.hpp" "$(@D)/cuda/include/math_functions_dbl_ptx3.hpp" && cp -f "/usr/local/cuda-9.0/include/mma.h" "$(@D)/cuda/include/mma.h" && cp -f "/usr/local/cuda-9.0/include/npp.h" "$(@D)/cuda/include/npp.h" && cp -f "/usr/local/cuda-9.0/include/nppcore.h" "$(@D)/cuda/include/nppcore.h" && cp -f "/usr/local/cuda-9.0/include/nppdefs.h" "$(@D)/cuda/include/nppdefs.h" && cp -f "/usr/local/cuda-9.0/include/nppi.h" "$(@D)/cuda/include/nppi.h" && cp -f "/usr/local/cuda-9.0/include/nppi_arithmetic_and_logical_operations.h" "$(@D)/cuda/include/nppi_arithmetic_and_logical_operations.h" && cp -f "/usr/local/cuda-9.0/include/nppi_color_conversion.h" "$(@D)/cuda/include/nppi_color_conversion.h" && cp -f "/usr/local/cuda-9.0/include/nppi_compression_functions.h" "$(@D)/cuda/include/nppi_compression_functions.h" && cp -f "/usr/local/cuda-9.0/include/nppi_computer_vision.h" "$(@D)/cuda/include/nppi_computer_vision.h" && cp -f "/usr/local/cuda-9.0/include/nppi_data_exchange_and_initialization.h" "$(@D)/cuda/include/nppi_data_exchange_and_initialization.h" && cp -f "/usr/local/cuda-9.0/include/nppi_filtering_functions.h" "$(@D)/cuda/include/nppi_filtering_functions.h" && cp -f "/usr/local/cuda-9.0/include/nppi_geometry_transforms.h" "$(@D)/cuda/include/nppi_geometry_transforms.h" && cp -f "/usr/local/cuda-9.0/include/nppi_linear_transforms.h" "$(@D)/cuda/include/nppi_linear_transforms.h" && cp -f "/usr/local/cuda-9.0/include/nppi_morphological_operations.h" "$(@D)/cuda/include/nppi_morphological_operations.h" && cp -f "/usr/local/cuda-9.0/include/nppi_statistics_functions.h" "$(@D)/cuda/include/nppi_statistics_functions.h" && cp -f "/usr/local/cuda-9.0/include/nppi_support_functions.h" "$(@D)/cuda/include/nppi_support_functions.h" && cp -f "/usr/local/cuda-9.0/include/nppi_threshold_and_compare_operations.h" "$(@D)/cuda/include/nppi_threshold_and_compare_operations.h" && cp -f "/usr/local/cuda-9.0/include/npps.h" "$(@D)/cuda/include/npps.h" && cp -f "/usr/local/cuda-9.0/include/npps_arithmetic_and_logical_operations.h" "$(@D)/cuda/include/npps_arithmetic_and_logical_operations.h" && cp -f "/usr/local/cuda-9.0/include/npps_conversion_functions.h" "$(@D)/cuda/include/npps_conversion_functions.h" && cp -f "/usr/local/cuda-9.0/include/npps_filtering_functions.h" "$(@D)/cuda/include/npps_filtering_functions.h" && cp -f "/usr/local/cuda-9.0/include/npps_initialization.h" "$(@D)/cuda/include/npps_initialization.h" && cp -f "/usr/local/cuda-9.0/include/npps_statistics_functions.h" "$(@D)/cuda/include/npps_statistics_functions.h" && cp -f "/usr/local/cuda-9.0/include/npps_support_functions.h" "$(@D)/cuda/include/npps_support_functions.h" && cp -f "/usr/local/cuda-9.0/include/nppversion.h" "$(@D)/cuda/include/nppversion.h" && cp -f "/usr/local/cuda-9.0/include/nvToolsExt.h" "$(@D)/cuda/include/nvToolsExt.h" && cp -f "/usr/local/cuda-9.0/include/nvToolsExtCuda.h" "$(@D)/cuda/include/nvToolsExtCuda.h" && cp -f "/usr/local/cuda-9.0/include/nvToolsExtCudaRt.h" "$(@D)/cuda/include/nvToolsExtCudaRt.h" && cp -f "/usr/local/cuda-9.0/include/nvToolsExtMeta.h" "$(@D)/cuda/include/nvToolsExtMeta.h" && cp -f "/usr/local/cuda-9.0/include/nvToolsExtSync.h" "$(@D)/cuda/include/nvToolsExtSync.h" && cp -f "/usr/local/cuda-9.0/include/nvblas.h" "$(@D)/cuda/include/nvblas.h" && cp -f "/usr/local/cuda-9.0/include/nvfunctional" "$(@D)/cuda/include/nvfunctional" && cp -f "/usr/local/cuda-9.0/include/nvgraph.h" "$(@D)/cuda/include/nvgraph.h" && cp -f "/usr/local/cuda-9.0/include/nvml.h" "$(@D)/cuda/include/nvml.h" && cp -f "/usr/local/cuda-9.0/include/nvrtc.h" "$(@D)/cuda/include/nvrtc.h" && cp -f "/usr/local/cuda-9.0/include/sm_20_atomic_functions.h" "$(@D)/cuda/include/sm_20_atomic_functions.h" && cp -f "/usr/local/cuda-9.0/include/sm_20_atomic_functions.hpp" "$(@D)/cuda/include/sm_20_atomic_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/sm_20_intrinsics.h" "$(@D)/cuda/include/sm_20_intrinsics.h" && cp -f "/usr/local/cuda-9.0/include/sm_20_intrinsics.hpp" "$(@D)/cuda/include/sm_20_intrinsics.hpp" && cp -f "/usr/local/cuda-9.0/include/sm_30_intrinsics.h" "$(@D)/cuda/include/sm_30_intrinsics.h" && cp -f "/usr/local/cuda-9.0/include/sm_30_intrinsics.hpp" "$(@D)/cuda/include/sm_30_intrinsics.hpp" && cp -f "/usr/local/cuda-9.0/include/sm_32_atomic_functions.h" "$(@D)/cuda/include/sm_32_atomic_functions.h" && cp -f "/usr/local/cuda-9.0/include/sm_32_atomic_functions.hpp" "$(@D)/cuda/include/sm_32_atomic_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/sm_32_intrinsics.h" "$(@D)/cuda/include/sm_32_intrinsics.h" && cp -f "/usr/local/cuda-9.0/include/sm_32_intrinsics.hpp" "$(@D)/cuda/include/sm_32_intrinsics.hpp" && cp -f "/usr/local/cuda-9.0/include/sm_35_atomic_functions.h" "$(@D)/cuda/include/sm_35_atomic_functions.h" && cp -f "/usr/local/cuda-9.0/include/sm_35_intrinsics.h" "$(@D)/cuda/include/sm_35_intrinsics.h" && cp -f "/usr/local/cuda-9.0/include/sm_60_atomic_functions.h" "$(@D)/cuda/include/sm_60_atomic_functions.h" && cp -f "/usr/local/cuda-9.0/include/sm_60_atomic_functions.hpp" "$(@D)/cuda/include/sm_60_atomic_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/sm_61_intrinsics.h" "$(@D)/cuda/include/sm_61_intrinsics.h" && cp -f "/usr/local/cuda-9.0/include/sm_61_intrinsics.hpp" "$(@D)/cuda/include/sm_61_intrinsics.hpp" && cp -f "/usr/local/cuda-9.0/include/sobol_direction_vectors.h" "$(@D)/cuda/include/sobol_direction_vectors.h" && cp -f "/usr/local/cuda-9.0/include/surface_functions.h" "$(@D)/cuda/include/surface_functions.h" && cp -f "/usr/local/cuda-9.0/include/surface_functions.hpp" "$(@D)/cuda/include/surface_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/surface_indirect_functions.h" "$(@D)/cuda/include/surface_indirect_functions.h" && cp -f "/usr/local/cuda-9.0/include/surface_indirect_functions.hpp" "$(@D)/cuda/include/surface_indirect_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/surface_types.h" "$(@D)/cuda/include/surface_types.h" && cp -f "/usr/local/cuda-9.0/include/texture_fetch_functions.h" "$(@D)/cuda/include/texture_fetch_functions.h" && cp -f "/usr/local/cuda-9.0/include/texture_fetch_functions.hpp" "$(@D)/cuda/include/texture_fetch_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/texture_indirect_functions.h" "$(@D)/cuda/include/texture_indirect_functions.h" && cp -f "/usr/local/cuda-9.0/include/texture_indirect_functions.hpp" "$(@D)/cuda/include/texture_indirect_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/texture_types.h" "$(@D)/cuda/include/texture_types.h" && cp -f "/usr/local/cuda-9.0/include/thrust/adjacent_difference.h" "$(@D)/cuda/include/thrust/adjacent_difference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/advance.h" "$(@D)/cuda/include/thrust/advance.h" && cp -f "/usr/local/cuda-9.0/include/thrust/binary_search.h" "$(@D)/cuda/include/thrust/binary_search.h" && cp -f "/usr/local/cuda-9.0/include/thrust/complex.h" "$(@D)/cuda/include/thrust/complex.h" && cp -f "/usr/local/cuda-9.0/include/thrust/copy.h" "$(@D)/cuda/include/thrust/copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/count.h" "$(@D)/cuda/include/thrust/count.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/adjacent_difference.inl" "$(@D)/cuda/include/thrust/detail/adjacent_difference.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/advance.inl" "$(@D)/cuda/include/thrust/detail/advance.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/allocator_traits.h" "$(@D)/cuda/include/thrust/detail/allocator/allocator_traits.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/allocator_traits.inl" "$(@D)/cuda/include/thrust/detail/allocator/allocator_traits.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/copy_construct_range.h" "$(@D)/cuda/include/thrust/detail/allocator/copy_construct_range.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/copy_construct_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/copy_construct_range.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/default_construct_range.h" "$(@D)/cuda/include/thrust/detail/allocator/default_construct_range.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/default_construct_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/default_construct_range.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/destroy_range.h" "$(@D)/cuda/include/thrust/detail/allocator/destroy_range.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/destroy_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/destroy_range.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/fill_construct_range.h" "$(@D)/cuda/include/thrust/detail/allocator/fill_construct_range.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/fill_construct_range.inl" "$(@D)/cuda/include/thrust/detail/allocator/fill_construct_range.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/malloc_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/malloc_allocator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/malloc_allocator.inl" "$(@D)/cuda/include/thrust/detail/allocator/malloc_allocator.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/no_throw_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/no_throw_allocator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/tagged_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/tagged_allocator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/tagged_allocator.inl" "$(@D)/cuda/include/thrust/detail/allocator/tagged_allocator.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/temporary_allocator.h" "$(@D)/cuda/include/thrust/detail/allocator/temporary_allocator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/allocator/temporary_allocator.inl" "$(@D)/cuda/include/thrust/detail/allocator/temporary_allocator.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/binary_search.inl" "$(@D)/cuda/include/thrust/detail/binary_search.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/arithmetic.h" "$(@D)/cuda/include/thrust/detail/complex/arithmetic.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/c99math.h" "$(@D)/cuda/include/thrust/detail/complex/c99math.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/catrig.h" "$(@D)/cuda/include/thrust/detail/complex/catrig.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/catrigf.h" "$(@D)/cuda/include/thrust/detail/complex/catrigf.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/ccosh.h" "$(@D)/cuda/include/thrust/detail/complex/ccosh.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/ccoshf.h" "$(@D)/cuda/include/thrust/detail/complex/ccoshf.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/cexp.h" "$(@D)/cuda/include/thrust/detail/complex/cexp.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/cexpf.h" "$(@D)/cuda/include/thrust/detail/complex/cexpf.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/clog.h" "$(@D)/cuda/include/thrust/detail/complex/clog.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/clogf.h" "$(@D)/cuda/include/thrust/detail/complex/clogf.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/complex.inl" "$(@D)/cuda/include/thrust/detail/complex/complex.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/cpow.h" "$(@D)/cuda/include/thrust/detail/complex/cpow.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/cpowf.h" "$(@D)/cuda/include/thrust/detail/complex/cpowf.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/cproj.h" "$(@D)/cuda/include/thrust/detail/complex/cproj.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/csinh.h" "$(@D)/cuda/include/thrust/detail/complex/csinh.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/csinhf.h" "$(@D)/cuda/include/thrust/detail/complex/csinhf.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/csqrt.h" "$(@D)/cuda/include/thrust/detail/complex/csqrt.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/csqrtf.h" "$(@D)/cuda/include/thrust/detail/complex/csqrtf.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/ctanh.h" "$(@D)/cuda/include/thrust/detail/complex/ctanh.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/ctanhf.h" "$(@D)/cuda/include/thrust/detail/complex/ctanhf.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/math_private.h" "$(@D)/cuda/include/thrust/detail/complex/math_private.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/complex/stream.h" "$(@D)/cuda/include/thrust/detail/complex/stream.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config.h" "$(@D)/cuda/include/thrust/detail/config.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/compiler.h" "$(@D)/cuda/include/thrust/detail/config/compiler.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/compiler_fence.h" "$(@D)/cuda/include/thrust/detail/config/compiler_fence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/config.h" "$(@D)/cuda/include/thrust/detail/config/config.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/debug.h" "$(@D)/cuda/include/thrust/detail/config/debug.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/device_system.h" "$(@D)/cuda/include/thrust/detail/config/device_system.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/exec_check_disable.h" "$(@D)/cuda/include/thrust/detail/config/exec_check_disable.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/forceinline.h" "$(@D)/cuda/include/thrust/detail/config/forceinline.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/global_workarounds.h" "$(@D)/cuda/include/thrust/detail/config/global_workarounds.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/host_device.h" "$(@D)/cuda/include/thrust/detail/config/host_device.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/host_system.h" "$(@D)/cuda/include/thrust/detail/config/host_system.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/config/simple_defines.h" "$(@D)/cuda/include/thrust/detail/config/simple_defines.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/contiguous_storage.h" "$(@D)/cuda/include/thrust/detail/contiguous_storage.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/contiguous_storage.inl" "$(@D)/cuda/include/thrust/detail/contiguous_storage.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/copy.h" "$(@D)/cuda/include/thrust/detail/copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/copy.inl" "$(@D)/cuda/include/thrust/detail/copy.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/copy_if.h" "$(@D)/cuda/include/thrust/detail/copy_if.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/copy_if.inl" "$(@D)/cuda/include/thrust/detail/copy_if.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/count.inl" "$(@D)/cuda/include/thrust/detail/count.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/cstdint.h" "$(@D)/cuda/include/thrust/detail/cstdint.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/device_delete.inl" "$(@D)/cuda/include/thrust/detail/device_delete.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/device_free.inl" "$(@D)/cuda/include/thrust/detail/device_free.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/device_malloc.inl" "$(@D)/cuda/include/thrust/detail/device_malloc.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/device_new.inl" "$(@D)/cuda/include/thrust/detail/device_new.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/device_ptr.inl" "$(@D)/cuda/include/thrust/detail/device_ptr.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/device_reference.inl" "$(@D)/cuda/include/thrust/detail/device_reference.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/device_vector.inl" "$(@D)/cuda/include/thrust/detail/device_vector.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/dispatch/is_trivial_copy.h" "$(@D)/cuda/include/thrust/detail/dispatch/is_trivial_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/distance.inl" "$(@D)/cuda/include/thrust/detail/distance.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/equal.inl" "$(@D)/cuda/include/thrust/detail/equal.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/execute_with_allocator.h" "$(@D)/cuda/include/thrust/detail/execute_with_allocator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/execution_policy.h" "$(@D)/cuda/include/thrust/detail/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/extrema.inl" "$(@D)/cuda/include/thrust/detail/extrema.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/fill.inl" "$(@D)/cuda/include/thrust/detail/fill.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/find.inl" "$(@D)/cuda/include/thrust/detail/find.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/for_each.inl" "$(@D)/cuda/include/thrust/detail/for_each.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/function.h" "$(@D)/cuda/include/thrust/detail/function.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional.inl" "$(@D)/cuda/include/thrust/detail/functional.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/actor.h" "$(@D)/cuda/include/thrust/detail/functional/actor.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/actor.inl" "$(@D)/cuda/include/thrust/detail/functional/actor.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/argument.h" "$(@D)/cuda/include/thrust/detail/functional/argument.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/composite.h" "$(@D)/cuda/include/thrust/detail/functional/composite.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/arithmetic_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/arithmetic_operators.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/assignment_operator.h" "$(@D)/cuda/include/thrust/detail/functional/operators/assignment_operator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/bitwise_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/bitwise_operators.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/compound_assignment_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/compound_assignment_operators.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/logical_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/logical_operators.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/operator_adaptors.h" "$(@D)/cuda/include/thrust/detail/functional/operators/operator_adaptors.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/operators/relational_operators.h" "$(@D)/cuda/include/thrust/detail/functional/operators/relational_operators.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/placeholder.h" "$(@D)/cuda/include/thrust/detail/functional/placeholder.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/functional/value.h" "$(@D)/cuda/include/thrust/detail/functional/value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/gather.inl" "$(@D)/cuda/include/thrust/detail/gather.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/generate.inl" "$(@D)/cuda/include/thrust/detail/generate.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/get_iterator_value.h" "$(@D)/cuda/include/thrust/detail/get_iterator_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/host_vector.inl" "$(@D)/cuda/include/thrust/detail/host_vector.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/inner_product.inl" "$(@D)/cuda/include/thrust/detail/inner_product.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/integer_math.h" "$(@D)/cuda/include/thrust/detail/integer_math.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/integer_traits.h" "$(@D)/cuda/include/thrust/detail/integer_traits.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/internal_functional.h" "$(@D)/cuda/include/thrust/detail/internal_functional.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/logical.inl" "$(@D)/cuda/include/thrust/detail/logical.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/merge.inl" "$(@D)/cuda/include/thrust/detail/merge.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/minmax.h" "$(@D)/cuda/include/thrust/detail/minmax.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/mismatch.inl" "$(@D)/cuda/include/thrust/detail/mismatch.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/mpl/math.h" "$(@D)/cuda/include/thrust/detail/mpl/math.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/numeric_traits.h" "$(@D)/cuda/include/thrust/detail/numeric_traits.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/overlapped_copy.h" "$(@D)/cuda/include/thrust/detail/overlapped_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/pair.inl" "$(@D)/cuda/include/thrust/detail/pair.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/partition.inl" "$(@D)/cuda/include/thrust/detail/partition.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/pointer.h" "$(@D)/cuda/include/thrust/detail/pointer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/pointer.inl" "$(@D)/cuda/include/thrust/detail/pointer.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/range/head_flags.h" "$(@D)/cuda/include/thrust/detail/range/head_flags.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/range/tail_flags.h" "$(@D)/cuda/include/thrust/detail/range/tail_flags.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/raw_pointer_cast.h" "$(@D)/cuda/include/thrust/detail/raw_pointer_cast.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/raw_reference_cast.h" "$(@D)/cuda/include/thrust/detail/raw_reference_cast.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/reduce.inl" "$(@D)/cuda/include/thrust/detail/reduce.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/reference.h" "$(@D)/cuda/include/thrust/detail/reference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/reference.inl" "$(@D)/cuda/include/thrust/detail/reference.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/reference_forward_declaration.h" "$(@D)/cuda/include/thrust/detail/reference_forward_declaration.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/remove.inl" "$(@D)/cuda/include/thrust/detail/remove.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/replace.inl" "$(@D)/cuda/include/thrust/detail/replace.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/reverse.inl" "$(@D)/cuda/include/thrust/detail/reverse.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/scan.inl" "$(@D)/cuda/include/thrust/detail/scan.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/scatter.inl" "$(@D)/cuda/include/thrust/detail/scatter.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/seq.h" "$(@D)/cuda/include/thrust/detail/seq.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/sequence.inl" "$(@D)/cuda/include/thrust/detail/sequence.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/set_operations.inl" "$(@D)/cuda/include/thrust/detail/set_operations.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/sort.inl" "$(@D)/cuda/include/thrust/detail/sort.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/static_assert.h" "$(@D)/cuda/include/thrust/detail/static_assert.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/static_map.h" "$(@D)/cuda/include/thrust/detail/static_map.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/swap.h" "$(@D)/cuda/include/thrust/detail/swap.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/swap.inl" "$(@D)/cuda/include/thrust/detail/swap.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/swap_ranges.inl" "$(@D)/cuda/include/thrust/detail/swap_ranges.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/tabulate.inl" "$(@D)/cuda/include/thrust/detail/tabulate.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/temporary_array.h" "$(@D)/cuda/include/thrust/detail/temporary_array.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/temporary_array.inl" "$(@D)/cuda/include/thrust/detail/temporary_array.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/transform.inl" "$(@D)/cuda/include/thrust/detail/transform.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/transform_reduce.inl" "$(@D)/cuda/include/thrust/detail/transform_reduce.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/transform_scan.inl" "$(@D)/cuda/include/thrust/detail/transform_scan.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/trivial_sequence.h" "$(@D)/cuda/include/thrust/detail/trivial_sequence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/tuple.inl" "$(@D)/cuda/include/thrust/detail/tuple.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/tuple_meta_transform.h" "$(@D)/cuda/include/thrust/detail/tuple_meta_transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/tuple_transform.h" "$(@D)/cuda/include/thrust/detail/tuple_transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits.h" "$(@D)/cuda/include/thrust/detail/type_traits.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/algorithm/intermediate_type_from_function_and_iterators.h" "$(@D)/cuda/include/thrust/detail/type_traits/algorithm/intermediate_type_from_function_and_iterators.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/function_traits.h" "$(@D)/cuda/include/thrust/detail/type_traits/function_traits.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/has_member_function.h" "$(@D)/cuda/include/thrust/detail/type_traits/has_member_function.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/has_nested_type.h" "$(@D)/cuda/include/thrust/detail/type_traits/has_nested_type.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/has_trivial_assign.h" "$(@D)/cuda/include/thrust/detail/type_traits/has_trivial_assign.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/is_call_possible.h" "$(@D)/cuda/include/thrust/detail/type_traits/is_call_possible.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/is_metafunction_defined.h" "$(@D)/cuda/include/thrust/detail/type_traits/is_metafunction_defined.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/iterator/is_discard_iterator.h" "$(@D)/cuda/include/thrust/detail/type_traits/iterator/is_discard_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/iterator/is_output_iterator.h" "$(@D)/cuda/include/thrust/detail/type_traits/iterator/is_output_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/minimum_type.h" "$(@D)/cuda/include/thrust/detail/type_traits/minimum_type.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/pointer_traits.h" "$(@D)/cuda/include/thrust/detail/type_traits/pointer_traits.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/type_traits/result_of_adaptable_function.h" "$(@D)/cuda/include/thrust/detail/type_traits/result_of_adaptable_function.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/uninitialized_copy.inl" "$(@D)/cuda/include/thrust/detail/uninitialized_copy.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/uninitialized_fill.inl" "$(@D)/cuda/include/thrust/detail/uninitialized_fill.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/unique.inl" "$(@D)/cuda/include/thrust/detail/unique.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/use_default.h" "$(@D)/cuda/include/thrust/detail/use_default.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/util/align.h" "$(@D)/cuda/include/thrust/detail/util/align.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/util/blocking.h" "$(@D)/cuda/include/thrust/detail/util/blocking.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/vector_base.h" "$(@D)/cuda/include/thrust/detail/vector_base.h" && cp -f "/usr/local/cuda-9.0/include/thrust/detail/vector_base.inl" "$(@D)/cuda/include/thrust/detail/vector_base.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/device_allocator.h" "$(@D)/cuda/include/thrust/device_allocator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/device_delete.h" "$(@D)/cuda/include/thrust/device_delete.h" && cp -f "/usr/local/cuda-9.0/include/thrust/device_free.h" "$(@D)/cuda/include/thrust/device_free.h" && cp -f "/usr/local/cuda-9.0/include/thrust/device_malloc.h" "$(@D)/cuda/include/thrust/device_malloc.h" && cp -f "/usr/local/cuda-9.0/include/thrust/device_malloc_allocator.h" "$(@D)/cuda/include/thrust/device_malloc_allocator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/device_new.h" "$(@D)/cuda/include/thrust/device_new.h" && cp -f "/usr/local/cuda-9.0/include/thrust/device_new_allocator.h" "$(@D)/cuda/include/thrust/device_new_allocator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/device_ptr.h" "$(@D)/cuda/include/thrust/device_ptr.h" && cp -f "/usr/local/cuda-9.0/include/thrust/device_reference.h" "$(@D)/cuda/include/thrust/device_reference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/device_vector.h" "$(@D)/cuda/include/thrust/device_vector.h" && cp -f "/usr/local/cuda-9.0/include/thrust/distance.h" "$(@D)/cuda/include/thrust/distance.h" && cp -f "/usr/local/cuda-9.0/include/thrust/equal.h" "$(@D)/cuda/include/thrust/equal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/execution_policy.h" "$(@D)/cuda/include/thrust/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/extrema.h" "$(@D)/cuda/include/thrust/extrema.h" && cp -f "/usr/local/cuda-9.0/include/thrust/fill.h" "$(@D)/cuda/include/thrust/fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/find.h" "$(@D)/cuda/include/thrust/find.h" && cp -f "/usr/local/cuda-9.0/include/thrust/for_each.h" "$(@D)/cuda/include/thrust/for_each.h" && cp -f "/usr/local/cuda-9.0/include/thrust/functional.h" "$(@D)/cuda/include/thrust/functional.h" && cp -f "/usr/local/cuda-9.0/include/thrust/gather.h" "$(@D)/cuda/include/thrust/gather.h" && cp -f "/usr/local/cuda-9.0/include/thrust/generate.h" "$(@D)/cuda/include/thrust/generate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/host_vector.h" "$(@D)/cuda/include/thrust/host_vector.h" && cp -f "/usr/local/cuda-9.0/include/thrust/inner_product.h" "$(@D)/cuda/include/thrust/inner_product.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/constant_iterator.h" "$(@D)/cuda/include/thrust/iterator/constant_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/counting_iterator.h" "$(@D)/cuda/include/thrust/iterator/counting_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/any_assign.h" "$(@D)/cuda/include/thrust/iterator/detail/any_assign.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/any_system_tag.h" "$(@D)/cuda/include/thrust/iterator/detail/any_system_tag.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/constant_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/constant_iterator_base.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/counting_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/counting_iterator.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/device_system_tag.h" "$(@D)/cuda/include/thrust/iterator/detail/device_system_tag.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/discard_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/discard_iterator_base.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/distance_from_result.h" "$(@D)/cuda/include/thrust/iterator/detail/distance_from_result.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/host_system_tag.h" "$(@D)/cuda/include/thrust/iterator/detail/host_system_tag.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/is_iterator_category.h" "$(@D)/cuda/include/thrust/iterator/detail/is_iterator_category.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/is_trivial_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/is_trivial_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_adaptor_base.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_adaptor_base.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_category_to_system.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_category_to_system.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_category_to_traversal.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_category_to_traversal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_category_with_system_and_traversal.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_category_with_system_and_traversal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_facade_category.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_facade_category.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_traits.inl" "$(@D)/cuda/include/thrust/iterator/detail/iterator_traits.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/iterator_traversal_tags.h" "$(@D)/cuda/include/thrust/iterator/detail/iterator_traversal_tags.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/join_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/join_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/minimum_category.h" "$(@D)/cuda/include/thrust/iterator/detail/minimum_category.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/minimum_system.h" "$(@D)/cuda/include/thrust/iterator/detail/minimum_system.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/normal_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/normal_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/permutation_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/permutation_iterator_base.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/retag.h" "$(@D)/cuda/include/thrust/iterator/detail/retag.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/reverse_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/reverse_iterator.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/reverse_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/reverse_iterator_base.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/tagged_iterator.h" "$(@D)/cuda/include/thrust/iterator/detail/tagged_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/transform_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/transform_iterator.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/transform_output_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/transform_output_iterator.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/tuple_of_iterator_references.h" "$(@D)/cuda/include/thrust/iterator/detail/tuple_of_iterator_references.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/universal_categories.h" "$(@D)/cuda/include/thrust/iterator/detail/universal_categories.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/zip_iterator.inl" "$(@D)/cuda/include/thrust/iterator/detail/zip_iterator.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/detail/zip_iterator_base.h" "$(@D)/cuda/include/thrust/iterator/detail/zip_iterator_base.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/discard_iterator.h" "$(@D)/cuda/include/thrust/iterator/discard_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/iterator_adaptor.h" "$(@D)/cuda/include/thrust/iterator/iterator_adaptor.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/iterator_categories.h" "$(@D)/cuda/include/thrust/iterator/iterator_categories.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/iterator_facade.h" "$(@D)/cuda/include/thrust/iterator/iterator_facade.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/iterator_traits.h" "$(@D)/cuda/include/thrust/iterator/iterator_traits.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/permutation_iterator.h" "$(@D)/cuda/include/thrust/iterator/permutation_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/retag.h" "$(@D)/cuda/include/thrust/iterator/retag.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/reverse_iterator.h" "$(@D)/cuda/include/thrust/iterator/reverse_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/transform_iterator.h" "$(@D)/cuda/include/thrust/iterator/transform_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/transform_output_iterator.h" "$(@D)/cuda/include/thrust/iterator/transform_output_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/iterator/zip_iterator.h" "$(@D)/cuda/include/thrust/iterator/zip_iterator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/logical.h" "$(@D)/cuda/include/thrust/logical.h" && cp -f "/usr/local/cuda-9.0/include/thrust/memory.h" "$(@D)/cuda/include/thrust/memory.h" && cp -f "/usr/local/cuda-9.0/include/thrust/merge.h" "$(@D)/cuda/include/thrust/merge.h" && cp -f "/usr/local/cuda-9.0/include/thrust/mismatch.h" "$(@D)/cuda/include/thrust/mismatch.h" && cp -f "/usr/local/cuda-9.0/include/thrust/pair.h" "$(@D)/cuda/include/thrust/pair.h" && cp -f "/usr/local/cuda-9.0/include/thrust/partition.h" "$(@D)/cuda/include/thrust/partition.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random.h" "$(@D)/cuda/include/thrust/random.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/discard_block_engine.inl" "$(@D)/cuda/include/thrust/random/detail/discard_block_engine.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/linear_congruential_engine.inl" "$(@D)/cuda/include/thrust/random/detail/linear_congruential_engine.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/linear_congruential_engine_discard.h" "$(@D)/cuda/include/thrust/random/detail/linear_congruential_engine_discard.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/linear_feedback_shift_engine.inl" "$(@D)/cuda/include/thrust/random/detail/linear_feedback_shift_engine.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/linear_feedback_shift_engine_wordmask.h" "$(@D)/cuda/include/thrust/random/detail/linear_feedback_shift_engine_wordmask.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/mod.h" "$(@D)/cuda/include/thrust/random/detail/mod.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/normal_distribution.inl" "$(@D)/cuda/include/thrust/random/detail/normal_distribution.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/normal_distribution_base.h" "$(@D)/cuda/include/thrust/random/detail/normal_distribution_base.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/random_core_access.h" "$(@D)/cuda/include/thrust/random/detail/random_core_access.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/subtract_with_carry_engine.inl" "$(@D)/cuda/include/thrust/random/detail/subtract_with_carry_engine.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/uniform_int_distribution.inl" "$(@D)/cuda/include/thrust/random/detail/uniform_int_distribution.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/uniform_real_distribution.inl" "$(@D)/cuda/include/thrust/random/detail/uniform_real_distribution.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/xor_combine_engine.inl" "$(@D)/cuda/include/thrust/random/detail/xor_combine_engine.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/random/detail/xor_combine_engine_max.h" "$(@D)/cuda/include/thrust/random/detail/xor_combine_engine_max.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/discard_block_engine.h" "$(@D)/cuda/include/thrust/random/discard_block_engine.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/linear_congruential_engine.h" "$(@D)/cuda/include/thrust/random/linear_congruential_engine.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/linear_feedback_shift_engine.h" "$(@D)/cuda/include/thrust/random/linear_feedback_shift_engine.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/normal_distribution.h" "$(@D)/cuda/include/thrust/random/normal_distribution.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/subtract_with_carry_engine.h" "$(@D)/cuda/include/thrust/random/subtract_with_carry_engine.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/uniform_int_distribution.h" "$(@D)/cuda/include/thrust/random/uniform_int_distribution.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/uniform_real_distribution.h" "$(@D)/cuda/include/thrust/random/uniform_real_distribution.h" && cp -f "/usr/local/cuda-9.0/include/thrust/random/xor_combine_engine.h" "$(@D)/cuda/include/thrust/random/xor_combine_engine.h" && cp -f "/usr/local/cuda-9.0/include/thrust/reduce.h" "$(@D)/cuda/include/thrust/reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/remove.h" "$(@D)/cuda/include/thrust/remove.h" && cp -f "/usr/local/cuda-9.0/include/thrust/replace.h" "$(@D)/cuda/include/thrust/replace.h" && cp -f "/usr/local/cuda-9.0/include/thrust/reverse.h" "$(@D)/cuda/include/thrust/reverse.h" && cp -f "/usr/local/cuda-9.0/include/thrust/scan.h" "$(@D)/cuda/include/thrust/scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/scatter.h" "$(@D)/cuda/include/thrust/scatter.h" && cp -f "/usr/local/cuda-9.0/include/thrust/sequence.h" "$(@D)/cuda/include/thrust/sequence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/set_operations.h" "$(@D)/cuda/include/thrust/set_operations.h" && cp -f "/usr/local/cuda-9.0/include/thrust/sort.h" "$(@D)/cuda/include/thrust/sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/swap.h" "$(@D)/cuda/include/thrust/swap.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/cpp/detail/adjacent_difference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/cpp/detail/assign_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/cpp/detail/binary_search.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/copy.h" "$(@D)/cuda/include/thrust/system/cpp/detail/copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/cpp/detail/copy_if.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/count.h" "$(@D)/cuda/include/thrust/system/cpp/detail/count.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/equal.h" "$(@D)/cuda/include/thrust/system/cpp/detail/equal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/cpp/detail/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/extrema.h" "$(@D)/cuda/include/thrust/system/cpp/detail/extrema.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/fill.h" "$(@D)/cuda/include/thrust/system/cpp/detail/fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/find.h" "$(@D)/cuda/include/thrust/system/cpp/detail/find.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/for_each.h" "$(@D)/cuda/include/thrust/system/cpp/detail/for_each.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/gather.h" "$(@D)/cuda/include/thrust/system/cpp/detail/gather.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/generate.h" "$(@D)/cuda/include/thrust/system/cpp/detail/generate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/get_value.h" "$(@D)/cuda/include/thrust/system/cpp/detail/get_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/cpp/detail/inner_product.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/cpp/detail/iter_swap.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/logical.h" "$(@D)/cuda/include/thrust/system/cpp/detail/logical.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/cpp/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/memory.inl" "$(@D)/cuda/include/thrust/system/cpp/detail/memory.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/merge.h" "$(@D)/cuda/include/thrust/system/cpp/detail/merge.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/cpp/detail/mismatch.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/par.h" "$(@D)/cuda/include/thrust/system/cpp/detail/par.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/partition.h" "$(@D)/cuda/include/thrust/system/cpp/detail/partition.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/reduce.h" "$(@D)/cuda/include/thrust/system/cpp/detail/reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/cpp/detail/reduce_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/remove.h" "$(@D)/cuda/include/thrust/system/cpp/detail/remove.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/replace.h" "$(@D)/cuda/include/thrust/system/cpp/detail/replace.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/reverse.h" "$(@D)/cuda/include/thrust/system/cpp/detail/reverse.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/scan.h" "$(@D)/cuda/include/thrust/system/cpp/detail/scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/cpp/detail/scan_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/scatter.h" "$(@D)/cuda/include/thrust/system/cpp/detail/scatter.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/sequence.h" "$(@D)/cuda/include/thrust/system/cpp/detail/sequence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/cpp/detail/set_operations.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/sort.h" "$(@D)/cuda/include/thrust/system/cpp/detail/sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/cpp/detail/swap_ranges.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/cpp/detail/tabulate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/cpp/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/transform.h" "$(@D)/cuda/include/thrust/system/cpp/detail/transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/cpp/detail/transform_reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/cpp/detail/transform_scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/cpp/detail/uninitialized_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/cpp/detail/uninitialized_fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/unique.h" "$(@D)/cuda/include/thrust/system/cpp/detail/unique.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/cpp/detail/unique_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/detail/vector.inl" "$(@D)/cuda/include/thrust/system/cpp/detail/vector.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/execution_policy.h" "$(@D)/cuda/include/thrust/system/cpp/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/memory.h" "$(@D)/cuda/include/thrust/system/cpp/memory.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cpp/vector.h" "$(@D)/cuda/include/thrust/system/cpp/vector.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/config.h" "$(@D)/cuda/include/thrust/system/cuda/config.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/cuda/detail/adjacent_difference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/cuda/detail/assign_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/cuda/detail/binary_search.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/copy.h" "$(@D)/cuda/include/thrust/system/cuda/detail/copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/cuda/detail/copy_if.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/core/agent_launcher.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/agent_launcher.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/core/alignment.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/alignment.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/core/triple_chevron_launch.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/triple_chevron_launch.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/core/util.h" "$(@D)/cuda/include/thrust/system/cuda/detail/core/util.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/count.h" "$(@D)/cuda/include/thrust/system/cuda/detail/count.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cross_system.h" "$(@D)/cuda/include/thrust/system/cuda/detail/cross_system.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_histogram.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_downsweep.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_downsweep.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_upsweep.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_radix_sort_upsweep.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_reduce.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_reduce_by_key.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_reduce_by_key.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_rle.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_rle.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_scan.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_segment_fixup.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_segment_fixup.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_select_if.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_select_if.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_spmv_csrt.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_spmv_csrt.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_spmv_orig.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_spmv_orig.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/agent_spmv_row_based.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/agent_spmv_row_based.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/agent/single_pass_scan_operators.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/agent/single_pass_scan_operators.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_adjacent_difference.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_adjacent_difference.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_discontinuity.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_discontinuity.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_exchange.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_exchange.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_histogram.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_load.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_load.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_radix_rank.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_radix_rank.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_radix_sort.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_raking_layout.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_raking_layout.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_reduce.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_scan.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_shuffle.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_shuffle.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/block_store.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/block_store.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_atomic.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_atomic.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_histogram_sort.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking_commutative_only.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_raking_commutative_only.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_warp_reductions.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_reduce_warp_reductions.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_raking.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_raking.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans2.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans2.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans3.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/block/specializations/block_scan_warp_scans3.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/cub.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/cub.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_histogram.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_partition.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_partition.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_radix_sort.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_reduce.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_run_length_encode.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_run_length_encode.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_scan.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_segmented_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_segmented_radix_sort.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_segmented_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_segmented_reduce.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_select.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_select.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/device_spmv.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/device_spmv.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_histogram.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_histogram.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_radix_sort.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_radix_sort.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce_by_key.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_reduce_by_key.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_rle.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_rle.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_scan.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_select_if.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_select_if.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_csrt.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_csrt.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_orig.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_orig.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_row_based.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/device/dispatch/dispatch_spmv_row_based.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/grid/grid_barrier.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_barrier.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/grid/grid_even_share.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_even_share.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/grid/grid_mapping.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_mapping.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/grid/grid_queue.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/grid/grid_queue.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/host/mutex.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/host/mutex.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/arg_index_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/arg_index_input_iterator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/cache_modified_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/cache_modified_input_iterator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/cache_modified_output_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/cache_modified_output_iterator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/constant_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/constant_input_iterator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/counting_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/counting_input_iterator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/discard_output_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/discard_output_iterator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/tex_obj_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/tex_obj_input_iterator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/tex_ref_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/tex_ref_input_iterator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/iterator/transform_input_iterator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/iterator/transform_input_iterator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_load.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_load.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_operators.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_operators.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_reduce.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_scan.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_search.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_search.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/thread/thread_store.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/thread/thread_store.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_allocator.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_allocator.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_arch.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_arch.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_debug.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_debug.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_device.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_device.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_macro.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_macro.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_namespace.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_namespace.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_ptx.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_ptx.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/util_type.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/util_type.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_shfl.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_shfl.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_smem.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_reduce_smem.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_shfl.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_shfl.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_smem.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/specializations/warp_scan_smem.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/warp_reduce.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/warp_reduce.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/cub/warp/warp_scan.cuh" "$(@D)/cuda/include/thrust/system/cuda/detail/cub/warp/warp_scan.cuh" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/equal.h" "$(@D)/cuda/include/thrust/system/cuda/detail/equal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/error.inl" "$(@D)/cuda/include/thrust/system/cuda/detail/error.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/cuda/detail/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/extrema.h" "$(@D)/cuda/include/thrust/system/cuda/detail/extrema.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/fill.h" "$(@D)/cuda/include/thrust/system/cuda/detail/fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/find.h" "$(@D)/cuda/include/thrust/system/cuda/detail/find.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/for_each.h" "$(@D)/cuda/include/thrust/system/cuda/detail/for_each.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/gather.h" "$(@D)/cuda/include/thrust/system/cuda/detail/gather.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/generate.h" "$(@D)/cuda/include/thrust/system/cuda/detail/generate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/get_value.h" "$(@D)/cuda/include/thrust/system/cuda/detail/get_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/guarded_cuda_runtime_api.h" "$(@D)/cuda/include/thrust/system/cuda/detail/guarded_cuda_runtime_api.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/guarded_driver_types.h" "$(@D)/cuda/include/thrust/system/cuda/detail/guarded_driver_types.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/cuda/detail/inner_product.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/internal/copy_cross_system.h" "$(@D)/cuda/include/thrust/system/cuda/detail/internal/copy_cross_system.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/internal/copy_device_to_device.h" "$(@D)/cuda/include/thrust/system/cuda/detail/internal/copy_device_to_device.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/cuda/detail/iter_swap.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/logical.h" "$(@D)/cuda/include/thrust/system/cuda/detail/logical.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/cuda/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/memory.inl" "$(@D)/cuda/include/thrust/system/cuda/detail/memory.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/memory_buffer.h" "$(@D)/cuda/include/thrust/system/cuda/detail/memory_buffer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/merge.h" "$(@D)/cuda/include/thrust/system/cuda/detail/merge.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/cuda/detail/mismatch.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/par.h" "$(@D)/cuda/include/thrust/system/cuda/detail/par.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/par_to_seq.h" "$(@D)/cuda/include/thrust/system/cuda/detail/par_to_seq.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/parallel_for.h" "$(@D)/cuda/include/thrust/system/cuda/detail/parallel_for.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/partition.h" "$(@D)/cuda/include/thrust/system/cuda/detail/partition.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/reduce.h" "$(@D)/cuda/include/thrust/system/cuda/detail/reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/cuda/detail/reduce_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/remove.h" "$(@D)/cuda/include/thrust/system/cuda/detail/remove.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/replace.h" "$(@D)/cuda/include/thrust/system/cuda/detail/replace.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/reverse.h" "$(@D)/cuda/include/thrust/system/cuda/detail/reverse.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/scan.h" "$(@D)/cuda/include/thrust/system/cuda/detail/scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/cuda/detail/scan_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/scatter.h" "$(@D)/cuda/include/thrust/system/cuda/detail/scatter.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/sequence.h" "$(@D)/cuda/include/thrust/system/cuda/detail/sequence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/cuda/detail/set_operations.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/sort.h" "$(@D)/cuda/include/thrust/system/cuda/detail/sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/cuda/detail/swap_ranges.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/cuda/detail/tabulate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/cuda/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/terminate.h" "$(@D)/cuda/include/thrust/system/cuda/detail/terminate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/transform.h" "$(@D)/cuda/include/thrust/system/cuda/detail/transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/cuda/detail/transform_reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/cuda/detail/transform_scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/cuda/detail/uninitialized_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/cuda/detail/uninitialized_fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/unique.h" "$(@D)/cuda/include/thrust/system/cuda/detail/unique.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/cuda/detail/unique_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/util.h" "$(@D)/cuda/include/thrust/system/cuda/detail/util.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/detail/vector.inl" "$(@D)/cuda/include/thrust/system/cuda/detail/vector.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/error.h" "$(@D)/cuda/include/thrust/system/cuda/error.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/execution_policy.h" "$(@D)/cuda/include/thrust/system/cuda/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/experimental/pinned_allocator.h" "$(@D)/cuda/include/thrust/system/cuda/experimental/pinned_allocator.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/memory.h" "$(@D)/cuda/include/thrust/system/cuda/memory.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/cuda/vector.h" "$(@D)/cuda/include/thrust/system/cuda/vector.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/detail/adl/adjacent_difference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/assign_value.h" "$(@D)/cuda/include/thrust/system/detail/adl/assign_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/adl/binary_search.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/copy.h" "$(@D)/cuda/include/thrust/system/detail/adl/copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/copy_if.h" "$(@D)/cuda/include/thrust/system/detail/adl/copy_if.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/count.h" "$(@D)/cuda/include/thrust/system/detail/adl/count.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/equal.h" "$(@D)/cuda/include/thrust/system/detail/adl/equal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/extrema.h" "$(@D)/cuda/include/thrust/system/detail/adl/extrema.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/fill.h" "$(@D)/cuda/include/thrust/system/detail/adl/fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/find.h" "$(@D)/cuda/include/thrust/system/detail/adl/find.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/for_each.h" "$(@D)/cuda/include/thrust/system/detail/adl/for_each.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/gather.h" "$(@D)/cuda/include/thrust/system/detail/adl/gather.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/generate.h" "$(@D)/cuda/include/thrust/system/detail/adl/generate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/get_value.h" "$(@D)/cuda/include/thrust/system/detail/adl/get_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/inner_product.h" "$(@D)/cuda/include/thrust/system/detail/adl/inner_product.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/iter_swap.h" "$(@D)/cuda/include/thrust/system/detail/adl/iter_swap.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/logical.h" "$(@D)/cuda/include/thrust/system/detail/adl/logical.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/detail/adl/malloc_and_free.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/merge.h" "$(@D)/cuda/include/thrust/system/detail/adl/merge.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/mismatch.h" "$(@D)/cuda/include/thrust/system/detail/adl/mismatch.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/partition.h" "$(@D)/cuda/include/thrust/system/detail/adl/partition.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/reduce.h" "$(@D)/cuda/include/thrust/system/detail/adl/reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/detail/adl/reduce_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/remove.h" "$(@D)/cuda/include/thrust/system/detail/adl/remove.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/replace.h" "$(@D)/cuda/include/thrust/system/detail/adl/replace.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/reverse.h" "$(@D)/cuda/include/thrust/system/detail/adl/reverse.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/scan.h" "$(@D)/cuda/include/thrust/system/detail/adl/scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/scan_by_key.h" "$(@D)/cuda/include/thrust/system/detail/adl/scan_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/scatter.h" "$(@D)/cuda/include/thrust/system/detail/adl/scatter.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/sequence.h" "$(@D)/cuda/include/thrust/system/detail/adl/sequence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/set_operations.h" "$(@D)/cuda/include/thrust/system/detail/adl/set_operations.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/sort.h" "$(@D)/cuda/include/thrust/system/detail/adl/sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/swap_ranges.h" "$(@D)/cuda/include/thrust/system/detail/adl/swap_ranges.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/tabulate.h" "$(@D)/cuda/include/thrust/system/detail/adl/tabulate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/detail/adl/temporary_buffer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/transform.h" "$(@D)/cuda/include/thrust/system/detail/adl/transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/transform_reduce.h" "$(@D)/cuda/include/thrust/system/detail/adl/transform_reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/transform_scan.h" "$(@D)/cuda/include/thrust/system/detail/adl/transform_scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/detail/adl/uninitialized_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/detail/adl/uninitialized_fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/unique.h" "$(@D)/cuda/include/thrust/system/detail/adl/unique.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/adl/unique_by_key.h" "$(@D)/cuda/include/thrust/system/detail/adl/unique_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/bad_alloc.h" "$(@D)/cuda/include/thrust/system/detail/bad_alloc.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/errno.h" "$(@D)/cuda/include/thrust/system/detail/errno.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/error_category.inl" "$(@D)/cuda/include/thrust/system/detail/error_category.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/error_code.inl" "$(@D)/cuda/include/thrust/system/detail/error_code.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/error_condition.inl" "$(@D)/cuda/include/thrust/system/detail/error_condition.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/detail/generic/adjacent_difference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/adjacent_difference.inl" "$(@D)/cuda/include/thrust/system/detail/generic/adjacent_difference.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/advance.h" "$(@D)/cuda/include/thrust/system/detail/generic/advance.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/advance.inl" "$(@D)/cuda/include/thrust/system/detail/generic/advance.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/generic/binary_search.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/binary_search.inl" "$(@D)/cuda/include/thrust/system/detail/generic/binary_search.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/copy.h" "$(@D)/cuda/include/thrust/system/detail/generic/copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/copy.inl" "$(@D)/cuda/include/thrust/system/detail/generic/copy.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/copy_if.h" "$(@D)/cuda/include/thrust/system/detail/generic/copy_if.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/copy_if.inl" "$(@D)/cuda/include/thrust/system/detail/generic/copy_if.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/count.h" "$(@D)/cuda/include/thrust/system/detail/generic/count.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/count.inl" "$(@D)/cuda/include/thrust/system/detail/generic/count.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/distance.h" "$(@D)/cuda/include/thrust/system/detail/generic/distance.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/distance.inl" "$(@D)/cuda/include/thrust/system/detail/generic/distance.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/equal.h" "$(@D)/cuda/include/thrust/system/detail/generic/equal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/equal.inl" "$(@D)/cuda/include/thrust/system/detail/generic/equal.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/extrema.h" "$(@D)/cuda/include/thrust/system/detail/generic/extrema.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/extrema.inl" "$(@D)/cuda/include/thrust/system/detail/generic/extrema.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/fill.h" "$(@D)/cuda/include/thrust/system/detail/generic/fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/find.h" "$(@D)/cuda/include/thrust/system/detail/generic/find.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/find.inl" "$(@D)/cuda/include/thrust/system/detail/generic/find.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/for_each.h" "$(@D)/cuda/include/thrust/system/detail/generic/for_each.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/gather.h" "$(@D)/cuda/include/thrust/system/detail/generic/gather.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/gather.inl" "$(@D)/cuda/include/thrust/system/detail/generic/gather.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/generate.h" "$(@D)/cuda/include/thrust/system/detail/generic/generate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/generate.inl" "$(@D)/cuda/include/thrust/system/detail/generic/generate.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/inner_product.h" "$(@D)/cuda/include/thrust/system/detail/generic/inner_product.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/inner_product.inl" "$(@D)/cuda/include/thrust/system/detail/generic/inner_product.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/logical.h" "$(@D)/cuda/include/thrust/system/detail/generic/logical.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/memory.h" "$(@D)/cuda/include/thrust/system/detail/generic/memory.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/memory.inl" "$(@D)/cuda/include/thrust/system/detail/generic/memory.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/merge.h" "$(@D)/cuda/include/thrust/system/detail/generic/merge.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/merge.inl" "$(@D)/cuda/include/thrust/system/detail/generic/merge.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/mismatch.h" "$(@D)/cuda/include/thrust/system/detail/generic/mismatch.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/mismatch.inl" "$(@D)/cuda/include/thrust/system/detail/generic/mismatch.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/partition.h" "$(@D)/cuda/include/thrust/system/detail/generic/partition.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/partition.inl" "$(@D)/cuda/include/thrust/system/detail/generic/partition.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reduce.h" "$(@D)/cuda/include/thrust/system/detail/generic/reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reduce.inl" "$(@D)/cuda/include/thrust/system/detail/generic/reduce.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/detail/generic/reduce_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reduce_by_key.inl" "$(@D)/cuda/include/thrust/system/detail/generic/reduce_by_key.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/remove.h" "$(@D)/cuda/include/thrust/system/detail/generic/remove.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/remove.inl" "$(@D)/cuda/include/thrust/system/detail/generic/remove.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/replace.h" "$(@D)/cuda/include/thrust/system/detail/generic/replace.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/replace.inl" "$(@D)/cuda/include/thrust/system/detail/generic/replace.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reverse.h" "$(@D)/cuda/include/thrust/system/detail/generic/reverse.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/reverse.inl" "$(@D)/cuda/include/thrust/system/detail/generic/reverse.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scalar/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/generic/scalar/binary_search.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scalar/binary_search.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scalar/binary_search.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scan.h" "$(@D)/cuda/include/thrust/system/detail/generic/scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scan.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scan.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scan_by_key.h" "$(@D)/cuda/include/thrust/system/detail/generic/scan_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scan_by_key.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scan_by_key.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scatter.h" "$(@D)/cuda/include/thrust/system/detail/generic/scatter.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/scatter.inl" "$(@D)/cuda/include/thrust/system/detail/generic/scatter.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/select_system.h" "$(@D)/cuda/include/thrust/system/detail/generic/select_system.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/sequence.h" "$(@D)/cuda/include/thrust/system/detail/generic/sequence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/sequence.inl" "$(@D)/cuda/include/thrust/system/detail/generic/sequence.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/set_operations.h" "$(@D)/cuda/include/thrust/system/detail/generic/set_operations.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/set_operations.inl" "$(@D)/cuda/include/thrust/system/detail/generic/set_operations.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/sort.h" "$(@D)/cuda/include/thrust/system/detail/generic/sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/sort.inl" "$(@D)/cuda/include/thrust/system/detail/generic/sort.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/swap_ranges.h" "$(@D)/cuda/include/thrust/system/detail/generic/swap_ranges.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/swap_ranges.inl" "$(@D)/cuda/include/thrust/system/detail/generic/swap_ranges.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/tabulate.h" "$(@D)/cuda/include/thrust/system/detail/generic/tabulate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/tabulate.inl" "$(@D)/cuda/include/thrust/system/detail/generic/tabulate.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/tag.h" "$(@D)/cuda/include/thrust/system/detail/generic/tag.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/detail/generic/temporary_buffer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/temporary_buffer.inl" "$(@D)/cuda/include/thrust/system/detail/generic/temporary_buffer.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform.h" "$(@D)/cuda/include/thrust/system/detail/generic/transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform.inl" "$(@D)/cuda/include/thrust/system/detail/generic/transform.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform_reduce.h" "$(@D)/cuda/include/thrust/system/detail/generic/transform_reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform_reduce.inl" "$(@D)/cuda/include/thrust/system/detail/generic/transform_reduce.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform_scan.h" "$(@D)/cuda/include/thrust/system/detail/generic/transform_scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/transform_scan.inl" "$(@D)/cuda/include/thrust/system/detail/generic/transform_scan.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/type_traits.h" "$(@D)/cuda/include/thrust/system/detail/generic/type_traits.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/uninitialized_copy.inl" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_copy.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/uninitialized_fill.inl" "$(@D)/cuda/include/thrust/system/detail/generic/uninitialized_fill.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/unique.h" "$(@D)/cuda/include/thrust/system/detail/generic/unique.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/unique.inl" "$(@D)/cuda/include/thrust/system/detail/generic/unique.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/unique_by_key.h" "$(@D)/cuda/include/thrust/system/detail/generic/unique_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/generic/unique_by_key.inl" "$(@D)/cuda/include/thrust/system/detail/generic/unique_by_key.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/internal/decompose.h" "$(@D)/cuda/include/thrust/system/detail/internal/decompose.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/detail/sequential/adjacent_difference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/assign_value.h" "$(@D)/cuda/include/thrust/system/detail/sequential/assign_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/binary_search.h" "$(@D)/cuda/include/thrust/system/detail/sequential/binary_search.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/copy.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/copy.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/copy_backward.h" "$(@D)/cuda/include/thrust/system/detail/sequential/copy_backward.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/copy_if.h" "$(@D)/cuda/include/thrust/system/detail/sequential/copy_if.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/count.h" "$(@D)/cuda/include/thrust/system/detail/sequential/count.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/equal.h" "$(@D)/cuda/include/thrust/system/detail/sequential/equal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/execution_policy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/extrema.h" "$(@D)/cuda/include/thrust/system/detail/sequential/extrema.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/fill.h" "$(@D)/cuda/include/thrust/system/detail/sequential/fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/find.h" "$(@D)/cuda/include/thrust/system/detail/sequential/find.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/for_each.h" "$(@D)/cuda/include/thrust/system/detail/sequential/for_each.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/gather.h" "$(@D)/cuda/include/thrust/system/detail/sequential/gather.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/general_copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/general_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/generate.h" "$(@D)/cuda/include/thrust/system/detail/sequential/generate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/get_value.h" "$(@D)/cuda/include/thrust/system/detail/sequential/get_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/inner_product.h" "$(@D)/cuda/include/thrust/system/detail/sequential/inner_product.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/insertion_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/insertion_sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/iter_swap.h" "$(@D)/cuda/include/thrust/system/detail/sequential/iter_swap.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/logical.h" "$(@D)/cuda/include/thrust/system/detail/sequential/logical.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/detail/sequential/malloc_and_free.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/merge.h" "$(@D)/cuda/include/thrust/system/detail/sequential/merge.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/merge.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/merge.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/mismatch.h" "$(@D)/cuda/include/thrust/system/detail/sequential/mismatch.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/partition.h" "$(@D)/cuda/include/thrust/system/detail/sequential/partition.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/reduce.h" "$(@D)/cuda/include/thrust/system/detail/sequential/reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/detail/sequential/reduce_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/remove.h" "$(@D)/cuda/include/thrust/system/detail/sequential/remove.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/replace.h" "$(@D)/cuda/include/thrust/system/detail/sequential/replace.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/reverse.h" "$(@D)/cuda/include/thrust/system/detail/sequential/reverse.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/scan.h" "$(@D)/cuda/include/thrust/system/detail/sequential/scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/scan_by_key.h" "$(@D)/cuda/include/thrust/system/detail/sequential/scan_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/scatter.h" "$(@D)/cuda/include/thrust/system/detail/sequential/scatter.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/sequence.h" "$(@D)/cuda/include/thrust/system/detail/sequential/sequence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/set_operations.h" "$(@D)/cuda/include/thrust/system/detail/sequential/set_operations.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/sort.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_merge_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_merge_sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_merge_sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_merge_sort.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_primitive_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_primitive_sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_primitive_sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_primitive_sort.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_radix_sort.h" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_radix_sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/stable_radix_sort.inl" "$(@D)/cuda/include/thrust/system/detail/sequential/stable_radix_sort.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/swap_ranges.h" "$(@D)/cuda/include/thrust/system/detail/sequential/swap_ranges.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/tabulate.h" "$(@D)/cuda/include/thrust/system/detail/sequential/tabulate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/detail/sequential/temporary_buffer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/transform.h" "$(@D)/cuda/include/thrust/system/detail/sequential/transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/transform_reduce.h" "$(@D)/cuda/include/thrust/system/detail/sequential/transform_reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/transform_scan.h" "$(@D)/cuda/include/thrust/system/detail/sequential/transform_scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/trivial_copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/trivial_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/detail/sequential/uninitialized_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/detail/sequential/uninitialized_fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/unique.h" "$(@D)/cuda/include/thrust/system/detail/sequential/unique.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/sequential/unique_by_key.h" "$(@D)/cuda/include/thrust/system/detail/sequential/unique_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/detail/system_error.inl" "$(@D)/cuda/include/thrust/system/detail/system_error.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/error_code.h" "$(@D)/cuda/include/thrust/system/error_code.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/omp/detail/adjacent_difference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/omp/detail/assign_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/omp/detail/binary_search.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/copy.h" "$(@D)/cuda/include/thrust/system/omp/detail/copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/copy.inl" "$(@D)/cuda/include/thrust/system/omp/detail/copy.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/omp/detail/copy_if.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/copy_if.inl" "$(@D)/cuda/include/thrust/system/omp/detail/copy_if.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/count.h" "$(@D)/cuda/include/thrust/system/omp/detail/count.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/default_decomposition.h" "$(@D)/cuda/include/thrust/system/omp/detail/default_decomposition.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/default_decomposition.inl" "$(@D)/cuda/include/thrust/system/omp/detail/default_decomposition.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/equal.h" "$(@D)/cuda/include/thrust/system/omp/detail/equal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/omp/detail/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/extrema.h" "$(@D)/cuda/include/thrust/system/omp/detail/extrema.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/fill.h" "$(@D)/cuda/include/thrust/system/omp/detail/fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/find.h" "$(@D)/cuda/include/thrust/system/omp/detail/find.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/for_each.h" "$(@D)/cuda/include/thrust/system/omp/detail/for_each.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/for_each.inl" "$(@D)/cuda/include/thrust/system/omp/detail/for_each.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/gather.h" "$(@D)/cuda/include/thrust/system/omp/detail/gather.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/generate.h" "$(@D)/cuda/include/thrust/system/omp/detail/generate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/get_value.h" "$(@D)/cuda/include/thrust/system/omp/detail/get_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/omp/detail/inner_product.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/omp/detail/iter_swap.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/logical.h" "$(@D)/cuda/include/thrust/system/omp/detail/logical.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/omp/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/memory.inl" "$(@D)/cuda/include/thrust/system/omp/detail/memory.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/merge.h" "$(@D)/cuda/include/thrust/system/omp/detail/merge.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/omp/detail/mismatch.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/par.h" "$(@D)/cuda/include/thrust/system/omp/detail/par.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/partition.h" "$(@D)/cuda/include/thrust/system/omp/detail/partition.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/partition.inl" "$(@D)/cuda/include/thrust/system/omp/detail/partition.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce.h" "$(@D)/cuda/include/thrust/system/omp/detail/reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce.inl" "$(@D)/cuda/include/thrust/system/omp/detail/reduce.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce_by_key.inl" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_by_key.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce_intervals.h" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_intervals.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reduce_intervals.inl" "$(@D)/cuda/include/thrust/system/omp/detail/reduce_intervals.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/remove.h" "$(@D)/cuda/include/thrust/system/omp/detail/remove.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/remove.inl" "$(@D)/cuda/include/thrust/system/omp/detail/remove.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/replace.h" "$(@D)/cuda/include/thrust/system/omp/detail/replace.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/reverse.h" "$(@D)/cuda/include/thrust/system/omp/detail/reverse.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/scan.h" "$(@D)/cuda/include/thrust/system/omp/detail/scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/omp/detail/scan_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/scatter.h" "$(@D)/cuda/include/thrust/system/omp/detail/scatter.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/sequence.h" "$(@D)/cuda/include/thrust/system/omp/detail/sequence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/omp/detail/set_operations.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/sort.h" "$(@D)/cuda/include/thrust/system/omp/detail/sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/sort.inl" "$(@D)/cuda/include/thrust/system/omp/detail/sort.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/omp/detail/swap_ranges.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/omp/detail/tabulate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/omp/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/transform.h" "$(@D)/cuda/include/thrust/system/omp/detail/transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/omp/detail/transform_reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/omp/detail/transform_scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/omp/detail/uninitialized_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/omp/detail/uninitialized_fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/unique.h" "$(@D)/cuda/include/thrust/system/omp/detail/unique.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/unique.inl" "$(@D)/cuda/include/thrust/system/omp/detail/unique.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/omp/detail/unique_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/unique_by_key.inl" "$(@D)/cuda/include/thrust/system/omp/detail/unique_by_key.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/detail/vector.inl" "$(@D)/cuda/include/thrust/system/omp/detail/vector.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/execution_policy.h" "$(@D)/cuda/include/thrust/system/omp/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/memory.h" "$(@D)/cuda/include/thrust/system/omp/memory.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/omp/vector.h" "$(@D)/cuda/include/thrust/system/omp/vector.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/system_error.h" "$(@D)/cuda/include/thrust/system/system_error.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/adjacent_difference.h" "$(@D)/cuda/include/thrust/system/tbb/detail/adjacent_difference.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/assign_value.h" "$(@D)/cuda/include/thrust/system/tbb/detail/assign_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/binary_search.h" "$(@D)/cuda/include/thrust/system/tbb/detail/binary_search.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/copy.h" "$(@D)/cuda/include/thrust/system/tbb/detail/copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/copy.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/copy.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/copy_if.h" "$(@D)/cuda/include/thrust/system/tbb/detail/copy_if.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/copy_if.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/copy_if.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/count.h" "$(@D)/cuda/include/thrust/system/tbb/detail/count.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/equal.h" "$(@D)/cuda/include/thrust/system/tbb/detail/equal.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/execution_policy.h" "$(@D)/cuda/include/thrust/system/tbb/detail/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/extrema.h" "$(@D)/cuda/include/thrust/system/tbb/detail/extrema.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/fill.h" "$(@D)/cuda/include/thrust/system/tbb/detail/fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/find.h" "$(@D)/cuda/include/thrust/system/tbb/detail/find.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/for_each.h" "$(@D)/cuda/include/thrust/system/tbb/detail/for_each.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/for_each.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/for_each.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/gather.h" "$(@D)/cuda/include/thrust/system/tbb/detail/gather.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/generate.h" "$(@D)/cuda/include/thrust/system/tbb/detail/generate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/get_value.h" "$(@D)/cuda/include/thrust/system/tbb/detail/get_value.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/inner_product.h" "$(@D)/cuda/include/thrust/system/tbb/detail/inner_product.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/iter_swap.h" "$(@D)/cuda/include/thrust/system/tbb/detail/iter_swap.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/logical.h" "$(@D)/cuda/include/thrust/system/tbb/detail/logical.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/malloc_and_free.h" "$(@D)/cuda/include/thrust/system/tbb/detail/malloc_and_free.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/memory.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/memory.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/merge.h" "$(@D)/cuda/include/thrust/system/tbb/detail/merge.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/merge.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/merge.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/mismatch.h" "$(@D)/cuda/include/thrust/system/tbb/detail/mismatch.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/par.h" "$(@D)/cuda/include/thrust/system/tbb/detail/par.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/partition.h" "$(@D)/cuda/include/thrust/system/tbb/detail/partition.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/partition.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/partition.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce_by_key.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce_by_key.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce_by_key.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reduce_intervals.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reduce_intervals.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/remove.h" "$(@D)/cuda/include/thrust/system/tbb/detail/remove.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/remove.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/remove.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/replace.h" "$(@D)/cuda/include/thrust/system/tbb/detail/replace.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/reverse.h" "$(@D)/cuda/include/thrust/system/tbb/detail/reverse.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/scan.h" "$(@D)/cuda/include/thrust/system/tbb/detail/scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/scan.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/scan.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/scan_by_key.h" "$(@D)/cuda/include/thrust/system/tbb/detail/scan_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/scatter.h" "$(@D)/cuda/include/thrust/system/tbb/detail/scatter.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/sequence.h" "$(@D)/cuda/include/thrust/system/tbb/detail/sequence.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/set_operations.h" "$(@D)/cuda/include/thrust/system/tbb/detail/set_operations.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/sort.h" "$(@D)/cuda/include/thrust/system/tbb/detail/sort.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/sort.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/sort.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/swap_ranges.h" "$(@D)/cuda/include/thrust/system/tbb/detail/swap_ranges.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/tabulate.h" "$(@D)/cuda/include/thrust/system/tbb/detail/tabulate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/temporary_buffer.h" "$(@D)/cuda/include/thrust/system/tbb/detail/temporary_buffer.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/transform.h" "$(@D)/cuda/include/thrust/system/tbb/detail/transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/transform_reduce.h" "$(@D)/cuda/include/thrust/system/tbb/detail/transform_reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/transform_scan.h" "$(@D)/cuda/include/thrust/system/tbb/detail/transform_scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/uninitialized_copy.h" "$(@D)/cuda/include/thrust/system/tbb/detail/uninitialized_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/uninitialized_fill.h" "$(@D)/cuda/include/thrust/system/tbb/detail/uninitialized_fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/unique.h" "$(@D)/cuda/include/thrust/system/tbb/detail/unique.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/unique.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/unique.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/unique_by_key.h" "$(@D)/cuda/include/thrust/system/tbb/detail/unique_by_key.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/unique_by_key.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/unique_by_key.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/detail/vector.inl" "$(@D)/cuda/include/thrust/system/tbb/detail/vector.inl" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/execution_policy.h" "$(@D)/cuda/include/thrust/system/tbb/execution_policy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/memory.h" "$(@D)/cuda/include/thrust/system/tbb/memory.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system/tbb/vector.h" "$(@D)/cuda/include/thrust/system/tbb/vector.h" && cp -f "/usr/local/cuda-9.0/include/thrust/system_error.h" "$(@D)/cuda/include/thrust/system_error.h" && cp -f "/usr/local/cuda-9.0/include/thrust/tabulate.h" "$(@D)/cuda/include/thrust/tabulate.h" && cp -f "/usr/local/cuda-9.0/include/thrust/transform.h" "$(@D)/cuda/include/thrust/transform.h" && cp -f "/usr/local/cuda-9.0/include/thrust/transform_reduce.h" "$(@D)/cuda/include/thrust/transform_reduce.h" && cp -f "/usr/local/cuda-9.0/include/thrust/transform_scan.h" "$(@D)/cuda/include/thrust/transform_scan.h" && cp -f "/usr/local/cuda-9.0/include/thrust/tuple.h" "$(@D)/cuda/include/thrust/tuple.h" && cp -f "/usr/local/cuda-9.0/include/thrust/uninitialized_copy.h" "$(@D)/cuda/include/thrust/uninitialized_copy.h" && cp -f "/usr/local/cuda-9.0/include/thrust/uninitialized_fill.h" "$(@D)/cuda/include/thrust/uninitialized_fill.h" && cp -f "/usr/local/cuda-9.0/include/thrust/unique.h" "$(@D)/cuda/include/thrust/unique.h" && cp -f "/usr/local/cuda-9.0/include/thrust/version.h" "$(@D)/cuda/include/thrust/version.h" && cp -f "/usr/local/cuda-9.0/include/vector_functions.h" "$(@D)/cuda/include/vector_functions.h" && cp -f "/usr/local/cuda-9.0/include/vector_functions.hpp" "$(@D)/cuda/include/vector_functions.hpp" && cp -f "/usr/local/cuda-9.0/include/vector_types.h" "$(@D)/cuda/include/vector_types.h" """, ) @@ -1198,7 +1198,7 @@ genrule( "cuda/nvvm/libdevice/libdevice.10.bc", ], cmd = """ -if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp "/usr/local/cuda-9.0/nvvm/libdevice/libdevice.10.bc" "$(@D)//libdevice.10.bc" +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/local/cuda-9.0/nvvm/libdevice/libdevice.10.bc" "$(@D)//libdevice.10.bc" """, ) @@ -1235,7 +1235,7 @@ genrule( "cuda/extras/CUPTI/include/openacc/cupti_openacc.h", ], cmd = """ -if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp "/usr/local/cuda-9.0/extras/CUPTI/include/GL/gl.h" "$(@D)/cuda/extras/CUPTI/include/GL/gl.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glew.h" "$(@D)/cuda/extras/CUPTI/include/GL/glew.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glext.h" "$(@D)/cuda/extras/CUPTI/include/GL/glext.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glu.h" "$(@D)/cuda/extras/CUPTI/include/GL/glu.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glut.h" "$(@D)/cuda/extras/CUPTI/include/GL/glut.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glx.h" "$(@D)/cuda/extras/CUPTI/include/GL/glx.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glxext.h" "$(@D)/cuda/extras/CUPTI/include/GL/glxext.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/GL/wglew.h" "$(@D)/cuda/extras/CUPTI/include/GL/wglew.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/GL/wglext.h" "$(@D)/cuda/extras/CUPTI/include/GL/wglext.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cuda_stdint.h" "$(@D)/cuda/extras/CUPTI/include/cuda_stdint.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti.h" "$(@D)/cuda/extras/CUPTI/include/cupti.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_activity.h" "$(@D)/cuda/extras/CUPTI/include/cupti_activity.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_callbacks.h" "$(@D)/cuda/extras/CUPTI/include/cupti_callbacks.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_driver_cbid.h" "$(@D)/cuda/extras/CUPTI/include/cupti_driver_cbid.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_events.h" "$(@D)/cuda/extras/CUPTI/include/cupti_events.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_metrics.h" "$(@D)/cuda/extras/CUPTI/include/cupti_metrics.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_nvtx_cbid.h" "$(@D)/cuda/extras/CUPTI/include/cupti_nvtx_cbid.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_result.h" "$(@D)/cuda/extras/CUPTI/include/cupti_result.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_runtime_cbid.h" "$(@D)/cuda/extras/CUPTI/include/cupti_runtime_cbid.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_version.h" "$(@D)/cuda/extras/CUPTI/include/cupti_version.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cudaGL_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cudaGL_meta.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cudaVDPAU_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cudaVDPAU_meta.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cuda_gl_interop_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_gl_interop_meta.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cuda_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_meta.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cuda_runtime_api_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_runtime_api_meta.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cuda_vdpau_interop_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_vdpau_interop_meta.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/generated_nvtx_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_nvtx_meta.h" && cp "/usr/local/cuda-9.0/extras/CUPTI/include/openacc/cupti_openacc.h" "$(@D)/cuda/extras/CUPTI/include/openacc/cupti_openacc.h" +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/GL/gl.h" "$(@D)/cuda/extras/CUPTI/include/GL/gl.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glew.h" "$(@D)/cuda/extras/CUPTI/include/GL/glew.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glext.h" "$(@D)/cuda/extras/CUPTI/include/GL/glext.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glu.h" "$(@D)/cuda/extras/CUPTI/include/GL/glu.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glut.h" "$(@D)/cuda/extras/CUPTI/include/GL/glut.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glx.h" "$(@D)/cuda/extras/CUPTI/include/GL/glx.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/GL/glxext.h" "$(@D)/cuda/extras/CUPTI/include/GL/glxext.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/GL/wglew.h" "$(@D)/cuda/extras/CUPTI/include/GL/wglew.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/GL/wglext.h" "$(@D)/cuda/extras/CUPTI/include/GL/wglext.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cuda_stdint.h" "$(@D)/cuda/extras/CUPTI/include/cuda_stdint.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti.h" "$(@D)/cuda/extras/CUPTI/include/cupti.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_activity.h" "$(@D)/cuda/extras/CUPTI/include/cupti_activity.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_callbacks.h" "$(@D)/cuda/extras/CUPTI/include/cupti_callbacks.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_driver_cbid.h" "$(@D)/cuda/extras/CUPTI/include/cupti_driver_cbid.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_events.h" "$(@D)/cuda/extras/CUPTI/include/cupti_events.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_metrics.h" "$(@D)/cuda/extras/CUPTI/include/cupti_metrics.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_nvtx_cbid.h" "$(@D)/cuda/extras/CUPTI/include/cupti_nvtx_cbid.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_result.h" "$(@D)/cuda/extras/CUPTI/include/cupti_result.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_runtime_cbid.h" "$(@D)/cuda/extras/CUPTI/include/cupti_runtime_cbid.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/cupti_version.h" "$(@D)/cuda/extras/CUPTI/include/cupti_version.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cudaGL_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cudaGL_meta.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cudaVDPAU_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cudaVDPAU_meta.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cuda_gl_interop_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_gl_interop_meta.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cuda_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_meta.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cuda_runtime_api_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_runtime_api_meta.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/generated_cuda_vdpau_interop_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_cuda_vdpau_interop_meta.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/generated_nvtx_meta.h" "$(@D)/cuda/extras/CUPTI/include/generated_nvtx_meta.h" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/include/openacc/cupti_openacc.h" "$(@D)/cuda/extras/CUPTI/include/openacc/cupti_openacc.h" """, ) @@ -1253,7 +1253,7 @@ genrule( "cuda/lib/libcupti.so.9.0", ], cmd = """ -if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp "/usr/local/cuda-9.0/targets/x86_64-linux/lib/stubs/libcuda.so" "$(@D)/cuda/lib/libcuda.so" && cp "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcudart.so.9.0.176" "$(@D)/cuda/lib/libcudart.so.9.0" && cp "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcudart_static.a" "$(@D)/cuda/lib/libcudart_static.a" && cp "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcublas.so.9.0.480" "$(@D)/cuda/lib/libcublas.so.9.0" && cp "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcusolver.so.9.0.176" "$(@D)/cuda/lib/libcusolver.so.9.0" && cp "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcurand.so.9.0.176" "$(@D)/cuda/lib/libcurand.so.9.0" && cp "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcufft.so.9.0.176" "$(@D)/cuda/lib/libcufft.so.9.0" && cp "/usr/lib/x86_64-linux-gnu/libcudnn.so.7.1.4" "$(@D)/cuda/lib/libcudnn.so.7" && cp "/usr/local/cuda/extras/CUPTI/lib64/libcupti.so.9.0.176" "$(@D)/cuda/lib/libcupti.so.9.0" +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/local/cuda-9.0/targets/x86_64-linux/lib/stubs/libcuda.so" "$(@D)/cuda/lib/libcuda.so" && cp -f "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcudart.so.9.0.176" "$(@D)/cuda/lib/libcudart.so.9.0" && cp -f "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcudart_static.a" "$(@D)/cuda/lib/libcudart_static.a" && cp -f "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcublas.so.9.0.480" "$(@D)/cuda/lib/libcublas.so.9.0" && cp -f "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcusolver.so.9.0.176" "$(@D)/cuda/lib/libcusolver.so.9.0" && cp -f "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcurand.so.9.0.176" "$(@D)/cuda/lib/libcurand.so.9.0" && cp -f "/usr/local/cuda-9.0/targets/x86_64-linux/lib/libcufft.so.9.0.176" "$(@D)/cuda/lib/libcufft.so.9.0" && cp -f "/usr/lib/x86_64-linux-gnu/libcudnn.so.7.1.4" "$(@D)/cuda/lib/libcudnn.so.7" && cp -f "/usr/local/cuda-9.0/extras/CUPTI/lib64/libcupti.so.9.0.176" "$(@D)/cuda/lib/libcupti.so.9.0" """, ) @@ -1263,6 +1263,6 @@ genrule( "cuda/include/cudnn.h", ], cmd = """ -if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp "/usr/include/cudnn.h" "$(@D)/cudnn.h" +if [ -d "$(@D)/extras" ]; then rm $(@D)/extras -drf; fi && if [ -d "$(@D)/include" ]; then rm $(@D)/include -drf; fi && if [ -d "$(@D)/lib" ]; then rm $(@D)/lib -drf; fi && if [ -d "$(@D)/nvvm" ]; then rm $(@D)/nvvm -drf; fi && cp -f "/usr/include/cudnn.h" "$(@D)/cudnn.h" """, ) diff --git a/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/build_defs.bzl b/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/build_defs.bzl index 5c6703aab4..a53c891d8b 100755 --- a/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/build_defs.bzl +++ b/third_party/toolchains/preconfig/ubuntu14.04/cuda9.0-cudnn7/cuda/build_defs.bzl @@ -9,15 +9,13 @@ def if_cuda(if_true, if_false = []): return select({ "@local_config_cuda//cuda:using_nvcc": if_true, "@local_config_cuda//cuda:using_clang": if_true, - "//conditions:default": if_false + "//conditions:default": if_false, }) - def cuda_default_copts(): """Default options for all CUDA compilations.""" return if_cuda(["-x", "cuda", "-DGOOGLE_CUDA=1"] + []) - def cuda_is_configured(): """Returns true if CUDA was enabled during the configure process.""" return True @@ -29,5 +27,5 @@ def if_cuda_is_configured(x): --config=cuda. Used to allow non-CUDA code to depend on CUDA libraries. """ if cuda_is_configured(): - return x + return x return [] diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/BUILD b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/BUILD new file mode 100755 index 0000000000..6442e7628a --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/BUILD @@ -0,0 +1,87 @@ +licenses(["restricted"]) + +package(default_visibility = ["//visibility:public"]) + +toolchain( + name = "toolchain-linux-x86_64", + exec_compatible_with = [ + "@bazel_tools//platforms:linux", + "@bazel_tools//platforms:x86_64", + ], + target_compatible_with = [ + "@bazel_tools//platforms:linux", + "@bazel_tools//platforms:x86_64", + ], + toolchain = ":cc-compiler-local", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +cc_toolchain_suite( + name = "toolchain", + toolchains = { + "local|compiler": ":cc-compiler-local", + "darwin|compiler": ":cc-compiler-darwin", + "x64_windows|msvc-cl": ":cc-compiler-windows", + }, +) + +cc_toolchain( + name = "cc-compiler-local", + all_files = ":crosstool_wrapper_driver_is_not_gcc", + compiler_files = ":empty", + cpu = "local", + dwp_files = ":empty", + dynamic_runtime_libs = [":empty"], + linker_files = ":crosstool_wrapper_driver_is_not_gcc", + objcopy_files = ":empty", + static_runtime_libs = [":empty"], + strip_files = ":empty", + # To support linker flags that need to go to the start of command line + # we need the toolchain to support parameter files. Parameter files are + # last on the command line and contain all shared libraries to link, so all + # regular options will be left of them. + supports_param_files = 1, +) + +cc_toolchain( + name = "cc-compiler-darwin", + all_files = ":crosstool_wrapper_driver_is_not_gcc", + compiler_files = ":empty", + cpu = "darwin", + dwp_files = ":empty", + dynamic_runtime_libs = [":empty"], + linker_files = ":crosstool_wrapper_driver_is_not_gcc", + objcopy_files = ":empty", + static_runtime_libs = [":empty"], + strip_files = ":empty", + supports_param_files = 0, +) + +cc_toolchain( + name = "cc-compiler-windows", + all_files = ":windows_msvc_wrapper_files", + compiler_files = ":empty", + cpu = "x64_windows", + dwp_files = ":empty", + dynamic_runtime_libs = [":empty"], + linker_files = ":windows_msvc_wrapper_files", + objcopy_files = ":empty", + static_runtime_libs = [":empty"], + strip_files = ":empty", + supports_param_files = 1, +) + +filegroup( + name = "empty", + srcs = [], +) + +filegroup( + name = "crosstool_wrapper_driver_is_not_gcc", + srcs = ["clang/bin/crosstool_wrapper_driver_is_not_gcc"], +) + +filegroup( + name = "windows_msvc_wrapper_files", + srcs = glob(["windows/msvc_*"]), +) diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/CROSSTOOL b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/CROSSTOOL new file mode 100755 index 0000000000..1c2e8bcae6 --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/CROSSTOOL @@ -0,0 +1,1431 @@ +major_version: "local" +minor_version: "" +default_target_cpu: "same_as_host" + +default_toolchain { + cpu: "k8" + toolchain_identifier: "local_linux" +} +default_toolchain { + cpu: "piii" + toolchain_identifier: "local_linux" +} +default_toolchain { + cpu: "arm" + toolchain_identifier: "local_linux" +} +default_toolchain { + cpu: "darwin" + toolchain_identifier: "local_darwin" +} +default_toolchain { + cpu: "ppc" + toolchain_identifier: "local_linux" +} +default_toolchain { + cpu: "x64_windows" + toolchain_identifier: "local_windows" +} + +toolchain { + abi_version: "local" + abi_libc_version: "local" + compiler: "compiler" + host_system_name: "local" + needsPic: true + target_libc: "local" + target_cpu: "local" + target_system_name: "local" + toolchain_identifier: "local_linux" + + feature { + name: "c++11" + flag_set { + action: "c++-compile" + flag_group { + flag: "-std=c++11" + } + } + } + + feature { + name: "stdlib" + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-lstdc++" + } + } + } + + feature { + name: "determinism" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # Make C++ compilation deterministic. Use linkstamping instead of these + # compiler symbols. + flag: "-Wno-builtin-macro-redefined" + flag: "-D__DATE__=\"redacted\"" + flag: "-D__TIMESTAMP__=\"redacted\"" + flag: "-D__TIME__=\"redacted\"" + } + } + } + + feature { + name: "alwayslink" + flag_set { + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-executable" + flag_group { + flag: "-Wl,-no-as-needed" + } + } + } + + # This feature will be enabled for builds that support pic by bazel. + feature { + name: "pic" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + expand_if_all_available: "pic" + flag: "-fPIC" + } + flag_group { + expand_if_none_available: "pic" + flag: "-fPIE" + } + } + } + + # Security hardening on by default. + feature { + name: "hardening" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # Conservative choice; -D_FORTIFY_SOURCE=2 may be unsafe in some cases. + # We need to undef it before redefining it as some distributions now + # have it enabled by default. + flag: "-U_FORTIFY_SOURCE" + flag: "-D_FORTIFY_SOURCE=1" + flag: "-fstack-protector" + } + } + flag_set { + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-Wl,-z,relro,-z,now" + } + } + flag_set { + action: "c++-link-executable" + flag_group { + flag: "-pie" + flag: "-Wl,-z,relro,-z,now" + } + } + } + + feature { + name: "warnings" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # All warnings are enabled. Maybe enable -Werror as well? + flag: "-Wall" + + } + } + } + + # Keep stack frames for debugging, even in opt mode. + feature { + name: "frame-pointer" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-fno-omit-frame-pointer" + } + } + } + + feature { + name: "build-id" + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + # Stamp the binary with a unique identifier. + flag: "-Wl,--build-id=md5" + flag: "-Wl,--hash-style=gnu" + } + } + } + + feature { + name: "no-canonical-prefixes" + flag_set { + action: "c-compile" + action: "c++-compile" + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-no-canonical-prefixes" + flag: "-fno-canonical-system-headers" + } + } + } + + feature { + name: "disable-assertions" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-DNDEBUG" + } + } + } + + feature { + name: "linker-bin-path" + + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-B/usr/bin" + } + } + } + + feature { + name: "common" + implies: "stdlib" + implies: "c++11" + implies: "determinism" + implies: "alwayslink" + implies: "hardening" + implies: "warnings" + implies: "frame-pointer" + implies: "build-id" + implies: "no-canonical-prefixes" + implies: "linker-bin-path" + } + + feature { + name: "opt" + implies: "common" + implies: "disable-assertions" + + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # No debug symbols. + # Maybe we should enable https://gcc.gnu.org/wiki/DebugFission for opt + # or even generally? However, that can't happen here, as it requires + # special handling in Bazel. + flag: "-g0" + + # Conservative choice for -O + # -O3 can increase binary size and even slow down the resulting binaries. + # Profile first and / or use FDO if you need better performance than this. + flag: "-O2" + + # Removal of unused code and data at link time (can this increase binary size in some cases?). + flag: "-ffunction-sections" + flag: "-fdata-sections" + } + } + flag_set { + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-executable" + flag_group { + flag: "-Wl,--gc-sections" + } + } + } + + feature { + name: "fastbuild" + implies: "common" + } + + feature { + name: "dbg" + implies: "common" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-g" + } + } + } + + # Set clang as a C/C++ compiler. + tool_path { name: "gcc" path: "clang/bin/crosstool_wrapper_driver_is_not_gcc" } + + # Use the default system toolchain for everything else. + tool_path { name: "ar" path: "/usr/bin/ar" } + tool_path { name: "compat-ld" path: "/usr/bin/ld" } + tool_path { name: "cpp" path: "/usr/bin/cpp" } + tool_path { name: "dwp" path: "/usr/bin/dwp" } + tool_path { name: "gcov" path: "/usr/bin/gcov" } + tool_path { name: "ld" path: "/usr/bin/ld" } + tool_path { name: "nm" path: "/usr/bin/nm" } + tool_path { name: "objcopy" path: "/usr/bin/objcopy" } + tool_path { name: "objdump" path: "/usr/bin/objdump" } + tool_path { name: "strip" path: "/usr/bin/strip" } + + # Enabled dynamic linking. + linking_mode_flags { mode: DYNAMIC } + + cxx_builtin_include_directory: "/usr/include/c++/4.8" + cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu/c++/4.8" + cxx_builtin_include_directory: "/usr/include/c++/4.8/backward" + cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/4.8/include" + cxx_builtin_include_directory: "/usr/local/include" + cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed" + cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu" + cxx_builtin_include_directory: "/usr/include" + cxx_builtin_include_directory: "/usr/local/cuda-10.0/targets/x86_64-linux/include" + cxx_builtin_include_directory: "/usr/local/cuda-10.0/include" + cxx_builtin_include_directory: "/usr/local/cuda-10.0/extras/CUPTI/include" + cxx_builtin_include_directory: "/usr/include" +} + +toolchain { + abi_version: "local" + abi_libc_version: "local" + compiler: "compiler" + host_system_name: "local" + needsPic: true + target_libc: "macosx" + target_cpu: "darwin" + target_system_name: "local" + toolchain_identifier: "local_darwin" + feature { + name: "c++11" + flag_set { + action: "c++-compile" + flag_group { + flag: "-std=c++11" + } + } + } + + feature { + name: "stdlib" + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-lc++" + } + } + } + + feature { + name: "determinism" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # Make C++ compilation deterministic. Use linkstamping instead of these + # compiler symbols. + flag: "-Wno-builtin-macro-redefined" + flag: "-D__DATE__=\"redacted\"" + flag: "-D__TIMESTAMP__=\"redacted\"" + flag: "-D__TIME__=\"redacted\"" + } + } + } + + # This feature will be enabled for builds that support pic by bazel. + feature { + name: "pic" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + expand_if_all_available: "pic" + flag: "-fPIC" + } + flag_group { + expand_if_none_available: "pic" + flag: "-fPIE" + } + } + } + + # Security hardening on by default. + feature { + name: "hardening" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # Conservative choice; -D_FORTIFY_SOURCE=2 may be unsafe in some cases. + # We need to undef it before redefining it as some distributions now + # have it enabled by default. + flag: "-U_FORTIFY_SOURCE" + flag: "-D_FORTIFY_SOURCE=1" + flag: "-fstack-protector" + } + } + flag_set { + action: "c++-link-executable" + flag_group { + flag: "-pie" + } + } + } + + feature { + name: "warnings" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # All warnings are enabled. Maybe enable -Werror as well? + flag: "-Wall" + + } + } + } + + # Keep stack frames for debugging, even in opt mode. + feature { + name: "frame-pointer" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-fno-omit-frame-pointer" + } + } + } + + feature { + name: "no-canonical-prefixes" + flag_set { + action: "c-compile" + action: "c++-compile" + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag:"-no-canonical-prefixes" + } + } + } + + feature { + name: "disable-assertions" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-DNDEBUG" + } + } + } + + feature { + name: "linker-bin-path" + + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-B/usr/bin" + } + } + } + + feature { + name: "undefined-dynamic" + flag_set { + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-executable" + flag_group { + flag: "-undefined" + flag: "dynamic_lookup" + } + } + } + + feature { + name: "common" + implies: "stdlib" + implies: "c++11" + implies: "determinism" + implies: "hardening" + implies: "warnings" + implies: "frame-pointer" + implies: "no-canonical-prefixes" + implies: "linker-bin-path" + implies: "undefined-dynamic" + } + + feature { + name: "opt" + implies: "common" + implies: "disable-assertions" + + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # No debug symbols. + # Maybe we should enable https://gcc.gnu.org/wiki/DebugFission for opt + # or even generally? However, that can't happen here, as it requires + # special handling in Bazel. + flag: "-g0" + + # Conservative choice for -O + # -O3 can increase binary size and even slow down the resulting binaries. + # Profile first and / or use FDO if you need better performance than this. + flag: "-O2" + + # Removal of unused code and data at link time (can this increase binary size in some cases?). + flag: "-ffunction-sections" + flag: "-fdata-sections" + } + } + } + + feature { + name: "fastbuild" + implies: "common" + } + + feature { + name: "dbg" + implies: "common" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-g" + } + } + } + + # Set clang as a C/C++ compiler. + tool_path { name: "gcc" path: "clang/bin/crosstool_wrapper_driver_is_not_gcc" } + + # Use the default system toolchain for everything else. + tool_path { name: "ar" path: "/usr/bin/libtool" } + tool_path { name: "compat-ld" path: "/usr/bin/ld" } + tool_path { name: "cpp" path: "/usr/bin/cpp" } + tool_path { name: "dwp" path: "/usr/bin/dwp" } + tool_path { name: "gcov" path: "/usr/bin/gcov" } + tool_path { name: "ld" path: "/usr/bin/ld" } + tool_path { name: "nm" path: "/usr/bin/nm" } + tool_path { name: "objcopy" path: "/usr/bin/objcopy" } + tool_path { name: "objdump" path: "/usr/bin/objdump" } + tool_path { name: "strip" path: "/usr/bin/strip" } + + # Enabled dynamic linking. + linking_mode_flags { mode: DYNAMIC } + + cxx_builtin_include_directory: "/usr/include/c++/4.8" + cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu/c++/4.8" + cxx_builtin_include_directory: "/usr/include/c++/4.8/backward" + cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/4.8/include" + cxx_builtin_include_directory: "/usr/local/include" + cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed" + cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu" + cxx_builtin_include_directory: "/usr/include" + cxx_builtin_include_directory: "/usr/local/cuda-10.0/targets/x86_64-linux/include" + cxx_builtin_include_directory: "/usr/local/cuda-10.0/include" + cxx_builtin_include_directory: "/usr/local/cuda-10.0/extras/CUPTI/include" + cxx_builtin_include_directory: "/usr/include" +} + +toolchain { + toolchain_identifier: "local_windows" + host_system_name: "local" + target_system_name: "local" + + abi_version: "local" + abi_libc_version: "local" + target_cpu: "x64_windows" + compiler: "msvc-cl" + target_libc: "msvcrt" + + + + tool_path { + name: "ar" + path: "" + } + tool_path { + name: "ml" + path: "" + } + tool_path { + name: "cpp" + path: "" + } + tool_path { + name: "gcc" + path: "" + } + tool_path { + name: "gcov" + path: "wrapper/bin/msvc_nop.bat" + } + tool_path { + name: "ld" + path: "" + } + tool_path { + name: "nm" + path: "wrapper/bin/msvc_nop.bat" + } + tool_path { + name: "objcopy" + path: "wrapper/bin/msvc_nop.bat" + } + tool_path { + name: "objdump" + path: "wrapper/bin/msvc_nop.bat" + } + tool_path { + name: "strip" + path: "wrapper/bin/msvc_nop.bat" + } + supports_interface_shared_objects: true + + # TODO(pcloudy): Review those flags below, they should be defined by cl.exe + compiler_flag: "/DCOMPILER_MSVC" + + # Don't define min/max macros in windows.h. + compiler_flag: "/DNOMINMAX" + + # Platform defines. + compiler_flag: "/D_WIN32_WINNT=0x0600" + # Turn off warning messages. + compiler_flag: "/D_CRT_SECURE_NO_DEPRECATE" + compiler_flag: "/D_CRT_SECURE_NO_WARNINGS" + compiler_flag: "/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS" + + # Useful options to have on for compilation. + # Increase the capacity of object files to 2^32 sections. + compiler_flag: "/bigobj" + # Allocate 500MB for precomputed headers. + compiler_flag: "/Zm500" + # Use unsigned char by default. + compiler_flag: "/J" + # Use function level linking. + compiler_flag: "/Gy" + # Use string pooling. + compiler_flag: "/GF" + # Catch C++ exceptions only and tell the compiler to assume that functions declared + # as extern "C" never throw a C++ exception. + compiler_flag: "/EHsc" + + # Globally disabled warnings. + # Don't warn about elements of array being be default initialized. + compiler_flag: "/wd4351" + # Don't warn about no matching delete found. + compiler_flag: "/wd4291" + # Don't warn about diamond inheritance patterns. + compiler_flag: "/wd4250" + # Don't warn about insecure functions (e.g. non _s functions). + compiler_flag: "/wd4996" + + linker_flag: "/MACHINE:X64" + + feature { + name: "no_legacy_features" + } + + # Suppress startup banner. + feature { + name: "nologo" + flag_set { + action: "c-compile" + action: "c++-compile" + action: "c++-module-compile" + action: "c++-module-codegen" + action: "c++-header-parsing" + action: "assemble" + action: "preprocess-assemble" + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-static-library" + flag_group { + flag: "/nologo" + } + } + } + + feature { + name: 'has_configured_linker_path' + } + + # This feature indicates strip is not supported, building stripped binary will just result a copy of orignial binary + feature { + name: 'no_stripping' + } + + # This feature indicates this is a toolchain targeting Windows. + feature { + name: 'targets_windows' + implies: 'copy_dynamic_libraries_to_binary' + enabled: true + } + + feature { + name: 'copy_dynamic_libraries_to_binary' + } + + action_config { + config_name: 'assemble' + action_name: 'assemble' + tool { + tool_path: '' + } + implies: 'compiler_input_flags' + implies: 'compiler_output_flags' + implies: 'nologo' + implies: 'msvc_env' + implies: 'sysroot' + } + + action_config { + config_name: 'preprocess-assemble' + action_name: 'preprocess-assemble' + tool { + tool_path: '' + } + implies: 'compiler_input_flags' + implies: 'compiler_output_flags' + implies: 'nologo' + implies: 'msvc_env' + implies: 'sysroot' + } + + action_config { + config_name: 'c-compile' + action_name: 'c-compile' + tool { + tool_path: '' + } + implies: 'compiler_input_flags' + implies: 'compiler_output_flags' + implies: 'legacy_compile_flags' + implies: 'nologo' + implies: 'msvc_env' + implies: 'parse_showincludes' + implies: 'user_compile_flags' + implies: 'sysroot' + implies: 'unfiltered_compile_flags' + } + + action_config { + config_name: 'c++-compile' + action_name: 'c++-compile' + tool { + tool_path: '' + } + implies: 'compiler_input_flags' + implies: 'compiler_output_flags' + implies: 'legacy_compile_flags' + implies: 'nologo' + implies: 'msvc_env' + implies: 'parse_showincludes' + implies: 'user_compile_flags' + implies: 'sysroot' + implies: 'unfiltered_compile_flags' + } + + action_config { + config_name: 'c++-link-executable' + action_name: 'c++-link-executable' + tool { + tool_path: '' + } + implies: 'nologo' + implies: 'linkstamps' + implies: 'output_execpath_flags' + implies: 'input_param_flags' + implies: 'user_link_flags' + implies: 'legacy_link_flags' + implies: 'linker_subsystem_flag' + implies: 'linker_param_file' + implies: 'msvc_env' + implies: 'no_stripping' + } + + action_config { + config_name: 'c++-link-dynamic-library' + action_name: 'c++-link-dynamic-library' + tool { + tool_path: '' + } + implies: 'nologo' + implies: 'shared_flag' + implies: 'linkstamps' + implies: 'output_execpath_flags' + implies: 'input_param_flags' + implies: 'user_link_flags' + implies: 'legacy_link_flags' + implies: 'linker_subsystem_flag' + implies: 'linker_param_file' + implies: 'msvc_env' + implies: 'no_stripping' + implies: 'has_configured_linker_path' + implies: 'def_file' + } + + action_config { + config_name: 'c++-link-nodeps-dynamic-library' + action_name: 'c++-link-nodeps-dynamic-library' + tool { + tool_path: '' + } + implies: 'nologo' + implies: 'shared_flag' + implies: 'linkstamps' + implies: 'output_execpath_flags' + implies: 'input_param_flags' + implies: 'user_link_flags' + implies: 'legacy_link_flags' + implies: 'linker_subsystem_flag' + implies: 'linker_param_file' + implies: 'msvc_env' + implies: 'no_stripping' + implies: 'has_configured_linker_path' + implies: 'def_file' + } + + action_config { + config_name: 'c++-link-static-library' + action_name: 'c++-link-static-library' + tool { + tool_path: '' + } + implies: 'nologo' + implies: 'archiver_flags' + implies: 'input_param_flags' + implies: 'linker_param_file' + implies: 'msvc_env' + } + + # TODO(b/65151735): Remove legacy_compile_flags feature when legacy fields are + # not used in this crosstool + feature { + name: 'legacy_compile_flags' + flag_set { + expand_if_all_available: 'legacy_compile_flags' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + iterate_over: 'legacy_compile_flags' + flag: '%{legacy_compile_flags}' + } + } + } + + feature { + name: "msvc_env" + env_set { + action: "c-compile" + action: "c++-compile" + action: "c++-module-compile" + action: "c++-module-codegen" + action: "c++-header-parsing" + action: "assemble" + action: "preprocess-assemble" + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-static-library" + env_entry { + key: "PATH" + value: "" + } + env_entry { + key: "INCLUDE" + value: "" + } + env_entry { + key: "LIB" + value: "" + } + env_entry { + key: "TMP" + value: "" + } + env_entry { + key: "TEMP" + value: "" + } + } + } + + feature { + name: 'include_paths' + flag_set { + action: "assemble" + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + flag_group { + iterate_over: 'quote_include_paths' + flag: '/I%{quote_include_paths}' + } + flag_group { + iterate_over: 'include_paths' + flag: '/I%{include_paths}' + } + flag_group { + iterate_over: 'system_include_paths' + flag: '/I%{system_include_paths}' + } + } + } + + feature { + name: "preprocessor_defines" + flag_set { + action: "assemble" + action: "preprocess-assemble" + action: "c-compile" + action: "c++-compile" + action: "c++-header-parsing" + action: "c++-module-compile" + flag_group { + flag: "/D%{preprocessor_defines}" + iterate_over: "preprocessor_defines" + } + } + } + + # Tell Bazel to parse the output of /showIncludes + feature { + name: 'parse_showincludes' + flag_set { + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-module-compile' + action: 'c++-header-parsing' + flag_group { + flag: "/showIncludes" + } + } + } + + + feature { + name: 'generate_pdb_file' + requires: { + feature: 'dbg' + } + requires: { + feature: 'fastbuild' + } + } + + feature { + name: 'shared_flag' + flag_set { + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: '/DLL' + } + } + } + + feature { + name: 'linkstamps' + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + expand_if_all_available: 'linkstamp_paths' + flag_group { + iterate_over: 'linkstamp_paths' + flag: '%{linkstamp_paths}' + } + } + } + + feature { + name: 'output_execpath_flags' + flag_set { + expand_if_all_available: 'output_execpath' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: '/OUT:%{output_execpath}' + } + } + } + + feature { + name: 'archiver_flags' + flag_set { + expand_if_all_available: 'output_execpath' + action: 'c++-link-static-library' + flag_group { + flag: '/OUT:%{output_execpath}' + } + } + } + + feature { + name: 'input_param_flags' + flag_set { + expand_if_all_available: 'interface_library_output_path' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/IMPLIB:%{interface_library_output_path}" + } + } + flag_set { + expand_if_all_available: 'libopts' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + iterate_over: 'libopts' + flag: '%{libopts}' + } + } + flag_set { + expand_if_all_available: 'libraries_to_link' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + action: 'c++-link-static-library' + flag_group { + iterate_over: 'libraries_to_link' + flag_group { + expand_if_equal: { + variable: 'libraries_to_link.type' + value: 'object_file_group' + } + iterate_over: 'libraries_to_link.object_files' + flag_group { + flag: '%{libraries_to_link.object_files}' + } + } + flag_group { + expand_if_equal: { + variable: 'libraries_to_link.type' + value: 'object_file' + } + flag_group { + flag: '%{libraries_to_link.name}' + } + } + flag_group { + expand_if_equal: { + variable: 'libraries_to_link.type' + value: 'interface_library' + } + flag_group { + flag: '%{libraries_to_link.name}' + } + } + flag_group { + expand_if_equal: { + variable: 'libraries_to_link.type' + value: 'static_library' + } + flag_group { + expand_if_false: 'libraries_to_link.is_whole_archive' + flag: '%{libraries_to_link.name}' + } + flag_group { + expand_if_true: 'libraries_to_link.is_whole_archive' + flag: '/WHOLEARCHIVE:%{libraries_to_link.name}' + } + } + } + } + } + + # Since this feature is declared earlier in the CROSSTOOL than + # "user_link_flags", this feature will be applied prior to it anwyhere they + # are both implied. And since "user_link_flags" contains the linkopts from + # the build rule, this allows the user to override the /SUBSYSTEM in the BUILD + # file. + feature { + name: 'linker_subsystem_flag' + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: '/SUBSYSTEM:CONSOLE' + } + } + } + + # The "user_link_flags" contains user-defined linkopts (from build rules) + # so it should be defined after features that declare user-overridable flags. + # For example the "linker_subsystem_flag" defines a default "/SUBSYSTEM" flag + # but we want to let the user override it, therefore "link_flag_subsystem" is + # defined earlier in the CROSSTOOL file than "user_link_flags". + feature { + name: 'user_link_flags' + flag_set { + expand_if_all_available: 'user_link_flags' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + iterate_over: 'user_link_flags' + flag: '%{user_link_flags}' + } + } + } + feature { + name: 'legacy_link_flags' + flag_set { + expand_if_all_available: 'legacy_link_flags' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + iterate_over: 'legacy_link_flags' + flag: '%{legacy_link_flags}' + } + } + } + + feature { + name: 'linker_param_file' + flag_set { + expand_if_all_available: 'linker_param_file' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + action: 'c++-link-static-library' + flag_group { + flag: '@%{linker_param_file}' + } + } + } + + feature { + name: 'static_link_msvcrt' + } + + feature { + name: 'static_link_msvcrt_no_debug' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/MT" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEFAULTLIB:libcmt.lib" + } + } + requires: { feature: 'fastbuild'} + requires: { feature: 'opt'} + } + + feature { + name: 'dynamic_link_msvcrt_no_debug' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/MD" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEFAULTLIB:msvcrt.lib" + } + } + requires: { feature: 'fastbuild'} + requires: { feature: 'opt'} + } + + feature { + name: 'static_link_msvcrt_debug' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/MTd" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEFAULTLIB:libcmtd.lib" + } + } + requires: { feature: 'dbg'} + } + + feature { + name: 'dynamic_link_msvcrt_debug' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/MDd" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEFAULTLIB:msvcrtd.lib" + } + } + requires: { feature: 'dbg'} + } + + feature { + name: 'dbg' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/Od" + flag: "/Z7" + flag: "/DDEBUG" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEBUG:FULL" + flag: "/INCREMENTAL:NO" + } + } + implies: 'generate_pdb_file' + } + + feature { + name: 'fastbuild' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/Od" + flag: "/Z7" + flag: "/DDEBUG" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEBUG:FASTLINK" + flag: "/INCREMENTAL:NO" + } + } + implies: 'generate_pdb_file' + } + + feature { + name: 'opt' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/O2" + flag: "/DNDEBUG" + } + } + } + + feature { + name: 'user_compile_flags' + flag_set { + expand_if_all_available: 'user_compile_flags' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + iterate_over: 'user_compile_flags' + flag: '%{user_compile_flags}' + } + } + } + + feature { + name: 'sysroot' + flag_set { + expand_if_all_available: 'sysroot' + action: 'assemble' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + iterate_over: 'sysroot' + flag: '--sysroot=%{sysroot}' + } + } + } + + feature { + name: 'unfiltered_compile_flags' + flag_set { + expand_if_all_available: 'unfiltered_compile_flags' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + iterate_over: 'unfiltered_compile_flags' + flag: '%{unfiltered_compile_flags}' + } + } + } + + feature { + name: 'compiler_output_flags' + flag_set { + action: 'assemble' + flag_group { + expand_if_all_available: 'output_file' + expand_if_none_available: 'output_assembly_file' + expand_if_none_available: 'output_preprocess_file' + flag: '/Fo%{output_file}' + flag: '/Zi' + } + } + flag_set { + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + expand_if_all_available: 'output_file' + expand_if_none_available: 'output_assembly_file' + expand_if_none_available: 'output_preprocess_file' + flag: '/Fo%{output_file}' + } + flag_group { + expand_if_all_available: 'output_file' + expand_if_all_available: 'output_assembly_file' + flag: '/Fa%{output_file}' + } + flag_group { + expand_if_all_available: 'output_file' + expand_if_all_available: 'output_preprocess_file' + flag: '/P' + flag: '/Fi%{output_file}' + } + } + } + + feature { + name: 'compiler_input_flags' + flag_set { + action: 'assemble' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + expand_if_all_available: 'source_file' + flag: '/c' + flag: '%{source_file}' + } + } + } + + feature { + name : 'def_file', + flag_set { + expand_if_all_available: 'def_file_path' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEF:%{def_file_path}" + # We can specify a different DLL name in DEF file, /ignore:4070 suppresses + # the warning message about DLL name doesn't match the default one. + # See https://msdn.microsoft.com/en-us/library/sfkk2fz7.aspx + flag: "/ignore:4070" + } + } + } + + feature { + name: 'windows_export_all_symbols' + } + + feature { + name: 'no_windows_export_all_symbols' + } + + linking_mode_flags { mode: DYNAMIC } +} diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/clang/bin/crosstool_wrapper_driver_is_not_gcc b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/clang/bin/crosstool_wrapper_driver_is_not_gcc new file mode 100755 index 0000000000..7ae59e9967 --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/clang/bin/crosstool_wrapper_driver_is_not_gcc @@ -0,0 +1,264 @@ +#!/usr/bin/env python +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Crosstool wrapper for compiling CUDA programs. + +SYNOPSIS: + crosstool_wrapper_is_not_gcc [options passed in by cc_library() + or cc_binary() rule] + +DESCRIPTION: + This script is expected to be called by the cc_library() or cc_binary() bazel + rules. When the option "-x cuda" is present in the list of arguments passed + to this script, it invokes the nvcc CUDA compiler. Most arguments are passed + as is as a string to --compiler-options of nvcc. When "-x cuda" is not + present, this wrapper invokes hybrid_driver_is_not_gcc with the input + arguments as is. + +NOTES: + Changes to the contents of this file must be propagated from + //third_party/gpus/crosstool/crosstool_wrapper_is_not_gcc to + //third_party/gpus/crosstool/v*/*/clang/bin/crosstool_wrapper_is_not_gcc +""" + +from __future__ import print_function + +__author__ = 'keveman@google.com (Manjunath Kudlur)' + +from argparse import ArgumentParser +import os +import subprocess +import re +import sys +import pipes + +# Template values set by cuda_autoconf. +CPU_COMPILER = ('/usr/bin/gcc') +GCC_HOST_COMPILER_PATH = ('/usr/bin/gcc') + +NVCC_PATH = '/usr/local/cuda-10.0/bin/nvcc' +PREFIX_DIR = os.path.dirname(GCC_HOST_COMPILER_PATH) +NVCC_VERSION = '10.0' + +def Log(s): + print('gpus/crosstool: {0}'.format(s)) + + +def GetOptionValue(argv, option): + """Extract the list of values for option from the argv list. + + Args: + argv: A list of strings, possibly the argv passed to main(). + option: The option whose value to extract, without the leading '-'. + + Returns: + A list of values, either directly following the option, + (eg., -opt val1 val2) or values collected from multiple occurrences of + the option (eg., -opt val1 -opt val2). + """ + + parser = ArgumentParser() + parser.add_argument('-' + option, nargs='*', action='append') + args, _ = parser.parse_known_args(argv) + if not args or not vars(args)[option]: + return [] + else: + return sum(vars(args)[option], []) + + +def GetHostCompilerOptions(argv): + """Collect the -isystem, -iquote, and --sysroot option values from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + + Returns: + The string that can be used as the --compiler-options to nvcc. + """ + + parser = ArgumentParser() + parser.add_argument('-isystem', nargs='*', action='append') + parser.add_argument('-iquote', nargs='*', action='append') + parser.add_argument('--sysroot', nargs=1) + parser.add_argument('-g', nargs='*', action='append') + parser.add_argument('-fno-canonical-system-headers', action='store_true') + + args, _ = parser.parse_known_args(argv) + + opts = '' + + if args.isystem: + opts += ' -isystem ' + ' -isystem '.join(sum(args.isystem, [])) + if args.iquote: + opts += ' -iquote ' + ' -iquote '.join(sum(args.iquote, [])) + if args.g: + opts += ' -g' + ' -g'.join(sum(args.g, [])) + if args.fno_canonical_system_headers: + opts += ' -fno-canonical-system-headers' + if args.sysroot: + opts += ' --sysroot ' + args.sysroot[0] + + return opts + +def _update_options(nvcc_options): + if NVCC_VERSION in ("7.0",): + return nvcc_options + + update_options = { "relaxed-constexpr" : "expt-relaxed-constexpr" } + return [ update_options[opt] if opt in update_options else opt + for opt in nvcc_options ] + +def GetNvccOptions(argv): + """Collect the -nvcc_options values from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + + Returns: + The string that can be passed directly to nvcc. + """ + + parser = ArgumentParser() + parser.add_argument('-nvcc_options', nargs='*', action='append') + + args, _ = parser.parse_known_args(argv) + + if args.nvcc_options: + options = _update_options(sum(args.nvcc_options, [])) + return ' '.join(['--'+a for a in options]) + return '' + + +def InvokeNvcc(argv, log=False): + """Call nvcc with arguments assembled from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + log: True if logging is requested. + + Returns: + The return value of calling os.system('nvcc ' + args) + """ + + host_compiler_options = GetHostCompilerOptions(argv) + nvcc_compiler_options = GetNvccOptions(argv) + opt_option = GetOptionValue(argv, 'O') + m_options = GetOptionValue(argv, 'm') + m_options = ''.join([' -m' + m for m in m_options if m in ['32', '64']]) + include_options = GetOptionValue(argv, 'I') + out_file = GetOptionValue(argv, 'o') + depfiles = GetOptionValue(argv, 'MF') + defines = GetOptionValue(argv, 'D') + defines = ''.join([' -D' + define for define in defines]) + undefines = GetOptionValue(argv, 'U') + undefines = ''.join([' -U' + define for define in undefines]) + std_options = GetOptionValue(argv, 'std') + # currently only c++11 is supported by Cuda 7.0 std argument + nvcc_allowed_std_options = ["c++11"] + std_options = ''.join([' -std=' + define + for define in std_options if define in nvcc_allowed_std_options]) + + # The list of source files get passed after the -c option. I don't know of + # any other reliable way to just get the list of source files to be compiled. + src_files = GetOptionValue(argv, 'c') + + # Pass -w through from host to nvcc, but don't do anything fancier with + # warnings-related flags, since they're not necessarily the same across + # compilers. + warning_options = ' -w' if '-w' in argv else '' + + if len(src_files) == 0: + return 1 + if len(out_file) != 1: + return 1 + + opt = (' -O2' if (len(opt_option) > 0 and int(opt_option[0]) > 0) + else ' -g -G') + + includes = (' -I ' + ' -I '.join(include_options) + if len(include_options) > 0 + else '') + + # Unfortunately, there are other options that have -c prefix too. + # So allowing only those look like C/C++ files. + src_files = [f for f in src_files if + re.search('\.cpp$|\.cc$|\.c$|\.cxx$|\.C$', f)] + srcs = ' '.join(src_files) + out = ' -o ' + out_file[0] + + supported_cuda_compute_capabilities = [ "3.0" ] + nvccopts = '-D_FORCE_INLINES ' + for capability in supported_cuda_compute_capabilities: + capability = capability.replace('.', '') + nvccopts += r'-gencode=arch=compute_%s,\"code=sm_%s,compute_%s\" ' % ( + capability, capability, capability) + nvccopts += ' ' + nvcc_compiler_options + nvccopts += undefines + nvccopts += defines + nvccopts += std_options + nvccopts += m_options + nvccopts += warning_options + + if depfiles: + # Generate the dependency file + depfile = depfiles[0] + cmd = (NVCC_PATH + ' ' + nvccopts + + ' --compiler-options "' + host_compiler_options + '"' + + ' --compiler-bindir=' + GCC_HOST_COMPILER_PATH + + ' -I .' + + ' -x cu ' + opt + includes + ' ' + srcs + ' -M -o ' + depfile) + if log: Log(cmd) + exit_status = os.system(cmd) + if exit_status != 0: + return exit_status + + cmd = (NVCC_PATH + ' ' + nvccopts + + ' --compiler-options "' + host_compiler_options + ' -fPIC"' + + ' --compiler-bindir=' + GCC_HOST_COMPILER_PATH + + ' -I .' + + ' -x cu ' + opt + includes + ' -c ' + srcs + out) + + # TODO(zhengxq): for some reason, 'gcc' needs this help to find 'as'. + # Need to investigate and fix. + cmd = 'PATH=' + PREFIX_DIR + ':$PATH ' + cmd + if log: Log(cmd) + return os.system(cmd) + + +def main(): + parser = ArgumentParser() + parser.add_argument('-x', nargs=1) + parser.add_argument('--cuda_log', action='store_true') + args, leftover = parser.parse_known_args(sys.argv[1:]) + + if args.x and args.x[0] == 'cuda': + if args.cuda_log: Log('-x cuda') + leftover = [pipes.quote(s) for s in leftover] + if args.cuda_log: Log('using nvcc') + return InvokeNvcc(leftover, log=args.cuda_log) + + # Strip our flags before passing through to the CPU compiler for files which + # are not -x cuda. We can't just pass 'leftover' because it also strips -x. + # We not only want to pass -x to the CPU compiler, but also keep it in its + # relative location in the argv list (the compiler is actually sensitive to + # this). + cpu_compiler_flags = [flag for flag in sys.argv[1:] + if not flag.startswith(('--cuda_log'))] + + return subprocess.call([CPU_COMPILER] + cpu_compiler_flags) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/windows/msvc_wrapper_for_nvcc.bat b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/windows/msvc_wrapper_for_nvcc.bat new file mode 100755 index 0000000000..e896e654fd --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/windows/msvc_wrapper_for_nvcc.bat @@ -0,0 +1,20 @@ +:: Copyright 2015 The TensorFlow Authors. All Rights Reserved. +:: +:: Licensed under the Apache License, Version 2.0 (the "License"); +:: you may not use this file except in compliance with the License. +:: You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, software +:: distributed under the License is distributed on an "AS IS" BASIS, +:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +:: See the License for the specific language governing permissions and +:: limitations under the License. +:: ============================================================================= + +:: Invoke msvc_wrapper_for_nvcc.py, which is located in the same directory. +@echo OFF +set arg0=%~0 +for %%F in ("%arg0%") do set DRIVER_BIN=%%~dpF +"/usr/bin/python3" -B "%DRIVER_BIN%\msvc_wrapper_for_nvcc.py" %* diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/windows/msvc_wrapper_for_nvcc.py b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/windows/msvc_wrapper_for_nvcc.py new file mode 100755 index 0000000000..00483951af --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda10.0/windows/msvc_wrapper_for_nvcc.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Crosstool wrapper for compiling CUDA programs with nvcc on Windows. + +DESCRIPTION: + This script is the Windows version of //third_party/gpus/crosstool/crosstool_wrapper_is_not_gcc +""" + +from __future__ import print_function + +from argparse import ArgumentParser +import os +import subprocess +import re +import sys +import pipes + +# Template values set by cuda_autoconf. +CPU_COMPILER = ('/usr/bin/gcc') +GCC_HOST_COMPILER_PATH = ('/usr/bin/gcc') + +NVCC_PATH = '/usr/local/cuda-10.0/bin/nvcc' +NVCC_VERSION = '10.0' +NVCC_TEMP_DIR = "C:\\Windows\\Temp\\nvcc_inter_files_tmp_dir" +supported_cuda_compute_capabilities = [ "3.0" ] + +def Log(s): + print('gpus/crosstool: {0}'.format(s)) + + +def GetOptionValue(argv, option): + """Extract the list of values for option from options. + + Args: + option: The option whose value to extract, without the leading '/'. + + Returns: + 1. A list of values, either directly following the option, + (eg., /opt val1 val2) or values collected from multiple occurrences of + the option (eg., /opt val1 /opt val2). + 2. The leftover options. + """ + + parser = ArgumentParser(prefix_chars='/') + parser.add_argument('/' + option, nargs='*', action='append') + args, leftover = parser.parse_known_args(argv) + if args and vars(args)[option]: + return (sum(vars(args)[option], []), leftover) + return ([], leftover) + +def _update_options(nvcc_options): + if NVCC_VERSION in ("7.0",): + return nvcc_options + + update_options = { "relaxed-constexpr" : "expt-relaxed-constexpr" } + return [ update_options[opt] if opt in update_options else opt + for opt in nvcc_options ] + +def GetNvccOptions(argv): + """Collect the -nvcc_options values from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + + Returns: + 1. The string that can be passed directly to nvcc. + 2. The leftover options. + """ + + parser = ArgumentParser() + parser.add_argument('-nvcc_options', nargs='*', action='append') + + args, leftover = parser.parse_known_args(argv) + + if args.nvcc_options: + options = _update_options(sum(args.nvcc_options, [])) + return (['--' + a for a in options], leftover) + return ([], leftover) + + +def InvokeNvcc(argv, log=False): + """Call nvcc with arguments assembled from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + log: True if logging is requested. + + Returns: + The return value of calling os.system('nvcc ' + args) + """ + + src_files = [f for f in argv if + re.search('\.cpp$|\.cc$|\.c$|\.cxx$|\.C$', f)] + if len(src_files) == 0: + raise Error('No source files found for cuda compilation.') + + out_file = [ f for f in argv if f.startswith('/Fo') ] + if len(out_file) != 1: + raise Error('Please sepecify exactly one output file for cuda compilation.') + out = ['-o', out_file[0][len('/Fo'):]] + + nvcc_compiler_options, argv = GetNvccOptions(argv) + + opt_option, argv = GetOptionValue(argv, 'O') + opt = ['-g', '-G'] + if (len(opt_option) > 0 and opt_option[0] != 'd'): + opt = ['-O2'] + + include_options, argv = GetOptionValue(argv, 'I') + includes = ["-I " + include for include in include_options] + + defines, argv = GetOptionValue(argv, 'D') + defines = ['-D' + define for define in defines] + + undefines, argv = GetOptionValue(argv, 'U') + undefines = ['-U' + define for define in undefines] + + # The rest of the unrecongized options should be passed to host compiler + host_compiler_options = [option for option in argv if option not in (src_files + out_file)] + + m_options = ["-m64"] + + nvccopts = ['-D_FORCE_INLINES'] + for capability in supported_cuda_compute_capabilities: + capability = capability.replace('.', '') + nvccopts += [r'-gencode=arch=compute_%s,"code=sm_%s,compute_%s"' % ( + capability, capability, capability)] + nvccopts += nvcc_compiler_options + nvccopts += undefines + nvccopts += defines + nvccopts += m_options + nvccopts += ['--compiler-options="' + " ".join(host_compiler_options) + '"'] + nvccopts += ['-x', 'cu'] + opt + includes + out + ['-c'] + src_files + # If we don't specify --keep-dir, nvcc will generate intermediate files under TEMP + # Put them under NVCC_TEMP_DIR instead, then Bazel can ignore files under NVCC_TEMP_DIR during dependency check + # http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#options-for-guiding-compiler-driver + # Different actions are sharing NVCC_TEMP_DIR, so we cannot remove it if the directory already exists. + if os.path.isfile(NVCC_TEMP_DIR): + os.remove(NVCC_TEMP_DIR) + if not os.path.exists(NVCC_TEMP_DIR): + os.makedirs(NVCC_TEMP_DIR) + nvccopts += ['--keep', '--keep-dir', NVCC_TEMP_DIR] + cmd = [NVCC_PATH] + nvccopts + if log: + Log(cmd) + proc = subprocess.Popen(cmd, + stdout=sys.stdout, + stderr=sys.stderr, + env=os.environ.copy(), + shell=True) + proc.wait() + return proc.returncode + +def main(): + parser = ArgumentParser() + parser.add_argument('-x', nargs=1) + parser.add_argument('--cuda_log', action='store_true') + args, leftover = parser.parse_known_args(sys.argv[1:]) + + if args.x and args.x[0] == 'cuda': + if args.cuda_log: Log('-x cuda') + leftover = [pipes.quote(s) for s in leftover] + if args.cuda_log: Log('using nvcc') + return InvokeNvcc(leftover, log=args.cuda_log) + + # Strip our flags before passing through to the CPU compiler for files which + # are not -x cuda. We can't just pass 'leftover' because it also strips -x. + # We not only want to pass -x to the CPU compiler, but also keep it in its + # relative location in the argv list (the compiler is actually sensitive to + # this). + cpu_compiler_flags = [flag for flag in sys.argv[1:] + if not flag.startswith(('--cuda_log')) + and not flag.startswith(('-nvcc_options'))] + + return subprocess.call([CPU_COMPILER] + cpu_compiler_flags) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/BUILD b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/BUILD new file mode 100755 index 0000000000..6442e7628a --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/BUILD @@ -0,0 +1,87 @@ +licenses(["restricted"]) + +package(default_visibility = ["//visibility:public"]) + +toolchain( + name = "toolchain-linux-x86_64", + exec_compatible_with = [ + "@bazel_tools//platforms:linux", + "@bazel_tools//platforms:x86_64", + ], + target_compatible_with = [ + "@bazel_tools//platforms:linux", + "@bazel_tools//platforms:x86_64", + ], + toolchain = ":cc-compiler-local", + toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", +) + +cc_toolchain_suite( + name = "toolchain", + toolchains = { + "local|compiler": ":cc-compiler-local", + "darwin|compiler": ":cc-compiler-darwin", + "x64_windows|msvc-cl": ":cc-compiler-windows", + }, +) + +cc_toolchain( + name = "cc-compiler-local", + all_files = ":crosstool_wrapper_driver_is_not_gcc", + compiler_files = ":empty", + cpu = "local", + dwp_files = ":empty", + dynamic_runtime_libs = [":empty"], + linker_files = ":crosstool_wrapper_driver_is_not_gcc", + objcopy_files = ":empty", + static_runtime_libs = [":empty"], + strip_files = ":empty", + # To support linker flags that need to go to the start of command line + # we need the toolchain to support parameter files. Parameter files are + # last on the command line and contain all shared libraries to link, so all + # regular options will be left of them. + supports_param_files = 1, +) + +cc_toolchain( + name = "cc-compiler-darwin", + all_files = ":crosstool_wrapper_driver_is_not_gcc", + compiler_files = ":empty", + cpu = "darwin", + dwp_files = ":empty", + dynamic_runtime_libs = [":empty"], + linker_files = ":crosstool_wrapper_driver_is_not_gcc", + objcopy_files = ":empty", + static_runtime_libs = [":empty"], + strip_files = ":empty", + supports_param_files = 0, +) + +cc_toolchain( + name = "cc-compiler-windows", + all_files = ":windows_msvc_wrapper_files", + compiler_files = ":empty", + cpu = "x64_windows", + dwp_files = ":empty", + dynamic_runtime_libs = [":empty"], + linker_files = ":windows_msvc_wrapper_files", + objcopy_files = ":empty", + static_runtime_libs = [":empty"], + strip_files = ":empty", + supports_param_files = 1, +) + +filegroup( + name = "empty", + srcs = [], +) + +filegroup( + name = "crosstool_wrapper_driver_is_not_gcc", + srcs = ["clang/bin/crosstool_wrapper_driver_is_not_gcc"], +) + +filegroup( + name = "windows_msvc_wrapper_files", + srcs = glob(["windows/msvc_*"]), +) diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/CROSSTOOL b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/CROSSTOOL new file mode 100755 index 0000000000..0d89a539b8 --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/CROSSTOOL @@ -0,0 +1,1431 @@ +major_version: "local" +minor_version: "" +default_target_cpu: "same_as_host" + +default_toolchain { + cpu: "k8" + toolchain_identifier: "local_linux" +} +default_toolchain { + cpu: "piii" + toolchain_identifier: "local_linux" +} +default_toolchain { + cpu: "arm" + toolchain_identifier: "local_linux" +} +default_toolchain { + cpu: "darwin" + toolchain_identifier: "local_darwin" +} +default_toolchain { + cpu: "ppc" + toolchain_identifier: "local_linux" +} +default_toolchain { + cpu: "x64_windows" + toolchain_identifier: "local_windows" +} + +toolchain { + abi_version: "local" + abi_libc_version: "local" + compiler: "compiler" + host_system_name: "local" + needsPic: true + target_libc: "local" + target_cpu: "local" + target_system_name: "local" + toolchain_identifier: "local_linux" + + feature { + name: "c++11" + flag_set { + action: "c++-compile" + flag_group { + flag: "-std=c++11" + } + } + } + + feature { + name: "stdlib" + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-lstdc++" + } + } + } + + feature { + name: "determinism" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # Make C++ compilation deterministic. Use linkstamping instead of these + # compiler symbols. + flag: "-Wno-builtin-macro-redefined" + flag: "-D__DATE__=\"redacted\"" + flag: "-D__TIMESTAMP__=\"redacted\"" + flag: "-D__TIME__=\"redacted\"" + } + } + } + + feature { + name: "alwayslink" + flag_set { + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-executable" + flag_group { + flag: "-Wl,-no-as-needed" + } + } + } + + # This feature will be enabled for builds that support pic by bazel. + feature { + name: "pic" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + expand_if_all_available: "pic" + flag: "-fPIC" + } + flag_group { + expand_if_none_available: "pic" + flag: "-fPIE" + } + } + } + + # Security hardening on by default. + feature { + name: "hardening" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # Conservative choice; -D_FORTIFY_SOURCE=2 may be unsafe in some cases. + # We need to undef it before redefining it as some distributions now + # have it enabled by default. + flag: "-U_FORTIFY_SOURCE" + flag: "-D_FORTIFY_SOURCE=1" + flag: "-fstack-protector" + } + } + flag_set { + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-Wl,-z,relro,-z,now" + } + } + flag_set { + action: "c++-link-executable" + flag_group { + flag: "-pie" + flag: "-Wl,-z,relro,-z,now" + } + } + } + + feature { + name: "warnings" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # All warnings are enabled. Maybe enable -Werror as well? + flag: "-Wall" + + } + } + } + + # Keep stack frames for debugging, even in opt mode. + feature { + name: "frame-pointer" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-fno-omit-frame-pointer" + } + } + } + + feature { + name: "build-id" + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + # Stamp the binary with a unique identifier. + flag: "-Wl,--build-id=md5" + flag: "-Wl,--hash-style=gnu" + } + } + } + + feature { + name: "no-canonical-prefixes" + flag_set { + action: "c-compile" + action: "c++-compile" + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-no-canonical-prefixes" + flag: "-fno-canonical-system-headers" + } + } + } + + feature { + name: "disable-assertions" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-DNDEBUG" + } + } + } + + feature { + name: "linker-bin-path" + + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-B/usr/bin" + } + } + } + + feature { + name: "common" + implies: "stdlib" + implies: "c++11" + implies: "determinism" + implies: "alwayslink" + implies: "hardening" + implies: "warnings" + implies: "frame-pointer" + implies: "build-id" + implies: "no-canonical-prefixes" + implies: "linker-bin-path" + } + + feature { + name: "opt" + implies: "common" + implies: "disable-assertions" + + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # No debug symbols. + # Maybe we should enable https://gcc.gnu.org/wiki/DebugFission for opt + # or even generally? However, that can't happen here, as it requires + # special handling in Bazel. + flag: "-g0" + + # Conservative choice for -O + # -O3 can increase binary size and even slow down the resulting binaries. + # Profile first and / or use FDO if you need better performance than this. + flag: "-O2" + + # Removal of unused code and data at link time (can this increase binary size in some cases?). + flag: "-ffunction-sections" + flag: "-fdata-sections" + } + } + flag_set { + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-executable" + flag_group { + flag: "-Wl,--gc-sections" + } + } + } + + feature { + name: "fastbuild" + implies: "common" + } + + feature { + name: "dbg" + implies: "common" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-g" + } + } + } + + # Set clang as a C/C++ compiler. + tool_path { name: "gcc" path: "clang/bin/crosstool_wrapper_driver_is_not_gcc" } + + # Use the default system toolchain for everything else. + tool_path { name: "ar" path: "/usr/bin/ar" } + tool_path { name: "compat-ld" path: "/usr/bin/ld" } + tool_path { name: "cpp" path: "/usr/bin/cpp" } + tool_path { name: "dwp" path: "/usr/bin/dwp" } + tool_path { name: "gcov" path: "/usr/bin/gcov" } + tool_path { name: "ld" path: "/usr/bin/ld" } + tool_path { name: "nm" path: "/usr/bin/nm" } + tool_path { name: "objcopy" path: "/usr/bin/objcopy" } + tool_path { name: "objdump" path: "/usr/bin/objdump" } + tool_path { name: "strip" path: "/usr/bin/strip" } + + # Enabled dynamic linking. + linking_mode_flags { mode: DYNAMIC } + + cxx_builtin_include_directory: "/usr/include/c++/4.8" + cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu/c++/4.8" + cxx_builtin_include_directory: "/usr/include/c++/4.8/backward" + cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/4.8/include" + cxx_builtin_include_directory: "/usr/local/include" + cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed" + cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu" + cxx_builtin_include_directory: "/usr/include" + cxx_builtin_include_directory: "/usr/local/cuda-9.0/targets/x86_64-linux/include" + cxx_builtin_include_directory: "/usr/local/cuda-9.0/include" + cxx_builtin_include_directory: "/usr/local/cuda-9.0/extras/CUPTI/include" + cxx_builtin_include_directory: "/usr/include" +} + +toolchain { + abi_version: "local" + abi_libc_version: "local" + compiler: "compiler" + host_system_name: "local" + needsPic: true + target_libc: "macosx" + target_cpu: "darwin" + target_system_name: "local" + toolchain_identifier: "local_darwin" + feature { + name: "c++11" + flag_set { + action: "c++-compile" + flag_group { + flag: "-std=c++11" + } + } + } + + feature { + name: "stdlib" + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-lc++" + } + } + } + + feature { + name: "determinism" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # Make C++ compilation deterministic. Use linkstamping instead of these + # compiler symbols. + flag: "-Wno-builtin-macro-redefined" + flag: "-D__DATE__=\"redacted\"" + flag: "-D__TIMESTAMP__=\"redacted\"" + flag: "-D__TIME__=\"redacted\"" + } + } + } + + # This feature will be enabled for builds that support pic by bazel. + feature { + name: "pic" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + expand_if_all_available: "pic" + flag: "-fPIC" + } + flag_group { + expand_if_none_available: "pic" + flag: "-fPIE" + } + } + } + + # Security hardening on by default. + feature { + name: "hardening" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # Conservative choice; -D_FORTIFY_SOURCE=2 may be unsafe in some cases. + # We need to undef it before redefining it as some distributions now + # have it enabled by default. + flag: "-U_FORTIFY_SOURCE" + flag: "-D_FORTIFY_SOURCE=1" + flag: "-fstack-protector" + } + } + flag_set { + action: "c++-link-executable" + flag_group { + flag: "-pie" + } + } + } + + feature { + name: "warnings" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # All warnings are enabled. Maybe enable -Werror as well? + flag: "-Wall" + + } + } + } + + # Keep stack frames for debugging, even in opt mode. + feature { + name: "frame-pointer" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-fno-omit-frame-pointer" + } + } + } + + feature { + name: "no-canonical-prefixes" + flag_set { + action: "c-compile" + action: "c++-compile" + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag:"-no-canonical-prefixes" + } + } + } + + feature { + name: "disable-assertions" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-DNDEBUG" + } + } + } + + feature { + name: "linker-bin-path" + + flag_set { + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "-B/usr/bin" + } + } + } + + feature { + name: "undefined-dynamic" + flag_set { + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-executable" + flag_group { + flag: "-undefined" + flag: "dynamic_lookup" + } + } + } + + feature { + name: "common" + implies: "stdlib" + implies: "c++11" + implies: "determinism" + implies: "hardening" + implies: "warnings" + implies: "frame-pointer" + implies: "no-canonical-prefixes" + implies: "linker-bin-path" + implies: "undefined-dynamic" + } + + feature { + name: "opt" + implies: "common" + implies: "disable-assertions" + + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + # No debug symbols. + # Maybe we should enable https://gcc.gnu.org/wiki/DebugFission for opt + # or even generally? However, that can't happen here, as it requires + # special handling in Bazel. + flag: "-g0" + + # Conservative choice for -O + # -O3 can increase binary size and even slow down the resulting binaries. + # Profile first and / or use FDO if you need better performance than this. + flag: "-O2" + + # Removal of unused code and data at link time (can this increase binary size in some cases?). + flag: "-ffunction-sections" + flag: "-fdata-sections" + } + } + } + + feature { + name: "fastbuild" + implies: "common" + } + + feature { + name: "dbg" + implies: "common" + flag_set { + action: "c-compile" + action: "c++-compile" + flag_group { + flag: "-g" + } + } + } + + # Set clang as a C/C++ compiler. + tool_path { name: "gcc" path: "clang/bin/crosstool_wrapper_driver_is_not_gcc" } + + # Use the default system toolchain for everything else. + tool_path { name: "ar" path: "/usr/bin/libtool" } + tool_path { name: "compat-ld" path: "/usr/bin/ld" } + tool_path { name: "cpp" path: "/usr/bin/cpp" } + tool_path { name: "dwp" path: "/usr/bin/dwp" } + tool_path { name: "gcov" path: "/usr/bin/gcov" } + tool_path { name: "ld" path: "/usr/bin/ld" } + tool_path { name: "nm" path: "/usr/bin/nm" } + tool_path { name: "objcopy" path: "/usr/bin/objcopy" } + tool_path { name: "objdump" path: "/usr/bin/objdump" } + tool_path { name: "strip" path: "/usr/bin/strip" } + + # Enabled dynamic linking. + linking_mode_flags { mode: DYNAMIC } + + cxx_builtin_include_directory: "/usr/include/c++/4.8" + cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu/c++/4.8" + cxx_builtin_include_directory: "/usr/include/c++/4.8/backward" + cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/4.8/include" + cxx_builtin_include_directory: "/usr/local/include" + cxx_builtin_include_directory: "/usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed" + cxx_builtin_include_directory: "/usr/include/x86_64-linux-gnu" + cxx_builtin_include_directory: "/usr/include" + cxx_builtin_include_directory: "/usr/local/cuda-9.0/targets/x86_64-linux/include" + cxx_builtin_include_directory: "/usr/local/cuda-9.0/include" + cxx_builtin_include_directory: "/usr/local/cuda-9.0/extras/CUPTI/include" + cxx_builtin_include_directory: "/usr/include" +} + +toolchain { + toolchain_identifier: "local_windows" + host_system_name: "local" + target_system_name: "local" + + abi_version: "local" + abi_libc_version: "local" + target_cpu: "x64_windows" + compiler: "msvc-cl" + target_libc: "msvcrt" + + + + tool_path { + name: "ar" + path: "" + } + tool_path { + name: "ml" + path: "" + } + tool_path { + name: "cpp" + path: "" + } + tool_path { + name: "gcc" + path: "" + } + tool_path { + name: "gcov" + path: "wrapper/bin/msvc_nop.bat" + } + tool_path { + name: "ld" + path: "" + } + tool_path { + name: "nm" + path: "wrapper/bin/msvc_nop.bat" + } + tool_path { + name: "objcopy" + path: "wrapper/bin/msvc_nop.bat" + } + tool_path { + name: "objdump" + path: "wrapper/bin/msvc_nop.bat" + } + tool_path { + name: "strip" + path: "wrapper/bin/msvc_nop.bat" + } + supports_interface_shared_objects: true + + # TODO(pcloudy): Review those flags below, they should be defined by cl.exe + compiler_flag: "/DCOMPILER_MSVC" + + # Don't define min/max macros in windows.h. + compiler_flag: "/DNOMINMAX" + + # Platform defines. + compiler_flag: "/D_WIN32_WINNT=0x0600" + # Turn off warning messages. + compiler_flag: "/D_CRT_SECURE_NO_DEPRECATE" + compiler_flag: "/D_CRT_SECURE_NO_WARNINGS" + compiler_flag: "/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS" + + # Useful options to have on for compilation. + # Increase the capacity of object files to 2^32 sections. + compiler_flag: "/bigobj" + # Allocate 500MB for precomputed headers. + compiler_flag: "/Zm500" + # Use unsigned char by default. + compiler_flag: "/J" + # Use function level linking. + compiler_flag: "/Gy" + # Use string pooling. + compiler_flag: "/GF" + # Catch C++ exceptions only and tell the compiler to assume that functions declared + # as extern "C" never throw a C++ exception. + compiler_flag: "/EHsc" + + # Globally disabled warnings. + # Don't warn about elements of array being be default initialized. + compiler_flag: "/wd4351" + # Don't warn about no matching delete found. + compiler_flag: "/wd4291" + # Don't warn about diamond inheritance patterns. + compiler_flag: "/wd4250" + # Don't warn about insecure functions (e.g. non _s functions). + compiler_flag: "/wd4996" + + linker_flag: "/MACHINE:X64" + + feature { + name: "no_legacy_features" + } + + # Suppress startup banner. + feature { + name: "nologo" + flag_set { + action: "c-compile" + action: "c++-compile" + action: "c++-module-compile" + action: "c++-module-codegen" + action: "c++-header-parsing" + action: "assemble" + action: "preprocess-assemble" + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-static-library" + flag_group { + flag: "/nologo" + } + } + } + + feature { + name: 'has_configured_linker_path' + } + + # This feature indicates strip is not supported, building stripped binary will just result a copy of orignial binary + feature { + name: 'no_stripping' + } + + # This feature indicates this is a toolchain targeting Windows. + feature { + name: 'targets_windows' + implies: 'copy_dynamic_libraries_to_binary' + enabled: true + } + + feature { + name: 'copy_dynamic_libraries_to_binary' + } + + action_config { + config_name: 'assemble' + action_name: 'assemble' + tool { + tool_path: '' + } + implies: 'compiler_input_flags' + implies: 'compiler_output_flags' + implies: 'nologo' + implies: 'msvc_env' + implies: 'sysroot' + } + + action_config { + config_name: 'preprocess-assemble' + action_name: 'preprocess-assemble' + tool { + tool_path: '' + } + implies: 'compiler_input_flags' + implies: 'compiler_output_flags' + implies: 'nologo' + implies: 'msvc_env' + implies: 'sysroot' + } + + action_config { + config_name: 'c-compile' + action_name: 'c-compile' + tool { + tool_path: '' + } + implies: 'compiler_input_flags' + implies: 'compiler_output_flags' + implies: 'legacy_compile_flags' + implies: 'nologo' + implies: 'msvc_env' + implies: 'parse_showincludes' + implies: 'user_compile_flags' + implies: 'sysroot' + implies: 'unfiltered_compile_flags' + } + + action_config { + config_name: 'c++-compile' + action_name: 'c++-compile' + tool { + tool_path: '' + } + implies: 'compiler_input_flags' + implies: 'compiler_output_flags' + implies: 'legacy_compile_flags' + implies: 'nologo' + implies: 'msvc_env' + implies: 'parse_showincludes' + implies: 'user_compile_flags' + implies: 'sysroot' + implies: 'unfiltered_compile_flags' + } + + action_config { + config_name: 'c++-link-executable' + action_name: 'c++-link-executable' + tool { + tool_path: '' + } + implies: 'nologo' + implies: 'linkstamps' + implies: 'output_execpath_flags' + implies: 'input_param_flags' + implies: 'user_link_flags' + implies: 'legacy_link_flags' + implies: 'linker_subsystem_flag' + implies: 'linker_param_file' + implies: 'msvc_env' + implies: 'no_stripping' + } + + action_config { + config_name: 'c++-link-dynamic-library' + action_name: 'c++-link-dynamic-library' + tool { + tool_path: '' + } + implies: 'nologo' + implies: 'shared_flag' + implies: 'linkstamps' + implies: 'output_execpath_flags' + implies: 'input_param_flags' + implies: 'user_link_flags' + implies: 'legacy_link_flags' + implies: 'linker_subsystem_flag' + implies: 'linker_param_file' + implies: 'msvc_env' + implies: 'no_stripping' + implies: 'has_configured_linker_path' + implies: 'def_file' + } + + action_config { + config_name: 'c++-link-nodeps-dynamic-library' + action_name: 'c++-link-nodeps-dynamic-library' + tool { + tool_path: '' + } + implies: 'nologo' + implies: 'shared_flag' + implies: 'linkstamps' + implies: 'output_execpath_flags' + implies: 'input_param_flags' + implies: 'user_link_flags' + implies: 'legacy_link_flags' + implies: 'linker_subsystem_flag' + implies: 'linker_param_file' + implies: 'msvc_env' + implies: 'no_stripping' + implies: 'has_configured_linker_path' + implies: 'def_file' + } + + action_config { + config_name: 'c++-link-static-library' + action_name: 'c++-link-static-library' + tool { + tool_path: '' + } + implies: 'nologo' + implies: 'archiver_flags' + implies: 'input_param_flags' + implies: 'linker_param_file' + implies: 'msvc_env' + } + + # TODO(b/65151735): Remove legacy_compile_flags feature when legacy fields are + # not used in this crosstool + feature { + name: 'legacy_compile_flags' + flag_set { + expand_if_all_available: 'legacy_compile_flags' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + iterate_over: 'legacy_compile_flags' + flag: '%{legacy_compile_flags}' + } + } + } + + feature { + name: "msvc_env" + env_set { + action: "c-compile" + action: "c++-compile" + action: "c++-module-compile" + action: "c++-module-codegen" + action: "c++-header-parsing" + action: "assemble" + action: "preprocess-assemble" + action: "c++-link-executable" + action: "c++-link-dynamic-library" + action: "c++-link-nodeps-dynamic-library" + action: "c++-link-static-library" + env_entry { + key: "PATH" + value: "" + } + env_entry { + key: "INCLUDE" + value: "" + } + env_entry { + key: "LIB" + value: "" + } + env_entry { + key: "TMP" + value: "" + } + env_entry { + key: "TEMP" + value: "" + } + } + } + + feature { + name: 'include_paths' + flag_set { + action: "assemble" + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + flag_group { + iterate_over: 'quote_include_paths' + flag: '/I%{quote_include_paths}' + } + flag_group { + iterate_over: 'include_paths' + flag: '/I%{include_paths}' + } + flag_group { + iterate_over: 'system_include_paths' + flag: '/I%{system_include_paths}' + } + } + } + + feature { + name: "preprocessor_defines" + flag_set { + action: "assemble" + action: "preprocess-assemble" + action: "c-compile" + action: "c++-compile" + action: "c++-header-parsing" + action: "c++-module-compile" + flag_group { + flag: "/D%{preprocessor_defines}" + iterate_over: "preprocessor_defines" + } + } + } + + # Tell Bazel to parse the output of /showIncludes + feature { + name: 'parse_showincludes' + flag_set { + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-module-compile' + action: 'c++-header-parsing' + flag_group { + flag: "/showIncludes" + } + } + } + + + feature { + name: 'generate_pdb_file' + requires: { + feature: 'dbg' + } + requires: { + feature: 'fastbuild' + } + } + + feature { + name: 'shared_flag' + flag_set { + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: '/DLL' + } + } + } + + feature { + name: 'linkstamps' + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + expand_if_all_available: 'linkstamp_paths' + flag_group { + iterate_over: 'linkstamp_paths' + flag: '%{linkstamp_paths}' + } + } + } + + feature { + name: 'output_execpath_flags' + flag_set { + expand_if_all_available: 'output_execpath' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: '/OUT:%{output_execpath}' + } + } + } + + feature { + name: 'archiver_flags' + flag_set { + expand_if_all_available: 'output_execpath' + action: 'c++-link-static-library' + flag_group { + flag: '/OUT:%{output_execpath}' + } + } + } + + feature { + name: 'input_param_flags' + flag_set { + expand_if_all_available: 'interface_library_output_path' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/IMPLIB:%{interface_library_output_path}" + } + } + flag_set { + expand_if_all_available: 'libopts' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + iterate_over: 'libopts' + flag: '%{libopts}' + } + } + flag_set { + expand_if_all_available: 'libraries_to_link' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + action: 'c++-link-static-library' + flag_group { + iterate_over: 'libraries_to_link' + flag_group { + expand_if_equal: { + variable: 'libraries_to_link.type' + value: 'object_file_group' + } + iterate_over: 'libraries_to_link.object_files' + flag_group { + flag: '%{libraries_to_link.object_files}' + } + } + flag_group { + expand_if_equal: { + variable: 'libraries_to_link.type' + value: 'object_file' + } + flag_group { + flag: '%{libraries_to_link.name}' + } + } + flag_group { + expand_if_equal: { + variable: 'libraries_to_link.type' + value: 'interface_library' + } + flag_group { + flag: '%{libraries_to_link.name}' + } + } + flag_group { + expand_if_equal: { + variable: 'libraries_to_link.type' + value: 'static_library' + } + flag_group { + expand_if_false: 'libraries_to_link.is_whole_archive' + flag: '%{libraries_to_link.name}' + } + flag_group { + expand_if_true: 'libraries_to_link.is_whole_archive' + flag: '/WHOLEARCHIVE:%{libraries_to_link.name}' + } + } + } + } + } + + # Since this feature is declared earlier in the CROSSTOOL than + # "user_link_flags", this feature will be applied prior to it anwyhere they + # are both implied. And since "user_link_flags" contains the linkopts from + # the build rule, this allows the user to override the /SUBSYSTEM in the BUILD + # file. + feature { + name: 'linker_subsystem_flag' + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: '/SUBSYSTEM:CONSOLE' + } + } + } + + # The "user_link_flags" contains user-defined linkopts (from build rules) + # so it should be defined after features that declare user-overridable flags. + # For example the "linker_subsystem_flag" defines a default "/SUBSYSTEM" flag + # but we want to let the user override it, therefore "link_flag_subsystem" is + # defined earlier in the CROSSTOOL file than "user_link_flags". + feature { + name: 'user_link_flags' + flag_set { + expand_if_all_available: 'user_link_flags' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + iterate_over: 'user_link_flags' + flag: '%{user_link_flags}' + } + } + } + feature { + name: 'legacy_link_flags' + flag_set { + expand_if_all_available: 'legacy_link_flags' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + iterate_over: 'legacy_link_flags' + flag: '%{legacy_link_flags}' + } + } + } + + feature { + name: 'linker_param_file' + flag_set { + expand_if_all_available: 'linker_param_file' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + action: 'c++-link-static-library' + flag_group { + flag: '@%{linker_param_file}' + } + } + } + + feature { + name: 'static_link_msvcrt' + } + + feature { + name: 'static_link_msvcrt_no_debug' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/MT" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEFAULTLIB:libcmt.lib" + } + } + requires: { feature: 'fastbuild'} + requires: { feature: 'opt'} + } + + feature { + name: 'dynamic_link_msvcrt_no_debug' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/MD" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEFAULTLIB:msvcrt.lib" + } + } + requires: { feature: 'fastbuild'} + requires: { feature: 'opt'} + } + + feature { + name: 'static_link_msvcrt_debug' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/MTd" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEFAULTLIB:libcmtd.lib" + } + } + requires: { feature: 'dbg'} + } + + feature { + name: 'dynamic_link_msvcrt_debug' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/MDd" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEFAULTLIB:msvcrtd.lib" + } + } + requires: { feature: 'dbg'} + } + + feature { + name: 'dbg' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/Od" + flag: "/Z7" + flag: "/DDEBUG" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEBUG:FULL" + flag: "/INCREMENTAL:NO" + } + } + implies: 'generate_pdb_file' + } + + feature { + name: 'fastbuild' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/Od" + flag: "/Z7" + flag: "/DDEBUG" + } + } + flag_set { + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEBUG:FASTLINK" + flag: "/INCREMENTAL:NO" + } + } + implies: 'generate_pdb_file' + } + + feature { + name: 'opt' + flag_set { + action: 'c-compile' + action: 'c++-compile' + flag_group { + flag: "/O2" + flag: "/DNDEBUG" + } + } + } + + feature { + name: 'user_compile_flags' + flag_set { + expand_if_all_available: 'user_compile_flags' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + iterate_over: 'user_compile_flags' + flag: '%{user_compile_flags}' + } + } + } + + feature { + name: 'sysroot' + flag_set { + expand_if_all_available: 'sysroot' + action: 'assemble' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + iterate_over: 'sysroot' + flag: '--sysroot=%{sysroot}' + } + } + } + + feature { + name: 'unfiltered_compile_flags' + flag_set { + expand_if_all_available: 'unfiltered_compile_flags' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + iterate_over: 'unfiltered_compile_flags' + flag: '%{unfiltered_compile_flags}' + } + } + } + + feature { + name: 'compiler_output_flags' + flag_set { + action: 'assemble' + flag_group { + expand_if_all_available: 'output_file' + expand_if_none_available: 'output_assembly_file' + expand_if_none_available: 'output_preprocess_file' + flag: '/Fo%{output_file}' + flag: '/Zi' + } + } + flag_set { + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + expand_if_all_available: 'output_file' + expand_if_none_available: 'output_assembly_file' + expand_if_none_available: 'output_preprocess_file' + flag: '/Fo%{output_file}' + } + flag_group { + expand_if_all_available: 'output_file' + expand_if_all_available: 'output_assembly_file' + flag: '/Fa%{output_file}' + } + flag_group { + expand_if_all_available: 'output_file' + expand_if_all_available: 'output_preprocess_file' + flag: '/P' + flag: '/Fi%{output_file}' + } + } + } + + feature { + name: 'compiler_input_flags' + flag_set { + action: 'assemble' + action: 'preprocess-assemble' + action: 'c-compile' + action: 'c++-compile' + action: 'c++-header-parsing' + action: 'c++-module-compile' + action: 'c++-module-codegen' + flag_group { + expand_if_all_available: 'source_file' + flag: '/c' + flag: '%{source_file}' + } + } + } + + feature { + name : 'def_file', + flag_set { + expand_if_all_available: 'def_file_path' + action: 'c++-link-executable' + action: 'c++-link-dynamic-library' + action: "c++-link-nodeps-dynamic-library" + flag_group { + flag: "/DEF:%{def_file_path}" + # We can specify a different DLL name in DEF file, /ignore:4070 suppresses + # the warning message about DLL name doesn't match the default one. + # See https://msdn.microsoft.com/en-us/library/sfkk2fz7.aspx + flag: "/ignore:4070" + } + } + } + + feature { + name: 'windows_export_all_symbols' + } + + feature { + name: 'no_windows_export_all_symbols' + } + + linking_mode_flags { mode: DYNAMIC } +} diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/clang/bin/crosstool_wrapper_driver_is_not_gcc b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/clang/bin/crosstool_wrapper_driver_is_not_gcc new file mode 100755 index 0000000000..63893d3722 --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/clang/bin/crosstool_wrapper_driver_is_not_gcc @@ -0,0 +1,264 @@ +#!/usr/bin/env python +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Crosstool wrapper for compiling CUDA programs. + +SYNOPSIS: + crosstool_wrapper_is_not_gcc [options passed in by cc_library() + or cc_binary() rule] + +DESCRIPTION: + This script is expected to be called by the cc_library() or cc_binary() bazel + rules. When the option "-x cuda" is present in the list of arguments passed + to this script, it invokes the nvcc CUDA compiler. Most arguments are passed + as is as a string to --compiler-options of nvcc. When "-x cuda" is not + present, this wrapper invokes hybrid_driver_is_not_gcc with the input + arguments as is. + +NOTES: + Changes to the contents of this file must be propagated from + //third_party/gpus/crosstool/crosstool_wrapper_is_not_gcc to + //third_party/gpus/crosstool/v*/*/clang/bin/crosstool_wrapper_is_not_gcc +""" + +from __future__ import print_function + +__author__ = 'keveman@google.com (Manjunath Kudlur)' + +from argparse import ArgumentParser +import os +import subprocess +import re +import sys +import pipes + +# Template values set by cuda_autoconf. +CPU_COMPILER = ('/usr/bin/gcc') +GCC_HOST_COMPILER_PATH = ('/usr/bin/gcc') + +NVCC_PATH = '/usr/local/cuda-9.0/bin/nvcc' +PREFIX_DIR = os.path.dirname(GCC_HOST_COMPILER_PATH) +NVCC_VERSION = '9.0' + +def Log(s): + print('gpus/crosstool: {0}'.format(s)) + + +def GetOptionValue(argv, option): + """Extract the list of values for option from the argv list. + + Args: + argv: A list of strings, possibly the argv passed to main(). + option: The option whose value to extract, without the leading '-'. + + Returns: + A list of values, either directly following the option, + (eg., -opt val1 val2) or values collected from multiple occurrences of + the option (eg., -opt val1 -opt val2). + """ + + parser = ArgumentParser() + parser.add_argument('-' + option, nargs='*', action='append') + args, _ = parser.parse_known_args(argv) + if not args or not vars(args)[option]: + return [] + else: + return sum(vars(args)[option], []) + + +def GetHostCompilerOptions(argv): + """Collect the -isystem, -iquote, and --sysroot option values from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + + Returns: + The string that can be used as the --compiler-options to nvcc. + """ + + parser = ArgumentParser() + parser.add_argument('-isystem', nargs='*', action='append') + parser.add_argument('-iquote', nargs='*', action='append') + parser.add_argument('--sysroot', nargs=1) + parser.add_argument('-g', nargs='*', action='append') + parser.add_argument('-fno-canonical-system-headers', action='store_true') + + args, _ = parser.parse_known_args(argv) + + opts = '' + + if args.isystem: + opts += ' -isystem ' + ' -isystem '.join(sum(args.isystem, [])) + if args.iquote: + opts += ' -iquote ' + ' -iquote '.join(sum(args.iquote, [])) + if args.g: + opts += ' -g' + ' -g'.join(sum(args.g, [])) + if args.fno_canonical_system_headers: + opts += ' -fno-canonical-system-headers' + if args.sysroot: + opts += ' --sysroot ' + args.sysroot[0] + + return opts + +def _update_options(nvcc_options): + if NVCC_VERSION in ("7.0",): + return nvcc_options + + update_options = { "relaxed-constexpr" : "expt-relaxed-constexpr" } + return [ update_options[opt] if opt in update_options else opt + for opt in nvcc_options ] + +def GetNvccOptions(argv): + """Collect the -nvcc_options values from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + + Returns: + The string that can be passed directly to nvcc. + """ + + parser = ArgumentParser() + parser.add_argument('-nvcc_options', nargs='*', action='append') + + args, _ = parser.parse_known_args(argv) + + if args.nvcc_options: + options = _update_options(sum(args.nvcc_options, [])) + return ' '.join(['--'+a for a in options]) + return '' + + +def InvokeNvcc(argv, log=False): + """Call nvcc with arguments assembled from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + log: True if logging is requested. + + Returns: + The return value of calling os.system('nvcc ' + args) + """ + + host_compiler_options = GetHostCompilerOptions(argv) + nvcc_compiler_options = GetNvccOptions(argv) + opt_option = GetOptionValue(argv, 'O') + m_options = GetOptionValue(argv, 'm') + m_options = ''.join([' -m' + m for m in m_options if m in ['32', '64']]) + include_options = GetOptionValue(argv, 'I') + out_file = GetOptionValue(argv, 'o') + depfiles = GetOptionValue(argv, 'MF') + defines = GetOptionValue(argv, 'D') + defines = ''.join([' -D' + define for define in defines]) + undefines = GetOptionValue(argv, 'U') + undefines = ''.join([' -U' + define for define in undefines]) + std_options = GetOptionValue(argv, 'std') + # currently only c++11 is supported by Cuda 7.0 std argument + nvcc_allowed_std_options = ["c++11"] + std_options = ''.join([' -std=' + define + for define in std_options if define in nvcc_allowed_std_options]) + + # The list of source files get passed after the -c option. I don't know of + # any other reliable way to just get the list of source files to be compiled. + src_files = GetOptionValue(argv, 'c') + + # Pass -w through from host to nvcc, but don't do anything fancier with + # warnings-related flags, since they're not necessarily the same across + # compilers. + warning_options = ' -w' if '-w' in argv else '' + + if len(src_files) == 0: + return 1 + if len(out_file) != 1: + return 1 + + opt = (' -O2' if (len(opt_option) > 0 and int(opt_option[0]) > 0) + else ' -g -G') + + includes = (' -I ' + ' -I '.join(include_options) + if len(include_options) > 0 + else '') + + # Unfortunately, there are other options that have -c prefix too. + # So allowing only those look like C/C++ files. + src_files = [f for f in src_files if + re.search('\.cpp$|\.cc$|\.c$|\.cxx$|\.C$', f)] + srcs = ' '.join(src_files) + out = ' -o ' + out_file[0] + + supported_cuda_compute_capabilities = [ "3.0" ] + nvccopts = '-D_FORCE_INLINES ' + for capability in supported_cuda_compute_capabilities: + capability = capability.replace('.', '') + nvccopts += r'-gencode=arch=compute_%s,\"code=sm_%s,compute_%s\" ' % ( + capability, capability, capability) + nvccopts += ' ' + nvcc_compiler_options + nvccopts += undefines + nvccopts += defines + nvccopts += std_options + nvccopts += m_options + nvccopts += warning_options + + if depfiles: + # Generate the dependency file + depfile = depfiles[0] + cmd = (NVCC_PATH + ' ' + nvccopts + + ' --compiler-options "' + host_compiler_options + '"' + + ' --compiler-bindir=' + GCC_HOST_COMPILER_PATH + + ' -I .' + + ' -x cu ' + opt + includes + ' ' + srcs + ' -M -o ' + depfile) + if log: Log(cmd) + exit_status = os.system(cmd) + if exit_status != 0: + return exit_status + + cmd = (NVCC_PATH + ' ' + nvccopts + + ' --compiler-options "' + host_compiler_options + ' -fPIC"' + + ' --compiler-bindir=' + GCC_HOST_COMPILER_PATH + + ' -I .' + + ' -x cu ' + opt + includes + ' -c ' + srcs + out) + + # TODO(zhengxq): for some reason, 'gcc' needs this help to find 'as'. + # Need to investigate and fix. + cmd = 'PATH=' + PREFIX_DIR + ':$PATH ' + cmd + if log: Log(cmd) + return os.system(cmd) + + +def main(): + parser = ArgumentParser() + parser.add_argument('-x', nargs=1) + parser.add_argument('--cuda_log', action='store_true') + args, leftover = parser.parse_known_args(sys.argv[1:]) + + if args.x and args.x[0] == 'cuda': + if args.cuda_log: Log('-x cuda') + leftover = [pipes.quote(s) for s in leftover] + if args.cuda_log: Log('using nvcc') + return InvokeNvcc(leftover, log=args.cuda_log) + + # Strip our flags before passing through to the CPU compiler for files which + # are not -x cuda. We can't just pass 'leftover' because it also strips -x. + # We not only want to pass -x to the CPU compiler, but also keep it in its + # relative location in the argv list (the compiler is actually sensitive to + # this). + cpu_compiler_flags = [flag for flag in sys.argv[1:] + if not flag.startswith(('--cuda_log'))] + + return subprocess.call([CPU_COMPILER] + cpu_compiler_flags) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/windows/msvc_wrapper_for_nvcc.bat b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/windows/msvc_wrapper_for_nvcc.bat new file mode 100755 index 0000000000..e896e654fd --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/windows/msvc_wrapper_for_nvcc.bat @@ -0,0 +1,20 @@ +:: Copyright 2015 The TensorFlow Authors. All Rights Reserved. +:: +:: Licensed under the Apache License, Version 2.0 (the "License"); +:: you may not use this file except in compliance with the License. +:: You may obtain a copy of the License at +:: +:: http://www.apache.org/licenses/LICENSE-2.0 +:: +:: Unless required by applicable law or agreed to in writing, software +:: distributed under the License is distributed on an "AS IS" BASIS, +:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +:: See the License for the specific language governing permissions and +:: limitations under the License. +:: ============================================================================= + +:: Invoke msvc_wrapper_for_nvcc.py, which is located in the same directory. +@echo OFF +set arg0=%~0 +for %%F in ("%arg0%") do set DRIVER_BIN=%%~dpF +"/usr/bin/python3" -B "%DRIVER_BIN%\msvc_wrapper_for_nvcc.py" %* diff --git a/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/windows/msvc_wrapper_for_nvcc.py b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/windows/msvc_wrapper_for_nvcc.py new file mode 100755 index 0000000000..859b3196d5 --- /dev/null +++ b/third_party/toolchains/preconfig/ubuntu14.04/gcc-nvcc-cuda9.0/windows/msvc_wrapper_for_nvcc.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Crosstool wrapper for compiling CUDA programs with nvcc on Windows. + +DESCRIPTION: + This script is the Windows version of //third_party/gpus/crosstool/crosstool_wrapper_is_not_gcc +""" + +from __future__ import print_function + +from argparse import ArgumentParser +import os +import subprocess +import re +import sys +import pipes + +# Template values set by cuda_autoconf. +CPU_COMPILER = ('/usr/bin/gcc') +GCC_HOST_COMPILER_PATH = ('/usr/bin/gcc') + +NVCC_PATH = '/usr/local/cuda-9.0/bin/nvcc' +NVCC_VERSION = '9.0' +NVCC_TEMP_DIR = "C:\\Windows\\Temp\\nvcc_inter_files_tmp_dir" +supported_cuda_compute_capabilities = [ "3.0" ] + +def Log(s): + print('gpus/crosstool: {0}'.format(s)) + + +def GetOptionValue(argv, option): + """Extract the list of values for option from options. + + Args: + option: The option whose value to extract, without the leading '/'. + + Returns: + 1. A list of values, either directly following the option, + (eg., /opt val1 val2) or values collected from multiple occurrences of + the option (eg., /opt val1 /opt val2). + 2. The leftover options. + """ + + parser = ArgumentParser(prefix_chars='/') + parser.add_argument('/' + option, nargs='*', action='append') + args, leftover = parser.parse_known_args(argv) + if args and vars(args)[option]: + return (sum(vars(args)[option], []), leftover) + return ([], leftover) + +def _update_options(nvcc_options): + if NVCC_VERSION in ("7.0",): + return nvcc_options + + update_options = { "relaxed-constexpr" : "expt-relaxed-constexpr" } + return [ update_options[opt] if opt in update_options else opt + for opt in nvcc_options ] + +def GetNvccOptions(argv): + """Collect the -nvcc_options values from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + + Returns: + 1. The string that can be passed directly to nvcc. + 2. The leftover options. + """ + + parser = ArgumentParser() + parser.add_argument('-nvcc_options', nargs='*', action='append') + + args, leftover = parser.parse_known_args(argv) + + if args.nvcc_options: + options = _update_options(sum(args.nvcc_options, [])) + return (['--' + a for a in options], leftover) + return ([], leftover) + + +def InvokeNvcc(argv, log=False): + """Call nvcc with arguments assembled from argv. + + Args: + argv: A list of strings, possibly the argv passed to main(). + log: True if logging is requested. + + Returns: + The return value of calling os.system('nvcc ' + args) + """ + + src_files = [f for f in argv if + re.search('\.cpp$|\.cc$|\.c$|\.cxx$|\.C$', f)] + if len(src_files) == 0: + raise Error('No source files found for cuda compilation.') + + out_file = [ f for f in argv if f.startswith('/Fo') ] + if len(out_file) != 1: + raise Error('Please sepecify exactly one output file for cuda compilation.') + out = ['-o', out_file[0][len('/Fo'):]] + + nvcc_compiler_options, argv = GetNvccOptions(argv) + + opt_option, argv = GetOptionValue(argv, 'O') + opt = ['-g', '-G'] + if (len(opt_option) > 0 and opt_option[0] != 'd'): + opt = ['-O2'] + + include_options, argv = GetOptionValue(argv, 'I') + includes = ["-I " + include for include in include_options] + + defines, argv = GetOptionValue(argv, 'D') + defines = ['-D' + define for define in defines] + + undefines, argv = GetOptionValue(argv, 'U') + undefines = ['-U' + define for define in undefines] + + # The rest of the unrecongized options should be passed to host compiler + host_compiler_options = [option for option in argv if option not in (src_files + out_file)] + + m_options = ["-m64"] + + nvccopts = ['-D_FORCE_INLINES'] + for capability in supported_cuda_compute_capabilities: + capability = capability.replace('.', '') + nvccopts += [r'-gencode=arch=compute_%s,"code=sm_%s,compute_%s"' % ( + capability, capability, capability)] + nvccopts += nvcc_compiler_options + nvccopts += undefines + nvccopts += defines + nvccopts += m_options + nvccopts += ['--compiler-options="' + " ".join(host_compiler_options) + '"'] + nvccopts += ['-x', 'cu'] + opt + includes + out + ['-c'] + src_files + # If we don't specify --keep-dir, nvcc will generate intermediate files under TEMP + # Put them under NVCC_TEMP_DIR instead, then Bazel can ignore files under NVCC_TEMP_DIR during dependency check + # http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#options-for-guiding-compiler-driver + # Different actions are sharing NVCC_TEMP_DIR, so we cannot remove it if the directory already exists. + if os.path.isfile(NVCC_TEMP_DIR): + os.remove(NVCC_TEMP_DIR) + if not os.path.exists(NVCC_TEMP_DIR): + os.makedirs(NVCC_TEMP_DIR) + nvccopts += ['--keep', '--keep-dir', NVCC_TEMP_DIR] + cmd = [NVCC_PATH] + nvccopts + if log: + Log(cmd) + proc = subprocess.Popen(cmd, + stdout=sys.stdout, + stderr=sys.stderr, + env=os.environ.copy(), + shell=True) + proc.wait() + return proc.returncode + +def main(): + parser = ArgumentParser() + parser.add_argument('-x', nargs=1) + parser.add_argument('--cuda_log', action='store_true') + args, leftover = parser.parse_known_args(sys.argv[1:]) + + if args.x and args.x[0] == 'cuda': + if args.cuda_log: Log('-x cuda') + leftover = [pipes.quote(s) for s in leftover] + if args.cuda_log: Log('using nvcc') + return InvokeNvcc(leftover, log=args.cuda_log) + + # Strip our flags before passing through to the CPU compiler for files which + # are not -x cuda. We can't just pass 'leftover' because it also strips -x. + # We not only want to pass -x to the CPU compiler, but also keep it in its + # relative location in the argv list (the compiler is actually sensitive to + # this). + cpu_compiler_flags = [flag for flag in sys.argv[1:] + if not flag.startswith(('--cuda_log')) + and not flag.startswith(('-nvcc_options'))] + + return subprocess.call([CPU_COMPILER] + cpu_compiler_flags) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/third_party/toolchains/preconfig/ubuntu14.04/py3/BUILD b/third_party/toolchains/preconfig/ubuntu14.04/py3/BUILD index e021df9e1e..460c879d32 100755 --- a/third_party/toolchains/preconfig/ubuntu14.04/py3/BUILD +++ b/third_party/toolchains/preconfig/ubuntu14.04/py3/BUILD @@ -136,7 +136,7 @@ genrule( "python_include/weakrefobject.h", ], cmd = """ -cp "/usr/include/python3.4m/Python-ast.h" "$(@D)/python_include/Python-ast.h" && cp "/usr/include/python3.4m/Python.h" "$(@D)/python_include/Python.h" && cp "/usr/include/python3.4m/abstract.h" "$(@D)/python_include/abstract.h" && cp "/usr/include/python3.4m/accu.h" "$(@D)/python_include/accu.h" && cp "/usr/include/python3.4m/asdl.h" "$(@D)/python_include/asdl.h" && cp "/usr/include/python3.4m/ast.h" "$(@D)/python_include/ast.h" && cp "/usr/include/python3.4m/bitset.h" "$(@D)/python_include/bitset.h" && cp "/usr/include/python3.4m/bltinmodule.h" "$(@D)/python_include/bltinmodule.h" && cp "/usr/include/python3.4m/boolobject.h" "$(@D)/python_include/boolobject.h" && cp "/usr/include/python3.4m/bytearrayobject.h" "$(@D)/python_include/bytearrayobject.h" && cp "/usr/include/python3.4m/bytes_methods.h" "$(@D)/python_include/bytes_methods.h" && cp "/usr/include/python3.4m/bytesobject.h" "$(@D)/python_include/bytesobject.h" && cp "/usr/include/python3.4m/cellobject.h" "$(@D)/python_include/cellobject.h" && cp "/usr/include/python3.4m/ceval.h" "$(@D)/python_include/ceval.h" && cp "/usr/include/python3.4m/classobject.h" "$(@D)/python_include/classobject.h" && cp "/usr/include/python3.4m/code.h" "$(@D)/python_include/code.h" && cp "/usr/include/python3.4m/codecs.h" "$(@D)/python_include/codecs.h" && cp "/usr/include/python3.4m/compile.h" "$(@D)/python_include/compile.h" && cp "/usr/include/python3.4m/complexobject.h" "$(@D)/python_include/complexobject.h" && cp "/usr/include/python3.4m/datetime.h" "$(@D)/python_include/datetime.h" && cp "/usr/include/python3.4m/descrobject.h" "$(@D)/python_include/descrobject.h" && cp "/usr/include/python3.4m/dictobject.h" "$(@D)/python_include/dictobject.h" && cp "/usr/include/python3.4m/dtoa.h" "$(@D)/python_include/dtoa.h" && cp "/usr/include/python3.4m/dynamic_annotations.h" "$(@D)/python_include/dynamic_annotations.h" && cp "/usr/include/python3.4m/enumobject.h" "$(@D)/python_include/enumobject.h" && cp "/usr/include/python3.4m/errcode.h" "$(@D)/python_include/errcode.h" && cp "/usr/include/python3.4m/eval.h" "$(@D)/python_include/eval.h" && cp "/usr/include/python3.4m/fileobject.h" "$(@D)/python_include/fileobject.h" && cp "/usr/include/python3.4m/fileutils.h" "$(@D)/python_include/fileutils.h" && cp "/usr/include/python3.4m/floatobject.h" "$(@D)/python_include/floatobject.h" && cp "/usr/include/python3.4m/frameobject.h" "$(@D)/python_include/frameobject.h" && cp "/usr/include/python3.4m/funcobject.h" "$(@D)/python_include/funcobject.h" && cp "/usr/include/python3.4m/genobject.h" "$(@D)/python_include/genobject.h" && cp "/usr/include/python3.4m/graminit.h" "$(@D)/python_include/graminit.h" && cp "/usr/include/python3.4m/grammar.h" "$(@D)/python_include/grammar.h" && cp "/usr/include/python3.4m/import.h" "$(@D)/python_include/import.h" && cp "/usr/include/python3.4m/intrcheck.h" "$(@D)/python_include/intrcheck.h" && cp "/usr/include/python3.4m/iterobject.h" "$(@D)/python_include/iterobject.h" && cp "/usr/include/python3.4m/listobject.h" "$(@D)/python_include/listobject.h" && cp "/usr/include/python3.4m/longintrepr.h" "$(@D)/python_include/longintrepr.h" && cp "/usr/include/python3.4m/longobject.h" "$(@D)/python_include/longobject.h" && cp "/usr/include/python3.4m/marshal.h" "$(@D)/python_include/marshal.h" && cp "/usr/include/python3.4m/memoryobject.h" "$(@D)/python_include/memoryobject.h" && cp "/usr/include/python3.4m/metagrammar.h" "$(@D)/python_include/metagrammar.h" && cp "/usr/include/python3.4m/methodobject.h" "$(@D)/python_include/methodobject.h" && cp "/usr/include/python3.4m/modsupport.h" "$(@D)/python_include/modsupport.h" && cp "/usr/include/python3.4m/moduleobject.h" "$(@D)/python_include/moduleobject.h" && cp "/usr/include/python3.4m/namespaceobject.h" "$(@D)/python_include/namespaceobject.h" && cp "/usr/include/python3.4m/node.h" "$(@D)/python_include/node.h" && cp "/usr/include/python3.4m/object.h" "$(@D)/python_include/object.h" && cp "/usr/include/python3.4m/objimpl.h" "$(@D)/python_include/objimpl.h" && cp "/usr/include/python3.4m/opcode.h" "$(@D)/python_include/opcode.h" && cp "/usr/include/python3.4m/osdefs.h" "$(@D)/python_include/osdefs.h" && cp "/usr/include/python3.4m/parsetok.h" "$(@D)/python_include/parsetok.h" && cp "/usr/include/python3.4m/patchlevel.h" "$(@D)/python_include/patchlevel.h" && cp "/usr/include/python3.4m/pgen.h" "$(@D)/python_include/pgen.h" && cp "/usr/include/python3.4m/pgenheaders.h" "$(@D)/python_include/pgenheaders.h" && cp "/usr/include/python3.4m/py_curses.h" "$(@D)/python_include/py_curses.h" && cp "/usr/include/python3.4m/pyarena.h" "$(@D)/python_include/pyarena.h" && cp "/usr/include/python3.4m/pyatomic.h" "$(@D)/python_include/pyatomic.h" && cp "/usr/include/python3.4m/pycapsule.h" "$(@D)/python_include/pycapsule.h" && cp "/usr/include/python3.4m/pyconfig.h" "$(@D)/python_include/pyconfig.h" && cp "/usr/include/python3.4m/pyctype.h" "$(@D)/python_include/pyctype.h" && cp "/usr/include/python3.4m/pydebug.h" "$(@D)/python_include/pydebug.h" && cp "/usr/include/python3.4m/pyerrors.h" "$(@D)/python_include/pyerrors.h" && cp "/usr/include/python3.4m/pyexpat.h" "$(@D)/python_include/pyexpat.h" && cp "/usr/include/python3.4m/pyfpe.h" "$(@D)/python_include/pyfpe.h" && cp "/usr/include/python3.4m/pygetopt.h" "$(@D)/python_include/pygetopt.h" && cp "/usr/include/python3.4m/pyhash.h" "$(@D)/python_include/pyhash.h" && cp "/usr/include/python3.4m/pymacconfig.h" "$(@D)/python_include/pymacconfig.h" && cp "/usr/include/python3.4m/pymacro.h" "$(@D)/python_include/pymacro.h" && cp "/usr/include/python3.4m/pymath.h" "$(@D)/python_include/pymath.h" && cp "/usr/include/python3.4m/pymem.h" "$(@D)/python_include/pymem.h" && cp "/usr/include/python3.4m/pyport.h" "$(@D)/python_include/pyport.h" && cp "/usr/include/python3.4m/pystate.h" "$(@D)/python_include/pystate.h" && cp "/usr/include/python3.4m/pystrcmp.h" "$(@D)/python_include/pystrcmp.h" && cp "/usr/include/python3.4m/pystrtod.h" "$(@D)/python_include/pystrtod.h" && cp "/usr/include/python3.4m/pythonrun.h" "$(@D)/python_include/pythonrun.h" && cp "/usr/include/python3.4m/pythread.h" "$(@D)/python_include/pythread.h" && cp "/usr/include/python3.4m/pytime.h" "$(@D)/python_include/pytime.h" && cp "/usr/include/python3.4m/rangeobject.h" "$(@D)/python_include/rangeobject.h" && cp "/usr/include/python3.4m/setobject.h" "$(@D)/python_include/setobject.h" && cp "/usr/include/python3.4m/sliceobject.h" "$(@D)/python_include/sliceobject.h" && cp "/usr/include/python3.4m/structmember.h" "$(@D)/python_include/structmember.h" && cp "/usr/include/python3.4m/structseq.h" "$(@D)/python_include/structseq.h" && cp "/usr/include/python3.4m/symtable.h" "$(@D)/python_include/symtable.h" && cp "/usr/include/python3.4m/sysmodule.h" "$(@D)/python_include/sysmodule.h" && cp "/usr/include/python3.4m/token.h" "$(@D)/python_include/token.h" && cp "/usr/include/python3.4m/traceback.h" "$(@D)/python_include/traceback.h" && cp "/usr/include/python3.4m/tupleobject.h" "$(@D)/python_include/tupleobject.h" && cp "/usr/include/python3.4m/typeslots.h" "$(@D)/python_include/typeslots.h" && cp "/usr/include/python3.4m/ucnhash.h" "$(@D)/python_include/ucnhash.h" && cp "/usr/include/python3.4m/unicodeobject.h" "$(@D)/python_include/unicodeobject.h" && cp "/usr/include/python3.4m/warnings.h" "$(@D)/python_include/warnings.h" && cp "/usr/include/python3.4m/weakrefobject.h" "$(@D)/python_include/weakrefobject.h" +cp -f "/usr/include/python3.4m/Python-ast.h" "$(@D)/python_include/Python-ast.h" && cp -f "/usr/include/python3.4m/Python.h" "$(@D)/python_include/Python.h" && cp -f "/usr/include/python3.4m/abstract.h" "$(@D)/python_include/abstract.h" && cp -f "/usr/include/python3.4m/accu.h" "$(@D)/python_include/accu.h" && cp -f "/usr/include/python3.4m/asdl.h" "$(@D)/python_include/asdl.h" && cp -f "/usr/include/python3.4m/ast.h" "$(@D)/python_include/ast.h" && cp -f "/usr/include/python3.4m/bitset.h" "$(@D)/python_include/bitset.h" && cp -f "/usr/include/python3.4m/bltinmodule.h" "$(@D)/python_include/bltinmodule.h" && cp -f "/usr/include/python3.4m/boolobject.h" "$(@D)/python_include/boolobject.h" && cp -f "/usr/include/python3.4m/bytearrayobject.h" "$(@D)/python_include/bytearrayobject.h" && cp -f "/usr/include/python3.4m/bytes_methods.h" "$(@D)/python_include/bytes_methods.h" && cp -f "/usr/include/python3.4m/bytesobject.h" "$(@D)/python_include/bytesobject.h" && cp -f "/usr/include/python3.4m/cellobject.h" "$(@D)/python_include/cellobject.h" && cp -f "/usr/include/python3.4m/ceval.h" "$(@D)/python_include/ceval.h" && cp -f "/usr/include/python3.4m/classobject.h" "$(@D)/python_include/classobject.h" && cp -f "/usr/include/python3.4m/code.h" "$(@D)/python_include/code.h" && cp -f "/usr/include/python3.4m/codecs.h" "$(@D)/python_include/codecs.h" && cp -f "/usr/include/python3.4m/compile.h" "$(@D)/python_include/compile.h" && cp -f "/usr/include/python3.4m/complexobject.h" "$(@D)/python_include/complexobject.h" && cp -f "/usr/include/python3.4m/datetime.h" "$(@D)/python_include/datetime.h" && cp -f "/usr/include/python3.4m/descrobject.h" "$(@D)/python_include/descrobject.h" && cp -f "/usr/include/python3.4m/dictobject.h" "$(@D)/python_include/dictobject.h" && cp -f "/usr/include/python3.4m/dtoa.h" "$(@D)/python_include/dtoa.h" && cp -f "/usr/include/python3.4m/dynamic_annotations.h" "$(@D)/python_include/dynamic_annotations.h" && cp -f "/usr/include/python3.4m/enumobject.h" "$(@D)/python_include/enumobject.h" && cp -f "/usr/include/python3.4m/errcode.h" "$(@D)/python_include/errcode.h" && cp -f "/usr/include/python3.4m/eval.h" "$(@D)/python_include/eval.h" && cp -f "/usr/include/python3.4m/fileobject.h" "$(@D)/python_include/fileobject.h" && cp -f "/usr/include/python3.4m/fileutils.h" "$(@D)/python_include/fileutils.h" && cp -f "/usr/include/python3.4m/floatobject.h" "$(@D)/python_include/floatobject.h" && cp -f "/usr/include/python3.4m/frameobject.h" "$(@D)/python_include/frameobject.h" && cp -f "/usr/include/python3.4m/funcobject.h" "$(@D)/python_include/funcobject.h" && cp -f "/usr/include/python3.4m/genobject.h" "$(@D)/python_include/genobject.h" && cp -f "/usr/include/python3.4m/graminit.h" "$(@D)/python_include/graminit.h" && cp -f "/usr/include/python3.4m/grammar.h" "$(@D)/python_include/grammar.h" && cp -f "/usr/include/python3.4m/import.h" "$(@D)/python_include/import.h" && cp -f "/usr/include/python3.4m/intrcheck.h" "$(@D)/python_include/intrcheck.h" && cp -f "/usr/include/python3.4m/iterobject.h" "$(@D)/python_include/iterobject.h" && cp -f "/usr/include/python3.4m/listobject.h" "$(@D)/python_include/listobject.h" && cp -f "/usr/include/python3.4m/longintrepr.h" "$(@D)/python_include/longintrepr.h" && cp -f "/usr/include/python3.4m/longobject.h" "$(@D)/python_include/longobject.h" && cp -f "/usr/include/python3.4m/marshal.h" "$(@D)/python_include/marshal.h" && cp -f "/usr/include/python3.4m/memoryobject.h" "$(@D)/python_include/memoryobject.h" && cp -f "/usr/include/python3.4m/metagrammar.h" "$(@D)/python_include/metagrammar.h" && cp -f "/usr/include/python3.4m/methodobject.h" "$(@D)/python_include/methodobject.h" && cp -f "/usr/include/python3.4m/modsupport.h" "$(@D)/python_include/modsupport.h" && cp -f "/usr/include/python3.4m/moduleobject.h" "$(@D)/python_include/moduleobject.h" && cp -f "/usr/include/python3.4m/namespaceobject.h" "$(@D)/python_include/namespaceobject.h" && cp -f "/usr/include/python3.4m/node.h" "$(@D)/python_include/node.h" && cp -f "/usr/include/python3.4m/object.h" "$(@D)/python_include/object.h" && cp -f "/usr/include/python3.4m/objimpl.h" "$(@D)/python_include/objimpl.h" && cp -f "/usr/include/python3.4m/opcode.h" "$(@D)/python_include/opcode.h" && cp -f "/usr/include/python3.4m/osdefs.h" "$(@D)/python_include/osdefs.h" && cp -f "/usr/include/python3.4m/parsetok.h" "$(@D)/python_include/parsetok.h" && cp -f "/usr/include/python3.4m/patchlevel.h" "$(@D)/python_include/patchlevel.h" && cp -f "/usr/include/python3.4m/pgen.h" "$(@D)/python_include/pgen.h" && cp -f "/usr/include/python3.4m/pgenheaders.h" "$(@D)/python_include/pgenheaders.h" && cp -f "/usr/include/python3.4m/py_curses.h" "$(@D)/python_include/py_curses.h" && cp -f "/usr/include/python3.4m/pyarena.h" "$(@D)/python_include/pyarena.h" && cp -f "/usr/include/python3.4m/pyatomic.h" "$(@D)/python_include/pyatomic.h" && cp -f "/usr/include/python3.4m/pycapsule.h" "$(@D)/python_include/pycapsule.h" && cp -f "/usr/include/python3.4m/pyconfig.h" "$(@D)/python_include/pyconfig.h" && cp -f "/usr/include/python3.4m/pyctype.h" "$(@D)/python_include/pyctype.h" && cp -f "/usr/include/python3.4m/pydebug.h" "$(@D)/python_include/pydebug.h" && cp -f "/usr/include/python3.4m/pyerrors.h" "$(@D)/python_include/pyerrors.h" && cp -f "/usr/include/python3.4m/pyexpat.h" "$(@D)/python_include/pyexpat.h" && cp -f "/usr/include/python3.4m/pyfpe.h" "$(@D)/python_include/pyfpe.h" && cp -f "/usr/include/python3.4m/pygetopt.h" "$(@D)/python_include/pygetopt.h" && cp -f "/usr/include/python3.4m/pyhash.h" "$(@D)/python_include/pyhash.h" && cp -f "/usr/include/python3.4m/pymacconfig.h" "$(@D)/python_include/pymacconfig.h" && cp -f "/usr/include/python3.4m/pymacro.h" "$(@D)/python_include/pymacro.h" && cp -f "/usr/include/python3.4m/pymath.h" "$(@D)/python_include/pymath.h" && cp -f "/usr/include/python3.4m/pymem.h" "$(@D)/python_include/pymem.h" && cp -f "/usr/include/python3.4m/pyport.h" "$(@D)/python_include/pyport.h" && cp -f "/usr/include/python3.4m/pystate.h" "$(@D)/python_include/pystate.h" && cp -f "/usr/include/python3.4m/pystrcmp.h" "$(@D)/python_include/pystrcmp.h" && cp -f "/usr/include/python3.4m/pystrtod.h" "$(@D)/python_include/pystrtod.h" && cp -f "/usr/include/python3.4m/pythonrun.h" "$(@D)/python_include/pythonrun.h" && cp -f "/usr/include/python3.4m/pythread.h" "$(@D)/python_include/pythread.h" && cp -f "/usr/include/python3.4m/pytime.h" "$(@D)/python_include/pytime.h" && cp -f "/usr/include/python3.4m/rangeobject.h" "$(@D)/python_include/rangeobject.h" && cp -f "/usr/include/python3.4m/setobject.h" "$(@D)/python_include/setobject.h" && cp -f "/usr/include/python3.4m/sliceobject.h" "$(@D)/python_include/sliceobject.h" && cp -f "/usr/include/python3.4m/structmember.h" "$(@D)/python_include/structmember.h" && cp -f "/usr/include/python3.4m/structseq.h" "$(@D)/python_include/structseq.h" && cp -f "/usr/include/python3.4m/symtable.h" "$(@D)/python_include/symtable.h" && cp -f "/usr/include/python3.4m/sysmodule.h" "$(@D)/python_include/sysmodule.h" && cp -f "/usr/include/python3.4m/token.h" "$(@D)/python_include/token.h" && cp -f "/usr/include/python3.4m/traceback.h" "$(@D)/python_include/traceback.h" && cp -f "/usr/include/python3.4m/tupleobject.h" "$(@D)/python_include/tupleobject.h" && cp -f "/usr/include/python3.4m/typeslots.h" "$(@D)/python_include/typeslots.h" && cp -f "/usr/include/python3.4m/ucnhash.h" "$(@D)/python_include/ucnhash.h" && cp -f "/usr/include/python3.4m/unicodeobject.h" "$(@D)/python_include/unicodeobject.h" && cp -f "/usr/include/python3.4m/warnings.h" "$(@D)/python_include/warnings.h" && cp -f "/usr/include/python3.4m/weakrefobject.h" "$(@D)/python_include/weakrefobject.h" """, ) @@ -171,6 +171,6 @@ genrule( "numpy_include/numpy/utils.h", ], cmd = """ -cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/__multiarray_api.h" "$(@D)/numpy_include/numpy/__multiarray_api.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/__ufunc_api.h" "$(@D)/numpy_include/numpy/__ufunc_api.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/_neighborhood_iterator_imp.h" "$(@D)/numpy_include/numpy/_neighborhood_iterator_imp.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/_numpyconfig.h" "$(@D)/numpy_include/numpy/_numpyconfig.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/arrayobject.h" "$(@D)/numpy_include/numpy/arrayobject.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/arrayscalars.h" "$(@D)/numpy_include/numpy/arrayscalars.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/halffloat.h" "$(@D)/numpy_include/numpy/halffloat.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/multiarray_api.txt" "$(@D)/numpy_include/numpy/multiarray_api.txt" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/ndarrayobject.h" "$(@D)/numpy_include/numpy/ndarrayobject.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/ndarraytypes.h" "$(@D)/numpy_include/numpy/ndarraytypes.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/noprefix.h" "$(@D)/numpy_include/numpy/noprefix.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h" "$(@D)/numpy_include/numpy/npy_1_7_deprecated_api.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_3kcompat.h" "$(@D)/numpy_include/numpy/npy_3kcompat.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_common.h" "$(@D)/numpy_include/numpy/npy_common.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_cpu.h" "$(@D)/numpy_include/numpy/npy_cpu.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_endian.h" "$(@D)/numpy_include/numpy/npy_endian.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_interrupt.h" "$(@D)/numpy_include/numpy/npy_interrupt.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_math.h" "$(@D)/numpy_include/numpy/npy_math.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_no_deprecated_api.h" "$(@D)/numpy_include/numpy/npy_no_deprecated_api.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_os.h" "$(@D)/numpy_include/numpy/npy_os.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/numpyconfig.h" "$(@D)/numpy_include/numpy/numpyconfig.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/old_defines.h" "$(@D)/numpy_include/numpy/old_defines.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/oldnumeric.h" "$(@D)/numpy_include/numpy/oldnumeric.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/ufunc_api.txt" "$(@D)/numpy_include/numpy/ufunc_api.txt" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/ufuncobject.h" "$(@D)/numpy_include/numpy/ufuncobject.h" && cp "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/utils.h" "$(@D)/numpy_include/numpy/utils.h" +cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/__multiarray_api.h" "$(@D)/numpy_include/numpy/__multiarray_api.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/__ufunc_api.h" "$(@D)/numpy_include/numpy/__ufunc_api.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/_neighborhood_iterator_imp.h" "$(@D)/numpy_include/numpy/_neighborhood_iterator_imp.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/_numpyconfig.h" "$(@D)/numpy_include/numpy/_numpyconfig.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/arrayobject.h" "$(@D)/numpy_include/numpy/arrayobject.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/arrayscalars.h" "$(@D)/numpy_include/numpy/arrayscalars.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/halffloat.h" "$(@D)/numpy_include/numpy/halffloat.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/multiarray_api.txt" "$(@D)/numpy_include/numpy/multiarray_api.txt" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/ndarrayobject.h" "$(@D)/numpy_include/numpy/ndarrayobject.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/ndarraytypes.h" "$(@D)/numpy_include/numpy/ndarraytypes.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/noprefix.h" "$(@D)/numpy_include/numpy/noprefix.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h" "$(@D)/numpy_include/numpy/npy_1_7_deprecated_api.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_3kcompat.h" "$(@D)/numpy_include/numpy/npy_3kcompat.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_common.h" "$(@D)/numpy_include/numpy/npy_common.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_cpu.h" "$(@D)/numpy_include/numpy/npy_cpu.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_endian.h" "$(@D)/numpy_include/numpy/npy_endian.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_interrupt.h" "$(@D)/numpy_include/numpy/npy_interrupt.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_math.h" "$(@D)/numpy_include/numpy/npy_math.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_no_deprecated_api.h" "$(@D)/numpy_include/numpy/npy_no_deprecated_api.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/npy_os.h" "$(@D)/numpy_include/numpy/npy_os.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/numpyconfig.h" "$(@D)/numpy_include/numpy/numpyconfig.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/old_defines.h" "$(@D)/numpy_include/numpy/old_defines.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/oldnumeric.h" "$(@D)/numpy_include/numpy/oldnumeric.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/ufunc_api.txt" "$(@D)/numpy_include/numpy/ufunc_api.txt" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/ufuncobject.h" "$(@D)/numpy_include/numpy/ufuncobject.h" && cp -f "/usr/local/lib/python3.4/dist-packages/numpy/core/include/numpy/utils.h" "$(@D)/numpy_include/numpy/utils.h" """, ) diff --git a/third_party/toolchains/preconfig/win_1803/BUILD b/third_party/toolchains/preconfig/win_1803/BUILD index 45209d260d..ac599bc2f3 100644 --- a/third_party/toolchains/preconfig/win_1803/BUILD +++ b/third_party/toolchains/preconfig/win_1803/BUILD @@ -17,7 +17,7 @@ platform( remote_execution_properties = """ properties:{ name:"container-image" - value:"docker://gcr.io/tensorflow-testing/tf-rbe-win@sha256:bd22c6bfff6afc1fa4304ec4411df2410d93645494117585332a4e2258358422" + value:"docker://gcr.io/tensorflow-testing/tf-rbe-win@sha256:fbc5713566011cc27fc3651183a6e7c2fd56fc6f006618c53f8fc71e742feebd" } properties:{ name: "OSFamily" value: "Windows" diff --git a/tools/bazel.rc b/tools/bazel.rc index 8c2052ee8a..1fdf51f53e 100644 --- a/tools/bazel.rc +++ b/tools/bazel.rc @@ -72,6 +72,7 @@ build:nogcp --define=no_gcp_support=true build:nohdfs --define=no_hdfs_support=true build:nokafka --define=no_kafka_support=true build:noignite --define=no_ignite_support=true +build:nonccl --define=no_nccl_support=true build --define=use_fast_cpp_protos=true build --define=allow_oversize_protos=true -- GitLab From 9ab5ff388ea286cea990e29b5c97d6c6e000cac5 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Wed, 5 Dec 2018 10:52:12 -0600 Subject: [PATCH 0049/1765] fixed readme --- .../micro/examples/micro_speech/apollo3/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md index 967b833501..66fa176a9b 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md @@ -1,7 +1,3 @@ -# TODO - -* preprocessor_cmsis_test_bin - # Description of Apollo3 Makefile targets * **pushbutton_cmsis_speech_test_bin**: -- GitLab From 35c76cde763b7a083e147e38db89404d374b499e Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Wed, 5 Dec 2018 10:59:13 -0600 Subject: [PATCH 0050/1765] checking out upstream/master files not captured in previous merge --- .../contrib/tensorrt/convert/convert_graph.cc | 5 +- .../contrib/tensorrt/kernels/trt_engine_op.cc | 5 +- .../contrib/tensorrt/segment/segment.cc | 8 +-- tensorflow/core/kernels/mkl_avgpooling_op.cc | 35 +++++++------ tensorflow/core/kernels/mkl_conv_ops.cc | 52 +++++++++++-------- tensorflow/core/kernels/mkl_maxpooling_op.cc | 34 ++++++------ tensorflow/python/eager/pywrap_tensor.cc | 8 --- tensorflow/python/eager/tensor_test.py | 12 ----- tensorflow/python/keras/BUILD | 37 ------------- tensorflow/python/keras/integration_test.py | 9 ---- .../training/checkpointable/util_test.py | 12 ----- tensorflow/tools/docs/parser.py | 2 +- 12 files changed, 77 insertions(+), 142 deletions(-) diff --git a/tensorflow/contrib/tensorrt/convert/convert_graph.cc b/tensorflow/contrib/tensorrt/convert/convert_graph.cc index 812948bb30..3b32f72bc1 100644 --- a/tensorflow/contrib/tensorrt/convert/convert_graph.cc +++ b/tensorflow/contrib/tensorrt/convert/convert_graph.cc @@ -892,8 +892,9 @@ tensorflow::Status ConvertAfterShapes(ConversionParams& params) { TrtCandidateSelector candidate_selector(*params.graph_properties, params.precision_mode); TF_RETURN_IF_ERROR(tensorrt::segment::SegmentGraph( - &graph, std::bind(&TrtCandidateSelector::IsTensorRTCandidate, - &candidate_selector, std::placeholders::_1), + &graph, + std::bind(&TrtCandidateSelector::IsTensorRTCandidate, &candidate_selector, + std::placeholders::_1), // Input validation is already done by TrtCandidateSelector, so we don't // need to check the input edges. [](const Edge* edge) { return true; }, OutputEdgeValidator(), diff --git a/tensorflow/contrib/tensorrt/kernels/trt_engine_op.cc b/tensorflow/contrib/tensorrt/kernels/trt_engine_op.cc index a5e09f73ac..bad568644b 100644 --- a/tensorflow/contrib/tensorrt/kernels/trt_engine_op.cc +++ b/tensorflow/contrib/tensorrt/kernels/trt_engine_op.cc @@ -252,8 +252,9 @@ int TRTEngineOp::GetEngineBatch(OpKernelContext* ctx) { cached_engine_batches_.push_back(num_batch); VLOG(1) << "Running with batch size " << num_batch; } else { - string msg = StrCat("Engine buffer is full. buffer limit=", - max_cached_engines_, ", current entries="); + string msg = + StrCat("Engine buffer is full. buffer limit=", max_cached_engines_, + ", current entries="); for (auto i : cached_engine_batches_) StrAppend(&msg, i, ","); StrAppend(&msg, " requested batch=", num_batch); LOG(WARNING) << msg; diff --git a/tensorflow/contrib/tensorrt/segment/segment.cc b/tensorflow/contrib/tensorrt/segment/segment.cc index d8f63779e6..6abc5226cc 100644 --- a/tensorflow/contrib/tensorrt/segment/segment.cc +++ b/tensorflow/contrib/tensorrt/segment/segment.cc @@ -460,8 +460,7 @@ tensorflow::Status SegmentGraph( std::vector order; order.reserve(graph->num_node_ids()); StableDFS(*graph, /*reverse=*/false, {graph->source_node()}, - /*enter=*/nullptr, - [&order](const SimpleNode* n) { + /*enter=*/nullptr, [&order](const SimpleNode* n) { order.push_back(n); return true; }); @@ -570,7 +569,7 @@ tensorflow::Status SegmentGraph( std::set& segment_nodes = itr.second; VLOG(1) << "Segment original size: " << segment_nodes.size(); while (true) { - std::deque in_nodes_que, out_nodes_que; + std::deque in_nodes_que, out_nodes_que; // Find an input node that is not eligible and add it to the queue. // Nodes that has no incoming edges should not be treated as "input", // as there are really no inputs to them. Similar for output nodes. @@ -616,7 +615,8 @@ tensorflow::Status SegmentGraph( // their outputs. In this way, for common cases the number of removed // nodes should be minimum. auto remove_nodes = [&segment_nodes]( - bool is_input_nodes, std::deque* que) { + bool is_input_nodes, + std::deque* que) { // Run a BFS on the queue to find all the input/output nodes. std::set visited; std::set logged(que->begin(), que->end()); diff --git a/tensorflow/core/kernels/mkl_avgpooling_op.cc b/tensorflow/core/kernels/mkl_avgpooling_op.cc index 939cbd6f96..28825e1a9c 100644 --- a/tensorflow/core/kernels/mkl_avgpooling_op.cc +++ b/tensorflow/core/kernels/mkl_avgpooling_op.cc @@ -357,10 +357,11 @@ class MklAvgPoolingGradOp : public OpKernel { if (!outbackprop_in_mkl_format) { // For avgpooling, tensor_in_shape should have 1 dimension, and 4 // elements. - OP_REQUIRES(context, tensor_in_shape.dims() == 1 && - tensor_in_shape.NumElements() == 4, - errors::InvalidArgument("original input shape must be " - "1-dimensional and 4 elements")); + OP_REQUIRES( + context, + tensor_in_shape.dims() == 1 && tensor_in_shape.NumElements() == 4, + errors::InvalidArgument("original input shape must be " + "1-dimensional and 4 elements")); // For avgpooling, out_backprop should have 4 dimensions. OP_REQUIRES( @@ -551,9 +552,9 @@ class MklAvgPoolingOp : public MklPoolingForwardOpBase { output_max->flat()(0) = max_input; } } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + ", message: " + - string(e.message) + ", in file " + string(__FILE__) + - ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + + ", message: " + string(e.message) + ", in file " + + string(__FILE__) + ":" + std::to_string(__LINE__); OP_REQUIRES_OK( context, errors::Aborted("Operation received an exception:", error_msg)); @@ -653,9 +654,9 @@ class MklAvgPoolingGradOp : public MklPoolingBackwardOpBase { // execute pooling op pooling_bwd->Execute(diff_dst_data, diff_src_data); } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + ", message: " + - string(e.message) + ", in file " + string(__FILE__) + - ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + + ", message: " + string(e.message) + ", in file " + + string(__FILE__) + ":" + std::to_string(__LINE__); OP_REQUIRES_OK(context, errors::Aborted("Compute received an exception:", error_msg)); } @@ -674,13 +675,15 @@ class MklAvgPoolingGradOp : public MklPoolingBackwardOpBase { const MklDnnShape& original_input_mkl_shape, const MklDnnShape& input_gradient_mkl_shape) { if (!original_input_mkl_shape.IsMklTensor()) { - OP_REQUIRES(context, tensor_in_shape.dims() == 1 && - tensor_in_shape.NumElements() == 4, - errors::InvalidArgument("original input shape must be " - "1-dimensional and 4 elements")); + OP_REQUIRES( + context, + tensor_in_shape.dims() == 1 && tensor_in_shape.NumElements() == 4, + errors::InvalidArgument("original input shape must be " + "1-dimensional and 4 elements")); } else { - OP_REQUIRES(context, original_input_mkl_shape.GetDimension() == 1 && - original_input_mkl_shape.DimSize(0) == 4, + OP_REQUIRES(context, + original_input_mkl_shape.GetDimension() == 1 && + original_input_mkl_shape.DimSize(0) == 4, errors::InvalidArgument("original input shape must be " "1-dimensional and 4 elements")); } diff --git a/tensorflow/core/kernels/mkl_conv_ops.cc b/tensorflow/core/kernels/mkl_conv_ops.cc index 75f08956b4..4b0ced3340 100644 --- a/tensorflow/core/kernels/mkl_conv_ops.cc +++ b/tensorflow/core/kernels/mkl_conv_ops.cc @@ -465,18 +465,19 @@ class MklConvOp : public OpKernel { filter.shape().DebugString())); for (int i = 0; i < 3; i++) { - OP_REQUIRES(context, FastBoundsCheck(filter.dim_size(i), - std::numeric_limits::max()), - errors::InvalidArgument("filter too large")); + OP_REQUIRES( + context, + FastBoundsCheck(filter.dim_size(i), std::numeric_limits::max()), + errors::InvalidArgument("filter too large")); } const int64 input_depth = input_in_mkl_format ? GetMklTensorDim(mkl_context.input_shape, 'C') : GetTensorDim(input, data_format_, 'C'); - OP_REQUIRES( - context, input_depth == filter.dim_size(2), - errors::InvalidArgument("input and filter must have the same depth: ", - input_depth, " vs ", filter.dim_size(2))); + OP_REQUIRES(context, input_depth == filter.dim_size(2), + errors::InvalidArgument( + "input and filter must have the same depth: ", input_depth, + " vs ", filter.dim_size(2))); // The last dimension for filter is out_depth. const int out_depth = static_cast(filter.dim_size(3)); @@ -485,9 +486,10 @@ class MklConvOp : public OpKernel { const int64 input_rows_raw = input_in_mkl_format ? GetMklTensorDim(mkl_context.input_shape, 'H') : GetTensorDim(input, data_format_, 'H'); - OP_REQUIRES(context, FastBoundsCheck(input_rows_raw, - std::numeric_limits::max()), - errors::InvalidArgument("Input rows too large")); + OP_REQUIRES( + context, + FastBoundsCheck(input_rows_raw, std::numeric_limits::max()), + errors::InvalidArgument("Input rows too large")); const int input_rows = static_cast(input_rows_raw); const int filter_rows = static_cast(filter.dim_size(0)); @@ -496,9 +498,10 @@ class MklConvOp : public OpKernel { const int64 input_cols_raw = input_in_mkl_format ? GetMklTensorDim(mkl_context.input_shape, 'W') : GetTensorDim(input, data_format_, 'W'); - OP_REQUIRES(context, FastBoundsCheck(input_cols_raw, - std::numeric_limits::max()), - errors::InvalidArgument("Input cols too large")); + OP_REQUIRES( + context, + FastBoundsCheck(input_cols_raw, std::numeric_limits::max()), + errors::InvalidArgument("Input cols too large")); const int input_cols = static_cast(input_cols_raw); const int filter_cols = static_cast(filter.dim_size(1)); @@ -506,9 +509,10 @@ class MklConvOp : public OpKernel { const int64 input_batch_raw = input_in_mkl_format ? GetMklTensorDim(mkl_context.input_shape, 'N') : GetTensorDim(input, data_format_, 'N'); - OP_REQUIRES(context, FastBoundsCheck(input_batch_raw, - std::numeric_limits::max()), - errors::InvalidArgument("batch is too large")); + OP_REQUIRES( + context, + FastBoundsCheck(input_batch_raw, std::numeric_limits::max()), + errors::InvalidArgument("batch is too large")); const int batch = static_cast(input_batch_raw); // For now we take the stride from the second and third dimensions only (we @@ -889,15 +893,17 @@ class MklConvOp : public OpKernel { OP_REQUIRES(context, dilations_.size() == 5, errors::InvalidArgument("Dilation rates field must " "specify 5 dimensions")); - OP_REQUIRES(context, (GetTensorDim(dilations_, data_format_, 'N') == 1 && - GetTensorDim(dilations_, data_format_, 'C') == 1), + OP_REQUIRES(context, + (GetTensorDim(dilations_, data_format_, 'N') == 1 && + GetTensorDim(dilations_, data_format_, 'C') == 1), errors::InvalidArgument( "Current implementation does not yet support " "dilations rates in the batch and depth dimensions.")); OP_REQUIRES( - context, (GetTensorDim(dilations_, data_format_, '0') > 0 && - GetTensorDim(dilations_, data_format_, '1') > 0 && - GetTensorDim(dilations_, data_format_, '2') > 0), + context, + (GetTensorDim(dilations_, data_format_, '0') > 0 && + GetTensorDim(dilations_, data_format_, '1') > 0 && + GetTensorDim(dilations_, data_format_, '2') > 0), errors::InvalidArgument("Dilated rates should be larger than 0.")); } } @@ -1533,8 +1539,8 @@ class MklQuantizedConv2DSumReluOp const float max_filter = context->input(5 + bias_index_offset).flat()(0); - reorder_sum_scale = - 255.0 * 127.0 / (std::max(std::abs(max_input), std::abs(min_input)) * + reorder_sum_scale = 255.0 * 127.0 / + (std::max(std::abs(max_input), std::abs(min_input)) * std::max(std::abs(max_filter), std::abs(min_filter))); std::vector scales; scales.push_back(reorder_sum_scale); diff --git a/tensorflow/core/kernels/mkl_maxpooling_op.cc b/tensorflow/core/kernels/mkl_maxpooling_op.cc index 0697251c7d..cb494f6c3e 100644 --- a/tensorflow/core/kernels/mkl_maxpooling_op.cc +++ b/tensorflow/core/kernels/mkl_maxpooling_op.cc @@ -399,18 +399,19 @@ class MklMaxPoolingGradOp : public OpKernel { if (workspace_enabled == false) { if (convert_input != nullptr) { if (input_in_mkl_format == false) { - CHECK_EQ( - dnnConversionExecute_F32( - convert_input, const_cast(static_cast( - tensor_in.flat().data())), - input_buf), - E_SUCCESS); + CHECK_EQ(dnnConversionExecute_F32( + convert_input, + const_cast(static_cast( + tensor_in.flat().data())), + input_buf), + E_SUCCESS); CHECK_EQ(dnnDelete_F32(convert_input), E_SUCCESS); convert_input = nullptr; } else { input_shape.GetConvertedFlatData( - lt_input_prim, const_cast(static_cast( - tensor_in.flat().data())), + lt_input_prim, + const_cast( + static_cast(tensor_in.flat().data())), input_buf); } pooling_resfwd[dnnResourceSrc] = input_buf; @@ -455,8 +456,9 @@ class MklMaxPoolingGradOp : public OpKernel { CHECK_EQ(dnnDelete_F32(convert_outbackprop), E_SUCCESS); } else { output_backprop_shape.GetConvertedFlatData( - lt_outbackprop_prim, const_cast(static_cast( - out_backprop.flat().data())), + lt_outbackprop_prim, + const_cast( + static_cast(out_backprop.flat().data())), outbackprop_buf); } pooling_res[dnnResourceDiffDst] = outbackprop_buf; @@ -637,9 +639,9 @@ class MklMaxPoolingOp : public MklPoolingForwardOpBase { pooling_fwd->Execute(src_data, dst_data, ws_data); } } catch (mkldnn::error& e) { - string error_msg = "Status: " + std::to_string(e.status) + ", message: " + - string(e.message) + ", in file " + string(__FILE__) + - ":" + std::to_string(__LINE__); + string error_msg = "Status: " + std::to_string(e.status) + + ", message: " + string(e.message) + ", in file " + + string(__FILE__) + ":" + std::to_string(__LINE__); OP_REQUIRES_OK(context, errors::Aborted("Compute received an exception:", error_msg)); } @@ -781,9 +783,9 @@ class MklMaxPoolingGradOp : public MklPoolingBackwardOpBase { // execute pooling pooling_bwd->Execute(diff_dst_data, diff_src_data, ws_data); } catch (mkldnn::error& e) { - string error_msg = "Status:" + std::to_string(e.status) + ", message: " + - string(e.message) + ". in file " + string(__FILE__) + - ":" + std::to_string(__LINE__); + string error_msg = "Status:" + std::to_string(e.status) + + ", message: " + string(e.message) + ". in file " + + string(__FILE__) + ":" + std::to_string(__LINE__); OP_REQUIRES_OK(context, errors::Aborted("Compute received an exception:", error_msg)); } diff --git a/tensorflow/python/eager/pywrap_tensor.cc b/tensorflow/python/eager/pywrap_tensor.cc index 206b96eef6..0d0f70d543 100644 --- a/tensorflow/python/eager/pywrap_tensor.cc +++ b/tensorflow/python/eager/pywrap_tensor.cc @@ -220,14 +220,6 @@ TFE_TensorHandle* ConvertToEagerTensor(PyObject* value, PyObject* dtype) { return nullptr; } } - tensorflow::Safe_PyObjectPtr value_decrefer; - if (PyArray_CheckAnyScalarExact(value)) { - // Convert numpy scalars to numpy arrays. - value = PyArray_FromScalar(value, nullptr); - // The returned value needs to be DECREF'd, but the original value was - // created in python code, and doesn't need to be DECREF'd. - value_decrefer.reset(value); - } if (PyArray_Check(value)) { int desired_np_dtype = -1; if (desired_dtype >= 0) { diff --git a/tensorflow/python/eager/tensor_test.py b/tensorflow/python/eager/tensor_test.py index 0ee2ff68c2..25442ff048 100644 --- a/tensorflow/python/eager/tensor_test.py +++ b/tensorflow/python/eager/tensor_test.py @@ -95,18 +95,6 @@ class TFETensorTest(test_util.TensorFlowTestCase): t = _create_tensor(values) self.assertAllEqual(values, t) - @test_util.assert_no_new_pyobjects_executing_eagerly - def testNumpyDtypeSurvivesThroughTensorConversion(self): - scalar_creators = [np.int32, np.int64, np.float32, np.float64] - conversion_functions = [ops.convert_to_tensor, constant_op.constant] - - for scalar_creator in scalar_creators: - for conversion_function in conversion_functions: - np_val = scalar_creator(3) - tensor_val = conversion_function(np_val) - self.assertEqual(tensor_val.numpy().dtype, np_val.dtype) - self.assertEqual(tensor_val.numpy(), np_val) - def testNumpyValueWithCast(self): values = np.array([3.0], dtype=np.float32) t = _create_tensor(values, dtype=dtypes.float64) diff --git a/tensorflow/python/keras/BUILD b/tensorflow/python/keras/BUILD index 3a27f75f4a..602cf79362 100755 --- a/tensorflow/python/keras/BUILD +++ b/tensorflow/python/keras/BUILD @@ -548,19 +548,6 @@ cuda_py_test( shard_count = 4, ) -cuda_py_test( - name = "unified_lstm_test", - size = "medium", - srcs = ["layers/unified_lstm_test.py"], - additional_deps = [ - ":keras", - "@absl_py//absl/testing:parameterized", - "//third_party/py/numpy", - "//tensorflow/python:client_testlib", - ], - shard_count = 4, -) - py_test( name = "serialization_test", size = "small", @@ -648,17 +635,6 @@ py_test( ], ) -py_test( - name = "tf_utils_test", - size = "small", - srcs = ["utils/tf_utils_test.py"], - srcs_version = "PY2AND3", - deps = [ - ":keras", - "//tensorflow/python:client_testlib", - ], -) - py_test( name = "io_utils_test", size = "small", @@ -811,19 +787,6 @@ py_test( ], ) -py_test( - name = "training_dataset_test", - size = "medium", - srcs = ["engine/training_dataset_test.py"], - srcs_version = "PY2AND3", - deps = [ - ":keras", - "//tensorflow/python:client_testlib", - "//third_party/py/numpy", - "@absl_py//absl/testing:parameterized", - ], -) - py_test( name = "training_generator_test", size = "enormous", diff --git a/tensorflow/python/keras/integration_test.py b/tensorflow/python/keras/integration_test.py index 23f5438505..f1a0932613 100644 --- a/tensorflow/python/keras/integration_test.py +++ b/tensorflow/python/keras/integration_test.py @@ -320,15 +320,6 @@ class KerasIntegrationTest(test.TestCase): verbose=0) self.assertGreater(history.history['val_acc'][-1], 0.7) - def test_regularizers_with_get_variable(self): - # Test case for GitHub issue 22470. - with self.cached_session(): - v = variable_scope.get_variable( - "v", - shape=[4, 4], - initializer=keras.initializers.glorot_uniform(), - regularizer=keras.regularizers.l2(0.)) - if __name__ == '__main__': test.main() diff --git a/tensorflow/python/training/checkpointable/util_test.py b/tensorflow/python/training/checkpointable/util_test.py index de9cac0863..78047eda90 100644 --- a/tensorflow/python/training/checkpointable/util_test.py +++ b/tensorflow/python/training/checkpointable/util_test.py @@ -44,7 +44,6 @@ from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables from tensorflow.python.training import adam from tensorflow.python.training import checkpoint_management -from tensorflow.python.training import momentum from tensorflow.python.training import saver as saver_lib from tensorflow.python.training import training_util from tensorflow.python.training.checkpointable import base @@ -199,17 +198,6 @@ class InterfaceTests(test.TestCase): with self.assertRaises(NotImplementedError): checkpoint_reversed.save(prefix) - @test_util.run_in_graph_and_eager_modes(assert_no_eager_garbage=True) - def test_object_graph_no_attributes(self): - root = tracking.Checkpointable() - root.v = resource_variable_ops.ResourceVariable(1.) - root.opt = momentum.MomentumOptimizer(0.01, 0.5) - root.opt.minimize(root.v.read_value) - object_graph = checkpointable_utils.make_object_graph_without_attributes( - root) - # Four objects: Root, v, opt, and a slot variable for v - self.assertEqual(4, len(object_graph.nodes)) - class _MirroringSaveable(saver_lib.BaseSaverBuilder.SaveableObject): diff --git a/tensorflow/tools/docs/parser.py b/tensorflow/tools/docs/parser.py index 6dc18ee8dc..83b4bf8128 100644 --- a/tensorflow/tools/docs/parser.py +++ b/tensorflow/tools/docs/parser.py @@ -39,7 +39,7 @@ def is_free_function(py_object, full_name, index): """Check if input is a free function (and not a class- or static method). Args: - py_object: The object in question. + py_object: The the object in question. full_name: The full name of the object, like `tf.module.symbol`. index: The {full_name:py_object} dictionary for the public API. -- GitLab From c506f4befdde4fbb1259bbf326336aa74f835191 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Wed, 5 Dec 2018 11:54:44 -0600 Subject: [PATCH 0051/1765] prep for pull request --- .../micro/examples/micro_speech/preprocessor_test.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc index d9b0c48ba3..e8b49f67e3 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc @@ -22,7 +22,6 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/testing/micro_test.h" - TF_LITE_MICRO_TESTS_BEGIN TF_LITE_MICRO_TEST(TestPreprocessor) { -- GitLab From bb804ddf78cd7583e6dad16e93611a73f40a3a2e Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Wed, 5 Dec 2018 12:00:48 -0600 Subject: [PATCH 0052/1765] prep for pull request --- tensorflow/lite/experimental/micro/tools/make/Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/Makefile b/tensorflow/lite/experimental/micro/tools/make/Makefile index 3f6f927358..30a51899e5 100644 --- a/tensorflow/lite/experimental/micro/tools/make/Makefile +++ b/tensorflow/lite/experimental/micro/tools/make/Makefile @@ -77,9 +77,7 @@ tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.cc \ tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_waveform.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc +tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc PREPROCESSOR_REFERENCE_TEST_SRCS = \ $(PREPROCESSOR_TEST_SRCS) \ -- GitLab From ed17f60a544e31ba79a649d1decafd29887fd6d9 Mon Sep 17 00:00:00 2001 From: manhyuk Date: Thu, 6 Dec 2018 15:47:30 +0900 Subject: [PATCH 0053/1765] fix typo --- tensorflow/compiler/xla/shape_util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/compiler/xla/shape_util.h b/tensorflow/compiler/xla/shape_util.h index 84a27f662a..30bf1dfb03 100644 --- a/tensorflow/compiler/xla/shape_util.h +++ b/tensorflow/compiler/xla/shape_util.h @@ -266,7 +266,7 @@ class ShapeUtil { } // Returns the higher-precision element type if a and b are both floating - // point types; otherwise, checks that that they have the same element type + // point types; otherwise, checks that they have the same element type // and returns it. static PrimitiveType HigherPrecisionElementType(const Shape& a, const Shape& b) { -- GitLab From aec214bc3870ecc0f5f831c2523a1609d8c12871 Mon Sep 17 00:00:00 2001 From: manhyuk Date: Thu, 6 Dec 2018 15:48:47 +0900 Subject: [PATCH 0054/1765] fix typo --- tensorflow/python/kernel_tests/cond_v2_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/python/kernel_tests/cond_v2_test.py b/tensorflow/python/kernel_tests/cond_v2_test.py index 843d007cc8..502d504bfe 100644 --- a/tensorflow/python/kernel_tests/cond_v2_test.py +++ b/tensorflow/python/kernel_tests/cond_v2_test.py @@ -1036,7 +1036,7 @@ class CondV2ColocationGroupAndDeviceTest(test.TestCase): self.evaluate(cond_v2.cond_v2(constant_op.constant(True), fn2, fn2))) else: - self.skipTest("Test requrires a GPU to check GPU device placement.") + self.skipTest("Test requires a GPU to check GPU device placement.") def testDeviceInAndOutOfCond(self): with ops.Graph().as_default() as g: -- GitLab From d14f39054f44d0a641db3a0997fe5d720918cd07 Mon Sep 17 00:00:00 2001 From: manhyuk Date: Thu, 6 Dec 2018 15:50:58 +0900 Subject: [PATCH 0055/1765] fix typo --- tensorflow/contrib/cmake/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/contrib/cmake/README.md b/tensorflow/contrib/cmake/README.md index df8b48dfc4..b2badc5785 100644 --- a/tensorflow/contrib/cmake/README.md +++ b/tensorflow/contrib/cmake/README.md @@ -157,7 +157,7 @@ suitable interface for project configuration and dependency setting. press `Finish`. Wait for a moment, the default project dependecy would automatically generate. 6. There are a few options that you can customize your own build. **The setting - here is crucial for a sucessful build, please check all items carefully.** + here is crucial for a successful build, please check all items carefully.** * `tensorflow_BUILD_ALL_KERNELS` should alway be `on` * `tensorflow_BUILD_CC_EXAMPLE` is default to be `on`. This can help you -- GitLab From 562b078b836b215b761fc91a177937cfcbdd0ea0 Mon Sep 17 00:00:00 2001 From: Nayana-ibm Date: Thu, 6 Dec 2018 11:13:12 -0500 Subject: [PATCH 0056/1765] resolve ImportError: cannot import name cloud on s390x - skip import clound --- tensorflow/contrib/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tensorflow/contrib/__init__.py b/tensorflow/contrib/__init__.py index 4f1a2a5693..a23e331f4f 100644 --- a/tensorflow/contrib/__init__.py +++ b/tensorflow/contrib/__init__.py @@ -20,13 +20,14 @@ from __future__ import division from __future__ import print_function import os +import platform # Add projects here, they will show up under tf.contrib. from tensorflow.contrib import autograph from tensorflow.contrib import batching from tensorflow.contrib import bayesflow from tensorflow.contrib import checkpoint -if os.name != "nt": +if os.name != "nt" and platform.machine() != "s390x": from tensorflow.contrib import cloud from tensorflow.contrib import cluster_resolver from tensorflow.contrib import coder -- GitLab From 5a2d4b053ed368c713e83121c73bd251e85300b9 Mon Sep 17 00:00:00 2001 From: Steve Nesae Date: Thu, 6 Dec 2018 14:59:10 -0600 Subject: [PATCH 0057/1765] Added pushbutton sources to makefile --- .../experimental/micro/tools/make/Makefile | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tensorflow/lite/experimental/micro/tools/make/Makefile b/tensorflow/lite/experimental/micro/tools/make/Makefile index 30a51899e5..63bbdc84ba 100644 --- a/tensorflow/lite/experimental/micro/tools/make/Makefile +++ b/tensorflow/lite/experimental/micro/tools/make/Makefile @@ -115,6 +115,8 @@ include $(wildcard $(MAKEFILE_DIR)/targets/*_makefile.inc) ALL_SRCS := \ $(MICRO_SPEECH_TEST_SRCS) \ + $(PUSHBUTTON_MICRO_SPEECH_TEST_SRCS) \ + $(PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS) \ $(PREPROCESSOR_REFERENCE_TEST_SRCS) \ $(PREPROCESSOR_FIXED_TEST_SRCS) \ $(MICROLITE_CC_SRCS) \ @@ -145,6 +147,13 @@ AR := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}ar MICRO_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(MICRO_SPEECH_TEST_SRCS)))) +PUSHBUTTON_MICRO_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ +$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PUSHBUTTON_MICRO_SPEECH_TEST_SRCS)))) + +PUSHBUTTON_CMSIS_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ +$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS))) \ +arm_bitreversal2.o) + PREPROCESSOR_REFERENCE_TEST_OBJS := $(addprefix $(OBJDIR), \ $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_REFERENCE_TEST_SRCS)))) @@ -200,6 +209,31 @@ micro_speech_test_bin: $(MICRO_SPEECH_TEST_BINARY).bin test_micro_speech: $(MICRO_SPEECH_TEST_BINARY) $(TEST_SCRIPT) $(MICRO_SPEECH_TEST_BINARY) '~~~ALL TESTS PASSED~~~' +$(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY): $(PUSHBUTTON_MICRO_SPEECH_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) $(PUSHBUTTON_MICRO_SPEECH_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + +pushbutton_micro_speech_test: $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) +pushbutton_micro_speech_test_bin: $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY).bin + +test_pushbutton_micro_speech: $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) + $(TEST_SCRIPT) $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + + +$(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY): $(PUSHBUTTON_CMSIS_SPEECH_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) $(PUSHBUTTON_CMSIS_SPEECH_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + +pushbutton_cmsis_speech_test: $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) +pushbutton_cmsis_speech_test_bin: $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY).bin + +test_pushbutton_cmsis_speech: $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) + $(TEST_SCRIPT) $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + $(PREPROCESSOR_REFERENCE_TEST_BINARY): $(PREPROCESSOR_REFERENCE_TEST_OBJS) $(MICROLITE_LIB_PATH) @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $(INCLUDES) \ -- GitLab From fc19d28247a87dbce66993e2effd2e9d0ac3652d Mon Sep 17 00:00:00 2001 From: hari Date: Fri, 7 Dec 2018 10:38:01 -0800 Subject: [PATCH 0058/1765] New files for Tensorflow Lite Micro Speech Example targetting the Eta Compute ECM3531 evaluation board --- .../micro/testing/test_ecm3531_binary.sh | 1 + .../tools/make/targets/ecm3531/README.txt | 32 + .../micro/tools/make/targets/ecm3531/_main.c | 97 +++ .../tools/make/targets/ecm3531/ecm3531.lds | 88 +++ .../tools/make/targets/ecm3531/load_program | 35 ++ .../tools/make/targets/ecm3531/startup.c | 592 ++++++++++++++++++ .../tools/make/targets/ecm3531_makefile.inc | 103 +++ 7 files changed, 948 insertions(+) create mode 100755 tensorflow/lite/experimental/micro/testing/test_ecm3531_binary.sh create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/README.txt create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/_main.c create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/ecm3531.lds create mode 100755 tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/load_program create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/ecm3531_makefile.inc diff --git a/tensorflow/lite/experimental/micro/testing/test_ecm3531_binary.sh b/tensorflow/lite/experimental/micro/testing/test_ecm3531_binary.sh new file mode 100755 index 0000000000..6d7af08d9f --- /dev/null +++ b/tensorflow/lite/experimental/micro/testing/test_ecm3531_binary.sh @@ -0,0 +1 @@ +echo "Testing should be performed on the ECM3531 EVB" diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/README.txt b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/README.txt new file mode 100644 index 0000000000..655340ceff --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/README.txt @@ -0,0 +1,32 @@ +Running The Micro Speech Example On Eta Compute's ECM3531EVB + +This code will enable you to compile and execute the Tensorflow Lite Micro Speech Example on Eta Computes's low power ECM3531 chip. + + +GETTING STARTED: + +1. Download the Tensorflow code from Github and follow anyinstructions there to download other dependencies. + +2. Download the Eta Compute SDK, version 0.0.17. + +3. Install the Arm compiler arm-none-eabi-gcc, version = arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2018-q2-update) 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907] + +4. Edit the file tensorflow/lite/experimental/micro/tools/make/targets/ecm3531_makefile.inc so that the variable ETA_SDK points to the location where the Eta Compute SDK is installed, and the variable GCC_ARM points to the Arm compiler. + +5. Compile the code with the command "make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=ecm3531 test". This will create the executable tensorflow/lite/experimental/micro/tools/make/gen/ecm3531_cortex-m3/bin/micro_speech_test. + +6. Connect the board to the host computer, start PuTTY (Connection type = Serial, Speed = 11520, Data bits = 8, Stop bits = 1, Parity = None), and load the executable with ocd. A sample script for loading the image is provided in tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/load_program. + +The following will be printed on the Uart: + +Testing TestInvoke +Ran successfully + +/ tests passed +~~~ALL TESTS PASSED~~~ + + + +CONTACT INFORMATION: + +Contact info@etacompute.com for more information on obtaining the Eta Compute SDK and evalution board. diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/_main.c b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/_main.c new file mode 100644 index 0000000000..5a595c26b3 --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/_main.c @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (C) 2018 Eta Compute, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include +#include +#include "eta_chip.h" +#include "eta_csp.h" +#include "eta_csp_uart.h" +#include "eta_csp_gpio.h" +#include "eta_csp_io.h" +#include "eta_csp_timer.h" +#include "eta_csp_socctrl.h" +#include "eta_csp_buck.h" +#include "eta_csp_rtc.h" +#include "eta_csp_sys_clock.h" +#include +#include "eta_bsp.h" +#include "eta_csp_pwr.h" +#include + + +tUart g_sUart0 = {eUartNum0, eUartBaud115200}; +tUart g_sUart1 = {eUartNum1, eUartBaud115200}; + +int init_main(int); +void EtaPrintExecutionTime(uint64_t); + + +//***************************************************************************** +// +// The entry point for the application. +// +//***************************************************************************** +extern int main(int argc, char**argv); + +void DebugLog(const char* s) { EtaCspIoPrintf( "%s", s); } +void DebugLogInt32(int32_t i) { EtaCspIoPrintf( "%d", i); } +void DebugLogUInt32(uint32_t i) { EtaCspIoPrintf( "%d", i); } +void DebugLogHex(uint32_t i) { EtaCspIoPrintf( "0x%8x", i); } +void DebugLogFloat(float i) { EtaCspIoPrintf( "%f", i); } + + +int _main(void) +{ + uint64_t time_ms; + + EtaCspInit(); //initialize csp registers + EtaCspGpioInit(); //initialize gpios + EtaCspUartInit(&g_sUart1, eUartNum0, eUartBaud115200, eUartFlowControlHardware); //initialize Uart + EtaCspBuckInit(ETA_BSP_VDD_IO_SETTING, eBuckAo600Mv, eBuckM3Frequency60Mhz, eBuckMemVoltage900Mv);//set M3 freq + EtaCspTimerInitMs(); //start timer + main(0, NULL); //Call to Tensorflow; this will print if test was successful. + time_ms = EtaCspTimerCountGetMs(); //read time + EtaPrintExecutionTime(time_ms); //print execution time + +} + + + +void EtaPrintExecutionTime(uint64_t time_ms) +{ + uint8_t c; + int k1; + char time_string[] = "00000"; + + EtaCspIoPrintf("Execution time (msec) = "); + if (time_ms < 100000) //Convert time to a string + { + for(k1 = 0; k1 < 5; k1++){ + c = time_ms % 10; + time_ms = time_ms/10; + time_string[k1] = (char)(0x30 + c); + } + for(k1 = 4; k1 > 0; k1--) { //print out 1 char at a time + EtaCspUartPutc(&g_sUart1, time_string[k1]); + } + } + else{ + EtaCspIoPrintf("Execution time exceeds 100 sec\n"); + } + EtaCspIoPrintf("\n\n"); + +} diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/ecm3531.lds b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/ecm3531.lds new file mode 100644 index 0000000000..2c77ebcc1d --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/ecm3531.lds @@ -0,0 +1,88 @@ +/******************************************************************************* + * + * Copyright (C) 2018 Eta Compute, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + + +/* + * linker script for use with ECM3531 + * All sections must map to 128KBytes of SRAM beginning at 0x10000000 + * + */ + + /* + * Indicate to the linker the entry point. + */ +ENTRY(ResetISR) + +/* + * SRAM is at 0x10000000 of length 0x00020000 + */ +MEMORY +{ + SRAM (RWX) : ORIGIN = 0x10000000, LENGTH = 0x00020000 +} + +SECTIONS +{ + .text : + { + _text = .; + KEEP(*(.vectors)) + . = ALIGN(0x4); + *(.text*) + . = ALIGN(0x4); + *(.rodata*) + . = ALIGN(0x4); + _etext = .; + } > SRAM= 0 + .dummy : + { + . = ALIGN(0x4); + _eftext = .; + } > SRAM + .datax : + { + _datax = .; + KEEP(*(.mainStack)) + . += 12288; + _edatax = .; + _stack_top = .; + . += 4; + } > SRAM + .data : + AT (ADDR(.text) + SIZEOF(.text) ) + { + _data = .; + *(.data*) + KEEP(*(.mainHeap)) + _edata = .; + } > SRAM + + .bss : + { + _bss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > SRAM + .ARM.exidx : + { + *(.ARM.exidx*) + } + +} + diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/load_program b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/load_program new file mode 100755 index 0000000000..5d4974ba6e --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/load_program @@ -0,0 +1,35 @@ +#!/usr/bin/python3 + +import os +import telnetlib + +def send_ocd_cmd(line): + ocd_sock.write(bytes(line,encoding = 'utf-8')) + print(ocd_sock.read_until(b'> ').decode('utf-8'), end='') + +def get_ocd_response(): + print(ocd_sock.read_until(b'> ').decode('utf-8'), end='') + +#get hooked up to openocd daemon +ocd_sock = telnetlib.Telnet(host='localhost', port=4444) +get_ocd_response() # clean it out + +# git path to project elf file +cur_dir = os.getcwd() +elf_file = cur_dir + '/../../gen/ecm3531_cortex-m3/bin/' + 'micro_speech_test' +print("elf_file = ",elf_file) + + +# use these to download and run the elf fle +ocd_commands = ["halt\n", + "load_image {}\n".format(elf_file), + "mww 0x1001FFF8 0xDEADBEEF\n", + "mww 0x1001FFFC 0xC369A517\n", + "reset\n"] + +# OK now do what we came here for!!! +for x in ocd_commands: + print(x) + send_ocd_cmd(x) + + diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c new file mode 100644 index 0000000000..da9f7a4b0e --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c @@ -0,0 +1,592 @@ +/******************************************************************************* + * + * Copyright (C) 2018 Eta Compute, Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include +#include "eta_chip.h" +#include "memio.h" + + +//#pragma GCC optimize ("align-functions=16") + + +#ifndef NULL +#define NULL (0) +#endif + + +//***************************************************************************** +// +// Macro for hardware access, both direct and via the bit-band region. +// +//***************************************************************************** + +#define NAKED +//#define NAKED __attribute__((naked)) + +int _main(int argc, char *argv[]); +void set_vtor(void); +void * startup_get_my_pc(void); + +//***************************************************************************** +// Forward DECLS for interrupt service routines (ISR) +//***************************************************************************** +extern void ResetISR(void) __attribute__((weak, alias("default_ResetISR"))); +extern void NmiSR(void) __attribute__((weak, alias("default_NmiSR"))); +extern void FaultISR(void) __attribute__((weak, alias("default_FaultISR"))); + +extern void DebugMonitor_ISR(void) __attribute__((weak, alias("default_DebugMonitor_ISR"))); +extern void SVCall_ISR(void) __attribute__((weak, alias("default_SVCall_ISR"))); +extern void PENDSV_ISR(void) __attribute__((weak, alias("default_PENDSV_ISR"))); + +extern void SYSTICK_ISR(void) __attribute__((weak, alias("default_SYSTICK_ISR"))); + +extern void GPIO0_ISR(void) __attribute__((weak, alias("default_GPIO0_ISR"))); +extern void GPIO1_ISR(void) __attribute__((weak, alias("default_GPIO1_ISR"))); +extern void TIMER0_ISR(void) __attribute__((weak, alias("default_TIMER0_ISR"))); +extern void TIMER1_ISR(void) __attribute__((weak, alias("default_TIMER1_ISR"))); +extern void UART0_ISR(void) __attribute__((weak, alias("default_UART0_ISR"))); +extern void UART1_ISR(void) __attribute__((weak, alias("default_UART1_ISR"))); +extern void SPI0_ISR(void) __attribute__((weak, alias("default_SPI0_ISR"))); +extern void SPI1_ISR(void) __attribute__((weak, alias("default_SPI1_ISR"))); +extern void I2C0_ISR(void) __attribute__((weak, alias("default_I2C0_ISR"))); +extern void I2C1_ISR(void) __attribute__((weak, alias("default_I2C1_ISR"))); +extern void RTC0_ISR(void) __attribute__((weak, alias("default_RTC0_ISR"))); +extern void RTC1_ISR(void) __attribute__((weak, alias("default_RTC1_ISR"))); +extern void DSP_ISR(void) __attribute__((weak, alias("default_DSP_ISR"))); +extern void ADC_ISR(void) __attribute__((weak, alias("default_ADC_ISR"))); +extern void SW0_ISR(void) __attribute__((weak, alias("default_SW0_ISR"))); +extern void SW1_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void PWM_ISR(void) __attribute__((weak, alias("default_PWM_ISR"))); +extern void WDT_ISR(void) __attribute__((weak, alias("default_WDT_ISR"))); +extern void RTC_TMR_ISR(void) __attribute__((weak, alias("default_RTC_TMR_ISR"))); + + +extern void SW2_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void SW3_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void SW4_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void SW5_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void SW6_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); + + +extern void IntDefaultHandler(void) __attribute__((weak)) NAKED; + +//***************************************************************************** +// +// Reserve space for the system stack. +// +//***************************************************************************** +extern uint32_t _stack_top; +//__attribute__ ((section(".mainStack"), used)) +//static uint32_t pui32Stack[2048]; +#define STARTUP_STACK_TOP (&_stack_top) + + + +//***************************************************************************** +// VECTOR TABLE +//***************************************************************************** +__attribute__ ((section(".vectors"), used)) +void (* const gVectors[])(void) = +{ + //(void (*)(void))((uint32_t)pui32Stack + sizeof(pui32Stack)), // Stack pointer + (void *)STARTUP_STACK_TOP, + ResetISR, // Reset handler + NmiSR, // The NMI handler + FaultISR, // The hard fault handler + IntDefaultHandler, // 4 The MPU fault handler + IntDefaultHandler, // 5 The bus fault handler + IntDefaultHandler, // 6 The usage fault handler + 0, // 7 Reserved + 0, // 8 Reserved + 0, // 9 Reserved + 0, // 10 Reserved + SVCall_ISR, // 11 SVCall handler + DebugMonitor_ISR, // 12 Debug monitor handler + 0, // 13 Reserved + PENDSV_ISR, // 14 The PendSV handler + SYSTICK_ISR, // 15 The SysTick handler + + // external interrupt service routines (ISR) + GPIO0_ISR, // 16 GPIO Port A [ 0] + GPIO1_ISR, // 17 GPIO Port B [ 1] + TIMER0_ISR, // 18 Timer 0 [ 2] + TIMER1_ISR, // 19 Timer 1 [ 3] + UART0_ISR, // 20 UART 0 [ 4] + UART1_ISR, // 21 UART 1 [ 5] + SPI0_ISR, // 22 SPI0 [ 6] + SPI1_ISR, // 23 SPI1 [ 7] + I2C0_ISR, // 24 I2C 0 [ 8] + I2C1_ISR, // 25 I2C 1 [ 9] + RTC0_ISR, // 26 RTC 0 [10] + RTC1_ISR, // 27 RTC 1 [11] + DSP_ISR, // 28 DSP MAILBOX [12] + ADC_ISR, // 29 ADC [13] + PWM_ISR, // 32 PWM [14] + WDT_ISR, // 33 WDT [15] + RTC_TMR_ISR, // 34 RTC [16] + + SW0_ISR, // 30 Software Interrupt 0 [17] + SW1_ISR, // 31 Software Interrupt 1 [18] + SW2_ISR, // 35 Software Interrupt 2 [19] + SW3_ISR, // 36 Software Interrupt 3 [20] + SW4_ISR, // 37 Software Interrupt 4 [21] + SW5_ISR, // 38 Software Interrupt 5 [22] + SW6_ISR, // 39 Software Interrupt 6 [23] + + + +}; + +//***************************************************************************** +// +// The following are constructs created by the linker, indicating where the +// the "data" and "bss" segments reside in memory. The initializers for the +// for the "data" segment resides immediately following the "text" segment. +// +//***************************************************************************** +extern uint32_t _etext; +extern uint32_t _eftext; +extern uint32_t _data; +extern uint32_t _edata; +extern uint32_t _bss; +extern uint32_t _ebss; + +// +// And here are the weak interrupt handlers. +// +void +default_NmiSR (void) +{ + __asm( + " movs r0, #2"); + while(1) + { + } +} + + +void +default_FaultISR (void) +{ + __asm( + " movs r0, #3"); + MEMIO32(0x1001FFF0) = 0xbad0beef; // near the top of 128KB of SRAM + MEMIO32(0x1001FFF4) = 0xbad1beef; // near the top of 128KB of SRAM + while(1) + { + __asm( + " BKPT #1"); + } +} + + +void +IntDefaultHandler (void) +{ + __asm( + " movs r0, #20"); + while(1) + { + __asm( + " BKPT #1"); + } +} + + +void +default_SVCall_ISR(void) +{ + __asm( + " movs r0, #11"); + while(1) + { + __asm( + " BKPT #11"); + } +} + + +void +default_DebugMonitor_ISR(void) +{ + __asm( + " movs r0, #12"); + while(1) + { + __asm( + " BKPT #12"); + } +} + +void +default_PENDSV_ISR(void) +{ + __asm( + " movs r0, #14"); + while(1) + { + __asm( + " BKPT #14"); + } +} + + +void +default_SYSTICK_ISR(void) +{ + __asm( + " movs r0, #15"); + while(1) + { + __asm( + " BKPT #15"); + } +} + + + +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +void +default_SPI0_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_SPI1_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_I2C0_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_I2C1_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_UART0_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_UART1_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_GPIO0_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_GPIO1_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_ADC_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_DSP_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_TIMER0_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_TIMER1_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_RTC0_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_RTC1_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_PWM_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_WDT_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_RTC_TMR_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_SW0_ISR(void) +{ + __asm( + " movs r0, #16"); + while(1) + { + __asm( + " BKPT #16"); + } +} + +void +default_SW1_ISR(void) +{ + __asm( + " movs r0, #17"); + while(1) + { + __asm( + " BKPT #17"); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Reset ISR +//////////////////////////////////////////////////////////////////////////////// +void +default_ResetISR (void) +{ + int rc; + bool bRunningInFlash; + + set_vtor(); + + bRunningInFlash = + ((((uint32_t) startup_get_my_pc()) & 0xFF000000) == 0x01000000); + + if(( ! REG_RTC_AO_CSR.BF.WARM_START_MODE) || bRunningInFlash) + { + + // + // Copy any .ro bytes to .data so that initialized global variables + // are actually properly initialized. + // + __asm(" ldr r0, =_eftext\n" + " ldr r1, =_data\n" + " ldr r2, =_edata\n" + "ro_copy_loop:\n" + " ldr r3, [r0], #4\n" + " str r3, [r1], #4\n" + " cmp r1, r2\n" + " ble ro_copy_loop\n"); + + // + // Zero fill the .bss section. + // + __asm(" ldr r0, =_bss\n" + " ldr r1, =_ebss\n" + " mov r2, #0\n" + "bss_zero_loop:\n" + " cmp r0, r1\n" + " it lt\n" + " strlt r2, [r0], #4\n" + " blt bss_zero_loop\n"); + } + + // + // call the main routine barefoot, i.e. without the normal CRTC0 entry + // point. + // + rc = _main(0,NULL); + + // + // If main ever returns, trap it here and wake up the debugger if it is + // connected. + // + while(1) // for FPGA/real chip use + { + __asm( + " BKPT #1"); + } + +} + + +//////////////////////////////////////////////////////////////////////////////// +// get my PC +//////////////////////////////////////////////////////////////////////////////// +void * startup_get_my_pc(void) +{ + void *pc; + asm("mov %0, pc" : "=r"(pc)); + return pc; +} + +//////////////////////////////////////////////////////////////////////////////// +// get my SP +//////////////////////////////////////////////////////////////////////////////// +void * startup_get_my_sp(void) +{ + void *sp; + asm("mov %0, sp" : "=r"(sp)); + return sp; +} + +//////////////////////////////////////////////////////////////////////////////// +// Set VTOR based on PC +//////////////////////////////////////////////////////////////////////////////// +void set_vtor(void) +{ + __asm(" ldr r0, =0xe000ed08\n" + " ldr r1, =0xFF000000\n" + " mov r2, lr\n" + " and r1, r2\n" + " str r1, [r0]\n"); + + return; +} + + + + + diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531_makefile.inc new file mode 100644 index 0000000000..baae58f87e --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531_makefile.inc @@ -0,0 +1,103 @@ +# Settings for eta ecm3531 platform +ifeq ($(TARGET), ecm3531) + TARGET_ARCH := cortex-m3 + TARGET_TOOLCHAIN_PREFIX := arm-none-eabi- + ETA_SDK := /home/hari/TensaiSDK-v0.0.17/soc/ + GCC_ARM := /home/hari/Downloads/gcc-arm-none-eabi-7-2018-q2-update/ + + ifeq ($(wildcard $(ETA_SDK)),) + $(error Path to ETA SDK is not set (ETA_SDK)) + endif + + ifeq ($(wildcard $(GCC_ARM)),) + $(error Path to gcc arm compiler is not set (GCC_ARM)) + endif + + PLATFORM_FLAGS = \ + -DFIRMWARE_BUILD \ + -DGEMMLOWP_ALLOW_SLOW_SCALAR_FALLBACK \ + -DTF_LITE_STATIC_MEMORY \ + -DTF_LITE_MCU_DEBUG_LOG \ + -fno-rtti \ + -fmessage-length=0 \ + -fno-exceptions \ + -fno-unwind-tables \ + -fno-builtin \ + -ffunction-sections \ + -fdata-sections \ + -funsigned-char \ + -MMD \ + -mcpu=cortex-m3 \ + -mthumb \ + -mlittle-endian \ + -mno-unaligned-access \ + -std=gnu++11 \ + -Wvla \ + -Wall \ + -Wextra \ + -Wno-unused-parameter \ + -Wno-missing-field-initializers \ + -Wno-write-strings \ + -Wno-sign-compare \ + -fno-delete-null-pointer-checks \ + -fomit-frame-pointer \ + -fpermissive \ + -nostdlib \ + -g \ + -Os + CXXFLAGS += $(PLATFORM_FLAGS) + CCFLAGS += $(PLATFORM_FLAGS) +# Adding the --specs=nano.specs flag causes the linker to use libc_nano.a +# instead of libc.a. This gets rid of lots of errors with various pieces +# of the exception unwinding code not being found. Not clear why it is +# trying to link in this code to begin with, though. + LDFLAGS += \ + -mthumb -mcpu=cortex-m3 \ + -nostartfiles -static \ + -Wl,--gc-sections -Wl,--entry,ResetISR \ + -Wl,--start-group -lm -lc -lgcc -Wl,--end-group \ + -fno-exceptions \ + -nostdlib --specs=nano.specs -t -lstdc++ -lc -lnosys -lm \ + -Wl,-T,$(MAKEFILE_DIR)/targets/ecm3531/ecm3531.lds \ + -Wl,-Map=$(MAKEFILE_DIR)/gen/$(TARGET).map,--cref + BUILD_TYPE := micro + MICROLITE_LIBS := \ + $(GCC_ARM)/lib/gcc/arm-none-eabi/7.3.1/thumb/v7e-m/fpv4-sp/softfp/crtbegin.o \ + -lm + INCLUDES += \ + -isystem$(MAKEFILE_DIR)/downloads/cmsis/CMSIS/Core/Include/ \ + -I$(GCC_ARM)/arm-none-eabi/include/ \ + -I$(ETA_SDK)/ecm3531/boards/eta_evb/projects/m3/common/inc/ \ + -I$(ETA_SDK)/ecm3531/m3/reg/inc/ \ + -I$(ETA_SDK)/ecm3531/m3/csp/inc/ \ + -I$(ETA_SDK)/ecm3531/common/csp/inc/ \ + -I$(ETA_SDK)/common/inc/ \ + -I$(ETA_SDK)/../utils/inc/ \ + -I$(ETA_SDK)/ecm3531/boards/eta_evb/eta_bsp/inc + + # _main.c contains application and target specific initialization, like + # setting clock speed, default uart setups, etc. and an implementation + # of the DebugLog interfaces. + MICROLITE_CC_SRCS += \ + $(MAKEFILE_DIR)/targets/ecm3531/startup.c \ + $(MAKEFILE_DIR)/targets/ecm3531/_main.c \ + $(wildcard $(ETA_SDK)/ecm3531/boards/eta_evb/projects/m3/common/src/*.c) \ + $(wildcard $(ETA_SDK)/ecm3531/m3/csp/src/*.c) \ + $(wildcard $(ETA_SDK)/ecm3531/m3/csp/src/*.s) \ + + TEST_SCRIPT := tensorflow/lite/experimental/micro/testing/test_ecm3531_binary.sh + # These are tests that don't currently work on the blue pill. + EXCLUDED_TESTS := \ + tensorflow/lite/experimental/micro/micro_interpreter_test.cc \ + tensorflow/lite/experimental/micro/simple_tensor_allocator_test.cc + MICROLITE_TEST_SRCS := $(filter-out $(EXCLUDED_TESTS), $(MICROLITE_TEST_SRCS)) + +# These are microcontroller-specific rules for converting the ELF output +# of the linker into a binary image that can be loaded directly. +OBJCOPY := $(TARGET_TOOLCHAIN_PREFIX)objcopy + +$(BINDIR)/%.bin: $(BINDIR)/% + @mkdir -p $(dir $@) + $(OBJCOPY) $< $@ -O binary + +endif -- GitLab From aff52125a0d172f4c3ae8ea7c170ca0f6d97e97d Mon Sep 17 00:00:00 2001 From: Andy Craze Date: Fri, 7 Dec 2018 20:37:37 -0800 Subject: [PATCH 0059/1765] Update tables_initializer to link to guide Resolves #20629 --- tensorflow/python/ops/lookup_ops.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tensorflow/python/ops/lookup_ops.py b/tensorflow/python/ops/lookup_ops.py index 758cb8041d..9302696a45 100644 --- a/tensorflow/python/ops/lookup_ops.py +++ b/tensorflow/python/ops/lookup_ops.py @@ -64,6 +64,8 @@ def initialize_all_tables(name="init_all_tables"): @tf_export(v1=["initializers.tables_initializer", "tables_initializer"]) def tables_initializer(name="init_all_tables"): """Returns an Op that initializes all tables of the default graph. + See the [Low Level Intro](https://www.tensorflow.org/guide/low_level_intro#feature_columns) + guide, for an example of usage. Args: name: Optional name for the initialization op. -- GitLab From 14f0dc7a6aef09b838df396bf5cc7be9b3f07fab Mon Sep 17 00:00:00 2001 From: Tongxuan Liu Date: Sun, 9 Dec 2018 00:46:42 +0800 Subject: [PATCH 0060/1765] Reduce lock contention in executor, change writelock to readlock --- tensorflow/core/common_runtime/executor.cc | 8 ++++---- tensorflow/core/framework/op_kernel.cc | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tensorflow/core/common_runtime/executor.cc b/tensorflow/core/common_runtime/executor.cc index 6b3284b84a..8e26031bf0 100644 --- a/tensorflow/core/common_runtime/executor.cc +++ b/tensorflow/core/common_runtime/executor.cc @@ -1883,7 +1883,7 @@ Status ExecutorState::PrepareInputs(const NodeItem& item, Entry* first_input, inp->tensor = entry->val.get(); } else { { - mutex_lock ml(*entry->ref_mu); + tf_shared_lock ml(*entry->ref_mu); if (!entry->ref->IsInitialized() && !IsInitializationOp(item.node)) { return AttachDef(errors::FailedPrecondition( "Attempting to use uninitialized value ", @@ -1899,7 +1899,7 @@ Status ExecutorState::PrepareInputs(const NodeItem& item, Entry* first_input, // tensor but is given a ref to a tensor. Need to deref it // under the mutex. { - mutex_lock l(*(entry->ref_mu)); + tf_shared_lock l(*(entry->ref_mu)); DCHECK(!entry->val_field_is_set); entry->val.Init(*entry->ref); entry->val_field_is_set = true; @@ -1988,7 +1988,7 @@ Status ExecutorState::ProcessOutputs(const NodeItem& item, OpKernelContext* ctx, // Sanity check of output tensor types. DataType dtype; if (val.is_ref()) { - mutex_lock ml(*val.mutex_if_ref); + tf_shared_lock ml(*val.mutex_if_ref); dtype = MakeRefType(val->dtype()); } else { dtype = val->dtype(); @@ -2005,7 +2005,7 @@ Status ExecutorState::ProcessOutputs(const NodeItem& item, OpKernelContext* ctx, Tensor to_log; { // Dereference the tensor under the lock. - mutex_lock l(*out->ref_mu); + tf_shared_lock l(*out->ref_mu); to_log = *out->ref; } LogMemory::RecordTensorOutput(ctx->op_kernel().name(), diff --git a/tensorflow/core/framework/op_kernel.cc b/tensorflow/core/framework/op_kernel.cc index e3cb4a40ec..d0ecde51d0 100644 --- a/tensorflow/core/framework/op_kernel.cc +++ b/tensorflow/core/framework/op_kernel.cc @@ -401,7 +401,7 @@ Tensor OpKernelContext::mutable_input(int index, bool lock_held) { record_tensor_reference(tensor); return tensor; } else { - mutex_lock l(*input_ref_mutex(index)); + tf_shared_lock l(*input_ref_mutex(index)); Tensor& tensor = *((*params_->inputs)[index].tensor); record_tensor_reference(tensor); return tensor; @@ -593,7 +593,7 @@ Status OpKernelContext::mutable_input(StringPiece name, Tensor* tensor, if (lock_held) { *tensor = *(*params_->inputs)[start].tensor; } else { - mutex_lock l(*input_ref_mutex(start)); + tf_shared_lock l(*input_ref_mutex(start)); *tensor = *(*params_->inputs)[start].tensor; } record_tensor_reference(*tensor); -- GitLab From 035955852708fba07565ead298cd54ad64ab1a55 Mon Sep 17 00:00:00 2001 From: Jacky Ko Date: Sun, 9 Dec 2018 18:33:50 +0800 Subject: [PATCH 0061/1765] static lib name change --- tensorflow/contrib/cmake/external/abseil_cpp.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tensorflow/contrib/cmake/external/abseil_cpp.cmake b/tensorflow/contrib/cmake/external/abseil_cpp.cmake index 8b76f37858..539c5cbb76 100644 --- a/tensorflow/contrib/cmake/external/abseil_cpp.cmake +++ b/tensorflow/contrib/cmake/external/abseil_cpp.cmake @@ -48,7 +48,7 @@ else (systemlib_ABSEIL_CPP) set(abseil_cpp_STATIC_LIBRARIES ${abseil_cpp_BUILD}/absl/base/Release/absl_base.lib ${abseil_cpp_BUILD}/absl/base/Release/absl_dynamic_annotations.lib - ${abseil_cpp_BUILD}/absl/base/Release/absl_internal_malloc_internal.lib + ${abseil_cpp_BUILD}/absl/base/Release/absl_malloc_internal.lib ${abseil_cpp_BUILD}/absl/strings/Release/absl_strings.lib ${abseil_cpp_BUILD}/absl/strings/Release/str_format_internal.lib ${abseil_cpp_BUILD}/absl/types/Release/absl_bad_optional_access.lib) @@ -94,6 +94,8 @@ else (systemlib_ABSEIL_CPP) ) include_directories(${abseil_cpp_INCLUDE_DIR}) + message(STATUS ${abseil_cpp_INCLUDE_DIR}) + list(APPEND tensorflow_EXTERNAL_LIBRARIES ${abseil_cpp_STATIC_LIBRARIES}) list(APPEND tensorflow_EXTERNAL_DEPENDENCIES abseil_cpp_build) -- GitLab From 5a4871af05392c2e5744515a4c67bc6f0f420943 Mon Sep 17 00:00:00 2001 From: fo40225 Date: Sat, 1 Sep 2018 00:58:14 +0800 Subject: [PATCH 0062/1765] fix AttributeError: 'module' object has no attribute '???'on windows python 2.7 --- tensorflow/api_template_v1.__init__.py | 3 ++- tensorflow/contrib/cmake/python_modules.txt | 3 +++ tensorflow/contrib/cmake/tf_python.cmake | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tensorflow/api_template_v1.__init__.py b/tensorflow/api_template_v1.__init__.py index 65bdb6cb1b..b9b21bad50 100644 --- a/tensorflow/api_template_v1.__init__.py +++ b/tensorflow/api_template_v1.__init__.py @@ -40,7 +40,8 @@ if '__all__' in vars(): vars()['__all__'].append('contrib') from tensorflow.python.platform import flags # pylint: disable=g-import-not-at-top -app.flags = flags # pylint: disable=undefined-variable +from tensorflow.python.platform import app # pylint: disable=g-import-not-at-top +app.flags = flags # Make sure directory containing top level submodules is in # the __path__ so that "from tensorflow.foo import bar" works. diff --git a/tensorflow/contrib/cmake/python_modules.txt b/tensorflow/contrib/cmake/python_modules.txt index 96160568fa..21ae9a08a6 100644 --- a/tensorflow/contrib/cmake/python_modules.txt +++ b/tensorflow/contrib/cmake/python_modules.txt @@ -1,6 +1,9 @@ # python_sanity_test.py will complain about invalid or missing entries # problematic entries can be commented for temporary whitelisting tensorflow +tensorflow/compiler +tensorflow/compiler/xla +tensorflow/compiler/xla/service tensorflow/core tensorflow/core/example tensorflow/core/framework diff --git a/tensorflow/contrib/cmake/tf_python.cmake b/tensorflow/contrib/cmake/tf_python.cmake index 8faccf8d55..1fe8795ddf 100755 --- a/tensorflow/contrib/cmake/tf_python.cmake +++ b/tensorflow/contrib/cmake/tf_python.cmake @@ -802,6 +802,7 @@ add_custom_command( # tensorflow/__init__.py depends on files generated in this step. So, remove it while # this step is running since the files aren't there yet. COMMAND ${CMAKE_COMMAND} -E remove -f ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/__init__.py + COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/tf_python/tensorflow/__init__.py # Run create_python_api.py to generate API init files. COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/tf_python "${PY_RUNTIME_ENV}" ${PYTHON_EXECUTABLE} -- GitLab From cc69b82bbcc68c21db839cca4f6fec043f6005aa Mon Sep 17 00:00:00 2001 From: Jacky Ko Date: Sun, 9 Dec 2018 19:08:32 +0800 Subject: [PATCH 0063/1765] abseil use master branch --- tensorflow/contrib/cmake/external/abseil_cpp.cmake | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tensorflow/contrib/cmake/external/abseil_cpp.cmake b/tensorflow/contrib/cmake/external/abseil_cpp.cmake index 539c5cbb76..f64b60fd5e 100644 --- a/tensorflow/contrib/cmake/external/abseil_cpp.cmake +++ b/tensorflow/contrib/cmake/external/abseil_cpp.cmake @@ -39,8 +39,8 @@ else (systemlib_ABSEIL_CPP) include (ExternalProject) set(abseil_cpp_INCLUDE_DIR ${CMAKE_BINARY_DIR}/abseil_cpp/src/abseil_cpp_build) - set(abseil_cpp_URL https://github.com/abseil/abseil-cpp/archive/e01d95528ea2137a4a27a88d1f57c6cb260aafed.tar.gz) - set(abseil_cpp_HASH SHA256=84043ed402d2a2a6ba4cdddb7e85118b1158fd81fe4ac3a14adc343d054c1e2e) + set(abseil_cpp_URL https://github.com/abseil/abseil-cpp.git) + set(abseil_cpp_TAG master) set(abseil_cpp_BUILD ${CMAKE_BINARY_DIR}/abseil_cpp/src/abseil_cpp_build) if(WIN32) @@ -48,7 +48,7 @@ else (systemlib_ABSEIL_CPP) set(abseil_cpp_STATIC_LIBRARIES ${abseil_cpp_BUILD}/absl/base/Release/absl_base.lib ${abseil_cpp_BUILD}/absl/base/Release/absl_dynamic_annotations.lib - ${abseil_cpp_BUILD}/absl/base/Release/absl_malloc_internal.lib + ${abseil_cpp_BUILD}/absl/base/Release/absl_internal_malloc_internal.lib ${abseil_cpp_BUILD}/absl/strings/Release/absl_strings.lib ${abseil_cpp_BUILD}/absl/strings/Release/str_format_internal.lib ${abseil_cpp_BUILD}/absl/types/Release/absl_bad_optional_access.lib) @@ -79,8 +79,7 @@ else (systemlib_ABSEIL_CPP) ExternalProject_Add(abseil_cpp_build PREFIX abseil_cpp - URL ${abseil_cpp_URL} - URL_HASH ${abseil_cpp_HASH} + GIT_REPOSITORY ${abseil_cpp_URL} DOWNLOAD_DIR "${DOWNLOAD_LOCATION}" BUILD_IN_SOURCE 1 BUILD_BYPRODUCTS ${abseil_cpp_STATIC_LIBRARIES} -- GitLab From 956b77a2a8f8db7a57b818bc0c06669fd395d56d Mon Sep 17 00:00:00 2001 From: Jacky Ko Date: Sun, 9 Dec 2018 19:31:05 +0800 Subject: [PATCH 0064/1765] abseil lib linkage update --- tensorflow/contrib/cmake/external/abseil_cpp.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tensorflow/contrib/cmake/external/abseil_cpp.cmake b/tensorflow/contrib/cmake/external/abseil_cpp.cmake index f64b60fd5e..eefa7d3f03 100644 --- a/tensorflow/contrib/cmake/external/abseil_cpp.cmake +++ b/tensorflow/contrib/cmake/external/abseil_cpp.cmake @@ -49,6 +49,8 @@ else (systemlib_ABSEIL_CPP) ${abseil_cpp_BUILD}/absl/base/Release/absl_base.lib ${abseil_cpp_BUILD}/absl/base/Release/absl_dynamic_annotations.lib ${abseil_cpp_BUILD}/absl/base/Release/absl_internal_malloc_internal.lib + ${abseil_cpp_BUILD}/absl/base/Release/absl_internal_throw_delegate.lib + ${abseil_cpp_BUILD}/absl/numeric/Release/absl_int128.lib ${abseil_cpp_BUILD}/absl/strings/Release/absl_strings.lib ${abseil_cpp_BUILD}/absl/strings/Release/str_format_internal.lib ${abseil_cpp_BUILD}/absl/types/Release/absl_bad_optional_access.lib) -- GitLab From 7578e120de2a3a5282ced8d41881f19363f83466 Mon Sep 17 00:00:00 2001 From: Dan Jarvis Date: Thu, 23 Nov 2017 13:06:02 -0500 Subject: [PATCH 0065/1765] Fix crash on closing the app when classifier failed to initialize When testing on an API 21 emulator, the classifier fails to initialize. `E/TfLiteCameraDemo: Failed to initialize an image classifier.` In this situation, the app crashes when pressing Back to exit. Here's the cause: ``` java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.android.tflitecamerademo.ImageClassifier.close()' on a null object reference at com.example.android.tflitecamerademo.Camera2BasicFragment.onDestroy(Camera2BasicFragment.java:331) at android.app.Fragment.performDestroy(Fragment.java:2266) ``` The fix is to check for null before calling `.close()`. I'll investigate why the classifier is failing to initialize separately. :-) --- .../android/tflitecamerademo/Camera2BasicFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tensorflow/lite/java/demo/app/src/main/java/com/example/android/tflitecamerademo/Camera2BasicFragment.java b/tensorflow/lite/java/demo/app/src/main/java/com/example/android/tflitecamerademo/Camera2BasicFragment.java index 165d335101..a7b3440536 100644 --- a/tensorflow/lite/java/demo/app/src/main/java/com/example/android/tflitecamerademo/Camera2BasicFragment.java +++ b/tensorflow/lite/java/demo/app/src/main/java/com/example/android/tflitecamerademo/Camera2BasicFragment.java @@ -476,7 +476,9 @@ public class Camera2BasicFragment extends Fragment @Override public void onDestroy() { - classifier.close(); + if (classifier != null) { + classifier.close(); + } super.onDestroy(); } -- GitLab From 9192d06bb62b11c40b1b5d3d5ed2e91adaacf6d8 Mon Sep 17 00:00:00 2001 From: hari Date: Mon, 10 Dec 2018 11:55:05 -0800 Subject: [PATCH 0066/1765] fixed grammer --- .../experimental/micro/tools/make/targets/ecm3531/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/README.txt b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/README.txt index 655340ceff..3cb74a7243 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/README.txt +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/README.txt @@ -5,7 +5,7 @@ This code will enable you to compile and execute the Tensorflow Lite Micro Speec GETTING STARTED: -1. Download the Tensorflow code from Github and follow anyinstructions there to download other dependencies. +1. Download the Tensorflow code from Github and follow instructions there to download other dependencies. 2. Download the Eta Compute SDK, version 0.0.17. -- GitLab From 374ad6b77c8edc8f5be6c12b510cd6a698894c29 Mon Sep 17 00:00:00 2001 From: hari Date: Mon, 10 Dec 2018 11:55:51 -0800 Subject: [PATCH 0067/1765] conform to Google coding standards --- .../micro/tools/make/targets/ecm3531/_main.c | 120 +++++++++--------- 1 file changed, 59 insertions(+), 61 deletions(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/_main.c b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/_main.c index 5a595c26b3..93941e119f 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/_main.c +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/_main.c @@ -1,37 +1,42 @@ -/******************************************************************************* - * Copyright (C) 2018 Eta Compute, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ +/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. -#include +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +/* This is file contains the entry point to the application and is called after + startup. + The GPIOs, Uart and timer are intialized and Tensorflow is invoked with the + call to main(). + Tensorflow will print out if the tests have passed or failed and the + execution time is also + printed. */ + +#include +#include #include +#include +#include "eta_bsp.h" #include "eta_chip.h" #include "eta_csp.h" -#include "eta_csp_uart.h" +#include "eta_csp_buck.h" #include "eta_csp_gpio.h" #include "eta_csp_io.h" -#include "eta_csp_timer.h" -#include "eta_csp_socctrl.h" -#include "eta_csp_buck.h" +#include "eta_csp_pwr.h" #include "eta_csp_rtc.h" +#include "eta_csp_socctrl.h" #include "eta_csp_sys_clock.h" -#include -#include "eta_bsp.h" -#include "eta_csp_pwr.h" -#include - +#include "eta_csp_timer.h" +#include "eta_csp_uart.h" tUart g_sUart0 = {eUartNum0, eUartBaud115200}; tUart g_sUart1 = {eUartNum1, eUartBaud115200}; @@ -39,59 +44,52 @@ tUart g_sUart1 = {eUartNum1, eUartBaud115200}; int init_main(int); void EtaPrintExecutionTime(uint64_t); - //***************************************************************************** // // The entry point for the application. // //***************************************************************************** -extern int main(int argc, char**argv); - -void DebugLog(const char* s) { EtaCspIoPrintf( "%s", s); } -void DebugLogInt32(int32_t i) { EtaCspIoPrintf( "%d", i); } -void DebugLogUInt32(uint32_t i) { EtaCspIoPrintf( "%d", i); } -void DebugLogHex(uint32_t i) { EtaCspIoPrintf( "0x%8x", i); } -void DebugLogFloat(float i) { EtaCspIoPrintf( "%f", i); } - - -int _main(void) -{ - uint64_t time_ms; - - EtaCspInit(); //initialize csp registers - EtaCspGpioInit(); //initialize gpios - EtaCspUartInit(&g_sUart1, eUartNum0, eUartBaud115200, eUartFlowControlHardware); //initialize Uart - EtaCspBuckInit(ETA_BSP_VDD_IO_SETTING, eBuckAo600Mv, eBuckM3Frequency60Mhz, eBuckMemVoltage900Mv);//set M3 freq - EtaCspTimerInitMs(); //start timer - main(0, NULL); //Call to Tensorflow; this will print if test was successful. - time_ms = EtaCspTimerCountGetMs(); //read time - EtaPrintExecutionTime(time_ms); //print execution time - +extern int main(int argc, char** argv); + +void DebugLog(const char* s) { EtaCspIoPrintf("%s", s); } +void DebugLogInt32(int32_t i) { EtaCspIoPrintf("%d", i); } +void DebugLogUInt32(uint32_t i) { EtaCspIoPrintf("%d", i); } +void DebugLogHex(uint32_t i) { EtaCspIoPrintf("0x%8x", i); } +void DebugLogFloat(float i) { EtaCspIoPrintf("%f", i); } + +int _main(void) { + uint64_t time_ms; + + EtaCspInit(); // initialize csp registers + EtaCspGpioInit(); // initialize gpios + EtaCspUartInit(&g_sUart1, eUartNum0, eUartBaud115200, + eUartFlowControlHardware); // initialize Uart + EtaCspBuckInit(ETA_BSP_VDD_IO_SETTING, eBuckAo600Mv, eBuckM3Frequency60Mhz, + eBuckMemVoltage900Mv); // set M3 freq + EtaCspTimerInitMs(); // start timer + main(0, NULL); // Call to Tensorflow; this will print if test was successful. + time_ms = EtaCspTimerCountGetMs(); // read time + EtaPrintExecutionTime(time_ms); // print execution time } - - -void EtaPrintExecutionTime(uint64_t time_ms) -{ +void EtaPrintExecutionTime(uint64_t time_ms) { uint8_t c; int k1; char time_string[] = "00000"; EtaCspIoPrintf("Execution time (msec) = "); - if (time_ms < 100000) //Convert time to a string + if (time_ms < 100000) // Convert time to a string { - for(k1 = 0; k1 < 5; k1++){ + for (k1 = 0; k1 < 5; k1++) { c = time_ms % 10; - time_ms = time_ms/10; + time_ms = time_ms / 10; time_string[k1] = (char)(0x30 + c); } - for(k1 = 4; k1 > 0; k1--) { //print out 1 char at a time + for (k1 = 4; k1 > 0; k1--) { // print out 1 char at a time EtaCspUartPutc(&g_sUart1, time_string[k1]); } + } else { + EtaCspIoPrintf("Execution time exceeds 100 sec\n"); } - else{ - EtaCspIoPrintf("Execution time exceeds 100 sec\n"); - } EtaCspIoPrintf("\n\n"); - } -- GitLab From 6042bbb3a9d87ea88b778761b7c1b20a2bc81237 Mon Sep 17 00:00:00 2001 From: hari Date: Mon, 10 Dec 2018 11:56:08 -0800 Subject: [PATCH 0068/1765] conform to Google coding standards --- .../tools/make/targets/ecm3531/startup.c | 771 +++++++----------- 1 file changed, 304 insertions(+), 467 deletions(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c index da9f7a4b0e..04b9abc3aa 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c @@ -1,89 +1,79 @@ -/******************************************************************************* - * - * Copyright (C) 2018 Eta Compute, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ +/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. -#include -#include "eta_chip.h" -#include "memio.h" +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 -//#pragma GCC optimize ("align-functions=16") +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include "eta_chip.h" +#include "memio.h" -#ifndef NULL -#define NULL (0) +#ifndef NULL +#define NULL (0) #endif - //***************************************************************************** // // Macro for hardware access, both direct and via the bit-band region. // //***************************************************************************** -#define NAKED -//#define NAKED __attribute__((naked)) - int _main(int argc, char *argv[]); void set_vtor(void); -void * startup_get_my_pc(void); +void *startup_get_my_pc(void); //***************************************************************************** // Forward DECLS for interrupt service routines (ISR) //***************************************************************************** -extern void ResetISR(void) __attribute__((weak, alias("default_ResetISR"))); -extern void NmiSR(void) __attribute__((weak, alias("default_NmiSR"))); -extern void FaultISR(void) __attribute__((weak, alias("default_FaultISR"))); - -extern void DebugMonitor_ISR(void) __attribute__((weak, alias("default_DebugMonitor_ISR"))); -extern void SVCall_ISR(void) __attribute__((weak, alias("default_SVCall_ISR"))); -extern void PENDSV_ISR(void) __attribute__((weak, alias("default_PENDSV_ISR"))); - -extern void SYSTICK_ISR(void) __attribute__((weak, alias("default_SYSTICK_ISR"))); - -extern void GPIO0_ISR(void) __attribute__((weak, alias("default_GPIO0_ISR"))); -extern void GPIO1_ISR(void) __attribute__((weak, alias("default_GPIO1_ISR"))); -extern void TIMER0_ISR(void) __attribute__((weak, alias("default_TIMER0_ISR"))); -extern void TIMER1_ISR(void) __attribute__((weak, alias("default_TIMER1_ISR"))); -extern void UART0_ISR(void) __attribute__((weak, alias("default_UART0_ISR"))); -extern void UART1_ISR(void) __attribute__((weak, alias("default_UART1_ISR"))); -extern void SPI0_ISR(void) __attribute__((weak, alias("default_SPI0_ISR"))); -extern void SPI1_ISR(void) __attribute__((weak, alias("default_SPI1_ISR"))); -extern void I2C0_ISR(void) __attribute__((weak, alias("default_I2C0_ISR"))); -extern void I2C1_ISR(void) __attribute__((weak, alias("default_I2C1_ISR"))); -extern void RTC0_ISR(void) __attribute__((weak, alias("default_RTC0_ISR"))); -extern void RTC1_ISR(void) __attribute__((weak, alias("default_RTC1_ISR"))); -extern void DSP_ISR(void) __attribute__((weak, alias("default_DSP_ISR"))); -extern void ADC_ISR(void) __attribute__((weak, alias("default_ADC_ISR"))); -extern void SW0_ISR(void) __attribute__((weak, alias("default_SW0_ISR"))); -extern void SW1_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); -extern void PWM_ISR(void) __attribute__((weak, alias("default_PWM_ISR"))); -extern void WDT_ISR(void) __attribute__((weak, alias("default_WDT_ISR"))); -extern void RTC_TMR_ISR(void) __attribute__((weak, alias("default_RTC_TMR_ISR"))); - - -extern void SW2_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); -extern void SW3_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); -extern void SW4_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); -extern void SW5_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); -extern void SW6_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); - - -extern void IntDefaultHandler(void) __attribute__((weak)) NAKED; +extern void ResetISR(void) __attribute__((weak, alias("default_ResetISR"))); +extern void NmiSR(void) __attribute__((weak, alias("default_NmiSR"))); +extern void FaultISR(void) __attribute__((weak, alias("default_FaultISR"))); + +extern void DebugMonitor_ISR(void) + __attribute__((weak, alias("default_DebugMonitor_ISR"))); +extern void SVCall_ISR(void) __attribute__((weak, alias("default_SVCall_ISR"))); +extern void PENDSV_ISR(void) __attribute__((weak, alias("default_PENDSV_ISR"))); + +extern void SYSTICK_ISR(void) + __attribute__((weak, alias("default_SYSTICK_ISR"))); + +extern void GPIO0_ISR(void) __attribute__((weak, alias("default_GPIO0_ISR"))); +extern void GPIO1_ISR(void) __attribute__((weak, alias("default_GPIO1_ISR"))); +extern void TIMER0_ISR(void) __attribute__((weak, alias("default_TIMER0_ISR"))); +extern void TIMER1_ISR(void) __attribute__((weak, alias("default_TIMER1_ISR"))); +extern void UART0_ISR(void) __attribute__((weak, alias("default_UART0_ISR"))); +extern void UART1_ISR(void) __attribute__((weak, alias("default_UART1_ISR"))); +extern void SPI0_ISR(void) __attribute__((weak, alias("default_SPI0_ISR"))); +extern void SPI1_ISR(void) __attribute__((weak, alias("default_SPI1_ISR"))); +extern void I2C0_ISR(void) __attribute__((weak, alias("default_I2C0_ISR"))); +extern void I2C1_ISR(void) __attribute__((weak, alias("default_I2C1_ISR"))); +extern void RTC0_ISR(void) __attribute__((weak, alias("default_RTC0_ISR"))); +extern void RTC1_ISR(void) __attribute__((weak, alias("default_RTC1_ISR"))); +extern void DSP_ISR(void) __attribute__((weak, alias("default_DSP_ISR"))); +extern void ADC_ISR(void) __attribute__((weak, alias("default_ADC_ISR"))); +extern void SW0_ISR(void) __attribute__((weak, alias("default_SW0_ISR"))); +extern void SW1_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void PWM_ISR(void) __attribute__((weak, alias("default_PWM_ISR"))); +extern void WDT_ISR(void) __attribute__((weak, alias("default_WDT_ISR"))); +extern void RTC_TMR_ISR(void) + __attribute__((weak, alias("default_RTC_TMR_ISR"))); + +extern void SW2_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void SW3_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void SW4_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void SW5_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); +extern void SW6_ISR(void) __attribute__((weak, alias("default_SW1_ISR"))); + +extern void IntDefaultHandler(void) __attribute__((weak)); //***************************************************************************** // @@ -92,63 +82,58 @@ extern void IntDefaultHandler(void) __attribute__((weak)) NAKED; //***************************************************************************** extern uint32_t _stack_top; //__attribute__ ((section(".mainStack"), used)) -//static uint32_t pui32Stack[2048]; +// static uint32_t pui32Stack[2048]; #define STARTUP_STACK_TOP (&_stack_top) - - //***************************************************************************** // VECTOR TABLE //***************************************************************************** -__attribute__ ((section(".vectors"), used)) -void (* const gVectors[])(void) = -{ - //(void (*)(void))((uint32_t)pui32Stack + sizeof(pui32Stack)), // Stack pointer - (void *)STARTUP_STACK_TOP, - ResetISR, // Reset handler - NmiSR, // The NMI handler - FaultISR, // The hard fault handler - IntDefaultHandler, // 4 The MPU fault handler - IntDefaultHandler, // 5 The bus fault handler - IntDefaultHandler, // 6 The usage fault handler - 0, // 7 Reserved - 0, // 8 Reserved - 0, // 9 Reserved - 0, // 10 Reserved - SVCall_ISR, // 11 SVCall handler - DebugMonitor_ISR, // 12 Debug monitor handler - 0, // 13 Reserved - PENDSV_ISR, // 14 The PendSV handler - SYSTICK_ISR, // 15 The SysTick handler - - // external interrupt service routines (ISR) - GPIO0_ISR, // 16 GPIO Port A [ 0] - GPIO1_ISR, // 17 GPIO Port B [ 1] - TIMER0_ISR, // 18 Timer 0 [ 2] - TIMER1_ISR, // 19 Timer 1 [ 3] - UART0_ISR, // 20 UART 0 [ 4] - UART1_ISR, // 21 UART 1 [ 5] - SPI0_ISR, // 22 SPI0 [ 6] - SPI1_ISR, // 23 SPI1 [ 7] - I2C0_ISR, // 24 I2C 0 [ 8] - I2C1_ISR, // 25 I2C 1 [ 9] - RTC0_ISR, // 26 RTC 0 [10] - RTC1_ISR, // 27 RTC 1 [11] - DSP_ISR, // 28 DSP MAILBOX [12] - ADC_ISR, // 29 ADC [13] - PWM_ISR, // 32 PWM [14] - WDT_ISR, // 33 WDT [15] - RTC_TMR_ISR, // 34 RTC [16] - - SW0_ISR, // 30 Software Interrupt 0 [17] - SW1_ISR, // 31 Software Interrupt 1 [18] - SW2_ISR, // 35 Software Interrupt 2 [19] - SW3_ISR, // 36 Software Interrupt 3 [20] - SW4_ISR, // 37 Software Interrupt 4 [21] - SW5_ISR, // 38 Software Interrupt 5 [22] - SW6_ISR, // 39 Software Interrupt 6 [23] - - +__attribute__((section(".vectors"), used)) void (*const gVectors[])(void) = { + //(void (*)(void))((uint32_t)pui32Stack + sizeof(pui32Stack)), // Stack + //pointer + (void *)STARTUP_STACK_TOP, + ResetISR, // Reset handler + NmiSR, // The NMI handler + FaultISR, // The hard fault handler + IntDefaultHandler, // 4 The MPU fault handler + IntDefaultHandler, // 5 The bus fault handler + IntDefaultHandler, // 6 The usage fault handler + 0, // 7 Reserved + 0, // 8 Reserved + 0, // 9 Reserved + 0, // 10 Reserved + SVCall_ISR, // 11 SVCall handler + DebugMonitor_ISR, // 12 Debug monitor handler + 0, // 13 Reserved + PENDSV_ISR, // 14 The PendSV handler + SYSTICK_ISR, // 15 The SysTick handler + + // external interrupt service routines (ISR) + GPIO0_ISR, // 16 GPIO Port A [ 0] + GPIO1_ISR, // 17 GPIO Port B [ 1] + TIMER0_ISR, // 18 Timer 0 [ 2] + TIMER1_ISR, // 19 Timer 1 [ 3] + UART0_ISR, // 20 UART 0 [ 4] + UART1_ISR, // 21 UART 1 [ 5] + SPI0_ISR, // 22 SPI0 [ 6] + SPI1_ISR, // 23 SPI1 [ 7] + I2C0_ISR, // 24 I2C 0 [ 8] + I2C1_ISR, // 25 I2C 1 [ 9] + RTC0_ISR, // 26 RTC 0 [10] + RTC1_ISR, // 27 RTC 1 [11] + DSP_ISR, // 28 DSP MAILBOX [12] + ADC_ISR, // 29 ADC [13] + PWM_ISR, // 32 PWM [14] + WDT_ISR, // 33 WDT [15] + RTC_TMR_ISR, // 34 RTC [16] + + SW0_ISR, // 30 Software Interrupt 0 [17] + SW1_ISR, // 31 Software Interrupt 1 [18] + SW2_ISR, // 35 Software Interrupt 2 [19] + SW3_ISR, // 36 Software Interrupt 3 [20] + SW4_ISR, // 37 Software Interrupt 4 [21] + SW5_ISR, // 38 Software Interrupt 5 [22] + SW6_ISR, // 39 Software Interrupt 6 [23] }; @@ -169,424 +154,276 @@ extern uint32_t _ebss; // // And here are the weak interrupt handlers. // -void -default_NmiSR (void) -{ - __asm( - " movs r0, #2"); - while(1) - { - } +void default_NmiSR(void) { + __asm(" movs r0, #2"); + while (1) { + } } - -void -default_FaultISR (void) -{ - __asm( - " movs r0, #3"); - MEMIO32(0x1001FFF0) = 0xbad0beef; // near the top of 128KB of SRAM - MEMIO32(0x1001FFF4) = 0xbad1beef; // near the top of 128KB of SRAM - while(1) - { - __asm( - " BKPT #1"); - } +void default_FaultISR(void) { + __asm(" movs r0, #3"); + MEMIO32(0x1001FFF0) = 0xbad0beef; // near the top of 128KB of SRAM + MEMIO32(0x1001FFF4) = 0xbad1beef; // near the top of 128KB of SRAM + while (1) { + __asm(" BKPT #1"); + } } - -void -IntDefaultHandler (void) -{ - __asm( - " movs r0, #20"); - while(1) - { - __asm( - " BKPT #1"); - } +void IntDefaultHandler(void) { + __asm(" movs r0, #20"); + while (1) { + __asm(" BKPT #1"); + } } - -void -default_SVCall_ISR(void) -{ - __asm( - " movs r0, #11"); - while(1) - { - __asm( - " BKPT #11"); - } +void default_SVCall_ISR(void) { + __asm(" movs r0, #11"); + while (1) { + __asm(" BKPT #11"); + } } - -void -default_DebugMonitor_ISR(void) -{ - __asm( - " movs r0, #12"); - while(1) - { - __asm( - " BKPT #12"); - } +void default_DebugMonitor_ISR(void) { + __asm(" movs r0, #12"); + while (1) { + __asm(" BKPT #12"); + } } -void -default_PENDSV_ISR(void) -{ - __asm( - " movs r0, #14"); - while(1) - { - __asm( - " BKPT #14"); - } +void default_PENDSV_ISR(void) { + __asm(" movs r0, #14"); + while (1) { + __asm(" BKPT #14"); + } } - -void -default_SYSTICK_ISR(void) -{ - __asm( - " movs r0, #15"); - while(1) - { - __asm( - " BKPT #15"); - } +void default_SYSTICK_ISR(void) { + __asm(" movs r0, #15"); + while (1) { + __asm(" BKPT #15"); + } } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void -default_SPI0_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_SPI0_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_SPI1_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_SPI1_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_I2C0_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_I2C0_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_I2C1_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_I2C1_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_UART0_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_UART0_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_UART1_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_UART1_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_GPIO0_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_GPIO0_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_GPIO1_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_GPIO1_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_ADC_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_ADC_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_DSP_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_DSP_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_TIMER0_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_TIMER0_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_TIMER1_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_TIMER1_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_RTC0_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_RTC0_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_RTC1_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_RTC1_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_PWM_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_PWM_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_WDT_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_WDT_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_RTC_TMR_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_RTC_TMR_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_SW0_ISR(void) -{ - __asm( - " movs r0, #16"); - while(1) - { - __asm( - " BKPT #16"); - } +void default_SW0_ISR(void) { + __asm(" movs r0, #16"); + while (1) { + __asm(" BKPT #16"); + } } -void -default_SW1_ISR(void) -{ - __asm( - " movs r0, #17"); - while(1) - { - __asm( - " BKPT #17"); - } +void default_SW1_ISR(void) { + __asm(" movs r0, #17"); + while (1) { + __asm(" BKPT #17"); + } } //////////////////////////////////////////////////////////////////////////////// // Reset ISR //////////////////////////////////////////////////////////////////////////////// -void -default_ResetISR (void) -{ - int rc; - bool bRunningInFlash; - - set_vtor(); - - bRunningInFlash = - ((((uint32_t) startup_get_my_pc()) & 0xFF000000) == 0x01000000); - - if(( ! REG_RTC_AO_CSR.BF.WARM_START_MODE) || bRunningInFlash) - { - - // - // Copy any .ro bytes to .data so that initialized global variables - // are actually properly initialized. - // - __asm(" ldr r0, =_eftext\n" - " ldr r1, =_data\n" - " ldr r2, =_edata\n" - "ro_copy_loop:\n" - " ldr r3, [r0], #4\n" - " str r3, [r1], #4\n" - " cmp r1, r2\n" - " ble ro_copy_loop\n"); - - // - // Zero fill the .bss section. - // - __asm(" ldr r0, =_bss\n" - " ldr r1, =_ebss\n" - " mov r2, #0\n" - "bss_zero_loop:\n" - " cmp r0, r1\n" - " it lt\n" - " strlt r2, [r0], #4\n" - " blt bss_zero_loop\n"); - } - - // - // call the main routine barefoot, i.e. without the normal CRTC0 entry - // point. - // - rc = _main(0,NULL); - - // - // If main ever returns, trap it here and wake up the debugger if it is - // connected. - // - while(1) // for FPGA/real chip use - { - __asm( - " BKPT #1"); - } - -} +void default_ResetISR(void) { + int rc; + bool bRunningInFlash; + + set_vtor(); + bRunningInFlash = + ((((uint32_t)startup_get_my_pc()) & 0xFF000000) == 0x01000000); + + if ((!REG_RTC_AO_CSR.BF.WARM_START_MODE) || bRunningInFlash) { + // + // Copy any .ro bytes to .data so that initialized global variables + // are actually properly initialized. + // + __asm( + " ldr r0, =_eftext\n" + " ldr r1, =_data\n" + " ldr r2, =_edata\n" + "ro_copy_loop:\n" + " ldr r3, [r0], #4\n" + " str r3, [r1], #4\n" + " cmp r1, r2\n" + " ble ro_copy_loop\n"); + + // + // Zero fill the .bss section. + // + __asm( + " ldr r0, =_bss\n" + " ldr r1, =_ebss\n" + " mov r2, #0\n" + "bss_zero_loop:\n" + " cmp r0, r1\n" + " it lt\n" + " strlt r2, [r0], #4\n" + " blt bss_zero_loop\n"); + } + + // + // call the main routine barefoot, i.e. without the normal CRTC0 entry + // point. + // + rc = _main(0, NULL); + + // + // If main ever returns, trap it here and wake up the debugger if it is + // connected. + // + while (1) // for FPGA/real chip use + { + __asm(" BKPT #1"); + } +} //////////////////////////////////////////////////////////////////////////////// // get my PC //////////////////////////////////////////////////////////////////////////////// -void * startup_get_my_pc(void) -{ - void *pc; - asm("mov %0, pc" : "=r"(pc)); - return pc; +void *startup_get_my_pc(void) { + void *pc; + asm("mov %0, pc" : "=r"(pc)); + return pc; } //////////////////////////////////////////////////////////////////////////////// // get my SP //////////////////////////////////////////////////////////////////////////////// -void * startup_get_my_sp(void) -{ - void *sp; - asm("mov %0, sp" : "=r"(sp)); - return sp; +void *startup_get_my_sp(void) { + void *sp; + asm("mov %0, sp" : "=r"(sp)); + return sp; } //////////////////////////////////////////////////////////////////////////////// // Set VTOR based on PC //////////////////////////////////////////////////////////////////////////////// -void set_vtor(void) -{ - __asm(" ldr r0, =0xe000ed08\n" - " ldr r1, =0xFF000000\n" - " mov r2, lr\n" - " and r1, r2\n" - " str r1, [r0]\n"); - - return; +void set_vtor(void) { + __asm( + " ldr r0, =0xe000ed08\n" + " ldr r1, =0xFF000000\n" + " mov r2, lr\n" + " and r1, r2\n" + " str r1, [r0]\n"); + + return; } - - - - - -- GitLab From 7fbd07114922c1d132e323f7bea14126b336f86e Mon Sep 17 00:00:00 2001 From: hari Date: Mon, 10 Dec 2018 11:56:50 -0800 Subject: [PATCH 0069/1765] added copyright statement --- .../tools/make/targets/ecm3531/ecm3531.lds | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/ecm3531.lds b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/ecm3531.lds index 2c77ebcc1d..af34f988f2 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/ecm3531.lds +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/ecm3531.lds @@ -1,20 +1,17 @@ -/******************************************************************************* - * - * Copyright (C) 2018 Eta Compute, Inc - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ +/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ /* -- GitLab From ac0d13b64d260b89822a73637e43c9098205f20f Mon Sep 17 00:00:00 2001 From: hari Date: Mon, 10 Dec 2018 11:58:00 -0800 Subject: [PATCH 0070/1765] added copyright statement and comment for usage --- .../tools/make/targets/ecm3531/load_program | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/load_program b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/load_program index 5d4974ba6e..ac1f49962a 100755 --- a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/load_program +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/load_program @@ -1,4 +1,22 @@ #!/usr/bin/python3 +#Usage: cd to the directory tensorflow/lite/experimental/micro/tools/make/targets/ecm3531 and type ./load_prgram to load the executable tensorflow/lite/experimental/micro/tools/make/gen/ecm3531_cortex-m3/bin/micro_speech_test into SRAM +# +# +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +#Licensed under the Apache License, Version 2.0 (the "License"); +#you may not use this file except in compliance with the License. +#You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +#Unless required by applicable law or agreed to in writing, software +#distributed under the License is distributed on an "AS IS" BASIS, +#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#See the License for the specific language governing permissions and +#limitations under the License. +#============================================================================== + import os import telnetlib -- GitLab From 6f5e6dc40f30b34af97e3813b046e572d8125fea Mon Sep 17 00:00:00 2001 From: hari Date: Mon, 10 Dec 2018 12:06:12 -0800 Subject: [PATCH 0071/1765] added brief comment about this file --- .../experimental/micro/tools/make/targets/ecm3531/startup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c index 04b9abc3aa..32d817ba48 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c +++ b/tensorflow/lite/experimental/micro/tools/make/targets/ecm3531/startup.c @@ -13,6 +13,9 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +/* This file is called at power up time to initialize the chip. It in turn +calls _main() which is the entry point into the application */ + #include #include "eta_chip.h" #include "memio.h" @@ -90,7 +93,7 @@ extern uint32_t _stack_top; //***************************************************************************** __attribute__((section(".vectors"), used)) void (*const gVectors[])(void) = { //(void (*)(void))((uint32_t)pui32Stack + sizeof(pui32Stack)), // Stack - //pointer + // pointer (void *)STARTUP_STACK_TOP, ResetISR, // Reset handler NmiSR, // The NMI handler -- GitLab From 16380e05087b41c39547e3f05e1ce85cea44efb2 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Tue, 11 Dec 2018 00:40:26 +0000 Subject: [PATCH 0072/1765] Fix warning caused by to_int32 While running tf.keras I noticed the following warning: ``` WARNING:tensorflow:From /usr/local/lib/python2.7/dist-packages/tensorflow/python/ops/math_ops.py:3064: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version. Instructions for updating: Use tf.cast instead. ``` This fix fixes the warning caused by deprecated to_int32. Signed-off-by: Yong Tang --- tensorflow/python/ops/math_ops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow/python/ops/math_ops.py b/tensorflow/python/ops/math_ops.py index e2b634ee8f..1d85fb0193 100644 --- a/tensorflow/python/ops/math_ops.py +++ b/tensorflow/python/ops/math_ops.py @@ -3061,8 +3061,8 @@ def reduced_shape(input_shape, axes): input_shape[axes] = 1 return input_shape - input_shape = to_int32(input_shape) # [2, 3, 5, 7] - axes = to_int32(axes) # [1, 2] + input_shape = cast(input_shape, dtypes.int32) # [2, 3, 5, 7] + axes = cast(axes, dtypes.int32) # [1, 2] input_rank = array_ops.size(input_shape) # 4 axes = (axes + input_rank) % input_rank -- GitLab From 16f454f95e9d9823145d6b00a7e007afd0ea569b Mon Sep 17 00:00:00 2001 From: Luke Han Date: Tue, 11 Dec 2018 11:03:05 +0900 Subject: [PATCH 0073/1765] fix typo in scatter_nd_add docstring --- tensorflow/python/ops/state_ops.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tensorflow/python/ops/state_ops.py b/tensorflow/python/ops/state_ops.py index 3ac69c1c20..25b31c698e 100644 --- a/tensorflow/python/ops/state_ops.py +++ b/tensorflow/python/ops/state_ops.py @@ -462,9 +462,8 @@ def scatter_nd_add(ref, indices, updates, use_locking=False, name=None): updates: A `Tensor`. Must have the same type as `ref`. A tensor of updated values to add to ref. use_locking: An optional `bool`. Defaults to `False`. - An optional bool. Defaults to True. If True, the assignment will - be protected by a lock; otherwise the behavior is undefined, - but may exhibit less contention. + If True, the assignment will be protected by a lock; + otherwise the behavior is undefined, but may exhibit less contention. name: A name for the operation (optional). Returns: -- GitLab From f0f7ed323983ab2cb157bf782950b6e2238b9f6b Mon Sep 17 00:00:00 2001 From: Jacky Ko Date: Tue, 11 Dec 2018 20:35:50 +0800 Subject: [PATCH 0074/1765] add abseil time library linking --- tensorflow/contrib/cmake/external/abseil_cpp.cmake | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tensorflow/contrib/cmake/external/abseil_cpp.cmake b/tensorflow/contrib/cmake/external/abseil_cpp.cmake index b85fd48f0f..6c6a5df7f7 100644 --- a/tensorflow/contrib/cmake/external/abseil_cpp.cmake +++ b/tensorflow/contrib/cmake/external/abseil_cpp.cmake @@ -31,8 +31,8 @@ if (systemlib_ABSEIL_CPP) message(STATUS " abseil_cpp includes: ${ABSEIL_CPP_INCLUDE_DIR}") message(STATUS " abseil_cpp libraries: ${ABSEIL_CPP_LIBRARIES}") - add_custom_target(abseil_cpp) - list(APPEND tensorflow_EXTERNAL_DEPENDENCIES abseil_cpp) + add_custom_target(abseil_cpp_build) + list(APPEND tensorflow_EXTERNAL_DEPENDENCIES abseil_cpp_build) else (systemlib_ABSEIL_CPP) @@ -53,6 +53,7 @@ else (systemlib_ABSEIL_CPP) ${abseil_cpp_BUILD}/absl/numeric/Release/absl_int128.lib ${abseil_cpp_BUILD}/absl/strings/Release/absl_strings.lib ${abseil_cpp_BUILD}/absl/strings/Release/str_format_internal.lib + ${abseil_cpp_BUILD}/absl/time/Release/absl_time.lib ${abseil_cpp_BUILD}/absl/types/Release/absl_bad_optional_access.lib) else() set(abseil_cpp_STATIC_LIBRARIES @@ -64,6 +65,7 @@ else (systemlib_ABSEIL_CPP) ${abseil_cpp_BUILD}/absl/numeric/absl_int128.lib ${abseil_cpp_BUILD}/absl/strings/absl_strings.lib ${abseil_cpp_BUILD}/absl/strings/str_format_internal.lib + ${abseil_cpp_BUILD}/absl/time/absl_time.lib ${abseil_cpp_BUILD}/absl/types/absl_bad_optional_access.lib) endif() else() @@ -76,14 +78,18 @@ else (systemlib_ABSEIL_CPP) ${abseil_cpp_BUILD}/absl/numeric/libabsl_int128.a ${abseil_cpp_BUILD}/absl/strings/libabsl_strings.a ${abseil_cpp_BUILD}/absl/strings/libstr_format_internal.a + ${abseil_cpp_BUILD}/absl/time/libabsl_time.a ${abseil_cpp_BUILD}/absl/types/libabsl_bad_optional_access.a) endif() - ExternalProject_Add(abseil_cpp + ExternalProject_Add(abseil_cpp_build PREFIX abseil_cpp GIT_REPOSITORY ${abseil_cpp_URL} DOWNLOAD_DIR "${DOWNLOAD_LOCATION}" + BUILD_IN_SOURCE 1 BUILD_BYPRODUCTS ${abseil_cpp_STATIC_LIBRARIES} + BUILD_COMMAND ${CMAKE_COMMAND} --build . --config Release + COMMAND ${CMAKE_COMMAND} --build . --config Release INSTALL_COMMAND "" CMAKE_CACHE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=${tensorflow_ENABLE_POSITION_INDEPENDENT_CODE} @@ -96,6 +102,6 @@ else (systemlib_ABSEIL_CPP) list(APPEND tensorflow_EXTERNAL_LIBRARIES ${abseil_cpp_STATIC_LIBRARIES}) - list(APPEND tensorflow_EXTERNAL_DEPENDENCIES abseil_cpp) + list(APPEND tensorflow_EXTERNAL_DEPENDENCIES abseil_cpp_build) endif (systemlib_ABSEIL_CPP) \ No newline at end of file -- GitLab From 568db5fb164092eaf2863f0e4a2fdb48533d76f9 Mon Sep 17 00:00:00 2001 From: Siju Samuel Date: Mon, 19 Nov 2018 07:20:36 +0530 Subject: [PATCH 0075/1765] Abs, Ceil ops initial --- tensorflow/lite/build_def.bzl | 1 + tensorflow/lite/builtin_ops.h | 1 + .../lite/core/api/flatbuffer_conversions.cc | 2 + .../lite/delegates/nnapi/nnapi_delegate.cc | 20 ++++ .../delegates/nnapi/nnapi_delegate_test.cc | 109 ++++++++++++++++++ .../writer/option_writer_generator.cc | 2 + tensorflow/lite/g3doc/tf_ops_compatibility.md | 22 ++++ tensorflow/lite/kernels/BUILD | 34 ++++++ tensorflow/lite/kernels/abs.cc | 59 ++++++++++ tensorflow/lite/kernels/abs_test.cc | 94 +++++++++++++++ tensorflow/lite/kernels/ceil.cc | 59 ++++++++++ tensorflow/lite/kernels/ceil_test.cc | 83 +++++++++++++ .../internal/optimized/legacy_optimized_ops.h | 12 ++ .../internal/optimized/optimized_ops.h | 16 +++ .../internal/reference/legacy_reference_ops.h | 12 ++ .../internal/reference/reference_ops.h | 20 ++++ tensorflow/lite/kernels/register.cc | 4 + tensorflow/lite/nnapi/NeuralNetworksShim.h | 2 + tensorflow/lite/nnapi_delegate.cc | 6 + tensorflow/lite/schema/schema.fbs | 1 + tensorflow/lite/schema/schema_generated.h | 10 +- tensorflow/lite/testing/generate_examples.py | 52 +++++++++ tensorflow/lite/toco/export_tensorflow.cc | 26 +++++ .../propagate_fixed_sizes.cc | 2 + .../reorder_elementwise_unary.cc | 2 + tensorflow/lite/toco/import_tensorflow.cc | 29 +++++ tensorflow/lite/toco/model.h | 22 ++++ tensorflow/lite/toco/tflite/operator.cc | 4 + tensorflow/lite/toco/tflite/operator_test.cc | 2 + .../lite/toco/tflite/whitelisted_flex_ops.cc | 1 + tensorflow/lite/toco/tooling_util.cc | 2 + 31 files changed, 708 insertions(+), 3 deletions(-) create mode 100644 tensorflow/lite/kernels/abs.cc create mode 100644 tensorflow/lite/kernels/abs_test.cc create mode 100644 tensorflow/lite/kernels/ceil.cc create mode 100644 tensorflow/lite/kernels/ceil_test.cc diff --git a/tensorflow/lite/build_def.bzl b/tensorflow/lite/build_def.bzl index c17eddf47b..1539ac788a 100644 --- a/tensorflow/lite/build_def.bzl +++ b/tensorflow/lite/build_def.bzl @@ -228,6 +228,7 @@ def generated_test_models(): "arg_min_max", "avg_pool", "batch_to_space_nd", + "ceil", "concat", "constant", "control_dep", diff --git a/tensorflow/lite/builtin_ops.h b/tensorflow/lite/builtin_ops.h index f97d3ac4bf..0077fade40 100644 --- a/tensorflow/lite/builtin_ops.h +++ b/tensorflow/lite/builtin_ops.h @@ -128,6 +128,7 @@ typedef enum { kTfLiteBuiltinMirrorPad = 100, kTfLiteBuiltinAbs = 101, kTfLiteBuiltinSplitV = 102, + kTfLiteBuiltinCeil = 103, } TfLiteBuiltinOperator; #ifdef __cplusplus diff --git a/tensorflow/lite/core/api/flatbuffer_conversions.cc b/tensorflow/lite/core/api/flatbuffer_conversions.cc index c00a0a3a54..8a436c440f 100644 --- a/tensorflow/lite/core/api/flatbuffer_conversions.cc +++ b/tensorflow/lite/core/api/flatbuffer_conversions.cc @@ -664,6 +664,8 @@ TfLiteStatus ParseOpData(const Operator* op, BuiltinOperator op_type, case BuiltinOperator_EQUAL: case BuiltinOperator_EXP: case BuiltinOperator_EXPAND_DIMS: + case BuiltinOperator_ABS: + case BuiltinOperator_CEIL: case BuiltinOperator_FLOOR: case BuiltinOperator_GREATER: case BuiltinOperator_GREATER_EQUAL: diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc index 4fe07004a8..1a95ac1891 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc @@ -638,6 +638,26 @@ class NNAPIDelegateKernel { return nullptr; } break; + case kTfLiteBuiltinCeil: + if (version == 1) { + return [](const NNAPIOpMappingArgs& mapping_args) + -> ANeuralNetworksOperationType { + return ANEURALNETWORKS_CEIL; + }; + } else { + return nullptr; + } + break; + case kTfLiteBuiltinAbs: + if (version == 1) { + return [](const NNAPIOpMappingArgs& mapping_args) + -> ANeuralNetworksOperationType { + return ANEURALNETWORKS_ABS; + }; + } else { + return nullptr; + } + break; case kTfLiteBuiltinRelu: if (version == 1) { return [](const NNAPIOpMappingArgs& mapping_args) diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc index ca48af0c95..3050b69028 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc @@ -1024,6 +1024,115 @@ TEST(NNAPIDelegate, FloorMultiDims) { EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); } +class CeilOpModel : public SingleOpModelWithNNAPI { + public: + CeilOpModel(std::initializer_list input_shape, TensorType input_type) { + input_ = AddInput(TensorType_FLOAT32); + output_ = AddOutput(TensorType_FLOAT32); + SetBuiltinOp(BuiltinOperator_CEIL, BuiltinOptions_NONE, 0); + BuildInterpreter({ + input_shape, + }); + } + + int input() { return input_; } + + std::vector GetOutput() { return ExtractVector(output_); } + std::vector GetOutputShape() { return GetTensorShape(output_); } + + private: + int input_; + int output_; +}; + +TEST(NNAPIDelegate, CeilSingleDim) { + CeilOpModel model({2}, TensorType_FLOAT32); + model.PopulateTensor(model.input(), {8.5, 0.0}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), ElementsAreArray({8, 0})); + EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2})); +} + +TEST(NNAPIDelegate, CeilMultiDims) { + CeilOpModel model({2, 1, 1, 5}, TensorType_FLOAT32); + model.PopulateTensor(model.input(), { + 0.0001, + 8.0001, + 0.9999, + 9.9999, + 0.5, + -0.0001, + -8.0001, + -0.9999, + -9.9999, + -0.5, + }); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({1, 9, 1, 10, 1, 0, -8, 0, -9, 0})); + EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); +} + +class AbsOpModel : public SingleOpModelWithNNAPI { + public: + AbsOpModel(std::initializer_list input_shape, TensorType input_type) { + input_ = AddInput(TensorType_FLOAT32); + output_ = AddOutput(TensorType_FLOAT32); + SetBuiltinOp(BuiltinOperator_ABS, BuiltinOptions_NONE, 0); + BuildInterpreter({ + input_shape, + }); + } + + int input() { return input_; } + + std::vector GetOutput() { return ExtractVector(output_); } + std::vector GetOutputShape() { return GetTensorShape(output_); } + + private: + int input_; + int output_; +}; + +TEST(NNAPIDelegate, AbsSingleDim) { + AbsOpModel model({2}, TensorType_FLOAT32); + model.PopulateTensor(model.input(), {8.5, -2.0}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), ElementsAreArray({8.5, 2.0})); + EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2})); +} + +TEST(NNAPIDelegate, AbsMultiDims) { + AbsOpModel model({2, 1, 1, 5}, TensorType_FLOAT32); + model.PopulateTensor(model.input(), { + 0.0001, + 8.0001, + 0.9999, + 9.9999, + 0.5, + -0.0001, + -8.0001, + -0.9999, + -9.9999, + -0.5, + }); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({ + 0.0001, + 8.0001, + 0.9999, + 9.9999, + 0.5, + 0.0001, + 8.0001, + 0.9999, + 9.9999, + 0.5, + })); + EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); +} + class LocalResponseNormOpModel : public SingleOpModelWithNNAPI { public: LocalResponseNormOpModel(std::initializer_list input_shape, int radius, diff --git a/tensorflow/lite/experimental/writer/option_writer_generator.cc b/tensorflow/lite/experimental/writer/option_writer_generator.cc index fa360a2f47..d79b6e8ca9 100644 --- a/tensorflow/lite/experimental/writer/option_writer_generator.cc +++ b/tensorflow/lite/experimental/writer/option_writer_generator.cc @@ -160,6 +160,8 @@ class OpOptionData { op_to_option_["EMBEDDING_LOOKUP"] = ""; // TODO(aselle): maybe something else. op_to_option_["FLOOR"] = ""; + op_to_option_["CEIL"] = ""; + op_to_option_["ABS"] = ""; op_to_option_["HASHTABLE_LOOKUP"] = ""; // TODO(aselle): maybe something else. op_to_option_["LOGISTIC"] = ""; diff --git a/tensorflow/lite/g3doc/tf_ops_compatibility.md b/tensorflow/lite/g3doc/tf_ops_compatibility.md index dcfda72137..dc6ba8a463 100644 --- a/tensorflow/lite/g3doc/tf_ops_compatibility.md +++ b/tensorflow/lite/g3doc/tf_ops_compatibility.md @@ -362,6 +362,28 @@ Outputs { } ``` +**CEIL** + +``` +inputs { + 0: tensor +} +outputs: { + 0: result of computing element-wise ceil of the input tensor +} +``` + +**ABS** + +``` +inputs { + 0: tensor +} +outputs: { + 0: result of computing element-wise absolute value of the input tensor +} +``` + **FULLY_CONNECTED** ``` diff --git a/tensorflow/lite/kernels/BUILD b/tensorflow/lite/kernels/BUILD index bad1c4aebf..f66f69870f 100644 --- a/tensorflow/lite/kernels/BUILD +++ b/tensorflow/lite/kernels/BUILD @@ -158,6 +158,7 @@ cc_library( cc_library( name = "builtin_op_kernels", srcs = [ + "abs.cc", "activations.cc", "add.cc", "arg_min_max.cc", @@ -167,6 +168,7 @@ cc_library( "bidirectional_sequence_lstm.cc", "bidirectional_sequence_rnn.cc", "cast.cc", + "ceil.cc", "comparisons.cc", "concatenation.cc", "conv.cc", @@ -599,6 +601,38 @@ tf_cc_test( ], ) +tf_cc_test( + name = "abs_test", + size = "small", + srcs = ["abs_test.cc"], + tags = [ + "no_oss", + "tflite_not_portable_ios", + ], + deps = [ + ":builtin_ops", + "//tensorflow/lite:framework", + "//tensorflow/lite/kernels:test_util", + "@com_google_googletest//:gtest", + ], +) + +tf_cc_test( + name = "ceil_test", + size = "small", + srcs = ["ceil_test.cc"], + tags = [ + "no_oss", + "tflite_not_portable_ios", + ], + deps = [ + ":builtin_ops", + "//tensorflow/lite:framework", + "//tensorflow/lite/kernels:test_util", + "@com_google_googletest//:gtest", + ], +) + tf_cc_test( name = "elementwise_test", size = "small", diff --git a/tensorflow/lite/kernels/abs.cc b/tensorflow/lite/kernels/abs.cc new file mode 100644 index 0000000000..b44f9de630 --- /dev/null +++ b/tensorflow/lite/kernels/abs.cc @@ -0,0 +1,59 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" +#include "tensorflow/lite/kernels/internal/tensor.h" +#include "tensorflow/lite/kernels/kernel_util.h" + +namespace tflite { +namespace ops { +namespace builtin { +namespace abs { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + const TfLiteTensor* input = GetInput(context, node, kInputTensor); + TfLiteTensor* output = GetOutput(context, node, kOutputTensor); + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TF_LITE_ENSURE_EQ(context, input->type, kTfLiteFloat32); + output->type = input->type; + TfLiteIntArray* output_size = TfLiteIntArrayCopy(input->dims); + return context->ResizeTensor(context, output, output_size); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteTensor* input = GetInput(context, node, kInputTensor); + TfLiteTensor* output = GetOutput(context, node, kOutputTensor); + + optimized_ops::Abs(GetTensorShape(input), GetTensorData(input), + GetTensorShape(output), GetTensorData(output)); + + return kTfLiteOk; +} +} // namespace abs + +TfLiteRegistration* Register_ABS() { + static TfLiteRegistration r = {/*init=*/nullptr, + /*free=*/nullptr, abs::Prepare, abs::Eval}; + return &r; +} + +} // namespace builtin +} // namespace ops +} // namespace tflite diff --git a/tensorflow/lite/kernels/abs_test.cc b/tensorflow/lite/kernels/abs_test.cc new file mode 100644 index 0000000000..5e3f95c43a --- /dev/null +++ b/tensorflow/lite/kernels/abs_test.cc @@ -0,0 +1,94 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include "tensorflow/lite/interpreter.h" +#include "tensorflow/lite/kernels/register.h" +#include "tensorflow/lite/kernels/test_util.h" +#include "tensorflow/lite/model.h" + +namespace tflite { +namespace { + +using ::testing::ElementsAreArray; + +class AbsOpModel : public SingleOpModel { + public: + AbsOpModel(std::initializer_list input_shape, TensorType input_type) { + input_ = AddInput(TensorType_FLOAT32); + output_ = AddOutput(TensorType_FLOAT32); + SetBuiltinOp(BuiltinOperator_ABS, BuiltinOptions_NONE, 0); + BuildInterpreter({ + input_shape, + }); + } + + int input() { return input_; } + + std::vector GetOutput() { return ExtractVector(output_); } + std::vector GetOutputShape() { return GetTensorShape(output_); } + + private: + int input_; + int output_; +}; + +TEST(AbsOpTest, SingleDim) { + AbsOpModel model({2}, TensorType_FLOAT32); + model.PopulateTensor(model.input(), {8.5, -2.0}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), ElementsAreArray({8.5, 2.0})); + EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2})); +} + +TEST(AbsOpTest, MultiDims) { + AbsOpModel model({2, 1, 1, 5}, TensorType_FLOAT32); + model.PopulateTensor(model.input(), { + 0.0001, + 8.0001, + 0.9999, + 9.9999, + 0.5, + -0.0001, + -8.0001, + -0.9999, + -9.9999, + -0.5, + }); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({ + 0.0001, + 8.0001, + 0.9999, + 9.9999, + 0.5, + 0.0001, + 8.0001, + 0.9999, + 9.9999, + 0.5, + })); + EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); +} + +} // namespace +} // namespace tflite + +int main(int argc, char** argv) { + ::tflite::LogToStderr(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tensorflow/lite/kernels/ceil.cc b/tensorflow/lite/kernels/ceil.cc new file mode 100644 index 0000000000..e0ea061f25 --- /dev/null +++ b/tensorflow/lite/kernels/ceil.cc @@ -0,0 +1,59 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" +#include "tensorflow/lite/kernels/internal/tensor.h" +#include "tensorflow/lite/kernels/kernel_util.h" + +namespace tflite { +namespace ops { +namespace builtin { +namespace ceil { + +constexpr int kInputTensor = 0; +constexpr int kOutputTensor = 0; + +TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { + const TfLiteTensor* input = GetInput(context, node, kInputTensor); + TfLiteTensor* output = GetOutput(context, node, kOutputTensor); + TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); + TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); + TF_LITE_ENSURE_EQ(context, input->type, kTfLiteFloat32); + output->type = input->type; + TfLiteIntArray* output_size = TfLiteIntArrayCopy(input->dims); + return context->ResizeTensor(context, output, output_size); +} + +TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { + const TfLiteTensor* input = GetInput(context, node, kInputTensor); + TfLiteTensor* output = GetOutput(context, node, kOutputTensor); + + optimized_ops::Ceil(GetTensorShape(input), GetTensorData(input), + GetTensorShape(output), GetTensorData(output)); + + return kTfLiteOk; +} +} // namespace ceil + +TfLiteRegistration* Register_CEIL() { + static TfLiteRegistration r = {/*init=*/nullptr, + /*free=*/nullptr, ceil::Prepare, ceil::Eval}; + return &r; +} + +} // namespace builtin +} // namespace ops +} // namespace tflite diff --git a/tensorflow/lite/kernels/ceil_test.cc b/tensorflow/lite/kernels/ceil_test.cc new file mode 100644 index 0000000000..e120105082 --- /dev/null +++ b/tensorflow/lite/kernels/ceil_test.cc @@ -0,0 +1,83 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include "tensorflow/lite/interpreter.h" +#include "tensorflow/lite/kernels/register.h" +#include "tensorflow/lite/kernels/test_util.h" +#include "tensorflow/lite/model.h" + +namespace tflite { +namespace { + +using ::testing::ElementsAreArray; + +class CeilOpModel : public SingleOpModel { + public: + CeilOpModel(std::initializer_list input_shape, TensorType input_type) { + input_ = AddInput(TensorType_FLOAT32); + output_ = AddOutput(TensorType_FLOAT32); + SetBuiltinOp(BuiltinOperator_CEIL, BuiltinOptions_NONE, 0); + BuildInterpreter({ + input_shape, + }); + } + + int input() { return input_; } + + std::vector GetOutput() { return ExtractVector(output_); } + std::vector GetOutputShape() { return GetTensorShape(output_); } + + private: + int input_; + int output_; +}; + +TEST(CeilOpTest, SingleDim) { + CeilOpModel model({2}, TensorType_FLOAT32); + model.PopulateTensor(model.input(), {8.5, 0.0}); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), ElementsAreArray({9, 0})); + EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2})); +} + +TEST(CeilOpTest, MultiDims) { + CeilOpModel model({2, 1, 1, 5}, TensorType_FLOAT32); + model.PopulateTensor(model.input(), { + 0.0001, + 8.0001, + 0.9999, + 9.9999, + 0.5, + -0.0001, + -8.0001, + -0.9999, + -9.9999, + -0.5, + }); + model.Invoke(); + EXPECT_THAT(model.GetOutput(), + ElementsAreArray({1, 9, 1, 10, 1, 0, -8, 0, -9, 0})); + EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); +} + +} // namespace +} // namespace tflite + +int main(int argc, char** argv) { + ::tflite::LogToStderr(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h index 5485d907c2..c24b7faa21 100644 --- a/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h +++ b/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h @@ -1740,6 +1740,18 @@ inline void Floor(const float* input_data, const Dims<4>& input_dims, output_data); } +inline void Ceil(const float* input_data, const Dims<4>& input_dims, + float* output_data, const Dims<4>& output_dims) { + Ceil(DimsToShape(input_dims), input_data, DimsToShape(output_dims), + output_data); +} + +inline void Abs(const float* input_data, const Dims<4>& input_dims, + float* output_data, const Dims<4>& output_dims) { + Abs(DimsToShape(input_dims), input_data, DimsToShape(output_dims), + output_data); +} + inline void ResizeBilinear(const float* input_data, const Dims<4>& input_dims, const int32* output_size_data, const Dims<4>& output_size_dims, float* output_data, diff --git a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h index c79b69a22e..7f7296ae97 100644 --- a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h +++ b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h @@ -4898,6 +4898,22 @@ inline void Floor(const RuntimeShape& input_shape, const float* input_data, output_map.array() = Eigen::floor(input_map.array()); } +inline void Ceil(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + gemmlowp::ScopedProfilingLabel label("Ceil"); + auto input_map = MapAsVector(input_data, input_shape); + auto output_map = MapAsVector(output_data, output_shape); + output_map.array() = Eigen::ceil(input_map.array()); +} + +inline void Abs(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + gemmlowp::ScopedProfilingLabel label("Abs"); + auto input_map = MapAsVector(input_data, input_shape); + auto output_map = MapAsVector(output_data, output_shape); + output_map.array() = Eigen::abs(input_map.array()); +} + #ifdef USE_NEON inline void ResizeBilinearKernel(const float* input_ptr, int32 depth, float scale, float* output_ptr) { diff --git a/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h b/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h index 380fc8f98e..30bb92c8b3 100644 --- a/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h +++ b/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h @@ -1883,6 +1883,18 @@ inline void Floor(const float* input_data, const Dims<4>& input_dims, output_data); } +inline void Ceil(const float* input_data, const Dims<4>& input_dims, + float* output_data, const Dims<4>& output_dims) { + Ceil(DimsToShape(input_dims), input_data, DimsToShape(output_dims), + output_data); +} + +inline void Abs(const float* input_data, const Dims<4>& input_dims, + float* output_data, const Dims<4>& output_dims) { + Abs(DimsToShape(input_dims), input_data, DimsToShape(output_dims), + output_data); +} + template inline void ResizeBilinear(const T* input_data, const Dims<4>& input_dims, const int32* output_size_data, diff --git a/tensorflow/lite/kernels/internal/reference/reference_ops.h b/tensorflow/lite/kernels/internal/reference/reference_ops.h index ea3ab06da1..133a455e9e 100644 --- a/tensorflow/lite/kernels/internal/reference/reference_ops.h +++ b/tensorflow/lite/kernels/internal/reference/reference_ops.h @@ -3040,6 +3040,26 @@ inline void Floor(const RuntimeShape& input_shape, const float* input_data, } } +inline void Ceil(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; i++) { + int offset = i; + output_data[offset] = std::ceil(input_data[offset]); + } +} + +inline void Abs(const RuntimeShape& input_shape, const float* input_data, + const RuntimeShape& output_shape, float* output_data) { + const int flat_size = MatchingFlatSize(input_shape, output_shape); + + for (int i = 0; i < flat_size; i++) { + int offset = i; + output_data[offset] = std::fabs(input_data[offset]); + } +} + template inline void Gather(const tflite::GatherParams& op_params, const RuntimeShape& input_shape, const T* input_data, diff --git a/tensorflow/lite/kernels/register.cc b/tensorflow/lite/kernels/register.cc index c0e6f6994f..caf61e9003 100644 --- a/tensorflow/lite/kernels/register.cc +++ b/tensorflow/lite/kernels/register.cc @@ -94,6 +94,8 @@ TfLiteRegistration* Register_GREATER_EQUAL(); TfLiteRegistration* Register_LESS(); TfLiteRegistration* Register_LESS_EQUAL(); TfLiteRegistration* Register_FLOOR(); +TfLiteRegistration* Register_CEIL(); +TfLiteRegistration* Register_ABS(); TfLiteRegistration* Register_TILE(); TfLiteRegistration* Register_NEG(); TfLiteRegistration* Register_SUM(); @@ -235,6 +237,8 @@ BuiltinOpResolver::BuiltinOpResolver() { AddBuiltin(BuiltinOperator_LESS, Register_LESS()); AddBuiltin(BuiltinOperator_LESS_EQUAL, Register_LESS_EQUAL()); AddBuiltin(BuiltinOperator_FLOOR, Register_FLOOR()); + AddBuiltin(BuiltinOperator_CEIL, Register_CEIL()); + AddBuiltin(BuiltinOperator_ABS, Register_ABS()); AddBuiltin(BuiltinOperator_NEG, Register_NEG()); AddBuiltin(BuiltinOperator_SELECT, Register_SELECT()); AddBuiltin(BuiltinOperator_SLICE, Register_SLICE()); diff --git a/tensorflow/lite/nnapi/NeuralNetworksShim.h b/tensorflow/lite/nnapi/NeuralNetworksShim.h index c39502f4ac..037d364c3b 100644 --- a/tensorflow/lite/nnapi/NeuralNetworksShim.h +++ b/tensorflow/lite/nnapi/NeuralNetworksShim.h @@ -143,6 +143,8 @@ enum { ANEURALNETWORKS_STRIDED_SLICE = 35, ANEURALNETWORKS_SUB = 36, ANEURALNETWORKS_TRANSPOSE = 37, + ANEURALNETWORKS_CEIL = 38, + ANEURALNETWORKS_ABS = 39, }; /** diff --git a/tensorflow/lite/nnapi_delegate.cc b/tensorflow/lite/nnapi_delegate.cc index 26d75696a1..6da803ce7b 100644 --- a/tensorflow/lite/nnapi_delegate.cc +++ b/tensorflow/lite/nnapi_delegate.cc @@ -489,6 +489,12 @@ TfLiteStatus AddOpsAndParams( case tflite::BuiltinOperator_FLOOR: nn_op_type = ANEURALNETWORKS_FLOOR; break; + case tflite::BuiltinOperator_CEIL: + nn_op_type = ANEURALNETWORKS_CEIL; + break; + case tflite::BuiltinOperator_ABS: + nn_op_type = ANEURALNETWORKS_ABS; + break; case tflite::BuiltinOperator_LOGISTIC: nn_op_type = ANEURALNETWORKS_LOGISTIC; break; diff --git a/tensorflow/lite/schema/schema.fbs b/tensorflow/lite/schema/schema.fbs index 980f13b19b..2d27722415 100644 --- a/tensorflow/lite/schema/schema.fbs +++ b/tensorflow/lite/schema/schema.fbs @@ -205,6 +205,7 @@ enum BuiltinOperator : byte { MIRROR_PAD = 100, ABS = 101, SPLIT_V = 102, + CEIL = 103, } // Options for the builtin operators. diff --git a/tensorflow/lite/schema/schema_generated.h b/tensorflow/lite/schema/schema_generated.h index 637cbafabd..a605c19b52 100755 --- a/tensorflow/lite/schema/schema_generated.h +++ b/tensorflow/lite/schema/schema_generated.h @@ -520,11 +520,12 @@ enum BuiltinOperator { BuiltinOperator_MIRROR_PAD = 100, BuiltinOperator_ABS = 101, BuiltinOperator_SPLIT_V = 102, + BuiltinOperator_CEIL = 103, BuiltinOperator_MIN = BuiltinOperator_ADD, - BuiltinOperator_MAX = BuiltinOperator_SPLIT_V + BuiltinOperator_MAX = BuiltinOperator_CEIL }; -inline const BuiltinOperator (&EnumValuesBuiltinOperator())[102] { +inline const BuiltinOperator (&EnumValuesBuiltinOperator())[103] { static const BuiltinOperator values[] = { BuiltinOperator_ADD, BuiltinOperator_AVERAGE_POOL_2D, @@ -627,7 +628,9 @@ inline const BuiltinOperator (&EnumValuesBuiltinOperator())[102] { BuiltinOperator_SQUARED_DIFFERENCE, BuiltinOperator_MIRROR_PAD, BuiltinOperator_ABS, - BuiltinOperator_SPLIT_V + BuiltinOperator_SPLIT_V, + BuiltinOperator_CEIL + }; return values; } @@ -737,6 +740,7 @@ inline const char * const *EnumNamesBuiltinOperator() { "MIRROR_PAD", "ABS", "SPLIT_V", + "CEIL", nullptr }; return names; diff --git a/tensorflow/lite/testing/generate_examples.py b/tensorflow/lite/testing/generate_examples.py index dd7b3d0745..825873a884 100644 --- a/tensorflow/lite/testing/generate_examples.py +++ b/tensorflow/lite/testing/generate_examples.py @@ -3021,6 +3021,58 @@ def make_floor_tests(zip_path): make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) +def make_ceil_tests(zip_path): + """Make a set of tests to do ceil.""" + + test_parameters = [{ + "input_dtype": [tf.float32], + "input_shape": [[1], [1, 2], [5, 6, 7, 8], [3, 4, 5, 6]], + }] + + def build_graph(parameters): + """Build the ceil op testing graph.""" + input_value = tf.placeholder( + dtype=parameters["input_dtype"], + name="input1", + shape=parameters["input_shape"]) + out = tf.ceil(input_value) + return [input_value], [out] + + def build_inputs(parameters, sess, inputs, outputs): + input_value = create_tensor_data(parameters["input_dtype"], + parameters["input_shape"]) + return [input_value], sess.run( + outputs, feed_dict={inputs[0]: input_value}) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + + +def make_abs_tests(zip_path): + """Make a set of tests to do abs.""" + + test_parameters = [{ + "input_dtype": [tf.float32], + "input_shape": [[1], [1, 2], [5, 6, 7, 8], [3, 4, 5, 6]], + }] + + def build_graph(parameters): + """Build the abs op testing graph.""" + input_value = tf.placeholder( + dtype=parameters["input_dtype"], + name="input1", + shape=parameters["input_shape"]) + out = tf.abs(input_value) + return [input_value], [out] + + def build_inputs(parameters, sess, inputs, outputs): + input_value = create_tensor_data(parameters["input_dtype"], + parameters["input_shape"]) + return [input_value], sess.run( + outputs, feed_dict={inputs[0]: input_value}) + + make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) + + def make_neg_tests(zip_path): """Make a set of tests to do neg.""" diff --git a/tensorflow/lite/toco/export_tensorflow.cc b/tensorflow/lite/toco/export_tensorflow.cc index 9fff001552..9dfeaad164 100644 --- a/tensorflow/lite/toco/export_tensorflow.cc +++ b/tensorflow/lite/toco/export_tensorflow.cc @@ -1205,6 +1205,26 @@ void ConvertFloorOperator(const Model& model, const FloorOperator& src_op, (*floor_op->mutable_attr())["T"].set_type(DT_FLOAT); } +void ConvertCeilOperator(const Model& model, const CeilOperator& src_op, + GraphDef* tensorflow_graph) { + tensorflow::NodeDef* ceil_op = tensorflow_graph->add_node(); + ceil_op->set_op("Ceil"); + ceil_op->set_name(src_op.outputs[0]); + CHECK_EQ(src_op.inputs.size(), 1); + *ceil_op->add_input() = src_op.inputs[0]; + (*ceil_op->mutable_attr())["T"].set_type(DT_FLOAT); +} + +void ConvertAbsOperator(const Model& model, const AbsOperator& src_op, + GraphDef* tensorflow_graph) { + tensorflow::NodeDef* abs_op = tensorflow_graph->add_node(); + abs_op->set_op("Abs"); + abs_op->set_name(src_op.outputs[0]); + CHECK_EQ(src_op.inputs.size(), 1); + *abs_op->add_input() = src_op.inputs[0]; + (*abs_op->mutable_attr())["T"].set_type(DT_FLOAT); +} + void ConvertGatherOperator(const Model& model, const GatherOperator& src_op, GraphDef* tensorflow_graph) { tensorflow::NodeDef* gather_op = tensorflow_graph->add_node(); @@ -2169,6 +2189,12 @@ void ConvertOperator(const Model& model, const Operator& src_op, } else if (src_op.type == OperatorType::kFloor) { ConvertFloorOperator(model, static_cast(src_op), tensorflow_graph); + } else if (src_op.type == OperatorType::kCeil) { + ConvertCeilOperator(model, static_cast(src_op), + tensorflow_graph); + } else if (src_op.type == OperatorType::kAbs) { + ConvertAbsOperator(model, static_cast(src_op), + tensorflow_graph); } else if (src_op.type == OperatorType::kGather) { ConvertGatherOperator(model, static_cast(src_op), tensorflow_graph); diff --git a/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc b/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc index 0e653f08a0..c6c7681c03 100644 --- a/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc +++ b/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc @@ -1869,6 +1869,8 @@ void ProcessMirrorPadOperator(Model* model, MirrorPadOperator* op) { case OperatorType::kAssert: case OperatorType::kCast: case OperatorType::kFloor: + case OperatorType::kCeil: + case OperatorType::kAbs: case OperatorType::kExp: case OperatorType::kSin: case OperatorType::kLogicalAnd: diff --git a/tensorflow/lite/toco/graph_transformations/reorder_elementwise_unary.cc b/tensorflow/lite/toco/graph_transformations/reorder_elementwise_unary.cc index 6a4b919854..90e64816c8 100644 --- a/tensorflow/lite/toco/graph_transformations/reorder_elementwise_unary.cc +++ b/tensorflow/lite/toco/graph_transformations/reorder_elementwise_unary.cc @@ -29,7 +29,9 @@ namespace { bool IsElementwiseOperator(OperatorType optype) { switch (optype) { + case OperatorType::kAbs: case OperatorType::kCast: + case OperatorType::kCeil: case OperatorType::kExp: case OperatorType::kFloor: case OperatorType::kNeg: diff --git a/tensorflow/lite/toco/import_tensorflow.cc b/tensorflow/lite/toco/import_tensorflow.cc index 0b2f810394..de8ae19a71 100644 --- a/tensorflow/lite/toco/import_tensorflow.cc +++ b/tensorflow/lite/toco/import_tensorflow.cc @@ -1491,6 +1491,34 @@ tensorflow::Status ConvertFloorOperator( return tensorflow::Status::OK(); } +tensorflow::Status ConvertCeilOperator( + const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, + Model* model) { + CHECK_EQ(node.op(), "Ceil"); + TF_QCHECK_OK(CheckInputsCount(node, tf_import_flags, 1)); + const auto data_type = GetDataTypeAttr(node, "T"); + CHECK(data_type == DT_FLOAT); + auto* op = new CeilOperator; + op->inputs.push_back(node.input(0)); + op->outputs.push_back(node.name()); + model->operators.emplace_back(op); + return tensorflow::Status::OK(); +} + +tensorflow::Status ConvertAbsOperator( + const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, + Model* model) { + CHECK_EQ(node.op(), "Abs"); + TF_QCHECK_OK(CheckInputsCount(node, tf_import_flags, 1)); + const auto data_type = GetDataTypeAttr(node, "T"); + CHECK(data_type == DT_FLOAT); + auto* op = new AbsOperator; + op->inputs.push_back(node.input(0)); + op->outputs.push_back(node.name()); + model->operators.emplace_back(op); + return tensorflow::Status::OK(); +} + tensorflow::Status ConvertGatherOperator( const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, Model* model) { @@ -2314,6 +2342,7 @@ ConverterMapType GetTensorFlowNodeConverterMap() { {"BatchToSpaceND", ConvertBatchToSpaceNDOperator}, {"BiasAdd", ConvertBiasAddOperator}, {"Cast", ConvertCastOperator}, + {"Ceil", ConvertCeilOperator}, {"CheckNumerics", ConvertIdentityOperator}, {"Concat", ConvertConcatOperator}, {"ConcatV2", ConvertConcatOperator}, diff --git a/tensorflow/lite/toco/model.h b/tensorflow/lite/toco/model.h index d392535f5c..69c6d7608a 100644 --- a/tensorflow/lite/toco/model.h +++ b/tensorflow/lite/toco/model.h @@ -37,11 +37,13 @@ using tflite::QuantizationParams; enum class OperatorType : uint8 { kNone, // General-purpose neural network operators. + kAbs, kAdd, kAddN, kAveragePool, kBatchMatMul, kBatchNormalization, + kCeil, kConv, kConcatenation, kDepthwiseConv, @@ -1658,6 +1660,26 @@ struct FloorOperator : Operator { FloorOperator() : Operator(OperatorType::kFloor) {} }; +// Ceil operator. +// +// Inputs: +// inputs[0]: required: the input array +// +// TensorFlow equivalent: Ceil +struct CeilOperator : Operator { + CeilOperator() : Operator(OperatorType::kCeil) {} +}; + +// Abs operator. +// +// Inputs: +// inputs[0]: required: the input array +// +// TensorFlow equivalent: Abs +struct AbsOperator : Operator { + AbsOperator() : Operator(OperatorType::kAbs) {} +}; + // Gather operator. It gathers slices from params according to indices. // Only 1-D indices are supported at the moment. // diff --git a/tensorflow/lite/toco/tflite/operator.cc b/tensorflow/lite/toco/tflite/operator.cc index 205af23da5..2122d04958 100644 --- a/tensorflow/lite/toco/tflite/operator.cc +++ b/tensorflow/lite/toco/tflite/operator.cc @@ -1649,6 +1649,10 @@ std::vector> BuildOperatorList( "DEQUANTIZE", OperatorType::kDequantize)); ops.push_back( MakeUnique>("FLOOR", OperatorType::kFloor)); + ops.push_back( + MakeUnique>("CEIL", OperatorType::kCeil)); + ops.push_back( + MakeUnique>("ABS", OperatorType::kAbs)); ops.push_back( MakeUnique>("RELU", OperatorType::kRelu)); ops.push_back(MakeUnique>( diff --git a/tensorflow/lite/toco/tflite/operator_test.cc b/tensorflow/lite/toco/tflite/operator_test.cc index 14ec89cd73..e284619903 100644 --- a/tensorflow/lite/toco/tflite/operator_test.cc +++ b/tensorflow/lite/toco/tflite/operator_test.cc @@ -114,6 +114,8 @@ TEST_F(OperatorTest, SimpleOperators) { CheckSimpleOperator("DEQUANTIZE", OperatorType::kDequantize); CheckSimpleOperator("FLOOR", OperatorType::kFloor); + CheckSimpleOperator("CEIL", OperatorType::kCeil); + CheckSimpleOperator("ABS", OperatorType::kAbs); CheckSimpleOperator("RELU", OperatorType::kRelu); CheckSimpleOperator("RELU_N1_TO_1", OperatorType::kRelu1); CheckSimpleOperator("RELU6", OperatorType::kRelu6); diff --git a/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc b/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc index 039a918af1..a96222a8a2 100644 --- a/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc +++ b/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc @@ -68,6 +68,7 @@ bool IsWhitelistedFlexOp(const std::string& tensorflow_op_name) { "BroadcastArgs", "BroadcastGradientArgs", "Cast", + "Ceil", "CheckNumerics", "ComplexAbs", "Concat", diff --git a/tensorflow/lite/toco/tooling_util.cc b/tensorflow/lite/toco/tooling_util.cc index af4cd386a2..0887dca9b5 100644 --- a/tensorflow/lite/toco/tooling_util.cc +++ b/tensorflow/lite/toco/tooling_util.cc @@ -385,6 +385,8 @@ const char* OperatorTypeName(OperatorType type) { HANDLE_OPERATORTYPENAME_CASE(ConcatV2) HANDLE_OPERATORTYPENAME_CASE(Cast) HANDLE_OPERATORTYPENAME_CASE(Floor) + HANDLE_OPERATORTYPENAME_CASE(Ceil) + HANDLE_OPERATORTYPENAME_CASE(Abs) HANDLE_OPERATORTYPENAME_CASE(Gather) HANDLE_OPERATORTYPENAME_CASE(ResizeBilinear) HANDLE_OPERATORTYPENAME_CASE(SpaceToBatchND) -- GitLab From 9e91a0899f116e8bfec46922221c45765346ce2e Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Wed, 12 Dec 2018 15:27:09 +0100 Subject: [PATCH 0076/1765] Update tensorflow.data.experimental goldens for v1 Add the drop_remainder argument for bucket_by_sequence_length to the goldens. --- .../tools/api/golden/v1/tensorflow.data.experimental.pbtxt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.pbtxt index ad10b82283..b8ba3e341f 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.data.experimental.pbtxt @@ -54,7 +54,7 @@ tf_module { } member_method { name: "bucket_by_sequence_length" - argspec: "args=[\'element_length_func\', \'bucket_boundaries\', \'bucket_batch_sizes\', \'padded_shapes\', \'padding_values\', \'pad_to_bucket_boundary\', \'no_padding\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'False\'], " + argspec: "args=[\'element_length_func\', \'bucket_boundaries\', \'bucket_batch_sizes\', \'padded_shapes\', \'padding_values\', \'pad_to_bucket_boundary\', \'no_padding\', \'drop_remainder\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'False\', \'False\'], " } member_method { name: "choose_from_datasets" -- GitLab From c266087d4d086913194bd621cad125853eca8fd6 Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Wed, 12 Dec 2018 15:29:25 +0100 Subject: [PATCH 0077/1765] Update tensorflow.data.experimental goldens for v2 Add the drop_remainder argument for bucket_by_sequence_length to the goldens. --- .../tools/api/golden/v2/tensorflow.data.experimental.pbtxt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.pbtxt index ad10b82283..b8ba3e341f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.data.experimental.pbtxt @@ -54,7 +54,7 @@ tf_module { } member_method { name: "bucket_by_sequence_length" - argspec: "args=[\'element_length_func\', \'bucket_boundaries\', \'bucket_batch_sizes\', \'padded_shapes\', \'padding_values\', \'pad_to_bucket_boundary\', \'no_padding\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'False\'], " + argspec: "args=[\'element_length_func\', \'bucket_boundaries\', \'bucket_batch_sizes\', \'padded_shapes\', \'padding_values\', \'pad_to_bucket_boundary\', \'no_padding\', \'drop_remainder\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'False\', \'False\', \'False\'], " } member_method { name: "choose_from_datasets" -- GitLab From e30a0a1de0b0b51da69b3d4bf5c545142accb3c2 Mon Sep 17 00:00:00 2001 From: Siju Samuel Date: Wed, 12 Dec 2018 20:03:36 +0530 Subject: [PATCH 0078/1765] Removed abs since already committed in 5916a9f0e4b5b2c4f80767ff83a001a6f86b4395 --- .../lite/core/api/flatbuffer_conversions.cc | 1 - .../lite/delegates/nnapi/nnapi_delegate.cc | 10 -- .../delegates/nnapi/nnapi_delegate_test.cc | 60 ------------ .../writer/option_writer_generator.cc | 1 - tensorflow/lite/g3doc/tf_ops_compatibility.md | 11 --- tensorflow/lite/kernels/BUILD | 17 ---- tensorflow/lite/kernels/abs.cc | 59 ------------ tensorflow/lite/kernels/abs_test.cc | 94 ------------------- .../internal/optimized/legacy_optimized_ops.h | 6 -- .../internal/optimized/optimized_ops.h | 8 -- .../internal/reference/legacy_reference_ops.h | 6 -- .../internal/reference/reference_ops.h | 10 -- tensorflow/lite/kernels/register.cc | 2 - tensorflow/lite/nnapi/NeuralNetworksShim.h | 1 - tensorflow/lite/nnapi_delegate.cc | 3 - tensorflow/lite/testing/generate_examples.py | 26 ----- tensorflow/lite/toco/export_tensorflow.cc | 13 --- .../propagate_fixed_sizes.cc | 1 - .../reorder_elementwise_unary.cc | 1 - tensorflow/lite/toco/import_tensorflow.cc | 14 --- tensorflow/lite/toco/model.h | 11 --- tensorflow/lite/toco/tflite/operator.cc | 2 - tensorflow/lite/toco/tflite/operator_test.cc | 1 - tensorflow/lite/toco/tooling_util.cc | 1 - 24 files changed, 359 deletions(-) delete mode 100644 tensorflow/lite/kernels/abs.cc delete mode 100644 tensorflow/lite/kernels/abs_test.cc diff --git a/tensorflow/lite/core/api/flatbuffer_conversions.cc b/tensorflow/lite/core/api/flatbuffer_conversions.cc index 8a436c440f..9c8eb5a2d8 100644 --- a/tensorflow/lite/core/api/flatbuffer_conversions.cc +++ b/tensorflow/lite/core/api/flatbuffer_conversions.cc @@ -664,7 +664,6 @@ TfLiteStatus ParseOpData(const Operator* op, BuiltinOperator op_type, case BuiltinOperator_EQUAL: case BuiltinOperator_EXP: case BuiltinOperator_EXPAND_DIMS: - case BuiltinOperator_ABS: case BuiltinOperator_CEIL: case BuiltinOperator_FLOOR: case BuiltinOperator_GREATER: diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc index 1a95ac1891..cac98ae3da 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc @@ -648,16 +648,6 @@ class NNAPIDelegateKernel { return nullptr; } break; - case kTfLiteBuiltinAbs: - if (version == 1) { - return [](const NNAPIOpMappingArgs& mapping_args) - -> ANeuralNetworksOperationType { - return ANEURALNETWORKS_ABS; - }; - } else { - return nullptr; - } - break; case kTfLiteBuiltinRelu: if (version == 1) { return [](const NNAPIOpMappingArgs& mapping_args) diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc index 3050b69028..f6a04e36cd 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc @@ -1073,66 +1073,6 @@ TEST(NNAPIDelegate, CeilMultiDims) { EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); } -class AbsOpModel : public SingleOpModelWithNNAPI { - public: - AbsOpModel(std::initializer_list input_shape, TensorType input_type) { - input_ = AddInput(TensorType_FLOAT32); - output_ = AddOutput(TensorType_FLOAT32); - SetBuiltinOp(BuiltinOperator_ABS, BuiltinOptions_NONE, 0); - BuildInterpreter({ - input_shape, - }); - } - - int input() { return input_; } - - std::vector GetOutput() { return ExtractVector(output_); } - std::vector GetOutputShape() { return GetTensorShape(output_); } - - private: - int input_; - int output_; -}; - -TEST(NNAPIDelegate, AbsSingleDim) { - AbsOpModel model({2}, TensorType_FLOAT32); - model.PopulateTensor(model.input(), {8.5, -2.0}); - model.Invoke(); - EXPECT_THAT(model.GetOutput(), ElementsAreArray({8.5, 2.0})); - EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2})); -} - -TEST(NNAPIDelegate, AbsMultiDims) { - AbsOpModel model({2, 1, 1, 5}, TensorType_FLOAT32); - model.PopulateTensor(model.input(), { - 0.0001, - 8.0001, - 0.9999, - 9.9999, - 0.5, - -0.0001, - -8.0001, - -0.9999, - -9.9999, - -0.5, - }); - model.Invoke(); - EXPECT_THAT(model.GetOutput(), - ElementsAreArray({ - 0.0001, - 8.0001, - 0.9999, - 9.9999, - 0.5, - 0.0001, - 8.0001, - 0.9999, - 9.9999, - 0.5, - })); - EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); -} - class LocalResponseNormOpModel : public SingleOpModelWithNNAPI { public: LocalResponseNormOpModel(std::initializer_list input_shape, int radius, diff --git a/tensorflow/lite/experimental/writer/option_writer_generator.cc b/tensorflow/lite/experimental/writer/option_writer_generator.cc index d79b6e8ca9..ba0303f9db 100644 --- a/tensorflow/lite/experimental/writer/option_writer_generator.cc +++ b/tensorflow/lite/experimental/writer/option_writer_generator.cc @@ -161,7 +161,6 @@ class OpOptionData { ""; // TODO(aselle): maybe something else. op_to_option_["FLOOR"] = ""; op_to_option_["CEIL"] = ""; - op_to_option_["ABS"] = ""; op_to_option_["HASHTABLE_LOOKUP"] = ""; // TODO(aselle): maybe something else. op_to_option_["LOGISTIC"] = ""; diff --git a/tensorflow/lite/g3doc/tf_ops_compatibility.md b/tensorflow/lite/g3doc/tf_ops_compatibility.md index dc6ba8a463..d20320a3b5 100644 --- a/tensorflow/lite/g3doc/tf_ops_compatibility.md +++ b/tensorflow/lite/g3doc/tf_ops_compatibility.md @@ -373,17 +373,6 @@ outputs: { } ``` -**ABS** - -``` -inputs { - 0: tensor -} -outputs: { - 0: result of computing element-wise absolute value of the input tensor -} -``` - **FULLY_CONNECTED** ``` diff --git a/tensorflow/lite/kernels/BUILD b/tensorflow/lite/kernels/BUILD index f66f69870f..71d06ba4d7 100644 --- a/tensorflow/lite/kernels/BUILD +++ b/tensorflow/lite/kernels/BUILD @@ -158,7 +158,6 @@ cc_library( cc_library( name = "builtin_op_kernels", srcs = [ - "abs.cc", "activations.cc", "add.cc", "arg_min_max.cc", @@ -601,22 +600,6 @@ tf_cc_test( ], ) -tf_cc_test( - name = "abs_test", - size = "small", - srcs = ["abs_test.cc"], - tags = [ - "no_oss", - "tflite_not_portable_ios", - ], - deps = [ - ":builtin_ops", - "//tensorflow/lite:framework", - "//tensorflow/lite/kernels:test_util", - "@com_google_googletest//:gtest", - ], -) - tf_cc_test( name = "ceil_test", size = "small", diff --git a/tensorflow/lite/kernels/abs.cc b/tensorflow/lite/kernels/abs.cc deleted file mode 100644 index b44f9de630..0000000000 --- a/tensorflow/lite/kernels/abs.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "tensorflow/lite/c/c_api_internal.h" -#include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" -#include "tensorflow/lite/kernels/internal/tensor.h" -#include "tensorflow/lite/kernels/kernel_util.h" - -namespace tflite { -namespace ops { -namespace builtin { -namespace abs { - -constexpr int kInputTensor = 0; -constexpr int kOutputTensor = 0; - -TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { - const TfLiteTensor* input = GetInput(context, node, kInputTensor); - TfLiteTensor* output = GetOutput(context, node, kOutputTensor); - TF_LITE_ENSURE_EQ(context, NumInputs(node), 1); - TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1); - TF_LITE_ENSURE_EQ(context, input->type, kTfLiteFloat32); - output->type = input->type; - TfLiteIntArray* output_size = TfLiteIntArrayCopy(input->dims); - return context->ResizeTensor(context, output, output_size); -} - -TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { - const TfLiteTensor* input = GetInput(context, node, kInputTensor); - TfLiteTensor* output = GetOutput(context, node, kOutputTensor); - - optimized_ops::Abs(GetTensorShape(input), GetTensorData(input), - GetTensorShape(output), GetTensorData(output)); - - return kTfLiteOk; -} -} // namespace abs - -TfLiteRegistration* Register_ABS() { - static TfLiteRegistration r = {/*init=*/nullptr, - /*free=*/nullptr, abs::Prepare, abs::Eval}; - return &r; -} - -} // namespace builtin -} // namespace ops -} // namespace tflite diff --git a/tensorflow/lite/kernels/abs_test.cc b/tensorflow/lite/kernels/abs_test.cc deleted file mode 100644 index 5e3f95c43a..0000000000 --- a/tensorflow/lite/kernels/abs_test.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include -#include "tensorflow/lite/interpreter.h" -#include "tensorflow/lite/kernels/register.h" -#include "tensorflow/lite/kernels/test_util.h" -#include "tensorflow/lite/model.h" - -namespace tflite { -namespace { - -using ::testing::ElementsAreArray; - -class AbsOpModel : public SingleOpModel { - public: - AbsOpModel(std::initializer_list input_shape, TensorType input_type) { - input_ = AddInput(TensorType_FLOAT32); - output_ = AddOutput(TensorType_FLOAT32); - SetBuiltinOp(BuiltinOperator_ABS, BuiltinOptions_NONE, 0); - BuildInterpreter({ - input_shape, - }); - } - - int input() { return input_; } - - std::vector GetOutput() { return ExtractVector(output_); } - std::vector GetOutputShape() { return GetTensorShape(output_); } - - private: - int input_; - int output_; -}; - -TEST(AbsOpTest, SingleDim) { - AbsOpModel model({2}, TensorType_FLOAT32); - model.PopulateTensor(model.input(), {8.5, -2.0}); - model.Invoke(); - EXPECT_THAT(model.GetOutput(), ElementsAreArray({8.5, 2.0})); - EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2})); -} - -TEST(AbsOpTest, MultiDims) { - AbsOpModel model({2, 1, 1, 5}, TensorType_FLOAT32); - model.PopulateTensor(model.input(), { - 0.0001, - 8.0001, - 0.9999, - 9.9999, - 0.5, - -0.0001, - -8.0001, - -0.9999, - -9.9999, - -0.5, - }); - model.Invoke(); - EXPECT_THAT(model.GetOutput(), - ElementsAreArray({ - 0.0001, - 8.0001, - 0.9999, - 9.9999, - 0.5, - 0.0001, - 8.0001, - 0.9999, - 9.9999, - 0.5, - })); - EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); -} - -} // namespace -} // namespace tflite - -int main(int argc, char** argv) { - ::tflite::LogToStderr(); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h index c24b7faa21..a76649f934 100644 --- a/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h +++ b/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h @@ -1746,12 +1746,6 @@ inline void Ceil(const float* input_data, const Dims<4>& input_dims, output_data); } -inline void Abs(const float* input_data, const Dims<4>& input_dims, - float* output_data, const Dims<4>& output_dims) { - Abs(DimsToShape(input_dims), input_data, DimsToShape(output_dims), - output_data); -} - inline void ResizeBilinear(const float* input_data, const Dims<4>& input_dims, const int32* output_size_data, const Dims<4>& output_size_dims, float* output_data, diff --git a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h index 7f7296ae97..0bd779bf3a 100644 --- a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h +++ b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h @@ -4906,14 +4906,6 @@ inline void Ceil(const RuntimeShape& input_shape, const float* input_data, output_map.array() = Eigen::ceil(input_map.array()); } -inline void Abs(const RuntimeShape& input_shape, const float* input_data, - const RuntimeShape& output_shape, float* output_data) { - gemmlowp::ScopedProfilingLabel label("Abs"); - auto input_map = MapAsVector(input_data, input_shape); - auto output_map = MapAsVector(output_data, output_shape); - output_map.array() = Eigen::abs(input_map.array()); -} - #ifdef USE_NEON inline void ResizeBilinearKernel(const float* input_ptr, int32 depth, float scale, float* output_ptr) { diff --git a/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h b/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h index 30bb92c8b3..431e2413e8 100644 --- a/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h +++ b/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h @@ -1889,12 +1889,6 @@ inline void Ceil(const float* input_data, const Dims<4>& input_dims, output_data); } -inline void Abs(const float* input_data, const Dims<4>& input_dims, - float* output_data, const Dims<4>& output_dims) { - Abs(DimsToShape(input_dims), input_data, DimsToShape(output_dims), - output_data); -} - template inline void ResizeBilinear(const T* input_data, const Dims<4>& input_dims, const int32* output_size_data, diff --git a/tensorflow/lite/kernels/internal/reference/reference_ops.h b/tensorflow/lite/kernels/internal/reference/reference_ops.h index 133a455e9e..6b8d817ca1 100644 --- a/tensorflow/lite/kernels/internal/reference/reference_ops.h +++ b/tensorflow/lite/kernels/internal/reference/reference_ops.h @@ -3050,16 +3050,6 @@ inline void Ceil(const RuntimeShape& input_shape, const float* input_data, } } -inline void Abs(const RuntimeShape& input_shape, const float* input_data, - const RuntimeShape& output_shape, float* output_data) { - const int flat_size = MatchingFlatSize(input_shape, output_shape); - - for (int i = 0; i < flat_size; i++) { - int offset = i; - output_data[offset] = std::fabs(input_data[offset]); - } -} - template inline void Gather(const tflite::GatherParams& op_params, const RuntimeShape& input_shape, const T* input_data, diff --git a/tensorflow/lite/kernels/register.cc b/tensorflow/lite/kernels/register.cc index caf61e9003..47ae934c4b 100644 --- a/tensorflow/lite/kernels/register.cc +++ b/tensorflow/lite/kernels/register.cc @@ -95,7 +95,6 @@ TfLiteRegistration* Register_LESS(); TfLiteRegistration* Register_LESS_EQUAL(); TfLiteRegistration* Register_FLOOR(); TfLiteRegistration* Register_CEIL(); -TfLiteRegistration* Register_ABS(); TfLiteRegistration* Register_TILE(); TfLiteRegistration* Register_NEG(); TfLiteRegistration* Register_SUM(); @@ -238,7 +237,6 @@ BuiltinOpResolver::BuiltinOpResolver() { AddBuiltin(BuiltinOperator_LESS_EQUAL, Register_LESS_EQUAL()); AddBuiltin(BuiltinOperator_FLOOR, Register_FLOOR()); AddBuiltin(BuiltinOperator_CEIL, Register_CEIL()); - AddBuiltin(BuiltinOperator_ABS, Register_ABS()); AddBuiltin(BuiltinOperator_NEG, Register_NEG()); AddBuiltin(BuiltinOperator_SELECT, Register_SELECT()); AddBuiltin(BuiltinOperator_SLICE, Register_SLICE()); diff --git a/tensorflow/lite/nnapi/NeuralNetworksShim.h b/tensorflow/lite/nnapi/NeuralNetworksShim.h index 037d364c3b..82c5840952 100644 --- a/tensorflow/lite/nnapi/NeuralNetworksShim.h +++ b/tensorflow/lite/nnapi/NeuralNetworksShim.h @@ -144,7 +144,6 @@ enum { ANEURALNETWORKS_SUB = 36, ANEURALNETWORKS_TRANSPOSE = 37, ANEURALNETWORKS_CEIL = 38, - ANEURALNETWORKS_ABS = 39, }; /** diff --git a/tensorflow/lite/nnapi_delegate.cc b/tensorflow/lite/nnapi_delegate.cc index 6da803ce7b..dfbb4813ad 100644 --- a/tensorflow/lite/nnapi_delegate.cc +++ b/tensorflow/lite/nnapi_delegate.cc @@ -492,9 +492,6 @@ TfLiteStatus AddOpsAndParams( case tflite::BuiltinOperator_CEIL: nn_op_type = ANEURALNETWORKS_CEIL; break; - case tflite::BuiltinOperator_ABS: - nn_op_type = ANEURALNETWORKS_ABS; - break; case tflite::BuiltinOperator_LOGISTIC: nn_op_type = ANEURALNETWORKS_LOGISTIC; break; diff --git a/tensorflow/lite/testing/generate_examples.py b/tensorflow/lite/testing/generate_examples.py index 825873a884..1dea01d59b 100644 --- a/tensorflow/lite/testing/generate_examples.py +++ b/tensorflow/lite/testing/generate_examples.py @@ -3047,32 +3047,6 @@ def make_ceil_tests(zip_path): make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) -def make_abs_tests(zip_path): - """Make a set of tests to do abs.""" - - test_parameters = [{ - "input_dtype": [tf.float32], - "input_shape": [[1], [1, 2], [5, 6, 7, 8], [3, 4, 5, 6]], - }] - - def build_graph(parameters): - """Build the abs op testing graph.""" - input_value = tf.placeholder( - dtype=parameters["input_dtype"], - name="input1", - shape=parameters["input_shape"]) - out = tf.abs(input_value) - return [input_value], [out] - - def build_inputs(parameters, sess, inputs, outputs): - input_value = create_tensor_data(parameters["input_dtype"], - parameters["input_shape"]) - return [input_value], sess.run( - outputs, feed_dict={inputs[0]: input_value}) - - make_zip_of_tests(zip_path, test_parameters, build_graph, build_inputs) - - def make_neg_tests(zip_path): """Make a set of tests to do neg.""" diff --git a/tensorflow/lite/toco/export_tensorflow.cc b/tensorflow/lite/toco/export_tensorflow.cc index 9dfeaad164..816cb9bc28 100644 --- a/tensorflow/lite/toco/export_tensorflow.cc +++ b/tensorflow/lite/toco/export_tensorflow.cc @@ -1215,16 +1215,6 @@ void ConvertCeilOperator(const Model& model, const CeilOperator& src_op, (*ceil_op->mutable_attr())["T"].set_type(DT_FLOAT); } -void ConvertAbsOperator(const Model& model, const AbsOperator& src_op, - GraphDef* tensorflow_graph) { - tensorflow::NodeDef* abs_op = tensorflow_graph->add_node(); - abs_op->set_op("Abs"); - abs_op->set_name(src_op.outputs[0]); - CHECK_EQ(src_op.inputs.size(), 1); - *abs_op->add_input() = src_op.inputs[0]; - (*abs_op->mutable_attr())["T"].set_type(DT_FLOAT); -} - void ConvertGatherOperator(const Model& model, const GatherOperator& src_op, GraphDef* tensorflow_graph) { tensorflow::NodeDef* gather_op = tensorflow_graph->add_node(); @@ -2192,9 +2182,6 @@ void ConvertOperator(const Model& model, const Operator& src_op, } else if (src_op.type == OperatorType::kCeil) { ConvertCeilOperator(model, static_cast(src_op), tensorflow_graph); - } else if (src_op.type == OperatorType::kAbs) { - ConvertAbsOperator(model, static_cast(src_op), - tensorflow_graph); } else if (src_op.type == OperatorType::kGather) { ConvertGatherOperator(model, static_cast(src_op), tensorflow_graph); diff --git a/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc b/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc index c6c7681c03..0aae68c9c4 100644 --- a/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc +++ b/tensorflow/lite/toco/graph_transformations/propagate_fixed_sizes.cc @@ -1870,7 +1870,6 @@ void ProcessMirrorPadOperator(Model* model, MirrorPadOperator* op) { case OperatorType::kCast: case OperatorType::kFloor: case OperatorType::kCeil: - case OperatorType::kAbs: case OperatorType::kExp: case OperatorType::kSin: case OperatorType::kLogicalAnd: diff --git a/tensorflow/lite/toco/graph_transformations/reorder_elementwise_unary.cc b/tensorflow/lite/toco/graph_transformations/reorder_elementwise_unary.cc index 90e64816c8..98105d384e 100644 --- a/tensorflow/lite/toco/graph_transformations/reorder_elementwise_unary.cc +++ b/tensorflow/lite/toco/graph_transformations/reorder_elementwise_unary.cc @@ -29,7 +29,6 @@ namespace { bool IsElementwiseOperator(OperatorType optype) { switch (optype) { - case OperatorType::kAbs: case OperatorType::kCast: case OperatorType::kCeil: case OperatorType::kExp: diff --git a/tensorflow/lite/toco/import_tensorflow.cc b/tensorflow/lite/toco/import_tensorflow.cc index de8ae19a71..53defed6cb 100644 --- a/tensorflow/lite/toco/import_tensorflow.cc +++ b/tensorflow/lite/toco/import_tensorflow.cc @@ -1505,20 +1505,6 @@ tensorflow::Status ConvertCeilOperator( return tensorflow::Status::OK(); } -tensorflow::Status ConvertAbsOperator( - const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, - Model* model) { - CHECK_EQ(node.op(), "Abs"); - TF_QCHECK_OK(CheckInputsCount(node, tf_import_flags, 1)); - const auto data_type = GetDataTypeAttr(node, "T"); - CHECK(data_type == DT_FLOAT); - auto* op = new AbsOperator; - op->inputs.push_back(node.input(0)); - op->outputs.push_back(node.name()); - model->operators.emplace_back(op); - return tensorflow::Status::OK(); -} - tensorflow::Status ConvertGatherOperator( const NodeDef& node, const TensorFlowImportFlags& tf_import_flags, Model* model) { diff --git a/tensorflow/lite/toco/model.h b/tensorflow/lite/toco/model.h index 69c6d7608a..c5cb215114 100644 --- a/tensorflow/lite/toco/model.h +++ b/tensorflow/lite/toco/model.h @@ -37,7 +37,6 @@ using tflite::QuantizationParams; enum class OperatorType : uint8 { kNone, // General-purpose neural network operators. - kAbs, kAdd, kAddN, kAveragePool, @@ -1670,16 +1669,6 @@ struct CeilOperator : Operator { CeilOperator() : Operator(OperatorType::kCeil) {} }; -// Abs operator. -// -// Inputs: -// inputs[0]: required: the input array -// -// TensorFlow equivalent: Abs -struct AbsOperator : Operator { - AbsOperator() : Operator(OperatorType::kAbs) {} -}; - // Gather operator. It gathers slices from params according to indices. // Only 1-D indices are supported at the moment. // diff --git a/tensorflow/lite/toco/tflite/operator.cc b/tensorflow/lite/toco/tflite/operator.cc index 2122d04958..dd47808046 100644 --- a/tensorflow/lite/toco/tflite/operator.cc +++ b/tensorflow/lite/toco/tflite/operator.cc @@ -1651,8 +1651,6 @@ std::vector> BuildOperatorList( MakeUnique>("FLOOR", OperatorType::kFloor)); ops.push_back( MakeUnique>("CEIL", OperatorType::kCeil)); - ops.push_back( - MakeUnique>("ABS", OperatorType::kAbs)); ops.push_back( MakeUnique>("RELU", OperatorType::kRelu)); ops.push_back(MakeUnique>( diff --git a/tensorflow/lite/toco/tflite/operator_test.cc b/tensorflow/lite/toco/tflite/operator_test.cc index e284619903..ba713edcb6 100644 --- a/tensorflow/lite/toco/tflite/operator_test.cc +++ b/tensorflow/lite/toco/tflite/operator_test.cc @@ -115,7 +115,6 @@ TEST_F(OperatorTest, SimpleOperators) { OperatorType::kDequantize); CheckSimpleOperator("FLOOR", OperatorType::kFloor); CheckSimpleOperator("CEIL", OperatorType::kCeil); - CheckSimpleOperator("ABS", OperatorType::kAbs); CheckSimpleOperator("RELU", OperatorType::kRelu); CheckSimpleOperator("RELU_N1_TO_1", OperatorType::kRelu1); CheckSimpleOperator("RELU6", OperatorType::kRelu6); diff --git a/tensorflow/lite/toco/tooling_util.cc b/tensorflow/lite/toco/tooling_util.cc index 0887dca9b5..9d6f554c59 100644 --- a/tensorflow/lite/toco/tooling_util.cc +++ b/tensorflow/lite/toco/tooling_util.cc @@ -386,7 +386,6 @@ const char* OperatorTypeName(OperatorType type) { HANDLE_OPERATORTYPENAME_CASE(Cast) HANDLE_OPERATORTYPENAME_CASE(Floor) HANDLE_OPERATORTYPENAME_CASE(Ceil) - HANDLE_OPERATORTYPENAME_CASE(Abs) HANDLE_OPERATORTYPENAME_CASE(Gather) HANDLE_OPERATORTYPENAME_CASE(ResizeBilinear) HANDLE_OPERATORTYPENAME_CASE(SpaceToBatchND) -- GitLab From f0ffba31ed278e2ada5537b54575ea05af1091a9 Mon Sep 17 00:00:00 2001 From: Siju Date: Thu, 13 Dec 2018 10:49:46 +0530 Subject: [PATCH 0079/1765] Update output_init_files_test.py --- tensorflow/python/tools/api/generator/output_init_files_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/python/tools/api/generator/output_init_files_test.py b/tensorflow/python/tools/api/generator/output_init_files_test.py index ab154af910..7013f007e5 100644 --- a/tensorflow/python/tools/api/generator/output_init_files_test.py +++ b/tensorflow/python/tools/api/generator/output_init_files_test.py @@ -45,7 +45,7 @@ def _get_modules(package, attr_name, constants_attr_name): API constant names. Returns: - Set of TensorFow API modules. + Set of TensorFlow API modules. """ modules = set() # TODO(annarev): split up the logic in create_python_api.py so that -- GitLab From 9d5ac5c511dca4a959014b6f9882309bc9bd703f Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Thu, 13 Dec 2018 22:40:14 +0100 Subject: [PATCH 0080/1765] Fix typos --- tensorflow/python/data/experimental/ops/grouping.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow/python/data/experimental/ops/grouping.py b/tensorflow/python/data/experimental/ops/grouping.py index 71e4b3391f..2eef36d0c8 100644 --- a/tensorflow/python/data/experimental/ops/grouping.py +++ b/tensorflow/python/data/experimental/ops/grouping.py @@ -162,8 +162,8 @@ def bucket_by_sequence_length(element_length_func, no_padding: `bool`, indicates whether to pad the batch features (features need to be either of type `tf.SparseTensor` or of same shape). drop_remainder: (Optional.) A `tf.bool` scalar `tf.Tensor`, representing - whether the last batch should be dropped in the case its has fewer than - batch_size` elements; the default behavior is not to drop the smaller + whether the last batch should be dropped in the case it has fewer than + `batch_size` elements; the default behavior is not to drop the smaller batch. Returns: -- GitLab From a06497bce4e91b267850b8b82ee4fe684c01e94b Mon Sep 17 00:00:00 2001 From: Steve Lang Date: Fri, 14 Dec 2018 09:01:27 +1100 Subject: [PATCH 0081/1765] .numpy() was missing in code example: tf.add(1, 2).numpy() --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68d7e180d1..c512aeb06c 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ $ python ```python >>> import tensorflow as tf >>> tf.enable_eager_execution() ->>> tf.add(1, 2) +>>> tf.add(1, 2).numpy() 3 >>> hello = tf.constant('Hello, TensorFlow!') >>> hello.numpy() -- GitLab From c8c5f69e9a4d2424ba4cc603daebd4c24e5128d4 Mon Sep 17 00:00:00 2001 From: Asim Shankar Date: Thu, 13 Dec 2018 14:45:48 -0800 Subject: [PATCH 0082/1765] [Go]: Fixup paths to protocol buffers. Without this: go generate github.com/tensorflow/tensorflow/tensorflow/go/op would fail with: ../genop/internal/api_def_map.go:34:2: cannot find package "github.com/tensorflow/tensorflow/tensorflow/go/genop/internal/proto/tensorflow/core/framework_go_proto" in any of: /usr/local/go/src/github.com/tensorflow/tensorflow/tensorflow/go/genop/internal/proto/tensorflow/core/framework_go_proto (from $GOROOT) /go/src/github.com/tensorflow/tensorflow/tensorflow/go/genop/internal/proto/tensorflow/core/framework_go_proto (from $GOPATH) This breakage was probably introduced by https://github.com/tensorflow/tensorflow/pull/17262 --- tensorflow/go/genop/internal/api_def_map.go | 2 +- tensorflow/go/genop/internal/genop.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tensorflow/go/genop/internal/api_def_map.go b/tensorflow/go/genop/internal/api_def_map.go index 8600452b47..0bbd88b61c 100644 --- a/tensorflow/go/genop/internal/api_def_map.go +++ b/tensorflow/go/genop/internal/api_def_map.go @@ -31,7 +31,7 @@ import ( "unsafe" "github.com/golang/protobuf/proto" - pb "github.com/tensorflow/tensorflow/tensorflow/go/genop/internal/proto/tensorflow/core/framework_go_proto" + pb "github.com/tensorflow/tensorflow/tensorflow/go/genop/internal/proto/github.com/tensorflow/tensorflow/tensorflow/go/core/framework" ) // Encapsulates a collection of API definitions. diff --git a/tensorflow/go/genop/internal/genop.go b/tensorflow/go/genop/internal/genop.go index fb81631218..1c05715a1a 100644 --- a/tensorflow/go/genop/internal/genop.go +++ b/tensorflow/go/genop/internal/genop.go @@ -47,7 +47,7 @@ import ( "unsafe" "github.com/golang/protobuf/proto" - pb "github.com/tensorflow/tensorflow/tensorflow/go/genop/internal/proto/tensorflow/core/framework_go_proto" + pb "github.com/tensorflow/tensorflow/tensorflow/go/genop/internal/proto/github.com/tensorflow/tensorflow/tensorflow/go/core/framework" ) // GenerateFunctionsForRegisteredOps writes a Go source code file to w -- GitLab From 1674bd08ce0c49a75a0f01c18ef940fa012124a8 Mon Sep 17 00:00:00 2001 From: Ben Barsdell Date: Thu, 13 Dec 2018 15:09:54 -0800 Subject: [PATCH 0083/1765] [XLA:GPU] Add sm_75 to LLVM supported procs list - This is required to prevent fallback to the default sm version when running on GPUs with the Turing architecture. --- .../xla/service/gpu/llvm_gpu_backend/nvptx_backend_lib.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/nvptx_backend_lib.cc b/tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/nvptx_backend_lib.cc index bd53b90b42..eddaa877f2 100644 --- a/tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/nvptx_backend_lib.cc +++ b/tensorflow/compiler/xla/service/gpu/llvm_gpu_backend/nvptx_backend_lib.cc @@ -125,6 +125,7 @@ static string GetSmName(std::pair compute_capability) { {{6, 2}, 62}, {{7, 0}, 70}, {{7, 2}, 72}, + {{7, 5}, 75}, }); int sm_version = 30; auto it = m->find(compute_capability); -- GitLab From 4b63e8c3662d5890548d38bc3fd2fdd926ff15e0 Mon Sep 17 00:00:00 2001 From: Siju Date: Fri, 14 Dec 2018 08:35:11 +0530 Subject: [PATCH 0084/1765] Update custom_operators.md Documentation issue --- tensorflow/lite/g3doc/custom_operators.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/lite/g3doc/custom_operators.md b/tensorflow/lite/g3doc/custom_operators.md index 4a22d6a675..bb7fbd9cfd 100644 --- a/tensorflow/lite/g3doc/custom_operators.md +++ b/tensorflow/lite/g3doc/custom_operators.md @@ -137,7 +137,7 @@ operations instead of a single operator. ## Special TF Graph Attributes -When Toco convertes a TF graph into TFLite format, it makes some assumption +When Toco converts a TF graph into TFLite format, it makes some assumption about custom operations that might be not correct. In this case, the generated graph can be not executable. -- GitLab From c1fc5d5036d850be852ec473f32292ca973f5bed Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Thu, 13 Dec 2018 22:57:22 +0100 Subject: [PATCH 0085/1765] Rewrite grouping tests to be @parameterized tests --- .../data/experimental/kernel_tests/BUILD | 1 + .../bucket_by_sequence_length_test.py | 60 ++++++++++++------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/tensorflow/python/data/experimental/kernel_tests/BUILD b/tensorflow/python/data/experimental/kernel_tests/BUILD index d7ca5a70e4..897e949b0f 100644 --- a/tensorflow/python/data/experimental/kernel_tests/BUILD +++ b/tensorflow/python/data/experimental/kernel_tests/BUILD @@ -23,6 +23,7 @@ py_test( "//tensorflow/python/data/kernel_tests:test_base", "//tensorflow/python/data/ops:dataset_ops", "//third_party/py/numpy", + "@absl_py//absl/testing:parameterized", ], ) diff --git a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py index fab79619a0..bcb7ef9496 100644 --- a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py @@ -19,6 +19,8 @@ from __future__ import print_function import random +from absl.testing import parameterized + from tensorflow.python.data.experimental.ops import grouping from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops @@ -69,9 +71,13 @@ def _get_record_shape(sparse): return tensor_shape.TensorShape([None]) -class BucketBySequenceLengthTest(test_base.DatasetTestBase): +class BucketBySequenceLengthTest(test_base.DatasetTestBase, parameterized.TestCase): - def testBucketDropReminder(self): + @parameterized.named_parameters( + ("WithoutPadding", True), + ("WithPadding", False), + ) + def testBucketDropReminder(self, param_no_padding): boundaries = [10, 20, 30] batch_sizes = [10, 8, 4, 2] @@ -192,10 +198,13 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): .format(sorted(expected_lengths), sorted(generated_lengths))) - for no_padding in (True, False): - _test_bucket_by_padding(no_padding) + _test_bucket_by_padding(param_no_padding) - def testBucket(self): + @parameterized.named_parameters( + ("WithoutPadding", True), + ("WithPadding", False), + ) + def testBucket(self, param_no_padding): boundaries = [10, 20, 30] batch_sizes = [10, 8, 4, 2] @@ -251,8 +260,7 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): self.assertEqual(sorted(batch_sizes), sorted(batch_sizes_val)) self.assertEqual(sorted(lengths), sorted(lengths_val)) - for no_padding in (True, False): - _test_bucket_by_padding(no_padding) + _test_bucket_by_padding(param_no_padding) def testPadToBoundary(self): @@ -336,7 +344,11 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): self.assertAllEqual(batches[4], [[1, 1, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]) - def testTupleElements(self): + @parameterized.named_parameters( + ("WithoutPadding", True), + ("WithPadding", False), + ) + def testTupleElements(self, param_no_padding): def build_dataset(sparse): def _generator(): @@ -364,10 +376,13 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): self.assertEqual([None, None], shapes[0].as_list()) self.assertEqual([None], shapes[1].as_list()) - for no_padding in (True, False): - _test_tuple_elements_by_padding(no_padding) + _test_tuple_elements_by_padding(param_no_padding) - def testBucketSparse(self): + @parameterized.named_parameters( + ("DoDropRemainder", True), + ("DoNotDropRemainder", False), + ) + def testBucketSparse(self, param_drop_remainder): """Tests bucketing of sparse tensors (case where `no_padding` == True). Test runs on following dataset: @@ -435,18 +450,17 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase): all_sparse_tensors.add(sprs_tensor) return all_sparse_tensors - for drop_remainder in (True, False): - dataset = _build_dataset() - boundaries = range(min_len + bucket_size + 1, max_len, bucket_size) - dataset = dataset.apply(grouping.bucket_by_sequence_length( - _element_length_fn, - boundaries, - [batch_size] * (len(boundaries) + 1), - no_padding=True, - drop_remainder=drop_remainder)) - batches = _compute_batches(dataset) - expected_batches = _compute_expected_batches(drop_remainder) - self.assertEqual(batches, expected_batches) + dataset = _build_dataset() + boundaries = range(min_len + bucket_size + 1, max_len, bucket_size) + dataset = dataset.apply(grouping.bucket_by_sequence_length( + _element_length_fn, + boundaries, + [batch_size] * (len(boundaries) + 1), + no_padding=True, + drop_remainder=param_drop_remainder)) + batches = _compute_batches(dataset) + expected_batches = _compute_expected_batches(param_drop_remainder) + self.assertEqual(batches, expected_batches) if __name__ == "__main__": -- GitLab From 8db73e896985d043f24592abf405fed4c867aee8 Mon Sep 17 00:00:00 2001 From: Pavel Samolysov Date: Mon, 17 Dec 2018 18:32:45 +0300 Subject: [PATCH 0086/1765] [OpenMP] Fix undeclared identifier in eigen_support.cc When OpenMP is enabled, the following error occurs during a compilation of the `tensorflow/lite/kernels/eigen_support.cc` unit: tensorflow/lite/kernels/eigen_support.cc:42:23: error: use of undeclared identifier 'context' Eigen::setNbThreads(context->recommended_num_threads); The `SetEigenNbThreads` method already gets the number of threads as the `threads` parameter and doesn't need to calculate it using a method of the `context` variable, so the invocation of the `Eigen::setNbThreads` member must be changed a little bit. Signed-off-by: Pavel Samolysov --- tensorflow/lite/kernels/eigen_support.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/lite/kernels/eigen_support.cc b/tensorflow/lite/kernels/eigen_support.cc index bad5975a7c..e2a2c4aac9 100644 --- a/tensorflow/lite/kernels/eigen_support.cc +++ b/tensorflow/lite/kernels/eigen_support.cc @@ -39,7 +39,7 @@ void SetEigenNbThreads(int threads) { #if defined(EIGEN_HAS_OPENMP) // The global Eigen thread count is only used when OpenMP is enabled. As this // call causes problems with tsan, make it only when OpenMP is available. - Eigen::setNbThreads(context->recommended_num_threads); + Eigen::setNbThreads(threads); #endif // defined(EIGEN_HAS_OPENMP) } -- GitLab From 3eb35ec8372abc93a043146e55b936392c2ba54c Mon Sep 17 00:00:00 2001 From: Pete Warden Date: Mon, 17 Dec 2018 14:13:52 -0800 Subject: [PATCH 0087/1765] Delete test_ecm3531_binary.sh Causes a missing-copyright error on internal verification --- .../lite/experimental/micro/testing/test_ecm3531_binary.sh | 1 - 1 file changed, 1 deletion(-) delete mode 100755 tensorflow/lite/experimental/micro/testing/test_ecm3531_binary.sh diff --git a/tensorflow/lite/experimental/micro/testing/test_ecm3531_binary.sh b/tensorflow/lite/experimental/micro/testing/test_ecm3531_binary.sh deleted file mode 100755 index 6d7af08d9f..0000000000 --- a/tensorflow/lite/experimental/micro/testing/test_ecm3531_binary.sh +++ /dev/null @@ -1 +0,0 @@ -echo "Testing should be performed on the ECM3531 EVB" -- GitLab From e09f4254fb418fc18075b9cb67e642635b5855f9 Mon Sep 17 00:00:00 2001 From: wenxizhu Date: Tue, 18 Dec 2018 14:00:13 +0800 Subject: [PATCH 0088/1765] Bug fix for reduandant transpose removal: 1. this bug is a last minute check-in to replace "CHECK()" with "DCHECK()", however it turns out that "CHECK()" and "DCHECK()" are not functional equivalent; 2. unlike "CHECK()" whose expression will always be excuted, the expression in "DCHECK()" will not be executed in release mode. This causes dangling pointer failures. 3. to fix this bug, we should check the result of the expression instead of the expression itself. --- tensorflow/core/graph/mkl_layout_pass.cc | 10 +++++----- tensorflow/core/graph/mkl_layout_pass_test.cc | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tensorflow/core/graph/mkl_layout_pass.cc b/tensorflow/core/graph/mkl_layout_pass.cc index 3c868dc222..56c31d5c84 100644 --- a/tensorflow/core/graph/mkl_layout_pass.cc +++ b/tensorflow/core/graph/mkl_layout_pass.cc @@ -1025,7 +1025,8 @@ class MklLayoutRewritePass : public GraphOptimizationPass { e->dst_input() == kPermTensorIndex) { // we find the "perm" node, now try to retrieve its value. const TensorProto* proto = nullptr; - DCHECK(GetNodeAttr(perm_node->def(), "value", &proto).ok()); + bool perm_has_value_attr = GetNodeAttr(perm_node->def(), "value", &proto).ok(); + DCHECK(perm_has_value_attr); DataType type; GetNodeAttr(perm_node->def(), "dtype", &type); @@ -3110,8 +3111,9 @@ Status MklLayoutRewritePass::FuseTransposeMklOpTranspose( for (const Edge* e : transpose_to_nchw->out_edges()) { if (!e->IsControlEdge()) { const int kTransposeWithMklOpOutputSlot = 0; - DCHECK((*g)->AddEdge(new_node, kTransposeWithMklOpOutputSlot, e->dst(), - e->dst_input())); + bool succ_add_edge = (*g)->AddEdge(new_node, kTransposeWithMklOpOutputSlot, e->dst(), + e->dst_input()); + DCHECK(succ_add_edge); } } @@ -3312,7 +3314,6 @@ bool MklLayoutRewritePass::RunPass(std::unique_ptr* g) { DumpGraph("After running MklLayoutRewritePass(NodeMerge)", &**g); -#ifdef ENABLE_TRANSPOSE_OPTIMIZATION order.clear(); GetReversePostOrder(**g, &order); // This will give us topological sort. for (Node* n : order) { @@ -3334,7 +3335,6 @@ bool MklLayoutRewritePass::RunPass(std::unique_ptr* g) { } } DumpGraph("After running MklLayoutRewritePass(NodeFusion)", &**g); -#endif // ENABLE_TRANSPOSE_OPTIMIZATION order.clear(); GetReversePostOrder(**g, &order); // This will give us topological sort. diff --git a/tensorflow/core/graph/mkl_layout_pass_test.cc b/tensorflow/core/graph/mkl_layout_pass_test.cc index 197ec0c4ae..0853907322 100644 --- a/tensorflow/core/graph/mkl_layout_pass_test.cc +++ b/tensorflow/core/graph/mkl_layout_pass_test.cc @@ -707,7 +707,7 @@ TEST_F(MklLayoutPassTest, NodeMerge_PadWithConv2D_Negative) { "C:control->DMT/_0:control;C:control->DMT/_1:control;" "D->E:1;DMT/_0->E:2;DMT/_1->E:3;E->Z;Y->Z:1"); } -#ifdef ENABLE_TRANSPOSE_OPTIMIZATION + TEST_F(MklLayoutPassTest, NodeMerge_TransposeConv2DTranspose_Positive) { InitGraph( "node { name: 'Input0' op: 'Input'}" @@ -1016,7 +1016,6 @@ TEST_F(MklLayoutPassTest, NodeMerge_TransposeConv2DTranspose_Negative) { "Transpose0:control->DMT/" "_1:control;Transpose1->Relu;Transpose1:control->DMT/_2:control"); } -#endif // ENABLE_TRANSPOSE_OPTIMIZATION ///////////////////////////////////////////////////////////////////// // Unit tests related to rewriting node to Mkl node -- GitLab From 7b7e7896f81f900a2636313fcc8700f0abc7b3c7 Mon Sep 17 00:00:00 2001 From: "candy.dc" Date: Tue, 18 Dec 2018 15:48:11 +0800 Subject: [PATCH 0089/1765] Fix-Bug: CHECK_GT(2^32, 0) return false --- tensorflow/core/platform/default/logging.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tensorflow/core/platform/default/logging.h b/tensorflow/core/platform/default/logging.h index bb8735ed32..99dd6de141 100644 --- a/tensorflow/core/platform/default/logging.h +++ b/tensorflow/core/platform/default/logging.h @@ -240,8 +240,7 @@ string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) { if (TF_PREDICT_FALSE(v2 < 0)) { \ return ::tensorflow::internal::MakeCheckOpString(v1, v2, exprtext); \ } \ - const size_t uval = (size_t)((unsigned)v1); \ - return name##Impl(uval, v2, exprtext); \ + return name##Impl(v1, v2, exprtext); \ } \ inline string* name##Impl(const int v1, const size_t v2, \ const char* exprtext) { \ -- GitLab From 64fa6b3108633fdfb0efbe8398cbf69b2a156cc7 Mon Sep 17 00:00:00 2001 From: Arpit Shah Date: Tue, 18 Dec 2018 08:18:25 -0600 Subject: [PATCH 0090/1765] Changed copy right headers --- .../examples/micro_speech/CMSIS/hanning.cc | 28 +++++++++---------- .../examples/micro_speech/CMSIS/hanning.h | 28 +++++++++---------- .../examples/micro_speech/CMSIS/sin_1k.cc | 28 +++++++++---------- .../examples/micro_speech/CMSIS/sin_1k.h | 28 +++++++++---------- .../apollo3/captured_data_to_wav.py | 13 +++++---- .../micro_speech/apollo3/compare_1k.py | 13 +++++---- .../micro_speech/apollo3/preprocessor_1k.cc | 7 ++--- .../apollo3/preprocessor_1k_cmsis_test.cmd | 15 +++------- .../apollo3/preprocessor_1k_micro_test.cmd | 15 +++------- .../apollo3/preprocessor_test.cmd | 13 ++------- .../apollo3/pushbutton_cmsis_scores.cmd | 15 +++------- .../apollo3/pushbutton_cmsis_voice.cmd | 15 +++++----- .../micro_speech/apollo3/pushbutton_main.c | 7 ++--- .../micro_speech/apollo3/pushbutton_test.cc | 7 ++--- 14 files changed, 99 insertions(+), 133 deletions(-) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc index 32aa5b2b7e..deb30ffd88 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc @@ -1,17 +1,17 @@ -/* SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h" diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h index 0982f33c48..e7d9c5c858 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h @@ -1,17 +1,17 @@ -/* SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ #ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_HANNING_H_ #define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_HANNING_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc index be66e5f548..3523d3ab76 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc @@ -1,17 +1,17 @@ -/* SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h" diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h index 645e262aa1..653a6f5830 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h @@ -1,17 +1,17 @@ -/* SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ #ifndef TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIN_1K_H_ #define TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_SIN_1K_H_ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/captured_data_to_wav.py b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/captured_data_to_wav.py index 84b6259452..a04b849656 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/captured_data_to_wav.py +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/captured_data_to_wav.py @@ -1,16 +1,17 @@ -# SPDX-License-Identifier: Apache-2.0 +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. # -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# ============================================================================== import numpy as np import re diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/compare_1k.py b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/compare_1k.py index 9c91560d50..93fb36fd01 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/compare_1k.py +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/compare_1k.py @@ -1,16 +1,17 @@ -# SPDX-License-Identifier: Apache-2.0 +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. # -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# ============================================================================== import numpy as np import re diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc index 31fae1f2dc..5246e00296 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc @@ -1,8 +1,3 @@ -/* This file is a modification of the Tensorflow Micro Lite file preprocessor.cc - * We have retained the original copyright and header information, in - * accordance with the Apache 2.0 license terms. - */ - /* Copyright 2018 The TensorFlow Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +/* This file is a modification of the Tensorflow Micro Lite file preprocessor.cc */ + #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h" #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd index 0f701660a8..5cc7a82c05 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd @@ -1,16 +1,9 @@ -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# # Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# ============================================================================== # Needs to be compiled with -O0 file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_1k_cmsis_test @@ -37,7 +30,7 @@ commands dump verilog memory cmsis_power_avg.txt output output+42 c end -break preprocessor_1k.cc:53 +break preprocessor_1k.cc:50 commands print count end diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_micro_test.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_micro_test.cmd index 35c602d78c..dc9cd4f0a4 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_micro_test.cmd +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_micro_test.cmd @@ -1,16 +1,9 @@ -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# # Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# ============================================================================== # Needs to be run when compiled with -O0 file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_1k_micro_test @@ -25,7 +18,7 @@ dump verilog value micro_power.txt power_spectrum dump verilog memory micro_power_avg.txt output output+42 c end -break preprocessor_1k.cc:53 +break preprocessor_1k.cc:50 commands print count end diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_test.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_test.cmd index 4458af17d6..bd2048e80a 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_test.cmd +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_test.cmd @@ -1,16 +1,9 @@ -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# # Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# ============================================================================== file ../../gen/apollo3evb_cortex-m4/bin/preprocessor_test target remote localhost:2331 diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd index db299f7277..e14ea2d83c 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd @@ -1,22 +1,15 @@ -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# www.apache.org/licenses/LICENSE-2.0 -# # Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# ============================================================================== file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test target remote localhost:2331 load ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test monitor reset -break pushbutton_main.c:325 +break pushbutton_main.c:322 commands printf "Silence score: %d\n", g_silence_score printf "Unknown score: %d\n", g_unknown_score diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd index 8cd1a7e90e..b49f9d2d92 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd @@ -1,22 +1,23 @@ -# SPDX-License-Identifier: Apache-2.0 +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. # -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# ============================================================================== file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test target remote localhost:2331 load ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test monitor reset -break pushbutton_main.c:316 +break pushbutton_main.c:313 commands dump verilog value captured_data.txt captured_data c diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c index 82337e63da..d06c81be66 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c @@ -1,8 +1,3 @@ -/* This file is a modification of the Tensorflow Micro Lite file _main.c - * We have retained the original copyright and header information, in - * accordance with the Apache 2.0 license terms. - */ - /* Copyright 2018 The TensorFlow Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +/* This file is a modification of the Tensorflow Micro Lite file _main.c */ + #include #include "am_mcu_apollo.h" // Defines AM_CMSIS_REGS #include "am_bsp.h" diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc index ce4de4dbd8..47f273c511 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc @@ -1,8 +1,3 @@ -/* This file is a modification of the Tensorflow Micro Lite file micro_speech_test.cc - * We have retained the original copyright and header information, in - * accordance with the Apache 2.0 license terms. - */ - /* Copyright 2018 The TensorFlow Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +/* This file is a modification of the Tensorflow Micro Lite file micro_speech_test.cc */ + #include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" -- GitLab From 26dbfbd5bba462cb8820566ec2659f221be2968d Mon Sep 17 00:00:00 2001 From: Arpit Shah Date: Tue, 18 Dec 2018 13:54:00 -0600 Subject: [PATCH 0091/1765] Moved copy right files out of repo --- .../examples/micro_speech/CMSIS/README.md | 7 +- .../CMSIS/arm_cmplx_mag_squared_q10p6.c | 141 - .../CMSIS/arm_cmplx_mag_squared_q10p6.h | 33 - .../micro_speech/CMSIS/preprocessor.cc | 2 +- .../examples/micro_speech/apollo3/README.md | 5 +- .../examples/micro_speech/apollo3/apollo3.h | 23332 ---------------- .../micro_speech/apollo3/preprocessor_1k.cc | 4 +- .../micro_speech/apollo3/system_apollo3.c | 116 - .../micro_speech/apollo3/system_apollo3.h | 72 - .../micro/tools/make/download_dependencies.sh | 5 + .../make/targets/apollo3evb_makefile.inc | 12 +- 11 files changed, 24 insertions(+), 23705 deletions(-) delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.c delete mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h delete mode 100755 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h delete mode 100755 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c delete mode 100755 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/README.md b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/README.md index fde48374c8..6b9339df36 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/README.md +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/README.md @@ -1,10 +1,13 @@ # Description of files -* **arm_cmplx_mag_squared_q10p6.c**: Modified version of the ARM CMSIS function [arm_cmplx_mag_squared.c](http://arm-software.github.io/CMSIS_5/DSP/html/group__cmplx__mag__squared.html#ga45537f576102d960d467eb722b8431f2). The modification is that we have changed the amount of right-shift to make sure our data is in the correct range. We redistribute because the original content was created with the Apache 2.0 license. -* **arm_cmplx_mag_squared_q10p6.h**: Header file for arm_cmplx_mag_squared_q10p6.c * **create_constants.py**: Python file used to create hanning.cc, hanning.h, sin_1k.cc, and sin_1k.h * **hanning.cc**: Precomputed [Hann window](https://en.wikipedia.org/wiki/Hann_function) for use in the preprocessor. This file is created in ../create_constants.py * **hanning.h**: Header file fro hanning.cc * **preprocessor.cc**: CMSIS version of the preprocessor * **sin_1k.cc**: A 1 kHZ sinusoid used for comparing the CMSIS preprocessor with the Micro-Lite fixed_point preprocessor * **sin_1k.h**: Header file for sin_1k.cc + +# Description of externally downloaded files in ../CMSIS_ext + +* **arm_cmplx_mag_squared_q10p6.c**: Modified version of the ARM CMSIS function [arm_cmplx_mag_squared.c](http://arm-software.github.io/CMSIS_5/DSP/html/group__cmplx__mag__squared.html#ga45537f576102d960d467eb722b8431f2). The modification is that we have changed the amount of right-shift to make sure our data is in the correct range. We redistribute because the original content was created with the Apache 2.0 license. +* **arm_cmplx_mag_squared_q10p6.h**: Header file for arm_cmplx_mag_squared_q10p6.c diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.c b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.c deleted file mode 100644 index b050f6048d..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.c +++ /dev/null @@ -1,141 +0,0 @@ -/* This file is a modification of the ARM CMSIS library file arm_cmplx_mag_squared_q15.c - * We have retained the original copyright and header information, in - * accordance with the Apache 2.0 license terms. - */ - -/* ---------------------------------------------------------------------- - * Project: CMSIS DSP Library - * Title: arm_cmplx_mag_squared_q15.c - * Description: Q15 complex magnitude squared - * - * $Date: 27. January 2017 - * $Revision: V.1.5.1 - * - * Target Processor: Cortex-M cores - * -------------------------------------------------------------------- */ -/* - * Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "arm_math.h" - -/** - * @ingroup groupCmplxMath - */ - -/** - * @addtogroup cmplx_mag_squared - * @{ - */ - -/** - * @brief Q15 complex magnitude squared - * @param *pSrc points to the complex input vector - * @param *pDst points to the real output vector - * @param numSamples number of complex samples in the input vector - * @return none. - * - * Scaling and Overflow Behavior: - * \par - * The function implements 1.15 by 1.15 multiplications and finally output is converted into 3.13 format. - */ - -void arm_cmplx_mag_squared_q10p6( - q15_t * pSrc, - q15_t * pDst, - uint32_t numSamples) -{ - q31_t acc0, acc1; /* Accumulators */ - -#if defined (ARM_MATH_DSP) - - /* Run the below code for Cortex-M4 and Cortex-M3 */ - uint32_t blkCnt; /* loop counter */ - q31_t in1, in2, in3, in4; - q31_t acc2, acc3; - - /*loop Unrolling */ - blkCnt = numSamples >> 2U; - - /* First part of the processing with loop unrolling. Compute 4 outputs at a time. - ** a second loop below computes the remaining 1 to 3 samples. */ - while (blkCnt > 0U) - { - /* C[0] = (A[0] * A[0] + A[1] * A[1]) */ - in1 = *__SIMD32(pSrc)++; - in2 = *__SIMD32(pSrc)++; - in3 = *__SIMD32(pSrc)++; - in4 = *__SIMD32(pSrc)++; - - acc0 = __SMUAD(in1, in1); - acc1 = __SMUAD(in2, in2); - acc2 = __SMUAD(in3, in3); - acc3 = __SMUAD(in4, in4); - - /* store the result in 3.13 format in the destination buffer. */ - *pDst++ = (q15_t) (acc0 >> 6); - *pDst++ = (q15_t) (acc1 >> 6); - *pDst++ = (q15_t) (acc2 >> 6); - *pDst++ = (q15_t) (acc3 >> 6); - - /* Decrement the loop counter */ - blkCnt--; - } - - /* If the numSamples is not a multiple of 4, compute any remaining output samples here. - ** No loop unrolling is used. */ - blkCnt = numSamples % 0x4U; - - while (blkCnt > 0U) - { - /* C[0] = (A[0] * A[0] + A[1] * A[1]) */ - in1 = *__SIMD32(pSrc)++; - acc0 = __SMUAD(in1, in1); - - /* store the result in 3.13 format in the destination buffer. */ - *pDst++ = (q15_t) (acc0 >> 6); - - /* Decrement the loop counter */ - blkCnt--; - } - -#else - - /* Run the below code for Cortex-M0 */ - q15_t real, imag; /* Temporary variables to store real and imaginary values */ - - while (numSamples > 0U) - { - /* out = ((real * real) + (imag * imag)) */ - real = *pSrc++; - imag = *pSrc++; - acc0 = (real * real); - acc1 = (imag * imag); - /* store the result in 3.13 format in the destination buffer. */ - *pDst++ = (q15_t) (((q63_t) acc0 + acc1) >> 6); - - /* Decrement the loop counter */ - numSamples--; - } - -#endif /* #if defined (ARM_MATH_DSP) */ - -} - -/** - * @} end of cmplx_mag_squared group - */ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h deleted file mode 100644 index 24144615cc..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h +++ /dev/null @@ -1,33 +0,0 @@ -/* This file is a modification of the ARM CMSIS library file arm_math.h - * We have retained the original copyright and header information, in - * accordance with the Apache 2.0 license terms. - */ - -/****************************************************************************** - * @file arm_math.h - * @brief Public header file for CMSIS DSP LibraryU - * @version V1.5.3 - * @date 10. January 2018 - ******************************************************************************/ -/* - * Copyright (C) 2010-2017 ARM Limited or its affiliates. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -void arm_cmplx_mag_squared_q10p6( - q15_t * pSrc, - q15_t * pDst, - uint32_t numSamples); diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc index 6bc3c4cb77..3e31f96aa3 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc @@ -21,7 +21,7 @@ extern "C" { #define FFT_SIZE_DIV2 256 #include #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h" - #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/arm_cmplx_mag_squared_q10p6.h" + #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS_ext/arm_cmplx_mag_squared_q10p6.h" } #include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md index 66fa176a9b..d3cfb88028 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/README.md @@ -46,7 +46,6 @@ # Description of files * **.gitignore**: Git should ignore \*.txt and \*.wav files that result from experiments run in this directory -* **apollo3.h**: Apollo 3 version of the [CMSIS Device Header File (device.h)](https://www.keil.com/pack/doc/CMSIS/Core/html/device_h_pg.html). Available in the [Ambiq Keil Pack](http://s3.ambiqmicro.com/pack/AmbiqMicro.Apollo_DFP.1.1.0.pack). * **captured\_data\_to\_wav.py**: Python script that parses a text file containing data dumped from GDB (specifically the verilog format) and creates a \*.wav file using [PySoundFile](https://pysoundfile.readthedocs.io/en/0.9.0/). * **compare\_1k.py**: This script compares the intermediate variables and final outputs of the micro-lite fixed-point preprocessor function and the CMSIS version of this function. The stimulus provided to each preprocessor is the same: a 1 kHz sinusoid. * **get\_yesno\_data.cmd**: A GDB command file that runs preprocessor_test (where TARGET=apollo3evb) and dumps the calculated data for the "yes" and "no" input wavfeorms to text files @@ -59,6 +58,10 @@ * **pushbutton_cmsis_voice.cmd**: GDB command file that runs pushbutton_cmsis_speech_test_bin. Dumps the recorded 1 second of audio to captured_data.txt, which can then be processed by the python file captured_data_to_wav.py. * **pushbutton_main.c**: Source file containing program point of entry \_main() for the pushbutton\_\* tests. Contains Interrupt Service Routines for PDM data capture and pushbuttons. Calls the main() function of pushbutton_test.cc * **pushbutton_test.cc**: Source file containing main() function for the pushbutton\_\* tests. main() calls the preprocessor function and the neural net inference function. + +# Description of externally downloaded files in ../apollo3_ext + +* **apollo3.h**: Apollo 3 version of the [CMSIS Device Header File (device.h)](https://www.keil.com/pack/doc/CMSIS/Core/html/device_h_pg.html). Available in the [Ambiq Keil Pack](http://s3.ambiqmicro.com/pack/AmbiqMicro.Apollo_DFP.1.1.0.pack). * **system_apollo3.c**: Apollo 3 version of the [CMSIS System Configuration File system\_\.c](https://www.keil.com/pack/doc/CMSIS/Core/html/system_c_pg.html). Available in the [Ambiq Keil Pack](http://s3.ambiqmicro.com/pack/AmbiqMicro.Apollo_DFP.1.1.0.pack). * **system_apollo3.h**: Apollo 3 version of the [CMSIS System Configuration File system\_\.h](https://www.keil.com/pack/doc/CMSIS/Core/html/system_c_pg.html). Available in the [Ambiq Keil Pack](http://s3.ambiqmicro.com/pack/AmbiqMicro.Apollo_DFP.1.1.0.pack). diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h deleted file mode 100755 index af22270e32..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h +++ /dev/null @@ -1,23332 +0,0 @@ -/* - * Copyright (C) 2015-2017, Ambiq Micro - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of itscontributors may be used to endorse - * or promote products derived from thissoftware without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @file apollo3.h - * @brief CMSIS HeaderFile - * @version 1.0 - * @date 10. August 2018 - * @note Generated by SVDConv V3.3.18 on Friday, 10.08.2018 16:52:09 - * from File 'apollo3.svd', - * last modified on Friday, 10.08.2018 20:01:31 - */ - - - -/** @addtogroup Ambiq Micro - * @{ - */ - - -/** @addtogroup apollo3 - * @{ - */ - - -#ifndef APOLLO3_H -#define APOLLO3_H - -#ifdef __cplusplus -extern "C" { -#endif - - -/** @addtogroup Configuration_of_CMSIS - * @{ - */ - - - -/* =========================================================================================================================== */ -/* ================ Interrupt Number Definition ================ */ -/* =========================================================================================================================== */ - -typedef enum { -/* ======================================= ARM Cortex-M4 Specific Interrupt Numbers ======================================== */ - Reset_IRQn = -15, /*!< -15 Reset Vector, invoked on Power up and warm reset */ - NonMaskableInt_IRQn = -14, /*!< -14 Non maskable Interrupt, cannot be stopped or preempted */ - HardFault_IRQn = -13, /*!< -13 Hard Fault, all classes of Fault */ - MemoryManagement_IRQn = -12, /*!< -12 Memory Management, MPU mismatch, including Access Violation - and No Match */ - BusFault_IRQn = -11, /*!< -11 Bus Fault, Pre-Fetch-, Memory Access Fault, other address/memory - related Fault */ - UsageFault_IRQn = -10, /*!< -10 Usage Fault, i.e. Undef Instruction, Illegal State Transition */ - SVCall_IRQn = -5, /*!< -5 System Service Call via SVC instruction */ - DebugMonitor_IRQn = -4, /*!< -4 Debug Monitor */ - PendSV_IRQn = -2, /*!< -2 Pendable request for system service */ - SysTick_IRQn = -1, /*!< -1 System Tick Timer */ -/* ========================================== apollo3 Specific Interrupt Numbers =========================================== */ - BROWNOUT_IRQn = 0, /*!< 0 BROWNOUT */ - WDT_IRQn = 1, /*!< 1 WDT */ - RTC_IRQn = 2, /*!< 2 RTC */ - VCOMP_IRQn = 3, /*!< 3 VCOMP */ - IOSLAVE_IRQn = 4, /*!< 4 IOSLAVE */ - IOSLAVEACC_IRQn = 5, /*!< 5 IOSLAVEACC */ - IOMSTR0_IRQn = 6, /*!< 6 IOMSTR0 */ - IOMSTR1_IRQn = 7, /*!< 7 IOMSTR1 */ - IOMSTR2_IRQn = 8, /*!< 8 IOMSTR2 */ - IOMSTR3_IRQn = 9, /*!< 9 IOMSTR3 */ - IOMSTR4_IRQn = 10, /*!< 10 IOMSTR4 */ - IOMSTR5_IRQn = 11, /*!< 11 IOMSTR5 */ - BLE_IRQn = 12, /*!< 12 BLE */ - GPIO_IRQn = 13, /*!< 13 GPIO */ - CTIMER_IRQn = 14, /*!< 14 CTIMER */ - UART0_IRQn = 15, /*!< 15 UART0 */ - UART1_IRQn = 16, /*!< 16 UART1 */ - SCARD_IRQn = 17, /*!< 17 SCARD */ - ADC_IRQn = 18, /*!< 18 ADC */ - PDM_IRQn = 19, /*!< 19 PDM */ - MSPI_IRQn = 20, /*!< 20 MSPI */ - STIMER_IRQn = 22, /*!< 22 STIMER */ - STIMER_CMPR0_IRQn = 23, /*!< 23 STIMER_CMPR0 */ - STIMER_CMPR1_IRQn = 24, /*!< 24 STIMER_CMPR1 */ - STIMER_CMPR2_IRQn = 25, /*!< 25 STIMER_CMPR2 */ - STIMER_CMPR3_IRQn = 26, /*!< 26 STIMER_CMPR3 */ - STIMER_CMPR4_IRQn = 27, /*!< 27 STIMER_CMPR4 */ - STIMER_CMPR5_IRQn = 28, /*!< 28 STIMER_CMPR5 */ - STIMER_CMPR6_IRQn = 29, /*!< 29 STIMER_CMPR6 */ - STIMER_CMPR7_IRQn = 30, /*!< 30 STIMER_CMPR7 */ - CLKGEN_IRQn = 31 /*!< 31 CLKGEN */ -} IRQn_Type; - - - -/* =========================================================================================================================== */ -/* ================ Processor and Core Peripheral Section ================ */ -/* =========================================================================================================================== */ - -/* =========================== Configuration of the ARM Cortex-M4 Processor and Core Peripherals =========================== */ -#define __CM4_REV 0x0100U /*!< CM4 Core Revision */ -#define __NVIC_PRIO_BITS 3 /*!< Number of Bits used for Priority Levels */ -#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ -#define __MPU_PRESENT 1 /*!< MPU present or not */ -#define __FPU_PRESENT 1 /*!< FPU present or not */ - - -/** @} */ /* End of group Configuration_of_CMSIS */ - -#include "core_cm4.h" /*!< ARM Cortex-M4 processor and core peripherals */ -#include "system_apollo3.h" /*!< apollo3 System */ - -#ifndef __IM /*!< Fallback for older CMSIS versions */ - #define __IM __I -#endif -#ifndef __OM /*!< Fallback for older CMSIS versions */ - #define __OM __O -#endif -#ifndef __IOM /*!< Fallback for older CMSIS versions */ - #define __IOM __IO -#endif - - -/* ======================================== Start of section using anonymous unions ======================================== */ -#if defined (__CC_ARM) - #pragma push - #pragma anon_unions -#elif defined (__ICCARM__) - #pragma language=extended -#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wc11-extensions" - #pragma clang diagnostic ignored "-Wreserved-id-macro" - #pragma clang diagnostic ignored "-Wgnu-anonymous-struct" - #pragma clang diagnostic ignored "-Wnested-anon-types" -#elif defined (__GNUC__) - /* anonymous unions are enabled by default */ -#elif defined (__TMS470__) - /* anonymous unions are enabled by default */ -#elif defined (__TASKING__) - #pragma warning 586 -#elif defined (__CSMC__) - /* anonymous unions are enabled by default */ -#else - #warning Not supported compiler type -#endif - - -/* =========================================================================================================================== */ -/* ================ Device Specific Peripheral Section ================ */ -/* =========================================================================================================================== */ - - -/** @addtogroup Device_Peripheral_peripherals - * @{ - */ - - - -/* =========================================================================================================================== */ -/* ================ ADC ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Analog Digital Converter Control (ADC) - */ - -typedef struct { /*!< (@ 0x50010000) ADC Structure */ - - union { - __IOM uint32_t CFG; /*!< (@ 0x00000000) Configuration Register */ - - struct { - __IOM uint32_t ADCEN : 1; /*!< [0..0] This bit enables the ADC module. While the ADC is enabled, - the ADCCFG and SLOT Configuration regsiter settings must - remain stable and unchanged. All configuration register - settings, slot configuration settings and window comparison - settings should be written prior to setting the ADCEN bit - to '1'. */ - __IM uint32_t : 1; - __IOM uint32_t RPTEN : 1; /*!< [2..2] This bit enables Repeating Scan Mode. */ - __IOM uint32_t LPMODE : 1; /*!< [3..3] Select power mode to enter between active scans. */ - __IOM uint32_t CKMODE : 1; /*!< [4..4] Clock mode register */ - __IM uint32_t : 3; - __IOM uint32_t REFSEL : 2; /*!< [9..8] Select the ADC reference voltage. */ - __IM uint32_t : 2; - __IOM uint32_t DFIFORDEN : 1; /*!< [12..12] Destructive FIFO Read Enable. Setting this will enable - FIFO pop upon reading the FIFOPR register. */ - __IM uint32_t : 3; - __IOM uint32_t TRIGSEL : 3; /*!< [18..16] Select the ADC trigger source. */ - __IOM uint32_t TRIGPOL : 1; /*!< [19..19] This bit selects the ADC trigger polarity for external - off chip triggers. */ - __IM uint32_t : 4; - __IOM uint32_t CLKSEL : 2; /*!< [25..24] Select the source and frequency for the ADC clock. - All values not enumerated below are undefined. */ - } CFG_b; - } ; - - union { - __IOM uint32_t STAT; /*!< (@ 0x00000004) ADC Power Status */ - - struct { - __IOM uint32_t PWDSTAT : 1; /*!< [0..0] Indicates the power-status of the ADC. */ - } STAT_b; - } ; - - union { - __IOM uint32_t SWT; /*!< (@ 0x00000008) Software trigger */ - - struct { - __IOM uint32_t SWT : 8; /*!< [7..0] Writing 0x37 to this register generates a software trigger. */ - } SWT_b; - } ; - - union { - __IOM uint32_t SL0CFG; /*!< (@ 0x0000000C) Slot 0 Configuration Register */ - - struct { - __IOM uint32_t SLEN0 : 1; /*!< [0..0] This bit enables slot 0 for ADC conversions. */ - __IOM uint32_t WCEN0 : 1; /*!< [1..1] This bit enables the window compare function for slot - 0. */ - __IM uint32_t : 6; - __IOM uint32_t CHSEL0 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ - __IM uint32_t : 4; - __IOM uint32_t PRMODE0 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ - __IM uint32_t : 6; - __IOM uint32_t ADSEL0 : 3; /*!< [26..24] Select the number of measurements to average in the - accumulate divide module for this slot. */ - } SL0CFG_b; - } ; - - union { - __IOM uint32_t SL1CFG; /*!< (@ 0x00000010) Slot 1 Configuration Register */ - - struct { - __IOM uint32_t SLEN1 : 1; /*!< [0..0] This bit enables slot 1 for ADC conversions. */ - __IOM uint32_t WCEN1 : 1; /*!< [1..1] This bit enables the window compare function for slot - 1. */ - __IM uint32_t : 6; - __IOM uint32_t CHSEL1 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ - __IM uint32_t : 4; - __IOM uint32_t PRMODE1 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ - __IM uint32_t : 6; - __IOM uint32_t ADSEL1 : 3; /*!< [26..24] Select the number of measurements to average in the - accumulate divide module for this slot. */ - } SL1CFG_b; - } ; - - union { - __IOM uint32_t SL2CFG; /*!< (@ 0x00000014) Slot 2 Configuration Register */ - - struct { - __IOM uint32_t SLEN2 : 1; /*!< [0..0] This bit enables slot 2 for ADC conversions. */ - __IOM uint32_t WCEN2 : 1; /*!< [1..1] This bit enables the window compare function for slot - 2. */ - __IM uint32_t : 6; - __IOM uint32_t CHSEL2 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ - __IM uint32_t : 4; - __IOM uint32_t PRMODE2 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ - __IM uint32_t : 6; - __IOM uint32_t ADSEL2 : 3; /*!< [26..24] Select the number of measurements to average in the - accumulate divide module for this slot. */ - } SL2CFG_b; - } ; - - union { - __IOM uint32_t SL3CFG; /*!< (@ 0x00000018) Slot 3 Configuration Register */ - - struct { - __IOM uint32_t SLEN3 : 1; /*!< [0..0] This bit enables slot 3 for ADC conversions. */ - __IOM uint32_t WCEN3 : 1; /*!< [1..1] This bit enables the window compare function for slot - 3. */ - __IM uint32_t : 6; - __IOM uint32_t CHSEL3 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ - __IM uint32_t : 4; - __IOM uint32_t PRMODE3 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ - __IM uint32_t : 6; - __IOM uint32_t ADSEL3 : 3; /*!< [26..24] Select the number of measurements to average in the - accumulate divide module for this slot. */ - } SL3CFG_b; - } ; - - union { - __IOM uint32_t SL4CFG; /*!< (@ 0x0000001C) Slot 4 Configuration Register */ - - struct { - __IOM uint32_t SLEN4 : 1; /*!< [0..0] This bit enables slot 4 for ADC conversions. */ - __IOM uint32_t WCEN4 : 1; /*!< [1..1] This bit enables the window compare function for slot - 4. */ - __IM uint32_t : 6; - __IOM uint32_t CHSEL4 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ - __IM uint32_t : 4; - __IOM uint32_t PRMODE4 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ - __IM uint32_t : 6; - __IOM uint32_t ADSEL4 : 3; /*!< [26..24] Select the number of measurements to average in the - accumulate divide module for this slot. */ - } SL4CFG_b; - } ; - - union { - __IOM uint32_t SL5CFG; /*!< (@ 0x00000020) Slot 5 Configuration Register */ - - struct { - __IOM uint32_t SLEN5 : 1; /*!< [0..0] This bit enables slot 5 for ADC conversions. */ - __IOM uint32_t WCEN5 : 1; /*!< [1..1] This bit enables the window compare function for slot - 5. */ - __IM uint32_t : 6; - __IOM uint32_t CHSEL5 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ - __IM uint32_t : 4; - __IOM uint32_t PRMODE5 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ - __IM uint32_t : 6; - __IOM uint32_t ADSEL5 : 3; /*!< [26..24] Select number of measurements to average in the accumulate - divide module for this slot. */ - } SL5CFG_b; - } ; - - union { - __IOM uint32_t SL6CFG; /*!< (@ 0x00000024) Slot 6 Configuration Register */ - - struct { - __IOM uint32_t SLEN6 : 1; /*!< [0..0] This bit enables slot 6 for ADC conversions. */ - __IOM uint32_t WCEN6 : 1; /*!< [1..1] This bit enables the window compare function for slot - 6. */ - __IM uint32_t : 6; - __IOM uint32_t CHSEL6 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ - __IM uint32_t : 4; - __IOM uint32_t PRMODE6 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ - __IM uint32_t : 6; - __IOM uint32_t ADSEL6 : 3; /*!< [26..24] Select the number of measurements to average in the - accumulate divide module for this slot. */ - } SL6CFG_b; - } ; - - union { - __IOM uint32_t SL7CFG; /*!< (@ 0x00000028) Slot 7 Configuration Register */ - - struct { - __IOM uint32_t SLEN7 : 1; /*!< [0..0] This bit enables slot 7 for ADC conversions. */ - __IOM uint32_t WCEN7 : 1; /*!< [1..1] This bit enables the window compare function for slot - 7. */ - __IM uint32_t : 6; - __IOM uint32_t CHSEL7 : 4; /*!< [11..8] Select one of the 14 channel inputs for this slot. */ - __IM uint32_t : 4; - __IOM uint32_t PRMODE7 : 2; /*!< [17..16] Set the Precision Mode For Slot. */ - __IM uint32_t : 6; - __IOM uint32_t ADSEL7 : 3; /*!< [26..24] Select the number of measurements to average in the - accumulate divide module for this slot. */ - } SL7CFG_b; - } ; - - union { - __IOM uint32_t WULIM; /*!< (@ 0x0000002C) Window Comparator Upper Limits Register */ - - struct { - __IOM uint32_t ULIM : 20; /*!< [19..0] Sets the upper limit for the window comparator. */ - } WULIM_b; - } ; - - union { - __IOM uint32_t WLLIM; /*!< (@ 0x00000030) Window Comparator Lower Limits Register */ - - struct { - __IOM uint32_t LLIM : 20; /*!< [19..0] Sets the lower limit for the window comparator. */ - } WLLIM_b; - } ; - - union { - __IOM uint32_t SCWLIM; /*!< (@ 0x00000034) Scale Window Comparator Limits */ - - struct { - __IOM uint32_t SCWLIMEN : 1; /*!< [0..0] Scale the window limits compare values per precision - mode. When set to 0x0 (default), the values in the 20-bit - limits registers will compare directly with the FIFO values - regardless of the precision mode the slot is configured - to. When set to 0x1, the compare values will be divided - by the difference in precision bits while performing the - window limit comparisons. */ - } SCWLIM_b; - } ; - - union { - __IOM uint32_t FIFO; /*!< (@ 0x00000038) FIFO Data and Valid Count Register */ - - struct { - __IOM uint32_t DATA : 20; /*!< [19..0] Oldest data in the FIFO. */ - __IOM uint32_t COUNT : 8; /*!< [27..20] Number of valid entries in the ADC FIFO. */ - __IOM uint32_t SLOTNUM : 3; /*!< [30..28] Slot number associated with this FIFO data. */ - __IOM uint32_t RSVD : 1; /*!< [31..31] RESERVED. */ - } FIFO_b; - } ; - - union { - __IOM uint32_t FIFOPR; /*!< (@ 0x0000003C) FIFO Data and Valid Count Register */ - - struct { - __IOM uint32_t DATA : 20; /*!< [19..0] Oldest data in the FIFO. */ - __IOM uint32_t COUNT : 8; /*!< [27..20] Number of valid entries in the ADC FIFO. */ - __IOM uint32_t SLOTNUMPR : 3; /*!< [30..28] Slot number associated with this FIFO data. */ - __IOM uint32_t RSVDPR : 1; /*!< [31..31] RESERVED. */ - } FIFOPR_b; - } ; - __IM uint32_t RESERVED[112]; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000200) ADC Interrupt registers: Enable */ - - struct { - __IOM uint32_t CNVCMP : 1; /*!< [0..0] ADC conversion complete interrupt. */ - __IOM uint32_t SCNCMP : 1; /*!< [1..1] ADC scan complete interrupt. */ - __IOM uint32_t FIFOOVR1 : 1; /*!< [2..2] FIFO 75 percent full interrupt. */ - __IOM uint32_t FIFOOVR2 : 1; /*!< [3..3] FIFO 100 percent full interrupt. */ - __IOM uint32_t WCEXC : 1; /*!< [4..4] Window comparator voltage excursion interrupt. */ - __IOM uint32_t WCINC : 1; /*!< [5..5] Window comparator voltage incursion interrupt. */ - __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Transfer Complete */ - __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Condition */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) ADC Interrupt registers: Status */ - - struct { - __IOM uint32_t CNVCMP : 1; /*!< [0..0] ADC conversion complete interrupt. */ - __IOM uint32_t SCNCMP : 1; /*!< [1..1] ADC scan complete interrupt. */ - __IOM uint32_t FIFOOVR1 : 1; /*!< [2..2] FIFO 75 percent full interrupt. */ - __IOM uint32_t FIFOOVR2 : 1; /*!< [3..3] FIFO 100 percent full interrupt. */ - __IOM uint32_t WCEXC : 1; /*!< [4..4] Window comparator voltage excursion interrupt. */ - __IOM uint32_t WCINC : 1; /*!< [5..5] Window comparator voltage incursion interrupt. */ - __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Transfer Complete */ - __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Condition */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000208) ADC Interrupt registers: Clear */ - - struct { - __IOM uint32_t CNVCMP : 1; /*!< [0..0] ADC conversion complete interrupt. */ - __IOM uint32_t SCNCMP : 1; /*!< [1..1] ADC scan complete interrupt. */ - __IOM uint32_t FIFOOVR1 : 1; /*!< [2..2] FIFO 75 percent full interrupt. */ - __IOM uint32_t FIFOOVR2 : 1; /*!< [3..3] FIFO 100 percent full interrupt. */ - __IOM uint32_t WCEXC : 1; /*!< [4..4] Window comparator voltage excursion interrupt. */ - __IOM uint32_t WCINC : 1; /*!< [5..5] Window comparator voltage incursion interrupt. */ - __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Transfer Complete */ - __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Condition */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000020C) ADC Interrupt registers: Set */ - - struct { - __IOM uint32_t CNVCMP : 1; /*!< [0..0] ADC conversion complete interrupt. */ - __IOM uint32_t SCNCMP : 1; /*!< [1..1] ADC scan complete interrupt. */ - __IOM uint32_t FIFOOVR1 : 1; /*!< [2..2] FIFO 75 percent full interrupt. */ - __IOM uint32_t FIFOOVR2 : 1; /*!< [3..3] FIFO 100 percent full interrupt. */ - __IOM uint32_t WCEXC : 1; /*!< [4..4] Window comparator voltage excursion interrupt. */ - __IOM uint32_t WCINC : 1; /*!< [5..5] Window comparator voltage incursion interrupt. */ - __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Transfer Complete */ - __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Condition */ - } INTSET_b; - } ; - __IM uint32_t RESERVED1[12]; - - union { - __IOM uint32_t DMATRIGEN; /*!< (@ 0x00000240) DMA Trigger Enable Register */ - - struct { - __IOM uint32_t DFIFO75 : 1; /*!< [0..0] Trigger DMA upon FIFO 75 percent Full */ - __IOM uint32_t DFIFOFULL : 1; /*!< [1..1] Trigger DMA upon FIFO 100 percent Full */ - } DMATRIGEN_b; - } ; - - union { - __IOM uint32_t DMATRIGSTAT; /*!< (@ 0x00000244) DMA Trigger Status Register */ - - struct { - __IOM uint32_t D75STAT : 1; /*!< [0..0] Triggered DMA from FIFO 75 percent Full */ - __IOM uint32_t DFULLSTAT : 1; /*!< [1..1] Triggered DMA from FIFO 100 percent Full */ - } DMATRIGSTAT_b; - } ; - __IM uint32_t RESERVED2[14]; - - union { - __IOM uint32_t DMACFG; /*!< (@ 0x00000280) DMA Configuration Register */ - - struct { - __IOM uint32_t DMAEN : 1; /*!< [0..0] DMA Enable */ - __IM uint32_t : 1; - __IOM uint32_t DMADIR : 1; /*!< [2..2] Direction */ - __IM uint32_t : 5; - __IOM uint32_t DMAPRI : 1; /*!< [8..8] Sets the Priority of the DMA request */ - __IOM uint32_t DMADYNPRI : 1; /*!< [9..9] Enables dynamic priority based on FIFO fullness. When - FIFO is full, priority is automatically set to HIGH. Otherwise, - DMAPRI is used. */ - __IM uint32_t : 6; - __IOM uint32_t DMAHONSTAT : 1; /*!< [16..16] Halt New ADC conversions until DMA Status DMAERR and - DMACPL Cleared. */ - __IOM uint32_t DMAMSK : 1; /*!< [17..17] Mask the FIFOCNT and SLOTNUM when transferring FIFO - contents to memory */ - __IOM uint32_t DPWROFF : 1; /*!< [18..18] Power Off the ADC System upon DMACPL. */ - } DMACFG_b; - } ; - __IM uint32_t RESERVED3; - - union { - __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x00000288) DMA Total Transfer Count */ - - struct { - __IM uint32_t : 2; - __IOM uint32_t TOTCOUNT : 16; /*!< [17..2] Total Transfer Count */ - } DMATOTCOUNT_b; - } ; - - union { - __IOM uint32_t DMATARGADDR; /*!< (@ 0x0000028C) DMA Target Address Register */ - - struct { - __IOM uint32_t LTARGADDR : 19; /*!< [18..0] DMA Target Address */ - __IOM uint32_t UTARGADDR : 13; /*!< [31..19] SRAM Target */ - } DMATARGADDR_b; - } ; - - union { - __IOM uint32_t DMASTAT; /*!< (@ 0x00000290) DMA Status Register */ - - struct { - __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress */ - __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete */ - __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error */ - } DMASTAT_b; - } ; -} ADC_Type; /*!< Size = 660 (0x294) */ - - - -/* =========================================================================================================================== */ -/* ================ APBDMA ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief APB DMA Register Interfaces (APBDMA) - */ - -typedef struct { /*!< (@ 0x40011000) APBDMA Structure */ - - union { - __IOM uint32_t BBVALUE; /*!< (@ 0x00000000) Control Register */ - - struct { - __IOM uint32_t DATAOUT : 8; /*!< [7..0] Data Output Values */ - __IM uint32_t : 8; - __IOM uint32_t PIN : 8; /*!< [23..16] PIO values */ - } BBVALUE_b; - } ; - - union { - __IOM uint32_t BBSETCLEAR; /*!< (@ 0x00000004) Set/Clear Register */ - - struct { - __IOM uint32_t SET : 8; /*!< [7..0] Write 1 to Set PIO value (set hier priority than clear - if both bit set) */ - __IM uint32_t : 8; - __IOM uint32_t CLEAR : 8; /*!< [23..16] Write 1 to Clear PIO value */ - } BBSETCLEAR_b; - } ; - - union { - __IOM uint32_t BBINPUT; /*!< (@ 0x00000008) PIO Input Values */ - - struct { - __IOM uint32_t DATAIN : 8; /*!< [7..0] PIO values */ - } BBINPUT_b; - } ; - __IM uint32_t RESERVED[5]; - - union { - __IOM uint32_t DEBUGDATA; /*!< (@ 0x00000020) PIO Input Values */ - - struct { - __IOM uint32_t DEBUGDATA : 32; /*!< [31..0] Debug Data */ - } DEBUGDATA_b; - } ; - __IM uint32_t RESERVED1[7]; - - union { - __IOM uint32_t DEBUG; /*!< (@ 0x00000040) PIO Input Values */ - - struct { - __IOM uint32_t DEBUGEN : 4; /*!< [3..0] Debug Enable */ - } DEBUG_b; - } ; -} APBDMA_Type; /*!< Size = 68 (0x44) */ - - - -/* =========================================================================================================================== */ -/* ================ BLEIF ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief BLE Interface (BLEIF) - */ - -typedef struct { /*!< (@ 0x5000C000) BLEIF Structure */ - - union { - __IOM uint32_t FIFO; /*!< (@ 0x00000000) FIFO Access Port */ - - struct { - __IOM uint32_t FIFO : 32; /*!< [31..0] FIFO direct access. Only locations 0 - 3F will return - valid information. */ - } FIFO_b; - } ; - __IM uint32_t RESERVED[63]; - - union { - __IOM uint32_t FIFOPTR; /*!< (@ 0x00000100) FIFO size and remaining slots open values */ - - struct { - __IOM uint32_t FIFO0SIZ : 8; /*!< [7..0] The number of valid data bytes currently in the FIFO - 0 (written by MCU, read by interface) */ - __IOM uint32_t FIFO0REM : 8; /*!< [15..8] The number of remaining data bytes slots currently in - FIFO 0 (written by MCU, read by interface) */ - __IOM uint32_t FIFO1SIZ : 8; /*!< [23..16] The number of valid data bytes currently in FIFO 1 - (written by interface, read by MCU) */ - __IOM uint32_t FIFO1REM : 8; /*!< [31..24] The number of remaining data bytes slots currently - in FIFO 1 (written by interface, read by MCU) */ - } FIFOPTR_b; - } ; - - union { - __IOM uint32_t FIFOTHR; /*!< (@ 0x00000104) FIFO Threshold Configuration */ - - struct { - __IOM uint32_t FIFORTHR : 6; /*!< [5..0] FIFO read threshold in bytes. A value of 0 will disable - the read FIFO level from activating the threshold interrupt. - If this field is non-zero, it will trigger a threshold - interrupt when the read fifo contains FIFORTHR valid bytes - of data, as indicated by the FIFO1SIZ field. This is intended - to signal when a data transfer of FIFORTHR bytes can be - done from the IOM module to the host via the read fifo - to support large IOM read operations. */ - __IM uint32_t : 2; - __IOM uint32_t FIFOWTHR : 6; /*!< [13..8] FIFO write threshold in bytes. A value of 0 will disable - the write FIFO level from activating the threshold interrupt. - If this field is non-zero, it will trigger a threshold - interrupt when the write fifo contains FIFOWTHR free bytes, - as indicated by the FIFO0REM field. This is intended to - signal when a transfer of FIFOWTHR bytes can be done from - the host to the IOM write fifo to support large IOM write - operations. */ - } FIFOTHR_b; - } ; - - union { - __IOM uint32_t FIFOPOP; /*!< (@ 0x00000108) FIFO POP register */ - - struct { - __IOM uint32_t FIFODOUT : 32; /*!< [31..0] This register will return the read data indicated by - the current read pointer on reads. If the POPWR control - bit in the FIFOCTRL register is reset (0), the fifo read - pointer will be advanced by one word as a result of the - read.If the POPWR bit is set (1), the fifo read pointer - will only be advanced after a write operation to this register. - The write data is ignored for this register.If less than - a even word multiple is available, and the command is completed, - the module will return the word containing */ - } FIFOPOP_b; - } ; - - union { - __IOM uint32_t FIFOPUSH; /*!< (@ 0x0000010C) FIFO PUSH register */ - - struct { - __IOM uint32_t FIFODIN : 32; /*!< [31..0] This register is used to write the FIFORAM in FIFO mode - and will cause a push event to occur to the next open slot - within the FIFORAM. Writing to this register will cause - the write point to increment by 1 word(4 bytes). */ - } FIFOPUSH_b; - } ; - - union { - __IOM uint32_t FIFOCTRL; /*!< (@ 0x00000110) FIFO Control Register */ - - struct { - __IOM uint32_t POPWR : 1; /*!< [0..0] Selects the mode in which 'pop' events are done for the - fifo read operations. A value of '1' will prevent a pop - event on a read operation, and will require a write to - the FIFOPOP register to create a pop event.A value of '0' - in this register will allow a pop event to occur on the - read of the FIFOPOP register, and may cause inadvertant - fifo pops when used in a debugging mode. */ - __IOM uint32_t FIFORSTN : 1; /*!< [1..1] Active low manual reset of the fifo. Write to 0 to reset - fifo, and then write to 1 to remove the reset. */ - } FIFOCTRL_b; - } ; - - union { - __IOM uint32_t FIFOLOC; /*!< (@ 0x00000114) FIFO Pointers */ - - struct { - __IOM uint32_t FIFOWPTR : 4; /*!< [3..0] Current FIFO write pointer. Value is the index into the - outgoing FIFO (FIFO0), which is used during write operations - to external devices. */ - __IM uint32_t : 4; - __IOM uint32_t FIFORPTR : 4; /*!< [11..8] Current FIFO read pointer. Used to index into the incoming - FIFO (FIFO1), which is used to store read data returned - from external devices during a read operation. */ - } FIFOLOC_b; - } ; - __IM uint32_t RESERVED1[58]; - - union { - __IOM uint32_t CLKCFG; /*!< (@ 0x00000200) I/O Clock Configuration */ - - struct { - __IOM uint32_t IOCLKEN : 1; /*!< [0..0] Enable for the interface clock. Must be enabled prior - to executing any IO operations. */ - __IM uint32_t : 7; - __IOM uint32_t FSEL : 3; /*!< [10..8] Select the input clock frequency. */ - __IOM uint32_t CLK32KEN : 1; /*!< [11..11] Enable for the 32Khz clock to the BLE module */ - __IOM uint32_t DIV3 : 1; /*!< [12..12] Enable of the divide by 3 of the source IOCLK. */ - } CLKCFG_b; - } ; - __IM uint32_t RESERVED2[2]; - - union { - __IOM uint32_t CMD; /*!< (@ 0x0000020C) Command and offset Register */ - - struct { - __IOM uint32_t CMD : 5; /*!< [4..0] Command for submodule. */ - __IOM uint32_t OFFSETCNT : 2; /*!< [6..5] Number of offset bytes to use for the command - 0, 1, - 2, 3 are valid selections. The second (byte 1) and third - byte (byte 2) are read from the OFFSETHI register, and - the low order byte is pulled from this register in the - OFFSETLO field.Offset bytes are transmitted highest byte - first. EG if offsetcnt == 3, OFFSETHI[15:8] will be transmitted - first, then OFFSETHI[7:0] then OFFSETLO.If offsetcnt == - 2, OFFSETHI[7:0] will be transmitted, then OFFSETLO.If - offsetcnt == 1, only OFFSETLO will be transmitted. */ - __IOM uint32_t CONT : 1; /*!< [7..7] Contine to hold the bus after the current transaction - if set to a 1 with a new command issued. */ - __IOM uint32_t TSIZE : 12; /*!< [19..8] Defines the transaction size in bytes. The offset transfer - is not included in this size. */ - __IOM uint32_t CMDSEL : 2; /*!< [21..20] Command Specific selection information */ - __IM uint32_t : 2; - __IOM uint32_t OFFSETLO : 8; /*!< [31..24] This register holds the low order byte of offset to - be used in the transaction. The number of offset bytes - to use is set with bits 1:0 of the command. Offset bytes - are transferred starting from the highest byte first. */ - } CMD_b; - } ; - - union { - __IOM uint32_t CMDRPT; /*!< (@ 0x00000210) Command Repeat Register */ - - struct { - __IOM uint32_t CMDRPT : 5; /*!< [4..0] Count of number of times to repeat the next command. */ - } CMDRPT_b; - } ; - - union { - __IOM uint32_t OFFSETHI; /*!< (@ 0x00000214) High order offset bytes */ - - struct { - __IOM uint32_t OFFSETHI : 16; /*!< [15..0] Holds the high order bytes of the 2 or 3 byte offset - phase of a transaction. */ - } OFFSETHI_b; - } ; - - union { - __IOM uint32_t CMDSTAT; /*!< (@ 0x00000218) Command status */ - - struct { - __IOM uint32_t CCMD : 5; /*!< [4..0] current command that is being executed */ - __IOM uint32_t CMDSTAT : 3; /*!< [7..5] The current status of the command execution. */ - __IOM uint32_t CTSIZE : 12; /*!< [19..8] The current number of bytes still to be transferred - with this command. This field will count down to zero. */ - } CMDSTAT_b; - } ; - __IM uint32_t RESERVED3; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000220) IO Master Interrupts: Enable */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current - operation has completed. For repeated commands, this will - only be asserted when the final repeated command is completed. */ - __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted - when the number of free bytes in the write FIFO equals - or exceeds the WTHR field.For read operations, asserted - when the number of valid bytes in the read FIFO equals - of exceeds the value set in the RTHR field. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. Asserted when a pop operation - is done to a empty read FIFO. */ - __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software - tries to write to a full fifo. The current operation does - not stop. */ - __IOM uint32_t B2MST : 1; /*!< [4..4] B2M State change interrupt. Asserted on any change in - the B2M_STATE signal from the BLE Core. */ - __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is - a overflow or underflow event */ - __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is - written when an active command is in progress. */ - __IOM uint32_t BLECIRQ : 1; /*!< [7..7] BLE Core IRQ signal. Asserted when the BLE_IRQ signal - from the BLE Core is asserted, indicating the availability - of read data from the BLE Core. */ - __IOM uint32_t BLECSSTAT : 1; /*!< [8..8] BLE Core SPI Status interrupt. Asserted when the SPI_STATUS - signal from the BLE Core is asserted, indicating that SPI - writes can be done to the BLE Core.Transfers to the BLE - Core should only be done when this signal is high. */ - __IOM uint32_t DCMP : 1; /*!< [9..9] DMA Complete. Processing of the DMA operation has completed - and the DMA submodule is returned into the idle state */ - __IOM uint32_t DERR : 1; /*!< [10..10] DMA Error encountered during the processing of the - DMA command. The DMA error could occur when the memory - access specified in the DMA operation is not available - or incorrectly specified. */ - __IOM uint32_t CQPAUSED : 1; /*!< [11..11] Command queue is paused due to an active event enabled - in the PAUSEEN register. The interrupt is posted when the - event is enabled within the PAUSEEN register, the mask - is active in the CQIRQMASK field and the event occurs. */ - __IOM uint32_t CQUPD : 1; /*!< [12..12] Command queue write operation executed a register write - with the register address bit 0 set to 1. The low address - bits in the CQ address fields are unused and bit 0 can - be used to trigger an interrupt to indicate when this register - write is performed by the CQ operation. */ - __IOM uint32_t CQERR : 1; /*!< [13..13] Command queue error during processing. When an error - occurs, the system will stop processing and halt operations - to allow software to take recovery actions */ - __IOM uint32_t B2MSLEEP : 1; /*!< [14..14] The B2M_STATE from the BLE Core transitioned into the - sleep state */ - __IOM uint32_t B2MACTIVE : 1; /*!< [15..15] The B2M_STATE from the BLE Core transitioned into the - active state */ - __IOM uint32_t B2MSHUTDN : 1; /*!< [16..16] The B2M_STATE from the BLE Core transitioned into shutdown - state */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000224) IO Master Interrupts: Status */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current - operation has completed. For repeated commands, this will - only be asserted when the final repeated command is completed. */ - __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted - when the number of free bytes in the write FIFO equals - or exceeds the WTHR field.For read operations, asserted - when the number of valid bytes in the read FIFO equals - of exceeds the value set in the RTHR field. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. Asserted when a pop operation - is done to a empty read FIFO. */ - __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software - tries to write to a full fifo. The current operation does - not stop. */ - __IOM uint32_t B2MST : 1; /*!< [4..4] B2M State change interrupt. Asserted on any change in - the B2M_STATE signal from the BLE Core. */ - __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is - a overflow or underflow event */ - __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is - written when an active command is in progress. */ - __IOM uint32_t BLECIRQ : 1; /*!< [7..7] BLE Core IRQ signal. Asserted when the BLE_IRQ signal - from the BLE Core is asserted, indicating the availability - of read data from the BLE Core. */ - __IOM uint32_t BLECSSTAT : 1; /*!< [8..8] BLE Core SPI Status interrupt. Asserted when the SPI_STATUS - signal from the BLE Core is asserted, indicating that SPI - writes can be done to the BLE Core.Transfers to the BLE - Core should only be done when this signal is high. */ - __IOM uint32_t DCMP : 1; /*!< [9..9] DMA Complete. Processing of the DMA operation has completed - and the DMA submodule is returned into the idle state */ - __IOM uint32_t DERR : 1; /*!< [10..10] DMA Error encountered during the processing of the - DMA command. The DMA error could occur when the memory - access specified in the DMA operation is not available - or incorrectly specified. */ - __IOM uint32_t CQPAUSED : 1; /*!< [11..11] Command queue is paused due to an active event enabled - in the PAUSEEN register. The interrupt is posted when the - event is enabled within the PAUSEEN register, the mask - is active in the CQIRQMASK field and the event occurs. */ - __IOM uint32_t CQUPD : 1; /*!< [12..12] Command queue write operation executed a register write - with the register address bit 0 set to 1. The low address - bits in the CQ address fields are unused and bit 0 can - be used to trigger an interrupt to indicate when this register - write is performed by the CQ operation. */ - __IOM uint32_t CQERR : 1; /*!< [13..13] Command queue error during processing. When an error - occurs, the system will stop processing and halt operations - to allow software to take recovery actions */ - __IOM uint32_t B2MSLEEP : 1; /*!< [14..14] The B2M_STATE from the BLE Core transitioned into the - sleep state */ - __IOM uint32_t B2MACTIVE : 1; /*!< [15..15] The B2M_STATE from the BLE Core transitioned into the - active state */ - __IOM uint32_t B2MSHUTDN : 1; /*!< [16..16] The B2M_STATE from the BLE Core transitioned into shutdown - state */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000228) IO Master Interrupts: Clear */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current - operation has completed. For repeated commands, this will - only be asserted when the final repeated command is completed. */ - __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted - when the number of free bytes in the write FIFO equals - or exceeds the WTHR field.For read operations, asserted - when the number of valid bytes in the read FIFO equals - of exceeds the value set in the RTHR field. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. Asserted when a pop operation - is done to a empty read FIFO. */ - __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software - tries to write to a full fifo. The current operation does - not stop. */ - __IOM uint32_t B2MST : 1; /*!< [4..4] B2M State change interrupt. Asserted on any change in - the B2M_STATE signal from the BLE Core. */ - __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is - a overflow or underflow event */ - __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is - written when an active command is in progress. */ - __IOM uint32_t BLECIRQ : 1; /*!< [7..7] BLE Core IRQ signal. Asserted when the BLE_IRQ signal - from the BLE Core is asserted, indicating the availability - of read data from the BLE Core. */ - __IOM uint32_t BLECSSTAT : 1; /*!< [8..8] BLE Core SPI Status interrupt. Asserted when the SPI_STATUS - signal from the BLE Core is asserted, indicating that SPI - writes can be done to the BLE Core.Transfers to the BLE - Core should only be done when this signal is high. */ - __IOM uint32_t DCMP : 1; /*!< [9..9] DMA Complete. Processing of the DMA operation has completed - and the DMA submodule is returned into the idle state */ - __IOM uint32_t DERR : 1; /*!< [10..10] DMA Error encountered during the processing of the - DMA command. The DMA error could occur when the memory - access specified in the DMA operation is not available - or incorrectly specified. */ - __IOM uint32_t CQPAUSED : 1; /*!< [11..11] Command queue is paused due to an active event enabled - in the PAUSEEN register. The interrupt is posted when the - event is enabled within the PAUSEEN register, the mask - is active in the CQIRQMASK field and the event occurs. */ - __IOM uint32_t CQUPD : 1; /*!< [12..12] Command queue write operation executed a register write - with the register address bit 0 set to 1. The low address - bits in the CQ address fields are unused and bit 0 can - be used to trigger an interrupt to indicate when this register - write is performed by the CQ operation. */ - __IOM uint32_t CQERR : 1; /*!< [13..13] Command queue error during processing. When an error - occurs, the system will stop processing and halt operations - to allow software to take recovery actions */ - __IOM uint32_t B2MSLEEP : 1; /*!< [14..14] The B2M_STATE from the BLE Core transitioned into the - sleep state */ - __IOM uint32_t B2MACTIVE : 1; /*!< [15..15] The B2M_STATE from the BLE Core transitioned into the - active state */ - __IOM uint32_t B2MSHUTDN : 1; /*!< [16..16] The B2M_STATE from the BLE Core transitioned into shutdown - state */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000022C) IO Master Interrupts: Set */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current - operation has completed. For repeated commands, this will - only be asserted when the final repeated command is completed. */ - __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted - when the number of free bytes in the write FIFO equals - or exceeds the WTHR field.For read operations, asserted - when the number of valid bytes in the read FIFO equals - of exceeds the value set in the RTHR field. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. Asserted when a pop operation - is done to a empty read FIFO. */ - __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software - tries to write to a full fifo. The current operation does - not stop. */ - __IOM uint32_t B2MST : 1; /*!< [4..4] B2M State change interrupt. Asserted on any change in - the B2M_STATE signal from the BLE Core. */ - __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is - a overflow or underflow event */ - __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is - written when an active command is in progress. */ - __IOM uint32_t BLECIRQ : 1; /*!< [7..7] BLE Core IRQ signal. Asserted when the BLE_IRQ signal - from the BLE Core is asserted, indicating the availability - of read data from the BLE Core. */ - __IOM uint32_t BLECSSTAT : 1; /*!< [8..8] BLE Core SPI Status interrupt. Asserted when the SPI_STATUS - signal from the BLE Core is asserted, indicating that SPI - writes can be done to the BLE Core.Transfers to the BLE - Core should only be done when this signal is high. */ - __IOM uint32_t DCMP : 1; /*!< [9..9] DMA Complete. Processing of the DMA operation has completed - and the DMA submodule is returned into the idle state */ - __IOM uint32_t DERR : 1; /*!< [10..10] DMA Error encountered during the processing of the - DMA command. The DMA error could occur when the memory - access specified in the DMA operation is not available - or incorrectly specified. */ - __IOM uint32_t CQPAUSED : 1; /*!< [11..11] Command queue is paused due to an active event enabled - in the PAUSEEN register. The interrupt is posted when the - event is enabled within the PAUSEEN register, the mask - is active in the CQIRQMASK field and the event occurs. */ - __IOM uint32_t CQUPD : 1; /*!< [12..12] Command queue write operation executed a register write - with the register address bit 0 set to 1. The low address - bits in the CQ address fields are unused and bit 0 can - be used to trigger an interrupt to indicate when this register - write is performed by the CQ operation. */ - __IOM uint32_t CQERR : 1; /*!< [13..13] Command queue error during processing. When an error - occurs, the system will stop processing and halt operations - to allow software to take recovery actions */ - __IOM uint32_t B2MSLEEP : 1; /*!< [14..14] The B2M_STATE from the BLE Core transitioned into the - sleep state */ - __IOM uint32_t B2MACTIVE : 1; /*!< [15..15] The B2M_STATE from the BLE Core transitioned into the - active state */ - __IOM uint32_t B2MSHUTDN : 1; /*!< [16..16] The B2M_STATE from the BLE Core transitioned into shutdown - state */ - } INTSET_b; - } ; - - union { - __IOM uint32_t DMATRIGEN; /*!< (@ 0x00000230) DMA Trigger Enable Register */ - - struct { - __IOM uint32_t DCMDCMPEN : 1; /*!< [0..0] Trigger DMA upon command complete. Enables the trigger - of the DMA when a command is completed. When this event - is triggered, the number of words transferred will be the - lesser of the remaining TOTCOUNT bytes, or the number of - bytes in the FIFO when the command completed. If this is - disabled, and the number of bytes in the FIFO is equal - or greater than the TOTCOUNT bytes, a transfer of TOTCOUNT - bytes will be done to ensure read data is stored when the - DMA is completed. */ - __IOM uint32_t DTHREN : 1; /*!< [1..1] Trigger DMA upon THR level reached. For M2P DMA operations - (IOM writes), the trigger will assert when the write FIFO - has (WTHR/4) number of words free in the write FIFO, and - will transfer (WTHR/4) number of wordsor, if the number - of words left to transfer is less than the WTHR value, - will transfer the remaining byte count.For P2M DMA operations, - the trigger will assert when the read FIFO has (RTHR/4) - words available in the read FIFO, and will transfer (RTHR/4) - words to SRAM. This trigger will NOT asser */ - } DMATRIGEN_b; - } ; - - union { - __IOM uint32_t DMATRIGSTAT; /*!< (@ 0x00000234) DMA Trigger Status Register */ - - struct { - __IOM uint32_t DCMDCMP : 1; /*!< [0..0] Triggered DMA from Command complete event. Bit is read - only and can be cleared by disabling the DCMDCMP trigger - enable or by disabling DMA. */ - __IOM uint32_t DTHR : 1; /*!< [1..1] Triggered DMA from THR event. Bit is read only and can - be cleared by disabling the DTHR trigger enable or by disabling - DMA. */ - __IOM uint32_t DTOTCMP : 1; /*!< [2..2] DMA triggered when DCMDCMP = 0, and the amount of data - in the FIFO was enough to complete the DMA operation (greater - than or equal to current TOTCOUNT) when the command completed. - This trigger is default active when the DCMDCMP trigger - isdisabled and there is enough data in the FIFO to complete - the DMA operation. */ - } DMATRIGSTAT_b; - } ; - - union { - __IOM uint32_t DMACFG; /*!< (@ 0x00000238) DMA Configuration Register */ - - struct { - __IOM uint32_t DMAEN : 1; /*!< [0..0] DMA Enable. Setting this bit to EN will start the DMA - operation. This should be the last DMA related register - set prior to issuing the command */ - __IOM uint32_t DMADIR : 1; /*!< [1..1] Direction */ - __IM uint32_t : 6; - __IOM uint32_t DMAPRI : 1; /*!< [8..8] Sets the Priority of the DMA request */ - __IOM uint32_t DPWROFF : 1; /*!< [9..9] Power off module after DMA is complete. If this bit is - active, the module will request to power off the supply - it is attached to. If there are other units still requiring - power from the same domain, power down will not be performed. */ - } DMACFG_b; - } ; - - union { - __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x0000023C) DMA Total Transfer Count */ - - struct { - __IOM uint32_t TOTCOUNT : 12; /*!< [11..0] Triggered DMA from Command complete event occured. Bit - is read only and can be cleared by disabling the DTHR trigger - enable or by disabling DMA. */ - } DMATOTCOUNT_b; - } ; - - union { - __IOM uint32_t DMATARGADDR; /*!< (@ 0x00000240) DMA Target Address Register */ - - struct { - __IOM uint32_t TARGADDR : 20; /*!< [19..0] Bits [19:0] of the target byte address for source of - DMA (either read or write). The address can be any byte - alignment, and does not have to be word aligned. In cases - of non-word aligned addresses, the DMA logic will take - care for ensuring only the target bytes are read/written. */ - __IM uint32_t : 8; - __IOM uint32_t TARGADDR28 : 1; /*!< [28..28] Bit 28 of the target byte address for source of DMA - (either read or write). In cases of non-word aligned addresses, - the DMA logic will take care for ensuring only the target - bytes are read/written.Setting to '1' will select the SRAM. - Setting to '0' will select the flash */ - } DMATARGADDR_b; - } ; - - union { - __IOM uint32_t DMASTAT; /*!< (@ 0x00000244) DMA Status Register */ - - struct { - __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress indicator. 1 will indicate that - a DMA transfer is active. The DMA transfer may be waiting - on data, transferring data, or waiting for priority.All - of these will be indicated with a 1. A 0 will indicate - that the DMA is fully complete and no further transactions - will be done. This bit is read only. */ - __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete. This signals the end of the DMA - operation. This bit can be cleared by writing to 0. */ - __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error. This active high bit signals that an error - was encountered during the DMA operation. */ - } DMASTAT_b; - } ; - - union { - __IOM uint32_t CQCFG; /*!< (@ 0x00000248) Command Queue Configuration Register */ - - struct { - __IOM uint32_t CQEN : 1; /*!< [0..0] Command queue enable. When set, will enable the processing - of the command queue and fetches of address/data pairs - will proceed from the word address within the CQADDR register. - Can be disabledusing a CQ executed write to this bit as - well. */ - __IOM uint32_t CQPRI : 1; /*!< [1..1] Sets the Priority of the command queue dma request. */ - } CQCFG_b; - } ; - - union { - __IOM uint32_t CQADDR; /*!< (@ 0x0000024C) CQ Target Read Address Register */ - - struct { - __IM uint32_t : 2; - __IOM uint32_t CQADDR : 18; /*!< [19..2] Bits 19:2 of target byte address for source of CQ (read - only). The buffer must be aligned on a word boundary */ - __IM uint32_t : 8; - __IOM uint32_t CQADDR28 : 1; /*!< [28..28] Bit 28 of target byte address for source of CQ (read - only). Used to denote Flash (0) or SRAM (1) access */ - } CQADDR_b; - } ; - - union { - __IOM uint32_t CQSTAT; /*!< (@ 0x00000250) Command Queue Status Register */ - - struct { - __IOM uint32_t CQTIP : 1; /*!< [0..0] Command queue Transfer In Progress indicator. 1 will - indicate that a CQ transfer is active and this will remain - active even when paused waiting for external event. */ - __IOM uint32_t CQPAUSED : 1; /*!< [1..1] Command queue operation is currently paused. */ - __IOM uint32_t CQERR : 1; /*!< [2..2] Command queue processing Error. This active high bit - signals that an error was encountered during the CQ operation. */ - } CQSTAT_b; - } ; - - union { - __IOM uint32_t CQFLAGS; /*!< (@ 0x00000254) Command Queue Flag Register */ - - struct { - __IOM uint32_t CQFLAGS : 16; /*!< [15..0] Current flag status (read-only). Bits [7:0] are software - controllable and bits [15:8] are hardware status. */ - __IOM uint32_t CQIRQMASK : 16; /*!< [31..16] Provides for a per-bit mask of the flags used to invoke - an interrupt. A '1' in the bit position will enable the - pause event to trigger the interrupt, if the CQWT_int interrupt - is enabled.Bits definitions are the same as CQPAUSE */ - } CQFLAGS_b; - } ; - - union { - __IOM uint32_t CQSETCLEAR; /*!< (@ 0x00000258) Command Queue Flag Set/Clear Register */ - - struct { - __IOM uint32_t CQFSET : 8; /*!< [7..0] Set CQFlag status bits. Will set to 1 the value of any - SWFLAG with a '1' in the corresponding bit position of - this field */ - __IOM uint32_t CQFTGL : 8; /*!< [15..8] Toggle the indicated bit. Will toggle the value of any - SWFLAG with a '1' in the corresponding bit position of - this field */ - __IOM uint32_t CQFCLR : 8; /*!< [23..16] Clear CQFlag status bits. Will clear to 0 any SWFLAG - with a '1' in the corresponding bit position of this field */ - } CQSETCLEAR_b; - } ; - - union { - __IOM uint32_t CQPAUSEEN; /*!< (@ 0x0000025C) Command Queue Pause Enable Register */ - - struct { - __IOM uint32_t CQPEN : 16; /*!< [15..0] Enables the specified event to pause command processing - when active */ - } CQPAUSEEN_b; - } ; - - union { - __IOM uint32_t CQCURIDX; /*!< (@ 0x00000260) IOM Command Queue current index value . Compared - to the CQENDIDX reg contents to generate - the IDXEQ Pause event for command queue */ - - struct { - __IOM uint32_t CQCURIDX : 8; /*!< [7..0] Holds 8 bits of data that will be compared with the CQENDIX - register field. If the values match, the IDXEQ pause event - will be activated, which will cause the pausing of command - quue operation if the IDXEQ bit is enabled in CQPAUSEEN. */ - } CQCURIDX_b; - } ; - - union { - __IOM uint32_t CQENDIDX; /*!< (@ 0x00000264) IOM Command Queue current index value . Compared - to the CQCURIDX reg contents to generate - the IDXEQ Pause event for command queue */ - - struct { - __IOM uint32_t CQENDIDX : 8; /*!< [7..0] Holds 8 bits of data that will be compared with the CQCURIX - register field. If the values match, the IDXEQ pause event - will be activated, which will cause the pausing of command - quue operation if the IDXEQ bit is enabled in CQPAUSEEN. */ - } CQENDIDX_b; - } ; - - union { - __IOM uint32_t STATUS; /*!< (@ 0x00000268) IOM Module Status Register */ - - struct { - __IOM uint32_t ERR : 1; /*!< [0..0] Bit has been deprecated. Please refer to the other error - indicators. This will always return 0. */ - __IOM uint32_t CMDACT : 1; /*!< [1..1] Indicates if the active I/O Command is currently processing - a transaction, or command is complete, but the FIFO pointers - are still syncronizing internally. This bit will go high - atthe start of the transaction, and will go low when the - command is complete, and the data and pointers within the - FIFO have been syncronized. */ - __IOM uint32_t IDLEST : 1; /*!< [2..2] indicates if the active I/O state machine is IDLE. Note - - The state machine could be in idle state due to holdoffs - from data availability, or as the command gets propagated - into the logic from the registers. */ - } STATUS_b; - } ; - __IM uint32_t RESERVED4[37]; - - union { - __IOM uint32_t MSPICFG; /*!< (@ 0x00000300) SPI module master configuration */ - - struct { - __IOM uint32_t SPOL : 1; /*!< [0..0] This bit selects SPI polarity. */ - __IOM uint32_t SPHA : 1; /*!< [1..1] Selects the SPI phase; When 1, will shift the sampling - edge by 1/2 clock. */ - __IOM uint32_t FULLDUP : 1; /*!< [2..2] Full Duplex mode. Capture read data during writes operations */ - __IM uint32_t : 13; - __IOM uint32_t WTFC : 1; /*!< [16..16] Enables flow control of new write transactions based - on the SPI_STATUS signal from the BLE Core. */ - __IOM uint32_t RDFC : 1; /*!< [17..17] Enables flow control of new read transactions based - on the SPI_STATUS signal from the BLE Core. */ - __IM uint32_t : 3; - __IOM uint32_t WTFCPOL : 1; /*!< [21..21] Selects the write flow control signal polarity. The - transfers are halted when the selected flow control signal - is OPPOSITE polarity of this bit. (For example: WTFCPOL - = 0 will allow a SPI_STATUS=1 to pause transfers). */ - __IOM uint32_t RDFCPOL : 1; /*!< [22..22] Selects the read flow control signal polarity. When - set, the clock will be held low until the flow control - is de-asserted. */ - __IOM uint32_t SPILSB : 1; /*!< [23..23] Selects data transfer as MSB first (0) or LSB first - (1) for the data portion of the SPI transaction. The offset - bytes are always transmitted MSB first. */ - __IOM uint32_t DINDLY : 3; /*!< [26..24] Delay tap to use for the input signal (MISO). This - gives more hold time on the input data. */ - __IOM uint32_t DOUTDLY : 3; /*!< [29..27] Delay tap to use for the output signal (MOSI). This - give more hold time on the output data. */ - __IOM uint32_t MSPIRST : 1; /*!< [30..30] Bit is deprecated. setting it will have no effect. */ - } MSPICFG_b; - } ; - - union { - __IOM uint32_t BLECFG; /*!< (@ 0x00000304) BLE Core Control */ - - struct { - __IOM uint32_t PWRSMEN : 1; /*!< [0..0] Enable the power state machine for automatic sequencing - and control of power states of the BLE Core module. */ - __IOM uint32_t BLERSTN : 1; /*!< [1..1] Reset line to the BLE Core. This will reset the BLE core - when asserted ('0') and must be written to '1' prior to - performing any BTLE related operations to the core. */ - __IOM uint32_t WAKEUPCTL : 2; /*!< [3..2] WAKE signal override. Controls the source of the WAKE - signal to the BLE Core. */ - __IOM uint32_t DCDCFLGCTL : 2; /*!< [5..4] DCDCFLG signal override. The value of this field will - be sent to the BLE Core when the PWRSM is off. Otherwise, - the value is supplied from internal logic. */ - __IOM uint32_t BLEHREQCTL : 2; /*!< [7..6] BLEH power on request override. The value of this field - will be sent to the BLE Core when the PWRSM is off. Otherwise, - the value is supplied from internal logic. */ - __IOM uint32_t WT4ACTOFF : 1; /*!< [8..8] Debug control of BLEIF power state machine. Allows transition - into the active state in the BLEIF state without waiting - for dcdc req from BLE Core. */ - __IOM uint32_t MCUFRCSLP : 1; /*!< [9..9] Force power state machine to go to the sleep state. Intended - for debug only. Has no effect on the actual BLE Core state, - only the state of the BLEIF interface state machine. */ - __IOM uint32_t FRCCLK : 1; /*!< [10..10] Force the clock in the BLEIF to be always running */ - __IOM uint32_t STAYASLEEP : 1; /*!< [11..11] Set to prevent the BLE power control module from waking - up the BLE Core after going into power down. To be used - for graceful shutdown, set by software prior to powering - off and will allow assertion of reset from sleep state. */ - __IOM uint32_t PWRISOCTL : 2; /*!< [13..12] Configuration of BLEH isolation control for power related - signals. */ - __IOM uint32_t SPIISOCTL : 2; /*!< [15..14] Configuration of BLEH isolation controls for SPI related - signals. */ - } BLECFG_b; - } ; - - union { - __IOM uint32_t PWRCMD; /*!< (@ 0x00000308) BLE Power command interface */ - - struct { - __IOM uint32_t WAKEREQ : 1; /*!< [0..0] Wake request from the MCU. When asserted (1), the BLE - Interface logic will assert the wakeup request signal to - the BLE Core. Only recognized when in the sleep state */ - __IOM uint32_t RESTART : 1; /*!< [1..1] Restart the BLE Core after going into the shutdown state. - Only valid when in the shutdown state. */ - } PWRCMD_b; - } ; - - union { - __IOM uint32_t BSTATUS; /*!< (@ 0x0000030C) BLE Core status */ - - struct { - __IOM uint32_t B2MSTATE : 3; /*!< [2..0] State of the BLE Core logic. */ - __IOM uint32_t SPISTATUS : 1; /*!< [3..3] Value of the SPISTATUS signal from the BLE Core. The - signal is asserted when the BLE Core is able to accept - write data via the SPI interface. Data should be transmitted - to theBLE core only when this signal is 1. The hardware - will automatically wait for this signal prior to performing - a write operation if flow control is active. */ - __IOM uint32_t DCDCREQ : 1; /*!< [4..4] Value of the DCDCREQ signal from the BLE Core. The DCDCREQ - signal is sent from the core to the BLEIF module when the - BLE core requires BLEH power to be active. When activated, - this isindicated by DCDCFLAG going to 1. */ - __IOM uint32_t DCDCFLAG : 1; /*!< [5..5] Value of the DCDCFLAG signal to the BLE Core. The DCDCFLAG - is a signal to the BLE Core indicating that the BLEH ppower - is active. */ - __IOM uint32_t WAKEUP : 1; /*!< [6..6] Value of the WAKEUP signal to the BLE Core . The WAKEUP - signals is sent from the BLEIF to the BLECORE to request - the BLE Core transition from sleep state to active state. */ - __IOM uint32_t BLEIRQ : 1; /*!< [7..7] Status of the BLEIRQ signal from the BLE Core. A value - of 1 idicates that read data is available in the core and - a read operation needs to be performed. */ - __IOM uint32_t PWRST : 3; /*!< [10..8] Current status of the power state machine */ - __IOM uint32_t BLEHACK : 1; /*!< [11..11] Value of the BLEHACK signal from the power control - unit. If the signal is '1', the BLEH power is active and - ready for use. */ - __IOM uint32_t BLEHREQ : 1; /*!< [12..12] Value of the BLEHREQ signal to the power control unit. - The BLEHREQ signal is sent from the BLEIF module to the - power control module to request the BLEH power up. When - the BLEHACK signal is asserted,BLEH power is stable and - ready for use. */ - } BSTATUS_b; - } ; - __IM uint32_t RESERVED5[64]; - - union { - __IOM uint32_t BLEDBG; /*!< (@ 0x00000410) BLEIF Master Debug Register */ - - struct { - __IOM uint32_t DBGEN : 1; /*!< [0..0] Debug Enable. Setting this bit will enable the update - of data within this register, otherwise it is clock gated - for power savings */ - __IOM uint32_t IOCLKON : 1; /*!< [1..1] IOCLK debug clock control. Enable IO_CLK to be active - when this bit is '1'. Otherwise, the clock is controlled - with gating from the logic as needed. */ - __IOM uint32_t APBCLKON : 1; /*!< [2..2] APBCLK debug clock control. Enable APB_CLK to be active - when this bit is '1'. Otherwise, the clock is controlled - with gating from the logic as needed. */ - __IOM uint32_t DBGDATA : 29; /*!< [31..3] Debug data */ - } BLEDBG_b; - } ; -} BLEIF_Type; /*!< Size = 1044 (0x414) */ - - - -/* =========================================================================================================================== */ -/* ================ CACHECTRL ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Flash Cache Controller (CACHECTRL) - */ - -typedef struct { /*!< (@ 0x40018000) CACHECTRL Structure */ - - union { - __IOM uint32_t CACHECFG; /*!< (@ 0x00000000) Flash Cache Control Register */ - - struct { - __IOM uint32_t ENABLE : 1; /*!< [0..0] Enables the flash cache controller and enables power - to the cache SRAMs. The ICACHE_ENABLE and DCACHE_ENABLE - should be set to enable caching for each type of access. */ - __IOM uint32_t LRU : 1; /*!< [1..1] Sets the cache repleacment policy. 0=LRR (least recently - replaced), 1=LRU (least recently used). LRR minimizes writes - to the TAG SRAM. */ - __IOM uint32_t ENABLE_NC0 : 1; /*!< [2..2] Enable Non-cacheable region 0. See NCR0 registers to - define the region. */ - __IOM uint32_t ENABLE_NC1 : 1; /*!< [3..3] Enable Non-cacheable region 1. See NCR1 registers to - define the region. */ - __IOM uint32_t CONFIG : 4; /*!< [7..4] Sets the cache configuration */ - __IOM uint32_t ICACHE_ENABLE : 1; /*!< [8..8] Enable Flash Instruction Caching */ - __IOM uint32_t DCACHE_ENABLE : 1; /*!< [9..9] Enable Flash Data Caching. */ - __IOM uint32_t CACHE_CLKGATE : 1; /*!< [10..10] Enable clock gating of cache TAG RAM. Software should - enable this bit for optimal power efficiency. */ - __IOM uint32_t CACHE_LS : 1; /*!< [11..11] Enable LS (light sleep) of cache RAMs. Software should - DISABLE this bit since cache activity is too high to benefit - from LS usage. */ - __IM uint32_t : 8; - __IOM uint32_t DATA_CLKGATE : 1; /*!< [20..20] Enable aggressive clock gating of entire data array. - This bit should be set to 1 for optimal power efficiency. */ - __IM uint32_t : 3; - __IOM uint32_t ENABLE_MONITOR : 1; /*!< [24..24] Enable Cache Monitoring Stats. Cache monitoring consumes - additional power and should only be enabled when profiling - code and counters will increment when this bit is set. - Counter values will be retained when this is set to 0, - allowing software to enable/disable counting for multiple - code segments. */ - } CACHECFG_b; - } ; - - union { - __IOM uint32_t FLASHCFG; /*!< (@ 0x00000004) Flash Control Register */ - - struct { - __IOM uint32_t RD_WAIT : 4; /*!< [3..0] Sets read waitstates for normal (fast) operation. A value - of 1 is recommended. */ - __IOM uint32_t SEDELAY : 3; /*!< [6..4] Sets SE delay (flash address setup). A value of 5 is - recommended. */ - __IM uint32_t : 1; - __IOM uint32_t LPM_RD_WAIT : 4; /*!< [11..8] Sets flash waitstates when in LPM Mode 2 (RD_WAIT in - LPM mode 2 only) */ - __IOM uint32_t LPMMODE : 2; /*!< [13..12] Controls flash low power modes (control of LPM pin). */ - } FLASHCFG_b; - } ; - - union { - __IOM uint32_t CTRL; /*!< (@ 0x00000008) Cache Control */ - - struct { - __IOM uint32_t INVALIDATE : 1; /*!< [0..0] Writing a 1 to this bitfield invalidates the flash cache - contents. */ - __IOM uint32_t RESET_STAT : 1; /*!< [1..1] Reset Cache Statistics. When written to a 1, the cache - monitor counters will be cleared. The monitor counters - can be reset only when the CACHECFG.ENABLE_MONITOR bit - is set. */ - __IOM uint32_t CACHE_READY : 1; /*!< [2..2] Cache Ready Status (enabled and not processing an invalidate - operation) */ - __IM uint32_t : 1; - __IOM uint32_t FLASH0_SLM_STATUS : 1; /*!< [4..4] Flash Sleep Mode Status. 1 indicates that flash0 is in - sleep mode, 0 indicates flash0 is in normal mode. */ - __IOM uint32_t FLASH0_SLM_DISABLE : 1; /*!< [5..5] Disable Flash Sleep Mode. Write 1 to wake flash0 from - sleep mode (reading the array will also automatically wake - it). */ - __IOM uint32_t FLASH0_SLM_ENABLE : 1; /*!< [6..6] Enable Flash Sleep Mode. Write to 1 to put flash 0 into - sleep mode. NOTE: there is a 5us latency after waking flash - until the first access will be returned. */ - __IM uint32_t : 1; - __IOM uint32_t FLASH1_SLM_STATUS : 1; /*!< [8..8] Flash Sleep Mode Status. 1 indicates that flash1 is in - sleep mode, 0 indicates flash1 is in normal mode. */ - __IOM uint32_t FLASH1_SLM_DISABLE : 1; /*!< [9..9] Disable Flash Sleep Mode. Write 1 to wake flash1 from - sleep mode (reading the array will also automatically wake - it). */ - __IOM uint32_t FLASH1_SLM_ENABLE : 1; /*!< [10..10] Enable Flash Sleep Mode. Write to 1 to put flash 1 - into sleep mode. NOTE: there is a 5us latency after waking - flash until the first access will be returned. */ - } CTRL_b; - } ; - __IM uint32_t RESERVED; - - union { - __IOM uint32_t NCR0START; /*!< (@ 0x00000010) Flash Cache Noncachable Region 0 Start */ - - struct { - __IM uint32_t : 4; - __IOM uint32_t ADDR : 23; /*!< [26..4] Start address for non-cacheable region 0 */ - } NCR0START_b; - } ; - - union { - __IOM uint32_t NCR0END; /*!< (@ 0x00000014) Flash Cache Noncachable Region 0 End */ - - struct { - __IM uint32_t : 4; - __IOM uint32_t ADDR : 23; /*!< [26..4] End address for non-cacheable region 0 */ - } NCR0END_b; - } ; - - union { - __IOM uint32_t NCR1START; /*!< (@ 0x00000018) Flash Cache Noncachable Region 1 Start */ - - struct { - __IM uint32_t : 4; - __IOM uint32_t ADDR : 23; /*!< [26..4] Start address for non-cacheable region 1 */ - } NCR1START_b; - } ; - - union { - __IOM uint32_t NCR1END; /*!< (@ 0x0000001C) Flash Cache Noncachable Region 1 End */ - - struct { - __IM uint32_t : 4; - __IOM uint32_t ADDR : 23; /*!< [26..4] End address for non-cacheable region 1 */ - } NCR1END_b; - } ; - __IM uint32_t RESERVED1[8]; - - union { - __IOM uint32_t DMON0; /*!< (@ 0x00000040) Data Cache Total Accesses */ - - struct { - __IOM uint32_t DACCESS_COUNT : 32; /*!< [31..0] Total accesses to data cache. All performance metrics - should be relative to the number of accesses performed. */ - } DMON0_b; - } ; - - union { - __IOM uint32_t DMON1; /*!< (@ 0x00000044) Data Cache Tag Lookups */ - - struct { - __IOM uint32_t DLOOKUP_COUNT : 32; /*!< [31..0] Total tag lookups from data cache. */ - } DMON1_b; - } ; - - union { - __IOM uint32_t DMON2; /*!< (@ 0x00000048) Data Cache Hits */ - - struct { - __IOM uint32_t DHIT_COUNT : 32; /*!< [31..0] Cache hits from lookup operations. */ - } DMON2_b; - } ; - - union { - __IOM uint32_t DMON3; /*!< (@ 0x0000004C) Data Cache Line Hits */ - - struct { - __IOM uint32_t DLINE_COUNT : 32; /*!< [31..0] Cache hits from line cache */ - } DMON3_b; - } ; - - union { - __IOM uint32_t IMON0; /*!< (@ 0x00000050) Instruction Cache Total Accesses */ - - struct { - __IOM uint32_t IACCESS_COUNT : 32; /*!< [31..0] Total accesses to Instruction cache */ - } IMON0_b; - } ; - - union { - __IOM uint32_t IMON1; /*!< (@ 0x00000054) Instruction Cache Tag Lookups */ - - struct { - __IOM uint32_t ILOOKUP_COUNT : 32; /*!< [31..0] Total tag lookups from Instruction cache */ - } IMON1_b; - } ; - - union { - __IOM uint32_t IMON2; /*!< (@ 0x00000058) Instruction Cache Hits */ - - struct { - __IOM uint32_t IHIT_COUNT : 32; /*!< [31..0] Cache hits from lookup operations */ - } IMON2_b; - } ; - - union { - __IOM uint32_t IMON3; /*!< (@ 0x0000005C) Instruction Cache Line Hits */ - - struct { - __IOM uint32_t ILINE_COUNT : 32; /*!< [31..0] Cache hits from line cache */ - } IMON3_b; - } ; -} CACHECTRL_Type; /*!< Size = 96 (0x60) */ - - - -/* =========================================================================================================================== */ -/* ================ CLKGEN ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Clock Generator (CLKGEN) - */ - -typedef struct { /*!< (@ 0x40004000) CLKGEN Structure */ - - union { - __IOM uint32_t CALXT; /*!< (@ 0x00000000) XT Oscillator Control */ - - struct { - __IOM uint32_t CALXT : 11; /*!< [10..0] XT Oscillator calibration value. This register will - enable the hardware to increase or decrease the number - of cycles in a 16KHz clock derived from the original 32KHz - version. The most significant bit is the sign. A '1' is - a reduction, and a '0' is an addition. This calibration - value will add or reduce the number of cycles programmed - here across a 32 second interval. The maximum value that - is effective is from -1024 to 1023. */ - } CALXT_b; - } ; - - union { - __IOM uint32_t CALRC; /*!< (@ 0x00000004) RC Oscillator Control */ - - struct { - __IOM uint32_t CALRC : 18; /*!< [17..0] LFRC Oscillator calibration value. This register will - enable the hardware to increase or decrease the number - of cycles in a 512 Hz clock derived from the original 1024 - version. The most significant bit is the sign. A '1' is - a reduction, and a '0' is an addition. This calibration - value will add or reduce the number of cycles programmed - here across a 32 second interval. The range is from -131072 - (decimal) to 131071 (decimal). This register is normally - used in conjuction with ACALCTR register. The CAL */ - } CALRC_b; - } ; - - union { - __IOM uint32_t ACALCTR; /*!< (@ 0x00000008) Autocalibration Counter */ - - struct { - __IOM uint32_t ACALCTR : 24; /*!< [23..0] Autocalibration Counter result. Bits 17 down to 0 of - this is feed directly to the CALRC register if ACAL register - in OCTRL register is set to 1024SEC or 512SEC. */ - } ACALCTR_b; - } ; - - union { - __IOM uint32_t OCTRL; /*!< (@ 0x0000000C) Oscillator Control */ - - struct { - __IOM uint32_t STOPXT : 1; /*!< [0..0] Stop the XT Oscillator to the RTC */ - __IOM uint32_t STOPRC : 1; /*!< [1..1] Stop the LFRC Oscillator to the RTC */ - __IM uint32_t : 4; - __IOM uint32_t FOS : 1; /*!< [6..6] Oscillator switch on failure function. If this is set, - then LFRC clock source will switch from XT to RC. */ - __IOM uint32_t OSEL : 1; /*!< [7..7] Selects the RTC oscillator (1 => LFRC, 0 => XT) */ - __IOM uint32_t ACAL : 3; /*!< [10..8] Autocalibration control. This selects the source to - be used in the autocalibration flow. This flow can also - be used to measure an internal clock against an external - clock source, with the external clock normally used as - the reference. */ - } OCTRL_b; - } ; - - union { - __IOM uint32_t CLKOUT; /*!< (@ 0x00000010) CLKOUT Frequency Select */ - - struct { - __IOM uint32_t CKSEL : 6; /*!< [5..0] CLKOUT signal select */ - __IM uint32_t : 1; - __IOM uint32_t CKEN : 1; /*!< [7..7] Enable the CLKOUT signal */ - } CLKOUT_b; - } ; - - union { - __IOM uint32_t CLKKEY; /*!< (@ 0x00000014) Key Register for Clock Control Register */ - - struct { - __IOM uint32_t CLKKEY : 32; /*!< [31..0] Key register value. */ - } CLKKEY_b; - } ; - - union { - __IOM uint32_t CCTRL; /*!< (@ 0x00000018) HFRC Clock Control */ - - struct { - __IOM uint32_t CORESEL : 1; /*!< [0..0] Core Clock divisor */ - } CCTRL_b; - } ; - - union { - __IOM uint32_t STATUS; /*!< (@ 0x0000001C) Clock Generator Status */ - - struct { - __IOM uint32_t OMODE : 1; /*!< [0..0] Current RTC oscillator (1 => LFRC, 0 => XT). After an - RTC oscillator change, it may take up to 2 seconds for - this field to reflect the new oscillator. */ - __IOM uint32_t OSCF : 1; /*!< [1..1] XT Oscillator is enabled but not oscillating */ - } STATUS_b; - } ; - - union { - __IOM uint32_t HFADJ; /*!< (@ 0x00000020) HFRC Adjustment */ - - struct { - __IOM uint32_t HFADJEN : 1; /*!< [0..0] HFRC adjustment control */ - __IOM uint32_t HFADJCK : 3; /*!< [3..1] Repeat period for HFRC adjustment */ - __IM uint32_t : 4; - __IOM uint32_t HFXTADJ : 12; /*!< [19..8] Target HFRC adjustment value. */ - __IOM uint32_t HFWARMUP : 1; /*!< [20..20] XT warmup period for HFRC adjustment */ - __IOM uint32_t HFADJGAIN : 3; /*!< [23..21] Gain control for HFRC adjustment */ - } HFADJ_b; - } ; - __IM uint32_t RESERVED; - - union { - __IOM uint32_t CLOCKENSTAT; /*!< (@ 0x00000028) Clock Enable Status */ - - struct { - __IOM uint32_t CLOCKENSTAT : 32; /*!< [31..0] Clock enable status */ - } CLOCKENSTAT_b; - } ; - - union { - __IOM uint32_t CLOCKEN2STAT; /*!< (@ 0x0000002C) Clock Enable Status */ - - struct { - __IOM uint32_t CLOCKEN2STAT : 32; /*!< [31..0] Clock enable status 2 */ - } CLOCKEN2STAT_b; - } ; - - union { - __IOM uint32_t CLOCKEN3STAT; /*!< (@ 0x00000030) Clock Enable Status */ - - struct { - __IOM uint32_t CLOCKEN3STAT : 32; /*!< [31..0] Clock enable status 3 */ - } CLOCKEN3STAT_b; - } ; - - union { - __IOM uint32_t FREQCTRL; /*!< (@ 0x00000034) HFRC Frequency Control register */ - - struct { - __IOM uint32_t BURSTREQ : 1; /*!< [0..0] Frequency Burst Enable Request */ - __IOM uint32_t BURSTACK : 1; /*!< [1..1] Frequency Burst Request Acknowledge. Frequency burst - requested is always acknowledged whether burst is granted - or not depending on feature enable. */ - __IOM uint32_t BURSTSTATUS : 1; /*!< [2..2] This represents frequency burst status. */ - } FREQCTRL_b; - } ; - __IM uint32_t RESERVED1; - - union { - __IOM uint32_t BLEBUCKTONADJ; /*!< (@ 0x0000003C) BLE BUCK TON ADJUST */ - - struct { - __IOM uint32_t TONLOWTHRESHOLD : 10; /*!< [9..0] TON ADJUST LOW THRESHOLD. Suggested values are #A(94KHz) - #15(47KHz) #53(12Khz) #14D(3Khz) */ - __IOM uint32_t TONHIGHTHRESHOLD : 10; /*!< [19..10] TON ADJUST HIGH THRESHOLD. Suggested values are #15(94KHz) - #2A(47Khz) #A6(12Khz) #29A(3Khz) */ - __IOM uint32_t TONADJUSTPERIOD : 2; /*!< [21..20] TON ADJUST PERIOD */ - __IOM uint32_t TONADJUSTEN : 1; /*!< [22..22] TON ADJUST ENABLE */ - __IOM uint32_t ZEROLENDETECTTRIM : 4; /*!< [26..23] BLEBUCK ZERO LENGTH DETECT TRIM */ - __IOM uint32_t ZEROLENDETECTEN : 1; /*!< [27..27] BLEBUCK ZERO LENGTH DETECT ENABLE */ - } BLEBUCKTONADJ_b; - } ; - __IM uint32_t RESERVED2[48]; - - union { - __IOM uint32_t INTRPTEN; /*!< (@ 0x00000100) CLKGEN Interrupt Register: Enable */ - - struct { - __IOM uint32_t ACF : 1; /*!< [0..0] Autocalibration Fail interrupt */ - __IOM uint32_t ACC : 1; /*!< [1..1] Autocalibration Complete interrupt */ - __IOM uint32_t OF : 1; /*!< [2..2] XT Oscillator Fail interrupt */ - } INTRPTEN_b; - } ; - - union { - __IOM uint32_t INTRPTSTAT; /*!< (@ 0x00000104) CLKGEN Interrupt Register: Status */ - - struct { - __IOM uint32_t ACF : 1; /*!< [0..0] Autocalibration Fail interrupt */ - __IOM uint32_t ACC : 1; /*!< [1..1] Autocalibration Complete interrupt */ - __IOM uint32_t OF : 1; /*!< [2..2] XT Oscillator Fail interrupt */ - } INTRPTSTAT_b; - } ; - - union { - __IOM uint32_t INTRPTCLR; /*!< (@ 0x00000108) CLKGEN Interrupt Register: Clear */ - - struct { - __IOM uint32_t ACF : 1; /*!< [0..0] Autocalibration Fail interrupt */ - __IOM uint32_t ACC : 1; /*!< [1..1] Autocalibration Complete interrupt */ - __IOM uint32_t OF : 1; /*!< [2..2] XT Oscillator Fail interrupt */ - } INTRPTCLR_b; - } ; - - union { - __IOM uint32_t INTRPTSET; /*!< (@ 0x0000010C) CLKGEN Interrupt Register: Set */ - - struct { - __IOM uint32_t ACF : 1; /*!< [0..0] Autocalibration Fail interrupt */ - __IOM uint32_t ACC : 1; /*!< [1..1] Autocalibration Complete interrupt */ - __IOM uint32_t OF : 1; /*!< [2..2] XT Oscillator Fail interrupt */ - } INTRPTSET_b; - } ; -} CLKGEN_Type; /*!< Size = 272 (0x110) */ - - - -/* =========================================================================================================================== */ -/* ================ CTIMER ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Counter/Timer (CTIMER) - */ - -typedef struct { /*!< (@ 0x40008000) CTIMER Structure */ - - union { - __IOM uint32_t TMR0; /*!< (@ 0x00000000) Counter/Timer Register */ - - struct { - __IOM uint32_t CTTMRA0 : 16; /*!< [15..0] Counter/Timer A0. */ - __IOM uint32_t CTTMRB0 : 16; /*!< [31..16] Counter/Timer B0. */ - } TMR0_b; - } ; - - union { - __IOM uint32_t CMPRA0; /*!< (@ 0x00000004) Counter/Timer A0 Compare Registers */ - - struct { - __IOM uint32_t CMPR0A0 : 16; /*!< [15..0] Counter/Timer A0 Compare Register 0. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR1A0 : 16; /*!< [31..16] Counter/Timer A0 Compare Register 1. Holds the upper - limit for timer half A. */ - } CMPRA0_b; - } ; - - union { - __IOM uint32_t CMPRB0; /*!< (@ 0x00000008) Counter/Timer B0 Compare Registers */ - - struct { - __IOM uint32_t CMPR0B0 : 16; /*!< [15..0] Counter/Timer B0 Compare Register 0. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR1B0 : 16; /*!< [31..16] Counter/Timer B0 Compare Register 1. Holds the upper - limit for timer half B. */ - } CMPRB0_b; - } ; - - union { - __IOM uint32_t CTRL0; /*!< (@ 0x0000000C) Counter/Timer Control */ - - struct { - __IOM uint32_t TMRA0EN : 1; /*!< [0..0] Counter/Timer A0 Enable bit. */ - __IOM uint32_t TMRA0CLK : 5; /*!< [5..1] Counter/Timer A0 Clock Select. */ - __IOM uint32_t TMRA0FN : 3; /*!< [8..6] Counter/Timer A0 Function Select. */ - __IOM uint32_t TMRA0IE0 : 1; /*!< [9..9] Counter/Timer A0 Interrupt Enable bit based on COMPR0. */ - __IOM uint32_t TMRA0IE1 : 1; /*!< [10..10] Counter/Timer A0 Interrupt Enable bit based on COMPR1. */ - __IOM uint32_t TMRA0CLR : 1; /*!< [11..11] Counter/Timer A0 Clear bit. */ - __IOM uint32_t TMRA0POL : 1; /*!< [12..12] Counter/Timer A0 output polarity. */ - __IM uint32_t : 3; - __IOM uint32_t TMRB0EN : 1; /*!< [16..16] Counter/Timer B0 Enable bit. */ - __IOM uint32_t TMRB0CLK : 5; /*!< [21..17] Counter/Timer B0 Clock Select. */ - __IOM uint32_t TMRB0FN : 3; /*!< [24..22] Counter/Timer B0 Function Select. */ - __IOM uint32_t TMRB0IE0 : 1; /*!< [25..25] Counter/Timer B0 Interrupt Enable bit for COMPR0. */ - __IOM uint32_t TMRB0IE1 : 1; /*!< [26..26] Counter/Timer B0 Interrupt Enable bit for COMPR1. */ - __IOM uint32_t TMRB0CLR : 1; /*!< [27..27] Counter/Timer B0 Clear bit. */ - __IOM uint32_t TMRB0POL : 1; /*!< [28..28] Counter/Timer B0 output polarity. */ - __IM uint32_t : 2; - __IOM uint32_t CTLINK0 : 1; /*!< [31..31] Counter/Timer A0/B0 Link bit. */ - } CTRL0_b; - } ; - __IM uint32_t RESERVED; - - union { - __IOM uint32_t CMPRAUXA0; /*!< (@ 0x00000014) Counter/Timer A0 Compare Registers */ - - struct { - __IOM uint32_t CMPR2A0 : 16; /*!< [15..0] Counter/Timer A0 Compare Register 2. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR3A0 : 16; /*!< [31..16] Counter/Timer A0 Compare Register 3. Holds the upper - limit for timer half A. */ - } CMPRAUXA0_b; - } ; - - union { - __IOM uint32_t CMPRAUXB0; /*!< (@ 0x00000018) Counter/Timer B0 Compare Registers */ - - struct { - __IOM uint32_t CMPR2B0 : 16; /*!< [15..0] Counter/Timer B0 Compare Register 2. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR3B0 : 16; /*!< [31..16] Counter/Timer B0 Compare Register 3. Holds the upper - limit for timer half B. */ - } CMPRAUXB0_b; - } ; - - union { - __IOM uint32_t AUX0; /*!< (@ 0x0000001C) Counter/Timer Auxiliary */ - - struct { - __IOM uint32_t TMRA0LMT : 7; /*!< [6..0] Counter/Timer A0 Pattern Limit Count. */ - __IOM uint32_t TMRA0TRIG : 4; /*!< [10..7] Counter/Timer A0 Trigger Select. */ - __IOM uint32_t TMRA0NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ - __IOM uint32_t TMRA0TINV : 1; /*!< [12..12] Counter/Timer A0 Invert on trigger. */ - __IOM uint32_t TMRA0POL23 : 1; /*!< [13..13] Counter/Timer A0 Upper output polarity */ - __IOM uint32_t TMRA0EN23 : 1; /*!< [14..14] Counter/Timer A0 Upper compare enable. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB0LMT : 6; /*!< [21..16] Counter/Timer B0 Pattern Limit Count. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB0TRIG : 4; /*!< [26..23] Counter/Timer B0 Trigger Select. */ - __IOM uint32_t TMRB0NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ - __IOM uint32_t TMRB0TINV : 1; /*!< [28..28] Counter/Timer B0 Invert on trigger. */ - __IOM uint32_t TMRB0POL23 : 1; /*!< [29..29] Upper output polarity */ - __IOM uint32_t TMRB0EN23 : 1; /*!< [30..30] Counter/Timer B0 Upper compare enable. */ - } AUX0_b; - } ; - - union { - __IOM uint32_t TMR1; /*!< (@ 0x00000020) Counter/Timer Register */ - - struct { - __IOM uint32_t CTTMRA1 : 16; /*!< [15..0] Counter/Timer A1. */ - __IOM uint32_t CTTMRB1 : 16; /*!< [31..16] Counter/Timer B1. */ - } TMR1_b; - } ; - - union { - __IOM uint32_t CMPRA1; /*!< (@ 0x00000024) Counter/Timer A1 Compare Registers */ - - struct { - __IOM uint32_t CMPR0A1 : 16; /*!< [15..0] Counter/Timer A1 Compare Register 0. */ - __IOM uint32_t CMPR1A1 : 16; /*!< [31..16] Counter/Timer A1 Compare Register 1. */ - } CMPRA1_b; - } ; - - union { - __IOM uint32_t CMPRB1; /*!< (@ 0x00000028) Counter/Timer B1 Compare Registers */ - - struct { - __IOM uint32_t CMPR0B1 : 16; /*!< [15..0] Counter/Timer B1 Compare Register 0. */ - __IOM uint32_t CMPR1B1 : 16; /*!< [31..16] Counter/Timer B1 Compare Register 1. */ - } CMPRB1_b; - } ; - - union { - __IOM uint32_t CTRL1; /*!< (@ 0x0000002C) Counter/Timer Control */ - - struct { - __IOM uint32_t TMRA1EN : 1; /*!< [0..0] Counter/Timer A1 Enable bit. */ - __IOM uint32_t TMRA1CLK : 5; /*!< [5..1] Counter/Timer A1 Clock Select. */ - __IOM uint32_t TMRA1FN : 3; /*!< [8..6] Counter/Timer A1 Function Select. */ - __IOM uint32_t TMRA1IE0 : 1; /*!< [9..9] Counter/Timer A1 Interrupt Enable bit based on COMPR0. */ - __IOM uint32_t TMRA1IE1 : 1; /*!< [10..10] Counter/Timer A1 Interrupt Enable bit based on COMPR1. */ - __IOM uint32_t TMRA1CLR : 1; /*!< [11..11] Counter/Timer A1 Clear bit. */ - __IOM uint32_t TMRA1POL : 1; /*!< [12..12] Counter/Timer A1 output polarity. */ - __IM uint32_t : 3; - __IOM uint32_t TMRB1EN : 1; /*!< [16..16] Counter/Timer B1 Enable bit. */ - __IOM uint32_t TMRB1CLK : 5; /*!< [21..17] Counter/Timer B1 Clock Select. */ - __IOM uint32_t TMRB1FN : 3; /*!< [24..22] Counter/Timer B1 Function Select. */ - __IOM uint32_t TMRB1IE0 : 1; /*!< [25..25] Counter/Timer B1 Interrupt Enable bit for COMPR0. */ - __IOM uint32_t TMRB1IE1 : 1; /*!< [26..26] Counter/Timer B1 Interrupt Enable bit for COMPR1. */ - __IOM uint32_t TMRB1CLR : 1; /*!< [27..27] Counter/Timer B1 Clear bit. */ - __IOM uint32_t TMRB1POL : 1; /*!< [28..28] Counter/Timer B1 output polarity. */ - __IM uint32_t : 2; - __IOM uint32_t CTLINK1 : 1; /*!< [31..31] Counter/Timer A1/B1 Link bit. */ - } CTRL1_b; - } ; - __IM uint32_t RESERVED1; - - union { - __IOM uint32_t CMPRAUXA1; /*!< (@ 0x00000034) Counter/Timer A1 Compare Registers */ - - struct { - __IOM uint32_t CMPR2A1 : 16; /*!< [15..0] Counter/Timer A1 Compare Register 2. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR3A1 : 16; /*!< [31..16] Counter/Timer A1 Compare Register 3. Holds the upper - limit for timer half A. */ - } CMPRAUXA1_b; - } ; - - union { - __IOM uint32_t CMPRAUXB1; /*!< (@ 0x00000038) Counter/Timer B1 Compare Registers */ - - struct { - __IOM uint32_t CMPR2B1 : 16; /*!< [15..0] Counter/Timer B1 Compare Register 2. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR3B1 : 16; /*!< [31..16] Counter/Timer B1 Compare Register 3. Holds the upper - limit for timer half B. */ - } CMPRAUXB1_b; - } ; - - union { - __IOM uint32_t AUX1; /*!< (@ 0x0000003C) Counter/Timer Auxiliary */ - - struct { - __IOM uint32_t TMRA1LMT : 7; /*!< [6..0] Counter/Timer A1 Pattern Limit Count. */ - __IOM uint32_t TMRA1TRIG : 4; /*!< [10..7] Counter/Timer A1 Trigger Select. */ - __IOM uint32_t TMRA1NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ - __IOM uint32_t TMRA1TINV : 1; /*!< [12..12] Counter/Timer A1 Invert on trigger. */ - __IOM uint32_t TMRA1POL23 : 1; /*!< [13..13] Counter/Timer A1 Upper output polarity */ - __IOM uint32_t TMRA1EN23 : 1; /*!< [14..14] Counter/Timer A1 Upper compare enable. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB1LMT : 6; /*!< [21..16] Counter/Timer B1 Pattern Limit Count. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB1TRIG : 4; /*!< [26..23] Counter/Timer B1 Trigger Select. */ - __IOM uint32_t TMRB1NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ - __IOM uint32_t TMRB1TINV : 1; /*!< [28..28] Counter/Timer B1 Invert on trigger. */ - __IOM uint32_t TMRB1POL23 : 1; /*!< [29..29] Upper output polarity */ - __IOM uint32_t TMRB1EN23 : 1; /*!< [30..30] Counter/Timer B1 Upper compare enable. */ - } AUX1_b; - } ; - - union { - __IOM uint32_t TMR2; /*!< (@ 0x00000040) Counter/Timer Register */ - - struct { - __IOM uint32_t CTTMRA2 : 16; /*!< [15..0] Counter/Timer A2. */ - __IOM uint32_t CTTMRB2 : 16; /*!< [31..16] Counter/Timer B2. */ - } TMR2_b; - } ; - - union { - __IOM uint32_t CMPRA2; /*!< (@ 0x00000044) Counter/Timer A2 Compare Registers */ - - struct { - __IOM uint32_t CMPR0A2 : 16; /*!< [15..0] Counter/Timer A2 Compare Register 0. */ - __IOM uint32_t CMPR1A2 : 16; /*!< [31..16] Counter/Timer A2 Compare Register 1. */ - } CMPRA2_b; - } ; - - union { - __IOM uint32_t CMPRB2; /*!< (@ 0x00000048) Counter/Timer B2 Compare Registers */ - - struct { - __IOM uint32_t CMPR0B2 : 16; /*!< [15..0] Counter/Timer B2 Compare Register 0. */ - __IOM uint32_t CMPR1B2 : 16; /*!< [31..16] Counter/Timer B2 Compare Register 1. */ - } CMPRB2_b; - } ; - - union { - __IOM uint32_t CTRL2; /*!< (@ 0x0000004C) Counter/Timer Control */ - - struct { - __IOM uint32_t TMRA2EN : 1; /*!< [0..0] Counter/Timer A2 Enable bit. */ - __IOM uint32_t TMRA2CLK : 5; /*!< [5..1] Counter/Timer A2 Clock Select. */ - __IOM uint32_t TMRA2FN : 3; /*!< [8..6] Counter/Timer A2 Function Select. */ - __IOM uint32_t TMRA2IE0 : 1; /*!< [9..9] Counter/Timer A2 Interrupt Enable bit based on COMPR0. */ - __IOM uint32_t TMRA2IE1 : 1; /*!< [10..10] Counter/Timer A2 Interrupt Enable bit based on COMPR1. */ - __IOM uint32_t TMRA2CLR : 1; /*!< [11..11] Counter/Timer A2 Clear bit. */ - __IOM uint32_t TMRA2POL : 1; /*!< [12..12] Counter/Timer A2 output polarity. */ - __IM uint32_t : 3; - __IOM uint32_t TMRB2EN : 1; /*!< [16..16] Counter/Timer B2 Enable bit. */ - __IOM uint32_t TMRB2CLK : 5; /*!< [21..17] Counter/Timer B2 Clock Select. */ - __IOM uint32_t TMRB2FN : 3; /*!< [24..22] Counter/Timer B2 Function Select. */ - __IOM uint32_t TMRB2IE0 : 1; /*!< [25..25] Counter/Timer B2 Interrupt Enable bit for COMPR0. */ - __IOM uint32_t TMRB2IE1 : 1; /*!< [26..26] Counter/Timer B2 Interrupt Enable bit for COMPR1. */ - __IOM uint32_t TMRB2CLR : 1; /*!< [27..27] Counter/Timer B2 Clear bit. */ - __IOM uint32_t TMRB2POL : 1; /*!< [28..28] Counter/Timer B2 output polarity. */ - __IM uint32_t : 2; - __IOM uint32_t CTLINK2 : 1; /*!< [31..31] Counter/Timer A2/B2 Link bit. */ - } CTRL2_b; - } ; - __IM uint32_t RESERVED2; - - union { - __IOM uint32_t CMPRAUXA2; /*!< (@ 0x00000054) Counter/Timer A2 Compare Registers */ - - struct { - __IOM uint32_t CMPR2A2 : 16; /*!< [15..0] Counter/Timer A2 Compare Register 2. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR3A2 : 16; /*!< [31..16] Counter/Timer A2 Compare Register 3. Holds the upper - limit for timer half A. */ - } CMPRAUXA2_b; - } ; - - union { - __IOM uint32_t CMPRAUXB2; /*!< (@ 0x00000058) Counter/Timer B2 Compare Registers */ - - struct { - __IOM uint32_t CMPR2B2 : 16; /*!< [15..0] Counter/Timer B2 Compare Register 2. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR3B2 : 16; /*!< [31..16] Counter/Timer B2 Compare Register 3. Holds the upper - limit for timer half B. */ - } CMPRAUXB2_b; - } ; - - union { - __IOM uint32_t AUX2; /*!< (@ 0x0000005C) Counter/Timer Auxiliary */ - - struct { - __IOM uint32_t TMRA2LMT : 7; /*!< [6..0] Counter/Timer A2 Pattern Limit Count. */ - __IOM uint32_t TMRA2TRIG : 4; /*!< [10..7] Counter/Timer A2 Trigger Select. */ - __IOM uint32_t TMRA2NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ - __IOM uint32_t TMRA2TINV : 1; /*!< [12..12] Counter/Timer A2 Invert on trigger. */ - __IOM uint32_t TMRA2POL23 : 1; /*!< [13..13] Counter/Timer A2 Upper output polarity */ - __IOM uint32_t TMRA2EN23 : 1; /*!< [14..14] Counter/Timer A2 Upper compare enable. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB2LMT : 6; /*!< [21..16] Counter/Timer B2 Pattern Limit Count. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB2TRIG : 4; /*!< [26..23] Counter/Timer B2 Trigger Select. */ - __IOM uint32_t TMRB2NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ - __IOM uint32_t TMRB2TINV : 1; /*!< [28..28] Counter/Timer B2 Invert on trigger. */ - __IOM uint32_t TMRB2POL23 : 1; /*!< [29..29] Upper output polarity */ - __IOM uint32_t TMRB2EN23 : 1; /*!< [30..30] Counter/Timer B2 Upper compare enable. */ - } AUX2_b; - } ; - - union { - __IOM uint32_t TMR3; /*!< (@ 0x00000060) Counter/Timer Register */ - - struct { - __IOM uint32_t CTTMRA3 : 16; /*!< [15..0] Counter/Timer A3. */ - __IOM uint32_t CTTMRB3 : 16; /*!< [31..16] Counter/Timer B3. */ - } TMR3_b; - } ; - - union { - __IOM uint32_t CMPRA3; /*!< (@ 0x00000064) Counter/Timer A3 Compare Registers */ - - struct { - __IOM uint32_t CMPR0A3 : 16; /*!< [15..0] Counter/Timer A3 Compare Register 0. */ - __IOM uint32_t CMPR1A3 : 16; /*!< [31..16] Counter/Timer A3 Compare Register 1. */ - } CMPRA3_b; - } ; - - union { - __IOM uint32_t CMPRB3; /*!< (@ 0x00000068) Counter/Timer B3 Compare Registers */ - - struct { - __IOM uint32_t CMPR0B3 : 16; /*!< [15..0] Counter/Timer B3 Compare Register 0. */ - __IOM uint32_t CMPR1B3 : 16; /*!< [31..16] Counter/Timer B3 Compare Register 1. */ - } CMPRB3_b; - } ; - - union { - __IOM uint32_t CTRL3; /*!< (@ 0x0000006C) Counter/Timer Control */ - - struct { - __IOM uint32_t TMRA3EN : 1; /*!< [0..0] Counter/Timer A3 Enable bit. */ - __IOM uint32_t TMRA3CLK : 5; /*!< [5..1] Counter/Timer A3 Clock Select. */ - __IOM uint32_t TMRA3FN : 3; /*!< [8..6] Counter/Timer A3 Function Select. */ - __IOM uint32_t TMRA3IE0 : 1; /*!< [9..9] Counter/Timer A3 Interrupt Enable bit based on COMPR0. */ - __IOM uint32_t TMRA3IE1 : 1; /*!< [10..10] Counter/Timer A3 Interrupt Enable bit based on COMPR1. */ - __IOM uint32_t TMRA3CLR : 1; /*!< [11..11] Counter/Timer A3 Clear bit. */ - __IOM uint32_t TMRA3POL : 1; /*!< [12..12] Counter/Timer A3 output polarity. */ - __IM uint32_t : 2; - __IOM uint32_t ADCEN : 1; /*!< [15..15] Special Timer A3 enable for ADC function. */ - __IOM uint32_t TMRB3EN : 1; /*!< [16..16] Counter/Timer B3 Enable bit. */ - __IOM uint32_t TMRB3CLK : 5; /*!< [21..17] Counter/Timer B3 Clock Select. */ - __IOM uint32_t TMRB3FN : 3; /*!< [24..22] Counter/Timer B3 Function Select. */ - __IOM uint32_t TMRB3IE0 : 1; /*!< [25..25] Counter/Timer B3 Interrupt Enable bit for COMPR0. */ - __IOM uint32_t TMRB3IE1 : 1; /*!< [26..26] Counter/Timer B3 Interrupt Enable bit for COMPR1. */ - __IOM uint32_t TMRB3CLR : 1; /*!< [27..27] Counter/Timer B3 Clear bit. */ - __IOM uint32_t TMRB3POL : 1; /*!< [28..28] Counter/Timer B3 output polarity. */ - __IM uint32_t : 2; - __IOM uint32_t CTLINK3 : 1; /*!< [31..31] Counter/Timer A3/B3 Link bit. */ - } CTRL3_b; - } ; - __IM uint32_t RESERVED3; - - union { - __IOM uint32_t CMPRAUXA3; /*!< (@ 0x00000074) Counter/Timer A3 Compare Registers */ - - struct { - __IOM uint32_t CMPR2A3 : 16; /*!< [15..0] Counter/Timer A3 Compare Register 2. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR3A3 : 16; /*!< [31..16] Counter/Timer A3 Compare Register 3. Holds the upper - limit for timer half A. */ - } CMPRAUXA3_b; - } ; - - union { - __IOM uint32_t CMPRAUXB3; /*!< (@ 0x00000078) Counter/Timer B3 Compare Registers */ - - struct { - __IOM uint32_t CMPR2B3 : 16; /*!< [15..0] Counter/Timer B3 Compare Register 2. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR3B3 : 16; /*!< [31..16] Counter/Timer B3 Compare Register 3. Holds the upper - limit for timer half B. */ - } CMPRAUXB3_b; - } ; - - union { - __IOM uint32_t AUX3; /*!< (@ 0x0000007C) Counter/Timer Auxiliary */ - - struct { - __IOM uint32_t TMRA3LMT : 7; /*!< [6..0] Counter/Timer A3 Pattern Limit Count. */ - __IOM uint32_t TMRA3TRIG : 4; /*!< [10..7] Counter/Timer A3 Trigger Select. */ - __IOM uint32_t TMRA3NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ - __IOM uint32_t TMRA3TINV : 1; /*!< [12..12] Counter/Timer A3 Invert on trigger. */ - __IOM uint32_t TMRA3POL23 : 1; /*!< [13..13] Counter/Timer A3 Upper output polarity */ - __IOM uint32_t TMRA3EN23 : 1; /*!< [14..14] Counter/Timer A3 Upper compare enable. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB3LMT : 6; /*!< [21..16] Counter/Timer B3 Pattern Limit Count. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB3TRIG : 4; /*!< [26..23] Counter/Timer B3 Trigger Select. */ - __IOM uint32_t TMRB3NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ - __IOM uint32_t TMRB3TINV : 1; /*!< [28..28] Counter/Timer B3 Invert on trigger. */ - __IOM uint32_t TMRB3POL23 : 1; /*!< [29..29] Upper output polarity */ - __IOM uint32_t TMRB3EN23 : 1; /*!< [30..30] Counter/Timer B3 Upper compare enable. */ - } AUX3_b; - } ; - - union { - __IOM uint32_t TMR4; /*!< (@ 0x00000080) Counter/Timer Register */ - - struct { - __IOM uint32_t CTTMRA4 : 16; /*!< [15..0] Counter/Timer A4. */ - __IOM uint32_t CTTMRB4 : 16; /*!< [31..16] Counter/Timer B4. */ - } TMR4_b; - } ; - - union { - __IOM uint32_t CMPRA4; /*!< (@ 0x00000084) Counter/Timer A4 Compare Registers */ - - struct { - __IOM uint32_t CMPR0A4 : 16; /*!< [15..0] Counter/Timer A4 Compare Register 0. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR1A4 : 16; /*!< [31..16] Counter/Timer A4 Compare Register 1. Holds the upper - limit for timer half A. */ - } CMPRA4_b; - } ; - - union { - __IOM uint32_t CMPRB4; /*!< (@ 0x00000088) Counter/Timer B4 Compare Registers */ - - struct { - __IOM uint32_t CMPR0B4 : 16; /*!< [15..0] Counter/Timer B4 Compare Register 0. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR1B4 : 16; /*!< [31..16] Counter/Timer B4 Compare Register 1. Holds the upper - limit for timer half B. */ - } CMPRB4_b; - } ; - - union { - __IOM uint32_t CTRL4; /*!< (@ 0x0000008C) Counter/Timer Control */ - - struct { - __IOM uint32_t TMRA4EN : 1; /*!< [0..0] Counter/Timer A4 Enable bit. */ - __IOM uint32_t TMRA4CLK : 5; /*!< [5..1] Counter/Timer A4 Clock Select. */ - __IOM uint32_t TMRA4FN : 3; /*!< [8..6] Counter/Timer A4 Function Select. */ - __IOM uint32_t TMRA4IE0 : 1; /*!< [9..9] Counter/Timer A4 Interrupt Enable bit based on COMPR0. */ - __IOM uint32_t TMRA4IE1 : 1; /*!< [10..10] Counter/Timer A4 Interrupt Enable bit based on COMPR1. */ - __IOM uint32_t TMRA4CLR : 1; /*!< [11..11] Counter/Timer A4 Clear bit. */ - __IOM uint32_t TMRA4POL : 1; /*!< [12..12] Counter/Timer A4 output polarity. */ - __IM uint32_t : 3; - __IOM uint32_t TMRB4EN : 1; /*!< [16..16] Counter/Timer B4 Enable bit. */ - __IOM uint32_t TMRB4CLK : 5; /*!< [21..17] Counter/Timer B4 Clock Select. */ - __IOM uint32_t TMRB4FN : 3; /*!< [24..22] Counter/Timer B4 Function Select. */ - __IOM uint32_t TMRB4IE0 : 1; /*!< [25..25] Counter/Timer B4 Interrupt Enable bit for COMPR0. */ - __IOM uint32_t TMRB4IE1 : 1; /*!< [26..26] Counter/Timer B4 Interrupt Enable bit for COMPR1. */ - __IOM uint32_t TMRB4CLR : 1; /*!< [27..27] Counter/Timer B4 Clear bit. */ - __IOM uint32_t TMRB4POL : 1; /*!< [28..28] Counter/Timer B4 output polarity. */ - __IM uint32_t : 2; - __IOM uint32_t CTLINK4 : 1; /*!< [31..31] Counter/Timer A4/B4 Link bit. */ - } CTRL4_b; - } ; - __IM uint32_t RESERVED4; - - union { - __IOM uint32_t CMPRAUXA4; /*!< (@ 0x00000094) Counter/Timer A4 Compare Registers */ - - struct { - __IOM uint32_t CMPR2A4 : 16; /*!< [15..0] Counter/Timer A4 Compare Register 2. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR3A4 : 16; /*!< [31..16] Counter/Timer A4 Compare Register 3. Holds the upper - limit for timer half A. */ - } CMPRAUXA4_b; - } ; - - union { - __IOM uint32_t CMPRAUXB4; /*!< (@ 0x00000098) Counter/Timer B4 Compare Registers */ - - struct { - __IOM uint32_t CMPR2B4 : 16; /*!< [15..0] Counter/Timer B4 Compare Register 2. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR3B4 : 16; /*!< [31..16] Counter/Timer B4 Compare Register 3. Holds the upper - limit for timer half B. */ - } CMPRAUXB4_b; - } ; - - union { - __IOM uint32_t AUX4; /*!< (@ 0x0000009C) Counter/Timer Auxiliary */ - - struct { - __IOM uint32_t TMRA4LMT : 7; /*!< [6..0] Counter/Timer A4 Pattern Limit Count. */ - __IOM uint32_t TMRA4TRIG : 4; /*!< [10..7] Counter/Timer A4 Trigger Select. */ - __IOM uint32_t TMRA4NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ - __IOM uint32_t TMRA4TINV : 1; /*!< [12..12] Counter/Timer A4 Invert on trigger. */ - __IOM uint32_t TMRA4POL23 : 1; /*!< [13..13] Counter/Timer A4 Upper output polarity */ - __IOM uint32_t TMRA4EN23 : 1; /*!< [14..14] Counter/Timer A4 Upper compare enable. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB4LMT : 6; /*!< [21..16] Counter/Timer B4 Pattern Limit Count. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB4TRIG : 4; /*!< [26..23] Counter/Timer B4 Trigger Select. */ - __IOM uint32_t TMRB4NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ - __IOM uint32_t TMRB4TINV : 1; /*!< [28..28] Counter/Timer B4 Invert on trigger. */ - __IOM uint32_t TMRB4POL23 : 1; /*!< [29..29] Upper output polarity */ - __IOM uint32_t TMRB4EN23 : 1; /*!< [30..30] Counter/Timer B4 Upper compare enable. */ - } AUX4_b; - } ; - - union { - __IOM uint32_t TMR5; /*!< (@ 0x000000A0) Counter/Timer Register */ - - struct { - __IOM uint32_t CTTMRA5 : 16; /*!< [15..0] Counter/Timer A5. */ - __IOM uint32_t CTTMRB5 : 16; /*!< [31..16] Counter/Timer B5. */ - } TMR5_b; - } ; - - union { - __IOM uint32_t CMPRA5; /*!< (@ 0x000000A4) Counter/Timer A5 Compare Registers */ - - struct { - __IOM uint32_t CMPR0A5 : 16; /*!< [15..0] Counter/Timer A5 Compare Register 0. */ - __IOM uint32_t CMPR1A5 : 16; /*!< [31..16] Counter/Timer A5 Compare Register 1. */ - } CMPRA5_b; - } ; - - union { - __IOM uint32_t CMPRB5; /*!< (@ 0x000000A8) Counter/Timer B5 Compare Registers */ - - struct { - __IOM uint32_t CMPR0B5 : 16; /*!< [15..0] Counter/Timer B5 Compare Register 0. */ - __IOM uint32_t CMPR1B5 : 16; /*!< [31..16] Counter/Timer B5 Compare Register 1. */ - } CMPRB5_b; - } ; - - union { - __IOM uint32_t CTRL5; /*!< (@ 0x000000AC) Counter/Timer Control */ - - struct { - __IOM uint32_t TMRA5EN : 1; /*!< [0..0] Counter/Timer A5 Enable bit. */ - __IOM uint32_t TMRA5CLK : 5; /*!< [5..1] Counter/Timer A5 Clock Select. */ - __IOM uint32_t TMRA5FN : 3; /*!< [8..6] Counter/Timer A5 Function Select. */ - __IOM uint32_t TMRA5IE0 : 1; /*!< [9..9] Counter/Timer A5 Interrupt Enable bit based on COMPR0. */ - __IOM uint32_t TMRA5IE1 : 1; /*!< [10..10] Counter/Timer A5 Interrupt Enable bit based on COMPR1. */ - __IOM uint32_t TMRA5CLR : 1; /*!< [11..11] Counter/Timer A5 Clear bit. */ - __IOM uint32_t TMRA5POL : 1; /*!< [12..12] Counter/Timer A5 output polarity. */ - __IM uint32_t : 3; - __IOM uint32_t TMRB5EN : 1; /*!< [16..16] Counter/Timer B5 Enable bit. */ - __IOM uint32_t TMRB5CLK : 5; /*!< [21..17] Counter/Timer B5 Clock Select. */ - __IOM uint32_t TMRB5FN : 3; /*!< [24..22] Counter/Timer B5 Function Select. */ - __IOM uint32_t TMRB5IE0 : 1; /*!< [25..25] Counter/Timer B5 Interrupt Enable bit for COMPR0. */ - __IOM uint32_t TMRB5IE1 : 1; /*!< [26..26] Counter/Timer B5 Interrupt Enable bit for COMPR1. */ - __IOM uint32_t TMRB5CLR : 1; /*!< [27..27] Counter/Timer B5 Clear bit. */ - __IOM uint32_t TMRB5POL : 1; /*!< [28..28] Counter/Timer B5 output polarity. */ - __IM uint32_t : 2; - __IOM uint32_t CTLINK5 : 1; /*!< [31..31] Counter/Timer A5/B5 Link bit. */ - } CTRL5_b; - } ; - __IM uint32_t RESERVED5; - - union { - __IOM uint32_t CMPRAUXA5; /*!< (@ 0x000000B4) Counter/Timer A5 Compare Registers */ - - struct { - __IOM uint32_t CMPR2A5 : 16; /*!< [15..0] Counter/Timer A5 Compare Register 2. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR3A5 : 16; /*!< [31..16] Counter/Timer A5 Compare Register 3. Holds the upper - limit for timer half A. */ - } CMPRAUXA5_b; - } ; - - union { - __IOM uint32_t CMPRAUXB5; /*!< (@ 0x000000B8) Counter/Timer B5 Compare Registers */ - - struct { - __IOM uint32_t CMPR2B5 : 16; /*!< [15..0] Counter/Timer B5 Compare Register 2. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR3B5 : 16; /*!< [31..16] Counter/Timer B5 Compare Register 3. Holds the upper - limit for timer half B. */ - } CMPRAUXB5_b; - } ; - - union { - __IOM uint32_t AUX5; /*!< (@ 0x000000BC) Counter/Timer Auxiliary */ - - struct { - __IOM uint32_t TMRA5LMT : 7; /*!< [6..0] Counter/Timer A5 Pattern Limit Count. */ - __IOM uint32_t TMRA5TRIG : 4; /*!< [10..7] Counter/Timer A5 Trigger Select. */ - __IOM uint32_t TMRA5NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ - __IOM uint32_t TMRA5TINV : 1; /*!< [12..12] Counter/Timer A5 Invert on trigger. */ - __IOM uint32_t TMRA5POL23 : 1; /*!< [13..13] Counter/Timer A5 Upper output polarity */ - __IOM uint32_t TMRA5EN23 : 1; /*!< [14..14] Counter/Timer A5 Upper compare enable. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB5LMT : 6; /*!< [21..16] Counter/Timer B5 Pattern Limit Count. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB5TRIG : 4; /*!< [26..23] Counter/Timer B5 Trigger Select. */ - __IOM uint32_t TMRB5NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ - __IOM uint32_t TMRB5TINV : 1; /*!< [28..28] Counter/Timer B5 Invert on trigger. */ - __IOM uint32_t TMRB5POL23 : 1; /*!< [29..29] Upper output polarity */ - __IOM uint32_t TMRB5EN23 : 1; /*!< [30..30] Counter/Timer B5 Upper compare enable. */ - } AUX5_b; - } ; - - union { - __IOM uint32_t TMR6; /*!< (@ 0x000000C0) Counter/Timer Register */ - - struct { - __IOM uint32_t CTTMRA6 : 16; /*!< [15..0] Counter/Timer A6. */ - __IOM uint32_t CTTMRB6 : 16; /*!< [31..16] Counter/Timer B6. */ - } TMR6_b; - } ; - - union { - __IOM uint32_t CMPRA6; /*!< (@ 0x000000C4) Counter/Timer A6 Compare Registers */ - - struct { - __IOM uint32_t CMPR0A6 : 16; /*!< [15..0] Counter/Timer A6 Compare Register 0. */ - __IOM uint32_t CMPR1A6 : 16; /*!< [31..16] Counter/Timer A6 Compare Register 1. */ - } CMPRA6_b; - } ; - - union { - __IOM uint32_t CMPRB6; /*!< (@ 0x000000C8) Counter/Timer B6 Compare Registers */ - - struct { - __IOM uint32_t CMPR0B6 : 16; /*!< [15..0] Counter/Timer B6 Compare Register 0. */ - __IOM uint32_t CMPR1B6 : 16; /*!< [31..16] Counter/Timer B6 Compare Register 1. */ - } CMPRB6_b; - } ; - - union { - __IOM uint32_t CTRL6; /*!< (@ 0x000000CC) Counter/Timer Control */ - - struct { - __IOM uint32_t TMRA6EN : 1; /*!< [0..0] Counter/Timer A6 Enable bit. */ - __IOM uint32_t TMRA6CLK : 5; /*!< [5..1] Counter/Timer A6 Clock Select. */ - __IOM uint32_t TMRA6FN : 3; /*!< [8..6] Counter/Timer A6 Function Select. */ - __IOM uint32_t TMRA6IE0 : 1; /*!< [9..9] Counter/Timer A6 Interrupt Enable bit based on COMPR0. */ - __IOM uint32_t TMRA6IE1 : 1; /*!< [10..10] Counter/Timer A6 Interrupt Enable bit based on COMPR1. */ - __IOM uint32_t TMRA6CLR : 1; /*!< [11..11] Counter/Timer A6 Clear bit. */ - __IOM uint32_t TMRA6POL : 1; /*!< [12..12] Counter/Timer A6 output polarity. */ - __IM uint32_t : 3; - __IOM uint32_t TMRB6EN : 1; /*!< [16..16] Counter/Timer B6 Enable bit. */ - __IOM uint32_t TMRB6CLK : 5; /*!< [21..17] Counter/Timer B6 Clock Select. */ - __IOM uint32_t TMRB6FN : 3; /*!< [24..22] Counter/Timer B6 Function Select. */ - __IOM uint32_t TMRB6IE0 : 1; /*!< [25..25] Counter/Timer B6 Interrupt Enable bit for COMPR0. */ - __IOM uint32_t TMRB6IE1 : 1; /*!< [26..26] Counter/Timer B6 Interrupt Enable bit for COMPR1. */ - __IOM uint32_t TMRB6CLR : 1; /*!< [27..27] Counter/Timer B6 Clear bit. */ - __IOM uint32_t TMRB6POL : 1; /*!< [28..28] Counter/Timer B6 output polarity. */ - __IM uint32_t : 2; - __IOM uint32_t CTLINK6 : 1; /*!< [31..31] Counter/Timer A6/B6 Link bit. */ - } CTRL6_b; - } ; - __IM uint32_t RESERVED6; - - union { - __IOM uint32_t CMPRAUXA6; /*!< (@ 0x000000D4) Counter/Timer A6 Compare Registers */ - - struct { - __IOM uint32_t CMPR2A6 : 16; /*!< [15..0] Counter/Timer A6 Compare Register 2. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR3A6 : 16; /*!< [31..16] Counter/Timer A6 Compare Register 3. Holds the upper - limit for timer half A. */ - } CMPRAUXA6_b; - } ; - - union { - __IOM uint32_t CMPRAUXB6; /*!< (@ 0x000000D8) Counter/Timer B6 Compare Registers */ - - struct { - __IOM uint32_t CMPR2B6 : 16; /*!< [15..0] Counter/Timer B6 Compare Register 2. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR3B6 : 16; /*!< [31..16] Counter/Timer B6 Compare Register 3. Holds the upper - limit for timer half B. */ - } CMPRAUXB6_b; - } ; - - union { - __IOM uint32_t AUX6; /*!< (@ 0x000000DC) Counter/Timer Auxiliary */ - - struct { - __IOM uint32_t TMRA6LMT : 7; /*!< [6..0] Counter/Timer A6 Pattern Limit Count. */ - __IOM uint32_t TMRA6TRIG : 4; /*!< [10..7] Counter/Timer A6 Trigger Select. */ - __IOM uint32_t TMRA6NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ - __IOM uint32_t TMRA6TINV : 1; /*!< [12..12] Counter/Timer A6 Invert on trigger. */ - __IOM uint32_t TMRA6POL23 : 1; /*!< [13..13] Counter/Timer A6 Upper output polarity */ - __IOM uint32_t TMRA6EN23 : 1; /*!< [14..14] Counter/Timer A6 Upper compare enable. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB6LMT : 6; /*!< [21..16] Counter/Timer B6 Pattern Limit Count. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB6TRIG : 4; /*!< [26..23] Counter/Timer B6 Trigger Select. */ - __IOM uint32_t TMRB6NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ - __IOM uint32_t TMRB6TINV : 1; /*!< [28..28] Counter/Timer B6 Invert on trigger. */ - __IOM uint32_t TMRB6POL23 : 1; /*!< [29..29] Upper output polarity */ - __IOM uint32_t TMRB6EN23 : 1; /*!< [30..30] Counter/Timer B6 Upper compare enable. */ - } AUX6_b; - } ; - - union { - __IOM uint32_t TMR7; /*!< (@ 0x000000E0) Counter/Timer Register */ - - struct { - __IOM uint32_t CTTMRA7 : 16; /*!< [15..0] Counter/Timer A7. */ - __IOM uint32_t CTTMRB7 : 16; /*!< [31..16] Counter/Timer B7. */ - } TMR7_b; - } ; - - union { - __IOM uint32_t CMPRA7; /*!< (@ 0x000000E4) Counter/Timer A7 Compare Registers */ - - struct { - __IOM uint32_t CMPR0A7 : 16; /*!< [15..0] Counter/Timer A7 Compare Register 0. */ - __IOM uint32_t CMPR1A7 : 16; /*!< [31..16] Counter/Timer A7 Compare Register 1. */ - } CMPRA7_b; - } ; - - union { - __IOM uint32_t CMPRB7; /*!< (@ 0x000000E8) Counter/Timer B7 Compare Registers */ - - struct { - __IOM uint32_t CMPR0B7 : 16; /*!< [15..0] Counter/Timer B3 Compare Register 0. */ - __IOM uint32_t CMPR1B7 : 16; /*!< [31..16] Counter/Timer B3 Compare Register 1. */ - } CMPRB7_b; - } ; - - union { - __IOM uint32_t CTRL7; /*!< (@ 0x000000EC) Counter/Timer Control */ - - struct { - __IOM uint32_t TMRA7EN : 1; /*!< [0..0] Counter/Timer A7 Enable bit. */ - __IOM uint32_t TMRA7CLK : 5; /*!< [5..1] Counter/Timer A7 Clock Select. */ - __IOM uint32_t TMRA7FN : 3; /*!< [8..6] Counter/Timer A7 Function Select. */ - __IOM uint32_t TMRA7IE0 : 1; /*!< [9..9] Counter/Timer A7 Interrupt Enable bit based on COMPR0. */ - __IOM uint32_t TMRA7IE1 : 1; /*!< [10..10] Counter/Timer A7 Interrupt Enable bit based on COMPR1. */ - __IOM uint32_t TMRA7CLR : 1; /*!< [11..11] Counter/Timer A7 Clear bit. */ - __IOM uint32_t TMRA7POL : 1; /*!< [12..12] Counter/Timer A7 output polarity. */ - __IM uint32_t : 3; - __IOM uint32_t TMRB7EN : 1; /*!< [16..16] Counter/Timer B7 Enable bit. */ - __IOM uint32_t TMRB7CLK : 5; /*!< [21..17] Counter/Timer B7 Clock Select. */ - __IOM uint32_t TMRB7FN : 3; /*!< [24..22] Counter/Timer B7 Function Select. */ - __IOM uint32_t TMRB7IE0 : 1; /*!< [25..25] Counter/Timer B7 Interrupt Enable bit for COMPR0. */ - __IOM uint32_t TMRB7IE1 : 1; /*!< [26..26] Counter/Timer B7 Interrupt Enable bit for COMPR1. */ - __IOM uint32_t TMRB7CLR : 1; /*!< [27..27] Counter/Timer B7 Clear bit. */ - __IOM uint32_t TMRB7POL : 1; /*!< [28..28] Counter/Timer B7 output polarity. */ - __IM uint32_t : 2; - __IOM uint32_t CTLINK7 : 1; /*!< [31..31] Counter/Timer A7/B7 Link bit. */ - } CTRL7_b; - } ; - __IM uint32_t RESERVED7; - - union { - __IOM uint32_t CMPRAUXA7; /*!< (@ 0x000000F4) Counter/Timer A7 Compare Registers */ - - struct { - __IOM uint32_t CMPR2A7 : 16; /*!< [15..0] Counter/Timer A7 Compare Register 2. Holds the lower - limit for timer half A. */ - __IOM uint32_t CMPR3A7 : 16; /*!< [31..16] Counter/Timer A7 Compare Register 3. Holds the upper - limit for timer half A. */ - } CMPRAUXA7_b; - } ; - - union { - __IOM uint32_t CMPRAUXB7; /*!< (@ 0x000000F8) Counter/Timer B7 Compare Registers */ - - struct { - __IOM uint32_t CMPR2B7 : 16; /*!< [15..0] Counter/Timer B7 Compare Register 2. Holds the lower - limit for timer half B. */ - __IOM uint32_t CMPR3B7 : 16; /*!< [31..16] Counter/Timer B7 Compare Register 3. Holds the upper - limit for timer half B. */ - } CMPRAUXB7_b; - } ; - - union { - __IOM uint32_t AUX7; /*!< (@ 0x000000FC) Counter/Timer Auxiliary */ - - struct { - __IOM uint32_t TMRA7LMT : 7; /*!< [6..0] Counter/Timer A7 Pattern Limit Count. */ - __IOM uint32_t TMRA7TRIG : 4; /*!< [10..7] Counter/Timer A7 Trigger Select. */ - __IOM uint32_t TMRA7NOSYNC : 1; /*!< [11..11] Source clock synchronization control. */ - __IOM uint32_t TMRA7TINV : 1; /*!< [12..12] Counter/Timer A7 Invert on trigger. */ - __IOM uint32_t TMRA7POL23 : 1; /*!< [13..13] Counter/Timer A7 Upper output polarity */ - __IOM uint32_t TMRA7EN23 : 1; /*!< [14..14] Counter/Timer A7 Upper compare enable. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB7LMT : 6; /*!< [21..16] Counter/Timer B7 Pattern Limit Count. */ - __IM uint32_t : 1; - __IOM uint32_t TMRB7TRIG : 4; /*!< [26..23] Counter/Timer B7 Trigger Select. */ - __IOM uint32_t TMRB7NOSYNC : 1; /*!< [27..27] Source clock synchronization control. */ - __IOM uint32_t TMRB7TINV : 1; /*!< [28..28] Counter/Timer B7 Invert on trigger. */ - __IOM uint32_t TMRB7POL23 : 1; /*!< [29..29] Upper output polarity */ - __IOM uint32_t TMRB7EN23 : 1; /*!< [30..30] Counter/Timer B7 Upper compare enable. */ - } AUX7_b; - } ; - - union { - __IOM uint32_t GLOBEN; /*!< (@ 0x00000100) Counter/Timer Global Enable */ - - struct { - __IOM uint32_t ENA0 : 1; /*!< [0..0] Alternate enable for A0 */ - __IOM uint32_t ENB0 : 1; /*!< [1..1] Alternate enable for B0 */ - __IOM uint32_t ENA1 : 1; /*!< [2..2] Alternate enable for A1 */ - __IOM uint32_t ENB1 : 1; /*!< [3..3] Alternate enable for B1 */ - __IOM uint32_t ENA2 : 1; /*!< [4..4] Alternate enable for A2 */ - __IOM uint32_t ENB2 : 1; /*!< [5..5] Alternate enable for B2 */ - __IOM uint32_t ENA3 : 1; /*!< [6..6] Alternate enable for A3 */ - __IOM uint32_t ENB3 : 1; /*!< [7..7] Alternate enable for B3. */ - __IOM uint32_t ENA4 : 1; /*!< [8..8] Alternate enable for A4 */ - __IOM uint32_t ENB4 : 1; /*!< [9..9] Alternate enable for B4 */ - __IOM uint32_t ENA5 : 1; /*!< [10..10] Alternate enable for A5 */ - __IOM uint32_t ENB5 : 1; /*!< [11..11] Alternate enable for B5 */ - __IOM uint32_t ENA6 : 1; /*!< [12..12] Alternate enable for A6 */ - __IOM uint32_t ENB6 : 1; /*!< [13..13] Alternate enable for B6 */ - __IOM uint32_t ENA7 : 1; /*!< [14..14] Alternate enable for A7 */ - __IOM uint32_t ENB7 : 1; /*!< [15..15] Alternate enable for B7. */ - } GLOBEN_b; - } ; - - union { - __IOM uint32_t OUTCFG0; /*!< (@ 0x00000104) Counter/Timer Output Config 0 */ - - struct { - __IOM uint32_t CFG0 : 3; /*!< [2..0] Pad output 0 configuration */ - __IOM uint32_t CFG1 : 3; /*!< [5..3] Pad output 1 configuration */ - __IOM uint32_t CFG2 : 3; /*!< [8..6] Pad output 2 configuration */ - __IOM uint32_t CFG3 : 3; /*!< [11..9] Pad output 3 configuration */ - __IOM uint32_t CFG4 : 3; /*!< [14..12] Pad output 4 configuration */ - __IM uint32_t : 1; - __IOM uint32_t CFG5 : 3; /*!< [18..16] Pad output 5 configuration */ - __IOM uint32_t CFG6 : 3; /*!< [21..19] Pad output 6 configuration */ - __IOM uint32_t CFG7 : 3; /*!< [24..22] Pad output 7 configuration */ - __IOM uint32_t CFG8 : 3; /*!< [27..25] Pad output 8 configuration */ - __IOM uint32_t CFG9 : 3; /*!< [30..28] Pad output 9 configuration */ - } OUTCFG0_b; - } ; - - union { - __IOM uint32_t OUTCFG1; /*!< (@ 0x00000108) Counter/Timer Output Config 1 */ - - struct { - __IOM uint32_t CFG10 : 3; /*!< [2..0] Pad output 10 configuration */ - __IOM uint32_t CFG11 : 3; /*!< [5..3] Pad output 11 configuration */ - __IOM uint32_t CFG12 : 3; /*!< [8..6] Pad output 12 configuration */ - __IOM uint32_t CFG13 : 3; /*!< [11..9] Pad output 13 configuration */ - __IOM uint32_t CFG14 : 3; /*!< [14..12] Pad output 14 configuration */ - __IM uint32_t : 1; - __IOM uint32_t CFG15 : 3; /*!< [18..16] Pad output 15 configuration */ - __IOM uint32_t CFG16 : 3; /*!< [21..19] Pad output 16 configuration */ - __IOM uint32_t CFG17 : 3; /*!< [24..22] Pad output 17 configuration */ - __IOM uint32_t CFG18 : 3; /*!< [27..25] Pad output 18 configuration */ - __IOM uint32_t CFG19 : 3; /*!< [30..28] Pad output 19 configuration */ - } OUTCFG1_b; - } ; - - union { - __IOM uint32_t OUTCFG2; /*!< (@ 0x0000010C) Counter/Timer Output Config 2 */ - - struct { - __IOM uint32_t CFG20 : 3; /*!< [2..0] Pad output 20 configuration */ - __IOM uint32_t CFG21 : 3; /*!< [5..3] Pad output 21 configuration */ - __IOM uint32_t CFG22 : 3; /*!< [8..6] Pad output 22 configuration */ - __IOM uint32_t CFG23 : 3; /*!< [11..9] Pad output 23 configuration */ - __IOM uint32_t CFG24 : 3; /*!< [14..12] Pad output 24 configuration */ - __IM uint32_t : 1; - __IOM uint32_t CFG25 : 3; /*!< [18..16] Pad output 25 configuration */ - __IOM uint32_t CFG26 : 3; /*!< [21..19] Pad output 26 configuration */ - __IOM uint32_t CFG27 : 3; /*!< [24..22] Pad output 27 configuration */ - __IOM uint32_t CFG28 : 3; /*!< [27..25] Pad output 28 configuration */ - __IOM uint32_t CFG29 : 3; /*!< [30..28] Pad output 29 configuration */ - } OUTCFG2_b; - } ; - __IM uint32_t RESERVED8; - - union { - __IOM uint32_t OUTCFG3; /*!< (@ 0x00000114) Counter/Timer Output Config 3 */ - - struct { - __IOM uint32_t CFG30 : 3; /*!< [2..0] Pad output 30 configuration */ - __IOM uint32_t CFG31 : 3; /*!< [5..3] Pad output 31 configuration */ - } OUTCFG3_b; - } ; - - union { - __IOM uint32_t INCFG; /*!< (@ 0x00000118) Counter/Timer Input Config */ - - struct { - __IOM uint32_t CFGA0 : 1; /*!< [0..0] CTIMER A0 input configuration */ - __IOM uint32_t CFGB0 : 1; /*!< [1..1] CTIMER B0 input configuration */ - __IOM uint32_t CFGA1 : 1; /*!< [2..2] CTIMER A1 input configuration */ - __IOM uint32_t CFGB1 : 1; /*!< [3..3] CTIMER B1 input configuration */ - __IOM uint32_t CFGA2 : 1; /*!< [4..4] CTIMER A2 input configuration */ - __IOM uint32_t CFGB2 : 1; /*!< [5..5] CTIMER B2 input configuration */ - __IOM uint32_t CFGA3 : 1; /*!< [6..6] CTIMER A3 input configuration */ - __IOM uint32_t CFGB3 : 1; /*!< [7..7] CTIMER B3 input configuration */ - __IOM uint32_t CFGA4 : 1; /*!< [8..8] CTIMER A4 input configuration */ - __IOM uint32_t CFGB4 : 1; /*!< [9..9] CTIMER B4 input configuration */ - __IOM uint32_t CFGA5 : 1; /*!< [10..10] CTIMER A5 input configuration */ - __IOM uint32_t CFGB5 : 1; /*!< [11..11] CTIMER B5 input configuration */ - __IOM uint32_t CFGA6 : 1; /*!< [12..12] CTIMER A6 input configuration */ - __IOM uint32_t CFGB6 : 1; /*!< [13..13] CTIMER B6 input configuration */ - __IOM uint32_t CFGA7 : 1; /*!< [14..14] CTIMER A7 input configuration */ - __IOM uint32_t CFGB7 : 1; /*!< [15..15] CTIMER B7 input configuration */ - } INCFG_b; - } ; - __IM uint32_t RESERVED9[9]; - - union { - __IOM uint32_t STCFG; /*!< (@ 0x00000140) Configuration Register */ - - struct { - __IOM uint32_t CLKSEL : 4; /*!< [3..0] Selects an appropriate clock source and divider to use - for the System Timer clock. */ - __IM uint32_t : 4; - __IOM uint32_t COMPARE_A_EN : 1; /*!< [8..8] Selects whether compare is enabled for the corresponding - SCMPR register. If compare is enabled, the interrupt status - is set once the comparision is met. */ - __IOM uint32_t COMPARE_B_EN : 1; /*!< [9..9] Selects whether compare is enabled for the corresponding - SCMPR register. If compare is enabled, the interrupt status - is set once the comparision is met. */ - __IOM uint32_t COMPARE_C_EN : 1; /*!< [10..10] Selects whether compare is enabled for the corresponding - SCMPR register. If compare is enabled, the interrupt status - is set once the comparision is met. */ - __IOM uint32_t COMPARE_D_EN : 1; /*!< [11..11] Selects whether compare is enabled for the corresponding - SCMPR register. If compare is enabled, the interrupt status - is set once the comparision is met. */ - __IOM uint32_t COMPARE_E_EN : 1; /*!< [12..12] Selects whether compare is enabled for the corresponding - SCMPR register. If compare is enabled, the interrupt status - is set once the comparision is met. */ - __IOM uint32_t COMPARE_F_EN : 1; /*!< [13..13] Selects whether compare is enabled for the corresponding - SCMPR register. If compare is enabled, the interrupt status - is set once the comparision is met. */ - __IOM uint32_t COMPARE_G_EN : 1; /*!< [14..14] Selects whether compare is enabled for the corresponding - SCMPR register. If compare is enabled, the interrupt status - is set once the comparision is met. */ - __IOM uint32_t COMPARE_H_EN : 1; /*!< [15..15] Selects whether compare is enabled for the corresponding - SCMPR register. If compare is enabled, the interrupt status - is set once the comparision is met. */ - __IM uint32_t : 14; - __IOM uint32_t CLEAR : 1; /*!< [30..30] Set this bit to one to clear the System Timer register. - If this bit is set to '1', the system timer register will - stay cleared. It needs to be set to '0' for the system - timer to start running. */ - __IOM uint32_t FREEZE : 1; /*!< [31..31] Set this bit to one to freeze the clock input to the - COUNTER register. Once frozen, the value can be safely - written from the MCU. Unfreeze to resume. */ - } STCFG_b; - } ; - - union { - __IOM uint32_t STTMR; /*!< (@ 0x00000144) System Timer Count Register (Real Time Counter) */ - - struct { - __IOM uint32_t STTMR : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ - } STTMR_b; - } ; - - union { - __IOM uint32_t CAPTURECONTROL; /*!< (@ 0x00000148) Capture Control Register */ - - struct { - __IOM uint32_t CAPTURE0 : 1; /*!< [0..0] Selects whether capture is enabled for the specified - capture register. */ - __IOM uint32_t CAPTURE1 : 1; /*!< [1..1] Selects whether capture is enabled for the specified - capture register. */ - __IOM uint32_t CAPTURE2 : 1; /*!< [2..2] Selects whether capture is enabled for the specified - capture register. */ - __IOM uint32_t CAPTURE3 : 1; /*!< [3..3] Selects whether capture is enabled for the specified - capture register. */ - } CAPTURECONTROL_b; - } ; - __IM uint32_t RESERVED10; - - union { - __IOM uint32_t SCMPR0; /*!< (@ 0x00000150) Compare Register A */ - - struct { - __IOM uint32_t SCMPR0 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register - according to the match criterion, as selected in the COMPARE_A_EN - bit in the REG_CTIMER_STCGF register. */ - } SCMPR0_b; - } ; - - union { - __IOM uint32_t SCMPR1; /*!< (@ 0x00000154) Compare Register B */ - - struct { - __IOM uint32_t SCMPR1 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register - according to the match criterion, as selected in the COMPARE_B_EN - bit in the REG_CTIMER_STCGF register. */ - } SCMPR1_b; - } ; - - union { - __IOM uint32_t SCMPR2; /*!< (@ 0x00000158) Compare Register C */ - - struct { - __IOM uint32_t SCMPR2 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register - according to the match criterion, as selected in the COMPARE_C_EN - bit in the REG_CTIMER_STCGF register. */ - } SCMPR2_b; - } ; - - union { - __IOM uint32_t SCMPR3; /*!< (@ 0x0000015C) Compare Register D */ - - struct { - __IOM uint32_t SCMPR3 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register - according to the match criterion, as selected in the COMPARE_D_EN - bit in the REG_CTIMER_STCGF register. */ - } SCMPR3_b; - } ; - - union { - __IOM uint32_t SCMPR4; /*!< (@ 0x00000160) Compare Register E */ - - struct { - __IOM uint32_t SCMPR4 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register - according to the match criterion, as selected in the COMPARE_E_EN - bit in the REG_CTIMER_STCGF register. */ - } SCMPR4_b; - } ; - - union { - __IOM uint32_t SCMPR5; /*!< (@ 0x00000164) Compare Register F */ - - struct { - __IOM uint32_t SCMPR5 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register - according to the match criterion, as selected in the COMPARE_F_EN - bit in the REG_CTIMER_STCGF register. */ - } SCMPR5_b; - } ; - - union { - __IOM uint32_t SCMPR6; /*!< (@ 0x00000168) Compare Register G */ - - struct { - __IOM uint32_t SCMPR6 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register - according to the match criterion, as selected in the COMPARE_G_EN - bit in the REG_CTIMER_STCGF register. */ - } SCMPR6_b; - } ; - - union { - __IOM uint32_t SCMPR7; /*!< (@ 0x0000016C) Compare Register H */ - - struct { - __IOM uint32_t SCMPR7 : 32; /*!< [31..0] Compare this value to the value in the COUNTER register - according to the match criterion, as selected in the COMPARE_H_EN - bit in the REG_CTIMER_STCGF register. */ - } SCMPR7_b; - } ; - __IM uint32_t RESERVED11[28]; - - union { - __IOM uint32_t SCAPT0; /*!< (@ 0x000001E0) Capture Register A */ - - struct { - __IOM uint32_t SCAPT0 : 32; /*!< [31..0] Whenever the event is detected, the value in the COUNTER - is copied into this register and the corresponding interrupt - status bit is set. */ - } SCAPT0_b; - } ; - - union { - __IOM uint32_t SCAPT1; /*!< (@ 0x000001E4) Capture Register B */ - - struct { - __IOM uint32_t SCAPT1 : 32; /*!< [31..0] Whenever the event is detected, the value in the COUNTER - is copied into this register and the corresponding interrupt - status bit is set. */ - } SCAPT1_b; - } ; - - union { - __IOM uint32_t SCAPT2; /*!< (@ 0x000001E8) Capture Register C */ - - struct { - __IOM uint32_t SCAPT2 : 32; /*!< [31..0] Whenever the event is detected, the value in the COUNTER - is copied into this register and the corresponding interrupt - status bit is set. */ - } SCAPT2_b; - } ; - - union { - __IOM uint32_t SCAPT3; /*!< (@ 0x000001EC) Capture Register D */ - - struct { - __IOM uint32_t SCAPT3 : 32; /*!< [31..0] Whenever the event is detected, the value in the COUNTER - is copied into this register and the corresponding interrupt - status bit is set. */ - } SCAPT3_b; - } ; - - union { - __IOM uint32_t SNVR0; /*!< (@ 0x000001F0) System Timer NVRAM_A Register */ - - struct { - __IOM uint32_t SNVR0 : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ - } SNVR0_b; - } ; - - union { - __IOM uint32_t SNVR1; /*!< (@ 0x000001F4) System Timer NVRAM_B Register */ - - struct { - __IOM uint32_t SNVR1 : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ - } SNVR1_b; - } ; - - union { - __IOM uint32_t SNVR2; /*!< (@ 0x000001F8) System Timer NVRAM_C Register */ - - struct { - __IOM uint32_t SNVR2 : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ - } SNVR2_b; - } ; - - union { - __IOM uint32_t SNVR3; /*!< (@ 0x000001FC) System Timer NVRAM_D Register */ - - struct { - __IOM uint32_t SNVR3 : 32; /*!< [31..0] Value of the 32-bit counter as it ticks over. */ - } SNVR3_b; - } ; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000200) Counter/Timer Interrupts: Enable */ - - struct { - __IOM uint32_t CTMRA0C0INT : 1; /*!< [0..0] Counter/Timer A0 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB0C0INT : 1; /*!< [1..1] Counter/Timer B0 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA1C0INT : 1; /*!< [2..2] Counter/Timer A1 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB1C0INT : 1; /*!< [3..3] Counter/Timer B1 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA2C0INT : 1; /*!< [4..4] Counter/Timer A2 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB2C0INT : 1; /*!< [5..5] Counter/Timer B2 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA3C0INT : 1; /*!< [6..6] Counter/Timer A3 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB3C0INT : 1; /*!< [7..7] Counter/Timer B3 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA4C0INT : 1; /*!< [8..8] Counter/Timer A4 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB4C0INT : 1; /*!< [9..9] Counter/Timer B4 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA5C0INT : 1; /*!< [10..10] Counter/Timer A5 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB5C0INT : 1; /*!< [11..11] Counter/Timer B5 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA6C0INT : 1; /*!< [12..12] Counter/Timer A6 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB6C0INT : 1; /*!< [13..13] Counter/Timer B6 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA7C0INT : 1; /*!< [14..14] Counter/Timer A7 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB7C0INT : 1; /*!< [15..15] Counter/Timer B7 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA0C1INT : 1; /*!< [16..16] Counter/Timer A0 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB0C1INT : 1; /*!< [17..17] Counter/Timer B0 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA1C1INT : 1; /*!< [18..18] Counter/Timer A1 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB1C1INT : 1; /*!< [19..19] Counter/Timer B1 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA2C1INT : 1; /*!< [20..20] Counter/Timer A2 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB2C1INT : 1; /*!< [21..21] Counter/Timer B2 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA3C1INT : 1; /*!< [22..22] Counter/Timer A3 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB3C1INT : 1; /*!< [23..23] Counter/Timer B3 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA4C1INT : 1; /*!< [24..24] Counter/Timer A4 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB4C1INT : 1; /*!< [25..25] Counter/Timer B4 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA5C1INT : 1; /*!< [26..26] Counter/Timer A5 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB5C1INT : 1; /*!< [27..27] Counter/Timer B5 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA6C1INT : 1; /*!< [28..28] Counter/Timer A6 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB6C1INT : 1; /*!< [29..29] Counter/Timer B6 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA7C1INT : 1; /*!< [30..30] Counter/Timer A7 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB7C1INT : 1; /*!< [31..31] Counter/Timer B7 interrupt based on COMPR1. */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) Counter/Timer Interrupts: Status */ - - struct { - __IOM uint32_t CTMRA0C0INT : 1; /*!< [0..0] Counter/Timer A0 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB0C0INT : 1; /*!< [1..1] Counter/Timer B0 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA1C0INT : 1; /*!< [2..2] Counter/Timer A1 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB1C0INT : 1; /*!< [3..3] Counter/Timer B1 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA2C0INT : 1; /*!< [4..4] Counter/Timer A2 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB2C0INT : 1; /*!< [5..5] Counter/Timer B2 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA3C0INT : 1; /*!< [6..6] Counter/Timer A3 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB3C0INT : 1; /*!< [7..7] Counter/Timer B3 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA4C0INT : 1; /*!< [8..8] Counter/Timer A4 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB4C0INT : 1; /*!< [9..9] Counter/Timer B4 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA5C0INT : 1; /*!< [10..10] Counter/Timer A5 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB5C0INT : 1; /*!< [11..11] Counter/Timer B5 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA6C0INT : 1; /*!< [12..12] Counter/Timer A6 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB6C0INT : 1; /*!< [13..13] Counter/Timer B6 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA7C0INT : 1; /*!< [14..14] Counter/Timer A7 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB7C0INT : 1; /*!< [15..15] Counter/Timer B7 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA0C1INT : 1; /*!< [16..16] Counter/Timer A0 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB0C1INT : 1; /*!< [17..17] Counter/Timer B0 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA1C1INT : 1; /*!< [18..18] Counter/Timer A1 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB1C1INT : 1; /*!< [19..19] Counter/Timer B1 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA2C1INT : 1; /*!< [20..20] Counter/Timer A2 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB2C1INT : 1; /*!< [21..21] Counter/Timer B2 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA3C1INT : 1; /*!< [22..22] Counter/Timer A3 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB3C1INT : 1; /*!< [23..23] Counter/Timer B3 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA4C1INT : 1; /*!< [24..24] Counter/Timer A4 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB4C1INT : 1; /*!< [25..25] Counter/Timer B4 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA5C1INT : 1; /*!< [26..26] Counter/Timer A5 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB5C1INT : 1; /*!< [27..27] Counter/Timer B5 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA6C1INT : 1; /*!< [28..28] Counter/Timer A6 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB6C1INT : 1; /*!< [29..29] Counter/Timer B6 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA7C1INT : 1; /*!< [30..30] Counter/Timer A7 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB7C1INT : 1; /*!< [31..31] Counter/Timer B7 interrupt based on COMPR1. */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000208) Counter/Timer Interrupts: Clear */ - - struct { - __IOM uint32_t CTMRA0C0INT : 1; /*!< [0..0] Counter/Timer A0 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB0C0INT : 1; /*!< [1..1] Counter/Timer B0 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA1C0INT : 1; /*!< [2..2] Counter/Timer A1 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB1C0INT : 1; /*!< [3..3] Counter/Timer B1 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA2C0INT : 1; /*!< [4..4] Counter/Timer A2 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB2C0INT : 1; /*!< [5..5] Counter/Timer B2 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA3C0INT : 1; /*!< [6..6] Counter/Timer A3 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB3C0INT : 1; /*!< [7..7] Counter/Timer B3 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA4C0INT : 1; /*!< [8..8] Counter/Timer A4 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB4C0INT : 1; /*!< [9..9] Counter/Timer B4 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA5C0INT : 1; /*!< [10..10] Counter/Timer A5 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB5C0INT : 1; /*!< [11..11] Counter/Timer B5 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA6C0INT : 1; /*!< [12..12] Counter/Timer A6 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB6C0INT : 1; /*!< [13..13] Counter/Timer B6 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA7C0INT : 1; /*!< [14..14] Counter/Timer A7 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB7C0INT : 1; /*!< [15..15] Counter/Timer B7 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA0C1INT : 1; /*!< [16..16] Counter/Timer A0 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB0C1INT : 1; /*!< [17..17] Counter/Timer B0 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA1C1INT : 1; /*!< [18..18] Counter/Timer A1 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB1C1INT : 1; /*!< [19..19] Counter/Timer B1 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA2C1INT : 1; /*!< [20..20] Counter/Timer A2 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB2C1INT : 1; /*!< [21..21] Counter/Timer B2 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA3C1INT : 1; /*!< [22..22] Counter/Timer A3 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB3C1INT : 1; /*!< [23..23] Counter/Timer B3 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA4C1INT : 1; /*!< [24..24] Counter/Timer A4 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB4C1INT : 1; /*!< [25..25] Counter/Timer B4 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA5C1INT : 1; /*!< [26..26] Counter/Timer A5 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB5C1INT : 1; /*!< [27..27] Counter/Timer B5 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA6C1INT : 1; /*!< [28..28] Counter/Timer A6 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB6C1INT : 1; /*!< [29..29] Counter/Timer B6 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA7C1INT : 1; /*!< [30..30] Counter/Timer A7 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB7C1INT : 1; /*!< [31..31] Counter/Timer B7 interrupt based on COMPR1. */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000020C) Counter/Timer Interrupts: Set */ - - struct { - __IOM uint32_t CTMRA0C0INT : 1; /*!< [0..0] Counter/Timer A0 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB0C0INT : 1; /*!< [1..1] Counter/Timer B0 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA1C0INT : 1; /*!< [2..2] Counter/Timer A1 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB1C0INT : 1; /*!< [3..3] Counter/Timer B1 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA2C0INT : 1; /*!< [4..4] Counter/Timer A2 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB2C0INT : 1; /*!< [5..5] Counter/Timer B2 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA3C0INT : 1; /*!< [6..6] Counter/Timer A3 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB3C0INT : 1; /*!< [7..7] Counter/Timer B3 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA4C0INT : 1; /*!< [8..8] Counter/Timer A4 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB4C0INT : 1; /*!< [9..9] Counter/Timer B4 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA5C0INT : 1; /*!< [10..10] Counter/Timer A5 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB5C0INT : 1; /*!< [11..11] Counter/Timer B5 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA6C0INT : 1; /*!< [12..12] Counter/Timer A6 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB6C0INT : 1; /*!< [13..13] Counter/Timer B6 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA7C0INT : 1; /*!< [14..14] Counter/Timer A7 interrupt based on COMPR0. */ - __IOM uint32_t CTMRB7C0INT : 1; /*!< [15..15] Counter/Timer B7 interrupt based on COMPR0. */ - __IOM uint32_t CTMRA0C1INT : 1; /*!< [16..16] Counter/Timer A0 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB0C1INT : 1; /*!< [17..17] Counter/Timer B0 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA1C1INT : 1; /*!< [18..18] Counter/Timer A1 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB1C1INT : 1; /*!< [19..19] Counter/Timer B1 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA2C1INT : 1; /*!< [20..20] Counter/Timer A2 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB2C1INT : 1; /*!< [21..21] Counter/Timer B2 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA3C1INT : 1; /*!< [22..22] Counter/Timer A3 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB3C1INT : 1; /*!< [23..23] Counter/Timer B3 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA4C1INT : 1; /*!< [24..24] Counter/Timer A4 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB4C1INT : 1; /*!< [25..25] Counter/Timer B4 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA5C1INT : 1; /*!< [26..26] Counter/Timer A5 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB5C1INT : 1; /*!< [27..27] Counter/Timer B5 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA6C1INT : 1; /*!< [28..28] Counter/Timer A6 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB6C1INT : 1; /*!< [29..29] Counter/Timer B6 interrupt based on COMPR1. */ - __IOM uint32_t CTMRA7C1INT : 1; /*!< [30..30] Counter/Timer A7 interrupt based on COMPR1. */ - __IOM uint32_t CTMRB7C1INT : 1; /*!< [31..31] Counter/Timer B7 interrupt based on COMPR1. */ - } INTSET_b; - } ; - __IM uint32_t RESERVED12[60]; - - union { - __IOM uint32_t STMINTEN; /*!< (@ 0x00000300) STIMER Interrupt registers: Enable */ - - struct { - __IOM uint32_t COMPAREA : 1; /*!< [0..0] COUNTER is greater than or equal to COMPARE register - A. */ - __IOM uint32_t COMPAREB : 1; /*!< [1..1] COUNTER is greater than or equal to COMPARE register - B. */ - __IOM uint32_t COMPAREC : 1; /*!< [2..2] COUNTER is greater than or equal to COMPARE register - C. */ - __IOM uint32_t COMPARED : 1; /*!< [3..3] COUNTER is greater than or equal to COMPARE register - D. */ - __IOM uint32_t COMPAREE : 1; /*!< [4..4] COUNTER is greater than or equal to COMPARE register - E. */ - __IOM uint32_t COMPAREF : 1; /*!< [5..5] COUNTER is greater than or equal to COMPARE register - F. */ - __IOM uint32_t COMPAREG : 1; /*!< [6..6] COUNTER is greater than or equal to COMPARE register - G. */ - __IOM uint32_t COMPAREH : 1; /*!< [7..7] COUNTER is greater than or equal to COMPARE register - H. */ - __IOM uint32_t OVERFLOW : 1; /*!< [8..8] COUNTER over flowed from 0xFFFFFFFF back to 0x00000000. */ - __IOM uint32_t CAPTUREA : 1; /*!< [9..9] CAPTURE register A has grabbed the value in the counter */ - __IOM uint32_t CAPTUREB : 1; /*!< [10..10] CAPTURE register B has grabbed the value in the counter */ - __IOM uint32_t CAPTUREC : 1; /*!< [11..11] CAPTURE register C has grabbed the value in the counter */ - __IOM uint32_t CAPTURED : 1; /*!< [12..12] CAPTURE register D has grabbed the value in the counter */ - } STMINTEN_b; - } ; - - union { - __IOM uint32_t STMINTSTAT; /*!< (@ 0x00000304) STIMER Interrupt registers: Status */ - - struct { - __IOM uint32_t COMPAREA : 1; /*!< [0..0] COUNTER is greater than or equal to COMPARE register - A. */ - __IOM uint32_t COMPAREB : 1; /*!< [1..1] COUNTER is greater than or equal to COMPARE register - B. */ - __IOM uint32_t COMPAREC : 1; /*!< [2..2] COUNTER is greater than or equal to COMPARE register - C. */ - __IOM uint32_t COMPARED : 1; /*!< [3..3] COUNTER is greater than or equal to COMPARE register - D. */ - __IOM uint32_t COMPAREE : 1; /*!< [4..4] COUNTER is greater than or equal to COMPARE register - E. */ - __IOM uint32_t COMPAREF : 1; /*!< [5..5] COUNTER is greater than or equal to COMPARE register - F. */ - __IOM uint32_t COMPAREG : 1; /*!< [6..6] COUNTER is greater than or equal to COMPARE register - G. */ - __IOM uint32_t COMPAREH : 1; /*!< [7..7] COUNTER is greater than or equal to COMPARE register - H. */ - __IOM uint32_t OVERFLOW : 1; /*!< [8..8] COUNTER over flowed from 0xFFFFFFFF back to 0x00000000. */ - __IOM uint32_t CAPTUREA : 1; /*!< [9..9] CAPTURE register A has grabbed the value in the counter */ - __IOM uint32_t CAPTUREB : 1; /*!< [10..10] CAPTURE register B has grabbed the value in the counter */ - __IOM uint32_t CAPTUREC : 1; /*!< [11..11] CAPTURE register C has grabbed the value in the counter */ - __IOM uint32_t CAPTURED : 1; /*!< [12..12] CAPTURE register D has grabbed the value in the counter */ - } STMINTSTAT_b; - } ; - - union { - __IOM uint32_t STMINTCLR; /*!< (@ 0x00000308) STIMER Interrupt registers: Clear */ - - struct { - __IOM uint32_t COMPAREA : 1; /*!< [0..0] COUNTER is greater than or equal to COMPARE register - A. */ - __IOM uint32_t COMPAREB : 1; /*!< [1..1] COUNTER is greater than or equal to COMPARE register - B. */ - __IOM uint32_t COMPAREC : 1; /*!< [2..2] COUNTER is greater than or equal to COMPARE register - C. */ - __IOM uint32_t COMPARED : 1; /*!< [3..3] COUNTER is greater than or equal to COMPARE register - D. */ - __IOM uint32_t COMPAREE : 1; /*!< [4..4] COUNTER is greater than or equal to COMPARE register - E. */ - __IOM uint32_t COMPAREF : 1; /*!< [5..5] COUNTER is greater than or equal to COMPARE register - F. */ - __IOM uint32_t COMPAREG : 1; /*!< [6..6] COUNTER is greater than or equal to COMPARE register - G. */ - __IOM uint32_t COMPAREH : 1; /*!< [7..7] COUNTER is greater than or equal to COMPARE register - H. */ - __IOM uint32_t OVERFLOW : 1; /*!< [8..8] COUNTER over flowed from 0xFFFFFFFF back to 0x00000000. */ - __IOM uint32_t CAPTUREA : 1; /*!< [9..9] CAPTURE register A has grabbed the value in the counter */ - __IOM uint32_t CAPTUREB : 1; /*!< [10..10] CAPTURE register B has grabbed the value in the counter */ - __IOM uint32_t CAPTUREC : 1; /*!< [11..11] CAPTURE register C has grabbed the value in the counter */ - __IOM uint32_t CAPTURED : 1; /*!< [12..12] CAPTURE register D has grabbed the value in the counter */ - } STMINTCLR_b; - } ; - - union { - __IOM uint32_t STMINTSET; /*!< (@ 0x0000030C) STIMER Interrupt registers: Set */ - - struct { - __IOM uint32_t COMPAREA : 1; /*!< [0..0] COUNTER is greater than or equal to COMPARE register - A. */ - __IOM uint32_t COMPAREB : 1; /*!< [1..1] COUNTER is greater than or equal to COMPARE register - B. */ - __IOM uint32_t COMPAREC : 1; /*!< [2..2] COUNTER is greater than or equal to COMPARE register - C. */ - __IOM uint32_t COMPARED : 1; /*!< [3..3] COUNTER is greater than or equal to COMPARE register - D. */ - __IOM uint32_t COMPAREE : 1; /*!< [4..4] COUNTER is greater than or equal to COMPARE register - E. */ - __IOM uint32_t COMPAREF : 1; /*!< [5..5] COUNTER is greater than or equal to COMPARE register - F. */ - __IOM uint32_t COMPAREG : 1; /*!< [6..6] COUNTER is greater than or equal to COMPARE register - G. */ - __IOM uint32_t COMPAREH : 1; /*!< [7..7] COUNTER is greater than or equal to COMPARE register - H. */ - __IOM uint32_t OVERFLOW : 1; /*!< [8..8] COUNTER over flowed from 0xFFFFFFFF back to 0x00000000. */ - __IOM uint32_t CAPTUREA : 1; /*!< [9..9] CAPTURE register A has grabbed the value in the counter */ - __IOM uint32_t CAPTUREB : 1; /*!< [10..10] CAPTURE register B has grabbed the value in the counter */ - __IOM uint32_t CAPTUREC : 1; /*!< [11..11] CAPTURE register C has grabbed the value in the counter */ - __IOM uint32_t CAPTURED : 1; /*!< [12..12] CAPTURE register D has grabbed the value in the counter */ - } STMINTSET_b; - } ; -} CTIMER_Type; /*!< Size = 784 (0x310) */ - - - -/* =========================================================================================================================== */ -/* ================ GPIO ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief General Purpose IO (GPIO) - */ - -typedef struct { /*!< (@ 0x40010000) GPIO Structure */ - - union { - __IOM uint32_t PADREGA; /*!< (@ 0x00000000) Pad Configuration Register A (Pads 0-3) */ - - struct { - __IOM uint32_t PAD0PULL : 1; /*!< [0..0] Pad 0 pullup enable */ - __IOM uint32_t PAD0INPEN : 1; /*!< [1..1] Pad 0 input enable */ - __IOM uint32_t PAD0STRNG : 1; /*!< [2..2] Pad 0 drive strength */ - __IOM uint32_t PAD0FNCSEL : 3; /*!< [5..3] Pad 0 function select */ - __IOM uint32_t PAD0RSEL : 2; /*!< [7..6] Pad 0 pullup resistor selection. */ - __IOM uint32_t PAD1PULL : 1; /*!< [8..8] Pad 1 pullup enable */ - __IOM uint32_t PAD1INPEN : 1; /*!< [9..9] Pad 1 input enable */ - __IOM uint32_t PAD1STRNG : 1; /*!< [10..10] Pad 1 drive strength */ - __IOM uint32_t PAD1FNCSEL : 3; /*!< [13..11] Pad 1 function select */ - __IOM uint32_t PAD1RSEL : 2; /*!< [15..14] Pad 1 pullup resistor selection. */ - __IOM uint32_t PAD2PULL : 1; /*!< [16..16] Pad 2 pullup enable */ - __IOM uint32_t PAD2INPEN : 1; /*!< [17..17] Pad 2 input enable */ - __IOM uint32_t PAD2STRNG : 1; /*!< [18..18] Pad 2 drive strength */ - __IOM uint32_t PAD2FNCSEL : 3; /*!< [21..19] Pad 2 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD3PULL : 1; /*!< [24..24] Pad 3 pullup enable */ - __IOM uint32_t PAD3INPEN : 1; /*!< [25..25] Pad 3 input enable. */ - __IOM uint32_t PAD3STRNG : 1; /*!< [26..26] Pad 3 drive strength. */ - __IOM uint32_t PAD3FNCSEL : 3; /*!< [29..27] Pad 3 function select */ - __IOM uint32_t PAD3PWRUP : 1; /*!< [30..30] Pad 3 VDD power switch enable */ - } PADREGA_b; - } ; - - union { - __IOM uint32_t PADREGB; /*!< (@ 0x00000004) Pad Configuration Register B (Pads 4-7) */ - - struct { - __IOM uint32_t PAD4PULL : 1; /*!< [0..0] Pad 4 pullup enable */ - __IOM uint32_t PAD4INPEN : 1; /*!< [1..1] Pad 4 input enable */ - __IOM uint32_t PAD4STRNG : 1; /*!< [2..2] Pad 4 drive strength */ - __IOM uint32_t PAD4FNCSEL : 3; /*!< [5..3] Pad 4 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD5PULL : 1; /*!< [8..8] Pad 5 pullup enable */ - __IOM uint32_t PAD5INPEN : 1; /*!< [9..9] Pad 5 input enable */ - __IOM uint32_t PAD5STRNG : 1; /*!< [10..10] Pad 5 drive strength */ - __IOM uint32_t PAD5FNCSEL : 3; /*!< [13..11] Pad 5 function select */ - __IOM uint32_t PAD5RSEL : 2; /*!< [15..14] Pad 5 pullup resistor selection. */ - __IOM uint32_t PAD6PULL : 1; /*!< [16..16] Pad 6 pullup enable */ - __IOM uint32_t PAD6INPEN : 1; /*!< [17..17] Pad 6 input enable */ - __IOM uint32_t PAD6STRNG : 1; /*!< [18..18] Pad 6 drive strength */ - __IOM uint32_t PAD6FNCSEL : 3; /*!< [21..19] Pad 6 function select */ - __IOM uint32_t PAD6RSEL : 2; /*!< [23..22] Pad 6 pullup resistor selection. */ - __IOM uint32_t PAD7PULL : 1; /*!< [24..24] Pad 7 pullup enable */ - __IOM uint32_t PAD7INPEN : 1; /*!< [25..25] Pad 7 input enable */ - __IOM uint32_t PAD7STRNG : 1; /*!< [26..26] Pad 7 drive strength */ - __IOM uint32_t PAD7FNCSEL : 3; /*!< [29..27] Pad 7 function select */ - } PADREGB_b; - } ; - - union { - __IOM uint32_t PADREGC; /*!< (@ 0x00000008) Pad Configuration Register C (Pads 8-11) */ - - struct { - __IOM uint32_t PAD8PULL : 1; /*!< [0..0] Pad 8 pullup enable */ - __IOM uint32_t PAD8INPEN : 1; /*!< [1..1] Pad 8 input enable */ - __IOM uint32_t PAD8STRNG : 1; /*!< [2..2] Pad 8 drive strength */ - __IOM uint32_t PAD8FNCSEL : 3; /*!< [5..3] Pad 8 function select */ - __IOM uint32_t PAD8RSEL : 2; /*!< [7..6] Pad 8 pullup resistor selection. */ - __IOM uint32_t PAD9PULL : 1; /*!< [8..8] Pad 9 pullup enable */ - __IOM uint32_t PAD9INPEN : 1; /*!< [9..9] Pad 9 input enable */ - __IOM uint32_t PAD9STRNG : 1; /*!< [10..10] Pad 9 drive strength */ - __IOM uint32_t PAD9FNCSEL : 3; /*!< [13..11] Pad 9 function select */ - __IOM uint32_t PAD9RSEL : 2; /*!< [15..14] Pad 9 pullup resistor selection */ - __IOM uint32_t PAD10PULL : 1; /*!< [16..16] Pad 10 pullup enable */ - __IOM uint32_t PAD10INPEN : 1; /*!< [17..17] Pad 10 input enable */ - __IOM uint32_t PAD10STRNG : 1; /*!< [18..18] Pad 10 drive strength */ - __IOM uint32_t PAD10FNCSEL : 3; /*!< [21..19] Pad 10 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD11PULL : 1; /*!< [24..24] Pad 11 pullup enable */ - __IOM uint32_t PAD11INPEN : 1; /*!< [25..25] Pad 11 input enable */ - __IOM uint32_t PAD11STRNG : 1; /*!< [26..26] Pad 11 drive strength */ - __IOM uint32_t PAD11FNCSEL : 3; /*!< [29..27] Pad 11 function select */ - } PADREGC_b; - } ; - - union { - __IOM uint32_t PADREGD; /*!< (@ 0x0000000C) Pad Configuration Register D (Pads 12-15) */ - - struct { - __IOM uint32_t PAD12PULL : 1; /*!< [0..0] Pad 12 pullup enable */ - __IOM uint32_t PAD12INPEN : 1; /*!< [1..1] Pad 12 input enable */ - __IOM uint32_t PAD12STRNG : 1; /*!< [2..2] Pad 12 drive strength */ - __IOM uint32_t PAD12FNCSEL : 3; /*!< [5..3] Pad 12 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD13PULL : 1; /*!< [8..8] Pad 13 pullup enable */ - __IOM uint32_t PAD13INPEN : 1; /*!< [9..9] Pad 13 input enable */ - __IOM uint32_t PAD13STRNG : 1; /*!< [10..10] Pad 13 drive strength */ - __IOM uint32_t PAD13FNCSEL : 3; /*!< [13..11] Pad 13 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD14PULL : 1; /*!< [16..16] Pad 14 pullup enable */ - __IOM uint32_t PAD14INPEN : 1; /*!< [17..17] Pad 14 input enable */ - __IOM uint32_t PAD14STRNG : 1; /*!< [18..18] Pad 14 drive strength */ - __IOM uint32_t PAD14FNCSEL : 3; /*!< [21..19] Pad 14 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD15PULL : 1; /*!< [24..24] Pad 15 pullup enable */ - __IOM uint32_t PAD15INPEN : 1; /*!< [25..25] Pad 15 input enable */ - __IOM uint32_t PAD15STRNG : 1; /*!< [26..26] Pad 15 drive strength */ - __IOM uint32_t PAD15FNCSEL : 3; /*!< [29..27] Pad 15 function select */ - } PADREGD_b; - } ; - - union { - __IOM uint32_t PADREGE; /*!< (@ 0x00000010) Pad Configuration Register E (Pads 16-19) */ - - struct { - __IOM uint32_t PAD16PULL : 1; /*!< [0..0] Pad 16 pullup enable */ - __IOM uint32_t PAD16INPEN : 1; /*!< [1..1] Pad 16 input enable */ - __IOM uint32_t PAD16STRNG : 1; /*!< [2..2] Pad 16 drive strength */ - __IOM uint32_t PAD16FNCSEL : 3; /*!< [5..3] Pad 16 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD17PULL : 1; /*!< [8..8] Pad 17 pullup enable */ - __IOM uint32_t PAD17INPEN : 1; /*!< [9..9] Pad 17 input enable */ - __IOM uint32_t PAD17STRNG : 1; /*!< [10..10] Pad 17 drive strength */ - __IOM uint32_t PAD17FNCSEL : 3; /*!< [13..11] Pad 17 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD18PULL : 1; /*!< [16..16] Pad 18 pullup enable */ - __IOM uint32_t PAD18INPEN : 1; /*!< [17..17] Pad 18 input enable */ - __IOM uint32_t PAD18STRNG : 1; /*!< [18..18] Pad 18 drive strength */ - __IOM uint32_t PAD18FNCSEL : 3; /*!< [21..19] Pad 18 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD19PULL : 1; /*!< [24..24] Pad 19 pullup enable */ - __IOM uint32_t PAD19INPEN : 1; /*!< [25..25] Pad 19 input enable */ - __IOM uint32_t PAD19STRNG : 1; /*!< [26..26] Pad 19 drive strength */ - __IOM uint32_t PAD19FNCSEL : 3; /*!< [29..27] Pad 19 function select */ - } PADREGE_b; - } ; - - union { - __IOM uint32_t PADREGF; /*!< (@ 0x00000014) Pad Configuration Register F (Pads 20-23) */ - - struct { - __IOM uint32_t PAD20PULL : 1; /*!< [0..0] Pad 20 pulldown enable */ - __IOM uint32_t PAD20INPEN : 1; /*!< [1..1] Pad 20 input enable */ - __IOM uint32_t PAD20STRNG : 1; /*!< [2..2] Pad 20 drive strength */ - __IOM uint32_t PAD20FNCSEL : 3; /*!< [5..3] Pad 20 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD21PULL : 1; /*!< [8..8] Pad 21 pullup enable */ - __IOM uint32_t PAD21INPEN : 1; /*!< [9..9] Pad 21 input enable */ - __IOM uint32_t PAD21STRNG : 1; /*!< [10..10] Pad 21 drive strength */ - __IOM uint32_t PAD21FNCSEL : 3; /*!< [13..11] Pad 21 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD22PULL : 1; /*!< [16..16] Pad 22 pullup enable */ - __IOM uint32_t PAD22INPEN : 1; /*!< [17..17] Pad 22 input enable */ - __IOM uint32_t PAD22STRNG : 1; /*!< [18..18] Pad 22 drive strength */ - __IOM uint32_t PAD22FNCSEL : 3; /*!< [21..19] Pad 22 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD23PULL : 1; /*!< [24..24] Pad 23 pullup enable */ - __IOM uint32_t PAD23INPEN : 1; /*!< [25..25] Pad 23 input enable */ - __IOM uint32_t PAD23STRNG : 1; /*!< [26..26] Pad 23 drive strength */ - __IOM uint32_t PAD23FNCSEL : 3; /*!< [29..27] Pad 23 function select */ - } PADREGF_b; - } ; - - union { - __IOM uint32_t PADREGG; /*!< (@ 0x00000018) Pad Configuration Register G (Pads 24-27) */ - - struct { - __IOM uint32_t PAD24PULL : 1; /*!< [0..0] Pad 24 pullup enable */ - __IOM uint32_t PAD24INPEN : 1; /*!< [1..1] Pad 24 input enable */ - __IOM uint32_t PAD24STRNG : 1; /*!< [2..2] Pad 24 drive strength */ - __IOM uint32_t PAD24FNCSEL : 3; /*!< [5..3] Pad 24 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD25PULL : 1; /*!< [8..8] Pad 25 pullup enable */ - __IOM uint32_t PAD25INPEN : 1; /*!< [9..9] Pad 25 input enable */ - __IOM uint32_t PAD25STRNG : 1; /*!< [10..10] Pad 25 drive strength */ - __IOM uint32_t PAD25FNCSEL : 3; /*!< [13..11] Pad 25 function select */ - __IOM uint32_t PAD25RSEL : 2; /*!< [15..14] Pad 25 pullup resistor selection. */ - __IOM uint32_t PAD26PULL : 1; /*!< [16..16] Pad 26 pullup enable */ - __IOM uint32_t PAD26INPEN : 1; /*!< [17..17] Pad 26 input enable */ - __IOM uint32_t PAD26STRNG : 1; /*!< [18..18] Pad 26 drive strength */ - __IOM uint32_t PAD26FNCSEL : 3; /*!< [21..19] Pad 26 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD27PULL : 1; /*!< [24..24] Pad 27 pullup enable */ - __IOM uint32_t PAD27INPEN : 1; /*!< [25..25] Pad 27 input enable */ - __IOM uint32_t PAD27STRNG : 1; /*!< [26..26] Pad 27 drive strength */ - __IOM uint32_t PAD27FNCSEL : 3; /*!< [29..27] Pad 27 function select */ - __IOM uint32_t PAD27RSEL : 2; /*!< [31..30] Pad 27 pullup resistor selection. */ - } PADREGG_b; - } ; - - union { - __IOM uint32_t PADREGH; /*!< (@ 0x0000001C) Pad Configuration Register H (Pads 28-31) */ - - struct { - __IOM uint32_t PAD28PULL : 1; /*!< [0..0] Pad 28 pullup enable */ - __IOM uint32_t PAD28INPEN : 1; /*!< [1..1] Pad 28 input enable */ - __IOM uint32_t PAD28STRNG : 1; /*!< [2..2] Pad 28 drive strength */ - __IOM uint32_t PAD28FNCSEL : 3; /*!< [5..3] Pad 28 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD29PULL : 1; /*!< [8..8] Pad 29 pullup enable */ - __IOM uint32_t PAD29INPEN : 1; /*!< [9..9] Pad 29 input enable */ - __IOM uint32_t PAD29STRNG : 1; /*!< [10..10] Pad 29 drive strength */ - __IOM uint32_t PAD29FNCSEL : 3; /*!< [13..11] Pad 29 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD30PULL : 1; /*!< [16..16] Pad 30 pullup enable */ - __IOM uint32_t PAD30INPEN : 1; /*!< [17..17] Pad 30 input enable */ - __IOM uint32_t PAD30STRNG : 1; /*!< [18..18] Pad 30 drive strength */ - __IOM uint32_t PAD30FNCSEL : 3; /*!< [21..19] Pad 30 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD31PULL : 1; /*!< [24..24] Pad 31 pullup enable */ - __IOM uint32_t PAD31INPEN : 1; /*!< [25..25] Pad 31 input enable */ - __IOM uint32_t PAD31STRNG : 1; /*!< [26..26] Pad 31 drive strength */ - __IOM uint32_t PAD31FNCSEL : 3; /*!< [29..27] Pad 31 function select */ - } PADREGH_b; - } ; - - union { - __IOM uint32_t PADREGI; /*!< (@ 0x00000020) Pad Configuration Register I (Pads 32-25) */ - - struct { - __IOM uint32_t PAD32PULL : 1; /*!< [0..0] Pad 32 pullup enable */ - __IOM uint32_t PAD32INPEN : 1; /*!< [1..1] Pad 32 input enable */ - __IOM uint32_t PAD32STRNG : 1; /*!< [2..2] Pad 32 drive strength */ - __IOM uint32_t PAD32FNCSEL : 3; /*!< [5..3] Pad 32 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD33PULL : 1; /*!< [8..8] Pad 33 pullup enable */ - __IOM uint32_t PAD33INPEN : 1; /*!< [9..9] Pad 33 input enable */ - __IOM uint32_t PAD33STRNG : 1; /*!< [10..10] Pad 33 drive strength */ - __IOM uint32_t PAD33FNCSEL : 3; /*!< [13..11] Pad 33 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD34PULL : 1; /*!< [16..16] Pad 34 pullup enable */ - __IOM uint32_t PAD34INPEN : 1; /*!< [17..17] Pad 34 input enable */ - __IOM uint32_t PAD34STRNG : 1; /*!< [18..18] Pad 34 drive strength */ - __IOM uint32_t PAD34FNCSEL : 3; /*!< [21..19] Pad 34 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD35PULL : 1; /*!< [24..24] Pad 35 pullup enable */ - __IOM uint32_t PAD35INPEN : 1; /*!< [25..25] Pad 35 input enable */ - __IOM uint32_t PAD35STRNG : 1; /*!< [26..26] Pad 35 drive strength */ - __IOM uint32_t PAD35FNCSEL : 3; /*!< [29..27] Pad 35 function select */ - } PADREGI_b; - } ; - - union { - __IOM uint32_t PADREGJ; /*!< (@ 0x00000024) Pad Configuration Register J (Pads 36-39) */ - - struct { - __IOM uint32_t PAD36PULL : 1; /*!< [0..0] Pad 36 pullup enable */ - __IOM uint32_t PAD36INPEN : 1; /*!< [1..1] Pad 36 input enable */ - __IOM uint32_t PAD36STRNG : 1; /*!< [2..2] Pad 36 drive strength */ - __IOM uint32_t PAD36FNCSEL : 3; /*!< [5..3] Pad 36 function select */ - __IOM uint32_t PAD36PWRUP : 1; /*!< [6..6] Pad 36 VDD power switch enable */ - __IM uint32_t : 1; - __IOM uint32_t PAD37PULL : 1; /*!< [8..8] Pad 37 pullup enable */ - __IOM uint32_t PAD37INPEN : 1; /*!< [9..9] Pad 37 input enable */ - __IOM uint32_t PAD37STRNG : 1; /*!< [10..10] Pad 37 drive strength */ - __IOM uint32_t PAD37FNCSEL : 3; /*!< [13..11] Pad 37 function select */ - __IM uint32_t : 1; - __IOM uint32_t PAD37PWRDN : 1; /*!< [15..15] Pad 37 VSS power switch enable */ - __IOM uint32_t PAD38PULL : 1; /*!< [16..16] Pad 38 pullup enable */ - __IOM uint32_t PAD38INPEN : 1; /*!< [17..17] Pad 38 input enable */ - __IOM uint32_t PAD38STRNG : 1; /*!< [18..18] Pad 38 drive strength */ - __IOM uint32_t PAD38FNCSEL : 3; /*!< [21..19] Pad 38 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD39PULL : 1; /*!< [24..24] Pad 39 pullup enable */ - __IOM uint32_t PAD39INPEN : 1; /*!< [25..25] Pad 39 input enable */ - __IOM uint32_t PAD39STRNG : 1; /*!< [26..26] Pad 39 drive strength */ - __IOM uint32_t PAD39FNCSEL : 3; /*!< [29..27] Pad 39 function select */ - __IOM uint32_t PAD39RSEL : 2; /*!< [31..30] Pad 39 pullup resistor selection. */ - } PADREGJ_b; - } ; - - union { - __IOM uint32_t PADREGK; /*!< (@ 0x00000028) Pad Configuration Register K (Pads 40-43) */ - - struct { - __IOM uint32_t PAD40PULL : 1; /*!< [0..0] Pad 40 pullup enable */ - __IOM uint32_t PAD40INPEN : 1; /*!< [1..1] Pad 40 input enable */ - __IOM uint32_t PAD40STRNG : 1; /*!< [2..2] Pad 40 drive strength */ - __IOM uint32_t PAD40FNCSEL : 3; /*!< [5..3] Pad 40 function select */ - __IOM uint32_t PAD40RSEL : 2; /*!< [7..6] Pad 40 pullup resistor selection. */ - __IOM uint32_t PAD41PULL : 1; /*!< [8..8] Pad 41 pullup enable */ - __IOM uint32_t PAD41INPEN : 1; /*!< [9..9] Pad 41 input enable */ - __IOM uint32_t PAD41STRNG : 1; /*!< [10..10] Pad 41 drive strength */ - __IOM uint32_t PAD41FNCSEL : 3; /*!< [13..11] Pad 41 function select */ - __IM uint32_t : 1; - __IOM uint32_t PAD41PWRDN : 1; /*!< [15..15] Pad 41 power switch enable */ - __IOM uint32_t PAD42PULL : 1; /*!< [16..16] Pad 42 pullup enable */ - __IOM uint32_t PAD42INPEN : 1; /*!< [17..17] Pad 42 input enable */ - __IOM uint32_t PAD42STRNG : 1; /*!< [18..18] Pad 42 drive strength */ - __IOM uint32_t PAD42FNCSEL : 3; /*!< [21..19] Pad 42 function select */ - __IOM uint32_t PAD42RSEL : 2; /*!< [23..22] Pad 42 pullup resistor selection. */ - __IOM uint32_t PAD43PULL : 1; /*!< [24..24] Pad 43 pullup enable */ - __IOM uint32_t PAD43INPEN : 1; /*!< [25..25] Pad 43 input enable */ - __IOM uint32_t PAD43STRNG : 1; /*!< [26..26] Pad 43 drive strength */ - __IOM uint32_t PAD43FNCSEL : 3; /*!< [29..27] Pad 43 function select */ - __IOM uint32_t PAD43RSEL : 2; /*!< [31..30] Pad 43 pullup resistor selection. */ - } PADREGK_b; - } ; - - union { - __IOM uint32_t PADREGL; /*!< (@ 0x0000002C) Pad Configuration Register L (Pads 44-47) */ - - struct { - __IOM uint32_t PAD44PULL : 1; /*!< [0..0] Pad 44 pullup enable */ - __IOM uint32_t PAD44INPEN : 1; /*!< [1..1] Pad 44 input enable */ - __IOM uint32_t PAD44STRNG : 1; /*!< [2..2] Pad 44 drive strength */ - __IOM uint32_t PAD44FNCSEL : 3; /*!< [5..3] Pad 44 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD45PULL : 1; /*!< [8..8] Pad 45 pullup enable */ - __IOM uint32_t PAD45INPEN : 1; /*!< [9..9] Pad 45 input enable */ - __IOM uint32_t PAD45STRNG : 1; /*!< [10..10] Pad 45 drive strength */ - __IOM uint32_t PAD45FNCSEL : 3; /*!< [13..11] Pad 45 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD46PULL : 1; /*!< [16..16] Pad 46 pullup enable */ - __IOM uint32_t PAD46INPEN : 1; /*!< [17..17] Pad 46 input enable */ - __IOM uint32_t PAD46STRNG : 1; /*!< [18..18] Pad 46 drive strength */ - __IOM uint32_t PAD46FNCSEL : 3; /*!< [21..19] Pad 46 function select */ - __IM uint32_t : 2; - __IOM uint32_t PAD47PULL : 1; /*!< [24..24] Pad 47 pullup enable */ - __IOM uint32_t PAD47INPEN : 1; /*!< [25..25] Pad 47 input enable */ - __IOM uint32_t PAD47STRNG : 1; /*!< [26..26] Pad 47 drive strength */ - __IOM uint32_t PAD47FNCSEL : 3; /*!< [29..27] Pad 47 function select */ - } PADREGL_b; - } ; - - union { - __IOM uint32_t PADREGM; /*!< (@ 0x00000030) Pad Configuration Register M (Pads 47-48) */ - - struct { - __IOM uint32_t PAD48PULL : 1; /*!< [0..0] Pad 48 pullup enable */ - __IOM uint32_t PAD48INPEN : 1; /*!< [1..1] Pad 48 input enable */ - __IOM uint32_t PAD48STRNG : 1; /*!< [2..2] Pad 48 drive strength */ - __IOM uint32_t PAD48FNCSEL : 3; /*!< [5..3] Pad 48 function select */ - __IOM uint32_t PAD48RSEL : 2; /*!< [7..6] Pad 48 pullup resistor selection. */ - __IOM uint32_t PAD49PULL : 1; /*!< [8..8] Pad 49 pullup enable */ - __IOM uint32_t PAD49INPEN : 1; /*!< [9..9] Pad 49 input enable */ - __IOM uint32_t PAD49STRNG : 1; /*!< [10..10] Pad 49 drive strength */ - __IOM uint32_t PAD49FNCSEL : 3; /*!< [13..11] Pad 49 function select */ - __IOM uint32_t PAD49RSEL : 2; /*!< [15..14] Pad 49 pullup resistor selection. */ - } PADREGM_b; - } ; - __IM uint32_t RESERVED[3]; - - union { - __IOM uint32_t CFGA; /*!< (@ 0x00000040) GPIO Configuration Register A (Pads 0-7) */ - - struct { - __IOM uint32_t GPIO0INCFG : 1; /*!< [0..0] GPIO0 input enable. */ - __IOM uint32_t GPIO0OUTCFG : 2; /*!< [2..1] GPIO0 output configuration. */ - __IOM uint32_t GPIO0INTD : 1; /*!< [3..3] GPIO0 interrupt direction. */ - __IOM uint32_t GPIO1INCFG : 1; /*!< [4..4] GPIO1 input enable. */ - __IOM uint32_t GPIO1OUTCFG : 2; /*!< [6..5] GPIO1 output configuration. */ - __IOM uint32_t GPIO1INTD : 1; /*!< [7..7] GPIO1 interrupt direction. */ - __IOM uint32_t GPIO2INCFG : 1; /*!< [8..8] GPIO2 input enable. */ - __IOM uint32_t GPIO2OUTCFG : 2; /*!< [10..9] GPIO2 output configuration. */ - __IOM uint32_t GPIO2INTD : 1; /*!< [11..11] GPIO2 interrupt direction. */ - __IOM uint32_t GPIO3INCFG : 1; /*!< [12..12] GPIO3 input enable. */ - __IOM uint32_t GPIO3OUTCFG : 2; /*!< [14..13] GPIO3 output configuration. */ - __IOM uint32_t GPIO3INTD : 1; /*!< [15..15] GPIO3 interrupt direction. */ - __IOM uint32_t GPIO4INCFG : 1; /*!< [16..16] GPIO4 input enable. */ - __IOM uint32_t GPIO4OUTCFG : 2; /*!< [18..17] GPIO4 output configuration. */ - __IOM uint32_t GPIO4INTD : 1; /*!< [19..19] GPIO4 interrupt direction. */ - __IOM uint32_t GPIO5INCFG : 1; /*!< [20..20] GPIO5 input enable. */ - __IOM uint32_t GPIO5OUTCFG : 2; /*!< [22..21] GPIO5 output configuration. */ - __IOM uint32_t GPIO5INTD : 1; /*!< [23..23] GPIO5 interrupt direction. */ - __IOM uint32_t GPIO6INCFG : 1; /*!< [24..24] GPIO6 input enable. */ - __IOM uint32_t GPIO6OUTCFG : 2; /*!< [26..25] GPIO6 output configuration. */ - __IOM uint32_t GPIO6INTD : 1; /*!< [27..27] GPIO6 interrupt direction. */ - __IOM uint32_t GPIO7INCFG : 1; /*!< [28..28] GPIO7 input enable. */ - __IOM uint32_t GPIO7OUTCFG : 2; /*!< [30..29] GPIO7 output configuration. */ - __IOM uint32_t GPIO7INTD : 1; /*!< [31..31] GPIO7 interrupt direction, nCE polarity. */ - } CFGA_b; - } ; - - union { - __IOM uint32_t CFGB; /*!< (@ 0x00000044) GPIO Configuration Register B (Pads 8-15) */ - - struct { - __IOM uint32_t GPIO8INCFG : 1; /*!< [0..0] GPIO8 input enable. */ - __IOM uint32_t GPIO8OUTCFG : 2; /*!< [2..1] GPIO8 output configuration. */ - __IOM uint32_t GPIO8INTD : 1; /*!< [3..3] GPIO8 interrupt direction. */ - __IOM uint32_t GPIO9INCFG : 1; /*!< [4..4] GPIO9 input enable. */ - __IOM uint32_t GPIO9OUTCFG : 2; /*!< [6..5] GPIO9 output configuration. */ - __IOM uint32_t GPIO9INTD : 1; /*!< [7..7] GPIO9 interrupt direction. */ - __IOM uint32_t GPIO10INCFG : 1; /*!< [8..8] GPIO10 input enable. */ - __IOM uint32_t GPIO10OUTCFG : 2; /*!< [10..9] GPIO10 output configuration. */ - __IOM uint32_t GPIO10INTD : 1; /*!< [11..11] GPIO10 interrupt direction. */ - __IOM uint32_t GPIO11INCFG : 1; /*!< [12..12] GPIO11 input enable. */ - __IOM uint32_t GPIO11OUTCFG : 2; /*!< [14..13] GPIO11 output configuration. */ - __IOM uint32_t GPIO11INTD : 1; /*!< [15..15] GPIO11 interrupt direction. */ - __IOM uint32_t GPIO12INCFG : 1; /*!< [16..16] GPIO12 input enable. */ - __IOM uint32_t GPIO12OUTCFG : 2; /*!< [18..17] GPIO12 output configuration. */ - __IOM uint32_t GPIO12INTD : 1; /*!< [19..19] GPIO12 interrupt direction. */ - __IOM uint32_t GPIO13INCFG : 1; /*!< [20..20] GPIO13 input enable. */ - __IOM uint32_t GPIO13OUTCFG : 2; /*!< [22..21] GPIO13 output configuration. */ - __IOM uint32_t GPIO13INTD : 1; /*!< [23..23] GPIO13 interrupt direction. */ - __IOM uint32_t GPIO14INCFG : 1; /*!< [24..24] GPIO14 input enable. */ - __IOM uint32_t GPIO14OUTCFG : 2; /*!< [26..25] GPIO14 output configuration. */ - __IOM uint32_t GPIO14INTD : 1; /*!< [27..27] GPIO14 interrupt direction. */ - __IOM uint32_t GPIO15INCFG : 1; /*!< [28..28] GPIO15 input enable. */ - __IOM uint32_t GPIO15OUTCFG : 2; /*!< [30..29] GPIO15 output configuration. */ - __IOM uint32_t GPIO15INTD : 1; /*!< [31..31] GPIO15 interrupt direction. */ - } CFGB_b; - } ; - - union { - __IOM uint32_t CFGC; /*!< (@ 0x00000048) GPIO Configuration Register C (Pads 16-23) */ - - struct { - __IOM uint32_t GPIO16INCFG : 1; /*!< [0..0] GPIO16 input enable. */ - __IOM uint32_t GPIO16OUTCFG : 2; /*!< [2..1] GPIO16 output configuration. */ - __IOM uint32_t GPIO16INTD : 1; /*!< [3..3] GPIO16 interrupt direction. */ - __IOM uint32_t GPIO17INCFG : 1; /*!< [4..4] GPIO17 input enable. */ - __IOM uint32_t GPIO17OUTCFG : 2; /*!< [6..5] GPIO17 output configuration. */ - __IOM uint32_t GPIO17INTD : 1; /*!< [7..7] GPIO17 interrupt direction. */ - __IOM uint32_t GPIO18INCFG : 1; /*!< [8..8] GPIO18 input enable. */ - __IOM uint32_t GPIO18OUTCFG : 2; /*!< [10..9] GPIO18 output configuration. */ - __IOM uint32_t GPIO18INTD : 1; /*!< [11..11] GPIO18 interrupt direction. */ - __IOM uint32_t GPIO19INCFG : 1; /*!< [12..12] GPIO19 input enable. */ - __IOM uint32_t GPIO19OUTCFG : 2; /*!< [14..13] GPIO19 output configuration. */ - __IOM uint32_t GPIO19INTD : 1; /*!< [15..15] GPIO19 interrupt direction. */ - __IOM uint32_t GPIO20INCFG : 1; /*!< [16..16] GPIO20 input enable. */ - __IOM uint32_t GPIO20OUTCFG : 2; /*!< [18..17] GPIO20 output configuration. */ - __IOM uint32_t GPIO20INTD : 1; /*!< [19..19] GPIO20 interrupt direction. */ - __IOM uint32_t GPIO21INCFG : 1; /*!< [20..20] GPIO21 input enable. */ - __IOM uint32_t GPIO21OUTCFG : 2; /*!< [22..21] GPIO21 output configuration. */ - __IOM uint32_t GPIO21INTD : 1; /*!< [23..23] GPIO21 interrupt direction. */ - __IOM uint32_t GPIO22INCFG : 1; /*!< [24..24] GPIO22 input enable. */ - __IOM uint32_t GPIO22OUTCFG : 2; /*!< [26..25] GPIO22 output configuration. */ - __IOM uint32_t GPIO22INTD : 1; /*!< [27..27] GPIO22 interrupt direction. */ - __IOM uint32_t GPIO23INCFG : 1; /*!< [28..28] GPIO23 input enable. */ - __IOM uint32_t GPIO23OUTCFG : 2; /*!< [30..29] GPIO23 output configuration. */ - __IOM uint32_t GPIO23INTD : 1; /*!< [31..31] GPIO23 interrupt direction. */ - } CFGC_b; - } ; - - union { - __IOM uint32_t CFGD; /*!< (@ 0x0000004C) GPIO Configuration Register D (Pads 24-31) */ - - struct { - __IOM uint32_t GPIO24INCFG : 1; /*!< [0..0] GPIO24 input enable. */ - __IOM uint32_t GPIO24OUTCFG : 2; /*!< [2..1] GPIO24 output configuration. */ - __IOM uint32_t GPIO24INTD : 1; /*!< [3..3] GPIO24 interrupt direction. */ - __IOM uint32_t GPIO25INCFG : 1; /*!< [4..4] GPIO25 input enable. */ - __IOM uint32_t GPIO25OUTCFG : 2; /*!< [6..5] GPIO25 output configuration. */ - __IOM uint32_t GPIO25INTD : 1; /*!< [7..7] GPIO25 interrupt direction. */ - __IOM uint32_t GPIO26INCFG : 1; /*!< [8..8] GPIO26 input enable. */ - __IOM uint32_t GPIO26OUTCFG : 2; /*!< [10..9] GPIO26 output configuration. */ - __IOM uint32_t GPIO26INTD : 1; /*!< [11..11] GPIO26 interrupt direction. */ - __IOM uint32_t GPIO27INCFG : 1; /*!< [12..12] GPIO27 input enable. */ - __IOM uint32_t GPIO27OUTCFG : 2; /*!< [14..13] GPIO27 output configuration. */ - __IOM uint32_t GPIO27INTD : 1; /*!< [15..15] GPIO27 interrupt direction. */ - __IOM uint32_t GPIO28INCFG : 1; /*!< [16..16] GPIO28 input enable. */ - __IOM uint32_t GPIO28OUTCFG : 2; /*!< [18..17] GPIO28 output configuration. */ - __IOM uint32_t GPIO28INTD : 1; /*!< [19..19] GPIO28 interrupt direction. */ - __IOM uint32_t GPIO29INCFG : 1; /*!< [20..20] GPIO29 input enable. */ - __IOM uint32_t GPIO29OUTCFG : 2; /*!< [22..21] GPIO29 output configuration. */ - __IOM uint32_t GPIO29INTD : 1; /*!< [23..23] GPIO29 interrupt direction. */ - __IOM uint32_t GPIO30INCFG : 1; /*!< [24..24] GPIO30 input enable. */ - __IOM uint32_t GPIO30OUTCFG : 2; /*!< [26..25] GPIO30 output configuration. */ - __IOM uint32_t GPIO30INTD : 1; /*!< [27..27] GPIO30 interrupt direction. */ - __IOM uint32_t GPIO31INCFG : 1; /*!< [28..28] GPIO31 input enable. */ - __IOM uint32_t GPIO31OUTCFG : 2; /*!< [30..29] GPIO31 output configuration. */ - __IOM uint32_t GPIO31INTD : 1; /*!< [31..31] GPIO31 interrupt direction. */ - } CFGD_b; - } ; - - union { - __IOM uint32_t CFGE; /*!< (@ 0x00000050) GPIO Configuration Register E (Pads 32-39) */ - - struct { - __IOM uint32_t GPIO32INCFG : 1; /*!< [0..0] GPIO32 input enable. */ - __IOM uint32_t GPIO32OUTCFG : 2; /*!< [2..1] GPIO32 output configuration. */ - __IOM uint32_t GPIO32INTD : 1; /*!< [3..3] GPIO32 interrupt direction. */ - __IOM uint32_t GPIO33INCFG : 1; /*!< [4..4] GPIO33 input enable. */ - __IOM uint32_t GPIO33OUTCFG : 2; /*!< [6..5] GPIO33 output configuration. */ - __IOM uint32_t GPIO33INTD : 1; /*!< [7..7] GPIO33 interrupt direction. */ - __IOM uint32_t GPIO34INCFG : 1; /*!< [8..8] GPIO34 input enable. */ - __IOM uint32_t GPIO34OUTCFG : 2; /*!< [10..9] GPIO34 output configuration. */ - __IOM uint32_t GPIO34INTD : 1; /*!< [11..11] GPIO34 interrupt direction. */ - __IOM uint32_t GPIO35INCFG : 1; /*!< [12..12] GPIO35 input enable. */ - __IOM uint32_t GPIO35OUTCFG : 2; /*!< [14..13] GPIO35 output configuration. */ - __IOM uint32_t GPIO35INTD : 1; /*!< [15..15] GPIO35 interrupt direction. */ - __IOM uint32_t GPIO36INCFG : 1; /*!< [16..16] GPIO36 input enable. */ - __IOM uint32_t GPIO36OUTCFG : 2; /*!< [18..17] GPIO36 output configuration. */ - __IOM uint32_t GPIO36INTD : 1; /*!< [19..19] GPIO36 interrupt direction. */ - __IOM uint32_t GPIO37INCFG : 1; /*!< [20..20] GPIO37 input enable. */ - __IOM uint32_t GPIO37OUTCFG : 2; /*!< [22..21] GPIO37 output configuration. */ - __IOM uint32_t GPIO37INTD : 1; /*!< [23..23] GPIO37 interrupt direction. */ - __IOM uint32_t GPIO38INCFG : 1; /*!< [24..24] GPIO38 input enable. */ - __IOM uint32_t GPIO38OUTCFG : 2; /*!< [26..25] GPIO38 output configuration. */ - __IOM uint32_t GPIO38INTD : 1; /*!< [27..27] GPIO38 interrupt direction. */ - __IOM uint32_t GPIO39INCFG : 1; /*!< [28..28] GPIO39 input enable. */ - __IOM uint32_t GPIO39OUTCFG : 2; /*!< [30..29] GPIO39 output configuration. */ - __IOM uint32_t GPIO39INTD : 1; /*!< [31..31] GPIO39 interrupt direction. */ - } CFGE_b; - } ; - - union { - __IOM uint32_t CFGF; /*!< (@ 0x00000054) GPIO Configuration Register F (Pads 40 -47) */ - - struct { - __IOM uint32_t GPIO40INCFG : 1; /*!< [0..0] GPIO40 input enable. */ - __IOM uint32_t GPIO40OUTCFG : 2; /*!< [2..1] GPIO40 output configuration. */ - __IOM uint32_t GPIO40INTD : 1; /*!< [3..3] GPIO40 interrupt direction. */ - __IOM uint32_t GPIO41INCFG : 1; /*!< [4..4] GPIO41 input enable. */ - __IOM uint32_t GPIO41OUTCFG : 2; /*!< [6..5] GPIO41 output configuration. */ - __IOM uint32_t GPIO41INTD : 1; /*!< [7..7] GPIO41 interrupt direction. */ - __IOM uint32_t GPIO42INCFG : 1; /*!< [8..8] GPIO42 input enable. */ - __IOM uint32_t GPIO42OUTCFG : 2; /*!< [10..9] GPIO42 output configuration. */ - __IOM uint32_t GPIO42INTD : 1; /*!< [11..11] GPIO42 interrupt direction. */ - __IOM uint32_t GPIO43INCFG : 1; /*!< [12..12] GPIO43 input enable. */ - __IOM uint32_t GPIO43OUTCFG : 2; /*!< [14..13] GPIO43 output configuration. */ - __IOM uint32_t GPIO43INTD : 1; /*!< [15..15] GPIO43 interrupt direction. */ - __IOM uint32_t GPIO44INCFG : 1; /*!< [16..16] GPIO44 input enable. */ - __IOM uint32_t GPIO44OUTCFG : 2; /*!< [18..17] GPIO44 output configuration. */ - __IOM uint32_t GPIO44INTD : 1; /*!< [19..19] GPIO44 interrupt direction. */ - __IOM uint32_t GPIO45INCFG : 1; /*!< [20..20] GPIO45 input enable. */ - __IOM uint32_t GPIO45OUTCFG : 2; /*!< [22..21] GPIO45 output configuration. */ - __IOM uint32_t GPIO45INTD : 1; /*!< [23..23] GPIO45 interrupt direction. */ - __IOM uint32_t GPIO46INCFG : 1; /*!< [24..24] GPIO46 input enable. */ - __IOM uint32_t GPIO46OUTCFG : 2; /*!< [26..25] GPIO46 output configuration. */ - __IOM uint32_t GPIO46INTD : 1; /*!< [27..27] GPIO46 interrupt direction. */ - __IOM uint32_t GPIO47INCFG : 1; /*!< [28..28] GPIO47 input enable. */ - __IOM uint32_t GPIO47OUTCFG : 2; /*!< [30..29] GPIO47 output configuration. */ - __IOM uint32_t GPIO47INTD : 1; /*!< [31..31] GPIO47 interrupt direction. */ - } CFGF_b; - } ; - - union { - __IOM uint32_t CFGG; /*!< (@ 0x00000058) GPIO Configuration Register G (Pads 48-49) */ - - struct { - __IOM uint32_t GPIO48INCFG : 1; /*!< [0..0] GPIO48 input enable. */ - __IOM uint32_t GPIO48OUTCFG : 2; /*!< [2..1] GPIO48 output configuration. */ - __IOM uint32_t GPIO48INTD : 1; /*!< [3..3] GPIO48 interrupt direction. */ - __IOM uint32_t GPIO49INCFG : 1; /*!< [4..4] GPIO49 input enable. */ - __IOM uint32_t GPIO49OUTCFG : 2; /*!< [6..5] GPIO49 output configuration. */ - __IOM uint32_t GPIO49INTD : 1; /*!< [7..7] GPIO49 interrupt direction. */ - } CFGG_b; - } ; - __IM uint32_t RESERVED1; - - union { - __IOM uint32_t PADKEY; /*!< (@ 0x00000060) Key Register for all pad configuration registers */ - - struct { - __IOM uint32_t PADKEY : 32; /*!< [31..0] Key register value. */ - } PADKEY_b; - } ; - __IM uint32_t RESERVED2[7]; - - union { - __IOM uint32_t RDA; /*!< (@ 0x00000080) GPIO Input Register A */ - - struct { - __IOM uint32_t RDA : 32; /*!< [31..0] GPIO31-0 read data. */ - } RDA_b; - } ; - - union { - __IOM uint32_t RDB; /*!< (@ 0x00000084) GPIO Input Register B */ - - struct { - __IOM uint32_t RDB : 18; /*!< [17..0] GPIO49-32 read data. */ - } RDB_b; - } ; - - union { - __IOM uint32_t WTA; /*!< (@ 0x00000088) GPIO Output Register A */ - - struct { - __IOM uint32_t WTA : 32; /*!< [31..0] GPIO31-0 write data. */ - } WTA_b; - } ; - - union { - __IOM uint32_t WTB; /*!< (@ 0x0000008C) GPIO Output Register B */ - - struct { - __IOM uint32_t WTB : 18; /*!< [17..0] GPIO49-32 write data. */ - } WTB_b; - } ; - - union { - __IOM uint32_t WTSA; /*!< (@ 0x00000090) GPIO Output Register A Set */ - - struct { - __IOM uint32_t WTSA : 32; /*!< [31..0] Set the GPIO31-0 write data. */ - } WTSA_b; - } ; - - union { - __IOM uint32_t WTSB; /*!< (@ 0x00000094) GPIO Output Register B Set */ - - struct { - __IOM uint32_t WTSB : 18; /*!< [17..0] Set the GPIO49-32 write data. */ - } WTSB_b; - } ; - - union { - __IOM uint32_t WTCA; /*!< (@ 0x00000098) GPIO Output Register A Clear */ - - struct { - __IOM uint32_t WTCA : 32; /*!< [31..0] Clear the GPIO31-0 write data. */ - } WTCA_b; - } ; - - union { - __IOM uint32_t WTCB; /*!< (@ 0x0000009C) GPIO Output Register B Clear */ - - struct { - __IOM uint32_t WTCB : 18; /*!< [17..0] Clear the GPIO49-32 write data. */ - } WTCB_b; - } ; - - union { - __IOM uint32_t ENA; /*!< (@ 0x000000A0) GPIO Enable Register A */ - - struct { - __IOM uint32_t ENA : 32; /*!< [31..0] GPIO31-0 output enables */ - } ENA_b; - } ; - - union { - __IOM uint32_t ENB; /*!< (@ 0x000000A4) GPIO Enable Register B */ - - struct { - __IOM uint32_t ENB : 18; /*!< [17..0] GPIO49-32 output enables */ - } ENB_b; - } ; - - union { - __IOM uint32_t ENSA; /*!< (@ 0x000000A8) GPIO Enable Register A Set */ - - struct { - __IOM uint32_t ENSA : 32; /*!< [31..0] Set the GPIO31-0 output enables */ - } ENSA_b; - } ; - - union { - __IOM uint32_t ENSB; /*!< (@ 0x000000AC) GPIO Enable Register B Set */ - - struct { - __IOM uint32_t ENSB : 18; /*!< [17..0] Set the GPIO49-32 output enables */ - } ENSB_b; - } ; - __IM uint32_t RESERVED3; - - union { - __IOM uint32_t ENCA; /*!< (@ 0x000000B4) GPIO Enable Register A Clear */ - - struct { - __IOM uint32_t ENCA : 32; /*!< [31..0] Clear the GPIO31-0 output enables */ - } ENCA_b; - } ; - - union { - __IOM uint32_t ENCB; /*!< (@ 0x000000B8) GPIO Enable Register B Clear */ - - struct { - __IOM uint32_t ENCB : 18; /*!< [17..0] Clear the GPIO49-32 output enables */ - } ENCB_b; - } ; - - union { - __IOM uint32_t STMRCAP; /*!< (@ 0x000000BC) STIMER Capture Control */ - - struct { - __IOM uint32_t STSEL0 : 6; /*!< [5..0] STIMER Capture 0 Select. */ - __IOM uint32_t STPOL0 : 1; /*!< [6..6] STIMER Capture 0 Polarity. */ - __IM uint32_t : 1; - __IOM uint32_t STSEL1 : 6; /*!< [13..8] STIMER Capture 1 Select. */ - __IOM uint32_t STPOL1 : 1; /*!< [14..14] STIMER Capture 1 Polarity. */ - __IM uint32_t : 1; - __IOM uint32_t STSEL2 : 6; /*!< [21..16] STIMER Capture 2 Select. */ - __IOM uint32_t STPOL2 : 1; /*!< [22..22] STIMER Capture 2 Polarity. */ - __IM uint32_t : 1; - __IOM uint32_t STSEL3 : 6; /*!< [29..24] STIMER Capture 3 Select. */ - __IOM uint32_t STPOL3 : 1; /*!< [30..30] STIMER Capture 3 Polarity. */ - } STMRCAP_b; - } ; - - union { - __IOM uint32_t IOM0IRQ; /*!< (@ 0x000000C0) IOM0 Flow Control IRQ Select */ - - struct { - __IOM uint32_t IOM0IRQ : 6; /*!< [5..0] IOMSTR0 IRQ pad select. */ - } IOM0IRQ_b; - } ; - - union { - __IOM uint32_t IOM1IRQ; /*!< (@ 0x000000C4) IOM1 Flow Control IRQ Select */ - - struct { - __IOM uint32_t IOM1IRQ : 6; /*!< [5..0] IOMSTR1 IRQ pad select. */ - } IOM1IRQ_b; - } ; - - union { - __IOM uint32_t IOM2IRQ; /*!< (@ 0x000000C8) IOM2 Flow Control IRQ Select */ - - struct { - __IOM uint32_t IOM2IRQ : 6; /*!< [5..0] IOMSTR2 IRQ pad select. */ - } IOM2IRQ_b; - } ; - - union { - __IOM uint32_t IOM3IRQ; /*!< (@ 0x000000CC) IOM3 Flow Control IRQ Select */ - - struct { - __IOM uint32_t IOM3IRQ : 6; /*!< [5..0] IOMSTR3 IRQ pad select. */ - } IOM3IRQ_b; - } ; - - union { - __IOM uint32_t IOM4IRQ; /*!< (@ 0x000000D0) IOM4 Flow Control IRQ Select */ - - struct { - __IOM uint32_t IOM4IRQ : 6; /*!< [5..0] IOMSTR4 IRQ pad select. */ - } IOM4IRQ_b; - } ; - - union { - __IOM uint32_t IOM5IRQ; /*!< (@ 0x000000D4) IOM5 Flow Control IRQ Select */ - - struct { - __IOM uint32_t IOM5IRQ : 6; /*!< [5..0] IOMSTR5 IRQ pad select. */ - } IOM5IRQ_b; - } ; - - union { - __IOM uint32_t BLEIFIRQ; /*!< (@ 0x000000D8) BLEIF Flow Control IRQ Select */ - - struct { - __IOM uint32_t BLEIFIRQ : 6; /*!< [5..0] BLEIF IRQ pad select. */ - } BLEIFIRQ_b; - } ; - - union { - __IOM uint32_t GPIOOBS; /*!< (@ 0x000000DC) GPIO Observation Mode Sample register */ - - struct { - __IOM uint32_t OBS_DATA : 16; /*!< [15..0] Sample of the data output on the GPIO observation port. - May have async sampling issues, as the data is not synronized - to the read operation. Intended for debug purposes only */ - } GPIOOBS_b; - } ; - - union { - __IOM uint32_t ALTPADCFGA; /*!< (@ 0x000000E0) Alternate Pad Configuration reg0 (Pads 3,2,1,0) */ - - struct { - __IOM uint32_t PAD0_DS1 : 1; /*!< [0..0] Pad 0 high order drive strength selection. Used in conjunction - with PAD0STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD0_SR : 1; /*!< [4..4] Pad 0 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD1_DS1 : 1; /*!< [8..8] Pad 1 high order drive strength selection. Used in conjunction - with PAD1STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD1_SR : 1; /*!< [12..12] Pad 1 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD2_DS1 : 1; /*!< [16..16] Pad 2 high order drive strength selection. Used in - conjunction with PAD2STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD2_SR : 1; /*!< [20..20] Pad 2 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD3_DS1 : 1; /*!< [24..24] Pad 3 high order drive strength selection. Used in - conjunction with PAD3STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD3_SR : 1; /*!< [28..28] Pad 3 slew rate selection. */ - } ALTPADCFGA_b; - } ; - - union { - __IOM uint32_t ALTPADCFGB; /*!< (@ 0x000000E4) Alternate Pad Configuration reg1 (Pads 7,6,5,4) */ - - struct { - __IOM uint32_t PAD4_DS1 : 1; /*!< [0..0] Pad 4 high order drive strength selection. Used in conjunction - with PAD4STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD4_SR : 1; /*!< [4..4] Pad 4 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD5_DS1 : 1; /*!< [8..8] Pad 5 high order drive strength selection. Used in conjunction - with PAD5STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD5_SR : 1; /*!< [12..12] Pad 5 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD6_DS1 : 1; /*!< [16..16] Pad 6 high order drive strength selection. Used in - conjunction with PAD6STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD6_SR : 1; /*!< [20..20] Pad 6 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD7_DS1 : 1; /*!< [24..24] Pad 7 high order drive strength selection. Used in - conjunction with PAD7STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD7_SR : 1; /*!< [28..28] Pad 7 slew rate selection. */ - } ALTPADCFGB_b; - } ; - - union { - __IOM uint32_t ALTPADCFGC; /*!< (@ 0x000000E8) Alternate Pad Configuration reg2 (Pads 11,10,9,8) */ - - struct { - __IOM uint32_t PAD8_DS1 : 1; /*!< [0..0] Pad 8 high order drive strength selection. Used in conjunction - with PAD8STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD8_SR : 1; /*!< [4..4] Pad 8 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD9_DS1 : 1; /*!< [8..8] Pad 9 high order drive strength selection. Used in conjunction - with PAD9STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD9_SR : 1; /*!< [12..12] Pad 9 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD10_DS1 : 1; /*!< [16..16] Pad 10 high order drive strength selection. Used in - conjunction with PAD10STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD10_SR : 1; /*!< [20..20] Pad 10 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD11_DS1 : 1; /*!< [24..24] Pad 11 high order drive strength selection. Used in - conjunction with PAD11STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD11_SR : 1; /*!< [28..28] Pad 11 slew rate selection. */ - } ALTPADCFGC_b; - } ; - - union { - __IOM uint32_t ALTPADCFGD; /*!< (@ 0x000000EC) Alternate Pad Configuration reg3 (Pads 15,14,13,12) */ - - struct { - __IOM uint32_t PAD12_DS1 : 1; /*!< [0..0] Pad 12 high order drive strength selection. Used in conjunction - with PAD12STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD12_SR : 1; /*!< [4..4] Pad 12 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD13_DS1 : 1; /*!< [8..8] Pad 13 high order drive strength selection. Used in conjunction - with PAD13STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD13_SR : 1; /*!< [12..12] Pad 13 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD14_DS1 : 1; /*!< [16..16] Pad 14 high order drive strength selection. Used in - conjunction with PAD14STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD14_SR : 1; /*!< [20..20] Pad 14 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD15_DS1 : 1; /*!< [24..24] Pad 15 high order drive strength selection. Used in - conjunction with PAD15STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD15_SR : 1; /*!< [28..28] Pad 15 slew rate selection. */ - } ALTPADCFGD_b; - } ; - - union { - __IOM uint32_t ALTPADCFGE; /*!< (@ 0x000000F0) Alternate Pad Configuration reg4 (Pads 19,18,17,16) */ - - struct { - __IOM uint32_t PAD16_DS1 : 1; /*!< [0..0] Pad 16 high order drive strength selection. Used in conjunction - with PAD16STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD16_SR : 1; /*!< [4..4] Pad 16 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD17_DS1 : 1; /*!< [8..8] Pad 17 high order drive strength selection. Used in conjunction - with PAD17STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD17_SR : 1; /*!< [12..12] Pad 17 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD18_DS1 : 1; /*!< [16..16] Pad 18 high order drive strength selection. Used in - conjunction with PAD18STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD18_SR : 1; /*!< [20..20] Pad 18 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD19_DS1 : 1; /*!< [24..24] Pad 19 high order drive strength selection. Used in - conjunction with PAD19STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD19_SR : 1; /*!< [28..28] Pad 19 slew rate selection. */ - } ALTPADCFGE_b; - } ; - - union { - __IOM uint32_t ALTPADCFGF; /*!< (@ 0x000000F4) Alternate Pad Configuration reg5 (Pads 23,22,21,20) */ - - struct { - __IOM uint32_t PAD20_DS1 : 1; /*!< [0..0] Pad 20 high order drive strength selection. Used in conjunction - with PAD20STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD20_SR : 1; /*!< [4..4] Pad 20 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD21_DS1 : 1; /*!< [8..8] Pad 21 high order drive strength selection. Used in conjunction - with PAD21STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD21_SR : 1; /*!< [12..12] Pad 21 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD22_DS1 : 1; /*!< [16..16] Pad 22 high order drive strength selection. Used in - conjunction with PAD22STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD22_SR : 1; /*!< [20..20] Pad 22 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD23_DS1 : 1; /*!< [24..24] Pad 23 high order drive strength selection. Used in - conjunction with PAD23STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD23_SR : 1; /*!< [28..28] Pad 23 slew rate selection. */ - } ALTPADCFGF_b; - } ; - - union { - __IOM uint32_t ALTPADCFGG; /*!< (@ 0x000000F8) Alternate Pad Configuration reg6 (Pads 27,26,25,24) */ - - struct { - __IOM uint32_t PAD24_DS1 : 1; /*!< [0..0] Pad 24 high order drive strength selection. Used in conjunction - with PAD24STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD24_SR : 1; /*!< [4..4] Pad 24 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD25_DS1 : 1; /*!< [8..8] Pad 25 high order drive strength selection. Used in conjunction - with PAD25STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD25_SR : 1; /*!< [12..12] Pad 25 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD26_DS1 : 1; /*!< [16..16] Pad 26 high order drive strength selection. Used in - conjunction with PAD26STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD26_SR : 1; /*!< [20..20] Pad 26 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD27_DS1 : 1; /*!< [24..24] Pad 27 high order drive strength selection. Used in - conjunction with PAD27STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD27_SR : 1; /*!< [28..28] Pad 27 slew rate selection. */ - } ALTPADCFGG_b; - } ; - - union { - __IOM uint32_t ALTPADCFGH; /*!< (@ 0x000000FC) Alternate Pad Configuration reg7 (Pads 31,30,29,28) */ - - struct { - __IOM uint32_t PAD28_DS1 : 1; /*!< [0..0] Pad 28 high order drive strength selection. Used in conjunction - with PAD28STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD28_SR : 1; /*!< [4..4] Pad 28 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD29_DS1 : 1; /*!< [8..8] Pad 29 high order drive strength selection. Used in conjunction - with PAD29STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD29_SR : 1; /*!< [12..12] Pad 29 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD30_DS1 : 1; /*!< [16..16] Pad 30 high order drive strength selection. Used in - conjunction with PAD30STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD30_SR : 1; /*!< [20..20] Pad 30 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD31_DS1 : 1; /*!< [24..24] Pad 31 high order drive strength selection. Used in - conjunction with PAD31STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD31_SR : 1; /*!< [28..28] Pad 31 slew rate selection. */ - } ALTPADCFGH_b; - } ; - - union { - __IOM uint32_t ALTPADCFGI; /*!< (@ 0x00000100) Alternate Pad Configuration reg8 (Pads 35,34,33,32) */ - - struct { - __IOM uint32_t PAD32_DS1 : 1; /*!< [0..0] Pad 32 high order drive strength selection. Used in conjunction - with PAD32STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD32_SR : 1; /*!< [4..4] Pad 32 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD33_DS1 : 1; /*!< [8..8] Pad 33 high order drive strength selection. Used in conjunction - with PAD33STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD33_SR : 1; /*!< [12..12] Pad 33 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD34_DS1 : 1; /*!< [16..16] Pad 34 high order drive strength selection. Used in - conjunction with PAD34STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD34_SR : 1; /*!< [20..20] Pad 34 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD35_DS1 : 1; /*!< [24..24] Pad 35 high order drive strength selection. Used in - conjunction with PAD35STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD35_SR : 1; /*!< [28..28] Pad 35 slew rate selection. */ - } ALTPADCFGI_b; - } ; - - union { - __IOM uint32_t ALTPADCFGJ; /*!< (@ 0x00000104) Alternate Pad Configuration reg9 (Pads 39,38,37,36) */ - - struct { - __IOM uint32_t PAD36_DS1 : 1; /*!< [0..0] Pad 36 high order drive strength selection. Used in conjunction - with PAD36STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD36_SR : 1; /*!< [4..4] Pad 36 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD37_DS1 : 1; /*!< [8..8] Pad 37 high order drive strength selection. Used in conjunction - with PAD37STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD37_SR : 1; /*!< [12..12] Pad 37 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD38_DS1 : 1; /*!< [16..16] Pad 38 high order drive strength selection. Used in - conjunction with PAD38STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD38_SR : 1; /*!< [20..20] Pad 38 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD39_DS1 : 1; /*!< [24..24] Pad 39 high order drive strength selection. Used in - conjunction with PAD39STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD39_SR : 1; /*!< [28..28] Pad 39 slew rate selection. */ - } ALTPADCFGJ_b; - } ; - - union { - __IOM uint32_t ALTPADCFGK; /*!< (@ 0x00000108) Alternate Pad Configuration reg10 (Pads 43,42,41,40) */ - - struct { - __IOM uint32_t PAD40_DS1 : 1; /*!< [0..0] Pad 40 high order drive strength selection. Used in conjunction - with PAD40STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD40_SR : 1; /*!< [4..4] Pad 40 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD41_DS1 : 1; /*!< [8..8] Pad 41 high order drive strength selection. Used in conjunction - with PAD41STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD41_SR : 1; /*!< [12..12] Pad 41 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD42_DS1 : 1; /*!< [16..16] Pad 42 high order drive strength selection. Used in - conjunction with PAD42STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD42_SR : 1; /*!< [20..20] Pad 42 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD43_DS1 : 1; /*!< [24..24] Pad 43 high order drive strength selection. Used in - conjunction with PAD43STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD43_SR : 1; /*!< [28..28] Pad 43 slew rate selection. */ - } ALTPADCFGK_b; - } ; - - union { - __IOM uint32_t ALTPADCFGL; /*!< (@ 0x0000010C) Alternate Pad Configuration reg11 (Pads 47,46,45,44) */ - - struct { - __IOM uint32_t PAD44_DS1 : 1; /*!< [0..0] Pad 44 high order drive strength selection. Used in conjunction - with PAD44STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD44_SR : 1; /*!< [4..4] Pad 44 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD45_DS1 : 1; /*!< [8..8] Pad 45 high order drive strength selection. Used in conjunction - with PAD45STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD45_SR : 1; /*!< [12..12] Pad 45 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD46_DS1 : 1; /*!< [16..16] Pad 46 high order drive strength selection. Used in - conjunction with PAD46STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD46_SR : 1; /*!< [20..20] Pad 46 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD47_DS1 : 1; /*!< [24..24] Pad 47 high order drive strength selection. Used in - conjunction with PAD47STRNG field to set the pad drive - strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD47_SR : 1; /*!< [28..28] Pad 47 slew rate selection. */ - } ALTPADCFGL_b; - } ; - - union { - __IOM uint32_t ALTPADCFGM; /*!< (@ 0x00000110) Alternate Pad Configuration reg12 (Pads 49,48) */ - - struct { - __IOM uint32_t PAD48_DS1 : 1; /*!< [0..0] Pad 48 high order drive strength selection. Used in conjunction - with PAD48STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD48_SR : 1; /*!< [4..4] Pad 48 slew rate selection. */ - __IM uint32_t : 3; - __IOM uint32_t PAD49_DS1 : 1; /*!< [8..8] Pad 49 high order drive strength selection. Used in conjunction - with PAD49STRNG field to set the pad drive strength. */ - __IM uint32_t : 3; - __IOM uint32_t PAD49_SR : 1; /*!< [12..12] Pad 49 slew rate selection. */ - } ALTPADCFGM_b; - } ; - - union { - __IOM uint32_t SCDET; /*!< (@ 0x00000114) SCARD Card Detect select */ - - struct { - __IOM uint32_t SCDET : 6; /*!< [5..0] SCARD card detect pad select. */ - } SCDET_b; - } ; - - union { - __IOM uint32_t CTENCFG; /*!< (@ 0x00000118) Counter/Timer Enable Config */ - - struct { - __IOM uint32_t EN0 : 1; /*!< [0..0] CT0 Enable */ - __IOM uint32_t EN1 : 1; /*!< [1..1] CT1 Enable */ - __IOM uint32_t EN2 : 1; /*!< [2..2] CT2 Enable */ - __IOM uint32_t EN3 : 1; /*!< [3..3] CT3 Enable */ - __IOM uint32_t EN4 : 1; /*!< [4..4] CT4 Enable */ - __IOM uint32_t EN5 : 1; /*!< [5..5] CT5 Enable */ - __IOM uint32_t EN6 : 1; /*!< [6..6] CT6 Enable */ - __IOM uint32_t EN7 : 1; /*!< [7..7] CT7 Enable */ - __IOM uint32_t EN8 : 1; /*!< [8..8] CT8 Enable */ - __IOM uint32_t EN9 : 1; /*!< [9..9] CT9 Enable */ - __IOM uint32_t EN10 : 1; /*!< [10..10] CT10 Enable */ - __IOM uint32_t EN11 : 1; /*!< [11..11] CT11 Enable */ - __IOM uint32_t EN12 : 1; /*!< [12..12] CT12 Enable */ - __IOM uint32_t EN13 : 1; /*!< [13..13] CT13 Enable */ - __IOM uint32_t EN14 : 1; /*!< [14..14] CT14 Enable */ - __IOM uint32_t EN15 : 1; /*!< [15..15] CT15 Enable */ - __IOM uint32_t EN16 : 1; /*!< [16..16] CT16 Enable */ - __IOM uint32_t EN17 : 1; /*!< [17..17] CT17 Enable */ - __IOM uint32_t EN18 : 1; /*!< [18..18] CT18 Enable */ - __IOM uint32_t EN19 : 1; /*!< [19..19] CT19 Enable */ - __IOM uint32_t EN20 : 1; /*!< [20..20] CT20 Enable */ - __IOM uint32_t EN21 : 1; /*!< [21..21] CT21 Enable */ - __IOM uint32_t EN22 : 1; /*!< [22..22] CT22 Enable */ - __IOM uint32_t EN23 : 1; /*!< [23..23] CT23 Enable */ - __IOM uint32_t EN24 : 1; /*!< [24..24] CT24 Enable */ - __IOM uint32_t EN25 : 1; /*!< [25..25] CT25 Enable */ - __IOM uint32_t EN26 : 1; /*!< [26..26] CT26 Enable */ - __IOM uint32_t EN27 : 1; /*!< [27..27] CT27 Enable */ - __IOM uint32_t EN28 : 1; /*!< [28..28] CT28 Enable */ - __IOM uint32_t EN29 : 1; /*!< [29..29] CT29 Enable */ - __IOM uint32_t EN30 : 1; /*!< [30..30] CT30 Enable */ - __IOM uint32_t EN31 : 1; /*!< [31..31] CT31 Enable */ - } CTENCFG_b; - } ; - __IM uint32_t RESERVED4[57]; - - union { - __IOM uint32_t INT0EN; /*!< (@ 0x00000200) GPIO Interrupt Registers 31-0: Enable */ - - struct { - __IOM uint32_t GPIO0 : 1; /*!< [0..0] GPIO0 interrupt. */ - __IOM uint32_t GPIO1 : 1; /*!< [1..1] GPIO1 interrupt. */ - __IOM uint32_t GPIO2 : 1; /*!< [2..2] GPIO2 interrupt. */ - __IOM uint32_t GPIO3 : 1; /*!< [3..3] GPIO3 interrupt. */ - __IOM uint32_t GPIO4 : 1; /*!< [4..4] GPIO4 interrupt. */ - __IOM uint32_t GPIO5 : 1; /*!< [5..5] GPIO5 interrupt. */ - __IOM uint32_t GPIO6 : 1; /*!< [6..6] GPIO6 interrupt. */ - __IOM uint32_t GPIO7 : 1; /*!< [7..7] GPIO7 interrupt. */ - __IOM uint32_t GPIO8 : 1; /*!< [8..8] GPIO8 interrupt. */ - __IOM uint32_t GPIO9 : 1; /*!< [9..9] GPIO9 interrupt. */ - __IOM uint32_t GPIO10 : 1; /*!< [10..10] GPIO10 interrupt. */ - __IOM uint32_t GPIO11 : 1; /*!< [11..11] GPIO11 interrupt. */ - __IOM uint32_t GPIO12 : 1; /*!< [12..12] GPIO12 interrupt. */ - __IOM uint32_t GPIO13 : 1; /*!< [13..13] GPIO13 interrupt. */ - __IOM uint32_t GPIO14 : 1; /*!< [14..14] GPIO14 interrupt. */ - __IOM uint32_t GPIO15 : 1; /*!< [15..15] GPIO15 interrupt. */ - __IOM uint32_t GPIO16 : 1; /*!< [16..16] GPIO16 interrupt. */ - __IOM uint32_t GPIO17 : 1; /*!< [17..17] GPIO17 interrupt. */ - __IOM uint32_t GPIO18 : 1; /*!< [18..18] GPIO18interrupt. */ - __IOM uint32_t GPIO19 : 1; /*!< [19..19] GPIO19 interrupt. */ - __IOM uint32_t GPIO20 : 1; /*!< [20..20] GPIO20 interrupt. */ - __IOM uint32_t GPIO21 : 1; /*!< [21..21] GPIO21 interrupt. */ - __IOM uint32_t GPIO22 : 1; /*!< [22..22] GPIO22 interrupt. */ - __IOM uint32_t GPIO23 : 1; /*!< [23..23] GPIO23 interrupt. */ - __IOM uint32_t GPIO24 : 1; /*!< [24..24] GPIO24 interrupt. */ - __IOM uint32_t GPIO25 : 1; /*!< [25..25] GPIO25 interrupt. */ - __IOM uint32_t GPIO26 : 1; /*!< [26..26] GPIO26 interrupt. */ - __IOM uint32_t GPIO27 : 1; /*!< [27..27] GPIO27 interrupt. */ - __IOM uint32_t GPIO28 : 1; /*!< [28..28] GPIO28 interrupt. */ - __IOM uint32_t GPIO29 : 1; /*!< [29..29] GPIO29 interrupt. */ - __IOM uint32_t GPIO30 : 1; /*!< [30..30] GPIO30 interrupt. */ - __IOM uint32_t GPIO31 : 1; /*!< [31..31] GPIO31 interrupt. */ - } INT0EN_b; - } ; - - union { - __IOM uint32_t INT0STAT; /*!< (@ 0x00000204) GPIO Interrupt Registers 31-0: Status */ - - struct { - __IOM uint32_t GPIO0 : 1; /*!< [0..0] GPIO0 interrupt. */ - __IOM uint32_t GPIO1 : 1; /*!< [1..1] GPIO1 interrupt. */ - __IOM uint32_t GPIO2 : 1; /*!< [2..2] GPIO2 interrupt. */ - __IOM uint32_t GPIO3 : 1; /*!< [3..3] GPIO3 interrupt. */ - __IOM uint32_t GPIO4 : 1; /*!< [4..4] GPIO4 interrupt. */ - __IOM uint32_t GPIO5 : 1; /*!< [5..5] GPIO5 interrupt. */ - __IOM uint32_t GPIO6 : 1; /*!< [6..6] GPIO6 interrupt. */ - __IOM uint32_t GPIO7 : 1; /*!< [7..7] GPIO7 interrupt. */ - __IOM uint32_t GPIO8 : 1; /*!< [8..8] GPIO8 interrupt. */ - __IOM uint32_t GPIO9 : 1; /*!< [9..9] GPIO9 interrupt. */ - __IOM uint32_t GPIO10 : 1; /*!< [10..10] GPIO10 interrupt. */ - __IOM uint32_t GPIO11 : 1; /*!< [11..11] GPIO11 interrupt. */ - __IOM uint32_t GPIO12 : 1; /*!< [12..12] GPIO12 interrupt. */ - __IOM uint32_t GPIO13 : 1; /*!< [13..13] GPIO13 interrupt. */ - __IOM uint32_t GPIO14 : 1; /*!< [14..14] GPIO14 interrupt. */ - __IOM uint32_t GPIO15 : 1; /*!< [15..15] GPIO15 interrupt. */ - __IOM uint32_t GPIO16 : 1; /*!< [16..16] GPIO16 interrupt. */ - __IOM uint32_t GPIO17 : 1; /*!< [17..17] GPIO17 interrupt. */ - __IOM uint32_t GPIO18 : 1; /*!< [18..18] GPIO18interrupt. */ - __IOM uint32_t GPIO19 : 1; /*!< [19..19] GPIO19 interrupt. */ - __IOM uint32_t GPIO20 : 1; /*!< [20..20] GPIO20 interrupt. */ - __IOM uint32_t GPIO21 : 1; /*!< [21..21] GPIO21 interrupt. */ - __IOM uint32_t GPIO22 : 1; /*!< [22..22] GPIO22 interrupt. */ - __IOM uint32_t GPIO23 : 1; /*!< [23..23] GPIO23 interrupt. */ - __IOM uint32_t GPIO24 : 1; /*!< [24..24] GPIO24 interrupt. */ - __IOM uint32_t GPIO25 : 1; /*!< [25..25] GPIO25 interrupt. */ - __IOM uint32_t GPIO26 : 1; /*!< [26..26] GPIO26 interrupt. */ - __IOM uint32_t GPIO27 : 1; /*!< [27..27] GPIO27 interrupt. */ - __IOM uint32_t GPIO28 : 1; /*!< [28..28] GPIO28 interrupt. */ - __IOM uint32_t GPIO29 : 1; /*!< [29..29] GPIO29 interrupt. */ - __IOM uint32_t GPIO30 : 1; /*!< [30..30] GPIO30 interrupt. */ - __IOM uint32_t GPIO31 : 1; /*!< [31..31] GPIO31 interrupt. */ - } INT0STAT_b; - } ; - - union { - __IOM uint32_t INT0CLR; /*!< (@ 0x00000208) GPIO Interrupt Registers 31-0: Clear */ - - struct { - __IOM uint32_t GPIO0 : 1; /*!< [0..0] GPIO0 interrupt. */ - __IOM uint32_t GPIO1 : 1; /*!< [1..1] GPIO1 interrupt. */ - __IOM uint32_t GPIO2 : 1; /*!< [2..2] GPIO2 interrupt. */ - __IOM uint32_t GPIO3 : 1; /*!< [3..3] GPIO3 interrupt. */ - __IOM uint32_t GPIO4 : 1; /*!< [4..4] GPIO4 interrupt. */ - __IOM uint32_t GPIO5 : 1; /*!< [5..5] GPIO5 interrupt. */ - __IOM uint32_t GPIO6 : 1; /*!< [6..6] GPIO6 interrupt. */ - __IOM uint32_t GPIO7 : 1; /*!< [7..7] GPIO7 interrupt. */ - __IOM uint32_t GPIO8 : 1; /*!< [8..8] GPIO8 interrupt. */ - __IOM uint32_t GPIO9 : 1; /*!< [9..9] GPIO9 interrupt. */ - __IOM uint32_t GPIO10 : 1; /*!< [10..10] GPIO10 interrupt. */ - __IOM uint32_t GPIO11 : 1; /*!< [11..11] GPIO11 interrupt. */ - __IOM uint32_t GPIO12 : 1; /*!< [12..12] GPIO12 interrupt. */ - __IOM uint32_t GPIO13 : 1; /*!< [13..13] GPIO13 interrupt. */ - __IOM uint32_t GPIO14 : 1; /*!< [14..14] GPIO14 interrupt. */ - __IOM uint32_t GPIO15 : 1; /*!< [15..15] GPIO15 interrupt. */ - __IOM uint32_t GPIO16 : 1; /*!< [16..16] GPIO16 interrupt. */ - __IOM uint32_t GPIO17 : 1; /*!< [17..17] GPIO17 interrupt. */ - __IOM uint32_t GPIO18 : 1; /*!< [18..18] GPIO18interrupt. */ - __IOM uint32_t GPIO19 : 1; /*!< [19..19] GPIO19 interrupt. */ - __IOM uint32_t GPIO20 : 1; /*!< [20..20] GPIO20 interrupt. */ - __IOM uint32_t GPIO21 : 1; /*!< [21..21] GPIO21 interrupt. */ - __IOM uint32_t GPIO22 : 1; /*!< [22..22] GPIO22 interrupt. */ - __IOM uint32_t GPIO23 : 1; /*!< [23..23] GPIO23 interrupt. */ - __IOM uint32_t GPIO24 : 1; /*!< [24..24] GPIO24 interrupt. */ - __IOM uint32_t GPIO25 : 1; /*!< [25..25] GPIO25 interrupt. */ - __IOM uint32_t GPIO26 : 1; /*!< [26..26] GPIO26 interrupt. */ - __IOM uint32_t GPIO27 : 1; /*!< [27..27] GPIO27 interrupt. */ - __IOM uint32_t GPIO28 : 1; /*!< [28..28] GPIO28 interrupt. */ - __IOM uint32_t GPIO29 : 1; /*!< [29..29] GPIO29 interrupt. */ - __IOM uint32_t GPIO30 : 1; /*!< [30..30] GPIO30 interrupt. */ - __IOM uint32_t GPIO31 : 1; /*!< [31..31] GPIO31 interrupt. */ - } INT0CLR_b; - } ; - - union { - __IOM uint32_t INT0SET; /*!< (@ 0x0000020C) GPIO Interrupt Registers 31-0: Set */ - - struct { - __IOM uint32_t GPIO0 : 1; /*!< [0..0] GPIO0 interrupt. */ - __IOM uint32_t GPIO1 : 1; /*!< [1..1] GPIO1 interrupt. */ - __IOM uint32_t GPIO2 : 1; /*!< [2..2] GPIO2 interrupt. */ - __IOM uint32_t GPIO3 : 1; /*!< [3..3] GPIO3 interrupt. */ - __IOM uint32_t GPIO4 : 1; /*!< [4..4] GPIO4 interrupt. */ - __IOM uint32_t GPIO5 : 1; /*!< [5..5] GPIO5 interrupt. */ - __IOM uint32_t GPIO6 : 1; /*!< [6..6] GPIO6 interrupt. */ - __IOM uint32_t GPIO7 : 1; /*!< [7..7] GPIO7 interrupt. */ - __IOM uint32_t GPIO8 : 1; /*!< [8..8] GPIO8 interrupt. */ - __IOM uint32_t GPIO9 : 1; /*!< [9..9] GPIO9 interrupt. */ - __IOM uint32_t GPIO10 : 1; /*!< [10..10] GPIO10 interrupt. */ - __IOM uint32_t GPIO11 : 1; /*!< [11..11] GPIO11 interrupt. */ - __IOM uint32_t GPIO12 : 1; /*!< [12..12] GPIO12 interrupt. */ - __IOM uint32_t GPIO13 : 1; /*!< [13..13] GPIO13 interrupt. */ - __IOM uint32_t GPIO14 : 1; /*!< [14..14] GPIO14 interrupt. */ - __IOM uint32_t GPIO15 : 1; /*!< [15..15] GPIO15 interrupt. */ - __IOM uint32_t GPIO16 : 1; /*!< [16..16] GPIO16 interrupt. */ - __IOM uint32_t GPIO17 : 1; /*!< [17..17] GPIO17 interrupt. */ - __IOM uint32_t GPIO18 : 1; /*!< [18..18] GPIO18interrupt. */ - __IOM uint32_t GPIO19 : 1; /*!< [19..19] GPIO19 interrupt. */ - __IOM uint32_t GPIO20 : 1; /*!< [20..20] GPIO20 interrupt. */ - __IOM uint32_t GPIO21 : 1; /*!< [21..21] GPIO21 interrupt. */ - __IOM uint32_t GPIO22 : 1; /*!< [22..22] GPIO22 interrupt. */ - __IOM uint32_t GPIO23 : 1; /*!< [23..23] GPIO23 interrupt. */ - __IOM uint32_t GPIO24 : 1; /*!< [24..24] GPIO24 interrupt. */ - __IOM uint32_t GPIO25 : 1; /*!< [25..25] GPIO25 interrupt. */ - __IOM uint32_t GPIO26 : 1; /*!< [26..26] GPIO26 interrupt. */ - __IOM uint32_t GPIO27 : 1; /*!< [27..27] GPIO27 interrupt. */ - __IOM uint32_t GPIO28 : 1; /*!< [28..28] GPIO28 interrupt. */ - __IOM uint32_t GPIO29 : 1; /*!< [29..29] GPIO29 interrupt. */ - __IOM uint32_t GPIO30 : 1; /*!< [30..30] GPIO30 interrupt. */ - __IOM uint32_t GPIO31 : 1; /*!< [31..31] GPIO31 interrupt. */ - } INT0SET_b; - } ; - - union { - __IOM uint32_t INT1EN; /*!< (@ 0x00000210) GPIO Interrupt Registers 49-32: Enable */ - - struct { - __IOM uint32_t GPIO32 : 1; /*!< [0..0] GPIO32 interrupt. */ - __IOM uint32_t GPIO33 : 1; /*!< [1..1] GPIO33 interrupt. */ - __IOM uint32_t GPIO34 : 1; /*!< [2..2] GPIO34 interrupt. */ - __IOM uint32_t GPIO35 : 1; /*!< [3..3] GPIO35 interrupt. */ - __IOM uint32_t GPIO36 : 1; /*!< [4..4] GPIO36 interrupt. */ - __IOM uint32_t GPIO37 : 1; /*!< [5..5] GPIO37 interrupt. */ - __IOM uint32_t GPIO38 : 1; /*!< [6..6] GPIO38 interrupt. */ - __IOM uint32_t GPIO39 : 1; /*!< [7..7] GPIO39 interrupt. */ - __IOM uint32_t GPIO40 : 1; /*!< [8..8] GPIO40 interrupt. */ - __IOM uint32_t GPIO41 : 1; /*!< [9..9] GPIO41 interrupt. */ - __IOM uint32_t GPIO42 : 1; /*!< [10..10] GPIO42 interrupt. */ - __IOM uint32_t GPIO43 : 1; /*!< [11..11] GPIO43 interrupt. */ - __IOM uint32_t GPIO44 : 1; /*!< [12..12] GPIO44 interrupt. */ - __IOM uint32_t GPIO45 : 1; /*!< [13..13] GPIO45 interrupt. */ - __IOM uint32_t GPIO46 : 1; /*!< [14..14] GPIO46 interrupt. */ - __IOM uint32_t GPIO47 : 1; /*!< [15..15] GPIO47 interrupt. */ - __IOM uint32_t GPIO48 : 1; /*!< [16..16] GPIO48 interrupt. */ - __IOM uint32_t GPIO49 : 1; /*!< [17..17] GPIO49 interrupt. */ - } INT1EN_b; - } ; - - union { - __IOM uint32_t INT1STAT; /*!< (@ 0x00000214) GPIO Interrupt Registers 49-32: Status */ - - struct { - __IOM uint32_t GPIO32 : 1; /*!< [0..0] GPIO32 interrupt. */ - __IOM uint32_t GPIO33 : 1; /*!< [1..1] GPIO33 interrupt. */ - __IOM uint32_t GPIO34 : 1; /*!< [2..2] GPIO34 interrupt. */ - __IOM uint32_t GPIO35 : 1; /*!< [3..3] GPIO35 interrupt. */ - __IOM uint32_t GPIO36 : 1; /*!< [4..4] GPIO36 interrupt. */ - __IOM uint32_t GPIO37 : 1; /*!< [5..5] GPIO37 interrupt. */ - __IOM uint32_t GPIO38 : 1; /*!< [6..6] GPIO38 interrupt. */ - __IOM uint32_t GPIO39 : 1; /*!< [7..7] GPIO39 interrupt. */ - __IOM uint32_t GPIO40 : 1; /*!< [8..8] GPIO40 interrupt. */ - __IOM uint32_t GPIO41 : 1; /*!< [9..9] GPIO41 interrupt. */ - __IOM uint32_t GPIO42 : 1; /*!< [10..10] GPIO42 interrupt. */ - __IOM uint32_t GPIO43 : 1; /*!< [11..11] GPIO43 interrupt. */ - __IOM uint32_t GPIO44 : 1; /*!< [12..12] GPIO44 interrupt. */ - __IOM uint32_t GPIO45 : 1; /*!< [13..13] GPIO45 interrupt. */ - __IOM uint32_t GPIO46 : 1; /*!< [14..14] GPIO46 interrupt. */ - __IOM uint32_t GPIO47 : 1; /*!< [15..15] GPIO47 interrupt. */ - __IOM uint32_t GPIO48 : 1; /*!< [16..16] GPIO48 interrupt. */ - __IOM uint32_t GPIO49 : 1; /*!< [17..17] GPIO49 interrupt. */ - } INT1STAT_b; - } ; - - union { - __IOM uint32_t INT1CLR; /*!< (@ 0x00000218) GPIO Interrupt Registers 49-32: Clear */ - - struct { - __IOM uint32_t GPIO32 : 1; /*!< [0..0] GPIO32 interrupt. */ - __IOM uint32_t GPIO33 : 1; /*!< [1..1] GPIO33 interrupt. */ - __IOM uint32_t GPIO34 : 1; /*!< [2..2] GPIO34 interrupt. */ - __IOM uint32_t GPIO35 : 1; /*!< [3..3] GPIO35 interrupt. */ - __IOM uint32_t GPIO36 : 1; /*!< [4..4] GPIO36 interrupt. */ - __IOM uint32_t GPIO37 : 1; /*!< [5..5] GPIO37 interrupt. */ - __IOM uint32_t GPIO38 : 1; /*!< [6..6] GPIO38 interrupt. */ - __IOM uint32_t GPIO39 : 1; /*!< [7..7] GPIO39 interrupt. */ - __IOM uint32_t GPIO40 : 1; /*!< [8..8] GPIO40 interrupt. */ - __IOM uint32_t GPIO41 : 1; /*!< [9..9] GPIO41 interrupt. */ - __IOM uint32_t GPIO42 : 1; /*!< [10..10] GPIO42 interrupt. */ - __IOM uint32_t GPIO43 : 1; /*!< [11..11] GPIO43 interrupt. */ - __IOM uint32_t GPIO44 : 1; /*!< [12..12] GPIO44 interrupt. */ - __IOM uint32_t GPIO45 : 1; /*!< [13..13] GPIO45 interrupt. */ - __IOM uint32_t GPIO46 : 1; /*!< [14..14] GPIO46 interrupt. */ - __IOM uint32_t GPIO47 : 1; /*!< [15..15] GPIO47 interrupt. */ - __IOM uint32_t GPIO48 : 1; /*!< [16..16] GPIO48 interrupt. */ - __IOM uint32_t GPIO49 : 1; /*!< [17..17] GPIO49 interrupt. */ - } INT1CLR_b; - } ; - - union { - __IOM uint32_t INT1SET; /*!< (@ 0x0000021C) GPIO Interrupt Registers 49-32: Set */ - - struct { - __IOM uint32_t GPIO32 : 1; /*!< [0..0] GPIO32 interrupt. */ - __IOM uint32_t GPIO33 : 1; /*!< [1..1] GPIO33 interrupt. */ - __IOM uint32_t GPIO34 : 1; /*!< [2..2] GPIO34 interrupt. */ - __IOM uint32_t GPIO35 : 1; /*!< [3..3] GPIO35 interrupt. */ - __IOM uint32_t GPIO36 : 1; /*!< [4..4] GPIO36 interrupt. */ - __IOM uint32_t GPIO37 : 1; /*!< [5..5] GPIO37 interrupt. */ - __IOM uint32_t GPIO38 : 1; /*!< [6..6] GPIO38 interrupt. */ - __IOM uint32_t GPIO39 : 1; /*!< [7..7] GPIO39 interrupt. */ - __IOM uint32_t GPIO40 : 1; /*!< [8..8] GPIO40 interrupt. */ - __IOM uint32_t GPIO41 : 1; /*!< [9..9] GPIO41 interrupt. */ - __IOM uint32_t GPIO42 : 1; /*!< [10..10] GPIO42 interrupt. */ - __IOM uint32_t GPIO43 : 1; /*!< [11..11] GPIO43 interrupt. */ - __IOM uint32_t GPIO44 : 1; /*!< [12..12] GPIO44 interrupt. */ - __IOM uint32_t GPIO45 : 1; /*!< [13..13] GPIO45 interrupt. */ - __IOM uint32_t GPIO46 : 1; /*!< [14..14] GPIO46 interrupt. */ - __IOM uint32_t GPIO47 : 1; /*!< [15..15] GPIO47 interrupt. */ - __IOM uint32_t GPIO48 : 1; /*!< [16..16] GPIO48 interrupt. */ - __IOM uint32_t GPIO49 : 1; /*!< [17..17] GPIO49 interrupt. */ - } INT1SET_b; - } ; -} GPIO_Type; /*!< Size = 544 (0x220) */ - - - -/* =========================================================================================================================== */ -/* ================ IOM0 ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief IO Peripheral Master (IOM0) - */ - -typedef struct { /*!< (@ 0x50004000) IOM0 Structure */ - - union { - __IOM uint32_t FIFO; /*!< (@ 0x00000000) FIFO Access Port */ - - struct { - __IOM uint32_t FIFO : 32; /*!< [31..0] FIFO direct access. Only locations 0 - 3F will return - valid information. */ - } FIFO_b; - } ; - __IM uint32_t RESERVED[63]; - - union { - __IOM uint32_t FIFOPTR; /*!< (@ 0x00000100) FIFO size and remaining slots open values */ - - struct { - __IOM uint32_t FIFO0SIZ : 8; /*!< [7..0] The number of valid data bytes currently in the FIFO - 0 (written by MCU, read by interface) */ - __IOM uint32_t FIFO0REM : 8; /*!< [15..8] The number of remaining data bytes slots currently in - FIFO 0 (written by MCU, read by interface) */ - __IOM uint32_t FIFO1SIZ : 8; /*!< [23..16] The number of valid data bytes currently in FIFO 1 - (written by interface, read by MCU) */ - __IOM uint32_t FIFO1REM : 8; /*!< [31..24] The number of remaining data bytes slots currently - in FIFO 1 (written by interface, read by MCU) */ - } FIFOPTR_b; - } ; - - union { - __IOM uint32_t FIFOTHR; /*!< (@ 0x00000104) FIFO Threshold Configuration */ - - struct { - __IOM uint32_t FIFORTHR : 6; /*!< [5..0] FIFO read threshold in bytes. A value of 0 will disable - the read FIFO level from activating the threshold interrupt. - If this field is non-zero, it will trigger a threshold - interrupt when the read fifo contains FIFORTHR valid bytes - of data, as indicated by the FIFO1SIZ field. This is intended - to signal when a data transfer of FIFORTHR bytes can be - done from the IOM module to the host via the read fifo - to support large IOM read operations. */ - __IM uint32_t : 2; - __IOM uint32_t FIFOWTHR : 6; /*!< [13..8] FIFO write threshold in bytes. A value of 0 will disable - the write FIFO level from activating the threshold interrupt. - If this field is non-zero, it will trigger a threshold - interrupt when the write fifo contains FIFOWTHR free bytes, - as indicated by the FIFO0REM field. This is intended to - signal when a transfer of FIFOWTHR bytes can be done from - the host to the IOM write fifo to support large IOM write - operations. */ - } FIFOTHR_b; - } ; - - union { - __IOM uint32_t FIFOPOP; /*!< (@ 0x00000108) FIFO POP register */ - - struct { - __IOM uint32_t FIFODOUT : 32; /*!< [31..0] This register will return the read data indicated by - the current read pointer on reads. If the POPWR control - bit in the FIFOCTRL register is reset (0), the fifo read - pointer will be advanced by one word as a result of the - read.If the POPWR bit is set (1), the fifo read pointer - will only be advanced after a write operation to this register. - The write data is ignored for this register.If less than - a even word multiple is available, and the command is completed, - the module will return the word containing */ - } FIFOPOP_b; - } ; - - union { - __IOM uint32_t FIFOPUSH; /*!< (@ 0x0000010C) FIFO PUSH register */ - - struct { - __IOM uint32_t FIFODIN : 32; /*!< [31..0] This register is used to write the FIFORAM in FIFO mode - and will cause a push event to occur to the next open slot - within the FIFORAM. Writing to this register will cause - the write point to increment by 1 word(4 bytes). */ - } FIFOPUSH_b; - } ; - - union { - __IOM uint32_t FIFOCTRL; /*!< (@ 0x00000110) FIFO Control Register */ - - struct { - __IOM uint32_t POPWR : 1; /*!< [0..0] Selects the mode in which 'pop' events are done for the - fifo read operations. A value of '1' will prevent a pop - event on a read operation, and will require a write to - the FIFOPOP register to create a pop event.A value of '0' - in this register will allow a pop event to occur on the - read of the FIFOPOP register, and may cause inadvertant - fifo pops when used in a debugging mode. */ - __IOM uint32_t FIFORSTN : 1; /*!< [1..1] Active low manual reset of the fifo. Write to 0 to reset - fifo, and then write to 1 to remove the reset. */ - } FIFOCTRL_b; - } ; - - union { - __IOM uint32_t FIFOLOC; /*!< (@ 0x00000114) FIFO Pointers */ - - struct { - __IOM uint32_t FIFOWPTR : 4; /*!< [3..0] Current FIFO write pointer. Value is the index into the - outgoing FIFO (FIFO0), which is used during write operations - to external devices. */ - __IM uint32_t : 4; - __IOM uint32_t FIFORPTR : 4; /*!< [11..8] Current FIFO read pointer. Used to index into the incoming - FIFO (FIFO1), which is used to store read data returned - from external devices during a read operation. */ - } FIFOLOC_b; - } ; - __IM uint32_t RESERVED1[58]; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000200) IO Master Interrupts: Enable */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current - operation has completed. For repeated commands, this will - only be asserted when the final repeated command is completed. */ - __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted - when the number of free bytes in the write FIFO equals - or exceeds the WTHR field.For read operations, asserted - when the number of valid bytes in the read FIFO equals - of exceeds the value set in the RTHR field. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. This occurs when software - tries to pop from an empty fifo. */ - __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software - tries to write to a full fifo. The current operation does - not stop. */ - __IOM uint32_t NAK : 1; /*!< [4..4] I2C NAK interrupt. Asserted when an unexpected NAK has - been received on the I2C bus. */ - __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is - a overflow or underflow event */ - __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is - written when an active command is in progress. */ - __IOM uint32_t START : 1; /*!< [7..7] START command interrupt. Asserted when another master - on the bus has signaled a START command. */ - __IOM uint32_t STOP : 1; /*!< [8..8] STOP command interrupt. Asserted when another master - on the bus has signaled a STOP command. */ - __IOM uint32_t ARB : 1; /*!< [9..9] Arbitration loss interrupt. Asserted when arbitration - is enabled and has been lost to another master on the bus. */ - __IOM uint32_t DCMP : 1; /*!< [10..10] DMA Complete. Processing of the DMA operation has completed - and the DMA submodule is returned into the idle state */ - __IOM uint32_t DERR : 1; /*!< [11..11] DMA Error encountered during the processing of the - DMA command. The DMA error could occur when the memory - access specified in the DMA operation is not available - or incorrectly specified. */ - __IOM uint32_t CQPAUSED : 1; /*!< [12..12] Command queue is paused due to an active event enabled - in the PAUSEEN register. The interrupt is posted when the - event is enabled within the PAUSEEN register, the mask - is active in the CQIRQMASK field and the event occurs. */ - __IOM uint32_t CQUPD : 1; /*!< [13..13] CQ write operation performed a register write with - the register address bit 0 set to 1. The low address bits - in the CQ address fields are unused and bit 0 can be used - to trigger an interrupt to indicate when this register - write is performed by the CQ operation. */ - __IOM uint32_t CQERR : 1; /*!< [14..14] Error during command queue operations */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) IO Master Interrupts: Status */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current - operation has completed. For repeated commands, this will - only be asserted when the final repeated command is completed. */ - __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted - when the number of free bytes in the write FIFO equals - or exceeds the WTHR field.For read operations, asserted - when the number of valid bytes in the read FIFO equals - of exceeds the value set in the RTHR field. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. This occurs when software - tries to pop from an empty fifo. */ - __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software - tries to write to a full fifo. The current operation does - not stop. */ - __IOM uint32_t NAK : 1; /*!< [4..4] I2C NAK interrupt. Asserted when an unexpected NAK has - been received on the I2C bus. */ - __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is - a overflow or underflow event */ - __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is - written when an active command is in progress. */ - __IOM uint32_t START : 1; /*!< [7..7] START command interrupt. Asserted when another master - on the bus has signaled a START command. */ - __IOM uint32_t STOP : 1; /*!< [8..8] STOP command interrupt. Asserted when another master - on the bus has signaled a STOP command. */ - __IOM uint32_t ARB : 1; /*!< [9..9] Arbitration loss interrupt. Asserted when arbitration - is enabled and has been lost to another master on the bus. */ - __IOM uint32_t DCMP : 1; /*!< [10..10] DMA Complete. Processing of the DMA operation has completed - and the DMA submodule is returned into the idle state */ - __IOM uint32_t DERR : 1; /*!< [11..11] DMA Error encountered during the processing of the - DMA command. The DMA error could occur when the memory - access specified in the DMA operation is not available - or incorrectly specified. */ - __IOM uint32_t CQPAUSED : 1; /*!< [12..12] Command queue is paused due to an active event enabled - in the PAUSEEN register. The interrupt is posted when the - event is enabled within the PAUSEEN register, the mask - is active in the CQIRQMASK field and the event occurs. */ - __IOM uint32_t CQUPD : 1; /*!< [13..13] CQ write operation performed a register write with - the register address bit 0 set to 1. The low address bits - in the CQ address fields are unused and bit 0 can be used - to trigger an interrupt to indicate when this register - write is performed by the CQ operation. */ - __IOM uint32_t CQERR : 1; /*!< [14..14] Error during command queue operations */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000208) IO Master Interrupts: Clear */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current - operation has completed. For repeated commands, this will - only be asserted when the final repeated command is completed. */ - __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted - when the number of free bytes in the write FIFO equals - or exceeds the WTHR field.For read operations, asserted - when the number of valid bytes in the read FIFO equals - of exceeds the value set in the RTHR field. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. This occurs when software - tries to pop from an empty fifo. */ - __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software - tries to write to a full fifo. The current operation does - not stop. */ - __IOM uint32_t NAK : 1; /*!< [4..4] I2C NAK interrupt. Asserted when an unexpected NAK has - been received on the I2C bus. */ - __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is - a overflow or underflow event */ - __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is - written when an active command is in progress. */ - __IOM uint32_t START : 1; /*!< [7..7] START command interrupt. Asserted when another master - on the bus has signaled a START command. */ - __IOM uint32_t STOP : 1; /*!< [8..8] STOP command interrupt. Asserted when another master - on the bus has signaled a STOP command. */ - __IOM uint32_t ARB : 1; /*!< [9..9] Arbitration loss interrupt. Asserted when arbitration - is enabled and has been lost to another master on the bus. */ - __IOM uint32_t DCMP : 1; /*!< [10..10] DMA Complete. Processing of the DMA operation has completed - and the DMA submodule is returned into the idle state */ - __IOM uint32_t DERR : 1; /*!< [11..11] DMA Error encountered during the processing of the - DMA command. The DMA error could occur when the memory - access specified in the DMA operation is not available - or incorrectly specified. */ - __IOM uint32_t CQPAUSED : 1; /*!< [12..12] Command queue is paused due to an active event enabled - in the PAUSEEN register. The interrupt is posted when the - event is enabled within the PAUSEEN register, the mask - is active in the CQIRQMASK field and the event occurs. */ - __IOM uint32_t CQUPD : 1; /*!< [13..13] CQ write operation performed a register write with - the register address bit 0 set to 1. The low address bits - in the CQ address fields are unused and bit 0 can be used - to trigger an interrupt to indicate when this register - write is performed by the CQ operation. */ - __IOM uint32_t CQERR : 1; /*!< [14..14] Error during command queue operations */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000020C) IO Master Interrupts: Set */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Command Complete interrupt. Asserted when the current - operation has completed. For repeated commands, this will - only be asserted when the final repeated command is completed. */ - __IOM uint32_t THR : 1; /*!< [1..1] FIFO Threshold interrupt. For write operations, asserted - when the number of free bytes in the write FIFO equals - or exceeds the WTHR field.For read operations, asserted - when the number of valid bytes in the read FIFO equals - of exceeds the value set in the RTHR field. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] Read FIFO Underflow interrupt. This occurs when software - tries to pop from an empty fifo. */ - __IOM uint32_t FOVFL : 1; /*!< [3..3] Write FIFO Overflow interrupt. This occurs when software - tries to write to a full fifo. The current operation does - not stop. */ - __IOM uint32_t NAK : 1; /*!< [4..4] I2C NAK interrupt. Asserted when an unexpected NAK has - been received on the I2C bus. */ - __IOM uint32_t IACC : 1; /*!< [5..5] illegal FIFO access interrupt. Asserted when there is - a overflow or underflow event */ - __IOM uint32_t ICMD : 1; /*!< [6..6] illegal command interrupt. Asserted when a command is - written when an active command is in progress. */ - __IOM uint32_t START : 1; /*!< [7..7] START command interrupt. Asserted when another master - on the bus has signaled a START command. */ - __IOM uint32_t STOP : 1; /*!< [8..8] STOP command interrupt. Asserted when another master - on the bus has signaled a STOP command. */ - __IOM uint32_t ARB : 1; /*!< [9..9] Arbitration loss interrupt. Asserted when arbitration - is enabled and has been lost to another master on the bus. */ - __IOM uint32_t DCMP : 1; /*!< [10..10] DMA Complete. Processing of the DMA operation has completed - and the DMA submodule is returned into the idle state */ - __IOM uint32_t DERR : 1; /*!< [11..11] DMA Error encountered during the processing of the - DMA command. The DMA error could occur when the memory - access specified in the DMA operation is not available - or incorrectly specified. */ - __IOM uint32_t CQPAUSED : 1; /*!< [12..12] Command queue is paused due to an active event enabled - in the PAUSEEN register. The interrupt is posted when the - event is enabled within the PAUSEEN register, the mask - is active in the CQIRQMASK field and the event occurs. */ - __IOM uint32_t CQUPD : 1; /*!< [13..13] CQ write operation performed a register write with - the register address bit 0 set to 1. The low address bits - in the CQ address fields are unused and bit 0 can be used - to trigger an interrupt to indicate when this register - write is performed by the CQ operation. */ - __IOM uint32_t CQERR : 1; /*!< [14..14] Error during command queue operations */ - } INTSET_b; - } ; - - union { - __IOM uint32_t CLKCFG; /*!< (@ 0x00000210) I/O Clock Configuration */ - - struct { - __IOM uint32_t IOCLKEN : 1; /*!< [0..0] Enable for the interface clock. Must be enabled prior - to executing any IO operations. */ - __IM uint32_t : 7; - __IOM uint32_t FSEL : 3; /*!< [10..8] Select the input clock frequency. */ - __IOM uint32_t DIV3 : 1; /*!< [11..11] Enable divide by 3 of the source IOCLK. Division by - 3 is done before the DIVEN programmable divider, and if - enabledwill provide the divided by 3 clock as the source - to the programmable divider. */ - __IOM uint32_t DIVEN : 1; /*!< [12..12] Enable clock division by TOTPER and LOWPER */ - __IM uint32_t : 3; - __IOM uint32_t LOWPER : 8; /*!< [23..16] Clock low clock count minus 1. This provides the number - of clocks the divided clock will be low when the DIVEN - = 1.Only applicable when DIVEN = 1. */ - __IOM uint32_t TOTPER : 8; /*!< [31..24] Clock total clock count minus 1. This provides the - total period of the divided clock -1 when the DIVEN is - active. Thesource clock is selected by FSEL. Only applicable - when DIVEN = 1. */ - } CLKCFG_b; - } ; - - union { - __IOM uint32_t SUBMODCTRL; /*!< (@ 0x00000214) Submodule control */ - - struct { - __IOM uint32_t SMOD0EN : 1; /*!< [0..0] Submodule 0 enable (1) or disable (0) */ - __IOM uint32_t SMOD0TYPE : 3; /*!< [3..1] Submodule 0 module type. This is the SPI Master interface. */ - __IOM uint32_t SMOD1EN : 1; /*!< [4..4] Submodule 1 enable (1) or disable (0) */ - __IOM uint32_t SMOD1TYPE : 3; /*!< [7..5] Submodule 0 module type. This is the I2C Master interface */ - } SUBMODCTRL_b; - } ; - - union { - __IOM uint32_t CMD; /*!< (@ 0x00000218) Command and offset Register */ - - struct { - __IOM uint32_t CMD : 5; /*!< [4..0] Command for submodule. */ - __IOM uint32_t OFFSETCNT : 2; /*!< [6..5] Number of offset bytes to use for the command - 0, 1, - 2, 3 are valid selections. The second (byte 1) and third - byte (byte 2) are read from the OFFSETHI register, and - the low order byte is pulled from this register in the - OFFSETLO field.Offset bytes are transmitted highest byte - first. EG if offsetcnt == 3, OFFSETHI[15:8] will be transmitted - first, then OFFSETHI[7:0] then OFFSETLO.If offsetcnt == - 2, OFFSETHI[7:0] will be transmitted, then OFFSETLO.If - offsetcnt == 1, only OFFSETLO will be transmitted. */ - __IOM uint32_t CONT : 1; /*!< [7..7] Contine to hold the bus after the current transaction - if set to a 1 with a new command issued. */ - __IOM uint32_t TSIZE : 12; /*!< [19..8] Defines the transaction size in bytes. The offset transfer - is not included in this size. */ - __IOM uint32_t CMDSEL : 2; /*!< [21..20] Command Specific selection information. Not used in - Master I2C. Used as CEn select for Master SPI transactions */ - __IM uint32_t : 2; - __IOM uint32_t OFFSETLO : 8; /*!< [31..24] This register holds the low order byte of offset to - be used in the transaction. The number of offset bytes - to use is set with bits 1:0 of the command. */ - } CMD_b; - } ; - - union { - __IOM uint32_t CMDRPT; /*!< (@ 0x0000021C) Command Repeat Register */ - - struct { - __IOM uint32_t CMDRPT : 5; /*!< [4..0] Count of number of times to repeat the next command. */ - } CMDRPT_b; - } ; - - union { - __IOM uint32_t OFFSETHI; /*!< (@ 0x00000220) High order 2 bytes of 3 byte offset for IO transaction */ - - struct { - __IOM uint32_t OFFSETHI : 16; /*!< [15..0] Holds the high order 2 bytes of the 3 byte addressing/offset - field to use with IO commands. The number of offset bytes - to use is specified in the command register */ - } OFFSETHI_b; - } ; - - union { - __IOM uint32_t CMDSTAT; /*!< (@ 0x00000224) Command status */ - - struct { - __IOM uint32_t CCMD : 5; /*!< [4..0] current command that is being executed */ - __IOM uint32_t CMDSTAT : 3; /*!< [7..5] The current status of the command execution. */ - __IOM uint32_t CTSIZE : 12; /*!< [19..8] The current number of bytes still to be transferred - with this command. This field will count down to zero. */ - } CMDSTAT_b; - } ; - __IM uint32_t RESERVED2[6]; - - union { - __IOM uint32_t DMATRIGEN; /*!< (@ 0x00000240) DMA Trigger Enable Register */ - - struct { - __IOM uint32_t DCMDCMPEN : 1; /*!< [0..0] Trigger DMA upon command complete. Enables the trigger - of the DMA when a command is completed. When this event - is triggered, the number of words transferred will be the - lesser of the remaining TOTCOUNT bytes, or */ - __IOM uint32_t DTHREN : 1; /*!< [1..1] Trigger DMA upon THR level reached. For M2P DMA operations - (IOM writes), the trigger will assert when the write FIFO - has (WTHR/4) number of words free in the write FIFO, and - will transfer (WTHR/4) number of wordsor, if the number - of words left to transfer is less than the WTHR value, - will transfer the remaining byte count.For P2M DMA operations, - the trigger will assert when the read FIFO has (RTHR/4) - words available in the read FIFO, and will transfer (RTHR/4) - words to SRAM. This trigger will NOT asser */ - } DMATRIGEN_b; - } ; - - union { - __IOM uint32_t DMATRIGSTAT; /*!< (@ 0x00000244) DMA Trigger Status Register */ - - struct { - __IOM uint32_t DCMDCMP : 1; /*!< [0..0] Triggered DMA from Command complete event. Bit is read - only and can be cleared by disabling the DCMDCMP trigger - enable or by disabling DMA. */ - __IOM uint32_t DTHR : 1; /*!< [1..1] Triggered DMA from THR event. Bit is read only and can - be cleared by disabling the DTHR trigger enable or by disabling - DMA. */ - __IOM uint32_t DTOTCMP : 1; /*!< [2..2] DMA triggered when DCMDCMP = 0, and the amount of data - in the FIFO was enough to complete the DMA operation (greater - than or equal to current TOTCOUNT) when the command completed. - This trigger is default active when the DCMDCMP trigger - isdisabled and there is enough data in the FIFO to complete - the DMA operation. */ - } DMATRIGSTAT_b; - } ; - __IM uint32_t RESERVED3[14]; - - union { - __IOM uint32_t DMACFG; /*!< (@ 0x00000280) DMA Configuration Register */ - - struct { - __IOM uint32_t DMAEN : 1; /*!< [0..0] DMA Enable. Setting this bit to EN will start the DMA - operation. This should be the last DMA related register - set prior to issuing the command */ - __IOM uint32_t DMADIR : 1; /*!< [1..1] Direction */ - __IM uint32_t : 6; - __IOM uint32_t DMAPRI : 1; /*!< [8..8] Sets the Priority of the DMA request */ - __IOM uint32_t DPWROFF : 1; /*!< [9..9] Power off module after DMA is complete. If this bit is - active, the module will request to power off the supply - it is attached to. If there are other units still requiring - power from the same domain, power down will not be performed. */ - } DMACFG_b; - } ; - __IM uint32_t RESERVED4; - - union { - __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x00000288) DMA Total Transfer Count */ - - struct { - __IOM uint32_t TOTCOUNT : 12; /*!< [11..0] Triggered DMA from Command complete event occured. Bit - is read only and can be cleared by disabling the DTHR trigger - enable or by disabling DMA. */ - } DMATOTCOUNT_b; - } ; - - union { - __IOM uint32_t DMATARGADDR; /*!< (@ 0x0000028C) DMA Target Address Register */ - - struct { - __IOM uint32_t TARGADDR : 20; /*!< [19..0] Bits [19:0] of the target byte address for source of - DMA (either read or write). The address can be any byte - alignment, and does not have to be word aligned. In cases - of non-word aligned addresses, the DMA logic will take - care for ensuring only the target bytes are read/written. */ - __IM uint32_t : 8; - __IOM uint32_t TARGADDR28 : 1; /*!< [28..28] Bit 28 of the target byte address for source of DMA - (either read or write). In cases of non-word aligned addresses, - the DMA logic will take care for ensuring only the target - bytes are read/written.Setting to '1' will select the SRAM. - Setting to '0' will select the flash */ - } DMATARGADDR_b; - } ; - - union { - __IOM uint32_t DMASTAT; /*!< (@ 0x00000290) DMA Status Register */ - - struct { - __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress indicator. 1 will indicate that - a DMA transfer is active. The DMA transfer may be waiting - on data, transferring data, or waiting for priority.All - of these will be indicated with a 1. A 0 will indicate - that the DMA is fully complete and no further transactions - will be done. This bit is read only. */ - __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete. This signals the end of the DMA - operation. This bit can be cleared by writing to 0, and - will also be cleared when a new DMA is started. */ - __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error. This active high bit signals an error was - encountered during the DMA operation. The bit can be cleared - by writing to 0. Once set, this bit will remain set until - cleared by software. */ - } DMASTAT_b; - } ; - - union { - __IOM uint32_t CQCFG; /*!< (@ 0x00000294) Command Queue Configuration Register */ - - struct { - __IOM uint32_t CQEN : 1; /*!< [0..0] Command queue enable. When set, will enable the processing - of the command queue and fetches of address/data pairs - will proceed from the word address within the CQADDR register. - Can be disabledusing a CQ executed write to this bit as - well. */ - __IOM uint32_t CQPRI : 1; /*!< [1..1] Sets the Priority of the command queue dma request */ - } CQCFG_b; - } ; - - union { - __IOM uint32_t CQADDR; /*!< (@ 0x00000298) CQ Target Read Address Register */ - - struct { - __IM uint32_t : 2; - __IOM uint32_t CQADDR : 18; /*!< [19..2] Bits 19:2 of target byte address for source of CQ (read - only). The buffer must be aligned on a word boundary */ - __IM uint32_t : 8; - __IOM uint32_t CQADDR28 : 1; /*!< [28..28] Bit 28 of target byte address for source of CQ (read - only). Used to denote Flash (0) or SRAM (1) access */ - } CQADDR_b; - } ; - - union { - __IOM uint32_t CQSTAT; /*!< (@ 0x0000029C) Command Queue Status Register */ - - struct { - __IOM uint32_t CQTIP : 1; /*!< [0..0] Command queue Transfer In Progress indicator. 1 will - indicate that a CQ transfer is active and this will remain - active even when paused waiting for external event. */ - __IOM uint32_t CQPAUSED : 1; /*!< [1..1] Command queue operation is currently paused. */ - __IOM uint32_t CQERR : 1; /*!< [2..2] Command queue processing Error. This active high bit - signals that an error was encountered during the CQ operation. */ - } CQSTAT_b; - } ; - - union { - __IOM uint32_t CQFLAGS; /*!< (@ 0x000002A0) Command Queue Flag Register */ - - struct { - __IOM uint32_t CQFLAGS : 16; /*!< [15..0] Current flag status (read-only). Bits [7:0] are software - controllable and bits [15:8] are hardware status. */ - __IOM uint32_t CQIRQMASK : 16; /*!< [31..16] Mask the bits used to generate the command queue interrupt. - A '1' in the bit position will enable the pause event to - trigger the interrupt, if the CQWT_int interrupt is enabled. - Bits definitions are the same as CQPAUSE */ - } CQFLAGS_b; - } ; - - union { - __IOM uint32_t CQSETCLEAR; /*!< (@ 0x000002A4) Command Queue Flag Set/Clear Register */ - - struct { - __IOM uint32_t CQFSET : 8; /*!< [7..0] Set CQFlag status bits. Will set to 1 the value of any - SWFLAG with a '1' in the corresponding bit position of - this field */ - __IOM uint32_t CQFTGL : 8; /*!< [15..8] Toggle the indicated bit. Will toggle the value of any - SWFLAG with a '1' in the corresponding bit position of - this field */ - __IOM uint32_t CQFCLR : 8; /*!< [23..16] Clear CQFlag status bits. Will clear to 0 any SWFLAG - with a '1' in the corresponding bit position of this field */ - } CQSETCLEAR_b; - } ; - - union { - __IOM uint32_t CQPAUSEEN; /*!< (@ 0x000002A8) Command Queue Pause Enable Register */ - - struct { - __IOM uint32_t CQPEN : 16; /*!< [15..0] Enables the specified event to pause command processing - when active */ - } CQPAUSEEN_b; - } ; - - union { - __IOM uint32_t CQCURIDX; /*!< (@ 0x000002AC) IOM Command Queue current index value . Compared - to the CQENDIDX reg contents to generate - the IDXEQ Pause event for command queue */ - - struct { - __IOM uint32_t CQCURIDX : 8; /*!< [7..0] Holds 8 bits of data that will be compared with the CQENDIX - register field. If the values match, the IDXEQ pause event - will be activated, which will cause the pausing of command - quue operation if the IDXEQ bit is enabled in CQPAUSEEN. */ - } CQCURIDX_b; - } ; - - union { - __IOM uint32_t CQENDIDX; /*!< (@ 0x000002B0) IOM Command Queue current index value . Compared - to the CQCURIDX reg contents to generate - the IDXEQ Pause event for command queue */ - - struct { - __IOM uint32_t CQENDIDX : 8; /*!< [7..0] Holds 8 bits of data that will be compared with the CQCURIX - register field. If the values match, the IDXEQ pause event - will be activated, which will cause the pausing of command - quue operation if the IDXEQ bit is enabled in CQPAUSEEN. */ - } CQENDIDX_b; - } ; - - union { - __IOM uint32_t STATUS; /*!< (@ 0x000002B4) IOM Module Status Register */ - - struct { - __IOM uint32_t ERR : 1; /*!< [0..0] Bit has been deprecated. Please refer to the other error - indicators. This will always return 0. */ - __IOM uint32_t CMDACT : 1; /*!< [1..1] Indicates if the active I/O Command is currently processing - a transaction, or command is complete, but the FIFO pointers - are still syncronizing internally. This bit will go high - atthe start of the transaction, and will go low when the - command is complete, and the data and pointers within the - FIFO have been syncronized. */ - __IOM uint32_t IDLEST : 1; /*!< [2..2] indicates if the active I/O state machine is IDLE. Note - - The state machine could be in idle state due to holdoffs - from data availability, or as the command gets propagated - into the logic from the registers. */ - } STATUS_b; - } ; - __IM uint32_t RESERVED5[18]; - - union { - __IOM uint32_t MSPICFG; /*!< (@ 0x00000300) SPI module master configuration */ - - struct { - __IOM uint32_t SPOL : 1; /*!< [0..0] selects SPI polarity. */ - __IOM uint32_t SPHA : 1; /*!< [1..1] selects SPI phase. */ - __IOM uint32_t FULLDUP : 1; /*!< [2..2] Enables full duplex mode for Master SPI write operations. - Data will be captured simultaneously into the read fifo */ - __IM uint32_t : 13; - __IOM uint32_t WTFC : 1; /*!< [16..16] enables write mode flow control. */ - __IOM uint32_t RDFC : 1; /*!< [17..17] enables read mode flow control. */ - __IOM uint32_t MOSIINV : 1; /*!< [18..18] inverts MOSI when flow control is enabled. */ - __IM uint32_t : 1; - __IOM uint32_t WTFCIRQ : 1; /*!< [20..20] selects the write mode flow control signal. */ - __IOM uint32_t WTFCPOL : 1; /*!< [21..21] selects the write flow control signal polarity. The - transfers are halted when the selected flow control signal - is OPPOSITE polarity of bit. (For example: WTFCPOL = 0 - will allow a IRQ=1 to pause transfers). */ - __IOM uint32_t RDFCPOL : 1; /*!< [22..22] selects the read flow control signal polarity. */ - __IOM uint32_t SPILSB : 1; /*!< [23..23] Selects data transfer as MSB first (0) or LSB first - (1) for the data portion of the SPI transaction. The offset - bytes are always transmitted MSB first. */ - __IOM uint32_t DINDLY : 3; /*!< [26..24] Delay tap to use for the input signal (MISO). This - gives more hold time on the input data. */ - __IOM uint32_t DOUTDLY : 3; /*!< [29..27] Delay tap to use for the output signal (MOSI). This - give more hold time on the output data */ - __IOM uint32_t MSPIRST : 1; /*!< [30..30] Not used. To reset the module, toggle the SMOD_EN for - the module */ - } MSPICFG_b; - } ; - __IM uint32_t RESERVED6[63]; - - union { - __IOM uint32_t MI2CCFG; /*!< (@ 0x00000400) I2C Master configuration */ - - struct { - __IOM uint32_t ADDRSZ : 1; /*!< [0..0] Sets the I2C master device address size to either 7b - (0) or 10b (1). */ - __IOM uint32_t I2CLSB : 1; /*!< [1..1] Direction of data transmit and receive, MSB(0) or LSB(1) - first. Default per I2C specification is MSB first. This - applies to both read and write data, and read data will - be bit */ - __IOM uint32_t ARBEN : 1; /*!< [2..2] Enables multi-master arbitration for the I2C master. - If the bus is known to have only a single master, this - function can be disabled to save clock cycles on I2C transactions */ - __IM uint32_t : 1; - __IOM uint32_t SDADLY : 2; /*!< [5..4] Delay to enable on the SDA output. Values are 0x0-0x3. */ - __IOM uint32_t MI2CRST : 1; /*!< [6..6] Not used. To reset the module, toggle the SMOD_EN for - the module */ - __IM uint32_t : 1; - __IOM uint32_t SCLENDLY : 4; /*!< [11..8] Number of IOCLK cycles to delay the rising edge of the - SCL output en (clock will go low on this edge). Used to - allow clock shaping. */ - __IOM uint32_t SDAENDLY : 4; /*!< [15..12] Number of IOCLK cycles to delay the SDA output en (all - transitions affected). Used to delay data relative to clock */ - __IOM uint32_t SMPCNT : 8; /*!< [23..16] Number of Base clk cycles to wait before sampling the - SCL clock to determine if a clock stretch event has occured */ - __IOM uint32_t STRDIS : 1; /*!< [24..24] Disable detection of clock stretch events smaller than - 1 cycle */ - } MI2CCFG_b; - } ; - - union { - __IOM uint32_t DEVCFG; /*!< (@ 0x00000404) I2C Device Configuration register */ - - struct { - __IOM uint32_t DEVADDR : 10; /*!< [9..0] I2C address of the device that the Master will use to - target for read/write operations. This can be either a - 7b or 10b address. */ - } DEVCFG_b; - } ; - __IM uint32_t RESERVED7[2]; - - union { - __IOM uint32_t IOMDBG; /*!< (@ 0x00000410) IOM Debug Register */ - - struct { - __IOM uint32_t DBGEN : 1; /*!< [0..0] Debug Enable. Setting bit will enable the update of data - within this register, otherwise it is clock gated for power - savings */ - __IOM uint32_t IOCLKON : 1; /*!< [1..1] IOCLK debug clock control. Enable IO_CLK to be active - when this bit is '1'. Otherwise, the clock is controlled - with gating from the logic as needed. */ - __IOM uint32_t APBCLKON : 1; /*!< [2..2] APBCLK debug clock control. Enable APB_CLK to be active - when this bit is '1'. Otherwise, the clock is controlled - with gating from the logic as needed. */ - __IOM uint32_t DBGDATA : 29; /*!< [31..3] Debug control for various options. DBGDATA[1:0] is used - to select between different debug data available in the - DBG0 and DBG1 registers. */ - } IOMDBG_b; - } ; -} IOM0_Type; /*!< Size = 1044 (0x414) */ - - - -/* =========================================================================================================================== */ -/* ================ IOSLAVE ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief I2C/SPI Slave (IOSLAVE) - */ - -typedef struct { /*!< (@ 0x50000000) IOSLAVE Structure */ - __IM uint32_t RESERVED[64]; - - union { - __IOM uint32_t FIFOPTR; /*!< (@ 0x00000100) Current FIFO Pointer */ - - struct { - __IOM uint32_t FIFOPTR : 8; /*!< [7..0] Current FIFO pointer. */ - __IOM uint32_t FIFOSIZ : 8; /*!< [15..8] The number of bytes currently in the hardware FIFO. */ - } FIFOPTR_b; - } ; - - union { - __IOM uint32_t FIFOCFG; /*!< (@ 0x00000104) FIFO Configuration */ - - struct { - __IOM uint32_t FIFOBASE : 5; /*!< [4..0] These bits hold the base address of the I/O FIFO in 8 - byte segments. The IO Slave FIFO is situated in LRAM at - (FIFOBASE*8) to (FIFOMAX*8-1). */ - __IM uint32_t : 3; - __IOM uint32_t FIFOMAX : 6; /*!< [13..8] These bits hold the maximum FIFO address in 8 byte segments. - It is also the beginning of the RAM area of the LRAM. Note - that no RAM area is configured if FIFOMAX is set to 0x1F. */ - __IM uint32_t : 10; - __IOM uint32_t ROBASE : 6; /*!< [29..24] Defines the read-only area. The IO Slave read-only - area is situated in LRAM at (ROBASE*8) to (FIFOBASE*8-1) */ - } FIFOCFG_b; - } ; - - union { - __IOM uint32_t FIFOTHR; /*!< (@ 0x00000108) FIFO Threshold Configuration */ - - struct { - __IOM uint32_t FIFOTHR : 8; /*!< [7..0] FIFO size interrupt threshold. */ - } FIFOTHR_b; - } ; - - union { - __IOM uint32_t FUPD; /*!< (@ 0x0000010C) FIFO Update Status */ - - struct { - __IOM uint32_t FIFOUPD : 1; /*!< [0..0] This bit indicates that a FIFO update is underway. */ - __IOM uint32_t IOREAD : 1; /*!< [1..1] This bitfield indicates an IO read is active. */ - } FUPD_b; - } ; - - union { - __IOM uint32_t FIFOCTR; /*!< (@ 0x00000110) Overall FIFO Counter */ - - struct { - __IOM uint32_t FIFOCTR : 10; /*!< [9..0] Virtual FIFO byte count */ - } FIFOCTR_b; - } ; - - union { - __IOM uint32_t FIFOINC; /*!< (@ 0x00000114) Overall FIFO Counter Increment */ - - struct { - __IOM uint32_t FIFOINC : 10; /*!< [9..0] Increment the Overall FIFO Counter by this value on a - write */ - } FIFOINC_b; - } ; - - union { - __IOM uint32_t CFG; /*!< (@ 0x00000118) I/O Slave Configuration */ - - struct { - __IOM uint32_t IFCSEL : 1; /*!< [0..0] This bit selects the I/O interface. */ - __IOM uint32_t SPOL : 1; /*!< [1..1] This bit selects SPI polarity. */ - __IOM uint32_t LSB : 1; /*!< [2..2] This bit selects the transfer bit ordering. */ - __IM uint32_t : 1; - __IOM uint32_t STARTRD : 1; /*!< [4..4] This bit holds the cycle to initiate an I/O RAM read. */ - __IM uint32_t : 3; - __IOM uint32_t I2CADDR : 12; /*!< [19..8] 7-bit or 10-bit I2C device address. */ - __IM uint32_t : 11; - __IOM uint32_t IFCEN : 1; /*!< [31..31] IOSLAVE interface enable. */ - } CFG_b; - } ; - - union { - __IOM uint32_t PRENC; /*!< (@ 0x0000011C) I/O Slave Interrupt Priority Encode */ - - struct { - __IOM uint32_t PRENC : 5; /*!< [4..0] These bits hold the priority encode of the REGACC interrupts. */ - } PRENC_b; - } ; - - union { - __IOM uint32_t IOINTCTL; /*!< (@ 0x00000120) I/O Interrupt Control */ - - struct { - __IOM uint32_t IOINTEN : 8; /*!< [7..0] These read-only bits indicate whether the IOINT interrupts - are enabled. */ - __IOM uint32_t IOINT : 8; /*!< [15..8] These bits read the IOINT interrupts. */ - __IOM uint32_t IOINTCLR : 1; /*!< [16..16] This bit clears all of the IOINT interrupts when written - with a 1. */ - __IM uint32_t : 7; - __IOM uint32_t IOINTSET : 8; /*!< [31..24] These bits set the IOINT interrupts when written with - a 1. */ - } IOINTCTL_b; - } ; - - union { - __IOM uint32_t GENADD; /*!< (@ 0x00000124) General Address Data */ - - struct { - __IOM uint32_t GADATA : 8; /*!< [7..0] The data supplied on the last General Address reference. */ - } GENADD_b; - } ; - __IM uint32_t RESERVED1[54]; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000200) IO Slave Interrupts: Enable */ - - struct { - __IOM uint32_t FSIZE : 1; /*!< [0..0] FIFO Size interrupt. */ - __IOM uint32_t FOVFL : 1; /*!< [1..1] FIFO Overflow interrupt. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] FIFO Underflow interrupt. */ - __IOM uint32_t FRDERR : 1; /*!< [3..3] FIFO Read Error interrupt. */ - __IOM uint32_t GENAD : 1; /*!< [4..4] I2C General Address interrupt. */ - __IOM uint32_t IOINTW : 1; /*!< [5..5] IO Write interrupt. */ - __IOM uint32_t XCMPRF : 1; /*!< [6..6] Transfer complete interrupt, read from FIFO space. */ - __IOM uint32_t XCMPRR : 1; /*!< [7..7] Transfer complete interrupt, read from register space. */ - __IOM uint32_t XCMPWF : 1; /*!< [8..8] Transfer complete interrupt, write to FIFO space. */ - __IOM uint32_t XCMPWR : 1; /*!< [9..9] Transfer complete interrupt, write to register space. */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) IO Slave Interrupts: Status */ - - struct { - __IOM uint32_t FSIZE : 1; /*!< [0..0] FIFO Size interrupt. */ - __IOM uint32_t FOVFL : 1; /*!< [1..1] FIFO Overflow interrupt. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] FIFO Underflow interrupt. */ - __IOM uint32_t FRDERR : 1; /*!< [3..3] FIFO Read Error interrupt. */ - __IOM uint32_t GENAD : 1; /*!< [4..4] I2C General Address interrupt. */ - __IOM uint32_t IOINTW : 1; /*!< [5..5] IO Write interrupt. */ - __IOM uint32_t XCMPRF : 1; /*!< [6..6] Transfer complete interrupt, read from FIFO space. */ - __IOM uint32_t XCMPRR : 1; /*!< [7..7] Transfer complete interrupt, read from register space. */ - __IOM uint32_t XCMPWF : 1; /*!< [8..8] Transfer complete interrupt, write to FIFO space. */ - __IOM uint32_t XCMPWR : 1; /*!< [9..9] Transfer complete interrupt, write to register space. */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000208) IO Slave Interrupts: Clear */ - - struct { - __IOM uint32_t FSIZE : 1; /*!< [0..0] FIFO Size interrupt. */ - __IOM uint32_t FOVFL : 1; /*!< [1..1] FIFO Overflow interrupt. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] FIFO Underflow interrupt. */ - __IOM uint32_t FRDERR : 1; /*!< [3..3] FIFO Read Error interrupt. */ - __IOM uint32_t GENAD : 1; /*!< [4..4] I2C General Address interrupt. */ - __IOM uint32_t IOINTW : 1; /*!< [5..5] IO Write interrupt. */ - __IOM uint32_t XCMPRF : 1; /*!< [6..6] Transfer complete interrupt, read from FIFO space. */ - __IOM uint32_t XCMPRR : 1; /*!< [7..7] Transfer complete interrupt, read from register space. */ - __IOM uint32_t XCMPWF : 1; /*!< [8..8] Transfer complete interrupt, write to FIFO space. */ - __IOM uint32_t XCMPWR : 1; /*!< [9..9] Transfer complete interrupt, write to register space. */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000020C) IO Slave Interrupts: Set */ - - struct { - __IOM uint32_t FSIZE : 1; /*!< [0..0] FIFO Size interrupt. */ - __IOM uint32_t FOVFL : 1; /*!< [1..1] FIFO Overflow interrupt. */ - __IOM uint32_t FUNDFL : 1; /*!< [2..2] FIFO Underflow interrupt. */ - __IOM uint32_t FRDERR : 1; /*!< [3..3] FIFO Read Error interrupt. */ - __IOM uint32_t GENAD : 1; /*!< [4..4] I2C General Address interrupt. */ - __IOM uint32_t IOINTW : 1; /*!< [5..5] IO Write interrupt. */ - __IOM uint32_t XCMPRF : 1; /*!< [6..6] Transfer complete interrupt, read from FIFO space. */ - __IOM uint32_t XCMPRR : 1; /*!< [7..7] Transfer complete interrupt, read from register space. */ - __IOM uint32_t XCMPWF : 1; /*!< [8..8] Transfer complete interrupt, write to FIFO space. */ - __IOM uint32_t XCMPWR : 1; /*!< [9..9] Transfer complete interrupt, write to register space. */ - } INTSET_b; - } ; - - union { - __IOM uint32_t REGACCINTEN; /*!< (@ 0x00000210) Register Access Interrupts: Enable */ - - struct { - __IOM uint32_t REGACC : 32; /*!< [31..0] Register access interrupts. */ - } REGACCINTEN_b; - } ; - - union { - __IOM uint32_t REGACCINTSTAT; /*!< (@ 0x00000214) Register Access Interrupts: Status */ - - struct { - __IOM uint32_t REGACC : 32; /*!< [31..0] Register access interrupts. */ - } REGACCINTSTAT_b; - } ; - - union { - __IOM uint32_t REGACCINTCLR; /*!< (@ 0x00000218) Register Access Interrupts: Clear */ - - struct { - __IOM uint32_t REGACC : 32; /*!< [31..0] Register access interrupts. */ - } REGACCINTCLR_b; - } ; - - union { - __IOM uint32_t REGACCINTSET; /*!< (@ 0x0000021C) Register Access Interrupts: Set */ - - struct { - __IOM uint32_t REGACC : 32; /*!< [31..0] Register access interrupts. */ - } REGACCINTSET_b; - } ; -} IOSLAVE_Type; /*!< Size = 544 (0x220) */ - - - -/* =========================================================================================================================== */ -/* ================ MCUCTRL ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief MCU Miscellaneous Control Logic (MCUCTRL) - */ - -typedef struct { /*!< (@ 0x40020000) MCUCTRL Structure */ - - union { - __IOM uint32_t CHIPPN; /*!< (@ 0x00000000) Chip Information Register */ - - struct { - __IOM uint32_t PARTNUM : 32; /*!< [31..0] BCD part number. */ - } CHIPPN_b; - } ; - - union { - __IOM uint32_t CHIPID0; /*!< (@ 0x00000004) Unique Chip ID 0 */ - - struct { - __IOM uint32_t CHIPID0 : 32; /*!< [31..0] Unique chip ID 0. */ - } CHIPID0_b; - } ; - - union { - __IOM uint32_t CHIPID1; /*!< (@ 0x00000008) Unique Chip ID 1 */ - - struct { - __IOM uint32_t CHIPID1 : 32; /*!< [31..0] Unique chip ID 1. */ - } CHIPID1_b; - } ; - - union { - __IOM uint32_t CHIPREV; /*!< (@ 0x0000000C) Chip Revision */ - - struct { - __IOM uint32_t REVMIN : 4; /*!< [3..0] Minor Revision ID. */ - __IOM uint32_t REVMAJ : 4; /*!< [7..4] Major Revision ID. */ - __IOM uint32_t SIPART : 12; /*!< [19..8] Silicon Part ID */ - } CHIPREV_b; - } ; - - union { - __IOM uint32_t VENDORID; /*!< (@ 0x00000010) Unique Vendor ID */ - - struct { - __IOM uint32_t VENDORID : 32; /*!< [31..0] Unique Vendor ID */ - } VENDORID_b; - } ; - - union { - __IOM uint32_t SKU; /*!< (@ 0x00000014) Unique Chip SKU */ - - struct { - __IOM uint32_t ALLOWBURST : 1; /*!< [0..0] Allow Burst feature */ - __IOM uint32_t ALLOWBLE : 1; /*!< [1..1] Allow BLE feature */ - __IOM uint32_t SECBOOT : 1; /*!< [2..2] Secure boot feature allowed */ - } SKU_b; - } ; - - union { - __IOM uint32_t FEATUREENABLE; /*!< (@ 0x00000018) Feature Enable on Burst and BLE */ - - struct { - __IOM uint32_t BLEREQ : 1; /*!< [0..0] Controls the BLE functionality */ - __IOM uint32_t BLEACK : 1; /*!< [1..1] ACK for BLEREQ */ - __IOM uint32_t BLEAVAIL : 1; /*!< [2..2] AVAILABILITY of the BLE functionality */ - __IM uint32_t : 1; - __IOM uint32_t BURSTREQ : 1; /*!< [4..4] Controls the Burst functionality */ - __IOM uint32_t BURSTACK : 1; /*!< [5..5] ACK for BURSTREQ */ - __IOM uint32_t BURSTAVAIL : 1; /*!< [6..6] Availability of Burst functionality */ - } FEATUREENABLE_b; - } ; - __IM uint32_t RESERVED; - - union { - __IOM uint32_t DEBUGGER; /*!< (@ 0x00000020) Debugger Control */ - - struct { - __IOM uint32_t LOCKOUT : 1; /*!< [0..0] Lockout of debugger (SWD). */ - } DEBUGGER_b; - } ; - __IM uint32_t RESERVED1[55]; - - union { - __IOM uint32_t BODCTRL; /*!< (@ 0x00000100) BOD control Register */ - - struct { - __IOM uint32_t BODLPWD : 1; /*!< [0..0] BODL Power Down. */ - __IOM uint32_t BODHPWD : 1; /*!< [1..1] BODH Power Down. */ - __IOM uint32_t BODCPWD : 1; /*!< [2..2] BODC Power Down. */ - __IOM uint32_t BODFPWD : 1; /*!< [3..3] BODF Power Down. */ - __IOM uint32_t BODLVREFSEL : 1; /*!< [4..4] BODL External Reference Select. Note: the SWE mux select - in PWRSEQ2SWE must be set for this to take effect. */ - __IOM uint32_t BODHVREFSEL : 1; /*!< [5..5] BODH External Reference Select. Note: the SWE mux select - in PWRSEQ2SWE must be set for this to take effect. */ - } BODCTRL_b; - } ; - - union { - __IOM uint32_t ADCPWRDLY; /*!< (@ 0x00000104) ADC Power Up Delay Control */ - - struct { - __IOM uint32_t ADCPWR0 : 8; /*!< [7..0] ADC Reference Buffer Power Enable delay in 64 ADC CLK - increments for ADC_CLKSEL = 0x1, 32 ADC CLOCK increments - for ADC_CLKSEL = 0x2. */ - __IOM uint32_t ADCPWR1 : 8; /*!< [15..8] ADC Reference Keeper enable delay in 16 ADC CLK increments - for ADC_CLKSEL = 0x1, 8 ADC CLOCK increments for ADC_CLKSEL - = 0x2. */ - } ADCPWRDLY_b; - } ; - __IM uint32_t RESERVED2; - - union { - __IOM uint32_t ADCCAL; /*!< (@ 0x0000010C) ADC Calibration Control */ - - struct { - __IOM uint32_t CALONPWRUP : 1; /*!< [0..0] Run ADC Calibration on initial power up sequence */ - __IOM uint32_t ADCCALIBRATED : 1; /*!< [1..1] Status for ADC Calibration */ - } ADCCAL_b; - } ; - - union { - __IOM uint32_t ADCBATTLOAD; /*!< (@ 0x00000110) ADC Battery Load Enable */ - - struct { - __IOM uint32_t BATTLOAD : 1; /*!< [0..0] Enable the ADC battery load resistor */ - } ADCBATTLOAD_b; - } ; - __IM uint32_t RESERVED3; - - union { - __IOM uint32_t ADCTRIM; /*!< (@ 0x00000118) ADC Trims */ - - struct { - __IOM uint32_t ADCREFKEEPIBTRIM : 2; /*!< [1..0] ADC Reference Ibias trim */ - __IM uint32_t : 4; - __IOM uint32_t ADCREFBUFTRIM : 5; /*!< [10..6] ADC Reference buffer trim */ - __IOM uint32_t ADCRFBUFIBTRIM : 2; /*!< [12..11] ADC reference buffer input bias trim */ - } ADCTRIM_b; - } ; - - union { - __IOM uint32_t ADCREFCOMP; /*!< (@ 0x0000011C) ADC Referece Keeper and Comparator Control */ - - struct { - __IOM uint32_t ADC_REFCOMP_OUT : 1; /*!< [0..0] Output of the ADC reference comparator */ - __IM uint32_t : 7; - __IOM uint32_t ADCREFKEEPTRIM : 5; /*!< [12..8] ADC Reference Keeper Trim */ - __IM uint32_t : 3; - __IOM uint32_t ADCRFCMPEN : 1; /*!< [16..16] ADC Reference comparator power down */ - } ADCREFCOMP_b; - } ; - - union { - __IOM uint32_t XTALCTRL; /*!< (@ 0x00000120) XTAL Oscillator Control */ - - struct { - __IOM uint32_t XTALSWE : 1; /*!< [0..0] XTAL Software Override Enable. */ - __IOM uint32_t FDBKDSBLXTAL : 1; /*!< [1..1] XTAL Oscillator Disable Feedback. */ - __IOM uint32_t BYPCMPRXTAL : 1; /*!< [2..2] XTAL Oscillator Bypass Comparator. */ - __IOM uint32_t PDNBCOREXTAL : 1; /*!< [3..3] XTAL Oscillator Power Down Core. */ - __IOM uint32_t PDNBCMPRXTAL : 1; /*!< [4..4] XTAL Oscillator Power Down Comparator. */ - __IOM uint32_t PWDBODXTAL : 1; /*!< [5..5] XTAL Power down on brown out. */ - __IOM uint32_t XTALIBUFTRIM : 2; /*!< [7..6] XTAL IBUFF trim */ - __IOM uint32_t XTALICOMPTRIM : 2; /*!< [9..8] XTAL ICOMP trim */ - } XTALCTRL_b; - } ; - - union { - __IOM uint32_t XTALGENCTRL; /*!< (@ 0x00000124) XTAL Oscillator General Control */ - - struct { - __IOM uint32_t ACWARMUP : 2; /*!< [1..0] Auto-calibration delay control */ - __IOM uint32_t XTALBIASTRIM : 6; /*!< [7..2] XTAL BIAS trim */ - __IOM uint32_t XTALKSBIASTRIM : 6; /*!< [13..8] XTAL IBIAS Kick start trim. This trim value is used - during the startup process to enable a faster lock. */ - } XTALGENCTRL_b; - } ; - __IM uint32_t RESERVED4[28]; - - union { - __IOM uint32_t MISCCTRL; /*!< (@ 0x00000198) Miscellaneous control register. */ - - struct { - __IOM uint32_t RESERVED_RW_0 : 5; /*!< [4..0] Reserved bits, always leave unchanged. The MISCCTRL register - must be modified via atomic RMW, leaving this bitfield - completely unmodified. Failure to do so will result in - unpredictable behavior. */ - __IOM uint32_t BLE_RESETN : 1; /*!< [5..5] BLE reset signal. */ - } MISCCTRL_b; - } ; - __IM uint32_t RESERVED5; - - union { - __IOM uint32_t BOOTLOADER; /*!< (@ 0x000001A0) Bootloader and secure boot functions */ - - struct { - __IOM uint32_t BOOTLOADERLOW : 1; /*!< [0..0] Determines whether the bootloader code is visible at - address 0x00000000 or not. Resets to 1, write 1 to clear. */ - __IOM uint32_t SBLOCK : 1; /*!< [1..1] Secure boot lock. Always resets to 1, write 1 to clear. - Enables system visibility to bootloader until set. */ - __IOM uint32_t PROTLOCK : 1; /*!< [2..2] Flash protection lock. Always resets to 1, write 1 to - clear. Enables writes to flash protection register set. */ - __IM uint32_t : 23; - __IOM uint32_t SECBOOTFEATURE : 2; /*!< [27..26] Indicates whether the secure boot feature is enabled. */ - __IOM uint32_t SECBOOT : 2; /*!< [29..28] Indicates whether the secure boot on cold reset is - enabled */ - __IOM uint32_t SECBOOTONRST : 2; /*!< [31..30] Indicates whether the secure boot on warm reset is - enabled */ - } BOOTLOADER_b; - } ; - - union { - __IOM uint32_t SHADOWVALID; /*!< (@ 0x000001A4) Register to indicate whether the shadow registers - have been successfully loaded from the Flash - Information Space. */ - - struct { - __IOM uint32_t VALID : 1; /*!< [0..0] Indicates whether the shadow registers contain valid - data from the Flash Information Space. */ - __IOM uint32_t BLDSLEEP : 1; /*!< [1..1] Indicates whether the bootloader should sleep or deep - sleep if no image loaded. */ - __IOM uint32_t INFO0_VALID : 1; /*!< [2..2] Indicates whether info0 contains valid data */ - } SHADOWVALID_b; - } ; - __IM uint32_t RESERVED6[2]; - - union { - __IOM uint32_t SCRATCH0; /*!< (@ 0x000001B0) Scratch register that is not reset by any reset */ - - struct { - __IOM uint32_t SCRATCH0 : 32; /*!< [31..0] Scratch register 0. */ - } SCRATCH0_b; - } ; - - union { - __IOM uint32_t SCRATCH1; /*!< (@ 0x000001B4) Scratch register that is not reset by any reset */ - - struct { - __IOM uint32_t SCRATCH1 : 32; /*!< [31..0] Scratch register 1. */ - } SCRATCH1_b; - } ; - __IM uint32_t RESERVED7[2]; - - union { - __IOM uint32_t ICODEFAULTADDR; /*!< (@ 0x000001C0) ICODE bus address which was present when a bus - fault occurred. */ - - struct { - __IOM uint32_t ICODEFAULTADDR : 32; /*!< [31..0] The ICODE bus address observed when a Bus Fault occurred. - Once an address is captured in this field, it is held until - the corresponding Fault Observed bit is cleared in the - FAULTSTATUS register. */ - } ICODEFAULTADDR_b; - } ; - - union { - __IOM uint32_t DCODEFAULTADDR; /*!< (@ 0x000001C4) DCODE bus address which was present when a bus - fault occurred. */ - - struct { - __IOM uint32_t DCODEFAULTADDR : 32; /*!< [31..0] The DCODE bus address observed when a Bus Fault occurred. - Once an address is captured in this field, it is held until - the corresponding Fault Observed bit is cleared in the - FAULTSTATUS register. */ - } DCODEFAULTADDR_b; - } ; - - union { - __IOM uint32_t SYSFAULTADDR; /*!< (@ 0x000001C8) System bus address which was present when a bus - fault occurred. */ - - struct { - __IOM uint32_t SYSFAULTADDR : 32; /*!< [31..0] SYS bus address observed when a Bus Fault occurred. - Once an address is captured in this field, it is held until - the corresponding Fault Observed bit is cleared in the - FAULTSTATUS register. */ - } SYSFAULTADDR_b; - } ; - - union { - __IOM uint32_t FAULTSTATUS; /*!< (@ 0x000001CC) Reflects the status of the bus decoders' fault - detection. Any write to this register will - clear all of the status bits within the - register. */ - - struct { - __IOM uint32_t ICODEFAULT : 1; /*!< [0..0] The ICODE Bus Decoder Fault Detected bit. When set, a - fault has been detected, and the ICODEFAULTADDR register - will contain the bus address which generated the fault. */ - __IOM uint32_t DCODEFAULT : 1; /*!< [1..1] DCODE Bus Decoder Fault Detected bit. When set, a fault - has been detected, and the DCODEFAULTADDR register will - contain the bus address which generated the fault. */ - __IOM uint32_t SYSFAULT : 1; /*!< [2..2] SYS Bus Decoder Fault Detected bit. When set, a fault - has been detected, and the SYSFAULTADDR register will contain - the bus address which generated the fault. */ - } FAULTSTATUS_b; - } ; - - union { - __IOM uint32_t FAULTCAPTUREEN; /*!< (@ 0x000001D0) Enable the fault capture registers */ - - struct { - __IOM uint32_t FAULTCAPTUREEN : 1; /*!< [0..0] Fault Capture Enable field. When set, the Fault Capture - monitors are enabled and addresses which generate a hard - fault are captured into the FAULTADDR registers. */ - } FAULTCAPTUREEN_b; - } ; - __IM uint32_t RESERVED8[11]; - - union { - __IOM uint32_t DBGR1; /*!< (@ 0x00000200) Read-only debug register 1 */ - - struct { - __IOM uint32_t ONETO8 : 32; /*!< [31..0] Read-only register for communication validation */ - } DBGR1_b; - } ; - - union { - __IOM uint32_t DBGR2; /*!< (@ 0x00000204) Read-only debug register 2 */ - - struct { - __IOM uint32_t COOLCODE : 32; /*!< [31..0] Read-only register for communication validation */ - } DBGR2_b; - } ; - __IM uint32_t RESERVED9[6]; - - union { - __IOM uint32_t PMUENABLE; /*!< (@ 0x00000220) Control bit to enable/disable the PMU */ - - struct { - __IOM uint32_t ENABLE : 1; /*!< [0..0] PMU Enable Control bit. When set, the MCU's PMU will - place the MCU into the lowest power consuming Deep Sleep - mode upon execution of a WFI instruction (dependent on - the setting of the SLEEPDEEP bit in the ARM SCR register). - When cleared, regardless of the requested sleep mode, the - PMU will not enter the lowest power Deep Sleep mode, instead - entering the Sleep mode. */ - } PMUENABLE_b; - } ; - __IM uint32_t RESERVED10[11]; - - union { - __IOM uint32_t TPIUCTRL; /*!< (@ 0x00000250) TPIU Control Register. Determines the clock enable - and frequency for the M4's TPIU interface. */ - - struct { - __IOM uint32_t ENABLE : 1; /*!< [0..0] TPIU Enable field. When set, the ARM M4 TPIU is enabled - and data can be streamed out of the MCU's SWO port using - the ARM ITM and TPIU modules. */ - __IM uint32_t : 7; - __IOM uint32_t CLKSEL : 3; /*!< [10..8] This field selects the frequency of the ARM M4 TPIU - port. */ - } TPIUCTRL_b; - } ; - __IM uint32_t RESERVED11[4]; - - union { - __IOM uint32_t OTAPOINTER; /*!< (@ 0x00000264) OTA (Over the Air) Update Pointer/Status. Reset - only by POA */ - - struct { - __IOM uint32_t OTAVALID : 1; /*!< [0..0] Indicates that an OTA update is valid */ - __IOM uint32_t OTASBLUPDATE : 1; /*!< [1..1] Indicates that the sbl_init has been updated */ - __IOM uint32_t OTAPOINTER : 30; /*!< [31..2] Flash page pointer with updated OTA image */ - } OTAPOINTER_b; - } ; - __IM uint32_t RESERVED12[6]; - - union { - __IOM uint32_t APBDMACTRL; /*!< (@ 0x00000280) DMA Control Register. Determines misc settings - for DMA operation */ - - struct { - __IOM uint32_t DMA_ENABLE : 1; /*!< [0..0] Enable the DMA controller. When disabled, DMA requests - will be ignored by the controller */ - __IOM uint32_t DECODEABORT : 1; /*!< [1..1] APB Decode Abort. When set, the APB bridge will issue - a data abort (bus fault) on transactions to peripherals - that are powered down. When set to 0, writes are quietly - discarded and reads return 0. */ - __IM uint32_t : 6; - __IOM uint32_t HYSTERESIS : 8; /*!< [15..8] This field determines how long the DMA will remain active - during deep sleep before shutting down and returning the - system to full deep sleep. Values are based on a 94KHz - clock and are roughly 10us increments for a range of ~10us - to 2.55ms */ - } APBDMACTRL_b; - } ; - - union { - __IOM uint32_t SRAMMODE; /*!< (@ 0x00000284) SRAM Controller mode bits */ - - struct { - __IOM uint32_t IPREFETCH : 1; /*!< [0..0] When set, instruction accesses to the SRAM banks will - be prefetched (normally 2 cycle read access). Generally, - this mode bit should be set for improved performance when - executing instructions from SRAM. */ - __IOM uint32_t IPREFETCH_CACHE : 1; /*!< [1..1] Secondary prefetch feature that will cache prefetched - data across bus waitstates (requires IPREFETCH to be set). */ - __IM uint32_t : 2; - __IOM uint32_t DPREFETCH : 1; /*!< [4..4] When set, data bus accesses to the SRAM banks will be - prefetched (normally 2 cycle read access). Use of this - mode bit is only recommended if the work flow has a large - number of sequential accesses. */ - __IOM uint32_t DPREFETCH_CACHE : 1; /*!< [5..5] Secondary prefetch feature that will cache prefetched - data across bus waitstates (requires DPREFETCH to be set). */ - } SRAMMODE_b; - } ; - __IM uint32_t RESERVED13[48]; - - union { - __IOM uint32_t KEXTCLKSEL; /*!< (@ 0x00000348) Key Register to enable the use of external clock - selects via the EXTCLKSEL reg */ - - struct { - __IOM uint32_t KEXTCLKSEL : 32; /*!< [31..0] Key register value. */ - } KEXTCLKSEL_b; - } ; - __IM uint32_t RESERVED14[4]; - - union { - __IOM uint32_t SIMOBUCK4; /*!< (@ 0x0000035C) SIMO Buck Control Reg1 */ - - struct { - __IOM uint32_t SIMOBUCKMEMLPLOWTONTRIM : 4;/*!< [3..0] simobuck_mem_lp_low_ton_trim */ - __IOM uint32_t SIMOBUCKMEMACTDRVSTRTRIM : 2;/*!< [5..4] simobuck_mem_act_drvstr_trim */ - __IOM uint32_t SIMOBUCKMEMLPDRVSTRTRIM : 2;/*!< [7..6] simobuck_mem_lp_drvstr_trim */ - __IOM uint32_t SIMOBUCKMEMLEAKAGETRIM : 2;/*!< [9..8] simobuck_mem_leakage_trim */ - __IOM uint32_t SIMOBUCKZXTRIM : 4; /*!< [13..10] simobuck_zx_trim */ - __IOM uint32_t SIMOBUCKUVLOCNTRTRIM : 3; /*!< [16..14] simobuck_uvlo_cntr_trim */ - __IOM uint32_t SIMOBUCKUVLODRVSTRTRIM : 3;/*!< [19..17] simobuck_uvlo_drvstr_trim */ - __IOM uint32_t SIMOBUCKEXTCLKSEL : 1; /*!< [20..20] simobuck_extclk_sel */ - __IOM uint32_t SIMOBUCKCLKDIVSEL : 2; /*!< [22..21] simobuck_clkdiv_sel */ - __IOM uint32_t SIMOBUCKCOMP2LPEN : 1; /*!< [23..23] simobuck_comp2_lp_en */ - __IOM uint32_t SIMOBUCKCOMP2TIMEOUTEN : 1;/*!< [24..24] simobuck_comp2_timeout_en */ - __IOM uint32_t SIMOBUCKPRIORITYSEL : 1; /*!< [25..25] simobuck_priority_sel */ - __IOM uint32_t SIMOBUCKUVLOMODE : 2; /*!< [27..26] simobuck_uvlo_mode */ - __IOM uint32_t SIMOBUCKIBIASTRIM : 4; /*!< [31..28] simobuck_bias_trim */ - } SIMOBUCK4_b; - } ; - __IM uint32_t RESERVED15[2]; - - union { - __IOM uint32_t BLEBUCK2; /*!< (@ 0x00000368) BLEBUCK2 Control Reg */ - - struct { - __IOM uint32_t BLEBUCKTONLOWTRIM : 6; /*!< [5..0] blebuck_ton_low_trim */ - __IOM uint32_t BLEBUCKTONHITRIM : 6; /*!< [11..6] blebuck_ton_hi_trim */ - __IOM uint32_t BLEBUCKTOND2ATRIM : 6; /*!< [17..12] blebuck_ton_trim */ - } BLEBUCK2_b; - } ; - __IM uint32_t RESERVED16[13]; - - union { - __IOM uint32_t FLASHWPROT0; /*!< (@ 0x000003A0) Flash Write Protection Bits */ - - struct { - __IOM uint32_t FW0BITS : 32; /*!< [31..0] Write protect flash 0x00000000 - 0x0007FFFF. Each bit - provides write protection for 16KB chunks of flash data - space. Bits are cleared by writing a 1 to the bit. When - read, 0 indicates the region is protected. Bits are sticky - (can be set when PROTLOCK is 1, but only cleared by reset) */ - } FLASHWPROT0_b; - } ; - - union { - __IOM uint32_t FLASHWPROT1; /*!< (@ 0x000003A4) Flash Write Protection Bits */ - - struct { - __IOM uint32_t FW1BITS : 32; /*!< [31..0] Write protect flash 0x00080000 - 0x000FFFFF. Each bit - provides write protection for 16KB chunks of flash data - space. Bits are cleared by writing a 1 to the bit. When - read, 0 indicates the region is protected. Bits are sticky - (can be set when PROTLOCK is 1, but only cleared by reset) */ - } FLASHWPROT1_b; - } ; - __IM uint32_t RESERVED17[2]; - - union { - __IOM uint32_t FLASHRPROT0; /*!< (@ 0x000003B0) Flash Read Protection Bits */ - - struct { - __IOM uint32_t FR0BITS : 32; /*!< [31..0] Copy (read) protect flash 0x00000000 - 0x0007FFFF. Each - bit provides read protection for 16KB chunks of flash. - Bits are cleared by writing a 1 to the bit. When read, - 0 indicates the region is protected. Bits are sticky (can - be set when PROTLOCK is 1, but only cleared by reset) */ - } FLASHRPROT0_b; - } ; - - union { - __IOM uint32_t FLASHRPROT1; /*!< (@ 0x000003B4) Flash Read Protection Bits */ - - struct { - __IOM uint32_t FR1BITS : 32; /*!< [31..0] Copy (read) protect flash 0x00080000 - 0x000FFFFF. Each - bit provides read protection for 16KB chunks of flash. - Bits are cleared by writing a 1 to the bit. When read, - 0 indicates the region is protected. Bits are sticky (can - be set when PROTLOCK is 1, but only cleared by reset) */ - } FLASHRPROT1_b; - } ; - __IM uint32_t RESERVED18[2]; - - union { - __IOM uint32_t DMASRAMWRITEPROTECT0; /*!< (@ 0x000003C0) SRAM write-protection bits. */ - - struct { - __IOM uint32_t DMA_WPROT0 : 32; /*!< [31..0] Write protect SRAM from DMA. Each bit provides write - protection for an 8KB region of memory. When set to 1, - the region will be protected from DMA writes, when set - to 0, DMA may write the region. */ - } DMASRAMWRITEPROTECT0_b; - } ; - - union { - __IOM uint32_t DMASRAMWRITEPROTECT1; /*!< (@ 0x000003C4) SRAM write-protection bits. */ - - struct { - __IOM uint32_t DMA_WPROT1 : 16; /*!< [15..0] Write protect SRAM from DMA. Each bit provides write - protection for an 8KB region of memory. When set to 1, - the region will be protected from DMA writes, when set - to 0, DMA may write the region. */ - } DMASRAMWRITEPROTECT1_b; - } ; - __IM uint32_t RESERVED19[2]; - - union { - __IOM uint32_t DMASRAMREADPROTECT0; /*!< (@ 0x000003D0) SRAM read-protection bits. */ - - struct { - __IOM uint32_t DMA_RPROT0 : 32; /*!< [31..0] Read protect SRAM from DMA. Each bit provides write - protection for an 8KB region of memory. When set to 1, - the region will be protected from DMA reads, when set to - 0, DMA may read the region. */ - } DMASRAMREADPROTECT0_b; - } ; - - union { - __IOM uint32_t DMASRAMREADPROTECT1; /*!< (@ 0x000003D4) SRAM read-protection bits. */ - - struct { - __IOM uint32_t DMA_RPROT1 : 16; /*!< [15..0] Read protect SRAM from DMA. Each bit provides write - protection for an 8KB region of memory. When set to 1, - the region will be protected from DMA reads, when set to - 0, DMA may read the region. */ - } DMASRAMREADPROTECT1_b; - } ; -} MCUCTRL_Type; /*!< Size = 984 (0x3d8) */ - - - -/* =========================================================================================================================== */ -/* ================ MSPI ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Multibit SPI Master (MSPI) - */ - -typedef struct { /*!< (@ 0x50014000) MSPI Structure */ - - union { - __IOM uint32_t CTRL; /*!< (@ 0x00000000) MSPI PIO Transfer Control/Status Register */ - - struct { - __IOM uint32_t START : 1; /*!< [0..0] Write to 1 to initiate a PIO transaction on the bus (typically - the entire register should be written at once with this - bit set). */ - __IOM uint32_t STATUS : 1; /*!< [1..1] Command status: 1 indicates command has completed. Cleared - by writing 1 to this bit or starting a new transfer. */ - __IOM uint32_t BUSY : 1; /*!< [2..2] Command status: 1 indicates controller is busy (command - in progress) */ - __IOM uint32_t QUADCMD : 1; /*!< [3..3] Flag indicating that the operation is a command that - should be replicated to both devices in paired QUAD mode. - This is typically only used when reading/writing configuration - registers in paired flash devices (do not set for memory - transfers). */ - __IM uint32_t : 1; - __IOM uint32_t CONT : 1; /*!< [5..5] Continuation transfer. When 1, indicates that the MSPI - will hold CE low after the transaction completes. This - is included for compatibility with IOM module since the - MSPI transfer module can handle most cases in a single - transfer. NOTE: CONT functionality only works with CLKDIV=2 - (24 MHz). */ - __IOM uint32_t BIGENDIAN : 1; /*!< [6..6] 1 indicates data in FIFO is in big endian format (MSB - first); 0 indicates little endian data (default, LSB first). */ - __IOM uint32_t ENTURN : 1; /*!< [7..7] Indicates whether TX->RX turnaround cycles should be - enabled for this operation (see TURNAROUND field in CFG - register). */ - __IOM uint32_t SENDA : 1; /*!< [8..8] Indicates whether an address phase should be sent (see - ADDR register and ASIZE field in CFG register) */ - __IOM uint32_t SENDI : 1; /*!< [9..9] Indicates whether an instruction phase should be sent - (see INSTR field and ISIZE field in CFG register) */ - __IOM uint32_t TXRX : 1; /*!< [10..10] 1 Indicates a TX operation, 0 indicates an RX operation - of XFERBYTES */ - __IOM uint32_t PIOSCRAMBLE : 1; /*!< [11..11] Enables data scrambling for PIO opertions. This should - only be used for data operations and never for commands - to a device. */ - __IM uint32_t : 4; - __IOM uint32_t XFERBYTES : 16; /*!< [31..16] Number of bytes to transmit or receive (based on TXRX - bit) */ - } CTRL_b; - } ; - - union { - __IOM uint32_t CFG; /*!< (@ 0x00000004) MSPI Transfer Configuration Register */ - - struct { - __IOM uint32_t DEVCFG : 4; /*!< [3..0] Flash configuration for XIP and AUTO DMA operations. - Controls value for SER (Slave Enable) for XIP operations - and address generation for DMA/XIP modes. Also used to - configure SPIFRF (frame format). */ - __IOM uint32_t ASIZE : 2; /*!< [5..4] Address Size. Address bytes to send from ADDR register - name = A1 value = 0x0 desc = Send one address byteenum - name = A2 value = 0x1 desc = Send two address bytesenum - name = A3 value = 0x2 desc = Send three address bytesenum - name = A4 value = 0x3 desc = Send four address bytes */ - __IOM uint32_t ISIZE : 1; /*!< [6..6] Instruction Sizeenum name = I8 value = 0x0 desc = Instruction - is 1 byteenum name = I16 value = 0x1 desc = Instruction - is 2 bytes */ - __IOM uint32_t SEPIO : 1; /*!< [7..7] Separate IO configuration. This bit should be set when - the target device has separate MOSI and MISO pins. Respective - IN/OUT bits below should be set to map pins. */ - __IOM uint32_t TURNAROUND : 6; /*!< [13..8] Number of turnaound cycles (for TX->RX transitions). - Qualified by ENTURN or XIPENTURN bit field. */ - __IM uint32_t : 2; - __IOM uint32_t CPHA : 1; /*!< [16..16] Serial clock phase. */ - __IOM uint32_t CPOL : 1; /*!< [17..17] Serial clock polarity. */ - } CFG_b; - } ; - - union { - __IOM uint32_t ADDR; /*!< (@ 0x00000008) MSPI Transfer Address Register */ - - struct { - __IOM uint32_t ADDR : 32; /*!< [31..0] Optional Address field to send (after optional instruction - field) - qualified by ASIZE in CMD register. NOTE: This - register is aliased to DMADEVADDR. */ - } ADDR_b; - } ; - - union { - __IOM uint32_t INSTR; /*!< (@ 0x0000000C) MSPI Transfer Instruction */ - - struct { - __IOM uint32_t INSTR : 16; /*!< [15..0] Optional Instruction field to send (1st byte) - qualified - by ISEND/ISIZE */ - } INSTR_b; - } ; - - union { - __IOM uint32_t TXFIFO; /*!< (@ 0x00000010) TX Data FIFO */ - - struct { - __IOM uint32_t TXFIFO : 32; /*!< [31..0] Data to be transmitted. Data should normall be aligned - to the LSB (pad the upper bits with zeros) unless BIGENDIAN - is set. */ - } TXFIFO_b; - } ; - - union { - __IOM uint32_t RXFIFO; /*!< (@ 0x00000014) RX Data FIFO */ - - struct { - __IOM uint32_t RXFIFO : 32; /*!< [31..0] Receive data. Data is aligned to the LSB (padded zeros - on upper bits) unless BIGENDIAN is set. */ - } RXFIFO_b; - } ; - - union { - __IOM uint32_t TXENTRIES; /*!< (@ 0x00000018) TX FIFO Entries */ - - struct { - __IOM uint32_t TXENTRIES : 5; /*!< [4..0] Number of 32-bit words/entries in TX FIFO */ - } TXENTRIES_b; - } ; - - union { - __IOM uint32_t RXENTRIES; /*!< (@ 0x0000001C) RX FIFO Entries */ - - struct { - __IOM uint32_t RXENTRIES : 5; /*!< [4..0] Number of 32-bit words/entries in RX FIFO */ - } RXENTRIES_b; - } ; - - union { - __IOM uint32_t THRESHOLD; /*!< (@ 0x00000020) TX/RX FIFO Threshhold Levels */ - - struct { - __IOM uint32_t TXTHRESH : 5; /*!< [4..0] Number of entries in TX FIFO that cause TXF interrupt */ - __IM uint32_t : 3; - __IOM uint32_t RXTHRESH : 5; /*!< [12..8] Number of entries in TX FIFO that cause RXE interrupt */ - } THRESHOLD_b; - } ; - __IM uint32_t RESERVED[55]; - - union { - __IOM uint32_t MSPICFG; /*!< (@ 0x00000100) MSPI Module Configuration */ - - struct { - __IOM uint32_t APBCLK : 1; /*!< [0..0] Enable continuous APB clock. For power-efficient operation, - APBCLK should be set to 0. */ - __IOM uint32_t RXCAP : 1; /*!< [1..1] Controls RX data capture phase. A setting of 0 (NORMAL) - captures read data at the normal capture point relative - to the internal clock launch point. However, to accomodate - chip/pad/board delays, a setting of RXCAP of 1 is expected - to be used to align the capture point with the return data - window. This bit is used in conjunction with RXNEG to provide - 4 unique capture points, all about 10ns apart. */ - __IOM uint32_t RXNEG : 1; /*!< [2..2] Adjusts the RX capture phase to the negedge of the 48MHz - internal clock (~10ns early). For normal operation, it - is expected that RXNEG will be set to 0. */ - __IOM uint32_t TXNEG : 1; /*!< [3..3] Launches TX data a half clock cycle (~10ns) early. This - should normally be programmed to zero (NORMAL). */ - __IOM uint32_t IOMSEL : 3; /*!< [6..4] Selects which IOM is selected for CQ handshake status. */ - __IM uint32_t : 1; - __IOM uint32_t CLKDIV : 6; /*!< [13..8] Clock Divider. Allows dividing 48 MHz base clock by - integer multiples. Enumerations are provided for common - frequency, but any integer divide from 48 MHz is allowed. - Odd divide ratios will result in a 33/66 percent duty cycle - with a long low clock pulse (to allow longer round-trip - for read data). */ - __IM uint32_t : 15; - __IOM uint32_t FIFORESET : 1; /*!< [29..29] Reset MSPI FIFO (active high). 1=reset FIFO, 0=normal - operation. May be used to manually flush the FIFO in error - handling. */ - __IOM uint32_t IPRSTN : 1; /*!< [30..30] IP block reset. Write to 0 to put the transfer module - in reset or 1 for normal operation. This may be required - after error conditions to clear the transfer on the bus. */ - __IOM uint32_t PRSTN : 1; /*!< [31..31] Peripheral reset. Master reset to the entire MSPI module - (DMA, XIP, and transfer state machines). 1=normal operation, - 0=in reset. */ - } MSPICFG_b; - } ; - - union { - __IOM uint32_t PADCFG; /*!< (@ 0x00000104) MSPI Output Pad Configuration */ - - struct { - __IOM uint32_t OUT3 : 1; /*!< [0..0] Output pad 3 configuration. 0=data[3] 1=CLK */ - __IOM uint32_t OUT4 : 1; /*!< [1..1] Output pad 4 configuration. 0=data[4] 1=data[0] */ - __IOM uint32_t OUT5 : 1; /*!< [2..2] Output pad 5 configuration. 0=data[5] 1=data[1] */ - __IOM uint32_t OUT6 : 1; /*!< [3..3] Output pad 6 configuration. 0=data[6] 1=data[2] */ - __IOM uint32_t OUT7 : 1; /*!< [4..4] Output pad 7 configuration. 0=data[7] 1=data[3] */ - __IM uint32_t : 11; - __IOM uint32_t IN0 : 2; /*!< [17..16] Data Input pad 0 pin muxing: 0=pad[0] 1=pad[4] 2=pad[1] - 3=pad[5] */ - __IOM uint32_t IN1 : 1; /*!< [18..18] Data Input pad 1 pin muxing: 0=pad[1] 1=pad[5] */ - __IOM uint32_t IN2 : 1; /*!< [19..19] Data Input pad 2 pin muxing: 0=pad[2] 1=pad[6] */ - __IOM uint32_t IN3 : 1; /*!< [20..20] Data Input pad 3 pin muxing: 0=pad[3] 1=pad[7] */ - __IOM uint32_t REVCS : 1; /*!< [21..21] Reverse CS connections. Allows CS1 to be associated - with lower data lanes and CS0 to be associated with upper - data lines */ - } PADCFG_b; - } ; - - union { - __IOM uint32_t PADOUTEN; /*!< (@ 0x00000108) MSPI Output Enable Pad Configuration */ - - struct { - __IOM uint32_t OUTEN : 9; /*!< [8..0] Output pad enable configuration. Indicates which pads - should be driven. Bits [3:0] are Quad0 data, [7:4] are - Quad1 data, and [8] is clock. */ - } PADOUTEN_b; - } ; - - union { - __IOM uint32_t FLASH; /*!< (@ 0x0000010C) Configuration for XIP/DMA support of SPI flash - modules. */ - - struct { - __IOM uint32_t XIPEN : 1; /*!< [0..0] Enable the XIP (eXecute In Place) function which effectively - enables the address decoding of the MSPI device in the - flash/cache address space at address 0x04000000-0x07FFFFFF. */ - __IM uint32_t : 1; - __IOM uint32_t XIPACK : 2; /*!< [3..2] Controls transmission of Micron XIP acknowledge cycles - (Micron Flash devices only) */ - __IOM uint32_t XIPBIGENDIAN : 1; /*!< [4..4] Indicates whether XIP/AUTO DMA data transfers are in - big or little endian format */ - __IOM uint32_t XIPENTURN : 1; /*!< [5..5] Indicates whether XIP/AUTO DMA operations should enable - TX->RX turnaround cycles */ - __IOM uint32_t XIPSENDA : 1; /*!< [6..6] Indicates whether XIP/AUTO DMA operations should send - an an address phase (see DMADEVADDR register and ASIZE - field in CFG) */ - __IOM uint32_t XIPSENDI : 1; /*!< [7..7] Indicates whether XIP/AUTO DMA operations should send - an instruction (see READINSTR field and ISIZE field in - CFG) */ - __IOM uint32_t XIPMIXED : 3; /*!< [10..8] Reserved. Set to 0x0 */ - __IM uint32_t : 5; - __IOM uint32_t WRITEINSTR : 8; /*!< [23..16] Write command sent for DMA operations */ - __IOM uint32_t READINSTR : 8; /*!< [31..24] Read command sent to flash for DMA/XIP operations */ - } FLASH_b; - } ; - __IM uint32_t RESERVED1[4]; - - union { - __IOM uint32_t SCRAMBLING; /*!< (@ 0x00000120) External Flash Scrambling Controls */ - - struct { - __IOM uint32_t SCRSTART : 10; /*!< [9..0] Scrambling region start address [25:16] (64K block granularity). - The START block is the FIRST block included in the scrambled - address range. */ - __IM uint32_t : 6; - __IOM uint32_t SCREND : 10; /*!< [25..16] Scrambling region end address [25:16] (64K block granularity). - The END block is the LAST block included in the scrambled - address range. */ - __IM uint32_t : 5; - __IOM uint32_t SCRENABLE : 1; /*!< [31..31] Enables Data Scrambling Region. When 1 reads and writes - to the range will be scrambled. When 0, data will be read/written - unmodified. Address range is specified in 64K granularity - and the START/END ranges are included within the range. */ - } SCRAMBLING_b; - } ; - __IM uint32_t RESERVED2[55]; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000200) MSPI Master Interrupts: Enable */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Transfer complete. Note that DMA and CQ operations are - layered, so CMDCMP, DCMP, and CQ* can all be signalled - simultaneously */ - __IOM uint32_t TXE : 1; /*!< [1..1] Transmit FIFO empty. */ - __IOM uint32_t TXO : 1; /*!< [2..2] Transmit FIFO Overflow (only occurs when SW writes to - a full FIFO). */ - __IOM uint32_t RXU : 1; /*!< [3..3] Receive FIFO underflow (only occurs when SW reads from - an empty FIFO) */ - __IOM uint32_t RXO : 1; /*!< [4..4] Receive FIFO overflow (cannot happen in MSPI design -- - MSPI bus pins will stall) */ - __IOM uint32_t RXF : 1; /*!< [5..5] Receive FIFO full */ - __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Complete Interrupt */ - __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Interrupt */ - __IOM uint32_t CQCMP : 1; /*!< [8..8] Command Queue Complete Interrupt */ - __IOM uint32_t CQUPD : 1; /*!< [9..9] Command Queue Update Interrupt. Issued whenever the CQ - performs an operation where address bit[0] is set. Useful - for triggering CURIDX interrupts. */ - __IOM uint32_t CQPAUSED : 1; /*!< [10..10] Command Queue is Paused. */ - __IOM uint32_t CQERR : 1; /*!< [11..11] Command Queue Error Interrupt */ - __IOM uint32_t SCRERR : 1; /*!< [12..12] Scrambling Alignment Error. Scrambling operations must - be aligned to word (4-byte) start address. */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) MSPI Master Interrupts: Status */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Transfer complete. Note that DMA and CQ operations are - layered, so CMDCMP, DCMP, and CQ* can all be signalled - simultaneously */ - __IOM uint32_t TXE : 1; /*!< [1..1] Transmit FIFO empty. */ - __IOM uint32_t TXO : 1; /*!< [2..2] Transmit FIFO Overflow (only occurs when SW writes to - a full FIFO). */ - __IOM uint32_t RXU : 1; /*!< [3..3] Receive FIFO underflow (only occurs when SW reads from - an empty FIFO) */ - __IOM uint32_t RXO : 1; /*!< [4..4] Receive FIFO overflow (cannot happen in MSPI design -- - MSPI bus pins will stall) */ - __IOM uint32_t RXF : 1; /*!< [5..5] Receive FIFO full */ - __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Complete Interrupt */ - __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Interrupt */ - __IOM uint32_t CQCMP : 1; /*!< [8..8] Command Queue Complete Interrupt */ - __IOM uint32_t CQUPD : 1; /*!< [9..9] Command Queue Update Interrupt. Issued whenever the CQ - performs an operation where address bit[0] is set. Useful - for triggering CURIDX interrupts. */ - __IOM uint32_t CQPAUSED : 1; /*!< [10..10] Command Queue is Paused. */ - __IOM uint32_t CQERR : 1; /*!< [11..11] Command Queue Error Interrupt */ - __IOM uint32_t SCRERR : 1; /*!< [12..12] Scrambling Alignment Error. Scrambling operations must - be aligned to word (4-byte) start address. */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000208) MSPI Master Interrupts: Clear */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Transfer complete. Note that DMA and CQ operations are - layered, so CMDCMP, DCMP, and CQ* can all be signalled - simultaneously */ - __IOM uint32_t TXE : 1; /*!< [1..1] Transmit FIFO empty. */ - __IOM uint32_t TXO : 1; /*!< [2..2] Transmit FIFO Overflow (only occurs when SW writes to - a full FIFO). */ - __IOM uint32_t RXU : 1; /*!< [3..3] Receive FIFO underflow (only occurs when SW reads from - an empty FIFO) */ - __IOM uint32_t RXO : 1; /*!< [4..4] Receive FIFO overflow (cannot happen in MSPI design -- - MSPI bus pins will stall) */ - __IOM uint32_t RXF : 1; /*!< [5..5] Receive FIFO full */ - __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Complete Interrupt */ - __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Interrupt */ - __IOM uint32_t CQCMP : 1; /*!< [8..8] Command Queue Complete Interrupt */ - __IOM uint32_t CQUPD : 1; /*!< [9..9] Command Queue Update Interrupt. Issued whenever the CQ - performs an operation where address bit[0] is set. Useful - for triggering CURIDX interrupts. */ - __IOM uint32_t CQPAUSED : 1; /*!< [10..10] Command Queue is Paused. */ - __IOM uint32_t CQERR : 1; /*!< [11..11] Command Queue Error Interrupt */ - __IOM uint32_t SCRERR : 1; /*!< [12..12] Scrambling Alignment Error. Scrambling operations must - be aligned to word (4-byte) start address. */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000020C) MSPI Master Interrupts: Set */ - - struct { - __IOM uint32_t CMDCMP : 1; /*!< [0..0] Transfer complete. Note that DMA and CQ operations are - layered, so CMDCMP, DCMP, and CQ* can all be signalled - simultaneously */ - __IOM uint32_t TXE : 1; /*!< [1..1] Transmit FIFO empty. */ - __IOM uint32_t TXO : 1; /*!< [2..2] Transmit FIFO Overflow (only occurs when SW writes to - a full FIFO). */ - __IOM uint32_t RXU : 1; /*!< [3..3] Receive FIFO underflow (only occurs when SW reads from - an empty FIFO) */ - __IOM uint32_t RXO : 1; /*!< [4..4] Receive FIFO overflow (cannot happen in MSPI design -- - MSPI bus pins will stall) */ - __IOM uint32_t RXF : 1; /*!< [5..5] Receive FIFO full */ - __IOM uint32_t DCMP : 1; /*!< [6..6] DMA Complete Interrupt */ - __IOM uint32_t DERR : 1; /*!< [7..7] DMA Error Interrupt */ - __IOM uint32_t CQCMP : 1; /*!< [8..8] Command Queue Complete Interrupt */ - __IOM uint32_t CQUPD : 1; /*!< [9..9] Command Queue Update Interrupt. Issued whenever the CQ - performs an operation where address bit[0] is set. Useful - for triggering CURIDX interrupts. */ - __IOM uint32_t CQPAUSED : 1; /*!< [10..10] Command Queue is Paused. */ - __IOM uint32_t CQERR : 1; /*!< [11..11] Command Queue Error Interrupt */ - __IOM uint32_t SCRERR : 1; /*!< [12..12] Scrambling Alignment Error. Scrambling operations must - be aligned to word (4-byte) start address. */ - } INTSET_b; - } ; - __IM uint32_t RESERVED3[16]; - - union { - __IOM uint32_t DMACFG; /*!< (@ 0x00000250) DMA Configuration Register */ - - struct { - __IOM uint32_t DMAEN : 2; /*!< [1..0] DMA Enable. Setting this bit to EN will start the DMA - operation */ - __IOM uint32_t DMADIR : 1; /*!< [2..2] Direction */ - __IOM uint32_t DMAPRI : 2; /*!< [4..3] Sets the Priority of the DMA request */ - __IM uint32_t : 13; - __IOM uint32_t DMAPWROFF : 1; /*!< [18..18] Power off MSPI domain upon completion of DMA operation. */ - } DMACFG_b; - } ; - - union { - __IOM uint32_t DMASTAT; /*!< (@ 0x00000254) DMA Status Register */ - - struct { - __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress indicator. 1 will indicate that - a DMA transfer is active. The DMA transfer may be waiting - on data, transferring data, or waiting for priority. All - of these will be indicated with a 1. A 0 will indicate - that the DMA is fully complete and no further transactions - will be done. */ - __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete. This signals the end of the DMA - operation. */ - __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error. This active high bit signals that an error - was encountered during the DMA operation. */ - __IOM uint32_t SCRERR : 1; /*!< [3..3] Scrambling Access Alignment Error. This active high bit - signals that a scrambling operation was specified for a - non-word aligned DEVADDR. */ - } DMASTAT_b; - } ; - - union { - __IOM uint32_t DMATARGADDR; /*!< (@ 0x00000258) DMA Target Address Register */ - - struct { - __IOM uint32_t TARGADDR : 32; /*!< [31..0] Target byte address for source of DMA (either read or - write). In cases of non-word aligned addresses, the DMA - logic will take care for ensuring only the target bytes - are read/written. */ - } DMATARGADDR_b; - } ; - - union { - __IOM uint32_t DMADEVADDR; /*!< (@ 0x0000025C) DMA Device Address Register */ - - struct { - __IOM uint32_t DEVADDR : 32; /*!< [31..0] SPI Device address for automated DMA transactions (both - read and write). */ - } DMADEVADDR_b; - } ; - - union { - __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x00000260) DMA Total Transfer Count */ - - struct { - __IOM uint32_t TOTCOUNT : 16; /*!< [15..0] Total Transfer Count in bytes. */ - } DMATOTCOUNT_b; - } ; - - union { - __IOM uint32_t DMABCOUNT; /*!< (@ 0x00000264) DMA BYTE Transfer Count */ - - struct { - __IOM uint32_t BCOUNT : 8; /*!< [7..0] Burst transfer size in bytes. This is the number of bytes - transferred when a FIFO trigger event occurs. Recommended - values are 16 or 32. */ - } DMABCOUNT_b; - } ; - __IM uint32_t RESERVED4[4]; - - union { - __IOM uint32_t DMATHRESH; /*!< (@ 0x00000278) DMA Transmit Trigger Threshhold */ - - struct { - __IOM uint32_t DMATHRESH : 4; /*!< [3..0] DMA transfer FIFO level trigger. For read operations, - DMA is triggered when the FIFO level is greater than this - value. For write operations, DMA is triggered when the - FIFO level is less than this level. Each DMA operation - will consist of BCOUNT bytes. */ - } DMATHRESH_b; - } ; - __IM uint32_t RESERVED5[9]; - - union { - __IOM uint32_t CQCFG; /*!< (@ 0x000002A0) Command Queue Configuration Register */ - - struct { - __IOM uint32_t CQEN : 1; /*!< [0..0] Command queue enable. When set, will enable the processing - of the command queue */ - __IOM uint32_t CQPRI : 1; /*!< [1..1] Sets the Priority of the command queue dma request */ - __IOM uint32_t CQPWROFF : 1; /*!< [2..2] Power off MSPI domain upon completion of DMA operation. */ - __IOM uint32_t CQAUTOCLEARMASK : 1; /*!< [3..3] Eanble clear of CQMASK after each pause operation. This - may be useful when using software flags to pause CQ. */ - } CQCFG_b; - } ; - __IM uint32_t RESERVED6; - - union { - __IOM uint32_t CQADDR; /*!< (@ 0x000002A8) CQ Target Read Address Register */ - - struct { - __IOM uint32_t CQADDR : 29; /*!< [28..0] Address of command queue buffer in SRAM or flash. The - buffer address must be aligned to a word boundary. */ - } CQADDR_b; - } ; - - union { - __IOM uint32_t CQSTAT; /*!< (@ 0x000002AC) Command Queue Status Register */ - - struct { - __IOM uint32_t CQTIP : 1; /*!< [0..0] Command queue Transfer In Progress indicator. 1 will - indicate that a CQ transfer is active and this will remain - active even when paused waiting for external event. */ - __IOM uint32_t CQCPL : 1; /*!< [1..1] Command queue operation Complete. This signals the end - of the command queue operation. */ - __IOM uint32_t CQERR : 1; /*!< [2..2] Command queue processing Error. This active high bit - signals that an error was encountered during the CQ operation. */ - __IOM uint32_t CQPAUSED : 1; /*!< [3..3] Command queue is currently paused status. */ - } CQSTAT_b; - } ; - - union { - __IOM uint32_t CQFLAGS; /*!< (@ 0x000002B0) Command Queue Flag Register */ - - struct { - __IOM uint32_t CQFLAGS : 16; /*!< [15..0] Current flag status (read-only). Bits [7:0] are software - controllable and bits [15:8] are hardware status. */ - } CQFLAGS_b; - } ; - - union { - __IOM uint32_t CQSETCLEAR; /*!< (@ 0x000002B4) Command Queue Flag Set/Clear Register */ - - struct { - __IOM uint32_t CQFSET : 8; /*!< [7..0] Set CQFlag status bits. Set has priority over clear if - both are high. */ - __IOM uint32_t CQFTOGGLE : 8; /*!< [15..8] Toggle CQFlag status bits */ - __IOM uint32_t CQFCLR : 8; /*!< [23..16] Clear CQFlag status bits. */ - } CQSETCLEAR_b; - } ; - - union { - __IOM uint32_t CQPAUSE; /*!< (@ 0x000002B8) Command Queue Pause Mask Register */ - - struct { - __IOM uint32_t CQMASK : 16; /*!< [15..0] CQ will pause processing until all specified events - are satisfied. */ - } CQPAUSE_b; - } ; - __IM uint32_t RESERVED7; - - union { - __IOM uint32_t CQCURIDX; /*!< (@ 0x000002C0) Command Queue Current Index */ - - struct { - __IOM uint32_t CQCURIDX : 8; /*!< [7..0] Can be used to indicate the current position of the command - queue by having CQ operations write this field. A CQ hardware - status flag indicates when CURIDX and ENDIDX are not equal, - allowing SW to pause the CQ processing until the end index - is updated. */ - } CQCURIDX_b; - } ; - - union { - __IOM uint32_t CQENDIDX; /*!< (@ 0x000002C4) Command Queue End Index */ - - struct { - __IOM uint32_t CQENDIDX : 8; /*!< [7..0] Can be used to indicate the end position of the command - queue. A CQ hardware status bit indices when CURIDX != - ENDIDX so that the CQ can be paused when it reaches the - end pointer. */ - } CQENDIDX_b; - } ; -} MSPI_Type; /*!< Size = 712 (0x2c8) */ - - - -/* =========================================================================================================================== */ -/* ================ PDM ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief PDM Audio (PDM) - */ - -typedef struct { /*!< (@ 0x50011000) PDM Structure */ - - union { - __IOM uint32_t PCFG; /*!< (@ 0x00000000) PDM Configuration Register */ - - struct { - __IOM uint32_t PDMCOREEN : 1; /*!< [0..0] Data Streaming Control. */ - __IOM uint32_t SOFTMUTE : 1; /*!< [1..1] Soft mute control. */ - __IOM uint32_t CYCLES : 3; /*!< [4..2] Number of clocks during gain-setting changes. */ - __IOM uint32_t HPCUTOFF : 4; /*!< [8..5] High pass filter coefficients. */ - __IOM uint32_t ADCHPD : 1; /*!< [9..9] High pass filter control. */ - __IOM uint32_t SINCRATE : 7; /*!< [16..10] SINC decimation rate. */ - __IOM uint32_t MCLKDIV : 2; /*!< [18..17] PDM_CLK frequency divisor. */ - __IM uint32_t : 2; - __IOM uint32_t PGALEFT : 5; /*!< [25..21] Left channel PGA gain. */ - __IOM uint32_t PGARIGHT : 5; /*!< [30..26] Right channel PGA gain. */ - __IOM uint32_t LRSWAP : 1; /*!< [31..31] Left/right channel swap. */ - } PCFG_b; - } ; - - union { - __IOM uint32_t VCFG; /*!< (@ 0x00000004) Voice Configuration Register */ - - struct { - __IM uint32_t : 3; - __IOM uint32_t CHSET : 2; /*!< [4..3] Set PCM channels. */ - __IM uint32_t : 3; - __IOM uint32_t PCMPACK : 1; /*!< [8..8] PCM data packing enable. */ - __IM uint32_t : 7; - __IOM uint32_t SELAP : 1; /*!< [16..16] Select PDM input clock source. */ - __IOM uint32_t DMICKDEL : 1; /*!< [17..17] PDM clock sampling delay. */ - __IM uint32_t : 1; - __IOM uint32_t BCLKINV : 1; /*!< [19..19] I2S BCLK input inversion. */ - __IOM uint32_t I2SEN : 1; /*!< [20..20] I2S interface enable. */ - __IM uint32_t : 5; - __IOM uint32_t PDMCLKEN : 1; /*!< [26..26] Enable the serial clock. */ - __IOM uint32_t PDMCLKSEL : 3; /*!< [29..27] Select the PDM input clock. */ - __IOM uint32_t RSTB : 1; /*!< [30..30] Reset the IP core. */ - __IOM uint32_t IOCLKEN : 1; /*!< [31..31] Enable the IO clock. */ - } VCFG_b; - } ; - - union { - __IOM uint32_t VOICESTAT; /*!< (@ 0x00000008) Voice Status Register */ - - struct { - __IOM uint32_t FIFOCNT : 6; /*!< [5..0] Valid 32-bit entries currently in the FIFO. */ - } VOICESTAT_b; - } ; - - union { - __IOM uint32_t FIFOREAD; /*!< (@ 0x0000000C) FIFO Read */ - - struct { - __IOM uint32_t FIFOREAD : 32; /*!< [31..0] FIFO read data. */ - } FIFOREAD_b; - } ; - - union { - __IOM uint32_t FIFOFLUSH; /*!< (@ 0x00000010) FIFO Flush */ - - struct { - __IOM uint32_t FIFOFLUSH : 1; /*!< [0..0] FIFO FLUSH. */ - } FIFOFLUSH_b; - } ; - - union { - __IOM uint32_t FIFOTHR; /*!< (@ 0x00000014) FIFO Threshold */ - - struct { - __IOM uint32_t FIFOTHR : 5; /*!< [4..0] FIFO Threshold value. When the FIFO count is equal to, - or larger than this value (in words), a THR interrupt is - generated (if enabled) */ - } FIFOTHR_b; - } ; - __IM uint32_t RESERVED[122]; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000200) IO Master Interrupts: Enable */ - - struct { - __IOM uint32_t THR : 1; /*!< [0..0] This is the FIFO threshold interrupt. */ - __IOM uint32_t OVF : 1; /*!< [1..1] This is the FIFO overflow interrupt. */ - __IOM uint32_t UNDFL : 1; /*!< [2..2] This is the FIFO underflow interrupt. */ - __IOM uint32_t DCMP : 1; /*!< [3..3] DMA completed a transfer */ - __IOM uint32_t DERR : 1; /*!< [4..4] DMA Error receieved */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) IO Master Interrupts: Status */ - - struct { - __IOM uint32_t THR : 1; /*!< [0..0] This is the FIFO threshold interrupt. */ - __IOM uint32_t OVF : 1; /*!< [1..1] This is the FIFO overflow interrupt. */ - __IOM uint32_t UNDFL : 1; /*!< [2..2] This is the FIFO underflow interrupt. */ - __IOM uint32_t DCMP : 1; /*!< [3..3] DMA completed a transfer */ - __IOM uint32_t DERR : 1; /*!< [4..4] DMA Error receieved */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000208) IO Master Interrupts: Clear */ - - struct { - __IOM uint32_t THR : 1; /*!< [0..0] This is the FIFO threshold interrupt. */ - __IOM uint32_t OVF : 1; /*!< [1..1] This is the FIFO overflow interrupt. */ - __IOM uint32_t UNDFL : 1; /*!< [2..2] This is the FIFO underflow interrupt. */ - __IOM uint32_t DCMP : 1; /*!< [3..3] DMA completed a transfer */ - __IOM uint32_t DERR : 1; /*!< [4..4] DMA Error receieved */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000020C) IO Master Interrupts: Set */ - - struct { - __IOM uint32_t THR : 1; /*!< [0..0] This is the FIFO threshold interrupt. */ - __IOM uint32_t OVF : 1; /*!< [1..1] This is the FIFO overflow interrupt. */ - __IOM uint32_t UNDFL : 1; /*!< [2..2] This is the FIFO underflow interrupt. */ - __IOM uint32_t DCMP : 1; /*!< [3..3] DMA completed a transfer */ - __IOM uint32_t DERR : 1; /*!< [4..4] DMA Error receieved */ - } INTSET_b; - } ; - __IM uint32_t RESERVED1[12]; - - union { - __IOM uint32_t DMATRIGEN; /*!< (@ 0x00000240) DMA Trigger Enable Register */ - - struct { - __IOM uint32_t DTHR : 1; /*!< [0..0] Trigger DMA upon when FIFO iss filled to level indicated - by the FIFO THRESHOLD,at granularity of 16 bytes only */ - __IOM uint32_t DTHR90 : 1; /*!< [1..1] Trigger DMA at FIFO 90 percent full. This signal is also - used internally for AUTOHIP function */ - } DMATRIGEN_b; - } ; - - union { - __IOM uint32_t DMATRIGSTAT; /*!< (@ 0x00000244) DMA Trigger Status Register */ - - struct { - __IOM uint32_t DTHRSTAT : 1; /*!< [0..0] Triggered DMA from FIFO reaching threshold */ - __IOM uint32_t DTHR90STAT : 1; /*!< [1..1] Triggered DMA from FIFO reaching 90 percent full */ - } DMATRIGSTAT_b; - } ; - __IM uint32_t RESERVED2[14]; - - union { - __IOM uint32_t DMACFG; /*!< (@ 0x00000280) DMA Configuration Register */ - - struct { - __IOM uint32_t DMAEN : 1; /*!< [0..0] DMA Enable */ - __IM uint32_t : 1; - __IOM uint32_t DMADIR : 1; /*!< [2..2] Direction */ - __IM uint32_t : 5; - __IOM uint32_t DMAPRI : 1; /*!< [8..8] Sets the Priority of the DMA request */ - __IOM uint32_t DAUTOHIP : 1; /*!< [9..9] Raise priority to high on fifo full, and DMAPRI set to - low */ - __IOM uint32_t DPWROFF : 1; /*!< [10..10] Power Off the ADC System upon DMACPL. */ - } DMACFG_b; - } ; - __IM uint32_t RESERVED3; - - union { - __IOM uint32_t DMATOTCOUNT; /*!< (@ 0x00000288) DMA Total Transfer Count */ - - struct { - __IOM uint32_t TOTCOUNT : 20; /*!< [19..0] Total Transfer Count. The transfer count must be a multiple - of the THR setting to avoid DMA overruns. */ - } DMATOTCOUNT_b; - } ; - - union { - __IOM uint32_t DMATARGADDR; /*!< (@ 0x0000028C) DMA Target Address Register */ - - struct { - __IOM uint32_t LTARGADDR : 20; /*!< [19..0] DMA Target Address. This register is not updated with - the current address of the DMA, but will remain static - with the original address during the DMA transfer. */ - __IOM uint32_t UTARGADDR : 12; /*!< [31..20] SRAM Target */ - } DMATARGADDR_b; - } ; - - union { - __IOM uint32_t DMASTAT; /*!< (@ 0x00000290) DMA Status Register */ - - struct { - __IOM uint32_t DMATIP : 1; /*!< [0..0] DMA Transfer In Progress */ - __IOM uint32_t DMACPL : 1; /*!< [1..1] DMA Transfer Complete */ - __IOM uint32_t DMAERR : 1; /*!< [2..2] DMA Error */ - } DMASTAT_b; - } ; -} PDM_Type; /*!< Size = 660 (0x294) */ - - - -/* =========================================================================================================================== */ -/* ================ PWRCTRL ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief PWR Controller Register Bank (PWRCTRL) - */ - -typedef struct { /*!< (@ 0x40021000) PWRCTRL Structure */ - - union { - __IOM uint32_t SUPPLYSRC; /*!< (@ 0x00000000) Voltage Regulator Select Register */ - - struct { - __IOM uint32_t BLEBUCKEN : 1; /*!< [0..0] Enables and Selects the BLE Buck as the supply for the - BLE power domain or for Burst LDO. It takes the initial - value from Customer INFO space. Buck will be powered up - only if there is an active request for BLEH domain or Burst - mode and appropriate feature is allowed. */ - } SUPPLYSRC_b; - } ; - - union { - __IOM uint32_t SUPPLYSTATUS; /*!< (@ 0x00000004) Voltage Regulators status */ - - struct { - __IOM uint32_t SIMOBUCKON : 1; /*!< [0..0] Indicates whether the Core/Mem low-voltage domains are - supplied from the LDO or the Buck. */ - __IOM uint32_t BLEBUCKON : 1; /*!< [1..1] Indicates whether the BLE (if supported) domain and burst - (if supported) domain is supplied from the LDO or the Buck. - Buck will be powered up only if there is an active request - for BLEH domain or Burst mode and appropriate reature is - allowed. */ - } SUPPLYSTATUS_b; - } ; - - union { - __IOM uint32_t DEVPWREN; /*!< (@ 0x00000008) Device Power Enables */ - - struct { - __IOM uint32_t PWRIOS : 1; /*!< [0..0] Power up IO Slave */ - __IOM uint32_t PWRIOM0 : 1; /*!< [1..1] Power up IO Master 0 */ - __IOM uint32_t PWRIOM1 : 1; /*!< [2..2] Power up IO Master 1 */ - __IOM uint32_t PWRIOM2 : 1; /*!< [3..3] Power up IO Master 2 */ - __IOM uint32_t PWRIOM3 : 1; /*!< [4..4] Power up IO Master 3 */ - __IOM uint32_t PWRIOM4 : 1; /*!< [5..5] Power up IO Master 4 */ - __IOM uint32_t PWRIOM5 : 1; /*!< [6..6] Power up IO Master 5 */ - __IOM uint32_t PWRUART0 : 1; /*!< [7..7] Power up UART Controller 0 */ - __IOM uint32_t PWRUART1 : 1; /*!< [8..8] Power up UART Controller 1 */ - __IOM uint32_t PWRADC : 1; /*!< [9..9] Power up ADC Digital Controller */ - __IOM uint32_t PWRSCARD : 1; /*!< [10..10] Power up SCARD Controller */ - __IOM uint32_t PWRMSPI : 1; /*!< [11..11] Power up MSPI Controller */ - __IOM uint32_t PWRPDM : 1; /*!< [12..12] Power up PDM block */ - __IOM uint32_t PWRBLEL : 1; /*!< [13..13] Power up BLE controller */ - } DEVPWREN_b; - } ; - - union { - __IOM uint32_t MEMPWDINSLEEP; /*!< (@ 0x0000000C) Powerdown SRAM banks in Deep Sleep mode */ - - struct { - __IOM uint32_t DTCMPWDSLP : 3; /*!< [2..0] power down DTCM in deep sleep */ - __IOM uint32_t SRAMPWDSLP : 10; /*!< [12..3] Selects which SRAM banks are powered down in deep sleep - mode, causing the contents of the bank to be lost. */ - __IOM uint32_t FLASH0PWDSLP : 1; /*!< [13..13] Powerdown flash0 in deep sleep */ - __IOM uint32_t FLASH1PWDSLP : 1; /*!< [14..14] Powerdown flash1 in deep sleep */ - __IM uint32_t : 16; - __IOM uint32_t CACHEPWDSLP : 1; /*!< [31..31] power down cache in deep sleep */ - } MEMPWDINSLEEP_b; - } ; - - union { - __IOM uint32_t MEMPWREN; /*!< (@ 0x00000010) Enables individual banks of the MEMORY array */ - - struct { - __IOM uint32_t DTCM : 3; /*!< [2..0] Power up DTCM */ - __IOM uint32_t SRAM : 10; /*!< [12..3] Power up SRAM groups */ - __IOM uint32_t FLASH0 : 1; /*!< [13..13] Power up Flash0 */ - __IOM uint32_t FLASH1 : 1; /*!< [14..14] Power up Flash1 */ - __IM uint32_t : 15; - __IOM uint32_t CACHEB0 : 1; /*!< [30..30] Power up Cache Bank 0. This works in conjunction with - Cache enable from flash_cache module. To power up cache - bank0, cache has to be enabled and this bit has to be set. */ - __IOM uint32_t CACHEB2 : 1; /*!< [31..31] Power up Cache Bank 2. This works in conjunction with - Cache enable from flash_cache module. To power up cache - bank2, cache has to be enabled and this bit has to be set. */ - } MEMPWREN_b; - } ; - - union { - __IOM uint32_t MEMPWRSTATUS; /*!< (@ 0x00000014) Mem Power ON Status */ - - struct { - __IOM uint32_t DTCM00 : 1; /*!< [0..0] This bit is 1 if power is supplied to DTCM GROUP0_0 */ - __IOM uint32_t DTCM01 : 1; /*!< [1..1] This bit is 1 if power is supplied to DTCM GROUP0_1 */ - __IOM uint32_t DTCM1 : 1; /*!< [2..2] This bit is 1 if power is supplied to DTCM GROUP1 */ - __IOM uint32_t SRAM0 : 1; /*!< [3..3] This bit is 1 if power is supplied to SRAM GROUP0 */ - __IOM uint32_t SRAM1 : 1; /*!< [4..4] This bit is 1 if power is supplied to SRAM GROUP1 */ - __IOM uint32_t SRAM2 : 1; /*!< [5..5] This bit is 1 if power is supplied to SRAM GROUP2 */ - __IOM uint32_t SRAM3 : 1; /*!< [6..6] This bit is 1 if power is supplied to SRAM GROUP3 */ - __IOM uint32_t SRAM4 : 1; /*!< [7..7] This bit is 1 if power is supplied to SRAM GROUP4 */ - __IOM uint32_t SRAM5 : 1; /*!< [8..8] This bit is 1 if power is supplied to SRAM GROUP5 */ - __IOM uint32_t SRAM6 : 1; /*!< [9..9] This bit is 1 if power is supplied to SRAM GROUP6 */ - __IOM uint32_t SRAM7 : 1; /*!< [10..10] This bit is 1 if power is supplied to SRAM GROUP7 */ - __IOM uint32_t SRAM8 : 1; /*!< [11..11] This bit is 1 if power is supplied to SRAM GROUP8 */ - __IOM uint32_t SRAM9 : 1; /*!< [12..12] This bit is 1 if power is supplied to SRAM GROUP9 */ - __IOM uint32_t FLASH0 : 1; /*!< [13..13] This bit is 1 if power is supplied to FLASH 0 */ - __IOM uint32_t FLASH1 : 1; /*!< [14..14] This bit is 1 if power is supplied to FLASH 1 */ - __IOM uint32_t CACHEB0 : 1; /*!< [15..15] This bit is 1 if power is supplied to Cache Bank 0 */ - __IOM uint32_t CACHEB2 : 1; /*!< [16..16] This bit is 1 if power is supplied to Cache Bank 2 */ - } MEMPWRSTATUS_b; - } ; - - union { - __IOM uint32_t DEVPWRSTATUS; /*!< (@ 0x00000018) Device Power ON Status */ - - struct { - __IOM uint32_t MCUL : 1; /*!< [0..0] This bit is 1 if power is supplied to MCUL */ - __IOM uint32_t MCUH : 1; /*!< [1..1] This bit is 1 if power is supplied to MCUH */ - __IOM uint32_t HCPA : 1; /*!< [2..2] This bit is 1 if power is supplied to HCPA domain (IO - SLAVE, UART0, UART1, SCARD) */ - __IOM uint32_t HCPB : 1; /*!< [3..3] This bit is 1 if power is supplied to HCPB domain (IO - MASTER 0, 1, 2) */ - __IOM uint32_t HCPC : 1; /*!< [4..4] This bit is 1 if power is supplied to HCPC domain (IO - MASTER4, 5, 6) */ - __IOM uint32_t PWRADC : 1; /*!< [5..5] This bit is 1 if power is supplied to ADC */ - __IOM uint32_t PWRMSPI : 1; /*!< [6..6] This bit is 1 if power is supplied to MSPI */ - __IOM uint32_t PWRPDM : 1; /*!< [7..7] This bit is 1 if power is supplied to PDM */ - __IOM uint32_t BLEL : 1; /*!< [8..8] This bit is 1 if power is supplied to BLEL */ - __IOM uint32_t BLEH : 1; /*!< [9..9] This bit is 1 if power is supplied to BLEH */ - __IM uint32_t : 19; - __IOM uint32_t CORESLEEP : 1; /*!< [29..29] This bit is 1 if CORE has been in SLEEP State. Write - '1' to this bit to clear it. */ - __IOM uint32_t COREDEEPSLEEP : 1; /*!< [30..30] This bit is 1 if CORE has been in Deep Sleep. Write - '1' to this bit to clear it. */ - __IOM uint32_t SYSDEEPSLEEP : 1; /*!< [31..31] This bit is 1 if SYSTEM has been in Deep Sleep. Write - '1' to this bit to clear it. */ - } DEVPWRSTATUS_b; - } ; - - union { - __IOM uint32_t SRAMCTRL; /*!< (@ 0x0000001C) SRAM Control register */ - - struct { - __IM uint32_t : 1; - __IOM uint32_t SRAMCLKGATE : 1; /*!< [1..1] This bit is 1 if clock gating is allowed for individual - system SRAMs */ - __IOM uint32_t SRAMMASTERCLKGATE : 1; /*!< [2..2] This bit is 1 when the master clock gate is enabled (top-level - clock gate for entire SRAM block) */ - __IM uint32_t : 5; - __IOM uint32_t SRAMLIGHTSLEEP : 12; /*!< [19..8] Light Sleep enable for each TCM/SRAM bank. When 1, corresponding - bank will be put into light sleep. For optimal power, banks - should be put into light sleep while the system is active - but the bank has minimal or no accesses. */ - } SRAMCTRL_b; - } ; - - union { - __IOM uint32_t ADCSTATUS; /*!< (@ 0x00000020) Power Status Register for ADC Block */ - - struct { - __IOM uint32_t ADCPWD : 1; /*!< [0..0] This bit indicates that the ADC is powered down */ - __IOM uint32_t BGTPWD : 1; /*!< [1..1] This bit indicates that the ADC Band Gap is powered down */ - __IOM uint32_t VPTATPWD : 1; /*!< [2..2] This bit indicates that the ADC temperature sensor input - buffer is powered down */ - __IOM uint32_t VBATPWD : 1; /*!< [3..3] This bit indicates that the ADC VBAT resistor divider - is powered down */ - __IOM uint32_t REFKEEPPWD : 1; /*!< [4..4] This bit indicates that the ADC REFKEEP is powered down */ - __IOM uint32_t REFBUFPWD : 1; /*!< [5..5] This bit indicates that the ADC REFBUF is powered down */ - } ADCSTATUS_b; - } ; - - union { - __IOM uint32_t MISC; /*!< (@ 0x00000024) Power Optimization Control Bits */ - - struct { - __IOM uint32_t SIMOBUCKEN : 1; /*!< [0..0] Enables and Selects the SIMO Buck as the supply for the - low-voltage power domain. It takes the initial value from - the bit set in Customer INFO space. */ - __IOM uint32_t FORCECOREVRLPPDM : 1; /*!< [1..1] Control bit to enable the core VR to go into LP mode - with HCPA/B/C/MSPI are powered off but PDM is powered on */ - __IOM uint32_t FORCECOREVRLPTIMERS : 1; /*!< [2..2] Control Bit to force Core VR to LP mode in deep sleep - even when hfrc based ctimer or stimer is running. */ - __IOM uint32_t FORCEMEMVRLPTIMERS : 1; /*!< [3..3] Control Bit to force Mem VR to LP mode in deep sleep - even when hfrc based ctimer or stimer is running. */ - __IOM uint32_t FORCEMEMVRADC : 2; /*!< [5..4] Control Bit to force mem VR to LP or ACT mode in deep - sleep when ADC is powered ON. 0x3 results in picking LP - mode. */ - __IOM uint32_t MEMVRLPBLE : 1; /*!< [6..6] Control Bit to let Mem VR go to lp mode in deep sleep - even when BLEL or BLEH is powered on given none of the - other domains require it. */ - __IOM uint32_t FORCEBLEBUCKACT : 1; /*!< [7..7] Control Bit to enable BLE Buck to be in active state - when BLE Buck is enabled. Default behavior is to be in - active only when Burst or BLEH power on are requested. */ - } MISC_b; - } ; - - union { - __IOM uint32_t DEVPWREVENTEN; /*!< (@ 0x00000028) Event enable register to control which DEVPWRSTATUS - bits are routed to event input of CPU. */ - - struct { - __IOM uint32_t MCULEVEN : 1; /*!< [0..0] Control MCUL power-on status event */ - __IOM uint32_t MCUHEVEN : 1; /*!< [1..1] Control MCUH power-on status event */ - __IOM uint32_t HCPAEVEN : 1; /*!< [2..2] Control HCPA power-on status event */ - __IOM uint32_t HCPBEVEN : 1; /*!< [3..3] Control HCPB power-on status event */ - __IOM uint32_t HCPCEVEN : 1; /*!< [4..4] Control HCPC power-on status event */ - __IOM uint32_t ADCEVEN : 1; /*!< [5..5] Control ADC power-on status event */ - __IOM uint32_t MSPIEVEN : 1; /*!< [6..6] Control MSPI power-on status event */ - __IOM uint32_t PDMEVEN : 1; /*!< [7..7] Control PDM power-on status event */ - __IOM uint32_t BLELEVEN : 1; /*!< [8..8] Control BLE power-on status event */ - __IM uint32_t : 20; - __IOM uint32_t BLEFEATUREEVEN : 1; /*!< [29..29] Control BLEFEATURE status event */ - __IOM uint32_t BURSTFEATUREEVEN : 1; /*!< [30..30] Control BURSTFEATURE status event */ - __IOM uint32_t BURSTEVEN : 1; /*!< [31..31] Control BURST status event */ - } DEVPWREVENTEN_b; - } ; - - union { - __IOM uint32_t MEMPWREVENTEN; /*!< (@ 0x0000002C) Event enable register to control which MEMPWRSTATUS - bits are routed to event input of CPU. */ - - struct { - __IOM uint32_t DTCMEN : 3; /*!< [2..0] Enable DTCM power-on status event */ - __IOM uint32_t SRAMEN : 10; /*!< [12..3] Control SRAM power-on status event */ - __IOM uint32_t FLASH0EN : 1; /*!< [13..13] Control Flash power-on status event */ - __IOM uint32_t FLASH1EN : 1; /*!< [14..14] Control Flash power-on status event */ - __IM uint32_t : 15; - __IOM uint32_t CACHEB0EN : 1; /*!< [30..30] Control CACHE BANK 0 power-on status event */ - __IOM uint32_t CACHEB2EN : 1; /*!< [31..31] Control CACHEB2 power-on status event */ - } MEMPWREVENTEN_b; - } ; -} PWRCTRL_Type; /*!< Size = 48 (0x30) */ - - - -/* =========================================================================================================================== */ -/* ================ RSTGEN ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief MCU Reset Generator (RSTGEN) - */ - -typedef struct { /*!< (@ 0x40000000) RSTGEN Structure */ - - union { - __IOM uint32_t CFG; /*!< (@ 0x00000000) Configuration Register */ - - struct { - __IOM uint32_t BODHREN : 1; /*!< [0..0] Brown out high (2.1v) reset enable. */ - __IOM uint32_t WDREN : 1; /*!< [1..1] Watchdog Timer Reset Enable. NOTE: The WDT module must - also be configured for WDT reset. This includes enabling - the RESEN bit in WDTCFG register in Watch dog timer block. */ - } CFG_b; - } ; - - union { - __IOM uint32_t SWPOI; /*!< (@ 0x00000004) Software POI Reset */ - - struct { - __IOM uint32_t SWPOIKEY : 8; /*!< [7..0] 0x1B generates a software POI reset. This is a write-only - register. Reading from this register will yield only all - 0s. */ - } SWPOI_b; - } ; - - union { - __IOM uint32_t SWPOR; /*!< (@ 0x00000008) Software POR Reset */ - - struct { - __IOM uint32_t SWPORKEY : 8; /*!< [7..0] 0xD4 generates a software POR reset. */ - } SWPOR_b; - } ; - __IM uint32_t RESERVED[2]; - - union { - __IOM uint32_t TPIURST; /*!< (@ 0x00000014) TPIU reset */ - - struct { - __IOM uint32_t TPIURST : 1; /*!< [0..0] Static reset for the TPIU. Write to '1' to assert reset - to TPIU. Write to '0' to clear the reset. */ - } TPIURST_b; - } ; - __IM uint32_t RESERVED1[122]; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000200) Reset Interrupt register: Enable */ - - struct { - __IOM uint32_t BODH : 1; /*!< [0..0] Enables an interrupt that triggers when VCC is below - BODH level. */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) Reset Interrupt register: Status */ - - struct { - __IOM uint32_t BODH : 1; /*!< [0..0] Enables an interrupt that triggers when VCC is below - BODH level. */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000208) Reset Interrupt register: Clear */ - - struct { - __IOM uint32_t BODH : 1; /*!< [0..0] Enables an interrupt that triggers when VCC is below - BODH level. */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000020C) Reset Interrupt register: Set */ - - struct { - __IOM uint32_t BODH : 1; /*!< [0..0] Enables an interrupt that triggers when VCC is below - BODH level. */ - } INTSET_b; - } ; - __IM uint32_t RESERVED2[67107708]; - - union { - __IOM uint32_t STAT; /*!< (@ 0x0FFFF000) Status Register (SBL) */ - - struct { - __IOM uint32_t EXRSTAT : 1; /*!< [0..0] Reset was initiated by an External Reset (SBL). */ - __IOM uint32_t PORSTAT : 1; /*!< [1..1] Reset was initiated by a Power-On Reset (SBL). */ - __IOM uint32_t BORSTAT : 1; /*!< [2..2] Reset was initiated by a Brown-Out Reset (SBL). */ - __IOM uint32_t SWRSTAT : 1; /*!< [3..3] Reset was a initiated by SW POR or AIRCR Reset (SBL). */ - __IOM uint32_t POIRSTAT : 1; /*!< [4..4] Reset was a initiated by Software POI Reset (SBL). */ - __IOM uint32_t DBGRSTAT : 1; /*!< [5..5] Reset was a initiated by Debugger Reset (SBL). */ - __IOM uint32_t WDRSTAT : 1; /*!< [6..6] Reset was initiated by a Watchdog Timer Reset (SBL). */ - __IOM uint32_t BOUSTAT : 1; /*!< [7..7] An Unregulated Supply Brownout Event occurred (SBL). */ - __IOM uint32_t BOCSTAT : 1; /*!< [8..8] A Core Regulator Brownout Event occurred (SBL). */ - __IOM uint32_t BOFSTAT : 1; /*!< [9..9] A Memory Regulator Brownout Event occurred (SBL). */ - __IOM uint32_t BOBSTAT : 1; /*!< [10..10] A BLE/Burst Regulator Brownout Event occurred (SBL). */ - __IM uint32_t : 19; - __IOM uint32_t FBOOT : 1; /*!< [30..30] Set if current boot was initiated by soft reset and - resulted in Fast Boot (SBL). */ - __IOM uint32_t SBOOT : 1; /*!< [31..31] Set when booting securely (SBL). */ - } STAT_b; - } ; -} RSTGEN_Type; /*!< Size = 268431364 (0xffff004) */ - - - -/* =========================================================================================================================== */ -/* ================ RTC ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Real Time Clock (RTC) - */ - -typedef struct { /*!< (@ 0x40004200) RTC Structure */ - __IM uint32_t RESERVED[16]; - - union { - __IOM uint32_t CTRLOW; /*!< (@ 0x00000040) RTC Counters Lower */ - - struct { - __IOM uint32_t CTR100 : 8; /*!< [7..0] 100ths of a second Counter */ - __IOM uint32_t CTRSEC : 7; /*!< [14..8] Seconds Counter */ - __IM uint32_t : 1; - __IOM uint32_t CTRMIN : 7; /*!< [22..16] Minutes Counter */ - __IM uint32_t : 1; - __IOM uint32_t CTRHR : 6; /*!< [29..24] Hours Counter */ - } CTRLOW_b; - } ; - - union { - __IOM uint32_t CTRUP; /*!< (@ 0x00000044) RTC Counters Upper */ - - struct { - __IOM uint32_t CTRDATE : 6; /*!< [5..0] Date Counter */ - __IM uint32_t : 2; - __IOM uint32_t CTRMO : 5; /*!< [12..8] Months Counter */ - __IM uint32_t : 3; - __IOM uint32_t CTRYR : 8; /*!< [23..16] Years Counter */ - __IOM uint32_t CTRWKDY : 3; /*!< [26..24] Weekdays Counter */ - __IOM uint32_t CB : 1; /*!< [27..27] Century */ - __IOM uint32_t CEB : 1; /*!< [28..28] Century enable */ - __IM uint32_t : 2; - __IOM uint32_t CTERR : 1; /*!< [31..31] Counter read error status. Error is triggered when - software reads the lower word of the counters, and fails - to read the upper counter within 1/100 second. This is - because when the lower counter is read, the upper counter - is held off from incrementing until it is read so that - the full time stamp can be read. */ - } CTRUP_b; - } ; - - union { - __IOM uint32_t ALMLOW; /*!< (@ 0x00000048) RTC Alarms Lower */ - - struct { - __IOM uint32_t ALM100 : 8; /*!< [7..0] 100ths of a second Alarm */ - __IOM uint32_t ALMSEC : 7; /*!< [14..8] Seconds Alarm */ - __IM uint32_t : 1; - __IOM uint32_t ALMMIN : 7; /*!< [22..16] Minutes Alarm */ - __IM uint32_t : 1; - __IOM uint32_t ALMHR : 6; /*!< [29..24] Hours Alarm */ - } ALMLOW_b; - } ; - - union { - __IOM uint32_t ALMUP; /*!< (@ 0x0000004C) RTC Alarms Upper */ - - struct { - __IOM uint32_t ALMDATE : 6; /*!< [5..0] Date Alarm */ - __IM uint32_t : 2; - __IOM uint32_t ALMMO : 5; /*!< [12..8] Months Alarm */ - __IM uint32_t : 3; - __IOM uint32_t ALMWKDY : 3; /*!< [18..16] Weekdays Alarm */ - } ALMUP_b; - } ; - - union { - __IOM uint32_t RTCCTL; /*!< (@ 0x00000050) RTC Control Register */ - - struct { - __IOM uint32_t WRTC : 1; /*!< [0..0] Counter write control */ - __IOM uint32_t RPT : 3; /*!< [3..1] Alarm repeat interval */ - __IOM uint32_t RSTOP : 1; /*!< [4..4] RTC input clock control */ - __IOM uint32_t HR1224 : 1; /*!< [5..5] Hours Counter mode */ - } RTCCTL_b; - } ; - __IM uint32_t RESERVED1[43]; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000100) RTC Interrupt Register: Enable */ - - struct { - __IOM uint32_t ALM : 1; /*!< [0..0] RTC Alarm interrupt */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000104) RTC Interrupt Register: Status */ - - struct { - __IOM uint32_t ALM : 1; /*!< [0..0] RTC Alarm interrupt */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000108) RTC Interrupt Register: Clear */ - - struct { - __IOM uint32_t ALM : 1; /*!< [0..0] RTC Alarm interrupt */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000010C) RTC Interrupt Register: Set */ - - struct { - __IOM uint32_t ALM : 1; /*!< [0..0] RTC Alarm interrupt */ - } INTSET_b; - } ; -} RTC_Type; /*!< Size = 272 (0x110) */ - - - -/* =========================================================================================================================== */ -/* ================ SCARD ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Serial ISO7816 (SCARD) - */ - -typedef struct { /*!< (@ 0x40080000) SCARD Structure */ - - union { - __IOM uint32_t SR; /*!< (@ 0x00000000) ISO7816 interrupt status */ - - struct { - __IOM uint32_t FNE : 1; /*!< [0..0] RX FIFO not empty. */ - __IOM uint32_t TBERBF : 1; /*!< [1..1] FIFO empty (transmit) or full (receive). */ - __IOM uint32_t FER : 1; /*!< [2..2] Framing error. */ - __IOM uint32_t OVR : 1; /*!< [3..3] RX FIFO overflow. */ - __IOM uint32_t PE : 1; /*!< [4..4] Parity Error. */ - __IOM uint32_t FT2REND : 1; /*!< [5..5] TX to RX finished. */ - __IOM uint32_t FHF : 1; /*!< [6..6] FIFO Half Full. */ - } SR_b; - } ; - __IM uint32_t RESERVED[3]; - - union { - __IOM uint32_t DR; /*!< (@ 0x00000010) ISO7816 data */ - - struct { - __IOM uint32_t DR : 8; /*!< [7..0] Data register. */ - } DR_b; - } ; - __IM uint32_t RESERVED1[3]; - - union { - __IOM uint32_t SR1; /*!< (@ 0x00000020) ISO7816 interrupt status 1 */ - - struct { - __IOM uint32_t ECNTOVER : 1; /*!< [0..0] ETU counter overflow. */ - __IOM uint32_t PRL : 1; /*!< [1..1] Card insert/remove. */ - __IOM uint32_t SYNCEND : 1; /*!< [2..2] Write complete synchronization. */ - __IOM uint32_t IDLE : 1; /*!< [3..3] ISO7816 idle. */ - } SR1_b; - } ; - __IM uint32_t RESERVED2[5]; - - union { - __IOM uint32_t RETXCNTRMI; /*!< (@ 0x00000038) ISO7816 resent count inquiry */ - - struct { - __IOM uint32_t RETXCNTRMI : 4; /*!< [3..0] Resent count inquiry register. */ - } RETXCNTRMI_b; - } ; - __IM uint32_t RESERVED3[49]; - - union { - __IOM uint32_t CLKCTRL; /*!< (@ 0x00000100) Clock Control */ - - struct { - __IOM uint32_t CLKEN : 1; /*!< [0..0] Enable the serial source clock for SCARD. */ - __IOM uint32_t APBCLKEN : 1; /*!< [1..1] Enable the SCARD APB clock to run continuously. */ - } CLKCTRL_b; - } ; -} SCARD_Type; /*!< Size = 260 (0x104) */ - - - -/* =========================================================================================================================== */ -/* ================ SECURITY ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Security Interfaces (SECURITY) - */ - -typedef struct { /*!< (@ 0x40030000) SECURITY Structure */ - - union { - __IOM uint32_t CTRL; /*!< (@ 0x00000000) Control Register */ - - struct { - __IOM uint32_t ENABLE : 1; /*!< [0..0] Function Enable. Software should set the ENABLE bit to - initiate a CRC operation. Hardware will clear the ENABLE - bit upon completion. */ - __IM uint32_t : 3; - __IOM uint32_t FUNCTION : 4; /*!< [7..4] Function Select */ - __IM uint32_t : 23; - __IOM uint32_t CRCERROR : 1; /*!< [31..31] CRC Error Status - Set to 1 if an error occurs during - a CRC operation. Cleared when CTRL register is written - (with any value). Usually indicates an invalid address - range. */ - } CTRL_b; - } ; - __IM uint32_t RESERVED[3]; - - union { - __IOM uint32_t SRCADDR; /*!< (@ 0x00000010) Source Addresss */ - - struct { - __IOM uint32_t ADDR : 32; /*!< [31..0] Source Buffer Address. Address may be byte aligned, - but the length must be a multiple of 4 bits. */ - } SRCADDR_b; - } ; - __IM uint32_t RESERVED1[3]; - - union { - __IOM uint32_t LEN; /*!< (@ 0x00000020) Length */ - - struct { - __IM uint32_t : 2; - __IOM uint32_t LEN : 18; /*!< [19..2] Buffer size (bottom two bits assumed to be zero to ensure - a multiple of 4 bytes) */ - } LEN_b; - } ; - __IM uint32_t RESERVED2[3]; - - union { - __IOM uint32_t RESULT; /*!< (@ 0x00000030) CRC Seed/Result Register */ - - struct { - __IOM uint32_t CRC : 32; /*!< [31..0] CRC Seed/Result. Software must seed the CRC with 0xFFFFFFFF - before starting a CRC operation (unless the CRC is continued - from a previous operation). */ - } RESULT_b; - } ; - __IM uint32_t RESERVED3[17]; - - union { - __IOM uint32_t LOCKCTRL; /*!< (@ 0x00000078) LOCK Control Register */ - - struct { - __IOM uint32_t SELECT : 8; /*!< [7..0] LOCK Function Select register. */ - } LOCKCTRL_b; - } ; - - union { - __IOM uint32_t LOCKSTAT; /*!< (@ 0x0000007C) LOCK Status Register */ - - struct { - __IOM uint32_t STATUS : 32; /*!< [31..0] LOCK Status register. This register is a bitmask for - which resources are currently unlocked. These bits are - one-hot per resource. */ - } LOCKSTAT_b; - } ; - - union { - __IOM uint32_t KEY0; /*!< (@ 0x00000080) Key0 Register */ - - struct { - __IOM uint32_t KEY0 : 32; /*!< [31..0] Bits [31:0] of the 128-bit key should be written to - this register. To protect key values, the register always - returns 0x00000000. */ - } KEY0_b; - } ; - - union { - __IOM uint32_t KEY1; /*!< (@ 0x00000084) Key1 Register */ - - struct { - __IOM uint32_t KEY1 : 32; /*!< [31..0] Bits [63:32] of the 128-bit key should be written to - this register. To protect key values, the register always - returns 0x00000000. */ - } KEY1_b; - } ; - - union { - __IOM uint32_t KEY2; /*!< (@ 0x00000088) Key2 Register */ - - struct { - __IOM uint32_t KEY2 : 32; /*!< [31..0] Bits [95:64] of the 128-bit key should be written to - this register. To protect key values, the register always - returns 0x00000000. */ - } KEY2_b; - } ; - - union { - __IOM uint32_t KEY3; /*!< (@ 0x0000008C) Key3 Register */ - - struct { - __IOM uint32_t KEY3 : 32; /*!< [31..0] Bits [127:96] of the 128-bit key should be written to - this register. To protect key values, the register always - returns 0x00000000. */ - } KEY3_b; - } ; -} SECURITY_Type; /*!< Size = 144 (0x90) */ - - - -/* =========================================================================================================================== */ -/* ================ UART0 ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Serial UART (UART0) - */ - -typedef struct { /*!< (@ 0x4001C000) UART0 Structure */ - - union { - __IOM uint32_t DR; /*!< (@ 0x00000000) UART Data Register */ - - struct { - __IOM uint32_t DATA : 8; /*!< [7..0] This is the UART data port. */ - __IOM uint32_t FEDATA : 1; /*!< [8..8] This is the framing error indicator. */ - __IOM uint32_t PEDATA : 1; /*!< [9..9] This is the parity error indicator. */ - __IOM uint32_t BEDATA : 1; /*!< [10..10] This is the break error indicator. */ - __IOM uint32_t OEDATA : 1; /*!< [11..11] This is the overrun error indicator. */ - } DR_b; - } ; - - union { - __IOM uint32_t RSR; /*!< (@ 0x00000004) UART Status Register */ - - struct { - __IOM uint32_t FESTAT : 1; /*!< [0..0] This is the framing error indicator. */ - __IOM uint32_t PESTAT : 1; /*!< [1..1] This is the parity error indicator. */ - __IOM uint32_t BESTAT : 1; /*!< [2..2] This is the break error indicator. */ - __IOM uint32_t OESTAT : 1; /*!< [3..3] This is the overrun error indicator. */ - } RSR_b; - } ; - __IM uint32_t RESERVED[4]; - - union { - __IOM uint32_t FR; /*!< (@ 0x00000018) Flag Register */ - - struct { - __IOM uint32_t CTS : 1; /*!< [0..0] This bit holds the clear to send indicator. */ - __IOM uint32_t DSR : 1; /*!< [1..1] This bit holds the data set ready indicator. */ - __IOM uint32_t DCD : 1; /*!< [2..2] This bit holds the data carrier detect indicator. */ - __IOM uint32_t BUSY : 1; /*!< [3..3] This bit holds the busy indicator. */ - __IOM uint32_t RXFE : 1; /*!< [4..4] This bit holds the receive FIFO empty indicator. */ - __IOM uint32_t TXFF : 1; /*!< [5..5] This bit holds the transmit FIFO full indicator. */ - __IOM uint32_t RXFF : 1; /*!< [6..6] This bit holds the receive FIFO full indicator. */ - __IOM uint32_t TXFE : 1; /*!< [7..7] This bit holds the transmit FIFO empty indicator. */ - __IOM uint32_t TXBUSY : 1; /*!< [8..8] This bit holds the transmit BUSY indicator. */ - } FR_b; - } ; - __IM uint32_t RESERVED1; - - union { - __IOM uint32_t ILPR; /*!< (@ 0x00000020) IrDA Counter */ - - struct { - __IOM uint32_t ILPDVSR : 8; /*!< [7..0] These bits hold the IrDA counter divisor. */ - } ILPR_b; - } ; - - union { - __IOM uint32_t IBRD; /*!< (@ 0x00000024) Integer Baud Rate Divisor */ - - struct { - __IOM uint32_t DIVINT : 16; /*!< [15..0] These bits hold the baud integer divisor. */ - } IBRD_b; - } ; - - union { - __IOM uint32_t FBRD; /*!< (@ 0x00000028) Fractional Baud Rate Divisor */ - - struct { - __IOM uint32_t DIVFRAC : 6; /*!< [5..0] These bits hold the baud fractional divisor. */ - } FBRD_b; - } ; - - union { - __IOM uint32_t LCRH; /*!< (@ 0x0000002C) Line Control High */ - - struct { - __IOM uint32_t BRK : 1; /*!< [0..0] This bit holds the break set. */ - __IOM uint32_t PEN : 1; /*!< [1..1] This bit holds the parity enable. */ - __IOM uint32_t EPS : 1; /*!< [2..2] This bit holds the even parity select. */ - __IOM uint32_t STP2 : 1; /*!< [3..3] This bit holds the two stop bits select. */ - __IOM uint32_t FEN : 1; /*!< [4..4] This bit holds the FIFO enable. */ - __IOM uint32_t WLEN : 2; /*!< [6..5] These bits hold the write length. */ - __IOM uint32_t SPS : 1; /*!< [7..7] This bit holds the stick parity select. */ - } LCRH_b; - } ; - - union { - __IOM uint32_t CR; /*!< (@ 0x00000030) Control Register */ - - struct { - __IOM uint32_t UARTEN : 1; /*!< [0..0] This bit is the UART enable. */ - __IOM uint32_t SIREN : 1; /*!< [1..1] This bit is the SIR ENDEC enable. */ - __IOM uint32_t SIRLP : 1; /*!< [2..2] This bit is the SIR low power select. */ - __IOM uint32_t CLKEN : 1; /*!< [3..3] This bit is the UART clock enable. */ - __IOM uint32_t CLKSEL : 3; /*!< [6..4] This bitfield is the UART clock select. */ - __IOM uint32_t LBE : 1; /*!< [7..7] This bit is the loopback enable. */ - __IOM uint32_t TXE : 1; /*!< [8..8] This bit is the transmit enable. */ - __IOM uint32_t RXE : 1; /*!< [9..9] This bit is the receive enable. */ - __IOM uint32_t DTR : 1; /*!< [10..10] This bit enables data transmit ready. */ - __IOM uint32_t RTS : 1; /*!< [11..11] This bit enables request to send. */ - __IOM uint32_t OUT1 : 1; /*!< [12..12] This bit holds modem Out1. */ - __IOM uint32_t OUT2 : 1; /*!< [13..13] This bit holds modem Out2. */ - __IOM uint32_t RTSEN : 1; /*!< [14..14] This bit enables RTS hardware flow control. */ - __IOM uint32_t CTSEN : 1; /*!< [15..15] This bit enables CTS hardware flow control. */ - } CR_b; - } ; - - union { - __IOM uint32_t IFLS; /*!< (@ 0x00000034) FIFO Interrupt Level Select */ - - struct { - __IOM uint32_t TXIFLSEL : 3; /*!< [2..0] These bits hold the transmit FIFO interrupt level. */ - __IOM uint32_t RXIFLSEL : 3; /*!< [5..3] These bits hold the receive FIFO interrupt level. */ - } IFLS_b; - } ; - - union { - __IOM uint32_t IER; /*!< (@ 0x00000038) Interrupt Enable */ - - struct { - __IOM uint32_t TXCMPMIM : 1; /*!< [0..0] This bit holds the modem TXCMP interrupt enable. */ - __IOM uint32_t CTSMIM : 1; /*!< [1..1] This bit holds the modem CTS interrupt enable. */ - __IOM uint32_t DCDMIM : 1; /*!< [2..2] This bit holds the modem DCD interrupt enable. */ - __IOM uint32_t DSRMIM : 1; /*!< [3..3] This bit holds the modem DSR interrupt enable. */ - __IOM uint32_t RXIM : 1; /*!< [4..4] This bit holds the receive interrupt enable. */ - __IOM uint32_t TXIM : 1; /*!< [5..5] This bit holds the transmit interrupt enable. */ - __IOM uint32_t RTIM : 1; /*!< [6..6] This bit holds the receive timeout interrupt enable. */ - __IOM uint32_t FEIM : 1; /*!< [7..7] This bit holds the framing error interrupt enable. */ - __IOM uint32_t PEIM : 1; /*!< [8..8] This bit holds the parity error interrupt enable. */ - __IOM uint32_t BEIM : 1; /*!< [9..9] This bit holds the break error interrupt enable. */ - __IOM uint32_t OEIM : 1; /*!< [10..10] This bit holds the overflow interrupt enable. */ - } IER_b; - } ; - - union { - __IOM uint32_t IES; /*!< (@ 0x0000003C) Interrupt Status */ - - struct { - __IOM uint32_t TXCMPMRIS : 1; /*!< [0..0] This bit holds the modem TXCMP interrupt status. */ - __IOM uint32_t CTSMRIS : 1; /*!< [1..1] This bit holds the modem CTS interrupt status. */ - __IOM uint32_t DCDMRIS : 1; /*!< [2..2] This bit holds the modem DCD interrupt status. */ - __IOM uint32_t DSRMRIS : 1; /*!< [3..3] This bit holds the modem DSR interrupt status. */ - __IOM uint32_t RXRIS : 1; /*!< [4..4] This bit holds the receive interrupt status. */ - __IOM uint32_t TXRIS : 1; /*!< [5..5] This bit holds the transmit interrupt status. */ - __IOM uint32_t RTRIS : 1; /*!< [6..6] This bit holds the receive timeout interrupt status. */ - __IOM uint32_t FERIS : 1; /*!< [7..7] This bit holds the framing error interrupt status. */ - __IOM uint32_t PERIS : 1; /*!< [8..8] This bit holds the parity error interrupt status. */ - __IOM uint32_t BERIS : 1; /*!< [9..9] This bit holds the break error interrupt status. */ - __IOM uint32_t OERIS : 1; /*!< [10..10] This bit holds the overflow interrupt status. */ - } IES_b; - } ; - - union { - __IOM uint32_t MIS; /*!< (@ 0x00000040) Masked Interrupt Status */ - - struct { - __IOM uint32_t TXCMPMMIS : 1; /*!< [0..0] This bit holds the modem TXCMP interrupt status masked. */ - __IOM uint32_t CTSMMIS : 1; /*!< [1..1] This bit holds the modem CTS interrupt status masked. */ - __IOM uint32_t DCDMMIS : 1; /*!< [2..2] This bit holds the modem DCD interrupt status masked. */ - __IOM uint32_t DSRMMIS : 1; /*!< [3..3] This bit holds the modem DSR interrupt status masked. */ - __IOM uint32_t RXMIS : 1; /*!< [4..4] This bit holds the receive interrupt status masked. */ - __IOM uint32_t TXMIS : 1; /*!< [5..5] This bit holds the transmit interrupt status masked. */ - __IOM uint32_t RTMIS : 1; /*!< [6..6] This bit holds the receive timeout interrupt status masked. */ - __IOM uint32_t FEMIS : 1; /*!< [7..7] This bit holds the framing error interrupt status masked. */ - __IOM uint32_t PEMIS : 1; /*!< [8..8] This bit holds the parity error interrupt status masked. */ - __IOM uint32_t BEMIS : 1; /*!< [9..9] This bit holds the break error interrupt status masked. */ - __IOM uint32_t OEMIS : 1; /*!< [10..10] This bit holds the overflow interrupt status masked. */ - } MIS_b; - } ; - - union { - __IOM uint32_t IEC; /*!< (@ 0x00000044) Interrupt Clear */ - - struct { - __IOM uint32_t TXCMPMIC : 1; /*!< [0..0] This bit holds the modem TXCMP interrupt clear. */ - __IOM uint32_t CTSMIC : 1; /*!< [1..1] This bit holds the modem CTS interrupt clear. */ - __IOM uint32_t DCDMIC : 1; /*!< [2..2] This bit holds the modem DCD interrupt clear. */ - __IOM uint32_t DSRMIC : 1; /*!< [3..3] This bit holds the modem DSR interrupt clear. */ - __IOM uint32_t RXIC : 1; /*!< [4..4] This bit holds the receive interrupt clear. */ - __IOM uint32_t TXIC : 1; /*!< [5..5] This bit holds the transmit interrupt clear. */ - __IOM uint32_t RTIC : 1; /*!< [6..6] This bit holds the receive timeout interrupt clear. */ - __IOM uint32_t FEIC : 1; /*!< [7..7] This bit holds the framing error interrupt clear. */ - __IOM uint32_t PEIC : 1; /*!< [8..8] This bit holds the parity error interrupt clear. */ - __IOM uint32_t BEIC : 1; /*!< [9..9] This bit holds the break error interrupt clear. */ - __IOM uint32_t OEIC : 1; /*!< [10..10] This bit holds the overflow interrupt clear. */ - } IEC_b; - } ; -} UART0_Type; /*!< Size = 72 (0x48) */ - - - -/* =========================================================================================================================== */ -/* ================ VCOMP ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Voltage Comparator (VCOMP) - */ - -typedef struct { /*!< (@ 0x4000C000) VCOMP Structure */ - - union { - __IOM uint32_t CFG; /*!< (@ 0x00000000) Configuration Register */ - - struct { - __IOM uint32_t PSEL : 2; /*!< [1..0] This bitfield selects the positive input to the comparator. */ - __IM uint32_t : 6; - __IOM uint32_t NSEL : 2; /*!< [9..8] This bitfield selects the negative input to the comparator. */ - __IM uint32_t : 6; - __IOM uint32_t LVLSEL : 4; /*!< [19..16] When the reference input NSEL is set to NSEL_DAC, this - bitfield selects the voltage level for the negative input - to the comparator. */ - } CFG_b; - } ; - - union { - __IOM uint32_t STAT; /*!< (@ 0x00000004) Status Register */ - - struct { - __IOM uint32_t CMPOUT : 1; /*!< [0..0] This bit is 1 if the positive input of the comparator - is greater than the negative input. */ - __IOM uint32_t PWDSTAT : 1; /*!< [1..1] This bit indicates the power down state of the voltage - comparator. */ - } STAT_b; - } ; - - union { - __IOM uint32_t PWDKEY; /*!< (@ 0x00000008) Key Register for Powering Down the Voltage Comparator */ - - struct { - __IOM uint32_t PWDKEY : 32; /*!< [31..0] Key register value. */ - } PWDKEY_b; - } ; - __IM uint32_t RESERVED[125]; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000200) Voltage Comparator Interrupt registers: Enable */ - - struct { - __IOM uint32_t OUTLOW : 1; /*!< [0..0] This bit is the vcompout low interrupt. */ - __IOM uint32_t OUTHI : 1; /*!< [1..1] This bit is the vcompout high interrupt. */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) Voltage Comparator Interrupt registers: Status */ - - struct { - __IOM uint32_t OUTLOW : 1; /*!< [0..0] This bit is the vcompout low interrupt. */ - __IOM uint32_t OUTHI : 1; /*!< [1..1] This bit is the vcompout high interrupt. */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000208) Voltage Comparator Interrupt registers: Clear */ - - struct { - __IOM uint32_t OUTLOW : 1; /*!< [0..0] This bit is the vcompout low interrupt. */ - __IOM uint32_t OUTHI : 1; /*!< [1..1] This bit is the vcompout high interrupt. */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000020C) Voltage Comparator Interrupt registers: Set */ - - struct { - __IOM uint32_t OUTLOW : 1; /*!< [0..0] This bit is the vcompout low interrupt. */ - __IOM uint32_t OUTHI : 1; /*!< [1..1] This bit is the vcompout high interrupt. */ - } INTSET_b; - } ; -} VCOMP_Type; /*!< Size = 528 (0x210) */ - - - -/* =========================================================================================================================== */ -/* ================ WDT ================ */ -/* =========================================================================================================================== */ - - -/** - * @brief Watchdog Timer (WDT) - */ - -typedef struct { /*!< (@ 0x40024000) WDT Structure */ - - union { - __IOM uint32_t CFG; /*!< (@ 0x00000000) Configuration Register */ - - struct { - __IOM uint32_t WDTEN : 1; /*!< [0..0] This bitfield enables the WDT. */ - __IOM uint32_t INTEN : 1; /*!< [1..1] This bitfield enables the WDT interrupt. Note : This - bit must be set before the interrupt status bit will reflect - a watchdog timer expiration. The IER interrupt register - must also be enabled for a WDT interrupt to be sent to - the NVIC. */ - __IOM uint32_t RESEN : 1; /*!< [2..2] This bitfield enables the WDT reset. This needs to be - set together with the WDREN bit in REG_RSTGEN_CFG register - (in reset gen) to trigger the reset. */ - __IM uint32_t : 5; - __IOM uint32_t RESVAL : 8; /*!< [15..8] This bitfield is the compare value for counter bits - 7:0 to generate a watchdog reset. This will cause a software - reset. */ - __IOM uint32_t INTVAL : 8; /*!< [23..16] This bitfield is the compare value for counter bits - 7:0 to generate a watchdog interrupt. */ - __IOM uint32_t CLKSEL : 3; /*!< [26..24] Select the frequency for the WDT. All values not enumerated - below are undefined. */ - } CFG_b; - } ; - - union { - __IOM uint32_t RSTRT; /*!< (@ 0x00000004) Restart the watchdog timer. */ - - struct { - __IOM uint32_t RSTRT : 8; /*!< [7..0] Writing 0xB2 to WDTRSTRT restarts the watchdog timer. - This is a write only register. Reading this register will - only provide all 0. */ - } RSTRT_b; - } ; - - union { - __IOM uint32_t LOCK; /*!< (@ 0x00000008) Locks the WDT */ - - struct { - __IOM uint32_t LOCK : 8; /*!< [7..0] Writing 0x3A locks the watchdog timer. Once locked, the - WDTCFG reg cannot be written and WDTEN is set. */ - } LOCK_b; - } ; - - union { - __IOM uint32_t COUNT; /*!< (@ 0x0000000C) Current Counter Value for WDT */ - - struct { - __IOM uint32_t COUNT : 8; /*!< [7..0] Read-Only current value of the WDT counter */ - } COUNT_b; - } ; - __IM uint32_t RESERVED[124]; - - union { - __IOM uint32_t INTEN; /*!< (@ 0x00000200) WDT Interrupt register: Enable */ - - struct { - __IOM uint32_t WDTINT : 1; /*!< [0..0] Watchdog Timer Interrupt. */ - } INTEN_b; - } ; - - union { - __IOM uint32_t INTSTAT; /*!< (@ 0x00000204) WDT Interrupt register: Status */ - - struct { - __IOM uint32_t WDTINT : 1; /*!< [0..0] Watchdog Timer Interrupt. */ - } INTSTAT_b; - } ; - - union { - __IOM uint32_t INTCLR; /*!< (@ 0x00000208) WDT Interrupt register: Clear */ - - struct { - __IOM uint32_t WDTINT : 1; /*!< [0..0] Watchdog Timer Interrupt. */ - } INTCLR_b; - } ; - - union { - __IOM uint32_t INTSET; /*!< (@ 0x0000020C) WDT Interrupt register: Set */ - - struct { - __IOM uint32_t WDTINT : 1; /*!< [0..0] Watchdog Timer Interrupt. */ - } INTSET_b; - } ; -} WDT_Type; /*!< Size = 528 (0x210) */ - - -/** @} */ /* End of group Device_Peripheral_peripherals */ - - -/* =========================================================================================================================== */ -/* ================ Device Specific Peripheral Address Map ================ */ -/* =========================================================================================================================== */ - - -/** @addtogroup Device_Peripheral_peripheralAddr - * @{ - */ - -#define ADC_BASE 0x50010000UL -#define APBDMA_BASE 0x40011000UL -#define BLEIF_BASE 0x5000C000UL -#define CACHECTRL_BASE 0x40018000UL -#define CLKGEN_BASE 0x40004000UL -#define CTIMER_BASE 0x40008000UL -#define GPIO_BASE 0x40010000UL -#define IOM0_BASE 0x50004000UL -#define IOM1_BASE 0x50005000UL -#define IOM2_BASE 0x50006000UL -#define IOM3_BASE 0x50007000UL -#define IOM4_BASE 0x50008000UL -#define IOM5_BASE 0x50009000UL -#define IOSLAVE_BASE 0x50000000UL -#define MCUCTRL_BASE 0x40020000UL -#define MSPI_BASE 0x50014000UL -#define PDM_BASE 0x50011000UL -#define PWRCTRL_BASE 0x40021000UL -#define RSTGEN_BASE 0x40000000UL -#define RTC_BASE 0x40004200UL -#define SCARD_BASE 0x40080000UL -#define SECURITY_BASE 0x40030000UL -#define UART0_BASE 0x4001C000UL -#define UART1_BASE 0x4001D000UL -#define VCOMP_BASE 0x4000C000UL -#define WDT_BASE 0x40024000UL - -/** @} */ /* End of group Device_Peripheral_peripheralAddr */ - - -/* =========================================================================================================================== */ -/* ================ Peripheral declaration ================ */ -/* =========================================================================================================================== */ - - -/** @addtogroup Device_Peripheral_declaration - * @{ - */ - -#define ADC ((ADC_Type*) ADC_BASE) -#define APBDMA ((APBDMA_Type*) APBDMA_BASE) -#define BLEIF ((BLEIF_Type*) BLEIF_BASE) -#define CACHECTRL ((CACHECTRL_Type*) CACHECTRL_BASE) -#define CLKGEN ((CLKGEN_Type*) CLKGEN_BASE) -#define CTIMER ((CTIMER_Type*) CTIMER_BASE) -#define GPIO ((GPIO_Type*) GPIO_BASE) -#define IOM0 ((IOM0_Type*) IOM0_BASE) -#define IOM1 ((IOM0_Type*) IOM1_BASE) -#define IOM2 ((IOM0_Type*) IOM2_BASE) -#define IOM3 ((IOM0_Type*) IOM3_BASE) -#define IOM4 ((IOM0_Type*) IOM4_BASE) -#define IOM5 ((IOM0_Type*) IOM5_BASE) -#define IOSLAVE ((IOSLAVE_Type*) IOSLAVE_BASE) -#define MCUCTRL ((MCUCTRL_Type*) MCUCTRL_BASE) -#define MSPI ((MSPI_Type*) MSPI_BASE) -#define PDM ((PDM_Type*) PDM_BASE) -#define PWRCTRL ((PWRCTRL_Type*) PWRCTRL_BASE) -#define RSTGEN ((RSTGEN_Type*) RSTGEN_BASE) -#define RTC ((RTC_Type*) RTC_BASE) -#define SCARD ((SCARD_Type*) SCARD_BASE) -#define SECURITY ((SECURITY_Type*) SECURITY_BASE) -#define UART0 ((UART0_Type*) UART0_BASE) -#define UART1 ((UART0_Type*) UART1_BASE) -#define VCOMP ((VCOMP_Type*) VCOMP_BASE) -#define WDT ((WDT_Type*) WDT_BASE) - -/** @} */ /* End of group Device_Peripheral_declaration */ - - -/* ========================================= End of section using anonymous unions ========================================= */ -#if defined (__CC_ARM) - #pragma pop -#elif defined (__ICCARM__) - /* leave anonymous unions enabled */ -#elif (__ARMCC_VERSION >= 6010050) - #pragma clang diagnostic pop -#elif defined (__GNUC__) - /* anonymous unions are enabled by default */ -#elif defined (__TMS470__) - /* anonymous unions are enabled by default */ -#elif defined (__TASKING__) - #pragma warning restore -#elif defined (__CSMC__) - /* anonymous unions are enabled by default */ -#endif - - -/* =========================================================================================================================== */ -/* ================ Pos/Mask Peripheral Section ================ */ -/* =========================================================================================================================== */ - - -/** @addtogroup PosMask_peripherals - * @{ - */ - - - -/* =========================================================================================================================== */ -/* ================ ADC ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== CFG ========================================================== */ -#define ADC_CFG_CLKSEL_Pos (24UL) /*!< ADC CFG: CLKSEL (Bit 24) */ -#define ADC_CFG_CLKSEL_Msk (0x3000000UL) /*!< ADC CFG: CLKSEL (Bitfield-Mask: 0x03) */ -#define ADC_CFG_TRIGPOL_Pos (19UL) /*!< ADC CFG: TRIGPOL (Bit 19) */ -#define ADC_CFG_TRIGPOL_Msk (0x80000UL) /*!< ADC CFG: TRIGPOL (Bitfield-Mask: 0x01) */ -#define ADC_CFG_TRIGSEL_Pos (16UL) /*!< ADC CFG: TRIGSEL (Bit 16) */ -#define ADC_CFG_TRIGSEL_Msk (0x70000UL) /*!< ADC CFG: TRIGSEL (Bitfield-Mask: 0x07) */ -#define ADC_CFG_DFIFORDEN_Pos (12UL) /*!< ADC CFG: DFIFORDEN (Bit 12) */ -#define ADC_CFG_DFIFORDEN_Msk (0x1000UL) /*!< ADC CFG: DFIFORDEN (Bitfield-Mask: 0x01) */ -#define ADC_CFG_REFSEL_Pos (8UL) /*!< ADC CFG: REFSEL (Bit 8) */ -#define ADC_CFG_REFSEL_Msk (0x300UL) /*!< ADC CFG: REFSEL (Bitfield-Mask: 0x03) */ -#define ADC_CFG_CKMODE_Pos (4UL) /*!< ADC CFG: CKMODE (Bit 4) */ -#define ADC_CFG_CKMODE_Msk (0x10UL) /*!< ADC CFG: CKMODE (Bitfield-Mask: 0x01) */ -#define ADC_CFG_LPMODE_Pos (3UL) /*!< ADC CFG: LPMODE (Bit 3) */ -#define ADC_CFG_LPMODE_Msk (0x8UL) /*!< ADC CFG: LPMODE (Bitfield-Mask: 0x01) */ -#define ADC_CFG_RPTEN_Pos (2UL) /*!< ADC CFG: RPTEN (Bit 2) */ -#define ADC_CFG_RPTEN_Msk (0x4UL) /*!< ADC CFG: RPTEN (Bitfield-Mask: 0x01) */ -#define ADC_CFG_ADCEN_Pos (0UL) /*!< ADC CFG: ADCEN (Bit 0) */ -#define ADC_CFG_ADCEN_Msk (0x1UL) /*!< ADC CFG: ADCEN (Bitfield-Mask: 0x01) */ -/* ========================================================= STAT ========================================================== */ -#define ADC_STAT_PWDSTAT_Pos (0UL) /*!< ADC STAT: PWDSTAT (Bit 0) */ -#define ADC_STAT_PWDSTAT_Msk (0x1UL) /*!< ADC STAT: PWDSTAT (Bitfield-Mask: 0x01) */ -/* ========================================================== SWT ========================================================== */ -#define ADC_SWT_SWT_Pos (0UL) /*!< ADC SWT: SWT (Bit 0) */ -#define ADC_SWT_SWT_Msk (0xffUL) /*!< ADC SWT: SWT (Bitfield-Mask: 0xff) */ -/* ======================================================== SL0CFG ========================================================= */ -#define ADC_SL0CFG_ADSEL0_Pos (24UL) /*!< ADC SL0CFG: ADSEL0 (Bit 24) */ -#define ADC_SL0CFG_ADSEL0_Msk (0x7000000UL) /*!< ADC SL0CFG: ADSEL0 (Bitfield-Mask: 0x07) */ -#define ADC_SL0CFG_PRMODE0_Pos (16UL) /*!< ADC SL0CFG: PRMODE0 (Bit 16) */ -#define ADC_SL0CFG_PRMODE0_Msk (0x30000UL) /*!< ADC SL0CFG: PRMODE0 (Bitfield-Mask: 0x03) */ -#define ADC_SL0CFG_CHSEL0_Pos (8UL) /*!< ADC SL0CFG: CHSEL0 (Bit 8) */ -#define ADC_SL0CFG_CHSEL0_Msk (0xf00UL) /*!< ADC SL0CFG: CHSEL0 (Bitfield-Mask: 0x0f) */ -#define ADC_SL0CFG_WCEN0_Pos (1UL) /*!< ADC SL0CFG: WCEN0 (Bit 1) */ -#define ADC_SL0CFG_WCEN0_Msk (0x2UL) /*!< ADC SL0CFG: WCEN0 (Bitfield-Mask: 0x01) */ -#define ADC_SL0CFG_SLEN0_Pos (0UL) /*!< ADC SL0CFG: SLEN0 (Bit 0) */ -#define ADC_SL0CFG_SLEN0_Msk (0x1UL) /*!< ADC SL0CFG: SLEN0 (Bitfield-Mask: 0x01) */ -/* ======================================================== SL1CFG ========================================================= */ -#define ADC_SL1CFG_ADSEL1_Pos (24UL) /*!< ADC SL1CFG: ADSEL1 (Bit 24) */ -#define ADC_SL1CFG_ADSEL1_Msk (0x7000000UL) /*!< ADC SL1CFG: ADSEL1 (Bitfield-Mask: 0x07) */ -#define ADC_SL1CFG_PRMODE1_Pos (16UL) /*!< ADC SL1CFG: PRMODE1 (Bit 16) */ -#define ADC_SL1CFG_PRMODE1_Msk (0x30000UL) /*!< ADC SL1CFG: PRMODE1 (Bitfield-Mask: 0x03) */ -#define ADC_SL1CFG_CHSEL1_Pos (8UL) /*!< ADC SL1CFG: CHSEL1 (Bit 8) */ -#define ADC_SL1CFG_CHSEL1_Msk (0xf00UL) /*!< ADC SL1CFG: CHSEL1 (Bitfield-Mask: 0x0f) */ -#define ADC_SL1CFG_WCEN1_Pos (1UL) /*!< ADC SL1CFG: WCEN1 (Bit 1) */ -#define ADC_SL1CFG_WCEN1_Msk (0x2UL) /*!< ADC SL1CFG: WCEN1 (Bitfield-Mask: 0x01) */ -#define ADC_SL1CFG_SLEN1_Pos (0UL) /*!< ADC SL1CFG: SLEN1 (Bit 0) */ -#define ADC_SL1CFG_SLEN1_Msk (0x1UL) /*!< ADC SL1CFG: SLEN1 (Bitfield-Mask: 0x01) */ -/* ======================================================== SL2CFG ========================================================= */ -#define ADC_SL2CFG_ADSEL2_Pos (24UL) /*!< ADC SL2CFG: ADSEL2 (Bit 24) */ -#define ADC_SL2CFG_ADSEL2_Msk (0x7000000UL) /*!< ADC SL2CFG: ADSEL2 (Bitfield-Mask: 0x07) */ -#define ADC_SL2CFG_PRMODE2_Pos (16UL) /*!< ADC SL2CFG: PRMODE2 (Bit 16) */ -#define ADC_SL2CFG_PRMODE2_Msk (0x30000UL) /*!< ADC SL2CFG: PRMODE2 (Bitfield-Mask: 0x03) */ -#define ADC_SL2CFG_CHSEL2_Pos (8UL) /*!< ADC SL2CFG: CHSEL2 (Bit 8) */ -#define ADC_SL2CFG_CHSEL2_Msk (0xf00UL) /*!< ADC SL2CFG: CHSEL2 (Bitfield-Mask: 0x0f) */ -#define ADC_SL2CFG_WCEN2_Pos (1UL) /*!< ADC SL2CFG: WCEN2 (Bit 1) */ -#define ADC_SL2CFG_WCEN2_Msk (0x2UL) /*!< ADC SL2CFG: WCEN2 (Bitfield-Mask: 0x01) */ -#define ADC_SL2CFG_SLEN2_Pos (0UL) /*!< ADC SL2CFG: SLEN2 (Bit 0) */ -#define ADC_SL2CFG_SLEN2_Msk (0x1UL) /*!< ADC SL2CFG: SLEN2 (Bitfield-Mask: 0x01) */ -/* ======================================================== SL3CFG ========================================================= */ -#define ADC_SL3CFG_ADSEL3_Pos (24UL) /*!< ADC SL3CFG: ADSEL3 (Bit 24) */ -#define ADC_SL3CFG_ADSEL3_Msk (0x7000000UL) /*!< ADC SL3CFG: ADSEL3 (Bitfield-Mask: 0x07) */ -#define ADC_SL3CFG_PRMODE3_Pos (16UL) /*!< ADC SL3CFG: PRMODE3 (Bit 16) */ -#define ADC_SL3CFG_PRMODE3_Msk (0x30000UL) /*!< ADC SL3CFG: PRMODE3 (Bitfield-Mask: 0x03) */ -#define ADC_SL3CFG_CHSEL3_Pos (8UL) /*!< ADC SL3CFG: CHSEL3 (Bit 8) */ -#define ADC_SL3CFG_CHSEL3_Msk (0xf00UL) /*!< ADC SL3CFG: CHSEL3 (Bitfield-Mask: 0x0f) */ -#define ADC_SL3CFG_WCEN3_Pos (1UL) /*!< ADC SL3CFG: WCEN3 (Bit 1) */ -#define ADC_SL3CFG_WCEN3_Msk (0x2UL) /*!< ADC SL3CFG: WCEN3 (Bitfield-Mask: 0x01) */ -#define ADC_SL3CFG_SLEN3_Pos (0UL) /*!< ADC SL3CFG: SLEN3 (Bit 0) */ -#define ADC_SL3CFG_SLEN3_Msk (0x1UL) /*!< ADC SL3CFG: SLEN3 (Bitfield-Mask: 0x01) */ -/* ======================================================== SL4CFG ========================================================= */ -#define ADC_SL4CFG_ADSEL4_Pos (24UL) /*!< ADC SL4CFG: ADSEL4 (Bit 24) */ -#define ADC_SL4CFG_ADSEL4_Msk (0x7000000UL) /*!< ADC SL4CFG: ADSEL4 (Bitfield-Mask: 0x07) */ -#define ADC_SL4CFG_PRMODE4_Pos (16UL) /*!< ADC SL4CFG: PRMODE4 (Bit 16) */ -#define ADC_SL4CFG_PRMODE4_Msk (0x30000UL) /*!< ADC SL4CFG: PRMODE4 (Bitfield-Mask: 0x03) */ -#define ADC_SL4CFG_CHSEL4_Pos (8UL) /*!< ADC SL4CFG: CHSEL4 (Bit 8) */ -#define ADC_SL4CFG_CHSEL4_Msk (0xf00UL) /*!< ADC SL4CFG: CHSEL4 (Bitfield-Mask: 0x0f) */ -#define ADC_SL4CFG_WCEN4_Pos (1UL) /*!< ADC SL4CFG: WCEN4 (Bit 1) */ -#define ADC_SL4CFG_WCEN4_Msk (0x2UL) /*!< ADC SL4CFG: WCEN4 (Bitfield-Mask: 0x01) */ -#define ADC_SL4CFG_SLEN4_Pos (0UL) /*!< ADC SL4CFG: SLEN4 (Bit 0) */ -#define ADC_SL4CFG_SLEN4_Msk (0x1UL) /*!< ADC SL4CFG: SLEN4 (Bitfield-Mask: 0x01) */ -/* ======================================================== SL5CFG ========================================================= */ -#define ADC_SL5CFG_ADSEL5_Pos (24UL) /*!< ADC SL5CFG: ADSEL5 (Bit 24) */ -#define ADC_SL5CFG_ADSEL5_Msk (0x7000000UL) /*!< ADC SL5CFG: ADSEL5 (Bitfield-Mask: 0x07) */ -#define ADC_SL5CFG_PRMODE5_Pos (16UL) /*!< ADC SL5CFG: PRMODE5 (Bit 16) */ -#define ADC_SL5CFG_PRMODE5_Msk (0x30000UL) /*!< ADC SL5CFG: PRMODE5 (Bitfield-Mask: 0x03) */ -#define ADC_SL5CFG_CHSEL5_Pos (8UL) /*!< ADC SL5CFG: CHSEL5 (Bit 8) */ -#define ADC_SL5CFG_CHSEL5_Msk (0xf00UL) /*!< ADC SL5CFG: CHSEL5 (Bitfield-Mask: 0x0f) */ -#define ADC_SL5CFG_WCEN5_Pos (1UL) /*!< ADC SL5CFG: WCEN5 (Bit 1) */ -#define ADC_SL5CFG_WCEN5_Msk (0x2UL) /*!< ADC SL5CFG: WCEN5 (Bitfield-Mask: 0x01) */ -#define ADC_SL5CFG_SLEN5_Pos (0UL) /*!< ADC SL5CFG: SLEN5 (Bit 0) */ -#define ADC_SL5CFG_SLEN5_Msk (0x1UL) /*!< ADC SL5CFG: SLEN5 (Bitfield-Mask: 0x01) */ -/* ======================================================== SL6CFG ========================================================= */ -#define ADC_SL6CFG_ADSEL6_Pos (24UL) /*!< ADC SL6CFG: ADSEL6 (Bit 24) */ -#define ADC_SL6CFG_ADSEL6_Msk (0x7000000UL) /*!< ADC SL6CFG: ADSEL6 (Bitfield-Mask: 0x07) */ -#define ADC_SL6CFG_PRMODE6_Pos (16UL) /*!< ADC SL6CFG: PRMODE6 (Bit 16) */ -#define ADC_SL6CFG_PRMODE6_Msk (0x30000UL) /*!< ADC SL6CFG: PRMODE6 (Bitfield-Mask: 0x03) */ -#define ADC_SL6CFG_CHSEL6_Pos (8UL) /*!< ADC SL6CFG: CHSEL6 (Bit 8) */ -#define ADC_SL6CFG_CHSEL6_Msk (0xf00UL) /*!< ADC SL6CFG: CHSEL6 (Bitfield-Mask: 0x0f) */ -#define ADC_SL6CFG_WCEN6_Pos (1UL) /*!< ADC SL6CFG: WCEN6 (Bit 1) */ -#define ADC_SL6CFG_WCEN6_Msk (0x2UL) /*!< ADC SL6CFG: WCEN6 (Bitfield-Mask: 0x01) */ -#define ADC_SL6CFG_SLEN6_Pos (0UL) /*!< ADC SL6CFG: SLEN6 (Bit 0) */ -#define ADC_SL6CFG_SLEN6_Msk (0x1UL) /*!< ADC SL6CFG: SLEN6 (Bitfield-Mask: 0x01) */ -/* ======================================================== SL7CFG ========================================================= */ -#define ADC_SL7CFG_ADSEL7_Pos (24UL) /*!< ADC SL7CFG: ADSEL7 (Bit 24) */ -#define ADC_SL7CFG_ADSEL7_Msk (0x7000000UL) /*!< ADC SL7CFG: ADSEL7 (Bitfield-Mask: 0x07) */ -#define ADC_SL7CFG_PRMODE7_Pos (16UL) /*!< ADC SL7CFG: PRMODE7 (Bit 16) */ -#define ADC_SL7CFG_PRMODE7_Msk (0x30000UL) /*!< ADC SL7CFG: PRMODE7 (Bitfield-Mask: 0x03) */ -#define ADC_SL7CFG_CHSEL7_Pos (8UL) /*!< ADC SL7CFG: CHSEL7 (Bit 8) */ -#define ADC_SL7CFG_CHSEL7_Msk (0xf00UL) /*!< ADC SL7CFG: CHSEL7 (Bitfield-Mask: 0x0f) */ -#define ADC_SL7CFG_WCEN7_Pos (1UL) /*!< ADC SL7CFG: WCEN7 (Bit 1) */ -#define ADC_SL7CFG_WCEN7_Msk (0x2UL) /*!< ADC SL7CFG: WCEN7 (Bitfield-Mask: 0x01) */ -#define ADC_SL7CFG_SLEN7_Pos (0UL) /*!< ADC SL7CFG: SLEN7 (Bit 0) */ -#define ADC_SL7CFG_SLEN7_Msk (0x1UL) /*!< ADC SL7CFG: SLEN7 (Bitfield-Mask: 0x01) */ -/* ========================================================= WULIM ========================================================= */ -#define ADC_WULIM_ULIM_Pos (0UL) /*!< ADC WULIM: ULIM (Bit 0) */ -#define ADC_WULIM_ULIM_Msk (0xfffffUL) /*!< ADC WULIM: ULIM (Bitfield-Mask: 0xfffff) */ -/* ========================================================= WLLIM ========================================================= */ -#define ADC_WLLIM_LLIM_Pos (0UL) /*!< ADC WLLIM: LLIM (Bit 0) */ -#define ADC_WLLIM_LLIM_Msk (0xfffffUL) /*!< ADC WLLIM: LLIM (Bitfield-Mask: 0xfffff) */ -/* ======================================================== SCWLIM ========================================================= */ -#define ADC_SCWLIM_SCWLIMEN_Pos (0UL) /*!< ADC SCWLIM: SCWLIMEN (Bit 0) */ -#define ADC_SCWLIM_SCWLIMEN_Msk (0x1UL) /*!< ADC SCWLIM: SCWLIMEN (Bitfield-Mask: 0x01) */ -/* ========================================================= FIFO ========================================================== */ -#define ADC_FIFO_RSVD_Pos (31UL) /*!< ADC FIFO: RSVD (Bit 31) */ -#define ADC_FIFO_RSVD_Msk (0x80000000UL) /*!< ADC FIFO: RSVD (Bitfield-Mask: 0x01) */ -#define ADC_FIFO_SLOTNUM_Pos (28UL) /*!< ADC FIFO: SLOTNUM (Bit 28) */ -#define ADC_FIFO_SLOTNUM_Msk (0x70000000UL) /*!< ADC FIFO: SLOTNUM (Bitfield-Mask: 0x07) */ -#define ADC_FIFO_COUNT_Pos (20UL) /*!< ADC FIFO: COUNT (Bit 20) */ -#define ADC_FIFO_COUNT_Msk (0xff00000UL) /*!< ADC FIFO: COUNT (Bitfield-Mask: 0xff) */ -#define ADC_FIFO_DATA_Pos (0UL) /*!< ADC FIFO: DATA (Bit 0) */ -#define ADC_FIFO_DATA_Msk (0xfffffUL) /*!< ADC FIFO: DATA (Bitfield-Mask: 0xfffff) */ -/* ======================================================== FIFOPR ========================================================= */ -#define ADC_FIFOPR_RSVDPR_Pos (31UL) /*!< ADC FIFOPR: RSVDPR (Bit 31) */ -#define ADC_FIFOPR_RSVDPR_Msk (0x80000000UL) /*!< ADC FIFOPR: RSVDPR (Bitfield-Mask: 0x01) */ -#define ADC_FIFOPR_SLOTNUMPR_Pos (28UL) /*!< ADC FIFOPR: SLOTNUMPR (Bit 28) */ -#define ADC_FIFOPR_SLOTNUMPR_Msk (0x70000000UL) /*!< ADC FIFOPR: SLOTNUMPR (Bitfield-Mask: 0x07) */ -#define ADC_FIFOPR_COUNT_Pos (20UL) /*!< ADC FIFOPR: COUNT (Bit 20) */ -#define ADC_FIFOPR_COUNT_Msk (0xff00000UL) /*!< ADC FIFOPR: COUNT (Bitfield-Mask: 0xff) */ -#define ADC_FIFOPR_DATA_Pos (0UL) /*!< ADC FIFOPR: DATA (Bit 0) */ -#define ADC_FIFOPR_DATA_Msk (0xfffffUL) /*!< ADC FIFOPR: DATA (Bitfield-Mask: 0xfffff) */ -/* ========================================================= INTEN ========================================================= */ -#define ADC_INTEN_DERR_Pos (7UL) /*!< ADC INTEN: DERR (Bit 7) */ -#define ADC_INTEN_DERR_Msk (0x80UL) /*!< ADC INTEN: DERR (Bitfield-Mask: 0x01) */ -#define ADC_INTEN_DCMP_Pos (6UL) /*!< ADC INTEN: DCMP (Bit 6) */ -#define ADC_INTEN_DCMP_Msk (0x40UL) /*!< ADC INTEN: DCMP (Bitfield-Mask: 0x01) */ -#define ADC_INTEN_WCINC_Pos (5UL) /*!< ADC INTEN: WCINC (Bit 5) */ -#define ADC_INTEN_WCINC_Msk (0x20UL) /*!< ADC INTEN: WCINC (Bitfield-Mask: 0x01) */ -#define ADC_INTEN_WCEXC_Pos (4UL) /*!< ADC INTEN: WCEXC (Bit 4) */ -#define ADC_INTEN_WCEXC_Msk (0x10UL) /*!< ADC INTEN: WCEXC (Bitfield-Mask: 0x01) */ -#define ADC_INTEN_FIFOOVR2_Pos (3UL) /*!< ADC INTEN: FIFOOVR2 (Bit 3) */ -#define ADC_INTEN_FIFOOVR2_Msk (0x8UL) /*!< ADC INTEN: FIFOOVR2 (Bitfield-Mask: 0x01) */ -#define ADC_INTEN_FIFOOVR1_Pos (2UL) /*!< ADC INTEN: FIFOOVR1 (Bit 2) */ -#define ADC_INTEN_FIFOOVR1_Msk (0x4UL) /*!< ADC INTEN: FIFOOVR1 (Bitfield-Mask: 0x01) */ -#define ADC_INTEN_SCNCMP_Pos (1UL) /*!< ADC INTEN: SCNCMP (Bit 1) */ -#define ADC_INTEN_SCNCMP_Msk (0x2UL) /*!< ADC INTEN: SCNCMP (Bitfield-Mask: 0x01) */ -#define ADC_INTEN_CNVCMP_Pos (0UL) /*!< ADC INTEN: CNVCMP (Bit 0) */ -#define ADC_INTEN_CNVCMP_Msk (0x1UL) /*!< ADC INTEN: CNVCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define ADC_INTSTAT_DERR_Pos (7UL) /*!< ADC INTSTAT: DERR (Bit 7) */ -#define ADC_INTSTAT_DERR_Msk (0x80UL) /*!< ADC INTSTAT: DERR (Bitfield-Mask: 0x01) */ -#define ADC_INTSTAT_DCMP_Pos (6UL) /*!< ADC INTSTAT: DCMP (Bit 6) */ -#define ADC_INTSTAT_DCMP_Msk (0x40UL) /*!< ADC INTSTAT: DCMP (Bitfield-Mask: 0x01) */ -#define ADC_INTSTAT_WCINC_Pos (5UL) /*!< ADC INTSTAT: WCINC (Bit 5) */ -#define ADC_INTSTAT_WCINC_Msk (0x20UL) /*!< ADC INTSTAT: WCINC (Bitfield-Mask: 0x01) */ -#define ADC_INTSTAT_WCEXC_Pos (4UL) /*!< ADC INTSTAT: WCEXC (Bit 4) */ -#define ADC_INTSTAT_WCEXC_Msk (0x10UL) /*!< ADC INTSTAT: WCEXC (Bitfield-Mask: 0x01) */ -#define ADC_INTSTAT_FIFOOVR2_Pos (3UL) /*!< ADC INTSTAT: FIFOOVR2 (Bit 3) */ -#define ADC_INTSTAT_FIFOOVR2_Msk (0x8UL) /*!< ADC INTSTAT: FIFOOVR2 (Bitfield-Mask: 0x01) */ -#define ADC_INTSTAT_FIFOOVR1_Pos (2UL) /*!< ADC INTSTAT: FIFOOVR1 (Bit 2) */ -#define ADC_INTSTAT_FIFOOVR1_Msk (0x4UL) /*!< ADC INTSTAT: FIFOOVR1 (Bitfield-Mask: 0x01) */ -#define ADC_INTSTAT_SCNCMP_Pos (1UL) /*!< ADC INTSTAT: SCNCMP (Bit 1) */ -#define ADC_INTSTAT_SCNCMP_Msk (0x2UL) /*!< ADC INTSTAT: SCNCMP (Bitfield-Mask: 0x01) */ -#define ADC_INTSTAT_CNVCMP_Pos (0UL) /*!< ADC INTSTAT: CNVCMP (Bit 0) */ -#define ADC_INTSTAT_CNVCMP_Msk (0x1UL) /*!< ADC INTSTAT: CNVCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define ADC_INTCLR_DERR_Pos (7UL) /*!< ADC INTCLR: DERR (Bit 7) */ -#define ADC_INTCLR_DERR_Msk (0x80UL) /*!< ADC INTCLR: DERR (Bitfield-Mask: 0x01) */ -#define ADC_INTCLR_DCMP_Pos (6UL) /*!< ADC INTCLR: DCMP (Bit 6) */ -#define ADC_INTCLR_DCMP_Msk (0x40UL) /*!< ADC INTCLR: DCMP (Bitfield-Mask: 0x01) */ -#define ADC_INTCLR_WCINC_Pos (5UL) /*!< ADC INTCLR: WCINC (Bit 5) */ -#define ADC_INTCLR_WCINC_Msk (0x20UL) /*!< ADC INTCLR: WCINC (Bitfield-Mask: 0x01) */ -#define ADC_INTCLR_WCEXC_Pos (4UL) /*!< ADC INTCLR: WCEXC (Bit 4) */ -#define ADC_INTCLR_WCEXC_Msk (0x10UL) /*!< ADC INTCLR: WCEXC (Bitfield-Mask: 0x01) */ -#define ADC_INTCLR_FIFOOVR2_Pos (3UL) /*!< ADC INTCLR: FIFOOVR2 (Bit 3) */ -#define ADC_INTCLR_FIFOOVR2_Msk (0x8UL) /*!< ADC INTCLR: FIFOOVR2 (Bitfield-Mask: 0x01) */ -#define ADC_INTCLR_FIFOOVR1_Pos (2UL) /*!< ADC INTCLR: FIFOOVR1 (Bit 2) */ -#define ADC_INTCLR_FIFOOVR1_Msk (0x4UL) /*!< ADC INTCLR: FIFOOVR1 (Bitfield-Mask: 0x01) */ -#define ADC_INTCLR_SCNCMP_Pos (1UL) /*!< ADC INTCLR: SCNCMP (Bit 1) */ -#define ADC_INTCLR_SCNCMP_Msk (0x2UL) /*!< ADC INTCLR: SCNCMP (Bitfield-Mask: 0x01) */ -#define ADC_INTCLR_CNVCMP_Pos (0UL) /*!< ADC INTCLR: CNVCMP (Bit 0) */ -#define ADC_INTCLR_CNVCMP_Msk (0x1UL) /*!< ADC INTCLR: CNVCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define ADC_INTSET_DERR_Pos (7UL) /*!< ADC INTSET: DERR (Bit 7) */ -#define ADC_INTSET_DERR_Msk (0x80UL) /*!< ADC INTSET: DERR (Bitfield-Mask: 0x01) */ -#define ADC_INTSET_DCMP_Pos (6UL) /*!< ADC INTSET: DCMP (Bit 6) */ -#define ADC_INTSET_DCMP_Msk (0x40UL) /*!< ADC INTSET: DCMP (Bitfield-Mask: 0x01) */ -#define ADC_INTSET_WCINC_Pos (5UL) /*!< ADC INTSET: WCINC (Bit 5) */ -#define ADC_INTSET_WCINC_Msk (0x20UL) /*!< ADC INTSET: WCINC (Bitfield-Mask: 0x01) */ -#define ADC_INTSET_WCEXC_Pos (4UL) /*!< ADC INTSET: WCEXC (Bit 4) */ -#define ADC_INTSET_WCEXC_Msk (0x10UL) /*!< ADC INTSET: WCEXC (Bitfield-Mask: 0x01) */ -#define ADC_INTSET_FIFOOVR2_Pos (3UL) /*!< ADC INTSET: FIFOOVR2 (Bit 3) */ -#define ADC_INTSET_FIFOOVR2_Msk (0x8UL) /*!< ADC INTSET: FIFOOVR2 (Bitfield-Mask: 0x01) */ -#define ADC_INTSET_FIFOOVR1_Pos (2UL) /*!< ADC INTSET: FIFOOVR1 (Bit 2) */ -#define ADC_INTSET_FIFOOVR1_Msk (0x4UL) /*!< ADC INTSET: FIFOOVR1 (Bitfield-Mask: 0x01) */ -#define ADC_INTSET_SCNCMP_Pos (1UL) /*!< ADC INTSET: SCNCMP (Bit 1) */ -#define ADC_INTSET_SCNCMP_Msk (0x2UL) /*!< ADC INTSET: SCNCMP (Bitfield-Mask: 0x01) */ -#define ADC_INTSET_CNVCMP_Pos (0UL) /*!< ADC INTSET: CNVCMP (Bit 0) */ -#define ADC_INTSET_CNVCMP_Msk (0x1UL) /*!< ADC INTSET: CNVCMP (Bitfield-Mask: 0x01) */ -/* ======================================================= DMATRIGEN ======================================================= */ -#define ADC_DMATRIGEN_DFIFOFULL_Pos (1UL) /*!< ADC DMATRIGEN: DFIFOFULL (Bit 1) */ -#define ADC_DMATRIGEN_DFIFOFULL_Msk (0x2UL) /*!< ADC DMATRIGEN: DFIFOFULL (Bitfield-Mask: 0x01) */ -#define ADC_DMATRIGEN_DFIFO75_Pos (0UL) /*!< ADC DMATRIGEN: DFIFO75 (Bit 0) */ -#define ADC_DMATRIGEN_DFIFO75_Msk (0x1UL) /*!< ADC DMATRIGEN: DFIFO75 (Bitfield-Mask: 0x01) */ -/* ====================================================== DMATRIGSTAT ====================================================== */ -#define ADC_DMATRIGSTAT_DFULLSTAT_Pos (1UL) /*!< ADC DMATRIGSTAT: DFULLSTAT (Bit 1) */ -#define ADC_DMATRIGSTAT_DFULLSTAT_Msk (0x2UL) /*!< ADC DMATRIGSTAT: DFULLSTAT (Bitfield-Mask: 0x01) */ -#define ADC_DMATRIGSTAT_D75STAT_Pos (0UL) /*!< ADC DMATRIGSTAT: D75STAT (Bit 0) */ -#define ADC_DMATRIGSTAT_D75STAT_Msk (0x1UL) /*!< ADC DMATRIGSTAT: D75STAT (Bitfield-Mask: 0x01) */ -/* ======================================================== DMACFG ========================================================= */ -#define ADC_DMACFG_DPWROFF_Pos (18UL) /*!< ADC DMACFG: DPWROFF (Bit 18) */ -#define ADC_DMACFG_DPWROFF_Msk (0x40000UL) /*!< ADC DMACFG: DPWROFF (Bitfield-Mask: 0x01) */ -#define ADC_DMACFG_DMAMSK_Pos (17UL) /*!< ADC DMACFG: DMAMSK (Bit 17) */ -#define ADC_DMACFG_DMAMSK_Msk (0x20000UL) /*!< ADC DMACFG: DMAMSK (Bitfield-Mask: 0x01) */ -#define ADC_DMACFG_DMAHONSTAT_Pos (16UL) /*!< ADC DMACFG: DMAHONSTAT (Bit 16) */ -#define ADC_DMACFG_DMAHONSTAT_Msk (0x10000UL) /*!< ADC DMACFG: DMAHONSTAT (Bitfield-Mask: 0x01) */ -#define ADC_DMACFG_DMADYNPRI_Pos (9UL) /*!< ADC DMACFG: DMADYNPRI (Bit 9) */ -#define ADC_DMACFG_DMADYNPRI_Msk (0x200UL) /*!< ADC DMACFG: DMADYNPRI (Bitfield-Mask: 0x01) */ -#define ADC_DMACFG_DMAPRI_Pos (8UL) /*!< ADC DMACFG: DMAPRI (Bit 8) */ -#define ADC_DMACFG_DMAPRI_Msk (0x100UL) /*!< ADC DMACFG: DMAPRI (Bitfield-Mask: 0x01) */ -#define ADC_DMACFG_DMADIR_Pos (2UL) /*!< ADC DMACFG: DMADIR (Bit 2) */ -#define ADC_DMACFG_DMADIR_Msk (0x4UL) /*!< ADC DMACFG: DMADIR (Bitfield-Mask: 0x01) */ -#define ADC_DMACFG_DMAEN_Pos (0UL) /*!< ADC DMACFG: DMAEN (Bit 0) */ -#define ADC_DMACFG_DMAEN_Msk (0x1UL) /*!< ADC DMACFG: DMAEN (Bitfield-Mask: 0x01) */ -/* ====================================================== DMATOTCOUNT ====================================================== */ -#define ADC_DMATOTCOUNT_TOTCOUNT_Pos (2UL) /*!< ADC DMATOTCOUNT: TOTCOUNT (Bit 2) */ -#define ADC_DMATOTCOUNT_TOTCOUNT_Msk (0x3fffcUL) /*!< ADC DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xffff) */ -/* ====================================================== DMATARGADDR ====================================================== */ -#define ADC_DMATARGADDR_UTARGADDR_Pos (19UL) /*!< ADC DMATARGADDR: UTARGADDR (Bit 19) */ -#define ADC_DMATARGADDR_UTARGADDR_Msk (0xfff80000UL) /*!< ADC DMATARGADDR: UTARGADDR (Bitfield-Mask: 0x1fff) */ -#define ADC_DMATARGADDR_LTARGADDR_Pos (0UL) /*!< ADC DMATARGADDR: LTARGADDR (Bit 0) */ -#define ADC_DMATARGADDR_LTARGADDR_Msk (0x7ffffUL) /*!< ADC DMATARGADDR: LTARGADDR (Bitfield-Mask: 0x7ffff) */ -/* ======================================================== DMASTAT ======================================================== */ -#define ADC_DMASTAT_DMAERR_Pos (2UL) /*!< ADC DMASTAT: DMAERR (Bit 2) */ -#define ADC_DMASTAT_DMAERR_Msk (0x4UL) /*!< ADC DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ -#define ADC_DMASTAT_DMACPL_Pos (1UL) /*!< ADC DMASTAT: DMACPL (Bit 1) */ -#define ADC_DMASTAT_DMACPL_Msk (0x2UL) /*!< ADC DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ -#define ADC_DMASTAT_DMATIP_Pos (0UL) /*!< ADC DMASTAT: DMATIP (Bit 0) */ -#define ADC_DMASTAT_DMATIP_Msk (0x1UL) /*!< ADC DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ APBDMA ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== BBVALUE ======================================================== */ -#define APBDMA_BBVALUE_PIN_Pos (16UL) /*!< APBDMA BBVALUE: PIN (Bit 16) */ -#define APBDMA_BBVALUE_PIN_Msk (0xff0000UL) /*!< APBDMA BBVALUE: PIN (Bitfield-Mask: 0xff) */ -#define APBDMA_BBVALUE_DATAOUT_Pos (0UL) /*!< APBDMA BBVALUE: DATAOUT (Bit 0) */ -#define APBDMA_BBVALUE_DATAOUT_Msk (0xffUL) /*!< APBDMA BBVALUE: DATAOUT (Bitfield-Mask: 0xff) */ -/* ====================================================== BBSETCLEAR ======================================================= */ -#define APBDMA_BBSETCLEAR_CLEAR_Pos (16UL) /*!< APBDMA BBSETCLEAR: CLEAR (Bit 16) */ -#define APBDMA_BBSETCLEAR_CLEAR_Msk (0xff0000UL) /*!< APBDMA BBSETCLEAR: CLEAR (Bitfield-Mask: 0xff) */ -#define APBDMA_BBSETCLEAR_SET_Pos (0UL) /*!< APBDMA BBSETCLEAR: SET (Bit 0) */ -#define APBDMA_BBSETCLEAR_SET_Msk (0xffUL) /*!< APBDMA BBSETCLEAR: SET (Bitfield-Mask: 0xff) */ -/* ======================================================== BBINPUT ======================================================== */ -#define APBDMA_BBINPUT_DATAIN_Pos (0UL) /*!< APBDMA BBINPUT: DATAIN (Bit 0) */ -#define APBDMA_BBINPUT_DATAIN_Msk (0xffUL) /*!< APBDMA BBINPUT: DATAIN (Bitfield-Mask: 0xff) */ -/* ======================================================= DEBUGDATA ======================================================= */ -#define APBDMA_DEBUGDATA_DEBUGDATA_Pos (0UL) /*!< APBDMA DEBUGDATA: DEBUGDATA (Bit 0) */ -#define APBDMA_DEBUGDATA_DEBUGDATA_Msk (0xffffffffUL) /*!< APBDMA DEBUGDATA: DEBUGDATA (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= DEBUG ========================================================= */ -#define APBDMA_DEBUG_DEBUGEN_Pos (0UL) /*!< APBDMA DEBUG: DEBUGEN (Bit 0) */ -#define APBDMA_DEBUG_DEBUGEN_Msk (0xfUL) /*!< APBDMA DEBUG: DEBUGEN (Bitfield-Mask: 0x0f) */ - - -/* =========================================================================================================================== */ -/* ================ BLEIF ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= FIFO ========================================================== */ -#define BLEIF_FIFO_FIFO_Pos (0UL) /*!< BLEIF FIFO: FIFO (Bit 0) */ -#define BLEIF_FIFO_FIFO_Msk (0xffffffffUL) /*!< BLEIF FIFO: FIFO (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== FIFOPTR ======================================================== */ -#define BLEIF_FIFOPTR_FIFO1REM_Pos (24UL) /*!< BLEIF FIFOPTR: FIFO1REM (Bit 24) */ -#define BLEIF_FIFOPTR_FIFO1REM_Msk (0xff000000UL) /*!< BLEIF FIFOPTR: FIFO1REM (Bitfield-Mask: 0xff) */ -#define BLEIF_FIFOPTR_FIFO1SIZ_Pos (16UL) /*!< BLEIF FIFOPTR: FIFO1SIZ (Bit 16) */ -#define BLEIF_FIFOPTR_FIFO1SIZ_Msk (0xff0000UL) /*!< BLEIF FIFOPTR: FIFO1SIZ (Bitfield-Mask: 0xff) */ -#define BLEIF_FIFOPTR_FIFO0REM_Pos (8UL) /*!< BLEIF FIFOPTR: FIFO0REM (Bit 8) */ -#define BLEIF_FIFOPTR_FIFO0REM_Msk (0xff00UL) /*!< BLEIF FIFOPTR: FIFO0REM (Bitfield-Mask: 0xff) */ -#define BLEIF_FIFOPTR_FIFO0SIZ_Pos (0UL) /*!< BLEIF FIFOPTR: FIFO0SIZ (Bit 0) */ -#define BLEIF_FIFOPTR_FIFO0SIZ_Msk (0xffUL) /*!< BLEIF FIFOPTR: FIFO0SIZ (Bitfield-Mask: 0xff) */ -/* ======================================================== FIFOTHR ======================================================== */ -#define BLEIF_FIFOTHR_FIFOWTHR_Pos (8UL) /*!< BLEIF FIFOTHR: FIFOWTHR (Bit 8) */ -#define BLEIF_FIFOTHR_FIFOWTHR_Msk (0x3f00UL) /*!< BLEIF FIFOTHR: FIFOWTHR (Bitfield-Mask: 0x3f) */ -#define BLEIF_FIFOTHR_FIFORTHR_Pos (0UL) /*!< BLEIF FIFOTHR: FIFORTHR (Bit 0) */ -#define BLEIF_FIFOTHR_FIFORTHR_Msk (0x3fUL) /*!< BLEIF FIFOTHR: FIFORTHR (Bitfield-Mask: 0x3f) */ -/* ======================================================== FIFOPOP ======================================================== */ -#define BLEIF_FIFOPOP_FIFODOUT_Pos (0UL) /*!< BLEIF FIFOPOP: FIFODOUT (Bit 0) */ -#define BLEIF_FIFOPOP_FIFODOUT_Msk (0xffffffffUL) /*!< BLEIF FIFOPOP: FIFODOUT (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= FIFOPUSH ======================================================== */ -#define BLEIF_FIFOPUSH_FIFODIN_Pos (0UL) /*!< BLEIF FIFOPUSH: FIFODIN (Bit 0) */ -#define BLEIF_FIFOPUSH_FIFODIN_Msk (0xffffffffUL) /*!< BLEIF FIFOPUSH: FIFODIN (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= FIFOCTRL ======================================================== */ -#define BLEIF_FIFOCTRL_FIFORSTN_Pos (1UL) /*!< BLEIF FIFOCTRL: FIFORSTN (Bit 1) */ -#define BLEIF_FIFOCTRL_FIFORSTN_Msk (0x2UL) /*!< BLEIF FIFOCTRL: FIFORSTN (Bitfield-Mask: 0x01) */ -#define BLEIF_FIFOCTRL_POPWR_Pos (0UL) /*!< BLEIF FIFOCTRL: POPWR (Bit 0) */ -#define BLEIF_FIFOCTRL_POPWR_Msk (0x1UL) /*!< BLEIF FIFOCTRL: POPWR (Bitfield-Mask: 0x01) */ -/* ======================================================== FIFOLOC ======================================================== */ -#define BLEIF_FIFOLOC_FIFORPTR_Pos (8UL) /*!< BLEIF FIFOLOC: FIFORPTR (Bit 8) */ -#define BLEIF_FIFOLOC_FIFORPTR_Msk (0xf00UL) /*!< BLEIF FIFOLOC: FIFORPTR (Bitfield-Mask: 0x0f) */ -#define BLEIF_FIFOLOC_FIFOWPTR_Pos (0UL) /*!< BLEIF FIFOLOC: FIFOWPTR (Bit 0) */ -#define BLEIF_FIFOLOC_FIFOWPTR_Msk (0xfUL) /*!< BLEIF FIFOLOC: FIFOWPTR (Bitfield-Mask: 0x0f) */ -/* ======================================================== CLKCFG ========================================================= */ -#define BLEIF_CLKCFG_DIV3_Pos (12UL) /*!< BLEIF CLKCFG: DIV3 (Bit 12) */ -#define BLEIF_CLKCFG_DIV3_Msk (0x1000UL) /*!< BLEIF CLKCFG: DIV3 (Bitfield-Mask: 0x01) */ -#define BLEIF_CLKCFG_CLK32KEN_Pos (11UL) /*!< BLEIF CLKCFG: CLK32KEN (Bit 11) */ -#define BLEIF_CLKCFG_CLK32KEN_Msk (0x800UL) /*!< BLEIF CLKCFG: CLK32KEN (Bitfield-Mask: 0x01) */ -#define BLEIF_CLKCFG_FSEL_Pos (8UL) /*!< BLEIF CLKCFG: FSEL (Bit 8) */ -#define BLEIF_CLKCFG_FSEL_Msk (0x700UL) /*!< BLEIF CLKCFG: FSEL (Bitfield-Mask: 0x07) */ -#define BLEIF_CLKCFG_IOCLKEN_Pos (0UL) /*!< BLEIF CLKCFG: IOCLKEN (Bit 0) */ -#define BLEIF_CLKCFG_IOCLKEN_Msk (0x1UL) /*!< BLEIF CLKCFG: IOCLKEN (Bitfield-Mask: 0x01) */ -/* ========================================================== CMD ========================================================== */ -#define BLEIF_CMD_OFFSETLO_Pos (24UL) /*!< BLEIF CMD: OFFSETLO (Bit 24) */ -#define BLEIF_CMD_OFFSETLO_Msk (0xff000000UL) /*!< BLEIF CMD: OFFSETLO (Bitfield-Mask: 0xff) */ -#define BLEIF_CMD_CMDSEL_Pos (20UL) /*!< BLEIF CMD: CMDSEL (Bit 20) */ -#define BLEIF_CMD_CMDSEL_Msk (0x300000UL) /*!< BLEIF CMD: CMDSEL (Bitfield-Mask: 0x03) */ -#define BLEIF_CMD_TSIZE_Pos (8UL) /*!< BLEIF CMD: TSIZE (Bit 8) */ -#define BLEIF_CMD_TSIZE_Msk (0xfff00UL) /*!< BLEIF CMD: TSIZE (Bitfield-Mask: 0xfff) */ -#define BLEIF_CMD_CONT_Pos (7UL) /*!< BLEIF CMD: CONT (Bit 7) */ -#define BLEIF_CMD_CONT_Msk (0x80UL) /*!< BLEIF CMD: CONT (Bitfield-Mask: 0x01) */ -#define BLEIF_CMD_OFFSETCNT_Pos (5UL) /*!< BLEIF CMD: OFFSETCNT (Bit 5) */ -#define BLEIF_CMD_OFFSETCNT_Msk (0x60UL) /*!< BLEIF CMD: OFFSETCNT (Bitfield-Mask: 0x03) */ -#define BLEIF_CMD_CMD_Pos (0UL) /*!< BLEIF CMD: CMD (Bit 0) */ -#define BLEIF_CMD_CMD_Msk (0x1fUL) /*!< BLEIF CMD: CMD (Bitfield-Mask: 0x1f) */ -/* ======================================================== CMDRPT ========================================================= */ -#define BLEIF_CMDRPT_CMDRPT_Pos (0UL) /*!< BLEIF CMDRPT: CMDRPT (Bit 0) */ -#define BLEIF_CMDRPT_CMDRPT_Msk (0x1fUL) /*!< BLEIF CMDRPT: CMDRPT (Bitfield-Mask: 0x1f) */ -/* ======================================================= OFFSETHI ======================================================== */ -#define BLEIF_OFFSETHI_OFFSETHI_Pos (0UL) /*!< BLEIF OFFSETHI: OFFSETHI (Bit 0) */ -#define BLEIF_OFFSETHI_OFFSETHI_Msk (0xffffUL) /*!< BLEIF OFFSETHI: OFFSETHI (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMDSTAT ======================================================== */ -#define BLEIF_CMDSTAT_CTSIZE_Pos (8UL) /*!< BLEIF CMDSTAT: CTSIZE (Bit 8) */ -#define BLEIF_CMDSTAT_CTSIZE_Msk (0xfff00UL) /*!< BLEIF CMDSTAT: CTSIZE (Bitfield-Mask: 0xfff) */ -#define BLEIF_CMDSTAT_CMDSTAT_Pos (5UL) /*!< BLEIF CMDSTAT: CMDSTAT (Bit 5) */ -#define BLEIF_CMDSTAT_CMDSTAT_Msk (0xe0UL) /*!< BLEIF CMDSTAT: CMDSTAT (Bitfield-Mask: 0x07) */ -#define BLEIF_CMDSTAT_CCMD_Pos (0UL) /*!< BLEIF CMDSTAT: CCMD (Bit 0) */ -#define BLEIF_CMDSTAT_CCMD_Msk (0x1fUL) /*!< BLEIF CMDSTAT: CCMD (Bitfield-Mask: 0x1f) */ -/* ========================================================= INTEN ========================================================= */ -#define BLEIF_INTEN_B2MSHUTDN_Pos (16UL) /*!< BLEIF INTEN: B2MSHUTDN (Bit 16) */ -#define BLEIF_INTEN_B2MSHUTDN_Msk (0x10000UL) /*!< BLEIF INTEN: B2MSHUTDN (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_B2MACTIVE_Pos (15UL) /*!< BLEIF INTEN: B2MACTIVE (Bit 15) */ -#define BLEIF_INTEN_B2MACTIVE_Msk (0x8000UL) /*!< BLEIF INTEN: B2MACTIVE (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_B2MSLEEP_Pos (14UL) /*!< BLEIF INTEN: B2MSLEEP (Bit 14) */ -#define BLEIF_INTEN_B2MSLEEP_Msk (0x4000UL) /*!< BLEIF INTEN: B2MSLEEP (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_CQERR_Pos (13UL) /*!< BLEIF INTEN: CQERR (Bit 13) */ -#define BLEIF_INTEN_CQERR_Msk (0x2000UL) /*!< BLEIF INTEN: CQERR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_CQUPD_Pos (12UL) /*!< BLEIF INTEN: CQUPD (Bit 12) */ -#define BLEIF_INTEN_CQUPD_Msk (0x1000UL) /*!< BLEIF INTEN: CQUPD (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_CQPAUSED_Pos (11UL) /*!< BLEIF INTEN: CQPAUSED (Bit 11) */ -#define BLEIF_INTEN_CQPAUSED_Msk (0x800UL) /*!< BLEIF INTEN: CQPAUSED (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_DERR_Pos (10UL) /*!< BLEIF INTEN: DERR (Bit 10) */ -#define BLEIF_INTEN_DERR_Msk (0x400UL) /*!< BLEIF INTEN: DERR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_DCMP_Pos (9UL) /*!< BLEIF INTEN: DCMP (Bit 9) */ -#define BLEIF_INTEN_DCMP_Msk (0x200UL) /*!< BLEIF INTEN: DCMP (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_BLECSSTAT_Pos (8UL) /*!< BLEIF INTEN: BLECSSTAT (Bit 8) */ -#define BLEIF_INTEN_BLECSSTAT_Msk (0x100UL) /*!< BLEIF INTEN: BLECSSTAT (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_BLECIRQ_Pos (7UL) /*!< BLEIF INTEN: BLECIRQ (Bit 7) */ -#define BLEIF_INTEN_BLECIRQ_Msk (0x80UL) /*!< BLEIF INTEN: BLECIRQ (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_ICMD_Pos (6UL) /*!< BLEIF INTEN: ICMD (Bit 6) */ -#define BLEIF_INTEN_ICMD_Msk (0x40UL) /*!< BLEIF INTEN: ICMD (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_IACC_Pos (5UL) /*!< BLEIF INTEN: IACC (Bit 5) */ -#define BLEIF_INTEN_IACC_Msk (0x20UL) /*!< BLEIF INTEN: IACC (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_B2MST_Pos (4UL) /*!< BLEIF INTEN: B2MST (Bit 4) */ -#define BLEIF_INTEN_B2MST_Msk (0x10UL) /*!< BLEIF INTEN: B2MST (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_FOVFL_Pos (3UL) /*!< BLEIF INTEN: FOVFL (Bit 3) */ -#define BLEIF_INTEN_FOVFL_Msk (0x8UL) /*!< BLEIF INTEN: FOVFL (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_FUNDFL_Pos (2UL) /*!< BLEIF INTEN: FUNDFL (Bit 2) */ -#define BLEIF_INTEN_FUNDFL_Msk (0x4UL) /*!< BLEIF INTEN: FUNDFL (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_THR_Pos (1UL) /*!< BLEIF INTEN: THR (Bit 1) */ -#define BLEIF_INTEN_THR_Msk (0x2UL) /*!< BLEIF INTEN: THR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTEN_CMDCMP_Pos (0UL) /*!< BLEIF INTEN: CMDCMP (Bit 0) */ -#define BLEIF_INTEN_CMDCMP_Msk (0x1UL) /*!< BLEIF INTEN: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define BLEIF_INTSTAT_B2MSHUTDN_Pos (16UL) /*!< BLEIF INTSTAT: B2MSHUTDN (Bit 16) */ -#define BLEIF_INTSTAT_B2MSHUTDN_Msk (0x10000UL) /*!< BLEIF INTSTAT: B2MSHUTDN (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_B2MACTIVE_Pos (15UL) /*!< BLEIF INTSTAT: B2MACTIVE (Bit 15) */ -#define BLEIF_INTSTAT_B2MACTIVE_Msk (0x8000UL) /*!< BLEIF INTSTAT: B2MACTIVE (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_B2MSLEEP_Pos (14UL) /*!< BLEIF INTSTAT: B2MSLEEP (Bit 14) */ -#define BLEIF_INTSTAT_B2MSLEEP_Msk (0x4000UL) /*!< BLEIF INTSTAT: B2MSLEEP (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_CQERR_Pos (13UL) /*!< BLEIF INTSTAT: CQERR (Bit 13) */ -#define BLEIF_INTSTAT_CQERR_Msk (0x2000UL) /*!< BLEIF INTSTAT: CQERR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_CQUPD_Pos (12UL) /*!< BLEIF INTSTAT: CQUPD (Bit 12) */ -#define BLEIF_INTSTAT_CQUPD_Msk (0x1000UL) /*!< BLEIF INTSTAT: CQUPD (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_CQPAUSED_Pos (11UL) /*!< BLEIF INTSTAT: CQPAUSED (Bit 11) */ -#define BLEIF_INTSTAT_CQPAUSED_Msk (0x800UL) /*!< BLEIF INTSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_DERR_Pos (10UL) /*!< BLEIF INTSTAT: DERR (Bit 10) */ -#define BLEIF_INTSTAT_DERR_Msk (0x400UL) /*!< BLEIF INTSTAT: DERR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_DCMP_Pos (9UL) /*!< BLEIF INTSTAT: DCMP (Bit 9) */ -#define BLEIF_INTSTAT_DCMP_Msk (0x200UL) /*!< BLEIF INTSTAT: DCMP (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_BLECSSTAT_Pos (8UL) /*!< BLEIF INTSTAT: BLECSSTAT (Bit 8) */ -#define BLEIF_INTSTAT_BLECSSTAT_Msk (0x100UL) /*!< BLEIF INTSTAT: BLECSSTAT (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_BLECIRQ_Pos (7UL) /*!< BLEIF INTSTAT: BLECIRQ (Bit 7) */ -#define BLEIF_INTSTAT_BLECIRQ_Msk (0x80UL) /*!< BLEIF INTSTAT: BLECIRQ (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_ICMD_Pos (6UL) /*!< BLEIF INTSTAT: ICMD (Bit 6) */ -#define BLEIF_INTSTAT_ICMD_Msk (0x40UL) /*!< BLEIF INTSTAT: ICMD (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_IACC_Pos (5UL) /*!< BLEIF INTSTAT: IACC (Bit 5) */ -#define BLEIF_INTSTAT_IACC_Msk (0x20UL) /*!< BLEIF INTSTAT: IACC (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_B2MST_Pos (4UL) /*!< BLEIF INTSTAT: B2MST (Bit 4) */ -#define BLEIF_INTSTAT_B2MST_Msk (0x10UL) /*!< BLEIF INTSTAT: B2MST (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_FOVFL_Pos (3UL) /*!< BLEIF INTSTAT: FOVFL (Bit 3) */ -#define BLEIF_INTSTAT_FOVFL_Msk (0x8UL) /*!< BLEIF INTSTAT: FOVFL (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_FUNDFL_Pos (2UL) /*!< BLEIF INTSTAT: FUNDFL (Bit 2) */ -#define BLEIF_INTSTAT_FUNDFL_Msk (0x4UL) /*!< BLEIF INTSTAT: FUNDFL (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_THR_Pos (1UL) /*!< BLEIF INTSTAT: THR (Bit 1) */ -#define BLEIF_INTSTAT_THR_Msk (0x2UL) /*!< BLEIF INTSTAT: THR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSTAT_CMDCMP_Pos (0UL) /*!< BLEIF INTSTAT: CMDCMP (Bit 0) */ -#define BLEIF_INTSTAT_CMDCMP_Msk (0x1UL) /*!< BLEIF INTSTAT: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define BLEIF_INTCLR_B2MSHUTDN_Pos (16UL) /*!< BLEIF INTCLR: B2MSHUTDN (Bit 16) */ -#define BLEIF_INTCLR_B2MSHUTDN_Msk (0x10000UL) /*!< BLEIF INTCLR: B2MSHUTDN (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_B2MACTIVE_Pos (15UL) /*!< BLEIF INTCLR: B2MACTIVE (Bit 15) */ -#define BLEIF_INTCLR_B2MACTIVE_Msk (0x8000UL) /*!< BLEIF INTCLR: B2MACTIVE (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_B2MSLEEP_Pos (14UL) /*!< BLEIF INTCLR: B2MSLEEP (Bit 14) */ -#define BLEIF_INTCLR_B2MSLEEP_Msk (0x4000UL) /*!< BLEIF INTCLR: B2MSLEEP (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_CQERR_Pos (13UL) /*!< BLEIF INTCLR: CQERR (Bit 13) */ -#define BLEIF_INTCLR_CQERR_Msk (0x2000UL) /*!< BLEIF INTCLR: CQERR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_CQUPD_Pos (12UL) /*!< BLEIF INTCLR: CQUPD (Bit 12) */ -#define BLEIF_INTCLR_CQUPD_Msk (0x1000UL) /*!< BLEIF INTCLR: CQUPD (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_CQPAUSED_Pos (11UL) /*!< BLEIF INTCLR: CQPAUSED (Bit 11) */ -#define BLEIF_INTCLR_CQPAUSED_Msk (0x800UL) /*!< BLEIF INTCLR: CQPAUSED (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_DERR_Pos (10UL) /*!< BLEIF INTCLR: DERR (Bit 10) */ -#define BLEIF_INTCLR_DERR_Msk (0x400UL) /*!< BLEIF INTCLR: DERR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_DCMP_Pos (9UL) /*!< BLEIF INTCLR: DCMP (Bit 9) */ -#define BLEIF_INTCLR_DCMP_Msk (0x200UL) /*!< BLEIF INTCLR: DCMP (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_BLECSSTAT_Pos (8UL) /*!< BLEIF INTCLR: BLECSSTAT (Bit 8) */ -#define BLEIF_INTCLR_BLECSSTAT_Msk (0x100UL) /*!< BLEIF INTCLR: BLECSSTAT (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_BLECIRQ_Pos (7UL) /*!< BLEIF INTCLR: BLECIRQ (Bit 7) */ -#define BLEIF_INTCLR_BLECIRQ_Msk (0x80UL) /*!< BLEIF INTCLR: BLECIRQ (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_ICMD_Pos (6UL) /*!< BLEIF INTCLR: ICMD (Bit 6) */ -#define BLEIF_INTCLR_ICMD_Msk (0x40UL) /*!< BLEIF INTCLR: ICMD (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_IACC_Pos (5UL) /*!< BLEIF INTCLR: IACC (Bit 5) */ -#define BLEIF_INTCLR_IACC_Msk (0x20UL) /*!< BLEIF INTCLR: IACC (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_B2MST_Pos (4UL) /*!< BLEIF INTCLR: B2MST (Bit 4) */ -#define BLEIF_INTCLR_B2MST_Msk (0x10UL) /*!< BLEIF INTCLR: B2MST (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_FOVFL_Pos (3UL) /*!< BLEIF INTCLR: FOVFL (Bit 3) */ -#define BLEIF_INTCLR_FOVFL_Msk (0x8UL) /*!< BLEIF INTCLR: FOVFL (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_FUNDFL_Pos (2UL) /*!< BLEIF INTCLR: FUNDFL (Bit 2) */ -#define BLEIF_INTCLR_FUNDFL_Msk (0x4UL) /*!< BLEIF INTCLR: FUNDFL (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_THR_Pos (1UL) /*!< BLEIF INTCLR: THR (Bit 1) */ -#define BLEIF_INTCLR_THR_Msk (0x2UL) /*!< BLEIF INTCLR: THR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTCLR_CMDCMP_Pos (0UL) /*!< BLEIF INTCLR: CMDCMP (Bit 0) */ -#define BLEIF_INTCLR_CMDCMP_Msk (0x1UL) /*!< BLEIF INTCLR: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define BLEIF_INTSET_B2MSHUTDN_Pos (16UL) /*!< BLEIF INTSET: B2MSHUTDN (Bit 16) */ -#define BLEIF_INTSET_B2MSHUTDN_Msk (0x10000UL) /*!< BLEIF INTSET: B2MSHUTDN (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_B2MACTIVE_Pos (15UL) /*!< BLEIF INTSET: B2MACTIVE (Bit 15) */ -#define BLEIF_INTSET_B2MACTIVE_Msk (0x8000UL) /*!< BLEIF INTSET: B2MACTIVE (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_B2MSLEEP_Pos (14UL) /*!< BLEIF INTSET: B2MSLEEP (Bit 14) */ -#define BLEIF_INTSET_B2MSLEEP_Msk (0x4000UL) /*!< BLEIF INTSET: B2MSLEEP (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_CQERR_Pos (13UL) /*!< BLEIF INTSET: CQERR (Bit 13) */ -#define BLEIF_INTSET_CQERR_Msk (0x2000UL) /*!< BLEIF INTSET: CQERR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_CQUPD_Pos (12UL) /*!< BLEIF INTSET: CQUPD (Bit 12) */ -#define BLEIF_INTSET_CQUPD_Msk (0x1000UL) /*!< BLEIF INTSET: CQUPD (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_CQPAUSED_Pos (11UL) /*!< BLEIF INTSET: CQPAUSED (Bit 11) */ -#define BLEIF_INTSET_CQPAUSED_Msk (0x800UL) /*!< BLEIF INTSET: CQPAUSED (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_DERR_Pos (10UL) /*!< BLEIF INTSET: DERR (Bit 10) */ -#define BLEIF_INTSET_DERR_Msk (0x400UL) /*!< BLEIF INTSET: DERR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_DCMP_Pos (9UL) /*!< BLEIF INTSET: DCMP (Bit 9) */ -#define BLEIF_INTSET_DCMP_Msk (0x200UL) /*!< BLEIF INTSET: DCMP (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_BLECSSTAT_Pos (8UL) /*!< BLEIF INTSET: BLECSSTAT (Bit 8) */ -#define BLEIF_INTSET_BLECSSTAT_Msk (0x100UL) /*!< BLEIF INTSET: BLECSSTAT (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_BLECIRQ_Pos (7UL) /*!< BLEIF INTSET: BLECIRQ (Bit 7) */ -#define BLEIF_INTSET_BLECIRQ_Msk (0x80UL) /*!< BLEIF INTSET: BLECIRQ (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_ICMD_Pos (6UL) /*!< BLEIF INTSET: ICMD (Bit 6) */ -#define BLEIF_INTSET_ICMD_Msk (0x40UL) /*!< BLEIF INTSET: ICMD (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_IACC_Pos (5UL) /*!< BLEIF INTSET: IACC (Bit 5) */ -#define BLEIF_INTSET_IACC_Msk (0x20UL) /*!< BLEIF INTSET: IACC (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_B2MST_Pos (4UL) /*!< BLEIF INTSET: B2MST (Bit 4) */ -#define BLEIF_INTSET_B2MST_Msk (0x10UL) /*!< BLEIF INTSET: B2MST (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_FOVFL_Pos (3UL) /*!< BLEIF INTSET: FOVFL (Bit 3) */ -#define BLEIF_INTSET_FOVFL_Msk (0x8UL) /*!< BLEIF INTSET: FOVFL (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_FUNDFL_Pos (2UL) /*!< BLEIF INTSET: FUNDFL (Bit 2) */ -#define BLEIF_INTSET_FUNDFL_Msk (0x4UL) /*!< BLEIF INTSET: FUNDFL (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_THR_Pos (1UL) /*!< BLEIF INTSET: THR (Bit 1) */ -#define BLEIF_INTSET_THR_Msk (0x2UL) /*!< BLEIF INTSET: THR (Bitfield-Mask: 0x01) */ -#define BLEIF_INTSET_CMDCMP_Pos (0UL) /*!< BLEIF INTSET: CMDCMP (Bit 0) */ -#define BLEIF_INTSET_CMDCMP_Msk (0x1UL) /*!< BLEIF INTSET: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================= DMATRIGEN ======================================================= */ -#define BLEIF_DMATRIGEN_DTHREN_Pos (1UL) /*!< BLEIF DMATRIGEN: DTHREN (Bit 1) */ -#define BLEIF_DMATRIGEN_DTHREN_Msk (0x2UL) /*!< BLEIF DMATRIGEN: DTHREN (Bitfield-Mask: 0x01) */ -#define BLEIF_DMATRIGEN_DCMDCMPEN_Pos (0UL) /*!< BLEIF DMATRIGEN: DCMDCMPEN (Bit 0) */ -#define BLEIF_DMATRIGEN_DCMDCMPEN_Msk (0x1UL) /*!< BLEIF DMATRIGEN: DCMDCMPEN (Bitfield-Mask: 0x01) */ -/* ====================================================== DMATRIGSTAT ====================================================== */ -#define BLEIF_DMATRIGSTAT_DTOTCMP_Pos (2UL) /*!< BLEIF DMATRIGSTAT: DTOTCMP (Bit 2) */ -#define BLEIF_DMATRIGSTAT_DTOTCMP_Msk (0x4UL) /*!< BLEIF DMATRIGSTAT: DTOTCMP (Bitfield-Mask: 0x01) */ -#define BLEIF_DMATRIGSTAT_DTHR_Pos (1UL) /*!< BLEIF DMATRIGSTAT: DTHR (Bit 1) */ -#define BLEIF_DMATRIGSTAT_DTHR_Msk (0x2UL) /*!< BLEIF DMATRIGSTAT: DTHR (Bitfield-Mask: 0x01) */ -#define BLEIF_DMATRIGSTAT_DCMDCMP_Pos (0UL) /*!< BLEIF DMATRIGSTAT: DCMDCMP (Bit 0) */ -#define BLEIF_DMATRIGSTAT_DCMDCMP_Msk (0x1UL) /*!< BLEIF DMATRIGSTAT: DCMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== DMACFG ========================================================= */ -#define BLEIF_DMACFG_DPWROFF_Pos (9UL) /*!< BLEIF DMACFG: DPWROFF (Bit 9) */ -#define BLEIF_DMACFG_DPWROFF_Msk (0x200UL) /*!< BLEIF DMACFG: DPWROFF (Bitfield-Mask: 0x01) */ -#define BLEIF_DMACFG_DMAPRI_Pos (8UL) /*!< BLEIF DMACFG: DMAPRI (Bit 8) */ -#define BLEIF_DMACFG_DMAPRI_Msk (0x100UL) /*!< BLEIF DMACFG: DMAPRI (Bitfield-Mask: 0x01) */ -#define BLEIF_DMACFG_DMADIR_Pos (1UL) /*!< BLEIF DMACFG: DMADIR (Bit 1) */ -#define BLEIF_DMACFG_DMADIR_Msk (0x2UL) /*!< BLEIF DMACFG: DMADIR (Bitfield-Mask: 0x01) */ -#define BLEIF_DMACFG_DMAEN_Pos (0UL) /*!< BLEIF DMACFG: DMAEN (Bit 0) */ -#define BLEIF_DMACFG_DMAEN_Msk (0x1UL) /*!< BLEIF DMACFG: DMAEN (Bitfield-Mask: 0x01) */ -/* ====================================================== DMATOTCOUNT ====================================================== */ -#define BLEIF_DMATOTCOUNT_TOTCOUNT_Pos (0UL) /*!< BLEIF DMATOTCOUNT: TOTCOUNT (Bit 0) */ -#define BLEIF_DMATOTCOUNT_TOTCOUNT_Msk (0xfffUL) /*!< BLEIF DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xfff) */ -/* ====================================================== DMATARGADDR ====================================================== */ -#define BLEIF_DMATARGADDR_TARGADDR28_Pos (28UL) /*!< BLEIF DMATARGADDR: TARGADDR28 (Bit 28) */ -#define BLEIF_DMATARGADDR_TARGADDR28_Msk (0x10000000UL) /*!< BLEIF DMATARGADDR: TARGADDR28 (Bitfield-Mask: 0x01) */ -#define BLEIF_DMATARGADDR_TARGADDR_Pos (0UL) /*!< BLEIF DMATARGADDR: TARGADDR (Bit 0) */ -#define BLEIF_DMATARGADDR_TARGADDR_Msk (0xfffffUL) /*!< BLEIF DMATARGADDR: TARGADDR (Bitfield-Mask: 0xfffff) */ -/* ======================================================== DMASTAT ======================================================== */ -#define BLEIF_DMASTAT_DMAERR_Pos (2UL) /*!< BLEIF DMASTAT: DMAERR (Bit 2) */ -#define BLEIF_DMASTAT_DMAERR_Msk (0x4UL) /*!< BLEIF DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ -#define BLEIF_DMASTAT_DMACPL_Pos (1UL) /*!< BLEIF DMASTAT: DMACPL (Bit 1) */ -#define BLEIF_DMASTAT_DMACPL_Msk (0x2UL) /*!< BLEIF DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ -#define BLEIF_DMASTAT_DMATIP_Pos (0UL) /*!< BLEIF DMASTAT: DMATIP (Bit 0) */ -#define BLEIF_DMASTAT_DMATIP_Msk (0x1UL) /*!< BLEIF DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ -/* ========================================================= CQCFG ========================================================= */ -#define BLEIF_CQCFG_CQPRI_Pos (1UL) /*!< BLEIF CQCFG: CQPRI (Bit 1) */ -#define BLEIF_CQCFG_CQPRI_Msk (0x2UL) /*!< BLEIF CQCFG: CQPRI (Bitfield-Mask: 0x01) */ -#define BLEIF_CQCFG_CQEN_Pos (0UL) /*!< BLEIF CQCFG: CQEN (Bit 0) */ -#define BLEIF_CQCFG_CQEN_Msk (0x1UL) /*!< BLEIF CQCFG: CQEN (Bitfield-Mask: 0x01) */ -/* ======================================================== CQADDR ========================================================= */ -#define BLEIF_CQADDR_CQADDR28_Pos (28UL) /*!< BLEIF CQADDR: CQADDR28 (Bit 28) */ -#define BLEIF_CQADDR_CQADDR28_Msk (0x10000000UL) /*!< BLEIF CQADDR: CQADDR28 (Bitfield-Mask: 0x01) */ -#define BLEIF_CQADDR_CQADDR_Pos (2UL) /*!< BLEIF CQADDR: CQADDR (Bit 2) */ -#define BLEIF_CQADDR_CQADDR_Msk (0xffffcUL) /*!< BLEIF CQADDR: CQADDR (Bitfield-Mask: 0x3ffff) */ -/* ======================================================== CQSTAT ========================================================= */ -#define BLEIF_CQSTAT_CQERR_Pos (2UL) /*!< BLEIF CQSTAT: CQERR (Bit 2) */ -#define BLEIF_CQSTAT_CQERR_Msk (0x4UL) /*!< BLEIF CQSTAT: CQERR (Bitfield-Mask: 0x01) */ -#define BLEIF_CQSTAT_CQPAUSED_Pos (1UL) /*!< BLEIF CQSTAT: CQPAUSED (Bit 1) */ -#define BLEIF_CQSTAT_CQPAUSED_Msk (0x2UL) /*!< BLEIF CQSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ -#define BLEIF_CQSTAT_CQTIP_Pos (0UL) /*!< BLEIF CQSTAT: CQTIP (Bit 0) */ -#define BLEIF_CQSTAT_CQTIP_Msk (0x1UL) /*!< BLEIF CQSTAT: CQTIP (Bitfield-Mask: 0x01) */ -/* ======================================================== CQFLAGS ======================================================== */ -#define BLEIF_CQFLAGS_CQIRQMASK_Pos (16UL) /*!< BLEIF CQFLAGS: CQIRQMASK (Bit 16) */ -#define BLEIF_CQFLAGS_CQIRQMASK_Msk (0xffff0000UL) /*!< BLEIF CQFLAGS: CQIRQMASK (Bitfield-Mask: 0xffff) */ -#define BLEIF_CQFLAGS_CQFLAGS_Pos (0UL) /*!< BLEIF CQFLAGS: CQFLAGS (Bit 0) */ -#define BLEIF_CQFLAGS_CQFLAGS_Msk (0xffffUL) /*!< BLEIF CQFLAGS: CQFLAGS (Bitfield-Mask: 0xffff) */ -/* ====================================================== CQSETCLEAR ======================================================= */ -#define BLEIF_CQSETCLEAR_CQFCLR_Pos (16UL) /*!< BLEIF CQSETCLEAR: CQFCLR (Bit 16) */ -#define BLEIF_CQSETCLEAR_CQFCLR_Msk (0xff0000UL) /*!< BLEIF CQSETCLEAR: CQFCLR (Bitfield-Mask: 0xff) */ -#define BLEIF_CQSETCLEAR_CQFTGL_Pos (8UL) /*!< BLEIF CQSETCLEAR: CQFTGL (Bit 8) */ -#define BLEIF_CQSETCLEAR_CQFTGL_Msk (0xff00UL) /*!< BLEIF CQSETCLEAR: CQFTGL (Bitfield-Mask: 0xff) */ -#define BLEIF_CQSETCLEAR_CQFSET_Pos (0UL) /*!< BLEIF CQSETCLEAR: CQFSET (Bit 0) */ -#define BLEIF_CQSETCLEAR_CQFSET_Msk (0xffUL) /*!< BLEIF CQSETCLEAR: CQFSET (Bitfield-Mask: 0xff) */ -/* ======================================================= CQPAUSEEN ======================================================= */ -#define BLEIF_CQPAUSEEN_CQPEN_Pos (0UL) /*!< BLEIF CQPAUSEEN: CQPEN (Bit 0) */ -#define BLEIF_CQPAUSEEN_CQPEN_Msk (0xffffUL) /*!< BLEIF CQPAUSEEN: CQPEN (Bitfield-Mask: 0xffff) */ -/* ======================================================= CQCURIDX ======================================================== */ -#define BLEIF_CQCURIDX_CQCURIDX_Pos (0UL) /*!< BLEIF CQCURIDX: CQCURIDX (Bit 0) */ -#define BLEIF_CQCURIDX_CQCURIDX_Msk (0xffUL) /*!< BLEIF CQCURIDX: CQCURIDX (Bitfield-Mask: 0xff) */ -/* ======================================================= CQENDIDX ======================================================== */ -#define BLEIF_CQENDIDX_CQENDIDX_Pos (0UL) /*!< BLEIF CQENDIDX: CQENDIDX (Bit 0) */ -#define BLEIF_CQENDIDX_CQENDIDX_Msk (0xffUL) /*!< BLEIF CQENDIDX: CQENDIDX (Bitfield-Mask: 0xff) */ -/* ======================================================== STATUS ========================================================= */ -#define BLEIF_STATUS_IDLEST_Pos (2UL) /*!< BLEIF STATUS: IDLEST (Bit 2) */ -#define BLEIF_STATUS_IDLEST_Msk (0x4UL) /*!< BLEIF STATUS: IDLEST (Bitfield-Mask: 0x01) */ -#define BLEIF_STATUS_CMDACT_Pos (1UL) /*!< BLEIF STATUS: CMDACT (Bit 1) */ -#define BLEIF_STATUS_CMDACT_Msk (0x2UL) /*!< BLEIF STATUS: CMDACT (Bitfield-Mask: 0x01) */ -#define BLEIF_STATUS_ERR_Pos (0UL) /*!< BLEIF STATUS: ERR (Bit 0) */ -#define BLEIF_STATUS_ERR_Msk (0x1UL) /*!< BLEIF STATUS: ERR (Bitfield-Mask: 0x01) */ -/* ======================================================== MSPICFG ======================================================== */ -#define BLEIF_MSPICFG_MSPIRST_Pos (30UL) /*!< BLEIF MSPICFG: MSPIRST (Bit 30) */ -#define BLEIF_MSPICFG_MSPIRST_Msk (0x40000000UL) /*!< BLEIF MSPICFG: MSPIRST (Bitfield-Mask: 0x01) */ -#define BLEIF_MSPICFG_DOUTDLY_Pos (27UL) /*!< BLEIF MSPICFG: DOUTDLY (Bit 27) */ -#define BLEIF_MSPICFG_DOUTDLY_Msk (0x38000000UL) /*!< BLEIF MSPICFG: DOUTDLY (Bitfield-Mask: 0x07) */ -#define BLEIF_MSPICFG_DINDLY_Pos (24UL) /*!< BLEIF MSPICFG: DINDLY (Bit 24) */ -#define BLEIF_MSPICFG_DINDLY_Msk (0x7000000UL) /*!< BLEIF MSPICFG: DINDLY (Bitfield-Mask: 0x07) */ -#define BLEIF_MSPICFG_SPILSB_Pos (23UL) /*!< BLEIF MSPICFG: SPILSB (Bit 23) */ -#define BLEIF_MSPICFG_SPILSB_Msk (0x800000UL) /*!< BLEIF MSPICFG: SPILSB (Bitfield-Mask: 0x01) */ -#define BLEIF_MSPICFG_RDFCPOL_Pos (22UL) /*!< BLEIF MSPICFG: RDFCPOL (Bit 22) */ -#define BLEIF_MSPICFG_RDFCPOL_Msk (0x400000UL) /*!< BLEIF MSPICFG: RDFCPOL (Bitfield-Mask: 0x01) */ -#define BLEIF_MSPICFG_WTFCPOL_Pos (21UL) /*!< BLEIF MSPICFG: WTFCPOL (Bit 21) */ -#define BLEIF_MSPICFG_WTFCPOL_Msk (0x200000UL) /*!< BLEIF MSPICFG: WTFCPOL (Bitfield-Mask: 0x01) */ -#define BLEIF_MSPICFG_RDFC_Pos (17UL) /*!< BLEIF MSPICFG: RDFC (Bit 17) */ -#define BLEIF_MSPICFG_RDFC_Msk (0x20000UL) /*!< BLEIF MSPICFG: RDFC (Bitfield-Mask: 0x01) */ -#define BLEIF_MSPICFG_WTFC_Pos (16UL) /*!< BLEIF MSPICFG: WTFC (Bit 16) */ -#define BLEIF_MSPICFG_WTFC_Msk (0x10000UL) /*!< BLEIF MSPICFG: WTFC (Bitfield-Mask: 0x01) */ -#define BLEIF_MSPICFG_FULLDUP_Pos (2UL) /*!< BLEIF MSPICFG: FULLDUP (Bit 2) */ -#define BLEIF_MSPICFG_FULLDUP_Msk (0x4UL) /*!< BLEIF MSPICFG: FULLDUP (Bitfield-Mask: 0x01) */ -#define BLEIF_MSPICFG_SPHA_Pos (1UL) /*!< BLEIF MSPICFG: SPHA (Bit 1) */ -#define BLEIF_MSPICFG_SPHA_Msk (0x2UL) /*!< BLEIF MSPICFG: SPHA (Bitfield-Mask: 0x01) */ -#define BLEIF_MSPICFG_SPOL_Pos (0UL) /*!< BLEIF MSPICFG: SPOL (Bit 0) */ -#define BLEIF_MSPICFG_SPOL_Msk (0x1UL) /*!< BLEIF MSPICFG: SPOL (Bitfield-Mask: 0x01) */ -/* ======================================================== BLECFG ========================================================= */ -#define BLEIF_BLECFG_SPIISOCTL_Pos (14UL) /*!< BLEIF BLECFG: SPIISOCTL (Bit 14) */ -#define BLEIF_BLECFG_SPIISOCTL_Msk (0xc000UL) /*!< BLEIF BLECFG: SPIISOCTL (Bitfield-Mask: 0x03) */ -#define BLEIF_BLECFG_PWRISOCTL_Pos (12UL) /*!< BLEIF BLECFG: PWRISOCTL (Bit 12) */ -#define BLEIF_BLECFG_PWRISOCTL_Msk (0x3000UL) /*!< BLEIF BLECFG: PWRISOCTL (Bitfield-Mask: 0x03) */ -#define BLEIF_BLECFG_STAYASLEEP_Pos (11UL) /*!< BLEIF BLECFG: STAYASLEEP (Bit 11) */ -#define BLEIF_BLECFG_STAYASLEEP_Msk (0x800UL) /*!< BLEIF BLECFG: STAYASLEEP (Bitfield-Mask: 0x01) */ -#define BLEIF_BLECFG_FRCCLK_Pos (10UL) /*!< BLEIF BLECFG: FRCCLK (Bit 10) */ -#define BLEIF_BLECFG_FRCCLK_Msk (0x400UL) /*!< BLEIF BLECFG: FRCCLK (Bitfield-Mask: 0x01) */ -#define BLEIF_BLECFG_MCUFRCSLP_Pos (9UL) /*!< BLEIF BLECFG: MCUFRCSLP (Bit 9) */ -#define BLEIF_BLECFG_MCUFRCSLP_Msk (0x200UL) /*!< BLEIF BLECFG: MCUFRCSLP (Bitfield-Mask: 0x01) */ -#define BLEIF_BLECFG_WT4ACTOFF_Pos (8UL) /*!< BLEIF BLECFG: WT4ACTOFF (Bit 8) */ -#define BLEIF_BLECFG_WT4ACTOFF_Msk (0x100UL) /*!< BLEIF BLECFG: WT4ACTOFF (Bitfield-Mask: 0x01) */ -#define BLEIF_BLECFG_BLEHREQCTL_Pos (6UL) /*!< BLEIF BLECFG: BLEHREQCTL (Bit 6) */ -#define BLEIF_BLECFG_BLEHREQCTL_Msk (0xc0UL) /*!< BLEIF BLECFG: BLEHREQCTL (Bitfield-Mask: 0x03) */ -#define BLEIF_BLECFG_DCDCFLGCTL_Pos (4UL) /*!< BLEIF BLECFG: DCDCFLGCTL (Bit 4) */ -#define BLEIF_BLECFG_DCDCFLGCTL_Msk (0x30UL) /*!< BLEIF BLECFG: DCDCFLGCTL (Bitfield-Mask: 0x03) */ -#define BLEIF_BLECFG_WAKEUPCTL_Pos (2UL) /*!< BLEIF BLECFG: WAKEUPCTL (Bit 2) */ -#define BLEIF_BLECFG_WAKEUPCTL_Msk (0xcUL) /*!< BLEIF BLECFG: WAKEUPCTL (Bitfield-Mask: 0x03) */ -#define BLEIF_BLECFG_BLERSTN_Pos (1UL) /*!< BLEIF BLECFG: BLERSTN (Bit 1) */ -#define BLEIF_BLECFG_BLERSTN_Msk (0x2UL) /*!< BLEIF BLECFG: BLERSTN (Bitfield-Mask: 0x01) */ -#define BLEIF_BLECFG_PWRSMEN_Pos (0UL) /*!< BLEIF BLECFG: PWRSMEN (Bit 0) */ -#define BLEIF_BLECFG_PWRSMEN_Msk (0x1UL) /*!< BLEIF BLECFG: PWRSMEN (Bitfield-Mask: 0x01) */ -/* ======================================================== PWRCMD ========================================================= */ -#define BLEIF_PWRCMD_RESTART_Pos (1UL) /*!< BLEIF PWRCMD: RESTART (Bit 1) */ -#define BLEIF_PWRCMD_RESTART_Msk (0x2UL) /*!< BLEIF PWRCMD: RESTART (Bitfield-Mask: 0x01) */ -#define BLEIF_PWRCMD_WAKEREQ_Pos (0UL) /*!< BLEIF PWRCMD: WAKEREQ (Bit 0) */ -#define BLEIF_PWRCMD_WAKEREQ_Msk (0x1UL) /*!< BLEIF PWRCMD: WAKEREQ (Bitfield-Mask: 0x01) */ -/* ======================================================== BSTATUS ======================================================== */ -#define BLEIF_BSTATUS_BLEHREQ_Pos (12UL) /*!< BLEIF BSTATUS: BLEHREQ (Bit 12) */ -#define BLEIF_BSTATUS_BLEHREQ_Msk (0x1000UL) /*!< BLEIF BSTATUS: BLEHREQ (Bitfield-Mask: 0x01) */ -#define BLEIF_BSTATUS_BLEHACK_Pos (11UL) /*!< BLEIF BSTATUS: BLEHACK (Bit 11) */ -#define BLEIF_BSTATUS_BLEHACK_Msk (0x800UL) /*!< BLEIF BSTATUS: BLEHACK (Bitfield-Mask: 0x01) */ -#define BLEIF_BSTATUS_PWRST_Pos (8UL) /*!< BLEIF BSTATUS: PWRST (Bit 8) */ -#define BLEIF_BSTATUS_PWRST_Msk (0x700UL) /*!< BLEIF BSTATUS: PWRST (Bitfield-Mask: 0x07) */ -#define BLEIF_BSTATUS_BLEIRQ_Pos (7UL) /*!< BLEIF BSTATUS: BLEIRQ (Bit 7) */ -#define BLEIF_BSTATUS_BLEIRQ_Msk (0x80UL) /*!< BLEIF BSTATUS: BLEIRQ (Bitfield-Mask: 0x01) */ -#define BLEIF_BSTATUS_WAKEUP_Pos (6UL) /*!< BLEIF BSTATUS: WAKEUP (Bit 6) */ -#define BLEIF_BSTATUS_WAKEUP_Msk (0x40UL) /*!< BLEIF BSTATUS: WAKEUP (Bitfield-Mask: 0x01) */ -#define BLEIF_BSTATUS_DCDCFLAG_Pos (5UL) /*!< BLEIF BSTATUS: DCDCFLAG (Bit 5) */ -#define BLEIF_BSTATUS_DCDCFLAG_Msk (0x20UL) /*!< BLEIF BSTATUS: DCDCFLAG (Bitfield-Mask: 0x01) */ -#define BLEIF_BSTATUS_DCDCREQ_Pos (4UL) /*!< BLEIF BSTATUS: DCDCREQ (Bit 4) */ -#define BLEIF_BSTATUS_DCDCREQ_Msk (0x10UL) /*!< BLEIF BSTATUS: DCDCREQ (Bitfield-Mask: 0x01) */ -#define BLEIF_BSTATUS_SPISTATUS_Pos (3UL) /*!< BLEIF BSTATUS: SPISTATUS (Bit 3) */ -#define BLEIF_BSTATUS_SPISTATUS_Msk (0x8UL) /*!< BLEIF BSTATUS: SPISTATUS (Bitfield-Mask: 0x01) */ -#define BLEIF_BSTATUS_B2MSTATE_Pos (0UL) /*!< BLEIF BSTATUS: B2MSTATE (Bit 0) */ -#define BLEIF_BSTATUS_B2MSTATE_Msk (0x7UL) /*!< BLEIF BSTATUS: B2MSTATE (Bitfield-Mask: 0x07) */ -/* ======================================================== BLEDBG ========================================================= */ -#define BLEIF_BLEDBG_DBGDATA_Pos (3UL) /*!< BLEIF BLEDBG: DBGDATA (Bit 3) */ -#define BLEIF_BLEDBG_DBGDATA_Msk (0xfffffff8UL) /*!< BLEIF BLEDBG: DBGDATA (Bitfield-Mask: 0x1fffffff) */ -#define BLEIF_BLEDBG_APBCLKON_Pos (2UL) /*!< BLEIF BLEDBG: APBCLKON (Bit 2) */ -#define BLEIF_BLEDBG_APBCLKON_Msk (0x4UL) /*!< BLEIF BLEDBG: APBCLKON (Bitfield-Mask: 0x01) */ -#define BLEIF_BLEDBG_IOCLKON_Pos (1UL) /*!< BLEIF BLEDBG: IOCLKON (Bit 1) */ -#define BLEIF_BLEDBG_IOCLKON_Msk (0x2UL) /*!< BLEIF BLEDBG: IOCLKON (Bitfield-Mask: 0x01) */ -#define BLEIF_BLEDBG_DBGEN_Pos (0UL) /*!< BLEIF BLEDBG: DBGEN (Bit 0) */ -#define BLEIF_BLEDBG_DBGEN_Msk (0x1UL) /*!< BLEIF BLEDBG: DBGEN (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ CACHECTRL ================ */ -/* =========================================================================================================================== */ - -/* ======================================================= CACHECFG ======================================================== */ -#define CACHECTRL_CACHECFG_ENABLE_MONITOR_Pos (24UL) /*!< CACHECTRL CACHECFG: ENABLE_MONITOR (Bit 24) */ -#define CACHECTRL_CACHECFG_ENABLE_MONITOR_Msk (0x1000000UL) /*!< CACHECTRL CACHECFG: ENABLE_MONITOR (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CACHECFG_DATA_CLKGATE_Pos (20UL) /*!< CACHECTRL CACHECFG: DATA_CLKGATE (Bit 20) */ -#define CACHECTRL_CACHECFG_DATA_CLKGATE_Msk (0x100000UL) /*!< CACHECTRL CACHECFG: DATA_CLKGATE (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CACHECFG_CACHE_LS_Pos (11UL) /*!< CACHECTRL CACHECFG: CACHE_LS (Bit 11) */ -#define CACHECTRL_CACHECFG_CACHE_LS_Msk (0x800UL) /*!< CACHECTRL CACHECFG: CACHE_LS (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CACHECFG_CACHE_CLKGATE_Pos (10UL) /*!< CACHECTRL CACHECFG: CACHE_CLKGATE (Bit 10) */ -#define CACHECTRL_CACHECFG_CACHE_CLKGATE_Msk (0x400UL) /*!< CACHECTRL CACHECFG: CACHE_CLKGATE (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CACHECFG_DCACHE_ENABLE_Pos (9UL) /*!< CACHECTRL CACHECFG: DCACHE_ENABLE (Bit 9) */ -#define CACHECTRL_CACHECFG_DCACHE_ENABLE_Msk (0x200UL) /*!< CACHECTRL CACHECFG: DCACHE_ENABLE (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CACHECFG_ICACHE_ENABLE_Pos (8UL) /*!< CACHECTRL CACHECFG: ICACHE_ENABLE (Bit 8) */ -#define CACHECTRL_CACHECFG_ICACHE_ENABLE_Msk (0x100UL) /*!< CACHECTRL CACHECFG: ICACHE_ENABLE (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CACHECFG_CONFIG_Pos (4UL) /*!< CACHECTRL CACHECFG: CONFIG (Bit 4) */ -#define CACHECTRL_CACHECFG_CONFIG_Msk (0xf0UL) /*!< CACHECTRL CACHECFG: CONFIG (Bitfield-Mask: 0x0f) */ -#define CACHECTRL_CACHECFG_ENABLE_NC1_Pos (3UL) /*!< CACHECTRL CACHECFG: ENABLE_NC1 (Bit 3) */ -#define CACHECTRL_CACHECFG_ENABLE_NC1_Msk (0x8UL) /*!< CACHECTRL CACHECFG: ENABLE_NC1 (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CACHECFG_ENABLE_NC0_Pos (2UL) /*!< CACHECTRL CACHECFG: ENABLE_NC0 (Bit 2) */ -#define CACHECTRL_CACHECFG_ENABLE_NC0_Msk (0x4UL) /*!< CACHECTRL CACHECFG: ENABLE_NC0 (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CACHECFG_LRU_Pos (1UL) /*!< CACHECTRL CACHECFG: LRU (Bit 1) */ -#define CACHECTRL_CACHECFG_LRU_Msk (0x2UL) /*!< CACHECTRL CACHECFG: LRU (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CACHECFG_ENABLE_Pos (0UL) /*!< CACHECTRL CACHECFG: ENABLE (Bit 0) */ -#define CACHECTRL_CACHECFG_ENABLE_Msk (0x1UL) /*!< CACHECTRL CACHECFG: ENABLE (Bitfield-Mask: 0x01) */ -/* ======================================================= FLASHCFG ======================================================== */ -#define CACHECTRL_FLASHCFG_LPMMODE_Pos (12UL) /*!< CACHECTRL FLASHCFG: LPMMODE (Bit 12) */ -#define CACHECTRL_FLASHCFG_LPMMODE_Msk (0x3000UL) /*!< CACHECTRL FLASHCFG: LPMMODE (Bitfield-Mask: 0x03) */ -#define CACHECTRL_FLASHCFG_LPM_RD_WAIT_Pos (8UL) /*!< CACHECTRL FLASHCFG: LPM_RD_WAIT (Bit 8) */ -#define CACHECTRL_FLASHCFG_LPM_RD_WAIT_Msk (0xf00UL) /*!< CACHECTRL FLASHCFG: LPM_RD_WAIT (Bitfield-Mask: 0x0f) */ -#define CACHECTRL_FLASHCFG_SEDELAY_Pos (4UL) /*!< CACHECTRL FLASHCFG: SEDELAY (Bit 4) */ -#define CACHECTRL_FLASHCFG_SEDELAY_Msk (0x70UL) /*!< CACHECTRL FLASHCFG: SEDELAY (Bitfield-Mask: 0x07) */ -#define CACHECTRL_FLASHCFG_RD_WAIT_Pos (0UL) /*!< CACHECTRL FLASHCFG: RD_WAIT (Bit 0) */ -#define CACHECTRL_FLASHCFG_RD_WAIT_Msk (0xfUL) /*!< CACHECTRL FLASHCFG: RD_WAIT (Bitfield-Mask: 0x0f) */ -/* ========================================================= CTRL ========================================================== */ -#define CACHECTRL_CTRL_FLASH1_SLM_ENABLE_Pos (10UL) /*!< CACHECTRL CTRL: FLASH1_SLM_ENABLE (Bit 10) */ -#define CACHECTRL_CTRL_FLASH1_SLM_ENABLE_Msk (0x400UL) /*!< CACHECTRL CTRL: FLASH1_SLM_ENABLE (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CTRL_FLASH1_SLM_DISABLE_Pos (9UL) /*!< CACHECTRL CTRL: FLASH1_SLM_DISABLE (Bit 9) */ -#define CACHECTRL_CTRL_FLASH1_SLM_DISABLE_Msk (0x200UL) /*!< CACHECTRL CTRL: FLASH1_SLM_DISABLE (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CTRL_FLASH1_SLM_STATUS_Pos (8UL) /*!< CACHECTRL CTRL: FLASH1_SLM_STATUS (Bit 8) */ -#define CACHECTRL_CTRL_FLASH1_SLM_STATUS_Msk (0x100UL) /*!< CACHECTRL CTRL: FLASH1_SLM_STATUS (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CTRL_FLASH0_SLM_ENABLE_Pos (6UL) /*!< CACHECTRL CTRL: FLASH0_SLM_ENABLE (Bit 6) */ -#define CACHECTRL_CTRL_FLASH0_SLM_ENABLE_Msk (0x40UL) /*!< CACHECTRL CTRL: FLASH0_SLM_ENABLE (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CTRL_FLASH0_SLM_DISABLE_Pos (5UL) /*!< CACHECTRL CTRL: FLASH0_SLM_DISABLE (Bit 5) */ -#define CACHECTRL_CTRL_FLASH0_SLM_DISABLE_Msk (0x20UL) /*!< CACHECTRL CTRL: FLASH0_SLM_DISABLE (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CTRL_FLASH0_SLM_STATUS_Pos (4UL) /*!< CACHECTRL CTRL: FLASH0_SLM_STATUS (Bit 4) */ -#define CACHECTRL_CTRL_FLASH0_SLM_STATUS_Msk (0x10UL) /*!< CACHECTRL CTRL: FLASH0_SLM_STATUS (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CTRL_CACHE_READY_Pos (2UL) /*!< CACHECTRL CTRL: CACHE_READY (Bit 2) */ -#define CACHECTRL_CTRL_CACHE_READY_Msk (0x4UL) /*!< CACHECTRL CTRL: CACHE_READY (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CTRL_RESET_STAT_Pos (1UL) /*!< CACHECTRL CTRL: RESET_STAT (Bit 1) */ -#define CACHECTRL_CTRL_RESET_STAT_Msk (0x2UL) /*!< CACHECTRL CTRL: RESET_STAT (Bitfield-Mask: 0x01) */ -#define CACHECTRL_CTRL_INVALIDATE_Pos (0UL) /*!< CACHECTRL CTRL: INVALIDATE (Bit 0) */ -#define CACHECTRL_CTRL_INVALIDATE_Msk (0x1UL) /*!< CACHECTRL CTRL: INVALIDATE (Bitfield-Mask: 0x01) */ -/* ======================================================= NCR0START ======================================================= */ -#define CACHECTRL_NCR0START_ADDR_Pos (4UL) /*!< CACHECTRL NCR0START: ADDR (Bit 4) */ -#define CACHECTRL_NCR0START_ADDR_Msk (0x7fffff0UL) /*!< CACHECTRL NCR0START: ADDR (Bitfield-Mask: 0x7fffff) */ -/* ======================================================== NCR0END ======================================================== */ -#define CACHECTRL_NCR0END_ADDR_Pos (4UL) /*!< CACHECTRL NCR0END: ADDR (Bit 4) */ -#define CACHECTRL_NCR0END_ADDR_Msk (0x7fffff0UL) /*!< CACHECTRL NCR0END: ADDR (Bitfield-Mask: 0x7fffff) */ -/* ======================================================= NCR1START ======================================================= */ -#define CACHECTRL_NCR1START_ADDR_Pos (4UL) /*!< CACHECTRL NCR1START: ADDR (Bit 4) */ -#define CACHECTRL_NCR1START_ADDR_Msk (0x7fffff0UL) /*!< CACHECTRL NCR1START: ADDR (Bitfield-Mask: 0x7fffff) */ -/* ======================================================== NCR1END ======================================================== */ -#define CACHECTRL_NCR1END_ADDR_Pos (4UL) /*!< CACHECTRL NCR1END: ADDR (Bit 4) */ -#define CACHECTRL_NCR1END_ADDR_Msk (0x7fffff0UL) /*!< CACHECTRL NCR1END: ADDR (Bitfield-Mask: 0x7fffff) */ -/* ========================================================= DMON0 ========================================================= */ -#define CACHECTRL_DMON0_DACCESS_COUNT_Pos (0UL) /*!< CACHECTRL DMON0: DACCESS_COUNT (Bit 0) */ -#define CACHECTRL_DMON0_DACCESS_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL DMON0: DACCESS_COUNT (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= DMON1 ========================================================= */ -#define CACHECTRL_DMON1_DLOOKUP_COUNT_Pos (0UL) /*!< CACHECTRL DMON1: DLOOKUP_COUNT (Bit 0) */ -#define CACHECTRL_DMON1_DLOOKUP_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL DMON1: DLOOKUP_COUNT (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= DMON2 ========================================================= */ -#define CACHECTRL_DMON2_DHIT_COUNT_Pos (0UL) /*!< CACHECTRL DMON2: DHIT_COUNT (Bit 0) */ -#define CACHECTRL_DMON2_DHIT_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL DMON2: DHIT_COUNT (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= DMON3 ========================================================= */ -#define CACHECTRL_DMON3_DLINE_COUNT_Pos (0UL) /*!< CACHECTRL DMON3: DLINE_COUNT (Bit 0) */ -#define CACHECTRL_DMON3_DLINE_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL DMON3: DLINE_COUNT (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= IMON0 ========================================================= */ -#define CACHECTRL_IMON0_IACCESS_COUNT_Pos (0UL) /*!< CACHECTRL IMON0: IACCESS_COUNT (Bit 0) */ -#define CACHECTRL_IMON0_IACCESS_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL IMON0: IACCESS_COUNT (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= IMON1 ========================================================= */ -#define CACHECTRL_IMON1_ILOOKUP_COUNT_Pos (0UL) /*!< CACHECTRL IMON1: ILOOKUP_COUNT (Bit 0) */ -#define CACHECTRL_IMON1_ILOOKUP_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL IMON1: ILOOKUP_COUNT (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= IMON2 ========================================================= */ -#define CACHECTRL_IMON2_IHIT_COUNT_Pos (0UL) /*!< CACHECTRL IMON2: IHIT_COUNT (Bit 0) */ -#define CACHECTRL_IMON2_IHIT_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL IMON2: IHIT_COUNT (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= IMON3 ========================================================= */ -#define CACHECTRL_IMON3_ILINE_COUNT_Pos (0UL) /*!< CACHECTRL IMON3: ILINE_COUNT (Bit 0) */ -#define CACHECTRL_IMON3_ILINE_COUNT_Msk (0xffffffffUL) /*!< CACHECTRL IMON3: ILINE_COUNT (Bitfield-Mask: 0xffffffff) */ - - -/* =========================================================================================================================== */ -/* ================ CLKGEN ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= CALXT ========================================================= */ -#define CLKGEN_CALXT_CALXT_Pos (0UL) /*!< CLKGEN CALXT: CALXT (Bit 0) */ -#define CLKGEN_CALXT_CALXT_Msk (0x7ffUL) /*!< CLKGEN CALXT: CALXT (Bitfield-Mask: 0x7ff) */ -/* ========================================================= CALRC ========================================================= */ -#define CLKGEN_CALRC_CALRC_Pos (0UL) /*!< CLKGEN CALRC: CALRC (Bit 0) */ -#define CLKGEN_CALRC_CALRC_Msk (0x3ffffUL) /*!< CLKGEN CALRC: CALRC (Bitfield-Mask: 0x3ffff) */ -/* ======================================================== ACALCTR ======================================================== */ -#define CLKGEN_ACALCTR_ACALCTR_Pos (0UL) /*!< CLKGEN ACALCTR: ACALCTR (Bit 0) */ -#define CLKGEN_ACALCTR_ACALCTR_Msk (0xffffffUL) /*!< CLKGEN ACALCTR: ACALCTR (Bitfield-Mask: 0xffffff) */ -/* ========================================================= OCTRL ========================================================= */ -#define CLKGEN_OCTRL_ACAL_Pos (8UL) /*!< CLKGEN OCTRL: ACAL (Bit 8) */ -#define CLKGEN_OCTRL_ACAL_Msk (0x700UL) /*!< CLKGEN OCTRL: ACAL (Bitfield-Mask: 0x07) */ -#define CLKGEN_OCTRL_OSEL_Pos (7UL) /*!< CLKGEN OCTRL: OSEL (Bit 7) */ -#define CLKGEN_OCTRL_OSEL_Msk (0x80UL) /*!< CLKGEN OCTRL: OSEL (Bitfield-Mask: 0x01) */ -#define CLKGEN_OCTRL_FOS_Pos (6UL) /*!< CLKGEN OCTRL: FOS (Bit 6) */ -#define CLKGEN_OCTRL_FOS_Msk (0x40UL) /*!< CLKGEN OCTRL: FOS (Bitfield-Mask: 0x01) */ -#define CLKGEN_OCTRL_STOPRC_Pos (1UL) /*!< CLKGEN OCTRL: STOPRC (Bit 1) */ -#define CLKGEN_OCTRL_STOPRC_Msk (0x2UL) /*!< CLKGEN OCTRL: STOPRC (Bitfield-Mask: 0x01) */ -#define CLKGEN_OCTRL_STOPXT_Pos (0UL) /*!< CLKGEN OCTRL: STOPXT (Bit 0) */ -#define CLKGEN_OCTRL_STOPXT_Msk (0x1UL) /*!< CLKGEN OCTRL: STOPXT (Bitfield-Mask: 0x01) */ -/* ======================================================== CLKOUT ========================================================= */ -#define CLKGEN_CLKOUT_CKEN_Pos (7UL) /*!< CLKGEN CLKOUT: CKEN (Bit 7) */ -#define CLKGEN_CLKOUT_CKEN_Msk (0x80UL) /*!< CLKGEN CLKOUT: CKEN (Bitfield-Mask: 0x01) */ -#define CLKGEN_CLKOUT_CKSEL_Pos (0UL) /*!< CLKGEN CLKOUT: CKSEL (Bit 0) */ -#define CLKGEN_CLKOUT_CKSEL_Msk (0x3fUL) /*!< CLKGEN CLKOUT: CKSEL (Bitfield-Mask: 0x3f) */ -/* ======================================================== CLKKEY ========================================================= */ -#define CLKGEN_CLKKEY_CLKKEY_Pos (0UL) /*!< CLKGEN CLKKEY: CLKKEY (Bit 0) */ -#define CLKGEN_CLKKEY_CLKKEY_Msk (0xffffffffUL) /*!< CLKGEN CLKKEY: CLKKEY (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= CCTRL ========================================================= */ -#define CLKGEN_CCTRL_CORESEL_Pos (0UL) /*!< CLKGEN CCTRL: CORESEL (Bit 0) */ -#define CLKGEN_CCTRL_CORESEL_Msk (0x1UL) /*!< CLKGEN CCTRL: CORESEL (Bitfield-Mask: 0x01) */ -/* ======================================================== STATUS ========================================================= */ -#define CLKGEN_STATUS_OSCF_Pos (1UL) /*!< CLKGEN STATUS: OSCF (Bit 1) */ -#define CLKGEN_STATUS_OSCF_Msk (0x2UL) /*!< CLKGEN STATUS: OSCF (Bitfield-Mask: 0x01) */ -#define CLKGEN_STATUS_OMODE_Pos (0UL) /*!< CLKGEN STATUS: OMODE (Bit 0) */ -#define CLKGEN_STATUS_OMODE_Msk (0x1UL) /*!< CLKGEN STATUS: OMODE (Bitfield-Mask: 0x01) */ -/* ========================================================= HFADJ ========================================================= */ -#define CLKGEN_HFADJ_HFADJGAIN_Pos (21UL) /*!< CLKGEN HFADJ: HFADJGAIN (Bit 21) */ -#define CLKGEN_HFADJ_HFADJGAIN_Msk (0xe00000UL) /*!< CLKGEN HFADJ: HFADJGAIN (Bitfield-Mask: 0x07) */ -#define CLKGEN_HFADJ_HFWARMUP_Pos (20UL) /*!< CLKGEN HFADJ: HFWARMUP (Bit 20) */ -#define CLKGEN_HFADJ_HFWARMUP_Msk (0x100000UL) /*!< CLKGEN HFADJ: HFWARMUP (Bitfield-Mask: 0x01) */ -#define CLKGEN_HFADJ_HFXTADJ_Pos (8UL) /*!< CLKGEN HFADJ: HFXTADJ (Bit 8) */ -#define CLKGEN_HFADJ_HFXTADJ_Msk (0xfff00UL) /*!< CLKGEN HFADJ: HFXTADJ (Bitfield-Mask: 0xfff) */ -#define CLKGEN_HFADJ_HFADJCK_Pos (1UL) /*!< CLKGEN HFADJ: HFADJCK (Bit 1) */ -#define CLKGEN_HFADJ_HFADJCK_Msk (0xeUL) /*!< CLKGEN HFADJ: HFADJCK (Bitfield-Mask: 0x07) */ -#define CLKGEN_HFADJ_HFADJEN_Pos (0UL) /*!< CLKGEN HFADJ: HFADJEN (Bit 0) */ -#define CLKGEN_HFADJ_HFADJEN_Msk (0x1UL) /*!< CLKGEN HFADJ: HFADJEN (Bitfield-Mask: 0x01) */ -/* ====================================================== CLOCKENSTAT ====================================================== */ -#define CLKGEN_CLOCKENSTAT_CLOCKENSTAT_Pos (0UL) /*!< CLKGEN CLOCKENSTAT: CLOCKENSTAT (Bit 0) */ -#define CLKGEN_CLOCKENSTAT_CLOCKENSTAT_Msk (0xffffffffUL) /*!< CLKGEN CLOCKENSTAT: CLOCKENSTAT (Bitfield-Mask: 0xffffffff) */ -/* ===================================================== CLOCKEN2STAT ====================================================== */ -#define CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_Pos (0UL) /*!< CLKGEN CLOCKEN2STAT: CLOCKEN2STAT (Bit 0) */ -#define CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_Msk (0xffffffffUL) /*!< CLKGEN CLOCKEN2STAT: CLOCKEN2STAT (Bitfield-Mask: 0xffffffff) */ -/* ===================================================== CLOCKEN3STAT ====================================================== */ -#define CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_Pos (0UL) /*!< CLKGEN CLOCKEN3STAT: CLOCKEN3STAT (Bit 0) */ -#define CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_Msk (0xffffffffUL) /*!< CLKGEN CLOCKEN3STAT: CLOCKEN3STAT (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= FREQCTRL ======================================================== */ -#define CLKGEN_FREQCTRL_BURSTSTATUS_Pos (2UL) /*!< CLKGEN FREQCTRL: BURSTSTATUS (Bit 2) */ -#define CLKGEN_FREQCTRL_BURSTSTATUS_Msk (0x4UL) /*!< CLKGEN FREQCTRL: BURSTSTATUS (Bitfield-Mask: 0x01) */ -#define CLKGEN_FREQCTRL_BURSTACK_Pos (1UL) /*!< CLKGEN FREQCTRL: BURSTACK (Bit 1) */ -#define CLKGEN_FREQCTRL_BURSTACK_Msk (0x2UL) /*!< CLKGEN FREQCTRL: BURSTACK (Bitfield-Mask: 0x01) */ -#define CLKGEN_FREQCTRL_BURSTREQ_Pos (0UL) /*!< CLKGEN FREQCTRL: BURSTREQ (Bit 0) */ -#define CLKGEN_FREQCTRL_BURSTREQ_Msk (0x1UL) /*!< CLKGEN FREQCTRL: BURSTREQ (Bitfield-Mask: 0x01) */ -/* ===================================================== BLEBUCKTONADJ ===================================================== */ -#define CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_Pos (27UL) /*!< CLKGEN BLEBUCKTONADJ: ZEROLENDETECTEN (Bit 27) */ -#define CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_Msk (0x8000000UL) /*!< CLKGEN BLEBUCKTONADJ: ZEROLENDETECTEN (Bitfield-Mask: 0x01) */ -#define CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Pos (23UL) /*!< CLKGEN BLEBUCKTONADJ: ZEROLENDETECTTRIM (Bit 23) */ -#define CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Msk (0x7800000UL) /*!< CLKGEN BLEBUCKTONADJ: ZEROLENDETECTTRIM (Bitfield-Mask: 0x0f) */ -#define CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_Pos (22UL) /*!< CLKGEN BLEBUCKTONADJ: TONADJUSTEN (Bit 22) */ -#define CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_Msk (0x400000UL) /*!< CLKGEN BLEBUCKTONADJ: TONADJUSTEN (Bitfield-Mask: 0x01) */ -#define CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_Pos (20UL) /*!< CLKGEN BLEBUCKTONADJ: TONADJUSTPERIOD (Bit 20) */ -#define CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_Msk (0x300000UL) /*!< CLKGEN BLEBUCKTONADJ: TONADJUSTPERIOD (Bitfield-Mask: 0x03) */ -#define CLKGEN_BLEBUCKTONADJ_TONHIGHTHRESHOLD_Pos (10UL) /*!< CLKGEN BLEBUCKTONADJ: TONHIGHTHRESHOLD (Bit 10) */ -#define CLKGEN_BLEBUCKTONADJ_TONHIGHTHRESHOLD_Msk (0xffc00UL) /*!< CLKGEN BLEBUCKTONADJ: TONHIGHTHRESHOLD (Bitfield-Mask: 0x3ff) */ -#define CLKGEN_BLEBUCKTONADJ_TONLOWTHRESHOLD_Pos (0UL) /*!< CLKGEN BLEBUCKTONADJ: TONLOWTHRESHOLD (Bit 0) */ -#define CLKGEN_BLEBUCKTONADJ_TONLOWTHRESHOLD_Msk (0x3ffUL) /*!< CLKGEN BLEBUCKTONADJ: TONLOWTHRESHOLD (Bitfield-Mask: 0x3ff) */ -/* ======================================================= INTRPTEN ======================================================== */ -#define CLKGEN_INTRPTEN_OF_Pos (2UL) /*!< CLKGEN INTRPTEN: OF (Bit 2) */ -#define CLKGEN_INTRPTEN_OF_Msk (0x4UL) /*!< CLKGEN INTRPTEN: OF (Bitfield-Mask: 0x01) */ -#define CLKGEN_INTRPTEN_ACC_Pos (1UL) /*!< CLKGEN INTRPTEN: ACC (Bit 1) */ -#define CLKGEN_INTRPTEN_ACC_Msk (0x2UL) /*!< CLKGEN INTRPTEN: ACC (Bitfield-Mask: 0x01) */ -#define CLKGEN_INTRPTEN_ACF_Pos (0UL) /*!< CLKGEN INTRPTEN: ACF (Bit 0) */ -#define CLKGEN_INTRPTEN_ACF_Msk (0x1UL) /*!< CLKGEN INTRPTEN: ACF (Bitfield-Mask: 0x01) */ -/* ====================================================== INTRPTSTAT ======================================================= */ -#define CLKGEN_INTRPTSTAT_OF_Pos (2UL) /*!< CLKGEN INTRPTSTAT: OF (Bit 2) */ -#define CLKGEN_INTRPTSTAT_OF_Msk (0x4UL) /*!< CLKGEN INTRPTSTAT: OF (Bitfield-Mask: 0x01) */ -#define CLKGEN_INTRPTSTAT_ACC_Pos (1UL) /*!< CLKGEN INTRPTSTAT: ACC (Bit 1) */ -#define CLKGEN_INTRPTSTAT_ACC_Msk (0x2UL) /*!< CLKGEN INTRPTSTAT: ACC (Bitfield-Mask: 0x01) */ -#define CLKGEN_INTRPTSTAT_ACF_Pos (0UL) /*!< CLKGEN INTRPTSTAT: ACF (Bit 0) */ -#define CLKGEN_INTRPTSTAT_ACF_Msk (0x1UL) /*!< CLKGEN INTRPTSTAT: ACF (Bitfield-Mask: 0x01) */ -/* ======================================================= INTRPTCLR ======================================================= */ -#define CLKGEN_INTRPTCLR_OF_Pos (2UL) /*!< CLKGEN INTRPTCLR: OF (Bit 2) */ -#define CLKGEN_INTRPTCLR_OF_Msk (0x4UL) /*!< CLKGEN INTRPTCLR: OF (Bitfield-Mask: 0x01) */ -#define CLKGEN_INTRPTCLR_ACC_Pos (1UL) /*!< CLKGEN INTRPTCLR: ACC (Bit 1) */ -#define CLKGEN_INTRPTCLR_ACC_Msk (0x2UL) /*!< CLKGEN INTRPTCLR: ACC (Bitfield-Mask: 0x01) */ -#define CLKGEN_INTRPTCLR_ACF_Pos (0UL) /*!< CLKGEN INTRPTCLR: ACF (Bit 0) */ -#define CLKGEN_INTRPTCLR_ACF_Msk (0x1UL) /*!< CLKGEN INTRPTCLR: ACF (Bitfield-Mask: 0x01) */ -/* ======================================================= INTRPTSET ======================================================= */ -#define CLKGEN_INTRPTSET_OF_Pos (2UL) /*!< CLKGEN INTRPTSET: OF (Bit 2) */ -#define CLKGEN_INTRPTSET_OF_Msk (0x4UL) /*!< CLKGEN INTRPTSET: OF (Bitfield-Mask: 0x01) */ -#define CLKGEN_INTRPTSET_ACC_Pos (1UL) /*!< CLKGEN INTRPTSET: ACC (Bit 1) */ -#define CLKGEN_INTRPTSET_ACC_Msk (0x2UL) /*!< CLKGEN INTRPTSET: ACC (Bitfield-Mask: 0x01) */ -#define CLKGEN_INTRPTSET_ACF_Pos (0UL) /*!< CLKGEN INTRPTSET: ACF (Bit 0) */ -#define CLKGEN_INTRPTSET_ACF_Msk (0x1UL) /*!< CLKGEN INTRPTSET: ACF (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ CTIMER ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= TMR0 ========================================================== */ -#define CTIMER_TMR0_CTTMRB0_Pos (16UL) /*!< CTIMER TMR0: CTTMRB0 (Bit 16) */ -#define CTIMER_TMR0_CTTMRB0_Msk (0xffff0000UL) /*!< CTIMER TMR0: CTTMRB0 (Bitfield-Mask: 0xffff) */ -#define CTIMER_TMR0_CTTMRA0_Pos (0UL) /*!< CTIMER TMR0: CTTMRA0 (Bit 0) */ -#define CTIMER_TMR0_CTTMRA0_Msk (0xffffUL) /*!< CTIMER TMR0: CTTMRA0 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRA0 ========================================================= */ -#define CTIMER_CMPRA0_CMPR1A0_Pos (16UL) /*!< CTIMER CMPRA0: CMPR1A0 (Bit 16) */ -#define CTIMER_CMPRA0_CMPR1A0_Msk (0xffff0000UL) /*!< CTIMER CMPRA0: CMPR1A0 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRA0_CMPR0A0_Pos (0UL) /*!< CTIMER CMPRA0: CMPR0A0 (Bit 0) */ -#define CTIMER_CMPRA0_CMPR0A0_Msk (0xffffUL) /*!< CTIMER CMPRA0: CMPR0A0 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRB0 ========================================================= */ -#define CTIMER_CMPRB0_CMPR1B0_Pos (16UL) /*!< CTIMER CMPRB0: CMPR1B0 (Bit 16) */ -#define CTIMER_CMPRB0_CMPR1B0_Msk (0xffff0000UL) /*!< CTIMER CMPRB0: CMPR1B0 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRB0_CMPR0B0_Pos (0UL) /*!< CTIMER CMPRB0: CMPR0B0 (Bit 0) */ -#define CTIMER_CMPRB0_CMPR0B0_Msk (0xffffUL) /*!< CTIMER CMPRB0: CMPR0B0 (Bitfield-Mask: 0xffff) */ -/* ========================================================= CTRL0 ========================================================= */ -#define CTIMER_CTRL0_CTLINK0_Pos (31UL) /*!< CTIMER CTRL0: CTLINK0 (Bit 31) */ -#define CTIMER_CTRL0_CTLINK0_Msk (0x80000000UL) /*!< CTIMER CTRL0: CTLINK0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRB0POL_Pos (28UL) /*!< CTIMER CTRL0: TMRB0POL (Bit 28) */ -#define CTIMER_CTRL0_TMRB0POL_Msk (0x10000000UL) /*!< CTIMER CTRL0: TMRB0POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRB0CLR_Pos (27UL) /*!< CTIMER CTRL0: TMRB0CLR (Bit 27) */ -#define CTIMER_CTRL0_TMRB0CLR_Msk (0x8000000UL) /*!< CTIMER CTRL0: TMRB0CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRB0IE1_Pos (26UL) /*!< CTIMER CTRL0: TMRB0IE1 (Bit 26) */ -#define CTIMER_CTRL0_TMRB0IE1_Msk (0x4000000UL) /*!< CTIMER CTRL0: TMRB0IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRB0IE0_Pos (25UL) /*!< CTIMER CTRL0: TMRB0IE0 (Bit 25) */ -#define CTIMER_CTRL0_TMRB0IE0_Msk (0x2000000UL) /*!< CTIMER CTRL0: TMRB0IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRB0FN_Pos (22UL) /*!< CTIMER CTRL0: TMRB0FN (Bit 22) */ -#define CTIMER_CTRL0_TMRB0FN_Msk (0x1c00000UL) /*!< CTIMER CTRL0: TMRB0FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL0_TMRB0CLK_Pos (17UL) /*!< CTIMER CTRL0: TMRB0CLK (Bit 17) */ -#define CTIMER_CTRL0_TMRB0CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL0: TMRB0CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL0_TMRB0EN_Pos (16UL) /*!< CTIMER CTRL0: TMRB0EN (Bit 16) */ -#define CTIMER_CTRL0_TMRB0EN_Msk (0x10000UL) /*!< CTIMER CTRL0: TMRB0EN (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRA0POL_Pos (12UL) /*!< CTIMER CTRL0: TMRA0POL (Bit 12) */ -#define CTIMER_CTRL0_TMRA0POL_Msk (0x1000UL) /*!< CTIMER CTRL0: TMRA0POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRA0CLR_Pos (11UL) /*!< CTIMER CTRL0: TMRA0CLR (Bit 11) */ -#define CTIMER_CTRL0_TMRA0CLR_Msk (0x800UL) /*!< CTIMER CTRL0: TMRA0CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRA0IE1_Pos (10UL) /*!< CTIMER CTRL0: TMRA0IE1 (Bit 10) */ -#define CTIMER_CTRL0_TMRA0IE1_Msk (0x400UL) /*!< CTIMER CTRL0: TMRA0IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRA0IE0_Pos (9UL) /*!< CTIMER CTRL0: TMRA0IE0 (Bit 9) */ -#define CTIMER_CTRL0_TMRA0IE0_Msk (0x200UL) /*!< CTIMER CTRL0: TMRA0IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL0_TMRA0FN_Pos (6UL) /*!< CTIMER CTRL0: TMRA0FN (Bit 6) */ -#define CTIMER_CTRL0_TMRA0FN_Msk (0x1c0UL) /*!< CTIMER CTRL0: TMRA0FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL0_TMRA0CLK_Pos (1UL) /*!< CTIMER CTRL0: TMRA0CLK (Bit 1) */ -#define CTIMER_CTRL0_TMRA0CLK_Msk (0x3eUL) /*!< CTIMER CTRL0: TMRA0CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL0_TMRA0EN_Pos (0UL) /*!< CTIMER CTRL0: TMRA0EN (Bit 0) */ -#define CTIMER_CTRL0_TMRA0EN_Msk (0x1UL) /*!< CTIMER CTRL0: TMRA0EN (Bitfield-Mask: 0x01) */ -/* ======================================================= CMPRAUXA0 ======================================================= */ -#define CTIMER_CMPRAUXA0_CMPR3A0_Pos (16UL) /*!< CTIMER CMPRAUXA0: CMPR3A0 (Bit 16) */ -#define CTIMER_CMPRAUXA0_CMPR3A0_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA0: CMPR3A0 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXA0_CMPR2A0_Pos (0UL) /*!< CTIMER CMPRAUXA0: CMPR2A0 (Bit 0) */ -#define CTIMER_CMPRAUXA0_CMPR2A0_Msk (0xffffUL) /*!< CTIMER CMPRAUXA0: CMPR2A0 (Bitfield-Mask: 0xffff) */ -/* ======================================================= CMPRAUXB0 ======================================================= */ -#define CTIMER_CMPRAUXB0_CMPR3B0_Pos (16UL) /*!< CTIMER CMPRAUXB0: CMPR3B0 (Bit 16) */ -#define CTIMER_CMPRAUXB0_CMPR3B0_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB0: CMPR3B0 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXB0_CMPR2B0_Pos (0UL) /*!< CTIMER CMPRAUXB0: CMPR2B0 (Bit 0) */ -#define CTIMER_CMPRAUXB0_CMPR2B0_Msk (0xffffUL) /*!< CTIMER CMPRAUXB0: CMPR2B0 (Bitfield-Mask: 0xffff) */ -/* ========================================================= AUX0 ========================================================== */ -#define CTIMER_AUX0_TMRB0EN23_Pos (30UL) /*!< CTIMER AUX0: TMRB0EN23 (Bit 30) */ -#define CTIMER_AUX0_TMRB0EN23_Msk (0x40000000UL) /*!< CTIMER AUX0: TMRB0EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX0_TMRB0POL23_Pos (29UL) /*!< CTIMER AUX0: TMRB0POL23 (Bit 29) */ -#define CTIMER_AUX0_TMRB0POL23_Msk (0x20000000UL) /*!< CTIMER AUX0: TMRB0POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX0_TMRB0TINV_Pos (28UL) /*!< CTIMER AUX0: TMRB0TINV (Bit 28) */ -#define CTIMER_AUX0_TMRB0TINV_Msk (0x10000000UL) /*!< CTIMER AUX0: TMRB0TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX0_TMRB0NOSYNC_Pos (27UL) /*!< CTIMER AUX0: TMRB0NOSYNC (Bit 27) */ -#define CTIMER_AUX0_TMRB0NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX0: TMRB0NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX0_TMRB0TRIG_Pos (23UL) /*!< CTIMER AUX0: TMRB0TRIG (Bit 23) */ -#define CTIMER_AUX0_TMRB0TRIG_Msk (0x7800000UL) /*!< CTIMER AUX0: TMRB0TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX0_TMRB0LMT_Pos (16UL) /*!< CTIMER AUX0: TMRB0LMT (Bit 16) */ -#define CTIMER_AUX0_TMRB0LMT_Msk (0x3f0000UL) /*!< CTIMER AUX0: TMRB0LMT (Bitfield-Mask: 0x3f) */ -#define CTIMER_AUX0_TMRA0EN23_Pos (14UL) /*!< CTIMER AUX0: TMRA0EN23 (Bit 14) */ -#define CTIMER_AUX0_TMRA0EN23_Msk (0x4000UL) /*!< CTIMER AUX0: TMRA0EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX0_TMRA0POL23_Pos (13UL) /*!< CTIMER AUX0: TMRA0POL23 (Bit 13) */ -#define CTIMER_AUX0_TMRA0POL23_Msk (0x2000UL) /*!< CTIMER AUX0: TMRA0POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX0_TMRA0TINV_Pos (12UL) /*!< CTIMER AUX0: TMRA0TINV (Bit 12) */ -#define CTIMER_AUX0_TMRA0TINV_Msk (0x1000UL) /*!< CTIMER AUX0: TMRA0TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX0_TMRA0NOSYNC_Pos (11UL) /*!< CTIMER AUX0: TMRA0NOSYNC (Bit 11) */ -#define CTIMER_AUX0_TMRA0NOSYNC_Msk (0x800UL) /*!< CTIMER AUX0: TMRA0NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX0_TMRA0TRIG_Pos (7UL) /*!< CTIMER AUX0: TMRA0TRIG (Bit 7) */ -#define CTIMER_AUX0_TMRA0TRIG_Msk (0x780UL) /*!< CTIMER AUX0: TMRA0TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX0_TMRA0LMT_Pos (0UL) /*!< CTIMER AUX0: TMRA0LMT (Bit 0) */ -#define CTIMER_AUX0_TMRA0LMT_Msk (0x7fUL) /*!< CTIMER AUX0: TMRA0LMT (Bitfield-Mask: 0x7f) */ -/* ========================================================= TMR1 ========================================================== */ -#define CTIMER_TMR1_CTTMRB1_Pos (16UL) /*!< CTIMER TMR1: CTTMRB1 (Bit 16) */ -#define CTIMER_TMR1_CTTMRB1_Msk (0xffff0000UL) /*!< CTIMER TMR1: CTTMRB1 (Bitfield-Mask: 0xffff) */ -#define CTIMER_TMR1_CTTMRA1_Pos (0UL) /*!< CTIMER TMR1: CTTMRA1 (Bit 0) */ -#define CTIMER_TMR1_CTTMRA1_Msk (0xffffUL) /*!< CTIMER TMR1: CTTMRA1 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRA1 ========================================================= */ -#define CTIMER_CMPRA1_CMPR1A1_Pos (16UL) /*!< CTIMER CMPRA1: CMPR1A1 (Bit 16) */ -#define CTIMER_CMPRA1_CMPR1A1_Msk (0xffff0000UL) /*!< CTIMER CMPRA1: CMPR1A1 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRA1_CMPR0A1_Pos (0UL) /*!< CTIMER CMPRA1: CMPR0A1 (Bit 0) */ -#define CTIMER_CMPRA1_CMPR0A1_Msk (0xffffUL) /*!< CTIMER CMPRA1: CMPR0A1 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRB1 ========================================================= */ -#define CTIMER_CMPRB1_CMPR1B1_Pos (16UL) /*!< CTIMER CMPRB1: CMPR1B1 (Bit 16) */ -#define CTIMER_CMPRB1_CMPR1B1_Msk (0xffff0000UL) /*!< CTIMER CMPRB1: CMPR1B1 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRB1_CMPR0B1_Pos (0UL) /*!< CTIMER CMPRB1: CMPR0B1 (Bit 0) */ -#define CTIMER_CMPRB1_CMPR0B1_Msk (0xffffUL) /*!< CTIMER CMPRB1: CMPR0B1 (Bitfield-Mask: 0xffff) */ -/* ========================================================= CTRL1 ========================================================= */ -#define CTIMER_CTRL1_CTLINK1_Pos (31UL) /*!< CTIMER CTRL1: CTLINK1 (Bit 31) */ -#define CTIMER_CTRL1_CTLINK1_Msk (0x80000000UL) /*!< CTIMER CTRL1: CTLINK1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRB1POL_Pos (28UL) /*!< CTIMER CTRL1: TMRB1POL (Bit 28) */ -#define CTIMER_CTRL1_TMRB1POL_Msk (0x10000000UL) /*!< CTIMER CTRL1: TMRB1POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRB1CLR_Pos (27UL) /*!< CTIMER CTRL1: TMRB1CLR (Bit 27) */ -#define CTIMER_CTRL1_TMRB1CLR_Msk (0x8000000UL) /*!< CTIMER CTRL1: TMRB1CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRB1IE1_Pos (26UL) /*!< CTIMER CTRL1: TMRB1IE1 (Bit 26) */ -#define CTIMER_CTRL1_TMRB1IE1_Msk (0x4000000UL) /*!< CTIMER CTRL1: TMRB1IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRB1IE0_Pos (25UL) /*!< CTIMER CTRL1: TMRB1IE0 (Bit 25) */ -#define CTIMER_CTRL1_TMRB1IE0_Msk (0x2000000UL) /*!< CTIMER CTRL1: TMRB1IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRB1FN_Pos (22UL) /*!< CTIMER CTRL1: TMRB1FN (Bit 22) */ -#define CTIMER_CTRL1_TMRB1FN_Msk (0x1c00000UL) /*!< CTIMER CTRL1: TMRB1FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL1_TMRB1CLK_Pos (17UL) /*!< CTIMER CTRL1: TMRB1CLK (Bit 17) */ -#define CTIMER_CTRL1_TMRB1CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL1: TMRB1CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL1_TMRB1EN_Pos (16UL) /*!< CTIMER CTRL1: TMRB1EN (Bit 16) */ -#define CTIMER_CTRL1_TMRB1EN_Msk (0x10000UL) /*!< CTIMER CTRL1: TMRB1EN (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRA1POL_Pos (12UL) /*!< CTIMER CTRL1: TMRA1POL (Bit 12) */ -#define CTIMER_CTRL1_TMRA1POL_Msk (0x1000UL) /*!< CTIMER CTRL1: TMRA1POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRA1CLR_Pos (11UL) /*!< CTIMER CTRL1: TMRA1CLR (Bit 11) */ -#define CTIMER_CTRL1_TMRA1CLR_Msk (0x800UL) /*!< CTIMER CTRL1: TMRA1CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRA1IE1_Pos (10UL) /*!< CTIMER CTRL1: TMRA1IE1 (Bit 10) */ -#define CTIMER_CTRL1_TMRA1IE1_Msk (0x400UL) /*!< CTIMER CTRL1: TMRA1IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRA1IE0_Pos (9UL) /*!< CTIMER CTRL1: TMRA1IE0 (Bit 9) */ -#define CTIMER_CTRL1_TMRA1IE0_Msk (0x200UL) /*!< CTIMER CTRL1: TMRA1IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL1_TMRA1FN_Pos (6UL) /*!< CTIMER CTRL1: TMRA1FN (Bit 6) */ -#define CTIMER_CTRL1_TMRA1FN_Msk (0x1c0UL) /*!< CTIMER CTRL1: TMRA1FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL1_TMRA1CLK_Pos (1UL) /*!< CTIMER CTRL1: TMRA1CLK (Bit 1) */ -#define CTIMER_CTRL1_TMRA1CLK_Msk (0x3eUL) /*!< CTIMER CTRL1: TMRA1CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL1_TMRA1EN_Pos (0UL) /*!< CTIMER CTRL1: TMRA1EN (Bit 0) */ -#define CTIMER_CTRL1_TMRA1EN_Msk (0x1UL) /*!< CTIMER CTRL1: TMRA1EN (Bitfield-Mask: 0x01) */ -/* ======================================================= CMPRAUXA1 ======================================================= */ -#define CTIMER_CMPRAUXA1_CMPR3A1_Pos (16UL) /*!< CTIMER CMPRAUXA1: CMPR3A1 (Bit 16) */ -#define CTIMER_CMPRAUXA1_CMPR3A1_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA1: CMPR3A1 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXA1_CMPR2A1_Pos (0UL) /*!< CTIMER CMPRAUXA1: CMPR2A1 (Bit 0) */ -#define CTIMER_CMPRAUXA1_CMPR2A1_Msk (0xffffUL) /*!< CTIMER CMPRAUXA1: CMPR2A1 (Bitfield-Mask: 0xffff) */ -/* ======================================================= CMPRAUXB1 ======================================================= */ -#define CTIMER_CMPRAUXB1_CMPR3B1_Pos (16UL) /*!< CTIMER CMPRAUXB1: CMPR3B1 (Bit 16) */ -#define CTIMER_CMPRAUXB1_CMPR3B1_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB1: CMPR3B1 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXB1_CMPR2B1_Pos (0UL) /*!< CTIMER CMPRAUXB1: CMPR2B1 (Bit 0) */ -#define CTIMER_CMPRAUXB1_CMPR2B1_Msk (0xffffUL) /*!< CTIMER CMPRAUXB1: CMPR2B1 (Bitfield-Mask: 0xffff) */ -/* ========================================================= AUX1 ========================================================== */ -#define CTIMER_AUX1_TMRB1EN23_Pos (30UL) /*!< CTIMER AUX1: TMRB1EN23 (Bit 30) */ -#define CTIMER_AUX1_TMRB1EN23_Msk (0x40000000UL) /*!< CTIMER AUX1: TMRB1EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX1_TMRB1POL23_Pos (29UL) /*!< CTIMER AUX1: TMRB1POL23 (Bit 29) */ -#define CTIMER_AUX1_TMRB1POL23_Msk (0x20000000UL) /*!< CTIMER AUX1: TMRB1POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX1_TMRB1TINV_Pos (28UL) /*!< CTIMER AUX1: TMRB1TINV (Bit 28) */ -#define CTIMER_AUX1_TMRB1TINV_Msk (0x10000000UL) /*!< CTIMER AUX1: TMRB1TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX1_TMRB1NOSYNC_Pos (27UL) /*!< CTIMER AUX1: TMRB1NOSYNC (Bit 27) */ -#define CTIMER_AUX1_TMRB1NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX1: TMRB1NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX1_TMRB1TRIG_Pos (23UL) /*!< CTIMER AUX1: TMRB1TRIG (Bit 23) */ -#define CTIMER_AUX1_TMRB1TRIG_Msk (0x7800000UL) /*!< CTIMER AUX1: TMRB1TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX1_TMRB1LMT_Pos (16UL) /*!< CTIMER AUX1: TMRB1LMT (Bit 16) */ -#define CTIMER_AUX1_TMRB1LMT_Msk (0x3f0000UL) /*!< CTIMER AUX1: TMRB1LMT (Bitfield-Mask: 0x3f) */ -#define CTIMER_AUX1_TMRA1EN23_Pos (14UL) /*!< CTIMER AUX1: TMRA1EN23 (Bit 14) */ -#define CTIMER_AUX1_TMRA1EN23_Msk (0x4000UL) /*!< CTIMER AUX1: TMRA1EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX1_TMRA1POL23_Pos (13UL) /*!< CTIMER AUX1: TMRA1POL23 (Bit 13) */ -#define CTIMER_AUX1_TMRA1POL23_Msk (0x2000UL) /*!< CTIMER AUX1: TMRA1POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX1_TMRA1TINV_Pos (12UL) /*!< CTIMER AUX1: TMRA1TINV (Bit 12) */ -#define CTIMER_AUX1_TMRA1TINV_Msk (0x1000UL) /*!< CTIMER AUX1: TMRA1TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX1_TMRA1NOSYNC_Pos (11UL) /*!< CTIMER AUX1: TMRA1NOSYNC (Bit 11) */ -#define CTIMER_AUX1_TMRA1NOSYNC_Msk (0x800UL) /*!< CTIMER AUX1: TMRA1NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX1_TMRA1TRIG_Pos (7UL) /*!< CTIMER AUX1: TMRA1TRIG (Bit 7) */ -#define CTIMER_AUX1_TMRA1TRIG_Msk (0x780UL) /*!< CTIMER AUX1: TMRA1TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX1_TMRA1LMT_Pos (0UL) /*!< CTIMER AUX1: TMRA1LMT (Bit 0) */ -#define CTIMER_AUX1_TMRA1LMT_Msk (0x7fUL) /*!< CTIMER AUX1: TMRA1LMT (Bitfield-Mask: 0x7f) */ -/* ========================================================= TMR2 ========================================================== */ -#define CTIMER_TMR2_CTTMRB2_Pos (16UL) /*!< CTIMER TMR2: CTTMRB2 (Bit 16) */ -#define CTIMER_TMR2_CTTMRB2_Msk (0xffff0000UL) /*!< CTIMER TMR2: CTTMRB2 (Bitfield-Mask: 0xffff) */ -#define CTIMER_TMR2_CTTMRA2_Pos (0UL) /*!< CTIMER TMR2: CTTMRA2 (Bit 0) */ -#define CTIMER_TMR2_CTTMRA2_Msk (0xffffUL) /*!< CTIMER TMR2: CTTMRA2 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRA2 ========================================================= */ -#define CTIMER_CMPRA2_CMPR1A2_Pos (16UL) /*!< CTIMER CMPRA2: CMPR1A2 (Bit 16) */ -#define CTIMER_CMPRA2_CMPR1A2_Msk (0xffff0000UL) /*!< CTIMER CMPRA2: CMPR1A2 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRA2_CMPR0A2_Pos (0UL) /*!< CTIMER CMPRA2: CMPR0A2 (Bit 0) */ -#define CTIMER_CMPRA2_CMPR0A2_Msk (0xffffUL) /*!< CTIMER CMPRA2: CMPR0A2 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRB2 ========================================================= */ -#define CTIMER_CMPRB2_CMPR1B2_Pos (16UL) /*!< CTIMER CMPRB2: CMPR1B2 (Bit 16) */ -#define CTIMER_CMPRB2_CMPR1B2_Msk (0xffff0000UL) /*!< CTIMER CMPRB2: CMPR1B2 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRB2_CMPR0B2_Pos (0UL) /*!< CTIMER CMPRB2: CMPR0B2 (Bit 0) */ -#define CTIMER_CMPRB2_CMPR0B2_Msk (0xffffUL) /*!< CTIMER CMPRB2: CMPR0B2 (Bitfield-Mask: 0xffff) */ -/* ========================================================= CTRL2 ========================================================= */ -#define CTIMER_CTRL2_CTLINK2_Pos (31UL) /*!< CTIMER CTRL2: CTLINK2 (Bit 31) */ -#define CTIMER_CTRL2_CTLINK2_Msk (0x80000000UL) /*!< CTIMER CTRL2: CTLINK2 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRB2POL_Pos (28UL) /*!< CTIMER CTRL2: TMRB2POL (Bit 28) */ -#define CTIMER_CTRL2_TMRB2POL_Msk (0x10000000UL) /*!< CTIMER CTRL2: TMRB2POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRB2CLR_Pos (27UL) /*!< CTIMER CTRL2: TMRB2CLR (Bit 27) */ -#define CTIMER_CTRL2_TMRB2CLR_Msk (0x8000000UL) /*!< CTIMER CTRL2: TMRB2CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRB2IE1_Pos (26UL) /*!< CTIMER CTRL2: TMRB2IE1 (Bit 26) */ -#define CTIMER_CTRL2_TMRB2IE1_Msk (0x4000000UL) /*!< CTIMER CTRL2: TMRB2IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRB2IE0_Pos (25UL) /*!< CTIMER CTRL2: TMRB2IE0 (Bit 25) */ -#define CTIMER_CTRL2_TMRB2IE0_Msk (0x2000000UL) /*!< CTIMER CTRL2: TMRB2IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRB2FN_Pos (22UL) /*!< CTIMER CTRL2: TMRB2FN (Bit 22) */ -#define CTIMER_CTRL2_TMRB2FN_Msk (0x1c00000UL) /*!< CTIMER CTRL2: TMRB2FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL2_TMRB2CLK_Pos (17UL) /*!< CTIMER CTRL2: TMRB2CLK (Bit 17) */ -#define CTIMER_CTRL2_TMRB2CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL2: TMRB2CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL2_TMRB2EN_Pos (16UL) /*!< CTIMER CTRL2: TMRB2EN (Bit 16) */ -#define CTIMER_CTRL2_TMRB2EN_Msk (0x10000UL) /*!< CTIMER CTRL2: TMRB2EN (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRA2POL_Pos (12UL) /*!< CTIMER CTRL2: TMRA2POL (Bit 12) */ -#define CTIMER_CTRL2_TMRA2POL_Msk (0x1000UL) /*!< CTIMER CTRL2: TMRA2POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRA2CLR_Pos (11UL) /*!< CTIMER CTRL2: TMRA2CLR (Bit 11) */ -#define CTIMER_CTRL2_TMRA2CLR_Msk (0x800UL) /*!< CTIMER CTRL2: TMRA2CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRA2IE1_Pos (10UL) /*!< CTIMER CTRL2: TMRA2IE1 (Bit 10) */ -#define CTIMER_CTRL2_TMRA2IE1_Msk (0x400UL) /*!< CTIMER CTRL2: TMRA2IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRA2IE0_Pos (9UL) /*!< CTIMER CTRL2: TMRA2IE0 (Bit 9) */ -#define CTIMER_CTRL2_TMRA2IE0_Msk (0x200UL) /*!< CTIMER CTRL2: TMRA2IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL2_TMRA2FN_Pos (6UL) /*!< CTIMER CTRL2: TMRA2FN (Bit 6) */ -#define CTIMER_CTRL2_TMRA2FN_Msk (0x1c0UL) /*!< CTIMER CTRL2: TMRA2FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL2_TMRA2CLK_Pos (1UL) /*!< CTIMER CTRL2: TMRA2CLK (Bit 1) */ -#define CTIMER_CTRL2_TMRA2CLK_Msk (0x3eUL) /*!< CTIMER CTRL2: TMRA2CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL2_TMRA2EN_Pos (0UL) /*!< CTIMER CTRL2: TMRA2EN (Bit 0) */ -#define CTIMER_CTRL2_TMRA2EN_Msk (0x1UL) /*!< CTIMER CTRL2: TMRA2EN (Bitfield-Mask: 0x01) */ -/* ======================================================= CMPRAUXA2 ======================================================= */ -#define CTIMER_CMPRAUXA2_CMPR3A2_Pos (16UL) /*!< CTIMER CMPRAUXA2: CMPR3A2 (Bit 16) */ -#define CTIMER_CMPRAUXA2_CMPR3A2_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA2: CMPR3A2 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXA2_CMPR2A2_Pos (0UL) /*!< CTIMER CMPRAUXA2: CMPR2A2 (Bit 0) */ -#define CTIMER_CMPRAUXA2_CMPR2A2_Msk (0xffffUL) /*!< CTIMER CMPRAUXA2: CMPR2A2 (Bitfield-Mask: 0xffff) */ -/* ======================================================= CMPRAUXB2 ======================================================= */ -#define CTIMER_CMPRAUXB2_CMPR3B2_Pos (16UL) /*!< CTIMER CMPRAUXB2: CMPR3B2 (Bit 16) */ -#define CTIMER_CMPRAUXB2_CMPR3B2_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB2: CMPR3B2 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXB2_CMPR2B2_Pos (0UL) /*!< CTIMER CMPRAUXB2: CMPR2B2 (Bit 0) */ -#define CTIMER_CMPRAUXB2_CMPR2B2_Msk (0xffffUL) /*!< CTIMER CMPRAUXB2: CMPR2B2 (Bitfield-Mask: 0xffff) */ -/* ========================================================= AUX2 ========================================================== */ -#define CTIMER_AUX2_TMRB2EN23_Pos (30UL) /*!< CTIMER AUX2: TMRB2EN23 (Bit 30) */ -#define CTIMER_AUX2_TMRB2EN23_Msk (0x40000000UL) /*!< CTIMER AUX2: TMRB2EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX2_TMRB2POL23_Pos (29UL) /*!< CTIMER AUX2: TMRB2POL23 (Bit 29) */ -#define CTIMER_AUX2_TMRB2POL23_Msk (0x20000000UL) /*!< CTIMER AUX2: TMRB2POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX2_TMRB2TINV_Pos (28UL) /*!< CTIMER AUX2: TMRB2TINV (Bit 28) */ -#define CTIMER_AUX2_TMRB2TINV_Msk (0x10000000UL) /*!< CTIMER AUX2: TMRB2TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX2_TMRB2NOSYNC_Pos (27UL) /*!< CTIMER AUX2: TMRB2NOSYNC (Bit 27) */ -#define CTIMER_AUX2_TMRB2NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX2: TMRB2NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX2_TMRB2TRIG_Pos (23UL) /*!< CTIMER AUX2: TMRB2TRIG (Bit 23) */ -#define CTIMER_AUX2_TMRB2TRIG_Msk (0x7800000UL) /*!< CTIMER AUX2: TMRB2TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX2_TMRB2LMT_Pos (16UL) /*!< CTIMER AUX2: TMRB2LMT (Bit 16) */ -#define CTIMER_AUX2_TMRB2LMT_Msk (0x3f0000UL) /*!< CTIMER AUX2: TMRB2LMT (Bitfield-Mask: 0x3f) */ -#define CTIMER_AUX2_TMRA2EN23_Pos (14UL) /*!< CTIMER AUX2: TMRA2EN23 (Bit 14) */ -#define CTIMER_AUX2_TMRA2EN23_Msk (0x4000UL) /*!< CTIMER AUX2: TMRA2EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX2_TMRA2POL23_Pos (13UL) /*!< CTIMER AUX2: TMRA2POL23 (Bit 13) */ -#define CTIMER_AUX2_TMRA2POL23_Msk (0x2000UL) /*!< CTIMER AUX2: TMRA2POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX2_TMRA2TINV_Pos (12UL) /*!< CTIMER AUX2: TMRA2TINV (Bit 12) */ -#define CTIMER_AUX2_TMRA2TINV_Msk (0x1000UL) /*!< CTIMER AUX2: TMRA2TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX2_TMRA2NOSYNC_Pos (11UL) /*!< CTIMER AUX2: TMRA2NOSYNC (Bit 11) */ -#define CTIMER_AUX2_TMRA2NOSYNC_Msk (0x800UL) /*!< CTIMER AUX2: TMRA2NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX2_TMRA2TRIG_Pos (7UL) /*!< CTIMER AUX2: TMRA2TRIG (Bit 7) */ -#define CTIMER_AUX2_TMRA2TRIG_Msk (0x780UL) /*!< CTIMER AUX2: TMRA2TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX2_TMRA2LMT_Pos (0UL) /*!< CTIMER AUX2: TMRA2LMT (Bit 0) */ -#define CTIMER_AUX2_TMRA2LMT_Msk (0x7fUL) /*!< CTIMER AUX2: TMRA2LMT (Bitfield-Mask: 0x7f) */ -/* ========================================================= TMR3 ========================================================== */ -#define CTIMER_TMR3_CTTMRB3_Pos (16UL) /*!< CTIMER TMR3: CTTMRB3 (Bit 16) */ -#define CTIMER_TMR3_CTTMRB3_Msk (0xffff0000UL) /*!< CTIMER TMR3: CTTMRB3 (Bitfield-Mask: 0xffff) */ -#define CTIMER_TMR3_CTTMRA3_Pos (0UL) /*!< CTIMER TMR3: CTTMRA3 (Bit 0) */ -#define CTIMER_TMR3_CTTMRA3_Msk (0xffffUL) /*!< CTIMER TMR3: CTTMRA3 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRA3 ========================================================= */ -#define CTIMER_CMPRA3_CMPR1A3_Pos (16UL) /*!< CTIMER CMPRA3: CMPR1A3 (Bit 16) */ -#define CTIMER_CMPRA3_CMPR1A3_Msk (0xffff0000UL) /*!< CTIMER CMPRA3: CMPR1A3 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRA3_CMPR0A3_Pos (0UL) /*!< CTIMER CMPRA3: CMPR0A3 (Bit 0) */ -#define CTIMER_CMPRA3_CMPR0A3_Msk (0xffffUL) /*!< CTIMER CMPRA3: CMPR0A3 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRB3 ========================================================= */ -#define CTIMER_CMPRB3_CMPR1B3_Pos (16UL) /*!< CTIMER CMPRB3: CMPR1B3 (Bit 16) */ -#define CTIMER_CMPRB3_CMPR1B3_Msk (0xffff0000UL) /*!< CTIMER CMPRB3: CMPR1B3 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRB3_CMPR0B3_Pos (0UL) /*!< CTIMER CMPRB3: CMPR0B3 (Bit 0) */ -#define CTIMER_CMPRB3_CMPR0B3_Msk (0xffffUL) /*!< CTIMER CMPRB3: CMPR0B3 (Bitfield-Mask: 0xffff) */ -/* ========================================================= CTRL3 ========================================================= */ -#define CTIMER_CTRL3_CTLINK3_Pos (31UL) /*!< CTIMER CTRL3: CTLINK3 (Bit 31) */ -#define CTIMER_CTRL3_CTLINK3_Msk (0x80000000UL) /*!< CTIMER CTRL3: CTLINK3 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRB3POL_Pos (28UL) /*!< CTIMER CTRL3: TMRB3POL (Bit 28) */ -#define CTIMER_CTRL3_TMRB3POL_Msk (0x10000000UL) /*!< CTIMER CTRL3: TMRB3POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRB3CLR_Pos (27UL) /*!< CTIMER CTRL3: TMRB3CLR (Bit 27) */ -#define CTIMER_CTRL3_TMRB3CLR_Msk (0x8000000UL) /*!< CTIMER CTRL3: TMRB3CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRB3IE1_Pos (26UL) /*!< CTIMER CTRL3: TMRB3IE1 (Bit 26) */ -#define CTIMER_CTRL3_TMRB3IE1_Msk (0x4000000UL) /*!< CTIMER CTRL3: TMRB3IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRB3IE0_Pos (25UL) /*!< CTIMER CTRL3: TMRB3IE0 (Bit 25) */ -#define CTIMER_CTRL3_TMRB3IE0_Msk (0x2000000UL) /*!< CTIMER CTRL3: TMRB3IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRB3FN_Pos (22UL) /*!< CTIMER CTRL3: TMRB3FN (Bit 22) */ -#define CTIMER_CTRL3_TMRB3FN_Msk (0x1c00000UL) /*!< CTIMER CTRL3: TMRB3FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL3_TMRB3CLK_Pos (17UL) /*!< CTIMER CTRL3: TMRB3CLK (Bit 17) */ -#define CTIMER_CTRL3_TMRB3CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL3: TMRB3CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL3_TMRB3EN_Pos (16UL) /*!< CTIMER CTRL3: TMRB3EN (Bit 16) */ -#define CTIMER_CTRL3_TMRB3EN_Msk (0x10000UL) /*!< CTIMER CTRL3: TMRB3EN (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_ADCEN_Pos (15UL) /*!< CTIMER CTRL3: ADCEN (Bit 15) */ -#define CTIMER_CTRL3_ADCEN_Msk (0x8000UL) /*!< CTIMER CTRL3: ADCEN (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRA3POL_Pos (12UL) /*!< CTIMER CTRL3: TMRA3POL (Bit 12) */ -#define CTIMER_CTRL3_TMRA3POL_Msk (0x1000UL) /*!< CTIMER CTRL3: TMRA3POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRA3CLR_Pos (11UL) /*!< CTIMER CTRL3: TMRA3CLR (Bit 11) */ -#define CTIMER_CTRL3_TMRA3CLR_Msk (0x800UL) /*!< CTIMER CTRL3: TMRA3CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRA3IE1_Pos (10UL) /*!< CTIMER CTRL3: TMRA3IE1 (Bit 10) */ -#define CTIMER_CTRL3_TMRA3IE1_Msk (0x400UL) /*!< CTIMER CTRL3: TMRA3IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRA3IE0_Pos (9UL) /*!< CTIMER CTRL3: TMRA3IE0 (Bit 9) */ -#define CTIMER_CTRL3_TMRA3IE0_Msk (0x200UL) /*!< CTIMER CTRL3: TMRA3IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL3_TMRA3FN_Pos (6UL) /*!< CTIMER CTRL3: TMRA3FN (Bit 6) */ -#define CTIMER_CTRL3_TMRA3FN_Msk (0x1c0UL) /*!< CTIMER CTRL3: TMRA3FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL3_TMRA3CLK_Pos (1UL) /*!< CTIMER CTRL3: TMRA3CLK (Bit 1) */ -#define CTIMER_CTRL3_TMRA3CLK_Msk (0x3eUL) /*!< CTIMER CTRL3: TMRA3CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL3_TMRA3EN_Pos (0UL) /*!< CTIMER CTRL3: TMRA3EN (Bit 0) */ -#define CTIMER_CTRL3_TMRA3EN_Msk (0x1UL) /*!< CTIMER CTRL3: TMRA3EN (Bitfield-Mask: 0x01) */ -/* ======================================================= CMPRAUXA3 ======================================================= */ -#define CTIMER_CMPRAUXA3_CMPR3A3_Pos (16UL) /*!< CTIMER CMPRAUXA3: CMPR3A3 (Bit 16) */ -#define CTIMER_CMPRAUXA3_CMPR3A3_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA3: CMPR3A3 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXA3_CMPR2A3_Pos (0UL) /*!< CTIMER CMPRAUXA3: CMPR2A3 (Bit 0) */ -#define CTIMER_CMPRAUXA3_CMPR2A3_Msk (0xffffUL) /*!< CTIMER CMPRAUXA3: CMPR2A3 (Bitfield-Mask: 0xffff) */ -/* ======================================================= CMPRAUXB3 ======================================================= */ -#define CTIMER_CMPRAUXB3_CMPR3B3_Pos (16UL) /*!< CTIMER CMPRAUXB3: CMPR3B3 (Bit 16) */ -#define CTIMER_CMPRAUXB3_CMPR3B3_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB3: CMPR3B3 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXB3_CMPR2B3_Pos (0UL) /*!< CTIMER CMPRAUXB3: CMPR2B3 (Bit 0) */ -#define CTIMER_CMPRAUXB3_CMPR2B3_Msk (0xffffUL) /*!< CTIMER CMPRAUXB3: CMPR2B3 (Bitfield-Mask: 0xffff) */ -/* ========================================================= AUX3 ========================================================== */ -#define CTIMER_AUX3_TMRB3EN23_Pos (30UL) /*!< CTIMER AUX3: TMRB3EN23 (Bit 30) */ -#define CTIMER_AUX3_TMRB3EN23_Msk (0x40000000UL) /*!< CTIMER AUX3: TMRB3EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX3_TMRB3POL23_Pos (29UL) /*!< CTIMER AUX3: TMRB3POL23 (Bit 29) */ -#define CTIMER_AUX3_TMRB3POL23_Msk (0x20000000UL) /*!< CTIMER AUX3: TMRB3POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX3_TMRB3TINV_Pos (28UL) /*!< CTIMER AUX3: TMRB3TINV (Bit 28) */ -#define CTIMER_AUX3_TMRB3TINV_Msk (0x10000000UL) /*!< CTIMER AUX3: TMRB3TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX3_TMRB3NOSYNC_Pos (27UL) /*!< CTIMER AUX3: TMRB3NOSYNC (Bit 27) */ -#define CTIMER_AUX3_TMRB3NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX3: TMRB3NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX3_TMRB3TRIG_Pos (23UL) /*!< CTIMER AUX3: TMRB3TRIG (Bit 23) */ -#define CTIMER_AUX3_TMRB3TRIG_Msk (0x7800000UL) /*!< CTIMER AUX3: TMRB3TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX3_TMRB3LMT_Pos (16UL) /*!< CTIMER AUX3: TMRB3LMT (Bit 16) */ -#define CTIMER_AUX3_TMRB3LMT_Msk (0x3f0000UL) /*!< CTIMER AUX3: TMRB3LMT (Bitfield-Mask: 0x3f) */ -#define CTIMER_AUX3_TMRA3EN23_Pos (14UL) /*!< CTIMER AUX3: TMRA3EN23 (Bit 14) */ -#define CTIMER_AUX3_TMRA3EN23_Msk (0x4000UL) /*!< CTIMER AUX3: TMRA3EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX3_TMRA3POL23_Pos (13UL) /*!< CTIMER AUX3: TMRA3POL23 (Bit 13) */ -#define CTIMER_AUX3_TMRA3POL23_Msk (0x2000UL) /*!< CTIMER AUX3: TMRA3POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX3_TMRA3TINV_Pos (12UL) /*!< CTIMER AUX3: TMRA3TINV (Bit 12) */ -#define CTIMER_AUX3_TMRA3TINV_Msk (0x1000UL) /*!< CTIMER AUX3: TMRA3TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX3_TMRA3NOSYNC_Pos (11UL) /*!< CTIMER AUX3: TMRA3NOSYNC (Bit 11) */ -#define CTIMER_AUX3_TMRA3NOSYNC_Msk (0x800UL) /*!< CTIMER AUX3: TMRA3NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX3_TMRA3TRIG_Pos (7UL) /*!< CTIMER AUX3: TMRA3TRIG (Bit 7) */ -#define CTIMER_AUX3_TMRA3TRIG_Msk (0x780UL) /*!< CTIMER AUX3: TMRA3TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX3_TMRA3LMT_Pos (0UL) /*!< CTIMER AUX3: TMRA3LMT (Bit 0) */ -#define CTIMER_AUX3_TMRA3LMT_Msk (0x7fUL) /*!< CTIMER AUX3: TMRA3LMT (Bitfield-Mask: 0x7f) */ -/* ========================================================= TMR4 ========================================================== */ -#define CTIMER_TMR4_CTTMRB4_Pos (16UL) /*!< CTIMER TMR4: CTTMRB4 (Bit 16) */ -#define CTIMER_TMR4_CTTMRB4_Msk (0xffff0000UL) /*!< CTIMER TMR4: CTTMRB4 (Bitfield-Mask: 0xffff) */ -#define CTIMER_TMR4_CTTMRA4_Pos (0UL) /*!< CTIMER TMR4: CTTMRA4 (Bit 0) */ -#define CTIMER_TMR4_CTTMRA4_Msk (0xffffUL) /*!< CTIMER TMR4: CTTMRA4 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRA4 ========================================================= */ -#define CTIMER_CMPRA4_CMPR1A4_Pos (16UL) /*!< CTIMER CMPRA4: CMPR1A4 (Bit 16) */ -#define CTIMER_CMPRA4_CMPR1A4_Msk (0xffff0000UL) /*!< CTIMER CMPRA4: CMPR1A4 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRA4_CMPR0A4_Pos (0UL) /*!< CTIMER CMPRA4: CMPR0A4 (Bit 0) */ -#define CTIMER_CMPRA4_CMPR0A4_Msk (0xffffUL) /*!< CTIMER CMPRA4: CMPR0A4 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRB4 ========================================================= */ -#define CTIMER_CMPRB4_CMPR1B4_Pos (16UL) /*!< CTIMER CMPRB4: CMPR1B4 (Bit 16) */ -#define CTIMER_CMPRB4_CMPR1B4_Msk (0xffff0000UL) /*!< CTIMER CMPRB4: CMPR1B4 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRB4_CMPR0B4_Pos (0UL) /*!< CTIMER CMPRB4: CMPR0B4 (Bit 0) */ -#define CTIMER_CMPRB4_CMPR0B4_Msk (0xffffUL) /*!< CTIMER CMPRB4: CMPR0B4 (Bitfield-Mask: 0xffff) */ -/* ========================================================= CTRL4 ========================================================= */ -#define CTIMER_CTRL4_CTLINK4_Pos (31UL) /*!< CTIMER CTRL4: CTLINK4 (Bit 31) */ -#define CTIMER_CTRL4_CTLINK4_Msk (0x80000000UL) /*!< CTIMER CTRL4: CTLINK4 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRB4POL_Pos (28UL) /*!< CTIMER CTRL4: TMRB4POL (Bit 28) */ -#define CTIMER_CTRL4_TMRB4POL_Msk (0x10000000UL) /*!< CTIMER CTRL4: TMRB4POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRB4CLR_Pos (27UL) /*!< CTIMER CTRL4: TMRB4CLR (Bit 27) */ -#define CTIMER_CTRL4_TMRB4CLR_Msk (0x8000000UL) /*!< CTIMER CTRL4: TMRB4CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRB4IE1_Pos (26UL) /*!< CTIMER CTRL4: TMRB4IE1 (Bit 26) */ -#define CTIMER_CTRL4_TMRB4IE1_Msk (0x4000000UL) /*!< CTIMER CTRL4: TMRB4IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRB4IE0_Pos (25UL) /*!< CTIMER CTRL4: TMRB4IE0 (Bit 25) */ -#define CTIMER_CTRL4_TMRB4IE0_Msk (0x2000000UL) /*!< CTIMER CTRL4: TMRB4IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRB4FN_Pos (22UL) /*!< CTIMER CTRL4: TMRB4FN (Bit 22) */ -#define CTIMER_CTRL4_TMRB4FN_Msk (0x1c00000UL) /*!< CTIMER CTRL4: TMRB4FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL4_TMRB4CLK_Pos (17UL) /*!< CTIMER CTRL4: TMRB4CLK (Bit 17) */ -#define CTIMER_CTRL4_TMRB4CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL4: TMRB4CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL4_TMRB4EN_Pos (16UL) /*!< CTIMER CTRL4: TMRB4EN (Bit 16) */ -#define CTIMER_CTRL4_TMRB4EN_Msk (0x10000UL) /*!< CTIMER CTRL4: TMRB4EN (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRA4POL_Pos (12UL) /*!< CTIMER CTRL4: TMRA4POL (Bit 12) */ -#define CTIMER_CTRL4_TMRA4POL_Msk (0x1000UL) /*!< CTIMER CTRL4: TMRA4POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRA4CLR_Pos (11UL) /*!< CTIMER CTRL4: TMRA4CLR (Bit 11) */ -#define CTIMER_CTRL4_TMRA4CLR_Msk (0x800UL) /*!< CTIMER CTRL4: TMRA4CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRA4IE1_Pos (10UL) /*!< CTIMER CTRL4: TMRA4IE1 (Bit 10) */ -#define CTIMER_CTRL4_TMRA4IE1_Msk (0x400UL) /*!< CTIMER CTRL4: TMRA4IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRA4IE0_Pos (9UL) /*!< CTIMER CTRL4: TMRA4IE0 (Bit 9) */ -#define CTIMER_CTRL4_TMRA4IE0_Msk (0x200UL) /*!< CTIMER CTRL4: TMRA4IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL4_TMRA4FN_Pos (6UL) /*!< CTIMER CTRL4: TMRA4FN (Bit 6) */ -#define CTIMER_CTRL4_TMRA4FN_Msk (0x1c0UL) /*!< CTIMER CTRL4: TMRA4FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL4_TMRA4CLK_Pos (1UL) /*!< CTIMER CTRL4: TMRA4CLK (Bit 1) */ -#define CTIMER_CTRL4_TMRA4CLK_Msk (0x3eUL) /*!< CTIMER CTRL4: TMRA4CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL4_TMRA4EN_Pos (0UL) /*!< CTIMER CTRL4: TMRA4EN (Bit 0) */ -#define CTIMER_CTRL4_TMRA4EN_Msk (0x1UL) /*!< CTIMER CTRL4: TMRA4EN (Bitfield-Mask: 0x01) */ -/* ======================================================= CMPRAUXA4 ======================================================= */ -#define CTIMER_CMPRAUXA4_CMPR3A4_Pos (16UL) /*!< CTIMER CMPRAUXA4: CMPR3A4 (Bit 16) */ -#define CTIMER_CMPRAUXA4_CMPR3A4_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA4: CMPR3A4 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXA4_CMPR2A4_Pos (0UL) /*!< CTIMER CMPRAUXA4: CMPR2A4 (Bit 0) */ -#define CTIMER_CMPRAUXA4_CMPR2A4_Msk (0xffffUL) /*!< CTIMER CMPRAUXA4: CMPR2A4 (Bitfield-Mask: 0xffff) */ -/* ======================================================= CMPRAUXB4 ======================================================= */ -#define CTIMER_CMPRAUXB4_CMPR3B4_Pos (16UL) /*!< CTIMER CMPRAUXB4: CMPR3B4 (Bit 16) */ -#define CTIMER_CMPRAUXB4_CMPR3B4_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB4: CMPR3B4 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXB4_CMPR2B4_Pos (0UL) /*!< CTIMER CMPRAUXB4: CMPR2B4 (Bit 0) */ -#define CTIMER_CMPRAUXB4_CMPR2B4_Msk (0xffffUL) /*!< CTIMER CMPRAUXB4: CMPR2B4 (Bitfield-Mask: 0xffff) */ -/* ========================================================= AUX4 ========================================================== */ -#define CTIMER_AUX4_TMRB4EN23_Pos (30UL) /*!< CTIMER AUX4: TMRB4EN23 (Bit 30) */ -#define CTIMER_AUX4_TMRB4EN23_Msk (0x40000000UL) /*!< CTIMER AUX4: TMRB4EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX4_TMRB4POL23_Pos (29UL) /*!< CTIMER AUX4: TMRB4POL23 (Bit 29) */ -#define CTIMER_AUX4_TMRB4POL23_Msk (0x20000000UL) /*!< CTIMER AUX4: TMRB4POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX4_TMRB4TINV_Pos (28UL) /*!< CTIMER AUX4: TMRB4TINV (Bit 28) */ -#define CTIMER_AUX4_TMRB4TINV_Msk (0x10000000UL) /*!< CTIMER AUX4: TMRB4TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX4_TMRB4NOSYNC_Pos (27UL) /*!< CTIMER AUX4: TMRB4NOSYNC (Bit 27) */ -#define CTIMER_AUX4_TMRB4NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX4: TMRB4NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX4_TMRB4TRIG_Pos (23UL) /*!< CTIMER AUX4: TMRB4TRIG (Bit 23) */ -#define CTIMER_AUX4_TMRB4TRIG_Msk (0x7800000UL) /*!< CTIMER AUX4: TMRB4TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX4_TMRB4LMT_Pos (16UL) /*!< CTIMER AUX4: TMRB4LMT (Bit 16) */ -#define CTIMER_AUX4_TMRB4LMT_Msk (0x3f0000UL) /*!< CTIMER AUX4: TMRB4LMT (Bitfield-Mask: 0x3f) */ -#define CTIMER_AUX4_TMRA4EN23_Pos (14UL) /*!< CTIMER AUX4: TMRA4EN23 (Bit 14) */ -#define CTIMER_AUX4_TMRA4EN23_Msk (0x4000UL) /*!< CTIMER AUX4: TMRA4EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX4_TMRA4POL23_Pos (13UL) /*!< CTIMER AUX4: TMRA4POL23 (Bit 13) */ -#define CTIMER_AUX4_TMRA4POL23_Msk (0x2000UL) /*!< CTIMER AUX4: TMRA4POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX4_TMRA4TINV_Pos (12UL) /*!< CTIMER AUX4: TMRA4TINV (Bit 12) */ -#define CTIMER_AUX4_TMRA4TINV_Msk (0x1000UL) /*!< CTIMER AUX4: TMRA4TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX4_TMRA4NOSYNC_Pos (11UL) /*!< CTIMER AUX4: TMRA4NOSYNC (Bit 11) */ -#define CTIMER_AUX4_TMRA4NOSYNC_Msk (0x800UL) /*!< CTIMER AUX4: TMRA4NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX4_TMRA4TRIG_Pos (7UL) /*!< CTIMER AUX4: TMRA4TRIG (Bit 7) */ -#define CTIMER_AUX4_TMRA4TRIG_Msk (0x780UL) /*!< CTIMER AUX4: TMRA4TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX4_TMRA4LMT_Pos (0UL) /*!< CTIMER AUX4: TMRA4LMT (Bit 0) */ -#define CTIMER_AUX4_TMRA4LMT_Msk (0x7fUL) /*!< CTIMER AUX4: TMRA4LMT (Bitfield-Mask: 0x7f) */ -/* ========================================================= TMR5 ========================================================== */ -#define CTIMER_TMR5_CTTMRB5_Pos (16UL) /*!< CTIMER TMR5: CTTMRB5 (Bit 16) */ -#define CTIMER_TMR5_CTTMRB5_Msk (0xffff0000UL) /*!< CTIMER TMR5: CTTMRB5 (Bitfield-Mask: 0xffff) */ -#define CTIMER_TMR5_CTTMRA5_Pos (0UL) /*!< CTIMER TMR5: CTTMRA5 (Bit 0) */ -#define CTIMER_TMR5_CTTMRA5_Msk (0xffffUL) /*!< CTIMER TMR5: CTTMRA5 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRA5 ========================================================= */ -#define CTIMER_CMPRA5_CMPR1A5_Pos (16UL) /*!< CTIMER CMPRA5: CMPR1A5 (Bit 16) */ -#define CTIMER_CMPRA5_CMPR1A5_Msk (0xffff0000UL) /*!< CTIMER CMPRA5: CMPR1A5 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRA5_CMPR0A5_Pos (0UL) /*!< CTIMER CMPRA5: CMPR0A5 (Bit 0) */ -#define CTIMER_CMPRA5_CMPR0A5_Msk (0xffffUL) /*!< CTIMER CMPRA5: CMPR0A5 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRB5 ========================================================= */ -#define CTIMER_CMPRB5_CMPR1B5_Pos (16UL) /*!< CTIMER CMPRB5: CMPR1B5 (Bit 16) */ -#define CTIMER_CMPRB5_CMPR1B5_Msk (0xffff0000UL) /*!< CTIMER CMPRB5: CMPR1B5 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRB5_CMPR0B5_Pos (0UL) /*!< CTIMER CMPRB5: CMPR0B5 (Bit 0) */ -#define CTIMER_CMPRB5_CMPR0B5_Msk (0xffffUL) /*!< CTIMER CMPRB5: CMPR0B5 (Bitfield-Mask: 0xffff) */ -/* ========================================================= CTRL5 ========================================================= */ -#define CTIMER_CTRL5_CTLINK5_Pos (31UL) /*!< CTIMER CTRL5: CTLINK5 (Bit 31) */ -#define CTIMER_CTRL5_CTLINK5_Msk (0x80000000UL) /*!< CTIMER CTRL5: CTLINK5 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRB5POL_Pos (28UL) /*!< CTIMER CTRL5: TMRB5POL (Bit 28) */ -#define CTIMER_CTRL5_TMRB5POL_Msk (0x10000000UL) /*!< CTIMER CTRL5: TMRB5POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRB5CLR_Pos (27UL) /*!< CTIMER CTRL5: TMRB5CLR (Bit 27) */ -#define CTIMER_CTRL5_TMRB5CLR_Msk (0x8000000UL) /*!< CTIMER CTRL5: TMRB5CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRB5IE1_Pos (26UL) /*!< CTIMER CTRL5: TMRB5IE1 (Bit 26) */ -#define CTIMER_CTRL5_TMRB5IE1_Msk (0x4000000UL) /*!< CTIMER CTRL5: TMRB5IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRB5IE0_Pos (25UL) /*!< CTIMER CTRL5: TMRB5IE0 (Bit 25) */ -#define CTIMER_CTRL5_TMRB5IE0_Msk (0x2000000UL) /*!< CTIMER CTRL5: TMRB5IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRB5FN_Pos (22UL) /*!< CTIMER CTRL5: TMRB5FN (Bit 22) */ -#define CTIMER_CTRL5_TMRB5FN_Msk (0x1c00000UL) /*!< CTIMER CTRL5: TMRB5FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL5_TMRB5CLK_Pos (17UL) /*!< CTIMER CTRL5: TMRB5CLK (Bit 17) */ -#define CTIMER_CTRL5_TMRB5CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL5: TMRB5CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL5_TMRB5EN_Pos (16UL) /*!< CTIMER CTRL5: TMRB5EN (Bit 16) */ -#define CTIMER_CTRL5_TMRB5EN_Msk (0x10000UL) /*!< CTIMER CTRL5: TMRB5EN (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRA5POL_Pos (12UL) /*!< CTIMER CTRL5: TMRA5POL (Bit 12) */ -#define CTIMER_CTRL5_TMRA5POL_Msk (0x1000UL) /*!< CTIMER CTRL5: TMRA5POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRA5CLR_Pos (11UL) /*!< CTIMER CTRL5: TMRA5CLR (Bit 11) */ -#define CTIMER_CTRL5_TMRA5CLR_Msk (0x800UL) /*!< CTIMER CTRL5: TMRA5CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRA5IE1_Pos (10UL) /*!< CTIMER CTRL5: TMRA5IE1 (Bit 10) */ -#define CTIMER_CTRL5_TMRA5IE1_Msk (0x400UL) /*!< CTIMER CTRL5: TMRA5IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRA5IE0_Pos (9UL) /*!< CTIMER CTRL5: TMRA5IE0 (Bit 9) */ -#define CTIMER_CTRL5_TMRA5IE0_Msk (0x200UL) /*!< CTIMER CTRL5: TMRA5IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL5_TMRA5FN_Pos (6UL) /*!< CTIMER CTRL5: TMRA5FN (Bit 6) */ -#define CTIMER_CTRL5_TMRA5FN_Msk (0x1c0UL) /*!< CTIMER CTRL5: TMRA5FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL5_TMRA5CLK_Pos (1UL) /*!< CTIMER CTRL5: TMRA5CLK (Bit 1) */ -#define CTIMER_CTRL5_TMRA5CLK_Msk (0x3eUL) /*!< CTIMER CTRL5: TMRA5CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL5_TMRA5EN_Pos (0UL) /*!< CTIMER CTRL5: TMRA5EN (Bit 0) */ -#define CTIMER_CTRL5_TMRA5EN_Msk (0x1UL) /*!< CTIMER CTRL5: TMRA5EN (Bitfield-Mask: 0x01) */ -/* ======================================================= CMPRAUXA5 ======================================================= */ -#define CTIMER_CMPRAUXA5_CMPR3A5_Pos (16UL) /*!< CTIMER CMPRAUXA5: CMPR3A5 (Bit 16) */ -#define CTIMER_CMPRAUXA5_CMPR3A5_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA5: CMPR3A5 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXA5_CMPR2A5_Pos (0UL) /*!< CTIMER CMPRAUXA5: CMPR2A5 (Bit 0) */ -#define CTIMER_CMPRAUXA5_CMPR2A5_Msk (0xffffUL) /*!< CTIMER CMPRAUXA5: CMPR2A5 (Bitfield-Mask: 0xffff) */ -/* ======================================================= CMPRAUXB5 ======================================================= */ -#define CTIMER_CMPRAUXB5_CMPR3B5_Pos (16UL) /*!< CTIMER CMPRAUXB5: CMPR3B5 (Bit 16) */ -#define CTIMER_CMPRAUXB5_CMPR3B5_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB5: CMPR3B5 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXB5_CMPR2B5_Pos (0UL) /*!< CTIMER CMPRAUXB5: CMPR2B5 (Bit 0) */ -#define CTIMER_CMPRAUXB5_CMPR2B5_Msk (0xffffUL) /*!< CTIMER CMPRAUXB5: CMPR2B5 (Bitfield-Mask: 0xffff) */ -/* ========================================================= AUX5 ========================================================== */ -#define CTIMER_AUX5_TMRB5EN23_Pos (30UL) /*!< CTIMER AUX5: TMRB5EN23 (Bit 30) */ -#define CTIMER_AUX5_TMRB5EN23_Msk (0x40000000UL) /*!< CTIMER AUX5: TMRB5EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX5_TMRB5POL23_Pos (29UL) /*!< CTIMER AUX5: TMRB5POL23 (Bit 29) */ -#define CTIMER_AUX5_TMRB5POL23_Msk (0x20000000UL) /*!< CTIMER AUX5: TMRB5POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX5_TMRB5TINV_Pos (28UL) /*!< CTIMER AUX5: TMRB5TINV (Bit 28) */ -#define CTIMER_AUX5_TMRB5TINV_Msk (0x10000000UL) /*!< CTIMER AUX5: TMRB5TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX5_TMRB5NOSYNC_Pos (27UL) /*!< CTIMER AUX5: TMRB5NOSYNC (Bit 27) */ -#define CTIMER_AUX5_TMRB5NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX5: TMRB5NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX5_TMRB5TRIG_Pos (23UL) /*!< CTIMER AUX5: TMRB5TRIG (Bit 23) */ -#define CTIMER_AUX5_TMRB5TRIG_Msk (0x7800000UL) /*!< CTIMER AUX5: TMRB5TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX5_TMRB5LMT_Pos (16UL) /*!< CTIMER AUX5: TMRB5LMT (Bit 16) */ -#define CTIMER_AUX5_TMRB5LMT_Msk (0x3f0000UL) /*!< CTIMER AUX5: TMRB5LMT (Bitfield-Mask: 0x3f) */ -#define CTIMER_AUX5_TMRA5EN23_Pos (14UL) /*!< CTIMER AUX5: TMRA5EN23 (Bit 14) */ -#define CTIMER_AUX5_TMRA5EN23_Msk (0x4000UL) /*!< CTIMER AUX5: TMRA5EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX5_TMRA5POL23_Pos (13UL) /*!< CTIMER AUX5: TMRA5POL23 (Bit 13) */ -#define CTIMER_AUX5_TMRA5POL23_Msk (0x2000UL) /*!< CTIMER AUX5: TMRA5POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX5_TMRA5TINV_Pos (12UL) /*!< CTIMER AUX5: TMRA5TINV (Bit 12) */ -#define CTIMER_AUX5_TMRA5TINV_Msk (0x1000UL) /*!< CTIMER AUX5: TMRA5TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX5_TMRA5NOSYNC_Pos (11UL) /*!< CTIMER AUX5: TMRA5NOSYNC (Bit 11) */ -#define CTIMER_AUX5_TMRA5NOSYNC_Msk (0x800UL) /*!< CTIMER AUX5: TMRA5NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX5_TMRA5TRIG_Pos (7UL) /*!< CTIMER AUX5: TMRA5TRIG (Bit 7) */ -#define CTIMER_AUX5_TMRA5TRIG_Msk (0x780UL) /*!< CTIMER AUX5: TMRA5TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX5_TMRA5LMT_Pos (0UL) /*!< CTIMER AUX5: TMRA5LMT (Bit 0) */ -#define CTIMER_AUX5_TMRA5LMT_Msk (0x7fUL) /*!< CTIMER AUX5: TMRA5LMT (Bitfield-Mask: 0x7f) */ -/* ========================================================= TMR6 ========================================================== */ -#define CTIMER_TMR6_CTTMRB6_Pos (16UL) /*!< CTIMER TMR6: CTTMRB6 (Bit 16) */ -#define CTIMER_TMR6_CTTMRB6_Msk (0xffff0000UL) /*!< CTIMER TMR6: CTTMRB6 (Bitfield-Mask: 0xffff) */ -#define CTIMER_TMR6_CTTMRA6_Pos (0UL) /*!< CTIMER TMR6: CTTMRA6 (Bit 0) */ -#define CTIMER_TMR6_CTTMRA6_Msk (0xffffUL) /*!< CTIMER TMR6: CTTMRA6 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRA6 ========================================================= */ -#define CTIMER_CMPRA6_CMPR1A6_Pos (16UL) /*!< CTIMER CMPRA6: CMPR1A6 (Bit 16) */ -#define CTIMER_CMPRA6_CMPR1A6_Msk (0xffff0000UL) /*!< CTIMER CMPRA6: CMPR1A6 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRA6_CMPR0A6_Pos (0UL) /*!< CTIMER CMPRA6: CMPR0A6 (Bit 0) */ -#define CTIMER_CMPRA6_CMPR0A6_Msk (0xffffUL) /*!< CTIMER CMPRA6: CMPR0A6 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRB6 ========================================================= */ -#define CTIMER_CMPRB6_CMPR1B6_Pos (16UL) /*!< CTIMER CMPRB6: CMPR1B6 (Bit 16) */ -#define CTIMER_CMPRB6_CMPR1B6_Msk (0xffff0000UL) /*!< CTIMER CMPRB6: CMPR1B6 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRB6_CMPR0B6_Pos (0UL) /*!< CTIMER CMPRB6: CMPR0B6 (Bit 0) */ -#define CTIMER_CMPRB6_CMPR0B6_Msk (0xffffUL) /*!< CTIMER CMPRB6: CMPR0B6 (Bitfield-Mask: 0xffff) */ -/* ========================================================= CTRL6 ========================================================= */ -#define CTIMER_CTRL6_CTLINK6_Pos (31UL) /*!< CTIMER CTRL6: CTLINK6 (Bit 31) */ -#define CTIMER_CTRL6_CTLINK6_Msk (0x80000000UL) /*!< CTIMER CTRL6: CTLINK6 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRB6POL_Pos (28UL) /*!< CTIMER CTRL6: TMRB6POL (Bit 28) */ -#define CTIMER_CTRL6_TMRB6POL_Msk (0x10000000UL) /*!< CTIMER CTRL6: TMRB6POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRB6CLR_Pos (27UL) /*!< CTIMER CTRL6: TMRB6CLR (Bit 27) */ -#define CTIMER_CTRL6_TMRB6CLR_Msk (0x8000000UL) /*!< CTIMER CTRL6: TMRB6CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRB6IE1_Pos (26UL) /*!< CTIMER CTRL6: TMRB6IE1 (Bit 26) */ -#define CTIMER_CTRL6_TMRB6IE1_Msk (0x4000000UL) /*!< CTIMER CTRL6: TMRB6IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRB6IE0_Pos (25UL) /*!< CTIMER CTRL6: TMRB6IE0 (Bit 25) */ -#define CTIMER_CTRL6_TMRB6IE0_Msk (0x2000000UL) /*!< CTIMER CTRL6: TMRB6IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRB6FN_Pos (22UL) /*!< CTIMER CTRL6: TMRB6FN (Bit 22) */ -#define CTIMER_CTRL6_TMRB6FN_Msk (0x1c00000UL) /*!< CTIMER CTRL6: TMRB6FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL6_TMRB6CLK_Pos (17UL) /*!< CTIMER CTRL6: TMRB6CLK (Bit 17) */ -#define CTIMER_CTRL6_TMRB6CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL6: TMRB6CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL6_TMRB6EN_Pos (16UL) /*!< CTIMER CTRL6: TMRB6EN (Bit 16) */ -#define CTIMER_CTRL6_TMRB6EN_Msk (0x10000UL) /*!< CTIMER CTRL6: TMRB6EN (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRA6POL_Pos (12UL) /*!< CTIMER CTRL6: TMRA6POL (Bit 12) */ -#define CTIMER_CTRL6_TMRA6POL_Msk (0x1000UL) /*!< CTIMER CTRL6: TMRA6POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRA6CLR_Pos (11UL) /*!< CTIMER CTRL6: TMRA6CLR (Bit 11) */ -#define CTIMER_CTRL6_TMRA6CLR_Msk (0x800UL) /*!< CTIMER CTRL6: TMRA6CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRA6IE1_Pos (10UL) /*!< CTIMER CTRL6: TMRA6IE1 (Bit 10) */ -#define CTIMER_CTRL6_TMRA6IE1_Msk (0x400UL) /*!< CTIMER CTRL6: TMRA6IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRA6IE0_Pos (9UL) /*!< CTIMER CTRL6: TMRA6IE0 (Bit 9) */ -#define CTIMER_CTRL6_TMRA6IE0_Msk (0x200UL) /*!< CTIMER CTRL6: TMRA6IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL6_TMRA6FN_Pos (6UL) /*!< CTIMER CTRL6: TMRA6FN (Bit 6) */ -#define CTIMER_CTRL6_TMRA6FN_Msk (0x1c0UL) /*!< CTIMER CTRL6: TMRA6FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL6_TMRA6CLK_Pos (1UL) /*!< CTIMER CTRL6: TMRA6CLK (Bit 1) */ -#define CTIMER_CTRL6_TMRA6CLK_Msk (0x3eUL) /*!< CTIMER CTRL6: TMRA6CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL6_TMRA6EN_Pos (0UL) /*!< CTIMER CTRL6: TMRA6EN (Bit 0) */ -#define CTIMER_CTRL6_TMRA6EN_Msk (0x1UL) /*!< CTIMER CTRL6: TMRA6EN (Bitfield-Mask: 0x01) */ -/* ======================================================= CMPRAUXA6 ======================================================= */ -#define CTIMER_CMPRAUXA6_CMPR3A6_Pos (16UL) /*!< CTIMER CMPRAUXA6: CMPR3A6 (Bit 16) */ -#define CTIMER_CMPRAUXA6_CMPR3A6_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA6: CMPR3A6 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXA6_CMPR2A6_Pos (0UL) /*!< CTIMER CMPRAUXA6: CMPR2A6 (Bit 0) */ -#define CTIMER_CMPRAUXA6_CMPR2A6_Msk (0xffffUL) /*!< CTIMER CMPRAUXA6: CMPR2A6 (Bitfield-Mask: 0xffff) */ -/* ======================================================= CMPRAUXB6 ======================================================= */ -#define CTIMER_CMPRAUXB6_CMPR3B6_Pos (16UL) /*!< CTIMER CMPRAUXB6: CMPR3B6 (Bit 16) */ -#define CTIMER_CMPRAUXB6_CMPR3B6_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB6: CMPR3B6 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXB6_CMPR2B6_Pos (0UL) /*!< CTIMER CMPRAUXB6: CMPR2B6 (Bit 0) */ -#define CTIMER_CMPRAUXB6_CMPR2B6_Msk (0xffffUL) /*!< CTIMER CMPRAUXB6: CMPR2B6 (Bitfield-Mask: 0xffff) */ -/* ========================================================= AUX6 ========================================================== */ -#define CTIMER_AUX6_TMRB6EN23_Pos (30UL) /*!< CTIMER AUX6: TMRB6EN23 (Bit 30) */ -#define CTIMER_AUX6_TMRB6EN23_Msk (0x40000000UL) /*!< CTIMER AUX6: TMRB6EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX6_TMRB6POL23_Pos (29UL) /*!< CTIMER AUX6: TMRB6POL23 (Bit 29) */ -#define CTIMER_AUX6_TMRB6POL23_Msk (0x20000000UL) /*!< CTIMER AUX6: TMRB6POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX6_TMRB6TINV_Pos (28UL) /*!< CTIMER AUX6: TMRB6TINV (Bit 28) */ -#define CTIMER_AUX6_TMRB6TINV_Msk (0x10000000UL) /*!< CTIMER AUX6: TMRB6TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX6_TMRB6NOSYNC_Pos (27UL) /*!< CTIMER AUX6: TMRB6NOSYNC (Bit 27) */ -#define CTIMER_AUX6_TMRB6NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX6: TMRB6NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX6_TMRB6TRIG_Pos (23UL) /*!< CTIMER AUX6: TMRB6TRIG (Bit 23) */ -#define CTIMER_AUX6_TMRB6TRIG_Msk (0x7800000UL) /*!< CTIMER AUX6: TMRB6TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX6_TMRB6LMT_Pos (16UL) /*!< CTIMER AUX6: TMRB6LMT (Bit 16) */ -#define CTIMER_AUX6_TMRB6LMT_Msk (0x3f0000UL) /*!< CTIMER AUX6: TMRB6LMT (Bitfield-Mask: 0x3f) */ -#define CTIMER_AUX6_TMRA6EN23_Pos (14UL) /*!< CTIMER AUX6: TMRA6EN23 (Bit 14) */ -#define CTIMER_AUX6_TMRA6EN23_Msk (0x4000UL) /*!< CTIMER AUX6: TMRA6EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX6_TMRA6POL23_Pos (13UL) /*!< CTIMER AUX6: TMRA6POL23 (Bit 13) */ -#define CTIMER_AUX6_TMRA6POL23_Msk (0x2000UL) /*!< CTIMER AUX6: TMRA6POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX6_TMRA6TINV_Pos (12UL) /*!< CTIMER AUX6: TMRA6TINV (Bit 12) */ -#define CTIMER_AUX6_TMRA6TINV_Msk (0x1000UL) /*!< CTIMER AUX6: TMRA6TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX6_TMRA6NOSYNC_Pos (11UL) /*!< CTIMER AUX6: TMRA6NOSYNC (Bit 11) */ -#define CTIMER_AUX6_TMRA6NOSYNC_Msk (0x800UL) /*!< CTIMER AUX6: TMRA6NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX6_TMRA6TRIG_Pos (7UL) /*!< CTIMER AUX6: TMRA6TRIG (Bit 7) */ -#define CTIMER_AUX6_TMRA6TRIG_Msk (0x780UL) /*!< CTIMER AUX6: TMRA6TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX6_TMRA6LMT_Pos (0UL) /*!< CTIMER AUX6: TMRA6LMT (Bit 0) */ -#define CTIMER_AUX6_TMRA6LMT_Msk (0x7fUL) /*!< CTIMER AUX6: TMRA6LMT (Bitfield-Mask: 0x7f) */ -/* ========================================================= TMR7 ========================================================== */ -#define CTIMER_TMR7_CTTMRB7_Pos (16UL) /*!< CTIMER TMR7: CTTMRB7 (Bit 16) */ -#define CTIMER_TMR7_CTTMRB7_Msk (0xffff0000UL) /*!< CTIMER TMR7: CTTMRB7 (Bitfield-Mask: 0xffff) */ -#define CTIMER_TMR7_CTTMRA7_Pos (0UL) /*!< CTIMER TMR7: CTTMRA7 (Bit 0) */ -#define CTIMER_TMR7_CTTMRA7_Msk (0xffffUL) /*!< CTIMER TMR7: CTTMRA7 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRA7 ========================================================= */ -#define CTIMER_CMPRA7_CMPR1A7_Pos (16UL) /*!< CTIMER CMPRA7: CMPR1A7 (Bit 16) */ -#define CTIMER_CMPRA7_CMPR1A7_Msk (0xffff0000UL) /*!< CTIMER CMPRA7: CMPR1A7 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRA7_CMPR0A7_Pos (0UL) /*!< CTIMER CMPRA7: CMPR0A7 (Bit 0) */ -#define CTIMER_CMPRA7_CMPR0A7_Msk (0xffffUL) /*!< CTIMER CMPRA7: CMPR0A7 (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMPRB7 ========================================================= */ -#define CTIMER_CMPRB7_CMPR1B7_Pos (16UL) /*!< CTIMER CMPRB7: CMPR1B7 (Bit 16) */ -#define CTIMER_CMPRB7_CMPR1B7_Msk (0xffff0000UL) /*!< CTIMER CMPRB7: CMPR1B7 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRB7_CMPR0B7_Pos (0UL) /*!< CTIMER CMPRB7: CMPR0B7 (Bit 0) */ -#define CTIMER_CMPRB7_CMPR0B7_Msk (0xffffUL) /*!< CTIMER CMPRB7: CMPR0B7 (Bitfield-Mask: 0xffff) */ -/* ========================================================= CTRL7 ========================================================= */ -#define CTIMER_CTRL7_CTLINK7_Pos (31UL) /*!< CTIMER CTRL7: CTLINK7 (Bit 31) */ -#define CTIMER_CTRL7_CTLINK7_Msk (0x80000000UL) /*!< CTIMER CTRL7: CTLINK7 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRB7POL_Pos (28UL) /*!< CTIMER CTRL7: TMRB7POL (Bit 28) */ -#define CTIMER_CTRL7_TMRB7POL_Msk (0x10000000UL) /*!< CTIMER CTRL7: TMRB7POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRB7CLR_Pos (27UL) /*!< CTIMER CTRL7: TMRB7CLR (Bit 27) */ -#define CTIMER_CTRL7_TMRB7CLR_Msk (0x8000000UL) /*!< CTIMER CTRL7: TMRB7CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRB7IE1_Pos (26UL) /*!< CTIMER CTRL7: TMRB7IE1 (Bit 26) */ -#define CTIMER_CTRL7_TMRB7IE1_Msk (0x4000000UL) /*!< CTIMER CTRL7: TMRB7IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRB7IE0_Pos (25UL) /*!< CTIMER CTRL7: TMRB7IE0 (Bit 25) */ -#define CTIMER_CTRL7_TMRB7IE0_Msk (0x2000000UL) /*!< CTIMER CTRL7: TMRB7IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRB7FN_Pos (22UL) /*!< CTIMER CTRL7: TMRB7FN (Bit 22) */ -#define CTIMER_CTRL7_TMRB7FN_Msk (0x1c00000UL) /*!< CTIMER CTRL7: TMRB7FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL7_TMRB7CLK_Pos (17UL) /*!< CTIMER CTRL7: TMRB7CLK (Bit 17) */ -#define CTIMER_CTRL7_TMRB7CLK_Msk (0x3e0000UL) /*!< CTIMER CTRL7: TMRB7CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL7_TMRB7EN_Pos (16UL) /*!< CTIMER CTRL7: TMRB7EN (Bit 16) */ -#define CTIMER_CTRL7_TMRB7EN_Msk (0x10000UL) /*!< CTIMER CTRL7: TMRB7EN (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRA7POL_Pos (12UL) /*!< CTIMER CTRL7: TMRA7POL (Bit 12) */ -#define CTIMER_CTRL7_TMRA7POL_Msk (0x1000UL) /*!< CTIMER CTRL7: TMRA7POL (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRA7CLR_Pos (11UL) /*!< CTIMER CTRL7: TMRA7CLR (Bit 11) */ -#define CTIMER_CTRL7_TMRA7CLR_Msk (0x800UL) /*!< CTIMER CTRL7: TMRA7CLR (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRA7IE1_Pos (10UL) /*!< CTIMER CTRL7: TMRA7IE1 (Bit 10) */ -#define CTIMER_CTRL7_TMRA7IE1_Msk (0x400UL) /*!< CTIMER CTRL7: TMRA7IE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRA7IE0_Pos (9UL) /*!< CTIMER CTRL7: TMRA7IE0 (Bit 9) */ -#define CTIMER_CTRL7_TMRA7IE0_Msk (0x200UL) /*!< CTIMER CTRL7: TMRA7IE0 (Bitfield-Mask: 0x01) */ -#define CTIMER_CTRL7_TMRA7FN_Pos (6UL) /*!< CTIMER CTRL7: TMRA7FN (Bit 6) */ -#define CTIMER_CTRL7_TMRA7FN_Msk (0x1c0UL) /*!< CTIMER CTRL7: TMRA7FN (Bitfield-Mask: 0x07) */ -#define CTIMER_CTRL7_TMRA7CLK_Pos (1UL) /*!< CTIMER CTRL7: TMRA7CLK (Bit 1) */ -#define CTIMER_CTRL7_TMRA7CLK_Msk (0x3eUL) /*!< CTIMER CTRL7: TMRA7CLK (Bitfield-Mask: 0x1f) */ -#define CTIMER_CTRL7_TMRA7EN_Pos (0UL) /*!< CTIMER CTRL7: TMRA7EN (Bit 0) */ -#define CTIMER_CTRL7_TMRA7EN_Msk (0x1UL) /*!< CTIMER CTRL7: TMRA7EN (Bitfield-Mask: 0x01) */ -/* ======================================================= CMPRAUXA7 ======================================================= */ -#define CTIMER_CMPRAUXA7_CMPR3A7_Pos (16UL) /*!< CTIMER CMPRAUXA7: CMPR3A7 (Bit 16) */ -#define CTIMER_CMPRAUXA7_CMPR3A7_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXA7: CMPR3A7 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXA7_CMPR2A7_Pos (0UL) /*!< CTIMER CMPRAUXA7: CMPR2A7 (Bit 0) */ -#define CTIMER_CMPRAUXA7_CMPR2A7_Msk (0xffffUL) /*!< CTIMER CMPRAUXA7: CMPR2A7 (Bitfield-Mask: 0xffff) */ -/* ======================================================= CMPRAUXB7 ======================================================= */ -#define CTIMER_CMPRAUXB7_CMPR3B7_Pos (16UL) /*!< CTIMER CMPRAUXB7: CMPR3B7 (Bit 16) */ -#define CTIMER_CMPRAUXB7_CMPR3B7_Msk (0xffff0000UL) /*!< CTIMER CMPRAUXB7: CMPR3B7 (Bitfield-Mask: 0xffff) */ -#define CTIMER_CMPRAUXB7_CMPR2B7_Pos (0UL) /*!< CTIMER CMPRAUXB7: CMPR2B7 (Bit 0) */ -#define CTIMER_CMPRAUXB7_CMPR2B7_Msk (0xffffUL) /*!< CTIMER CMPRAUXB7: CMPR2B7 (Bitfield-Mask: 0xffff) */ -/* ========================================================= AUX7 ========================================================== */ -#define CTIMER_AUX7_TMRB7EN23_Pos (30UL) /*!< CTIMER AUX7: TMRB7EN23 (Bit 30) */ -#define CTIMER_AUX7_TMRB7EN23_Msk (0x40000000UL) /*!< CTIMER AUX7: TMRB7EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX7_TMRB7POL23_Pos (29UL) /*!< CTIMER AUX7: TMRB7POL23 (Bit 29) */ -#define CTIMER_AUX7_TMRB7POL23_Msk (0x20000000UL) /*!< CTIMER AUX7: TMRB7POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX7_TMRB7TINV_Pos (28UL) /*!< CTIMER AUX7: TMRB7TINV (Bit 28) */ -#define CTIMER_AUX7_TMRB7TINV_Msk (0x10000000UL) /*!< CTIMER AUX7: TMRB7TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX7_TMRB7NOSYNC_Pos (27UL) /*!< CTIMER AUX7: TMRB7NOSYNC (Bit 27) */ -#define CTIMER_AUX7_TMRB7NOSYNC_Msk (0x8000000UL) /*!< CTIMER AUX7: TMRB7NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX7_TMRB7TRIG_Pos (23UL) /*!< CTIMER AUX7: TMRB7TRIG (Bit 23) */ -#define CTIMER_AUX7_TMRB7TRIG_Msk (0x7800000UL) /*!< CTIMER AUX7: TMRB7TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX7_TMRB7LMT_Pos (16UL) /*!< CTIMER AUX7: TMRB7LMT (Bit 16) */ -#define CTIMER_AUX7_TMRB7LMT_Msk (0x3f0000UL) /*!< CTIMER AUX7: TMRB7LMT (Bitfield-Mask: 0x3f) */ -#define CTIMER_AUX7_TMRA7EN23_Pos (14UL) /*!< CTIMER AUX7: TMRA7EN23 (Bit 14) */ -#define CTIMER_AUX7_TMRA7EN23_Msk (0x4000UL) /*!< CTIMER AUX7: TMRA7EN23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX7_TMRA7POL23_Pos (13UL) /*!< CTIMER AUX7: TMRA7POL23 (Bit 13) */ -#define CTIMER_AUX7_TMRA7POL23_Msk (0x2000UL) /*!< CTIMER AUX7: TMRA7POL23 (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX7_TMRA7TINV_Pos (12UL) /*!< CTIMER AUX7: TMRA7TINV (Bit 12) */ -#define CTIMER_AUX7_TMRA7TINV_Msk (0x1000UL) /*!< CTIMER AUX7: TMRA7TINV (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX7_TMRA7NOSYNC_Pos (11UL) /*!< CTIMER AUX7: TMRA7NOSYNC (Bit 11) */ -#define CTIMER_AUX7_TMRA7NOSYNC_Msk (0x800UL) /*!< CTIMER AUX7: TMRA7NOSYNC (Bitfield-Mask: 0x01) */ -#define CTIMER_AUX7_TMRA7TRIG_Pos (7UL) /*!< CTIMER AUX7: TMRA7TRIG (Bit 7) */ -#define CTIMER_AUX7_TMRA7TRIG_Msk (0x780UL) /*!< CTIMER AUX7: TMRA7TRIG (Bitfield-Mask: 0x0f) */ -#define CTIMER_AUX7_TMRA7LMT_Pos (0UL) /*!< CTIMER AUX7: TMRA7LMT (Bit 0) */ -#define CTIMER_AUX7_TMRA7LMT_Msk (0x7fUL) /*!< CTIMER AUX7: TMRA7LMT (Bitfield-Mask: 0x7f) */ -/* ======================================================== GLOBEN ========================================================= */ -#define CTIMER_GLOBEN_ENB7_Pos (15UL) /*!< CTIMER GLOBEN: ENB7 (Bit 15) */ -#define CTIMER_GLOBEN_ENB7_Msk (0x8000UL) /*!< CTIMER GLOBEN: ENB7 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENA7_Pos (14UL) /*!< CTIMER GLOBEN: ENA7 (Bit 14) */ -#define CTIMER_GLOBEN_ENA7_Msk (0x4000UL) /*!< CTIMER GLOBEN: ENA7 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENB6_Pos (13UL) /*!< CTIMER GLOBEN: ENB6 (Bit 13) */ -#define CTIMER_GLOBEN_ENB6_Msk (0x2000UL) /*!< CTIMER GLOBEN: ENB6 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENA6_Pos (12UL) /*!< CTIMER GLOBEN: ENA6 (Bit 12) */ -#define CTIMER_GLOBEN_ENA6_Msk (0x1000UL) /*!< CTIMER GLOBEN: ENA6 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENB5_Pos (11UL) /*!< CTIMER GLOBEN: ENB5 (Bit 11) */ -#define CTIMER_GLOBEN_ENB5_Msk (0x800UL) /*!< CTIMER GLOBEN: ENB5 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENA5_Pos (10UL) /*!< CTIMER GLOBEN: ENA5 (Bit 10) */ -#define CTIMER_GLOBEN_ENA5_Msk (0x400UL) /*!< CTIMER GLOBEN: ENA5 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENB4_Pos (9UL) /*!< CTIMER GLOBEN: ENB4 (Bit 9) */ -#define CTIMER_GLOBEN_ENB4_Msk (0x200UL) /*!< CTIMER GLOBEN: ENB4 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENA4_Pos (8UL) /*!< CTIMER GLOBEN: ENA4 (Bit 8) */ -#define CTIMER_GLOBEN_ENA4_Msk (0x100UL) /*!< CTIMER GLOBEN: ENA4 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENB3_Pos (7UL) /*!< CTIMER GLOBEN: ENB3 (Bit 7) */ -#define CTIMER_GLOBEN_ENB3_Msk (0x80UL) /*!< CTIMER GLOBEN: ENB3 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENA3_Pos (6UL) /*!< CTIMER GLOBEN: ENA3 (Bit 6) */ -#define CTIMER_GLOBEN_ENA3_Msk (0x40UL) /*!< CTIMER GLOBEN: ENA3 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENB2_Pos (5UL) /*!< CTIMER GLOBEN: ENB2 (Bit 5) */ -#define CTIMER_GLOBEN_ENB2_Msk (0x20UL) /*!< CTIMER GLOBEN: ENB2 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENA2_Pos (4UL) /*!< CTIMER GLOBEN: ENA2 (Bit 4) */ -#define CTIMER_GLOBEN_ENA2_Msk (0x10UL) /*!< CTIMER GLOBEN: ENA2 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENB1_Pos (3UL) /*!< CTIMER GLOBEN: ENB1 (Bit 3) */ -#define CTIMER_GLOBEN_ENB1_Msk (0x8UL) /*!< CTIMER GLOBEN: ENB1 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENA1_Pos (2UL) /*!< CTIMER GLOBEN: ENA1 (Bit 2) */ -#define CTIMER_GLOBEN_ENA1_Msk (0x4UL) /*!< CTIMER GLOBEN: ENA1 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENB0_Pos (1UL) /*!< CTIMER GLOBEN: ENB0 (Bit 1) */ -#define CTIMER_GLOBEN_ENB0_Msk (0x2UL) /*!< CTIMER GLOBEN: ENB0 (Bitfield-Mask: 0x01) */ -#define CTIMER_GLOBEN_ENA0_Pos (0UL) /*!< CTIMER GLOBEN: ENA0 (Bit 0) */ -#define CTIMER_GLOBEN_ENA0_Msk (0x1UL) /*!< CTIMER GLOBEN: ENA0 (Bitfield-Mask: 0x01) */ -/* ======================================================== OUTCFG0 ======================================================== */ -#define CTIMER_OUTCFG0_CFG9_Pos (28UL) /*!< CTIMER OUTCFG0: CFG9 (Bit 28) */ -#define CTIMER_OUTCFG0_CFG9_Msk (0x70000000UL) /*!< CTIMER OUTCFG0: CFG9 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG0_CFG8_Pos (25UL) /*!< CTIMER OUTCFG0: CFG8 (Bit 25) */ -#define CTIMER_OUTCFG0_CFG8_Msk (0xe000000UL) /*!< CTIMER OUTCFG0: CFG8 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG0_CFG7_Pos (22UL) /*!< CTIMER OUTCFG0: CFG7 (Bit 22) */ -#define CTIMER_OUTCFG0_CFG7_Msk (0x1c00000UL) /*!< CTIMER OUTCFG0: CFG7 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG0_CFG6_Pos (19UL) /*!< CTIMER OUTCFG0: CFG6 (Bit 19) */ -#define CTIMER_OUTCFG0_CFG6_Msk (0x380000UL) /*!< CTIMER OUTCFG0: CFG6 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG0_CFG5_Pos (16UL) /*!< CTIMER OUTCFG0: CFG5 (Bit 16) */ -#define CTIMER_OUTCFG0_CFG5_Msk (0x70000UL) /*!< CTIMER OUTCFG0: CFG5 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG0_CFG4_Pos (12UL) /*!< CTIMER OUTCFG0: CFG4 (Bit 12) */ -#define CTIMER_OUTCFG0_CFG4_Msk (0x7000UL) /*!< CTIMER OUTCFG0: CFG4 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG0_CFG3_Pos (9UL) /*!< CTIMER OUTCFG0: CFG3 (Bit 9) */ -#define CTIMER_OUTCFG0_CFG3_Msk (0xe00UL) /*!< CTIMER OUTCFG0: CFG3 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG0_CFG2_Pos (6UL) /*!< CTIMER OUTCFG0: CFG2 (Bit 6) */ -#define CTIMER_OUTCFG0_CFG2_Msk (0x1c0UL) /*!< CTIMER OUTCFG0: CFG2 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG0_CFG1_Pos (3UL) /*!< CTIMER OUTCFG0: CFG1 (Bit 3) */ -#define CTIMER_OUTCFG0_CFG1_Msk (0x38UL) /*!< CTIMER OUTCFG0: CFG1 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG0_CFG0_Pos (0UL) /*!< CTIMER OUTCFG0: CFG0 (Bit 0) */ -#define CTIMER_OUTCFG0_CFG0_Msk (0x7UL) /*!< CTIMER OUTCFG0: CFG0 (Bitfield-Mask: 0x07) */ -/* ======================================================== OUTCFG1 ======================================================== */ -#define CTIMER_OUTCFG1_CFG19_Pos (28UL) /*!< CTIMER OUTCFG1: CFG19 (Bit 28) */ -#define CTIMER_OUTCFG1_CFG19_Msk (0x70000000UL) /*!< CTIMER OUTCFG1: CFG19 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG1_CFG18_Pos (25UL) /*!< CTIMER OUTCFG1: CFG18 (Bit 25) */ -#define CTIMER_OUTCFG1_CFG18_Msk (0xe000000UL) /*!< CTIMER OUTCFG1: CFG18 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG1_CFG17_Pos (22UL) /*!< CTIMER OUTCFG1: CFG17 (Bit 22) */ -#define CTIMER_OUTCFG1_CFG17_Msk (0x1c00000UL) /*!< CTIMER OUTCFG1: CFG17 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG1_CFG16_Pos (19UL) /*!< CTIMER OUTCFG1: CFG16 (Bit 19) */ -#define CTIMER_OUTCFG1_CFG16_Msk (0x380000UL) /*!< CTIMER OUTCFG1: CFG16 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG1_CFG15_Pos (16UL) /*!< CTIMER OUTCFG1: CFG15 (Bit 16) */ -#define CTIMER_OUTCFG1_CFG15_Msk (0x70000UL) /*!< CTIMER OUTCFG1: CFG15 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG1_CFG14_Pos (12UL) /*!< CTIMER OUTCFG1: CFG14 (Bit 12) */ -#define CTIMER_OUTCFG1_CFG14_Msk (0x7000UL) /*!< CTIMER OUTCFG1: CFG14 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG1_CFG13_Pos (9UL) /*!< CTIMER OUTCFG1: CFG13 (Bit 9) */ -#define CTIMER_OUTCFG1_CFG13_Msk (0xe00UL) /*!< CTIMER OUTCFG1: CFG13 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG1_CFG12_Pos (6UL) /*!< CTIMER OUTCFG1: CFG12 (Bit 6) */ -#define CTIMER_OUTCFG1_CFG12_Msk (0x1c0UL) /*!< CTIMER OUTCFG1: CFG12 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG1_CFG11_Pos (3UL) /*!< CTIMER OUTCFG1: CFG11 (Bit 3) */ -#define CTIMER_OUTCFG1_CFG11_Msk (0x38UL) /*!< CTIMER OUTCFG1: CFG11 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG1_CFG10_Pos (0UL) /*!< CTIMER OUTCFG1: CFG10 (Bit 0) */ -#define CTIMER_OUTCFG1_CFG10_Msk (0x7UL) /*!< CTIMER OUTCFG1: CFG10 (Bitfield-Mask: 0x07) */ -/* ======================================================== OUTCFG2 ======================================================== */ -#define CTIMER_OUTCFG2_CFG29_Pos (28UL) /*!< CTIMER OUTCFG2: CFG29 (Bit 28) */ -#define CTIMER_OUTCFG2_CFG29_Msk (0x70000000UL) /*!< CTIMER OUTCFG2: CFG29 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG2_CFG28_Pos (25UL) /*!< CTIMER OUTCFG2: CFG28 (Bit 25) */ -#define CTIMER_OUTCFG2_CFG28_Msk (0xe000000UL) /*!< CTIMER OUTCFG2: CFG28 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG2_CFG27_Pos (22UL) /*!< CTIMER OUTCFG2: CFG27 (Bit 22) */ -#define CTIMER_OUTCFG2_CFG27_Msk (0x1c00000UL) /*!< CTIMER OUTCFG2: CFG27 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG2_CFG26_Pos (19UL) /*!< CTIMER OUTCFG2: CFG26 (Bit 19) */ -#define CTIMER_OUTCFG2_CFG26_Msk (0x380000UL) /*!< CTIMER OUTCFG2: CFG26 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG2_CFG25_Pos (16UL) /*!< CTIMER OUTCFG2: CFG25 (Bit 16) */ -#define CTIMER_OUTCFG2_CFG25_Msk (0x70000UL) /*!< CTIMER OUTCFG2: CFG25 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG2_CFG24_Pos (12UL) /*!< CTIMER OUTCFG2: CFG24 (Bit 12) */ -#define CTIMER_OUTCFG2_CFG24_Msk (0x7000UL) /*!< CTIMER OUTCFG2: CFG24 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG2_CFG23_Pos (9UL) /*!< CTIMER OUTCFG2: CFG23 (Bit 9) */ -#define CTIMER_OUTCFG2_CFG23_Msk (0xe00UL) /*!< CTIMER OUTCFG2: CFG23 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG2_CFG22_Pos (6UL) /*!< CTIMER OUTCFG2: CFG22 (Bit 6) */ -#define CTIMER_OUTCFG2_CFG22_Msk (0x1c0UL) /*!< CTIMER OUTCFG2: CFG22 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG2_CFG21_Pos (3UL) /*!< CTIMER OUTCFG2: CFG21 (Bit 3) */ -#define CTIMER_OUTCFG2_CFG21_Msk (0x38UL) /*!< CTIMER OUTCFG2: CFG21 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG2_CFG20_Pos (0UL) /*!< CTIMER OUTCFG2: CFG20 (Bit 0) */ -#define CTIMER_OUTCFG2_CFG20_Msk (0x7UL) /*!< CTIMER OUTCFG2: CFG20 (Bitfield-Mask: 0x07) */ -/* ======================================================== OUTCFG3 ======================================================== */ -#define CTIMER_OUTCFG3_CFG31_Pos (3UL) /*!< CTIMER OUTCFG3: CFG31 (Bit 3) */ -#define CTIMER_OUTCFG3_CFG31_Msk (0x38UL) /*!< CTIMER OUTCFG3: CFG31 (Bitfield-Mask: 0x07) */ -#define CTIMER_OUTCFG3_CFG30_Pos (0UL) /*!< CTIMER OUTCFG3: CFG30 (Bit 0) */ -#define CTIMER_OUTCFG3_CFG30_Msk (0x7UL) /*!< CTIMER OUTCFG3: CFG30 (Bitfield-Mask: 0x07) */ -/* ========================================================= INCFG ========================================================= */ -#define CTIMER_INCFG_CFGB7_Pos (15UL) /*!< CTIMER INCFG: CFGB7 (Bit 15) */ -#define CTIMER_INCFG_CFGB7_Msk (0x8000UL) /*!< CTIMER INCFG: CFGB7 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGA7_Pos (14UL) /*!< CTIMER INCFG: CFGA7 (Bit 14) */ -#define CTIMER_INCFG_CFGA7_Msk (0x4000UL) /*!< CTIMER INCFG: CFGA7 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGB6_Pos (13UL) /*!< CTIMER INCFG: CFGB6 (Bit 13) */ -#define CTIMER_INCFG_CFGB6_Msk (0x2000UL) /*!< CTIMER INCFG: CFGB6 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGA6_Pos (12UL) /*!< CTIMER INCFG: CFGA6 (Bit 12) */ -#define CTIMER_INCFG_CFGA6_Msk (0x1000UL) /*!< CTIMER INCFG: CFGA6 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGB5_Pos (11UL) /*!< CTIMER INCFG: CFGB5 (Bit 11) */ -#define CTIMER_INCFG_CFGB5_Msk (0x800UL) /*!< CTIMER INCFG: CFGB5 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGA5_Pos (10UL) /*!< CTIMER INCFG: CFGA5 (Bit 10) */ -#define CTIMER_INCFG_CFGA5_Msk (0x400UL) /*!< CTIMER INCFG: CFGA5 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGB4_Pos (9UL) /*!< CTIMER INCFG: CFGB4 (Bit 9) */ -#define CTIMER_INCFG_CFGB4_Msk (0x200UL) /*!< CTIMER INCFG: CFGB4 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGA4_Pos (8UL) /*!< CTIMER INCFG: CFGA4 (Bit 8) */ -#define CTIMER_INCFG_CFGA4_Msk (0x100UL) /*!< CTIMER INCFG: CFGA4 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGB3_Pos (7UL) /*!< CTIMER INCFG: CFGB3 (Bit 7) */ -#define CTIMER_INCFG_CFGB3_Msk (0x80UL) /*!< CTIMER INCFG: CFGB3 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGA3_Pos (6UL) /*!< CTIMER INCFG: CFGA3 (Bit 6) */ -#define CTIMER_INCFG_CFGA3_Msk (0x40UL) /*!< CTIMER INCFG: CFGA3 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGB2_Pos (5UL) /*!< CTIMER INCFG: CFGB2 (Bit 5) */ -#define CTIMER_INCFG_CFGB2_Msk (0x20UL) /*!< CTIMER INCFG: CFGB2 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGA2_Pos (4UL) /*!< CTIMER INCFG: CFGA2 (Bit 4) */ -#define CTIMER_INCFG_CFGA2_Msk (0x10UL) /*!< CTIMER INCFG: CFGA2 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGB1_Pos (3UL) /*!< CTIMER INCFG: CFGB1 (Bit 3) */ -#define CTIMER_INCFG_CFGB1_Msk (0x8UL) /*!< CTIMER INCFG: CFGB1 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGA1_Pos (2UL) /*!< CTIMER INCFG: CFGA1 (Bit 2) */ -#define CTIMER_INCFG_CFGA1_Msk (0x4UL) /*!< CTIMER INCFG: CFGA1 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGB0_Pos (1UL) /*!< CTIMER INCFG: CFGB0 (Bit 1) */ -#define CTIMER_INCFG_CFGB0_Msk (0x2UL) /*!< CTIMER INCFG: CFGB0 (Bitfield-Mask: 0x01) */ -#define CTIMER_INCFG_CFGA0_Pos (0UL) /*!< CTIMER INCFG: CFGA0 (Bit 0) */ -#define CTIMER_INCFG_CFGA0_Msk (0x1UL) /*!< CTIMER INCFG: CFGA0 (Bitfield-Mask: 0x01) */ -/* ========================================================= STCFG ========================================================= */ -#define CTIMER_STCFG_FREEZE_Pos (31UL) /*!< CTIMER STCFG: FREEZE (Bit 31) */ -#define CTIMER_STCFG_FREEZE_Msk (0x80000000UL) /*!< CTIMER STCFG: FREEZE (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_CLEAR_Pos (30UL) /*!< CTIMER STCFG: CLEAR (Bit 30) */ -#define CTIMER_STCFG_CLEAR_Msk (0x40000000UL) /*!< CTIMER STCFG: CLEAR (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_COMPARE_H_EN_Pos (15UL) /*!< CTIMER STCFG: COMPARE_H_EN (Bit 15) */ -#define CTIMER_STCFG_COMPARE_H_EN_Msk (0x8000UL) /*!< CTIMER STCFG: COMPARE_H_EN (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_COMPARE_G_EN_Pos (14UL) /*!< CTIMER STCFG: COMPARE_G_EN (Bit 14) */ -#define CTIMER_STCFG_COMPARE_G_EN_Msk (0x4000UL) /*!< CTIMER STCFG: COMPARE_G_EN (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_COMPARE_F_EN_Pos (13UL) /*!< CTIMER STCFG: COMPARE_F_EN (Bit 13) */ -#define CTIMER_STCFG_COMPARE_F_EN_Msk (0x2000UL) /*!< CTIMER STCFG: COMPARE_F_EN (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_COMPARE_E_EN_Pos (12UL) /*!< CTIMER STCFG: COMPARE_E_EN (Bit 12) */ -#define CTIMER_STCFG_COMPARE_E_EN_Msk (0x1000UL) /*!< CTIMER STCFG: COMPARE_E_EN (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_COMPARE_D_EN_Pos (11UL) /*!< CTIMER STCFG: COMPARE_D_EN (Bit 11) */ -#define CTIMER_STCFG_COMPARE_D_EN_Msk (0x800UL) /*!< CTIMER STCFG: COMPARE_D_EN (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_COMPARE_C_EN_Pos (10UL) /*!< CTIMER STCFG: COMPARE_C_EN (Bit 10) */ -#define CTIMER_STCFG_COMPARE_C_EN_Msk (0x400UL) /*!< CTIMER STCFG: COMPARE_C_EN (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_COMPARE_B_EN_Pos (9UL) /*!< CTIMER STCFG: COMPARE_B_EN (Bit 9) */ -#define CTIMER_STCFG_COMPARE_B_EN_Msk (0x200UL) /*!< CTIMER STCFG: COMPARE_B_EN (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_COMPARE_A_EN_Pos (8UL) /*!< CTIMER STCFG: COMPARE_A_EN (Bit 8) */ -#define CTIMER_STCFG_COMPARE_A_EN_Msk (0x100UL) /*!< CTIMER STCFG: COMPARE_A_EN (Bitfield-Mask: 0x01) */ -#define CTIMER_STCFG_CLKSEL_Pos (0UL) /*!< CTIMER STCFG: CLKSEL (Bit 0) */ -#define CTIMER_STCFG_CLKSEL_Msk (0xfUL) /*!< CTIMER STCFG: CLKSEL (Bitfield-Mask: 0x0f) */ -/* ========================================================= STTMR ========================================================= */ -#define CTIMER_STTMR_STTMR_Pos (0UL) /*!< CTIMER STTMR: STTMR (Bit 0) */ -#define CTIMER_STTMR_STTMR_Msk (0xffffffffUL) /*!< CTIMER STTMR: STTMR (Bitfield-Mask: 0xffffffff) */ -/* ==================================================== CAPTURECONTROL ===================================================== */ -#define CTIMER_CAPTURECONTROL_CAPTURE3_Pos (3UL) /*!< CTIMER CAPTURECONTROL: CAPTURE3 (Bit 3) */ -#define CTIMER_CAPTURECONTROL_CAPTURE3_Msk (0x8UL) /*!< CTIMER CAPTURECONTROL: CAPTURE3 (Bitfield-Mask: 0x01) */ -#define CTIMER_CAPTURECONTROL_CAPTURE2_Pos (2UL) /*!< CTIMER CAPTURECONTROL: CAPTURE2 (Bit 2) */ -#define CTIMER_CAPTURECONTROL_CAPTURE2_Msk (0x4UL) /*!< CTIMER CAPTURECONTROL: CAPTURE2 (Bitfield-Mask: 0x01) */ -#define CTIMER_CAPTURECONTROL_CAPTURE1_Pos (1UL) /*!< CTIMER CAPTURECONTROL: CAPTURE1 (Bit 1) */ -#define CTIMER_CAPTURECONTROL_CAPTURE1_Msk (0x2UL) /*!< CTIMER CAPTURECONTROL: CAPTURE1 (Bitfield-Mask: 0x01) */ -#define CTIMER_CAPTURECONTROL_CAPTURE0_Pos (0UL) /*!< CTIMER CAPTURECONTROL: CAPTURE0 (Bit 0) */ -#define CTIMER_CAPTURECONTROL_CAPTURE0_Msk (0x1UL) /*!< CTIMER CAPTURECONTROL: CAPTURE0 (Bitfield-Mask: 0x01) */ -/* ======================================================== SCMPR0 ========================================================= */ -#define CTIMER_SCMPR0_SCMPR0_Pos (0UL) /*!< CTIMER SCMPR0: SCMPR0 (Bit 0) */ -#define CTIMER_SCMPR0_SCMPR0_Msk (0xffffffffUL) /*!< CTIMER SCMPR0: SCMPR0 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCMPR1 ========================================================= */ -#define CTIMER_SCMPR1_SCMPR1_Pos (0UL) /*!< CTIMER SCMPR1: SCMPR1 (Bit 0) */ -#define CTIMER_SCMPR1_SCMPR1_Msk (0xffffffffUL) /*!< CTIMER SCMPR1: SCMPR1 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCMPR2 ========================================================= */ -#define CTIMER_SCMPR2_SCMPR2_Pos (0UL) /*!< CTIMER SCMPR2: SCMPR2 (Bit 0) */ -#define CTIMER_SCMPR2_SCMPR2_Msk (0xffffffffUL) /*!< CTIMER SCMPR2: SCMPR2 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCMPR3 ========================================================= */ -#define CTIMER_SCMPR3_SCMPR3_Pos (0UL) /*!< CTIMER SCMPR3: SCMPR3 (Bit 0) */ -#define CTIMER_SCMPR3_SCMPR3_Msk (0xffffffffUL) /*!< CTIMER SCMPR3: SCMPR3 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCMPR4 ========================================================= */ -#define CTIMER_SCMPR4_SCMPR4_Pos (0UL) /*!< CTIMER SCMPR4: SCMPR4 (Bit 0) */ -#define CTIMER_SCMPR4_SCMPR4_Msk (0xffffffffUL) /*!< CTIMER SCMPR4: SCMPR4 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCMPR5 ========================================================= */ -#define CTIMER_SCMPR5_SCMPR5_Pos (0UL) /*!< CTIMER SCMPR5: SCMPR5 (Bit 0) */ -#define CTIMER_SCMPR5_SCMPR5_Msk (0xffffffffUL) /*!< CTIMER SCMPR5: SCMPR5 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCMPR6 ========================================================= */ -#define CTIMER_SCMPR6_SCMPR6_Pos (0UL) /*!< CTIMER SCMPR6: SCMPR6 (Bit 0) */ -#define CTIMER_SCMPR6_SCMPR6_Msk (0xffffffffUL) /*!< CTIMER SCMPR6: SCMPR6 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCMPR7 ========================================================= */ -#define CTIMER_SCMPR7_SCMPR7_Pos (0UL) /*!< CTIMER SCMPR7: SCMPR7 (Bit 0) */ -#define CTIMER_SCMPR7_SCMPR7_Msk (0xffffffffUL) /*!< CTIMER SCMPR7: SCMPR7 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCAPT0 ========================================================= */ -#define CTIMER_SCAPT0_SCAPT0_Pos (0UL) /*!< CTIMER SCAPT0: SCAPT0 (Bit 0) */ -#define CTIMER_SCAPT0_SCAPT0_Msk (0xffffffffUL) /*!< CTIMER SCAPT0: SCAPT0 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCAPT1 ========================================================= */ -#define CTIMER_SCAPT1_SCAPT1_Pos (0UL) /*!< CTIMER SCAPT1: SCAPT1 (Bit 0) */ -#define CTIMER_SCAPT1_SCAPT1_Msk (0xffffffffUL) /*!< CTIMER SCAPT1: SCAPT1 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCAPT2 ========================================================= */ -#define CTIMER_SCAPT2_SCAPT2_Pos (0UL) /*!< CTIMER SCAPT2: SCAPT2 (Bit 0) */ -#define CTIMER_SCAPT2_SCAPT2_Msk (0xffffffffUL) /*!< CTIMER SCAPT2: SCAPT2 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== SCAPT3 ========================================================= */ -#define CTIMER_SCAPT3_SCAPT3_Pos (0UL) /*!< CTIMER SCAPT3: SCAPT3 (Bit 0) */ -#define CTIMER_SCAPT3_SCAPT3_Msk (0xffffffffUL) /*!< CTIMER SCAPT3: SCAPT3 (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= SNVR0 ========================================================= */ -#define CTIMER_SNVR0_SNVR0_Pos (0UL) /*!< CTIMER SNVR0: SNVR0 (Bit 0) */ -#define CTIMER_SNVR0_SNVR0_Msk (0xffffffffUL) /*!< CTIMER SNVR0: SNVR0 (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= SNVR1 ========================================================= */ -#define CTIMER_SNVR1_SNVR1_Pos (0UL) /*!< CTIMER SNVR1: SNVR1 (Bit 0) */ -#define CTIMER_SNVR1_SNVR1_Msk (0xffffffffUL) /*!< CTIMER SNVR1: SNVR1 (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= SNVR2 ========================================================= */ -#define CTIMER_SNVR2_SNVR2_Pos (0UL) /*!< CTIMER SNVR2: SNVR2 (Bit 0) */ -#define CTIMER_SNVR2_SNVR2_Msk (0xffffffffUL) /*!< CTIMER SNVR2: SNVR2 (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= SNVR3 ========================================================= */ -#define CTIMER_SNVR3_SNVR3_Pos (0UL) /*!< CTIMER SNVR3: SNVR3 (Bit 0) */ -#define CTIMER_SNVR3_SNVR3_Msk (0xffffffffUL) /*!< CTIMER SNVR3: SNVR3 (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= INTEN ========================================================= */ -#define CTIMER_INTEN_CTMRB7C1INT_Pos (31UL) /*!< CTIMER INTEN: CTMRB7C1INT (Bit 31) */ -#define CTIMER_INTEN_CTMRB7C1INT_Msk (0x80000000UL) /*!< CTIMER INTEN: CTMRB7C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA7C1INT_Pos (30UL) /*!< CTIMER INTEN: CTMRA7C1INT (Bit 30) */ -#define CTIMER_INTEN_CTMRA7C1INT_Msk (0x40000000UL) /*!< CTIMER INTEN: CTMRA7C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB6C1INT_Pos (29UL) /*!< CTIMER INTEN: CTMRB6C1INT (Bit 29) */ -#define CTIMER_INTEN_CTMRB6C1INT_Msk (0x20000000UL) /*!< CTIMER INTEN: CTMRB6C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA6C1INT_Pos (28UL) /*!< CTIMER INTEN: CTMRA6C1INT (Bit 28) */ -#define CTIMER_INTEN_CTMRA6C1INT_Msk (0x10000000UL) /*!< CTIMER INTEN: CTMRA6C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB5C1INT_Pos (27UL) /*!< CTIMER INTEN: CTMRB5C1INT (Bit 27) */ -#define CTIMER_INTEN_CTMRB5C1INT_Msk (0x8000000UL) /*!< CTIMER INTEN: CTMRB5C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA5C1INT_Pos (26UL) /*!< CTIMER INTEN: CTMRA5C1INT (Bit 26) */ -#define CTIMER_INTEN_CTMRA5C1INT_Msk (0x4000000UL) /*!< CTIMER INTEN: CTMRA5C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB4C1INT_Pos (25UL) /*!< CTIMER INTEN: CTMRB4C1INT (Bit 25) */ -#define CTIMER_INTEN_CTMRB4C1INT_Msk (0x2000000UL) /*!< CTIMER INTEN: CTMRB4C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA4C1INT_Pos (24UL) /*!< CTIMER INTEN: CTMRA4C1INT (Bit 24) */ -#define CTIMER_INTEN_CTMRA4C1INT_Msk (0x1000000UL) /*!< CTIMER INTEN: CTMRA4C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB3C1INT_Pos (23UL) /*!< CTIMER INTEN: CTMRB3C1INT (Bit 23) */ -#define CTIMER_INTEN_CTMRB3C1INT_Msk (0x800000UL) /*!< CTIMER INTEN: CTMRB3C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA3C1INT_Pos (22UL) /*!< CTIMER INTEN: CTMRA3C1INT (Bit 22) */ -#define CTIMER_INTEN_CTMRA3C1INT_Msk (0x400000UL) /*!< CTIMER INTEN: CTMRA3C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB2C1INT_Pos (21UL) /*!< CTIMER INTEN: CTMRB2C1INT (Bit 21) */ -#define CTIMER_INTEN_CTMRB2C1INT_Msk (0x200000UL) /*!< CTIMER INTEN: CTMRB2C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA2C1INT_Pos (20UL) /*!< CTIMER INTEN: CTMRA2C1INT (Bit 20) */ -#define CTIMER_INTEN_CTMRA2C1INT_Msk (0x100000UL) /*!< CTIMER INTEN: CTMRA2C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB1C1INT_Pos (19UL) /*!< CTIMER INTEN: CTMRB1C1INT (Bit 19) */ -#define CTIMER_INTEN_CTMRB1C1INT_Msk (0x80000UL) /*!< CTIMER INTEN: CTMRB1C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA1C1INT_Pos (18UL) /*!< CTIMER INTEN: CTMRA1C1INT (Bit 18) */ -#define CTIMER_INTEN_CTMRA1C1INT_Msk (0x40000UL) /*!< CTIMER INTEN: CTMRA1C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB0C1INT_Pos (17UL) /*!< CTIMER INTEN: CTMRB0C1INT (Bit 17) */ -#define CTIMER_INTEN_CTMRB0C1INT_Msk (0x20000UL) /*!< CTIMER INTEN: CTMRB0C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA0C1INT_Pos (16UL) /*!< CTIMER INTEN: CTMRA0C1INT (Bit 16) */ -#define CTIMER_INTEN_CTMRA0C1INT_Msk (0x10000UL) /*!< CTIMER INTEN: CTMRA0C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB7C0INT_Pos (15UL) /*!< CTIMER INTEN: CTMRB7C0INT (Bit 15) */ -#define CTIMER_INTEN_CTMRB7C0INT_Msk (0x8000UL) /*!< CTIMER INTEN: CTMRB7C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA7C0INT_Pos (14UL) /*!< CTIMER INTEN: CTMRA7C0INT (Bit 14) */ -#define CTIMER_INTEN_CTMRA7C0INT_Msk (0x4000UL) /*!< CTIMER INTEN: CTMRA7C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB6C0INT_Pos (13UL) /*!< CTIMER INTEN: CTMRB6C0INT (Bit 13) */ -#define CTIMER_INTEN_CTMRB6C0INT_Msk (0x2000UL) /*!< CTIMER INTEN: CTMRB6C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA6C0INT_Pos (12UL) /*!< CTIMER INTEN: CTMRA6C0INT (Bit 12) */ -#define CTIMER_INTEN_CTMRA6C0INT_Msk (0x1000UL) /*!< CTIMER INTEN: CTMRA6C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB5C0INT_Pos (11UL) /*!< CTIMER INTEN: CTMRB5C0INT (Bit 11) */ -#define CTIMER_INTEN_CTMRB5C0INT_Msk (0x800UL) /*!< CTIMER INTEN: CTMRB5C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA5C0INT_Pos (10UL) /*!< CTIMER INTEN: CTMRA5C0INT (Bit 10) */ -#define CTIMER_INTEN_CTMRA5C0INT_Msk (0x400UL) /*!< CTIMER INTEN: CTMRA5C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB4C0INT_Pos (9UL) /*!< CTIMER INTEN: CTMRB4C0INT (Bit 9) */ -#define CTIMER_INTEN_CTMRB4C0INT_Msk (0x200UL) /*!< CTIMER INTEN: CTMRB4C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA4C0INT_Pos (8UL) /*!< CTIMER INTEN: CTMRA4C0INT (Bit 8) */ -#define CTIMER_INTEN_CTMRA4C0INT_Msk (0x100UL) /*!< CTIMER INTEN: CTMRA4C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB3C0INT_Pos (7UL) /*!< CTIMER INTEN: CTMRB3C0INT (Bit 7) */ -#define CTIMER_INTEN_CTMRB3C0INT_Msk (0x80UL) /*!< CTIMER INTEN: CTMRB3C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA3C0INT_Pos (6UL) /*!< CTIMER INTEN: CTMRA3C0INT (Bit 6) */ -#define CTIMER_INTEN_CTMRA3C0INT_Msk (0x40UL) /*!< CTIMER INTEN: CTMRA3C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB2C0INT_Pos (5UL) /*!< CTIMER INTEN: CTMRB2C0INT (Bit 5) */ -#define CTIMER_INTEN_CTMRB2C0INT_Msk (0x20UL) /*!< CTIMER INTEN: CTMRB2C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA2C0INT_Pos (4UL) /*!< CTIMER INTEN: CTMRA2C0INT (Bit 4) */ -#define CTIMER_INTEN_CTMRA2C0INT_Msk (0x10UL) /*!< CTIMER INTEN: CTMRA2C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB1C0INT_Pos (3UL) /*!< CTIMER INTEN: CTMRB1C0INT (Bit 3) */ -#define CTIMER_INTEN_CTMRB1C0INT_Msk (0x8UL) /*!< CTIMER INTEN: CTMRB1C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA1C0INT_Pos (2UL) /*!< CTIMER INTEN: CTMRA1C0INT (Bit 2) */ -#define CTIMER_INTEN_CTMRA1C0INT_Msk (0x4UL) /*!< CTIMER INTEN: CTMRA1C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRB0C0INT_Pos (1UL) /*!< CTIMER INTEN: CTMRB0C0INT (Bit 1) */ -#define CTIMER_INTEN_CTMRB0C0INT_Msk (0x2UL) /*!< CTIMER INTEN: CTMRB0C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTEN_CTMRA0C0INT_Pos (0UL) /*!< CTIMER INTEN: CTMRA0C0INT (Bit 0) */ -#define CTIMER_INTEN_CTMRA0C0INT_Msk (0x1UL) /*!< CTIMER INTEN: CTMRA0C0INT (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define CTIMER_INTSTAT_CTMRB7C1INT_Pos (31UL) /*!< CTIMER INTSTAT: CTMRB7C1INT (Bit 31) */ -#define CTIMER_INTSTAT_CTMRB7C1INT_Msk (0x80000000UL) /*!< CTIMER INTSTAT: CTMRB7C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA7C1INT_Pos (30UL) /*!< CTIMER INTSTAT: CTMRA7C1INT (Bit 30) */ -#define CTIMER_INTSTAT_CTMRA7C1INT_Msk (0x40000000UL) /*!< CTIMER INTSTAT: CTMRA7C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB6C1INT_Pos (29UL) /*!< CTIMER INTSTAT: CTMRB6C1INT (Bit 29) */ -#define CTIMER_INTSTAT_CTMRB6C1INT_Msk (0x20000000UL) /*!< CTIMER INTSTAT: CTMRB6C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA6C1INT_Pos (28UL) /*!< CTIMER INTSTAT: CTMRA6C1INT (Bit 28) */ -#define CTIMER_INTSTAT_CTMRA6C1INT_Msk (0x10000000UL) /*!< CTIMER INTSTAT: CTMRA6C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB5C1INT_Pos (27UL) /*!< CTIMER INTSTAT: CTMRB5C1INT (Bit 27) */ -#define CTIMER_INTSTAT_CTMRB5C1INT_Msk (0x8000000UL) /*!< CTIMER INTSTAT: CTMRB5C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA5C1INT_Pos (26UL) /*!< CTIMER INTSTAT: CTMRA5C1INT (Bit 26) */ -#define CTIMER_INTSTAT_CTMRA5C1INT_Msk (0x4000000UL) /*!< CTIMER INTSTAT: CTMRA5C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB4C1INT_Pos (25UL) /*!< CTIMER INTSTAT: CTMRB4C1INT (Bit 25) */ -#define CTIMER_INTSTAT_CTMRB4C1INT_Msk (0x2000000UL) /*!< CTIMER INTSTAT: CTMRB4C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA4C1INT_Pos (24UL) /*!< CTIMER INTSTAT: CTMRA4C1INT (Bit 24) */ -#define CTIMER_INTSTAT_CTMRA4C1INT_Msk (0x1000000UL) /*!< CTIMER INTSTAT: CTMRA4C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB3C1INT_Pos (23UL) /*!< CTIMER INTSTAT: CTMRB3C1INT (Bit 23) */ -#define CTIMER_INTSTAT_CTMRB3C1INT_Msk (0x800000UL) /*!< CTIMER INTSTAT: CTMRB3C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA3C1INT_Pos (22UL) /*!< CTIMER INTSTAT: CTMRA3C1INT (Bit 22) */ -#define CTIMER_INTSTAT_CTMRA3C1INT_Msk (0x400000UL) /*!< CTIMER INTSTAT: CTMRA3C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB2C1INT_Pos (21UL) /*!< CTIMER INTSTAT: CTMRB2C1INT (Bit 21) */ -#define CTIMER_INTSTAT_CTMRB2C1INT_Msk (0x200000UL) /*!< CTIMER INTSTAT: CTMRB2C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA2C1INT_Pos (20UL) /*!< CTIMER INTSTAT: CTMRA2C1INT (Bit 20) */ -#define CTIMER_INTSTAT_CTMRA2C1INT_Msk (0x100000UL) /*!< CTIMER INTSTAT: CTMRA2C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB1C1INT_Pos (19UL) /*!< CTIMER INTSTAT: CTMRB1C1INT (Bit 19) */ -#define CTIMER_INTSTAT_CTMRB1C1INT_Msk (0x80000UL) /*!< CTIMER INTSTAT: CTMRB1C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA1C1INT_Pos (18UL) /*!< CTIMER INTSTAT: CTMRA1C1INT (Bit 18) */ -#define CTIMER_INTSTAT_CTMRA1C1INT_Msk (0x40000UL) /*!< CTIMER INTSTAT: CTMRA1C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB0C1INT_Pos (17UL) /*!< CTIMER INTSTAT: CTMRB0C1INT (Bit 17) */ -#define CTIMER_INTSTAT_CTMRB0C1INT_Msk (0x20000UL) /*!< CTIMER INTSTAT: CTMRB0C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA0C1INT_Pos (16UL) /*!< CTIMER INTSTAT: CTMRA0C1INT (Bit 16) */ -#define CTIMER_INTSTAT_CTMRA0C1INT_Msk (0x10000UL) /*!< CTIMER INTSTAT: CTMRA0C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB7C0INT_Pos (15UL) /*!< CTIMER INTSTAT: CTMRB7C0INT (Bit 15) */ -#define CTIMER_INTSTAT_CTMRB7C0INT_Msk (0x8000UL) /*!< CTIMER INTSTAT: CTMRB7C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA7C0INT_Pos (14UL) /*!< CTIMER INTSTAT: CTMRA7C0INT (Bit 14) */ -#define CTIMER_INTSTAT_CTMRA7C0INT_Msk (0x4000UL) /*!< CTIMER INTSTAT: CTMRA7C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB6C0INT_Pos (13UL) /*!< CTIMER INTSTAT: CTMRB6C0INT (Bit 13) */ -#define CTIMER_INTSTAT_CTMRB6C0INT_Msk (0x2000UL) /*!< CTIMER INTSTAT: CTMRB6C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA6C0INT_Pos (12UL) /*!< CTIMER INTSTAT: CTMRA6C0INT (Bit 12) */ -#define CTIMER_INTSTAT_CTMRA6C0INT_Msk (0x1000UL) /*!< CTIMER INTSTAT: CTMRA6C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB5C0INT_Pos (11UL) /*!< CTIMER INTSTAT: CTMRB5C0INT (Bit 11) */ -#define CTIMER_INTSTAT_CTMRB5C0INT_Msk (0x800UL) /*!< CTIMER INTSTAT: CTMRB5C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA5C0INT_Pos (10UL) /*!< CTIMER INTSTAT: CTMRA5C0INT (Bit 10) */ -#define CTIMER_INTSTAT_CTMRA5C0INT_Msk (0x400UL) /*!< CTIMER INTSTAT: CTMRA5C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB4C0INT_Pos (9UL) /*!< CTIMER INTSTAT: CTMRB4C0INT (Bit 9) */ -#define CTIMER_INTSTAT_CTMRB4C0INT_Msk (0x200UL) /*!< CTIMER INTSTAT: CTMRB4C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA4C0INT_Pos (8UL) /*!< CTIMER INTSTAT: CTMRA4C0INT (Bit 8) */ -#define CTIMER_INTSTAT_CTMRA4C0INT_Msk (0x100UL) /*!< CTIMER INTSTAT: CTMRA4C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB3C0INT_Pos (7UL) /*!< CTIMER INTSTAT: CTMRB3C0INT (Bit 7) */ -#define CTIMER_INTSTAT_CTMRB3C0INT_Msk (0x80UL) /*!< CTIMER INTSTAT: CTMRB3C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA3C0INT_Pos (6UL) /*!< CTIMER INTSTAT: CTMRA3C0INT (Bit 6) */ -#define CTIMER_INTSTAT_CTMRA3C0INT_Msk (0x40UL) /*!< CTIMER INTSTAT: CTMRA3C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB2C0INT_Pos (5UL) /*!< CTIMER INTSTAT: CTMRB2C0INT (Bit 5) */ -#define CTIMER_INTSTAT_CTMRB2C0INT_Msk (0x20UL) /*!< CTIMER INTSTAT: CTMRB2C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA2C0INT_Pos (4UL) /*!< CTIMER INTSTAT: CTMRA2C0INT (Bit 4) */ -#define CTIMER_INTSTAT_CTMRA2C0INT_Msk (0x10UL) /*!< CTIMER INTSTAT: CTMRA2C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB1C0INT_Pos (3UL) /*!< CTIMER INTSTAT: CTMRB1C0INT (Bit 3) */ -#define CTIMER_INTSTAT_CTMRB1C0INT_Msk (0x8UL) /*!< CTIMER INTSTAT: CTMRB1C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA1C0INT_Pos (2UL) /*!< CTIMER INTSTAT: CTMRA1C0INT (Bit 2) */ -#define CTIMER_INTSTAT_CTMRA1C0INT_Msk (0x4UL) /*!< CTIMER INTSTAT: CTMRA1C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRB0C0INT_Pos (1UL) /*!< CTIMER INTSTAT: CTMRB0C0INT (Bit 1) */ -#define CTIMER_INTSTAT_CTMRB0C0INT_Msk (0x2UL) /*!< CTIMER INTSTAT: CTMRB0C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSTAT_CTMRA0C0INT_Pos (0UL) /*!< CTIMER INTSTAT: CTMRA0C0INT (Bit 0) */ -#define CTIMER_INTSTAT_CTMRA0C0INT_Msk (0x1UL) /*!< CTIMER INTSTAT: CTMRA0C0INT (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define CTIMER_INTCLR_CTMRB7C1INT_Pos (31UL) /*!< CTIMER INTCLR: CTMRB7C1INT (Bit 31) */ -#define CTIMER_INTCLR_CTMRB7C1INT_Msk (0x80000000UL) /*!< CTIMER INTCLR: CTMRB7C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA7C1INT_Pos (30UL) /*!< CTIMER INTCLR: CTMRA7C1INT (Bit 30) */ -#define CTIMER_INTCLR_CTMRA7C1INT_Msk (0x40000000UL) /*!< CTIMER INTCLR: CTMRA7C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB6C1INT_Pos (29UL) /*!< CTIMER INTCLR: CTMRB6C1INT (Bit 29) */ -#define CTIMER_INTCLR_CTMRB6C1INT_Msk (0x20000000UL) /*!< CTIMER INTCLR: CTMRB6C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA6C1INT_Pos (28UL) /*!< CTIMER INTCLR: CTMRA6C1INT (Bit 28) */ -#define CTIMER_INTCLR_CTMRA6C1INT_Msk (0x10000000UL) /*!< CTIMER INTCLR: CTMRA6C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB5C1INT_Pos (27UL) /*!< CTIMER INTCLR: CTMRB5C1INT (Bit 27) */ -#define CTIMER_INTCLR_CTMRB5C1INT_Msk (0x8000000UL) /*!< CTIMER INTCLR: CTMRB5C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA5C1INT_Pos (26UL) /*!< CTIMER INTCLR: CTMRA5C1INT (Bit 26) */ -#define CTIMER_INTCLR_CTMRA5C1INT_Msk (0x4000000UL) /*!< CTIMER INTCLR: CTMRA5C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB4C1INT_Pos (25UL) /*!< CTIMER INTCLR: CTMRB4C1INT (Bit 25) */ -#define CTIMER_INTCLR_CTMRB4C1INT_Msk (0x2000000UL) /*!< CTIMER INTCLR: CTMRB4C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA4C1INT_Pos (24UL) /*!< CTIMER INTCLR: CTMRA4C1INT (Bit 24) */ -#define CTIMER_INTCLR_CTMRA4C1INT_Msk (0x1000000UL) /*!< CTIMER INTCLR: CTMRA4C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB3C1INT_Pos (23UL) /*!< CTIMER INTCLR: CTMRB3C1INT (Bit 23) */ -#define CTIMER_INTCLR_CTMRB3C1INT_Msk (0x800000UL) /*!< CTIMER INTCLR: CTMRB3C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA3C1INT_Pos (22UL) /*!< CTIMER INTCLR: CTMRA3C1INT (Bit 22) */ -#define CTIMER_INTCLR_CTMRA3C1INT_Msk (0x400000UL) /*!< CTIMER INTCLR: CTMRA3C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB2C1INT_Pos (21UL) /*!< CTIMER INTCLR: CTMRB2C1INT (Bit 21) */ -#define CTIMER_INTCLR_CTMRB2C1INT_Msk (0x200000UL) /*!< CTIMER INTCLR: CTMRB2C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA2C1INT_Pos (20UL) /*!< CTIMER INTCLR: CTMRA2C1INT (Bit 20) */ -#define CTIMER_INTCLR_CTMRA2C1INT_Msk (0x100000UL) /*!< CTIMER INTCLR: CTMRA2C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB1C1INT_Pos (19UL) /*!< CTIMER INTCLR: CTMRB1C1INT (Bit 19) */ -#define CTIMER_INTCLR_CTMRB1C1INT_Msk (0x80000UL) /*!< CTIMER INTCLR: CTMRB1C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA1C1INT_Pos (18UL) /*!< CTIMER INTCLR: CTMRA1C1INT (Bit 18) */ -#define CTIMER_INTCLR_CTMRA1C1INT_Msk (0x40000UL) /*!< CTIMER INTCLR: CTMRA1C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB0C1INT_Pos (17UL) /*!< CTIMER INTCLR: CTMRB0C1INT (Bit 17) */ -#define CTIMER_INTCLR_CTMRB0C1INT_Msk (0x20000UL) /*!< CTIMER INTCLR: CTMRB0C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA0C1INT_Pos (16UL) /*!< CTIMER INTCLR: CTMRA0C1INT (Bit 16) */ -#define CTIMER_INTCLR_CTMRA0C1INT_Msk (0x10000UL) /*!< CTIMER INTCLR: CTMRA0C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB7C0INT_Pos (15UL) /*!< CTIMER INTCLR: CTMRB7C0INT (Bit 15) */ -#define CTIMER_INTCLR_CTMRB7C0INT_Msk (0x8000UL) /*!< CTIMER INTCLR: CTMRB7C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA7C0INT_Pos (14UL) /*!< CTIMER INTCLR: CTMRA7C0INT (Bit 14) */ -#define CTIMER_INTCLR_CTMRA7C0INT_Msk (0x4000UL) /*!< CTIMER INTCLR: CTMRA7C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB6C0INT_Pos (13UL) /*!< CTIMER INTCLR: CTMRB6C0INT (Bit 13) */ -#define CTIMER_INTCLR_CTMRB6C0INT_Msk (0x2000UL) /*!< CTIMER INTCLR: CTMRB6C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA6C0INT_Pos (12UL) /*!< CTIMER INTCLR: CTMRA6C0INT (Bit 12) */ -#define CTIMER_INTCLR_CTMRA6C0INT_Msk (0x1000UL) /*!< CTIMER INTCLR: CTMRA6C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB5C0INT_Pos (11UL) /*!< CTIMER INTCLR: CTMRB5C0INT (Bit 11) */ -#define CTIMER_INTCLR_CTMRB5C0INT_Msk (0x800UL) /*!< CTIMER INTCLR: CTMRB5C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA5C0INT_Pos (10UL) /*!< CTIMER INTCLR: CTMRA5C0INT (Bit 10) */ -#define CTIMER_INTCLR_CTMRA5C0INT_Msk (0x400UL) /*!< CTIMER INTCLR: CTMRA5C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB4C0INT_Pos (9UL) /*!< CTIMER INTCLR: CTMRB4C0INT (Bit 9) */ -#define CTIMER_INTCLR_CTMRB4C0INT_Msk (0x200UL) /*!< CTIMER INTCLR: CTMRB4C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA4C0INT_Pos (8UL) /*!< CTIMER INTCLR: CTMRA4C0INT (Bit 8) */ -#define CTIMER_INTCLR_CTMRA4C0INT_Msk (0x100UL) /*!< CTIMER INTCLR: CTMRA4C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB3C0INT_Pos (7UL) /*!< CTIMER INTCLR: CTMRB3C0INT (Bit 7) */ -#define CTIMER_INTCLR_CTMRB3C0INT_Msk (0x80UL) /*!< CTIMER INTCLR: CTMRB3C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA3C0INT_Pos (6UL) /*!< CTIMER INTCLR: CTMRA3C0INT (Bit 6) */ -#define CTIMER_INTCLR_CTMRA3C0INT_Msk (0x40UL) /*!< CTIMER INTCLR: CTMRA3C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB2C0INT_Pos (5UL) /*!< CTIMER INTCLR: CTMRB2C0INT (Bit 5) */ -#define CTIMER_INTCLR_CTMRB2C0INT_Msk (0x20UL) /*!< CTIMER INTCLR: CTMRB2C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA2C0INT_Pos (4UL) /*!< CTIMER INTCLR: CTMRA2C0INT (Bit 4) */ -#define CTIMER_INTCLR_CTMRA2C0INT_Msk (0x10UL) /*!< CTIMER INTCLR: CTMRA2C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB1C0INT_Pos (3UL) /*!< CTIMER INTCLR: CTMRB1C0INT (Bit 3) */ -#define CTIMER_INTCLR_CTMRB1C0INT_Msk (0x8UL) /*!< CTIMER INTCLR: CTMRB1C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA1C0INT_Pos (2UL) /*!< CTIMER INTCLR: CTMRA1C0INT (Bit 2) */ -#define CTIMER_INTCLR_CTMRA1C0INT_Msk (0x4UL) /*!< CTIMER INTCLR: CTMRA1C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRB0C0INT_Pos (1UL) /*!< CTIMER INTCLR: CTMRB0C0INT (Bit 1) */ -#define CTIMER_INTCLR_CTMRB0C0INT_Msk (0x2UL) /*!< CTIMER INTCLR: CTMRB0C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTCLR_CTMRA0C0INT_Pos (0UL) /*!< CTIMER INTCLR: CTMRA0C0INT (Bit 0) */ -#define CTIMER_INTCLR_CTMRA0C0INT_Msk (0x1UL) /*!< CTIMER INTCLR: CTMRA0C0INT (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define CTIMER_INTSET_CTMRB7C1INT_Pos (31UL) /*!< CTIMER INTSET: CTMRB7C1INT (Bit 31) */ -#define CTIMER_INTSET_CTMRB7C1INT_Msk (0x80000000UL) /*!< CTIMER INTSET: CTMRB7C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA7C1INT_Pos (30UL) /*!< CTIMER INTSET: CTMRA7C1INT (Bit 30) */ -#define CTIMER_INTSET_CTMRA7C1INT_Msk (0x40000000UL) /*!< CTIMER INTSET: CTMRA7C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB6C1INT_Pos (29UL) /*!< CTIMER INTSET: CTMRB6C1INT (Bit 29) */ -#define CTIMER_INTSET_CTMRB6C1INT_Msk (0x20000000UL) /*!< CTIMER INTSET: CTMRB6C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA6C1INT_Pos (28UL) /*!< CTIMER INTSET: CTMRA6C1INT (Bit 28) */ -#define CTIMER_INTSET_CTMRA6C1INT_Msk (0x10000000UL) /*!< CTIMER INTSET: CTMRA6C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB5C1INT_Pos (27UL) /*!< CTIMER INTSET: CTMRB5C1INT (Bit 27) */ -#define CTIMER_INTSET_CTMRB5C1INT_Msk (0x8000000UL) /*!< CTIMER INTSET: CTMRB5C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA5C1INT_Pos (26UL) /*!< CTIMER INTSET: CTMRA5C1INT (Bit 26) */ -#define CTIMER_INTSET_CTMRA5C1INT_Msk (0x4000000UL) /*!< CTIMER INTSET: CTMRA5C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB4C1INT_Pos (25UL) /*!< CTIMER INTSET: CTMRB4C1INT (Bit 25) */ -#define CTIMER_INTSET_CTMRB4C1INT_Msk (0x2000000UL) /*!< CTIMER INTSET: CTMRB4C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA4C1INT_Pos (24UL) /*!< CTIMER INTSET: CTMRA4C1INT (Bit 24) */ -#define CTIMER_INTSET_CTMRA4C1INT_Msk (0x1000000UL) /*!< CTIMER INTSET: CTMRA4C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB3C1INT_Pos (23UL) /*!< CTIMER INTSET: CTMRB3C1INT (Bit 23) */ -#define CTIMER_INTSET_CTMRB3C1INT_Msk (0x800000UL) /*!< CTIMER INTSET: CTMRB3C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA3C1INT_Pos (22UL) /*!< CTIMER INTSET: CTMRA3C1INT (Bit 22) */ -#define CTIMER_INTSET_CTMRA3C1INT_Msk (0x400000UL) /*!< CTIMER INTSET: CTMRA3C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB2C1INT_Pos (21UL) /*!< CTIMER INTSET: CTMRB2C1INT (Bit 21) */ -#define CTIMER_INTSET_CTMRB2C1INT_Msk (0x200000UL) /*!< CTIMER INTSET: CTMRB2C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA2C1INT_Pos (20UL) /*!< CTIMER INTSET: CTMRA2C1INT (Bit 20) */ -#define CTIMER_INTSET_CTMRA2C1INT_Msk (0x100000UL) /*!< CTIMER INTSET: CTMRA2C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB1C1INT_Pos (19UL) /*!< CTIMER INTSET: CTMRB1C1INT (Bit 19) */ -#define CTIMER_INTSET_CTMRB1C1INT_Msk (0x80000UL) /*!< CTIMER INTSET: CTMRB1C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA1C1INT_Pos (18UL) /*!< CTIMER INTSET: CTMRA1C1INT (Bit 18) */ -#define CTIMER_INTSET_CTMRA1C1INT_Msk (0x40000UL) /*!< CTIMER INTSET: CTMRA1C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB0C1INT_Pos (17UL) /*!< CTIMER INTSET: CTMRB0C1INT (Bit 17) */ -#define CTIMER_INTSET_CTMRB0C1INT_Msk (0x20000UL) /*!< CTIMER INTSET: CTMRB0C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA0C1INT_Pos (16UL) /*!< CTIMER INTSET: CTMRA0C1INT (Bit 16) */ -#define CTIMER_INTSET_CTMRA0C1INT_Msk (0x10000UL) /*!< CTIMER INTSET: CTMRA0C1INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB7C0INT_Pos (15UL) /*!< CTIMER INTSET: CTMRB7C0INT (Bit 15) */ -#define CTIMER_INTSET_CTMRB7C0INT_Msk (0x8000UL) /*!< CTIMER INTSET: CTMRB7C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA7C0INT_Pos (14UL) /*!< CTIMER INTSET: CTMRA7C0INT (Bit 14) */ -#define CTIMER_INTSET_CTMRA7C0INT_Msk (0x4000UL) /*!< CTIMER INTSET: CTMRA7C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB6C0INT_Pos (13UL) /*!< CTIMER INTSET: CTMRB6C0INT (Bit 13) */ -#define CTIMER_INTSET_CTMRB6C0INT_Msk (0x2000UL) /*!< CTIMER INTSET: CTMRB6C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA6C0INT_Pos (12UL) /*!< CTIMER INTSET: CTMRA6C0INT (Bit 12) */ -#define CTIMER_INTSET_CTMRA6C0INT_Msk (0x1000UL) /*!< CTIMER INTSET: CTMRA6C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB5C0INT_Pos (11UL) /*!< CTIMER INTSET: CTMRB5C0INT (Bit 11) */ -#define CTIMER_INTSET_CTMRB5C0INT_Msk (0x800UL) /*!< CTIMER INTSET: CTMRB5C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA5C0INT_Pos (10UL) /*!< CTIMER INTSET: CTMRA5C0INT (Bit 10) */ -#define CTIMER_INTSET_CTMRA5C0INT_Msk (0x400UL) /*!< CTIMER INTSET: CTMRA5C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB4C0INT_Pos (9UL) /*!< CTIMER INTSET: CTMRB4C0INT (Bit 9) */ -#define CTIMER_INTSET_CTMRB4C0INT_Msk (0x200UL) /*!< CTIMER INTSET: CTMRB4C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA4C0INT_Pos (8UL) /*!< CTIMER INTSET: CTMRA4C0INT (Bit 8) */ -#define CTIMER_INTSET_CTMRA4C0INT_Msk (0x100UL) /*!< CTIMER INTSET: CTMRA4C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB3C0INT_Pos (7UL) /*!< CTIMER INTSET: CTMRB3C0INT (Bit 7) */ -#define CTIMER_INTSET_CTMRB3C0INT_Msk (0x80UL) /*!< CTIMER INTSET: CTMRB3C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA3C0INT_Pos (6UL) /*!< CTIMER INTSET: CTMRA3C0INT (Bit 6) */ -#define CTIMER_INTSET_CTMRA3C0INT_Msk (0x40UL) /*!< CTIMER INTSET: CTMRA3C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB2C0INT_Pos (5UL) /*!< CTIMER INTSET: CTMRB2C0INT (Bit 5) */ -#define CTIMER_INTSET_CTMRB2C0INT_Msk (0x20UL) /*!< CTIMER INTSET: CTMRB2C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA2C0INT_Pos (4UL) /*!< CTIMER INTSET: CTMRA2C0INT (Bit 4) */ -#define CTIMER_INTSET_CTMRA2C0INT_Msk (0x10UL) /*!< CTIMER INTSET: CTMRA2C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB1C0INT_Pos (3UL) /*!< CTIMER INTSET: CTMRB1C0INT (Bit 3) */ -#define CTIMER_INTSET_CTMRB1C0INT_Msk (0x8UL) /*!< CTIMER INTSET: CTMRB1C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA1C0INT_Pos (2UL) /*!< CTIMER INTSET: CTMRA1C0INT (Bit 2) */ -#define CTIMER_INTSET_CTMRA1C0INT_Msk (0x4UL) /*!< CTIMER INTSET: CTMRA1C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRB0C0INT_Pos (1UL) /*!< CTIMER INTSET: CTMRB0C0INT (Bit 1) */ -#define CTIMER_INTSET_CTMRB0C0INT_Msk (0x2UL) /*!< CTIMER INTSET: CTMRB0C0INT (Bitfield-Mask: 0x01) */ -#define CTIMER_INTSET_CTMRA0C0INT_Pos (0UL) /*!< CTIMER INTSET: CTMRA0C0INT (Bit 0) */ -#define CTIMER_INTSET_CTMRA0C0INT_Msk (0x1UL) /*!< CTIMER INTSET: CTMRA0C0INT (Bitfield-Mask: 0x01) */ -/* ======================================================= STMINTEN ======================================================== */ -#define CTIMER_STMINTEN_CAPTURED_Pos (12UL) /*!< CTIMER STMINTEN: CAPTURED (Bit 12) */ -#define CTIMER_STMINTEN_CAPTURED_Msk (0x1000UL) /*!< CTIMER STMINTEN: CAPTURED (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_CAPTUREC_Pos (11UL) /*!< CTIMER STMINTEN: CAPTUREC (Bit 11) */ -#define CTIMER_STMINTEN_CAPTUREC_Msk (0x800UL) /*!< CTIMER STMINTEN: CAPTUREC (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_CAPTUREB_Pos (10UL) /*!< CTIMER STMINTEN: CAPTUREB (Bit 10) */ -#define CTIMER_STMINTEN_CAPTUREB_Msk (0x400UL) /*!< CTIMER STMINTEN: CAPTUREB (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_CAPTUREA_Pos (9UL) /*!< CTIMER STMINTEN: CAPTUREA (Bit 9) */ -#define CTIMER_STMINTEN_CAPTUREA_Msk (0x200UL) /*!< CTIMER STMINTEN: CAPTUREA (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_OVERFLOW_Pos (8UL) /*!< CTIMER STMINTEN: OVERFLOW (Bit 8) */ -#define CTIMER_STMINTEN_OVERFLOW_Msk (0x100UL) /*!< CTIMER STMINTEN: OVERFLOW (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_COMPAREH_Pos (7UL) /*!< CTIMER STMINTEN: COMPAREH (Bit 7) */ -#define CTIMER_STMINTEN_COMPAREH_Msk (0x80UL) /*!< CTIMER STMINTEN: COMPAREH (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_COMPAREG_Pos (6UL) /*!< CTIMER STMINTEN: COMPAREG (Bit 6) */ -#define CTIMER_STMINTEN_COMPAREG_Msk (0x40UL) /*!< CTIMER STMINTEN: COMPAREG (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_COMPAREF_Pos (5UL) /*!< CTIMER STMINTEN: COMPAREF (Bit 5) */ -#define CTIMER_STMINTEN_COMPAREF_Msk (0x20UL) /*!< CTIMER STMINTEN: COMPAREF (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_COMPAREE_Pos (4UL) /*!< CTIMER STMINTEN: COMPAREE (Bit 4) */ -#define CTIMER_STMINTEN_COMPAREE_Msk (0x10UL) /*!< CTIMER STMINTEN: COMPAREE (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_COMPARED_Pos (3UL) /*!< CTIMER STMINTEN: COMPARED (Bit 3) */ -#define CTIMER_STMINTEN_COMPARED_Msk (0x8UL) /*!< CTIMER STMINTEN: COMPARED (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_COMPAREC_Pos (2UL) /*!< CTIMER STMINTEN: COMPAREC (Bit 2) */ -#define CTIMER_STMINTEN_COMPAREC_Msk (0x4UL) /*!< CTIMER STMINTEN: COMPAREC (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_COMPAREB_Pos (1UL) /*!< CTIMER STMINTEN: COMPAREB (Bit 1) */ -#define CTIMER_STMINTEN_COMPAREB_Msk (0x2UL) /*!< CTIMER STMINTEN: COMPAREB (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTEN_COMPAREA_Pos (0UL) /*!< CTIMER STMINTEN: COMPAREA (Bit 0) */ -#define CTIMER_STMINTEN_COMPAREA_Msk (0x1UL) /*!< CTIMER STMINTEN: COMPAREA (Bitfield-Mask: 0x01) */ -/* ====================================================== STMINTSTAT ======================================================= */ -#define CTIMER_STMINTSTAT_CAPTURED_Pos (12UL) /*!< CTIMER STMINTSTAT: CAPTURED (Bit 12) */ -#define CTIMER_STMINTSTAT_CAPTURED_Msk (0x1000UL) /*!< CTIMER STMINTSTAT: CAPTURED (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_CAPTUREC_Pos (11UL) /*!< CTIMER STMINTSTAT: CAPTUREC (Bit 11) */ -#define CTIMER_STMINTSTAT_CAPTUREC_Msk (0x800UL) /*!< CTIMER STMINTSTAT: CAPTUREC (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_CAPTUREB_Pos (10UL) /*!< CTIMER STMINTSTAT: CAPTUREB (Bit 10) */ -#define CTIMER_STMINTSTAT_CAPTUREB_Msk (0x400UL) /*!< CTIMER STMINTSTAT: CAPTUREB (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_CAPTUREA_Pos (9UL) /*!< CTIMER STMINTSTAT: CAPTUREA (Bit 9) */ -#define CTIMER_STMINTSTAT_CAPTUREA_Msk (0x200UL) /*!< CTIMER STMINTSTAT: CAPTUREA (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_OVERFLOW_Pos (8UL) /*!< CTIMER STMINTSTAT: OVERFLOW (Bit 8) */ -#define CTIMER_STMINTSTAT_OVERFLOW_Msk (0x100UL) /*!< CTIMER STMINTSTAT: OVERFLOW (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_COMPAREH_Pos (7UL) /*!< CTIMER STMINTSTAT: COMPAREH (Bit 7) */ -#define CTIMER_STMINTSTAT_COMPAREH_Msk (0x80UL) /*!< CTIMER STMINTSTAT: COMPAREH (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_COMPAREG_Pos (6UL) /*!< CTIMER STMINTSTAT: COMPAREG (Bit 6) */ -#define CTIMER_STMINTSTAT_COMPAREG_Msk (0x40UL) /*!< CTIMER STMINTSTAT: COMPAREG (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_COMPAREF_Pos (5UL) /*!< CTIMER STMINTSTAT: COMPAREF (Bit 5) */ -#define CTIMER_STMINTSTAT_COMPAREF_Msk (0x20UL) /*!< CTIMER STMINTSTAT: COMPAREF (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_COMPAREE_Pos (4UL) /*!< CTIMER STMINTSTAT: COMPAREE (Bit 4) */ -#define CTIMER_STMINTSTAT_COMPAREE_Msk (0x10UL) /*!< CTIMER STMINTSTAT: COMPAREE (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_COMPARED_Pos (3UL) /*!< CTIMER STMINTSTAT: COMPARED (Bit 3) */ -#define CTIMER_STMINTSTAT_COMPARED_Msk (0x8UL) /*!< CTIMER STMINTSTAT: COMPARED (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_COMPAREC_Pos (2UL) /*!< CTIMER STMINTSTAT: COMPAREC (Bit 2) */ -#define CTIMER_STMINTSTAT_COMPAREC_Msk (0x4UL) /*!< CTIMER STMINTSTAT: COMPAREC (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_COMPAREB_Pos (1UL) /*!< CTIMER STMINTSTAT: COMPAREB (Bit 1) */ -#define CTIMER_STMINTSTAT_COMPAREB_Msk (0x2UL) /*!< CTIMER STMINTSTAT: COMPAREB (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSTAT_COMPAREA_Pos (0UL) /*!< CTIMER STMINTSTAT: COMPAREA (Bit 0) */ -#define CTIMER_STMINTSTAT_COMPAREA_Msk (0x1UL) /*!< CTIMER STMINTSTAT: COMPAREA (Bitfield-Mask: 0x01) */ -/* ======================================================= STMINTCLR ======================================================= */ -#define CTIMER_STMINTCLR_CAPTURED_Pos (12UL) /*!< CTIMER STMINTCLR: CAPTURED (Bit 12) */ -#define CTIMER_STMINTCLR_CAPTURED_Msk (0x1000UL) /*!< CTIMER STMINTCLR: CAPTURED (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_CAPTUREC_Pos (11UL) /*!< CTIMER STMINTCLR: CAPTUREC (Bit 11) */ -#define CTIMER_STMINTCLR_CAPTUREC_Msk (0x800UL) /*!< CTIMER STMINTCLR: CAPTUREC (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_CAPTUREB_Pos (10UL) /*!< CTIMER STMINTCLR: CAPTUREB (Bit 10) */ -#define CTIMER_STMINTCLR_CAPTUREB_Msk (0x400UL) /*!< CTIMER STMINTCLR: CAPTUREB (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_CAPTUREA_Pos (9UL) /*!< CTIMER STMINTCLR: CAPTUREA (Bit 9) */ -#define CTIMER_STMINTCLR_CAPTUREA_Msk (0x200UL) /*!< CTIMER STMINTCLR: CAPTUREA (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_OVERFLOW_Pos (8UL) /*!< CTIMER STMINTCLR: OVERFLOW (Bit 8) */ -#define CTIMER_STMINTCLR_OVERFLOW_Msk (0x100UL) /*!< CTIMER STMINTCLR: OVERFLOW (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_COMPAREH_Pos (7UL) /*!< CTIMER STMINTCLR: COMPAREH (Bit 7) */ -#define CTIMER_STMINTCLR_COMPAREH_Msk (0x80UL) /*!< CTIMER STMINTCLR: COMPAREH (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_COMPAREG_Pos (6UL) /*!< CTIMER STMINTCLR: COMPAREG (Bit 6) */ -#define CTIMER_STMINTCLR_COMPAREG_Msk (0x40UL) /*!< CTIMER STMINTCLR: COMPAREG (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_COMPAREF_Pos (5UL) /*!< CTIMER STMINTCLR: COMPAREF (Bit 5) */ -#define CTIMER_STMINTCLR_COMPAREF_Msk (0x20UL) /*!< CTIMER STMINTCLR: COMPAREF (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_COMPAREE_Pos (4UL) /*!< CTIMER STMINTCLR: COMPAREE (Bit 4) */ -#define CTIMER_STMINTCLR_COMPAREE_Msk (0x10UL) /*!< CTIMER STMINTCLR: COMPAREE (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_COMPARED_Pos (3UL) /*!< CTIMER STMINTCLR: COMPARED (Bit 3) */ -#define CTIMER_STMINTCLR_COMPARED_Msk (0x8UL) /*!< CTIMER STMINTCLR: COMPARED (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_COMPAREC_Pos (2UL) /*!< CTIMER STMINTCLR: COMPAREC (Bit 2) */ -#define CTIMER_STMINTCLR_COMPAREC_Msk (0x4UL) /*!< CTIMER STMINTCLR: COMPAREC (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_COMPAREB_Pos (1UL) /*!< CTIMER STMINTCLR: COMPAREB (Bit 1) */ -#define CTIMER_STMINTCLR_COMPAREB_Msk (0x2UL) /*!< CTIMER STMINTCLR: COMPAREB (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTCLR_COMPAREA_Pos (0UL) /*!< CTIMER STMINTCLR: COMPAREA (Bit 0) */ -#define CTIMER_STMINTCLR_COMPAREA_Msk (0x1UL) /*!< CTIMER STMINTCLR: COMPAREA (Bitfield-Mask: 0x01) */ -/* ======================================================= STMINTSET ======================================================= */ -#define CTIMER_STMINTSET_CAPTURED_Pos (12UL) /*!< CTIMER STMINTSET: CAPTURED (Bit 12) */ -#define CTIMER_STMINTSET_CAPTURED_Msk (0x1000UL) /*!< CTIMER STMINTSET: CAPTURED (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_CAPTUREC_Pos (11UL) /*!< CTIMER STMINTSET: CAPTUREC (Bit 11) */ -#define CTIMER_STMINTSET_CAPTUREC_Msk (0x800UL) /*!< CTIMER STMINTSET: CAPTUREC (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_CAPTUREB_Pos (10UL) /*!< CTIMER STMINTSET: CAPTUREB (Bit 10) */ -#define CTIMER_STMINTSET_CAPTUREB_Msk (0x400UL) /*!< CTIMER STMINTSET: CAPTUREB (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_CAPTUREA_Pos (9UL) /*!< CTIMER STMINTSET: CAPTUREA (Bit 9) */ -#define CTIMER_STMINTSET_CAPTUREA_Msk (0x200UL) /*!< CTIMER STMINTSET: CAPTUREA (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_OVERFLOW_Pos (8UL) /*!< CTIMER STMINTSET: OVERFLOW (Bit 8) */ -#define CTIMER_STMINTSET_OVERFLOW_Msk (0x100UL) /*!< CTIMER STMINTSET: OVERFLOW (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_COMPAREH_Pos (7UL) /*!< CTIMER STMINTSET: COMPAREH (Bit 7) */ -#define CTIMER_STMINTSET_COMPAREH_Msk (0x80UL) /*!< CTIMER STMINTSET: COMPAREH (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_COMPAREG_Pos (6UL) /*!< CTIMER STMINTSET: COMPAREG (Bit 6) */ -#define CTIMER_STMINTSET_COMPAREG_Msk (0x40UL) /*!< CTIMER STMINTSET: COMPAREG (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_COMPAREF_Pos (5UL) /*!< CTIMER STMINTSET: COMPAREF (Bit 5) */ -#define CTIMER_STMINTSET_COMPAREF_Msk (0x20UL) /*!< CTIMER STMINTSET: COMPAREF (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_COMPAREE_Pos (4UL) /*!< CTIMER STMINTSET: COMPAREE (Bit 4) */ -#define CTIMER_STMINTSET_COMPAREE_Msk (0x10UL) /*!< CTIMER STMINTSET: COMPAREE (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_COMPARED_Pos (3UL) /*!< CTIMER STMINTSET: COMPARED (Bit 3) */ -#define CTIMER_STMINTSET_COMPARED_Msk (0x8UL) /*!< CTIMER STMINTSET: COMPARED (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_COMPAREC_Pos (2UL) /*!< CTIMER STMINTSET: COMPAREC (Bit 2) */ -#define CTIMER_STMINTSET_COMPAREC_Msk (0x4UL) /*!< CTIMER STMINTSET: COMPAREC (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_COMPAREB_Pos (1UL) /*!< CTIMER STMINTSET: COMPAREB (Bit 1) */ -#define CTIMER_STMINTSET_COMPAREB_Msk (0x2UL) /*!< CTIMER STMINTSET: COMPAREB (Bitfield-Mask: 0x01) */ -#define CTIMER_STMINTSET_COMPAREA_Pos (0UL) /*!< CTIMER STMINTSET: COMPAREA (Bit 0) */ -#define CTIMER_STMINTSET_COMPAREA_Msk (0x1UL) /*!< CTIMER STMINTSET: COMPAREA (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ GPIO ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== PADREGA ======================================================== */ -#define GPIO_PADREGA_PAD3PWRUP_Pos (30UL) /*!< GPIO PADREGA: PAD3PWRUP (Bit 30) */ -#define GPIO_PADREGA_PAD3PWRUP_Msk (0x40000000UL) /*!< GPIO PADREGA: PAD3PWRUP (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD3FNCSEL_Pos (27UL) /*!< GPIO PADREGA: PAD3FNCSEL (Bit 27) */ -#define GPIO_PADREGA_PAD3FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGA: PAD3FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGA_PAD3STRNG_Pos (26UL) /*!< GPIO PADREGA: PAD3STRNG (Bit 26) */ -#define GPIO_PADREGA_PAD3STRNG_Msk (0x4000000UL) /*!< GPIO PADREGA: PAD3STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD3INPEN_Pos (25UL) /*!< GPIO PADREGA: PAD3INPEN (Bit 25) */ -#define GPIO_PADREGA_PAD3INPEN_Msk (0x2000000UL) /*!< GPIO PADREGA: PAD3INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD3PULL_Pos (24UL) /*!< GPIO PADREGA: PAD3PULL (Bit 24) */ -#define GPIO_PADREGA_PAD3PULL_Msk (0x1000000UL) /*!< GPIO PADREGA: PAD3PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD2FNCSEL_Pos (19UL) /*!< GPIO PADREGA: PAD2FNCSEL (Bit 19) */ -#define GPIO_PADREGA_PAD2FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGA: PAD2FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGA_PAD2STRNG_Pos (18UL) /*!< GPIO PADREGA: PAD2STRNG (Bit 18) */ -#define GPIO_PADREGA_PAD2STRNG_Msk (0x40000UL) /*!< GPIO PADREGA: PAD2STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD2INPEN_Pos (17UL) /*!< GPIO PADREGA: PAD2INPEN (Bit 17) */ -#define GPIO_PADREGA_PAD2INPEN_Msk (0x20000UL) /*!< GPIO PADREGA: PAD2INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD2PULL_Pos (16UL) /*!< GPIO PADREGA: PAD2PULL (Bit 16) */ -#define GPIO_PADREGA_PAD2PULL_Msk (0x10000UL) /*!< GPIO PADREGA: PAD2PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD1RSEL_Pos (14UL) /*!< GPIO PADREGA: PAD1RSEL (Bit 14) */ -#define GPIO_PADREGA_PAD1RSEL_Msk (0xc000UL) /*!< GPIO PADREGA: PAD1RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGA_PAD1FNCSEL_Pos (11UL) /*!< GPIO PADREGA: PAD1FNCSEL (Bit 11) */ -#define GPIO_PADREGA_PAD1FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGA: PAD1FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGA_PAD1STRNG_Pos (10UL) /*!< GPIO PADREGA: PAD1STRNG (Bit 10) */ -#define GPIO_PADREGA_PAD1STRNG_Msk (0x400UL) /*!< GPIO PADREGA: PAD1STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD1INPEN_Pos (9UL) /*!< GPIO PADREGA: PAD1INPEN (Bit 9) */ -#define GPIO_PADREGA_PAD1INPEN_Msk (0x200UL) /*!< GPIO PADREGA: PAD1INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD1PULL_Pos (8UL) /*!< GPIO PADREGA: PAD1PULL (Bit 8) */ -#define GPIO_PADREGA_PAD1PULL_Msk (0x100UL) /*!< GPIO PADREGA: PAD1PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD0RSEL_Pos (6UL) /*!< GPIO PADREGA: PAD0RSEL (Bit 6) */ -#define GPIO_PADREGA_PAD0RSEL_Msk (0xc0UL) /*!< GPIO PADREGA: PAD0RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGA_PAD0FNCSEL_Pos (3UL) /*!< GPIO PADREGA: PAD0FNCSEL (Bit 3) */ -#define GPIO_PADREGA_PAD0FNCSEL_Msk (0x38UL) /*!< GPIO PADREGA: PAD0FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGA_PAD0STRNG_Pos (2UL) /*!< GPIO PADREGA: PAD0STRNG (Bit 2) */ -#define GPIO_PADREGA_PAD0STRNG_Msk (0x4UL) /*!< GPIO PADREGA: PAD0STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD0INPEN_Pos (1UL) /*!< GPIO PADREGA: PAD0INPEN (Bit 1) */ -#define GPIO_PADREGA_PAD0INPEN_Msk (0x2UL) /*!< GPIO PADREGA: PAD0INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGA_PAD0PULL_Pos (0UL) /*!< GPIO PADREGA: PAD0PULL (Bit 0) */ -#define GPIO_PADREGA_PAD0PULL_Msk (0x1UL) /*!< GPIO PADREGA: PAD0PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGB ======================================================== */ -#define GPIO_PADREGB_PAD7FNCSEL_Pos (27UL) /*!< GPIO PADREGB: PAD7FNCSEL (Bit 27) */ -#define GPIO_PADREGB_PAD7FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGB: PAD7FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGB_PAD7STRNG_Pos (26UL) /*!< GPIO PADREGB: PAD7STRNG (Bit 26) */ -#define GPIO_PADREGB_PAD7STRNG_Msk (0x4000000UL) /*!< GPIO PADREGB: PAD7STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD7INPEN_Pos (25UL) /*!< GPIO PADREGB: PAD7INPEN (Bit 25) */ -#define GPIO_PADREGB_PAD7INPEN_Msk (0x2000000UL) /*!< GPIO PADREGB: PAD7INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD7PULL_Pos (24UL) /*!< GPIO PADREGB: PAD7PULL (Bit 24) */ -#define GPIO_PADREGB_PAD7PULL_Msk (0x1000000UL) /*!< GPIO PADREGB: PAD7PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD6RSEL_Pos (22UL) /*!< GPIO PADREGB: PAD6RSEL (Bit 22) */ -#define GPIO_PADREGB_PAD6RSEL_Msk (0xc00000UL) /*!< GPIO PADREGB: PAD6RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGB_PAD6FNCSEL_Pos (19UL) /*!< GPIO PADREGB: PAD6FNCSEL (Bit 19) */ -#define GPIO_PADREGB_PAD6FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGB: PAD6FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGB_PAD6STRNG_Pos (18UL) /*!< GPIO PADREGB: PAD6STRNG (Bit 18) */ -#define GPIO_PADREGB_PAD6STRNG_Msk (0x40000UL) /*!< GPIO PADREGB: PAD6STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD6INPEN_Pos (17UL) /*!< GPIO PADREGB: PAD6INPEN (Bit 17) */ -#define GPIO_PADREGB_PAD6INPEN_Msk (0x20000UL) /*!< GPIO PADREGB: PAD6INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD6PULL_Pos (16UL) /*!< GPIO PADREGB: PAD6PULL (Bit 16) */ -#define GPIO_PADREGB_PAD6PULL_Msk (0x10000UL) /*!< GPIO PADREGB: PAD6PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD5RSEL_Pos (14UL) /*!< GPIO PADREGB: PAD5RSEL (Bit 14) */ -#define GPIO_PADREGB_PAD5RSEL_Msk (0xc000UL) /*!< GPIO PADREGB: PAD5RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGB_PAD5FNCSEL_Pos (11UL) /*!< GPIO PADREGB: PAD5FNCSEL (Bit 11) */ -#define GPIO_PADREGB_PAD5FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGB: PAD5FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGB_PAD5STRNG_Pos (10UL) /*!< GPIO PADREGB: PAD5STRNG (Bit 10) */ -#define GPIO_PADREGB_PAD5STRNG_Msk (0x400UL) /*!< GPIO PADREGB: PAD5STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD5INPEN_Pos (9UL) /*!< GPIO PADREGB: PAD5INPEN (Bit 9) */ -#define GPIO_PADREGB_PAD5INPEN_Msk (0x200UL) /*!< GPIO PADREGB: PAD5INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD5PULL_Pos (8UL) /*!< GPIO PADREGB: PAD5PULL (Bit 8) */ -#define GPIO_PADREGB_PAD5PULL_Msk (0x100UL) /*!< GPIO PADREGB: PAD5PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD4FNCSEL_Pos (3UL) /*!< GPIO PADREGB: PAD4FNCSEL (Bit 3) */ -#define GPIO_PADREGB_PAD4FNCSEL_Msk (0x38UL) /*!< GPIO PADREGB: PAD4FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGB_PAD4STRNG_Pos (2UL) /*!< GPIO PADREGB: PAD4STRNG (Bit 2) */ -#define GPIO_PADREGB_PAD4STRNG_Msk (0x4UL) /*!< GPIO PADREGB: PAD4STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD4INPEN_Pos (1UL) /*!< GPIO PADREGB: PAD4INPEN (Bit 1) */ -#define GPIO_PADREGB_PAD4INPEN_Msk (0x2UL) /*!< GPIO PADREGB: PAD4INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGB_PAD4PULL_Pos (0UL) /*!< GPIO PADREGB: PAD4PULL (Bit 0) */ -#define GPIO_PADREGB_PAD4PULL_Msk (0x1UL) /*!< GPIO PADREGB: PAD4PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGC ======================================================== */ -#define GPIO_PADREGC_PAD11FNCSEL_Pos (27UL) /*!< GPIO PADREGC: PAD11FNCSEL (Bit 27) */ -#define GPIO_PADREGC_PAD11FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGC: PAD11FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGC_PAD11STRNG_Pos (26UL) /*!< GPIO PADREGC: PAD11STRNG (Bit 26) */ -#define GPIO_PADREGC_PAD11STRNG_Msk (0x4000000UL) /*!< GPIO PADREGC: PAD11STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD11INPEN_Pos (25UL) /*!< GPIO PADREGC: PAD11INPEN (Bit 25) */ -#define GPIO_PADREGC_PAD11INPEN_Msk (0x2000000UL) /*!< GPIO PADREGC: PAD11INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD11PULL_Pos (24UL) /*!< GPIO PADREGC: PAD11PULL (Bit 24) */ -#define GPIO_PADREGC_PAD11PULL_Msk (0x1000000UL) /*!< GPIO PADREGC: PAD11PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD10FNCSEL_Pos (19UL) /*!< GPIO PADREGC: PAD10FNCSEL (Bit 19) */ -#define GPIO_PADREGC_PAD10FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGC: PAD10FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGC_PAD10STRNG_Pos (18UL) /*!< GPIO PADREGC: PAD10STRNG (Bit 18) */ -#define GPIO_PADREGC_PAD10STRNG_Msk (0x40000UL) /*!< GPIO PADREGC: PAD10STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD10INPEN_Pos (17UL) /*!< GPIO PADREGC: PAD10INPEN (Bit 17) */ -#define GPIO_PADREGC_PAD10INPEN_Msk (0x20000UL) /*!< GPIO PADREGC: PAD10INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD10PULL_Pos (16UL) /*!< GPIO PADREGC: PAD10PULL (Bit 16) */ -#define GPIO_PADREGC_PAD10PULL_Msk (0x10000UL) /*!< GPIO PADREGC: PAD10PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD9RSEL_Pos (14UL) /*!< GPIO PADREGC: PAD9RSEL (Bit 14) */ -#define GPIO_PADREGC_PAD9RSEL_Msk (0xc000UL) /*!< GPIO PADREGC: PAD9RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGC_PAD9FNCSEL_Pos (11UL) /*!< GPIO PADREGC: PAD9FNCSEL (Bit 11) */ -#define GPIO_PADREGC_PAD9FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGC: PAD9FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGC_PAD9STRNG_Pos (10UL) /*!< GPIO PADREGC: PAD9STRNG (Bit 10) */ -#define GPIO_PADREGC_PAD9STRNG_Msk (0x400UL) /*!< GPIO PADREGC: PAD9STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD9INPEN_Pos (9UL) /*!< GPIO PADREGC: PAD9INPEN (Bit 9) */ -#define GPIO_PADREGC_PAD9INPEN_Msk (0x200UL) /*!< GPIO PADREGC: PAD9INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD9PULL_Pos (8UL) /*!< GPIO PADREGC: PAD9PULL (Bit 8) */ -#define GPIO_PADREGC_PAD9PULL_Msk (0x100UL) /*!< GPIO PADREGC: PAD9PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD8RSEL_Pos (6UL) /*!< GPIO PADREGC: PAD8RSEL (Bit 6) */ -#define GPIO_PADREGC_PAD8RSEL_Msk (0xc0UL) /*!< GPIO PADREGC: PAD8RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGC_PAD8FNCSEL_Pos (3UL) /*!< GPIO PADREGC: PAD8FNCSEL (Bit 3) */ -#define GPIO_PADREGC_PAD8FNCSEL_Msk (0x38UL) /*!< GPIO PADREGC: PAD8FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGC_PAD8STRNG_Pos (2UL) /*!< GPIO PADREGC: PAD8STRNG (Bit 2) */ -#define GPIO_PADREGC_PAD8STRNG_Msk (0x4UL) /*!< GPIO PADREGC: PAD8STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD8INPEN_Pos (1UL) /*!< GPIO PADREGC: PAD8INPEN (Bit 1) */ -#define GPIO_PADREGC_PAD8INPEN_Msk (0x2UL) /*!< GPIO PADREGC: PAD8INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGC_PAD8PULL_Pos (0UL) /*!< GPIO PADREGC: PAD8PULL (Bit 0) */ -#define GPIO_PADREGC_PAD8PULL_Msk (0x1UL) /*!< GPIO PADREGC: PAD8PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGD ======================================================== */ -#define GPIO_PADREGD_PAD15FNCSEL_Pos (27UL) /*!< GPIO PADREGD: PAD15FNCSEL (Bit 27) */ -#define GPIO_PADREGD_PAD15FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGD: PAD15FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGD_PAD15STRNG_Pos (26UL) /*!< GPIO PADREGD: PAD15STRNG (Bit 26) */ -#define GPIO_PADREGD_PAD15STRNG_Msk (0x4000000UL) /*!< GPIO PADREGD: PAD15STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD15INPEN_Pos (25UL) /*!< GPIO PADREGD: PAD15INPEN (Bit 25) */ -#define GPIO_PADREGD_PAD15INPEN_Msk (0x2000000UL) /*!< GPIO PADREGD: PAD15INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD15PULL_Pos (24UL) /*!< GPIO PADREGD: PAD15PULL (Bit 24) */ -#define GPIO_PADREGD_PAD15PULL_Msk (0x1000000UL) /*!< GPIO PADREGD: PAD15PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD14FNCSEL_Pos (19UL) /*!< GPIO PADREGD: PAD14FNCSEL (Bit 19) */ -#define GPIO_PADREGD_PAD14FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGD: PAD14FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGD_PAD14STRNG_Pos (18UL) /*!< GPIO PADREGD: PAD14STRNG (Bit 18) */ -#define GPIO_PADREGD_PAD14STRNG_Msk (0x40000UL) /*!< GPIO PADREGD: PAD14STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD14INPEN_Pos (17UL) /*!< GPIO PADREGD: PAD14INPEN (Bit 17) */ -#define GPIO_PADREGD_PAD14INPEN_Msk (0x20000UL) /*!< GPIO PADREGD: PAD14INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD14PULL_Pos (16UL) /*!< GPIO PADREGD: PAD14PULL (Bit 16) */ -#define GPIO_PADREGD_PAD14PULL_Msk (0x10000UL) /*!< GPIO PADREGD: PAD14PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD13FNCSEL_Pos (11UL) /*!< GPIO PADREGD: PAD13FNCSEL (Bit 11) */ -#define GPIO_PADREGD_PAD13FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGD: PAD13FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGD_PAD13STRNG_Pos (10UL) /*!< GPIO PADREGD: PAD13STRNG (Bit 10) */ -#define GPIO_PADREGD_PAD13STRNG_Msk (0x400UL) /*!< GPIO PADREGD: PAD13STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD13INPEN_Pos (9UL) /*!< GPIO PADREGD: PAD13INPEN (Bit 9) */ -#define GPIO_PADREGD_PAD13INPEN_Msk (0x200UL) /*!< GPIO PADREGD: PAD13INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD13PULL_Pos (8UL) /*!< GPIO PADREGD: PAD13PULL (Bit 8) */ -#define GPIO_PADREGD_PAD13PULL_Msk (0x100UL) /*!< GPIO PADREGD: PAD13PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD12FNCSEL_Pos (3UL) /*!< GPIO PADREGD: PAD12FNCSEL (Bit 3) */ -#define GPIO_PADREGD_PAD12FNCSEL_Msk (0x38UL) /*!< GPIO PADREGD: PAD12FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGD_PAD12STRNG_Pos (2UL) /*!< GPIO PADREGD: PAD12STRNG (Bit 2) */ -#define GPIO_PADREGD_PAD12STRNG_Msk (0x4UL) /*!< GPIO PADREGD: PAD12STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD12INPEN_Pos (1UL) /*!< GPIO PADREGD: PAD12INPEN (Bit 1) */ -#define GPIO_PADREGD_PAD12INPEN_Msk (0x2UL) /*!< GPIO PADREGD: PAD12INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGD_PAD12PULL_Pos (0UL) /*!< GPIO PADREGD: PAD12PULL (Bit 0) */ -#define GPIO_PADREGD_PAD12PULL_Msk (0x1UL) /*!< GPIO PADREGD: PAD12PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGE ======================================================== */ -#define GPIO_PADREGE_PAD19FNCSEL_Pos (27UL) /*!< GPIO PADREGE: PAD19FNCSEL (Bit 27) */ -#define GPIO_PADREGE_PAD19FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGE: PAD19FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGE_PAD19STRNG_Pos (26UL) /*!< GPIO PADREGE: PAD19STRNG (Bit 26) */ -#define GPIO_PADREGE_PAD19STRNG_Msk (0x4000000UL) /*!< GPIO PADREGE: PAD19STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD19INPEN_Pos (25UL) /*!< GPIO PADREGE: PAD19INPEN (Bit 25) */ -#define GPIO_PADREGE_PAD19INPEN_Msk (0x2000000UL) /*!< GPIO PADREGE: PAD19INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD19PULL_Pos (24UL) /*!< GPIO PADREGE: PAD19PULL (Bit 24) */ -#define GPIO_PADREGE_PAD19PULL_Msk (0x1000000UL) /*!< GPIO PADREGE: PAD19PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD18FNCSEL_Pos (19UL) /*!< GPIO PADREGE: PAD18FNCSEL (Bit 19) */ -#define GPIO_PADREGE_PAD18FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGE: PAD18FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGE_PAD18STRNG_Pos (18UL) /*!< GPIO PADREGE: PAD18STRNG (Bit 18) */ -#define GPIO_PADREGE_PAD18STRNG_Msk (0x40000UL) /*!< GPIO PADREGE: PAD18STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD18INPEN_Pos (17UL) /*!< GPIO PADREGE: PAD18INPEN (Bit 17) */ -#define GPIO_PADREGE_PAD18INPEN_Msk (0x20000UL) /*!< GPIO PADREGE: PAD18INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD18PULL_Pos (16UL) /*!< GPIO PADREGE: PAD18PULL (Bit 16) */ -#define GPIO_PADREGE_PAD18PULL_Msk (0x10000UL) /*!< GPIO PADREGE: PAD18PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD17FNCSEL_Pos (11UL) /*!< GPIO PADREGE: PAD17FNCSEL (Bit 11) */ -#define GPIO_PADREGE_PAD17FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGE: PAD17FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGE_PAD17STRNG_Pos (10UL) /*!< GPIO PADREGE: PAD17STRNG (Bit 10) */ -#define GPIO_PADREGE_PAD17STRNG_Msk (0x400UL) /*!< GPIO PADREGE: PAD17STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD17INPEN_Pos (9UL) /*!< GPIO PADREGE: PAD17INPEN (Bit 9) */ -#define GPIO_PADREGE_PAD17INPEN_Msk (0x200UL) /*!< GPIO PADREGE: PAD17INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD17PULL_Pos (8UL) /*!< GPIO PADREGE: PAD17PULL (Bit 8) */ -#define GPIO_PADREGE_PAD17PULL_Msk (0x100UL) /*!< GPIO PADREGE: PAD17PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD16FNCSEL_Pos (3UL) /*!< GPIO PADREGE: PAD16FNCSEL (Bit 3) */ -#define GPIO_PADREGE_PAD16FNCSEL_Msk (0x38UL) /*!< GPIO PADREGE: PAD16FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGE_PAD16STRNG_Pos (2UL) /*!< GPIO PADREGE: PAD16STRNG (Bit 2) */ -#define GPIO_PADREGE_PAD16STRNG_Msk (0x4UL) /*!< GPIO PADREGE: PAD16STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD16INPEN_Pos (1UL) /*!< GPIO PADREGE: PAD16INPEN (Bit 1) */ -#define GPIO_PADREGE_PAD16INPEN_Msk (0x2UL) /*!< GPIO PADREGE: PAD16INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGE_PAD16PULL_Pos (0UL) /*!< GPIO PADREGE: PAD16PULL (Bit 0) */ -#define GPIO_PADREGE_PAD16PULL_Msk (0x1UL) /*!< GPIO PADREGE: PAD16PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGF ======================================================== */ -#define GPIO_PADREGF_PAD23FNCSEL_Pos (27UL) /*!< GPIO PADREGF: PAD23FNCSEL (Bit 27) */ -#define GPIO_PADREGF_PAD23FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGF: PAD23FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGF_PAD23STRNG_Pos (26UL) /*!< GPIO PADREGF: PAD23STRNG (Bit 26) */ -#define GPIO_PADREGF_PAD23STRNG_Msk (0x4000000UL) /*!< GPIO PADREGF: PAD23STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD23INPEN_Pos (25UL) /*!< GPIO PADREGF: PAD23INPEN (Bit 25) */ -#define GPIO_PADREGF_PAD23INPEN_Msk (0x2000000UL) /*!< GPIO PADREGF: PAD23INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD23PULL_Pos (24UL) /*!< GPIO PADREGF: PAD23PULL (Bit 24) */ -#define GPIO_PADREGF_PAD23PULL_Msk (0x1000000UL) /*!< GPIO PADREGF: PAD23PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD22FNCSEL_Pos (19UL) /*!< GPIO PADREGF: PAD22FNCSEL (Bit 19) */ -#define GPIO_PADREGF_PAD22FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGF: PAD22FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGF_PAD22STRNG_Pos (18UL) /*!< GPIO PADREGF: PAD22STRNG (Bit 18) */ -#define GPIO_PADREGF_PAD22STRNG_Msk (0x40000UL) /*!< GPIO PADREGF: PAD22STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD22INPEN_Pos (17UL) /*!< GPIO PADREGF: PAD22INPEN (Bit 17) */ -#define GPIO_PADREGF_PAD22INPEN_Msk (0x20000UL) /*!< GPIO PADREGF: PAD22INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD22PULL_Pos (16UL) /*!< GPIO PADREGF: PAD22PULL (Bit 16) */ -#define GPIO_PADREGF_PAD22PULL_Msk (0x10000UL) /*!< GPIO PADREGF: PAD22PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD21FNCSEL_Pos (11UL) /*!< GPIO PADREGF: PAD21FNCSEL (Bit 11) */ -#define GPIO_PADREGF_PAD21FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGF: PAD21FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGF_PAD21STRNG_Pos (10UL) /*!< GPIO PADREGF: PAD21STRNG (Bit 10) */ -#define GPIO_PADREGF_PAD21STRNG_Msk (0x400UL) /*!< GPIO PADREGF: PAD21STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD21INPEN_Pos (9UL) /*!< GPIO PADREGF: PAD21INPEN (Bit 9) */ -#define GPIO_PADREGF_PAD21INPEN_Msk (0x200UL) /*!< GPIO PADREGF: PAD21INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD21PULL_Pos (8UL) /*!< GPIO PADREGF: PAD21PULL (Bit 8) */ -#define GPIO_PADREGF_PAD21PULL_Msk (0x100UL) /*!< GPIO PADREGF: PAD21PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD20FNCSEL_Pos (3UL) /*!< GPIO PADREGF: PAD20FNCSEL (Bit 3) */ -#define GPIO_PADREGF_PAD20FNCSEL_Msk (0x38UL) /*!< GPIO PADREGF: PAD20FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGF_PAD20STRNG_Pos (2UL) /*!< GPIO PADREGF: PAD20STRNG (Bit 2) */ -#define GPIO_PADREGF_PAD20STRNG_Msk (0x4UL) /*!< GPIO PADREGF: PAD20STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD20INPEN_Pos (1UL) /*!< GPIO PADREGF: PAD20INPEN (Bit 1) */ -#define GPIO_PADREGF_PAD20INPEN_Msk (0x2UL) /*!< GPIO PADREGF: PAD20INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGF_PAD20PULL_Pos (0UL) /*!< GPIO PADREGF: PAD20PULL (Bit 0) */ -#define GPIO_PADREGF_PAD20PULL_Msk (0x1UL) /*!< GPIO PADREGF: PAD20PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGG ======================================================== */ -#define GPIO_PADREGG_PAD27RSEL_Pos (30UL) /*!< GPIO PADREGG: PAD27RSEL (Bit 30) */ -#define GPIO_PADREGG_PAD27RSEL_Msk (0xc0000000UL) /*!< GPIO PADREGG: PAD27RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGG_PAD27FNCSEL_Pos (27UL) /*!< GPIO PADREGG: PAD27FNCSEL (Bit 27) */ -#define GPIO_PADREGG_PAD27FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGG: PAD27FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGG_PAD27STRNG_Pos (26UL) /*!< GPIO PADREGG: PAD27STRNG (Bit 26) */ -#define GPIO_PADREGG_PAD27STRNG_Msk (0x4000000UL) /*!< GPIO PADREGG: PAD27STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD27INPEN_Pos (25UL) /*!< GPIO PADREGG: PAD27INPEN (Bit 25) */ -#define GPIO_PADREGG_PAD27INPEN_Msk (0x2000000UL) /*!< GPIO PADREGG: PAD27INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD27PULL_Pos (24UL) /*!< GPIO PADREGG: PAD27PULL (Bit 24) */ -#define GPIO_PADREGG_PAD27PULL_Msk (0x1000000UL) /*!< GPIO PADREGG: PAD27PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD26FNCSEL_Pos (19UL) /*!< GPIO PADREGG: PAD26FNCSEL (Bit 19) */ -#define GPIO_PADREGG_PAD26FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGG: PAD26FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGG_PAD26STRNG_Pos (18UL) /*!< GPIO PADREGG: PAD26STRNG (Bit 18) */ -#define GPIO_PADREGG_PAD26STRNG_Msk (0x40000UL) /*!< GPIO PADREGG: PAD26STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD26INPEN_Pos (17UL) /*!< GPIO PADREGG: PAD26INPEN (Bit 17) */ -#define GPIO_PADREGG_PAD26INPEN_Msk (0x20000UL) /*!< GPIO PADREGG: PAD26INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD26PULL_Pos (16UL) /*!< GPIO PADREGG: PAD26PULL (Bit 16) */ -#define GPIO_PADREGG_PAD26PULL_Msk (0x10000UL) /*!< GPIO PADREGG: PAD26PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD25RSEL_Pos (14UL) /*!< GPIO PADREGG: PAD25RSEL (Bit 14) */ -#define GPIO_PADREGG_PAD25RSEL_Msk (0xc000UL) /*!< GPIO PADREGG: PAD25RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGG_PAD25FNCSEL_Pos (11UL) /*!< GPIO PADREGG: PAD25FNCSEL (Bit 11) */ -#define GPIO_PADREGG_PAD25FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGG: PAD25FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGG_PAD25STRNG_Pos (10UL) /*!< GPIO PADREGG: PAD25STRNG (Bit 10) */ -#define GPIO_PADREGG_PAD25STRNG_Msk (0x400UL) /*!< GPIO PADREGG: PAD25STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD25INPEN_Pos (9UL) /*!< GPIO PADREGG: PAD25INPEN (Bit 9) */ -#define GPIO_PADREGG_PAD25INPEN_Msk (0x200UL) /*!< GPIO PADREGG: PAD25INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD25PULL_Pos (8UL) /*!< GPIO PADREGG: PAD25PULL (Bit 8) */ -#define GPIO_PADREGG_PAD25PULL_Msk (0x100UL) /*!< GPIO PADREGG: PAD25PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD24FNCSEL_Pos (3UL) /*!< GPIO PADREGG: PAD24FNCSEL (Bit 3) */ -#define GPIO_PADREGG_PAD24FNCSEL_Msk (0x38UL) /*!< GPIO PADREGG: PAD24FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGG_PAD24STRNG_Pos (2UL) /*!< GPIO PADREGG: PAD24STRNG (Bit 2) */ -#define GPIO_PADREGG_PAD24STRNG_Msk (0x4UL) /*!< GPIO PADREGG: PAD24STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD24INPEN_Pos (1UL) /*!< GPIO PADREGG: PAD24INPEN (Bit 1) */ -#define GPIO_PADREGG_PAD24INPEN_Msk (0x2UL) /*!< GPIO PADREGG: PAD24INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGG_PAD24PULL_Pos (0UL) /*!< GPIO PADREGG: PAD24PULL (Bit 0) */ -#define GPIO_PADREGG_PAD24PULL_Msk (0x1UL) /*!< GPIO PADREGG: PAD24PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGH ======================================================== */ -#define GPIO_PADREGH_PAD31FNCSEL_Pos (27UL) /*!< GPIO PADREGH: PAD31FNCSEL (Bit 27) */ -#define GPIO_PADREGH_PAD31FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGH: PAD31FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGH_PAD31STRNG_Pos (26UL) /*!< GPIO PADREGH: PAD31STRNG (Bit 26) */ -#define GPIO_PADREGH_PAD31STRNG_Msk (0x4000000UL) /*!< GPIO PADREGH: PAD31STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD31INPEN_Pos (25UL) /*!< GPIO PADREGH: PAD31INPEN (Bit 25) */ -#define GPIO_PADREGH_PAD31INPEN_Msk (0x2000000UL) /*!< GPIO PADREGH: PAD31INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD31PULL_Pos (24UL) /*!< GPIO PADREGH: PAD31PULL (Bit 24) */ -#define GPIO_PADREGH_PAD31PULL_Msk (0x1000000UL) /*!< GPIO PADREGH: PAD31PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD30FNCSEL_Pos (19UL) /*!< GPIO PADREGH: PAD30FNCSEL (Bit 19) */ -#define GPIO_PADREGH_PAD30FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGH: PAD30FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGH_PAD30STRNG_Pos (18UL) /*!< GPIO PADREGH: PAD30STRNG (Bit 18) */ -#define GPIO_PADREGH_PAD30STRNG_Msk (0x40000UL) /*!< GPIO PADREGH: PAD30STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD30INPEN_Pos (17UL) /*!< GPIO PADREGH: PAD30INPEN (Bit 17) */ -#define GPIO_PADREGH_PAD30INPEN_Msk (0x20000UL) /*!< GPIO PADREGH: PAD30INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD30PULL_Pos (16UL) /*!< GPIO PADREGH: PAD30PULL (Bit 16) */ -#define GPIO_PADREGH_PAD30PULL_Msk (0x10000UL) /*!< GPIO PADREGH: PAD30PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD29FNCSEL_Pos (11UL) /*!< GPIO PADREGH: PAD29FNCSEL (Bit 11) */ -#define GPIO_PADREGH_PAD29FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGH: PAD29FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGH_PAD29STRNG_Pos (10UL) /*!< GPIO PADREGH: PAD29STRNG (Bit 10) */ -#define GPIO_PADREGH_PAD29STRNG_Msk (0x400UL) /*!< GPIO PADREGH: PAD29STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD29INPEN_Pos (9UL) /*!< GPIO PADREGH: PAD29INPEN (Bit 9) */ -#define GPIO_PADREGH_PAD29INPEN_Msk (0x200UL) /*!< GPIO PADREGH: PAD29INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD29PULL_Pos (8UL) /*!< GPIO PADREGH: PAD29PULL (Bit 8) */ -#define GPIO_PADREGH_PAD29PULL_Msk (0x100UL) /*!< GPIO PADREGH: PAD29PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD28FNCSEL_Pos (3UL) /*!< GPIO PADREGH: PAD28FNCSEL (Bit 3) */ -#define GPIO_PADREGH_PAD28FNCSEL_Msk (0x38UL) /*!< GPIO PADREGH: PAD28FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGH_PAD28STRNG_Pos (2UL) /*!< GPIO PADREGH: PAD28STRNG (Bit 2) */ -#define GPIO_PADREGH_PAD28STRNG_Msk (0x4UL) /*!< GPIO PADREGH: PAD28STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD28INPEN_Pos (1UL) /*!< GPIO PADREGH: PAD28INPEN (Bit 1) */ -#define GPIO_PADREGH_PAD28INPEN_Msk (0x2UL) /*!< GPIO PADREGH: PAD28INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGH_PAD28PULL_Pos (0UL) /*!< GPIO PADREGH: PAD28PULL (Bit 0) */ -#define GPIO_PADREGH_PAD28PULL_Msk (0x1UL) /*!< GPIO PADREGH: PAD28PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGI ======================================================== */ -#define GPIO_PADREGI_PAD35FNCSEL_Pos (27UL) /*!< GPIO PADREGI: PAD35FNCSEL (Bit 27) */ -#define GPIO_PADREGI_PAD35FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGI: PAD35FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGI_PAD35STRNG_Pos (26UL) /*!< GPIO PADREGI: PAD35STRNG (Bit 26) */ -#define GPIO_PADREGI_PAD35STRNG_Msk (0x4000000UL) /*!< GPIO PADREGI: PAD35STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD35INPEN_Pos (25UL) /*!< GPIO PADREGI: PAD35INPEN (Bit 25) */ -#define GPIO_PADREGI_PAD35INPEN_Msk (0x2000000UL) /*!< GPIO PADREGI: PAD35INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD35PULL_Pos (24UL) /*!< GPIO PADREGI: PAD35PULL (Bit 24) */ -#define GPIO_PADREGI_PAD35PULL_Msk (0x1000000UL) /*!< GPIO PADREGI: PAD35PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD34FNCSEL_Pos (19UL) /*!< GPIO PADREGI: PAD34FNCSEL (Bit 19) */ -#define GPIO_PADREGI_PAD34FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGI: PAD34FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGI_PAD34STRNG_Pos (18UL) /*!< GPIO PADREGI: PAD34STRNG (Bit 18) */ -#define GPIO_PADREGI_PAD34STRNG_Msk (0x40000UL) /*!< GPIO PADREGI: PAD34STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD34INPEN_Pos (17UL) /*!< GPIO PADREGI: PAD34INPEN (Bit 17) */ -#define GPIO_PADREGI_PAD34INPEN_Msk (0x20000UL) /*!< GPIO PADREGI: PAD34INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD34PULL_Pos (16UL) /*!< GPIO PADREGI: PAD34PULL (Bit 16) */ -#define GPIO_PADREGI_PAD34PULL_Msk (0x10000UL) /*!< GPIO PADREGI: PAD34PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD33FNCSEL_Pos (11UL) /*!< GPIO PADREGI: PAD33FNCSEL (Bit 11) */ -#define GPIO_PADREGI_PAD33FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGI: PAD33FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGI_PAD33STRNG_Pos (10UL) /*!< GPIO PADREGI: PAD33STRNG (Bit 10) */ -#define GPIO_PADREGI_PAD33STRNG_Msk (0x400UL) /*!< GPIO PADREGI: PAD33STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD33INPEN_Pos (9UL) /*!< GPIO PADREGI: PAD33INPEN (Bit 9) */ -#define GPIO_PADREGI_PAD33INPEN_Msk (0x200UL) /*!< GPIO PADREGI: PAD33INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD33PULL_Pos (8UL) /*!< GPIO PADREGI: PAD33PULL (Bit 8) */ -#define GPIO_PADREGI_PAD33PULL_Msk (0x100UL) /*!< GPIO PADREGI: PAD33PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD32FNCSEL_Pos (3UL) /*!< GPIO PADREGI: PAD32FNCSEL (Bit 3) */ -#define GPIO_PADREGI_PAD32FNCSEL_Msk (0x38UL) /*!< GPIO PADREGI: PAD32FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGI_PAD32STRNG_Pos (2UL) /*!< GPIO PADREGI: PAD32STRNG (Bit 2) */ -#define GPIO_PADREGI_PAD32STRNG_Msk (0x4UL) /*!< GPIO PADREGI: PAD32STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD32INPEN_Pos (1UL) /*!< GPIO PADREGI: PAD32INPEN (Bit 1) */ -#define GPIO_PADREGI_PAD32INPEN_Msk (0x2UL) /*!< GPIO PADREGI: PAD32INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGI_PAD32PULL_Pos (0UL) /*!< GPIO PADREGI: PAD32PULL (Bit 0) */ -#define GPIO_PADREGI_PAD32PULL_Msk (0x1UL) /*!< GPIO PADREGI: PAD32PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGJ ======================================================== */ -#define GPIO_PADREGJ_PAD39RSEL_Pos (30UL) /*!< GPIO PADREGJ: PAD39RSEL (Bit 30) */ -#define GPIO_PADREGJ_PAD39RSEL_Msk (0xc0000000UL) /*!< GPIO PADREGJ: PAD39RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGJ_PAD39FNCSEL_Pos (27UL) /*!< GPIO PADREGJ: PAD39FNCSEL (Bit 27) */ -#define GPIO_PADREGJ_PAD39FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGJ: PAD39FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGJ_PAD39STRNG_Pos (26UL) /*!< GPIO PADREGJ: PAD39STRNG (Bit 26) */ -#define GPIO_PADREGJ_PAD39STRNG_Msk (0x4000000UL) /*!< GPIO PADREGJ: PAD39STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD39INPEN_Pos (25UL) /*!< GPIO PADREGJ: PAD39INPEN (Bit 25) */ -#define GPIO_PADREGJ_PAD39INPEN_Msk (0x2000000UL) /*!< GPIO PADREGJ: PAD39INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD39PULL_Pos (24UL) /*!< GPIO PADREGJ: PAD39PULL (Bit 24) */ -#define GPIO_PADREGJ_PAD39PULL_Msk (0x1000000UL) /*!< GPIO PADREGJ: PAD39PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD38FNCSEL_Pos (19UL) /*!< GPIO PADREGJ: PAD38FNCSEL (Bit 19) */ -#define GPIO_PADREGJ_PAD38FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGJ: PAD38FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGJ_PAD38STRNG_Pos (18UL) /*!< GPIO PADREGJ: PAD38STRNG (Bit 18) */ -#define GPIO_PADREGJ_PAD38STRNG_Msk (0x40000UL) /*!< GPIO PADREGJ: PAD38STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD38INPEN_Pos (17UL) /*!< GPIO PADREGJ: PAD38INPEN (Bit 17) */ -#define GPIO_PADREGJ_PAD38INPEN_Msk (0x20000UL) /*!< GPIO PADREGJ: PAD38INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD38PULL_Pos (16UL) /*!< GPIO PADREGJ: PAD38PULL (Bit 16) */ -#define GPIO_PADREGJ_PAD38PULL_Msk (0x10000UL) /*!< GPIO PADREGJ: PAD38PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD37PWRDN_Pos (15UL) /*!< GPIO PADREGJ: PAD37PWRDN (Bit 15) */ -#define GPIO_PADREGJ_PAD37PWRDN_Msk (0x8000UL) /*!< GPIO PADREGJ: PAD37PWRDN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD37FNCSEL_Pos (11UL) /*!< GPIO PADREGJ: PAD37FNCSEL (Bit 11) */ -#define GPIO_PADREGJ_PAD37FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGJ: PAD37FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGJ_PAD37STRNG_Pos (10UL) /*!< GPIO PADREGJ: PAD37STRNG (Bit 10) */ -#define GPIO_PADREGJ_PAD37STRNG_Msk (0x400UL) /*!< GPIO PADREGJ: PAD37STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD37INPEN_Pos (9UL) /*!< GPIO PADREGJ: PAD37INPEN (Bit 9) */ -#define GPIO_PADREGJ_PAD37INPEN_Msk (0x200UL) /*!< GPIO PADREGJ: PAD37INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD37PULL_Pos (8UL) /*!< GPIO PADREGJ: PAD37PULL (Bit 8) */ -#define GPIO_PADREGJ_PAD37PULL_Msk (0x100UL) /*!< GPIO PADREGJ: PAD37PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD36PWRUP_Pos (6UL) /*!< GPIO PADREGJ: PAD36PWRUP (Bit 6) */ -#define GPIO_PADREGJ_PAD36PWRUP_Msk (0x40UL) /*!< GPIO PADREGJ: PAD36PWRUP (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD36FNCSEL_Pos (3UL) /*!< GPIO PADREGJ: PAD36FNCSEL (Bit 3) */ -#define GPIO_PADREGJ_PAD36FNCSEL_Msk (0x38UL) /*!< GPIO PADREGJ: PAD36FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGJ_PAD36STRNG_Pos (2UL) /*!< GPIO PADREGJ: PAD36STRNG (Bit 2) */ -#define GPIO_PADREGJ_PAD36STRNG_Msk (0x4UL) /*!< GPIO PADREGJ: PAD36STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD36INPEN_Pos (1UL) /*!< GPIO PADREGJ: PAD36INPEN (Bit 1) */ -#define GPIO_PADREGJ_PAD36INPEN_Msk (0x2UL) /*!< GPIO PADREGJ: PAD36INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGJ_PAD36PULL_Pos (0UL) /*!< GPIO PADREGJ: PAD36PULL (Bit 0) */ -#define GPIO_PADREGJ_PAD36PULL_Msk (0x1UL) /*!< GPIO PADREGJ: PAD36PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGK ======================================================== */ -#define GPIO_PADREGK_PAD43RSEL_Pos (30UL) /*!< GPIO PADREGK: PAD43RSEL (Bit 30) */ -#define GPIO_PADREGK_PAD43RSEL_Msk (0xc0000000UL) /*!< GPIO PADREGK: PAD43RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGK_PAD43FNCSEL_Pos (27UL) /*!< GPIO PADREGK: PAD43FNCSEL (Bit 27) */ -#define GPIO_PADREGK_PAD43FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGK: PAD43FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGK_PAD43STRNG_Pos (26UL) /*!< GPIO PADREGK: PAD43STRNG (Bit 26) */ -#define GPIO_PADREGK_PAD43STRNG_Msk (0x4000000UL) /*!< GPIO PADREGK: PAD43STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD43INPEN_Pos (25UL) /*!< GPIO PADREGK: PAD43INPEN (Bit 25) */ -#define GPIO_PADREGK_PAD43INPEN_Msk (0x2000000UL) /*!< GPIO PADREGK: PAD43INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD43PULL_Pos (24UL) /*!< GPIO PADREGK: PAD43PULL (Bit 24) */ -#define GPIO_PADREGK_PAD43PULL_Msk (0x1000000UL) /*!< GPIO PADREGK: PAD43PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD42RSEL_Pos (22UL) /*!< GPIO PADREGK: PAD42RSEL (Bit 22) */ -#define GPIO_PADREGK_PAD42RSEL_Msk (0xc00000UL) /*!< GPIO PADREGK: PAD42RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGK_PAD42FNCSEL_Pos (19UL) /*!< GPIO PADREGK: PAD42FNCSEL (Bit 19) */ -#define GPIO_PADREGK_PAD42FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGK: PAD42FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGK_PAD42STRNG_Pos (18UL) /*!< GPIO PADREGK: PAD42STRNG (Bit 18) */ -#define GPIO_PADREGK_PAD42STRNG_Msk (0x40000UL) /*!< GPIO PADREGK: PAD42STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD42INPEN_Pos (17UL) /*!< GPIO PADREGK: PAD42INPEN (Bit 17) */ -#define GPIO_PADREGK_PAD42INPEN_Msk (0x20000UL) /*!< GPIO PADREGK: PAD42INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD42PULL_Pos (16UL) /*!< GPIO PADREGK: PAD42PULL (Bit 16) */ -#define GPIO_PADREGK_PAD42PULL_Msk (0x10000UL) /*!< GPIO PADREGK: PAD42PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD41PWRDN_Pos (15UL) /*!< GPIO PADREGK: PAD41PWRDN (Bit 15) */ -#define GPIO_PADREGK_PAD41PWRDN_Msk (0x8000UL) /*!< GPIO PADREGK: PAD41PWRDN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD41FNCSEL_Pos (11UL) /*!< GPIO PADREGK: PAD41FNCSEL (Bit 11) */ -#define GPIO_PADREGK_PAD41FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGK: PAD41FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGK_PAD41STRNG_Pos (10UL) /*!< GPIO PADREGK: PAD41STRNG (Bit 10) */ -#define GPIO_PADREGK_PAD41STRNG_Msk (0x400UL) /*!< GPIO PADREGK: PAD41STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD41INPEN_Pos (9UL) /*!< GPIO PADREGK: PAD41INPEN (Bit 9) */ -#define GPIO_PADREGK_PAD41INPEN_Msk (0x200UL) /*!< GPIO PADREGK: PAD41INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD41PULL_Pos (8UL) /*!< GPIO PADREGK: PAD41PULL (Bit 8) */ -#define GPIO_PADREGK_PAD41PULL_Msk (0x100UL) /*!< GPIO PADREGK: PAD41PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD40RSEL_Pos (6UL) /*!< GPIO PADREGK: PAD40RSEL (Bit 6) */ -#define GPIO_PADREGK_PAD40RSEL_Msk (0xc0UL) /*!< GPIO PADREGK: PAD40RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGK_PAD40FNCSEL_Pos (3UL) /*!< GPIO PADREGK: PAD40FNCSEL (Bit 3) */ -#define GPIO_PADREGK_PAD40FNCSEL_Msk (0x38UL) /*!< GPIO PADREGK: PAD40FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGK_PAD40STRNG_Pos (2UL) /*!< GPIO PADREGK: PAD40STRNG (Bit 2) */ -#define GPIO_PADREGK_PAD40STRNG_Msk (0x4UL) /*!< GPIO PADREGK: PAD40STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD40INPEN_Pos (1UL) /*!< GPIO PADREGK: PAD40INPEN (Bit 1) */ -#define GPIO_PADREGK_PAD40INPEN_Msk (0x2UL) /*!< GPIO PADREGK: PAD40INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGK_PAD40PULL_Pos (0UL) /*!< GPIO PADREGK: PAD40PULL (Bit 0) */ -#define GPIO_PADREGK_PAD40PULL_Msk (0x1UL) /*!< GPIO PADREGK: PAD40PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGL ======================================================== */ -#define GPIO_PADREGL_PAD47FNCSEL_Pos (27UL) /*!< GPIO PADREGL: PAD47FNCSEL (Bit 27) */ -#define GPIO_PADREGL_PAD47FNCSEL_Msk (0x38000000UL) /*!< GPIO PADREGL: PAD47FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGL_PAD47STRNG_Pos (26UL) /*!< GPIO PADREGL: PAD47STRNG (Bit 26) */ -#define GPIO_PADREGL_PAD47STRNG_Msk (0x4000000UL) /*!< GPIO PADREGL: PAD47STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD47INPEN_Pos (25UL) /*!< GPIO PADREGL: PAD47INPEN (Bit 25) */ -#define GPIO_PADREGL_PAD47INPEN_Msk (0x2000000UL) /*!< GPIO PADREGL: PAD47INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD47PULL_Pos (24UL) /*!< GPIO PADREGL: PAD47PULL (Bit 24) */ -#define GPIO_PADREGL_PAD47PULL_Msk (0x1000000UL) /*!< GPIO PADREGL: PAD47PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD46FNCSEL_Pos (19UL) /*!< GPIO PADREGL: PAD46FNCSEL (Bit 19) */ -#define GPIO_PADREGL_PAD46FNCSEL_Msk (0x380000UL) /*!< GPIO PADREGL: PAD46FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGL_PAD46STRNG_Pos (18UL) /*!< GPIO PADREGL: PAD46STRNG (Bit 18) */ -#define GPIO_PADREGL_PAD46STRNG_Msk (0x40000UL) /*!< GPIO PADREGL: PAD46STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD46INPEN_Pos (17UL) /*!< GPIO PADREGL: PAD46INPEN (Bit 17) */ -#define GPIO_PADREGL_PAD46INPEN_Msk (0x20000UL) /*!< GPIO PADREGL: PAD46INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD46PULL_Pos (16UL) /*!< GPIO PADREGL: PAD46PULL (Bit 16) */ -#define GPIO_PADREGL_PAD46PULL_Msk (0x10000UL) /*!< GPIO PADREGL: PAD46PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD45FNCSEL_Pos (11UL) /*!< GPIO PADREGL: PAD45FNCSEL (Bit 11) */ -#define GPIO_PADREGL_PAD45FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGL: PAD45FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGL_PAD45STRNG_Pos (10UL) /*!< GPIO PADREGL: PAD45STRNG (Bit 10) */ -#define GPIO_PADREGL_PAD45STRNG_Msk (0x400UL) /*!< GPIO PADREGL: PAD45STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD45INPEN_Pos (9UL) /*!< GPIO PADREGL: PAD45INPEN (Bit 9) */ -#define GPIO_PADREGL_PAD45INPEN_Msk (0x200UL) /*!< GPIO PADREGL: PAD45INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD45PULL_Pos (8UL) /*!< GPIO PADREGL: PAD45PULL (Bit 8) */ -#define GPIO_PADREGL_PAD45PULL_Msk (0x100UL) /*!< GPIO PADREGL: PAD45PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD44FNCSEL_Pos (3UL) /*!< GPIO PADREGL: PAD44FNCSEL (Bit 3) */ -#define GPIO_PADREGL_PAD44FNCSEL_Msk (0x38UL) /*!< GPIO PADREGL: PAD44FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGL_PAD44STRNG_Pos (2UL) /*!< GPIO PADREGL: PAD44STRNG (Bit 2) */ -#define GPIO_PADREGL_PAD44STRNG_Msk (0x4UL) /*!< GPIO PADREGL: PAD44STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD44INPEN_Pos (1UL) /*!< GPIO PADREGL: PAD44INPEN (Bit 1) */ -#define GPIO_PADREGL_PAD44INPEN_Msk (0x2UL) /*!< GPIO PADREGL: PAD44INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGL_PAD44PULL_Pos (0UL) /*!< GPIO PADREGL: PAD44PULL (Bit 0) */ -#define GPIO_PADREGL_PAD44PULL_Msk (0x1UL) /*!< GPIO PADREGL: PAD44PULL (Bitfield-Mask: 0x01) */ -/* ======================================================== PADREGM ======================================================== */ -#define GPIO_PADREGM_PAD49RSEL_Pos (14UL) /*!< GPIO PADREGM: PAD49RSEL (Bit 14) */ -#define GPIO_PADREGM_PAD49RSEL_Msk (0xc000UL) /*!< GPIO PADREGM: PAD49RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGM_PAD49FNCSEL_Pos (11UL) /*!< GPIO PADREGM: PAD49FNCSEL (Bit 11) */ -#define GPIO_PADREGM_PAD49FNCSEL_Msk (0x3800UL) /*!< GPIO PADREGM: PAD49FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGM_PAD49STRNG_Pos (10UL) /*!< GPIO PADREGM: PAD49STRNG (Bit 10) */ -#define GPIO_PADREGM_PAD49STRNG_Msk (0x400UL) /*!< GPIO PADREGM: PAD49STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGM_PAD49INPEN_Pos (9UL) /*!< GPIO PADREGM: PAD49INPEN (Bit 9) */ -#define GPIO_PADREGM_PAD49INPEN_Msk (0x200UL) /*!< GPIO PADREGM: PAD49INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGM_PAD49PULL_Pos (8UL) /*!< GPIO PADREGM: PAD49PULL (Bit 8) */ -#define GPIO_PADREGM_PAD49PULL_Msk (0x100UL) /*!< GPIO PADREGM: PAD49PULL (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGM_PAD48RSEL_Pos (6UL) /*!< GPIO PADREGM: PAD48RSEL (Bit 6) */ -#define GPIO_PADREGM_PAD48RSEL_Msk (0xc0UL) /*!< GPIO PADREGM: PAD48RSEL (Bitfield-Mask: 0x03) */ -#define GPIO_PADREGM_PAD48FNCSEL_Pos (3UL) /*!< GPIO PADREGM: PAD48FNCSEL (Bit 3) */ -#define GPIO_PADREGM_PAD48FNCSEL_Msk (0x38UL) /*!< GPIO PADREGM: PAD48FNCSEL (Bitfield-Mask: 0x07) */ -#define GPIO_PADREGM_PAD48STRNG_Pos (2UL) /*!< GPIO PADREGM: PAD48STRNG (Bit 2) */ -#define GPIO_PADREGM_PAD48STRNG_Msk (0x4UL) /*!< GPIO PADREGM: PAD48STRNG (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGM_PAD48INPEN_Pos (1UL) /*!< GPIO PADREGM: PAD48INPEN (Bit 1) */ -#define GPIO_PADREGM_PAD48INPEN_Msk (0x2UL) /*!< GPIO PADREGM: PAD48INPEN (Bitfield-Mask: 0x01) */ -#define GPIO_PADREGM_PAD48PULL_Pos (0UL) /*!< GPIO PADREGM: PAD48PULL (Bit 0) */ -#define GPIO_PADREGM_PAD48PULL_Msk (0x1UL) /*!< GPIO PADREGM: PAD48PULL (Bitfield-Mask: 0x01) */ -/* ========================================================= CFGA ========================================================== */ -#define GPIO_CFGA_GPIO7INTD_Pos (31UL) /*!< GPIO CFGA: GPIO7INTD (Bit 31) */ -#define GPIO_CFGA_GPIO7INTD_Msk (0x80000000UL) /*!< GPIO CFGA: GPIO7INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO7OUTCFG_Pos (29UL) /*!< GPIO CFGA: GPIO7OUTCFG (Bit 29) */ -#define GPIO_CFGA_GPIO7OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGA: GPIO7OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGA_GPIO7INCFG_Pos (28UL) /*!< GPIO CFGA: GPIO7INCFG (Bit 28) */ -#define GPIO_CFGA_GPIO7INCFG_Msk (0x10000000UL) /*!< GPIO CFGA: GPIO7INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO6INTD_Pos (27UL) /*!< GPIO CFGA: GPIO6INTD (Bit 27) */ -#define GPIO_CFGA_GPIO6INTD_Msk (0x8000000UL) /*!< GPIO CFGA: GPIO6INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO6OUTCFG_Pos (25UL) /*!< GPIO CFGA: GPIO6OUTCFG (Bit 25) */ -#define GPIO_CFGA_GPIO6OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGA: GPIO6OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGA_GPIO6INCFG_Pos (24UL) /*!< GPIO CFGA: GPIO6INCFG (Bit 24) */ -#define GPIO_CFGA_GPIO6INCFG_Msk (0x1000000UL) /*!< GPIO CFGA: GPIO6INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO5INTD_Pos (23UL) /*!< GPIO CFGA: GPIO5INTD (Bit 23) */ -#define GPIO_CFGA_GPIO5INTD_Msk (0x800000UL) /*!< GPIO CFGA: GPIO5INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO5OUTCFG_Pos (21UL) /*!< GPIO CFGA: GPIO5OUTCFG (Bit 21) */ -#define GPIO_CFGA_GPIO5OUTCFG_Msk (0x600000UL) /*!< GPIO CFGA: GPIO5OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGA_GPIO5INCFG_Pos (20UL) /*!< GPIO CFGA: GPIO5INCFG (Bit 20) */ -#define GPIO_CFGA_GPIO5INCFG_Msk (0x100000UL) /*!< GPIO CFGA: GPIO5INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO4INTD_Pos (19UL) /*!< GPIO CFGA: GPIO4INTD (Bit 19) */ -#define GPIO_CFGA_GPIO4INTD_Msk (0x80000UL) /*!< GPIO CFGA: GPIO4INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO4OUTCFG_Pos (17UL) /*!< GPIO CFGA: GPIO4OUTCFG (Bit 17) */ -#define GPIO_CFGA_GPIO4OUTCFG_Msk (0x60000UL) /*!< GPIO CFGA: GPIO4OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGA_GPIO4INCFG_Pos (16UL) /*!< GPIO CFGA: GPIO4INCFG (Bit 16) */ -#define GPIO_CFGA_GPIO4INCFG_Msk (0x10000UL) /*!< GPIO CFGA: GPIO4INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO3INTD_Pos (15UL) /*!< GPIO CFGA: GPIO3INTD (Bit 15) */ -#define GPIO_CFGA_GPIO3INTD_Msk (0x8000UL) /*!< GPIO CFGA: GPIO3INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO3OUTCFG_Pos (13UL) /*!< GPIO CFGA: GPIO3OUTCFG (Bit 13) */ -#define GPIO_CFGA_GPIO3OUTCFG_Msk (0x6000UL) /*!< GPIO CFGA: GPIO3OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGA_GPIO3INCFG_Pos (12UL) /*!< GPIO CFGA: GPIO3INCFG (Bit 12) */ -#define GPIO_CFGA_GPIO3INCFG_Msk (0x1000UL) /*!< GPIO CFGA: GPIO3INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO2INTD_Pos (11UL) /*!< GPIO CFGA: GPIO2INTD (Bit 11) */ -#define GPIO_CFGA_GPIO2INTD_Msk (0x800UL) /*!< GPIO CFGA: GPIO2INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO2OUTCFG_Pos (9UL) /*!< GPIO CFGA: GPIO2OUTCFG (Bit 9) */ -#define GPIO_CFGA_GPIO2OUTCFG_Msk (0x600UL) /*!< GPIO CFGA: GPIO2OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGA_GPIO2INCFG_Pos (8UL) /*!< GPIO CFGA: GPIO2INCFG (Bit 8) */ -#define GPIO_CFGA_GPIO2INCFG_Msk (0x100UL) /*!< GPIO CFGA: GPIO2INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO1INTD_Pos (7UL) /*!< GPIO CFGA: GPIO1INTD (Bit 7) */ -#define GPIO_CFGA_GPIO1INTD_Msk (0x80UL) /*!< GPIO CFGA: GPIO1INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO1OUTCFG_Pos (5UL) /*!< GPIO CFGA: GPIO1OUTCFG (Bit 5) */ -#define GPIO_CFGA_GPIO1OUTCFG_Msk (0x60UL) /*!< GPIO CFGA: GPIO1OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGA_GPIO1INCFG_Pos (4UL) /*!< GPIO CFGA: GPIO1INCFG (Bit 4) */ -#define GPIO_CFGA_GPIO1INCFG_Msk (0x10UL) /*!< GPIO CFGA: GPIO1INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO0INTD_Pos (3UL) /*!< GPIO CFGA: GPIO0INTD (Bit 3) */ -#define GPIO_CFGA_GPIO0INTD_Msk (0x8UL) /*!< GPIO CFGA: GPIO0INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGA_GPIO0OUTCFG_Pos (1UL) /*!< GPIO CFGA: GPIO0OUTCFG (Bit 1) */ -#define GPIO_CFGA_GPIO0OUTCFG_Msk (0x6UL) /*!< GPIO CFGA: GPIO0OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGA_GPIO0INCFG_Pos (0UL) /*!< GPIO CFGA: GPIO0INCFG (Bit 0) */ -#define GPIO_CFGA_GPIO0INCFG_Msk (0x1UL) /*!< GPIO CFGA: GPIO0INCFG (Bitfield-Mask: 0x01) */ -/* ========================================================= CFGB ========================================================== */ -#define GPIO_CFGB_GPIO15INTD_Pos (31UL) /*!< GPIO CFGB: GPIO15INTD (Bit 31) */ -#define GPIO_CFGB_GPIO15INTD_Msk (0x80000000UL) /*!< GPIO CFGB: GPIO15INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO15OUTCFG_Pos (29UL) /*!< GPIO CFGB: GPIO15OUTCFG (Bit 29) */ -#define GPIO_CFGB_GPIO15OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGB: GPIO15OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGB_GPIO15INCFG_Pos (28UL) /*!< GPIO CFGB: GPIO15INCFG (Bit 28) */ -#define GPIO_CFGB_GPIO15INCFG_Msk (0x10000000UL) /*!< GPIO CFGB: GPIO15INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO14INTD_Pos (27UL) /*!< GPIO CFGB: GPIO14INTD (Bit 27) */ -#define GPIO_CFGB_GPIO14INTD_Msk (0x8000000UL) /*!< GPIO CFGB: GPIO14INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO14OUTCFG_Pos (25UL) /*!< GPIO CFGB: GPIO14OUTCFG (Bit 25) */ -#define GPIO_CFGB_GPIO14OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGB: GPIO14OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGB_GPIO14INCFG_Pos (24UL) /*!< GPIO CFGB: GPIO14INCFG (Bit 24) */ -#define GPIO_CFGB_GPIO14INCFG_Msk (0x1000000UL) /*!< GPIO CFGB: GPIO14INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO13INTD_Pos (23UL) /*!< GPIO CFGB: GPIO13INTD (Bit 23) */ -#define GPIO_CFGB_GPIO13INTD_Msk (0x800000UL) /*!< GPIO CFGB: GPIO13INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO13OUTCFG_Pos (21UL) /*!< GPIO CFGB: GPIO13OUTCFG (Bit 21) */ -#define GPIO_CFGB_GPIO13OUTCFG_Msk (0x600000UL) /*!< GPIO CFGB: GPIO13OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGB_GPIO13INCFG_Pos (20UL) /*!< GPIO CFGB: GPIO13INCFG (Bit 20) */ -#define GPIO_CFGB_GPIO13INCFG_Msk (0x100000UL) /*!< GPIO CFGB: GPIO13INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO12INTD_Pos (19UL) /*!< GPIO CFGB: GPIO12INTD (Bit 19) */ -#define GPIO_CFGB_GPIO12INTD_Msk (0x80000UL) /*!< GPIO CFGB: GPIO12INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO12OUTCFG_Pos (17UL) /*!< GPIO CFGB: GPIO12OUTCFG (Bit 17) */ -#define GPIO_CFGB_GPIO12OUTCFG_Msk (0x60000UL) /*!< GPIO CFGB: GPIO12OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGB_GPIO12INCFG_Pos (16UL) /*!< GPIO CFGB: GPIO12INCFG (Bit 16) */ -#define GPIO_CFGB_GPIO12INCFG_Msk (0x10000UL) /*!< GPIO CFGB: GPIO12INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO11INTD_Pos (15UL) /*!< GPIO CFGB: GPIO11INTD (Bit 15) */ -#define GPIO_CFGB_GPIO11INTD_Msk (0x8000UL) /*!< GPIO CFGB: GPIO11INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO11OUTCFG_Pos (13UL) /*!< GPIO CFGB: GPIO11OUTCFG (Bit 13) */ -#define GPIO_CFGB_GPIO11OUTCFG_Msk (0x6000UL) /*!< GPIO CFGB: GPIO11OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGB_GPIO11INCFG_Pos (12UL) /*!< GPIO CFGB: GPIO11INCFG (Bit 12) */ -#define GPIO_CFGB_GPIO11INCFG_Msk (0x1000UL) /*!< GPIO CFGB: GPIO11INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO10INTD_Pos (11UL) /*!< GPIO CFGB: GPIO10INTD (Bit 11) */ -#define GPIO_CFGB_GPIO10INTD_Msk (0x800UL) /*!< GPIO CFGB: GPIO10INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO10OUTCFG_Pos (9UL) /*!< GPIO CFGB: GPIO10OUTCFG (Bit 9) */ -#define GPIO_CFGB_GPIO10OUTCFG_Msk (0x600UL) /*!< GPIO CFGB: GPIO10OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGB_GPIO10INCFG_Pos (8UL) /*!< GPIO CFGB: GPIO10INCFG (Bit 8) */ -#define GPIO_CFGB_GPIO10INCFG_Msk (0x100UL) /*!< GPIO CFGB: GPIO10INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO9INTD_Pos (7UL) /*!< GPIO CFGB: GPIO9INTD (Bit 7) */ -#define GPIO_CFGB_GPIO9INTD_Msk (0x80UL) /*!< GPIO CFGB: GPIO9INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO9OUTCFG_Pos (5UL) /*!< GPIO CFGB: GPIO9OUTCFG (Bit 5) */ -#define GPIO_CFGB_GPIO9OUTCFG_Msk (0x60UL) /*!< GPIO CFGB: GPIO9OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGB_GPIO9INCFG_Pos (4UL) /*!< GPIO CFGB: GPIO9INCFG (Bit 4) */ -#define GPIO_CFGB_GPIO9INCFG_Msk (0x10UL) /*!< GPIO CFGB: GPIO9INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO8INTD_Pos (3UL) /*!< GPIO CFGB: GPIO8INTD (Bit 3) */ -#define GPIO_CFGB_GPIO8INTD_Msk (0x8UL) /*!< GPIO CFGB: GPIO8INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGB_GPIO8OUTCFG_Pos (1UL) /*!< GPIO CFGB: GPIO8OUTCFG (Bit 1) */ -#define GPIO_CFGB_GPIO8OUTCFG_Msk (0x6UL) /*!< GPIO CFGB: GPIO8OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGB_GPIO8INCFG_Pos (0UL) /*!< GPIO CFGB: GPIO8INCFG (Bit 0) */ -#define GPIO_CFGB_GPIO8INCFG_Msk (0x1UL) /*!< GPIO CFGB: GPIO8INCFG (Bitfield-Mask: 0x01) */ -/* ========================================================= CFGC ========================================================== */ -#define GPIO_CFGC_GPIO23INTD_Pos (31UL) /*!< GPIO CFGC: GPIO23INTD (Bit 31) */ -#define GPIO_CFGC_GPIO23INTD_Msk (0x80000000UL) /*!< GPIO CFGC: GPIO23INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO23OUTCFG_Pos (29UL) /*!< GPIO CFGC: GPIO23OUTCFG (Bit 29) */ -#define GPIO_CFGC_GPIO23OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGC: GPIO23OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGC_GPIO23INCFG_Pos (28UL) /*!< GPIO CFGC: GPIO23INCFG (Bit 28) */ -#define GPIO_CFGC_GPIO23INCFG_Msk (0x10000000UL) /*!< GPIO CFGC: GPIO23INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO22INTD_Pos (27UL) /*!< GPIO CFGC: GPIO22INTD (Bit 27) */ -#define GPIO_CFGC_GPIO22INTD_Msk (0x8000000UL) /*!< GPIO CFGC: GPIO22INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO22OUTCFG_Pos (25UL) /*!< GPIO CFGC: GPIO22OUTCFG (Bit 25) */ -#define GPIO_CFGC_GPIO22OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGC: GPIO22OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGC_GPIO22INCFG_Pos (24UL) /*!< GPIO CFGC: GPIO22INCFG (Bit 24) */ -#define GPIO_CFGC_GPIO22INCFG_Msk (0x1000000UL) /*!< GPIO CFGC: GPIO22INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO21INTD_Pos (23UL) /*!< GPIO CFGC: GPIO21INTD (Bit 23) */ -#define GPIO_CFGC_GPIO21INTD_Msk (0x800000UL) /*!< GPIO CFGC: GPIO21INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO21OUTCFG_Pos (21UL) /*!< GPIO CFGC: GPIO21OUTCFG (Bit 21) */ -#define GPIO_CFGC_GPIO21OUTCFG_Msk (0x600000UL) /*!< GPIO CFGC: GPIO21OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGC_GPIO21INCFG_Pos (20UL) /*!< GPIO CFGC: GPIO21INCFG (Bit 20) */ -#define GPIO_CFGC_GPIO21INCFG_Msk (0x100000UL) /*!< GPIO CFGC: GPIO21INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO20INTD_Pos (19UL) /*!< GPIO CFGC: GPIO20INTD (Bit 19) */ -#define GPIO_CFGC_GPIO20INTD_Msk (0x80000UL) /*!< GPIO CFGC: GPIO20INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO20OUTCFG_Pos (17UL) /*!< GPIO CFGC: GPIO20OUTCFG (Bit 17) */ -#define GPIO_CFGC_GPIO20OUTCFG_Msk (0x60000UL) /*!< GPIO CFGC: GPIO20OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGC_GPIO20INCFG_Pos (16UL) /*!< GPIO CFGC: GPIO20INCFG (Bit 16) */ -#define GPIO_CFGC_GPIO20INCFG_Msk (0x10000UL) /*!< GPIO CFGC: GPIO20INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO19INTD_Pos (15UL) /*!< GPIO CFGC: GPIO19INTD (Bit 15) */ -#define GPIO_CFGC_GPIO19INTD_Msk (0x8000UL) /*!< GPIO CFGC: GPIO19INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO19OUTCFG_Pos (13UL) /*!< GPIO CFGC: GPIO19OUTCFG (Bit 13) */ -#define GPIO_CFGC_GPIO19OUTCFG_Msk (0x6000UL) /*!< GPIO CFGC: GPIO19OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGC_GPIO19INCFG_Pos (12UL) /*!< GPIO CFGC: GPIO19INCFG (Bit 12) */ -#define GPIO_CFGC_GPIO19INCFG_Msk (0x1000UL) /*!< GPIO CFGC: GPIO19INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO18INTD_Pos (11UL) /*!< GPIO CFGC: GPIO18INTD (Bit 11) */ -#define GPIO_CFGC_GPIO18INTD_Msk (0x800UL) /*!< GPIO CFGC: GPIO18INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO18OUTCFG_Pos (9UL) /*!< GPIO CFGC: GPIO18OUTCFG (Bit 9) */ -#define GPIO_CFGC_GPIO18OUTCFG_Msk (0x600UL) /*!< GPIO CFGC: GPIO18OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGC_GPIO18INCFG_Pos (8UL) /*!< GPIO CFGC: GPIO18INCFG (Bit 8) */ -#define GPIO_CFGC_GPIO18INCFG_Msk (0x100UL) /*!< GPIO CFGC: GPIO18INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO17INTD_Pos (7UL) /*!< GPIO CFGC: GPIO17INTD (Bit 7) */ -#define GPIO_CFGC_GPIO17INTD_Msk (0x80UL) /*!< GPIO CFGC: GPIO17INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO17OUTCFG_Pos (5UL) /*!< GPIO CFGC: GPIO17OUTCFG (Bit 5) */ -#define GPIO_CFGC_GPIO17OUTCFG_Msk (0x60UL) /*!< GPIO CFGC: GPIO17OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGC_GPIO17INCFG_Pos (4UL) /*!< GPIO CFGC: GPIO17INCFG (Bit 4) */ -#define GPIO_CFGC_GPIO17INCFG_Msk (0x10UL) /*!< GPIO CFGC: GPIO17INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO16INTD_Pos (3UL) /*!< GPIO CFGC: GPIO16INTD (Bit 3) */ -#define GPIO_CFGC_GPIO16INTD_Msk (0x8UL) /*!< GPIO CFGC: GPIO16INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGC_GPIO16OUTCFG_Pos (1UL) /*!< GPIO CFGC: GPIO16OUTCFG (Bit 1) */ -#define GPIO_CFGC_GPIO16OUTCFG_Msk (0x6UL) /*!< GPIO CFGC: GPIO16OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGC_GPIO16INCFG_Pos (0UL) /*!< GPIO CFGC: GPIO16INCFG (Bit 0) */ -#define GPIO_CFGC_GPIO16INCFG_Msk (0x1UL) /*!< GPIO CFGC: GPIO16INCFG (Bitfield-Mask: 0x01) */ -/* ========================================================= CFGD ========================================================== */ -#define GPIO_CFGD_GPIO31INTD_Pos (31UL) /*!< GPIO CFGD: GPIO31INTD (Bit 31) */ -#define GPIO_CFGD_GPIO31INTD_Msk (0x80000000UL) /*!< GPIO CFGD: GPIO31INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO31OUTCFG_Pos (29UL) /*!< GPIO CFGD: GPIO31OUTCFG (Bit 29) */ -#define GPIO_CFGD_GPIO31OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGD: GPIO31OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGD_GPIO31INCFG_Pos (28UL) /*!< GPIO CFGD: GPIO31INCFG (Bit 28) */ -#define GPIO_CFGD_GPIO31INCFG_Msk (0x10000000UL) /*!< GPIO CFGD: GPIO31INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO30INTD_Pos (27UL) /*!< GPIO CFGD: GPIO30INTD (Bit 27) */ -#define GPIO_CFGD_GPIO30INTD_Msk (0x8000000UL) /*!< GPIO CFGD: GPIO30INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO30OUTCFG_Pos (25UL) /*!< GPIO CFGD: GPIO30OUTCFG (Bit 25) */ -#define GPIO_CFGD_GPIO30OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGD: GPIO30OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGD_GPIO30INCFG_Pos (24UL) /*!< GPIO CFGD: GPIO30INCFG (Bit 24) */ -#define GPIO_CFGD_GPIO30INCFG_Msk (0x1000000UL) /*!< GPIO CFGD: GPIO30INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO29INTD_Pos (23UL) /*!< GPIO CFGD: GPIO29INTD (Bit 23) */ -#define GPIO_CFGD_GPIO29INTD_Msk (0x800000UL) /*!< GPIO CFGD: GPIO29INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO29OUTCFG_Pos (21UL) /*!< GPIO CFGD: GPIO29OUTCFG (Bit 21) */ -#define GPIO_CFGD_GPIO29OUTCFG_Msk (0x600000UL) /*!< GPIO CFGD: GPIO29OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGD_GPIO29INCFG_Pos (20UL) /*!< GPIO CFGD: GPIO29INCFG (Bit 20) */ -#define GPIO_CFGD_GPIO29INCFG_Msk (0x100000UL) /*!< GPIO CFGD: GPIO29INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO28INTD_Pos (19UL) /*!< GPIO CFGD: GPIO28INTD (Bit 19) */ -#define GPIO_CFGD_GPIO28INTD_Msk (0x80000UL) /*!< GPIO CFGD: GPIO28INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO28OUTCFG_Pos (17UL) /*!< GPIO CFGD: GPIO28OUTCFG (Bit 17) */ -#define GPIO_CFGD_GPIO28OUTCFG_Msk (0x60000UL) /*!< GPIO CFGD: GPIO28OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGD_GPIO28INCFG_Pos (16UL) /*!< GPIO CFGD: GPIO28INCFG (Bit 16) */ -#define GPIO_CFGD_GPIO28INCFG_Msk (0x10000UL) /*!< GPIO CFGD: GPIO28INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO27INTD_Pos (15UL) /*!< GPIO CFGD: GPIO27INTD (Bit 15) */ -#define GPIO_CFGD_GPIO27INTD_Msk (0x8000UL) /*!< GPIO CFGD: GPIO27INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO27OUTCFG_Pos (13UL) /*!< GPIO CFGD: GPIO27OUTCFG (Bit 13) */ -#define GPIO_CFGD_GPIO27OUTCFG_Msk (0x6000UL) /*!< GPIO CFGD: GPIO27OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGD_GPIO27INCFG_Pos (12UL) /*!< GPIO CFGD: GPIO27INCFG (Bit 12) */ -#define GPIO_CFGD_GPIO27INCFG_Msk (0x1000UL) /*!< GPIO CFGD: GPIO27INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO26INTD_Pos (11UL) /*!< GPIO CFGD: GPIO26INTD (Bit 11) */ -#define GPIO_CFGD_GPIO26INTD_Msk (0x800UL) /*!< GPIO CFGD: GPIO26INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO26OUTCFG_Pos (9UL) /*!< GPIO CFGD: GPIO26OUTCFG (Bit 9) */ -#define GPIO_CFGD_GPIO26OUTCFG_Msk (0x600UL) /*!< GPIO CFGD: GPIO26OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGD_GPIO26INCFG_Pos (8UL) /*!< GPIO CFGD: GPIO26INCFG (Bit 8) */ -#define GPIO_CFGD_GPIO26INCFG_Msk (0x100UL) /*!< GPIO CFGD: GPIO26INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO25INTD_Pos (7UL) /*!< GPIO CFGD: GPIO25INTD (Bit 7) */ -#define GPIO_CFGD_GPIO25INTD_Msk (0x80UL) /*!< GPIO CFGD: GPIO25INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO25OUTCFG_Pos (5UL) /*!< GPIO CFGD: GPIO25OUTCFG (Bit 5) */ -#define GPIO_CFGD_GPIO25OUTCFG_Msk (0x60UL) /*!< GPIO CFGD: GPIO25OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGD_GPIO25INCFG_Pos (4UL) /*!< GPIO CFGD: GPIO25INCFG (Bit 4) */ -#define GPIO_CFGD_GPIO25INCFG_Msk (0x10UL) /*!< GPIO CFGD: GPIO25INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO24INTD_Pos (3UL) /*!< GPIO CFGD: GPIO24INTD (Bit 3) */ -#define GPIO_CFGD_GPIO24INTD_Msk (0x8UL) /*!< GPIO CFGD: GPIO24INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGD_GPIO24OUTCFG_Pos (1UL) /*!< GPIO CFGD: GPIO24OUTCFG (Bit 1) */ -#define GPIO_CFGD_GPIO24OUTCFG_Msk (0x6UL) /*!< GPIO CFGD: GPIO24OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGD_GPIO24INCFG_Pos (0UL) /*!< GPIO CFGD: GPIO24INCFG (Bit 0) */ -#define GPIO_CFGD_GPIO24INCFG_Msk (0x1UL) /*!< GPIO CFGD: GPIO24INCFG (Bitfield-Mask: 0x01) */ -/* ========================================================= CFGE ========================================================== */ -#define GPIO_CFGE_GPIO39INTD_Pos (31UL) /*!< GPIO CFGE: GPIO39INTD (Bit 31) */ -#define GPIO_CFGE_GPIO39INTD_Msk (0x80000000UL) /*!< GPIO CFGE: GPIO39INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO39OUTCFG_Pos (29UL) /*!< GPIO CFGE: GPIO39OUTCFG (Bit 29) */ -#define GPIO_CFGE_GPIO39OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGE: GPIO39OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGE_GPIO39INCFG_Pos (28UL) /*!< GPIO CFGE: GPIO39INCFG (Bit 28) */ -#define GPIO_CFGE_GPIO39INCFG_Msk (0x10000000UL) /*!< GPIO CFGE: GPIO39INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO38INTD_Pos (27UL) /*!< GPIO CFGE: GPIO38INTD (Bit 27) */ -#define GPIO_CFGE_GPIO38INTD_Msk (0x8000000UL) /*!< GPIO CFGE: GPIO38INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO38OUTCFG_Pos (25UL) /*!< GPIO CFGE: GPIO38OUTCFG (Bit 25) */ -#define GPIO_CFGE_GPIO38OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGE: GPIO38OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGE_GPIO38INCFG_Pos (24UL) /*!< GPIO CFGE: GPIO38INCFG (Bit 24) */ -#define GPIO_CFGE_GPIO38INCFG_Msk (0x1000000UL) /*!< GPIO CFGE: GPIO38INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO37INTD_Pos (23UL) /*!< GPIO CFGE: GPIO37INTD (Bit 23) */ -#define GPIO_CFGE_GPIO37INTD_Msk (0x800000UL) /*!< GPIO CFGE: GPIO37INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO37OUTCFG_Pos (21UL) /*!< GPIO CFGE: GPIO37OUTCFG (Bit 21) */ -#define GPIO_CFGE_GPIO37OUTCFG_Msk (0x600000UL) /*!< GPIO CFGE: GPIO37OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGE_GPIO37INCFG_Pos (20UL) /*!< GPIO CFGE: GPIO37INCFG (Bit 20) */ -#define GPIO_CFGE_GPIO37INCFG_Msk (0x100000UL) /*!< GPIO CFGE: GPIO37INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO36INTD_Pos (19UL) /*!< GPIO CFGE: GPIO36INTD (Bit 19) */ -#define GPIO_CFGE_GPIO36INTD_Msk (0x80000UL) /*!< GPIO CFGE: GPIO36INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO36OUTCFG_Pos (17UL) /*!< GPIO CFGE: GPIO36OUTCFG (Bit 17) */ -#define GPIO_CFGE_GPIO36OUTCFG_Msk (0x60000UL) /*!< GPIO CFGE: GPIO36OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGE_GPIO36INCFG_Pos (16UL) /*!< GPIO CFGE: GPIO36INCFG (Bit 16) */ -#define GPIO_CFGE_GPIO36INCFG_Msk (0x10000UL) /*!< GPIO CFGE: GPIO36INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO35INTD_Pos (15UL) /*!< GPIO CFGE: GPIO35INTD (Bit 15) */ -#define GPIO_CFGE_GPIO35INTD_Msk (0x8000UL) /*!< GPIO CFGE: GPIO35INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO35OUTCFG_Pos (13UL) /*!< GPIO CFGE: GPIO35OUTCFG (Bit 13) */ -#define GPIO_CFGE_GPIO35OUTCFG_Msk (0x6000UL) /*!< GPIO CFGE: GPIO35OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGE_GPIO35INCFG_Pos (12UL) /*!< GPIO CFGE: GPIO35INCFG (Bit 12) */ -#define GPIO_CFGE_GPIO35INCFG_Msk (0x1000UL) /*!< GPIO CFGE: GPIO35INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO34INTD_Pos (11UL) /*!< GPIO CFGE: GPIO34INTD (Bit 11) */ -#define GPIO_CFGE_GPIO34INTD_Msk (0x800UL) /*!< GPIO CFGE: GPIO34INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO34OUTCFG_Pos (9UL) /*!< GPIO CFGE: GPIO34OUTCFG (Bit 9) */ -#define GPIO_CFGE_GPIO34OUTCFG_Msk (0x600UL) /*!< GPIO CFGE: GPIO34OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGE_GPIO34INCFG_Pos (8UL) /*!< GPIO CFGE: GPIO34INCFG (Bit 8) */ -#define GPIO_CFGE_GPIO34INCFG_Msk (0x100UL) /*!< GPIO CFGE: GPIO34INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO33INTD_Pos (7UL) /*!< GPIO CFGE: GPIO33INTD (Bit 7) */ -#define GPIO_CFGE_GPIO33INTD_Msk (0x80UL) /*!< GPIO CFGE: GPIO33INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO33OUTCFG_Pos (5UL) /*!< GPIO CFGE: GPIO33OUTCFG (Bit 5) */ -#define GPIO_CFGE_GPIO33OUTCFG_Msk (0x60UL) /*!< GPIO CFGE: GPIO33OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGE_GPIO33INCFG_Pos (4UL) /*!< GPIO CFGE: GPIO33INCFG (Bit 4) */ -#define GPIO_CFGE_GPIO33INCFG_Msk (0x10UL) /*!< GPIO CFGE: GPIO33INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO32INTD_Pos (3UL) /*!< GPIO CFGE: GPIO32INTD (Bit 3) */ -#define GPIO_CFGE_GPIO32INTD_Msk (0x8UL) /*!< GPIO CFGE: GPIO32INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGE_GPIO32OUTCFG_Pos (1UL) /*!< GPIO CFGE: GPIO32OUTCFG (Bit 1) */ -#define GPIO_CFGE_GPIO32OUTCFG_Msk (0x6UL) /*!< GPIO CFGE: GPIO32OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGE_GPIO32INCFG_Pos (0UL) /*!< GPIO CFGE: GPIO32INCFG (Bit 0) */ -#define GPIO_CFGE_GPIO32INCFG_Msk (0x1UL) /*!< GPIO CFGE: GPIO32INCFG (Bitfield-Mask: 0x01) */ -/* ========================================================= CFGF ========================================================== */ -#define GPIO_CFGF_GPIO47INTD_Pos (31UL) /*!< GPIO CFGF: GPIO47INTD (Bit 31) */ -#define GPIO_CFGF_GPIO47INTD_Msk (0x80000000UL) /*!< GPIO CFGF: GPIO47INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO47OUTCFG_Pos (29UL) /*!< GPIO CFGF: GPIO47OUTCFG (Bit 29) */ -#define GPIO_CFGF_GPIO47OUTCFG_Msk (0x60000000UL) /*!< GPIO CFGF: GPIO47OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGF_GPIO47INCFG_Pos (28UL) /*!< GPIO CFGF: GPIO47INCFG (Bit 28) */ -#define GPIO_CFGF_GPIO47INCFG_Msk (0x10000000UL) /*!< GPIO CFGF: GPIO47INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO46INTD_Pos (27UL) /*!< GPIO CFGF: GPIO46INTD (Bit 27) */ -#define GPIO_CFGF_GPIO46INTD_Msk (0x8000000UL) /*!< GPIO CFGF: GPIO46INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO46OUTCFG_Pos (25UL) /*!< GPIO CFGF: GPIO46OUTCFG (Bit 25) */ -#define GPIO_CFGF_GPIO46OUTCFG_Msk (0x6000000UL) /*!< GPIO CFGF: GPIO46OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGF_GPIO46INCFG_Pos (24UL) /*!< GPIO CFGF: GPIO46INCFG (Bit 24) */ -#define GPIO_CFGF_GPIO46INCFG_Msk (0x1000000UL) /*!< GPIO CFGF: GPIO46INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO45INTD_Pos (23UL) /*!< GPIO CFGF: GPIO45INTD (Bit 23) */ -#define GPIO_CFGF_GPIO45INTD_Msk (0x800000UL) /*!< GPIO CFGF: GPIO45INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO45OUTCFG_Pos (21UL) /*!< GPIO CFGF: GPIO45OUTCFG (Bit 21) */ -#define GPIO_CFGF_GPIO45OUTCFG_Msk (0x600000UL) /*!< GPIO CFGF: GPIO45OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGF_GPIO45INCFG_Pos (20UL) /*!< GPIO CFGF: GPIO45INCFG (Bit 20) */ -#define GPIO_CFGF_GPIO45INCFG_Msk (0x100000UL) /*!< GPIO CFGF: GPIO45INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO44INTD_Pos (19UL) /*!< GPIO CFGF: GPIO44INTD (Bit 19) */ -#define GPIO_CFGF_GPIO44INTD_Msk (0x80000UL) /*!< GPIO CFGF: GPIO44INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO44OUTCFG_Pos (17UL) /*!< GPIO CFGF: GPIO44OUTCFG (Bit 17) */ -#define GPIO_CFGF_GPIO44OUTCFG_Msk (0x60000UL) /*!< GPIO CFGF: GPIO44OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGF_GPIO44INCFG_Pos (16UL) /*!< GPIO CFGF: GPIO44INCFG (Bit 16) */ -#define GPIO_CFGF_GPIO44INCFG_Msk (0x10000UL) /*!< GPIO CFGF: GPIO44INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO43INTD_Pos (15UL) /*!< GPIO CFGF: GPIO43INTD (Bit 15) */ -#define GPIO_CFGF_GPIO43INTD_Msk (0x8000UL) /*!< GPIO CFGF: GPIO43INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO43OUTCFG_Pos (13UL) /*!< GPIO CFGF: GPIO43OUTCFG (Bit 13) */ -#define GPIO_CFGF_GPIO43OUTCFG_Msk (0x6000UL) /*!< GPIO CFGF: GPIO43OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGF_GPIO43INCFG_Pos (12UL) /*!< GPIO CFGF: GPIO43INCFG (Bit 12) */ -#define GPIO_CFGF_GPIO43INCFG_Msk (0x1000UL) /*!< GPIO CFGF: GPIO43INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO42INTD_Pos (11UL) /*!< GPIO CFGF: GPIO42INTD (Bit 11) */ -#define GPIO_CFGF_GPIO42INTD_Msk (0x800UL) /*!< GPIO CFGF: GPIO42INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO42OUTCFG_Pos (9UL) /*!< GPIO CFGF: GPIO42OUTCFG (Bit 9) */ -#define GPIO_CFGF_GPIO42OUTCFG_Msk (0x600UL) /*!< GPIO CFGF: GPIO42OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGF_GPIO42INCFG_Pos (8UL) /*!< GPIO CFGF: GPIO42INCFG (Bit 8) */ -#define GPIO_CFGF_GPIO42INCFG_Msk (0x100UL) /*!< GPIO CFGF: GPIO42INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO41INTD_Pos (7UL) /*!< GPIO CFGF: GPIO41INTD (Bit 7) */ -#define GPIO_CFGF_GPIO41INTD_Msk (0x80UL) /*!< GPIO CFGF: GPIO41INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO41OUTCFG_Pos (5UL) /*!< GPIO CFGF: GPIO41OUTCFG (Bit 5) */ -#define GPIO_CFGF_GPIO41OUTCFG_Msk (0x60UL) /*!< GPIO CFGF: GPIO41OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGF_GPIO41INCFG_Pos (4UL) /*!< GPIO CFGF: GPIO41INCFG (Bit 4) */ -#define GPIO_CFGF_GPIO41INCFG_Msk (0x10UL) /*!< GPIO CFGF: GPIO41INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO40INTD_Pos (3UL) /*!< GPIO CFGF: GPIO40INTD (Bit 3) */ -#define GPIO_CFGF_GPIO40INTD_Msk (0x8UL) /*!< GPIO CFGF: GPIO40INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGF_GPIO40OUTCFG_Pos (1UL) /*!< GPIO CFGF: GPIO40OUTCFG (Bit 1) */ -#define GPIO_CFGF_GPIO40OUTCFG_Msk (0x6UL) /*!< GPIO CFGF: GPIO40OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGF_GPIO40INCFG_Pos (0UL) /*!< GPIO CFGF: GPIO40INCFG (Bit 0) */ -#define GPIO_CFGF_GPIO40INCFG_Msk (0x1UL) /*!< GPIO CFGF: GPIO40INCFG (Bitfield-Mask: 0x01) */ -/* ========================================================= CFGG ========================================================== */ -#define GPIO_CFGG_GPIO49INTD_Pos (7UL) /*!< GPIO CFGG: GPIO49INTD (Bit 7) */ -#define GPIO_CFGG_GPIO49INTD_Msk (0x80UL) /*!< GPIO CFGG: GPIO49INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGG_GPIO49OUTCFG_Pos (5UL) /*!< GPIO CFGG: GPIO49OUTCFG (Bit 5) */ -#define GPIO_CFGG_GPIO49OUTCFG_Msk (0x60UL) /*!< GPIO CFGG: GPIO49OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGG_GPIO49INCFG_Pos (4UL) /*!< GPIO CFGG: GPIO49INCFG (Bit 4) */ -#define GPIO_CFGG_GPIO49INCFG_Msk (0x10UL) /*!< GPIO CFGG: GPIO49INCFG (Bitfield-Mask: 0x01) */ -#define GPIO_CFGG_GPIO48INTD_Pos (3UL) /*!< GPIO CFGG: GPIO48INTD (Bit 3) */ -#define GPIO_CFGG_GPIO48INTD_Msk (0x8UL) /*!< GPIO CFGG: GPIO48INTD (Bitfield-Mask: 0x01) */ -#define GPIO_CFGG_GPIO48OUTCFG_Pos (1UL) /*!< GPIO CFGG: GPIO48OUTCFG (Bit 1) */ -#define GPIO_CFGG_GPIO48OUTCFG_Msk (0x6UL) /*!< GPIO CFGG: GPIO48OUTCFG (Bitfield-Mask: 0x03) */ -#define GPIO_CFGG_GPIO48INCFG_Pos (0UL) /*!< GPIO CFGG: GPIO48INCFG (Bit 0) */ -#define GPIO_CFGG_GPIO48INCFG_Msk (0x1UL) /*!< GPIO CFGG: GPIO48INCFG (Bitfield-Mask: 0x01) */ -/* ======================================================== PADKEY ========================================================= */ -#define GPIO_PADKEY_PADKEY_Pos (0UL) /*!< GPIO PADKEY: PADKEY (Bit 0) */ -#define GPIO_PADKEY_PADKEY_Msk (0xffffffffUL) /*!< GPIO PADKEY: PADKEY (Bitfield-Mask: 0xffffffff) */ -/* ========================================================== RDA ========================================================== */ -#define GPIO_RDA_RDA_Pos (0UL) /*!< GPIO RDA: RDA (Bit 0) */ -#define GPIO_RDA_RDA_Msk (0xffffffffUL) /*!< GPIO RDA: RDA (Bitfield-Mask: 0xffffffff) */ -/* ========================================================== RDB ========================================================== */ -#define GPIO_RDB_RDB_Pos (0UL) /*!< GPIO RDB: RDB (Bit 0) */ -#define GPIO_RDB_RDB_Msk (0x3ffffUL) /*!< GPIO RDB: RDB (Bitfield-Mask: 0x3ffff) */ -/* ========================================================== WTA ========================================================== */ -#define GPIO_WTA_WTA_Pos (0UL) /*!< GPIO WTA: WTA (Bit 0) */ -#define GPIO_WTA_WTA_Msk (0xffffffffUL) /*!< GPIO WTA: WTA (Bitfield-Mask: 0xffffffff) */ -/* ========================================================== WTB ========================================================== */ -#define GPIO_WTB_WTB_Pos (0UL) /*!< GPIO WTB: WTB (Bit 0) */ -#define GPIO_WTB_WTB_Msk (0x3ffffUL) /*!< GPIO WTB: WTB (Bitfield-Mask: 0x3ffff) */ -/* ========================================================= WTSA ========================================================== */ -#define GPIO_WTSA_WTSA_Pos (0UL) /*!< GPIO WTSA: WTSA (Bit 0) */ -#define GPIO_WTSA_WTSA_Msk (0xffffffffUL) /*!< GPIO WTSA: WTSA (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= WTSB ========================================================== */ -#define GPIO_WTSB_WTSB_Pos (0UL) /*!< GPIO WTSB: WTSB (Bit 0) */ -#define GPIO_WTSB_WTSB_Msk (0x3ffffUL) /*!< GPIO WTSB: WTSB (Bitfield-Mask: 0x3ffff) */ -/* ========================================================= WTCA ========================================================== */ -#define GPIO_WTCA_WTCA_Pos (0UL) /*!< GPIO WTCA: WTCA (Bit 0) */ -#define GPIO_WTCA_WTCA_Msk (0xffffffffUL) /*!< GPIO WTCA: WTCA (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= WTCB ========================================================== */ -#define GPIO_WTCB_WTCB_Pos (0UL) /*!< GPIO WTCB: WTCB (Bit 0) */ -#define GPIO_WTCB_WTCB_Msk (0x3ffffUL) /*!< GPIO WTCB: WTCB (Bitfield-Mask: 0x3ffff) */ -/* ========================================================== ENA ========================================================== */ -#define GPIO_ENA_ENA_Pos (0UL) /*!< GPIO ENA: ENA (Bit 0) */ -#define GPIO_ENA_ENA_Msk (0xffffffffUL) /*!< GPIO ENA: ENA (Bitfield-Mask: 0xffffffff) */ -/* ========================================================== ENB ========================================================== */ -#define GPIO_ENB_ENB_Pos (0UL) /*!< GPIO ENB: ENB (Bit 0) */ -#define GPIO_ENB_ENB_Msk (0x3ffffUL) /*!< GPIO ENB: ENB (Bitfield-Mask: 0x3ffff) */ -/* ========================================================= ENSA ========================================================== */ -#define GPIO_ENSA_ENSA_Pos (0UL) /*!< GPIO ENSA: ENSA (Bit 0) */ -#define GPIO_ENSA_ENSA_Msk (0xffffffffUL) /*!< GPIO ENSA: ENSA (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= ENSB ========================================================== */ -#define GPIO_ENSB_ENSB_Pos (0UL) /*!< GPIO ENSB: ENSB (Bit 0) */ -#define GPIO_ENSB_ENSB_Msk (0x3ffffUL) /*!< GPIO ENSB: ENSB (Bitfield-Mask: 0x3ffff) */ -/* ========================================================= ENCA ========================================================== */ -#define GPIO_ENCA_ENCA_Pos (0UL) /*!< GPIO ENCA: ENCA (Bit 0) */ -#define GPIO_ENCA_ENCA_Msk (0xffffffffUL) /*!< GPIO ENCA: ENCA (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= ENCB ========================================================== */ -#define GPIO_ENCB_ENCB_Pos (0UL) /*!< GPIO ENCB: ENCB (Bit 0) */ -#define GPIO_ENCB_ENCB_Msk (0x3ffffUL) /*!< GPIO ENCB: ENCB (Bitfield-Mask: 0x3ffff) */ -/* ======================================================== STMRCAP ======================================================== */ -#define GPIO_STMRCAP_STPOL3_Pos (30UL) /*!< GPIO STMRCAP: STPOL3 (Bit 30) */ -#define GPIO_STMRCAP_STPOL3_Msk (0x40000000UL) /*!< GPIO STMRCAP: STPOL3 (Bitfield-Mask: 0x01) */ -#define GPIO_STMRCAP_STSEL3_Pos (24UL) /*!< GPIO STMRCAP: STSEL3 (Bit 24) */ -#define GPIO_STMRCAP_STSEL3_Msk (0x3f000000UL) /*!< GPIO STMRCAP: STSEL3 (Bitfield-Mask: 0x3f) */ -#define GPIO_STMRCAP_STPOL2_Pos (22UL) /*!< GPIO STMRCAP: STPOL2 (Bit 22) */ -#define GPIO_STMRCAP_STPOL2_Msk (0x400000UL) /*!< GPIO STMRCAP: STPOL2 (Bitfield-Mask: 0x01) */ -#define GPIO_STMRCAP_STSEL2_Pos (16UL) /*!< GPIO STMRCAP: STSEL2 (Bit 16) */ -#define GPIO_STMRCAP_STSEL2_Msk (0x3f0000UL) /*!< GPIO STMRCAP: STSEL2 (Bitfield-Mask: 0x3f) */ -#define GPIO_STMRCAP_STPOL1_Pos (14UL) /*!< GPIO STMRCAP: STPOL1 (Bit 14) */ -#define GPIO_STMRCAP_STPOL1_Msk (0x4000UL) /*!< GPIO STMRCAP: STPOL1 (Bitfield-Mask: 0x01) */ -#define GPIO_STMRCAP_STSEL1_Pos (8UL) /*!< GPIO STMRCAP: STSEL1 (Bit 8) */ -#define GPIO_STMRCAP_STSEL1_Msk (0x3f00UL) /*!< GPIO STMRCAP: STSEL1 (Bitfield-Mask: 0x3f) */ -#define GPIO_STMRCAP_STPOL0_Pos (6UL) /*!< GPIO STMRCAP: STPOL0 (Bit 6) */ -#define GPIO_STMRCAP_STPOL0_Msk (0x40UL) /*!< GPIO STMRCAP: STPOL0 (Bitfield-Mask: 0x01) */ -#define GPIO_STMRCAP_STSEL0_Pos (0UL) /*!< GPIO STMRCAP: STSEL0 (Bit 0) */ -#define GPIO_STMRCAP_STSEL0_Msk (0x3fUL) /*!< GPIO STMRCAP: STSEL0 (Bitfield-Mask: 0x3f) */ -/* ======================================================== IOM0IRQ ======================================================== */ -#define GPIO_IOM0IRQ_IOM0IRQ_Pos (0UL) /*!< GPIO IOM0IRQ: IOM0IRQ (Bit 0) */ -#define GPIO_IOM0IRQ_IOM0IRQ_Msk (0x3fUL) /*!< GPIO IOM0IRQ: IOM0IRQ (Bitfield-Mask: 0x3f) */ -/* ======================================================== IOM1IRQ ======================================================== */ -#define GPIO_IOM1IRQ_IOM1IRQ_Pos (0UL) /*!< GPIO IOM1IRQ: IOM1IRQ (Bit 0) */ -#define GPIO_IOM1IRQ_IOM1IRQ_Msk (0x3fUL) /*!< GPIO IOM1IRQ: IOM1IRQ (Bitfield-Mask: 0x3f) */ -/* ======================================================== IOM2IRQ ======================================================== */ -#define GPIO_IOM2IRQ_IOM2IRQ_Pos (0UL) /*!< GPIO IOM2IRQ: IOM2IRQ (Bit 0) */ -#define GPIO_IOM2IRQ_IOM2IRQ_Msk (0x3fUL) /*!< GPIO IOM2IRQ: IOM2IRQ (Bitfield-Mask: 0x3f) */ -/* ======================================================== IOM3IRQ ======================================================== */ -#define GPIO_IOM3IRQ_IOM3IRQ_Pos (0UL) /*!< GPIO IOM3IRQ: IOM3IRQ (Bit 0) */ -#define GPIO_IOM3IRQ_IOM3IRQ_Msk (0x3fUL) /*!< GPIO IOM3IRQ: IOM3IRQ (Bitfield-Mask: 0x3f) */ -/* ======================================================== IOM4IRQ ======================================================== */ -#define GPIO_IOM4IRQ_IOM4IRQ_Pos (0UL) /*!< GPIO IOM4IRQ: IOM4IRQ (Bit 0) */ -#define GPIO_IOM4IRQ_IOM4IRQ_Msk (0x3fUL) /*!< GPIO IOM4IRQ: IOM4IRQ (Bitfield-Mask: 0x3f) */ -/* ======================================================== IOM5IRQ ======================================================== */ -#define GPIO_IOM5IRQ_IOM5IRQ_Pos (0UL) /*!< GPIO IOM5IRQ: IOM5IRQ (Bit 0) */ -#define GPIO_IOM5IRQ_IOM5IRQ_Msk (0x3fUL) /*!< GPIO IOM5IRQ: IOM5IRQ (Bitfield-Mask: 0x3f) */ -/* ======================================================= BLEIFIRQ ======================================================== */ -#define GPIO_BLEIFIRQ_BLEIFIRQ_Pos (0UL) /*!< GPIO BLEIFIRQ: BLEIFIRQ (Bit 0) */ -#define GPIO_BLEIFIRQ_BLEIFIRQ_Msk (0x3fUL) /*!< GPIO BLEIFIRQ: BLEIFIRQ (Bitfield-Mask: 0x3f) */ -/* ======================================================== GPIOOBS ======================================================== */ -#define GPIO_GPIOOBS_OBS_DATA_Pos (0UL) /*!< GPIO GPIOOBS: OBS_DATA (Bit 0) */ -#define GPIO_GPIOOBS_OBS_DATA_Msk (0xffffUL) /*!< GPIO GPIOOBS: OBS_DATA (Bitfield-Mask: 0xffff) */ -/* ====================================================== ALTPADCFGA ======================================================= */ -#define GPIO_ALTPADCFGA_PAD3_SR_Pos (28UL) /*!< GPIO ALTPADCFGA: PAD3_SR (Bit 28) */ -#define GPIO_ALTPADCFGA_PAD3_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGA: PAD3_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGA_PAD3_DS1_Pos (24UL) /*!< GPIO ALTPADCFGA: PAD3_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGA_PAD3_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGA: PAD3_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGA_PAD2_SR_Pos (20UL) /*!< GPIO ALTPADCFGA: PAD2_SR (Bit 20) */ -#define GPIO_ALTPADCFGA_PAD2_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGA: PAD2_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGA_PAD2_DS1_Pos (16UL) /*!< GPIO ALTPADCFGA: PAD2_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGA_PAD2_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGA: PAD2_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGA_PAD1_SR_Pos (12UL) /*!< GPIO ALTPADCFGA: PAD1_SR (Bit 12) */ -#define GPIO_ALTPADCFGA_PAD1_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGA: PAD1_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGA_PAD1_DS1_Pos (8UL) /*!< GPIO ALTPADCFGA: PAD1_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGA_PAD1_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGA: PAD1_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGA_PAD0_SR_Pos (4UL) /*!< GPIO ALTPADCFGA: PAD0_SR (Bit 4) */ -#define GPIO_ALTPADCFGA_PAD0_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGA: PAD0_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGA_PAD0_DS1_Pos (0UL) /*!< GPIO ALTPADCFGA: PAD0_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGA_PAD0_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGA: PAD0_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGB ======================================================= */ -#define GPIO_ALTPADCFGB_PAD7_SR_Pos (28UL) /*!< GPIO ALTPADCFGB: PAD7_SR (Bit 28) */ -#define GPIO_ALTPADCFGB_PAD7_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGB: PAD7_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGB_PAD7_DS1_Pos (24UL) /*!< GPIO ALTPADCFGB: PAD7_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGB_PAD7_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGB: PAD7_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGB_PAD6_SR_Pos (20UL) /*!< GPIO ALTPADCFGB: PAD6_SR (Bit 20) */ -#define GPIO_ALTPADCFGB_PAD6_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGB: PAD6_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGB_PAD6_DS1_Pos (16UL) /*!< GPIO ALTPADCFGB: PAD6_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGB_PAD6_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGB: PAD6_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGB_PAD5_SR_Pos (12UL) /*!< GPIO ALTPADCFGB: PAD5_SR (Bit 12) */ -#define GPIO_ALTPADCFGB_PAD5_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGB: PAD5_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGB_PAD5_DS1_Pos (8UL) /*!< GPIO ALTPADCFGB: PAD5_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGB_PAD5_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGB: PAD5_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGB_PAD4_SR_Pos (4UL) /*!< GPIO ALTPADCFGB: PAD4_SR (Bit 4) */ -#define GPIO_ALTPADCFGB_PAD4_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGB: PAD4_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGB_PAD4_DS1_Pos (0UL) /*!< GPIO ALTPADCFGB: PAD4_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGB_PAD4_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGB: PAD4_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGC ======================================================= */ -#define GPIO_ALTPADCFGC_PAD11_SR_Pos (28UL) /*!< GPIO ALTPADCFGC: PAD11_SR (Bit 28) */ -#define GPIO_ALTPADCFGC_PAD11_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGC: PAD11_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGC_PAD11_DS1_Pos (24UL) /*!< GPIO ALTPADCFGC: PAD11_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGC_PAD11_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGC: PAD11_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGC_PAD10_SR_Pos (20UL) /*!< GPIO ALTPADCFGC: PAD10_SR (Bit 20) */ -#define GPIO_ALTPADCFGC_PAD10_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGC: PAD10_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGC_PAD10_DS1_Pos (16UL) /*!< GPIO ALTPADCFGC: PAD10_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGC_PAD10_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGC: PAD10_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGC_PAD9_SR_Pos (12UL) /*!< GPIO ALTPADCFGC: PAD9_SR (Bit 12) */ -#define GPIO_ALTPADCFGC_PAD9_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGC: PAD9_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGC_PAD9_DS1_Pos (8UL) /*!< GPIO ALTPADCFGC: PAD9_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGC_PAD9_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGC: PAD9_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGC_PAD8_SR_Pos (4UL) /*!< GPIO ALTPADCFGC: PAD8_SR (Bit 4) */ -#define GPIO_ALTPADCFGC_PAD8_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGC: PAD8_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGC_PAD8_DS1_Pos (0UL) /*!< GPIO ALTPADCFGC: PAD8_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGC_PAD8_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGC: PAD8_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGD ======================================================= */ -#define GPIO_ALTPADCFGD_PAD15_SR_Pos (28UL) /*!< GPIO ALTPADCFGD: PAD15_SR (Bit 28) */ -#define GPIO_ALTPADCFGD_PAD15_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGD: PAD15_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGD_PAD15_DS1_Pos (24UL) /*!< GPIO ALTPADCFGD: PAD15_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGD_PAD15_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGD: PAD15_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGD_PAD14_SR_Pos (20UL) /*!< GPIO ALTPADCFGD: PAD14_SR (Bit 20) */ -#define GPIO_ALTPADCFGD_PAD14_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGD: PAD14_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGD_PAD14_DS1_Pos (16UL) /*!< GPIO ALTPADCFGD: PAD14_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGD_PAD14_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGD: PAD14_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGD_PAD13_SR_Pos (12UL) /*!< GPIO ALTPADCFGD: PAD13_SR (Bit 12) */ -#define GPIO_ALTPADCFGD_PAD13_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGD: PAD13_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGD_PAD13_DS1_Pos (8UL) /*!< GPIO ALTPADCFGD: PAD13_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGD_PAD13_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGD: PAD13_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGD_PAD12_SR_Pos (4UL) /*!< GPIO ALTPADCFGD: PAD12_SR (Bit 4) */ -#define GPIO_ALTPADCFGD_PAD12_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGD: PAD12_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGD_PAD12_DS1_Pos (0UL) /*!< GPIO ALTPADCFGD: PAD12_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGD_PAD12_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGD: PAD12_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGE ======================================================= */ -#define GPIO_ALTPADCFGE_PAD19_SR_Pos (28UL) /*!< GPIO ALTPADCFGE: PAD19_SR (Bit 28) */ -#define GPIO_ALTPADCFGE_PAD19_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGE: PAD19_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGE_PAD19_DS1_Pos (24UL) /*!< GPIO ALTPADCFGE: PAD19_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGE_PAD19_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGE: PAD19_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGE_PAD18_SR_Pos (20UL) /*!< GPIO ALTPADCFGE: PAD18_SR (Bit 20) */ -#define GPIO_ALTPADCFGE_PAD18_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGE: PAD18_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGE_PAD18_DS1_Pos (16UL) /*!< GPIO ALTPADCFGE: PAD18_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGE_PAD18_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGE: PAD18_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGE_PAD17_SR_Pos (12UL) /*!< GPIO ALTPADCFGE: PAD17_SR (Bit 12) */ -#define GPIO_ALTPADCFGE_PAD17_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGE: PAD17_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGE_PAD17_DS1_Pos (8UL) /*!< GPIO ALTPADCFGE: PAD17_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGE_PAD17_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGE: PAD17_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGE_PAD16_SR_Pos (4UL) /*!< GPIO ALTPADCFGE: PAD16_SR (Bit 4) */ -#define GPIO_ALTPADCFGE_PAD16_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGE: PAD16_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGE_PAD16_DS1_Pos (0UL) /*!< GPIO ALTPADCFGE: PAD16_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGE_PAD16_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGE: PAD16_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGF ======================================================= */ -#define GPIO_ALTPADCFGF_PAD23_SR_Pos (28UL) /*!< GPIO ALTPADCFGF: PAD23_SR (Bit 28) */ -#define GPIO_ALTPADCFGF_PAD23_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGF: PAD23_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGF_PAD23_DS1_Pos (24UL) /*!< GPIO ALTPADCFGF: PAD23_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGF_PAD23_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGF: PAD23_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGF_PAD22_SR_Pos (20UL) /*!< GPIO ALTPADCFGF: PAD22_SR (Bit 20) */ -#define GPIO_ALTPADCFGF_PAD22_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGF: PAD22_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGF_PAD22_DS1_Pos (16UL) /*!< GPIO ALTPADCFGF: PAD22_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGF_PAD22_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGF: PAD22_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGF_PAD21_SR_Pos (12UL) /*!< GPIO ALTPADCFGF: PAD21_SR (Bit 12) */ -#define GPIO_ALTPADCFGF_PAD21_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGF: PAD21_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGF_PAD21_DS1_Pos (8UL) /*!< GPIO ALTPADCFGF: PAD21_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGF_PAD21_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGF: PAD21_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGF_PAD20_SR_Pos (4UL) /*!< GPIO ALTPADCFGF: PAD20_SR (Bit 4) */ -#define GPIO_ALTPADCFGF_PAD20_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGF: PAD20_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGF_PAD20_DS1_Pos (0UL) /*!< GPIO ALTPADCFGF: PAD20_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGF_PAD20_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGF: PAD20_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGG ======================================================= */ -#define GPIO_ALTPADCFGG_PAD27_SR_Pos (28UL) /*!< GPIO ALTPADCFGG: PAD27_SR (Bit 28) */ -#define GPIO_ALTPADCFGG_PAD27_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGG: PAD27_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGG_PAD27_DS1_Pos (24UL) /*!< GPIO ALTPADCFGG: PAD27_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGG_PAD27_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGG: PAD27_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGG_PAD26_SR_Pos (20UL) /*!< GPIO ALTPADCFGG: PAD26_SR (Bit 20) */ -#define GPIO_ALTPADCFGG_PAD26_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGG: PAD26_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGG_PAD26_DS1_Pos (16UL) /*!< GPIO ALTPADCFGG: PAD26_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGG_PAD26_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGG: PAD26_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGG_PAD25_SR_Pos (12UL) /*!< GPIO ALTPADCFGG: PAD25_SR (Bit 12) */ -#define GPIO_ALTPADCFGG_PAD25_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGG: PAD25_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGG_PAD25_DS1_Pos (8UL) /*!< GPIO ALTPADCFGG: PAD25_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGG_PAD25_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGG: PAD25_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGG_PAD24_SR_Pos (4UL) /*!< GPIO ALTPADCFGG: PAD24_SR (Bit 4) */ -#define GPIO_ALTPADCFGG_PAD24_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGG: PAD24_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGG_PAD24_DS1_Pos (0UL) /*!< GPIO ALTPADCFGG: PAD24_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGG_PAD24_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGG: PAD24_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGH ======================================================= */ -#define GPIO_ALTPADCFGH_PAD31_SR_Pos (28UL) /*!< GPIO ALTPADCFGH: PAD31_SR (Bit 28) */ -#define GPIO_ALTPADCFGH_PAD31_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGH: PAD31_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGH_PAD31_DS1_Pos (24UL) /*!< GPIO ALTPADCFGH: PAD31_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGH_PAD31_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGH: PAD31_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGH_PAD30_SR_Pos (20UL) /*!< GPIO ALTPADCFGH: PAD30_SR (Bit 20) */ -#define GPIO_ALTPADCFGH_PAD30_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGH: PAD30_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGH_PAD30_DS1_Pos (16UL) /*!< GPIO ALTPADCFGH: PAD30_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGH_PAD30_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGH: PAD30_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGH_PAD29_SR_Pos (12UL) /*!< GPIO ALTPADCFGH: PAD29_SR (Bit 12) */ -#define GPIO_ALTPADCFGH_PAD29_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGH: PAD29_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGH_PAD29_DS1_Pos (8UL) /*!< GPIO ALTPADCFGH: PAD29_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGH_PAD29_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGH: PAD29_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGH_PAD28_SR_Pos (4UL) /*!< GPIO ALTPADCFGH: PAD28_SR (Bit 4) */ -#define GPIO_ALTPADCFGH_PAD28_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGH: PAD28_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGH_PAD28_DS1_Pos (0UL) /*!< GPIO ALTPADCFGH: PAD28_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGH_PAD28_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGH: PAD28_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGI ======================================================= */ -#define GPIO_ALTPADCFGI_PAD35_SR_Pos (28UL) /*!< GPIO ALTPADCFGI: PAD35_SR (Bit 28) */ -#define GPIO_ALTPADCFGI_PAD35_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGI: PAD35_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGI_PAD35_DS1_Pos (24UL) /*!< GPIO ALTPADCFGI: PAD35_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGI_PAD35_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGI: PAD35_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGI_PAD34_SR_Pos (20UL) /*!< GPIO ALTPADCFGI: PAD34_SR (Bit 20) */ -#define GPIO_ALTPADCFGI_PAD34_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGI: PAD34_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGI_PAD34_DS1_Pos (16UL) /*!< GPIO ALTPADCFGI: PAD34_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGI_PAD34_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGI: PAD34_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGI_PAD33_SR_Pos (12UL) /*!< GPIO ALTPADCFGI: PAD33_SR (Bit 12) */ -#define GPIO_ALTPADCFGI_PAD33_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGI: PAD33_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGI_PAD33_DS1_Pos (8UL) /*!< GPIO ALTPADCFGI: PAD33_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGI_PAD33_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGI: PAD33_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGI_PAD32_SR_Pos (4UL) /*!< GPIO ALTPADCFGI: PAD32_SR (Bit 4) */ -#define GPIO_ALTPADCFGI_PAD32_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGI: PAD32_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGI_PAD32_DS1_Pos (0UL) /*!< GPIO ALTPADCFGI: PAD32_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGI_PAD32_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGI: PAD32_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGJ ======================================================= */ -#define GPIO_ALTPADCFGJ_PAD39_SR_Pos (28UL) /*!< GPIO ALTPADCFGJ: PAD39_SR (Bit 28) */ -#define GPIO_ALTPADCFGJ_PAD39_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGJ: PAD39_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGJ_PAD39_DS1_Pos (24UL) /*!< GPIO ALTPADCFGJ: PAD39_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGJ_PAD39_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGJ: PAD39_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGJ_PAD38_SR_Pos (20UL) /*!< GPIO ALTPADCFGJ: PAD38_SR (Bit 20) */ -#define GPIO_ALTPADCFGJ_PAD38_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGJ: PAD38_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGJ_PAD38_DS1_Pos (16UL) /*!< GPIO ALTPADCFGJ: PAD38_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGJ_PAD38_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGJ: PAD38_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGJ_PAD37_SR_Pos (12UL) /*!< GPIO ALTPADCFGJ: PAD37_SR (Bit 12) */ -#define GPIO_ALTPADCFGJ_PAD37_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGJ: PAD37_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGJ_PAD37_DS1_Pos (8UL) /*!< GPIO ALTPADCFGJ: PAD37_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGJ_PAD37_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGJ: PAD37_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGJ_PAD36_SR_Pos (4UL) /*!< GPIO ALTPADCFGJ: PAD36_SR (Bit 4) */ -#define GPIO_ALTPADCFGJ_PAD36_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGJ: PAD36_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGJ_PAD36_DS1_Pos (0UL) /*!< GPIO ALTPADCFGJ: PAD36_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGJ_PAD36_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGJ: PAD36_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGK ======================================================= */ -#define GPIO_ALTPADCFGK_PAD43_SR_Pos (28UL) /*!< GPIO ALTPADCFGK: PAD43_SR (Bit 28) */ -#define GPIO_ALTPADCFGK_PAD43_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGK: PAD43_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGK_PAD43_DS1_Pos (24UL) /*!< GPIO ALTPADCFGK: PAD43_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGK_PAD43_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGK: PAD43_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGK_PAD42_SR_Pos (20UL) /*!< GPIO ALTPADCFGK: PAD42_SR (Bit 20) */ -#define GPIO_ALTPADCFGK_PAD42_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGK: PAD42_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGK_PAD42_DS1_Pos (16UL) /*!< GPIO ALTPADCFGK: PAD42_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGK_PAD42_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGK: PAD42_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGK_PAD41_SR_Pos (12UL) /*!< GPIO ALTPADCFGK: PAD41_SR (Bit 12) */ -#define GPIO_ALTPADCFGK_PAD41_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGK: PAD41_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGK_PAD41_DS1_Pos (8UL) /*!< GPIO ALTPADCFGK: PAD41_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGK_PAD41_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGK: PAD41_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGK_PAD40_SR_Pos (4UL) /*!< GPIO ALTPADCFGK: PAD40_SR (Bit 4) */ -#define GPIO_ALTPADCFGK_PAD40_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGK: PAD40_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGK_PAD40_DS1_Pos (0UL) /*!< GPIO ALTPADCFGK: PAD40_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGK_PAD40_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGK: PAD40_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGL ======================================================= */ -#define GPIO_ALTPADCFGL_PAD47_SR_Pos (28UL) /*!< GPIO ALTPADCFGL: PAD47_SR (Bit 28) */ -#define GPIO_ALTPADCFGL_PAD47_SR_Msk (0x10000000UL) /*!< GPIO ALTPADCFGL: PAD47_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGL_PAD47_DS1_Pos (24UL) /*!< GPIO ALTPADCFGL: PAD47_DS1 (Bit 24) */ -#define GPIO_ALTPADCFGL_PAD47_DS1_Msk (0x1000000UL) /*!< GPIO ALTPADCFGL: PAD47_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGL_PAD46_SR_Pos (20UL) /*!< GPIO ALTPADCFGL: PAD46_SR (Bit 20) */ -#define GPIO_ALTPADCFGL_PAD46_SR_Msk (0x100000UL) /*!< GPIO ALTPADCFGL: PAD46_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGL_PAD46_DS1_Pos (16UL) /*!< GPIO ALTPADCFGL: PAD46_DS1 (Bit 16) */ -#define GPIO_ALTPADCFGL_PAD46_DS1_Msk (0x10000UL) /*!< GPIO ALTPADCFGL: PAD46_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGL_PAD45_SR_Pos (12UL) /*!< GPIO ALTPADCFGL: PAD45_SR (Bit 12) */ -#define GPIO_ALTPADCFGL_PAD45_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGL: PAD45_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGL_PAD45_DS1_Pos (8UL) /*!< GPIO ALTPADCFGL: PAD45_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGL_PAD45_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGL: PAD45_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGL_PAD44_SR_Pos (4UL) /*!< GPIO ALTPADCFGL: PAD44_SR (Bit 4) */ -#define GPIO_ALTPADCFGL_PAD44_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGL: PAD44_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGL_PAD44_DS1_Pos (0UL) /*!< GPIO ALTPADCFGL: PAD44_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGL_PAD44_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGL: PAD44_DS1 (Bitfield-Mask: 0x01) */ -/* ====================================================== ALTPADCFGM ======================================================= */ -#define GPIO_ALTPADCFGM_PAD49_SR_Pos (12UL) /*!< GPIO ALTPADCFGM: PAD49_SR (Bit 12) */ -#define GPIO_ALTPADCFGM_PAD49_SR_Msk (0x1000UL) /*!< GPIO ALTPADCFGM: PAD49_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGM_PAD49_DS1_Pos (8UL) /*!< GPIO ALTPADCFGM: PAD49_DS1 (Bit 8) */ -#define GPIO_ALTPADCFGM_PAD49_DS1_Msk (0x100UL) /*!< GPIO ALTPADCFGM: PAD49_DS1 (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGM_PAD48_SR_Pos (4UL) /*!< GPIO ALTPADCFGM: PAD48_SR (Bit 4) */ -#define GPIO_ALTPADCFGM_PAD48_SR_Msk (0x10UL) /*!< GPIO ALTPADCFGM: PAD48_SR (Bitfield-Mask: 0x01) */ -#define GPIO_ALTPADCFGM_PAD48_DS1_Pos (0UL) /*!< GPIO ALTPADCFGM: PAD48_DS1 (Bit 0) */ -#define GPIO_ALTPADCFGM_PAD48_DS1_Msk (0x1UL) /*!< GPIO ALTPADCFGM: PAD48_DS1 (Bitfield-Mask: 0x01) */ -/* ========================================================= SCDET ========================================================= */ -#define GPIO_SCDET_SCDET_Pos (0UL) /*!< GPIO SCDET: SCDET (Bit 0) */ -#define GPIO_SCDET_SCDET_Msk (0x3fUL) /*!< GPIO SCDET: SCDET (Bitfield-Mask: 0x3f) */ -/* ======================================================== CTENCFG ======================================================== */ -#define GPIO_CTENCFG_EN31_Pos (31UL) /*!< GPIO CTENCFG: EN31 (Bit 31) */ -#define GPIO_CTENCFG_EN31_Msk (0x80000000UL) /*!< GPIO CTENCFG: EN31 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN30_Pos (30UL) /*!< GPIO CTENCFG: EN30 (Bit 30) */ -#define GPIO_CTENCFG_EN30_Msk (0x40000000UL) /*!< GPIO CTENCFG: EN30 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN29_Pos (29UL) /*!< GPIO CTENCFG: EN29 (Bit 29) */ -#define GPIO_CTENCFG_EN29_Msk (0x20000000UL) /*!< GPIO CTENCFG: EN29 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN28_Pos (28UL) /*!< GPIO CTENCFG: EN28 (Bit 28) */ -#define GPIO_CTENCFG_EN28_Msk (0x10000000UL) /*!< GPIO CTENCFG: EN28 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN27_Pos (27UL) /*!< GPIO CTENCFG: EN27 (Bit 27) */ -#define GPIO_CTENCFG_EN27_Msk (0x8000000UL) /*!< GPIO CTENCFG: EN27 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN26_Pos (26UL) /*!< GPIO CTENCFG: EN26 (Bit 26) */ -#define GPIO_CTENCFG_EN26_Msk (0x4000000UL) /*!< GPIO CTENCFG: EN26 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN25_Pos (25UL) /*!< GPIO CTENCFG: EN25 (Bit 25) */ -#define GPIO_CTENCFG_EN25_Msk (0x2000000UL) /*!< GPIO CTENCFG: EN25 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN24_Pos (24UL) /*!< GPIO CTENCFG: EN24 (Bit 24) */ -#define GPIO_CTENCFG_EN24_Msk (0x1000000UL) /*!< GPIO CTENCFG: EN24 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN23_Pos (23UL) /*!< GPIO CTENCFG: EN23 (Bit 23) */ -#define GPIO_CTENCFG_EN23_Msk (0x800000UL) /*!< GPIO CTENCFG: EN23 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN22_Pos (22UL) /*!< GPIO CTENCFG: EN22 (Bit 22) */ -#define GPIO_CTENCFG_EN22_Msk (0x400000UL) /*!< GPIO CTENCFG: EN22 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN21_Pos (21UL) /*!< GPIO CTENCFG: EN21 (Bit 21) */ -#define GPIO_CTENCFG_EN21_Msk (0x200000UL) /*!< GPIO CTENCFG: EN21 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN20_Pos (20UL) /*!< GPIO CTENCFG: EN20 (Bit 20) */ -#define GPIO_CTENCFG_EN20_Msk (0x100000UL) /*!< GPIO CTENCFG: EN20 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN19_Pos (19UL) /*!< GPIO CTENCFG: EN19 (Bit 19) */ -#define GPIO_CTENCFG_EN19_Msk (0x80000UL) /*!< GPIO CTENCFG: EN19 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN18_Pos (18UL) /*!< GPIO CTENCFG: EN18 (Bit 18) */ -#define GPIO_CTENCFG_EN18_Msk (0x40000UL) /*!< GPIO CTENCFG: EN18 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN17_Pos (17UL) /*!< GPIO CTENCFG: EN17 (Bit 17) */ -#define GPIO_CTENCFG_EN17_Msk (0x20000UL) /*!< GPIO CTENCFG: EN17 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN16_Pos (16UL) /*!< GPIO CTENCFG: EN16 (Bit 16) */ -#define GPIO_CTENCFG_EN16_Msk (0x10000UL) /*!< GPIO CTENCFG: EN16 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN15_Pos (15UL) /*!< GPIO CTENCFG: EN15 (Bit 15) */ -#define GPIO_CTENCFG_EN15_Msk (0x8000UL) /*!< GPIO CTENCFG: EN15 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN14_Pos (14UL) /*!< GPIO CTENCFG: EN14 (Bit 14) */ -#define GPIO_CTENCFG_EN14_Msk (0x4000UL) /*!< GPIO CTENCFG: EN14 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN13_Pos (13UL) /*!< GPIO CTENCFG: EN13 (Bit 13) */ -#define GPIO_CTENCFG_EN13_Msk (0x2000UL) /*!< GPIO CTENCFG: EN13 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN12_Pos (12UL) /*!< GPIO CTENCFG: EN12 (Bit 12) */ -#define GPIO_CTENCFG_EN12_Msk (0x1000UL) /*!< GPIO CTENCFG: EN12 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN11_Pos (11UL) /*!< GPIO CTENCFG: EN11 (Bit 11) */ -#define GPIO_CTENCFG_EN11_Msk (0x800UL) /*!< GPIO CTENCFG: EN11 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN10_Pos (10UL) /*!< GPIO CTENCFG: EN10 (Bit 10) */ -#define GPIO_CTENCFG_EN10_Msk (0x400UL) /*!< GPIO CTENCFG: EN10 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN9_Pos (9UL) /*!< GPIO CTENCFG: EN9 (Bit 9) */ -#define GPIO_CTENCFG_EN9_Msk (0x200UL) /*!< GPIO CTENCFG: EN9 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN8_Pos (8UL) /*!< GPIO CTENCFG: EN8 (Bit 8) */ -#define GPIO_CTENCFG_EN8_Msk (0x100UL) /*!< GPIO CTENCFG: EN8 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN7_Pos (7UL) /*!< GPIO CTENCFG: EN7 (Bit 7) */ -#define GPIO_CTENCFG_EN7_Msk (0x80UL) /*!< GPIO CTENCFG: EN7 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN6_Pos (6UL) /*!< GPIO CTENCFG: EN6 (Bit 6) */ -#define GPIO_CTENCFG_EN6_Msk (0x40UL) /*!< GPIO CTENCFG: EN6 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN5_Pos (5UL) /*!< GPIO CTENCFG: EN5 (Bit 5) */ -#define GPIO_CTENCFG_EN5_Msk (0x20UL) /*!< GPIO CTENCFG: EN5 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN4_Pos (4UL) /*!< GPIO CTENCFG: EN4 (Bit 4) */ -#define GPIO_CTENCFG_EN4_Msk (0x10UL) /*!< GPIO CTENCFG: EN4 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN3_Pos (3UL) /*!< GPIO CTENCFG: EN3 (Bit 3) */ -#define GPIO_CTENCFG_EN3_Msk (0x8UL) /*!< GPIO CTENCFG: EN3 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN2_Pos (2UL) /*!< GPIO CTENCFG: EN2 (Bit 2) */ -#define GPIO_CTENCFG_EN2_Msk (0x4UL) /*!< GPIO CTENCFG: EN2 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN1_Pos (1UL) /*!< GPIO CTENCFG: EN1 (Bit 1) */ -#define GPIO_CTENCFG_EN1_Msk (0x2UL) /*!< GPIO CTENCFG: EN1 (Bitfield-Mask: 0x01) */ -#define GPIO_CTENCFG_EN0_Pos (0UL) /*!< GPIO CTENCFG: EN0 (Bit 0) */ -#define GPIO_CTENCFG_EN0_Msk (0x1UL) /*!< GPIO CTENCFG: EN0 (Bitfield-Mask: 0x01) */ -/* ======================================================== INT0EN ========================================================= */ -#define GPIO_INT0EN_GPIO31_Pos (31UL) /*!< GPIO INT0EN: GPIO31 (Bit 31) */ -#define GPIO_INT0EN_GPIO31_Msk (0x80000000UL) /*!< GPIO INT0EN: GPIO31 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO30_Pos (30UL) /*!< GPIO INT0EN: GPIO30 (Bit 30) */ -#define GPIO_INT0EN_GPIO30_Msk (0x40000000UL) /*!< GPIO INT0EN: GPIO30 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO29_Pos (29UL) /*!< GPIO INT0EN: GPIO29 (Bit 29) */ -#define GPIO_INT0EN_GPIO29_Msk (0x20000000UL) /*!< GPIO INT0EN: GPIO29 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO28_Pos (28UL) /*!< GPIO INT0EN: GPIO28 (Bit 28) */ -#define GPIO_INT0EN_GPIO28_Msk (0x10000000UL) /*!< GPIO INT0EN: GPIO28 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO27_Pos (27UL) /*!< GPIO INT0EN: GPIO27 (Bit 27) */ -#define GPIO_INT0EN_GPIO27_Msk (0x8000000UL) /*!< GPIO INT0EN: GPIO27 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO26_Pos (26UL) /*!< GPIO INT0EN: GPIO26 (Bit 26) */ -#define GPIO_INT0EN_GPIO26_Msk (0x4000000UL) /*!< GPIO INT0EN: GPIO26 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO25_Pos (25UL) /*!< GPIO INT0EN: GPIO25 (Bit 25) */ -#define GPIO_INT0EN_GPIO25_Msk (0x2000000UL) /*!< GPIO INT0EN: GPIO25 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO24_Pos (24UL) /*!< GPIO INT0EN: GPIO24 (Bit 24) */ -#define GPIO_INT0EN_GPIO24_Msk (0x1000000UL) /*!< GPIO INT0EN: GPIO24 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO23_Pos (23UL) /*!< GPIO INT0EN: GPIO23 (Bit 23) */ -#define GPIO_INT0EN_GPIO23_Msk (0x800000UL) /*!< GPIO INT0EN: GPIO23 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO22_Pos (22UL) /*!< GPIO INT0EN: GPIO22 (Bit 22) */ -#define GPIO_INT0EN_GPIO22_Msk (0x400000UL) /*!< GPIO INT0EN: GPIO22 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO21_Pos (21UL) /*!< GPIO INT0EN: GPIO21 (Bit 21) */ -#define GPIO_INT0EN_GPIO21_Msk (0x200000UL) /*!< GPIO INT0EN: GPIO21 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO20_Pos (20UL) /*!< GPIO INT0EN: GPIO20 (Bit 20) */ -#define GPIO_INT0EN_GPIO20_Msk (0x100000UL) /*!< GPIO INT0EN: GPIO20 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO19_Pos (19UL) /*!< GPIO INT0EN: GPIO19 (Bit 19) */ -#define GPIO_INT0EN_GPIO19_Msk (0x80000UL) /*!< GPIO INT0EN: GPIO19 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO18_Pos (18UL) /*!< GPIO INT0EN: GPIO18 (Bit 18) */ -#define GPIO_INT0EN_GPIO18_Msk (0x40000UL) /*!< GPIO INT0EN: GPIO18 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO17_Pos (17UL) /*!< GPIO INT0EN: GPIO17 (Bit 17) */ -#define GPIO_INT0EN_GPIO17_Msk (0x20000UL) /*!< GPIO INT0EN: GPIO17 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO16_Pos (16UL) /*!< GPIO INT0EN: GPIO16 (Bit 16) */ -#define GPIO_INT0EN_GPIO16_Msk (0x10000UL) /*!< GPIO INT0EN: GPIO16 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO15_Pos (15UL) /*!< GPIO INT0EN: GPIO15 (Bit 15) */ -#define GPIO_INT0EN_GPIO15_Msk (0x8000UL) /*!< GPIO INT0EN: GPIO15 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO14_Pos (14UL) /*!< GPIO INT0EN: GPIO14 (Bit 14) */ -#define GPIO_INT0EN_GPIO14_Msk (0x4000UL) /*!< GPIO INT0EN: GPIO14 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO13_Pos (13UL) /*!< GPIO INT0EN: GPIO13 (Bit 13) */ -#define GPIO_INT0EN_GPIO13_Msk (0x2000UL) /*!< GPIO INT0EN: GPIO13 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO12_Pos (12UL) /*!< GPIO INT0EN: GPIO12 (Bit 12) */ -#define GPIO_INT0EN_GPIO12_Msk (0x1000UL) /*!< GPIO INT0EN: GPIO12 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO11_Pos (11UL) /*!< GPIO INT0EN: GPIO11 (Bit 11) */ -#define GPIO_INT0EN_GPIO11_Msk (0x800UL) /*!< GPIO INT0EN: GPIO11 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO10_Pos (10UL) /*!< GPIO INT0EN: GPIO10 (Bit 10) */ -#define GPIO_INT0EN_GPIO10_Msk (0x400UL) /*!< GPIO INT0EN: GPIO10 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO9_Pos (9UL) /*!< GPIO INT0EN: GPIO9 (Bit 9) */ -#define GPIO_INT0EN_GPIO9_Msk (0x200UL) /*!< GPIO INT0EN: GPIO9 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO8_Pos (8UL) /*!< GPIO INT0EN: GPIO8 (Bit 8) */ -#define GPIO_INT0EN_GPIO8_Msk (0x100UL) /*!< GPIO INT0EN: GPIO8 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO7_Pos (7UL) /*!< GPIO INT0EN: GPIO7 (Bit 7) */ -#define GPIO_INT0EN_GPIO7_Msk (0x80UL) /*!< GPIO INT0EN: GPIO7 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO6_Pos (6UL) /*!< GPIO INT0EN: GPIO6 (Bit 6) */ -#define GPIO_INT0EN_GPIO6_Msk (0x40UL) /*!< GPIO INT0EN: GPIO6 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO5_Pos (5UL) /*!< GPIO INT0EN: GPIO5 (Bit 5) */ -#define GPIO_INT0EN_GPIO5_Msk (0x20UL) /*!< GPIO INT0EN: GPIO5 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO4_Pos (4UL) /*!< GPIO INT0EN: GPIO4 (Bit 4) */ -#define GPIO_INT0EN_GPIO4_Msk (0x10UL) /*!< GPIO INT0EN: GPIO4 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO3_Pos (3UL) /*!< GPIO INT0EN: GPIO3 (Bit 3) */ -#define GPIO_INT0EN_GPIO3_Msk (0x8UL) /*!< GPIO INT0EN: GPIO3 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO2_Pos (2UL) /*!< GPIO INT0EN: GPIO2 (Bit 2) */ -#define GPIO_INT0EN_GPIO2_Msk (0x4UL) /*!< GPIO INT0EN: GPIO2 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO1_Pos (1UL) /*!< GPIO INT0EN: GPIO1 (Bit 1) */ -#define GPIO_INT0EN_GPIO1_Msk (0x2UL) /*!< GPIO INT0EN: GPIO1 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0EN_GPIO0_Pos (0UL) /*!< GPIO INT0EN: GPIO0 (Bit 0) */ -#define GPIO_INT0EN_GPIO0_Msk (0x1UL) /*!< GPIO INT0EN: GPIO0 (Bitfield-Mask: 0x01) */ -/* ======================================================= INT0STAT ======================================================== */ -#define GPIO_INT0STAT_GPIO31_Pos (31UL) /*!< GPIO INT0STAT: GPIO31 (Bit 31) */ -#define GPIO_INT0STAT_GPIO31_Msk (0x80000000UL) /*!< GPIO INT0STAT: GPIO31 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO30_Pos (30UL) /*!< GPIO INT0STAT: GPIO30 (Bit 30) */ -#define GPIO_INT0STAT_GPIO30_Msk (0x40000000UL) /*!< GPIO INT0STAT: GPIO30 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO29_Pos (29UL) /*!< GPIO INT0STAT: GPIO29 (Bit 29) */ -#define GPIO_INT0STAT_GPIO29_Msk (0x20000000UL) /*!< GPIO INT0STAT: GPIO29 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO28_Pos (28UL) /*!< GPIO INT0STAT: GPIO28 (Bit 28) */ -#define GPIO_INT0STAT_GPIO28_Msk (0x10000000UL) /*!< GPIO INT0STAT: GPIO28 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO27_Pos (27UL) /*!< GPIO INT0STAT: GPIO27 (Bit 27) */ -#define GPIO_INT0STAT_GPIO27_Msk (0x8000000UL) /*!< GPIO INT0STAT: GPIO27 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO26_Pos (26UL) /*!< GPIO INT0STAT: GPIO26 (Bit 26) */ -#define GPIO_INT0STAT_GPIO26_Msk (0x4000000UL) /*!< GPIO INT0STAT: GPIO26 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO25_Pos (25UL) /*!< GPIO INT0STAT: GPIO25 (Bit 25) */ -#define GPIO_INT0STAT_GPIO25_Msk (0x2000000UL) /*!< GPIO INT0STAT: GPIO25 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO24_Pos (24UL) /*!< GPIO INT0STAT: GPIO24 (Bit 24) */ -#define GPIO_INT0STAT_GPIO24_Msk (0x1000000UL) /*!< GPIO INT0STAT: GPIO24 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO23_Pos (23UL) /*!< GPIO INT0STAT: GPIO23 (Bit 23) */ -#define GPIO_INT0STAT_GPIO23_Msk (0x800000UL) /*!< GPIO INT0STAT: GPIO23 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO22_Pos (22UL) /*!< GPIO INT0STAT: GPIO22 (Bit 22) */ -#define GPIO_INT0STAT_GPIO22_Msk (0x400000UL) /*!< GPIO INT0STAT: GPIO22 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO21_Pos (21UL) /*!< GPIO INT0STAT: GPIO21 (Bit 21) */ -#define GPIO_INT0STAT_GPIO21_Msk (0x200000UL) /*!< GPIO INT0STAT: GPIO21 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO20_Pos (20UL) /*!< GPIO INT0STAT: GPIO20 (Bit 20) */ -#define GPIO_INT0STAT_GPIO20_Msk (0x100000UL) /*!< GPIO INT0STAT: GPIO20 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO19_Pos (19UL) /*!< GPIO INT0STAT: GPIO19 (Bit 19) */ -#define GPIO_INT0STAT_GPIO19_Msk (0x80000UL) /*!< GPIO INT0STAT: GPIO19 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO18_Pos (18UL) /*!< GPIO INT0STAT: GPIO18 (Bit 18) */ -#define GPIO_INT0STAT_GPIO18_Msk (0x40000UL) /*!< GPIO INT0STAT: GPIO18 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO17_Pos (17UL) /*!< GPIO INT0STAT: GPIO17 (Bit 17) */ -#define GPIO_INT0STAT_GPIO17_Msk (0x20000UL) /*!< GPIO INT0STAT: GPIO17 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO16_Pos (16UL) /*!< GPIO INT0STAT: GPIO16 (Bit 16) */ -#define GPIO_INT0STAT_GPIO16_Msk (0x10000UL) /*!< GPIO INT0STAT: GPIO16 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO15_Pos (15UL) /*!< GPIO INT0STAT: GPIO15 (Bit 15) */ -#define GPIO_INT0STAT_GPIO15_Msk (0x8000UL) /*!< GPIO INT0STAT: GPIO15 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO14_Pos (14UL) /*!< GPIO INT0STAT: GPIO14 (Bit 14) */ -#define GPIO_INT0STAT_GPIO14_Msk (0x4000UL) /*!< GPIO INT0STAT: GPIO14 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO13_Pos (13UL) /*!< GPIO INT0STAT: GPIO13 (Bit 13) */ -#define GPIO_INT0STAT_GPIO13_Msk (0x2000UL) /*!< GPIO INT0STAT: GPIO13 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO12_Pos (12UL) /*!< GPIO INT0STAT: GPIO12 (Bit 12) */ -#define GPIO_INT0STAT_GPIO12_Msk (0x1000UL) /*!< GPIO INT0STAT: GPIO12 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO11_Pos (11UL) /*!< GPIO INT0STAT: GPIO11 (Bit 11) */ -#define GPIO_INT0STAT_GPIO11_Msk (0x800UL) /*!< GPIO INT0STAT: GPIO11 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO10_Pos (10UL) /*!< GPIO INT0STAT: GPIO10 (Bit 10) */ -#define GPIO_INT0STAT_GPIO10_Msk (0x400UL) /*!< GPIO INT0STAT: GPIO10 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO9_Pos (9UL) /*!< GPIO INT0STAT: GPIO9 (Bit 9) */ -#define GPIO_INT0STAT_GPIO9_Msk (0x200UL) /*!< GPIO INT0STAT: GPIO9 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO8_Pos (8UL) /*!< GPIO INT0STAT: GPIO8 (Bit 8) */ -#define GPIO_INT0STAT_GPIO8_Msk (0x100UL) /*!< GPIO INT0STAT: GPIO8 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO7_Pos (7UL) /*!< GPIO INT0STAT: GPIO7 (Bit 7) */ -#define GPIO_INT0STAT_GPIO7_Msk (0x80UL) /*!< GPIO INT0STAT: GPIO7 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO6_Pos (6UL) /*!< GPIO INT0STAT: GPIO6 (Bit 6) */ -#define GPIO_INT0STAT_GPIO6_Msk (0x40UL) /*!< GPIO INT0STAT: GPIO6 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO5_Pos (5UL) /*!< GPIO INT0STAT: GPIO5 (Bit 5) */ -#define GPIO_INT0STAT_GPIO5_Msk (0x20UL) /*!< GPIO INT0STAT: GPIO5 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO4_Pos (4UL) /*!< GPIO INT0STAT: GPIO4 (Bit 4) */ -#define GPIO_INT0STAT_GPIO4_Msk (0x10UL) /*!< GPIO INT0STAT: GPIO4 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO3_Pos (3UL) /*!< GPIO INT0STAT: GPIO3 (Bit 3) */ -#define GPIO_INT0STAT_GPIO3_Msk (0x8UL) /*!< GPIO INT0STAT: GPIO3 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO2_Pos (2UL) /*!< GPIO INT0STAT: GPIO2 (Bit 2) */ -#define GPIO_INT0STAT_GPIO2_Msk (0x4UL) /*!< GPIO INT0STAT: GPIO2 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO1_Pos (1UL) /*!< GPIO INT0STAT: GPIO1 (Bit 1) */ -#define GPIO_INT0STAT_GPIO1_Msk (0x2UL) /*!< GPIO INT0STAT: GPIO1 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0STAT_GPIO0_Pos (0UL) /*!< GPIO INT0STAT: GPIO0 (Bit 0) */ -#define GPIO_INT0STAT_GPIO0_Msk (0x1UL) /*!< GPIO INT0STAT: GPIO0 (Bitfield-Mask: 0x01) */ -/* ======================================================== INT0CLR ======================================================== */ -#define GPIO_INT0CLR_GPIO31_Pos (31UL) /*!< GPIO INT0CLR: GPIO31 (Bit 31) */ -#define GPIO_INT0CLR_GPIO31_Msk (0x80000000UL) /*!< GPIO INT0CLR: GPIO31 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO30_Pos (30UL) /*!< GPIO INT0CLR: GPIO30 (Bit 30) */ -#define GPIO_INT0CLR_GPIO30_Msk (0x40000000UL) /*!< GPIO INT0CLR: GPIO30 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO29_Pos (29UL) /*!< GPIO INT0CLR: GPIO29 (Bit 29) */ -#define GPIO_INT0CLR_GPIO29_Msk (0x20000000UL) /*!< GPIO INT0CLR: GPIO29 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO28_Pos (28UL) /*!< GPIO INT0CLR: GPIO28 (Bit 28) */ -#define GPIO_INT0CLR_GPIO28_Msk (0x10000000UL) /*!< GPIO INT0CLR: GPIO28 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO27_Pos (27UL) /*!< GPIO INT0CLR: GPIO27 (Bit 27) */ -#define GPIO_INT0CLR_GPIO27_Msk (0x8000000UL) /*!< GPIO INT0CLR: GPIO27 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO26_Pos (26UL) /*!< GPIO INT0CLR: GPIO26 (Bit 26) */ -#define GPIO_INT0CLR_GPIO26_Msk (0x4000000UL) /*!< GPIO INT0CLR: GPIO26 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO25_Pos (25UL) /*!< GPIO INT0CLR: GPIO25 (Bit 25) */ -#define GPIO_INT0CLR_GPIO25_Msk (0x2000000UL) /*!< GPIO INT0CLR: GPIO25 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO24_Pos (24UL) /*!< GPIO INT0CLR: GPIO24 (Bit 24) */ -#define GPIO_INT0CLR_GPIO24_Msk (0x1000000UL) /*!< GPIO INT0CLR: GPIO24 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO23_Pos (23UL) /*!< GPIO INT0CLR: GPIO23 (Bit 23) */ -#define GPIO_INT0CLR_GPIO23_Msk (0x800000UL) /*!< GPIO INT0CLR: GPIO23 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO22_Pos (22UL) /*!< GPIO INT0CLR: GPIO22 (Bit 22) */ -#define GPIO_INT0CLR_GPIO22_Msk (0x400000UL) /*!< GPIO INT0CLR: GPIO22 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO21_Pos (21UL) /*!< GPIO INT0CLR: GPIO21 (Bit 21) */ -#define GPIO_INT0CLR_GPIO21_Msk (0x200000UL) /*!< GPIO INT0CLR: GPIO21 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO20_Pos (20UL) /*!< GPIO INT0CLR: GPIO20 (Bit 20) */ -#define GPIO_INT0CLR_GPIO20_Msk (0x100000UL) /*!< GPIO INT0CLR: GPIO20 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO19_Pos (19UL) /*!< GPIO INT0CLR: GPIO19 (Bit 19) */ -#define GPIO_INT0CLR_GPIO19_Msk (0x80000UL) /*!< GPIO INT0CLR: GPIO19 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO18_Pos (18UL) /*!< GPIO INT0CLR: GPIO18 (Bit 18) */ -#define GPIO_INT0CLR_GPIO18_Msk (0x40000UL) /*!< GPIO INT0CLR: GPIO18 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO17_Pos (17UL) /*!< GPIO INT0CLR: GPIO17 (Bit 17) */ -#define GPIO_INT0CLR_GPIO17_Msk (0x20000UL) /*!< GPIO INT0CLR: GPIO17 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO16_Pos (16UL) /*!< GPIO INT0CLR: GPIO16 (Bit 16) */ -#define GPIO_INT0CLR_GPIO16_Msk (0x10000UL) /*!< GPIO INT0CLR: GPIO16 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO15_Pos (15UL) /*!< GPIO INT0CLR: GPIO15 (Bit 15) */ -#define GPIO_INT0CLR_GPIO15_Msk (0x8000UL) /*!< GPIO INT0CLR: GPIO15 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO14_Pos (14UL) /*!< GPIO INT0CLR: GPIO14 (Bit 14) */ -#define GPIO_INT0CLR_GPIO14_Msk (0x4000UL) /*!< GPIO INT0CLR: GPIO14 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO13_Pos (13UL) /*!< GPIO INT0CLR: GPIO13 (Bit 13) */ -#define GPIO_INT0CLR_GPIO13_Msk (0x2000UL) /*!< GPIO INT0CLR: GPIO13 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO12_Pos (12UL) /*!< GPIO INT0CLR: GPIO12 (Bit 12) */ -#define GPIO_INT0CLR_GPIO12_Msk (0x1000UL) /*!< GPIO INT0CLR: GPIO12 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO11_Pos (11UL) /*!< GPIO INT0CLR: GPIO11 (Bit 11) */ -#define GPIO_INT0CLR_GPIO11_Msk (0x800UL) /*!< GPIO INT0CLR: GPIO11 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO10_Pos (10UL) /*!< GPIO INT0CLR: GPIO10 (Bit 10) */ -#define GPIO_INT0CLR_GPIO10_Msk (0x400UL) /*!< GPIO INT0CLR: GPIO10 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO9_Pos (9UL) /*!< GPIO INT0CLR: GPIO9 (Bit 9) */ -#define GPIO_INT0CLR_GPIO9_Msk (0x200UL) /*!< GPIO INT0CLR: GPIO9 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO8_Pos (8UL) /*!< GPIO INT0CLR: GPIO8 (Bit 8) */ -#define GPIO_INT0CLR_GPIO8_Msk (0x100UL) /*!< GPIO INT0CLR: GPIO8 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO7_Pos (7UL) /*!< GPIO INT0CLR: GPIO7 (Bit 7) */ -#define GPIO_INT0CLR_GPIO7_Msk (0x80UL) /*!< GPIO INT0CLR: GPIO7 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO6_Pos (6UL) /*!< GPIO INT0CLR: GPIO6 (Bit 6) */ -#define GPIO_INT0CLR_GPIO6_Msk (0x40UL) /*!< GPIO INT0CLR: GPIO6 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO5_Pos (5UL) /*!< GPIO INT0CLR: GPIO5 (Bit 5) */ -#define GPIO_INT0CLR_GPIO5_Msk (0x20UL) /*!< GPIO INT0CLR: GPIO5 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO4_Pos (4UL) /*!< GPIO INT0CLR: GPIO4 (Bit 4) */ -#define GPIO_INT0CLR_GPIO4_Msk (0x10UL) /*!< GPIO INT0CLR: GPIO4 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO3_Pos (3UL) /*!< GPIO INT0CLR: GPIO3 (Bit 3) */ -#define GPIO_INT0CLR_GPIO3_Msk (0x8UL) /*!< GPIO INT0CLR: GPIO3 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO2_Pos (2UL) /*!< GPIO INT0CLR: GPIO2 (Bit 2) */ -#define GPIO_INT0CLR_GPIO2_Msk (0x4UL) /*!< GPIO INT0CLR: GPIO2 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO1_Pos (1UL) /*!< GPIO INT0CLR: GPIO1 (Bit 1) */ -#define GPIO_INT0CLR_GPIO1_Msk (0x2UL) /*!< GPIO INT0CLR: GPIO1 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0CLR_GPIO0_Pos (0UL) /*!< GPIO INT0CLR: GPIO0 (Bit 0) */ -#define GPIO_INT0CLR_GPIO0_Msk (0x1UL) /*!< GPIO INT0CLR: GPIO0 (Bitfield-Mask: 0x01) */ -/* ======================================================== INT0SET ======================================================== */ -#define GPIO_INT0SET_GPIO31_Pos (31UL) /*!< GPIO INT0SET: GPIO31 (Bit 31) */ -#define GPIO_INT0SET_GPIO31_Msk (0x80000000UL) /*!< GPIO INT0SET: GPIO31 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO30_Pos (30UL) /*!< GPIO INT0SET: GPIO30 (Bit 30) */ -#define GPIO_INT0SET_GPIO30_Msk (0x40000000UL) /*!< GPIO INT0SET: GPIO30 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO29_Pos (29UL) /*!< GPIO INT0SET: GPIO29 (Bit 29) */ -#define GPIO_INT0SET_GPIO29_Msk (0x20000000UL) /*!< GPIO INT0SET: GPIO29 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO28_Pos (28UL) /*!< GPIO INT0SET: GPIO28 (Bit 28) */ -#define GPIO_INT0SET_GPIO28_Msk (0x10000000UL) /*!< GPIO INT0SET: GPIO28 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO27_Pos (27UL) /*!< GPIO INT0SET: GPIO27 (Bit 27) */ -#define GPIO_INT0SET_GPIO27_Msk (0x8000000UL) /*!< GPIO INT0SET: GPIO27 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO26_Pos (26UL) /*!< GPIO INT0SET: GPIO26 (Bit 26) */ -#define GPIO_INT0SET_GPIO26_Msk (0x4000000UL) /*!< GPIO INT0SET: GPIO26 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO25_Pos (25UL) /*!< GPIO INT0SET: GPIO25 (Bit 25) */ -#define GPIO_INT0SET_GPIO25_Msk (0x2000000UL) /*!< GPIO INT0SET: GPIO25 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO24_Pos (24UL) /*!< GPIO INT0SET: GPIO24 (Bit 24) */ -#define GPIO_INT0SET_GPIO24_Msk (0x1000000UL) /*!< GPIO INT0SET: GPIO24 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO23_Pos (23UL) /*!< GPIO INT0SET: GPIO23 (Bit 23) */ -#define GPIO_INT0SET_GPIO23_Msk (0x800000UL) /*!< GPIO INT0SET: GPIO23 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO22_Pos (22UL) /*!< GPIO INT0SET: GPIO22 (Bit 22) */ -#define GPIO_INT0SET_GPIO22_Msk (0x400000UL) /*!< GPIO INT0SET: GPIO22 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO21_Pos (21UL) /*!< GPIO INT0SET: GPIO21 (Bit 21) */ -#define GPIO_INT0SET_GPIO21_Msk (0x200000UL) /*!< GPIO INT0SET: GPIO21 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO20_Pos (20UL) /*!< GPIO INT0SET: GPIO20 (Bit 20) */ -#define GPIO_INT0SET_GPIO20_Msk (0x100000UL) /*!< GPIO INT0SET: GPIO20 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO19_Pos (19UL) /*!< GPIO INT0SET: GPIO19 (Bit 19) */ -#define GPIO_INT0SET_GPIO19_Msk (0x80000UL) /*!< GPIO INT0SET: GPIO19 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO18_Pos (18UL) /*!< GPIO INT0SET: GPIO18 (Bit 18) */ -#define GPIO_INT0SET_GPIO18_Msk (0x40000UL) /*!< GPIO INT0SET: GPIO18 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO17_Pos (17UL) /*!< GPIO INT0SET: GPIO17 (Bit 17) */ -#define GPIO_INT0SET_GPIO17_Msk (0x20000UL) /*!< GPIO INT0SET: GPIO17 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO16_Pos (16UL) /*!< GPIO INT0SET: GPIO16 (Bit 16) */ -#define GPIO_INT0SET_GPIO16_Msk (0x10000UL) /*!< GPIO INT0SET: GPIO16 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO15_Pos (15UL) /*!< GPIO INT0SET: GPIO15 (Bit 15) */ -#define GPIO_INT0SET_GPIO15_Msk (0x8000UL) /*!< GPIO INT0SET: GPIO15 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO14_Pos (14UL) /*!< GPIO INT0SET: GPIO14 (Bit 14) */ -#define GPIO_INT0SET_GPIO14_Msk (0x4000UL) /*!< GPIO INT0SET: GPIO14 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO13_Pos (13UL) /*!< GPIO INT0SET: GPIO13 (Bit 13) */ -#define GPIO_INT0SET_GPIO13_Msk (0x2000UL) /*!< GPIO INT0SET: GPIO13 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO12_Pos (12UL) /*!< GPIO INT0SET: GPIO12 (Bit 12) */ -#define GPIO_INT0SET_GPIO12_Msk (0x1000UL) /*!< GPIO INT0SET: GPIO12 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO11_Pos (11UL) /*!< GPIO INT0SET: GPIO11 (Bit 11) */ -#define GPIO_INT0SET_GPIO11_Msk (0x800UL) /*!< GPIO INT0SET: GPIO11 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO10_Pos (10UL) /*!< GPIO INT0SET: GPIO10 (Bit 10) */ -#define GPIO_INT0SET_GPIO10_Msk (0x400UL) /*!< GPIO INT0SET: GPIO10 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO9_Pos (9UL) /*!< GPIO INT0SET: GPIO9 (Bit 9) */ -#define GPIO_INT0SET_GPIO9_Msk (0x200UL) /*!< GPIO INT0SET: GPIO9 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO8_Pos (8UL) /*!< GPIO INT0SET: GPIO8 (Bit 8) */ -#define GPIO_INT0SET_GPIO8_Msk (0x100UL) /*!< GPIO INT0SET: GPIO8 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO7_Pos (7UL) /*!< GPIO INT0SET: GPIO7 (Bit 7) */ -#define GPIO_INT0SET_GPIO7_Msk (0x80UL) /*!< GPIO INT0SET: GPIO7 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO6_Pos (6UL) /*!< GPIO INT0SET: GPIO6 (Bit 6) */ -#define GPIO_INT0SET_GPIO6_Msk (0x40UL) /*!< GPIO INT0SET: GPIO6 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO5_Pos (5UL) /*!< GPIO INT0SET: GPIO5 (Bit 5) */ -#define GPIO_INT0SET_GPIO5_Msk (0x20UL) /*!< GPIO INT0SET: GPIO5 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO4_Pos (4UL) /*!< GPIO INT0SET: GPIO4 (Bit 4) */ -#define GPIO_INT0SET_GPIO4_Msk (0x10UL) /*!< GPIO INT0SET: GPIO4 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO3_Pos (3UL) /*!< GPIO INT0SET: GPIO3 (Bit 3) */ -#define GPIO_INT0SET_GPIO3_Msk (0x8UL) /*!< GPIO INT0SET: GPIO3 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO2_Pos (2UL) /*!< GPIO INT0SET: GPIO2 (Bit 2) */ -#define GPIO_INT0SET_GPIO2_Msk (0x4UL) /*!< GPIO INT0SET: GPIO2 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO1_Pos (1UL) /*!< GPIO INT0SET: GPIO1 (Bit 1) */ -#define GPIO_INT0SET_GPIO1_Msk (0x2UL) /*!< GPIO INT0SET: GPIO1 (Bitfield-Mask: 0x01) */ -#define GPIO_INT0SET_GPIO0_Pos (0UL) /*!< GPIO INT0SET: GPIO0 (Bit 0) */ -#define GPIO_INT0SET_GPIO0_Msk (0x1UL) /*!< GPIO INT0SET: GPIO0 (Bitfield-Mask: 0x01) */ -/* ======================================================== INT1EN ========================================================= */ -#define GPIO_INT1EN_GPIO49_Pos (17UL) /*!< GPIO INT1EN: GPIO49 (Bit 17) */ -#define GPIO_INT1EN_GPIO49_Msk (0x20000UL) /*!< GPIO INT1EN: GPIO49 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO48_Pos (16UL) /*!< GPIO INT1EN: GPIO48 (Bit 16) */ -#define GPIO_INT1EN_GPIO48_Msk (0x10000UL) /*!< GPIO INT1EN: GPIO48 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO47_Pos (15UL) /*!< GPIO INT1EN: GPIO47 (Bit 15) */ -#define GPIO_INT1EN_GPIO47_Msk (0x8000UL) /*!< GPIO INT1EN: GPIO47 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO46_Pos (14UL) /*!< GPIO INT1EN: GPIO46 (Bit 14) */ -#define GPIO_INT1EN_GPIO46_Msk (0x4000UL) /*!< GPIO INT1EN: GPIO46 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO45_Pos (13UL) /*!< GPIO INT1EN: GPIO45 (Bit 13) */ -#define GPIO_INT1EN_GPIO45_Msk (0x2000UL) /*!< GPIO INT1EN: GPIO45 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO44_Pos (12UL) /*!< GPIO INT1EN: GPIO44 (Bit 12) */ -#define GPIO_INT1EN_GPIO44_Msk (0x1000UL) /*!< GPIO INT1EN: GPIO44 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO43_Pos (11UL) /*!< GPIO INT1EN: GPIO43 (Bit 11) */ -#define GPIO_INT1EN_GPIO43_Msk (0x800UL) /*!< GPIO INT1EN: GPIO43 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO42_Pos (10UL) /*!< GPIO INT1EN: GPIO42 (Bit 10) */ -#define GPIO_INT1EN_GPIO42_Msk (0x400UL) /*!< GPIO INT1EN: GPIO42 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO41_Pos (9UL) /*!< GPIO INT1EN: GPIO41 (Bit 9) */ -#define GPIO_INT1EN_GPIO41_Msk (0x200UL) /*!< GPIO INT1EN: GPIO41 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO40_Pos (8UL) /*!< GPIO INT1EN: GPIO40 (Bit 8) */ -#define GPIO_INT1EN_GPIO40_Msk (0x100UL) /*!< GPIO INT1EN: GPIO40 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO39_Pos (7UL) /*!< GPIO INT1EN: GPIO39 (Bit 7) */ -#define GPIO_INT1EN_GPIO39_Msk (0x80UL) /*!< GPIO INT1EN: GPIO39 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO38_Pos (6UL) /*!< GPIO INT1EN: GPIO38 (Bit 6) */ -#define GPIO_INT1EN_GPIO38_Msk (0x40UL) /*!< GPIO INT1EN: GPIO38 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO37_Pos (5UL) /*!< GPIO INT1EN: GPIO37 (Bit 5) */ -#define GPIO_INT1EN_GPIO37_Msk (0x20UL) /*!< GPIO INT1EN: GPIO37 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO36_Pos (4UL) /*!< GPIO INT1EN: GPIO36 (Bit 4) */ -#define GPIO_INT1EN_GPIO36_Msk (0x10UL) /*!< GPIO INT1EN: GPIO36 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO35_Pos (3UL) /*!< GPIO INT1EN: GPIO35 (Bit 3) */ -#define GPIO_INT1EN_GPIO35_Msk (0x8UL) /*!< GPIO INT1EN: GPIO35 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO34_Pos (2UL) /*!< GPIO INT1EN: GPIO34 (Bit 2) */ -#define GPIO_INT1EN_GPIO34_Msk (0x4UL) /*!< GPIO INT1EN: GPIO34 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO33_Pos (1UL) /*!< GPIO INT1EN: GPIO33 (Bit 1) */ -#define GPIO_INT1EN_GPIO33_Msk (0x2UL) /*!< GPIO INT1EN: GPIO33 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1EN_GPIO32_Pos (0UL) /*!< GPIO INT1EN: GPIO32 (Bit 0) */ -#define GPIO_INT1EN_GPIO32_Msk (0x1UL) /*!< GPIO INT1EN: GPIO32 (Bitfield-Mask: 0x01) */ -/* ======================================================= INT1STAT ======================================================== */ -#define GPIO_INT1STAT_GPIO49_Pos (17UL) /*!< GPIO INT1STAT: GPIO49 (Bit 17) */ -#define GPIO_INT1STAT_GPIO49_Msk (0x20000UL) /*!< GPIO INT1STAT: GPIO49 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO48_Pos (16UL) /*!< GPIO INT1STAT: GPIO48 (Bit 16) */ -#define GPIO_INT1STAT_GPIO48_Msk (0x10000UL) /*!< GPIO INT1STAT: GPIO48 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO47_Pos (15UL) /*!< GPIO INT1STAT: GPIO47 (Bit 15) */ -#define GPIO_INT1STAT_GPIO47_Msk (0x8000UL) /*!< GPIO INT1STAT: GPIO47 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO46_Pos (14UL) /*!< GPIO INT1STAT: GPIO46 (Bit 14) */ -#define GPIO_INT1STAT_GPIO46_Msk (0x4000UL) /*!< GPIO INT1STAT: GPIO46 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO45_Pos (13UL) /*!< GPIO INT1STAT: GPIO45 (Bit 13) */ -#define GPIO_INT1STAT_GPIO45_Msk (0x2000UL) /*!< GPIO INT1STAT: GPIO45 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO44_Pos (12UL) /*!< GPIO INT1STAT: GPIO44 (Bit 12) */ -#define GPIO_INT1STAT_GPIO44_Msk (0x1000UL) /*!< GPIO INT1STAT: GPIO44 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO43_Pos (11UL) /*!< GPIO INT1STAT: GPIO43 (Bit 11) */ -#define GPIO_INT1STAT_GPIO43_Msk (0x800UL) /*!< GPIO INT1STAT: GPIO43 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO42_Pos (10UL) /*!< GPIO INT1STAT: GPIO42 (Bit 10) */ -#define GPIO_INT1STAT_GPIO42_Msk (0x400UL) /*!< GPIO INT1STAT: GPIO42 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO41_Pos (9UL) /*!< GPIO INT1STAT: GPIO41 (Bit 9) */ -#define GPIO_INT1STAT_GPIO41_Msk (0x200UL) /*!< GPIO INT1STAT: GPIO41 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO40_Pos (8UL) /*!< GPIO INT1STAT: GPIO40 (Bit 8) */ -#define GPIO_INT1STAT_GPIO40_Msk (0x100UL) /*!< GPIO INT1STAT: GPIO40 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO39_Pos (7UL) /*!< GPIO INT1STAT: GPIO39 (Bit 7) */ -#define GPIO_INT1STAT_GPIO39_Msk (0x80UL) /*!< GPIO INT1STAT: GPIO39 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO38_Pos (6UL) /*!< GPIO INT1STAT: GPIO38 (Bit 6) */ -#define GPIO_INT1STAT_GPIO38_Msk (0x40UL) /*!< GPIO INT1STAT: GPIO38 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO37_Pos (5UL) /*!< GPIO INT1STAT: GPIO37 (Bit 5) */ -#define GPIO_INT1STAT_GPIO37_Msk (0x20UL) /*!< GPIO INT1STAT: GPIO37 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO36_Pos (4UL) /*!< GPIO INT1STAT: GPIO36 (Bit 4) */ -#define GPIO_INT1STAT_GPIO36_Msk (0x10UL) /*!< GPIO INT1STAT: GPIO36 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO35_Pos (3UL) /*!< GPIO INT1STAT: GPIO35 (Bit 3) */ -#define GPIO_INT1STAT_GPIO35_Msk (0x8UL) /*!< GPIO INT1STAT: GPIO35 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO34_Pos (2UL) /*!< GPIO INT1STAT: GPIO34 (Bit 2) */ -#define GPIO_INT1STAT_GPIO34_Msk (0x4UL) /*!< GPIO INT1STAT: GPIO34 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO33_Pos (1UL) /*!< GPIO INT1STAT: GPIO33 (Bit 1) */ -#define GPIO_INT1STAT_GPIO33_Msk (0x2UL) /*!< GPIO INT1STAT: GPIO33 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1STAT_GPIO32_Pos (0UL) /*!< GPIO INT1STAT: GPIO32 (Bit 0) */ -#define GPIO_INT1STAT_GPIO32_Msk (0x1UL) /*!< GPIO INT1STAT: GPIO32 (Bitfield-Mask: 0x01) */ -/* ======================================================== INT1CLR ======================================================== */ -#define GPIO_INT1CLR_GPIO49_Pos (17UL) /*!< GPIO INT1CLR: GPIO49 (Bit 17) */ -#define GPIO_INT1CLR_GPIO49_Msk (0x20000UL) /*!< GPIO INT1CLR: GPIO49 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO48_Pos (16UL) /*!< GPIO INT1CLR: GPIO48 (Bit 16) */ -#define GPIO_INT1CLR_GPIO48_Msk (0x10000UL) /*!< GPIO INT1CLR: GPIO48 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO47_Pos (15UL) /*!< GPIO INT1CLR: GPIO47 (Bit 15) */ -#define GPIO_INT1CLR_GPIO47_Msk (0x8000UL) /*!< GPIO INT1CLR: GPIO47 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO46_Pos (14UL) /*!< GPIO INT1CLR: GPIO46 (Bit 14) */ -#define GPIO_INT1CLR_GPIO46_Msk (0x4000UL) /*!< GPIO INT1CLR: GPIO46 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO45_Pos (13UL) /*!< GPIO INT1CLR: GPIO45 (Bit 13) */ -#define GPIO_INT1CLR_GPIO45_Msk (0x2000UL) /*!< GPIO INT1CLR: GPIO45 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO44_Pos (12UL) /*!< GPIO INT1CLR: GPIO44 (Bit 12) */ -#define GPIO_INT1CLR_GPIO44_Msk (0x1000UL) /*!< GPIO INT1CLR: GPIO44 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO43_Pos (11UL) /*!< GPIO INT1CLR: GPIO43 (Bit 11) */ -#define GPIO_INT1CLR_GPIO43_Msk (0x800UL) /*!< GPIO INT1CLR: GPIO43 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO42_Pos (10UL) /*!< GPIO INT1CLR: GPIO42 (Bit 10) */ -#define GPIO_INT1CLR_GPIO42_Msk (0x400UL) /*!< GPIO INT1CLR: GPIO42 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO41_Pos (9UL) /*!< GPIO INT1CLR: GPIO41 (Bit 9) */ -#define GPIO_INT1CLR_GPIO41_Msk (0x200UL) /*!< GPIO INT1CLR: GPIO41 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO40_Pos (8UL) /*!< GPIO INT1CLR: GPIO40 (Bit 8) */ -#define GPIO_INT1CLR_GPIO40_Msk (0x100UL) /*!< GPIO INT1CLR: GPIO40 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO39_Pos (7UL) /*!< GPIO INT1CLR: GPIO39 (Bit 7) */ -#define GPIO_INT1CLR_GPIO39_Msk (0x80UL) /*!< GPIO INT1CLR: GPIO39 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO38_Pos (6UL) /*!< GPIO INT1CLR: GPIO38 (Bit 6) */ -#define GPIO_INT1CLR_GPIO38_Msk (0x40UL) /*!< GPIO INT1CLR: GPIO38 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO37_Pos (5UL) /*!< GPIO INT1CLR: GPIO37 (Bit 5) */ -#define GPIO_INT1CLR_GPIO37_Msk (0x20UL) /*!< GPIO INT1CLR: GPIO37 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO36_Pos (4UL) /*!< GPIO INT1CLR: GPIO36 (Bit 4) */ -#define GPIO_INT1CLR_GPIO36_Msk (0x10UL) /*!< GPIO INT1CLR: GPIO36 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO35_Pos (3UL) /*!< GPIO INT1CLR: GPIO35 (Bit 3) */ -#define GPIO_INT1CLR_GPIO35_Msk (0x8UL) /*!< GPIO INT1CLR: GPIO35 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO34_Pos (2UL) /*!< GPIO INT1CLR: GPIO34 (Bit 2) */ -#define GPIO_INT1CLR_GPIO34_Msk (0x4UL) /*!< GPIO INT1CLR: GPIO34 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO33_Pos (1UL) /*!< GPIO INT1CLR: GPIO33 (Bit 1) */ -#define GPIO_INT1CLR_GPIO33_Msk (0x2UL) /*!< GPIO INT1CLR: GPIO33 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1CLR_GPIO32_Pos (0UL) /*!< GPIO INT1CLR: GPIO32 (Bit 0) */ -#define GPIO_INT1CLR_GPIO32_Msk (0x1UL) /*!< GPIO INT1CLR: GPIO32 (Bitfield-Mask: 0x01) */ -/* ======================================================== INT1SET ======================================================== */ -#define GPIO_INT1SET_GPIO49_Pos (17UL) /*!< GPIO INT1SET: GPIO49 (Bit 17) */ -#define GPIO_INT1SET_GPIO49_Msk (0x20000UL) /*!< GPIO INT1SET: GPIO49 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO48_Pos (16UL) /*!< GPIO INT1SET: GPIO48 (Bit 16) */ -#define GPIO_INT1SET_GPIO48_Msk (0x10000UL) /*!< GPIO INT1SET: GPIO48 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO47_Pos (15UL) /*!< GPIO INT1SET: GPIO47 (Bit 15) */ -#define GPIO_INT1SET_GPIO47_Msk (0x8000UL) /*!< GPIO INT1SET: GPIO47 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO46_Pos (14UL) /*!< GPIO INT1SET: GPIO46 (Bit 14) */ -#define GPIO_INT1SET_GPIO46_Msk (0x4000UL) /*!< GPIO INT1SET: GPIO46 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO45_Pos (13UL) /*!< GPIO INT1SET: GPIO45 (Bit 13) */ -#define GPIO_INT1SET_GPIO45_Msk (0x2000UL) /*!< GPIO INT1SET: GPIO45 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO44_Pos (12UL) /*!< GPIO INT1SET: GPIO44 (Bit 12) */ -#define GPIO_INT1SET_GPIO44_Msk (0x1000UL) /*!< GPIO INT1SET: GPIO44 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO43_Pos (11UL) /*!< GPIO INT1SET: GPIO43 (Bit 11) */ -#define GPIO_INT1SET_GPIO43_Msk (0x800UL) /*!< GPIO INT1SET: GPIO43 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO42_Pos (10UL) /*!< GPIO INT1SET: GPIO42 (Bit 10) */ -#define GPIO_INT1SET_GPIO42_Msk (0x400UL) /*!< GPIO INT1SET: GPIO42 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO41_Pos (9UL) /*!< GPIO INT1SET: GPIO41 (Bit 9) */ -#define GPIO_INT1SET_GPIO41_Msk (0x200UL) /*!< GPIO INT1SET: GPIO41 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO40_Pos (8UL) /*!< GPIO INT1SET: GPIO40 (Bit 8) */ -#define GPIO_INT1SET_GPIO40_Msk (0x100UL) /*!< GPIO INT1SET: GPIO40 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO39_Pos (7UL) /*!< GPIO INT1SET: GPIO39 (Bit 7) */ -#define GPIO_INT1SET_GPIO39_Msk (0x80UL) /*!< GPIO INT1SET: GPIO39 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO38_Pos (6UL) /*!< GPIO INT1SET: GPIO38 (Bit 6) */ -#define GPIO_INT1SET_GPIO38_Msk (0x40UL) /*!< GPIO INT1SET: GPIO38 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO37_Pos (5UL) /*!< GPIO INT1SET: GPIO37 (Bit 5) */ -#define GPIO_INT1SET_GPIO37_Msk (0x20UL) /*!< GPIO INT1SET: GPIO37 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO36_Pos (4UL) /*!< GPIO INT1SET: GPIO36 (Bit 4) */ -#define GPIO_INT1SET_GPIO36_Msk (0x10UL) /*!< GPIO INT1SET: GPIO36 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO35_Pos (3UL) /*!< GPIO INT1SET: GPIO35 (Bit 3) */ -#define GPIO_INT1SET_GPIO35_Msk (0x8UL) /*!< GPIO INT1SET: GPIO35 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO34_Pos (2UL) /*!< GPIO INT1SET: GPIO34 (Bit 2) */ -#define GPIO_INT1SET_GPIO34_Msk (0x4UL) /*!< GPIO INT1SET: GPIO34 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO33_Pos (1UL) /*!< GPIO INT1SET: GPIO33 (Bit 1) */ -#define GPIO_INT1SET_GPIO33_Msk (0x2UL) /*!< GPIO INT1SET: GPIO33 (Bitfield-Mask: 0x01) */ -#define GPIO_INT1SET_GPIO32_Pos (0UL) /*!< GPIO INT1SET: GPIO32 (Bit 0) */ -#define GPIO_INT1SET_GPIO32_Msk (0x1UL) /*!< GPIO INT1SET: GPIO32 (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ IOM0 ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= FIFO ========================================================== */ -#define IOM0_FIFO_FIFO_Pos (0UL) /*!< IOM0 FIFO: FIFO (Bit 0) */ -#define IOM0_FIFO_FIFO_Msk (0xffffffffUL) /*!< IOM0 FIFO: FIFO (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== FIFOPTR ======================================================== */ -#define IOM0_FIFOPTR_FIFO1REM_Pos (24UL) /*!< IOM0 FIFOPTR: FIFO1REM (Bit 24) */ -#define IOM0_FIFOPTR_FIFO1REM_Msk (0xff000000UL) /*!< IOM0 FIFOPTR: FIFO1REM (Bitfield-Mask: 0xff) */ -#define IOM0_FIFOPTR_FIFO1SIZ_Pos (16UL) /*!< IOM0 FIFOPTR: FIFO1SIZ (Bit 16) */ -#define IOM0_FIFOPTR_FIFO1SIZ_Msk (0xff0000UL) /*!< IOM0 FIFOPTR: FIFO1SIZ (Bitfield-Mask: 0xff) */ -#define IOM0_FIFOPTR_FIFO0REM_Pos (8UL) /*!< IOM0 FIFOPTR: FIFO0REM (Bit 8) */ -#define IOM0_FIFOPTR_FIFO0REM_Msk (0xff00UL) /*!< IOM0 FIFOPTR: FIFO0REM (Bitfield-Mask: 0xff) */ -#define IOM0_FIFOPTR_FIFO0SIZ_Pos (0UL) /*!< IOM0 FIFOPTR: FIFO0SIZ (Bit 0) */ -#define IOM0_FIFOPTR_FIFO0SIZ_Msk (0xffUL) /*!< IOM0 FIFOPTR: FIFO0SIZ (Bitfield-Mask: 0xff) */ -/* ======================================================== FIFOTHR ======================================================== */ -#define IOM0_FIFOTHR_FIFOWTHR_Pos (8UL) /*!< IOM0 FIFOTHR: FIFOWTHR (Bit 8) */ -#define IOM0_FIFOTHR_FIFOWTHR_Msk (0x3f00UL) /*!< IOM0 FIFOTHR: FIFOWTHR (Bitfield-Mask: 0x3f) */ -#define IOM0_FIFOTHR_FIFORTHR_Pos (0UL) /*!< IOM0 FIFOTHR: FIFORTHR (Bit 0) */ -#define IOM0_FIFOTHR_FIFORTHR_Msk (0x3fUL) /*!< IOM0 FIFOTHR: FIFORTHR (Bitfield-Mask: 0x3f) */ -/* ======================================================== FIFOPOP ======================================================== */ -#define IOM0_FIFOPOP_FIFODOUT_Pos (0UL) /*!< IOM0 FIFOPOP: FIFODOUT (Bit 0) */ -#define IOM0_FIFOPOP_FIFODOUT_Msk (0xffffffffUL) /*!< IOM0 FIFOPOP: FIFODOUT (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= FIFOPUSH ======================================================== */ -#define IOM0_FIFOPUSH_FIFODIN_Pos (0UL) /*!< IOM0 FIFOPUSH: FIFODIN (Bit 0) */ -#define IOM0_FIFOPUSH_FIFODIN_Msk (0xffffffffUL) /*!< IOM0 FIFOPUSH: FIFODIN (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= FIFOCTRL ======================================================== */ -#define IOM0_FIFOCTRL_FIFORSTN_Pos (1UL) /*!< IOM0 FIFOCTRL: FIFORSTN (Bit 1) */ -#define IOM0_FIFOCTRL_FIFORSTN_Msk (0x2UL) /*!< IOM0 FIFOCTRL: FIFORSTN (Bitfield-Mask: 0x01) */ -#define IOM0_FIFOCTRL_POPWR_Pos (0UL) /*!< IOM0 FIFOCTRL: POPWR (Bit 0) */ -#define IOM0_FIFOCTRL_POPWR_Msk (0x1UL) /*!< IOM0 FIFOCTRL: POPWR (Bitfield-Mask: 0x01) */ -/* ======================================================== FIFOLOC ======================================================== */ -#define IOM0_FIFOLOC_FIFORPTR_Pos (8UL) /*!< IOM0 FIFOLOC: FIFORPTR (Bit 8) */ -#define IOM0_FIFOLOC_FIFORPTR_Msk (0xf00UL) /*!< IOM0 FIFOLOC: FIFORPTR (Bitfield-Mask: 0x0f) */ -#define IOM0_FIFOLOC_FIFOWPTR_Pos (0UL) /*!< IOM0 FIFOLOC: FIFOWPTR (Bit 0) */ -#define IOM0_FIFOLOC_FIFOWPTR_Msk (0xfUL) /*!< IOM0 FIFOLOC: FIFOWPTR (Bitfield-Mask: 0x0f) */ -/* ========================================================= INTEN ========================================================= */ -#define IOM0_INTEN_CQERR_Pos (14UL) /*!< IOM0 INTEN: CQERR (Bit 14) */ -#define IOM0_INTEN_CQERR_Msk (0x4000UL) /*!< IOM0 INTEN: CQERR (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_CQUPD_Pos (13UL) /*!< IOM0 INTEN: CQUPD (Bit 13) */ -#define IOM0_INTEN_CQUPD_Msk (0x2000UL) /*!< IOM0 INTEN: CQUPD (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_CQPAUSED_Pos (12UL) /*!< IOM0 INTEN: CQPAUSED (Bit 12) */ -#define IOM0_INTEN_CQPAUSED_Msk (0x1000UL) /*!< IOM0 INTEN: CQPAUSED (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_DERR_Pos (11UL) /*!< IOM0 INTEN: DERR (Bit 11) */ -#define IOM0_INTEN_DERR_Msk (0x800UL) /*!< IOM0 INTEN: DERR (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_DCMP_Pos (10UL) /*!< IOM0 INTEN: DCMP (Bit 10) */ -#define IOM0_INTEN_DCMP_Msk (0x400UL) /*!< IOM0 INTEN: DCMP (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_ARB_Pos (9UL) /*!< IOM0 INTEN: ARB (Bit 9) */ -#define IOM0_INTEN_ARB_Msk (0x200UL) /*!< IOM0 INTEN: ARB (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_STOP_Pos (8UL) /*!< IOM0 INTEN: STOP (Bit 8) */ -#define IOM0_INTEN_STOP_Msk (0x100UL) /*!< IOM0 INTEN: STOP (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_START_Pos (7UL) /*!< IOM0 INTEN: START (Bit 7) */ -#define IOM0_INTEN_START_Msk (0x80UL) /*!< IOM0 INTEN: START (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_ICMD_Pos (6UL) /*!< IOM0 INTEN: ICMD (Bit 6) */ -#define IOM0_INTEN_ICMD_Msk (0x40UL) /*!< IOM0 INTEN: ICMD (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_IACC_Pos (5UL) /*!< IOM0 INTEN: IACC (Bit 5) */ -#define IOM0_INTEN_IACC_Msk (0x20UL) /*!< IOM0 INTEN: IACC (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_NAK_Pos (4UL) /*!< IOM0 INTEN: NAK (Bit 4) */ -#define IOM0_INTEN_NAK_Msk (0x10UL) /*!< IOM0 INTEN: NAK (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_FOVFL_Pos (3UL) /*!< IOM0 INTEN: FOVFL (Bit 3) */ -#define IOM0_INTEN_FOVFL_Msk (0x8UL) /*!< IOM0 INTEN: FOVFL (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_FUNDFL_Pos (2UL) /*!< IOM0 INTEN: FUNDFL (Bit 2) */ -#define IOM0_INTEN_FUNDFL_Msk (0x4UL) /*!< IOM0 INTEN: FUNDFL (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_THR_Pos (1UL) /*!< IOM0 INTEN: THR (Bit 1) */ -#define IOM0_INTEN_THR_Msk (0x2UL) /*!< IOM0 INTEN: THR (Bitfield-Mask: 0x01) */ -#define IOM0_INTEN_CMDCMP_Pos (0UL) /*!< IOM0 INTEN: CMDCMP (Bit 0) */ -#define IOM0_INTEN_CMDCMP_Msk (0x1UL) /*!< IOM0 INTEN: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define IOM0_INTSTAT_CQERR_Pos (14UL) /*!< IOM0 INTSTAT: CQERR (Bit 14) */ -#define IOM0_INTSTAT_CQERR_Msk (0x4000UL) /*!< IOM0 INTSTAT: CQERR (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_CQUPD_Pos (13UL) /*!< IOM0 INTSTAT: CQUPD (Bit 13) */ -#define IOM0_INTSTAT_CQUPD_Msk (0x2000UL) /*!< IOM0 INTSTAT: CQUPD (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_CQPAUSED_Pos (12UL) /*!< IOM0 INTSTAT: CQPAUSED (Bit 12) */ -#define IOM0_INTSTAT_CQPAUSED_Msk (0x1000UL) /*!< IOM0 INTSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_DERR_Pos (11UL) /*!< IOM0 INTSTAT: DERR (Bit 11) */ -#define IOM0_INTSTAT_DERR_Msk (0x800UL) /*!< IOM0 INTSTAT: DERR (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_DCMP_Pos (10UL) /*!< IOM0 INTSTAT: DCMP (Bit 10) */ -#define IOM0_INTSTAT_DCMP_Msk (0x400UL) /*!< IOM0 INTSTAT: DCMP (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_ARB_Pos (9UL) /*!< IOM0 INTSTAT: ARB (Bit 9) */ -#define IOM0_INTSTAT_ARB_Msk (0x200UL) /*!< IOM0 INTSTAT: ARB (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_STOP_Pos (8UL) /*!< IOM0 INTSTAT: STOP (Bit 8) */ -#define IOM0_INTSTAT_STOP_Msk (0x100UL) /*!< IOM0 INTSTAT: STOP (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_START_Pos (7UL) /*!< IOM0 INTSTAT: START (Bit 7) */ -#define IOM0_INTSTAT_START_Msk (0x80UL) /*!< IOM0 INTSTAT: START (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_ICMD_Pos (6UL) /*!< IOM0 INTSTAT: ICMD (Bit 6) */ -#define IOM0_INTSTAT_ICMD_Msk (0x40UL) /*!< IOM0 INTSTAT: ICMD (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_IACC_Pos (5UL) /*!< IOM0 INTSTAT: IACC (Bit 5) */ -#define IOM0_INTSTAT_IACC_Msk (0x20UL) /*!< IOM0 INTSTAT: IACC (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_NAK_Pos (4UL) /*!< IOM0 INTSTAT: NAK (Bit 4) */ -#define IOM0_INTSTAT_NAK_Msk (0x10UL) /*!< IOM0 INTSTAT: NAK (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_FOVFL_Pos (3UL) /*!< IOM0 INTSTAT: FOVFL (Bit 3) */ -#define IOM0_INTSTAT_FOVFL_Msk (0x8UL) /*!< IOM0 INTSTAT: FOVFL (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_FUNDFL_Pos (2UL) /*!< IOM0 INTSTAT: FUNDFL (Bit 2) */ -#define IOM0_INTSTAT_FUNDFL_Msk (0x4UL) /*!< IOM0 INTSTAT: FUNDFL (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_THR_Pos (1UL) /*!< IOM0 INTSTAT: THR (Bit 1) */ -#define IOM0_INTSTAT_THR_Msk (0x2UL) /*!< IOM0 INTSTAT: THR (Bitfield-Mask: 0x01) */ -#define IOM0_INTSTAT_CMDCMP_Pos (0UL) /*!< IOM0 INTSTAT: CMDCMP (Bit 0) */ -#define IOM0_INTSTAT_CMDCMP_Msk (0x1UL) /*!< IOM0 INTSTAT: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define IOM0_INTCLR_CQERR_Pos (14UL) /*!< IOM0 INTCLR: CQERR (Bit 14) */ -#define IOM0_INTCLR_CQERR_Msk (0x4000UL) /*!< IOM0 INTCLR: CQERR (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_CQUPD_Pos (13UL) /*!< IOM0 INTCLR: CQUPD (Bit 13) */ -#define IOM0_INTCLR_CQUPD_Msk (0x2000UL) /*!< IOM0 INTCLR: CQUPD (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_CQPAUSED_Pos (12UL) /*!< IOM0 INTCLR: CQPAUSED (Bit 12) */ -#define IOM0_INTCLR_CQPAUSED_Msk (0x1000UL) /*!< IOM0 INTCLR: CQPAUSED (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_DERR_Pos (11UL) /*!< IOM0 INTCLR: DERR (Bit 11) */ -#define IOM0_INTCLR_DERR_Msk (0x800UL) /*!< IOM0 INTCLR: DERR (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_DCMP_Pos (10UL) /*!< IOM0 INTCLR: DCMP (Bit 10) */ -#define IOM0_INTCLR_DCMP_Msk (0x400UL) /*!< IOM0 INTCLR: DCMP (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_ARB_Pos (9UL) /*!< IOM0 INTCLR: ARB (Bit 9) */ -#define IOM0_INTCLR_ARB_Msk (0x200UL) /*!< IOM0 INTCLR: ARB (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_STOP_Pos (8UL) /*!< IOM0 INTCLR: STOP (Bit 8) */ -#define IOM0_INTCLR_STOP_Msk (0x100UL) /*!< IOM0 INTCLR: STOP (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_START_Pos (7UL) /*!< IOM0 INTCLR: START (Bit 7) */ -#define IOM0_INTCLR_START_Msk (0x80UL) /*!< IOM0 INTCLR: START (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_ICMD_Pos (6UL) /*!< IOM0 INTCLR: ICMD (Bit 6) */ -#define IOM0_INTCLR_ICMD_Msk (0x40UL) /*!< IOM0 INTCLR: ICMD (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_IACC_Pos (5UL) /*!< IOM0 INTCLR: IACC (Bit 5) */ -#define IOM0_INTCLR_IACC_Msk (0x20UL) /*!< IOM0 INTCLR: IACC (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_NAK_Pos (4UL) /*!< IOM0 INTCLR: NAK (Bit 4) */ -#define IOM0_INTCLR_NAK_Msk (0x10UL) /*!< IOM0 INTCLR: NAK (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_FOVFL_Pos (3UL) /*!< IOM0 INTCLR: FOVFL (Bit 3) */ -#define IOM0_INTCLR_FOVFL_Msk (0x8UL) /*!< IOM0 INTCLR: FOVFL (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_FUNDFL_Pos (2UL) /*!< IOM0 INTCLR: FUNDFL (Bit 2) */ -#define IOM0_INTCLR_FUNDFL_Msk (0x4UL) /*!< IOM0 INTCLR: FUNDFL (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_THR_Pos (1UL) /*!< IOM0 INTCLR: THR (Bit 1) */ -#define IOM0_INTCLR_THR_Msk (0x2UL) /*!< IOM0 INTCLR: THR (Bitfield-Mask: 0x01) */ -#define IOM0_INTCLR_CMDCMP_Pos (0UL) /*!< IOM0 INTCLR: CMDCMP (Bit 0) */ -#define IOM0_INTCLR_CMDCMP_Msk (0x1UL) /*!< IOM0 INTCLR: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define IOM0_INTSET_CQERR_Pos (14UL) /*!< IOM0 INTSET: CQERR (Bit 14) */ -#define IOM0_INTSET_CQERR_Msk (0x4000UL) /*!< IOM0 INTSET: CQERR (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_CQUPD_Pos (13UL) /*!< IOM0 INTSET: CQUPD (Bit 13) */ -#define IOM0_INTSET_CQUPD_Msk (0x2000UL) /*!< IOM0 INTSET: CQUPD (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_CQPAUSED_Pos (12UL) /*!< IOM0 INTSET: CQPAUSED (Bit 12) */ -#define IOM0_INTSET_CQPAUSED_Msk (0x1000UL) /*!< IOM0 INTSET: CQPAUSED (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_DERR_Pos (11UL) /*!< IOM0 INTSET: DERR (Bit 11) */ -#define IOM0_INTSET_DERR_Msk (0x800UL) /*!< IOM0 INTSET: DERR (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_DCMP_Pos (10UL) /*!< IOM0 INTSET: DCMP (Bit 10) */ -#define IOM0_INTSET_DCMP_Msk (0x400UL) /*!< IOM0 INTSET: DCMP (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_ARB_Pos (9UL) /*!< IOM0 INTSET: ARB (Bit 9) */ -#define IOM0_INTSET_ARB_Msk (0x200UL) /*!< IOM0 INTSET: ARB (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_STOP_Pos (8UL) /*!< IOM0 INTSET: STOP (Bit 8) */ -#define IOM0_INTSET_STOP_Msk (0x100UL) /*!< IOM0 INTSET: STOP (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_START_Pos (7UL) /*!< IOM0 INTSET: START (Bit 7) */ -#define IOM0_INTSET_START_Msk (0x80UL) /*!< IOM0 INTSET: START (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_ICMD_Pos (6UL) /*!< IOM0 INTSET: ICMD (Bit 6) */ -#define IOM0_INTSET_ICMD_Msk (0x40UL) /*!< IOM0 INTSET: ICMD (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_IACC_Pos (5UL) /*!< IOM0 INTSET: IACC (Bit 5) */ -#define IOM0_INTSET_IACC_Msk (0x20UL) /*!< IOM0 INTSET: IACC (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_NAK_Pos (4UL) /*!< IOM0 INTSET: NAK (Bit 4) */ -#define IOM0_INTSET_NAK_Msk (0x10UL) /*!< IOM0 INTSET: NAK (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_FOVFL_Pos (3UL) /*!< IOM0 INTSET: FOVFL (Bit 3) */ -#define IOM0_INTSET_FOVFL_Msk (0x8UL) /*!< IOM0 INTSET: FOVFL (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_FUNDFL_Pos (2UL) /*!< IOM0 INTSET: FUNDFL (Bit 2) */ -#define IOM0_INTSET_FUNDFL_Msk (0x4UL) /*!< IOM0 INTSET: FUNDFL (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_THR_Pos (1UL) /*!< IOM0 INTSET: THR (Bit 1) */ -#define IOM0_INTSET_THR_Msk (0x2UL) /*!< IOM0 INTSET: THR (Bitfield-Mask: 0x01) */ -#define IOM0_INTSET_CMDCMP_Pos (0UL) /*!< IOM0 INTSET: CMDCMP (Bit 0) */ -#define IOM0_INTSET_CMDCMP_Msk (0x1UL) /*!< IOM0 INTSET: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== CLKCFG ========================================================= */ -#define IOM0_CLKCFG_TOTPER_Pos (24UL) /*!< IOM0 CLKCFG: TOTPER (Bit 24) */ -#define IOM0_CLKCFG_TOTPER_Msk (0xff000000UL) /*!< IOM0 CLKCFG: TOTPER (Bitfield-Mask: 0xff) */ -#define IOM0_CLKCFG_LOWPER_Pos (16UL) /*!< IOM0 CLKCFG: LOWPER (Bit 16) */ -#define IOM0_CLKCFG_LOWPER_Msk (0xff0000UL) /*!< IOM0 CLKCFG: LOWPER (Bitfield-Mask: 0xff) */ -#define IOM0_CLKCFG_DIVEN_Pos (12UL) /*!< IOM0 CLKCFG: DIVEN (Bit 12) */ -#define IOM0_CLKCFG_DIVEN_Msk (0x1000UL) /*!< IOM0 CLKCFG: DIVEN (Bitfield-Mask: 0x01) */ -#define IOM0_CLKCFG_DIV3_Pos (11UL) /*!< IOM0 CLKCFG: DIV3 (Bit 11) */ -#define IOM0_CLKCFG_DIV3_Msk (0x800UL) /*!< IOM0 CLKCFG: DIV3 (Bitfield-Mask: 0x01) */ -#define IOM0_CLKCFG_FSEL_Pos (8UL) /*!< IOM0 CLKCFG: FSEL (Bit 8) */ -#define IOM0_CLKCFG_FSEL_Msk (0x700UL) /*!< IOM0 CLKCFG: FSEL (Bitfield-Mask: 0x07) */ -#define IOM0_CLKCFG_IOCLKEN_Pos (0UL) /*!< IOM0 CLKCFG: IOCLKEN (Bit 0) */ -#define IOM0_CLKCFG_IOCLKEN_Msk (0x1UL) /*!< IOM0 CLKCFG: IOCLKEN (Bitfield-Mask: 0x01) */ -/* ====================================================== SUBMODCTRL ======================================================= */ -#define IOM0_SUBMODCTRL_SMOD1TYPE_Pos (5UL) /*!< IOM0 SUBMODCTRL: SMOD1TYPE (Bit 5) */ -#define IOM0_SUBMODCTRL_SMOD1TYPE_Msk (0xe0UL) /*!< IOM0 SUBMODCTRL: SMOD1TYPE (Bitfield-Mask: 0x07) */ -#define IOM0_SUBMODCTRL_SMOD1EN_Pos (4UL) /*!< IOM0 SUBMODCTRL: SMOD1EN (Bit 4) */ -#define IOM0_SUBMODCTRL_SMOD1EN_Msk (0x10UL) /*!< IOM0 SUBMODCTRL: SMOD1EN (Bitfield-Mask: 0x01) */ -#define IOM0_SUBMODCTRL_SMOD0TYPE_Pos (1UL) /*!< IOM0 SUBMODCTRL: SMOD0TYPE (Bit 1) */ -#define IOM0_SUBMODCTRL_SMOD0TYPE_Msk (0xeUL) /*!< IOM0 SUBMODCTRL: SMOD0TYPE (Bitfield-Mask: 0x07) */ -#define IOM0_SUBMODCTRL_SMOD0EN_Pos (0UL) /*!< IOM0 SUBMODCTRL: SMOD0EN (Bit 0) */ -#define IOM0_SUBMODCTRL_SMOD0EN_Msk (0x1UL) /*!< IOM0 SUBMODCTRL: SMOD0EN (Bitfield-Mask: 0x01) */ -/* ========================================================== CMD ========================================================== */ -#define IOM0_CMD_OFFSETLO_Pos (24UL) /*!< IOM0 CMD: OFFSETLO (Bit 24) */ -#define IOM0_CMD_OFFSETLO_Msk (0xff000000UL) /*!< IOM0 CMD: OFFSETLO (Bitfield-Mask: 0xff) */ -#define IOM0_CMD_CMDSEL_Pos (20UL) /*!< IOM0 CMD: CMDSEL (Bit 20) */ -#define IOM0_CMD_CMDSEL_Msk (0x300000UL) /*!< IOM0 CMD: CMDSEL (Bitfield-Mask: 0x03) */ -#define IOM0_CMD_TSIZE_Pos (8UL) /*!< IOM0 CMD: TSIZE (Bit 8) */ -#define IOM0_CMD_TSIZE_Msk (0xfff00UL) /*!< IOM0 CMD: TSIZE (Bitfield-Mask: 0xfff) */ -#define IOM0_CMD_CONT_Pos (7UL) /*!< IOM0 CMD: CONT (Bit 7) */ -#define IOM0_CMD_CONT_Msk (0x80UL) /*!< IOM0 CMD: CONT (Bitfield-Mask: 0x01) */ -#define IOM0_CMD_OFFSETCNT_Pos (5UL) /*!< IOM0 CMD: OFFSETCNT (Bit 5) */ -#define IOM0_CMD_OFFSETCNT_Msk (0x60UL) /*!< IOM0 CMD: OFFSETCNT (Bitfield-Mask: 0x03) */ -#define IOM0_CMD_CMD_Pos (0UL) /*!< IOM0 CMD: CMD (Bit 0) */ -#define IOM0_CMD_CMD_Msk (0x1fUL) /*!< IOM0 CMD: CMD (Bitfield-Mask: 0x1f) */ -/* ======================================================== CMDRPT ========================================================= */ -#define IOM0_CMDRPT_CMDRPT_Pos (0UL) /*!< IOM0 CMDRPT: CMDRPT (Bit 0) */ -#define IOM0_CMDRPT_CMDRPT_Msk (0x1fUL) /*!< IOM0 CMDRPT: CMDRPT (Bitfield-Mask: 0x1f) */ -/* ======================================================= OFFSETHI ======================================================== */ -#define IOM0_OFFSETHI_OFFSETHI_Pos (0UL) /*!< IOM0 OFFSETHI: OFFSETHI (Bit 0) */ -#define IOM0_OFFSETHI_OFFSETHI_Msk (0xffffUL) /*!< IOM0 OFFSETHI: OFFSETHI (Bitfield-Mask: 0xffff) */ -/* ======================================================== CMDSTAT ======================================================== */ -#define IOM0_CMDSTAT_CTSIZE_Pos (8UL) /*!< IOM0 CMDSTAT: CTSIZE (Bit 8) */ -#define IOM0_CMDSTAT_CTSIZE_Msk (0xfff00UL) /*!< IOM0 CMDSTAT: CTSIZE (Bitfield-Mask: 0xfff) */ -#define IOM0_CMDSTAT_CMDSTAT_Pos (5UL) /*!< IOM0 CMDSTAT: CMDSTAT (Bit 5) */ -#define IOM0_CMDSTAT_CMDSTAT_Msk (0xe0UL) /*!< IOM0 CMDSTAT: CMDSTAT (Bitfield-Mask: 0x07) */ -#define IOM0_CMDSTAT_CCMD_Pos (0UL) /*!< IOM0 CMDSTAT: CCMD (Bit 0) */ -#define IOM0_CMDSTAT_CCMD_Msk (0x1fUL) /*!< IOM0 CMDSTAT: CCMD (Bitfield-Mask: 0x1f) */ -/* ======================================================= DMATRIGEN ======================================================= */ -#define IOM0_DMATRIGEN_DTHREN_Pos (1UL) /*!< IOM0 DMATRIGEN: DTHREN (Bit 1) */ -#define IOM0_DMATRIGEN_DTHREN_Msk (0x2UL) /*!< IOM0 DMATRIGEN: DTHREN (Bitfield-Mask: 0x01) */ -#define IOM0_DMATRIGEN_DCMDCMPEN_Pos (0UL) /*!< IOM0 DMATRIGEN: DCMDCMPEN (Bit 0) */ -#define IOM0_DMATRIGEN_DCMDCMPEN_Msk (0x1UL) /*!< IOM0 DMATRIGEN: DCMDCMPEN (Bitfield-Mask: 0x01) */ -/* ====================================================== DMATRIGSTAT ====================================================== */ -#define IOM0_DMATRIGSTAT_DTOTCMP_Pos (2UL) /*!< IOM0 DMATRIGSTAT: DTOTCMP (Bit 2) */ -#define IOM0_DMATRIGSTAT_DTOTCMP_Msk (0x4UL) /*!< IOM0 DMATRIGSTAT: DTOTCMP (Bitfield-Mask: 0x01) */ -#define IOM0_DMATRIGSTAT_DTHR_Pos (1UL) /*!< IOM0 DMATRIGSTAT: DTHR (Bit 1) */ -#define IOM0_DMATRIGSTAT_DTHR_Msk (0x2UL) /*!< IOM0 DMATRIGSTAT: DTHR (Bitfield-Mask: 0x01) */ -#define IOM0_DMATRIGSTAT_DCMDCMP_Pos (0UL) /*!< IOM0 DMATRIGSTAT: DCMDCMP (Bit 0) */ -#define IOM0_DMATRIGSTAT_DCMDCMP_Msk (0x1UL) /*!< IOM0 DMATRIGSTAT: DCMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== DMACFG ========================================================= */ -#define IOM0_DMACFG_DPWROFF_Pos (9UL) /*!< IOM0 DMACFG: DPWROFF (Bit 9) */ -#define IOM0_DMACFG_DPWROFF_Msk (0x200UL) /*!< IOM0 DMACFG: DPWROFF (Bitfield-Mask: 0x01) */ -#define IOM0_DMACFG_DMAPRI_Pos (8UL) /*!< IOM0 DMACFG: DMAPRI (Bit 8) */ -#define IOM0_DMACFG_DMAPRI_Msk (0x100UL) /*!< IOM0 DMACFG: DMAPRI (Bitfield-Mask: 0x01) */ -#define IOM0_DMACFG_DMADIR_Pos (1UL) /*!< IOM0 DMACFG: DMADIR (Bit 1) */ -#define IOM0_DMACFG_DMADIR_Msk (0x2UL) /*!< IOM0 DMACFG: DMADIR (Bitfield-Mask: 0x01) */ -#define IOM0_DMACFG_DMAEN_Pos (0UL) /*!< IOM0 DMACFG: DMAEN (Bit 0) */ -#define IOM0_DMACFG_DMAEN_Msk (0x1UL) /*!< IOM0 DMACFG: DMAEN (Bitfield-Mask: 0x01) */ -/* ====================================================== DMATOTCOUNT ====================================================== */ -#define IOM0_DMATOTCOUNT_TOTCOUNT_Pos (0UL) /*!< IOM0 DMATOTCOUNT: TOTCOUNT (Bit 0) */ -#define IOM0_DMATOTCOUNT_TOTCOUNT_Msk (0xfffUL) /*!< IOM0 DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xfff) */ -/* ====================================================== DMATARGADDR ====================================================== */ -#define IOM0_DMATARGADDR_TARGADDR28_Pos (28UL) /*!< IOM0 DMATARGADDR: TARGADDR28 (Bit 28) */ -#define IOM0_DMATARGADDR_TARGADDR28_Msk (0x10000000UL) /*!< IOM0 DMATARGADDR: TARGADDR28 (Bitfield-Mask: 0x01) */ -#define IOM0_DMATARGADDR_TARGADDR_Pos (0UL) /*!< IOM0 DMATARGADDR: TARGADDR (Bit 0) */ -#define IOM0_DMATARGADDR_TARGADDR_Msk (0xfffffUL) /*!< IOM0 DMATARGADDR: TARGADDR (Bitfield-Mask: 0xfffff) */ -/* ======================================================== DMASTAT ======================================================== */ -#define IOM0_DMASTAT_DMAERR_Pos (2UL) /*!< IOM0 DMASTAT: DMAERR (Bit 2) */ -#define IOM0_DMASTAT_DMAERR_Msk (0x4UL) /*!< IOM0 DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ -#define IOM0_DMASTAT_DMACPL_Pos (1UL) /*!< IOM0 DMASTAT: DMACPL (Bit 1) */ -#define IOM0_DMASTAT_DMACPL_Msk (0x2UL) /*!< IOM0 DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ -#define IOM0_DMASTAT_DMATIP_Pos (0UL) /*!< IOM0 DMASTAT: DMATIP (Bit 0) */ -#define IOM0_DMASTAT_DMATIP_Msk (0x1UL) /*!< IOM0 DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ -/* ========================================================= CQCFG ========================================================= */ -#define IOM0_CQCFG_CQPRI_Pos (1UL) /*!< IOM0 CQCFG: CQPRI (Bit 1) */ -#define IOM0_CQCFG_CQPRI_Msk (0x2UL) /*!< IOM0 CQCFG: CQPRI (Bitfield-Mask: 0x01) */ -#define IOM0_CQCFG_CQEN_Pos (0UL) /*!< IOM0 CQCFG: CQEN (Bit 0) */ -#define IOM0_CQCFG_CQEN_Msk (0x1UL) /*!< IOM0 CQCFG: CQEN (Bitfield-Mask: 0x01) */ -/* ======================================================== CQADDR ========================================================= */ -#define IOM0_CQADDR_CQADDR28_Pos (28UL) /*!< IOM0 CQADDR: CQADDR28 (Bit 28) */ -#define IOM0_CQADDR_CQADDR28_Msk (0x10000000UL) /*!< IOM0 CQADDR: CQADDR28 (Bitfield-Mask: 0x01) */ -#define IOM0_CQADDR_CQADDR_Pos (2UL) /*!< IOM0 CQADDR: CQADDR (Bit 2) */ -#define IOM0_CQADDR_CQADDR_Msk (0xffffcUL) /*!< IOM0 CQADDR: CQADDR (Bitfield-Mask: 0x3ffff) */ -/* ======================================================== CQSTAT ========================================================= */ -#define IOM0_CQSTAT_CQERR_Pos (2UL) /*!< IOM0 CQSTAT: CQERR (Bit 2) */ -#define IOM0_CQSTAT_CQERR_Msk (0x4UL) /*!< IOM0 CQSTAT: CQERR (Bitfield-Mask: 0x01) */ -#define IOM0_CQSTAT_CQPAUSED_Pos (1UL) /*!< IOM0 CQSTAT: CQPAUSED (Bit 1) */ -#define IOM0_CQSTAT_CQPAUSED_Msk (0x2UL) /*!< IOM0 CQSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ -#define IOM0_CQSTAT_CQTIP_Pos (0UL) /*!< IOM0 CQSTAT: CQTIP (Bit 0) */ -#define IOM0_CQSTAT_CQTIP_Msk (0x1UL) /*!< IOM0 CQSTAT: CQTIP (Bitfield-Mask: 0x01) */ -/* ======================================================== CQFLAGS ======================================================== */ -#define IOM0_CQFLAGS_CQIRQMASK_Pos (16UL) /*!< IOM0 CQFLAGS: CQIRQMASK (Bit 16) */ -#define IOM0_CQFLAGS_CQIRQMASK_Msk (0xffff0000UL) /*!< IOM0 CQFLAGS: CQIRQMASK (Bitfield-Mask: 0xffff) */ -#define IOM0_CQFLAGS_CQFLAGS_Pos (0UL) /*!< IOM0 CQFLAGS: CQFLAGS (Bit 0) */ -#define IOM0_CQFLAGS_CQFLAGS_Msk (0xffffUL) /*!< IOM0 CQFLAGS: CQFLAGS (Bitfield-Mask: 0xffff) */ -/* ====================================================== CQSETCLEAR ======================================================= */ -#define IOM0_CQSETCLEAR_CQFCLR_Pos (16UL) /*!< IOM0 CQSETCLEAR: CQFCLR (Bit 16) */ -#define IOM0_CQSETCLEAR_CQFCLR_Msk (0xff0000UL) /*!< IOM0 CQSETCLEAR: CQFCLR (Bitfield-Mask: 0xff) */ -#define IOM0_CQSETCLEAR_CQFTGL_Pos (8UL) /*!< IOM0 CQSETCLEAR: CQFTGL (Bit 8) */ -#define IOM0_CQSETCLEAR_CQFTGL_Msk (0xff00UL) /*!< IOM0 CQSETCLEAR: CQFTGL (Bitfield-Mask: 0xff) */ -#define IOM0_CQSETCLEAR_CQFSET_Pos (0UL) /*!< IOM0 CQSETCLEAR: CQFSET (Bit 0) */ -#define IOM0_CQSETCLEAR_CQFSET_Msk (0xffUL) /*!< IOM0 CQSETCLEAR: CQFSET (Bitfield-Mask: 0xff) */ -/* ======================================================= CQPAUSEEN ======================================================= */ -#define IOM0_CQPAUSEEN_CQPEN_Pos (0UL) /*!< IOM0 CQPAUSEEN: CQPEN (Bit 0) */ -#define IOM0_CQPAUSEEN_CQPEN_Msk (0xffffUL) /*!< IOM0 CQPAUSEEN: CQPEN (Bitfield-Mask: 0xffff) */ -/* ======================================================= CQCURIDX ======================================================== */ -#define IOM0_CQCURIDX_CQCURIDX_Pos (0UL) /*!< IOM0 CQCURIDX: CQCURIDX (Bit 0) */ -#define IOM0_CQCURIDX_CQCURIDX_Msk (0xffUL) /*!< IOM0 CQCURIDX: CQCURIDX (Bitfield-Mask: 0xff) */ -/* ======================================================= CQENDIDX ======================================================== */ -#define IOM0_CQENDIDX_CQENDIDX_Pos (0UL) /*!< IOM0 CQENDIDX: CQENDIDX (Bit 0) */ -#define IOM0_CQENDIDX_CQENDIDX_Msk (0xffUL) /*!< IOM0 CQENDIDX: CQENDIDX (Bitfield-Mask: 0xff) */ -/* ======================================================== STATUS ========================================================= */ -#define IOM0_STATUS_IDLEST_Pos (2UL) /*!< IOM0 STATUS: IDLEST (Bit 2) */ -#define IOM0_STATUS_IDLEST_Msk (0x4UL) /*!< IOM0 STATUS: IDLEST (Bitfield-Mask: 0x01) */ -#define IOM0_STATUS_CMDACT_Pos (1UL) /*!< IOM0 STATUS: CMDACT (Bit 1) */ -#define IOM0_STATUS_CMDACT_Msk (0x2UL) /*!< IOM0 STATUS: CMDACT (Bitfield-Mask: 0x01) */ -#define IOM0_STATUS_ERR_Pos (0UL) /*!< IOM0 STATUS: ERR (Bit 0) */ -#define IOM0_STATUS_ERR_Msk (0x1UL) /*!< IOM0 STATUS: ERR (Bitfield-Mask: 0x01) */ -/* ======================================================== MSPICFG ======================================================== */ -#define IOM0_MSPICFG_MSPIRST_Pos (30UL) /*!< IOM0 MSPICFG: MSPIRST (Bit 30) */ -#define IOM0_MSPICFG_MSPIRST_Msk (0x40000000UL) /*!< IOM0 MSPICFG: MSPIRST (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_DOUTDLY_Pos (27UL) /*!< IOM0 MSPICFG: DOUTDLY (Bit 27) */ -#define IOM0_MSPICFG_DOUTDLY_Msk (0x38000000UL) /*!< IOM0 MSPICFG: DOUTDLY (Bitfield-Mask: 0x07) */ -#define IOM0_MSPICFG_DINDLY_Pos (24UL) /*!< IOM0 MSPICFG: DINDLY (Bit 24) */ -#define IOM0_MSPICFG_DINDLY_Msk (0x7000000UL) /*!< IOM0 MSPICFG: DINDLY (Bitfield-Mask: 0x07) */ -#define IOM0_MSPICFG_SPILSB_Pos (23UL) /*!< IOM0 MSPICFG: SPILSB (Bit 23) */ -#define IOM0_MSPICFG_SPILSB_Msk (0x800000UL) /*!< IOM0 MSPICFG: SPILSB (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_RDFCPOL_Pos (22UL) /*!< IOM0 MSPICFG: RDFCPOL (Bit 22) */ -#define IOM0_MSPICFG_RDFCPOL_Msk (0x400000UL) /*!< IOM0 MSPICFG: RDFCPOL (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_WTFCPOL_Pos (21UL) /*!< IOM0 MSPICFG: WTFCPOL (Bit 21) */ -#define IOM0_MSPICFG_WTFCPOL_Msk (0x200000UL) /*!< IOM0 MSPICFG: WTFCPOL (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_WTFCIRQ_Pos (20UL) /*!< IOM0 MSPICFG: WTFCIRQ (Bit 20) */ -#define IOM0_MSPICFG_WTFCIRQ_Msk (0x100000UL) /*!< IOM0 MSPICFG: WTFCIRQ (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_MOSIINV_Pos (18UL) /*!< IOM0 MSPICFG: MOSIINV (Bit 18) */ -#define IOM0_MSPICFG_MOSIINV_Msk (0x40000UL) /*!< IOM0 MSPICFG: MOSIINV (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_RDFC_Pos (17UL) /*!< IOM0 MSPICFG: RDFC (Bit 17) */ -#define IOM0_MSPICFG_RDFC_Msk (0x20000UL) /*!< IOM0 MSPICFG: RDFC (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_WTFC_Pos (16UL) /*!< IOM0 MSPICFG: WTFC (Bit 16) */ -#define IOM0_MSPICFG_WTFC_Msk (0x10000UL) /*!< IOM0 MSPICFG: WTFC (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_FULLDUP_Pos (2UL) /*!< IOM0 MSPICFG: FULLDUP (Bit 2) */ -#define IOM0_MSPICFG_FULLDUP_Msk (0x4UL) /*!< IOM0 MSPICFG: FULLDUP (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_SPHA_Pos (1UL) /*!< IOM0 MSPICFG: SPHA (Bit 1) */ -#define IOM0_MSPICFG_SPHA_Msk (0x2UL) /*!< IOM0 MSPICFG: SPHA (Bitfield-Mask: 0x01) */ -#define IOM0_MSPICFG_SPOL_Pos (0UL) /*!< IOM0 MSPICFG: SPOL (Bit 0) */ -#define IOM0_MSPICFG_SPOL_Msk (0x1UL) /*!< IOM0 MSPICFG: SPOL (Bitfield-Mask: 0x01) */ -/* ======================================================== MI2CCFG ======================================================== */ -#define IOM0_MI2CCFG_STRDIS_Pos (24UL) /*!< IOM0 MI2CCFG: STRDIS (Bit 24) */ -#define IOM0_MI2CCFG_STRDIS_Msk (0x1000000UL) /*!< IOM0 MI2CCFG: STRDIS (Bitfield-Mask: 0x01) */ -#define IOM0_MI2CCFG_SMPCNT_Pos (16UL) /*!< IOM0 MI2CCFG: SMPCNT (Bit 16) */ -#define IOM0_MI2CCFG_SMPCNT_Msk (0xff0000UL) /*!< IOM0 MI2CCFG: SMPCNT (Bitfield-Mask: 0xff) */ -#define IOM0_MI2CCFG_SDAENDLY_Pos (12UL) /*!< IOM0 MI2CCFG: SDAENDLY (Bit 12) */ -#define IOM0_MI2CCFG_SDAENDLY_Msk (0xf000UL) /*!< IOM0 MI2CCFG: SDAENDLY (Bitfield-Mask: 0x0f) */ -#define IOM0_MI2CCFG_SCLENDLY_Pos (8UL) /*!< IOM0 MI2CCFG: SCLENDLY (Bit 8) */ -#define IOM0_MI2CCFG_SCLENDLY_Msk (0xf00UL) /*!< IOM0 MI2CCFG: SCLENDLY (Bitfield-Mask: 0x0f) */ -#define IOM0_MI2CCFG_MI2CRST_Pos (6UL) /*!< IOM0 MI2CCFG: MI2CRST (Bit 6) */ -#define IOM0_MI2CCFG_MI2CRST_Msk (0x40UL) /*!< IOM0 MI2CCFG: MI2CRST (Bitfield-Mask: 0x01) */ -#define IOM0_MI2CCFG_SDADLY_Pos (4UL) /*!< IOM0 MI2CCFG: SDADLY (Bit 4) */ -#define IOM0_MI2CCFG_SDADLY_Msk (0x30UL) /*!< IOM0 MI2CCFG: SDADLY (Bitfield-Mask: 0x03) */ -#define IOM0_MI2CCFG_ARBEN_Pos (2UL) /*!< IOM0 MI2CCFG: ARBEN (Bit 2) */ -#define IOM0_MI2CCFG_ARBEN_Msk (0x4UL) /*!< IOM0 MI2CCFG: ARBEN (Bitfield-Mask: 0x01) */ -#define IOM0_MI2CCFG_I2CLSB_Pos (1UL) /*!< IOM0 MI2CCFG: I2CLSB (Bit 1) */ -#define IOM0_MI2CCFG_I2CLSB_Msk (0x2UL) /*!< IOM0 MI2CCFG: I2CLSB (Bitfield-Mask: 0x01) */ -#define IOM0_MI2CCFG_ADDRSZ_Pos (0UL) /*!< IOM0 MI2CCFG: ADDRSZ (Bit 0) */ -#define IOM0_MI2CCFG_ADDRSZ_Msk (0x1UL) /*!< IOM0 MI2CCFG: ADDRSZ (Bitfield-Mask: 0x01) */ -/* ======================================================== DEVCFG ========================================================= */ -#define IOM0_DEVCFG_DEVADDR_Pos (0UL) /*!< IOM0 DEVCFG: DEVADDR (Bit 0) */ -#define IOM0_DEVCFG_DEVADDR_Msk (0x3ffUL) /*!< IOM0 DEVCFG: DEVADDR (Bitfield-Mask: 0x3ff) */ -/* ======================================================== IOMDBG ========================================================= */ -#define IOM0_IOMDBG_DBGDATA_Pos (3UL) /*!< IOM0 IOMDBG: DBGDATA (Bit 3) */ -#define IOM0_IOMDBG_DBGDATA_Msk (0xfffffff8UL) /*!< IOM0 IOMDBG: DBGDATA (Bitfield-Mask: 0x1fffffff) */ -#define IOM0_IOMDBG_APBCLKON_Pos (2UL) /*!< IOM0 IOMDBG: APBCLKON (Bit 2) */ -#define IOM0_IOMDBG_APBCLKON_Msk (0x4UL) /*!< IOM0 IOMDBG: APBCLKON (Bitfield-Mask: 0x01) */ -#define IOM0_IOMDBG_IOCLKON_Pos (1UL) /*!< IOM0 IOMDBG: IOCLKON (Bit 1) */ -#define IOM0_IOMDBG_IOCLKON_Msk (0x2UL) /*!< IOM0 IOMDBG: IOCLKON (Bitfield-Mask: 0x01) */ -#define IOM0_IOMDBG_DBGEN_Pos (0UL) /*!< IOM0 IOMDBG: DBGEN (Bit 0) */ -#define IOM0_IOMDBG_DBGEN_Msk (0x1UL) /*!< IOM0 IOMDBG: DBGEN (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ IOSLAVE ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== FIFOPTR ======================================================== */ -#define IOSLAVE_FIFOPTR_FIFOSIZ_Pos (8UL) /*!< IOSLAVE FIFOPTR: FIFOSIZ (Bit 8) */ -#define IOSLAVE_FIFOPTR_FIFOSIZ_Msk (0xff00UL) /*!< IOSLAVE FIFOPTR: FIFOSIZ (Bitfield-Mask: 0xff) */ -#define IOSLAVE_FIFOPTR_FIFOPTR_Pos (0UL) /*!< IOSLAVE FIFOPTR: FIFOPTR (Bit 0) */ -#define IOSLAVE_FIFOPTR_FIFOPTR_Msk (0xffUL) /*!< IOSLAVE FIFOPTR: FIFOPTR (Bitfield-Mask: 0xff) */ -/* ======================================================== FIFOCFG ======================================================== */ -#define IOSLAVE_FIFOCFG_ROBASE_Pos (24UL) /*!< IOSLAVE FIFOCFG: ROBASE (Bit 24) */ -#define IOSLAVE_FIFOCFG_ROBASE_Msk (0x3f000000UL) /*!< IOSLAVE FIFOCFG: ROBASE (Bitfield-Mask: 0x3f) */ -#define IOSLAVE_FIFOCFG_FIFOMAX_Pos (8UL) /*!< IOSLAVE FIFOCFG: FIFOMAX (Bit 8) */ -#define IOSLAVE_FIFOCFG_FIFOMAX_Msk (0x3f00UL) /*!< IOSLAVE FIFOCFG: FIFOMAX (Bitfield-Mask: 0x3f) */ -#define IOSLAVE_FIFOCFG_FIFOBASE_Pos (0UL) /*!< IOSLAVE FIFOCFG: FIFOBASE (Bit 0) */ -#define IOSLAVE_FIFOCFG_FIFOBASE_Msk (0x1fUL) /*!< IOSLAVE FIFOCFG: FIFOBASE (Bitfield-Mask: 0x1f) */ -/* ======================================================== FIFOTHR ======================================================== */ -#define IOSLAVE_FIFOTHR_FIFOTHR_Pos (0UL) /*!< IOSLAVE FIFOTHR: FIFOTHR (Bit 0) */ -#define IOSLAVE_FIFOTHR_FIFOTHR_Msk (0xffUL) /*!< IOSLAVE FIFOTHR: FIFOTHR (Bitfield-Mask: 0xff) */ -/* ========================================================= FUPD ========================================================== */ -#define IOSLAVE_FUPD_IOREAD_Pos (1UL) /*!< IOSLAVE FUPD: IOREAD (Bit 1) */ -#define IOSLAVE_FUPD_IOREAD_Msk (0x2UL) /*!< IOSLAVE FUPD: IOREAD (Bitfield-Mask: 0x01) */ -#define IOSLAVE_FUPD_FIFOUPD_Pos (0UL) /*!< IOSLAVE FUPD: FIFOUPD (Bit 0) */ -#define IOSLAVE_FUPD_FIFOUPD_Msk (0x1UL) /*!< IOSLAVE FUPD: FIFOUPD (Bitfield-Mask: 0x01) */ -/* ======================================================== FIFOCTR ======================================================== */ -#define IOSLAVE_FIFOCTR_FIFOCTR_Pos (0UL) /*!< IOSLAVE FIFOCTR: FIFOCTR (Bit 0) */ -#define IOSLAVE_FIFOCTR_FIFOCTR_Msk (0x3ffUL) /*!< IOSLAVE FIFOCTR: FIFOCTR (Bitfield-Mask: 0x3ff) */ -/* ======================================================== FIFOINC ======================================================== */ -#define IOSLAVE_FIFOINC_FIFOINC_Pos (0UL) /*!< IOSLAVE FIFOINC: FIFOINC (Bit 0) */ -#define IOSLAVE_FIFOINC_FIFOINC_Msk (0x3ffUL) /*!< IOSLAVE FIFOINC: FIFOINC (Bitfield-Mask: 0x3ff) */ -/* ========================================================== CFG ========================================================== */ -#define IOSLAVE_CFG_IFCEN_Pos (31UL) /*!< IOSLAVE CFG: IFCEN (Bit 31) */ -#define IOSLAVE_CFG_IFCEN_Msk (0x80000000UL) /*!< IOSLAVE CFG: IFCEN (Bitfield-Mask: 0x01) */ -#define IOSLAVE_CFG_I2CADDR_Pos (8UL) /*!< IOSLAVE CFG: I2CADDR (Bit 8) */ -#define IOSLAVE_CFG_I2CADDR_Msk (0xfff00UL) /*!< IOSLAVE CFG: I2CADDR (Bitfield-Mask: 0xfff) */ -#define IOSLAVE_CFG_STARTRD_Pos (4UL) /*!< IOSLAVE CFG: STARTRD (Bit 4) */ -#define IOSLAVE_CFG_STARTRD_Msk (0x10UL) /*!< IOSLAVE CFG: STARTRD (Bitfield-Mask: 0x01) */ -#define IOSLAVE_CFG_LSB_Pos (2UL) /*!< IOSLAVE CFG: LSB (Bit 2) */ -#define IOSLAVE_CFG_LSB_Msk (0x4UL) /*!< IOSLAVE CFG: LSB (Bitfield-Mask: 0x01) */ -#define IOSLAVE_CFG_SPOL_Pos (1UL) /*!< IOSLAVE CFG: SPOL (Bit 1) */ -#define IOSLAVE_CFG_SPOL_Msk (0x2UL) /*!< IOSLAVE CFG: SPOL (Bitfield-Mask: 0x01) */ -#define IOSLAVE_CFG_IFCSEL_Pos (0UL) /*!< IOSLAVE CFG: IFCSEL (Bit 0) */ -#define IOSLAVE_CFG_IFCSEL_Msk (0x1UL) /*!< IOSLAVE CFG: IFCSEL (Bitfield-Mask: 0x01) */ -/* ========================================================= PRENC ========================================================= */ -#define IOSLAVE_PRENC_PRENC_Pos (0UL) /*!< IOSLAVE PRENC: PRENC (Bit 0) */ -#define IOSLAVE_PRENC_PRENC_Msk (0x1fUL) /*!< IOSLAVE PRENC: PRENC (Bitfield-Mask: 0x1f) */ -/* ======================================================= IOINTCTL ======================================================== */ -#define IOSLAVE_IOINTCTL_IOINTSET_Pos (24UL) /*!< IOSLAVE IOINTCTL: IOINTSET (Bit 24) */ -#define IOSLAVE_IOINTCTL_IOINTSET_Msk (0xff000000UL) /*!< IOSLAVE IOINTCTL: IOINTSET (Bitfield-Mask: 0xff) */ -#define IOSLAVE_IOINTCTL_IOINTCLR_Pos (16UL) /*!< IOSLAVE IOINTCTL: IOINTCLR (Bit 16) */ -#define IOSLAVE_IOINTCTL_IOINTCLR_Msk (0x10000UL) /*!< IOSLAVE IOINTCTL: IOINTCLR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_IOINTCTL_IOINT_Pos (8UL) /*!< IOSLAVE IOINTCTL: IOINT (Bit 8) */ -#define IOSLAVE_IOINTCTL_IOINT_Msk (0xff00UL) /*!< IOSLAVE IOINTCTL: IOINT (Bitfield-Mask: 0xff) */ -#define IOSLAVE_IOINTCTL_IOINTEN_Pos (0UL) /*!< IOSLAVE IOINTCTL: IOINTEN (Bit 0) */ -#define IOSLAVE_IOINTCTL_IOINTEN_Msk (0xffUL) /*!< IOSLAVE IOINTCTL: IOINTEN (Bitfield-Mask: 0xff) */ -/* ======================================================== GENADD ========================================================= */ -#define IOSLAVE_GENADD_GADATA_Pos (0UL) /*!< IOSLAVE GENADD: GADATA (Bit 0) */ -#define IOSLAVE_GENADD_GADATA_Msk (0xffUL) /*!< IOSLAVE GENADD: GADATA (Bitfield-Mask: 0xff) */ -/* ========================================================= INTEN ========================================================= */ -#define IOSLAVE_INTEN_XCMPWR_Pos (9UL) /*!< IOSLAVE INTEN: XCMPWR (Bit 9) */ -#define IOSLAVE_INTEN_XCMPWR_Msk (0x200UL) /*!< IOSLAVE INTEN: XCMPWR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTEN_XCMPWF_Pos (8UL) /*!< IOSLAVE INTEN: XCMPWF (Bit 8) */ -#define IOSLAVE_INTEN_XCMPWF_Msk (0x100UL) /*!< IOSLAVE INTEN: XCMPWF (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTEN_XCMPRR_Pos (7UL) /*!< IOSLAVE INTEN: XCMPRR (Bit 7) */ -#define IOSLAVE_INTEN_XCMPRR_Msk (0x80UL) /*!< IOSLAVE INTEN: XCMPRR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTEN_XCMPRF_Pos (6UL) /*!< IOSLAVE INTEN: XCMPRF (Bit 6) */ -#define IOSLAVE_INTEN_XCMPRF_Msk (0x40UL) /*!< IOSLAVE INTEN: XCMPRF (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTEN_IOINTW_Pos (5UL) /*!< IOSLAVE INTEN: IOINTW (Bit 5) */ -#define IOSLAVE_INTEN_IOINTW_Msk (0x20UL) /*!< IOSLAVE INTEN: IOINTW (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTEN_GENAD_Pos (4UL) /*!< IOSLAVE INTEN: GENAD (Bit 4) */ -#define IOSLAVE_INTEN_GENAD_Msk (0x10UL) /*!< IOSLAVE INTEN: GENAD (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTEN_FRDERR_Pos (3UL) /*!< IOSLAVE INTEN: FRDERR (Bit 3) */ -#define IOSLAVE_INTEN_FRDERR_Msk (0x8UL) /*!< IOSLAVE INTEN: FRDERR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTEN_FUNDFL_Pos (2UL) /*!< IOSLAVE INTEN: FUNDFL (Bit 2) */ -#define IOSLAVE_INTEN_FUNDFL_Msk (0x4UL) /*!< IOSLAVE INTEN: FUNDFL (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTEN_FOVFL_Pos (1UL) /*!< IOSLAVE INTEN: FOVFL (Bit 1) */ -#define IOSLAVE_INTEN_FOVFL_Msk (0x2UL) /*!< IOSLAVE INTEN: FOVFL (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTEN_FSIZE_Pos (0UL) /*!< IOSLAVE INTEN: FSIZE (Bit 0) */ -#define IOSLAVE_INTEN_FSIZE_Msk (0x1UL) /*!< IOSLAVE INTEN: FSIZE (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define IOSLAVE_INTSTAT_XCMPWR_Pos (9UL) /*!< IOSLAVE INTSTAT: XCMPWR (Bit 9) */ -#define IOSLAVE_INTSTAT_XCMPWR_Msk (0x200UL) /*!< IOSLAVE INTSTAT: XCMPWR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSTAT_XCMPWF_Pos (8UL) /*!< IOSLAVE INTSTAT: XCMPWF (Bit 8) */ -#define IOSLAVE_INTSTAT_XCMPWF_Msk (0x100UL) /*!< IOSLAVE INTSTAT: XCMPWF (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSTAT_XCMPRR_Pos (7UL) /*!< IOSLAVE INTSTAT: XCMPRR (Bit 7) */ -#define IOSLAVE_INTSTAT_XCMPRR_Msk (0x80UL) /*!< IOSLAVE INTSTAT: XCMPRR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSTAT_XCMPRF_Pos (6UL) /*!< IOSLAVE INTSTAT: XCMPRF (Bit 6) */ -#define IOSLAVE_INTSTAT_XCMPRF_Msk (0x40UL) /*!< IOSLAVE INTSTAT: XCMPRF (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSTAT_IOINTW_Pos (5UL) /*!< IOSLAVE INTSTAT: IOINTW (Bit 5) */ -#define IOSLAVE_INTSTAT_IOINTW_Msk (0x20UL) /*!< IOSLAVE INTSTAT: IOINTW (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSTAT_GENAD_Pos (4UL) /*!< IOSLAVE INTSTAT: GENAD (Bit 4) */ -#define IOSLAVE_INTSTAT_GENAD_Msk (0x10UL) /*!< IOSLAVE INTSTAT: GENAD (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSTAT_FRDERR_Pos (3UL) /*!< IOSLAVE INTSTAT: FRDERR (Bit 3) */ -#define IOSLAVE_INTSTAT_FRDERR_Msk (0x8UL) /*!< IOSLAVE INTSTAT: FRDERR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSTAT_FUNDFL_Pos (2UL) /*!< IOSLAVE INTSTAT: FUNDFL (Bit 2) */ -#define IOSLAVE_INTSTAT_FUNDFL_Msk (0x4UL) /*!< IOSLAVE INTSTAT: FUNDFL (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSTAT_FOVFL_Pos (1UL) /*!< IOSLAVE INTSTAT: FOVFL (Bit 1) */ -#define IOSLAVE_INTSTAT_FOVFL_Msk (0x2UL) /*!< IOSLAVE INTSTAT: FOVFL (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSTAT_FSIZE_Pos (0UL) /*!< IOSLAVE INTSTAT: FSIZE (Bit 0) */ -#define IOSLAVE_INTSTAT_FSIZE_Msk (0x1UL) /*!< IOSLAVE INTSTAT: FSIZE (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define IOSLAVE_INTCLR_XCMPWR_Pos (9UL) /*!< IOSLAVE INTCLR: XCMPWR (Bit 9) */ -#define IOSLAVE_INTCLR_XCMPWR_Msk (0x200UL) /*!< IOSLAVE INTCLR: XCMPWR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTCLR_XCMPWF_Pos (8UL) /*!< IOSLAVE INTCLR: XCMPWF (Bit 8) */ -#define IOSLAVE_INTCLR_XCMPWF_Msk (0x100UL) /*!< IOSLAVE INTCLR: XCMPWF (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTCLR_XCMPRR_Pos (7UL) /*!< IOSLAVE INTCLR: XCMPRR (Bit 7) */ -#define IOSLAVE_INTCLR_XCMPRR_Msk (0x80UL) /*!< IOSLAVE INTCLR: XCMPRR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTCLR_XCMPRF_Pos (6UL) /*!< IOSLAVE INTCLR: XCMPRF (Bit 6) */ -#define IOSLAVE_INTCLR_XCMPRF_Msk (0x40UL) /*!< IOSLAVE INTCLR: XCMPRF (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTCLR_IOINTW_Pos (5UL) /*!< IOSLAVE INTCLR: IOINTW (Bit 5) */ -#define IOSLAVE_INTCLR_IOINTW_Msk (0x20UL) /*!< IOSLAVE INTCLR: IOINTW (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTCLR_GENAD_Pos (4UL) /*!< IOSLAVE INTCLR: GENAD (Bit 4) */ -#define IOSLAVE_INTCLR_GENAD_Msk (0x10UL) /*!< IOSLAVE INTCLR: GENAD (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTCLR_FRDERR_Pos (3UL) /*!< IOSLAVE INTCLR: FRDERR (Bit 3) */ -#define IOSLAVE_INTCLR_FRDERR_Msk (0x8UL) /*!< IOSLAVE INTCLR: FRDERR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTCLR_FUNDFL_Pos (2UL) /*!< IOSLAVE INTCLR: FUNDFL (Bit 2) */ -#define IOSLAVE_INTCLR_FUNDFL_Msk (0x4UL) /*!< IOSLAVE INTCLR: FUNDFL (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTCLR_FOVFL_Pos (1UL) /*!< IOSLAVE INTCLR: FOVFL (Bit 1) */ -#define IOSLAVE_INTCLR_FOVFL_Msk (0x2UL) /*!< IOSLAVE INTCLR: FOVFL (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTCLR_FSIZE_Pos (0UL) /*!< IOSLAVE INTCLR: FSIZE (Bit 0) */ -#define IOSLAVE_INTCLR_FSIZE_Msk (0x1UL) /*!< IOSLAVE INTCLR: FSIZE (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define IOSLAVE_INTSET_XCMPWR_Pos (9UL) /*!< IOSLAVE INTSET: XCMPWR (Bit 9) */ -#define IOSLAVE_INTSET_XCMPWR_Msk (0x200UL) /*!< IOSLAVE INTSET: XCMPWR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSET_XCMPWF_Pos (8UL) /*!< IOSLAVE INTSET: XCMPWF (Bit 8) */ -#define IOSLAVE_INTSET_XCMPWF_Msk (0x100UL) /*!< IOSLAVE INTSET: XCMPWF (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSET_XCMPRR_Pos (7UL) /*!< IOSLAVE INTSET: XCMPRR (Bit 7) */ -#define IOSLAVE_INTSET_XCMPRR_Msk (0x80UL) /*!< IOSLAVE INTSET: XCMPRR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSET_XCMPRF_Pos (6UL) /*!< IOSLAVE INTSET: XCMPRF (Bit 6) */ -#define IOSLAVE_INTSET_XCMPRF_Msk (0x40UL) /*!< IOSLAVE INTSET: XCMPRF (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSET_IOINTW_Pos (5UL) /*!< IOSLAVE INTSET: IOINTW (Bit 5) */ -#define IOSLAVE_INTSET_IOINTW_Msk (0x20UL) /*!< IOSLAVE INTSET: IOINTW (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSET_GENAD_Pos (4UL) /*!< IOSLAVE INTSET: GENAD (Bit 4) */ -#define IOSLAVE_INTSET_GENAD_Msk (0x10UL) /*!< IOSLAVE INTSET: GENAD (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSET_FRDERR_Pos (3UL) /*!< IOSLAVE INTSET: FRDERR (Bit 3) */ -#define IOSLAVE_INTSET_FRDERR_Msk (0x8UL) /*!< IOSLAVE INTSET: FRDERR (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSET_FUNDFL_Pos (2UL) /*!< IOSLAVE INTSET: FUNDFL (Bit 2) */ -#define IOSLAVE_INTSET_FUNDFL_Msk (0x4UL) /*!< IOSLAVE INTSET: FUNDFL (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSET_FOVFL_Pos (1UL) /*!< IOSLAVE INTSET: FOVFL (Bit 1) */ -#define IOSLAVE_INTSET_FOVFL_Msk (0x2UL) /*!< IOSLAVE INTSET: FOVFL (Bitfield-Mask: 0x01) */ -#define IOSLAVE_INTSET_FSIZE_Pos (0UL) /*!< IOSLAVE INTSET: FSIZE (Bit 0) */ -#define IOSLAVE_INTSET_FSIZE_Msk (0x1UL) /*!< IOSLAVE INTSET: FSIZE (Bitfield-Mask: 0x01) */ -/* ====================================================== REGACCINTEN ====================================================== */ -#define IOSLAVE_REGACCINTEN_REGACC_Pos (0UL) /*!< IOSLAVE REGACCINTEN: REGACC (Bit 0) */ -#define IOSLAVE_REGACCINTEN_REGACC_Msk (0xffffffffUL) /*!< IOSLAVE REGACCINTEN: REGACC (Bitfield-Mask: 0xffffffff) */ -/* ===================================================== REGACCINTSTAT ===================================================== */ -#define IOSLAVE_REGACCINTSTAT_REGACC_Pos (0UL) /*!< IOSLAVE REGACCINTSTAT: REGACC (Bit 0) */ -#define IOSLAVE_REGACCINTSTAT_REGACC_Msk (0xffffffffUL) /*!< IOSLAVE REGACCINTSTAT: REGACC (Bitfield-Mask: 0xffffffff) */ -/* ===================================================== REGACCINTCLR ====================================================== */ -#define IOSLAVE_REGACCINTCLR_REGACC_Pos (0UL) /*!< IOSLAVE REGACCINTCLR: REGACC (Bit 0) */ -#define IOSLAVE_REGACCINTCLR_REGACC_Msk (0xffffffffUL) /*!< IOSLAVE REGACCINTCLR: REGACC (Bitfield-Mask: 0xffffffff) */ -/* ===================================================== REGACCINTSET ====================================================== */ -#define IOSLAVE_REGACCINTSET_REGACC_Pos (0UL) /*!< IOSLAVE REGACCINTSET: REGACC (Bit 0) */ -#define IOSLAVE_REGACCINTSET_REGACC_Msk (0xffffffffUL) /*!< IOSLAVE REGACCINTSET: REGACC (Bitfield-Mask: 0xffffffff) */ - - -/* =========================================================================================================================== */ -/* ================ MCUCTRL ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== CHIPPN ========================================================= */ -#define MCUCTRL_CHIPPN_PARTNUM_Pos (0UL) /*!< MCUCTRL CHIPPN: PARTNUM (Bit 0) */ -#define MCUCTRL_CHIPPN_PARTNUM_Msk (0xffffffffUL) /*!< MCUCTRL CHIPPN: PARTNUM (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== CHIPID0 ======================================================== */ -#define MCUCTRL_CHIPID0_CHIPID0_Pos (0UL) /*!< MCUCTRL CHIPID0: CHIPID0 (Bit 0) */ -#define MCUCTRL_CHIPID0_CHIPID0_Msk (0xffffffffUL) /*!< MCUCTRL CHIPID0: CHIPID0 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== CHIPID1 ======================================================== */ -#define MCUCTRL_CHIPID1_CHIPID1_Pos (0UL) /*!< MCUCTRL CHIPID1: CHIPID1 (Bit 0) */ -#define MCUCTRL_CHIPID1_CHIPID1_Msk (0xffffffffUL) /*!< MCUCTRL CHIPID1: CHIPID1 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== CHIPREV ======================================================== */ -#define MCUCTRL_CHIPREV_SIPART_Pos (8UL) /*!< MCUCTRL CHIPREV: SIPART (Bit 8) */ -#define MCUCTRL_CHIPREV_SIPART_Msk (0xfff00UL) /*!< MCUCTRL CHIPREV: SIPART (Bitfield-Mask: 0xfff) */ -#define MCUCTRL_CHIPREV_REVMAJ_Pos (4UL) /*!< MCUCTRL CHIPREV: REVMAJ (Bit 4) */ -#define MCUCTRL_CHIPREV_REVMAJ_Msk (0xf0UL) /*!< MCUCTRL CHIPREV: REVMAJ (Bitfield-Mask: 0x0f) */ -#define MCUCTRL_CHIPREV_REVMIN_Pos (0UL) /*!< MCUCTRL CHIPREV: REVMIN (Bit 0) */ -#define MCUCTRL_CHIPREV_REVMIN_Msk (0xfUL) /*!< MCUCTRL CHIPREV: REVMIN (Bitfield-Mask: 0x0f) */ -/* ======================================================= VENDORID ======================================================== */ -#define MCUCTRL_VENDORID_VENDORID_Pos (0UL) /*!< MCUCTRL VENDORID: VENDORID (Bit 0) */ -#define MCUCTRL_VENDORID_VENDORID_Msk (0xffffffffUL) /*!< MCUCTRL VENDORID: VENDORID (Bitfield-Mask: 0xffffffff) */ -/* ========================================================== SKU ========================================================== */ -#define MCUCTRL_SKU_SECBOOT_Pos (2UL) /*!< MCUCTRL SKU: SECBOOT (Bit 2) */ -#define MCUCTRL_SKU_SECBOOT_Msk (0x4UL) /*!< MCUCTRL SKU: SECBOOT (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SKU_ALLOWBLE_Pos (1UL) /*!< MCUCTRL SKU: ALLOWBLE (Bit 1) */ -#define MCUCTRL_SKU_ALLOWBLE_Msk (0x2UL) /*!< MCUCTRL SKU: ALLOWBLE (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SKU_ALLOWBURST_Pos (0UL) /*!< MCUCTRL SKU: ALLOWBURST (Bit 0) */ -#define MCUCTRL_SKU_ALLOWBURST_Msk (0x1UL) /*!< MCUCTRL SKU: ALLOWBURST (Bitfield-Mask: 0x01) */ -/* ===================================================== FEATUREENABLE ===================================================== */ -#define MCUCTRL_FEATUREENABLE_BURSTAVAIL_Pos (6UL) /*!< MCUCTRL FEATUREENABLE: BURSTAVAIL (Bit 6) */ -#define MCUCTRL_FEATUREENABLE_BURSTAVAIL_Msk (0x40UL) /*!< MCUCTRL FEATUREENABLE: BURSTAVAIL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_FEATUREENABLE_BURSTACK_Pos (5UL) /*!< MCUCTRL FEATUREENABLE: BURSTACK (Bit 5) */ -#define MCUCTRL_FEATUREENABLE_BURSTACK_Msk (0x20UL) /*!< MCUCTRL FEATUREENABLE: BURSTACK (Bitfield-Mask: 0x01) */ -#define MCUCTRL_FEATUREENABLE_BURSTREQ_Pos (4UL) /*!< MCUCTRL FEATUREENABLE: BURSTREQ (Bit 4) */ -#define MCUCTRL_FEATUREENABLE_BURSTREQ_Msk (0x10UL) /*!< MCUCTRL FEATUREENABLE: BURSTREQ (Bitfield-Mask: 0x01) */ -#define MCUCTRL_FEATUREENABLE_BLEAVAIL_Pos (2UL) /*!< MCUCTRL FEATUREENABLE: BLEAVAIL (Bit 2) */ -#define MCUCTRL_FEATUREENABLE_BLEAVAIL_Msk (0x4UL) /*!< MCUCTRL FEATUREENABLE: BLEAVAIL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_FEATUREENABLE_BLEACK_Pos (1UL) /*!< MCUCTRL FEATUREENABLE: BLEACK (Bit 1) */ -#define MCUCTRL_FEATUREENABLE_BLEACK_Msk (0x2UL) /*!< MCUCTRL FEATUREENABLE: BLEACK (Bitfield-Mask: 0x01) */ -#define MCUCTRL_FEATUREENABLE_BLEREQ_Pos (0UL) /*!< MCUCTRL FEATUREENABLE: BLEREQ (Bit 0) */ -#define MCUCTRL_FEATUREENABLE_BLEREQ_Msk (0x1UL) /*!< MCUCTRL FEATUREENABLE: BLEREQ (Bitfield-Mask: 0x01) */ -/* ======================================================= DEBUGGER ======================================================== */ -#define MCUCTRL_DEBUGGER_LOCKOUT_Pos (0UL) /*!< MCUCTRL DEBUGGER: LOCKOUT (Bit 0) */ -#define MCUCTRL_DEBUGGER_LOCKOUT_Msk (0x1UL) /*!< MCUCTRL DEBUGGER: LOCKOUT (Bitfield-Mask: 0x01) */ -/* ======================================================== BODCTRL ======================================================== */ -#define MCUCTRL_BODCTRL_BODHVREFSEL_Pos (5UL) /*!< MCUCTRL BODCTRL: BODHVREFSEL (Bit 5) */ -#define MCUCTRL_BODCTRL_BODHVREFSEL_Msk (0x20UL) /*!< MCUCTRL BODCTRL: BODHVREFSEL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_BODCTRL_BODLVREFSEL_Pos (4UL) /*!< MCUCTRL BODCTRL: BODLVREFSEL (Bit 4) */ -#define MCUCTRL_BODCTRL_BODLVREFSEL_Msk (0x10UL) /*!< MCUCTRL BODCTRL: BODLVREFSEL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_BODCTRL_BODFPWD_Pos (3UL) /*!< MCUCTRL BODCTRL: BODFPWD (Bit 3) */ -#define MCUCTRL_BODCTRL_BODFPWD_Msk (0x8UL) /*!< MCUCTRL BODCTRL: BODFPWD (Bitfield-Mask: 0x01) */ -#define MCUCTRL_BODCTRL_BODCPWD_Pos (2UL) /*!< MCUCTRL BODCTRL: BODCPWD (Bit 2) */ -#define MCUCTRL_BODCTRL_BODCPWD_Msk (0x4UL) /*!< MCUCTRL BODCTRL: BODCPWD (Bitfield-Mask: 0x01) */ -#define MCUCTRL_BODCTRL_BODHPWD_Pos (1UL) /*!< MCUCTRL BODCTRL: BODHPWD (Bit 1) */ -#define MCUCTRL_BODCTRL_BODHPWD_Msk (0x2UL) /*!< MCUCTRL BODCTRL: BODHPWD (Bitfield-Mask: 0x01) */ -#define MCUCTRL_BODCTRL_BODLPWD_Pos (0UL) /*!< MCUCTRL BODCTRL: BODLPWD (Bit 0) */ -#define MCUCTRL_BODCTRL_BODLPWD_Msk (0x1UL) /*!< MCUCTRL BODCTRL: BODLPWD (Bitfield-Mask: 0x01) */ -/* ======================================================= ADCPWRDLY ======================================================= */ -#define MCUCTRL_ADCPWRDLY_ADCPWR1_Pos (8UL) /*!< MCUCTRL ADCPWRDLY: ADCPWR1 (Bit 8) */ -#define MCUCTRL_ADCPWRDLY_ADCPWR1_Msk (0xff00UL) /*!< MCUCTRL ADCPWRDLY: ADCPWR1 (Bitfield-Mask: 0xff) */ -#define MCUCTRL_ADCPWRDLY_ADCPWR0_Pos (0UL) /*!< MCUCTRL ADCPWRDLY: ADCPWR0 (Bit 0) */ -#define MCUCTRL_ADCPWRDLY_ADCPWR0_Msk (0xffUL) /*!< MCUCTRL ADCPWRDLY: ADCPWR0 (Bitfield-Mask: 0xff) */ -/* ======================================================== ADCCAL ========================================================= */ -#define MCUCTRL_ADCCAL_ADCCALIBRATED_Pos (1UL) /*!< MCUCTRL ADCCAL: ADCCALIBRATED (Bit 1) */ -#define MCUCTRL_ADCCAL_ADCCALIBRATED_Msk (0x2UL) /*!< MCUCTRL ADCCAL: ADCCALIBRATED (Bitfield-Mask: 0x01) */ -#define MCUCTRL_ADCCAL_CALONPWRUP_Pos (0UL) /*!< MCUCTRL ADCCAL: CALONPWRUP (Bit 0) */ -#define MCUCTRL_ADCCAL_CALONPWRUP_Msk (0x1UL) /*!< MCUCTRL ADCCAL: CALONPWRUP (Bitfield-Mask: 0x01) */ -/* ====================================================== ADCBATTLOAD ====================================================== */ -#define MCUCTRL_ADCBATTLOAD_BATTLOAD_Pos (0UL) /*!< MCUCTRL ADCBATTLOAD: BATTLOAD (Bit 0) */ -#define MCUCTRL_ADCBATTLOAD_BATTLOAD_Msk (0x1UL) /*!< MCUCTRL ADCBATTLOAD: BATTLOAD (Bitfield-Mask: 0x01) */ -/* ======================================================== ADCTRIM ======================================================== */ -#define MCUCTRL_ADCTRIM_ADCRFBUFIBTRIM_Pos (11UL) /*!< MCUCTRL ADCTRIM: ADCRFBUFIBTRIM (Bit 11) */ -#define MCUCTRL_ADCTRIM_ADCRFBUFIBTRIM_Msk (0x1800UL) /*!< MCUCTRL ADCTRIM: ADCRFBUFIBTRIM (Bitfield-Mask: 0x03) */ -#define MCUCTRL_ADCTRIM_ADCREFBUFTRIM_Pos (6UL) /*!< MCUCTRL ADCTRIM: ADCREFBUFTRIM (Bit 6) */ -#define MCUCTRL_ADCTRIM_ADCREFBUFTRIM_Msk (0x7c0UL) /*!< MCUCTRL ADCTRIM: ADCREFBUFTRIM (Bitfield-Mask: 0x1f) */ -#define MCUCTRL_ADCTRIM_ADCREFKEEPIBTRIM_Pos (0UL) /*!< MCUCTRL ADCTRIM: ADCREFKEEPIBTRIM (Bit 0) */ -#define MCUCTRL_ADCTRIM_ADCREFKEEPIBTRIM_Msk (0x3UL) /*!< MCUCTRL ADCTRIM: ADCREFKEEPIBTRIM (Bitfield-Mask: 0x03) */ -/* ====================================================== ADCREFCOMP ======================================================= */ -#define MCUCTRL_ADCREFCOMP_ADCRFCMPEN_Pos (16UL) /*!< MCUCTRL ADCREFCOMP: ADCRFCMPEN (Bit 16) */ -#define MCUCTRL_ADCREFCOMP_ADCRFCMPEN_Msk (0x10000UL) /*!< MCUCTRL ADCREFCOMP: ADCRFCMPEN (Bitfield-Mask: 0x01) */ -#define MCUCTRL_ADCREFCOMP_ADCREFKEEPTRIM_Pos (8UL) /*!< MCUCTRL ADCREFCOMP: ADCREFKEEPTRIM (Bit 8) */ -#define MCUCTRL_ADCREFCOMP_ADCREFKEEPTRIM_Msk (0x1f00UL) /*!< MCUCTRL ADCREFCOMP: ADCREFKEEPTRIM (Bitfield-Mask: 0x1f) */ -#define MCUCTRL_ADCREFCOMP_ADC_REFCOMP_OUT_Pos (0UL) /*!< MCUCTRL ADCREFCOMP: ADC_REFCOMP_OUT (Bit 0) */ -#define MCUCTRL_ADCREFCOMP_ADC_REFCOMP_OUT_Msk (0x1UL) /*!< MCUCTRL ADCREFCOMP: ADC_REFCOMP_OUT (Bitfield-Mask: 0x01) */ -/* ======================================================= XTALCTRL ======================================================== */ -#define MCUCTRL_XTALCTRL_XTALICOMPTRIM_Pos (8UL) /*!< MCUCTRL XTALCTRL: XTALICOMPTRIM (Bit 8) */ -#define MCUCTRL_XTALCTRL_XTALICOMPTRIM_Msk (0x300UL) /*!< MCUCTRL XTALCTRL: XTALICOMPTRIM (Bitfield-Mask: 0x03) */ -#define MCUCTRL_XTALCTRL_XTALIBUFTRIM_Pos (6UL) /*!< MCUCTRL XTALCTRL: XTALIBUFTRIM (Bit 6) */ -#define MCUCTRL_XTALCTRL_XTALIBUFTRIM_Msk (0xc0UL) /*!< MCUCTRL XTALCTRL: XTALIBUFTRIM (Bitfield-Mask: 0x03) */ -#define MCUCTRL_XTALCTRL_PWDBODXTAL_Pos (5UL) /*!< MCUCTRL XTALCTRL: PWDBODXTAL (Bit 5) */ -#define MCUCTRL_XTALCTRL_PWDBODXTAL_Msk (0x20UL) /*!< MCUCTRL XTALCTRL: PWDBODXTAL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_XTALCTRL_PDNBCMPRXTAL_Pos (4UL) /*!< MCUCTRL XTALCTRL: PDNBCMPRXTAL (Bit 4) */ -#define MCUCTRL_XTALCTRL_PDNBCMPRXTAL_Msk (0x10UL) /*!< MCUCTRL XTALCTRL: PDNBCMPRXTAL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_XTALCTRL_PDNBCOREXTAL_Pos (3UL) /*!< MCUCTRL XTALCTRL: PDNBCOREXTAL (Bit 3) */ -#define MCUCTRL_XTALCTRL_PDNBCOREXTAL_Msk (0x8UL) /*!< MCUCTRL XTALCTRL: PDNBCOREXTAL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_XTALCTRL_BYPCMPRXTAL_Pos (2UL) /*!< MCUCTRL XTALCTRL: BYPCMPRXTAL (Bit 2) */ -#define MCUCTRL_XTALCTRL_BYPCMPRXTAL_Msk (0x4UL) /*!< MCUCTRL XTALCTRL: BYPCMPRXTAL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_XTALCTRL_FDBKDSBLXTAL_Pos (1UL) /*!< MCUCTRL XTALCTRL: FDBKDSBLXTAL (Bit 1) */ -#define MCUCTRL_XTALCTRL_FDBKDSBLXTAL_Msk (0x2UL) /*!< MCUCTRL XTALCTRL: FDBKDSBLXTAL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_XTALCTRL_XTALSWE_Pos (0UL) /*!< MCUCTRL XTALCTRL: XTALSWE (Bit 0) */ -#define MCUCTRL_XTALCTRL_XTALSWE_Msk (0x1UL) /*!< MCUCTRL XTALCTRL: XTALSWE (Bitfield-Mask: 0x01) */ -/* ====================================================== XTALGENCTRL ====================================================== */ -#define MCUCTRL_XTALGENCTRL_XTALKSBIASTRIM_Pos (8UL) /*!< MCUCTRL XTALGENCTRL: XTALKSBIASTRIM (Bit 8) */ -#define MCUCTRL_XTALGENCTRL_XTALKSBIASTRIM_Msk (0x3f00UL) /*!< MCUCTRL XTALGENCTRL: XTALKSBIASTRIM (Bitfield-Mask: 0x3f) */ -#define MCUCTRL_XTALGENCTRL_XTALBIASTRIM_Pos (2UL) /*!< MCUCTRL XTALGENCTRL: XTALBIASTRIM (Bit 2) */ -#define MCUCTRL_XTALGENCTRL_XTALBIASTRIM_Msk (0xfcUL) /*!< MCUCTRL XTALGENCTRL: XTALBIASTRIM (Bitfield-Mask: 0x3f) */ -#define MCUCTRL_XTALGENCTRL_ACWARMUP_Pos (0UL) /*!< MCUCTRL XTALGENCTRL: ACWARMUP (Bit 0) */ -#define MCUCTRL_XTALGENCTRL_ACWARMUP_Msk (0x3UL) /*!< MCUCTRL XTALGENCTRL: ACWARMUP (Bitfield-Mask: 0x03) */ -/* ======================================================= MISCCTRL ======================================================== */ -#define MCUCTRL_MISCCTRL_BLE_RESETN_Pos (5UL) /*!< MCUCTRL MISCCTRL: BLE_RESETN (Bit 5) */ -#define MCUCTRL_MISCCTRL_BLE_RESETN_Msk (0x20UL) /*!< MCUCTRL MISCCTRL: BLE_RESETN (Bitfield-Mask: 0x01) */ -#define MCUCTRL_MISCCTRL_RESERVED_RW_0_Pos (0UL) /*!< MCUCTRL MISCCTRL: RESERVED_RW_0 (Bit 0) */ -#define MCUCTRL_MISCCTRL_RESERVED_RW_0_Msk (0x1fUL) /*!< MCUCTRL MISCCTRL: RESERVED_RW_0 (Bitfield-Mask: 0x1f) */ -/* ====================================================== BOOTLOADER ======================================================= */ -#define MCUCTRL_BOOTLOADER_SECBOOTONRST_Pos (30UL) /*!< MCUCTRL BOOTLOADER: SECBOOTONRST (Bit 30) */ -#define MCUCTRL_BOOTLOADER_SECBOOTONRST_Msk (0xc0000000UL) /*!< MCUCTRL BOOTLOADER: SECBOOTONRST (Bitfield-Mask: 0x03) */ -#define MCUCTRL_BOOTLOADER_SECBOOT_Pos (28UL) /*!< MCUCTRL BOOTLOADER: SECBOOT (Bit 28) */ -#define MCUCTRL_BOOTLOADER_SECBOOT_Msk (0x30000000UL) /*!< MCUCTRL BOOTLOADER: SECBOOT (Bitfield-Mask: 0x03) */ -#define MCUCTRL_BOOTLOADER_SECBOOTFEATURE_Pos (26UL) /*!< MCUCTRL BOOTLOADER: SECBOOTFEATURE (Bit 26) */ -#define MCUCTRL_BOOTLOADER_SECBOOTFEATURE_Msk (0xc000000UL) /*!< MCUCTRL BOOTLOADER: SECBOOTFEATURE (Bitfield-Mask: 0x03) */ -#define MCUCTRL_BOOTLOADER_PROTLOCK_Pos (2UL) /*!< MCUCTRL BOOTLOADER: PROTLOCK (Bit 2) */ -#define MCUCTRL_BOOTLOADER_PROTLOCK_Msk (0x4UL) /*!< MCUCTRL BOOTLOADER: PROTLOCK (Bitfield-Mask: 0x01) */ -#define MCUCTRL_BOOTLOADER_SBLOCK_Pos (1UL) /*!< MCUCTRL BOOTLOADER: SBLOCK (Bit 1) */ -#define MCUCTRL_BOOTLOADER_SBLOCK_Msk (0x2UL) /*!< MCUCTRL BOOTLOADER: SBLOCK (Bitfield-Mask: 0x01) */ -#define MCUCTRL_BOOTLOADER_BOOTLOADERLOW_Pos (0UL) /*!< MCUCTRL BOOTLOADER: BOOTLOADERLOW (Bit 0) */ -#define MCUCTRL_BOOTLOADER_BOOTLOADERLOW_Msk (0x1UL) /*!< MCUCTRL BOOTLOADER: BOOTLOADERLOW (Bitfield-Mask: 0x01) */ -/* ====================================================== SHADOWVALID ====================================================== */ -#define MCUCTRL_SHADOWVALID_INFO0_VALID_Pos (2UL) /*!< MCUCTRL SHADOWVALID: INFO0_VALID (Bit 2) */ -#define MCUCTRL_SHADOWVALID_INFO0_VALID_Msk (0x4UL) /*!< MCUCTRL SHADOWVALID: INFO0_VALID (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SHADOWVALID_BLDSLEEP_Pos (1UL) /*!< MCUCTRL SHADOWVALID: BLDSLEEP (Bit 1) */ -#define MCUCTRL_SHADOWVALID_BLDSLEEP_Msk (0x2UL) /*!< MCUCTRL SHADOWVALID: BLDSLEEP (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SHADOWVALID_VALID_Pos (0UL) /*!< MCUCTRL SHADOWVALID: VALID (Bit 0) */ -#define MCUCTRL_SHADOWVALID_VALID_Msk (0x1UL) /*!< MCUCTRL SHADOWVALID: VALID (Bitfield-Mask: 0x01) */ -/* ======================================================= SCRATCH0 ======================================================== */ -#define MCUCTRL_SCRATCH0_SCRATCH0_Pos (0UL) /*!< MCUCTRL SCRATCH0: SCRATCH0 (Bit 0) */ -#define MCUCTRL_SCRATCH0_SCRATCH0_Msk (0xffffffffUL) /*!< MCUCTRL SCRATCH0: SCRATCH0 (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= SCRATCH1 ======================================================== */ -#define MCUCTRL_SCRATCH1_SCRATCH1_Pos (0UL) /*!< MCUCTRL SCRATCH1: SCRATCH1 (Bit 0) */ -#define MCUCTRL_SCRATCH1_SCRATCH1_Msk (0xffffffffUL) /*!< MCUCTRL SCRATCH1: SCRATCH1 (Bitfield-Mask: 0xffffffff) */ -/* ==================================================== ICODEFAULTADDR ===================================================== */ -#define MCUCTRL_ICODEFAULTADDR_ICODEFAULTADDR_Pos (0UL) /*!< MCUCTRL ICODEFAULTADDR: ICODEFAULTADDR (Bit 0) */ -#define MCUCTRL_ICODEFAULTADDR_ICODEFAULTADDR_Msk (0xffffffffUL) /*!< MCUCTRL ICODEFAULTADDR: ICODEFAULTADDR (Bitfield-Mask: 0xffffffff) */ -/* ==================================================== DCODEFAULTADDR ===================================================== */ -#define MCUCTRL_DCODEFAULTADDR_DCODEFAULTADDR_Pos (0UL) /*!< MCUCTRL DCODEFAULTADDR: DCODEFAULTADDR (Bit 0) */ -#define MCUCTRL_DCODEFAULTADDR_DCODEFAULTADDR_Msk (0xffffffffUL) /*!< MCUCTRL DCODEFAULTADDR: DCODEFAULTADDR (Bitfield-Mask: 0xffffffff) */ -/* ===================================================== SYSFAULTADDR ====================================================== */ -#define MCUCTRL_SYSFAULTADDR_SYSFAULTADDR_Pos (0UL) /*!< MCUCTRL SYSFAULTADDR: SYSFAULTADDR (Bit 0) */ -#define MCUCTRL_SYSFAULTADDR_SYSFAULTADDR_Msk (0xffffffffUL) /*!< MCUCTRL SYSFAULTADDR: SYSFAULTADDR (Bitfield-Mask: 0xffffffff) */ -/* ====================================================== FAULTSTATUS ====================================================== */ -#define MCUCTRL_FAULTSTATUS_SYSFAULT_Pos (2UL) /*!< MCUCTRL FAULTSTATUS: SYSFAULT (Bit 2) */ -#define MCUCTRL_FAULTSTATUS_SYSFAULT_Msk (0x4UL) /*!< MCUCTRL FAULTSTATUS: SYSFAULT (Bitfield-Mask: 0x01) */ -#define MCUCTRL_FAULTSTATUS_DCODEFAULT_Pos (1UL) /*!< MCUCTRL FAULTSTATUS: DCODEFAULT (Bit 1) */ -#define MCUCTRL_FAULTSTATUS_DCODEFAULT_Msk (0x2UL) /*!< MCUCTRL FAULTSTATUS: DCODEFAULT (Bitfield-Mask: 0x01) */ -#define MCUCTRL_FAULTSTATUS_ICODEFAULT_Pos (0UL) /*!< MCUCTRL FAULTSTATUS: ICODEFAULT (Bit 0) */ -#define MCUCTRL_FAULTSTATUS_ICODEFAULT_Msk (0x1UL) /*!< MCUCTRL FAULTSTATUS: ICODEFAULT (Bitfield-Mask: 0x01) */ -/* ==================================================== FAULTCAPTUREEN ===================================================== */ -#define MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_Pos (0UL) /*!< MCUCTRL FAULTCAPTUREEN: FAULTCAPTUREEN (Bit 0) */ -#define MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_Msk (0x1UL) /*!< MCUCTRL FAULTCAPTUREEN: FAULTCAPTUREEN (Bitfield-Mask: 0x01) */ -/* ========================================================= DBGR1 ========================================================= */ -#define MCUCTRL_DBGR1_ONETO8_Pos (0UL) /*!< MCUCTRL DBGR1: ONETO8 (Bit 0) */ -#define MCUCTRL_DBGR1_ONETO8_Msk (0xffffffffUL) /*!< MCUCTRL DBGR1: ONETO8 (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= DBGR2 ========================================================= */ -#define MCUCTRL_DBGR2_COOLCODE_Pos (0UL) /*!< MCUCTRL DBGR2: COOLCODE (Bit 0) */ -#define MCUCTRL_DBGR2_COOLCODE_Msk (0xffffffffUL) /*!< MCUCTRL DBGR2: COOLCODE (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= PMUENABLE ======================================================= */ -#define MCUCTRL_PMUENABLE_ENABLE_Pos (0UL) /*!< MCUCTRL PMUENABLE: ENABLE (Bit 0) */ -#define MCUCTRL_PMUENABLE_ENABLE_Msk (0x1UL) /*!< MCUCTRL PMUENABLE: ENABLE (Bitfield-Mask: 0x01) */ -/* ======================================================= TPIUCTRL ======================================================== */ -#define MCUCTRL_TPIUCTRL_CLKSEL_Pos (8UL) /*!< MCUCTRL TPIUCTRL: CLKSEL (Bit 8) */ -#define MCUCTRL_TPIUCTRL_CLKSEL_Msk (0x700UL) /*!< MCUCTRL TPIUCTRL: CLKSEL (Bitfield-Mask: 0x07) */ -#define MCUCTRL_TPIUCTRL_ENABLE_Pos (0UL) /*!< MCUCTRL TPIUCTRL: ENABLE (Bit 0) */ -#define MCUCTRL_TPIUCTRL_ENABLE_Msk (0x1UL) /*!< MCUCTRL TPIUCTRL: ENABLE (Bitfield-Mask: 0x01) */ -/* ====================================================== OTAPOINTER ======================================================= */ -#define MCUCTRL_OTAPOINTER_OTAPOINTER_Pos (2UL) /*!< MCUCTRL OTAPOINTER: OTAPOINTER (Bit 2) */ -#define MCUCTRL_OTAPOINTER_OTAPOINTER_Msk (0xfffffffcUL) /*!< MCUCTRL OTAPOINTER: OTAPOINTER (Bitfield-Mask: 0x3fffffff) */ -#define MCUCTRL_OTAPOINTER_OTASBLUPDATE_Pos (1UL) /*!< MCUCTRL OTAPOINTER: OTASBLUPDATE (Bit 1) */ -#define MCUCTRL_OTAPOINTER_OTASBLUPDATE_Msk (0x2UL) /*!< MCUCTRL OTAPOINTER: OTASBLUPDATE (Bitfield-Mask: 0x01) */ -#define MCUCTRL_OTAPOINTER_OTAVALID_Pos (0UL) /*!< MCUCTRL OTAPOINTER: OTAVALID (Bit 0) */ -#define MCUCTRL_OTAPOINTER_OTAVALID_Msk (0x1UL) /*!< MCUCTRL OTAPOINTER: OTAVALID (Bitfield-Mask: 0x01) */ -/* ====================================================== APBDMACTRL ======================================================= */ -#define MCUCTRL_APBDMACTRL_HYSTERESIS_Pos (8UL) /*!< MCUCTRL APBDMACTRL: HYSTERESIS (Bit 8) */ -#define MCUCTRL_APBDMACTRL_HYSTERESIS_Msk (0xff00UL) /*!< MCUCTRL APBDMACTRL: HYSTERESIS (Bitfield-Mask: 0xff) */ -#define MCUCTRL_APBDMACTRL_DECODEABORT_Pos (1UL) /*!< MCUCTRL APBDMACTRL: DECODEABORT (Bit 1) */ -#define MCUCTRL_APBDMACTRL_DECODEABORT_Msk (0x2UL) /*!< MCUCTRL APBDMACTRL: DECODEABORT (Bitfield-Mask: 0x01) */ -#define MCUCTRL_APBDMACTRL_DMA_ENABLE_Pos (0UL) /*!< MCUCTRL APBDMACTRL: DMA_ENABLE (Bit 0) */ -#define MCUCTRL_APBDMACTRL_DMA_ENABLE_Msk (0x1UL) /*!< MCUCTRL APBDMACTRL: DMA_ENABLE (Bitfield-Mask: 0x01) */ -/* ======================================================= SRAMMODE ======================================================== */ -#define MCUCTRL_SRAMMODE_DPREFETCH_CACHE_Pos (5UL) /*!< MCUCTRL SRAMMODE: DPREFETCH_CACHE (Bit 5) */ -#define MCUCTRL_SRAMMODE_DPREFETCH_CACHE_Msk (0x20UL) /*!< MCUCTRL SRAMMODE: DPREFETCH_CACHE (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SRAMMODE_DPREFETCH_Pos (4UL) /*!< MCUCTRL SRAMMODE: DPREFETCH (Bit 4) */ -#define MCUCTRL_SRAMMODE_DPREFETCH_Msk (0x10UL) /*!< MCUCTRL SRAMMODE: DPREFETCH (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SRAMMODE_IPREFETCH_CACHE_Pos (1UL) /*!< MCUCTRL SRAMMODE: IPREFETCH_CACHE (Bit 1) */ -#define MCUCTRL_SRAMMODE_IPREFETCH_CACHE_Msk (0x2UL) /*!< MCUCTRL SRAMMODE: IPREFETCH_CACHE (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SRAMMODE_IPREFETCH_Pos (0UL) /*!< MCUCTRL SRAMMODE: IPREFETCH (Bit 0) */ -#define MCUCTRL_SRAMMODE_IPREFETCH_Msk (0x1UL) /*!< MCUCTRL SRAMMODE: IPREFETCH (Bitfield-Mask: 0x01) */ -/* ====================================================== KEXTCLKSEL ======================================================= */ -#define MCUCTRL_KEXTCLKSEL_KEXTCLKSEL_Pos (0UL) /*!< MCUCTRL KEXTCLKSEL: KEXTCLKSEL (Bit 0) */ -#define MCUCTRL_KEXTCLKSEL_KEXTCLKSEL_Msk (0xffffffffUL) /*!< MCUCTRL KEXTCLKSEL: KEXTCLKSEL (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= SIMOBUCK4 ======================================================= */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKIBIASTRIM_Pos (28UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKIBIASTRIM (Bit 28) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKIBIASTRIM_Msk (0xf0000000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKIBIASTRIM (Bitfield-Mask: 0x0f) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLOMODE_Pos (26UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLOMODE (Bit 26) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLOMODE_Msk (0xc000000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLOMODE (Bitfield-Mask: 0x03) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKPRIORITYSEL_Pos (25UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKPRIORITYSEL (Bit 25) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKPRIORITYSEL_Msk (0x2000000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKPRIORITYSEL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKCOMP2TIMEOUTEN_Pos (24UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCOMP2TIMEOUTEN (Bit 24) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKCOMP2TIMEOUTEN_Msk (0x1000000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCOMP2TIMEOUTEN (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKCOMP2LPEN_Pos (23UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCOMP2LPEN (Bit 23) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKCOMP2LPEN_Msk (0x800000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCOMP2LPEN (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKCLKDIVSEL_Pos (21UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCLKDIVSEL (Bit 21) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKCLKDIVSEL_Msk (0x600000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKCLKDIVSEL (Bitfield-Mask: 0x03) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKEXTCLKSEL_Pos (20UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKEXTCLKSEL (Bit 20) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKEXTCLKSEL_Msk (0x100000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKEXTCLKSEL (Bitfield-Mask: 0x01) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLODRVSTRTRIM_Pos (17UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLODRVSTRTRIM (Bit 17) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLODRVSTRTRIM_Msk (0xe0000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLODRVSTRTRIM (Bitfield-Mask: 0x07) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLOCNTRTRIM_Pos (14UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLOCNTRTRIM (Bit 14) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKUVLOCNTRTRIM_Msk (0x1c000UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKUVLOCNTRTRIM (Bitfield-Mask: 0x07) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKZXTRIM_Pos (10UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKZXTRIM (Bit 10) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKZXTRIM_Msk (0x3c00UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKZXTRIM (Bitfield-Mask: 0x0f) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLEAKAGETRIM_Pos (8UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLEAKAGETRIM (Bit 8) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLEAKAGETRIM_Msk (0x300UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLEAKAGETRIM (Bitfield-Mask: 0x03) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLPDRVSTRTRIM_Pos (6UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLPDRVSTRTRIM (Bit 6) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLPDRVSTRTRIM_Msk (0xc0UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLPDRVSTRTRIM (Bitfield-Mask: 0x03) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMACTDRVSTRTRIM_Pos (4UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMACTDRVSTRTRIM (Bit 4) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMACTDRVSTRTRIM_Msk (0x30UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMACTDRVSTRTRIM (Bitfield-Mask: 0x03) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLPLOWTONTRIM_Pos (0UL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLPLOWTONTRIM (Bit 0) */ -#define MCUCTRL_SIMOBUCK4_SIMOBUCKMEMLPLOWTONTRIM_Msk (0xfUL) /*!< MCUCTRL SIMOBUCK4: SIMOBUCKMEMLPLOWTONTRIM (Bitfield-Mask: 0x0f) */ -/* ======================================================= BLEBUCK2 ======================================================== */ -#define MCUCTRL_BLEBUCK2_BLEBUCKTOND2ATRIM_Pos (12UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTOND2ATRIM (Bit 12) */ -#define MCUCTRL_BLEBUCK2_BLEBUCKTOND2ATRIM_Msk (0x3f000UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTOND2ATRIM (Bitfield-Mask: 0x3f) */ -#define MCUCTRL_BLEBUCK2_BLEBUCKTONHITRIM_Pos (6UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTONHITRIM (Bit 6) */ -#define MCUCTRL_BLEBUCK2_BLEBUCKTONHITRIM_Msk (0xfc0UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTONHITRIM (Bitfield-Mask: 0x3f) */ -#define MCUCTRL_BLEBUCK2_BLEBUCKTONLOWTRIM_Pos (0UL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTONLOWTRIM (Bit 0) */ -#define MCUCTRL_BLEBUCK2_BLEBUCKTONLOWTRIM_Msk (0x3fUL) /*!< MCUCTRL BLEBUCK2: BLEBUCKTONLOWTRIM (Bitfield-Mask: 0x3f) */ -/* ====================================================== FLASHWPROT0 ====================================================== */ -#define MCUCTRL_FLASHWPROT0_FW0BITS_Pos (0UL) /*!< MCUCTRL FLASHWPROT0: FW0BITS (Bit 0) */ -#define MCUCTRL_FLASHWPROT0_FW0BITS_Msk (0xffffffffUL) /*!< MCUCTRL FLASHWPROT0: FW0BITS (Bitfield-Mask: 0xffffffff) */ -/* ====================================================== FLASHWPROT1 ====================================================== */ -#define MCUCTRL_FLASHWPROT1_FW1BITS_Pos (0UL) /*!< MCUCTRL FLASHWPROT1: FW1BITS (Bit 0) */ -#define MCUCTRL_FLASHWPROT1_FW1BITS_Msk (0xffffffffUL) /*!< MCUCTRL FLASHWPROT1: FW1BITS (Bitfield-Mask: 0xffffffff) */ -/* ====================================================== FLASHRPROT0 ====================================================== */ -#define MCUCTRL_FLASHRPROT0_FR0BITS_Pos (0UL) /*!< MCUCTRL FLASHRPROT0: FR0BITS (Bit 0) */ -#define MCUCTRL_FLASHRPROT0_FR0BITS_Msk (0xffffffffUL) /*!< MCUCTRL FLASHRPROT0: FR0BITS (Bitfield-Mask: 0xffffffff) */ -/* ====================================================== FLASHRPROT1 ====================================================== */ -#define MCUCTRL_FLASHRPROT1_FR1BITS_Pos (0UL) /*!< MCUCTRL FLASHRPROT1: FR1BITS (Bit 0) */ -#define MCUCTRL_FLASHRPROT1_FR1BITS_Msk (0xffffffffUL) /*!< MCUCTRL FLASHRPROT1: FR1BITS (Bitfield-Mask: 0xffffffff) */ -/* ================================================= DMASRAMWRITEPROTECT0 ================================================== */ -#define MCUCTRL_DMASRAMWRITEPROTECT0_DMA_WPROT0_Pos (0UL) /*!< MCUCTRL DMASRAMWRITEPROTECT0: DMA_WPROT0 (Bit 0) */ -#define MCUCTRL_DMASRAMWRITEPROTECT0_DMA_WPROT0_Msk (0xffffffffUL) /*!< MCUCTRL DMASRAMWRITEPROTECT0: DMA_WPROT0 (Bitfield-Mask: 0xffffffff) */ -/* ================================================= DMASRAMWRITEPROTECT1 ================================================== */ -#define MCUCTRL_DMASRAMWRITEPROTECT1_DMA_WPROT1_Pos (0UL) /*!< MCUCTRL DMASRAMWRITEPROTECT1: DMA_WPROT1 (Bit 0) */ -#define MCUCTRL_DMASRAMWRITEPROTECT1_DMA_WPROT1_Msk (0xffffUL) /*!< MCUCTRL DMASRAMWRITEPROTECT1: DMA_WPROT1 (Bitfield-Mask: 0xffff) */ -/* ================================================== DMASRAMREADPROTECT0 ================================================== */ -#define MCUCTRL_DMASRAMREADPROTECT0_DMA_RPROT0_Pos (0UL) /*!< MCUCTRL DMASRAMREADPROTECT0: DMA_RPROT0 (Bit 0) */ -#define MCUCTRL_DMASRAMREADPROTECT0_DMA_RPROT0_Msk (0xffffffffUL) /*!< MCUCTRL DMASRAMREADPROTECT0: DMA_RPROT0 (Bitfield-Mask: 0xffffffff) */ -/* ================================================== DMASRAMREADPROTECT1 ================================================== */ -#define MCUCTRL_DMASRAMREADPROTECT1_DMA_RPROT1_Pos (0UL) /*!< MCUCTRL DMASRAMREADPROTECT1: DMA_RPROT1 (Bit 0) */ -#define MCUCTRL_DMASRAMREADPROTECT1_DMA_RPROT1_Msk (0xffffUL) /*!< MCUCTRL DMASRAMREADPROTECT1: DMA_RPROT1 (Bitfield-Mask: 0xffff) */ - - -/* =========================================================================================================================== */ -/* ================ MSPI ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= CTRL ========================================================== */ -#define MSPI_CTRL_XFERBYTES_Pos (16UL) /*!< MSPI CTRL: XFERBYTES (Bit 16) */ -#define MSPI_CTRL_XFERBYTES_Msk (0xffff0000UL) /*!< MSPI CTRL: XFERBYTES (Bitfield-Mask: 0xffff) */ -#define MSPI_CTRL_PIOSCRAMBLE_Pos (11UL) /*!< MSPI CTRL: PIOSCRAMBLE (Bit 11) */ -#define MSPI_CTRL_PIOSCRAMBLE_Msk (0x800UL) /*!< MSPI CTRL: PIOSCRAMBLE (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_TXRX_Pos (10UL) /*!< MSPI CTRL: TXRX (Bit 10) */ -#define MSPI_CTRL_TXRX_Msk (0x400UL) /*!< MSPI CTRL: TXRX (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_SENDI_Pos (9UL) /*!< MSPI CTRL: SENDI (Bit 9) */ -#define MSPI_CTRL_SENDI_Msk (0x200UL) /*!< MSPI CTRL: SENDI (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_SENDA_Pos (8UL) /*!< MSPI CTRL: SENDA (Bit 8) */ -#define MSPI_CTRL_SENDA_Msk (0x100UL) /*!< MSPI CTRL: SENDA (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_ENTURN_Pos (7UL) /*!< MSPI CTRL: ENTURN (Bit 7) */ -#define MSPI_CTRL_ENTURN_Msk (0x80UL) /*!< MSPI CTRL: ENTURN (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_BIGENDIAN_Pos (6UL) /*!< MSPI CTRL: BIGENDIAN (Bit 6) */ -#define MSPI_CTRL_BIGENDIAN_Msk (0x40UL) /*!< MSPI CTRL: BIGENDIAN (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_CONT_Pos (5UL) /*!< MSPI CTRL: CONT (Bit 5) */ -#define MSPI_CTRL_CONT_Msk (0x20UL) /*!< MSPI CTRL: CONT (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_QUADCMD_Pos (3UL) /*!< MSPI CTRL: QUADCMD (Bit 3) */ -#define MSPI_CTRL_QUADCMD_Msk (0x8UL) /*!< MSPI CTRL: QUADCMD (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_BUSY_Pos (2UL) /*!< MSPI CTRL: BUSY (Bit 2) */ -#define MSPI_CTRL_BUSY_Msk (0x4UL) /*!< MSPI CTRL: BUSY (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_STATUS_Pos (1UL) /*!< MSPI CTRL: STATUS (Bit 1) */ -#define MSPI_CTRL_STATUS_Msk (0x2UL) /*!< MSPI CTRL: STATUS (Bitfield-Mask: 0x01) */ -#define MSPI_CTRL_START_Pos (0UL) /*!< MSPI CTRL: START (Bit 0) */ -#define MSPI_CTRL_START_Msk (0x1UL) /*!< MSPI CTRL: START (Bitfield-Mask: 0x01) */ -/* ========================================================== CFG ========================================================== */ -#define MSPI_CFG_CPOL_Pos (17UL) /*!< MSPI CFG: CPOL (Bit 17) */ -#define MSPI_CFG_CPOL_Msk (0x20000UL) /*!< MSPI CFG: CPOL (Bitfield-Mask: 0x01) */ -#define MSPI_CFG_CPHA_Pos (16UL) /*!< MSPI CFG: CPHA (Bit 16) */ -#define MSPI_CFG_CPHA_Msk (0x10000UL) /*!< MSPI CFG: CPHA (Bitfield-Mask: 0x01) */ -#define MSPI_CFG_TURNAROUND_Pos (8UL) /*!< MSPI CFG: TURNAROUND (Bit 8) */ -#define MSPI_CFG_TURNAROUND_Msk (0x3f00UL) /*!< MSPI CFG: TURNAROUND (Bitfield-Mask: 0x3f) */ -#define MSPI_CFG_SEPIO_Pos (7UL) /*!< MSPI CFG: SEPIO (Bit 7) */ -#define MSPI_CFG_SEPIO_Msk (0x80UL) /*!< MSPI CFG: SEPIO (Bitfield-Mask: 0x01) */ -#define MSPI_CFG_ISIZE_Pos (6UL) /*!< MSPI CFG: ISIZE (Bit 6) */ -#define MSPI_CFG_ISIZE_Msk (0x40UL) /*!< MSPI CFG: ISIZE (Bitfield-Mask: 0x01) */ -#define MSPI_CFG_ASIZE_Pos (4UL) /*!< MSPI CFG: ASIZE (Bit 4) */ -#define MSPI_CFG_ASIZE_Msk (0x30UL) /*!< MSPI CFG: ASIZE (Bitfield-Mask: 0x03) */ -#define MSPI_CFG_DEVCFG_Pos (0UL) /*!< MSPI CFG: DEVCFG (Bit 0) */ -#define MSPI_CFG_DEVCFG_Msk (0xfUL) /*!< MSPI CFG: DEVCFG (Bitfield-Mask: 0x0f) */ -/* ========================================================= ADDR ========================================================== */ -#define MSPI_ADDR_ADDR_Pos (0UL) /*!< MSPI ADDR: ADDR (Bit 0) */ -#define MSPI_ADDR_ADDR_Msk (0xffffffffUL) /*!< MSPI ADDR: ADDR (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= INSTR ========================================================= */ -#define MSPI_INSTR_INSTR_Pos (0UL) /*!< MSPI INSTR: INSTR (Bit 0) */ -#define MSPI_INSTR_INSTR_Msk (0xffffUL) /*!< MSPI INSTR: INSTR (Bitfield-Mask: 0xffff) */ -/* ======================================================== TXFIFO ========================================================= */ -#define MSPI_TXFIFO_TXFIFO_Pos (0UL) /*!< MSPI TXFIFO: TXFIFO (Bit 0) */ -#define MSPI_TXFIFO_TXFIFO_Msk (0xffffffffUL) /*!< MSPI TXFIFO: TXFIFO (Bitfield-Mask: 0xffffffff) */ -/* ======================================================== RXFIFO ========================================================= */ -#define MSPI_RXFIFO_RXFIFO_Pos (0UL) /*!< MSPI RXFIFO: RXFIFO (Bit 0) */ -#define MSPI_RXFIFO_RXFIFO_Msk (0xffffffffUL) /*!< MSPI RXFIFO: RXFIFO (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= TXENTRIES ======================================================= */ -#define MSPI_TXENTRIES_TXENTRIES_Pos (0UL) /*!< MSPI TXENTRIES: TXENTRIES (Bit 0) */ -#define MSPI_TXENTRIES_TXENTRIES_Msk (0x1fUL) /*!< MSPI TXENTRIES: TXENTRIES (Bitfield-Mask: 0x1f) */ -/* ======================================================= RXENTRIES ======================================================= */ -#define MSPI_RXENTRIES_RXENTRIES_Pos (0UL) /*!< MSPI RXENTRIES: RXENTRIES (Bit 0) */ -#define MSPI_RXENTRIES_RXENTRIES_Msk (0x1fUL) /*!< MSPI RXENTRIES: RXENTRIES (Bitfield-Mask: 0x1f) */ -/* ======================================================= THRESHOLD ======================================================= */ -#define MSPI_THRESHOLD_RXTHRESH_Pos (8UL) /*!< MSPI THRESHOLD: RXTHRESH (Bit 8) */ -#define MSPI_THRESHOLD_RXTHRESH_Msk (0x1f00UL) /*!< MSPI THRESHOLD: RXTHRESH (Bitfield-Mask: 0x1f) */ -#define MSPI_THRESHOLD_TXTHRESH_Pos (0UL) /*!< MSPI THRESHOLD: TXTHRESH (Bit 0) */ -#define MSPI_THRESHOLD_TXTHRESH_Msk (0x1fUL) /*!< MSPI THRESHOLD: TXTHRESH (Bitfield-Mask: 0x1f) */ -/* ======================================================== MSPICFG ======================================================== */ -#define MSPI_MSPICFG_PRSTN_Pos (31UL) /*!< MSPI MSPICFG: PRSTN (Bit 31) */ -#define MSPI_MSPICFG_PRSTN_Msk (0x80000000UL) /*!< MSPI MSPICFG: PRSTN (Bitfield-Mask: 0x01) */ -#define MSPI_MSPICFG_IPRSTN_Pos (30UL) /*!< MSPI MSPICFG: IPRSTN (Bit 30) */ -#define MSPI_MSPICFG_IPRSTN_Msk (0x40000000UL) /*!< MSPI MSPICFG: IPRSTN (Bitfield-Mask: 0x01) */ -#define MSPI_MSPICFG_FIFORESET_Pos (29UL) /*!< MSPI MSPICFG: FIFORESET (Bit 29) */ -#define MSPI_MSPICFG_FIFORESET_Msk (0x20000000UL) /*!< MSPI MSPICFG: FIFORESET (Bitfield-Mask: 0x01) */ -#define MSPI_MSPICFG_CLKDIV_Pos (8UL) /*!< MSPI MSPICFG: CLKDIV (Bit 8) */ -#define MSPI_MSPICFG_CLKDIV_Msk (0x3f00UL) /*!< MSPI MSPICFG: CLKDIV (Bitfield-Mask: 0x3f) */ -#define MSPI_MSPICFG_IOMSEL_Pos (4UL) /*!< MSPI MSPICFG: IOMSEL (Bit 4) */ -#define MSPI_MSPICFG_IOMSEL_Msk (0x70UL) /*!< MSPI MSPICFG: IOMSEL (Bitfield-Mask: 0x07) */ -#define MSPI_MSPICFG_TXNEG_Pos (3UL) /*!< MSPI MSPICFG: TXNEG (Bit 3) */ -#define MSPI_MSPICFG_TXNEG_Msk (0x8UL) /*!< MSPI MSPICFG: TXNEG (Bitfield-Mask: 0x01) */ -#define MSPI_MSPICFG_RXNEG_Pos (2UL) /*!< MSPI MSPICFG: RXNEG (Bit 2) */ -#define MSPI_MSPICFG_RXNEG_Msk (0x4UL) /*!< MSPI MSPICFG: RXNEG (Bitfield-Mask: 0x01) */ -#define MSPI_MSPICFG_RXCAP_Pos (1UL) /*!< MSPI MSPICFG: RXCAP (Bit 1) */ -#define MSPI_MSPICFG_RXCAP_Msk (0x2UL) /*!< MSPI MSPICFG: RXCAP (Bitfield-Mask: 0x01) */ -#define MSPI_MSPICFG_APBCLK_Pos (0UL) /*!< MSPI MSPICFG: APBCLK (Bit 0) */ -#define MSPI_MSPICFG_APBCLK_Msk (0x1UL) /*!< MSPI MSPICFG: APBCLK (Bitfield-Mask: 0x01) */ -/* ======================================================== PADCFG ========================================================= */ -#define MSPI_PADCFG_REVCS_Pos (21UL) /*!< MSPI PADCFG: REVCS (Bit 21) */ -#define MSPI_PADCFG_REVCS_Msk (0x200000UL) /*!< MSPI PADCFG: REVCS (Bitfield-Mask: 0x01) */ -#define MSPI_PADCFG_IN3_Pos (20UL) /*!< MSPI PADCFG: IN3 (Bit 20) */ -#define MSPI_PADCFG_IN3_Msk (0x100000UL) /*!< MSPI PADCFG: IN3 (Bitfield-Mask: 0x01) */ -#define MSPI_PADCFG_IN2_Pos (19UL) /*!< MSPI PADCFG: IN2 (Bit 19) */ -#define MSPI_PADCFG_IN2_Msk (0x80000UL) /*!< MSPI PADCFG: IN2 (Bitfield-Mask: 0x01) */ -#define MSPI_PADCFG_IN1_Pos (18UL) /*!< MSPI PADCFG: IN1 (Bit 18) */ -#define MSPI_PADCFG_IN1_Msk (0x40000UL) /*!< MSPI PADCFG: IN1 (Bitfield-Mask: 0x01) */ -#define MSPI_PADCFG_IN0_Pos (16UL) /*!< MSPI PADCFG: IN0 (Bit 16) */ -#define MSPI_PADCFG_IN0_Msk (0x30000UL) /*!< MSPI PADCFG: IN0 (Bitfield-Mask: 0x03) */ -#define MSPI_PADCFG_OUT7_Pos (4UL) /*!< MSPI PADCFG: OUT7 (Bit 4) */ -#define MSPI_PADCFG_OUT7_Msk (0x10UL) /*!< MSPI PADCFG: OUT7 (Bitfield-Mask: 0x01) */ -#define MSPI_PADCFG_OUT6_Pos (3UL) /*!< MSPI PADCFG: OUT6 (Bit 3) */ -#define MSPI_PADCFG_OUT6_Msk (0x8UL) /*!< MSPI PADCFG: OUT6 (Bitfield-Mask: 0x01) */ -#define MSPI_PADCFG_OUT5_Pos (2UL) /*!< MSPI PADCFG: OUT5 (Bit 2) */ -#define MSPI_PADCFG_OUT5_Msk (0x4UL) /*!< MSPI PADCFG: OUT5 (Bitfield-Mask: 0x01) */ -#define MSPI_PADCFG_OUT4_Pos (1UL) /*!< MSPI PADCFG: OUT4 (Bit 1) */ -#define MSPI_PADCFG_OUT4_Msk (0x2UL) /*!< MSPI PADCFG: OUT4 (Bitfield-Mask: 0x01) */ -#define MSPI_PADCFG_OUT3_Pos (0UL) /*!< MSPI PADCFG: OUT3 (Bit 0) */ -#define MSPI_PADCFG_OUT3_Msk (0x1UL) /*!< MSPI PADCFG: OUT3 (Bitfield-Mask: 0x01) */ -/* ======================================================= PADOUTEN ======================================================== */ -#define MSPI_PADOUTEN_OUTEN_Pos (0UL) /*!< MSPI PADOUTEN: OUTEN (Bit 0) */ -#define MSPI_PADOUTEN_OUTEN_Msk (0x1ffUL) /*!< MSPI PADOUTEN: OUTEN (Bitfield-Mask: 0x1ff) */ -/* ========================================================= FLASH ========================================================= */ -#define MSPI_FLASH_READINSTR_Pos (24UL) /*!< MSPI FLASH: READINSTR (Bit 24) */ -#define MSPI_FLASH_READINSTR_Msk (0xff000000UL) /*!< MSPI FLASH: READINSTR (Bitfield-Mask: 0xff) */ -#define MSPI_FLASH_WRITEINSTR_Pos (16UL) /*!< MSPI FLASH: WRITEINSTR (Bit 16) */ -#define MSPI_FLASH_WRITEINSTR_Msk (0xff0000UL) /*!< MSPI FLASH: WRITEINSTR (Bitfield-Mask: 0xff) */ -#define MSPI_FLASH_XIPMIXED_Pos (8UL) /*!< MSPI FLASH: XIPMIXED (Bit 8) */ -#define MSPI_FLASH_XIPMIXED_Msk (0x700UL) /*!< MSPI FLASH: XIPMIXED (Bitfield-Mask: 0x07) */ -#define MSPI_FLASH_XIPSENDI_Pos (7UL) /*!< MSPI FLASH: XIPSENDI (Bit 7) */ -#define MSPI_FLASH_XIPSENDI_Msk (0x80UL) /*!< MSPI FLASH: XIPSENDI (Bitfield-Mask: 0x01) */ -#define MSPI_FLASH_XIPSENDA_Pos (6UL) /*!< MSPI FLASH: XIPSENDA (Bit 6) */ -#define MSPI_FLASH_XIPSENDA_Msk (0x40UL) /*!< MSPI FLASH: XIPSENDA (Bitfield-Mask: 0x01) */ -#define MSPI_FLASH_XIPENTURN_Pos (5UL) /*!< MSPI FLASH: XIPENTURN (Bit 5) */ -#define MSPI_FLASH_XIPENTURN_Msk (0x20UL) /*!< MSPI FLASH: XIPENTURN (Bitfield-Mask: 0x01) */ -#define MSPI_FLASH_XIPBIGENDIAN_Pos (4UL) /*!< MSPI FLASH: XIPBIGENDIAN (Bit 4) */ -#define MSPI_FLASH_XIPBIGENDIAN_Msk (0x10UL) /*!< MSPI FLASH: XIPBIGENDIAN (Bitfield-Mask: 0x01) */ -#define MSPI_FLASH_XIPACK_Pos (2UL) /*!< MSPI FLASH: XIPACK (Bit 2) */ -#define MSPI_FLASH_XIPACK_Msk (0xcUL) /*!< MSPI FLASH: XIPACK (Bitfield-Mask: 0x03) */ -#define MSPI_FLASH_XIPEN_Pos (0UL) /*!< MSPI FLASH: XIPEN (Bit 0) */ -#define MSPI_FLASH_XIPEN_Msk (0x1UL) /*!< MSPI FLASH: XIPEN (Bitfield-Mask: 0x01) */ -/* ====================================================== SCRAMBLING ======================================================= */ -#define MSPI_SCRAMBLING_SCRENABLE_Pos (31UL) /*!< MSPI SCRAMBLING: SCRENABLE (Bit 31) */ -#define MSPI_SCRAMBLING_SCRENABLE_Msk (0x80000000UL) /*!< MSPI SCRAMBLING: SCRENABLE (Bitfield-Mask: 0x01) */ -#define MSPI_SCRAMBLING_SCREND_Pos (16UL) /*!< MSPI SCRAMBLING: SCREND (Bit 16) */ -#define MSPI_SCRAMBLING_SCREND_Msk (0x3ff0000UL) /*!< MSPI SCRAMBLING: SCREND (Bitfield-Mask: 0x3ff) */ -#define MSPI_SCRAMBLING_SCRSTART_Pos (0UL) /*!< MSPI SCRAMBLING: SCRSTART (Bit 0) */ -#define MSPI_SCRAMBLING_SCRSTART_Msk (0x3ffUL) /*!< MSPI SCRAMBLING: SCRSTART (Bitfield-Mask: 0x3ff) */ -/* ========================================================= INTEN ========================================================= */ -#define MSPI_INTEN_SCRERR_Pos (12UL) /*!< MSPI INTEN: SCRERR (Bit 12) */ -#define MSPI_INTEN_SCRERR_Msk (0x1000UL) /*!< MSPI INTEN: SCRERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_CQERR_Pos (11UL) /*!< MSPI INTEN: CQERR (Bit 11) */ -#define MSPI_INTEN_CQERR_Msk (0x800UL) /*!< MSPI INTEN: CQERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_CQPAUSED_Pos (10UL) /*!< MSPI INTEN: CQPAUSED (Bit 10) */ -#define MSPI_INTEN_CQPAUSED_Msk (0x400UL) /*!< MSPI INTEN: CQPAUSED (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_CQUPD_Pos (9UL) /*!< MSPI INTEN: CQUPD (Bit 9) */ -#define MSPI_INTEN_CQUPD_Msk (0x200UL) /*!< MSPI INTEN: CQUPD (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_CQCMP_Pos (8UL) /*!< MSPI INTEN: CQCMP (Bit 8) */ -#define MSPI_INTEN_CQCMP_Msk (0x100UL) /*!< MSPI INTEN: CQCMP (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_DERR_Pos (7UL) /*!< MSPI INTEN: DERR (Bit 7) */ -#define MSPI_INTEN_DERR_Msk (0x80UL) /*!< MSPI INTEN: DERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_DCMP_Pos (6UL) /*!< MSPI INTEN: DCMP (Bit 6) */ -#define MSPI_INTEN_DCMP_Msk (0x40UL) /*!< MSPI INTEN: DCMP (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_RXF_Pos (5UL) /*!< MSPI INTEN: RXF (Bit 5) */ -#define MSPI_INTEN_RXF_Msk (0x20UL) /*!< MSPI INTEN: RXF (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_RXO_Pos (4UL) /*!< MSPI INTEN: RXO (Bit 4) */ -#define MSPI_INTEN_RXO_Msk (0x10UL) /*!< MSPI INTEN: RXO (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_RXU_Pos (3UL) /*!< MSPI INTEN: RXU (Bit 3) */ -#define MSPI_INTEN_RXU_Msk (0x8UL) /*!< MSPI INTEN: RXU (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_TXO_Pos (2UL) /*!< MSPI INTEN: TXO (Bit 2) */ -#define MSPI_INTEN_TXO_Msk (0x4UL) /*!< MSPI INTEN: TXO (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_TXE_Pos (1UL) /*!< MSPI INTEN: TXE (Bit 1) */ -#define MSPI_INTEN_TXE_Msk (0x2UL) /*!< MSPI INTEN: TXE (Bitfield-Mask: 0x01) */ -#define MSPI_INTEN_CMDCMP_Pos (0UL) /*!< MSPI INTEN: CMDCMP (Bit 0) */ -#define MSPI_INTEN_CMDCMP_Msk (0x1UL) /*!< MSPI INTEN: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define MSPI_INTSTAT_SCRERR_Pos (12UL) /*!< MSPI INTSTAT: SCRERR (Bit 12) */ -#define MSPI_INTSTAT_SCRERR_Msk (0x1000UL) /*!< MSPI INTSTAT: SCRERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_CQERR_Pos (11UL) /*!< MSPI INTSTAT: CQERR (Bit 11) */ -#define MSPI_INTSTAT_CQERR_Msk (0x800UL) /*!< MSPI INTSTAT: CQERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_CQPAUSED_Pos (10UL) /*!< MSPI INTSTAT: CQPAUSED (Bit 10) */ -#define MSPI_INTSTAT_CQPAUSED_Msk (0x400UL) /*!< MSPI INTSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_CQUPD_Pos (9UL) /*!< MSPI INTSTAT: CQUPD (Bit 9) */ -#define MSPI_INTSTAT_CQUPD_Msk (0x200UL) /*!< MSPI INTSTAT: CQUPD (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_CQCMP_Pos (8UL) /*!< MSPI INTSTAT: CQCMP (Bit 8) */ -#define MSPI_INTSTAT_CQCMP_Msk (0x100UL) /*!< MSPI INTSTAT: CQCMP (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_DERR_Pos (7UL) /*!< MSPI INTSTAT: DERR (Bit 7) */ -#define MSPI_INTSTAT_DERR_Msk (0x80UL) /*!< MSPI INTSTAT: DERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_DCMP_Pos (6UL) /*!< MSPI INTSTAT: DCMP (Bit 6) */ -#define MSPI_INTSTAT_DCMP_Msk (0x40UL) /*!< MSPI INTSTAT: DCMP (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_RXF_Pos (5UL) /*!< MSPI INTSTAT: RXF (Bit 5) */ -#define MSPI_INTSTAT_RXF_Msk (0x20UL) /*!< MSPI INTSTAT: RXF (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_RXO_Pos (4UL) /*!< MSPI INTSTAT: RXO (Bit 4) */ -#define MSPI_INTSTAT_RXO_Msk (0x10UL) /*!< MSPI INTSTAT: RXO (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_RXU_Pos (3UL) /*!< MSPI INTSTAT: RXU (Bit 3) */ -#define MSPI_INTSTAT_RXU_Msk (0x8UL) /*!< MSPI INTSTAT: RXU (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_TXO_Pos (2UL) /*!< MSPI INTSTAT: TXO (Bit 2) */ -#define MSPI_INTSTAT_TXO_Msk (0x4UL) /*!< MSPI INTSTAT: TXO (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_TXE_Pos (1UL) /*!< MSPI INTSTAT: TXE (Bit 1) */ -#define MSPI_INTSTAT_TXE_Msk (0x2UL) /*!< MSPI INTSTAT: TXE (Bitfield-Mask: 0x01) */ -#define MSPI_INTSTAT_CMDCMP_Pos (0UL) /*!< MSPI INTSTAT: CMDCMP (Bit 0) */ -#define MSPI_INTSTAT_CMDCMP_Msk (0x1UL) /*!< MSPI INTSTAT: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define MSPI_INTCLR_SCRERR_Pos (12UL) /*!< MSPI INTCLR: SCRERR (Bit 12) */ -#define MSPI_INTCLR_SCRERR_Msk (0x1000UL) /*!< MSPI INTCLR: SCRERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_CQERR_Pos (11UL) /*!< MSPI INTCLR: CQERR (Bit 11) */ -#define MSPI_INTCLR_CQERR_Msk (0x800UL) /*!< MSPI INTCLR: CQERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_CQPAUSED_Pos (10UL) /*!< MSPI INTCLR: CQPAUSED (Bit 10) */ -#define MSPI_INTCLR_CQPAUSED_Msk (0x400UL) /*!< MSPI INTCLR: CQPAUSED (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_CQUPD_Pos (9UL) /*!< MSPI INTCLR: CQUPD (Bit 9) */ -#define MSPI_INTCLR_CQUPD_Msk (0x200UL) /*!< MSPI INTCLR: CQUPD (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_CQCMP_Pos (8UL) /*!< MSPI INTCLR: CQCMP (Bit 8) */ -#define MSPI_INTCLR_CQCMP_Msk (0x100UL) /*!< MSPI INTCLR: CQCMP (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_DERR_Pos (7UL) /*!< MSPI INTCLR: DERR (Bit 7) */ -#define MSPI_INTCLR_DERR_Msk (0x80UL) /*!< MSPI INTCLR: DERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_DCMP_Pos (6UL) /*!< MSPI INTCLR: DCMP (Bit 6) */ -#define MSPI_INTCLR_DCMP_Msk (0x40UL) /*!< MSPI INTCLR: DCMP (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_RXF_Pos (5UL) /*!< MSPI INTCLR: RXF (Bit 5) */ -#define MSPI_INTCLR_RXF_Msk (0x20UL) /*!< MSPI INTCLR: RXF (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_RXO_Pos (4UL) /*!< MSPI INTCLR: RXO (Bit 4) */ -#define MSPI_INTCLR_RXO_Msk (0x10UL) /*!< MSPI INTCLR: RXO (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_RXU_Pos (3UL) /*!< MSPI INTCLR: RXU (Bit 3) */ -#define MSPI_INTCLR_RXU_Msk (0x8UL) /*!< MSPI INTCLR: RXU (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_TXO_Pos (2UL) /*!< MSPI INTCLR: TXO (Bit 2) */ -#define MSPI_INTCLR_TXO_Msk (0x4UL) /*!< MSPI INTCLR: TXO (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_TXE_Pos (1UL) /*!< MSPI INTCLR: TXE (Bit 1) */ -#define MSPI_INTCLR_TXE_Msk (0x2UL) /*!< MSPI INTCLR: TXE (Bitfield-Mask: 0x01) */ -#define MSPI_INTCLR_CMDCMP_Pos (0UL) /*!< MSPI INTCLR: CMDCMP (Bit 0) */ -#define MSPI_INTCLR_CMDCMP_Msk (0x1UL) /*!< MSPI INTCLR: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define MSPI_INTSET_SCRERR_Pos (12UL) /*!< MSPI INTSET: SCRERR (Bit 12) */ -#define MSPI_INTSET_SCRERR_Msk (0x1000UL) /*!< MSPI INTSET: SCRERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_CQERR_Pos (11UL) /*!< MSPI INTSET: CQERR (Bit 11) */ -#define MSPI_INTSET_CQERR_Msk (0x800UL) /*!< MSPI INTSET: CQERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_CQPAUSED_Pos (10UL) /*!< MSPI INTSET: CQPAUSED (Bit 10) */ -#define MSPI_INTSET_CQPAUSED_Msk (0x400UL) /*!< MSPI INTSET: CQPAUSED (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_CQUPD_Pos (9UL) /*!< MSPI INTSET: CQUPD (Bit 9) */ -#define MSPI_INTSET_CQUPD_Msk (0x200UL) /*!< MSPI INTSET: CQUPD (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_CQCMP_Pos (8UL) /*!< MSPI INTSET: CQCMP (Bit 8) */ -#define MSPI_INTSET_CQCMP_Msk (0x100UL) /*!< MSPI INTSET: CQCMP (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_DERR_Pos (7UL) /*!< MSPI INTSET: DERR (Bit 7) */ -#define MSPI_INTSET_DERR_Msk (0x80UL) /*!< MSPI INTSET: DERR (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_DCMP_Pos (6UL) /*!< MSPI INTSET: DCMP (Bit 6) */ -#define MSPI_INTSET_DCMP_Msk (0x40UL) /*!< MSPI INTSET: DCMP (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_RXF_Pos (5UL) /*!< MSPI INTSET: RXF (Bit 5) */ -#define MSPI_INTSET_RXF_Msk (0x20UL) /*!< MSPI INTSET: RXF (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_RXO_Pos (4UL) /*!< MSPI INTSET: RXO (Bit 4) */ -#define MSPI_INTSET_RXO_Msk (0x10UL) /*!< MSPI INTSET: RXO (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_RXU_Pos (3UL) /*!< MSPI INTSET: RXU (Bit 3) */ -#define MSPI_INTSET_RXU_Msk (0x8UL) /*!< MSPI INTSET: RXU (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_TXO_Pos (2UL) /*!< MSPI INTSET: TXO (Bit 2) */ -#define MSPI_INTSET_TXO_Msk (0x4UL) /*!< MSPI INTSET: TXO (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_TXE_Pos (1UL) /*!< MSPI INTSET: TXE (Bit 1) */ -#define MSPI_INTSET_TXE_Msk (0x2UL) /*!< MSPI INTSET: TXE (Bitfield-Mask: 0x01) */ -#define MSPI_INTSET_CMDCMP_Pos (0UL) /*!< MSPI INTSET: CMDCMP (Bit 0) */ -#define MSPI_INTSET_CMDCMP_Msk (0x1UL) /*!< MSPI INTSET: CMDCMP (Bitfield-Mask: 0x01) */ -/* ======================================================== DMACFG ========================================================= */ -#define MSPI_DMACFG_DMAPWROFF_Pos (18UL) /*!< MSPI DMACFG: DMAPWROFF (Bit 18) */ -#define MSPI_DMACFG_DMAPWROFF_Msk (0x40000UL) /*!< MSPI DMACFG: DMAPWROFF (Bitfield-Mask: 0x01) */ -#define MSPI_DMACFG_DMAPRI_Pos (3UL) /*!< MSPI DMACFG: DMAPRI (Bit 3) */ -#define MSPI_DMACFG_DMAPRI_Msk (0x18UL) /*!< MSPI DMACFG: DMAPRI (Bitfield-Mask: 0x03) */ -#define MSPI_DMACFG_DMADIR_Pos (2UL) /*!< MSPI DMACFG: DMADIR (Bit 2) */ -#define MSPI_DMACFG_DMADIR_Msk (0x4UL) /*!< MSPI DMACFG: DMADIR (Bitfield-Mask: 0x01) */ -#define MSPI_DMACFG_DMAEN_Pos (0UL) /*!< MSPI DMACFG: DMAEN (Bit 0) */ -#define MSPI_DMACFG_DMAEN_Msk (0x3UL) /*!< MSPI DMACFG: DMAEN (Bitfield-Mask: 0x03) */ -/* ======================================================== DMASTAT ======================================================== */ -#define MSPI_DMASTAT_SCRERR_Pos (3UL) /*!< MSPI DMASTAT: SCRERR (Bit 3) */ -#define MSPI_DMASTAT_SCRERR_Msk (0x8UL) /*!< MSPI DMASTAT: SCRERR (Bitfield-Mask: 0x01) */ -#define MSPI_DMASTAT_DMAERR_Pos (2UL) /*!< MSPI DMASTAT: DMAERR (Bit 2) */ -#define MSPI_DMASTAT_DMAERR_Msk (0x4UL) /*!< MSPI DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ -#define MSPI_DMASTAT_DMACPL_Pos (1UL) /*!< MSPI DMASTAT: DMACPL (Bit 1) */ -#define MSPI_DMASTAT_DMACPL_Msk (0x2UL) /*!< MSPI DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ -#define MSPI_DMASTAT_DMATIP_Pos (0UL) /*!< MSPI DMASTAT: DMATIP (Bit 0) */ -#define MSPI_DMASTAT_DMATIP_Msk (0x1UL) /*!< MSPI DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ -/* ====================================================== DMATARGADDR ====================================================== */ -#define MSPI_DMATARGADDR_TARGADDR_Pos (0UL) /*!< MSPI DMATARGADDR: TARGADDR (Bit 0) */ -#define MSPI_DMATARGADDR_TARGADDR_Msk (0xffffffffUL) /*!< MSPI DMATARGADDR: TARGADDR (Bitfield-Mask: 0xffffffff) */ -/* ====================================================== DMADEVADDR ======================================================= */ -#define MSPI_DMADEVADDR_DEVADDR_Pos (0UL) /*!< MSPI DMADEVADDR: DEVADDR (Bit 0) */ -#define MSPI_DMADEVADDR_DEVADDR_Msk (0xffffffffUL) /*!< MSPI DMADEVADDR: DEVADDR (Bitfield-Mask: 0xffffffff) */ -/* ====================================================== DMATOTCOUNT ====================================================== */ -#define MSPI_DMATOTCOUNT_TOTCOUNT_Pos (0UL) /*!< MSPI DMATOTCOUNT: TOTCOUNT (Bit 0) */ -#define MSPI_DMATOTCOUNT_TOTCOUNT_Msk (0xffffUL) /*!< MSPI DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xffff) */ -/* ======================================================= DMABCOUNT ======================================================= */ -#define MSPI_DMABCOUNT_BCOUNT_Pos (0UL) /*!< MSPI DMABCOUNT: BCOUNT (Bit 0) */ -#define MSPI_DMABCOUNT_BCOUNT_Msk (0xffUL) /*!< MSPI DMABCOUNT: BCOUNT (Bitfield-Mask: 0xff) */ -/* ======================================================= DMATHRESH ======================================================= */ -#define MSPI_DMATHRESH_DMATHRESH_Pos (0UL) /*!< MSPI DMATHRESH: DMATHRESH (Bit 0) */ -#define MSPI_DMATHRESH_DMATHRESH_Msk (0xfUL) /*!< MSPI DMATHRESH: DMATHRESH (Bitfield-Mask: 0x0f) */ -/* ========================================================= CQCFG ========================================================= */ -#define MSPI_CQCFG_CQAUTOCLEARMASK_Pos (3UL) /*!< MSPI CQCFG: CQAUTOCLEARMASK (Bit 3) */ -#define MSPI_CQCFG_CQAUTOCLEARMASK_Msk (0x8UL) /*!< MSPI CQCFG: CQAUTOCLEARMASK (Bitfield-Mask: 0x01) */ -#define MSPI_CQCFG_CQPWROFF_Pos (2UL) /*!< MSPI CQCFG: CQPWROFF (Bit 2) */ -#define MSPI_CQCFG_CQPWROFF_Msk (0x4UL) /*!< MSPI CQCFG: CQPWROFF (Bitfield-Mask: 0x01) */ -#define MSPI_CQCFG_CQPRI_Pos (1UL) /*!< MSPI CQCFG: CQPRI (Bit 1) */ -#define MSPI_CQCFG_CQPRI_Msk (0x2UL) /*!< MSPI CQCFG: CQPRI (Bitfield-Mask: 0x01) */ -#define MSPI_CQCFG_CQEN_Pos (0UL) /*!< MSPI CQCFG: CQEN (Bit 0) */ -#define MSPI_CQCFG_CQEN_Msk (0x1UL) /*!< MSPI CQCFG: CQEN (Bitfield-Mask: 0x01) */ -/* ======================================================== CQADDR ========================================================= */ -#define MSPI_CQADDR_CQADDR_Pos (0UL) /*!< MSPI CQADDR: CQADDR (Bit 0) */ -#define MSPI_CQADDR_CQADDR_Msk (0x1fffffffUL) /*!< MSPI CQADDR: CQADDR (Bitfield-Mask: 0x1fffffff) */ -/* ======================================================== CQSTAT ========================================================= */ -#define MSPI_CQSTAT_CQPAUSED_Pos (3UL) /*!< MSPI CQSTAT: CQPAUSED (Bit 3) */ -#define MSPI_CQSTAT_CQPAUSED_Msk (0x8UL) /*!< MSPI CQSTAT: CQPAUSED (Bitfield-Mask: 0x01) */ -#define MSPI_CQSTAT_CQERR_Pos (2UL) /*!< MSPI CQSTAT: CQERR (Bit 2) */ -#define MSPI_CQSTAT_CQERR_Msk (0x4UL) /*!< MSPI CQSTAT: CQERR (Bitfield-Mask: 0x01) */ -#define MSPI_CQSTAT_CQCPL_Pos (1UL) /*!< MSPI CQSTAT: CQCPL (Bit 1) */ -#define MSPI_CQSTAT_CQCPL_Msk (0x2UL) /*!< MSPI CQSTAT: CQCPL (Bitfield-Mask: 0x01) */ -#define MSPI_CQSTAT_CQTIP_Pos (0UL) /*!< MSPI CQSTAT: CQTIP (Bit 0) */ -#define MSPI_CQSTAT_CQTIP_Msk (0x1UL) /*!< MSPI CQSTAT: CQTIP (Bitfield-Mask: 0x01) */ -/* ======================================================== CQFLAGS ======================================================== */ -#define MSPI_CQFLAGS_CQFLAGS_Pos (0UL) /*!< MSPI CQFLAGS: CQFLAGS (Bit 0) */ -#define MSPI_CQFLAGS_CQFLAGS_Msk (0xffffUL) /*!< MSPI CQFLAGS: CQFLAGS (Bitfield-Mask: 0xffff) */ -/* ====================================================== CQSETCLEAR ======================================================= */ -#define MSPI_CQSETCLEAR_CQFCLR_Pos (16UL) /*!< MSPI CQSETCLEAR: CQFCLR (Bit 16) */ -#define MSPI_CQSETCLEAR_CQFCLR_Msk (0xff0000UL) /*!< MSPI CQSETCLEAR: CQFCLR (Bitfield-Mask: 0xff) */ -#define MSPI_CQSETCLEAR_CQFTOGGLE_Pos (8UL) /*!< MSPI CQSETCLEAR: CQFTOGGLE (Bit 8) */ -#define MSPI_CQSETCLEAR_CQFTOGGLE_Msk (0xff00UL) /*!< MSPI CQSETCLEAR: CQFTOGGLE (Bitfield-Mask: 0xff) */ -#define MSPI_CQSETCLEAR_CQFSET_Pos (0UL) /*!< MSPI CQSETCLEAR: CQFSET (Bit 0) */ -#define MSPI_CQSETCLEAR_CQFSET_Msk (0xffUL) /*!< MSPI CQSETCLEAR: CQFSET (Bitfield-Mask: 0xff) */ -/* ======================================================== CQPAUSE ======================================================== */ -#define MSPI_CQPAUSE_CQMASK_Pos (0UL) /*!< MSPI CQPAUSE: CQMASK (Bit 0) */ -#define MSPI_CQPAUSE_CQMASK_Msk (0xffffUL) /*!< MSPI CQPAUSE: CQMASK (Bitfield-Mask: 0xffff) */ -/* ======================================================= CQCURIDX ======================================================== */ -#define MSPI_CQCURIDX_CQCURIDX_Pos (0UL) /*!< MSPI CQCURIDX: CQCURIDX (Bit 0) */ -#define MSPI_CQCURIDX_CQCURIDX_Msk (0xffUL) /*!< MSPI CQCURIDX: CQCURIDX (Bitfield-Mask: 0xff) */ -/* ======================================================= CQENDIDX ======================================================== */ -#define MSPI_CQENDIDX_CQENDIDX_Pos (0UL) /*!< MSPI CQENDIDX: CQENDIDX (Bit 0) */ -#define MSPI_CQENDIDX_CQENDIDX_Msk (0xffUL) /*!< MSPI CQENDIDX: CQENDIDX (Bitfield-Mask: 0xff) */ - - -/* =========================================================================================================================== */ -/* ================ PDM ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= PCFG ========================================================== */ -#define PDM_PCFG_LRSWAP_Pos (31UL) /*!< PDM PCFG: LRSWAP (Bit 31) */ -#define PDM_PCFG_LRSWAP_Msk (0x80000000UL) /*!< PDM PCFG: LRSWAP (Bitfield-Mask: 0x01) */ -#define PDM_PCFG_PGARIGHT_Pos (26UL) /*!< PDM PCFG: PGARIGHT (Bit 26) */ -#define PDM_PCFG_PGARIGHT_Msk (0x7c000000UL) /*!< PDM PCFG: PGARIGHT (Bitfield-Mask: 0x1f) */ -#define PDM_PCFG_PGALEFT_Pos (21UL) /*!< PDM PCFG: PGALEFT (Bit 21) */ -#define PDM_PCFG_PGALEFT_Msk (0x3e00000UL) /*!< PDM PCFG: PGALEFT (Bitfield-Mask: 0x1f) */ -#define PDM_PCFG_MCLKDIV_Pos (17UL) /*!< PDM PCFG: MCLKDIV (Bit 17) */ -#define PDM_PCFG_MCLKDIV_Msk (0x60000UL) /*!< PDM PCFG: MCLKDIV (Bitfield-Mask: 0x03) */ -#define PDM_PCFG_SINCRATE_Pos (10UL) /*!< PDM PCFG: SINCRATE (Bit 10) */ -#define PDM_PCFG_SINCRATE_Msk (0x1fc00UL) /*!< PDM PCFG: SINCRATE (Bitfield-Mask: 0x7f) */ -#define PDM_PCFG_ADCHPD_Pos (9UL) /*!< PDM PCFG: ADCHPD (Bit 9) */ -#define PDM_PCFG_ADCHPD_Msk (0x200UL) /*!< PDM PCFG: ADCHPD (Bitfield-Mask: 0x01) */ -#define PDM_PCFG_HPCUTOFF_Pos (5UL) /*!< PDM PCFG: HPCUTOFF (Bit 5) */ -#define PDM_PCFG_HPCUTOFF_Msk (0x1e0UL) /*!< PDM PCFG: HPCUTOFF (Bitfield-Mask: 0x0f) */ -#define PDM_PCFG_CYCLES_Pos (2UL) /*!< PDM PCFG: CYCLES (Bit 2) */ -#define PDM_PCFG_CYCLES_Msk (0x1cUL) /*!< PDM PCFG: CYCLES (Bitfield-Mask: 0x07) */ -#define PDM_PCFG_SOFTMUTE_Pos (1UL) /*!< PDM PCFG: SOFTMUTE (Bit 1) */ -#define PDM_PCFG_SOFTMUTE_Msk (0x2UL) /*!< PDM PCFG: SOFTMUTE (Bitfield-Mask: 0x01) */ -#define PDM_PCFG_PDMCOREEN_Pos (0UL) /*!< PDM PCFG: PDMCOREEN (Bit 0) */ -#define PDM_PCFG_PDMCOREEN_Msk (0x1UL) /*!< PDM PCFG: PDMCOREEN (Bitfield-Mask: 0x01) */ -/* ========================================================= VCFG ========================================================== */ -#define PDM_VCFG_IOCLKEN_Pos (31UL) /*!< PDM VCFG: IOCLKEN (Bit 31) */ -#define PDM_VCFG_IOCLKEN_Msk (0x80000000UL) /*!< PDM VCFG: IOCLKEN (Bitfield-Mask: 0x01) */ -#define PDM_VCFG_RSTB_Pos (30UL) /*!< PDM VCFG: RSTB (Bit 30) */ -#define PDM_VCFG_RSTB_Msk (0x40000000UL) /*!< PDM VCFG: RSTB (Bitfield-Mask: 0x01) */ -#define PDM_VCFG_PDMCLKSEL_Pos (27UL) /*!< PDM VCFG: PDMCLKSEL (Bit 27) */ -#define PDM_VCFG_PDMCLKSEL_Msk (0x38000000UL) /*!< PDM VCFG: PDMCLKSEL (Bitfield-Mask: 0x07) */ -#define PDM_VCFG_PDMCLKEN_Pos (26UL) /*!< PDM VCFG: PDMCLKEN (Bit 26) */ -#define PDM_VCFG_PDMCLKEN_Msk (0x4000000UL) /*!< PDM VCFG: PDMCLKEN (Bitfield-Mask: 0x01) */ -#define PDM_VCFG_I2SEN_Pos (20UL) /*!< PDM VCFG: I2SEN (Bit 20) */ -#define PDM_VCFG_I2SEN_Msk (0x100000UL) /*!< PDM VCFG: I2SEN (Bitfield-Mask: 0x01) */ -#define PDM_VCFG_BCLKINV_Pos (19UL) /*!< PDM VCFG: BCLKINV (Bit 19) */ -#define PDM_VCFG_BCLKINV_Msk (0x80000UL) /*!< PDM VCFG: BCLKINV (Bitfield-Mask: 0x01) */ -#define PDM_VCFG_DMICKDEL_Pos (17UL) /*!< PDM VCFG: DMICKDEL (Bit 17) */ -#define PDM_VCFG_DMICKDEL_Msk (0x20000UL) /*!< PDM VCFG: DMICKDEL (Bitfield-Mask: 0x01) */ -#define PDM_VCFG_SELAP_Pos (16UL) /*!< PDM VCFG: SELAP (Bit 16) */ -#define PDM_VCFG_SELAP_Msk (0x10000UL) /*!< PDM VCFG: SELAP (Bitfield-Mask: 0x01) */ -#define PDM_VCFG_PCMPACK_Pos (8UL) /*!< PDM VCFG: PCMPACK (Bit 8) */ -#define PDM_VCFG_PCMPACK_Msk (0x100UL) /*!< PDM VCFG: PCMPACK (Bitfield-Mask: 0x01) */ -#define PDM_VCFG_CHSET_Pos (3UL) /*!< PDM VCFG: CHSET (Bit 3) */ -#define PDM_VCFG_CHSET_Msk (0x18UL) /*!< PDM VCFG: CHSET (Bitfield-Mask: 0x03) */ -/* ======================================================= VOICESTAT ======================================================= */ -#define PDM_VOICESTAT_FIFOCNT_Pos (0UL) /*!< PDM VOICESTAT: FIFOCNT (Bit 0) */ -#define PDM_VOICESTAT_FIFOCNT_Msk (0x3fUL) /*!< PDM VOICESTAT: FIFOCNT (Bitfield-Mask: 0x3f) */ -/* ======================================================= FIFOREAD ======================================================== */ -#define PDM_FIFOREAD_FIFOREAD_Pos (0UL) /*!< PDM FIFOREAD: FIFOREAD (Bit 0) */ -#define PDM_FIFOREAD_FIFOREAD_Msk (0xffffffffUL) /*!< PDM FIFOREAD: FIFOREAD (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= FIFOFLUSH ======================================================= */ -#define PDM_FIFOFLUSH_FIFOFLUSH_Pos (0UL) /*!< PDM FIFOFLUSH: FIFOFLUSH (Bit 0) */ -#define PDM_FIFOFLUSH_FIFOFLUSH_Msk (0x1UL) /*!< PDM FIFOFLUSH: FIFOFLUSH (Bitfield-Mask: 0x01) */ -/* ======================================================== FIFOTHR ======================================================== */ -#define PDM_FIFOTHR_FIFOTHR_Pos (0UL) /*!< PDM FIFOTHR: FIFOTHR (Bit 0) */ -#define PDM_FIFOTHR_FIFOTHR_Msk (0x1fUL) /*!< PDM FIFOTHR: FIFOTHR (Bitfield-Mask: 0x1f) */ -/* ========================================================= INTEN ========================================================= */ -#define PDM_INTEN_DERR_Pos (4UL) /*!< PDM INTEN: DERR (Bit 4) */ -#define PDM_INTEN_DERR_Msk (0x10UL) /*!< PDM INTEN: DERR (Bitfield-Mask: 0x01) */ -#define PDM_INTEN_DCMP_Pos (3UL) /*!< PDM INTEN: DCMP (Bit 3) */ -#define PDM_INTEN_DCMP_Msk (0x8UL) /*!< PDM INTEN: DCMP (Bitfield-Mask: 0x01) */ -#define PDM_INTEN_UNDFL_Pos (2UL) /*!< PDM INTEN: UNDFL (Bit 2) */ -#define PDM_INTEN_UNDFL_Msk (0x4UL) /*!< PDM INTEN: UNDFL (Bitfield-Mask: 0x01) */ -#define PDM_INTEN_OVF_Pos (1UL) /*!< PDM INTEN: OVF (Bit 1) */ -#define PDM_INTEN_OVF_Msk (0x2UL) /*!< PDM INTEN: OVF (Bitfield-Mask: 0x01) */ -#define PDM_INTEN_THR_Pos (0UL) /*!< PDM INTEN: THR (Bit 0) */ -#define PDM_INTEN_THR_Msk (0x1UL) /*!< PDM INTEN: THR (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define PDM_INTSTAT_DERR_Pos (4UL) /*!< PDM INTSTAT: DERR (Bit 4) */ -#define PDM_INTSTAT_DERR_Msk (0x10UL) /*!< PDM INTSTAT: DERR (Bitfield-Mask: 0x01) */ -#define PDM_INTSTAT_DCMP_Pos (3UL) /*!< PDM INTSTAT: DCMP (Bit 3) */ -#define PDM_INTSTAT_DCMP_Msk (0x8UL) /*!< PDM INTSTAT: DCMP (Bitfield-Mask: 0x01) */ -#define PDM_INTSTAT_UNDFL_Pos (2UL) /*!< PDM INTSTAT: UNDFL (Bit 2) */ -#define PDM_INTSTAT_UNDFL_Msk (0x4UL) /*!< PDM INTSTAT: UNDFL (Bitfield-Mask: 0x01) */ -#define PDM_INTSTAT_OVF_Pos (1UL) /*!< PDM INTSTAT: OVF (Bit 1) */ -#define PDM_INTSTAT_OVF_Msk (0x2UL) /*!< PDM INTSTAT: OVF (Bitfield-Mask: 0x01) */ -#define PDM_INTSTAT_THR_Pos (0UL) /*!< PDM INTSTAT: THR (Bit 0) */ -#define PDM_INTSTAT_THR_Msk (0x1UL) /*!< PDM INTSTAT: THR (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define PDM_INTCLR_DERR_Pos (4UL) /*!< PDM INTCLR: DERR (Bit 4) */ -#define PDM_INTCLR_DERR_Msk (0x10UL) /*!< PDM INTCLR: DERR (Bitfield-Mask: 0x01) */ -#define PDM_INTCLR_DCMP_Pos (3UL) /*!< PDM INTCLR: DCMP (Bit 3) */ -#define PDM_INTCLR_DCMP_Msk (0x8UL) /*!< PDM INTCLR: DCMP (Bitfield-Mask: 0x01) */ -#define PDM_INTCLR_UNDFL_Pos (2UL) /*!< PDM INTCLR: UNDFL (Bit 2) */ -#define PDM_INTCLR_UNDFL_Msk (0x4UL) /*!< PDM INTCLR: UNDFL (Bitfield-Mask: 0x01) */ -#define PDM_INTCLR_OVF_Pos (1UL) /*!< PDM INTCLR: OVF (Bit 1) */ -#define PDM_INTCLR_OVF_Msk (0x2UL) /*!< PDM INTCLR: OVF (Bitfield-Mask: 0x01) */ -#define PDM_INTCLR_THR_Pos (0UL) /*!< PDM INTCLR: THR (Bit 0) */ -#define PDM_INTCLR_THR_Msk (0x1UL) /*!< PDM INTCLR: THR (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define PDM_INTSET_DERR_Pos (4UL) /*!< PDM INTSET: DERR (Bit 4) */ -#define PDM_INTSET_DERR_Msk (0x10UL) /*!< PDM INTSET: DERR (Bitfield-Mask: 0x01) */ -#define PDM_INTSET_DCMP_Pos (3UL) /*!< PDM INTSET: DCMP (Bit 3) */ -#define PDM_INTSET_DCMP_Msk (0x8UL) /*!< PDM INTSET: DCMP (Bitfield-Mask: 0x01) */ -#define PDM_INTSET_UNDFL_Pos (2UL) /*!< PDM INTSET: UNDFL (Bit 2) */ -#define PDM_INTSET_UNDFL_Msk (0x4UL) /*!< PDM INTSET: UNDFL (Bitfield-Mask: 0x01) */ -#define PDM_INTSET_OVF_Pos (1UL) /*!< PDM INTSET: OVF (Bit 1) */ -#define PDM_INTSET_OVF_Msk (0x2UL) /*!< PDM INTSET: OVF (Bitfield-Mask: 0x01) */ -#define PDM_INTSET_THR_Pos (0UL) /*!< PDM INTSET: THR (Bit 0) */ -#define PDM_INTSET_THR_Msk (0x1UL) /*!< PDM INTSET: THR (Bitfield-Mask: 0x01) */ -/* ======================================================= DMATRIGEN ======================================================= */ -#define PDM_DMATRIGEN_DTHR90_Pos (1UL) /*!< PDM DMATRIGEN: DTHR90 (Bit 1) */ -#define PDM_DMATRIGEN_DTHR90_Msk (0x2UL) /*!< PDM DMATRIGEN: DTHR90 (Bitfield-Mask: 0x01) */ -#define PDM_DMATRIGEN_DTHR_Pos (0UL) /*!< PDM DMATRIGEN: DTHR (Bit 0) */ -#define PDM_DMATRIGEN_DTHR_Msk (0x1UL) /*!< PDM DMATRIGEN: DTHR (Bitfield-Mask: 0x01) */ -/* ====================================================== DMATRIGSTAT ====================================================== */ -#define PDM_DMATRIGSTAT_DTHR90STAT_Pos (1UL) /*!< PDM DMATRIGSTAT: DTHR90STAT (Bit 1) */ -#define PDM_DMATRIGSTAT_DTHR90STAT_Msk (0x2UL) /*!< PDM DMATRIGSTAT: DTHR90STAT (Bitfield-Mask: 0x01) */ -#define PDM_DMATRIGSTAT_DTHRSTAT_Pos (0UL) /*!< PDM DMATRIGSTAT: DTHRSTAT (Bit 0) */ -#define PDM_DMATRIGSTAT_DTHRSTAT_Msk (0x1UL) /*!< PDM DMATRIGSTAT: DTHRSTAT (Bitfield-Mask: 0x01) */ -/* ======================================================== DMACFG ========================================================= */ -#define PDM_DMACFG_DPWROFF_Pos (10UL) /*!< PDM DMACFG: DPWROFF (Bit 10) */ -#define PDM_DMACFG_DPWROFF_Msk (0x400UL) /*!< PDM DMACFG: DPWROFF (Bitfield-Mask: 0x01) */ -#define PDM_DMACFG_DAUTOHIP_Pos (9UL) /*!< PDM DMACFG: DAUTOHIP (Bit 9) */ -#define PDM_DMACFG_DAUTOHIP_Msk (0x200UL) /*!< PDM DMACFG: DAUTOHIP (Bitfield-Mask: 0x01) */ -#define PDM_DMACFG_DMAPRI_Pos (8UL) /*!< PDM DMACFG: DMAPRI (Bit 8) */ -#define PDM_DMACFG_DMAPRI_Msk (0x100UL) /*!< PDM DMACFG: DMAPRI (Bitfield-Mask: 0x01) */ -#define PDM_DMACFG_DMADIR_Pos (2UL) /*!< PDM DMACFG: DMADIR (Bit 2) */ -#define PDM_DMACFG_DMADIR_Msk (0x4UL) /*!< PDM DMACFG: DMADIR (Bitfield-Mask: 0x01) */ -#define PDM_DMACFG_DMAEN_Pos (0UL) /*!< PDM DMACFG: DMAEN (Bit 0) */ -#define PDM_DMACFG_DMAEN_Msk (0x1UL) /*!< PDM DMACFG: DMAEN (Bitfield-Mask: 0x01) */ -/* ====================================================== DMATOTCOUNT ====================================================== */ -#define PDM_DMATOTCOUNT_TOTCOUNT_Pos (0UL) /*!< PDM DMATOTCOUNT: TOTCOUNT (Bit 0) */ -#define PDM_DMATOTCOUNT_TOTCOUNT_Msk (0xfffffUL) /*!< PDM DMATOTCOUNT: TOTCOUNT (Bitfield-Mask: 0xfffff) */ -/* ====================================================== DMATARGADDR ====================================================== */ -#define PDM_DMATARGADDR_UTARGADDR_Pos (20UL) /*!< PDM DMATARGADDR: UTARGADDR (Bit 20) */ -#define PDM_DMATARGADDR_UTARGADDR_Msk (0xfff00000UL) /*!< PDM DMATARGADDR: UTARGADDR (Bitfield-Mask: 0xfff) */ -#define PDM_DMATARGADDR_LTARGADDR_Pos (0UL) /*!< PDM DMATARGADDR: LTARGADDR (Bit 0) */ -#define PDM_DMATARGADDR_LTARGADDR_Msk (0xfffffUL) /*!< PDM DMATARGADDR: LTARGADDR (Bitfield-Mask: 0xfffff) */ -/* ======================================================== DMASTAT ======================================================== */ -#define PDM_DMASTAT_DMAERR_Pos (2UL) /*!< PDM DMASTAT: DMAERR (Bit 2) */ -#define PDM_DMASTAT_DMAERR_Msk (0x4UL) /*!< PDM DMASTAT: DMAERR (Bitfield-Mask: 0x01) */ -#define PDM_DMASTAT_DMACPL_Pos (1UL) /*!< PDM DMASTAT: DMACPL (Bit 1) */ -#define PDM_DMASTAT_DMACPL_Msk (0x2UL) /*!< PDM DMASTAT: DMACPL (Bitfield-Mask: 0x01) */ -#define PDM_DMASTAT_DMATIP_Pos (0UL) /*!< PDM DMASTAT: DMATIP (Bit 0) */ -#define PDM_DMASTAT_DMATIP_Msk (0x1UL) /*!< PDM DMASTAT: DMATIP (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ PWRCTRL ================ */ -/* =========================================================================================================================== */ - -/* ======================================================= SUPPLYSRC ======================================================= */ -#define PWRCTRL_SUPPLYSRC_BLEBUCKEN_Pos (0UL) /*!< PWRCTRL SUPPLYSRC: BLEBUCKEN (Bit 0) */ -#define PWRCTRL_SUPPLYSRC_BLEBUCKEN_Msk (0x1UL) /*!< PWRCTRL SUPPLYSRC: BLEBUCKEN (Bitfield-Mask: 0x01) */ -/* ===================================================== SUPPLYSTATUS ====================================================== */ -#define PWRCTRL_SUPPLYSTATUS_BLEBUCKON_Pos (1UL) /*!< PWRCTRL SUPPLYSTATUS: BLEBUCKON (Bit 1) */ -#define PWRCTRL_SUPPLYSTATUS_BLEBUCKON_Msk (0x2UL) /*!< PWRCTRL SUPPLYSTATUS: BLEBUCKON (Bitfield-Mask: 0x01) */ -#define PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_Pos (0UL) /*!< PWRCTRL SUPPLYSTATUS: SIMOBUCKON (Bit 0) */ -#define PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_Msk (0x1UL) /*!< PWRCTRL SUPPLYSTATUS: SIMOBUCKON (Bitfield-Mask: 0x01) */ -/* ======================================================= DEVPWREN ======================================================== */ -#define PWRCTRL_DEVPWREN_PWRBLEL_Pos (13UL) /*!< PWRCTRL DEVPWREN: PWRBLEL (Bit 13) */ -#define PWRCTRL_DEVPWREN_PWRBLEL_Msk (0x2000UL) /*!< PWRCTRL DEVPWREN: PWRBLEL (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRPDM_Pos (12UL) /*!< PWRCTRL DEVPWREN: PWRPDM (Bit 12) */ -#define PWRCTRL_DEVPWREN_PWRPDM_Msk (0x1000UL) /*!< PWRCTRL DEVPWREN: PWRPDM (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRMSPI_Pos (11UL) /*!< PWRCTRL DEVPWREN: PWRMSPI (Bit 11) */ -#define PWRCTRL_DEVPWREN_PWRMSPI_Msk (0x800UL) /*!< PWRCTRL DEVPWREN: PWRMSPI (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRSCARD_Pos (10UL) /*!< PWRCTRL DEVPWREN: PWRSCARD (Bit 10) */ -#define PWRCTRL_DEVPWREN_PWRSCARD_Msk (0x400UL) /*!< PWRCTRL DEVPWREN: PWRSCARD (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRADC_Pos (9UL) /*!< PWRCTRL DEVPWREN: PWRADC (Bit 9) */ -#define PWRCTRL_DEVPWREN_PWRADC_Msk (0x200UL) /*!< PWRCTRL DEVPWREN: PWRADC (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRUART1_Pos (8UL) /*!< PWRCTRL DEVPWREN: PWRUART1 (Bit 8) */ -#define PWRCTRL_DEVPWREN_PWRUART1_Msk (0x100UL) /*!< PWRCTRL DEVPWREN: PWRUART1 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRUART0_Pos (7UL) /*!< PWRCTRL DEVPWREN: PWRUART0 (Bit 7) */ -#define PWRCTRL_DEVPWREN_PWRUART0_Msk (0x80UL) /*!< PWRCTRL DEVPWREN: PWRUART0 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRIOM5_Pos (6UL) /*!< PWRCTRL DEVPWREN: PWRIOM5 (Bit 6) */ -#define PWRCTRL_DEVPWREN_PWRIOM5_Msk (0x40UL) /*!< PWRCTRL DEVPWREN: PWRIOM5 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRIOM4_Pos (5UL) /*!< PWRCTRL DEVPWREN: PWRIOM4 (Bit 5) */ -#define PWRCTRL_DEVPWREN_PWRIOM4_Msk (0x20UL) /*!< PWRCTRL DEVPWREN: PWRIOM4 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRIOM3_Pos (4UL) /*!< PWRCTRL DEVPWREN: PWRIOM3 (Bit 4) */ -#define PWRCTRL_DEVPWREN_PWRIOM3_Msk (0x10UL) /*!< PWRCTRL DEVPWREN: PWRIOM3 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRIOM2_Pos (3UL) /*!< PWRCTRL DEVPWREN: PWRIOM2 (Bit 3) */ -#define PWRCTRL_DEVPWREN_PWRIOM2_Msk (0x8UL) /*!< PWRCTRL DEVPWREN: PWRIOM2 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRIOM1_Pos (2UL) /*!< PWRCTRL DEVPWREN: PWRIOM1 (Bit 2) */ -#define PWRCTRL_DEVPWREN_PWRIOM1_Msk (0x4UL) /*!< PWRCTRL DEVPWREN: PWRIOM1 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRIOM0_Pos (1UL) /*!< PWRCTRL DEVPWREN: PWRIOM0 (Bit 1) */ -#define PWRCTRL_DEVPWREN_PWRIOM0_Msk (0x2UL) /*!< PWRCTRL DEVPWREN: PWRIOM0 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREN_PWRIOS_Pos (0UL) /*!< PWRCTRL DEVPWREN: PWRIOS (Bit 0) */ -#define PWRCTRL_DEVPWREN_PWRIOS_Msk (0x1UL) /*!< PWRCTRL DEVPWREN: PWRIOS (Bitfield-Mask: 0x01) */ -/* ===================================================== MEMPWDINSLEEP ===================================================== */ -#define PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_Pos (31UL) /*!< PWRCTRL MEMPWDINSLEEP: CACHEPWDSLP (Bit 31) */ -#define PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_Msk (0x80000000UL) /*!< PWRCTRL MEMPWDINSLEEP: CACHEPWDSLP (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_Pos (14UL) /*!< PWRCTRL MEMPWDINSLEEP: FLASH1PWDSLP (Bit 14) */ -#define PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_Msk (0x4000UL) /*!< PWRCTRL MEMPWDINSLEEP: FLASH1PWDSLP (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_Pos (13UL) /*!< PWRCTRL MEMPWDINSLEEP: FLASH0PWDSLP (Bit 13) */ -#define PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_Msk (0x2000UL) /*!< PWRCTRL MEMPWDINSLEEP: FLASH0PWDSLP (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_Pos (3UL) /*!< PWRCTRL MEMPWDINSLEEP: SRAMPWDSLP (Bit 3) */ -#define PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_Msk (0x1ff8UL) /*!< PWRCTRL MEMPWDINSLEEP: SRAMPWDSLP (Bitfield-Mask: 0x3ff) */ -#define PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_Pos (0UL) /*!< PWRCTRL MEMPWDINSLEEP: DTCMPWDSLP (Bit 0) */ -#define PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_Msk (0x7UL) /*!< PWRCTRL MEMPWDINSLEEP: DTCMPWDSLP (Bitfield-Mask: 0x07) */ -/* ======================================================= MEMPWREN ======================================================== */ -#define PWRCTRL_MEMPWREN_CACHEB2_Pos (31UL) /*!< PWRCTRL MEMPWREN: CACHEB2 (Bit 31) */ -#define PWRCTRL_MEMPWREN_CACHEB2_Msk (0x80000000UL) /*!< PWRCTRL MEMPWREN: CACHEB2 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWREN_CACHEB0_Pos (30UL) /*!< PWRCTRL MEMPWREN: CACHEB0 (Bit 30) */ -#define PWRCTRL_MEMPWREN_CACHEB0_Msk (0x40000000UL) /*!< PWRCTRL MEMPWREN: CACHEB0 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWREN_FLASH1_Pos (14UL) /*!< PWRCTRL MEMPWREN: FLASH1 (Bit 14) */ -#define PWRCTRL_MEMPWREN_FLASH1_Msk (0x4000UL) /*!< PWRCTRL MEMPWREN: FLASH1 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWREN_FLASH0_Pos (13UL) /*!< PWRCTRL MEMPWREN: FLASH0 (Bit 13) */ -#define PWRCTRL_MEMPWREN_FLASH0_Msk (0x2000UL) /*!< PWRCTRL MEMPWREN: FLASH0 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWREN_SRAM_Pos (3UL) /*!< PWRCTRL MEMPWREN: SRAM (Bit 3) */ -#define PWRCTRL_MEMPWREN_SRAM_Msk (0x1ff8UL) /*!< PWRCTRL MEMPWREN: SRAM (Bitfield-Mask: 0x3ff) */ -#define PWRCTRL_MEMPWREN_DTCM_Pos (0UL) /*!< PWRCTRL MEMPWREN: DTCM (Bit 0) */ -#define PWRCTRL_MEMPWREN_DTCM_Msk (0x7UL) /*!< PWRCTRL MEMPWREN: DTCM (Bitfield-Mask: 0x07) */ -/* ===================================================== MEMPWRSTATUS ====================================================== */ -#define PWRCTRL_MEMPWRSTATUS_CACHEB2_Pos (16UL) /*!< PWRCTRL MEMPWRSTATUS: CACHEB2 (Bit 16) */ -#define PWRCTRL_MEMPWRSTATUS_CACHEB2_Msk (0x10000UL) /*!< PWRCTRL MEMPWRSTATUS: CACHEB2 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_CACHEB0_Pos (15UL) /*!< PWRCTRL MEMPWRSTATUS: CACHEB0 (Bit 15) */ -#define PWRCTRL_MEMPWRSTATUS_CACHEB0_Msk (0x8000UL) /*!< PWRCTRL MEMPWRSTATUS: CACHEB0 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_FLASH1_Pos (14UL) /*!< PWRCTRL MEMPWRSTATUS: FLASH1 (Bit 14) */ -#define PWRCTRL_MEMPWRSTATUS_FLASH1_Msk (0x4000UL) /*!< PWRCTRL MEMPWRSTATUS: FLASH1 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_FLASH0_Pos (13UL) /*!< PWRCTRL MEMPWRSTATUS: FLASH0 (Bit 13) */ -#define PWRCTRL_MEMPWRSTATUS_FLASH0_Msk (0x2000UL) /*!< PWRCTRL MEMPWRSTATUS: FLASH0 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM9_Pos (12UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM9 (Bit 12) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM9_Msk (0x1000UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM9 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM8_Pos (11UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM8 (Bit 11) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM8_Msk (0x800UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM8 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM7_Pos (10UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM7 (Bit 10) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM7_Msk (0x400UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM7 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM6_Pos (9UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM6 (Bit 9) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM6_Msk (0x200UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM6 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM5_Pos (8UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM5 (Bit 8) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM5_Msk (0x100UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM5 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM4_Pos (7UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM4 (Bit 7) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM4_Msk (0x80UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM4 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM3_Pos (6UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM3 (Bit 6) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM3_Msk (0x40UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM3 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM2_Pos (5UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM2 (Bit 5) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM2_Msk (0x20UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM2 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM1_Pos (4UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM1 (Bit 4) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM1_Msk (0x10UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM1 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM0_Pos (3UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM0 (Bit 3) */ -#define PWRCTRL_MEMPWRSTATUS_SRAM0_Msk (0x8UL) /*!< PWRCTRL MEMPWRSTATUS: SRAM0 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_DTCM1_Pos (2UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM1 (Bit 2) */ -#define PWRCTRL_MEMPWRSTATUS_DTCM1_Msk (0x4UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM1 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_DTCM01_Pos (1UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM01 (Bit 1) */ -#define PWRCTRL_MEMPWRSTATUS_DTCM01_Msk (0x2UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM01 (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWRSTATUS_DTCM00_Pos (0UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM00 (Bit 0) */ -#define PWRCTRL_MEMPWRSTATUS_DTCM00_Msk (0x1UL) /*!< PWRCTRL MEMPWRSTATUS: DTCM00 (Bitfield-Mask: 0x01) */ -/* ===================================================== DEVPWRSTATUS ====================================================== */ -#define PWRCTRL_DEVPWRSTATUS_SYSDEEPSLEEP_Pos (31UL) /*!< PWRCTRL DEVPWRSTATUS: SYSDEEPSLEEP (Bit 31) */ -#define PWRCTRL_DEVPWRSTATUS_SYSDEEPSLEEP_Msk (0x80000000UL) /*!< PWRCTRL DEVPWRSTATUS: SYSDEEPSLEEP (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_COREDEEPSLEEP_Pos (30UL) /*!< PWRCTRL DEVPWRSTATUS: COREDEEPSLEEP (Bit 30) */ -#define PWRCTRL_DEVPWRSTATUS_COREDEEPSLEEP_Msk (0x40000000UL) /*!< PWRCTRL DEVPWRSTATUS: COREDEEPSLEEP (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_CORESLEEP_Pos (29UL) /*!< PWRCTRL DEVPWRSTATUS: CORESLEEP (Bit 29) */ -#define PWRCTRL_DEVPWRSTATUS_CORESLEEP_Msk (0x20000000UL) /*!< PWRCTRL DEVPWRSTATUS: CORESLEEP (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_BLEH_Pos (9UL) /*!< PWRCTRL DEVPWRSTATUS: BLEH (Bit 9) */ -#define PWRCTRL_DEVPWRSTATUS_BLEH_Msk (0x200UL) /*!< PWRCTRL DEVPWRSTATUS: BLEH (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_BLEL_Pos (8UL) /*!< PWRCTRL DEVPWRSTATUS: BLEL (Bit 8) */ -#define PWRCTRL_DEVPWRSTATUS_BLEL_Msk (0x100UL) /*!< PWRCTRL DEVPWRSTATUS: BLEL (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_PWRPDM_Pos (7UL) /*!< PWRCTRL DEVPWRSTATUS: PWRPDM (Bit 7) */ -#define PWRCTRL_DEVPWRSTATUS_PWRPDM_Msk (0x80UL) /*!< PWRCTRL DEVPWRSTATUS: PWRPDM (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_PWRMSPI_Pos (6UL) /*!< PWRCTRL DEVPWRSTATUS: PWRMSPI (Bit 6) */ -#define PWRCTRL_DEVPWRSTATUS_PWRMSPI_Msk (0x40UL) /*!< PWRCTRL DEVPWRSTATUS: PWRMSPI (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_PWRADC_Pos (5UL) /*!< PWRCTRL DEVPWRSTATUS: PWRADC (Bit 5) */ -#define PWRCTRL_DEVPWRSTATUS_PWRADC_Msk (0x20UL) /*!< PWRCTRL DEVPWRSTATUS: PWRADC (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_HCPC_Pos (4UL) /*!< PWRCTRL DEVPWRSTATUS: HCPC (Bit 4) */ -#define PWRCTRL_DEVPWRSTATUS_HCPC_Msk (0x10UL) /*!< PWRCTRL DEVPWRSTATUS: HCPC (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_HCPB_Pos (3UL) /*!< PWRCTRL DEVPWRSTATUS: HCPB (Bit 3) */ -#define PWRCTRL_DEVPWRSTATUS_HCPB_Msk (0x8UL) /*!< PWRCTRL DEVPWRSTATUS: HCPB (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_HCPA_Pos (2UL) /*!< PWRCTRL DEVPWRSTATUS: HCPA (Bit 2) */ -#define PWRCTRL_DEVPWRSTATUS_HCPA_Msk (0x4UL) /*!< PWRCTRL DEVPWRSTATUS: HCPA (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_MCUH_Pos (1UL) /*!< PWRCTRL DEVPWRSTATUS: MCUH (Bit 1) */ -#define PWRCTRL_DEVPWRSTATUS_MCUH_Msk (0x2UL) /*!< PWRCTRL DEVPWRSTATUS: MCUH (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWRSTATUS_MCUL_Pos (0UL) /*!< PWRCTRL DEVPWRSTATUS: MCUL (Bit 0) */ -#define PWRCTRL_DEVPWRSTATUS_MCUL_Msk (0x1UL) /*!< PWRCTRL DEVPWRSTATUS: MCUL (Bitfield-Mask: 0x01) */ -/* ======================================================= SRAMCTRL ======================================================== */ -#define PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_Pos (8UL) /*!< PWRCTRL SRAMCTRL: SRAMLIGHTSLEEP (Bit 8) */ -#define PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_Msk (0xfff00UL) /*!< PWRCTRL SRAMCTRL: SRAMLIGHTSLEEP (Bitfield-Mask: 0xfff) */ -#define PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_Pos (2UL) /*!< PWRCTRL SRAMCTRL: SRAMMASTERCLKGATE (Bit 2) */ -#define PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_Msk (0x4UL) /*!< PWRCTRL SRAMCTRL: SRAMMASTERCLKGATE (Bitfield-Mask: 0x01) */ -#define PWRCTRL_SRAMCTRL_SRAMCLKGATE_Pos (1UL) /*!< PWRCTRL SRAMCTRL: SRAMCLKGATE (Bit 1) */ -#define PWRCTRL_SRAMCTRL_SRAMCLKGATE_Msk (0x2UL) /*!< PWRCTRL SRAMCTRL: SRAMCLKGATE (Bitfield-Mask: 0x01) */ -/* ======================================================= ADCSTATUS ======================================================= */ -#define PWRCTRL_ADCSTATUS_REFBUFPWD_Pos (5UL) /*!< PWRCTRL ADCSTATUS: REFBUFPWD (Bit 5) */ -#define PWRCTRL_ADCSTATUS_REFBUFPWD_Msk (0x20UL) /*!< PWRCTRL ADCSTATUS: REFBUFPWD (Bitfield-Mask: 0x01) */ -#define PWRCTRL_ADCSTATUS_REFKEEPPWD_Pos (4UL) /*!< PWRCTRL ADCSTATUS: REFKEEPPWD (Bit 4) */ -#define PWRCTRL_ADCSTATUS_REFKEEPPWD_Msk (0x10UL) /*!< PWRCTRL ADCSTATUS: REFKEEPPWD (Bitfield-Mask: 0x01) */ -#define PWRCTRL_ADCSTATUS_VBATPWD_Pos (3UL) /*!< PWRCTRL ADCSTATUS: VBATPWD (Bit 3) */ -#define PWRCTRL_ADCSTATUS_VBATPWD_Msk (0x8UL) /*!< PWRCTRL ADCSTATUS: VBATPWD (Bitfield-Mask: 0x01) */ -#define PWRCTRL_ADCSTATUS_VPTATPWD_Pos (2UL) /*!< PWRCTRL ADCSTATUS: VPTATPWD (Bit 2) */ -#define PWRCTRL_ADCSTATUS_VPTATPWD_Msk (0x4UL) /*!< PWRCTRL ADCSTATUS: VPTATPWD (Bitfield-Mask: 0x01) */ -#define PWRCTRL_ADCSTATUS_BGTPWD_Pos (1UL) /*!< PWRCTRL ADCSTATUS: BGTPWD (Bit 1) */ -#define PWRCTRL_ADCSTATUS_BGTPWD_Msk (0x2UL) /*!< PWRCTRL ADCSTATUS: BGTPWD (Bitfield-Mask: 0x01) */ -#define PWRCTRL_ADCSTATUS_ADCPWD_Pos (0UL) /*!< PWRCTRL ADCSTATUS: ADCPWD (Bit 0) */ -#define PWRCTRL_ADCSTATUS_ADCPWD_Msk (0x1UL) /*!< PWRCTRL ADCSTATUS: ADCPWD (Bitfield-Mask: 0x01) */ -/* ========================================================= MISC ========================================================== */ -#define PWRCTRL_MISC_FORCEBLEBUCKACT_Pos (7UL) /*!< PWRCTRL MISC: FORCEBLEBUCKACT (Bit 7) */ -#define PWRCTRL_MISC_FORCEBLEBUCKACT_Msk (0x80UL) /*!< PWRCTRL MISC: FORCEBLEBUCKACT (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MISC_MEMVRLPBLE_Pos (6UL) /*!< PWRCTRL MISC: MEMVRLPBLE (Bit 6) */ -#define PWRCTRL_MISC_MEMVRLPBLE_Msk (0x40UL) /*!< PWRCTRL MISC: MEMVRLPBLE (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MISC_FORCEMEMVRADC_Pos (4UL) /*!< PWRCTRL MISC: FORCEMEMVRADC (Bit 4) */ -#define PWRCTRL_MISC_FORCEMEMVRADC_Msk (0x30UL) /*!< PWRCTRL MISC: FORCEMEMVRADC (Bitfield-Mask: 0x03) */ -#define PWRCTRL_MISC_FORCEMEMVRLPTIMERS_Pos (3UL) /*!< PWRCTRL MISC: FORCEMEMVRLPTIMERS (Bit 3) */ -#define PWRCTRL_MISC_FORCEMEMVRLPTIMERS_Msk (0x8UL) /*!< PWRCTRL MISC: FORCEMEMVRLPTIMERS (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MISC_FORCECOREVRLPTIMERS_Pos (2UL) /*!< PWRCTRL MISC: FORCECOREVRLPTIMERS (Bit 2) */ -#define PWRCTRL_MISC_FORCECOREVRLPTIMERS_Msk (0x4UL) /*!< PWRCTRL MISC: FORCECOREVRLPTIMERS (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MISC_FORCECOREVRLPPDM_Pos (1UL) /*!< PWRCTRL MISC: FORCECOREVRLPPDM (Bit 1) */ -#define PWRCTRL_MISC_FORCECOREVRLPPDM_Msk (0x2UL) /*!< PWRCTRL MISC: FORCECOREVRLPPDM (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MISC_SIMOBUCKEN_Pos (0UL) /*!< PWRCTRL MISC: SIMOBUCKEN (Bit 0) */ -#define PWRCTRL_MISC_SIMOBUCKEN_Msk (0x1UL) /*!< PWRCTRL MISC: SIMOBUCKEN (Bitfield-Mask: 0x01) */ -/* ===================================================== DEVPWREVENTEN ===================================================== */ -#define PWRCTRL_DEVPWREVENTEN_BURSTEVEN_Pos (31UL) /*!< PWRCTRL DEVPWREVENTEN: BURSTEVEN (Bit 31) */ -#define PWRCTRL_DEVPWREVENTEN_BURSTEVEN_Msk (0x80000000UL) /*!< PWRCTRL DEVPWREVENTEN: BURSTEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_Pos (30UL) /*!< PWRCTRL DEVPWREVENTEN: BURSTFEATUREEVEN (Bit 30) */ -#define PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_Msk (0x40000000UL) /*!< PWRCTRL DEVPWREVENTEN: BURSTFEATUREEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_Pos (29UL) /*!< PWRCTRL DEVPWREVENTEN: BLEFEATUREEVEN (Bit 29) */ -#define PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_Msk (0x20000000UL) /*!< PWRCTRL DEVPWREVENTEN: BLEFEATUREEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_BLELEVEN_Pos (8UL) /*!< PWRCTRL DEVPWREVENTEN: BLELEVEN (Bit 8) */ -#define PWRCTRL_DEVPWREVENTEN_BLELEVEN_Msk (0x100UL) /*!< PWRCTRL DEVPWREVENTEN: BLELEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_PDMEVEN_Pos (7UL) /*!< PWRCTRL DEVPWREVENTEN: PDMEVEN (Bit 7) */ -#define PWRCTRL_DEVPWREVENTEN_PDMEVEN_Msk (0x80UL) /*!< PWRCTRL DEVPWREVENTEN: PDMEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_MSPIEVEN_Pos (6UL) /*!< PWRCTRL DEVPWREVENTEN: MSPIEVEN (Bit 6) */ -#define PWRCTRL_DEVPWREVENTEN_MSPIEVEN_Msk (0x40UL) /*!< PWRCTRL DEVPWREVENTEN: MSPIEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_ADCEVEN_Pos (5UL) /*!< PWRCTRL DEVPWREVENTEN: ADCEVEN (Bit 5) */ -#define PWRCTRL_DEVPWREVENTEN_ADCEVEN_Msk (0x20UL) /*!< PWRCTRL DEVPWREVENTEN: ADCEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_HCPCEVEN_Pos (4UL) /*!< PWRCTRL DEVPWREVENTEN: HCPCEVEN (Bit 4) */ -#define PWRCTRL_DEVPWREVENTEN_HCPCEVEN_Msk (0x10UL) /*!< PWRCTRL DEVPWREVENTEN: HCPCEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_HCPBEVEN_Pos (3UL) /*!< PWRCTRL DEVPWREVENTEN: HCPBEVEN (Bit 3) */ -#define PWRCTRL_DEVPWREVENTEN_HCPBEVEN_Msk (0x8UL) /*!< PWRCTRL DEVPWREVENTEN: HCPBEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_HCPAEVEN_Pos (2UL) /*!< PWRCTRL DEVPWREVENTEN: HCPAEVEN (Bit 2) */ -#define PWRCTRL_DEVPWREVENTEN_HCPAEVEN_Msk (0x4UL) /*!< PWRCTRL DEVPWREVENTEN: HCPAEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_MCUHEVEN_Pos (1UL) /*!< PWRCTRL DEVPWREVENTEN: MCUHEVEN (Bit 1) */ -#define PWRCTRL_DEVPWREVENTEN_MCUHEVEN_Msk (0x2UL) /*!< PWRCTRL DEVPWREVENTEN: MCUHEVEN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_DEVPWREVENTEN_MCULEVEN_Pos (0UL) /*!< PWRCTRL DEVPWREVENTEN: MCULEVEN (Bit 0) */ -#define PWRCTRL_DEVPWREVENTEN_MCULEVEN_Msk (0x1UL) /*!< PWRCTRL DEVPWREVENTEN: MCULEVEN (Bitfield-Mask: 0x01) */ -/* ===================================================== MEMPWREVENTEN ===================================================== */ -#define PWRCTRL_MEMPWREVENTEN_CACHEB2EN_Pos (31UL) /*!< PWRCTRL MEMPWREVENTEN: CACHEB2EN (Bit 31) */ -#define PWRCTRL_MEMPWREVENTEN_CACHEB2EN_Msk (0x80000000UL) /*!< PWRCTRL MEMPWREVENTEN: CACHEB2EN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWREVENTEN_CACHEB0EN_Pos (30UL) /*!< PWRCTRL MEMPWREVENTEN: CACHEB0EN (Bit 30) */ -#define PWRCTRL_MEMPWREVENTEN_CACHEB0EN_Msk (0x40000000UL) /*!< PWRCTRL MEMPWREVENTEN: CACHEB0EN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWREVENTEN_FLASH1EN_Pos (14UL) /*!< PWRCTRL MEMPWREVENTEN: FLASH1EN (Bit 14) */ -#define PWRCTRL_MEMPWREVENTEN_FLASH1EN_Msk (0x4000UL) /*!< PWRCTRL MEMPWREVENTEN: FLASH1EN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWREVENTEN_FLASH0EN_Pos (13UL) /*!< PWRCTRL MEMPWREVENTEN: FLASH0EN (Bit 13) */ -#define PWRCTRL_MEMPWREVENTEN_FLASH0EN_Msk (0x2000UL) /*!< PWRCTRL MEMPWREVENTEN: FLASH0EN (Bitfield-Mask: 0x01) */ -#define PWRCTRL_MEMPWREVENTEN_SRAMEN_Pos (3UL) /*!< PWRCTRL MEMPWREVENTEN: SRAMEN (Bit 3) */ -#define PWRCTRL_MEMPWREVENTEN_SRAMEN_Msk (0x1ff8UL) /*!< PWRCTRL MEMPWREVENTEN: SRAMEN (Bitfield-Mask: 0x3ff) */ -#define PWRCTRL_MEMPWREVENTEN_DTCMEN_Pos (0UL) /*!< PWRCTRL MEMPWREVENTEN: DTCMEN (Bit 0) */ -#define PWRCTRL_MEMPWREVENTEN_DTCMEN_Msk (0x7UL) /*!< PWRCTRL MEMPWREVENTEN: DTCMEN (Bitfield-Mask: 0x07) */ - - -/* =========================================================================================================================== */ -/* ================ RSTGEN ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== CFG ========================================================== */ -#define RSTGEN_CFG_WDREN_Pos (1UL) /*!< RSTGEN CFG: WDREN (Bit 1) */ -#define RSTGEN_CFG_WDREN_Msk (0x2UL) /*!< RSTGEN CFG: WDREN (Bitfield-Mask: 0x01) */ -#define RSTGEN_CFG_BODHREN_Pos (0UL) /*!< RSTGEN CFG: BODHREN (Bit 0) */ -#define RSTGEN_CFG_BODHREN_Msk (0x1UL) /*!< RSTGEN CFG: BODHREN (Bitfield-Mask: 0x01) */ -/* ========================================================= SWPOI ========================================================= */ -#define RSTGEN_SWPOI_SWPOIKEY_Pos (0UL) /*!< RSTGEN SWPOI: SWPOIKEY (Bit 0) */ -#define RSTGEN_SWPOI_SWPOIKEY_Msk (0xffUL) /*!< RSTGEN SWPOI: SWPOIKEY (Bitfield-Mask: 0xff) */ -/* ========================================================= SWPOR ========================================================= */ -#define RSTGEN_SWPOR_SWPORKEY_Pos (0UL) /*!< RSTGEN SWPOR: SWPORKEY (Bit 0) */ -#define RSTGEN_SWPOR_SWPORKEY_Msk (0xffUL) /*!< RSTGEN SWPOR: SWPORKEY (Bitfield-Mask: 0xff) */ -/* ======================================================== TPIURST ======================================================== */ -#define RSTGEN_TPIURST_TPIURST_Pos (0UL) /*!< RSTGEN TPIURST: TPIURST (Bit 0) */ -#define RSTGEN_TPIURST_TPIURST_Msk (0x1UL) /*!< RSTGEN TPIURST: TPIURST (Bitfield-Mask: 0x01) */ -/* ========================================================= INTEN ========================================================= */ -#define RSTGEN_INTEN_BODH_Pos (0UL) /*!< RSTGEN INTEN: BODH (Bit 0) */ -#define RSTGEN_INTEN_BODH_Msk (0x1UL) /*!< RSTGEN INTEN: BODH (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define RSTGEN_INTSTAT_BODH_Pos (0UL) /*!< RSTGEN INTSTAT: BODH (Bit 0) */ -#define RSTGEN_INTSTAT_BODH_Msk (0x1UL) /*!< RSTGEN INTSTAT: BODH (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define RSTGEN_INTCLR_BODH_Pos (0UL) /*!< RSTGEN INTCLR: BODH (Bit 0) */ -#define RSTGEN_INTCLR_BODH_Msk (0x1UL) /*!< RSTGEN INTCLR: BODH (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define RSTGEN_INTSET_BODH_Pos (0UL) /*!< RSTGEN INTSET: BODH (Bit 0) */ -#define RSTGEN_INTSET_BODH_Msk (0x1UL) /*!< RSTGEN INTSET: BODH (Bitfield-Mask: 0x01) */ -/* ========================================================= STAT ========================================================== */ -#define RSTGEN_STAT_SBOOT_Pos (31UL) /*!< RSTGEN STAT: SBOOT (Bit 31) */ -#define RSTGEN_STAT_SBOOT_Msk (0x80000000UL) /*!< RSTGEN STAT: SBOOT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_FBOOT_Pos (30UL) /*!< RSTGEN STAT: FBOOT (Bit 30) */ -#define RSTGEN_STAT_FBOOT_Msk (0x40000000UL) /*!< RSTGEN STAT: FBOOT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_BOBSTAT_Pos (10UL) /*!< RSTGEN STAT: BOBSTAT (Bit 10) */ -#define RSTGEN_STAT_BOBSTAT_Msk (0x400UL) /*!< RSTGEN STAT: BOBSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_BOFSTAT_Pos (9UL) /*!< RSTGEN STAT: BOFSTAT (Bit 9) */ -#define RSTGEN_STAT_BOFSTAT_Msk (0x200UL) /*!< RSTGEN STAT: BOFSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_BOCSTAT_Pos (8UL) /*!< RSTGEN STAT: BOCSTAT (Bit 8) */ -#define RSTGEN_STAT_BOCSTAT_Msk (0x100UL) /*!< RSTGEN STAT: BOCSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_BOUSTAT_Pos (7UL) /*!< RSTGEN STAT: BOUSTAT (Bit 7) */ -#define RSTGEN_STAT_BOUSTAT_Msk (0x80UL) /*!< RSTGEN STAT: BOUSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_WDRSTAT_Pos (6UL) /*!< RSTGEN STAT: WDRSTAT (Bit 6) */ -#define RSTGEN_STAT_WDRSTAT_Msk (0x40UL) /*!< RSTGEN STAT: WDRSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_DBGRSTAT_Pos (5UL) /*!< RSTGEN STAT: DBGRSTAT (Bit 5) */ -#define RSTGEN_STAT_DBGRSTAT_Msk (0x20UL) /*!< RSTGEN STAT: DBGRSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_POIRSTAT_Pos (4UL) /*!< RSTGEN STAT: POIRSTAT (Bit 4) */ -#define RSTGEN_STAT_POIRSTAT_Msk (0x10UL) /*!< RSTGEN STAT: POIRSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_SWRSTAT_Pos (3UL) /*!< RSTGEN STAT: SWRSTAT (Bit 3) */ -#define RSTGEN_STAT_SWRSTAT_Msk (0x8UL) /*!< RSTGEN STAT: SWRSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_BORSTAT_Pos (2UL) /*!< RSTGEN STAT: BORSTAT (Bit 2) */ -#define RSTGEN_STAT_BORSTAT_Msk (0x4UL) /*!< RSTGEN STAT: BORSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_PORSTAT_Pos (1UL) /*!< RSTGEN STAT: PORSTAT (Bit 1) */ -#define RSTGEN_STAT_PORSTAT_Msk (0x2UL) /*!< RSTGEN STAT: PORSTAT (Bitfield-Mask: 0x01) */ -#define RSTGEN_STAT_EXRSTAT_Pos (0UL) /*!< RSTGEN STAT: EXRSTAT (Bit 0) */ -#define RSTGEN_STAT_EXRSTAT_Msk (0x1UL) /*!< RSTGEN STAT: EXRSTAT (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ RTC ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== CTRLOW ========================================================= */ -#define RTC_CTRLOW_CTRHR_Pos (24UL) /*!< RTC CTRLOW: CTRHR (Bit 24) */ -#define RTC_CTRLOW_CTRHR_Msk (0x3f000000UL) /*!< RTC CTRLOW: CTRHR (Bitfield-Mask: 0x3f) */ -#define RTC_CTRLOW_CTRMIN_Pos (16UL) /*!< RTC CTRLOW: CTRMIN (Bit 16) */ -#define RTC_CTRLOW_CTRMIN_Msk (0x7f0000UL) /*!< RTC CTRLOW: CTRMIN (Bitfield-Mask: 0x7f) */ -#define RTC_CTRLOW_CTRSEC_Pos (8UL) /*!< RTC CTRLOW: CTRSEC (Bit 8) */ -#define RTC_CTRLOW_CTRSEC_Msk (0x7f00UL) /*!< RTC CTRLOW: CTRSEC (Bitfield-Mask: 0x7f) */ -#define RTC_CTRLOW_CTR100_Pos (0UL) /*!< RTC CTRLOW: CTR100 (Bit 0) */ -#define RTC_CTRLOW_CTR100_Msk (0xffUL) /*!< RTC CTRLOW: CTR100 (Bitfield-Mask: 0xff) */ -/* ========================================================= CTRUP ========================================================= */ -#define RTC_CTRUP_CTERR_Pos (31UL) /*!< RTC CTRUP: CTERR (Bit 31) */ -#define RTC_CTRUP_CTERR_Msk (0x80000000UL) /*!< RTC CTRUP: CTERR (Bitfield-Mask: 0x01) */ -#define RTC_CTRUP_CEB_Pos (28UL) /*!< RTC CTRUP: CEB (Bit 28) */ -#define RTC_CTRUP_CEB_Msk (0x10000000UL) /*!< RTC CTRUP: CEB (Bitfield-Mask: 0x01) */ -#define RTC_CTRUP_CB_Pos (27UL) /*!< RTC CTRUP: CB (Bit 27) */ -#define RTC_CTRUP_CB_Msk (0x8000000UL) /*!< RTC CTRUP: CB (Bitfield-Mask: 0x01) */ -#define RTC_CTRUP_CTRWKDY_Pos (24UL) /*!< RTC CTRUP: CTRWKDY (Bit 24) */ -#define RTC_CTRUP_CTRWKDY_Msk (0x7000000UL) /*!< RTC CTRUP: CTRWKDY (Bitfield-Mask: 0x07) */ -#define RTC_CTRUP_CTRYR_Pos (16UL) /*!< RTC CTRUP: CTRYR (Bit 16) */ -#define RTC_CTRUP_CTRYR_Msk (0xff0000UL) /*!< RTC CTRUP: CTRYR (Bitfield-Mask: 0xff) */ -#define RTC_CTRUP_CTRMO_Pos (8UL) /*!< RTC CTRUP: CTRMO (Bit 8) */ -#define RTC_CTRUP_CTRMO_Msk (0x1f00UL) /*!< RTC CTRUP: CTRMO (Bitfield-Mask: 0x1f) */ -#define RTC_CTRUP_CTRDATE_Pos (0UL) /*!< RTC CTRUP: CTRDATE (Bit 0) */ -#define RTC_CTRUP_CTRDATE_Msk (0x3fUL) /*!< RTC CTRUP: CTRDATE (Bitfield-Mask: 0x3f) */ -/* ======================================================== ALMLOW ========================================================= */ -#define RTC_ALMLOW_ALMHR_Pos (24UL) /*!< RTC ALMLOW: ALMHR (Bit 24) */ -#define RTC_ALMLOW_ALMHR_Msk (0x3f000000UL) /*!< RTC ALMLOW: ALMHR (Bitfield-Mask: 0x3f) */ -#define RTC_ALMLOW_ALMMIN_Pos (16UL) /*!< RTC ALMLOW: ALMMIN (Bit 16) */ -#define RTC_ALMLOW_ALMMIN_Msk (0x7f0000UL) /*!< RTC ALMLOW: ALMMIN (Bitfield-Mask: 0x7f) */ -#define RTC_ALMLOW_ALMSEC_Pos (8UL) /*!< RTC ALMLOW: ALMSEC (Bit 8) */ -#define RTC_ALMLOW_ALMSEC_Msk (0x7f00UL) /*!< RTC ALMLOW: ALMSEC (Bitfield-Mask: 0x7f) */ -#define RTC_ALMLOW_ALM100_Pos (0UL) /*!< RTC ALMLOW: ALM100 (Bit 0) */ -#define RTC_ALMLOW_ALM100_Msk (0xffUL) /*!< RTC ALMLOW: ALM100 (Bitfield-Mask: 0xff) */ -/* ========================================================= ALMUP ========================================================= */ -#define RTC_ALMUP_ALMWKDY_Pos (16UL) /*!< RTC ALMUP: ALMWKDY (Bit 16) */ -#define RTC_ALMUP_ALMWKDY_Msk (0x70000UL) /*!< RTC ALMUP: ALMWKDY (Bitfield-Mask: 0x07) */ -#define RTC_ALMUP_ALMMO_Pos (8UL) /*!< RTC ALMUP: ALMMO (Bit 8) */ -#define RTC_ALMUP_ALMMO_Msk (0x1f00UL) /*!< RTC ALMUP: ALMMO (Bitfield-Mask: 0x1f) */ -#define RTC_ALMUP_ALMDATE_Pos (0UL) /*!< RTC ALMUP: ALMDATE (Bit 0) */ -#define RTC_ALMUP_ALMDATE_Msk (0x3fUL) /*!< RTC ALMUP: ALMDATE (Bitfield-Mask: 0x3f) */ -/* ======================================================== RTCCTL ========================================================= */ -#define RTC_RTCCTL_HR1224_Pos (5UL) /*!< RTC RTCCTL: HR1224 (Bit 5) */ -#define RTC_RTCCTL_HR1224_Msk (0x20UL) /*!< RTC RTCCTL: HR1224 (Bitfield-Mask: 0x01) */ -#define RTC_RTCCTL_RSTOP_Pos (4UL) /*!< RTC RTCCTL: RSTOP (Bit 4) */ -#define RTC_RTCCTL_RSTOP_Msk (0x10UL) /*!< RTC RTCCTL: RSTOP (Bitfield-Mask: 0x01) */ -#define RTC_RTCCTL_RPT_Pos (1UL) /*!< RTC RTCCTL: RPT (Bit 1) */ -#define RTC_RTCCTL_RPT_Msk (0xeUL) /*!< RTC RTCCTL: RPT (Bitfield-Mask: 0x07) */ -#define RTC_RTCCTL_WRTC_Pos (0UL) /*!< RTC RTCCTL: WRTC (Bit 0) */ -#define RTC_RTCCTL_WRTC_Msk (0x1UL) /*!< RTC RTCCTL: WRTC (Bitfield-Mask: 0x01) */ -/* ========================================================= INTEN ========================================================= */ -#define RTC_INTEN_ALM_Pos (0UL) /*!< RTC INTEN: ALM (Bit 0) */ -#define RTC_INTEN_ALM_Msk (0x1UL) /*!< RTC INTEN: ALM (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define RTC_INTSTAT_ALM_Pos (0UL) /*!< RTC INTSTAT: ALM (Bit 0) */ -#define RTC_INTSTAT_ALM_Msk (0x1UL) /*!< RTC INTSTAT: ALM (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define RTC_INTCLR_ALM_Pos (0UL) /*!< RTC INTCLR: ALM (Bit 0) */ -#define RTC_INTCLR_ALM_Msk (0x1UL) /*!< RTC INTCLR: ALM (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define RTC_INTSET_ALM_Pos (0UL) /*!< RTC INTSET: ALM (Bit 0) */ -#define RTC_INTSET_ALM_Msk (0x1UL) /*!< RTC INTSET: ALM (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ SCARD ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== SR =========================================================== */ -#define SCARD_SR_FHF_Pos (6UL) /*!< SCARD SR: FHF (Bit 6) */ -#define SCARD_SR_FHF_Msk (0x40UL) /*!< SCARD SR: FHF (Bitfield-Mask: 0x01) */ -#define SCARD_SR_FT2REND_Pos (5UL) /*!< SCARD SR: FT2REND (Bit 5) */ -#define SCARD_SR_FT2REND_Msk (0x20UL) /*!< SCARD SR: FT2REND (Bitfield-Mask: 0x01) */ -#define SCARD_SR_PE_Pos (4UL) /*!< SCARD SR: PE (Bit 4) */ -#define SCARD_SR_PE_Msk (0x10UL) /*!< SCARD SR: PE (Bitfield-Mask: 0x01) */ -#define SCARD_SR_OVR_Pos (3UL) /*!< SCARD SR: OVR (Bit 3) */ -#define SCARD_SR_OVR_Msk (0x8UL) /*!< SCARD SR: OVR (Bitfield-Mask: 0x01) */ -#define SCARD_SR_FER_Pos (2UL) /*!< SCARD SR: FER (Bit 2) */ -#define SCARD_SR_FER_Msk (0x4UL) /*!< SCARD SR: FER (Bitfield-Mask: 0x01) */ -#define SCARD_SR_TBERBF_Pos (1UL) /*!< SCARD SR: TBERBF (Bit 1) */ -#define SCARD_SR_TBERBF_Msk (0x2UL) /*!< SCARD SR: TBERBF (Bitfield-Mask: 0x01) */ -#define SCARD_SR_FNE_Pos (0UL) /*!< SCARD SR: FNE (Bit 0) */ -#define SCARD_SR_FNE_Msk (0x1UL) /*!< SCARD SR: FNE (Bitfield-Mask: 0x01) */ -/* ========================================================== DR =========================================================== */ -#define SCARD_DR_DR_Pos (0UL) /*!< SCARD DR: DR (Bit 0) */ -#define SCARD_DR_DR_Msk (0xffUL) /*!< SCARD DR: DR (Bitfield-Mask: 0xff) */ -/* ========================================================== SR1 ========================================================== */ -#define SCARD_SR1_IDLE_Pos (3UL) /*!< SCARD SR1: IDLE (Bit 3) */ -#define SCARD_SR1_IDLE_Msk (0x8UL) /*!< SCARD SR1: IDLE (Bitfield-Mask: 0x01) */ -#define SCARD_SR1_SYNCEND_Pos (2UL) /*!< SCARD SR1: SYNCEND (Bit 2) */ -#define SCARD_SR1_SYNCEND_Msk (0x4UL) /*!< SCARD SR1: SYNCEND (Bitfield-Mask: 0x01) */ -#define SCARD_SR1_PRL_Pos (1UL) /*!< SCARD SR1: PRL (Bit 1) */ -#define SCARD_SR1_PRL_Msk (0x2UL) /*!< SCARD SR1: PRL (Bitfield-Mask: 0x01) */ -#define SCARD_SR1_ECNTOVER_Pos (0UL) /*!< SCARD SR1: ECNTOVER (Bit 0) */ -#define SCARD_SR1_ECNTOVER_Msk (0x1UL) /*!< SCARD SR1: ECNTOVER (Bitfield-Mask: 0x01) */ -/* ====================================================== RETXCNTRMI ======================================================= */ -#define SCARD_RETXCNTRMI_RETXCNTRMI_Pos (0UL) /*!< SCARD RETXCNTRMI: RETXCNTRMI (Bit 0) */ -#define SCARD_RETXCNTRMI_RETXCNTRMI_Msk (0xfUL) /*!< SCARD RETXCNTRMI: RETXCNTRMI (Bitfield-Mask: 0x0f) */ -/* ======================================================== CLKCTRL ======================================================== */ -#define SCARD_CLKCTRL_APBCLKEN_Pos (1UL) /*!< SCARD CLKCTRL: APBCLKEN (Bit 1) */ -#define SCARD_CLKCTRL_APBCLKEN_Msk (0x2UL) /*!< SCARD CLKCTRL: APBCLKEN (Bitfield-Mask: 0x01) */ -#define SCARD_CLKCTRL_CLKEN_Pos (0UL) /*!< SCARD CLKCTRL: CLKEN (Bit 0) */ -#define SCARD_CLKCTRL_CLKEN_Msk (0x1UL) /*!< SCARD CLKCTRL: CLKEN (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ SECURITY ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= CTRL ========================================================== */ -#define SECURITY_CTRL_CRCERROR_Pos (31UL) /*!< SECURITY CTRL: CRCERROR (Bit 31) */ -#define SECURITY_CTRL_CRCERROR_Msk (0x80000000UL) /*!< SECURITY CTRL: CRCERROR (Bitfield-Mask: 0x01) */ -#define SECURITY_CTRL_FUNCTION_Pos (4UL) /*!< SECURITY CTRL: FUNCTION (Bit 4) */ -#define SECURITY_CTRL_FUNCTION_Msk (0xf0UL) /*!< SECURITY CTRL: FUNCTION (Bitfield-Mask: 0x0f) */ -#define SECURITY_CTRL_ENABLE_Pos (0UL) /*!< SECURITY CTRL: ENABLE (Bit 0) */ -#define SECURITY_CTRL_ENABLE_Msk (0x1UL) /*!< SECURITY CTRL: ENABLE (Bitfield-Mask: 0x01) */ -/* ======================================================== SRCADDR ======================================================== */ -#define SECURITY_SRCADDR_ADDR_Pos (0UL) /*!< SECURITY SRCADDR: ADDR (Bit 0) */ -#define SECURITY_SRCADDR_ADDR_Msk (0xffffffffUL) /*!< SECURITY SRCADDR: ADDR (Bitfield-Mask: 0xffffffff) */ -/* ========================================================== LEN ========================================================== */ -#define SECURITY_LEN_LEN_Pos (2UL) /*!< SECURITY LEN: LEN (Bit 2) */ -#define SECURITY_LEN_LEN_Msk (0xffffcUL) /*!< SECURITY LEN: LEN (Bitfield-Mask: 0x3ffff) */ -/* ======================================================== RESULT ========================================================= */ -#define SECURITY_RESULT_CRC_Pos (0UL) /*!< SECURITY RESULT: CRC (Bit 0) */ -#define SECURITY_RESULT_CRC_Msk (0xffffffffUL) /*!< SECURITY RESULT: CRC (Bitfield-Mask: 0xffffffff) */ -/* ======================================================= LOCKCTRL ======================================================== */ -#define SECURITY_LOCKCTRL_SELECT_Pos (0UL) /*!< SECURITY LOCKCTRL: SELECT (Bit 0) */ -#define SECURITY_LOCKCTRL_SELECT_Msk (0xffUL) /*!< SECURITY LOCKCTRL: SELECT (Bitfield-Mask: 0xff) */ -/* ======================================================= LOCKSTAT ======================================================== */ -#define SECURITY_LOCKSTAT_STATUS_Pos (0UL) /*!< SECURITY LOCKSTAT: STATUS (Bit 0) */ -#define SECURITY_LOCKSTAT_STATUS_Msk (0xffffffffUL) /*!< SECURITY LOCKSTAT: STATUS (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= KEY0 ========================================================== */ -#define SECURITY_KEY0_KEY0_Pos (0UL) /*!< SECURITY KEY0: KEY0 (Bit 0) */ -#define SECURITY_KEY0_KEY0_Msk (0xffffffffUL) /*!< SECURITY KEY0: KEY0 (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= KEY1 ========================================================== */ -#define SECURITY_KEY1_KEY1_Pos (0UL) /*!< SECURITY KEY1: KEY1 (Bit 0) */ -#define SECURITY_KEY1_KEY1_Msk (0xffffffffUL) /*!< SECURITY KEY1: KEY1 (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= KEY2 ========================================================== */ -#define SECURITY_KEY2_KEY2_Pos (0UL) /*!< SECURITY KEY2: KEY2 (Bit 0) */ -#define SECURITY_KEY2_KEY2_Msk (0xffffffffUL) /*!< SECURITY KEY2: KEY2 (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= KEY3 ========================================================== */ -#define SECURITY_KEY3_KEY3_Pos (0UL) /*!< SECURITY KEY3: KEY3 (Bit 0) */ -#define SECURITY_KEY3_KEY3_Msk (0xffffffffUL) /*!< SECURITY KEY3: KEY3 (Bitfield-Mask: 0xffffffff) */ - - -/* =========================================================================================================================== */ -/* ================ UART0 ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== DR =========================================================== */ -#define UART0_DR_OEDATA_Pos (11UL) /*!< UART0 DR: OEDATA (Bit 11) */ -#define UART0_DR_OEDATA_Msk (0x800UL) /*!< UART0 DR: OEDATA (Bitfield-Mask: 0x01) */ -#define UART0_DR_BEDATA_Pos (10UL) /*!< UART0 DR: BEDATA (Bit 10) */ -#define UART0_DR_BEDATA_Msk (0x400UL) /*!< UART0 DR: BEDATA (Bitfield-Mask: 0x01) */ -#define UART0_DR_PEDATA_Pos (9UL) /*!< UART0 DR: PEDATA (Bit 9) */ -#define UART0_DR_PEDATA_Msk (0x200UL) /*!< UART0 DR: PEDATA (Bitfield-Mask: 0x01) */ -#define UART0_DR_FEDATA_Pos (8UL) /*!< UART0 DR: FEDATA (Bit 8) */ -#define UART0_DR_FEDATA_Msk (0x100UL) /*!< UART0 DR: FEDATA (Bitfield-Mask: 0x01) */ -#define UART0_DR_DATA_Pos (0UL) /*!< UART0 DR: DATA (Bit 0) */ -#define UART0_DR_DATA_Msk (0xffUL) /*!< UART0 DR: DATA (Bitfield-Mask: 0xff) */ -/* ========================================================== RSR ========================================================== */ -#define UART0_RSR_OESTAT_Pos (3UL) /*!< UART0 RSR: OESTAT (Bit 3) */ -#define UART0_RSR_OESTAT_Msk (0x8UL) /*!< UART0 RSR: OESTAT (Bitfield-Mask: 0x01) */ -#define UART0_RSR_BESTAT_Pos (2UL) /*!< UART0 RSR: BESTAT (Bit 2) */ -#define UART0_RSR_BESTAT_Msk (0x4UL) /*!< UART0 RSR: BESTAT (Bitfield-Mask: 0x01) */ -#define UART0_RSR_PESTAT_Pos (1UL) /*!< UART0 RSR: PESTAT (Bit 1) */ -#define UART0_RSR_PESTAT_Msk (0x2UL) /*!< UART0 RSR: PESTAT (Bitfield-Mask: 0x01) */ -#define UART0_RSR_FESTAT_Pos (0UL) /*!< UART0 RSR: FESTAT (Bit 0) */ -#define UART0_RSR_FESTAT_Msk (0x1UL) /*!< UART0 RSR: FESTAT (Bitfield-Mask: 0x01) */ -/* ========================================================== FR =========================================================== */ -#define UART0_FR_TXBUSY_Pos (8UL) /*!< UART0 FR: TXBUSY (Bit 8) */ -#define UART0_FR_TXBUSY_Msk (0x100UL) /*!< UART0 FR: TXBUSY (Bitfield-Mask: 0x01) */ -#define UART0_FR_TXFE_Pos (7UL) /*!< UART0 FR: TXFE (Bit 7) */ -#define UART0_FR_TXFE_Msk (0x80UL) /*!< UART0 FR: TXFE (Bitfield-Mask: 0x01) */ -#define UART0_FR_RXFF_Pos (6UL) /*!< UART0 FR: RXFF (Bit 6) */ -#define UART0_FR_RXFF_Msk (0x40UL) /*!< UART0 FR: RXFF (Bitfield-Mask: 0x01) */ -#define UART0_FR_TXFF_Pos (5UL) /*!< UART0 FR: TXFF (Bit 5) */ -#define UART0_FR_TXFF_Msk (0x20UL) /*!< UART0 FR: TXFF (Bitfield-Mask: 0x01) */ -#define UART0_FR_RXFE_Pos (4UL) /*!< UART0 FR: RXFE (Bit 4) */ -#define UART0_FR_RXFE_Msk (0x10UL) /*!< UART0 FR: RXFE (Bitfield-Mask: 0x01) */ -#define UART0_FR_BUSY_Pos (3UL) /*!< UART0 FR: BUSY (Bit 3) */ -#define UART0_FR_BUSY_Msk (0x8UL) /*!< UART0 FR: BUSY (Bitfield-Mask: 0x01) */ -#define UART0_FR_DCD_Pos (2UL) /*!< UART0 FR: DCD (Bit 2) */ -#define UART0_FR_DCD_Msk (0x4UL) /*!< UART0 FR: DCD (Bitfield-Mask: 0x01) */ -#define UART0_FR_DSR_Pos (1UL) /*!< UART0 FR: DSR (Bit 1) */ -#define UART0_FR_DSR_Msk (0x2UL) /*!< UART0 FR: DSR (Bitfield-Mask: 0x01) */ -#define UART0_FR_CTS_Pos (0UL) /*!< UART0 FR: CTS (Bit 0) */ -#define UART0_FR_CTS_Msk (0x1UL) /*!< UART0 FR: CTS (Bitfield-Mask: 0x01) */ -/* ========================================================= ILPR ========================================================== */ -#define UART0_ILPR_ILPDVSR_Pos (0UL) /*!< UART0 ILPR: ILPDVSR (Bit 0) */ -#define UART0_ILPR_ILPDVSR_Msk (0xffUL) /*!< UART0 ILPR: ILPDVSR (Bitfield-Mask: 0xff) */ -/* ========================================================= IBRD ========================================================== */ -#define UART0_IBRD_DIVINT_Pos (0UL) /*!< UART0 IBRD: DIVINT (Bit 0) */ -#define UART0_IBRD_DIVINT_Msk (0xffffUL) /*!< UART0 IBRD: DIVINT (Bitfield-Mask: 0xffff) */ -/* ========================================================= FBRD ========================================================== */ -#define UART0_FBRD_DIVFRAC_Pos (0UL) /*!< UART0 FBRD: DIVFRAC (Bit 0) */ -#define UART0_FBRD_DIVFRAC_Msk (0x3fUL) /*!< UART0 FBRD: DIVFRAC (Bitfield-Mask: 0x3f) */ -/* ========================================================= LCRH ========================================================== */ -#define UART0_LCRH_SPS_Pos (7UL) /*!< UART0 LCRH: SPS (Bit 7) */ -#define UART0_LCRH_SPS_Msk (0x80UL) /*!< UART0 LCRH: SPS (Bitfield-Mask: 0x01) */ -#define UART0_LCRH_WLEN_Pos (5UL) /*!< UART0 LCRH: WLEN (Bit 5) */ -#define UART0_LCRH_WLEN_Msk (0x60UL) /*!< UART0 LCRH: WLEN (Bitfield-Mask: 0x03) */ -#define UART0_LCRH_FEN_Pos (4UL) /*!< UART0 LCRH: FEN (Bit 4) */ -#define UART0_LCRH_FEN_Msk (0x10UL) /*!< UART0 LCRH: FEN (Bitfield-Mask: 0x01) */ -#define UART0_LCRH_STP2_Pos (3UL) /*!< UART0 LCRH: STP2 (Bit 3) */ -#define UART0_LCRH_STP2_Msk (0x8UL) /*!< UART0 LCRH: STP2 (Bitfield-Mask: 0x01) */ -#define UART0_LCRH_EPS_Pos (2UL) /*!< UART0 LCRH: EPS (Bit 2) */ -#define UART0_LCRH_EPS_Msk (0x4UL) /*!< UART0 LCRH: EPS (Bitfield-Mask: 0x01) */ -#define UART0_LCRH_PEN_Pos (1UL) /*!< UART0 LCRH: PEN (Bit 1) */ -#define UART0_LCRH_PEN_Msk (0x2UL) /*!< UART0 LCRH: PEN (Bitfield-Mask: 0x01) */ -#define UART0_LCRH_BRK_Pos (0UL) /*!< UART0 LCRH: BRK (Bit 0) */ -#define UART0_LCRH_BRK_Msk (0x1UL) /*!< UART0 LCRH: BRK (Bitfield-Mask: 0x01) */ -/* ========================================================== CR =========================================================== */ -#define UART0_CR_CTSEN_Pos (15UL) /*!< UART0 CR: CTSEN (Bit 15) */ -#define UART0_CR_CTSEN_Msk (0x8000UL) /*!< UART0 CR: CTSEN (Bitfield-Mask: 0x01) */ -#define UART0_CR_RTSEN_Pos (14UL) /*!< UART0 CR: RTSEN (Bit 14) */ -#define UART0_CR_RTSEN_Msk (0x4000UL) /*!< UART0 CR: RTSEN (Bitfield-Mask: 0x01) */ -#define UART0_CR_OUT2_Pos (13UL) /*!< UART0 CR: OUT2 (Bit 13) */ -#define UART0_CR_OUT2_Msk (0x2000UL) /*!< UART0 CR: OUT2 (Bitfield-Mask: 0x01) */ -#define UART0_CR_OUT1_Pos (12UL) /*!< UART0 CR: OUT1 (Bit 12) */ -#define UART0_CR_OUT1_Msk (0x1000UL) /*!< UART0 CR: OUT1 (Bitfield-Mask: 0x01) */ -#define UART0_CR_RTS_Pos (11UL) /*!< UART0 CR: RTS (Bit 11) */ -#define UART0_CR_RTS_Msk (0x800UL) /*!< UART0 CR: RTS (Bitfield-Mask: 0x01) */ -#define UART0_CR_DTR_Pos (10UL) /*!< UART0 CR: DTR (Bit 10) */ -#define UART0_CR_DTR_Msk (0x400UL) /*!< UART0 CR: DTR (Bitfield-Mask: 0x01) */ -#define UART0_CR_RXE_Pos (9UL) /*!< UART0 CR: RXE (Bit 9) */ -#define UART0_CR_RXE_Msk (0x200UL) /*!< UART0 CR: RXE (Bitfield-Mask: 0x01) */ -#define UART0_CR_TXE_Pos (8UL) /*!< UART0 CR: TXE (Bit 8) */ -#define UART0_CR_TXE_Msk (0x100UL) /*!< UART0 CR: TXE (Bitfield-Mask: 0x01) */ -#define UART0_CR_LBE_Pos (7UL) /*!< UART0 CR: LBE (Bit 7) */ -#define UART0_CR_LBE_Msk (0x80UL) /*!< UART0 CR: LBE (Bitfield-Mask: 0x01) */ -#define UART0_CR_CLKSEL_Pos (4UL) /*!< UART0 CR: CLKSEL (Bit 4) */ -#define UART0_CR_CLKSEL_Msk (0x70UL) /*!< UART0 CR: CLKSEL (Bitfield-Mask: 0x07) */ -#define UART0_CR_CLKEN_Pos (3UL) /*!< UART0 CR: CLKEN (Bit 3) */ -#define UART0_CR_CLKEN_Msk (0x8UL) /*!< UART0 CR: CLKEN (Bitfield-Mask: 0x01) */ -#define UART0_CR_SIRLP_Pos (2UL) /*!< UART0 CR: SIRLP (Bit 2) */ -#define UART0_CR_SIRLP_Msk (0x4UL) /*!< UART0 CR: SIRLP (Bitfield-Mask: 0x01) */ -#define UART0_CR_SIREN_Pos (1UL) /*!< UART0 CR: SIREN (Bit 1) */ -#define UART0_CR_SIREN_Msk (0x2UL) /*!< UART0 CR: SIREN (Bitfield-Mask: 0x01) */ -#define UART0_CR_UARTEN_Pos (0UL) /*!< UART0 CR: UARTEN (Bit 0) */ -#define UART0_CR_UARTEN_Msk (0x1UL) /*!< UART0 CR: UARTEN (Bitfield-Mask: 0x01) */ -/* ========================================================= IFLS ========================================================== */ -#define UART0_IFLS_RXIFLSEL_Pos (3UL) /*!< UART0 IFLS: RXIFLSEL (Bit 3) */ -#define UART0_IFLS_RXIFLSEL_Msk (0x38UL) /*!< UART0 IFLS: RXIFLSEL (Bitfield-Mask: 0x07) */ -#define UART0_IFLS_TXIFLSEL_Pos (0UL) /*!< UART0 IFLS: TXIFLSEL (Bit 0) */ -#define UART0_IFLS_TXIFLSEL_Msk (0x7UL) /*!< UART0 IFLS: TXIFLSEL (Bitfield-Mask: 0x07) */ -/* ========================================================== IER ========================================================== */ -#define UART0_IER_OEIM_Pos (10UL) /*!< UART0 IER: OEIM (Bit 10) */ -#define UART0_IER_OEIM_Msk (0x400UL) /*!< UART0 IER: OEIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_BEIM_Pos (9UL) /*!< UART0 IER: BEIM (Bit 9) */ -#define UART0_IER_BEIM_Msk (0x200UL) /*!< UART0 IER: BEIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_PEIM_Pos (8UL) /*!< UART0 IER: PEIM (Bit 8) */ -#define UART0_IER_PEIM_Msk (0x100UL) /*!< UART0 IER: PEIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_FEIM_Pos (7UL) /*!< UART0 IER: FEIM (Bit 7) */ -#define UART0_IER_FEIM_Msk (0x80UL) /*!< UART0 IER: FEIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_RTIM_Pos (6UL) /*!< UART0 IER: RTIM (Bit 6) */ -#define UART0_IER_RTIM_Msk (0x40UL) /*!< UART0 IER: RTIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_TXIM_Pos (5UL) /*!< UART0 IER: TXIM (Bit 5) */ -#define UART0_IER_TXIM_Msk (0x20UL) /*!< UART0 IER: TXIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_RXIM_Pos (4UL) /*!< UART0 IER: RXIM (Bit 4) */ -#define UART0_IER_RXIM_Msk (0x10UL) /*!< UART0 IER: RXIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_DSRMIM_Pos (3UL) /*!< UART0 IER: DSRMIM (Bit 3) */ -#define UART0_IER_DSRMIM_Msk (0x8UL) /*!< UART0 IER: DSRMIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_DCDMIM_Pos (2UL) /*!< UART0 IER: DCDMIM (Bit 2) */ -#define UART0_IER_DCDMIM_Msk (0x4UL) /*!< UART0 IER: DCDMIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_CTSMIM_Pos (1UL) /*!< UART0 IER: CTSMIM (Bit 1) */ -#define UART0_IER_CTSMIM_Msk (0x2UL) /*!< UART0 IER: CTSMIM (Bitfield-Mask: 0x01) */ -#define UART0_IER_TXCMPMIM_Pos (0UL) /*!< UART0 IER: TXCMPMIM (Bit 0) */ -#define UART0_IER_TXCMPMIM_Msk (0x1UL) /*!< UART0 IER: TXCMPMIM (Bitfield-Mask: 0x01) */ -/* ========================================================== IES ========================================================== */ -#define UART0_IES_OERIS_Pos (10UL) /*!< UART0 IES: OERIS (Bit 10) */ -#define UART0_IES_OERIS_Msk (0x400UL) /*!< UART0 IES: OERIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_BERIS_Pos (9UL) /*!< UART0 IES: BERIS (Bit 9) */ -#define UART0_IES_BERIS_Msk (0x200UL) /*!< UART0 IES: BERIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_PERIS_Pos (8UL) /*!< UART0 IES: PERIS (Bit 8) */ -#define UART0_IES_PERIS_Msk (0x100UL) /*!< UART0 IES: PERIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_FERIS_Pos (7UL) /*!< UART0 IES: FERIS (Bit 7) */ -#define UART0_IES_FERIS_Msk (0x80UL) /*!< UART0 IES: FERIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_RTRIS_Pos (6UL) /*!< UART0 IES: RTRIS (Bit 6) */ -#define UART0_IES_RTRIS_Msk (0x40UL) /*!< UART0 IES: RTRIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_TXRIS_Pos (5UL) /*!< UART0 IES: TXRIS (Bit 5) */ -#define UART0_IES_TXRIS_Msk (0x20UL) /*!< UART0 IES: TXRIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_RXRIS_Pos (4UL) /*!< UART0 IES: RXRIS (Bit 4) */ -#define UART0_IES_RXRIS_Msk (0x10UL) /*!< UART0 IES: RXRIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_DSRMRIS_Pos (3UL) /*!< UART0 IES: DSRMRIS (Bit 3) */ -#define UART0_IES_DSRMRIS_Msk (0x8UL) /*!< UART0 IES: DSRMRIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_DCDMRIS_Pos (2UL) /*!< UART0 IES: DCDMRIS (Bit 2) */ -#define UART0_IES_DCDMRIS_Msk (0x4UL) /*!< UART0 IES: DCDMRIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_CTSMRIS_Pos (1UL) /*!< UART0 IES: CTSMRIS (Bit 1) */ -#define UART0_IES_CTSMRIS_Msk (0x2UL) /*!< UART0 IES: CTSMRIS (Bitfield-Mask: 0x01) */ -#define UART0_IES_TXCMPMRIS_Pos (0UL) /*!< UART0 IES: TXCMPMRIS (Bit 0) */ -#define UART0_IES_TXCMPMRIS_Msk (0x1UL) /*!< UART0 IES: TXCMPMRIS (Bitfield-Mask: 0x01) */ -/* ========================================================== MIS ========================================================== */ -#define UART0_MIS_OEMIS_Pos (10UL) /*!< UART0 MIS: OEMIS (Bit 10) */ -#define UART0_MIS_OEMIS_Msk (0x400UL) /*!< UART0 MIS: OEMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_BEMIS_Pos (9UL) /*!< UART0 MIS: BEMIS (Bit 9) */ -#define UART0_MIS_BEMIS_Msk (0x200UL) /*!< UART0 MIS: BEMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_PEMIS_Pos (8UL) /*!< UART0 MIS: PEMIS (Bit 8) */ -#define UART0_MIS_PEMIS_Msk (0x100UL) /*!< UART0 MIS: PEMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_FEMIS_Pos (7UL) /*!< UART0 MIS: FEMIS (Bit 7) */ -#define UART0_MIS_FEMIS_Msk (0x80UL) /*!< UART0 MIS: FEMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_RTMIS_Pos (6UL) /*!< UART0 MIS: RTMIS (Bit 6) */ -#define UART0_MIS_RTMIS_Msk (0x40UL) /*!< UART0 MIS: RTMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_TXMIS_Pos (5UL) /*!< UART0 MIS: TXMIS (Bit 5) */ -#define UART0_MIS_TXMIS_Msk (0x20UL) /*!< UART0 MIS: TXMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_RXMIS_Pos (4UL) /*!< UART0 MIS: RXMIS (Bit 4) */ -#define UART0_MIS_RXMIS_Msk (0x10UL) /*!< UART0 MIS: RXMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_DSRMMIS_Pos (3UL) /*!< UART0 MIS: DSRMMIS (Bit 3) */ -#define UART0_MIS_DSRMMIS_Msk (0x8UL) /*!< UART0 MIS: DSRMMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_DCDMMIS_Pos (2UL) /*!< UART0 MIS: DCDMMIS (Bit 2) */ -#define UART0_MIS_DCDMMIS_Msk (0x4UL) /*!< UART0 MIS: DCDMMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_CTSMMIS_Pos (1UL) /*!< UART0 MIS: CTSMMIS (Bit 1) */ -#define UART0_MIS_CTSMMIS_Msk (0x2UL) /*!< UART0 MIS: CTSMMIS (Bitfield-Mask: 0x01) */ -#define UART0_MIS_TXCMPMMIS_Pos (0UL) /*!< UART0 MIS: TXCMPMMIS (Bit 0) */ -#define UART0_MIS_TXCMPMMIS_Msk (0x1UL) /*!< UART0 MIS: TXCMPMMIS (Bitfield-Mask: 0x01) */ -/* ========================================================== IEC ========================================================== */ -#define UART0_IEC_OEIC_Pos (10UL) /*!< UART0 IEC: OEIC (Bit 10) */ -#define UART0_IEC_OEIC_Msk (0x400UL) /*!< UART0 IEC: OEIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_BEIC_Pos (9UL) /*!< UART0 IEC: BEIC (Bit 9) */ -#define UART0_IEC_BEIC_Msk (0x200UL) /*!< UART0 IEC: BEIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_PEIC_Pos (8UL) /*!< UART0 IEC: PEIC (Bit 8) */ -#define UART0_IEC_PEIC_Msk (0x100UL) /*!< UART0 IEC: PEIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_FEIC_Pos (7UL) /*!< UART0 IEC: FEIC (Bit 7) */ -#define UART0_IEC_FEIC_Msk (0x80UL) /*!< UART0 IEC: FEIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_RTIC_Pos (6UL) /*!< UART0 IEC: RTIC (Bit 6) */ -#define UART0_IEC_RTIC_Msk (0x40UL) /*!< UART0 IEC: RTIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_TXIC_Pos (5UL) /*!< UART0 IEC: TXIC (Bit 5) */ -#define UART0_IEC_TXIC_Msk (0x20UL) /*!< UART0 IEC: TXIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_RXIC_Pos (4UL) /*!< UART0 IEC: RXIC (Bit 4) */ -#define UART0_IEC_RXIC_Msk (0x10UL) /*!< UART0 IEC: RXIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_DSRMIC_Pos (3UL) /*!< UART0 IEC: DSRMIC (Bit 3) */ -#define UART0_IEC_DSRMIC_Msk (0x8UL) /*!< UART0 IEC: DSRMIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_DCDMIC_Pos (2UL) /*!< UART0 IEC: DCDMIC (Bit 2) */ -#define UART0_IEC_DCDMIC_Msk (0x4UL) /*!< UART0 IEC: DCDMIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_CTSMIC_Pos (1UL) /*!< UART0 IEC: CTSMIC (Bit 1) */ -#define UART0_IEC_CTSMIC_Msk (0x2UL) /*!< UART0 IEC: CTSMIC (Bitfield-Mask: 0x01) */ -#define UART0_IEC_TXCMPMIC_Pos (0UL) /*!< UART0 IEC: TXCMPMIC (Bit 0) */ -#define UART0_IEC_TXCMPMIC_Msk (0x1UL) /*!< UART0 IEC: TXCMPMIC (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ VCOMP ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== CFG ========================================================== */ -#define VCOMP_CFG_LVLSEL_Pos (16UL) /*!< VCOMP CFG: LVLSEL (Bit 16) */ -#define VCOMP_CFG_LVLSEL_Msk (0xf0000UL) /*!< VCOMP CFG: LVLSEL (Bitfield-Mask: 0x0f) */ -#define VCOMP_CFG_NSEL_Pos (8UL) /*!< VCOMP CFG: NSEL (Bit 8) */ -#define VCOMP_CFG_NSEL_Msk (0x300UL) /*!< VCOMP CFG: NSEL (Bitfield-Mask: 0x03) */ -#define VCOMP_CFG_PSEL_Pos (0UL) /*!< VCOMP CFG: PSEL (Bit 0) */ -#define VCOMP_CFG_PSEL_Msk (0x3UL) /*!< VCOMP CFG: PSEL (Bitfield-Mask: 0x03) */ -/* ========================================================= STAT ========================================================== */ -#define VCOMP_STAT_PWDSTAT_Pos (1UL) /*!< VCOMP STAT: PWDSTAT (Bit 1) */ -#define VCOMP_STAT_PWDSTAT_Msk (0x2UL) /*!< VCOMP STAT: PWDSTAT (Bitfield-Mask: 0x01) */ -#define VCOMP_STAT_CMPOUT_Pos (0UL) /*!< VCOMP STAT: CMPOUT (Bit 0) */ -#define VCOMP_STAT_CMPOUT_Msk (0x1UL) /*!< VCOMP STAT: CMPOUT (Bitfield-Mask: 0x01) */ -/* ======================================================== PWDKEY ========================================================= */ -#define VCOMP_PWDKEY_PWDKEY_Pos (0UL) /*!< VCOMP PWDKEY: PWDKEY (Bit 0) */ -#define VCOMP_PWDKEY_PWDKEY_Msk (0xffffffffUL) /*!< VCOMP PWDKEY: PWDKEY (Bitfield-Mask: 0xffffffff) */ -/* ========================================================= INTEN ========================================================= */ -#define VCOMP_INTEN_OUTHI_Pos (1UL) /*!< VCOMP INTEN: OUTHI (Bit 1) */ -#define VCOMP_INTEN_OUTHI_Msk (0x2UL) /*!< VCOMP INTEN: OUTHI (Bitfield-Mask: 0x01) */ -#define VCOMP_INTEN_OUTLOW_Pos (0UL) /*!< VCOMP INTEN: OUTLOW (Bit 0) */ -#define VCOMP_INTEN_OUTLOW_Msk (0x1UL) /*!< VCOMP INTEN: OUTLOW (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define VCOMP_INTSTAT_OUTHI_Pos (1UL) /*!< VCOMP INTSTAT: OUTHI (Bit 1) */ -#define VCOMP_INTSTAT_OUTHI_Msk (0x2UL) /*!< VCOMP INTSTAT: OUTHI (Bitfield-Mask: 0x01) */ -#define VCOMP_INTSTAT_OUTLOW_Pos (0UL) /*!< VCOMP INTSTAT: OUTLOW (Bit 0) */ -#define VCOMP_INTSTAT_OUTLOW_Msk (0x1UL) /*!< VCOMP INTSTAT: OUTLOW (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define VCOMP_INTCLR_OUTHI_Pos (1UL) /*!< VCOMP INTCLR: OUTHI (Bit 1) */ -#define VCOMP_INTCLR_OUTHI_Msk (0x2UL) /*!< VCOMP INTCLR: OUTHI (Bitfield-Mask: 0x01) */ -#define VCOMP_INTCLR_OUTLOW_Pos (0UL) /*!< VCOMP INTCLR: OUTLOW (Bit 0) */ -#define VCOMP_INTCLR_OUTLOW_Msk (0x1UL) /*!< VCOMP INTCLR: OUTLOW (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define VCOMP_INTSET_OUTHI_Pos (1UL) /*!< VCOMP INTSET: OUTHI (Bit 1) */ -#define VCOMP_INTSET_OUTHI_Msk (0x2UL) /*!< VCOMP INTSET: OUTHI (Bitfield-Mask: 0x01) */ -#define VCOMP_INTSET_OUTLOW_Pos (0UL) /*!< VCOMP INTSET: OUTLOW (Bit 0) */ -#define VCOMP_INTSET_OUTLOW_Msk (0x1UL) /*!< VCOMP INTSET: OUTLOW (Bitfield-Mask: 0x01) */ - - -/* =========================================================================================================================== */ -/* ================ WDT ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== CFG ========================================================== */ -#define WDT_CFG_CLKSEL_Pos (24UL) /*!< WDT CFG: CLKSEL (Bit 24) */ -#define WDT_CFG_CLKSEL_Msk (0x7000000UL) /*!< WDT CFG: CLKSEL (Bitfield-Mask: 0x07) */ -#define WDT_CFG_INTVAL_Pos (16UL) /*!< WDT CFG: INTVAL (Bit 16) */ -#define WDT_CFG_INTVAL_Msk (0xff0000UL) /*!< WDT CFG: INTVAL (Bitfield-Mask: 0xff) */ -#define WDT_CFG_RESVAL_Pos (8UL) /*!< WDT CFG: RESVAL (Bit 8) */ -#define WDT_CFG_RESVAL_Msk (0xff00UL) /*!< WDT CFG: RESVAL (Bitfield-Mask: 0xff) */ -#define WDT_CFG_RESEN_Pos (2UL) /*!< WDT CFG: RESEN (Bit 2) */ -#define WDT_CFG_RESEN_Msk (0x4UL) /*!< WDT CFG: RESEN (Bitfield-Mask: 0x01) */ -#define WDT_CFG_INTEN_Pos (1UL) /*!< WDT CFG: INTEN (Bit 1) */ -#define WDT_CFG_INTEN_Msk (0x2UL) /*!< WDT CFG: INTEN (Bitfield-Mask: 0x01) */ -#define WDT_CFG_WDTEN_Pos (0UL) /*!< WDT CFG: WDTEN (Bit 0) */ -#define WDT_CFG_WDTEN_Msk (0x1UL) /*!< WDT CFG: WDTEN (Bitfield-Mask: 0x01) */ -/* ========================================================= RSTRT ========================================================= */ -#define WDT_RSTRT_RSTRT_Pos (0UL) /*!< WDT RSTRT: RSTRT (Bit 0) */ -#define WDT_RSTRT_RSTRT_Msk (0xffUL) /*!< WDT RSTRT: RSTRT (Bitfield-Mask: 0xff) */ -/* ========================================================= LOCK ========================================================== */ -#define WDT_LOCK_LOCK_Pos (0UL) /*!< WDT LOCK: LOCK (Bit 0) */ -#define WDT_LOCK_LOCK_Msk (0xffUL) /*!< WDT LOCK: LOCK (Bitfield-Mask: 0xff) */ -/* ========================================================= COUNT ========================================================= */ -#define WDT_COUNT_COUNT_Pos (0UL) /*!< WDT COUNT: COUNT (Bit 0) */ -#define WDT_COUNT_COUNT_Msk (0xffUL) /*!< WDT COUNT: COUNT (Bitfield-Mask: 0xff) */ -/* ========================================================= INTEN ========================================================= */ -#define WDT_INTEN_WDTINT_Pos (0UL) /*!< WDT INTEN: WDTINT (Bit 0) */ -#define WDT_INTEN_WDTINT_Msk (0x1UL) /*!< WDT INTEN: WDTINT (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSTAT ======================================================== */ -#define WDT_INTSTAT_WDTINT_Pos (0UL) /*!< WDT INTSTAT: WDTINT (Bit 0) */ -#define WDT_INTSTAT_WDTINT_Msk (0x1UL) /*!< WDT INTSTAT: WDTINT (Bitfield-Mask: 0x01) */ -/* ======================================================== INTCLR ========================================================= */ -#define WDT_INTCLR_WDTINT_Pos (0UL) /*!< WDT INTCLR: WDTINT (Bit 0) */ -#define WDT_INTCLR_WDTINT_Msk (0x1UL) /*!< WDT INTCLR: WDTINT (Bitfield-Mask: 0x01) */ -/* ======================================================== INTSET ========================================================= */ -#define WDT_INTSET_WDTINT_Pos (0UL) /*!< WDT INTSET: WDTINT (Bit 0) */ -#define WDT_INTSET_WDTINT_Msk (0x1UL) /*!< WDT INTSET: WDTINT (Bitfield-Mask: 0x01) */ - -/** @} */ /* End of group PosMask_peripherals */ - - -/* =========================================================================================================================== */ -/* ================ Enumerated Values Peripheral Section ================ */ -/* =========================================================================================================================== */ - - -/** @addtogroup EnumValue_peripherals - * @{ - */ - - - -/* =========================================================================================================================== */ -/* ================ ADC ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== CFG ========================================================== */ -/* ================================================ ADC CFG CLKSEL [24..25] ================================================ */ -typedef enum { /*!< ADC_CFG_CLKSEL */ - ADC_CFG_CLKSEL_OFF = 0, /*!< OFF : Off mode. The HFRC or HFRC_DIV2 clock must be selected - for the ADC to function. The ADC controller - automatically shuts off the clock in it's - low power modes. When setting ADCEN to '0', - the CLKSEL should remain set to one of the - two clock selects for proper power down - sequencing. value. */ - ADC_CFG_CLKSEL_HFRC = 1, /*!< HFRC : HFRC Core Clock divided by (CORESEL+1) value. */ - ADC_CFG_CLKSEL_HFRC_DIV2 = 2, /*!< HFRC_DIV2 : HFRC Core Clock / 2 further divided by (CORESEL+1) - value. */ -} ADC_CFG_CLKSEL_Enum; - -/* =============================================== ADC CFG TRIGPOL [19..19] ================================================ */ -typedef enum { /*!< ADC_CFG_TRIGPOL */ - ADC_CFG_TRIGPOL_RISING_EDGE = 0, /*!< RISING_EDGE : Trigger on rising edge. value. */ - ADC_CFG_TRIGPOL_FALLING_EDGE = 1, /*!< FALLING_EDGE : Trigger on falling edge. value. */ -} ADC_CFG_TRIGPOL_Enum; - -/* =============================================== ADC CFG TRIGSEL [16..18] ================================================ */ -typedef enum { /*!< ADC_CFG_TRIGSEL */ - ADC_CFG_TRIGSEL_EXT0 = 0, /*!< EXT0 : Off chip External Trigger0 (ADC_ET0) value. */ - ADC_CFG_TRIGSEL_EXT1 = 1, /*!< EXT1 : Off chip External Trigger1 (ADC_ET1) value. */ - ADC_CFG_TRIGSEL_EXT2 = 2, /*!< EXT2 : Off chip External Trigger2 (ADC_ET2) value. */ - ADC_CFG_TRIGSEL_EXT3 = 3, /*!< EXT3 : Off chip External Trigger3 (ADC_ET3) value. */ - ADC_CFG_TRIGSEL_VCOMP = 4, /*!< VCOMP : Voltage Comparator Output value. */ - ADC_CFG_TRIGSEL_SWT = 7, /*!< SWT : Software Trigger value. */ -} ADC_CFG_TRIGSEL_Enum; - -/* ============================================== ADC CFG DFIFORDEN [12..12] =============================================== */ -typedef enum { /*!< ADC_CFG_DFIFORDEN */ - ADC_CFG_DFIFORDEN_DIS = 0, /*!< DIS : Destructive Reads are prevented. Reads to the FIFOPR register - will not POP an entry off the FIFO. value. */ - ADC_CFG_DFIFORDEN_EN = 1, /*!< EN : Reads to the FIFOPR registger will automatically pop an - entry off the FIFO. value. */ -} ADC_CFG_DFIFORDEN_Enum; - -/* ================================================= ADC CFG REFSEL [8..9] ================================================= */ -typedef enum { /*!< ADC_CFG_REFSEL */ - ADC_CFG_REFSEL_INT2P0 = 0, /*!< INT2P0 : Internal 2.0V Bandgap Reference Voltage value. */ - ADC_CFG_REFSEL_INT1P5 = 1, /*!< INT1P5 : Internal 1.5V Bandgap Reference Voltage value. */ - ADC_CFG_REFSEL_EXT2P0 = 2, /*!< EXT2P0 : Off Chip 2.0V Reference value. */ - ADC_CFG_REFSEL_EXT1P5 = 3, /*!< EXT1P5 : Off Chip 1.5V Reference value. */ -} ADC_CFG_REFSEL_Enum; - -/* ================================================= ADC CFG CKMODE [4..4] ================================================= */ -typedef enum { /*!< ADC_CFG_CKMODE */ - ADC_CFG_CKMODE_LPCKMODE = 0, /*!< LPCKMODE : Disable the clock between scans for LPMODE0. Set - LPCKMODE to 0x1 while configuring the ADC. value. */ - ADC_CFG_CKMODE_LLCKMODE = 1, /*!< LLCKMODE : Low Latency Clock Mode. When set, HFRC and the adc_clk - will remain on while in functioning in LPMODE0. value. */ -} ADC_CFG_CKMODE_Enum; - -/* ================================================= ADC CFG LPMODE [3..3] ================================================= */ -typedef enum { /*!< ADC_CFG_LPMODE */ - ADC_CFG_LPMODE_MODE0 = 0, /*!< MODE0 : Low Power Mode 0. Leaves the ADC fully powered between - scans with minimum latency between a trigger event and - sample data collection. value. */ - ADC_CFG_LPMODE_MODE1 = 1, /*!< MODE1 : Low Power Mode 1. Powers down all circuity and clocks - associated with the ADC until the next trigger event. Between - scans, the reference buffer requires up to 50us of delay - from a scan trigger event before the conversion will commence - while operating in this mode. value. */ -} ADC_CFG_LPMODE_Enum; - -/* ================================================= ADC CFG RPTEN [2..2] ================================================== */ -typedef enum { /*!< ADC_CFG_RPTEN */ - ADC_CFG_RPTEN_SINGLE_SCAN = 0, /*!< SINGLE_SCAN : In Single Scan Mode, the ADC will complete a single - scan upon each trigger event. value. */ - ADC_CFG_RPTEN_REPEATING_SCAN = 1, /*!< REPEATING_SCAN : In Repeating Scan Mode, the ADC will complete - it's first scan upon the initial trigger event and all - subsequent scans will occur at regular intervals defined - by the configuration programmed for the CTTMRA3 internal - timer until the timer is disabled or the ADC is disabled. - When disabling the ADC (setting ADCEN to '0'), the RPTEN - bit should be cleared. value. */ -} ADC_CFG_RPTEN_Enum; - -/* ================================================= ADC CFG ADCEN [0..0] ================================================== */ -typedef enum { /*!< ADC_CFG_ADCEN */ - ADC_CFG_ADCEN_DIS = 0, /*!< DIS : Disable the ADC module. value. */ - ADC_CFG_ADCEN_EN = 1, /*!< EN : Enable the ADC module. value. */ -} ADC_CFG_ADCEN_Enum; - -/* ========================================================= STAT ========================================================== */ -/* ================================================ ADC STAT PWDSTAT [0..0] ================================================ */ -typedef enum { /*!< ADC_STAT_PWDSTAT */ - ADC_STAT_PWDSTAT_ON = 0, /*!< ON : Powered on. value. */ - ADC_STAT_PWDSTAT_POWERED_DOWN = 1, /*!< POWERED_DOWN : ADC Low Power Mode 1. value. */ -} ADC_STAT_PWDSTAT_Enum; - -/* ========================================================== SWT ========================================================== */ -/* ================================================== ADC SWT SWT [0..7] =================================================== */ -typedef enum { /*!< ADC_SWT_SWT */ - ADC_SWT_SWT_GEN_SW_TRIGGER = 55, /*!< GEN_SW_TRIGGER : Writing this value generates a software trigger. - value. */ -} ADC_SWT_SWT_Enum; - -/* ======================================================== SL0CFG ========================================================= */ -/* ============================================== ADC SL0CFG ADSEL0 [24..26] =============================================== */ -typedef enum { /*!< ADC_SL0CFG_ADSEL0 */ - ADC_SL0CFG_ADSEL0_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide - module for this slot. value. */ - ADC_SL0CFG_ADSEL0_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL0CFG_ADSEL0_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL0CFG_ADSEL0_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL0CFG_ADSEL0_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL0CFG_ADSEL0_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL0CFG_ADSEL0_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL0CFG_ADSEL0_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate - divide module for this slot. value. */ -} ADC_SL0CFG_ADSEL0_Enum; - -/* ============================================== ADC SL0CFG PRMODE0 [16..17] ============================================== */ -typedef enum { /*!< ADC_SL0CFG_PRMODE0 */ - ADC_SL0CFG_PRMODE0_P14B = 0, /*!< P14B : 14-bit precision mode value. */ - ADC_SL0CFG_PRMODE0_P12B = 1, /*!< P12B : 12-bit precision mode value. */ - ADC_SL0CFG_PRMODE0_P10B = 2, /*!< P10B : 10-bit precision mode value. */ - ADC_SL0CFG_PRMODE0_P8B = 3, /*!< P8B : 8-bit precision mode value. */ -} ADC_SL0CFG_PRMODE0_Enum; - -/* =============================================== ADC SL0CFG CHSEL0 [8..11] =============================================== */ -typedef enum { /*!< ADC_SL0CFG_CHSEL0 */ - ADC_SL0CFG_CHSEL0_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ - ADC_SL0CFG_CHSEL0_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ - ADC_SL0CFG_CHSEL0_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ - ADC_SL0CFG_CHSEL0_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ - ADC_SL0CFG_CHSEL0_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ - ADC_SL0CFG_CHSEL0_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ - ADC_SL0CFG_CHSEL0_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ - ADC_SL0CFG_CHSEL0_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ - ADC_SL0CFG_CHSEL0_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ - ADC_SL0CFG_CHSEL0_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ - ADC_SL0CFG_CHSEL0_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and - pad13(P). value. */ - ADC_SL0CFG_CHSEL0_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and - pad14(P). value. */ - ADC_SL0CFG_CHSEL0_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ - ADC_SL0CFG_CHSEL0_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ - ADC_SL0CFG_CHSEL0_VSS = 14, /*!< VSS : Input VSS value. */ -} ADC_SL0CFG_CHSEL0_Enum; - -/* ================================================ ADC SL0CFG WCEN0 [1..1] ================================================ */ -typedef enum { /*!< ADC_SL0CFG_WCEN0 */ - ADC_SL0CFG_WCEN0_WCEN = 1, /*!< WCEN : Enable the window compare for slot 0. value. */ -} ADC_SL0CFG_WCEN0_Enum; - -/* ================================================ ADC SL0CFG SLEN0 [0..0] ================================================ */ -typedef enum { /*!< ADC_SL0CFG_SLEN0 */ - ADC_SL0CFG_SLEN0_SLEN = 1, /*!< SLEN : Enable slot 0 for ADC conversions. value. */ -} ADC_SL0CFG_SLEN0_Enum; - -/* ======================================================== SL1CFG ========================================================= */ -/* ============================================== ADC SL1CFG ADSEL1 [24..26] =============================================== */ -typedef enum { /*!< ADC_SL1CFG_ADSEL1 */ - ADC_SL1CFG_ADSEL1_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide - module for this slot. value. */ - ADC_SL1CFG_ADSEL1_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL1CFG_ADSEL1_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL1CFG_ADSEL1_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL1CFG_ADSEL1_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL1CFG_ADSEL1_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL1CFG_ADSEL1_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL1CFG_ADSEL1_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate - divide module for this slot. value. */ -} ADC_SL1CFG_ADSEL1_Enum; - -/* ============================================== ADC SL1CFG PRMODE1 [16..17] ============================================== */ -typedef enum { /*!< ADC_SL1CFG_PRMODE1 */ - ADC_SL1CFG_PRMODE1_P14B = 0, /*!< P14B : 14-bit precision mode value. */ - ADC_SL1CFG_PRMODE1_P12B = 1, /*!< P12B : 12-bit precision mode value. */ - ADC_SL1CFG_PRMODE1_P10B = 2, /*!< P10B : 10-bit precision mode value. */ - ADC_SL1CFG_PRMODE1_P8B = 3, /*!< P8B : 8-bit precision mode value. */ -} ADC_SL1CFG_PRMODE1_Enum; - -/* =============================================== ADC SL1CFG CHSEL1 [8..11] =============================================== */ -typedef enum { /*!< ADC_SL1CFG_CHSEL1 */ - ADC_SL1CFG_CHSEL1_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ - ADC_SL1CFG_CHSEL1_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ - ADC_SL1CFG_CHSEL1_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ - ADC_SL1CFG_CHSEL1_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ - ADC_SL1CFG_CHSEL1_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ - ADC_SL1CFG_CHSEL1_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ - ADC_SL1CFG_CHSEL1_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ - ADC_SL1CFG_CHSEL1_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ - ADC_SL1CFG_CHSEL1_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ - ADC_SL1CFG_CHSEL1_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ - ADC_SL1CFG_CHSEL1_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and - pad13(P). value. */ - ADC_SL1CFG_CHSEL1_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and - pad14(P). value. */ - ADC_SL1CFG_CHSEL1_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ - ADC_SL1CFG_CHSEL1_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ - ADC_SL1CFG_CHSEL1_VSS = 14, /*!< VSS : Input VSS value. */ -} ADC_SL1CFG_CHSEL1_Enum; - -/* ================================================ ADC SL1CFG WCEN1 [1..1] ================================================ */ -typedef enum { /*!< ADC_SL1CFG_WCEN1 */ - ADC_SL1CFG_WCEN1_WCEN = 1, /*!< WCEN : Enable the window compare for slot 1. value. */ -} ADC_SL1CFG_WCEN1_Enum; - -/* ================================================ ADC SL1CFG SLEN1 [0..0] ================================================ */ -typedef enum { /*!< ADC_SL1CFG_SLEN1 */ - ADC_SL1CFG_SLEN1_SLEN = 1, /*!< SLEN : Enable slot 1 for ADC conversions. value. */ -} ADC_SL1CFG_SLEN1_Enum; - -/* ======================================================== SL2CFG ========================================================= */ -/* ============================================== ADC SL2CFG ADSEL2 [24..26] =============================================== */ -typedef enum { /*!< ADC_SL2CFG_ADSEL2 */ - ADC_SL2CFG_ADSEL2_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide - module for this slot. value. */ - ADC_SL2CFG_ADSEL2_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL2CFG_ADSEL2_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL2CFG_ADSEL2_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL2CFG_ADSEL2_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL2CFG_ADSEL2_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL2CFG_ADSEL2_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL2CFG_ADSEL2_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate - divide module for this slot. value. */ -} ADC_SL2CFG_ADSEL2_Enum; - -/* ============================================== ADC SL2CFG PRMODE2 [16..17] ============================================== */ -typedef enum { /*!< ADC_SL2CFG_PRMODE2 */ - ADC_SL2CFG_PRMODE2_P14B = 0, /*!< P14B : 14-bit precision mode value. */ - ADC_SL2CFG_PRMODE2_P12B = 1, /*!< P12B : 12-bit precision mode value. */ - ADC_SL2CFG_PRMODE2_P10B = 2, /*!< P10B : 10-bit precision mode value. */ - ADC_SL2CFG_PRMODE2_P8B = 3, /*!< P8B : 8-bit precision mode value. */ -} ADC_SL2CFG_PRMODE2_Enum; - -/* =============================================== ADC SL2CFG CHSEL2 [8..11] =============================================== */ -typedef enum { /*!< ADC_SL2CFG_CHSEL2 */ - ADC_SL2CFG_CHSEL2_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ - ADC_SL2CFG_CHSEL2_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ - ADC_SL2CFG_CHSEL2_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ - ADC_SL2CFG_CHSEL2_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ - ADC_SL2CFG_CHSEL2_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ - ADC_SL2CFG_CHSEL2_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ - ADC_SL2CFG_CHSEL2_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ - ADC_SL2CFG_CHSEL2_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ - ADC_SL2CFG_CHSEL2_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ - ADC_SL2CFG_CHSEL2_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ - ADC_SL2CFG_CHSEL2_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and - pad13(P). value. */ - ADC_SL2CFG_CHSEL2_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and - pad14(P). value. */ - ADC_SL2CFG_CHSEL2_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ - ADC_SL2CFG_CHSEL2_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ - ADC_SL2CFG_CHSEL2_VSS = 14, /*!< VSS : Input VSS value. */ -} ADC_SL2CFG_CHSEL2_Enum; - -/* ================================================ ADC SL2CFG WCEN2 [1..1] ================================================ */ -typedef enum { /*!< ADC_SL2CFG_WCEN2 */ - ADC_SL2CFG_WCEN2_WCEN = 1, /*!< WCEN : Enable the window compare for slot 2. value. */ -} ADC_SL2CFG_WCEN2_Enum; - -/* ================================================ ADC SL2CFG SLEN2 [0..0] ================================================ */ -typedef enum { /*!< ADC_SL2CFG_SLEN2 */ - ADC_SL2CFG_SLEN2_SLEN = 1, /*!< SLEN : Enable slot 2 for ADC conversions. value. */ -} ADC_SL2CFG_SLEN2_Enum; - -/* ======================================================== SL3CFG ========================================================= */ -/* ============================================== ADC SL3CFG ADSEL3 [24..26] =============================================== */ -typedef enum { /*!< ADC_SL3CFG_ADSEL3 */ - ADC_SL3CFG_ADSEL3_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide - module for this slot. value. */ - ADC_SL3CFG_ADSEL3_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL3CFG_ADSEL3_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL3CFG_ADSEL3_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL3CFG_ADSEL3_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL3CFG_ADSEL3_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL3CFG_ADSEL3_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL3CFG_ADSEL3_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate - divide module for this slot. value. */ -} ADC_SL3CFG_ADSEL3_Enum; - -/* ============================================== ADC SL3CFG PRMODE3 [16..17] ============================================== */ -typedef enum { /*!< ADC_SL3CFG_PRMODE3 */ - ADC_SL3CFG_PRMODE3_P14B = 0, /*!< P14B : 14-bit precision mode value. */ - ADC_SL3CFG_PRMODE3_P12B = 1, /*!< P12B : 12-bit precision mode value. */ - ADC_SL3CFG_PRMODE3_P10B = 2, /*!< P10B : 10-bit precision mode value. */ - ADC_SL3CFG_PRMODE3_P8B = 3, /*!< P8B : 8-bit precision mode value. */ -} ADC_SL3CFG_PRMODE3_Enum; - -/* =============================================== ADC SL3CFG CHSEL3 [8..11] =============================================== */ -typedef enum { /*!< ADC_SL3CFG_CHSEL3 */ - ADC_SL3CFG_CHSEL3_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ - ADC_SL3CFG_CHSEL3_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ - ADC_SL3CFG_CHSEL3_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ - ADC_SL3CFG_CHSEL3_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ - ADC_SL3CFG_CHSEL3_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ - ADC_SL3CFG_CHSEL3_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ - ADC_SL3CFG_CHSEL3_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ - ADC_SL3CFG_CHSEL3_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ - ADC_SL3CFG_CHSEL3_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ - ADC_SL3CFG_CHSEL3_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ - ADC_SL3CFG_CHSEL3_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and - pad13(P). value. */ - ADC_SL3CFG_CHSEL3_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and - pad14(P). value. */ - ADC_SL3CFG_CHSEL3_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ - ADC_SL3CFG_CHSEL3_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ - ADC_SL3CFG_CHSEL3_VSS = 14, /*!< VSS : Input VSS value. */ -} ADC_SL3CFG_CHSEL3_Enum; - -/* ================================================ ADC SL3CFG WCEN3 [1..1] ================================================ */ -typedef enum { /*!< ADC_SL3CFG_WCEN3 */ - ADC_SL3CFG_WCEN3_WCEN = 1, /*!< WCEN : Enable the window compare for slot 3. value. */ -} ADC_SL3CFG_WCEN3_Enum; - -/* ================================================ ADC SL3CFG SLEN3 [0..0] ================================================ */ -typedef enum { /*!< ADC_SL3CFG_SLEN3 */ - ADC_SL3CFG_SLEN3_SLEN = 1, /*!< SLEN : Enable slot 3 for ADC conversions. value. */ -} ADC_SL3CFG_SLEN3_Enum; - -/* ======================================================== SL4CFG ========================================================= */ -/* ============================================== ADC SL4CFG ADSEL4 [24..26] =============================================== */ -typedef enum { /*!< ADC_SL4CFG_ADSEL4 */ - ADC_SL4CFG_ADSEL4_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide - module for this slot. value. */ - ADC_SL4CFG_ADSEL4_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL4CFG_ADSEL4_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL4CFG_ADSEL4_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL4CFG_ADSEL4_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL4CFG_ADSEL4_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL4CFG_ADSEL4_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL4CFG_ADSEL4_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate - divide module for this slot. value. */ -} ADC_SL4CFG_ADSEL4_Enum; - -/* ============================================== ADC SL4CFG PRMODE4 [16..17] ============================================== */ -typedef enum { /*!< ADC_SL4CFG_PRMODE4 */ - ADC_SL4CFG_PRMODE4_P14B = 0, /*!< P14B : 14-bit precision mode value. */ - ADC_SL4CFG_PRMODE4_P12B = 1, /*!< P12B : 12-bit precision mode value. */ - ADC_SL4CFG_PRMODE4_P10B = 2, /*!< P10B : 10-bit precision mode value. */ - ADC_SL4CFG_PRMODE4_P8B = 3, /*!< P8B : 8-bit precision mode value. */ -} ADC_SL4CFG_PRMODE4_Enum; - -/* =============================================== ADC SL4CFG CHSEL4 [8..11] =============================================== */ -typedef enum { /*!< ADC_SL4CFG_CHSEL4 */ - ADC_SL4CFG_CHSEL4_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ - ADC_SL4CFG_CHSEL4_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ - ADC_SL4CFG_CHSEL4_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ - ADC_SL4CFG_CHSEL4_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ - ADC_SL4CFG_CHSEL4_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ - ADC_SL4CFG_CHSEL4_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ - ADC_SL4CFG_CHSEL4_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ - ADC_SL4CFG_CHSEL4_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ - ADC_SL4CFG_CHSEL4_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ - ADC_SL4CFG_CHSEL4_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ - ADC_SL4CFG_CHSEL4_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and - pad13(P). value. */ - ADC_SL4CFG_CHSEL4_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and - pad14(P). value. */ - ADC_SL4CFG_CHSEL4_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ - ADC_SL4CFG_CHSEL4_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ - ADC_SL4CFG_CHSEL4_VSS = 14, /*!< VSS : Input VSS value. */ -} ADC_SL4CFG_CHSEL4_Enum; - -/* ================================================ ADC SL4CFG WCEN4 [1..1] ================================================ */ -typedef enum { /*!< ADC_SL4CFG_WCEN4 */ - ADC_SL4CFG_WCEN4_WCEN = 1, /*!< WCEN : Enable the window compare for slot 4. value. */ -} ADC_SL4CFG_WCEN4_Enum; - -/* ================================================ ADC SL4CFG SLEN4 [0..0] ================================================ */ -typedef enum { /*!< ADC_SL4CFG_SLEN4 */ - ADC_SL4CFG_SLEN4_SLEN = 1, /*!< SLEN : Enable slot 4 for ADC conversions. value. */ -} ADC_SL4CFG_SLEN4_Enum; - -/* ======================================================== SL5CFG ========================================================= */ -/* ============================================== ADC SL5CFG ADSEL5 [24..26] =============================================== */ -typedef enum { /*!< ADC_SL5CFG_ADSEL5 */ - ADC_SL5CFG_ADSEL5_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide - module for this slot. value. */ - ADC_SL5CFG_ADSEL5_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL5CFG_ADSEL5_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL5CFG_ADSEL5_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL5CFG_ADSEL5_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL5CFG_ADSEL5_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL5CFG_ADSEL5_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL5CFG_ADSEL5_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate - divide module for this slot. value. */ -} ADC_SL5CFG_ADSEL5_Enum; - -/* ============================================== ADC SL5CFG PRMODE5 [16..17] ============================================== */ -typedef enum { /*!< ADC_SL5CFG_PRMODE5 */ - ADC_SL5CFG_PRMODE5_P14B = 0, /*!< P14B : 14-bit precision mode value. */ - ADC_SL5CFG_PRMODE5_P12B = 1, /*!< P12B : 12-bit precision mode value. */ - ADC_SL5CFG_PRMODE5_P10B = 2, /*!< P10B : 10-bit precision mode value. */ - ADC_SL5CFG_PRMODE5_P8B = 3, /*!< P8B : 8-bit precision mode value. */ -} ADC_SL5CFG_PRMODE5_Enum; - -/* =============================================== ADC SL5CFG CHSEL5 [8..11] =============================================== */ -typedef enum { /*!< ADC_SL5CFG_CHSEL5 */ - ADC_SL5CFG_CHSEL5_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ - ADC_SL5CFG_CHSEL5_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ - ADC_SL5CFG_CHSEL5_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ - ADC_SL5CFG_CHSEL5_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ - ADC_SL5CFG_CHSEL5_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ - ADC_SL5CFG_CHSEL5_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ - ADC_SL5CFG_CHSEL5_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ - ADC_SL5CFG_CHSEL5_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ - ADC_SL5CFG_CHSEL5_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ - ADC_SL5CFG_CHSEL5_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ - ADC_SL5CFG_CHSEL5_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and - pad13(P). value. */ - ADC_SL5CFG_CHSEL5_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and - pad14(P). value. */ - ADC_SL5CFG_CHSEL5_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ - ADC_SL5CFG_CHSEL5_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ - ADC_SL5CFG_CHSEL5_VSS = 14, /*!< VSS : Input VSS value. */ -} ADC_SL5CFG_CHSEL5_Enum; - -/* ================================================ ADC SL5CFG WCEN5 [1..1] ================================================ */ -typedef enum { /*!< ADC_SL5CFG_WCEN5 */ - ADC_SL5CFG_WCEN5_WCEN = 1, /*!< WCEN : Enable the window compare for slot 5. value. */ -} ADC_SL5CFG_WCEN5_Enum; - -/* ================================================ ADC SL5CFG SLEN5 [0..0] ================================================ */ -typedef enum { /*!< ADC_SL5CFG_SLEN5 */ - ADC_SL5CFG_SLEN5_SLEN = 1, /*!< SLEN : Enable slot 5 for ADC conversions. value. */ -} ADC_SL5CFG_SLEN5_Enum; - -/* ======================================================== SL6CFG ========================================================= */ -/* ============================================== ADC SL6CFG ADSEL6 [24..26] =============================================== */ -typedef enum { /*!< ADC_SL6CFG_ADSEL6 */ - ADC_SL6CFG_ADSEL6_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide - module for this slot. value. */ - ADC_SL6CFG_ADSEL6_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL6CFG_ADSEL6_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL6CFG_ADSEL6_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL6CFG_ADSEL6_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL6CFG_ADSEL6_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL6CFG_ADSEL6_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL6CFG_ADSEL6_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate - divide module for this slot. value. */ -} ADC_SL6CFG_ADSEL6_Enum; - -/* ============================================== ADC SL6CFG PRMODE6 [16..17] ============================================== */ -typedef enum { /*!< ADC_SL6CFG_PRMODE6 */ - ADC_SL6CFG_PRMODE6_P14B = 0, /*!< P14B : 14-bit precision mode value. */ - ADC_SL6CFG_PRMODE6_P12B = 1, /*!< P12B : 12-bit precision mode value. */ - ADC_SL6CFG_PRMODE6_P10B = 2, /*!< P10B : 10-bit precision mode value. */ - ADC_SL6CFG_PRMODE6_P8B = 3, /*!< P8B : 8-bit precision mode value. */ -} ADC_SL6CFG_PRMODE6_Enum; - -/* =============================================== ADC SL6CFG CHSEL6 [8..11] =============================================== */ -typedef enum { /*!< ADC_SL6CFG_CHSEL6 */ - ADC_SL6CFG_CHSEL6_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ - ADC_SL6CFG_CHSEL6_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ - ADC_SL6CFG_CHSEL6_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ - ADC_SL6CFG_CHSEL6_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ - ADC_SL6CFG_CHSEL6_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ - ADC_SL6CFG_CHSEL6_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ - ADC_SL6CFG_CHSEL6_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ - ADC_SL6CFG_CHSEL6_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ - ADC_SL6CFG_CHSEL6_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ - ADC_SL6CFG_CHSEL6_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ - ADC_SL6CFG_CHSEL6_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and - pad13(P). value. */ - ADC_SL6CFG_CHSEL6_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and - pad14(P). value. */ - ADC_SL6CFG_CHSEL6_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ - ADC_SL6CFG_CHSEL6_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ - ADC_SL6CFG_CHSEL6_VSS = 14, /*!< VSS : Input VSS value. */ -} ADC_SL6CFG_CHSEL6_Enum; - -/* ================================================ ADC SL6CFG WCEN6 [1..1] ================================================ */ -typedef enum { /*!< ADC_SL6CFG_WCEN6 */ - ADC_SL6CFG_WCEN6_WCEN = 1, /*!< WCEN : Enable the window compare for slot 6. value. */ -} ADC_SL6CFG_WCEN6_Enum; - -/* ================================================ ADC SL6CFG SLEN6 [0..0] ================================================ */ -typedef enum { /*!< ADC_SL6CFG_SLEN6 */ - ADC_SL6CFG_SLEN6_SLEN = 1, /*!< SLEN : Enable slot 6 for ADC conversions. value. */ -} ADC_SL6CFG_SLEN6_Enum; - -/* ======================================================== SL7CFG ========================================================= */ -/* ============================================== ADC SL7CFG ADSEL7 [24..26] =============================================== */ -typedef enum { /*!< ADC_SL7CFG_ADSEL7 */ - ADC_SL7CFG_ADSEL7_AVG_1_MSRMT = 0, /*!< AVG_1_MSRMT : Average in 1 measurement in the accumulate divide - module for this slot. value. */ - ADC_SL7CFG_ADSEL7_AVG_2_MSRMTS = 1, /*!< AVG_2_MSRMTS : Average in 2 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL7CFG_ADSEL7_AVG_4_MSRMTS = 2, /*!< AVG_4_MSRMTS : Average in 4 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL7CFG_ADSEL7_AVG_8_MSRMT = 3, /*!< AVG_8_MSRMT : Average in 8 measurements in the accumulate divide - module for this slot. value. */ - ADC_SL7CFG_ADSEL7_AVG_16_MSRMTS = 4, /*!< AVG_16_MSRMTS : Average in 16 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL7CFG_ADSEL7_AVG_32_MSRMTS = 5, /*!< AVG_32_MSRMTS : Average in 32 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL7CFG_ADSEL7_AVG_64_MSRMTS = 6, /*!< AVG_64_MSRMTS : Average in 64 measurements in the accumulate - divide module for this slot. value. */ - ADC_SL7CFG_ADSEL7_AVG_128_MSRMTS = 7, /*!< AVG_128_MSRMTS : Average in 128 measurements in the accumulate - divide module for this slot. value. */ -} ADC_SL7CFG_ADSEL7_Enum; - -/* ============================================== ADC SL7CFG PRMODE7 [16..17] ============================================== */ -typedef enum { /*!< ADC_SL7CFG_PRMODE7 */ - ADC_SL7CFG_PRMODE7_P14B = 0, /*!< P14B : 14-bit precision mode value. */ - ADC_SL7CFG_PRMODE7_P12B = 1, /*!< P12B : 12-bit precision mode value. */ - ADC_SL7CFG_PRMODE7_P10B = 2, /*!< P10B : 10-bit precision mode value. */ - ADC_SL7CFG_PRMODE7_P8B = 3, /*!< P8B : 8-bit precision mode value. */ -} ADC_SL7CFG_PRMODE7_Enum; - -/* =============================================== ADC SL7CFG CHSEL7 [8..11] =============================================== */ -typedef enum { /*!< ADC_SL7CFG_CHSEL7 */ - ADC_SL7CFG_CHSEL7_SE0 = 0, /*!< SE0 : single ended external GPIO connection to pad16. value. */ - ADC_SL7CFG_CHSEL7_SE1 = 1, /*!< SE1 : single ended external GPIO connection to pad29. value. */ - ADC_SL7CFG_CHSEL7_SE2 = 2, /*!< SE2 : single ended external GPIO connection to pad11. value. */ - ADC_SL7CFG_CHSEL7_SE3 = 3, /*!< SE3 : single ended external GPIO connection to pad31. value. */ - ADC_SL7CFG_CHSEL7_SE4 = 4, /*!< SE4 : single ended external GPIO connection to pad32. value. */ - ADC_SL7CFG_CHSEL7_SE5 = 5, /*!< SE5 : single ended external GPIO connection to pad33. value. */ - ADC_SL7CFG_CHSEL7_SE6 = 6, /*!< SE6 : single ended external GPIO connection to pad34. value. */ - ADC_SL7CFG_CHSEL7_SE7 = 7, /*!< SE7 : single ended external GPIO connection to pad35. value. */ - ADC_SL7CFG_CHSEL7_SE8 = 8, /*!< SE8 : single ended external GPIO connection to pad13. value. */ - ADC_SL7CFG_CHSEL7_SE9 = 9, /*!< SE9 : single ended external GPIO connection to pad12. value. */ - ADC_SL7CFG_CHSEL7_DF0 = 10, /*!< DF0 : differential external GPIO connections to pad12(N) and - pad13(P). value. */ - ADC_SL7CFG_CHSEL7_DF1 = 11, /*!< DF1 : differential external GPIO connections to pad15(N) and - pad14(P). value. */ - ADC_SL7CFG_CHSEL7_TEMP = 12, /*!< TEMP : internal temperature sensor. value. */ - ADC_SL7CFG_CHSEL7_BATT = 13, /*!< BATT : internal voltage divide-by-3 connection. value. */ - ADC_SL7CFG_CHSEL7_VSS = 14, /*!< VSS : Input VSS value. */ -} ADC_SL7CFG_CHSEL7_Enum; - -/* ================================================ ADC SL7CFG WCEN7 [1..1] ================================================ */ -typedef enum { /*!< ADC_SL7CFG_WCEN7 */ - ADC_SL7CFG_WCEN7_WCEN = 1, /*!< WCEN : Enable the window compare for slot 7. value. */ -} ADC_SL7CFG_WCEN7_Enum; - -/* ================================================ ADC SL7CFG SLEN7 [0..0] ================================================ */ -typedef enum { /*!< ADC_SL7CFG_SLEN7 */ - ADC_SL7CFG_SLEN7_SLEN = 1, /*!< SLEN : Enable slot 7 for ADC conversions. value. */ -} ADC_SL7CFG_SLEN7_Enum; - -/* ========================================================= WULIM ========================================================= */ -/* ========================================================= WLLIM ========================================================= */ -/* ======================================================== SCWLIM ========================================================= */ -/* ========================================================= FIFO ========================================================== */ -/* ======================================================== FIFOPR ========================================================= */ -/* ========================================================= INTEN ========================================================= */ -/* ================================================= ADC INTEN DERR [7..7] ================================================= */ -typedef enum { /*!< ADC_INTEN_DERR */ - ADC_INTEN_DERR_DMAERROR = 1, /*!< DMAERROR : DMA Error Condition Occurred value. */ -} ADC_INTEN_DERR_Enum; - -/* ================================================= ADC INTEN DCMP [6..6] ================================================= */ -typedef enum { /*!< ADC_INTEN_DCMP */ - ADC_INTEN_DCMP_DMACOMPLETE = 1, /*!< DMACOMPLETE : DMA Completed a transfer value. */ -} ADC_INTEN_DCMP_Enum; - -/* ================================================ ADC INTEN WCINC [5..5] ================================================= */ -typedef enum { /*!< ADC_INTEN_WCINC */ - ADC_INTEN_WCINC_WCINCINT = 1, /*!< WCINCINT : Window comparitor voltage incursion interrupt. value. */ -} ADC_INTEN_WCINC_Enum; - -/* ================================================ ADC INTEN WCEXC [4..4] ================================================= */ -typedef enum { /*!< ADC_INTEN_WCEXC */ - ADC_INTEN_WCEXC_WCEXCINT = 1, /*!< WCEXCINT : Window comparitor voltage excursion interrupt. value. */ -} ADC_INTEN_WCEXC_Enum; - -/* =============================================== ADC INTEN FIFOOVR2 [3..3] =============================================== */ -typedef enum { /*!< ADC_INTEN_FIFOOVR2 */ - ADC_INTEN_FIFOOVR2_FIFOFULLINT = 1, /*!< FIFOFULLINT : FIFO 100 percent full interrupt. value. */ -} ADC_INTEN_FIFOOVR2_Enum; - -/* =============================================== ADC INTEN FIFOOVR1 [2..2] =============================================== */ -typedef enum { /*!< ADC_INTEN_FIFOOVR1 */ - ADC_INTEN_FIFOOVR1_FIFO75INT = 1, /*!< FIFO75INT : FIFO 75 percent full interrupt. value. */ -} ADC_INTEN_FIFOOVR1_Enum; - -/* ================================================ ADC INTEN SCNCMP [1..1] ================================================ */ -typedef enum { /*!< ADC_INTEN_SCNCMP */ - ADC_INTEN_SCNCMP_SCNCMPINT = 1, /*!< SCNCMPINT : ADC scan complete interrupt. value. */ -} ADC_INTEN_SCNCMP_Enum; - -/* ================================================ ADC INTEN CNVCMP [0..0] ================================================ */ -typedef enum { /*!< ADC_INTEN_CNVCMP */ - ADC_INTEN_CNVCMP_CNVCMPINT = 1, /*!< CNVCMPINT : ADC conversion complete interrupt. value. */ -} ADC_INTEN_CNVCMP_Enum; - -/* ======================================================== INTSTAT ======================================================== */ -/* ================================================ ADC INTSTAT DERR [7..7] ================================================ */ -typedef enum { /*!< ADC_INTSTAT_DERR */ - ADC_INTSTAT_DERR_DMAERROR = 1, /*!< DMAERROR : DMA Error Condition Occurred value. */ -} ADC_INTSTAT_DERR_Enum; - -/* ================================================ ADC INTSTAT DCMP [6..6] ================================================ */ -typedef enum { /*!< ADC_INTSTAT_DCMP */ - ADC_INTSTAT_DCMP_DMACOMPLETE = 1, /*!< DMACOMPLETE : DMA Completed a transfer value. */ -} ADC_INTSTAT_DCMP_Enum; - -/* =============================================== ADC INTSTAT WCINC [5..5] ================================================ */ -typedef enum { /*!< ADC_INTSTAT_WCINC */ - ADC_INTSTAT_WCINC_WCINCINT = 1, /*!< WCINCINT : Window comparitor voltage incursion interrupt. value. */ -} ADC_INTSTAT_WCINC_Enum; - -/* =============================================== ADC INTSTAT WCEXC [4..4] ================================================ */ -typedef enum { /*!< ADC_INTSTAT_WCEXC */ - ADC_INTSTAT_WCEXC_WCEXCINT = 1, /*!< WCEXCINT : Window comparitor voltage excursion interrupt. value. */ -} ADC_INTSTAT_WCEXC_Enum; - -/* ============================================== ADC INTSTAT FIFOOVR2 [3..3] ============================================== */ -typedef enum { /*!< ADC_INTSTAT_FIFOOVR2 */ - ADC_INTSTAT_FIFOOVR2_FIFOFULLINT = 1, /*!< FIFOFULLINT : FIFO 100 percent full interrupt. value. */ -} ADC_INTSTAT_FIFOOVR2_Enum; - -/* ============================================== ADC INTSTAT FIFOOVR1 [2..2] ============================================== */ -typedef enum { /*!< ADC_INTSTAT_FIFOOVR1 */ - ADC_INTSTAT_FIFOOVR1_FIFO75INT = 1, /*!< FIFO75INT : FIFO 75 percent full interrupt. value. */ -} ADC_INTSTAT_FIFOOVR1_Enum; - -/* =============================================== ADC INTSTAT SCNCMP [1..1] =============================================== */ -typedef enum { /*!< ADC_INTSTAT_SCNCMP */ - ADC_INTSTAT_SCNCMP_SCNCMPINT = 1, /*!< SCNCMPINT : ADC scan complete interrupt. value. */ -} ADC_INTSTAT_SCNCMP_Enum; - -/* =============================================== ADC INTSTAT CNVCMP [0..0] =============================================== */ -typedef enum { /*!< ADC_INTSTAT_CNVCMP */ - ADC_INTSTAT_CNVCMP_CNVCMPINT = 1, /*!< CNVCMPINT : ADC conversion complete interrupt. value. */ -} ADC_INTSTAT_CNVCMP_Enum; - -/* ======================================================== INTCLR ========================================================= */ -/* ================================================ ADC INTCLR DERR [7..7] ================================================= */ -typedef enum { /*!< ADC_INTCLR_DERR */ - ADC_INTCLR_DERR_DMAERROR = 1, /*!< DMAERROR : DMA Error Condition Occurred value. */ -} ADC_INTCLR_DERR_Enum; - -/* ================================================ ADC INTCLR DCMP [6..6] ================================================= */ -typedef enum { /*!< ADC_INTCLR_DCMP */ - ADC_INTCLR_DCMP_DMACOMPLETE = 1, /*!< DMACOMPLETE : DMA Completed a transfer value. */ -} ADC_INTCLR_DCMP_Enum; - -/* ================================================ ADC INTCLR WCINC [5..5] ================================================ */ -typedef enum { /*!< ADC_INTCLR_WCINC */ - ADC_INTCLR_WCINC_WCINCINT = 1, /*!< WCINCINT : Window comparitor voltage incursion interrupt. value. */ -} ADC_INTCLR_WCINC_Enum; - -/* ================================================ ADC INTCLR WCEXC [4..4] ================================================ */ -typedef enum { /*!< ADC_INTCLR_WCEXC */ - ADC_INTCLR_WCEXC_WCEXCINT = 1, /*!< WCEXCINT : Window comparitor voltage excursion interrupt. value. */ -} ADC_INTCLR_WCEXC_Enum; - -/* ============================================== ADC INTCLR FIFOOVR2 [3..3] =============================================== */ -typedef enum { /*!< ADC_INTCLR_FIFOOVR2 */ - ADC_INTCLR_FIFOOVR2_FIFOFULLINT = 1, /*!< FIFOFULLINT : FIFO 100 percent full interrupt. value. */ -} ADC_INTCLR_FIFOOVR2_Enum; - -/* ============================================== ADC INTCLR FIFOOVR1 [2..2] =============================================== */ -typedef enum { /*!< ADC_INTCLR_FIFOOVR1 */ - ADC_INTCLR_FIFOOVR1_FIFO75INT = 1, /*!< FIFO75INT : FIFO 75 percent full interrupt. value. */ -} ADC_INTCLR_FIFOOVR1_Enum; - -/* =============================================== ADC INTCLR SCNCMP [1..1] ================================================ */ -typedef enum { /*!< ADC_INTCLR_SCNCMP */ - ADC_INTCLR_SCNCMP_SCNCMPINT = 1, /*!< SCNCMPINT : ADC scan complete interrupt. value. */ -} ADC_INTCLR_SCNCMP_Enum; - -/* =============================================== ADC INTCLR CNVCMP [0..0] ================================================ */ -typedef enum { /*!< ADC_INTCLR_CNVCMP */ - ADC_INTCLR_CNVCMP_CNVCMPINT = 1, /*!< CNVCMPINT : ADC conversion complete interrupt. value. */ -} ADC_INTCLR_CNVCMP_Enum; - -/* ======================================================== INTSET ========================================================= */ -/* ================================================ ADC INTSET DERR [7..7] ================================================= */ -typedef enum { /*!< ADC_INTSET_DERR */ - ADC_INTSET_DERR_DMAERROR = 1, /*!< DMAERROR : DMA Error Condition Occurred value. */ -} ADC_INTSET_DERR_Enum; - -/* ================================================ ADC INTSET DCMP [6..6] ================================================= */ -typedef enum { /*!< ADC_INTSET_DCMP */ - ADC_INTSET_DCMP_DMACOMPLETE = 1, /*!< DMACOMPLETE : DMA Completed a transfer value. */ -} ADC_INTSET_DCMP_Enum; - -/* ================================================ ADC INTSET WCINC [5..5] ================================================ */ -typedef enum { /*!< ADC_INTSET_WCINC */ - ADC_INTSET_WCINC_WCINCINT = 1, /*!< WCINCINT : Window comparitor voltage incursion interrupt. value. */ -} ADC_INTSET_WCINC_Enum; - -/* ================================================ ADC INTSET WCEXC [4..4] ================================================ */ -typedef enum { /*!< ADC_INTSET_WCEXC */ - ADC_INTSET_WCEXC_WCEXCINT = 1, /*!< WCEXCINT : Window comparitor voltage excursion interrupt. value. */ -} ADC_INTSET_WCEXC_Enum; - -/* ============================================== ADC INTSET FIFOOVR2 [3..3] =============================================== */ -typedef enum { /*!< ADC_INTSET_FIFOOVR2 */ - ADC_INTSET_FIFOOVR2_FIFOFULLINT = 1, /*!< FIFOFULLINT : FIFO 100 percent full interrupt. value. */ -} ADC_INTSET_FIFOOVR2_Enum; - -/* ============================================== ADC INTSET FIFOOVR1 [2..2] =============================================== */ -typedef enum { /*!< ADC_INTSET_FIFOOVR1 */ - ADC_INTSET_FIFOOVR1_FIFO75INT = 1, /*!< FIFO75INT : FIFO 75 percent full interrupt. value. */ -} ADC_INTSET_FIFOOVR1_Enum; - -/* =============================================== ADC INTSET SCNCMP [1..1] ================================================ */ -typedef enum { /*!< ADC_INTSET_SCNCMP */ - ADC_INTSET_SCNCMP_SCNCMPINT = 1, /*!< SCNCMPINT : ADC scan complete interrupt. value. */ -} ADC_INTSET_SCNCMP_Enum; - -/* =============================================== ADC INTSET CNVCMP [0..0] ================================================ */ -typedef enum { /*!< ADC_INTSET_CNVCMP */ - ADC_INTSET_CNVCMP_CNVCMPINT = 1, /*!< CNVCMPINT : ADC conversion complete interrupt. value. */ -} ADC_INTSET_CNVCMP_Enum; - -/* ======================================================= DMATRIGEN ======================================================= */ -/* ====================================================== DMATRIGSTAT ====================================================== */ -/* ======================================================== DMACFG ========================================================= */ -/* ============================================== ADC DMACFG DMAMSK [17..17] =============================================== */ -typedef enum { /*!< ADC_DMACFG_DMAMSK */ - ADC_DMACFG_DMAMSK_DIS = 0, /*!< DIS : FIFO Contents are copied directly to memory without modification. - value. */ - ADC_DMACFG_DMAMSK_EN = 1, /*!< EN : Only the FIFODATA contents are copied to memory on DMA - transfers. The SLOTNUM and FIFOCNT contents are cleared - to zero. value. */ -} ADC_DMACFG_DMAMSK_Enum; - -/* ============================================ ADC DMACFG DMAHONSTAT [16..16] ============================================= */ -typedef enum { /*!< ADC_DMACFG_DMAHONSTAT */ - ADC_DMACFG_DMAHONSTAT_DIS = 0, /*!< DIS : ADC conversions will continue regardless of DMA status - register value. */ - ADC_DMACFG_DMAHONSTAT_EN = 1, /*!< EN : ADC conversions will not progress if DMAERR or DMACPL bits - in DMA status register are set. value. */ -} ADC_DMACFG_DMAHONSTAT_Enum; - -/* ============================================== ADC DMACFG DMADYNPRI [9..9] ============================================== */ -typedef enum { /*!< ADC_DMACFG_DMADYNPRI */ - ADC_DMACFG_DMADYNPRI_DIS = 0, /*!< DIS : Disable dynamic priority (use DMAPRI setting only) value. */ - ADC_DMACFG_DMADYNPRI_EN = 1, /*!< EN : Enable dynamic priority value. */ -} ADC_DMACFG_DMADYNPRI_Enum; - -/* =============================================== ADC DMACFG DMAPRI [8..8] ================================================ */ -typedef enum { /*!< ADC_DMACFG_DMAPRI */ - ADC_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ - ADC_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ -} ADC_DMACFG_DMAPRI_Enum; - -/* =============================================== ADC DMACFG DMADIR [2..2] ================================================ */ -typedef enum { /*!< ADC_DMACFG_DMADIR */ - ADC_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction value. */ - ADC_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction value. */ -} ADC_DMACFG_DMADIR_Enum; - -/* ================================================ ADC DMACFG DMAEN [0..0] ================================================ */ -typedef enum { /*!< ADC_DMACFG_DMAEN */ - ADC_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ - ADC_DMACFG_DMAEN_EN = 1, /*!< EN : Enable DMA Function value. */ -} ADC_DMACFG_DMAEN_Enum; - -/* ====================================================== DMATOTCOUNT ====================================================== */ -/* ====================================================== DMATARGADDR ====================================================== */ -/* ======================================================== DMASTAT ======================================================== */ - - -/* =========================================================================================================================== */ -/* ================ APBDMA ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== BBVALUE ======================================================== */ -/* ====================================================== BBSETCLEAR ======================================================= */ -/* ======================================================== BBINPUT ======================================================== */ -/* ======================================================= DEBUGDATA ======================================================= */ -/* ========================================================= DEBUG ========================================================= */ -/* ============================================== APBDMA DEBUG DEBUGEN [0..3] ============================================== */ -typedef enum { /*!< APBDMA_DEBUG_DEBUGEN */ - APBDMA_DEBUG_DEBUGEN_OFF = 0, /*!< OFF : Debug Disabled value. */ - APBDMA_DEBUG_DEBUGEN_ARB = 1, /*!< ARB : Debug Arb values value. */ -} APBDMA_DEBUG_DEBUGEN_Enum; - - - -/* =========================================================================================================================== */ -/* ================ BLEIF ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= FIFO ========================================================== */ -/* ======================================================== FIFOPTR ======================================================== */ -/* ======================================================== FIFOTHR ======================================================== */ -/* ======================================================== FIFOPOP ======================================================== */ -/* ======================================================= FIFOPUSH ======================================================== */ -/* ======================================================= FIFOCTRL ======================================================== */ -/* ======================================================== FIFOLOC ======================================================== */ -/* ======================================================== CLKCFG ========================================================= */ -/* =============================================== BLEIF CLKCFG FSEL [8..10] =============================================== */ -typedef enum { /*!< BLEIF_CLKCFG_FSEL */ - BLEIF_CLKCFG_FSEL_MIN_PWR = 0, /*!< MIN_PWR : Selects the minimum power clock. This setting should - be used whenever the IOM is not active. value. */ - BLEIF_CLKCFG_FSEL_HFRC = 1, /*!< HFRC : Selects the HFRC as the input clock. value. */ - BLEIF_CLKCFG_FSEL_HFRC_DIV2 = 2, /*!< HFRC_DIV2 : Selects the HFRC / 2 as the input clock. value. */ - BLEIF_CLKCFG_FSEL_HFRC_DIV4 = 3, /*!< HFRC_DIV4 : Selects the HFRC / 4 as the input clock. value. */ - BLEIF_CLKCFG_FSEL_HFRC_DIV8 = 4, /*!< HFRC_DIV8 : Selects the HFRC / 8 as the input clock. value. */ - BLEIF_CLKCFG_FSEL_HFRC_DIV16 = 5, /*!< HFRC_DIV16 : Selects the HFRC / 16 as the input clock. value. */ - BLEIF_CLKCFG_FSEL_HFRC_DIV32 = 6, /*!< HFRC_DIV32 : Selects the HFRC / 32 as the input clock. value. */ - BLEIF_CLKCFG_FSEL_HFRC_DIV64 = 7, /*!< HFRC_DIV64 : Selects the HFRC / 64 as the input clock. value. */ -} BLEIF_CLKCFG_FSEL_Enum; - -/* ========================================================== CMD ========================================================== */ -/* ================================================= BLEIF CMD CMD [0..4] ================================================== */ -typedef enum { /*!< BLEIF_CMD_CMD */ - BLEIF_CMD_CMD_WRITE = 1, /*!< WRITE : Write command using count of offset bytes specified - in the OFFSETCNT field value. */ - BLEIF_CMD_CMD_READ = 2, /*!< READ : Read command using count of offset bytes specified in - the OFFSETCNT field value. */ -} BLEIF_CMD_CMD_Enum; - -/* ======================================================== CMDRPT ========================================================= */ -/* ======================================================= OFFSETHI ======================================================== */ -/* ======================================================== CMDSTAT ======================================================== */ -/* ============================================= BLEIF CMDSTAT CMDSTAT [5..7] ============================================== */ -typedef enum { /*!< BLEIF_CMDSTAT_CMDSTAT */ - BLEIF_CMDSTAT_CMDSTAT_ERR = 1, /*!< ERR : Error encountered with command value. */ - BLEIF_CMDSTAT_CMDSTAT_ACTIVE = 2, /*!< ACTIVE : Actively processing command value. */ - BLEIF_CMDSTAT_CMDSTAT_IDLE = 4, /*!< IDLE : Idle state, no active command, no error value. */ - BLEIF_CMDSTAT_CMDSTAT_WAIT = 6, /*!< WAIT : Command in progress, but waiting on data from host value. */ -} BLEIF_CMDSTAT_CMDSTAT_Enum; - -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ -/* ======================================================= DMATRIGEN ======================================================= */ -/* ====================================================== DMATRIGSTAT ====================================================== */ -/* ======================================================== DMACFG ========================================================= */ -/* ============================================== BLEIF DMACFG DPWROFF [9..9] ============================================== */ -typedef enum { /*!< BLEIF_DMACFG_DPWROFF */ - BLEIF_DMACFG_DPWROFF_DIS = 0, /*!< DIS : Power off disabled value. */ - BLEIF_DMACFG_DPWROFF_EN = 1, /*!< EN : Power off enabled value. */ -} BLEIF_DMACFG_DPWROFF_Enum; - -/* ============================================== BLEIF DMACFG DMAPRI [8..8] =============================================== */ -typedef enum { /*!< BLEIF_DMACFG_DMAPRI */ - BLEIF_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ - BLEIF_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ -} BLEIF_DMACFG_DMAPRI_Enum; - -/* ============================================== BLEIF DMACFG DMADIR [1..1] =============================================== */ -typedef enum { /*!< BLEIF_DMACFG_DMADIR */ - BLEIF_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction. To be set when - doing IOM read operations, ie reading data from external - devices. value. */ - BLEIF_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction. To be set when doing - IOM write operations, ie writing data to external devices. - value. */ -} BLEIF_DMACFG_DMADIR_Enum; - -/* =============================================== BLEIF DMACFG DMAEN [0..0] =============================================== */ -typedef enum { /*!< BLEIF_DMACFG_DMAEN */ - BLEIF_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ - BLEIF_DMACFG_DMAEN_EN = 1, /*!< EN : Enable DMA Function value. */ -} BLEIF_DMACFG_DMAEN_Enum; - -/* ====================================================== DMATOTCOUNT ====================================================== */ -/* ====================================================== DMATARGADDR ====================================================== */ -/* ======================================================== DMASTAT ======================================================== */ -/* ========================================================= CQCFG ========================================================= */ -/* =============================================== BLEIF CQCFG CQPRI [1..1] ================================================ */ -typedef enum { /*!< BLEIF_CQCFG_CQPRI */ - BLEIF_CQCFG_CQPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ - BLEIF_CQCFG_CQPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ -} BLEIF_CQCFG_CQPRI_Enum; - -/* ================================================ BLEIF CQCFG CQEN [0..0] ================================================ */ -typedef enum { /*!< BLEIF_CQCFG_CQEN */ - BLEIF_CQCFG_CQEN_DIS = 0, /*!< DIS : Disable CQ Function value. */ - BLEIF_CQCFG_CQEN_EN = 1, /*!< EN : Enable CQ Function value. */ -} BLEIF_CQCFG_CQEN_Enum; - -/* ======================================================== CQADDR ========================================================= */ -/* ======================================================== CQSTAT ========================================================= */ -/* ======================================================== CQFLAGS ======================================================== */ -/* ====================================================== CQSETCLEAR ======================================================= */ -/* ======================================================= CQPAUSEEN ======================================================= */ -/* ============================================= BLEIF CQPAUSEEN CQPEN [0..15] ============================================= */ -typedef enum { /*!< BLEIF_CQPAUSEEN_CQPEN */ - BLEIF_CQPAUSEEN_CQPEN_CNTEQ = 32768, /*!< CNTEQ : Pauses command queue processing when HWCNT matches SWCNT - value. */ - BLEIF_CQPAUSEEN_CQPEN_BLEXOREN = 16384, /*!< BLEXOREN : Pause command queue when input BLE bit XORed with - SWFLAG4 is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_IOMXOREN = 8192, /*!< IOMXOREN : Pause command queue when input IOM bit XORed with - SWFLAG3 is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_GPIOXOREN = 4096, /*!< GPIOXOREN : Pause command queue when input GPIO irq_bit XORed - with SWFLAG2 is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_MSPI1XNOREN = 2048, /*!< MSPI1XNOREN : Pause command queue when input MSPI1 bit XNORed - with SWFLAG1 is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_MSPI0XNOREN = 1024, /*!< MSPI0XNOREN : Pause command queue when input MSPI0 bit XNORed - with SWFLAG0 is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_MSPI1XOREN = 512, /*!< MSPI1XOREN : Pause command queue when input MSPI1 bit XORed - with SWFLAG1 is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_MSPI0XOREN = 256, /*!< MSPI0XOREN : Pause command queue when input MSPI0 bit XORed - with SWFLAG0 is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN7 = 128, /*!< SWFLAGEN7 : Pause the command queue when software flag bit 7 - is '1'. value. */ - BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN6 = 64, /*!< SWFLAGEN6 : Pause the command queue when software flag bit 7 - is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN5 = 32, /*!< SWFLAGEN5 : Pause the command queue when software flag bit 7 - is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN4 = 16, /*!< SWFLAGEN4 : Pause the command queue when software flag bit 7 - is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN3 = 8, /*!< SWFLAGEN3 : Pause the command queue when software flag bit 7 - is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN2 = 4, /*!< SWFLAGEN2 : Pause the command queue when software flag bit 7 - is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_SWFLAGEN1 = 2, /*!< SWFLAGEN1 : Pause the command queue when software flag bit 7 - is '1' value. */ - BLEIF_CQPAUSEEN_CQPEN_SWFLGEN0 = 1, /*!< SWFLGEN0 : Pause the command queue when software flag bit 7 - is '1' value. */ -} BLEIF_CQPAUSEEN_CQPEN_Enum; - -/* ======================================================= CQCURIDX ======================================================== */ -/* ======================================================= CQENDIDX ======================================================== */ -/* ======================================================== STATUS ========================================================= */ -/* ============================================== BLEIF STATUS IDLEST [2..2] =============================================== */ -typedef enum { /*!< BLEIF_STATUS_IDLEST */ - BLEIF_STATUS_IDLEST_IDLE = 1, /*!< IDLE : The I/O state machine is in the idle state. value. */ -} BLEIF_STATUS_IDLEST_Enum; - -/* ============================================== BLEIF STATUS CMDACT [1..1] =============================================== */ -typedef enum { /*!< BLEIF_STATUS_CMDACT */ - BLEIF_STATUS_CMDACT_ACTIVE = 1, /*!< ACTIVE : An I/O command is active. Indicates the active module - has an active command and is processing this. De-asserted - when the command is completed. value. */ -} BLEIF_STATUS_CMDACT_Enum; - -/* ================================================ BLEIF STATUS ERR [0..0] ================================================ */ -typedef enum { /*!< BLEIF_STATUS_ERR */ - BLEIF_STATUS_ERR_ERROR = 1, /*!< ERROR : Bit has been deprecated and will always return 0. value. */ -} BLEIF_STATUS_ERR_Enum; - -/* ======================================================== MSPICFG ======================================================== */ -/* ============================================= BLEIF MSPICFG SPILSB [23..23] ============================================= */ -typedef enum { /*!< BLEIF_MSPICFG_SPILSB */ - BLEIF_MSPICFG_SPILSB_MSB = 0, /*!< MSB : Send and receive MSB bit first value. */ - BLEIF_MSPICFG_SPILSB_LSB = 1, /*!< LSB : Send and receive LSB bit first value. */ -} BLEIF_MSPICFG_SPILSB_Enum; - -/* ============================================ BLEIF MSPICFG RDFCPOL [22..22] ============================================= */ -typedef enum { /*!< BLEIF_MSPICFG_RDFCPOL */ - BLEIF_MSPICFG_RDFCPOL_NORMAL = 0, /*!< NORMAL : SPI_STATUS signal from BLE Core high(1) creates flow - control and new read spi transactions will not be started - until the signal goes low.(default) value. */ - BLEIF_MSPICFG_RDFCPOL_INVERTED = 1, /*!< INVERTED : SPI_STATUS signal from BLE Core low(0) creates flow - control and new read spi transactions will not be started - until the signal goes high. value. */ -} BLEIF_MSPICFG_RDFCPOL_Enum; - -/* ============================================ BLEIF MSPICFG WTFCPOL [21..21] ============================================= */ -typedef enum { /*!< BLEIF_MSPICFG_WTFCPOL */ - BLEIF_MSPICFG_WTFCPOL_NORMAL = 0, /*!< NORMAL : SPI_STATUS signal from BLE Core high(1) creates flow - control and new write spi transactions will not be started - until the signal goes low.(default) value. */ - BLEIF_MSPICFG_WTFCPOL_INVERTED = 1, /*!< INVERTED : SPI_STATUS signal from BLE Core high(1) creates low(0) - control and new write spi transactions will not be started - until the signal goes high. value. */ -} BLEIF_MSPICFG_WTFCPOL_Enum; - -/* ============================================== BLEIF MSPICFG RDFC [17..17] ============================================== */ -typedef enum { /*!< BLEIF_MSPICFG_RDFC */ - BLEIF_MSPICFG_RDFC_DIS = 0, /*!< DIS : Read mode flow control disabled. value. */ - BLEIF_MSPICFG_RDFC_EN = 1, /*!< EN : Read mode flow control enabled. value. */ -} BLEIF_MSPICFG_RDFC_Enum; - -/* ============================================== BLEIF MSPICFG WTFC [16..16] ============================================== */ -typedef enum { /*!< BLEIF_MSPICFG_WTFC */ - BLEIF_MSPICFG_WTFC_DIS = 0, /*!< DIS : Write mode flow control disabled. value. */ - BLEIF_MSPICFG_WTFC_EN = 1, /*!< EN : Write mode flow control enabled. value. */ -} BLEIF_MSPICFG_WTFC_Enum; - -/* =============================================== BLEIF MSPICFG SPHA [1..1] =============================================== */ -typedef enum { /*!< BLEIF_MSPICFG_SPHA */ - BLEIF_MSPICFG_SPHA_SAMPLE_LEADING_EDGE = 0, /*!< SAMPLE_LEADING_EDGE : Sample on the leading (first) clock edge, - rising or falling dependant on the value of SPOL value. */ - BLEIF_MSPICFG_SPHA_SAMPLE_TRAILING_EDGE = 1, /*!< SAMPLE_TRAILING_EDGE : Sample on the trailing (second) clock - edge, rising of falling dependant on the value of SPOL - value. */ -} BLEIF_MSPICFG_SPHA_Enum; - -/* =============================================== BLEIF MSPICFG SPOL [0..0] =============================================== */ -typedef enum { /*!< BLEIF_MSPICFG_SPOL */ - BLEIF_MSPICFG_SPOL_CLK_BASE_0 = 0, /*!< CLK_BASE_0 : The initial value of the clock is 0. value. */ - BLEIF_MSPICFG_SPOL_CLK_BASE_1 = 1, /*!< CLK_BASE_1 : The initial value of the clock is 1. value. */ -} BLEIF_MSPICFG_SPOL_Enum; - -/* ======================================================== BLECFG ========================================================= */ -/* ============================================ BLEIF BLECFG SPIISOCTL [14..15] ============================================ */ -typedef enum { /*!< BLEIF_BLECFG_SPIISOCTL */ - BLEIF_BLECFG_SPIISOCTL_ON = 3, /*!< ON : SPI signals from BLE Core to/from MCU Core are isolated. - value. */ - BLEIF_BLECFG_SPIISOCTL_OFF = 2, /*!< OFF : SPI signals from BLE Core to/from MCU Core are not isolated. - value. */ - BLEIF_BLECFG_SPIISOCTL_AUTO = 0, /*!< AUTO : SPI signals from BLE Core to/from MCU Core are automatically - isolated by the logic value. */ -} BLEIF_BLECFG_SPIISOCTL_Enum; - -/* ============================================ BLEIF BLECFG PWRISOCTL [12..13] ============================================ */ -typedef enum { /*!< BLEIF_BLECFG_PWRISOCTL */ - BLEIF_BLECFG_PWRISOCTL_ON = 3, /*!< ON : BLEH power signal isolation to on (isolated). value. */ - BLEIF_BLECFG_PWRISOCTL_OFF = 2, /*!< OFF : BLEH power signal isolation to off (not isolated). value. */ - BLEIF_BLECFG_PWRISOCTL_AUTO = 0, /*!< AUTO : BLEH Power signal isolation is controlled automatically - through the interface logic value. */ -} BLEIF_BLECFG_PWRISOCTL_Enum; - -/* ============================================ BLEIF BLECFG BLEHREQCTL [6..7] ============================================= */ -typedef enum { /*!< BLEIF_BLECFG_BLEHREQCTL */ - BLEIF_BLECFG_BLEHREQCTL_ON = 3, /*!< ON : BLEH Power-on reg signal is set to on (1). value. */ - BLEIF_BLECFG_BLEHREQCTL_OFF = 2, /*!< OFF : BLEH Power-on signal is set to off (0). value. */ - BLEIF_BLECFG_BLEHREQCTL_AUTO = 0, /*!< AUTO : BLEH Power-on signal is controlled by the PWRSM logic - and automatically controlled value. */ -} BLEIF_BLECFG_BLEHREQCTL_Enum; - -/* ============================================ BLEIF BLECFG DCDCFLGCTL [4..5] ============================================= */ -typedef enum { /*!< BLEIF_BLECFG_DCDCFLGCTL */ - BLEIF_BLECFG_DCDCFLGCTL_ON = 3, /*!< ON : DCDC Flag signal is set to on (1). value. */ - BLEIF_BLECFG_DCDCFLGCTL_OFF = 2, /*!< OFF : DCDC Flag signal is set to off (0). value. */ - BLEIF_BLECFG_DCDCFLGCTL_AUTO = 0, /*!< AUTO : DCDC Flag signal is controlled by the PWRSM logic and - automatically controlled value. */ -} BLEIF_BLECFG_DCDCFLGCTL_Enum; - -/* ============================================= BLEIF BLECFG WAKEUPCTL [2..3] ============================================= */ -typedef enum { /*!< BLEIF_BLECFG_WAKEUPCTL */ - BLEIF_BLECFG_WAKEUPCTL_ON = 3, /*!< ON : Wake signal is set to on (1). value. */ - BLEIF_BLECFG_WAKEUPCTL_OFF = 2, /*!< OFF : Wake signal is set to off (0). value. */ - BLEIF_BLECFG_WAKEUPCTL_AUTO = 0, /*!< AUTO : Wake signal is controlled by the PWRSM logic and automatically - controlled value. */ -} BLEIF_BLECFG_WAKEUPCTL_Enum; - -/* ============================================== BLEIF BLECFG BLERSTN [1..1] ============================================== */ -typedef enum { /*!< BLEIF_BLECFG_BLERSTN */ - BLEIF_BLECFG_BLERSTN_ACTIVE = 1, /*!< ACTIVE : The reset signal is active (0) value. */ - BLEIF_BLECFG_BLERSTN_INACTIVE = 0, /*!< INACTIVE : The reset signal is inactive (1) value. */ -} BLEIF_BLECFG_BLERSTN_Enum; - -/* ============================================== BLEIF BLECFG PWRSMEN [0..0] ============================================== */ -typedef enum { /*!< BLEIF_BLECFG_PWRSMEN */ - BLEIF_BLECFG_PWRSMEN_ON = 1, /*!< ON : Internal power state machine is enabled and will sequence - the BLEH power domain as indicated in the design document. - Overrides for the power signals are not enabled. value. */ - BLEIF_BLECFG_PWRSMEN_OFF = 0, /*!< OFF : Internal power state machine is disabled and will not - sequence the BLEH power domain. The values of the overrides - will be used to drive the output sequencing signals value. */ -} BLEIF_BLECFG_PWRSMEN_Enum; - -/* ======================================================== PWRCMD ========================================================= */ -/* ======================================================== BSTATUS ======================================================== */ -/* ============================================== BLEIF BSTATUS PWRST [8..10] ============================================== */ -typedef enum { /*!< BLEIF_BSTATUS_PWRST */ - BLEIF_BSTATUS_PWRST_OFF = 0, /*!< OFF : Internal power state machine is disabled and will not - sequence the BLEH power domain. The values of the overrides - will be used to drive the output sequencing signals value. */ - BLEIF_BSTATUS_PWRST_INIT = 1, /*!< INIT : Initialization state. BLEH not powered value. */ - BLEIF_BSTATUS_PWRST_PWRON = 2, /*!< PWRON : Waiting for the powerup of the BLEH value. */ - BLEIF_BSTATUS_PWRST_ACTIVE = 3, /*!< ACTIVE : The BLE Core is powered and active value. */ - BLEIF_BSTATUS_PWRST_SLEEP = 6, /*!< SLEEP : The BLE Core has entered sleep mode and the power request - is inactive value. */ - BLEIF_BSTATUS_PWRST_SHUTDOWN = 4, /*!< SHUTDOWN : The BLE Core is in shutdown mode value. */ -} BLEIF_BSTATUS_PWRST_Enum; - -/* ============================================= BLEIF BSTATUS B2MSTATE [0..2] ============================================= */ -typedef enum { /*!< BLEIF_BSTATUS_B2MSTATE */ - BLEIF_BSTATUS_B2MSTATE_RESET = 0, /*!< RESET : Reset State value. */ - BLEIF_BSTATUS_B2MSTATE_Sleep = 1, /*!< Sleep : Sleep state. value. */ - BLEIF_BSTATUS_B2MSTATE_Standby = 2, /*!< Standby : Standby State value. */ - BLEIF_BSTATUS_B2MSTATE_Idle = 3, /*!< Idle : Idle state value. */ - BLEIF_BSTATUS_B2MSTATE_Active = 4, /*!< Active : Active state. value. */ -} BLEIF_BSTATUS_B2MSTATE_Enum; - -/* ======================================================== BLEDBG ========================================================= */ - - -/* =========================================================================================================================== */ -/* ================ CACHECTRL ================ */ -/* =========================================================================================================================== */ - -/* ======================================================= CACHECFG ======================================================== */ -/* =========================================== CACHECTRL CACHECFG CONFIG [4..7] ============================================ */ -typedef enum { /*!< CACHECTRL_CACHECFG_CONFIG */ - CACHECTRL_CACHECFG_CONFIG_W1_128B_512E = 4, /*!< W1_128B_512E : Direct mapped, 128-bit linesize, 512 entries - (4 SRAMs active) value. */ - CACHECTRL_CACHECFG_CONFIG_W2_128B_512E = 5, /*!< W2_128B_512E : Two-way set associative, 128-bit linesize, 512 - entries (8 SRAMs active) value. */ - CACHECTRL_CACHECFG_CONFIG_W1_128B_1024E = 8, /*!< W1_128B_1024E : Direct mapped, 128-bit linesize, 1024 entries - (8 SRAMs active) value. */ -} CACHECTRL_CACHECFG_CONFIG_Enum; - -/* ======================================================= FLASHCFG ======================================================== */ -/* ========================================== CACHECTRL FLASHCFG LPMMODE [12..13] ========================================== */ -typedef enum { /*!< CACHECTRL_FLASHCFG_LPMMODE */ - CACHECTRL_FLASHCFG_LPMMODE_NEVER = 0, /*!< NEVER : High power mode (LPM not used). value. */ - CACHECTRL_FLASHCFG_LPMMODE_STANDBY = 1, /*!< STANDBY : Fast Standby mode. LPM deasserted for read operations, - but asserted while flash IDLE. value. */ - CACHECTRL_FLASHCFG_LPMMODE_ALWAYS = 2, /*!< ALWAYS : Low Power mode. LPM always asserted for reads. LPM_RD_WAIT - must be programmed to accomodate longer read access times. - value. */ -} CACHECTRL_FLASHCFG_LPMMODE_Enum; - -/* ========================================================= CTRL ========================================================== */ -/* =========================================== CACHECTRL CTRL RESET_STAT [1..1] ============================================ */ -typedef enum { /*!< CACHECTRL_CTRL_RESET_STAT */ - CACHECTRL_CTRL_RESET_STAT_CLEAR = 1, /*!< CLEAR : Clear Cache Stats value. */ -} CACHECTRL_CTRL_RESET_STAT_Enum; - -/* ======================================================= NCR0START ======================================================= */ -/* ======================================================== NCR0END ======================================================== */ -/* ======================================================= NCR1START ======================================================= */ -/* ======================================================== NCR1END ======================================================== */ -/* ========================================================= DMON0 ========================================================= */ -/* ========================================================= DMON1 ========================================================= */ -/* ========================================================= DMON2 ========================================================= */ -/* ========================================================= DMON3 ========================================================= */ -/* ========================================================= IMON0 ========================================================= */ -/* ========================================================= IMON1 ========================================================= */ -/* ========================================================= IMON2 ========================================================= */ -/* ========================================================= IMON3 ========================================================= */ - - -/* =========================================================================================================================== */ -/* ================ CLKGEN ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= CALXT ========================================================= */ -/* ========================================================= CALRC ========================================================= */ -/* ======================================================== ACALCTR ======================================================== */ -/* ========================================================= OCTRL ========================================================= */ -/* =============================================== CLKGEN OCTRL ACAL [8..10] =============================================== */ -typedef enum { /*!< CLKGEN_OCTRL_ACAL */ - CLKGEN_OCTRL_ACAL_DIS = 0, /*!< DIS : Disable Autocalibration value. */ - CLKGEN_OCTRL_ACAL_1024SEC = 2, /*!< 1024SEC : Autocalibrate every 1024 seconds. Once autocalibration - is done, an interrupt will be triggered at the end of 1024 - seconds. value. */ - CLKGEN_OCTRL_ACAL_512SEC = 3, /*!< 512SEC : Autocalibrate every 512 seconds. Once autocalibration - is done, an interrupt will be trigged at the end of 512 - seconds. value. */ - CLKGEN_OCTRL_ACAL_XTFREQ = 6, /*!< XTFREQ : Frequency measurement using XT. The XT clock is normally - considered much more accurate than the LFRC clock source. - value. */ - CLKGEN_OCTRL_ACAL_EXTFREQ = 7, /*!< EXTFREQ : Frequency measurement using external clock. value. */ -} CLKGEN_OCTRL_ACAL_Enum; - -/* =============================================== CLKGEN OCTRL OSEL [7..7] ================================================ */ -typedef enum { /*!< CLKGEN_OCTRL_OSEL */ - CLKGEN_OCTRL_OSEL_RTC_XT = 0, /*!< RTC_XT : RTC uses the XT value. */ - CLKGEN_OCTRL_OSEL_RTC_LFRC = 1, /*!< RTC_LFRC : RTC uses the LFRC value. */ -} CLKGEN_OCTRL_OSEL_Enum; - -/* ================================================ CLKGEN OCTRL FOS [6..6] ================================================ */ -typedef enum { /*!< CLKGEN_OCTRL_FOS */ - CLKGEN_OCTRL_FOS_DIS = 0, /*!< DIS : Disable the oscillator switch on failure function. value. */ - CLKGEN_OCTRL_FOS_EN = 1, /*!< EN : Enable the oscillator switch on failure function. value. */ -} CLKGEN_OCTRL_FOS_Enum; - -/* ============================================== CLKGEN OCTRL STOPRC [1..1] =============================================== */ -typedef enum { /*!< CLKGEN_OCTRL_STOPRC */ - CLKGEN_OCTRL_STOPRC_EN = 0, /*!< EN : Enable the LFRC Oscillator to drive the RTC value. */ - CLKGEN_OCTRL_STOPRC_STOP = 1, /*!< STOP : Stop the LFRC Oscillator when driving the RTC value. */ -} CLKGEN_OCTRL_STOPRC_Enum; - -/* ============================================== CLKGEN OCTRL STOPXT [0..0] =============================================== */ -typedef enum { /*!< CLKGEN_OCTRL_STOPXT */ - CLKGEN_OCTRL_STOPXT_EN = 0, /*!< EN : Enable the XT Oscillator to drive the RTC value. */ - CLKGEN_OCTRL_STOPXT_STOP = 1, /*!< STOP : Stop the XT Oscillator when driving the RTC value. */ -} CLKGEN_OCTRL_STOPXT_Enum; - -/* ======================================================== CLKOUT ========================================================= */ -/* =============================================== CLKGEN CLKOUT CKEN [7..7] =============================================== */ -typedef enum { /*!< CLKGEN_CLKOUT_CKEN */ - CLKGEN_CLKOUT_CKEN_DIS = 0, /*!< DIS : Disable CLKOUT value. */ - CLKGEN_CLKOUT_CKEN_EN = 1, /*!< EN : Enable CLKOUT value. */ -} CLKGEN_CLKOUT_CKEN_Enum; - -/* ============================================== CLKGEN CLKOUT CKSEL [0..5] =============================================== */ -typedef enum { /*!< CLKGEN_CLKOUT_CKSEL */ - CLKGEN_CLKOUT_CKSEL_LFRC = 0, /*!< LFRC : LFRC value. */ - CLKGEN_CLKOUT_CKSEL_XT_DIV2 = 1, /*!< XT_DIV2 : XT / 2 value. */ - CLKGEN_CLKOUT_CKSEL_XT_DIV4 = 2, /*!< XT_DIV4 : XT / 4 value. */ - CLKGEN_CLKOUT_CKSEL_XT_DIV8 = 3, /*!< XT_DIV8 : XT / 8 value. */ - CLKGEN_CLKOUT_CKSEL_XT_DIV16 = 4, /*!< XT_DIV16 : XT / 16 value. */ - CLKGEN_CLKOUT_CKSEL_XT_DIV32 = 5, /*!< XT_DIV32 : XT / 32 value. */ - CLKGEN_CLKOUT_CKSEL_RTC_1Hz = 16, /*!< RTC_1Hz : 1 Hz as selected in RTC value. */ - CLKGEN_CLKOUT_CKSEL_XT_DIV2M = 22, /*!< XT_DIV2M : XT / 2^21 value. */ - CLKGEN_CLKOUT_CKSEL_XT = 23, /*!< XT : XT value. */ - CLKGEN_CLKOUT_CKSEL_CG_100Hz = 24, /*!< CG_100Hz : 100 Hz as selected in CLKGEN value. */ - CLKGEN_CLKOUT_CKSEL_HFRC = 25, /*!< HFRC : HFRC value. */ - CLKGEN_CLKOUT_CKSEL_HFRC_DIV4 = 26, /*!< HFRC_DIV4 : HFRC / 4 value. */ - CLKGEN_CLKOUT_CKSEL_HFRC_DIV8 = 27, /*!< HFRC_DIV8 : HFRC / 8 value. */ - CLKGEN_CLKOUT_CKSEL_HFRC_DIV16 = 28, /*!< HFRC_DIV16 : HFRC / 16 value. */ - CLKGEN_CLKOUT_CKSEL_HFRC_DIV64 = 29, /*!< HFRC_DIV64 : HFRC / 64 value. */ - CLKGEN_CLKOUT_CKSEL_HFRC_DIV128 = 30, /*!< HFRC_DIV128 : HFRC / 128 value. */ - CLKGEN_CLKOUT_CKSEL_HFRC_DIV256 = 31, /*!< HFRC_DIV256 : HFRC / 256 value. */ - CLKGEN_CLKOUT_CKSEL_HFRC_DIV512 = 32, /*!< HFRC_DIV512 : HFRC / 512 value. */ - CLKGEN_CLKOUT_CKSEL_FLASH_CLK = 34, /*!< FLASH_CLK : Flash Clock value. */ - CLKGEN_CLKOUT_CKSEL_LFRC_DIV2 = 35, /*!< LFRC_DIV2 : LFRC / 2 value. */ - CLKGEN_CLKOUT_CKSEL_LFRC_DIV32 = 36, /*!< LFRC_DIV32 : LFRC / 32 value. */ - CLKGEN_CLKOUT_CKSEL_LFRC_DIV512 = 37, /*!< LFRC_DIV512 : LFRC / 512 value. */ - CLKGEN_CLKOUT_CKSEL_LFRC_DIV32K = 38, /*!< LFRC_DIV32K : LFRC / 32768 value. */ - CLKGEN_CLKOUT_CKSEL_XT_DIV256 = 39, /*!< XT_DIV256 : XT / 256 value. */ - CLKGEN_CLKOUT_CKSEL_XT_DIV8K = 40, /*!< XT_DIV8K : XT / 8192 value. */ - CLKGEN_CLKOUT_CKSEL_XT_DIV64K = 41, /*!< XT_DIV64K : XT / 2^16 value. */ - CLKGEN_CLKOUT_CKSEL_ULFRC_DIV16 = 42, /*!< ULFRC_DIV16 : Uncal LFRC / 16 value. */ - CLKGEN_CLKOUT_CKSEL_ULFRC_DIV128 = 43, /*!< ULFRC_DIV128 : Uncal LFRC / 128 value. */ - CLKGEN_CLKOUT_CKSEL_ULFRC_1Hz = 44, /*!< ULFRC_1Hz : Uncal LFRC / 1024 value. */ - CLKGEN_CLKOUT_CKSEL_ULFRC_DIV4K = 45, /*!< ULFRC_DIV4K : Uncal LFRC / 4096 value. */ - CLKGEN_CLKOUT_CKSEL_ULFRC_DIV1M = 46, /*!< ULFRC_DIV1M : Uncal LFRC / 2^20 value. */ - CLKGEN_CLKOUT_CKSEL_HFRC_DIV64K = 47, /*!< HFRC_DIV64K : HFRC / 2^16 value. */ - CLKGEN_CLKOUT_CKSEL_HFRC_DIV16M = 48, /*!< HFRC_DIV16M : HFRC / 2^24 value. */ - CLKGEN_CLKOUT_CKSEL_LFRC_DIV1M = 49, /*!< LFRC_DIV1M : LFRC / 2^20 value. */ - CLKGEN_CLKOUT_CKSEL_HFRCNE = 50, /*!< HFRCNE : HFRC (not autoenabled) value. */ - CLKGEN_CLKOUT_CKSEL_HFRCNE_DIV8 = 51, /*!< HFRCNE_DIV8 : HFRC / 8 (not autoenabled) value. */ - CLKGEN_CLKOUT_CKSEL_XTNE = 53, /*!< XTNE : XT (not autoenabled) value. */ - CLKGEN_CLKOUT_CKSEL_XTNE_DIV16 = 54, /*!< XTNE_DIV16 : XT / 16 (not autoenabled) value. */ - CLKGEN_CLKOUT_CKSEL_LFRCNE_DIV32 = 55, /*!< LFRCNE_DIV32 : LFRC / 32 (not autoenabled) value. */ - CLKGEN_CLKOUT_CKSEL_LFRCNE = 57, /*!< LFRCNE : LFRC (not autoenabled) - Default for undefined values - value. */ -} CLKGEN_CLKOUT_CKSEL_Enum; - -/* ======================================================== CLKKEY ========================================================= */ -/* ============================================= CLKGEN CLKKEY CLKKEY [0..31] ============================================== */ -typedef enum { /*!< CLKGEN_CLKKEY_CLKKEY */ - CLKGEN_CLKKEY_CLKKEY_Key = 71, /*!< Key : Key value. */ -} CLKGEN_CLKKEY_CLKKEY_Enum; - -/* ========================================================= CCTRL ========================================================= */ -/* ============================================== CLKGEN CCTRL CORESEL [0..0] ============================================== */ -typedef enum { /*!< CLKGEN_CCTRL_CORESEL */ - CLKGEN_CCTRL_CORESEL_HFRC = 0, /*!< HFRC : Core Clock is HFRC value. */ - CLKGEN_CCTRL_CORESEL_HFRC_DIV2 = 1, /*!< HFRC_DIV2 : Core Clock is HFRC / 2 value. */ -} CLKGEN_CCTRL_CORESEL_Enum; - -/* ======================================================== STATUS ========================================================= */ -/* ========================================================= HFADJ ========================================================= */ -/* ============================================ CLKGEN HFADJ HFADJGAIN [21..23] ============================================ */ -typedef enum { /*!< CLKGEN_HFADJ_HFADJGAIN */ - CLKGEN_HFADJ_HFADJGAIN_Gain_of_1 = 0, /*!< Gain_of_1 : HF Adjust with Gain of 1 value. */ - CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_2 = 1, /*!< Gain_of_1_in_2 : HF Adjust with Gain of 0.5 value. */ - CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_4 = 2, /*!< Gain_of_1_in_4 : HF Adjust with Gain of 0.25 value. */ - CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_8 = 3, /*!< Gain_of_1_in_8 : HF Adjust with Gain of 0.125 value. */ - CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_16 = 4, /*!< Gain_of_1_in_16 : HF Adjust with Gain of 0.0625 value. */ - CLKGEN_HFADJ_HFADJGAIN_Gain_of_1_in_32 = 5, /*!< Gain_of_1_in_32 : HF Adjust with Gain of 0.03125 value. */ -} CLKGEN_HFADJ_HFADJGAIN_Enum; - -/* ============================================ CLKGEN HFADJ HFWARMUP [20..20] ============================================= */ -typedef enum { /*!< CLKGEN_HFADJ_HFWARMUP */ - CLKGEN_HFADJ_HFWARMUP_1SEC = 0, /*!< 1SEC : Autoadjust XT warmup period = 1-2 seconds value. */ - CLKGEN_HFADJ_HFWARMUP_2SEC = 1, /*!< 2SEC : Autoadjust XT warmup period = 2-4 seconds value. */ -} CLKGEN_HFADJ_HFWARMUP_Enum; - -/* ============================================== CLKGEN HFADJ HFADJCK [1..3] ============================================== */ -typedef enum { /*!< CLKGEN_HFADJ_HFADJCK */ - CLKGEN_HFADJ_HFADJCK_4SEC = 0, /*!< 4SEC : Autoadjust repeat period = 4 seconds value. */ - CLKGEN_HFADJ_HFADJCK_16SEC = 1, /*!< 16SEC : Autoadjust repeat period = 16 seconds value. */ - CLKGEN_HFADJ_HFADJCK_32SEC = 2, /*!< 32SEC : Autoadjust repeat period = 32 seconds value. */ - CLKGEN_HFADJ_HFADJCK_64SEC = 3, /*!< 64SEC : Autoadjust repeat period = 64 seconds value. */ - CLKGEN_HFADJ_HFADJCK_128SEC = 4, /*!< 128SEC : Autoadjust repeat period = 128 seconds value. */ - CLKGEN_HFADJ_HFADJCK_256SEC = 5, /*!< 256SEC : Autoadjust repeat period = 256 seconds value. */ - CLKGEN_HFADJ_HFADJCK_512SEC = 6, /*!< 512SEC : Autoadjust repeat period = 512 seconds value. */ - CLKGEN_HFADJ_HFADJCK_1024SEC = 7, /*!< 1024SEC : Autoadjust repeat period = 1024 seconds value. */ -} CLKGEN_HFADJ_HFADJCK_Enum; - -/* ============================================== CLKGEN HFADJ HFADJEN [0..0] ============================================== */ -typedef enum { /*!< CLKGEN_HFADJ_HFADJEN */ - CLKGEN_HFADJ_HFADJEN_DIS = 0, /*!< DIS : Disable the HFRC adjustment value. */ - CLKGEN_HFADJ_HFADJEN_EN = 1, /*!< EN : Enable the HFRC adjustment value. */ -} CLKGEN_HFADJ_HFADJEN_Enum; - -/* ====================================================== CLOCKENSTAT ====================================================== */ -/* ======================================== CLKGEN CLOCKENSTAT CLOCKENSTAT [0..31] ========================================= */ -typedef enum { /*!< CLKGEN_CLOCKENSTAT_CLOCKENSTAT */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_ADC_CLKEN = 1, /*!< ADC_CLKEN : Clock enable for the ADC. value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_ACTIVITY_CLKEN = 2,/*!< APBDMA_ACTIVITY_CLKEN : Clock enable for the APBDMA ACTIVITY - value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_AOH_CLKEN = 4,/*!< APBDMA_AOH_CLKEN : Clock enable for the APBDMA AOH DOMAIN value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_AOL_CLKEN = 8,/*!< APBDMA_AOL_CLKEN : Clock enable for the APBDMA AOL DOMAIN value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_APB_CLKEN = 16,/*!< APBDMA_APB_CLKEN : Clock enable for the APBDMA_APB value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_BLEL_CLKEN = 32,/*!< APBDMA_BLEL_CLKEN : Clock enable for the APBDMA_BLEL value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_HCPA_CLKEN = 64,/*!< APBDMA_HCPA_CLKEN : Clock enable for the APBDMA_HCPA value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_HCPB_CLKEN = 128,/*!< APBDMA_HCPB_CLKEN : Clock enable for the APBDMA_HCPB value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_HCPC_CLKEN = 256,/*!< APBDMA_HCPC_CLKEN : Clock enable for the APBDMA_HCPC value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_MSPI_CLKEN = 512,/*!< APBDMA_MSPI_CLKEN : Clock enable for the APBDMA_MSPI value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_APBDMA_PDM_CLKEN = 1024,/*!< APBDMA_PDM_CLKEN : Clock enable for the APBDMA_PDM value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_BLEIF_CLK_CLKEN = 2048,/*!< BLEIF_CLK_CLKEN : Clock enable for the BLEIF value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_BLEIF_CLK32K_CLKEN = 4096,/*!< BLEIF_CLK32K_CLKEN : Clock enable for the BLEIF 32khZ CLOCK - value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER_CLKEN = 8192,/*!< CTIMER_CLKEN : Clock enable for the CTIMER BLOCK value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER0A_CLKEN = 16384,/*!< CTIMER0A_CLKEN : Clock enable for the CTIMER0A value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER0B_CLKEN = 32768,/*!< CTIMER0B_CLKEN : Clock enable for the CTIMER0B value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER1A_CLKEN = 65536,/*!< CTIMER1A_CLKEN : Clock enable for the CTIMER1A value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER1B_CLKEN = 131072,/*!< CTIMER1B_CLKEN : Clock enable for the CTIMER1B value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER2A_CLKEN = 262144,/*!< CTIMER2A_CLKEN : Clock enable for the CTIMER2A value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER2B_CLKEN = 524288,/*!< CTIMER2B_CLKEN : Clock enable for the CTIMER2B value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER3A_CLKEN = 1048576,/*!< CTIMER3A_CLKEN : Clock enable for the CTIMER3A value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER3B_CLKEN = 2097152,/*!< CTIMER3B_CLKEN : Clock enable for the CTIMER3B value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER4A_CLKEN = 4194304,/*!< CTIMER4A_CLKEN : Clock enable for the CTIMER4A value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER4B_CLKEN = 8388608,/*!< CTIMER4B_CLKEN : Clock enable for the CTIMER4B value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER5A_CLKEN = 16777216,/*!< CTIMER5A_CLKEN : Clock enable for the CTIMER5A value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER5B_CLKEN = 33554432,/*!< CTIMER5B_CLKEN : Clock enable for the CTIMER5B value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER6A_CLKEN = 67108864,/*!< CTIMER6A_CLKEN : Clock enable for the CTIMER6A value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER6B_CLKEN = 134217728,/*!< CTIMER6B_CLKEN : Clock enable for the CTIMER6B value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER7A_CLKEN = 268435456,/*!< CTIMER7A_CLKEN : Clock enable for the CTIMER7A value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_CTIMER7B_CLKEN = 536870912,/*!< CTIMER7B_CLKEN : Clock enable for the CTIMER7B value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_DAP_CLKEN = 1073741824,/*!< DAP_CLKEN : Clock enable for the DAP value. */ - CLKGEN_CLOCKENSTAT_CLOCKENSTAT_IOMSTRIFC0_CLKEN = -2147483648,/*!< IOMSTRIFC0_CLKEN : Clock enable for the IOMSTRIFC0 value. */ -} CLKGEN_CLOCKENSTAT_CLOCKENSTAT_Enum; - -/* ===================================================== CLOCKEN2STAT ====================================================== */ -/* ======================================= CLKGEN CLOCKEN2STAT CLOCKEN2STAT [0..31] ======================================== */ -typedef enum { /*!< CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC1_CLKEN = 1,/*!< IOMSTRIFC1_CLKEN : Clock enable for the IO MASTER 1 IFC INTERFACE - value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC2_CLKEN = 2,/*!< IOMSTRIFC2_CLKEN : Clock enable for the IO MASTER 2 IFC INTERFACE - value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC3_CLKEN = 4,/*!< IOMSTRIFC3_CLKEN : Clock enable for the IO MASTER 3 IFC INTERFACE - value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC4_CLKEN = 8,/*!< IOMSTRIFC4_CLKEN : Clock enable for the IO MASTER 4 IFC INTERFACE - value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_IOMSTRIFC5_CLKEN = 16,/*!< IOMSTRIFC5_CLKEN : Clock enable for the IO MASTER 5 IFC INTERFACE - value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_PDM_CLKEN = 32,/*!< PDM_CLKEN : Clock enable for the PDM value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_PDMIFC_CLKEN = 64,/*!< PDMIFC_CLKEN : Clock enable for the PDM INTERFACE value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_PWRCTRL_CLKEN = 128,/*!< PWRCTRL_CLKEN : Clock enable for the PWRCTRL value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_RSTGEN_CLKEN = 256,/*!< RSTGEN_CLKEN : Clock enable for the RSTGEN value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_SCARD_CLKEN = 512,/*!< SCARD_CLKEN : Clock enable for the SCARD value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_SCARD_ALTAPB_CLKEN = 1024,/*!< SCARD_ALTAPB_CLKEN : Clock enable for the SCARD ALTAPB value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_STIMER_CNT_CLKEN = 2048,/*!< STIMER_CNT_CLKEN : Clock enable for the STIMER_CNT_CLKEN value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_TPIU_CLKEN = 4096,/*!< TPIU_CLKEN : Clock enable for the TPIU_CLKEN value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_UART0HF_CLKEN = 8192,/*!< UART0HF_CLKEN : Clock enable for the UART0 HF value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_UART1HF_CLKEN = 16384,/*!< UART1HF_CLKEN : Clock enable for the UART1 HF value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_XT_32KHZ_EN = 1073741824,/*!< XT_32KHZ_EN : Clock enable for the XT 32KHZ value. */ - CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_FORCEHFRC = -2147483648,/*!< FORCEHFRC : HFRC is forced on Status. value. */ -} CLKGEN_CLOCKEN2STAT_CLOCKEN2STAT_Enum; - -/* ===================================================== CLOCKEN3STAT ====================================================== */ -/* ======================================= CLKGEN CLOCKEN3STAT CLOCKEN3STAT [0..31] ======================================== */ -typedef enum { /*!< CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT */ - CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_XTAL_enabled = 16777216,/*!< XTAL_enabled : XTAL is enabled value. */ - CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_HFRC_enabled = 33554432,/*!< HFRC_enabled : HFRC is enabled value. */ - CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_HFADJEN = 67108864,/*!< HFADJEN : HFRC Adjust enabled value. */ - CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_HFRC_en_out = 134217728,/*!< HFRC_en_out : HFRC Enabled out value. */ - CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_RTC_XT = 268435456,/*!< RTC_XT : RTC use XT value. */ - CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_clkout_xtal_en = 536870912,/*!< clkout_xtal_en : XTAL clkout enabled value. */ - CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_clkout_hfrc_en = 1073741824,/*!< clkout_hfrc_en : HFRC clkout enabled value. */ - CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_flashclk_en = -2147483648,/*!< flashclk_en : Flash clk is enabled value. */ -} CLKGEN_CLOCKEN3STAT_CLOCKEN3STAT_Enum; - -/* ======================================================= FREQCTRL ======================================================== */ -/* ============================================ CLKGEN FREQCTRL BURSTREQ [0..0] ============================================ */ -typedef enum { /*!< CLKGEN_FREQCTRL_BURSTREQ */ - CLKGEN_FREQCTRL_BURSTREQ_DIS = 0, /*!< DIS : Frequency for ARM core stays at 48MHz value. */ - CLKGEN_FREQCTRL_BURSTREQ_EN = 1, /*!< EN : Frequency for ARM core is increased to 96MHz value. */ -} CLKGEN_FREQCTRL_BURSTREQ_Enum; - -/* ===================================================== BLEBUCKTONADJ ===================================================== */ -/* ===================================== CLKGEN BLEBUCKTONADJ ZEROLENDETECTEN [27..27] ===================================== */ -typedef enum { /*!< CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_DIS = 0, /*!< DIS : Disable Zero Length Detect value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_EN = 1, /*!< EN : Enable Zero Length Detect value. */ -} CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTEN_Enum; - -/* ==================================== CLKGEN BLEBUCKTONADJ ZEROLENDETECTTRIM [23..26] ==================================== */ -typedef enum { /*!< CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetF = 15,/*!< SetF : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 81us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetE = 14,/*!< SetE : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 75.6us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetD = 13,/*!< SetD : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 70.2us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetC = 12,/*!< SetC : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 64.8us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetB = 11,/*!< SetB : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 59.4us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_SetA = 10,/*!< SetA : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 54.0us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set9 = 9,/*!< Set9 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 48.6us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set8 = 8,/*!< Set8 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 43.2us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set7 = 7,/*!< Set7 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 37.8us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set6 = 6,/*!< Set6 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 32.4us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set5 = 5,/*!< Set5 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 27.0us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set4 = 4,/*!< Set4 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 21.6us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set3 = 3,/*!< Set3 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 16.2us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set2 = 2,/*!< Set2 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 10.8us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set1 = 1,/*!< Set1 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 5.4us (10 percent margin of error) or more value. */ - CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Set0 = 0,/*!< Set0 : Indicator send when the BLE BUCK asserts blebuck_comp1 - for about 2.0us (10 percent margin of error) or more value. */ -} CLKGEN_BLEBUCKTONADJ_ZEROLENDETECTTRIM_Enum; - -/* ======================================= CLKGEN BLEBUCKTONADJ TONADJUSTEN [22..22] ======================================= */ -typedef enum { /*!< CLKGEN_BLEBUCKTONADJ_TONADJUSTEN */ - CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_DIS = 0, /*!< DIS : Disable Adjust for BLE BUCK TON trim value. */ - CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_EN = 1, /*!< EN : Enable Adjust for BLE BUCK TON trim value. */ -} CLKGEN_BLEBUCKTONADJ_TONADJUSTEN_Enum; - -/* ===================================== CLKGEN BLEBUCKTONADJ TONADJUSTPERIOD [20..21] ===================================== */ -typedef enum { /*!< CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD */ - CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_HFRC_3KHz = 3,/*!< HFRC_3KHz : Adjust done for every 1 3KHz period value. */ - CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_HFRC_12KHz = 2,/*!< HFRC_12KHz : Adjust done for every 1 12KHz period value. */ - CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_HFRC_47KHz = 1,/*!< HFRC_47KHz : Adjust done for every 1 47KHz period value. */ - CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_HFRC_94KHz = 0,/*!< HFRC_94KHz : Adjust done for every 1 94KHz period value. */ -} CLKGEN_BLEBUCKTONADJ_TONADJUSTPERIOD_Enum; - -/* ======================================================= INTRPTEN ======================================================== */ -/* ====================================================== INTRPTSTAT ======================================================= */ -/* ======================================================= INTRPTCLR ======================================================= */ -/* ======================================================= INTRPTSET ======================================================= */ - - -/* =========================================================================================================================== */ -/* ================ CTIMER ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= TMR0 ========================================================== */ -/* ======================================================== CMPRA0 ========================================================= */ -/* ======================================================== CMPRB0 ========================================================= */ -/* ========================================================= CTRL0 ========================================================= */ -/* ============================================= CTIMER CTRL0 CTLINK0 [31..31] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_CTLINK0 */ - CTIMER_CTRL0_CTLINK0_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A0/B0 timers as two independent 16-bit - timers (default). value. */ - CTIMER_CTRL0_CTLINK0_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A0/B0 timers into a single 32-bit timer. - value. */ -} CTIMER_CTRL0_CTLINK0_Enum; - -/* ============================================ CTIMER CTRL0 TMRB0POL [28..28] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRB0POL */ - CTIMER_CTRL0_TMRB0POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB0 pin is the same as the - timer output. value. */ - CTIMER_CTRL0_TMRB0POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB0 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL0_TMRB0POL_Enum; - -/* ============================================ CTIMER CTRL0 TMRB0CLR [27..27] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRB0CLR */ - CTIMER_CTRL0_TMRB0CLR_RUN = 0, /*!< RUN : Allow counter/timer B0 to run value. */ - CTIMER_CTRL0_TMRB0CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B0 at 0x0000. value. */ -} CTIMER_CTRL0_TMRB0CLR_Enum; - -/* ============================================ CTIMER CTRL0 TMRB0IE1 [26..26] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRB0IE1 */ - CTIMER_CTRL0_TMRB0IE1_DIS = 0, /*!< DIS : Disable counter/timer B0 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL0_TMRB0IE1_EN = 1, /*!< EN : Enable counter/timer B0 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL0_TMRB0IE1_Enum; - -/* ============================================ CTIMER CTRL0 TMRB0IE0 [25..25] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRB0IE0 */ - CTIMER_CTRL0_TMRB0IE0_DIS = 0, /*!< DIS : Disable counter/timer B0 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL0_TMRB0IE0_EN = 1, /*!< EN : Enable counter/timer B0 to generate an interrupt based - on COMPR0 value. */ -} CTIMER_CTRL0_TMRB0IE0_Enum; - -/* ============================================= CTIMER CTRL0 TMRB0FN [22..24] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRB0FN */ - CTIMER_CTRL0_TMRB0FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0B0, stop. value. */ - CTIMER_CTRL0_TMRB0FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0B0, restart. value. */ - CTIMER_CTRL0_TMRB0FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B0, assert, - count to CMPR1B0, deassert, stop. value. */ - CTIMER_CTRL0_TMRB0FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B0, assert, count - to CMPR1B0, deassert, restart. value. */ - CTIMER_CTRL0_TMRB0FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL0_TMRB0FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL0_TMRB0FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL0_TMRB0FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL0_TMRB0FN_Enum; - -/* ============================================ CTIMER CTRL0 TMRB0CLK [17..21] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRB0CLK */ - CTIMER_CTRL0_TMRB0CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ - CTIMER_CTRL0_TMRB0CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL0_TMRB0CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL0_TMRB0CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL0_TMRB0CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL0_TMRB0CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL0_TMRB0CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL0_TMRB0CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL0_TMRB0CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL0_TMRB0CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL0_TMRB0CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL0_TMRB0CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL0_TMRB0CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL0_TMRB0CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL0_TMRB0CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL0_TMRB0CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL0_TMRB0CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL0_TMRB0CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL0_TMRB0CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL0_TMRB0CLK_CTMRA0 = 20, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ - CTIMER_CTRL0_TMRB0CLK_CTMRB1 = 21, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL0_TMRB0CLK_CTMRA1 = 22, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ - CTIMER_CTRL0_TMRB0CLK_CTMRA2 = 23, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ - CTIMER_CTRL0_TMRB0CLK_CTMRB2 = 24, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL0_TMRB0CLK_CTMRB3 = 25, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL0_TMRB0CLK_CTMRB4 = 26, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL0_TMRB0CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL0_TMRB0CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL0_TMRB0CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL0_TMRB0CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL0_TMRB0CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL0_TMRB0CLK_Enum; - -/* ============================================= CTIMER CTRL0 TMRB0EN [16..16] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRB0EN */ - CTIMER_CTRL0_TMRB0EN_DIS = 0, /*!< DIS : Counter/Timer B0 Disable. value. */ - CTIMER_CTRL0_TMRB0EN_EN = 1, /*!< EN : Counter/Timer B0 Enable. value. */ -} CTIMER_CTRL0_TMRB0EN_Enum; - -/* ============================================ CTIMER CTRL0 TMRA0POL [12..12] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRA0POL */ - CTIMER_CTRL0_TMRA0POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA0 pin is the same as the - timer output. value. */ - CTIMER_CTRL0_TMRA0POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA0 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL0_TMRA0POL_Enum; - -/* ============================================ CTIMER CTRL0 TMRA0CLR [11..11] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRA0CLR */ - CTIMER_CTRL0_TMRA0CLR_RUN = 0, /*!< RUN : Allow counter/timer A0 to run value. */ - CTIMER_CTRL0_TMRA0CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A0 at 0x0000. value. */ -} CTIMER_CTRL0_TMRA0CLR_Enum; - -/* ============================================ CTIMER CTRL0 TMRA0IE1 [10..10] ============================================= */ -typedef enum { /*!< CTIMER_CTRL0_TMRA0IE1 */ - CTIMER_CTRL0_TMRA0IE1_DIS = 0, /*!< DIS : Disable counter/timer A0 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL0_TMRA0IE1_EN = 1, /*!< EN : Enable counter/timer A0 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL0_TMRA0IE1_Enum; - -/* ============================================= CTIMER CTRL0 TMRA0IE0 [9..9] ============================================== */ -typedef enum { /*!< CTIMER_CTRL0_TMRA0IE0 */ - CTIMER_CTRL0_TMRA0IE0_DIS = 0, /*!< DIS : Disable counter/timer A0 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL0_TMRA0IE0_EN = 1, /*!< EN : Enable counter/timer A0 to generate an interrupt based - on COMPR0. value. */ -} CTIMER_CTRL0_TMRA0IE0_Enum; - -/* ============================================== CTIMER CTRL0 TMRA0FN [6..8] ============================================== */ -typedef enum { /*!< CTIMER_CTRL0_TMRA0FN */ - CTIMER_CTRL0_TMRA0FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0A0, stop. value. */ - CTIMER_CTRL0_TMRA0FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0A0, restart. value. */ - CTIMER_CTRL0_TMRA0FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A0, assert, - count to CMPR1A0, deassert, stop. value. */ - CTIMER_CTRL0_TMRA0FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A0, assert, count - to CMPR1A0, deassert, restart. value. */ - CTIMER_CTRL0_TMRA0FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL0_TMRA0FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL0_TMRA0FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL0_TMRA0FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL0_TMRA0FN_Enum; - -/* ============================================= CTIMER CTRL0 TMRA0CLK [1..5] ============================================== */ -typedef enum { /*!< CTIMER_CTRL0_TMRA0CLK */ - CTIMER_CTRL0_TMRA0CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ - CTIMER_CTRL0_TMRA0CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL0_TMRA0CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL0_TMRA0CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL0_TMRA0CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL0_TMRA0CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL0_TMRA0CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL0_TMRA0CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL0_TMRA0CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL0_TMRA0CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL0_TMRA0CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL0_TMRA0CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL0_TMRA0CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL0_TMRA0CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL0_TMRA0CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL0_TMRA0CLK_HCLK_DIV4 = 15, /*!< HCLK_DIV4 : Clock source is HCLK / 4. value. */ - CTIMER_CTRL0_TMRA0CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL0_TMRA0CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL0_TMRA0CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL0_TMRA0CLK_CTMRB0 = 20, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL0_TMRA0CLK_CTMRA1 = 21, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ - CTIMER_CTRL0_TMRA0CLK_CTMRB1 = 22, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL0_TMRA0CLK_CTMRA2 = 23, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ - CTIMER_CTRL0_TMRA0CLK_CTMRB2 = 24, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL0_TMRA0CLK_CTMRB3 = 25, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL0_TMRA0CLK_CTMRB4 = 26, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL0_TMRA0CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL0_TMRA0CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL0_TMRA0CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL0_TMRA0CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL0_TMRA0CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL0_TMRA0CLK_Enum; - -/* ============================================== CTIMER CTRL0 TMRA0EN [0..0] ============================================== */ -typedef enum { /*!< CTIMER_CTRL0_TMRA0EN */ - CTIMER_CTRL0_TMRA0EN_DIS = 0, /*!< DIS : Counter/Timer A0 Disable. value. */ - CTIMER_CTRL0_TMRA0EN_EN = 1, /*!< EN : Counter/Timer A0 Enable. value. */ -} CTIMER_CTRL0_TMRA0EN_Enum; - -/* ======================================================= CMPRAUXA0 ======================================================= */ -/* ======================================================= CMPRAUXB0 ======================================================= */ -/* ========================================================= AUX0 ========================================================== */ -/* ============================================ CTIMER AUX0 TMRB0EN23 [30..30] ============================================= */ -typedef enum { /*!< CTIMER_AUX0_TMRB0EN23 */ - CTIMER_AUX0_TMRB0EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX0_TMRB0EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX0_TMRB0EN23_Enum; - -/* ============================================ CTIMER AUX0 TMRB0POL23 [29..29] ============================================ */ -typedef enum { /*!< CTIMER_AUX0_TMRB0POL23 */ - CTIMER_AUX0_TMRB0POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX0_TMRB0POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX0_TMRB0POL23_Enum; - -/* ============================================ CTIMER AUX0 TMRB0TINV [28..28] ============================================= */ -typedef enum { /*!< CTIMER_AUX0_TMRB0TINV */ - CTIMER_AUX0_TMRB0TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX0_TMRB0TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX0_TMRB0TINV_Enum; - -/* =========================================== CTIMER AUX0 TMRB0NOSYNC [27..27] ============================================ */ -typedef enum { /*!< CTIMER_AUX0_TMRB0NOSYNC */ - CTIMER_AUX0_TMRB0NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX0_TMRB0NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX0_TMRB0NOSYNC_Enum; - -/* ============================================ CTIMER AUX0 TMRB0TRIG [23..26] ============================================= */ -typedef enum { /*!< CTIMER_AUX0_TMRB0TRIG */ - CTIMER_AUX0_TMRB0TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX0_TMRB0TRIG_A0OUT = 1, /*!< A0OUT : Trigger source is CTIMERA0 OUT. value. */ - CTIMER_AUX0_TMRB0TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX0_TMRB0TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX0_TMRB0TRIG_B2OUT = 4, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ - CTIMER_AUX0_TMRB0TRIG_B5OUT = 5, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ - CTIMER_AUX0_TMRB0TRIG_A4OUT = 6, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ - CTIMER_AUX0_TMRB0TRIG_B4OUT = 7, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ - CTIMER_AUX0_TMRB0TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX0_TMRB0TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX0_TMRB0TRIG_B7OUT2 = 10, /*!< B7OUT2 : Trigger source is CTIMERB7 OUT2. value. */ - CTIMER_AUX0_TMRB0TRIG_A2OUT2 = 11, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ - CTIMER_AUX0_TMRB0TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX0_TMRB0TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX0_TMRB0TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ - CTIMER_AUX0_TMRB0TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ -} CTIMER_AUX0_TMRB0TRIG_Enum; - -/* ============================================ CTIMER AUX0 TMRA0EN23 [14..14] ============================================= */ -typedef enum { /*!< CTIMER_AUX0_TMRA0EN23 */ - CTIMER_AUX0_TMRA0EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX0_TMRA0EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX0_TMRA0EN23_Enum; - -/* ============================================ CTIMER AUX0 TMRA0POL23 [13..13] ============================================ */ -typedef enum { /*!< CTIMER_AUX0_TMRA0POL23 */ - CTIMER_AUX0_TMRA0POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX0_TMRA0POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX0_TMRA0POL23_Enum; - -/* ============================================ CTIMER AUX0 TMRA0TINV [12..12] ============================================= */ -typedef enum { /*!< CTIMER_AUX0_TMRA0TINV */ - CTIMER_AUX0_TMRA0TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX0_TMRA0TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX0_TMRA0TINV_Enum; - -/* =========================================== CTIMER AUX0 TMRA0NOSYNC [11..11] ============================================ */ -typedef enum { /*!< CTIMER_AUX0_TMRA0NOSYNC */ - CTIMER_AUX0_TMRA0NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX0_TMRA0NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX0_TMRA0NOSYNC_Enum; - -/* ============================================= CTIMER AUX0 TMRA0TRIG [7..10] ============================================= */ -typedef enum { /*!< CTIMER_AUX0_TMRA0TRIG */ - CTIMER_AUX0_TMRA0TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX0_TMRA0TRIG_B0OUT = 1, /*!< B0OUT : Trigger source is CTIMERB0 OUT. value. */ - CTIMER_AUX0_TMRA0TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX0_TMRA0TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX0_TMRA0TRIG_A1OUT = 4, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ - CTIMER_AUX0_TMRA0TRIG_B1OUT = 5, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ - CTIMER_AUX0_TMRA0TRIG_A5OUT = 6, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ - CTIMER_AUX0_TMRA0TRIG_B5OUT = 7, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ - CTIMER_AUX0_TMRA0TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX0_TMRA0TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX0_TMRA0TRIG_B6OUT2 = 10, /*!< B6OUT2 : Trigger source is CTIMERB6 OUT2. value. */ - CTIMER_AUX0_TMRA0TRIG_A2OUT2 = 11, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ - CTIMER_AUX0_TMRA0TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX0_TMRA0TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX0_TMRA0TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ - CTIMER_AUX0_TMRA0TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ -} CTIMER_AUX0_TMRA0TRIG_Enum; - -/* ========================================================= TMR1 ========================================================== */ -/* ======================================================== CMPRA1 ========================================================= */ -/* ======================================================== CMPRB1 ========================================================= */ -/* ========================================================= CTRL1 ========================================================= */ -/* ============================================= CTIMER CTRL1 CTLINK1 [31..31] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_CTLINK1 */ - CTIMER_CTRL1_CTLINK1_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A1/B1 timers as two independent 16-bit - timers (default). value. */ - CTIMER_CTRL1_CTLINK1_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A1/B1 timers into a single 32-bit timer. - value. */ -} CTIMER_CTRL1_CTLINK1_Enum; - -/* ============================================ CTIMER CTRL1 TMRB1POL [28..28] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRB1POL */ - CTIMER_CTRL1_TMRB1POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB1 pin is the same as the - timer output. value. */ - CTIMER_CTRL1_TMRB1POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB1 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL1_TMRB1POL_Enum; - -/* ============================================ CTIMER CTRL1 TMRB1CLR [27..27] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRB1CLR */ - CTIMER_CTRL1_TMRB1CLR_RUN = 0, /*!< RUN : Allow counter/timer B1 to run value. */ - CTIMER_CTRL1_TMRB1CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B1 at 0x0000. value. */ -} CTIMER_CTRL1_TMRB1CLR_Enum; - -/* ============================================ CTIMER CTRL1 TMRB1IE1 [26..26] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRB1IE1 */ - CTIMER_CTRL1_TMRB1IE1_DIS = 0, /*!< DIS : Disable counter/timer B1 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL1_TMRB1IE1_EN = 1, /*!< EN : Enable counter/timer B1 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL1_TMRB1IE1_Enum; - -/* ============================================ CTIMER CTRL1 TMRB1IE0 [25..25] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRB1IE0 */ - CTIMER_CTRL1_TMRB1IE0_DIS = 0, /*!< DIS : Disable counter/timer B1 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL1_TMRB1IE0_EN = 1, /*!< EN : Enable counter/timer B1 to generate an interrupt based - on COMPR0 value. */ -} CTIMER_CTRL1_TMRB1IE0_Enum; - -/* ============================================= CTIMER CTRL1 TMRB1FN [22..24] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRB1FN */ - CTIMER_CTRL1_TMRB1FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0B1, stop. value. */ - CTIMER_CTRL1_TMRB1FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0B1, restart. value. */ - CTIMER_CTRL1_TMRB1FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B1, assert, - count to CMPR1B1, deassert, stop. value. */ - CTIMER_CTRL1_TMRB1FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B1, assert, count - to CMPR1B1, deassert, restart. value. */ - CTIMER_CTRL1_TMRB1FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL1_TMRB1FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL1_TMRB1FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL1_TMRB1FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL1_TMRB1FN_Enum; - -/* ============================================ CTIMER CTRL1 TMRB1CLK [17..21] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRB1CLK */ - CTIMER_CTRL1_TMRB1CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ - CTIMER_CTRL1_TMRB1CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL1_TMRB1CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL1_TMRB1CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL1_TMRB1CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL1_TMRB1CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL1_TMRB1CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL1_TMRB1CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL1_TMRB1CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL1_TMRB1CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL1_TMRB1CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL1_TMRB1CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL1_TMRB1CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL1_TMRB1CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL1_TMRB1CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL1_TMRB1CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL1_TMRB1CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL1_TMRB1CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL1_TMRB1CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL1_TMRB1CLK_CTMRA1 = 20, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ - CTIMER_CTRL1_TMRB1CLK_CTMRA0 = 21, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ - CTIMER_CTRL1_TMRB1CLK_CTMRB0 = 22, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL1_TMRB1CLK_CTMRA2 = 23, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ - CTIMER_CTRL1_TMRB1CLK_CTMRB2 = 24, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL1_TMRB1CLK_CTMRB3 = 25, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL1_TMRB1CLK_CTMRB4 = 26, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL1_TMRB1CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL1_TMRB1CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL1_TMRB1CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL1_TMRB1CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL1_TMRB1CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL1_TMRB1CLK_Enum; - -/* ============================================= CTIMER CTRL1 TMRB1EN [16..16] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRB1EN */ - CTIMER_CTRL1_TMRB1EN_DIS = 0, /*!< DIS : Counter/Timer B1 Disable. value. */ - CTIMER_CTRL1_TMRB1EN_EN = 1, /*!< EN : Counter/Timer B1 Enable. value. */ -} CTIMER_CTRL1_TMRB1EN_Enum; - -/* ============================================ CTIMER CTRL1 TMRA1POL [12..12] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRA1POL */ - CTIMER_CTRL1_TMRA1POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA1 pin is the same as the - timer output. value. */ - CTIMER_CTRL1_TMRA1POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA1 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL1_TMRA1POL_Enum; - -/* ============================================ CTIMER CTRL1 TMRA1CLR [11..11] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRA1CLR */ - CTIMER_CTRL1_TMRA1CLR_RUN = 0, /*!< RUN : Allow counter/timer A1 to run value. */ - CTIMER_CTRL1_TMRA1CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A1 at 0x0000. value. */ -} CTIMER_CTRL1_TMRA1CLR_Enum; - -/* ============================================ CTIMER CTRL1 TMRA1IE1 [10..10] ============================================= */ -typedef enum { /*!< CTIMER_CTRL1_TMRA1IE1 */ - CTIMER_CTRL1_TMRA1IE1_DIS = 0, /*!< DIS : Disable counter/timer A1 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL1_TMRA1IE1_EN = 1, /*!< EN : Enable counter/timer A1 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL1_TMRA1IE1_Enum; - -/* ============================================= CTIMER CTRL1 TMRA1IE0 [9..9] ============================================== */ -typedef enum { /*!< CTIMER_CTRL1_TMRA1IE0 */ - CTIMER_CTRL1_TMRA1IE0_DIS = 0, /*!< DIS : Disable counter/timer A1 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL1_TMRA1IE0_EN = 1, /*!< EN : Enable counter/timer A1 to generate an interrupt based - on COMPR0. value. */ -} CTIMER_CTRL1_TMRA1IE0_Enum; - -/* ============================================== CTIMER CTRL1 TMRA1FN [6..8] ============================================== */ -typedef enum { /*!< CTIMER_CTRL1_TMRA1FN */ - CTIMER_CTRL1_TMRA1FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0A1, stop. value. */ - CTIMER_CTRL1_TMRA1FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0A1, restart. value. */ - CTIMER_CTRL1_TMRA1FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A1, assert, - count to CMPR1A1, deassert, stop. value. */ - CTIMER_CTRL1_TMRA1FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A1, assert, count - to CMPR1A1, deassert, restart. value. */ - CTIMER_CTRL1_TMRA1FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL1_TMRA1FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL1_TMRA1FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL1_TMRA1FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL1_TMRA1FN_Enum; - -/* ============================================= CTIMER CTRL1 TMRA1CLK [1..5] ============================================== */ -typedef enum { /*!< CTIMER_CTRL1_TMRA1CLK */ - CTIMER_CTRL1_TMRA1CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ - CTIMER_CTRL1_TMRA1CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL1_TMRA1CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL1_TMRA1CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL1_TMRA1CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL1_TMRA1CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL1_TMRA1CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL1_TMRA1CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL1_TMRA1CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL1_TMRA1CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL1_TMRA1CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL1_TMRA1CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL1_TMRA1CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL1_TMRA1CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL1_TMRA1CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL1_TMRA1CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL1_TMRA1CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL1_TMRA1CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL1_TMRA1CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL1_TMRA1CLK_CTMRB1 = 20, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL1_TMRA1CLK_CTMRA0 = 21, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ - CTIMER_CTRL1_TMRA1CLK_CTMRB0 = 22, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL1_TMRA1CLK_CTMRA2 = 23, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ - CTIMER_CTRL1_TMRA1CLK_CTMRB2 = 24, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL1_TMRA1CLK_CTMRB3 = 25, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL1_TMRA1CLK_CTMRB4 = 26, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL1_TMRA1CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL1_TMRA1CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL1_TMRA1CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL1_TMRA1CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL1_TMRA1CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL1_TMRA1CLK_Enum; - -/* ============================================== CTIMER CTRL1 TMRA1EN [0..0] ============================================== */ -typedef enum { /*!< CTIMER_CTRL1_TMRA1EN */ - CTIMER_CTRL1_TMRA1EN_DIS = 0, /*!< DIS : Counter/Timer A1 Disable. value. */ - CTIMER_CTRL1_TMRA1EN_EN = 1, /*!< EN : Counter/Timer A1 Enable. value. */ -} CTIMER_CTRL1_TMRA1EN_Enum; - -/* ======================================================= CMPRAUXA1 ======================================================= */ -/* ======================================================= CMPRAUXB1 ======================================================= */ -/* ========================================================= AUX1 ========================================================== */ -/* ============================================ CTIMER AUX1 TMRB1EN23 [30..30] ============================================= */ -typedef enum { /*!< CTIMER_AUX1_TMRB1EN23 */ - CTIMER_AUX1_TMRB1EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX1_TMRB1EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX1_TMRB1EN23_Enum; - -/* ============================================ CTIMER AUX1 TMRB1POL23 [29..29] ============================================ */ -typedef enum { /*!< CTIMER_AUX1_TMRB1POL23 */ - CTIMER_AUX1_TMRB1POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX1_TMRB1POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX1_TMRB1POL23_Enum; - -/* ============================================ CTIMER AUX1 TMRB1TINV [28..28] ============================================= */ -typedef enum { /*!< CTIMER_AUX1_TMRB1TINV */ - CTIMER_AUX1_TMRB1TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX1_TMRB1TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX1_TMRB1TINV_Enum; - -/* =========================================== CTIMER AUX1 TMRB1NOSYNC [27..27] ============================================ */ -typedef enum { /*!< CTIMER_AUX1_TMRB1NOSYNC */ - CTIMER_AUX1_TMRB1NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX1_TMRB1NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX1_TMRB1NOSYNC_Enum; - -/* ============================================ CTIMER AUX1 TMRB1TRIG [23..26] ============================================= */ -typedef enum { /*!< CTIMER_AUX1_TMRB1TRIG */ - CTIMER_AUX1_TMRB1TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX1_TMRB1TRIG_A1OUT = 1, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ - CTIMER_AUX1_TMRB1TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX1_TMRB1TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX1_TMRB1TRIG_A6OUT = 4, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ - CTIMER_AUX1_TMRB1TRIG_B6OUT = 5, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ - CTIMER_AUX1_TMRB1TRIG_A0OUT = 6, /*!< A0OUT : Trigger source is CTIMERA0 OUT. value. */ - CTIMER_AUX1_TMRB1TRIG_B0OUT = 7, /*!< B0OUT : Trigger source is CTIMERB0 OUT. value. */ - CTIMER_AUX1_TMRB1TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX1_TMRB1TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX1_TMRB1TRIG_A4OUT2 = 10, /*!< A4OUT2 : Trigger source is CTIMERA4 OUT2. value. */ - CTIMER_AUX1_TMRB1TRIG_B4OUT2 = 11, /*!< B4OUT2 : Trigger source is CTIMERB4 OUT2. value. */ - CTIMER_AUX1_TMRB1TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX1_TMRB1TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX1_TMRB1TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ - CTIMER_AUX1_TMRB1TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ -} CTIMER_AUX1_TMRB1TRIG_Enum; - -/* ============================================ CTIMER AUX1 TMRA1EN23 [14..14] ============================================= */ -typedef enum { /*!< CTIMER_AUX1_TMRA1EN23 */ - CTIMER_AUX1_TMRA1EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX1_TMRA1EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX1_TMRA1EN23_Enum; - -/* ============================================ CTIMER AUX1 TMRA1POL23 [13..13] ============================================ */ -typedef enum { /*!< CTIMER_AUX1_TMRA1POL23 */ - CTIMER_AUX1_TMRA1POL23_NORMAL = 0, /*!< NORMAL : Upper output normal polarity value. */ - CTIMER_AUX1_TMRA1POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX1_TMRA1POL23_Enum; - -/* ============================================ CTIMER AUX1 TMRA1TINV [12..12] ============================================= */ -typedef enum { /*!< CTIMER_AUX1_TMRA1TINV */ - CTIMER_AUX1_TMRA1TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX1_TMRA1TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX1_TMRA1TINV_Enum; - -/* =========================================== CTIMER AUX1 TMRA1NOSYNC [11..11] ============================================ */ -typedef enum { /*!< CTIMER_AUX1_TMRA1NOSYNC */ - CTIMER_AUX1_TMRA1NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX1_TMRA1NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX1_TMRA1NOSYNC_Enum; - -/* ============================================= CTIMER AUX1 TMRA1TRIG [7..10] ============================================= */ -typedef enum { /*!< CTIMER_AUX1_TMRA1TRIG */ - CTIMER_AUX1_TMRA1TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX1_TMRA1TRIG_B1OUT = 1, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ - CTIMER_AUX1_TMRA1TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX1_TMRA1TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX1_TMRA1TRIG_A0OUT = 4, /*!< A0OUT : Trigger source is CTIMERA0 OUT. value. */ - CTIMER_AUX1_TMRA1TRIG_B0OUT = 5, /*!< B0OUT : Trigger source is CTIMERB0 OUT. value. */ - CTIMER_AUX1_TMRA1TRIG_A5OUT = 6, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ - CTIMER_AUX1_TMRA1TRIG_B5OUT = 7, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ - CTIMER_AUX1_TMRA1TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX1_TMRA1TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX1_TMRA1TRIG_A4OUT2 = 10, /*!< A4OUT2 : Trigger source is CTIMERA4 OUT2. value. */ - CTIMER_AUX1_TMRA1TRIG_B4OUT2 = 11, /*!< B4OUT2 : Trigger source is CTIMERB4 OUT2. value. */ - CTIMER_AUX1_TMRA1TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX1_TMRA1TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX1_TMRA1TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ - CTIMER_AUX1_TMRA1TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ -} CTIMER_AUX1_TMRA1TRIG_Enum; - -/* ========================================================= TMR2 ========================================================== */ -/* ======================================================== CMPRA2 ========================================================= */ -/* ======================================================== CMPRB2 ========================================================= */ -/* ========================================================= CTRL2 ========================================================= */ -/* ============================================= CTIMER CTRL2 CTLINK2 [31..31] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_CTLINK2 */ - CTIMER_CTRL2_CTLINK2_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A2/B2 timers as two independent 16-bit - timers (default). value. */ - CTIMER_CTRL2_CTLINK2_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A2/B2 timers into a single 32-bit timer. - value. */ -} CTIMER_CTRL2_CTLINK2_Enum; - -/* ============================================ CTIMER CTRL2 TMRB2POL [28..28] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRB2POL */ - CTIMER_CTRL2_TMRB2POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB2 pin is the same as the - timer output. value. */ - CTIMER_CTRL2_TMRB2POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB2 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL2_TMRB2POL_Enum; - -/* ============================================ CTIMER CTRL2 TMRB2CLR [27..27] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRB2CLR */ - CTIMER_CTRL2_TMRB2CLR_RUN = 0, /*!< RUN : Allow counter/timer B2 to run value. */ - CTIMER_CTRL2_TMRB2CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B2 at 0x0000. value. */ -} CTIMER_CTRL2_TMRB2CLR_Enum; - -/* ============================================ CTIMER CTRL2 TMRB2IE1 [26..26] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRB2IE1 */ - CTIMER_CTRL2_TMRB2IE1_DIS = 0, /*!< DIS : Disable counter/timer B2 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL2_TMRB2IE1_EN = 1, /*!< EN : Enable counter/timer B2 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL2_TMRB2IE1_Enum; - -/* ============================================ CTIMER CTRL2 TMRB2IE0 [25..25] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRB2IE0 */ - CTIMER_CTRL2_TMRB2IE0_DIS = 0, /*!< DIS : Disable counter/timer B2 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL2_TMRB2IE0_EN = 1, /*!< EN : Enable counter/timer B2 to generate an interrupt based - on COMPR0 value. */ -} CTIMER_CTRL2_TMRB2IE0_Enum; - -/* ============================================= CTIMER CTRL2 TMRB2FN [22..24] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRB2FN */ - CTIMER_CTRL2_TMRB2FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0B2, stop. value. */ - CTIMER_CTRL2_TMRB2FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0B2, restart. value. */ - CTIMER_CTRL2_TMRB2FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B2, assert, - count to CMPR1B2, deassert, stop. value. */ - CTIMER_CTRL2_TMRB2FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B2, assert, count - to CMPR1B2, deassert, restart. value. */ - CTIMER_CTRL2_TMRB2FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL2_TMRB2FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL2_TMRB2FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL2_TMRB2FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL2_TMRB2FN_Enum; - -/* ============================================ CTIMER CTRL2 TMRB2CLK [17..21] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRB2CLK */ - CTIMER_CTRL2_TMRB2CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ - CTIMER_CTRL2_TMRB2CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL2_TMRB2CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL2_TMRB2CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL2_TMRB2CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL2_TMRB2CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL2_TMRB2CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL2_TMRB2CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL2_TMRB2CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL2_TMRB2CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL2_TMRB2CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL2_TMRB2CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL2_TMRB2CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL2_TMRB2CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL2_TMRB2CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL2_TMRB2CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL2_TMRB2CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL2_TMRB2CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL2_TMRB2CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL2_TMRB2CLK_CTMRA2 = 20, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ - CTIMER_CTRL2_TMRB2CLK_CTMRB3 = 21, /*!< CTMRB3 : Clock source is CTIMERA3 OUT. value. */ - CTIMER_CTRL2_TMRB2CLK_CTMRA3 = 22, /*!< CTMRA3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL2_TMRB2CLK_CTMRA4 = 23, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ - CTIMER_CTRL2_TMRB2CLK_CTMRB4 = 24, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL2_TMRB2CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL2_TMRB2CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL2_TMRB2CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL2_TMRB2CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL2_TMRB2CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL2_TMRB2CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL2_TMRB2CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL2_TMRB2CLK_Enum; - -/* ============================================= CTIMER CTRL2 TMRB2EN [16..16] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRB2EN */ - CTIMER_CTRL2_TMRB2EN_DIS = 0, /*!< DIS : Counter/Timer B2 Disable. value. */ - CTIMER_CTRL2_TMRB2EN_EN = 1, /*!< EN : Counter/Timer B2 Enable. value. */ -} CTIMER_CTRL2_TMRB2EN_Enum; - -/* ============================================ CTIMER CTRL2 TMRA2POL [12..12] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRA2POL */ - CTIMER_CTRL2_TMRA2POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA2 pin is the same as the - timer output. value. */ - CTIMER_CTRL2_TMRA2POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA2 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL2_TMRA2POL_Enum; - -/* ============================================ CTIMER CTRL2 TMRA2CLR [11..11] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRA2CLR */ - CTIMER_CTRL2_TMRA2CLR_RUN = 0, /*!< RUN : Allow counter/timer A2 to run value. */ - CTIMER_CTRL2_TMRA2CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A2 at 0x0000. value. */ -} CTIMER_CTRL2_TMRA2CLR_Enum; - -/* ============================================ CTIMER CTRL2 TMRA2IE1 [10..10] ============================================= */ -typedef enum { /*!< CTIMER_CTRL2_TMRA2IE1 */ - CTIMER_CTRL2_TMRA2IE1_DIS = 0, /*!< DIS : Disable counter/timer A2 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL2_TMRA2IE1_EN = 1, /*!< EN : Enable counter/timer A2 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL2_TMRA2IE1_Enum; - -/* ============================================= CTIMER CTRL2 TMRA2IE0 [9..9] ============================================== */ -typedef enum { /*!< CTIMER_CTRL2_TMRA2IE0 */ - CTIMER_CTRL2_TMRA2IE0_DIS = 0, /*!< DIS : Disable counter/timer A2 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL2_TMRA2IE0_EN = 1, /*!< EN : Enable counter/timer A2 to generate an interrupt based - on COMPR0. value. */ -} CTIMER_CTRL2_TMRA2IE0_Enum; - -/* ============================================== CTIMER CTRL2 TMRA2FN [6..8] ============================================== */ -typedef enum { /*!< CTIMER_CTRL2_TMRA2FN */ - CTIMER_CTRL2_TMRA2FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0A2, stop. value. */ - CTIMER_CTRL2_TMRA2FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0A2, restart. value. */ - CTIMER_CTRL2_TMRA2FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A2, assert, - count to CMPR1A2, deassert, stop. value. */ - CTIMER_CTRL2_TMRA2FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A2, assert, count - to CMPR1A2, deassert, restart. value. */ - CTIMER_CTRL2_TMRA2FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL2_TMRA2FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL2_TMRA2FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL2_TMRA2FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL2_TMRA2FN_Enum; - -/* ============================================= CTIMER CTRL2 TMRA2CLK [1..5] ============================================== */ -typedef enum { /*!< CTIMER_CTRL2_TMRA2CLK */ - CTIMER_CTRL2_TMRA2CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ - CTIMER_CTRL2_TMRA2CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL2_TMRA2CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL2_TMRA2CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL2_TMRA2CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL2_TMRA2CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL2_TMRA2CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL2_TMRA2CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL2_TMRA2CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL2_TMRA2CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL2_TMRA2CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL2_TMRA2CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL2_TMRA2CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL2_TMRA2CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL2_TMRA2CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL2_TMRA2CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL2_TMRA2CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL2_TMRA2CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL2_TMRA2CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL2_TMRA2CLK_CTMRB2 = 20, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL2_TMRA2CLK_CTMRB3 = 21, /*!< CTMRB3 : Clock source is CTIMERA3 OUT. value. */ - CTIMER_CTRL2_TMRA2CLK_CTMRA3 = 22, /*!< CTMRA3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL2_TMRA2CLK_CTMRA4 = 23, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ - CTIMER_CTRL2_TMRA2CLK_CTMRB4 = 24, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL2_TMRA2CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL2_TMRA2CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL2_TMRA2CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL2_TMRA2CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL2_TMRA2CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL2_TMRA2CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL2_TMRA2CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL2_TMRA2CLK_Enum; - -/* ============================================== CTIMER CTRL2 TMRA2EN [0..0] ============================================== */ -typedef enum { /*!< CTIMER_CTRL2_TMRA2EN */ - CTIMER_CTRL2_TMRA2EN_DIS = 0, /*!< DIS : Counter/Timer A2 Disable. value. */ - CTIMER_CTRL2_TMRA2EN_EN = 1, /*!< EN : Counter/Timer A2 Enable. value. */ -} CTIMER_CTRL2_TMRA2EN_Enum; - -/* ======================================================= CMPRAUXA2 ======================================================= */ -/* ======================================================= CMPRAUXB2 ======================================================= */ -/* ========================================================= AUX2 ========================================================== */ -/* ============================================ CTIMER AUX2 TMRB2EN23 [30..30] ============================================= */ -typedef enum { /*!< CTIMER_AUX2_TMRB2EN23 */ - CTIMER_AUX2_TMRB2EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX2_TMRB2EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX2_TMRB2EN23_Enum; - -/* ============================================ CTIMER AUX2 TMRB2POL23 [29..29] ============================================ */ -typedef enum { /*!< CTIMER_AUX2_TMRB2POL23 */ - CTIMER_AUX2_TMRB2POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX2_TMRB2POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX2_TMRB2POL23_Enum; - -/* ============================================ CTIMER AUX2 TMRB2TINV [28..28] ============================================= */ -typedef enum { /*!< CTIMER_AUX2_TMRB2TINV */ - CTIMER_AUX2_TMRB2TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX2_TMRB2TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX2_TMRB2TINV_Enum; - -/* =========================================== CTIMER AUX2 TMRB2NOSYNC [27..27] ============================================ */ -typedef enum { /*!< CTIMER_AUX2_TMRB2NOSYNC */ - CTIMER_AUX2_TMRB2NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX2_TMRB2NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX2_TMRB2NOSYNC_Enum; - -/* ============================================ CTIMER AUX2 TMRB2TRIG [23..26] ============================================= */ -typedef enum { /*!< CTIMER_AUX2_TMRB2TRIG */ - CTIMER_AUX2_TMRB2TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX2_TMRB2TRIG_A2OUT = 1, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ - CTIMER_AUX2_TMRB2TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX2_TMRB2TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX2_TMRB2TRIG_A1OUT = 4, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ - CTIMER_AUX2_TMRB2TRIG_B1OUT = 5, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ - CTIMER_AUX2_TMRB2TRIG_A4OUT = 6, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ - CTIMER_AUX2_TMRB2TRIG_B4OUT = 7, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ - CTIMER_AUX2_TMRB2TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX2_TMRB2TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX2_TMRB2TRIG_A5OUT2 = 10, /*!< A5OUT2 : Trigger source is CTIMERA5 OUT2. value. */ - CTIMER_AUX2_TMRB2TRIG_B5OUT2 = 11, /*!< B5OUT2 : Trigger source is CTIMERB5 OUT2. value. */ - CTIMER_AUX2_TMRB2TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX2_TMRB2TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX2_TMRB2TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ - CTIMER_AUX2_TMRB2TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ -} CTIMER_AUX2_TMRB2TRIG_Enum; - -/* ============================================ CTIMER AUX2 TMRA2EN23 [14..14] ============================================= */ -typedef enum { /*!< CTIMER_AUX2_TMRA2EN23 */ - CTIMER_AUX2_TMRA2EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX2_TMRA2EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX2_TMRA2EN23_Enum; - -/* ============================================ CTIMER AUX2 TMRA2POL23 [13..13] ============================================ */ -typedef enum { /*!< CTIMER_AUX2_TMRA2POL23 */ - CTIMER_AUX2_TMRA2POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX2_TMRA2POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX2_TMRA2POL23_Enum; - -/* ============================================ CTIMER AUX2 TMRA2TINV [12..12] ============================================= */ -typedef enum { /*!< CTIMER_AUX2_TMRA2TINV */ - CTIMER_AUX2_TMRA2TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX2_TMRA2TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX2_TMRA2TINV_Enum; - -/* =========================================== CTIMER AUX2 TMRA2NOSYNC [11..11] ============================================ */ -typedef enum { /*!< CTIMER_AUX2_TMRA2NOSYNC */ - CTIMER_AUX2_TMRA2NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX2_TMRA2NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX2_TMRA2NOSYNC_Enum; - -/* ============================================= CTIMER AUX2 TMRA2TRIG [7..10] ============================================= */ -typedef enum { /*!< CTIMER_AUX2_TMRA2TRIG */ - CTIMER_AUX2_TMRA2TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX2_TMRA2TRIG_B2OUT = 1, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ - CTIMER_AUX2_TMRA2TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX2_TMRA2TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX2_TMRA2TRIG_A0OUT = 4, /*!< A0OUT : Trigger source is CTIMERA0 OUT. value. */ - CTIMER_AUX2_TMRA2TRIG_B0OUT = 5, /*!< B0OUT : Trigger source is CTIMERB0 OUT. value. */ - CTIMER_AUX2_TMRA2TRIG_A4OUT = 6, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ - CTIMER_AUX2_TMRA2TRIG_B4OUT = 7, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ - CTIMER_AUX2_TMRA2TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX2_TMRA2TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX2_TMRA2TRIG_A5OUT2 = 10, /*!< A5OUT2 : Trigger source is CTIMERA5 OUT2. value. */ - CTIMER_AUX2_TMRA2TRIG_B5OUT2 = 11, /*!< B5OUT2 : Trigger source is CTIMERB5 OUT2. value. */ - CTIMER_AUX2_TMRA2TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX2_TMRA2TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX2_TMRA2TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ - CTIMER_AUX2_TMRA2TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ -} CTIMER_AUX2_TMRA2TRIG_Enum; - -/* ========================================================= TMR3 ========================================================== */ -/* ======================================================== CMPRA3 ========================================================= */ -/* ======================================================== CMPRB3 ========================================================= */ -/* ========================================================= CTRL3 ========================================================= */ -/* ============================================= CTIMER CTRL3 CTLINK3 [31..31] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_CTLINK3 */ - CTIMER_CTRL3_CTLINK3_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A3/B3 timers as two independent 16-bit - timers (default). value. */ - CTIMER_CTRL3_CTLINK3_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A3/B3 timers into a single 32-bit timer. - value. */ -} CTIMER_CTRL3_CTLINK3_Enum; - -/* ============================================ CTIMER CTRL3 TMRB3POL [28..28] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRB3POL */ - CTIMER_CTRL3_TMRB3POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB3 pin is the same as the - timer output. value. */ - CTIMER_CTRL3_TMRB3POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB3 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL3_TMRB3POL_Enum; - -/* ============================================ CTIMER CTRL3 TMRB3CLR [27..27] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRB3CLR */ - CTIMER_CTRL3_TMRB3CLR_RUN = 0, /*!< RUN : Allow counter/timer B3 to run value. */ - CTIMER_CTRL3_TMRB3CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B3 at 0x0000. value. */ -} CTIMER_CTRL3_TMRB3CLR_Enum; - -/* ============================================ CTIMER CTRL3 TMRB3IE1 [26..26] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRB3IE1 */ - CTIMER_CTRL3_TMRB3IE1_DIS = 0, /*!< DIS : Disable counter/timer B3 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL3_TMRB3IE1_EN = 1, /*!< EN : Enable counter/timer B3 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL3_TMRB3IE1_Enum; - -/* ============================================ CTIMER CTRL3 TMRB3IE0 [25..25] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRB3IE0 */ - CTIMER_CTRL3_TMRB3IE0_DIS = 0, /*!< DIS : Disable counter/timer B3 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL3_TMRB3IE0_EN = 1, /*!< EN : Enable counter/timer B3 to generate an interrupt based - on COMPR0 value. */ -} CTIMER_CTRL3_TMRB3IE0_Enum; - -/* ============================================= CTIMER CTRL3 TMRB3FN [22..24] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRB3FN */ - CTIMER_CTRL3_TMRB3FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0B3, stop. value. */ - CTIMER_CTRL3_TMRB3FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0B3, restart. value. */ - CTIMER_CTRL3_TMRB3FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B3, assert, - count to CMPR1B3, deassert, stop. value. */ - CTIMER_CTRL3_TMRB3FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B3, assert, count - to CMPR1B3, deassert, restart. value. */ - CTIMER_CTRL3_TMRB3FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL3_TMRB3FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL3_TMRB3FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL3_TMRB3FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL3_TMRB3FN_Enum; - -/* ============================================ CTIMER CTRL3 TMRB3CLK [17..21] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRB3CLK */ - CTIMER_CTRL3_TMRB3CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ - CTIMER_CTRL3_TMRB3CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL3_TMRB3CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL3_TMRB3CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL3_TMRB3CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL3_TMRB3CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL3_TMRB3CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL3_TMRB3CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL3_TMRB3CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL3_TMRB3CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL3_TMRB3CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL3_TMRB3CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL3_TMRB3CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL3_TMRB3CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL3_TMRB3CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL3_TMRB3CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL3_TMRB3CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL3_TMRB3CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL3_TMRB3CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL3_TMRB3CLK_CTMRA3 = 20, /*!< CTMRA3 : Clock source is CTIMERA3 OUT. value. */ - CTIMER_CTRL3_TMRB3CLK_CTMRA2 = 21, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ - CTIMER_CTRL3_TMRB3CLK_CTMRB2 = 22, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL3_TMRB3CLK_CTMRA4 = 23, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ - CTIMER_CTRL3_TMRB3CLK_CTMRB4 = 24, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL3_TMRB3CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL3_TMRB3CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL3_TMRB3CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL3_TMRB3CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL3_TMRB3CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL3_TMRB3CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL3_TMRB3CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL3_TMRB3CLK_Enum; - -/* ============================================= CTIMER CTRL3 TMRB3EN [16..16] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRB3EN */ - CTIMER_CTRL3_TMRB3EN_DIS = 0, /*!< DIS : Counter/Timer B3 Disable. value. */ - CTIMER_CTRL3_TMRB3EN_EN = 1, /*!< EN : Counter/Timer B3 Enable. value. */ -} CTIMER_CTRL3_TMRB3EN_Enum; - -/* ============================================ CTIMER CTRL3 TMRA3POL [12..12] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRA3POL */ - CTIMER_CTRL3_TMRA3POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA3 pin is the same as the - timer output. value. */ - CTIMER_CTRL3_TMRA3POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA3 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL3_TMRA3POL_Enum; - -/* ============================================ CTIMER CTRL3 TMRA3CLR [11..11] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRA3CLR */ - CTIMER_CTRL3_TMRA3CLR_RUN = 0, /*!< RUN : Allow counter/timer A3 to run value. */ - CTIMER_CTRL3_TMRA3CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A3 at 0x0000. value. */ -} CTIMER_CTRL3_TMRA3CLR_Enum; - -/* ============================================ CTIMER CTRL3 TMRA3IE1 [10..10] ============================================= */ -typedef enum { /*!< CTIMER_CTRL3_TMRA3IE1 */ - CTIMER_CTRL3_TMRA3IE1_DIS = 0, /*!< DIS : Disable counter/timer A3 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL3_TMRA3IE1_EN = 1, /*!< EN : Enable counter/timer A3 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL3_TMRA3IE1_Enum; - -/* ============================================= CTIMER CTRL3 TMRA3IE0 [9..9] ============================================== */ -typedef enum { /*!< CTIMER_CTRL3_TMRA3IE0 */ - CTIMER_CTRL3_TMRA3IE0_DIS = 0, /*!< DIS : Disable counter/timer A3 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL3_TMRA3IE0_EN = 1, /*!< EN : Enable counter/timer A3 to generate an interrupt based - on COMPR0. value. */ -} CTIMER_CTRL3_TMRA3IE0_Enum; - -/* ============================================== CTIMER CTRL3 TMRA3FN [6..8] ============================================== */ -typedef enum { /*!< CTIMER_CTRL3_TMRA3FN */ - CTIMER_CTRL3_TMRA3FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0A3, stop. value. */ - CTIMER_CTRL3_TMRA3FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0A3, restart. value. */ - CTIMER_CTRL3_TMRA3FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A3, assert, - count to CMPR1A3, deassert, stop. value. */ - CTIMER_CTRL3_TMRA3FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A3, assert, count - to CMPR1A3, deassert, restart. value. */ - CTIMER_CTRL3_TMRA3FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL3_TMRA3FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL3_TMRA3FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL3_TMRA3FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL3_TMRA3FN_Enum; - -/* ============================================= CTIMER CTRL3 TMRA3CLK [1..5] ============================================== */ -typedef enum { /*!< CTIMER_CTRL3_TMRA3CLK */ - CTIMER_CTRL3_TMRA3CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ - CTIMER_CTRL3_TMRA3CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL3_TMRA3CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL3_TMRA3CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL3_TMRA3CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL3_TMRA3CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL3_TMRA3CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL3_TMRA3CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL3_TMRA3CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL3_TMRA3CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL3_TMRA3CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL3_TMRA3CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL3_TMRA3CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL3_TMRA3CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL3_TMRA3CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL3_TMRA3CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL3_TMRA3CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL3_TMRA3CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL3_TMRA3CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL3_TMRA3CLK_CTMRB3 = 20, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL3_TMRA3CLK_CTMRA2 = 21, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ - CTIMER_CTRL3_TMRA3CLK_CTMRB2 = 22, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL3_TMRA3CLK_CTMRA4 = 23, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ - CTIMER_CTRL3_TMRA3CLK_CTMRB4 = 24, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL3_TMRA3CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL3_TMRA3CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL3_TMRA3CLK_CTMRB5 = 27, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL3_TMRA3CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL3_TMRA3CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL3_TMRA3CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL3_TMRA3CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL3_TMRA3CLK_Enum; - -/* ============================================== CTIMER CTRL3 TMRA3EN [0..0] ============================================== */ -typedef enum { /*!< CTIMER_CTRL3_TMRA3EN */ - CTIMER_CTRL3_TMRA3EN_DIS = 0, /*!< DIS : Counter/Timer A3 Disable. value. */ - CTIMER_CTRL3_TMRA3EN_EN = 1, /*!< EN : Counter/Timer A3 Enable. value. */ -} CTIMER_CTRL3_TMRA3EN_Enum; - -/* ======================================================= CMPRAUXA3 ======================================================= */ -/* ======================================================= CMPRAUXB3 ======================================================= */ -/* ========================================================= AUX3 ========================================================== */ -/* ============================================ CTIMER AUX3 TMRB3EN23 [30..30] ============================================= */ -typedef enum { /*!< CTIMER_AUX3_TMRB3EN23 */ - CTIMER_AUX3_TMRB3EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX3_TMRB3EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX3_TMRB3EN23_Enum; - -/* ============================================ CTIMER AUX3 TMRB3POL23 [29..29] ============================================ */ -typedef enum { /*!< CTIMER_AUX3_TMRB3POL23 */ - CTIMER_AUX3_TMRB3POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX3_TMRB3POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX3_TMRB3POL23_Enum; - -/* ============================================ CTIMER AUX3 TMRB3TINV [28..28] ============================================= */ -typedef enum { /*!< CTIMER_AUX3_TMRB3TINV */ - CTIMER_AUX3_TMRB3TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX3_TMRB3TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX3_TMRB3TINV_Enum; - -/* =========================================== CTIMER AUX3 TMRB3NOSYNC [27..27] ============================================ */ -typedef enum { /*!< CTIMER_AUX3_TMRB3NOSYNC */ - CTIMER_AUX3_TMRB3NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX3_TMRB3NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX3_TMRB3NOSYNC_Enum; - -/* ============================================ CTIMER AUX3 TMRB3TRIG [23..26] ============================================= */ -typedef enum { /*!< CTIMER_AUX3_TMRB3TRIG */ - CTIMER_AUX3_TMRB3TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX3_TMRB3TRIG_A3OUT = 1, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX3_TMRB3TRIG_B2OUT = 2, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ - CTIMER_AUX3_TMRB3TRIG_A2OUT = 3, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ - CTIMER_AUX3_TMRB3TRIG_A4OUT = 4, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ - CTIMER_AUX3_TMRB3TRIG_B4OUT = 5, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ - CTIMER_AUX3_TMRB3TRIG_A6OUT = 6, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ - CTIMER_AUX3_TMRB3TRIG_B6OUT = 7, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ - CTIMER_AUX3_TMRB3TRIG_B5OUT2 = 8, /*!< B5OUT2 : Trigger source is CTIMERB5 OUT2. value. */ - CTIMER_AUX3_TMRB3TRIG_A5OUT2 = 9, /*!< A5OUT2 : Trigger source is CTIMERA5 OUT2. value. */ - CTIMER_AUX3_TMRB3TRIG_A1OUT2 = 10, /*!< A1OUT2 : Trigger source is CTIMERA1 OUT2. value. */ - CTIMER_AUX3_TMRB3TRIG_B1OUT2 = 11, /*!< B1OUT2 : Trigger source is CTIMERB1 OUT2. value. */ - CTIMER_AUX3_TMRB3TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX3_TMRB3TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX3_TMRB3TRIG_B2OUT2DUAL = 14, /*!< B2OUT2DUAL : Trigger source is CTIMERB2 OUT2, dual edge. value. */ - CTIMER_AUX3_TMRB3TRIG_A2OUT2DUAL = 15, /*!< A2OUT2DUAL : Trigger source is CTIMERA2 OUT2, dual edge. value. */ -} CTIMER_AUX3_TMRB3TRIG_Enum; - -/* ============================================ CTIMER AUX3 TMRA3EN23 [14..14] ============================================= */ -typedef enum { /*!< CTIMER_AUX3_TMRA3EN23 */ - CTIMER_AUX3_TMRA3EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX3_TMRA3EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX3_TMRA3EN23_Enum; - -/* ============================================ CTIMER AUX3 TMRA3POL23 [13..13] ============================================ */ -typedef enum { /*!< CTIMER_AUX3_TMRA3POL23 */ - CTIMER_AUX3_TMRA3POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX3_TMRA3POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX3_TMRA3POL23_Enum; - -/* ============================================ CTIMER AUX3 TMRA3TINV [12..12] ============================================= */ -typedef enum { /*!< CTIMER_AUX3_TMRA3TINV */ - CTIMER_AUX3_TMRA3TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX3_TMRA3TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX3_TMRA3TINV_Enum; - -/* =========================================== CTIMER AUX3 TMRA3NOSYNC [11..11] ============================================ */ -typedef enum { /*!< CTIMER_AUX3_TMRA3NOSYNC */ - CTIMER_AUX3_TMRA3NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX3_TMRA3NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX3_TMRA3NOSYNC_Enum; - -/* ============================================= CTIMER AUX3 TMRA3TRIG [7..10] ============================================= */ -typedef enum { /*!< CTIMER_AUX3_TMRA3TRIG */ - CTIMER_AUX3_TMRA3TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX3_TMRA3TRIG_B3OUT = 1, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX3_TMRA3TRIG_B2OUT = 2, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ - CTIMER_AUX3_TMRA3TRIG_A2OUT = 3, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ - CTIMER_AUX3_TMRA3TRIG_A4OUT = 4, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ - CTIMER_AUX3_TMRA3TRIG_B4OUT = 5, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ - CTIMER_AUX3_TMRA3TRIG_A7OUT = 6, /*!< A7OUT : Trigger source is CTIMERA7 OUT. value. */ - CTIMER_AUX3_TMRA3TRIG_B7OUT = 7, /*!< B7OUT : Trigger source is CTIMERB7 OUT. value. */ - CTIMER_AUX3_TMRA3TRIG_B5OUT2 = 8, /*!< B5OUT2 : Trigger source is CTIMERB5 OUT2. value. */ - CTIMER_AUX3_TMRA3TRIG_A5OUT2 = 9, /*!< A5OUT2 : Trigger source is CTIMERA5 OUT2. value. */ - CTIMER_AUX3_TMRA3TRIG_A1OUT2 = 10, /*!< A1OUT2 : Trigger source is CTIMERA1 OUT2. value. */ - CTIMER_AUX3_TMRA3TRIG_B1OUT2 = 11, /*!< B1OUT2 : Trigger source is CTIMERB1 OUT2. value. */ - CTIMER_AUX3_TMRA3TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX3_TMRA3TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX3_TMRA3TRIG_B2OUT2DUAL = 14, /*!< B2OUT2DUAL : Trigger source is CTIMERB2 OUT2, dual edge. value. */ - CTIMER_AUX3_TMRA3TRIG_A2OUT2DUAL = 15, /*!< A2OUT2DUAL : Trigger source is CTIMERA2 OUT2, dual edge. value. */ -} CTIMER_AUX3_TMRA3TRIG_Enum; - -/* ========================================================= TMR4 ========================================================== */ -/* ======================================================== CMPRA4 ========================================================= */ -/* ======================================================== CMPRB4 ========================================================= */ -/* ========================================================= CTRL4 ========================================================= */ -/* ============================================= CTIMER CTRL4 CTLINK4 [31..31] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_CTLINK4 */ - CTIMER_CTRL4_CTLINK4_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A4/B4 timers as two independent 16-bit - timers (default). value. */ - CTIMER_CTRL4_CTLINK4_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A4/B4 timers into a single 32-bit timer. - value. */ -} CTIMER_CTRL4_CTLINK4_Enum; - -/* ============================================ CTIMER CTRL4 TMRB4POL [28..28] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRB4POL */ - CTIMER_CTRL4_TMRB4POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB4 pin is the same as the - timer output. value. */ - CTIMER_CTRL4_TMRB4POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB4 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL4_TMRB4POL_Enum; - -/* ============================================ CTIMER CTRL4 TMRB4CLR [27..27] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRB4CLR */ - CTIMER_CTRL4_TMRB4CLR_RUN = 0, /*!< RUN : Allow counter/timer B4 to run value. */ - CTIMER_CTRL4_TMRB4CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B4 at 0x0000. value. */ -} CTIMER_CTRL4_TMRB4CLR_Enum; - -/* ============================================ CTIMER CTRL4 TMRB4IE1 [26..26] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRB4IE1 */ - CTIMER_CTRL4_TMRB4IE1_DIS = 0, /*!< DIS : Disable counter/timer B4 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL4_TMRB4IE1_EN = 1, /*!< EN : Enable counter/timer B4 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL4_TMRB4IE1_Enum; - -/* ============================================ CTIMER CTRL4 TMRB4IE0 [25..25] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRB4IE0 */ - CTIMER_CTRL4_TMRB4IE0_DIS = 0, /*!< DIS : Disable counter/timer B4 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL4_TMRB4IE0_EN = 1, /*!< EN : Enable counter/timer B4 to generate an interrupt based - on COMPR0 value. */ -} CTIMER_CTRL4_TMRB4IE0_Enum; - -/* ============================================= CTIMER CTRL4 TMRB4FN [22..24] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRB4FN */ - CTIMER_CTRL4_TMRB4FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0B4, stop. value. */ - CTIMER_CTRL4_TMRB4FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0B4, restart. value. */ - CTIMER_CTRL4_TMRB4FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B4, assert, - count to CMPR1B4, deassert, stop. value. */ - CTIMER_CTRL4_TMRB4FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B4, assert, count - to CMPR1B4, deassert, restart. value. */ - CTIMER_CTRL4_TMRB4FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL4_TMRB4FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL4_TMRB4FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL4_TMRB4FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL4_TMRB4FN_Enum; - -/* ============================================ CTIMER CTRL4 TMRB4CLK [17..21] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRB4CLK */ - CTIMER_CTRL4_TMRB4CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ - CTIMER_CTRL4_TMRB4CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL4_TMRB4CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL4_TMRB4CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL4_TMRB4CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL4_TMRB4CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL4_TMRB4CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL4_TMRB4CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL4_TMRB4CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL4_TMRB4CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL4_TMRB4CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL4_TMRB4CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL4_TMRB4CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL4_TMRB4CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL4_TMRB4CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL4_TMRB4CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL4_TMRB4CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL4_TMRB4CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL4_TMRB4CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL4_TMRB4CLK_CTMRA4 = 20, /*!< CTMRA4 : Clock source is CTIMERA4 OUT. value. */ - CTIMER_CTRL4_TMRB4CLK_CTMRA1 = 21, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ - CTIMER_CTRL4_TMRB4CLK_CTMRB1 = 22, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL4_TMRB4CLK_CTMRA5 = 23, /*!< CTMRA5 : Clock source is CTIMERA5 OUT. value. */ - CTIMER_CTRL4_TMRB4CLK_CTMRB5 = 24, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL4_TMRB4CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL4_TMRB4CLK_CTMRB2 = 26, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL4_TMRB4CLK_CTMRB3 = 27, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL4_TMRB4CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL4_TMRB4CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL4_TMRB4CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL4_TMRB4CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL4_TMRB4CLK_Enum; - -/* ============================================= CTIMER CTRL4 TMRB4EN [16..16] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRB4EN */ - CTIMER_CTRL4_TMRB4EN_DIS = 0, /*!< DIS : Counter/Timer B4 Disable. value. */ - CTIMER_CTRL4_TMRB4EN_EN = 1, /*!< EN : Counter/Timer B4 Enable. value. */ -} CTIMER_CTRL4_TMRB4EN_Enum; - -/* ============================================ CTIMER CTRL4 TMRA4POL [12..12] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRA4POL */ - CTIMER_CTRL4_TMRA4POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA4 pin is the same as the - timer output. value. */ - CTIMER_CTRL4_TMRA4POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA4 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL4_TMRA4POL_Enum; - -/* ============================================ CTIMER CTRL4 TMRA4CLR [11..11] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRA4CLR */ - CTIMER_CTRL4_TMRA4CLR_RUN = 0, /*!< RUN : Allow counter/timer A4 to run value. */ - CTIMER_CTRL4_TMRA4CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A4 at 0x0000. value. */ -} CTIMER_CTRL4_TMRA4CLR_Enum; - -/* ============================================ CTIMER CTRL4 TMRA4IE1 [10..10] ============================================= */ -typedef enum { /*!< CTIMER_CTRL4_TMRA4IE1 */ - CTIMER_CTRL4_TMRA4IE1_DIS = 0, /*!< DIS : Disable counter/timer A4 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL4_TMRA4IE1_EN = 1, /*!< EN : Enable counter/timer A4 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL4_TMRA4IE1_Enum; - -/* ============================================= CTIMER CTRL4 TMRA4IE0 [9..9] ============================================== */ -typedef enum { /*!< CTIMER_CTRL4_TMRA4IE0 */ - CTIMER_CTRL4_TMRA4IE0_DIS = 0, /*!< DIS : Disable counter/timer A4 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL4_TMRA4IE0_EN = 1, /*!< EN : Enable counter/timer A4 to generate an interrupt based - on COMPR0. value. */ -} CTIMER_CTRL4_TMRA4IE0_Enum; - -/* ============================================== CTIMER CTRL4 TMRA4FN [6..8] ============================================== */ -typedef enum { /*!< CTIMER_CTRL4_TMRA4FN */ - CTIMER_CTRL4_TMRA4FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0A4, stop. value. */ - CTIMER_CTRL4_TMRA4FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0A4, restart. value. */ - CTIMER_CTRL4_TMRA4FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A4, assert, - count to CMPR1A4, deassert, stop. value. */ - CTIMER_CTRL4_TMRA4FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A4, assert, count - to CMPR1A4, deassert, restart. value. */ - CTIMER_CTRL4_TMRA4FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL4_TMRA4FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL4_TMRA4FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL4_TMRA4FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL4_TMRA4FN_Enum; - -/* ============================================= CTIMER CTRL4 TMRA4CLK [1..5] ============================================== */ -typedef enum { /*!< CTIMER_CTRL4_TMRA4CLK */ - CTIMER_CTRL4_TMRA4CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ - CTIMER_CTRL4_TMRA4CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL4_TMRA4CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL4_TMRA4CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL4_TMRA4CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL4_TMRA4CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL4_TMRA4CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL4_TMRA4CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL4_TMRA4CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL4_TMRA4CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL4_TMRA4CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL4_TMRA4CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL4_TMRA4CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL4_TMRA4CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL4_TMRA4CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL4_TMRA4CLK_HCLK_DIV4 = 15, /*!< HCLK_DIV4 : Clock source is HCLK / 4. value. */ - CTIMER_CTRL4_TMRA4CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL4_TMRA4CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL4_TMRA4CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL4_TMRA4CLK_CTMRB4 = 20, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL4_TMRA4CLK_CTMRA1 = 21, /*!< CTMRA1 : Clock source is CTIMERA1 OUT. value. */ - CTIMER_CTRL4_TMRA4CLK_CTMRB1 = 22, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL4_TMRA4CLK_CTMRA5 = 23, /*!< CTMRA5 : Clock source is CTIMERA5 OUT. value. */ - CTIMER_CTRL4_TMRA4CLK_CTMRB5 = 24, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL4_TMRA4CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL4_TMRA4CLK_CTMRB2 = 26, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL4_TMRA4CLK_CTMRB3 = 27, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL4_TMRA4CLK_CTMRB6 = 28, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL4_TMRA4CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL4_TMRA4CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL4_TMRA4CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL4_TMRA4CLK_Enum; - -/* ============================================== CTIMER CTRL4 TMRA4EN [0..0] ============================================== */ -typedef enum { /*!< CTIMER_CTRL4_TMRA4EN */ - CTIMER_CTRL4_TMRA4EN_DIS = 0, /*!< DIS : Counter/Timer A4 Disable. value. */ - CTIMER_CTRL4_TMRA4EN_EN = 1, /*!< EN : Counter/Timer A4 Enable. value. */ -} CTIMER_CTRL4_TMRA4EN_Enum; - -/* ======================================================= CMPRAUXA4 ======================================================= */ -/* ======================================================= CMPRAUXB4 ======================================================= */ -/* ========================================================= AUX4 ========================================================== */ -/* ============================================ CTIMER AUX4 TMRB4EN23 [30..30] ============================================= */ -typedef enum { /*!< CTIMER_AUX4_TMRB4EN23 */ - CTIMER_AUX4_TMRB4EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX4_TMRB4EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX4_TMRB4EN23_Enum; - -/* ============================================ CTIMER AUX4 TMRB4POL23 [29..29] ============================================ */ -typedef enum { /*!< CTIMER_AUX4_TMRB4POL23 */ - CTIMER_AUX4_TMRB4POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX4_TMRB4POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX4_TMRB4POL23_Enum; - -/* ============================================ CTIMER AUX4 TMRB4TINV [28..28] ============================================= */ -typedef enum { /*!< CTIMER_AUX4_TMRB4TINV */ - CTIMER_AUX4_TMRB4TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX4_TMRB4TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX4_TMRB4TINV_Enum; - -/* =========================================== CTIMER AUX4 TMRB4NOSYNC [27..27] ============================================ */ -typedef enum { /*!< CTIMER_AUX4_TMRB4NOSYNC */ - CTIMER_AUX4_TMRB4NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX4_TMRB4NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX4_TMRB4NOSYNC_Enum; - -/* ============================================ CTIMER AUX4 TMRB4TRIG [23..26] ============================================= */ -typedef enum { /*!< CTIMER_AUX4_TMRB4TRIG */ - CTIMER_AUX4_TMRB4TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX4_TMRB4TRIG_A4OUT = 1, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ - CTIMER_AUX4_TMRB4TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX4_TMRB4TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX4_TMRB4TRIG_A7OUT = 4, /*!< A7OUT : Trigger source is CTIMERA7 OUT. value. */ - CTIMER_AUX4_TMRB4TRIG_B7OUT = 5, /*!< B7OUT : Trigger source is CTIMERB7 OUT. value. */ - CTIMER_AUX4_TMRB4TRIG_A1OUT = 6, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ - CTIMER_AUX4_TMRB4TRIG_B1OUT = 7, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ - CTIMER_AUX4_TMRB4TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX4_TMRB4TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX4_TMRB4TRIG_A1OUT2 = 10, /*!< A1OUT2 : Trigger source is CTIMERA1 OUT2. value. */ - CTIMER_AUX4_TMRB4TRIG_B1OUT2 = 11, /*!< B1OUT2 : Trigger source is CTIMERB1 OUT2. value. */ - CTIMER_AUX4_TMRB4TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX4_TMRB4TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX4_TMRB4TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ - CTIMER_AUX4_TMRB4TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ -} CTIMER_AUX4_TMRB4TRIG_Enum; - -/* ============================================ CTIMER AUX4 TMRA4EN23 [14..14] ============================================= */ -typedef enum { /*!< CTIMER_AUX4_TMRA4EN23 */ - CTIMER_AUX4_TMRA4EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX4_TMRA4EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX4_TMRA4EN23_Enum; - -/* ============================================ CTIMER AUX4 TMRA4POL23 [13..13] ============================================ */ -typedef enum { /*!< CTIMER_AUX4_TMRA4POL23 */ - CTIMER_AUX4_TMRA4POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX4_TMRA4POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX4_TMRA4POL23_Enum; - -/* ============================================ CTIMER AUX4 TMRA4TINV [12..12] ============================================= */ -typedef enum { /*!< CTIMER_AUX4_TMRA4TINV */ - CTIMER_AUX4_TMRA4TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX4_TMRA4TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX4_TMRA4TINV_Enum; - -/* =========================================== CTIMER AUX4 TMRA4NOSYNC [11..11] ============================================ */ -typedef enum { /*!< CTIMER_AUX4_TMRA4NOSYNC */ - CTIMER_AUX4_TMRA4NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX4_TMRA4NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX4_TMRA4NOSYNC_Enum; - -/* ============================================= CTIMER AUX4 TMRA4TRIG [7..10] ============================================= */ -typedef enum { /*!< CTIMER_AUX4_TMRA4TRIG */ - CTIMER_AUX4_TMRA4TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX4_TMRA4TRIG_B4OUT = 1, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ - CTIMER_AUX4_TMRA4TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX4_TMRA4TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX4_TMRA4TRIG_A6OUT = 4, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ - CTIMER_AUX4_TMRA4TRIG_B6OUT = 5, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ - CTIMER_AUX4_TMRA4TRIG_A2OUT = 6, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ - CTIMER_AUX4_TMRA4TRIG_B2OUT = 7, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ - CTIMER_AUX4_TMRA4TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX4_TMRA4TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX4_TMRA4TRIG_A1OUT2 = 10, /*!< A1OUT2 : Trigger source is CTIMERA1 OUT2. value. */ - CTIMER_AUX4_TMRA4TRIG_B1OUT2 = 11, /*!< B1OUT2 : Trigger source is CTIMERB1 OUT2. value. */ - CTIMER_AUX4_TMRA4TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX4_TMRA4TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX4_TMRA4TRIG_B5OUT2DUAL = 14, /*!< B5OUT2DUAL : Trigger source is CTIMERB5 OUT2, dual edge. value. */ - CTIMER_AUX4_TMRA4TRIG_A5OUT2DUAL = 15, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ -} CTIMER_AUX4_TMRA4TRIG_Enum; - -/* ========================================================= TMR5 ========================================================== */ -/* ======================================================== CMPRA5 ========================================================= */ -/* ======================================================== CMPRB5 ========================================================= */ -/* ========================================================= CTRL5 ========================================================= */ -/* ============================================= CTIMER CTRL5 CTLINK5 [31..31] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_CTLINK5 */ - CTIMER_CTRL5_CTLINK5_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A5/B5 timers as two independent 16-bit - timers (default). value. */ - CTIMER_CTRL5_CTLINK5_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A5/B5 timers into a single 32-bit timer. - value. */ -} CTIMER_CTRL5_CTLINK5_Enum; - -/* ============================================ CTIMER CTRL5 TMRB5POL [28..28] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRB5POL */ - CTIMER_CTRL5_TMRB5POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB5 pin is the same as the - timer output. value. */ - CTIMER_CTRL5_TMRB5POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB5 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL5_TMRB5POL_Enum; - -/* ============================================ CTIMER CTRL5 TMRB5CLR [27..27] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRB5CLR */ - CTIMER_CTRL5_TMRB5CLR_RUN = 0, /*!< RUN : Allow counter/timer B5 to run value. */ - CTIMER_CTRL5_TMRB5CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B5 at 0x0000. value. */ -} CTIMER_CTRL5_TMRB5CLR_Enum; - -/* ============================================ CTIMER CTRL5 TMRB5IE1 [26..26] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRB5IE1 */ - CTIMER_CTRL5_TMRB5IE1_DIS = 0, /*!< DIS : Disable counter/timer B5 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL5_TMRB5IE1_EN = 1, /*!< EN : Enable counter/timer B5 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL5_TMRB5IE1_Enum; - -/* ============================================ CTIMER CTRL5 TMRB5IE0 [25..25] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRB5IE0 */ - CTIMER_CTRL5_TMRB5IE0_DIS = 0, /*!< DIS : Disable counter/timer B5 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL5_TMRB5IE0_EN = 1, /*!< EN : Enable counter/timer B5 to generate an interrupt based - on COMPR0 value. */ -} CTIMER_CTRL5_TMRB5IE0_Enum; - -/* ============================================= CTIMER CTRL5 TMRB5FN [22..24] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRB5FN */ - CTIMER_CTRL5_TMRB5FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0B5, stop. value. */ - CTIMER_CTRL5_TMRB5FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0B5, restart. value. */ - CTIMER_CTRL5_TMRB5FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B5, assert, - count to CMPR1B5, deassert, stop. value. */ - CTIMER_CTRL5_TMRB5FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B5, assert, count - to CMPR1B5, deassert, restart. value. */ - CTIMER_CTRL5_TMRB5FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL5_TMRB5FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL5_TMRB5FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL5_TMRB5FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL5_TMRB5FN_Enum; - -/* ============================================ CTIMER CTRL5 TMRB5CLK [17..21] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRB5CLK */ - CTIMER_CTRL5_TMRB5CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ - CTIMER_CTRL5_TMRB5CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL5_TMRB5CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL5_TMRB5CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL5_TMRB5CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL5_TMRB5CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL5_TMRB5CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL5_TMRB5CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL5_TMRB5CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL5_TMRB5CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL5_TMRB5CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL5_TMRB5CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL5_TMRB5CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL5_TMRB5CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL5_TMRB5CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL5_TMRB5CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL5_TMRB5CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL5_TMRB5CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL5_TMRB5CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL5_TMRB5CLK_CTMRA5 = 20, /*!< CTMRA5 : Clock source is CTIMERA5 OUT. value. */ - CTIMER_CTRL5_TMRB5CLK_CTMRA0 = 21, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ - CTIMER_CTRL5_TMRB5CLK_CTMRB0 = 22, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL5_TMRB5CLK_CTMRA6 = 23, /*!< CTMRA6 : Clock source is CTIMERA6 OUT. value. */ - CTIMER_CTRL5_TMRB5CLK_CTMRB6 = 24, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL5_TMRB5CLK_CTMRB1 = 25, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL5_TMRB5CLK_CTMRB2 = 26, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL5_TMRB5CLK_CTMRB3 = 27, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL5_TMRB5CLK_CTMRB4 = 28, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL5_TMRB5CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL5_TMRB5CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL5_TMRB5CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL5_TMRB5CLK_Enum; - -/* ============================================= CTIMER CTRL5 TMRB5EN [16..16] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRB5EN */ - CTIMER_CTRL5_TMRB5EN_DIS = 0, /*!< DIS : Counter/Timer B5 Disable. value. */ - CTIMER_CTRL5_TMRB5EN_EN = 1, /*!< EN : Counter/Timer B5 Enable. value. */ -} CTIMER_CTRL5_TMRB5EN_Enum; - -/* ============================================ CTIMER CTRL5 TMRA5POL [12..12] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRA5POL */ - CTIMER_CTRL5_TMRA5POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA5 pin is the same as the - timer output. value. */ - CTIMER_CTRL5_TMRA5POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA5 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL5_TMRA5POL_Enum; - -/* ============================================ CTIMER CTRL5 TMRA5CLR [11..11] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRA5CLR */ - CTIMER_CTRL5_TMRA5CLR_RUN = 0, /*!< RUN : Allow counter/timer A5 to run value. */ - CTIMER_CTRL5_TMRA5CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A5 at 0x0000. value. */ -} CTIMER_CTRL5_TMRA5CLR_Enum; - -/* ============================================ CTIMER CTRL5 TMRA5IE1 [10..10] ============================================= */ -typedef enum { /*!< CTIMER_CTRL5_TMRA5IE1 */ - CTIMER_CTRL5_TMRA5IE1_DIS = 0, /*!< DIS : Disable counter/timer A5 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL5_TMRA5IE1_EN = 1, /*!< EN : Enable counter/timer A5 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL5_TMRA5IE1_Enum; - -/* ============================================= CTIMER CTRL5 TMRA5IE0 [9..9] ============================================== */ -typedef enum { /*!< CTIMER_CTRL5_TMRA5IE0 */ - CTIMER_CTRL5_TMRA5IE0_DIS = 0, /*!< DIS : Disable counter/timer A5 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL5_TMRA5IE0_EN = 1, /*!< EN : Enable counter/timer A5 to generate an interrupt based - on COMPR0. value. */ -} CTIMER_CTRL5_TMRA5IE0_Enum; - -/* ============================================== CTIMER CTRL5 TMRA5FN [6..8] ============================================== */ -typedef enum { /*!< CTIMER_CTRL5_TMRA5FN */ - CTIMER_CTRL5_TMRA5FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0A5, stop. value. */ - CTIMER_CTRL5_TMRA5FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0A5, restart. value. */ - CTIMER_CTRL5_TMRA5FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A5, assert, - count to CMPR1A5, deassert, stop. value. */ - CTIMER_CTRL5_TMRA5FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A5, assert, count - to CMPR1A5, deassert, restart. value. */ - CTIMER_CTRL5_TMRA5FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL5_TMRA5FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL5_TMRA5FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL5_TMRA5FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL5_TMRA5FN_Enum; - -/* ============================================= CTIMER CTRL5 TMRA5CLK [1..5] ============================================== */ -typedef enum { /*!< CTIMER_CTRL5_TMRA5CLK */ - CTIMER_CTRL5_TMRA5CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ - CTIMER_CTRL5_TMRA5CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL5_TMRA5CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL5_TMRA5CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL5_TMRA5CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL5_TMRA5CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL5_TMRA5CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL5_TMRA5CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL5_TMRA5CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL5_TMRA5CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL5_TMRA5CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL5_TMRA5CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL5_TMRA5CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL5_TMRA5CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL5_TMRA5CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL5_TMRA5CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL5_TMRA5CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL5_TMRA5CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL5_TMRA5CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL5_TMRA5CLK_CTMRB5 = 20, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL5_TMRA5CLK_CTMRA0 = 21, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ - CTIMER_CTRL5_TMRA5CLK_CTMRB0 = 22, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL5_TMRA5CLK_CTMRA6 = 23, /*!< CTMRA6 : Clock source is CTIMERA6 OUT. value. */ - CTIMER_CTRL5_TMRA5CLK_CTMRB6 = 24, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL5_TMRA5CLK_CTMRB1 = 25, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL5_TMRA5CLK_CTMRB2 = 26, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL5_TMRA5CLK_CTMRB3 = 27, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL5_TMRA5CLK_CTMRB4 = 28, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL5_TMRA5CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL5_TMRA5CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL5_TMRA5CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL5_TMRA5CLK_Enum; - -/* ============================================== CTIMER CTRL5 TMRA5EN [0..0] ============================================== */ -typedef enum { /*!< CTIMER_CTRL5_TMRA5EN */ - CTIMER_CTRL5_TMRA5EN_DIS = 0, /*!< DIS : Counter/Timer A5 Disable. value. */ - CTIMER_CTRL5_TMRA5EN_EN = 1, /*!< EN : Counter/Timer A5 Enable. value. */ -} CTIMER_CTRL5_TMRA5EN_Enum; - -/* ======================================================= CMPRAUXA5 ======================================================= */ -/* ======================================================= CMPRAUXB5 ======================================================= */ -/* ========================================================= AUX5 ========================================================== */ -/* ============================================ CTIMER AUX5 TMRB5EN23 [30..30] ============================================= */ -typedef enum { /*!< CTIMER_AUX5_TMRB5EN23 */ - CTIMER_AUX5_TMRB5EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX5_TMRB5EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX5_TMRB5EN23_Enum; - -/* ============================================ CTIMER AUX5 TMRB5POL23 [29..29] ============================================ */ -typedef enum { /*!< CTIMER_AUX5_TMRB5POL23 */ - CTIMER_AUX5_TMRB5POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX5_TMRB5POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX5_TMRB5POL23_Enum; - -/* ============================================ CTIMER AUX5 TMRB5TINV [28..28] ============================================= */ -typedef enum { /*!< CTIMER_AUX5_TMRB5TINV */ - CTIMER_AUX5_TMRB5TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX5_TMRB5TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX5_TMRB5TINV_Enum; - -/* =========================================== CTIMER AUX5 TMRB5NOSYNC [27..27] ============================================ */ -typedef enum { /*!< CTIMER_AUX5_TMRB5NOSYNC */ - CTIMER_AUX5_TMRB5NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX5_TMRB5NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX5_TMRB5NOSYNC_Enum; - -/* ============================================ CTIMER AUX5 TMRB5TRIG [23..26] ============================================= */ -typedef enum { /*!< CTIMER_AUX5_TMRB5TRIG */ - CTIMER_AUX5_TMRB5TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX5_TMRB5TRIG_A5OUT = 1, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ - CTIMER_AUX5_TMRB5TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX5_TMRB5TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX5_TMRB5TRIG_A6OUT = 4, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ - CTIMER_AUX5_TMRB5TRIG_B6OUT = 5, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ - CTIMER_AUX5_TMRB5TRIG_A1OUT = 6, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ - CTIMER_AUX5_TMRB5TRIG_B1OUT = 7, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ - CTIMER_AUX5_TMRB5TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX5_TMRB5TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX5_TMRB5TRIG_A0OUT2 = 10, /*!< A0OUT2 : Trigger source is CTIMERA0 OUT2. value. */ - CTIMER_AUX5_TMRB5TRIG_B0OUT2 = 11, /*!< B0OUT2 : Trigger source is CTIMERB0 OUT2. value. */ - CTIMER_AUX5_TMRB5TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX5_TMRB5TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX5_TMRB5TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ - CTIMER_AUX5_TMRB5TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ -} CTIMER_AUX5_TMRB5TRIG_Enum; - -/* ============================================ CTIMER AUX5 TMRA5EN23 [14..14] ============================================= */ -typedef enum { /*!< CTIMER_AUX5_TMRA5EN23 */ - CTIMER_AUX5_TMRA5EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX5_TMRA5EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX5_TMRA5EN23_Enum; - -/* ============================================ CTIMER AUX5 TMRA5POL23 [13..13] ============================================ */ -typedef enum { /*!< CTIMER_AUX5_TMRA5POL23 */ - CTIMER_AUX5_TMRA5POL23_NORMAL = 0, /*!< NORMAL : Upper output normal polarity value. */ - CTIMER_AUX5_TMRA5POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX5_TMRA5POL23_Enum; - -/* ============================================ CTIMER AUX5 TMRA5TINV [12..12] ============================================= */ -typedef enum { /*!< CTIMER_AUX5_TMRA5TINV */ - CTIMER_AUX5_TMRA5TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX5_TMRA5TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX5_TMRA5TINV_Enum; - -/* =========================================== CTIMER AUX5 TMRA5NOSYNC [11..11] ============================================ */ -typedef enum { /*!< CTIMER_AUX5_TMRA5NOSYNC */ - CTIMER_AUX5_TMRA5NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX5_TMRA5NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX5_TMRA5NOSYNC_Enum; - -/* ============================================= CTIMER AUX5 TMRA5TRIG [7..10] ============================================= */ -typedef enum { /*!< CTIMER_AUX5_TMRA5TRIG */ - CTIMER_AUX5_TMRA5TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX5_TMRA5TRIG_B5OUT = 1, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ - CTIMER_AUX5_TMRA5TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX5_TMRA5TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX5_TMRA5TRIG_A4OUT = 4, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ - CTIMER_AUX5_TMRA5TRIG_B4OUT = 5, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ - CTIMER_AUX5_TMRA5TRIG_A2OUT = 6, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ - CTIMER_AUX5_TMRA5TRIG_B2OUT = 7, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ - CTIMER_AUX5_TMRA5TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX5_TMRA5TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX5_TMRA5TRIG_A0OUT2 = 10, /*!< A0OUT2 : Trigger source is CTIMERA0 OUT2. value. */ - CTIMER_AUX5_TMRA5TRIG_B0OUT2 = 11, /*!< B0OUT2 : Trigger source is CTIMERB0 OUT2. value. */ - CTIMER_AUX5_TMRA5TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX5_TMRA5TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX5_TMRA5TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ - CTIMER_AUX5_TMRA5TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ -} CTIMER_AUX5_TMRA5TRIG_Enum; - -/* ========================================================= TMR6 ========================================================== */ -/* ======================================================== CMPRA6 ========================================================= */ -/* ======================================================== CMPRB6 ========================================================= */ -/* ========================================================= CTRL6 ========================================================= */ -/* ============================================= CTIMER CTRL6 CTLINK6 [31..31] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_CTLINK6 */ - CTIMER_CTRL6_CTLINK6_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A6/B6 timers as two independent 16-bit - timers (default). value. */ - CTIMER_CTRL6_CTLINK6_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A6/B6 timers into a single 32-bit timer. - value. */ -} CTIMER_CTRL6_CTLINK6_Enum; - -/* ============================================ CTIMER CTRL6 TMRB6POL [28..28] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRB6POL */ - CTIMER_CTRL6_TMRB6POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB6 pin is the same as the - timer output. value. */ - CTIMER_CTRL6_TMRB6POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB6 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL6_TMRB6POL_Enum; - -/* ============================================ CTIMER CTRL6 TMRB6CLR [27..27] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRB6CLR */ - CTIMER_CTRL6_TMRB6CLR_RUN = 0, /*!< RUN : Allow counter/timer B6 to run value. */ - CTIMER_CTRL6_TMRB6CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B6 at 0x0000. value. */ -} CTIMER_CTRL6_TMRB6CLR_Enum; - -/* ============================================ CTIMER CTRL6 TMRB6IE1 [26..26] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRB6IE1 */ - CTIMER_CTRL6_TMRB6IE1_DIS = 0, /*!< DIS : Disable counter/timer B6 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL6_TMRB6IE1_EN = 1, /*!< EN : Enable counter/timer B6 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL6_TMRB6IE1_Enum; - -/* ============================================ CTIMER CTRL6 TMRB6IE0 [25..25] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRB6IE0 */ - CTIMER_CTRL6_TMRB6IE0_DIS = 0, /*!< DIS : Disable counter/timer B6 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL6_TMRB6IE0_EN = 1, /*!< EN : Enable counter/timer B6 to generate an interrupt based - on COMPR0 value. */ -} CTIMER_CTRL6_TMRB6IE0_Enum; - -/* ============================================= CTIMER CTRL6 TMRB6FN [22..24] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRB6FN */ - CTIMER_CTRL6_TMRB6FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0B6, stop. value. */ - CTIMER_CTRL6_TMRB6FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0B6, restart. value. */ - CTIMER_CTRL6_TMRB6FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B6, assert, - count to CMPR1B6, deassert, stop. value. */ - CTIMER_CTRL6_TMRB6FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B6, assert, count - to CMPR1B6, deassert, restart. value. */ - CTIMER_CTRL6_TMRB6FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL6_TMRB6FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL6_TMRB6FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL6_TMRB6FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL6_TMRB6FN_Enum; - -/* ============================================ CTIMER CTRL6 TMRB6CLK [17..21] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRB6CLK */ - CTIMER_CTRL6_TMRB6CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ - CTIMER_CTRL6_TMRB6CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL6_TMRB6CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL6_TMRB6CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL6_TMRB6CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL6_TMRB6CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL6_TMRB6CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL6_TMRB6CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL6_TMRB6CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL6_TMRB6CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL6_TMRB6CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL6_TMRB6CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL6_TMRB6CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL6_TMRB6CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL6_TMRB6CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL6_TMRB6CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL6_TMRB6CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL6_TMRB6CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL6_TMRB6CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL6_TMRB6CLK_CTMRA6 = 20, /*!< CTMRA6 : Clock source is CTIMERA6 OUT. value. */ - CTIMER_CTRL6_TMRB6CLK_CTMRA3 = 21, /*!< CTMRA3 : Clock source is CTIMERA3 OUT. value. */ - CTIMER_CTRL6_TMRB6CLK_CTMRB3 = 22, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL6_TMRB6CLK_CTMRA7 = 23, /*!< CTMRA7 : Clock source is CTIMERA7 OUT. value. */ - CTIMER_CTRL6_TMRB6CLK_CTMRB7 = 24, /*!< CTMRB7 : Clock source is CTIMERB7 OUT. value. */ - CTIMER_CTRL6_TMRB6CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL6_TMRB6CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL6_TMRB6CLK_CTMRB2 = 27, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL6_TMRB6CLK_CTMRB4 = 28, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL6_TMRB6CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL6_TMRB6CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL6_TMRB6CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL6_TMRB6CLK_Enum; - -/* ============================================= CTIMER CTRL6 TMRB6EN [16..16] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRB6EN */ - CTIMER_CTRL6_TMRB6EN_DIS = 0, /*!< DIS : Counter/Timer B6 Disable. value. */ - CTIMER_CTRL6_TMRB6EN_EN = 1, /*!< EN : Counter/Timer B6 Enable. value. */ -} CTIMER_CTRL6_TMRB6EN_Enum; - -/* ============================================ CTIMER CTRL6 TMRA6POL [12..12] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRA6POL */ - CTIMER_CTRL6_TMRA6POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA6 pin is the same as the - timer output. value. */ - CTIMER_CTRL6_TMRA6POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA6 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL6_TMRA6POL_Enum; - -/* ============================================ CTIMER CTRL6 TMRA6CLR [11..11] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRA6CLR */ - CTIMER_CTRL6_TMRA6CLR_RUN = 0, /*!< RUN : Allow counter/timer A6 to run value. */ - CTIMER_CTRL6_TMRA6CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A6 at 0x0000. value. */ -} CTIMER_CTRL6_TMRA6CLR_Enum; - -/* ============================================ CTIMER CTRL6 TMRA6IE1 [10..10] ============================================= */ -typedef enum { /*!< CTIMER_CTRL6_TMRA6IE1 */ - CTIMER_CTRL6_TMRA6IE1_DIS = 0, /*!< DIS : Disable counter/timer A6 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL6_TMRA6IE1_EN = 1, /*!< EN : Enable counter/timer A6 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL6_TMRA6IE1_Enum; - -/* ============================================= CTIMER CTRL6 TMRA6IE0 [9..9] ============================================== */ -typedef enum { /*!< CTIMER_CTRL6_TMRA6IE0 */ - CTIMER_CTRL6_TMRA6IE0_DIS = 0, /*!< DIS : Disable counter/timer A6 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL6_TMRA6IE0_EN = 1, /*!< EN : Enable counter/timer A6 to generate an interrupt based - on COMPR0. value. */ -} CTIMER_CTRL6_TMRA6IE0_Enum; - -/* ============================================== CTIMER CTRL6 TMRA6FN [6..8] ============================================== */ -typedef enum { /*!< CTIMER_CTRL6_TMRA6FN */ - CTIMER_CTRL6_TMRA6FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0A6, stop. value. */ - CTIMER_CTRL6_TMRA6FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0A6, restart. value. */ - CTIMER_CTRL6_TMRA6FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A6, assert, - count to CMPR1A6, deassert, stop. value. */ - CTIMER_CTRL6_TMRA6FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A6, assert, count - to CMPR1A6, deassert, restart. value. */ - CTIMER_CTRL6_TMRA6FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL6_TMRA6FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL6_TMRA6FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL6_TMRA6FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL6_TMRA6FN_Enum; - -/* ============================================= CTIMER CTRL6 TMRA6CLK [1..5] ============================================== */ -typedef enum { /*!< CTIMER_CTRL6_TMRA6CLK */ - CTIMER_CTRL6_TMRA6CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ - CTIMER_CTRL6_TMRA6CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL6_TMRA6CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL6_TMRA6CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL6_TMRA6CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL6_TMRA6CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL6_TMRA6CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL6_TMRA6CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL6_TMRA6CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL6_TMRA6CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL6_TMRA6CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL6_TMRA6CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL6_TMRA6CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL6_TMRA6CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL6_TMRA6CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL6_TMRA6CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL6_TMRA6CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL6_TMRA6CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL6_TMRA6CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL6_TMRA6CLK_CTMRB6 = 20, /*!< CTMRB6 : Clock source is CTIMERB6 OUT. value. */ - CTIMER_CTRL6_TMRA6CLK_CTMRA3 = 21, /*!< CTMRA3 : Clock source is CTIMERA3 OUT. value. */ - CTIMER_CTRL6_TMRA6CLK_CTMRB3 = 22, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL6_TMRA6CLK_CTMRA7 = 23, /*!< CTMRA7 : Clock source is CTIMERA7 OUT. value. */ - CTIMER_CTRL6_TMRA6CLK_CTMRB7 = 24, /*!< CTMRB7 : Clock source is CTIMERB7 OUT. value. */ - CTIMER_CTRL6_TMRA6CLK_CTMRB0 = 25, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL6_TMRA6CLK_CTMRB1 = 26, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL6_TMRA6CLK_CTMRB2 = 27, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL6_TMRA6CLK_CTMRB4 = 28, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL6_TMRA6CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL6_TMRA6CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL6_TMRA6CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL6_TMRA6CLK_Enum; - -/* ============================================== CTIMER CTRL6 TMRA6EN [0..0] ============================================== */ -typedef enum { /*!< CTIMER_CTRL6_TMRA6EN */ - CTIMER_CTRL6_TMRA6EN_DIS = 0, /*!< DIS : Counter/Timer A6 Disable. value. */ - CTIMER_CTRL6_TMRA6EN_EN = 1, /*!< EN : Counter/Timer A6 Enable. value. */ -} CTIMER_CTRL6_TMRA6EN_Enum; - -/* ======================================================= CMPRAUXA6 ======================================================= */ -/* ======================================================= CMPRAUXB6 ======================================================= */ -/* ========================================================= AUX6 ========================================================== */ -/* ============================================ CTIMER AUX6 TMRB6EN23 [30..30] ============================================= */ -typedef enum { /*!< CTIMER_AUX6_TMRB6EN23 */ - CTIMER_AUX6_TMRB6EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX6_TMRB6EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX6_TMRB6EN23_Enum; - -/* ============================================ CTIMER AUX6 TMRB6POL23 [29..29] ============================================ */ -typedef enum { /*!< CTIMER_AUX6_TMRB6POL23 */ - CTIMER_AUX6_TMRB6POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX6_TMRB6POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX6_TMRB6POL23_Enum; - -/* ============================================ CTIMER AUX6 TMRB6TINV [28..28] ============================================= */ -typedef enum { /*!< CTIMER_AUX6_TMRB6TINV */ - CTIMER_AUX6_TMRB6TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX6_TMRB6TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX6_TMRB6TINV_Enum; - -/* =========================================== CTIMER AUX6 TMRB6NOSYNC [27..27] ============================================ */ -typedef enum { /*!< CTIMER_AUX6_TMRB6NOSYNC */ - CTIMER_AUX6_TMRB6NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX6_TMRB6NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX6_TMRB6NOSYNC_Enum; - -/* ============================================ CTIMER AUX6 TMRB6TRIG [23..26] ============================================= */ -typedef enum { /*!< CTIMER_AUX6_TMRB6TRIG */ - CTIMER_AUX6_TMRB6TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX6_TMRB6TRIG_A6OUT = 1, /*!< A6OUT : Trigger source is CTIMERA6 OUT. value. */ - CTIMER_AUX6_TMRB6TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX6_TMRB6TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX6_TMRB6TRIG_A4OUT = 4, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ - CTIMER_AUX6_TMRB6TRIG_B4OUT = 5, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ - CTIMER_AUX6_TMRB6TRIG_A1OUT = 6, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ - CTIMER_AUX6_TMRB6TRIG_B1OUT = 7, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ - CTIMER_AUX6_TMRB6TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX6_TMRB6TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX6_TMRB6TRIG_A2OUT2 = 10, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ - CTIMER_AUX6_TMRB6TRIG_B2OUT2 = 11, /*!< B2OUT2 : Trigger source is CTIMERB2 OUT2. value. */ - CTIMER_AUX6_TMRB6TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX6_TMRB6TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX6_TMRB6TRIG_B0OUT2DUAL = 14, /*!< B0OUT2DUAL : Trigger source is CTIMERB0 OUT2, dual edge. value. */ - CTIMER_AUX6_TMRB6TRIG_A0OUT2DUAL = 15, /*!< A0OUT2DUAL : Trigger source is CTIMERA0 OUT2, dual edge. value. */ -} CTIMER_AUX6_TMRB6TRIG_Enum; - -/* ============================================ CTIMER AUX6 TMRA6EN23 [14..14] ============================================= */ -typedef enum { /*!< CTIMER_AUX6_TMRA6EN23 */ - CTIMER_AUX6_TMRA6EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX6_TMRA6EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX6_TMRA6EN23_Enum; - -/* ============================================ CTIMER AUX6 TMRA6POL23 [13..13] ============================================ */ -typedef enum { /*!< CTIMER_AUX6_TMRA6POL23 */ - CTIMER_AUX6_TMRA6POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX6_TMRA6POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX6_TMRA6POL23_Enum; - -/* ============================================ CTIMER AUX6 TMRA6TINV [12..12] ============================================= */ -typedef enum { /*!< CTIMER_AUX6_TMRA6TINV */ - CTIMER_AUX6_TMRA6TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX6_TMRA6TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX6_TMRA6TINV_Enum; - -/* =========================================== CTIMER AUX6 TMRA6NOSYNC [11..11] ============================================ */ -typedef enum { /*!< CTIMER_AUX6_TMRA6NOSYNC */ - CTIMER_AUX6_TMRA6NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX6_TMRA6NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX6_TMRA6NOSYNC_Enum; - -/* ============================================= CTIMER AUX6 TMRA6TRIG [7..10] ============================================= */ -typedef enum { /*!< CTIMER_AUX6_TMRA6TRIG */ - CTIMER_AUX6_TMRA6TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX6_TMRA6TRIG_B6OUT = 1, /*!< B6OUT : Trigger source is CTIMERB6 OUT. value. */ - CTIMER_AUX6_TMRA6TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX6_TMRA6TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX6_TMRA6TRIG_A5OUT = 4, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ - CTIMER_AUX6_TMRA6TRIG_B5OUT = 5, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ - CTIMER_AUX6_TMRA6TRIG_A1OUT = 6, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ - CTIMER_AUX6_TMRA6TRIG_B1OUT = 7, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ - CTIMER_AUX6_TMRA6TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX6_TMRA6TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX6_TMRA6TRIG_A2OUT2 = 10, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ - CTIMER_AUX6_TMRA6TRIG_B2OUT2 = 11, /*!< B2OUT2 : Trigger source is CTIMERBb OUT2. value. */ - CTIMER_AUX6_TMRA6TRIG_A5OUT2DUAL = 12, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ - CTIMER_AUX6_TMRA6TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX6_TMRA6TRIG_B0OUT2DUAL = 14, /*!< B0OUT2DUAL : Trigger source is CTIMERB0 OUT2, dual edge. value. */ - CTIMER_AUX6_TMRA6TRIG_A0OUT2DUAL = 15, /*!< A0OUT2DUAL : Trigger source is CTIMERA0 OUT2, dual edge. value. */ -} CTIMER_AUX6_TMRA6TRIG_Enum; - -/* ========================================================= TMR7 ========================================================== */ -/* ======================================================== CMPRA7 ========================================================= */ -/* ======================================================== CMPRB7 ========================================================= */ -/* ========================================================= CTRL7 ========================================================= */ -/* ============================================= CTIMER CTRL7 CTLINK7 [31..31] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_CTLINK7 */ - CTIMER_CTRL7_CTLINK7_TWO_16BIT_TIMERS = 0, /*!< TWO_16BIT_TIMERS : Use A7/B7 timers as two independent 16-bit - timers (default). value. */ - CTIMER_CTRL7_CTLINK7_32BIT_TIMER = 1, /*!< 32BIT_TIMER : Link A7/B7 timers into a single 32-bit timer. - value. */ -} CTIMER_CTRL7_CTLINK7_Enum; - -/* ============================================ CTIMER CTRL7 TMRB7POL [28..28] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRB7POL */ - CTIMER_CTRL7_TMRB7POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINB7 pin is the same as the - timer output. value. */ - CTIMER_CTRL7_TMRB7POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINB7 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL7_TMRB7POL_Enum; - -/* ============================================ CTIMER CTRL7 TMRB7CLR [27..27] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRB7CLR */ - CTIMER_CTRL7_TMRB7CLR_RUN = 0, /*!< RUN : Allow counter/timer B7 to run value. */ - CTIMER_CTRL7_TMRB7CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer B7 at 0x0000. value. */ -} CTIMER_CTRL7_TMRB7CLR_Enum; - -/* ============================================ CTIMER CTRL7 TMRB7IE1 [26..26] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRB7IE1 */ - CTIMER_CTRL7_TMRB7IE1_DIS = 0, /*!< DIS : Disable counter/timer B7 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL7_TMRB7IE1_EN = 1, /*!< EN : Enable counter/timer B7 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL7_TMRB7IE1_Enum; - -/* ============================================ CTIMER CTRL7 TMRB7IE0 [25..25] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRB7IE0 */ - CTIMER_CTRL7_TMRB7IE0_DIS = 0, /*!< DIS : Disable counter/timer B7 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL7_TMRB7IE0_EN = 1, /*!< EN : Enable counter/timer B7 to generate an interrupt based - on COMPR0 value. */ -} CTIMER_CTRL7_TMRB7IE0_Enum; - -/* ============================================= CTIMER CTRL7 TMRB7FN [22..24] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRB7FN */ - CTIMER_CTRL7_TMRB7FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0B7, stop. value. */ - CTIMER_CTRL7_TMRB7FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0B7, restart. value. */ - CTIMER_CTRL7_TMRB7FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0B7, assert, - count to CMPR1B7, deassert, stop. value. */ - CTIMER_CTRL7_TMRB7FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0B7, assert, count - to CMPR1B7, deassert, restart. value. */ - CTIMER_CTRL7_TMRB7FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL7_TMRB7FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL7_TMRB7FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL7_TMRB7FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL7_TMRB7FN_Enum; - -/* ============================================ CTIMER CTRL7 TMRB7CLK [17..21] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRB7CLK */ - CTIMER_CTRL7_TMRB7CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINB. value. */ - CTIMER_CTRL7_TMRB7CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL7_TMRB7CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL7_TMRB7CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL7_TMRB7CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL7_TMRB7CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL7_TMRB7CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL7_TMRB7CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL7_TMRB7CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL7_TMRB7CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL7_TMRB7CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL7_TMRB7CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL7_TMRB7CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL7_TMRB7CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL7_TMRB7CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL7_TMRB7CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL7_TMRB7CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL7_TMRB7CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL7_TMRB7CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL7_TMRB7CLK_CTMRA7 = 20, /*!< CTMRA7 : Clock source is CTIMERA7 OUT. value. */ - CTIMER_CTRL7_TMRB7CLK_CTMRA2 = 21, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ - CTIMER_CTRL7_TMRB7CLK_CTMRB2 = 22, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL7_TMRB7CLK_CTMRA0 = 23, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ - CTIMER_CTRL7_TMRB7CLK_CTMRB0 = 24, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL7_TMRB7CLK_CTMRB1 = 25, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL7_TMRB7CLK_CTMRB3 = 26, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL7_TMRB7CLK_CTMRB4 = 27, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL7_TMRB7CLK_CTMRB5 = 28, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL7_TMRB7CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL7_TMRB7CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL7_TMRB7CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL7_TMRB7CLK_Enum; - -/* ============================================= CTIMER CTRL7 TMRB7EN [16..16] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRB7EN */ - CTIMER_CTRL7_TMRB7EN_DIS = 0, /*!< DIS : Counter/Timer B7 Disable. value. */ - CTIMER_CTRL7_TMRB7EN_EN = 1, /*!< EN : Counter/Timer B7 Enable. value. */ -} CTIMER_CTRL7_TMRB7EN_Enum; - -/* ============================================ CTIMER CTRL7 TMRA7POL [12..12] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRA7POL */ - CTIMER_CTRL7_TMRA7POL_NORMAL = 0, /*!< NORMAL : The polarity of the TMRPINA7 pin is the same as the - timer output. value. */ - CTIMER_CTRL7_TMRA7POL_INVERTED = 1, /*!< INVERTED : The polarity of the TMRPINA7 pin is the inverse of - the timer output. value. */ -} CTIMER_CTRL7_TMRA7POL_Enum; - -/* ============================================ CTIMER CTRL7 TMRA7CLR [11..11] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRA7CLR */ - CTIMER_CTRL7_TMRA7CLR_RUN = 0, /*!< RUN : Allow counter/timer A7 to run value. */ - CTIMER_CTRL7_TMRA7CLR_CLEAR = 1, /*!< CLEAR : Holds counter/timer A7 at 0x0000. value. */ -} CTIMER_CTRL7_TMRA7CLR_Enum; - -/* ============================================ CTIMER CTRL7 TMRA7IE1 [10..10] ============================================= */ -typedef enum { /*!< CTIMER_CTRL7_TMRA7IE1 */ - CTIMER_CTRL7_TMRA7IE1_DIS = 0, /*!< DIS : Disable counter/timer A7 from generating an interrupt - based on COMPR1. value. */ - CTIMER_CTRL7_TMRA7IE1_EN = 1, /*!< EN : Enable counter/timer A7 to generate an interrupt based - on COMPR1. value. */ -} CTIMER_CTRL7_TMRA7IE1_Enum; - -/* ============================================= CTIMER CTRL7 TMRA7IE0 [9..9] ============================================== */ -typedef enum { /*!< CTIMER_CTRL7_TMRA7IE0 */ - CTIMER_CTRL7_TMRA7IE0_DIS = 0, /*!< DIS : Disable counter/timer A7 from generating an interrupt - based on COMPR0. value. */ - CTIMER_CTRL7_TMRA7IE0_EN = 1, /*!< EN : Enable counter/timer A7 to generate an interrupt based - on COMPR0. value. */ -} CTIMER_CTRL7_TMRA7IE0_Enum; - -/* ============================================== CTIMER CTRL7 TMRA7FN [6..8] ============================================== */ -typedef enum { /*!< CTIMER_CTRL7_TMRA7FN */ - CTIMER_CTRL7_TMRA7FN_SINGLECOUNT = 0, /*!< SINGLECOUNT : Single count (output toggles and sticks). Count - to CMPR0A7, stop. value. */ - CTIMER_CTRL7_TMRA7FN_REPEATEDCOUNT = 1, /*!< REPEATEDCOUNT : Repeated count (periodic 1-clock-cycle-wide - pulses). Count to CMPR0A7, restart. value. */ - CTIMER_CTRL7_TMRA7FN_PULSE_ONCE = 2, /*!< PULSE_ONCE : Pulse once (aka one-shot). Count to CMPR0A7, assert, - count to CMPR1A7, deassert, stop. value. */ - CTIMER_CTRL7_TMRA7FN_PULSE_CONT = 3, /*!< PULSE_CONT : Pulse continously. Count to CMPR0A7, assert, count - to CMPR1A7, deassert, restart. value. */ - CTIMER_CTRL7_TMRA7FN_SINGLEPATTERN = 4, /*!< SINGLEPATTERN : Single pattern. value. */ - CTIMER_CTRL7_TMRA7FN_REPEATPATTERN = 5, /*!< REPEATPATTERN : Repeated pattern. value. */ - CTIMER_CTRL7_TMRA7FN_CONTINUOUS = 6, /*!< CONTINUOUS : Continuous run (aka Free Run). Count continuously. - value. */ - CTIMER_CTRL7_TMRA7FN_ALTPWN = 7, /*!< ALTPWN : Alternate PWM value. */ -} CTIMER_CTRL7_TMRA7FN_Enum; - -/* ============================================= CTIMER CTRL7 TMRA7CLK [1..5] ============================================== */ -typedef enum { /*!< CTIMER_CTRL7_TMRA7CLK */ - CTIMER_CTRL7_TMRA7CLK_TMRPIN = 0, /*!< TMRPIN : Clock source is TMRPINA. value. */ - CTIMER_CTRL7_TMRA7CLK_HFRC_DIV4 = 1, /*!< HFRC_DIV4 : Clock source is the HFRC / 4 value. */ - CTIMER_CTRL7_TMRA7CLK_HFRC_DIV16 = 2, /*!< HFRC_DIV16 : Clock source is HFRC / 16 value. */ - CTIMER_CTRL7_TMRA7CLK_HFRC_DIV256 = 3, /*!< HFRC_DIV256 : Clock source is HFRC / 256 value. */ - CTIMER_CTRL7_TMRA7CLK_HFRC_DIV1024 = 4, /*!< HFRC_DIV1024 : Clock source is HFRC / 1024 value. */ - CTIMER_CTRL7_TMRA7CLK_HFRC_DIV4K = 5, /*!< HFRC_DIV4K : Clock source is HFRC / 4096 value. */ - CTIMER_CTRL7_TMRA7CLK_XT = 6, /*!< XT : Clock source is the XT (uncalibrated). value. */ - CTIMER_CTRL7_TMRA7CLK_XT_DIV2 = 7, /*!< XT_DIV2 : Clock source is XT / 2 value. */ - CTIMER_CTRL7_TMRA7CLK_XT_DIV16 = 8, /*!< XT_DIV16 : Clock source is XT / 16 value. */ - CTIMER_CTRL7_TMRA7CLK_XT_DIV128 = 9, /*!< XT_DIV128 : Clock source is XT / 128 value. */ - CTIMER_CTRL7_TMRA7CLK_LFRC_DIV2 = 10, /*!< LFRC_DIV2 : Clock source is LFRC / 2 value. */ - CTIMER_CTRL7_TMRA7CLK_LFRC_DIV32 = 11, /*!< LFRC_DIV32 : Clock source is LFRC / 32 value. */ - CTIMER_CTRL7_TMRA7CLK_LFRC_DIV1K = 12, /*!< LFRC_DIV1K : Clock source is LFRC / 1024 value. */ - CTIMER_CTRL7_TMRA7CLK_LFRC = 13, /*!< LFRC : Clock source is LFRC value. */ - CTIMER_CTRL7_TMRA7CLK_RTC_100HZ = 14, /*!< RTC_100HZ : Clock source is 100 Hz from the current RTC oscillator. - value. */ - CTIMER_CTRL7_TMRA7CLK_HCLK = 15, /*!< HCLK : Clock source is HCLK. value. */ - CTIMER_CTRL7_TMRA7CLK_XT_DIV4 = 16, /*!< XT_DIV4 : Clock source is XT / 4 value. */ - CTIMER_CTRL7_TMRA7CLK_XT_DIV8 = 17, /*!< XT_DIV8 : Clock source is XT / 8 value. */ - CTIMER_CTRL7_TMRA7CLK_XT_DIV32 = 18, /*!< XT_DIV32 : Clock source is XT / 32 value. */ - CTIMER_CTRL7_TMRA7CLK_CTMRB7 = 20, /*!< CTMRB7 : Clock source is CTIMERB7 OUT. value. */ - CTIMER_CTRL7_TMRA7CLK_CTMRA2 = 21, /*!< CTMRA2 : Clock source is CTIMERA2 OUT. value. */ - CTIMER_CTRL7_TMRA7CLK_CTMRB2 = 22, /*!< CTMRB2 : Clock source is CTIMERB2 OUT. value. */ - CTIMER_CTRL7_TMRA7CLK_CTMRA0 = 23, /*!< CTMRA0 : Clock source is CTIMERA0 OUT. value. */ - CTIMER_CTRL7_TMRA7CLK_CTMRB0 = 24, /*!< CTMRB0 : Clock source is CTIMERB0 OUT. value. */ - CTIMER_CTRL7_TMRA7CLK_CTMRB1 = 25, /*!< CTMRB1 : Clock source is CTIMERB1 OUT. value. */ - CTIMER_CTRL7_TMRA7CLK_CTMRB3 = 26, /*!< CTMRB3 : Clock source is CTIMERB3 OUT. value. */ - CTIMER_CTRL7_TMRA7CLK_CTMRB4 = 27, /*!< CTMRB4 : Clock source is CTIMERB4 OUT. value. */ - CTIMER_CTRL7_TMRA7CLK_CTMRB5 = 28, /*!< CTMRB5 : Clock source is CTIMERB5 OUT. value. */ - CTIMER_CTRL7_TMRA7CLK_BUCKBLE = 29, /*!< BUCKBLE : Clock source is BLE buck converter TON pulses. value. */ - CTIMER_CTRL7_TMRA7CLK_BUCKB = 30, /*!< BUCKB : Clock source is Memory buck converter TON pulses. value. */ - CTIMER_CTRL7_TMRA7CLK_BUCKA = 31, /*!< BUCKA : Clock source is CPU buck converter TON pulses. value. */ -} CTIMER_CTRL7_TMRA7CLK_Enum; - -/* ============================================== CTIMER CTRL7 TMRA7EN [0..0] ============================================== */ -typedef enum { /*!< CTIMER_CTRL7_TMRA7EN */ - CTIMER_CTRL7_TMRA7EN_DIS = 0, /*!< DIS : Counter/Timer A7 Disable. value. */ - CTIMER_CTRL7_TMRA7EN_EN = 1, /*!< EN : Counter/Timer A7 Enable. value. */ -} CTIMER_CTRL7_TMRA7EN_Enum; - -/* ======================================================= CMPRAUXA7 ======================================================= */ -/* ======================================================= CMPRAUXB7 ======================================================= */ -/* ========================================================= AUX7 ========================================================== */ -/* ============================================ CTIMER AUX7 TMRB7EN23 [30..30] ============================================= */ -typedef enum { /*!< CTIMER_AUX7_TMRB7EN23 */ - CTIMER_AUX7_TMRB7EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX7_TMRB7EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX7_TMRB7EN23_Enum; - -/* ============================================ CTIMER AUX7 TMRB7POL23 [29..29] ============================================ */ -typedef enum { /*!< CTIMER_AUX7_TMRB7POL23 */ - CTIMER_AUX7_TMRB7POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX7_TMRB7POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX7_TMRB7POL23_Enum; - -/* ============================================ CTIMER AUX7 TMRB7TINV [28..28] ============================================= */ -typedef enum { /*!< CTIMER_AUX7_TMRB7TINV */ - CTIMER_AUX7_TMRB7TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX7_TMRB7TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX7_TMRB7TINV_Enum; - -/* =========================================== CTIMER AUX7 TMRB7NOSYNC [27..27] ============================================ */ -typedef enum { /*!< CTIMER_AUX7_TMRB7NOSYNC */ - CTIMER_AUX7_TMRB7NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX7_TMRB7NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX7_TMRB7NOSYNC_Enum; - -/* ============================================ CTIMER AUX7 TMRB7TRIG [23..26] ============================================= */ -typedef enum { /*!< CTIMER_AUX7_TMRB7TRIG */ - CTIMER_AUX7_TMRB7TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX7_TMRB7TRIG_A7OUT = 1, /*!< A7OUT : Trigger source is CTIMERA7 OUT. value. */ - CTIMER_AUX7_TMRB7TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX7_TMRB7TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX7_TMRB7TRIG_A5OUT = 4, /*!< A5OUT : Trigger source is CTIMERA5 OUT. value. */ - CTIMER_AUX7_TMRB7TRIG_B5OUT = 5, /*!< B5OUT : Trigger source is CTIMERB5 OUT. value. */ - CTIMER_AUX7_TMRB7TRIG_A2OUT = 6, /*!< A2OUT : Trigger source is CTIMERA2 OUT. value. */ - CTIMER_AUX7_TMRB7TRIG_B2OUT = 7, /*!< B2OUT : Trigger source is CTIMERB2 OUT. value. */ - CTIMER_AUX7_TMRB7TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX7_TMRB7TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX7_TMRB7TRIG_A2OUT2 = 10, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ - CTIMER_AUX7_TMRB7TRIG_B2OUT2 = 11, /*!< B2OUT2 : Trigger source is CTIMERB2 OUT2. value. */ - CTIMER_AUX7_TMRB7TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX7_TMRB7TRIG_A7OUT2DUAL = 13, /*!< A7OUT2DUAL : Trigger source is CTIMERA7 OUT2, dual edge. value. */ - CTIMER_AUX7_TMRB7TRIG_B1OUT2DUAL = 14, /*!< B1OUT2DUAL : Trigger source is CTIMERB1 OUT2, dual edge. value. */ - CTIMER_AUX7_TMRB7TRIG_A1OUT2DUAL = 15, /*!< A1OUT2DUAL : Trigger source is CTIMERA1 OUT2, dual edge. value. */ -} CTIMER_AUX7_TMRB7TRIG_Enum; - -/* ============================================ CTIMER AUX7 TMRA7EN23 [14..14] ============================================= */ -typedef enum { /*!< CTIMER_AUX7_TMRA7EN23 */ - CTIMER_AUX7_TMRA7EN23_DIS = 1, /*!< DIS : Disable enhanced functions. value. */ - CTIMER_AUX7_TMRA7EN23_EN = 0, /*!< EN : Enable enhanced functions. value. */ -} CTIMER_AUX7_TMRA7EN23_Enum; - -/* ============================================ CTIMER AUX7 TMRA7POL23 [13..13] ============================================ */ -typedef enum { /*!< CTIMER_AUX7_TMRA7POL23 */ - CTIMER_AUX7_TMRA7POL23_NORM = 0, /*!< NORM : Upper output normal polarity value. */ - CTIMER_AUX7_TMRA7POL23_INV = 1, /*!< INV : Upper output inverted polarity. value. */ -} CTIMER_AUX7_TMRA7POL23_Enum; - -/* ============================================ CTIMER AUX7 TMRA7TINV [12..12] ============================================= */ -typedef enum { /*!< CTIMER_AUX7_TMRA7TINV */ - CTIMER_AUX7_TMRA7TINV_DIS = 0, /*!< DIS : Disable invert on trigger value. */ - CTIMER_AUX7_TMRA7TINV_EN = 1, /*!< EN : Enable invert on trigger value. */ -} CTIMER_AUX7_TMRA7TINV_Enum; - -/* =========================================== CTIMER AUX7 TMRA7NOSYNC [11..11] ============================================ */ -typedef enum { /*!< CTIMER_AUX7_TMRA7NOSYNC */ - CTIMER_AUX7_TMRA7NOSYNC_DIS = 0, /*!< DIS : Synchronization on source clock value. */ - CTIMER_AUX7_TMRA7NOSYNC_NOSYNC = 1, /*!< NOSYNC : No synchronization on source clock value. */ -} CTIMER_AUX7_TMRA7NOSYNC_Enum; - -/* ============================================= CTIMER AUX7 TMRA7TRIG [7..10] ============================================= */ -typedef enum { /*!< CTIMER_AUX7_TMRA7TRIG */ - CTIMER_AUX7_TMRA7TRIG_DIS = 0, /*!< DIS : Trigger source is disabled. value. */ - CTIMER_AUX7_TMRA7TRIG_B7OUT = 1, /*!< B7OUT : Trigger source is CTIMERB7 OUT. value. */ - CTIMER_AUX7_TMRA7TRIG_B3OUT = 2, /*!< B3OUT : Trigger source is CTIMERB3 OUT. value. */ - CTIMER_AUX7_TMRA7TRIG_A3OUT = 3, /*!< A3OUT : Trigger source is CTIMERA3 OUT. value. */ - CTIMER_AUX7_TMRA7TRIG_A1OUT = 4, /*!< A1OUT : Trigger source is CTIMERA1 OUT. value. */ - CTIMER_AUX7_TMRA7TRIG_B1OUT = 5, /*!< B1OUT : Trigger source is CTIMERB1 OUT. value. */ - CTIMER_AUX7_TMRA7TRIG_A4OUT = 6, /*!< A4OUT : Trigger source is CTIMERA4 OUT. value. */ - CTIMER_AUX7_TMRA7TRIG_B4OUT = 7, /*!< B4OUT : Trigger source is CTIMERB4 OUT. value. */ - CTIMER_AUX7_TMRA7TRIG_B3OUT2 = 8, /*!< B3OUT2 : Trigger source is CTIMERB3 OUT2. value. */ - CTIMER_AUX7_TMRA7TRIG_A3OUT2 = 9, /*!< A3OUT2 : Trigger source is CTIMERA3 OUT2. value. */ - CTIMER_AUX7_TMRA7TRIG_A2OUT2 = 10, /*!< A2OUT2 : Trigger source is CTIMERA2 OUT2. value. */ - CTIMER_AUX7_TMRA7TRIG_B2OUT2 = 11, /*!< B2OUT2 : Trigger source is CTIMERB2 OUT2. value. */ - CTIMER_AUX7_TMRA7TRIG_A6OUT2DUAL = 12, /*!< A6OUT2DUAL : Trigger source is CTIMERA6 OUT2, dual edge. value. */ - CTIMER_AUX7_TMRA7TRIG_A5OUT2DUAL = 13, /*!< A5OUT2DUAL : Trigger source is CTIMERA5 OUT2, dual edge. value. */ - CTIMER_AUX7_TMRA7TRIG_B4OUT2DUAL = 14, /*!< B4OUT2DUAL : Trigger source is CTIMERB4 OUT2, dual edge. value. */ - CTIMER_AUX7_TMRA7TRIG_A4OUT2DUAL = 15, /*!< A4OUT2DUAL : Trigger source is CTIMERA4 OUT2, dual edge. value. */ -} CTIMER_AUX7_TMRA7TRIG_Enum; - -/* ======================================================== GLOBEN ========================================================= */ -/* ============================================== CTIMER GLOBEN ENB7 [15..15] ============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENB7 */ - CTIMER_GLOBEN_ENB7_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENB7_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENB7_Enum; - -/* ============================================== CTIMER GLOBEN ENA7 [14..14] ============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENA7 */ - CTIMER_GLOBEN_ENA7_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENA7_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENA7_Enum; - -/* ============================================== CTIMER GLOBEN ENB6 [13..13] ============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENB6 */ - CTIMER_GLOBEN_ENB6_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENB6_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENB6_Enum; - -/* ============================================== CTIMER GLOBEN ENA6 [12..12] ============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENA6 */ - CTIMER_GLOBEN_ENA6_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENA6_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENA6_Enum; - -/* ============================================== CTIMER GLOBEN ENB5 [11..11] ============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENB5 */ - CTIMER_GLOBEN_ENB5_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENB5_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENB5_Enum; - -/* ============================================== CTIMER GLOBEN ENA5 [10..10] ============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENA5 */ - CTIMER_GLOBEN_ENA5_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENA5_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENA5_Enum; - -/* =============================================== CTIMER GLOBEN ENB4 [9..9] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENB4 */ - CTIMER_GLOBEN_ENB4_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENB4_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENB4_Enum; - -/* =============================================== CTIMER GLOBEN ENA4 [8..8] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENA4 */ - CTIMER_GLOBEN_ENA4_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENA4_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENA4_Enum; - -/* =============================================== CTIMER GLOBEN ENB3 [7..7] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENB3 */ - CTIMER_GLOBEN_ENB3_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENB3_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENB3_Enum; - -/* =============================================== CTIMER GLOBEN ENA3 [6..6] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENA3 */ - CTIMER_GLOBEN_ENA3_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENA3_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENA3_Enum; - -/* =============================================== CTIMER GLOBEN ENB2 [5..5] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENB2 */ - CTIMER_GLOBEN_ENB2_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENB2_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENB2_Enum; - -/* =============================================== CTIMER GLOBEN ENA2 [4..4] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENA2 */ - CTIMER_GLOBEN_ENA2_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENA2_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENA2_Enum; - -/* =============================================== CTIMER GLOBEN ENB1 [3..3] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENB1 */ - CTIMER_GLOBEN_ENB1_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENB1_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENB1_Enum; - -/* =============================================== CTIMER GLOBEN ENA1 [2..2] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENA1 */ - CTIMER_GLOBEN_ENA1_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENA1_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENA1_Enum; - -/* =============================================== CTIMER GLOBEN ENB0 [1..1] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENB0 */ - CTIMER_GLOBEN_ENB0_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENB0_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENB0_Enum; - -/* =============================================== CTIMER GLOBEN ENA0 [0..0] =============================================== */ -typedef enum { /*!< CTIMER_GLOBEN_ENA0 */ - CTIMER_GLOBEN_ENA0_LCO = 1, /*!< LCO : Use local enable. value. */ - CTIMER_GLOBEN_ENA0_DIS = 0, /*!< DIS : Disable CTIMER. value. */ -} CTIMER_GLOBEN_ENA0_Enum; - -/* ======================================================== OUTCFG0 ======================================================== */ -/* ============================================= CTIMER OUTCFG0 CFG9 [28..30] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG9 */ - CTIMER_OUTCFG0_CFG9_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG9_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG9_B0OUT = 5, /*!< B0OUT : Output is B0OUT. value. */ - CTIMER_OUTCFG0_CFG9_A4OUT = 4, /*!< A4OUT : Output is A4OUT. value. */ - CTIMER_OUTCFG0_CFG9_A2OUT = 3, /*!< A2OUT : Output is A2OUT. value. */ - CTIMER_OUTCFG0_CFG9_A2OUT2 = 2, /*!< A2OUT2 : Output is A2OUT2 value. */ - CTIMER_OUTCFG0_CFG9_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG9_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG9_Enum; - -/* ============================================= CTIMER OUTCFG0 CFG8 [25..27] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG8 */ - CTIMER_OUTCFG0_CFG8_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG8_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG8_B6OUT = 5, /*!< B6OUT : Output is B6OUT. value. */ - CTIMER_OUTCFG0_CFG8_A4OUT2 = 4, /*!< A4OUT2 : Output is A4OUT2. value. */ - CTIMER_OUTCFG0_CFG8_A3OUT2 = 3, /*!< A3OUT2 : Output is A3OUT. value. */ - CTIMER_OUTCFG0_CFG8_A2OUT = 2, /*!< A2OUT : Output is A2OUT value. */ - CTIMER_OUTCFG0_CFG8_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG8_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG8_Enum; - -/* ============================================= CTIMER OUTCFG0 CFG7 [22..24] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG7 */ - CTIMER_OUTCFG0_CFG7_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG7_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG7_A7OUT = 5, /*!< A7OUT : Output is A7OUT. value. */ - CTIMER_OUTCFG0_CFG7_B5OUT = 4, /*!< B5OUT : Output is B5OUT. value. */ - CTIMER_OUTCFG0_CFG7_B1OUT = 3, /*!< B1OUT : Output is B1OUT. value. */ - CTIMER_OUTCFG0_CFG7_B1OUT2 = 2, /*!< B1OUT2 : Output is B1OUT2 value. */ - CTIMER_OUTCFG0_CFG7_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG7_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG7_Enum; - -/* ============================================= CTIMER OUTCFG0 CFG6 [19..21] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG6 */ - CTIMER_OUTCFG0_CFG6_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG6_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG6_B7OUT = 5, /*!< B7OUT : Output is B7OUT. value. */ - CTIMER_OUTCFG0_CFG6_B5OUT2 = 4, /*!< B5OUT2 : Output is B5OUT2. value. */ - CTIMER_OUTCFG0_CFG6_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ - CTIMER_OUTCFG0_CFG6_B1OUT = 2, /*!< B1OUT : Output is B1OUT value. */ - CTIMER_OUTCFG0_CFG6_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG6_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG6_Enum; - -/* ============================================= CTIMER OUTCFG0 CFG5 [16..18] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG5 */ - CTIMER_OUTCFG0_CFG5_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG5_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG5_A7OUT = 5, /*!< A7OUT : Output is A7OUT. value. */ - CTIMER_OUTCFG0_CFG5_B6OUT = 4, /*!< B6OUT : Output is A5OUT. value. */ - CTIMER_OUTCFG0_CFG5_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ - CTIMER_OUTCFG0_CFG5_A1OUT2 = 2, /*!< A1OUT2 : Output is A1OUT2 value. */ - CTIMER_OUTCFG0_CFG5_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG5_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG5_Enum; - -/* ============================================= CTIMER OUTCFG0 CFG4 [12..14] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG4 */ - CTIMER_OUTCFG0_CFG4_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG4_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG4_B5OUT = 5, /*!< B5OUT : Output is B5OUT. value. */ - CTIMER_OUTCFG0_CFG4_A5OUT2 = 4, /*!< A5OUT2 : Output is A5OUT2. value. */ - CTIMER_OUTCFG0_CFG4_A2OUT2 = 3, /*!< A2OUT2 : Output is A2OUT2. value. */ - CTIMER_OUTCFG0_CFG4_A1OUT = 2, /*!< A1OUT : Output is A1OUT value. */ - CTIMER_OUTCFG0_CFG4_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG4_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG4_Enum; - -/* ============================================== CTIMER OUTCFG0 CFG3 [9..11] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG3 */ - CTIMER_OUTCFG0_CFG3_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG3_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG3_A6OUT = 5, /*!< A6OUT : Output is A6OUT. value. */ - CTIMER_OUTCFG0_CFG3_A1OUT = 4, /*!< A1OUT : Output is A1OUT. value. */ - CTIMER_OUTCFG0_CFG3_B0OUT = 3, /*!< B0OUT : Output is B0OUT. value. */ - CTIMER_OUTCFG0_CFG3_B0OUT2 = 2, /*!< B0OUT2 : Output is B0OUT2 value. */ - CTIMER_OUTCFG0_CFG3_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG3_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG3_Enum; - -/* ============================================== CTIMER OUTCFG0 CFG2 [6..8] =============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG2 */ - CTIMER_OUTCFG0_CFG2_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG2_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG2_A7OUT = 5, /*!< A7OUT : Output is A7OUT. value. */ - CTIMER_OUTCFG0_CFG2_B6OUT2 = 4, /*!< B6OUT2 : Output is B6OUT2. value. */ - CTIMER_OUTCFG0_CFG2_B1OUT2 = 3, /*!< B1OUT2 : Output is B1OUT2. value. */ - CTIMER_OUTCFG0_CFG2_B0OUT = 2, /*!< B0OUT : Output is B0OUT value. */ - CTIMER_OUTCFG0_CFG2_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG2_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG2_Enum; - -/* ============================================== CTIMER OUTCFG0 CFG1 [3..5] =============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG1 */ - CTIMER_OUTCFG0_CFG1_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG1_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG1_B7OUT2 = 5, /*!< B7OUT2 : Output is B7OUT2. value. */ - CTIMER_OUTCFG0_CFG1_A5OUT = 4, /*!< A5OUT : Output is A5OUT. value. */ - CTIMER_OUTCFG0_CFG1_A0OUT = 3, /*!< A0OUT : Output is A0OUT. value. */ - CTIMER_OUTCFG0_CFG1_A0OUT2 = 2, /*!< A0OUT2 : Output is A0OUT2 value. */ - CTIMER_OUTCFG0_CFG1_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG1_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG1_Enum; - -/* ============================================== CTIMER OUTCFG0 CFG0 [0..2] =============================================== */ -typedef enum { /*!< CTIMER_OUTCFG0_CFG0 */ - CTIMER_OUTCFG0_CFG0_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG0_CFG0_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG0_CFG0_A6OUT = 5, /*!< A6OUT : Output is A6OUT. value. */ - CTIMER_OUTCFG0_CFG0_A5OUT2 = 4, /*!< A5OUT2 : Output is A5OUT2. value. */ - CTIMER_OUTCFG0_CFG0_B2OUT2 = 3, /*!< B2OUT2 : Output is B2OUT2. value. */ - CTIMER_OUTCFG0_CFG0_A0OUT = 2, /*!< A0OUT : Output is A0OUT value. */ - CTIMER_OUTCFG0_CFG0_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG0_CFG0_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG0_CFG0_Enum; - -/* ======================================================== OUTCFG1 ======================================================== */ -/* ============================================= CTIMER OUTCFG1 CFG19 [28..30] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG19 */ - CTIMER_OUTCFG1_CFG19_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG19_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG19_B1OUT2 = 5, /*!< B1OUT2 : Output is B1OUT2. value. */ - CTIMER_OUTCFG1_CFG19_B4OUT = 4, /*!< B4OUT : Output is B4OUT. value. */ - CTIMER_OUTCFG1_CFG19_A2OUT = 3, /*!< A2OUT : Output is A2OUT. value. */ - CTIMER_OUTCFG1_CFG19_B4OUT2 = 2, /*!< B4OUT2 : Output is B4OUT2 value. */ - CTIMER_OUTCFG1_CFG19_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG19_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG19_Enum; - -/* ============================================= CTIMER OUTCFG1 CFG18 [25..27] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG18 */ - CTIMER_OUTCFG1_CFG18_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG18_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG18_A3OUT2 = 5, /*!< A3OUT2 : Output is A3OUT2. value. */ - CTIMER_OUTCFG1_CFG18_A0OUT = 4, /*!< A0OUT : Output is A0OUT. value. */ - CTIMER_OUTCFG1_CFG18_B0OUT = 3, /*!< B0OUT : Output is B0OUT. value. */ - CTIMER_OUTCFG1_CFG18_B4OUT = 2, /*!< B4OUT : Output is B4OUT value. */ - CTIMER_OUTCFG1_CFG18_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG18_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG18_Enum; - -/* ============================================= CTIMER OUTCFG1 CFG17 [22..24] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG17 */ - CTIMER_OUTCFG1_CFG17_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG17_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG17_A1OUT2 = 5, /*!< A1OUT2 : Output is A1OUT2. value. */ - CTIMER_OUTCFG1_CFG17_A4OUT = 4, /*!< A4OUT : Output is A4OUT. value. */ - CTIMER_OUTCFG1_CFG17_B7OUT = 3, /*!< B7OUT : Output is B7OUT. value. */ - CTIMER_OUTCFG1_CFG17_A4OUT2 = 2, /*!< A4OUT2 : Output is A4OUT2 value. */ - CTIMER_OUTCFG1_CFG17_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG17_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG17_Enum; - -/* ============================================= CTIMER OUTCFG1 CFG16 [19..21] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG16 */ - CTIMER_OUTCFG1_CFG16_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG16_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG16_B3OUT2 = 5, /*!< B3OUT2 : Output is B3OUT2. value. */ - CTIMER_OUTCFG1_CFG16_A0OUT2 = 4, /*!< A0OUT2 : Output is A0OUT2. value. */ - CTIMER_OUTCFG1_CFG16_A0OUT = 3, /*!< A0OUT : Output is A0OUT. value. */ - CTIMER_OUTCFG1_CFG16_A4OUT = 2, /*!< A4OUT : Output is A4OUT value. */ - CTIMER_OUTCFG1_CFG16_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG16_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG16_Enum; - -/* ============================================= CTIMER OUTCFG1 CFG15 [16..18] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG15 */ - CTIMER_OUTCFG1_CFG15_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG15_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG15_A4OUT2 = 5, /*!< A4OUT2 : Output is A4OUT2. value. */ - CTIMER_OUTCFG1_CFG15_A7OUT = 4, /*!< A7OUT : Output is B1OUT. value. */ - CTIMER_OUTCFG1_CFG15_B3OUT = 3, /*!< B3OUT : Output is B3OUT. value. */ - CTIMER_OUTCFG1_CFG15_B3OUT2 = 2, /*!< B3OUT2 : Output is B3OUT2 value. */ - CTIMER_OUTCFG1_CFG15_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG15_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG15_Enum; - -/* ============================================= CTIMER OUTCFG1 CFG14 [12..14] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG14 */ - CTIMER_OUTCFG1_CFG14_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG14_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG14_A7OUT = 5, /*!< A7OUT : Output is A7OUT. value. */ - CTIMER_OUTCFG1_CFG14_B7OUT2 = 4, /*!< B7OUT2 : Output is B7OUT2. value. */ - CTIMER_OUTCFG1_CFG14_B1OUT = 3, /*!< B1OUT : Output is B1OUT. value. */ - CTIMER_OUTCFG1_CFG14_B3OUT = 2, /*!< B3OUT : Output is B3OUT value. */ - CTIMER_OUTCFG1_CFG14_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG14_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG14_Enum; - -/* ============================================= CTIMER OUTCFG1 CFG13 [9..11] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG13 */ - CTIMER_OUTCFG1_CFG13_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG13_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG13_B4OUT2 = 5, /*!< B4OUT2 : Output is B4OUT2. value. */ - CTIMER_OUTCFG1_CFG13_A6OUT = 4, /*!< A6OUT : Output is B1OUT. value. */ - CTIMER_OUTCFG1_CFG13_A3OUT = 3, /*!< A3OUT : Output is A3OUT. value. */ - CTIMER_OUTCFG1_CFG13_A3OUT2 = 2, /*!< A3OUT2 : Output is A3OUT2 value. */ - CTIMER_OUTCFG1_CFG13_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG13_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG13_Enum; - -/* ============================================== CTIMER OUTCFG1 CFG12 [6..8] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG12 */ - CTIMER_OUTCFG1_CFG12_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG12_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG12_B6OUT2 = 5, /*!< B6OUT2 : Output is B6OUT2. value. */ - CTIMER_OUTCFG1_CFG12_B0OUT2 = 4, /*!< B0OUT2 : Output is B0OUT2. value. */ - CTIMER_OUTCFG1_CFG12_B1OUT = 3, /*!< B1OUT : Output is B1OUT. value. */ - CTIMER_OUTCFG1_CFG12_A3OUT = 2, /*!< A3OUT : Output is A3OUT value. */ - CTIMER_OUTCFG1_CFG12_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG12_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG12_Enum; - -/* ============================================== CTIMER OUTCFG1 CFG11 [3..5] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG11 */ - CTIMER_OUTCFG1_CFG11_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG11_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG11_B5OUT2 = 5, /*!< B5OUT2 : Output is B5OUT2. value. */ - CTIMER_OUTCFG1_CFG11_B4OUT = 4, /*!< B4OUT : Output is B4OUT. value. */ - CTIMER_OUTCFG1_CFG11_B2OUT = 3, /*!< B2OUT : Output is B2OUT. value. */ - CTIMER_OUTCFG1_CFG11_B2OUT2 = 2, /*!< B2OUT2 : Output is B2OUT2 value. */ - CTIMER_OUTCFG1_CFG11_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG11_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG11_Enum; - -/* ============================================== CTIMER OUTCFG1 CFG10 [0..2] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG1_CFG10 */ - CTIMER_OUTCFG1_CFG10_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG1_CFG10_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG1_CFG10_A6OUT = 5, /*!< A6OUT : Output is A6OUT. value. */ - CTIMER_OUTCFG1_CFG10_B4OUT2 = 4, /*!< B4OUT2 : Output is B4OUT2. value. */ - CTIMER_OUTCFG1_CFG10_B3OUT2 = 3, /*!< B3OUT2 : Output is B3OUT2. value. */ - CTIMER_OUTCFG1_CFG10_B2OUT = 2, /*!< B2OUT : Output is B2OUT value. */ - CTIMER_OUTCFG1_CFG10_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG1_CFG10_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG1_CFG10_Enum; - -/* ======================================================== OUTCFG2 ======================================================== */ -/* ============================================= CTIMER OUTCFG2 CFG29 [28..30] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG29 */ - CTIMER_OUTCFG2_CFG29_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG29_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG29_A3OUT2 = 5, /*!< A3OUT2 : Output is A3OUT2. value. */ - CTIMER_OUTCFG2_CFG29_A7OUT = 4, /*!< A7OUT : Output is A7OUT. value. */ - CTIMER_OUTCFG2_CFG29_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ - CTIMER_OUTCFG2_CFG29_B5OUT2 = 2, /*!< B5OUT2 : Output is B5OUT2 value. */ - CTIMER_OUTCFG2_CFG29_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG29_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG29_Enum; - -/* ============================================= CTIMER OUTCFG2 CFG28 [25..27] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG28 */ - CTIMER_OUTCFG2_CFG28_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG28_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG28_B0OUT2 = 5, /*!< B0OUT2 : Output is B0OUT2. value. */ - CTIMER_OUTCFG2_CFG28_A5OUT2 = 4, /*!< A5OUT2 : Output is A5OUT2. value. */ - CTIMER_OUTCFG2_CFG28_A3OUT = 3, /*!< A3OUT : Output is A3OUT. value. */ - CTIMER_OUTCFG2_CFG28_A7OUT = 2, /*!< A7OUT : Output is A7OUT value. */ - CTIMER_OUTCFG2_CFG28_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG28_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG28_Enum; - -/* ============================================= CTIMER OUTCFG2 CFG27 [22..24] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG27 */ - CTIMER_OUTCFG2_CFG27_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG27_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG27_B2OUT2 = 5, /*!< B2OUT2 : Output is B2OUT2. value. */ - CTIMER_OUTCFG2_CFG27_B6OUT = 4, /*!< B6OUT : Output is B6OUT. value. */ - CTIMER_OUTCFG2_CFG27_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ - CTIMER_OUTCFG2_CFG27_B6OUT2 = 2, /*!< B6OUT2 : Output is B6OUT2 value. */ - CTIMER_OUTCFG2_CFG27_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG27_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG27_Enum; - -/* ============================================= CTIMER OUTCFG2 CFG26 [19..21] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG26 */ - CTIMER_OUTCFG2_CFG26_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG26_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG26_A1OUT2 = 5, /*!< A1OUT2 : Output is A1OUT2. value. */ - CTIMER_OUTCFG2_CFG26_A5OUT = 4, /*!< A5OUT : Output is A5OUT. value. */ - CTIMER_OUTCFG2_CFG26_B2OUT = 3, /*!< B2OUT : Output is B2OUT. value. */ - CTIMER_OUTCFG2_CFG26_B6OUT = 2, /*!< B6OUT : Output is B6OUT value. */ - CTIMER_OUTCFG2_CFG26_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG26_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG26_Enum; - -/* ============================================= CTIMER OUTCFG2 CFG25 [16..18] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG25 */ - CTIMER_OUTCFG2_CFG25_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG25_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG25_A2OUT2 = 5, /*!< A2OUT2 : Output is A2OUT2. value. */ - CTIMER_OUTCFG2_CFG25_A6OUT = 4, /*!< A6OUT : Output is A6OUT. value. */ - CTIMER_OUTCFG2_CFG25_B2OUT = 3, /*!< B2OUT : Output is B2OUT. value. */ - CTIMER_OUTCFG2_CFG25_B4OUT2 = 2, /*!< B4OUT2 : Output is B4OUT2 value. */ - CTIMER_OUTCFG2_CFG25_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG25_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG25_Enum; - -/* ============================================= CTIMER OUTCFG2 CFG24 [12..14] ============================================= */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG24 */ - CTIMER_OUTCFG2_CFG24_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG24_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG24_B1OUT2 = 5, /*!< B1OUT2 : Output is B1OUT2. value. */ - CTIMER_OUTCFG2_CFG24_A1OUT = 4, /*!< A1OUT : Output is A1OUT. value. */ - CTIMER_OUTCFG2_CFG24_A2OUT = 3, /*!< A2OUT : Output is A2OUT. value. */ - CTIMER_OUTCFG2_CFG24_A6OUT = 2, /*!< A6OUT : Output is A6OUT value. */ - CTIMER_OUTCFG2_CFG24_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG24_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG24_Enum; - -/* ============================================= CTIMER OUTCFG2 CFG23 [9..11] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG23 */ - CTIMER_OUTCFG2_CFG23_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG23_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG23_B0OUT2 = 5, /*!< B0OUT2 : Output is B0OUT2. value. */ - CTIMER_OUTCFG2_CFG23_A5OUT = 4, /*!< A5OUT : Output is A5OUT. value. */ - CTIMER_OUTCFG2_CFG23_A7OUT = 3, /*!< A7OUT : Output is B1OUT. value. */ - CTIMER_OUTCFG2_CFG23_B5OUT2 = 2, /*!< B5OUT2 : Output is B5OUT2 value. */ - CTIMER_OUTCFG2_CFG23_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG23_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG23_Enum; - -/* ============================================== CTIMER OUTCFG2 CFG22 [6..8] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG22 */ - CTIMER_OUTCFG2_CFG22_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG22_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG22_A2OUT2 = 5, /*!< A2OUT2 : Output is A2OUT2. value. */ - CTIMER_OUTCFG2_CFG22_A1OUT = 4, /*!< A1OUT : Output is A1OUT. value. */ - CTIMER_OUTCFG2_CFG22_A6OUT = 3, /*!< A6OUT : Output is B1OUT. value. */ - CTIMER_OUTCFG2_CFG22_B5OUT = 2, /*!< B5OUT : Output is B5OUT value. */ - CTIMER_OUTCFG2_CFG22_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG22_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG22_Enum; - -/* ============================================== CTIMER OUTCFG2 CFG21 [3..5] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG21 */ - CTIMER_OUTCFG2_CFG21_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG21_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG21_A0OUT2 = 5, /*!< A0OUT2 : Output is A0OUT2. value. */ - CTIMER_OUTCFG2_CFG21_B5OUT = 4, /*!< B5OUT : Output is B5OUT. value. */ - CTIMER_OUTCFG2_CFG21_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ - CTIMER_OUTCFG2_CFG21_A5OUT2 = 2, /*!< A5OUT2 : Output is A5OUT2 value. */ - CTIMER_OUTCFG2_CFG21_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG21_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG21_Enum; - -/* ============================================== CTIMER OUTCFG2 CFG20 [0..2] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG2_CFG20 */ - CTIMER_OUTCFG2_CFG20_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG2_CFG20_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG2_CFG20_B2OUT2 = 5, /*!< B2OUT2 : Output is B2OUT2. value. */ - CTIMER_OUTCFG2_CFG20_A1OUT2 = 4, /*!< A1OUT2 : Output is A1OUT2. value. */ - CTIMER_OUTCFG2_CFG20_A1OUT = 3, /*!< A1OUT : Output is A1OUT. value. */ - CTIMER_OUTCFG2_CFG20_A5OUT = 2, /*!< A5OUT : Output is A5OUT value. */ - CTIMER_OUTCFG2_CFG20_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG2_CFG20_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG2_CFG20_Enum; - -/* ======================================================== OUTCFG3 ======================================================== */ -/* ============================================== CTIMER OUTCFG3 CFG31 [3..5] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG3_CFG31 */ - CTIMER_OUTCFG3_CFG31_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG3_CFG31_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG3_CFG31_B3OUT2 = 5, /*!< B3OUT2 : Output is B3OUT2. value. */ - CTIMER_OUTCFG3_CFG31_B7OUT = 4, /*!< B7OUT : Output is B7OUT. value. */ - CTIMER_OUTCFG3_CFG31_A6OUT = 3, /*!< A6OUT : Output is A6OUT. value. */ - CTIMER_OUTCFG3_CFG31_B7OUT2 = 2, /*!< B7OUT2 : Output is B7OUT2 value. */ - CTIMER_OUTCFG3_CFG31_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG3_CFG31_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG3_CFG31_Enum; - -/* ============================================== CTIMER OUTCFG3 CFG30 [0..2] ============================================== */ -typedef enum { /*!< CTIMER_OUTCFG3_CFG30 */ - CTIMER_OUTCFG3_CFG30_A7OUT2 = 7, /*!< A7OUT2 : Output is A7OUT2. value. */ - CTIMER_OUTCFG3_CFG30_A6OUT2 = 6, /*!< A6OUT2 : Output is A6OUT2. value. */ - CTIMER_OUTCFG3_CFG30_A0OUT2 = 5, /*!< A0OUT2 : Output is A0OUT2. value. */ - CTIMER_OUTCFG3_CFG30_A4OUT2 = 4, /*!< A4OUT2 : Output is A4OUT2. value. */ - CTIMER_OUTCFG3_CFG30_B3OUT = 3, /*!< B3OUT : Output is B3OUT. value. */ - CTIMER_OUTCFG3_CFG30_B7OUT = 2, /*!< B7OUT : Output is B7OUT value. */ - CTIMER_OUTCFG3_CFG30_ONE = 1, /*!< ONE : Force output to 1. value. */ - CTIMER_OUTCFG3_CFG30_ZERO = 0, /*!< ZERO : Force output to 0 value. */ -} CTIMER_OUTCFG3_CFG30_Enum; - -/* ========================================================= INCFG ========================================================= */ -/* ============================================== CTIMER INCFG CFGB7 [15..15] ============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGB7 */ - CTIMER_INCFG_CFGB7_CT31 = 1, /*!< CT31 : Input is CT31 value. */ - CTIMER_INCFG_CFGB7_CT30 = 0, /*!< CT30 : Input is CT30 value. */ -} CTIMER_INCFG_CFGB7_Enum; - -/* ============================================== CTIMER INCFG CFGA7 [14..14] ============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGA7 */ - CTIMER_INCFG_CFGA7_CT29 = 1, /*!< CT29 : Input is CT29 value. */ - CTIMER_INCFG_CFGA7_CT28 = 0, /*!< CT28 : Input is CT28 value. */ -} CTIMER_INCFG_CFGA7_Enum; - -/* ============================================== CTIMER INCFG CFGB6 [13..13] ============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGB6 */ - CTIMER_INCFG_CFGB6_CT27 = 1, /*!< CT27 : Input is CT27 value. */ - CTIMER_INCFG_CFGB6_CT26 = 0, /*!< CT26 : Input is CT26 value. */ -} CTIMER_INCFG_CFGB6_Enum; - -/* ============================================== CTIMER INCFG CFGA6 [12..12] ============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGA6 */ - CTIMER_INCFG_CFGA6_CT25 = 1, /*!< CT25 : Input is CT25 value. */ - CTIMER_INCFG_CFGA6_CT24 = 0, /*!< CT24 : Input is CT24 value. */ -} CTIMER_INCFG_CFGA6_Enum; - -/* ============================================== CTIMER INCFG CFGB5 [11..11] ============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGB5 */ - CTIMER_INCFG_CFGB5_CT23 = 1, /*!< CT23 : Input is CT23 value. */ - CTIMER_INCFG_CFGB5_CT22 = 0, /*!< CT22 : Input is CT22 value. */ -} CTIMER_INCFG_CFGB5_Enum; - -/* ============================================== CTIMER INCFG CFGA5 [10..10] ============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGA5 */ - CTIMER_INCFG_CFGA5_CT21 = 1, /*!< CT21 : Input is CT21 value. */ - CTIMER_INCFG_CFGA5_CT20 = 0, /*!< CT20 : Input is CT20 value. */ -} CTIMER_INCFG_CFGA5_Enum; - -/* =============================================== CTIMER INCFG CFGB4 [9..9] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGB4 */ - CTIMER_INCFG_CFGB4_CT19 = 1, /*!< CT19 : Input is CT19 value. */ - CTIMER_INCFG_CFGB4_CT18 = 0, /*!< CT18 : Input is CT18 value. */ -} CTIMER_INCFG_CFGB4_Enum; - -/* =============================================== CTIMER INCFG CFGA4 [8..8] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGA4 */ - CTIMER_INCFG_CFGA4_CT17 = 1, /*!< CT17 : Input is CT17 value. */ - CTIMER_INCFG_CFGA4_CT16 = 0, /*!< CT16 : Input is CT16 value. */ -} CTIMER_INCFG_CFGA4_Enum; - -/* =============================================== CTIMER INCFG CFGB3 [7..7] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGB3 */ - CTIMER_INCFG_CFGB3_CT15 = 1, /*!< CT15 : Input is CT15 value. */ - CTIMER_INCFG_CFGB3_CT14 = 0, /*!< CT14 : Input is CT14 value. */ -} CTIMER_INCFG_CFGB3_Enum; - -/* =============================================== CTIMER INCFG CFGA3 [6..6] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGA3 */ - CTIMER_INCFG_CFGA3_CT13 = 1, /*!< CT13 : Input is CT13 value. */ - CTIMER_INCFG_CFGA3_CT12 = 0, /*!< CT12 : Input is CT12 value. */ -} CTIMER_INCFG_CFGA3_Enum; - -/* =============================================== CTIMER INCFG CFGB2 [5..5] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGB2 */ - CTIMER_INCFG_CFGB2_CT11 = 1, /*!< CT11 : Input is CT11 value. */ - CTIMER_INCFG_CFGB2_CT10 = 0, /*!< CT10 : Input is CT10 value. */ -} CTIMER_INCFG_CFGB2_Enum; - -/* =============================================== CTIMER INCFG CFGA2 [4..4] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGA2 */ - CTIMER_INCFG_CFGA2_CT9 = 1, /*!< CT9 : Input is CT9 value. */ - CTIMER_INCFG_CFGA2_CT8 = 0, /*!< CT8 : Input is CT8 value. */ -} CTIMER_INCFG_CFGA2_Enum; - -/* =============================================== CTIMER INCFG CFGB1 [3..3] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGB1 */ - CTIMER_INCFG_CFGB1_CT7 = 1, /*!< CT7 : Input is CT7 value. */ - CTIMER_INCFG_CFGB1_CT6 = 0, /*!< CT6 : Input is CT6 value. */ -} CTIMER_INCFG_CFGB1_Enum; - -/* =============================================== CTIMER INCFG CFGA1 [2..2] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGA1 */ - CTIMER_INCFG_CFGA1_CT5 = 1, /*!< CT5 : Input is CT5 value. */ - CTIMER_INCFG_CFGA1_CT4 = 0, /*!< CT4 : Input is CT4 value. */ -} CTIMER_INCFG_CFGA1_Enum; - -/* =============================================== CTIMER INCFG CFGB0 [1..1] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGB0 */ - CTIMER_INCFG_CFGB0_CT3 = 1, /*!< CT3 : Input is CT3 value. */ - CTIMER_INCFG_CFGB0_CT2 = 0, /*!< CT2 : Input is CT2 value. */ -} CTIMER_INCFG_CFGB0_Enum; - -/* =============================================== CTIMER INCFG CFGA0 [0..0] =============================================== */ -typedef enum { /*!< CTIMER_INCFG_CFGA0 */ - CTIMER_INCFG_CFGA0_CT1 = 1, /*!< CT1 : Input is CT1 value. */ - CTIMER_INCFG_CFGA0_CT0 = 0, /*!< CT0 : Input is CT0 value. */ -} CTIMER_INCFG_CFGA0_Enum; - -/* ========================================================= STCFG ========================================================= */ -/* ============================================= CTIMER STCFG FREEZE [31..31] ============================================== */ -typedef enum { /*!< CTIMER_STCFG_FREEZE */ - CTIMER_STCFG_FREEZE_THAW = 0, /*!< THAW : Let the COUNTER register run on its input clock. value. */ - CTIMER_STCFG_FREEZE_FREEZE = 1, /*!< FREEZE : Stop the COUNTER register for loading. value. */ -} CTIMER_STCFG_FREEZE_Enum; - -/* ============================================== CTIMER STCFG CLEAR [30..30] ============================================== */ -typedef enum { /*!< CTIMER_STCFG_CLEAR */ - CTIMER_STCFG_CLEAR_RUN = 0, /*!< RUN : Let the COUNTER register run on its input clock. value. */ - CTIMER_STCFG_CLEAR_CLEAR = 1, /*!< CLEAR : Stop the COUNTER register for loading. value. */ -} CTIMER_STCFG_CLEAR_Enum; - -/* ========================================== CTIMER STCFG COMPARE_H_EN [15..15] =========================================== */ -typedef enum { /*!< CTIMER_STCFG_COMPARE_H_EN */ - CTIMER_STCFG_COMPARE_H_EN_DISABLE = 0, /*!< DISABLE : Compare H disabled. value. */ - CTIMER_STCFG_COMPARE_H_EN_ENABLE = 1, /*!< ENABLE : Compare H enabled. value. */ -} CTIMER_STCFG_COMPARE_H_EN_Enum; - -/* ========================================== CTIMER STCFG COMPARE_G_EN [14..14] =========================================== */ -typedef enum { /*!< CTIMER_STCFG_COMPARE_G_EN */ - CTIMER_STCFG_COMPARE_G_EN_DISABLE = 0, /*!< DISABLE : Compare G disabled. value. */ - CTIMER_STCFG_COMPARE_G_EN_ENABLE = 1, /*!< ENABLE : Compare G enabled. value. */ -} CTIMER_STCFG_COMPARE_G_EN_Enum; - -/* ========================================== CTIMER STCFG COMPARE_F_EN [13..13] =========================================== */ -typedef enum { /*!< CTIMER_STCFG_COMPARE_F_EN */ - CTIMER_STCFG_COMPARE_F_EN_DISABLE = 0, /*!< DISABLE : Compare F disabled. value. */ - CTIMER_STCFG_COMPARE_F_EN_ENABLE = 1, /*!< ENABLE : Compare F enabled. value. */ -} CTIMER_STCFG_COMPARE_F_EN_Enum; - -/* ========================================== CTIMER STCFG COMPARE_E_EN [12..12] =========================================== */ -typedef enum { /*!< CTIMER_STCFG_COMPARE_E_EN */ - CTIMER_STCFG_COMPARE_E_EN_DISABLE = 0, /*!< DISABLE : Compare E disabled. value. */ - CTIMER_STCFG_COMPARE_E_EN_ENABLE = 1, /*!< ENABLE : Compare E enabled. value. */ -} CTIMER_STCFG_COMPARE_E_EN_Enum; - -/* ========================================== CTIMER STCFG COMPARE_D_EN [11..11] =========================================== */ -typedef enum { /*!< CTIMER_STCFG_COMPARE_D_EN */ - CTIMER_STCFG_COMPARE_D_EN_DISABLE = 0, /*!< DISABLE : Compare D disabled. value. */ - CTIMER_STCFG_COMPARE_D_EN_ENABLE = 1, /*!< ENABLE : Compare D enabled. value. */ -} CTIMER_STCFG_COMPARE_D_EN_Enum; - -/* ========================================== CTIMER STCFG COMPARE_C_EN [10..10] =========================================== */ -typedef enum { /*!< CTIMER_STCFG_COMPARE_C_EN */ - CTIMER_STCFG_COMPARE_C_EN_DISABLE = 0, /*!< DISABLE : Compare C disabled. value. */ - CTIMER_STCFG_COMPARE_C_EN_ENABLE = 1, /*!< ENABLE : Compare C enabled. value. */ -} CTIMER_STCFG_COMPARE_C_EN_Enum; - -/* =========================================== CTIMER STCFG COMPARE_B_EN [9..9] ============================================ */ -typedef enum { /*!< CTIMER_STCFG_COMPARE_B_EN */ - CTIMER_STCFG_COMPARE_B_EN_DISABLE = 0, /*!< DISABLE : Compare B disabled. value. */ - CTIMER_STCFG_COMPARE_B_EN_ENABLE = 1, /*!< ENABLE : Compare B enabled. value. */ -} CTIMER_STCFG_COMPARE_B_EN_Enum; - -/* =========================================== CTIMER STCFG COMPARE_A_EN [8..8] ============================================ */ -typedef enum { /*!< CTIMER_STCFG_COMPARE_A_EN */ - CTIMER_STCFG_COMPARE_A_EN_DISABLE = 0, /*!< DISABLE : Compare A disabled. value. */ - CTIMER_STCFG_COMPARE_A_EN_ENABLE = 1, /*!< ENABLE : Compare A enabled. value. */ -} CTIMER_STCFG_COMPARE_A_EN_Enum; - -/* ============================================== CTIMER STCFG CLKSEL [0..3] =============================================== */ -typedef enum { /*!< CTIMER_STCFG_CLKSEL */ - CTIMER_STCFG_CLKSEL_NOCLK = 0, /*!< NOCLK : No clock enabled. value. */ - CTIMER_STCFG_CLKSEL_HFRC_DIV16 = 1, /*!< HFRC_DIV16 : 3MHz from the HFRC clock divider. value. */ - CTIMER_STCFG_CLKSEL_HFRC_DIV256 = 2, /*!< HFRC_DIV256 : 187.5KHz from the HFRC clock divider. value. */ - CTIMER_STCFG_CLKSEL_XTAL_DIV1 = 3, /*!< XTAL_DIV1 : 32768Hz from the crystal oscillator. value. */ - CTIMER_STCFG_CLKSEL_XTAL_DIV2 = 4, /*!< XTAL_DIV2 : 16384Hz from the crystal oscillator. value. */ - CTIMER_STCFG_CLKSEL_XTAL_DIV32 = 5, /*!< XTAL_DIV32 : 1024Hz from the crystal oscillator. value. */ - CTIMER_STCFG_CLKSEL_LFRC_DIV1 = 6, /*!< LFRC_DIV1 : Approximately 1KHz from the LFRC oscillator (uncalibrated). - value. */ - CTIMER_STCFG_CLKSEL_CTIMER0A = 7, /*!< CTIMER0A : Use CTIMER 0 section A as a prescaler for the clock - source. value. */ - CTIMER_STCFG_CLKSEL_CTIMER0B = 8, /*!< CTIMER0B : Use CTIMER 0 section B (or A and B linked together) - as a prescaler for the clock source. value. */ -} CTIMER_STCFG_CLKSEL_Enum; - -/* ========================================================= STTMR ========================================================= */ -/* ==================================================== CAPTURECONTROL ===================================================== */ -/* ========================================= CTIMER CAPTURECONTROL CAPTURE3 [3..3] ========================================= */ -typedef enum { /*!< CTIMER_CAPTURECONTROL_CAPTURE3 */ - CTIMER_CAPTURECONTROL_CAPTURE3_DISABLE = 0, /*!< DISABLE : Capture function disabled. value. */ - CTIMER_CAPTURECONTROL_CAPTURE3_ENABLE = 1, /*!< ENABLE : Capture function enabled. value. */ -} CTIMER_CAPTURECONTROL_CAPTURE3_Enum; - -/* ========================================= CTIMER CAPTURECONTROL CAPTURE2 [2..2] ========================================= */ -typedef enum { /*!< CTIMER_CAPTURECONTROL_CAPTURE2 */ - CTIMER_CAPTURECONTROL_CAPTURE2_DISABLE = 0, /*!< DISABLE : Capture function disabled. value. */ - CTIMER_CAPTURECONTROL_CAPTURE2_ENABLE = 1, /*!< ENABLE : Capture function enabled. value. */ -} CTIMER_CAPTURECONTROL_CAPTURE2_Enum; - -/* ========================================= CTIMER CAPTURECONTROL CAPTURE1 [1..1] ========================================= */ -typedef enum { /*!< CTIMER_CAPTURECONTROL_CAPTURE1 */ - CTIMER_CAPTURECONTROL_CAPTURE1_DISABLE = 0, /*!< DISABLE : Capture function disabled. value. */ - CTIMER_CAPTURECONTROL_CAPTURE1_ENABLE = 1, /*!< ENABLE : Capture function enabled. value. */ -} CTIMER_CAPTURECONTROL_CAPTURE1_Enum; - -/* ========================================= CTIMER CAPTURECONTROL CAPTURE0 [0..0] ========================================= */ -typedef enum { /*!< CTIMER_CAPTURECONTROL_CAPTURE0 */ - CTIMER_CAPTURECONTROL_CAPTURE0_DISABLE = 0, /*!< DISABLE : Capture function disabled. value. */ - CTIMER_CAPTURECONTROL_CAPTURE0_ENABLE = 1, /*!< ENABLE : Capture function enabled. value. */ -} CTIMER_CAPTURECONTROL_CAPTURE0_Enum; - -/* ======================================================== SCMPR0 ========================================================= */ -/* ======================================================== SCMPR1 ========================================================= */ -/* ======================================================== SCMPR2 ========================================================= */ -/* ======================================================== SCMPR3 ========================================================= */ -/* ======================================================== SCMPR4 ========================================================= */ -/* ======================================================== SCMPR5 ========================================================= */ -/* ======================================================== SCMPR6 ========================================================= */ -/* ======================================================== SCMPR7 ========================================================= */ -/* ======================================================== SCAPT0 ========================================================= */ -/* ======================================================== SCAPT1 ========================================================= */ -/* ======================================================== SCAPT2 ========================================================= */ -/* ======================================================== SCAPT3 ========================================================= */ -/* ========================================================= SNVR0 ========================================================= */ -/* ========================================================= SNVR1 ========================================================= */ -/* ========================================================= SNVR2 ========================================================= */ -/* ========================================================= SNVR3 ========================================================= */ -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ -/* ======================================================= STMINTEN ======================================================== */ -/* =========================================== CTIMER STMINTEN CAPTURED [12..12] =========================================== */ -typedef enum { /*!< CTIMER_STMINTEN_CAPTURED */ - CTIMER_STMINTEN_CAPTURED_CAPD_INT = 1, /*!< CAPD_INT : Capture D interrupt status bit was set. value. */ -} CTIMER_STMINTEN_CAPTURED_Enum; - -/* =========================================== CTIMER STMINTEN CAPTUREC [11..11] =========================================== */ -typedef enum { /*!< CTIMER_STMINTEN_CAPTUREC */ - CTIMER_STMINTEN_CAPTUREC_CAPC_INT = 1, /*!< CAPC_INT : CAPTURE C interrupt status bit was set. value. */ -} CTIMER_STMINTEN_CAPTUREC_Enum; - -/* =========================================== CTIMER STMINTEN CAPTUREB [10..10] =========================================== */ -typedef enum { /*!< CTIMER_STMINTEN_CAPTUREB */ - CTIMER_STMINTEN_CAPTUREB_CAPB_INT = 1, /*!< CAPB_INT : CAPTURE B interrupt status bit was set. value. */ -} CTIMER_STMINTEN_CAPTUREB_Enum; - -/* ============================================ CTIMER STMINTEN CAPTUREA [9..9] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_CAPTUREA */ - CTIMER_STMINTEN_CAPTUREA_CAPA_INT = 1, /*!< CAPA_INT : CAPTURE A interrupt status bit was set. value. */ -} CTIMER_STMINTEN_CAPTUREA_Enum; - -/* ============================================ CTIMER STMINTEN OVERFLOW [8..8] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_OVERFLOW */ - CTIMER_STMINTEN_OVERFLOW_OFLOW_INT = 1, /*!< OFLOW_INT : Overflow interrupt status bit was set. value. */ -} CTIMER_STMINTEN_OVERFLOW_Enum; - -/* ============================================ CTIMER STMINTEN COMPAREH [7..7] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_COMPAREH */ - CTIMER_STMINTEN_COMPAREH_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTEN_COMPAREH_Enum; - -/* ============================================ CTIMER STMINTEN COMPAREG [6..6] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_COMPAREG */ - CTIMER_STMINTEN_COMPAREG_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTEN_COMPAREG_Enum; - -/* ============================================ CTIMER STMINTEN COMPAREF [5..5] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_COMPAREF */ - CTIMER_STMINTEN_COMPAREF_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTEN_COMPAREF_Enum; - -/* ============================================ CTIMER STMINTEN COMPAREE [4..4] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_COMPAREE */ - CTIMER_STMINTEN_COMPAREE_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTEN_COMPAREE_Enum; - -/* ============================================ CTIMER STMINTEN COMPARED [3..3] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_COMPARED */ - CTIMER_STMINTEN_COMPARED_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTEN_COMPARED_Enum; - -/* ============================================ CTIMER STMINTEN COMPAREC [2..2] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_COMPAREC */ - CTIMER_STMINTEN_COMPAREC_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTEN_COMPAREC_Enum; - -/* ============================================ CTIMER STMINTEN COMPAREB [1..1] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_COMPAREB */ - CTIMER_STMINTEN_COMPAREB_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTEN_COMPAREB_Enum; - -/* ============================================ CTIMER STMINTEN COMPAREA [0..0] ============================================ */ -typedef enum { /*!< CTIMER_STMINTEN_COMPAREA */ - CTIMER_STMINTEN_COMPAREA_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTEN_COMPAREA_Enum; - -/* ====================================================== STMINTSTAT ======================================================= */ -/* ========================================== CTIMER STMINTSTAT CAPTURED [12..12] ========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_CAPTURED */ - CTIMER_STMINTSTAT_CAPTURED_CAPD_INT = 1, /*!< CAPD_INT : Capture D interrupt status bit was set. value. */ -} CTIMER_STMINTSTAT_CAPTURED_Enum; - -/* ========================================== CTIMER STMINTSTAT CAPTUREC [11..11] ========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_CAPTUREC */ - CTIMER_STMINTSTAT_CAPTUREC_CAPC_INT = 1, /*!< CAPC_INT : CAPTURE C interrupt status bit was set. value. */ -} CTIMER_STMINTSTAT_CAPTUREC_Enum; - -/* ========================================== CTIMER STMINTSTAT CAPTUREB [10..10] ========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_CAPTUREB */ - CTIMER_STMINTSTAT_CAPTUREB_CAPB_INT = 1, /*!< CAPB_INT : CAPTURE B interrupt status bit was set. value. */ -} CTIMER_STMINTSTAT_CAPTUREB_Enum; - -/* =========================================== CTIMER STMINTSTAT CAPTUREA [9..9] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_CAPTUREA */ - CTIMER_STMINTSTAT_CAPTUREA_CAPA_INT = 1, /*!< CAPA_INT : CAPTURE A interrupt status bit was set. value. */ -} CTIMER_STMINTSTAT_CAPTUREA_Enum; - -/* =========================================== CTIMER STMINTSTAT OVERFLOW [8..8] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_OVERFLOW */ - CTIMER_STMINTSTAT_OVERFLOW_OFLOW_INT = 1, /*!< OFLOW_INT : Overflow interrupt status bit was set. value. */ -} CTIMER_STMINTSTAT_OVERFLOW_Enum; - -/* =========================================== CTIMER STMINTSTAT COMPAREH [7..7] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREH */ - CTIMER_STMINTSTAT_COMPAREH_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSTAT_COMPAREH_Enum; - -/* =========================================== CTIMER STMINTSTAT COMPAREG [6..6] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREG */ - CTIMER_STMINTSTAT_COMPAREG_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSTAT_COMPAREG_Enum; - -/* =========================================== CTIMER STMINTSTAT COMPAREF [5..5] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREF */ - CTIMER_STMINTSTAT_COMPAREF_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSTAT_COMPAREF_Enum; - -/* =========================================== CTIMER STMINTSTAT COMPAREE [4..4] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREE */ - CTIMER_STMINTSTAT_COMPAREE_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSTAT_COMPAREE_Enum; - -/* =========================================== CTIMER STMINTSTAT COMPARED [3..3] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_COMPARED */ - CTIMER_STMINTSTAT_COMPARED_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSTAT_COMPARED_Enum; - -/* =========================================== CTIMER STMINTSTAT COMPAREC [2..2] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREC */ - CTIMER_STMINTSTAT_COMPAREC_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSTAT_COMPAREC_Enum; - -/* =========================================== CTIMER STMINTSTAT COMPAREB [1..1] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREB */ - CTIMER_STMINTSTAT_COMPAREB_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSTAT_COMPAREB_Enum; - -/* =========================================== CTIMER STMINTSTAT COMPAREA [0..0] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSTAT_COMPAREA */ - CTIMER_STMINTSTAT_COMPAREA_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSTAT_COMPAREA_Enum; - -/* ======================================================= STMINTCLR ======================================================= */ -/* ========================================== CTIMER STMINTCLR CAPTURED [12..12] =========================================== */ -typedef enum { /*!< CTIMER_STMINTCLR_CAPTURED */ - CTIMER_STMINTCLR_CAPTURED_CAPD_INT = 1, /*!< CAPD_INT : Capture D interrupt status bit was set. value. */ -} CTIMER_STMINTCLR_CAPTURED_Enum; - -/* ========================================== CTIMER STMINTCLR CAPTUREC [11..11] =========================================== */ -typedef enum { /*!< CTIMER_STMINTCLR_CAPTUREC */ - CTIMER_STMINTCLR_CAPTUREC_CAPC_INT = 1, /*!< CAPC_INT : CAPTURE C interrupt status bit was set. value. */ -} CTIMER_STMINTCLR_CAPTUREC_Enum; - -/* ========================================== CTIMER STMINTCLR CAPTUREB [10..10] =========================================== */ -typedef enum { /*!< CTIMER_STMINTCLR_CAPTUREB */ - CTIMER_STMINTCLR_CAPTUREB_CAPB_INT = 1, /*!< CAPB_INT : CAPTURE B interrupt status bit was set. value. */ -} CTIMER_STMINTCLR_CAPTUREB_Enum; - -/* =========================================== CTIMER STMINTCLR CAPTUREA [9..9] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_CAPTUREA */ - CTIMER_STMINTCLR_CAPTUREA_CAPA_INT = 1, /*!< CAPA_INT : CAPTURE A interrupt status bit was set. value. */ -} CTIMER_STMINTCLR_CAPTUREA_Enum; - -/* =========================================== CTIMER STMINTCLR OVERFLOW [8..8] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_OVERFLOW */ - CTIMER_STMINTCLR_OVERFLOW_OFLOW_INT = 1, /*!< OFLOW_INT : Overflow interrupt status bit was set. value. */ -} CTIMER_STMINTCLR_OVERFLOW_Enum; - -/* =========================================== CTIMER STMINTCLR COMPAREH [7..7] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_COMPAREH */ - CTIMER_STMINTCLR_COMPAREH_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTCLR_COMPAREH_Enum; - -/* =========================================== CTIMER STMINTCLR COMPAREG [6..6] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_COMPAREG */ - CTIMER_STMINTCLR_COMPAREG_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTCLR_COMPAREG_Enum; - -/* =========================================== CTIMER STMINTCLR COMPAREF [5..5] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_COMPAREF */ - CTIMER_STMINTCLR_COMPAREF_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTCLR_COMPAREF_Enum; - -/* =========================================== CTIMER STMINTCLR COMPAREE [4..4] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_COMPAREE */ - CTIMER_STMINTCLR_COMPAREE_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTCLR_COMPAREE_Enum; - -/* =========================================== CTIMER STMINTCLR COMPARED [3..3] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_COMPARED */ - CTIMER_STMINTCLR_COMPARED_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTCLR_COMPARED_Enum; - -/* =========================================== CTIMER STMINTCLR COMPAREC [2..2] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_COMPAREC */ - CTIMER_STMINTCLR_COMPAREC_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTCLR_COMPAREC_Enum; - -/* =========================================== CTIMER STMINTCLR COMPAREB [1..1] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_COMPAREB */ - CTIMER_STMINTCLR_COMPAREB_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTCLR_COMPAREB_Enum; - -/* =========================================== CTIMER STMINTCLR COMPAREA [0..0] ============================================ */ -typedef enum { /*!< CTIMER_STMINTCLR_COMPAREA */ - CTIMER_STMINTCLR_COMPAREA_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTCLR_COMPAREA_Enum; - -/* ======================================================= STMINTSET ======================================================= */ -/* ========================================== CTIMER STMINTSET CAPTURED [12..12] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSET_CAPTURED */ - CTIMER_STMINTSET_CAPTURED_CAPD_INT = 1, /*!< CAPD_INT : Capture D interrupt status bit was set. value. */ -} CTIMER_STMINTSET_CAPTURED_Enum; - -/* ========================================== CTIMER STMINTSET CAPTUREC [11..11] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSET_CAPTUREC */ - CTIMER_STMINTSET_CAPTUREC_CAPC_INT = 1, /*!< CAPC_INT : CAPTURE C interrupt status bit was set. value. */ -} CTIMER_STMINTSET_CAPTUREC_Enum; - -/* ========================================== CTIMER STMINTSET CAPTUREB [10..10] =========================================== */ -typedef enum { /*!< CTIMER_STMINTSET_CAPTUREB */ - CTIMER_STMINTSET_CAPTUREB_CAPB_INT = 1, /*!< CAPB_INT : CAPTURE B interrupt status bit was set. value. */ -} CTIMER_STMINTSET_CAPTUREB_Enum; - -/* =========================================== CTIMER STMINTSET CAPTUREA [9..9] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_CAPTUREA */ - CTIMER_STMINTSET_CAPTUREA_CAPA_INT = 1, /*!< CAPA_INT : CAPTURE A interrupt status bit was set. value. */ -} CTIMER_STMINTSET_CAPTUREA_Enum; - -/* =========================================== CTIMER STMINTSET OVERFLOW [8..8] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_OVERFLOW */ - CTIMER_STMINTSET_OVERFLOW_OFLOW_INT = 1, /*!< OFLOW_INT : Overflow interrupt status bit was set. value. */ -} CTIMER_STMINTSET_OVERFLOW_Enum; - -/* =========================================== CTIMER STMINTSET COMPAREH [7..7] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_COMPAREH */ - CTIMER_STMINTSET_COMPAREH_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSET_COMPAREH_Enum; - -/* =========================================== CTIMER STMINTSET COMPAREG [6..6] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_COMPAREG */ - CTIMER_STMINTSET_COMPAREG_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSET_COMPAREG_Enum; - -/* =========================================== CTIMER STMINTSET COMPAREF [5..5] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_COMPAREF */ - CTIMER_STMINTSET_COMPAREF_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSET_COMPAREF_Enum; - -/* =========================================== CTIMER STMINTSET COMPAREE [4..4] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_COMPAREE */ - CTIMER_STMINTSET_COMPAREE_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSET_COMPAREE_Enum; - -/* =========================================== CTIMER STMINTSET COMPARED [3..3] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_COMPARED */ - CTIMER_STMINTSET_COMPARED_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSET_COMPARED_Enum; - -/* =========================================== CTIMER STMINTSET COMPAREC [2..2] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_COMPAREC */ - CTIMER_STMINTSET_COMPAREC_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSET_COMPAREC_Enum; - -/* =========================================== CTIMER STMINTSET COMPAREB [1..1] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_COMPAREB */ - CTIMER_STMINTSET_COMPAREB_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSET_COMPAREB_Enum; - -/* =========================================== CTIMER STMINTSET COMPAREA [0..0] ============================================ */ -typedef enum { /*!< CTIMER_STMINTSET_COMPAREA */ - CTIMER_STMINTSET_COMPAREA_COMPARED = 1, /*!< COMPARED : COUNTER greater than or equal to COMPARE register. - value. */ -} CTIMER_STMINTSET_COMPAREA_Enum; - - - -/* =========================================================================================================================== */ -/* ================ GPIO ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== PADREGA ======================================================== */ -/* ============================================ GPIO PADREGA PAD3PWRUP [30..30] ============================================ */ -typedef enum { /*!< GPIO_PADREGA_PAD3PWRUP */ - GPIO_PADREGA_PAD3PWRUP_DIS = 0, /*!< DIS : Power switch disabled value. */ - GPIO_PADREGA_PAD3PWRUP_EN = 1, /*!< EN : Power switch enabled (switched to VDD) value. */ -} GPIO_PADREGA_PAD3PWRUP_Enum; - -/* =========================================== GPIO PADREGA PAD3FNCSEL [27..29] ============================================ */ -typedef enum { /*!< GPIO_PADREGA_PAD3FNCSEL */ - GPIO_PADREGA_PAD3FNCSEL_UA0RTS = 0, /*!< UA0RTS : Configure as the UART0 RTS output value. */ - GPIO_PADREGA_PAD3FNCSEL_SLnCE = 1, /*!< SLnCE : Configure as the IOSLAVE SPI nCE signal value. */ - GPIO_PADREGA_PAD3FNCSEL_NCE3 = 2, /*!< NCE3 : IOM/MSPI nCE group 3 value. */ - GPIO_PADREGA_PAD3FNCSEL_GPIO3 = 3, /*!< GPIO3 : Configure as GPIO3 value. */ - GPIO_PADREGA_PAD3FNCSEL_MSPI7 = 5, /*!< MSPI7 : MSPI data connection 7 value. */ - GPIO_PADREGA_PAD3FNCSEL_TRIG1 = 6, /*!< TRIG1 : Configure as the ADC Trigger 1 signal value. */ - GPIO_PADREGA_PAD3FNCSEL_I2S_WCLK = 7, /*!< I2S_WCLK : Configure as the PDM I2S Word Clock input value. */ -} GPIO_PADREGA_PAD3FNCSEL_Enum; - -/* ============================================ GPIO PADREGA PAD3STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGA_PAD3STRNG */ - GPIO_PADREGA_PAD3STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGA_PAD3STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGA_PAD3STRNG_Enum; - -/* ============================================ GPIO PADREGA PAD3INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGA_PAD3INPEN */ - GPIO_PADREGA_PAD3INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGA_PAD3INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGA_PAD3INPEN_Enum; - -/* ============================================ GPIO PADREGA PAD3PULL [24..24] ============================================= */ -typedef enum { /*!< GPIO_PADREGA_PAD3PULL */ - GPIO_PADREGA_PAD3PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGA_PAD3PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGA_PAD3PULL_Enum; - -/* =========================================== GPIO PADREGA PAD2FNCSEL [19..21] ============================================ */ -typedef enum { /*!< GPIO_PADREGA_PAD2FNCSEL */ - GPIO_PADREGA_PAD2FNCSEL_SLMISO = 1, /*!< SLMISO : Configure as the IOSLAVE SPI MISO signal value. */ - GPIO_PADREGA_PAD2FNCSEL_UART0RX = 2, /*!< UART0RX : Configure as the UART0 RX input value. */ - GPIO_PADREGA_PAD2FNCSEL_GPIO2 = 3, /*!< GPIO2 : Configure as GPIO2 value. */ - GPIO_PADREGA_PAD2FNCSEL_MSPI6 = 5, /*!< MSPI6 : CMSPI data connection 6 value. */ - GPIO_PADREGA_PAD2FNCSEL_NCE2 = 7, /*!< NCE2 : IOM/MSPI nCE group 2 value. */ -} GPIO_PADREGA_PAD2FNCSEL_Enum; - -/* ============================================ GPIO PADREGA PAD2STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGA_PAD2STRNG */ - GPIO_PADREGA_PAD2STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGA_PAD2STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGA_PAD2STRNG_Enum; - -/* ============================================ GPIO PADREGA PAD2INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGA_PAD2INPEN */ - GPIO_PADREGA_PAD2INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGA_PAD2INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGA_PAD2INPEN_Enum; - -/* ============================================ GPIO PADREGA PAD2PULL [16..16] ============================================= */ -typedef enum { /*!< GPIO_PADREGA_PAD2PULL */ - GPIO_PADREGA_PAD2PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGA_PAD2PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGA_PAD2PULL_Enum; - -/* ============================================ GPIO PADREGA PAD1RSEL [14..15] ============================================= */ -typedef enum { /*!< GPIO_PADREGA_PAD1RSEL */ - GPIO_PADREGA_PAD1RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGA_PAD1RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGA_PAD1RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGA_PAD1RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGA_PAD1RSEL_Enum; - -/* =========================================== GPIO PADREGA PAD1FNCSEL [11..13] ============================================ */ -typedef enum { /*!< GPIO_PADREGA_PAD1FNCSEL */ - GPIO_PADREGA_PAD1FNCSEL_SLSDAWIR3 = 0, /*!< SLSDAWIR3 : Configure as the IOSLAVE I2C SDA or SPI WIR3 signal - value. */ - GPIO_PADREGA_PAD1FNCSEL_SLMOSI = 1, /*!< SLMOSI : Configure as the IOSLAVE SPI MOSI signal value. */ - GPIO_PADREGA_PAD1FNCSEL_UART0TX = 2, /*!< UART0TX : Configure as the UART0 TX output signal value. */ - GPIO_PADREGA_PAD1FNCSEL_GPIO1 = 3, /*!< GPIO1 : Configure as GPIO1 value. */ - GPIO_PADREGA_PAD1FNCSEL_MSPI5 = 5, /*!< MSPI5 : MSPI data connection 5 value. */ - GPIO_PADREGA_PAD1FNCSEL_NCE1 = 7, /*!< NCE1 : IOM/MSPI nCE group 1 value. */ -} GPIO_PADREGA_PAD1FNCSEL_Enum; - -/* ============================================ GPIO PADREGA PAD1STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGA_PAD1STRNG */ - GPIO_PADREGA_PAD1STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGA_PAD1STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGA_PAD1STRNG_Enum; - -/* ============================================= GPIO PADREGA PAD1INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGA_PAD1INPEN */ - GPIO_PADREGA_PAD1INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGA_PAD1INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGA_PAD1INPEN_Enum; - -/* ============================================= GPIO PADREGA PAD1PULL [8..8] ============================================== */ -typedef enum { /*!< GPIO_PADREGA_PAD1PULL */ - GPIO_PADREGA_PAD1PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGA_PAD1PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGA_PAD1PULL_Enum; - -/* ============================================= GPIO PADREGA PAD0RSEL [6..7] ============================================== */ -typedef enum { /*!< GPIO_PADREGA_PAD0RSEL */ - GPIO_PADREGA_PAD0RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGA_PAD0RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGA_PAD0RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGA_PAD0RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGA_PAD0RSEL_Enum; - -/* ============================================ GPIO PADREGA PAD0FNCSEL [3..5] ============================================= */ -typedef enum { /*!< GPIO_PADREGA_PAD0FNCSEL */ - GPIO_PADREGA_PAD0FNCSEL_SLSCL = 0, /*!< SLSCL : Configure as the IOSLAVE I2C SCL signal value. */ - GPIO_PADREGA_PAD0FNCSEL_SLSCK = 1, /*!< SLSCK : Configure as the IOSLAVE SPI SCK signal value. */ - GPIO_PADREGA_PAD0FNCSEL_CLKOUT = 2, /*!< CLKOUT : Configure as the CLKOUT signal value. */ - GPIO_PADREGA_PAD0FNCSEL_GPIO0 = 3, /*!< GPIO0 : Configure as GPIO0 value. */ - GPIO_PADREGA_PAD0FNCSEL_MSPI4 = 5, /*!< MSPI4 : MSPI data connection 4 value. */ - GPIO_PADREGA_PAD0FNCSEL_NCE0 = 7, /*!< NCE0 : IOM/MSPI nCE group 0 value. */ -} GPIO_PADREGA_PAD0FNCSEL_Enum; - -/* ============================================= GPIO PADREGA PAD0STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGA_PAD0STRNG */ - GPIO_PADREGA_PAD0STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGA_PAD0STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGA_PAD0STRNG_Enum; - -/* ============================================= GPIO PADREGA PAD0INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGA_PAD0INPEN */ - GPIO_PADREGA_PAD0INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGA_PAD0INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGA_PAD0INPEN_Enum; - -/* ============================================= GPIO PADREGA PAD0PULL [0..0] ============================================== */ -typedef enum { /*!< GPIO_PADREGA_PAD0PULL */ - GPIO_PADREGA_PAD0PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGA_PAD0PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGA_PAD0PULL_Enum; - -/* ======================================================== PADREGB ======================================================== */ -/* =========================================== GPIO PADREGB PAD7FNCSEL [27..29] ============================================ */ -typedef enum { /*!< GPIO_PADREGB_PAD7FNCSEL */ - GPIO_PADREGB_PAD7FNCSEL_NCE7 = 0, /*!< NCE7 : IOM/MSPI nCE group 7 value. */ - GPIO_PADREGB_PAD7FNCSEL_M0MOSI = 1, /*!< M0MOSI : Configure as the IOMSTR0 SPI MOSI signal value. */ - GPIO_PADREGB_PAD7FNCSEL_CLKOUT = 2, /*!< CLKOUT : Configure as the CLKOUT signal value. */ - GPIO_PADREGB_PAD7FNCSEL_GPIO7 = 3, /*!< GPIO7 : Configure as GPIO7 value. */ - GPIO_PADREGB_PAD7FNCSEL_TRIG0 = 4, /*!< TRIG0 : Configure as the ADC Trigger 0 signal value. */ - GPIO_PADREGB_PAD7FNCSEL_UART0TX = 5, /*!< UART0TX : Configure as the UART0 TX output signal value. */ - GPIO_PADREGB_PAD7FNCSEL_CT19 = 7, /*!< CT19 : CTIMER connection 19 value. */ -} GPIO_PADREGB_PAD7FNCSEL_Enum; - -/* ============================================ GPIO PADREGB PAD7STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGB_PAD7STRNG */ - GPIO_PADREGB_PAD7STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGB_PAD7STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGB_PAD7STRNG_Enum; - -/* ============================================ GPIO PADREGB PAD7INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGB_PAD7INPEN */ - GPIO_PADREGB_PAD7INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGB_PAD7INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGB_PAD7INPEN_Enum; - -/* ============================================ GPIO PADREGB PAD7PULL [24..24] ============================================= */ -typedef enum { /*!< GPIO_PADREGB_PAD7PULL */ - GPIO_PADREGB_PAD7PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGB_PAD7PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGB_PAD7PULL_Enum; - -/* ============================================ GPIO PADREGB PAD6RSEL [22..23] ============================================= */ -typedef enum { /*!< GPIO_PADREGB_PAD6RSEL */ - GPIO_PADREGB_PAD6RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGB_PAD6RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGB_PAD6RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGB_PAD6RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGB_PAD6RSEL_Enum; - -/* =========================================== GPIO PADREGB PAD6FNCSEL [19..21] ============================================ */ -typedef enum { /*!< GPIO_PADREGB_PAD6FNCSEL */ - GPIO_PADREGB_PAD6FNCSEL_M0SDAWIR3 = 0, /*!< M0SDAWIR3 : Configure as the IOMSTR0 I2C SDA or SPI WIR3 signal - value. */ - GPIO_PADREGB_PAD6FNCSEL_M0MISO = 1, /*!< M0MISO : Configure as the IOMSTR0 SPI MISO signal value. */ - GPIO_PADREGB_PAD6FNCSEL_UA0CTS = 2, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ - GPIO_PADREGB_PAD6FNCSEL_GPIO6 = 3, /*!< GPIO6 : Configure as GPIO6 value. */ - GPIO_PADREGB_PAD6FNCSEL_CT10 = 5, /*!< CT10 : CTIMER connection 10 value. */ - GPIO_PADREGB_PAD6FNCSEL_I2S_DAT = 7, /*!< I2S_DAT : Configure as the PDM I2S Data output signal value. */ -} GPIO_PADREGB_PAD6FNCSEL_Enum; - -/* ============================================ GPIO PADREGB PAD6STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGB_PAD6STRNG */ - GPIO_PADREGB_PAD6STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGB_PAD6STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGB_PAD6STRNG_Enum; - -/* ============================================ GPIO PADREGB PAD6INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGB_PAD6INPEN */ - GPIO_PADREGB_PAD6INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGB_PAD6INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGB_PAD6INPEN_Enum; - -/* ============================================ GPIO PADREGB PAD6PULL [16..16] ============================================= */ -typedef enum { /*!< GPIO_PADREGB_PAD6PULL */ - GPIO_PADREGB_PAD6PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGB_PAD6PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGB_PAD6PULL_Enum; - -/* ============================================ GPIO PADREGB PAD5RSEL [14..15] ============================================= */ -typedef enum { /*!< GPIO_PADREGB_PAD5RSEL */ - GPIO_PADREGB_PAD5RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGB_PAD5RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGB_PAD5RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGB_PAD5RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGB_PAD5RSEL_Enum; - -/* =========================================== GPIO PADREGB PAD5FNCSEL [11..13] ============================================ */ -typedef enum { /*!< GPIO_PADREGB_PAD5FNCSEL */ - GPIO_PADREGB_PAD5FNCSEL_M0SCL = 0, /*!< M0SCL : Configure as the IOMSTR0 I2C SCL signal value. */ - GPIO_PADREGB_PAD5FNCSEL_M0SCK = 1, /*!< M0SCK : Configure as the IOMSTR0 SPI SCK signal value. */ - GPIO_PADREGB_PAD5FNCSEL_UA0RTS = 2, /*!< UA0RTS : Configure as the UART0 RTS signal output value. */ - GPIO_PADREGB_PAD5FNCSEL_GPIO5 = 3, /*!< GPIO5 : Configure as GPIO5 value. */ - GPIO_PADREGB_PAD5FNCSEL_EXTHFA = 5, /*!< EXTHFA : Configure as the External HFA input clock value. */ - GPIO_PADREGB_PAD5FNCSEL_CT8 = 7, /*!< CT8 : CTIMER connection 8 value. */ -} GPIO_PADREGB_PAD5FNCSEL_Enum; - -/* ============================================ GPIO PADREGB PAD5STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGB_PAD5STRNG */ - GPIO_PADREGB_PAD5STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGB_PAD5STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGB_PAD5STRNG_Enum; - -/* ============================================= GPIO PADREGB PAD5INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGB_PAD5INPEN */ - GPIO_PADREGB_PAD5INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGB_PAD5INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGB_PAD5INPEN_Enum; - -/* ============================================= GPIO PADREGB PAD5PULL [8..8] ============================================== */ -typedef enum { /*!< GPIO_PADREGB_PAD5PULL */ - GPIO_PADREGB_PAD5PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGB_PAD5PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGB_PAD5PULL_Enum; - -/* ============================================ GPIO PADREGB PAD4FNCSEL [3..5] ============================================= */ -typedef enum { /*!< GPIO_PADREGB_PAD4FNCSEL */ - GPIO_PADREGB_PAD4FNCSEL_UA0CTS = 0, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ - GPIO_PADREGB_PAD4FNCSEL_SLINT = 1, /*!< SLINT : Configure as the IOSLAVE interrupt out signal value. */ - GPIO_PADREGB_PAD4FNCSEL_NCE4 = 2, /*!< NCE4 : IOM/SPI nCE group 4 value. */ - GPIO_PADREGB_PAD4FNCSEL_GPIO4 = 3, /*!< GPIO4 : Configure as GPIO4 value. */ - GPIO_PADREGB_PAD4FNCSEL_UART0RX = 5, /*!< UART0RX : Configure as the UART0 RX input value. */ - GPIO_PADREGB_PAD4FNCSEL_CT17 = 6, /*!< CT17 : CTIMER connection 17 value. */ - GPIO_PADREGB_PAD4FNCSEL_MSPI2 = 7, /*!< MSPI2 : MSPI data connection 2 value. */ -} GPIO_PADREGB_PAD4FNCSEL_Enum; - -/* ============================================= GPIO PADREGB PAD4STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGB_PAD4STRNG */ - GPIO_PADREGB_PAD4STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGB_PAD4STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGB_PAD4STRNG_Enum; - -/* ============================================= GPIO PADREGB PAD4INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGB_PAD4INPEN */ - GPIO_PADREGB_PAD4INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGB_PAD4INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGB_PAD4INPEN_Enum; - -/* ============================================= GPIO PADREGB PAD4PULL [0..0] ============================================== */ -typedef enum { /*!< GPIO_PADREGB_PAD4PULL */ - GPIO_PADREGB_PAD4PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGB_PAD4PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGB_PAD4PULL_Enum; - -/* ======================================================== PADREGC ======================================================== */ -/* =========================================== GPIO PADREGC PAD11FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGC_PAD11FNCSEL */ - GPIO_PADREGC_PAD11FNCSEL_ADCSE2 = 0, /*!< ADCSE2 : Configure as the analog input for ADC single ended - input 2 value. */ - GPIO_PADREGC_PAD11FNCSEL_NCE11 = 1, /*!< NCE11 : IOM/MSPI nCE group 11 value. */ - GPIO_PADREGC_PAD11FNCSEL_CT31 = 2, /*!< CT31 : CTIMER connection 31 value. */ - GPIO_PADREGC_PAD11FNCSEL_GPIO11 = 3, /*!< GPIO11 : Configure as GPIO11 value. */ - GPIO_PADREGC_PAD11FNCSEL_SLINT = 4, /*!< SLINT : Configure as the IOSLAVE interrupt out signal value. */ - GPIO_PADREGC_PAD11FNCSEL_UA1CTS = 5, /*!< UA1CTS : Configure as the UART1 CTS input signal value. */ - GPIO_PADREGC_PAD11FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as the UART0 RX input signal value. */ - GPIO_PADREGC_PAD11FNCSEL_PDM_DATA = 7, /*!< PDM_DATA : Configure as the PDM Data input signal value. */ -} GPIO_PADREGC_PAD11FNCSEL_Enum; - -/* =========================================== GPIO PADREGC PAD11STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGC_PAD11STRNG */ - GPIO_PADREGC_PAD11STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGC_PAD11STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGC_PAD11STRNG_Enum; - -/* =========================================== GPIO PADREGC PAD11INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGC_PAD11INPEN */ - GPIO_PADREGC_PAD11INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGC_PAD11INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGC_PAD11INPEN_Enum; - -/* ============================================ GPIO PADREGC PAD11PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGC_PAD11PULL */ - GPIO_PADREGC_PAD11PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGC_PAD11PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGC_PAD11PULL_Enum; - -/* =========================================== GPIO PADREGC PAD10FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGC_PAD10FNCSEL */ - GPIO_PADREGC_PAD10FNCSEL_M1MOSI = 1, /*!< M1MOSI : Configure as the IOMSTR1 SPI MOSI signal value. */ - GPIO_PADREGC_PAD10FNCSEL_NCE10 = 2, /*!< NCE10 : IOM/MSPI nCE group 10 value. */ - GPIO_PADREGC_PAD10FNCSEL_GPIO10 = 3, /*!< GPIO10 : Configure as GPIO10 value. */ - GPIO_PADREGC_PAD10FNCSEL_PDMCLK = 4, /*!< PDMCLK : PDM serial clock out value. */ - GPIO_PADREGC_PAD10FNCSEL_UA1RTS = 5, /*!< UA1RTS : Configure as the UART1 RTS output signal value. */ -} GPIO_PADREGC_PAD10FNCSEL_Enum; - -/* =========================================== GPIO PADREGC PAD10STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGC_PAD10STRNG */ - GPIO_PADREGC_PAD10STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGC_PAD10STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGC_PAD10STRNG_Enum; - -/* =========================================== GPIO PADREGC PAD10INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGC_PAD10INPEN */ - GPIO_PADREGC_PAD10INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGC_PAD10INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGC_PAD10INPEN_Enum; - -/* ============================================ GPIO PADREGC PAD10PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGC_PAD10PULL */ - GPIO_PADREGC_PAD10PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGC_PAD10PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGC_PAD10PULL_Enum; - -/* ============================================ GPIO PADREGC PAD9RSEL [14..15] ============================================= */ -typedef enum { /*!< GPIO_PADREGC_PAD9RSEL */ - GPIO_PADREGC_PAD9RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGC_PAD9RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGC_PAD9RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGC_PAD9RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGC_PAD9RSEL_Enum; - -/* =========================================== GPIO PADREGC PAD9FNCSEL [11..13] ============================================ */ -typedef enum { /*!< GPIO_PADREGC_PAD9FNCSEL */ - GPIO_PADREGC_PAD9FNCSEL_M1SDAWIR3 = 0, /*!< M1SDAWIR3 : Configure as the IOMSTR1 I2C SDA or SPI WIR3 signal - value. */ - GPIO_PADREGC_PAD9FNCSEL_M1MISO = 1, /*!< M1MISO : Configure as the IOMSTR1 SPI MISO signal value. */ - GPIO_PADREGC_PAD9FNCSEL_NCE9 = 2, /*!< NCE9 : IOM/MSPI nCE group 9 value. */ - GPIO_PADREGC_PAD9FNCSEL_GPIO9 = 3, /*!< GPIO9 : Configure as GPIO9 value. */ - GPIO_PADREGC_PAD9FNCSEL_SCCIO = 4, /*!< SCCIO : SCARD data I/O connection value. */ - GPIO_PADREGC_PAD9FNCSEL_UART1RX = 6, /*!< UART1RX : Configure as UART1 RX input signal value. */ -} GPIO_PADREGC_PAD9FNCSEL_Enum; - -/* ============================================ GPIO PADREGC PAD9STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGC_PAD9STRNG */ - GPIO_PADREGC_PAD9STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGC_PAD9STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGC_PAD9STRNG_Enum; - -/* ============================================= GPIO PADREGC PAD9INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGC_PAD9INPEN */ - GPIO_PADREGC_PAD9INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGC_PAD9INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGC_PAD9INPEN_Enum; - -/* ============================================= GPIO PADREGC PAD9PULL [8..8] ============================================== */ -typedef enum { /*!< GPIO_PADREGC_PAD9PULL */ - GPIO_PADREGC_PAD9PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGC_PAD9PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGC_PAD9PULL_Enum; - -/* ============================================= GPIO PADREGC PAD8RSEL [6..7] ============================================== */ -typedef enum { /*!< GPIO_PADREGC_PAD8RSEL */ - GPIO_PADREGC_PAD8RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGC_PAD8RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGC_PAD8RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGC_PAD8RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGC_PAD8RSEL_Enum; - -/* ============================================ GPIO PADREGC PAD8FNCSEL [3..5] ============================================= */ -typedef enum { /*!< GPIO_PADREGC_PAD8FNCSEL */ - GPIO_PADREGC_PAD8FNCSEL_M1SCL = 0, /*!< M1SCL : Configure as the IOMSTR1 I2C SCL signal value. */ - GPIO_PADREGC_PAD8FNCSEL_M1SCK = 1, /*!< M1SCK : Configure as the IOMSTR1 SPI SCK signal value. */ - GPIO_PADREGC_PAD8FNCSEL_NCE8 = 2, /*!< NCE8 : IOM/MSPI nCE group 8 value. */ - GPIO_PADREGC_PAD8FNCSEL_GPIO8 = 3, /*!< GPIO8 : Configure as GPIO8 value. */ - GPIO_PADREGC_PAD8FNCSEL_SCCLK = 4, /*!< SCCLK : SCARD serial clock output value. */ - GPIO_PADREGC_PAD8FNCSEL_UART1TX = 6, /*!< UART1TX : Configure as the UART1 TX output signal value. */ -} GPIO_PADREGC_PAD8FNCSEL_Enum; - -/* ============================================= GPIO PADREGC PAD8STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGC_PAD8STRNG */ - GPIO_PADREGC_PAD8STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGC_PAD8STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGC_PAD8STRNG_Enum; - -/* ============================================= GPIO PADREGC PAD8INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGC_PAD8INPEN */ - GPIO_PADREGC_PAD8INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGC_PAD8INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGC_PAD8INPEN_Enum; - -/* ============================================= GPIO PADREGC PAD8PULL [0..0] ============================================== */ -typedef enum { /*!< GPIO_PADREGC_PAD8PULL */ - GPIO_PADREGC_PAD8PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGC_PAD8PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGC_PAD8PULL_Enum; - -/* ======================================================== PADREGD ======================================================== */ -/* =========================================== GPIO PADREGD PAD15FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGD_PAD15FNCSEL */ - GPIO_PADREGD_PAD15FNCSEL_ADCD1N = 0, /*!< ADCD1N : Configure as the analog ADC differential pair 1 N input - signal value. */ - GPIO_PADREGD_PAD15FNCSEL_NCE15 = 1, /*!< NCE15 : IOM/MSPI nCE group 15 value. */ - GPIO_PADREGD_PAD15FNCSEL_UART1RX = 2, /*!< UART1RX : Configure as the UART1 RX signal value. */ - GPIO_PADREGD_PAD15FNCSEL_GPIO15 = 3, /*!< GPIO15 : Configure as GPIO15 value. */ - GPIO_PADREGD_PAD15FNCSEL_PDMDATA = 4, /*!< PDMDATA : PDM serial data input value. */ - GPIO_PADREGD_PAD15FNCSEL_EXTXT = 5, /*!< EXTXT : Configure as the external XTAL oscillator input value. */ - GPIO_PADREGD_PAD15FNCSEL_SWDIO = 6, /*!< SWDIO : Configure as an alternate port for the SWDIO I/O signal - value. */ - GPIO_PADREGD_PAD15FNCSEL_SWO = 7, /*!< SWO : Configure as an SWO (Serial Wire Trace output) value. */ -} GPIO_PADREGD_PAD15FNCSEL_Enum; - -/* =========================================== GPIO PADREGD PAD15STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGD_PAD15STRNG */ - GPIO_PADREGD_PAD15STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGD_PAD15STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGD_PAD15STRNG_Enum; - -/* =========================================== GPIO PADREGD PAD15INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGD_PAD15INPEN */ - GPIO_PADREGD_PAD15INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGD_PAD15INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGD_PAD15INPEN_Enum; - -/* ============================================ GPIO PADREGD PAD15PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGD_PAD15PULL */ - GPIO_PADREGD_PAD15PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGD_PAD15PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGD_PAD15PULL_Enum; - -/* =========================================== GPIO PADREGD PAD14FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGD_PAD14FNCSEL */ - GPIO_PADREGD_PAD14FNCSEL_ADCD1P = 0, /*!< ADCD1P : Configure as the analog ADC differential pair 1 P input - signal value. */ - GPIO_PADREGD_PAD14FNCSEL_NCE14 = 1, /*!< NCE14 : IOM/MSPI nCE group 14 value. */ - GPIO_PADREGD_PAD14FNCSEL_UART1TX = 2, /*!< UART1TX : Configure as the UART1 TX output signal value. */ - GPIO_PADREGD_PAD14FNCSEL_GPIO14 = 3, /*!< GPIO14 : Configure as GPIO14 value. */ - GPIO_PADREGD_PAD14FNCSEL_PDMCLK = 4, /*!< PDMCLK : PDM serial clock output value. */ - GPIO_PADREGD_PAD14FNCSEL_EXTHFS = 5, /*!< EXTHFS : Configure as the External HFRC oscillator input select - value. */ - GPIO_PADREGD_PAD14FNCSEL_SWDCK = 6, /*!< SWDCK : Configure as the alternate input for the SWDCK input - signal value. */ - GPIO_PADREGD_PAD14FNCSEL_32kHzXT = 7, /*!< 32kHzXT : Configure as the 32kHz crystal output signal value. */ -} GPIO_PADREGD_PAD14FNCSEL_Enum; - -/* =========================================== GPIO PADREGD PAD14STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGD_PAD14STRNG */ - GPIO_PADREGD_PAD14STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGD_PAD14STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGD_PAD14STRNG_Enum; - -/* =========================================== GPIO PADREGD PAD14INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGD_PAD14INPEN */ - GPIO_PADREGD_PAD14INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGD_PAD14INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGD_PAD14INPEN_Enum; - -/* ============================================ GPIO PADREGD PAD14PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGD_PAD14PULL */ - GPIO_PADREGD_PAD14PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGD_PAD14PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGD_PAD14PULL_Enum; - -/* =========================================== GPIO PADREGD PAD13FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGD_PAD13FNCSEL */ - GPIO_PADREGD_PAD13FNCSEL_ADCD0PSE8 = 0, /*!< ADCD0PSE8 : Configure as the ADC Differential pair 0 P, or Single - Ended input 8 analog input signal. Determination of the - D0P vs SE8 usage is done when the particular channel is - selected within the ADC module value. */ - GPIO_PADREGD_PAD13FNCSEL_NCE13 = 1, /*!< NCE13 : IOM/MSPI nCE group 13 value. */ - GPIO_PADREGD_PAD13FNCSEL_CT2 = 2, /*!< CT2 : CTIMER connection 2 value. */ - GPIO_PADREGD_PAD13FNCSEL_GPIO13 = 3, /*!< GPIO13 : Configure as GPIO13 value. */ - GPIO_PADREGD_PAD13FNCSEL_I2SBCLK = 4, /*!< I2SBCLK : I2C interface bit clock value. */ - GPIO_PADREGD_PAD13FNCSEL_EXTHFB = 5, /*!< EXTHFB : Configure as the external HFRC oscillator input value. */ - GPIO_PADREGD_PAD13FNCSEL_UA0RTS = 6, /*!< UA0RTS : Configure as the UART0 RTS signal output value. */ - GPIO_PADREGD_PAD13FNCSEL_UART1RX = 7, /*!< UART1RX : Configure as the UART1 RX input signal value. */ -} GPIO_PADREGD_PAD13FNCSEL_Enum; - -/* =========================================== GPIO PADREGD PAD13STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGD_PAD13STRNG */ - GPIO_PADREGD_PAD13STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGD_PAD13STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGD_PAD13STRNG_Enum; - -/* ============================================ GPIO PADREGD PAD13INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGD_PAD13INPEN */ - GPIO_PADREGD_PAD13INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGD_PAD13INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGD_PAD13INPEN_Enum; - -/* ============================================= GPIO PADREGD PAD13PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGD_PAD13PULL */ - GPIO_PADREGD_PAD13PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGD_PAD13PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGD_PAD13PULL_Enum; - -/* ============================================ GPIO PADREGD PAD12FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGD_PAD12FNCSEL */ - GPIO_PADREGD_PAD12FNCSEL_ADCD0NSE9 = 0, /*!< ADCD0NSE9 : Configure as the ADC Differential pair 0 N, or Single - Ended input 9 analog input signal. Determination of the - D0N vs SE9 usage is done when the particular channel is - selected within the ADC module value. */ - GPIO_PADREGD_PAD12FNCSEL_NCE12 = 1, /*!< NCE12 : IOM/MSPI nCE group 12 value. */ - GPIO_PADREGD_PAD12FNCSEL_CT0 = 2, /*!< CT0 : CTIMER connection 0 value. */ - GPIO_PADREGD_PAD12FNCSEL_GPIO12 = 3, /*!< GPIO12 : Configure as GPIO12 value. */ - GPIO_PADREGD_PAD12FNCSEL_SLnCE = 4, /*!< SLnCE : Configure as the IOSLAVE SPI nCE signal value. */ - GPIO_PADREGD_PAD12FNCSEL_PDMCLK = 5, /*!< PDMCLK : PDM serial clock output value. */ - GPIO_PADREGD_PAD12FNCSEL_UA0CTS = 6, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ - GPIO_PADREGD_PAD12FNCSEL_UART1TX = 7, /*!< UART1TX : Configure as the UART1 TX output signal value. */ -} GPIO_PADREGD_PAD12FNCSEL_Enum; - -/* ============================================ GPIO PADREGD PAD12STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGD_PAD12STRNG */ - GPIO_PADREGD_PAD12STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGD_PAD12STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGD_PAD12STRNG_Enum; - -/* ============================================ GPIO PADREGD PAD12INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGD_PAD12INPEN */ - GPIO_PADREGD_PAD12INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGD_PAD12INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGD_PAD12INPEN_Enum; - -/* ============================================= GPIO PADREGD PAD12PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGD_PAD12PULL */ - GPIO_PADREGD_PAD12PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGD_PAD12PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGD_PAD12PULL_Enum; - -/* ======================================================== PADREGE ======================================================== */ -/* =========================================== GPIO PADREGE PAD19FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGE_PAD19FNCSEL */ - GPIO_PADREGE_PAD19FNCSEL_CMPRF0 = 0, /*!< CMPRF0 : Configure as the analog comparator reference 0 signal - value. */ - GPIO_PADREGE_PAD19FNCSEL_NCE19 = 1, /*!< NCE19 : IOM/MSPI nCE group 19 value. */ - GPIO_PADREGE_PAD19FNCSEL_CT6 = 2, /*!< CT6 : CTIMER conenction 6 value. */ - GPIO_PADREGE_PAD19FNCSEL_GPIO19 = 3, /*!< GPIO19 : Configure as GPIO19 value. */ - GPIO_PADREGE_PAD19FNCSEL_SCCLK = 4, /*!< SCCLK : SCARD serial clock value. */ - GPIO_PADREGE_PAD19FNCSEL_ANATEST1 = 5, /*!< ANATEST1 : Configure as the ANATEST1 I/O signal value. */ - GPIO_PADREGE_PAD19FNCSEL_UART1RX = 6, /*!< UART1RX : Configure as the UART1 RX input signal value. */ - GPIO_PADREGE_PAD19FNCSEL_I2SBCLK = 7, /*!< I2SBCLK : Configure as the PDM I2S bit clock input signal value. */ -} GPIO_PADREGE_PAD19FNCSEL_Enum; - -/* =========================================== GPIO PADREGE PAD19STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGE_PAD19STRNG */ - GPIO_PADREGE_PAD19STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGE_PAD19STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGE_PAD19STRNG_Enum; - -/* =========================================== GPIO PADREGE PAD19INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGE_PAD19INPEN */ - GPIO_PADREGE_PAD19INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGE_PAD19INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGE_PAD19INPEN_Enum; - -/* ============================================ GPIO PADREGE PAD19PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGE_PAD19PULL */ - GPIO_PADREGE_PAD19PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGE_PAD19PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGE_PAD19PULL_Enum; - -/* =========================================== GPIO PADREGE PAD18FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGE_PAD18FNCSEL */ - GPIO_PADREGE_PAD18FNCSEL_CMPIN1 = 0, /*!< CMPIN1 : Configure as the analog comparator input 1 signal value. */ - GPIO_PADREGE_PAD18FNCSEL_NCE18 = 1, /*!< NCE18 : IOM/MSPI nCE group 18 value. */ - GPIO_PADREGE_PAD18FNCSEL_CT4 = 2, /*!< CT4 : CTIMER connection 4 value. */ - GPIO_PADREGE_PAD18FNCSEL_GPIO18 = 3, /*!< GPIO18 : Configure as GPIO18 value. */ - GPIO_PADREGE_PAD18FNCSEL_UA0RTS = 4, /*!< UA0RTS : Configure as UART0 RTS output signal value. */ - GPIO_PADREGE_PAD18FNCSEL_ANATEST2 = 5, /*!< ANATEST2 : Configure as ANATEST2 I/O signal value. */ - GPIO_PADREGE_PAD18FNCSEL_UART1TX = 6, /*!< UART1TX : Configure as UART1 TX output signal value. */ - GPIO_PADREGE_PAD18FNCSEL_SCCIO = 7, /*!< SCCIO : SCARD data input/output connectin value. */ -} GPIO_PADREGE_PAD18FNCSEL_Enum; - -/* =========================================== GPIO PADREGE PAD18STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGE_PAD18STRNG */ - GPIO_PADREGE_PAD18STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGE_PAD18STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGE_PAD18STRNG_Enum; - -/* =========================================== GPIO PADREGE PAD18INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGE_PAD18INPEN */ - GPIO_PADREGE_PAD18INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGE_PAD18INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGE_PAD18INPEN_Enum; - -/* ============================================ GPIO PADREGE PAD18PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGE_PAD18PULL */ - GPIO_PADREGE_PAD18PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGE_PAD18PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGE_PAD18PULL_Enum; - -/* =========================================== GPIO PADREGE PAD17FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGE_PAD17FNCSEL */ - GPIO_PADREGE_PAD17FNCSEL_CMPRF1 = 0, /*!< CMPRF1 : Configure as the analog comparator reference signal - 1 input signal value. */ - GPIO_PADREGE_PAD17FNCSEL_NCE17 = 1, /*!< NCE17 : IOM/MSPI nCE group 17 value. */ - GPIO_PADREGE_PAD17FNCSEL_TRIG1 = 2, /*!< TRIG1 : Configure as the ADC Trigger 1 signal value. */ - GPIO_PADREGE_PAD17FNCSEL_GPIO17 = 3, /*!< GPIO17 : Configure as GPIO17 value. */ - GPIO_PADREGE_PAD17FNCSEL_SCCCLK = 4, /*!< SCCCLK : SCARD serial clock output value. */ - GPIO_PADREGE_PAD17FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as UART0 RX input signal value. */ - GPIO_PADREGE_PAD17FNCSEL_UA1CTS = 7, /*!< UA1CTS : Configure as UART1 CTS input signal value. */ -} GPIO_PADREGE_PAD17FNCSEL_Enum; - -/* =========================================== GPIO PADREGE PAD17STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGE_PAD17STRNG */ - GPIO_PADREGE_PAD17STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGE_PAD17STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGE_PAD17STRNG_Enum; - -/* ============================================ GPIO PADREGE PAD17INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGE_PAD17INPEN */ - GPIO_PADREGE_PAD17INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGE_PAD17INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGE_PAD17INPEN_Enum; - -/* ============================================= GPIO PADREGE PAD17PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGE_PAD17PULL */ - GPIO_PADREGE_PAD17PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGE_PAD17PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGE_PAD17PULL_Enum; - -/* ============================================ GPIO PADREGE PAD16FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGE_PAD16FNCSEL */ - GPIO_PADREGE_PAD16FNCSEL_ADCSE0 = 0, /*!< ADCSE0 : Configure as the analog ADC single ended port 0 input - signal value. */ - GPIO_PADREGE_PAD16FNCSEL_NCE16 = 1, /*!< NCE16 : IOM/MSPI nCE group 16 value. */ - GPIO_PADREGE_PAD16FNCSEL_TRIG0 = 2, /*!< TRIG0 : Configure as the ADC Trigger 0 signal value. */ - GPIO_PADREGE_PAD16FNCSEL_GPIO16 = 3, /*!< GPIO16 : Configure as GPIO16 value. */ - GPIO_PADREGE_PAD16FNCSEL_SCCRST = 4, /*!< SCCRST : SCARD reset output value. */ - GPIO_PADREGE_PAD16FNCSEL_CMPIN0 = 5, /*!< CMPIN0 : Configure as comparator input 0 signal value. */ - GPIO_PADREGE_PAD16FNCSEL_UART0TX = 6, /*!< UART0TX : Configure as UART0 TX output signal value. */ - GPIO_PADREGE_PAD16FNCSEL_UA1RTS = 7, /*!< UA1RTS : Configure as UART1 RTS output signal value. */ -} GPIO_PADREGE_PAD16FNCSEL_Enum; - -/* ============================================ GPIO PADREGE PAD16STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGE_PAD16STRNG */ - GPIO_PADREGE_PAD16STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGE_PAD16STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGE_PAD16STRNG_Enum; - -/* ============================================ GPIO PADREGE PAD16INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGE_PAD16INPEN */ - GPIO_PADREGE_PAD16INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGE_PAD16INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGE_PAD16INPEN_Enum; - -/* ============================================= GPIO PADREGE PAD16PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGE_PAD16PULL */ - GPIO_PADREGE_PAD16PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGE_PAD16PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGE_PAD16PULL_Enum; - -/* ======================================================== PADREGF ======================================================== */ -/* =========================================== GPIO PADREGF PAD23FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGF_PAD23FNCSEL */ - GPIO_PADREGF_PAD23FNCSEL_UART0RX = 0, /*!< UART0RX : Configure as the UART0 RX signal value. */ - GPIO_PADREGF_PAD23FNCSEL_NCE23 = 1, /*!< NCE23 : IOM/MSPI nCE group 23 value. */ - GPIO_PADREGF_PAD23FNCSEL_CT14 = 2, /*!< CT14 : CTIMER connection 14 value. */ - GPIO_PADREGF_PAD23FNCSEL_GPIO23 = 3, /*!< GPIO23 : Configure as GPIO23 value. */ - GPIO_PADREGF_PAD23FNCSEL_I2SWCLK = 4, /*!< I2SWCLK : I2S word clock input value. */ - GPIO_PADREGF_PAD23FNCSEL_CMPOUT = 5, /*!< CMPOUT : Configure as voltage comparitor output value. */ - GPIO_PADREGF_PAD23FNCSEL_MSPI3 = 6, /*!< MSPI3 : MSPI data connection 3 value. */ - GPIO_PADREGF_PAD23FNCSEL_EXTXT = 7, /*!< EXTXT : External XTAL osacillatgor input value. */ -} GPIO_PADREGF_PAD23FNCSEL_Enum; - -/* =========================================== GPIO PADREGF PAD23STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGF_PAD23STRNG */ - GPIO_PADREGF_PAD23STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGF_PAD23STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGF_PAD23STRNG_Enum; - -/* =========================================== GPIO PADREGF PAD23INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGF_PAD23INPEN */ - GPIO_PADREGF_PAD23INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGF_PAD23INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGF_PAD23INPEN_Enum; - -/* ============================================ GPIO PADREGF PAD23PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGF_PAD23PULL */ - GPIO_PADREGF_PAD23PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGF_PAD23PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGF_PAD23PULL_Enum; - -/* =========================================== GPIO PADREGF PAD22FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGF_PAD22FNCSEL */ - GPIO_PADREGF_PAD22FNCSEL_UART0TX = 0, /*!< UART0TX : Configure as the UART0 TX signal value. */ - GPIO_PADREGF_PAD22FNCSEL_NCE22 = 1, /*!< NCE22 : IOM/MSPI nCE group 22 value. */ - GPIO_PADREGF_PAD22FNCSEL_CT12 = 2, /*!< CT12 : CTIMER connection 12 value. */ - GPIO_PADREGF_PAD22FNCSEL_GPIO22 = 3, /*!< GPIO22 : Configure as GPIO22 value. */ - GPIO_PADREGF_PAD22FNCSEL_PDM_CLK = 4, /*!< PDM_CLK : Configure as the PDM CLK output value. */ - GPIO_PADREGF_PAD22FNCSEL_EXTLF = 5, /*!< EXTLF : External LFRC input value. */ - GPIO_PADREGF_PAD22FNCSEL_MSPI0 = 6, /*!< MSPI0 : MSPI data connection 0 value. */ - GPIO_PADREGF_PAD22FNCSEL_SWO = 7, /*!< SWO : Configure as the serial trace data output signal value. */ -} GPIO_PADREGF_PAD22FNCSEL_Enum; - -/* =========================================== GPIO PADREGF PAD22STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGF_PAD22STRNG */ - GPIO_PADREGF_PAD22STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGF_PAD22STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGF_PAD22STRNG_Enum; - -/* =========================================== GPIO PADREGF PAD22INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGF_PAD22INPEN */ - GPIO_PADREGF_PAD22INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGF_PAD22INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGF_PAD22INPEN_Enum; - -/* ============================================ GPIO PADREGF PAD22PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGF_PAD22PULL */ - GPIO_PADREGF_PAD22PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGF_PAD22PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGF_PAD22PULL_Enum; - -/* =========================================== GPIO PADREGF PAD21FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGF_PAD21FNCSEL */ - GPIO_PADREGF_PAD21FNCSEL_SWDIO = 0, /*!< SWDIO : Configure as the serial wire debug data signal value. */ - GPIO_PADREGF_PAD21FNCSEL_NCE21 = 1, /*!< NCE21 : IOM/MSPI nCE group 21 value. */ - GPIO_PADREGF_PAD21FNCSEL_GPIO21 = 3, /*!< GPIO21 : Configure as GPIO21 value. */ - GPIO_PADREGF_PAD21FNCSEL_UART0RX = 4, /*!< UART0RX : Configure as UART0 RX input signal value. */ - GPIO_PADREGF_PAD21FNCSEL_UART1RX = 5, /*!< UART1RX : Configure as UART1 RX input signal value. */ - GPIO_PADREGF_PAD21FNCSEL_I2SBCLK = 6, /*!< I2SBCLK : I2S byte clock input value. */ - GPIO_PADREGF_PAD21FNCSEL_UA1CTS = 7, /*!< UA1CTS : Configure as UART1 CTS input signal value. */ -} GPIO_PADREGF_PAD21FNCSEL_Enum; - -/* =========================================== GPIO PADREGF PAD21STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGF_PAD21STRNG */ - GPIO_PADREGF_PAD21STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGF_PAD21STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGF_PAD21STRNG_Enum; - -/* ============================================ GPIO PADREGF PAD21INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGF_PAD21INPEN */ - GPIO_PADREGF_PAD21INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGF_PAD21INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGF_PAD21INPEN_Enum; - -/* ============================================= GPIO PADREGF PAD21PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGF_PAD21PULL */ - GPIO_PADREGF_PAD21PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGF_PAD21PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGF_PAD21PULL_Enum; - -/* ============================================ GPIO PADREGF PAD20FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGF_PAD20FNCSEL */ - GPIO_PADREGF_PAD20FNCSEL_SWDCK = 0, /*!< SWDCK : Configure as the serial wire debug clock signal value. */ - GPIO_PADREGF_PAD20FNCSEL_NCE20 = 1, /*!< NCE20 : IOM/MSPI nCE group 20 value. */ - GPIO_PADREGF_PAD20FNCSEL_GPIO20 = 3, /*!< GPIO20 : Configure as GPIO20 value. */ - GPIO_PADREGF_PAD20FNCSEL_UART0TX = 4, /*!< UART0TX : Configure as UART0 TX output signal value. */ - GPIO_PADREGF_PAD20FNCSEL_UART1TX = 5, /*!< UART1TX : Configure as UART1 TX output signal value. */ - GPIO_PADREGF_PAD20FNCSEL_I2SBCLK = 6, /*!< I2SBCLK : I2S byte clock input value. */ - GPIO_PADREGF_PAD20FNCSEL_UA1RTS = 7, /*!< UA1RTS : Configure as UART1 RTS output signal value. */ -} GPIO_PADREGF_PAD20FNCSEL_Enum; - -/* ============================================ GPIO PADREGF PAD20STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGF_PAD20STRNG */ - GPIO_PADREGF_PAD20STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGF_PAD20STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGF_PAD20STRNG_Enum; - -/* ============================================ GPIO PADREGF PAD20INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGF_PAD20INPEN */ - GPIO_PADREGF_PAD20INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGF_PAD20INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGF_PAD20INPEN_Enum; - -/* ============================================= GPIO PADREGF PAD20PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGF_PAD20PULL */ - GPIO_PADREGF_PAD20PULL_DIS = 0, /*!< DIS : Pulldown disabled value. */ - GPIO_PADREGF_PAD20PULL_EN = 1, /*!< EN : Pulldown enabled value. */ -} GPIO_PADREGF_PAD20PULL_Enum; - -/* ======================================================== PADREGG ======================================================== */ -/* ============================================ GPIO PADREGG PAD27RSEL [30..31] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD27RSEL */ - GPIO_PADREGG_PAD27RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGG_PAD27RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGG_PAD27RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGG_PAD27RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGG_PAD27RSEL_Enum; - -/* =========================================== GPIO PADREGG PAD27FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGG_PAD27FNCSEL */ - GPIO_PADREGG_PAD27FNCSEL_UART0RX = 0, /*!< UART0RX : Configure as UART0 RX input signal value. */ - GPIO_PADREGG_PAD27FNCSEL_NCE27 = 1, /*!< NCE27 : IOM/MSPI nCE group 27 value. */ - GPIO_PADREGG_PAD27FNCSEL_CT5 = 2, /*!< CT5 : CTIMER connection 5 value. */ - GPIO_PADREGG_PAD27FNCSEL_GPIO27 = 3, /*!< GPIO27 : Configure as GPIO27 value. */ - GPIO_PADREGG_PAD27FNCSEL_M2SCL = 4, /*!< M2SCL : Configure as I2C clock I/O signal from IOMSTR2 value. */ - GPIO_PADREGG_PAD27FNCSEL_M2SCK = 5, /*!< M2SCK : Configure as SPI clock output signal from IOMSTR2 value. */ -} GPIO_PADREGG_PAD27FNCSEL_Enum; - -/* =========================================== GPIO PADREGG PAD27STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD27STRNG */ - GPIO_PADREGG_PAD27STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGG_PAD27STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGG_PAD27STRNG_Enum; - -/* =========================================== GPIO PADREGG PAD27INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD27INPEN */ - GPIO_PADREGG_PAD27INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGG_PAD27INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGG_PAD27INPEN_Enum; - -/* ============================================ GPIO PADREGG PAD27PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD27PULL */ - GPIO_PADREGG_PAD27PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGG_PAD27PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGG_PAD27PULL_Enum; - -/* =========================================== GPIO PADREGG PAD26FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGG_PAD26FNCSEL */ - GPIO_PADREGG_PAD26FNCSEL_EXTHF = 0, /*!< EXTHF : Configure as the external HFRC oscillator input value. */ - GPIO_PADREGG_PAD26FNCSEL_NCE26 = 1, /*!< NCE26 : IOM/MSPI nCE group 26 value. */ - GPIO_PADREGG_PAD26FNCSEL_CT3 = 2, /*!< CT3 : CTIMER connection 3 value. */ - GPIO_PADREGG_PAD26FNCSEL_GPIO26 = 3, /*!< GPIO26 : Configure as GPIO26 value. */ - GPIO_PADREGG_PAD26FNCSEL_SCCRST = 4, /*!< SCCRST : SCARD reset output value. */ - GPIO_PADREGG_PAD26FNCSEL_MSPI1 = 5, /*!< MSPI1 : MSPI data connection 1 value. */ - GPIO_PADREGG_PAD26FNCSEL_UART0TX = 6, /*!< UART0TX : Configure as UART0 TX output signal value. */ - GPIO_PADREGG_PAD26FNCSEL_UA1CTS = 7, /*!< UA1CTS : Configure as UART1 CTS input signal value. */ -} GPIO_PADREGG_PAD26FNCSEL_Enum; - -/* =========================================== GPIO PADREGG PAD26STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD26STRNG */ - GPIO_PADREGG_PAD26STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGG_PAD26STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGG_PAD26STRNG_Enum; - -/* =========================================== GPIO PADREGG PAD26INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD26INPEN */ - GPIO_PADREGG_PAD26INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGG_PAD26INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGG_PAD26INPEN_Enum; - -/* ============================================ GPIO PADREGG PAD26PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD26PULL */ - GPIO_PADREGG_PAD26PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGG_PAD26PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGG_PAD26PULL_Enum; - -/* ============================================ GPIO PADREGG PAD25RSEL [14..15] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD25RSEL */ - GPIO_PADREGG_PAD25RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGG_PAD25RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGG_PAD25RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGG_PAD25RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGG_PAD25RSEL_Enum; - -/* =========================================== GPIO PADREGG PAD25FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGG_PAD25FNCSEL */ - GPIO_PADREGG_PAD25FNCSEL_UART1RX = 0, /*!< UART1RX : Configure as UART1 RX input signal value. */ - GPIO_PADREGG_PAD25FNCSEL_NCE25 = 1, /*!< NCE25 : IOM/MSPI nCE group 25 value. */ - GPIO_PADREGG_PAD25FNCSEL_CT1 = 2, /*!< CT1 : CTIMER connection 1 value. */ - GPIO_PADREGG_PAD25FNCSEL_GPIO25 = 3, /*!< GPIO25 : Configure as GPIO25 value. */ - GPIO_PADREGG_PAD25FNCSEL_M2SDAWIR3 = 4, /*!< M2SDAWIR3 : Configure as the IOMSTR2 I2C SDA or SPI WIR3 signal - value. */ - GPIO_PADREGG_PAD25FNCSEL_M2MISO = 5, /*!< M2MISO : Configure as the IOMSTR2 SPI MISO input signal value. */ -} GPIO_PADREGG_PAD25FNCSEL_Enum; - -/* =========================================== GPIO PADREGG PAD25STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD25STRNG */ - GPIO_PADREGG_PAD25STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGG_PAD25STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGG_PAD25STRNG_Enum; - -/* ============================================ GPIO PADREGG PAD25INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGG_PAD25INPEN */ - GPIO_PADREGG_PAD25INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGG_PAD25INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGG_PAD25INPEN_Enum; - -/* ============================================= GPIO PADREGG PAD25PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGG_PAD25PULL */ - GPIO_PADREGG_PAD25PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGG_PAD25PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGG_PAD25PULL_Enum; - -/* ============================================ GPIO PADREGG PAD24FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGG_PAD24FNCSEL */ - GPIO_PADREGG_PAD24FNCSEL_UART1TX = 0, /*!< UART1TX : Configure as UART1 TX output signal value. */ - GPIO_PADREGG_PAD24FNCSEL_NCE24 = 1, /*!< NCE24 : IOM/MSPI nCE group 24 value. */ - GPIO_PADREGG_PAD24FNCSEL_MSPI8 = 2, /*!< MSPI8 : MSPI data connection 8 value. */ - GPIO_PADREGG_PAD24FNCSEL_GPIO24 = 3, /*!< GPIO24 : Configure as GPIO24 value. */ - GPIO_PADREGG_PAD24FNCSEL_UA0CTS = 4, /*!< UA0CTS : Configure as UART0 CTS input signal value. */ - GPIO_PADREGG_PAD24FNCSEL_CT21 = 5, /*!< CT21 : CTIMER connection 21 value. */ - GPIO_PADREGG_PAD24FNCSEL_32kHzXT = 6, /*!< 32kHzXT : Configure as the 32kHz crystal output signal value. */ - GPIO_PADREGG_PAD24FNCSEL_SWO = 7, /*!< SWO : Configure as the serial trace data output signal value. */ -} GPIO_PADREGG_PAD24FNCSEL_Enum; - -/* ============================================ GPIO PADREGG PAD24STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGG_PAD24STRNG */ - GPIO_PADREGG_PAD24STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGG_PAD24STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGG_PAD24STRNG_Enum; - -/* ============================================ GPIO PADREGG PAD24INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGG_PAD24INPEN */ - GPIO_PADREGG_PAD24INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGG_PAD24INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGG_PAD24INPEN_Enum; - -/* ============================================= GPIO PADREGG PAD24PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGG_PAD24PULL */ - GPIO_PADREGG_PAD24PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGG_PAD24PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGG_PAD24PULL_Enum; - -/* ======================================================== PADREGH ======================================================== */ -/* =========================================== GPIO PADREGH PAD31FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGH_PAD31FNCSEL */ - GPIO_PADREGH_PAD31FNCSEL_ADCSE3 = 0, /*!< ADCSE3 : Configure as the analog input for ADC single ended - input 3 value. */ - GPIO_PADREGH_PAD31FNCSEL_NCE31 = 1, /*!< NCE31 : IOM/MSPI nCE group 31 value. */ - GPIO_PADREGH_PAD31FNCSEL_CT13 = 2, /*!< CT13 : CTIMER connection 13 value. */ - GPIO_PADREGH_PAD31FNCSEL_GPIO31 = 3, /*!< GPIO31 : Configure as GPIO31 value. */ - GPIO_PADREGH_PAD31FNCSEL_UART0RX = 4, /*!< UART0RX : Configure as the UART0 RX input signal value. */ - GPIO_PADREGH_PAD31FNCSEL_SCCCLK = 5, /*!< SCCCLK : SCARD serial clock output value. */ - GPIO_PADREGH_PAD31FNCSEL_UA1RTS = 7, /*!< UA1RTS : Configure as UART1 RTS output signal value. */ -} GPIO_PADREGH_PAD31FNCSEL_Enum; - -/* =========================================== GPIO PADREGH PAD31STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGH_PAD31STRNG */ - GPIO_PADREGH_PAD31STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGH_PAD31STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGH_PAD31STRNG_Enum; - -/* =========================================== GPIO PADREGH PAD31INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGH_PAD31INPEN */ - GPIO_PADREGH_PAD31INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGH_PAD31INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGH_PAD31INPEN_Enum; - -/* ============================================ GPIO PADREGH PAD31PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGH_PAD31PULL */ - GPIO_PADREGH_PAD31PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGH_PAD31PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGH_PAD31PULL_Enum; - -/* =========================================== GPIO PADREGH PAD30FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGH_PAD30FNCSEL */ - GPIO_PADREGH_PAD30FNCSEL_ANATEST1 = 0, /*!< ANATEST1 : Configure as the ANATEST1 I/O signal value. */ - GPIO_PADREGH_PAD30FNCSEL_NCE30 = 1, /*!< NCE30 : IOM/MSPI nCE group 30 value. */ - GPIO_PADREGH_PAD30FNCSEL_CT11 = 2, /*!< CT11 : CTIMER connection 11 value. */ - GPIO_PADREGH_PAD30FNCSEL_GPIO30 = 3, /*!< GPIO30 : Configure as GPIO30 value. */ - GPIO_PADREGH_PAD30FNCSEL_UART0TX = 4, /*!< UART0TX : Configure as UART0 TX output signal value. */ - GPIO_PADREGH_PAD30FNCSEL_UA1RTS = 5, /*!< UA1RTS : Configure as UART1 RTS output signal value. */ - GPIO_PADREGH_PAD30FNCSEL_I2S_DAT = 7, /*!< I2S_DAT : Configure as the PDM I2S Data output signal value. */ -} GPIO_PADREGH_PAD30FNCSEL_Enum; - -/* =========================================== GPIO PADREGH PAD30STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGH_PAD30STRNG */ - GPIO_PADREGH_PAD30STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGH_PAD30STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGH_PAD30STRNG_Enum; - -/* =========================================== GPIO PADREGH PAD30INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGH_PAD30INPEN */ - GPIO_PADREGH_PAD30INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGH_PAD30INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGH_PAD30INPEN_Enum; - -/* ============================================ GPIO PADREGH PAD30PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGH_PAD30PULL */ - GPIO_PADREGH_PAD30PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGH_PAD30PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGH_PAD30PULL_Enum; - -/* =========================================== GPIO PADREGH PAD29FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGH_PAD29FNCSEL */ - GPIO_PADREGH_PAD29FNCSEL_ADCSE1 = 0, /*!< ADCSE1 : Configure as the analog input for ADC single ended - input 1 value. */ - GPIO_PADREGH_PAD29FNCSEL_NCE29 = 1, /*!< NCE29 : IOM/MSPI nCE group 29 value. */ - GPIO_PADREGH_PAD29FNCSEL_CT9 = 2, /*!< CT9 : CTIMER connection 9 value. */ - GPIO_PADREGH_PAD29FNCSEL_GPIO29 = 3, /*!< GPIO29 : Configure as GPIO29 value. */ - GPIO_PADREGH_PAD29FNCSEL_UA0CTS = 4, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ - GPIO_PADREGH_PAD29FNCSEL_UA1CTS = 5, /*!< UA1CTS : Configure as the UART1 CTS input signal value. */ - GPIO_PADREGH_PAD29FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as the UART0 RX input signal value. */ - GPIO_PADREGH_PAD29FNCSEL_PDM_DATA = 7, /*!< PDM_DATA : Configure as PDM DATA input value. */ -} GPIO_PADREGH_PAD29FNCSEL_Enum; - -/* =========================================== GPIO PADREGH PAD29STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGH_PAD29STRNG */ - GPIO_PADREGH_PAD29STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGH_PAD29STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGH_PAD29STRNG_Enum; - -/* ============================================ GPIO PADREGH PAD29INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGH_PAD29INPEN */ - GPIO_PADREGH_PAD29INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGH_PAD29INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGH_PAD29INPEN_Enum; - -/* ============================================= GPIO PADREGH PAD29PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGH_PAD29PULL */ - GPIO_PADREGH_PAD29PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGH_PAD29PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGH_PAD29PULL_Enum; - -/* ============================================ GPIO PADREGH PAD28FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGH_PAD28FNCSEL */ - GPIO_PADREGH_PAD28FNCSEL_I2S_WCLK = 0, /*!< I2S_WCLK : Configure as the PDM I2S Word Clock input value. */ - GPIO_PADREGH_PAD28FNCSEL_NCE28 = 1, /*!< NCE28 : IOM/MSPI nCE group 28 value. */ - GPIO_PADREGH_PAD28FNCSEL_CT7 = 2, /*!< CT7 : CTIMER connection 7 value. */ - GPIO_PADREGH_PAD28FNCSEL_GPIO28 = 3, /*!< GPIO28 : Configure as GPIO28 value. */ - GPIO_PADREGH_PAD28FNCSEL_M2MOSI = 5, /*!< M2MOSI : Configure as the IOMSTR2 SPI MOSI output signal value. */ - GPIO_PADREGH_PAD28FNCSEL_UART0TX = 6, /*!< UART0TX : Configure as the UART0 TX output signal value. */ -} GPIO_PADREGH_PAD28FNCSEL_Enum; - -/* ============================================ GPIO PADREGH PAD28STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGH_PAD28STRNG */ - GPIO_PADREGH_PAD28STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGH_PAD28STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGH_PAD28STRNG_Enum; - -/* ============================================ GPIO PADREGH PAD28INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGH_PAD28INPEN */ - GPIO_PADREGH_PAD28INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGH_PAD28INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGH_PAD28INPEN_Enum; - -/* ============================================= GPIO PADREGH PAD28PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGH_PAD28PULL */ - GPIO_PADREGH_PAD28PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGH_PAD28PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGH_PAD28PULL_Enum; - -/* ======================================================== PADREGI ======================================================== */ -/* =========================================== GPIO PADREGI PAD35FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGI_PAD35FNCSEL */ - GPIO_PADREGI_PAD35FNCSEL_ADCSE7 = 0, /*!< ADCSE7 : Configure as the analog input for ADC single ended - input 7 value. */ - GPIO_PADREGI_PAD35FNCSEL_NCE35 = 1, /*!< NCE35 : IOM/MSPI nCE group 35 value. */ - GPIO_PADREGI_PAD35FNCSEL_UART1TX = 2, /*!< UART1TX : Configure as the UART1 TX signal value. */ - GPIO_PADREGI_PAD35FNCSEL_GPIO35 = 3, /*!< GPIO35 : Configure as GPIO35 value. */ - GPIO_PADREGI_PAD35FNCSEL_I2SDAT = 4, /*!< I2SDAT : I2S serial data output value. */ - GPIO_PADREGI_PAD35FNCSEL_CT27 = 5, /*!< CT27 : CTIMER connection 27 value. */ - GPIO_PADREGI_PAD35FNCSEL_UA0RTS = 6, /*!< UA0RTS : Configure as the UART0 RTS output value. */ -} GPIO_PADREGI_PAD35FNCSEL_Enum; - -/* =========================================== GPIO PADREGI PAD35STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGI_PAD35STRNG */ - GPIO_PADREGI_PAD35STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGI_PAD35STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGI_PAD35STRNG_Enum; - -/* =========================================== GPIO PADREGI PAD35INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGI_PAD35INPEN */ - GPIO_PADREGI_PAD35INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGI_PAD35INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGI_PAD35INPEN_Enum; - -/* ============================================ GPIO PADREGI PAD35PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGI_PAD35PULL */ - GPIO_PADREGI_PAD35PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGI_PAD35PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGI_PAD35PULL_Enum; - -/* =========================================== GPIO PADREGI PAD34FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGI_PAD34FNCSEL */ - GPIO_PADREGI_PAD34FNCSEL_ADCSE6 = 0, /*!< ADCSE6 : Configure as the analog input for ADC single ended - input 6 value. */ - GPIO_PADREGI_PAD34FNCSEL_NCE34 = 1, /*!< NCE34 : IOM/MSPI nCE group 34 value. */ - GPIO_PADREGI_PAD34FNCSEL_UA1RTS = 2, /*!< UA1RTS : Configure as the UART1 RTS output value. */ - GPIO_PADREGI_PAD34FNCSEL_GPIO34 = 3, /*!< GPIO34 : Configure as GPIO34 value. */ - GPIO_PADREGI_PAD34FNCSEL_CMPRF2 = 4, /*!< CMPRF2 : Configure as the analog comparator reference 2 signal - value. */ - GPIO_PADREGI_PAD34FNCSEL_UA0RTS = 5, /*!< UA0RTS : Configure as the UART0 RTS output value. */ - GPIO_PADREGI_PAD34FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as the UART0 RX input value. */ - GPIO_PADREGI_PAD34FNCSEL_PDMDATA = 7, /*!< PDMDATA : PDM serial data input value. */ -} GPIO_PADREGI_PAD34FNCSEL_Enum; - -/* =========================================== GPIO PADREGI PAD34STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGI_PAD34STRNG */ - GPIO_PADREGI_PAD34STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGI_PAD34STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGI_PAD34STRNG_Enum; - -/* =========================================== GPIO PADREGI PAD34INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGI_PAD34INPEN */ - GPIO_PADREGI_PAD34INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGI_PAD34INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGI_PAD34INPEN_Enum; - -/* ============================================ GPIO PADREGI PAD34PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGI_PAD34PULL */ - GPIO_PADREGI_PAD34PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGI_PAD34PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGI_PAD34PULL_Enum; - -/* =========================================== GPIO PADREGI PAD33FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGI_PAD33FNCSEL */ - GPIO_PADREGI_PAD33FNCSEL_ADCSE5 = 0, /*!< ADCSE5 : Configure as the analog ADC single ended port 5 input - signal value. */ - GPIO_PADREGI_PAD33FNCSEL_NCE33 = 1, /*!< NCE33 : IOM/MSPI nCE group 33 value. */ - GPIO_PADREGI_PAD33FNCSEL_32kHzXT = 2, /*!< 32kHzXT : Configure as the 32kHz crystal output signal value. */ - GPIO_PADREGI_PAD33FNCSEL_GPIO33 = 3, /*!< GPIO33 : Configure as GPIO33 value. */ - GPIO_PADREGI_PAD33FNCSEL_UA0CTS = 5, /*!< UA0CTS : Configure as the UART0 CTS input value. */ - GPIO_PADREGI_PAD33FNCSEL_CT23 = 6, /*!< CT23 : CTIMER connection 23 value. */ - GPIO_PADREGI_PAD33FNCSEL_SWO = 7, /*!< SWO : Configure as the serial trace data output signal value. */ -} GPIO_PADREGI_PAD33FNCSEL_Enum; - -/* =========================================== GPIO PADREGI PAD33STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGI_PAD33STRNG */ - GPIO_PADREGI_PAD33STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGI_PAD33STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGI_PAD33STRNG_Enum; - -/* ============================================ GPIO PADREGI PAD33INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGI_PAD33INPEN */ - GPIO_PADREGI_PAD33INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGI_PAD33INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGI_PAD33INPEN_Enum; - -/* ============================================= GPIO PADREGI PAD33PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGI_PAD33PULL */ - GPIO_PADREGI_PAD33PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGI_PAD33PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGI_PAD33PULL_Enum; - -/* ============================================ GPIO PADREGI PAD32FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGI_PAD32FNCSEL */ - GPIO_PADREGI_PAD32FNCSEL_ADCSE4 = 0, /*!< ADCSE4 : Configure as the analog input for ADC single ended - input 4 value. */ - GPIO_PADREGI_PAD32FNCSEL_NCE32 = 1, /*!< NCE32 : IOM/MSPI nCE group 32 value. */ - GPIO_PADREGI_PAD32FNCSEL_CT15 = 2, /*!< CT15 : CTIMER connection 15 value. */ - GPIO_PADREGI_PAD32FNCSEL_GPIO32 = 3, /*!< GPIO32 : Configure as GPIO32 value. */ - GPIO_PADREGI_PAD32FNCSEL_SCCIO = 4, /*!< SCCIO : SCARD serial data input/output value. */ - GPIO_PADREGI_PAD32FNCSEL_EXTLF = 5, /*!< EXTLF : External input to the LFRC oscillator value. */ - GPIO_PADREGI_PAD32FNCSEL_UA1CTS = 7, /*!< UA1CTS : Configure as the UART1 CTS input value. */ -} GPIO_PADREGI_PAD32FNCSEL_Enum; - -/* ============================================ GPIO PADREGI PAD32STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGI_PAD32STRNG */ - GPIO_PADREGI_PAD32STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGI_PAD32STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGI_PAD32STRNG_Enum; - -/* ============================================ GPIO PADREGI PAD32INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGI_PAD32INPEN */ - GPIO_PADREGI_PAD32INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGI_PAD32INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGI_PAD32INPEN_Enum; - -/* ============================================= GPIO PADREGI PAD32PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGI_PAD32PULL */ - GPIO_PADREGI_PAD32PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGI_PAD32PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGI_PAD32PULL_Enum; - -/* ======================================================== PADREGJ ======================================================== */ -/* ============================================ GPIO PADREGJ PAD39RSEL [30..31] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD39RSEL */ - GPIO_PADREGJ_PAD39RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGJ_PAD39RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGJ_PAD39RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGJ_PAD39RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGJ_PAD39RSEL_Enum; - -/* =========================================== GPIO PADREGJ PAD39FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGJ_PAD39FNCSEL */ - GPIO_PADREGJ_PAD39FNCSEL_UART0TX = 0, /*!< UART0TX : Configure as the UART0 TX output signal value. */ - GPIO_PADREGJ_PAD39FNCSEL_UART1TX = 1, /*!< UART1TX : Configure as the UART1 TX output signal value. */ - GPIO_PADREGJ_PAD39FNCSEL_CT25 = 2, /*!< CT25 : CTIMER connection 25 value. */ - GPIO_PADREGJ_PAD39FNCSEL_GPIO39 = 3, /*!< GPIO39 : Configure as GPIO39 value. */ - GPIO_PADREGJ_PAD39FNCSEL_M4SCL = 4, /*!< M4SCL : Configure as the IOMSTR4 I2C SCL signal value. */ - GPIO_PADREGJ_PAD39FNCSEL_M4SCK = 5, /*!< M4SCK : Configure as the IOMSTR4 SPI SCK signal value. */ -} GPIO_PADREGJ_PAD39FNCSEL_Enum; - -/* =========================================== GPIO PADREGJ PAD39STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD39STRNG */ - GPIO_PADREGJ_PAD39STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGJ_PAD39STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGJ_PAD39STRNG_Enum; - -/* =========================================== GPIO PADREGJ PAD39INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD39INPEN */ - GPIO_PADREGJ_PAD39INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGJ_PAD39INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGJ_PAD39INPEN_Enum; - -/* ============================================ GPIO PADREGJ PAD39PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD39PULL */ - GPIO_PADREGJ_PAD39PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGJ_PAD39PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGJ_PAD39PULL_Enum; - -/* =========================================== GPIO PADREGJ PAD38FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGJ_PAD38FNCSEL */ - GPIO_PADREGJ_PAD38FNCSEL_TRIG3 = 0, /*!< TRIG3 : Configure as the ADC Trigger 3 signal value. */ - GPIO_PADREGJ_PAD38FNCSEL_NCE38 = 1, /*!< NCE38 : IOM/MSPI nCE group 38 value. */ - GPIO_PADREGJ_PAD38FNCSEL_UA0CTS = 2, /*!< UA0CTS : Configure as the UART0 CTS signal value. */ - GPIO_PADREGJ_PAD38FNCSEL_GPIO38 = 3, /*!< GPIO38 : Configure as GPIO38 value. */ - GPIO_PADREGJ_PAD38FNCSEL_M3MOSI = 5, /*!< M3MOSI : Configure as the IOMSTR3 SPI MOSI output signal value. */ - GPIO_PADREGJ_PAD38FNCSEL_UART1RX = 6, /*!< UART1RX : Configure as the UART1 RX input signal value. */ -} GPIO_PADREGJ_PAD38FNCSEL_Enum; - -/* =========================================== GPIO PADREGJ PAD38STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD38STRNG */ - GPIO_PADREGJ_PAD38STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGJ_PAD38STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGJ_PAD38STRNG_Enum; - -/* =========================================== GPIO PADREGJ PAD38INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD38INPEN */ - GPIO_PADREGJ_PAD38INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGJ_PAD38INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGJ_PAD38INPEN_Enum; - -/* ============================================ GPIO PADREGJ PAD38PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD38PULL */ - GPIO_PADREGJ_PAD38PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGJ_PAD38PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGJ_PAD38PULL_Enum; - -/* =========================================== GPIO PADREGJ PAD37PWRDN [15..15] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD37PWRDN */ - GPIO_PADREGJ_PAD37PWRDN_DIS = 0, /*!< DIS : Power switch disabled value. */ - GPIO_PADREGJ_PAD37PWRDN_EN = 1, /*!< EN : Power switch enabled (switch to GND) value. */ -} GPIO_PADREGJ_PAD37PWRDN_Enum; - -/* =========================================== GPIO PADREGJ PAD37FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGJ_PAD37FNCSEL */ - GPIO_PADREGJ_PAD37FNCSEL_TRIG2 = 0, /*!< TRIG2 : Configure as the ADC Trigger 2 signal value. */ - GPIO_PADREGJ_PAD37FNCSEL_NCE37 = 1, /*!< NCE37 : IOM/MSPI nCE group 37 value. */ - GPIO_PADREGJ_PAD37FNCSEL_UA0RTS = 2, /*!< UA0RTS : Configure as the UART0 RTS output signal value. */ - GPIO_PADREGJ_PAD37FNCSEL_GPIO37 = 3, /*!< GPIO37 : Configure as GPIO37 value. */ - GPIO_PADREGJ_PAD37FNCSEL_SCCIO = 4, /*!< SCCIO : SCARD serial data input/output value. */ - GPIO_PADREGJ_PAD37FNCSEL_UART1TX = 5, /*!< UART1TX : Configure as the UART1 TX output signal value. */ - GPIO_PADREGJ_PAD37FNCSEL_PDMCLK = 6, /*!< PDMCLK : Configure as the PDM CLK output signal value. */ - GPIO_PADREGJ_PAD37FNCSEL_CT29 = 7, /*!< CT29 : CTIMER connection 29 value. */ -} GPIO_PADREGJ_PAD37FNCSEL_Enum; - -/* =========================================== GPIO PADREGJ PAD37STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD37STRNG */ - GPIO_PADREGJ_PAD37STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGJ_PAD37STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGJ_PAD37STRNG_Enum; - -/* ============================================ GPIO PADREGJ PAD37INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGJ_PAD37INPEN */ - GPIO_PADREGJ_PAD37INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGJ_PAD37INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGJ_PAD37INPEN_Enum; - -/* ============================================= GPIO PADREGJ PAD37PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGJ_PAD37PULL */ - GPIO_PADREGJ_PAD37PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGJ_PAD37PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGJ_PAD37PULL_Enum; - -/* ============================================ GPIO PADREGJ PAD36PWRUP [6..6] ============================================= */ -typedef enum { /*!< GPIO_PADREGJ_PAD36PWRUP */ - GPIO_PADREGJ_PAD36PWRUP_DIS = 0, /*!< DIS : Power switch disabled value. */ - GPIO_PADREGJ_PAD36PWRUP_EN = 1, /*!< EN : Power switch enabled (switched to VDD) value. */ -} GPIO_PADREGJ_PAD36PWRUP_Enum; - -/* ============================================ GPIO PADREGJ PAD36FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGJ_PAD36FNCSEL */ - GPIO_PADREGJ_PAD36FNCSEL_TRIG1 = 0, /*!< TRIG1 : Configure as the ADC Trigger 1 signal value. */ - GPIO_PADREGJ_PAD36FNCSEL_NCE36 = 1, /*!< NCE36 : IOM/MSPI nCE group 36 value. */ - GPIO_PADREGJ_PAD36FNCSEL_UART1RX = 2, /*!< UART1RX : Configure as the UART1 RX input signal value. */ - GPIO_PADREGJ_PAD36FNCSEL_GPIO36 = 3, /*!< GPIO36 : Configure as GPIO36 value. */ - GPIO_PADREGJ_PAD36FNCSEL_32kHzXT = 4, /*!< 32kHzXT : Configure as the 32kHz output clock from the crystal - value. */ - GPIO_PADREGJ_PAD36FNCSEL_UA1CTS = 5, /*!< UA1CTS : Configure as the UART1 CTS input signal value. */ - GPIO_PADREGJ_PAD36FNCSEL_UA0CTS = 6, /*!< UA0CTS : Configure as the UART0 CTS input signal value. */ - GPIO_PADREGJ_PAD36FNCSEL_PDMDATA = 7, /*!< PDMDATA : PDM serial data input value. */ -} GPIO_PADREGJ_PAD36FNCSEL_Enum; - -/* ============================================ GPIO PADREGJ PAD36STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGJ_PAD36STRNG */ - GPIO_PADREGJ_PAD36STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGJ_PAD36STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGJ_PAD36STRNG_Enum; - -/* ============================================ GPIO PADREGJ PAD36INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGJ_PAD36INPEN */ - GPIO_PADREGJ_PAD36INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGJ_PAD36INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGJ_PAD36INPEN_Enum; - -/* ============================================= GPIO PADREGJ PAD36PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGJ_PAD36PULL */ - GPIO_PADREGJ_PAD36PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGJ_PAD36PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGJ_PAD36PULL_Enum; - -/* ======================================================== PADREGK ======================================================== */ -/* ============================================ GPIO PADREGK PAD43RSEL [30..31] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD43RSEL */ - GPIO_PADREGK_PAD43RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGK_PAD43RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGK_PAD43RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGK_PAD43RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGK_PAD43RSEL_Enum; - -/* =========================================== GPIO PADREGK PAD43FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGK_PAD43FNCSEL */ - GPIO_PADREGK_PAD43FNCSEL_UART1RX = 0, /*!< UART1RX : Configure as the UART1 RX input signal value. */ - GPIO_PADREGK_PAD43FNCSEL_NCE43 = 1, /*!< NCE43 : IOM/MSPI nCE group 43 value. */ - GPIO_PADREGK_PAD43FNCSEL_CT18 = 2, /*!< CT18 : CTIMER connection 18 value. */ - GPIO_PADREGK_PAD43FNCSEL_GPIO43 = 3, /*!< GPIO43 : Configure as GPIO43 value. */ - GPIO_PADREGK_PAD43FNCSEL_M3SDAWIR3 = 4, /*!< M3SDAWIR3 : Configure as the IOMSTR3 I2C SDA or SPI WIR3 signal - value. */ - GPIO_PADREGK_PAD43FNCSEL_M3MISO = 5, /*!< M3MISO : Configure as the IOMSTR3 SPI MISO signal value. */ -} GPIO_PADREGK_PAD43FNCSEL_Enum; - -/* =========================================== GPIO PADREGK PAD43STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD43STRNG */ - GPIO_PADREGK_PAD43STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGK_PAD43STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGK_PAD43STRNG_Enum; - -/* =========================================== GPIO PADREGK PAD43INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD43INPEN */ - GPIO_PADREGK_PAD43INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGK_PAD43INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGK_PAD43INPEN_Enum; - -/* ============================================ GPIO PADREGK PAD43PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD43PULL */ - GPIO_PADREGK_PAD43PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGK_PAD43PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGK_PAD43PULL_Enum; - -/* ============================================ GPIO PADREGK PAD42RSEL [22..23] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD42RSEL */ - GPIO_PADREGK_PAD42RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGK_PAD42RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGK_PAD42RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGK_PAD42RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGK_PAD42RSEL_Enum; - -/* =========================================== GPIO PADREGK PAD42FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGK_PAD42FNCSEL */ - GPIO_PADREGK_PAD42FNCSEL_UART1TX = 0, /*!< UART1TX : Configure as the UART1 TX output signal value. */ - GPIO_PADREGK_PAD42FNCSEL_NCE42 = 1, /*!< NCE42 : IOM/MSPI nCE group 42 value. */ - GPIO_PADREGK_PAD42FNCSEL_CT16 = 2, /*!< CT16 : CTIMER connection 16 value. */ - GPIO_PADREGK_PAD42FNCSEL_GPIO42 = 3, /*!< GPIO42 : Configure as GPIO42 value. */ - GPIO_PADREGK_PAD42FNCSEL_M3SCL = 4, /*!< M3SCL : Configure as the IOMSTR3 I2C SCL clock I/O signal value. */ - GPIO_PADREGK_PAD42FNCSEL_M3SCK = 5, /*!< M3SCK : Configure as the IOMSTR3 SPI SCK output value. */ -} GPIO_PADREGK_PAD42FNCSEL_Enum; - -/* =========================================== GPIO PADREGK PAD42STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD42STRNG */ - GPIO_PADREGK_PAD42STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGK_PAD42STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGK_PAD42STRNG_Enum; - -/* =========================================== GPIO PADREGK PAD42INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD42INPEN */ - GPIO_PADREGK_PAD42INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGK_PAD42INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGK_PAD42INPEN_Enum; - -/* ============================================ GPIO PADREGK PAD42PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD42PULL */ - GPIO_PADREGK_PAD42PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGK_PAD42PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGK_PAD42PULL_Enum; - -/* =========================================== GPIO PADREGK PAD41PWRDN [15..15] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD41PWRDN */ - GPIO_PADREGK_PAD41PWRDN_DIS = 0, /*!< DIS : Power switch disabled value. */ - GPIO_PADREGK_PAD41PWRDN_EN = 1, /*!< EN : Power switch enabled (Switch pad to VSS) value. */ -} GPIO_PADREGK_PAD41PWRDN_Enum; - -/* =========================================== GPIO PADREGK PAD41FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGK_PAD41FNCSEL */ - GPIO_PADREGK_PAD41FNCSEL_NCE41 = 0, /*!< NCE41 : IOM/MSPI nCE group 41 value. */ - GPIO_PADREGK_PAD41FNCSEL_SWO = 2, /*!< SWO : Configure as the serial wire debug SWO signal value. */ - GPIO_PADREGK_PAD41FNCSEL_GPIO41 = 3, /*!< GPIO41 : Configure as GPIO41 value. */ - GPIO_PADREGK_PAD41FNCSEL_I2SWCLK = 4, /*!< I2SWCLK : I2S word clock input value. */ - GPIO_PADREGK_PAD41FNCSEL_UA1RTS = 5, /*!< UA1RTS : Configure as the UART1 RTS output signal value. */ - GPIO_PADREGK_PAD41FNCSEL_UART0TX = 6, /*!< UART0TX : Configure as the UART0 TX output signal value. */ - GPIO_PADREGK_PAD41FNCSEL_UA0RTS = 7, /*!< UA0RTS : Configure as the UART0 RTS output signal value. */ -} GPIO_PADREGK_PAD41FNCSEL_Enum; - -/* =========================================== GPIO PADREGK PAD41STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD41STRNG */ - GPIO_PADREGK_PAD41STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGK_PAD41STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGK_PAD41STRNG_Enum; - -/* ============================================ GPIO PADREGK PAD41INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGK_PAD41INPEN */ - GPIO_PADREGK_PAD41INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGK_PAD41INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGK_PAD41INPEN_Enum; - -/* ============================================= GPIO PADREGK PAD41PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGK_PAD41PULL */ - GPIO_PADREGK_PAD41PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGK_PAD41PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGK_PAD41PULL_Enum; - -/* ============================================= GPIO PADREGK PAD40RSEL [6..7] ============================================= */ -typedef enum { /*!< GPIO_PADREGK_PAD40RSEL */ - GPIO_PADREGK_PAD40RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGK_PAD40RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGK_PAD40RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGK_PAD40RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGK_PAD40RSEL_Enum; - -/* ============================================ GPIO PADREGK PAD40FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGK_PAD40FNCSEL */ - GPIO_PADREGK_PAD40FNCSEL_UART0RX = 0, /*!< UART0RX : Configure as the UART0 RX input signal value. */ - GPIO_PADREGK_PAD40FNCSEL_UART1RX = 1, /*!< UART1RX : Configure as the UART1 RX input signal value. */ - GPIO_PADREGK_PAD40FNCSEL_TRIG0 = 2, /*!< TRIG0 : Configure as the ADC Trigger 0 signal value. */ - GPIO_PADREGK_PAD40FNCSEL_GPIO40 = 3, /*!< GPIO40 : Configure as GPIO40 value. */ - GPIO_PADREGK_PAD40FNCSEL_M4SDAWIR3 = 4, /*!< M4SDAWIR3 : Configure as the IOMSTR4 I2C SDA or SPI WIR3 signal - value. */ - GPIO_PADREGK_PAD40FNCSEL_M4MISO = 5, /*!< M4MISO : Configure as the IOMSTR4 SPI MISO input signal value. */ -} GPIO_PADREGK_PAD40FNCSEL_Enum; - -/* ============================================ GPIO PADREGK PAD40STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGK_PAD40STRNG */ - GPIO_PADREGK_PAD40STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGK_PAD40STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGK_PAD40STRNG_Enum; - -/* ============================================ GPIO PADREGK PAD40INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGK_PAD40INPEN */ - GPIO_PADREGK_PAD40INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGK_PAD40INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGK_PAD40INPEN_Enum; - -/* ============================================= GPIO PADREGK PAD40PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGK_PAD40PULL */ - GPIO_PADREGK_PAD40PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGK_PAD40PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGK_PAD40PULL_Enum; - -/* ======================================================== PADREGL ======================================================== */ -/* =========================================== GPIO PADREGL PAD47FNCSEL [27..29] =========================================== */ -typedef enum { /*!< GPIO_PADREGL_PAD47FNCSEL */ - GPIO_PADREGL_PAD47FNCSEL_32kHzXT = 0, /*!< 32kHzXT : Configure as the 32kHz output clock from the crystal - value. */ - GPIO_PADREGL_PAD47FNCSEL_NCE47 = 1, /*!< NCE47 : IOM/MSPI nCE group 47 value. */ - GPIO_PADREGL_PAD47FNCSEL_CT26 = 2, /*!< CT26 : CTIMER connection 26 value. */ - GPIO_PADREGL_PAD47FNCSEL_GPIO47 = 3, /*!< GPIO47 : Configure as GPIO47 value. */ - GPIO_PADREGL_PAD47FNCSEL_M5MOSI = 5, /*!< M5MOSI : Configure as the IOMSTR5 SPI MOSI output signal value. */ - GPIO_PADREGL_PAD47FNCSEL_UART1RX = 6, /*!< UART1RX : Configure as the UART1 RX input signal value. */ -} GPIO_PADREGL_PAD47FNCSEL_Enum; - -/* =========================================== GPIO PADREGL PAD47STRNG [26..26] ============================================ */ -typedef enum { /*!< GPIO_PADREGL_PAD47STRNG */ - GPIO_PADREGL_PAD47STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGL_PAD47STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGL_PAD47STRNG_Enum; - -/* =========================================== GPIO PADREGL PAD47INPEN [25..25] ============================================ */ -typedef enum { /*!< GPIO_PADREGL_PAD47INPEN */ - GPIO_PADREGL_PAD47INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGL_PAD47INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGL_PAD47INPEN_Enum; - -/* ============================================ GPIO PADREGL PAD47PULL [24..24] ============================================ */ -typedef enum { /*!< GPIO_PADREGL_PAD47PULL */ - GPIO_PADREGL_PAD47PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGL_PAD47PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGL_PAD47PULL_Enum; - -/* =========================================== GPIO PADREGL PAD46FNCSEL [19..21] =========================================== */ -typedef enum { /*!< GPIO_PADREGL_PAD46FNCSEL */ - GPIO_PADREGL_PAD46FNCSEL_32khz_XT = 0, /*!< 32khz_XT : Configure as the 32kHz output clock from the crystal - value. */ - GPIO_PADREGL_PAD46FNCSEL_NCE46 = 1, /*!< NCE46 : IOM/MSPI nCE group 46 value. */ - GPIO_PADREGL_PAD46FNCSEL_CT24 = 2, /*!< CT24 : CTIMER connection 24 value. */ - GPIO_PADREGL_PAD46FNCSEL_GPIO46 = 3, /*!< GPIO46 : Configure as GPIO46 value. */ - GPIO_PADREGL_PAD46FNCSEL_SCCRST = 4, /*!< SCCRST : SCARD reset output value. */ - GPIO_PADREGL_PAD46FNCSEL_PDMCLK = 5, /*!< PDMCLK : PDM serial clock output value. */ - GPIO_PADREGL_PAD46FNCSEL_UART1TX = 6, /*!< UART1TX : Configure as the UART1 TX output signal value. */ - GPIO_PADREGL_PAD46FNCSEL_SWO = 7, /*!< SWO : Configure as the serial wire debug SWO signal value. */ -} GPIO_PADREGL_PAD46FNCSEL_Enum; - -/* =========================================== GPIO PADREGL PAD46STRNG [18..18] ============================================ */ -typedef enum { /*!< GPIO_PADREGL_PAD46STRNG */ - GPIO_PADREGL_PAD46STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGL_PAD46STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGL_PAD46STRNG_Enum; - -/* =========================================== GPIO PADREGL PAD46INPEN [17..17] ============================================ */ -typedef enum { /*!< GPIO_PADREGL_PAD46INPEN */ - GPIO_PADREGL_PAD46INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGL_PAD46INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGL_PAD46INPEN_Enum; - -/* ============================================ GPIO PADREGL PAD46PULL [16..16] ============================================ */ -typedef enum { /*!< GPIO_PADREGL_PAD46PULL */ - GPIO_PADREGL_PAD46PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGL_PAD46PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGL_PAD46PULL_Enum; - -/* =========================================== GPIO PADREGL PAD45FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGL_PAD45FNCSEL */ - GPIO_PADREGL_PAD45FNCSEL_UA1CTS = 0, /*!< UA1CTS : Configure as the UART1 CTS input signal value. */ - GPIO_PADREGL_PAD45FNCSEL_NCE45 = 1, /*!< NCE45 : IOM/MSPI nCE group 45 value. */ - GPIO_PADREGL_PAD45FNCSEL_CT22 = 2, /*!< CT22 : CTIMER connection 22 value. */ - GPIO_PADREGL_PAD45FNCSEL_GPIO45 = 3, /*!< GPIO45 : Configure as GPIO45 value. */ - GPIO_PADREGL_PAD45FNCSEL_I2SDAT = 4, /*!< I2SDAT : I2S serial data output value. */ - GPIO_PADREGL_PAD45FNCSEL_PDMDATA = 5, /*!< PDMDATA : PDM serial data input value. */ - GPIO_PADREGL_PAD45FNCSEL_UART0RX = 6, /*!< UART0RX : Configure as the SPI channel 5 nCE signal from IOMSTR5 - value. */ - GPIO_PADREGL_PAD45FNCSEL_SWO = 7, /*!< SWO : Configure as the serial wire debug SWO signal value. */ -} GPIO_PADREGL_PAD45FNCSEL_Enum; - -/* =========================================== GPIO PADREGL PAD45STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGL_PAD45STRNG */ - GPIO_PADREGL_PAD45STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGL_PAD45STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGL_PAD45STRNG_Enum; - -/* ============================================ GPIO PADREGL PAD45INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGL_PAD45INPEN */ - GPIO_PADREGL_PAD45INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGL_PAD45INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGL_PAD45INPEN_Enum; - -/* ============================================= GPIO PADREGL PAD45PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGL_PAD45PULL */ - GPIO_PADREGL_PAD45PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGL_PAD45PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGL_PAD45PULL_Enum; - -/* ============================================ GPIO PADREGL PAD44FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGL_PAD44FNCSEL */ - GPIO_PADREGL_PAD44FNCSEL_UA1RTS = 0, /*!< UA1RTS : Configure as the UART1 RTS output signal value. */ - GPIO_PADREGL_PAD44FNCSEL_NCE44 = 1, /*!< NCE44 : IOM/MSPI nCE group 44 value. */ - GPIO_PADREGL_PAD44FNCSEL_CT20 = 2, /*!< CT20 : CTIMER connection 20 value. */ - GPIO_PADREGL_PAD44FNCSEL_GPIO44 = 3, /*!< GPIO44 : Configure as GPIO44 value. */ - GPIO_PADREGL_PAD44FNCSEL_M4MOSI = 5, /*!< M4MOSI : Configure as the IOMSTR4 SPI MOSI signal value. */ - GPIO_PADREGL_PAD44FNCSEL_M5nCE6 = 6, /*!< M5nCE6 : Configure as the SPI channel 6 nCE signal from IOMSTR5 - value. */ -} GPIO_PADREGL_PAD44FNCSEL_Enum; - -/* ============================================ GPIO PADREGL PAD44STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGL_PAD44STRNG */ - GPIO_PADREGL_PAD44STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGL_PAD44STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGL_PAD44STRNG_Enum; - -/* ============================================ GPIO PADREGL PAD44INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGL_PAD44INPEN */ - GPIO_PADREGL_PAD44INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGL_PAD44INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGL_PAD44INPEN_Enum; - -/* ============================================= GPIO PADREGL PAD44PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGL_PAD44PULL */ - GPIO_PADREGL_PAD44PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGL_PAD44PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGL_PAD44PULL_Enum; - -/* ======================================================== PADREGM ======================================================== */ -/* ============================================ GPIO PADREGM PAD49RSEL [14..15] ============================================ */ -typedef enum { /*!< GPIO_PADREGM_PAD49RSEL */ - GPIO_PADREGM_PAD49RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGM_PAD49RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGM_PAD49RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGM_PAD49RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGM_PAD49RSEL_Enum; - -/* =========================================== GPIO PADREGM PAD49FNCSEL [11..13] =========================================== */ -typedef enum { /*!< GPIO_PADREGM_PAD49FNCSEL */ - GPIO_PADREGM_PAD49FNCSEL_UART0RX = 0, /*!< UART0RX : Configure as the UART0 RX input signal value. */ - GPIO_PADREGM_PAD49FNCSEL_NCE49 = 1, /*!< NCE49 : IOM/MSPPI nCE group 49 value. */ - GPIO_PADREGM_PAD49FNCSEL_CT30 = 2, /*!< CT30 : CTIMER connection 30 value. */ - GPIO_PADREGM_PAD49FNCSEL_GPIO49 = 3, /*!< GPIO49 : Configure as GPIO49 value. */ - GPIO_PADREGM_PAD49FNCSEL_M5SDAWIR3 = 4, /*!< M5SDAWIR3 : Configure as the IOMSTR5 I2C SDA or SPI WIR3 signal - value. */ - GPIO_PADREGM_PAD49FNCSEL_M5MISO = 5, /*!< M5MISO : Configure as the IOMSTR5 SPI MISO input signal value. */ -} GPIO_PADREGM_PAD49FNCSEL_Enum; - -/* =========================================== GPIO PADREGM PAD49STRNG [10..10] ============================================ */ -typedef enum { /*!< GPIO_PADREGM_PAD49STRNG */ - GPIO_PADREGM_PAD49STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGM_PAD49STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGM_PAD49STRNG_Enum; - -/* ============================================ GPIO PADREGM PAD49INPEN [9..9] ============================================= */ -typedef enum { /*!< GPIO_PADREGM_PAD49INPEN */ - GPIO_PADREGM_PAD49INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGM_PAD49INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGM_PAD49INPEN_Enum; - -/* ============================================= GPIO PADREGM PAD49PULL [8..8] ============================================= */ -typedef enum { /*!< GPIO_PADREGM_PAD49PULL */ - GPIO_PADREGM_PAD49PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGM_PAD49PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGM_PAD49PULL_Enum; - -/* ============================================= GPIO PADREGM PAD48RSEL [6..7] ============================================= */ -typedef enum { /*!< GPIO_PADREGM_PAD48RSEL */ - GPIO_PADREGM_PAD48RSEL_PULL1_5K = 0, /*!< PULL1_5K : Pullup is ~1.5 KOhms value. */ - GPIO_PADREGM_PAD48RSEL_PULL6K = 1, /*!< PULL6K : Pullup is ~6 KOhms value. */ - GPIO_PADREGM_PAD48RSEL_PULL12K = 2, /*!< PULL12K : Pullup is ~12 KOhms value. */ - GPIO_PADREGM_PAD48RSEL_PULL24K = 3, /*!< PULL24K : Pullup is ~24 KOhms value. */ -} GPIO_PADREGM_PAD48RSEL_Enum; - -/* ============================================ GPIO PADREGM PAD48FNCSEL [3..5] ============================================ */ -typedef enum { /*!< GPIO_PADREGM_PAD48FNCSEL */ - GPIO_PADREGM_PAD48FNCSEL_UART0TX = 0, /*!< UART0TX : Configure as the UART0 TX output signal value. */ - GPIO_PADREGM_PAD48FNCSEL_NCE48 = 1, /*!< NCE48 : IOM/MSPI nCE group 48 value. */ - GPIO_PADREGM_PAD48FNCSEL_CT28 = 2, /*!< CT28 : CTIMER conenction 28 value. */ - GPIO_PADREGM_PAD48FNCSEL_GPIO48 = 3, /*!< GPIO48 : Configure as GPIO48 value. */ - GPIO_PADREGM_PAD48FNCSEL_M5SCL = 4, /*!< M5SCL : Configure as the IOMSTR5 I2C SCL clock I/O signal value. */ - GPIO_PADREGM_PAD48FNCSEL_M5SCK = 5, /*!< M5SCK : Configure as the IOMSTR5 SPI SCK output value. */ -} GPIO_PADREGM_PAD48FNCSEL_Enum; - -/* ============================================ GPIO PADREGM PAD48STRNG [2..2] ============================================= */ -typedef enum { /*!< GPIO_PADREGM_PAD48STRNG */ - GPIO_PADREGM_PAD48STRNG_LOW = 0, /*!< LOW : Low drive strength value. */ - GPIO_PADREGM_PAD48STRNG_HIGH = 1, /*!< HIGH : High drive strength value. */ -} GPIO_PADREGM_PAD48STRNG_Enum; - -/* ============================================ GPIO PADREGM PAD48INPEN [1..1] ============================================= */ -typedef enum { /*!< GPIO_PADREGM_PAD48INPEN */ - GPIO_PADREGM_PAD48INPEN_DIS = 0, /*!< DIS : Pad input disabled value. */ - GPIO_PADREGM_PAD48INPEN_EN = 1, /*!< EN : Pad input enabled value. */ -} GPIO_PADREGM_PAD48INPEN_Enum; - -/* ============================================= GPIO PADREGM PAD48PULL [0..0] ============================================= */ -typedef enum { /*!< GPIO_PADREGM_PAD48PULL */ - GPIO_PADREGM_PAD48PULL_DIS = 0, /*!< DIS : Pullup disabled value. */ - GPIO_PADREGM_PAD48PULL_EN = 1, /*!< EN : Pullup enabled value. */ -} GPIO_PADREGM_PAD48PULL_Enum; - -/* ========================================================= CFGA ========================================================== */ -/* ============================================= GPIO CFGA GPIO7INTD [31..31] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO7INTD */ - GPIO_CFGA_GPIO7INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x0 - nCE polarity active low value. */ - GPIO_CFGA_GPIO7INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x0 - nCE polarity active high value. */ -} GPIO_CFGA_GPIO7INTD_Enum; - -/* ============================================ GPIO CFGA GPIO7OUTCFG [29..30] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO7OUTCFG */ - GPIO_CFGA_GPIO7OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGA_GPIO7OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGA_GPIO7OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGA_GPIO7OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGA_GPIO7OUTCFG_Enum; - -/* ============================================= GPIO CFGA GPIO7INCFG [28..28] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO7INCFG */ - GPIO_CFGA_GPIO7INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGA_GPIO7INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGA_GPIO7INCFG_Enum; - -/* ============================================= GPIO CFGA GPIO6INTD [27..27] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO6INTD */ - GPIO_CFGA_GPIO6INTD_INTDIS = 0, /*!< INTDIS : INCFG = 1 - No interrupt on GPIO transition value. */ - GPIO_CFGA_GPIO6INTD_INTBOTH = 1, /*!< INTBOTH : INCFG = 1 - Interrupt on either low to high or high - to low GPIO transition value. */ -} GPIO_CFGA_GPIO6INTD_Enum; - -/* ============================================ GPIO CFGA GPIO6OUTCFG [25..26] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO6OUTCFG */ - GPIO_CFGA_GPIO6OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGA_GPIO6OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGA_GPIO6OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGA_GPIO6OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGA_GPIO6OUTCFG_Enum; - -/* ============================================= GPIO CFGA GPIO6INCFG [24..24] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO6INCFG */ - GPIO_CFGA_GPIO6INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGA_GPIO6INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGA_GPIO6INCFG_Enum; - -/* ============================================= GPIO CFGA GPIO5INTD [23..23] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO5INTD */ - GPIO_CFGA_GPIO5INTD_INTDIS = 0, /*!< INTDIS : INCFG = 1 - No interrupt on GPIO transition value. */ - GPIO_CFGA_GPIO5INTD_INTBOTH = 1, /*!< INTBOTH : INCFG = 1 - Interrupt on either low to high or high - to low GPIO transition value. */ -} GPIO_CFGA_GPIO5INTD_Enum; - -/* ============================================ GPIO CFGA GPIO5OUTCFG [21..22] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO5OUTCFG */ - GPIO_CFGA_GPIO5OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGA_GPIO5OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGA_GPIO5OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGA_GPIO5OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGA_GPIO5OUTCFG_Enum; - -/* ============================================= GPIO CFGA GPIO5INCFG [20..20] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO5INCFG */ - GPIO_CFGA_GPIO5INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGA_GPIO5INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGA_GPIO5INCFG_Enum; - -/* ============================================= GPIO CFGA GPIO4INTD [19..19] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO4INTD */ - GPIO_CFGA_GPIO4INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ - GPIO_CFGA_GPIO4INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ -} GPIO_CFGA_GPIO4INTD_Enum; - -/* ============================================ GPIO CFGA GPIO4OUTCFG [17..18] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO4OUTCFG */ - GPIO_CFGA_GPIO4OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGA_GPIO4OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGA_GPIO4OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGA_GPIO4OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGA_GPIO4OUTCFG_Enum; - -/* ============================================= GPIO CFGA GPIO4INCFG [16..16] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO4INCFG */ - GPIO_CFGA_GPIO4INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGA_GPIO4INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGA_GPIO4INCFG_Enum; - -/* ============================================= GPIO CFGA GPIO3INTD [15..15] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO3INTD */ - GPIO_CFGA_GPIO3INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ - GPIO_CFGA_GPIO3INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ -} GPIO_CFGA_GPIO3INTD_Enum; - -/* ============================================ GPIO CFGA GPIO3OUTCFG [13..14] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO3OUTCFG */ - GPIO_CFGA_GPIO3OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGA_GPIO3OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGA_GPIO3OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGA_GPIO3OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGA_GPIO3OUTCFG_Enum; - -/* ============================================= GPIO CFGA GPIO3INCFG [12..12] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO3INCFG */ - GPIO_CFGA_GPIO3INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGA_GPIO3INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGA_GPIO3INCFG_Enum; - -/* ============================================= GPIO CFGA GPIO2INTD [11..11] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO2INTD */ - GPIO_CFGA_GPIO2INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x7 - nCE polarity active low value. */ - GPIO_CFGA_GPIO2INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x7 - nCE polarity active high value. */ -} GPIO_CFGA_GPIO2INTD_Enum; - -/* ============================================= GPIO CFGA GPIO2OUTCFG [9..10] ============================================= */ -typedef enum { /*!< GPIO_CFGA_GPIO2OUTCFG */ - GPIO_CFGA_GPIO2OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGA_GPIO2OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGA_GPIO2OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGA_GPIO2OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGA_GPIO2OUTCFG_Enum; - -/* ============================================== GPIO CFGA GPIO2INCFG [8..8] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO2INCFG */ - GPIO_CFGA_GPIO2INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGA_GPIO2INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGA_GPIO2INCFG_Enum; - -/* ============================================== GPIO CFGA GPIO1INTD [7..7] =============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO1INTD */ - GPIO_CFGA_GPIO1INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x7 - nCE polarity active low value. */ - GPIO_CFGA_GPIO1INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x7 - nCE polarity active high value. */ -} GPIO_CFGA_GPIO1INTD_Enum; - -/* ============================================= GPIO CFGA GPIO1OUTCFG [5..6] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO1OUTCFG */ - GPIO_CFGA_GPIO1OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGA_GPIO1OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGA_GPIO1OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGA_GPIO1OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGA_GPIO1OUTCFG_Enum; - -/* ============================================== GPIO CFGA GPIO1INCFG [4..4] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO1INCFG */ - GPIO_CFGA_GPIO1INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGA_GPIO1INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGA_GPIO1INCFG_Enum; - -/* ============================================== GPIO CFGA GPIO0INTD [3..3] =============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO0INTD */ - GPIO_CFGA_GPIO0INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x7 - nCE polarity active low value. */ - GPIO_CFGA_GPIO0INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x7 - nCE polarity active high value. */ -} GPIO_CFGA_GPIO0INTD_Enum; - -/* ============================================= GPIO CFGA GPIO0OUTCFG [1..2] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO0OUTCFG */ - GPIO_CFGA_GPIO0OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGA_GPIO0OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGA_GPIO0OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGA_GPIO0OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGA_GPIO0OUTCFG_Enum; - -/* ============================================== GPIO CFGA GPIO0INCFG [0..0] ============================================== */ -typedef enum { /*!< GPIO_CFGA_GPIO0INCFG */ - GPIO_CFGA_GPIO0INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGA_GPIO0INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGA_GPIO0INCFG_Enum; - -/* ========================================================= CFGB ========================================================== */ -/* ============================================= GPIO CFGB GPIO15INTD [31..31] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO15INTD */ - GPIO_CFGB_GPIO15INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGB_GPIO15INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGB_GPIO15INTD_Enum; - -/* ============================================ GPIO CFGB GPIO15OUTCFG [29..30] ============================================ */ -typedef enum { /*!< GPIO_CFGB_GPIO15OUTCFG */ - GPIO_CFGB_GPIO15OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGB_GPIO15OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGB_GPIO15OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGB_GPIO15OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGB_GPIO15OUTCFG_Enum; - -/* ============================================ GPIO CFGB GPIO15INCFG [28..28] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO15INCFG */ - GPIO_CFGB_GPIO15INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGB_GPIO15INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGB_GPIO15INCFG_Enum; - -/* ============================================= GPIO CFGB GPIO14INTD [27..27] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO14INTD */ - GPIO_CFGB_GPIO14INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGB_GPIO14INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGB_GPIO14INTD_Enum; - -/* ============================================ GPIO CFGB GPIO14OUTCFG [25..26] ============================================ */ -typedef enum { /*!< GPIO_CFGB_GPIO14OUTCFG */ - GPIO_CFGB_GPIO14OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGB_GPIO14OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGB_GPIO14OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGB_GPIO14OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGB_GPIO14OUTCFG_Enum; - -/* ============================================ GPIO CFGB GPIO14INCFG [24..24] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO14INCFG */ - GPIO_CFGB_GPIO14INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGB_GPIO14INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGB_GPIO14INCFG_Enum; - -/* ============================================= GPIO CFGB GPIO13INTD [23..23] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO13INTD */ - GPIO_CFGB_GPIO13INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGB_GPIO13INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGB_GPIO13INTD_Enum; - -/* ============================================ GPIO CFGB GPIO13OUTCFG [21..22] ============================================ */ -typedef enum { /*!< GPIO_CFGB_GPIO13OUTCFG */ - GPIO_CFGB_GPIO13OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGB_GPIO13OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGB_GPIO13OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGB_GPIO13OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGB_GPIO13OUTCFG_Enum; - -/* ============================================ GPIO CFGB GPIO13INCFG [20..20] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO13INCFG */ - GPIO_CFGB_GPIO13INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGB_GPIO13INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGB_GPIO13INCFG_Enum; - -/* ============================================= GPIO CFGB GPIO12INTD [19..19] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO12INTD */ - GPIO_CFGB_GPIO12INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGB_GPIO12INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGB_GPIO12INTD_Enum; - -/* ============================================ GPIO CFGB GPIO12OUTCFG [17..18] ============================================ */ -typedef enum { /*!< GPIO_CFGB_GPIO12OUTCFG */ - GPIO_CFGB_GPIO12OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGB_GPIO12OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGB_GPIO12OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGB_GPIO12OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGB_GPIO12OUTCFG_Enum; - -/* ============================================ GPIO CFGB GPIO12INCFG [16..16] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO12INCFG */ - GPIO_CFGB_GPIO12INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGB_GPIO12INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGB_GPIO12INCFG_Enum; - -/* ============================================= GPIO CFGB GPIO11INTD [15..15] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO11INTD */ - GPIO_CFGB_GPIO11INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGB_GPIO11INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGB_GPIO11INTD_Enum; - -/* ============================================ GPIO CFGB GPIO11OUTCFG [13..14] ============================================ */ -typedef enum { /*!< GPIO_CFGB_GPIO11OUTCFG */ - GPIO_CFGB_GPIO11OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGB_GPIO11OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGB_GPIO11OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGB_GPIO11OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGB_GPIO11OUTCFG_Enum; - -/* ============================================ GPIO CFGB GPIO11INCFG [12..12] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO11INCFG */ - GPIO_CFGB_GPIO11INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGB_GPIO11INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGB_GPIO11INCFG_Enum; - -/* ============================================= GPIO CFGB GPIO10INTD [11..11] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO10INTD */ - GPIO_CFGB_GPIO10INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ - GPIO_CFGB_GPIO10INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ -} GPIO_CFGB_GPIO10INTD_Enum; - -/* ============================================ GPIO CFGB GPIO10OUTCFG [9..10] ============================================= */ -typedef enum { /*!< GPIO_CFGB_GPIO10OUTCFG */ - GPIO_CFGB_GPIO10OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGB_GPIO10OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGB_GPIO10OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGB_GPIO10OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGB_GPIO10OUTCFG_Enum; - -/* ============================================= GPIO CFGB GPIO10INCFG [8..8] ============================================== */ -typedef enum { /*!< GPIO_CFGB_GPIO10INCFG */ - GPIO_CFGB_GPIO10INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGB_GPIO10INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGB_GPIO10INCFG_Enum; - -/* ============================================== GPIO CFGB GPIO9INTD [7..7] =============================================== */ -typedef enum { /*!< GPIO_CFGB_GPIO9INTD */ - GPIO_CFGB_GPIO9INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ - GPIO_CFGB_GPIO9INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ -} GPIO_CFGB_GPIO9INTD_Enum; - -/* ============================================= GPIO CFGB GPIO9OUTCFG [5..6] ============================================== */ -typedef enum { /*!< GPIO_CFGB_GPIO9OUTCFG */ - GPIO_CFGB_GPIO9OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGB_GPIO9OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGB_GPIO9OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGB_GPIO9OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGB_GPIO9OUTCFG_Enum; - -/* ============================================== GPIO CFGB GPIO9INCFG [4..4] ============================================== */ -typedef enum { /*!< GPIO_CFGB_GPIO9INCFG */ - GPIO_CFGB_GPIO9INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGB_GPIO9INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGB_GPIO9INCFG_Enum; - -/* ============================================== GPIO CFGB GPIO8INTD [3..3] =============================================== */ -typedef enum { /*!< GPIO_CFGB_GPIO8INTD */ - GPIO_CFGB_GPIO8INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x2 - nCE polarity active low value. */ - GPIO_CFGB_GPIO8INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x2 - nCE polarity active high value. */ -} GPIO_CFGB_GPIO8INTD_Enum; - -/* ============================================= GPIO CFGB GPIO8OUTCFG [1..2] ============================================== */ -typedef enum { /*!< GPIO_CFGB_GPIO8OUTCFG */ - GPIO_CFGB_GPIO8OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGB_GPIO8OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGB_GPIO8OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGB_GPIO8OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGB_GPIO8OUTCFG_Enum; - -/* ============================================== GPIO CFGB GPIO8INCFG [0..0] ============================================== */ -typedef enum { /*!< GPIO_CFGB_GPIO8INCFG */ - GPIO_CFGB_GPIO8INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGB_GPIO8INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGB_GPIO8INCFG_Enum; - -/* ========================================================= CFGC ========================================================== */ -/* ============================================= GPIO CFGC GPIO23INTD [31..31] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO23INTD */ - GPIO_CFGC_GPIO23INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGC_GPIO23INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGC_GPIO23INTD_Enum; - -/* ============================================ GPIO CFGC GPIO23OUTCFG [29..30] ============================================ */ -typedef enum { /*!< GPIO_CFGC_GPIO23OUTCFG */ - GPIO_CFGC_GPIO23OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGC_GPIO23OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGC_GPIO23OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGC_GPIO23OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGC_GPIO23OUTCFG_Enum; - -/* ============================================ GPIO CFGC GPIO23INCFG [28..28] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO23INCFG */ - GPIO_CFGC_GPIO23INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGC_GPIO23INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGC_GPIO23INCFG_Enum; - -/* ============================================= GPIO CFGC GPIO22INTD [27..27] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO22INTD */ - GPIO_CFGC_GPIO22INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGC_GPIO22INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGC_GPIO22INTD_Enum; - -/* ============================================ GPIO CFGC GPIO22OUTCFG [25..26] ============================================ */ -typedef enum { /*!< GPIO_CFGC_GPIO22OUTCFG */ - GPIO_CFGC_GPIO22OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGC_GPIO22OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGC_GPIO22OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGC_GPIO22OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGC_GPIO22OUTCFG_Enum; - -/* ============================================ GPIO CFGC GPIO22INCFG [24..24] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO22INCFG */ - GPIO_CFGC_GPIO22INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGC_GPIO22INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGC_GPIO22INCFG_Enum; - -/* ============================================= GPIO CFGC GPIO21INTD [23..23] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO21INTD */ - GPIO_CFGC_GPIO21INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGC_GPIO21INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGC_GPIO21INTD_Enum; - -/* ============================================ GPIO CFGC GPIO21OUTCFG [21..22] ============================================ */ -typedef enum { /*!< GPIO_CFGC_GPIO21OUTCFG */ - GPIO_CFGC_GPIO21OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGC_GPIO21OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGC_GPIO21OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGC_GPIO21OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGC_GPIO21OUTCFG_Enum; - -/* ============================================ GPIO CFGC GPIO21INCFG [20..20] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO21INCFG */ - GPIO_CFGC_GPIO21INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGC_GPIO21INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGC_GPIO21INCFG_Enum; - -/* ============================================= GPIO CFGC GPIO20INTD [19..19] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO20INTD */ - GPIO_CFGC_GPIO20INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGC_GPIO20INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGC_GPIO20INTD_Enum; - -/* ============================================ GPIO CFGC GPIO20OUTCFG [17..18] ============================================ */ -typedef enum { /*!< GPIO_CFGC_GPIO20OUTCFG */ - GPIO_CFGC_GPIO20OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGC_GPIO20OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGC_GPIO20OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGC_GPIO20OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGC_GPIO20OUTCFG_Enum; - -/* ============================================ GPIO CFGC GPIO20INCFG [16..16] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO20INCFG */ - GPIO_CFGC_GPIO20INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGC_GPIO20INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGC_GPIO20INCFG_Enum; - -/* ============================================= GPIO CFGC GPIO19INTD [15..15] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO19INTD */ - GPIO_CFGC_GPIO19INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGC_GPIO19INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGC_GPIO19INTD_Enum; - -/* ============================================ GPIO CFGC GPIO19OUTCFG [13..14] ============================================ */ -typedef enum { /*!< GPIO_CFGC_GPIO19OUTCFG */ - GPIO_CFGC_GPIO19OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGC_GPIO19OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGC_GPIO19OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGC_GPIO19OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGC_GPIO19OUTCFG_Enum; - -/* ============================================ GPIO CFGC GPIO19INCFG [12..12] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO19INCFG */ - GPIO_CFGC_GPIO19INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGC_GPIO19INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGC_GPIO19INCFG_Enum; - -/* ============================================= GPIO CFGC GPIO18INTD [11..11] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO18INTD */ - GPIO_CFGC_GPIO18INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGC_GPIO18INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGC_GPIO18INTD_Enum; - -/* ============================================ GPIO CFGC GPIO18OUTCFG [9..10] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO18OUTCFG */ - GPIO_CFGC_GPIO18OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGC_GPIO18OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGC_GPIO18OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGC_GPIO18OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGC_GPIO18OUTCFG_Enum; - -/* ============================================= GPIO CFGC GPIO18INCFG [8..8] ============================================== */ -typedef enum { /*!< GPIO_CFGC_GPIO18INCFG */ - GPIO_CFGC_GPIO18INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGC_GPIO18INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGC_GPIO18INCFG_Enum; - -/* ============================================== GPIO CFGC GPIO17INTD [7..7] ============================================== */ -typedef enum { /*!< GPIO_CFGC_GPIO17INTD */ - GPIO_CFGC_GPIO17INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGC_GPIO17INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGC_GPIO17INTD_Enum; - -/* ============================================= GPIO CFGC GPIO17OUTCFG [5..6] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO17OUTCFG */ - GPIO_CFGC_GPIO17OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGC_GPIO17OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGC_GPIO17OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGC_GPIO17OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGC_GPIO17OUTCFG_Enum; - -/* ============================================= GPIO CFGC GPIO17INCFG [4..4] ============================================== */ -typedef enum { /*!< GPIO_CFGC_GPIO17INCFG */ - GPIO_CFGC_GPIO17INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGC_GPIO17INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGC_GPIO17INCFG_Enum; - -/* ============================================== GPIO CFGC GPIO16INTD [3..3] ============================================== */ -typedef enum { /*!< GPIO_CFGC_GPIO16INTD */ - GPIO_CFGC_GPIO16INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGC_GPIO16INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGC_GPIO16INTD_Enum; - -/* ============================================= GPIO CFGC GPIO16OUTCFG [1..2] ============================================= */ -typedef enum { /*!< GPIO_CFGC_GPIO16OUTCFG */ - GPIO_CFGC_GPIO16OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGC_GPIO16OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGC_GPIO16OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGC_GPIO16OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGC_GPIO16OUTCFG_Enum; - -/* ============================================= GPIO CFGC GPIO16INCFG [0..0] ============================================== */ -typedef enum { /*!< GPIO_CFGC_GPIO16INCFG */ - GPIO_CFGC_GPIO16INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGC_GPIO16INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGC_GPIO16INCFG_Enum; - -/* ========================================================= CFGD ========================================================== */ -/* ============================================= GPIO CFGD GPIO31INTD [31..31] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO31INTD */ - GPIO_CFGD_GPIO31INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGD_GPIO31INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGD_GPIO31INTD_Enum; - -/* ============================================ GPIO CFGD GPIO31OUTCFG [29..30] ============================================ */ -typedef enum { /*!< GPIO_CFGD_GPIO31OUTCFG */ - GPIO_CFGD_GPIO31OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGD_GPIO31OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGD_GPIO31OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGD_GPIO31OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGD_GPIO31OUTCFG_Enum; - -/* ============================================ GPIO CFGD GPIO31INCFG [28..28] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO31INCFG */ - GPIO_CFGD_GPIO31INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGD_GPIO31INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGD_GPIO31INCFG_Enum; - -/* ============================================= GPIO CFGD GPIO30INTD [27..27] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO30INTD */ - GPIO_CFGD_GPIO30INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGD_GPIO30INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGD_GPIO30INTD_Enum; - -/* ============================================ GPIO CFGD GPIO30OUTCFG [25..26] ============================================ */ -typedef enum { /*!< GPIO_CFGD_GPIO30OUTCFG */ - GPIO_CFGD_GPIO30OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGD_GPIO30OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGD_GPIO30OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGD_GPIO30OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGD_GPIO30OUTCFG_Enum; - -/* ============================================ GPIO CFGD GPIO30INCFG [24..24] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO30INCFG */ - GPIO_CFGD_GPIO30INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGD_GPIO30INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGD_GPIO30INCFG_Enum; - -/* ============================================= GPIO CFGD GPIO29INTD [23..23] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO29INTD */ - GPIO_CFGD_GPIO29INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGD_GPIO29INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGD_GPIO29INTD_Enum; - -/* ============================================ GPIO CFGD GPIO29OUTCFG [21..22] ============================================ */ -typedef enum { /*!< GPIO_CFGD_GPIO29OUTCFG */ - GPIO_CFGD_GPIO29OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGD_GPIO29OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGD_GPIO29OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGD_GPIO29OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGD_GPIO29OUTCFG_Enum; - -/* ============================================ GPIO CFGD GPIO29INCFG [20..20] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO29INCFG */ - GPIO_CFGD_GPIO29INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGD_GPIO29INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGD_GPIO29INCFG_Enum; - -/* ============================================= GPIO CFGD GPIO28INTD [19..19] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO28INTD */ - GPIO_CFGD_GPIO28INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGD_GPIO28INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGD_GPIO28INTD_Enum; - -/* ============================================ GPIO CFGD GPIO28OUTCFG [17..18] ============================================ */ -typedef enum { /*!< GPIO_CFGD_GPIO28OUTCFG */ - GPIO_CFGD_GPIO28OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGD_GPIO28OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGD_GPIO28OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGD_GPIO28OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGD_GPIO28OUTCFG_Enum; - -/* ============================================ GPIO CFGD GPIO28INCFG [16..16] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO28INCFG */ - GPIO_CFGD_GPIO28INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGD_GPIO28INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGD_GPIO28INCFG_Enum; - -/* ============================================= GPIO CFGD GPIO27INTD [15..15] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO27INTD */ - GPIO_CFGD_GPIO27INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGD_GPIO27INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGD_GPIO27INTD_Enum; - -/* ============================================ GPIO CFGD GPIO27OUTCFG [13..14] ============================================ */ -typedef enum { /*!< GPIO_CFGD_GPIO27OUTCFG */ - GPIO_CFGD_GPIO27OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGD_GPIO27OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGD_GPIO27OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGD_GPIO27OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGD_GPIO27OUTCFG_Enum; - -/* ============================================ GPIO CFGD GPIO27INCFG [12..12] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO27INCFG */ - GPIO_CFGD_GPIO27INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGD_GPIO27INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGD_GPIO27INCFG_Enum; - -/* ============================================= GPIO CFGD GPIO26INTD [11..11] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO26INTD */ - GPIO_CFGD_GPIO26INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGD_GPIO26INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGD_GPIO26INTD_Enum; - -/* ============================================ GPIO CFGD GPIO26OUTCFG [9..10] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO26OUTCFG */ - GPIO_CFGD_GPIO26OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGD_GPIO26OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGD_GPIO26OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGD_GPIO26OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGD_GPIO26OUTCFG_Enum; - -/* ============================================= GPIO CFGD GPIO26INCFG [8..8] ============================================== */ -typedef enum { /*!< GPIO_CFGD_GPIO26INCFG */ - GPIO_CFGD_GPIO26INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGD_GPIO26INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGD_GPIO26INCFG_Enum; - -/* ============================================== GPIO CFGD GPIO25INTD [7..7] ============================================== */ -typedef enum { /*!< GPIO_CFGD_GPIO25INTD */ - GPIO_CFGD_GPIO25INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGD_GPIO25INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGD_GPIO25INTD_Enum; - -/* ============================================= GPIO CFGD GPIO25OUTCFG [5..6] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO25OUTCFG */ - GPIO_CFGD_GPIO25OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGD_GPIO25OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGD_GPIO25OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGD_GPIO25OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGD_GPIO25OUTCFG_Enum; - -/* ============================================= GPIO CFGD GPIO25INCFG [4..4] ============================================== */ -typedef enum { /*!< GPIO_CFGD_GPIO25INCFG */ - GPIO_CFGD_GPIO25INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGD_GPIO25INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGD_GPIO25INCFG_Enum; - -/* ============================================== GPIO CFGD GPIO24INTD [3..3] ============================================== */ -typedef enum { /*!< GPIO_CFGD_GPIO24INTD */ - GPIO_CFGD_GPIO24INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGD_GPIO24INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGD_GPIO24INTD_Enum; - -/* ============================================= GPIO CFGD GPIO24OUTCFG [1..2] ============================================= */ -typedef enum { /*!< GPIO_CFGD_GPIO24OUTCFG */ - GPIO_CFGD_GPIO24OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGD_GPIO24OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGD_GPIO24OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGD_GPIO24OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGD_GPIO24OUTCFG_Enum; - -/* ============================================= GPIO CFGD GPIO24INCFG [0..0] ============================================== */ -typedef enum { /*!< GPIO_CFGD_GPIO24INCFG */ - GPIO_CFGD_GPIO24INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGD_GPIO24INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGD_GPIO24INCFG_Enum; - -/* ========================================================= CFGE ========================================================== */ -/* ============================================= GPIO CFGE GPIO39INTD [31..31] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO39INTD */ - GPIO_CFGE_GPIO39INTD_INTDIS = 0, /*!< INTDIS : INCFG = 1 - No interrupt on GPIO transition value. */ - GPIO_CFGE_GPIO39INTD_INTBOTH = 1, /*!< INTBOTH : INCFG = 1 - Interrupt on either low to high or high - to low GPIO transition value. */ -} GPIO_CFGE_GPIO39INTD_Enum; - -/* ============================================ GPIO CFGE GPIO39OUTCFG [29..30] ============================================ */ -typedef enum { /*!< GPIO_CFGE_GPIO39OUTCFG */ - GPIO_CFGE_GPIO39OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGE_GPIO39OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGE_GPIO39OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGE_GPIO39OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGE_GPIO39OUTCFG_Enum; - -/* ============================================ GPIO CFGE GPIO39INCFG [28..28] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO39INCFG */ - GPIO_CFGE_GPIO39INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGE_GPIO39INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGE_GPIO39INCFG_Enum; - -/* ============================================= GPIO CFGE GPIO38INTD [27..27] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO38INTD */ - GPIO_CFGE_GPIO38INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGE_GPIO38INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGE_GPIO38INTD_Enum; - -/* ============================================ GPIO CFGE GPIO38OUTCFG [25..26] ============================================ */ -typedef enum { /*!< GPIO_CFGE_GPIO38OUTCFG */ - GPIO_CFGE_GPIO38OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGE_GPIO38OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGE_GPIO38OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGE_GPIO38OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGE_GPIO38OUTCFG_Enum; - -/* ============================================ GPIO CFGE GPIO38INCFG [24..24] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO38INCFG */ - GPIO_CFGE_GPIO38INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGE_GPIO38INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGE_GPIO38INCFG_Enum; - -/* ============================================= GPIO CFGE GPIO37INTD [23..23] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO37INTD */ - GPIO_CFGE_GPIO37INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGE_GPIO37INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGE_GPIO37INTD_Enum; - -/* ============================================ GPIO CFGE GPIO37OUTCFG [21..22] ============================================ */ -typedef enum { /*!< GPIO_CFGE_GPIO37OUTCFG */ - GPIO_CFGE_GPIO37OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGE_GPIO37OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGE_GPIO37OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGE_GPIO37OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGE_GPIO37OUTCFG_Enum; - -/* ============================================ GPIO CFGE GPIO37INCFG [20..20] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO37INCFG */ - GPIO_CFGE_GPIO37INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGE_GPIO37INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGE_GPIO37INCFG_Enum; - -/* ============================================= GPIO CFGE GPIO36INTD [19..19] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO36INTD */ - GPIO_CFGE_GPIO36INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGE_GPIO36INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGE_GPIO36INTD_Enum; - -/* ============================================ GPIO CFGE GPIO36OUTCFG [17..18] ============================================ */ -typedef enum { /*!< GPIO_CFGE_GPIO36OUTCFG */ - GPIO_CFGE_GPIO36OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGE_GPIO36OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGE_GPIO36OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGE_GPIO36OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGE_GPIO36OUTCFG_Enum; - -/* ============================================ GPIO CFGE GPIO36INCFG [16..16] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO36INCFG */ - GPIO_CFGE_GPIO36INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGE_GPIO36INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGE_GPIO36INCFG_Enum; - -/* ============================================= GPIO CFGE GPIO35INTD [15..15] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO35INTD */ - GPIO_CFGE_GPIO35INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGE_GPIO35INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGE_GPIO35INTD_Enum; - -/* ============================================ GPIO CFGE GPIO35OUTCFG [13..14] ============================================ */ -typedef enum { /*!< GPIO_CFGE_GPIO35OUTCFG */ - GPIO_CFGE_GPIO35OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGE_GPIO35OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGE_GPIO35OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGE_GPIO35OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGE_GPIO35OUTCFG_Enum; - -/* ============================================ GPIO CFGE GPIO35INCFG [12..12] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO35INCFG */ - GPIO_CFGE_GPIO35INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGE_GPIO35INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGE_GPIO35INCFG_Enum; - -/* ============================================= GPIO CFGE GPIO34INTD [11..11] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO34INTD */ - GPIO_CFGE_GPIO34INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGE_GPIO34INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGE_GPIO34INTD_Enum; - -/* ============================================ GPIO CFGE GPIO34OUTCFG [9..10] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO34OUTCFG */ - GPIO_CFGE_GPIO34OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGE_GPIO34OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGE_GPIO34OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGE_GPIO34OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGE_GPIO34OUTCFG_Enum; - -/* ============================================= GPIO CFGE GPIO34INCFG [8..8] ============================================== */ -typedef enum { /*!< GPIO_CFGE_GPIO34INCFG */ - GPIO_CFGE_GPIO34INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGE_GPIO34INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGE_GPIO34INCFG_Enum; - -/* ============================================== GPIO CFGE GPIO33INTD [7..7] ============================================== */ -typedef enum { /*!< GPIO_CFGE_GPIO33INTD */ - GPIO_CFGE_GPIO33INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGE_GPIO33INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGE_GPIO33INTD_Enum; - -/* ============================================= GPIO CFGE GPIO33OUTCFG [5..6] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO33OUTCFG */ - GPIO_CFGE_GPIO33OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGE_GPIO33OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGE_GPIO33OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGE_GPIO33OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGE_GPIO33OUTCFG_Enum; - -/* ============================================= GPIO CFGE GPIO33INCFG [4..4] ============================================== */ -typedef enum { /*!< GPIO_CFGE_GPIO33INCFG */ - GPIO_CFGE_GPIO33INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGE_GPIO33INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGE_GPIO33INCFG_Enum; - -/* ============================================== GPIO CFGE GPIO32INTD [3..3] ============================================== */ -typedef enum { /*!< GPIO_CFGE_GPIO32INTD */ - GPIO_CFGE_GPIO32INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGE_GPIO32INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGE_GPIO32INTD_Enum; - -/* ============================================= GPIO CFGE GPIO32OUTCFG [1..2] ============================================= */ -typedef enum { /*!< GPIO_CFGE_GPIO32OUTCFG */ - GPIO_CFGE_GPIO32OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGE_GPIO32OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGE_GPIO32OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGE_GPIO32OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGE_GPIO32OUTCFG_Enum; - -/* ============================================= GPIO CFGE GPIO32INCFG [0..0] ============================================== */ -typedef enum { /*!< GPIO_CFGE_GPIO32INCFG */ - GPIO_CFGE_GPIO32INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGE_GPIO32INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGE_GPIO32INCFG_Enum; - -/* ========================================================= CFGF ========================================================== */ -/* ============================================= GPIO CFGF GPIO47INTD [31..31] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO47INTD */ - GPIO_CFGF_GPIO47INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGF_GPIO47INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGF_GPIO47INTD_Enum; - -/* ============================================ GPIO CFGF GPIO47OUTCFG [29..30] ============================================ */ -typedef enum { /*!< GPIO_CFGF_GPIO47OUTCFG */ - GPIO_CFGF_GPIO47OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGF_GPIO47OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGF_GPIO47OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGF_GPIO47OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGF_GPIO47OUTCFG_Enum; - -/* ============================================ GPIO CFGF GPIO47INCFG [28..28] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO47INCFG */ - GPIO_CFGF_GPIO47INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGF_GPIO47INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGF_GPIO47INCFG_Enum; - -/* ============================================= GPIO CFGF GPIO46INTD [27..27] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO46INTD */ - GPIO_CFGF_GPIO46INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGF_GPIO46INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGF_GPIO46INTD_Enum; - -/* ============================================ GPIO CFGF GPIO46OUTCFG [25..26] ============================================ */ -typedef enum { /*!< GPIO_CFGF_GPIO46OUTCFG */ - GPIO_CFGF_GPIO46OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGF_GPIO46OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGF_GPIO46OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGF_GPIO46OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGF_GPIO46OUTCFG_Enum; - -/* ============================================ GPIO CFGF GPIO46INCFG [24..24] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO46INCFG */ - GPIO_CFGF_GPIO46INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGF_GPIO46INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGF_GPIO46INCFG_Enum; - -/* ============================================= GPIO CFGF GPIO45INTD [23..23] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO45INTD */ - GPIO_CFGF_GPIO45INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGF_GPIO45INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGF_GPIO45INTD_Enum; - -/* ============================================ GPIO CFGF GPIO45OUTCFG [21..22] ============================================ */ -typedef enum { /*!< GPIO_CFGF_GPIO45OUTCFG */ - GPIO_CFGF_GPIO45OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGF_GPIO45OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGF_GPIO45OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGF_GPIO45OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGF_GPIO45OUTCFG_Enum; - -/* ============================================ GPIO CFGF GPIO45INCFG [20..20] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO45INCFG */ - GPIO_CFGF_GPIO45INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGF_GPIO45INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGF_GPIO45INCFG_Enum; - -/* ============================================= GPIO CFGF GPIO44INTD [19..19] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO44INTD */ - GPIO_CFGF_GPIO44INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGF_GPIO44INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGF_GPIO44INTD_Enum; - -/* ============================================ GPIO CFGF GPIO44OUTCFG [17..18] ============================================ */ -typedef enum { /*!< GPIO_CFGF_GPIO44OUTCFG */ - GPIO_CFGF_GPIO44OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGF_GPIO44OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGF_GPIO44OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGF_GPIO44OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGF_GPIO44OUTCFG_Enum; - -/* ============================================ GPIO CFGF GPIO44INCFG [16..16] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO44INCFG */ - GPIO_CFGF_GPIO44INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGF_GPIO44INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGF_GPIO44INCFG_Enum; - -/* ============================================= GPIO CFGF GPIO43INTD [15..15] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO43INTD */ - GPIO_CFGF_GPIO43INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGF_GPIO43INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGF_GPIO43INTD_Enum; - -/* ============================================ GPIO CFGF GPIO43OUTCFG [13..14] ============================================ */ -typedef enum { /*!< GPIO_CFGF_GPIO43OUTCFG */ - GPIO_CFGF_GPIO43OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGF_GPIO43OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGF_GPIO43OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGF_GPIO43OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGF_GPIO43OUTCFG_Enum; - -/* ============================================ GPIO CFGF GPIO43INCFG [12..12] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO43INCFG */ - GPIO_CFGF_GPIO43INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGF_GPIO43INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGF_GPIO43INCFG_Enum; - -/* ============================================= GPIO CFGF GPIO42INTD [11..11] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO42INTD */ - GPIO_CFGF_GPIO42INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGF_GPIO42INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGF_GPIO42INTD_Enum; - -/* ============================================ GPIO CFGF GPIO42OUTCFG [9..10] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO42OUTCFG */ - GPIO_CFGF_GPIO42OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGF_GPIO42OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGF_GPIO42OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGF_GPIO42OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGF_GPIO42OUTCFG_Enum; - -/* ============================================= GPIO CFGF GPIO42INCFG [8..8] ============================================== */ -typedef enum { /*!< GPIO_CFGF_GPIO42INCFG */ - GPIO_CFGF_GPIO42INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGF_GPIO42INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGF_GPIO42INCFG_Enum; - -/* ============================================== GPIO CFGF GPIO41INTD [7..7] ============================================== */ -typedef enum { /*!< GPIO_CFGF_GPIO41INTD */ - GPIO_CFGF_GPIO41INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x0 - nCE polarity active low value. */ - GPIO_CFGF_GPIO41INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x0 - nCE polarity active high value. */ -} GPIO_CFGF_GPIO41INTD_Enum; - -/* ============================================= GPIO CFGF GPIO41OUTCFG [5..6] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO41OUTCFG */ - GPIO_CFGF_GPIO41OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGF_GPIO41OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGF_GPIO41OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGF_GPIO41OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGF_GPIO41OUTCFG_Enum; - -/* ============================================= GPIO CFGF GPIO41INCFG [4..4] ============================================== */ -typedef enum { /*!< GPIO_CFGF_GPIO41INCFG */ - GPIO_CFGF_GPIO41INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGF_GPIO41INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGF_GPIO41INCFG_Enum; - -/* ============================================== GPIO CFGF GPIO40INTD [3..3] ============================================== */ -typedef enum { /*!< GPIO_CFGF_GPIO40INTD */ - GPIO_CFGF_GPIO40INTD_INTDIS = 0, /*!< INTDIS : INCFG = 1 - No interrupt on GPIO transition value. */ - GPIO_CFGF_GPIO40INTD_INTBOTH = 1, /*!< INTBOTH : INCFG = 1 - Interrupt on either low to high or high - to low GPIO transition value. */ -} GPIO_CFGF_GPIO40INTD_Enum; - -/* ============================================= GPIO CFGF GPIO40OUTCFG [1..2] ============================================= */ -typedef enum { /*!< GPIO_CFGF_GPIO40OUTCFG */ - GPIO_CFGF_GPIO40OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGF_GPIO40OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGF_GPIO40OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGF_GPIO40OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGF_GPIO40OUTCFG_Enum; - -/* ============================================= GPIO CFGF GPIO40INCFG [0..0] ============================================== */ -typedef enum { /*!< GPIO_CFGF_GPIO40INCFG */ - GPIO_CFGF_GPIO40INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGF_GPIO40INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGF_GPIO40INCFG_Enum; - -/* ========================================================= CFGG ========================================================== */ -/* ============================================== GPIO CFGG GPIO49INTD [7..7] ============================================== */ -typedef enum { /*!< GPIO_CFGG_GPIO49INTD */ - GPIO_CFGG_GPIO49INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGG_GPIO49INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGG_GPIO49INTD_Enum; - -/* ============================================= GPIO CFGG GPIO49OUTCFG [5..6] ============================================= */ -typedef enum { /*!< GPIO_CFGG_GPIO49OUTCFG */ - GPIO_CFGG_GPIO49OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGG_GPIO49OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGG_GPIO49OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGG_GPIO49OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGG_GPIO49OUTCFG_Enum; - -/* ============================================= GPIO CFGG GPIO49INCFG [4..4] ============================================== */ -typedef enum { /*!< GPIO_CFGG_GPIO49INCFG */ - GPIO_CFGG_GPIO49INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGG_GPIO49INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGG_GPIO49INCFG_Enum; - -/* ============================================== GPIO CFGG GPIO48INTD [3..3] ============================================== */ -typedef enum { /*!< GPIO_CFGG_GPIO48INTD */ - GPIO_CFGG_GPIO48INTD_nCELOW = 0, /*!< nCELOW : FNCSEL = 0x1 - nCE polarity active low value. */ - GPIO_CFGG_GPIO48INTD_nCEHIGH = 1, /*!< nCEHIGH : FNCSEL = 0x1 - nCE polarity active high value. */ -} GPIO_CFGG_GPIO48INTD_Enum; - -/* ============================================= GPIO CFGG GPIO48OUTCFG [1..2] ============================================= */ -typedef enum { /*!< GPIO_CFGG_GPIO48OUTCFG */ - GPIO_CFGG_GPIO48OUTCFG_DIS = 0, /*!< DIS : FNCSEL = 0x3 - Output disabled value. */ - GPIO_CFGG_GPIO48OUTCFG_PUSHPULL = 1, /*!< PUSHPULL : FNCSEL = 0x3 - Output is push-pull value. */ - GPIO_CFGG_GPIO48OUTCFG_OD = 2, /*!< OD : FNCSEL = 0x3 - Output is open drain value. */ - GPIO_CFGG_GPIO48OUTCFG_TS = 3, /*!< TS : FNCSEL = 0x3 - Output is tri-state value. */ -} GPIO_CFGG_GPIO48OUTCFG_Enum; - -/* ============================================= GPIO CFGG GPIO48INCFG [0..0] ============================================== */ -typedef enum { /*!< GPIO_CFGG_GPIO48INCFG */ - GPIO_CFGG_GPIO48INCFG_READ = 0, /*!< READ : Read the GPIO pin data value. */ - GPIO_CFGG_GPIO48INCFG_RDZERO = 1, /*!< RDZERO : INTD = 0 - Readback will always be zero value. */ -} GPIO_CFGG_GPIO48INCFG_Enum; - -/* ======================================================== PADKEY ========================================================= */ -/* ============================================== GPIO PADKEY PADKEY [0..31] =============================================== */ -typedef enum { /*!< GPIO_PADKEY_PADKEY */ - GPIO_PADKEY_PADKEY_Key = 115, /*!< Key : Key value. */ -} GPIO_PADKEY_PADKEY_Enum; - -/* ========================================================== RDA ========================================================== */ -/* ========================================================== RDB ========================================================== */ -/* ========================================================== WTA ========================================================== */ -/* ========================================================== WTB ========================================================== */ -/* ========================================================= WTSA ========================================================== */ -/* ========================================================= WTSB ========================================================== */ -/* ========================================================= WTCA ========================================================== */ -/* ========================================================= WTCB ========================================================== */ -/* ========================================================== ENA ========================================================== */ -/* ========================================================== ENB ========================================================== */ -/* ========================================================= ENSA ========================================================== */ -/* ========================================================= ENSB ========================================================== */ -/* ========================================================= ENCA ========================================================== */ -/* ========================================================= ENCB ========================================================== */ -/* ======================================================== STMRCAP ======================================================== */ -/* ============================================= GPIO STMRCAP STPOL3 [30..30] ============================================== */ -typedef enum { /*!< GPIO_STMRCAP_STPOL3 */ - GPIO_STMRCAP_STPOL3_CAPLH = 0, /*!< CAPLH : Capture on low to high GPIO transition value. */ - GPIO_STMRCAP_STPOL3_CAPHL = 1, /*!< CAPHL : Capture on high to low GPIO transition value. */ -} GPIO_STMRCAP_STPOL3_Enum; - -/* ============================================= GPIO STMRCAP STPOL2 [22..22] ============================================== */ -typedef enum { /*!< GPIO_STMRCAP_STPOL2 */ - GPIO_STMRCAP_STPOL2_CAPLH = 0, /*!< CAPLH : Capture on low to high GPIO transition value. */ - GPIO_STMRCAP_STPOL2_CAPHL = 1, /*!< CAPHL : Capture on high to low GPIO transition value. */ -} GPIO_STMRCAP_STPOL2_Enum; - -/* ============================================= GPIO STMRCAP STPOL1 [14..14] ============================================== */ -typedef enum { /*!< GPIO_STMRCAP_STPOL1 */ - GPIO_STMRCAP_STPOL1_CAPLH = 0, /*!< CAPLH : Capture on low to high GPIO transition value. */ - GPIO_STMRCAP_STPOL1_CAPHL = 1, /*!< CAPHL : Capture on high to low GPIO transition value. */ -} GPIO_STMRCAP_STPOL1_Enum; - -/* ============================================== GPIO STMRCAP STPOL0 [6..6] =============================================== */ -typedef enum { /*!< GPIO_STMRCAP_STPOL0 */ - GPIO_STMRCAP_STPOL0_CAPLH = 0, /*!< CAPLH : Capture on low to high GPIO transition value. */ - GPIO_STMRCAP_STPOL0_CAPHL = 1, /*!< CAPHL : Capture on high to low GPIO transition value. */ -} GPIO_STMRCAP_STPOL0_Enum; - -/* ======================================================== IOM0IRQ ======================================================== */ -/* ======================================================== IOM1IRQ ======================================================== */ -/* ======================================================== IOM2IRQ ======================================================== */ -/* ======================================================== IOM3IRQ ======================================================== */ -/* ======================================================== IOM4IRQ ======================================================== */ -/* ======================================================== IOM5IRQ ======================================================== */ -/* ======================================================= BLEIFIRQ ======================================================== */ -/* ======================================================== GPIOOBS ======================================================== */ -/* ====================================================== ALTPADCFGA ======================================================= */ -/* =========================================== GPIO ALTPADCFGA PAD3_SR [28..28] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGA_PAD3_SR */ - GPIO_ALTPADCFGA_PAD3_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGA_PAD3_SR_Enum; - -/* =========================================== GPIO ALTPADCFGA PAD2_SR [20..20] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGA_PAD2_SR */ - GPIO_ALTPADCFGA_PAD2_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGA_PAD2_SR_Enum; - -/* =========================================== GPIO ALTPADCFGA PAD1_SR [12..12] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGA_PAD1_SR */ - GPIO_ALTPADCFGA_PAD1_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGA_PAD1_SR_Enum; - -/* ============================================ GPIO ALTPADCFGA PAD0_SR [4..4] ============================================= */ -typedef enum { /*!< GPIO_ALTPADCFGA_PAD0_SR */ - GPIO_ALTPADCFGA_PAD0_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGA_PAD0_SR_Enum; - -/* ====================================================== ALTPADCFGB ======================================================= */ -/* =========================================== GPIO ALTPADCFGB PAD7_SR [28..28] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGB_PAD7_SR */ - GPIO_ALTPADCFGB_PAD7_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGB_PAD7_SR_Enum; - -/* =========================================== GPIO ALTPADCFGB PAD6_SR [20..20] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGB_PAD6_SR */ - GPIO_ALTPADCFGB_PAD6_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGB_PAD6_SR_Enum; - -/* =========================================== GPIO ALTPADCFGB PAD5_SR [12..12] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGB_PAD5_SR */ - GPIO_ALTPADCFGB_PAD5_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGB_PAD5_SR_Enum; - -/* ============================================ GPIO ALTPADCFGB PAD4_SR [4..4] ============================================= */ -typedef enum { /*!< GPIO_ALTPADCFGB_PAD4_SR */ - GPIO_ALTPADCFGB_PAD4_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGB_PAD4_SR_Enum; - -/* ====================================================== ALTPADCFGC ======================================================= */ -/* =========================================== GPIO ALTPADCFGC PAD11_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGC_PAD11_SR */ - GPIO_ALTPADCFGC_PAD11_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGC_PAD11_SR_Enum; - -/* =========================================== GPIO ALTPADCFGC PAD10_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGC_PAD10_SR */ - GPIO_ALTPADCFGC_PAD10_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGC_PAD10_SR_Enum; - -/* =========================================== GPIO ALTPADCFGC PAD9_SR [12..12] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGC_PAD9_SR */ - GPIO_ALTPADCFGC_PAD9_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGC_PAD9_SR_Enum; - -/* ============================================ GPIO ALTPADCFGC PAD8_SR [4..4] ============================================= */ -typedef enum { /*!< GPIO_ALTPADCFGC_PAD8_SR */ - GPIO_ALTPADCFGC_PAD8_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGC_PAD8_SR_Enum; - -/* ====================================================== ALTPADCFGD ======================================================= */ -/* =========================================== GPIO ALTPADCFGD PAD15_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGD_PAD15_SR */ - GPIO_ALTPADCFGD_PAD15_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGD_PAD15_SR_Enum; - -/* =========================================== GPIO ALTPADCFGD PAD14_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGD_PAD14_SR */ - GPIO_ALTPADCFGD_PAD14_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGD_PAD14_SR_Enum; - -/* =========================================== GPIO ALTPADCFGD PAD13_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGD_PAD13_SR */ - GPIO_ALTPADCFGD_PAD13_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGD_PAD13_SR_Enum; - -/* ============================================ GPIO ALTPADCFGD PAD12_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGD_PAD12_SR */ - GPIO_ALTPADCFGD_PAD12_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGD_PAD12_SR_Enum; - -/* ====================================================== ALTPADCFGE ======================================================= */ -/* =========================================== GPIO ALTPADCFGE PAD19_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGE_PAD19_SR */ - GPIO_ALTPADCFGE_PAD19_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGE_PAD19_SR_Enum; - -/* =========================================== GPIO ALTPADCFGE PAD18_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGE_PAD18_SR */ - GPIO_ALTPADCFGE_PAD18_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGE_PAD18_SR_Enum; - -/* =========================================== GPIO ALTPADCFGE PAD17_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGE_PAD17_SR */ - GPIO_ALTPADCFGE_PAD17_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGE_PAD17_SR_Enum; - -/* ============================================ GPIO ALTPADCFGE PAD16_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGE_PAD16_SR */ - GPIO_ALTPADCFGE_PAD16_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGE_PAD16_SR_Enum; - -/* ====================================================== ALTPADCFGF ======================================================= */ -/* =========================================== GPIO ALTPADCFGF PAD23_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGF_PAD23_SR */ - GPIO_ALTPADCFGF_PAD23_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGF_PAD23_SR_Enum; - -/* =========================================== GPIO ALTPADCFGF PAD22_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGF_PAD22_SR */ - GPIO_ALTPADCFGF_PAD22_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGF_PAD22_SR_Enum; - -/* =========================================== GPIO ALTPADCFGF PAD21_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGF_PAD21_SR */ - GPIO_ALTPADCFGF_PAD21_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGF_PAD21_SR_Enum; - -/* ============================================ GPIO ALTPADCFGF PAD20_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGF_PAD20_SR */ - GPIO_ALTPADCFGF_PAD20_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGF_PAD20_SR_Enum; - -/* ====================================================== ALTPADCFGG ======================================================= */ -/* =========================================== GPIO ALTPADCFGG PAD27_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGG_PAD27_SR */ - GPIO_ALTPADCFGG_PAD27_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGG_PAD27_SR_Enum; - -/* =========================================== GPIO ALTPADCFGG PAD26_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGG_PAD26_SR */ - GPIO_ALTPADCFGG_PAD26_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGG_PAD26_SR_Enum; - -/* =========================================== GPIO ALTPADCFGG PAD25_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGG_PAD25_SR */ - GPIO_ALTPADCFGG_PAD25_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGG_PAD25_SR_Enum; - -/* ============================================ GPIO ALTPADCFGG PAD24_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGG_PAD24_SR */ - GPIO_ALTPADCFGG_PAD24_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGG_PAD24_SR_Enum; - -/* ====================================================== ALTPADCFGH ======================================================= */ -/* =========================================== GPIO ALTPADCFGH PAD31_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGH_PAD31_SR */ - GPIO_ALTPADCFGH_PAD31_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGH_PAD31_SR_Enum; - -/* =========================================== GPIO ALTPADCFGH PAD30_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGH_PAD30_SR */ - GPIO_ALTPADCFGH_PAD30_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGH_PAD30_SR_Enum; - -/* =========================================== GPIO ALTPADCFGH PAD29_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGH_PAD29_SR */ - GPIO_ALTPADCFGH_PAD29_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGH_PAD29_SR_Enum; - -/* ============================================ GPIO ALTPADCFGH PAD28_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGH_PAD28_SR */ - GPIO_ALTPADCFGH_PAD28_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGH_PAD28_SR_Enum; - -/* ====================================================== ALTPADCFGI ======================================================= */ -/* =========================================== GPIO ALTPADCFGI PAD35_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGI_PAD35_SR */ - GPIO_ALTPADCFGI_PAD35_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGI_PAD35_SR_Enum; - -/* =========================================== GPIO ALTPADCFGI PAD34_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGI_PAD34_SR */ - GPIO_ALTPADCFGI_PAD34_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGI_PAD34_SR_Enum; - -/* =========================================== GPIO ALTPADCFGI PAD33_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGI_PAD33_SR */ - GPIO_ALTPADCFGI_PAD33_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGI_PAD33_SR_Enum; - -/* ============================================ GPIO ALTPADCFGI PAD32_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGI_PAD32_SR */ - GPIO_ALTPADCFGI_PAD32_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGI_PAD32_SR_Enum; - -/* ====================================================== ALTPADCFGJ ======================================================= */ -/* =========================================== GPIO ALTPADCFGJ PAD39_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGJ_PAD39_SR */ - GPIO_ALTPADCFGJ_PAD39_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGJ_PAD39_SR_Enum; - -/* =========================================== GPIO ALTPADCFGJ PAD38_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGJ_PAD38_SR */ - GPIO_ALTPADCFGJ_PAD38_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGJ_PAD38_SR_Enum; - -/* =========================================== GPIO ALTPADCFGJ PAD37_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGJ_PAD37_SR */ - GPIO_ALTPADCFGJ_PAD37_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGJ_PAD37_SR_Enum; - -/* ============================================ GPIO ALTPADCFGJ PAD36_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGJ_PAD36_SR */ - GPIO_ALTPADCFGJ_PAD36_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGJ_PAD36_SR_Enum; - -/* ====================================================== ALTPADCFGK ======================================================= */ -/* =========================================== GPIO ALTPADCFGK PAD43_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGK_PAD43_SR */ - GPIO_ALTPADCFGK_PAD43_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGK_PAD43_SR_Enum; - -/* =========================================== GPIO ALTPADCFGK PAD42_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGK_PAD42_SR */ - GPIO_ALTPADCFGK_PAD42_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGK_PAD42_SR_Enum; - -/* =========================================== GPIO ALTPADCFGK PAD41_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGK_PAD41_SR */ - GPIO_ALTPADCFGK_PAD41_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGK_PAD41_SR_Enum; - -/* ============================================ GPIO ALTPADCFGK PAD40_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGK_PAD40_SR */ - GPIO_ALTPADCFGK_PAD40_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGK_PAD40_SR_Enum; - -/* ====================================================== ALTPADCFGL ======================================================= */ -/* =========================================== GPIO ALTPADCFGL PAD47_SR [28..28] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGL_PAD47_SR */ - GPIO_ALTPADCFGL_PAD47_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGL_PAD47_SR_Enum; - -/* =========================================== GPIO ALTPADCFGL PAD46_SR [20..20] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGL_PAD46_SR */ - GPIO_ALTPADCFGL_PAD46_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGL_PAD46_SR_Enum; - -/* =========================================== GPIO ALTPADCFGL PAD45_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGL_PAD45_SR */ - GPIO_ALTPADCFGL_PAD45_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGL_PAD45_SR_Enum; - -/* ============================================ GPIO ALTPADCFGL PAD44_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGL_PAD44_SR */ - GPIO_ALTPADCFGL_PAD44_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGL_PAD44_SR_Enum; - -/* ====================================================== ALTPADCFGM ======================================================= */ -/* =========================================== GPIO ALTPADCFGM PAD49_SR [12..12] =========================================== */ -typedef enum { /*!< GPIO_ALTPADCFGM_PAD49_SR */ - GPIO_ALTPADCFGM_PAD49_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGM_PAD49_SR_Enum; - -/* ============================================ GPIO ALTPADCFGM PAD48_SR [4..4] ============================================ */ -typedef enum { /*!< GPIO_ALTPADCFGM_PAD48_SR */ - GPIO_ALTPADCFGM_PAD48_SR_SR_EN = 1, /*!< SR_EN : Enables Slew rate control on pad value. */ -} GPIO_ALTPADCFGM_PAD48_SR_Enum; - -/* ========================================================= SCDET ========================================================= */ -/* ======================================================== CTENCFG ======================================================== */ -/* ============================================== GPIO CTENCFG EN31 [31..31] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN31 */ - GPIO_CTENCFG_EN31_DIS = 1, /*!< DIS : Disable CT31 for output value. */ - GPIO_CTENCFG_EN31_EN = 0, /*!< EN : Enable CT31 for output value. */ -} GPIO_CTENCFG_EN31_Enum; - -/* ============================================== GPIO CTENCFG EN30 [30..30] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN30 */ - GPIO_CTENCFG_EN30_DIS = 1, /*!< DIS : Disable CT30 for output value. */ - GPIO_CTENCFG_EN30_EN = 0, /*!< EN : Enable CT30 for output value. */ -} GPIO_CTENCFG_EN30_Enum; - -/* ============================================== GPIO CTENCFG EN29 [29..29] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN29 */ - GPIO_CTENCFG_EN29_DIS = 1, /*!< DIS : Disable CT29 for output value. */ - GPIO_CTENCFG_EN29_EN = 0, /*!< EN : Enable CT29 for output value. */ -} GPIO_CTENCFG_EN29_Enum; - -/* ============================================== GPIO CTENCFG EN28 [28..28] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN28 */ - GPIO_CTENCFG_EN28_DIS = 1, /*!< DIS : Disable CT28 for output value. */ - GPIO_CTENCFG_EN28_EN = 0, /*!< EN : Enable CT28 for output value. */ -} GPIO_CTENCFG_EN28_Enum; - -/* ============================================== GPIO CTENCFG EN27 [27..27] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN27 */ - GPIO_CTENCFG_EN27_DIS = 1, /*!< DIS : Disable CT27 for output value. */ - GPIO_CTENCFG_EN27_EN = 0, /*!< EN : Enable CT27 for output value. */ -} GPIO_CTENCFG_EN27_Enum; - -/* ============================================== GPIO CTENCFG EN26 [26..26] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN26 */ - GPIO_CTENCFG_EN26_DIS = 1, /*!< DIS : Disable CT26 for output value. */ - GPIO_CTENCFG_EN26_EN = 0, /*!< EN : Enable CT26 for output value. */ -} GPIO_CTENCFG_EN26_Enum; - -/* ============================================== GPIO CTENCFG EN25 [25..25] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN25 */ - GPIO_CTENCFG_EN25_DIS = 1, /*!< DIS : Disable CT25 for output value. */ - GPIO_CTENCFG_EN25_EN = 0, /*!< EN : Enable CT25 for output value. */ -} GPIO_CTENCFG_EN25_Enum; - -/* ============================================== GPIO CTENCFG EN24 [24..24] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN24 */ - GPIO_CTENCFG_EN24_DIS = 1, /*!< DIS : Disable CT24 for output value. */ - GPIO_CTENCFG_EN24_EN = 0, /*!< EN : Enable CT24 for output value. */ -} GPIO_CTENCFG_EN24_Enum; - -/* ============================================== GPIO CTENCFG EN23 [23..23] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN23 */ - GPIO_CTENCFG_EN23_DIS = 1, /*!< DIS : Disable CT23 for output value. */ - GPIO_CTENCFG_EN23_EN = 0, /*!< EN : Enable CT23 for output value. */ -} GPIO_CTENCFG_EN23_Enum; - -/* ============================================== GPIO CTENCFG EN22 [22..22] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN22 */ - GPIO_CTENCFG_EN22_DIS = 1, /*!< DIS : Disable CT22 for output value. */ - GPIO_CTENCFG_EN22_EN = 0, /*!< EN : Enable CT22 for output value. */ -} GPIO_CTENCFG_EN22_Enum; - -/* ============================================== GPIO CTENCFG EN21 [21..21] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN21 */ - GPIO_CTENCFG_EN21_DIS = 1, /*!< DIS : Disable CT21 for output value. */ - GPIO_CTENCFG_EN21_EN = 0, /*!< EN : Enable CT21 for output value. */ -} GPIO_CTENCFG_EN21_Enum; - -/* ============================================== GPIO CTENCFG EN20 [20..20] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN20 */ - GPIO_CTENCFG_EN20_DIS = 1, /*!< DIS : Disable CT20 for output value. */ - GPIO_CTENCFG_EN20_EN = 0, /*!< EN : Enable CT20 for output value. */ -} GPIO_CTENCFG_EN20_Enum; - -/* ============================================== GPIO CTENCFG EN19 [19..19] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN19 */ - GPIO_CTENCFG_EN19_DIS = 1, /*!< DIS : Disable CT19 for output value. */ - GPIO_CTENCFG_EN19_EN = 0, /*!< EN : Enable CT19 for output value. */ -} GPIO_CTENCFG_EN19_Enum; - -/* ============================================== GPIO CTENCFG EN18 [18..18] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN18 */ - GPIO_CTENCFG_EN18_DIS = 1, /*!< DIS : Disable CT18 for output value. */ - GPIO_CTENCFG_EN18_EN = 0, /*!< EN : Enable CT18 for output value. */ -} GPIO_CTENCFG_EN18_Enum; - -/* ============================================== GPIO CTENCFG EN17 [17..17] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN17 */ - GPIO_CTENCFG_EN17_DIS = 1, /*!< DIS : Disable CT17 for output value. */ - GPIO_CTENCFG_EN17_EN = 0, /*!< EN : Enable CT17 for output value. */ -} GPIO_CTENCFG_EN17_Enum; - -/* ============================================== GPIO CTENCFG EN16 [16..16] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN16 */ - GPIO_CTENCFG_EN16_DIS = 1, /*!< DIS : Disable CT16 for output value. */ - GPIO_CTENCFG_EN16_EN = 0, /*!< EN : Enable CT16 for output value. */ -} GPIO_CTENCFG_EN16_Enum; - -/* ============================================== GPIO CTENCFG EN15 [15..15] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN15 */ - GPIO_CTENCFG_EN15_DIS = 1, /*!< DIS : Disable CT15 for output value. */ - GPIO_CTENCFG_EN15_EN = 0, /*!< EN : Enable CT15 for output value. */ -} GPIO_CTENCFG_EN15_Enum; - -/* ============================================== GPIO CTENCFG EN14 [14..14] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN14 */ - GPIO_CTENCFG_EN14_DIS = 1, /*!< DIS : Disable CT14 for output value. */ - GPIO_CTENCFG_EN14_EN = 0, /*!< EN : Enable CT14 for output value. */ -} GPIO_CTENCFG_EN14_Enum; - -/* ============================================== GPIO CTENCFG EN13 [13..13] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN13 */ - GPIO_CTENCFG_EN13_DIS = 1, /*!< DIS : Disable CT13 for output value. */ - GPIO_CTENCFG_EN13_EN = 0, /*!< EN : Enable CT13 for output value. */ -} GPIO_CTENCFG_EN13_Enum; - -/* ============================================== GPIO CTENCFG EN12 [12..12] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN12 */ - GPIO_CTENCFG_EN12_DIS = 1, /*!< DIS : Disable CT12 for output value. */ - GPIO_CTENCFG_EN12_EN = 0, /*!< EN : Enable CT12 for output value. */ -} GPIO_CTENCFG_EN12_Enum; - -/* ============================================== GPIO CTENCFG EN11 [11..11] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN11 */ - GPIO_CTENCFG_EN11_DIS = 1, /*!< DIS : Disable CT11 for output value. */ - GPIO_CTENCFG_EN11_EN = 0, /*!< EN : Enable CT11 for output value. */ -} GPIO_CTENCFG_EN11_Enum; - -/* ============================================== GPIO CTENCFG EN10 [10..10] =============================================== */ -typedef enum { /*!< GPIO_CTENCFG_EN10 */ - GPIO_CTENCFG_EN10_DIS = 1, /*!< DIS : Disable CT10 for output value. */ - GPIO_CTENCFG_EN10_EN = 0, /*!< EN : Enable CT10 for output value. */ -} GPIO_CTENCFG_EN10_Enum; - -/* ================================================ GPIO CTENCFG EN9 [9..9] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN9 */ - GPIO_CTENCFG_EN9_DIS = 0, /*!< DIS : Disable CT9 for output value. */ -} GPIO_CTENCFG_EN9_Enum; - -/* ================================================ GPIO CTENCFG EN8 [8..8] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN8 */ - GPIO_CTENCFG_EN8_DIS = 1, /*!< DIS : Disable CT8 for output value. */ - GPIO_CTENCFG_EN8_EN = 0, /*!< EN : Enable CT8 for output value. */ -} GPIO_CTENCFG_EN8_Enum; - -/* ================================================ GPIO CTENCFG EN7 [7..7] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN7 */ - GPIO_CTENCFG_EN7_DIS = 1, /*!< DIS : Disable CT7 for output value. */ - GPIO_CTENCFG_EN7_EN = 0, /*!< EN : Enable CT7 for output value. */ -} GPIO_CTENCFG_EN7_Enum; - -/* ================================================ GPIO CTENCFG EN6 [6..6] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN6 */ - GPIO_CTENCFG_EN6_DIS = 1, /*!< DIS : Disable CT6 for output value. */ - GPIO_CTENCFG_EN6_EN = 0, /*!< EN : Enable CT6 for output value. */ -} GPIO_CTENCFG_EN6_Enum; - -/* ================================================ GPIO CTENCFG EN5 [5..5] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN5 */ - GPIO_CTENCFG_EN5_DIS = 1, /*!< DIS : Disable CT5 for output value. */ - GPIO_CTENCFG_EN5_EN = 0, /*!< EN : Enable CT5 for output value. */ -} GPIO_CTENCFG_EN5_Enum; - -/* ================================================ GPIO CTENCFG EN4 [4..4] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN4 */ - GPIO_CTENCFG_EN4_DIS = 1, /*!< DIS : Disable CT4 for output value. */ - GPIO_CTENCFG_EN4_EN = 0, /*!< EN : Enable CT4 for output value. */ -} GPIO_CTENCFG_EN4_Enum; - -/* ================================================ GPIO CTENCFG EN3 [3..3] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN3 */ - GPIO_CTENCFG_EN3_DIS = 1, /*!< DIS : Disable CT3 for output value. */ - GPIO_CTENCFG_EN3_EN = 0, /*!< EN : Enable CT3 for output value. */ -} GPIO_CTENCFG_EN3_Enum; - -/* ================================================ GPIO CTENCFG EN2 [2..2] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN2 */ - GPIO_CTENCFG_EN2_DIS = 1, /*!< DIS : Disable CT2 for output value. */ - GPIO_CTENCFG_EN2_EN = 0, /*!< EN : Enable CT2 for output value. */ -} GPIO_CTENCFG_EN2_Enum; - -/* ================================================ GPIO CTENCFG EN1 [1..1] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN1 */ - GPIO_CTENCFG_EN1_DIS = 1, /*!< DIS : Disable CT1 for output value. */ - GPIO_CTENCFG_EN1_EN = 0, /*!< EN : Enable CT1 for output value. */ -} GPIO_CTENCFG_EN1_Enum; - -/* ================================================ GPIO CTENCFG EN0 [0..0] ================================================ */ -typedef enum { /*!< GPIO_CTENCFG_EN0 */ - GPIO_CTENCFG_EN0_DIS = 1, /*!< DIS : Disable CT0 for output value. */ - GPIO_CTENCFG_EN0_EN = 0, /*!< EN : Enable CT0 for output value. */ -} GPIO_CTENCFG_EN0_Enum; - -/* ======================================================== INT0EN ========================================================= */ -/* ======================================================= INT0STAT ======================================================== */ -/* ======================================================== INT0CLR ======================================================== */ -/* ======================================================== INT0SET ======================================================== */ -/* ======================================================== INT1EN ========================================================= */ -/* ======================================================= INT1STAT ======================================================== */ -/* ======================================================== INT1CLR ======================================================== */ -/* ======================================================== INT1SET ======================================================== */ - - -/* =========================================================================================================================== */ -/* ================ IOM0 ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= FIFO ========================================================== */ -/* ======================================================== FIFOPTR ======================================================== */ -/* ======================================================== FIFOTHR ======================================================== */ -/* ======================================================== FIFOPOP ======================================================== */ -/* ======================================================= FIFOPUSH ======================================================== */ -/* ======================================================= FIFOCTRL ======================================================== */ -/* ======================================================== FIFOLOC ======================================================== */ -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ -/* ======================================================== CLKCFG ========================================================= */ -/* ============================================== IOM0 CLKCFG DIVEN [12..12] =============================================== */ -typedef enum { /*!< IOM0_CLKCFG_DIVEN */ - IOM0_CLKCFG_DIVEN_DIS = 0, /*!< DIS : Disable TOTPER division. value. */ - IOM0_CLKCFG_DIVEN_EN = 1, /*!< EN : Enable TOTPER division. value. */ -} IOM0_CLKCFG_DIVEN_Enum; - -/* =============================================== IOM0 CLKCFG DIV3 [11..11] =============================================== */ -typedef enum { /*!< IOM0_CLKCFG_DIV3 */ - IOM0_CLKCFG_DIV3_DIS = 0, /*!< DIS : Select divide by 1. value. */ - IOM0_CLKCFG_DIV3_EN = 1, /*!< EN : Select divide by 3. value. */ -} IOM0_CLKCFG_DIV3_Enum; - -/* =============================================== IOM0 CLKCFG FSEL [8..10] ================================================ */ -typedef enum { /*!< IOM0_CLKCFG_FSEL */ - IOM0_CLKCFG_FSEL_MIN_PWR = 0, /*!< MIN_PWR : Selects the minimum power clock. This setting should - be used whenever the IOM is not active. value. */ - IOM0_CLKCFG_FSEL_HFRC = 1, /*!< HFRC : Selects the HFRC as the input clock. value. */ - IOM0_CLKCFG_FSEL_HFRC_DIV2 = 2, /*!< HFRC_DIV2 : Selects the HFRC / 2 as the input clock. value. */ - IOM0_CLKCFG_FSEL_HFRC_DIV4 = 3, /*!< HFRC_DIV4 : Selects the HFRC / 4 as the input clock. value. */ - IOM0_CLKCFG_FSEL_HFRC_DIV8 = 4, /*!< HFRC_DIV8 : Selects the HFRC / 8 as the input clock. value. */ - IOM0_CLKCFG_FSEL_HFRC_DIV16 = 5, /*!< HFRC_DIV16 : Selects the HFRC / 16 as the input clock. value. */ - IOM0_CLKCFG_FSEL_HFRC_DIV32 = 6, /*!< HFRC_DIV32 : Selects the HFRC / 32 as the input clock. value. */ - IOM0_CLKCFG_FSEL_HFRC_DIV64 = 7, /*!< HFRC_DIV64 : Selects the HFRC / 64 as the input clock. value. */ -} IOM0_CLKCFG_FSEL_Enum; - -/* ====================================================== SUBMODCTRL ======================================================= */ -/* =========================================== IOM0 SUBMODCTRL SMOD1TYPE [5..7] ============================================ */ -typedef enum { /*!< IOM0_SUBMODCTRL_SMOD1TYPE */ - IOM0_SUBMODCTRL_SMOD1TYPE_MSPI = 0, /*!< MSPI : SPI Master submodule value. */ - IOM0_SUBMODCTRL_SMOD1TYPE_I2C_MASTER = 1, /*!< I2C_MASTER : MI2C submodule value. */ - IOM0_SUBMODCTRL_SMOD1TYPE_SSPI = 2, /*!< SSPI : SPI Slave submodule value. */ - IOM0_SUBMODCTRL_SMOD1TYPE_SI2C = 3, /*!< SI2C : I2C Slave submodule value. */ - IOM0_SUBMODCTRL_SMOD1TYPE_NA = 7, /*!< NA : NOT INSTALLED value. */ -} IOM0_SUBMODCTRL_SMOD1TYPE_Enum; - -/* =========================================== IOM0 SUBMODCTRL SMOD0TYPE [1..3] ============================================ */ -typedef enum { /*!< IOM0_SUBMODCTRL_SMOD0TYPE */ - IOM0_SUBMODCTRL_SMOD0TYPE_SPI_MASTER = 0, /*!< SPI_MASTER : MSPI submodule value. */ - IOM0_SUBMODCTRL_SMOD0TYPE_I2C_MASTER = 1, /*!< I2C_MASTER : I2C Master submodule value. */ - IOM0_SUBMODCTRL_SMOD0TYPE_SSPI = 2, /*!< SSPI : SPI Slave submodule value. */ - IOM0_SUBMODCTRL_SMOD0TYPE_SI2C = 3, /*!< SI2C : I2C Slave submodule value. */ - IOM0_SUBMODCTRL_SMOD0TYPE_NA = 7, /*!< NA : NOT INSTALLED value. */ -} IOM0_SUBMODCTRL_SMOD0TYPE_Enum; - -/* ========================================================== CMD ========================================================== */ -/* ================================================== IOM0 CMD CMD [0..4] ================================================== */ -typedef enum { /*!< IOM0_CMD_CMD */ - IOM0_CMD_CMD_WRITE = 1, /*!< WRITE : Write command using count of offset bytes specified - in the OFFSETCNT field value. */ - IOM0_CMD_CMD_READ = 2, /*!< READ : Read command using count of offset bytes specified in - the OFFSETCNT field value. */ - IOM0_CMD_CMD_TMW = 3, /*!< TMW : SPI only. Test mode to do constant write operations. Useful - for debug and power measurements. Will continually send - data in OFFSET field value. */ - IOM0_CMD_CMD_TMR = 4, /*!< TMR : SPI Only. Test mode to do constant read operations. Useful - for debug and power measurements. Will continually read - data from external input value. */ -} IOM0_CMD_CMD_Enum; - -/* ======================================================== CMDRPT ========================================================= */ -/* ======================================================= OFFSETHI ======================================================== */ -/* ======================================================== CMDSTAT ======================================================== */ -/* ============================================== IOM0 CMDSTAT CMDSTAT [5..7] ============================================== */ -typedef enum { /*!< IOM0_CMDSTAT_CMDSTAT */ - IOM0_CMDSTAT_CMDSTAT_ERR = 1, /*!< ERR : Error encountered with command value. */ - IOM0_CMDSTAT_CMDSTAT_ACTIVE = 2, /*!< ACTIVE : Actively processing command value. */ - IOM0_CMDSTAT_CMDSTAT_IDLE = 4, /*!< IDLE : Idle state, no active command, no error value. */ - IOM0_CMDSTAT_CMDSTAT_WAIT = 6, /*!< WAIT : Command in progress, but waiting on data from host value. */ -} IOM0_CMDSTAT_CMDSTAT_Enum; - -/* ======================================================= DMATRIGEN ======================================================= */ -/* ====================================================== DMATRIGSTAT ====================================================== */ -/* ======================================================== DMACFG ========================================================= */ -/* ============================================== IOM0 DMACFG DPWROFF [9..9] =============================================== */ -typedef enum { /*!< IOM0_DMACFG_DPWROFF */ - IOM0_DMACFG_DPWROFF_DIS = 0, /*!< DIS : Power off disabled value. */ - IOM0_DMACFG_DPWROFF_EN = 1, /*!< EN : Power off enabled value. */ -} IOM0_DMACFG_DPWROFF_Enum; - -/* =============================================== IOM0 DMACFG DMAPRI [8..8] =============================================== */ -typedef enum { /*!< IOM0_DMACFG_DMAPRI */ - IOM0_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ - IOM0_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ -} IOM0_DMACFG_DMAPRI_Enum; - -/* =============================================== IOM0 DMACFG DMADIR [1..1] =============================================== */ -typedef enum { /*!< IOM0_DMACFG_DMADIR */ - IOM0_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction. To be set when - doing IOM read operations, ie reading data from external - devices. value. */ - IOM0_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction. To be set when doing - IOM write operations, ie writing data to external devices. - value. */ -} IOM0_DMACFG_DMADIR_Enum; - -/* =============================================== IOM0 DMACFG DMAEN [0..0] ================================================ */ -typedef enum { /*!< IOM0_DMACFG_DMAEN */ - IOM0_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ - IOM0_DMACFG_DMAEN_EN = 1, /*!< EN : Enable DMA Function value. */ -} IOM0_DMACFG_DMAEN_Enum; - -/* ====================================================== DMATOTCOUNT ====================================================== */ -/* ====================================================== DMATARGADDR ====================================================== */ -/* ======================================================== DMASTAT ======================================================== */ -/* ========================================================= CQCFG ========================================================= */ -/* ================================================ IOM0 CQCFG CQPRI [1..1] ================================================ */ -typedef enum { /*!< IOM0_CQCFG_CQPRI */ - IOM0_CQCFG_CQPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ - IOM0_CQCFG_CQPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ -} IOM0_CQCFG_CQPRI_Enum; - -/* ================================================ IOM0 CQCFG CQEN [0..0] ================================================= */ -typedef enum { /*!< IOM0_CQCFG_CQEN */ - IOM0_CQCFG_CQEN_DIS = 0, /*!< DIS : Disable CQ Function value. */ - IOM0_CQCFG_CQEN_EN = 1, /*!< EN : Enable CQ Function value. */ -} IOM0_CQCFG_CQEN_Enum; - -/* ======================================================== CQADDR ========================================================= */ -/* ======================================================== CQSTAT ========================================================= */ -/* ======================================================== CQFLAGS ======================================================== */ -/* ====================================================== CQSETCLEAR ======================================================= */ -/* ======================================================= CQPAUSEEN ======================================================= */ -/* ============================================= IOM0 CQPAUSEEN CQPEN [0..15] ============================================== */ -typedef enum { /*!< IOM0_CQPAUSEEN_CQPEN */ - IOM0_CQPAUSEEN_CQPEN_IDXEQ = 32768, /*!< IDXEQ : Pauses the command queue when the current index matches - the last index value. */ - IOM0_CQPAUSEEN_CQPEN_BLEXOREN = 16384, /*!< BLEXOREN : Pause command queue when input BLE bit XORed with - SWFLAG4 is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_IOMXOREN = 8192, /*!< IOMXOREN : Pause command queue when input IOM bit XORed with - SWFLAG3 is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_GPIOXOREN = 4096, /*!< GPIOXOREN : Pause command queue when input GPIO irq_bit XORed - with SWFLAG2 is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_MSPI1XNOREN = 2048, /*!< MSPI1XNOREN : Pause command queue when input MSPI1 bit XNORed - with SWFLAG1 is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_MSPI0XNOREN = 1024, /*!< MSPI0XNOREN : Pause command queue when input MSPI0 bit XNORed - with SWFLAG0 is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_MSPI1XOREN = 512, /*!< MSPI1XOREN : Pause command queue when input MSPI1 bit XORed - with SWFLAG1 is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_MSPI0XOREN = 256, /*!< MSPI0XOREN : Pause command queue when input MSPI0 bit XORed - with SWFLAG0 is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_SWFLAGEN7 = 128, /*!< SWFLAGEN7 : Pause the command queue when software flag bit 7 - is '1'. value. */ - IOM0_CQPAUSEEN_CQPEN_SWFLAGEN6 = 64, /*!< SWFLAGEN6 : Pause the command queue when software flag bit 6 - is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_SWFLAGEN5 = 32, /*!< SWFLAGEN5 : Pause the command queue when software flag bit 5 - is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_SWFLAGEN4 = 16, /*!< SWFLAGEN4 : Pause the command queue when software flag bit 4 - is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_SWFLAGEN3 = 8, /*!< SWFLAGEN3 : Pause the command queue when software flag bit 3 - is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_SWFLAGEN2 = 4, /*!< SWFLAGEN2 : Pause the command queue when software flag bit 2 - is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_SWFLAGEN1 = 2, /*!< SWFLAGEN1 : Pause the command queue when software flag bit 1 - is '1' value. */ - IOM0_CQPAUSEEN_CQPEN_SWFLAGEN0 = 1, /*!< SWFLAGEN0 : Pause the command queue when software flag bit 0 - is '1' value. */ -} IOM0_CQPAUSEEN_CQPEN_Enum; - -/* ======================================================= CQCURIDX ======================================================== */ -/* ======================================================= CQENDIDX ======================================================== */ -/* ======================================================== STATUS ========================================================= */ -/* =============================================== IOM0 STATUS IDLEST [2..2] =============================================== */ -typedef enum { /*!< IOM0_STATUS_IDLEST */ - IOM0_STATUS_IDLEST_IDLE = 1, /*!< IDLE : The I/O state machine is in the idle state. value. */ -} IOM0_STATUS_IDLEST_Enum; - -/* =============================================== IOM0 STATUS CMDACT [1..1] =============================================== */ -typedef enum { /*!< IOM0_STATUS_CMDACT */ - IOM0_STATUS_CMDACT_ACTIVE = 1, /*!< ACTIVE : An I/O command is active. Indicates the active module - has an active command and is processing this. De-asserted - when the command is completed. value. */ -} IOM0_STATUS_CMDACT_Enum; - -/* ================================================ IOM0 STATUS ERR [0..0] ================================================= */ -typedef enum { /*!< IOM0_STATUS_ERR */ - IOM0_STATUS_ERR_ERROR = 1, /*!< ERROR : Bit has been deprecated and will always return 0. value. */ -} IOM0_STATUS_ERR_Enum; - -/* ======================================================== MSPICFG ======================================================== */ -/* ============================================= IOM0 MSPICFG SPILSB [23..23] ============================================== */ -typedef enum { /*!< IOM0_MSPICFG_SPILSB */ - IOM0_MSPICFG_SPILSB_MSB = 0, /*!< MSB : Send and receive MSB bit first value. */ - IOM0_MSPICFG_SPILSB_LSB = 1, /*!< LSB : Send and receive LSB bit first value. */ -} IOM0_MSPICFG_SPILSB_Enum; - -/* ============================================= IOM0 MSPICFG RDFCPOL [22..22] ============================================= */ -typedef enum { /*!< IOM0_MSPICFG_RDFCPOL */ - IOM0_MSPICFG_RDFCPOL_HIGH = 0, /*!< HIGH : Flow control signal high creates flow control. value. */ - IOM0_MSPICFG_RDFCPOL_LOW = 1, /*!< LOW : Flow control signal low creates flow control. value. */ -} IOM0_MSPICFG_RDFCPOL_Enum; - -/* ============================================= IOM0 MSPICFG WTFCPOL [21..21] ============================================= */ -typedef enum { /*!< IOM0_MSPICFG_WTFCPOL */ - IOM0_MSPICFG_WTFCPOL_HIGH = 0, /*!< HIGH : Flow control signal high(1) creates flow control and - byte transfers will stop until the flow control signal - goes low. value. */ - IOM0_MSPICFG_WTFCPOL_LOW = 1, /*!< LOW : Flow control signal low(0) creates flow control and byte - transfers will stop until the flow control signal goes - high(1). value. */ -} IOM0_MSPICFG_WTFCPOL_Enum; - -/* ============================================= IOM0 MSPICFG WTFCIRQ [20..20] ============================================= */ -typedef enum { /*!< IOM0_MSPICFG_WTFCIRQ */ - IOM0_MSPICFG_WTFCIRQ_MISO = 0, /*!< MISO : MISO is used as the write mode flow control signal. value. */ - IOM0_MSPICFG_WTFCIRQ_IRQ = 1, /*!< IRQ : IRQ is used as the write mode flow control signal. value. */ -} IOM0_MSPICFG_WTFCIRQ_Enum; - -/* ============================================= IOM0 MSPICFG MOSIINV [18..18] ============================================= */ -typedef enum { /*!< IOM0_MSPICFG_MOSIINV */ - IOM0_MSPICFG_MOSIINV_NORMAL = 0, /*!< NORMAL : MOSI is set to 0 in read mode and 1 in write mode. - value. */ - IOM0_MSPICFG_MOSIINV_INVERT = 1, /*!< INVERT : MOSI is set to 1 in read mode and 0 in write mode. - value. */ -} IOM0_MSPICFG_MOSIINV_Enum; - -/* ============================================== IOM0 MSPICFG RDFC [17..17] =============================================== */ -typedef enum { /*!< IOM0_MSPICFG_RDFC */ - IOM0_MSPICFG_RDFC_DIS = 0, /*!< DIS : Read mode flow control disabled. value. */ - IOM0_MSPICFG_RDFC_EN = 1, /*!< EN : Read mode flow control enabled. value. */ -} IOM0_MSPICFG_RDFC_Enum; - -/* ============================================== IOM0 MSPICFG WTFC [16..16] =============================================== */ -typedef enum { /*!< IOM0_MSPICFG_WTFC */ - IOM0_MSPICFG_WTFC_DIS = 0, /*!< DIS : Write mode flow control disabled. value. */ - IOM0_MSPICFG_WTFC_EN = 1, /*!< EN : Write mode flow control enabled. value. */ -} IOM0_MSPICFG_WTFC_Enum; - -/* =============================================== IOM0 MSPICFG SPHA [1..1] ================================================ */ -typedef enum { /*!< IOM0_MSPICFG_SPHA */ - IOM0_MSPICFG_SPHA_SAMPLE_LEADING_EDGE = 0, /*!< SAMPLE_LEADING_EDGE : Sample on the leading (first) clock edge. - value. */ - IOM0_MSPICFG_SPHA_SAMPLE_TRAILING_EDGE = 1, /*!< SAMPLE_TRAILING_EDGE : Sample on the trailing (second) clock - edge. value. */ -} IOM0_MSPICFG_SPHA_Enum; - -/* =============================================== IOM0 MSPICFG SPOL [0..0] ================================================ */ -typedef enum { /*!< IOM0_MSPICFG_SPOL */ - IOM0_MSPICFG_SPOL_CLK_BASE_0 = 0, /*!< CLK_BASE_0 : The base value of the clock is 0. value. */ - IOM0_MSPICFG_SPOL_CLK_BASE_1 = 1, /*!< CLK_BASE_1 : The base value of the clock is 1. value. */ -} IOM0_MSPICFG_SPOL_Enum; - -/* ======================================================== MI2CCFG ======================================================== */ -/* =============================================== IOM0 MI2CCFG ARBEN [2..2] =============================================== */ -typedef enum { /*!< IOM0_MI2CCFG_ARBEN */ - IOM0_MI2CCFG_ARBEN_ARBEN = 1, /*!< ARBEN : Enable multi-master bus arbitration support for this - i2c master value. */ - IOM0_MI2CCFG_ARBEN_ARBDIS = 0, /*!< ARBDIS : Disable multi-master bus arbitration support for this - i2c master value. */ -} IOM0_MI2CCFG_ARBEN_Enum; - -/* ============================================== IOM0 MI2CCFG I2CLSB [1..1] =============================================== */ -typedef enum { /*!< IOM0_MI2CCFG_I2CLSB */ - IOM0_MI2CCFG_I2CLSB_MSBFIRST = 0, /*!< MSBFIRST : Byte data is transmitted MSB first onto the bus/read - from the bus value. */ - IOM0_MI2CCFG_I2CLSB_LSBFIRST = 1, /*!< LSBFIRST : Byte data is transmitted LSB first onto the bus/read - from the bus value. */ -} IOM0_MI2CCFG_I2CLSB_Enum; - -/* ============================================== IOM0 MI2CCFG ADDRSZ [0..0] =============================================== */ -typedef enum { /*!< IOM0_MI2CCFG_ADDRSZ */ - IOM0_MI2CCFG_ADDRSZ_ADDRSZ7 = 0, /*!< ADDRSZ7 : Use 7b addressing for I2C master transactions value. */ - IOM0_MI2CCFG_ADDRSZ_ADDRSZ10 = 1, /*!< ADDRSZ10 : Use 10b addressing for I2C master transactions value. */ -} IOM0_MI2CCFG_ADDRSZ_Enum; - -/* ======================================================== DEVCFG ========================================================= */ -/* ======================================================== IOMDBG ========================================================= */ - - -/* =========================================================================================================================== */ -/* ================ IOSLAVE ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== FIFOPTR ======================================================== */ -/* ======================================================== FIFOCFG ======================================================== */ -/* ======================================================== FIFOTHR ======================================================== */ -/* ========================================================= FUPD ========================================================== */ -/* ======================================================== FIFOCTR ======================================================== */ -/* ======================================================== FIFOINC ======================================================== */ -/* ========================================================== CFG ========================================================== */ -/* ============================================== IOSLAVE CFG IFCEN [31..31] =============================================== */ -typedef enum { /*!< IOSLAVE_CFG_IFCEN */ - IOSLAVE_CFG_IFCEN_DIS = 0, /*!< DIS : Disable the IOSLAVE value. */ - IOSLAVE_CFG_IFCEN_EN = 1, /*!< EN : Enable the IOSLAVE value. */ -} IOSLAVE_CFG_IFCEN_Enum; - -/* ============================================== IOSLAVE CFG STARTRD [4..4] =============================================== */ -typedef enum { /*!< IOSLAVE_CFG_STARTRD */ - IOSLAVE_CFG_STARTRD_LATE = 0, /*!< LATE : Initiate I/O RAM read late in each transferred byte. - value. */ - IOSLAVE_CFG_STARTRD_EARLY = 1, /*!< EARLY : Initiate I/O RAM read early in each transferred byte. - value. */ -} IOSLAVE_CFG_STARTRD_Enum; - -/* ================================================ IOSLAVE CFG LSB [2..2] ================================================= */ -typedef enum { /*!< IOSLAVE_CFG_LSB */ - IOSLAVE_CFG_LSB_MSB_FIRST = 0, /*!< MSB_FIRST : Data is assumed to be sent and received with MSB - first. value. */ - IOSLAVE_CFG_LSB_LSB_FIRST = 1, /*!< LSB_FIRST : Data is assumed to be sent and received with LSB - first. value. */ -} IOSLAVE_CFG_LSB_Enum; - -/* ================================================ IOSLAVE CFG SPOL [1..1] ================================================ */ -typedef enum { /*!< IOSLAVE_CFG_SPOL */ - IOSLAVE_CFG_SPOL_SPI_MODES_0_3 = 0, /*!< SPI_MODES_0_3 : Polarity 0, handles SPI modes 0 and 3. value. */ - IOSLAVE_CFG_SPOL_SPI_MODES_1_2 = 1, /*!< SPI_MODES_1_2 : Polarity 1, handles SPI modes 1 and 2. value. */ -} IOSLAVE_CFG_SPOL_Enum; - -/* =============================================== IOSLAVE CFG IFCSEL [0..0] =============================================== */ -typedef enum { /*!< IOSLAVE_CFG_IFCSEL */ - IOSLAVE_CFG_IFCSEL_I2C = 0, /*!< I2C : Selects I2C interface for the IO Slave. value. */ - IOSLAVE_CFG_IFCSEL_SPI = 1, /*!< SPI : Selects SPI interface for the IO Slave. value. */ -} IOSLAVE_CFG_IFCSEL_Enum; - -/* ========================================================= PRENC ========================================================= */ -/* ======================================================= IOINTCTL ======================================================== */ -/* ======================================================== GENADD ========================================================= */ -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ -/* ====================================================== REGACCINTEN ====================================================== */ -/* ===================================================== REGACCINTSTAT ===================================================== */ -/* ===================================================== REGACCINTCLR ====================================================== */ -/* ===================================================== REGACCINTSET ====================================================== */ - - -/* =========================================================================================================================== */ -/* ================ MCUCTRL ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== CHIPPN ========================================================= */ -/* ============================================ MCUCTRL CHIPPN PARTNUM [0..31] ============================================= */ -typedef enum { /*!< MCUCTRL_CHIPPN_PARTNUM */ - MCUCTRL_CHIPPN_PARTNUM_APOLLO3 = 100663296,/*!< APOLLO3 : Apollo3 part number is 0x06xxxxxx. value. */ - MCUCTRL_CHIPPN_PARTNUM_APOLLO2 = 50331648,/*!< APOLLO2 : Apollo2 part number is 0x03xxxxxx. value. */ - MCUCTRL_CHIPPN_PARTNUM_APOLLO = 16777216,/*!< APOLLO : Apollo part number is 0x01xxxxxx. value. */ - MCUCTRL_CHIPPN_PARTNUM_PN_M = -16777216,/*!< PN_M : Mask for the part number field. value. */ - MCUCTRL_CHIPPN_PARTNUM_PN_S = 24, /*!< PN_S : Bit position for the part number field. value. */ - MCUCTRL_CHIPPN_PARTNUM_FLASHSIZE_M = 15728640,/*!< FLASHSIZE_M : Mask for the FLASH_SIZE field.Values:0: 16KB1: - 32KB2: 64KB3: 128KB4: 256KB5: 512KB6: 1MB7: 2MB value. */ - MCUCTRL_CHIPPN_PARTNUM_FLASHSIZE_S = 20, /*!< FLASHSIZE_S : Bit position for the FLASH_SIZE field. value. */ - MCUCTRL_CHIPPN_PARTNUM_SRAMSIZE_M = 983040,/*!< SRAMSIZE_M : Mask for the SRAM_SIZE field.Values:0: 16KB1: 32KB2: - 64KB3: 128KB4: 256KB5: 512KB6: 1MB7: 384KB value. */ - MCUCTRL_CHIPPN_PARTNUM_SRAMSIZE_S = 16, /*!< SRAMSIZE_S : Bit position for the SRAM_SIZE field. value. */ - MCUCTRL_CHIPPN_PARTNUM_REV_M = 65280, /*!< REV_M : Mask for the revision field. Bits [15:12] are major - rev, [11:8] are minor rev.Values:0: Major Rev A, Minor - Rev 01: Major Rev B, Minor Rev 1 value. */ - MCUCTRL_CHIPPN_PARTNUM_REV_S = 8, /*!< REV_S : Bit position for the revision field. value. */ - MCUCTRL_CHIPPN_PARTNUM_PKG_M = 192, /*!< PKG_M : Mask for the package field.Values:0: SIP1: QFN2: BGA3: - CSP value. */ - MCUCTRL_CHIPPN_PARTNUM_PKG_S = 6, /*!< PKG_S : Bit position for the package field. value. */ - MCUCTRL_CHIPPN_PARTNUM_PINS_M = 56, /*!< PINS_M : Mask for the pins field.Values:0: 25 pins1: 49 pins2: - 64 pins3: 81 pins value. */ - MCUCTRL_CHIPPN_PARTNUM_PINS_S = 3, /*!< PINS_S : Bit position for the pins field. value. */ - MCUCTRL_CHIPPN_PARTNUM_TEMP_S = 1, /*!< TEMP_S : Bit position for the temperature field. value. */ - MCUCTRL_CHIPPN_PARTNUM_QUAL_S = 0, /*!< QUAL_S : Bit position for the qualified field. value. */ -} MCUCTRL_CHIPPN_PARTNUM_Enum; - -/* ======================================================== CHIPID0 ======================================================== */ -/* ============================================ MCUCTRL CHIPID0 CHIPID0 [0..31] ============================================ */ -typedef enum { /*!< MCUCTRL_CHIPID0_CHIPID0 */ - MCUCTRL_CHIPID0_CHIPID0_APOLLO3 = 0, /*!< APOLLO3 : Apollo3 CHIPID0. value. */ -} MCUCTRL_CHIPID0_CHIPID0_Enum; - -/* ======================================================== CHIPID1 ======================================================== */ -/* ============================================ MCUCTRL CHIPID1 CHIPID1 [0..31] ============================================ */ -typedef enum { /*!< MCUCTRL_CHIPID1_CHIPID1 */ - MCUCTRL_CHIPID1_CHIPID1_APOLLO3 = 0, /*!< APOLLO3 : Apollo3 CHIPID1. value. */ -} MCUCTRL_CHIPID1_CHIPID1_Enum; - -/* ======================================================== CHIPREV ======================================================== */ -/* ============================================= MCUCTRL CHIPREV REVMAJ [4..7] ============================================= */ -typedef enum { /*!< MCUCTRL_CHIPREV_REVMAJ */ - MCUCTRL_CHIPREV_REVMAJ_A = 1, /*!< A : Apollo3 revision A value. */ -} MCUCTRL_CHIPREV_REVMAJ_Enum; - -/* ============================================= MCUCTRL CHIPREV REVMIN [0..3] ============================================= */ -typedef enum { /*!< MCUCTRL_CHIPREV_REVMIN */ - MCUCTRL_CHIPREV_REVMIN_REV1 = 2, /*!< REV1 : Apollo3 minor rev 1. value. */ - MCUCTRL_CHIPREV_REVMIN_REV0 = 1, /*!< REV0 : Apollo3 minor rev 0. Minor revision value, succeeding - minor revisions will increment from this value. value. */ -} MCUCTRL_CHIPREV_REVMIN_Enum; - -/* ======================================================= VENDORID ======================================================== */ -/* =========================================== MCUCTRL VENDORID VENDORID [0..31] =========================================== */ -typedef enum { /*!< MCUCTRL_VENDORID_VENDORID */ - MCUCTRL_VENDORID_VENDORID_AMBIQ = 1095582289,/*!< AMBIQ : Ambiq Vendor ID value. */ -} MCUCTRL_VENDORID_VENDORID_Enum; - -/* ========================================================== SKU ========================================================== */ -/* ===================================================== FEATUREENABLE ===================================================== */ -/* ======================================== MCUCTRL FEATUREENABLE BURSTAVAIL [6..6] ======================================== */ -typedef enum { /*!< MCUCTRL_FEATUREENABLE_BURSTAVAIL */ - MCUCTRL_FEATUREENABLE_BURSTAVAIL_AVAIL = 1, /*!< AVAIL : Burst functionality available value. */ - MCUCTRL_FEATUREENABLE_BURSTAVAIL_NOTAVAIL = 0,/*!< NOTAVAIL : Burst functionality not available value. */ -} MCUCTRL_FEATUREENABLE_BURSTAVAIL_Enum; - -/* ========================================= MCUCTRL FEATUREENABLE BURSTREQ [4..4] ========================================= */ -typedef enum { /*!< MCUCTRL_FEATUREENABLE_BURSTREQ */ - MCUCTRL_FEATUREENABLE_BURSTREQ_EN = 1, /*!< EN : Enable the Burst functionality value. */ - MCUCTRL_FEATUREENABLE_BURSTREQ_DIS = 0, /*!< DIS : Disable the Burst functionality value. */ -} MCUCTRL_FEATUREENABLE_BURSTREQ_Enum; - -/* ========================================= MCUCTRL FEATUREENABLE BLEAVAIL [2..2] ========================================= */ -typedef enum { /*!< MCUCTRL_FEATUREENABLE_BLEAVAIL */ - MCUCTRL_FEATUREENABLE_BLEAVAIL_AVAIL = 1, /*!< AVAIL : BLE functionality available value. */ - MCUCTRL_FEATUREENABLE_BLEAVAIL_NOTAVAIL = 0, /*!< NOTAVAIL : BLE functionality not available value. */ -} MCUCTRL_FEATUREENABLE_BLEAVAIL_Enum; - -/* ========================================== MCUCTRL FEATUREENABLE BLEREQ [0..0] ========================================== */ -typedef enum { /*!< MCUCTRL_FEATUREENABLE_BLEREQ */ - MCUCTRL_FEATUREENABLE_BLEREQ_EN = 1, /*!< EN : Enable the BLE functionality value. */ - MCUCTRL_FEATUREENABLE_BLEREQ_DIS = 0, /*!< DIS : Disable the BLE functionality value. */ -} MCUCTRL_FEATUREENABLE_BLEREQ_Enum; - -/* ======================================================= DEBUGGER ======================================================== */ -/* ======================================================== BODCTRL ======================================================== */ -/* ======================================================= ADCPWRDLY ======================================================= */ -/* ======================================================== ADCCAL ========================================================= */ -/* ========================================== MCUCTRL ADCCAL ADCCALIBRATED [1..1] ========================================== */ -typedef enum { /*!< MCUCTRL_ADCCAL_ADCCALIBRATED */ - MCUCTRL_ADCCAL_ADCCALIBRATED_FALSE = 0, /*!< FALSE : ADC is not calibrated value. */ - MCUCTRL_ADCCAL_ADCCALIBRATED_TRUE = 1, /*!< TRUE : ADC is calibrated value. */ -} MCUCTRL_ADCCAL_ADCCALIBRATED_Enum; - -/* =========================================== MCUCTRL ADCCAL CALONPWRUP [0..0] ============================================ */ -typedef enum { /*!< MCUCTRL_ADCCAL_CALONPWRUP */ - MCUCTRL_ADCCAL_CALONPWRUP_DIS = 0, /*!< DIS : Disable automatic calibration on initial power up value. */ - MCUCTRL_ADCCAL_CALONPWRUP_EN = 1, /*!< EN : Enable automatic calibration on initial power up value. */ -} MCUCTRL_ADCCAL_CALONPWRUP_Enum; - -/* ====================================================== ADCBATTLOAD ====================================================== */ -/* ========================================== MCUCTRL ADCBATTLOAD BATTLOAD [0..0] ========================================== */ -typedef enum { /*!< MCUCTRL_ADCBATTLOAD_BATTLOAD */ - MCUCTRL_ADCBATTLOAD_BATTLOAD_DIS = 0, /*!< DIS : Battery load is disconnected value. */ - MCUCTRL_ADCBATTLOAD_BATTLOAD_EN = 1, /*!< EN : Battery load is enabled value. */ -} MCUCTRL_ADCBATTLOAD_BATTLOAD_Enum; - -/* ======================================================== ADCTRIM ======================================================== */ -/* ====================================================== ADCREFCOMP ======================================================= */ -/* ======================================================= XTALCTRL ======================================================== */ -/* ========================================== MCUCTRL XTALCTRL PWDBODXTAL [5..5] =========================================== */ -typedef enum { /*!< MCUCTRL_XTALCTRL_PWDBODXTAL */ - MCUCTRL_XTALCTRL_PWDBODXTAL_PWRUPBOD = 0, /*!< PWRUPBOD : Power up xtal on BOD value. */ - MCUCTRL_XTALCTRL_PWDBODXTAL_PWRDNBOD = 1, /*!< PWRDNBOD : Power down XTAL on BOD. value. */ -} MCUCTRL_XTALCTRL_PWDBODXTAL_Enum; - -/* ========================================= MCUCTRL XTALCTRL PDNBCMPRXTAL [4..4] ========================================== */ -typedef enum { /*!< MCUCTRL_XTALCTRL_PDNBCMPRXTAL */ - MCUCTRL_XTALCTRL_PDNBCMPRXTAL_PWRUPCOMP = 1, /*!< PWRUPCOMP : Power up XTAL oscillator comparator. value. */ - MCUCTRL_XTALCTRL_PDNBCMPRXTAL_PWRDNCOMP = 0, /*!< PWRDNCOMP : Power down XTAL oscillator comparator. value. */ -} MCUCTRL_XTALCTRL_PDNBCMPRXTAL_Enum; - -/* ========================================= MCUCTRL XTALCTRL PDNBCOREXTAL [3..3] ========================================== */ -typedef enum { /*!< MCUCTRL_XTALCTRL_PDNBCOREXTAL */ - MCUCTRL_XTALCTRL_PDNBCOREXTAL_PWRUPCORE = 1, /*!< PWRUPCORE : Power up XTAL oscillator core. value. */ - MCUCTRL_XTALCTRL_PDNBCOREXTAL_PWRDNCORE = 0, /*!< PWRDNCORE : Power down XTAL oscillator core. value. */ -} MCUCTRL_XTALCTRL_PDNBCOREXTAL_Enum; - -/* ========================================== MCUCTRL XTALCTRL BYPCMPRXTAL [2..2] ========================================== */ -typedef enum { /*!< MCUCTRL_XTALCTRL_BYPCMPRXTAL */ - MCUCTRL_XTALCTRL_BYPCMPRXTAL_USECOMP = 0, /*!< USECOMP : Use the XTAL oscillator comparator. value. */ - MCUCTRL_XTALCTRL_BYPCMPRXTAL_BYPCOMP = 1, /*!< BYPCOMP : Bypass the XTAL oscillator comparator. value. */ -} MCUCTRL_XTALCTRL_BYPCMPRXTAL_Enum; - -/* ========================================= MCUCTRL XTALCTRL FDBKDSBLXTAL [1..1] ========================================== */ -typedef enum { /*!< MCUCTRL_XTALCTRL_FDBKDSBLXTAL */ - MCUCTRL_XTALCTRL_FDBKDSBLXTAL_EN = 0, /*!< EN : Enable XTAL oscillator comparator. value. */ - MCUCTRL_XTALCTRL_FDBKDSBLXTAL_DIS = 1, /*!< DIS : Disable XTAL oscillator comparator. value. */ -} MCUCTRL_XTALCTRL_FDBKDSBLXTAL_Enum; - -/* ============================================ MCUCTRL XTALCTRL XTALSWE [0..0] ============================================ */ -typedef enum { /*!< MCUCTRL_XTALCTRL_XTALSWE */ - MCUCTRL_XTALCTRL_XTALSWE_OVERRIDE_DIS = 0, /*!< OVERRIDE_DIS : XTAL Software Override Disable. value. */ - MCUCTRL_XTALCTRL_XTALSWE_OVERRIDE_EN = 1, /*!< OVERRIDE_EN : XTAL Software Override Enable. value. */ -} MCUCTRL_XTALCTRL_XTALSWE_Enum; - -/* ====================================================== XTALGENCTRL ====================================================== */ -/* ========================================== MCUCTRL XTALGENCTRL ACWARMUP [0..1] ========================================== */ -typedef enum { /*!< MCUCTRL_XTALGENCTRL_ACWARMUP */ - MCUCTRL_XTALGENCTRL_ACWARMUP_SEC1 = 0, /*!< SEC1 : Warmup period of 1-2 seconds value. */ - MCUCTRL_XTALGENCTRL_ACWARMUP_SEC2 = 1, /*!< SEC2 : Warmup period of 2-4 seconds value. */ - MCUCTRL_XTALGENCTRL_ACWARMUP_SEC4 = 2, /*!< SEC4 : Warmup period of 4-8 seconds value. */ - MCUCTRL_XTALGENCTRL_ACWARMUP_SEC8 = 3, /*!< SEC8 : Warmup period of 8-16 seconds value. */ -} MCUCTRL_XTALGENCTRL_ACWARMUP_Enum; - -/* ======================================================= MISCCTRL ======================================================== */ -/* ====================================================== BOOTLOADER ======================================================= */ -/* ======================================= MCUCTRL BOOTLOADER SECBOOTONRST [30..31] ======================================== */ -typedef enum { /*!< MCUCTRL_BOOTLOADER_SECBOOTONRST */ - MCUCTRL_BOOTLOADER_SECBOOTONRST_DISABLED = 0, /*!< DISABLED : Secure boot disabled value. */ - MCUCTRL_BOOTLOADER_SECBOOTONRST_ENABLED = 1, /*!< ENABLED : Secure boot enabled value. */ - MCUCTRL_BOOTLOADER_SECBOOTONRST_ERROR = 2, /*!< ERROR : Error in secure boot configuration value. */ -} MCUCTRL_BOOTLOADER_SECBOOTONRST_Enum; - -/* ========================================== MCUCTRL BOOTLOADER SECBOOT [28..29] ========================================== */ -typedef enum { /*!< MCUCTRL_BOOTLOADER_SECBOOT */ - MCUCTRL_BOOTLOADER_SECBOOT_DISABLED = 0, /*!< DISABLED : Secure boot disabled value. */ - MCUCTRL_BOOTLOADER_SECBOOT_ENABLED = 1, /*!< ENABLED : Secure boot enabled value. */ - MCUCTRL_BOOTLOADER_SECBOOT_ERROR = 2, /*!< ERROR : Error in secure boot configuration value. */ -} MCUCTRL_BOOTLOADER_SECBOOT_Enum; - -/* ====================================== MCUCTRL BOOTLOADER SECBOOTFEATURE [26..27] ======================================= */ -typedef enum { /*!< MCUCTRL_BOOTLOADER_SECBOOTFEATURE */ - MCUCTRL_BOOTLOADER_SECBOOTFEATURE_DISABLED = 0,/*!< DISABLED : Secure boot disabled value. */ - MCUCTRL_BOOTLOADER_SECBOOTFEATURE_ENABLED = 1,/*!< ENABLED : Secure boot enabled value. */ - MCUCTRL_BOOTLOADER_SECBOOTFEATURE_ERROR = 2, /*!< ERROR : Error in secure boot configuration value. */ -} MCUCTRL_BOOTLOADER_SECBOOTFEATURE_Enum; - -/* ========================================== MCUCTRL BOOTLOADER PROTLOCK [2..2] =========================================== */ -typedef enum { /*!< MCUCTRL_BOOTLOADER_PROTLOCK */ - MCUCTRL_BOOTLOADER_PROTLOCK_LOCK = 1, /*!< LOCK : Enable the secure boot lock value. */ -} MCUCTRL_BOOTLOADER_PROTLOCK_Enum; - -/* =========================================== MCUCTRL BOOTLOADER SBLOCK [1..1] ============================================ */ -typedef enum { /*!< MCUCTRL_BOOTLOADER_SBLOCK */ - MCUCTRL_BOOTLOADER_SBLOCK_LOCK = 1, /*!< LOCK : Enable the secure boot lock value. */ -} MCUCTRL_BOOTLOADER_SBLOCK_Enum; - -/* ======================================== MCUCTRL BOOTLOADER BOOTLOADERLOW [0..0] ======================================== */ -typedef enum { /*!< MCUCTRL_BOOTLOADER_BOOTLOADERLOW */ - MCUCTRL_BOOTLOADER_BOOTLOADERLOW_ADDR0 = 1, /*!< ADDR0 : Bootloader code at 0x00000000. value. */ -} MCUCTRL_BOOTLOADER_BOOTLOADERLOW_Enum; - -/* ====================================================== SHADOWVALID ====================================================== */ -/* ======================================== MCUCTRL SHADOWVALID INFO0_VALID [2..2] ========================================= */ -typedef enum { /*!< MCUCTRL_SHADOWVALID_INFO0_VALID */ - MCUCTRL_SHADOWVALID_INFO0_VALID_VALID = 1, /*!< VALID : Flash info0 (customer) space contains valid data. value. */ -} MCUCTRL_SHADOWVALID_INFO0_VALID_Enum; - -/* ========================================== MCUCTRL SHADOWVALID BLDSLEEP [1..1] ========================================== */ -typedef enum { /*!< MCUCTRL_SHADOWVALID_BLDSLEEP */ - MCUCTRL_SHADOWVALID_BLDSLEEP_DEEPSLEEP = 1, /*!< DEEPSLEEP : Bootloader will go to deep sleep if no flash image - loaded value. */ -} MCUCTRL_SHADOWVALID_BLDSLEEP_Enum; - -/* =========================================== MCUCTRL SHADOWVALID VALID [0..0] ============================================ */ -typedef enum { /*!< MCUCTRL_SHADOWVALID_VALID */ - MCUCTRL_SHADOWVALID_VALID_VALID = 1, /*!< VALID : Flash information space contains valid data. value. */ -} MCUCTRL_SHADOWVALID_VALID_Enum; - -/* ======================================================= SCRATCH0 ======================================================== */ -/* ======================================================= SCRATCH1 ======================================================== */ -/* ==================================================== ICODEFAULTADDR ===================================================== */ -/* ==================================================== DCODEFAULTADDR ===================================================== */ -/* ===================================================== SYSFAULTADDR ====================================================== */ -/* ====================================================== FAULTSTATUS ====================================================== */ -/* ========================================== MCUCTRL FAULTSTATUS SYSFAULT [2..2] ========================================== */ -typedef enum { /*!< MCUCTRL_FAULTSTATUS_SYSFAULT */ - MCUCTRL_FAULTSTATUS_SYSFAULT_NOFAULT = 0, /*!< NOFAULT : No bus fault has been detected. value. */ - MCUCTRL_FAULTSTATUS_SYSFAULT_FAULT = 1, /*!< FAULT : Bus fault detected. value. */ -} MCUCTRL_FAULTSTATUS_SYSFAULT_Enum; - -/* ========================================= MCUCTRL FAULTSTATUS DCODEFAULT [1..1] ========================================= */ -typedef enum { /*!< MCUCTRL_FAULTSTATUS_DCODEFAULT */ - MCUCTRL_FAULTSTATUS_DCODEFAULT_NOFAULT = 0, /*!< NOFAULT : No DCODE fault has been detected. value. */ - MCUCTRL_FAULTSTATUS_DCODEFAULT_FAULT = 1, /*!< FAULT : DCODE fault detected. value. */ -} MCUCTRL_FAULTSTATUS_DCODEFAULT_Enum; - -/* ========================================= MCUCTRL FAULTSTATUS ICODEFAULT [0..0] ========================================= */ -typedef enum { /*!< MCUCTRL_FAULTSTATUS_ICODEFAULT */ - MCUCTRL_FAULTSTATUS_ICODEFAULT_NOFAULT = 0, /*!< NOFAULT : No ICODE fault has been detected. value. */ - MCUCTRL_FAULTSTATUS_ICODEFAULT_FAULT = 1, /*!< FAULT : ICODE fault detected. value. */ -} MCUCTRL_FAULTSTATUS_ICODEFAULT_Enum; - -/* ==================================================== FAULTCAPTUREEN ===================================================== */ -/* ===================================== MCUCTRL FAULTCAPTUREEN FAULTCAPTUREEN [0..0] ====================================== */ -typedef enum { /*!< MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN */ - MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_DIS = 0,/*!< DIS : Disable fault capture. value. */ - MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_EN = 1, /*!< EN : Enable fault capture. value. */ -} MCUCTRL_FAULTCAPTUREEN_FAULTCAPTUREEN_Enum; - -/* ========================================================= DBGR1 ========================================================= */ -/* ========================================================= DBGR2 ========================================================= */ -/* ======================================================= PMUENABLE ======================================================= */ -/* ============================================ MCUCTRL PMUENABLE ENABLE [0..0] ============================================ */ -typedef enum { /*!< MCUCTRL_PMUENABLE_ENABLE */ - MCUCTRL_PMUENABLE_ENABLE_DIS = 0, /*!< DIS : Disable MCU power management. value. */ - MCUCTRL_PMUENABLE_ENABLE_EN = 1, /*!< EN : Enable MCU power management. value. */ -} MCUCTRL_PMUENABLE_ENABLE_Enum; - -/* ======================================================= TPIUCTRL ======================================================== */ -/* ============================================ MCUCTRL TPIUCTRL CLKSEL [8..10] ============================================ */ -typedef enum { /*!< MCUCTRL_TPIUCTRL_CLKSEL */ - MCUCTRL_TPIUCTRL_CLKSEL_LOWPWR = 0, /*!< LOWPWR : Low power state. value. */ - MCUCTRL_TPIUCTRL_CLKSEL_HFRCDIV2 = 1, /*!< HFRCDIV2 : Selects HFRC divided by 2 as the source TPIU clk - value. */ - MCUCTRL_TPIUCTRL_CLKSEL_HFRCDIV8 = 2, /*!< HFRCDIV8 : Selects HFRC divided by 8 as the source TPIU clk - value. */ - MCUCTRL_TPIUCTRL_CLKSEL_HFRCDIV16 = 3, /*!< HFRCDIV16 : Selects HFRC divided by 16 as the source TPIU clk - value. */ - MCUCTRL_TPIUCTRL_CLKSEL_HFRCDIV32 = 4, /*!< HFRCDIV32 : Selects HFRC divided by 32 as the source TPIU clk - value. */ -} MCUCTRL_TPIUCTRL_CLKSEL_Enum; - -/* ============================================ MCUCTRL TPIUCTRL ENABLE [0..0] ============================================= */ -typedef enum { /*!< MCUCTRL_TPIUCTRL_ENABLE */ - MCUCTRL_TPIUCTRL_ENABLE_DIS = 0, /*!< DIS : Disable the TPIU. value. */ - MCUCTRL_TPIUCTRL_ENABLE_EN = 1, /*!< EN : Enable the TPIU. value. */ -} MCUCTRL_TPIUCTRL_ENABLE_Enum; - -/* ====================================================== OTAPOINTER ======================================================= */ -/* ====================================================== APBDMACTRL ======================================================= */ -/* ========================================= MCUCTRL APBDMACTRL DECODEABORT [1..1] ========================================= */ -typedef enum { /*!< MCUCTRL_APBDMACTRL_DECODEABORT */ - MCUCTRL_APBDMACTRL_DECODEABORT_DISABLE = 0, /*!< DISABLE : Bus operations to powered down peripherals are quietly - discarded value. */ - MCUCTRL_APBDMACTRL_DECODEABORT_ENABLE = 1, /*!< ENABLE : Bus operations to powered down peripherals result in - a bus fault. value. */ -} MCUCTRL_APBDMACTRL_DECODEABORT_Enum; - -/* ========================================= MCUCTRL APBDMACTRL DMA_ENABLE [0..0] ========================================== */ -typedef enum { /*!< MCUCTRL_APBDMACTRL_DMA_ENABLE */ - MCUCTRL_APBDMACTRL_DMA_ENABLE_DISABLE = 0, /*!< DISABLE : DMA operations disabled value. */ - MCUCTRL_APBDMACTRL_DMA_ENABLE_ENABLE = 1, /*!< ENABLE : DMA operations enabled value. */ -} MCUCTRL_APBDMACTRL_DMA_ENABLE_Enum; - -/* ======================================================= SRAMMODE ======================================================== */ -/* ====================================================== KEXTCLKSEL ======================================================= */ -/* ========================================= MCUCTRL KEXTCLKSEL KEXTCLKSEL [0..31] ========================================= */ -typedef enum { /*!< MCUCTRL_KEXTCLKSEL_KEXTCLKSEL */ - MCUCTRL_KEXTCLKSEL_KEXTCLKSEL_Key = 83, /*!< Key : Key value. */ -} MCUCTRL_KEXTCLKSEL_KEXTCLKSEL_Enum; - -/* ======================================================= SIMOBUCK4 ======================================================= */ -/* ======================================================= BLEBUCK2 ======================================================== */ -/* ====================================================== FLASHWPROT0 ====================================================== */ -/* ====================================================== FLASHWPROT1 ====================================================== */ -/* ====================================================== FLASHRPROT0 ====================================================== */ -/* ====================================================== FLASHRPROT1 ====================================================== */ -/* ================================================= DMASRAMWRITEPROTECT0 ================================================== */ -/* ================================================= DMASRAMWRITEPROTECT1 ================================================== */ -/* ================================================== DMASRAMREADPROTECT0 ================================================== */ -/* ================================================== DMASRAMREADPROTECT1 ================================================== */ - - -/* =========================================================================================================================== */ -/* ================ MSPI ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= CTRL ========================================================== */ -/* ========================================================== CFG ========================================================== */ -/* ================================================ MSPI CFG CPOL [17..17] ================================================= */ -typedef enum { /*!< MSPI_CFG_CPOL */ - MSPI_CFG_CPOL_LOW = 0, /*!< LOW : Clock inactive state is low. value. */ - MSPI_CFG_CPOL_HIGH = 1, /*!< HIGH : Clock inactive state is high. value. */ -} MSPI_CFG_CPOL_Enum; - -/* ================================================ MSPI CFG CPHA [16..16] ================================================= */ -typedef enum { /*!< MSPI_CFG_CPHA */ - MSPI_CFG_CPHA_MIDDLE = 0, /*!< MIDDLE : Clock toggles in middle of data bit. value. */ - MSPI_CFG_CPHA_START = 1, /*!< START : Clock toggles at start of data bit. value. */ -} MSPI_CFG_CPHA_Enum; - -/* ================================================ MSPI CFG DEVCFG [0..3] ================================================= */ -typedef enum { /*!< MSPI_CFG_DEVCFG */ - MSPI_CFG_DEVCFG_SERIAL0 = 1, /*!< SERIAL0 : Single bit SPI flash on chip select 0 value. */ - MSPI_CFG_DEVCFG_SERIAL1 = 2, /*!< SERIAL1 : Single bit SPI flash on chip select 1 value. */ - MSPI_CFG_DEVCFG_DUAL0 = 5, /*!< DUAL0 : Dual SPI flash on chip select 0 value. */ - MSPI_CFG_DEVCFG_DUAL1 = 6, /*!< DUAL1 : Dual bit SPI flash on chip select 1 value. */ - MSPI_CFG_DEVCFG_QUAD0 = 9, /*!< QUAD0 : Quad SPI flash on chip select 0 value. */ - MSPI_CFG_DEVCFG_QUAD1 = 10, /*!< QUAD1 : Quad SPI flash on chip select 1 value. */ - MSPI_CFG_DEVCFG_OCTAL0 = 13, /*!< OCTAL0 : Octal SPI flash on chip select 0 value. */ - MSPI_CFG_DEVCFG_OCTAL1 = 14, /*!< OCTAL1 : Octal SPI flash on chip select 1 value. */ - MSPI_CFG_DEVCFG_QUADPAIRED = 15, /*!< QUADPAIRED : Dual Quad SPI flash on chip selects 0/1. value. */ - MSPI_CFG_DEVCFG_QUADPAIRED_SERIAL = 3, /*!< QUADPAIRED_SERIAL : Dual Quad SPI flash on chip selects 0/1, - but transmit in serial mode for initialization operations - value. */ -} MSPI_CFG_DEVCFG_Enum; - -/* ========================================================= ADDR ========================================================== */ -/* ========================================================= INSTR ========================================================= */ -/* ======================================================== TXFIFO ========================================================= */ -/* ======================================================== RXFIFO ========================================================= */ -/* ======================================================= TXENTRIES ======================================================= */ -/* ======================================================= RXENTRIES ======================================================= */ -/* ======================================================= THRESHOLD ======================================================= */ -/* ======================================================== MSPICFG ======================================================== */ -/* ============================================== MSPI MSPICFG CLKDIV [8..13] ============================================== */ -typedef enum { /*!< MSPI_MSPICFG_CLKDIV */ - MSPI_MSPICFG_CLKDIV_CLK24 = 2, /*!< CLK24 : 24 MHz MSPI clock value. */ - MSPI_MSPICFG_CLKDIV_CLK12 = 4, /*!< CLK12 : 12 MHz MSPI clock value. */ - MSPI_MSPICFG_CLKDIV_CLK6 = 8, /*!< CLK6 : 6 MHz MSPI clock value. */ - MSPI_MSPICFG_CLKDIV_CLK3 = 16, /*!< CLK3 : 3 MHz MSPI clock value. */ - MSPI_MSPICFG_CLKDIV_CLK1_5 = 32, /*!< CLK1_5 : 1.5 MHz MSPI clock value. */ -} MSPI_MSPICFG_CLKDIV_Enum; - -/* ============================================== MSPI MSPICFG IOMSEL [4..6] =============================================== */ -typedef enum { /*!< MSPI_MSPICFG_IOMSEL */ - MSPI_MSPICFG_IOMSEL_IOM0 = 0, /*!< IOM0 : ERROR: desc VALUE MISSING value. */ - MSPI_MSPICFG_IOMSEL_IOM1 = 1, /*!< IOM1 : ERROR: desc VALUE MISSING value. */ - MSPI_MSPICFG_IOMSEL_IOM2 = 2, /*!< IOM2 : ERROR: desc VALUE MISSING value. */ - MSPI_MSPICFG_IOMSEL_IOM3 = 3, /*!< IOM3 : ERROR: desc VALUE MISSING value. */ - MSPI_MSPICFG_IOMSEL_IOM4 = 4, /*!< IOM4 : ERROR: desc VALUE MISSING value. */ - MSPI_MSPICFG_IOMSEL_IOM5 = 5, /*!< IOM5 : ERROR: desc VALUE MISSING value. */ - MSPI_MSPICFG_IOMSEL_DISABLED = 7, /*!< DISABLED : No IOM selected. Signals always zero. value. */ -} MSPI_MSPICFG_IOMSEL_Enum; - -/* =============================================== MSPI MSPICFG TXNEG [3..3] =============================================== */ -typedef enum { /*!< MSPI_MSPICFG_TXNEG */ - MSPI_MSPICFG_TXNEG_NORMAL = 0, /*!< NORMAL : TX launched from posedge internal clock value. */ - MSPI_MSPICFG_TXNEG_NEGEDGE = 1, /*!< NEGEDGE : TX data launched from negedge of internal clock value. */ -} MSPI_MSPICFG_TXNEG_Enum; - -/* =============================================== MSPI MSPICFG RXNEG [2..2] =============================================== */ -typedef enum { /*!< MSPI_MSPICFG_RXNEG */ - MSPI_MSPICFG_RXNEG_NORMAL = 0, /*!< NORMAL : RX data sampled on posedge of internal clock value. */ - MSPI_MSPICFG_RXNEG_NEGEDGE = 1, /*!< NEGEDGE : RX data sampled on negedge of internal clock value. */ -} MSPI_MSPICFG_RXNEG_Enum; - -/* =============================================== MSPI MSPICFG RXCAP [1..1] =============================================== */ -typedef enum { /*!< MSPI_MSPICFG_RXCAP */ - MSPI_MSPICFG_RXCAP_NORMAL = 0, /*!< NORMAL : RX Capture phase aligns with CPHA setting value. */ - MSPI_MSPICFG_RXCAP_DELAY = 1, /*!< DELAY : RX Capture phase is delayed from CPHA setting by one - clock edge value. */ -} MSPI_MSPICFG_RXCAP_Enum; - -/* ============================================== MSPI MSPICFG APBCLK [0..0] =============================================== */ -typedef enum { /*!< MSPI_MSPICFG_APBCLK */ - MSPI_MSPICFG_APBCLK_DIS = 0, /*!< DIS : Disable continuous clock. value. */ - MSPI_MSPICFG_APBCLK_EN = 1, /*!< EN : Enable continuous clock. value. */ -} MSPI_MSPICFG_APBCLK_Enum; - -/* ======================================================== PADCFG ========================================================= */ -/* ======================================================= PADOUTEN ======================================================== */ -/* ============================================== MSPI PADOUTEN OUTEN [0..8] =============================================== */ -typedef enum { /*!< MSPI_PADOUTEN_OUTEN */ - MSPI_PADOUTEN_OUTEN_QUAD0 = 271, /*!< QUAD0 : Quad0 (4 data + 1 clock) value. */ - MSPI_PADOUTEN_OUTEN_QUAD1 = 496, /*!< QUAD1 : Quad1 (4 data + 1 clock) value. */ - MSPI_PADOUTEN_OUTEN_OCTAL = 511, /*!< OCTAL : Octal (8 data + 1 clock) value. */ - MSPI_PADOUTEN_OUTEN_SERIAL0 = 259, /*!< SERIAL0 : Serial (2 data + 1 clock) value. */ -} MSPI_PADOUTEN_OUTEN_Enum; - -/* ========================================================= FLASH ========================================================= */ -/* =============================================== MSPI FLASH XIPACK [2..3] ================================================ */ -typedef enum { /*!< MSPI_FLASH_XIPACK */ - MSPI_FLASH_XIPACK_NOACK = 0, /*!< NOACK : No acknowledege sent. Data IOs are tristated the first - turnaround cycle value. */ - MSPI_FLASH_XIPACK_ACK = 2, /*!< ACK : Positive acknowledege sent. Data IOs are driven to 0 the - first turnaround cycle to acknowledge XIP mode value. */ - MSPI_FLASH_XIPACK_TERMINATE = 3, /*!< TERMINATE : Negative acknowledege sent. Data IOs are driven - to 1 the first turnaround cycle to terminate XIP mode. - XIPSENDI should be reenabled for the next transfer value. */ -} MSPI_FLASH_XIPACK_Enum; - -/* ====================================================== SCRAMBLING ======================================================= */ -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ -/* ======================================================== DMACFG ========================================================= */ -/* =============================================== MSPI DMACFG DMAPRI [3..4] =============================================== */ -typedef enum { /*!< MSPI_DMACFG_DMAPRI */ - MSPI_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ - MSPI_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ - MSPI_DMACFG_DMAPRI_AUTO = 2, /*!< AUTO : Auto Priority (priority raised once TX FIFO empties or - RX FIFO fills) value. */ -} MSPI_DMACFG_DMAPRI_Enum; - -/* =============================================== MSPI DMACFG DMADIR [2..2] =============================================== */ -typedef enum { /*!< MSPI_DMACFG_DMADIR */ - MSPI_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction value. */ - MSPI_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction value. */ -} MSPI_DMACFG_DMADIR_Enum; - -/* =============================================== MSPI DMACFG DMAEN [0..1] ================================================ */ -typedef enum { /*!< MSPI_DMACFG_DMAEN */ - MSPI_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ - MSPI_DMACFG_DMAEN_EN = 3, /*!< EN : Enable HW controlled DMA Function to manage DMA to flash - devices. HW will automatically handle issuance of instruction/address - bytes based on settings in the FLASH register. value. */ -} MSPI_DMACFG_DMAEN_Enum; - -/* ======================================================== DMASTAT ======================================================== */ -/* ====================================================== DMATARGADDR ====================================================== */ -/* ====================================================== DMADEVADDR ======================================================= */ -/* ====================================================== DMATOTCOUNT ====================================================== */ -/* ======================================================= DMABCOUNT ======================================================= */ -/* ======================================================= DMATHRESH ======================================================= */ -/* ========================================================= CQCFG ========================================================= */ -/* ================================================ MSPI CQCFG CQPRI [1..1] ================================================ */ -typedef enum { /*!< MSPI_CQCFG_CQPRI */ - MSPI_CQCFG_CQPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ - MSPI_CQCFG_CQPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ -} MSPI_CQCFG_CQPRI_Enum; - -/* ================================================ MSPI CQCFG CQEN [0..0] ================================================= */ -typedef enum { /*!< MSPI_CQCFG_CQEN */ - MSPI_CQCFG_CQEN_DIS = 0, /*!< DIS : Disable CQ Function value. */ - MSPI_CQCFG_CQEN_EN = 1, /*!< EN : Enable CQ Function value. */ -} MSPI_CQCFG_CQEN_Enum; - -/* ======================================================== CQADDR ========================================================= */ -/* ======================================================== CQSTAT ========================================================= */ -/* ======================================================== CQFLAGS ======================================================== */ -/* ============================================= MSPI CQFLAGS CQFLAGS [0..15] ============================================== */ -typedef enum { /*!< MSPI_CQFLAGS_CQFLAGS */ - MSPI_CQFLAGS_CQFLAGS_STOP = 32768, /*!< STOP : CQ Stop Flag. When set, CQ processing will complete. - value. */ - MSPI_CQFLAGS_CQFLAGS_CQIDX = 16384, /*!< CQIDX : CQ Index Pointers (CURIDX/ENDIDX) match. value. */ - MSPI_CQFLAGS_CQFLAGS_DMACPL = 2048, /*!< DMACPL : DMA Complete Status (hardwired DMACPL bit in DMASTAT) - value. */ - MSPI_CQFLAGS_CQFLAGS_CMDCPL = 1024, /*!< CMDCPL : PIO Operation completed (STATUS bit in CTRL register) - value. */ - MSPI_CQFLAGS_CQFLAGS_IOM1READY = 512, /*!< IOM1READY : IOM Buffer 1 Ready Status (from selected IOM). This - status is the result of XOR'ing the IOM0START with the - incoming status from the IOM. When high, MSPI can send - to the buffer. value. */ - MSPI_CQFLAGS_CQFLAGS_IOM0READY = 256, /*!< IOM0READY : IOM Buffer 0 Ready Status (from selected IOM). This - status is the result of XOR'ing the IOM0START with the - incoming status from the IOM. When high, MSPI can send - to the buffer. value. */ - MSPI_CQFLAGS_CQFLAGS_SWFLAG7 = 128, /*!< SWFLAG7 : Software flag 7. Can be used by software to start/pause - operations value. */ - MSPI_CQFLAGS_CQFLAGS_SWFLAG6 = 64, /*!< SWFLAG6 : Software flag 6. Can be used by software to start/pause - operatoins value. */ - MSPI_CQFLAGS_CQFLAGS_SWFLAG5 = 32, /*!< SWFLAG5 : Software flag 5. Can be used by software to start/pause - operations value. */ - MSPI_CQFLAGS_CQFLAGS_SWFLAG4 = 16, /*!< SWFLAG4 : Software flag 4. Can be used by software to start/pause - operatoins value. */ - MSPI_CQFLAGS_CQFLAGS_SWFLAG3 = 8, /*!< SWFLAG3 : Software flag 3. Can be used by software to start/pause - operations value. */ - MSPI_CQFLAGS_CQFLAGS_SWFLAG2 = 4, /*!< SWFLAG2 : Software flag 2. Can be used by software to start/pause - operatoins value. */ - MSPI_CQFLAGS_CQFLAGS_SWFLAG1 = 2, /*!< SWFLAG1 : Software flag 1. Can be used by software to start/pause - operations value. */ - MSPI_CQFLAGS_CQFLAGS_SWFLAG0 = 1, /*!< SWFLAG0 : Software flag 0. Can be used by software to start/pause - operatoins value. */ -} MSPI_CQFLAGS_CQFLAGS_Enum; - -/* ====================================================== CQSETCLEAR ======================================================= */ -/* ======================================================== CQPAUSE ======================================================== */ -/* ============================================== MSPI CQPAUSE CQMASK [0..15] ============================================== */ -typedef enum { /*!< MSPI_CQPAUSE_CQMASK */ - MSPI_CQPAUSE_CQMASK_STOP = 32768, /*!< STOP : CQ Stop Flag. When set, CQ processing will complete. - value. */ - MSPI_CQPAUSE_CQMASK_CQIDX = 16384, /*!< CQIDX : CQ Index Pointers (CURIDX/ENDIDX) match. value. */ - MSPI_CQPAUSE_CQMASK_DMACPL = 2048, /*!< DMACPL : DMA Complete Status (hardwired DMACPL bit in DMASTAT) - value. */ - MSPI_CQPAUSE_CQMASK_CMDCPL = 1024, /*!< CMDCPL : PIO Operation completed (STATUS bit in CTRL register) - value. */ - MSPI_CQPAUSE_CQMASK_IOM1READY = 512, /*!< IOM1READY : IOM Buffer 1 Ready Status (from selected IOM). This - status is the result of XOR'ing the IOM0START with the - incoming status from the IOM. When high, MSPI can send - to the buffer. value. */ - MSPI_CQPAUSE_CQMASK_IOM0READY = 256, /*!< IOM0READY : IOM Buffer 0 Ready Status (from selected IOM). This - status is the result of XOR'ing the IOM0START with the - incoming status from the IOM. When high, MSPI can send - to the buffer. value. */ - MSPI_CQPAUSE_CQMASK_SWFLAG7 = 128, /*!< SWFLAG7 : Software flag 7. Can be used by software to start/pause - operations value. */ - MSPI_CQPAUSE_CQMASK_SWFLAG6 = 64, /*!< SWFLAG6 : Software flag 6. Can be used by software to start/pause - operatoins value. */ - MSPI_CQPAUSE_CQMASK_SWFLAG5 = 32, /*!< SWFLAG5 : Software flag 5. Can be used by software to start/pause - operations value. */ - MSPI_CQPAUSE_CQMASK_SWFLAG4 = 16, /*!< SWFLAG4 : Software flag 4. Can be used by software to start/pause - operatoins value. */ - MSPI_CQPAUSE_CQMASK_SWFLAG3 = 8, /*!< SWFLAG3 : Software flag 3. Can be used by software to start/pause - operations value. */ - MSPI_CQPAUSE_CQMASK_SWFLAG2 = 4, /*!< SWFLAG2 : Software flag 2. Can be used by software to start/pause - operatoins value. */ - MSPI_CQPAUSE_CQMASK_SWFLAG1 = 2, /*!< SWFLAG1 : Software flag 1. Can be used by software to start/pause - operations value. */ - MSPI_CQPAUSE_CQMASK_SWFLAG0 = 1, /*!< SWFLAG0 : Software flag 0. Can be used by software to start/pause - operatoins value. */ -} MSPI_CQPAUSE_CQMASK_Enum; - -/* ======================================================= CQCURIDX ======================================================== */ -/* ======================================================= CQENDIDX ======================================================== */ - - -/* =========================================================================================================================== */ -/* ================ PDM ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= PCFG ========================================================== */ -/* =============================================== PDM PCFG LRSWAP [31..31] ================================================ */ -typedef enum { /*!< PDM_PCFG_LRSWAP */ - PDM_PCFG_LRSWAP_EN = 1, /*!< EN : Swap left and right channels (FIFO Read RIGHT_LEFT). value. */ - PDM_PCFG_LRSWAP_NOSWAP = 0, /*!< NOSWAP : No channel swapping (IFO Read LEFT_RIGHT). value. */ -} PDM_PCFG_LRSWAP_Enum; - -/* ============================================== PDM PCFG PGARIGHT [26..30] =============================================== */ -typedef enum { /*!< PDM_PCFG_PGARIGHT */ - PDM_PCFG_PGARIGHT_P405DB = 31, /*!< P405DB : 40.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P390DB = 30, /*!< P390DB : 39.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P375DB = 29, /*!< P375DB : 37.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P360DB = 28, /*!< P360DB : 36.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P345DB = 27, /*!< P345DB : 34.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P330DB = 26, /*!< P330DB : 33.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P315DB = 25, /*!< P315DB : 31.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P300DB = 24, /*!< P300DB : 30.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P285DB = 23, /*!< P285DB : 28.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P270DB = 22, /*!< P270DB : 27.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P255DB = 21, /*!< P255DB : 25.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P240DB = 20, /*!< P240DB : 24.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P225DB = 19, /*!< P225DB : 22.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P210DB = 18, /*!< P210DB : 21.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P195DB = 17, /*!< P195DB : 19.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P180DB = 16, /*!< P180DB : 18.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P165DB = 15, /*!< P165DB : 16.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P150DB = 14, /*!< P150DB : 15.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P135DB = 13, /*!< P135DB : 13.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P120DB = 12, /*!< P120DB : 12.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P105DB = 11, /*!< P105DB : 10.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P90DB = 10, /*!< P90DB : 9.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P75DB = 9, /*!< P75DB : 7.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P60DB = 8, /*!< P60DB : 6.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P45DB = 7, /*!< P45DB : 4.5 db gain. value. */ - PDM_PCFG_PGARIGHT_P30DB = 6, /*!< P30DB : 3.0 db gain. value. */ - PDM_PCFG_PGARIGHT_P15DB = 5, /*!< P15DB : 1.5 db gain. value. */ - PDM_PCFG_PGARIGHT_0DB = 4, /*!< 0DB : 0.0 db gain. value. */ - PDM_PCFG_PGARIGHT_M15DB = 3, /*!< M15DB : -1.5 db gain. value. */ - PDM_PCFG_PGARIGHT_M300DB = 2, /*!< M300DB : -3.0 db gain. value. */ - PDM_PCFG_PGARIGHT_M45DB = 1, /*!< M45DB : -4.5 db gain. value. */ - PDM_PCFG_PGARIGHT_M60DB = 0, /*!< M60DB : -6.0 db gain. value. */ -} PDM_PCFG_PGARIGHT_Enum; - -/* =============================================== PDM PCFG PGALEFT [21..25] =============================================== */ -typedef enum { /*!< PDM_PCFG_PGALEFT */ - PDM_PCFG_PGALEFT_P405DB = 31, /*!< P405DB : 40.5 db gain. value. */ - PDM_PCFG_PGALEFT_P390DB = 30, /*!< P390DB : 39.0 db gain. value. */ - PDM_PCFG_PGALEFT_P375DB = 29, /*!< P375DB : 37.5 db gain. value. */ - PDM_PCFG_PGALEFT_P360DB = 28, /*!< P360DB : 36.0 db gain. value. */ - PDM_PCFG_PGALEFT_P345DB = 27, /*!< P345DB : 34.5 db gain. value. */ - PDM_PCFG_PGALEFT_P330DB = 26, /*!< P330DB : 33.0 db gain. value. */ - PDM_PCFG_PGALEFT_P315DB = 25, /*!< P315DB : 31.5 db gain. value. */ - PDM_PCFG_PGALEFT_P300DB = 24, /*!< P300DB : 30.0 db gain. value. */ - PDM_PCFG_PGALEFT_P285DB = 23, /*!< P285DB : 28.5 db gain. value. */ - PDM_PCFG_PGALEFT_P270DB = 22, /*!< P270DB : 27.0 db gain. value. */ - PDM_PCFG_PGALEFT_P255DB = 21, /*!< P255DB : 25.5 db gain. value. */ - PDM_PCFG_PGALEFT_P240DB = 20, /*!< P240DB : 24.0 db gain. value. */ - PDM_PCFG_PGALEFT_P225DB = 19, /*!< P225DB : 22.5 db gain. value. */ - PDM_PCFG_PGALEFT_P210DB = 18, /*!< P210DB : 21.0 db gain. value. */ - PDM_PCFG_PGALEFT_P195DB = 17, /*!< P195DB : 19.5 db gain. value. */ - PDM_PCFG_PGALEFT_P180DB = 16, /*!< P180DB : 18.0 db gain. value. */ - PDM_PCFG_PGALEFT_P165DB = 15, /*!< P165DB : 16.5 db gain. value. */ - PDM_PCFG_PGALEFT_P150DB = 14, /*!< P150DB : 15.0 db gain. value. */ - PDM_PCFG_PGALEFT_P135DB = 13, /*!< P135DB : 13.5 db gain. value. */ - PDM_PCFG_PGALEFT_P120DB = 12, /*!< P120DB : 12.0 db gain. value. */ - PDM_PCFG_PGALEFT_P105DB = 11, /*!< P105DB : 10.5 db gain. value. */ - PDM_PCFG_PGALEFT_P90DB = 10, /*!< P90DB : 9.0 db gain. value. */ - PDM_PCFG_PGALEFT_P75DB = 9, /*!< P75DB : 7.5 db gain. value. */ - PDM_PCFG_PGALEFT_P60DB = 8, /*!< P60DB : 6.0 db gain. value. */ - PDM_PCFG_PGALEFT_P45DB = 7, /*!< P45DB : 4.5 db gain. value. */ - PDM_PCFG_PGALEFT_P30DB = 6, /*!< P30DB : 3.0 db gain. value. */ - PDM_PCFG_PGALEFT_P15DB = 5, /*!< P15DB : 1.5 db gain. value. */ - PDM_PCFG_PGALEFT_0DB = 4, /*!< 0DB : 0.0 db gain. value. */ - PDM_PCFG_PGALEFT_M15DB = 3, /*!< M15DB : -1.5 db gain. value. */ - PDM_PCFG_PGALEFT_M300DB = 2, /*!< M300DB : -3.0 db gain. value. */ - PDM_PCFG_PGALEFT_M45DB = 1, /*!< M45DB : -4.5 db gain. value. */ - PDM_PCFG_PGALEFT_M60DB = 0, /*!< M60DB : -6.0 db gain. value. */ -} PDM_PCFG_PGALEFT_Enum; - -/* =============================================== PDM PCFG MCLKDIV [17..18] =============================================== */ -typedef enum { /*!< PDM_PCFG_MCLKDIV */ - PDM_PCFG_MCLKDIV_MCKDIV4 = 3, /*!< MCKDIV4 : Divide input clock by 4 value. */ - PDM_PCFG_MCLKDIV_MCKDIV3 = 2, /*!< MCKDIV3 : Divide input clock by 3 value. */ - PDM_PCFG_MCLKDIV_MCKDIV2 = 1, /*!< MCKDIV2 : Divide input clock by 2 value. */ - PDM_PCFG_MCLKDIV_MCKDIV1 = 0, /*!< MCKDIV1 : Divide input clock by 1 value. */ -} PDM_PCFG_MCLKDIV_Enum; - -/* ================================================ PDM PCFG ADCHPD [9..9] ================================================= */ -typedef enum { /*!< PDM_PCFG_ADCHPD */ - PDM_PCFG_ADCHPD_EN = 1, /*!< EN : Enable high pass filter. value. */ - PDM_PCFG_ADCHPD_DIS = 0, /*!< DIS : Disable high pass filter. value. */ -} PDM_PCFG_ADCHPD_Enum; - -/* =============================================== PDM PCFG SOFTMUTE [1..1] ================================================ */ -typedef enum { /*!< PDM_PCFG_SOFTMUTE */ - PDM_PCFG_SOFTMUTE_EN = 1, /*!< EN : Enable Soft Mute. value. */ - PDM_PCFG_SOFTMUTE_DIS = 0, /*!< DIS : Disable Soft Mute. value. */ -} PDM_PCFG_SOFTMUTE_Enum; - -/* =============================================== PDM PCFG PDMCOREEN [0..0] =============================================== */ -typedef enum { /*!< PDM_PCFG_PDMCOREEN */ - PDM_PCFG_PDMCOREEN_EN = 1, /*!< EN : Enable Data Streaming. value. */ - PDM_PCFG_PDMCOREEN_DIS = 0, /*!< DIS : Disable Data Streaming. value. */ -} PDM_PCFG_PDMCOREEN_Enum; - -/* ========================================================= VCFG ========================================================== */ -/* =============================================== PDM VCFG IOCLKEN [31..31] =============================================== */ -typedef enum { /*!< PDM_VCFG_IOCLKEN */ - PDM_VCFG_IOCLKEN_DIS = 0, /*!< DIS : Disable FIFO read. value. */ - PDM_VCFG_IOCLKEN_EN = 1, /*!< EN : Enable FIFO read. value. */ -} PDM_VCFG_IOCLKEN_Enum; - -/* ================================================ PDM VCFG RSTB [30..30] ================================================= */ -typedef enum { /*!< PDM_VCFG_RSTB */ - PDM_VCFG_RSTB_RESET = 0, /*!< RESET : Reset the core. value. */ - PDM_VCFG_RSTB_NORM = 1, /*!< NORM : Enable the core. value. */ -} PDM_VCFG_RSTB_Enum; - -/* ============================================== PDM VCFG PDMCLKSEL [27..29] ============================================== */ -typedef enum { /*!< PDM_VCFG_PDMCLKSEL */ - PDM_VCFG_PDMCLKSEL_DISABLE = 0, /*!< DISABLE : Static value. value. */ - PDM_VCFG_PDMCLKSEL_12MHz = 1, /*!< 12MHz : PDM clock is 12 MHz. value. */ - PDM_VCFG_PDMCLKSEL_6MHz = 2, /*!< 6MHz : PDM clock is 6 MHz. value. */ - PDM_VCFG_PDMCLKSEL_3MHz = 3, /*!< 3MHz : PDM clock is 3 MHz. value. */ - PDM_VCFG_PDMCLKSEL_1_5MHz = 4, /*!< 1_5MHz : PDM clock is 1.5 MHz. value. */ - PDM_VCFG_PDMCLKSEL_750KHz = 5, /*!< 750KHz : PDM clock is 750 KHz. value. */ - PDM_VCFG_PDMCLKSEL_375KHz = 6, /*!< 375KHz : PDM clock is 375 KHz. value. */ - PDM_VCFG_PDMCLKSEL_187KHz = 7, /*!< 187KHz : PDM clock is 187.5 KHz. value. */ -} PDM_VCFG_PDMCLKSEL_Enum; - -/* ============================================== PDM VCFG PDMCLKEN [26..26] =============================================== */ -typedef enum { /*!< PDM_VCFG_PDMCLKEN */ - PDM_VCFG_PDMCLKEN_DIS = 0, /*!< DIS : Disable serial clock. value. */ - PDM_VCFG_PDMCLKEN_EN = 1, /*!< EN : Enable serial clock. value. */ -} PDM_VCFG_PDMCLKEN_Enum; - -/* ================================================ PDM VCFG I2SEN [20..20] ================================================ */ -typedef enum { /*!< PDM_VCFG_I2SEN */ - PDM_VCFG_I2SEN_DIS = 0, /*!< DIS : Disable I2S interface. value. */ - PDM_VCFG_I2SEN_EN = 1, /*!< EN : Enable I2S interface. value. */ -} PDM_VCFG_I2SEN_Enum; - -/* =============================================== PDM VCFG BCLKINV [19..19] =============================================== */ -typedef enum { /*!< PDM_VCFG_BCLKINV */ - PDM_VCFG_BCLKINV_INV = 0, /*!< INV : BCLK inverted. value. */ - PDM_VCFG_BCLKINV_NORM = 1, /*!< NORM : BCLK not inverted. value. */ -} PDM_VCFG_BCLKINV_Enum; - -/* ============================================== PDM VCFG DMICKDEL [17..17] =============================================== */ -typedef enum { /*!< PDM_VCFG_DMICKDEL */ - PDM_VCFG_DMICKDEL_0CYC = 0, /*!< 0CYC : No delay. value. */ - PDM_VCFG_DMICKDEL_1CYC = 1, /*!< 1CYC : 1 cycle delay. value. */ -} PDM_VCFG_DMICKDEL_Enum; - -/* ================================================ PDM VCFG SELAP [16..16] ================================================ */ -typedef enum { /*!< PDM_VCFG_SELAP */ - PDM_VCFG_SELAP_I2S = 1, /*!< I2S : Clock source from I2S BCLK. value. */ - PDM_VCFG_SELAP_INTERNAL = 0, /*!< INTERNAL : Clock source from internal clock generator. value. */ -} PDM_VCFG_SELAP_Enum; - -/* ================================================ PDM VCFG PCMPACK [8..8] ================================================ */ -typedef enum { /*!< PDM_VCFG_PCMPACK */ - PDM_VCFG_PCMPACK_DIS = 0, /*!< DIS : Disable PCM packing. value. */ - PDM_VCFG_PCMPACK_EN = 1, /*!< EN : Enable PCM packing. value. */ -} PDM_VCFG_PCMPACK_Enum; - -/* ================================================= PDM VCFG CHSET [3..4] ================================================= */ -typedef enum { /*!< PDM_VCFG_CHSET */ - PDM_VCFG_CHSET_DIS = 0, /*!< DIS : Channel disabled. value. */ - PDM_VCFG_CHSET_LEFT = 1, /*!< LEFT : Mono left channel. value. */ - PDM_VCFG_CHSET_RIGHT = 2, /*!< RIGHT : Mono right channel. value. */ - PDM_VCFG_CHSET_STEREO = 3, /*!< STEREO : Stereo channels. value. */ -} PDM_VCFG_CHSET_Enum; - -/* ======================================================= VOICESTAT ======================================================= */ -/* ======================================================= FIFOREAD ======================================================== */ -/* ======================================================= FIFOFLUSH ======================================================= */ -/* ======================================================== FIFOTHR ======================================================== */ -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ -/* ======================================================= DMATRIGEN ======================================================= */ -/* ====================================================== DMATRIGSTAT ====================================================== */ -/* ======================================================== DMACFG ========================================================= */ -/* =============================================== PDM DMACFG DMAPRI [8..8] ================================================ */ -typedef enum { /*!< PDM_DMACFG_DMAPRI */ - PDM_DMACFG_DMAPRI_LOW = 0, /*!< LOW : Low Priority (service as best effort) value. */ - PDM_DMACFG_DMAPRI_HIGH = 1, /*!< HIGH : High Priority (service immediately) value. */ -} PDM_DMACFG_DMAPRI_Enum; - -/* =============================================== PDM DMACFG DMADIR [2..2] ================================================ */ -typedef enum { /*!< PDM_DMACFG_DMADIR */ - PDM_DMACFG_DMADIR_P2M = 0, /*!< P2M : Peripheral to Memory (SRAM) transaction. THe PDM module - will only DMA to memory. value. */ - PDM_DMACFG_DMADIR_M2P = 1, /*!< M2P : Memory to Peripheral transaction. Not available for PDM - module value. */ -} PDM_DMACFG_DMADIR_Enum; - -/* ================================================ PDM DMACFG DMAEN [0..0] ================================================ */ -typedef enum { /*!< PDM_DMACFG_DMAEN */ - PDM_DMACFG_DMAEN_DIS = 0, /*!< DIS : Disable DMA Function value. */ - PDM_DMACFG_DMAEN_EN = 1, /*!< EN : Enable DMA Function value. */ -} PDM_DMACFG_DMAEN_Enum; - -/* ====================================================== DMATOTCOUNT ====================================================== */ -/* ====================================================== DMATARGADDR ====================================================== */ -/* ======================================================== DMASTAT ======================================================== */ - - -/* =========================================================================================================================== */ -/* ================ PWRCTRL ================ */ -/* =========================================================================================================================== */ - -/* ======================================================= SUPPLYSRC ======================================================= */ -/* ========================================== PWRCTRL SUPPLYSRC BLEBUCKEN [0..0] =========================================== */ -typedef enum { /*!< PWRCTRL_SUPPLYSRC_BLEBUCKEN */ - PWRCTRL_SUPPLYSRC_BLEBUCKEN_EN = 1, /*!< EN : Enable the BLE Buck. value. */ - PWRCTRL_SUPPLYSRC_BLEBUCKEN_DIS = 0, /*!< DIS : Disable the BLE Buck. value. */ -} PWRCTRL_SUPPLYSRC_BLEBUCKEN_Enum; - -/* ===================================================== SUPPLYSTATUS ====================================================== */ -/* ========================================= PWRCTRL SUPPLYSTATUS BLEBUCKON [1..1] ========================================= */ -typedef enum { /*!< PWRCTRL_SUPPLYSTATUS_BLEBUCKON */ - PWRCTRL_SUPPLYSTATUS_BLEBUCKON_LDO = 0, /*!< LDO : Indicates the the LDO is supplying the BLE/Burst power - domain value. */ - PWRCTRL_SUPPLYSTATUS_BLEBUCKON_BUCK = 1, /*!< BUCK : Indicates the the Buck is supplying the BLE/Burst power - domain value. */ -} PWRCTRL_SUPPLYSTATUS_BLEBUCKON_Enum; - -/* ======================================== PWRCTRL SUPPLYSTATUS SIMOBUCKON [0..0] ========================================= */ -typedef enum { /*!< PWRCTRL_SUPPLYSTATUS_SIMOBUCKON */ - PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_OFF = 0, /*!< OFF : Indicates the the SIMO Buck is OFF. value. */ - PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_ON = 1, /*!< ON : Indicates the the SIMO Buck is ON. value. */ -} PWRCTRL_SUPPLYSTATUS_SIMOBUCKON_Enum; - -/* ======================================================= DEVPWREN ======================================================== */ -/* =========================================== PWRCTRL DEVPWREN PWRBLEL [13..13] =========================================== */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRBLEL */ - PWRCTRL_DEVPWREN_PWRBLEL_EN = 1, /*!< EN : Power up BLE controller value. */ - PWRCTRL_DEVPWREN_PWRBLEL_DIS = 0, /*!< DIS : Power down BLE controller value. */ -} PWRCTRL_DEVPWREN_PWRBLEL_Enum; - -/* =========================================== PWRCTRL DEVPWREN PWRPDM [12..12] ============================================ */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRPDM */ - PWRCTRL_DEVPWREN_PWRPDM_EN = 1, /*!< EN : Power up PDM value. */ - PWRCTRL_DEVPWREN_PWRPDM_DIS = 0, /*!< DIS : Power down PDM value. */ -} PWRCTRL_DEVPWREN_PWRPDM_Enum; - -/* =========================================== PWRCTRL DEVPWREN PWRMSPI [11..11] =========================================== */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRMSPI */ - PWRCTRL_DEVPWREN_PWRMSPI_EN = 1, /*!< EN : Power up MSPI value. */ - PWRCTRL_DEVPWREN_PWRMSPI_DIS = 0, /*!< DIS : Power down MSPI value. */ -} PWRCTRL_DEVPWREN_PWRMSPI_Enum; - -/* ========================================== PWRCTRL DEVPWREN PWRSCARD [10..10] =========================================== */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRSCARD */ - PWRCTRL_DEVPWREN_PWRSCARD_EN = 1, /*!< EN : Power up SCARD value. */ - PWRCTRL_DEVPWREN_PWRSCARD_DIS = 0, /*!< DIS : Power down SCARD value. */ -} PWRCTRL_DEVPWREN_PWRSCARD_Enum; - -/* ============================================ PWRCTRL DEVPWREN PWRADC [9..9] ============================================= */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRADC */ - PWRCTRL_DEVPWREN_PWRADC_EN = 1, /*!< EN : Power up ADC value. */ - PWRCTRL_DEVPWREN_PWRADC_DIS = 0, /*!< DIS : Power Down ADC value. */ -} PWRCTRL_DEVPWREN_PWRADC_Enum; - -/* =========================================== PWRCTRL DEVPWREN PWRUART1 [8..8] ============================================ */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRUART1 */ - PWRCTRL_DEVPWREN_PWRUART1_EN = 1, /*!< EN : Power up UART 1 value. */ - PWRCTRL_DEVPWREN_PWRUART1_DIS = 0, /*!< DIS : Power down UART 1 value. */ -} PWRCTRL_DEVPWREN_PWRUART1_Enum; - -/* =========================================== PWRCTRL DEVPWREN PWRUART0 [7..7] ============================================ */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRUART0 */ - PWRCTRL_DEVPWREN_PWRUART0_EN = 1, /*!< EN : Power up UART 0 value. */ - PWRCTRL_DEVPWREN_PWRUART0_DIS = 0, /*!< DIS : Power down UART 0 value. */ -} PWRCTRL_DEVPWREN_PWRUART0_Enum; - -/* ============================================ PWRCTRL DEVPWREN PWRIOM5 [6..6] ============================================ */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM5 */ - PWRCTRL_DEVPWREN_PWRIOM5_EN = 1, /*!< EN : Power up IO Master 5 value. */ - PWRCTRL_DEVPWREN_PWRIOM5_DIS = 0, /*!< DIS : Power down IO Master 5 value. */ -} PWRCTRL_DEVPWREN_PWRIOM5_Enum; - -/* ============================================ PWRCTRL DEVPWREN PWRIOM4 [5..5] ============================================ */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM4 */ - PWRCTRL_DEVPWREN_PWRIOM4_EN = 1, /*!< EN : Power up IO Master 4 value. */ - PWRCTRL_DEVPWREN_PWRIOM4_DIS = 0, /*!< DIS : Power down IO Master 4 value. */ -} PWRCTRL_DEVPWREN_PWRIOM4_Enum; - -/* ============================================ PWRCTRL DEVPWREN PWRIOM3 [4..4] ============================================ */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM3 */ - PWRCTRL_DEVPWREN_PWRIOM3_EN = 1, /*!< EN : Power up IO Master 3 value. */ - PWRCTRL_DEVPWREN_PWRIOM3_DIS = 0, /*!< DIS : Power down IO Master 3 value. */ -} PWRCTRL_DEVPWREN_PWRIOM3_Enum; - -/* ============================================ PWRCTRL DEVPWREN PWRIOM2 [3..3] ============================================ */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM2 */ - PWRCTRL_DEVPWREN_PWRIOM2_EN = 1, /*!< EN : Power up IO Master 2 value. */ - PWRCTRL_DEVPWREN_PWRIOM2_DIS = 0, /*!< DIS : Power down IO Master 2 value. */ -} PWRCTRL_DEVPWREN_PWRIOM2_Enum; - -/* ============================================ PWRCTRL DEVPWREN PWRIOM1 [2..2] ============================================ */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM1 */ - PWRCTRL_DEVPWREN_PWRIOM1_EN = 1, /*!< EN : Power up IO Master 1 value. */ - PWRCTRL_DEVPWREN_PWRIOM1_DIS = 0, /*!< DIS : Power down IO Master 1 value. */ -} PWRCTRL_DEVPWREN_PWRIOM1_Enum; - -/* ============================================ PWRCTRL DEVPWREN PWRIOM0 [1..1] ============================================ */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOM0 */ - PWRCTRL_DEVPWREN_PWRIOM0_EN = 1, /*!< EN : Power up IO Master 0 value. */ - PWRCTRL_DEVPWREN_PWRIOM0_DIS = 0, /*!< DIS : Power down IO Master 0 value. */ -} PWRCTRL_DEVPWREN_PWRIOM0_Enum; - -/* ============================================ PWRCTRL DEVPWREN PWRIOS [0..0] ============================================= */ -typedef enum { /*!< PWRCTRL_DEVPWREN_PWRIOS */ - PWRCTRL_DEVPWREN_PWRIOS_EN = 1, /*!< EN : Power up IO slave value. */ - PWRCTRL_DEVPWREN_PWRIOS_DIS = 0, /*!< DIS : Power down IO slave value. */ -} PWRCTRL_DEVPWREN_PWRIOS_Enum; - -/* ===================================================== MEMPWDINSLEEP ===================================================== */ -/* ====================================== PWRCTRL MEMPWDINSLEEP CACHEPWDSLP [31..31] ======================================= */ -typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP */ - PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_EN = 1, /*!< EN : Power down cache in deep sleep value. */ - PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_DIS = 0, /*!< DIS : Retain cache in deep sleep value. */ -} PWRCTRL_MEMPWDINSLEEP_CACHEPWDSLP_Enum; - -/* ====================================== PWRCTRL MEMPWDINSLEEP FLASH1PWDSLP [14..14] ====================================== */ -typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP */ - PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_EN = 1, /*!< EN : Flash1 is powered down during deepsleep value. */ - PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_DIS = 0, /*!< DIS : Flash1 is kept powered on during deepsleep value. */ -} PWRCTRL_MEMPWDINSLEEP_FLASH1PWDSLP_Enum; - -/* ====================================== PWRCTRL MEMPWDINSLEEP FLASH0PWDSLP [13..13] ====================================== */ -typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP */ - PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_EN = 1, /*!< EN : Flash0 is powered down during deepsleep value. */ - PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_DIS = 0, /*!< DIS : Flash0 is kept powered on during deepsleep value. */ -} PWRCTRL_MEMPWDINSLEEP_FLASH0PWDSLP_Enum; - -/* ======================================= PWRCTRL MEMPWDINSLEEP SRAMPWDSLP [3..12] ======================================== */ -typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_NONE = 0, /*!< NONE : All banks retained value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP0 = 1, /*!< GROUP0 : SRAM GROUP0 powered down (64KB-96KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP1 = 2, /*!< GROUP1 : SRAM GROUP1 powered down (96KB-128KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP2 = 4, /*!< GROUP2 : SRAM GROUP2 powered down (128KB-160KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP3 = 8, /*!< GROUP3 : SRAM GROUP3 powered down (160KB-192KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP4 = 16, /*!< GROUP4 : SRAM GROUP4 powered down (192KB-224KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP5 = 32, /*!< GROUP5 : SRAM GROUP5 powered down (224KB-256KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP6 = 64, /*!< GROUP6 : SRAM GROUP6 powered down (256KB-288KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP7 = 128,/*!< GROUP7 : SRAM GROUP7 powered down (288KB-320KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP8 = 256,/*!< GROUP8 : SRAM GROUP8 powered down (320KB-352KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_GROUP9 = 512,/*!< GROUP9 : SRAM GROUP9 powered down (352KB-384KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_SRAM64K = 3, /*!< SRAM64K : Powerdown lower 64k SRAM (64KB-128KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_SRAM128K = 15,/*!< SRAM128K : Powerdown lower 128k SRAM (64KB-192KB) value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER32K = 1022,/*!< ALLBUTLOWER32K : All SRAM banks but lower 32k powered down (96KB-384KB). - value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER64K = 1020,/*!< ALLBUTLOWER64K : All banks but lower 64k powered down. value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALLBUTLOWER128K = 1008,/*!< ALLBUTLOWER128K : All banks but lower 128k powered down. value. */ - PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_ALL = 1023, /*!< ALL : All banks powered down. value. */ -} PWRCTRL_MEMPWDINSLEEP_SRAMPWDSLP_Enum; - -/* ======================================== PWRCTRL MEMPWDINSLEEP DTCMPWDSLP [0..2] ======================================== */ -typedef enum { /*!< PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP */ - PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_NONE = 0, /*!< NONE : All DTCM retained value. */ - PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_GROUP0DTCM0 = 1,/*!< GROUP0DTCM0 : Group0_DTCM0 powered down in deep sleep (0KB-8KB) - value. */ - PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_GROUP0DTCM1 = 2,/*!< GROUP0DTCM1 : Group0_DTCM1 powered down in deep sleep (8KB-32KB) - value. */ - PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_GROUP0 = 3, /*!< GROUP0 : Both DTCMs in group0 are powered down in deep sleep - (0KB-32KB) value. */ - PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_ALLBUTGROUP0DTCM0 = 6,/*!< ALLBUTGROUP0DTCM0 : Group1 and Group0_DTCM1 are powered down - in deep sleep (8KB-64KB) value. */ - PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_GROUP1 = 4, /*!< GROUP1 : Group1 DTCM powered down in deep sleep (32KB-64KB) - value. */ - PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_ALL = 7, /*!< ALL : All DTCMs powered down in deep sleep (0KB-64KB) value. */ -} PWRCTRL_MEMPWDINSLEEP_DTCMPWDSLP_Enum; - -/* ======================================================= MEMPWREN ======================================================== */ -/* =========================================== PWRCTRL MEMPWREN CACHEB2 [31..31] =========================================== */ -typedef enum { /*!< PWRCTRL_MEMPWREN_CACHEB2 */ - PWRCTRL_MEMPWREN_CACHEB2_EN = 1, /*!< EN : Power up Cache Bank 2 value. */ - PWRCTRL_MEMPWREN_CACHEB2_DIS = 0, /*!< DIS : Power down Cache Bank 2 value. */ -} PWRCTRL_MEMPWREN_CACHEB2_Enum; - -/* =========================================== PWRCTRL MEMPWREN CACHEB0 [30..30] =========================================== */ -typedef enum { /*!< PWRCTRL_MEMPWREN_CACHEB0 */ - PWRCTRL_MEMPWREN_CACHEB0_EN = 1, /*!< EN : Power up Cache Bank 0 value. */ - PWRCTRL_MEMPWREN_CACHEB0_DIS = 0, /*!< DIS : Power down Cache Bank 0 value. */ -} PWRCTRL_MEMPWREN_CACHEB0_Enum; - -/* =========================================== PWRCTRL MEMPWREN FLASH1 [14..14] ============================================ */ -typedef enum { /*!< PWRCTRL_MEMPWREN_FLASH1 */ - PWRCTRL_MEMPWREN_FLASH1_EN = 1, /*!< EN : Power up Flash1 value. */ - PWRCTRL_MEMPWREN_FLASH1_DIS = 0, /*!< DIS : Power down Flash1 value. */ -} PWRCTRL_MEMPWREN_FLASH1_Enum; - -/* =========================================== PWRCTRL MEMPWREN FLASH0 [13..13] ============================================ */ -typedef enum { /*!< PWRCTRL_MEMPWREN_FLASH0 */ - PWRCTRL_MEMPWREN_FLASH0_EN = 1, /*!< EN : Power up Flash0 value. */ - PWRCTRL_MEMPWREN_FLASH0_DIS = 0, /*!< DIS : Power down Flash0 value. */ -} PWRCTRL_MEMPWREN_FLASH0_Enum; - -/* ============================================= PWRCTRL MEMPWREN SRAM [3..12] ============================================= */ -typedef enum { /*!< PWRCTRL_MEMPWREN_SRAM */ - PWRCTRL_MEMPWREN_SRAM_NONE = 0, /*!< NONE : Do not power ON any of the SRAM banks value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP0 = 1, /*!< GROUP0 : Power ON only SRAM group0 (0KB-32KB) value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP1 = 2, /*!< GROUP1 : Power ON only SRAM group1 (32KB-64KB) value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP2 = 4, /*!< GROUP2 : Power ON only SRAM group2 (64KB-96KB) value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP3 = 8, /*!< GROUP3 : Power ON only SRAM group3 (96KB-128KB) value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP4 = 16, /*!< GROUP4 : Power ON only SRAM group4 (128KB-160KB) value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP5 = 32, /*!< GROUP5 : Power ON only SRAM group5 (160KB-192KB) value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP6 = 64, /*!< GROUP6 : Power ON only SRAM group6 (192KB-224KB) value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP7 = 128, /*!< GROUP7 : Power ON only SRAM group7 (224KB-256KB) value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP8 = 256, /*!< GROUP8 : Power ON only SRAM group8 (256KB-288KB) value. */ - PWRCTRL_MEMPWREN_SRAM_GROUP9 = 512, /*!< GROUP9 : Power ON only SRAM group9 (288KB-320KB) value. */ - PWRCTRL_MEMPWREN_SRAM_SRAM64K = 3, /*!< SRAM64K : Power ON only lower 64k value. */ - PWRCTRL_MEMPWREN_SRAM_SRAM128K = 15, /*!< SRAM128K : Power ON only lower 128k value. */ - PWRCTRL_MEMPWREN_SRAM_SRAM256K = 255, /*!< SRAM256K : Power ON only lower 256k value. */ - PWRCTRL_MEMPWREN_SRAM_ALL = 1023, /*!< ALL : All SRAM banks (320K) powered ON value. */ -} PWRCTRL_MEMPWREN_SRAM_Enum; - -/* ============================================= PWRCTRL MEMPWREN DTCM [0..2] ============================================== */ -typedef enum { /*!< PWRCTRL_MEMPWREN_DTCM */ - PWRCTRL_MEMPWREN_DTCM_NONE = 0, /*!< NONE : Do not enable power to any DTCMs value. */ - PWRCTRL_MEMPWREN_DTCM_GROUP0DTCM0 = 1, /*!< GROUP0DTCM0 : Power ON only GROUP0_DTCM0 value. */ - PWRCTRL_MEMPWREN_DTCM_GROUP0DTCM1 = 2, /*!< GROUP0DTCM1 : Power ON only GROUP0_DTCM1 value. */ - PWRCTRL_MEMPWREN_DTCM_GROUP0 = 3, /*!< GROUP0 : Power ON only DTCMs in group0 value. */ - PWRCTRL_MEMPWREN_DTCM_GROUP1 = 4, /*!< GROUP1 : Power ON only DTCMs in group1 value. */ - PWRCTRL_MEMPWREN_DTCM_ALL = 7, /*!< ALL : Power ON all DTCMs value. */ -} PWRCTRL_MEMPWREN_DTCM_Enum; - -/* ===================================================== MEMPWRSTATUS ====================================================== */ -/* ===================================================== DEVPWRSTATUS ====================================================== */ -/* ======================================================= SRAMCTRL ======================================================== */ -/* ======================================== PWRCTRL SRAMCTRL SRAMLIGHTSLEEP [8..19] ======================================== */ -typedef enum { /*!< PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP */ - PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_ALL = 255, /*!< ALL : Enable LIGHT SLEEP for ALL SRAMs value. */ - PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_DIS = 0, /*!< DIS : Disables LIGHT SLEEP for ALL SRAMs value. */ -} PWRCTRL_SRAMCTRL_SRAMLIGHTSLEEP_Enum; - -/* ======================================= PWRCTRL SRAMCTRL SRAMMASTERCLKGATE [2..2] ======================================= */ -typedef enum { /*!< PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE */ - PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_EN = 1, /*!< EN : Enable Master SRAM Clock Gate value. */ - PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_DIS = 0, /*!< DIS : Disables Master SRAM Clock Gating value. */ -} PWRCTRL_SRAMCTRL_SRAMMASTERCLKGATE_Enum; - -/* ========================================== PWRCTRL SRAMCTRL SRAMCLKGATE [1..1] ========================================== */ -typedef enum { /*!< PWRCTRL_SRAMCTRL_SRAMCLKGATE */ - PWRCTRL_SRAMCTRL_SRAMCLKGATE_EN = 1, /*!< EN : Enable Individual SRAM Clock Gating value. */ - PWRCTRL_SRAMCTRL_SRAMCLKGATE_DIS = 0, /*!< DIS : Disables Individual SRAM Clock Gating value. */ -} PWRCTRL_SRAMCTRL_SRAMCLKGATE_Enum; - -/* ======================================================= ADCSTATUS ======================================================= */ -/* ========================================================= MISC ========================================================== */ -/* ============================================ PWRCTRL MISC MEMVRLPBLE [6..6] ============================================= */ -typedef enum { /*!< PWRCTRL_MISC_MEMVRLPBLE */ - PWRCTRL_MISC_MEMVRLPBLE_EN = 1, /*!< EN : Mem VR can go to lp mode even when BLE is powered on. value. */ - PWRCTRL_MISC_MEMVRLPBLE_DIS = 0, /*!< DIS : Mem VR will stay in active mode when BLE is powered on. - value. */ -} PWRCTRL_MISC_MEMVRLPBLE_Enum; - -/* =========================================== PWRCTRL MISC FORCEMEMVRADC [4..5] =========================================== */ -typedef enum { /*!< PWRCTRL_MISC_FORCEMEMVRADC */ - PWRCTRL_MISC_FORCEMEMVRADC_ACT = 2, /*!< ACT : In this mode if all the other domains but ADC are powered - down, mem VR will stay in ACT mode. value. */ - PWRCTRL_MISC_FORCEMEMVRADC_LP = 1, /*!< LP : In this mode if all the other domains but ADC are powered - down, mem VR will stay in LP mode. value. */ - PWRCTRL_MISC_FORCEMEMVRADC_DIS = 0, /*!< DIS : In this mode if all the other domains but ADC are powered - down, mem VR will duty cycle between active and LP modes - depending on ADC sampling. value. */ -} PWRCTRL_MISC_FORCEMEMVRADC_Enum; - -/* ============================================ PWRCTRL MISC SIMOBUCKEN [0..0] ============================================= */ -typedef enum { /*!< PWRCTRL_MISC_SIMOBUCKEN */ - PWRCTRL_MISC_SIMOBUCKEN_EN = 1, /*!< EN : Enable the SIMO Buck value. */ - PWRCTRL_MISC_SIMOBUCKEN_DIS = 0, /*!< DIS : Disable the SIMO Buck value. */ -} PWRCTRL_MISC_SIMOBUCKEN_Enum; - -/* ===================================================== DEVPWREVENTEN ===================================================== */ -/* ======================================= PWRCTRL DEVPWREVENTEN BURSTEVEN [31..31] ======================================== */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_BURSTEVEN */ - PWRCTRL_DEVPWREVENTEN_BURSTEVEN_EN = 1, /*!< EN : Enable BURST status event value. */ - PWRCTRL_DEVPWREVENTEN_BURSTEVEN_DIS = 0, /*!< DIS : Disable BURST status event value. */ -} PWRCTRL_DEVPWREVENTEN_BURSTEVEN_Enum; - -/* ==================================== PWRCTRL DEVPWREVENTEN BURSTFEATUREEVEN [30..30] ==================================== */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN */ - PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_EN = 1,/*!< EN : Enable BURSTFEATURE status event value. */ - PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_DIS = 0,/*!< DIS : Disable BURSTFEATURE status event value. */ -} PWRCTRL_DEVPWREVENTEN_BURSTFEATUREEVEN_Enum; - -/* ===================================== PWRCTRL DEVPWREVENTEN BLEFEATUREEVEN [29..29] ===================================== */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN */ - PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_EN = 1, /*!< EN : Enable BLEFEATURE status event value. */ - PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_DIS = 0, /*!< DIS : Disable BLEFEATURE status event value. */ -} PWRCTRL_DEVPWREVENTEN_BLEFEATUREEVEN_Enum; - -/* ========================================= PWRCTRL DEVPWREVENTEN BLELEVEN [8..8] ========================================= */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_BLELEVEN */ - PWRCTRL_DEVPWREVENTEN_BLELEVEN_EN = 1, /*!< EN : Enable BLE power-on status event value. */ - PWRCTRL_DEVPWREVENTEN_BLELEVEN_DIS = 0, /*!< DIS : Disable BLE power-on status event value. */ -} PWRCTRL_DEVPWREVENTEN_BLELEVEN_Enum; - -/* ========================================= PWRCTRL DEVPWREVENTEN PDMEVEN [7..7] ========================================== */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_PDMEVEN */ - PWRCTRL_DEVPWREVENTEN_PDMEVEN_EN = 1, /*!< EN : Enable PDM power-on status event value. */ - PWRCTRL_DEVPWREVENTEN_PDMEVEN_DIS = 0, /*!< DIS : Disable PDM power-on status event value. */ -} PWRCTRL_DEVPWREVENTEN_PDMEVEN_Enum; - -/* ========================================= PWRCTRL DEVPWREVENTEN MSPIEVEN [6..6] ========================================= */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_MSPIEVEN */ - PWRCTRL_DEVPWREVENTEN_MSPIEVEN_EN = 1, /*!< EN : Enable MSPI power-on status event value. */ - PWRCTRL_DEVPWREVENTEN_MSPIEVEN_DIS = 0, /*!< DIS : Disable MSPI power-on status event value. */ -} PWRCTRL_DEVPWREVENTEN_MSPIEVEN_Enum; - -/* ========================================= PWRCTRL DEVPWREVENTEN ADCEVEN [5..5] ========================================== */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_ADCEVEN */ - PWRCTRL_DEVPWREVENTEN_ADCEVEN_EN = 1, /*!< EN : Enable ADC power-on status event value. */ - PWRCTRL_DEVPWREVENTEN_ADCEVEN_DIS = 0, /*!< DIS : Disable ADC power-on status event value. */ -} PWRCTRL_DEVPWREVENTEN_ADCEVEN_Enum; - -/* ========================================= PWRCTRL DEVPWREVENTEN HCPCEVEN [4..4] ========================================= */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_HCPCEVEN */ - PWRCTRL_DEVPWREVENTEN_HCPCEVEN_EN = 1, /*!< EN : Enable HCPC power-on status event value. */ - PWRCTRL_DEVPWREVENTEN_HCPCEVEN_DIS = 0, /*!< DIS : Disable HCPC power-on status event value. */ -} PWRCTRL_DEVPWREVENTEN_HCPCEVEN_Enum; - -/* ========================================= PWRCTRL DEVPWREVENTEN HCPBEVEN [3..3] ========================================= */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_HCPBEVEN */ - PWRCTRL_DEVPWREVENTEN_HCPBEVEN_EN = 1, /*!< EN : Enable HCPB power-on status event value. */ - PWRCTRL_DEVPWREVENTEN_HCPBEVEN_DIS = 0, /*!< DIS : Disable HCPB power-on status event value. */ -} PWRCTRL_DEVPWREVENTEN_HCPBEVEN_Enum; - -/* ========================================= PWRCTRL DEVPWREVENTEN HCPAEVEN [2..2] ========================================= */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_HCPAEVEN */ - PWRCTRL_DEVPWREVENTEN_HCPAEVEN_EN = 1, /*!< EN : Enable HCPA power-on status event value. */ - PWRCTRL_DEVPWREVENTEN_HCPAEVEN_DIS = 0, /*!< DIS : Disable HCPA power-on status event value. */ -} PWRCTRL_DEVPWREVENTEN_HCPAEVEN_Enum; - -/* ========================================= PWRCTRL DEVPWREVENTEN MCUHEVEN [1..1] ========================================= */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_MCUHEVEN */ - PWRCTRL_DEVPWREVENTEN_MCUHEVEN_EN = 1, /*!< EN : Enable MCHU power-on status event value. */ - PWRCTRL_DEVPWREVENTEN_MCUHEVEN_DIS = 0, /*!< DIS : Disable MCUH power-on status event value. */ -} PWRCTRL_DEVPWREVENTEN_MCUHEVEN_Enum; - -/* ========================================= PWRCTRL DEVPWREVENTEN MCULEVEN [0..0] ========================================= */ -typedef enum { /*!< PWRCTRL_DEVPWREVENTEN_MCULEVEN */ - PWRCTRL_DEVPWREVENTEN_MCULEVEN_EN = 1, /*!< EN : Enable MCUL power-on status event value. */ - PWRCTRL_DEVPWREVENTEN_MCULEVEN_DIS = 0, /*!< DIS : Disable MCUL power-on status event value. */ -} PWRCTRL_DEVPWREVENTEN_MCULEVEN_Enum; - -/* ===================================================== MEMPWREVENTEN ===================================================== */ -/* ======================================= PWRCTRL MEMPWREVENTEN CACHEB2EN [31..31] ======================================== */ -typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_CACHEB2EN */ - PWRCTRL_MEMPWREVENTEN_CACHEB2EN_EN = 1, /*!< EN : Enable CACHE BANK 2 status event value. */ - PWRCTRL_MEMPWREVENTEN_CACHEB2EN_DIS = 0, /*!< DIS : Disable CACHE BANK 2 status event value. */ -} PWRCTRL_MEMPWREVENTEN_CACHEB2EN_Enum; - -/* ======================================= PWRCTRL MEMPWREVENTEN CACHEB0EN [30..30] ======================================== */ -typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_CACHEB0EN */ - PWRCTRL_MEMPWREVENTEN_CACHEB0EN_EN = 1, /*!< EN : Enable CACHE BANK 0 status event value. */ - PWRCTRL_MEMPWREVENTEN_CACHEB0EN_DIS = 0, /*!< DIS : Disable CACHE BANK 0 status event value. */ -} PWRCTRL_MEMPWREVENTEN_CACHEB0EN_Enum; - -/* ======================================== PWRCTRL MEMPWREVENTEN FLASH1EN [14..14] ======================================== */ -typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_FLASH1EN */ - PWRCTRL_MEMPWREVENTEN_FLASH1EN_EN = 1, /*!< EN : Enable FLASH status event value. */ - PWRCTRL_MEMPWREVENTEN_FLASH1EN_DIS = 0, /*!< DIS : Disables FLASH status event value. */ -} PWRCTRL_MEMPWREVENTEN_FLASH1EN_Enum; - -/* ======================================== PWRCTRL MEMPWREVENTEN FLASH0EN [13..13] ======================================== */ -typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_FLASH0EN */ - PWRCTRL_MEMPWREVENTEN_FLASH0EN_EN = 1, /*!< EN : Enable FLASH status event value. */ - PWRCTRL_MEMPWREVENTEN_FLASH0EN_DIS = 0, /*!< DIS : Disables FLASH status event value. */ -} PWRCTRL_MEMPWREVENTEN_FLASH0EN_Enum; - -/* ========================================= PWRCTRL MEMPWREVENTEN SRAMEN [3..12] ========================================== */ -typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_SRAMEN */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_NONE = 0, /*!< NONE : Disable SRAM power-on status event value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP0EN = 1, /*!< GROUP0EN : Enable SRAM group0 (0KB-32KB) power on status event - value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP1EN = 2, /*!< GROUP1EN : Enable SRAM group1 (32KB-64KB) power on status event - value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP2EN = 4, /*!< GROUP2EN : Enable SRAM group2 (64KB-96KB) power on status event - value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP3EN = 8, /*!< GROUP3EN : Enable SRAM group3 (96KB-128KB) power on status event - value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP4EN = 16, /*!< GROUP4EN : Enable SRAM group4 (128KB-160KB) power on status - event value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP5EN = 32, /*!< GROUP5EN : Enable SRAM group5 (160KB-192KB) power on status - event value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP6EN = 64, /*!< GROUP6EN : Enable SRAM group6 (192KB-224KB) power on status - event value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP7EN = 128, /*!< GROUP7EN : Enable SRAM group7 (224KB-256KB) power on status - event value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP8EN = 256, /*!< GROUP8EN : Enable SRAM group8 (256KB-288KB) power on status - event value. */ - PWRCTRL_MEMPWREVENTEN_SRAMEN_GROUP9EN = 512, /*!< GROUP9EN : Enable SRAM group9 (288KB-320KB) power on status - event value. */ -} PWRCTRL_MEMPWREVENTEN_SRAMEN_Enum; - -/* ========================================== PWRCTRL MEMPWREVENTEN DTCMEN [0..2] ========================================== */ -typedef enum { /*!< PWRCTRL_MEMPWREVENTEN_DTCMEN */ - PWRCTRL_MEMPWREVENTEN_DTCMEN_NONE = 0, /*!< NONE : Do not enable DTCM power-on status event value. */ - PWRCTRL_MEMPWREVENTEN_DTCMEN_GROUP0DTCM0EN = 1,/*!< GROUP0DTCM0EN : Enable GROUP0_DTCM0 power on status event value. */ - PWRCTRL_MEMPWREVENTEN_DTCMEN_GROUP0DTCM1EN = 2,/*!< GROUP0DTCM1EN : Enable GROUP0_DTCM1 power on status event value. */ - PWRCTRL_MEMPWREVENTEN_DTCMEN_GROUP0EN = 3, /*!< GROUP0EN : Enable DTCMs in group0 power on status event value. */ - PWRCTRL_MEMPWREVENTEN_DTCMEN_GROUP1EN = 4, /*!< GROUP1EN : Enable DTCMs in group1 power on status event value. */ - PWRCTRL_MEMPWREVENTEN_DTCMEN_ALL = 7, /*!< ALL : Enable all DTCM power on status event value. */ -} PWRCTRL_MEMPWREVENTEN_DTCMEN_Enum; - - - -/* =========================================================================================================================== */ -/* ================ RSTGEN ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== CFG ========================================================== */ -/* ========================================================= SWPOI ========================================================= */ -/* ============================================= RSTGEN SWPOI SWPOIKEY [0..7] ============================================== */ -typedef enum { /*!< RSTGEN_SWPOI_SWPOIKEY */ - RSTGEN_SWPOI_SWPOIKEY_KEYVALUE = 27, /*!< KEYVALUE : Writing 0x1B key value generates a software POI reset. - value. */ -} RSTGEN_SWPOI_SWPOIKEY_Enum; - -/* ========================================================= SWPOR ========================================================= */ -/* ============================================= RSTGEN SWPOR SWPORKEY [0..7] ============================================== */ -typedef enum { /*!< RSTGEN_SWPOR_SWPORKEY */ - RSTGEN_SWPOR_SWPORKEY_KEYVALUE = 212, /*!< KEYVALUE : Writing 0xD4 key value generates a software POR reset. - value. */ -} RSTGEN_SWPOR_SWPORKEY_Enum; - -/* ======================================================== TPIURST ======================================================== */ -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ -/* ========================================================= STAT ========================================================== */ - - -/* =========================================================================================================================== */ -/* ================ RTC ================ */ -/* =========================================================================================================================== */ - -/* ======================================================== CTRLOW ========================================================= */ -/* ========================================================= CTRUP ========================================================= */ -/* =============================================== RTC CTRUP CTERR [31..31] ================================================ */ -typedef enum { /*!< RTC_CTRUP_CTERR */ - RTC_CTRUP_CTERR_NOERR = 0, /*!< NOERR : No read error occurred value. */ - RTC_CTRUP_CTERR_RDERR = 1, /*!< RDERR : Read error occurred value. */ -} RTC_CTRUP_CTERR_Enum; - -/* ================================================ RTC CTRUP CEB [28..28] ================================================= */ -typedef enum { /*!< RTC_CTRUP_CEB */ - RTC_CTRUP_CEB_DIS = 0, /*!< DIS : Disable the Century bit from changing value. */ - RTC_CTRUP_CEB_EN = 1, /*!< EN : Enable the Century bit to change value. */ -} RTC_CTRUP_CEB_Enum; - -/* ================================================= RTC CTRUP CB [27..27] ================================================= */ -typedef enum { /*!< RTC_CTRUP_CB */ - RTC_CTRUP_CB_2000 = 0, /*!< 2000 : Century is 2000s value. */ - RTC_CTRUP_CB_1900_2100 = 1, /*!< 1900_2100 : Century is 1900s/2100s value. */ -} RTC_CTRUP_CB_Enum; - -/* ======================================================== ALMLOW ========================================================= */ -/* ========================================================= ALMUP ========================================================= */ -/* ======================================================== RTCCTL ========================================================= */ -/* =============================================== RTC RTCCTL HR1224 [5..5] ================================================ */ -typedef enum { /*!< RTC_RTCCTL_HR1224 */ - RTC_RTCCTL_HR1224_24HR = 0, /*!< 24HR : Hours in 24 hour mode value. */ - RTC_RTCCTL_HR1224_12HR = 1, /*!< 12HR : Hours in 12 hour mode value. */ -} RTC_RTCCTL_HR1224_Enum; - -/* ================================================ RTC RTCCTL RSTOP [4..4] ================================================ */ -typedef enum { /*!< RTC_RTCCTL_RSTOP */ - RTC_RTCCTL_RSTOP_RUN = 0, /*!< RUN : Allow the RTC input clock to run value. */ - RTC_RTCCTL_RSTOP_STOP = 1, /*!< STOP : Stop the RTC input clock value. */ -} RTC_RTCCTL_RSTOP_Enum; - -/* ================================================= RTC RTCCTL RPT [1..3] ================================================= */ -typedef enum { /*!< RTC_RTCCTL_RPT */ - RTC_RTCCTL_RPT_DIS = 0, /*!< DIS : Alarm interrupt disabled value. */ - RTC_RTCCTL_RPT_YEAR = 1, /*!< YEAR : Interrupt every year value. */ - RTC_RTCCTL_RPT_MONTH = 2, /*!< MONTH : Interrupt every month value. */ - RTC_RTCCTL_RPT_WEEK = 3, /*!< WEEK : Interrupt every week value. */ - RTC_RTCCTL_RPT_DAY = 4, /*!< DAY : Interrupt every day value. */ - RTC_RTCCTL_RPT_HR = 5, /*!< HR : Interrupt every hour value. */ - RTC_RTCCTL_RPT_MIN = 6, /*!< MIN : Interrupt every minute value. */ - RTC_RTCCTL_RPT_SEC = 7, /*!< SEC : Interrupt every second/10th/100th value. */ -} RTC_RTCCTL_RPT_Enum; - -/* ================================================ RTC RTCCTL WRTC [0..0] ================================================= */ -typedef enum { /*!< RTC_RTCCTL_WRTC */ - RTC_RTCCTL_WRTC_DIS = 0, /*!< DIS : Counter writes are disabled value. */ - RTC_RTCCTL_WRTC_EN = 1, /*!< EN : Counter writes are enabled value. */ -} RTC_RTCCTL_WRTC_Enum; - -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ - - -/* =========================================================================================================================== */ -/* ================ SCARD ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== SR =========================================================== */ -/* ========================================================== DR =========================================================== */ -/* ========================================================== SR1 ========================================================== */ -/* ====================================================== RETXCNTRMI ======================================================= */ -/* ======================================================== CLKCTRL ======================================================== */ - - -/* =========================================================================================================================== */ -/* ================ SECURITY ================ */ -/* =========================================================================================================================== */ - -/* ========================================================= CTRL ========================================================== */ -/* ============================================= SECURITY CTRL FUNCTION [4..7] ============================================= */ -typedef enum { /*!< SECURITY_CTRL_FUNCTION */ - SECURITY_CTRL_FUNCTION_CRC32 = 0, /*!< CRC32 : Perform CRC32 operation value. */ -} SECURITY_CTRL_FUNCTION_Enum; - -/* ======================================================== SRCADDR ======================================================== */ -/* ========================================================== LEN ========================================================== */ -/* ======================================================== RESULT ========================================================= */ -/* ======================================================= LOCKCTRL ======================================================== */ -/* ============================================ SECURITY LOCKCTRL SELECT [0..7] ============================================ */ -typedef enum { /*!< SECURITY_LOCKCTRL_SELECT */ - SECURITY_LOCKCTRL_SELECT_CUSTOMER_KEY = 1, /*!< CUSTOMER_KEY : Unlock Customer Key (access to top half of info0) - value. */ - SECURITY_LOCKCTRL_SELECT_NONE = 0, /*!< NONE : Lock Control should be set to NONE when not in use. value. */ -} SECURITY_LOCKCTRL_SELECT_Enum; - -/* ======================================================= LOCKSTAT ======================================================== */ -/* =========================================== SECURITY LOCKSTAT STATUS [0..31] ============================================ */ -typedef enum { /*!< SECURITY_LOCKSTAT_STATUS */ - SECURITY_LOCKSTAT_STATUS_CUSTOMER_KEY = 1, /*!< CUSTOMER_KEY : Customer Key is unlocked (access is granted to - top half of info0) value. */ - SECURITY_LOCKSTAT_STATUS_NONE = 0, /*!< NONE : No resources are unlocked value. */ -} SECURITY_LOCKSTAT_STATUS_Enum; - -/* ========================================================= KEY0 ========================================================== */ -/* ========================================================= KEY1 ========================================================== */ -/* ========================================================= KEY2 ========================================================== */ -/* ========================================================= KEY3 ========================================================== */ - - -/* =========================================================================================================================== */ -/* ================ UART0 ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== DR =========================================================== */ -/* =============================================== UART0 DR OEDATA [11..11] ================================================ */ -typedef enum { /*!< UART0_DR_OEDATA */ - UART0_DR_OEDATA_NOERR = 0, /*!< NOERR : No error on UART OEDATA, overrun error indicator. value. */ - UART0_DR_OEDATA_ERR = 1, /*!< ERR : Error on UART OEDATA, overrun error indicator. value. */ -} UART0_DR_OEDATA_Enum; - -/* =============================================== UART0 DR BEDATA [10..10] ================================================ */ -typedef enum { /*!< UART0_DR_BEDATA */ - UART0_DR_BEDATA_NOERR = 0, /*!< NOERR : No error on UART BEDATA, break error indicator. value. */ - UART0_DR_BEDATA_ERR = 1, /*!< ERR : Error on UART BEDATA, break error indicator. value. */ -} UART0_DR_BEDATA_Enum; - -/* ================================================ UART0 DR PEDATA [9..9] ================================================= */ -typedef enum { /*!< UART0_DR_PEDATA */ - UART0_DR_PEDATA_NOERR = 0, /*!< NOERR : No error on UART PEDATA, parity error indicator. value. */ - UART0_DR_PEDATA_ERR = 1, /*!< ERR : Error on UART PEDATA, parity error indicator. value. */ -} UART0_DR_PEDATA_Enum; - -/* ================================================ UART0 DR FEDATA [8..8] ================================================= */ -typedef enum { /*!< UART0_DR_FEDATA */ - UART0_DR_FEDATA_NOERR = 0, /*!< NOERR : No error on UART FEDATA, framing error indicator. value. */ - UART0_DR_FEDATA_ERR = 1, /*!< ERR : Error on UART FEDATA, framing error indicator. value. */ -} UART0_DR_FEDATA_Enum; - -/* ========================================================== RSR ========================================================== */ -/* ================================================ UART0 RSR OESTAT [3..3] ================================================ */ -typedef enum { /*!< UART0_RSR_OESTAT */ - UART0_RSR_OESTAT_NOERR = 0, /*!< NOERR : No error on UART OESTAT, overrun error indicator. value. */ - UART0_RSR_OESTAT_ERR = 1, /*!< ERR : Error on UART OESTAT, overrun error indicator. value. */ -} UART0_RSR_OESTAT_Enum; - -/* ================================================ UART0 RSR BESTAT [2..2] ================================================ */ -typedef enum { /*!< UART0_RSR_BESTAT */ - UART0_RSR_BESTAT_NOERR = 0, /*!< NOERR : No error on UART BESTAT, break error indicator. value. */ - UART0_RSR_BESTAT_ERR = 1, /*!< ERR : Error on UART BESTAT, break error indicator. value. */ -} UART0_RSR_BESTAT_Enum; - -/* ================================================ UART0 RSR PESTAT [1..1] ================================================ */ -typedef enum { /*!< UART0_RSR_PESTAT */ - UART0_RSR_PESTAT_NOERR = 0, /*!< NOERR : No error on UART PESTAT, parity error indicator. value. */ - UART0_RSR_PESTAT_ERR = 1, /*!< ERR : Error on UART PESTAT, parity error indicator. value. */ -} UART0_RSR_PESTAT_Enum; - -/* ================================================ UART0 RSR FESTAT [0..0] ================================================ */ -typedef enum { /*!< UART0_RSR_FESTAT */ - UART0_RSR_FESTAT_NOERR = 0, /*!< NOERR : No error on UART FESTAT, framing error indicator. value. */ - UART0_RSR_FESTAT_ERR = 1, /*!< ERR : Error on UART FESTAT, framing error indicator. value. */ -} UART0_RSR_FESTAT_Enum; - -/* ========================================================== FR =========================================================== */ -/* ================================================= UART0 FR TXFE [7..7] ================================================== */ -typedef enum { /*!< UART0_FR_TXFE */ - UART0_FR_TXFE_XMTFIFO_EMPTY = 1, /*!< XMTFIFO_EMPTY : Transmit fifo is empty. value. */ -} UART0_FR_TXFE_Enum; - -/* ================================================= UART0 FR RXFF [6..6] ================================================== */ -typedef enum { /*!< UART0_FR_RXFF */ - UART0_FR_RXFF_RCVFIFO_FULL = 1, /*!< RCVFIFO_FULL : Receive fifo is full. value. */ -} UART0_FR_RXFF_Enum; - -/* ================================================= UART0 FR TXFF [5..5] ================================================== */ -typedef enum { /*!< UART0_FR_TXFF */ - UART0_FR_TXFF_XMTFIFO_FULL = 1, /*!< XMTFIFO_FULL : Transmit fifo is full. value. */ -} UART0_FR_TXFF_Enum; - -/* ================================================= UART0 FR RXFE [4..4] ================================================== */ -typedef enum { /*!< UART0_FR_RXFE */ - UART0_FR_RXFE_RCVFIFO_EMPTY = 1, /*!< RCVFIFO_EMPTY : Receive fifo is empty. value. */ -} UART0_FR_RXFE_Enum; - -/* ================================================= UART0 FR BUSY [3..3] ================================================== */ -typedef enum { /*!< UART0_FR_BUSY */ - UART0_FR_BUSY_BUSY = 1, /*!< BUSY : UART busy indicator. value. */ -} UART0_FR_BUSY_Enum; - -/* ================================================== UART0 FR DCD [2..2] ================================================== */ -typedef enum { /*!< UART0_FR_DCD */ - UART0_FR_DCD_DETECTED = 1, /*!< DETECTED : Data carrier detect detected. value. */ -} UART0_FR_DCD_Enum; - -/* ================================================== UART0 FR DSR [1..1] ================================================== */ -typedef enum { /*!< UART0_FR_DSR */ - UART0_FR_DSR_READY = 1, /*!< READY : Data set ready. value. */ -} UART0_FR_DSR_Enum; - -/* ================================================== UART0 FR CTS [0..0] ================================================== */ -typedef enum { /*!< UART0_FR_CTS */ - UART0_FR_CTS_CLEARTOSEND = 1, /*!< CLEARTOSEND : Clear to send is indicated. value. */ -} UART0_FR_CTS_Enum; - -/* ========================================================= ILPR ========================================================== */ -/* ========================================================= IBRD ========================================================== */ -/* ========================================================= FBRD ========================================================== */ -/* ========================================================= LCRH ========================================================== */ -/* ========================================================== CR =========================================================== */ -/* ================================================ UART0 CR CLKSEL [4..6] ================================================= */ -typedef enum { /*!< UART0_CR_CLKSEL */ - UART0_CR_CLKSEL_NOCLK = 0, /*!< NOCLK : No UART clock. This is the low power default. value. */ - UART0_CR_CLKSEL_24MHZ = 1, /*!< 24MHZ : 24 MHz clock. value. */ - UART0_CR_CLKSEL_12MHZ = 2, /*!< 12MHZ : 12 MHz clock. value. */ - UART0_CR_CLKSEL_6MHZ = 3, /*!< 6MHZ : 6 MHz clock. value. */ - UART0_CR_CLKSEL_3MHZ = 4, /*!< 3MHZ : 3 MHz clock. value. */ -} UART0_CR_CLKSEL_Enum; - -/* ========================================================= IFLS ========================================================== */ -/* ========================================================== IER ========================================================== */ -/* ========================================================== IES ========================================================== */ -/* ========================================================== MIS ========================================================== */ -/* ========================================================== IEC ========================================================== */ - - -/* =========================================================================================================================== */ -/* ================ VCOMP ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== CFG ========================================================== */ -/* =============================================== VCOMP CFG LVLSEL [16..19] =============================================== */ -typedef enum { /*!< VCOMP_CFG_LVLSEL */ - VCOMP_CFG_LVLSEL_0P58V = 0, /*!< 0P58V : Set Reference input to 0.58 Volts. value. */ - VCOMP_CFG_LVLSEL_0P77V = 1, /*!< 0P77V : Set Reference input to 0.77 Volts. value. */ - VCOMP_CFG_LVLSEL_0P97V = 2, /*!< 0P97V : Set Reference input to 0.97 Volts. value. */ - VCOMP_CFG_LVLSEL_1P16V = 3, /*!< 1P16V : Set Reference input to 1.16 Volts. value. */ - VCOMP_CFG_LVLSEL_1P35V = 4, /*!< 1P35V : Set Reference input to 1.35 Volts. value. */ - VCOMP_CFG_LVLSEL_1P55V = 5, /*!< 1P55V : Set Reference input to 1.55 Volts. value. */ - VCOMP_CFG_LVLSEL_1P74V = 6, /*!< 1P74V : Set Reference input to 1.74 Volts. value. */ - VCOMP_CFG_LVLSEL_1P93V = 7, /*!< 1P93V : Set Reference input to 1.93 Volts. value. */ - VCOMP_CFG_LVLSEL_2P13V = 8, /*!< 2P13V : Set Reference input to 2.13 Volts. value. */ - VCOMP_CFG_LVLSEL_2P32V = 9, /*!< 2P32V : Set Reference input to 2.32 Volts. value. */ - VCOMP_CFG_LVLSEL_2P51V = 10, /*!< 2P51V : Set Reference input to 2.51 Volts. value. */ - VCOMP_CFG_LVLSEL_2P71V = 11, /*!< 2P71V : Set Reference input to 2.71 Volts. value. */ - VCOMP_CFG_LVLSEL_2P90V = 12, /*!< 2P90V : Set Reference input to 2.90 Volts. value. */ - VCOMP_CFG_LVLSEL_3P09V = 13, /*!< 3P09V : Set Reference input to 3.09 Volts. value. */ - VCOMP_CFG_LVLSEL_3P29V = 14, /*!< 3P29V : Set Reference input to 3.29 Volts. value. */ - VCOMP_CFG_LVLSEL_3P48V = 15, /*!< 3P48V : Set Reference input to 3.48 Volts. value. */ -} VCOMP_CFG_LVLSEL_Enum; - -/* ================================================= VCOMP CFG NSEL [8..9] ================================================= */ -typedef enum { /*!< VCOMP_CFG_NSEL */ - VCOMP_CFG_NSEL_VREFEXT1 = 0, /*!< VREFEXT1 : Use external reference 1 for reference input. value. */ - VCOMP_CFG_NSEL_VREFEXT2 = 1, /*!< VREFEXT2 : Use external reference 2 for reference input. value. */ - VCOMP_CFG_NSEL_VREFEXT3 = 2, /*!< VREFEXT3 : Use external reference 3 for reference input. value. */ - VCOMP_CFG_NSEL_DAC = 3, /*!< DAC : Use DAC output selected by LVLSEL for reference input. - value. */ -} VCOMP_CFG_NSEL_Enum; - -/* ================================================= VCOMP CFG PSEL [0..1] ================================================= */ -typedef enum { /*!< VCOMP_CFG_PSEL */ - VCOMP_CFG_PSEL_VDDADJ = 0, /*!< VDDADJ : Use VDDADJ for the positive input. value. */ - VCOMP_CFG_PSEL_VTEMP = 1, /*!< VTEMP : Use the temperature sensor output for the positive input. - Note: If this channel is selected for PSEL, the bandap - circuit required for temperature comparisons will automatically - turn on. The bandgap circuit requires 11us to stabalize. - value. */ - VCOMP_CFG_PSEL_VEXT1 = 2, /*!< VEXT1 : Use external voltage 0 for positive input. value. */ - VCOMP_CFG_PSEL_VEXT2 = 3, /*!< VEXT2 : Use external voltage 1 for positive input. value. */ -} VCOMP_CFG_PSEL_Enum; - -/* ========================================================= STAT ========================================================== */ -/* =============================================== VCOMP STAT PWDSTAT [1..1] =============================================== */ -typedef enum { /*!< VCOMP_STAT_PWDSTAT */ - VCOMP_STAT_PWDSTAT_POWERED_DOWN = 1, /*!< POWERED_DOWN : The voltage comparator is powered down. value. */ -} VCOMP_STAT_PWDSTAT_Enum; - -/* =============================================== VCOMP STAT CMPOUT [0..0] ================================================ */ -typedef enum { /*!< VCOMP_STAT_CMPOUT */ - VCOMP_STAT_CMPOUT_VOUT_LOW = 0, /*!< VOUT_LOW : The negative input of the comparator is greater than - the positive input. value. */ - VCOMP_STAT_CMPOUT_VOUT_HIGH = 1, /*!< VOUT_HIGH : The positive input of the comparator is greater - than the negative input. value. */ -} VCOMP_STAT_CMPOUT_Enum; - -/* ======================================================== PWDKEY ========================================================= */ -/* ============================================== VCOMP PWDKEY PWDKEY [0..31] ============================================== */ -typedef enum { /*!< VCOMP_PWDKEY_PWDKEY */ - VCOMP_PWDKEY_PWDKEY_Key = 55, /*!< Key : Key value. */ -} VCOMP_PWDKEY_PWDKEY_Enum; - -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ - - -/* =========================================================================================================================== */ -/* ================ WDT ================ */ -/* =========================================================================================================================== */ - -/* ========================================================== CFG ========================================================== */ -/* ================================================ WDT CFG CLKSEL [24..26] ================================================ */ -typedef enum { /*!< WDT_CFG_CLKSEL */ - WDT_CFG_CLKSEL_OFF = 0, /*!< OFF : Low Power Mode. This setting disables the watch dog timer. - value. */ - WDT_CFG_CLKSEL_128HZ = 1, /*!< 128HZ : 128 Hz LFRC clock. value. */ - WDT_CFG_CLKSEL_16HZ = 2, /*!< 16HZ : 16 Hz LFRC clock. value. */ - WDT_CFG_CLKSEL_1HZ = 3, /*!< 1HZ : 1 Hz LFRC clock. value. */ - WDT_CFG_CLKSEL_1_16HZ = 4, /*!< 1_16HZ : 1/16th Hz LFRC clock. value. */ -} WDT_CFG_CLKSEL_Enum; - -/* ========================================================= RSTRT ========================================================= */ -/* ================================================ WDT RSTRT RSTRT [0..7] ================================================= */ -typedef enum { /*!< WDT_RSTRT_RSTRT */ - WDT_RSTRT_RSTRT_KEYVALUE = 178, /*!< KEYVALUE : This is the key value to write to WDTRSTRT to restart - the WDT. This is a write only register. value. */ -} WDT_RSTRT_RSTRT_Enum; - -/* ========================================================= LOCK ========================================================== */ -/* ================================================= WDT LOCK LOCK [0..7] ================================================== */ -typedef enum { /*!< WDT_LOCK_LOCK */ - WDT_LOCK_LOCK_KEYVALUE = 58, /*!< KEYVALUE : This is the key value to write to WDTLOCK to lock - the WDT. value. */ -} WDT_LOCK_LOCK_Enum; - -/* ========================================================= COUNT ========================================================= */ -/* ========================================================= INTEN ========================================================= */ -/* ======================================================== INTSTAT ======================================================== */ -/* ======================================================== INTCLR ========================================================= */ -/* ======================================================== INTSET ========================================================= */ - -/** @} */ /* End of group EnumValue_peripherals */ - - -#ifdef __cplusplus -} -#endif - -#endif /* APOLLO3_H */ - - -/** @} */ /* End of group apollo3 */ - -/** @} */ /* End of group Ambiq Micro */ diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc index 5246e00296..561c46ce33 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc @@ -21,8 +21,8 @@ limitations under the License. #include "tensorflow/lite/experimental/micro/testing/micro_test.h" extern "C" { -#include "tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/apollo3.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/apollo3_ext/system_apollo3.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/apollo3_ext/apollo3.h" } #define output_data_size 43 diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c deleted file mode 100755 index c7f1573563..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c +++ /dev/null @@ -1,116 +0,0 @@ -//***************************************************************************** -// -//! @file system_apollo3.c -//! -//! @brief Ambiq Micro Apollo3 MCU specific functions. -// -//***************************************************************************** - -/* - * Copyright (C) 2015-2017, Ambiq Micro - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of itscontributors may be used to endorse - * or promote products derived from thissoftware without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @file apollo3.h - * @brief CMSIS HeaderFile - * @version 1.0 - * @date 10. August 2018 - * @note Generated by SVDConv V3.3.18 on Friday, 10.08.2018 16:52:09 - * from File 'apollo3.svd', - * last modified on Friday, 10.08.2018 20:01:31 - */ - - -#include -#include "system_apollo3.h" -#include "apollo3.h" - -//***************************************************************************** -// -// Defines -// -//***************************************************************************** - -// -// Clocks -// -#define __HSI (6000000UL) -#define __XTAL (32768UL) // Crystal Oscillator frequency -#define __SYS_OSC_CLK (48000000) // Main oscillator frequency -#define __SYSTEM_CLOCK (1*__SYS_OSC_CLK) - -// -// Initialize SystemCoreClock with the system core clock frequency value -// achieved after system intitialization. -// This means system core clock frequency after call to SystemInit() -// -uint32_t SystemCoreClock = __SYSTEM_CLOCK; // System Clock Frequency (Core Clock) - -//***************************************************************************** -// -//! @brief Set the global clock frequncy. -//! -//! This function sets the global clock frequency. -//! -//! @return None. -// -//***************************************************************************** -void -SystemCoreClockUpdate(void) -{ - // - // Calculate the system frequency based upon the current register settings. - // This function can be used to retrieve the system core clock frequeny - // after user changed register sittings. - // - SystemCoreClock = __SYS_OSC_CLK / (CLKGEN->CCTRL_b.CORESEL + 1); -} - -//***************************************************************************** -// -//! @brief Initialize the system. -//! -//! This function sets up the microcontroller system. -//! -//! @return None. -// -//***************************************************************************** -void -SystemInit(void) -{ - // - // Initialize the system - // Do not use global variables because this function is called before - // reaching pre-main. RW section maybe overwritten afterwards. - // - SystemCoreClock = __SYSTEM_CLOCK; - - CLKGEN->CLKKEY = 0x47; // Enable write to CCTRL - CLKGEN->CCTRL_b.CORESEL = 0; // Div by 1 for 48MHz - CLKGEN->CLKKEY = 0; // Disable write to CCTRL -} - diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h deleted file mode 100755 index 7fd9b51d5a..0000000000 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.h +++ /dev/null @@ -1,72 +0,0 @@ -//***************************************************************************** -// -//! @file system_Apollo3.h -//! -//! @brief Ambiq Micro Apollo3 MCU specific functions. -// -//***************************************************************************** - -/* - * Copyright (C) 2015-2017, Ambiq Micro - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of itscontributors may be used to endorse - * or promote products derived from thissoftware without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * @file apollo3.h - * @brief CMSIS HeaderFile - * @version 1.0 - * @date 10. August 2018 - * @note Generated by SVDConv V3.3.18 on Friday, 10.08.2018 16:52:09 - * from File 'apollo3.svd', - * last modified on Friday, 10.08.2018 20:01:31 - */ - - -#ifndef SYSTEM_APOLLO3_H -#define SYSTEM_APOLLO3_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -extern uint32_t SystemCoreClock; // System Clock Frequency (Core Clock) - -//***************************************************************************** -// -// External function definitions -// -//***************************************************************************** -extern void SystemInit (void); -extern void SystemCoreClockUpdate (void); - -#ifdef __cplusplus -} -#endif - -#endif // SYSTEM_APOLLO3_H - diff --git a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh index 6749858bdb..ba1fbb7fcf 100755 --- a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh +++ b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh @@ -21,6 +21,7 @@ cd "$SCRIPT_DIR/../../../../../.." DOWNLOADS_DIR=tensorflow/lite/experimental/micro/tools/make/downloads BZL_FILE_PATH=tensorflow/workspace.bzl +AP3_DOWNLOADS_DIR=tensorflow/lite/experimental/micro/examples/micro_speech # Ensure it is being run from repo root if [ ! -f $BZL_FILE_PATH ]; then @@ -33,6 +34,8 @@ GEMMLOWP_URL="https://github.com/google/gemmlowp/archive/719139ce755a0f31cbf1c37 FLATBUFFERS_URL="https://github.com/google/flatbuffers/archive/1f5eae5d6a135ff6811724f6c57f911d1f46bb15.tar.gz" CMSIS_URL="https://github.com/ARM-software/CMSIS_5/archive/5.4.0.zip" STM32_BARE_LIB_URL="https://github.com/google/stm32_bare_lib/archive/c07d611fb0af58450c5a3e0ab4d52b47f99bc82d.zip" +AP3_URL="https://github.com/AmbiqMicro/TFLiteMicro_Apollo3/archive/dfbcef9a57276c087d95aab7cb234f1d4c9eaaba.zip" +CUST_CMSIS_URL="https://github.com/AmbiqMicro/TFLiteMicro_CustCMSIS/archive/8f63966c5692e6a3a83956efd2e4aed77c4c9949.zip" download_and_extract() { local usage="Usage: download_and_extract URL DIR" @@ -69,5 +72,7 @@ download_and_extract "${GEMMLOWP_URL}" "${DOWNLOADS_DIR}/gemmlowp" download_and_extract "${FLATBUFFERS_URL}" "${DOWNLOADS_DIR}/flatbuffers" download_and_extract "${CMSIS_URL}" "${DOWNLOADS_DIR}/cmsis" download_and_extract "${STM32_BARE_LIB_URL}" "${DOWNLOADS_DIR}/stm32_bare_lib" +download_and_extract "${AP3_URL}" "${AP3_DOWNLOADS_DIR}/apollo3_ext" +download_and_extract "${CUST_CMSIS_URL}" "${AP3_DOWNLOADS_DIR}/CMSIS_ext" echo "download_dependencies.sh completed successfully." >&2 diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc index 3db4367a17..68ef79ea02 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc @@ -99,8 +99,10 @@ ifeq ($(TARGET), apollo3evb) $(CMSIS_SRC_DIR)/StatisticsFunctions/arm_mean_q15.c \ $(CMSIS_SRC_DIR)/StatisticsFunctions/arm_max_q7.c + AP3_EXT_MICRO_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/apollo3_ext AP3_MICRO_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/apollo3 CMSIS_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS + CMSIS_EXT_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS_ext MICRO_SPEECH_TEST_SRCS += \ $(AP3_MICRO_DIR)/_main.c @@ -108,16 +110,16 @@ ifeq ($(TARGET), apollo3evb) PREPROCESSOR_1K_CMSIS_TEST_SRCS := \ $(PREPROCESSOR_1K_SRCS) \ $(CMSIS_DIR)/preprocessor.cc \ - $(CMSIS_DIR)/arm_cmplx_mag_squared_q10p6.c \ + $(CMSIS_EXT_DIR)/arm_cmplx_mag_squared_q10p6.c \ $(CMSIS_DIR)/hanning.c \ - $(AP3_MICRO_DIR)/system_apollo3.c \ + $(AP3_EXT_MICRO_DIR)/system_apollo3.c \ $(AP3_MICRO_DIR)/_main.c \ $(CMSIS_SRCS) PREPROCESSOR_1K_MICRO_TEST_SRCS := \ $(PREPROCESSOR_1K_SRCS) \ - tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc \ - tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/system_apollo3.c \ + $(AP3_MICRO_DIR)/../fixed_point/preprocessor.cc \ + $(AP3_EXT_MICRO_DIR)/system_apollo3.c \ $(AP3_MICRO_DIR)/_main.c PUSHBUTTON_MICRO_SPEECH_TEST_SRCS := \ @@ -132,7 +134,7 @@ ifeq ($(TARGET), apollo3evb) $(AP3_MICRO_DIR)/pushbutton_test.cc \ $(AP3_MICRO_DIR)/../tiny_conv_model_data.cc \ $(CMSIS_DIR)/preprocessor.cc \ - $(CMSIS_DIR)/arm_cmplx_mag_squared_q10p6.c \ + $(CMSIS_EXT_DIR)/arm_cmplx_mag_squared_q10p6.c \ $(CMSIS_DIR)/hanning.c \ $(APOLLO3_SDK)/devices/am_devices_led.c \ $(CMSIS_SRCS) -- GitLab From 5657221c1efeef26d17991f6170d5e4ce353a522 Mon Sep 17 00:00:00 2001 From: wenxizhu Date: Wed, 19 Dec 2018 09:45:33 +0800 Subject: [PATCH 0092/1765] Use TF_CHECK_OK() to check: 1. perm_node->attr(); 2. AddEdge(). --- tensorflow/core/graph/mkl_layout_pass.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tensorflow/core/graph/mkl_layout_pass.cc b/tensorflow/core/graph/mkl_layout_pass.cc index 56c31d5c84..b203cd3de5 100644 --- a/tensorflow/core/graph/mkl_layout_pass.cc +++ b/tensorflow/core/graph/mkl_layout_pass.cc @@ -1025,8 +1025,7 @@ class MklLayoutRewritePass : public GraphOptimizationPass { e->dst_input() == kPermTensorIndex) { // we find the "perm" node, now try to retrieve its value. const TensorProto* proto = nullptr; - bool perm_has_value_attr = GetNodeAttr(perm_node->def(), "value", &proto).ok(); - DCHECK(perm_has_value_attr); + TF_CHECK_OK(GetNodeAttr(perm_node->def(), "value", &proto)); DataType type; GetNodeAttr(perm_node->def(), "dtype", &type); @@ -3111,9 +3110,9 @@ Status MklLayoutRewritePass::FuseTransposeMklOpTranspose( for (const Edge* e : transpose_to_nchw->out_edges()) { if (!e->IsControlEdge()) { const int kTransposeWithMklOpOutputSlot = 0; - bool succ_add_edge = (*g)->AddEdge(new_node, kTransposeWithMklOpOutputSlot, e->dst(), - e->dst_input()); - DCHECK(succ_add_edge); + auto new_edge = (*g)->AddEdge(new_node, kTransposeWithMklOpOutputSlot, e->dst(), + e->dst_input()); + DCHECK(new_edge); } } -- GitLab From c5720d1626c3c7e85069b0436bffacc8c6ca8122 Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Wed, 19 Dec 2018 11:54:28 +0100 Subject: [PATCH 0093/1765] Update testBucketDropReminder test case See #24071 --- .../bucket_by_sequence_length_test.py | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py index e0978676fd..a95d8e1049 100644 --- a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py @@ -76,11 +76,12 @@ def _get_record_shape(sparse): @test_util.run_all_in_graph_and_eager_modes class BucketBySequenceLengthTest(test_base.DatasetTestBase, parameterized.TestCase): + # TODO(b/117581999): add eager coverage. @parameterized.named_parameters( ("WithoutPadding", True), ("WithPadding", False), ) - def testBucketDropReminder(self, param_no_padding): + def testSkipEagerBucketDropReminder(self, param_no_padding): boundaries = [10, 20, 30] batch_sizes = [10, 8, 4, 2] @@ -142,14 +143,15 @@ class BucketBySequenceLengthTest(test_base.DatasetTestBase, parameterized.TestCa batch_sizes, no_padding=no_padding, drop_remainder=True)) - batch, = dataset.make_one_shot_iterator().get_next() - - with self.cached_session() as sess: - batches = [] - for _ in range(n_expected_batches): - batches.append(self.evaluate(batch)) - with self.assertRaises(errors.OutOfRangeError): - self.evaluate(batch) + + get_next = self.getNext(dataset) + batches = [] + for _ in range(n_expected_batches): + batch, = self.evaluate(get_next()) + batches.append(batch) + + with self.assertRaises(errors.OutOfRangeError): + self.evaluate(get_next()) generated_lengths = [] -- GitLab From c30e6b769f8f6be9d93372a000ee330d7a5ec56a Mon Sep 17 00:00:00 2001 From: Ashwin Ramaswami Date: Wed, 19 Dec 2018 09:59:49 -0500 Subject: [PATCH 0094/1765] Update doc references to use tfp.distributions --- tensorflow/python/ops/distributions/bijector_impl.py | 2 +- .../python/ops/distributions/transformed_distribution.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tensorflow/python/ops/distributions/bijector_impl.py b/tensorflow/python/ops/distributions/bijector_impl.py index 9c63385dd0..a347cfdec1 100644 --- a/tensorflow/python/ops/distributions/bijector_impl.py +++ b/tensorflow/python/ops/distributions/bijector_impl.py @@ -462,7 +462,7 @@ class Bijector(object): ```python - abs = tf.contrib.distributions.bijectors.AbsoluteValue() + abs = tfp.distributions.bijectors.AbsoluteValue() abs.forward(-1.) ==> 1. diff --git a/tensorflow/python/ops/distributions/transformed_distribution.py b/tensorflow/python/ops/distributions/transformed_distribution.py index 1becfc1877..3c6476864a 100644 --- a/tensorflow/python/ops/distributions/transformed_distribution.py +++ b/tensorflow/python/ops/distributions/transformed_distribution.py @@ -167,7 +167,7 @@ class TransformedDistribution(distribution_lib.Distribution): distribution: ```python - ds = tf.contrib.distributions + ds = tfp.distributions log_normal = ds.TransformedDistribution( distribution=ds.Normal(loc=0., scale=1.), bijector=ds.bijectors.Exp(), @@ -177,7 +177,7 @@ class TransformedDistribution(distribution_lib.Distribution): A `LogNormal` made from callables: ```python - ds = tf.contrib.distributions + ds = tfp.distributions log_normal = ds.TransformedDistribution( distribution=ds.Normal(loc=0., scale=1.), bijector=ds.bijectors.Inline( @@ -191,7 +191,7 @@ class TransformedDistribution(distribution_lib.Distribution): Another example constructing a Normal from a StandardNormal: ```python - ds = tf.contrib.distributions + ds = tfp.distributions normal = ds.TransformedDistribution( distribution=ds.Normal(loc=0., scale=1.), bijector=ds.bijectors.Affine( @@ -209,7 +209,7 @@ class TransformedDistribution(distribution_lib.Distribution): multivariate Normal as a `TransformedDistribution`. ```python - ds = tf.contrib.distributions + ds = tfp.distributions # We will create two MVNs with batch_shape = event_shape = 2. mean = [[-1., 0], # batch:0 [0., 1]] # batch:1 -- GitLab From 5bbdac505efbc4decaf7f15b247a26060fe25d46 Mon Sep 17 00:00:00 2001 From: Mark Daoust Date: Wed, 19 Dec 2018 12:39:03 -0800 Subject: [PATCH 0095/1765] Update lookup_ops.py --- tensorflow/python/ops/lookup_ops.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow/python/ops/lookup_ops.py b/tensorflow/python/ops/lookup_ops.py index 9302696a45..70bbbb72e6 100644 --- a/tensorflow/python/ops/lookup_ops.py +++ b/tensorflow/python/ops/lookup_ops.py @@ -64,6 +64,7 @@ def initialize_all_tables(name="init_all_tables"): @tf_export(v1=["initializers.tables_initializer", "tables_initializer"]) def tables_initializer(name="init_all_tables"): """Returns an Op that initializes all tables of the default graph. + See the [Low Level Intro](https://www.tensorflow.org/guide/low_level_intro#feature_columns) guide, for an example of usage. -- GitLab From 2eb720ce512edef25a2ee13647255c245506cbfe Mon Sep 17 00:00:00 2001 From: Austin Anderson Date: Tue, 18 Dec 2018 16:36:59 -0800 Subject: [PATCH 0096/1765] Fix some typos and add built-tags output support This change makes some minor changes: - Fix some typos - Add a "test your changes" example to the README - Add a --nocache flag to ignore the Docker build cache - Add a --write_tags_to flag to save a clean list of built tags to a file. Can be used to build tags, then run tests in parallel by combining xargs with --only_tags_matching. --- tensorflow/tools/dockerfiles/README.md | 19 ++++++++++-------- tensorflow/tools/dockerfiles/assembler.py | 24 ++++++++++++++++++++++- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/tensorflow/tools/dockerfiles/README.md b/tensorflow/tools/dockerfiles/README.md index b42dd9fc0c..6bb94bfa34 100644 --- a/tensorflow/tools/dockerfiles/README.md +++ b/tensorflow/tools/dockerfiles/README.md @@ -29,12 +29,12 @@ in the Dockerfile itself. After building the image with the tag `tf` (for example), use `docker run` to run the images. -Note for new Docker users: the `-v` and `-u` flags share directories between -the Docker container and your machine, and very important. Without -`-v`, your work will be wiped once the container quits, and without `-u`, files -created by the container will have the wrong file permissions on your host -machine. If you are confused, check out the [Docker run -documentation](https://docs.docker.com/engine/reference/run/). +Note for new Docker users: the `-v` and `-u` flags share directories and +permissions between the Docker container and your machine. Without `-v`, your +work will be wiped once the container quits, and without `-u`, files created by +the container will have the wrong file permissions on your host machine. +Check out the [Docker run +documentation](https://docs.docker.com/engine/reference/run/) for more info. ```bash # Volume mount (-v) is optional but highly recommended, especially for Jupyter. @@ -83,7 +83,7 @@ $ alias asm_images="docker run --rm -v $(pwd):/tf -v /var/run/docker.sock:/var/r # If you're REBUILDING OR ADDING DOCKERFILES, remove docker.sock and add -u: $ alias asm_dockerfiles="docker run --rm -u $(id -u):$(id -g) -v $(pwd):/tf tf-tools python3 assembler.py " -# Check flags +# Check assembler flags $ asm_dockerfiles --help # Assemble all of the Dockerfiles @@ -93,5 +93,8 @@ $ asm_dockerfiles --release dockerfiles --construct_dockerfiles $ asm_images --release nightly --build_images # Build version release for version 99.0, except "gpu" tags: -$ asm_images --release versioned --arg _TAG_PREFIX=99.0 --build_images --exclude_tags_matching '*.gpu.*' +$ asm_images --release versioned --arg _TAG_PREFIX=99.0 --build_images --exclude_tags_matching '.*gpu.*' + +# Test your changes to the devel images: +$ asm_images --release nightly --build_images --run_tests_path=$(realpath tests) --only_tags_matching="^devel-gpu-py3$" ``` diff --git a/tensorflow/tools/dockerfiles/assembler.py b/tensorflow/tools/dockerfiles/assembler.py index 67a0320241..a73a701971 100644 --- a/tensorflow/tools/dockerfiles/assembler.py +++ b/tensorflow/tools/dockerfiles/assembler.py @@ -49,7 +49,7 @@ flags.DEFINE_string('hub_username', None, flags.DEFINE_string( 'hub_password', None, ('Dockerhub password, only used with --upload_to_hub. Use from an env param' - 'so your password isn\'t in your history.')) + ' so your password isn\'t in your history.')) flags.DEFINE_integer('hub_timeout', 3600, 'Abort Hub upload if it takes longer than this.') @@ -89,6 +89,11 @@ flags.DEFINE_string( 'Flag value must be a full path to the "tests" directory, which is usually' ' $(realpath ./tests). A failed tests counts the same as a failed build.')) +flags.DEFINE_string( + 'write_tags_to', None, + 'Write the list of tagged images to a file. Useful for parallelizing tests.' +) + flags.DEFINE_boolean( 'stop_on_failure', False, ('Stop processing tags if any one build fails. If False or not specified, ' @@ -142,6 +147,10 @@ flags.DEFINE_multi_string( 'args will print a warning).'), short_name='a') +flags.DEFINE_boolean( + 'nocache', False, + 'Disable the Docker build cache; identical to "docker build --no-cache"') + flags.DEFINE_string( 'spec_file', './spec.yml', @@ -513,6 +522,7 @@ def main(argv): # Each tag has a name ('tag') and a definition consisting of the contents # of its Dockerfile, its build arg list, etc. failed_tags = [] + succeeded_tags = [] for tag, tag_defs in all_tags.items(): for tag_def in tag_defs: eprint('> Working on {}'.format(tag)) @@ -569,6 +579,7 @@ def main(argv): image, logs = dock.images.build( timeout=FLAGS.hub_timeout, path='.', + nocache=FLAGS.nocache, dockerfile=dockerfile, buildargs=tag_def['cli_args'], tag=repo_tag) @@ -656,12 +667,23 @@ def main(argv): args=(FLAGS.hub_repository, dock, image, tag)) p.start() + if not tag_failed: + succeeded_tags.append(tag) + if failed_tags: eprint( '> Some tags failed to build or failed testing, check scrollback for ' 'errors: {}'.format(','.join(failed_tags))) exit(1) + if FLAGS.write_tags_to: + eprint('> Writing built{} tags to {}.'.format( + ' and tested' if FLAGS.run_tests_path else '', + FLAGS.write_tags_to)) + with open(FLAGS.write_tags_to, 'w') as f: + for tag in succeeded_tags: + f.write('{}:{}\n'.format(FLAGS.repository, tag)) + if __name__ == '__main__': app.run(main) -- GitLab From 55cc35ca35e1dfae9e39c02b8b1387cb9fd07fec Mon Sep 17 00:00:00 2001 From: Austin Anderson Date: Wed, 19 Dec 2018 10:11:10 -0800 Subject: [PATCH 0097/1765] Change file output to stdout --- tensorflow/tools/dockerfiles/README.md | 3 +++ tensorflow/tools/dockerfiles/assembler.py | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tensorflow/tools/dockerfiles/README.md b/tensorflow/tools/dockerfiles/README.md index 6bb94bfa34..4e8b6b1b04 100644 --- a/tensorflow/tools/dockerfiles/README.md +++ b/tensorflow/tools/dockerfiles/README.md @@ -92,6 +92,9 @@ $ asm_dockerfiles --release dockerfiles --construct_dockerfiles # Build all of the "nightly" images on your local machine: $ asm_images --release nightly --build_images +# Save the list of built images to a file: +$ asm_images --release nightly --build_images > tf-built.txt + # Build version release for version 99.0, except "gpu" tags: $ asm_images --release versioned --arg _TAG_PREFIX=99.0 --build_images --exclude_tags_matching '.*gpu.*' diff --git a/tensorflow/tools/dockerfiles/assembler.py b/tensorflow/tools/dockerfiles/assembler.py index a73a701971..d8f2e48411 100644 --- a/tensorflow/tools/dockerfiles/assembler.py +++ b/tensorflow/tools/dockerfiles/assembler.py @@ -18,6 +18,9 @@ - Builds images (and optionally runs image tests) - Pushes images to Docker Hub (provided with credentials) +Logs are written to stderr; the list of successfully built images is +written to stdout. + Read README.md (in this directory) for instructions! """ @@ -676,13 +679,10 @@ def main(argv): 'errors: {}'.format(','.join(failed_tags))) exit(1) - if FLAGS.write_tags_to: - eprint('> Writing built{} tags to {}.'.format( - ' and tested' if FLAGS.run_tests_path else '', - FLAGS.write_tags_to)) - with open(FLAGS.write_tags_to, 'w') as f: - for tag in succeeded_tags: - f.write('{}:{}\n'.format(FLAGS.repository, tag)) + eprint('> Writing built{} tags to standard out.'.format( + ' and tested' if FLAGS.run_tests_path else '')) + for tag in succeeded_tags: + print('{}:{}'.format(FLAGS.repository, tag)) if __name__ == '__main__': -- GitLab From 933bb8adbf9c3dd52ba487b44e2916009636e0b7 Mon Sep 17 00:00:00 2001 From: Austin Anderson Date: Wed, 19 Dec 2018 10:13:58 -0800 Subject: [PATCH 0098/1765] Remove old flag --- tensorflow/tools/dockerfiles/assembler.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tensorflow/tools/dockerfiles/assembler.py b/tensorflow/tools/dockerfiles/assembler.py index d8f2e48411..09537b7314 100644 --- a/tensorflow/tools/dockerfiles/assembler.py +++ b/tensorflow/tools/dockerfiles/assembler.py @@ -92,11 +92,6 @@ flags.DEFINE_string( 'Flag value must be a full path to the "tests" directory, which is usually' ' $(realpath ./tests). A failed tests counts the same as a failed build.')) -flags.DEFINE_string( - 'write_tags_to', None, - 'Write the list of tagged images to a file. Useful for parallelizing tests.' -) - flags.DEFINE_boolean( 'stop_on_failure', False, ('Stop processing tags if any one build fails. If False or not specified, ' -- GitLab From 9e92c2fe264debad1548554182dcc9af06d2e6ee Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Wed, 19 Dec 2018 13:48:25 -0800 Subject: [PATCH 0099/1765] Fix bug with renaming output bindings --- tensorflow/contrib/tensorrt/BUILD | 1 + .../contrib/tensorrt/convert/convert_nodes.cc | 17 +++++ .../tensorrt/test/identity_output_test.py | 72 +++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 tensorflow/contrib/tensorrt/test/identity_output_test.py diff --git a/tensorflow/contrib/tensorrt/BUILD b/tensorflow/contrib/tensorrt/BUILD index 784acce444..3e8c486d8c 100644 --- a/tensorflow/contrib/tensorrt/BUILD +++ b/tensorflow/contrib/tensorrt/BUILD @@ -491,6 +491,7 @@ cuda_py_tests( "test/binary_tensor_weight_broadcast_test.py", "test/concatenation_test.py", "test/const_broadcast_test.py", + "test/identity_output_test.py", "test/manual_test.py", "test/memory_alignment_test.py", "test/multi_connection_neighbor_engine_test.py", diff --git a/tensorflow/contrib/tensorrt/convert/convert_nodes.cc b/tensorflow/contrib/tensorrt/convert/convert_nodes.cc index adf8831b96..729afe6c64 100644 --- a/tensorflow/contrib/tensorrt/convert/convert_nodes.cc +++ b/tensorflow/contrib/tensorrt/convert/convert_nodes.cc @@ -879,6 +879,8 @@ Status Converter::ConvertNode(const NodeDef& node_def) { // We need to check the name before setting it. If the input is one of the // engine input, setting the name here will overwrite engine input // bindings which will cause runtime error. + // TODO(tmorris): Remove this work-around once we use TRT's IIdentityLayer + // in ConvertIdentity. if (output.is_tensor()) { const char* tensor_name = output.tensor()->getName(); if (!tensorflow::str_util::StartsWith(tensor_name, kInputPHName)) { @@ -939,6 +941,21 @@ Status Converter::RenameAndMarkOutputTensors( if (tensor == nullptr) { return errors::NotFound("Output tensor not found: ", output.first); } + // Check if this tensor has already been marked as an output. + // ConvertIdentity can cause the same tensor to be repeated in + // output_tensors, which can cause us to overwrite the name of the output + // tensor binding. For example, if we rename OutputPH_0 to OutputPH_1 then + // we won't be able to locate OutputPH_0 during runtime. To fix this, + // duplicate the tensor using no-op shuffle. + // TODO(tmorris): Remove this work-around once we use TRT's IIdentityLayer + // in ConvertIdentity. + if (tensorflow::str_util::StartsWith(tensor->getName(), kOutputPHName)) { + nvinfer1::IShuffleLayer* layer = network()->addShuffle(*tensor); + TFTRT_RETURN_ERROR_IF_NULLPTR( + layer, StrCat("Output Copy for ", tensor->getName())); + MarkQuantizationRangesAsInferrable(tensor, layer->getOutput(0)); + tensor = layer->getOutput(0); + } tensor->setName(output.second.c_str()); VLOG(1) << "Marking output tensor " << output.first << ", as output tensor " << output.second; diff --git a/tensorflow/contrib/tensorrt/test/identity_output_test.py b/tensorflow/contrib/tensorrt/test/identity_output_test.py new file mode 100644 index 0000000000..391434ba83 --- /dev/null +++ b/tensorflow/contrib/tensorrt/test/identity_output_test.py @@ -0,0 +1,72 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Model script to test TF-TensorRT integration.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.contrib.tensorrt.test import tf_trt_integration_test_base as trt_test +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import ops +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gen_array_ops +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import nn +from tensorflow.python.platform import test + + +class IdentityTest(trt_test.TfTrtIntegrationTestBase): + + def _ConstOp(self, shape): + return constant_op.constant(np.random.randn(*shape), dtype=dtypes.float32) + + def GetParams(self): + """Testing conversion of BiasAdd MatMul in TF-TRT conversion.""" + input_name = "input" + input_dims = [100, 32] + g = ops.Graph() + with g.as_default(): + x = array_ops.placeholder( + dtype=dtypes.float32, shape=input_dims, name=input_name) + + b = self._ConstOp((32, 4)) + x1 = math_ops.matmul(x, b) + b = self._ConstOp((1, 4)) + x1 = x1 + b + + out1 = array_ops.identity(x1, name='output1') + out2 = array_ops.identity(x1, name='output2') + iden1 = array_ops.identity(x1) + out3 = array_ops.identity(iden1, name='output3') + + return trt_test.TfTrtIntegrationTestParams( + gdef=g.as_graph_def(), + input_names=[input_name], + input_dims=[input_dims], + output_names=['output1', 'output2', 'output3'], + expected_output_dims=[(100, 4), (100, 4), (100, 4)]) + + + def ExpectedEnginesToBuild(self, run_params): + """Return the expected engines to build.""" + return ["TRTEngineOp_0"] + + +if __name__ == "__main__": + test.main() -- GitLab From cfe7df2cf064f9eacdf8ab30574ebe9ec6438544 Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Wed, 19 Dec 2018 14:14:28 -0800 Subject: [PATCH 0100/1765] Update comment in test --- tensorflow/contrib/tensorrt/test/identity_output_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/contrib/tensorrt/test/identity_output_test.py b/tensorflow/contrib/tensorrt/test/identity_output_test.py index 391434ba83..1aa05999bd 100644 --- a/tensorflow/contrib/tensorrt/test/identity_output_test.py +++ b/tensorflow/contrib/tensorrt/test/identity_output_test.py @@ -37,7 +37,7 @@ class IdentityTest(trt_test.TfTrtIntegrationTestBase): return constant_op.constant(np.random.randn(*shape), dtype=dtypes.float32) def GetParams(self): - """Testing conversion of BiasAdd MatMul in TF-TRT conversion.""" + """Testing engine with the same tensor repeated as output via identity.""" input_name = "input" input_dims = [100, 32] g = ops.Graph() -- GitLab From f03cf64b1295ea4e9e431a7a524cc23b2c1f3306 Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Wed, 19 Dec 2018 15:10:58 -0800 Subject: [PATCH 0101/1765] Explain usage of shuffle layer --- tensorflow/contrib/tensorrt/convert/convert_nodes.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow/contrib/tensorrt/convert/convert_nodes.cc b/tensorflow/contrib/tensorrt/convert/convert_nodes.cc index 729afe6c64..2a402fe699 100644 --- a/tensorflow/contrib/tensorrt/convert/convert_nodes.cc +++ b/tensorflow/contrib/tensorrt/convert/convert_nodes.cc @@ -950,6 +950,7 @@ Status Converter::RenameAndMarkOutputTensors( // TODO(tmorris): Remove this work-around once we use TRT's IIdentityLayer // in ConvertIdentity. if (tensorflow::str_util::StartsWith(tensor->getName(), kOutputPHName)) { + // Using shuffle layer for identity by not setting reshape or transpose. nvinfer1::IShuffleLayer* layer = network()->addShuffle(*tensor); TFTRT_RETURN_ERROR_IF_NULLPTR( layer, StrCat("Output Copy for ", tensor->getName())); -- GitLab From d489a943a0fbb995d48ee70558270c4a5f0f9c39 Mon Sep 17 00:00:00 2001 From: Taylor Thornton Date: Tue, 18 Dec 2018 22:19:59 -0800 Subject: [PATCH 0102/1765] upgrade aws-sdk-cpp to 1.5.8 in order to pick up the auth retry changeset that landed in that version --- third_party/aws/BUILD.bazel | 5 +++++ third_party/aws/workspace.bzl | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/third_party/aws/BUILD.bazel b/third_party/aws/BUILD.bazel index 5426f79e46..1f61858777 100644 --- a/third_party/aws/BUILD.bazel +++ b/third_party/aws/BUILD.bazel @@ -80,6 +80,11 @@ cc_library( deps = [ "@curl", ], + copts = [ + "-DAWS_SDK_VERSION_MAJOR=1", + "-DAWS_SDK_VERSION_MINOR=5", + "-DAWS_SDK_VERSION_PATCH=8" + ], ) template_rule( diff --git a/third_party/aws/workspace.bzl b/third_party/aws/workspace.bzl index c216638154..10799b5153 100644 --- a/third_party/aws/workspace.bzl +++ b/third_party/aws/workspace.bzl @@ -2,14 +2,17 @@ load("//third_party:repo.bzl", "third_party_http_archive") +# NOTE: version updates here should also update the major, minor, and patch variables declared in +# the copts field of the //third_party/aws:aws target + def repo(): third_party_http_archive( name = "aws", urls = [ - "https://mirror.bazel.build/github.com/aws/aws-sdk-cpp/archive/1.3.15.tar.gz", - "https://github.com/aws/aws-sdk-cpp/archive/1.3.15.tar.gz", + "https://mirror.bazel.build/github.com/aws/aws-sdk-cpp/archive/1.5.8.tar.gz", + "https://github.com/aws/aws-sdk-cpp/archive/1.5.8.tar.gz", ], - sha256 = "b888d8ce5fc10254c3dd6c9020c7764dd53cf39cf011249d0b4deda895de1b7c", - strip_prefix = "aws-sdk-cpp-1.3.15", + sha256 = "89905075fe50aa13e0337ff905c2e8c1ce9caf77a3504484a7cda39179120ffc", + strip_prefix = "aws-sdk-cpp-1.5.8", build_file = "//third_party/aws:BUILD.bazel", ) -- GitLab From c75023169590ef0534579758285d6a1d8ad54ad2 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Wed, 19 Dec 2018 23:38:51 +0000 Subject: [PATCH 0103/1765] Replace deprecated FastGFile with GFile FastGFile has been deprecated and replaced with GFile, though the example in speech_commands still uses FastGFile. This fix fix the issue to remove the deprecated warning: ``` WARNING:tensorflow:From :1: __init__ (from tensorflow.python.platform.gfile) is deprecated and will be removed in a future version. Instructions for updating: Use tf.gfile.GFile. ``` Signed-off-by: Yong Tang --- tensorflow/examples/speech_commands/label_wav.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/examples/speech_commands/label_wav.py b/tensorflow/examples/speech_commands/label_wav.py index 0017aec3a5..eb8323454c 100644 --- a/tensorflow/examples/speech_commands/label_wav.py +++ b/tensorflow/examples/speech_commands/label_wav.py @@ -45,7 +45,7 @@ FLAGS = None def load_graph(filename): """Unpersists graph from file as default graph.""" - with tf.gfile.FastGFile(filename, 'rb') as f: + with tf.gfile.GFile(filename, 'rb') as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) tf.import_graph_def(graph_def, name='') -- GitLab From 4696da4bf9a586cf250b32a062da833af3ffd4a9 Mon Sep 17 00:00:00 2001 From: Yong Tang Date: Wed, 19 Dec 2018 23:41:52 +0000 Subject: [PATCH 0104/1765] Also replace FastGFile to GFile in label_wav_dir.py Signed-off-by: Yong Tang --- tensorflow/examples/speech_commands/label_wav_dir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/examples/speech_commands/label_wav_dir.py b/tensorflow/examples/speech_commands/label_wav_dir.py index a34db512dd..2e1890c3e8 100644 --- a/tensorflow/examples/speech_commands/label_wav_dir.py +++ b/tensorflow/examples/speech_commands/label_wav_dir.py @@ -46,7 +46,7 @@ FLAGS = None def load_graph(filename): """Unpersists graph from file as default graph.""" - with tf.gfile.FastGFile(filename, 'rb') as f: + with tf.gfile.GFile(filename, 'rb') as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) tf.import_graph_def(graph_def, name='') -- GitLab From 0f10d9fcd0c47b497d1bd5069f28d21f94fedc60 Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Wed, 19 Dec 2018 15:56:19 -0800 Subject: [PATCH 0105/1765] Improve comment --- tensorflow/contrib/tensorrt/test/identity_output_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tensorflow/contrib/tensorrt/test/identity_output_test.py b/tensorflow/contrib/tensorrt/test/identity_output_test.py index 1aa05999bd..2be9da9ede 100644 --- a/tensorflow/contrib/tensorrt/test/identity_output_test.py +++ b/tensorflow/contrib/tensorrt/test/identity_output_test.py @@ -12,7 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Model script to test TF-TensorRT integration.""" +"""This test checks a situation where the same tensor is considered as an output +multiple times because it has been duplicated by 2+ indentity ops. Previously, +the tensor would be renamed multiple times, overwriting the output binding name +which resulted in a runtime error when the binding would not be found. +""" from __future__ import absolute_import from __future__ import division -- GitLab From cc3e7217aeb92d289834fa5409f37a59f5918777 Mon Sep 17 00:00:00 2001 From: Arpit Shah Date: Wed, 19 Dec 2018 18:13:39 -0600 Subject: [PATCH 0106/1765] Fixed header --- .../examples/micro_speech/CMSIS/create_constants.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/create_constants.py b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/create_constants.py index c7cf8bf61b..732ae5f7f5 100755 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/create_constants.py +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/create_constants.py @@ -1,16 +1,17 @@ -# SPDX-License-Identifier: Apache-2.0 +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. # -# Licensed under the Apache License, Version 2.0 (the License); you may -# not use this file except in compliance with the License. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an AS IS BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +# ============================================================================== import soundfile as sf import numpy as np -- GitLab From caf2d701d27bf5b2e9378db5dfa63e08054ff497 Mon Sep 17 00:00:00 2001 From: Mark Daoust Date: Wed, 19 Dec 2018 13:08:19 -0800 Subject: [PATCH 0107/1765] fix git clone command. Fixes #24286 PiperOrigin-RevId: 226221213 --- tensorflow/lite/experimental/micro/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/lite/experimental/micro/README.md b/tensorflow/lite/experimental/micro/README.md index 673daed74c..e20efb2253 100644 --- a/tensorflow/lite/experimental/micro/README.md +++ b/tensorflow/lite/experimental/micro/README.md @@ -31,7 +31,7 @@ This initial preview release is designed to get early feedback, and is not inten Building requires a Linux or OS X machine. - Open a terminal - - Download the TensorFlow source with `git clone https://github.com/tensorflow` + - Download the TensorFlow source with `git clone https://github.com/tensorflow/tensorflow.git` - Enter the source root directory by running `cd tensorflow` - Download the dependencies by running `tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh`. This may take a few minutes - Build and test the library with `make -f tensorflow/lite/experimental/micro/tools/make/Makefile test` -- GitLab From 7faefa4bb665e115cc744d7895a407338624993f Mon Sep 17 00:00:00 2001 From: Clayne Robison Date: Wed, 19 Dec 2018 19:08:29 -0700 Subject: [PATCH 0108/1765] This PR tempers the unused CPU instruction warning when TensorFlow is built with support for Intel(R) MKL-DNN. Many customers have complained about this warning because they don't understand that MKL-DNN has support for JIT compilation that detects CPU features at runtime. --- tensorflow/core/platform/cpu_feature_guard.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tensorflow/core/platform/cpu_feature_guard.cc b/tensorflow/core/platform/cpu_feature_guard.cc index 2efe0c0876..3f0d1cdb51 100644 --- a/tensorflow/core/platform/cpu_feature_guard.cc +++ b/tensorflow/core/platform/cpu_feature_guard.cc @@ -139,7 +139,19 @@ void InfoAboutUnusedCPUFeatures() { #endif // else of if defined(_MSC_VER) && !defined(__clang__) if (!missing_instructions.empty()) { LOG(INFO) << "Your CPU supports instructions that this TensorFlow " +#ifndef INTEL_MKL << "binary was not compiled to use:" << missing_instructions; +#else + << "binary was not compiled to use:" << missing_instructions + << ". When TensorFlow is compiled with support for these " + << "instructions, performance can improve. However, because " + << "this version of TensorFlow has been compiled with support " + << "for Intel(R) MKL-DNN, which supports just-in-time " + << "compilation, many performance-critical codepaths will use " + << "these instructions, even though TensorFlow was compiled " + << "without explicit support them. See " + << "https://github.com/intel/mkl-dnn/issues/3"; +#endif } }); } -- GitLab From 5adc74c3e4cac1de5945377dad419484d0c3b794 Mon Sep 17 00:00:00 2001 From: Rohan Jain Date: Wed, 19 Dec 2018 13:08:34 -0800 Subject: [PATCH 0109/1765] Now that we have the Captured Function fix and create dataset kernels as we go, we can re-enable this dataset structure test in Eager mode. PiperOrigin-RevId: 226221250 --- tensorflow/python/data/kernel_tests/dataset_test.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tensorflow/python/data/kernel_tests/dataset_test.py b/tensorflow/python/data/kernel_tests/dataset_test.py index 8193dffc7d..db8a999491 100644 --- a/tensorflow/python/data/kernel_tests/dataset_test.py +++ b/tensorflow/python/data/kernel_tests/dataset_test.py @@ -209,7 +209,6 @@ class DatasetTest(test_base.DatasetTestBase, parameterized.TestCase): self.assertEqual(2, inputs.count(ds2)) self.assertEqual(1, inputs.count(ds3)) - # TODO(b/119882922): use-after-free bug in eager mode. # pylint: disable=g-long-lambda @parameterized.named_parameters( ("Tensor", lambda: constant_op.constant(37.0), @@ -233,8 +232,7 @@ class DatasetTest(test_base.DatasetTestBase, parameterized.TestCase): optional_ops.OptionalStructure( structure.TensorStructure(dtypes.float32, []))), ) - def testSkipEagerDatasetStructure(self, tf_value_fn, - expected_element_structure): + def testDatasetStructure(self, tf_value_fn, expected_element_structure): dataset = dataset_ops.Dataset.from_tensors(0).map(lambda _: tf_value_fn()) dataset_structure = structure.Structure.from_value(dataset) self.assertIsInstance(dataset_structure, dataset_ops.DatasetStructure) -- GitLab From 915b8783a05b0da7c30ba36531ce03c811930852 Mon Sep 17 00:00:00 2001 From: Clayne Robison Date: Wed, 19 Dec 2018 19:13:27 -0700 Subject: [PATCH 0110/1765] [Intel MKL] Remove TensorFlow lite test from the public CI. MKL does not support TF lite. --- tensorflow/tools/ci_build/linux/cpu/run_mkl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/tools/ci_build/linux/cpu/run_mkl.sh b/tensorflow/tools/ci_build/linux/cpu/run_mkl.sh index 7be5f454ec..a8b73cbe0c 100755 --- a/tensorflow/tools/ci_build/linux/cpu/run_mkl.sh +++ b/tensorflow/tools/ci_build/linux/cpu/run_mkl.sh @@ -36,4 +36,4 @@ yes "" | $PYTHON_BIN_PATH configure.py bazel test --test_tag_filters=-no_oss,-oss_serial,-gpu,-benchmark-test --test_lang_filters=cc,py -k \ --jobs=${N_JOBS} --test_timeout 300,450,1200,3600 --build_tests_only \ --config=mkl --test_env=KMP_BLOCKTIME=0 --config=opt --test_output=errors -- \ - //tensorflow/... -//tensorflow/compiler/... -//tensorflow/contrib/... + //tensorflow/... -//tensorflow/compiler/... -//tensorflow/contrib/... -//tensorflow/lite/... -- GitLab From 2f2344684c2a0e6af17248da94f9a2c6835d6dea Mon Sep 17 00:00:00 2001 From: Andrew Selle Date: Wed, 19 Dec 2018 13:11:07 -0800 Subject: [PATCH 0111/1765] Handle Python 2 and Python 3 compatibility by forcing to bytes. This had previously been done but not uniformly. Change to remove #!/usr/bin/env python in October caused this problems in latest release. PiperOrigin-RevId: 226221579 --- tensorflow/tools/git/gen_git_source.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tensorflow/tools/git/gen_git_source.py b/tensorflow/tools/git/gen_git_source.py index 8e7cd9b104..645d817d9f 100755 --- a/tensorflow/tools/git/gen_git_source.py +++ b/tensorflow/tools/git/gen_git_source.py @@ -159,12 +159,14 @@ def get_git_version(git_base_path, git_tag_override): """ unknown_label = b"unknown" try: + # Force to bytes so this works on python 2 and python 3 val = bytes(subprocess.check_output([ "git", str("--git-dir=%s/.git" % git_base_path), str("--work-tree=" + git_base_path), "describe", "--long", "--tags" ]).strip()) + version_separator = b"-" if git_tag_override and val: - split_val = val.split("-") + split_val = val.split(version_separator) if len(split_val) < 3: raise Exception( ("Expected git version in format 'TAG-COMMITS AFTER TAG-HASH' " @@ -173,7 +175,7 @@ def get_git_version(git_base_path, git_tag_override): # two "-" are those inserted by the git describe command. abbrev_commit = split_val[-1] val = bytes( - "-".join([git_tag_override, "0", abbrev_commit])) + version_separator.join([git_tag_override, "0", abbrev_commit])) return val if val else unknown_label except (subprocess.CalledProcessError, OSError): return unknown_label -- GitLab From ca24162a806e63d6a058489863b989b09edf43e9 Mon Sep 17 00:00:00 2001 From: Allen Lavoie Date: Wed, 19 Dec 2018 13:31:26 -0800 Subject: [PATCH 0112/1765] Silence __del__ exceptions We have tests that they do their job, so printing exceptions is pointless PiperOrigin-RevId: 226224643 --- tensorflow/python/eager/function.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tensorflow/python/eager/function.py b/tensorflow/python/eager/function.py index 8b8f6af93b..58d1f6b886 100644 --- a/tensorflow/python/eager/function.py +++ b/tensorflow/python/eager/function.py @@ -1763,9 +1763,12 @@ class _PolymorphicFunctionGarbageCollector(object): def __del__(self): if func_graph_module is None or memory is None: return - while self._cache: - self._cache.popitem() - memory.dismantle_ordered_dict(self._cache) + try: + while self._cache: + self._cache.popitem() + memory.dismantle_ordered_dict(self._cache) + except: # pylint: disable=bare-except + pass class _FunctionGarbageCollector(object): @@ -1781,4 +1784,7 @@ class _FunctionGarbageCollector(object): def __del__(self): if func_graph_module is None or memory is None or self._func_graph is None: return - func_graph_module.dismantle_func_graph(self._func_graph) + try: + func_graph_module.dismantle_func_graph(self._func_graph) + except: # pylint: disable=bare-except + pass -- GitLab From 0c4de546c11e90cd5b7401cec812a916b4c1298c Mon Sep 17 00:00:00 2001 From: Rohan Jain Date: Wed, 19 Dec 2018 13:31:47 -0800 Subject: [PATCH 0113/1765] Marking contrib/tpu:datasets_test as medium as it rarely times out PiperOrigin-RevId: 226224704 --- tensorflow/contrib/tpu/BUILD | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tensorflow/contrib/tpu/BUILD b/tensorflow/contrib/tpu/BUILD index ec8a273ea8..7664131813 100644 --- a/tensorflow/contrib/tpu/BUILD +++ b/tensorflow/contrib/tpu/BUILD @@ -337,6 +337,7 @@ py_library( tf_py_test( name = "datasets_test", + size = "medium", srcs = ["python/tpu/datasets_test.py"], additional_deps = [ "//tensorflow/python:client_testlib", @@ -344,6 +345,7 @@ tf_py_test( ], flaky = 1, # TODO(b/117363808): fails 1/1000 OSS runs grpc_enabled = True, + shard_count = 4, ) tf_py_test( -- GitLab From c1f29584c37df02bfc3eea654114e188284f5d74 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Wed, 19 Dec 2018 13:44:13 -0800 Subject: [PATCH 0114/1765] The error_interpolation.py code already traverses the graph and determines the nodes causing error, their inputs and their stacktraces. So we don't need the old error reporting framework. PiperOrigin-RevId: 226226764 --- .../python/framework/error_interpolation.py | 17 ++++++----- tensorflow/python/framework/errors_impl.py | 29 +++++++++++++++---- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/tensorflow/python/framework/error_interpolation.py b/tensorflow/python/framework/error_interpolation.py index 557f947291..b4f99017a2 100644 --- a/tensorflow/python/framework/error_interpolation.py +++ b/tensorflow/python/framework/error_interpolation.py @@ -29,7 +29,6 @@ import re import six -from tensorflow.python.framework.ops import Tensor from tensorflow.python.util import tf_stack _NAME_REGEX = r"[A-Za-z0-9.][A-Za-z0-9_.\-/]*?" @@ -270,7 +269,7 @@ def compute_field_dict(op, strip_file_prefix=""): return field_dict -def _common_prefix(all_ops): +def traceback_files_common_prefix(all_ops): """Determines the common prefix from the paths of the stacktrace of 'all_ops'. For example, if the paths are '/foo/bar/baz/' and '/foo/car', this would @@ -315,11 +314,13 @@ def _sources_for_node(name, graph): if name.startswith("^"): name = name[1:] try: - op = graph.as_graph_element(name) - except KeyError: - return - if isinstance(op, Tensor): - op = op.op + tensor = graph.get_tensor_by_name(name) + op = tensor.op + except (KeyError, ValueError): + try: + op = graph.get_operation_by_name(name) + except KeyError: + return name = op.name if name in seen_names: return @@ -398,7 +399,7 @@ def interpolate(error_message, graph): else: tagged_ops.append([op] + _sources_for_node(op.name, graph)) - common_prefix = _common_prefix(tagged_ops) + common_prefix = traceback_files_common_prefix(tagged_ops) for tag, ops in zip(tags, tagged_ops): msg = "{{%s %s}}" % (tag.type, tag.name) if ops is not None: diff --git a/tensorflow/python/framework/errors_impl.py b/tensorflow/python/framework/errors_impl.py index faa4fa7c6f..ee2aa6eb44 100644 --- a/tensorflow/python/framework/errors_impl.py +++ b/tensorflow/python/framework/errors_impl.py @@ -24,12 +24,31 @@ import warnings from tensorflow.core.lib.core import error_codes_pb2 from tensorflow.python import pywrap_tensorflow as c_api from tensorflow.python.framework import c_api_util +from tensorflow.python.framework import error_interpolation from tensorflow.python.util import compat from tensorflow.python.util import deprecation from tensorflow.python.util import tf_inspect +from tensorflow.python.util import tf_stack from tensorflow.python.util.tf_export import tf_export +def _compact_stack_trace(op): + """Returns a traceback for `op` with common file prefixes stripped.""" + compact_traces = [] + common_prefix = error_interpolation.traceback_files_common_prefix([[op]]) + # pylint: disable=protected-access + tf_traceback = tf_stack.convert_stack(op._traceback) + # pylint: enable=protected-access + for frame in tf_traceback: + frame = list(frame) + filename = frame[tf_stack.TB_FILENAME] + if filename.startswith(common_prefix): + filename = filename[len(common_prefix):] + frame[tf_stack.TB_FILENAME] = filename + compact_traces.append(tuple(frame)) + return compact_traces + + @tf_export("errors.OpError", v1=["errors.OpError", "OpError"]) @deprecation.deprecated_endpoints("OpError") class OpError(Exception): @@ -94,9 +113,10 @@ class OpError(Exception): def __str__(self): if self._op is not None: - output = ["%s\n\nCaused by op %r, defined at:\n" % (self.message, + output = ["%s\n\nOriginal stack trace for %r:\n" % (self.message, self._op.name,)] - curr_traceback_list = traceback.format_list(self._op.traceback) + curr_traceback_list = traceback.format_list( + _compact_stack_trace(self._op)) output.extend(curr_traceback_list) # pylint: disable=protected-access original_op = self._op._original_op @@ -106,7 +126,8 @@ class OpError(Exception): "\n...which was originally created as op %r, defined at:\n" % (original_op.name,)) prev_traceback_list = curr_traceback_list - curr_traceback_list = traceback.format_list(original_op.traceback) + curr_traceback_list = traceback.format_list( + _compact_stack_trace(original_op)) # Attempt to elide large common subsequences of the subsequent # stack traces. @@ -136,8 +157,6 @@ class OpError(Exception): # pylint: disable=protected-access original_op = original_op._original_op # pylint: enable=protected-access - output.append("\n%s (see above for traceback): %s\n" % - (type(self).__name__, self.message)) return "".join(output) else: return self.message -- GitLab From 1f7cf13a868db07aefc23c87afa597ec678cbb94 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Wed, 19 Dec 2018 13:45:05 -0800 Subject: [PATCH 0115/1765] Typo fix in docs. PiperOrigin-RevId: 226226879 --- tensorflow/python/ops/ragged/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/python/ops/ragged/__init__.py b/tensorflow/python/ops/ragged/__init__.py index 7806f56978..30ed9c53ab 100644 --- a/tensorflow/python/ops/ragged/__init__.py +++ b/tensorflow/python/ops/ragged/__init__.py @@ -21,7 +21,7 @@ different lengths. For example, the inner (column) dimension of `rt=[[3, 1, 4, 1], [], [5, 9, 2], [6], []]` is ragged, since the column slices (`rt[0, :]`, ..., `rt[4, :]`) have different lengths. For a more detailed description of ragged tensors, see the `tf.RaggedTensor` class documentation -and the [Ragged Tensor Guide](/guides/ragged_tensor). +and the [Ragged Tensor Guide](/guide/ragged_tensors). """ from __future__ import absolute_import -- GitLab From 9b34185c81d6d98ff3b254f6ed620346dabcb1c1 Mon Sep 17 00:00:00 2001 From: Rick Chao Date: Wed, 19 Dec 2018 14:03:34 -0800 Subject: [PATCH 0116/1765] Export estimator.experimental.stop_if_no_increase_hook and estimator.experimental.stop_if_no_decrease_hook to tf.estimator.experimental.*. PiperOrigin-RevId: 226229945 --- .../api/golden/v1/tensorflow.estimator.experimental.pbtxt | 8 ++++++++ .../api/golden/v2/tensorflow.estimator.experimental.pbtxt | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.pbtxt index 741102466d..b1bd5a2661 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.estimator.experimental.pbtxt @@ -40,4 +40,12 @@ tf_module { name: "stop_if_lower_hook" argspec: "args=[\'estimator\', \'metric_name\', \'threshold\', \'eval_dir\', \'min_steps\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'60\', \'None\'], " } + member_method { + name: "stop_if_no_decrease_hook" + argspec: "args=[\'estimator\', \'metric_name\', \'max_steps_without_decrease\', \'eval_dir\', \'min_steps\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'60\', \'None\'], " + } + member_method { + name: "stop_if_no_increase_hook" + argspec: "args=[\'estimator\', \'metric_name\', \'max_steps_without_increase\', \'eval_dir\', \'min_steps\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'60\', \'None\'], " + } } diff --git a/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.pbtxt index 741102466d..b1bd5a2661 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.estimator.experimental.pbtxt @@ -40,4 +40,12 @@ tf_module { name: "stop_if_lower_hook" argspec: "args=[\'estimator\', \'metric_name\', \'threshold\', \'eval_dir\', \'min_steps\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'60\', \'None\'], " } + member_method { + name: "stop_if_no_decrease_hook" + argspec: "args=[\'estimator\', \'metric_name\', \'max_steps_without_decrease\', \'eval_dir\', \'min_steps\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'60\', \'None\'], " + } + member_method { + name: "stop_if_no_increase_hook" + argspec: "args=[\'estimator\', \'metric_name\', \'max_steps_without_increase\', \'eval_dir\', \'min_steps\', \'run_every_secs\', \'run_every_steps\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'60\', \'None\'], " + } } -- GitLab From 08c051745904767b43e3007bc0e60d311e82fdaf Mon Sep 17 00:00:00 2001 From: Andrew Selle Date: Wed, 19 Dec 2018 14:05:12 -0800 Subject: [PATCH 0117/1765] Remove test that is no longer in respository. PiperOrigin-RevId: 226230363 --- tensorflow/tools/ci_build/builds/test_tutorials.sh | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tensorflow/tools/ci_build/builds/test_tutorials.sh b/tensorflow/tools/ci_build/builds/test_tutorials.sh index db335f14ca..a8672220c8 100755 --- a/tensorflow/tools/ci_build/builds/test_tutorials.sh +++ b/tensorflow/tools/ci_build/builds/test_tutorials.sh @@ -212,16 +212,6 @@ test_word2vec() { } -# ----------------------------------------------------------- -# Estimator: abalone -test_estimator_abalone() { - LOG_FILE=$1 - - run_in_directory "${TEST_DIR}" "${LOG_FILE}" \ - "tensorflow/examples/tutorials/estimators/abalone.py" -} - - # ----------------------------------------------------------- # ptb_word_lm test_ptb_word_lm() { -- GitLab From b185ef78847a5ba823348c55f0e5481e904dee27 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Wed, 19 Dec 2018 14:19:21 -0800 Subject: [PATCH 0118/1765] [TF:XLA] Bump open source llvm revision to r349610 PiperOrigin-RevId: 226232734 --- tensorflow/workspace.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tensorflow/workspace.bzl b/tensorflow/workspace.bzl index 700aa065b1..157cb52806 100755 --- a/tensorflow/workspace.bzl +++ b/tensorflow/workspace.bzl @@ -498,11 +498,11 @@ def tf_workspace(path_prefix = "", tf_repo_name = ""): tf_http_archive( name = "llvm", build_file = clean_dep("//third_party/llvm:llvm.autogenerated.BUILD"), - sha256 = "65b48c80eba736ab834a9790b78a72cd0e3919b6dace44a96259d3e6936624ec", - strip_prefix = "llvm-cfa2cf74cd9ba0e759974ce11bfd7b9e051dd8ff", + sha256 = "65a1aeb29e5940f9f480a41e904659d944e738458afd139caa7bde14bd6aab8a", + strip_prefix = "llvm-331ffd31b3dd49b3f02a27556938b836b679f564", urls = [ - "https://mirror.bazel.build/github.com/llvm-mirror/llvm/archive/cfa2cf74cd9ba0e759974ce11bfd7b9e051dd8ff.tar.gz", - "https://github.com/llvm-mirror/llvm/archive/cfa2cf74cd9ba0e759974ce11bfd7b9e051dd8ff.tar.gz", + "https://mirror.bazel.build/github.com/llvm-mirror/llvm/archive/331ffd31b3dd49b3f02a27556938b836b679f564.tar.gz", + "https://github.com/llvm-mirror/llvm/archive/331ffd31b3dd49b3f02a27556938b836b679f564.tar.gz", ], ) -- GitLab From 9b46c486fd50eb44a3403f16e68a661e9273ef59 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Wed, 19 Dec 2018 14:26:25 -0800 Subject: [PATCH 0119/1765] Remove second bazel installation PiperOrigin-RevId: 226233807 --- tensorflow/tools/ci_build/install/install_pi_toolchain.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tensorflow/tools/ci_build/install/install_pi_toolchain.sh b/tensorflow/tools/ci_build/install/install_pi_toolchain.sh index 03c43cc838..0238cc5895 100755 --- a/tensorflow/tools/ci_build/install/install_pi_toolchain.sh +++ b/tensorflow/tools/ci_build/install/install_pi_toolchain.sh @@ -25,5 +25,4 @@ apt-get install -y libpython-all-dev:armhf echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add - apt-get update -rm -rf /usr/local/bin/bazel -apt-get install -y bazel python python-numpy python-dev python-pip +apt-get install -y python python-numpy python-dev python-pip -- GitLab From 0d9b8ac2ece6904c009272e5be73561413bc9126 Mon Sep 17 00:00:00 2001 From: Alexandre Passos Date: Wed, 19 Dec 2018 14:34:06 -0800 Subject: [PATCH 0120/1765] Removes assertion which is not always true. It's perfectly fine to have float tensors which are loop variables which are not related to the gradient objective. PiperOrigin-RevId: 226235207 --- tensorflow/python/ops/while_v2.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tensorflow/python/ops/while_v2.py b/tensorflow/python/ops/while_v2.py index 3e5a8fcdfa..25fd2460ae 100644 --- a/tensorflow/python/ops/while_v2.py +++ b/tensorflow/python/ops/while_v2.py @@ -265,10 +265,6 @@ def _WhileGrad(op, *grads): # pylint: disable=invalid-name for grad, output in zip(grads, body_graph.outputs) ] - # Ensure that all non-resource trainable outputs have incoming gradients. - assert all(g is not None or o.dtype == dtypes.resource or not _is_trainable(o) - for o, g in zip(body_graph.outputs, grads) - ), "All trainable loop vars must receive incoming gradients." # We compute the gradient for the sub-graph between trainable ys and xs # with non-None incoming gradients. We later pad the None's to the list of # outputs. -- GitLab From c62d244e1f4aebf3b9ad7451d09cc974953a4cf8 Mon Sep 17 00:00:00 2001 From: Mihai Maruseac Date: Wed, 19 Dec 2018 14:41:34 -0800 Subject: [PATCH 0121/1765] Add fuzzer for ScatterNd. PiperOrigin-RevId: 226236341 --- tensorflow/core/kernels/fuzzing/BUILD | 4 + .../5b0e5f8d2990c3cac80fa792ba141c43 | Bin 0 -> 10 bytes .../5b61fa3a30dd267828f12d9ea2b2a191 | Bin 0 -> 13 bytes .../8bc8b7d8beb3483c48158739791e56b0 | Bin 0 -> 9 bytes .../d2ef31d47578e9de8323bb0e4806f1be | Bin 0 -> 10 bytes .../e2791edcf2c8d9f4af3678a75d43a3e4 | Bin 0 -> 10 bytes .../core/kernels/fuzzing/scatter_nd_fuzz.cc | 133 ++++++++++++++++++ 7 files changed, 137 insertions(+) create mode 100644 tensorflow/core/kernels/fuzzing/corpus/scatter_nd/5b0e5f8d2990c3cac80fa792ba141c43 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/scatter_nd/5b61fa3a30dd267828f12d9ea2b2a191 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/scatter_nd/8bc8b7d8beb3483c48158739791e56b0 create mode 100644 tensorflow/core/kernels/fuzzing/corpus/scatter_nd/d2ef31d47578e9de8323bb0e4806f1be create mode 100644 tensorflow/core/kernels/fuzzing/corpus/scatter_nd/e2791edcf2c8d9f4af3678a75d43a3e4 create mode 100644 tensorflow/core/kernels/fuzzing/scatter_nd_fuzz.cc diff --git a/tensorflow/core/kernels/fuzzing/BUILD b/tensorflow/core/kernels/fuzzing/BUILD index 7300f7a4e2..c9f025a5b0 100644 --- a/tensorflow/core/kernels/fuzzing/BUILD +++ b/tensorflow/core/kernels/fuzzing/BUILD @@ -72,3 +72,7 @@ tf_oss_fuzz_dict("decode_json_example") tf_ops_fuzz_target_lib("check_numerics") tf_ops_fuzz_target_lib("one_hot") + +tf_ops_fuzz_target_lib("scatter_nd") + +tf_oss_fuzz_corpus("scatter_nd") diff --git a/tensorflow/core/kernels/fuzzing/corpus/scatter_nd/5b0e5f8d2990c3cac80fa792ba141c43 b/tensorflow/core/kernels/fuzzing/corpus/scatter_nd/5b0e5f8d2990c3cac80fa792ba141c43 new file mode 100644 index 0000000000000000000000000000000000000000..d1239633c843b1b8fd64d232604a3d61e9eb07dc GIT binary patch literal 10 RcmZSJU}RxrVP<6K0ssKF04M+e literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/scatter_nd/5b61fa3a30dd267828f12d9ea2b2a191 b/tensorflow/core/kernels/fuzzing/corpus/scatter_nd/5b61fa3a30dd267828f12d9ea2b2a191 new file mode 100644 index 0000000000000000000000000000000000000000..1bd0905cdd6efab2b8450e6cb03f1d15ffae9993 GIT binary patch literal 13 UcmZSJU}9osWME-pWM<<600930D*ylh literal 0 HcmV?d00001 diff --git a/tensorflow/core/kernels/fuzzing/corpus/scatter_nd/8bc8b7d8beb3483c48158739791e56b0 b/tensorflow/core/kernels/fuzzing/corpus/scatter_nd/8bc8b7d8beb3483c48158739791e56b0 new file mode 100644 index 0000000000000000000000000000000000000000..65a6d0083ee72a2920014fbe252970bff43ca75d GIT binary patch literal 9 QcmZQzWn^Y#U}53{003zK8vp + +#include "tensorflow/cc/ops/array_ops.h" +#include "tensorflow/cc/ops/standard_ops.h" +#include "tensorflow/core/kernels/fuzzing/fuzz_session.h" + +namespace tensorflow { +namespace fuzzing { + +class FuzzScatterNd : public FuzzSession { + void BuildGraph(const Scope& scope) override { + auto indices = + tensorflow::ops::Placeholder(scope.WithOpName("indices"), DT_INT32); + auto updates = + tensorflow::ops::Placeholder(scope.WithOpName("updates"), DT_INT32); + auto shape = + tensorflow::ops::Placeholder(scope.WithOpName("shape"), DT_INT32); + (void)tensorflow::ops::ScatterNd(scope.WithOpName("output"), indices, + updates, shape); + } + + void FuzzImpl(const uint8_t* data, size_t size) override { + // This op's runtime is heavily determined by the shape of the tensor + // arguments and almost not at all by the values of those tensors. Hence, + // the fuzzing data here is only used to determine the shape of the + // arguments and the output and the data of these tensors is just a constant + // value. Furthermore, the shape of the updates_tensor tensor is fully + // determined by the contents of the shape_tensor and the shape of the + // indices_tensor. Rather than using random values for the + // updates_tensor.shape and getting most of the fuzz runs stopped in the + // check, it's better to just create a proper update_tensor. + + // First element of the data buffer gives the number of dimensions of the + // shape tensor. + size_t i; + size_t data_ix = 0; + size_t shape_dims = 1 + (data[data_ix++] % kMaxShapeDims); + Tensor shape_tensor(tensorflow::DT_INT32, + TensorShape({static_cast(shape_dims)})); + + // Check that we have enough elements left for the shape tensor + if (data_ix + shape_dims >= size) { + return; // not enough elements, no fuzz + } + + // Subsequent elements give the contents of the shape tensor. + // To not get out of memory, reduce all dimensions to at most kMaxDim + auto flat_shape = shape_tensor.flat(); + for (i = 0; i < shape_dims; i++) { + flat_shape(i) = data[data_ix++] % kMaxDim; + } + + // Next, we have to fill in the indices tensor. Take the next element from + // the buffer to represent the rank of this tensor. + if (data_ix >= size) { + return; + } + size_t indices_rank = 1 + (data[data_ix++] % kMaxIndicesRank); + + // Now, read the dimensions of the indices_tensor + if (data_ix + indices_rank >= size) { + return; + } + std::vector indices_dims; + size_t num_indices = 1; + for (i = 0; i < indices_rank; i++) { + // Modulo kMaxDim to not request too much memory + int64 dim = data[data_ix++] % kMaxDim; + num_indices *= dim; + indices_dims.push_back(dim); + } + Tensor indices_tensor(tensorflow::DT_INT32, TensorShape(indices_dims)); + + // Rest of the buffer is used to fill in the indices_tensor + auto flat_indices = indices_tensor.flat(); + for (i = 0; i < num_indices && data_ix < size; i++) { + flat_indices(i) = data[data_ix++]; + } + for (; i < num_indices; i++) { + flat_indices(i) = 0; // ensure that indices_tensor has all values + } + + // Given the values in the shape_tensor and the dimensions of the + // indices_tensor, the shape of updates_tensor is fixed. + num_indices = 1; + std::vector updates_dims; + for (i = 0; i < indices_rank - 1; i++) { + updates_dims.push_back(indices_dims[i]); + num_indices *= indices_dims[i]; + } + int64 last = indices_dims[indices_rank - 1]; + for (i = last; i < shape_dims; i++) { + updates_dims.push_back(flat_shape(i)); + num_indices *= flat_shape(i); + } + Tensor updates_tensor(tensorflow::DT_INT32, TensorShape(updates_dims)); + + // We don't care about the values in the updates_tensor, make them all be 1 + auto flat_updates = updates_tensor.flat(); + for (i = 0; i < num_indices; i++) { + flat_updates(i) = 1; + } + + RunInputs({{"indices", indices_tensor}, + {"updates", updates_tensor}, + {"shape", shape_tensor}}); + } + + private: + const size_t kMaxShapeDims = 5; + const size_t kMaxIndicesRank = 3; + const size_t kMaxDim = 10; +}; + +STANDARD_TF_FUZZ_FUNCTION(FuzzScatterNd); + +} // end namespace fuzzing +} // end namespace tensorflow -- GitLab From b6185defa48abd2af99d3a171c59640f06b65f5a Mon Sep 17 00:00:00 2001 From: Jiri Simsa Date: Wed, 19 Dec 2018 14:43:34 -0800 Subject: [PATCH 0122/1765] [tf.data] Refining the modeling framework to take buffer size into account. PiperOrigin-RevId: 226236644 --- tensorflow/core/framework/model.cc | 34 +- tensorflow/core/framework/model_test.cc | 291 +++++++++--------- .../benchmarks/autotune_benchmark.py | 61 +++- 3 files changed, 225 insertions(+), 161 deletions(-) diff --git a/tensorflow/core/framework/model.cc b/tensorflow/core/framework/model.cc index b7c6d80910..96cc7e583a 100644 --- a/tensorflow/core/framework/model.cc +++ b/tensorflow/core/framework/model.cc @@ -29,6 +29,32 @@ std::shared_ptr MakeParameter(const string& name, namespace { +// Given the average time between output events (`output_time`), the average +// time between input events (`input_time`) and the buffer size, the method +// computes the expected time an input event will have to wait. +// +// The wait time is approximated as the product of the probability the buffer +// will be empty and the time it takes to produce an element into the buffer. +// +// The formula used for computing the probability is derived by modeling the +// problem as an M/M/1/K queue +// (https://en.wikipedia.org/wiki/Birth%E2%80%93death_process#M/M/1/K_queue). +int64 ComputeWaitTime(int64 output_time, int64 input_time, int64 buffer_size) { + if (output_time == 0 || input_time == 0) { + return output_time; + } + if (input_time == output_time) { + const double p_buffer_empty = 1.0L / static_cast(buffer_size + 1); + return p_buffer_empty * output_time; + } + const double alpha = 1.0L / static_cast(input_time); + const double beta = 1.0L / static_cast(output_time); + const double p_buffer_empty = + (1.0L - beta / alpha) / + (1.0L - std::pow((beta / alpha), static_cast(buffer_size + 1))); + return p_buffer_empty * output_time; +} + // The first input of InterleaveMany corresponds to the input dataset whose // elements are used to create the (derived) input datasets whose elements are // interleaved as output. @@ -119,8 +145,8 @@ class AsyncInterleaveMany : public Node { static_cast(OutputTimeForInputs(input_times) - inputs_.front()->OutputTime(input_times)) / static_cast(inputs_.size() - 1) / parallelism; - return std::max(0LL, - NanosPerElementLocked() + output_time - old_input_time); + return ComputeWaitTime(NanosPerElementLocked() + output_time, + old_input_time, parallelism); } int64 ProcessingTimeLocked() const override SHARED_LOCKS_REQUIRED(mu_) { @@ -202,7 +228,7 @@ class AsyncKnownRatio : public Node { if (ratio_ == 0.0) { int64 output_time = static_cast(NanosPerElementLocked()) / parallelism; - return std::max(0LL, output_time - input_times->back()); + return ComputeWaitTime(output_time, input_times->back(), parallelism); } int64 old_input_time = input_times->back(); int64 new_input_time = static_cast( @@ -213,7 +239,7 @@ class AsyncKnownRatio : public Node { int64 output_time = static_cast( static_cast(NanosPerElementLocked()) / parallelism + ratio_ * OutputTimeForInputs(input_times)); - return std::max(0LL, output_time - old_input_time); + return ComputeWaitTime(output_time, old_input_time, parallelism); } int64 ProcessingTimeLocked() const override SHARED_LOCKS_REQUIRED(mu_) { diff --git a/tensorflow/core/framework/model_test.cc b/tensorflow/core/framework/model_test.cc index 90bd570f90..013f1e61c8 100644 --- a/tensorflow/core/framework/model_test.cc +++ b/tensorflow/core/framework/model_test.cc @@ -57,28 +57,30 @@ TEST_P(AsyncInterleaveManyTest, Model) { }); std::vector input_times(1, input_time); async_interleave_many->add_processing_time(100); - EXPECT_EQ(100, async_interleave_many->processing_time()); - EXPECT_EQ(0, async_interleave_many->ProcessingTime()); - EXPECT_EQ(0, async_interleave_many->OutputTime(&input_times)); + EXPECT_EQ(async_interleave_many->processing_time(), 100); + EXPECT_EQ(async_interleave_many->ProcessingTime(), 0); + EXPECT_EQ(async_interleave_many->OutputTime(&input_times), 0); async_interleave_many->record_element(); - EXPECT_EQ(1, async_interleave_many->num_elements()); - EXPECT_EQ(100, async_interleave_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, 100 - input_time), - async_interleave_many->OutputTime(&input_times)); + EXPECT_EQ(async_interleave_many->num_elements(), 1); + EXPECT_EQ(async_interleave_many->ProcessingTime(), 100); + EXPECT_LE(async_interleave_many->OutputTime(&input_times), 100); + EXPECT_GE(async_interleave_many->OutputTime(&input_times), 0); source1->add_processing_time(200); source2->add_processing_time(300); - EXPECT_EQ(100, async_interleave_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, 100 - input_time), - async_interleave_many->OutputTime(&input_times)); + EXPECT_EQ(async_interleave_many->ProcessingTime(), 100); + EXPECT_LE(async_interleave_many->OutputTime(&input_times), 100); + EXPECT_GE(async_interleave_many->OutputTime(&input_times), 0); source1->record_element(); source2->record_element(); - EXPECT_EQ(100 + 250, async_interleave_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, 100 + 250 / parallelism - input_time), - async_interleave_many->OutputTime(&input_times)); + EXPECT_EQ(async_interleave_many->ProcessingTime(), 100 + 250); + EXPECT_LE(async_interleave_many->OutputTime(&input_times), + 100 + 250 / parallelism); + EXPECT_GE(async_interleave_many->OutputTime(&input_times), 0); async_interleave_many->record_element(); - EXPECT_EQ(50 + 250, async_interleave_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, 50 + 250 / parallelism - input_time), - async_interleave_many->OutputTime(&input_times)); + EXPECT_EQ(async_interleave_many->ProcessingTime(), 50 + 250); + EXPECT_LE(async_interleave_many->OutputTime(&input_times), + 50 + 250 / parallelism); + EXPECT_GE(async_interleave_many->OutputTime(&input_times), 0); } INSTANTIATE_TEST_CASE_P(Test, AsyncInterleaveManyTest, @@ -106,47 +108,52 @@ TEST_P(AsyncKnownRatioTest, Model) { async_known_many->add_input(source2); std::vector input_times(1, input_time); source1->add_processing_time(100); - EXPECT_EQ(0, async_known_many->ProcessingTime()); - EXPECT_EQ(0, async_known_many->OutputTime(&input_times)); + EXPECT_EQ(async_known_many->ProcessingTime(), 0); + EXPECT_EQ(async_known_many->OutputTime(&input_times), 0); source2->add_processing_time(200); - EXPECT_EQ(0, async_known_many->ProcessingTime()); - EXPECT_EQ(0, async_known_many->OutputTime(&input_times)); + EXPECT_EQ(async_known_many->ProcessingTime(), 0); + EXPECT_EQ(async_known_many->OutputTime(&input_times), 0); source1->record_element(); - EXPECT_EQ(num_inputs_per_output * 100, async_known_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, num_inputs_per_output * 100 - input_time), - async_known_many->OutputTime(&input_times)); + EXPECT_EQ(async_known_many->ProcessingTime(), num_inputs_per_output * 100); + EXPECT_LE(async_known_many->OutputTime(&input_times), + num_inputs_per_output * 100); + EXPECT_GE(async_known_many->OutputTime(&input_times), 0); source2->record_element(); - EXPECT_EQ(num_inputs_per_output * (100 + 200), - async_known_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, num_inputs_per_output * (100 + 200) - input_time), - async_known_many->OutputTime(&input_times)); + EXPECT_EQ(async_known_many->ProcessingTime(), + num_inputs_per_output * (100 + 200)); + EXPECT_LE(async_known_many->OutputTime(&input_times), + num_inputs_per_output * (100 + 200)); + EXPECT_GE(async_known_many->OutputTime(&input_times), 0); source1->record_element(); - EXPECT_EQ(num_inputs_per_output * (50 + 200), - async_known_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, num_inputs_per_output * (50 + 200) - input_time), - async_known_many->OutputTime(&input_times)); + EXPECT_EQ(async_known_many->ProcessingTime(), + num_inputs_per_output * (50 + 200)); + EXPECT_LE(async_known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 200)); + EXPECT_GE(async_known_many->OutputTime(&input_times), 0); source2->record_element(); - EXPECT_EQ(num_inputs_per_output * (50 + 100), - async_known_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, num_inputs_per_output * (50 + 100) - input_time), - async_known_many->OutputTime(&input_times)); + EXPECT_EQ(async_known_many->ProcessingTime(), + num_inputs_per_output * (50 + 100)); + EXPECT_LE(async_known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 100)); + EXPECT_GE(async_known_many->OutputTime(&input_times), 0); async_known_many->add_processing_time(128); - EXPECT_EQ(num_inputs_per_output * (50 + 100), - async_known_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, num_inputs_per_output * (50 + 100) - input_time), - async_known_many->OutputTime(&input_times)); + EXPECT_EQ(async_known_many->ProcessingTime(), + num_inputs_per_output * (50 + 100)); + EXPECT_LE(async_known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 100)); + EXPECT_GE(async_known_many->OutputTime(&input_times), 0); async_known_many->record_element(); - EXPECT_EQ(num_inputs_per_output * (50 + 100) + 128, - async_known_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, num_inputs_per_output * (50 + 100) + - 128 / parallelism - input_time), - async_known_many->OutputTime(&input_times)); + EXPECT_EQ(async_known_many->ProcessingTime(), + num_inputs_per_output * (50 + 100) + 128); + EXPECT_LE(async_known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 100) + 128 / parallelism); + EXPECT_GE(async_known_many->OutputTime(&input_times), 0); async_known_many->record_element(); - EXPECT_EQ(num_inputs_per_output * (50 + 100) + 64, - async_known_many->ProcessingTime()); - EXPECT_EQ(std::max(0LL, num_inputs_per_output * (50 + 100) + - 64 / parallelism - input_time), - async_known_many->OutputTime(&input_times)); + EXPECT_EQ(async_known_many->ProcessingTime(), + num_inputs_per_output * (50 + 100) + 64); + EXPECT_LE(async_known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 100) + 64 / parallelism); + EXPECT_GE(async_known_many->OutputTime(&input_times), 0); } INSTANTIATE_TEST_CASE_P(Test, AsyncKnownRatioTest, @@ -168,24 +175,24 @@ TEST(InterleaveManyTest, Model) { interleave_many->add_input(source2); std::vector input_times(1, 0); interleave_many->add_processing_time(100); - EXPECT_EQ(100, interleave_many->processing_time()); - EXPECT_EQ(0, interleave_many->ProcessingTime()); - EXPECT_EQ(0, interleave_many->OutputTime(&input_times)); + EXPECT_EQ(interleave_many->processing_time(), 100); + EXPECT_EQ(interleave_many->ProcessingTime(), 0); + EXPECT_EQ(interleave_many->OutputTime(&input_times), 0); interleave_many->record_element(); - EXPECT_EQ(1, interleave_many->num_elements()); - EXPECT_EQ(100, interleave_many->ProcessingTime()); - EXPECT_EQ(100, interleave_many->OutputTime(&input_times)); + EXPECT_EQ(interleave_many->num_elements(), 1); + EXPECT_EQ(interleave_many->ProcessingTime(), 100); + EXPECT_EQ(interleave_many->OutputTime(&input_times), 100); source1->add_processing_time(200); source2->add_processing_time(300); - EXPECT_EQ(100, interleave_many->ProcessingTime()); - EXPECT_EQ(100, interleave_many->OutputTime(&input_times)); + EXPECT_EQ(interleave_many->ProcessingTime(), 100); + EXPECT_EQ(interleave_many->OutputTime(&input_times), 100); source1->record_element(); source2->record_element(); - EXPECT_EQ(350, interleave_many->ProcessingTime()); - EXPECT_EQ(350, interleave_many->OutputTime(&input_times)); + EXPECT_EQ(interleave_many->ProcessingTime(), 350); + EXPECT_EQ(interleave_many->OutputTime(&input_times), 350); interleave_many->record_element(); - EXPECT_EQ(300, interleave_many->ProcessingTime()); - EXPECT_EQ(300, interleave_many->OutputTime(&input_times)); + EXPECT_EQ(interleave_many->ProcessingTime(), 300); + EXPECT_EQ(interleave_many->OutputTime(&input_times), 300); } class KnownRatioTest : public ::testing::TestWithParam {}; @@ -202,40 +209,40 @@ TEST_P(KnownRatioTest, Model) { known_many->add_input(source2); std::vector input_times(1, 0); source1->add_processing_time(100); - EXPECT_EQ(0, known_many->ProcessingTime()); - EXPECT_EQ(0, known_many->OutputTime(&input_times)); + EXPECT_EQ(known_many->ProcessingTime(), 0); + EXPECT_EQ(known_many->OutputTime(&input_times), 0); source2->add_processing_time(200); - EXPECT_EQ(0, known_many->ProcessingTime()); - EXPECT_EQ(0, known_many->OutputTime(&input_times)); + EXPECT_EQ(known_many->ProcessingTime(), 0); + EXPECT_EQ(known_many->OutputTime(&input_times), 0); source1->record_element(); - EXPECT_EQ(num_inputs_per_output * 100, known_many->ProcessingTime()); - EXPECT_EQ(num_inputs_per_output * 100, known_many->OutputTime(&input_times)); + EXPECT_EQ(known_many->ProcessingTime(), num_inputs_per_output * 100); + EXPECT_EQ(known_many->OutputTime(&input_times), num_inputs_per_output * 100); source2->record_element(); - EXPECT_EQ(num_inputs_per_output * (100 + 200), known_many->ProcessingTime()); - EXPECT_EQ(num_inputs_per_output * (100 + 200), - known_many->OutputTime(&input_times)); + EXPECT_EQ(known_many->ProcessingTime(), num_inputs_per_output * (100 + 200)); + EXPECT_EQ(known_many->OutputTime(&input_times), + num_inputs_per_output * (100 + 200)); source1->record_element(); - EXPECT_EQ(num_inputs_per_output * (50 + 200), known_many->ProcessingTime()); - EXPECT_EQ(num_inputs_per_output * (50 + 200), - known_many->OutputTime(&input_times)); + EXPECT_EQ(known_many->ProcessingTime(), num_inputs_per_output * (50 + 200)); + EXPECT_EQ(known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 200)); source2->record_element(); - EXPECT_EQ(num_inputs_per_output * (50 + 100), known_many->ProcessingTime()); - EXPECT_EQ(num_inputs_per_output * (50 + 100), - known_many->OutputTime(&input_times)); + EXPECT_EQ(known_many->ProcessingTime(), num_inputs_per_output * (50 + 100)); + EXPECT_EQ(known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 100)); known_many->add_processing_time(128); - EXPECT_EQ(num_inputs_per_output * (50 + 100), known_many->ProcessingTime()); - EXPECT_EQ(num_inputs_per_output * (50 + 100), - known_many->OutputTime(&input_times)); + EXPECT_EQ(known_many->ProcessingTime(), num_inputs_per_output * (50 + 100)); + EXPECT_EQ(known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 100)); known_many->record_element(); - EXPECT_EQ(num_inputs_per_output * (50 + 100) + 128, - known_many->ProcessingTime()); - EXPECT_EQ(num_inputs_per_output * (50 + 100) + 128, - known_many->OutputTime(&input_times)); + EXPECT_EQ(known_many->ProcessingTime(), + num_inputs_per_output * (50 + 100) + 128); + EXPECT_EQ(known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 100) + 128); known_many->record_element(); - EXPECT_EQ(num_inputs_per_output * (50 + 100) + 64, - known_many->ProcessingTime()); - EXPECT_EQ(num_inputs_per_output * (50 + 100) + 64, - known_many->OutputTime(&input_times)); + EXPECT_EQ(known_many->ProcessingTime(), + num_inputs_per_output * (50 + 100) + 64); + EXPECT_EQ(known_many->OutputTime(&input_times), + num_inputs_per_output * (50 + 100) + 64); } INSTANTIATE_TEST_CASE_P(Test, KnownRatioTest, ::testing::Values(0, 1, 2, 4)); @@ -244,17 +251,17 @@ TEST(SourceTest, Model) { std::shared_ptr source = model::MakeSourceNode({0, "source", nullptr}); std::vector input_times(1, 0); source->add_processing_time(100); - EXPECT_EQ(100, source->processing_time()); - EXPECT_EQ(0, source->ProcessingTime()); - EXPECT_EQ(0, source->OutputTime(&input_times)); + EXPECT_EQ(source->processing_time(), 100); + EXPECT_EQ(source->ProcessingTime(), 0); + EXPECT_EQ(source->OutputTime(&input_times), 0); source->record_element(); - EXPECT_EQ(1, source->num_elements()); - EXPECT_EQ(100, source->ProcessingTime()); - EXPECT_EQ(100, source->OutputTime(&input_times)); + EXPECT_EQ(source->num_elements(), 1); + EXPECT_EQ(source->ProcessingTime(), 100); + EXPECT_EQ(source->OutputTime(&input_times), 100); source->record_element(); - EXPECT_EQ(2, source->num_elements()); - EXPECT_EQ(50, source->ProcessingTime()); - EXPECT_EQ(50, source->OutputTime(&input_times)); + EXPECT_EQ(source->num_elements(), 2); + EXPECT_EQ(source->ProcessingTime(), 50); + EXPECT_EQ(source->OutputTime(&input_times), 50); } TEST(UnknownRatioTest, Model) { @@ -268,24 +275,24 @@ TEST(UnknownRatioTest, Model) { unknown_many->add_input(source2); std::vector input_times(1, 0); unknown_many->add_processing_time(100); - EXPECT_EQ(100, unknown_many->processing_time()); - EXPECT_EQ(0, unknown_many->ProcessingTime()); - EXPECT_EQ(0, unknown_many->OutputTime(&input_times)); + EXPECT_EQ(unknown_many->processing_time(), 100); + EXPECT_EQ(unknown_many->ProcessingTime(), 0); + EXPECT_EQ(unknown_many->OutputTime(&input_times), 0); unknown_many->record_element(); - EXPECT_EQ(1, unknown_many->num_elements()); - EXPECT_EQ(100, unknown_many->ProcessingTime()); - EXPECT_EQ(100, unknown_many->OutputTime(&input_times)); + EXPECT_EQ(unknown_many->num_elements(), 1); + EXPECT_EQ(unknown_many->ProcessingTime(), 100); + EXPECT_EQ(unknown_many->OutputTime(&input_times), 100); source1->add_processing_time(100); source2->add_processing_time(200); - EXPECT_EQ(100, unknown_many->ProcessingTime()); - EXPECT_EQ(100, unknown_many->OutputTime(&input_times)); + EXPECT_EQ(unknown_many->ProcessingTime(), 100); + EXPECT_EQ(unknown_many->OutputTime(&input_times), 100); source1->record_element(); source2->record_element(); - EXPECT_EQ(400, unknown_many->ProcessingTime()); - EXPECT_EQ(400, unknown_many->OutputTime(&input_times)); + EXPECT_EQ(unknown_many->ProcessingTime(), 400); + EXPECT_EQ(unknown_many->OutputTime(&input_times), 400); unknown_many->record_element(); - EXPECT_EQ(200, unknown_many->ProcessingTime()); - EXPECT_EQ(200, unknown_many->OutputTime(&input_times)); + EXPECT_EQ(unknown_many->ProcessingTime(), 200); + EXPECT_EQ(unknown_many->OutputTime(&input_times), 200); } TEST(UnknownTest, Model) { @@ -299,35 +306,35 @@ TEST(UnknownTest, Model) { unknown->add_input(source2); std::vector input_times(1, 0); source1->add_processing_time(100); - EXPECT_EQ(0, unknown->ProcessingTime()); - EXPECT_EQ(0, unknown->OutputTime(&input_times)); + EXPECT_EQ(unknown->ProcessingTime(), 0); + EXPECT_EQ(unknown->OutputTime(&input_times), 0); source2->add_processing_time(100); - EXPECT_EQ(0, unknown->ProcessingTime()); - EXPECT_EQ(0, unknown->OutputTime(&input_times)); + EXPECT_EQ(unknown->ProcessingTime(), 0); + EXPECT_EQ(unknown->OutputTime(&input_times), 0); source1->record_element(); - EXPECT_EQ(100, unknown->ProcessingTime()); - EXPECT_EQ(100, unknown->OutputTime(&input_times)); + EXPECT_EQ(unknown->ProcessingTime(), 100); + EXPECT_EQ(unknown->OutputTime(&input_times), 100); source2->record_element(); - EXPECT_EQ(200, unknown->ProcessingTime()); - EXPECT_EQ(200, unknown->OutputTime(&input_times)); + EXPECT_EQ(unknown->ProcessingTime(), 200); + EXPECT_EQ(unknown->OutputTime(&input_times), 200); source1->record_element(); - EXPECT_EQ(150, unknown->ProcessingTime()); - EXPECT_EQ(150, unknown->OutputTime(&input_times)); + EXPECT_EQ(unknown->ProcessingTime(), 150); + EXPECT_EQ(unknown->OutputTime(&input_times), 150); source2->record_element(); - EXPECT_EQ(100, unknown->ProcessingTime()); - EXPECT_EQ(100, unknown->OutputTime(&input_times)); + EXPECT_EQ(unknown->ProcessingTime(), 100); + EXPECT_EQ(unknown->OutputTime(&input_times), 100); // Unknown node processing time should not affect its ProcessingTime() or // OutputTime(). unknown->add_processing_time(100); - EXPECT_EQ(100, unknown->processing_time()); - EXPECT_EQ(100, unknown->ProcessingTime()); - EXPECT_EQ(100, unknown->OutputTime(&input_times)); + EXPECT_EQ(unknown->processing_time(), 100); + EXPECT_EQ(unknown->ProcessingTime(), 100); + EXPECT_EQ(unknown->OutputTime(&input_times), 100); // Unknown node number of elements should not affect its ProcessingTime() or // OutputTime(). unknown->record_element(); - EXPECT_EQ(1, unknown->num_elements()); - EXPECT_EQ(100, unknown->ProcessingTime()); - EXPECT_EQ(100, unknown->OutputTime(&input_times)); + EXPECT_EQ(unknown->num_elements(), 1); + EXPECT_EQ(unknown->ProcessingTime(), 100); + EXPECT_EQ(unknown->OutputTime(&input_times), 100); } class TestNode : public model::Node { @@ -355,35 +362,35 @@ class TestNode : public model::Node { TEST(SetterGetterTest, Node) { std::shared_ptr node = std::make_shared(model::Node::Args{-1, "TestNode", nullptr}); - EXPECT_EQ(-1, node->id()); - EXPECT_EQ("TestNode", node->name()); - EXPECT_EQ(nullptr, node->output()); + EXPECT_EQ(node->id(), -1); + EXPECT_EQ(node->name(), "TestNode"); + EXPECT_EQ(node->output(), nullptr); - EXPECT_EQ(0, node->buffered_bytes()); + EXPECT_EQ(node->buffered_bytes(), 0); node->add_buffered_bytes(42); - EXPECT_EQ(42, node->buffered_bytes()); + EXPECT_EQ(node->buffered_bytes(), 42); - EXPECT_EQ(0, node->processing_time()); + EXPECT_EQ(node->processing_time(), 0); node->record_start(1); - EXPECT_EQ(0, node->processing_time()); + EXPECT_EQ(node->processing_time(), 0); node->record_stop(41); - EXPECT_EQ(40, node->processing_time()); + EXPECT_EQ(node->processing_time(), 40); node->add_processing_time(2); - EXPECT_EQ(42, node->processing_time()); + EXPECT_EQ(node->processing_time(), 42); std::shared_ptr input = std::make_shared(model::Node::Args{-1, "TestInput", node}); - EXPECT_EQ(node.get(), input->output()); - EXPECT_EQ(0, node->inputs().size()); + EXPECT_EQ(input->output(), node.get()); + EXPECT_EQ(node->inputs().size(), 0); node->add_input(input); - EXPECT_EQ(1, node->inputs().size()); - EXPECT_EQ(input, node->inputs().front()); + EXPECT_EQ(node->inputs().size(), 1); + EXPECT_EQ(node->inputs().front(), input); node->remove_input(input); - EXPECT_EQ(0, node->inputs().size()); + EXPECT_EQ(node->inputs().size(), 0); - EXPECT_EQ(0, node->num_elements()); + EXPECT_EQ(node->num_elements(), 0); node->record_element(); - EXPECT_EQ(1, node->num_elements()); + EXPECT_EQ(node->num_elements(), 1); } } // namespace diff --git a/tensorflow/python/data/experimental/benchmarks/autotune_benchmark.py b/tensorflow/python/data/experimental/benchmarks/autotune_benchmark.py index e713494b52..391b6711e9 100644 --- a/tensorflow/python/data/experimental/benchmarks/autotune_benchmark.py +++ b/tensorflow/python/data/experimental/benchmarks/autotune_benchmark.py @@ -33,12 +33,20 @@ class AutotuneBenchmark(test.Benchmark): """Benchmarks for autotuning performance knobs.""" def benchmarkMap(self): + a = self._benchmarkMap(autotune=False) + b = self._benchmarkMap(autotune=True) + print("speedup: %f" % (a / b)) + + def _benchmarkMap(self, autotune): k = 1024 * 1024 dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), np.random.rand(4 * k, 1))).repeat() dataset = dataset.map( math_ops.matmul, num_parallel_calls=optimization.AUTOTUNE) + options = dataset_ops.Options() + options.experimental_autotune = autotune + dataset = dataset.with_options(options) iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() @@ -46,7 +54,7 @@ class AutotuneBenchmark(test.Benchmark): with session.Session() as sess: for _ in range(5): sess.run(get_next.op) - for _ in range(1000): + for _ in range(10000): start = time.time() sess.run(get_next.op) end = time.time() @@ -56,13 +64,17 @@ class AutotuneBenchmark(test.Benchmark): (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), np.max(deltas))) self.report_benchmark( - iters=1000, wall_time=np.median(deltas), name="map_autotune") + iters=10000, + wall_time=np.median(deltas), + name="map" + ("_autotune" if autotune else "")) + return np.median(deltas) def benchmarkMapAndBatch(self): - self._benchmarkMapAndBatch(numa_aware=False) - self._benchmarkMapAndBatch(numa_aware=True) + a = self._benchmarkMapAndBatch(autotune=False) + b = self._benchmarkMapAndBatch(autotune=True) + print("speedup: %f" % (a / b)) - def _benchmarkMapAndBatch(self, numa_aware): + def _benchmarkMapAndBatch(self, autotune): batch_size = 16 k = 1024 * 1024 dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), @@ -74,7 +86,7 @@ class AutotuneBenchmark(test.Benchmark): num_parallel_calls=optimization.AUTOTUNE, batch_size=batch_size)) options = dataset_ops.Options() - options.experimental_numa_aware = numa_aware + options.experimental_autotune = autotune dataset = dataset.with_options(options) iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() @@ -83,7 +95,7 @@ class AutotuneBenchmark(test.Benchmark): with session.Session() as sess: for _ in range(5): sess.run(get_next.op) - for _ in range(100): + for _ in range(1000): start = time.time() sess.run(get_next.op) end = time.time() @@ -94,11 +106,17 @@ class AutotuneBenchmark(test.Benchmark): np.max(deltas))) self.report_benchmark( - iters=100, + iters=1000, wall_time=np.median(deltas), - name=("numa_" if numa_aware else "") + "map_and_batch_autotune") + name="map_and_batch" + ("_autotune" if autotune else "")) + return np.median(deltas) def benchmarkInterleave(self): + a = self._benchmarkInterleave(autotune=False) + b = self._benchmarkInterleave(autotune=True) + print("speedup: %f" % (a / b)) + + def _benchmarkInterleave(self, autotune): k = 1024 * 1024 dataset = dataset_ops.Dataset.from_tensors((np.random.rand(1, 4 * k), np.random.rand(4 * k, @@ -108,6 +126,9 @@ class AutotuneBenchmark(test.Benchmark): lambda _: dataset, cycle_length=10, num_parallel_calls=optimization.AUTOTUNE) + options = dataset_ops.Options() + options.experimental_autotune = autotune + dataset = dataset.with_options(options) iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() @@ -115,7 +136,7 @@ class AutotuneBenchmark(test.Benchmark): with session.Session() as sess: for _ in range(5): sess.run(get_next.op) - for _ in range(1000): + for _ in range(10000): start = time.time() sess.run(get_next.op) end = time.time() @@ -125,11 +146,17 @@ class AutotuneBenchmark(test.Benchmark): (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), np.max(deltas))) self.report_benchmark( - iters=1000, + iters=10000, wall_time=np.median(deltas), - name="interleave_autotune") + name="interleave" + ("_autotune" if autotune else "")) + return np.median(deltas) def benchmarkMapAndInterleave(self): + a = self._benchmarkMapAndInterleave(autotune=False) + b = self._benchmarkMapAndInterleave(autotune=True) + print("speedup: %f" % (a / b)) + + def _benchmarkMapAndInterleave(self, autotune): k = 1024 * 1024 a = (np.random.rand(1, 8 * k), np.random.rand(8 * k, 1)) b = (np.random.rand(1, 4 * k), np.random.rand(4 * k, 1)) @@ -161,6 +188,9 @@ class AutotuneBenchmark(test.Benchmark): dataset = dataset_ops.Dataset.zip((dataset, dataset_c)) dataset = dataset.map(f2, num_parallel_calls=optimization.AUTOTUNE) + options = dataset_ops.Options() + options.experimental_autotune = autotune + dataset = dataset.with_options(options) iterator = dataset_ops.make_one_shot_iterator(dataset) get_next = iterator.get_next() @@ -168,7 +198,7 @@ class AutotuneBenchmark(test.Benchmark): with session.Session() as sess: for _ in range(5): sess.run(get_next) - for _ in range(100): + for _ in range(1000): start = time.time() sess.run(get_next) end = time.time() @@ -178,9 +208,10 @@ class AutotuneBenchmark(test.Benchmark): (np.median(deltas), np.mean(deltas), np.std(deltas), np.min(deltas), np.max(deltas))) self.report_benchmark( - iters=100, + iters=1000, wall_time=np.median(deltas), - name="map_and_interleave_autotune") + name="map_and_interleave" + ("_autotune" if autotune else "")) + return np.median(deltas) if __name__ == "__main__": -- GitLab From 2a09c39fff6908070302a77359d8a5f70826dbd8 Mon Sep 17 00:00:00 2001 From: Russell Power Date: Wed, 19 Dec 2018 15:10:02 -0800 Subject: [PATCH 0123/1765] Remove device capture from replay logs. PiperOrigin-RevId: 226240619 --- tensorflow/python/client/session_ref.cc | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tensorflow/python/client/session_ref.cc b/tensorflow/python/client/session_ref.cc index 4d361612b7..6639cf506e 100644 --- a/tensorflow/python/client/session_ref.cc +++ b/tensorflow/python/client/session_ref.cc @@ -109,21 +109,8 @@ class SessionLogger { } Status RecordNewSession(Session* session) { - LOG(INFO) << "New session discovered. Capturing devices..."; ReplayOp op; NewReplaySession* req = op.mutable_new_replay_session(); - - std::vector devices; - Status status = session->ListDevices(&devices); - if (status.ok()) { - LOG(INFO) << "Found: " << devices.size() << " devices."; - for (const DeviceAttributes& dev : devices) { - *req->mutable_devices()->add_local_device() = dev; - } - } else { - LOG(WARNING) << "Failed to list devices on session. Continuing."; - } - req->set_session_handle(SessionToHandle(session)); return Flush(op); } -- GitLab From f4867d3e4fecdb1ca8a445addad383aa0292a3b3 Mon Sep 17 00:00:00 2001 From: Sami Kama Date: Wed, 19 Dec 2018 19:40:22 -0800 Subject: [PATCH 0124/1765] Initialize only CPU devices in optimize_dataset_op --- tensorflow/core/grappler/grappler_item_builder.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tensorflow/core/grappler/grappler_item_builder.cc b/tensorflow/core/grappler/grappler_item_builder.cc index 9224ee7849..a984efd10d 100644 --- a/tensorflow/core/grappler/grappler_item_builder.cc +++ b/tensorflow/core/grappler/grappler_item_builder.cc @@ -103,7 +103,11 @@ Status OptimizeGraph(const GraphDef& graph_def_arg, GraphDef* output_graph_def, // Instantiate all variables for function library runtime creation. std::vector> devices; - TF_RETURN_IF_ERROR(DeviceFactory::AddDevices( + // Only CPU device is used so instead of calling DeviceFactory::AddDevices() + // with dummy session config, which will conflict with user defined options and + // create unwanted devices, call cpu_factory->CreateDevices() to get CPU only devices. + DeviceFactory* cpu_factory = DeviceFactory::GetFactory("CPU"); + TF_RETURN_IF_ERROR(cpu_factory->CreateDevices( options, "/job:localhost/replica:0/task:0", &devices)); Device* cpu_device = devices[0].get(); std::unique_ptr dvc_mgr(new DeviceMgr(std::move(devices))); -- GitLab From 4c7452c8c9b632d7ad7232099637e6fe388c3dd2 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Wed, 19 Dec 2018 15:11:25 -0800 Subject: [PATCH 0125/1765] Modify TFLite NNAPI interface to use a struct instead of using directly function calls. Add an empty implementation for NNAPI outside Android. PiperOrigin-RevId: 226240820 --- .../lite/delegates/nnapi/nnapi_delegate.cc | 142 +- tensorflow/lite/nnapi/BUILD | 12 + tensorflow/lite/nnapi/NeuralNetworksShim.cc | 129 ++ tensorflow/lite/nnapi/NeuralNetworksShim.h | 1204 ++++++++--------- tensorflow/lite/nnapi/nnapi_lib_test.cc | 90 ++ tensorflow/lite/nnapi_delegate.cc | 135 +- 6 files changed, 909 insertions(+), 803 deletions(-) create mode 100644 tensorflow/lite/nnapi/NeuralNetworksShim.cc create mode 100644 tensorflow/lite/nnapi/nnapi_lib_test.cc diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc index 7908bbf164..a10a2ee963 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc @@ -48,55 +48,35 @@ namespace { } while (0) namespace { -int32_t GetAndroidSdkVersion() { -#ifdef __ANDROID__ - const char* sdkProp = "ro.build.version.sdk"; - char sdkVersion[PROP_VALUE_MAX]; - int length = __system_property_get(sdkProp, sdkVersion); - if (length != 0) { - for (int i = 0; i < length; ++i) { - int digit = sdkVersion[i] - '0'; - if (digit < 0 || digit > 9) { - // Non-numeric SDK version, assume it's higher then expected; - return std::numeric_limits::max(); - } - } - return atoi(sdkVersion); - } -#endif // __ANDROID__ - return 0; -} - constexpr int32_t kMinSdkVersionForNNAPI = 27; constexpr int32_t kMinSdkVersionForNNAPI11 = 28; -static const int32_t kAndroidSdkVersion = GetAndroidSdkVersion(); - } // namespace // RAII NN API Model Destructor for use with std::unique_ptr struct NNFreeModel { void operator()(ANeuralNetworksModel* model) { - ANeuralNetworksModel_free(model); + NnApiImplementation()->ANeuralNetworksModel_free(model); } }; // RAII NN API Compilation Destructor for use with std::unique_ptr struct NNFreeCompilation { void operator()(ANeuralNetworksCompilation* model) { - ANeuralNetworksCompilation_free(model); + NnApiImplementation()->ANeuralNetworksCompilation_free(model); } }; // Manage NNAPI shared memory handle class NNMemory { public: - NNMemory(const char* name, size_t size) { + NNMemory(const NnApi* nnapi, const char* name, size_t size) { #ifdef __ANDROID__ + nnapi_ = nnapi; byte_size_ = size; fd_ = ASharedMemory_create(name, size); data_ptr_ = reinterpret_cast( mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0)); - ANeuralNetworksMemory_createFromFd(size, PROT_READ | PROT_WRITE, fd_, 0, - &nn_memory_handle_); + nnapi_->ANeuralNetworksMemory_createFromFd(size, PROT_READ | PROT_WRITE, + fd_, 0, &nn_memory_handle_); #endif } @@ -106,7 +86,7 @@ class NNMemory { munmap(data_ptr_, byte_size_); } if (nn_memory_handle_) { - ANeuralNetworksMemory_free(nn_memory_handle_); + nnapi_->ANeuralNetworksMemory_free(nn_memory_handle_); } if (fd_ > 0) close(fd_); #endif @@ -117,6 +97,7 @@ class NNMemory { private: #ifdef __ANDROID__ + const NnApi* nnapi_; int fd_ = 0; size_t byte_size_ = 0; #endif @@ -166,9 +147,10 @@ class OperandMapping { // operands for both tensors and parameters, and TFLite separates the two. class NNAPIOpBuilder { public: - NNAPIOpBuilder(TfLiteContext* context, OperandMapping* tensor_mapping, - ANeuralNetworksModel* nn_model) - : context_(context), + NNAPIOpBuilder(const NnApi* nnapi, TfLiteContext* context, + OperandMapping* tensor_mapping, ANeuralNetworksModel* nn_model) + : nnapi_(nnapi), + context_(context), operand_mapping_(tensor_mapping), nn_model_(nn_model) {} @@ -224,7 +206,7 @@ class NNAPIOpBuilder { .dimensionCount = dimension_count, .dimensions = dims.data()}; CHECK_NN(context_, - ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); int ann_operand = operand_mapping_->add_new_non_tensor_operand(); augmented_outputs_.push_back(ann_operand); return kTfLiteOk; @@ -241,7 +223,7 @@ class NNAPIOpBuilder { reinterpret_cast(tensor->dims->data), tensor->params.scale, tensor->params.zero_point}; CHECK_NN(context_, - ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); augmented_outputs_.push_back(ann_index); *ann_tensor_index_out = ann_index; @@ -298,11 +280,11 @@ class NNAPIOpBuilder { nn_type, static_cast(tensor->dims->size), reinterpret_cast(tensor->dims->data), scale, zeroPoint}; CHECK_NN(context_, - ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); if (tensor->allocation_type == kTfLiteMmapRo) { // TODO(b/80630405): Use NNAPIAllocation. - CHECK_NN(context_, ANeuralNetworksModel_setOperandValue( + CHECK_NN(context_, nnapi_->ANeuralNetworksModel_setOperandValue( nn_model_, ann_tensor_index, tensor->data.raw, tensor->bytes)); } @@ -314,7 +296,7 @@ class NNAPIOpBuilder { // Finish emitting the op (of type `type`) into the NN API. TfLiteStatus FinalizeAddOperation(ANeuralNetworksOperationType type) { // Actually add a NN API operation - CHECK_NN(context_, ANeuralNetworksModel_addOperation( + CHECK_NN(context_, nnapi_->ANeuralNetworksModel_addOperation( nn_model_, type, static_cast(augmented_inputs_.size()), augmented_inputs_.data(), @@ -330,9 +312,9 @@ class NNAPIOpBuilder { TfLiteStatus AddScalarOperand(T value, int32_t nn_type) { ANeuralNetworksOperandType operand_type{.type = nn_type}; CHECK_NN(context_, - ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); int ann_operand = operand_mapping_->add_new_non_tensor_operand(); - CHECK_NN(context_, ANeuralNetworksModel_setOperandValue( + CHECK_NN(context_, nnapi_->ANeuralNetworksModel_setOperandValue( nn_model_, ann_operand, &value, sizeof(T))); augmented_inputs_.push_back(ann_operand); return kTfLiteOk; @@ -344,15 +326,18 @@ class NNAPIOpBuilder { ANeuralNetworksOperandType operand_type{ .type = nn_type, .dimensionCount = 1, .dimensions = &num_values}; CHECK_NN(context_, - ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); int ann_operand = operand_mapping_->add_new_non_tensor_operand(); CHECK_NN(context_, - ANeuralNetworksModel_setOperandValue( + nnapi_->ANeuralNetworksModel_setOperandValue( nn_model_, ann_operand, values, sizeof(T) * num_values)); augmented_inputs_.push_back(ann_operand); return kTfLiteOk; } + // Access to NNAPI. + const NnApi* const nnapi_; + // TfLiteContext for error handling. TfLiteContext* const context_; @@ -388,7 +373,7 @@ ANeuralNetworksOperationType BasicMappingFn( // The kernel that represents the node sub set of TF Lite being run on NN API. class NNAPIDelegateKernel { public: - NNAPIDelegateKernel() = default; + NNAPIDelegateKernel() { nnapi_ = NnApiImplementation(); } typedef ANeuralNetworksOperationType (*MappingFn)( const NNAPIOpMappingArgs& mapping_args); @@ -397,7 +382,7 @@ class NNAPIDelegateKernel { // when called. You can use this function to see if a node is supported // (i.e. that MappingFn is not nullptr). static MappingFn Map(TfLiteContext* context, int builtin_code, int version, - TfLiteNode* node) { + int android_sdk_version, TfLiteNode* node) { switch (builtin_code) { case kTfLiteBuiltinAdd: if (version == 1) { @@ -516,7 +501,7 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinSqueeze: - if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) { + if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11) { return [](const NNAPIOpMappingArgs& mapping_args) -> ANeuralNetworksOperationType { auto builtin = reinterpret_cast( @@ -632,7 +617,7 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinSub: - if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11 && + if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11 && context->tensors[node->inputs->data[0]].type == kTfLiteFloat32) { // NNAPI only support float sub. return [](const NNAPIOpMappingArgs& mapping_args) @@ -645,7 +630,7 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinDiv: - if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11 && + if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11 && context->tensors[node->inputs->data[0]].type == kTfLiteFloat32) { // NNAPI only support float div. return [](const NNAPIOpMappingArgs& mapping_args) @@ -658,7 +643,7 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinPad: - if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11 && + if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11 && node->inputs->size == 2 && context->tensors[node->inputs->data[0]].type == kTfLiteFloat32) { // NNAPI does not support specifying the padding value. @@ -668,12 +653,12 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinSpaceToBatchNd: - if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) { + if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11) { return BasicMappingFn; } break; case kTfLiteBuiltinStridedSlice: - if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) { + if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11) { return [](const NNAPIOpMappingArgs& mapping_args) -> ANeuralNetworksOperationType { auto builtin = reinterpret_cast( @@ -691,7 +676,7 @@ class NNAPIDelegateKernel { // dimensions. // TODO(b/110888333): Support dynamically-sized tensors in delegates. if ((version == 1) && - (kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) && + (android_sdk_version >= kMinSdkVersionForNNAPI11) && (node->inputs->size > 1) && (context->tensors[node->inputs->data[1]].allocation_type == kTfLiteMmapRo)) { @@ -789,7 +774,7 @@ class NNAPIDelegateKernel { break; case kTfLiteBuiltinMean: // NNAPI does not support generating a scalar as output for MEAN. - if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11 && + if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11 && context->tensors[node->inputs->data[0]].type == kTfLiteFloat32 && context->tensors[node->outputs->data[0]].dims->size > 0) { return [](const NNAPIOpMappingArgs& mapping_args) @@ -833,7 +818,7 @@ class NNAPIDelegateKernel { if (!nn_model_) { ANeuralNetworksModel* model; - CHECK_NN(context, ANeuralNetworksModel_create(&model)); + CHECK_NN(context, nnapi_->ANeuralNetworksModel_create(&model)); nn_model_.reset(model); TF_LITE_ENSURE_STATUS( @@ -842,9 +827,9 @@ class NNAPIDelegateKernel { if (!nn_compilation_) { ANeuralNetworksCompilation* compilation; - CHECK_NN(context, ANeuralNetworksCompilation_create(nn_model_.get(), - &compilation)); - CHECK_NN(context, ANeuralNetworksCompilation_finish(compilation)); + CHECK_NN(context, nnapi_->ANeuralNetworksCompilation_create( + nn_model_.get(), &compilation)); + CHECK_NN(context, nnapi_->ANeuralNetworksCompilation_finish(compilation)); nn_compilation_.reset(compilation); } return kTfLiteOk; @@ -852,8 +837,8 @@ class NNAPIDelegateKernel { TfLiteStatus Invoke(TfLiteContext* context, TfLiteNode* node) { ANeuralNetworksExecution* execution = nullptr; - CHECK_NN(context, ANeuralNetworksExecution_create(nn_compilation_.get(), - &execution)); + CHECK_NN(context, nnapi_->ANeuralNetworksExecution_create( + nn_compilation_.get(), &execution)); // Set the input tensor buffers. Note: we access tflite tensors using // absolute indices but NN api indices inputs by relative indices. @@ -871,7 +856,7 @@ class NNAPIDelegateKernel { // copy data to pre-allocated shared memory. memcpy(nn_input_memory_->get_data_ptr() + input_offset, tensor->data.raw, tensor->bytes); - CHECK_NN(context, ANeuralNetworksExecution_setInputFromMemory( + CHECK_NN(context, nnapi_->ANeuralNetworksExecution_setInputFromMemory( execution, relative_input_index, nullptr, nn_input_memory_->get_handle(), input_offset, tensor->bytes)); @@ -885,7 +870,7 @@ class NNAPIDelegateKernel { size_t output_offset = 0; for (auto output_index : TfLiteIntArrayView(node->outputs)) { TfLiteTensor* tensor = &context->tensors[output_index]; - CHECK_NN(context, ANeuralNetworksExecution_setOutputFromMemory( + CHECK_NN(context, nnapi_->ANeuralNetworksExecution_setOutputFromMemory( execution, relative_output_index, nullptr, nn_output_memory_->get_handle(), output_offset, tensor->bytes)); @@ -901,17 +886,18 @@ class NNAPIDelegateKernel { // Here we are using a deep copy for state_in tensors so that we are not // reading and writing into the same buffer during a invocation. // TODO(110369471): using double shared buffer to minimize the copies. - CHECK_NN(context, ANeuralNetworksExecution_setOutput( + CHECK_NN(context, nnapi_->ANeuralNetworksExecution_setOutput( execution, relative_output_index, nullptr, tensor->data.raw, tensor->bytes)); relative_output_index++; } // Invoke ANN in blocking fashion. ANeuralNetworksEvent* event = nullptr; - CHECK_NN(context, ANeuralNetworksExecution_startCompute(execution, &event)); - CHECK_NN(context, ANeuralNetworksEvent_wait(event)); - ANeuralNetworksEvent_free(event); - ANeuralNetworksExecution_free(execution); + CHECK_NN(context, + nnapi_->ANeuralNetworksExecution_startCompute(execution, &event)); + CHECK_NN(context, nnapi_->ANeuralNetworksEvent_wait(event)); + nnapi_->ANeuralNetworksEvent_free(event); + nnapi_->ANeuralNetworksExecution_free(execution); // copy results from shared memory to the destination. output_offset = 0; @@ -926,6 +912,8 @@ class NNAPIDelegateKernel { } private: + // Access to NNApi. + const NnApi* nnapi_; // ANN API state. std::unique_ptr nn_model_; std::unique_ptr @@ -946,7 +934,7 @@ class NNAPIDelegateKernel { // The operand builder allows creating a single op. We create it at this // reduced power position rather than in the for loop to avoid reallocating // the vectors. - NNAPIOpBuilder builder(context, &operand_mapping_, nn_model_.get()); + NNAPIOpBuilder builder(nnapi_, context, &operand_mapping_, nn_model_.get()); // Add Tensors // allocate outside to avoid realloc for (auto node_index : nodes_) { @@ -969,9 +957,10 @@ class NNAPIDelegateKernel { } } // Get op type and operands - int nn_op_type = Map(context, reg->builtin_code, reg->version, node)( - {context, &builder, node, &model_state_outputs_, - &model_state_tfl_inputs_}); + int nn_op_type = Map( + context, reg->builtin_code, reg->version, nnapi_->android_sdk_version, + node)({context, &builder, node, &model_state_outputs_, + &model_state_tfl_inputs_}); // Map outputs to NN API tensor indices. for (auto output_index : TfLiteIntArrayView(node->outputs)) { TF_LITE_ENSURE_STATUS(builder.AddTensorOutput(output_index)); @@ -1016,24 +1005,25 @@ class NNAPIDelegateKernel { } // Tell ANN to declare inputs/outputs - CHECK_NN(context, ANeuralNetworksModel_identifyInputsAndOutputs( + CHECK_NN(context, nnapi_->ANeuralNetworksModel_identifyInputsAndOutputs( nn_model_.get(), inputs.size(), inputs.data(), outputs.size(), outputs.data())); // Set relaxed computation mode for fp32 if possible. - if (kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) { + if (nnapi_->android_sdk_version >= kMinSdkVersionForNNAPI11) { CHECK_NN(context, - ANeuralNetworksModel_relaxComputationFloat32toFloat16( + nnapi_->ANeuralNetworksModel_relaxComputationFloat32toFloat16( nn_model_.get(), context->allow_fp32_relax_to_fp16)); } // Finalize the model - CHECK_NN(context, ANeuralNetworksModel_finish(nn_model_.get())); + CHECK_NN(context, nnapi_->ANeuralNetworksModel_finish(nn_model_.get())); // Create shared memory pool for inputs and outputs. - nn_input_memory_.reset(new NNMemory("input_pool", total_input_byte_size)); + nn_input_memory_.reset( + new NNMemory(nnapi_, "input_pool", total_input_byte_size)); nn_output_memory_.reset( - new NNMemory("output_pool", total_output_byte_size)); + new NNMemory(nnapi_, "output_pool", total_output_byte_size)); return kTfLiteOk; } @@ -1049,7 +1039,9 @@ TfLiteDelegate* NnApiDelegate() { .Prepare = [](TfLiteContext* context, TfLiteDelegate* delegate) -> TfLiteStatus { // Do not check nodes_ if NN API is unavailable. - if (kAndroidSdkVersion < kMinSdkVersionForNNAPI || !NNAPIExists()) { + const NnApi* nnapi = NnApiImplementation(); + if (nnapi->android_sdk_version < kMinSdkVersionForNNAPI || + !nnapi->nnapi_exists) { return kTfLiteOk; } @@ -1062,6 +1054,7 @@ TfLiteDelegate* NnApiDelegate() { TfLiteIntArray* plan; TF_LITE_ENSURE_STATUS(context->GetExecutionPlan(context, &plan)); + int android_sdk_version = NnApiImplementation()->android_sdk_version; // Check for every node if it is supported // TODO(b/80625235): Fix this to do more careful checking of versioning. for (int node_index : TfLiteIntArrayView(plan)) { @@ -1070,7 +1063,8 @@ TfLiteDelegate* NnApiDelegate() { TF_LITE_ENSURE_STATUS(context->GetNodeAndRegistration( context, node_index, &node, ®istration)); if (NNAPIDelegateKernel::Map(context, registration->builtin_code, - registration->version, node)) { + registration->version, + android_sdk_version, node)) { supported_nodes.push_back(node_index); } } diff --git a/tensorflow/lite/nnapi/BUILD b/tensorflow/lite/nnapi/BUILD index 467a2b7a7b..390c3730cb 100644 --- a/tensorflow/lite/nnapi/BUILD +++ b/tensorflow/lite/nnapi/BUILD @@ -6,8 +6,20 @@ package(default_visibility = [ cc_library( name = "nnapi_lib", + srcs = [ + "NeuralNetworksShim.cc", + ], hdrs = [ "NeuralNetworksShim.h", ], linkopts = ["-ldl"], ) + +cc_test( + name = "nnapi_lib_test", + srcs = ["nnapi_lib_test.cc"], + deps = [ + "//tensorflow/lite/nnapi:nnapi_lib", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/tensorflow/lite/nnapi/NeuralNetworksShim.cc b/tensorflow/lite/nnapi/NeuralNetworksShim.cc new file mode 100644 index 0000000000..6858fbdd57 --- /dev/null +++ b/tensorflow/lite/nnapi/NeuralNetworksShim.cc @@ -0,0 +1,129 @@ +/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/nnapi/NeuralNetworksShim.h" + +#include + +#ifdef __ANDROID__ +#include +#include +#include +#endif + +#define NNAPI_LOG(format, ...) fprintf(stderr, format "\n", __VA_ARGS__); + +namespace { + +#ifdef __ANDROID__ +int32_t GetAndroidSdkVersion() { + const char* sdkProp = "ro.build.version.sdk"; + char sdkVersion[PROP_VALUE_MAX]; + int length = __system_property_get(sdkProp, sdkVersion); + if (length != 0) { + int32_t result = 0; + for (int i = 0; i < length; ++i) { + int digit = sdkVersion[i] - '0'; + if (digit < 0 || digit > 9) { + // Non-numeric SDK version, assume it's higher than expected; + return 0xffff; + } + result = result * 10 + digit; + } + return result; + } + return 0; +} + +void* LoadFunction(void* handle, const char* name) { + if (handle == nullptr) { + return nullptr; + } + void* fn = dlsym(handle, name); + if (fn == nullptr) { + NNAPI_LOG("nnapi error: unable to open function %s", name); + } + return fn; +} + +#define LOAD_FUNCTION(handle, name) \ + nnapi.name = reinterpret_cast(LoadFunction(handle, #name)); + +#else + +#define LOAD_FUNCTION(handle, name) nnapi.name = nullptr; + +#endif + +const NnApi LoadNnApi() { + NnApi nnapi = {}; + +#ifdef __ANDROID__ + // TODO: change RTLD_LOCAL? Assumes there can be multiple instances of nn + // api RT + void* libneuralnetworks = + dlopen("libneuralnetworks.so", RTLD_LAZY | RTLD_LOCAL); + if (libneuralnetworks == nullptr) { + NNAPI_LOG("nnapi error: unable to open library %s", "libneuralnetworks.so"); + } + void* libandroid = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL); + if (libneuralnetworks == nullptr) { + NNAPI_LOG("nnapi error: unable to open library %s", "libandroid.so"); + } + nnapi.nnapi_exists = libneuralnetworks != nullptr; + nnapi.android_sdk_version = GetAndroidSdkVersion(); +#else + nnapi.nnapi_exists = false; + nnapi.android_sdk_version = 0; +#endif + + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_createFromFd); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_free); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_create); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_free); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_finish); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperand); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValue); + LOAD_FUNCTION(libneuralnetworks, + ANeuralNetworksModel_setOperandValueFromMemory); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperation); + LOAD_FUNCTION(libneuralnetworks, + ANeuralNetworksModel_identifyInputsAndOutputs); + LOAD_FUNCTION(libneuralnetworks, + ANeuralNetworksModel_relaxComputationFloat32toFloat16); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_create); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_free); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_setPreference); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_finish); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_create); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_free); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInput); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInputFromMemory); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutput); + LOAD_FUNCTION(libneuralnetworks, + ANeuralNetworksExecution_setOutputFromMemory); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_startCompute); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_wait); + LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_free); + LOAD_FUNCTION(libandroid, ASharedMemory_create); + + return nnapi; +} + +} // namespace + +const NnApi* NnApiImplementation() { + static const NnApi nnapi = LoadNnApi(); + return &nnapi; +} diff --git a/tensorflow/lite/nnapi/NeuralNetworksShim.h b/tensorflow/lite/nnapi/NeuralNetworksShim.h index c39502f4ac..de44852666 100644 --- a/tensorflow/lite/nnapi/NeuralNetworksShim.h +++ b/tensorflow/lite/nnapi/NeuralNetworksShim.h @@ -20,64 +20,6 @@ limitations under the License. #include #include -// helpers - -#define NNAPI_LOG(format, ...) fprintf(stderr, format "\n", __VA_ARGS__); -#define LOAD_FUNCTION(name) \ - static name##_fn fn = reinterpret_cast(loadFunction(#name)); -#define EXECUTE_FUNCTION(...) \ - if (fn != nullptr) { \ - fn(__VA_ARGS__); \ - } -#define EXECUTE_FUNCTION_RETURN(...) return fn != nullptr ? fn(__VA_ARGS__) : 0; - -inline void* loadLibrary(const char* name) { - // TODO: change RTLD_LOCAL? Assumes there can be multiple instances of nn - // api RT - void* handle = nullptr; -#ifdef __ANDROID__ - handle = dlopen(name, RTLD_LAZY | RTLD_LOCAL); - if (handle == nullptr) { - NNAPI_LOG("nnapi error: unable to open library %s", name); - } -#endif - return handle; -} - -typedef int (*ASharedMemory_create_fn)(const char* name, size_t size); - -// ASharedMemory_create was added in Android 8.0, so safe to use with NNAPI -// which was added in 8.1. -inline int ASharedMemory_create(const char* name, size_t size) { - static void* handle = loadLibrary("libandroid.so"); - static ASharedMemory_create_fn fn = - handle != nullptr ? reinterpret_cast( - dlsym(handle, "ASharedMemory_create")) - : nullptr; - return fn(name, size); -} - -inline void* getLibraryHandle() { - static void* handle = loadLibrary("libneuralnetworks.so"); - return handle; -} - -inline void* loadFunction(const char* name) { - void* fn = nullptr; - if (getLibraryHandle() != nullptr) { - fn = dlsym(getLibraryHandle(), name); - } - if (fn == nullptr) { - NNAPI_LOG("nnapi error: unable to open function %s", name); - } - return fn; -} - -inline bool NNAPIExists() { - static bool nnapi_is_available = getLibraryHandle(); - return nnapi_is_available; -} - // NN api types based on NNAPI header file // https://developer.android.com/ndk/reference/group/neural-networks @@ -407,606 +349,564 @@ typedef int (*ANeuralNetworksEvent_wait_fn)(ANeuralNetworksEvent* event); typedef void (*ANeuralNetworksEvent_free_fn)(ANeuralNetworksEvent* event); -/** - * Creates a shared memory object from a file descriptor. - * - * The shared memory is backed by a file descriptor via mmap. - * See {@link ANeuralNetworksMemory} for a description on how to use - * this shared memory. - * - * @param size The requested size in bytes. - * Must not be larger than the file size. - * @param prot The desired memory protection for the mapping. - * It is either PROT_NONE or the bitwise OR of one or - * more of the following flags: PROT_READ, PROT_WRITE. - * @param fd The requested file descriptor. - * The file descriptor has to be mmap-able. The file - * descriptor will be duplicated. - * @param offset The offset to the beginning of the file of the area to map. - * The offset has to be aligned to a page size. - * @param memory The memory object to be created. - * Set to NULL if unsuccessful. - * - * @return ANEURALNETWORKS_NO_ERROR if the request completed normally. - */ -inline int ANeuralNetworksMemory_createFromFd(size_t size, int protect, int fd, - size_t offset, - ANeuralNetworksMemory** memory) { - LOAD_FUNCTION(ANeuralNetworksMemory_createFromFd); - EXECUTE_FUNCTION_RETURN(size, protect, fd, offset, memory); -} - -/** - * Delete a memory object. - * - * Destroys the object used by the run time to keep track of the memory. - * This will free the underlying actual memory if no other code has open - * handles to this memory. - * - * @param memory The memory object to be freed. - */ -inline void ANeuralNetworksMemory_free(ANeuralNetworksMemory* memory) { - LOAD_FUNCTION(ANeuralNetworksMemory_free); - EXECUTE_FUNCTION(memory); -} - -/** - * Create an empty {@link ANeuralNetworksModel}. - * - *

    This only creates the object. Computation is performed once - * {@link ANeuralNetworksExecution_startCompute} is invoked. - * - * The model should be constructed with calls to - * {@link ANeuralNetworksModel_addOperation} and - * {@link ANeuralNetworksModel_addOperand} - * - *

    {@link ANeuralNetworksModel_finish} should be called once the model - * has been fully constructed.

    - * - *

    {@link ANeuralNetworksModel_free} should be called once the model - * is no longer needed.

    - * - * @param model The {@link ANeuralNetworksModel} to be created. - * Set to NULL if unsuccessful. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ -inline int ANeuralNetworksModel_create(ANeuralNetworksModel** model) { - LOAD_FUNCTION(ANeuralNetworksModel_create); - EXECUTE_FUNCTION_RETURN(model); -} - -/** - * Destroy a model. - * - * The model need not have been finished by a call to - * {@link ANeuralNetworksModel_finish}. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be destroyed. Passing NULL is acceptable and - * results in no operation. - */ -inline void ANeuralNetworksModel_free(ANeuralNetworksModel* model) { - LOAD_FUNCTION(ANeuralNetworksModel_free); - EXECUTE_FUNCTION(model); -} - -/** - * Indicate that we have finished modifying a model. Required before - * calling {@link ANeuralNetworksCompilation_compile}. - * - * An application is responsible to make sure that no other thread uses - * the model at the same time. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be finished. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ -inline int ANeuralNetworksModel_finish(ANeuralNetworksModel* model) { - LOAD_FUNCTION(ANeuralNetworksModel_finish); - EXECUTE_FUNCTION_RETURN(model); -} - -/** - * Add an operand to a model. - * - * The order in which the operands are added is important. The first one added - * to a model will have the index value 0, the second 1, etc. These indexes are - * used as operand identifiers in {@link ANeuralNetworksModel_addOperation}, - * {@link ANeuralNetworksExecution_setInput}, - * {@link ANeuralNetworksExecution_setInputFromMemory}, - * {@link ANeuralNetworksExecution_setOutput}, - * {@link ANeuralNetworksExecution_setOutputFromMemory} and - * {@link ANeuralNetworksExecution_setOperandValue}. - * - * To build a model that can accommodate inputs of various sizes, as you may - * want to do for a CNN, set the size of the dimensions that will vary at run - * time to 0. If you do so, provide the full dimensions when calling - * {@link ANeuralNetworksExecution_setInput} or {@link - * ANeuralNetworksExecution_setInputFromMemory}. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be modified. - * @param type The {@link ANeuralNetworksOperandType} that describes the shape - * of the operand. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ -inline int ANeuralNetworksModel_addOperand( - ANeuralNetworksModel* model, const ANeuralNetworksOperandType* type) { - LOAD_FUNCTION(ANeuralNetworksModel_addOperand); - EXECUTE_FUNCTION_RETURN(model, type); -} - -/** - * Sets an operand to a constant value. - * - * For scalar values, the content of buffer is copied into the model. - * - * For tensor values, a pointer to the buffer is stored within the model. - * The application is responsible for not changing the content of this region - * until all executions using this model have completed. As the data may - * be copied during processing, modifying the data after this call yields - * undefined results. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be modified. - * @param index The index of the model operand we're setting. - * @param buffer A pointer to the data to use. - * @param length The size in bytes of the data value. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ -inline int ANeuralNetworksModel_setOperandValue(ANeuralNetworksModel* model, - int32_t index, - const void* buffer, - size_t length) { - LOAD_FUNCTION(ANeuralNetworksModel_setOperandValue); - EXECUTE_FUNCTION_RETURN(model, index, buffer, length); -} - -/** - * Sets an operand to a value stored in a memory object. - * - * The content of the memory is not copied. A reference to that memory is stored - * inside the model. The application is responsible for not changing the content - * of the memory region until all executions using this model have completed. - * As the data may be copied during processing, modifying the data after this - * call yields undefined results. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be modified. - * @param index The index of the model operand we're setting. - * @param buffer A pointer to the data to use. - * @param memory The memory containing the data. - * @param offset This specifies the location of the data within the memory. - * The offset is in bytes from the start of memory. - * @param length The size in bytes of the data value. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ -inline int ANeuralNetworksModel_setOperandValueFromMemory( - ANeuralNetworksModel* model, int32_t index, - const ANeuralNetworksMemory* memory, size_t offset, size_t length) { - LOAD_FUNCTION(ANeuralNetworksModel_setOperandValueFromMemory); - EXECUTE_FUNCTION_RETURN(model, index, memory, offset, length); -} - -/** - * Add an operation to a model. - * - * @param model The model to be modified. - * @param type The type of the operation. - * @param inputCount The number of entries in the inputs array. - * @param inputs An array of indexes identifying each operand. - * @param outputCount The number of entries in the outputs array. - * @param outputs An array of indexes identifying each operand. - * - * The operands specified by inputs and outputs must have been - * previously added by calls to {@link ANeuralNetworksModel_addOperand}. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ -inline int ANeuralNetworksModel_addOperation(ANeuralNetworksModel* model, - ANeuralNetworksOperationType type, - uint32_t inputCount, - const uint32_t* inputs, - uint32_t outputCount, - const uint32_t* outputs) { - LOAD_FUNCTION(ANeuralNetworksModel_addOperation); - EXECUTE_FUNCTION_RETURN(model, type, inputCount, inputs, outputCount, - outputs); -} - -/** - * Specifies which operands will be the model's inputs and outputs. - * - * An operand cannot be used for both input and output. Doing so will - * return an error. - * - * @param model The model to be modified. - * @param inputCount The number of entries in the inputs array. - * @param inputs An array of indexes identifying the input operands. - * @param outputCount The number of entries in the outputs array. - * @param outputs An array of indexes identifying the output operands. - * - * The operands specified by inputs and outputs must have been - * previously added by calls to {@link ANeuralNetworksModel_addOperand}. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - */ -inline int ANeuralNetworksModel_identifyInputsAndOutputs( - ANeuralNetworksModel* model, uint32_t inputCount, const uint32_t* inputs, - uint32_t outputCount, const uint32_t* outputs) { - LOAD_FUNCTION(ANeuralNetworksModel_identifyInputsAndOutputs); - EXECUTE_FUNCTION_RETURN(model, inputCount, inputs, outputCount, outputs); -} - -/** - * Specifies whether {@link ANEURALNETWORKS_TENSOR_FLOAT32} is allowed to be - * calculated with range and/or precision as low as that of the IEEE 754 16-bit - * floating-point format. By default, {@link ANEURALNETWORKS_TENSOR_FLOAT32} - * must be calculated using at least the range and precision of the IEEE 754 - * 32-bit floating-point format. - * - * @param model The model to be modified. - * @param allow 'true' indicates {@link ANEURALNETWORKS_TENSOR_FLOAT32} may be - * calculated with range and/or precision as low as that of the - * IEEE 754 16-bit floating point format. 'false' indicates - * {@link ANEURALNETWORKS_TENSOR_FLOAT32} must be calculated using - * at least the range and precision of the IEEE 754 32-bit floating - * point format. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * Available since API level 28. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - */ -inline int ANeuralNetworksModel_relaxComputationFloat32toFloat16( - ANeuralNetworksModel* model, bool allow) { - LOAD_FUNCTION(ANeuralNetworksModel_relaxComputationFloat32toFloat16); - EXECUTE_FUNCTION_RETURN(model, allow); -} - -/** - * Create a {@link ANeuralNetworksCompilation} to compile the given model. - * This only creates the object. Compilation is only performed once - * {@link ANeuralNetworksCompilation_start} is invoked. - * - *

    The provided model must outlive the compilation.

    - * - * The model must already have been finished by a call to - * {@link ANeuralNetworksModel_finish}. - * - * See {@link ANeuralNetworksCompilation} for information on multithreaded - * usage. - * - * @param model The {@link ANeuralNetworksModel} to be compiled. - * @param compilation The newly created object or NULL if unsuccessful. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA - * if the model is invalid. - */ -inline int ANeuralNetworksCompilation_create( - ANeuralNetworksModel* model, ANeuralNetworksCompilation** compilation) { - LOAD_FUNCTION(ANeuralNetworksCompilation_create); - EXECUTE_FUNCTION_RETURN(model, compilation); -} - -/** - * Destroy a compilation. - * - *

    If called on a compilation for which - * {@link ANeuralNetworksCompilation_start} has been called, the - * function will return immediately but will mark the compilation to be deleted - * once the compilation completes. The {@link ANeuralNetworksCompilation_wait} - * will return ERROR_DELETED. - * - * See {@link ANeuralNetworksCompilation} for information on multithreaded - * usage. - * - * @param compilation The compilation to be destroyed. Passing NULL is - * acceptable and results in no operation. - */ -inline void ANeuralNetworksCompilation_free( - ANeuralNetworksCompilation* compilation) { - LOAD_FUNCTION(ANeuralNetworksCompilation_free); - EXECUTE_FUNCTION(compilation); -} - -/** - * Sets the execution preference. - * - *

    Provides guidance to the runtime when trade-offs are possible.

    - * - * See {@link ANeuralNetworksCompilation} for information on multithreaded - * usage. - * - * @param compilation The compilation to be modified. - * @param preference Either {@link PREFER_LOW_POWER}, - * {@link PREFER_SINGLE_FAST_ANSWER}, or - * {@link PREFER_SUSTAINED_SPEED}. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ -inline int ANeuralNetworksCompilation_setPreference( - ANeuralNetworksCompilation* compilation, int32_t preference) { - LOAD_FUNCTION(ANeuralNetworksCompilation_setPreference); - EXECUTE_FUNCTION_RETURN(compilation, preference); -} - -/** - * Waits until the compilation completes. - * - * More than one thread can wait on a compilation. When the compilation - * completes, all threads will be released. - * - * See {@link ANeuralNetworksCompilation} for information on multithreaded - * usage. - * - * @return ANEURALNETWORKS_NO_ERROR if the compilation completed normally. - */ -inline int ANeuralNetworksCompilation_finish( - ANeuralNetworksCompilation* compilation) { - LOAD_FUNCTION(ANeuralNetworksCompilation_finish); - EXECUTE_FUNCTION_RETURN(compilation); -} -/** - * Create a {@link ANeuralNetworksExecution} to apply the given compilation. - * This only creates the object. Computation is only performed once - * {@link ANeuralNetworksExecution_startCompute} is invoked. - * - *

    The provided compilation must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded usage. - * - * @param compilation The {@link ANeuralNetworksCompilation} to be evaluated. - * @param execution The newly created object or NULL if unsuccessful. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA - * if the compilation is invalid. - */ -inline int ANeuralNetworksExecution_create( - ANeuralNetworksCompilation* compilation, - ANeuralNetworksExecution** execution) { - LOAD_FUNCTION(ANeuralNetworksExecution_create); - EXECUTE_FUNCTION_RETURN(compilation, execution); -} - -/** - * Destroy an execution. - * - *

    If called on an execution for which - * {@link ANeuralNetworksExecution_startCompute} has been called, the - * function will return immediately but will mark the execution to be deleted - * once the computation completes. The {link ANeuralNetworksExecution_wait} - * will return ANEURALNETWORKS_ERROR_DELETED. - * - * See {@link ANeuralNetworksExecution} for information on multithreaded usage. - * - * @param execution The execution to be destroyed. Passing NULL is acceptable - * and results in no operation. - */ -inline void ANeuralNetworksExecution_free(ANeuralNetworksExecution* execution) { - LOAD_FUNCTION(ANeuralNetworksExecution_free); - EXECUTE_FUNCTION(execution); -} - -/** - * Associate a user buffer with an input of the model of the - * {@link ANeuralNetworksExecution}. - * - *

    The provided buffer must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded usage. - * - * @param execution The execution to be modified. - * @param index The index of the input argument we are setting. It is - * an index into the lists passed to - * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is not - * the index associated with {@link - * ANeuralNetworksModel_addOperand}. - * @param type The type of the operand. This should be used to specify the - * dimensions that were set to 0 when the operand was added to the - * model. All other properties of the type must be the same as - * specified in the model. If the type is the same as specified - * when the model was built, NULL can be passed. - * @param buffer The buffer containing the data. - * @param length The length in bytes of the buffer. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if - * the name is not recognized or the buffer is too small for the input. - */ -inline int ANeuralNetworksExecution_setInput( - ANeuralNetworksExecution* execution, int32_t index, - const ANeuralNetworksOperandType* type, const void* buffer, size_t length) { - LOAD_FUNCTION(ANeuralNetworksExecution_setInput); - EXECUTE_FUNCTION_RETURN(execution, index, type, buffer, length); -} - -/** - * Associate part of a memory object with an input of the model of the - * {@link ANeuralNetworksExecution}. - * - *

    The provided memory must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded usage. - * - * @param execution The execution to be modified. - * @param index The index of the input argument we are setting. It is - * an index into the lists passed to - * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is not - * the index associated with {@link - * ANeuralNetworksModel_addOperand}. - * @param type The type of the operand. This can be used to specify the - * dimensions that were set to 0 when the operand was added to the - * model. All other values must be the same as specified in the - * model. If the type is the same as specified when the model - * was built, NULL can be passed. - * @param memory The memory containing the data. - * @param offset This specifies the location of the data within the memory. - * The offset is in bytes from the start of memory. - * @param length The size in bytes of the data value. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if - * the name is not recognized or the buffer is too small for the input. - */ -inline int ANeuralNetworksExecution_setInputFromMemory( - ANeuralNetworksExecution* execution, int32_t index, - const ANeuralNetworksOperandType* type, const ANeuralNetworksMemory* memory, - size_t offset, size_t length) { - LOAD_FUNCTION(ANeuralNetworksExecution_setInputFromMemory); - EXECUTE_FUNCTION_RETURN(execution, index, type, memory, offset, length); -} +typedef int (*ASharedMemory_create_fn)(const char* name, size_t size); -/** - * Associate a user buffer with an output of the model of the - * {@link ANeuralNetworksExecution}. - * - *

    The provided buffer must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded usage. - * - * @param execution The execution to be modified. - * @param index The index of the output argument we are setting. It is - * an index into the lists passed to - * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is not - * the index associated with {@link - * ANeuralNetworksModel_addOperand}. - * @param type The type of the operand. This can be used to specify the - * dimensions that were set to 0 when the operand was added to the - * model. All other values must be the same as specified in the - * model. If the type is the same as specified when the model - * was built, NULL can be passed. - * @param buffer The buffer where the data is to be written. - * @param length The length in bytes of the buffer. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if - * the name is not recognized or the buffer is too small for the output. - */ -inline int ANeuralNetworksExecution_setOutput( - ANeuralNetworksExecution* execution, int32_t index, - const ANeuralNetworksOperandType* type, void* buffer, size_t length) { - LOAD_FUNCTION(ANeuralNetworksExecution_setOutput); - EXECUTE_FUNCTION_RETURN(execution, index, type, buffer, length); -} +struct NnApi { + bool nnapi_exists; + int32_t android_sdk_version; + + /** + * Creates a shared memory object from a file descriptor. + * + * The shared memory is backed by a file descriptor via mmap. + * See {@link ANeuralNetworksMemory} for a description on how to use + * this shared memory. + * + * @param size The requested size in bytes. + * Must not be larger than the file size. + * @param prot The desired memory protection for the mapping. + * It is either PROT_NONE or the bitwise OR of one or + * more of the following flags: PROT_READ, PROT_WRITE. + * @param fd The requested file descriptor. + * The file descriptor has to be mmap-able. The file + * descriptor will be duplicated. + * @param offset The offset to the beginning of the file of the area to map. + * The offset has to be aligned to a page size. + * @param memory The memory object to be created. + * Set to NULL if unsuccessful. + * + * @return ANEURALNETWORKS_NO_ERROR if the request completed normally. + */ + int (*ANeuralNetworksMemory_createFromFd)(size_t size, int protect, int fd, + size_t offset, + ANeuralNetworksMemory** memory); + + /** + * Delete a memory object. + * + * Destroys the object used by the run time to keep track of the memory. + * This will free the underlying actual memory if no other code has open + * handles to this memory. + * + * @param memory The memory object to be freed. + */ + void (*ANeuralNetworksMemory_free)(ANeuralNetworksMemory* memory); + + /** + * Create an empty {@link ANeuralNetworksModel}. + * + *

    This only creates the object. Computation is performed once + * {@link ANeuralNetworksExecution_startCompute} is invoked. + * + * The model should be constructed with calls to + * {@link ANeuralNetworksModel_addOperation} and + * {@link ANeuralNetworksModel_addOperand} + * + *

    {@link ANeuralNetworksModel_finish} should be called once the model + * has been fully constructed.

    + * + *

    {@link ANeuralNetworksModel_free} should be called once the model + * is no longer needed.

    + * + * @param model The {@link ANeuralNetworksModel} to be created. + * Set to NULL if unsuccessful. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ + int (*ANeuralNetworksModel_create)(ANeuralNetworksModel** model); + + /** + * Destroy a model. + * + * The model need not have been finished by a call to + * {@link ANeuralNetworksModel_finish}. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be destroyed. Passing NULL is acceptable and + * results in no operation. + */ + void (*ANeuralNetworksModel_free)(ANeuralNetworksModel* model); + + /** + * Indicate that we have finished modifying a model. Required before + * calling {@link ANeuralNetworksCompilation_compile}. + * + * An application is responsible to make sure that no other thread uses + * the model at the same time. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be finished. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ + int (*ANeuralNetworksModel_finish)(ANeuralNetworksModel* model); + + /** + * Add an operand to a model. + * + * The order in which the operands are added is important. The first one added + * to a model will have the index value 0, the second 1, etc. These indexes + * are used as operand identifiers in + * {@link ANeuralNetworksModel_addOperation}, + * {@link ANeuralNetworksExecution_setInput}, + * {@link ANeuralNetworksExecution_setInputFromMemory}, + * {@link ANeuralNetworksExecution_setOutput}, + * {@link ANeuralNetworksExecution_setOutputFromMemory} and + * {@link ANeuralNetworksExecution_setOperandValue}. + * + * To build a model that can accommodate inputs of various sizes, as you may + * want to do for a CNN, set the size of the dimensions that will vary at run + * time to 0. If you do so, provide the full dimensions when calling + * {@link ANeuralNetworksExecution_setInput} or {@link + * ANeuralNetworksExecution_setInputFromMemory}. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be modified. + * @param type The {@link ANeuralNetworksOperandType} that describes the shape + * of the operand. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ + int (*ANeuralNetworksModel_addOperand)( + ANeuralNetworksModel* model, const ANeuralNetworksOperandType* type); + + /** + * Sets an operand to a constant value. + * + * For scalar values, the content of buffer is copied into the model. + * + * For tensor values, a pointer to the buffer is stored within the model. + * The application is responsible for not changing the content of this region + * until all executions using this model have completed. As the data may + * be copied during processing, modifying the data after this call yields + * undefined results. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be modified. + * @param index The index of the model operand we're setting. + * @param buffer A pointer to the data to use. + * @param length The size in bytes of the data value. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ + int (*ANeuralNetworksModel_setOperandValue)(ANeuralNetworksModel* model, + int32_t index, const void* buffer, + size_t length); + + /** + * Sets an operand to a value stored in a memory object. + * + * The content of the memory is not copied. A reference to that memory is + * stored inside the model. The application is responsible for not changing + * the content of the memory region until all executions using this model have + * completed. + * As the data may be copied during processing, modifying the data after this + * call yields undefined results. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be modified. + * @param index The index of the model operand we're setting. + * @param buffer A pointer to the data to use. + * @param memory The memory containing the data. + * @param offset This specifies the location of the data within the memory. + * The offset is in bytes from the start of memory. + * @param length The size in bytes of the data value. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ + int (*ANeuralNetworksModel_setOperandValueFromMemory)( + ANeuralNetworksModel* model, int32_t index, + const ANeuralNetworksMemory* memory, size_t offset, size_t length); + + /** + * Add an operation to a model. + * + * @param model The model to be modified. + * @param type The type of the operation. + * @param inputCount The number of entries in the inputs array. + * @param inputs An array of indexes identifying each operand. + * @param outputCount The number of entries in the outputs array. + * @param outputs An array of indexes identifying each operand. + * + * The operands specified by inputs and outputs must have been + * previously added by calls to {@link ANeuralNetworksModel_addOperand}. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ + int (*ANeuralNetworksModel_addOperation)(ANeuralNetworksModel* model, + ANeuralNetworksOperationType type, + uint32_t inputCount, + const uint32_t* inputs, + uint32_t outputCount, + const uint32_t* outputs); + + /** + * Specifies which operands will be the model's inputs and outputs. + * + * An operand cannot be used for both input and output. Doing so will + * return an error. + * + * @param model The model to be modified. + * @param inputCount The number of entries in the inputs array. + * @param inputs An array of indexes identifying the input operands. + * @param outputCount The number of entries in the outputs array. + * @param outputs An array of indexes identifying the output operands. + * + * The operands specified by inputs and outputs must have been + * previously added by calls to {@link ANeuralNetworksModel_addOperand}. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + */ + int (*ANeuralNetworksModel_identifyInputsAndOutputs)( + ANeuralNetworksModel* model, uint32_t inputCount, const uint32_t* inputs, + uint32_t outputCount, const uint32_t* outputs); + + /** + * Specifies whether {@link ANEURALNETWORKS_TENSOR_FLOAT32} is allowed to be + * calculated with range and/or precision as low as that of the + * IEEE 754 16-bit floating-point format. By default, + * {@link ANEURALNETWORKS_TENSOR_FLOAT32} must be calculated using at least + * the range and precision of the IEEE 754 32-bit floating-point format. + * + * @param model The model to be modified. + * @param allow 'true' indicates {@link ANEURALNETWORKS_TENSOR_FLOAT32} may be + * calculated with range and/or precision as low as that of the + * IEEE 754 16-bit floating point format. 'false' indicates + * {@link ANEURALNETWORKS_TENSOR_FLOAT32} must be calculated + * using at least the range and precision of the IEEE 754 32-bit + * floating point format. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * Available since API level 28. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + */ + int (*ANeuralNetworksModel_relaxComputationFloat32toFloat16)( + ANeuralNetworksModel* model, bool allow); + + /** + * Create a {@link ANeuralNetworksCompilation} to compile the given model. + * This only creates the object. Compilation is only performed once + * {@link ANeuralNetworksCompilation_start} is invoked. + * + *

    The provided model must outlive the compilation.

    + * + * The model must already have been finished by a call to + * {@link ANeuralNetworksModel_finish}. + * + * See {@link ANeuralNetworksCompilation} for information on multithreaded + * usage. + * + * @param model The {@link ANeuralNetworksModel} to be compiled. + * @param compilation The newly created object or NULL if unsuccessful. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA + * if the model is invalid. + */ + int (*ANeuralNetworksCompilation_create)( + ANeuralNetworksModel* model, ANeuralNetworksCompilation** compilation); + + /** + * Destroy a compilation. + * + *

    If called on a compilation for which + * {@link ANeuralNetworksCompilation_start} has been called, the + * function will return immediately but will mark the compilation to be + * deleted once the compilation completes. The + * {@link ANeuralNetworksCompilation_wait} will return ERROR_DELETED. + * + * See {@link ANeuralNetworksCompilation} for information on multithreaded + * usage. + * + * @param compilation The compilation to be destroyed. Passing NULL is + * acceptable and results in no operation. + */ + void (*ANeuralNetworksCompilation_free)( + ANeuralNetworksCompilation* compilation); + + /** + * Sets the execution preference. + * + *

    Provides guidance to the runtime when trade-offs are possible.

    + * + * See {@link ANeuralNetworksCompilation} for information on multithreaded + * usage. + * + * @param compilation The compilation to be modified. + * @param preference Either {@link PREFER_LOW_POWER}, + * {@link PREFER_SINGLE_FAST_ANSWER}, or + * {@link PREFER_SUSTAINED_SPEED}. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ + int (*ANeuralNetworksCompilation_setPreference)( + ANeuralNetworksCompilation* compilation, int32_t preference); + + /** + * Waits until the compilation completes. + * + * More than one thread can wait on a compilation. When the compilation + * completes, all threads will be released. + * + * See {@link ANeuralNetworksCompilation} for information on multithreaded + * usage. + * + * @return ANEURALNETWORKS_NO_ERROR if the compilation completed normally. + */ + int (*ANeuralNetworksCompilation_finish)( + ANeuralNetworksCompilation* compilation); + + /** + * Create a {@link ANeuralNetworksExecution} to apply the given compilation. + * This only creates the object. Computation is only performed once + * {@link ANeuralNetworksExecution_startCompute} is invoked. + * + *

    The provided compilation must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded + * usage. + * + * @param compilation The {@link ANeuralNetworksCompilation} to be evaluated. + * @param execution The newly created object or NULL if unsuccessful. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA + * if the compilation is invalid. + */ + int (*ANeuralNetworksExecution_create)( + ANeuralNetworksCompilation* compilation, + ANeuralNetworksExecution** execution); + + /** + * Destroy an execution. + * + *

    If called on an execution for which + * {@link ANeuralNetworksExecution_startCompute} has been called, the + * function will return immediately but will mark the execution to be deleted + * once the computation completes. The {link ANeuralNetworksExecution_wait} + * will return ANEURALNETWORKS_ERROR_DELETED. + * + * See {@link ANeuralNetworksExecution} for information on multithreaded + * usage. + * + * @param execution The execution to be destroyed. Passing NULL is acceptable + * and results in no operation. + */ + void (*ANeuralNetworksExecution_free)(ANeuralNetworksExecution* execution); + + /** + * Associate a user buffer with an input of the model of the + * {@link ANeuralNetworksExecution}. + * + *

    The provided buffer must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded + * usage. + * + * @param execution The execution to be modified. + * @param index The index of the input argument we are setting. It is + * an index into the lists passed to + * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is + * not the index associated with {@link + * ANeuralNetworksModel_addOperand}. + * @param type The type of the operand. This should be used to specify the + * dimensions that were set to 0 when the operand was added to the + * model. All other properties of the type must be the same as + * specified in the model. If the type is the same as specified + * when the model was built, NULL can be passed. + * @param buffer The buffer containing the data. + * @param length The length in bytes of the buffer. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if + * the name is not recognized or the buffer is too small for the input. + */ + int (*ANeuralNetworksExecution_setInput)( + ANeuralNetworksExecution* execution, int32_t index, + const ANeuralNetworksOperandType* type, const void* buffer, + size_t length); + + /** + * Associate part of a memory object with an input of the model of the + * {@link ANeuralNetworksExecution}. + * + *

    The provided memory must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded + * usage. + * + * @param execution The execution to be modified. + * @param index The index of the input argument we are setting. It is + * an index into the lists passed to + * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is + * not the index associated with {@link + * ANeuralNetworksModel_addOperand}. + * @param type The type of the operand. This can be used to specify the + * dimensions that were set to 0 when the operand was added to the + * model. All other values must be the same as specified in the + * model. If the type is the same as specified when the model + * was built, NULL can be passed. + * @param memory The memory containing the data. + * @param offset This specifies the location of the data within the memory. + * The offset is in bytes from the start of memory. + * @param length The size in bytes of the data value. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if + * the name is not recognized or the buffer is too small for the input. + */ + int (*ANeuralNetworksExecution_setInputFromMemory)( + ANeuralNetworksExecution* execution, int32_t index, + const ANeuralNetworksOperandType* type, + const ANeuralNetworksMemory* memory, size_t offset, size_t length); + + /** + * Associate a user buffer with an output of the model of the + * {@link ANeuralNetworksExecution}. + * + *

    The provided buffer must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded + * usage. + * + * @param execution The execution to be modified. + * @param index The index of the output argument we are setting. It is + * an index into the lists passed to + * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is + * not the index associated with {@link + * ANeuralNetworksModel_addOperand}. + * @param type The type of the operand. This can be used to specify the + * dimensions that were set to 0 when the operand was added to the + * model. All other values must be the same as specified in the + * model. If the type is the same as specified when the model + * was built, NULL can be passed. + * @param buffer The buffer where the data is to be written. + * @param length The length in bytes of the buffer. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if + * the name is not recognized or the buffer is too small for the output. + */ + int (*ANeuralNetworksExecution_setOutput)( + ANeuralNetworksExecution* execution, int32_t index, + const ANeuralNetworksOperandType* type, void* buffer, size_t length); + + /** + * Associate part of a memory object with an output of the model of the + * {@link ANeuralNetworksExecution}. + * + *

    The provided memory must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded + * usage. + * + * @param execution The execution to be modified. + * @param index The index of the output argument we are setting. It is + * an index into the lists passed to + * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is + * not the index associated with {@link + * ANeuralNetworksModel_addOperand}. + * @param type The type of the operand. This can be used to specify the + * dimensions that were set to 0 when the operand was added to the + * model. All other values must be the same as specified in the + * model. If the type is the same as specified when the model + * was built, NULL can be passed. + * @param memory The memory where the data is to be stored. + * @param offset This specifies the location of the data within the memory. + * The offset is in bytes from the start of memory. + * @param length The length in bytes of the data value. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if + * the name is not recognized or the buffer is too small for the output. + */ + int (*ANeuralNetworksExecution_setOutputFromMemory)( + ANeuralNetworksExecution* execution, int32_t index, + const ANeuralNetworksOperandType* type, + const ANeuralNetworksMemory* memory, size_t offset, size_t length); + + /** + * Schedule evaluation of the execution. + * + *

    Schedules evaluation of the execution. Once the model has been + * applied and the outputs are ready to be consumed, the execution will be + * signaled. Use {@link ANeuralNetworksExecution_wait} to wait for that + * signal. + *

    + * + * Multiple executions can be scheduled and evaluated concurrently, and + * compilations can be performed concurrently with executions. The runtime + * makes no guarantee on the ordering of the completion of compilations and + * executions. If it's important to the application, the application should + * enforce the ordering by using {@link ANeuralNetworksCompilation_wait} and + * {@link ANeuralNetworksExecution_wait}. + * + * ANeuralNetworksExecution_wait must be called to recuperate the resources + * used by the execution. + * + * See {@link ANeuralNetworksExecution} for information on multithreaded + * usage. + * + * @param execution The execution to be scheduled and executed. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ + int (*ANeuralNetworksExecution_startCompute)( + ANeuralNetworksExecution* execution, ANeuralNetworksEvent** event); + + /** + * Waits until the execution completes. + * + * More than one thread can wait on an event. When the execution completes, + * all threads will be released. + * + * See {@link ANeuralNetworksExecution} for information on multithreaded + * usage. + * + * @return ANEURALNETWORKS_NO_ERROR if the execution completed normally. + */ + int (*ANeuralNetworksEvent_wait)(ANeuralNetworksEvent* event); -/** - * Associate part of a memory object with an output of the model of the - * {@link ANeuralNetworksExecution}. - * - *

    The provided memory must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded usage. - * - * @param execution The execution to be modified. - * @param index The index of the output argument we are setting. It is - * an index into the lists passed to - * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is not - * the index associated with {@link - * ANeuralNetworksModel_addOperand}. - * @param type The type of the operand. This can be used to specify the - * dimensions that were set to 0 when the operand was added to the - * model. All other values must be the same as specified in the - * model. If the type is the same as specified when the model - * was built, NULL can be passed. - * @param memory The memory where the data is to be stored. - * @param offset This specifies the location of the data within the memory. - * The offset is in bytes from the start of memory. - * @param length The length in bytes of the data value. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if - * the name is not recognized or the buffer is too small for the output. - */ -inline int ANeuralNetworksExecution_setOutputFromMemory( - ANeuralNetworksExecution* execution, int32_t index, - const ANeuralNetworksOperandType* type, const ANeuralNetworksMemory* memory, - size_t offset, size_t length) { - LOAD_FUNCTION(ANeuralNetworksExecution_setOutputFromMemory); - EXECUTE_FUNCTION_RETURN(execution, index, type, memory, offset, length); -} + /** + * Destroys the event. + * + * See {@link ANeuralNetworksExecution} for information on multithreaded + * usage. + */ + void (*ANeuralNetworksEvent_free)(ANeuralNetworksEvent* event); -/** - * Schedule evaluation of the execution. - * - *

    Schedules evaluation of the execution. Once the model has been - * applied and the outputs are ready to be consumed, the execution will be - * signaled. Use {@link ANeuralNetworksExecution_wait} to wait for that signal. - *

    - * - * Multiple executions can be scheduled and evaluated concurrently, and - * compilations can be performed concurrently with executions. The runtime makes - * no guarantee on the ordering of the completion of compilations and - * executions. If it's important to the application, the application should - * enforce the ordering by using {@link ANeuralNetworksCompilation_wait} and - * {@link ANeuralNetworksExecution_wait}. - * - * ANeuralNetworksExecution_wait must be called to recuperate the resources used - * by the execution. - * - * See {@link ANeuralNetworksExecution} for information on multithreaded usage. - * - * @param execution The execution to be scheduled and executed. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ -inline int ANeuralNetworksExecution_startCompute( - ANeuralNetworksExecution* execution, ANeuralNetworksEvent** event) { - LOAD_FUNCTION(ANeuralNetworksExecution_startCompute); - EXECUTE_FUNCTION_RETURN(execution, event); -} + // ASharedMemory_create was added in Android 8.0, so safe to use with NNAPI + // which was added in 8.1. + int (*ASharedMemory_create)(const char* name, size_t size); -/** - * Waits until the execution completes. - * - * More than one thread can wait on an event. When the execution completes, - * all threads will be released. - * - * See {@link ANeuralNetworksExecution} for information on multithreaded usage. - * - * @return ANEURALNETWORKS_NO_ERROR if the execution completed normally. - */ -inline int ANeuralNetworksEvent_wait(ANeuralNetworksEvent* event) { - LOAD_FUNCTION(ANeuralNetworksEvent_wait); - EXECUTE_FUNCTION_RETURN(event); -} + /**/ +}; /** - * Destroys the event. - * - * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + * Load the NNAPI implementation from the shared libraries. + * The NnApi structure is filled with all the pointers. If one function doesn't + * exist, a null pointer is stored. */ -inline void ANeuralNetworksEvent_free(ANeuralNetworksEvent* event) { - LOAD_FUNCTION(ANeuralNetworksEvent_free); - EXECUTE_FUNCTION(event); -} - -/**/ +const NnApi* NnApiImplementation(); #endif // TENSORFLOW_LITE_NNAPI_NEURALNETWORKSSHIM_H_ diff --git a/tensorflow/lite/nnapi/nnapi_lib_test.cc b/tensorflow/lite/nnapi/nnapi_lib_test.cc new file mode 100644 index 0000000000..46b90115b6 --- /dev/null +++ b/tensorflow/lite/nnapi/nnapi_lib_test.cc @@ -0,0 +1,90 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include "tensorflow/lite/nnapi/NeuralNetworksShim.h" + +namespace { + +TEST(NnapiLibTest, NnApiImplementation) { + const NnApi* nnapi_ = NnApiImplementation(); + EXPECT_NE(nnapi_, nullptr); +#ifdef __ANDROID__ + EXPECT_TRUE(nnapi_->nnapi_exists); + EXPECT_GT(nnapi_->android_sdk_version, 0); + EXPECT_NE(nnapi_->ANeuralNetworksMemory_createFromFd, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksMemory_free, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksModel_create, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksModel_free, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksModel_finish, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksModel_addOperand, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksModel_setOperandValue, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksModel_setOperandValueFromMemory, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksModel_addOperation, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksModel_identifyInputsAndOutputs, nullptr); + if (nnapi_->android_sdk_version >= 28) { + // relaxComputationFloat32toFloat16 only available with Android 9.0 (P). + EXPECT_NE(nnapi_->ANeuralNetworksModel_relaxComputationFloat32toFloat16, + nullptr); + } else { + EXPECT_EQ(nnapi_->ANeuralNetworksModel_relaxComputationFloat32toFloat16, + nullptr); + } + EXPECT_NE(nnapi_->ANeuralNetworksCompilation_create, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksCompilation_free, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksCompilation_setPreference, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksCompilation_finish, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksExecution_create, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksExecution_free, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksExecution_setInput, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksExecution_setInputFromMemory, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksExecution_setOutput, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksExecution_setOutputFromMemory, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksExecution_startCompute, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksEvent_wait, nullptr); + EXPECT_NE(nnapi_->ANeuralNetworksEvent_free, nullptr); + EXPECT_NE(nnapi_->ASharedMemory_create, nullptr); +#else + EXPECT_FALSE(nnapi_->nnapi_exists); + EXPECT_EQ(nnapi_->android_sdk_version, 0); + EXPECT_EQ(nnapi_->ANeuralNetworksMemory_createFromFd, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksMemory_free, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksModel_create, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksModel_free, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksModel_finish, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksModel_addOperand, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksModel_setOperandValue, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksModel_setOperandValueFromMemory, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksModel_addOperation, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksModel_identifyInputsAndOutputs, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksModel_relaxComputationFloat32toFloat16, + nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksCompilation_create, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksCompilation_free, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksCompilation_setPreference, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksCompilation_finish, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksExecution_create, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksExecution_free, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksExecution_setInput, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksExecution_setInputFromMemory, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksExecution_setOutput, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksExecution_setOutputFromMemory, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksExecution_startCompute, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksEvent_wait, nullptr); + EXPECT_EQ(nnapi_->ANeuralNetworksEvent_free, nullptr); + EXPECT_EQ(nnapi_->ASharedMemory_create, nullptr); +#endif +} + +} // namespace diff --git a/tensorflow/lite/nnapi_delegate.cc b/tensorflow/lite/nnapi_delegate.cc index 26d75696a1..202f38ba9c 100644 --- a/tensorflow/lite/nnapi_delegate.cc +++ b/tensorflow/lite/nnapi_delegate.cc @@ -84,56 +84,27 @@ void logError(const char* format, ...) { static const int64_t kOperandIdNotSet = -1; static const int64_t kOperandNotNeeded = -2; -namespace { - -int32_t GetAndroidSdkVersion() { -#ifdef __ANDROID__ - const char* sdkProp = "ro.build.version.sdk"; - char sdkVersion[PROP_VALUE_MAX]; - int length = __system_property_get(sdkProp, sdkVersion); - if (length != 0) { - for (int i = 0; i < length; ++i) { - int digit = sdkVersion[i] - '0'; - if (digit < 0 || digit > 9) { - // Non-numeric SDK version, assume it's higher then expected; - return 0xFFFF; - } - } - return atoi(sdkVersion); - } - FATAL("No %s prop", sdkProp); -#endif // __ANDROID__ - return 0; -} - -int32_t GetAndroidSdkVersionCached() { - static int32_t androidSdkVersion = GetAndroidSdkVersion(); - return androidSdkVersion; -} - -} // namespace - NNAPIAllocation::NNAPIAllocation(const char* filename, ErrorReporter* error_reporter) : MMAPAllocation(filename, error_reporter) { if (mmapped_buffer_ != MAP_FAILED) - CHECK_NN(ANeuralNetworksMemory_createFromFd(buffer_size_bytes_, PROT_READ, - mmap_fd_, 0, &handle_)); + CHECK_NN(NnApiImplementation()->ANeuralNetworksMemory_createFromFd( + buffer_size_bytes_, PROT_READ, mmap_fd_, 0, &handle_)); } NNAPIAllocation::~NNAPIAllocation() { if (handle_) { - ANeuralNetworksMemory_free(handle_); + NnApiImplementation()->ANeuralNetworksMemory_free(handle_); } } NNAPIDelegate::~NNAPIDelegate() { if (nn_compiled_model_) { - ANeuralNetworksCompilation_free(nn_compiled_model_); + NnApiImplementation()->ANeuralNetworksCompilation_free(nn_compiled_model_); nn_compiled_model_ = nullptr; } if (nn_model_) { - ANeuralNetworksModel_free(nn_model_); + NnApiImplementation()->ANeuralNetworksModel_free(nn_model_); nn_model_ = nullptr; // TODO(aselle): Is this thread-safe and callable multiple times? } @@ -145,6 +116,7 @@ TfLiteStatus addTensorOperands(tflite::Subgraph* subgraph, ANeuralNetworksModel* nn_model, uint32_t* no_of_operands_added, std::vector* nnapi_ids) { + const NnApi* nnapi = NnApiImplementation(); uint32_t next_id = 0; for (size_t i = 0; i < subgraph->tensors_size(); i++) { // Skip temporaries and RNN back-edges. @@ -198,24 +170,24 @@ TfLiteStatus addTensorOperands(tflite::Subgraph* subgraph, nn_type, static_cast(tensor->dims->size), reinterpret_cast(tensor->dims->data), scale, zeroPoint}; RETURN_ERROR_IF_NN_FAILED( - ANeuralNetworksModel_addOperand(nn_model, &operand_type)); + nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)); // TODO(aselle): Based on Michael's suggestion, limiting this to read // only memory if (tensor->allocation_type == kTfLiteMmapRo) { if (const NNAPIAllocation* alloc = dynamic_cast( static_cast(tensor->allocation))) { RETURN_ERROR_IF_NN_FAILED( - ANeuralNetworksModel_setOperandValueFromMemory( + nnapi->ANeuralNetworksModel_setOperandValueFromMemory( nn_model, next_id, alloc->memory(), alloc->offset(tensor->data.raw), tensor->bytes)); } else { - RETURN_ERROR_IF_NN_FAILED(ANeuralNetworksModel_setOperandValue( + RETURN_ERROR_IF_NN_FAILED(nnapi->ANeuralNetworksModel_setOperandValue( nn_model, next_id, tensor->data.raw, tensor->bytes)); } } else if (tensor->bytes == 0) { // These size 0 tensors are optional tensors reserved. - RETURN_ERROR_IF_NN_FAILED( - ANeuralNetworksModel_setOperandValue(nn_model, next_id, nullptr, 0)); + RETURN_ERROR_IF_NN_FAILED(nnapi->ANeuralNetworksModel_setOperandValue( + nn_model, next_id, nullptr, 0)); } ++next_id; @@ -244,6 +216,7 @@ TfLiteStatus AddOpsAndParams( uint32_t next_id, std::vector* model_state_inputs, std::vector* model_state_outputs, const std::vector& tensor_id_to_nnapi_id) { + const NnApi* nnapi = NnApiImplementation(); for (size_t i = 0; i < subgraph->nodes_size(); i++) { const auto* node_and_registration = subgraph->node_and_registration(i); const TfLiteNode& node = node_and_registration->first; @@ -258,21 +231,21 @@ TfLiteStatus AddOpsAndParams( MapAndAddTensorIds(node.outputs->data, node.outputs->size, &augmented_outputs, tensor_id_to_nnapi_id); - auto add_scalar_int32 = [&nn_model, &augmented_inputs, + auto add_scalar_int32 = [nnapi, &nn_model, &augmented_inputs, &next_id](int value) { ANeuralNetworksOperandType operand_type{.type = ANEURALNETWORKS_INT32}; - CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)) - CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, &value, - sizeof(int32_t))) + CHECK_NN(nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)) + CHECK_NN(nnapi->ANeuralNetworksModel_setOperandValue( + nn_model, next_id, &value, sizeof(int32_t))) augmented_inputs.push_back(next_id++); }; - auto add_scalar_float32 = [&nn_model, &augmented_inputs, + auto add_scalar_float32 = [nnapi, &nn_model, &augmented_inputs, &next_id](float value) { ANeuralNetworksOperandType operand_type{.type = ANEURALNETWORKS_FLOAT32}; - CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)) - CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, &value, - sizeof(float))) + CHECK_NN(nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)) + CHECK_NN(nnapi->ANeuralNetworksModel_setOperandValue( + nn_model, next_id, &value, sizeof(float))) augmented_inputs.push_back(next_id++); }; @@ -281,8 +254,8 @@ TfLiteStatus AddOpsAndParams( .type = ANEURALNETWORKS_TENSOR_INT32, .dimensionCount = 1, .dimensions = &num_values}; - CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)) - CHECK_NN(ANeuralNetworksModel_setOperandValue( + CHECK_NN(nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)) + CHECK_NN(nnapi->ANeuralNetworksModel_setOperandValue( nn_model, next_id, values, sizeof(int32_t) * num_values)); augmented_inputs.push_back(next_id++); }; @@ -291,15 +264,16 @@ TfLiteStatus AddOpsAndParams( // For each state_out tensor, a corresponding state_in operand needs to be // created for NNAPI. auto duplicate_state_tensor_float32 = - [subgraph, &nn_model, &next_id, &augmented_inputs, &model_state_inputs, - &model_state_outputs](int tensor_id) { + [nnapi, subgraph, &nn_model, &next_id, &augmented_inputs, + &model_state_inputs, &model_state_outputs](int tensor_id) { const TfLiteTensor* tensor = subgraph->tensor(tensor_id); ANeuralNetworksOperandType operand_type{ ANEURALNETWORKS_TENSOR_FLOAT32, static_cast(tensor->dims->size), reinterpret_cast(tensor->dims->data), tensor->params.scale, tensor->params.zero_point}; - CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)); + CHECK_NN( + nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)); augmented_inputs.push_back(next_id); model_state_inputs->push_back(next_id); model_state_outputs->push_back(tensor_id); @@ -388,7 +362,7 @@ TfLiteStatus AddOpsAndParams( }; // LSTM in NNAPI requires scratch tensor as an output operand. - auto add_lstm_scratch_tensor_float32 = [subgraph, &node, &nn_model, + auto add_lstm_scratch_tensor_float32 = [nnapi, subgraph, &node, &nn_model, &next_id, &augmented_outputs]() { if (node.temporaries->size == 0) return; int scratch_buffer_index = node.temporaries->data[0]; @@ -398,7 +372,7 @@ TfLiteStatus AddOpsAndParams( static_cast(tensor->dims->size), reinterpret_cast(tensor->dims->data), tensor->params.scale, tensor->params.zero_point}; - CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)); + CHECK_NN(nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)); augmented_outputs.insert(augmented_outputs.begin(), next_id++); }; @@ -427,15 +401,16 @@ TfLiteStatus AddOpsAndParams( }; // Handle optional input tensors. - auto add_optional_tensors = [&nn_model, &augmented_inputs, + auto add_optional_tensors = [nnapi, &nn_model, &augmented_inputs, &next_id](int nn_type) { for (size_t idx = 0; idx < augmented_inputs.size(); idx++) { if (augmented_inputs[idx] == kOptionalTensor) { const std::vector dim = {0, 0}; ANeuralNetworksOperandType operand_type{nn_type, 2, dim.data(), 0, 0}; - CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)) - CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, - nullptr, 0)) + CHECK_NN( + nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)) + CHECK_NN(nnapi->ANeuralNetworksModel_setOperandValue( + nn_model, next_id, nullptr, 0)) augmented_inputs[idx] = next_id++; } } @@ -695,13 +670,13 @@ TfLiteStatus AddOpsAndParams( break; } - if (nnapi_version == 11 && GetAndroidSdkVersionCached() < 28) { + if (nnapi_version == 11 && nnapi->android_sdk_version < 28) { logError("Op %d needs NNAPI1.1", builtin); return kTfLiteError; } // Add the operation. - RETURN_ERROR_IF_NN_FAILED(ANeuralNetworksModel_addOperation( + RETURN_ERROR_IF_NN_FAILED(nnapi->ANeuralNetworksModel_addOperation( nn_model, nn_op_type, static_cast(augmented_inputs.size()), augmented_inputs.data(), static_cast(augmented_outputs.size()), @@ -713,9 +688,10 @@ TfLiteStatus AddOpsAndParams( TfLiteStatus NNAPIDelegate::BuildGraph(Subgraph* subgraph) { if (nn_model_ && nn_compiled_model_) return model_status_; + const NnApi* nnapi = NnApiImplementation(); // TODO(aselle): This is not correct. need to handle resize invalidation. if (!nn_model_) { - CHECK_NN(ANeuralNetworksModel_create(&nn_model_)); + CHECK_NN(nnapi->ANeuralNetworksModel_create(&nn_model_)); // Find which tensors should be added to NNAPI. TFLite has temporaries // and RNN back-edges which are are not valid for NNAPI. We look through all @@ -762,21 +738,22 @@ TfLiteStatus NNAPIDelegate::BuildGraph(Subgraph* subgraph) { model_states_outputs_.size(), &augmented_outputs, tensor_id_to_nnapi_id); - CHECK_NN(ANeuralNetworksModel_identifyInputsAndOutputs( + CHECK_NN(nnapi->ANeuralNetworksModel_identifyInputsAndOutputs( nn_model_, static_cast(augmented_inputs.size()), reinterpret_cast(augmented_inputs.data()), static_cast(augmented_outputs.size()), reinterpret_cast(augmented_outputs.data()))); - if (GetAndroidSdkVersionCached() >= 28) { - CHECK_NN(ANeuralNetworksModel_relaxComputationFloat32toFloat16( + if (nnapi->android_sdk_version >= 28) { + CHECK_NN(nnapi->ANeuralNetworksModel_relaxComputationFloat32toFloat16( nn_model_, subgraph->GetAllowFp16PrecisionForFp32())); } - CHECK_NN(ANeuralNetworksModel_finish(nn_model_)); + CHECK_NN(nnapi->ANeuralNetworksModel_finish(nn_model_)); } if (!nn_compiled_model_) { - CHECK_NN(ANeuralNetworksCompilation_create(nn_model_, &nn_compiled_model_)); - CHECK_NN(ANeuralNetworksCompilation_finish(nn_compiled_model_)); + CHECK_NN(nnapi->ANeuralNetworksCompilation_create(nn_model_, + &nn_compiled_model_)); + CHECK_NN(nnapi->ANeuralNetworksCompilation_finish(nn_compiled_model_)); } return kTfLiteOk; } @@ -792,8 +769,10 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { return model_status_; } + const NnApi* nnapi = NnApiImplementation(); ANeuralNetworksExecution* execution = nullptr; - CHECK_NN(ANeuralNetworksExecution_create(nn_compiled_model_, &execution)); + CHECK_NN( + nnapi->ANeuralNetworksExecution_create(nn_compiled_model_, &execution)); // Currently perform deep copy of input buffer for (size_t i = 0; i < subgraph->inputs().size(); i++) { @@ -801,7 +780,7 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { // TODO(aselle): Is this what we want or do we want input instead? // TODO(aselle): This should be called setInputValue maybe to be cons. TfLiteTensor* tensor = subgraph->tensor(input); - CHECK_NN(ANeuralNetworksExecution_setInput( + CHECK_NN(nnapi->ANeuralNetworksExecution_setInput( execution, i, nullptr, tensor->data.raw, tensor->bytes)); } @@ -809,7 +788,7 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { for (size_t i = 0; i < subgraph->outputs().size(); i++) { int output = subgraph->outputs()[i]; TfLiteTensor* tensor = subgraph->tensor(output); - CHECK_NN(ANeuralNetworksExecution_setOutput( + CHECK_NN(nnapi->ANeuralNetworksExecution_setOutput( execution, i, nullptr, tensor->data.raw, tensor->bytes)); } @@ -821,21 +800,21 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { // Here we are using a deep copy for state_in tensors so that we are not // reading and writing into the same buffer during a invocation. // TODO(miaowang): using double shared buffer to minimize the copies. - CHECK_NN(ANeuralNetworksExecution_setInput( + CHECK_NN(nnapi->ANeuralNetworksExecution_setInput( execution, i + subgraph->inputs().size(), nullptr, tensor->data.raw, tensor->bytes)); // Tell NNAPI where to output the state_out. - CHECK_NN(ANeuralNetworksExecution_setOutput( + CHECK_NN(nnapi->ANeuralNetworksExecution_setOutput( execution, i + subgraph->outputs().size(), nullptr, tensor->data.raw, tensor->bytes)); } // Currently use blocking compute. ANeuralNetworksEvent* event = nullptr; - CHECK_NN(ANeuralNetworksExecution_startCompute(execution, &event)); - CHECK_NN(ANeuralNetworksEvent_wait(event)); - ANeuralNetworksEvent_free(event); - ANeuralNetworksExecution_free(execution); + CHECK_NN(nnapi->ANeuralNetworksExecution_startCompute(execution, &event)); + CHECK_NN(nnapi->ANeuralNetworksEvent_wait(event)); + nnapi->ANeuralNetworksEvent_free(event); + nnapi->ANeuralNetworksExecution_free(execution); #if 0 printf("From the NN API:\n"); @@ -853,6 +832,8 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { return kTfLiteOk; } -bool NNAPIDelegate::IsSupported() { return NNAPIExists(); } +bool NNAPIDelegate::IsSupported() { + return NnApiImplementation()->nnapi_exists; +} } // namespace tflite -- GitLab From 5b864796352c49a15fa2a443bc54b4d6bfdd6349 Mon Sep 17 00:00:00 2001 From: Andrew Selle Date: Wed, 19 Dec 2018 15:11:29 -0800 Subject: [PATCH 0126/1765] Automated rollback of commit 7b9865971ed38fb3c46aa15c64c6660c50af2d83. Revert #23929. PiperOrigin-RevId: 226240832 --- tensorflow/examples/tutorials/word2vec/word2vec_basic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/examples/tutorials/word2vec/word2vec_basic.py b/tensorflow/examples/tutorials/word2vec/word2vec_basic.py index 77889effc8..b09ee99768 100644 --- a/tensorflow/examples/tutorials/word2vec/word2vec_basic.py +++ b/tensorflow/examples/tutorials/word2vec/word2vec_basic.py @@ -91,7 +91,7 @@ vocabulary_size = 50000 def build_dataset(words, n_words): """Process raw inputs into a dataset.""" - count = [('UNK', -1)] + count = [['UNK', -1]] count.extend(collections.Counter(words).most_common(n_words - 1)) dictionary = dict() for word, _ in count: -- GitLab From 94e331ac5b8ae01efde2d9948ec956e337d9eaf4 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Wed, 19 Dec 2018 15:21:24 -0800 Subject: [PATCH 0127/1765] In case StatusGroup has multiple status messages which all have a common prefix, we return the longest one. This is especially helpful when the status messages are incrementally build by appending to the previous ones during runtime. PiperOrigin-RevId: 226242326 --- tensorflow/core/lib/core/status.cc | 19 +++++++++++++------ tensorflow/core/lib/core/status_test.cc | 25 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/tensorflow/core/lib/core/status.cc b/tensorflow/core/lib/core/status.cc index 7be5b9b513..3076c09337 100644 --- a/tensorflow/core/lib/core/status.cc +++ b/tensorflow/core/lib/core/status.cc @@ -156,19 +156,26 @@ Status StatusGroup::as_status() const { return Status::OK(); } - // If there is only one message, or all of the messages are identical, return - // the original status. This reduces verbosity and preserves existing - // behavior when possible. + // Reduce verbosity when handling duplicate messages. If there is only a + // single message, or all messages have similar content, then return the + // longest status message. + std::vector sorted_children(children_); + std::sort(sorted_children.begin(), sorted_children.end(), + [](const Status& a, const Status& b) { + return a.error_message().length() > b.error_message().length(); + }); bool single_status = true; - for (const Status& s : children_) { - if (s != children_[0]) { + for (const auto& s : sorted_children) { + if (s.code() != sorted_children[0].code() || + sorted_children[0].error_message().find(s.error_message()) == + string::npos) { single_status = false; break; } } if (single_status) { - return children_[0]; + return sorted_children[0]; } std::vector fmt; diff --git a/tensorflow/core/lib/core/status_test.cc b/tensorflow/core/lib/core/status_test.cc index d3296b4fac..7c28184080 100644 --- a/tensorflow/core/lib/core/status_test.cc +++ b/tensorflow/core/lib/core/status_test.cc @@ -141,6 +141,31 @@ TEST(StatusGroup, ContainsChildMessages) { LOG(INFO) << d.as_status(); } +TEST(StatusGroup, ContainsIdenticalMessage) { + StatusGroup sg; + const Status internal(errors::Internal("Original error")); + for (size_t i = 0; i < 10; i++) { + sg.Update(internal); + } + EXPECT_EQ(sg.as_status(), internal); +} + +TEST(StatusGroup, ContainsCommonPrefix) { + StatusGroup sg; + const Status a(errors::Internal("Original error")); + const Status b(errors::Internal("Original error is")); + const Status c(errors::Internal("Original error is invalid")); + sg.Update(a); + sg.Update(c); + sg.Update(c); + sg.Update(b); + sg.Update(c); + sg.Update(b); + sg.Update(a); + sg.Update(b); + EXPECT_EQ(sg.as_status(), c); +} + static void BM_TF_CHECK_OK(int iters) { tensorflow::Status s = (iters < 0) ? errors::InvalidArgument("Invalid") : Status::OK(); -- GitLab From 85ef6de9fcb5977bd738e10264f0641869594b83 Mon Sep 17 00:00:00 2001 From: Sami Kama Date: Wed, 19 Dec 2018 19:52:47 -0800 Subject: [PATCH 0128/1765] Fix clang format --- tensorflow/core/grappler/grappler_item_builder.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tensorflow/core/grappler/grappler_item_builder.cc b/tensorflow/core/grappler/grappler_item_builder.cc index a984efd10d..fc55fb5b3d 100644 --- a/tensorflow/core/grappler/grappler_item_builder.cc +++ b/tensorflow/core/grappler/grappler_item_builder.cc @@ -104,8 +104,9 @@ Status OptimizeGraph(const GraphDef& graph_def_arg, GraphDef* output_graph_def, // Instantiate all variables for function library runtime creation. std::vector> devices; // Only CPU device is used so instead of calling DeviceFactory::AddDevices() - // with dummy session config, which will conflict with user defined options and - // create unwanted devices, call cpu_factory->CreateDevices() to get CPU only devices. + // with dummy session config, which will conflict with user defined options + // and create unwanted devices, call cpu_factory->CreateDevices() to get CPU + // only devices. DeviceFactory* cpu_factory = DeviceFactory::GetFactory("CPU"); TF_RETURN_IF_ERROR(cpu_factory->CreateDevices( options, "/job:localhost/replica:0/task:0", &devices)); -- GitLab From 62070156d9a54c7a810b6bc8383ab190a98c7c64 Mon Sep 17 00:00:00 2001 From: Eugene Zhulenev Date: Wed, 19 Dec 2018 15:36:22 -0800 Subject: [PATCH 0129/1765] Place inlined inputs before placing function body PiperOrigin-RevId: 226244885 --- .../grappler/optimizers/function_optimizer.cc | 21 +++++++++++++++++-- .../optimizers/function_optimizer_test.cc | 5 +++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tensorflow/core/grappler/optimizers/function_optimizer.cc b/tensorflow/core/grappler/optimizers/function_optimizer.cc index 4ec68c7543..73c950b3fc 100644 --- a/tensorflow/core/grappler/optimizers/function_optimizer.cc +++ b/tensorflow/core/grappler/optimizers/function_optimizer.cc @@ -1374,7 +1374,24 @@ Status InlineIndirectFunctionCall(const NodeDef& func_node, const string prefix = strings::StrCat(func_node.name(), "/"); // ------------------------------------------------------------------------ // - // First we need to assign device placements to all function body nodes. + // Before placing the function body nodes we pin input placeholders to the + // same device as their corresponding input nodes. + + for (NodeDef& func_body_node : *item.graph.mutable_node()) { + if (item.IsInputPlaceholder(func_body_node.name())) { + const int input_idx = input_placeholders_idx[func_body_node.name()]; + const GraphView::OutputPort output_port = + ctx->graph_view().GetRegularFanin({&func_node, input_idx}); + + VLOG(3) << "Pin inlined function input node '" << func_body_node.name() + << "' to the '" << output_port.node->device() << "' device."; + func_body_node.set_device(output_port.node->device()); + } + } + + // ------------------------------------------------------------------------ // + // After placing nodes corresponding to the function inputs, we need to assign + // device placements to all other function body nodes. GraphDef placed_graph_def; @@ -1432,7 +1449,7 @@ Status InlineIndirectFunctionCall(const NodeDef& func_node, (*func_body_node.mutable_attr())["T"] = func_body_node.attr().at("dtype"); func_body_node.mutable_attr()->erase("dtype"); func_body_node.mutable_attr()->erase("shape"); - int input_idx = input_placeholders_idx[func_body_node.name()]; + const int input_idx = input_placeholders_idx[func_body_node.name()]; func_body_node.add_input(strings::StrCat(inputs[input_idx].ToString())); // All side effects must happen before inputs can start executing. diff --git a/tensorflow/core/grappler/optimizers/function_optimizer_test.cc b/tensorflow/core/grappler/optimizers/function_optimizer_test.cc index c971eec3f4..79da7dfa2d 100644 --- a/tensorflow/core/grappler/optimizers/function_optimizer_test.cc +++ b/tensorflow/core/grappler/optimizers/function_optimizer_test.cc @@ -924,8 +924,9 @@ TEST_F(FunctionOptimizerTest, InlineIndirectFunctionWithDevicePlacement) { {NDef("a", "Placeholder", {}, {{"dtype", DT_FLOAT}}, cpu0), NDef("b", "Placeholder", {}, {{"dtype", DT_FLOAT}}, cpu1), - // Function must be inlined and `mul` node placed on a requested device. - NDef("c/x", "Identity", {"a:0"}, {{"T", DT_FLOAT}}, cpu1), + // Function must be inlined and `mul` node placed on a requested device, + // and input `Identity` nodes must be colocated with their source nodes. + NDef("c/x", "Identity", {"a:0"}, {{"T", DT_FLOAT}}, cpu0), NDef("c/y", "Identity", {"b:0"}, {{"T", DT_FLOAT}}, cpu1), NDef("c/mul", "Mul", {"c/x", "c/y"}, {{"T", DT_FLOAT}}, cpu1), -- GitLab From 286e5e5d59f9b1dd1565f464348e044b704d3ac9 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Wed, 19 Dec 2018 15:39:44 -0800 Subject: [PATCH 0130/1765] [XLA:GPU] Don't segfault if infeeding data of the wrong shape. Instead, return a helpful error. PiperOrigin-RevId: 226245605 --- .../compiler/xla/service/gpu/infeed_thunk.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tensorflow/compiler/xla/service/gpu/infeed_thunk.cc b/tensorflow/compiler/xla/service/gpu/infeed_thunk.cc index 8c3a026740..8a96b5fabc 100644 --- a/tensorflow/compiler/xla/service/gpu/infeed_thunk.cc +++ b/tensorflow/compiler/xla/service/gpu/infeed_thunk.cc @@ -36,6 +36,21 @@ Status InfeedThunk::ExecuteOnStream(const BufferAllocations& buffer_allocations, ShapeTree infeed_buffers = GetOrCreateInfeedManager()->BlockingGetNextDestination(); + // infeed_slices_'s shape should be a tuple of shape (buffers, token). + const auto& infeed_shape = infeed_slices_.shape(); + TF_RET_CHECK(ShapeUtil::IsTuple(infeed_shape)) + << ShapeUtil::HumanStringWithLayout(infeed_shape); + TF_RET_CHECK(infeed_shape.tuple_shapes().size() == 2) + << ShapeUtil::HumanStringWithLayout(infeed_shape); + TF_RET_CHECK(ShapeUtil::IsToken(infeed_shape.tuple_shapes(1))) + << ShapeUtil::HumanStringWithLayout(infeed_shape); + TF_RET_CHECK( + ShapeUtil::Equal(infeed_buffers.shape(), infeed_shape.tuple_shapes(0))) + << "Expected infeed of shape " + << ShapeUtil::HumanStringWithLayout(infeed_shape.tuple_shapes(0)) + << " but was " + << ShapeUtil::HumanStringWithLayout(infeed_buffers.shape()); + { // The infeed buffer has an extra outer tuple with a token. Adjust the index // accordingly. -- GitLab From 632a5d9d405ff41c7701055792446d72d42eea1a Mon Sep 17 00:00:00 2001 From: Peter Hawkins Date: Wed, 19 Dec 2018 15:53:36 -0800 Subject: [PATCH 0131/1765] [XLA] Make TriangularSolve ignore the elements not in the triangle of its triangular input. PiperOrigin-RevId: 226247755 --- tensorflow/compiler/xla/client/lib/BUILD | 1 + tensorflow/compiler/xla/client/lib/matrix.cc | 21 ++--- tensorflow/compiler/xla/client/lib/matrix.h | 4 + .../xla/client/lib/triangular_solve.cc | 5 + .../xla/client/lib/triangular_solve_test.cc | 92 +++++++++++++++++-- 5 files changed, 104 insertions(+), 19 deletions(-) diff --git a/tensorflow/compiler/xla/client/lib/BUILD b/tensorflow/compiler/xla/client/lib/BUILD index 826b13fe37..6192b89b4a 100644 --- a/tensorflow/compiler/xla/client/lib/BUILD +++ b/tensorflow/compiler/xla/client/lib/BUILD @@ -412,6 +412,7 @@ xla_test( srcs = ["triangular_solve_test.cc"], tags = ["noasan"], # sometimes times out, http://b/78650012 deps = [ + ":math", ":matrix", ":triangular_solve", "//tensorflow/compiler/xla:array2d", diff --git a/tensorflow/compiler/xla/client/lib/matrix.cc b/tensorflow/compiler/xla/client/lib/matrix.cc index ffd744d190..16c177b4e2 100644 --- a/tensorflow/compiler/xla/client/lib/matrix.cc +++ b/tensorflow/compiler/xla/client/lib/matrix.cc @@ -64,7 +64,7 @@ XlaOp GetMatrixDiagonal(XlaOp x) { }); } -XlaOp Triangle(XlaOp x, bool lower) { +XlaOp TriangleMask(XlaOp x, int diagonal) { XlaBuilder* builder = x.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); @@ -74,20 +74,19 @@ XlaOp Triangle(XlaOp x, bool lower) { const int64 n = shape.dimensions(n_dims - 1); absl::Span major_dims = AsInt64Slice(shape.dimensions()).subspan(/*pos=*/0, /*len=*/n_dims - 2); - auto a = Iota(builder, U32, n); - auto b = Iota(builder, U32, m); + auto a = Iota(builder, S32, n); + auto b = Iota(builder, S32, m) + ConstantR0(builder, diagonal); XlaOp indicator; - if (lower) { - indicator = Ge(b, Broadcast(a, {m}), /*broadcast_dimensions=*/{0}); - } else { - indicator = Le(b, Broadcast(a, {m}), /*broadcast_dimensions=*/{0}); - } - auto mask = Broadcast(indicator, major_dims); - - return Select(mask, x, Zeros(builder, shape)); + indicator = Ge(b, Broadcast(a, {m}), /*broadcast_dimensions=*/{0}); + return Broadcast(indicator, major_dims); }); } +XlaOp Triangle(XlaOp x, bool lower) { + return lower ? Select(TriangleMask(x, 0), x, ZerosLike(x)) + : Select(TriangleMask(x, -1), ZerosLike(x), x); +} + XlaOp UpperTriangle(XlaOp x) { return Triangle(x, false); } XlaOp LowerTriangle(XlaOp x) { return Triangle(x, true); } diff --git a/tensorflow/compiler/xla/client/lib/matrix.h b/tensorflow/compiler/xla/client/lib/matrix.h index 8856f99c7a..916cd83748 100644 --- a/tensorflow/compiler/xla/client/lib/matrix.h +++ b/tensorflow/compiler/xla/client/lib/matrix.h @@ -31,6 +31,10 @@ XlaOp IdentityMatrix(XlaBuilder* builder, PrimitiveType type, int64 m, int64 n); // diagonal elements (i.e., with indices [..., i, i]). XlaOp GetMatrixDiagonal(XlaOp x); +// Returns a lower-triangular mask, i.e., true below the `diagonal`-th diagonal +// and false above that diagonal. +XlaOp TriangleMask(XlaOp x, int diagonal); + // Get the upper or lower triangle part of the last two dimensions XlaOp Triangle(XlaOp x, bool lower); diff --git a/tensorflow/compiler/xla/client/lib/triangular_solve.cc b/tensorflow/compiler/xla/client/lib/triangular_solve.cc index 159e0c82dc..4bc2f3d121 100644 --- a/tensorflow/compiler/xla/client/lib/triangular_solve.cc +++ b/tensorflow/compiler/xla/client/lib/triangular_solve.cc @@ -417,6 +417,11 @@ XlaOp TriangularSolve(XlaOp a, XlaOp b, bool left_side, bool lower, auto inv_diag_blocks = InvertDiagonalBlocks(diag_blocks, lower, transpose_a, conjugate_a, precision); + // Mask off the ignored elements of the triangular matrix a. + // TODO(phawkins): it would probably be preferable to perform this masking + // block by block inside SolveWithInvertedDiagonalBlocks. + a = Triangle(a, lower); + // We now find the solution using GEMMs auto x = SolveWithInvertedDiagonalBlocks(a, b, inv_diag_blocks, left_side, lower, diff --git a/tensorflow/compiler/xla/client/lib/triangular_solve_test.cc b/tensorflow/compiler/xla/client/lib/triangular_solve_test.cc index 3fea627e6a..703227c949 100644 --- a/tensorflow/compiler/xla/client/lib/triangular_solve_test.cc +++ b/tensorflow/compiler/xla/client/lib/triangular_solve_test.cc @@ -20,6 +20,7 @@ limitations under the License. #include #include "tensorflow/compiler/xla/array2d.h" +#include "tensorflow/compiler/xla/client/lib/math.h" #include "tensorflow/compiler/xla/client/lib/matrix.h" #include "tensorflow/compiler/xla/client/xla_builder.h" #include "tensorflow/compiler/xla/literal.h" @@ -37,12 +38,20 @@ namespace { using TriangularSolveTest = ClientLibraryTestBase; using TriangularSolveLeftLookingTest = ClientLibraryTestBase; +static constexpr float kNan = std::numeric_limits::quiet_NaN(); + Array2D AValsLower() { - return {{2, 0, 0, 0}, {3, 6, 0, 0}, {4, 7, 9, 0}, {5, 8, 10, 11}}; + return {{2, kNan, kNan, kNan}, + {3, 6, kNan, kNan}, + {4, 7, 9, kNan}, + {5, 8, 10, 11}}; } Array2D AValsUpper() { - return {{2, 3, 4, 5}, {0, 6, 7, 8}, {0, 0, 9, 10}, {0, 0, 0, 11}}; + return {{2, 3, 4, 5}, + {kNan, 6, 7, 8}, + {kNan, kNan, 9, 10}, + {kNan, kNan, kNan, 11}}; } Array2D BValsRight() { @@ -53,18 +62,20 @@ Array2D BValsLeft() { return {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}; } +static constexpr complex64 kNanC64 = complex64(kNan, kNan); + Array2D AValsLowerComplex() { - return {{2, 0, 0, 0}, - {complex64(3, 1), 6, 0, 0}, - {4, complex64(7, 2), 9, 0}, + return {{2, kNanC64, kNanC64, kNanC64}, + {complex64(3, 1), 6, kNanC64, kNanC64}, + {4, complex64(7, 2), 9, kNanC64}, {5, 8, complex64(10, 3), 11}}; } Array2D AValsUpperComplex() { return {{2, 3, complex64(4, 3), 5}, - {0, 6, complex64(7, 2), 8}, - {0, 0, complex64(9, 1), 10}, - {0, 0, 0, 11}}; + {kNanC64, 6, complex64(7, 2), 8}, + {kNanC64, kNanC64, complex64(9, 1), 10}, + {kNanC64, kNanC64, kNanC64, 11}}; } Array2D BValsRightComplex() { @@ -367,5 +378,70 @@ XLA_TEST_F(TriangularSolveTest, BatchedLeftUpper) { ErrorSpec(1e-2, 1e-2)); } +struct TriangularSolveTestSpec { + int m, n; // A is mxm, B is mxn + bool left_side; + bool lower; + bool transpose_a; +}; + +class TriangularSolveParametricTest + : public ClientLibraryTestBase, + public ::testing::WithParamInterface {}; + +XLA_TEST_P(TriangularSolveParametricTest, Random) { + TriangularSolveTestSpec spec = GetParam(); + + XlaBuilder builder(TestName()); + + Array2D avals(spec.m, spec.m); + avals.FillRandom(1.0); + for (int i = 0; i < spec.m; ++i) { + avals(i, i) += 10; + } + + std::pair bdims = spec.left_side ? std::make_pair(spec.m, spec.n) + : std::make_pair(spec.n, spec.m); + Array2D bvals(bdims.first, bdims.second); + bvals.FillRandom(1.0); + + XlaOp a, b; + auto a_data = CreateR2Parameter(avals, 0, "a", &builder, &a); + auto b_data = CreateR2Parameter(bvals, 1, "b", &builder, &b); + auto x = TriangularSolve(a, b, spec.left_side, spec.lower, spec.transpose_a, + /*conjugate_a=*/false, + /*block_size=*/3); + auto a_tri = Triangle(a, spec.lower); + a_tri = MaybeTransposeInMinorDims(a_tri, spec.transpose_a); + if (spec.left_side) { + BatchDot(a_tri, x); + } else { + BatchDot(x, a_tri); + } + + ComputeAndCompareR2(&builder, bvals, {a_data.get(), b_data.get()}, + ErrorSpec(1e-2, 1e-2)); +} + +std::vector TriangularSolveTests() { + std::vector specs; + for (int m : {5, 10}) { + for (int n : {5, 10}) { + for (bool left_side : {false, true}) { + for (bool lower : {false, true}) { + for (bool transpose_a : {false, true}) { + specs.push_back({m, n, left_side, lower, transpose_a}); + } + } + } + } + } + return specs; +} + +INSTANTIATE_TEST_CASE_P(TriangularSolveParametricTestInstantiation, + TriangularSolveParametricTest, + ::testing::ValuesIn(TriangularSolveTests())); + } // namespace } // namespace xla -- GitLab From 33096914a7e1afa84007451faa25ad66ab78f15d Mon Sep 17 00:00:00 2001 From: Yunlu Li Date: Wed, 19 Dec 2018 16:00:11 -0800 Subject: [PATCH 0132/1765] Make tflite_driver able to run single op model with reference kernels. PiperOrigin-RevId: 226248707 --- tensorflow/lite/kernels/BUILD | 15 + tensorflow/lite/kernels/register_ref.cc | 297 ++++++++++++++++++ tensorflow/lite/kernels/register_ref.h | 39 +++ tensorflow/lite/testing/BUILD | 1 + tensorflow/lite/testing/tflite_driver.cc | 14 +- tensorflow/lite/testing/tflite_driver.h | 6 +- tensorflow/lite/testing/tflite_driver_test.cc | 34 ++ 7 files changed, 402 insertions(+), 4 deletions(-) create mode 100644 tensorflow/lite/kernels/register_ref.cc create mode 100644 tensorflow/lite/kernels/register_ref.h diff --git a/tensorflow/lite/kernels/BUILD b/tensorflow/lite/kernels/BUILD index bad1c4aebf..5cc06c7a63 100644 --- a/tensorflow/lite/kernels/BUILD +++ b/tensorflow/lite/kernels/BUILD @@ -285,6 +285,21 @@ cc_library( ], ) +# The builtin_ops target will resolve to optimized kernels when available. This +# target uses reference kernels only, and is useful for validation and testing. +# It should *not* generally be used in production. +cc_library( + name = "reference_ops", + srcs = ["register_ref.cc"], + hdrs = ["register_ref.h"], + deps = [ + ":builtin_op_kernels", + "//tensorflow/lite:framework", + "//tensorflow/lite:util", + "//tensorflow/lite/c:c_api_internal", + ], +) + tf_cc_test( name = "audio_spectrogram_test", size = "small", diff --git a/tensorflow/lite/kernels/register_ref.cc b/tensorflow/lite/kernels/register_ref.cc new file mode 100644 index 0000000000..584e044b98 --- /dev/null +++ b/tensorflow/lite/kernels/register_ref.cc @@ -0,0 +1,297 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/lite/kernels/register_ref.h" +#include "tensorflow/lite/util.h" + +namespace tflite { +namespace ops { + +namespace custom { + +TfLiteRegistration* Register_AUDIO_SPECTROGRAM(); +TfLiteRegistration* Register_LAYER_NORM_LSTM(); +TfLiteRegistration* Register_MFCC(); +TfLiteRegistration* Register_DETECTION_POSTPROCESS(); +TfLiteRegistration* Register_RELU_1(); + +} // namespace custom + +namespace builtin { + +// TODO(yunluli): Some of the registries, e.g. Tanh(), could only invoke +// optimized kernels. Add a _REF() variant for them. +TfLiteRegistration* Register_ABS(); +TfLiteRegistration* Register_RELU(); +TfLiteRegistration* Register_RELU_N1_TO_1(); +TfLiteRegistration* Register_RELU6(); +TfLiteRegistration* Register_TANH(); +TfLiteRegistration* Register_LOGISTIC(); +TfLiteRegistration* Register_AVERAGE_POOL_REF(); +TfLiteRegistration* Register_MAX_POOL_REF(); +TfLiteRegistration* Register_L2_POOL_REF(); +TfLiteRegistration* Register_CONVOLUTION_REF(); +TfLiteRegistration* Register_DEPTHWISE_CONVOLUTION_REF(); +TfLiteRegistration* Register_SVDF(); +TfLiteRegistration* Register_RNN(); +TfLiteRegistration* Register_BIDIRECTIONAL_SEQUENCE_RNN(); +TfLiteRegistration* Register_UNIDIRECTIONAL_SEQUENCE_RNN(); +TfLiteRegistration* Register_EMBEDDING_LOOKUP(); +TfLiteRegistration* Register_EMBEDDING_LOOKUP_SPARSE(); +TfLiteRegistration* Register_FULLY_CONNECTED_REF(); +TfLiteRegistration* Register_LSH_PROJECTION(); +TfLiteRegistration* Register_HASHTABLE_LOOKUP(); +TfLiteRegistration* Register_SOFTMAX(); +TfLiteRegistration* Register_CONCATENATION_REF(); +TfLiteRegistration* Register_ADD_REF(); +TfLiteRegistration* Register_SPACE_TO_BATCH_ND_REF(); +TfLiteRegistration* Register_DIV_REF(); +TfLiteRegistration* Register_SUB_REF(); +TfLiteRegistration* Register_BATCH_TO_SPACE_ND_REF(); +TfLiteRegistration* Register_MUL_REF(); +TfLiteRegistration* Register_L2NORM_REF(); +TfLiteRegistration* Register_LOCAL_RESPONSE_NORM_REF(); +TfLiteRegistration* Register_LSTM(); +TfLiteRegistration* Register_BIDIRECTIONAL_SEQUENCE_LSTM(); +TfLiteRegistration* Register_UNIDIRECTIONAL_SEQUENCE_LSTM(); +TfLiteRegistration* Register_PAD_REF(); +TfLiteRegistration* Register_PADV2_REF(); +TfLiteRegistration* Register_RESHAPE(); +TfLiteRegistration* Register_RESIZE_BILINEAR_REF(); +TfLiteRegistration* Register_RESIZE_NEAREST_NEIGHBOR_REF(); +TfLiteRegistration* Register_SKIP_GRAM(); +TfLiteRegistration* Register_SPACE_TO_DEPTH_REF(); +TfLiteRegistration* Register_GATHER(); +TfLiteRegistration* Register_TRANSPOSE_REF(); +TfLiteRegistration* Register_MEAN_REF(); +TfLiteRegistration* Register_SPLIT(); +TfLiteRegistration* Register_SPLIT_V(); +TfLiteRegistration* Register_SQUEEZE(); +TfLiteRegistration* Register_STRIDED_SLICE_REF(); +TfLiteRegistration* Register_EXP(); +TfLiteRegistration* Register_TOPK_V2(); +TfLiteRegistration* Register_LOG(); +TfLiteRegistration* Register_LOG_SOFTMAX(); +TfLiteRegistration* Register_CAST(); +TfLiteRegistration* Register_DEQUANTIZE(); +TfLiteRegistration* Register_PRELU(); +TfLiteRegistration* Register_MAXIMUM(); +TfLiteRegistration* Register_MINIMUM(); +TfLiteRegistration* Register_ARG_MAX(); +TfLiteRegistration* Register_ARG_MIN(); +TfLiteRegistration* Register_GREATER(); +TfLiteRegistration* Register_GREATER_EQUAL(); +TfLiteRegistration* Register_LESS(); +TfLiteRegistration* Register_LESS_EQUAL(); +TfLiteRegistration* Register_FLOOR(); +TfLiteRegistration* Register_TILE(); +TfLiteRegistration* Register_NEG(); +TfLiteRegistration* Register_SUM(); +TfLiteRegistration* Register_REDUCE_PROD(); +TfLiteRegistration* Register_REDUCE_MAX(); +TfLiteRegistration* Register_REDUCE_MIN(); +TfLiteRegistration* Register_REDUCE_ANY(); +TfLiteRegistration* Register_SELECT(); +TfLiteRegistration* Register_SLICE(); +TfLiteRegistration* Register_SIN(); +TfLiteRegistration* Register_TRANSPOSECONV_REF(); +TfLiteRegistration* Register_EXPAND_DIMS(); +TfLiteRegistration* Register_SPARSE_TO_DENSE(); +TfLiteRegistration* Register_EQUAL(); +TfLiteRegistration* Register_NOT_EQUAL(); +TfLiteRegistration* Register_SQRT(); +TfLiteRegistration* Register_RSQRT(); +TfLiteRegistration* Register_SHAPE(); +TfLiteRegistration* Register_POW(); +TfLiteRegistration* Register_FAKE_QUANT(); +TfLiteRegistration* Register_PACK(); +TfLiteRegistration* Register_ONE_HOT(); +TfLiteRegistration* Register_LOGICAL_OR(); +TfLiteRegistration* Register_LOGICAL_AND(); +TfLiteRegistration* Register_LOGICAL_NOT(); +TfLiteRegistration* Register_UNPACK(); +TfLiteRegistration* Register_FLOOR_DIV(); +TfLiteRegistration* Register_SQUARE(); +TfLiteRegistration* Register_ZEROS_LIKE(); +TfLiteRegistration* Register_FLOOR_MOD(); +TfLiteRegistration* Register_RANGE(); +TfLiteRegistration* Register_LEAKY_RELU(); +TfLiteRegistration* Register_SQUARED_DIFFERENCE(); +TfLiteRegistration* Register_FILL(); +TfLiteRegistration* Register_MIRROR_PAD(); + +namespace { + +TfLiteStatus UnsupportedTensorFlowOp(TfLiteContext* context, TfLiteNode* node) { + context->ReportError( + context, + "Regular TensorFlow ops are not supported by this interpreter. Make sure " + "you invoke the Flex delegate before inference."); + return kTfLiteError; +} + +} // namespace + +const TfLiteRegistration* BuiltinRefOpResolver::FindOp( + tflite::BuiltinOperator op, int version) const { + return MutableOpResolver::FindOp(op, version); +} + +const TfLiteRegistration* BuiltinRefOpResolver::FindOp(const char* op, + int version) const { + // Return the NULL Op for all ops whose name start with "Flex", allowing + // the interpreter to delegate their execution. + if (IsFlexOp(op)) { + static TfLiteRegistration null_op{ + nullptr, nullptr, &UnsupportedTensorFlowOp, + nullptr, nullptr, BuiltinOperator_CUSTOM, + "Flex", 1}; + return &null_op; + } + return MutableOpResolver::FindOp(op, version); +} + +BuiltinRefOpResolver::BuiltinRefOpResolver() { + AddBuiltin(BuiltinOperator_ABS, Register_ABS()); + AddBuiltin(BuiltinOperator_RELU, Register_RELU()); + AddBuiltin(BuiltinOperator_RELU_N1_TO_1, Register_RELU_N1_TO_1()); + AddBuiltin(BuiltinOperator_RELU6, Register_RELU6()); + AddBuiltin(BuiltinOperator_TANH, Register_TANH()); + AddBuiltin(BuiltinOperator_LOGISTIC, Register_LOGISTIC()); + AddBuiltin(BuiltinOperator_AVERAGE_POOL_2D, Register_AVERAGE_POOL_REF()); + AddBuiltin(BuiltinOperator_MAX_POOL_2D, Register_MAX_POOL_REF()); + AddBuiltin(BuiltinOperator_L2_POOL_2D, Register_L2_POOL_REF()); + AddBuiltin(BuiltinOperator_CONV_2D, Register_CONVOLUTION_REF()); + AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, + Register_DEPTHWISE_CONVOLUTION_REF(), + /* min_version */ 1, + /* max_version */ 2); + AddBuiltin(BuiltinOperator_SVDF, Register_SVDF()); + AddBuiltin(BuiltinOperator_RNN, Register_RNN()); + AddBuiltin(BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN, + Register_BIDIRECTIONAL_SEQUENCE_RNN()); + AddBuiltin(BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN, + Register_UNIDIRECTIONAL_SEQUENCE_RNN()); + AddBuiltin(BuiltinOperator_EMBEDDING_LOOKUP, Register_EMBEDDING_LOOKUP()); + AddBuiltin(BuiltinOperator_EMBEDDING_LOOKUP_SPARSE, + Register_EMBEDDING_LOOKUP_SPARSE()); + AddBuiltin(BuiltinOperator_FULLY_CONNECTED, Register_FULLY_CONNECTED_REF(), + /* min_version */ 1, + /* max_version */ 2); + AddBuiltin(BuiltinOperator_LSH_PROJECTION, Register_LSH_PROJECTION()); + AddBuiltin(BuiltinOperator_HASHTABLE_LOOKUP, Register_HASHTABLE_LOOKUP()); + AddBuiltin(BuiltinOperator_SOFTMAX, Register_SOFTMAX()); + AddBuiltin(BuiltinOperator_CONCATENATION, Register_CONCATENATION_REF()); + AddBuiltin(BuiltinOperator_ADD, Register_ADD_REF()); + AddBuiltin(BuiltinOperator_SPACE_TO_BATCH_ND, + Register_SPACE_TO_BATCH_ND_REF()); + AddBuiltin(BuiltinOperator_BATCH_TO_SPACE_ND, + Register_BATCH_TO_SPACE_ND_REF()); + AddBuiltin(BuiltinOperator_MUL, Register_MUL_REF()); + AddBuiltin(BuiltinOperator_L2_NORMALIZATION, Register_L2NORM_REF()); + AddBuiltin(BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION, + Register_LOCAL_RESPONSE_NORM_REF()); + AddBuiltin(BuiltinOperator_LSTM, Register_LSTM(), /* min_version */ 1, + /* max_version */ 2); + AddBuiltin(BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM, + Register_BIDIRECTIONAL_SEQUENCE_LSTM(), /* min_version */ 1, + /* max_version */ 2); + AddBuiltin(BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_LSTM, + Register_UNIDIRECTIONAL_SEQUENCE_LSTM()); + AddBuiltin(BuiltinOperator_PAD, Register_PAD_REF()); + AddBuiltin(BuiltinOperator_PADV2, Register_PADV2_REF()); + AddBuiltin(BuiltinOperator_RESHAPE, Register_RESHAPE()); + AddBuiltin(BuiltinOperator_RESIZE_BILINEAR, Register_RESIZE_BILINEAR_REF()); + AddBuiltin(BuiltinOperator_RESIZE_NEAREST_NEIGHBOR, + Register_RESIZE_NEAREST_NEIGHBOR_REF()); + AddBuiltin(BuiltinOperator_SKIP_GRAM, Register_SKIP_GRAM()); + AddBuiltin(BuiltinOperator_SPACE_TO_DEPTH, Register_SPACE_TO_DEPTH_REF()); + AddBuiltin(BuiltinOperator_GATHER, Register_GATHER()); + AddBuiltin(BuiltinOperator_TRANSPOSE, Register_TRANSPOSE_REF()); + AddBuiltin(BuiltinOperator_MEAN, Register_MEAN_REF()); + AddBuiltin(BuiltinOperator_DIV, Register_DIV_REF()); + AddBuiltin(BuiltinOperator_SUB, Register_SUB_REF()); + AddBuiltin(BuiltinOperator_SPLIT, Register_SPLIT()); + AddBuiltin(BuiltinOperator_SPLIT_V, Register_SPLIT_V()); + AddBuiltin(BuiltinOperator_SQUEEZE, Register_SQUEEZE()); + AddBuiltin(BuiltinOperator_STRIDED_SLICE, Register_STRIDED_SLICE_REF()); + AddBuiltin(BuiltinOperator_EXP, Register_EXP()); + AddBuiltin(BuiltinOperator_TOPK_V2, Register_TOPK_V2()); + AddBuiltin(BuiltinOperator_LOG, Register_LOG()); + AddBuiltin(BuiltinOperator_LOG_SOFTMAX, Register_LOG_SOFTMAX()); + AddBuiltin(BuiltinOperator_CAST, Register_CAST()); + AddBuiltin(BuiltinOperator_DEQUANTIZE, Register_DEQUANTIZE(), + /* min_version */ 1, + /* max_version */ 2); + AddBuiltin(BuiltinOperator_PRELU, Register_PRELU()); + AddBuiltin(BuiltinOperator_MAXIMUM, Register_MAXIMUM()); + AddBuiltin(BuiltinOperator_MINIMUM, Register_MINIMUM()); + AddBuiltin(BuiltinOperator_ARG_MAX, Register_ARG_MAX()); + AddBuiltin(BuiltinOperator_ARG_MIN, Register_ARG_MIN()); + AddBuiltin(BuiltinOperator_GREATER, Register_GREATER()); + AddBuiltin(BuiltinOperator_GREATER_EQUAL, Register_GREATER_EQUAL()); + AddBuiltin(BuiltinOperator_LESS, Register_LESS()); + AddBuiltin(BuiltinOperator_LESS_EQUAL, Register_LESS_EQUAL()); + AddBuiltin(BuiltinOperator_FLOOR, Register_FLOOR()); + AddBuiltin(BuiltinOperator_NEG, Register_NEG()); + AddBuiltin(BuiltinOperator_SELECT, Register_SELECT()); + AddBuiltin(BuiltinOperator_SLICE, Register_SLICE()); + AddBuiltin(BuiltinOperator_SIN, Register_SIN()); + AddBuiltin(BuiltinOperator_TRANSPOSE_CONV, Register_TRANSPOSECONV_REF()); + AddBuiltin(BuiltinOperator_TILE, Register_TILE()); + AddBuiltin(BuiltinOperator_SUM, Register_SUM()); + AddBuiltin(BuiltinOperator_REDUCE_PROD, Register_REDUCE_PROD()); + AddBuiltin(BuiltinOperator_REDUCE_MAX, Register_REDUCE_MAX()); + AddBuiltin(BuiltinOperator_REDUCE_MIN, Register_REDUCE_MIN()); + AddBuiltin(BuiltinOperator_REDUCE_ANY, Register_REDUCE_ANY()); + AddBuiltin(BuiltinOperator_EXPAND_DIMS, Register_EXPAND_DIMS()); + AddBuiltin(BuiltinOperator_SPARSE_TO_DENSE, Register_SPARSE_TO_DENSE()); + AddBuiltin(BuiltinOperator_EQUAL, Register_EQUAL()); + AddBuiltin(BuiltinOperator_NOT_EQUAL, Register_NOT_EQUAL()); + AddBuiltin(BuiltinOperator_SQRT, Register_SQRT()); + AddBuiltin(BuiltinOperator_RSQRT, Register_RSQRT()); + AddBuiltin(BuiltinOperator_SHAPE, Register_SHAPE()); + AddBuiltin(BuiltinOperator_POW, Register_POW()); + AddBuiltin(BuiltinOperator_FAKE_QUANT, Register_FAKE_QUANT(), 1, 2); + AddBuiltin(BuiltinOperator_PACK, Register_PACK()); + AddBuiltin(BuiltinOperator_ONE_HOT, Register_ONE_HOT()); + AddBuiltin(BuiltinOperator_LOGICAL_OR, Register_LOGICAL_OR()); + AddBuiltin(BuiltinOperator_LOGICAL_AND, Register_LOGICAL_AND()); + AddBuiltin(BuiltinOperator_LOGICAL_NOT, Register_LOGICAL_NOT()); + AddBuiltin(BuiltinOperator_UNPACK, Register_UNPACK()); + AddBuiltin(BuiltinOperator_FLOOR_DIV, Register_FLOOR_DIV()); + AddBuiltin(BuiltinOperator_SQUARE, Register_SQUARE()); + AddBuiltin(BuiltinOperator_ZEROS_LIKE, Register_ZEROS_LIKE()); + AddBuiltin(BuiltinOperator_FLOOR_MOD, Register_FLOOR_MOD()); + AddBuiltin(BuiltinOperator_RANGE, Register_RANGE()); + AddBuiltin(BuiltinOperator_LEAKY_RELU, Register_LEAKY_RELU()); + AddBuiltin(BuiltinOperator_SQUARED_DIFFERENCE, Register_SQUARED_DIFFERENCE()); + AddBuiltin(BuiltinOperator_FILL, Register_FILL()); + AddBuiltin(BuiltinOperator_MIRROR_PAD, Register_MIRROR_PAD()); + + // TODO(andrewharp, ahentz): Move these somewhere more appropriate so that + // custom ops aren't always included by default. + AddCustom("Mfcc", tflite::ops::custom::Register_MFCC()); + AddCustom("AudioSpectrogram", + tflite::ops::custom::Register_AUDIO_SPECTROGRAM()); + AddCustom("LayerNormLstm", tflite::ops::custom::Register_LAYER_NORM_LSTM()); + AddCustom("Relu1", tflite::ops::custom::Register_RELU_1()); + AddCustom("TFLite_Detection_PostProcess", + tflite::ops::custom::Register_DETECTION_POSTPROCESS()); +} + +} // namespace builtin +} // namespace ops +} // namespace tflite diff --git a/tensorflow/lite/kernels/register_ref.h b/tensorflow/lite/kernels/register_ref.h new file mode 100644 index 0000000000..c66d4a25bc --- /dev/null +++ b/tensorflow/lite/kernels/register_ref.h @@ -0,0 +1,39 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_REGISTER_REF_H_ +#define TENSORFLOW_LITE_KERNELS_REGISTER_REF_H_ + +#include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/model.h" +#include "tensorflow/lite/mutable_op_resolver.h" + +namespace tflite { +namespace ops { +namespace builtin { + +class BuiltinRefOpResolver : public MutableOpResolver { + public: + BuiltinRefOpResolver(); + + const TfLiteRegistration* FindOp(tflite::BuiltinOperator op, + int version) const override; + const TfLiteRegistration* FindOp(const char* op, int version) const override; +}; + +} // namespace builtin +} // namespace ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_REGISTER_REF_H_ diff --git a/tensorflow/lite/testing/BUILD b/tensorflow/lite/testing/BUILD index 22ffed43cc..fa25cfaa69 100644 --- a/tensorflow/lite/testing/BUILD +++ b/tensorflow/lite/testing/BUILD @@ -165,6 +165,7 @@ cc_library( "//tensorflow/lite:string_util", "//tensorflow/lite/delegates/flex:delegate", "//tensorflow/lite/kernels:builtin_ops", + "//tensorflow/lite/kernels:reference_ops", "@com_google_absl//absl/strings", ], ) diff --git a/tensorflow/lite/testing/tflite_driver.cc b/tensorflow/lite/testing/tflite_driver.cc index 4e11d49f25..ffe296432a 100644 --- a/tensorflow/lite/testing/tflite_driver.cc +++ b/tensorflow/lite/testing/tflite_driver.cc @@ -19,6 +19,8 @@ limitations under the License. #include "absl/strings/escaping.h" #include "tensorflow/lite/builtin_op_data.h" #include "tensorflow/lite/delegates/flex/delegate.h" +#include "tensorflow/lite/kernels/register.h" +#include "tensorflow/lite/kernels/register_ref.h" #include "tensorflow/lite/string_util.h" #include "tensorflow/lite/testing/split.h" @@ -188,8 +190,15 @@ class TfLiteDriver::Expectation { size_t num_elements_; }; -TfLiteDriver::TfLiteDriver(bool use_nnapi, const string& delegate_name) +TfLiteDriver::TfLiteDriver(bool use_nnapi, const string& delegate_name, + bool reference_kernel) : use_nnapi_(use_nnapi) { + if (reference_kernel) { + resolver_.reset(new ops::builtin::BuiltinRefOpResolver); + } else { + resolver_.reset(new ops::builtin::BuiltinOpResolver); + } + if (delegate_name == "FLEX") { delegate_ = FlexDelegate::Create(); } @@ -221,8 +230,7 @@ void TfLiteDriver::LoadModel(const string& bin_file_path) { Invalidate("Failed to mmap model " + bin_file_path); return; } - ops::builtin::BuiltinOpResolver builtins; - InterpreterBuilder(*model_, builtins)(&interpreter_); + InterpreterBuilder(*model_, *resolver_)(&interpreter_); if (!interpreter_) { Invalidate("Failed build interpreter"); return; diff --git a/tensorflow/lite/testing/tflite_driver.h b/tensorflow/lite/testing/tflite_driver.h index 1da0533c57..537f20dfbf 100644 --- a/tensorflow/lite/testing/tflite_driver.h +++ b/tensorflow/lite/testing/tflite_driver.h @@ -16,10 +16,12 @@ limitations under the License. #define TENSORFLOW_LITE_TESTING_TFLITE_DRIVER_H_ #include +#include #include "tensorflow/lite/delegates/flex/delegate.h" #include "tensorflow/lite/interpreter.h" #include "tensorflow/lite/kernels/register.h" +#include "tensorflow/lite/kernels/register_ref.h" #include "tensorflow/lite/model.h" #include "tensorflow/lite/testing/test_runner.h" @@ -29,7 +31,8 @@ namespace testing { // A test runner that feeds inputs into TF Lite and verifies its outputs. class TfLiteDriver : public TestRunner { public: - explicit TfLiteDriver(bool use_nnapi, const string& delegate = ""); + explicit TfLiteDriver(bool use_nnapi, const string& delegate = "", + bool reference_kernel = false); ~TfLiteDriver() override; void LoadModel(const string& bin_file_path) override; @@ -65,6 +68,7 @@ class TfLiteDriver : public TestRunner { class Expectation; + std::unique_ptr resolver_; std::unique_ptr delegate_; bool use_nnapi_ = false; std::unique_ptr model_; diff --git a/tensorflow/lite/testing/tflite_driver_test.cc b/tensorflow/lite/testing/tflite_driver_test.cc index 6e953e5e19..81bf6700cb 100644 --- a/tensorflow/lite/testing/tflite_driver_test.cc +++ b/tensorflow/lite/testing/tflite_driver_test.cc @@ -56,6 +56,40 @@ TEST(TfliteDriverTest, SimpleTest) { ASSERT_TRUE(runner->CheckResults()); } +TEST(TfliteDriverTest, SingleAddOpTest) { + std::unique_ptr runner(new TfLiteDriver( + /*use_nnapi*/ false, /*delegate*/ "", /*reference_kernel*/ true)); + + runner->SetModelBaseDir("tensorflow/lite"); + runner->LoadModel("testdata/multi_add.bin"); + ASSERT_TRUE(runner->IsValid()); + + ASSERT_THAT(runner->GetInputs(), ElementsAre(0, 1, 2, 3)); + ASSERT_THAT(runner->GetOutputs(), ElementsAre(5, 6)); + + for (int i : {0, 1, 2, 3}) { + runner->ReshapeTensor(i, "1,2,2,1"); + } + ASSERT_TRUE(runner->IsValid()); + + runner->AllocateTensors(); + + runner->SetInput(0, "0.1,0.2,0.3,0.4"); + runner->SetInput(1, "0.001,0.002,0.003,0.004"); + runner->SetInput(2, "0.001,0.002,0.003,0.004"); + runner->SetInput(3, "0.01,0.02,0.03,0.04"); + + runner->ResetTensor(2); + + runner->SetExpectation(5, "0.101,0.202,0.303,0.404"); + runner->SetExpectation(6, "0.011,0.022,0.033,0.044"); + + runner->Invoke(); + ASSERT_TRUE(runner->IsValid()); + + ASSERT_TRUE(runner->CheckResults()); +} + } // namespace } // namespace testing } // namespace tflite -- GitLab From d5ab00f2d6eb5c0a3c624312f58f4878230fb4a9 Mon Sep 17 00:00:00 2001 From: Alexandre Passos Date: Wed, 19 Dec 2018 16:04:16 -0800 Subject: [PATCH 0133/1765] Makes while_v2 compatible with the GradientTape. Adds a test. PiperOrigin-RevId: 226249565 --- .../python/kernel_tests/while_v2_test.py | 13 +++++++++ tensorflow/python/ops/while_v2.py | 28 +++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/tensorflow/python/kernel_tests/while_v2_test.py b/tensorflow/python/kernel_tests/while_v2_test.py index 6567ac9429..1f2c6f94c5 100644 --- a/tensorflow/python/kernel_tests/while_v2_test.py +++ b/tensorflow/python/kernel_tests/while_v2_test.py @@ -22,6 +22,7 @@ from absl.testing import parameterized from tensorflow.core.protobuf import config_pb2 from tensorflow.core.protobuf import rewriter_config_pb2 +from tensorflow.python.eager import backprop from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import meta_graph @@ -116,6 +117,18 @@ class WhileV2Test(test.TestCase, parameterized.TestCase): self.assertSequenceEqual(self.evaluate(grady_1), [6.]) self.assertSequenceEqual(self.evaluate(grady_2), [61.]) + @test_util.run_deprecated_v1 + def testGradientTape(self): + with backprop.GradientTape() as t: + x = constant_op.constant(2.) + t.watch(x) + ret = while_loop_v2( + lambda v: v < 4., lambda v: v * v, [x], + return_same_structure=False) # x**2 + grad = t.gradient(ret, x) + with self.cached_session() as sess: + self.assertAllEqual(sess.run(grad), 4.0) + @test_util.run_deprecated_v1 def testMultipleWhileLoops(self): x = constant_op.constant(2.) diff --git a/tensorflow/python/ops/while_v2.py b/tensorflow/python/ops/while_v2.py index 25fd2460ae..295686f814 100644 --- a/tensorflow/python/ops/while_v2.py +++ b/tensorflow/python/ops/while_v2.py @@ -242,8 +242,13 @@ def while_loop(cond, @ops.RegisterGradient("While") def _WhileGrad(op, *grads): # pylint: disable=invalid-name """The gradient of a While op produced by while_loop.""" - cond_graph = _get_graph(op, "cond") - body_graph = _get_graph(op, "body") + # Note that op is not always the same as while_op because the gradient tape, + # for eager mode compatibility, forgets information about the proper op. Since + # the loop cannot run in eager mode, however, we can safely introspect into + # the graph here. + while_op = op.outputs[0].op + cond_graph = _get_graph(while_op, "cond") + body_graph = _get_graph(while_op, "body") orig_num_params = len(body_graph.outputs) maximum_iterations = op.get_attr( @@ -287,16 +292,17 @@ def _WhileGrad(op, *grads): # pylint: disable=invalid-name new_inputs = body_grad_graph.empty_tensor_lists new_outputs = body_graph.outputs[orig_num_params:] - op._set_func_attr("cond", util.create_new_tf_function(cond_graph)) - op._set_func_attr("body", util.create_new_tf_function(body_graph)) - op._set_type_list_attr("T", body_graph.output_types) - op._set_shape_list_attr("output_shapes", body_graph.output_shapes) - op._add_while_inputs(new_inputs) - op._add_outputs([t.dtype for t in new_outputs], - [t.shape for t in new_outputs]) + while_op._set_func_attr("cond", util.create_new_tf_function(cond_graph)) + while_op._set_func_attr("body", util.create_new_tf_function(body_graph)) + while_op._set_type_list_attr("T", body_graph.output_types) + while_op._set_shape_list_attr("output_shapes", body_graph.output_shapes) + while_op._add_while_inputs(new_inputs) + while_op._add_outputs([t.dtype for t in new_outputs], + [t.shape for t in new_outputs]) _copy_handle_data(new_outputs, op.outputs[orig_num_params:]) - captured_inputs = _resolve_grad_captures(body_graph, body_grad_graph, op) + captured_inputs = _resolve_grad_captures(body_graph, body_grad_graph, + while_op) loop_vars = args + captured_inputs def grad_cond(counter, max_iters, *unused_args): @@ -314,7 +320,7 @@ def _WhileGrad(op, *grads): # pylint: disable=invalid-name util.create_new_tf_function(cond_grad_graph), util.create_new_tf_function(body_grad_graph), output_shapes=[t.shape for t in body_grad_graph.outputs], - name="%s_grad" % op.name) + name="%s_grad" % while_op.name) _copy_handle_data(body_grad_graph.outputs, outputs) util.maybe_set_lowering_attr(outputs[0].op) -- GitLab From c77e7e56de56c624116cf9eea340b4f96f032c85 Mon Sep 17 00:00:00 2001 From: Jared Duke Date: Wed, 19 Dec 2018 16:08:17 -0800 Subject: [PATCH 0134/1765] Add FFT kernels to TFMobile The marginal increase in binary size for an optimized ARM build of libtensorflow_inference.so is ~100KB, a 0.5% increase. Clients concerned about binary size should take advantage of op stripping via selective registration. PiperOrigin-RevId: 226250166 --- tensorflow/contrib/makefile/tf_op_files.txt | 1 + tensorflow/core/kernels/BUILD | 1 + tensorflow/lite/toco/tflite/operator_test.cc | 5 +++-- tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc | 12 ++++++++++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/tensorflow/contrib/makefile/tf_op_files.txt b/tensorflow/contrib/makefile/tf_op_files.txt index 655c7eefcb..2cd7d6d519 100644 --- a/tensorflow/contrib/makefile/tf_op_files.txt +++ b/tensorflow/contrib/makefile/tf_op_files.txt @@ -119,6 +119,7 @@ tensorflow/core/kernels/fake_quant_ops.cc tensorflow/core/kernels/fifo_queue.cc tensorflow/core/kernels/fifo_queue_op.cc tensorflow/core/kernels/fill_functor.cc +tensorflow/core/kernels/fft_ops.cc tensorflow/core/kernels/function_ops.cc tensorflow/core/kernels/fused_batch_norm_op.cc tensorflow/core/kernels/gather_functor.cc diff --git a/tensorflow/core/kernels/BUILD b/tensorflow/core/kernels/BUILD index c8aa2b3265..6bbce457f3 100644 --- a/tensorflow/core/kernels/BUILD +++ b/tensorflow/core/kernels/BUILD @@ -5595,6 +5595,7 @@ filegroup( "decode_bmp_op.cc", "depthtospace_op.cc", "dynamic_stitch_op.cc", + "fft_ops.cc", "in_topk_op.cc", "initializable_lookup_table.cc", "logging_ops.cc", diff --git a/tensorflow/lite/toco/tflite/operator_test.cc b/tensorflow/lite/toco/tflite/operator_test.cc index f2f7221eb1..849eace8cc 100644 --- a/tensorflow/lite/toco/tflite/operator_test.cc +++ b/tensorflow/lite/toco/tflite/operator_test.cc @@ -614,10 +614,11 @@ TEST_F(OperatorTest, TestShouldExportAsFlexOp) { EXPECT_FALSE(ShouldExportAsFlexOp(false, "Conv2D")); EXPECT_TRUE(ShouldExportAsFlexOp(true, "Conv2D")); EXPECT_TRUE(ShouldExportAsFlexOp(true, "EluGrad")); + EXPECT_TRUE(ShouldExportAsFlexOp(true, "RFFT")); EXPECT_FALSE(ShouldExportAsFlexOp(true, "MyAwesomeCustomOp")); - // While the RFFT op is available on desktop, it is not in the kernel + // While the RandomShuffle op is available on desktop, it is not in the kernel // set available on mobile and should be excluded. - EXPECT_FALSE(ShouldExportAsFlexOp(true, "RFFT")); + EXPECT_FALSE(ShouldExportAsFlexOp(true, "RandomShuffle")); } TEST_F(OperatorTest, BuiltinMirrorPad) { diff --git a/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc b/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc index 039a918af1..3611c5d2f2 100644 --- a/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc +++ b/tensorflow/lite/toco/tflite/whitelisted_flex_ops.cc @@ -118,6 +118,9 @@ bool IsWhitelistedFlexOp(const std::string& tensorflow_op_name) { "FakeQuantWithMinMaxVarsPerChannel", "FakeQuantWithMinMaxVarsPerChannelGradient", "FakeQueue", + "FFT", + "FFT2D", + "FFT3D", "FIFOQueue", "FIFOQueueV2", "Fill", @@ -143,6 +146,12 @@ bool IsWhitelistedFlexOp(const std::string& tensorflow_op_name) { "_HostSend", "Identity", "IdentityN", + "IFFT", + "IFFT2D", + "IFFT3D", + "IRFFT", + "IRFFT2D", + "IRFFT3D", "ImmutableConst", "InTopK", "InTopKV2", @@ -311,6 +320,9 @@ bool IsWhitelistedFlexOp(const std::string& tensorflow_op_name) { "Reverse", "ReverseSequence", "ReverseV2", + "RFFT", + "RFFT2D", + "RFFT3D", "Round", "Rsqrt", "RsqrtGrad", -- GitLab From 31c0a32740d70bb0f4c1787e1087d4bd70d59dfe Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Wed, 19 Dec 2018 16:21:53 -0800 Subject: [PATCH 0135/1765] Add `distribute_strategy` attribute to distributed variables. PiperOrigin-RevId: 226252079 --- .../python/collective_all_reduce_strategy.py | 3 +- .../python/mirrored_strategy_multigpu_test.py | 9 ++ .../python/parameter_server_strategy.py | 3 +- .../python/parameter_server_strategy_test.py | 1 + .../contrib/distribute/python/tpu_strategy.py | 9 +- .../contrib/distribute/python/values_test.py | 26 ++-- .../python/distribute/mirrored_strategy.py | 19 +-- tensorflow/python/distribute/values.py | 114 +++++++++++------- 8 files changed, 115 insertions(+), 69 deletions(-) diff --git a/tensorflow/contrib/distribute/python/collective_all_reduce_strategy.py b/tensorflow/contrib/distribute/python/collective_all_reduce_strategy.py index e6bbf0c308..12197c3d0d 100644 --- a/tensorflow/contrib/distribute/python/collective_all_reduce_strategy.py +++ b/tensorflow/contrib/distribute/python/collective_all_reduce_strategy.py @@ -222,7 +222,8 @@ class CollectiveAllReduceExtended(mirrored_strategy.MirroredExtended): # pylint: disable=protected-access return mirrored_strategy._create_mirrored_variable( - device_map, logical_device, _real_mirrored_creator, *args, **kwargs) + self._container_strategy(), device_map, logical_device, + _real_mirrored_creator, *args, **kwargs) def _distribute_dataset(self, dataset_fn): """Distributes the dataset to each local GPU.""" diff --git a/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py b/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py index f4becf1d62..a6348d2457 100644 --- a/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py +++ b/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py @@ -693,6 +693,15 @@ class MirroredStrategyVariableCreationTest(test.TestCase): distribution.extended.worker_devices[0]).read_value())) self.assertEqual(10.0, self.evaluate(ret_v_sum)) + def testVarDistributeStrategy(self, distribution): + with distribution.scope(): + mirrored = variable_scope.variable(1.0) + replica_local = variable_scope.variable( + 1.0, + synchronization=variable_scope.VariableSynchronization.ON_READ) + self.assertIs(distribution, mirrored.distribute_strategy) + self.assertIs(distribution, replica_local.distribute_strategy) + @combinations.generate(combinations.combine( distribution=[ diff --git a/tensorflow/contrib/distribute/python/parameter_server_strategy.py b/tensorflow/contrib/distribute/python/parameter_server_strategy.py index 5029d59641..2fd0c4d6ea 100644 --- a/tensorflow/contrib/distribute/python/parameter_server_strategy.py +++ b/tensorflow/contrib/distribute/python/parameter_server_strategy.py @@ -303,7 +303,8 @@ class ParameterServerExtended(distribute_lib.DistributionStrategyExtended): # Create and wrap the variable. v = next_creator(*args, **kwargs) - wrapped = values.AggregatingVariable(v, aggregation) + wrapped = values.AggregatingVariable( + self._container_strategy(), v, aggregation) # Add the wrapped variable to the requested collections. # The handling of eager mode and the global step matches diff --git a/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py b/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py index 805c643e67..e6ae16d856 100644 --- a/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py +++ b/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py @@ -716,6 +716,7 @@ class ParameterServerStrategyWithChiefTest(ParameterServerStrategyTestBase, id(get_step), get_step.__class__.__name__))) self.assertIs(values.AggregatingVariable, type(created_step)) self.assertIs(values.AggregatingVariable, type(get_step)) + self.assertIs(distribution, created_step.distribute_strategy) def testValueContainer(self): distribution = parameter_server_strategy.ParameterServerStrategy( diff --git a/tensorflow/contrib/distribute/python/tpu_strategy.py b/tensorflow/contrib/distribute/python/tpu_strategy.py index 7352203fe1..e081a735e2 100644 --- a/tensorflow/contrib/distribute/python/tpu_strategy.py +++ b/tensorflow/contrib/distribute/python/tpu_strategy.py @@ -68,7 +68,8 @@ def get_tpu_system_metadata(tpu_cluster_resolver): # TODO(jhseu): Deduplicate with MirroredStrategy? def _create_tpu_mirrored_variable( # pylint: disable=missing-docstring - device_map, logical_device, real_mirrored_creator, *args, **kwargs): + strategy, device_map, logical_device, real_mirrored_creator, + *args, **kwargs): # Figure out what collections this variable should be added to. # We'll add the TPUMirroredVariable to those collections instead. collections = kwargs.pop("collections", None) @@ -101,7 +102,8 @@ def _create_tpu_mirrored_variable( # pylint: disable=missing-docstring devices = device_map.logical_to_actual_devices(logical_device) value_list = real_mirrored_creator(devices, *args, **kwargs) result = values.TPUMirroredVariable( - device_map, value_list, aggregation, logical_device=logical_device) + strategy, device_map, value_list, aggregation, + logical_device=logical_device) if not context.executing_eagerly(): g = ops.get_default_graph() @@ -475,7 +477,8 @@ class TPUExtended(distribute_lib.DistributionStrategyExtended): return value_list return _create_tpu_mirrored_variable( - device_map, logical_device, _real_mirrored_creator, *args, **kwargs) + self._container_strategy(), device_map, logical_device, + _real_mirrored_creator, *args, **kwargs) def _reduce_to(self, reduce_op, value, destinations): if values._enclosing_tpu_context() is not None: # pylint: disable=protected-access diff --git a/tensorflow/contrib/distribute/python/values_test.py b/tensorflow/contrib/distribute/python/values_test.py index 0e8e86f6b9..73efb524b9 100644 --- a/tensorflow/contrib/distribute/python/values_test.py +++ b/tensorflow/contrib/distribute/python/values_test.py @@ -191,7 +191,7 @@ def _make_mirrored(): v.append(variable_scope.get_variable( name=n, initializer=init, use_resource=True)) device_map = values.ReplicaDeviceMap(devices) - mirrored = values.MirroredVariable(device_map, v, + mirrored = values.MirroredVariable(None, device_map, v, variable_scope.VariableAggregation.SUM) return v, device_map, mirrored @@ -314,7 +314,7 @@ class RegroupAndSelectDeviceTest(test.TestCase): v = variable_scope.get_variable( name="v", initializer=1., use_resource=True) device_map = values.ReplicaDeviceMap((d,)) - mirrored = values.MirroredVariable(device_map, (v,), + mirrored = values.MirroredVariable(None, device_map, (v,), variable_scope.VariableAggregation.SUM) result = values.regroup(device_map, (v,)) self.assertIs(mirrored, result) @@ -813,7 +813,7 @@ class MirroredVariableTest(test.TestCase, parameterized.TestCase): v = variable_scope.get_variable( name="v", initializer=[1.], use_resource=True) device_map = values.ReplicaDeviceMap(("/job:foo/device:CPU:0",)) - mirrored = values.MirroredVariable(device_map, (v,), + mirrored = values.MirroredVariable(None, device_map, (v,), variable_scope.VariableAggregation.MEAN) self.assertEqual(v.name, mirrored.name) @@ -952,7 +952,7 @@ class MirroredVariableTest(test.TestCase, parameterized.TestCase): v = variable_scope.get_variable( name="v", initializer=1., use_resource=True) mirrored = values.MirroredVariable( - values.ReplicaDeviceMap(("/device:GPU:0",)), (v,), + distribution, values.ReplicaDeviceMap(("/device:GPU:0",)), (v,), variable_scope.VariableAggregation.MEAN) sess.run(variables_lib.global_variables_initializer()) sess.run({"complicated": mirrored}) @@ -961,14 +961,14 @@ class MirroredVariableTest(test.TestCase, parameterized.TestCase): _devices = ("/device:GPU:0", "/device:CPU:0") -def _make_replica_local(method): +def _make_replica_local(method, strategy=None): device_map = values.ReplicaDeviceMap(_devices) v = [] for d, n, init in zip(_devices, ["v", "v/replica"], [1., 2.]): with ops.device(d): v.append(variable_scope.get_variable( name=n, initializer=init, use_resource=True)) - replica_local = values.ReplicaLocalVariable(device_map, v, method) + replica_local = values.ReplicaLocalVariable(strategy, device_map, v, method) return v, replica_local @@ -996,7 +996,7 @@ class ReplicaLocalVariablePropertiesTest(test.TestCase): name="v", initializer=[1.], use_resource=True) device_map = values.ReplicaDeviceMap(("/job:foo/device:CPU:0",)) replica_local = values.ReplicaLocalVariable( - device_map, (v,), variable_scope.VariableAggregation.MEAN) + None, device_map, (v,), variable_scope.VariableAggregation.MEAN) self.assertEqual(v.name, replica_local.name) self.assertEqual(v.dtype, replica_local.dtype) @@ -1043,7 +1043,7 @@ class ReplicaLocalVariableTest(test.TestCase, parameterized.TestCase): def testSaveAndRestoreReplicaLocalSumOneGraph(self, distribution): with self.cached_session() as sess: v, replica_local = _make_replica_local( - variable_scope.VariableAggregation.SUM) + variable_scope.VariableAggregation.SUM, distribution) # Overwrite the initial values. self._assign_replica_local(_devices, v, [3., 4.]) @@ -1066,7 +1066,7 @@ class ReplicaLocalVariableTest(test.TestCase, parameterized.TestCase): with self.cached_session() as sess: v, replica_local = _make_replica_local( - variable_scope.VariableAggregation.MEAN) + variable_scope.VariableAggregation.MEAN, distribution) # Overwrite the initial values. self._assign_replica_local(_devices, v, [3., 4.]) @@ -1086,7 +1086,7 @@ class ReplicaLocalVariableTest(test.TestCase, parameterized.TestCase): """Save variables with mirroring, returns save_path.""" with self.session(graph=ops.Graph()) as sess: v, replica_local = _make_replica_local( - variable_scope.VariableAggregation.MEAN) + variable_scope.VariableAggregation.MEAN, distribution) # Overwrite the initial values. self._assign_replica_local(_devices, v, [3., 4.]) @@ -1102,7 +1102,7 @@ class ReplicaLocalVariableTest(test.TestCase, parameterized.TestCase): def _save_replica_local_sum(self, distribution): """Save variables with mirroring, returns save_path.""" with self.session(graph=ops.Graph()) as sess: - v, replica_local = _make_replica_local("sum") + v, replica_local = _make_replica_local("sum", distribution) # Overwrite the initial values. self._assign_replica_local(_devices, v, [1.5, 2.]) @@ -1149,7 +1149,7 @@ class ReplicaLocalVariableTest(test.TestCase, parameterized.TestCase): """Restore to variables with mirroring in a fresh graph.""" with self.session(graph=ops.Graph()) as sess: v, replica_local = _make_replica_local( - variable_scope.VariableAggregation.MEAN) + variable_scope.VariableAggregation.MEAN, distribution) # Overwrite the initial values. self._assign_replica_local(_devices, v, [7., 8.]) @@ -1164,7 +1164,7 @@ class ReplicaLocalVariableTest(test.TestCase, parameterized.TestCase): """Restore to variables with mirroring in a fresh graph.""" with self.session(graph=ops.Graph()) as sess: v, replica_local = _make_replica_local( - variable_scope.VariableAggregation.SUM) + variable_scope.VariableAggregation.SUM, distribution) # Overwrite the initial values. self._assign_replica_local(_devices, v, [7., 8.]) diff --git a/tensorflow/python/distribute/mirrored_strategy.py b/tensorflow/python/distribute/mirrored_strategy.py index 4f29d916c4..71030d750b 100644 --- a/tensorflow/python/distribute/mirrored_strategy.py +++ b/tensorflow/python/distribute/mirrored_strategy.py @@ -193,8 +193,8 @@ def _call_for_each_replica(distribution, device_map, fn, args, kwargs): return values.regroup(device_map, tuple(t.main_result for t in threads)) -def _create_mirrored_variable(device_map, logical_device, real_mirrored_creator, - *args, **kwargs): # pylint: disable=g-missing-docstring +def _create_mirrored_variable(strategy, device_map, logical_device, # pylint: disable=missing-docstring + real_mirrored_creator, *args, **kwargs): # Figure out what collections this variable should be added to. # We'll add the MirroredVariable to those collections instead. collections = kwargs.pop("collections", None) @@ -245,11 +245,13 @@ def _create_mirrored_variable(device_map, logical_device, real_mirrored_creator, value_list = real_mirrored_creator(devices, *args, **kwargs) if is_replica_local: - result = values.ReplicaLocalVariable(device_map, value_list, aggregation, - logical_device=logical_device) + result = values.ReplicaLocalVariable( + strategy, device_map, value_list, aggregation, + logical_device=logical_device) else: - result = values.MirroredVariable(device_map, value_list, aggregation, - logical_device=logical_device) + result = values.MirroredVariable( + strategy, device_map, value_list, aggregation, + logical_device=logical_device) # Add the wrapped variable to the requested collections. # The handling of eager mode and the global step matches @@ -531,8 +533,9 @@ class MirroredExtended(distribute_lib.DistributionStrategyExtended): value_list.append(v) return value_list - return _create_mirrored_variable(device_map, logical_device, - _real_mirrored_creator, *args, **kwargs) + return _create_mirrored_variable( + self._container_strategy(), device_map, logical_device, + _real_mirrored_creator, *args, **kwargs) def _distribute_dataset(self, dataset_fn): if self._local_mode: diff --git a/tensorflow/python/distribute/values.py b/tensorflow/python/distribute/values.py index e0c575b01c..c3036b5aa5 100644 --- a/tensorflow/python/distribute/values.py +++ b/tensorflow/python/distribute/values.py @@ -413,6 +413,18 @@ def _assign_on_device(device, variable, tensor): return variable.assign(array_ops.identity(tensor)) +def _assert_strategy(strategy): + if not distribution_strategy_context.has_distribution_strategy(): + raise RuntimeError( + 'Need to be inside "with strategy.scope()" for %s' % + (strategy,)) + current_strategy = distribution_strategy_context.get_distribution_strategy() + if current_strategy is not strategy: + raise RuntimeError( + "Mixing different tf.distribute.Strategy objects: %s is not %s" % + (current_strategy, strategy)) + + DistributedVarOp = collections.namedtuple( "DistributedVarOp", ["name", "graph", "type"]) @@ -422,7 +434,8 @@ class DistributedVariable(DistributedDelegate): # TODO(josh11b): Support changing the set of variables if e.g. if new # devices are joining or a device is to leave. - def __init__(self, device_map, values, logical_device=None): + def __init__(self, strategy, device_map, values, logical_device=None): + self._distribute_strategy = strategy super(DistributedVariable, self).__init__( device_map, values, logical_device=logical_device) self._common_name = self.primary.name.split(":")[0] @@ -519,6 +532,10 @@ class DistributedVariable(DistributedDelegate): def shape(self): return self.primary.shape + @property + def distribute_strategy(self): + return self._distribute_strategy + def get_shape(self): return self.primary.get_shape() @@ -530,7 +547,7 @@ class DistributedVariable(DistributedDelegate): # We want cross-replica code that does some var.op.X calls # to work (even if the current device isn't in self.devices), but # other uses of var.op in a cross-replica context to fail. - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): return DistributedVarOp(self.primary.op.name, self.primary.op.graph, self.primary.op.type) @@ -541,8 +558,7 @@ class DistributedVariable(DistributedDelegate): return self.primary._in_graph_mode # pylint: disable=protected-access def read_value(self): - strategy = distribution_strategy_context.get_distribution_strategy() - return strategy.extended.read_var(self) + return self._distribute_strategy.extended.read_var(self) def _should_act_as_resource_variable(self): """Pass resource_variable_ops.is_resource_variable check.""" @@ -579,9 +595,10 @@ class MirroredVariable(DistributedVariable, Mirrored, checkpointable.CheckpointableBase): """Holds a map from device to variables whose values are kept in sync.""" - def __init__(self, device_map, values, aggregation, logical_device=None): + def __init__( + self, strategy, device_map, values, aggregation, logical_device=None): super(MirroredVariable, self).__init__( - device_map, values, logical_device=logical_device) + strategy, device_map, values, logical_device=logical_device) self._aggregation = aggregation # The arguments to update() are automatically unwrapped so the update() @@ -591,8 +608,9 @@ class MirroredVariable(DistributedVariable, Mirrored, # update_non_slot() function (like OptimizerV2._finish), which can # update several non-slot variables in one call. def _assign_func(self, *args, **kwargs): + _assert_strategy(self._distribute_strategy) f = kwargs.pop("f") - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): update_device = distribute_lib.get_update_device() if update_device is not None: # We are calling an assign function on the mirrored variable in an @@ -602,10 +620,9 @@ class MirroredVariable(DistributedVariable, Mirrored, # We are calling assign on the mirrored variable in cross replica context, # use `strategy.update()` to update the variable. - strategy = distribution_strategy_context.get_distribution_strategy() - return strategy.update(self, f, *args, **kwargs) + return self._distribute_strategy.update(self, f, *args, **kwargs) else: - _assert_replica_context() + _assert_replica_context(self._distribute_strategy) # We are calling an assign function on the mirrored variable in replica # context. # We reduce the value we want to assign/add/sub. More details about how we @@ -648,7 +665,7 @@ class MirroredVariable(DistributedVariable, Mirrored, def _as_graph_element(self): # pylint: disable=protected-access - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): return self.primary._as_graph_element() return self.get()._as_graph_element() @@ -698,8 +715,10 @@ def _enclosing_tpu_context(): class TPUMirroredVariable(checkpointable.CheckpointableBase): """Holds a map from device to TPU variables whose values are kept in sync.""" - def __init__(self, device_map, values, aggregation, logical_device=None): + def __init__( + self, strategy, device_map, values, aggregation, logical_device=None): assert isinstance(device_map, DeviceMap) + self._distribute_strategy = strategy self._device_map = device_map self._values = tuple(values) if logical_device is None: @@ -756,6 +775,10 @@ class TPUMirroredVariable(checkpointable.CheckpointableBase): def values(self): return self._values + @property + def distribute_strategy(self): + return self._distribute_strategy + # pylint: disable=multiple-statements def __add__(self, o): return self.read_value() + o def __radd__(self, o): return o + self.read_value() @@ -853,15 +876,11 @@ class TPUMirroredVariable(checkpointable.CheckpointableBase): # update_non_slot() function (like OptimizerV2._finish), which can # update several non-slot variables in one call. def _assign_func(self, *args, **kwargs): - strategy = distribution_strategy_context.get_distribution_strategy() - if strategy.__class__.__name__ != "TPUStrategy": - raise ValueError("You may only assign to a TPUMirroredVariable within a " - "TPUStrategy.") + _assert_strategy(self._distribute_strategy) f = kwargs.pop("f") - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): if _enclosing_tpu_context() is not None: - return distribution_strategy_context.get_distribution_strategy().update( - self, f, *args, **kwargs) + return self._distribute_strategy.update(self, f, *args, **kwargs) update_device = distribute_lib.get_update_device() # We are calling update on the mirrored variable in cross replica context. @@ -871,10 +890,9 @@ class TPUMirroredVariable(checkpointable.CheckpointableBase): v = self._get(device=update_device) return f(v, *args, **kwargs) - return distribution_strategy_context.get_distribution_strategy().update( - self, f, *args, **kwargs) + return self._distribute_strategy.update(self, f, *args, **kwargs) else: - _assert_replica_context() + _assert_replica_context(self._distribute_strategy) # We are calling an assign function on the mirrored variable in replica # context. # We reduce the value we want to assign/add/sub. More details about how we @@ -1019,7 +1037,7 @@ class TPUMirroredVariable(checkpointable.CheckpointableBase): def _as_graph_element(self): # pylint: disable=protected-access - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): return self.primary._as_graph_element() return self._read_variable_op() @@ -1117,7 +1135,7 @@ class _ReplicaLocalSaveable(saver.BaseSaverBuilder.SaveableObject): # We use a callable so that we don't have to evaluate this expression # in the case where we are trying to restore instead of save. def tensor(): - strategy = distribution_strategy_context.get_distribution_strategy() + strategy = replica_local_variable.distribute_strategy return strategy.extended.read_var(replica_local_variable) spec = saver.BaseSaverBuilder.SaveSpec( @@ -1133,8 +1151,12 @@ class _ReplicaLocalSaveable(saver.BaseSaverBuilder.SaveableObject): return self._replica_local_variable.assign(tensor) -def _assert_replica_context(): - if not distribution_strategy_context.get_replica_context(): +def _assert_replica_context(strategy): + replica_context = distribution_strategy_context.get_replica_context() + if not replica_context: + raise RuntimeError( + "Replica-local variables may only be assigned in a replica context.") + if replica_context.strategy is not strategy: raise RuntimeError( "Replica-local variables may only be assigned in a replica context.") @@ -1143,21 +1165,22 @@ class ReplicaLocalVariable(DistributedVariable, PerReplica, checkpointable.CheckpointableBase): """Holds a map from device to variables whose values are reduced on save.""" - def __init__(self, device_map, values, aggregation, logical_device=None): + def __init__( + self, strategy, device_map, values, aggregation, logical_device=None): self._aggregation = aggregation super(ReplicaLocalVariable, self).__init__( - device_map, values, logical_device=logical_device) + strategy, device_map, values, logical_device=logical_device) def assign_sub(self, *args, **kwargs): - _assert_replica_context() + _assert_replica_context(self._distribute_strategy) return self.get().assign_sub(*args, **kwargs) def assign_add(self, *args, **kwargs): - _assert_replica_context() + _assert_replica_context(self._distribute_strategy) return self.get().assign_add(*args, **kwargs) def assign(self, *args, **kwargs): - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): # To preserve the sum across save and restore, we have to divide the # total across all devices when restoring a variable that was summed # when saving. @@ -1167,7 +1190,7 @@ class ReplicaLocalVariable(DistributedVariable, PerReplica, return control_flow_ops.group(tuple( _assign_on_device(v.device, v, tensor) for v in self._values)) else: - _assert_replica_context() + _assert_replica_context(self._distribute_strategy) return self.get().assign(*args, **kwargs) @property @@ -1185,7 +1208,7 @@ class ReplicaLocalVariable(DistributedVariable, PerReplica, def _as_graph_element(self): # pylint: disable=protected-access - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): return self._get_cross_replica() return self.get()._as_graph_element() @@ -1998,7 +2021,7 @@ class MultiStepContext(object): `_last_step_outputs_reduce_ops` for later interpreting of the outputs as already reduced or not. """ - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): self._last_step_outputs_reduce_ops[name] = reduce_op if reduce_op is None: self._last_step_outputs[name] = output @@ -2024,7 +2047,7 @@ class MultiStepContext(object): def set_non_tensor_output(self, name, output): """Set `output` with `name` to be captured as a non tensor output.""" - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): self._non_tensor_outputs[name] = output else: def merge_fn(distribution, value): @@ -2061,7 +2084,8 @@ def value_container(val): class AggregatingVariable(checkpointable.CheckpointableBase): """A wrapper around a variable that aggregates updates across replicas.""" - def __init__(self, v, aggregation): + def __init__(self, strategy, v, aggregation): + self._distribute_strategy = strategy self._v = v # NOTE: We don't use "_distributed_container" here because we don't want # to trigger that code path in regroup(). @@ -2071,12 +2095,17 @@ class AggregatingVariable(checkpointable.CheckpointableBase): def get(self): return self._v + @property + def distribute_strategy(self): + return self._distribute_strategy + def __getattr__(self, name): return getattr(self._v, name) def _assign_func(self, *args, **kwargs): + _assert_strategy(self._distribute_strategy) f = kwargs.pop("f") - if distribution_strategy_context.get_cross_replica_context(): + if distribution_strategy_context.in_cross_replica_context(): update_device = distribute_lib.get_update_device() if update_device is not None: # We are calling an assign function in an update context. @@ -2084,24 +2113,23 @@ class AggregatingVariable(checkpointable.CheckpointableBase): # We are calling an assign function in cross replica context, wrap it in # an update call. - return distribution_strategy_context.get_distribution_strategy().update( - self, f, *args, **kwargs) + return self._distribute_strategy.update(self, f, *args, **kwargs) else: - assert distribution_strategy_context.get_replica_context() + replica_context = distribution_strategy_context.get_replica_context() + assert replica_context # We are calling an assign function in replica context. # We reduce the value we want to assign/add/sub. More details about how we # handle the different use cases can be found in the _reduce method. # We call the function with the reduced value. if self._aggregation == vs.VariableAggregation.NONE: raise ValueError("You must specify an aggregation method to update a " - "a variable in Replica Context.") + "a variable in replica context.") def merge_fn(strategy, value, *other_args, **other_kwargs): v = _apply_aggregation(strategy, value, self._aggregation, self) return strategy.update(self, f, v, *other_args, **other_kwargs) - return distribution_strategy_context.get_replica_context().merge_call( - merge_fn, args=args, kwargs=kwargs) + return replica_context.merge_call(merge_fn, args=args, kwargs=kwargs) def assign_sub(self, *args, **kwargs): assign_sub_fn = lambda var, *a, **kw: var.assign_sub(*a, **kw) -- GitLab From 8cd607c56d53e041b0b8e4d76fef194fa0bf624f Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Wed, 19 Dec 2018 16:22:42 -0800 Subject: [PATCH 0136/1765] Explicitly defining PI to fix windows build. PiperOrigin-RevId: 226252206 --- tensorflow/core/kernels/sampling_kernels.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tensorflow/core/kernels/sampling_kernels.h b/tensorflow/core/kernels/sampling_kernels.h index 4e79d89831..a03a2c88db 100644 --- a/tensorflow/core/kernels/sampling_kernels.h +++ b/tensorflow/core/kernels/sampling_kernels.h @@ -17,6 +17,7 @@ limitations under the License. #define TENSORFLOW_CORE_KERNELS_SAMPLING_KERNELS_H_ #include + #include "tensorflow/core/lib/core/stringpiece.h" namespace tensorflow { @@ -68,14 +69,15 @@ struct LanczosKernelFunc { // Pass 1 for Lanczos1 kernel, 3 for Lanczos3 etc. explicit LanczosKernelFunc(float _radius) : radius(_radius) {} float operator()(float x) const { + constexpr float kPI = 3.14159265359; x = std::abs(x); if (x > radius) return 0.0; // Need to special case the limit case of sin(x) / x when x is zero. if (x <= 1e-3) { return 1.0; } - return radius * std::sin(M_PI * x) * std::sin(M_PI * x / radius) / - (M_PI * M_PI * x * x); + return radius * std::sin(kPI * x) * std::sin(kPI * x / radius) / + (kPI * kPI * x * x); } float Radius() const { return radius; } const float radius; -- GitLab From 0445684a64d1bea8490a99eb9ce278176133df75 Mon Sep 17 00:00:00 2001 From: Skye Wanderman-Milne Date: Wed, 19 Dec 2018 16:23:12 -0800 Subject: [PATCH 0137/1765] Enable control flow v2 inside TF functions. This makes it so control flow v2 is enabled when inside a function and otherwise disabled (i.e. if inside of a legacy graph), regardless of whether TF 2.0 behavior is enabled. Note that in eager mode, Python control flow is used instead of control flow graph ops. PiperOrigin-RevId: 226252291 --- tensorflow/python/framework/importer.py | 3 ++- tensorflow/python/keras/layers/normalization.py | 8 +++++--- tensorflow/python/keras/layers/unified_gru_test.py | 2 ++ tensorflow/python/ops/control_flow_ops.py | 8 ++++++-- tensorflow/python/ops/control_flow_util.py | 12 +++++++++--- tensorflow/python/ops/tensor_array_ops.py | 2 +- tensorflow/python/saved_model/save_test.py | 1 + 7 files changed, 26 insertions(+), 10 deletions(-) diff --git a/tensorflow/python/framework/importer.py b/tensorflow/python/framework/importer.py index c737bd4881..e6f86f7f93 100644 --- a/tensorflow/python/framework/importer.py +++ b/tensorflow/python/framework/importer.py @@ -28,6 +28,7 @@ from tensorflow.python.framework import errors from tensorflow.python.framework import function from tensorflow.python.framework import op_def_registry from tensorflow.python.framework import ops +from tensorflow.python.ops import control_flow_util from tensorflow.python.util import compat from tensorflow.python.util.deprecation import deprecated_args from tensorflow.python.util.tf_export import tf_export @@ -266,7 +267,7 @@ def _ProcessNewOps(graph): coloc_op = graph._get_operation_by_name_unsafe(coloc_op_name) # pylint: disable=protected-access except KeyError: # Do not error in TF2 if the colocation cannot be guaranteed - if tf2.enabled(): + if tf2.enabled() or control_flow_util.EnableControlFlowV2(graph): continue raise ValueError('Specified colocation to an op that ' diff --git a/tensorflow/python/keras/layers/normalization.py b/tensorflow/python/keras/layers/normalization.py index c3c5b2db7d..cee0da1b32 100644 --- a/tensorflow/python/keras/layers/normalization.py +++ b/tensorflow/python/keras/layers/normalization.py @@ -34,6 +34,7 @@ from tensorflow.python.keras.engine.base_layer import Layer from tensorflow.python.keras.engine.input_spec import InputSpec from tensorflow.python.keras.utils import tf_utils from tensorflow.python.ops import array_ops +from tensorflow.python.ops import control_flow_util from tensorflow.python.ops import init_ops from tensorflow.python.ops import math_ops from tensorflow.python.ops import nn @@ -424,9 +425,10 @@ class BatchNormalizationV2(Layer): is_tpu_strategy = True # TODO(apassos,srbs,skyewm): the colocation constraints here are disabled - # because of a bug which leads cond_v2 to skip rewriting them creating - # conflicts. - if tf2.enabled() or is_tpu_strategy: + # because of a bug which leads cond_v2/while_v2 to skip rewriting them + # creating conflicts. + if (control_flow_util.EnableControlFlowV2(ops.get_default_graph()) or + is_tpu_strategy): cm = contextlib.contextmanager(lambda: (yield))() else: cm = ops.colocate_with(variable) diff --git a/tensorflow/python/keras/layers/unified_gru_test.py b/tensorflow/python/keras/layers/unified_gru_test.py index 6e77acc20a..57c1e151f9 100644 --- a/tensorflow/python/keras/layers/unified_gru_test.py +++ b/tensorflow/python/keras/layers/unified_gru_test.py @@ -423,6 +423,8 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): @test_util.run_v1_only("b/120941292") @test_util.run_in_graph_and_eager_modes(config=_config) def test_statefulness_GRU(self): + self.skipTest('b/121275483') + num_samples = 2 timesteps = 3 embedding_dim = 4 diff --git a/tensorflow/python/ops/control_flow_ops.py b/tensorflow/python/ops/control_flow_ops.py index 99216d7fb1..2b481bded5 100644 --- a/tensorflow/python/ops/control_flow_ops.py +++ b/tensorflow/python/ops/control_flow_ops.py @@ -2047,7 +2047,9 @@ def cond(pred, ``` """ - if util.ENABLE_CONTROL_FLOW_V2 and not context.executing_eagerly(): + # Always enable control flow v2 if building a function, regardless of toggle. + if (util.EnableControlFlowV2(ops.get_default_graph()) and + not context.executing_eagerly()): return cond_v2.cond_v2(pred, true_fn, false_fn, name) # We needed to make true_fn/false_fn keyword arguments for @@ -3482,7 +3484,9 @@ def while_loop(cond, ``` """ - if util.ENABLE_CONTROL_FLOW_V2 and not context.executing_eagerly(): + # Always enable control flow v2 if building a function, regardless of toggle. + if (util.EnableControlFlowV2(ops.get_default_graph()) and + not context.executing_eagerly()): return while_v2.while_loop( cond, body, diff --git a/tensorflow/python/ops/control_flow_util.py b/tensorflow/python/ops/control_flow_util.py index 1747f06109..8f5442da5e 100644 --- a/tensorflow/python/ops/control_flow_util.py +++ b/tensorflow/python/ops/control_flow_util.py @@ -26,16 +26,22 @@ from __future__ import print_function import os import traceback -from tensorflow.python import tf2 from tensorflow.python.platform import tf_logging as logging -ENABLE_CONTROL_FLOW_V2 = (tf2.enabled() or - os.getenv("TF_ENABLE_CONTROL_FLOW_V2", "0") != "0" or +ENABLE_CONTROL_FLOW_V2 = (os.getenv("TF_ENABLE_CONTROL_FLOW_V2", "0") != "0" or os.getenv("TF_ENABLE_COND_V2", "0") != "0" or os.getenv("TF_ENABLE_WHILE_V2", "0") != "0" or os.getenv("TF_ENABLE_TENSOR_ARRAY_V2", "0") != "0") +def EnableControlFlowV2(graph): + """Returns whether control flow v2 should be used in `graph`.""" + # Enable new control flow in FuncGraphs (but not legacy _FuncGraphs). + # TODO(skyewm): do something better than hasattr without messing up imports. + return ENABLE_CONTROL_FLOW_V2 or ( + graph.building_function and not hasattr(graph, "_captured")) + + def IsInXLAContext(op): try: xla_compile = op.get_attr("_XlaCompile") diff --git a/tensorflow/python/ops/tensor_array_ops.py b/tensorflow/python/ops/tensor_array_ops.py index 85333ee6b5..37d5e6ae2a 100644 --- a/tensorflow/python/ops/tensor_array_ops.py +++ b/tensorflow/python/ops/tensor_array_ops.py @@ -1008,7 +1008,7 @@ class TensorArray(object): if context.executing_eagerly(): implementation = _EagerTensorArray else: - if control_flow_util.ENABLE_CONTROL_FLOW_V2: + if control_flow_util.EnableControlFlowV2(ops.get_default_graph()): implementation = _GraphTensorArrayV2 else: implementation = _GraphTensorArray diff --git a/tensorflow/python/saved_model/save_test.py b/tensorflow/python/saved_model/save_test.py index cffc1ec202..f5d4b3d5a9 100644 --- a/tensorflow/python/saved_model/save_test.py +++ b/tensorflow/python/saved_model/save_test.py @@ -378,6 +378,7 @@ class MemoryTests(test.TestCase): @test_util.assert_no_garbage_created def test_no_reference_cycles(self): + self.skipTest("b/121159261") x = constant_op.constant([[3., 4.]]) y = constant_op.constant([2.]) self._model.call(x, y) -- GitLab From 65093ecfe62147c5b03d43e47c14318cd076b9d1 Mon Sep 17 00:00:00 2001 From: Rick Chao Date: Wed, 19 Dec 2018 16:25:49 -0800 Subject: [PATCH 0138/1765] Remove the 'mode' argument in on_epoch_begin and on_epoch_end methods of CallbackList and Callback classes, to eliminate exposure of ModeKeys api that's intended to be TensorFlow-internal. Add doc that says the methods should only be called during TRAIN mode. PiperOrigin-RevId: 226252687 --- tensorflow/python/keras/callbacks.py | 36 +++++++++---------- .../python/keras/engine/training_arrays.py | 6 ++-- .../python/keras/engine/training_generator.py | 6 ++-- ...orflow.keras.callbacks.-c-s-v-logger.pbtxt | 2 +- ...tensorflow.keras.callbacks.-callback.pbtxt | 4 +-- ...flow.keras.callbacks.-early-stopping.pbtxt | 2 +- .../tensorflow.keras.callbacks.-history.pbtxt | 2 +- ...low.keras.callbacks.-lambda-callback.pbtxt | 4 +-- ...ow.keras.callbacks.-model-checkpoint.pbtxt | 2 +- ...ras.callbacks.-reduce-l-r-on-plateau.pbtxt | 2 +- ...flow.keras.callbacks.-remote-monitor.pbtxt | 2 +- ...w.keras.callbacks.-terminate-on-na-n.pbtxt | 4 +-- ...orflow.keras.callbacks.-c-s-v-logger.pbtxt | 2 +- ...tensorflow.keras.callbacks.-callback.pbtxt | 4 +-- ...flow.keras.callbacks.-early-stopping.pbtxt | 2 +- .../tensorflow.keras.callbacks.-history.pbtxt | 2 +- ...low.keras.callbacks.-lambda-callback.pbtxt | 4 +-- ...ow.keras.callbacks.-model-checkpoint.pbtxt | 2 +- ...ras.callbacks.-reduce-l-r-on-plateau.pbtxt | 2 +- ...flow.keras.callbacks.-remote-monitor.pbtxt | 2 +- ...w.keras.callbacks.-terminate-on-na-n.pbtxt | 4 +-- 21 files changed, 50 insertions(+), 46 deletions(-) diff --git a/tensorflow/python/keras/callbacks.py b/tensorflow/python/keras/callbacks.py index a8fb87f5cc..53a51f5274 100644 --- a/tensorflow/python/keras/callbacks.py +++ b/tensorflow/python/keras/callbacks.py @@ -242,35 +242,35 @@ class CallbackList(object): def on_batch_end(self, batch, logs=None): self._call_batch_hook(_TRAIN, 'end', batch, logs=logs) - def on_epoch_begin(self, epoch, logs=None, mode='train'): + def on_epoch_begin(self, epoch, logs=None): """Calls the `on_epoch_begin` methods of its callbacks. + This function should only be called during TRAIN mode. + Arguments: epoch: integer, index of epoch. logs: dict. Currently no data is passed to this argument for this method but that may change in the future. - mode: One of 'train'/'test'/'predict' """ - if mode == _TRAIN: - logs = logs or {} - for callback in self.callbacks: - callback.on_epoch_begin(epoch, logs) + logs = logs or {} + for callback in self.callbacks: + callback.on_epoch_begin(epoch, logs) self._reset_batch_timing() - def on_epoch_end(self, epoch, logs=None, mode='train'): + def on_epoch_end(self, epoch, logs=None): """Calls the `on_epoch_end` methods of its callbacks. + This function should only be called during TRAIN mode. + Arguments: epoch: integer, index of epoch. logs: dict, metric results for this training epoch, and for the validation epoch if validation is performed. Validation result keys are prefixed with `val_`. - mode: One of 'train'/'test'/'predict' """ - if mode == _TRAIN: - logs = logs or {} - for callback in self.callbacks: - callback.on_epoch_end(epoch, logs) + logs = logs or {} + for callback in self.callbacks: + callback.on_epoch_end(epoch, logs) def on_train_batch_begin(self, batch, logs=None): """Calls the `on_train_batch_begin` methods of its callbacks. @@ -437,29 +437,29 @@ class Callback(object): def on_batch_end(self, batch, logs=None): """A backwards compatibility alias for `on_train_batch_end`.""" - def on_epoch_begin(self, epoch, logs=None, mode='train'): + def on_epoch_begin(self, epoch, logs=None): """Called at the start of an epoch. - Subclasses should override for any actions to run. + Subclasses should override for any actions to run. This function should only + be called during TRAIN mode. Arguments: epoch: integer, index of epoch. logs: dict. Currently no data is passed to this argument for this method but that may change in the future. - mode: One of 'train'/'test'/'predict' """ - def on_epoch_end(self, epoch, logs=None, mode='train'): + def on_epoch_end(self, epoch, logs=None): """Called at the end of an epoch. - Subclasses should override for any actions to run. + Subclasses should override for any actions to run. This function should only + be called during TRAIN mode. Arguments: epoch: integer, index of epoch. logs: dict, metric results for this training epoch, and for the validation epoch if validation is performed. Validation result keys are prefixed with `val_`. - mode: One of 'train'/'test'/'predict' """ def on_train_batch_begin(self, batch, logs=None): diff --git a/tensorflow/python/keras/engine/training_arrays.py b/tensorflow/python/keras/engine/training_arrays.py index af67444b01..47074e6087 100644 --- a/tensorflow/python/keras/engine/training_arrays.py +++ b/tensorflow/python/keras/engine/training_arrays.py @@ -32,6 +32,7 @@ from tensorflow.python.keras.engine import training_utils from tensorflow.python.keras.utils.generic_utils import make_batches from tensorflow.python.keras.utils.generic_utils import slice_arrays from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.training.mode_keys import ModeKeys try: from scipy.sparse import issparse # pylint: disable=g-import-not-at-top @@ -251,7 +252,8 @@ def model_iteration(model, # Setup work for each epoch epoch_logs = {} model.reset_metrics() - callbacks.on_epoch_begin(epoch, epoch_logs, mode=mode) + if mode == ModeKeys.TRAIN: + callbacks.on_epoch_begin(epoch, epoch_logs) progbar.on_epoch_begin(epoch, epoch_logs) if use_steps: @@ -371,7 +373,7 @@ def model_iteration(model, if mode == 'train': # Epochs only apply to `fit`. - callbacks.on_epoch_end(epoch, epoch_logs, mode=mode) + callbacks.on_epoch_end(epoch, epoch_logs) progbar.on_epoch_end(epoch, epoch_logs) callbacks._call_end_hook(mode) diff --git a/tensorflow/python/keras/engine/training_generator.py b/tensorflow/python/keras/engine/training_generator.py index bc6a3e8dd0..03cbe91dc4 100644 --- a/tensorflow/python/keras/engine/training_generator.py +++ b/tensorflow/python/keras/engine/training_generator.py @@ -34,6 +34,7 @@ from tensorflow.python.keras.engine import training_utils from tensorflow.python.keras.utils import data_utils from tensorflow.python.keras.utils import generic_utils from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.training.mode_keys import ModeKeys from tensorflow.python.util import nest @@ -170,7 +171,8 @@ def model_iteration(model, # Setup work for each epoch. model.reset_metrics() epoch_logs = {} - callbacks.on_epoch_begin(epoch, epoch_logs, mode=mode) + if mode == ModeKeys.TRAIN: + callbacks.on_epoch_begin(epoch, epoch_logs) progbar.on_epoch_begin(epoch, epoch_logs) for step in range(steps_per_epoch): @@ -233,7 +235,7 @@ def model_iteration(model, if mode == 'train': # Epochs only apply to `fit`. - callbacks.on_epoch_end(epoch, epoch_logs, mode=mode) + callbacks.on_epoch_end(epoch, epoch_logs) progbar.on_epoch_end(epoch, epoch_logs) callbacks._call_end_hook(mode) diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-c-s-v-logger.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-c-s-v-logger.pbtxt index a5804d3bbc..0725f606e2 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-c-s-v-logger.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-c-s-v-logger.pbtxt @@ -17,7 +17,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-callback.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-callback.pbtxt index bbc02c4d71..14bfc3bedb 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-callback.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-callback.pbtxt @@ -16,11 +16,11 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_predict_batch_begin" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-early-stopping.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-early-stopping.pbtxt index 6182baf0a3..9812bad8f6 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-early-stopping.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-early-stopping.pbtxt @@ -21,7 +21,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-history.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-history.pbtxt index 9b1b068e22..5aa739391e 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-history.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-history.pbtxt @@ -17,7 +17,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-lambda-callback.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-lambda-callback.pbtxt index 92440188c8..bf5bcb68df 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-lambda-callback.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-lambda-callback.pbtxt @@ -17,11 +17,11 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_predict_batch_begin" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-model-checkpoint.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-model-checkpoint.pbtxt index c10c236ad1..5ae176017b 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-model-checkpoint.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-model-checkpoint.pbtxt @@ -17,7 +17,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-reduce-l-r-on-plateau.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-reduce-l-r-on-plateau.pbtxt index 0db6b8d371..0fed6fd236 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-reduce-l-r-on-plateau.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-reduce-l-r-on-plateau.pbtxt @@ -21,7 +21,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-remote-monitor.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-remote-monitor.pbtxt index dac2049fe1..71cf7f4a49 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-remote-monitor.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-remote-monitor.pbtxt @@ -17,7 +17,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-terminate-on-na-n.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-terminate-on-na-n.pbtxt index 2834b74e8a..d5a59d870a 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-terminate-on-na-n.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.keras.callbacks.-terminate-on-na-n.pbtxt @@ -17,11 +17,11 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_predict_batch_begin" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-c-s-v-logger.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-c-s-v-logger.pbtxt index a5804d3bbc..0725f606e2 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-c-s-v-logger.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-c-s-v-logger.pbtxt @@ -17,7 +17,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-callback.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-callback.pbtxt index bbc02c4d71..14bfc3bedb 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-callback.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-callback.pbtxt @@ -16,11 +16,11 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_predict_batch_begin" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-early-stopping.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-early-stopping.pbtxt index 6182baf0a3..9812bad8f6 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-early-stopping.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-early-stopping.pbtxt @@ -21,7 +21,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-history.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-history.pbtxt index 9b1b068e22..5aa739391e 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-history.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-history.pbtxt @@ -17,7 +17,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-lambda-callback.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-lambda-callback.pbtxt index 92440188c8..bf5bcb68df 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-lambda-callback.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-lambda-callback.pbtxt @@ -17,11 +17,11 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_predict_batch_begin" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-model-checkpoint.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-model-checkpoint.pbtxt index c10c236ad1..5ae176017b 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-model-checkpoint.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-model-checkpoint.pbtxt @@ -17,7 +17,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-reduce-l-r-on-plateau.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-reduce-l-r-on-plateau.pbtxt index 0db6b8d371..0fed6fd236 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-reduce-l-r-on-plateau.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-reduce-l-r-on-plateau.pbtxt @@ -21,7 +21,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-remote-monitor.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-remote-monitor.pbtxt index dac2049fe1..71cf7f4a49 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-remote-monitor.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-remote-monitor.pbtxt @@ -17,7 +17,7 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-terminate-on-na-n.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-terminate-on-na-n.pbtxt index 2834b74e8a..d5a59d870a 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-terminate-on-na-n.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.callbacks.-terminate-on-na-n.pbtxt @@ -17,11 +17,11 @@ tf_class { } member_method { name: "on_epoch_begin" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_epoch_end" - argspec: "args=[\'self\', \'epoch\', \'logs\', \'mode\'], varargs=None, keywords=None, defaults=[\'None\', \'train\'], " + argspec: "args=[\'self\', \'epoch\', \'logs\'], varargs=None, keywords=None, defaults=[\'None\'], " } member_method { name: "on_predict_batch_begin" -- GitLab From a2748231219a6c4582ce7e6593710db4c3eec176 Mon Sep 17 00:00:00 2001 From: Rohan Jain Date: Wed, 19 Dec 2018 16:41:08 -0800 Subject: [PATCH 0139/1765] Adds eager support for MultiDeviceIterator PiperOrigin-RevId: 226254965 --- .../multi_device_iterator_test.py | 85 ++++++++++++------- .../data/ops/multi_device_iterator_ops.py | 73 ++++++++-------- 2 files changed, 95 insertions(+), 63 deletions(-) diff --git a/tensorflow/python/data/kernel_tests/multi_device_iterator_test.py b/tensorflow/python/data/kernel_tests/multi_device_iterator_test.py index 433ea620e1..66117cf5b9 100644 --- a/tensorflow/python/data/kernel_tests/multi_device_iterator_test.py +++ b/tensorflow/python/data/kernel_tests/multi_device_iterator_test.py @@ -23,6 +23,7 @@ from tensorflow.python.data.experimental.ops import optimization from tensorflow.python.data.kernel_tests import test_base from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import multi_device_iterator_ops +from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import ops @@ -31,97 +32,109 @@ from tensorflow.python.ops import array_ops from tensorflow.python.platform import test -# TODO(b/117581999): Add eager coverage. +# TODO(b/121264236): Once we have a mechanism to have multiple devices in eager +# / V2 mode, we should remove this annotation and the run_v1_only annotations +# as well. +@test_util.run_all_in_graph_and_eager_modes class MultiDeviceIteratorTest(test_base.DatasetTestBase): - @test_util.run_v1_only("b/120545219") + @test_util.run_v1_only def testNoGetNext(self): dataset = dataset_ops.Dataset.range(10) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:1", "/cpu:2"]) config = config_pb2.ConfigProto(device_count={"CPU": 3}) - with self.test_session(config=config) as sess: + with self.test_session(config=config): self.evaluate(multi_device_iterator.initializer) - @test_util.run_v1_only("b/120545219") + @test_util.run_v1_only def testBasic(self): dataset = dataset_ops.Dataset.range(10) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:1", "/cpu:2"]) - elem_on_1, elem_on_2 = multi_device_iterator.get_next() config = config_pb2.ConfigProto(device_count={"CPU": 3}) - with self.test_session(config=config) as sess: + with self.test_session(config=config): self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.assertEqual(i, self.evaluate(elem_on_1)) self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.evaluate(elem_on_1) self.evaluate(elem_on_2) - @test_util.run_v1_only("b/120545219") + @test_util.run_v1_only def testOneOnSameDevice(self): with ops.device("/cpu:0"): dataset = dataset_ops.Dataset.range(10) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:0", "/cpu:1"]) - elem_on_1, elem_on_2 = multi_device_iterator.get_next() config = config_pb2.ConfigProto(device_count={"CPU": 2}) - with self.test_session(config=config) as sess: + with self.test_session(config=config): self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.assertEqual(i, self.evaluate(elem_on_1)) self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.evaluate(elem_on_1) self.evaluate(elem_on_2) - @test_util.run_v1_only("b/120545219") + @test_util.run_v1_only def testRepeatDevices(self): with ops.device("/cpu:0"): dataset = dataset_ops.Dataset.range(20) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:1", "/cpu:2", "/cpu:1", "/cpu:2"]) - elements = multi_device_iterator.get_next() - elem_on_1, elem_on_2, elem_on_3, elem_on_4 = elements config = config_pb2.ConfigProto(device_count={"CPU": 3}) - with self.test_session(config=config) as sess: + with self.test_session(config=config): self.evaluate(multi_device_iterator.initializer) for i in range(0, 20, 4): + elements = multi_device_iterator.get_next() + elem_on_1, elem_on_2, elem_on_3, elem_on_4 = elements self.assertEqual(i, self.evaluate(elem_on_1)) self.assertEqual(i + 1, self.evaluate(elem_on_2)) self.assertEqual(i + 2, self.evaluate(elem_on_3)) self.assertEqual(i + 3, self.evaluate(elem_on_4)) with self.assertRaises(errors.OutOfRangeError): + elements = multi_device_iterator.get_next() + elem_on_1, elem_on_2, elem_on_3, elem_on_4 = elements self.evaluate(elem_on_1) self.evaluate(elem_on_2) self.evaluate(elem_on_3) self.evaluate(elem_on_4) - @test_util.run_v1_only("b/120545219") + @test_util.run_v1_only def testNotFullyDivisible(self): dataset = dataset_ops.Dataset.range(9) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:1", "/cpu:2"]) - elem_on_1, elem_on_2 = multi_device_iterator.get_next() config = config_pb2.ConfigProto(device_count={"CPU": 3}) - with self.test_session(config=config) as sess: + with self.test_session(config=config): self.evaluate(multi_device_iterator.initializer) for i in range(0, 8, 2): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.assertEqual(i, self.evaluate(elem_on_1)) self.assertEqual(i + 1, self.evaluate(elem_on_2)) + elem_on_1 = multi_device_iterator.get_next("/cpu:1") self.assertEqual(8, self.evaluate(elem_on_1)) with self.assertRaises(errors.OutOfRangeError): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.evaluate(elem_on_1) self.evaluate(elem_on_2) - @test_util.run_v1_only("b/120545219") + @test_util.run_v1_only def testGetNextAsOptional(self): + if context.executing_eagerly(): + return + dataset = dataset_ops.Dataset.range(9) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:1", "/cpu:2"]) @@ -154,26 +167,31 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): with self.assertRaises(errors.InvalidArgumentError): self.evaluate(elem_on_2_t) - @test_util.run_v1_only("b/120545219") + @test_util.run_v1_only def testUneven(self): dataset = dataset_ops.Dataset.range(10) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:1", "/cpu:2"], max_buffer_size=4) - elem_on_1, elem_on_2 = multi_device_iterator.get_next() config = config_pb2.ConfigProto(device_count={"CPU": 3}) - with self.test_session(config=config) as sess: + with self.test_session(config=config): self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): + elem_on_1 = multi_device_iterator.get_next("/cpu:1") self.assertEqual(i, self.evaluate(elem_on_1)) for i in range(0, 10, 2): + elem_on_2 = multi_device_iterator.get_next("/cpu:2") self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.evaluate(elem_on_1) self.evaluate(elem_on_2) - @test_util.run_v1_only("b/120545219") + @test_util.run_v1_only def testMultipleInitializations(self): + if context.executing_eagerly(): + return + with ops.device("/cpu:0"): epoch = array_ops.placeholder(dtypes.int64, shape=[]) dataset1 = dataset_ops.Dataset.from_tensors(epoch).repeat(1000) @@ -191,6 +209,7 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): self.assertEqual([(i, 0), (i, 1)], self.evaluate([elem_on_1, elem_on_2])) + @test_util.run_v1_only def testBasicGpu(self): if not test_util.is_gpu_available(): self.skipTest("No GPU available") @@ -198,18 +217,20 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): dataset = dataset_ops.Dataset.range(10) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:1", "/gpu:0"]) - elem_on_1, elem_on_2 = multi_device_iterator.get_next() config = config_pb2.ConfigProto(device_count={"CPU": 2, "GPU": 1}) - with self.test_session(config=config) as sess: + with self.test_session(config=config): self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.assertEqual(i, self.evaluate(elem_on_1)) self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.evaluate(elem_on_1) self.evaluate(elem_on_2) + @test_util.run_v1_only def testUnevenGpu(self): if not test_util.is_gpu_available(): self.skipTest("No GPU available") @@ -217,21 +238,24 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): dataset = dataset_ops.Dataset.range(10) multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:1", "/gpu:0"], max_buffer_size=4) - elem_on_1, elem_on_2 = multi_device_iterator.get_next() config = config_pb2.ConfigProto(device_count={"CPU": 2, "GPU": 1}) - with self.test_session(config=config) as sess: + with self.test_session(config=config): self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): + elem_on_1 = multi_device_iterator.get_next("/cpu:1") self.assertEqual(i, self.evaluate(elem_on_1)) for i in range(0, 10, 2): + elem_on_2 = multi_device_iterator.get_next("/gpu:0") self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.evaluate(elem_on_1) self.evaluate(elem_on_2) + @test_util.run_v1_only def testGetNextAsOptionalGpu(self): - if not test_util.is_gpu_available(): + if not test_util.is_gpu_available() or context.executing_eagerly(): self.skipTest("No GPU available") dataset = dataset_ops.Dataset.range(9) @@ -266,7 +290,7 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): with self.assertRaises(errors.InvalidArgumentError): self.evaluate(elem_on_2_t) - @test_util.run_v1_only("b/120545219") + @test_util.run_v1_only def testOptimization(self): dataset = dataset_ops.Dataset.range(10) dataset = dataset.apply(optimization.assert_next(["MemoryCacheImpl"])) @@ -279,18 +303,21 @@ class MultiDeviceIteratorTest(test_base.DatasetTestBase): multi_device_iterator = multi_device_iterator_ops.MultiDeviceIterator( dataset, ["/cpu:1", "/cpu:2"]) - elem_on_1, elem_on_2 = multi_device_iterator.get_next() config = config_pb2.ConfigProto(device_count={"CPU": 3}) - with self.test_session(config=config) as sess: + with self.test_session(config=config): self.evaluate(multi_device_iterator.initializer) for i in range(0, 10, 2): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.assertEqual(i, self.evaluate(elem_on_1)) self.assertEqual(i + 1, self.evaluate(elem_on_2)) with self.assertRaises(errors.OutOfRangeError): + elem_on_1, elem_on_2 = multi_device_iterator.get_next() self.evaluate(elem_on_1) self.evaluate(elem_on_2) if __name__ == "__main__": + ops.enable_eager_execution( + config=config_pb2.ConfigProto(device_count={"CPU": 3, "GPU": 1})) test.main() diff --git a/tensorflow/python/data/ops/multi_device_iterator_ops.py b/tensorflow/python/data/ops/multi_device_iterator_ops.py index 8192d53891..2682e4acd0 100644 --- a/tensorflow/python/data/ops/multi_device_iterator_ops.py +++ b/tensorflow/python/data/ops/multi_device_iterator_ops.py @@ -34,8 +34,7 @@ class _PerDeviceGenerator(dataset_ops.DatasetV2): """A `dummy` generator dataset.""" def __init__(self, shard_num, multi_device_iterator_resource, incarnation_id, - source_device, target_device, element_structure): - self._target_device = target_device + source_device, element_structure): self._structure = element_structure multi_device_iterator_string_handle = ( @@ -107,15 +106,14 @@ class _PerDeviceGenerator(dataset_ops.DatasetV2): ) self._finalize_captured_args = self._finalize_func.captured_inputs - with ops.device(self._target_device): - variant_tensor = gen_dataset_ops.generator_dataset( - self._init_captured_args, - self._next_captured_args, - self._finalize_captured_args, - init_func=self._init_func, - next_func=self._next_func, - finalize_func=self._finalize_func, - **dataset_ops.flat_structure(self)) + variant_tensor = gen_dataset_ops.generator_dataset( + self._init_captured_args, + self._next_captured_args, + self._finalize_captured_args, + init_func=self._init_func, + next_func=self._next_func, + finalize_func=self._finalize_func, + **dataset_ops.flat_structure(self)) super(_PerDeviceGenerator, self).__init__(variant_tensor) def _inputs(self): @@ -155,10 +153,6 @@ class MultiDeviceIterator(object): Raises: RuntimeError: If run in Eager mode. """ - if context.executing_eagerly(): - # TODO(rohanj): Fix this. Tracking bug: b/116467184 - raise RuntimeError("MultiDeviceIterator is not currently supported in " - "Eager mode.") self._dataset = dataset._apply_options() # pylint: disable=protected-access self._devices = devices self._source_device = source_device @@ -187,27 +181,36 @@ class MultiDeviceIterator(object): # Create the per device iterators. self._device_iterators = [] for i, device in enumerate(self._devices): - ds = _PerDeviceGenerator( - i, self._multi_device_iterator_resource, self._incarnation_id, - self._source_device_tensor, device, dataset._element_structure) # pylint: disable=protected-access - if prefetch_buffer_size > 0: - ds = ds.prefetch(prefetch_buffer_size) - # TODO(jsimsa): Enable auto-tuning and optimizations when supported for - # non-CPU devices. - options = dataset_ops.Options() - options.experimental_autotune = False - options.experimental_optimization.apply_default_optimizations = False - ds = ds.with_options(options) with ops.device(device): - self._device_iterators.append( - dataset_ops.make_initializable_iterator(ds)) - - device_iterator_initializers = [ - iterator.initializer for iterator in self._device_iterators - ] - self._initializer = control_flow_ops.group(*device_iterator_initializers) + ds = _PerDeviceGenerator( + i, self._multi_device_iterator_resource, self._incarnation_id, + self._source_device_tensor, dataset._element_structure) # pylint: disable=protected-access + if prefetch_buffer_size > 0: + ds = ds.prefetch(prefetch_buffer_size) + # TODO(jsimsa): Enable auto-tuning and optimizations when supported for + # non-CPU devices. + options = dataset_ops.Options() + options.experimental_autotune = False + options.experimental_optimization.apply_default_optimizations = False + ds = ds.with_options(options) + if context.executing_eagerly(): + self._device_iterators.append(dataset_ops.make_one_shot_iterator(ds)) + else: + self._device_iterators.append( + dataset_ops.make_initializable_iterator(ds)) + + if not context.executing_eagerly(): + device_iterator_initializers = [ + iterator.initializer for iterator in self._device_iterators + ] + self._initializer = control_flow_ops.group(*device_iterator_initializers) + + def get_next(self, device=None): + """Returns the next element given a `device`, else returns all in a list.""" + if device is not None: + index = self._devices.index(device) + return self._device_iterators[index].get_next() - def get_next(self): result = [] for i, device in enumerate(self._devices): with ops.device(device): @@ -224,6 +227,8 @@ class MultiDeviceIterator(object): @property def initializer(self): + if context.executing_eagerly(): + return control_flow_ops.no_op() return self._initializer @property -- GitLab From 0b63a3af2faf0f4b484c4830ab2b73878737fafe Mon Sep 17 00:00:00 2001 From: Anna R Date: Wed, 19 Dec 2018 16:44:12 -0800 Subject: [PATCH 0140/1765] Automated rollback of commit 4c7452c8c9b632d7ad7232099637e6fe388c3dd2 PiperOrigin-RevId: 226255352 --- .../lite/delegates/nnapi/nnapi_delegate.cc | 142 +- tensorflow/lite/nnapi/BUILD | 12 - tensorflow/lite/nnapi/NeuralNetworksShim.cc | 129 -- tensorflow/lite/nnapi/NeuralNetworksShim.h | 1204 +++++++++-------- tensorflow/lite/nnapi/nnapi_lib_test.cc | 90 -- tensorflow/lite/nnapi_delegate.cc | 135 +- 6 files changed, 803 insertions(+), 909 deletions(-) delete mode 100644 tensorflow/lite/nnapi/NeuralNetworksShim.cc delete mode 100644 tensorflow/lite/nnapi/nnapi_lib_test.cc diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc index a10a2ee963..7908bbf164 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc @@ -48,35 +48,55 @@ namespace { } while (0) namespace { +int32_t GetAndroidSdkVersion() { +#ifdef __ANDROID__ + const char* sdkProp = "ro.build.version.sdk"; + char sdkVersion[PROP_VALUE_MAX]; + int length = __system_property_get(sdkProp, sdkVersion); + if (length != 0) { + for (int i = 0; i < length; ++i) { + int digit = sdkVersion[i] - '0'; + if (digit < 0 || digit > 9) { + // Non-numeric SDK version, assume it's higher then expected; + return std::numeric_limits::max(); + } + } + return atoi(sdkVersion); + } +#endif // __ANDROID__ + return 0; +} + constexpr int32_t kMinSdkVersionForNNAPI = 27; constexpr int32_t kMinSdkVersionForNNAPI11 = 28; +static const int32_t kAndroidSdkVersion = GetAndroidSdkVersion(); + } // namespace // RAII NN API Model Destructor for use with std::unique_ptr struct NNFreeModel { void operator()(ANeuralNetworksModel* model) { - NnApiImplementation()->ANeuralNetworksModel_free(model); + ANeuralNetworksModel_free(model); } }; // RAII NN API Compilation Destructor for use with std::unique_ptr struct NNFreeCompilation { void operator()(ANeuralNetworksCompilation* model) { - NnApiImplementation()->ANeuralNetworksCompilation_free(model); + ANeuralNetworksCompilation_free(model); } }; // Manage NNAPI shared memory handle class NNMemory { public: - NNMemory(const NnApi* nnapi, const char* name, size_t size) { + NNMemory(const char* name, size_t size) { #ifdef __ANDROID__ - nnapi_ = nnapi; byte_size_ = size; fd_ = ASharedMemory_create(name, size); data_ptr_ = reinterpret_cast( mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0)); - nnapi_->ANeuralNetworksMemory_createFromFd(size, PROT_READ | PROT_WRITE, - fd_, 0, &nn_memory_handle_); + ANeuralNetworksMemory_createFromFd(size, PROT_READ | PROT_WRITE, fd_, 0, + &nn_memory_handle_); #endif } @@ -86,7 +106,7 @@ class NNMemory { munmap(data_ptr_, byte_size_); } if (nn_memory_handle_) { - nnapi_->ANeuralNetworksMemory_free(nn_memory_handle_); + ANeuralNetworksMemory_free(nn_memory_handle_); } if (fd_ > 0) close(fd_); #endif @@ -97,7 +117,6 @@ class NNMemory { private: #ifdef __ANDROID__ - const NnApi* nnapi_; int fd_ = 0; size_t byte_size_ = 0; #endif @@ -147,10 +166,9 @@ class OperandMapping { // operands for both tensors and parameters, and TFLite separates the two. class NNAPIOpBuilder { public: - NNAPIOpBuilder(const NnApi* nnapi, TfLiteContext* context, - OperandMapping* tensor_mapping, ANeuralNetworksModel* nn_model) - : nnapi_(nnapi), - context_(context), + NNAPIOpBuilder(TfLiteContext* context, OperandMapping* tensor_mapping, + ANeuralNetworksModel* nn_model) + : context_(context), operand_mapping_(tensor_mapping), nn_model_(nn_model) {} @@ -206,7 +224,7 @@ class NNAPIOpBuilder { .dimensionCount = dimension_count, .dimensions = dims.data()}; CHECK_NN(context_, - nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); int ann_operand = operand_mapping_->add_new_non_tensor_operand(); augmented_outputs_.push_back(ann_operand); return kTfLiteOk; @@ -223,7 +241,7 @@ class NNAPIOpBuilder { reinterpret_cast(tensor->dims->data), tensor->params.scale, tensor->params.zero_point}; CHECK_NN(context_, - nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); augmented_outputs_.push_back(ann_index); *ann_tensor_index_out = ann_index; @@ -280,11 +298,11 @@ class NNAPIOpBuilder { nn_type, static_cast(tensor->dims->size), reinterpret_cast(tensor->dims->data), scale, zeroPoint}; CHECK_NN(context_, - nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); if (tensor->allocation_type == kTfLiteMmapRo) { // TODO(b/80630405): Use NNAPIAllocation. - CHECK_NN(context_, nnapi_->ANeuralNetworksModel_setOperandValue( + CHECK_NN(context_, ANeuralNetworksModel_setOperandValue( nn_model_, ann_tensor_index, tensor->data.raw, tensor->bytes)); } @@ -296,7 +314,7 @@ class NNAPIOpBuilder { // Finish emitting the op (of type `type`) into the NN API. TfLiteStatus FinalizeAddOperation(ANeuralNetworksOperationType type) { // Actually add a NN API operation - CHECK_NN(context_, nnapi_->ANeuralNetworksModel_addOperation( + CHECK_NN(context_, ANeuralNetworksModel_addOperation( nn_model_, type, static_cast(augmented_inputs_.size()), augmented_inputs_.data(), @@ -312,9 +330,9 @@ class NNAPIOpBuilder { TfLiteStatus AddScalarOperand(T value, int32_t nn_type) { ANeuralNetworksOperandType operand_type{.type = nn_type}; CHECK_NN(context_, - nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); int ann_operand = operand_mapping_->add_new_non_tensor_operand(); - CHECK_NN(context_, nnapi_->ANeuralNetworksModel_setOperandValue( + CHECK_NN(context_, ANeuralNetworksModel_setOperandValue( nn_model_, ann_operand, &value, sizeof(T))); augmented_inputs_.push_back(ann_operand); return kTfLiteOk; @@ -326,18 +344,15 @@ class NNAPIOpBuilder { ANeuralNetworksOperandType operand_type{ .type = nn_type, .dimensionCount = 1, .dimensions = &num_values}; CHECK_NN(context_, - nnapi_->ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); + ANeuralNetworksModel_addOperand(nn_model_, &operand_type)); int ann_operand = operand_mapping_->add_new_non_tensor_operand(); CHECK_NN(context_, - nnapi_->ANeuralNetworksModel_setOperandValue( + ANeuralNetworksModel_setOperandValue( nn_model_, ann_operand, values, sizeof(T) * num_values)); augmented_inputs_.push_back(ann_operand); return kTfLiteOk; } - // Access to NNAPI. - const NnApi* const nnapi_; - // TfLiteContext for error handling. TfLiteContext* const context_; @@ -373,7 +388,7 @@ ANeuralNetworksOperationType BasicMappingFn( // The kernel that represents the node sub set of TF Lite being run on NN API. class NNAPIDelegateKernel { public: - NNAPIDelegateKernel() { nnapi_ = NnApiImplementation(); } + NNAPIDelegateKernel() = default; typedef ANeuralNetworksOperationType (*MappingFn)( const NNAPIOpMappingArgs& mapping_args); @@ -382,7 +397,7 @@ class NNAPIDelegateKernel { // when called. You can use this function to see if a node is supported // (i.e. that MappingFn is not nullptr). static MappingFn Map(TfLiteContext* context, int builtin_code, int version, - int android_sdk_version, TfLiteNode* node) { + TfLiteNode* node) { switch (builtin_code) { case kTfLiteBuiltinAdd: if (version == 1) { @@ -501,7 +516,7 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinSqueeze: - if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11) { + if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) { return [](const NNAPIOpMappingArgs& mapping_args) -> ANeuralNetworksOperationType { auto builtin = reinterpret_cast( @@ -617,7 +632,7 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinSub: - if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11 && + if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11 && context->tensors[node->inputs->data[0]].type == kTfLiteFloat32) { // NNAPI only support float sub. return [](const NNAPIOpMappingArgs& mapping_args) @@ -630,7 +645,7 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinDiv: - if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11 && + if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11 && context->tensors[node->inputs->data[0]].type == kTfLiteFloat32) { // NNAPI only support float div. return [](const NNAPIOpMappingArgs& mapping_args) @@ -643,7 +658,7 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinPad: - if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11 && + if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11 && node->inputs->size == 2 && context->tensors[node->inputs->data[0]].type == kTfLiteFloat32) { // NNAPI does not support specifying the padding value. @@ -653,12 +668,12 @@ class NNAPIDelegateKernel { } break; case kTfLiteBuiltinSpaceToBatchNd: - if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11) { + if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) { return BasicMappingFn; } break; case kTfLiteBuiltinStridedSlice: - if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11) { + if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) { return [](const NNAPIOpMappingArgs& mapping_args) -> ANeuralNetworksOperationType { auto builtin = reinterpret_cast( @@ -676,7 +691,7 @@ class NNAPIDelegateKernel { // dimensions. // TODO(b/110888333): Support dynamically-sized tensors in delegates. if ((version == 1) && - (android_sdk_version >= kMinSdkVersionForNNAPI11) && + (kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) && (node->inputs->size > 1) && (context->tensors[node->inputs->data[1]].allocation_type == kTfLiteMmapRo)) { @@ -774,7 +789,7 @@ class NNAPIDelegateKernel { break; case kTfLiteBuiltinMean: // NNAPI does not support generating a scalar as output for MEAN. - if (version == 1 && android_sdk_version >= kMinSdkVersionForNNAPI11 && + if (version == 1 && kAndroidSdkVersion >= kMinSdkVersionForNNAPI11 && context->tensors[node->inputs->data[0]].type == kTfLiteFloat32 && context->tensors[node->outputs->data[0]].dims->size > 0) { return [](const NNAPIOpMappingArgs& mapping_args) @@ -818,7 +833,7 @@ class NNAPIDelegateKernel { if (!nn_model_) { ANeuralNetworksModel* model; - CHECK_NN(context, nnapi_->ANeuralNetworksModel_create(&model)); + CHECK_NN(context, ANeuralNetworksModel_create(&model)); nn_model_.reset(model); TF_LITE_ENSURE_STATUS( @@ -827,9 +842,9 @@ class NNAPIDelegateKernel { if (!nn_compilation_) { ANeuralNetworksCompilation* compilation; - CHECK_NN(context, nnapi_->ANeuralNetworksCompilation_create( - nn_model_.get(), &compilation)); - CHECK_NN(context, nnapi_->ANeuralNetworksCompilation_finish(compilation)); + CHECK_NN(context, ANeuralNetworksCompilation_create(nn_model_.get(), + &compilation)); + CHECK_NN(context, ANeuralNetworksCompilation_finish(compilation)); nn_compilation_.reset(compilation); } return kTfLiteOk; @@ -837,8 +852,8 @@ class NNAPIDelegateKernel { TfLiteStatus Invoke(TfLiteContext* context, TfLiteNode* node) { ANeuralNetworksExecution* execution = nullptr; - CHECK_NN(context, nnapi_->ANeuralNetworksExecution_create( - nn_compilation_.get(), &execution)); + CHECK_NN(context, ANeuralNetworksExecution_create(nn_compilation_.get(), + &execution)); // Set the input tensor buffers. Note: we access tflite tensors using // absolute indices but NN api indices inputs by relative indices. @@ -856,7 +871,7 @@ class NNAPIDelegateKernel { // copy data to pre-allocated shared memory. memcpy(nn_input_memory_->get_data_ptr() + input_offset, tensor->data.raw, tensor->bytes); - CHECK_NN(context, nnapi_->ANeuralNetworksExecution_setInputFromMemory( + CHECK_NN(context, ANeuralNetworksExecution_setInputFromMemory( execution, relative_input_index, nullptr, nn_input_memory_->get_handle(), input_offset, tensor->bytes)); @@ -870,7 +885,7 @@ class NNAPIDelegateKernel { size_t output_offset = 0; for (auto output_index : TfLiteIntArrayView(node->outputs)) { TfLiteTensor* tensor = &context->tensors[output_index]; - CHECK_NN(context, nnapi_->ANeuralNetworksExecution_setOutputFromMemory( + CHECK_NN(context, ANeuralNetworksExecution_setOutputFromMemory( execution, relative_output_index, nullptr, nn_output_memory_->get_handle(), output_offset, tensor->bytes)); @@ -886,18 +901,17 @@ class NNAPIDelegateKernel { // Here we are using a deep copy for state_in tensors so that we are not // reading and writing into the same buffer during a invocation. // TODO(110369471): using double shared buffer to minimize the copies. - CHECK_NN(context, nnapi_->ANeuralNetworksExecution_setOutput( + CHECK_NN(context, ANeuralNetworksExecution_setOutput( execution, relative_output_index, nullptr, tensor->data.raw, tensor->bytes)); relative_output_index++; } // Invoke ANN in blocking fashion. ANeuralNetworksEvent* event = nullptr; - CHECK_NN(context, - nnapi_->ANeuralNetworksExecution_startCompute(execution, &event)); - CHECK_NN(context, nnapi_->ANeuralNetworksEvent_wait(event)); - nnapi_->ANeuralNetworksEvent_free(event); - nnapi_->ANeuralNetworksExecution_free(execution); + CHECK_NN(context, ANeuralNetworksExecution_startCompute(execution, &event)); + CHECK_NN(context, ANeuralNetworksEvent_wait(event)); + ANeuralNetworksEvent_free(event); + ANeuralNetworksExecution_free(execution); // copy results from shared memory to the destination. output_offset = 0; @@ -912,8 +926,6 @@ class NNAPIDelegateKernel { } private: - // Access to NNApi. - const NnApi* nnapi_; // ANN API state. std::unique_ptr nn_model_; std::unique_ptr @@ -934,7 +946,7 @@ class NNAPIDelegateKernel { // The operand builder allows creating a single op. We create it at this // reduced power position rather than in the for loop to avoid reallocating // the vectors. - NNAPIOpBuilder builder(nnapi_, context, &operand_mapping_, nn_model_.get()); + NNAPIOpBuilder builder(context, &operand_mapping_, nn_model_.get()); // Add Tensors // allocate outside to avoid realloc for (auto node_index : nodes_) { @@ -957,10 +969,9 @@ class NNAPIDelegateKernel { } } // Get op type and operands - int nn_op_type = Map( - context, reg->builtin_code, reg->version, nnapi_->android_sdk_version, - node)({context, &builder, node, &model_state_outputs_, - &model_state_tfl_inputs_}); + int nn_op_type = Map(context, reg->builtin_code, reg->version, node)( + {context, &builder, node, &model_state_outputs_, + &model_state_tfl_inputs_}); // Map outputs to NN API tensor indices. for (auto output_index : TfLiteIntArrayView(node->outputs)) { TF_LITE_ENSURE_STATUS(builder.AddTensorOutput(output_index)); @@ -1005,25 +1016,24 @@ class NNAPIDelegateKernel { } // Tell ANN to declare inputs/outputs - CHECK_NN(context, nnapi_->ANeuralNetworksModel_identifyInputsAndOutputs( + CHECK_NN(context, ANeuralNetworksModel_identifyInputsAndOutputs( nn_model_.get(), inputs.size(), inputs.data(), outputs.size(), outputs.data())); // Set relaxed computation mode for fp32 if possible. - if (nnapi_->android_sdk_version >= kMinSdkVersionForNNAPI11) { + if (kAndroidSdkVersion >= kMinSdkVersionForNNAPI11) { CHECK_NN(context, - nnapi_->ANeuralNetworksModel_relaxComputationFloat32toFloat16( + ANeuralNetworksModel_relaxComputationFloat32toFloat16( nn_model_.get(), context->allow_fp32_relax_to_fp16)); } // Finalize the model - CHECK_NN(context, nnapi_->ANeuralNetworksModel_finish(nn_model_.get())); + CHECK_NN(context, ANeuralNetworksModel_finish(nn_model_.get())); // Create shared memory pool for inputs and outputs. - nn_input_memory_.reset( - new NNMemory(nnapi_, "input_pool", total_input_byte_size)); + nn_input_memory_.reset(new NNMemory("input_pool", total_input_byte_size)); nn_output_memory_.reset( - new NNMemory(nnapi_, "output_pool", total_output_byte_size)); + new NNMemory("output_pool", total_output_byte_size)); return kTfLiteOk; } @@ -1039,9 +1049,7 @@ TfLiteDelegate* NnApiDelegate() { .Prepare = [](TfLiteContext* context, TfLiteDelegate* delegate) -> TfLiteStatus { // Do not check nodes_ if NN API is unavailable. - const NnApi* nnapi = NnApiImplementation(); - if (nnapi->android_sdk_version < kMinSdkVersionForNNAPI || - !nnapi->nnapi_exists) { + if (kAndroidSdkVersion < kMinSdkVersionForNNAPI || !NNAPIExists()) { return kTfLiteOk; } @@ -1054,7 +1062,6 @@ TfLiteDelegate* NnApiDelegate() { TfLiteIntArray* plan; TF_LITE_ENSURE_STATUS(context->GetExecutionPlan(context, &plan)); - int android_sdk_version = NnApiImplementation()->android_sdk_version; // Check for every node if it is supported // TODO(b/80625235): Fix this to do more careful checking of versioning. for (int node_index : TfLiteIntArrayView(plan)) { @@ -1063,8 +1070,7 @@ TfLiteDelegate* NnApiDelegate() { TF_LITE_ENSURE_STATUS(context->GetNodeAndRegistration( context, node_index, &node, ®istration)); if (NNAPIDelegateKernel::Map(context, registration->builtin_code, - registration->version, - android_sdk_version, node)) { + registration->version, node)) { supported_nodes.push_back(node_index); } } diff --git a/tensorflow/lite/nnapi/BUILD b/tensorflow/lite/nnapi/BUILD index 390c3730cb..467a2b7a7b 100644 --- a/tensorflow/lite/nnapi/BUILD +++ b/tensorflow/lite/nnapi/BUILD @@ -6,20 +6,8 @@ package(default_visibility = [ cc_library( name = "nnapi_lib", - srcs = [ - "NeuralNetworksShim.cc", - ], hdrs = [ "NeuralNetworksShim.h", ], linkopts = ["-ldl"], ) - -cc_test( - name = "nnapi_lib_test", - srcs = ["nnapi_lib_test.cc"], - deps = [ - "//tensorflow/lite/nnapi:nnapi_lib", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/tensorflow/lite/nnapi/NeuralNetworksShim.cc b/tensorflow/lite/nnapi/NeuralNetworksShim.cc deleted file mode 100644 index 6858fbdd57..0000000000 --- a/tensorflow/lite/nnapi/NeuralNetworksShim.cc +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -#include "tensorflow/lite/nnapi/NeuralNetworksShim.h" - -#include - -#ifdef __ANDROID__ -#include -#include -#include -#endif - -#define NNAPI_LOG(format, ...) fprintf(stderr, format "\n", __VA_ARGS__); - -namespace { - -#ifdef __ANDROID__ -int32_t GetAndroidSdkVersion() { - const char* sdkProp = "ro.build.version.sdk"; - char sdkVersion[PROP_VALUE_MAX]; - int length = __system_property_get(sdkProp, sdkVersion); - if (length != 0) { - int32_t result = 0; - for (int i = 0; i < length; ++i) { - int digit = sdkVersion[i] - '0'; - if (digit < 0 || digit > 9) { - // Non-numeric SDK version, assume it's higher than expected; - return 0xffff; - } - result = result * 10 + digit; - } - return result; - } - return 0; -} - -void* LoadFunction(void* handle, const char* name) { - if (handle == nullptr) { - return nullptr; - } - void* fn = dlsym(handle, name); - if (fn == nullptr) { - NNAPI_LOG("nnapi error: unable to open function %s", name); - } - return fn; -} - -#define LOAD_FUNCTION(handle, name) \ - nnapi.name = reinterpret_cast(LoadFunction(handle, #name)); - -#else - -#define LOAD_FUNCTION(handle, name) nnapi.name = nullptr; - -#endif - -const NnApi LoadNnApi() { - NnApi nnapi = {}; - -#ifdef __ANDROID__ - // TODO: change RTLD_LOCAL? Assumes there can be multiple instances of nn - // api RT - void* libneuralnetworks = - dlopen("libneuralnetworks.so", RTLD_LAZY | RTLD_LOCAL); - if (libneuralnetworks == nullptr) { - NNAPI_LOG("nnapi error: unable to open library %s", "libneuralnetworks.so"); - } - void* libandroid = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL); - if (libneuralnetworks == nullptr) { - NNAPI_LOG("nnapi error: unable to open library %s", "libandroid.so"); - } - nnapi.nnapi_exists = libneuralnetworks != nullptr; - nnapi.android_sdk_version = GetAndroidSdkVersion(); -#else - nnapi.nnapi_exists = false; - nnapi.android_sdk_version = 0; -#endif - - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_createFromFd); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_free); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_create); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_free); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_finish); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperand); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValue); - LOAD_FUNCTION(libneuralnetworks, - ANeuralNetworksModel_setOperandValueFromMemory); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperation); - LOAD_FUNCTION(libneuralnetworks, - ANeuralNetworksModel_identifyInputsAndOutputs); - LOAD_FUNCTION(libneuralnetworks, - ANeuralNetworksModel_relaxComputationFloat32toFloat16); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_create); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_free); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_setPreference); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_finish); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_create); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_free); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInput); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInputFromMemory); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutput); - LOAD_FUNCTION(libneuralnetworks, - ANeuralNetworksExecution_setOutputFromMemory); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_startCompute); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_wait); - LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_free); - LOAD_FUNCTION(libandroid, ASharedMemory_create); - - return nnapi; -} - -} // namespace - -const NnApi* NnApiImplementation() { - static const NnApi nnapi = LoadNnApi(); - return &nnapi; -} diff --git a/tensorflow/lite/nnapi/NeuralNetworksShim.h b/tensorflow/lite/nnapi/NeuralNetworksShim.h index de44852666..c39502f4ac 100644 --- a/tensorflow/lite/nnapi/NeuralNetworksShim.h +++ b/tensorflow/lite/nnapi/NeuralNetworksShim.h @@ -20,6 +20,64 @@ limitations under the License. #include #include +// helpers + +#define NNAPI_LOG(format, ...) fprintf(stderr, format "\n", __VA_ARGS__); +#define LOAD_FUNCTION(name) \ + static name##_fn fn = reinterpret_cast(loadFunction(#name)); +#define EXECUTE_FUNCTION(...) \ + if (fn != nullptr) { \ + fn(__VA_ARGS__); \ + } +#define EXECUTE_FUNCTION_RETURN(...) return fn != nullptr ? fn(__VA_ARGS__) : 0; + +inline void* loadLibrary(const char* name) { + // TODO: change RTLD_LOCAL? Assumes there can be multiple instances of nn + // api RT + void* handle = nullptr; +#ifdef __ANDROID__ + handle = dlopen(name, RTLD_LAZY | RTLD_LOCAL); + if (handle == nullptr) { + NNAPI_LOG("nnapi error: unable to open library %s", name); + } +#endif + return handle; +} + +typedef int (*ASharedMemory_create_fn)(const char* name, size_t size); + +// ASharedMemory_create was added in Android 8.0, so safe to use with NNAPI +// which was added in 8.1. +inline int ASharedMemory_create(const char* name, size_t size) { + static void* handle = loadLibrary("libandroid.so"); + static ASharedMemory_create_fn fn = + handle != nullptr ? reinterpret_cast( + dlsym(handle, "ASharedMemory_create")) + : nullptr; + return fn(name, size); +} + +inline void* getLibraryHandle() { + static void* handle = loadLibrary("libneuralnetworks.so"); + return handle; +} + +inline void* loadFunction(const char* name) { + void* fn = nullptr; + if (getLibraryHandle() != nullptr) { + fn = dlsym(getLibraryHandle(), name); + } + if (fn == nullptr) { + NNAPI_LOG("nnapi error: unable to open function %s", name); + } + return fn; +} + +inline bool NNAPIExists() { + static bool nnapi_is_available = getLibraryHandle(); + return nnapi_is_available; +} + // NN api types based on NNAPI header file // https://developer.android.com/ndk/reference/group/neural-networks @@ -349,564 +407,606 @@ typedef int (*ANeuralNetworksEvent_wait_fn)(ANeuralNetworksEvent* event); typedef void (*ANeuralNetworksEvent_free_fn)(ANeuralNetworksEvent* event); -typedef int (*ASharedMemory_create_fn)(const char* name, size_t size); +/** + * Creates a shared memory object from a file descriptor. + * + * The shared memory is backed by a file descriptor via mmap. + * See {@link ANeuralNetworksMemory} for a description on how to use + * this shared memory. + * + * @param size The requested size in bytes. + * Must not be larger than the file size. + * @param prot The desired memory protection for the mapping. + * It is either PROT_NONE or the bitwise OR of one or + * more of the following flags: PROT_READ, PROT_WRITE. + * @param fd The requested file descriptor. + * The file descriptor has to be mmap-able. The file + * descriptor will be duplicated. + * @param offset The offset to the beginning of the file of the area to map. + * The offset has to be aligned to a page size. + * @param memory The memory object to be created. + * Set to NULL if unsuccessful. + * + * @return ANEURALNETWORKS_NO_ERROR if the request completed normally. + */ +inline int ANeuralNetworksMemory_createFromFd(size_t size, int protect, int fd, + size_t offset, + ANeuralNetworksMemory** memory) { + LOAD_FUNCTION(ANeuralNetworksMemory_createFromFd); + EXECUTE_FUNCTION_RETURN(size, protect, fd, offset, memory); +} -struct NnApi { - bool nnapi_exists; - int32_t android_sdk_version; - - /** - * Creates a shared memory object from a file descriptor. - * - * The shared memory is backed by a file descriptor via mmap. - * See {@link ANeuralNetworksMemory} for a description on how to use - * this shared memory. - * - * @param size The requested size in bytes. - * Must not be larger than the file size. - * @param prot The desired memory protection for the mapping. - * It is either PROT_NONE or the bitwise OR of one or - * more of the following flags: PROT_READ, PROT_WRITE. - * @param fd The requested file descriptor. - * The file descriptor has to be mmap-able. The file - * descriptor will be duplicated. - * @param offset The offset to the beginning of the file of the area to map. - * The offset has to be aligned to a page size. - * @param memory The memory object to be created. - * Set to NULL if unsuccessful. - * - * @return ANEURALNETWORKS_NO_ERROR if the request completed normally. - */ - int (*ANeuralNetworksMemory_createFromFd)(size_t size, int protect, int fd, - size_t offset, - ANeuralNetworksMemory** memory); - - /** - * Delete a memory object. - * - * Destroys the object used by the run time to keep track of the memory. - * This will free the underlying actual memory if no other code has open - * handles to this memory. - * - * @param memory The memory object to be freed. - */ - void (*ANeuralNetworksMemory_free)(ANeuralNetworksMemory* memory); - - /** - * Create an empty {@link ANeuralNetworksModel}. - * - *

    This only creates the object. Computation is performed once - * {@link ANeuralNetworksExecution_startCompute} is invoked. - * - * The model should be constructed with calls to - * {@link ANeuralNetworksModel_addOperation} and - * {@link ANeuralNetworksModel_addOperand} - * - *

    {@link ANeuralNetworksModel_finish} should be called once the model - * has been fully constructed.

    - * - *

    {@link ANeuralNetworksModel_free} should be called once the model - * is no longer needed.

    - * - * @param model The {@link ANeuralNetworksModel} to be created. - * Set to NULL if unsuccessful. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ - int (*ANeuralNetworksModel_create)(ANeuralNetworksModel** model); - - /** - * Destroy a model. - * - * The model need not have been finished by a call to - * {@link ANeuralNetworksModel_finish}. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be destroyed. Passing NULL is acceptable and - * results in no operation. - */ - void (*ANeuralNetworksModel_free)(ANeuralNetworksModel* model); - - /** - * Indicate that we have finished modifying a model. Required before - * calling {@link ANeuralNetworksCompilation_compile}. - * - * An application is responsible to make sure that no other thread uses - * the model at the same time. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be finished. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ - int (*ANeuralNetworksModel_finish)(ANeuralNetworksModel* model); - - /** - * Add an operand to a model. - * - * The order in which the operands are added is important. The first one added - * to a model will have the index value 0, the second 1, etc. These indexes - * are used as operand identifiers in - * {@link ANeuralNetworksModel_addOperation}, - * {@link ANeuralNetworksExecution_setInput}, - * {@link ANeuralNetworksExecution_setInputFromMemory}, - * {@link ANeuralNetworksExecution_setOutput}, - * {@link ANeuralNetworksExecution_setOutputFromMemory} and - * {@link ANeuralNetworksExecution_setOperandValue}. - * - * To build a model that can accommodate inputs of various sizes, as you may - * want to do for a CNN, set the size of the dimensions that will vary at run - * time to 0. If you do so, provide the full dimensions when calling - * {@link ANeuralNetworksExecution_setInput} or {@link - * ANeuralNetworksExecution_setInputFromMemory}. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be modified. - * @param type The {@link ANeuralNetworksOperandType} that describes the shape - * of the operand. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ - int (*ANeuralNetworksModel_addOperand)( - ANeuralNetworksModel* model, const ANeuralNetworksOperandType* type); - - /** - * Sets an operand to a constant value. - * - * For scalar values, the content of buffer is copied into the model. - * - * For tensor values, a pointer to the buffer is stored within the model. - * The application is responsible for not changing the content of this region - * until all executions using this model have completed. As the data may - * be copied during processing, modifying the data after this call yields - * undefined results. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be modified. - * @param index The index of the model operand we're setting. - * @param buffer A pointer to the data to use. - * @param length The size in bytes of the data value. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ - int (*ANeuralNetworksModel_setOperandValue)(ANeuralNetworksModel* model, - int32_t index, const void* buffer, - size_t length); - - /** - * Sets an operand to a value stored in a memory object. - * - * The content of the memory is not copied. A reference to that memory is - * stored inside the model. The application is responsible for not changing - * the content of the memory region until all executions using this model have - * completed. - * As the data may be copied during processing, modifying the data after this - * call yields undefined results. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @param model The model to be modified. - * @param index The index of the model operand we're setting. - * @param buffer A pointer to the data to use. - * @param memory The memory containing the data. - * @param offset This specifies the location of the data within the memory. - * The offset is in bytes from the start of memory. - * @param length The size in bytes of the data value. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ - int (*ANeuralNetworksModel_setOperandValueFromMemory)( - ANeuralNetworksModel* model, int32_t index, - const ANeuralNetworksMemory* memory, size_t offset, size_t length); - - /** - * Add an operation to a model. - * - * @param model The model to be modified. - * @param type The type of the operation. - * @param inputCount The number of entries in the inputs array. - * @param inputs An array of indexes identifying each operand. - * @param outputCount The number of entries in the outputs array. - * @param outputs An array of indexes identifying each operand. - * - * The operands specified by inputs and outputs must have been - * previously added by calls to {@link ANeuralNetworksModel_addOperand}. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ - int (*ANeuralNetworksModel_addOperation)(ANeuralNetworksModel* model, - ANeuralNetworksOperationType type, - uint32_t inputCount, - const uint32_t* inputs, - uint32_t outputCount, - const uint32_t* outputs); - - /** - * Specifies which operands will be the model's inputs and outputs. - * - * An operand cannot be used for both input and output. Doing so will - * return an error. - * - * @param model The model to be modified. - * @param inputCount The number of entries in the inputs array. - * @param inputs An array of indexes identifying the input operands. - * @param outputCount The number of entries in the outputs array. - * @param outputs An array of indexes identifying the output operands. - * - * The operands specified by inputs and outputs must have been - * previously added by calls to {@link ANeuralNetworksModel_addOperand}. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - * - */ - int (*ANeuralNetworksModel_identifyInputsAndOutputs)( - ANeuralNetworksModel* model, uint32_t inputCount, const uint32_t* inputs, - uint32_t outputCount, const uint32_t* outputs); - - /** - * Specifies whether {@link ANEURALNETWORKS_TENSOR_FLOAT32} is allowed to be - * calculated with range and/or precision as low as that of the - * IEEE 754 16-bit floating-point format. By default, - * {@link ANEURALNETWORKS_TENSOR_FLOAT32} must be calculated using at least - * the range and precision of the IEEE 754 32-bit floating-point format. - * - * @param model The model to be modified. - * @param allow 'true' indicates {@link ANEURALNETWORKS_TENSOR_FLOAT32} may be - * calculated with range and/or precision as low as that of the - * IEEE 754 16-bit floating point format. 'false' indicates - * {@link ANEURALNETWORKS_TENSOR_FLOAT32} must be calculated - * using at least the range and precision of the IEEE 754 32-bit - * floating point format. - * - * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has - * been called will return an error. - * - * Available since API level 28. - * - * See {@link ANeuralNetworksModel} for information on multithreaded usage. - */ - int (*ANeuralNetworksModel_relaxComputationFloat32toFloat16)( - ANeuralNetworksModel* model, bool allow); - - /** - * Create a {@link ANeuralNetworksCompilation} to compile the given model. - * This only creates the object. Compilation is only performed once - * {@link ANeuralNetworksCompilation_start} is invoked. - * - *

    The provided model must outlive the compilation.

    - * - * The model must already have been finished by a call to - * {@link ANeuralNetworksModel_finish}. - * - * See {@link ANeuralNetworksCompilation} for information on multithreaded - * usage. - * - * @param model The {@link ANeuralNetworksModel} to be compiled. - * @param compilation The newly created object or NULL if unsuccessful. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA - * if the model is invalid. - */ - int (*ANeuralNetworksCompilation_create)( - ANeuralNetworksModel* model, ANeuralNetworksCompilation** compilation); - - /** - * Destroy a compilation. - * - *

    If called on a compilation for which - * {@link ANeuralNetworksCompilation_start} has been called, the - * function will return immediately but will mark the compilation to be - * deleted once the compilation completes. The - * {@link ANeuralNetworksCompilation_wait} will return ERROR_DELETED. - * - * See {@link ANeuralNetworksCompilation} for information on multithreaded - * usage. - * - * @param compilation The compilation to be destroyed. Passing NULL is - * acceptable and results in no operation. - */ - void (*ANeuralNetworksCompilation_free)( - ANeuralNetworksCompilation* compilation); - - /** - * Sets the execution preference. - * - *

    Provides guidance to the runtime when trade-offs are possible.

    - * - * See {@link ANeuralNetworksCompilation} for information on multithreaded - * usage. - * - * @param compilation The compilation to be modified. - * @param preference Either {@link PREFER_LOW_POWER}, - * {@link PREFER_SINGLE_FAST_ANSWER}, or - * {@link PREFER_SUSTAINED_SPEED}. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ - int (*ANeuralNetworksCompilation_setPreference)( - ANeuralNetworksCompilation* compilation, int32_t preference); - - /** - * Waits until the compilation completes. - * - * More than one thread can wait on a compilation. When the compilation - * completes, all threads will be released. - * - * See {@link ANeuralNetworksCompilation} for information on multithreaded - * usage. - * - * @return ANEURALNETWORKS_NO_ERROR if the compilation completed normally. - */ - int (*ANeuralNetworksCompilation_finish)( - ANeuralNetworksCompilation* compilation); - - /** - * Create a {@link ANeuralNetworksExecution} to apply the given compilation. - * This only creates the object. Computation is only performed once - * {@link ANeuralNetworksExecution_startCompute} is invoked. - * - *

    The provided compilation must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded - * usage. - * - * @param compilation The {@link ANeuralNetworksCompilation} to be evaluated. - * @param execution The newly created object or NULL if unsuccessful. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA - * if the compilation is invalid. - */ - int (*ANeuralNetworksExecution_create)( - ANeuralNetworksCompilation* compilation, - ANeuralNetworksExecution** execution); - - /** - * Destroy an execution. - * - *

    If called on an execution for which - * {@link ANeuralNetworksExecution_startCompute} has been called, the - * function will return immediately but will mark the execution to be deleted - * once the computation completes. The {link ANeuralNetworksExecution_wait} - * will return ANEURALNETWORKS_ERROR_DELETED. - * - * See {@link ANeuralNetworksExecution} for information on multithreaded - * usage. - * - * @param execution The execution to be destroyed. Passing NULL is acceptable - * and results in no operation. - */ - void (*ANeuralNetworksExecution_free)(ANeuralNetworksExecution* execution); - - /** - * Associate a user buffer with an input of the model of the - * {@link ANeuralNetworksExecution}. - * - *

    The provided buffer must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded - * usage. - * - * @param execution The execution to be modified. - * @param index The index of the input argument we are setting. It is - * an index into the lists passed to - * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is - * not the index associated with {@link - * ANeuralNetworksModel_addOperand}. - * @param type The type of the operand. This should be used to specify the - * dimensions that were set to 0 when the operand was added to the - * model. All other properties of the type must be the same as - * specified in the model. If the type is the same as specified - * when the model was built, NULL can be passed. - * @param buffer The buffer containing the data. - * @param length The length in bytes of the buffer. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if - * the name is not recognized or the buffer is too small for the input. - */ - int (*ANeuralNetworksExecution_setInput)( - ANeuralNetworksExecution* execution, int32_t index, - const ANeuralNetworksOperandType* type, const void* buffer, - size_t length); - - /** - * Associate part of a memory object with an input of the model of the - * {@link ANeuralNetworksExecution}. - * - *

    The provided memory must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded - * usage. - * - * @param execution The execution to be modified. - * @param index The index of the input argument we are setting. It is - * an index into the lists passed to - * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is - * not the index associated with {@link - * ANeuralNetworksModel_addOperand}. - * @param type The type of the operand. This can be used to specify the - * dimensions that were set to 0 when the operand was added to the - * model. All other values must be the same as specified in the - * model. If the type is the same as specified when the model - * was built, NULL can be passed. - * @param memory The memory containing the data. - * @param offset This specifies the location of the data within the memory. - * The offset is in bytes from the start of memory. - * @param length The size in bytes of the data value. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if - * the name is not recognized or the buffer is too small for the input. - */ - int (*ANeuralNetworksExecution_setInputFromMemory)( - ANeuralNetworksExecution* execution, int32_t index, - const ANeuralNetworksOperandType* type, - const ANeuralNetworksMemory* memory, size_t offset, size_t length); - - /** - * Associate a user buffer with an output of the model of the - * {@link ANeuralNetworksExecution}. - * - *

    The provided buffer must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded - * usage. - * - * @param execution The execution to be modified. - * @param index The index of the output argument we are setting. It is - * an index into the lists passed to - * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is - * not the index associated with {@link - * ANeuralNetworksModel_addOperand}. - * @param type The type of the operand. This can be used to specify the - * dimensions that were set to 0 when the operand was added to the - * model. All other values must be the same as specified in the - * model. If the type is the same as specified when the model - * was built, NULL can be passed. - * @param buffer The buffer where the data is to be written. - * @param length The length in bytes of the buffer. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if - * the name is not recognized or the buffer is too small for the output. - */ - int (*ANeuralNetworksExecution_setOutput)( - ANeuralNetworksExecution* execution, int32_t index, - const ANeuralNetworksOperandType* type, void* buffer, size_t length); - - /** - * Associate part of a memory object with an output of the model of the - * {@link ANeuralNetworksExecution}. - * - *

    The provided memory must outlive the execution.

    - * - * See {@link ANeuralNetworksExecution} for information on multithreaded - * usage. - * - * @param execution The execution to be modified. - * @param index The index of the output argument we are setting. It is - * an index into the lists passed to - * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is - * not the index associated with {@link - * ANeuralNetworksModel_addOperand}. - * @param type The type of the operand. This can be used to specify the - * dimensions that were set to 0 when the operand was added to the - * model. All other values must be the same as specified in the - * model. If the type is the same as specified when the model - * was built, NULL can be passed. - * @param memory The memory where the data is to be stored. - * @param offset This specifies the location of the data within the memory. - * The offset is in bytes from the start of memory. - * @param length The length in bytes of the data value. - * - * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if - * the name is not recognized or the buffer is too small for the output. - */ - int (*ANeuralNetworksExecution_setOutputFromMemory)( - ANeuralNetworksExecution* execution, int32_t index, - const ANeuralNetworksOperandType* type, - const ANeuralNetworksMemory* memory, size_t offset, size_t length); - - /** - * Schedule evaluation of the execution. - * - *

    Schedules evaluation of the execution. Once the model has been - * applied and the outputs are ready to be consumed, the execution will be - * signaled. Use {@link ANeuralNetworksExecution_wait} to wait for that - * signal. - *

    - * - * Multiple executions can be scheduled and evaluated concurrently, and - * compilations can be performed concurrently with executions. The runtime - * makes no guarantee on the ordering of the completion of compilations and - * executions. If it's important to the application, the application should - * enforce the ordering by using {@link ANeuralNetworksCompilation_wait} and - * {@link ANeuralNetworksExecution_wait}. - * - * ANeuralNetworksExecution_wait must be called to recuperate the resources - * used by the execution. - * - * See {@link ANeuralNetworksExecution} for information on multithreaded - * usage. - * - * @param execution The execution to be scheduled and executed. - * - * @return ANEURALNETWORKS_NO_ERROR if successful. - */ - int (*ANeuralNetworksExecution_startCompute)( - ANeuralNetworksExecution* execution, ANeuralNetworksEvent** event); - - /** - * Waits until the execution completes. - * - * More than one thread can wait on an event. When the execution completes, - * all threads will be released. - * - * See {@link ANeuralNetworksExecution} for information on multithreaded - * usage. - * - * @return ANEURALNETWORKS_NO_ERROR if the execution completed normally. - */ - int (*ANeuralNetworksEvent_wait)(ANeuralNetworksEvent* event); +/** + * Delete a memory object. + * + * Destroys the object used by the run time to keep track of the memory. + * This will free the underlying actual memory if no other code has open + * handles to this memory. + * + * @param memory The memory object to be freed. + */ +inline void ANeuralNetworksMemory_free(ANeuralNetworksMemory* memory) { + LOAD_FUNCTION(ANeuralNetworksMemory_free); + EXECUTE_FUNCTION(memory); +} - /** - * Destroys the event. - * - * See {@link ANeuralNetworksExecution} for information on multithreaded - * usage. - */ - void (*ANeuralNetworksEvent_free)(ANeuralNetworksEvent* event); +/** + * Create an empty {@link ANeuralNetworksModel}. + * + *

    This only creates the object. Computation is performed once + * {@link ANeuralNetworksExecution_startCompute} is invoked. + * + * The model should be constructed with calls to + * {@link ANeuralNetworksModel_addOperation} and + * {@link ANeuralNetworksModel_addOperand} + * + *

    {@link ANeuralNetworksModel_finish} should be called once the model + * has been fully constructed.

    + * + *

    {@link ANeuralNetworksModel_free} should be called once the model + * is no longer needed.

    + * + * @param model The {@link ANeuralNetworksModel} to be created. + * Set to NULL if unsuccessful. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ +inline int ANeuralNetworksModel_create(ANeuralNetworksModel** model) { + LOAD_FUNCTION(ANeuralNetworksModel_create); + EXECUTE_FUNCTION_RETURN(model); +} - // ASharedMemory_create was added in Android 8.0, so safe to use with NNAPI - // which was added in 8.1. - int (*ASharedMemory_create)(const char* name, size_t size); +/** + * Destroy a model. + * + * The model need not have been finished by a call to + * {@link ANeuralNetworksModel_finish}. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be destroyed. Passing NULL is acceptable and + * results in no operation. + */ +inline void ANeuralNetworksModel_free(ANeuralNetworksModel* model) { + LOAD_FUNCTION(ANeuralNetworksModel_free); + EXECUTE_FUNCTION(model); +} - /**/ -}; +/** + * Indicate that we have finished modifying a model. Required before + * calling {@link ANeuralNetworksCompilation_compile}. + * + * An application is responsible to make sure that no other thread uses + * the model at the same time. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be finished. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ +inline int ANeuralNetworksModel_finish(ANeuralNetworksModel* model) { + LOAD_FUNCTION(ANeuralNetworksModel_finish); + EXECUTE_FUNCTION_RETURN(model); +} + +/** + * Add an operand to a model. + * + * The order in which the operands are added is important. The first one added + * to a model will have the index value 0, the second 1, etc. These indexes are + * used as operand identifiers in {@link ANeuralNetworksModel_addOperation}, + * {@link ANeuralNetworksExecution_setInput}, + * {@link ANeuralNetworksExecution_setInputFromMemory}, + * {@link ANeuralNetworksExecution_setOutput}, + * {@link ANeuralNetworksExecution_setOutputFromMemory} and + * {@link ANeuralNetworksExecution_setOperandValue}. + * + * To build a model that can accommodate inputs of various sizes, as you may + * want to do for a CNN, set the size of the dimensions that will vary at run + * time to 0. If you do so, provide the full dimensions when calling + * {@link ANeuralNetworksExecution_setInput} or {@link + * ANeuralNetworksExecution_setInputFromMemory}. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be modified. + * @param type The {@link ANeuralNetworksOperandType} that describes the shape + * of the operand. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ +inline int ANeuralNetworksModel_addOperand( + ANeuralNetworksModel* model, const ANeuralNetworksOperandType* type) { + LOAD_FUNCTION(ANeuralNetworksModel_addOperand); + EXECUTE_FUNCTION_RETURN(model, type); +} + +/** + * Sets an operand to a constant value. + * + * For scalar values, the content of buffer is copied into the model. + * + * For tensor values, a pointer to the buffer is stored within the model. + * The application is responsible for not changing the content of this region + * until all executions using this model have completed. As the data may + * be copied during processing, modifying the data after this call yields + * undefined results. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be modified. + * @param index The index of the model operand we're setting. + * @param buffer A pointer to the data to use. + * @param length The size in bytes of the data value. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ +inline int ANeuralNetworksModel_setOperandValue(ANeuralNetworksModel* model, + int32_t index, + const void* buffer, + size_t length) { + LOAD_FUNCTION(ANeuralNetworksModel_setOperandValue); + EXECUTE_FUNCTION_RETURN(model, index, buffer, length); +} /** - * Load the NNAPI implementation from the shared libraries. - * The NnApi structure is filled with all the pointers. If one function doesn't - * exist, a null pointer is stored. + * Sets an operand to a value stored in a memory object. + * + * The content of the memory is not copied. A reference to that memory is stored + * inside the model. The application is responsible for not changing the content + * of the memory region until all executions using this model have completed. + * As the data may be copied during processing, modifying the data after this + * call yields undefined results. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @param model The model to be modified. + * @param index The index of the model operand we're setting. + * @param buffer A pointer to the data to use. + * @param memory The memory containing the data. + * @param offset This specifies the location of the data within the memory. + * The offset is in bytes from the start of memory. + * @param length The size in bytes of the data value. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. */ -const NnApi* NnApiImplementation(); +inline int ANeuralNetworksModel_setOperandValueFromMemory( + ANeuralNetworksModel* model, int32_t index, + const ANeuralNetworksMemory* memory, size_t offset, size_t length) { + LOAD_FUNCTION(ANeuralNetworksModel_setOperandValueFromMemory); + EXECUTE_FUNCTION_RETURN(model, index, memory, offset, length); +} + +/** + * Add an operation to a model. + * + * @param model The model to be modified. + * @param type The type of the operation. + * @param inputCount The number of entries in the inputs array. + * @param inputs An array of indexes identifying each operand. + * @param outputCount The number of entries in the outputs array. + * @param outputs An array of indexes identifying each operand. + * + * The operands specified by inputs and outputs must have been + * previously added by calls to {@link ANeuralNetworksModel_addOperand}. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ +inline int ANeuralNetworksModel_addOperation(ANeuralNetworksModel* model, + ANeuralNetworksOperationType type, + uint32_t inputCount, + const uint32_t* inputs, + uint32_t outputCount, + const uint32_t* outputs) { + LOAD_FUNCTION(ANeuralNetworksModel_addOperation); + EXECUTE_FUNCTION_RETURN(model, type, inputCount, inputs, outputCount, + outputs); +} + +/** + * Specifies which operands will be the model's inputs and outputs. + * + * An operand cannot be used for both input and output. Doing so will + * return an error. + * + * @param model The model to be modified. + * @param inputCount The number of entries in the inputs array. + * @param inputs An array of indexes identifying the input operands. + * @param outputCount The number of entries in the outputs array. + * @param outputs An array of indexes identifying the output operands. + * + * The operands specified by inputs and outputs must have been + * previously added by calls to {@link ANeuralNetworksModel_addOperand}. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + * + */ +inline int ANeuralNetworksModel_identifyInputsAndOutputs( + ANeuralNetworksModel* model, uint32_t inputCount, const uint32_t* inputs, + uint32_t outputCount, const uint32_t* outputs) { + LOAD_FUNCTION(ANeuralNetworksModel_identifyInputsAndOutputs); + EXECUTE_FUNCTION_RETURN(model, inputCount, inputs, outputCount, outputs); +} + +/** + * Specifies whether {@link ANEURALNETWORKS_TENSOR_FLOAT32} is allowed to be + * calculated with range and/or precision as low as that of the IEEE 754 16-bit + * floating-point format. By default, {@link ANEURALNETWORKS_TENSOR_FLOAT32} + * must be calculated using at least the range and precision of the IEEE 754 + * 32-bit floating-point format. + * + * @param model The model to be modified. + * @param allow 'true' indicates {@link ANEURALNETWORKS_TENSOR_FLOAT32} may be + * calculated with range and/or precision as low as that of the + * IEEE 754 16-bit floating point format. 'false' indicates + * {@link ANEURALNETWORKS_TENSOR_FLOAT32} must be calculated using + * at least the range and precision of the IEEE 754 32-bit floating + * point format. + * + * Attempting to modify a model once {@link ANeuralNetworksModel_finish} has + * been called will return an error. + * + * Available since API level 28. + * + * See {@link ANeuralNetworksModel} for information on multithreaded usage. + */ +inline int ANeuralNetworksModel_relaxComputationFloat32toFloat16( + ANeuralNetworksModel* model, bool allow) { + LOAD_FUNCTION(ANeuralNetworksModel_relaxComputationFloat32toFloat16); + EXECUTE_FUNCTION_RETURN(model, allow); +} + +/** + * Create a {@link ANeuralNetworksCompilation} to compile the given model. + * This only creates the object. Compilation is only performed once + * {@link ANeuralNetworksCompilation_start} is invoked. + * + *

    The provided model must outlive the compilation.

    + * + * The model must already have been finished by a call to + * {@link ANeuralNetworksModel_finish}. + * + * See {@link ANeuralNetworksCompilation} for information on multithreaded + * usage. + * + * @param model The {@link ANeuralNetworksModel} to be compiled. + * @param compilation The newly created object or NULL if unsuccessful. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA + * if the model is invalid. + */ +inline int ANeuralNetworksCompilation_create( + ANeuralNetworksModel* model, ANeuralNetworksCompilation** compilation) { + LOAD_FUNCTION(ANeuralNetworksCompilation_create); + EXECUTE_FUNCTION_RETURN(model, compilation); +} + +/** + * Destroy a compilation. + * + *

    If called on a compilation for which + * {@link ANeuralNetworksCompilation_start} has been called, the + * function will return immediately but will mark the compilation to be deleted + * once the compilation completes. The {@link ANeuralNetworksCompilation_wait} + * will return ERROR_DELETED. + * + * See {@link ANeuralNetworksCompilation} for information on multithreaded + * usage. + * + * @param compilation The compilation to be destroyed. Passing NULL is + * acceptable and results in no operation. + */ +inline void ANeuralNetworksCompilation_free( + ANeuralNetworksCompilation* compilation) { + LOAD_FUNCTION(ANeuralNetworksCompilation_free); + EXECUTE_FUNCTION(compilation); +} + +/** + * Sets the execution preference. + * + *

    Provides guidance to the runtime when trade-offs are possible.

    + * + * See {@link ANeuralNetworksCompilation} for information on multithreaded + * usage. + * + * @param compilation The compilation to be modified. + * @param preference Either {@link PREFER_LOW_POWER}, + * {@link PREFER_SINGLE_FAST_ANSWER}, or + * {@link PREFER_SUSTAINED_SPEED}. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ +inline int ANeuralNetworksCompilation_setPreference( + ANeuralNetworksCompilation* compilation, int32_t preference) { + LOAD_FUNCTION(ANeuralNetworksCompilation_setPreference); + EXECUTE_FUNCTION_RETURN(compilation, preference); +} + +/** + * Waits until the compilation completes. + * + * More than one thread can wait on a compilation. When the compilation + * completes, all threads will be released. + * + * See {@link ANeuralNetworksCompilation} for information on multithreaded + * usage. + * + * @return ANEURALNETWORKS_NO_ERROR if the compilation completed normally. + */ +inline int ANeuralNetworksCompilation_finish( + ANeuralNetworksCompilation* compilation) { + LOAD_FUNCTION(ANeuralNetworksCompilation_finish); + EXECUTE_FUNCTION_RETURN(compilation); +} +/** + * Create a {@link ANeuralNetworksExecution} to apply the given compilation. + * This only creates the object. Computation is only performed once + * {@link ANeuralNetworksExecution_startCompute} is invoked. + * + *

    The provided compilation must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + * + * @param compilation The {@link ANeuralNetworksCompilation} to be evaluated. + * @param execution The newly created object or NULL if unsuccessful. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA + * if the compilation is invalid. + */ +inline int ANeuralNetworksExecution_create( + ANeuralNetworksCompilation* compilation, + ANeuralNetworksExecution** execution) { + LOAD_FUNCTION(ANeuralNetworksExecution_create); + EXECUTE_FUNCTION_RETURN(compilation, execution); +} + +/** + * Destroy an execution. + * + *

    If called on an execution for which + * {@link ANeuralNetworksExecution_startCompute} has been called, the + * function will return immediately but will mark the execution to be deleted + * once the computation completes. The {link ANeuralNetworksExecution_wait} + * will return ANEURALNETWORKS_ERROR_DELETED. + * + * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + * + * @param execution The execution to be destroyed. Passing NULL is acceptable + * and results in no operation. + */ +inline void ANeuralNetworksExecution_free(ANeuralNetworksExecution* execution) { + LOAD_FUNCTION(ANeuralNetworksExecution_free); + EXECUTE_FUNCTION(execution); +} + +/** + * Associate a user buffer with an input of the model of the + * {@link ANeuralNetworksExecution}. + * + *

    The provided buffer must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + * + * @param execution The execution to be modified. + * @param index The index of the input argument we are setting. It is + * an index into the lists passed to + * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is not + * the index associated with {@link + * ANeuralNetworksModel_addOperand}. + * @param type The type of the operand. This should be used to specify the + * dimensions that were set to 0 when the operand was added to the + * model. All other properties of the type must be the same as + * specified in the model. If the type is the same as specified + * when the model was built, NULL can be passed. + * @param buffer The buffer containing the data. + * @param length The length in bytes of the buffer. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if + * the name is not recognized or the buffer is too small for the input. + */ +inline int ANeuralNetworksExecution_setInput( + ANeuralNetworksExecution* execution, int32_t index, + const ANeuralNetworksOperandType* type, const void* buffer, size_t length) { + LOAD_FUNCTION(ANeuralNetworksExecution_setInput); + EXECUTE_FUNCTION_RETURN(execution, index, type, buffer, length); +} + +/** + * Associate part of a memory object with an input of the model of the + * {@link ANeuralNetworksExecution}. + * + *

    The provided memory must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + * + * @param execution The execution to be modified. + * @param index The index of the input argument we are setting. It is + * an index into the lists passed to + * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is not + * the index associated with {@link + * ANeuralNetworksModel_addOperand}. + * @param type The type of the operand. This can be used to specify the + * dimensions that were set to 0 when the operand was added to the + * model. All other values must be the same as specified in the + * model. If the type is the same as specified when the model + * was built, NULL can be passed. + * @param memory The memory containing the data. + * @param offset This specifies the location of the data within the memory. + * The offset is in bytes from the start of memory. + * @param length The size in bytes of the data value. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if + * the name is not recognized or the buffer is too small for the input. + */ +inline int ANeuralNetworksExecution_setInputFromMemory( + ANeuralNetworksExecution* execution, int32_t index, + const ANeuralNetworksOperandType* type, const ANeuralNetworksMemory* memory, + size_t offset, size_t length) { + LOAD_FUNCTION(ANeuralNetworksExecution_setInputFromMemory); + EXECUTE_FUNCTION_RETURN(execution, index, type, memory, offset, length); +} + +/** + * Associate a user buffer with an output of the model of the + * {@link ANeuralNetworksExecution}. + * + *

    The provided buffer must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + * + * @param execution The execution to be modified. + * @param index The index of the output argument we are setting. It is + * an index into the lists passed to + * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is not + * the index associated with {@link + * ANeuralNetworksModel_addOperand}. + * @param type The type of the operand. This can be used to specify the + * dimensions that were set to 0 when the operand was added to the + * model. All other values must be the same as specified in the + * model. If the type is the same as specified when the model + * was built, NULL can be passed. + * @param buffer The buffer where the data is to be written. + * @param length The length in bytes of the buffer. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if + * the name is not recognized or the buffer is too small for the output. + */ +inline int ANeuralNetworksExecution_setOutput( + ANeuralNetworksExecution* execution, int32_t index, + const ANeuralNetworksOperandType* type, void* buffer, size_t length) { + LOAD_FUNCTION(ANeuralNetworksExecution_setOutput); + EXECUTE_FUNCTION_RETURN(execution, index, type, buffer, length); +} + +/** + * Associate part of a memory object with an output of the model of the + * {@link ANeuralNetworksExecution}. + * + *

    The provided memory must outlive the execution.

    + * + * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + * + * @param execution The execution to be modified. + * @param index The index of the output argument we are setting. It is + * an index into the lists passed to + * {@link ANeuralNetworksModel_identifyInputsAndOutputs}. It is not + * the index associated with {@link + * ANeuralNetworksModel_addOperand}. + * @param type The type of the operand. This can be used to specify the + * dimensions that were set to 0 when the operand was added to the + * model. All other values must be the same as specified in the + * model. If the type is the same as specified when the model + * was built, NULL can be passed. + * @param memory The memory where the data is to be stored. + * @param offset This specifies the location of the data within the memory. + * The offset is in bytes from the start of memory. + * @param length The length in bytes of the data value. + * + * @return ANEURALNETWORKS_NO_ERROR if successful, ANEURALNETWORKS_BAD_DATA if + * the name is not recognized or the buffer is too small for the output. + */ +inline int ANeuralNetworksExecution_setOutputFromMemory( + ANeuralNetworksExecution* execution, int32_t index, + const ANeuralNetworksOperandType* type, const ANeuralNetworksMemory* memory, + size_t offset, size_t length) { + LOAD_FUNCTION(ANeuralNetworksExecution_setOutputFromMemory); + EXECUTE_FUNCTION_RETURN(execution, index, type, memory, offset, length); +} + +/** + * Schedule evaluation of the execution. + * + *

    Schedules evaluation of the execution. Once the model has been + * applied and the outputs are ready to be consumed, the execution will be + * signaled. Use {@link ANeuralNetworksExecution_wait} to wait for that signal. + *

    + * + * Multiple executions can be scheduled and evaluated concurrently, and + * compilations can be performed concurrently with executions. The runtime makes + * no guarantee on the ordering of the completion of compilations and + * executions. If it's important to the application, the application should + * enforce the ordering by using {@link ANeuralNetworksCompilation_wait} and + * {@link ANeuralNetworksExecution_wait}. + * + * ANeuralNetworksExecution_wait must be called to recuperate the resources used + * by the execution. + * + * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + * + * @param execution The execution to be scheduled and executed. + * + * @return ANEURALNETWORKS_NO_ERROR if successful. + */ +inline int ANeuralNetworksExecution_startCompute( + ANeuralNetworksExecution* execution, ANeuralNetworksEvent** event) { + LOAD_FUNCTION(ANeuralNetworksExecution_startCompute); + EXECUTE_FUNCTION_RETURN(execution, event); +} + +/** + * Waits until the execution completes. + * + * More than one thread can wait on an event. When the execution completes, + * all threads will be released. + * + * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + * + * @return ANEURALNETWORKS_NO_ERROR if the execution completed normally. + */ +inline int ANeuralNetworksEvent_wait(ANeuralNetworksEvent* event) { + LOAD_FUNCTION(ANeuralNetworksEvent_wait); + EXECUTE_FUNCTION_RETURN(event); +} + +/** + * Destroys the event. + * + * See {@link ANeuralNetworksExecution} for information on multithreaded usage. + */ +inline void ANeuralNetworksEvent_free(ANeuralNetworksEvent* event) { + LOAD_FUNCTION(ANeuralNetworksEvent_free); + EXECUTE_FUNCTION(event); +} + +/**/ #endif // TENSORFLOW_LITE_NNAPI_NEURALNETWORKSSHIM_H_ diff --git a/tensorflow/lite/nnapi/nnapi_lib_test.cc b/tensorflow/lite/nnapi/nnapi_lib_test.cc deleted file mode 100644 index 46b90115b6..0000000000 --- a/tensorflow/lite/nnapi/nnapi_lib_test.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ -#include -#include "tensorflow/lite/nnapi/NeuralNetworksShim.h" - -namespace { - -TEST(NnapiLibTest, NnApiImplementation) { - const NnApi* nnapi_ = NnApiImplementation(); - EXPECT_NE(nnapi_, nullptr); -#ifdef __ANDROID__ - EXPECT_TRUE(nnapi_->nnapi_exists); - EXPECT_GT(nnapi_->android_sdk_version, 0); - EXPECT_NE(nnapi_->ANeuralNetworksMemory_createFromFd, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksMemory_free, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksModel_create, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksModel_free, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksModel_finish, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksModel_addOperand, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksModel_setOperandValue, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksModel_setOperandValueFromMemory, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksModel_addOperation, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksModel_identifyInputsAndOutputs, nullptr); - if (nnapi_->android_sdk_version >= 28) { - // relaxComputationFloat32toFloat16 only available with Android 9.0 (P). - EXPECT_NE(nnapi_->ANeuralNetworksModel_relaxComputationFloat32toFloat16, - nullptr); - } else { - EXPECT_EQ(nnapi_->ANeuralNetworksModel_relaxComputationFloat32toFloat16, - nullptr); - } - EXPECT_NE(nnapi_->ANeuralNetworksCompilation_create, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksCompilation_free, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksCompilation_setPreference, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksCompilation_finish, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksExecution_create, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksExecution_free, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksExecution_setInput, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksExecution_setInputFromMemory, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksExecution_setOutput, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksExecution_setOutputFromMemory, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksExecution_startCompute, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksEvent_wait, nullptr); - EXPECT_NE(nnapi_->ANeuralNetworksEvent_free, nullptr); - EXPECT_NE(nnapi_->ASharedMemory_create, nullptr); -#else - EXPECT_FALSE(nnapi_->nnapi_exists); - EXPECT_EQ(nnapi_->android_sdk_version, 0); - EXPECT_EQ(nnapi_->ANeuralNetworksMemory_createFromFd, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksMemory_free, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksModel_create, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksModel_free, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksModel_finish, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksModel_addOperand, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksModel_setOperandValue, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksModel_setOperandValueFromMemory, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksModel_addOperation, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksModel_identifyInputsAndOutputs, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksModel_relaxComputationFloat32toFloat16, - nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksCompilation_create, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksCompilation_free, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksCompilation_setPreference, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksCompilation_finish, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksExecution_create, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksExecution_free, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksExecution_setInput, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksExecution_setInputFromMemory, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksExecution_setOutput, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksExecution_setOutputFromMemory, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksExecution_startCompute, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksEvent_wait, nullptr); - EXPECT_EQ(nnapi_->ANeuralNetworksEvent_free, nullptr); - EXPECT_EQ(nnapi_->ASharedMemory_create, nullptr); -#endif -} - -} // namespace diff --git a/tensorflow/lite/nnapi_delegate.cc b/tensorflow/lite/nnapi_delegate.cc index 202f38ba9c..26d75696a1 100644 --- a/tensorflow/lite/nnapi_delegate.cc +++ b/tensorflow/lite/nnapi_delegate.cc @@ -84,27 +84,56 @@ void logError(const char* format, ...) { static const int64_t kOperandIdNotSet = -1; static const int64_t kOperandNotNeeded = -2; +namespace { + +int32_t GetAndroidSdkVersion() { +#ifdef __ANDROID__ + const char* sdkProp = "ro.build.version.sdk"; + char sdkVersion[PROP_VALUE_MAX]; + int length = __system_property_get(sdkProp, sdkVersion); + if (length != 0) { + for (int i = 0; i < length; ++i) { + int digit = sdkVersion[i] - '0'; + if (digit < 0 || digit > 9) { + // Non-numeric SDK version, assume it's higher then expected; + return 0xFFFF; + } + } + return atoi(sdkVersion); + } + FATAL("No %s prop", sdkProp); +#endif // __ANDROID__ + return 0; +} + +int32_t GetAndroidSdkVersionCached() { + static int32_t androidSdkVersion = GetAndroidSdkVersion(); + return androidSdkVersion; +} + +} // namespace + NNAPIAllocation::NNAPIAllocation(const char* filename, ErrorReporter* error_reporter) : MMAPAllocation(filename, error_reporter) { if (mmapped_buffer_ != MAP_FAILED) - CHECK_NN(NnApiImplementation()->ANeuralNetworksMemory_createFromFd( - buffer_size_bytes_, PROT_READ, mmap_fd_, 0, &handle_)); + CHECK_NN(ANeuralNetworksMemory_createFromFd(buffer_size_bytes_, PROT_READ, + mmap_fd_, 0, &handle_)); } NNAPIAllocation::~NNAPIAllocation() { if (handle_) { - NnApiImplementation()->ANeuralNetworksMemory_free(handle_); + ANeuralNetworksMemory_free(handle_); } } NNAPIDelegate::~NNAPIDelegate() { if (nn_compiled_model_) { - NnApiImplementation()->ANeuralNetworksCompilation_free(nn_compiled_model_); + ANeuralNetworksCompilation_free(nn_compiled_model_); nn_compiled_model_ = nullptr; } if (nn_model_) { - NnApiImplementation()->ANeuralNetworksModel_free(nn_model_); + ANeuralNetworksModel_free(nn_model_); nn_model_ = nullptr; // TODO(aselle): Is this thread-safe and callable multiple times? } @@ -116,7 +145,6 @@ TfLiteStatus addTensorOperands(tflite::Subgraph* subgraph, ANeuralNetworksModel* nn_model, uint32_t* no_of_operands_added, std::vector* nnapi_ids) { - const NnApi* nnapi = NnApiImplementation(); uint32_t next_id = 0; for (size_t i = 0; i < subgraph->tensors_size(); i++) { // Skip temporaries and RNN back-edges. @@ -170,24 +198,24 @@ TfLiteStatus addTensorOperands(tflite::Subgraph* subgraph, nn_type, static_cast(tensor->dims->size), reinterpret_cast(tensor->dims->data), scale, zeroPoint}; RETURN_ERROR_IF_NN_FAILED( - nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)); + ANeuralNetworksModel_addOperand(nn_model, &operand_type)); // TODO(aselle): Based on Michael's suggestion, limiting this to read // only memory if (tensor->allocation_type == kTfLiteMmapRo) { if (const NNAPIAllocation* alloc = dynamic_cast( static_cast(tensor->allocation))) { RETURN_ERROR_IF_NN_FAILED( - nnapi->ANeuralNetworksModel_setOperandValueFromMemory( + ANeuralNetworksModel_setOperandValueFromMemory( nn_model, next_id, alloc->memory(), alloc->offset(tensor->data.raw), tensor->bytes)); } else { - RETURN_ERROR_IF_NN_FAILED(nnapi->ANeuralNetworksModel_setOperandValue( + RETURN_ERROR_IF_NN_FAILED(ANeuralNetworksModel_setOperandValue( nn_model, next_id, tensor->data.raw, tensor->bytes)); } } else if (tensor->bytes == 0) { // These size 0 tensors are optional tensors reserved. - RETURN_ERROR_IF_NN_FAILED(nnapi->ANeuralNetworksModel_setOperandValue( - nn_model, next_id, nullptr, 0)); + RETURN_ERROR_IF_NN_FAILED( + ANeuralNetworksModel_setOperandValue(nn_model, next_id, nullptr, 0)); } ++next_id; @@ -216,7 +244,6 @@ TfLiteStatus AddOpsAndParams( uint32_t next_id, std::vector* model_state_inputs, std::vector* model_state_outputs, const std::vector& tensor_id_to_nnapi_id) { - const NnApi* nnapi = NnApiImplementation(); for (size_t i = 0; i < subgraph->nodes_size(); i++) { const auto* node_and_registration = subgraph->node_and_registration(i); const TfLiteNode& node = node_and_registration->first; @@ -231,21 +258,21 @@ TfLiteStatus AddOpsAndParams( MapAndAddTensorIds(node.outputs->data, node.outputs->size, &augmented_outputs, tensor_id_to_nnapi_id); - auto add_scalar_int32 = [nnapi, &nn_model, &augmented_inputs, + auto add_scalar_int32 = [&nn_model, &augmented_inputs, &next_id](int value) { ANeuralNetworksOperandType operand_type{.type = ANEURALNETWORKS_INT32}; - CHECK_NN(nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)) - CHECK_NN(nnapi->ANeuralNetworksModel_setOperandValue( - nn_model, next_id, &value, sizeof(int32_t))) + CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)) + CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, &value, + sizeof(int32_t))) augmented_inputs.push_back(next_id++); }; - auto add_scalar_float32 = [nnapi, &nn_model, &augmented_inputs, + auto add_scalar_float32 = [&nn_model, &augmented_inputs, &next_id](float value) { ANeuralNetworksOperandType operand_type{.type = ANEURALNETWORKS_FLOAT32}; - CHECK_NN(nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)) - CHECK_NN(nnapi->ANeuralNetworksModel_setOperandValue( - nn_model, next_id, &value, sizeof(float))) + CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)) + CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, &value, + sizeof(float))) augmented_inputs.push_back(next_id++); }; @@ -254,8 +281,8 @@ TfLiteStatus AddOpsAndParams( .type = ANEURALNETWORKS_TENSOR_INT32, .dimensionCount = 1, .dimensions = &num_values}; - CHECK_NN(nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)) - CHECK_NN(nnapi->ANeuralNetworksModel_setOperandValue( + CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)) + CHECK_NN(ANeuralNetworksModel_setOperandValue( nn_model, next_id, values, sizeof(int32_t) * num_values)); augmented_inputs.push_back(next_id++); }; @@ -264,16 +291,15 @@ TfLiteStatus AddOpsAndParams( // For each state_out tensor, a corresponding state_in operand needs to be // created for NNAPI. auto duplicate_state_tensor_float32 = - [nnapi, subgraph, &nn_model, &next_id, &augmented_inputs, - &model_state_inputs, &model_state_outputs](int tensor_id) { + [subgraph, &nn_model, &next_id, &augmented_inputs, &model_state_inputs, + &model_state_outputs](int tensor_id) { const TfLiteTensor* tensor = subgraph->tensor(tensor_id); ANeuralNetworksOperandType operand_type{ ANEURALNETWORKS_TENSOR_FLOAT32, static_cast(tensor->dims->size), reinterpret_cast(tensor->dims->data), tensor->params.scale, tensor->params.zero_point}; - CHECK_NN( - nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)); + CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)); augmented_inputs.push_back(next_id); model_state_inputs->push_back(next_id); model_state_outputs->push_back(tensor_id); @@ -362,7 +388,7 @@ TfLiteStatus AddOpsAndParams( }; // LSTM in NNAPI requires scratch tensor as an output operand. - auto add_lstm_scratch_tensor_float32 = [nnapi, subgraph, &node, &nn_model, + auto add_lstm_scratch_tensor_float32 = [subgraph, &node, &nn_model, &next_id, &augmented_outputs]() { if (node.temporaries->size == 0) return; int scratch_buffer_index = node.temporaries->data[0]; @@ -372,7 +398,7 @@ TfLiteStatus AddOpsAndParams( static_cast(tensor->dims->size), reinterpret_cast(tensor->dims->data), tensor->params.scale, tensor->params.zero_point}; - CHECK_NN(nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)); + CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)); augmented_outputs.insert(augmented_outputs.begin(), next_id++); }; @@ -401,16 +427,15 @@ TfLiteStatus AddOpsAndParams( }; // Handle optional input tensors. - auto add_optional_tensors = [nnapi, &nn_model, &augmented_inputs, + auto add_optional_tensors = [&nn_model, &augmented_inputs, &next_id](int nn_type) { for (size_t idx = 0; idx < augmented_inputs.size(); idx++) { if (augmented_inputs[idx] == kOptionalTensor) { const std::vector dim = {0, 0}; ANeuralNetworksOperandType operand_type{nn_type, 2, dim.data(), 0, 0}; - CHECK_NN( - nnapi->ANeuralNetworksModel_addOperand(nn_model, &operand_type)) - CHECK_NN(nnapi->ANeuralNetworksModel_setOperandValue( - nn_model, next_id, nullptr, 0)) + CHECK_NN(ANeuralNetworksModel_addOperand(nn_model, &operand_type)) + CHECK_NN(ANeuralNetworksModel_setOperandValue(nn_model, next_id, + nullptr, 0)) augmented_inputs[idx] = next_id++; } } @@ -670,13 +695,13 @@ TfLiteStatus AddOpsAndParams( break; } - if (nnapi_version == 11 && nnapi->android_sdk_version < 28) { + if (nnapi_version == 11 && GetAndroidSdkVersionCached() < 28) { logError("Op %d needs NNAPI1.1", builtin); return kTfLiteError; } // Add the operation. - RETURN_ERROR_IF_NN_FAILED(nnapi->ANeuralNetworksModel_addOperation( + RETURN_ERROR_IF_NN_FAILED(ANeuralNetworksModel_addOperation( nn_model, nn_op_type, static_cast(augmented_inputs.size()), augmented_inputs.data(), static_cast(augmented_outputs.size()), @@ -688,10 +713,9 @@ TfLiteStatus AddOpsAndParams( TfLiteStatus NNAPIDelegate::BuildGraph(Subgraph* subgraph) { if (nn_model_ && nn_compiled_model_) return model_status_; - const NnApi* nnapi = NnApiImplementation(); // TODO(aselle): This is not correct. need to handle resize invalidation. if (!nn_model_) { - CHECK_NN(nnapi->ANeuralNetworksModel_create(&nn_model_)); + CHECK_NN(ANeuralNetworksModel_create(&nn_model_)); // Find which tensors should be added to NNAPI. TFLite has temporaries // and RNN back-edges which are are not valid for NNAPI. We look through all @@ -738,22 +762,21 @@ TfLiteStatus NNAPIDelegate::BuildGraph(Subgraph* subgraph) { model_states_outputs_.size(), &augmented_outputs, tensor_id_to_nnapi_id); - CHECK_NN(nnapi->ANeuralNetworksModel_identifyInputsAndOutputs( + CHECK_NN(ANeuralNetworksModel_identifyInputsAndOutputs( nn_model_, static_cast(augmented_inputs.size()), reinterpret_cast(augmented_inputs.data()), static_cast(augmented_outputs.size()), reinterpret_cast(augmented_outputs.data()))); - if (nnapi->android_sdk_version >= 28) { - CHECK_NN(nnapi->ANeuralNetworksModel_relaxComputationFloat32toFloat16( + if (GetAndroidSdkVersionCached() >= 28) { + CHECK_NN(ANeuralNetworksModel_relaxComputationFloat32toFloat16( nn_model_, subgraph->GetAllowFp16PrecisionForFp32())); } - CHECK_NN(nnapi->ANeuralNetworksModel_finish(nn_model_)); + CHECK_NN(ANeuralNetworksModel_finish(nn_model_)); } if (!nn_compiled_model_) { - CHECK_NN(nnapi->ANeuralNetworksCompilation_create(nn_model_, - &nn_compiled_model_)); - CHECK_NN(nnapi->ANeuralNetworksCompilation_finish(nn_compiled_model_)); + CHECK_NN(ANeuralNetworksCompilation_create(nn_model_, &nn_compiled_model_)); + CHECK_NN(ANeuralNetworksCompilation_finish(nn_compiled_model_)); } return kTfLiteOk; } @@ -769,10 +792,8 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { return model_status_; } - const NnApi* nnapi = NnApiImplementation(); ANeuralNetworksExecution* execution = nullptr; - CHECK_NN( - nnapi->ANeuralNetworksExecution_create(nn_compiled_model_, &execution)); + CHECK_NN(ANeuralNetworksExecution_create(nn_compiled_model_, &execution)); // Currently perform deep copy of input buffer for (size_t i = 0; i < subgraph->inputs().size(); i++) { @@ -780,7 +801,7 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { // TODO(aselle): Is this what we want or do we want input instead? // TODO(aselle): This should be called setInputValue maybe to be cons. TfLiteTensor* tensor = subgraph->tensor(input); - CHECK_NN(nnapi->ANeuralNetworksExecution_setInput( + CHECK_NN(ANeuralNetworksExecution_setInput( execution, i, nullptr, tensor->data.raw, tensor->bytes)); } @@ -788,7 +809,7 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { for (size_t i = 0; i < subgraph->outputs().size(); i++) { int output = subgraph->outputs()[i]; TfLiteTensor* tensor = subgraph->tensor(output); - CHECK_NN(nnapi->ANeuralNetworksExecution_setOutput( + CHECK_NN(ANeuralNetworksExecution_setOutput( execution, i, nullptr, tensor->data.raw, tensor->bytes)); } @@ -800,21 +821,21 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { // Here we are using a deep copy for state_in tensors so that we are not // reading and writing into the same buffer during a invocation. // TODO(miaowang): using double shared buffer to minimize the copies. - CHECK_NN(nnapi->ANeuralNetworksExecution_setInput( + CHECK_NN(ANeuralNetworksExecution_setInput( execution, i + subgraph->inputs().size(), nullptr, tensor->data.raw, tensor->bytes)); // Tell NNAPI where to output the state_out. - CHECK_NN(nnapi->ANeuralNetworksExecution_setOutput( + CHECK_NN(ANeuralNetworksExecution_setOutput( execution, i + subgraph->outputs().size(), nullptr, tensor->data.raw, tensor->bytes)); } // Currently use blocking compute. ANeuralNetworksEvent* event = nullptr; - CHECK_NN(nnapi->ANeuralNetworksExecution_startCompute(execution, &event)); - CHECK_NN(nnapi->ANeuralNetworksEvent_wait(event)); - nnapi->ANeuralNetworksEvent_free(event); - nnapi->ANeuralNetworksExecution_free(execution); + CHECK_NN(ANeuralNetworksExecution_startCompute(execution, &event)); + CHECK_NN(ANeuralNetworksEvent_wait(event)); + ANeuralNetworksEvent_free(event); + ANeuralNetworksExecution_free(execution); #if 0 printf("From the NN API:\n"); @@ -832,8 +853,6 @@ TfLiteStatus NNAPIDelegate::Invoke(Subgraph* subgraph) { return kTfLiteOk; } -bool NNAPIDelegate::IsSupported() { - return NnApiImplementation()->nnapi_exists; -} +bool NNAPIDelegate::IsSupported() { return NNAPIExists(); } } // namespace tflite -- GitLab From 5155fb326907d14f6f1b1011163a49e2862cd850 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Wed, 19 Dec 2018 16:51:27 -0800 Subject: [PATCH 0141/1765] Moves the collections-based losses symbols to compat.v1 in tf2. PiperOrigin-RevId: 226256303 --- tensorflow/python/ops/losses/util.py | 10 +++++----- .../api/golden/v2/tensorflow.losses.pbtxt | 20 ------------------- tensorflow/tools/compatibility/renames_v2.py | 7 ++++++- 3 files changed, 11 insertions(+), 26 deletions(-) diff --git a/tensorflow/python/ops/losses/util.py b/tensorflow/python/ops/losses/util.py index 97bba46661..73f4c750b8 100644 --- a/tensorflow/python/ops/losses/util.py +++ b/tensorflow/python/ops/losses/util.py @@ -25,7 +25,7 @@ from tensorflow.python.ops import math_ops from tensorflow.python.util.tf_export import tf_export -@tf_export("losses.add_loss") +@tf_export(v1=["losses.add_loss"]) def add_loss(loss, loss_collection=ops.GraphKeys.LOSSES): """Adds a externally defined loss to the collection of losses. @@ -40,7 +40,7 @@ def add_loss(loss, loss_collection=ops.GraphKeys.LOSSES): ops.add_to_collection(loss_collection, loss) -@tf_export("losses.get_losses") +@tf_export(v1=["losses.get_losses"]) def get_losses(scope=None, loss_collection=ops.GraphKeys.LOSSES): """Gets the list of losses from the loss_collection. @@ -54,7 +54,7 @@ def get_losses(scope=None, loss_collection=ops.GraphKeys.LOSSES): return ops.get_collection(loss_collection, scope) -@tf_export("losses.get_regularization_losses") +@tf_export(v1=["losses.get_regularization_losses"]) def get_regularization_losses(scope=None): """Gets the list of regularization losses. @@ -67,7 +67,7 @@ def get_regularization_losses(scope=None): return ops.get_collection(ops.GraphKeys.REGULARIZATION_LOSSES, scope) -@tf_export("losses.get_regularization_loss") +@tf_export(v1=["losses.get_regularization_loss"]) def get_regularization_loss(scope=None, name="total_regularization_loss"): """Gets the total regularization loss. @@ -85,7 +85,7 @@ def get_regularization_loss(scope=None, name="total_regularization_loss"): return constant_op.constant(0.0) -@tf_export("losses.get_total_loss") +@tf_export(v1=["losses.get_total_loss"]) def get_total_loss(add_regularization_losses=True, name="total_loss"): """Returns a tensor whose value represents the total loss. diff --git a/tensorflow/tools/api/golden/v2/tensorflow.losses.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.losses.pbtxt index 233b1a0131..36007d3ca6 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.losses.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.losses.pbtxt @@ -4,24 +4,4 @@ tf_module { name: "Reduction" mtype: "" } - member_method { - name: "add_loss" - argspec: "args=[\'loss\', \'loss_collection\'], varargs=None, keywords=None, defaults=[\'losses\'], " - } - member_method { - name: "get_losses" - argspec: "args=[\'scope\', \'loss_collection\'], varargs=None, keywords=None, defaults=[\'None\', \'losses\'], " - } - member_method { - name: "get_regularization_loss" - argspec: "args=[\'scope\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'total_regularization_loss\'], " - } - member_method { - name: "get_regularization_losses" - argspec: "args=[\'scope\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "get_total_loss" - argspec: "args=[\'add_regularization_losses\', \'name\'], varargs=None, keywords=None, defaults=[\'True\', \'total_loss\'], " - } } diff --git a/tensorflow/tools/compatibility/renames_v2.py b/tensorflow/tools/compatibility/renames_v2.py index 6235eb3eed..d67cb7cb9a 100644 --- a/tensorflow/tools/compatibility/renames_v2.py +++ b/tensorflow/tools/compatibility/renames_v2.py @@ -203,7 +203,7 @@ renames = { 'tf.global_norm': 'tf.linalg.global_norm', 'tf.global_variables': 'tf.compat.v1.global_variables', 'tf.global_variables_initializer': 'tf.compat.v1.global_variables_initializer', - 'tf.glorot_normal_initializer': 'tf.keras.initializers.glorot_normal', + 'tf.glorot_normal_initializer': 'tf.initializers.glorot_normal', 'tf.graph_util.convert_variables_to_constants': 'tf.compat.v1.graph_util.convert_variables_to_constants', 'tf.graph_util.extract_sub_graph': 'tf.compat.v1.graph_util.extract_sub_graph', 'tf.graph_util.must_run_on_cpu': 'tf.compat.v1.graph_util.must_run_on_cpu', @@ -313,8 +313,13 @@ renames = { 'tf.logging.warning': 'tf.compat.v1.logging.warning', 'tf.logical_xor': 'tf.math.logical_xor', 'tf.losses.absolute_difference': 'tf.compat.v1.losses.absolute_difference', + 'tf.losses.add_loss': 'tf.compat.v1.losses.add_loss', 'tf.losses.compute_weighted_loss': 'tf.compat.v1.losses.compute_weighted_loss', 'tf.losses.cosine_distance': 'tf.compat.v1.losses.cosine_distance', + 'tf.losses.get_losses': 'tf.compat.v1.losses.get_losses', + 'tf.losses.get_regularization_loss': 'tf.compat.v1.losses.get_regularization_loss', + 'tf.losses.get_regularization_losses': 'tf.compat.v1.losses.get_regularization_losses', + 'tf.losses.get_total_loss': 'tf.compat.v1.losses.get_total_loss', 'tf.losses.hinge_loss': 'tf.compat.v1.losses.hinge_loss', 'tf.losses.huber_loss': 'tf.compat.v1.losses.huber_loss', 'tf.losses.log_loss': 'tf.compat.v1.losses.log_loss', -- GitLab From 18fe16b0a7242428649f45fd15a184c6f58b9c31 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Wed, 19 Dec 2018 16:58:08 -0800 Subject: [PATCH 0142/1765] Fixing build failure due to import error. PiperOrigin-RevId: 226257168 --- tensorflow/python/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow/python/BUILD b/tensorflow/python/BUILD index c12e9ee3f3..5f6d4b6bdc 100644 --- a/tensorflow/python/BUILD +++ b/tensorflow/python/BUILD @@ -735,6 +735,7 @@ py_library( srcs_version = "PY2AND3", deps = [ ":c_api_util", + ":error_interpolation", ":util", ], ) -- GitLab From f8005ddb0883b796a9b4aea9b77444bee7975110 Mon Sep 17 00:00:00 2001 From: Allen Lavoie Date: Wed, 19 Dec 2018 18:04:59 -0800 Subject: [PATCH 0143/1765] Switch off v2 control flow for the reference cycle test instead of skipping it Otherwise it's going to get broken; it's a useful test PiperOrigin-RevId: 226265071 --- tensorflow/python/saved_model/save_test.py | 26 ++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/tensorflow/python/saved_model/save_test.py b/tensorflow/python/saved_model/save_test.py index f5d4b3d5a9..4573495998 100644 --- a/tensorflow/python/saved_model/save_test.py +++ b/tensorflow/python/saved_model/save_test.py @@ -23,6 +23,7 @@ import sys from tensorflow.python.client import session as session_lib from tensorflow.python.eager import backprop +from tensorflow.python.eager import function from tensorflow.python.eager import def_function from tensorflow.python.eager import test from tensorflow.python.framework import constant_op @@ -371,14 +372,35 @@ class AssetTests(test.TestCase): save.save(root, export_dir) +class _ModelWithOptimizerUsingDefun(util.Checkpoint): + + def __init__(self): + self.dense = core.Dense(1) + self.optimizer = adam.AdamOptimizer(0.01) + + # Using defun due to control flow v2 cycles, b/121159261. def_function uses + # conds to gate variable initialization and so triggers cond reference cycles, + # but the thing being wrapped here does not use cond itself. + @function.defun( + input_signature=(tensor_spec.TensorSpec([None, 2], dtypes.float32), + tensor_spec.TensorSpec([None], dtypes.float32)), + ) + def call(self, x, y): + with backprop.GradientTape() as tape: + loss = math_ops.reduce_mean((self.dense(x) - y) ** 2.) + trainable_variables = self.dense.trainable_variables + gradients = tape.gradient(loss, trainable_variables) + self.optimizer.apply_gradients(zip(gradients, trainable_variables)) + return {"loss": loss} + + class MemoryTests(test.TestCase): def setUp(self): - self._model = _ModelWithOptimizer() + self._model = _ModelWithOptimizerUsingDefun() @test_util.assert_no_garbage_created def test_no_reference_cycles(self): - self.skipTest("b/121159261") x = constant_op.constant([[3., 4.]]) y = constant_op.constant([2.]) self._model.call(x, y) -- GitLab From a11de92aa0cc81835096b2ed323872b456feddfe Mon Sep 17 00:00:00 2001 From: Scott Zhu Date: Wed, 19 Dec 2018 18:10:41 -0800 Subject: [PATCH 0144/1765] Cleanup the v1 only test cases for RNN layers. Move them to test under 3 keras modes. PiperOrigin-RevId: 226265610 --- tensorflow/python/keras/BUILD | 2 +- .../python/keras/layers/unified_gru_test.py | 73 ++--- .../python/keras/layers/unified_lstm_test.py | 300 +++++++++--------- 3 files changed, 180 insertions(+), 195 deletions(-) diff --git a/tensorflow/python/keras/BUILD b/tensorflow/python/keras/BUILD index 47fb480aa1..6e1a6fc123 100755 --- a/tensorflow/python/keras/BUILD +++ b/tensorflow/python/keras/BUILD @@ -561,7 +561,7 @@ cuda_py_test( "//third_party/py/numpy", "//tensorflow/python:client_testlib", ], - shard_count = 4, + shard_count = 8, ) cuda_py_test( diff --git a/tensorflow/python/keras/layers/unified_gru_test.py b/tensorflow/python/keras/layers/unified_gru_test.py index 57c1e151f9..5527f21b6f 100644 --- a/tensorflow/python/keras/layers/unified_gru_test.py +++ b/tensorflow/python/keras/layers/unified_gru_test.py @@ -137,37 +137,6 @@ class UnifiedGRUTest(keras_parameterized.TestCase): l2 = layer_class.from_config(l1.get_config()) assert l1.get_config() == l2.get_config() - -class GRULayerGradientTapeTest(test.TestCase): - - @test_util.run_in_graph_and_eager_modes(config=_config) - def test_in_tape(self): - if not context.executing_eagerly(): - self.skipTest('bloo') - time_steps = 10 - embedding_size = 11 - gru_unit_size = 12 - - gru = keras.layers.UnifiedGRU(gru_unit_size, - return_sequences=True, - return_state=True, - recurrent_activation='sigmoid', - recurrent_initializer='glorot_uniform') - - x = random_ops.random_uniform([1, time_steps, embedding_size]) - y = random_ops.random_uniform([1, gru_unit_size]) - - with backprop.GradientTape() as tape: - hidden_state = array_ops.zeros([1, gru_unit_size], dtype=dtypes.float32) - _, state = gru(x, initial_state=hidden_state) - - loss = math_ops.reduce_mean(math_ops.square(state - y)) - - tape.gradient(loss, gru.variables) - - -class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): - def test_unified_gru_feature_parity_with_canonical_gru(self): with context.eager_mode(): # Run this test under eager only due to b/120160788 for model.set_weights. @@ -216,7 +185,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): ('no_bias', False, 'zeros'), ('random_bias', True, 'random_uniform'), ) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_unified_gru_model_save_load(self, use_bias, bias_initializer): temp_dir = self.get_temp_dir() self.addCleanup(shutil.rmtree, temp_dir) @@ -250,7 +218,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): self.assertAllClose(y, y_ref) self.assertAllClose(layer.get_weights(), new_layer.get_weights()) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_unified_gru_output_on_multiple_kernel(self): input_shape = 10 rnn_state_size = 8 @@ -297,7 +264,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): ('go_backwards', False, True), ('both', True, True), ) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_time_major_and_go_backward(self, time_major, go_backwards): input_shape = 10 rnn_state_size = 8 @@ -335,7 +301,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): self.assertAllClose(y, y_ref) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_with_masking_layer_GRU(self): layer_class = keras.layers.UnifiedGRU inputs = np.random.random((2, 3, 4)) @@ -348,7 +313,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): optimizer=gradient_descent.GradientDescentOptimizer(0.001)) model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_masking_with_stacking_GRU(self): inputs = np.random.random((2, 3, 4)) targets = np.abs(np.random.random((2, 3, 5))) @@ -362,7 +326,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): optimizer=gradient_descent.GradientDescentOptimizer(0.01)) model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_return_sequences_GRU(self): num_samples = 2 timesteps = 3 @@ -374,7 +337,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): 'return_sequences': True}, input_shape=(num_samples, timesteps, embedding_dim)) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_dropout_GRU(self): num_samples = 2 timesteps = 3 @@ -387,7 +349,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): 'recurrent_dropout': 0.1}, input_shape=(num_samples, timesteps, embedding_dim)) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_constraints_GRU(self): embedding_dim = 4 layer_class = keras.layers.UnifiedGRU @@ -408,7 +369,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): self.assertEqual(layer.cell.bias.constraint, b_constraint) @parameterized.parameters([0, 1, 2]) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_implementation_mode_GRU(self, implementation_mode): num_samples = 2 timesteps = 3 @@ -420,7 +380,38 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): 'implementation': implementation_mode}, input_shape=(num_samples, timesteps, embedding_dim)) - @test_util.run_v1_only("b/120941292") + +class GRULayerGradientTapeTest(test.TestCase): + + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_in_tape(self): + if not context.executing_eagerly(): + self.skipTest('bloo') + time_steps = 10 + embedding_size = 11 + gru_unit_size = 12 + + gru = keras.layers.UnifiedGRU(gru_unit_size, + return_sequences=True, + return_state=True, + recurrent_activation='sigmoid', + recurrent_initializer='glorot_uniform') + + x = random_ops.random_uniform([1, time_steps, embedding_size]) + y = random_ops.random_uniform([1, gru_unit_size]) + + with backprop.GradientTape() as tape: + hidden_state = array_ops.zeros([1, gru_unit_size], dtype=dtypes.float32) + _, state = gru(x, initial_state=hidden_state) + + loss = math_ops.reduce_mean(math_ops.square(state - y)) + + tape.gradient(loss, gru.variables) + + +class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): + + @test_util.run_v1_only('b/120941292') @test_util.run_in_graph_and_eager_modes(config=_config) def test_statefulness_GRU(self): self.skipTest('b/121275483') diff --git a/tensorflow/python/keras/layers/unified_lstm_test.py b/tensorflow/python/keras/layers/unified_lstm_test.py index 15086a53a8..afa68d954c 100644 --- a/tensorflow/python/keras/layers/unified_lstm_test.py +++ b/tensorflow/python/keras/layers/unified_lstm_test.py @@ -296,152 +296,6 @@ class UnifiedLSTMTest(keras_parameterized.TestCase): targets = np.random.random((num_samples, units)) model.train_on_batch([main_inputs] + initial_state, targets) - -class LSTMLayerGraphOnlyTest(test.TestCase): - - # Need session for test - @test_util.run_deprecated_v1 - def test_unifiedLSTM(self): - input_shape = 10 - rnn_state_size = 8 - output_shape = 8 - timestep = 4 - batch = 100 - epoch = 1 - - with self.cached_session(config=_config, use_gpu=True) as sess: - (x_train, y_train), _ = testing_utils.get_test_data( - train_samples=batch, - test_samples=0, - input_shape=(timestep, input_shape), - num_classes=output_shape) - y_train = keras.utils.to_categorical(y_train, output_shape) - - layer = keras.layers.UnifiedLSTM(rnn_state_size, return_runtime=True) - - inputs = array_ops.placeholder( - dtypes.float32, shape=(None, timestep, input_shape), name='inputs') - predict = array_ops.placeholder( - dtypes.float32, shape=(None, output_shape), name='predict') - - outputs, runtime = layer(inputs) - loss = losses.softmax_cross_entropy(predict, outputs) - optimizer = gradient_descent.GradientDescentOptimizer(0.001) - train_op = optimizer.minimize(loss) - - sess.run([variables.global_variables_initializer()]) - existing_loss = 0 - for _ in range(epoch): - loss_value, _, runtime_value = sess.run([loss, train_op, runtime], { - inputs: x_train, - predict: y_train - }) - if test.is_gpu_available(): - self.assertEqual(runtime_value, b'cudnn') - else: - self.assertEqual(runtime_value, b'cpu') - # Make sure the loss is updated for every epoch - # (layer weights properly updated). - self.assertNotEqual(existing_loss, loss_value) - existing_loss = loss_value - - # Need session for test - @test_util.run_deprecated_v1 - def test_unifiedLSTM_with_cond(self): - # This test is to demonstrate the graph rewrite of grappler plugin under - # the condition that the function returns different number of internal - # states. - input_shape = 10 - rnn_state_size = 8 - output_shape = 8 - timestep = 4 - batch = 100 - epoch = 1 - - with self.cached_session(config=_config, use_gpu=True) as sess: - (x_train, y_train), _ = testing_utils.get_test_data( - train_samples=batch, - test_samples=0, - input_shape=(timestep, input_shape), - num_classes=output_shape) - y_train = keras.utils.to_categorical(y_train, output_shape) - - layer = keras.layers.UnifiedLSTM(rnn_state_size, return_runtime=True) - - inputs = array_ops.placeholder( - dtypes.float32, shape=(None, timestep, input_shape), name='inputs') - predict = array_ops.placeholder( - dtypes.float32, shape=(None, output_shape), name='predict') - - zeros = array_ops.zeros([batch, output_shape]) - dummy_runtime = constant_op.constant( - 'unknown', dtype=dtypes.string, name='runtime') - a = constant_op.constant(0) - b = constant_op.constant(1) - # Will always run the lstm layer. - outputs, runtime = control_flow_ops.cond( - gen_math_ops.less(a, b), - lambda: layer(inputs), - lambda: (zeros, dummy_runtime)) - loss = losses.softmax_cross_entropy(predict, outputs) - optimizer = gradient_descent.GradientDescentOptimizer(0.001) - train_op = optimizer.minimize(loss) - - sess.run([variables.global_variables_initializer()]) - existing_loss = 0 - - for _ in range(epoch): - loss_value, _, runtime_value = sess.run([loss, train_op, runtime], { - inputs: x_train, - predict: y_train - }) - if test.is_gpu_available(): - self.assertEqual(runtime_value, b'cudnn') - else: - self.assertEqual(runtime_value, b'cpu') - # Make sure the loss is updated for every epoch - # (layer weights properly updated). - self.assertNotEqual(existing_loss, loss_value) - existing_loss = loss_value - - # b/120919032 - @test_util.run_deprecated_v1 - def test_regularizers_LSTM(self): - embedding_dim = 4 - layer_class = keras.layers.UnifiedLSTM - layer = layer_class( - 5, - return_sequences=False, - weights=None, - input_shape=(None, embedding_dim), - kernel_regularizer=keras.regularizers.l1(0.01), - recurrent_regularizer=keras.regularizers.l1(0.01), - bias_regularizer='l2', - activity_regularizer='l1') - layer.build((None, None, 2)) - self.assertEqual(len(layer.losses), 3) - x = keras.backend.variable(np.ones((2, 3, 2))) - layer(x) - self.assertEqual(len(layer.get_losses_for(x)), 1) - - -class LSTMLayerV1OnlyTest(test.TestCase, parameterized.TestCase): - - @test_util.run_in_graph_and_eager_modes(config=_config) - def test_dropout_LSTM(self): - num_samples = 2 - timesteps = 3 - embedding_dim = 4 - units = 2 - testing_utils.layer_test( - keras.layers.UnifiedLSTM, - kwargs={ - 'units': units, - 'dropout': 0.1, - 'recurrent_dropout': 0.1 - }, - input_shape=(num_samples, timesteps, embedding_dim)) - def test_unified_lstm_feature_parity_with_canonical_lstm(self): with context.eager_mode(): # Run this test under eager only due to b/120160788 for model.set_weights. @@ -482,7 +336,6 @@ class LSTMLayerV1OnlyTest(test.TestCase, parameterized.TestCase): self.assertAllClose(y_2, y_4) @parameterized.named_parameters(('v0', 0), ('v1', 1), ('v2', 2)) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_implementation_mode_LSTM(self, implementation_mode): num_samples = 2 timesteps = 3 @@ -525,7 +378,6 @@ class LSTMLayerV1OnlyTest(test.TestCase, parameterized.TestCase): optimizer=gradient_descent.GradientDescentOptimizer(0.01)) model.fit(inputs, targets, epochs=1, batch_size=2, verbose=1) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_masking_with_stacking_LSTM(self): inputs = np.random.random((2, 3, 4)) targets = np.abs(np.random.random((2, 3, 5))) @@ -546,7 +398,6 @@ class LSTMLayerV1OnlyTest(test.TestCase, parameterized.TestCase): ('go_backwards', False, True), ('both', True, True), ) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_time_major_and_go_backward(self, time_major, go_backwards): input_shape = 10 rnn_state_size = 8 @@ -615,7 +466,6 @@ class LSTMLayerV1OnlyTest(test.TestCase, parameterized.TestCase): ('no_bias', False, 'zeros'), ('random_bias', True, 'random_uniform'), ) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_unified_lstm_model_save_load(self, use_bias, bias_initializer): temp_dir = self.get_temp_dir() self.addCleanup(shutil.rmtree, temp_dir) @@ -649,7 +499,6 @@ class LSTMLayerV1OnlyTest(test.TestCase, parameterized.TestCase): self.assertAllClose(y, y_ref) self.assertAllClose(layer.get_weights(), new_layer.get_weights()) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_unified_lstm_output_on_multiple_kernel(self): input_shape = 10 rnn_state_size = 8 @@ -688,7 +537,6 @@ class LSTMLayerV1OnlyTest(test.TestCase, parameterized.TestCase): self.assertAllClose(y_1, y_2) self.assertAllClose(y_2, y_3) - @test_util.run_in_graph_and_eager_modes(config=_config) def test_return_sequences_LSTM(self): num_samples = 2 timesteps = 3 @@ -703,7 +551,153 @@ class LSTMLayerV1OnlyTest(test.TestCase, parameterized.TestCase): input_shape=(num_samples, timesteps, embedding_dim)) - @test_util.run_v1_only("b/120941292") +class LSTMLayerGraphOnlyTest(test.TestCase): + + # Need session for test + @test_util.run_deprecated_v1 + def test_unifiedLSTM(self): + input_shape = 10 + rnn_state_size = 8 + output_shape = 8 + timestep = 4 + batch = 100 + epoch = 1 + + with self.cached_session(config=_config, use_gpu=True) as sess: + (x_train, y_train), _ = testing_utils.get_test_data( + train_samples=batch, + test_samples=0, + input_shape=(timestep, input_shape), + num_classes=output_shape) + y_train = keras.utils.to_categorical(y_train, output_shape) + + layer = keras.layers.UnifiedLSTM(rnn_state_size, return_runtime=True) + + inputs = array_ops.placeholder( + dtypes.float32, shape=(None, timestep, input_shape), name='inputs') + predict = array_ops.placeholder( + dtypes.float32, shape=(None, output_shape), name='predict') + + outputs, runtime = layer(inputs) + loss = losses.softmax_cross_entropy(predict, outputs) + optimizer = gradient_descent.GradientDescentOptimizer(0.001) + train_op = optimizer.minimize(loss) + + sess.run([variables.global_variables_initializer()]) + existing_loss = 0 + for _ in range(epoch): + loss_value, _, runtime_value = sess.run([loss, train_op, runtime], { + inputs: x_train, + predict: y_train + }) + if test.is_gpu_available(): + self.assertEqual(runtime_value, b'cudnn') + else: + self.assertEqual(runtime_value, b'cpu') + # Make sure the loss is updated for every epoch + # (layer weights properly updated). + self.assertNotEqual(existing_loss, loss_value) + existing_loss = loss_value + + # Need session for test + @test_util.run_deprecated_v1 + def test_unifiedLSTM_with_cond(self): + # This test is to demonstrate the graph rewrite of grappler plugin under + # the condition that the function returns different number of internal + # states. + input_shape = 10 + rnn_state_size = 8 + output_shape = 8 + timestep = 4 + batch = 100 + epoch = 1 + + with self.cached_session(config=_config, use_gpu=True) as sess: + (x_train, y_train), _ = testing_utils.get_test_data( + train_samples=batch, + test_samples=0, + input_shape=(timestep, input_shape), + num_classes=output_shape) + y_train = keras.utils.to_categorical(y_train, output_shape) + + layer = keras.layers.UnifiedLSTM(rnn_state_size, return_runtime=True) + + inputs = array_ops.placeholder( + dtypes.float32, shape=(None, timestep, input_shape), name='inputs') + predict = array_ops.placeholder( + dtypes.float32, shape=(None, output_shape), name='predict') + + zeros = array_ops.zeros([batch, output_shape]) + dummy_runtime = constant_op.constant( + 'unknown', dtype=dtypes.string, name='runtime') + a = constant_op.constant(0) + b = constant_op.constant(1) + # Will always run the lstm layer. + outputs, runtime = control_flow_ops.cond( + gen_math_ops.less(a, b), + lambda: layer(inputs), + lambda: (zeros, dummy_runtime)) + loss = losses.softmax_cross_entropy(predict, outputs) + optimizer = gradient_descent.GradientDescentOptimizer(0.001) + train_op = optimizer.minimize(loss) + + sess.run([variables.global_variables_initializer()]) + existing_loss = 0 + + for _ in range(epoch): + loss_value, _, runtime_value = sess.run([loss, train_op, runtime], { + inputs: x_train, + predict: y_train + }) + if test.is_gpu_available(): + self.assertEqual(runtime_value, b'cudnn') + else: + self.assertEqual(runtime_value, b'cpu') + # Make sure the loss is updated for every epoch + # (layer weights properly updated). + self.assertNotEqual(existing_loss, loss_value) + existing_loss = loss_value + + # b/120919032 + @test_util.run_deprecated_v1 + def test_regularizers_LSTM(self): + embedding_dim = 4 + layer_class = keras.layers.UnifiedLSTM + layer = layer_class( + 5, + return_sequences=False, + weights=None, + input_shape=(None, embedding_dim), + kernel_regularizer=keras.regularizers.l1(0.01), + recurrent_regularizer=keras.regularizers.l1(0.01), + bias_regularizer='l2', + activity_regularizer='l1') + layer.build((None, None, 2)) + self.assertEqual(len(layer.losses), 3) + x = keras.backend.variable(np.ones((2, 3, 2))) + layer(x) + self.assertEqual(len(layer.get_losses_for(x)), 1) + + +class LSTMLayerV1OnlyTest(test.TestCase, parameterized.TestCase): + + @test_util.run_v1_only('b/121278392') + @test_util.run_in_graph_and_eager_modes(config=_config) + def test_dropout_LSTM(self): + num_samples = 2 + timesteps = 3 + embedding_dim = 4 + units = 2 + testing_utils.layer_test( + keras.layers.UnifiedLSTM, + kwargs={ + 'units': units, + 'dropout': 0.1, + 'recurrent_dropout': 0.1 + }, + input_shape=(num_samples, timesteps, embedding_dim)) + + @test_util.run_v1_only('b/120941292') @test_util.run_in_graph_and_eager_modes(config=_config) def test_statefulness_LSTM(self): num_samples = 2 -- GitLab From f1102cacd4a3cb8eb9bb11af42b5e20a4f6f4162 Mon Sep 17 00:00:00 2001 From: Rohan Jain Date: Wed, 19 Dec 2018 18:23:07 -0800 Subject: [PATCH 0145/1765] Moving the repeat after the sloppy parallel interleave to make sure that each epoch is fully done before moving on. This removes the flakiness of the tests as well. PiperOrigin-RevId: 226266737 --- tensorflow/contrib/tpu/BUILD | 1 - tensorflow/contrib/tpu/python/tpu/datasets.py | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/tensorflow/contrib/tpu/BUILD b/tensorflow/contrib/tpu/BUILD index 7664131813..416abcf068 100644 --- a/tensorflow/contrib/tpu/BUILD +++ b/tensorflow/contrib/tpu/BUILD @@ -343,7 +343,6 @@ tf_py_test( "//tensorflow/python:client_testlib", ":datasets", ], - flaky = 1, # TODO(b/117363808): fails 1/1000 OSS runs grpc_enabled = True, shard_count = 4, ) diff --git a/tensorflow/contrib/tpu/python/tpu/datasets.py b/tensorflow/contrib/tpu/python/tpu/datasets.py index 8d6245390f..bc0cd41d21 100644 --- a/tensorflow/contrib/tpu/python/tpu/datasets.py +++ b/tensorflow/contrib/tpu/python/tpu/datasets.py @@ -142,15 +142,12 @@ def StreamingFilesDataset(files, source_dataset = source_dataset.shuffle( buffer_size=filename_shuffle_buffer_size) - # NOTE: We perform the `repeat` on the source dataset, because the output - # dataset does not currently have enough information to recreate an iterator - # over the source dataset when it reaches the end. - source_dataset = source_dataset.repeat(num_epochs) - source_dataset = source_dataset.apply( interleave_ops.parallel_interleave( reader_fn, cycle_length=num_parallel_reads, sloppy=sloppy)) + source_dataset = source_dataset.repeat(num_epochs) + if batch_transfer_size: source_dataset = source_dataset.batch(batch_transfer_size) -- GitLab From d8e755a0da01068e60a797efaf76df71b65bacbb Mon Sep 17 00:00:00 2001 From: Rick Chao Date: Wed, 19 Dec 2018 18:26:04 -0800 Subject: [PATCH 0146/1765] Replace mode string literals 'train', 'test', and 'predict' with ModeKeys constants. PiperOrigin-RevId: 226266973 --- tensorflow/python/keras/callbacks.py | 42 ++++++------- tensorflow/python/keras/engine/training.py | 2 +- .../python/keras/engine/training_arrays.py | 37 ++++++------ .../keras/engine/training_distributed.py | 59 +++++++++---------- .../python/keras/engine/training_generator.py | 40 ++++++------- 5 files changed, 88 insertions(+), 92 deletions(-) diff --git a/tensorflow/python/keras/callbacks.py b/tensorflow/python/keras/callbacks.py index 53a51f5274..589cd992d6 100644 --- a/tensorflow/python/keras/callbacks.py +++ b/tensorflow/python/keras/callbacks.py @@ -43,6 +43,7 @@ from tensorflow.python.ops import variables from tensorflow.python.platform import tf_logging as logging from tensorflow.python.summary import summary as tf_summary from tensorflow.python.training import saver +from tensorflow.python.training.mode_keys import ModeKeys from tensorflow.python.util.tf_export import keras_export try: @@ -51,11 +52,6 @@ except ImportError: requests = None -_TRAIN = 'train' -_TEST = 'test' -_PREDICT = 'predict' - - # pylint: disable=protected-access def configure_callbacks(callbacks, model, @@ -66,7 +62,7 @@ def configure_callbacks(callbacks, samples=None, verbose=1, count_mode='steps', - mode=_TRAIN): + mode=ModeKeys.TRAIN): """Configures callbacks for use in various training loops. Arguments: @@ -79,8 +75,8 @@ def configure_callbacks(callbacks, samples: Number of training samples. verbose: int, 0 or 1. Keras logging verbosity to pass to ProgbarLogger. count_mode: One of 'steps' or 'samples'. Per-batch or per-sample count. - mode: String. One of 'train', 'test', or 'predict'. Which loop mode to - configure callbacks for. + mode: String. One of ModeKeys.TRAIN, ModeKeys.TEST, or ModeKeys.PREDICT. + Which loop mode to configure callbacks for. Returns: Instance of CallbackList used to control all Callbacks. @@ -93,7 +89,7 @@ def configure_callbacks(callbacks, callbacks = [] # Add additional callbacks during training. - if mode == _TRAIN: + if mode == ModeKeys.TRAIN: model.history = History() stateful_metric_names = None if hasattr(model, 'metrics_names'): @@ -113,7 +109,7 @@ def configure_callbacks(callbacks, callback_metrics = [] # When we have deferred build scenario with iterator input, we will compile # when we standardize first batch of data. - if mode != _PREDICT and hasattr(model, 'metrics_names'): + if mode != ModeKeys.PREDICT and hasattr(model, 'metrics_names'): callback_metrics = copy.copy(model.metrics_names) if do_validation: callback_metrics += ['val_' + n for n in model.metrics_names] @@ -148,7 +144,7 @@ def _is_generator_like(data): def make_logs(model, logs, outputs, mode, prefix=''): """Computes logs for sending to `on_batch_end` methods.""" - if mode in {_TRAIN, _TEST}: + if mode in {ModeKeys.TRAIN, ModeKeys.TEST}: if hasattr(model, 'metrics_names'): for label, output in zip(model.metrics_names, outputs): logs[prefix + label] = output @@ -220,27 +216,27 @@ class CallbackList(object): def _call_begin_hook(self, mode): """Helper function for on_{train|test|predict}_begin methods.""" - if mode == _TRAIN: + if mode == ModeKeys.TRAIN: self.on_train_begin() - elif mode == _TEST: + elif mode == ModeKeys.TEST: self.on_test_begin() else: self.on_predict_begin() def _call_end_hook(self, mode): """Helper function for on_{train|test|predict}_end methods.""" - if mode == _TRAIN: + if mode == ModeKeys.TRAIN: self.on_train_end() - elif mode == _TEST: + elif mode == ModeKeys.TEST: self.on_test_end() else: self.on_predict_end() def on_batch_begin(self, batch, logs=None): - self._call_batch_hook(_TRAIN, 'begin', batch, logs=logs) + self._call_batch_hook(ModeKeys.TRAIN, 'begin', batch, logs=logs) def on_batch_end(self, batch, logs=None): - self._call_batch_hook(_TRAIN, 'end', batch, logs=logs) + self._call_batch_hook(ModeKeys.TRAIN, 'end', batch, logs=logs) def on_epoch_begin(self, epoch, logs=None): """Calls the `on_epoch_begin` methods of its callbacks. @@ -280,7 +276,7 @@ class CallbackList(object): logs: dict. Has keys `batch` and `size` representing the current batch number and the size of the batch. """ - self._call_batch_hook(_TRAIN, 'begin', batch, logs=logs) + self._call_batch_hook(ModeKeys.TRAIN, 'begin', batch, logs=logs) def on_train_batch_end(self, batch, logs=None): """Calls the `on_train_batch_end` methods of its callbacks. @@ -289,7 +285,7 @@ class CallbackList(object): batch: integer, index of batch within the current epoch. logs: dict. Metric results for this batch. """ - self._call_batch_hook(_TRAIN, 'end', batch, logs=logs) + self._call_batch_hook(ModeKeys.TRAIN, 'end', batch, logs=logs) def on_test_batch_begin(self, batch, logs=None): """Calls the `on_test_batch_begin` methods of its callbacks. @@ -299,7 +295,7 @@ class CallbackList(object): logs: dict. Has keys `batch` and `size` representing the current batch number and the size of the batch. """ - self._call_batch_hook(_TEST, 'begin', batch, logs=logs) + self._call_batch_hook(ModeKeys.TEST, 'begin', batch, logs=logs) def on_test_batch_end(self, batch, logs=None): """Calls the `on_test_batch_end` methods of its callbacks. @@ -308,7 +304,7 @@ class CallbackList(object): batch: integer, index of batch within the current epoch. logs: dict. Metric results for this batch. """ - self._call_batch_hook(_TEST, 'end', batch, logs=logs) + self._call_batch_hook(ModeKeys.TEST, 'end', batch, logs=logs) def on_predict_batch_begin(self, batch, logs=None): """Calls the `on_predict_batch_begin` methods of its callbacks. @@ -318,7 +314,7 @@ class CallbackList(object): logs: dict. Has keys `batch` and `size` representing the current batch number and the size of the batch. """ - self._call_batch_hook(_PREDICT, 'begin', batch, logs=logs) + self._call_batch_hook(ModeKeys.PREDICT, 'begin', batch, logs=logs) def on_predict_batch_end(self, batch, logs=None): """Calls the `on_predict_batch_end` methods of its callbacks. @@ -327,7 +323,7 @@ class CallbackList(object): batch: integer, index of batch within the current epoch. logs: dict. Metric results for this batch. """ - self._call_batch_hook(_PREDICT, 'end', batch, logs=logs) + self._call_batch_hook(ModeKeys.PREDICT, 'end', batch, logs=logs) def on_train_begin(self, logs=None): """Calls the `on_train_begin` methods of its callbacks. diff --git a/tensorflow/python/keras/engine/training.py b/tensorflow/python/keras/engine/training.py index 4a398cdb16..ce8570e31e 100644 --- a/tensorflow/python/keras/engine/training.py +++ b/tensorflow/python/keras/engine/training.py @@ -2057,7 +2057,7 @@ class Model(Network): # Gets network outputs. Does not update weights. # Does update the network states. kwargs = getattr(self, '_function_kwargs', {}) - with K.name_scope('predict'): + with K.name_scope(ModeKeys.PREDICT): self.predict_function = K.function( inputs, self.outputs, diff --git a/tensorflow/python/keras/engine/training_arrays.py b/tensorflow/python/keras/engine/training_arrays.py index 47074e6087..e4f91fa18a 100644 --- a/tensorflow/python/keras/engine/training_arrays.py +++ b/tensorflow/python/keras/engine/training_arrays.py @@ -41,7 +41,7 @@ except ImportError: def _get_model_feed(model, mode): - if mode == 'predict': + if mode == ModeKeys.PREDICT: feed = model._feed_inputs else: feed = ( @@ -85,7 +85,7 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): inputs: List or dict of model inputs. targets: Optional list of model targets. sample_weights: Optional list of sample weight arrays. - mode: One of 'train'/'test'/'predict'. + mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT. Returns: Feed values for the model in the given mode. @@ -111,7 +111,8 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): targets = targets or [] sample_weights = sample_weights or [] ins = inputs + targets + sample_weights - if mode == 'train' and not isinstance(K.symbolic_learning_phase(), int): + if mode == ModeKeys.TRAIN and not isinstance(K.symbolic_learning_phase(), + int): ins += [True] return ins @@ -138,10 +139,10 @@ def model_iteration(model, initial_epoch=0, steps_per_epoch=None, validation_steps=None, - mode='train', + mode=ModeKeys.TRAIN, validation_in_fit=False, **kwargs): - """Loop function for arrays of data with modes 'train'/'test'/'predict'. + """Loop function for arrays of data with modes TRAIN/TEST/PREDICT. Arguments: model: Keras Model instance. @@ -165,7 +166,7 @@ def model_iteration(model, the default value of `None`. validation_steps: Number of steps to run validation for (only if doing validation from data tensors). Ignored with the default value of `None`. - mode: One of 'train'/'test'/'predict'. + mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT. validation_in_fit: DEPRECATED: if true, then this method is invoked from within training iteration (for validation). In this case, do not copy weights when using a tf.distribute.Strategy. The input is deprecated as @@ -174,9 +175,9 @@ def model_iteration(model, **kwargs: Additional arguments for backwards compatibility. Returns: - - In 'train' mode: `History` object. - - In 'test' mode: Evaluation metrics. - - In 'predict' mode: Outputs of the Model called on inputs. + - In TRAIN mode: `History` object. + - In TEST mode: Evaluation metrics. + - In PREDICT mode: Outputs of the Model called on inputs. Raises: ValueError: in case of invalid arguments. @@ -186,7 +187,7 @@ def model_iteration(model, steps_per_epoch = kwargs['steps'] _validate_arguments(steps_per_epoch, validation_steps, kwargs) - if mode == 'train': + if mode == ModeKeys.TRAIN: _print_train_info(inputs, val_inputs, steps_per_epoch, verbose) # Enter DistributionStrategy scope. @@ -230,7 +231,7 @@ def model_iteration(model, indices_for_conversion_to_dense.append(i) # Select aggregation method. - if mode == 'predict': + if mode == ModeKeys.PREDICT: aggregator = training_utils.OutputsAggregator(use_steps, num_samples_or_steps) else: @@ -364,14 +365,14 @@ def model_iteration(model, steps_per_epoch=validation_steps, callbacks=callbacks, verbose=0, - mode='test', + mode=ModeKeys.TEST, validation_in_fit=True) if not isinstance(val_results, list): val_results = [val_results] epoch_logs = cbks.make_logs( model, epoch_logs, val_results, mode, prefix='val_') - if mode == 'train': + if mode == ModeKeys.TRAIN: # Epochs only apply to `fit`. callbacks.on_epoch_end(epoch, epoch_logs) progbar.on_epoch_end(epoch, epoch_logs) @@ -385,12 +386,14 @@ def model_iteration(model, model, model._distributed_model, mode) scope.__exit__(None, None, None) - if mode == 'train': + if mode == ModeKeys.TRAIN: return model.history return results # For backwards compatibility for internal users of these loops. -fit_loop = functools.partial(model_iteration, mode='train') -test_loop = functools.partial(model_iteration, mode='test', shuffle=False) -predict_loop = functools.partial(model_iteration, mode='predict', shuffle=False) +fit_loop = functools.partial(model_iteration, mode=ModeKeys.TRAIN) +test_loop = functools.partial( + model_iteration, mode=ModeKeys.TEST, shuffle=False) +predict_loop = functools.partial( + model_iteration, mode=ModeKeys.PREDICT, shuffle=False) diff --git a/tensorflow/python/keras/engine/training_distributed.py b/tensorflow/python/keras/engine/training_distributed.py index 7842228e05..7cf5854af0 100644 --- a/tensorflow/python/keras/engine/training_distributed.py +++ b/tensorflow/python/keras/engine/training_distributed.py @@ -19,7 +19,6 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -import enum # pylint: disable=g-bad-import-order import numpy as np from tensorflow.python.distribute import distribute_lib @@ -38,13 +37,10 @@ from tensorflow.python.keras.utils.generic_utils import Progbar from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.training.mode_keys import ModeKeys from tensorflow.python.util import nest -class _Mode(enum.Enum): - TRAIN = 'train' - TEST = 'test' - PREDICT = 'predict' # TODO(priyag, sourabhbajaj): Refactor this file to address code duplication. @@ -100,10 +96,10 @@ def experimental_fit_loop(model, if model._compile_distribution: clone_model_on_replicas(model, current_strategy, make_callback_model=True, inputs=inputs, - targets=targets, mode=_Mode.TRAIN) + targets=targets, mode=ModeKeys.TRAIN) else: _build_distributed_network(model, current_strategy, inputs, - targets, mode=_Mode.TRAIN) + targets, mode=ModeKeys.TRAIN) (grouped_inputs, grouped_outputs, grouped_updates, grouped_session_args) = current_strategy.extended.call_for_each_replica( @@ -215,7 +211,7 @@ def experimental_fit_loop(model, # the weights back to the original model before we can run validation. with current_strategy.scope(): _copy_weights_to_original_model( - model, model._distributed_model_train, 'train') + model, model._distributed_model_train, ModeKeys.TRAIN) val_outs = experimental_test_loop( # pylint: disable=undefined-variable model, @@ -237,7 +233,7 @@ def experimental_fit_loop(model, # Copy the weights back from the replicated model to the original model. with current_strategy.scope(): _copy_weights_to_original_model(model, model._distributed_model_train, - 'train') + ModeKeys.TRAIN) scope.__exit__(None, None, None) return model.history @@ -281,10 +277,10 @@ def experimental_test_loop(model, if model._compile_distribution: clone_model_on_replicas(model, current_strategy, make_callback_model=False, inputs=inputs, - targets=targets, mode=_Mode.TEST) + targets=targets, mode=ModeKeys.TEST) else: _build_distributed_network(model, current_strategy, inputs, - targets, mode=_Mode.TEST) + targets, mode=ModeKeys.TEST) (grouped_inputs, grouped_outputs, grouped_updates, grouped_session_args) = current_strategy.extended.call_for_each_replica( @@ -397,10 +393,10 @@ def experimental_predict_loop(model, iterator, verbose=0, steps=None): if model._compile_distribution: clone_model_on_replicas(model, current_strategy, make_callback_model=False, inputs=inputs, - mode=_Mode.PREDICT) + mode=ModeKeys.PREDICT) else: _build_distributed_network(model, current_strategy, inputs, - mode=_Mode.PREDICT) + mode=ModeKeys.PREDICT) (grouped_inputs, grouped_outputs, grouped_updates, grouped_session_args) = current_strategy.extended.call_for_each_replica( @@ -535,7 +531,7 @@ def _build_network_on_replica(model, inputs=None, targets=None, mode=None): if isinstance(targets, tuple): targets = nest.flatten(targets) - if mode == _Mode.PREDICT: + if mode == ModeKeys.PREDICT: _custom_compile_for_predict(updated_model) else: updated_model.compile( @@ -557,11 +553,11 @@ def _build_distributed_network(model, strategy, inputs=None, targets=None, distributed_model = strategy.extended.call_for_each_replica( _build_network_on_replica, args=(model, inputs, targets, mode)) - if mode is _Mode.TRAIN: + if mode is ModeKeys.TRAIN: model._distributed_model_train = distributed_model - elif mode is _Mode.TEST: + elif mode is ModeKeys.TEST: model._distributed_model_test = distributed_model - elif mode is _Mode.PREDICT: + elif mode is ModeKeys.PREDICT: model._distributed_model_predict = distributed_model else: model._distributed_model = distributed_model @@ -594,7 +590,7 @@ def _clone_and_build_model(model, inputs=None, targets=None, mode=None): if isinstance(targets, tuple): targets = nest.flatten(targets) - if mode == _Mode.PREDICT: + if mode == ModeKeys.PREDICT: _custom_compile_for_predict(cloned_model) else: cloned_model.compile( @@ -615,11 +611,11 @@ def clone_model_on_replicas(model, strategy, make_callback_model=False, with K.get_graph().as_default(), strategy.scope(): distributed_model = strategy.extended.call_for_each_replica( _clone_and_build_model, args=(model, inputs, targets, mode)) - if mode is _Mode.TRAIN: + if mode is ModeKeys.TRAIN: model._distributed_model_train = distributed_model - elif mode is _Mode.TEST: + elif mode is ModeKeys.TEST: model._distributed_model_test = distributed_model - elif mode is _Mode.PREDICT: + elif mode is ModeKeys.PREDICT: model._distributed_model_predict = distributed_model else: model._distributed_model = distributed_model @@ -659,7 +655,7 @@ def _make_execution_function(model, mode): if not model._distributed_model: if model._compile_distribution: clone_model_on_replicas( - model, strategy, make_callback_model=(mode == 'train')) + model, strategy, make_callback_model=(mode == ModeKeys.TRAIN)) else: _build_distributed_network(model, strategy) @@ -674,7 +670,7 @@ def _make_execution_function(model, mode): grouped_session_args) = strategy.extended.call_for_each_replica( _per_device_function, args=(model._distributed_model,)) - if mode == 'train': + if mode == ModeKeys.TRAIN: # Initialize the variables in the replicated model. This is necessary for # multi-worker training because on some workers, initialization is not # needed. This method does initialization or waiting for initialization @@ -692,7 +688,7 @@ def _make_execution_function(model, mode): grouped_outputs, grouped_updates, grouped_session_args, - with_loss_tensor=(mode != 'predict')) + with_loss_tensor=(mode != ModeKeys.PREDICT)) return K.function( all_inputs, @@ -708,7 +704,7 @@ def _make_eager_execution_function(model, mode): if not model._distributed_model: if model._compile_distribution: clone_model_on_replicas( - model, strategy, make_callback_model=(mode == 'train')) + model, strategy, make_callback_model=(mode == ModeKeys.TRAIN)) else: _build_distributed_network(model, strategy) @@ -732,7 +728,7 @@ def _make_eager_execution_function(model, mode): strategy, grouped_inputs, grouped_outputs, - with_loss_tensor=(mode != 'predict')) + with_loss_tensor=(mode != ModeKeys.PREDICT)) return K.function( all_inputs, @@ -748,7 +744,7 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): inputs: List or dict of model inputs. targets: Optional list of model targets. sample_weights: Optional list of sample weight arrays. - mode: One of 'train'/'test'/'predict'. + mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT. Returns: Feed values for the model in the given mode. @@ -758,7 +754,7 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): inputs = distributed_training_utils.flatten_perdevice_values(strategy, inputs) targets = distributed_training_utils.flatten_perdevice_values( strategy, targets) - if mode == 'predict': + if mode == ModeKeys.PREDICT: sample_weights = [] targets = [] else: @@ -766,7 +762,8 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): None for _ in range(len(model.outputs) * strategy.num_replicas_in_sync) ] ins = inputs + targets + sample_weights - if mode == 'train' and not isinstance(K.symbolic_learning_phase(), int): + if mode == ModeKeys.TRAIN and not isinstance(K.symbolic_learning_phase(), + int): ins += [True] return ins @@ -785,7 +782,7 @@ def _copy_weights_to_distributed_model(original_model, grouped_model): def _copy_weights_to_original_model(model, grouped_model, mode): """Copies weights from first distributed model back to original model.""" - if model._distribution_strategy and mode == 'train': + if model._distribution_strategy and mode == ModeKeys.TRAIN: updated_weights = model._distribution_strategy.unwrap( grouped_model)[0].get_weights() model.set_weights(updated_weights) @@ -793,7 +790,7 @@ def _copy_weights_to_original_model(model, grouped_model, mode): def _per_device_aggregate_batch(batch_outs, model, mode): """Aggregates the per-device batch-level outputs from a distributed step.""" - if model._distribution_strategy is not None and mode == 'predict': + if model._distribution_strategy is not None and mode == ModeKeys.PREDICT: total_batch_outs = [] for i in range(len(model.outputs)): num_replicas = model._distribution_strategy.num_replicas_in_sync diff --git a/tensorflow/python/keras/engine/training_generator.py b/tensorflow/python/keras/engine/training_generator.py index 03cbe91dc4..d1699b2827 100644 --- a/tensorflow/python/keras/engine/training_generator.py +++ b/tensorflow/python/keras/engine/training_generator.py @@ -52,10 +52,10 @@ def model_iteration(model, use_multiprocessing=False, shuffle=False, initial_epoch=0, - mode='train', + mode=ModeKeys.TRAIN, batch_size=None, **kwargs): - """Loop function for arrays of data with modes 'train'/'test'/'predict'. + """Loop function for arrays of data with modes TRAIN/TEST/PREDICT. Arguments: model: Keras Model instance. @@ -90,16 +90,16 @@ def model_iteration(model, `None`. initial_epoch: Epoch at which to start training (useful for resuming a previous training run). - mode: One of 'train'/'test'/'predict'. + mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT. batch_size: Integer batch size or None if unknown. Will only be used if `data` is in NumPy/Tensor format. **kwargs: Additional arguments for backwards compatibility. `steps` is accepted as an alias for `steps_per_epoch`. Returns: - - In 'train' mode: `History` object. - - In 'test' mode: Evaluation metrics. - - In 'predict' mode: Outputs of the Model called on inputs. + - In TRAIN mode: `History` object. + - In TEST mode: Evaluation metrics. + - In PREDICT mode: Outputs of the Model called on inputs. Raises: ValueError: in case of invalid arguments. @@ -152,14 +152,14 @@ def model_iteration(model, progbar.params = callbacks.params progbar.params['verbose'] = verbose - if mode == 'predict': + if mode == ModeKeys.PREDICT: aggregator = training_utils.OutputsAggregator(True, steps_per_epoch) else: aggregator = training_utils.MetricsAggregator(True, steps_per_epoch) if should_set_learning_phase: old_learning_phase = backend.learning_phase() - backend.set_learning_phase(1 if mode == 'train' else 0) + backend.set_learning_phase(1 if mode == ModeKeys.TRAIN else 0) callbacks.model.stop_training = False callbacks._call_begin_hook(mode) @@ -226,14 +226,14 @@ def model_iteration(model, max_queue_size=max_queue_size, callbacks=callbacks, verbose=0, - mode='test') + mode=ModeKeys.TEST) if not isinstance(val_results, list): val_results = [val_results] epoch_logs = cbks.make_logs( model, epoch_logs, val_results, mode, prefix='val_') - if mode == 'train': + if mode == ModeKeys.TRAIN: # Epochs only apply to `fit`. callbacks.on_epoch_end(epoch, epoch_logs) progbar.on_epoch_end(epoch, epoch_logs) @@ -246,17 +246,17 @@ def model_iteration(model, if should_set_learning_phase: backend.set_learning_phase(old_learning_phase) - if mode == 'train': + if mode == ModeKeys.TRAIN: return model.history return results # Maintain compatibility with the existing names. -fit_generator = functools.partial(model_iteration, mode='train') +fit_generator = functools.partial(model_iteration, mode=ModeKeys.TRAIN) evaluate_generator = functools.partial( - model_iteration, mode='test', shuffle=False) + model_iteration, mode=ModeKeys.TEST, shuffle=False) predict_generator = functools.partial( - model_iteration, mode='predict', shuffle=False) + model_iteration, mode=ModeKeys.PREDICT, shuffle=False) def _get_next_batch(output_generator, mode): @@ -268,7 +268,7 @@ def _get_next_batch(output_generator, mode): logging.warning('Your dataset iterator ran out of data.') return None if not isinstance(generator_output, tuple): - if mode == 'predict': + if mode == ModeKeys.PREDICT: # Always wrap in a tuple. return (generator_output,) else: @@ -307,7 +307,7 @@ def _validate_arguments(is_sequence, use_multiprocessing, workers, `keras.utils.data_utils.Sequence` object or Eager Iterator or Dataset. validation_steps: Total number of steps (batches of samples) before declaring validation finished. - mode: One of 'train'/'test'/'predict'. + mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT. kwargs: Additional arguments for backwards compatibility. Raises: @@ -323,7 +323,7 @@ def _validate_arguments(is_sequence, use_multiprocessing, workers, ' class.')) if steps_per_epoch is None: - arg_name = 'steps_per_epoch' if mode == 'train' else 'steps' + arg_name = 'steps_per_epoch' if mode == ModeKeys.TRAIN else 'steps' raise ValueError('Please specify the number of steps via the ' '`{}` argument.'.format(arg_name)) @@ -429,11 +429,11 @@ def _make_enqueued_generator(generator, def _make_execution_function(model, mode, class_weight=None): """Makes function to run one step of model execution.""" - if mode == 'train': + if mode == ModeKeys.TRAIN: if not context.executing_eagerly(): model._make_fit_function() f = functools.partial(model.train_on_batch, class_weight=class_weight) - elif mode == 'test': + elif mode == ModeKeys.TEST: if not context.executing_eagerly(): model._make_eval_function() f = model.test_on_batch @@ -446,7 +446,7 @@ def _make_execution_function(model, mode, class_weight=None): f = predict_on_batch # Maintain stateful metrics across batch-level calls. - if mode != 'predict': + if mode != ModeKeys.PREDICT: f = functools.partial(f, reset_metrics=False) return f -- GitLab From 67cd0544a60a7b018e2adb18293855f156d18c25 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Wed, 19 Dec 2018 18:58:02 -0800 Subject: [PATCH 0147/1765] Fix infeed in replay_computation.cc Pass in the correct shape (stripping off the token from the kInfeed op). PiperOrigin-RevId: 226269498 --- tensorflow/compiler/xla/tools/replay_computation.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tensorflow/compiler/xla/tools/replay_computation.cc b/tensorflow/compiler/xla/tools/replay_computation.cc index 27a8dd1330..75023f6edf 100644 --- a/tensorflow/compiler/xla/tools/replay_computation.cc +++ b/tensorflow/compiler/xla/tools/replay_computation.cc @@ -157,7 +157,9 @@ StatusOr ReplayComputation(const HloSnapshot& module, << "--generate_fake_infeed only works if the model has 0 or 1 " "infeed ops, but this one has >= 2."; provide_infeed = true; - infeed_shape = Shape(instruction.shape()); + // The kInfeed instruction should have a shape (buffer, token). We + // want to infeed just `buffer`. + infeed_shape = Shape(instruction.shape()).tuple_shapes(0); LOG(INFO) << "Generating fake infeed shape for inferred shape: " << ShapeUtil::HumanString(infeed_shape); } -- GitLab From f97d56c9175beb075cb18e517b7d05059c8d8dd4 Mon Sep 17 00:00:00 2001 From: Russell Power Date: Wed, 19 Dec 2018 19:13:50 -0800 Subject: [PATCH 0148/1765] ArithmeticOptimizer: Memoize computation of in-place ops. Previously, for each op A, we walked the graph to find all connected in-place ops. This is a transitive relation so we can reference the results from previous lookups to avoid quadratic behavior on deep graphs. PiperOrigin-RevId: 226270951 --- .../optimizers/arithmetic_optimizer.cc | 41 ++++++------ tensorflow/core/grappler/utils.cc | 62 +++++++++++++++++-- tensorflow/core/grappler/utils.h | 13 +++- 3 files changed, 88 insertions(+), 28 deletions(-) diff --git a/tensorflow/core/grappler/optimizers/arithmetic_optimizer.cc b/tensorflow/core/grappler/optimizers/arithmetic_optimizer.cc index e28f991e2d..94a87c3ff2 100644 --- a/tensorflow/core/grappler/optimizers/arithmetic_optimizer.cc +++ b/tensorflow/core/grappler/optimizers/arithmetic_optimizer.cc @@ -3316,25 +3316,6 @@ bool UniqueNodes::SameNode(const NodeDef& node1, const NodeDef& node2) const { return true; } -namespace { - -bool FeedsInPlaceOp(const SimpleGraphView& graph_view, const NodeDef& node) { - const std::unordered_set op_types_to_traverse = { - node.op(), "Identity", "IdentityN", "Reshape", - "ExpandDims", "Enter", "Switch", "Merge"}; - int node_idx = graph_view.index(node.name()); - std::set node_fanout; - graph_view.DepthFirstSearch(op_types_to_traverse, node_idx, &node_fanout); - for (int fanout : node_fanout) { - if (ModifiesInputsInPlace(graph_view.graph()->node(fanout))) { - return true; - } - } - return false; -} - -} // namespace - bool ArithmeticOptimizer::CanDedup(const NodeDef& node) const { if (nodes_to_preserve_.find(node.name()) != nodes_to_preserve_.end()) { return false; @@ -3361,12 +3342,28 @@ void ArithmeticOptimizer::DedupComputations() { } std::set duplicates; // Populate feed_inplace_op; - std::unordered_set feeds_inplace_op; + std::unordered_set feeds_inplace_op; for (int i = 0; i < optimized_graph_->node_size(); ++i) { - if (FeedsInPlaceOp(graph_view, optimized_graph_->node(i))) { - feeds_inplace_op.insert(optimized_graph_->mutable_node(i)); + const NodeDef& root = optimized_graph_->node(i); + if (feeds_inplace_op.find(&root) != feeds_inplace_op.end()) { + continue; + } + + if (ModifiesInputsInPlace(root)) { + const std::unordered_set op_types_to_traverse = { + root.op(), "Identity", "IdentityN", "Reshape", + "ExpandDims", "Enter", "Switch", "Merge"}; + + graph_view.DepthFirstSearchWithCallback( + op_types_to_traverse, i, + [&](const NodeDef& node) { + feeds_inplace_op.insert(&node); + return false; + }, + SimpleGraphView::kFollowInputs /* search through inputs */); } } + do { stop = true; UniqueNodes nodes; diff --git a/tensorflow/core/grappler/utils.cc b/tensorflow/core/grappler/utils.cc index 90ad04cf47..d8fb88d95f 100644 --- a/tensorflow/core/grappler/utils.cc +++ b/tensorflow/core/grappler/utils.cc @@ -473,7 +473,8 @@ Status SimpleGraphView::Initialize( void SimpleGraphView::DepthFirstSearch( const std::unordered_set& op_types_to_traverse, int root_node, - std::set* nodes_found) const { + std::set* nodes_found, + SimpleGraphView::SearchDirection direction) const { nodes_found->clear(); const string& op_type = graph_->node(root_node).op(); if (!op_types_to_traverse.empty() && @@ -483,6 +484,16 @@ void SimpleGraphView::DepthFirstSearch( std::vector stack; stack.reserve(32); stack.push_back(root_node); + + auto push_neighbors = [&stack, + &nodes_found](absl::Span neighbors) { + for (auto output_idx : neighbors) { + if (nodes_found->find(output_idx) == nodes_found->end()) { + stack.push_back(output_idx); + } + } + }; + while (!stack.empty()) { const int node_idx = stack.back(); stack.pop_back(); @@ -490,10 +501,51 @@ void SimpleGraphView::DepthFirstSearch( const string& op_type = graph_->node(node_idx).op(); if (op_types_to_traverse.empty() || op_types_to_traverse.find(op_type) != op_types_to_traverse.end()) { - for (auto output_idx : this->outputs(node_idx)) { - if (nodes_found->find(output_idx) == nodes_found->end()) { - stack.push_back(output_idx); - } + if (direction == kFollowOutputs) { + push_neighbors(this->outputs(node_idx)); + } else { + push_neighbors(this->inputs(node_idx)); + } + } + } +} + +void SimpleGraphView::DepthFirstSearchWithCallback( + const std::unordered_set& op_types_to_traverse, int node_idx, + SimpleGraphView::DFSCallback callback, + SimpleGraphView::SearchDirection direction) const { + std::set nodes_found; + nodes_found.clear(); + const string& op_type = graph_->node(node_idx).op(); + if (!op_types_to_traverse.empty() && + op_types_to_traverse.find(op_type) == op_types_to_traverse.end()) { + return; + } + std::vector stack; + stack.reserve(32); + stack.push_back(node_idx); + auto push_neighbors = [&stack, + &nodes_found](absl::Span neighbors) { + for (auto output_idx : neighbors) { + if (nodes_found.find(output_idx) == nodes_found.end()) { + stack.push_back(output_idx); + } + } + }; + while (!stack.empty()) { + const int node_idx = stack.back(); + stack.pop_back(); + if (callback(graph_->node(node_idx))) { + return; + } + nodes_found.insert(node_idx); + const string& op_type = graph_->node(node_idx).op(); + if (op_types_to_traverse.empty() || + op_types_to_traverse.find(op_type) != op_types_to_traverse.end()) { + if (direction == kFollowOutputs) { + push_neighbors(this->outputs(node_idx)); + } else { + push_neighbors(this->inputs(node_idx)); } } } diff --git a/tensorflow/core/grappler/utils.h b/tensorflow/core/grappler/utils.h index 89a87af323..a9d6abd6db 100644 --- a/tensorflow/core/grappler/utils.h +++ b/tensorflow/core/grappler/utils.h @@ -346,13 +346,24 @@ class SimpleGraphView { return outputs_[node_idx]; } + enum SearchDirection { kFollowOutputs = 1, kFollowInputs = 2 }; + // Traverse the graph starting at `node_idx`, collecting indices of nodes // visited in nodes_found. If a node has an op in `op_types_to_traverse`, the // walk continues to its children. It is assumed that *graph_ was not modified // after the call to Initialize(). // If `op_types_to_traverse` is empty the DFS will traverse any node type. void DepthFirstSearch(const std::unordered_set& op_types_to_traverse, - int node_idx, std::set* nodes_found) const; + int node_idx, std::set* nodes_found, + SearchDirection direction = kFollowOutputs) const; + + typedef std::function DFSCallback; + + // Like DepthFirstSearch, but invoke `callback` as each node is discovered. If + // `callback` returns true, the search is terminated early. + void DepthFirstSearchWithCallback( + const std::unordered_set& op_types_to_traverse, int node_idx, + DFSCallback callback, SearchDirection direction = kFollowOutputs) const; string PrintToString() const; -- GitLab From 01b5dfc86cfc0ff341caf39724b9c48499c076b1 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 19 Dec 2018 19:42:08 -0800 Subject: [PATCH 0149/1765] [XLA] Add test assertions to xla_hlo_profile_test These assertions help catch scenarios where the profile text is missing. Without these assertions, the test would dereference memory locations that they should not. PiperOrigin-RevId: 226273052 --- tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc b/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc index e57d072a06..1538f2afba 100644 --- a/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc +++ b/tensorflow/compiler/xla/tests/xla_hlo_profile_test.cc @@ -225,14 +225,17 @@ XLA_TEST_F(HloProfileTest, ProfileSingleComputation) { line_no++; // Skip 'Execution profile for ....' + ASSERT_LT(line_no, profile_output_lines.size()); TF_ASSERT_OK(ParseOneProfileOutputLine(profile_output_lines[line_no++], /*expect_hlo=*/false, &parsed_profile_lines)); + ASSERT_LT(line_no, profile_output_lines.size()); TF_ASSERT_OK(ParseOneProfileOutputLine(profile_output_lines[line_no++], /*expect_hlo=*/true, &parsed_profile_lines)); + ASSERT_LT(line_no, profile_output_lines.size()); TF_ASSERT_OK(ParseOneProfileOutputLine(profile_output_lines[line_no++], /*expect_hlo=*/true, &parsed_profile_lines)); -- GitLab From cc3786bacbbc09f730a40915c0ec939953c141a7 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 00:42:27 -0800 Subject: [PATCH 0150/1765] Roll-forward of CL 225051897 (adjust NCCL source so it can be built with clang). PiperOrigin-RevId: 226293762 --- third_party/nccl/archive.BUILD | 178 ++++------- third_party/nccl/build_defs.bzl.tpl | 472 ++++++++++++++++++---------- 2 files changed, 360 insertions(+), 290 deletions(-) diff --git a/third_party/nccl/archive.BUILD b/third_party/nccl/archive.BUILD index 7a08f97ef3..211b794bb0 100644 --- a/third_party/nccl/archive.BUILD +++ b/third_party/nccl/archive.BUILD @@ -1,174 +1,106 @@ # NVIDIA NCCL 2 # A package of optimized primitives for collective multi-GPU communication. -licenses(["restricted"]) +licenses(["notice"]) exports_files(["LICENSE.txt"]) load( "@local_config_nccl//:build_defs.bzl", - "gen_nccl_h", - "nccl_library", - "rdc_copts", - "rdc_library", -) -load( - "@local_config_cuda//cuda:build_defs.bzl", - "cuda_default_copts", -) - -# Generate the nccl.h header file. -gen_nccl_h( - name = "nccl_h", - output = "src/nccl.h", - template = "src/nccl.h.in", + "cuda_rdc_library", + "gen_device_srcs", + "process_srcs", ) +load("@local_config_cuda//cuda:build_defs.bzl", "cuda_default_copts") -nccl_library( +cc_library( name = "src_hdrs", - hdrs = [ - "src/nccl.h", - # src/include/common_coll.h #includes "collectives/collectives.h". - # All other #includes of collectives.h are patched in process_srcs. + hdrs = process_srcs([ "src/collectives/collectives.h", - ], - strip_include_prefix = "src", + "src/nccl.h.in", + ]), ) -nccl_library( +cc_library( name = "include_hdrs", - hdrs = glob(["src/include/*.h"]), - strip_include_prefix = "src/include", -) - -filegroup( - name = "device_hdrs", - srcs = glob(["src/collectives/device/*.h"]), + hdrs = process_srcs(glob(["src/include/*.h"])), + strip_include_prefix = "include", ) -filegroup( - name = "device_srcs", - srcs = [ - "src/collectives/device/all_gather.cu", - "src/collectives/device/all_reduce.cu", - "src/collectives/device/broadcast.cu", - "src/collectives/device/reduce.cu", - "src/collectives/device/reduce_scatter.cu", - ], -) +device_srcs = process_srcs([ + "src/collectives/device/all_gather.cu", + "src/collectives/device/all_reduce.cu", + "src/collectives/device/broadcast.cu", + "src/collectives/device/reduce.cu", + "src/collectives/device/reduce_scatter.cu", +]) -nccl_library( +# NCCL compiles the same source files with different NCCL_OP defines. RDC +# compilation requires that each compiled module has a unique ID. Clang derives +# the module ID from the path only so we need to rename the files to get +# different IDs for different parts of compilation. NVCC does not have that +# problem because it generates IDs based on preprocessed content. +gen_device_srcs( name = "sum", - srcs = [ - ":device_hdrs", - ":device_srcs", - ], - copts = ["-DNCCL_OP=0"] + rdc_copts(), - linkstatic = True, - prefix = "sum_", - deps = [ - ":include_hdrs", - ":src_hdrs", - "@local_config_cuda//cuda:cuda_headers", - ], + srcs = device_srcs, + NCCL_OP = 0, ) -nccl_library( +gen_device_srcs( name = "prod", - srcs = [ - ":device_hdrs", - ":device_srcs", - ], - copts = ["-DNCCL_OP=1"] + rdc_copts(), - linkstatic = True, - prefix = "_prod", - deps = [ - ":include_hdrs", - ":src_hdrs", - "@local_config_cuda//cuda:cuda_headers", - ], + srcs = device_srcs, + NCCL_OP = 1, ) -nccl_library( +gen_device_srcs( name = "min", - srcs = [ - ":device_hdrs", - ":device_srcs", - ], - copts = ["-DNCCL_OP=2"] + rdc_copts(), - linkstatic = True, - prefix = "min_", - deps = [ - ":include_hdrs", - ":src_hdrs", - "@local_config_cuda//cuda:cuda_headers", - ], + srcs = device_srcs, + NCCL_OP = 2, ) -nccl_library( +gen_device_srcs( name = "max", - srcs = [ - ":device_hdrs", - ":device_srcs", - ], - copts = ["-DNCCL_OP=3"] + rdc_copts(), - linkstatic = True, - prefix = "max_", - deps = [ - ":include_hdrs", - ":src_hdrs", - "@local_config_cuda//cuda:cuda_headers", - ], + srcs = device_srcs, + NCCL_OP = 3, ) -nccl_library( - name = "functions", +cuda_rdc_library( + name = "device", srcs = [ - "src/collectives/device/functions.cu", - ":device_hdrs", - ], - copts = rdc_copts(), - linkstatic = True, - deps = [ - ":include_hdrs", - ":src_hdrs", - "@local_config_cuda//cuda:cuda_headers", - ], -) - -rdc_library( - name = "device_code", - deps = [ - ":functions", ":max", ":min", ":prod", ":sum", + ] + process_srcs(glob([ + "src/collectives/device/*.h", + "src/collectives/device/functions.cu", + ])), + deps = [ + ":include_hdrs", + ":src_hdrs", ], ) # Primary NCCL target. -nccl_library( +cc_library( name = "nccl", - srcs = glob( + srcs = process_srcs(glob( include = ["src/**/*.cu"], # Exclude device-library code. exclude = ["src/collectives/device/**"], - ) + [ + )) + [ # Required for header inclusion checking (see # http://docs.bazel.build/versions/master/be/c-cpp.html#hdrs). - # Files in src/ which #include "nccl.h" load it from there rather than - # from the virtual includes directory. - "src/nccl.h", + "nccl.h", + "collectives/collectives.h", ], - hdrs = ["src/nccl.h"], - copts = cuda_default_copts(), - include_prefix = "third_party/nccl", - strip_include_prefix = "src", + hdrs = ["nccl.h"], + copts = cuda_default_copts() + ["-Wno-vla"], + include_prefix = "third_party/nccl/", visibility = ["//visibility:public"], deps = [ - ":device_code", + ":device", ":include_hdrs", - ":src_hdrs", + "@local_config_cuda//cuda:cudart_static", ], ) diff --git a/third_party/nccl/build_defs.bzl.tpl b/third_party/nccl/build_defs.bzl.tpl index 42de79c411..1fb90eea22 100644 --- a/third_party/nccl/build_defs.bzl.tpl +++ b/third_party/nccl/build_defs.bzl.tpl @@ -1,87 +1,97 @@ """Repository rule for NCCL.""" load("@local_config_cuda//cuda:build_defs.bzl", "cuda_default_copts") +load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") -def _gen_nccl_h_impl(ctx): - """Creates nccl.h from a template.""" +def _process_src_impl(ctx): + """Applies various patches to the NCCL source.""" + substitutions = { + "\"collectives.h": "\"collectives/collectives.h", + "\"../collectives.h": "\"collectives/collectives.h", + # Clang does not define __CUDACC_VER_*__, use CUDA_VERSION instead. + # TODO(csigg): Apply substitutions upstream and remove here. + "#if __CUDACC_VER_MAJOR__ >= 10 || (__CUDACC_VER_MAJOR__ >= 9 && __CUDACC_VER_MINOR__ >= 2)": "#if CUDART_VERSION >= 9200", + "#if __CUDACC_VER_MAJOR__ >= 10": "#if CUDART_VERSION >= 10000", + "#if __CUDACC_VER_MAJOR__ >= 9": "#if CUDART_VERSION >= 9000", + "#if __CUDACC_VER_MAJOR__ < 9": "#if CUDART_VERSION < 9000", + "nullptr_t": "std::nullptr_t", + } + if ctx.file.src.basename == "nccl.h.in": + substitutions.update({ + "${nccl:Major}": "2", + "${nccl:Minor}": "3", + "${nccl:Patch}": "5", + "${nccl:Suffix}": "", + "${nccl:Version}": "2305", + }) + if ctx.file.src.basename == "function.cu": + substitutions.update({ + # Don't try to initialize the host shadow copy of this device-side + # global variable. There is no host pointer to a device-side + # function, which confuses clang. + # TODO(csigg): remove when fixed in clang. + "NCCL_FUNCS2B(ncclBroadcast),": "#if __CUDA_ARCH__\nNCCL_FUNCS2B(ncclBroadcast),", + "NCCL_FUNCS2A(ncclAllReduce)": "NCCL_FUNCS2A(ncclAllReduce)\n#endif", + }) ctx.actions.expand_template( - output = ctx.outputs.output, - template = ctx.file.template, - substitutions = { - "${nccl:Major}": "2", - "${nccl:Minor}": "3", - "${nccl:Patch}": "5", - "${nccl:Suffix}": "", - "${nccl:Version}": "2305", - }, + output = ctx.outputs.out, + template = ctx.file.src, + substitutions = substitutions, ) -gen_nccl_h = rule( - implementation = _gen_nccl_h_impl, +_process_src = rule( + implementation = _process_src_impl, attrs = { - "template": attr.label(allow_single_file = True), - "output": attr.output(), + "src": attr.label(allow_single_file = True), + "out": attr.output(), }, ) -"""Creates the NCCL header file.""" +"""Processes one NCCL source file so it can be compiled with bazel and clang.""" + +def _out(src): + if not src.startswith("src/"): + fail("Source file not under src/...:", src) + src = src[4:] # Strip 'src/' + if src == "nccl.h.in": + return "nccl.h" + if src.endswith(".cu"): + return src + ".cc" + return src + +def process_srcs(srcs): + """Processes files under src/ and copies them to the parent directory.""" + [_process_src( + name = "_" + src, + src = src, + out = _out(src), + ) for src in srcs] + return ["_" + src for src in srcs] -def _process_srcs_impl(ctx): - """Appends .cc to .cu files, patches include directives.""" +def _gen_device_srcs_impl(ctx): files = [] for src in ctx.files.srcs: - if not src.is_source: - # Process only once, specifically "src/nccl.h". - files.append(src) - continue - name = src.basename - if src.extension == "cu": - name = ctx.attr.prefix + name + ".cc" + name = "%s_%s" % (ctx.attr.name, src.basename) file = ctx.actions.declare_file(name, sibling = src) ctx.actions.expand_template( output = file, template = src, substitutions = { - "\"collectives.h": "\"collectives/collectives.h", - "\"../collectives.h": "\"collectives/collectives.h", - "#if __CUDACC_VER_MAJOR__": "#if defined __CUDACC_VER_MAJOR__ && __CUDACC_VER_MAJOR__", - # Substitutions are applied in order. - "std::nullptr_t": "nullptr_t", - "nullptr_t": "std::nullptr_t", + "#define UNROLL 4": "#define UNROLL 4\n#define NCCL_OP %d" % ctx.attr.NCCL_OP, }, ) files.append(file) return [DefaultInfo(files = depset(files))] -_process_srcs = rule( - implementation = _process_srcs_impl, +gen_device_srcs = rule( + implementation = _gen_device_srcs_impl, attrs = { "srcs": attr.label_list(allow_files = True), - "prefix": attr.string(default = ""), + "NCCL_OP": attr.int(), }, ) -"""Processes the NCCL srcs so they can be compiled with bazel and clang.""" - -def nccl_library(name, srcs = None, hdrs = None, prefix = None, **kwargs): - """Processes the srcs and hdrs and creates a cc_library.""" - - _process_srcs( - name = name + "_srcs", - srcs = srcs, - prefix = prefix, - ) - _process_srcs( - name = name + "_hdrs", - srcs = hdrs, - ) +"""Adds prefix to each file name in srcs and adds #define NCCL_OP.""" - native.cc_library( - name = name, - srcs = [name + "_srcs"] if srcs else [], - hdrs = [name + "_hdrs"] if hdrs else [], - **kwargs - ) - -def rdc_copts(): +def _rdc_copts(): """Returns copts for compiling relocatable device code.""" # The global functions can not have a lower register count than the @@ -100,118 +110,255 @@ def rdc_copts(): "-fcuda-rdc", "-Xcuda-ptxas", maxrregcount, + # Work around for clang bug (fixed in r348662), declaring + # '__device__ operator delete(void*, std::size_t)' non-inline. + # TODO(csigg): Only add this option for older clang versions. + "-std=gnu++11", ], "//conditions:default": [], - }) + ["-fvisibility=hidden"] + }) -def _filter_impl(ctx): - suffix = ctx.attr.suffix - files = [src for src in ctx.files.srcs if src.path.endswith(suffix)] - return [DefaultInfo(files = depset(files))] +def _lookup_file(filegroup, path): + """Extracts file at (relative) path in filegroup.""" + for file in filegroup.files: + if file.path.endswith(path): + return file + return None -_filter = rule( - implementation = _filter_impl, - attrs = { - "srcs": attr.label_list(allow_files = True), - "suffix": attr.string(), - }, -) -"""Filters the srcs to the ones ending with suffix.""" +def _pic_only(files): + """Returns the PIC files if there are any in 'files', otherwise 'files'.""" + pic_only = [f for f in files if f.basename.find(".pic.") >= 0] + return pic_only if pic_only else files + +def _device_link_impl(ctx): + if not ctx.attr.gpu_archs: + fail("No GPU architecture specified. NCCL requires --config=cuda or similar.") + + inputs = [] + for dep in ctx.attr.deps: + inputs += dep.files.to_list() + inputs = _pic_only(inputs) -def _gen_link_src_impl(ctx): + # Device-link to cubins for each architecture. + name = ctx.attr.name + register_h = None + cubins = [] + images = [] + for arch in ctx.attr.gpu_archs: + cubin = ctx.actions.declare_file("%s_%s.cubin" % (name, arch)) + register_h = ctx.actions.declare_file("%s_register_%s.h" % (name, arch)) + ctx.actions.run( + outputs = [register_h, cubin], + inputs = inputs, + executable = ctx.file._nvlink, + arguments = ctx.attr.nvlink_args + [ + "--arch=%s" % arch, + "--register-link-binaries=%s" % register_h.path, + "--output-file=%s" % cubin.path, + ] + [file.path for file in inputs], + mnemonic = "nvlink", + ) + cubins.append(cubin) + images.append("--image=profile=%s,file=%s" % (arch, cubin.path)) + + # Generate fatbin header from all cubins. + tmp_fatbin = ctx.actions.declare_file("%s.fatbin" % name) + fatbin_h = ctx.actions.declare_file("%s_fatbin.h" % name) + bin2c = ctx.file._bin2c + ctx.actions.run( + outputs = [tmp_fatbin, fatbin_h], + inputs = cubins, + executable = ctx.file._fatbinary, + arguments = [ + "-64", + "--cmdline=--compile-only", + "--link", + "--compress-all", + "--bin2c-path=%s" % bin2c.dirname, + "--create=%s" % tmp_fatbin.path, + "--embedded-fatbin=%s" % fatbin_h.path, + ] + images, + tools = [bin2c], + mnemonic = "fatbinary", + ) + + # Generate the source file #including the headers generated above. ctx.actions.expand_template( - output = ctx.outputs.output, - template = ctx.file.template, + output = ctx.outputs.out, + template = ctx.file._link_stub, substitutions = { - "REGISTERLINKBINARYFILE": '"%s"' % ctx.file.register_hdr.short_path, - "FATBINFILE": '"%s"' % ctx.file.fatbin_hdr.short_path, + "REGISTERLINKBINARYFILE": '"%s"' % register_h.short_path, + "FATBINFILE": '"%s"' % fatbin_h.short_path, }, ) -_gen_link_src = rule( - implementation = _gen_link_src_impl, + return [DefaultInfo(files = depset([register_h, fatbin_h]))] + +_device_link = rule( + implementation = _device_link_impl, attrs = { - "register_hdr": attr.label(allow_single_file = True), - "fatbin_hdr": attr.label(allow_single_file = True), - "template": attr.label(allow_single_file = True), - "output": attr.output(), + "deps": attr.label_list(), + "out": attr.output(mandatory = True), + "gpu_archs": attr.string_list(), + "nvlink_args": attr.string_list(), + "_nvlink": attr.label( + default = Label("@local_config_nccl//:nvlink"), + allow_single_file = True, + executable = True, + cfg = "host", + ), + "_fatbinary": attr.label( + default = Label("@local_config_nccl//:cuda/bin/fatbinary"), + allow_single_file = True, + executable = True, + cfg = "host", + ), + "_bin2c": attr.label( + default = Label("@local_config_nccl//:cuda/bin/bin2c"), + allow_single_file = True, + executable = True, + cfg = "host", + ), + "_link_stub": attr.label( + default = Label("@local_config_nccl//:cuda/bin/crt/link.stub"), + allow_single_file = True, + ), }, ) -"""Patches the include directives for the link.stub file.""" - -def rdc_library(name, deps): - """Produces a cc_library from deps containing relocatable device code.""" - - # From .a and .pic.a archives, just use the latter. Otherwise we get - # multiply defined symbols. - # TODO(csigg): C++ Sandwich once available should allow passing this target - # to a cc_library dependency, which would avoid the linking order issue. - _filter( - name = name + "_deps_a", - srcs = deps, - suffix = ".pic.a", +"""Links device code and generates source code for kernel registration.""" + +def _merge_archive_impl(ctx): + # Generate an mri script to the merge archives in srcs and pass it to 'ar'. + # See https://stackoverflow.com/a/23621751. + files = _pic_only(ctx.files.srcs) + mri_script = "create " + ctx.outputs.out.path + for f in files: + mri_script += "\\naddlib " + f.path + mri_script += "\\nsave\\nend" + + cc_toolchain = find_cpp_toolchain(ctx) + ctx.actions.run_shell( + inputs = ctx.files.srcs, # + ctx.files._crosstool, + outputs = [ctx.outputs.out], + command = ("printf \"%s\" " % mri_script + + "| %s -M" % cc_toolchain.ar_executable), ) - # Device-link to cubins for each architecture. - images = [] - cubins = [] - for arch in %{gpu_architectures}: - cubin = "%s_%s.cubin" % (name, arch) - register_hdr = "%s_%s.h" % (name, arch) - nvlink = "@local_config_nccl//:nvlink" - cmd = ("$(location %s) " % nvlink + - select({ - # NCCL is only supported on Linux. - "@org_tensorflow//tensorflow:linux_x86_64": "--cpu-arch=X86_64 ", - "@org_tensorflow//tensorflow:linux_ppc64le": "--cpu-arch=PPC64LE ", - "//conditions:default": "", - }) + - "--arch=%s $(SRCS) " % arch + - "--register-link-binaries=$(location %s) " % register_hdr + - "--output-file=$(location %s)" % cubin) - native.genrule( - name = "%s_%s" % (name, arch), - outs = [register_hdr, cubin], - srcs = [name + "_deps_a"], - cmd = cmd, - tools = [nvlink], - ) - images.append("--image=profile=%s,file=$(location %s)" % (arch, cubin)) - cubins.append(cubin) +_merge_archive = rule( + implementation = _merge_archive_impl, + attrs = { + "srcs": attr.label_list(mandatory = True, allow_files = True), + "_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"), + # "_crosstool": attr.label_list(cfg = "host", default = ["@bazel_tools//tools/cpp:crosstool"]), + }, + outputs = {"out": "lib%{name}.a"}, +) +"""Merges srcs into a single archive.""" - # Generate fatbin header from all cubins. - fatbin_hdr = name + ".fatbin.h" - fatbinary = "@local_config_nccl//:cuda/bin/fatbinary" - bin2c = "@local_config_nccl//:cuda/bin/bin2c" - cmd = ("$(location %s) -64 --cmdline=--compile-only " % fatbinary + - "--link --bin2c-path $$(dirname $(location %s)) " % bin2c + - "--compress-all %s --create=%%{name}.fatbin " % " ".join(images) + - "--embedded-fatbin=$@") - native.genrule( - name = name + "_fatbin_h", - outs = [fatbin_hdr], - srcs = cubins, - cmd = cmd, - tools = [fatbinary, bin2c], +def cuda_rdc_library(name, hdrs = None, copts = None, linkstatic = True, **kwargs): + """Produces a cuda_library using separate compilation and linking. + + CUDA separate compilation and linking allows device function calls across + translation units. This is different from the normal whole program + compilation where each translation unit contains all device code. For more + background, see + https://devblogs.nvidia.com/separate-compilation-linking-cuda-device-code/, + https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#nvcc-options-for-separate-compilation + + During separate compilation, the different CUDA source files are compiled + to 'relocatable device code' (RDC) and embedded in the host object files. + When using nvcc, linking the device code for each supported GPU + architecture and generating kernel registration code for the CUDA runtime + is handled automatically. Clang supports generating relocatable device + code, but it can't link it. We therefore rely on tools provided by the CUDA + SDK to link the device code and generate the host code to register the + kernels. + + The nvlink tool extracts the RDC code from the object files and links it + into cubin files, one per GPU architecture. It also produces a header file + with a list of kernel names to register. The cubins are merged into a + binary blob using the fatbinary tool, and converted to a C header file with + the help of the bin2c tool. The registration header file, the fatbinary + header file, and the link.stub file (shipped with the CUDA SDK) are + compiled as ordinary host code. + + Here is a diagram of the CUDA separate compilation trajectory: + + x.cu.cc y.cu.cc + \ / cc_library (compile RDC and archive) + xy.a + / \ * nvlink + register.h xy.cubin + : | * fatbinary and bin2c + : xy.fatbin.h + : : * #include + dlink.cc * Expanded from crt/dlink.stub template + | cc_library (host compile and archive) + dlink.a + + The steps marked with '*' are implemented in the _device_link rule. + + The object files in both xy.a and dlink.a reference symbols defined in the + other archive. The separate archives are a side effect of using two + cc_library targets to implement a single compilation trajectory. We could + fix this once bazel supports C++ sandwich. For now, we just merge the two + archives to avoid unresolved symbols: + + xy.a dlink.a + \ / merge archive + xy_dlink.a + | cc_library (or alternatively, cc_import) + final target + + Another complication is that cc_library produces (depending on the + configuration) both PIC and non-PIC archives, but the distinction + is hidden from Starlark until C++ sandwich becomes available. We work + around this by dropping the non-PIC files if PIC files are available. + + Args: + name: Target name. + hdrs: Header files. + copts: Compiler options. + linkstatic: Must be true. + **kwargs: Any other arguments. + """ + + if not hdrs: + hdrs = [] + if not copts: + copts = [] + + # Compile host and device code into library. + lib = name + "_lib" + native.cc_library( + name = lib, + hdrs = hdrs, + copts = _rdc_copts() + copts, + linkstatic = linkstatic, + **kwargs ) - # Generate the source file #including the headers generated above. - _gen_link_src( - name = name + "_dlink_src", - # Include just the last one, they are equivalent. - register_hdr = register_hdr, - fatbin_hdr = fatbin_hdr, - template = "@local_config_nccl//:cuda/bin/crt/link.stub", - output = name + ".cc", + # Generate source file containing linked device code. + dlink_hdrs = name + "_dlink_hdrs" + dlink_cc = name + "_dlink.cc" + _device_link( + name = dlink_hdrs, + deps = [lib], + out = dlink_cc, + gpu_archs = %{gpu_architectures}, + nvlink_args = select({ + "@org_tensorflow//tensorflow:linux_x86_64": ["--cpu-arch=X86_64"], + "@org_tensorflow//tensorflow:linux_ppc64le": ["--cpu-arch=PPC64LE"], + "//conditions:default": [], + }), ) - # Compile the source file into the cc_library. + # Compile the source file into a library. + dlink = name + "_dlink" native.cc_library( - name = name + "_dlink_a", - srcs = [ - name + "_dlink_src", - ], - textual_hdrs = [register_hdr, fatbin_hdr], + name = dlink, + srcs = [dlink_cc], + textual_hdrs = [dlink_hdrs], deps = [ "@local_config_cuda//cuda:cuda_headers", ], @@ -222,31 +369,22 @@ def rdc_library(name, deps): "__NV_EXTRA_INITIALIZATION=", "__NV_EXTRA_FINALIZATION=", ], - linkstatic = True, + linkstatic = linkstatic, ) - # Repackage deps into a single archive. This avoid unresolved symbols when - # the archives happen to be linked in the wrong order. For more details, see + # Repackage the two libs into a single archive. This is required because + # both libs reference symbols defined in the other one. For details, see # https://eli.thegreenplace.net/2013/07/09/library-order-in-static-linking - native.genrule( - name = name + "_a", - srcs = [ - name + "_deps_a", - name + "_dlink_a", - ], - outs = [name + ".a"], - # See https://stackoverflow.com/a/23621751 - cmd = """ -addlibs=$$(echo $(SRCS) | sed "s/[^ ]* */\\naddlib &/g") -printf "create $@$${addlibs}\\nsave\\nend" | $(AR) -M -""", + archive = name + "_a" + _merge_archive( + name = archive, + srcs = [lib, dlink], ) + # Create cc target from archive. native.cc_library( name = name, - srcs = [name + "_a"], - deps = [ - "@local_config_cuda//cuda:cudart_static", - ], - linkstatic = True, + srcs = [archive], + hdrs = hdrs, + linkstatic = linkstatic, ) -- GitLab From a5e8aac5fb85101ab8aa96bfa14a32d85c1c7d7b Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 01:03:05 -0800 Subject: [PATCH 0151/1765] compat: Update forward compatibility horizon to 2018-12-20 PiperOrigin-RevId: 226296668 --- tensorflow/python/compat/compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/python/compat/compat.py b/tensorflow/python/compat/compat.py index db99b2e452..216e27e85f 100644 --- a/tensorflow/python/compat/compat.py +++ b/tensorflow/python/compat/compat.py @@ -32,7 +32,7 @@ from tensorflow.python.ops import variable_scope from tensorflow.python.util import tf_contextlib from tensorflow.python.util.tf_export import tf_export -_FORWARD_COMPATIBILITY_HORIZON = datetime.date(2018, 12, 19) +_FORWARD_COMPATIBILITY_HORIZON = datetime.date(2018, 12, 20) @tf_export("compat.forward_compatible") -- GitLab From 7cd0a903f69628ca8dd758f6dfad96c3b84fdeee Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Thu, 20 Dec 2018 03:09:55 -0800 Subject: [PATCH 0152/1765] Update downloadable clang to r348507 PiperOrigin-RevId: 226308835 --- third_party/clang_toolchain/download_clang.bzl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/third_party/clang_toolchain/download_clang.bzl b/third_party/clang_toolchain/download_clang.bzl index 7ced902747..20ac3a8d5a 100644 --- a/third_party/clang_toolchain/download_clang.bzl +++ b/third_party/clang_toolchain/download_clang.bzl @@ -39,15 +39,15 @@ def download_clang(repo_ctx, out_folder): # Latest CLANG_REVISION and CLANG_SUB_REVISION of the Chromiums's release # can be found in https://chromium.googlesource.com/chromium/src/tools/clang/+/master/scripts/update.py - CLANG_REVISION = "347933" + CLANG_REVISION = "348507" CLANG_SUB_REVISION = 1 package_version = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION) checksums = { - "Linux_x64": "cae3643fdf5d46fc9bc8731212bb37573547148d90b64b083165e090133d11b0", - "Mac": "083a0e91a38c06e568652313ac7372b17a101268f7d65533d721ca30413442b4", - "Win": "43160487cfc7e88076a369a2b6e8e4a0f42e104c28d8903f3aaa62d630aba949", + "Linux_x64": "85a24f215737af91e0054d3a1cb435bd8ff06178cef14241c029c8a04ff16a79", + "Mac": "16a96a3c4b599d0418e812307087a223d5fee2ee3c7fd96f5cbc2a9e5bf8607d", + "Win": "4c144f24d3a82d546845c680f5b029ff02dd4de7614e93d1b21cfc6e20a26dad", } platform_folder = _get_platform_folder(repo_ctx.os.name) -- GitLab From 2565842e71e1665d8a4fc126edc40b37becfed71 Mon Sep 17 00:00:00 2001 From: Innovimax Date: Thu, 20 Dec 2018 14:11:27 +0100 Subject: [PATCH 0153/1765] fix typo --- tensorflow/java/src/gen/cc/op_gen_main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/java/src/gen/cc/op_gen_main.cc b/tensorflow/java/src/gen/cc/op_gen_main.cc index 0d9e0883af..cf4bb03dad 100644 --- a/tensorflow/java/src/gen/cc/op_gen_main.cc +++ b/tensorflow/java/src/gen/cc/op_gen_main.cc @@ -35,7 +35,7 @@ const char kUsageHeader[] = "graph.\n\n" "Operation wrappers are generated under the path specified by the " "'--output_dir' argument. This path can be absolute or relative to the\n" - "current working directory and will be created if it does not exists.\n\n" + "current working directory and will be created if it does not exist.\n\n" "Note that the operations will not be available through the " "'org.tensorflow.op.Ops' API until the generated classes are compiled\n" "using an appropriate annotation processor.\n\n" -- GitLab From 90524712e34b568e5c2ae57ae36a21a72f4b43f1 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 05:16:46 -0800 Subject: [PATCH 0154/1765] Made object based saved_model load support nested functions. The functions are loaded back based on a topologic sort of their dependencies. PiperOrigin-RevId: 226320365 --- .../saved_model/function_deserialization.py | 110 ++++++++++++++++++ tensorflow/python/saved_model/load.py | 15 +-- tensorflow/python/saved_model/load_test.py | 13 +++ 3 files changed, 125 insertions(+), 13 deletions(-) diff --git a/tensorflow/python/saved_model/function_deserialization.py b/tensorflow/python/saved_model/function_deserialization.py index 7845aab089..dc839cf61c 100644 --- a/tensorflow/python/saved_model/function_deserialization.py +++ b/tensorflow/python/saved_model/function_deserialization.py @@ -18,8 +18,13 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import collections +import re + +from tensorflow.core.framework import function_pb2 from tensorflow.python.eager import def_function from tensorflow.python.eager import function as function_lib +from tensorflow.python.framework import function_def_to_graph as function_def_lib from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_spec from tensorflow.python.ops import resource_variable_ops @@ -106,3 +111,108 @@ def recreate_polymorphic_function( raise AssertionError( "Could not find matching function to call for arguments: %s" % (args,)) return restored_function + + +def load_function_def_library(library): + """Load a set of functions as concrete functions without captured inputs. + + Functions names are manipulated during load such that they do not overlap + with previously created ones. + + Args: + library: FunctionDefLibrary proto message. + + Returns: + Map of original function names in the library to instances of `Function` + without captured inputs. + + Raises: + ValueError: if functions dependencies have a cycle. + """ + # TODO(andresp): Look into restoring gradient function information. + functions = {} + name_mapping = {} + # Note: Use a new graph to allow function_def_to_graph to help validating + # that the functions are loaded correctly. This is not possible to do + # just in eager mode as there is no python API to find if a function has + # been registered in eager. Note also that despite this the created + # func_graphs can still be used in eager or in other graphs. + with ops.Graph().as_default() as import_graph: + for fdef in _sort_function_defs(library): + copy = _fix_fdef(fdef, name_mapping) + + func_graph = function_def_lib.function_def_to_graph(copy) + func = function_lib.Function(func_graph) + func.add_to_graph(import_graph) + + name_mapping[fdef.signature.name] = func.name + functions[fdef.signature.name] = func + return functions + + +def _sort_function_defs(library): + """Return a topologic sort of FunctionDefs in a library.""" + edges = collections.defaultdict(list) + in_count = collections.defaultdict(lambda: 0) + + for fdef in library.function: + for dep in _list_function_deps(fdef): + edges[dep].append(fdef.signature.name) + in_count[fdef.signature.name] += 1 + + ready = [ + fdef.signature.name + for fdef in library.function + if in_count[fdef.signature.name] == 0 + ] + output = [] + while ready: + node = ready.pop() + output.append(node) + for dest in edges[node]: + in_count[dest] -= 1 + if not in_count[dest]: + ready.append(dest) + + if len(output) != len(library.function): + loaded = set([x.signature.name for x in output]) + failed_to_resolve = sorted(set(in_count.keys()) - loaded) + raise ValueError("There is a cyclic-dependency between functions. ", + "Could not resolve %r." % (failed_to_resolve,)) + + reverse = {fdef.signature.name: fdef for fdef in library.function} + return [reverse[x] for x in output] + + +def _fix_fdef(orig_fdef, name_map): + fdef = function_pb2.FunctionDef() + fdef.CopyFrom(orig_fdef) + fdef.signature.name = _clean_function_name(fdef.signature.name) + for node_def in fdef.node_def: + for _, attr_value in node_def.attr.items(): + if attr_value.func.name: + attr_value.func.name = name_map[attr_value.func.name] + return fdef + + +def _list_function_deps(fdef): + # TODO(andresp): Recurse into list attributes and into NameAttrList attrs both + # when listing deps and when fixing them. `function_def_to_graph` also + # requires fixes. + deps = set() + for node_def in fdef.node_def: + for _, attr_value in node_def.attr.items(): + if attr_value.WhichOneof("value") == "func": + deps.add(attr_value.func.name) + return deps + + +def _clean_function_name(name): + """Vanity function to keep the function names comprehensible.""" + # Note: each time a function is wrapped into `function_lib.Function` its + # name becomes "__inference__xyz". + match = re.search(r"^__inference_(.*)_\d+$", name) + if match: + return match.group(1) + else: + return name diff --git a/tensorflow/python/saved_model/load.py b/tensorflow/python/saved_model/load.py index 0f3dd36d4c..3e85fade50 100644 --- a/tensorflow/python/saved_model/load.py +++ b/tensorflow/python/saved_model/load.py @@ -20,8 +20,6 @@ from __future__ import print_function import os -from tensorflow.python.eager import function -from tensorflow.python.framework import function_def_to_graph as function_def_lib from tensorflow.python.lib.io import file_io from tensorflow.python.ops import init_ops from tensorflow.python.ops import resource_variable_ops @@ -44,21 +42,12 @@ class _Loader(object): self._asset_file_def = meta_graph.asset_file_def self._proto = object_graph_proto self._export_dir = export_dir - self._load_func_graphs(meta_graph.graph_def.library) + self._functions = function_deserialization.load_function_def_library( + meta_graph.graph_def.library) self._load_all() self._bind_function_captures() self._restore_checkpoint() - def _load_func_graphs(self, function_library): - # TODO(allenl): Do we need to do name mapping here? Not quite sure what - # happens when loaded names collide with existing names. - # TODO(andresp): Look into restoring nested and gradient functions in the - # right order. - self._functions = {} - for fdef in function_library.function: - graph = function_def_lib.function_def_to_graph(fdef) - self._functions[fdef.signature.name] = function.Function(graph) - def _bind_function_captures(self): """Setup captured tensors in restored concrete functions.""" seen_functions = set() diff --git a/tensorflow/python/saved_model/load_test.py b/tensorflow/python/saved_model/load_test.py index 0f7fba0c66..657cec4178 100644 --- a/tensorflow/python/saved_model/load_test.py +++ b/tensorflow/python/saved_model/load_test.py @@ -154,6 +154,19 @@ class LoadTest(test.TestCase): imported = self.cycle(root) self.assertEqual(4., imported.f(constant_op.constant(2.0)).numpy()) + def test_nested_func(self): + f = def_function.function( + lambda x: x*2.0, + input_signature=[tensor_spec.TensorSpec(None, dtypes.float32)]) + g = def_function.function( + lambda x: f(x) + 1.0, + input_signature=[tensor_spec.TensorSpec(None, dtypes.float32)]) + + root = tracking.Checkpointable() + root.g = g + imported = self.cycle(root) + imported.g(constant_op.constant([1.0])) + def test_function_with_default_bool_input(self): def func(x, training=False): -- GitLab From fe84b75a8c30792b404d5cd81a8fdb2dd4d16732 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 07:37:28 -0800 Subject: [PATCH 0155/1765] Fix TensorRT header file path for remote config. PiperOrigin-RevId: 226333796 --- third_party/toolchains/preconfig/generate/generate.sh | 7 ++++--- .../toolchains/preconfig/ubuntu14.04/tensorrt5/BUILD | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/third_party/toolchains/preconfig/generate/generate.sh b/third_party/toolchains/preconfig/generate/generate.sh index 523c232ee1..8e3a1e6ada 100755 --- a/third_party/toolchains/preconfig/generate/generate.sh +++ b/third_party/toolchains/preconfig/generate/generate.sh @@ -52,9 +52,10 @@ bazel build --define=mount_project="${PWD}" "${PKG}/generate:${TARGET}" cd "${TEMPDIR}" tar xvf "${ROOT}/bazel-bin/${PKG}/generate/${TARGET}_outputs.tar" -# Other than @local_config_tensorrt, the remote config repo is a subpackage of -# @org_tensorflow and we need to add '-iquote ' manually. -buildozer "set strip_include_prefix package_name()" //local_config_tensorrt:%cc_library +# Other than in @local_config_tensorrt, the header files in the remote config +# repo are not relative to the repository root. Add a dummy include_prefix to +# make them available as virtual includes. +buildozer 'set include_prefix ""' //local_config_tensorrt:%cc_library # Delete all empty files: configurations leave empty files around when they are # unnecessary. diff --git a/third_party/toolchains/preconfig/ubuntu14.04/tensorrt5/BUILD b/third_party/toolchains/preconfig/ubuntu14.04/tensorrt5/BUILD index da16bb31b6..941d99a0db 100755 --- a/third_party/toolchains/preconfig/ubuntu14.04/tensorrt5/BUILD +++ b/third_party/toolchains/preconfig/ubuntu14.04/tensorrt5/BUILD @@ -12,7 +12,7 @@ package(default_visibility = ["//visibility:public"]) cc_library( name = "tensorrt_headers", hdrs = [":tensorrt_include"], - strip_include_prefix = package_name(), + include_prefix = "", visibility = ["//visibility:public"], ) @@ -21,8 +21,8 @@ cc_library( srcs = ["tensorrt/lib/libnvinfer.so.5"], copts = cuda_default_copts(), data = ["tensorrt/lib/libnvinfer.so.5"], + include_prefix = "", linkstatic = 1, - strip_include_prefix = package_name(), visibility = ["//visibility:public"], deps = [ ":tensorrt_headers", -- GitLab From 8cf1cf01615e68b4946ebad5a49d8096f0366e7f Mon Sep 17 00:00:00 2001 From: Mahmoud Abuzaina Date: Thu, 20 Dec 2018 08:58:52 -0800 Subject: [PATCH 0156/1765] Hiding Mkl Quantized Ops --- .../api_def/base_api/api_def_QuantizedConv2DAndRelu.pbtxt | 4 ++++ .../api_def_QuantizedConv2DAndReluAndRequantize.pbtxt | 4 ++++ .../base_api/api_def_QuantizedConv2DAndRequantize.pbtxt | 4 ++++ .../api_def/base_api/api_def_QuantizedConv2DWithBias.pbtxt | 4 ++++ .../base_api/api_def_QuantizedConv2DWithBiasAndRelu.pbtxt | 4 ++++ .../api_def_QuantizedConv2DWithBiasAndReluAndRequantize.pbtxt | 4 ++++ .../api_def_QuantizedConv2DWithBiasAndRequantize.pbtxt | 4 ++++ ...QuantizedConv2DWithBiasSignedSumAndReluAndRequantize.pbtxt | 4 ++++ .../base_api/api_def_QuantizedConv2DWithBiasSumAndRelu.pbtxt | 4 ++++ ...i_def_QuantizedConv2DWithBiasSumAndReluAndRequantize.pbtxt | 4 ++++ 10 files changed, 40 insertions(+) create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndRelu.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndReluAndRequantize.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndRequantize.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBias.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndRelu.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndReluAndRequantize.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndRequantize.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSignedSumAndReluAndRequantize.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSumAndRelu.pbtxt create mode 100644 tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSumAndReluAndRequantize.pbtxt diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndRelu.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndRelu.pbtxt new file mode 100644 index 0000000000..17ff15378c --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndRelu.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DAndRelu" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndReluAndRequantize.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndReluAndRequantize.pbtxt new file mode 100644 index 0000000000..b3ab3eba2c --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndReluAndRequantize.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DAndReluAndRequantize" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndRequantize.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndRequantize.pbtxt new file mode 100644 index 0000000000..8b00c2b7f6 --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DAndRequantize.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DAndRequantize" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBias.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBias.pbtxt new file mode 100644 index 0000000000..f309f648ca --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBias.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DWithBias" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndRelu.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndRelu.pbtxt new file mode 100644 index 0000000000..b6b73eaae3 --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndRelu.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DWithBiasAndRelu" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndReluAndRequantize.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndReluAndRequantize.pbtxt new file mode 100644 index 0000000000..101f72708a --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndReluAndRequantize.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DWithBiasAndReluAndRequantize" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndRequantize.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndRequantize.pbtxt new file mode 100644 index 0000000000..697e268415 --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasAndRequantize.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DWithBiasAndRequantize" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSignedSumAndReluAndRequantize.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSignedSumAndReluAndRequantize.pbtxt new file mode 100644 index 0000000000..0cf52d6c89 --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSignedSumAndReluAndRequantize.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DWithBiasSignedSumAndReluAndRequantize" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSumAndRelu.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSumAndRelu.pbtxt new file mode 100644 index 0000000000..e91a2b8dc0 --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSumAndRelu.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DWithBiasSumAndRelu" + visibility: HIDDEN +} diff --git a/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSumAndReluAndRequantize.pbtxt b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSumAndReluAndRequantize.pbtxt new file mode 100644 index 0000000000..fe3ec528bf --- /dev/null +++ b/tensorflow/core/api_def/base_api/api_def_QuantizedConv2DWithBiasSumAndReluAndRequantize.pbtxt @@ -0,0 +1,4 @@ +op { + graph_op_name: "QuantizedConv2DWithBiasSumAndReluAndRequantize" + visibility: HIDDEN +} -- GitLab From b0667edeb9b444c95299bef1e754f8c83b08d68c Mon Sep 17 00:00:00 2001 From: Scott Zhu Date: Thu, 20 Dec 2018 09:34:06 -0800 Subject: [PATCH 0157/1765] Internal cleanup. PiperOrigin-RevId: 226348159 --- tensorflow/python/keras/BUILD | 119 ++++++++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 12 deletions(-) diff --git a/tensorflow/python/keras/BUILD b/tensorflow/python/keras/BUILD index 6e1a6fc123..002e72fa21 100755 --- a/tensorflow/python/keras/BUILD +++ b/tensorflow/python/keras/BUILD @@ -122,9 +122,6 @@ py_library( py_library( name = "engine", srcs = [ - "activations.py", - "callbacks.py", - "constraints.py", "engine/__init__.py", "engine/base_layer.py", "engine/base_layer_utils.py", @@ -140,29 +137,127 @@ py_library( "engine/training_eager.py", "engine/training_generator.py", "engine/training_utils.py", - "initializers.py", - "losses.py", - "metrics.py", + "metrics.py", # Need base_layer "models.py", - "optimizers.py", - "regularizers.py", - "utils/data_utils.py", - "utils/io_utils.py", - "utils/losses_utils.py", "utils/metrics_utils.py", ], srcs_version = "PY2AND3", deps = [ + ":activations", ":backend", + ":callbacks", + ":constraints", + ":engine_utils", + ":initializers", + ":losses", + ":optimizers", + ":regularizers", "//tensorflow/python/data", "//tensorflow/python/distribute:reduce_util", - "//tensorflow/python/keras/optimizer_v2", "//tensorflow/python/training/checkpointable:data_structures", "//tensorflow/tools/docs:doc_controls", "@six_archive//:six", ], ) +py_library( + name = "activations", + srcs = [ + "activations.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":backend", + ":engine_utils", + ], +) + +py_library( + name = "callbacks", + srcs = [ + "callbacks.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":backend", + ":engine_utils", + ], +) + +py_library( + name = "constraints", + srcs = [ + "constraints.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":backend", + ":engine_utils", + ], +) + +py_library( + name = "initializers", + srcs = [ + "initializers.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":backend", + ":engine_utils", + ], +) + +py_library( + name = "losses", + srcs = [ + "losses.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":backend", + ":engine_utils", + ], +) + +py_library( + name = "optimizers", + srcs = [ + "optimizers.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":backend", + ":engine_utils", + "//tensorflow/python/keras/optimizer_v2", + ], +) + +py_library( + name = "regularizers", + srcs = [ + "regularizers.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":backend", + ":engine_utils", + ], +) + +py_library( + name = "engine_utils", + srcs = [ + "utils/data_utils.py", + "utils/io_utils.py", + "utils/losses_utils.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":backend", + ], +) + py_library( name = "layers", srcs = [ -- GitLab From 1573126fb027c13c8ba6167c410e4d35ce1220c8 Mon Sep 17 00:00:00 2001 From: Shashi Shekhar Date: Thu, 20 Dec 2018 09:51:13 -0800 Subject: [PATCH 0158/1765] Refactor quantization utility functions. PiperOrigin-RevId: 226350563 --- tensorflow/lite/tools/optimize/BUILD | 30 ++++ .../lite/tools/optimize/quantization_utils.cc | 65 +++++++++ .../lite/tools/optimize/quantization_utils.h | 42 ++++++ .../tools/optimize/quantization_utils_test.cc | 133 ++++++++++++++++++ .../lite/tools/optimize/quantize_weights.cc | 72 +++------- 5 files changed, 290 insertions(+), 52 deletions(-) create mode 100644 tensorflow/lite/tools/optimize/quantization_utils.cc create mode 100644 tensorflow/lite/tools/optimize/quantization_utils.h create mode 100644 tensorflow/lite/tools/optimize/quantization_utils_test.cc diff --git a/tensorflow/lite/tools/optimize/BUILD b/tensorflow/lite/tools/optimize/BUILD index 0a0d5cc412..2cdec00433 100644 --- a/tensorflow/lite/tools/optimize/BUILD +++ b/tensorflow/lite/tools/optimize/BUILD @@ -10,11 +10,41 @@ exports_files(["LICENSE"]) load("//tensorflow/lite:build_def.bzl", "tflite_copts") +cc_library( + name = "quantization_utils", + srcs = ["quantization_utils.cc"], + hdrs = ["quantization_utils.h"], + deps = [ + "//tensorflow/lite:framework", + "//tensorflow/lite/schema:schema_fbs", + "@com_google_absl//absl/memory", + "@flatbuffers", + ], +) + +cc_test( + name = "quantizatin_utils_test", + srcs = ["quantization_utils_test.cc"], + copts = ["-Wall"], + tags = [ + "tflite_not_portable_android", + "tflite_not_portable_ios", + ], + deps = [ + ":quantization_utils", + "//tensorflow/lite:framework", + "//tensorflow/lite/schema:schema_fbs", + "@com_google_googletest//:gtest", + "@flatbuffers", + ], +) + cc_library( name = "quantize_weights", srcs = ["quantize_weights.cc"], hdrs = ["quantize_weights.h"], deps = [ + ":quantization_utils", "//tensorflow/core:tflite_portable_logging", "//tensorflow/lite:framework", "//tensorflow/lite/kernels/internal:tensor_utils", diff --git a/tensorflow/lite/tools/optimize/quantization_utils.cc b/tensorflow/lite/tools/optimize/quantization_utils.cc new file mode 100644 index 0000000000..27292f74a6 --- /dev/null +++ b/tensorflow/lite/tools/optimize/quantization_utils.cc @@ -0,0 +1,65 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/tools/optimize/quantization_utils.h" + +#include +#include + +namespace tflite { +namespace optimize { +namespace utils { + +TfLiteStatus NumElements(const TensorT& tensor, uint64_t* num_elements) { + if (tensor.shape.empty()) { + return kTfLiteError; + } + *num_elements = 1; + for (const uint64_t dim : tensor.shape) { + *num_elements *= dim; + } + return kTfLiteOk; +} + +// Nudge min and max so that floating point 0 falls exactly on a quantized +// value, returning the nudges scale and zero_point. +// +// Although this code originates from FakeQuantization in quantized training, +// we may deviate from that implementation as we please since we do not fine +// tune the weights with quantized training. +void GetAsymmetricQuantizationParams( + const float min, const float max, const int quant_min, const int quant_max, + QuantizationParametersT* quantization_params) { + // Adjust the boundaries to guarantee 0 is included. + const float quant_min_float = std::min(static_cast(quant_min), 0.0f); + const float quant_max_float = std::max(static_cast(quant_max), 0.0f); + const float scale = (max - min) / (quant_max_float - quant_min_float); + const float zero_point_from_min = quant_min_float - min / scale; + int64_t zero_point; + if (zero_point_from_min < quant_min_float) { + zero_point = static_cast(quant_min); + } else if (zero_point_from_min > quant_max_float) { + zero_point = static_cast(quant_max); + } else { + zero_point = static_cast(std::round(zero_point_from_min)); + } + quantization_params->min = std::vector(1, min); + quantization_params->max = std::vector(1, max); + quantization_params->scale = std::vector(1, scale); + quantization_params->zero_point = std::vector(1, zero_point); +} + +} // namespace utils +} // namespace optimize +} // namespace tflite diff --git a/tensorflow/lite/tools/optimize/quantization_utils.h b/tensorflow/lite/tools/optimize/quantization_utils.h new file mode 100644 index 0000000000..e832812251 --- /dev/null +++ b/tensorflow/lite/tools/optimize/quantization_utils.h @@ -0,0 +1,42 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_TOOLS_OPTIMIZE_QUANTIZATION_UTILS_H_ +#define TENSORFLOW_LITE_TOOLS_OPTIMIZE_QUANTIZATION_UTILS_H_ + +#include + +#include "tensorflow/lite/context.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +namespace optimize { +namespace utils { + +// Returns the number of elements in the given tensor. +TfLiteStatus NumElements(const TensorT& tensor, uint64_t* num_elements); + +// Populates the scale and zero point for quantization parameters. +// +// Nudges min and max so that floating point 0 falls exactly on a quantized +// value, returning the nudges scale and zero_point. +void GetAsymmetricQuantizationParams( + const float min, const float max, const int quant_min, const int quant_max, + QuantizationParametersT* quantization_params); + +} // namespace utils +} // namespace optimize +} // namespace tflite + +#endif // TENSORFLOW_LITE_TOOLS_OPTIMIZE_QUANTIZATION_UTILS_H_ diff --git a/tensorflow/lite/tools/optimize/quantization_utils_test.cc b/tensorflow/lite/tools/optimize/quantization_utils_test.cc new file mode 100644 index 0000000000..06f51ebaf1 --- /dev/null +++ b/tensorflow/lite/tools/optimize/quantization_utils_test.cc @@ -0,0 +1,133 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/tools/optimize/quantization_utils.h" +#include +#include + +namespace tflite { +namespace optimize { +namespace utils { +namespace { + +TEST(QuantizationUtilsTest, NumElements) { + TensorT tensor; + tensor.shape = {1, 2, 3, 4}; + uint64_t num_elements; + EXPECT_EQ(kTfLiteOk, NumElements(tensor, &num_elements)); + EXPECT_EQ(num_elements, 1 * 2 * 3 * 4); + + tensor.shape = {5}; + EXPECT_EQ(kTfLiteOk, NumElements(tensor, &num_elements)); + EXPECT_EQ(num_elements, 5); + + tensor.shape = {}; + EXPECT_EQ(kTfLiteError, NumElements(tensor, &num_elements)); +} + +TEST(QuantizationUtilsTest, GetAsymmetricQuantizationParamsUnitRange) { + const float float_min = -128.0; + const float float_max = 127.0; + const int quant_min = -128; + const int quant_max = 127; + QuantizationParametersT params; + GetAsymmetricQuantizationParams(float_min, float_max, quant_min, quant_max, + ¶ms); + ASSERT_EQ(params.max.size(), 1); + ASSERT_EQ(params.min.size(), 1); + ASSERT_EQ(params.scale.size(), 1); + ASSERT_EQ(params.zero_point.size(), 1); + EXPECT_EQ(params.max[0], float_max); + EXPECT_EQ(params.min[0], float_min); + + int64_t zero_point = params.zero_point[0]; + float scale = params.scale[0]; + const float eps = 1e-7f; + EXPECT_EQ(zero_point, 0); + EXPECT_NEAR(scale, 1, eps); +} + +TEST(QuantizationUtilsTest, AsymmetricQuantizationParamsWithAllPositiveRange) { + const float float_min = 1.0; + const float float_max = 5.0; + const int quant_min = -128; + const int quant_max = 127; + QuantizationParametersT params; + GetAsymmetricQuantizationParams(float_min, float_max, quant_min, quant_max, + ¶ms); + ASSERT_EQ(params.max.size(), 1); + ASSERT_EQ(params.min.size(), 1); + ASSERT_EQ(params.scale.size(), 1); + ASSERT_EQ(params.zero_point.size(), 1); + EXPECT_EQ(params.max[0], float_max); + EXPECT_EQ(params.min[0], float_min); + int64_t zero_point = params.zero_point[0]; + float scale = params.scale[0]; + const float eps = 1e-7f; + EXPECT_EQ(zero_point, -128); + EXPECT_NEAR(scale, 4 / 255.0f, eps); +} + +TEST(QuantizationUtilsTest, AsymmetricQuantizationParamsWithAllNegativeRange) { + const float float_min = -5.0; + const float float_max = -1.0; + const int quant_min = -128; + const int quant_max = 127; + QuantizationParametersT params; + GetAsymmetricQuantizationParams(float_min, float_max, quant_min, quant_max, + ¶ms); + ASSERT_EQ(params.max.size(), 1); + ASSERT_EQ(params.min.size(), 1); + ASSERT_EQ(params.scale.size(), 1); + ASSERT_EQ(params.zero_point.size(), 1); + EXPECT_EQ(params.max[0], float_max); + EXPECT_EQ(params.min[0], float_min); + int64_t zero_point = params.zero_point[0]; + float scale = params.scale[0]; + const float eps = 1e-7f; + EXPECT_EQ(zero_point, 127); + EXPECT_NEAR(scale, 4 / 255.0f, eps); +} + +TEST(QuantizationUtilsTest, AsymmetricQuantizationParamsWithZeroInRange) { + const float float_min = -5.0; + const float float_max = 1.0; + const int quant_min = -128; + const int quant_max = 127; + QuantizationParametersT params; + GetAsymmetricQuantizationParams(float_min, float_max, quant_min, quant_max, + ¶ms); + ASSERT_EQ(params.max.size(), 1); + ASSERT_EQ(params.min.size(), 1); + ASSERT_EQ(params.scale.size(), 1); + ASSERT_EQ(params.zero_point.size(), 1); + EXPECT_EQ(params.max[0], float_max); + EXPECT_EQ(params.min[0], float_min); + int64_t zero_point = params.zero_point[0]; + float scale = params.scale[0]; + const float eps = 1e-7f; + EXPECT_NEAR(scale, 6 / 255.0f, eps); + EXPECT_GT(zero_point, quant_min); + EXPECT_LT(zero_point, quant_max); +} + +} // namespace +} // namespace utils +} // namespace optimize +} // namespace tflite + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tensorflow/lite/tools/optimize/quantize_weights.cc b/tensorflow/lite/tools/optimize/quantize_weights.cc index de3c0b0323..b376d465e1 100644 --- a/tensorflow/lite/tools/optimize/quantize_weights.cc +++ b/tensorflow/lite/tools/optimize/quantize_weights.cc @@ -21,11 +21,12 @@ limitations under the License. #include "flatbuffers/flexbuffers.h" #include "absl/memory/memory.h" +#include "tensorflow/core/platform/logging.h" #include "tensorflow/lite/context.h" #include "tensorflow/lite/kernels/internal/tensor_utils.h" #include "tensorflow/lite/model.h" #include "tensorflow/lite/schema/schema_generated.h" -#include "tensorflow/core/platform/logging.h" +#include "tensorflow/lite/tools/optimize/quantization_utils.h" namespace tflite { namespace optimize { @@ -46,44 +47,6 @@ typedef struct { // quantized by this transformation. const int kWeightsMinNumElementsDefault = 1024; -// Nudge min and max so that floating point 0 falls exactly on a quantized -// value, returning the nudges scale and zero_point. -// -// Although this code originates from FakeQuantization in quantized training, -// we may deviate from that implementation as we please since we do not fine -// tune the weights with quantized training. -void GetAsymmetricQuantizationParams( - const float min, const float max, const int quant_min, const int quant_max, - QuantizationParametersT* quantization_params) { - // Adjust the boundaries to guarantee 0 is included. - const float quant_min_float = std::min(static_cast(quant_min), 0.0f); - const float quant_max_float = std::max(static_cast(quant_max), 0.0f); - const float scale = (max - min) / (quant_max_float - quant_min_float); - const float zero_point_from_min = quant_min_float - min / scale; - int64_t zero_point; - if (zero_point_from_min < quant_min_float) { - zero_point = static_cast(quant_min); - } else if (zero_point_from_min > quant_max_float) { - zero_point = static_cast(quant_max); - } else { - zero_point = static_cast(std::round(zero_point_from_min)); - } - quantization_params->scale = std::vector(1, scale); - quantization_params->zero_point = std::vector(1, zero_point); -} - -// Returns the number of elements in tensor. -uint64_t NumElements(const TensorT* tensor) { - if (tensor->shape.empty()) { - LOG(FATAL) << "Tensor has no shape information."; - } - uint64_t num_elements = 1; - for (const uint64_t dim : tensor->shape) { - num_elements *= dim; - } - return num_elements; -} - uint64_t CountTensorConsumers(const ModelT* model, const SubGraphT* subgraph, int32_t tensor_idx) { uint64_t count = 0; @@ -156,16 +119,16 @@ bool IsHybridEvaluationOp(const OperatorT* op, const BuiltinOperator& op_code) { return eval_hybrid; } -// Returns a vector of TensorInfos for each input tensor of op that should be +// Populates a vector of TensorInfos for each input tensor of op that should be // quantized. -std::vector GetQuantizableTensorsFromOperator( +TfLiteStatus GetQuantizableTensorsFromOperator( const ModelT* model, const OperatorT* op, uint64_t weights_min_num_elements, - bool use_hybrid_evaluation) { + bool use_hybrid_evaluation, std::vector* tensor_infos) { SubGraphT* subgraph = model->subgraphs.at(0).get(); const BuiltinOperator op_code = model->operator_codes[op->opcode_index]->builtin_code; - std::vector tensor_infos; + tensor_infos->clear(); bool eval_hybrid = use_hybrid_evaluation && IsHybridEvaluationOp(op, op_code); @@ -194,7 +157,8 @@ std::vector GetQuantizableTensorsFromOperator( continue; } - const uint64_t num_elements = NumElements(tensor); + uint64_t num_elements; + TF_LITE_ENSURE_STATUS(utils::NumElements(*tensor, &num_elements)); if (num_elements < weights_min_num_elements) { LOG(INFO) << "Skipping quantization of tensor " << tensor->name << " because it has fewer than " << weights_min_num_elements @@ -219,10 +183,10 @@ std::vector GetQuantizableTensorsFromOperator( tensor_info.tensor_idx = tensor_idx; tensor_info.tensor = tensor; - tensor_infos.push_back(tensor_info); + tensor_infos->push_back(tensor_info); } - return tensor_infos; + return kTfLiteOk; } // Quantizes tensor using asymmetric quantization with the min and max elements @@ -230,7 +194,8 @@ std::vector GetQuantizableTensorsFromOperator( TfLiteStatus AsymmetricQuantizeTensor(ModelT* model, TensorT* tensor) { BufferT* buffer = model->buffers[tensor->buffer].get(); float* float_data = reinterpret_cast(buffer->data.data()); - const uint64_t num_elements = NumElements(tensor); + uint64_t num_elements; + TF_LITE_ENSURE_STATUS(utils::NumElements(*tensor, &num_elements)); LOG(INFO) << "Quantizing tensor " << tensor->name << " with " << num_elements << " elements for float evaluation."; @@ -241,8 +206,8 @@ TfLiteStatus AsymmetricQuantizeTensor(ModelT* model, TensorT* tensor) { if (tensor->quantization == nullptr) { tensor->quantization = absl::make_unique(); } - GetAsymmetricQuantizationParams(min_value, max_value, 0, 255, - tensor->quantization.get()); + utils::GetAsymmetricQuantizationParams(min_value, max_value, 0, 255, + tensor->quantization.get()); // Quantize the buffer. std::vector quantized_buffer; @@ -274,7 +239,8 @@ TfLiteStatus AsymmetricQuantizeTensor(ModelT* model, TensorT* tensor) { TfLiteStatus SymmetricQuantizeTensor(ModelT* model, TensorT* tensor) { BufferT* buffer = model->buffers[tensor->buffer].get(); float* float_data = reinterpret_cast(buffer->data.data()); - const uint64_t num_elements = NumElements(tensor); + uint64_t num_elements; + TF_LITE_ENSURE_STATUS(utils::NumElements(*tensor, &num_elements)); LOG(INFO) << "Quantizing tensor " << tensor->name << " with " << num_elements << " elements for hybrid evaluation."; @@ -360,8 +326,10 @@ TfLiteStatus QuantizeWeightsInternal(flatbuffers::FlatBufferBuilder* builder, for (int i = 0; i < subgraph->operators.size(); ++i) { OperatorT* op = subgraph->operators[i].get(); - std::vector tensor_infos = GetQuantizableTensorsFromOperator( - model.get(), op, weights_min_num_elements, use_hybrid_evaluation); + std::vector tensor_infos; + TF_LITE_ENSURE_STATUS(GetQuantizableTensorsFromOperator( + model.get(), op, weights_min_num_elements, use_hybrid_evaluation, + &tensor_infos)); for (const TensorInfo& tensor_info : tensor_infos) { if (tensor_info.eval_hybrid) { -- GitLab From 2f0e31e258496889783b3347a1494000ee6208be Mon Sep 17 00:00:00 2001 From: Dimitris Vardoulakis Date: Thu, 20 Dec 2018 10:14:34 -0800 Subject: [PATCH 0159/1765] [TF:XLA] Add many clarifications to the async scheduler, to make it more understandable. PiperOrigin-RevId: 226354067 --- .../xla/service/hlo_module_group_metadata.cc | 55 ++++++++++--------- .../xla/service/hlo_module_group_metadata.h | 18 +++--- .../xla/service/hlo_module_group_util.cc | 2 + .../xla/service/hlo_module_group_util.h | 2 +- 4 files changed, 42 insertions(+), 35 deletions(-) diff --git a/tensorflow/compiler/xla/service/hlo_module_group_metadata.cc b/tensorflow/compiler/xla/service/hlo_module_group_metadata.cc index b4aac4c807..80f8ca2226 100644 --- a/tensorflow/compiler/xla/service/hlo_module_group_metadata.cc +++ b/tensorflow/compiler/xla/service/hlo_module_group_metadata.cc @@ -79,36 +79,36 @@ Status HloModuleGroupMetadata::Build() { return Status::OK(); } - std::vector peers; - if (IsChannelInstruction(hlo)) { - peers.push_back(PeerComputation(hlo)); - } else if (hlo->IsCrossModuleAllReduce()) { - for (HloInstruction* instr : GetAllReduceGroup(*hlo->all_reduce_id())) { - if (instr == hlo) { - continue; + if (IsChannelInstruction(hlo) || hlo->IsCrossModuleAllReduce()) { + std::vector peers; + if (IsChannelInstruction(hlo)) { + peers.push_back(PeerComputation(hlo)); + } else if (hlo->IsCrossModuleAllReduce()) { + for (HloInstruction* instr : GetAllReduceGroup(*hlo->all_reduce_id())) { + if (instr == hlo) { + continue; + } + peers.push_back(instr->parent()); } - peers.push_back(instr->parent()); } - } - - // Add the parent computation of this channel (or all-reduce) instruction - // and its peer computation(s) (both must be while computations) as - // companions. - for (HloComputation* peer_computation : peers) { - const TrackedInstruction* peer_tracked = - GetTrackedInstruction(peer_computation); - TF_RET_CHECK(peer_tracked != nullptr) - << "Peer instruction is not a possible companion"; - TF_RET_CHECK(*tracked == *peer_tracked) - << "Peer instruction does not match the computation kind"; - TF_RETURN_IF_ERROR( - AddCompanion(tracked->instruction(), peer_tracked->instruction())); - tracked_instructions_comms_[tracked->instruction()].push_back(hlo); - } - // Add the parents of companion instructions (they must be all of the same - // kind of instructions, opcode wise) as companions. - if (IsCompanionInstruction(hlo)) { + // Add the parent computation of this channel (or all-reduce) instruction + // and its peer computation(s) (both must be while computations) as + // companions. + for (HloComputation* peer_computation : peers) { + const TrackedInstruction* peer_tracked = + GetTrackedInstruction(peer_computation); + TF_RET_CHECK(peer_tracked != nullptr) + << "Peer instruction is not a possible companion"; + TF_RET_CHECK(*tracked == *peer_tracked) + << "Peer instruction does not match the computation kind"; + TF_RETURN_IF_ERROR( + AddCompanion(tracked->instruction(), peer_tracked->instruction())); + tracked_instructions_comms_[tracked->instruction()].push_back(hlo); + } + } else if (IsCompanionInstruction(hlo)) { + // Add the parents of companion instructions (they must be all of the same + // kind of instructions, opcode wise) as companions. for (HloInstruction* companion : Companions(hlo)) { const TrackedInstruction* companion_tracked = GetTrackedInstruction(companion->parent()); @@ -118,6 +118,7 @@ Status HloModuleGroupMetadata::Build() { companion_tracked->instruction())); } } + return Status::OK(); }; diff --git a/tensorflow/compiler/xla/service/hlo_module_group_metadata.h b/tensorflow/compiler/xla/service/hlo_module_group_metadata.h index 928df0f5a7..5cd0e38f38 100644 --- a/tensorflow/compiler/xla/service/hlo_module_group_metadata.h +++ b/tensorflow/compiler/xla/service/hlo_module_group_metadata.h @@ -38,7 +38,7 @@ namespace xla { // Class for bookkeeping the information on the given modules, in particular on // the interaction between computations. // -// Companion instructions are one of the information collected as we build the +// Companion instructions are one piece of information collected as we build the // metadata. For example, for each While instruction, companion instructions // refer to a set of While instructions in other computations that communicate // with each other. @@ -51,6 +51,13 @@ namespace xla { // } While_4() { Recv(0) } // } // +// Each instruction can belong to at most one companion set: While_0 and While_5 +// are in the same set even though they don't communicate with each other, +// because they both communicate with While_2. +// +// A send and the matching recv must both have the same level of nesting of +// companion instructions. +// // Companion instructions are used to detect cycles in the graph and also for // global scheduling. class HloModuleGroupMetadata { @@ -215,11 +222,8 @@ class HloModuleGroupMetadata { // * Each channel has all 4 instructions (Send, Recv, SendDone, RecvDone). // * The shape of channel instructions match. // * The nest level of channel instructions match. - // * Channel instructions are used in allowed computations; i.e., in the + // * Channel instructions are used in allowed computations, i.e., in the // entry computation of the module or condition/body of While computations. - // - // TODO(b/62064342): Currently, HloModuleGroupScheduler checks if there is a - // cycle in the graph, but it would be good to verify here. Status VerifyChannelInstructions(); // Adds metadata that the given two instructions are companions. @@ -231,8 +235,8 @@ class HloModuleGroupMetadata { Status CheckCommunicatingInstruction(HloInstruction* instruction) const; // Performs a consistency check on the companion sets built for the input - // modules. Check that a companion set does not include instructions from the - // same module/device. + // modules. Checks that each instruction in a companion set is in a different + // module/device. Status VerifyCompanionSets() const; // Retrieves a pointer to the stored TrackedInstruction associated with a diff --git a/tensorflow/compiler/xla/service/hlo_module_group_util.cc b/tensorflow/compiler/xla/service/hlo_module_group_util.cc index fddeb5f0a2..91417bd2d9 100644 --- a/tensorflow/compiler/xla/service/hlo_module_group_util.cc +++ b/tensorflow/compiler/xla/service/hlo_module_group_util.cc @@ -198,6 +198,8 @@ std::vector HloModuleGroupUtil::RootInstructions( for (HloComputation* computation : computations) { for (HloInstruction* instruction : computation->instructions()) { if (GlobalSuccessors(instruction).empty()) { + // An instruction that has no successors, e.g., an unused instruction, + // is in roots, even though it's not the ROOT of its computation. roots.push_back(instruction); } } diff --git a/tensorflow/compiler/xla/service/hlo_module_group_util.h b/tensorflow/compiler/xla/service/hlo_module_group_util.h index f21b44bcd9..862666b48c 100644 --- a/tensorflow/compiler/xla/service/hlo_module_group_util.h +++ b/tensorflow/compiler/xla/service/hlo_module_group_util.h @@ -49,7 +49,7 @@ class HloModuleGroupUtil { // Returns all unique successors of the instruction. This includes: // * successors in the same computation: users and control successors // * Send is a successor of Recv - // * RecvDone is a predecessor of Send + // * RecvDone is a successor of Send // * successors of companions (if the instruction is a companion while) // * successors' companions (for any successor that is a companion while) std::vector GlobalSuccessors(HloInstruction* instruction); -- GitLab From 6cbd27b8ffb0ee33ae0f3151a202ba8dd0fa22a9 Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Thu, 20 Dec 2018 10:26:17 -0800 Subject: [PATCH 0160/1765] Only apply size limit if size of tensor is increasing --- tensorflow/core/grappler/optimizers/constant_folding.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tensorflow/core/grappler/optimizers/constant_folding.cc b/tensorflow/core/grappler/optimizers/constant_folding.cc index 3882e3b3a9..bb7ed05e33 100644 --- a/tensorflow/core/grappler/optimizers/constant_folding.cc +++ b/tensorflow/core/grappler/optimizers/constant_folding.cc @@ -913,6 +913,7 @@ Status ConstantFolding::CreateNodeDef(const string& name, AttrValue attr_tensor; TensorProto* t = attr_tensor.mutable_tensor(); bool optimized = false; + const size_t original_size = tensor->TotalBytes(); size_t encoded_size; // Use the packed representation whenever possible to avoid generating large // graphdefs. Moreover, avoid repeating the last values if they're equal. @@ -980,11 +981,11 @@ Status ConstantFolding::CreateNodeDef(const string& name, } node->mutable_attr()->insert({"value", attr_tensor}); - if (encoded_size < 10 * 1024 * 1024) { - return Status::OK(); + if (encoded_size > original_size && encoded_size >= 10 * 1024 * 1024) { + return errors::InvalidArgument( + strings::StrCat("Can't fold ", name, ", its size would be too large")); } - return errors::InvalidArgument( - strings::StrCat("Can't fold ", name, ", its size would be too large")); + return Status::OK(); } Status ConstantFolding::EvaluateNode(const NodeDef& node, -- GitLab From 9f3acf3d89a4ef5f9313a6e2cb2d81e03177e8ef Mon Sep 17 00:00:00 2001 From: Jared Duke Date: Thu, 20 Dec 2018 10:21:09 -0800 Subject: [PATCH 0161/1765] Include op defs in the toco converter bindings This allows conversion of TFLite models with support for select TF ops via the standard pip installation. Note that support for *executing* TFLite models with select TF ops, via Python, will land separately. PiperOrigin-RevId: 226355228 --- tensorflow/lite/python/BUILD | 1 - tensorflow/lite/python/convert.py | 13 ++++++++----- tensorflow/lite/toco/python/BUILD | 21 +++------------------ 3 files changed, 11 insertions(+), 24 deletions(-) diff --git a/tensorflow/lite/python/BUILD b/tensorflow/lite/python/BUILD index acf827892b..b0ca3f8dcc 100644 --- a/tensorflow/lite/python/BUILD +++ b/tensorflow/lite/python/BUILD @@ -73,7 +73,6 @@ py_test( data = ["@tflite_mobilenet_ssd_quant_protobuf//:tflite_graph.pb"], srcs_version = "PY2AND3", tags = [ - "no_oss", "no_windows", ], deps = [ diff --git a/tensorflow/lite/python/convert.py b/tensorflow/lite/python/convert.py index 9c60399871..9f315fc874 100644 --- a/tensorflow/lite/python/convert.py +++ b/tensorflow/lite/python/convert.py @@ -37,11 +37,14 @@ from tensorflow.python.util.tf_export import tf_export as _tf_export # Lazy load since some of the performance benchmark skylark rules # break dependencies. -_toco_python = LazyLoader( - "tensorflow_wrap_toco", globals(), - "tensorflow.lite.toco.python." - "tensorflow_wrap_toco") -del LazyLoader +if lite_constants.EXPERIMENTAL_USE_TOCO_API_DIRECTLY: + _toco_python = LazyLoader( + "tensorflow_wrap_toco", globals(), + "tensorflow.lite.toco.python." + "tensorflow_wrap_toco") + del LazyLoader +else: + _toco_python = None # Find the toco_from_protos binary using the resource loader if using from # bazel, otherwise we are in a pip where console_scripts already has diff --git a/tensorflow/lite/toco/python/BUILD b/tensorflow/lite/toco/python/BUILD index 8a6e82ec46..f3ea5b7bfe 100644 --- a/tensorflow/lite/toco/python/BUILD +++ b/tensorflow/lite/toco/python/BUILD @@ -10,35 +10,20 @@ load("//tensorflow:tensorflow.bzl", "tf_py_wrap_cc") load("//tensorflow:tensorflow.bzl", "tf_py_test") load("//tensorflow:tensorflow.bzl", "py_binary") -config_setting( - name = "tflite_convert_with_select_tf_ops", - define_values = {"tflite_convert_with_select_tf_ops": "true"}, - visibility = [ - "//tensorflow/contrib/lite:__subpackages__", - "//tensorflow/lite:__subpackages__", - ], -) - cc_library( name = "toco_python_api", srcs = ["toco_python_api.cc"], hdrs = ["toco_python_api.h"], deps = [ - "//third_party/python_runtime:headers", "//tensorflow/core:lib", + "//tensorflow/core:ops", "//tensorflow/lite/toco:model_flags_proto_cc", "//tensorflow/lite/toco:toco_flags_proto_cc", "//tensorflow/lite/toco:toco_graphviz_dump_options", "//tensorflow/lite/toco:toco_port", "//tensorflow/lite/toco:toco_tooling", - ] + select({ - # This is required when running `tflite_convert` from `bazel`. - # It requires to link with TensorFlow Ops to get the op definitions. - ":tflite_convert_with_select_tf_ops": [ - "//tensorflow/core:ops", - ], - "//conditions:default": [], - }), + "//third_party/python_runtime:headers", + ], ) tf_py_wrap_cc( -- GitLab From 0cc35b3d409ddf9d3baeb54edd88b1addd186b17 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 10:23:38 -0800 Subject: [PATCH 0162/1765] Fix behavior of `stack()` when passed a single ragged tensor, to be consistent with handling of multiple tensors. PiperOrigin-RevId: 226355632 --- .../python/ops/ragged/ragged_array_ops.py | 2 +- .../python/ops/ragged/ragged_stack_op_test.py | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/tensorflow/python/ops/ragged/ragged_array_ops.py b/tensorflow/python/ops/ragged/ragged_array_ops.py index 8ba8c53212..be49830c98 100644 --- a/tensorflow/python/ops/ragged/ragged_array_ops.py +++ b/tensorflow/python/ops/ragged/ragged_array_ops.py @@ -655,7 +655,7 @@ def _ragged_stack_concat_helper(rt_inputs, axis, stack_values): # Special case: if there's only one input, then return it as-is. if len(rt_inputs) == 1: if stack_values: - return expand_dims(rt_inputs[0], axis=0) + return expand_dims(rt_inputs[0], axis=axis) else: return rt_inputs[0] diff --git a/tensorflow/python/ops/ragged/ragged_stack_op_test.py b/tensorflow/python/ops/ragged/ragged_stack_op_test.py index f9c825168e..b2b96a9465 100644 --- a/tensorflow/python/ops/ragged/ragged_stack_op_test.py +++ b/tensorflow/python/ops/ragged/ragged_stack_op_test.py @@ -33,6 +33,52 @@ class RaggedStackOpTest(ragged_test_util.RaggedTensorTestCase, parameterized.TestCase): @parameterized.parameters( + dict( + descr='One rank-2 input (ragged_rank=1), axis=0', + rt_inputs=( + [['a00', 'a01'], [], ['a20', 'a21']],), # shape=(3, None) + axis=0, + expected=[[[b'a00', b'a01'], [], [b'a20', b'a21']]]), + dict( + descr='One rank-2 input (ragged_rank=1), axis=1', + rt_inputs=( + [['a00', 'a01'], [], ['a20', 'a21', 'a22']],), # shape=(3, None) + axis=1, + expected=[ + [[b'a00', b'a01']], + [[]], + [[b'a20', b'a21', b'a22']]]), + dict( + descr='One rank-2 input (ragged_rank=1), axis=2', + rt_inputs=( + [['a00', 'a01'], [], ['a20', 'a21', 'a22']],), # shape=(3, None) + axis=2, + expected=[ + [[b'a00'], [b'a01']], [], + [[b'a20'], [b'a21'], [b'a22']]]), + dict( + descr='One rank-2 input (ragged_rank=1), axis=-3', + rt_inputs=( + [['a00', 'a01'], [], ['a20', 'a21']],), # shape=(3, None) + axis=-3, + expected=[[[b'a00', b'a01'], [], [b'a20', b'a21']]]), + dict( + descr='One rank-2 input (ragged_rank=1), axis=-2', + rt_inputs=( + [['a00', 'a01'], [], ['a20', 'a21', 'a22']],), # shape=(3, None) + axis=-2, + expected=[ + [[b'a00', b'a01']], + [[]], + [[b'a20', b'a21', b'a22']]]), + dict( + descr='One rank-2 input (ragged_rank=1), axis=-1', + rt_inputs=( + [['a00', 'a01'], [], ['a20', 'a21', 'a22']],), # shape=(3, None) + axis=-1, + expected=[ + [[b'a00'], [b'a01']], [], + [[b'a20'], [b'a21'], [b'a22']]]), dict( descr='Two rank-2 inputs (ragged_rank=1), axis=0', rt_inputs=( -- GitLab From 56c0758d5eb48772793a1e05473c6a6b4b266a62 Mon Sep 17 00:00:00 2001 From: Skye Wanderman-Milne Date: Thu, 20 Dec 2018 10:46:29 -0800 Subject: [PATCH 0163/1765] Add more GPU registrations needed for while_v2. These registrations are needed because the placer's too stupid to always place resource handles and accesses on the same device, if other colocation constraints dictate they be on different devices. Ideally when soft placement is enabled, the placer would prioritize colocating resource handles and accesses over other constraints to avoid runtime errors. PiperOrigin-RevId: 226359107 --- tensorflow/core/kernels/control_flow_ops.cc | 4 ++++ tensorflow/core/kernels/list_kernels.cc | 1 + tensorflow/python/keras/layers/unified_gru_test.py | 2 -- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tensorflow/core/kernels/control_flow_ops.cc b/tensorflow/core/kernels/control_flow_ops.cc index 4bd90d36b8..c0981805bb 100644 --- a/tensorflow/core/kernels/control_flow_ops.cc +++ b/tensorflow/core/kernels/control_flow_ops.cc @@ -267,6 +267,7 @@ TF_CALL_QUANTIZED_TYPES(REGISTER_GPU_REF_KERNEL); REGISTER_GPU_KERNEL(bool); REGISTER_GPU_REF_KERNEL(bool); REGISTER_GPU_KERNEL(uint64); +TF_CALL_variant(REGISTER_GPU_KERNEL); #undef REGISTER_GPU_KERNEL #undef REGISTER_GPU_REF_KERNEL @@ -365,6 +366,7 @@ TF_CALL_NUMBER_TYPES_NO_INT32(REGISTER_GPU_KERNEL); TF_CALL_NUMBER_TYPES_NO_INT32(REGISTER_GPU_REF_KERNEL); REGISTER_GPU_KERNEL(bool); REGISTER_GPU_REF_KERNEL(bool); +TF_CALL_variant(REGISTER_GPU_KERNEL); #undef REGISTER_GPU_KERNEL #undef REGISTER_GPU_REF_KERNEL @@ -460,6 +462,7 @@ TF_CALL_NUMBER_TYPES_NO_INT32(REGISTER_GPU_KERNEL); TF_CALL_NUMBER_TYPES_NO_INT32(REGISTER_GPU_REF_KERNEL); REGISTER_GPU_KERNEL(bool); REGISTER_GPU_REF_KERNEL(bool); +TF_CALL_variant(REGISTER_GPU_KERNEL); #undef REGISTER_GPU_KERNEL #undef REGISTER_GPU_REF_KERNEL @@ -541,6 +544,7 @@ REGISTER_KERNEL_BUILDER(Name("RefNextIteration").Device(DEVICE_CPU), TF_CALL_NUMBER_TYPES_NO_INT32(REGISTER_GPU_KERNEL); REGISTER_GPU_KERNEL(bool); +TF_CALL_variant(REGISTER_GPU_KERNEL); #undef REGISTER_GPU_KERNEL diff --git a/tensorflow/core/kernels/list_kernels.cc b/tensorflow/core/kernels/list_kernels.cc index 42fad1d4b0..f3684ffa20 100644 --- a/tensorflow/core/kernels/list_kernels.cc +++ b/tensorflow/core/kernels/list_kernels.cc @@ -495,6 +495,7 @@ TF_CALL_complex64(REGISTER_TENSOR_LIST_GET_ITEM_GPU); TF_CALL_complex128(REGISTER_TENSOR_LIST_GET_ITEM_GPU); TF_CALL_int64(REGISTER_TENSOR_LIST_GET_ITEM_GPU); REGISTER_TENSOR_LIST_GET_ITEM_GPU(bfloat16) +REGISTER_TENSOR_LIST_GET_ITEM_GPU(bool) #undef REGISTER_TENSOR_LIST_GET_ITEM_GPU #endif // GOOGLE_CUDA diff --git a/tensorflow/python/keras/layers/unified_gru_test.py b/tensorflow/python/keras/layers/unified_gru_test.py index 5527f21b6f..c1a9a360dc 100644 --- a/tensorflow/python/keras/layers/unified_gru_test.py +++ b/tensorflow/python/keras/layers/unified_gru_test.py @@ -414,8 +414,6 @@ class GRULayerV1OnlyTest(test.TestCase, parameterized.TestCase): @test_util.run_v1_only('b/120941292') @test_util.run_in_graph_and_eager_modes(config=_config) def test_statefulness_GRU(self): - self.skipTest('b/121275483') - num_samples = 2 timesteps = 3 embedding_dim = 4 -- GitLab From a9ba4a47efb80d2951ee6deea8e2d8de56dbaaf9 Mon Sep 17 00:00:00 2001 From: vitor-alves Date: Thu, 20 Dec 2018 17:26:45 -0200 Subject: [PATCH 0164/1765] Typo --- tensorflow/lite/examples/label_image/label_image.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/lite/examples/label_image/label_image.md b/tensorflow/lite/examples/label_image/label_image.md index fd9f49918b..debe8ffbc5 100644 --- a/tensorflow/lite/examples/label_image/label_image.md +++ b/tensorflow/lite/examples/label_image/label_image.md @@ -51,7 +51,7 @@ average time: 100.986 ms 0.0235294: 514 cornet 0.0196078: 835 suit ``` -Run `interpreter->Invoker()` 100 times: +Run `interpreter->Invoke()` 100 times: ``` > ./label_image -c 100 Loaded model ./mobilenet_quant_v1_224.tflite -- GitLab From 1d7de99259eae3e9076b3fe2acbddaac560e027b Mon Sep 17 00:00:00 2001 From: Francois Chollet Date: Thu, 20 Dec 2018 11:29:40 -0800 Subject: [PATCH 0165/1765] Clearly factor out the different code paths used for different input modes in `fit`, `evaluate`, and `predict`. This makes it clearer which arguments are supported in each case, and which validation checks or preprocessing steps are being applied in each case. The refactor revealed that `validation_split` was not supported with distribution strategies (not previously checked). PiperOrigin-RevId: 226366415 --- .../python/keras_backward_compat_test.py | 6 +- .../contrib/distribute/python/keras_test.py | 8 +- .../engine/distributed_training_utils.py | 343 ++++++++++ tensorflow/python/keras/engine/training.py | 286 +++++---- .../python/keras/engine/training_arrays.py | 12 +- .../keras/engine/training_dataset_test.py | 12 +- .../keras/engine/training_distributed.py | 596 +++++++----------- .../python/keras/engine/training_utils.py | 32 +- 8 files changed, 743 insertions(+), 552 deletions(-) diff --git a/tensorflow/contrib/distribute/python/keras_backward_compat_test.py b/tensorflow/contrib/distribute/python/keras_backward_compat_test.py index 93c0280c82..5e2a3d1184 100644 --- a/tensorflow/contrib/distribute/python/keras_backward_compat_test.py +++ b/tensorflow/contrib/distribute/python/keras_backward_compat_test.py @@ -1135,14 +1135,14 @@ class TestDistributionStrategyErrorCases(test.TestCase, parameterized.TestCase): # Test with not specifying the `steps` argument. with self.assertRaisesRegexp( - ValueError, 'you should specify the `steps_per_epoch` argument'): + ValueError, 'the `steps_per_epoch` argument'): model.fit(dataset, epochs=1, verbose=0) with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): + 'the `steps` argument'): model.evaluate(dataset, verbose=0) with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): + 'the `steps` argument'): model.predict(dataset, verbose=0) @combinations.generate(combinations.combine( diff --git a/tensorflow/contrib/distribute/python/keras_test.py b/tensorflow/contrib/distribute/python/keras_test.py index 84e9aea228..6339aa0e0d 100644 --- a/tensorflow/contrib/distribute/python/keras_test.py +++ b/tensorflow/contrib/distribute/python/keras_test.py @@ -1045,14 +1045,12 @@ class TestDistributionStrategyErrorCases(test.TestCase, parameterized.TestCase): # Test with not specifying the `steps` argument. with self.assertRaisesRegexp( - ValueError, 'you should specify the `steps_per_epoch` argument'): + ValueError, 'the `steps_per_epoch` argument'): model.fit(dataset, epochs=1, verbose=0) - with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): + with self.assertRaisesRegexp(ValueError, 'the `steps` argument'): model.evaluate(dataset, verbose=0) - with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): + with self.assertRaisesRegexp(ValueError, 'the `steps` argument'): model.predict(dataset, verbose=0) @combinations.generate(combinations.combine( diff --git a/tensorflow/python/keras/engine/distributed_training_utils.py b/tensorflow/python/keras/engine/distributed_training_utils.py index 4598f63c02..38a1a57522 100644 --- a/tensorflow/python/keras/engine/distributed_training_utils.py +++ b/tensorflow/python/keras/engine/distributed_training_utils.py @@ -13,6 +13,7 @@ # limitations under the License. # ============================================================================== """Utilities related to distributed training.""" +# pylint:disable=protected-access from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -24,15 +25,20 @@ from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import iterator_ops from tensorflow.python.distribute import distribute_coordinator_context as dc_context from tensorflow.python.distribute import distribute_lib +from tensorflow.python.eager import context from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops from tensorflow.python.framework import tensor_util from tensorflow.python.keras import backend as K from tensorflow.python.keras import callbacks +from tensorflow.python.keras import metrics as metrics_module +from tensorflow.python.keras import optimizers from tensorflow.python.keras.optimizer_v2 import optimizer_v2 from tensorflow.python.ops import array_ops +from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.training.mode_keys import ModeKeys from tensorflow.python.util import nest @@ -607,3 +613,340 @@ def _get_var_for_numpy(distribution_strategy, input_array): start = end return input_var + + +def _get_input_from_iterator(iterator, model): + """Get elements from the iterator and verify the input shape and type.""" + next_element = iterator.get_next() + + if len(nest.flatten(next_element)) == len(model.inputs): + x = next_element + y = None + sample_weights = None + elif len(nest.flatten(next_element)) == (len(model.inputs) + + len(model.outputs)): + x, y = next_element + sample_weights = None + else: + x, y, sample_weights = next_element + + # Validate that all the elements in x and y are of the same type and shape. + # We can then pass the first element of x and y to `_standardize_weights` + # below and be confident of the output. + validate_distributed_dataset_inputs( + model._distribution_strategy, x, y, sample_weights) + return x, y, sample_weights + + +def _prepare_feed_values(model, inputs, targets, sample_weights, mode): + """Prepare feed values to the model execution function. + + Arguments: + model: Model to prepare feed values for. + inputs: List or dict of model inputs. + targets: Optional list of model targets. + sample_weights: Optional list of sample weight arrays. + mode: One of 'train'/'test'/'predict'. + + Returns: + Feed values for the model in the given mode. + """ + strategy = model._distribution_strategy + inputs, targets, sample_weights = _get_input_from_iterator(inputs, model) + inputs = flatten_perdevice_values(strategy, inputs) + targets = flatten_perdevice_values(strategy, targets) + if mode == 'predict': + sample_weights = [] + targets = [] + else: + sample_weights = [ + None for _ in range(len(model.outputs) * strategy.num_replicas_in_sync) + ] + ins = inputs + targets + sample_weights + if mode == 'train' and not isinstance(K.symbolic_learning_phase(), int): + ins += [True] + return ins + + +def _custom_compile_for_predict(model): + """Custom compile for TPU predict mode.""" + model.total_loss = None + model._fit_function = None + model._eval_function = None + model.train_function = None + model.test_function = None + model.predict_function = None + + +def _build_network_on_replica(model, inputs=None, targets=None, mode=None): + """Build an updated model on replicas. + + We create a new Keras model while sharing the variables from the old graph. + Building a new sub-graph is required since the original keras model creates + placeholders for the input and the output that are not accessible till we + call iterator.get_next() inside the step_fn for `fit`/`evaluate`/`predict`. + + The sharing of weights and layers between the old and the new model gaurantee + that we're using Strategy variables and any updates on either model are + reflected correctly in callbacks and loop iterations. + + We need to make sure we share the optimizers between the old and the new model + as well so that optimizer state is not lost if the user is running fit + multiple times. + + Args: + model: Model to be replicated across Replicas + inputs: Input variables to be passed to the model + targets: Target tensor to be passed to model.compile + mode: Which of fit/eval/predict is building the distributed network + + Returns: + A new model with shared layers with the old model. + """ + # Need to do imports here since we run into a circular dependency error. + from tensorflow.python.keras import models # pylint: disable=g-import-not-at-top + from tensorflow.python.keras.engine import sequential # pylint: disable=g-import-not-at-top + + # We rely on the internal methods to avoid having share_weights weights in the + # public API. + if isinstance(model, sequential.Sequential): + updated_model = models._clone_sequential_model(model, input_tensors=inputs, + share_weights=True) + else: + updated_model = models._clone_functional_model(model, input_tensors=inputs, + share_weights=True) + + # Recast all low precision outputs back to float32 since we only casted + # the inputs to bfloat16 and not targets. This is done so that we can preserve + # precision when calculating the loss value. + def _upcast_low_precision_outputs(output): + if output.dtype == dtypes.bfloat16: + return math_ops.cast(output, dtypes.float32) + else: + return output + updated_model.outputs = [_upcast_low_precision_outputs(o) + for o in updated_model.outputs] + + if isinstance(targets, tuple): + targets = nest.flatten(targets) + + if mode == ModeKeys.PREDICT: + _custom_compile_for_predict(updated_model) + else: + updated_model.compile( + model.optimizer, + model.loss, + metrics=metrics_module.clone_metrics(model._compile_metrics), + loss_weights=model.loss_weights, + sample_weight_mode=model.sample_weight_mode, + weighted_metrics=metrics_module.clone_metrics( + model._compile_weighted_metrics), + target_tensors=targets) + return updated_model + + +def _build_distributed_network(model, strategy, inputs=None, targets=None, + mode=None): + """Create a cloned model on each replica.""" + with K.get_graph().as_default(), strategy.scope(): + distributed_model = strategy.extended.call_for_each_replica( + _build_network_on_replica, + args=(model, inputs, targets, mode)) + if mode is ModeKeys.TRAIN: + model._distributed_model_train = distributed_model + elif mode is ModeKeys.TEST: + model._distributed_model_test = distributed_model + elif mode is ModeKeys.PREDICT: + model._distributed_model_predict = distributed_model + else: + model._distributed_model = distributed_model + + +def _clone_and_build_model(model, inputs=None, targets=None, mode=None): + """Clone and build the given keras_model.""" + # We need to set the import here since we run into a circular dependency + # error. + from tensorflow.python.keras import models # pylint: disable=g-import-not-at-top + cloned_model = models.clone_model(model, input_tensors=inputs) + + # Compile and build model. + if isinstance(model.optimizer, optimizers.TFOptimizer): + optimizer = model.optimizer + else: + optimizer_config = model.optimizer.get_config() + optimizer = model.optimizer.__class__.from_config(optimizer_config) + + # Recast all low precision outputs back to float32 since we only casted + # the inputs to bfloat16 and not targets. This is done so that we can preserve + # precision when calculating the loss value. + def _upcast_low_precision_outputs(output): + if output.dtype == dtypes.bfloat16: + return math_ops.cast(output, dtypes.float32) + else: + return output + cloned_model.outputs = [_upcast_low_precision_outputs(o) + for o in cloned_model.outputs] + + if isinstance(targets, tuple): + targets = nest.flatten(targets) + if mode == ModeKeys.PREDICT: + _custom_compile_for_predict(cloned_model) + else: + cloned_model.compile( + optimizer, + model.loss, + metrics=metrics_module.clone_metrics(model._compile_metrics), + loss_weights=model.loss_weights, + sample_weight_mode=model.sample_weight_mode, + weighted_metrics=metrics_module.clone_metrics( + model._compile_weighted_metrics), + target_tensors=targets) + return cloned_model + + +def clone_model_on_replicas(model, strategy, make_callback_model=False, + inputs=None, targets=None, mode=None): + """Create a cloned model on each replica.""" + with K.get_graph().as_default(), strategy.scope(): + distributed_model = strategy.extended.call_for_each_replica( + _clone_and_build_model, args=(model, inputs, targets, mode)) + if mode is ModeKeys.TRAIN: + model._distributed_model_train = distributed_model + elif mode is ModeKeys.TEST: + model._distributed_model_test = distributed_model + elif mode is ModeKeys.PREDICT: + model._distributed_model_predict = distributed_model + else: + model._distributed_model = distributed_model + if make_callback_model: + model._make_callback_model(distributed_model) + + +def _make_execution_function(model, mode): + """Makes function to run one step of distributed model execution.""" + if context.executing_eagerly(): + return _make_eager_execution_function(model, mode) + + strategy = model._distribution_strategy + if not model._distributed_model: + if model._compile_distribution: + clone_model_on_replicas( + model, strategy, make_callback_model=(mode == 'train')) + else: + _build_distributed_network(model, strategy) + + def _per_device_function(model): + f = model._make_execution_function(mode) + return (f.inputs, f.outputs, f.updates_op, f.session_kwargs) + + with strategy.scope(): + # Create train ops on each of the devices when we call + # `_per_device_fit_function`. + (grouped_inputs, grouped_outputs, grouped_updates, + grouped_session_args) = strategy.extended.call_for_each_replica( + _per_device_function, args=(model._distributed_model,)) + + if mode == 'train': + # Initialize the variables in the replicated model. This is necessary for + # multi-worker training because on some workers, initialization is not + # needed. This method does initialization or waiting for initialization + # according to the context object of distribute coordinator. + init_restore_or_wait_for_variables() + + # Unwrap all the per device values returned from `call_for_each_replica`. + # Unwrapping per device values gives you a list of values that can be + # used to construct a new train function that is composed of update ops on + # all the devices over which the model is distributed. + (all_inputs, all_outputs, all_updates, + all_session_args) = unwrap_values( + strategy, + grouped_inputs, + grouped_outputs, + grouped_updates, + grouped_session_args, + with_loss_tensor=(mode != 'predict')) + + return K.function( + all_inputs, + all_outputs, + updates=all_updates, + name='distributed_{}_function'.format(mode), + **all_session_args) + + +def _make_eager_execution_function(model, mode): + """Makes function to run one step of distributed model eager execution.""" + strategy = model._distribution_strategy + if not model._distributed_model: + if model._compile_distribution: + clone_model_on_replicas( + model, strategy, make_callback_model=(mode == 'train')) + else: + _build_distributed_network(model, strategy) + + def _per_device_function(model): + f = model._make_execution_function(mode) + return (f.inputs, f.outputs) + + # NOTE(priyag): Try creating a new FuncGraph within DS scope instead of using + # the global one. + with K.get_graph().as_default(), strategy.scope(): + # Create train ops on each of the devices when we call + # `_per_device_fit_function`. + (grouped_inputs, grouped_outputs) = strategy.call_for_each_replica( + _per_device_function, args=(model._distributed_model,)) + + # Unwrap all the per device values returned from `call_for_each_replica`. + # Unwrapping per device values gives you a list of values that can be + # used to construct a new train function that is composed of inptus/outputs + # on all the devices over which the model is distributed. + (all_inputs, all_outputs, _, _) = unwrap_values( + strategy, + grouped_inputs, + grouped_outputs, + with_loss_tensor=(mode != 'predict')) + + return K.function( + all_inputs, + all_outputs, + name='eager_distributed_{}_function'.format(mode)) + + +def _copy_weights_to_distributed_model(original_model, grouped_model): + """Copies weights from original model to distributed models.""" + strategy = original_model._distribution_strategy + if strategy: + # Copy the weights from the original model to each of the replicated + # models. + orig_model_weights = original_model.get_weights() + distributed_model = strategy.unwrap(grouped_model)[0] + set_weights(strategy, distributed_model, orig_model_weights) + + +def _copy_weights_to_original_model(model, grouped_model, mode): + """Copies weights from first distributed model back to original model.""" + if model._distribution_strategy and mode == 'train': + updated_weights = model._distribution_strategy.unwrap( + grouped_model)[0].get_weights() + model.set_weights(updated_weights) + + +def _per_device_aggregate_batch(batch_outs, model, mode): + """Aggregates the per-device batch-level outputs from a distributed step.""" + if model._distribution_strategy is not None and mode == 'predict': + total_batch_outs = [] + for i in range(len(model.outputs)): + num_replicas = model._distribution_strategy.num_replicas_in_sync + nested_outs = batch_outs[i * num_replicas:i * num_replicas + num_replicas] + total_batch_outs.append(np.concatenate(nest.flatten(nested_outs))) + return total_batch_outs + return batch_outs + + +def _reset_metrics(model, distributed_model=None): + if model._distribution_strategy: + distributed_model = ( + distributed_model or + model._distribution_strategy.unwrap(model._distributed_model)[0]) + distributed_model.reset_metrics() + diff --git a/tensorflow/python/keras/engine/training.py b/tensorflow/python/keras/engine/training.py index ce8570e31e..2ef2e37a39 100644 --- a/tensorflow/python/keras/engine/training.py +++ b/tensorflow/python/keras/engine/training.py @@ -756,10 +756,42 @@ class Model(Network): ValueError: In case of mismatch between the provided input data and what the model expects. """ - # TODO(fchollet): this method may be creating reference cycles, which would - # lead to accumulating garbage in memory when called in a loop. Investigate. + # Legacy support + if 'nb_epoch' in kwargs: + logging.warning( + 'The `nb_epoch` argument in `fit` ' + 'has been renamed `epochs`.') + epochs = kwargs.pop('nb_epoch') + if kwargs: + raise TypeError('Unrecognized keyword arguments: ' + str(kwargs)) + + # Case 1: distribution strategy. + if self._distribution_strategy: + return training_distributed.fit_distributed( + self, + x=x, + y=y, + batch_size=batch_size, + epochs=epochs, + verbose=verbose, + callbacks=callbacks, + validation_split=validation_split, + validation_data=validation_data, + shuffle=shuffle, + class_weight=class_weight, + sample_weight=sample_weight, + initial_epoch=initial_epoch, + steps_per_epoch=steps_per_epoch, + validation_steps=validation_steps) + + batch_size = self._validate_or_infer_batch_size( + batch_size, steps_per_epoch, x) + + # Case 2: generator-like. Input is Python generator, or Sequence object, + # or a non-distributed Dataset or iterator in eager execution. if data_utils.is_generator_or_sequence(x): - training_utils.check_generator_arguments(y, sample_weight) + training_utils.check_generator_arguments( + y, sample_weight, validation_split=validation_split) return self.fit_generator( x, steps_per_epoch=steps_per_epoch, @@ -774,33 +806,26 @@ class Model(Network): use_multiprocessing=use_multiprocessing, shuffle=shuffle, initial_epoch=initial_epoch) + if training_utils.is_eager_dataset_or_iterator(x): + # Make sure that y, sample_weights, validation_split are not passed. + training_utils.validate_dataset_input(x, y, sample_weight, + validation_split) + return self.fit_generator( + x, + steps_per_epoch=steps_per_epoch, + epochs=epochs, + verbose=verbose, + callbacks=callbacks, + validation_data=validation_data, + validation_steps=validation_steps, + class_weight=class_weight, + workers=0, + shuffle=shuffle, + initial_epoch=initial_epoch) - # Legacy support - if 'nb_epoch' in kwargs: - logging.warning( - 'The `nb_epoch` argument in `fit` ' - 'has been renamed `epochs`.') - epochs = kwargs.pop('nb_epoch') - if kwargs: - raise TypeError('Unrecognized keyword arguments: ' + str(kwargs)) - - # Validate and standardize user data. - if self._distribution_strategy: - distributed_training_utils.validate_callbacks(callbacks, self.optimizer) - - distributed_training_utils.validate_inputs( - x, y, self._distribution_strategy) - - first_x_value = nest.flatten(x)[0] - if isinstance(first_x_value, np.ndarray): - steps_per_epoch, batch_size = ( - distributed_training_utils.get_input_params( - self._distribution_strategy, first_x_value, steps_per_epoch, - batch_size, is_training=True)) - - batch_size = self._validate_or_infer_batch_size(batch_size, steps_per_epoch, - x) - + # Case 3: Symbolic tensors or Numpy array-like. + # This includes Datasets and iterators in graph mode (since they + # generate symbolic tensors). x, y, sample_weights = self._standardize_user_data( x, y, @@ -815,43 +840,15 @@ class Model(Network): # Prepare validation data. if validation_data: - if (isinstance(validation_data, iterator_ops.Iterator) or - isinstance(validation_data, iterator_ops.EagerIterator) or - isinstance(validation_data, dataset_ops.DatasetV2)): - val_x = validation_data - val_y = None - val_sample_weight = None - elif len(validation_data) == 2: - val_x, val_y = validation_data # pylint: disable=unpacking-non-sequence - val_sample_weight = None - elif len(validation_data) == 3: - val_x, val_y, val_sample_weight = validation_data # pylint: disable=unpacking-non-sequence - else: - raise ValueError( - 'When passing a `validation_data` argument, ' - 'it must contain either 2 items (x_val, y_val), ' - 'or 3 items (x_val, y_val, val_sample_weights), ' - 'or alternatively it could be a dataset or a ' - 'dataset or a dataset iterator. ' - 'However we received `validation_data=%s`' % validation_data) - - # Validate and standardize validation data. - if self._distribution_strategy: - distributed_training_utils.validate_inputs( - val_x, val_y, self._distribution_strategy) - first_valx_value = nest.flatten(val_x)[0] - if isinstance(first_valx_value, np.ndarray): - validation_steps, _ = distributed_training_utils.get_input_params( - self._distribution_strategy, first_valx_value, validation_steps, - batch_size) - + val_x, val_y, val_sample_weights = self._unpack_validation_data( + validation_data) val_x, val_y, val_sample_weights = self._standardize_user_data( val_x, val_y, - sample_weight=val_sample_weight, + sample_weight=val_sample_weights, batch_size=batch_size, - steps=validation_steps) - + steps=validation_steps, + steps_name='validation_steps') elif validation_split and 0. < validation_split < 1.: if training_utils.has_symbolic_tensors(x): raise ValueError('If your data is in the form of symbolic tensors, ' @@ -873,32 +870,19 @@ class Model(Network): val_y = None val_sample_weights = None - if (self.run_eagerly or (isinstance(x, iterator_ops.EagerIterator) and - not self._distribution_strategy)): + if self.run_eagerly: return training_generator.fit_generator( self, (x, y, sample_weights), steps_per_epoch=steps_per_epoch, batch_size=batch_size, epochs=epochs, - shuffle=shuffle, verbose=verbose, callbacks=callbacks, validation_data=validation_data, validation_steps=validation_steps, workers=0, + shuffle=shuffle, initial_epoch=initial_epoch) - elif distributed_training_utils.is_tpu_strategy( - self._distribution_strategy): - return training_distributed.experimental_fit_loop( - self, - x, - epochs=epochs, - verbose=verbose, - callbacks=callbacks, - val_iterator=val_x, - initial_epoch=initial_epoch, - steps_per_epoch=steps_per_epoch, - validation_steps=validation_steps) else: return training_arrays.fit_loop( self, @@ -1001,8 +985,25 @@ class Model(Network): Raises: ValueError: in case of invalid arguments. """ + # Case 1: distribution strategy. + if self._distribution_strategy: + return training_distributed.evaluate_distributed( + self, + x=x, + y=y, + batch_size=batch_size, + verbose=verbose, + sample_weight=sample_weight, + steps=steps, + callbacks=callbacks) + + batch_size = self._validate_or_infer_batch_size(batch_size, steps, x) + + # Case 2: generator-like. Input is Python generator, or Sequence object, + # or a non-distributed Dataset or iterator in eager execution. if data_utils.is_generator_or_sequence(x): training_utils.check_generator_arguments(y, sample_weight) + # TODO(fchollet): why aren't callbacks supported here? return self.evaluate_generator( x, steps=steps, @@ -1010,17 +1011,20 @@ class Model(Network): max_queue_size=max_queue_size, workers=workers, use_multiprocessing=use_multiprocessing) - # Validate and standardize user data. - if self._distribution_strategy: - distributed_training_utils.validate_inputs( - x, y, self._distribution_strategy) - first_x_value = nest.flatten(x)[0] - if isinstance(first_x_value, np.ndarray): - steps, batch_size = distributed_training_utils.get_input_params( - self._distribution_strategy, first_x_value, steps, batch_size) - - batch_size = self._validate_or_infer_batch_size(batch_size, steps, x) + if training_utils.is_eager_dataset_or_iterator(x): + # Make sure that y, sample_weights are not passed. + training_utils.validate_dataset_input(x, y, sample_weight) + return training_generator.evaluate_generator( + self, x, + steps=steps, + batch_size=batch_size, + verbose=verbose, + workers=0, + callbacks=callbacks) + # Case 3: Symbolic tensors or Numpy array-like. + # This includes Datasets and iterators in graph mode (since they + # generate symbolic tensors). x, y, sample_weights = self._standardize_user_data( x, y, @@ -1030,8 +1034,7 @@ class Model(Network): steps_name='steps', steps=steps) - if (self.run_eagerly or (isinstance(x, iterator_ops.EagerIterator) and - not self._distribution_strategy)): + if self.run_eagerly: return training_generator.evaluate_generator( self, (x, y, sample_weights), steps=steps, @@ -1039,10 +1042,6 @@ class Model(Network): verbose=verbose, workers=0, callbacks=callbacks) - elif distributed_training_utils.is_tpu_strategy( - self._distribution_strategy): - return training_distributed.experimental_test_loop( - self, iterator=x, verbose=verbose, steps=steps) else: return training_arrays.test_loop( self, @@ -1113,7 +1112,21 @@ class Model(Network): or in case a stateful model receives a number of samples that is not a multiple of the batch size. """ + # Case 1: distribution strategy. + if self._distribution_strategy: + return training_distributed.predict_distributed(self, + x=x, + batch_size=batch_size, + verbose=verbose, + steps=steps, + callbacks=callbacks) + + batch_size = self._validate_or_infer_batch_size(batch_size, steps, x) + + # Case 2: generator-like. Input is Python generator, or Sequence object, + # or a non-distributed Dataset or iterator in eager execution. if data_utils.is_generator_or_sequence(x): + # TODO(fchollet): why aren't callbacks supported here? return self.predict_generator( x, steps=steps, @@ -1121,30 +1134,23 @@ class Model(Network): max_queue_size=max_queue_size, workers=workers, use_multiprocessing=use_multiprocessing) - if self._distribution_strategy: - distributed_training_utils.validate_inputs( - x, None, self._distribution_strategy) - first_x_value = nest.flatten(x)[0] - if isinstance(first_x_value, np.ndarray): - steps, batch_size = distributed_training_utils.get_input_params( - self._distribution_strategy, first_x_value, steps, batch_size) + if training_utils.is_eager_dataset_or_iterator(x): + return training_generator.predict_generator( + self, + x, + steps=steps, + batch_size=batch_size, + verbose=verbose, + workers=0, + callbacks=callbacks) - batch_size = self._validate_or_infer_batch_size(batch_size, steps, x) + # Case 3: Symbolic tensors or Numpy array-like. + # This includes Datasets and iterators in graph mode (since they + # generate symbolic tensors). + x, _, _ = self._standardize_user_data( + x, check_steps=True, steps_name='steps', steps=steps) - # Validate and standardize user data. - if self._distribution_strategy: - x, _, _ = self._standardize_user_data( - x, check_steps=True, steps_name='steps', steps=steps, - batch_size=batch_size) - else: - # TODO(anjalisridhar): We don't pass batch_size here for some reason. This - # means we need to special case distribution strategy which needs the - # batch size. - x, _, _ = self._standardize_user_data( - x, check_steps=True, steps_name='steps', steps=steps) - - if (self.run_eagerly or (isinstance(x, iterator_ops.EagerIterator) and - not self._distribution_strategy)): + if self.run_eagerly: return training_generator.predict_generator( self, x, @@ -1153,10 +1159,6 @@ class Model(Network): verbose=verbose, workers=0, callbacks=callbacks) - elif distributed_training_utils.is_tpu_strategy( - self._distribution_strategy): - return training_distributed.experimental_predict_loop( - self, x, verbose=verbose, steps=steps) else: return training_arrays.predict_loop( self, @@ -1172,7 +1174,7 @@ class Model(Network): for m in self.metrics: m.reset_states() if self._distribution_strategy: - training_distributed._reset_metrics(self) # pylint: disable=protected-access + distributed_training_utils._reset_metrics(self) # pylint: disable=protected-access def train_on_batch(self, x, @@ -2191,8 +2193,8 @@ class Model(Network): if not context.executing_eagerly(): K.get_session().run(init_op) - training_utils.validate_iterator_input(x, y, sample_weight, - validation_split) + training_utils.validate_dataset_input(x, y, sample_weight, + validation_split) return iterator def _standardize_user_data(self, @@ -2260,20 +2262,6 @@ class Model(Network): ValueError: In case of invalid user-provided data. RuntimeError: If the model was never compiled. """ - if self._distribution_strategy: - iterator = self._distribution_standardize_user_data( - x, - y, - sample_weight=sample_weight, - class_weight=class_weight, - batch_size=batch_size, - check_steps=check_steps, - steps_name=steps_name, - steps=steps, - validation_split=validation_split, - shuffle=shuffle) - return iterator, None, None - if isinstance(x, dataset_ops.DatasetV2): if context.executing_eagerly(): x = iter(x) @@ -2295,8 +2283,8 @@ class Model(Network): # Validate user inputs when data is given as a dataset or dataset iterator. if is_x_iterator or is_x_eager_iterator: - training_utils.validate_iterator_input(x, y, sample_weight, - validation_split) + training_utils.validate_dataset_input(x, y, sample_weight, + validation_split) # For eager iterators, when we have to process multiple batches of samples, # we will standardize the data when we actually loop over iterator and get @@ -2540,6 +2528,28 @@ class Model(Network): x = dict(zip(feed_input_names, x)) return x, y, sample_weights + def _unpack_validation_data(self, validation_data): + if (isinstance(validation_data, (iterator_ops.Iterator, + iterator_ops.EagerIterator, + dataset_ops.DatasetV2))): + val_x = validation_data + val_y = None + val_sample_weight = None + elif len(validation_data) == 2: + val_x, val_y = validation_data # pylint: disable=unpacking-non-sequence + val_sample_weight = None + elif len(validation_data) == 3: + val_x, val_y, val_sample_weight = validation_data # pylint: disable=unpacking-non-sequence + else: + raise ValueError( + 'When passing a `validation_data` argument, ' + 'it must contain either 2 items (x_val, y_val), ' + 'or 3 items (x_val, y_val, val_sample_weights), ' + 'or alternatively it could be a dataset or a ' + 'dataset or a dataset iterator. ' + 'However we received `validation_data=%s`' % validation_data) + return val_x, val_y, val_sample_weight + @checkpointable.no_automatic_dependency_tracking def _set_inputs(self, inputs, outputs=None, training=None): """Set model's input and output specs based on the input data received. diff --git a/tensorflow/python/keras/engine/training_arrays.py b/tensorflow/python/keras/engine/training_arrays.py index e4f91fa18a..97025a9e18 100644 --- a/tensorflow/python/keras/engine/training_arrays.py +++ b/tensorflow/python/keras/engine/training_arrays.py @@ -27,7 +27,7 @@ from tensorflow.python.eager import context from tensorflow.python.framework import errors from tensorflow.python.keras import backend as K from tensorflow.python.keras import callbacks as cbks -from tensorflow.python.keras.engine import training_distributed +from tensorflow.python.keras.engine import distributed_training_utils from tensorflow.python.keras.engine import training_utils from tensorflow.python.keras.utils.generic_utils import make_batches from tensorflow.python.keras.utils.generic_utils import slice_arrays @@ -92,7 +92,7 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): """ if model._distribution_strategy: def get_distributed_inputs(): - return training_distributed._prepare_feed_values( + return distributed_training_utils._prepare_feed_values( model, inputs, targets, sample_weights, mode) # In the eager case, we want to call the input method per step, so return @@ -120,7 +120,7 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): def _make_execution_function(model, mode): """Makes function to run one step of model execution.""" if model._distribution_strategy: - return training_distributed._make_execution_function(model, mode) + return distributed_training_utils._make_execution_function(model, mode) return model._make_execution_function(mode) @@ -239,7 +239,7 @@ def model_iteration(model, num_samples_or_steps) if model._compile_distribution and not validation_in_fit: - training_distributed._copy_weights_to_distributed_model( + distributed_training_utils._copy_weights_to_distributed_model( model, model._distributed_model) callbacks.model.stop_training = False @@ -281,7 +281,7 @@ def model_iteration(model, batch_outs = [batch_outs] if model._distribution_strategy: - batch_outs = training_distributed._per_device_aggregate_batch( + batch_outs = distributed_training_utils._per_device_aggregate_batch( batch_outs, model, mode) # Aggregate results. @@ -382,7 +382,7 @@ def model_iteration(model, if model._distribution_strategy: if model._compile_distribution and not validation_in_fit: # TODO(priyag, psv): Copy back metrics to the original model as well? - training_distributed._copy_weights_to_original_model( + distributed_training_utils._copy_weights_to_original_model( model, model._distributed_model, mode) scope.__exit__(None, None, None) diff --git a/tensorflow/python/keras/engine/training_dataset_test.py b/tensorflow/python/keras/engine/training_dataset_test.py index d6cc93d1ef..f542ebfddc 100644 --- a/tensorflow/python/keras/engine/training_dataset_test.py +++ b/tensorflow/python/keras/engine/training_dataset_test.py @@ -90,13 +90,13 @@ class TestTrainingWithDatasetIterators(keras_parameterized.TestCase): epochs=1, steps_per_epoch=2, verbose=0) with self.assertRaisesRegexp( - ValueError, 'you should specify the `steps_per_epoch` argument'): + ValueError, 'the `steps_per_epoch` argument'): model.fit(iterator, epochs=1, verbose=0) with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): + 'the `steps` argument'): model.evaluate(iterator, verbose=0) with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): + 'the `steps` argument'): model.predict(iterator, verbose=0) @keras_parameterized.run_with_all_model_types @@ -229,13 +229,13 @@ class TestTrainingWithDataset(keras_parameterized.TestCase): epochs=1, steps_per_epoch=2, verbose=0) with self.assertRaisesRegexp( - ValueError, 'you should specify the `steps_per_epoch` argument'): + ValueError, 'the `steps_per_epoch` argument'): model.fit(dataset, epochs=1, verbose=0) with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): + 'the `steps` argument'): model.evaluate(dataset, verbose=0) with self.assertRaisesRegexp(ValueError, - 'you should specify the `steps` argument'): + 'the `steps` argument'): model.predict(dataset, verbose=0) @keras_parameterized.run_with_all_model_types diff --git a/tensorflow/python/keras/engine/training_distributed.py b/tensorflow/python/keras/engine/training_distributed.py index 7cf5854af0..3102a0127a 100644 --- a/tensorflow/python/keras/engine/training_distributed.py +++ b/tensorflow/python/keras/engine/training_distributed.py @@ -23,36 +23,190 @@ import numpy as np from tensorflow.python.distribute import distribute_lib from tensorflow.python.distribute import reduce_util as ds_reduce_util -from tensorflow.python.eager import context from tensorflow.python.framework import constant_op -from tensorflow.python.framework import dtypes from tensorflow.python.framework import errors from tensorflow.python.framework import tensor_shape from tensorflow.python.keras import backend as K from tensorflow.python.keras import callbacks as cbks -from tensorflow.python.keras import metrics as metrics_module -from tensorflow.python.keras import optimizers from tensorflow.python.keras.engine import distributed_training_utils +from tensorflow.python.keras.engine import training_arrays from tensorflow.python.keras.utils.generic_utils import Progbar from tensorflow.python.ops import array_ops -from tensorflow.python.ops import math_ops from tensorflow.python.platform import tf_logging as logging from tensorflow.python.training.mode_keys import ModeKeys from tensorflow.python.util import nest -# TODO(priyag, sourabhbajaj): Refactor this file to address code duplication. - - -def experimental_fit_loop(model, - iterator, - epochs=100, - verbose=1, - callbacks=None, - initial_epoch=0, - steps_per_epoch=None, - val_iterator=None, - validation_steps=None): +def fit_distributed(model, + x=None, + y=None, + batch_size=None, + epochs=1, + verbose=1, + callbacks=None, + validation_split=0., + validation_data=None, + shuffle=True, + class_weight=None, + sample_weight=None, + initial_epoch=0, + steps_per_epoch=None, + validation_steps=None): + """Fit loop for Distribution Strategies.""" + distributed_training_utils.validate_callbacks(callbacks, model.optimizer) + distributed_training_utils.validate_inputs( + x, y, model._distribution_strategy) + + first_x_value = nest.flatten(x)[0] + if isinstance(first_x_value, np.ndarray): + steps_per_epoch, batch_size = ( + distributed_training_utils.get_input_params( + model._distribution_strategy, first_x_value, steps_per_epoch, + batch_size, is_training=True)) + batch_size = model._validate_or_infer_batch_size( + batch_size, steps_per_epoch, x) + iterator = model._distribution_standardize_user_data( + x, y, + sample_weight=sample_weight, + class_weight=class_weight, + batch_size=batch_size, + check_steps=True, + steps_name='steps_per_epoch', + steps=steps_per_epoch, + validation_split=validation_split, + shuffle=shuffle) + + val_iterator = None + if validation_data: + val_x, val_y, val_sample_weights = model._unpack_validation_data( + validation_data) + distributed_training_utils.validate_inputs( + val_x, val_y, model._distribution_strategy) + first_valx_value = nest.flatten(val_x)[0] + if isinstance(first_valx_value, np.ndarray): + validation_steps, _ = distributed_training_utils.get_input_params( + model._distribution_strategy, first_valx_value, validation_steps, + batch_size) + val_iterator = model._distribution_standardize_user_data( + val_x, val_y, + sample_weight=val_sample_weights, + class_weight=None, + batch_size=batch_size, + check_steps=True, + steps_name='validation_steps', + steps=validation_steps, + validation_split=validation_split, + shuffle=shuffle) + elif validation_split: + raise ValueError('validation_split argument is not supported with ' + 'distribution strategies.') + + if distributed_training_utils.is_tpu_strategy(model._distribution_strategy): + return experimental_tpu_fit_loop( + model, + iterator, + epochs=epochs, + verbose=verbose, + callbacks=callbacks, + val_iterator=val_iterator, + initial_epoch=initial_epoch, + steps_per_epoch=steps_per_epoch, + validation_steps=validation_steps) + else: + return training_arrays.fit_loop( + model, + iterator, + batch_size=batch_size, + epochs=epochs, + verbose=verbose, + callbacks=callbacks, + val_inputs=val_iterator, + shuffle=shuffle, + initial_epoch=initial_epoch, + steps_per_epoch=steps_per_epoch, + validation_steps=validation_steps) + + +def evaluate_distributed(model, + x=None, + y=None, + batch_size=None, + verbose=1, + sample_weight=None, + steps=None, + callbacks=None): + """Evaluate loop for Distribution Strategies.""" + distributed_training_utils.validate_inputs(x, y, model._distribution_strategy) + first_x_value = nest.flatten(x)[0] + if isinstance(first_x_value, np.ndarray): + steps, batch_size = distributed_training_utils.get_input_params( + model._distribution_strategy, first_x_value, steps, batch_size) + batch_size = model._validate_or_infer_batch_size(batch_size, steps, x) + iterator = model._distribution_standardize_user_data( + x, y, + sample_weight=sample_weight, + batch_size=batch_size, + check_steps=True, + steps_name='steps', + steps=steps) + + if distributed_training_utils.is_tpu_strategy(model._distribution_strategy): + # TODO(fchollet): why aren't callbacks supported here? + return experimental_tpu_test_loop( + model, iterator=iterator, verbose=verbose, steps=steps) + else: + return training_arrays.test_loop( + model, + inputs=iterator, + batch_size=batch_size, + verbose=verbose, + steps=steps, + callbacks=callbacks) + + +def predict_distributed(model, + x=None, + batch_size=None, + verbose=0, + steps=None, + callbacks=None): + """Predict loop for Distribution Strategies.""" + distributed_training_utils.validate_inputs( + x, None, model._distribution_strategy) + first_x_value = nest.flatten(x)[0] + if isinstance(first_x_value, np.ndarray): + steps, batch_size = distributed_training_utils.get_input_params( + model._distribution_strategy, first_x_value, steps, batch_size) + batch_size = model._validate_or_infer_batch_size(batch_size, steps, x) + iterator = model._distribution_standardize_user_data( + x, + batch_size=batch_size, + check_steps=True, + steps_name='steps', + steps=steps) + if distributed_training_utils.is_tpu_strategy(model._distribution_strategy): + # TODO(fchollet): why aren't callbacks supported here? + return experimental_tpu_predict_loop( + model, iterator, verbose=verbose, steps=steps) + else: + return training_arrays.predict_loop( + model, + iterator, + batch_size=batch_size, + verbose=verbose, + steps=steps, + callbacks=callbacks) + + +def experimental_tpu_fit_loop(model, + iterator, + epochs=100, + verbose=1, + callbacks=None, + initial_epoch=0, + steps_per_epoch=None, + val_iterator=None, + validation_steps=None): """Fit loop for training with TPU DistributionStrategy. Arguments: @@ -94,12 +248,14 @@ def experimental_fit_loop(model, """Clones the model and calls make_fit_function.""" inputs, targets = inputs if model._compile_distribution: - clone_model_on_replicas(model, current_strategy, - make_callback_model=True, inputs=inputs, - targets=targets, mode=ModeKeys.TRAIN) + distributed_training_utils.clone_model_on_replicas( + model, current_strategy, + make_callback_model=True, inputs=inputs, + targets=targets, mode=distributed_training_utils.ModeKeys.TRAIN) else: - _build_distributed_network(model, current_strategy, inputs, - targets, mode=ModeKeys.TRAIN) + distributed_training_utils._build_distributed_network( + model, current_strategy, inputs, + targets, mode=distributed_training_utils.ModeKeys.TRAIN) (grouped_inputs, grouped_outputs, grouped_updates, grouped_session_args) = current_strategy.extended.call_for_each_replica( @@ -156,7 +312,8 @@ def experimental_fit_loop(model, if model._compile_distribution: with current_strategy.scope(): - _copy_weights_to_distributed_model(model, model._distributed_model_train) + distributed_training_utils._copy_weights_to_distributed_model( + model, model._distributed_model_train) callbacks = cbks.configure_callbacks( callbacks, @@ -176,7 +333,8 @@ def experimental_fit_loop(model, callbacks.on_train_begin() for epoch in range(initial_epoch, epochs): with current_strategy.scope(): - _reset_metrics(model, model._distributed_model_train) + distributed_training_utils._reset_metrics( + model, model._distributed_model_train) callbacks.on_epoch_begin(epoch) epoch_logs = {} step_index = 0 @@ -210,10 +368,10 @@ def experimental_fit_loop(model, # Since we create a new clone from the original model we need to copy # the weights back to the original model before we can run validation. with current_strategy.scope(): - _copy_weights_to_original_model( + distributed_training_utils._copy_weights_to_original_model( model, model._distributed_model_train, ModeKeys.TRAIN) - val_outs = experimental_test_loop( # pylint: disable=undefined-variable + val_outs = experimental_tpu_test_loop( # pylint: disable=undefined-variable model, val_iterator, steps=validation_steps, @@ -232,16 +390,16 @@ def experimental_fit_loop(model, if model._compile_distribution: # Copy the weights back from the replicated model to the original model. with current_strategy.scope(): - _copy_weights_to_original_model(model, model._distributed_model_train, - ModeKeys.TRAIN) + distributed_training_utils._copy_weights_to_original_model( + model, model._distributed_model_train, 'train') scope.__exit__(None, None, None) return model.history -def experimental_test_loop(model, - iterator, - verbose=0, - steps=None): +def experimental_tpu_test_loop(model, + iterator, + verbose=0, + steps=None): """Test loop for evaluating with TPU DistributionStrategy. Arguments: @@ -275,12 +433,14 @@ def experimental_test_loop(model, """Clones the model and calls make_eval_function.""" inputs, targets = inputs if model._compile_distribution: - clone_model_on_replicas(model, current_strategy, - make_callback_model=False, inputs=inputs, - targets=targets, mode=ModeKeys.TEST) + distributed_training_utils. clone_model_on_replicas( + model, current_strategy, + make_callback_model=False, inputs=inputs, + targets=targets, mode=distributed_training_utils.ModeKeys.TEST) else: - _build_distributed_network(model, current_strategy, inputs, - targets, mode=ModeKeys.TEST) + distributed_training_utils._build_distributed_network( + model, current_strategy, inputs, targets, + mode=distributed_training_utils.ModeKeys.TEST) (grouped_inputs, grouped_outputs, grouped_updates, grouped_session_args) = current_strategy.extended.call_for_each_replica( @@ -330,9 +490,11 @@ def experimental_test_loop(model, if model._compile_distribution: with current_strategy.scope(): - _copy_weights_to_distributed_model(model, model._distributed_model_test) + distributed_training_utils._copy_weights_to_distributed_model( + model, model._distributed_model_test) with current_strategy.scope(): - _reset_metrics(model, model._distributed_model_test) + distributed_training_utils._reset_metrics( + model, model._distributed_model_test) assert steps is not None outs = [0.] * len(model.metrics_names) @@ -358,7 +520,7 @@ def experimental_test_loop(model, return outs -def experimental_predict_loop(model, iterator, verbose=0, steps=None): +def experimental_tpu_predict_loop(model, iterator, verbose=0, steps=None): """Predict loop for predicting with TPU DistributionStrategy. Arguments: @@ -391,12 +553,14 @@ def experimental_predict_loop(model, iterator, verbose=0, steps=None): def step_fn(ctx, inputs): """Clones the model and calls make_predict_function.""" if model._compile_distribution: - clone_model_on_replicas(model, current_strategy, - make_callback_model=False, inputs=inputs, - mode=ModeKeys.PREDICT) + distributed_training_utils. clone_model_on_replicas( + model, current_strategy, + make_callback_model=False, inputs=inputs, + mode=distributed_training_utils.ModeKeys.PREDICT) else: - _build_distributed_network(model, current_strategy, inputs, - mode=ModeKeys.PREDICT) + distributed_training_utils._build_distributed_network( + model, current_strategy, inputs, + mode=distributed_training_utils.ModeKeys.PREDICT) (grouped_inputs, grouped_outputs, grouped_updates, grouped_session_args) = current_strategy.extended.call_for_each_replica( @@ -442,10 +606,11 @@ def experimental_predict_loop(model, iterator, verbose=0, steps=None): if model._compile_distribution: with current_strategy.scope(): - _copy_weights_to_distributed_model( + distributed_training_utils._copy_weights_to_distributed_model( model, model._distributed_model_predict) with current_strategy.scope(): - _reset_metrics(model, model._distributed_model_predict) + distributed_training_utils._reset_metrics( + model, model._distributed_model_predict) assert steps is not None # Since we do not know how many samples we will see, we cannot pre-allocate @@ -469,340 +634,3 @@ def experimental_predict_loop(model, iterator, verbose=0, steps=None): ] -def _custom_compile_for_predict(model): - """Custom compile for TPU predict mode.""" - model.total_loss = None - model._fit_function = None - model._eval_function = None - model.train_function = None - model.test_function = None - model.predict_function = None - - -def _build_network_on_replica(model, inputs=None, targets=None, mode=None): - """Build an updated model on replicas. - - We create a new Keras model while sharing the variables from the old graph. - Building a new sub-graph is required since the original keras model creates - placeholders for the input and the output that are not accessible till we - call iterator.get_next() inside the step_fn for `fit`/`evaluate`/`predict`. - - The sharing of weights and layers between the old and the new model gaurantee - that we're using Strategy variables and any updates on either model are - reflected correctly in callbacks and loop iterations. - - We need to make sure we share the optimizers between the old and the new model - as well so that optimizer state is not lost if the user is running fit - multiple times. - - Args: - model: Model to be replicated across Replicas - inputs: Input variables to be passed to the model - targets: Target tensor to be passed to model.compile - mode: Which of fit/eval/predict is building the distributed network - - Returns: - A new model with shared layers with the old model. - """ - # Need to do imports here since we run into a circular dependency error. - from tensorflow.python.keras import models # pylint: disable=g-import-not-at-top - from tensorflow.python.keras.engine import sequential # pylint: disable=g-import-not-at-top - - # We rely on the internal methods to avoid having share_weights weights in the - # public API. - if isinstance(model, sequential.Sequential): - updated_model = models._clone_sequential_model(model, input_tensors=inputs, - share_weights=True) - else: - updated_model = models._clone_functional_model(model, input_tensors=inputs, - share_weights=True) - - # Recast all low precision outputs back to float32 since we only casted - # the inputs to bfloat16 and not targets. This is done so that we can preserve - # precision when calculating the loss value. - def _upcast_low_precision_outputs(output): - if output.dtype == dtypes.bfloat16: - return math_ops.cast(output, dtypes.float32) - else: - return output - updated_model.outputs = [_upcast_low_precision_outputs(o) - for o in updated_model.outputs] - - if isinstance(targets, tuple): - targets = nest.flatten(targets) - - if mode == ModeKeys.PREDICT: - _custom_compile_for_predict(updated_model) - else: - updated_model.compile( - model.optimizer, - model.loss, - metrics=metrics_module.clone_metrics(model._compile_metrics), - loss_weights=model.loss_weights, - sample_weight_mode=model.sample_weight_mode, - weighted_metrics=metrics_module.clone_metrics( - model._compile_weighted_metrics), - target_tensors=targets) - return updated_model - - -def _build_distributed_network(model, strategy, inputs=None, targets=None, - mode=None): - """Create a cloned model on each replica.""" - with K.get_graph().as_default(), strategy.scope(): - distributed_model = strategy.extended.call_for_each_replica( - _build_network_on_replica, - args=(model, inputs, targets, mode)) - if mode is ModeKeys.TRAIN: - model._distributed_model_train = distributed_model - elif mode is ModeKeys.TEST: - model._distributed_model_test = distributed_model - elif mode is ModeKeys.PREDICT: - model._distributed_model_predict = distributed_model - else: - model._distributed_model = distributed_model - - -def _clone_and_build_model(model, inputs=None, targets=None, mode=None): - """Clone and build the given keras_model.""" - # We need to set the import here since we run into a circular dependency - # error. - from tensorflow.python.keras import models # pylint: disable=g-import-not-at-top - cloned_model = models.clone_model(model, input_tensors=inputs) - - # Compile and build model. - if isinstance(model.optimizer, optimizers.TFOptimizer): - optimizer = model.optimizer - else: - optimizer_config = model.optimizer.get_config() - optimizer = model.optimizer.__class__.from_config(optimizer_config) - - # Recast all low precision outputs back to float32 since we only casted - # the inputs to bfloat16 and not targets. This is done so that we can preserve - # precision when calculating the loss value. - def _upcast_low_precision_outputs(output): - if output.dtype == dtypes.bfloat16: - return math_ops.cast(output, dtypes.float32) - else: - return output - cloned_model.outputs = [_upcast_low_precision_outputs(o) - for o in cloned_model.outputs] - - if isinstance(targets, tuple): - targets = nest.flatten(targets) - if mode == ModeKeys.PREDICT: - _custom_compile_for_predict(cloned_model) - else: - cloned_model.compile( - optimizer, - model.loss, - metrics=metrics_module.clone_metrics(model._compile_metrics), - loss_weights=model.loss_weights, - sample_weight_mode=model.sample_weight_mode, - weighted_metrics=metrics_module.clone_metrics( - model._compile_weighted_metrics), - target_tensors=targets) - return cloned_model - - -def clone_model_on_replicas(model, strategy, make_callback_model=False, - inputs=None, targets=None, mode=None): - """Create a cloned model on each replica.""" - with K.get_graph().as_default(), strategy.scope(): - distributed_model = strategy.extended.call_for_each_replica( - _clone_and_build_model, args=(model, inputs, targets, mode)) - if mode is ModeKeys.TRAIN: - model._distributed_model_train = distributed_model - elif mode is ModeKeys.TEST: - model._distributed_model_test = distributed_model - elif mode is ModeKeys.PREDICT: - model._distributed_model_predict = distributed_model - else: - model._distributed_model = distributed_model - if make_callback_model: - model._make_callback_model(distributed_model) - - -def _get_input_from_iterator(iterator, model): - """Get elements from the iterator and verify the input shape and type.""" - next_element = iterator.get_next() - - if len(nest.flatten(next_element)) == len(model.inputs): - x = next_element - y = None - sample_weights = None - elif len(nest.flatten(next_element)) == (len(model.inputs) + - len(model.outputs)): - x, y = next_element - sample_weights = None - else: - x, y, sample_weights = next_element - - # Validate that all the elements in x and y are of the same type and shape. - # We can then pass the first element of x and y to `_standardize_weights` - # below and be confident of the output. - distributed_training_utils.validate_distributed_dataset_inputs( - model._distribution_strategy, x, y, sample_weights) - return x, y, sample_weights - - -def _make_execution_function(model, mode): - """Makes function to run one step of distributed model execution.""" - if context.executing_eagerly(): - return _make_eager_execution_function(model, mode) - - strategy = model._distribution_strategy - if not model._distributed_model: - if model._compile_distribution: - clone_model_on_replicas( - model, strategy, make_callback_model=(mode == ModeKeys.TRAIN)) - else: - _build_distributed_network(model, strategy) - - def _per_device_function(model): - f = model._make_execution_function(mode) - return (f.inputs, f.outputs, f.updates_op, f.session_kwargs) - - with strategy.scope(): - # Create train ops on each of the devices when we call - # `_per_device_fit_function`. - (grouped_inputs, grouped_outputs, grouped_updates, - grouped_session_args) = strategy.extended.call_for_each_replica( - _per_device_function, args=(model._distributed_model,)) - - if mode == ModeKeys.TRAIN: - # Initialize the variables in the replicated model. This is necessary for - # multi-worker training because on some workers, initialization is not - # needed. This method does initialization or waiting for initialization - # according to the context object of distribute coordinator. - distributed_training_utils.init_restore_or_wait_for_variables() - - # Unwrap all the per device values returned from `call_for_each_replica`. - # Unwrapping per device values gives you a list of values that can be - # used to construct a new train function that is composed of update ops on - # all the devices over which the model is distributed. - (all_inputs, all_outputs, all_updates, - all_session_args) = distributed_training_utils.unwrap_values( - strategy, - grouped_inputs, - grouped_outputs, - grouped_updates, - grouped_session_args, - with_loss_tensor=(mode != ModeKeys.PREDICT)) - - return K.function( - all_inputs, - all_outputs, - updates=all_updates, - name='distributed_{}_function'.format(mode), - **all_session_args) - - -def _make_eager_execution_function(model, mode): - """Makes function to run one step of distributed model eager execution.""" - strategy = model._distribution_strategy - if not model._distributed_model: - if model._compile_distribution: - clone_model_on_replicas( - model, strategy, make_callback_model=(mode == ModeKeys.TRAIN)) - else: - _build_distributed_network(model, strategy) - - def _per_device_function(model): - f = model._make_execution_function(mode) - return (f.inputs, f.outputs) - - # NOTE(priyag): Try creating a new FuncGraph within DS scope instead of using - # the global one. - with K.get_graph().as_default(), strategy.scope(): - # Create train ops on each of the devices when we call - # `_per_device_fit_function`. - (grouped_inputs, grouped_outputs) = strategy.call_for_each_replica( - _per_device_function, args=(model._distributed_model,)) - - # Unwrap all the per device values returned from `call_for_each_replica`. - # Unwrapping per device values gives you a list of values that can be - # used to construct a new train function that is composed of inptus/outputs - # on all the devices over which the model is distributed. - (all_inputs, all_outputs, _, _) = distributed_training_utils.unwrap_values( - strategy, - grouped_inputs, - grouped_outputs, - with_loss_tensor=(mode != ModeKeys.PREDICT)) - - return K.function( - all_inputs, - all_outputs, - name='eager_distributed_{}_function'.format(mode)) - - -def _prepare_feed_values(model, inputs, targets, sample_weights, mode): - """Prepare feed values to the model execution function. - - Arguments: - model: Model to prepare feed values for. - inputs: List or dict of model inputs. - targets: Optional list of model targets. - sample_weights: Optional list of sample weight arrays. - mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT. - - Returns: - Feed values for the model in the given mode. - """ - strategy = model._distribution_strategy - inputs, targets, sample_weights = _get_input_from_iterator(inputs, model) - inputs = distributed_training_utils.flatten_perdevice_values(strategy, inputs) - targets = distributed_training_utils.flatten_perdevice_values( - strategy, targets) - if mode == ModeKeys.PREDICT: - sample_weights = [] - targets = [] - else: - sample_weights = [ - None for _ in range(len(model.outputs) * strategy.num_replicas_in_sync) - ] - ins = inputs + targets + sample_weights - if mode == ModeKeys.TRAIN and not isinstance(K.symbolic_learning_phase(), - int): - ins += [True] - return ins - - -def _copy_weights_to_distributed_model(original_model, grouped_model): - """Copies weights from original model to distributed models.""" - strategy = original_model._distribution_strategy - if strategy: - # Copy the weights from the original model to each of the replicated - # models. - orig_model_weights = original_model.get_weights() - distributed_model = strategy.unwrap(grouped_model)[0] - distributed_training_utils.set_weights(strategy, distributed_model, - orig_model_weights) - - -def _copy_weights_to_original_model(model, grouped_model, mode): - """Copies weights from first distributed model back to original model.""" - if model._distribution_strategy and mode == ModeKeys.TRAIN: - updated_weights = model._distribution_strategy.unwrap( - grouped_model)[0].get_weights() - model.set_weights(updated_weights) - - -def _per_device_aggregate_batch(batch_outs, model, mode): - """Aggregates the per-device batch-level outputs from a distributed step.""" - if model._distribution_strategy is not None and mode == ModeKeys.PREDICT: - total_batch_outs = [] - for i in range(len(model.outputs)): - num_replicas = model._distribution_strategy.num_replicas_in_sync - nested_outs = batch_outs[i * num_replicas:i * num_replicas + num_replicas] - total_batch_outs.append(np.concatenate(nest.flatten(nested_outs))) - return total_batch_outs - return batch_outs - - -def _reset_metrics(model, distributed_model=None): - if model._distribution_strategy: - distributed_model = ( - distributed_model or - model._distribution_strategy.unwrap(model._distributed_model)[0]) - distributed_model.reset_metrics() diff --git a/tensorflow/python/keras/engine/training_utils.py b/tensorflow/python/keras/engine/training_utils.py index 8325a91c57..b568da4dd8 100644 --- a/tensorflow/python/keras/engine/training_utils.py +++ b/tensorflow/python/keras/engine/training_utils.py @@ -25,6 +25,7 @@ import copy import numpy as np import six +from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import iterator_ops from tensorflow.python.eager import context from tensorflow.python.eager import def_function @@ -861,11 +862,11 @@ def get_loss_function(loss): return losses.get(loss) -def validate_iterator_input(x, y, sample_weight, validation_split=None): +def validate_dataset_input(x, y, sample_weight, validation_split=None): """Validates user input arguments when a dataset iterator is passed. Arguments: - x: Input data. A `tf.data` dataset iterator. + x: Input data. A `tf.data` dataset or iterator. y: Target data. It could be either Numpy array(s) or TensorFlow tensor(s). Expected to be `None` when `x` is a dataset iterator. sample_weight: An optional sample-weight array passed by the user to @@ -899,7 +900,9 @@ def validate_iterator_input(x, y, sample_weight, validation_split=None): 'Received: x=%s, validation_split=%f' % (x, validation_split)) -def check_generator_arguments(y=None, sample_weight=None): +def check_generator_arguments(y=None, + sample_weight=None, + validation_split=None): """Validates arguments passed when using a generator.""" if y is not None: raise ValueError('`y` argument is not supported when data is' @@ -909,6 +912,9 @@ def check_generator_arguments(y=None, sample_weight=None): raise ValueError('`sample_weight` argument is not supported when data is' 'a generator or Sequence instance. Instead pass sample' ' weights as the third element of the generator.') + if validation_split: + raise ValueError('If your data is in the form of a Python generator, ' + 'you cannot use `validation_split`.') def check_steps_argument(input_data, steps, steps_name): @@ -934,15 +940,14 @@ def check_steps_argument(input_data, steps, steps_name): ValueError: if `steps` argument is required for given input data type but not provided. """ - - is_x_iterator = ( - isinstance(input_data, iterator_ops.Iterator) or - isinstance(input_data, iterator_ops.EagerIterator)) - - if (input_data is None or is_x_iterator or has_symbolic_tensors(input_data) or + # TODO(fchollet): allow datasets with steps=None if cardinality is known. + is_x_dataset = isinstance(input_data, (iterator_ops.Iterator, + iterator_ops.EagerIterator, + dataset_ops.DatasetV2)) + if (input_data is None or is_x_dataset or has_symbolic_tensors(input_data) or (isinstance(input_data, list) and not input_data)): if steps is None: - input_type_str = 'iterators' if is_x_iterator else 'data tensors' + input_type_str = 'a Dataset' if is_x_dataset else 'data tensors' raise ValueError('When using {input_type} as input to a model, you should' ' specify the `{steps_name}` argument.'.format( input_type=input_type_str, steps_name=steps_name)) @@ -1063,6 +1068,13 @@ def is_feature_layer(layer): return getattr(layer, '_is_feature_layer', False) +def is_eager_dataset_or_iterator(data): + if context.executing_eagerly(): + if isinstance(data, (dataset_ops.DatasetV2, iterator_ops.EagerIterator)): + return True + return False + + class ModelInputs(object): """Encapsulates model inputs. -- GitLab From beed5ef6fc98f513f368e68ae08357a8db623ef0 Mon Sep 17 00:00:00 2001 From: Pooya Davoodi Date: Thu, 20 Dec 2018 11:38:58 -0800 Subject: [PATCH 0166/1765] TFTRT: Convert between str and unicode in py2 Also check for types before doing conversion. --- tensorflow/contrib/tensorrt/python/trt_convert.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tensorflow/contrib/tensorrt/python/trt_convert.py b/tensorflow/contrib/tensorrt/python/trt_convert.py index 203b2697ba..3d2b6b499d 100644 --- a/tensorflow/contrib/tensorrt/python/trt_convert.py +++ b/tensorflow/contrib/tensorrt/python/trt_convert.py @@ -46,11 +46,13 @@ from tensorflow.python.saved_model import tag_constants from tensorflow.python.training import saver if _six.PY2: - _to_bytes = lambda s: s - _to_string = lambda s: s + _to_bytes = lambda s: s.encode("utf-8", errors="surrogateescape") \ + if isinstance(s, unicode) else s + _to_string = lambda s: s.decode("utf-8") if isinstance(s, str) else s else: - _to_bytes = lambda s: s.encode("utf-8", errors="surrogateescape") - _to_string = lambda s: s.decode("utf-8") + _to_bytes = lambda s: s.encode("utf-8", errors="surrogateescape") \ + if isinstance(s, str) else s + _to_string = lambda s: s.decode("utf-8") if isinstance(s, bytes) else s class TrtPrecisionMode(object): -- GitLab From 58621c1db6ee0ac52aab0ff868f666454d2aa5a3 Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Thu, 20 Dec 2018 11:47:58 -0800 Subject: [PATCH 0167/1765] Calculate input size correctly --- .../core/grappler/optimizers/constant_folding.cc | 11 ++++++----- .../core/grappler/optimizers/constant_folding.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tensorflow/core/grappler/optimizers/constant_folding.cc b/tensorflow/core/grappler/optimizers/constant_folding.cc index bb7ed05e33..5a053d3a89 100644 --- a/tensorflow/core/grappler/optimizers/constant_folding.cc +++ b/tensorflow/core/grappler/optimizers/constant_folding.cc @@ -902,7 +902,8 @@ DataType GetDataTypeFromNodeOrProps(const NodeDef& node, // static Status ConstantFolding::CreateNodeDef(const string& name, const TensorValue& tensor, - NodeDef* node) { + NodeDef* node, + size_t input_size) { node->set_name(name); node->set_op("Const"); @@ -913,7 +914,6 @@ Status ConstantFolding::CreateNodeDef(const string& name, AttrValue attr_tensor; TensorProto* t = attr_tensor.mutable_tensor(); bool optimized = false; - const size_t original_size = tensor->TotalBytes(); size_t encoded_size; // Use the packed representation whenever possible to avoid generating large // graphdefs. Moreover, avoid repeating the last values if they're equal. @@ -980,8 +980,7 @@ Status ConstantFolding::CreateNodeDef(const string& name, encoded_size = t->tensor_content().size(); } node->mutable_attr()->insert({"value", attr_tensor}); - - if (encoded_size > original_size && encoded_size >= 10 * 1024 * 1024) { + if (encoded_size > input_size && encoded_size >= 10 * 1024 * 1024) { return errors::InvalidArgument( strings::StrCat("Can't fold ", name, ", its size would be too large")); } @@ -1011,6 +1010,7 @@ Status ConstantFolding::EvaluateOneFoldable(const NodeDef& node, } }); + size_t input_size = 0; for (const auto& input : node.input()) { const TensorId input_tensor = ParseTensorName(input); if (input_tensor.index() < 0) { @@ -1025,6 +1025,7 @@ Status ConstantFolding::EvaluateOneFoldable(const NodeDef& node, } TF_RETURN_IF_ERROR(CheckAttrExists(*input_node, "value")); const TensorProto& raw_val = input_node->attr().at("value").tensor(); + input_size += raw_val.tensor_content().size(); Tensor* value = new Tensor(raw_val.dtype(), raw_val.tensor_shape()); CHECK(value->FromProto(raw_val)); inputs.emplace_back(value); @@ -1042,7 +1043,7 @@ Status ConstantFolding::EvaluateOneFoldable(const NodeDef& node, node_name = strings::StrCat(node_name, "-", i); } if (output_tensors[i].tensor) { - Status s = CreateNodeDef(node_name, output_tensors[i], &outputs->at(i)); + Status s = CreateNodeDef(node_name, output_tensors[i], &outputs->at(i), input_size); if (!s.ok()) { *result_too_large = true; return s; diff --git a/tensorflow/core/grappler/optimizers/constant_folding.h b/tensorflow/core/grappler/optimizers/constant_folding.h index 0b778882d7..8843ac161f 100644 --- a/tensorflow/core/grappler/optimizers/constant_folding.h +++ b/tensorflow/core/grappler/optimizers/constant_folding.h @@ -36,7 +36,7 @@ const char kConstantFoldingCtrl[] = "ConstantFoldingCtrl"; class ConstantFolding : public GraphOptimizer { public: static Status CreateNodeDef(const string& name, const TensorValue& tensor, - NodeDef* node); + NodeDef* node, size_t input_size = 0); static string AddControlDependency(const string& input_name, GraphDef* graph, NodeMap* node_map); -- GitLab From 929e9a09dfa215d5b4c546a8d05ac3b6956e6d01 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 11:39:02 -0800 Subject: [PATCH 0168/1765] CL 1/N: This is the first CL of many CLs in extending TFlite infrastructure for RISC-V 1. RISC-V MUC target for TFlite. 2. round.h uses ::round() instead of std::round() when compiling for RISCV target 3. Initial update to README for quickly testing the micro_speech_test binary 4. Simple Docker Script for RISC-V target patched from CL 221153645 PiperOrigin-RevId: 226368155 --- tensorflow/lite/experimental/micro/README.md | 63 ++++++ .../micro/riscv32_mcu/debug_log.cc | 190 ++++++++++++++++++ .../micro/testing/Dockerfile.riscv | 24 +++ .../micro/testing/sifive_fe310.resc | 20 ++ .../experimental/micro/tools/make/Makefile | 86 +++++++- .../micro/tools/make/download_dependencies.sh | 4 + .../tools/make/targets/mcu_riscv_makefile.inc | 76 +++++++ tensorflow/lite/kernels/internal/round.h | 3 +- 8 files changed, 462 insertions(+), 4 deletions(-) create mode 100644 tensorflow/lite/experimental/micro/riscv32_mcu/debug_log.cc create mode 100644 tensorflow/lite/experimental/micro/testing/Dockerfile.riscv create mode 100644 tensorflow/lite/experimental/micro/testing/sifive_fe310.resc create mode 100644 tensorflow/lite/experimental/micro/tools/make/targets/mcu_riscv_makefile.inc diff --git a/tensorflow/lite/experimental/micro/README.md b/tensorflow/lite/experimental/micro/README.md index e20efb2253..97bc093b06 100644 --- a/tensorflow/lite/experimental/micro/README.md +++ b/tensorflow/lite/experimental/micro/README.md @@ -126,3 +126,66 @@ debug logs here, along with the magic string `~~~ALL TESTS PASSED~~~`. This is the exact same code as before, just compiled and run on the STM32F103 rather than your desktop. We hope that the simplicity of this testing approach will help make adding support for new platforms as easy as possible. + +## Building for "Hifive1" SiFive FE310 development board +We've targeted the ["HiFive1" Arduino-compatible development board](https://www.sifive.com/boards/hifive1) as a test platform for RISC-V MCU. + +Similar to Blue Pill setup, you will need Docker installed. The binary can be executed on either HiFive1 board or emulated using [Renode project](https://renode.io/) on your desktop machine. + +The following instructions builds and transfers the source files to the Docker +``` +docker build -t riscv_build \ +-f {PATH_TO_TENSORFLOW_ROOT_DIR}/tensorflow/lite/experimental/micro/testing/Dockerfile.riscv \ +{PATH_TO_TENSORFLOW_ROOT_DIR}/tensorflow/lite/experimental/micro/testing/ +``` + +You should see output that looks something like this: + +``` +Sending build context to Docker daemon 28.16kB +Step 1/4 : FROM antmicro/renode:latest + ---> 19c08590e817 +Step 2/4 : LABEL maintainer="Pete Warden " + ---> Using cache + ---> 5a7770d3d3f5 +Step 3/4 : RUN apt-get update + ---> Using cache + ---> b807ab77eeb1 +Step 4/4 : RUN apt-get install -y curl git unzip make g++ + ---> Using cache + ---> 8da1b2aa2438 +Successfully built 8da1b2aa2438 +Successfully tagged riscv_build:latest +``` + +Building micro_speech_test binary + + - Lauch the Docker that we just created using: `docker run -it-v /tmp/copybara_out:/workspace riscv_build:latest bash` + - Enter the source root directory by running `cd /workspace` + - Download the dependencies by running `./tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh`. This may take a few minutes. + - Set the path to RISC-V tools: `export PATH=${PATH}:/workspace/tensorflow/lite/experimental/micro/tools/make/downloads/riscv_toolchain/bin/` + - Build the binary: `make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=riscv32_mcu` + +Lauching Renode to test the binary, currently this set up is not automated. + + - Until https://github.com/renode/renode/pull/30 is in the Docker image, patch the change manully: `sed -E -i 's/"rv32g"/"rv32imac"/g' /opt/renode/platforms/cpus/sifive-fe310.repl` + + + - Execute the binary on Renode: `renode -P 5000 --disable-xwt -e 's @/workspace/tensorflow/lite/experimental/micro/testing/sifive_fe310.resc'` + +You should see the following log with the magic string `~~~ALL TEST PASSED~~~`: + +``` +02:25:22.2059 [DEBUG] uart0: [+17.25s host +80ms virt 80ms virt from start] core freq at 0 Hz +02:25:22.2065 [DEBUG] uart0: [+0.61ms host +0s virt 80ms virt from start] Testing TestInvoke +02:25:22.4243 [DEBUG] uart0: [+0.22s host +0.2s virt 0.28s virt from start] Ran successfully +02:25:22.4244 [DEBUG] uart0: [+42µs host +0s virt 0.28s virt from start] +02:25:22.4245 [DEBUG] uart0: [+0.15ms host +0s virt 0.28s virt from start] 1/1 tests passed +02:25:22.4247 [DEBUG] uart0: [+62µs host +0s virt 0.28s virt from start] ~~~ALL TESTS PASSED~~~ +02:25:22.4251 [DEBUG] uart0: [+8µs host +0s virt 0.28s virt from start] +02:25:22.4252 [DEBUG] uart0: [+0.39ms host +0s virt 0.28s virt from start] +02:25:22.4253 [DEBUG] uart0: [+0.16ms host +0s virt 0.28s virt from start] Progam has exited with code:0x00000000 +``` + + + diff --git a/tensorflow/lite/experimental/micro/riscv32_mcu/debug_log.cc b/tensorflow/lite/experimental/micro/riscv32_mcu/debug_log.cc new file mode 100644 index 0000000000..f0065267bf --- /dev/null +++ b/tensorflow/lite/experimental/micro/riscv32_mcu/debug_log.cc @@ -0,0 +1,190 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +// TODO(b/121324430): Add test for DebugLog fuctions +// TODO(b/121275099): Remove dependency on debug_log once the platform supports +// printf + +#include + +namespace { + +// All input buffers to the number conversion functions must be this long. +static const int kFastToBufferSize = 48; + +// Reverses a zero-terminated string in-place. +char* ReverseStringInPlace(char* start, char* end) { + char* p1 = start; + char* p2 = end - 1; + while (p1 < p2) { + char tmp = *p1; + *p1++ = *p2; + *p2-- = tmp; + } + return start; +} + +// Appends a string to a string, in-place. You need to pass in the maximum +// string length as the second argument. +char* StrCatStr(char* main, int main_max_length, char* to_append) { + char* current = main; + while (*current != 0) { + ++current; + } + char* current_end = main + (main_max_length - 1); + while ((*to_append != 0) && (current < current_end)) { + *current = *to_append; + ++current; + ++to_append; + } + *current = 0; + return current; +} + +char* StrCpy(char* main, int main_max_length, const char* source) { + char* current = main; + char* current_end = main + (main_max_length - 1); + while ((*source != 0) && (current < current_end)) { + *current = *source; + ++current; + ++source; + } + *current = 0; + return current; +} + +// Populates the provided buffer with an ASCII representation of the number. +char* FastUInt32ToBufferLeft(uint32_t i, char* buffer, int base) { + char* start = buffer; + do { + int32_t digit = i % base; + char character; + if (digit < 10) { + character = '0' + digit; + } else { + character = 'a' + (digit - 10); + } + *buffer++ = character; + i /= base; + } while (i > 0); + *buffer = 0; + ReverseStringInPlace(start, buffer); + return buffer; +} + +// Populates the provided buffer with an ASCII representation of the number. +char* FastInt32ToBufferLeft(int32_t i, char* buffer) { + uint32_t u = i; + if (i < 0) { + *buffer++ = '-'; + u = -u; + } + return FastUInt32ToBufferLeft(u, buffer, 10); +} + +// Converts a number to a string and appends it to another. +char* StrCatInt32(char* main, int main_max_length, int32_t number) { + char number_string[kFastToBufferSize]; + FastInt32ToBufferLeft(number, number_string); + return StrCatStr(main, main_max_length, number_string); +} + +// Converts a number to a string and appends it to another. +char* StrCatUInt32(char* main, int main_max_length, uint32_t number, int base) { + char number_string[kFastToBufferSize]; + FastUInt32ToBufferLeft(number, number_string, base); + return StrCatStr(main, main_max_length, number_string); +} + +// Populates the provided buffer with ASCII representation of the float number. +// Avoids the use of any floating point instructions (since these aren't +// supported on many microcontrollers) and as a consequence prints values with +// power-of-two exponents. +char* FastFloatToBufferLeft(float i, char* buffer) { + char* current = buffer; + char* current_end = buffer + (kFastToBufferSize - 1); + // Access the bit fields of the floating point value to avoid requiring any + // float instructions. These constants are derived from IEEE 754. + const uint32_t sign_mask = 0x80000000; + const uint32_t exponent_mask = 0x7f800000; + const int32_t exponent_shift = 23; + const int32_t exponent_bias = 127; + const uint32_t fraction_mask = 0x007fffff; + const uint32_t u = *(uint32_t*)(&i); + const int32_t exponent = + ((u & exponent_mask) >> exponent_shift) - exponent_bias; + const uint32_t fraction = (u & fraction_mask); + // Expect ~0x2B1B9D3 for fraction. + if (u & sign_mask) { + *current = '-'; + current += 1; + } + *current = 0; + // These are special cases for infinities and not-a-numbers. + if (exponent == 128) { + if (fraction == 0) { + current = StrCatStr(current, (current_end - current), "Inf"); + return current; + } else { + current = StrCatStr(current, (current_end - current), "NaN"); + return current; + } + } + // 0x007fffff represents 0.99... for the fraction, so to print the correct + // decimal digits we need to scale our value before passing it to the + // conversion function. This scale should be 10000000/8388608 = 1.1920928955. + // We can approximate this using multipy-adds and right-shifts using the + // values in this array. + const int32_t scale_shifts_size = 13; + const int8_t scale_shifts[13] = {3, 4, 8, 11, 13, 14, 17, + 18, 19, 20, 21, 22, 23}; + uint32_t scaled_fraction = fraction; + for (int i = 0; i < scale_shifts_size; ++i) { + scaled_fraction += (fraction >> scale_shifts[i]); + } + *current = '1'; + current += 1; + *current = '.'; + current += 1; + *current = 0; + current = StrCatUInt32(current, (current_end - current), scaled_fraction, 10); + current = StrCatStr(current, (current_end - current), "*2^"); + current = StrCatInt32(current, (current_end - current), exponent); + return current; +} + +} // namespace + +extern "C" void DebugLog(const char* s) { puts(s); } + +extern "C" void DebugLogInt32(int32_t i) { + char number_string[kFastToBufferSize]; + FastInt32ToBufferLeft(i, number_string); + DebugLog(number_string); +} + +extern "C" void DebugLogUInt32(uint32_t i) { + char number_string[kFastToBufferSize]; + FastUInt32ToBufferLeft(i, number_string, 10); + DebugLog(number_string); +} + +extern "C" void DebugLogHex(uint32_t i) { + char number_string[kFastToBufferSize]; + FastUInt32ToBufferLeft(i, number_string, 16); + DebugLog(number_string); +} + +extern "C" void DebugLogFloat(float i) { + char number_string[kFastToBufferSize]; + FastFloatToBufferLeft(i, number_string); + DebugLog(number_string); +} diff --git a/tensorflow/lite/experimental/micro/testing/Dockerfile.riscv b/tensorflow/lite/experimental/micro/testing/Dockerfile.riscv new file mode 100644 index 0000000000..4f7ac555e6 --- /dev/null +++ b/tensorflow/lite/experimental/micro/testing/Dockerfile.riscv @@ -0,0 +1,24 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +# This docker configuration file lets you emulate a Hifive1 board +# on an x86 desktop or laptop, which can be useful for debugging and +# automated testing. +FROM antmicro/renode:latest + +LABEL maintainer="Pete Warden " + +RUN apt-get update +RUN apt-get install -y curl git unzip make g++ \ No newline at end of file diff --git a/tensorflow/lite/experimental/micro/testing/sifive_fe310.resc b/tensorflow/lite/experimental/micro/testing/sifive_fe310.resc new file mode 100644 index 0000000000..c84ce5091c --- /dev/null +++ b/tensorflow/lite/experimental/micro/testing/sifive_fe310.resc @@ -0,0 +1,20 @@ +:name: SiFive-FE310 +:description: This script runs Zephyr RTOS shell sample on SiFive-FE310 platform. + +$name?="SiFive-FE310" + +using sysbus +mach create $name +machine LoadPlatformDescription @platforms/cpus/sifive-fe310.repl + +$bin?=@/workspace/tensorflow/lite/experimental/micro/tools/make/gen/riscv32_mcu_riscv32_mcu/bin/micro_speech_test + +showAnalyzer uart0 Antmicro.Renode.Analyzers.LoggingUartAnalyzer +logFile @/tmp/renode_riscv_log.txt + +sysbus LoadELF $bin + +sysbus Tag <0x10008000 4> "PRCI_HFROSCCFG" 0xFFFFFFFF +sysbus Tag <0x10008008 4> "PRCI_PLLCFG" 0xFFFFFFFF + +cpu PerformanceInMips 320 diff --git a/tensorflow/lite/experimental/micro/tools/make/Makefile b/tensorflow/lite/experimental/micro/tools/make/Makefile index 20307e2b21..438eae6478 100644 --- a/tensorflow/lite/experimental/micro/tools/make/Makefile +++ b/tensorflow/lite/experimental/micro/tools/make/Makefile @@ -25,6 +25,7 @@ INCLUDES := \ -I. \ -I$(MAKEFILE_DIR)/../../../../../ \ -I$(MAKEFILE_DIR)/../../../../../../ \ +-I$(MAKEFILE_DIR)/../../../../../../../ \ -I$(MAKEFILE_DIR)/downloads/ \ -I$(MAKEFILE_DIR)/downloads/gemmlowp \ -I$(MAKEFILE_DIR)/downloads/flatbuffers/include \ @@ -52,6 +53,29 @@ CC_PREFIX := # runtime that can be linked in to other programs. MICROLITE_LIB_NAME := libtensorflow-microlite.a +# Test binary for the microcontroller speech model. +MICRO_SPEECH_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc + +# Test binary for the microcontroller speech model. +PREPROCESSOR_TEST_SRCS := \ +tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.cc \ +tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc + +PREPROCESSOR_REFERENCE_TEST_SRCS = \ +$(PREPROCESSOR_TEST_SRCS) \ +tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc + +PREPROCESSOR_FIXED_TEST_SRCS += \ +$(PREPROCESSOR_TEST_SRCS) \ +tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc + MICROLITE_TEST_SRCS := \ $(wildcard tensorflow/lite/experimental/micro/*test.cc) \ $(wildcard tensorflow/lite/experimental/micro/kernels/*test.cc) @@ -74,6 +98,9 @@ MICROLITE_CC_SRCS := $(filter-out $(MICROLITE_TEST_SRCS), $(MICROLITE_CC_BASE_SR include $(wildcard $(MAKEFILE_DIR)/targets/*_makefile.inc) ALL_SRCS := \ + $(MICRO_SPEECH_TEST_SRCS) \ + $(PREPROCESSOR_REFERENCE_TEST_SRCS) \ + $(PREPROCESSOR_FIXED_TEST_SRCS) \ $(MICROLITE_CC_SRCS) \ $(MICROLITE_TEST_SRCS) @@ -85,12 +112,22 @@ LIBDIR := $(GENDIR)lib/ MICROLITE_LIB_PATH := $(LIBDIR)$(MICROLITE_LIB_NAME) +MICRO_SPEECH_TEST_BINARY := $(BINDIR)micro_speech_test +PREPROCESSOR_REFERENCE_TEST_BINARY := $(BINDIR)preprocessor_reference_test +PREPROCESSOR_FIXED_TEST_BINARY := $(BINDIR)preprocessor_fixed_test + CXX := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}g++ CC := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}gcc AR := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}ar -# Load the examples. -include $(wildcard tensorflow/lite/experimental/micro/examples/*/Makefile.inc) +MICRO_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ +$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(patsubst %.S,%.o,$(MICRO_SPEECH_TEST_SRCS))))) + +PREPROCESSOR_REFERENCE_TEST_OBJS := $(addprefix $(OBJDIR), \ +$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_REFERENCE_TEST_SRCS)))) + +PREPROCESSOR_FIXED_TEST_OBJS := $(addprefix $(OBJDIR), \ +$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_FIXED_TEST_SRCS)))) MICROLITE_LIB_OBJS := $(addprefix $(OBJDIR), \ $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(MICROLITE_CC_SRCS)))) @@ -108,8 +145,13 @@ $(OBJDIR)%.o: %.c @mkdir -p $(dir $@) $(CC) $(CCFLAGS) $(INCLUDES) -c $< -o $@ + # For normal manually-created TensorFlow ASM source files. +$(OBJDIR)%.o: %.S + @mkdir -p $(dir $@) + $(CC) $(CCFLAGS) $(INCLUDES) -c $< -o $@ + # The target that's compiled if there's no command-line arguments. -all: $(MICROLITE_LIB_PATH) $(ALL_BINARIES) +all: $(MICROLITE_LIB_PATH) $(MICRO_SPEECH_TEST_BINARY) $(PREPROCESSOR_TEST_BINARY) microlite: $(MICROLITE_LIB_PATH) @@ -122,6 +164,42 @@ $(MICROLITE_LIB_PATH): tensorflow/lite/schema/schema_generated.h $(MICROLITE_LIB @mkdir -p $(dir $@) $(AR) $(ARFLAGS) $(MICROLITE_LIB_PATH) $(MICROLITE_LIB_OBJS) +$(MICRO_SPEECH_TEST_BINARY): $(MICRO_SPEECH_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(MICRO_SPEECH_TEST_BINARY) $(MICRO_SPEECH_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + +micro_speech_test: $(MICRO_SPEECH_TEST_BINARY) +micro_speech_test_bin: $(MICRO_SPEECH_TEST_BINARY).bin + +test_micro_speech: $(MICRO_SPEECH_TEST_BINARY) + $(TEST_SCRIPT) $(MICRO_SPEECH_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + +$(PREPROCESSOR_REFERENCE_TEST_BINARY): $(PREPROCESSOR_REFERENCE_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PREPROCESSOR_REFERENCE_TEST_BINARY) $(PREPROCESSOR_REFERENCE_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + +preprocessor_reference_test: $(PREPROCESSOR_REFERENCE_TEST_BINARY) +preprocessor_reference_test_bin: $(PREPROCESSOR_REFERENCE_TEST_BINARY).bin + +test_preprocessor_reference: $(PREPROCESSOR_REFERENCE_TEST_BINARY) + $(TEST_SCRIPT) $(PREPROCESSOR_REFERENCE_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + +$(PREPROCESSOR_FIXED_TEST_BINARY): $(PREPROCESSOR_FIXED_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PREPROCESSOR_FIXED_TEST_BINARY) $(PREPROCESSOR_FIXED_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + +preprocessor_fixed_test: $(PREPROCESSOR_FIXED_TEST_BINARY) +preprocessor_fixed_test_bin: $(PREPROCESSOR_FIXED_TEST_BINARY).bin + +test_preprocessor_fixed: $(PREPROCESSOR_FIXED_TEST_BINARY) + $(TEST_SCRIPT) $(PREPROCESSOR_FIXED_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + $(BINDIR)%_test : $(OBJDIR)%_test.o $(MICROLITE_LIB_PATH) @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $(INCLUDES) \ @@ -131,6 +209,8 @@ $(BINDIR)%_test : $(OBJDIR)%_test.o $(MICROLITE_LIB_PATH) $(BINDIR)%.test_target: $(BINDIR)%_test $(TEST_SCRIPT) $< '~~~ALL TESTS PASSED~~~' +$(info $(MICROLITE_TEST_TARGETS)) + test: test_micro_speech $(MICROLITE_TEST_TARGETS) # Gets rid of all generated files. diff --git a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh index 6749858bdb..1661695225 100755 --- a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh +++ b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh @@ -33,6 +33,8 @@ GEMMLOWP_URL="https://github.com/google/gemmlowp/archive/719139ce755a0f31cbf1c37 FLATBUFFERS_URL="https://github.com/google/flatbuffers/archive/1f5eae5d6a135ff6811724f6c57f911d1f46bb15.tar.gz" CMSIS_URL="https://github.com/ARM-software/CMSIS_5/archive/5.4.0.zip" STM32_BARE_LIB_URL="https://github.com/google/stm32_bare_lib/archive/c07d611fb0af58450c5a3e0ab4d52b47f99bc82d.zip" +SIFIVE_FE310_LIB_URL="https://github.com/sifive/freedom-e-sdk/archive/baeeb8fd497a99b3c141d7494309ec2e64f19bdf.zip" +RISCV_TOOLCHAIN_URL="https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-20181030-x86_64-linux-ubuntu14.tar.gz" download_and_extract() { local usage="Usage: download_and_extract URL DIR" @@ -69,5 +71,7 @@ download_and_extract "${GEMMLOWP_URL}" "${DOWNLOADS_DIR}/gemmlowp" download_and_extract "${FLATBUFFERS_URL}" "${DOWNLOADS_DIR}/flatbuffers" download_and_extract "${CMSIS_URL}" "${DOWNLOADS_DIR}/cmsis" download_and_extract "${STM32_BARE_LIB_URL}" "${DOWNLOADS_DIR}/stm32_bare_lib" +download_and_extract "${SIFIVE_FE310_LIB_URL}" "${DOWNLOADS_DIR}/sifive_fe310_lib" +download_and_extract "${RISCV_TOOLCHAIN_URL}" "${DOWNLOADS_DIR}/riscv_toolchain" echo "download_dependencies.sh completed successfully." >&2 diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/mcu_riscv_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/mcu_riscv_makefile.inc new file mode 100644 index 0000000000..a259f68a3e --- /dev/null +++ b/tensorflow/lite/experimental/micro/tools/make/targets/mcu_riscv_makefile.inc @@ -0,0 +1,76 @@ +# Settings for RISCV 32-bit MCU toolchain. +ifeq ($(TARGET), riscv32_mcu) + TARGET_ARCH := riscv32_mcu + TARGET_TOOLCHAIN_PREFIX := riscv64-unknown-elf- + + PLATFORM_FLAGS = \ + -march=rv32imac \ + -mabi=ilp32 \ + -mcmodel=medany \ + -mexplicit-relocs \ + -fno-builtin-printf \ + -fno-exceptions \ + -DTF_LITE_MCU_DEBUG_LOG \ + -DTF_LITE_USE_GLOBAL_ROUND \ + -fno-unwind-tables \ + -fno-builtin \ + -ffunction-sections \ + -fdata-sections \ + -funsigned-char \ + -Wvla \ + -Wall \ + -Wextra \ + -Wno-unused-parameter \ + -Wno-missing-field-initializers \ + -Wno-write-strings \ + -Wno-sign-compare \ + -fno-delete-null-pointer-checks \ + -fomit-frame-pointer \ + -Os + + CXXFLAGS += $(PLATFORM_FLAGS) \ + -fpermissive \ + -fno-rtti \ + --std=gnu++11 + + CCFLAGS += $(PLATFORM_FLAGS) + + BUILD_TYPE := micro + + INCLUDES += \ + -I$(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/include \ + -I$(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/drivers/ \ + -I$(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/env \ + -I$(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/env/freedom-e300-hifive1 + + MICROLITE_CC_SRCS += \ + $(wildcard tensorflow/lite/experimental/micro/riscv32_mcu/*.cc) + MICRO_SPEECH_TEST_SRCS += \ + $(wildcard $(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/libwrap/sys/*.c) \ + $(wildcard $(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/libwrap/sys/*.cc) \ + $(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/libwrap/misc/write_hex.c \ + $(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/libwrap/stdlib/malloc.c \ + $(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/env/start.S \ + $(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/env/entry.S \ + $(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/env/freedom-e300-hifive1/init.c + LIBWRAP_SYMS := malloc free \ + open lseek read write fstat stat close link unlink \ + execve fork getpid kill wait \ + isatty times sbrk _exit puts + + LDFLAGS += $(foreach s,$(LIBWRAP_SYMS),-Wl,--wrap=$(s)) + LDFLAGS += $(foreach s,$(LIBWRAP_SYMS),-Wl,--wrap=_$(s)) + LDFLAGS += -L. -Wl,--start-group -lc -Wl,--end-group + LDFLAGS += \ + -T$(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/env/freedom-e300-hifive1/flash.lds \ + -nostartfiles \ + -L$(MAKEFILE_DIR)/downloads/sifive_fe310_lib/bsp/env \ + --specs=nano.specs + +# These are microcontroller-specific rules for converting the ELF output +# of the linker into a binary image that can be loaded directly. + OBJCOPY := $(TARGET_TOOLCHAIN_PREFIX)objcopy + $(BINDIR)/%.bin: $(BINDIR)/% + @mkdir -p $(dir $@) + $(OBJCOPY) $< $@ -O binary +endif \ No newline at end of file diff --git a/tensorflow/lite/kernels/internal/round.h b/tensorflow/lite/kernels/internal/round.h index cb494bfd53..135deced44 100644 --- a/tensorflow/lite/kernels/internal/round.h +++ b/tensorflow/lite/kernels/internal/round.h @@ -21,7 +21,8 @@ namespace tflite { // TODO(aselle): See if we can do this only on jdk. Also mikecase, check // if you need this for java host build. -#if defined(__ANDROID__) && !defined(__NDK_MAJOR__) +#if defined(TF_LITE_USE_GLOBAL_ROUND) || \ + (defined(__ANDROID__) && !defined(__NDK_MAJOR__)) template inline float TfLiteRound(const float x) { return ::round(x); -- GitLab From 7009febfed6721cbf664b1ccfd44358392c3d5ca Mon Sep 17 00:00:00 2001 From: Smit Hinsu Date: Thu, 20 Dec 2018 11:53:01 -0800 Subject: [PATCH 0169/1765] Temporarily disable tensorrt/quantization_mnist_test_gpu test to fix nightly build PiperOrigin-RevId: 226370379 --- tensorflow/contrib/tensorrt/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow/contrib/tensorrt/BUILD b/tensorflow/contrib/tensorrt/BUILD index 784acce444..da123e1623 100644 --- a/tensorflow/contrib/tensorrt/BUILD +++ b/tensorflow/contrib/tensorrt/BUILD @@ -549,6 +549,7 @@ cuda_py_test( ], tags = [ "no_cuda_on_cpu_tap", + "no_oss", # TODO(b/121194394): re-enable in OSS after OOM is fixed. "no_pip", "no_tap", # It is not able to download the mnist data. "no_windows", -- GitLab From d969cd8ff9a337503963c8f4a02f56b7d776171e Mon Sep 17 00:00:00 2001 From: Scott Zhu Date: Thu, 20 Dec 2018 11:53:54 -0800 Subject: [PATCH 0170/1765] Fix flakiness in the test case. PiperOrigin-RevId: 226370519 --- tensorflow/python/keras/BUILD | 2 +- tensorflow/python/keras/layers/unified_gru_test.py | 4 ++-- tensorflow/python/keras/layers/unified_lstm_test.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tensorflow/python/keras/BUILD b/tensorflow/python/keras/BUILD index 002e72fa21..9154db8980 100755 --- a/tensorflow/python/keras/BUILD +++ b/tensorflow/python/keras/BUILD @@ -669,7 +669,7 @@ cuda_py_test( "//third_party/py/numpy", "//tensorflow/python:client_testlib", ], - shard_count = 4, + shard_count = 6, ) py_test( diff --git a/tensorflow/python/keras/layers/unified_gru_test.py b/tensorflow/python/keras/layers/unified_gru_test.py index c1a9a360dc..33cd9e9703 100644 --- a/tensorflow/python/keras/layers/unified_gru_test.py +++ b/tensorflow/python/keras/layers/unified_gru_test.py @@ -176,8 +176,8 @@ class UnifiedGRUTest(keras_parameterized.TestCase): cudnn_model.fit(x_train, y_train) y_4 = cudnn_model.predict(x_train) - self.assertAllClose(y_1, y_3) - self.assertAllClose(y_2, y_4) + self.assertAllClose(y_1, y_3, rtol=1e-5, atol=1e-5) + self.assertAllClose(y_2, y_4, rtol=1e-5, atol=1e-5) @parameterized.named_parameters( # test_name, use_bias, bias_initializer, activation diff --git a/tensorflow/python/keras/layers/unified_lstm_test.py b/tensorflow/python/keras/layers/unified_lstm_test.py index afa68d954c..ed50cb9570 100644 --- a/tensorflow/python/keras/layers/unified_lstm_test.py +++ b/tensorflow/python/keras/layers/unified_lstm_test.py @@ -332,8 +332,8 @@ class UnifiedLSTMTest(keras_parameterized.TestCase): cudnn_model.fit(x_train, y_train) y_4 = cudnn_model.predict(x_train) - self.assertAllClose(y_1, y_3) - self.assertAllClose(y_2, y_4) + self.assertAllClose(y_1, y_3, rtol=1e-5, atol=1e-5) + self.assertAllClose(y_2, y_4, rtol=1e-5, atol=1e-5) @parameterized.named_parameters(('v0', 0), ('v1', 1), ('v2', 2)) def test_implementation_mode_LSTM(self, implementation_mode): -- GitLab From 69be3780298639ae9d490e543200110cd3fcab6d Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 12:15:37 -0800 Subject: [PATCH 0171/1765] Teach toco to import "shortened" TF tensors. PiperOrigin-RevId: 226373841 --- tensorflow/lite/toco/import_tensorflow.cc | 277 +++++++++--------- .../lite/toco/import_tensorflow_test.cc | 142 +++++++-- 2 files changed, 263 insertions(+), 156 deletions(-) diff --git a/tensorflow/lite/toco/import_tensorflow.cc b/tensorflow/lite/toco/import_tensorflow.cc index 6a496875f9..e1f7eb82ee 100644 --- a/tensorflow/lite/toco/import_tensorflow.cc +++ b/tensorflow/lite/toco/import_tensorflow.cc @@ -235,6 +235,131 @@ tensorflow::Status ImportShape( return NumElements(input_dims_only_sizes, input_flat_size); } +// Define ways to retrieve data from tensors of different types. +// TODO(b/80208043): simply use tensorflow::Tensor::FromProto() instead. +template +struct TensorTraits; + +template <> +struct TensorTraits { + static int size(const TensorProto& p) { return p.float_val_size(); } + static float get(const TensorProto& p, int i) { return p.float_val(i); } + static string accessor_name() { return "float_val"; } + static string type_name() { return "float"; } + static void CopyFromContent(const TensorProto& p, std::vector* data) { + toco::port::CopyToBuffer(p.tensor_content(), + reinterpret_cast(data->data())); + } +}; + +template <> +struct TensorTraits { + static int size(const TensorProto& p) { return p.int_val_size(); } + static uint8_t get(const TensorProto& p, int i) { return p.int_val(i); } + static string accessor_name() { return "int_val"; } + static string type_name() { return "uint8"; } + static void CopyFromContent(const TensorProto& p, + std::vector* data) { + toco::port::CopyToBuffer(p.tensor_content(), + reinterpret_cast(data->data())); + } +}; + +template <> +struct TensorTraits> { + static int size(const TensorProto& p) { return p.scomplex_val_size() / 2; } + static std::complex get(const TensorProto& p, int i) { + return std::complex(p.scomplex_val(2 * i), + p.scomplex_val(2 * i + 1)); + } + static string accessor_name() { return "scomplex_val"; } + static string type_name() { return "complex64"; } + static void CopyFromContent(const TensorProto& p, + std::vector>* data) { + toco::port::CopyToBuffer(p.tensor_content(), + reinterpret_cast(data->data())); + } +}; + +template <> +struct TensorTraits { + static int size(const TensorProto& p) { return p.int_val_size(); } + static int32 get(const TensorProto& p, int i) { return p.int_val(i); } + static string accessor_name() { return "int_val"; } + static string type_name() { return "int32"; } + static void CopyFromContent(const TensorProto& p, std::vector* data) { + toco::port::CopyToBuffer(p.tensor_content(), + reinterpret_cast(data->data())); + } +}; + +template <> +struct TensorTraits { + static int size(const TensorProto& p) { return p.int64_val_size(); } + static int64 get(const TensorProto& p, int i) { return p.int64_val(i); } + static string accessor_name() { return "int64_val"; } + static string type_name() { return "int64"; } + static void CopyFromContent(const TensorProto& p, std::vector* data) { + toco::port::CopyToBuffer(p.tensor_content(), + reinterpret_cast(data->data())); + } +}; + +template <> +struct TensorTraits { + static int size(const TensorProto& p) { return p.bool_val_size(); } + static bool get(const TensorProto& p, int i) { return p.bool_val(i); } + static string accessor_name() { return "bool_val"; } + static string type_name() { return "bool"; } + static void CopyFromContent(const TensorProto& p, std::vector* data) { + std::vector buf(p.tensor_content().size()); + toco::port::CopyToBuffer(p.tensor_content(), buf.data()); + for (int i = 0; i < p.tensor_content().size(); i++) { + (*data)[i] = static_cast(buf[i]); + } + } +}; + +template +tensorflow::Status ImportTensorData(const TensorProto& input_tensor, + int input_flat_size, + std::vector* output_data) { + CHECK_GE(output_data->size(), input_flat_size); + int num_elements_in_tensor = TensorTraits::size(input_tensor); + if (num_elements_in_tensor == input_flat_size) { + for (int i = 0; i < num_elements_in_tensor; i++) { + (*output_data)[i] = TensorTraits::get(input_tensor, i); + } + } else if (input_tensor.tensor_content().size() == + input_flat_size * sizeof(T)) { + TensorTraits::CopyFromContent(input_tensor, output_data); + } else if (num_elements_in_tensor > 0 && + num_elements_in_tensor < input_flat_size) { + // TODO(b/80208043): use tensorflow::Tensor::FromProto() which is the + // official way to import tensor data. This particular else-if handles a + // grappler optimization where the last few elements in a tensor are + // omitted if they are repeated. + int i = 0; + for (; i < num_elements_in_tensor; ++i) { + (*output_data)[i] = TensorTraits::get(input_tensor, i); + } + auto last = (*output_data)[i - 1]; + for (; i < input_flat_size; ++i) { + (*output_data)[i] = last; + } + } else { + string accessor_name = TensorTraits::accessor_name(); + string type_name = TensorTraits::type_name(); + return tensorflow::errors::InvalidArgument( + absl::StrCat("Neither input_content (", + input_tensor.tensor_content().size() / sizeof(T), ") nor ", + accessor_name, " (", num_elements_in_tensor, + ") have the right dimensions (", input_flat_size, + ") for this ", type_name, " tensor")); + } + return tensorflow::Status::OK(); +} + tensorflow::Status ImportFloatArray(const TensorProto& input_tensor, Array* output_array) { CHECK_EQ(input_tensor.dtype(), DT_FLOAT); @@ -249,28 +374,8 @@ tensorflow::Status ImportFloatArray(const TensorProto& input_tensor, output_array->GetMutableBuffer().data; output_float_data.resize(RequiredBufferSizeForShape(output_array->shape()), 0.f); - CHECK_GE(output_float_data.size(), input_flat_size); - if (input_tensor.float_val_size() == 1) { - for (int i = 0; i < input_flat_size; i++) { - output_float_data[i] = input_tensor.float_val(0); - } - } else if (input_tensor.float_val_size() == input_flat_size) { - for (int i = 0; i < input_tensor.float_val_size(); i++) { - output_float_data[i] = input_tensor.float_val(i); - } - } else if (input_tensor.tensor_content().size() == - input_flat_size * sizeof(float)) { - toco::port::CopyToBuffer(input_tensor.tensor_content(), - reinterpret_cast(output_float_data.data())); - } else { - return tensorflow::errors::InvalidArgument( - absl::StrCat("Neither input_content (", - input_tensor.tensor_content().size() / sizeof(float), - ") nor float_val (", input_tensor.float_val_size(), - ") have the right dimensions (", input_flat_size, - ") for this float tensor")); - } - return tensorflow::Status::OK(); + return ImportTensorData(input_tensor, input_flat_size, + &output_float_data); } tensorflow::Status ImportComplex64Array(const TensorProto& input_tensor, @@ -287,32 +392,8 @@ tensorflow::Status ImportComplex64Array(const TensorProto& input_tensor, output_array->GetMutableBuffer().data; output_complex_data.resize(RequiredBufferSizeForShape(output_array->shape()), std::complex(0.f, 0.f)); - CHECK_GE(output_complex_data.size(), input_flat_size); - if (input_tensor.scomplex_val_size() == 2) { - for (int i = 0; i < input_flat_size; i++) { - output_complex_data[i] = std::complex( - input_tensor.scomplex_val(0), input_tensor.scomplex_val(1)); - } - } else if (input_tensor.scomplex_val_size() == 2 * input_flat_size) { - for (int i = 0; i < input_flat_size; ++i) { - output_complex_data[i] = - std::complex(input_tensor.scomplex_val(2 * i), - input_tensor.scomplex_val(2 * i + 1)); - } - } else if (input_tensor.tensor_content().size() == - input_flat_size * sizeof(std::complex)) { - toco::port::CopyToBuffer( - input_tensor.tensor_content(), - reinterpret_cast(output_complex_data.data())); - } else { - return tensorflow::errors::InvalidArgument(absl::StrCat( - "Neither input_content (", - input_tensor.tensor_content().size() / sizeof(std::complex), - ") nor scomplex_val (", input_tensor.scomplex_val_size(), - ") have the right dimensions (", input_flat_size, - ") for this complex64 tensor")); - } - return tensorflow::Status::OK(); + return ImportTensorData>(input_tensor, input_flat_size, + &output_complex_data); } tensorflow::Status ImportQuint8Array(const TensorProto& input_tensor, @@ -328,28 +409,8 @@ tensorflow::Status ImportQuint8Array(const TensorProto& input_tensor, auto& output_int_data = output_array->GetMutableBuffer().data; output_int_data.resize(RequiredBufferSizeForShape(output_array->shape()), 0); - CHECK_GE(output_int_data.size(), input_flat_size); - if (input_tensor.int_val_size() == 1) { - for (int i = 0; i < input_flat_size; i++) { - output_int_data[i] = input_tensor.int_val(0); - } - } else if (input_tensor.int_val_size() == input_flat_size) { - for (int i = 0; i < input_tensor.int_val_size(); i++) { - output_int_data[i] = input_tensor.int_val(i); - } - } else if (input_tensor.tensor_content().size() == - input_flat_size * sizeof(uint8_t)) { - toco::port::CopyToBuffer(input_tensor.tensor_content(), - reinterpret_cast(output_int_data.data())); - } else { - return tensorflow::errors::InvalidArgument( - absl::StrCat("Neither input_content (", - input_tensor.tensor_content().size() / sizeof(uint8_t), - ") nor int_val (", input_tensor.int_val_size(), - ") have the right dimensions (", input_flat_size, - ") for this uint8 tensor")); - } - return tensorflow::Status::OK(); + return ImportTensorData(input_tensor, input_flat_size, + &output_int_data); } tensorflow::Status ImportInt32Array(const TensorProto& input_tensor, @@ -365,27 +426,8 @@ tensorflow::Status ImportInt32Array(const TensorProto& input_tensor, auto& output_int_data = output_array->GetMutableBuffer().data; output_int_data.resize(RequiredBufferSizeForShape(output_array->shape()), 0); - CHECK_GE(output_int_data.size(), input_flat_size); - if (input_tensor.int_val_size() == 1) { - for (int i = 0; i < input_flat_size; i++) { - output_int_data[i] = input_tensor.int_val(0); - } - } else if (input_tensor.int_val_size() == input_flat_size) { - for (int i = 0; i < input_tensor.int_val_size(); i++) { - output_int_data[i] = input_tensor.int_val(i); - } - } else if (input_tensor.tensor_content().size() == - input_flat_size * sizeof(int32)) { - toco::port::CopyToBuffer(input_tensor.tensor_content(), - reinterpret_cast(output_int_data.data())); - } else { - return tensorflow::errors::InvalidArgument(absl::StrCat( - "Neither input_content (", - input_tensor.tensor_content().size() / sizeof(int32), ") nor int_val (", - input_tensor.int_val_size(), ") have the right dimensions (", - input_flat_size, ") for this int32 tensor")); - } - return tensorflow::Status::OK(); + return ImportTensorData(input_tensor, input_flat_size, + &output_int_data); } tensorflow::Status ImportInt64Array(const TensorProto& input_tensor, @@ -401,28 +443,8 @@ tensorflow::Status ImportInt64Array(const TensorProto& input_tensor, auto& output_int_data = output_array->GetMutableBuffer().data; output_int_data.resize(RequiredBufferSizeForShape(output_array->shape()), 0); - CHECK_GE(output_int_data.size(), input_flat_size); - if (input_tensor.int64_val_size() == 1) { - for (int i = 0; i < input_flat_size; i++) { - output_int_data[i] = input_tensor.int64_val(0); - } - } else if (input_tensor.int64_val_size() == input_flat_size) { - for (int i = 0; i < input_tensor.float_val_size(); i++) { - output_int_data[i] = input_tensor.int64_val(i); - } - } else if (input_tensor.tensor_content().size() == - input_flat_size * sizeof(int64)) { - toco::port::CopyToBuffer(input_tensor.tensor_content(), - reinterpret_cast(output_int_data.data())); - } else { - return tensorflow::errors::InvalidArgument( - absl::StrCat("Neither input_content (", - input_tensor.tensor_content().size() / sizeof(int64), - ") nor int64_val (", input_tensor.int64_val_size(), - ") have the right dimensions (", input_flat_size, - ") for this int64 tensor")); - } - return tensorflow::Status::OK(); + return ImportTensorData(input_tensor, input_flat_size, + &output_int_data); } tensorflow::Status ImportBoolArray(const TensorProto& input_tensor, @@ -439,36 +461,17 @@ tensorflow::Status ImportBoolArray(const TensorProto& input_tensor, output_array->GetMutableBuffer().data; output_bool_data.resize(RequiredBufferSizeForShape(output_array->shape()), false); - CHECK_GE(output_bool_data.size(), input_flat_size); - if (input_tensor.bool_val_size() == 1) { - for (int i = 0; i < input_flat_size; i++) { - output_bool_data[i] = input_tensor.bool_val(0); - } - } else if (input_tensor.bool_val_size() == input_flat_size) { - for (int i = 0; i < input_tensor.bool_val_size(); i++) { - output_bool_data[i] = input_tensor.bool_val(i); - } - } else if (input_tensor.tensor_content().size() == input_flat_size) { - std::vector buf(input_tensor.tensor_content().size()); - toco::port::CopyToBuffer(input_tensor.tensor_content(), buf.data()); - for (int i = 0; i < input_tensor.tensor_content().size(); i++) { - output_bool_data[i] = static_cast(buf[i]); - } - } else { + status = + ImportTensorData(input_tensor, input_flat_size, &output_bool_data); + if (!status.ok() && output_bool_data.size() == 1) { // Some graphs have bool const nodes without actual value... // assuming that 'false' is implied. // So far only encountered that in an array with 1 entry, let's // require that until we encounter a graph where that's not the case. - if (output_bool_data.size() != 1) { - return tensorflow::errors::InvalidArgument(absl::StrCat( - "Neither input_content (", input_tensor.tensor_content().size(), - ") nor bool_val (", input_tensor.bool_val_size(), - ") have the right dimensions (", input_flat_size, - ") for this bool tensor")); - } output_bool_data[0] = false; + return tensorflow::Status::OK(); } - return tensorflow::Status::OK(); + return status; } tensorflow::Status ImportStringArray(const TensorProto& input_tensor, diff --git a/tensorflow/lite/toco/import_tensorflow_test.cc b/tensorflow/lite/toco/import_tensorflow_test.cc index ac020c1049..260704fd2a 100644 --- a/tensorflow/lite/toco/import_tensorflow_test.cc +++ b/tensorflow/lite/toco/import_tensorflow_test.cc @@ -37,6 +37,7 @@ using tensorflow::DT_QUINT8; using tensorflow::DT_STRING; using tensorflow::NodeDef; using tensorflow::Status; +using ::testing::ElementsAre; namespace internal { using ConverterType = tensorflow::Status (*)( @@ -116,35 +117,35 @@ void BuildConstNode(std::initializer_list shape, switch (dtype) { case DT_FLOAT: for (int64_t i = 0; i < num_elements; ++i) { - t.add_float_val(i / 10000.0); + t.add_float_val(i / 10000.0 + 1); } break; case DT_INT32: for (int64_t i = 0; i < num_elements; ++i) { - t.add_int_val(i % std::numeric_limits::max()); + t.add_int_val(i % std::numeric_limits::max() + 1); } break; case DT_QUINT8: for (int64_t i = 0; i < num_elements; ++i) { - t.add_int_val(i % std::numeric_limits::max()); + t.add_int_val(i % std::numeric_limits::max() + 1); } break; case DT_INT64: for (int64_t i = 0; i < num_elements; ++i) { - t.add_int64_val(i); + t.add_int64_val(i + 1); } break; case DT_STRING: break; case DT_BOOL: for (int64_t i = 0; i < num_elements; ++i) { - t.add_bool_val(i % 2); + t.add_bool_val((i % 2) == 0); } break; case DT_COMPLEX64: for (int64_t i = 0; i < num_elements; ++i) { - t.add_scomplex_val(i / 10000.0); - t.add_scomplex_val(-i / 10000.0); + t.add_scomplex_val(i / 10000.0 + 1); + t.add_scomplex_val(-i / 10000.0 - 1); } break; default: @@ -257,20 +258,123 @@ std::vector TestTypes() { INSTANTIATE_TEST_CASE_P(ShapeImportTest, ShapeImportTest, ::testing::ValuesIn(TestTypes())); -TEST(ImportTest, Complex64ConstNode) { +class ContentImportTest : public ::testing::Test { + public: + template + std::vector> ImportAndGetData(const NodeDef& node) { + Model model; + auto status = ImportNode(node, &model); + CHECK(status.ok()) << status.error_message(); + const auto& array = model.GetArray("Node1"); + return array.GetBuffer().data; + } + void RemoveTrailingElements(NodeDef* node, int num) { + tensorflow::TensorProto* p = + node->mutable_attr()->at("value").mutable_tensor(); + for (int i = 0; i < num; ++i) { + if (p->int_val_size() > 0) p->mutable_int_val()->RemoveLast(); + if (p->int64_val_size() > 0) p->mutable_int64_val()->RemoveLast(); + if (p->float_val_size() > 0) p->mutable_float_val()->RemoveLast(); + if (p->bool_val_size() > 0) p->mutable_bool_val()->RemoveLast(); + if (p->scomplex_val_size() > 0) p->mutable_scomplex_val()->RemoveLast(); + if (p->scomplex_val_size() > 0) p->mutable_scomplex_val()->RemoveLast(); + } + } +}; + +TEST_F(ContentImportTest, Int32) { + constexpr ArrayDataType kType = ArrayDataType::kInt32; + + NodeDef node; + BuildConstNode({1, 2, 3}, DT_INT32, 6, &node); + + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 2, 3, 4, 5, 6)); + RemoveTrailingElements(&node, 1); + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 2, 3, 4, 5, 5)); + RemoveTrailingElements(&node, 4); + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 1, 1, 1, 1, 1)); +} + +TEST_F(ContentImportTest, Int64) { + constexpr ArrayDataType kType = ArrayDataType::kInt64; + + NodeDef node; + BuildConstNode({1, 2, 3}, DT_INT64, 6, &node); + + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 2, 3, 4, 5, 6)); + RemoveTrailingElements(&node, 1); + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 2, 3, 4, 5, 5)); + RemoveTrailingElements(&node, 4); + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 1, 1, 1, 1, 1)); +} + +TEST_F(ContentImportTest, Quint8) { + constexpr ArrayDataType kType = ArrayDataType::kUint8; + + NodeDef node; + BuildConstNode({1, 2, 3}, DT_QUINT8, 6, &node); + + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 2, 3, 4, 5, 6)); + RemoveTrailingElements(&node, 1); + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 2, 3, 4, 5, 5)); + RemoveTrailingElements(&node, 4); + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 1, 1, 1, 1, 1)); +} + +TEST_F(ContentImportTest, Bool) { + constexpr ArrayDataType kType = ArrayDataType::kBool; + + NodeDef node; + BuildConstNode({1, 2, 3}, DT_BOOL, 6, &node); + + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 0, 1, 0, 1, 0)); + RemoveTrailingElements(&node, 1); + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 0, 1, 0, 1, 1)); + RemoveTrailingElements(&node, 4); + EXPECT_THAT(ImportAndGetData(node), ElementsAre(1, 1, 1, 1, 1, 1)); +} + +TEST_F(ContentImportTest, Float) { + constexpr ArrayDataType kType = ArrayDataType::kFloat; + + NodeDef node; + BuildConstNode({1, 2, 3}, DT_FLOAT, 6, &node); + + EXPECT_THAT(ImportAndGetData(node), + ElementsAre(1.0000, 1.0001, 1.0002, 1.0003, 1.0004, 1.0005)); + RemoveTrailingElements(&node, 1); + EXPECT_THAT(ImportAndGetData(node), + ElementsAre(1.0000, 1.0001, 1.0002, 1.0003, 1.0004, 1.0004)); + RemoveTrailingElements(&node, 4); + EXPECT_THAT(ImportAndGetData(node), + ElementsAre(1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000)); +} + +TEST_F(ContentImportTest, Complex64) { + constexpr ArrayDataType kType = ArrayDataType::kComplex64; + NodeDef node; BuildConstNode({1, 2, 3}, DT_COMPLEX64, 6, &node); - Model model; - EXPECT_TRUE(ImportNode(node, &model).ok()); - const auto& array = model.GetArray("Node1"); - EXPECT_EQ(ArrayDataType::kComplex64, array.data_type); - EXPECT_EQ(6, array.GetBuffer().Length()); - int64_t i = 0; - for (const auto& datum : array.GetBuffer().data) { - EXPECT_EQ(i / 10000.0f, std::real(datum)); - EXPECT_EQ(-i / 10000.0f, std::imag(datum)); - i++; - } + + using cplx = std::complex; + EXPECT_THAT( + ImportAndGetData(node), + ElementsAre(std::complex(1.0000, -1.0000), cplx(1.0001, -1.0001), + cplx(1.0002, -1.0002), cplx(1.0003, -1.0003), + cplx(1.0004, -1.0004), cplx(1.0005, -1.0005))); + RemoveTrailingElements(&node, 1); + EXPECT_THAT( + ImportAndGetData(node), + ElementsAre(std::complex(1.0000, -1.0000), cplx(1.0001, -1.0001), + cplx(1.0002, -1.0002), cplx(1.0003, -1.0003), + cplx(1.0004, -1.0004), cplx(1.0004, -1.0004))); + + RemoveTrailingElements(&node, 4); + EXPECT_THAT( + ImportAndGetData(node), + ElementsAre(std::complex(1.0000, -1.0000), cplx(1.0000, -1.0000), + cplx(1.0000, -1.0000), cplx(1.0000, -1.0000), + cplx(1.0000, -1.0000), cplx(1.0000, -1.0000))); } std::vector> UnaryTestTypes() { -- GitLab From 2b2001e637a00de37a28faea14f9e2449d173b6d Mon Sep 17 00:00:00 2001 From: Anna R Date: Thu, 20 Dec 2018 12:17:12 -0800 Subject: [PATCH 0172/1765] Internal change. PiperOrigin-RevId: 226374068 --- tensorflow/contrib/tpu/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow/contrib/tpu/BUILD b/tensorflow/contrib/tpu/BUILD index 416abcf068..3cbf265f68 100644 --- a/tensorflow/contrib/tpu/BUILD +++ b/tensorflow/contrib/tpu/BUILD @@ -345,6 +345,7 @@ tf_py_test( ], grpc_enabled = True, shard_count = 4, + tags = ["no_oss"], ) tf_py_test( -- GitLab From f20bc658490e5191c920f04336a030d13a77e8f5 Mon Sep 17 00:00:00 2001 From: Pete Warden Date: Thu, 20 Dec 2018 12:30:39 -0800 Subject: [PATCH 0173/1765] Updated download script and instructions to contain modified files away from regular sources --- tensorflow/lite/experimental/micro/README.md | 13 +++--- .../micro_speech/CMSIS/preprocessor.cc | 43 +++++++++---------- .../micro/tools/make/download_dependencies.sh | 32 ++++++++++++-- .../make/targets/apollo3evb_makefile.inc | 13 +++--- 4 files changed, 62 insertions(+), 39 deletions(-) diff --git a/tensorflow/lite/experimental/micro/README.md b/tensorflow/lite/experimental/micro/README.md index cc2a62cb8a..1df31b3c31 100644 --- a/tensorflow/lite/experimental/micro/README.md +++ b/tensorflow/lite/experimental/micro/README.md @@ -132,16 +132,13 @@ help make adding support for new platforms as easy as possible. Follow these steps to get the pushbutton yes/no example working on Apollo 3: 1. Make sure to run the "Getting Started" section before performing the following steps -2. Download Apollo3-SDK-2018.08.13 and place in tensorflow/lite/experimental/micro/tools/make/downloads -3. Copy and prepare files by running tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb/prep_apollo3_files.sh from the toplevel of git +2. Download Apollo3-SDK-2018.08.13 and place in `tensorflow/lite/experimental/micro/tools/make/downloads`. This is not yet publicly released, but you can contact ashah@ambiqmicro.com to request a copy. +3. Compile the project with the following command: make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=apollo3evb pushbutton_cmsis_speech_test_bin 4. Install [Segger JLink tools](https://www.segger.com/downloads/jlink/) -5. Make sure the [GNU Arm Embedded Toolchain (gcc-arm-none-eabi-7-2018-q2-update)](https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads) is installed to tensorflow/lite/experimental/micro/tools/make/downloads - 1. Confirm directory is in $PATH -6. Compile the project with the following command: make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=apollo3evb pushbutton_cmsis_speech_test_bin -7. Connect the Apollo3 EVB (with mic shield) to the computer and power it on -8. Start the GDB server in a new terminal with the following command: JLinkGDBServer -select USB -device AMA3B1KK-KBR -endian little -if SWD -speed 1000 -noir -noLocalhostOnly +5. Connect the Apollo3 EVB (with mic shield) to the computer and power it on +6. Start the GDB server in a new terminal with the following command: JLinkGDBServer -select USB -device AMA3B1KK-KBR -endian little -if SWD -speed 1000 -noir -noLocalhostOnly 1. The command has run successfully if you see the message "Waiting for GDB connection" -9. Back in the original terminal, run the program via the debugger +7. Back in the original terminal, run the program via the debugger 1. Navigate to tensorflow/lite/experimental/micro/examples/micro_speech/apollo3 2. Start gdb by entering the following command: arm-none-eabi-gdb 3. Run the command script by entering the following command: source pushbutton_cmsis_scores.cmd. This script does the following: diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc index 3e31f96aa3..5c6978b5ed 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/preprocessor.cc @@ -14,22 +14,20 @@ limitations under the License. ==============================================================================*/ extern "C" { - #define ARM_MATH_CM4 - #define IFFT_FLAG_R 0 - #define BIT_REVERSE_FLAG 1 - #define FFT_SIZE 512 - #define FFT_SIZE_DIV2 256 - #include - #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h" - #include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS_ext/arm_cmplx_mag_squared_q10p6.h" +#define ARM_MATH_CM4 +#define IFFT_FLAG_R 0 +#define BIT_REVERSE_FLAG 1 +#define FFT_SIZE 512 +#define FFT_SIZE_DIV2 256 +#include +#include "arm_cmplx_mag_squared_q10p6.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.h" } #include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" void quantize(q15_t* bufA, q15_t* bufB, uint8_t* output); - - q15_t bufA[FFT_SIZE]; q15_t bufB[FFT_SIZE]; arm_rfft_instance_q15 S_arm_fft; @@ -42,7 +40,7 @@ constexpr int kInputSize = 512; constexpr int kAverageWindowSize = 6; constexpr int kOutputSize = ((kInputSize / 2) + (kAverageWindowSize - 1)) / kAverageWindowSize; -} //namespace +} // namespace TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, const int16_t* input, int input_size, int output_size, @@ -60,14 +58,15 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, // 30ms at 16 kHz = 480 samples // We want to pad the rest of the 512-sample buffer with zeros - arm_mult_q15((q15_t *) input, g_hanning, bufB, 480); + arm_mult_q15((q15_t*)input, g_hanning, bufB, 480); int i; - for(i=480; i<512; i++) { + for (i = 480; i < 512; i++) { bufB[i] = 0; } // Should move init code outside of Preprocess() function - arm_math_status = arm_rfft_init_q15(&S_arm_fft, FFT_SIZE, IFFT_FLAG_R, BIT_REVERSE_FLAG); + arm_math_status = + arm_rfft_init_q15(&S_arm_fft, FFT_SIZE, IFFT_FLAG_R, BIT_REVERSE_FLAG); arm_rfft_q15(&S_arm_fft, bufB, bufA); // The rfft function packs data as follows: @@ -86,21 +85,21 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, void quantize(q15_t* bufA, q15_t* bufB, uint8_t* output) { int i; - for (i=0; i<42; i++) { - arm_mean_q15(bufB+6*i, 6, bufA+i); + for (i = 0; i < 42; i++) { + arm_mean_q15(bufB + 6 * i, 6, bufA + i); } - arm_mean_q15(bufB+252, 5, bufA+42); + arm_mean_q15(bufB + 252, 5, bufA + 42); - for (i=0; i<43; i++) { - output[i] = (uint8_t) (bufA[i] >> 5); + for (i = 0; i < 43; i++) { + output[i] = (uint8_t)(bufA[i] >> 5); } } TfLiteStatus Preprocess_1sec(tflite::ErrorReporter* error_reporter, - const int16_t* input, uint8_t* output) { + const int16_t* input, uint8_t* output) { int i; - for(i=0; i<49; i++) { - Preprocess(error_reporter, input+i*320, 480, 43, output+i*43); + for (i = 0; i < 49; i++) { + Preprocess(error_reporter, input + i * 320, 480, 43, output + i * 43); } return kTfLiteOk; } diff --git a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh index ba1fbb7fcf..43e481a590 100755 --- a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh +++ b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh @@ -21,7 +21,6 @@ cd "$SCRIPT_DIR/../../../../../.." DOWNLOADS_DIR=tensorflow/lite/experimental/micro/tools/make/downloads BZL_FILE_PATH=tensorflow/workspace.bzl -AP3_DOWNLOADS_DIR=tensorflow/lite/experimental/micro/examples/micro_speech # Ensure it is being run from repo root if [ ! -f $BZL_FILE_PATH ]; then @@ -36,6 +35,7 @@ CMSIS_URL="https://github.com/ARM-software/CMSIS_5/archive/5.4.0.zip" STM32_BARE_LIB_URL="https://github.com/google/stm32_bare_lib/archive/c07d611fb0af58450c5a3e0ab4d52b47f99bc82d.zip" AP3_URL="https://github.com/AmbiqMicro/TFLiteMicro_Apollo3/archive/dfbcef9a57276c087d95aab7cb234f1d4c9eaaba.zip" CUST_CMSIS_URL="https://github.com/AmbiqMicro/TFLiteMicro_CustCMSIS/archive/8f63966c5692e6a3a83956efd2e4aed77c4c9949.zip" +GCC_EMBEDDED_URL="https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2" download_and_extract() { local usage="Usage: download_and_extract URL DIR" @@ -45,6 +45,8 @@ download_and_extract() { mkdir -p "${dir}" if [[ "${url}" == *gz ]]; then curl -Ls "${url}" | tar -C "${dir}" --strip-components=1 -xz + elif [[ "${url}" == *bz2 ]]; then + curl -Ls "${url}" | tar -C "${dir}" --strip-components=1 -xj elif [[ "${url}" == *zip ]]; then tempdir=$(mktemp -d) tempdir2=$(mktemp -d) @@ -68,11 +70,35 @@ download_and_extract() { find "${dir}" -type f -name '*BUILD' -delete } +patch_apollo3_sdk() { + local ap3_dir="${1}" + if [ ! -f ${ap3_dir}/VERSION.txt ]; then + echo "Could not find ${ap3_dir}, skipping Apollo3 SDK"; + return; + fi + local src_dir=${ap3_dir}/boards/apollo3_evb/examples/hello_world/gcc + local dest_dir=${ap3_dir}/boards/apollo3_evb/examples/hello_world/gcc_patched + rm -rf ${dest_dir} + mkdir ${dest_dir} + cp "${src_dir}/startup_gcc.c" "${dest_dir}/startup_gcc.c" + cp "${src_dir}/hello_world.ld" "${dest_dir}/apollo3evb.ld" + sed -i -e '131s/1024/1024\*20/g' "${dest_dir}/startup_gcc.c" + sed -i -e 's/main/_main/g' "${dest_dir}/startup_gcc.c" + sed -i -e '3s/hello_world.ld/apollo3evb.ld/g' "${dest_dir}/apollo3evb.ld" + sed -i -e '3s/startup_gnu/startup_gcc/g' "${dest_dir}/apollo3evb.ld" + sed -i -e '6s/am_reset_isr/Reset_Handler/g' "${dest_dir}/apollo3evb.ld" + sed -i -e '22s/\*(.text\*)/\*(.text\*)\n\n\t\/\* These are the C++ global constructors. Stick them all here and\n\t \* then walk through the array in main() calling them all.\n\t \*\/\n\t_init_array_start = .;\n\tKEEP (\*(SORT(.init_array\*)))\n\t_init_array_end = .;\n\n\t\/\* XXX Currently not doing anything for global destructors. \*\/\n/g' "${dest_dir}/apollo3evb.ld" + sed -i -e "70s/} > SRAM/} > SRAM\n \/\* Add this to satisfy reference to symbol 'end' from libnosys.a(sbrk.o)\n \* to denote the HEAP start.\n \*\/\n end = .;/g" "${dest_dir}/apollo3evb.ld" + echo "Finished preparing Apollo3 files" +} + download_and_extract "${GEMMLOWP_URL}" "${DOWNLOADS_DIR}/gemmlowp" download_and_extract "${FLATBUFFERS_URL}" "${DOWNLOADS_DIR}/flatbuffers" download_and_extract "${CMSIS_URL}" "${DOWNLOADS_DIR}/cmsis" download_and_extract "${STM32_BARE_LIB_URL}" "${DOWNLOADS_DIR}/stm32_bare_lib" -download_and_extract "${AP3_URL}" "${AP3_DOWNLOADS_DIR}/apollo3_ext" -download_and_extract "${CUST_CMSIS_URL}" "${AP3_DOWNLOADS_DIR}/CMSIS_ext" +download_and_extract "${AP3_URL}" "${DOWNLOADS_DIR}/apollo3_ext" +patch_apollo3_sdk "${DOWNLOADS_DIR}/Apollo3-SDK-2018.08.13" +download_and_extract "${CUST_CMSIS_URL}" "${DOWNLOADS_DIR}/CMSIS_ext" +download_and_extract "${GCC_EMBEDDED_URL}" "${DOWNLOADS_DIR}/gcc_embedded" echo "download_dependencies.sh completed successfully." >&2 diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc index 68ef79ea02..de48d5d46f 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc @@ -1,5 +1,6 @@ # Settings for apollo3 evb platforms. ifeq ($(TARGET), apollo3evb) + export PATH := $(MAKEFILE_DIR)/downloads/gcc_embedded/bin/:$(PATH) TARGET_ARCH := cortex-m4 TARGET_TOOLCHAIN_PREFIX := arm-none-eabi- # Download the Ambiq Apollo3 SDK and set this variable to find the header @@ -7,7 +8,7 @@ ifeq ($(TARGET), apollo3evb) APOLLO3_SDK := $(MAKEFILE_DIR)/downloads/Apollo3-SDK-2018.08.13 # Need a pointer to the GNU ARM toolchain for crtbegin.o for the fp functions # with the softfp interfaces. - GCC_ARM := $(MAKEFILE_DIR)/downloads/gcc-arm-none-eabi-7-2018-q2-update/ + GCC_ARM := $(MAKEFILE_DIR)/downloads/gcc_embedded/ PLATFORM_FLAGS = \ -DPART_apollo3 \ @@ -54,7 +55,7 @@ ifeq ($(TARGET), apollo3evb) -Wl,--start-group -lm -lc -lgcc -Wl,--end-group \ -fno-exceptions \ -nostdlib --specs=nano.specs -t -lstdc++ -lc -lnosys -lm \ - -Wl,-T,$(MAKEFILE_DIR)/targets/apollo3evb/apollo3evb.ld \ + -Wl,-T,$(APOLLO3_SDK)/boards/apollo3_evb/examples/hello_world/gcc_patched/apollo3evb.ld \ -Wl,-Map=$(MAKEFILE_DIR)/gen/$(TARGET).map,--cref BUILD_TYPE := micro MICROLITE_LIBS := \ @@ -65,6 +66,7 @@ ifeq ($(TARGET), apollo3evb) INCLUDES += \ -isystem$(MAKEFILE_DIR)/downloads/cmsis/CMSIS/Core/Include/ \ -isystem$(MAKEFILE_DIR)/downloads/cmsis/CMSIS/DSP/Include/ \ + -I$(MAKEFILE_DIR)/downloads/CMSIS_ext/ \ -I$(GCC_ARM)/arm-none-eabi/ \ -I$(APOLLO3_SDK)/mcu/apollo3/ \ -I$(APOLLO3_SDK)/CMSIS/AmbiqMicro/Include/ \ @@ -81,7 +83,7 @@ ifeq ($(TARGET), apollo3evb) # setting clock speed, default uart setups, etc. and an implementation # of the DebugLog interfaces. MICROLITE_CC_SRCS += \ - $(MAKEFILE_DIR)/targets/apollo3evb/startup_gcc.c \ + $(APOLLO3_SDK)/boards/apollo3_evb/examples/hello_world/gcc_patched/startup_gcc.c \ $(APOLLO3_SDK)/utils/am_util_delay.c \ $(APOLLO3_SDK)/utils/am_util_faultisr.c \ $(APOLLO3_SDK)/utils/am_util_id.c \ @@ -102,7 +104,7 @@ ifeq ($(TARGET), apollo3evb) AP3_EXT_MICRO_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/apollo3_ext AP3_MICRO_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/apollo3 CMSIS_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS - CMSIS_EXT_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS_ext + CMSIS_EXT_DIR := $(MAKEFILE_DIR)/downloads/CMSIS_ext MICRO_SPEECH_TEST_SRCS += \ $(AP3_MICRO_DIR)/_main.c @@ -143,11 +145,10 @@ ifeq ($(TARGET), apollo3evb) $(AP3_MICRO_DIR)/_main.c TEST_SCRIPT := tensorflow/lite/experimental/log_test/test_apollo3evb_binary.sh - # These are tests that don't currently work on the blue pill. + # These are tests that don't currently work on the Apollo3 board. EXCLUDED_TESTS := \ tensorflow/lite/experimental/micro/micro_interpreter_test.cc \ tensorflow/lite/experimental/micro/simple_tensor_allocator_test.cc MICROLITE_TEST_SRCS := $(filter-out $(EXCLUDED_TESTS), $(MICROLITE_TEST_SRCS)) - endif -- GitLab From 110a4fdd663aede91e3081bd44f14b9a13ec7dd7 Mon Sep 17 00:00:00 2001 From: Jiri Simsa Date: Thu, 20 Dec 2018 12:18:39 -0800 Subject: [PATCH 0174/1765] [tf.keras] Adding utility methods for analyzing whether a dataset is not batched / shuffled. PiperOrigin-RevId: 226374309 --- .../python/keras/engine/training_utils.py | 113 ++++++++++++++++++ .../keras/engine/training_utils_test.py | 104 +++++++++++++++- 2 files changed, 216 insertions(+), 1 deletion(-) diff --git a/tensorflow/python/keras/engine/training_utils.py b/tensorflow/python/keras/engine/training_utils.py index b568da4dd8..8ff3af310b 100644 --- a/tensorflow/python/keras/engine/training_utils.py +++ b/tensorflow/python/keras/engine/training_utils.py @@ -27,6 +27,7 @@ import six from tensorflow.python.data.ops import dataset_ops from tensorflow.python.data.ops import iterator_ops +from tensorflow.python.data.ops import readers from tensorflow.python.eager import context from tensorflow.python.eager import def_function from tensorflow.python.framework import constant_op @@ -1075,6 +1076,118 @@ def is_eager_dataset_or_iterator(data): return False +# pylint: disable=protected-access +def assert_not_batched(dataset): + """Asserts that `dataset` is not batched. + + The algorithm used by this method is sound but not complete. In other words, + if the method fails to establish the assertion, it does not mean the dataset + is batched. + + Example usage: + ```python + try: + assert_not_batched(dataset) + # safe to assume `dataset` it not batched here + expect ValueError: + # make no assumptions about `dataset` + ``` + + Args: + dataset: The dataset to analyze. + + Raises: + ValueError: If the method cannot establish the assertion. + """ + if isinstance(dataset, dataset_ops.DatasetV1Adapter): + return assert_not_batched(dataset._dataset) + else: + whitelisted_types = [ + dataset_ops._OptionsDataset, + dataset_ops.ConcatenateDataset, + dataset_ops.CacheDataset, + dataset_ops.FilterDataset, + dataset_ops.MapDataset, + dataset_ops.ParallelMapDataset, + dataset_ops.PrefetchDataset, + dataset_ops.RangeDataset, + dataset_ops.RepeatDataset, + dataset_ops.ShuffleDataset, + dataset_ops.SkipDataset, + dataset_ops.SparseTensorSliceDataset, + dataset_ops.TakeDataset, + dataset_ops.TensorDataset, + dataset_ops.TensorSliceDataset, + dataset_ops.ZipDataset, + readers.FixedLengthRecordDatasetV2, + readers.TextLineDatasetV2, + readers.TFRecordDatasetV2, + ] + for ty in whitelisted_types: + if isinstance(dataset, ty): + for input_dataset in dataset._inputs(): + assert_not_batched(input_dataset) + return + raise ValueError('Could not assert that dataset is not batched.') + + +# pylint: disable=protected-access +def assert_not_shuffled(dataset): + """Asserts that `dataset` is not shuffled. + + The algorithm used by this method is sound but not complete. In other words, + if the method fails to establish the assertion, it does not mean the dataset + is shuffled. + + Example usage: + ```python + try: + assert_not_shuffled(dataset) + # safe to assume `dataset` it not shuffled here + expect ValueError: + # make no assumptions about `dataset` + ``` + + Args: + dataset: The dataset to analyze. + + Raises: + ValueError: If the method cannot establish the assertion. + """ + if isinstance(dataset, dataset_ops.DatasetV1Adapter): + return assert_not_shuffled(dataset._dataset) + else: + whitelisted_types = [ + dataset_ops._OptionsDataset, + dataset_ops.BatchDataset, + dataset_ops.ConcatenateDataset, + dataset_ops.CacheDataset, + dataset_ops.FilterDataset, + dataset_ops.MapDataset, + dataset_ops.PaddedBatchDataset, + dataset_ops.ParallelMapDataset, + dataset_ops.PrefetchDataset, + dataset_ops.RangeDataset, + dataset_ops.RepeatDataset, + dataset_ops.SkipDataset, + dataset_ops.SparseTensorSliceDataset, + dataset_ops.TakeDataset, + dataset_ops.TensorDataset, + dataset_ops.TensorSliceDataset, + dataset_ops.WindowDataset, + dataset_ops.ZipDataset, + readers.FixedLengthRecordDatasetV2, + readers.TextLineDatasetV2, + readers.TFRecordDatasetV2, + ] + for ty in whitelisted_types: + if isinstance(dataset, ty): + for input_dataset in dataset._inputs(): + assert_not_shuffled(input_dataset) + return + raise ValueError('Could not assert that dataset is not shuffled.') + + class ModelInputs(object): """Encapsulates model inputs. diff --git a/tensorflow/python/keras/engine/training_utils_test.py b/tensorflow/python/keras/engine/training_utils_test.py index d8acec32cb..405618796c 100644 --- a/tensorflow/python/keras/engine/training_utils_test.py +++ b/tensorflow/python/keras/engine/training_utils_test.py @@ -20,11 +20,14 @@ from __future__ import print_function import os +from absl.testing import parameterized import numpy as np -from tensorflow.python.client import session as session_lib from tensorflow.python import keras +from tensorflow.python.client import session as session_lib +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.data.ops import readers from tensorflow.python.eager import context from tensorflow.python.eager import def_function from tensorflow.python.framework import dtypes @@ -265,5 +268,104 @@ class ModelSaveTest(keras_parameterized.TestCase): {model.output_names[0]: model.predict_on_batch(inputs)}, _import_and_infer(save_dir, {model.input_names[0]: np.ones((8, 5))})) + +class DatasetUtilsTest(test.TestCase, parameterized.TestCase): + + @parameterized.named_parameters( + # pylint: disable=g-long-lambda + ('Batch', lambda: dataset_ops.Dataset.range(5).batch(2), ValueError), + ('Cache', lambda: dataset_ops.Dataset.range(5).cache()), + ('Concatenate', lambda: dataset_ops.Dataset.range(5).concatenate( + dataset_ops.Dataset.range(5))), + ('FlatMap', lambda: dataset_ops.Dataset.range(5).flat_map( + lambda _: dataset_ops.Dataset.from_tensors(0)), ValueError), + ('Filter', lambda: dataset_ops.Dataset.range(5).filter(lambda _: True)), + ('FixedLengthRecordDatasetV2', + lambda: readers.FixedLengthRecordDatasetV2([], 42)), + ('FromTensors', lambda: dataset_ops.Dataset.from_tensors(0)), + ('FromTensorSlices', + lambda: dataset_ops.Dataset.from_tensor_slices([0, 0, 0])), + ('Interleave', lambda: dataset_ops.Dataset.range(5).interleave( + lambda _: dataset_ops.Dataset.from_tensors(0), cycle_length=1), + ValueError), + ('ParallelInterleave', lambda: dataset_ops.Dataset.range(5).interleave( + lambda _: dataset_ops.Dataset.from_tensors(0), + cycle_length=1, + num_parallel_calls=1), ValueError), + ('Map', lambda: dataset_ops.Dataset.range(5).map(lambda x: x)), + ('Options', + lambda: dataset_ops.Dataset.range(5).with_options(dataset_ops.Options()) + ), + ('PaddedBatch', lambda: dataset_ops.Dataset.range(5).padded_batch(2, []), + ValueError), + ('ParallelMap', lambda: dataset_ops.Dataset.range(5).map( + lambda x: x, num_parallel_calls=1)), + ('Prefetch', lambda: dataset_ops.Dataset.range(5).prefetch(1)), + ('Range', lambda: dataset_ops.Dataset.range(0)), + ('Repeat', lambda: dataset_ops.Dataset.range(0).repeat(0)), + ('Shuffle', lambda: dataset_ops.Dataset.range(5).shuffle(1)), + ('Skip', lambda: dataset_ops.Dataset.range(5).skip(2)), + ('Take', lambda: dataset_ops.Dataset.range(5).take(2)), + ('TextLineDataset', lambda: readers.TextLineDatasetV2([])), + ('TFRecordDataset', lambda: readers.TFRecordDatasetV2([])), + ('Window', lambda: dataset_ops.Dataset.range(5).window(2), ValueError), + ('Zip', lambda: dataset_ops.Dataset.zip(dataset_ops.Dataset.range(5))), + # pylint: enable=g-long-lambda + ) + def test_assert_not_batched(self, dataset_fn, expected_error=None): + if expected_error is None: + training_utils.assert_not_batched(dataset_fn()) + else: + with self.assertRaises(expected_error): + training_utils.assert_not_batched(dataset_fn()) + + @parameterized.named_parameters( + # pylint: disable=g-long-lambda + ('Batch', lambda: dataset_ops.Dataset.range(5).batch(2)), + ('Cache', lambda: dataset_ops.Dataset.range(5).cache()), + ('Concatenate', lambda: dataset_ops.Dataset.range(5).concatenate( + dataset_ops.Dataset.range(5))), + ('FlatMap', lambda: dataset_ops.Dataset.range(5).flat_map( + lambda _: dataset_ops.Dataset.from_tensors(0)), ValueError), + ('Filter', lambda: dataset_ops.Dataset.range(5).filter(lambda _: True)), + ('FixedLengthRecordDatasetV2', + lambda: readers.FixedLengthRecordDatasetV2([], 42)), + ('FromTensors', lambda: dataset_ops.Dataset.from_tensors(0)), + ('FromTensorSlices', + lambda: dataset_ops.Dataset.from_tensor_slices([0, 0, 0])), + ('Interleave', lambda: dataset_ops.Dataset.range(5).interleave( + lambda _: dataset_ops.Dataset.from_tensors(0), cycle_length=1), + ValueError), + ('Map', lambda: dataset_ops.Dataset.range(5).map(lambda x: x)), + ('Options', + lambda: dataset_ops.Dataset.range(5).with_options(dataset_ops.Options()) + ), + ('PaddedBatch', lambda: dataset_ops.Dataset.range(5).padded_batch(2, [])), + ('ParallelInterleave', lambda: dataset_ops.Dataset.range(5).interleave( + lambda _: dataset_ops.Dataset.from_tensors(0), + cycle_length=1, + num_parallel_calls=1), ValueError), + ('ParallelMap', lambda: dataset_ops.Dataset.range(5).map( + lambda x: x, num_parallel_calls=1)), + ('Prefetch', lambda: dataset_ops.Dataset.range(5).prefetch(1)), + ('Range', lambda: dataset_ops.Dataset.range(0)), + ('Repeat', lambda: dataset_ops.Dataset.range(0).repeat(0)), + ('Shuffle', lambda: dataset_ops.Dataset.range(5).shuffle(1), ValueError), + ('Skip', lambda: dataset_ops.Dataset.range(5).skip(2)), + ('Take', lambda: dataset_ops.Dataset.range(5).take(2)), + ('TextLineDataset', lambda: readers.TextLineDatasetV2([])), + ('TFRecordDataset', lambda: readers.TFRecordDatasetV2([])), + ('Window', lambda: dataset_ops.Dataset.range(5).window(2)), + ('Zip', lambda: dataset_ops.Dataset.zip(dataset_ops.Dataset.range(5))), + # pylint: enable=g-long-lambda + ) + def test_assert_not_shuffled(self, dataset_fn, expected_error=None): + if expected_error is None: + training_utils.assert_not_shuffled(dataset_fn()) + else: + with self.assertRaises(expected_error): + training_utils.assert_not_shuffled(dataset_fn()) + + if __name__ == '__main__': test.main() -- GitLab From 0b5f632b4807030cbe7bab9daa1103df3429cafb Mon Sep 17 00:00:00 2001 From: Suharsh Sivakumar Date: Thu, 20 Dec 2018 12:28:19 -0800 Subject: [PATCH 0175/1765] Fix code to include 0 in the floating point range. PiperOrigin-RevId: 226375694 --- .../lite/tools/optimize/quantization_utils.cc | 8 +++++--- .../lite/tools/optimize/quantization_utils.h | 2 +- .../lite/tools/optimize/quantization_utils_test.cc | 14 ++++++++------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/tensorflow/lite/tools/optimize/quantization_utils.cc b/tensorflow/lite/tools/optimize/quantization_utils.cc index 27292f74a6..ebac65ed10 100644 --- a/tensorflow/lite/tools/optimize/quantization_utils.cc +++ b/tensorflow/lite/tools/optimize/quantization_utils.cc @@ -39,11 +39,13 @@ TfLiteStatus NumElements(const TensorT& tensor, uint64_t* num_elements) { // we may deviate from that implementation as we please since we do not fine // tune the weights with quantized training. void GetAsymmetricQuantizationParams( - const float min, const float max, const int quant_min, const int quant_max, + float min, float max, const int quant_min, const int quant_max, QuantizationParametersT* quantization_params) { + const float quant_min_float = static_cast(quant_min); + const float quant_max_float = static_cast(quant_max); // Adjust the boundaries to guarantee 0 is included. - const float quant_min_float = std::min(static_cast(quant_min), 0.0f); - const float quant_max_float = std::max(static_cast(quant_max), 0.0f); + min = std::min(static_cast(min), 0.0f); + max = std::max(static_cast(max), 0.0f); const float scale = (max - min) / (quant_max_float - quant_min_float); const float zero_point_from_min = quant_min_float - min / scale; int64_t zero_point; diff --git a/tensorflow/lite/tools/optimize/quantization_utils.h b/tensorflow/lite/tools/optimize/quantization_utils.h index e832812251..8e05c69a40 100644 --- a/tensorflow/lite/tools/optimize/quantization_utils.h +++ b/tensorflow/lite/tools/optimize/quantization_utils.h @@ -32,7 +32,7 @@ TfLiteStatus NumElements(const TensorT& tensor, uint64_t* num_elements); // Nudges min and max so that floating point 0 falls exactly on a quantized // value, returning the nudges scale and zero_point. void GetAsymmetricQuantizationParams( - const float min, const float max, const int quant_min, const int quant_max, + float min, float max, const int quant_min, const int quant_max, QuantizationParametersT* quantization_params); } // namespace utils diff --git a/tensorflow/lite/tools/optimize/quantization_utils_test.cc b/tensorflow/lite/tools/optimize/quantization_utils_test.cc index 06f51ebaf1..482ec70470 100644 --- a/tensorflow/lite/tools/optimize/quantization_utils_test.cc +++ b/tensorflow/lite/tools/optimize/quantization_utils_test.cc @@ -59,8 +59,9 @@ TEST(QuantizationUtilsTest, GetAsymmetricQuantizationParamsUnitRange) { } TEST(QuantizationUtilsTest, AsymmetricQuantizationParamsWithAllPositiveRange) { + // The min should get nudged to include 0, so the effective range is [0, 6]. const float float_min = 1.0; - const float float_max = 5.0; + const float float_max = 6.0; const int quant_min = -128; const int quant_max = 127; QuantizationParametersT params; @@ -71,16 +72,17 @@ TEST(QuantizationUtilsTest, AsymmetricQuantizationParamsWithAllPositiveRange) { ASSERT_EQ(params.scale.size(), 1); ASSERT_EQ(params.zero_point.size(), 1); EXPECT_EQ(params.max[0], float_max); - EXPECT_EQ(params.min[0], float_min); + EXPECT_EQ(params.min[0], 0.0); int64_t zero_point = params.zero_point[0]; float scale = params.scale[0]; const float eps = 1e-7f; EXPECT_EQ(zero_point, -128); - EXPECT_NEAR(scale, 4 / 255.0f, eps); + EXPECT_NEAR(scale, 6 / 255.0f, eps); } TEST(QuantizationUtilsTest, AsymmetricQuantizationParamsWithAllNegativeRange) { - const float float_min = -5.0; + // The min should get nudged to include 0, so the effective range is [-6, 0]. + const float float_min = -6.0; const float float_max = -1.0; const int quant_min = -128; const int quant_max = 127; @@ -91,13 +93,13 @@ TEST(QuantizationUtilsTest, AsymmetricQuantizationParamsWithAllNegativeRange) { ASSERT_EQ(params.min.size(), 1); ASSERT_EQ(params.scale.size(), 1); ASSERT_EQ(params.zero_point.size(), 1); - EXPECT_EQ(params.max[0], float_max); + EXPECT_EQ(params.max[0], 0.0); EXPECT_EQ(params.min[0], float_min); int64_t zero_point = params.zero_point[0]; float scale = params.scale[0]; const float eps = 1e-7f; EXPECT_EQ(zero_point, 127); - EXPECT_NEAR(scale, 4 / 255.0f, eps); + EXPECT_NEAR(scale, 6 / 255.0f, eps); } TEST(QuantizationUtilsTest, AsymmetricQuantizationParamsWithZeroInRange) { -- GitLab From 4ccb03f468d98d482d6d28108215bb200326b21e Mon Sep 17 00:00:00 2001 From: Jiri Simsa Date: Thu, 20 Dec 2018 12:43:15 -0800 Subject: [PATCH 0176/1765] Adding `Name` to the `RandomAccessFile` and `WritableFile` API. PiperOrigin-RevId: 226377832 --- tensorflow/core/lib/io/table_test.cc | 7 +++++++ tensorflow/core/lib/io/zlib_outputbuffer.cc | 4 ++++ tensorflow/core/lib/io/zlib_outputbuffer.h | 4 ++++ .../core/platform/cloud/gcs_file_system.cc | 9 +++++++++ .../platform/cloud/gcs_file_system_test.cc | 4 ++++ .../platform/cloud/retrying_file_system.h | 7 +++++++ .../cloud/retrying_file_system_test.cc | 19 +++++++++++++++++-- tensorflow/core/platform/file_system.h | 16 ++++++++++++++++ .../platform/hadoop/hadoop_file_system.cc | 10 ++++++++++ .../hadoop/hadoop_file_system_test.cc | 8 +++++++- .../core/platform/posix/posix_file_system.cc | 10 ++++++++++ tensorflow/core/platform/s3/s3_file_system.cc | 8 ++++++++ .../platform/windows/windows_file_system.cc | 10 ++++++++++ tensorflow/core/util/memmapped_file_system.cc | 5 +++++ 14 files changed, 118 insertions(+), 3 deletions(-) diff --git a/tensorflow/core/lib/io/table_test.cc b/tensorflow/core/lib/io/table_test.cc index addba92005..d57135be72 100644 --- a/tensorflow/core/lib/io/table_test.cc +++ b/tensorflow/core/lib/io/table_test.cc @@ -96,6 +96,9 @@ class StringSink : public WritableFile { Status Close() override { return Status::OK(); } Status Flush() override { return Status::OK(); } + Status Name(StringPiece* result) const override { + return errors::Unimplemented("StringSink does not support Name()"); + } Status Sync() override { return Status::OK(); } Status Tell(int64* pos) override { *pos = contents_.size(); @@ -120,6 +123,10 @@ class StringSource : public RandomAccessFile { uint64 Size() const { return contents_.size(); } + Status Name(StringPiece* result) const override { + return errors::Unimplemented("StringSource does not support Name()"); + } + Status Read(uint64 offset, size_t n, StringPiece* result, char* scratch) const override { if (offset > contents_.size()) { diff --git a/tensorflow/core/lib/io/zlib_outputbuffer.cc b/tensorflow/core/lib/io/zlib_outputbuffer.cc index 726d2b1364..aa7bdab03a 100644 --- a/tensorflow/core/lib/io/zlib_outputbuffer.cc +++ b/tensorflow/core/lib/io/zlib_outputbuffer.cc @@ -197,6 +197,10 @@ Status ZlibOutputBuffer::Flush() { return Status::OK(); } +Status ZlibOutputBuffer::Name(StringPiece* result) const { + return file_->Name(result); +} + Status ZlibOutputBuffer::Sync() { TF_RETURN_IF_ERROR(Flush()); return file_->Sync(); diff --git a/tensorflow/core/lib/io/zlib_outputbuffer.h b/tensorflow/core/lib/io/zlib_outputbuffer.h index f4c4d9cbc3..e3d2aec37e 100644 --- a/tensorflow/core/lib/io/zlib_outputbuffer.h +++ b/tensorflow/core/lib/io/zlib_outputbuffer.h @@ -21,6 +21,7 @@ limitations under the License. #include #include "tensorflow/core/lib/core/status.h" +#include "tensorflow/core/lib/core/stringpiece.h" #include "tensorflow/core/lib/io/zlib_compression_options.h" #include "tensorflow/core/platform/env.h" #include "tensorflow/core/platform/file_system.h" @@ -77,6 +78,9 @@ class ZlibOutputBuffer : public WritableFile { // will fail. Status Close() override; + // Returns the name of the underlying file. + Status Name(StringPiece* result) const override; + // Deflates any cached input, writes all output to file and syncs it. Status Sync() override; diff --git a/tensorflow/core/platform/cloud/gcs_file_system.cc b/tensorflow/core/platform/cloud/gcs_file_system.cc index fe2e0f5b1f..d1e5779f02 100644 --- a/tensorflow/core/platform/cloud/gcs_file_system.cc +++ b/tensorflow/core/platform/cloud/gcs_file_system.cc @@ -310,6 +310,11 @@ class GcsRandomAccessFile : public RandomAccessFile { GcsRandomAccessFile(const string& filename, ReadFn read_fn) : filename_(filename), read_fn_(std::move(read_fn)) {} + Status Name(StringPiece* result) const override { + *result = filename_; + return Status::OK(); + } + /// The implementation of reads with an LRU block cache. Thread safe. Status Read(uint64 offset, size_t n, StringPiece* result, char* scratch) const override { @@ -394,6 +399,10 @@ class GcsWritableFile : public WritableFile { Status Flush() override { return Sync(); } + Status Name(StringPiece* result) const override { + return errors::Unimplemented("GCSWritableFile does not support Name()"); + } + Status Sync() override { TF_RETURN_IF_ERROR(CheckWritable()); if (!sync_needed_) { diff --git a/tensorflow/core/platform/cloud/gcs_file_system_test.cc b/tensorflow/core/platform/cloud/gcs_file_system_test.cc index bf057d876f..dc9eb7796f 100644 --- a/tensorflow/core/platform/cloud/gcs_file_system_test.cc +++ b/tensorflow/core/platform/cloud/gcs_file_system_test.cc @@ -79,6 +79,10 @@ TEST(GcsFileSystemTest, NewRandomAccessFile_NoBlockCache) { std::unique_ptr file; TF_EXPECT_OK(fs.NewRandomAccessFile("gs://bucket/random_access.txt", &file)); + StringPiece filename; + TF_EXPECT_OK(file->Name(&filename)); + EXPECT_EQ(filename, "gs://bucket/random_access.txt"); + char scratch[6]; StringPiece result; diff --git a/tensorflow/core/platform/cloud/retrying_file_system.h b/tensorflow/core/platform/cloud/retrying_file_system.h index f72a666690..9659edd890 100644 --- a/tensorflow/core/platform/cloud/retrying_file_system.h +++ b/tensorflow/core/platform/cloud/retrying_file_system.h @@ -150,6 +150,10 @@ class RetryingRandomAccessFile : public RandomAccessFile { const RetryConfig& retry_config) : base_file_(std::move(base_file)), retry_config_(retry_config) {} + Status Name(StringPiece* result) const override { + return base_file_->Name(result); + } + Status Read(uint64 offset, size_t n, StringPiece* result, char* scratch) const override { return RetryingUtils::CallWithRetries( @@ -187,6 +191,9 @@ class RetryingWritableFile : public WritableFile { return RetryingUtils::CallWithRetries( [this]() { return base_file_->Flush(); }, retry_config_); } + Status Name(StringPiece* result) const override { + return base_file_->Name(result); + } Status Sync() override { return RetryingUtils::CallWithRetries( [this]() { return base_file_->Sync(); }, retry_config_); diff --git a/tensorflow/core/platform/cloud/retrying_file_system_test.cc b/tensorflow/core/platform/cloud/retrying_file_system_test.cc index 2bc9d830aa..8a0b865499 100644 --- a/tensorflow/core/platform/cloud/retrying_file_system_test.cc +++ b/tensorflow/core/platform/cloud/retrying_file_system_test.cc @@ -60,6 +60,9 @@ class MockCallSequence { class MockRandomAccessFile : public RandomAccessFile { public: explicit MockRandomAccessFile(const ExpectedCalls& calls) : calls_(calls) {} + Status Name(StringPiece* result) const override { + return calls_.ConsumeNextCall("Name"); + } Status Read(uint64 offset, size_t n, StringPiece* result, char* scratch) const override { return calls_.ConsumeNextCall("Read"); @@ -77,6 +80,9 @@ class MockWritableFile : public WritableFile { } Status Close() override { return calls_.ConsumeNextCall("Close"); } Status Flush() override { return calls_.ConsumeNextCall("Flush"); } + Status Name(StringPiece* result) const override { + return calls_.ConsumeNextCall("Name"); + } Status Sync() override { return calls_.ConsumeNextCall("Sync"); } Status Tell(int64* position) override { return calls_.ConsumeNextCall("Tell"); @@ -177,7 +183,8 @@ class MockFileSystem : public FileSystem { TEST(RetryingFileSystemTest, NewRandomAccessFile_ImmediateSuccess) { // Configure the mock base random access file. - ExpectedCalls expected_file_calls({std::make_tuple("Read", Status::OK())}); + ExpectedCalls expected_file_calls({std::make_tuple("Name", Status::OK()), + std::make_tuple("Read", Status::OK())}); std::unique_ptr base_file( new MockRandomAccessFile(expected_file_calls)); @@ -196,6 +203,9 @@ TEST(RetryingFileSystemTest, NewRandomAccessFile_ImmediateSuccess) { // Use it and check the results. StringPiece result; + TF_EXPECT_OK(random_access_file->Name(&result)); + EXPECT_EQ(result, ""); + char scratch[10]; TF_EXPECT_OK(random_access_file->Read(0, 10, &result, scratch)); } @@ -287,7 +297,8 @@ TEST(RetryingFileSystemTest, NewRandomAccessFile_NoRetriesForSomeErrors) { TEST(RetryingFileSystemTest, NewWritableFile_ImmediateSuccess) { // Configure the mock base random access file. - ExpectedCalls expected_file_calls({std::make_tuple("Sync", Status::OK()), + ExpectedCalls expected_file_calls({std::make_tuple("Name", Status::OK()), + std::make_tuple("Sync", Status::OK()), std::make_tuple("Close", Status::OK())}); std::unique_ptr base_file( new MockWritableFile(expected_file_calls)); @@ -305,6 +316,10 @@ TEST(RetryingFileSystemTest, NewWritableFile_ImmediateSuccess) { std::unique_ptr writable_file; TF_EXPECT_OK(fs.NewWritableFile("filename.txt", &writable_file)); + StringPiece result; + TF_EXPECT_OK(writable_file->Name(&result)); + EXPECT_EQ(result, ""); + // Use it and check the results. TF_EXPECT_OK(writable_file->Sync()); } diff --git a/tensorflow/core/platform/file_system.h b/tensorflow/core/platform/file_system.h index 48ffa66358..a3a2b6c7f3 100644 --- a/tensorflow/core/platform/file_system.h +++ b/tensorflow/core/platform/file_system.h @@ -234,6 +234,14 @@ class RandomAccessFile { RandomAccessFile() {} virtual ~RandomAccessFile(); + /// \brief Returns the name of the file. + /// + /// This is an optional operation that may not be implemented by every + /// filesystem. + virtual Status Name(StringPiece* result) const { + return errors::Unimplemented("This filesystem does not support Name()"); + } + /// \brief Reads up to `n` bytes from the file starting at `offset`. /// /// `scratch[0..n-1]` may be written by this routine. Sets `*result` @@ -297,6 +305,14 @@ class WritableFile { /// persisted, depending on the implementation. virtual Status Flush() = 0; + // \brief Returns the name of the file. + /// + /// This is an optional operation that may not be implemented by every + /// filesystem. + virtual Status Name(StringPiece* result) const { + return errors::Unimplemented("This filesystem does not support Name()"); + } + /// \brief Syncs contents of file to filesystem. /// /// This waits for confirmation from the filesystem that the contents diff --git a/tensorflow/core/platform/hadoop/hadoop_file_system.cc b/tensorflow/core/platform/hadoop/hadoop_file_system.cc index ad4ed5cdd8..2cf1036cc8 100644 --- a/tensorflow/core/platform/hadoop/hadoop_file_system.cc +++ b/tensorflow/core/platform/hadoop/hadoop_file_system.cc @@ -205,6 +205,11 @@ class HDFSRandomAccessFile : public RandomAccessFile { } } + Status Name(StringPiece* result) const override { + *result = filename_; + return Status::OK(); + } + Status Read(uint64 offset, size_t n, StringPiece* result, char* scratch) const override { Status s; @@ -310,6 +315,11 @@ class HDFSWritableFile : public WritableFile { return Status::OK(); } + Status Name(StringPiece* result) const override { + *result = filename_; + return Status::OK(); + } + Status Sync() override { if (hdfs_->hdfsHSync(fs_, file_) != 0) { return IOError(filename_, errno); diff --git a/tensorflow/core/platform/hadoop/hadoop_file_system_test.cc b/tensorflow/core/platform/hadoop/hadoop_file_system_test.cc index d29667944a..b9e8f28739 100644 --- a/tensorflow/core/platform/hadoop/hadoop_file_system_test.cc +++ b/tensorflow/core/platform/hadoop/hadoop_file_system_test.cc @@ -75,9 +75,12 @@ TEST_F(HadoopFileSystemTest, RandomAccessFile) { std::unique_ptr reader; TF_EXPECT_OK(hdfs.NewRandomAccessFile(fname, &reader)); + StringPiece result; + TF_EXPECT_OK(reader->Name(&result)); + EXPECT_EQ(result, fname); + string got; got.resize(content.size()); - StringPiece result; TF_EXPECT_OK( reader->Read(0, content.size(), &result, gtl::string_as_array(&got))); EXPECT_EQ(content.size(), result.size()); @@ -94,6 +97,9 @@ TEST_F(HadoopFileSystemTest, WritableFile) { std::unique_ptr writer; const string fname = TmpDir("WritableFile"); TF_EXPECT_OK(hdfs.NewWritableFile(fname, &writer)); + StringPiece result; + TF_EXPECT_OK(writer->Name(&result)); + EXPECT_EQ(result, fname); TF_EXPECT_OK(writer->Append("content1,")); int64 pos; TF_EXPECT_OK(writer->Tell(&pos)); diff --git a/tensorflow/core/platform/posix/posix_file_system.cc b/tensorflow/core/platform/posix/posix_file_system.cc index 2f59940ef3..003ab170fe 100644 --- a/tensorflow/core/platform/posix/posix_file_system.cc +++ b/tensorflow/core/platform/posix/posix_file_system.cc @@ -52,6 +52,11 @@ class PosixRandomAccessFile : public RandomAccessFile { : filename_(fname), fd_(fd) {} ~PosixRandomAccessFile() override { close(fd_); } + Status Name(StringPiece* result) const override { + *result = filename_; + return Status::OK(); + } + Status Read(uint64 offset, size_t n, StringPiece* result, char* scratch) const override { Status s; @@ -115,6 +120,11 @@ class PosixWritableFile : public WritableFile { return Status::OK(); } + Status Name(StringPiece* result) const override { + *result = filename_; + return Status::OK(); + } + Status Sync() override { Status s; if (fflush(file_) != 0) { diff --git a/tensorflow/core/platform/s3/s3_file_system.cc b/tensorflow/core/platform/s3/s3_file_system.cc index e0b8e37745..0ff65fb6b3 100644 --- a/tensorflow/core/platform/s3/s3_file_system.cc +++ b/tensorflow/core/platform/s3/s3_file_system.cc @@ -170,6 +170,10 @@ class S3RandomAccessFile : public RandomAccessFile { std::shared_ptr s3_client) : bucket_(bucket), object_(object), s3_client_(s3_client) {} + Status Name(StringPiece* result) const override { + return errors::Unimplemented("S3RandomAccessFile does not support Name()"); + } + Status Read(uint64 offset, size_t n, StringPiece* result, char* scratch) const override { Aws::S3::Model::GetObjectRequest getObjectRequest; @@ -235,6 +239,10 @@ class S3WritableFile : public WritableFile { Status Flush() override { return Sync(); } + Status Name(StringPiece* result) const override { + return errors::Unimplemented("S3WritableFile does not support Name()"); + } + Status Sync() override { if (!outfile_) { return errors::FailedPrecondition( diff --git a/tensorflow/core/platform/windows/windows_file_system.cc b/tensorflow/core/platform/windows/windows_file_system.cc index 993b9906b1..8580c3a3ef 100644 --- a/tensorflow/core/platform/windows/windows_file_system.cc +++ b/tensorflow/core/platform/windows/windows_file_system.cc @@ -112,6 +112,11 @@ class WindowsRandomAccessFile : public RandomAccessFile { } } + Status Name(StringPiece* result) const override { + *result = filename_; + return Status::OK(); + } + Status Read(uint64 offset, size_t n, StringPiece* result, char* scratch) const override { Status s; @@ -189,6 +194,11 @@ class WindowsWritableFile : public WritableFile { return Status::OK(); } + Status Name(StringPiece* result) const override { + *result = filename_; + return Status::OK(); + } + Status Sync() override { return Flush(); } }; diff --git a/tensorflow/core/util/memmapped_file_system.cc b/tensorflow/core/util/memmapped_file_system.cc index d3439cbc93..b1773a2517 100644 --- a/tensorflow/core/util/memmapped_file_system.cc +++ b/tensorflow/core/util/memmapped_file_system.cc @@ -56,6 +56,11 @@ class RandomAccessFileFromMemmapped : public RandomAccessFile { ~RandomAccessFileFromMemmapped() override = default; + Status Name(StringPiece* result) const override { + return errors::Unimplemented( + "RandomAccessFileFromMemmapped does not support Name()"); + } + Status Read(uint64 offset, size_t to_read, StringPiece* result, char* scratch) const override { if (offset >= length_) { -- GitLab From 123fd34a1158539fd28f713727a960803f3a6e5c Mon Sep 17 00:00:00 2001 From: Michael Case Date: Thu, 20 Dec 2018 13:03:04 -0800 Subject: [PATCH 0177/1765] Add new layers_util target to break some dependencies on Keras. - Many tests still depend on Keras so adding back some of the Keras dependencies to :framework_test_lib. - Adding new keras_lib target that will consist of much of the code being split from core TF. In future CL, will remove keras_lib dep from tensorflow/python:no_contrib. PiperOrigin-RevId: 226380802 --- tensorflow/python/BUILD | 42 +++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/tensorflow/python/BUILD b/tensorflow/python/BUILD index 5f6d4b6bdc..da44a41536 100644 --- a/tensorflow/python/BUILD +++ b/tensorflow/python/BUILD @@ -74,6 +74,16 @@ py_library( ], ) +py_library( + name = "keras_lib", + srcs_version = "PY2AND3", + deps = [ + "//tensorflow/python:layers", + "//tensorflow/python/feature_column:feature_column_py", + "//tensorflow/python/keras", + ], +) + py_library( name = "no_contrib", srcs = ["__init__.py"], @@ -110,8 +120,8 @@ py_library( ":image_ops", ":initializers_ns", ":io_ops", + ":keras_lib", ":kernels", - ":layers", ":lib", ":list_ops", ":manip_ops", @@ -152,8 +162,6 @@ py_library( "//tensorflow/python/distribute:estimator_training", "//tensorflow/python/eager:def_function", "//tensorflow/python/eager:remote", - "//tensorflow/python/feature_column:feature_column_py", - "//tensorflow/python/keras", "//tensorflow/python/ops/distributions", "//tensorflow/python/ops/linalg", "//tensorflow/python/ops/losses", @@ -1070,6 +1078,7 @@ py_library( ":client", ":errors", ":framework_for_generated_wrappers", + ":layers_base", ":platform", ":platform_test", ":pywrap_tensorflow", @@ -1084,6 +1093,7 @@ py_library( "//tensorflow/python/eager:backprop", "//tensorflow/python/eager:context", "//tensorflow/python/eager:tape", + "//tensorflow/python/keras:layers", "//third_party/py/numpy", "@six_archive//:six", ], @@ -3552,7 +3562,7 @@ py_library( ":gradients", ":init_ops", ":io_ops", - ":layers_base", + ":layers_util", ":lookup_ops", ":math_ops", ":platform", @@ -3573,19 +3583,17 @@ py_library( ":util", ":variable_scope", ":variables", - "//third_party/py/numpy", - "@six_archive//:six", "//tensorflow/core:protos_all_py", "//tensorflow/python/data/ops:dataset_ops", - "//tensorflow/python/distribute:reduce_util", "//tensorflow/python/distribute:distribute_coordinator_context", + "//tensorflow/python/distribute:reduce_util", "//tensorflow/python/eager:backprop", "//tensorflow/python/eager:context", - # `layers` dependency only exists due to the use of a small utility. - "//tensorflow/python/keras:layers", "//tensorflow/python/ops/losses", "//tensorflow/python/training/checkpointable:base", "//tensorflow/python/training/checkpointable:util", + "//third_party/py/numpy", + "@six_archive//:six", ], ) @@ -5149,13 +5157,13 @@ py_library( srcs = [ "layers/__init__.py", "layers/base.py", - "layers/utils.py", ], srcs_version = "PY2AND3", deps = [ ":array_ops", ":control_flow_ops", ":framework_for_generated_wrappers", + ":layers_util", ":platform", ":smart_cond", ":tensor_util", @@ -5168,6 +5176,20 @@ py_library( ], ) +py_library( + name = "layers_util", + srcs = [ + "layers/utils.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":control_flow_ops", + ":smart_cond", + ":util", + ":variables", + ], +) + py_library( name = "layers", srcs = [ -- GitLab From d573107b32371d28bce06ffb041d01c23c34a6d2 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 13:04:14 -0800 Subject: [PATCH 0178/1765] Disallow specifying batch_size parameter when using tf.data.Dataset as an input for train/predict/eval. PiperOrigin-RevId: 226381028 --- tensorflow/python/keras/engine/training.py | 8 +++++++- .../python/keras/engine/training_dataset_test.py | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/tensorflow/python/keras/engine/training.py b/tensorflow/python/keras/engine/training.py index 2ef2e37a39..b10f24b4ad 100644 --- a/tensorflow/python/keras/engine/training.py +++ b/tensorflow/python/keras/engine/training.py @@ -1635,7 +1635,9 @@ class Model(Network): InputLayer. If so, this method checks the provided `batch_size` and `x` arguments are consistent with this static batch size. Also, if `batch_size` is `None`, this method will attempt to infer the batch size - from the static batch size of the InputLayer. + from the static batch size of the InputLayer. Lastly, ValueError will be + raised if `x` is a tf.data.Dataset and `batch_size` is specified as we + expect users to provide batched datasets. Arguments: batch_size: The batch_size provided as an argument to @@ -1647,6 +1649,10 @@ class Model(Network): The validated batch_size, auto-inferred from the first layer if not provided. """ + if batch_size is not None and isinstance(x, dataset_ops.DatasetV2): + raise ValueError('The `batch_size` argument must not be specified when' + ' using dataset as an input.') + layers = super(Model, self).layers # Avoids the override in Sequential. if layers: first_layer = layers[0] diff --git a/tensorflow/python/keras/engine/training_dataset_test.py b/tensorflow/python/keras/engine/training_dataset_test.py index f542ebfddc..646ce31909 100644 --- a/tensorflow/python/keras/engine/training_dataset_test.py +++ b/tensorflow/python/keras/engine/training_dataset_test.py @@ -223,6 +223,20 @@ class TestTrainingWithDataset(keras_parameterized.TestCase): sample_weight=sample_weight) # Test invalid usage + with self.assertRaisesRegexp(ValueError, 'The `batch_size` argument' + ' must not be specified when using dataset' + ' as an input.'): + model.fit(dataset, batch_size=10, epochs=1, steps_per_epoch=2, + verbose=0) + with self.assertRaisesRegexp(ValueError, 'The `batch_size` argument' + ' must not be specified when using dataset' + ' as an input.'): + model.predict(dataset, batch_size=10, steps=2, verbose=0) + with self.assertRaisesRegexp(ValueError, 'The `batch_size` argument' + ' must not be specified when using dataset' + ' as an input.'): + model.evaluate(dataset, batch_size=10, steps=2, verbose=0) + with self.assertRaisesRegexp(ValueError, 'you should not specify a target'): model.fit(dataset, dataset, -- GitLab From 63dcc4cc34fbb6e4de906e9e84e67645eefcfd3b Mon Sep 17 00:00:00 2001 From: mars20 Date: Thu, 20 Dec 2018 13:18:56 -0800 Subject: [PATCH 0179/1765] Adding a 'README' file for RISC-V --- tensorflow/lite/experimental/micro/riscv32_mcu/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tensorflow/lite/experimental/micro/riscv32_mcu/README.md diff --git a/tensorflow/lite/experimental/micro/riscv32_mcu/README.md b/tensorflow/lite/experimental/micro/riscv32_mcu/README.md new file mode 100644 index 0000000000..82f1dcbb61 --- /dev/null +++ b/tensorflow/lite/experimental/micro/riscv32_mcu/README.md @@ -0,0 +1,5 @@ +# RISC-V MCU + +This folder contains TFLite kernel operations optimized for RISC-V micro controllers. + +It is designed to be portable even to 'bare metal', so it follows the same design goals as the micro experimental port. -- GitLab From ec83e9758c7f98c6cb731e6e509bd0634e5f02cc Mon Sep 17 00:00:00 2001 From: James Keeling Date: Thu, 20 Dec 2018 13:24:54 -0800 Subject: [PATCH 0180/1765] Fix missing backtick in documentation for StridedSliceAssign. This was causing the docs to be formatted incorrectly. PiperOrigin-RevId: 226384008 --- .../core/api_def/base_api/api_def_StridedSliceAssign.pbtxt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/core/api_def/base_api/api_def_StridedSliceAssign.pbtxt b/tensorflow/core/api_def/base_api/api_def_StridedSliceAssign.pbtxt index 0fc89576ad..c5177612ef 100644 --- a/tensorflow/core/api_def/base_api/api_def_StridedSliceAssign.pbtxt +++ b/tensorflow/core/api_def/base_api/api_def_StridedSliceAssign.pbtxt @@ -4,7 +4,7 @@ op { description: < Date: Thu, 20 Dec 2018 13:26:33 -0800 Subject: [PATCH 0181/1765] Adds correctness test with _dynamic_ LR where the LR callback changes it the value every batch. PiperOrigin-RevId: 226384247 --- .../python/keras_correctness_test.py | 285 ++++++++++++------ 1 file changed, 190 insertions(+), 95 deletions(-) diff --git a/tensorflow/contrib/distribute/python/keras_correctness_test.py b/tensorflow/contrib/distribute/python/keras_correctness_test.py index e078731610..8247105074 100644 --- a/tensorflow/contrib/distribute/python/keras_correctness_test.py +++ b/tensorflow/contrib/distribute/python/keras_correctness_test.py @@ -38,6 +38,44 @@ _RANDOM_SEED = 1337 # keras_backward_compat_test for features that are supported with both APIs. +class MaybeDistributionScope(object): + """Provides a context allowing no distribution strategy.""" + + def __init__(self, distribution): + self._distribution = distribution + self._scope = None + + def __enter__(self): + if self._distribution: + self._scope = self._distribution.scope() + self._scope.__enter__() + + def __exit__(self, exc_type, value, traceback): + if self._distribution: + self._scope.__exit__(exc_type, value, traceback) + self._scope = None + + +def _create_dnn_model(weights=None, distribution=None, compile_model=True): + with MaybeDistributionScope(distribution): + # We add few non-linear layers to make it non-trivial. + model = keras.Sequential() + model.add(keras.layers.Dense(10, activation='relu', input_shape=(1,))) + model.add(keras.layers.Dense(10, activation='relu')) + model.add(keras.layers.Dense(10, activation='relu')) + model.add(keras.layers.Dense(1)) + + if weights: + model.set_weights(weights) + + if compile_model: + model.compile( + loss=keras.losses.mean_squared_error, + optimizer=gradient_descent_keras.SGD(0.5), + metrics=['mse']) + return model + + def batch_wrapper(dataset, batch_size, distribution, repeat=None): if repeat: dataset = dataset.repeat(repeat) @@ -49,20 +87,24 @@ def batch_wrapper(dataset, batch_size, distribution, repeat=None): return dataset.batch(batch_size) +def get_batch_size(global_batch_size, distribution): + batch_size = global_batch_size + # TODO(b/118776054): Use global batch size for Keras/DS support. + use_per_core_batch_size = ( + distribution and + not distributed_training_utils.global_batch_size_supported(distribution)) + if use_per_core_batch_size: + batch_size //= distribution.num_replicas_in_sync + return batch_size + + def get_correctness_test_inputs(use_numpy, use_validation_data, with_distribution, x_train, y_train, x_predict): """Generates the inputs for correctness check when enable Keras with DS.""" training_epochs = 2 global_batch_size = 64 - batch_size = global_batch_size - # TODO(b/118776054): Use global batch size for Keras/DS support. - use_per_core_batch_size = ( - with_distribution and - not distributed_training_utils.global_batch_size_supported( - with_distribution)) - if use_per_core_batch_size: - batch_size //= with_distribution.num_replicas_in_sync + batch_size = get_batch_size(global_batch_size, with_distribution) if use_numpy: training_inputs = { @@ -116,9 +158,7 @@ def get_correctness_test_inputs(use_numpy, use_validation_data, 'steps': 20, } - predict_batch_size = len(x_predict) - if use_per_core_batch_size: - predict_batch_size //= with_distribution.num_replicas_in_sync + predict_batch_size = get_batch_size(len(x_predict), with_distribution) predict_dataset = dataset_ops.Dataset.from_tensor_slices(x_predict) predict_dataset = batch_wrapper(predict_dataset, predict_batch_size, with_distribution) @@ -159,6 +199,12 @@ def all_strategy_combinations(): return strategy_minus_tpu_combinations() + tpu_strategy_combinations() +def all_strategy_combinations_with_graph_mode(): + return combinations.combine( + distribution=strategies_minus_tpu, + mode=['graph']) + tpu_strategy_combinations() + + def strategy_and_input_combinations(): return ( combinations.times( @@ -176,6 +222,83 @@ def strategy_and_input_combinations(): use_validation_data=[True, False]))) +def fit_eval_and_predict( + initial_weights, input_fn, distribution=None): + model = _create_dnn_model(initial_weights, distribution) + training_inputs, eval_inputs, predict_inputs = input_fn(distribution) + + result = {} + result['training_history_1'] = model.fit(**training_inputs).history + + if eval_inputs is not None: + result['eval_result_1'] = model.evaluate(**eval_inputs) + + result['weights_1'] = model.get_weights() + + if predict_inputs is not None: + result['predict_result_1'] = model.predict(**predict_inputs) + + # Train and eval again to mimic user's flow. + + result['training_history_2'] = model.fit(**training_inputs).history + + if eval_inputs is not None: + result['eval_result_2'] = model.evaluate(**eval_inputs) + + result['weights_2'] = model.get_weights() + + return result + + +def compare_results(results_with_ds, results_without_ds, distribution, + testcase): + default_tolerance = 1e-5 + tol_table = {} + + if isinstance(distribution, ( + mirrored_strategy.MirroredStrategy, + mirrored_strategy.CoreMirroredStrategy, + distribute_lib._DefaultDistributionStrategy)): # pylint: disable=protected-access + # TODO(b/119257215): Weights are not exactly the same, so use larger + # tolerance for now. Predict should be related to weights. + tol_table = { + 'weights_1': 1e-4, + 'weights_2': 1e-4, + 'predict_result_1': 1e-4, + } + + for key in results_with_ds: + if (key.startswith('training_history') and + isinstance(distribution, tpu_strategy.TPUStrategy) and + distribution.extended.steps_per_run > 1): + # TODO(b/119894254): Enable this test for all cases once the + # underlying bug is fixed. + continue + + tolerance = tol_table.get(key, default_tolerance) + + testcase.assertAllClose( + results_with_ds[key], + results_without_ds[key], + atol=tolerance, + rtol=tolerance, + msg='Fail to assert {}.'.format(key)) + + +class LearningRateBatchScheduler(keras.callbacks.Callback): + + def __init__(self, update_freq=None): + self._update_freq = update_freq + + def on_batch_begin(self, batch, logs=None): + if self._update_freq and batch % self._update_freq != 0: + return + + # To avoid divergence, limit the value range. + lr = 0.001 * (batch % 10) + keras.backend.set_value(self.model.optimizer.lr, lr) + + class TestDistributionStrategyCorrectness(test.TestCase, parameterized.TestCase): @@ -246,20 +369,6 @@ class TestDistributionStrategyCorrectness(test.TestCase, @combinations.generate(strategy_and_input_combinations()) def test_correctness(self, distribution, use_numpy, use_validation_data): with self.cached_session(): - default_tolerance = 1e-5 - tol_table = {} - - if isinstance(distribution, ( - mirrored_strategy.MirroredStrategy, - mirrored_strategy.CoreMirroredStrategy, - distribute_lib._DefaultDistributionStrategy)): # pylint: disable=protected-access - # TODO(b/119257215): Weights are not exactly the same, so use larger - # tolerance for now. Predict should be related to weights. - tol_table = { - 'weights_1': 1e-4, - 'weights_2': 1e-4, - 'predict_result_1': 1e-4, - } keras.backend.set_image_data_format('channels_last') np.random.seed(_RANDOM_SEED) @@ -278,84 +387,70 @@ class TestDistributionStrategyCorrectness(test.TestCase, # The model is built once and the initial weights are saved. # This is used to initialize the model for both the distribution and - # non-distribution run. In addition, we add few non-linear layers to make - # it non-trivial. - def _create_model(): - model = keras.Sequential() - model.add(keras.layers.Dense(10, activation='relu', input_shape=(1,))) - model.add(keras.layers.Dense(10, activation='relu')) - model.add(keras.layers.Dense(10, activation='relu')) - model.add(keras.layers.Dense(1)) - return model - - model = _create_model() + # non-distribution run. + model = _create_dnn_model(compile_model=False) initial_weights = model.get_weights() - del model # avoid accident usage. - - def _build_and_compile_model(): - # We have initialized the model to the same weight for the distribution - # and non-distribution run. - model = _create_model() - model.set_weights(initial_weights) - model.compile( - loss=keras.losses.mean_squared_error, - optimizer=gradient_descent_keras.SGD(0.5), - metrics=['mse']) - return model - def fit_eval_and_predict(with_distribution=None): - if with_distribution: - with with_distribution.scope(): - model = _build_and_compile_model() - else: - model = _build_and_compile_model() + def input_fn(dist): + return get_correctness_test_inputs( + use_numpy, use_validation_data, dist, x_train, y_train, x_predict) - training_inputs, eval_inputs, predict_inputs = ( - get_correctness_test_inputs(use_numpy, use_validation_data, - with_distribution, - x_train, y_train, x_predict)) + results_with_ds = fit_eval_and_predict( + initial_weights, input_fn=input_fn, distribution=distribution) + results_without_ds = fit_eval_and_predict( + initial_weights, input_fn=input_fn, distribution=None) + compare_results(results_with_ds, results_without_ds, distribution, + testcase=self) - result = {} - result['training_history_1'] = model.fit(**training_inputs).history - - if eval_inputs is not None: - result['eval_result_1'] = model.evaluate(**eval_inputs) - - result['weights_1'] = model.get_weights() - result['predict_result_1'] = model.predict(**predict_inputs) - - # Train and eval again to mimic user's flow. - - result['training_history_2'] = model.fit(**training_inputs).history - - if eval_inputs is not None: - result['eval_result_2'] = model.evaluate(**eval_inputs) - - result['weights_2'] = model.get_weights() - - return result + @combinations.generate(all_strategy_combinations_with_graph_mode()) + def test_dynamic_lr(self, distribution): + with self.cached_session(): - results_with_ds = fit_eval_and_predict(with_distribution=distribution) - results_without_ds = fit_eval_and_predict(with_distribution=None) + keras.backend.set_image_data_format('channels_last') + np.random.seed(_RANDOM_SEED) + random_seed.set_random_seed(_RANDOM_SEED) - # Verify that the weights, training history, eval results, predict outputs - # are the same within some limits of tolerance. - for key in results_with_ds: - if (key.startswith('training_history') and - isinstance(distribution, tpu_strategy.TPUStrategy) and - distribution.extended.steps_per_run > 1): - # TODO(b/119894254): Enable this test for all cases once the - # underlying bug is fixed. - continue + # TODO(xiejw): Change this back to 10000, once we support final partial + # batch. + num_samples = 9984 + x_train = np.random.rand(num_samples, 1).astype('float32') + y_train = 3 * x_train - tolerance = tol_table.get(key, default_tolerance) + model = _create_dnn_model(compile_model=False) + initial_weights = model.get_weights() - self.assertAllClose( - results_with_ds[key], - results_without_ds[key], - atol=tolerance, - rtol=tolerance, - msg='Fail to assert {}.'.format(key)) + update_freq = None + if (isinstance(distribution, tpu_strategy.TPUStrategy) and + distribution.extended.steps_per_run > 1): + # For TPUStrategy with steps_per_run > 1, the callback is not invoked + # every step. So, to compare the CPU/TPU, we let the CPU to behave the + # same as TPU. + update_freq = distribution.extended.steps_per_run + + def input_fn(dist): + training_epochs = 2 + global_batch_size = 64 + batch_size = get_batch_size(global_batch_size, dist) + + training_inputs = { + 'batch_size': batch_size, + 'x': x_train, + 'y': y_train, + 'epochs': training_epochs, + 'shuffle': False, + 'callbacks': [LearningRateBatchScheduler(update_freq)], + 'validation_data': (x_train, y_train) + } + # In this test case, we do not care eval and predict. + eval_inputs, predict_inputs = None, None + return training_inputs, eval_inputs, predict_inputs + + results_with_ds = fit_eval_and_predict( + initial_weights, input_fn=input_fn, distribution=distribution) + results_without_ds = fit_eval_and_predict( + initial_weights, input_fn=input_fn, distribution=None) + compare_results(results_with_ds, results_without_ds, distribution, + testcase=self) if __name__ == '__main__': -- GitLab From 6a6658f3e2bae16e2d0067fcb7d7cb0850272d1b Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 13:34:54 -0800 Subject: [PATCH 0182/1765] Run grappler optimization after importing frozen graphdefs. PiperOrigin-RevId: 226385619 --- tensorflow/lite/python/BUILD | 1 + tensorflow/lite/python/lite.py | 41 ++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/tensorflow/lite/python/BUILD b/tensorflow/lite/python/BUILD index b0ca3f8dcc..e666812bd2 100644 --- a/tensorflow/lite/python/BUILD +++ b/tensorflow/lite/python/BUILD @@ -61,6 +61,7 @@ py_library( ":lite_constants", ":op_hint", "//tensorflow/python:graph_util", + "//tensorflow/python:tf_optimizer", "//tensorflow/python/keras", "//tensorflow/python/saved_model:constants", "//tensorflow/python/saved_model:loader", diff --git a/tensorflow/lite/python/lite.py b/tensorflow/lite/python/lite.py index 1b20ff2f92..159eacd26f 100644 --- a/tensorflow/lite/python/lite.py +++ b/tensorflow/lite/python/lite.py @@ -53,19 +53,49 @@ from tensorflow.lite.python.interpreter import Interpreter # pylint: disable=un from tensorflow.lite.python.op_hint import convert_op_hints_to_stubs # pylint: disable=unused-import from tensorflow.lite.python.op_hint import OpHint # pylint: disable=unused-import from tensorflow.core.framework import graph_pb2 as _graph_pb2 +from tensorflow.core.protobuf import rewriter_config_pb2 as _rewriter_config_pb2 +from tensorflow.core.protobuf import config_pb2 as _config_pb2 +from tensorflow.core.protobuf import meta_graph_pb2 as _meta_graph_pb2 from tensorflow.python import keras as _keras from tensorflow.python.client import session as _session from tensorflow.python.framework import graph_util as _tf_graph_util from tensorflow.python.framework import ops as _ops from tensorflow.python.framework.errors_impl import NotFoundError as _NotFoundError from tensorflow.python.framework.importer import import_graph_def as _import_graph_def +from tensorflow.python.grappler import tf_optimizer as _tf_optimizer from tensorflow.python.lib.io import file_io as _file_io from tensorflow.python.saved_model import signature_constants as _signature_constants from tensorflow.python.saved_model import tag_constants as _tag_constants +from tensorflow.python.training.saver import export_meta_graph as _export_meta_graph from tensorflow.python.util import deprecation as _deprecation from tensorflow.python.util.tf_export import tf_export as _tf_export +def _run_graph_optimizations(graph_def, output_arrays): + """Apply standard TensorFlow optimizations to the graph_def. + + Args: + graph_def: Frozen GraphDef to be optimized. + output_arrays: List of arrays that are considered outputs of the graph. + + Returns: + A new, optimized GraphDef. + """ + meta_graph = _export_meta_graph(graph_def=graph_def) + + # We need to add a collection called 'train_op' so that grappler + # knows what the outputs are. + fetch_collection = _meta_graph_pb2.CollectionDef() + for output in output_arrays: + fetch_collection.node_list.value.append(output) + meta_graph.collection_def["train_op"].CopyFrom(fetch_collection) + + config = _config_pb2.ConfigProto() + rewrite_options = config.graph_options.rewrite_options + rewrite_options.layout_optimizer = _rewriter_config_pb2.RewriterConfig.ON + return _tf_optimizer.OptimizeGraph(config, meta_graph) + + @_tf_export("lite.TFLiteConverter") class TFLiteConverter(object): """Convert a TensorFlow model into `output_format` using TOCO. @@ -446,16 +476,23 @@ class TFLiteConverter(object): "dump_graphviz_video": self.dump_graphviz_video } + optimized_graph = None + try: + optimized_graph = _run_graph_optimizations( + self._graph_def, [t.name for t in self._output_tensors]) + except Exception: + optimized_graph = self._graph_def + # Converts model. if self._has_valid_tensors(): result = _toco_convert_impl( - input_data=self._graph_def, + input_data=optimized_graph, input_tensors=self._input_tensors, output_tensors=self._output_tensors, **converter_kwargs) else: result = _toco_convert_graph_def( - input_data=self._graph_def, + input_data=optimized_graph, input_arrays_with_shape=self._input_arrays_with_shape, output_arrays=self._output_arrays, **converter_kwargs) -- GitLab From a785fd08261a081d3a4e1a36f7b842dcd78c5d18 Mon Sep 17 00:00:00 2001 From: Martin Wicke Date: Thu, 20 Dec 2018 13:34:59 -0800 Subject: [PATCH 0183/1765] Export Dimension related compatibility tooling to compat. PiperOrigin-RevId: 226385629 --- tensorflow/python/framework/tensor_shape.py | 6 ++++-- tensorflow/tools/api/golden/v1/tensorflow.compat.pbtxt | 8 ++++++++ tensorflow/tools/api/golden/v2/tensorflow.compat.pbtxt | 8 ++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/tensorflow/python/framework/tensor_shape.py b/tensorflow/python/framework/tensor_shape.py index 960a3dad73..a4c626c64c 100644 --- a/tensorflow/python/framework/tensor_shape.py +++ b/tensorflow/python/framework/tensor_shape.py @@ -90,7 +90,8 @@ def disable_v2_tensorshape(): TensorShape = TensorShapeV1 -@tf_export(v1=["dimension_value"]) +@tf_export("compat.dimension_value", + v1=["dimension_value", "compat.dimension_value"]) def dimension_value(dimension): """Compatibility utility required to allow for both V1 and V2 behavior in TF. @@ -122,7 +123,8 @@ def dimension_value(dimension): return dimension -@tf_export(v1=["dimension_at_index"]) +@tf_export("compat.dimension_at_index", + v1=["dimension_at_index", "compat.dimension_at_index"]) def dimension_at_index(shape, index): """Compatibility utility required to allow for both V1 and V2 behavior in TF. diff --git a/tensorflow/tools/api/golden/v1/tensorflow.compat.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.compat.pbtxt index f1d760603e..95352dff3a 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.compat.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.compat.pbtxt @@ -32,6 +32,14 @@ tf_module { name: "as_text" argspec: "args=[\'bytes_or_text\', \'encoding\'], varargs=None, keywords=None, defaults=[\'utf-8\'], " } + member_method { + name: "dimension_at_index" + argspec: "args=[\'shape\', \'index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "dimension_value" + argspec: "args=[\'dimension\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "forward_compatibility_horizon" argspec: "args=[\'year\', \'month\', \'day\'], varargs=None, keywords=None, defaults=None" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.compat.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.compat.pbtxt index f1d760603e..95352dff3a 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.compat.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.compat.pbtxt @@ -32,6 +32,14 @@ tf_module { name: "as_text" argspec: "args=[\'bytes_or_text\', \'encoding\'], varargs=None, keywords=None, defaults=[\'utf-8\'], " } + member_method { + name: "dimension_at_index" + argspec: "args=[\'shape\', \'index\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "dimension_value" + argspec: "args=[\'dimension\'], varargs=None, keywords=None, defaults=None" + } member_method { name: "forward_compatibility_horizon" argspec: "args=[\'year\', \'month\', \'day\'], varargs=None, keywords=None, defaults=None" -- GitLab From e4bfd939500f54882cc0a229db9df97bac794e54 Mon Sep 17 00:00:00 2001 From: Gunhan Gulsoy Date: Thu, 20 Dec 2018 13:36:01 -0800 Subject: [PATCH 0184/1765] Bump max version of bazel to 0.21 PiperOrigin-RevId: 226385826 --- configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.py b/configure.py index 1e732db264..acb92cbc1e 100644 --- a/configure.py +++ b/configure.py @@ -1554,7 +1554,7 @@ def main(): # environment variables. environ_cp = dict(os.environ) - check_bazel_version('0.19.0', '0.20.0') + check_bazel_version('0.19.0', '0.21.0') reset_tf_configure_bazelrc() -- GitLab From 87595cb68738153d15de8a19724046625c5a3cc9 Mon Sep 17 00:00:00 2001 From: Anna R Date: Thu, 20 Dec 2018 13:36:26 -0800 Subject: [PATCH 0185/1765] Add more toolchain cpus to BUILD file and remove corresponding default toolchains from CROSSTOOL files. PiperOrigin-RevId: 226385901 --- third_party/gpus/crosstool/BUILD.tpl | 4 +++ third_party/gpus/crosstool/CROSSTOOL.tpl | 25 ------------------- third_party/toolchains/cpus/arm/BUILD | 4 +++ third_party/toolchains/cpus/arm/CROSSTOOL.tpl | 20 --------------- 4 files changed, 8 insertions(+), 45 deletions(-) diff --git a/third_party/gpus/crosstool/BUILD.tpl b/third_party/gpus/crosstool/BUILD.tpl index 5e6b47f44f..db76306ffb 100644 --- a/third_party/gpus/crosstool/BUILD.tpl +++ b/third_party/gpus/crosstool/BUILD.tpl @@ -23,7 +23,11 @@ cc_toolchain_suite( "darwin|compiler": ":cc-compiler-darwin", "x64_windows|msvc-cl": ":cc-compiler-windows", "x64_windows": ":cc-compiler-windows", + "arm": ":cc-compiler-local", "k8": ":cc-compiler-local", + "piii": ":cc-compiler-local", + "ppc": ":cc-compiler-local", + "darwin": ":cc-compiler-darwin", }, ) diff --git a/third_party/gpus/crosstool/CROSSTOOL.tpl b/third_party/gpus/crosstool/CROSSTOOL.tpl index 5ca9b2deb4..1a13ac844c 100644 --- a/third_party/gpus/crosstool/CROSSTOOL.tpl +++ b/third_party/gpus/crosstool/CROSSTOOL.tpl @@ -2,31 +2,6 @@ major_version: "local" minor_version: "" default_target_cpu: "same_as_host" -default_toolchain { - cpu: "k8" - toolchain_identifier: "local_linux" -} -default_toolchain { - cpu: "piii" - toolchain_identifier: "local_linux" -} -default_toolchain { - cpu: "arm" - toolchain_identifier: "local_linux" -} -default_toolchain { - cpu: "darwin" - toolchain_identifier: "local_darwin" -} -default_toolchain { - cpu: "ppc" - toolchain_identifier: "local_linux" -} -default_toolchain { - cpu: "x64_windows" - toolchain_identifier: "local_windows" -} - toolchain { abi_version: "local" abi_libc_version: "local" diff --git a/third_party/toolchains/cpus/arm/BUILD b/third_party/toolchains/cpus/arm/BUILD index a565e1e55f..efed697239 100644 --- a/third_party/toolchains/cpus/arm/BUILD +++ b/third_party/toolchains/cpus/arm/BUILD @@ -6,6 +6,10 @@ cc_toolchain_suite( "armeabi|compiler": ":cc-compiler-armeabi", "local|compiler": ":cc-compiler-local", "armeabi": ":cc-compiler-armeabi", + "k8": ":cc-compiler-local", + "piii": ":cc-compiler-local", + "arm": ":cc-compiler-local", + "s390x": ":cc-compiler-local", }, ) diff --git a/third_party/toolchains/cpus/arm/CROSSTOOL.tpl b/third_party/toolchains/cpus/arm/CROSSTOOL.tpl index f0e17d1fe0..8d51e9b0c6 100644 --- a/third_party/toolchains/cpus/arm/CROSSTOOL.tpl +++ b/third_party/toolchains/cpus/arm/CROSSTOOL.tpl @@ -2,14 +2,6 @@ major_version: "local" minor_version: "" default_target_cpu: "same_as_host" -default_toolchain { - cpu: "k8" - toolchain_identifier: "local_linux" -} -default_toolchain { - cpu: "piii" - toolchain_identifier: "local_linux" -} default_toolchain { cpu: "darwin" toolchain_identifier: "local_darwin" @@ -18,14 +10,6 @@ default_toolchain { cpu: "freebsd" toolchain_identifier: "local_freebsd" } -default_toolchain { - cpu: "armeabi" - toolchain_identifier: "arm-linux-gnueabihf" -} -default_toolchain { - cpu: "arm" - toolchain_identifier: "local_linux" -} default_toolchain { cpu: "x64_windows" toolchain_identifier: "local_windows_msys64" @@ -34,10 +18,6 @@ default_toolchain { cpu: "x64_windows_msvc" toolchain_identifier: "vc_14_0_x64" } -default_toolchain { - cpu: "s390x" - toolchain_identifier: "local_linux" -} toolchain { abi_version: "armeabi" -- GitLab From 5dde9b79227bafc3ee7e75e9fa1d0b1b477fe62c Mon Sep 17 00:00:00 2001 From: Pete Warden Date: Thu, 20 Dec 2018 14:07:45 -0800 Subject: [PATCH 0186/1765] Moved targets to examples directory --- .../micro/examples/micro_speech/Makefile.inc | 3 + .../micro_speech/apollo3/Makefile.inc | 100 ++++++++++ .../micro_speech/apollo3/preprocessor_1k.cc | 21 +-- .../experimental/micro/tools/make/Makefile | 171 +----------------- .../micro/tools/make/download_dependencies.sh | 7 +- .../make/targets/apollo3evb_makefile.inc | 37 +--- 6 files changed, 118 insertions(+), 221 deletions(-) create mode 100644 tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/Makefile.inc diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/Makefile.inc b/tensorflow/lite/experimental/micro/examples/micro_speech/Makefile.inc index 0e42329cad..0d9c9a56a7 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/Makefile.inc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/Makefile.inc @@ -151,3 +151,6 @@ $(MICRO_SPEECH_BINARY): $(MICRO_SPEECH_OBJS) $(MICROLITE_LIB_PATH) $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) micro_speech: $(MICRO_SPEECH_BINARY) micro_speech_bin: $(MICRO_SPEECH_BINARY).bin + +# Find any platform-specific rules for this example. +include $(wildcard tensorflow/lite/experimental/micro/examples/micro_speech/*/Makefile.inc) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/Makefile.inc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/Makefile.inc new file mode 100644 index 0000000000..0aa362be00 --- /dev/null +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/Makefile.inc @@ -0,0 +1,100 @@ +# Settings for apollo3 evb platforms. +ifeq ($(TARGET), apollo3evb) + + PUSHBUTTON_MICRO_SPEECH_TEST_SRCS := \ + $(AP3_MICRO_DIR)/../preprocessor.cc \ + $(AP3_MICRO_DIR)/pushbutton_main.c \ + $(AP3_MICRO_DIR)/pushbutton_test.cc \ + $(AP3_MICRO_DIR)/../tiny_conv_model_data.cc \ + $(APOLLO3_SDK)/devices/am_devices_led.c + ALL_SRCS += $(PUSHBUTTON_MICRO_SPEECH_TEST_SRCS) + PUSHBUTTON_MICRO_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ + $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PUSHBUTTON_MICRO_SPEECH_TEST_SRCS)))) + PUSHBUTTON_MICRO_SPEECH_TEST_BINARY := $(BINDIR)pushbutton_micro_speech_test + $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY): $(PUSHBUTTON_MICRO_SPEECH_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) $(PUSHBUTTON_MICRO_SPEECH_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + pushbutton_micro_speech_test: $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) + pushbutton_micro_speech_test_bin: $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY).bin + test_pushbutton_micro_speech: $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) + $(TEST_SCRIPT) $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + + PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS := \ + $(AP3_MICRO_DIR)/pushbutton_main.c \ + $(AP3_MICRO_DIR)/pushbutton_test.cc \ + $(AP3_MICRO_DIR)/../tiny_conv_model_data.cc \ + $(CMSIS_DIR)/preprocessor.cc \ + $(CMSIS_EXT_DIR)/arm_cmplx_mag_squared_q10p6.c \ + $(CMSIS_DIR)/hanning.c \ + $(APOLLO3_SDK)/devices/am_devices_led.c \ + $(CMSIS_SRCS) + ALL_SRCS += $(PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS) + PUSHBUTTON_CMSIS_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ + $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS))) \ + arm_bitreversal2.o) + PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY := $(BINDIR)pushbutton_cmsis_speech_test + $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY): $(PUSHBUTTON_CMSIS_SPEECH_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) $(PUSHBUTTON_CMSIS_SPEECH_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + pushbutton_cmsis_speech_test: $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) + pushbutton_cmsis_speech_test_bin: $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY).bin + test_pushbutton_cmsis_speech: $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) + $(TEST_SCRIPT) $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + + PREPROCESSOR_1K_SRCS := \ + tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc \ + tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc + + PREPROCESSOR_1K_MICRO_TEST_SRCS := \ + $(PREPROCESSOR_1K_SRCS) \ + $(AP3_MICRO_DIR)/../fixed_point/preprocessor.cc \ + $(AP3_EXT_MICRO_DIR)/system_apollo3.c \ + $(AP3_MICRO_DIR)/_main.c + ALL_SRCS += $(PREPROCESSOR_1K_MICRO_TEST_SRCS) + PREPROCESSOR_1K_MICRO_TEST_OBJS := $(addprefix $(OBJDIR), \ + $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_1K_MICRO_TEST_SRCS)))) + PREPROCESSOR_1K_MICRO_TEST_BINARY := $(BINDIR)preprocessor_1k_micro_test + $(PREPROCESSOR_1K_MICRO_TEST_BINARY): $(PREPROCESSOR_1K_MICRO_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PREPROCESSOR_1K_MICRO_TEST_BINARY) $(PREPROCESSOR_1K_MICRO_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + preprocessor_1k_micro_test: $(PREPROCESSOR_1K_MICRO_TEST_BINARY) + preprocessor_1k_micro_test_bin: $(PREPROCESSOR_1K_MICRO_TEST_BINARY).bin + test_preprocessor_1k_micro: $(PREPROCESSOR_1K_MICRO_TEST_BINARY) + $(TEST_SCRIPT) $(PREPROCESSOR_1K_MICRO_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + + PREPROCESSOR_1K_CMSIS_TEST_SRCS := \ + $(PREPROCESSOR_1K_SRCS) \ + $(CMSIS_DIR)/preprocessor.cc \ + $(CMSIS_EXT_DIR)/arm_cmplx_mag_squared_q10p6.c \ + $(CMSIS_DIR)/hanning.c \ + $(AP3_EXT_MICRO_DIR)/system_apollo3.c \ + $(AP3_MICRO_DIR)/_main.c \ + $(CMSIS_SRCS) + ALL_SRCS += $(PREPROCESSOR_1K_CMSIS_TEST_SRCS) + PREPROCESSOR_1K_CMSIS_TEST_BINARY := $(BINDIR)preprocessor_1k_cmsis_test + PREPROCESSOR_1K_CMSIS_TEST_OBJS := $(addprefix $(OBJDIR), \ + $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_1K_CMSIS_TEST_SRCS)))\ + arm_bitreversal2.o) + $(PREPROCESSOR_1K_CMSIS_TEST_BINARY): $(PREPROCESSOR_1K_CMSIS_TEST_OBJS) $(MICROLITE_LIB_PATH) + @mkdir -p $(dir $@) + $(CXX) $(CXXFLAGS) $(INCLUDES) \ + -o $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) $(PREPROCESSOR_1K_CMSIS_TEST_OBJS) \ + $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) + preprocessor_1k_cmsis_test: $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) + preprocessor_1k_cmsis_test_bin: $(PREPROCESSOR_1K_CMSIS_TEST_BINARY).bin + test_preprocessor_1k_cmsis: $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) + $(TEST_SCRIPT) $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) '~~~ALL TESTS PASSED~~~' + + PREPROCESSOR_TEST_SRCS += \ + $(AP3_MICRO_DIR)/_main.c + + $(OBJDIR)arm_bitreversal2.o: + $(CXX) $(CXXFLAGS) $(INCLUDES) -c $(CMSIS_SRC_DIR)/TransformFunctions/arm_bitreversal2.S -o $(OBJDIR)arm_bitreversal2.o + +endif diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc index 561c46ce33..007772e77a 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc @@ -13,28 +13,29 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -/* This file is a modification of the Tensorflow Micro Lite file preprocessor.cc */ +/* This file is a modification of the Tensorflow Micro Lite file preprocessor.cc + */ -#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h" #include "tensorflow/lite/c/c_api_internal.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.h" #include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/testing/micro_test.h" extern "C" { -#include "tensorflow/lite/experimental/micro/examples/micro_speech/apollo3_ext/system_apollo3.h" -#include "tensorflow/lite/experimental/micro/examples/micro_speech/apollo3_ext/apollo3.h" +#include "apollo3.h" +#include "system_apollo3.h" } #define output_data_size 43 int count; extern TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, - const int16_t* input, int input_size, int output_size, - uint8_t* output); + const int16_t* input, int input_size, + int output_size, uint8_t* output); TF_LITE_MICRO_TESTS_BEGIN CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; -//DWT->LAR = 0xC5ACCE55; +// DWT->LAR = 0xC5ACCE55; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; @@ -43,12 +44,10 @@ TF_LITE_MICRO_TEST(TestPreprocessor) { tflite::ErrorReporter* error_reporter = µ_error_reporter; uint8_t calculated_data[output_data_size]; - TfLiteStatus yes_status = Preprocess( - error_reporter, g_sin_1k, g_sin_1k_size, - output_data_size, calculated_data); + TfLiteStatus yes_status = Preprocess(error_reporter, g_sin_1k, g_sin_1k_size, + output_data_size, calculated_data); count = DWT->CYCCNT; TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, yes_status); - } TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/tools/make/Makefile b/tensorflow/lite/experimental/micro/tools/make/Makefile index 7223ea3d1e..6a7c875888 100644 --- a/tensorflow/lite/experimental/micro/tools/make/Makefile +++ b/tensorflow/lite/experimental/micro/tools/make/Makefile @@ -53,46 +53,6 @@ CC_PREFIX := # runtime that can be linked in to other programs. MICROLITE_LIB_NAME := libtensorflow-microlite.a -# Test binary for the microcontroller speech model. -MICRO_SPEECH_TEST_SRCS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc - -# Test binary for the streaming microcontroller speech model. -PUSHBUTTON_MICRO_SPEECH_TEST_SRCS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_features_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_features_data.cc - -# Test binary for the streaming microcontroller speech model. -PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/micro_speech_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.cc - -# Test binary for the microcontroller speech model. -PREPROCESSOR_TEST_SRCS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor_test.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_30ms_sample_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_30ms_sample_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/no_power_spectrum_data.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/yes_power_spectrum_data.cc - -PREPROCESSOR_REFERENCE_TEST_SRCS = \ -$(PREPROCESSOR_TEST_SRCS) \ -tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc - -PREPROCESSOR_FIXED_TEST_SRCS += \ -$(PREPROCESSOR_TEST_SRCS) \ -tensorflow/lite/experimental/micro/examples/micro_speech/fixed_point/preprocessor.cc - -PREPROCESSOR_1K_SRCS := \ -tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k.cc \ -tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc - - MICROLITE_TEST_SRCS := \ $(wildcard tensorflow/lite/experimental/micro/*test.cc) \ $(wildcard tensorflow/lite/experimental/micro/kernels/*test.cc) @@ -115,14 +75,7 @@ MICROLITE_CC_SRCS := $(filter-out $(MICROLITE_TEST_SRCS), $(MICROLITE_CC_BASE_SR include $(wildcard $(MAKEFILE_DIR)/targets/*_makefile.inc) ALL_SRCS := \ - $(MICRO_SPEECH_TEST_SRCS) \ - $(PUSHBUTTON_MICRO_SPEECH_TEST_SRCS) \ - $(PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS) \ - $(PREPROCESSOR_REFERENCE_TEST_SRCS) \ - $(PREPROCESSOR_FIXED_TEST_SRCS) \ $(MICROLITE_CC_SRCS) \ - $(PREPROCESSOR_1K_MICRO_TEST_SRCS) \ - $(PREPROCESSOR_1K_CMSIS_TEST_SRCS) \ $(MICROLITE_TEST_SRCS) # Where compiled objects are stored. @@ -133,40 +86,12 @@ LIBDIR := $(GENDIR)lib/ MICROLITE_LIB_PATH := $(LIBDIR)$(MICROLITE_LIB_NAME) -MICRO_SPEECH_TEST_BINARY := $(BINDIR)micro_speech_test -PUSHBUTTON_MICRO_SPEECH_TEST_BINARY := $(BINDIR)pushbutton_micro_speech_test -PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY := $(BINDIR)pushbutton_cmsis_speech_test -PREPROCESSOR_REFERENCE_TEST_BINARY := $(BINDIR)preprocessor_reference_test -PREPROCESSOR_FIXED_TEST_BINARY := $(BINDIR)preprocessor_fixed_test -PREPROCESSOR_1K_MICRO_TEST_BINARY := $(BINDIR)preprocessor_1k_micro_test -PREPROCESSOR_1K_CMSIS_TEST_BINARY := $(BINDIR)preprocessor_1k_cmsis_test - CXX := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}g++ CC := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}gcc AR := $(CC_PREFIX)${TARGET_TOOLCHAIN_PREFIX}ar -MICRO_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ -$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(patsubst %.S,%.o,$(MICRO_SPEECH_TEST_SRCS))))) - -PUSHBUTTON_MICRO_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ -$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PUSHBUTTON_MICRO_SPEECH_TEST_SRCS)))) - -PUSHBUTTON_CMSIS_SPEECH_TEST_OBJS := $(addprefix $(OBJDIR), \ -$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS))) \ -arm_bitreversal2.o) - -PREPROCESSOR_REFERENCE_TEST_OBJS := $(addprefix $(OBJDIR), \ -$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_REFERENCE_TEST_SRCS)))) - -PREPROCESSOR_FIXED_TEST_OBJS := $(addprefix $(OBJDIR), \ -$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_FIXED_TEST_SRCS)))) - -PREPROCESSOR_1K_MICRO_TEST_OBJS := $(addprefix $(OBJDIR), \ -$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_1K_MICRO_TEST_SRCS)))) - -PREPROCESSOR_1K_CMSIS_TEST_OBJS := $(addprefix $(OBJDIR), \ -$(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(PREPROCESSOR_1K_CMSIS_TEST_SRCS))) \ -arm_bitreversal2.o) +# Load the examples. +include $(wildcard tensorflow/lite/experimental/micro/examples/*/Makefile.inc) MICROLITE_LIB_OBJS := $(addprefix $(OBJDIR), \ $(patsubst %.cc,%.o,$(patsubst %.c,%.o,$(MICROLITE_CC_SRCS)))) @@ -203,96 +128,6 @@ $(MICROLITE_LIB_PATH): tensorflow/lite/schema/schema_generated.h $(MICROLITE_LIB @mkdir -p $(dir $@) $(AR) $(ARFLAGS) $(MICROLITE_LIB_PATH) $(MICROLITE_LIB_OBJS) -$(MICRO_SPEECH_TEST_BINARY): $(MICRO_SPEECH_TEST_OBJS) $(MICROLITE_LIB_PATH) - @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) $(INCLUDES) \ - -o $(MICRO_SPEECH_TEST_BINARY) $(MICRO_SPEECH_TEST_OBJS) \ - $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) - -micro_speech_test: $(MICRO_SPEECH_TEST_BINARY) -micro_speech_test_bin: $(MICRO_SPEECH_TEST_BINARY).bin - -test_micro_speech: $(MICRO_SPEECH_TEST_BINARY) - $(TEST_SCRIPT) $(MICRO_SPEECH_TEST_BINARY) '~~~ALL TESTS PASSED~~~' - -$(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY): $(PUSHBUTTON_MICRO_SPEECH_TEST_OBJS) $(MICROLITE_LIB_PATH) - @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) $(INCLUDES) \ - -o $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) $(PUSHBUTTON_MICRO_SPEECH_TEST_OBJS) \ - $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) - -pushbutton_micro_speech_test: $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) -pushbutton_micro_speech_test_bin: $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY).bin - -test_pushbutton_micro_speech: $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) - $(TEST_SCRIPT) $(PUSHBUTTON_MICRO_SPEECH_TEST_BINARY) '~~~ALL TESTS PASSED~~~' - - -$(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY): $(PUSHBUTTON_CMSIS_SPEECH_TEST_OBJS) $(MICROLITE_LIB_PATH) - @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) $(INCLUDES) \ - -o $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) $(PUSHBUTTON_CMSIS_SPEECH_TEST_OBJS) \ - $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) - -pushbutton_cmsis_speech_test: $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) -pushbutton_cmsis_speech_test_bin: $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY).bin - -test_pushbutton_cmsis_speech: $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) - $(TEST_SCRIPT) $(PUSHBUTTON_CMSIS_SPEECH_TEST_BINARY) '~~~ALL TESTS PASSED~~~' - -$(PREPROCESSOR_REFERENCE_TEST_BINARY): $(PREPROCESSOR_REFERENCE_TEST_OBJS) $(MICROLITE_LIB_PATH) - @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) $(INCLUDES) \ - -o $(PREPROCESSOR_REFERENCE_TEST_BINARY) $(PREPROCESSOR_REFERENCE_TEST_OBJS) \ - $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) - -preprocessor_reference_test: $(PREPROCESSOR_REFERENCE_TEST_BINARY) -preprocessor_reference_test_bin: $(PREPROCESSOR_REFERENCE_TEST_BINARY).bin - -test_preprocessor_reference: $(PREPROCESSOR_REFERENCE_TEST_BINARY) - $(TEST_SCRIPT) $(PREPROCESSOR_REFERENCE_TEST_BINARY) '~~~ALL TESTS PASSED~~~' - -$(PREPROCESSOR_FIXED_TEST_BINARY): $(PREPROCESSOR_FIXED_TEST_OBJS) $(MICROLITE_LIB_PATH) - @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) $(INCLUDES) \ - -o $(PREPROCESSOR_FIXED_TEST_BINARY) $(PREPROCESSOR_FIXED_TEST_OBJS) \ - $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) - -preprocessor_fixed_test: $(PREPROCESSOR_FIXED_TEST_BINARY) -preprocessor_fixed_test_bin: $(PREPROCESSOR_FIXED_TEST_BINARY).bin - -test_preprocessor_fixed: $(PREPROCESSOR_FIXED_TEST_BINARY) - $(TEST_SCRIPT) $(PREPROCESSOR_FIXED_TEST_BINARY) '~~~ALL TESTS PASSED~~~' - -$(PREPROCESSOR_1K_MICRO_TEST_BINARY): $(PREPROCESSOR_1K_MICRO_TEST_OBJS) $(MICROLITE_LIB_PATH) - @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) $(INCLUDES) \ - -o $(PREPROCESSOR_1K_MICRO_TEST_BINARY) $(PREPROCESSOR_1K_MICRO_TEST_OBJS) \ - $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) - -preprocessor_1k_micro_test: $(PREPROCESSOR_1K_MICRO_TEST_BINARY) -preprocessor_1k_micro_test_bin: $(PREPROCESSOR_1K_MICRO_TEST_BINARY).bin - -test_preprocessor_1k_micro: $(PREPROCESSOR_1K_MICRO_TEST_BINARY) - $(TEST_SCRIPT) $(PREPROCESSOR_1K_MICRO_TEST_BINARY) '~~~ALL TESTS PASSED~~~' - - -$(PREPROCESSOR_1K_CMSIS_TEST_BINARY): $(PREPROCESSOR_1K_CMSIS_TEST_OBJS) $(MICROLITE_LIB_PATH) - @mkdir -p $(dir $@) - $(CXX) $(CXXFLAGS) $(INCLUDES) \ - -o $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) $(PREPROCESSOR_1K_CMSIS_TEST_OBJS) \ - $(LIBFLAGS) $(MICROLITE_LIB_PATH) $(LDFLAGS) $(MICROLITE_LIBS) - -preprocessor_1k_cmsis_test: $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) -preprocessor_1k_cmsis_test_bin: $(PREPROCESSOR_1K_CMSIS_TEST_BINARY).bin - -test_preprocessor_1k_cmsis: $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) - $(TEST_SCRIPT) $(PREPROCESSOR_1K_CMSIS_TEST_BINARY) '~~~ALL TESTS PASSED~~~' - - -$(OBJDIR)arm_bitreversal2.o: - $(CXX) $(CXXFLAGS) $(INCLUDES) -c $(CMSIS_SRC_DIR)/TransformFunctions/arm_bitreversal2.S -o $(OBJDIR)arm_bitreversal2.o - $(BINDIR)%_test : $(OBJDIR)%_test.o $(MICROLITE_LIB_PATH) @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $(INCLUDES) \ @@ -310,8 +145,6 @@ $(BINDIR)%.bin: $(BINDIR)% @mkdir -p $(dir $@) $(OBJCOPY) $< $@ -O binary -$(info $(MICROLITE_TEST_TARGETS)) - test: test_micro_speech $(MICROLITE_TEST_TARGETS) # Gets rid of all generated files. diff --git a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh index 81f1583bdc..82c15e32f6 100755 --- a/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh +++ b/tensorflow/lite/experimental/micro/tools/make/download_dependencies.sh @@ -33,14 +33,11 @@ GEMMLOWP_URL="https://github.com/google/gemmlowp/archive/719139ce755a0f31cbf1c37 FLATBUFFERS_URL="https://github.com/google/flatbuffers/archive/1f5eae5d6a135ff6811724f6c57f911d1f46bb15.tar.gz" CMSIS_URL="https://github.com/ARM-software/CMSIS_5/archive/5.4.0.zip" STM32_BARE_LIB_URL="https://github.com/google/stm32_bare_lib/archive/c07d611fb0af58450c5a3e0ab4d52b47f99bc82d.zip" -<<<<<<< HEAD +SIFIVE_FE310_LIB_URL="https://github.com/sifive/freedom-e-sdk/archive/baeeb8fd497a99b3c141d7494309ec2e64f19bdf.zip" +RISCV_TOOLCHAIN_URL="https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-20181030-x86_64-linux-ubuntu14.tar.gz" AP3_URL="https://github.com/AmbiqMicro/TFLiteMicro_Apollo3/archive/dfbcef9a57276c087d95aab7cb234f1d4c9eaaba.zip" CUST_CMSIS_URL="https://github.com/AmbiqMicro/TFLiteMicro_CustCMSIS/archive/8f63966c5692e6a3a83956efd2e4aed77c4c9949.zip" GCC_EMBEDDED_URL="https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2" -======= -SIFIVE_FE310_LIB_URL="https://github.com/sifive/freedom-e-sdk/archive/baeeb8fd497a99b3c141d7494309ec2e64f19bdf.zip" -RISCV_TOOLCHAIN_URL="https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-20181030-x86_64-linux-ubuntu14.tar.gz" ->>>>>>> upstream/master download_and_extract() { local usage="Usage: download_and_extract URL DIR" diff --git a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc index de48d5d46f..6ed402a623 100644 --- a/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc +++ b/tensorflow/lite/experimental/micro/tools/make/targets/apollo3evb_makefile.inc @@ -101,7 +101,7 @@ ifeq ($(TARGET), apollo3evb) $(CMSIS_SRC_DIR)/StatisticsFunctions/arm_mean_q15.c \ $(CMSIS_SRC_DIR)/StatisticsFunctions/arm_max_q7.c - AP3_EXT_MICRO_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/apollo3_ext + AP3_EXT_MICRO_DIR := $(MAKEFILE_DIR)/downloads/apollo3_ext AP3_MICRO_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/apollo3 CMSIS_DIR := tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS CMSIS_EXT_DIR := $(MAKEFILE_DIR)/downloads/CMSIS_ext @@ -109,41 +109,6 @@ ifeq ($(TARGET), apollo3evb) MICRO_SPEECH_TEST_SRCS += \ $(AP3_MICRO_DIR)/_main.c - PREPROCESSOR_1K_CMSIS_TEST_SRCS := \ - $(PREPROCESSOR_1K_SRCS) \ - $(CMSIS_DIR)/preprocessor.cc \ - $(CMSIS_EXT_DIR)/arm_cmplx_mag_squared_q10p6.c \ - $(CMSIS_DIR)/hanning.c \ - $(AP3_EXT_MICRO_DIR)/system_apollo3.c \ - $(AP3_MICRO_DIR)/_main.c \ - $(CMSIS_SRCS) - - PREPROCESSOR_1K_MICRO_TEST_SRCS := \ - $(PREPROCESSOR_1K_SRCS) \ - $(AP3_MICRO_DIR)/../fixed_point/preprocessor.cc \ - $(AP3_EXT_MICRO_DIR)/system_apollo3.c \ - $(AP3_MICRO_DIR)/_main.c - - PUSHBUTTON_MICRO_SPEECH_TEST_SRCS := \ - $(AP3_MICRO_DIR)/../preprocessor.cc \ - $(AP3_MICRO_DIR)/pushbutton_main.c \ - $(AP3_MICRO_DIR)/pushbutton_test.cc \ - $(AP3_MICRO_DIR)/../tiny_conv_model_data.cc \ - $(APOLLO3_SDK)/devices/am_devices_led.c - - PUSHBUTTON_CMSIS_SPEECH_TEST_SRCS := \ - $(AP3_MICRO_DIR)/pushbutton_main.c \ - $(AP3_MICRO_DIR)/pushbutton_test.cc \ - $(AP3_MICRO_DIR)/../tiny_conv_model_data.cc \ - $(CMSIS_DIR)/preprocessor.cc \ - $(CMSIS_EXT_DIR)/arm_cmplx_mag_squared_q10p6.c \ - $(CMSIS_DIR)/hanning.c \ - $(APOLLO3_SDK)/devices/am_devices_led.c \ - $(CMSIS_SRCS) - - PREPROCESSOR_TEST_SRCS += \ - $(AP3_MICRO_DIR)/_main.c - TEST_SCRIPT := tensorflow/lite/experimental/log_test/test_apollo3evb_binary.sh # These are tests that don't currently work on the Apollo3 board. EXCLUDED_TESTS := \ -- GitLab From 3783db8af931de160e6997c7b103e87578efa1d2 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 13:37:19 -0800 Subject: [PATCH 0187/1765] Internal change PiperOrigin-RevId: 226386044 --- .../tools/ci_build/install/install_pi_python3_toolchain.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tensorflow/tools/ci_build/install/install_pi_python3_toolchain.sh b/tensorflow/tools/ci_build/install/install_pi_python3_toolchain.sh index 9d8e3df3b5..b6734e5522 100755 --- a/tensorflow/tools/ci_build/install/install_pi_python3_toolchain.sh +++ b/tensorflow/tools/ci_build/install/install_pi_python3_toolchain.sh @@ -25,5 +25,4 @@ apt-get install -y libpython3-all-dev:armhf echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add - apt-get update -rm -rf /usr/local/bin/bazel -apt-get install -y bazel python3 python3-numpy python3-dev python3-pip +apt-get install -y python3 python3-numpy python3-dev python3-pip -- GitLab From e9821ef1dfa03d883691019bb93dbfeb18641ec2 Mon Sep 17 00:00:00 2001 From: Allen Lavoie Date: Thu, 20 Dec 2018 13:37:48 -0800 Subject: [PATCH 0188/1765] Object-based checkpointing for Estimator Allows a tf.train.Checkpoint in Scaffold(saver=...), in which case it'll make a tf.train.Saver out of it. Restores will be based on fixed keys, and so are much more fragile than the usual object-based restores. That kind of fuzzy matching can be added later if there is demand. A followup CL will add the integration test with Estimator (which lives in the Estimator repository and so needs to wait on this CL syncing first). PiperOrigin-RevId: 226386123 --- .../python/training/checkpointable/base.py | 4 +++- .../python/training/checkpointable/util.py | 11 ++++++++--- .../python/training/monitored_session.py | 19 ++++++++++++++++++- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/tensorflow/python/training/checkpointable/base.py b/tensorflow/python/training/checkpointable/base.py index c752f9ca7e..1aaa85258c 100644 --- a/tensorflow/python/training/checkpointable/base.py +++ b/tensorflow/python/training/checkpointable/base.py @@ -162,8 +162,10 @@ class PythonStringStateSaveable(PythonStateSaveable): def freeze(self): """Create a frozen `SaveableObject` which saves the current state.""" + def _constant_state(): + return constant_op.constant(self._state_callback(), dtype=dtypes.string) return NoRestoreSaveable( - tensor=self._state_callback, + tensor=_constant_state, dtype=dtypes.string, name=self.name) diff --git a/tensorflow/python/training/checkpointable/util.py b/tensorflow/python/training/checkpointable/util.py index 7f70d973d0..c890a7f440 100644 --- a/tensorflow/python/training/checkpointable/util.py +++ b/tensorflow/python/training/checkpointable/util.py @@ -1391,8 +1391,8 @@ class CheckpointableSaver(object): name=base.OBJECT_GRAPH_PROTO_KEY)) return named_saveable_objects, graph_proto, feed_additions - def freeze(self, object_map=None, to_graph=None): - """Creates a `tf.train.Saver` with the current object graph frozen.""" + def gather_objects(self, object_map=None, to_graph=None): + """Creates SaveableObjects with the current object graph frozen.""" checkpointable_objects, path_to_root = ( _breadth_first_checkpointable_traversal(self._root_checkpointable)) if to_graph: @@ -1412,7 +1412,12 @@ class CheckpointableSaver(object): base.NoRestoreSaveable( tensor=object_graph_tensor, name=base.OBJECT_GRAPH_PROTO_KEY)) - return functional_saver.Saver(named_saveable_objects) + return named_saveable_objects + + def freeze(self, object_map=None, to_graph=None): + named_saveable_objects = self.gather_objects( + object_map=object_map, to_graph=to_graph) + return functional_saver.Saver(named_saveable_objects) def _save_cached_when_graph_building( self, diff --git a/tensorflow/python/training/monitored_session.py b/tensorflow/python/training/monitored_session.py index 072dbc1730..41a42bd269 100644 --- a/tensorflow/python/training/monitored_session.py +++ b/tensorflow/python/training/monitored_session.py @@ -41,6 +41,7 @@ from tensorflow.python.training import queue_runner from tensorflow.python.training import saver as training_saver from tensorflow.python.training import session_manager as sm from tensorflow.python.training import session_run_hook +from tensorflow.python.training.checkpointable import util as checkpointable_util from tensorflow.python.util import function_utils from tensorflow.python.util.tf_export import tf_export @@ -136,6 +137,16 @@ class Scaffold(object): string tensor containing a serialized `Summary` proto. saver: Optional `tf.train.Saver` object to use to save and restore variables. + + May also be a `tf.train.Checkpoint` object, in which case object-based + checkpoints are saved. This will also load some object-based checkpoints + saved from elsewhere, but that loading may be fragile since it uses + fixed keys rather than performing a full graph-based match. For example + if a variable has two paths from the `Checkpoint` object because two + `Model` objects share the `Layer` object that owns it, removing one + `Model` may change the keys and break checkpoint loading through this + API, whereas a graph-based match would match the variable through the + other `Model`. copy_from_scaffold: Optional scaffold object to copy fields from. Its fields will be overwritten by the provided fields in this function. """ @@ -216,7 +227,13 @@ class Scaffold(object): if self._saver is None: self._saver = training_saver._get_saver_or_default() # pylint: disable=protected-access # pylint: enable=g-long-lambda - self._saver.build() + if isinstance(self._saver, checkpointable_util.Checkpoint): + self._saver = training_saver.Saver( + var_list=checkpointable_util.CheckpointableSaver( + self._saver).gather_objects(), + sharded=True) + else: + self._saver.build() ops.get_default_graph().finalize() logging.info('Graph was finalized.') -- GitLab From 2f4d4da52f0c488417d7e917edaf1b7569b5e408 Mon Sep 17 00:00:00 2001 From: Allen Lavoie Date: Thu, 20 Dec 2018 14:05:51 -0800 Subject: [PATCH 0189/1765] Workaround for PartitionedCall trying and failing to run on TPUs when saving Just omits the function decorator for now. This is pretty terrible and we should fix it, but it will need some work on the TPU side. Spoke to iga@. Apparently the CPU annotations don't work because the function captures a resource which is on the TPU (and so the eager placer puts the call op on the TPU). One option is to then XLA-compile the function, although that fails right now because we're trying to save strings and XLA doesn't have a kernel for that. I should also follow up with TPU+checkpointing integration tests. PiperOrigin-RevId: 226390521 --- .../training/saving/functional_saver.py | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/tensorflow/python/training/saving/functional_saver.py b/tensorflow/python/training/saving/functional_saver.py index 74991b240c..51f618ddd3 100644 --- a/tensorflow/python/training/saving/functional_saver.py +++ b/tensorflow/python/training/saving/functional_saver.py @@ -55,22 +55,24 @@ class Saver(object): filename_tensor = array_ops.placeholder( shape=[], dtype=dtypes.string, name="saver_filename") # TODO(allenl): Add save and restore function names to the proto directly. - save_tensor = self.save(filename_tensor) - restore_op = self.restore(filename_tensor).op + signature = (tensor_spec.TensorSpec(shape=(), dtype=dtypes.string),) + # Autograph is off because of reference cycles which must be collected when + # a function is created and destroyed (as in tf.saved_model.save). It's also + # not necessary, so having it off may be slightly faster. + # + # TODO(b/121302372): We should be able to decorate save() and restore() + # unconditionally. + save_tensor = def_function.function( + self.save, input_signature=signature, autograph=False)(filename_tensor) + restore_op = def_function.function( + self.restore, input_signature=signature, autograph=False)( + filename_tensor).op return saver_pb2.SaverDef( filename_tensor_name=filename_tensor.name, save_tensor_name=save_tensor.name, restore_op_name=restore_op.name, version=saver_pb2.SaverDef.V2) - @def_function.function( - input_signature=(tensor_spec.TensorSpec(shape=(), dtype=dtypes.string),), - # Autograph is off because of reference cycles which must be collected - # when a function is created and destroyed (as in - # tf.saved_model.save). It's also not necessary, so having it off may be - # slightly faster. - autograph=False, - ) def save(self, file_prefix): """Save the saveable objects to a checkpoint with `file_prefix`. @@ -89,13 +91,11 @@ class Saver(object): tensor_names.append(spec.name) tensors.append(spec.tensor) tensor_slices.append(spec.slice_spec) - io_ops.save_v2(file_prefix, tensor_names, tensor_slices, tensors) - return file_prefix + with ops.device("cpu:0"): + with ops.control_dependencies([io_ops.save_v2( + file_prefix, tensor_names, tensor_slices, tensors)]): + return array_ops.identity(file_prefix) - @def_function.function( - input_signature=(tensor_spec.TensorSpec(shape=(), dtype=dtypes.string),), - autograph=False, - ) def restore(self, file_prefix): """Restore the saveable objects from a checkpoint with `file_prefix`. @@ -121,8 +121,11 @@ class Saver(object): file_prefix, tensor_names, tensor_slices, tensor_dtypes) structured_restored_tensors = nest.pack_sequence_as( tensor_structure, restored_tensors) + restore_ops = [] for saveable, restored_tensors in zip(self._saveable_objects, structured_restored_tensors): - saveable.restore(restored_tensors, - restored_shapes=None) - return file_prefix + restore_ops.append(saveable.restore(restored_tensors, + restored_shapes=None)) + with ops.device("cpu:0"): + with ops.control_dependencies(restore_ops): + return array_ops.identity(file_prefix) -- GitLab From 43cb5e8be4e954dba9abe74c472f732b5a7604d6 Mon Sep 17 00:00:00 2001 From: Rohan Jain Date: Thu, 20 Dec 2018 14:08:45 -0800 Subject: [PATCH 0190/1765] Disabling some parallel_for tests that fail in eager mode. PiperOrigin-RevId: 226390986 --- tensorflow/python/ops/parallel_for/control_flow_ops_test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tensorflow/python/ops/parallel_for/control_flow_ops_test.py b/tensorflow/python/ops/parallel_for/control_flow_ops_test.py index 933bddd8cc..8acb0d839c 100644 --- a/tensorflow/python/ops/parallel_for/control_flow_ops_test.py +++ b/tensorflow/python/ops/parallel_for/control_flow_ops_test.py @@ -27,6 +27,7 @@ from tensorflow.core.example import example_pb2 from tensorflow.core.example import feature_pb2 from tensorflow.python.client import session from tensorflow.python.eager import backprop +from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops @@ -104,6 +105,10 @@ class PForTest(test.TestCase): flags.FLAGS.op_conversion_fallback_to_while_loop = False def test_parallel_iterations(self): + # TODO(b/121334512): Remove this check once this passes in Eager mode. + if context.executing_eagerly(): + return + for parallel_iterations in [2, 3, 8, 10]: x = random_ops.random_uniform([8, 3]) -- GitLab From e0963c4073d6ab0a801878188063cd5b2f1f2f8d Mon Sep 17 00:00:00 2001 From: Mihai Maruseac Date: Thu, 20 Dec 2018 14:27:40 -0800 Subject: [PATCH 0191/1765] Add instructions to downgrade Bazel if greater than max_bazel_version. PiperOrigin-RevId: 226393897 --- configure.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/configure.py b/configure.py index acb92cbc1e..c588381d40 100644 --- a/configure.py +++ b/configure.py @@ -480,7 +480,9 @@ def check_bazel_version(min_version, max_version): if (curr_version_int > max_version_int and 'TF_IGNORE_MAX_BAZEL_VERSION' not in os.environ): print('Please downgrade your bazel installation to version %s or lower to ' - 'build TensorFlow!' % max_version) + 'build TensorFlow! To downgrade: download the installer for the old ' + 'version (from https://github.com/bazelbuild/bazel/releases) then ' + 'run the installer.' % max_version) sys.exit(1) return curr_version -- GitLab From 0c31fca446887430b7898b43ee89f8aaf82bede1 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 14:43:25 -0800 Subject: [PATCH 0192/1765] Allow forwarding inputs in eager PiperOrigin-RevId: 226396223 --- tensorflow/c/eager/BUILD | 56 +++++++++++++++++++ tensorflow/c/eager/c_api_experimental.cc | 23 ++++++++ tensorflow/c/eager/c_api_experimental.h | 32 +++++++++++ .../common_runtime/eager/eager_operation.cc | 5 ++ .../common_runtime/eager/eager_operation.h | 1 + .../core/common_runtime/eager/execute.cc | 29 +++++++--- .../common_runtime/eager/kernel_and_device.cc | 13 ++--- .../common_runtime/eager/kernel_and_device.h | 9 +-- .../eager/kernel_and_device_test.cc | 8 +-- .../common_runtime/eager/tensor_handle.cc | 8 ++- .../core/common_runtime/eager/tensor_handle.h | 3 +- 11 files changed, 161 insertions(+), 26 deletions(-) create mode 100644 tensorflow/c/eager/c_api_experimental.cc create mode 100644 tensorflow/c/eager/c_api_experimental.h diff --git a/tensorflow/c/eager/BUILD b/tensorflow/c/eager/BUILD index c34a84fcfe..9f09ad1fc3 100644 --- a/tensorflow/c/eager/BUILD +++ b/tensorflow/c/eager/BUILD @@ -148,6 +148,62 @@ tf_cuda_cc_test( ], ) +tf_cuda_library( + name = "c_api_experimental", + srcs = [ + "c_api_experimental.cc", + ], + hdrs = ["c_api_experimental.h"], + copts = tf_copts() + tfe_xla_copts(), + visibility = ["//visibility:public"], + deps = select({ + "//tensorflow:android": [ + "//tensorflow/core:android_tensorflow_lib_lite", + ], + "//conditions:default": [ + ":c_api", + ":c_api_internal", + "//tensorflow/c:c_api", + "//tensorflow/c:c_api_internal", + "//tensorflow/core:core_cpu", + "//tensorflow/core/common_runtime/eager:attr_builder", + "//tensorflow/core/common_runtime/eager:context", + "//tensorflow/core/common_runtime/eager:eager_executor", + "//tensorflow/core/common_runtime/eager:execute", + "//tensorflow/core/common_runtime/eager:kernel_and_device", + "//tensorflow/core/common_runtime/eager:tensor_handle", + "//tensorflow/core/common_runtime/eager:copy_to_device_node", + "//tensorflow/core:core_cpu_internal", + "//tensorflow/core:framework", + "//tensorflow/core:framework_internal", + "//tensorflow/core:lib", + "//tensorflow/core:lib_internal", + "//tensorflow/core:protos_all_cc", + ], + }) + select({ + "//tensorflow:with_xla_support": [ + "//tensorflow/compiler/tf2xla:xla_compiler", + "//tensorflow/compiler/jit", + "//tensorflow/compiler/jit:xla_device", + ], + "//conditions:default": [], + }) + [ + "@com_google_absl//absl/memory", + "//tensorflow/core/common_runtime/eager:eager_operation", + "//tensorflow/core/distributed_runtime/eager:eager_client", + "//tensorflow/core/distributed_runtime/rpc/eager:grpc_eager_client", + "//tensorflow/core/distributed_runtime/rpc:grpc_channel", + "//tensorflow/core/distributed_runtime/rpc:grpc_server_lib", + "//tensorflow/core/distributed_runtime/rpc:grpc_worker_cache", + "//tensorflow/core/distributed_runtime/rpc:grpc_worker_service", + "//tensorflow/core/distributed_runtime/rpc:rpc_rendezvous_mgr", + "//tensorflow/core/distributed_runtime:remote_device", + "//tensorflow/core/distributed_runtime:server_lib", + "//tensorflow/core/distributed_runtime:worker_env", + "//tensorflow/core:gpu_runtime", + ], +) + cc_library( name = "tape", hdrs = ["tape.h"], diff --git a/tensorflow/c/eager/c_api_experimental.cc b/tensorflow/c/eager/c_api_experimental.cc new file mode 100644 index 0000000000..3461d81b93 --- /dev/null +++ b/tensorflow/c/eager/c_api_experimental.cc @@ -0,0 +1,23 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/c/eager/c_api_experimental.h" + +#include "tensorflow/c/c_api.h" +#include "tensorflow/c/eager/c_api_internal.h" + +void TFE_OpConsumeInput(TFE_Op* op, TFE_TensorHandle* h, TF_Status* status) { + op->operation.ConsumeInput(h->handle); +} diff --git a/tensorflow/c/eager/c_api_experimental.h b/tensorflow/c/eager/c_api_experimental.h new file mode 100644 index 0000000000..4ee6c066ee --- /dev/null +++ b/tensorflow/c/eager/c_api_experimental.h @@ -0,0 +1,32 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_C_EAGER_C_API_EXPERIMENTAL_H_ +#define TENSORFLOW_C_EAGER_C_API_EXPERIMENTAL_H_ + +#include "tensorflow/c/c_api.h" +#include "tensorflow/c/eager/c_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +TF_CAPI_EXPORT extern void TFE_OpConsumeInput(TFE_Op* op, TFE_TensorHandle* h, + TF_Status* status); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // TENSORFLOW_C_EAGER_C_API_EXPERIMENTAL_H_ diff --git a/tensorflow/core/common_runtime/eager/eager_operation.cc b/tensorflow/core/common_runtime/eager/eager_operation.cc index 381b05ada8..0718e68932 100644 --- a/tensorflow/core/common_runtime/eager/eager_operation.cc +++ b/tensorflow/core/common_runtime/eager/eager_operation.cc @@ -30,4 +30,9 @@ void EagerOperation::AddInput(tensorflow::TensorHandle* h) { inputs_.push_back(h); attrs_.NumInputs(static_cast(inputs_.size())); } + +void EagerOperation::ConsumeInput(tensorflow::TensorHandle* h) { + inputs_.push_back(h); + attrs_.NumInputs(static_cast(inputs_.size())); +} } // namespace tensorflow diff --git a/tensorflow/core/common_runtime/eager/eager_operation.h b/tensorflow/core/common_runtime/eager/eager_operation.h index 935ca7f9aa..5a9e1f0292 100644 --- a/tensorflow/core/common_runtime/eager/eager_operation.h +++ b/tensorflow/core/common_runtime/eager/eager_operation.h @@ -53,6 +53,7 @@ class EagerOperation { return &inputs_; } void AddInput(tensorflow::TensorHandle* h); + void ConsumeInput(tensorflow::TensorHandle* h); const tensorflow::string& Name() const { return name_; } const tensorflow::AttrTypeMap* AttrTypes() const { return attr_types_; } diff --git a/tensorflow/core/common_runtime/eager/execute.cc b/tensorflow/core/common_runtime/eager/execute.cc index 783baa96c9..79806c3c73 100644 --- a/tensorflow/core/common_runtime/eager/execute.cc +++ b/tensorflow/core/common_runtime/eager/execute.cc @@ -712,22 +712,37 @@ Status EagerExecute(EagerContext* ctx, Device* device, std::vector outputs(1); const MemoryTypeVector* output_memory_types = nullptr; output_memory_types = &kernel->kernel()->output_memory_types(); - std::vector inputs(op_inputs.size()); + + // If there are multiple references to a TensorHandle in 'op_inputs' we must + // increment the reference count of the corresponding Tensor or risk it being + // overwritten during kernel execution. The reference count is incremented + // below when we insert a copy of the Tensor into protected_tensors, and will + // be decremented once execution is complete. + std::vector protected_tensors; for (int i = 0; i < op_inputs.size(); ++i) { - const Tensor* input_tensor = nullptr; - TF_RETURN_IF_ERROR(op_inputs[i]->Tensor(&input_tensor)); - inputs[i] = *input_tensor; + if (!op_inputs[i]->RefCountIsOne()) { + const Tensor* input_tensor = nullptr; + TF_RETURN_IF_ERROR(op_inputs[i]->Tensor(&input_tensor)); + protected_tensors.push_back(*input_tensor); + } } + + gtl::InlinedVector input_vector(op_inputs.size()); + for (int i = 0; i < op_inputs.size(); ++i) { + TF_RETURN_IF_ERROR(op_inputs[i]->TensorValue(&input_vector[i])); + } + // TODO(apassos) figure out how to record stats for ops which are a part of // functions. // TODO(agarwal): change Run to take vector of handles ? ScopedStepContainer* container = ctx->StepContainer(); if (container == nullptr) { - TF_RETURN_IF_ERROR(kernel->Run(&inputs, &outputs, maybe_stats, + TF_RETURN_IF_ERROR(kernel->Run(input_vector, &outputs, maybe_stats, maybe_step_stats, graph_collector)); } else { - TF_RETURN_IF_ERROR(kernel->Run(container, &inputs, &outputs, maybe_stats, - maybe_step_stats, graph_collector)); + TF_RETURN_IF_ERROR(kernel->Run(container, input_vector, &outputs, + maybe_stats, maybe_step_stats, + graph_collector)); } if (maybe_stats != nullptr) { int64 nanos = Env::Default()->NowNanos(); diff --git a/tensorflow/core/common_runtime/eager/kernel_and_device.cc b/tensorflow/core/common_runtime/eager/kernel_and_device.cc index 317e9a1607..354f96c440 100644 --- a/tensorflow/core/common_runtime/eager/kernel_and_device.cc +++ b/tensorflow/core/common_runtime/eager/kernel_and_device.cc @@ -57,7 +57,7 @@ Status KernelAndDevice::Init(const NodeDef& ndef, FunctionLibraryRuntime* flr, return OutputTypesForNode(ndef, *op_def, &out->output_dtypes_); } -Status KernelAndDevice::Run(std::vector* inputs, +Status KernelAndDevice::Run(const gtl::InlinedVector& inputs, std::vector* outputs, NodeExecStats* stats, StepStats* step_stats, GraphCollector* graph_collector) { @@ -69,15 +69,10 @@ Status KernelAndDevice::Run(std::vector* inputs, } Status KernelAndDevice::Run(ScopedStepContainer* step_container, - std::vector* inputs, + const gtl::InlinedVector& inputs, std::vector* outputs, NodeExecStats* stats, StepStats* step_stats, GraphCollector* graph_collector) { - gtl::InlinedVector input_vector; - for (Tensor& t : *inputs) { - input_vector.push_back(TensorValue(&t)); - } - std::vector out_attrs(kernel_->num_outputs()); for (size_t i = 0; i < out_attrs.size(); ++i) { out_attrs[i].set_on_host(kernel_->output_memory_types()[i] == @@ -85,7 +80,7 @@ Status KernelAndDevice::Run(ScopedStepContainer* step_container, } gtl::InlinedVector input_device_contexts; - for (int i = 0; i < inputs->size(); i++) { + for (int i = 0; i < inputs.size(); i++) { DeviceContext* device_context = nullptr; if (device_->tensorflow_gpu_device_info() != nullptr) { device_context = device_->tensorflow_gpu_device_info()->default_context; @@ -96,7 +91,7 @@ Status KernelAndDevice::Run(ScopedStepContainer* step_container, OpKernelContext::Params params; params.device = device_; params.frame_iter = FrameAndIter(0, 0); - params.inputs = &input_vector; + params.inputs = &inputs; params.op_kernel = kernel_.get(); params.resource_manager = device_->resource_manager(); params.output_attr_array = gtl::vector_as_array(&out_attrs); diff --git a/tensorflow/core/common_runtime/eager/kernel_and_device.h b/tensorflow/core/common_runtime/eager/kernel_and_device.h index ee430b7fc7..f7a5b76518 100644 --- a/tensorflow/core/common_runtime/eager/kernel_and_device.h +++ b/tensorflow/core/common_runtime/eager/kernel_and_device.h @@ -68,11 +68,12 @@ class KernelAndDevice { collective_executor_(std::move(collective_executor)) {} // TODO(ashankar): Handle list-valued inputs. - Status Run(std::vector* inputs, std::vector* outputs, - NodeExecStats* stats, StepStats* step_stats, - GraphCollector* graph_collector); + Status Run(const gtl::InlinedVector& inputs, + std::vector* outputs, NodeExecStats* stats, + StepStats* step_stats, GraphCollector* graph_collector); - Status Run(ScopedStepContainer* step_container, std::vector* inputs, + Status Run(ScopedStepContainer* step_container, + const gtl::InlinedVector& inputs, std::vector* outputs, NodeExecStats* stats, StepStats* step_stats, GraphCollector* graph_collector); diff --git a/tensorflow/core/common_runtime/eager/kernel_and_device_test.cc b/tensorflow/core/common_runtime/eager/kernel_and_device_test.cc index 3ffed3ce32..8d6db96779 100644 --- a/tensorflow/core/common_runtime/eager/kernel_and_device_test.cc +++ b/tensorflow/core/common_runtime/eager/kernel_and_device_test.cc @@ -118,9 +118,9 @@ BENCHMARK(BM_KernelAndDeviceInit); void BM_KernelAndDeviceRun(int iters) { tensorflow::testing::StopTiming(); Tensor t(Input({{1.0f, 2.0f}, {3.0f, 4.0f}}).tensor()); - std::vector inputs; - inputs.push_back(t); - inputs.push_back(t); + gtl::InlinedVector inputs; + inputs.push_back(TensorValue(&t)); + inputs.push_back(TensorValue(&t)); std::vector outputs; NodeDef ndef(AttrBuilder("MatMul") .Set("T", DT_FLOAT) @@ -134,7 +134,7 @@ void BM_KernelAndDeviceRun(int iters) { nullptr, &kernel)); tensorflow::testing::StartTiming(); for (int i = 0; i < iters; ++i) { - TF_CHECK_OK(kernel.Run(&inputs, &outputs, nullptr, nullptr, nullptr)); + TF_CHECK_OK(kernel.Run(inputs, &outputs, nullptr, nullptr, nullptr)); } } BENCHMARK(BM_KernelAndDeviceRun); diff --git a/tensorflow/core/common_runtime/eager/tensor_handle.cc b/tensorflow/core/common_runtime/eager/tensor_handle.cc index 0acd160936..47a856a36e 100644 --- a/tensorflow/core/common_runtime/eager/tensor_handle.cc +++ b/tensorflow/core/common_runtime/eager/tensor_handle.cc @@ -27,7 +27,6 @@ limitations under the License. #include "tensorflow/core/common_runtime/device_factory.h" #include "tensorflow/core/common_runtime/eager/context.h" #include "tensorflow/core/common_runtime/eager/eager_executor.h" -#include "tensorflow/core/common_runtime/eager/kernel_and_device.h" #include "tensorflow/core/common_runtime/function.h" #include "tensorflow/core/common_runtime/rendezvous_mgr.h" #include "tensorflow/core/framework/rendezvous.h" @@ -79,6 +78,13 @@ Status TensorHandle::Tensor(const tensorflow::Tensor** t) { return Status::OK(); } +Status TensorHandle::TensorValue(tensorflow::TensorValue* t) { + TF_RETURN_IF_ERROR(WaitReady()); + DCHECK(IsReady()); + *t = tensorflow::TensorValue(&tensor_); + return Status::OK(); +} + Status TensorHandle::TensorAndDevice(const tensorflow::Tensor** tensor, tensorflow::Device** device, tensorflow::Device** op_device) { diff --git a/tensorflow/core/common_runtime/eager/tensor_handle.h b/tensorflow/core/common_runtime/eager/tensor_handle.h index 0fdd31ab5f..1c81087f1f 100644 --- a/tensorflow/core/common_runtime/eager/tensor_handle.h +++ b/tensorflow/core/common_runtime/eager/tensor_handle.h @@ -27,7 +27,6 @@ limitations under the License. #include "tensorflow/core/common_runtime/device_factory.h" #include "tensorflow/core/common_runtime/eager/context.h" #include "tensorflow/core/common_runtime/eager/eager_executor.h" -#include "tensorflow/core/common_runtime/eager/kernel_and_device.h" #include "tensorflow/core/common_runtime/function.h" #include "tensorflow/core/common_runtime/rendezvous_mgr.h" #include "tensorflow/core/framework/rendezvous.h" @@ -102,6 +101,8 @@ class TensorHandle : public core::RefCounted { Status Tensor(const tensorflow::Tensor** t); + Status TensorValue(tensorflow::TensorValue* t); + tensorflow::Device* device() const { return device_; } tensorflow::Device* op_device() const { return op_device_; } -- GitLab From b71a6b031adf0da61db59312847cccb675771b84 Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Thu, 20 Dec 2018 14:51:38 -0800 Subject: [PATCH 0193/1765] Fix input size, add comment --- tensorflow/core/grappler/optimizers/constant_folding.cc | 7 ++++--- tensorflow/core/grappler/optimizers/constant_folding.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tensorflow/core/grappler/optimizers/constant_folding.cc b/tensorflow/core/grappler/optimizers/constant_folding.cc index 5a053d3a89..a5f6f57747 100644 --- a/tensorflow/core/grappler/optimizers/constant_folding.cc +++ b/tensorflow/core/grappler/optimizers/constant_folding.cc @@ -1010,7 +1010,7 @@ Status ConstantFolding::EvaluateOneFoldable(const NodeDef& node, } }); - size_t input_size = 0; + size_t total_inputs_size = 0; for (const auto& input : node.input()) { const TensorId input_tensor = ParseTensorName(input); if (input_tensor.index() < 0) { @@ -1025,10 +1025,10 @@ Status ConstantFolding::EvaluateOneFoldable(const NodeDef& node, } TF_RETURN_IF_ERROR(CheckAttrExists(*input_node, "value")); const TensorProto& raw_val = input_node->attr().at("value").tensor(); - input_size += raw_val.tensor_content().size(); Tensor* value = new Tensor(raw_val.dtype(), raw_val.tensor_shape()); CHECK(value->FromProto(raw_val)); inputs.emplace_back(value); + total_inputs_size += value->TotalBytes(); } TF_RETURN_IF_ERROR(EvaluateNode(node, inputs, &output_tensors)); @@ -1043,7 +1043,8 @@ Status ConstantFolding::EvaluateOneFoldable(const NodeDef& node, node_name = strings::StrCat(node_name, "-", i); } if (output_tensors[i].tensor) { - Status s = CreateNodeDef(node_name, output_tensors[i], &outputs->at(i), input_size); + Status s = CreateNodeDef(node_name, output_tensors[i], &outputs->at(i), + total_inputs_size); if (!s.ok()) { *result_too_large = true; return s; diff --git a/tensorflow/core/grappler/optimizers/constant_folding.h b/tensorflow/core/grappler/optimizers/constant_folding.h index 8843ac161f..58a962ba9b 100644 --- a/tensorflow/core/grappler/optimizers/constant_folding.h +++ b/tensorflow/core/grappler/optimizers/constant_folding.h @@ -35,6 +35,8 @@ const char kConstantFoldingCtrl[] = "ConstantFoldingCtrl"; // Constant folding optimization for a graph. class ConstantFolding : public GraphOptimizer { public: + // The size limit will only be considered if the newly created node is greater + // than input_size (optional). static Status CreateNodeDef(const string& name, const TensorValue& tensor, NodeDef* node, size_t input_size = 0); static string AddControlDependency(const string& input_name, GraphDef* graph, -- GitLab From 795f9cbf91d6a447a115c477f815adcc71944619 Mon Sep 17 00:00:00 2001 From: Sourabh Bajaj Date: Thu, 20 Dec 2018 14:44:36 -0800 Subject: [PATCH 0194/1765] Remove num_cores from the TPU Strategy constructor as that is not supported or correct. PiperOrigin-RevId: 226396428 --- .../contrib/distribute/python/tpu_strategy.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/tensorflow/contrib/distribute/python/tpu_strategy.py b/tensorflow/contrib/distribute/python/tpu_strategy.py index e081a735e2..1139f494d7 100644 --- a/tensorflow/contrib/distribute/python/tpu_strategy.py +++ b/tensorflow/contrib/distribute/python/tpu_strategy.py @@ -126,8 +126,7 @@ class TPUStrategy(distribute_lib.DistributionStrategy): def __init__(self, tpu_cluster_resolver=None, - steps_per_run=None, - num_cores=None): + steps_per_run=None): """Initializes the TPUStrategy object. Args: @@ -138,11 +137,9 @@ class TPUStrategy(distribute_lib.DistributionStrategy): metrics, summaries etc. This parameter is only used when Distribution Strategy is used with estimator or keras. - num_cores: Number of cores to use on the TPU. If None specified, then - auto-detect the cores and topology of the TPU system. """ super(TPUStrategy, self).__init__(TPUExtended( - self, tpu_cluster_resolver, steps_per_run, num_cores)) + self, tpu_cluster_resolver, steps_per_run)) @property def steps_per_run(self): @@ -161,8 +158,7 @@ class TPUExtended(distribute_lib.DistributionStrategyExtended): def __init__(self, container_strategy, tpu_cluster_resolver=None, - steps_per_run=None, - num_cores=None): + steps_per_run=None): super(TPUExtended, self).__init__(container_strategy) if tpu_cluster_resolver is None: @@ -175,8 +171,6 @@ class TPUExtended(distribute_lib.DistributionStrategyExtended): self._tpu_cluster_resolver = tpu_cluster_resolver self._tpu_metadata = get_tpu_system_metadata(self._tpu_cluster_resolver) - # TODO(sourabhbajaj): Change this from num_cores to metadata_override - self._num_cores_override = num_cores # TODO(jhseu): Switch to DeviceAssignment to support pods and model # parallelism. @@ -570,7 +564,7 @@ class TPUExtended(distribute_lib.DistributionStrategyExtended): @property def _num_replicas_in_sync(self): - return self._num_cores_override or self._tpu_metadata.num_cores + return self._tpu_metadata.num_cores @property def experimental_between_graph(self): -- GitLab From d5216948d1a4fcf234102448e19013ee84b61c51 Mon Sep 17 00:00:00 2001 From: Ayush Dubey Date: Thu, 20 Dec 2018 14:51:19 -0800 Subject: [PATCH 0195/1765] Enable a deterministic and sequential execution order of potentially concurrent collective instances. Before this change, collective op instances that were concurrent could execute in a random, overlapping order across devices and workers. This change introduces a mechanism to enforce the same execution order of collective instances across devices and workers. It first determines dependencies between collective op nodes in the graph. For each pair of collective instances that do not depend on each other, this change adds an arbitrary but deterministic control edge between the nodes. This ordering only kicks in if `collective_deterministic_sequential_execution` is true in ConfigProto. PiperOrigin-RevId: 226397542 --- tensorflow/core/BUILD | 23 +++ .../core/common_runtime/direct_session.cc | 7 + tensorflow/core/graph/collective_order.cc | 95 ++++++++++ tensorflow/core/graph/collective_order.h | 30 +++ .../core/graph/collective_order_test.cc | 174 ++++++++++++++++++ tensorflow/core/protobuf/config.proto | 4 + tensorflow/python/ops/collective_ops_test.py | 25 +++ ...nsorflow.-config-proto.-experimental.pbtxt | 8 +- .../golden/v1/tensorflow.-config-proto.pbtxt | 6 + 9 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 tensorflow/core/graph/collective_order.cc create mode 100644 tensorflow/core/graph/collective_order.h create mode 100644 tensorflow/core/graph/collective_order_test.cc diff --git a/tensorflow/core/BUILD b/tensorflow/core/BUILD index 8bf1480d33..f7eab3e359 100644 --- a/tensorflow/core/BUILD +++ b/tensorflow/core/BUILD @@ -2772,6 +2772,7 @@ cc_library( # in this library. GRAPH_HDRS = [ "graph/algorithm.h", + "graph/collective_order.h", "graph/colors.h", "graph/control_flow.h", "graph/costmodel.h", @@ -2798,6 +2799,7 @@ tf_cuda_library( name = "graph", srcs = [ "graph/algorithm.cc", + "graph/collective_order.cc", "graph/colors.cc", "graph/control_flow.cc", "graph/costmodel.cc", @@ -3842,6 +3844,27 @@ tf_cc_test( ], ) +tf_cc_tests( + name = "collective_order_test", + size = "small", + srcs = [ + "graph/collective_order_test.cc", + ], + deps = [ + ":core", + ":core_cpu", + ":core_cpu_internal", + ":framework", + ":framework_internal", + ":lib", + ":lib_internal", + ":ops", + ":protos_all_cc", + ":test", + "@com_google_googletest//:gtest_main", + ], +) + tf_cc_tests_gpu( name = "ring_reducer_test", size = "medium", diff --git a/tensorflow/core/common_runtime/direct_session.cc b/tensorflow/core/common_runtime/direct_session.cc index 0434ca47b6..51b2c68c76 100644 --- a/tensorflow/core/common_runtime/direct_session.cc +++ b/tensorflow/core/common_runtime/direct_session.cc @@ -45,6 +45,7 @@ limitations under the License. #include "tensorflow/core/framework/tensor.h" #include "tensorflow/core/framework/versions.pb.h" #include "tensorflow/core/graph/algorithm.h" +#include "tensorflow/core/graph/collective_order.h" #include "tensorflow/core/graph/graph.h" #include "tensorflow/core/graph/graph_constructor.h" #include "tensorflow/core/graph/graph_partition.h" @@ -1519,6 +1520,12 @@ Status DirectSession::CreateGraphs( CopyGraph(*execution_state->full_graph(), run_state_args->graph.get()); } + // Make collective execution order deterministic if needed. + if (options_.config.experimental() + .collective_deterministic_sequential_execution()) { + TF_RETURN_IF_ERROR(OrderCollectives(&client_graph->graph)); + } + // Partition the graph across devices. PartitionOptions popts; popts.node_to_loc = [](const Node* node) { diff --git a/tensorflow/core/graph/collective_order.cc b/tensorflow/core/graph/collective_order.cc new file mode 100644 index 0000000000..bd8fd767ee --- /dev/null +++ b/tensorflow/core/graph/collective_order.cc @@ -0,0 +1,95 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/core/graph/collective_order.h" + +#include "tensorflow/core/graph/algorithm.h" + +namespace tensorflow { + +Status OrderCollectives(Graph* graph) { + // `instance_keys[i]` corresponds to `collective_nodes[i]` + std::vector collective_nodes; + std::vector instance_keys; + // node -> set of collectives on which node depends. + std::unordered_map> node_dependencies; + Status s; + + // Algorithm: do Reverse DFS starting at sink. `node_leave` is called when + // all parents of `node` have been visited. At that point, the collectives + // on which this node depends on are up to date. For this node's children, + // add all these collectives. Also, if this node is collective, add as a + // dependency for the children. + auto node_leave = [&collective_nodes, &instance_keys, &node_dependencies, + &s](Node* node) { + int32 instance_key; + if (node->IsCollective()) { + Status get_attr_status = + GetNodeAttr(node->attrs(), "instance_key", &instance_key); + s.Update(get_attr_status); + collective_nodes.push_back(node); + instance_keys.push_back(instance_key); + VLOG(2) << "collective node " << node->DebugString(); + } + const auto& node_deps = node_dependencies[node]; + for (const Edge* out_edge : node->out_edges()) { + auto& child_deps = node_dependencies[out_edge->dst()]; + child_deps.insert(node_deps.begin(), node_deps.end()); + if (node->IsCollective() && s.ok()) { + child_deps.insert(instance_key); + } + } + }; + ReverseDFS(*graph, nullptr, node_leave); + if (!s.ok()) return s; + + // For all pairs of collective nodes n1 and n2 on the same device, if n1 does + // not depend on n2 and n2 does not depend on n1, then they are potentially + // concurrent. Add an arbitrary, deterministic control edge between them. + for (int i = 0; i < collective_nodes.size() - 1; i++) { + if (!collective_nodes[i]->IsCollective()) { + return errors::Internal("Unexpected node ", + collective_nodes[i]->DebugString()); + } + const auto& deps_i = node_dependencies[collective_nodes[i]]; + for (int j = i + 1; j < collective_nodes.size(); j++) { + if (collective_nodes[i]->requested_device() != + collective_nodes[j]->requested_device()) { + continue; + } + if (instance_keys[i] == instance_keys[j]) { + return errors::Internal("Unexpected same instance_key ", + instance_keys[i], + " on 2 nodes with the same device ", + collective_nodes[i]->requested_device()); + } + const auto& deps_j = node_dependencies[collective_nodes[j]]; + if (deps_i.find(instance_keys[j]) == deps_i.end() && + deps_j.find(instance_keys[i]) == deps_j.end()) { + int src_idx = instance_keys[i] < instance_keys[j] ? i : j; + int dst_idx = instance_keys[i] < instance_keys[j] ? j : i; + Node* src_node = collective_nodes[src_idx]; + Node* dst_node = collective_nodes[dst_idx]; + VLOG(1) << "Adding control edge from node " << src_node->name() + << " instance " << instance_keys[src_idx] << " to node " + << dst_node->name() << " instance " << instance_keys[dst_idx]; + graph->AddControlEdge(src_node, dst_node); + } + } + } + + return Status::OK(); +} + +} // namespace tensorflow diff --git a/tensorflow/core/graph/collective_order.h b/tensorflow/core/graph/collective_order.h new file mode 100644 index 0000000000..66210a2ab4 --- /dev/null +++ b/tensorflow/core/graph/collective_order.h @@ -0,0 +1,30 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_CORE_GRAPH_COLLECTIVE_ORDER_H_ +#define TENSORFLOW_CORE_GRAPH_COLLECTIVE_ORDER_H_ + +#include "tensorflow/core/graph/graph.h" + +namespace tensorflow { + +// Introduces control edges between potentially concurrent CollectiveOps to make +// their execution order deterministic. This may be used to execute collectives +// in the same order across all workers in a distributed execution, if all +// workers are executing the same graph. +Status OrderCollectives(Graph* graph); + +} // namespace tensorflow + +#endif // TENSORFLOW_CORE_GRAPH_COLLECTIVE_ORDER_H_ diff --git a/tensorflow/core/graph/collective_order_test.cc b/tensorflow/core/graph/collective_order_test.cc new file mode 100644 index 0000000000..b0ced7b007 --- /dev/null +++ b/tensorflow/core/graph/collective_order_test.cc @@ -0,0 +1,174 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/core/graph/collective_order.h" + +#include +#include "tensorflow/core/framework/node_def_builder.h" +#include "tensorflow/core/graph/graph_def_builder.h" +#include "tensorflow/core/graph/graph_def_builder_util.h" +#include "tensorflow/core/lib/core/status_test_util.h" +#include "tensorflow/core/platform/test.h" + +namespace tensorflow { +namespace { + +using ::testing::UnorderedElementsAreArray; + +REGISTER_OP("TestParams").Output("o: float"); + +// Verifies that the list of collective nodes in `graph` matches +// `expected_collective_nodes`, and that the list of control edges between these +// collective nodes matches `expected_collective_control_edges`. +void VerifyGraph(const Graph& graph, + const std::vector& expected_collective_nodes, + const std::vector>& + expected_collective_control_edges) { + std::vector actual_collective_nodes; + std::vector> actual_collective_control_edges; + for (const Node* src : graph.nodes()) { + if (!src->IsCollective()) { + continue; + } + actual_collective_nodes.push_back(src->name()); + for (const Edge* edge : src->out_edges()) { + VLOG(2) << "collective edge " << edge->src()->name() << " -> " + << edge->dst()->name(); + // Add all control edges found except those to `_SINK`. + if (!edge->IsControlEdge() || edge->dst()->name() == "_SINK") { + continue; + } + actual_collective_control_edges.emplace_back(src->name(), + edge->dst()->name()); + } + } + EXPECT_THAT(actual_collective_nodes, + UnorderedElementsAreArray(expected_collective_nodes)); + EXPECT_THAT(actual_collective_control_edges, + UnorderedElementsAreArray(expected_collective_control_edges)); +} + +Node* CollectiveReduceNode(GraphDefBuilder* builder, Node* input, + const string& name, const string& device, + int instance_key) { + Node* collective_node = + ops::UnaryOp("CollectiveReduce", input, + builder->opts() + .WithName(name) + .WithDevice(device) + .WithAttr("T", DT_FLOAT) + .WithAttr("group_size", 2) + .WithAttr("group_key", 1) + .WithAttr("instance_key", instance_key) + .WithAttr("merge_op", "Add") + .WithAttr("final_op", "Id") + .WithAttr("subdiv_offsets", {1})); + return collective_node; +} + +// Initialize the following graph: +// +// (cpu0) (cpu1) +// a b +// | | +// c1 c1 +// | | +// id id +// / \ / \ +// c2 c3 c2 c3 +// +// Here ci denotes a collective node with `instance_key` i. `a` and `b` are +// inputs, `id` is identity node. +std::unique_ptr InitGraph() { + GraphDefBuilder builder(GraphDefBuilder::kFailImmediately); + const string dev0 = "/job:localhost/replica:0/task:0/device:CPU:0"; + const string dev1 = "/job:localhost/replica:0/task:0/device:CPU:1"; + Node* a = ops::SourceOp("TestParams", + builder.opts().WithName("a").WithDevice(dev0)); + Node* b = ops::SourceOp("TestParams", + builder.opts().WithName("b").WithDevice(dev1)); + Node* c1_0 = CollectiveReduceNode(&builder, a, "c1_0", dev0, 1); + Node* c1_1 = CollectiveReduceNode(&builder, b, "c1_1", dev1, 1); + Node* id0 = ops::UnaryOp( + "Identity", c1_0, + builder.opts().WithName("id0").WithDevice(dev0).WithAttr("T", DT_FLOAT)); + Node* id1 = ops::UnaryOp( + "Identity", c1_1, + builder.opts().WithName("id1").WithDevice(dev1).WithAttr("T", DT_FLOAT)); + CollectiveReduceNode(&builder, id0, "c2_0", dev0, 2); + CollectiveReduceNode(&builder, id1, "c2_1", dev1, 2); + CollectiveReduceNode(&builder, id0, "c3_0", dev0, 3); + CollectiveReduceNode(&builder, id1, "c3_1", dev1, 3); + + std::unique_ptr graph = absl::make_unique(OpRegistry::Global()); + Status s = GraphDefBuilderToGraph(builder, graph.get()); + if (!s.ok()) { + LOG(FATAL) << "Error building graph " << s; + } + return graph; +} + +// Tests that in the graph created by `InitGraph`, exactly 2 control edges are +// added after calling `OrderCollectives`: c2_0 -> c3_0 and c2_1 -> c3_1. +TEST(CollectiveOrderTest, SimpleOrder) { + std::unique_ptr graph = InitGraph(); + TF_EXPECT_OK(OrderCollectives(graph.get())); + VerifyGraph(*graph, {"c1_0", "c1_1", "c2_0", "c2_1", "c3_0", "c3_1"}, + {{"c2_0", "c3_0"}, {"c2_1", "c3_1"}}); +} + +// Initialize the following graph: +// +// a +// | +// c1 +// / \ +// c4 id +// / \ +// c2 c3 +// +// Here ci denotes a collective node with `instance_key` i. `a` is an input, +// `id` is identity node. +std::unique_ptr InitGraph2() { + GraphDefBuilder builder(GraphDefBuilder::kFailImmediately); + const string dev0 = "/job:localhost/replica:0/task:0/device:CPU:0"; + Node* a = ops::SourceOp("TestParams", + builder.opts().WithName("a").WithDevice(dev0)); + Node* c1 = CollectiveReduceNode(&builder, a, "c1", dev0, 1); + CollectiveReduceNode(&builder, c1, "c4", dev0, 4); + Node* id = ops::UnaryOp( + "Identity", c1, + builder.opts().WithName("id").WithDevice(dev0).WithAttr("T", DT_FLOAT)); + CollectiveReduceNode(&builder, id, "c2", dev0, 2); + CollectiveReduceNode(&builder, id, "c3", dev0, 3); + + std::unique_ptr graph = absl::make_unique(OpRegistry::Global()); + Status s = GraphDefBuilderToGraph(builder, graph.get()); + if (!s.ok()) { + LOG(FATAL) << "Error building graph " << s; + } + return graph; +} + +// Tests that in the graph created by `InitGraph2`, we add the following control +// edges after calling `OrderCollectives`: c2 -> c3, c3 -> c4, and c2 -> c4. +TEST(CollectiveOrderTest, SimpleOrder2) { + std::unique_ptr graph = InitGraph2(); + TF_EXPECT_OK(OrderCollectives(graph.get())); + VerifyGraph(*graph, {"c1", "c2", "c3", "c4"}, + {{"c2", "c3"}, {"c3", "c4"}, {"c2", "c4"}}); +} + +} // namespace +} // namespace tensorflow diff --git a/tensorflow/core/protobuf/config.proto b/tensorflow/core/protobuf/config.proto index b3dc5dccc0..a2cc1bc935 100644 --- a/tensorflow/core/protobuf/config.proto +++ b/tensorflow/core/protobuf/config.proto @@ -425,6 +425,10 @@ message ConfigProto { // use NUMA affinity where applicable. One consequence will be the // existence of as many CPU devices as there are available NUMA nodes. bool use_numa_affinity = 5; + + // If true, make collective op execution order sequential and deterministic + // for potentially concurrent collective instances. + bool collective_deterministic_sequential_execution = 6; }; Experimental experimental = 16; diff --git a/tensorflow/python/ops/collective_ops_test.py b/tensorflow/python/ops/collective_ops_test.py index 0fd9368d21..9c5a39b90e 100644 --- a/tensorflow/python/ops/collective_ops_test.py +++ b/tensorflow/python/ops/collective_ops_test.py @@ -50,6 +50,24 @@ class CollectiveOpTest(test.TestCase): self.assertAllClose(results[0], expected, rtol=1e-5, atol=1e-5) self.assertAllClose(results[1], expected, rtol=1e-5, atol=1e-5) + def _testMultipleConcurrentCollectiveReduce(self, t0, t1, expected): + group_key = 1 + group_size = 2 + num_instances = 2 + all_reduces = [] + config = config_pb2.ConfigProto(device_count={'CPU': group_size}) + config.experimental.collective_deterministic_sequential_execution = True + with self.session(config=config) as sess: + for cpu in range(group_size): + with ops.device('/CPU:%d' % cpu): + in_tensor = constant_op.constant(t0 if cpu == 0 else t1) + for instance in range(num_instances): + all_reduces.append(collective_ops.all_reduce( + in_tensor, group_size, group_key, instance, 'Add', 'Div')) + results = sess.run(all_reduces) + for i in range(group_size * num_instances): + self.assertAllClose(results[i], expected, rtol=1e-5, atol=1e-5) + @test_util.run_deprecated_v1 def testCollectiveReduce(self): self._testCollectiveReduce([0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1], @@ -62,6 +80,13 @@ class CollectiveOpTest(test.TestCase): [0.3, 1.3, 2.3, 3.3, 4.3, 5.3, 6.3, 7.3], [0.2, 1.2, 2.2, 3.2, 4.2, 5.2, 6.2, 7.2], False) + @test_util.run_deprecated_v1 + def testCollectiveMultipleConcurrentReduce(self): + self._testMultipleConcurrentCollectiveReduce( + [0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1], + [0.3, 1.3, 2.3, 3.3, 4.3, 5.3, 6.3, 7.3], + [0.2, 1.2, 2.2, 3.2, 4.2, 5.2, 6.2, 7.2]) + @test_util.run_deprecated_v1 def testCollectiveReduceScalar(self): self._testCollectiveReduce(0.1, 0.3, 0.2, True) diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.-experimental.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.-experimental.pbtxt index a1083d732a..078f1028fd 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.-experimental.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.-experimental.pbtxt @@ -26,7 +26,13 @@ tf_proto { label: LABEL_OPTIONAL type: TYPE_BOOL } - reserved_range { + field { + name: "collective_deterministic_sequential_execution" + number: 6 + label: LABEL_OPTIONAL + type: TYPE_BOOL + } + reserved_range { start: 2 end: 3 } diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.pbtxt index b505d81350..d2ee0c4db6 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.-config-proto.pbtxt @@ -149,6 +149,12 @@ tf_proto { label: LABEL_OPTIONAL type: TYPE_BOOL } + field { + name: "collective_deterministic_sequential_execution" + number: 6 + label: LABEL_OPTIONAL + type: TYPE_BOOL + } reserved_range { start: 2 end: 3 -- GitLab From 5ff27167b274a7471b35ba80491004093a3f6133 Mon Sep 17 00:00:00 2001 From: Skye Wanderman-Milne Date: Thu, 20 Dec 2018 14:53:11 -0800 Subject: [PATCH 0196/1765] Don't automatically add control deps to collective ops. These ops need to run asynchronously to avoid deadlock. PiperOrigin-RevId: 226397820 --- .../python/framework/auto_control_deps.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tensorflow/python/framework/auto_control_deps.py b/tensorflow/python/framework/auto_control_deps.py index a72ded1131..a7d61417bf 100644 --- a/tensorflow/python/framework/auto_control_deps.py +++ b/tensorflow/python/framework/auto_control_deps.py @@ -29,13 +29,22 @@ from tensorflow.python.ops import tensor_array_ops from tensorflow.python.util import nest from tensorflow.python.util import tf_decorator +# Op types that should not run in program order, e.g. because they need to run +# asynchronously to avoid deadlock. +ASYNC_STATEFUL_OPS = [ + "CollectiveReduce", + "CollectiveBcastSend", + "CollectiveBcastRecv", +] + class AutomaticControlDependencies(object): """Context manager to automatically add control dependencies. Code under this context manager will act as if a sensible set of control dependencies were present. More specifically: - 1. All stateful ops in the scope will execute + 1. All stateful ops in the scope will execute (with the exception of ops in + ASYNC_STATEFUL_OPS) 2. Stateful ops which modify the same resource will execute in program order Note: creating variables in an automatic control dependencies context is not @@ -223,7 +232,8 @@ class AutomaticControlDependencies(object): control_inputs = set() # Ensure stateful ops run if (op.type not in self._graph._registered_ops # pylint: disable=protected-access - or self._graph._registered_ops[op.type].is_stateful): # pylint: disable=protected-access + or (self._graph._registered_ops[op.type].is_stateful # pylint: disable=protected-access + and op.type not in ASYNC_STATEFUL_OPS)): ops_which_must_run.add(op) # Ignore switches (they're handled separately) if op.type == "Switch" and op.inputs[0].dtype == dtypes_module.resource: @@ -255,8 +265,8 @@ class AutomaticControlDependencies(object): if inp in merge_for_resource: merge_for_resource[inp]._add_control_input(op) # pylint: disable=protected-access last_op_using_resource_tensor[inp] = op - if (op.op_def.is_stateful and not found_resource - and op._control_flow_context is None): # pylint: disable=protected-access + if (op.op_def.is_stateful and op.type not in ASYNC_STATEFUL_OPS + and not found_resource and op._control_flow_context is None): # pylint: disable=protected-access if None in last_op_using_resource_tensor: op._add_control_input(last_op_using_resource_tensor[None]) # pylint: disable=protected-access last_op_using_resource_tensor[None] = op -- GitLab From fdb5e7c3eadf8cd5995e1ac84f69af4667b55f57 Mon Sep 17 00:00:00 2001 From: Anna R Date: Thu, 20 Dec 2018 15:01:11 -0800 Subject: [PATCH 0197/1765] Assert return value of InsertTfPlatformGpuIdPair in tensorflow/core/grappler/clusters:utils_test test. PiperOrigin-RevId: 226399061 --- tensorflow/core/grappler/clusters/utils_test.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tensorflow/core/grappler/clusters/utils_test.cc b/tensorflow/core/grappler/clusters/utils_test.cc index 3863d62980..3cf72fd817 100644 --- a/tensorflow/core/grappler/clusters/utils_test.cc +++ b/tensorflow/core/grappler/clusters/utils_test.cc @@ -17,6 +17,7 @@ limitations under the License. #include "tensorflow/core/common_runtime/gpu/gpu_id.h" #include "tensorflow/core/common_runtime/gpu/gpu_id_manager.h" +#include "tensorflow/core/lib/core/status_test_util.h" #include "tensorflow/core/platform/logging.h" #include "tensorflow/core/platform/test.h" #include "tensorflow/core/protobuf/device_properties.pb.h" @@ -82,12 +83,14 @@ TEST(UtilsTest, GetDeviceInfo) { #if GOOGLE_CUDA // Invalid platform GPU id. - GpuIdManager::InsertTfPlatformGpuIdPair(TfGpuId(0), PlatformGpuId(100)); + TF_ASSERT_OK( + GpuIdManager::InsertTfPlatformGpuIdPair(TfGpuId(0), PlatformGpuId(100))); properties = GetDeviceInfo(device); EXPECT_EQ("UNKNOWN", properties.type()); // Valid platform GPU id. - GpuIdManager::InsertTfPlatformGpuIdPair(TfGpuId(1), PlatformGpuId(0)); + TF_ASSERT_OK( + GpuIdManager::InsertTfPlatformGpuIdPair(TfGpuId(1), PlatformGpuId(0))); device.id = 1; properties = GetDeviceInfo(device); EXPECT_EQ("GPU", properties.type()); -- GitLab From 676e0be5b166d08e4af5c3044e889c66de6837c9 Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Thu, 20 Dec 2018 15:16:11 -0800 Subject: [PATCH 0198/1765] Rename input_size -> original_size --- tensorflow/core/grappler/optimizers/constant_folding.cc | 5 +++-- tensorflow/core/grappler/optimizers/constant_folding.h | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tensorflow/core/grappler/optimizers/constant_folding.cc b/tensorflow/core/grappler/optimizers/constant_folding.cc index a5f6f57747..89be08800d 100644 --- a/tensorflow/core/grappler/optimizers/constant_folding.cc +++ b/tensorflow/core/grappler/optimizers/constant_folding.cc @@ -903,7 +903,7 @@ DataType GetDataTypeFromNodeOrProps(const NodeDef& node, Status ConstantFolding::CreateNodeDef(const string& name, const TensorValue& tensor, NodeDef* node, - size_t input_size) { + size_t original_size) { node->set_name(name); node->set_op("Const"); @@ -980,7 +980,8 @@ Status ConstantFolding::CreateNodeDef(const string& name, encoded_size = t->tensor_content().size(); } node->mutable_attr()->insert({"value", attr_tensor}); - if (encoded_size > input_size && encoded_size >= 10 * 1024 * 1024) { + + if (encoded_size > original_size && encoded_size >= 10 * 1024 * 1024) { return errors::InvalidArgument( strings::StrCat("Can't fold ", name, ", its size would be too large")); } diff --git a/tensorflow/core/grappler/optimizers/constant_folding.h b/tensorflow/core/grappler/optimizers/constant_folding.h index 58a962ba9b..bb86c4aeb3 100644 --- a/tensorflow/core/grappler/optimizers/constant_folding.h +++ b/tensorflow/core/grappler/optimizers/constant_folding.h @@ -36,9 +36,9 @@ const char kConstantFoldingCtrl[] = "ConstantFoldingCtrl"; class ConstantFolding : public GraphOptimizer { public: // The size limit will only be considered if the newly created node is greater - // than input_size (optional). + // than original_size (optional). static Status CreateNodeDef(const string& name, const TensorValue& tensor, - NodeDef* node, size_t input_size = 0); + NodeDef* node, size_t original_size = 0); static string AddControlDependency(const string& input_name, GraphDef* graph, NodeMap* node_map); -- GitLab From 7a0c9559a9f70f2bf3d490ffe6b90ae11f4da55a Mon Sep 17 00:00:00 2001 From: Suharsh Sivakumar Date: Thu, 20 Dec 2018 15:04:04 -0800 Subject: [PATCH 0199/1765] Bump Conv and hybrid conv versions. PiperOrigin-RevId: 226399680 --- tensorflow/lite/kernels/register.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tensorflow/lite/kernels/register.cc b/tensorflow/lite/kernels/register.cc index d5219bfa83..40e55d9a44 100644 --- a/tensorflow/lite/kernels/register.cc +++ b/tensorflow/lite/kernels/register.cc @@ -167,10 +167,12 @@ BuiltinOpResolver::BuiltinOpResolver() { AddBuiltin(BuiltinOperator_AVERAGE_POOL_2D, Register_AVERAGE_POOL_2D()); AddBuiltin(BuiltinOperator_MAX_POOL_2D, Register_MAX_POOL_2D()); AddBuiltin(BuiltinOperator_L2_POOL_2D, Register_L2_POOL_2D()); - AddBuiltin(BuiltinOperator_CONV_2D, Register_CONV_2D()); - AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D(), + AddBuiltin(BuiltinOperator_CONV_2D, Register_CONV_2D(), /* min_version */ 1, /* max_version */ 2); + AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D(), + /* min_version */ 1, + /* max_version */ 3); AddBuiltin(BuiltinOperator_SVDF, Register_SVDF()); AddBuiltin(BuiltinOperator_RNN, Register_RNN()); AddBuiltin(BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN, -- GitLab From 23178bd4985caa7a2ad3c1dcb0c876874f70dd19 Mon Sep 17 00:00:00 2001 From: Jian Li Date: Thu, 20 Dec 2018 15:13:09 -0800 Subject: [PATCH 0200/1765] Create fixed point Softmax that uses asymmetric quantization with int8 as input and output. PiperOrigin-RevId: 226401161 --- tensorflow/lite/kernels/activations.cc | 128 +++++++++++++-- tensorflow/lite/kernels/activations_test.cc | 153 +++++++++++++++++- tensorflow/lite/kernels/internal/BUILD | 7 +- tensorflow/lite/kernels/internal/common.h | 17 ++ .../internal/reference/integer_ops/softmax.h | 102 ++++++++++++ .../lite/kernels/internal/reference/softmax.h | 16 +- tensorflow/lite/toco/tflite/operator.cc | 13 +- 7 files changed, 394 insertions(+), 42 deletions(-) create mode 100644 tensorflow/lite/kernels/internal/reference/integer_ops/softmax.h diff --git a/tensorflow/lite/kernels/activations.cc b/tensorflow/lite/kernels/activations.cc index ab09cf7196..31f93ff376 100644 --- a/tensorflow/lite/kernels/activations.cc +++ b/tensorflow/lite/kernels/activations.cc @@ -23,6 +23,7 @@ limitations under the License. #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" #include "tensorflow/lite/kernels/internal/quantization_util.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/softmax.h" #include "tensorflow/lite/kernels/internal/reference/reference_ops.h" #include "tensorflow/lite/kernels/internal/tensor.h" #include "tensorflow/lite/kernels/kernel_util.h" @@ -50,6 +51,20 @@ struct PreluOpData : public OpData { int output_shift = 0; }; +namespace { +TfLiteStatus CheckInputQuantParams(TfLiteContext* context, + const TfLiteTensor* input, + const TfLiteTensor* output) { + if (input->type == kTfLiteUInt8) { + TF_LITE_ENSURE_EQ(context, output->params.zero_point, 0); + TF_LITE_ENSURE(context, output->params.scale == 1. / 256); + } else { + TF_LITE_ENSURE_EQ(context, output->params.zero_point, -128); + } + return kTfLiteOk; +} +} // namespace + void* Init(TfLiteContext* context, const char* buffer, size_t length) { // This is a builtin op, so we don't use the contents in 'buffer', if any. // Instead, we allocate a new object to carry information from Prepare() to @@ -215,12 +230,12 @@ TfLiteStatus SoftmaxPrepare(TfLiteContext* context, TfLiteNode* node) { const int num_dims = NumDimensions(input); TF_LITE_ENSURE(context, num_dims >= 1 && num_dims <= 4); - if (input->type == kTfLiteUInt8) { - TF_LITE_ENSURE_EQ(context, output->params.zero_point, 0); - TF_LITE_ENSURE(context, output->params.scale == 1. / 256); + if (input->type == kTfLiteUInt8 || input->type == kTfLiteInt8) { + if (CheckInputQuantParams(context, input, output) == kTfLiteError) { + return kTfLiteError; + } static const int kScaledDiffIntegerBits = 5; - tflite::PreprocessSoftmaxScaling( params->beta, input->params.scale, kScaledDiffIntegerBits, &data->input_multiplier, &data->input_left_shift); @@ -505,8 +520,8 @@ void Softmax3DFloat(const TfLiteTensor* input, TfLiteTensor* output, GetTensorData(output)); } -void Softmax1DQuantized(const TfLiteTensor* input, TfLiteTensor* output, - TfLiteSoftmaxParams* params, OpData* data) { +void Softmax1DQuantizedUint8(const TfLiteTensor* input, TfLiteTensor* output, + TfLiteSoftmaxParams* params, OpData* data) { // TODO(ahentz): this is arguably a dirty trick. Since the implementation // always traverses the last dimension of a 4D tensor, we will pretend our 1D // tensor is 4D in a special way. We will convert a (Y) shape into a (1, @@ -521,8 +536,8 @@ void Softmax1DQuantized(const TfLiteTensor* input, TfLiteTensor* output, GetTensorShape({1, 1, 1, input_size}), GetTensorData(output)); } -void Softmax2DQuantized(const TfLiteTensor* input, TfLiteTensor* output, - TfLiteSoftmaxParams* params, OpData* data) { +void Softmax2DQuantizedUint8(const TfLiteTensor* input, TfLiteTensor* output, + TfLiteSoftmaxParams* params, OpData* data) { // TODO(ahentz): this is arguably a dirty trick. Since the implementation // always traverses the last dimension of a 4D tensor, we will pretend our 2D // tensor is 4D in a special way. We will convert a (X, Y) shape into a (X, @@ -540,8 +555,8 @@ void Softmax2DQuantized(const TfLiteTensor* input, TfLiteTensor* output, GetTensorData(output)); } -void Softmax3DQuantized(const TfLiteTensor* input, TfLiteTensor* output, - TfLiteSoftmaxParams* params, OpData* data) { +void Softmax3DQuantizedUint8(const TfLiteTensor* input, TfLiteTensor* output, + TfLiteSoftmaxParams* params, OpData* data) { const int batch_size = input->dims->data[0]; const int intermediate_size = input->dims->data[1]; const int input_size = input->dims->data[2]; @@ -566,8 +581,8 @@ void Softmax4DFloat(const TfLiteTensor* input, TfLiteTensor* output, GetTensorData(output)); } -void Softmax4DQuantized(const TfLiteTensor* input, TfLiteTensor* output, - TfLiteSoftmaxParams* params, OpData* data) { +void Softmax4DQuantizedUint8(const TfLiteTensor* input, TfLiteTensor* output, + TfLiteSoftmaxParams* params, OpData* data) { SoftmaxParams op_params; op_params.input_multiplier = data->input_multiplier; op_params.input_left_shift = data->input_left_shift; @@ -577,6 +592,63 @@ void Softmax4DQuantized(const TfLiteTensor* input, TfLiteTensor* output, GetTensorData(output)); } +// TODO(jianlijianli): Try merging SoftmaxDQuantizedInt8 with +// SoftmaxDQuantized, which needs a larger refactor. +void Softmax1DQuantizedInt8(const TfLiteTensor* input, TfLiteTensor* output, + TfLiteSoftmaxParams* params, OpData* data) { + const int input_size = input->dims->data[0]; + SoftmaxParams op_params; + op_params.input_multiplier = data->input_multiplier; + op_params.input_left_shift = data->input_left_shift; + op_params.diff_min = data->diff_min; + reference_integer_ops::Softmax( + op_params, GetTensorShape({1, 1, 1, input_size}), + GetTensorData(input), GetTensorShape({1, 1, 1, input_size}), + GetTensorData(output)); +} + +void Softmax2DQuantizedInt8(const TfLiteTensor* input, TfLiteTensor* output, + TfLiteSoftmaxParams* params, OpData* data) { + const int batch_size = input->dims->data[0]; + const int input_size = input->dims->data[1]; + SoftmaxParams op_params; + op_params.input_multiplier = data->input_multiplier; + op_params.input_left_shift = data->input_left_shift; + op_params.diff_min = data->diff_min; + reference_integer_ops::Softmax(op_params, + GetTensorShape({batch_size, 1, 1, input_size}), + GetTensorData(input), + GetTensorShape({batch_size, 1, 1, input_size}), + GetTensorData(output)); +} + +void Softmax3DQuantizedInt8(const TfLiteTensor* input, TfLiteTensor* output, + TfLiteSoftmaxParams* params, OpData* data) { + const int batch_size = input->dims->data[0]; + const int intermediate_size = input->dims->data[1]; + const int input_size = input->dims->data[2]; + SoftmaxParams op_params; + op_params.input_multiplier = data->input_multiplier; + op_params.input_left_shift = data->input_left_shift; + op_params.diff_min = data->diff_min; + reference_integer_ops::Softmax( + op_params, GetTensorShape({batch_size, intermediate_size, 1, input_size}), + GetTensorData(input), + GetTensorShape({batch_size, intermediate_size, 1, input_size}), + GetTensorData(output)); +} + +void Softmax4DQuantizedInt8(const TfLiteTensor* input, TfLiteTensor* output, + TfLiteSoftmaxParams* params, OpData* data) { + SoftmaxParams op_params; + op_params.input_multiplier = data->input_multiplier; + op_params.input_left_shift = data->input_left_shift; + op_params.diff_min = data->diff_min; + reference_integer_ops::Softmax( + op_params, GetTensorShape(input), GetTensorData(input), + GetTensorShape(output), GetTensorData(output)); +} + TfLiteStatus SoftmaxEval(TfLiteContext* context, TfLiteNode* node) { auto* params = reinterpret_cast(node->builtin_data); OpData* data = reinterpret_cast(node->user_data); @@ -611,19 +683,19 @@ TfLiteStatus SoftmaxEval(TfLiteContext* context, TfLiteNode* node) { } case kTfLiteUInt8: { if (NumDimensions(input) == 1) { - Softmax1DQuantized(input, output, params, data); + Softmax1DQuantizedUint8(input, output, params, data); return kTfLiteOk; } if (NumDimensions(input) == 2) { - Softmax2DQuantized(input, output, params, data); + Softmax2DQuantizedUint8(input, output, params, data); return kTfLiteOk; } if (NumDimensions(input) == 3) { - Softmax3DQuantized(input, output, params, data); + Softmax3DQuantizedUint8(input, output, params, data); return kTfLiteOk; } if (NumDimensions(input) == 4) { - Softmax4DQuantized(input, output, params, data); + Softmax4DQuantizedUint8(input, output, params, data); return kTfLiteOk; } context->ReportError( @@ -631,6 +703,30 @@ TfLiteStatus SoftmaxEval(TfLiteContext* context, TfLiteNode* node) { NumDimensions(input)); return kTfLiteError; } + case kTfLiteInt8: { + if (NumDimensions(input) == 1) { + Softmax1DQuantizedInt8(input, output, params, data); + return kTfLiteOk; + } + if (NumDimensions(input) == 2) { + Softmax2DQuantizedInt8(input, output, params, data); + return kTfLiteOk; + } + if (NumDimensions(input) == 3) { + Softmax3DQuantizedInt8(input, output, params, data); + return kTfLiteOk; + } + if (NumDimensions(input) == 4) { + Softmax4DQuantizedInt8(input, output, params, data); + return kTfLiteOk; + } + context->ReportError( + context, + "Only 4D tensors supported currently for Int8 kernels, got %dD.", + NumDimensions(input)); + return kTfLiteError; + } + default: context->ReportError( context, "Only float32 and uint8_t supported currently, got %s.", diff --git a/tensorflow/lite/kernels/activations_test.cc b/tensorflow/lite/kernels/activations_test.cc index 67f137baff..5e3c56ed5b 100644 --- a/tensorflow/lite/kernels/activations_test.cc +++ b/tensorflow/lite/kernels/activations_test.cc @@ -44,6 +44,8 @@ class BaseActivationsOpModel : public SingleOpModel { input_ = AddInput(input); if (input.type == TensorType_UINT8) { output_ = AddOutput({input.type, {}, 0, 0, 1. / 256}); + } else if (input.type == TensorType_INT8) { + output_ = AddOutput({TensorType_INT8, {}, 0, 0, 1. / 256, -128}); } else { output_ = AddOutput({input.type, {}}); } @@ -52,8 +54,8 @@ class BaseActivationsOpModel : public SingleOpModel { BuildInterpreter({GetShape(input_)}); } - BaseActivationsOpModel(BuiltinOperator type, const TensorData &input, - const TensorData &output) { + BaseActivationsOpModel(BuiltinOperator type, const TensorData& input, + const TensorData& output) { input_ = AddInput(input); output_ = AddOutput(output); SetBuiltinOp(type, BuiltinOptions_NONE, 0); @@ -323,7 +325,7 @@ TEST(FloatActivationsOpTest, Softmax4D) { }))); } -TEST(QuantizedActivationsOpTest, Softmax4D) { +TEST(QuantizedActivationsOpTest, Softmax4DUint8) { QuantizedActivationsOpModel m( 0.1, /*input=*/{TensorType_UINT8, {1, 2, 1, 4}, -10, 10}); @@ -362,6 +364,145 @@ TEST(QuantizedActivationsOpTest, Softmax4D) { kQuantizedTolerance))); } +// Test quantized softmax with int8 input and output. With the same input as in +// QuantizedActivationsOpTest.Softmax1D, the dequantized output is identical. +TEST(QuantizedActivationsOpTest, Softmax1DInt8) { + QuantizedActivationsOpModel m(0.1, + /*input=*/{TensorType_INT8, {8}, -10, 10}); + m.SetInput({0, -6, 2, 4, 3, -2, 10, 1}); + m.Invoke(); + EXPECT_THAT( + m.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear({0.09766, 0.05469, 0.12109, 0.14453, + 0.13281, 0.07813, 0.26563, 0.10938}, + kQuantizedTolerance))); +} + +// Test quantized softmax with int8 input and output. With the same input as in +// QuantizedActivationsOpTest.Softmax2D, the dequantized output is identical. +TEST(QuantizedActivationsOpTest, Softmax2DInt8) { + QuantizedActivationsOpModel m(0.1, + /*input=*/{TensorType_INT8, {2, 4}, -10, 10}); + m.SetInput({ + 0, -6, 2, 4, // + 3, -2, 10, 1, // + }); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear( + { + .23463, .12877, .28658, .35003, // + .22528, .13664, .45365, .18443, // + }, + kQuantizedTolerance))); + + // Same input, but a different shape. + QuantizedActivationsOpModel m2(0.1, + /*input=*/{TensorType_INT8, {4, 2}, -10, 10}); + m2.SetInput({ + 0, -6, // + 2, 4, // + 3, -2, // + 10, 1, // + }); + m2.Invoke(); + EXPECT_THAT(m2.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear( + { + 0.645656, 0.354344, // + 0.450166, 0.549834, // + 0.622459, 0.377541, // + 0.710949, 0.28905, // + }, + kQuantizedTolerance))); +} + +// Test quantized softmax with int8 input and output. With the same input as in +// QuantizedActivationsOpTest.Softmax3D, the dequantized output is identical. +TEST(QuantizedActivationsOpTest, Softmax3DInt8) { + QuantizedActivationsOpModel m( + 0.1, + /*input=*/{TensorType_INT8, {1, 2, 4}, -10, 10}); + m.SetInput({ + 0, -6, 2, 4, // depth = 0 + 3, -2, 10, 1, // depth = 1 + }); + m.Invoke(); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear( + { + .23463, .12877, .28658, .35003, // + .22528, .13664, .45365, .18443, // + }, + kQuantizedTolerance))); + + // Same input, but a different shape. + QuantizedActivationsOpModel m2( + 0.1, + /*input=*/{TensorType_INT8, {4, 1, 2}, -10, 10}); + m2.SetInput({ + 0, -6, // + 2, 4, // + 3, -2, // + 10, 1, // + }); + m2.Invoke(); + EXPECT_THAT(m2.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear( + { + 0.645656, 0.354344, // + 0.450166, 0.549834, // + 0.622459, 0.377541, // + 0.710949, 0.28905, // + }, + kQuantizedTolerance))); +} + +// Test quantized softmax with int8 input and output. With the same input as in +// QuantizedActivationsOpTest.Softmax4D, the dequantized output is identical. +TEST(QuantizedActivationsOpTest, Softmax4DInt8) { + QuantizedActivationsOpModel m( + 0.1, + /*input=*/{TensorType_INT8, {1, 2, 1, 4}, -10, 10}); + m.SetInput({ + 0, -6, 2, 4, // depth = 0 + 3, -2, 10, 1, // depth = 1 + }); + m.Invoke(); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({ + -68, -95, -54, -38, // + -70, -93, -12, -81, // + })); + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear( + { + .23463, .12877, .28658, .35003, // + .22528, .13664, .45365, .18443, // + }, + kQuantizedTolerance))); + + // Same input, but a different shape. + QuantizedActivationsOpModel m2( + 0.1, + /*input=*/{TensorType_INT8, {4, 1, 1, 2}, -10, 10}); + m2.SetInput({ + 0, -6, // + 2, 4, // + 3, -2, // + 10, 1, // + }); + m2.Invoke(); + EXPECT_THAT(m2.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear( + { + 0.645656, 0.354344, // + 0.450166, 0.549834, // + 0.622459, 0.377541, // + 0.710949, 0.28905, // + }, + kQuantizedTolerance))); +} + TEST(FloatActivationsOpTest, Softmax3D) { FloatActivationsOpModel m(0.1, /*input=*/{TensorType_FLOAT32, {1, 2, 4}}); @@ -393,7 +534,7 @@ TEST(FloatActivationsOpTest, Softmax3D) { }))); } -TEST(QuantizedActivationsOpTest, Softmax3D) { +TEST(QuantizedActivationsOpTest, Softmax3DUint8) { QuantizedActivationsOpModel m( 0.1, /*input=*/{TensorType_UINT8, {1, 2, 4}, -10, 10}); @@ -443,7 +584,7 @@ TEST(FloatActivationsOpTest, Softmax1D) { {.09752, .05352, .11911, .14548, .13164, .07984, .26509, .10778}))); } -TEST(QuantizedActivationsOpTest, Softmax1D) { +TEST(QuantizedActivationsOpTest, Softmax1DUint8) { QuantizedActivationsOpModel m(0.1, /*input=*/{TensorType_UINT8, {8}, -10, 10}); m.SetInput({0, -6, 2, 4, 3, -2, 10, 1}); @@ -486,7 +627,7 @@ TEST(FloatActivationsOpTest, Softmax2D) { }))); } -TEST(QuantizedActivationsOpTest, Softmax2D) { +TEST(QuantizedActivationsOpTest, Softmax2DUint8) { QuantizedActivationsOpModel m(0.1, /*input=*/{TensorType_UINT8, {2, 4}, -10, 10}); m.SetInput({ diff --git a/tensorflow/lite/kernels/internal/BUILD b/tensorflow/lite/kernels/internal/BUILD index 69816583f5..442373b5c4 100644 --- a/tensorflow/lite/kernels/internal/BUILD +++ b/tensorflow/lite/kernels/internal/BUILD @@ -1,12 +1,12 @@ +load("//tensorflow/lite:build_def.bzl", "tflite_copts") +load("//tensorflow/lite:special_rules.bzl", "tflite_portable_test_suite") + package(default_visibility = [ "//visibility:public", ]) licenses(["notice"]) # Apache 2.0 -load("//tensorflow/lite:build_def.bzl", "tflite_copts") -load("//tensorflow/lite:special_rules.bzl", "tflite_portable_test_suite") - tflite_deps_intel = [ "@arm_neon_2_x86_sse", ] @@ -314,6 +314,7 @@ cc_library( "reference/depthwiseconv_uint8.h", "reference/fully_connected.h", "reference/integer_ops/dequantize.h", + "reference/integer_ops/softmax.h", "reference/reference_ops.h", "reference/softmax.h", ], diff --git a/tensorflow/lite/kernels/internal/common.h b/tensorflow/lite/kernels/internal/common.h index fdb72037f8..bc30ac9122 100644 --- a/tensorflow/lite/kernels/internal/common.h +++ b/tensorflow/lite/kernels/internal/common.h @@ -131,6 +131,23 @@ int CountLeadingZeros(T integer_input) { #endif } +inline int32 GetReciprocal(int32 x, int x_integer_digits, + int* num_bits_over_unit) { + int headroom_plus_one = CountLeadingZeros(static_cast(x)); + // This is the number of bits to the left of the binary point above 1.0. + // Consider x=1.25. In that case shifted_scale=0.8 and + // no later adjustment will be needed. + *num_bits_over_unit = x_integer_digits - headroom_plus_one; + const int32 shifted_sum_minus_one = + static_cast((static_cast(x) << headroom_plus_one) - + (static_cast(1) << 31)); + + gemmlowp::FixedPoint shifted_scale = + gemmlowp::one_over_one_plus_x_for_x_in_0_1( + gemmlowp::FixedPoint::FromRaw(shifted_sum_minus_one)); + return shifted_scale.raw(); +} + // DO NOT USE THIS STRUCT FOR NEW FUNCTIONALITY BEYOND IMPLEMENTING // BROADCASTING. // diff --git a/tensorflow/lite/kernels/internal/reference/integer_ops/softmax.h b/tensorflow/lite/kernels/internal/reference/integer_ops/softmax.h new file mode 100644 index 0000000000..3f6bf1cb73 --- /dev/null +++ b/tensorflow/lite/kernels/internal/reference/integer_ops/softmax.h @@ -0,0 +1,102 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_SOFTMAX_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_SOFTMAX_H_ + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +// Quantized softmax with int8 input and output. +inline void Softmax(const SoftmaxParams& params, + const RuntimeShape& input_shape, const int8* input_data, + const RuntimeShape& output_shape, int8* output_data) { + const int32 input_beta_multiplier = params.input_multiplier; + const int32 input_beta_left_shift = params.input_left_shift; + const int diff_min = params.diff_min; + // The representation chosen for the input to the exp() function is Q5.26. + // We need to leave extra space since values that we skip might be as large as + // -32 before multiplying by input_beta_multiplier, and therefore as large as + // -16 afterwards. Note that exp(-8) is definitely not insignificant to + // accumulation, but exp(-16) definitely is. + static const int kScaledDiffIntegerBits = 5; + static const int kAccumulationIntegerBits = 12; + using FixedPointScaledDiff = + gemmlowp::FixedPoint; + using FixedPointAccum = gemmlowp::FixedPoint; + using FixedPoint0 = gemmlowp::FixedPoint; + + const int trailing_dim = input_shape.DimensionsCount() - 1; + const int outer_size = + MatchingFlatSizeSkipDim(input_shape, trailing_dim, output_shape); + const int depth = + MatchingDim(input_shape, trailing_dim, output_shape, trailing_dim); + + for (int i = 0; i < outer_size; ++i) { + int8 max_in_row = -128; + for (int c = 0; c < depth; ++c) { + max_in_row = std::max(max_in_row, input_data[i * depth + c]); + } + + FixedPointAccum sum_of_exps = FixedPointAccum::Zero(); + for (int c = 0; c < depth; ++c) { + int32 input_diff = + static_cast(input_data[i * depth + c]) - max_in_row; + if (input_diff >= diff_min) { + const int32 input_diff_rescaled = + MultiplyByQuantizedMultiplierGreaterThanOne( + input_diff, input_beta_multiplier, input_beta_left_shift); + const FixedPointScaledDiff scaled_diff_f8 = + FixedPointScaledDiff::FromRaw(input_diff_rescaled); + sum_of_exps = sum_of_exps + gemmlowp::Rescale( + exp_on_negative_values(scaled_diff_f8)); + } + } + + int num_bits_over_unit; + FixedPoint0 shifted_scale = FixedPoint0::FromRaw(GetReciprocal( + sum_of_exps.raw(), kAccumulationIntegerBits, &num_bits_over_unit)); + + for (int c = 0; c < depth; ++c) { + int32 input_diff = + static_cast(input_data[i * depth + c]) - max_in_row; + if (input_diff >= diff_min) { + const int32 input_diff_rescaled = + MultiplyByQuantizedMultiplierGreaterThanOne( + input_diff, input_beta_multiplier, input_beta_left_shift); + const FixedPointScaledDiff scaled_diff_f8 = + FixedPointScaledDiff::FromRaw(input_diff_rescaled); + + FixedPoint0 exp_in_0 = exp_on_negative_values(scaled_diff_f8); + const int32 unsat_output = gemmlowp::RoundingDivideByPOT( + (shifted_scale * exp_in_0).raw(), num_bits_over_unit + 31 - 8); + const int32 shifted_output = unsat_output - 128; + + output_data[i * depth + c] = static_cast( + std::max(std::min(shifted_output, static_cast(127)), + static_cast(-128))); + + } else { + output_data[i * depth + c] = -128; + } + } + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_SOFTMAX_H_ diff --git a/tensorflow/lite/kernels/internal/reference/softmax.h b/tensorflow/lite/kernels/internal/reference/softmax.h index 51de6b51aa..45a18cdb47 100644 --- a/tensorflow/lite/kernels/internal/reference/softmax.h +++ b/tensorflow/lite/kernels/internal/reference/softmax.h @@ -102,19 +102,9 @@ inline void Softmax(const SoftmaxParams& params, } } - int32 fixed_sum_of_exps = sum_of_exps.raw(); - int headroom_plus_one = - CountLeadingZeros(static_cast(fixed_sum_of_exps)); - // This is the number of bits to the left of the binary point above 1.0. - // Consider fixed_sum_of_exps=1.25. In that case shifted_scale=0.8 and - // no later adjustment will be needed. - int num_bits_over_unit = kAccumulationIntegerBits - headroom_plus_one; - int32 shifted_sum_minus_one = static_cast( - (static_cast(fixed_sum_of_exps) << headroom_plus_one) - - (static_cast(1) << 31)); - - FixedPoint0 shifted_scale = gemmlowp::one_over_one_plus_x_for_x_in_0_1( - FixedPoint0::FromRaw(shifted_sum_minus_one)); + int num_bits_over_unit; + FixedPoint0 shifted_scale = FixedPoint0::FromRaw(GetReciprocal( + sum_of_exps.raw(), kAccumulationIntegerBits, &num_bits_over_unit)); for (int c = 0; c < depth; ++c) { int32 input_diff = diff --git a/tensorflow/lite/toco/tflite/operator.cc b/tensorflow/lite/toco/tflite/operator.cc index abfd370b86..11c8237eb6 100644 --- a/tensorflow/lite/toco/tflite/operator.cc +++ b/tensorflow/lite/toco/tflite/operator.cc @@ -706,6 +706,11 @@ class Softmax } int GetVersion(const OperatorSignature& op_signature) const override { + const string& input_name = op_signature.op->inputs[0]; + const Array& input_array = op_signature.model->GetArray(input_name); + if (input_array.data_type == ArrayDataType::kInt8) { + return 2; + } return 1; } }; @@ -1556,10 +1561,6 @@ class TensorFlowUnsupported : public BaseOperator { return std::unique_ptr(fbb.release()); } -// TODO(wvo): hack to make this code compile with 2 different API versions. -// Please remove once OS/internal versions are in sync. -// See hardcoded values in the switch below. - void ReadOptions(const flexbuffers::Map& m, TensorFlowUnsupportedOperator* op) const { ::tensorflow::NodeDef node_def; @@ -1569,6 +1570,10 @@ class TensorFlowUnsupported : public BaseOperator { for (size_t i = 0; i < keys.size(); ++i) { const auto key = keys[i].AsKey(); const auto& value = m[key]; + // TODO(wvo): hack to make this code compile with 2 different API + // versions. + // Please remove once OS/internal versions are in sync. + // See hardcoded values in the switch below. switch (value.GetType()) { case 5: // flexbuffers::FBT_STRING: (*attr)[key].set_s(value.AsString().c_str()); -- GitLab From 1a6591def1413de1b82c9211ec005b7fd25d3b2b Mon Sep 17 00:00:00 2001 From: Rohan Jain Date: Thu, 20 Dec 2018 15:14:37 -0800 Subject: [PATCH 0201/1765] Removing GpuDefinedDataset test which is not relevant anymore as we expect dataset kernels to get created as we go. PiperOrigin-RevId: 226401392 --- tensorflow/contrib/eager/python/datasets_test.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tensorflow/contrib/eager/python/datasets_test.py b/tensorflow/contrib/eager/python/datasets_test.py index 257d02057a..78ab155896 100644 --- a/tensorflow/contrib/eager/python/datasets_test.py +++ b/tensorflow/contrib/eager/python/datasets_test.py @@ -200,13 +200,6 @@ class IteratorTest(test.TestCase): y = math_ops.add(x, x) self.assertAllEqual([0., 2.], y.numpy()) - def testGpuDefinedDataset(self): - with ops.device(test.gpu_device_name()): - ds = Dataset.from_tensors([0., 1.]) - for x in ds: - y = math_ops.add(x, x) - self.assertAllEqual([0., 2.], y.numpy()) - def testOverrideThreadPool(self): def get_thread_id(_): -- GitLab From 10a114c0d3b0aa669b9b90f906f104a913fb2b18 Mon Sep 17 00:00:00 2001 From: Jiri Simsa Date: Thu, 20 Dec 2018 15:22:34 -0800 Subject: [PATCH 0202/1765] [tf.data] Making it possible to override modeling framework implementations. PiperOrigin-RevId: 226402626 --- tensorflow/core/framework/model.h | 8 +- tensorflow/core/kernels/data/BUILD | 2 + .../core/kernels/data/model_dataset_op.cc | 260 +++++++++--------- .../core/kernels/data/model_dataset_op.h | 42 +++ tensorflow/python/data/ops/dataset_ops.py | 2 - 5 files changed, 182 insertions(+), 132 deletions(-) create mode 100644 tensorflow/core/kernels/data/model_dataset_op.h diff --git a/tensorflow/core/framework/model.h b/tensorflow/core/framework/model.h index c3a694227c..bb1d7b6bff 100644 --- a/tensorflow/core/framework/model.h +++ b/tensorflow/core/framework/model.h @@ -365,8 +365,10 @@ class Model { bool collect_resource_usage() const { return collect_resource_usage_; } // Adds a node with the given name and given output. - std::shared_ptr AddNode(Node::Factory factory, const string& name, - const string& output_name) LOCKS_EXCLUDED(mu_); + virtual std::shared_ptr AddNode(Node::Factory factory, + const string& name, + const string& output_name) + LOCKS_EXCLUDED(mu_); // Increments the processing time for the given node.. void AddProcessingTime(const string& name, int64 delta) LOCKS_EXCLUDED(mu_); @@ -388,7 +390,7 @@ class Model { // Removes the given node. void RemoveNode(const string& name) LOCKS_EXCLUDED(mu_); - private: + protected: // Collects tunable parameters in the tree rooted in the given node. std::vector> CollectTunableParameters( std::shared_ptr node); diff --git a/tensorflow/core/kernels/data/BUILD b/tensorflow/core/kernels/data/BUILD index e2ab77632d..663717ffb0 100644 --- a/tensorflow/core/kernels/data/BUILD +++ b/tensorflow/core/kernels/data/BUILD @@ -504,10 +504,12 @@ tf_kernel_library( tf_kernel_library( name = "model_dataset_op", srcs = ["model_dataset_op.cc"], + hdrs = ["model_dataset_op.h"], deps = [ "//tensorflow/core:core_cpu_internal", "//tensorflow/core:dataset_ops_op_lib", "//tensorflow/core:framework", + "//tensorflow/core:framework_internal", "//tensorflow/core:lib", "//tensorflow/core:lib_internal", ], diff --git a/tensorflow/core/kernels/data/model_dataset_op.cc b/tensorflow/core/kernels/data/model_dataset_op.cc index 069d61d80d..e1a0d94f5f 100644 --- a/tensorflow/core/kernels/data/model_dataset_op.cc +++ b/tensorflow/core/kernels/data/model_dataset_op.cc @@ -13,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "tensorflow/core/kernels/data/model_dataset_op.h" + #include "tensorflow/core/framework/dataset.h" #include "tensorflow/core/framework/partial_tensor_shape.h" #include "tensorflow/core/framework/tensor.h" @@ -21,166 +23,170 @@ limitations under the License. namespace tensorflow { namespace data { -namespace { const int kOptimizationPeriodThresholdMs = 60 * EnvTime::kSecondsToMicros; -class ModelDatasetOp : public UnaryDatasetOpKernel { +class ModelDatasetOp::Dataset : public DatasetBase { public: - explicit ModelDatasetOp(OpKernelConstruction* ctx) - : UnaryDatasetOpKernel(ctx) {} + explicit Dataset(OpKernelContext* ctx, const DatasetBase* input, + ModelFactory model_factory) + : DatasetBase(DatasetContext(ctx)), + input_(input), + model_factory_(std::move(model_factory)) { + input_->Ref(); + } + + ~Dataset() override { input_->Unref(); } + + std::unique_ptr MakeIteratorInternal( + const string& prefix) const override { + return std::unique_ptr(new Iterator( + {this, strings::StrCat(prefix, "::Model")}, model_factory_)); + } - void MakeDataset(OpKernelContext* ctx, DatasetBase* input, - DatasetBase** output) override { - *output = new Dataset(ctx, input); + const DataTypeVector& output_dtypes() const override { + return input_->output_dtypes(); + } + const std::vector& output_shapes() const override { + return input_->output_shapes(); + } + + string DebugString() const override { return "ModelDatasetOp::Dataset"; } + + int64 Cardinality() const override { return input_->Cardinality(); } + + protected: + Status AsGraphDefInternal(SerializationContext* ctx, + DatasetGraphDefBuilder* b, + Node** output) const override { + Node* input_graph_node = nullptr; + TF_RETURN_IF_ERROR(b->AddInputDataset(ctx, input_, &input_graph_node)); + TF_RETURN_IF_ERROR(b->AddDataset(this, {input_graph_node}, output)); + return Status::OK(); } private: - class Dataset : public DatasetBase { + class Iterator : public DatasetIterator { public: - explicit Dataset(OpKernelContext* ctx, const DatasetBase* input) - : DatasetBase(DatasetContext(ctx)), input_(input) { - input_->Ref(); + explicit Iterator(const Params& params, ModelFactory model_factory) + : DatasetIterator(params), model_(model_factory()) {} + + ~Iterator() override { + // Signal the optimize thread to terminate it. We will then join that + // thread when we delete `this->optimize_thread_`. + mutex_lock l(mu_); + cancelled_ = true; + cond_var_.notify_all(); } - ~Dataset() override { input_->Unref(); } - - std::unique_ptr MakeIteratorInternal( - const string& prefix) const override { - return std::unique_ptr( - new Iterator({this, strings::StrCat(prefix, "::Model")})); + Status Initialize(IteratorContext* ctx) override { + IteratorContext::Params params(ctx); + params.model = model_; + return dataset()->input_->MakeIterator(IteratorContext(std::move(params)), + prefix(), &input_impl_); } - const DataTypeVector& output_dtypes() const override { - return input_->output_dtypes(); - } - const std::vector& output_shapes() const override { - return input_->output_shapes(); + Status GetNextInternal(IteratorContext* ctx, + std::vector* out_tensors, + bool* end_of_sequence) override { + IteratorContext::Params params(ctx); + { + mutex_lock l(mu_); + TF_RETURN_IF_ERROR(EnsureOptimizeThreadStarted(ctx)); + params.model = model_; + } + return input_impl_->GetNext(IteratorContext(std::move(params)), + out_tensors, end_of_sequence); } - string DebugString() const override { return "ModelDatasetOp::Dataset"; } + protected: + std::shared_ptr CreateNode( + IteratorContext* ctx, model::Node::Args args) const override { + return model::MakeKnownRatioNode(std::move(args), + /*ratio=*/1); + } - int64 Cardinality() const override { return input_->Cardinality(); } + Status SaveInternal(IteratorStateWriter* writer) override { + mutex_lock l(mu_); + TF_RETURN_IF_ERROR(SaveInput(writer, input_impl_)); + return Status::OK(); + } - protected: - Status AsGraphDefInternal(SerializationContext* ctx, - DatasetGraphDefBuilder* b, - Node** output) const override { - Node* input_graph_node = nullptr; - TF_RETURN_IF_ERROR(b->AddInputDataset(ctx, input_, &input_graph_node)); - TF_RETURN_IF_ERROR(b->AddDataset(this, {input_graph_node}, output)); + Status RestoreInternal(IteratorContext* ctx, + IteratorStateReader* reader) override { + mutex_lock l(mu_); + TF_RETURN_IF_ERROR(RestoreInput(ctx, reader, input_impl_)); return Status::OK(); } private: - class Iterator : public DatasetIterator { - public: - explicit Iterator(const Params& params) - : DatasetIterator(params), - model_(std::make_shared()) {} - - ~Iterator() override { - // Signal the optimize thread to terminate it. We will then join that - // thread when we delete `this->optimize_thread_`. - mutex_lock l(mu_); - cancelled_ = true; - cond_var_.notify_all(); - } - - Status Initialize(IteratorContext* ctx) override { - IteratorContext::Params params(ctx); - params.model = model_; - return dataset()->input_->MakeIterator( - IteratorContext(std::move(params)), prefix(), &input_impl_); + Status EnsureOptimizeThreadStarted(IteratorContext* ctx) + EXCLUSIVE_LOCKS_REQUIRED(mu_) { + if (!optimize_thread_) { + std::shared_ptr new_ctx(new IteratorContext(*ctx)); + optimize_thread_.reset(ctx->env()->StartThread( + {}, "tf_data_model", + [this, new_ctx]() { OptimizeThread(new_ctx); })); } + return Status::OK(); + } - Status GetNextInternal(IteratorContext* ctx, - std::vector* out_tensors, - bool* end_of_sequence) override { - IteratorContext::Params params(ctx); + void OptimizeThread(const std::shared_ptr& ctx) { + int64 last_optimization_ms = 0; + int64 optimization_period_ms = 10; + while (true) { { mutex_lock l(mu_); - TF_RETURN_IF_ERROR(EnsureOptimizeThreadStarted(ctx)); - params.model = model_; + while (!cancelled_ && + last_optimization_ms + optimization_period_ms >= + ctx->env()->NowMicros() / EnvTime::kMillisToMicros) { + cond_var_.wait_for( + l, std::chrono::milliseconds( + last_optimization_ms + optimization_period_ms - + ctx->env()->NowMicros() / EnvTime::kMillisToMicros)); + } + if (cancelled_) return; } - return input_impl_->GetNext(IteratorContext(std::move(params)), - out_tensors, end_of_sequence); - } - - protected: - std::shared_ptr CreateNode( - IteratorContext* ctx, model::Node::Args args) const override { - return model::MakeKnownRatioNode(std::move(args), - /*ratio=*/1); + model_->Optimize(port::NumSchedulableCPUs()); + // Exponentially increase the period of running the optimization + // until a threshold is reached. + if (optimization_period_ms < kOptimizationPeriodThresholdMs) { + if (optimization_period_ms << 1 < kOptimizationPeriodThresholdMs) { + optimization_period_ms <<= 1; + } else { + optimization_period_ms = kOptimizationPeriodThresholdMs; + } + } + last_optimization_ms = + ctx->env()->NowMicros() / EnvTime::kMillisToMicros; } + } - Status SaveInternal(IteratorStateWriter* writer) override { - mutex_lock l(mu_); - TF_RETURN_IF_ERROR(SaveInput(writer, input_impl_)); - return Status::OK(); - } + mutex mu_; + condition_variable cond_var_; + std::shared_ptr model_; + std::unique_ptr optimize_thread_ GUARDED_BY(mu_); + bool cancelled_ GUARDED_BY(mu_) = false; + std::unique_ptr input_impl_; + }; - Status RestoreInternal(IteratorContext* ctx, - IteratorStateReader* reader) override { - mutex_lock l(mu_); - TF_RETURN_IF_ERROR(RestoreInput(ctx, reader, input_impl_)); - return Status::OK(); - } + const DatasetBase* input_; + const ModelFactory model_factory_; +}; - private: - Status EnsureOptimizeThreadStarted(IteratorContext* ctx) - EXCLUSIVE_LOCKS_REQUIRED(mu_) { - if (!optimize_thread_) { - std::shared_ptr new_ctx(new IteratorContext(*ctx)); - optimize_thread_.reset(ctx->env()->StartThread( - {}, "tf_data_model", - [this, new_ctx]() { OptimizeThread(new_ctx); })); - } - return Status::OK(); - } +ModelDatasetOp::ModelDatasetOp(OpKernelConstruction* ctx) + : UnaryDatasetOpKernel(ctx) {} - void OptimizeThread(const std::shared_ptr& ctx) { - int64 last_optimization_ms = 0; - int64 optimization_period_ms = 10; - while (true) { - { - mutex_lock l(mu_); - while (!cancelled_ && - last_optimization_ms + optimization_period_ms >= - ctx->env()->NowMicros() / EnvTime::kMillisToMicros) { - cond_var_.wait_for( - l, std::chrono::milliseconds( - last_optimization_ms + optimization_period_ms - - ctx->env()->NowMicros() / EnvTime::kMillisToMicros)); - } - if (cancelled_) return; - } - model_->Optimize(port::NumSchedulableCPUs()); - // Exponentially increase the period of running the optimization - // until a threshold is reached. - if (optimization_period_ms < kOptimizationPeriodThresholdMs) { - if (optimization_period_ms << 1 < kOptimizationPeriodThresholdMs) { - optimization_period_ms <<= 1; - } else { - optimization_period_ms = kOptimizationPeriodThresholdMs; - } - } - last_optimization_ms = - ctx->env()->NowMicros() / EnvTime::kMillisToMicros; - } - } +void ModelDatasetOp::MakeDataset(OpKernelContext* ctx, DatasetBase* input, + DatasetBase** output) { + *output = new ModelDatasetOp::Dataset(ctx, input, CreateModelFactory()); +} - mutex mu_; - condition_variable cond_var_; - std::shared_ptr model_; - std::unique_ptr optimize_thread_ GUARDED_BY(mu_); - bool cancelled_ GUARDED_BY(mu_) = false; - std::unique_ptr input_impl_; - }; +ModelDatasetOp::ModelFactory ModelDatasetOp::CreateModelFactory() const { + return []() { return std::make_shared(); }; +} - const DatasetBase* input_; - }; -}; +namespace { REGISTER_KERNEL_BUILDER(Name("ModelDataset").Device(DEVICE_CPU), ModelDatasetOp); diff --git a/tensorflow/core/kernels/data/model_dataset_op.h b/tensorflow/core/kernels/data/model_dataset_op.h new file mode 100644 index 0000000000..38d3fcb234 --- /dev/null +++ b/tensorflow/core/kernels/data/model_dataset_op.h @@ -0,0 +1,42 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_CORE_KERNELS_DATA_MODEL_DATASET_OP_H_ +#define TENSORFLOW_CORE_KERNELS_DATA_MODEL_DATASET_OP_H_ + +#include "tensorflow/core/framework/dataset.h" +#include "tensorflow/core/framework/model.h" + +namespace tensorflow { +namespace data { + +class ModelDatasetOp : public UnaryDatasetOpKernel { + public: + using ModelFactory = std::function()>; + + explicit ModelDatasetOp(OpKernelConstruction* ctx); + + void MakeDataset(OpKernelContext* ctx, DatasetBase* input, + DatasetBase** output) override; + + virtual ModelFactory CreateModelFactory() const; + + private: + class Dataset; +}; + +} // namespace data +} // namespace tensorflow +#endif // TENSORFLOW_CORE_KERNELS_DATA_MODEL_DATASET_OP_H_ diff --git a/tensorflow/python/data/ops/dataset_ops.py b/tensorflow/python/data/ops/dataset_ops.py index 7fa9ea59e8..1ba00a8e69 100644 --- a/tensorflow/python/data/ops/dataset_ops.py +++ b/tensorflow/python/data/ops/dataset_ops.py @@ -3017,7 +3017,6 @@ class _ModelDataset(UnaryUnchangedStructureDataset): """A `Dataset` that acts as an identity, and models performance.""" def __init__(self, input_dataset): - """See `optimize()` for details.""" self._input_dataset = input_dataset variant_tensor = gen_dataset_ops.model_dataset( input_dataset._variant_tensor, # pylint: disable=protected-access @@ -3029,7 +3028,6 @@ class _OptimizeDataset(UnaryUnchangedStructureDataset): """A `Dataset` that acts as an identity, and applies optimizations.""" def __init__(self, input_dataset, optimizations): - """See `optimize()` for details.""" self._input_dataset = input_dataset if optimizations is None: optimizations = [] -- GitLab From 148047be4e1b8ca9968cadd10bc56dc627f17f62 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 15:35:16 -0800 Subject: [PATCH 0203/1765] Automated rollback of commit 8d24064a291322b1d39a8f439832ab95be8fc261. Revert #24193. PiperOrigin-RevId: 226404585 --- tensorflow/core/distributed_runtime/master_session.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tensorflow/core/distributed_runtime/master_session.cc b/tensorflow/core/distributed_runtime/master_session.cc index 5a524eba76..2bb4375831 100644 --- a/tensorflow/core/distributed_runtime/master_session.cc +++ b/tensorflow/core/distributed_runtime/master_session.cc @@ -1354,9 +1354,7 @@ Status MasterSession::DeleteWorkerSessions() { &workers[i].call_opts, &workers[i].request, &workers[i].response, cb); } - if (!done.WaitFor(std::chrono::milliseconds(10000))) { - LOG(WARNING) << "Timeout for closing worker session"; - } + done.Wait(); for (size_t i = 0; i < workers.size(); ++i) { status.Update(workers[i].status); } -- GitLab From e387f58b820ff689eaf99dea0e5fd50865fc3a1c Mon Sep 17 00:00:00 2001 From: Pete Warden Date: Thu, 20 Dec 2018 16:02:17 -0800 Subject: [PATCH 0204/1765] Fixed formatting to match required style --- .../examples/micro_speech/CMSIS/hanning.cc | 92 +++++++++---------- .../examples/micro_speech/CMSIS/sin_1k.cc | 92 +++++++++---------- .../micro_speech/apollo3/pushbutton_test.cc | 17 ++-- .../examples/micro_speech/preprocessor.cc | 7 +- .../examples/micro_speech/preprocessor.h | 2 +- 5 files changed, 100 insertions(+), 110 deletions(-) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc index deb30ffd88..e6a11ce52c 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/hanning.cc @@ -17,51 +17,47 @@ limitations under the License. const int g_hanning_size = 480; const int16_t g_hanning[480] = { - 0, 1, 5, 12, 22, 35, 50, 69, 90, 114, - 140, 170, 202, 237, 275, 316, 359, 405, 454, 506, - 560, 617, 677, 740, 805, 873, 943, 1016, 1092, 1171, - 1252, 1336, 1422, 1511, 1602, 1696, 1793, 1892, 1993, 2097, - 2204, 2312, 2424, 2537, 2653, 2772, 2893, 3016, 3141, 3269, - 3399, 3531, 3665, 3802, 3941, 4082, 4225, 4370, 4517, 4666, - 4817, 4971, 5126, 5283, 5442, 5603, 5765, 5930, 6096, 6265, - 6435, 6606, 6779, 6954, 7131, 7309, 7489, 7670, 7853, 8037, - 8223, 8410, 8598, 8788, 8979, 9171, 9365, 9560, 9756, 9953, - 10151, 10350, 10551, 10752, 10954, 11157, 11362, 11567, 11772, 11979, - 12186, 12395, 12603, 12813, 13023, 13233, 13445, 13656, 13868, 14081, - 14294, 14507, 14721, 14935, 15149, 15363, 15578, 15793, 16008, 16222, - 16437, 16652, 16867, 17082, 17297, 17511, 17725, 17939, 18153, 18367, - 18580, 18793, 19005, 19217, 19428, 19639, 19850, 20059, 20269, 20477, - 20685, 20892, 21098, 21303, 21508, 21712, 21914, 22116, 22317, 22517, - 22716, 22913, 23110, 23305, 23499, 23692, 23884, 24075, 24264, 24451, - 24638, 24823, 25006, 25188, 25369, 25548, 25725, 25901, 26075, 26247, - 26418, 26587, 26754, 26920, 27083, 27245, 27405, 27563, 27719, 27874, - 28026, 28176, 28324, 28470, 28614, 28756, 28896, 29034, 29169, 29303, - 29434, 29563, 29689, 29813, 29935, 30055, 30172, 30287, 30400, 30510, - 30617, 30723, 30825, 30926, 31023, 31119, 31211, 31301, 31389, 31474, - 31556, 31636, 31713, 31788, 31860, 31929, 31996, 32059, 32121, 32179, - 32235, 32288, 32338, 32386, 32430, 32472, 32512, 32548, 32582, 32613, - 32641, 32666, 32689, 32708, 32725, 32739, 32751, 32759, 32765, 32767, - 32767, 32765, 32759, 32751, 32739, 32725, 32708, 32689, 32666, 32641, - 32613, 32582, 32548, 32512, 32472, 32430, 32386, 32338, 32288, 32235, - 32179, 32121, 32059, 31996, 31929, 31860, 31788, 31713, 31636, 31556, - 31474, 31389, 31301, 31211, 31119, 31023, 30926, 30825, 30723, 30617, - 30510, 30400, 30287, 30172, 30055, 29935, 29813, 29689, 29563, 29434, - 29303, 29169, 29034, 28896, 28756, 28614, 28470, 28324, 28176, 28026, - 27874, 27719, 27563, 27405, 27245, 27083, 26920, 26754, 26587, 26418, - 26247, 26075, 25901, 25725, 25548, 25369, 25188, 25006, 24823, 24638, - 24451, 24264, 24075, 23884, 23692, 23499, 23305, 23110, 22913, 22716, - 22517, 22317, 22116, 21914, 21712, 21508, 21303, 21098, 20892, 20685, - 20477, 20269, 20059, 19850, 19639, 19428, 19217, 19005, 18793, 18580, - 18367, 18153, 17939, 17725, 17511, 17297, 17082, 16867, 16652, 16437, - 16222, 16008, 15793, 15578, 15363, 15149, 14935, 14721, 14507, 14294, - 14081, 13868, 13656, 13445, 13233, 13023, 12813, 12603, 12395, 12186, - 11979, 11772, 11567, 11362, 11157, 10954, 10752, 10551, 10350, 10151, - 9953, 9756, 9560, 9365, 9171, 8979, 8788, 8598, 8410, 8223, - 8037, 7853, 7670, 7489, 7309, 7131, 6954, 6779, 6606, 6435, - 6265, 6096, 5930, 5765, 5603, 5442, 5283, 5126, 4971, 4817, - 4666, 4517, 4370, 4225, 4082, 3941, 3802, 3665, 3531, 3399, - 3269, 3141, 3016, 2893, 2772, 2653, 2537, 2424, 2312, 2204, - 2097, 1993, 1892, 1793, 1696, 1602, 1511, 1422, 1336, 1252, - 1171, 1092, 1016, 943, 873, 805, 740, 677, 617, 560, - 506, 454, 405, 359, 316, 275, 237, 202, 170, 140, - 114, 90, 69, 50, 35, 22, 12, 5, 1, 0}; + 0, 1, 5, 12, 22, 35, 50, 69, 90, 114, 140, + 170, 202, 237, 275, 316, 359, 405, 454, 506, 560, 617, + 677, 740, 805, 873, 943, 1016, 1092, 1171, 1252, 1336, 1422, + 1511, 1602, 1696, 1793, 1892, 1993, 2097, 2204, 2312, 2424, 2537, + 2653, 2772, 2893, 3016, 3141, 3269, 3399, 3531, 3665, 3802, 3941, + 4082, 4225, 4370, 4517, 4666, 4817, 4971, 5126, 5283, 5442, 5603, + 5765, 5930, 6096, 6265, 6435, 6606, 6779, 6954, 7131, 7309, 7489, + 7670, 7853, 8037, 8223, 8410, 8598, 8788, 8979, 9171, 9365, 9560, + 9756, 9953, 10151, 10350, 10551, 10752, 10954, 11157, 11362, 11567, 11772, + 11979, 12186, 12395, 12603, 12813, 13023, 13233, 13445, 13656, 13868, 14081, + 14294, 14507, 14721, 14935, 15149, 15363, 15578, 15793, 16008, 16222, 16437, + 16652, 16867, 17082, 17297, 17511, 17725, 17939, 18153, 18367, 18580, 18793, + 19005, 19217, 19428, 19639, 19850, 20059, 20269, 20477, 20685, 20892, 21098, + 21303, 21508, 21712, 21914, 22116, 22317, 22517, 22716, 22913, 23110, 23305, + 23499, 23692, 23884, 24075, 24264, 24451, 24638, 24823, 25006, 25188, 25369, + 25548, 25725, 25901, 26075, 26247, 26418, 26587, 26754, 26920, 27083, 27245, + 27405, 27563, 27719, 27874, 28026, 28176, 28324, 28470, 28614, 28756, 28896, + 29034, 29169, 29303, 29434, 29563, 29689, 29813, 29935, 30055, 30172, 30287, + 30400, 30510, 30617, 30723, 30825, 30926, 31023, 31119, 31211, 31301, 31389, + 31474, 31556, 31636, 31713, 31788, 31860, 31929, 31996, 32059, 32121, 32179, + 32235, 32288, 32338, 32386, 32430, 32472, 32512, 32548, 32582, 32613, 32641, + 32666, 32689, 32708, 32725, 32739, 32751, 32759, 32765, 32767, 32767, 32765, + 32759, 32751, 32739, 32725, 32708, 32689, 32666, 32641, 32613, 32582, 32548, + 32512, 32472, 32430, 32386, 32338, 32288, 32235, 32179, 32121, 32059, 31996, + 31929, 31860, 31788, 31713, 31636, 31556, 31474, 31389, 31301, 31211, 31119, + 31023, 30926, 30825, 30723, 30617, 30510, 30400, 30287, 30172, 30055, 29935, + 29813, 29689, 29563, 29434, 29303, 29169, 29034, 28896, 28756, 28614, 28470, + 28324, 28176, 28026, 27874, 27719, 27563, 27405, 27245, 27083, 26920, 26754, + 26587, 26418, 26247, 26075, 25901, 25725, 25548, 25369, 25188, 25006, 24823, + 24638, 24451, 24264, 24075, 23884, 23692, 23499, 23305, 23110, 22913, 22716, + 22517, 22317, 22116, 21914, 21712, 21508, 21303, 21098, 20892, 20685, 20477, + 20269, 20059, 19850, 19639, 19428, 19217, 19005, 18793, 18580, 18367, 18153, + 17939, 17725, 17511, 17297, 17082, 16867, 16652, 16437, 16222, 16008, 15793, + 15578, 15363, 15149, 14935, 14721, 14507, 14294, 14081, 13868, 13656, 13445, + 13233, 13023, 12813, 12603, 12395, 12186, 11979, 11772, 11567, 11362, 11157, + 10954, 10752, 10551, 10350, 10151, 9953, 9756, 9560, 9365, 9171, 8979, + 8788, 8598, 8410, 8223, 8037, 7853, 7670, 7489, 7309, 7131, 6954, + 6779, 6606, 6435, 6265, 6096, 5930, 5765, 5603, 5442, 5283, 5126, + 4971, 4817, 4666, 4517, 4370, 4225, 4082, 3941, 3802, 3665, 3531, + 3399, 3269, 3141, 3016, 2893, 2772, 2653, 2537, 2424, 2312, 2204, + 2097, 1993, 1892, 1793, 1696, 1602, 1511, 1422, 1336, 1252, 1171, + 1092, 1016, 943, 873, 805, 740, 677, 617, 560, 506, 454, + 405, 359, 316, 275, 237, 202, 170, 140, 114, 90, 69, + 50, 35, 22, 12, 5, 1, 0}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc index 3523d3ab76..45e9f798ef 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/CMSIS/sin_1k.cc @@ -17,51 +17,47 @@ limitations under the License. const int g_sin_1k_size = 480; const int16_t g_sin_1k[480] = { - 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, - -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, - 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, - -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, - 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, - 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, - -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, - 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, - 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, - -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, - 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, - -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, - 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, - 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, - -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, - 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, - 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, - -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, - 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, - -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, - 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, - 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, - -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, - 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, - 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, - -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, - 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, - -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, - 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, - 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, - -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, - 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, - 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, - -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, - 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, - -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, - 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, - 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, - -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, - 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, - 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, - -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, - 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, - -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, - 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, - 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, - -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, - 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253}; + 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, + -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, + 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, + 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, + -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, + 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, + 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, + -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, + 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, + 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, + -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, + -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, + 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, + -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, + -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, + 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, + 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, + -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, + 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, + 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, + -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, + 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, + 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, + -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, + 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, + 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, + -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, + -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, + 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, + -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, + -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, + 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, + 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, + -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, + 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, + 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, + -3276, -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, + 1253, 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, + 2317, 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, + -3027, -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, + 0, -1253, -2317, -3027, -3276, -3027, -2317, -1253, 0, 1253, 2317, + 3027, 3276, 3027, 2317, 1253, 0, -1253, -2317, -3027, -3276, -3027, + -2317, -1253, 0, 1253, 2317, 3027, 3276, 3027, 2317, 1253, 0, + -1253, -2317, -3027, -3276, -3027, -2317, -1253}; diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc index 47f273c511..95043f857b 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_test.cc @@ -13,15 +13,16 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -/* This file is a modification of the Tensorflow Micro Lite file micro_speech_test.cc */ +/* This file is a modification of the Tensorflow Micro Lite file + * micro_speech_test.cc */ -#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" #include "tensorflow/lite/c/c_api_internal.h" -#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" -#include "tensorflow/lite/experimental/micro/testing/micro_test.h" +#include "tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h" #include "tensorflow/lite/experimental/micro/examples/micro_speech/tiny_conv_model_data.h" #include "tensorflow/lite/experimental/micro/kernels/all_ops_resolver.h" +#include "tensorflow/lite/experimental/micro/micro_error_reporter.h" #include "tensorflow/lite/experimental/micro/micro_interpreter.h" +#include "tensorflow/lite/experimental/micro/testing/micro_test.h" #include "tensorflow/lite/schema/schema_generated.h" #include "tensorflow/lite/version.h" @@ -37,12 +38,11 @@ TF_LITE_MICRO_TEST(TestPreprocessor) { tflite::MicroErrorReporter micro_error_reporter; tflite::ErrorReporter* error_reporter = µ_error_reporter; - uint8_t preprocessed_data[43*49]; - TfLiteStatus preprocess_1sec_status = Preprocess_1sec( - error_reporter, captured_data, preprocessed_data); + uint8_t preprocessed_data[43 * 49]; + TfLiteStatus preprocess_1sec_status = + Preprocess_1sec(error_reporter, captured_data, preprocessed_data); TF_LITE_MICRO_EXPECT_EQ(kTfLiteOk, preprocess_1sec_status); - // Map the model into a usable data structure. This doesn't involve any // copying or parsing, it's a very lightweight operation. const tflite::Model* model = ::tflite::GetModel(g_tiny_conv_model_data); @@ -111,7 +111,6 @@ TF_LITE_MICRO_TEST(TestPreprocessor) { g_no_score = output->data.uint8[kNoIndex]; error_reporter->Report("Ran successfully\n"); - } TF_LITE_MICRO_TESTS_END diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc index 743d229224..7b7db173ab 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.cc @@ -145,11 +145,10 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, } TfLiteStatus Preprocess_1sec(tflite::ErrorReporter* error_reporter, - const int16_t* input, uint8_t* output) { + const int16_t* input, uint8_t* output) { int i; - for(i=0; i<49; i++) { - Preprocess(error_reporter, input+i*320, 480, 43, output+i*43); + for (i = 0; i < 49; i++) { + Preprocess(error_reporter, input + i * 320, 480, 43, output + i * 43); } return kTfLiteOk; } - diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h index 0057b4505f..d710beecee 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/preprocessor.h @@ -29,6 +29,6 @@ TfLiteStatus Preprocess(tflite::ErrorReporter* error_reporter, uint8_t* output); TfLiteStatus Preprocess_1sec(tflite::ErrorReporter* error_reporter, - const int16_t* input, uint8_t* output); + const int16_t* input, uint8_t* output); #endif // TENSORFLOW_LITE_EXPERIMENTAL_MICRO_EXAMPLES_MICRO_SPEECH_PREPROCESSOR_H_ -- GitLab From 69ce586e9731bd2e8e04e056867429384f4d1416 Mon Sep 17 00:00:00 2001 From: Mihai Maruseac Date: Thu, 20 Dec 2018 15:36:11 -0800 Subject: [PATCH 0205/1765] Fix ScatterNd empty shape bug. PiperOrigin-RevId: 226404765 --- tensorflow/core/kernels/scatter_nd_op.cc | 42 ++++++++++++++++-------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/tensorflow/core/kernels/scatter_nd_op.cc b/tensorflow/core/kernels/scatter_nd_op.cc index b466e57249..5a14ab6330 100644 --- a/tensorflow/core/kernels/scatter_nd_op.cc +++ b/tensorflow/core/kernels/scatter_nd_op.cc @@ -49,6 +49,19 @@ typedef Eigen::GpuDevice GPUDevice; typedef Eigen::SyclDevice SYCLDevice; #endif // TENSORFLOW_USE_SYCL +// Returns true if the three tensors have valid number of elements +// If shape_input has 0 elements, then we need to have indices and updates with +// exactly 0 elements too, otherwise we should error. If indices has 0 elements +// then updates should also have 0 elements, otherwise we should error. +bool ValidEmptyOutputShape(int64 num_inputs, int64 num_indices, + int64 num_updates) { + if (num_indices == 0 && num_updates == 0) { + return true; // regardless of num_inputs ?= 0, covers both cases + } + // now we want all 3 tensors to have values + return (num_inputs != 0 && num_indices != 0 && num_updates != 0); +} + template class ScatterNdOp : public OpKernel { public: @@ -77,12 +90,12 @@ class ScatterNdOp : public OpKernel { OP_REQUIRES_OK(c, TensorShapeUtils::MakeShape(vec.data(), vec.size(), &shape)); - OP_REQUIRES( - c, - (shape.num_elements() > 0 || (indices.shape().num_elements() == 0 && - updates.shape().num_elements() == 0)), - errors::InvalidArgument( - "Indices and updates specified for empty output shape")); + OP_REQUIRES(c, + ValidEmptyOutputShape(shape_input.NumElements(), + indices.shape().num_elements(), + updates.shape().num_elements()), + errors::InvalidArgument( + "Indices and updates specified for empty output shape")); const int64 outer_dims = indices.shape().dims() - 1; @@ -148,12 +161,12 @@ class TensorScatterOp : public OpKernel { TensorShape shape = input.shape(); - OP_REQUIRES( - c, - (shape.num_elements() > 0 || (indices.shape().num_elements() == 0 && - updates.shape().num_elements() == 0)), - errors::InvalidArgument( - "Indices and updates specified for empty output shape")); + OP_REQUIRES(c, + ValidEmptyOutputShape(shape.num_elements(), + indices.shape().num_elements(), + updates.shape().num_elements()), + errors::InvalidArgument( + "Indices and updates specified for empty output shape")); const int64 outer_dims = indices.shape().dims() - 1; @@ -546,8 +559,9 @@ Status PrepareAndValidateInputs(const TensorShape& params_shape, "got shape: ", params_shape.DebugString()); } - if (!(params_shape.num_elements() > 0 || - (indices.NumElements() == 0 && updates.NumElements() == 0))) { + if (!ValidEmptyOutputShape(params_shape.num_elements(), + indices_shape.num_elements(), + updates_shape.num_elements())) { return errors::InvalidArgument( "Indices and updates specified for empty output. indices shape: ", indices.shape().DebugString()); -- GitLab From dd3ae1ae55e725e1cb421b9a79d135c335913273 Mon Sep 17 00:00:00 2001 From: Rick Chao Date: Thu, 20 Dec 2018 15:46:23 -0800 Subject: [PATCH 0206/1765] Replace mode string literals 'train', 'test', and 'predict' in Keras with ModeKeys constants. PiperOrigin-RevId: 226406277 --- .../engine/distributed_training_utils.py | 35 +++++++++---------- .../keras/engine/training_distributed.py | 6 ++-- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/tensorflow/python/keras/engine/distributed_training_utils.py b/tensorflow/python/keras/engine/distributed_training_utils.py index 38a1a57522..a4fc2cf196 100644 --- a/tensorflow/python/keras/engine/distributed_training_utils.py +++ b/tensorflow/python/keras/engine/distributed_training_utils.py @@ -646,7 +646,7 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): inputs: List or dict of model inputs. targets: Optional list of model targets. sample_weights: Optional list of sample weight arrays. - mode: One of 'train'/'test'/'predict'. + mode: One of ModeKeys.TRAIN/ModeKeys.TEST/ModeKeys.PREDICT. Returns: Feed values for the model in the given mode. @@ -655,7 +655,7 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): inputs, targets, sample_weights = _get_input_from_iterator(inputs, model) inputs = flatten_perdevice_values(strategy, inputs) targets = flatten_perdevice_values(strategy, targets) - if mode == 'predict': + if mode == ModeKeys.PREDICT: sample_weights = [] targets = [] else: @@ -663,7 +663,8 @@ def _prepare_feed_values(model, inputs, targets, sample_weights, mode): None for _ in range(len(model.outputs) * strategy.num_replicas_in_sync) ] ins = inputs + targets + sample_weights - if mode == 'train' and not isinstance(K.symbolic_learning_phase(), int): + if mode == ModeKeys.TRAIN and not isinstance(K.symbolic_learning_phase(), + int): ins += [True] return ins @@ -831,7 +832,7 @@ def _make_execution_function(model, mode): if not model._distributed_model: if model._compile_distribution: clone_model_on_replicas( - model, strategy, make_callback_model=(mode == 'train')) + model, strategy, make_callback_model=(mode == ModeKeys.TRAIN)) else: _build_distributed_network(model, strategy) @@ -846,7 +847,7 @@ def _make_execution_function(model, mode): grouped_session_args) = strategy.extended.call_for_each_replica( _per_device_function, args=(model._distributed_model,)) - if mode == 'train': + if mode == ModeKeys.TRAIN: # Initialize the variables in the replicated model. This is necessary for # multi-worker training because on some workers, initialization is not # needed. This method does initialization or waiting for initialization @@ -857,14 +858,13 @@ def _make_execution_function(model, mode): # Unwrapping per device values gives you a list of values that can be # used to construct a new train function that is composed of update ops on # all the devices over which the model is distributed. - (all_inputs, all_outputs, all_updates, - all_session_args) = unwrap_values( - strategy, - grouped_inputs, - grouped_outputs, - grouped_updates, - grouped_session_args, - with_loss_tensor=(mode != 'predict')) + (all_inputs, all_outputs, all_updates, all_session_args) = unwrap_values( + strategy, + grouped_inputs, + grouped_outputs, + grouped_updates, + grouped_session_args, + with_loss_tensor=(mode != ModeKeys.PREDICT)) return K.function( all_inputs, @@ -880,7 +880,7 @@ def _make_eager_execution_function(model, mode): if not model._distributed_model: if model._compile_distribution: clone_model_on_replicas( - model, strategy, make_callback_model=(mode == 'train')) + model, strategy, make_callback_model=(mode == ModeKeys.TRAIN)) else: _build_distributed_network(model, strategy) @@ -904,7 +904,7 @@ def _make_eager_execution_function(model, mode): strategy, grouped_inputs, grouped_outputs, - with_loss_tensor=(mode != 'predict')) + with_loss_tensor=(mode != ModeKeys.PREDICT)) return K.function( all_inputs, @@ -925,7 +925,7 @@ def _copy_weights_to_distributed_model(original_model, grouped_model): def _copy_weights_to_original_model(model, grouped_model, mode): """Copies weights from first distributed model back to original model.""" - if model._distribution_strategy and mode == 'train': + if model._distribution_strategy and mode == ModeKeys.TRAIN: updated_weights = model._distribution_strategy.unwrap( grouped_model)[0].get_weights() model.set_weights(updated_weights) @@ -933,7 +933,7 @@ def _copy_weights_to_original_model(model, grouped_model, mode): def _per_device_aggregate_batch(batch_outs, model, mode): """Aggregates the per-device batch-level outputs from a distributed step.""" - if model._distribution_strategy is not None and mode == 'predict': + if model._distribution_strategy is not None and mode == ModeKeys.PREDICT: total_batch_outs = [] for i in range(len(model.outputs)): num_replicas = model._distribution_strategy.num_replicas_in_sync @@ -949,4 +949,3 @@ def _reset_metrics(model, distributed_model=None): distributed_model or model._distribution_strategy.unwrap(model._distributed_model)[0]) distributed_model.reset_metrics() - diff --git a/tensorflow/python/keras/engine/training_distributed.py b/tensorflow/python/keras/engine/training_distributed.py index 3102a0127a..0bd79f2b47 100644 --- a/tensorflow/python/keras/engine/training_distributed.py +++ b/tensorflow/python/keras/engine/training_distributed.py @@ -151,7 +151,7 @@ def evaluate_distributed(model, steps=steps) if distributed_training_utils.is_tpu_strategy(model._distribution_strategy): - # TODO(fchollet): why aren't callbacks supported here? + # TODO(fchollet): why aren't callbacks supported here? return experimental_tpu_test_loop( model, iterator=iterator, verbose=verbose, steps=steps) else: @@ -391,7 +391,7 @@ def experimental_tpu_fit_loop(model, # Copy the weights back from the replicated model to the original model. with current_strategy.scope(): distributed_training_utils._copy_weights_to_original_model( - model, model._distributed_model_train, 'train') + model, model._distributed_model_train, ModeKeys.TRAIN) scope.__exit__(None, None, None) return model.history @@ -632,5 +632,3 @@ def experimental_tpu_predict_loop(model, iterator, verbose=0, steps=None): np.concatenate(unconcatenated_outs[i], axis=0) for i in range(len(unconcatenated_outs)) ] - - -- GitLab From 9aba8353341e438356da71e7ff6959b5bbba277a Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 15:55:55 -0800 Subject: [PATCH 0207/1765] Avoid keeping references to TF Tensors, in order to not prevent tensor-forwarding optimizations done by the TF ops. PiperOrigin-RevId: 226407654 --- tensorflow/lite/delegates/flex/buffer_map.cc | 14 +++++ tensorflow/lite/delegates/flex/buffer_map.h | 21 +++++++ .../lite/delegates/flex/buffer_map_test.cc | 58 +++++++++++++++++++ tensorflow/lite/delegates/flex/kernel.cc | 34 +++++++++++ 4 files changed, 127 insertions(+) diff --git a/tensorflow/lite/delegates/flex/buffer_map.cc b/tensorflow/lite/delegates/flex/buffer_map.cc index 0d0c953636..9408efaaa1 100644 --- a/tensorflow/lite/delegates/flex/buffer_map.cc +++ b/tensorflow/lite/delegates/flex/buffer_map.cc @@ -173,5 +173,19 @@ void BufferMap::SetFromTensorFlow(int tensor_index, tensorflow::Tensor tensor) { owned_by_tf_.insert(tensor_index); } +void BufferMap::RemoveTensor(int tensor_index) { + id_to_tensor_.erase(tensor_index); +} + +void BufferMap::RemoveTensorsNotInSet(const std::set& keep) { + for (auto it = id_to_tensor_.begin(); it != id_to_tensor_.end();) { + if (keep.count(it->first) == 0 && IsTensorFlowTensor(it->first)) { + it = id_to_tensor_.erase(it); + } else { + ++it; + } + } +} + } // namespace flex } // namespace tflite diff --git a/tensorflow/lite/delegates/flex/buffer_map.h b/tensorflow/lite/delegates/flex/buffer_map.h index b73ed88d37..6c1df4c836 100644 --- a/tensorflow/lite/delegates/flex/buffer_map.h +++ b/tensorflow/lite/delegates/flex/buffer_map.h @@ -52,11 +52,32 @@ class BufferMap { // shallow copy. void SetFromTensorFlow(int tensor_index, tensorflow::Tensor tensor); + // Removes any association of a tensor and the given 'tensor_index'. + void RemoveTensor(int tensor_index); + + // Removes all *TF* tensors that are not contained in the given 'keep' set. + void RemoveTensorsNotInSet(const std::set& keep); + // Same as above but creates a new tensorflow::Tensor with a copy of the // given TfLiteTensor's data. void SetFromTfLite(int tensor_index, const TfLiteTensor* tensor); + // Sets a bit indicating that the tensor associated with 'tensor_index' can + // be use by TF's forwarding optimizations. + void SetForwardable(int tensor_index) { forwardable_.insert(tensor_index); } + + // Returns true if this tensor has been explicitly marks as forwardable by + // a call to SetForwardable(). + bool IsForwardable(int tensor_index) const { + return forwardable_.count(tensor_index) > 0; + } + private: + // List of tensors that can be used by TF in its forwarding optimization. + // Doing so allows an input tensor to be modified and used as the output + // tensor. The delegate takes care of not holding any references to tensors + // in this list while Eager is executing the corresponding op. + std::set forwardable_; // Mapping from TL Lite tensor ID to TensorFlow's Tensor. All tensors that // are inputs or outputs of a subgraph will be added here, irrespective of // whether their data are managed by TF Lite or TensorFlow. diff --git a/tensorflow/lite/delegates/flex/buffer_map_test.cc b/tensorflow/lite/delegates/flex/buffer_map_test.cc index 9e8472f1e7..2148bfe8e2 100644 --- a/tensorflow/lite/delegates/flex/buffer_map_test.cc +++ b/tensorflow/lite/delegates/flex/buffer_map_test.cc @@ -222,6 +222,64 @@ TEST(BufferMapTest, TensorFlowOverwritesTfLite) { ElementsAre(0, 0, 0, 0.123f, 0, 0)); } +TEST(BufferMapTest, RemoveTensorFlowTensor) { + tensorflow::Tensor t1 = + MakeTensor({1, 2, 1, 3}, {0, 0, 0, 0.123f, 0, 0}); + BufferMap buffer_map; + buffer_map.SetFromTensorFlow(0, t1); + EXPECT_TRUE(buffer_map.HasTensor(0)); + buffer_map.RemoveTensor(0); + EXPECT_FALSE(buffer_map.HasTensor(0)); +} + +TEST(BufferMapTest, RemoveTfLiteTensor) { + UniqueTfLiteTensor t2 = + MakeLiteTensor({1, 2, 4}, {0, 0, 0, 3, 0, 0, 1, 2}); + BufferMap buffer_map; + buffer_map.SetFromTfLite(0, t2.get()); + EXPECT_TRUE(buffer_map.HasTensor(0)); + buffer_map.RemoveTensor(0); + EXPECT_FALSE(buffer_map.HasTensor(0)); +} + +TEST(BufferMapTest, RemoveTensorsInSet) { + tensorflow::Tensor t1 = + MakeTensor({1, 2, 1, 3}, {0, 0, 0, 0.123f, 0, 0}); + UniqueTfLiteTensor t2 = + MakeLiteTensor({1, 2, 4}, {0, 0, 0, 3, 0, 0, 1, 2}); + BufferMap buffer_map; + + auto list_existing_tensors = [&buffer_map]() { + std::vector result; + for (int i : {0, 1, 2, 3}) { + if (buffer_map.HasTensor(i)) { + result.push_back(i); + } + } + return result; + }; + + buffer_map.SetFromTensorFlow(0, t1); + buffer_map.SetFromTfLite(1, t2.get()); + buffer_map.SetFromTfLite(2, t2.get()); + buffer_map.SetFromTensorFlow(3, t1); + + EXPECT_THAT(list_existing_tensors(), ElementsAre(0, 1, 2, 3)); + + buffer_map.RemoveTensorsNotInSet({0, 3}); + EXPECT_THAT(list_existing_tensors(), ElementsAre(0, 1, 2, 3)); + + buffer_map.RemoveTensorsNotInSet({}); + EXPECT_THAT(list_existing_tensors(), ElementsAre(1, 2)); +} + +TEST(BufferMapTest, Forwardable) { + BufferMap buffer_map; + EXPECT_FALSE(buffer_map.IsForwardable(0)); + buffer_map.SetForwardable(0); + EXPECT_TRUE(buffer_map.IsForwardable(0)); +} + } // namespace } // namespace flex } // namespace tflite diff --git a/tensorflow/lite/delegates/flex/kernel.cc b/tensorflow/lite/delegates/flex/kernel.cc index 4e66921146..d6e12ef650 100644 --- a/tensorflow/lite/delegates/flex/kernel.cc +++ b/tensorflow/lite/delegates/flex/kernel.cc @@ -105,6 +105,12 @@ tensorflow::Status ExecuteFlexOp(tensorflow::EagerContext* eager_context, buffer_map->GetTensor(input_index), nullptr, nullptr, nullptr); op.AddInput(handle); handle->Unref(); + + if (buffer_map->IsForwardable(input_index)) { + // Take it out of the map, so Eager/TF can reuse the buffer for an output + // tensor of the op. + buffer_map->RemoveTensor(input_index); + } } int num_retvals = outputs.size(); @@ -233,6 +239,10 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { "device has not been registered, presumably because some symbols from " "tensorflow/core:core_cpu_impl were not linked into the binary."); + // We will keep track of the number of references to each tensor in the + // graph, so we can make them "forwardable" if there is only one reference. + std::map tensor_ref_count; + // Whenever we find a constant tensor, insert it in the buffer map. BufferMap* buffer_map = op_data->buffer_map; for (auto tensor_index : op_data->subgraph_inputs) { @@ -242,12 +252,29 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { buffer_map->SetFromTfLite(tensor_index, tensor); } } + ++tensor_ref_count[tensor_index]; } // All output tensors are allocated by TensorFlow/Eager, so we // mark them as kTfLiteDynamic. for (auto tensor_index : op_data->subgraph_outputs) { SetTensorToDynamic(&context->tensors[tensor_index]); + ++tensor_ref_count[tensor_index]; + } + + for (const auto& node_data : op_data->nodes) { + for (int tensor_index : node_data.inputs) { + ++tensor_ref_count[tensor_index]; + } + } + + for (const auto& x : tensor_ref_count) { + if (x.second == 1) { + // This tensor is referenced once by a single op. We can allow the TF + // kernel to "forward" it to the output, meaning its buffer will be + // reused and overwritten. + buffer_map->SetForwardable(x.first); + } } return kTfLiteOk; @@ -303,6 +330,13 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { tensor->data_is_stale = true; } + // We don't need to keep track of internal TF tensors any longer, so take + // them out of the buffer_map, but make sure we keep all the one we might + // need for other subgraphs, or as final output of inference. + const auto& outputs = op_data->subgraph_outputs; + std::set keep(outputs.begin(), outputs.end()); + buffer_map->RemoveTensorsNotInSet(keep); + return kTfLiteOk; } -- GitLab From 81fa63d5dd34b9a8046f79c16731efa4dee9dd63 Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Thu, 20 Dec 2018 16:08:54 -0800 Subject: [PATCH 0208/1765] roll-forward (yet again): Introduce a logger overriding mechanism. Before: the whole program has to link against a unique Logger::Singleton(), and there is no default. It's hard to control when to use the custom logger vs the default. After: By default always use the default logger. The pubsub logger overrides via REGISTER_MODULE_INITIALIZER. Multiple implementations can co-exist. This simplifies the registration management and dependency management. PiperOrigin-RevId: 226409838 --- tensorflow/core/BUILD | 20 ++----------- .../core/platform/default/build_config/BUILD | 5 ---- .../core/platform/{default => }/logger.cc | 25 +++++++++------- tensorflow/core/platform/logger.h | 19 +++++++++++- tensorflow/stream_executor/BUILD | 3 ++ .../stream_executor/stream_executor_pimpl.cc | 30 ++++++++++++++++++- 6 files changed, 66 insertions(+), 36 deletions(-) rename tensorflow/core/platform/{default => }/logger.cc (72%) diff --git a/tensorflow/core/BUILD b/tensorflow/core/BUILD index f7eab3e359..2abaadc657 100644 --- a/tensorflow/core/BUILD +++ b/tensorflow/core/BUILD @@ -445,7 +445,8 @@ cc_library( ) cc_library( - name = "logger_interface", + name = "logger", + srcs = ["platform/logger.cc"], hdrs = ["platform/logger.h"], copts = tf_copts(), visibility = ["//visibility:public"], @@ -455,23 +456,6 @@ cc_library( ], ) -cc_library( - name = "default_logger", - srcs = ["platform/default/logger.cc"], - hdrs = ["platform/logger.h"], - deps = [ - "//tensorflow/core:lib_proto_parsing", - "//tensorflow/core:logger_interface", - ], -) - -cc_library( - name = "logger", - hdrs = ["platform/logger.h"], - visibility = ["//visibility:public"], - deps = ["//tensorflow/core/platform/default/build_config:logger"], -) - filegroup( name = "platform_env_hdrs", srcs = [ diff --git a/tensorflow/core/platform/default/build_config/BUILD b/tensorflow/core/platform/default/build_config/BUILD index ee6936b372..da1f66dc67 100644 --- a/tensorflow/core/platform/default/build_config/BUILD +++ b/tensorflow/core/platform/default/build_config/BUILD @@ -275,8 +275,3 @@ alias( actual = ":mobile_srcs", visibility = ["//visibility:public"], ) - -alias( - name = "logger", - actual = "//tensorflow/core:default_logger", -) diff --git a/tensorflow/core/platform/default/logger.cc b/tensorflow/core/platform/logger.cc similarity index 72% rename from tensorflow/core/platform/default/logger.cc rename to tensorflow/core/platform/logger.cc index 54b1a1a67c..f5a961e4d3 100644 --- a/tensorflow/core/platform/default/logger.cc +++ b/tensorflow/core/platform/logger.cc @@ -18,17 +18,20 @@ limitations under the License. #include "tensorflow/core/platform/logging.h" namespace tensorflow { +namespace { -Logger* Logger::Singleton() { - class DefaultLogger : public Logger { - private: - void DoLogProto(google::protobuf::Any* proto) override { - VLOG(2) << proto->ShortDebugString(); - } - void DoFlush() override {} - }; - static Logger* instance = new DefaultLogger(); - return instance; -} +class DefaultLogger : public Logger { + private: + void DoLogProto(google::protobuf::Any* proto) override { + VLOG(2) << proto->ShortDebugString(); + } + void DoFlush() override {} +}; + +} // namespace + +Logger::FactoryFunc Logger::singleton_factory_ = []() -> Logger* { + return new DefaultLogger(); +}; } // namespace tensorflow diff --git a/tensorflow/core/platform/logger.h b/tensorflow/core/platform/logger.h index 5d304bea63..f0bfef4f2d 100644 --- a/tensorflow/core/platform/logger.h +++ b/tensorflow/core/platform/logger.h @@ -26,7 +26,22 @@ namespace tensorflow { // log anything to a non-local place, e.g. a database. class Logger { public: - static Logger* Singleton(); + // The singleton is supposed to be used in the following steps: + // * At program start time, REGISTER_MOUDLE_INITIALIZER calls + // SetSingletonFactory. + // * At some point in the program execution, Singleton() is called for the + // first time, initializing the logger. + // * Succeeding calls to Singleton() return the initiailized logger. + using FactoryFunc = Logger* (*)(); + + static void SetSingletonFactory(FactoryFunc factory) { + singleton_factory_ = factory; + } + + static Logger* Singleton() { + static Logger* instance = singleton_factory_(); + return instance; + } virtual ~Logger() = default; @@ -44,6 +59,8 @@ class Logger { private: virtual void DoLogProto(google::protobuf::Any* proto) = 0; virtual void DoFlush() = 0; + + static FactoryFunc singleton_factory_; }; } // namespace tensorflow diff --git a/tensorflow/stream_executor/BUILD b/tensorflow/stream_executor/BUILD index 00c23b8d17..c43efc799c 100644 --- a/tensorflow/stream_executor/BUILD +++ b/tensorflow/stream_executor/BUILD @@ -54,7 +54,9 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":dnn_proto_cc_impl", + ":logging_proto_cc_impl", "//tensorflow/core:lib", + "//tensorflow/core:logger", "//tensorflow/core:ptr_util", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/strings", @@ -71,6 +73,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":dnn_proto_cc", + ":logging_proto_cc", "//tensorflow/core:lib", "//tensorflow/core:ptr_util", "@com_google_absl//absl/strings", diff --git a/tensorflow/stream_executor/stream_executor_pimpl.cc b/tensorflow/stream_executor/stream_executor_pimpl.cc index ee3d2b6da0..cb67a906a8 100644 --- a/tensorflow/stream_executor/stream_executor_pimpl.cc +++ b/tensorflow/stream_executor/stream_executor_pimpl.cc @@ -23,6 +23,7 @@ limitations under the License. #include #include "absl/strings/str_cat.h" +#include "tensorflow/core/platform/logger.h" #include "tensorflow/core/util/env_var.h" #include "tensorflow/stream_executor/blas.h" #include "tensorflow/stream_executor/fft.h" @@ -33,6 +34,7 @@ limitations under the License. #include "tensorflow/stream_executor/lib/str_util.h" #include "tensorflow/stream_executor/lib/stringprintf.h" #include "tensorflow/stream_executor/lib/threadpool.h" +#include "tensorflow/stream_executor/logging.pb.h" #include "tensorflow/stream_executor/platform/port.h" #include "tensorflow/stream_executor/rng.h" #include "tensorflow/stream_executor/stream_executor_internal.h" @@ -192,6 +194,8 @@ StreamExecutor::StreamExecutor( platform_kind_ = PlatformKind::kOpenCL; } else if (port::Lowercase(platform_->Name()) == "host") { platform_kind_ = PlatformKind::kHost; + } else { + platform_kind_ = PlatformKind::kInvalid; } } @@ -217,7 +221,31 @@ StreamExecutor::~StreamExecutor() { port::Status StreamExecutor::Init(int device_ordinal, DeviceOptions device_options) { device_ordinal_ = device_ordinal; - return implementation_->Init(device_ordinal, std::move(device_options)); + TF_RETURN_IF_ERROR( + implementation_->Init(device_ordinal, std::move(device_options))); + + if (platform_kind_ == PlatformKind::kCuda) { + CudaInfo info; + + int cc_major, cc_minor; + GetDeviceDescription().cuda_compute_capability(&cc_major, &cc_minor); + info.mutable_compute_capability()->set_major(cc_major); + info.mutable_compute_capability()->set_minor(cc_minor); + + if (auto *dnn = AsDnn()) { + port::StatusOr version_or = dnn->GetVersion(); + if (version_or.ok()) { + const auto &version = version_or.ValueOrDie(); + info.mutable_cudnn_version()->set_major(version.major_version()); + info.mutable_cudnn_version()->set_minor(version.minor_version()); + info.mutable_cudnn_version()->set_patch(version.patch()); + } + } + + tensorflow::Logger::Singleton()->LogProto(info); + } + + return port::Status::OK(); } port::Status StreamExecutor::Init() { -- GitLab From cb92d9f3aafa65796737ccf834f254c719147ffc Mon Sep 17 00:00:00 2001 From: Mark Heffernan Date: Thu, 20 Dec 2018 16:10:42 -0800 Subject: [PATCH 0209/1765] Add depth field to CallGraphNode. Depth is the length of the longest path from the entry node (or other root node in the call graph) to the node in the call graph. Change CallGraph::NearestAncestorsInSameComputation to use this new field. This makes this method linear in the height of the call graph rather than quadratic. PiperOrigin-RevId: 226410144 --- tensorflow/compiler/xla/service/call_graph.cc | 72 +++++++++++++++++-- tensorflow/compiler/xla/service/call_graph.h | 14 ++++ .../compiler/xla/service/call_graph_test.cc | 24 ++++++- 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/tensorflow/compiler/xla/service/call_graph.cc b/tensorflow/compiler/xla/service/call_graph.cc index 173b3fc05f..94af788c54 100644 --- a/tensorflow/compiler/xla/service/call_graph.cc +++ b/tensorflow/compiler/xla/service/call_graph.cc @@ -236,6 +236,41 @@ void CallGraph::SetCallContexts() { } } +void CallGraph::SetNodeDepths() { + std::queue worklist; + + // Initialize node depths to -1. + for (CallGraphNode& node : nodes_) { + node.set_depth(-1); + } + + // Initialize worklist with all roots of the call graph (computations without + // callers). + for (const HloComputation* computation : module_->computations()) { + CallGraphNode& node = GetNode(computation); + if (node.callers().empty()) { + node.set_depth(0); + worklist.push(&node); + } + } + + while (!worklist.empty()) { + CallGraphNode* node = worklist.front(); + worklist.pop(); + for (const HloComputation* callee : node->callees()) { + CallGraphNode& callee_node = GetNode(callee); + if (callee_node.depth() < node->depth() + 1) { + callee_node.set_depth(node->depth() + 1); + worklist.push(&callee_node); + } + } + } + + for (CallGraphNode& node : nodes_) { + CHECK_NE(node.depth(), -1); + } +} + /* static */ std::unique_ptr CallGraph::Build(const HloModule* module) { // Constructor for CallGraph is private so absl::make_unique can't be used. @@ -271,6 +306,8 @@ std::unique_ptr CallGraph::Build(const HloModule* module) { } call_graph->SetCallContexts(); + call_graph->SetNodeDepths(); + XLA_VLOG_LINES(1, call_graph->ToString()); return call_graph; @@ -352,15 +389,38 @@ CallGraph::NearestAncestorsInSameComputation(HloInstruction* a, // Iterate through the callee->caller chains and find the earliest common // element. - for (HloInstruction* a_ancestor = a; a_ancestor != nullptr; - a_ancestor = next_caller(a_ancestor)) { - for (HloInstruction* b_ancestor = b; b_ancestor != nullptr; - b_ancestor = next_caller(b_ancestor)) { - if (a_ancestor->parent() == b_ancestor->parent()) { - return {a_ancestor, b_ancestor}; + HloInstruction* a_ancestor = a; + HloInstruction* b_ancestor = b; + int a_depth = GetNode(a->parent()).depth(); + int b_depth = GetNode(b->parent()).depth(); + + // Advance a_ancestor (b_ancestor) up the call chain until the call depth of + // a_ancestor or b_ancestor are the same. Necessarily each call to next_caller + // reduces the depth by exactly one. + if (a_depth > b_depth) { + for (int i = 0; i < a_depth - b_depth; ++i) { + a_ancestor = next_caller(a_ancestor); + if (a_ancestor == nullptr) { + return {nullptr, nullptr}; + } + } + } else if (b_depth > a_depth) { + for (int i = 0; i < b_depth - a_depth; ++i) { + b_ancestor = next_caller(b_ancestor); + if (b_ancestor == nullptr) { + return {nullptr, nullptr}; } } } + + while ((a_ancestor != nullptr) && (b_ancestor != nullptr)) { + if (a_ancestor->parent() == b_ancestor->parent()) { + return {a_ancestor, b_ancestor}; + } + + a_ancestor = next_caller(a_ancestor); + b_ancestor = next_caller(b_ancestor); + } return {nullptr, nullptr}; } diff --git a/tensorflow/compiler/xla/service/call_graph.h b/tensorflow/compiler/xla/service/call_graph.h index 05c7c99873..f41367914c 100644 --- a/tensorflow/compiler/xla/service/call_graph.h +++ b/tensorflow/compiler/xla/service/call_graph.h @@ -121,6 +121,11 @@ class CallGraphNode { // Returns the context in which this computation is called. CallContext context() const { return context_; } + // Returns the depth of this node in the call graph. The depth is defined as + // the length of the longest call chain from a computation with no callers + // (usually the entry computation node) to this node. + int depth() const { return depth_; } + string ToString() const; private: @@ -130,6 +135,9 @@ class CallGraphNode { // Sets the context in which this computation is called. void set_context(CallContext value) { context_ = value; } + // Sets the depth of this node in the graph. + void set_depth(int value) { depth_ = value; } + // Adds a callsite which calls this computation. Updates callers to include // the calling computation. void AddCallerCallSite(const CallSite& caller_callsite); @@ -164,6 +172,9 @@ class CallGraphNode { // The context in which this computation is called. CallContext context_ = CallContext::kNone; + + // The depth of this node in the call graph. + int depth_ = 0; }; // The call graph for an HLO module. The graph includes a node for each @@ -248,6 +259,9 @@ class CallGraph { // Sets the call contexts for every node in the graph. void SetCallContexts(); + // Sets the call node depths for every node in the graph. + void SetNodeDepths(); + // Helper method for VisitNodes(). Traverses the call graph from 'node' in DFS // post order (callee before caller) calling visitor_func on each node. Adds // nodes to 'visited' as each node is visited. Skips nodes already in diff --git a/tensorflow/compiler/xla/service/call_graph_test.cc b/tensorflow/compiler/xla/service/call_graph_test.cc index a3ac2568b0..7924134200 100644 --- a/tensorflow/compiler/xla/service/call_graph_test.cc +++ b/tensorflow/compiler/xla/service/call_graph_test.cc @@ -102,6 +102,7 @@ TEST_F(CallGraphTest, SingletonComputation) { const CallGraphNode& node = call_graph->GetNode(computation); EXPECT_EQ(computation, node.computation()); + EXPECT_EQ(node.depth(), 0); EXPECT_TRUE(node.callsites().empty()); EXPECT_TRUE(node.callees().empty()); EXPECT_TRUE(node.caller_callsites().empty()); @@ -122,11 +123,13 @@ TEST_F(CallGraphTest, UnreachableComputation) { EXPECT_EQ(2, call_graph->nodes().size()); const CallGraphNode& entry_node = call_graph->GetNode(entry_computation); + EXPECT_EQ(entry_node.depth(), 0); EXPECT_EQ(entry_computation, entry_node.computation()); EXPECT_EQ(CallContext::kSequential, entry_node.context()); const CallGraphNode& unreachable_node = call_graph->GetNode(unreachable_computation); + EXPECT_EQ(unreachable_node.depth(), 0); EXPECT_EQ(unreachable_computation, unreachable_node.computation()); EXPECT_EQ(CallContext::kSequential, unreachable_node.context()); } @@ -145,6 +148,7 @@ TEST_F(CallGraphTest, ParallelComputation) { const CallGraphNode& entry_node = call_graph->GetNode(entry_computation); EXPECT_EQ(entry_computation, entry_node.computation()); + EXPECT_EQ(entry_node.depth(), 0); EXPECT_EQ(CallContext::kSequential, entry_node.context()); EXPECT_EQ(5, entry_node.callsites().size()); EXPECT_EQ(1, entry_node.callees().size()); @@ -153,6 +157,7 @@ TEST_F(CallGraphTest, ParallelComputation) { const CallGraphNode& map_node = call_graph->GetNode(map_computation); EXPECT_EQ(map_computation, map_node.computation()); + EXPECT_EQ(map_node.depth(), 1); EXPECT_EQ(CallContext::kParallel, map_node.context()); EXPECT_TRUE(map_node.callsites().empty()); EXPECT_TRUE(map_node.callees().empty()); @@ -234,6 +239,7 @@ TEST_F(CallGraphTest, ContextBothComputations) { EXPECT_EQ(entry_node.GetCallSite(map), &map_callsite); const CallGraphNode& sub_node = call_graph->GetNode(subcomputation); + EXPECT_EQ(sub_node.depth(), 1); EXPECT_EQ(CallContext::kBoth, sub_node.context()); } @@ -264,6 +270,7 @@ TEST_F(CallGraphTest, ComputationWithConditional) { EXPECT_EQ(3, call_graph->nodes().size()); const CallGraphNode& entry_node = call_graph->GetNode(entry_computation); + EXPECT_EQ(entry_node.depth(), 0); EXPECT_EQ(entry_computation, entry_node.computation()); EXPECT_EQ(1, entry_node.callsites().size()); @@ -275,11 +282,13 @@ TEST_F(CallGraphTest, ComputationWithConditional) { EXPECT_EQ(entry_node.GetCallSite(conditional), &conditional_callsite); const CallGraphNode& true_node = call_graph->GetNode(true_computation); + EXPECT_EQ(true_node.depth(), 1); EXPECT_TRUE(true_node.callees().empty()); EXPECT_EQ(1, true_node.callers().size()); EXPECT_EQ(entry_computation, true_node.callers()[0]); const CallGraphNode& false_node = call_graph->GetNode(false_computation); + EXPECT_EQ(false_node.depth(), 1); EXPECT_TRUE(false_node.callees().empty()); EXPECT_EQ(1, false_node.callers().size()); EXPECT_EQ(entry_computation, false_node.callers()[0]); @@ -332,9 +341,21 @@ TEST_F(CallGraphTest, ComplexGraph) { EXPECT_EQ(5, call_graph->nodes().size()); EXPECT_FALSE(call_graph->IsFlattened()); + const CallGraphNode& entry_node = call_graph->GetNode(entry_computation); + const CallGraphNode& a_node = call_graph->GetNode(a_computation); + const CallGraphNode& b_node = call_graph->GetNode(b_computation); + const CallGraphNode& c_node = call_graph->GetNode(c_computation); + const CallGraphNode& cond_node = call_graph->GetNode(cond_computation); + + // Verify depths. + EXPECT_EQ(entry_node.depth(), 0); + EXPECT_EQ(a_node.depth(), 1); + EXPECT_EQ(b_node.depth(), 2); + EXPECT_EQ(c_node.depth(), 3); + EXPECT_EQ(cond_node.depth(), 2); + // Entry computation has one while instruction calling two computations // (cond_computation and a_computation). - const CallGraphNode& entry_node = call_graph->GetNode(entry_computation); ASSERT_EQ(1, entry_node.callsites().size()); const std::vector& called_computations = entry_node.callsites()[0].called_computations(); @@ -342,7 +363,6 @@ TEST_F(CallGraphTest, ComplexGraph) { UnorderedElementsAre(cond_computation, a_computation)); EXPECT_EQ(CallContext::kSequential, entry_node.context()); - const CallGraphNode& c_node = call_graph->GetNode(c_computation); EXPECT_TRUE(c_node.callsites().empty()); EXPECT_THAT(c_node.callers(), UnorderedElementsAre(a_computation, b_computation)); -- GitLab From d5a8035691372c645d4781bb240f4d6fbb251860 Mon Sep 17 00:00:00 2001 From: Peter Hawkins Date: Thu, 20 Dec 2018 16:17:33 -0800 Subject: [PATCH 0210/1765] [XLA] Add a transfer manager method that writes the root tuple index table without writing any nested tuple buffers. PiperOrigin-RevId: 226411125 --- .../compiler/xla/service/transfer_manager.cc | 16 ++++++++++++++++ .../compiler/xla/service/transfer_manager.h | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/tensorflow/compiler/xla/service/transfer_manager.cc b/tensorflow/compiler/xla/service/transfer_manager.cc index a21e586efa..146815da54 100644 --- a/tensorflow/compiler/xla/service/transfer_manager.cc +++ b/tensorflow/compiler/xla/service/transfer_manager.cc @@ -248,6 +248,22 @@ Status TransferManager::WriteTupleIndexTablesAsync( }); } +Status TransferManager::WriteRootTupleIndexTable( + se::Stream* stream, const ShapedBuffer& device_buffer) { + TF_RET_CHECK(ShapeUtil::IsTuple(device_buffer.on_device_shape())); + se::DeviceMemoryBase device_memory = device_buffer.buffer({}); + TF_RET_CHECK(GetByteSizeRequirement(device_buffer.on_device_shape()) == + device_memory.size()); + + std::vector elements; + for (int64 i = 0; + i < ShapeUtil::TupleElementCount(device_buffer.on_device_shape()); ++i) { + elements.push_back(device_buffer.buffer({i})); + } + return WriteSingleTupleIndexTable( + stream, elements, device_buffer.on_device_shape(), &device_memory); +} + Status TransferManager::TransferBufferFromDevice( se::Stream* stream, const se::DeviceMemoryBase& source, int64 size, void* destination) { diff --git a/tensorflow/compiler/xla/service/transfer_manager.h b/tensorflow/compiler/xla/service/transfer_manager.h index 49f0b8f8b7..43a50487c6 100644 --- a/tensorflow/compiler/xla/service/transfer_manager.h +++ b/tensorflow/compiler/xla/service/transfer_manager.h @@ -146,6 +146,12 @@ class TransferManager { Status WriteTupleIndexTablesAsync(se::Stream* stream, const ShapedBuffer& device_buffer); + // Writes a tuple index buffer for the root of 'device_buffer', which must + // be a tuple. Unlike WriteTupleIndexTables, only writes the root buffer, + // rather than writing all subbuffers. This method is always asynchronous. + Status WriteRootTupleIndexTable(se::Stream* stream, + const ShapedBuffer& device_buffer); + // Determines the byte size requirement for the given shape on the underlying // architecture. This will be used to allocate an appropriately sized memory // region for a host-to-device transfer. -- GitLab From e7bac9435dd57740ea2b5a1a0a8bb14a1fbf093f Mon Sep 17 00:00:00 2001 From: Jared Duke Date: Thu, 20 Dec 2018 16:23:58 -0800 Subject: [PATCH 0211/1765] Internal change PiperOrigin-RevId: 226412019 --- .../java/org/tensorflow/lite/Interpreter.java | 14 ++++-- .../main/java/org/tensorflow/lite/Tensor.java | 27 +++++++++--- .../lite/java/src/main/native/tensor_jni.cc | 11 +++++ .../lite/java/src/main/native/tensor_jni.h | 10 +++++ .../org/tensorflow/lite/InterpreterTest.java | 43 +++++++++++++++++++ .../java/org/tensorflow/lite/TensorTest.java | 20 +++++++++ .../src/test/native/interpreter_test_jni.cc | 7 ++- 7 files changed, 122 insertions(+), 10 deletions(-) diff --git a/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Interpreter.java b/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Interpreter.java index 1b2d0d5aa8..5aef4fb057 100644 --- a/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Interpreter.java +++ b/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Interpreter.java @@ -234,11 +234,15 @@ public final class Interpreter implements AutoCloseable { * including int, float, long, and byte. {@link ByteBuffer} is the preferred way to pass large * input data for primitive types, whereas string types require using the (multi-dimensional) * array input path. When {@link ByteBuffer} is used, its content should remain unchanged - * until model inference is done. + * until model inference is done. A {@code null} value is allowed only if the caller is using + * a {@link Delegate} that allows buffer handle interop, and such a buffer has been bound to + * the input {@link Tensor}. * @param output a multidimensional array of output data, or a {@link ByteBuffer} of primitive - * types including int, float, long, and byte. + * types including int, float, long, and byte. A null value is allowed only if the caller is + * using a {@link Delegate} that allows buffer handle interop, and such a buffer has been + * bound to the output {@link Tensor}. See also {@link Options#setAllowBufferHandleOutput()}. */ - public void run(@NonNull Object input, @NonNull Object output) { + public void run(Object input, Object output) { Object[] inputs = {input}; Map outputs = new HashMap<>(); outputs.put(0, output); @@ -251,6 +255,10 @@ public final class Interpreter implements AutoCloseable { *

    Warning: The API runs much faster if {@link ByteBuffer} is used as input data type. Please * consider using {@link ByteBuffer} to feed primitive input data for better performance. * + *

    Note: {@code null} values for invididual elements of {@code inputs} and {@code outputs} is + * allowed only if the caller is using a {@link Delegate} that allows buffer handle interop, and + * such a buffer has been bound to the corresponding input or output {@link Tensor}(s). + * * @param inputs an array of input data. The inputs should be in the same order as inputs of the * model. Each input can be an array or multidimensional array, or a {@link ByteBuffer} of * primitive types including int, float, long, and byte. {@link ByteBuffer} is the preferred diff --git a/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Tensor.java b/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Tensor.java index b56fcd772b..725bb326ba 100644 --- a/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Tensor.java +++ b/tensorflow/lite/java/src/main/java/org/tensorflow/lite/Tensor.java @@ -93,12 +93,20 @@ public final class Tensor { * Copies the contents of the provided {@code src} object to the Tensor. * *

    The {@code src} should either be a (multi-dimensional) array with a shape matching that of - * this tensor, or a {@link ByteByffer} of compatible primitive type with a matching flat size. + * this tensor, a {@link ByteByffer} of compatible primitive type with a matching flat size, or + * {@code null} iff the tensor has an underlying delegate buffer handle. * * @throws IllegalArgumentException if the tensor is a scalar or if {@code src} is not compatible * with the tensor (for example, mismatched data types or shapes). */ void setTo(Object src) { + if (src == null) { + if (hasDelegateBufferHandle(nativeHandle)) { + return; + } + throw new IllegalArgumentException( + "Null inputs are allowed only if the Tensor is bound to a buffer handle."); + } throwExceptionIfTypeIsIncompatible(src); if (isByteBuffer(src)) { ByteBuffer srcBuffer = (ByteBuffer) src; @@ -117,11 +125,19 @@ public final class Tensor { /** * Copies the contents of the tensor to {@code dst} and returns {@code dst}. * - * @param dst the destination buffer, either an explicitly-typed array or a {@link ByteBuffer}. + * @param dst the destination buffer, either an explicitly-typed array, a {@link ByteBuffer} or + * {@code null} iff the tensor has an underlying delegate buffer handle. * @throws IllegalArgumentException if {@code dst} is not compatible with the tensor (for example, * mismatched data types or shapes). */ Object copyTo(Object dst) { + if (dst == null) { + if (hasDelegateBufferHandle(nativeHandle)) { + return dst; + } + throw new IllegalArgumentException( + "Null outputs are allowed only if the Tensor is bound to a buffer handle."); + } throwExceptionIfTypeIsIncompatible(dst); if (dst instanceof ByteBuffer) { ByteBuffer dstByteBuffer = (ByteBuffer) dst; @@ -135,6 +151,9 @@ public final class Tensor { /** Returns the provided buffer's shape if specified and different from this Tensor's shape. */ // TODO(b/80431971): Remove this method after deprecating multi-dimensional array inputs. int[] getInputShapeIfDifferent(Object input) { + if (input == null) { + return null; + } // Implicit resizes based on ByteBuffer capacity isn't supported, so short-circuit that path. // The ByteBuffer's size will be validated against this Tensor's size in {@link #setTo(Object)}. if (isByteBuffer(input)) { @@ -287,9 +306,7 @@ public final class Tensor { private static native int numBytes(long handle); - private static native int setBufferHandle(long handle, long delegateHandle, int bufferHandle); - - private static native int bufferHandle(long handle); + private static native boolean hasDelegateBufferHandle(long handle); private static native void readMultiDimensionalArray(long handle, Object dst); diff --git a/tensorflow/lite/java/src/main/native/tensor_jni.cc b/tensorflow/lite/java/src/main/native/tensor_jni.cc index cc81eb8d51..f07437e7f3 100644 --- a/tensorflow/lite/java/src/main/native/tensor_jni.cc +++ b/tensorflow/lite/java/src/main/native/tensor_jni.cc @@ -410,6 +410,17 @@ JNIEXPORT jint JNICALL Java_org_tensorflow_lite_Tensor_numBytes(JNIEnv* env, return static_cast(tensor->bytes); } +JNIEXPORT jboolean JNICALL +Java_org_tensorflow_lite_Tensor_hasDelegateBufferHandle(JNIEnv* env, + jclass clazz, + jlong handle) { + const TfLiteTensor* tensor = GetTensorFromHandle(env, handle); + if (tensor == nullptr) return false; + return tensor->delegate && (tensor->buffer_handle != kTfLiteNullBufferHandle) + ? JNI_TRUE + : JNI_FALSE; +} + JNIEXPORT jint JNICALL Java_org_tensorflow_lite_Tensor_index(JNIEnv* env, jclass clazz, jlong handle) { diff --git a/tensorflow/lite/java/src/main/native/tensor_jni.h b/tensorflow/lite/java/src/main/native/tensor_jni.h index 52150bf3ab..a14f24a47d 100644 --- a/tensorflow/lite/java/src/main/native/tensor_jni.h +++ b/tensorflow/lite/java/src/main/native/tensor_jni.h @@ -84,6 +84,16 @@ JNIEXPORT jint JNICALL Java_org_tensorflow_lite_Tensor_numBytes(JNIEnv* env, jclass clazz, jlong handle); +/* + * Class: org_tensorflow_lite_Tensor + * Method: hasDelegateBufferHandle + * Signature: (J)Z + */ +JNIEXPORT jboolean JNICALL +Java_org_tensorflow_lite_Tensor_hasDelegateBufferHandle(JNIEnv* env, + jclass clazz, + jlong handle); + /* * Class: org_tensorflow_lite_Tensor * Method: readMultiDimensionalArray diff --git a/tensorflow/lite/java/src/test/java/org/tensorflow/lite/InterpreterTest.java b/tensorflow/lite/java/src/test/java/org/tensorflow/lite/InterpreterTest.java index f89062ba45..c5496e3a21 100644 --- a/tensorflow/lite/java/src/test/java/org/tensorflow/lite/InterpreterTest.java +++ b/tensorflow/lite/java/src/test/java/org/tensorflow/lite/InterpreterTest.java @@ -334,6 +334,30 @@ public final class InterpreterTest { interpreter.close(); } + @Test + public void testNullInputs() throws Exception { + Interpreter interpreter = new Interpreter(MODEL_FILE); + try { + interpreter.run(null, new float[2][8][8][3]); + fail(); + } catch (IllegalArgumentException e) { + // Expected failure. + } + interpreter.close(); + } + + @Test + public void testNullOutputs() throws Exception { + Interpreter interpreter = new Interpreter(MODEL_FILE); + try { + interpreter.run(new float[2][8][8][3], null); + fail(); + } catch (IllegalArgumentException e) { + // Expected failure. + } + interpreter.close(); + } + /** Smoke test validating that flex model loading fails when the flex delegate is not linked. */ @Test public void testFlexModel() throws Exception { @@ -372,6 +396,25 @@ public final class InterpreterTest { interpreter.close(); } + @Test + public void testNullInputsAndOutputsWithDelegate() throws Exception { + System.loadLibrary("tensorflowlite_test_jni"); + Delegate delegate = + new Delegate() { + @Override + public long getNativeHandle() { + return getNativeHandleForDelegate(); + } + }; + Interpreter interpreter = + new Interpreter(MODEL_FILE, new Interpreter.Options().addDelegate(delegate)); + // The delegate installs a custom buffer handle for all tensors, in turn allowing null to be + // provided for the inputs/outputs (as the client can reference the buffer directly). + interpreter.run(new float[2][8][8][3], null); + interpreter.run(null, new float[2][8][8][3]); + interpreter.close(); + } + @Test public void testModifyGraphWithDelegate() throws Exception { System.loadLibrary("tensorflowlite_test_jni"); diff --git a/tensorflow/lite/java/src/test/java/org/tensorflow/lite/TensorTest.java b/tensorflow/lite/java/src/test/java/org/tensorflow/lite/TensorTest.java index be6a706b8d..d9b2051010 100644 --- a/tensorflow/lite/java/src/test/java/org/tensorflow/lite/TensorTest.java +++ b/tensorflow/lite/java/src/test/java/org/tensorflow/lite/TensorTest.java @@ -78,6 +78,16 @@ public final class TensorTest { assertThat(outputOneD).usingTolerance(0.1f).containsExactly(expected).inOrder(); } + @Test + public void testCopyToNull() { + try { + tensor.copyTo(null); + fail(); + } catch (IllegalArgumentException e) { + // Success. + } + } + @Test public void testCopyToByteBuffer() { ByteBuffer parsedOutput = @@ -150,6 +160,16 @@ public final class TensorTest { assertThat(output[0][0][0][0]).isEqualTo(3.0f); } + @Test + public void testSetToNull() { + try { + tensor.setTo(null); + fail(); + } catch (IllegalArgumentException e) { + // Success. + } + } + @Test public void testSetToInvalidByteBuffer() { ByteBuffer input = ByteBuffer.allocateDirect(3 * 4).order(ByteOrder.nativeOrder()); diff --git a/tensorflow/lite/java/src/test/native/interpreter_test_jni.cc b/tensorflow/lite/java/src/test/native/interpreter_test_jni.cc index 000e718ba7..f5bcc1249f 100644 --- a/tensorflow/lite/java/src/test/native/interpreter_test_jni.cc +++ b/tensorflow/lite/java/src/test/native/interpreter_test_jni.cc @@ -49,8 +49,6 @@ Java_org_tensorflow_lite_InterpreterTest_getNativeHandleForDelegate( .custom_name = "", .version = 1, }; - // A simple delegate which replaces all ops with a single op that outputs a - // vector of length 1 with the value [7]. static TfLiteDelegate delegate = { .data_ = nullptr, .Prepare = [](TfLiteContext* context, @@ -60,6 +58,11 @@ Java_org_tensorflow_lite_InterpreterTest_getNativeHandleForDelegate( context->GetExecutionPlan(context, &execution_plan)); context->ReplaceNodeSubsetsWithDelegateKernels( context, registration, execution_plan, delegate); + // Now bind delegate buffer handles for all tensors. + for (size_t i = 0; i < context->tensors_size; ++i) { + context->tensors[i].delegate = delegate; + context->tensors[i].buffer_handle = static_cast(i); + } return kTfLiteOk; }, .CopyFromBufferHandle = nullptr, -- GitLab From 1ed59e52b11cf7e3981ab54aeb722085a07d3923 Mon Sep 17 00:00:00 2001 From: Mark Heffernan Date: Thu, 20 Dec 2018 16:24:50 -0800 Subject: [PATCH 0212/1765] Replace calls to ShapeUtil::Rank with Shape::rank. No functional change. ShapeUtil::Rank is marked as deprecated. A later CL will remove it. PiperOrigin-RevId: 226412117 --- tensorflow/compiler/aot/codegen.cc | 2 +- .../tf2xla/kernels/batchtospace_op.cc | 2 +- .../compiler/tf2xla/kernels/index_ops_cpu.cc | 4 +- .../compiler/tf2xla/kernels/mirror_pad_op.cc | 3 +- .../tf2xla/kernels/spacetobatch_op.cc | 2 +- tensorflow/compiler/tf2xla/lib/scatter.cc | 8 +- tensorflow/compiler/tf2xla/shape_util.cc | 4 +- tensorflow/compiler/tf2xla/xla_helpers.cc | 2 +- tensorflow/compiler/tf2xla/xla_op_kernel.cc | 6 +- .../compiler/xla/client/lib/arithmetic.cc | 2 +- .../compiler/xla/client/lib/cholesky.cc | 4 +- tensorflow/compiler/xla/client/lib/matrix.cc | 10 +- tensorflow/compiler/xla/client/lib/qr.cc | 4 +- tensorflow/compiler/xla/client/lib/slicing.cc | 10 +- .../xla/client/lib/triangular_solve.cc | 8 +- .../compiler/xla/client/sharding_builder.cc | 2 +- tensorflow/compiler/xla/client/xla_builder.cc | 33 ++-- tensorflow/compiler/xla/index_util.cc | 2 +- tensorflow/compiler/xla/layout_util.cc | 14 +- tensorflow/compiler/xla/literal.cc | 46 ++--- tensorflow/compiler/xla/literal.h | 14 +- tensorflow/compiler/xla/literal_comparison.cc | 4 +- .../compiler/xla/python/numpy_bridge.cc | 4 +- tensorflow/compiler/xla/reference_util.cc | 2 +- .../xla/service/algebraic_simplifier.cc | 42 ++-- .../xla/service/algebraic_simplifier_test.cc | 4 +- .../xla/service/batchnorm_expander.cc | 8 +- .../xla/service/cpu/dot_op_emitter.cc | 2 +- .../compiler/xla/service/cpu/ir_emitter.cc | 6 +- .../service/dynamic_dimension_inference.cc | 6 +- .../xla/service/dynamic_parameter_binding.cc | 5 +- .../xla/service/elemental_ir_emitter.cc | 10 +- .../gpu/cudnn_conv_pad_for_tensor_cores.cc | 4 +- .../gpu/cudnn_conv_padding_legalization.cc | 2 +- .../compiler/xla/service/gpu/gemm_thunk.cc | 3 +- .../compiler/xla/service/gpu/gpu_fusible.cc | 6 +- .../xla/service/gpu/gpu_layout_assignment.cc | 8 +- .../xla/service/gpu/ir_emission_utils.cc | 2 +- .../xla/service/gpu/ir_emitter_unnested.cc | 15 +- .../xla/service/hlo_creation_utils.cc | 5 +- .../compiler/xla/service/hlo_evaluator.cc | 10 +- .../xla/service/hlo_evaluator_typed_visitor.h | 37 ++-- .../compiler/xla/service/hlo_instruction.cc | 4 +- .../compiler/xla/service/hlo_instructions.cc | 2 +- tensorflow/compiler/xla/service/hlo_parser.cc | 4 +- .../compiler/xla/service/hlo_sharding.cc | 4 +- .../compiler/xla/service/hlo_verifier.cc | 19 +- .../xla/service/indexed_array_analysis.cc | 8 +- .../compiler/xla/service/layout_assignment.cc | 31 ++- .../xla/service/layout_assignment_test.cc | 3 +- .../llvm_ir/dynamic_update_slice_util.cc | 2 +- .../compiler/xla/service/llvm_ir/ir_array.cc | 14 +- .../compiler/xla/service/llvm_ir/llvm_loop.cc | 2 +- .../compiler/xla/service/llvm_ir/sort_util.cc | 2 +- .../compiler/xla/service/pattern_matcher.h | 2 +- .../compiler/xla/service/scatter_expander.cc | 2 +- .../compiler/xla/service/shape_inference.cc | 185 +++++++++--------- .../compiler/xla/service/transpose_folding.cc | 2 +- tensorflow/compiler/xla/shape.cc | 6 + tensorflow/compiler/xla/shape.h | 4 + tensorflow/compiler/xla/shape_util.cc | 6 +- tensorflow/compiler/xla/shape_util.h | 1 + tensorflow/compiler/xla/sparse_index_array.cc | 2 +- .../xla/tests/client_library_test_base.cc | 4 +- tensorflow/compiler/xla/tests/test_utils.cc | 6 +- 65 files changed, 335 insertions(+), 347 deletions(-) diff --git a/tensorflow/compiler/aot/codegen.cc b/tensorflow/compiler/aot/codegen.cc index ab1c1be344..347a365dcb 100644 --- a/tensorflow/compiler/aot/codegen.cc +++ b/tensorflow/compiler/aot/codegen.cc @@ -129,7 +129,7 @@ Status AddRewritesForShape(int i, const xla::Shape& shape, TF_RETURN_IF_ERROR(XLATypeToCpp(shape.element_type(), &type)); std::vector dim_vars; string dim_sizes, indices; - if (xla::ShapeUtil::Rank(shape) == 0 || + if (shape.rank() == 0 || (shape.dimensions_size() == 1 && shape.dimensions(0) == 1)) { dim_sizes = "[1]"; indices = "[0]"; diff --git a/tensorflow/compiler/tf2xla/kernels/batchtospace_op.cc b/tensorflow/compiler/tf2xla/kernels/batchtospace_op.cc index 46e5d68c78..6b675fa8a9 100644 --- a/tensorflow/compiler/tf2xla/kernels/batchtospace_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/batchtospace_op.cc @@ -39,7 +39,7 @@ void BatchToSpace(XlaOpKernelContext* ctx, const xla::XlaOp& input, OP_REQUIRES( ctx, - xla::ShapeUtil::Rank(crops.shape()) == 2 && + crops.shape().rank() == 2 && block_rank == xla::ShapeUtil::GetDimension(crops.shape(), 0) && 2 == xla::ShapeUtil::GetDimension(crops.shape(), 1), errors::InvalidArgument("crops should have shape [", block_rank, diff --git a/tensorflow/compiler/tf2xla/kernels/index_ops_cpu.cc b/tensorflow/compiler/tf2xla/kernels/index_ops_cpu.cc index e2c05b648b..3e7e8eae6e 100644 --- a/tensorflow/compiler/tf2xla/kernels/index_ops_cpu.cc +++ b/tensorflow/compiler/tf2xla/kernels/index_ops_cpu.cc @@ -110,8 +110,8 @@ class ArgMaxCustomCallOp : public XlaOpKernel { auto shape_status = b.GetShape(arg); OP_REQUIRES_OK(ctx, shape_status.status()); xla::Shape arg_shape = shape_status.ConsumeValueOrDie(); - *arg_shape.mutable_layout() = xla::LayoutUtil::MakeDescendingLayout( - xla::ShapeUtil::Rank(arg_shape)); + *arg_shape.mutable_layout() = + xla::LayoutUtil::MakeDescendingLayout(arg_shape.rank()); arg_shapes.push_back(std::move(arg_shape)); } diff --git a/tensorflow/compiler/tf2xla/kernels/mirror_pad_op.cc b/tensorflow/compiler/tf2xla/kernels/mirror_pad_op.cc index f6b8534f4d..656f9b898f 100644 --- a/tensorflow/compiler/tf2xla/kernels/mirror_pad_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/mirror_pad_op.cc @@ -38,8 +38,7 @@ class MirrorPadOp : public XlaOpKernel { // - [1, 2, 3, 3, 2] in symmetric mode. int64 excluded_edges = mode == MirrorPadMode::REFLECT ? 1 : 0; xla::XlaOp accum = t; - for (int64 dimno = xla::ShapeUtil::Rank(original_shape) - 1; dimno >= 0; - --dimno) { + for (int64 dimno = original_shape.rank() - 1; dimno >= 0; --dimno) { auto t_rev = xla::Rev(accum, {dimno}); int64 lhs_padding = pad_literal.Get({dimno, 0}); int64 rhs_padding = pad_literal.Get({dimno, 1}); diff --git a/tensorflow/compiler/tf2xla/kernels/spacetobatch_op.cc b/tensorflow/compiler/tf2xla/kernels/spacetobatch_op.cc index 622efac817..52bed2670b 100644 --- a/tensorflow/compiler/tf2xla/kernels/spacetobatch_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/spacetobatch_op.cc @@ -39,7 +39,7 @@ void SpaceToBatch(XlaOpKernelContext* ctx, const xla::XlaOp& input, OP_REQUIRES( ctx, - xla::ShapeUtil::Rank(paddings.shape()) == 2 && + paddings.shape().rank() == 2 && block_rank == xla::ShapeUtil::GetDimension(paddings.shape(), 0) && 2 == xla::ShapeUtil::GetDimension(paddings.shape(), 1), errors::InvalidArgument("paddings should have shape [", block_rank, diff --git a/tensorflow/compiler/tf2xla/lib/scatter.cc b/tensorflow/compiler/tf2xla/lib/scatter.cc index 688056791f..1cd5a79171 100644 --- a/tensorflow/compiler/tf2xla/lib/scatter.cc +++ b/tensorflow/compiler/tf2xla/lib/scatter.cc @@ -48,7 +48,7 @@ xla::StatusOr XlaScatter( if (indices_are_vectors) { TF_RET_CHECK(!indices_dims.empty()); num_index_dims = indices_dims.back(); - if (num_index_dims > xla::ShapeUtil::Rank(buffer_shape)) { + if (num_index_dims > buffer_shape.rank()) { return errors::InvalidArgument( "The size of the minor dimension of the indices (shape: ", xla::ShapeUtil::HumanString(indices_shape), @@ -140,8 +140,8 @@ xla::StatusOr XlaScatter( ? indices_shape.dimensions_size() - 1 : indices_shape.dimensions_size()); - int64 updates_rank = xla::ShapeUtil::Rank(updates_shape); - int64 buffer_rank = xla::ShapeUtil::Rank(buffer_shape); + int64 updates_rank = updates_shape.rank(); + int64 buffer_rank = buffer_shape.rank(); int64 num_window_dims_in_updates = buffer_rank - num_index_dims; // If the rank of `updates` is 0 and does not match the expected rank of @@ -156,7 +156,7 @@ xla::StatusOr XlaScatter( if (updates_rank == 0 && expected_updates_rank != 0) { new_updates = xla::Broadcast(updates, expected_updates_dims); TF_ASSIGN_OR_RETURN(updates_shape, builder->GetShape(new_updates)); - updates_rank = xla::ShapeUtil::Rank(updates_shape); + updates_rank = updates_shape.rank(); } if (updates_rank > 0) { diff --git a/tensorflow/compiler/tf2xla/shape_util.cc b/tensorflow/compiler/tf2xla/shape_util.cc index ec604af138..2116a735d7 100644 --- a/tensorflow/compiler/tf2xla/shape_util.cc +++ b/tensorflow/compiler/tf2xla/shape_util.cc @@ -39,7 +39,7 @@ Status PopulateInfeedLayoutVector(const xla::Shape& shape, layouts->push_back(dim); } } else { - layouts->insert(layouts->end(), xla::ShapeUtil::Rank(shape), -1); + layouts->insert(layouts->end(), shape.rank(), -1); } return Status::OK(); } @@ -55,7 +55,7 @@ Status XLAShapeToTensorShape(const xla::Shape& shape, " cannot be converted to a TensorShape"); } *tensor_shape = TensorShape(); - for (int i = 0; i < xla::ShapeUtil::Rank(shape); ++i) { + for (int i = 0; i < shape.rank(); ++i) { tensor_shape->AddDim(shape.dimensions(i)); } return Status::OK(); diff --git a/tensorflow/compiler/tf2xla/xla_helpers.cc b/tensorflow/compiler/tf2xla/xla_helpers.cc index c2c0751211..83ba11b3bf 100644 --- a/tensorflow/compiler/tf2xla/xla_helpers.cc +++ b/tensorflow/compiler/tf2xla/xla_helpers.cc @@ -55,7 +55,7 @@ xla::XlaOp ArgMinMax(xla::XlaOp input, xla::PrimitiveType output_type, int axis, xla::XlaOp input_max = xla::Reduce(input, init_value, reducer, /*dimensions_to_reduce=*/{axis}); - std::vector broadcast_dims(xla::ShapeUtil::Rank(input_shape) - 1); + std::vector broadcast_dims(input_shape.rank() - 1); std::iota(broadcast_dims.begin(), broadcast_dims.begin() + axis, 0); std::iota(broadcast_dims.begin() + axis, broadcast_dims.end(), axis + 1); // Compute a mask that has 1s for elements equal to the maximum. diff --git a/tensorflow/compiler/tf2xla/xla_op_kernel.cc b/tensorflow/compiler/tf2xla/xla_op_kernel.cc index 58808c76de..58bd173e61 100644 --- a/tensorflow/compiler/tf2xla/xla_op_kernel.cc +++ b/tensorflow/compiler/tf2xla/xla_op_kernel.cc @@ -178,7 +178,7 @@ Status XlaOpKernelContext::ConstantInputReshaped( // Converts an int32 or int64 scalar literal to an int64. static Status LiteralToInt64Scalar(const xla::LiteralSlice& literal, int64* out) { - if (xla::ShapeUtil::Rank(literal.shape()) != 0) { + if (literal.shape().rank() != 0) { return errors::InvalidArgument("value is not a scalar"); } if (literal.shape().element_type() == xla::S32) { @@ -194,7 +194,7 @@ static Status LiteralToInt64Scalar(const xla::LiteralSlice& literal, // Converts an float32 or float64 scalar literal to a float64. static Status LiteralToFloat64Scalar(const xla::LiteralSlice& literal, double* out) { - if (xla::ShapeUtil::Rank(literal.shape()) != 0) { + if (literal.shape().rank() != 0) { return errors::InvalidArgument("value is not a scalar"); } if (literal.shape().element_type() == xla::F32) { @@ -228,7 +228,7 @@ Status XlaOpKernelContext::ConstantInputAsFloatScalar(int index, double* out) { // Converts an int32 or int64 1D literal to an int64 vector. static Status LiteralToInt64Vector(const xla::LiteralSlice& literal, std::vector* out) { - if (xla::ShapeUtil::Rank(literal.shape()) != 1) { + if (literal.shape().rank() != 1) { return errors::InvalidArgument("value is not 1D"); } int64 size = xla::ShapeUtil::ElementsIn(literal.shape()); diff --git a/tensorflow/compiler/xla/client/lib/arithmetic.cc b/tensorflow/compiler/xla/client/lib/arithmetic.cc index e86c10f030..33ff3971d7 100644 --- a/tensorflow/compiler/xla/client/lib/arithmetic.cc +++ b/tensorflow/compiler/xla/client/lib/arithmetic.cc @@ -117,7 +117,7 @@ XlaOp Any(XlaOp predicates) { XlaComputation logical_or = CreateScalarOrComputation(PRED, builder); TF_ASSIGN_OR_RETURN(const Shape& predicates_shape, builder->GetShape(predicates)); - std::vector all_dimensions(ShapeUtil::Rank(predicates_shape)); + std::vector all_dimensions(predicates_shape.rank()); std::iota(all_dimensions.begin(), all_dimensions.end(), 0); return Reduce(predicates, f, logical_or, all_dimensions); }); diff --git a/tensorflow/compiler/xla/client/lib/cholesky.cc b/tensorflow/compiler/xla/client/lib/cholesky.cc index fd98049968..83b8319879 100644 --- a/tensorflow/compiler/xla/client/lib/cholesky.cc +++ b/tensorflow/compiler/xla/client/lib/cholesky.cc @@ -54,7 +54,7 @@ XlaOp CholeskyUnblocked(XlaOp a, PrecisionConfig::Precision precision) { XlaBuilder* builder = a.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a)); - const int n_dims = ShapeUtil::Rank(a_shape); + const int n_dims = a_shape.rank(); const int64 n = ShapeUtil::GetDimension(a_shape, -1); auto major_dims = AsInt64Slice(a_shape.dimensions()) .subspan( @@ -144,7 +144,7 @@ XlaOp Cholesky(XlaOp a, int64 block_size, XlaBuilder* builder = a.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a)); - const int ndims = ShapeUtil::Rank(a_shape); + const int ndims = a_shape.rank(); if (ndims < 2) { return InvalidArgument( "Argument to Cholesky must have rank >= 2; shape was %s", diff --git a/tensorflow/compiler/xla/client/lib/matrix.cc b/tensorflow/compiler/xla/client/lib/matrix.cc index 16c177b4e2..2a1e832dc2 100644 --- a/tensorflow/compiler/xla/client/lib/matrix.cc +++ b/tensorflow/compiler/xla/client/lib/matrix.cc @@ -41,7 +41,7 @@ XlaOp GetMatrixDiagonal(XlaOp x) { XlaBuilder* builder = x.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); + const int64 n_dims = shape.rank(); TF_RET_CHECK(n_dims >= 2); const int64 m = shape.dimensions(n_dims - 2); const int64 n = shape.dimensions(n_dims - 1); @@ -68,7 +68,7 @@ XlaOp TriangleMask(XlaOp x, int diagonal) { XlaBuilder* builder = x.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); + const int64 n_dims = shape.rank(); TF_RET_CHECK(n_dims >= 2); const int64 m = shape.dimensions(n_dims - 2); const int64 n = shape.dimensions(n_dims - 1); @@ -99,12 +99,12 @@ XlaOp BatchDot(XlaOp x, XlaOp y, PrecisionConfig::Precision precision) { // Check that both tensors have the same number of dimensions. There must be // at least two (the batch dimensions can be empty). - if (ShapeUtil::Rank(x_shape) != ShapeUtil::Rank(y_shape)) { + if (x_shape.rank() != y_shape.rank()) { return InvalidArgument( "Arguments to BatchDot have different ranks: %s vs. %s", ShapeUtil::HumanString(x_shape), ShapeUtil::HumanString(y_shape)); } - const int ndims = ShapeUtil::Rank(x_shape); + const int ndims = x_shape.rank(); if (ndims < 2) { return InvalidArgument( "Arguments to BatchDot must have rank >= 2: got %d", ndims); @@ -169,7 +169,7 @@ XlaOp TransposeInMinorDims(XlaOp x) { XlaBuilder* builder = x.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); + const int64 n_dims = shape.rank(); TF_RET_CHECK(n_dims >= 2); std::vector permutation(n_dims); std::iota(permutation.begin(), permutation.end(), 0); diff --git a/tensorflow/compiler/xla/client/lib/qr.cc b/tensorflow/compiler/xla/client/lib/qr.cc index 72ca653173..640412ec8b 100644 --- a/tensorflow/compiler/xla/client/lib/qr.cc +++ b/tensorflow/compiler/xla/client/lib/qr.cc @@ -154,7 +154,7 @@ struct QRBlockResult { StatusOr QRBlock(XlaOp a, PrecisionConfig::Precision precision) { XlaBuilder* builder = a.builder(); TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a)); - const int num_dims = ShapeUtil::Rank(a_shape); + const int num_dims = a_shape.rank(); if (num_dims < 2) { return InvalidArgument("Argument to QR must have rank >= 2; got shape %s", a_shape.ToString()); @@ -325,7 +325,7 @@ StatusOr QRDecomposition( PrecisionConfig::Precision precision) { XlaBuilder* builder = a.builder(); TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a)); - const int num_dims = ShapeUtil::Rank(a_shape); + const int num_dims = a_shape.rank(); if (num_dims < 2) { return InvalidArgument("Arguments to QR must have rank >= 2: got shape %s", a_shape.ToString()); diff --git a/tensorflow/compiler/xla/client/lib/slicing.cc b/tensorflow/compiler/xla/client/lib/slicing.cc index f8c7df3ff5..611fffba8d 100644 --- a/tensorflow/compiler/xla/client/lib/slicing.cc +++ b/tensorflow/compiler/xla/client/lib/slicing.cc @@ -26,7 +26,7 @@ XlaOp SliceInMinorDims(XlaOp x, absl::Span start, TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); + const int64 n_dims = shape.rank(); TF_RET_CHECK(n_minor_dims <= n_dims); auto major_dims = AsInt64Slice(shape.dimensions()) .subspan( @@ -55,7 +55,7 @@ XlaOp UpdateSlice(XlaOp x, XlaOp update, absl::Span start) { std::vector start_as_int32(start.begin(), start.end()); auto start_constant = ConstantR1(builder, start_as_int32); TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); + const int64 n_dims = shape.rank(); TF_ASSIGN_OR_RETURN(Shape start_constant_shape, builder->GetShape(start_constant)); const int64 start_length = @@ -70,7 +70,7 @@ XlaOp UpdateSliceInMinorDims(XlaOp x, XlaOp update, XlaBuilder* builder = x.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); + const int64 n_dims = shape.rank(); const int64 n_minor_dims = start.size(); TF_RET_CHECK(n_minor_dims <= n_dims); std::vector padded_start(n_dims, 0); @@ -94,7 +94,7 @@ XlaOp PrependZerosInMajorDims(XlaOp x, absl::Span starts) { XlaBuilder* builder = x.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); + const int64 n_dims = shape.rank(); auto zero = Reshape(ConstantR0(builder, 0), {1}); std::vector padded_starts(n_dims, zero); for (int i = 0; i < starts.size(); ++i) { @@ -111,7 +111,7 @@ XlaOp DynamicSliceInMinorDims(XlaOp x, absl::Span starts, XlaBuilder* builder = x.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(x)); - const int64 n_dims = ShapeUtil::Rank(shape); + const int64 n_dims = shape.rank(); int64 n_minor_dims = starts.size(); TF_RET_CHECK(n_minor_dims == sizes.size()); TF_RET_CHECK(n_minor_dims <= n_dims); diff --git a/tensorflow/compiler/xla/client/lib/triangular_solve.cc b/tensorflow/compiler/xla/client/lib/triangular_solve.cc index 4bc2f3d121..6061e64656 100644 --- a/tensorflow/compiler/xla/client/lib/triangular_solve.cc +++ b/tensorflow/compiler/xla/client/lib/triangular_solve.cc @@ -38,7 +38,7 @@ XlaOp DiagonalBlocks(XlaOp a, int64 block_size) { XlaBuilder* builder = a.builder(); return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape shape, builder->GetShape(a)); - int ndims = ShapeUtil::Rank(shape); + int ndims = shape.rank(); int64 n = ShapeUtil::GetDimension(shape, -1); int64 num_blocks = n / block_size; @@ -262,7 +262,7 @@ XlaOp SolveWithInvertedDiagonalBlocks(XlaOp a, XlaOp b, XlaOp inv_diag_blocks, int64 block_size = ShapeUtil::GetDimension(blocks_shape, -1); TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a)); - int64 ndims = ShapeUtil::Rank(a_shape); + int64 ndims = a_shape.rank(); int64 n = ShapeUtil::GetDimension(a_shape, -1); int64 num_blocks = n / block_size + (n % block_size != 0); int64 m_dim = (left_side) ? -1 : -2; @@ -356,13 +356,13 @@ XlaOp TriangularSolve(XlaOp a, XlaOp b, bool left_side, bool lower, return builder->ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(Shape a_shape, builder->GetShape(a)); TF_ASSIGN_OR_RETURN(Shape b_shape, builder->GetShape(b)); - if (ShapeUtil::Rank(a_shape) != ShapeUtil::Rank(b_shape)) { + if (a_shape.rank() != b_shape.rank()) { return InvalidArgument( "Arguments to TriangularSolve have shapes with different ranks: " "%s vs. %s", ShapeUtil::HumanString(a_shape), ShapeUtil::HumanString(b_shape)); } - const int64 ndims = ShapeUtil::Rank(a_shape); + const int64 ndims = a_shape.rank(); if (ndims < 2) { return InvalidArgument( "Arguments to TriangularSolve was rank %d but must have rank >= 2.", diff --git a/tensorflow/compiler/xla/client/sharding_builder.cc b/tensorflow/compiler/xla/client/sharding_builder.cc index fb9ea6ec3f..b9bff06cbd 100644 --- a/tensorflow/compiler/xla/client/sharding_builder.cc +++ b/tensorflow/compiler/xla/client/sharding_builder.cc @@ -50,7 +50,7 @@ OpSharding Tile1D(const Shape& tile_shape, int64 num_tiles) { OpSharding result; result.set_type(OpSharding::Type::OpSharding_Type_OTHER); - CHECK_EQ(ShapeUtil::Rank(tile_shape), 1); + CHECK_EQ(tile_shape.rank(), 1); std::vector dimensions(1, num_tiles); *result.mutable_tile_shape() = tile_shape.ToProto(); auto& tile_dimension = diff --git a/tensorflow/compiler/xla/client/xla_builder.cc b/tensorflow/compiler/xla/client/xla_builder.cc index 622fc158e1..fc37a38813 100644 --- a/tensorflow/compiler/xla/client/xla_builder.cc +++ b/tensorflow/compiler/xla/client/xla_builder.cc @@ -343,7 +343,7 @@ StatusOr XlaBuilder::AddBroadcastSequence(const Shape& output_shape, TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); CHECK(ShapeUtil::IsScalar(operand_shape) || - ShapeUtil::Rank(operand_shape) == ShapeUtil::Rank(output_shape)); + operand_shape.rank() == output_shape.rank()); Shape broadcast_shape = ShapeUtil::ChangeElementType(output_shape, operand_shape.element_type()); @@ -355,7 +355,7 @@ StatusOr XlaBuilder::AddBroadcastSequence(const Shape& output_shape, // Do explicit broadcast for degenerate broadcast. std::vector broadcast_dimensions; std::vector reshaped_dimensions; - for (int i = 0; i < ShapeUtil::Rank(operand_shape); i++) { + for (int i = 0; i < operand_shape.rank(); i++) { if (operand_shape.dimensions(i) == output_shape.dimensions(i)) { broadcast_dimensions.push_back(i); reshaped_dimensions.push_back(operand_shape.dimensions(i)); @@ -398,8 +398,8 @@ XlaOp XlaBuilder::BinaryOp(HloOpcode binop, const XlaOp& lhs, const XlaOp& rhs, binop, lhs_shape, rhs_shape, broadcast_dimensions)); *instr.mutable_shape() = shape.ToProto(); - const int64 lhs_rank = ShapeUtil::Rank(lhs_shape); - const int64 rhs_rank = ShapeUtil::Rank(rhs_shape); + const int64 lhs_rank = lhs_shape.rank(); + const int64 rhs_rank = rhs_shape.rank(); XlaOp updated_lhs = lhs; XlaOp updated_rhs = rhs; @@ -413,8 +413,7 @@ XlaOp XlaBuilder::BinaryOp(HloOpcode binop, const XlaOp& lhs, const XlaOp& rhs, for (int64 size : shape.dimensions()) { to_size.push_back(size); } - for (int64 from_dim = 0; from_dim < ShapeUtil::Rank(from_shape); - from_dim++) { + for (int64 from_dim = 0; from_dim < from_shape.rank(); from_dim++) { int64 to_dim = broadcast_dimensions[from_dim]; to_size[to_dim] = from_shape.dimensions(from_dim); } @@ -563,10 +562,10 @@ XlaOp XlaBuilder::Broadcast(const XlaOp& operand, // output, so to append dimensions on the left the instruction's dimensions // should just be the n highest dimension numbers of the output shape where // n is the number of input dimensions. - const int64 operand_rank = ShapeUtil::Rank(operand_shape); + const int64 operand_rank = operand_shape.rank(); std::vector dimensions(operand_rank); for (int i = 0; i < operand_rank; ++i) { - dimensions[i] = i + ShapeUtil::Rank(shape) - operand_rank; + dimensions[i] = i + shape.rank() - operand_rank; } return InDimBroadcast(shape, operand, dimensions); }); @@ -639,10 +638,10 @@ XlaOp XlaBuilder::SliceInDim(const XlaOp& operand, int64 start_index, int64 limit_index, int64 stride, int64 dimno) { return ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(const Shape& shape, GetShape(operand)); - std::vector starts(ShapeUtil::Rank(shape), 0); + std::vector starts(shape.rank(), 0); std::vector limits(shape.dimensions().begin(), shape.dimensions().end()); - std::vector strides(ShapeUtil::Rank(shape), 1); + std::vector strides(shape.rank(), 1); starts[dimno] = start_index; limits[dimno] = limit_index; strides[dimno] = stride; @@ -780,7 +779,7 @@ XlaOp XlaBuilder::Collapse(const XlaOp& operand, VLOG(3) << "dims to collapse: " << absl::StrJoin(dimensions, ","); std::vector new_sizes; - for (int i = 0; i < ShapeUtil::Rank(original_shape); ++i) { + for (int i = 0; i < original_shape.rank(); ++i) { if (i <= dimensions.front() || i > dimensions.back()) { new_sizes.push_back(original_shape.dimensions(i)); } else { @@ -915,13 +914,13 @@ XlaOp XlaBuilder::DotGeneral(const XlaOp& lhs, const XlaOp& rhs, Status XlaBuilder::VerifyConvolution( const Shape& lhs_shape, const Shape& rhs_shape, const ConvolutionDimensionNumbers& dimension_numbers) const { - if (ShapeUtil::Rank(lhs_shape) != ShapeUtil::Rank(rhs_shape)) { + if (lhs_shape.rank() != rhs_shape.rank()) { return InvalidArgument( "Convolution arguments must have same number of " "dimensions. Got: %s and %s", ShapeUtil::HumanString(lhs_shape), ShapeUtil::HumanString(rhs_shape)); } - int num_dims = ShapeUtil::Rank(lhs_shape); + int num_dims = lhs_shape.rank(); if (num_dims < 2) { return InvalidArgument( "Convolution expects argument arrays with >= 3 dimensions. " @@ -1582,7 +1581,7 @@ XlaOp XlaBuilder::Sort(const XlaOp& keys, absl::Span values, *instr.mutable_shape() = shape.ToProto(); if (dimension == -1) { TF_ASSIGN_OR_RETURN(const Shape& keys_shape, GetShape(keys)); - dimension = ShapeUtil::Rank(keys_shape) - 1; + dimension = keys_shape.rank() - 1; } instr.add_dimensions(dimension); std::vector operands{keys}; @@ -1652,12 +1651,12 @@ XlaOp XlaBuilder::Map(absl::Span operands, *instr.mutable_shape() = shape.ToProto(); Shape output_shape(instr.shape()); - const int64 output_rank = ShapeUtil::Rank(output_shape); + const int64 output_rank = output_shape.rank(); AddCalledComputation(computation, &instr); std::vector new_operands(operands.begin(), operands.end()); for (XlaOp& new_operand : new_operands) { TF_ASSIGN_OR_RETURN(Shape shape, GetShape(new_operand)); - const int64 rank = ShapeUtil::Rank(shape); + const int64 rank = shape.rank(); if (rank != output_rank) { TF_ASSIGN_OR_RETURN(new_operand, InDimBroadcast(output_shape, new_operand, {})); @@ -1866,7 +1865,7 @@ XlaOp XlaBuilder::ReduceAll(const XlaOp& operand, const XlaOp& init_value, const XlaComputation& computation) { return ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - std::vector all_dimnos(ShapeUtil::Rank(operand_shape)); + std::vector all_dimnos(operand_shape.rank()); std::iota(all_dimnos.begin(), all_dimnos.end(), 0); return Reduce(operand, init_value, computation, all_dimnos); }); diff --git a/tensorflow/compiler/xla/index_util.cc b/tensorflow/compiler/xla/index_util.cc index 2a0241af3e..7e22a32e54 100644 --- a/tensorflow/compiler/xla/index_util.cc +++ b/tensorflow/compiler/xla/index_util.cc @@ -141,7 +141,7 @@ namespace xla { /* static */ bool IndexUtil::IndexInBounds(const Shape& shape, absl::Span index) { - int64 rank = ShapeUtil::Rank(shape); + int64 rank = shape.rank(); if (rank != index.size()) { return false; } diff --git a/tensorflow/compiler/xla/layout_util.cc b/tensorflow/compiler/xla/layout_util.cc index ddccd8c798..0f07f123a8 100644 --- a/tensorflow/compiler/xla/layout_util.cc +++ b/tensorflow/compiler/xla/layout_util.cc @@ -211,19 +211,19 @@ Layout CreateDefaultLayoutForRank(int64 rank) { } if (layout.format() == DENSE) { - if (layout.minor_to_major_size() != ShapeUtil::Rank(shape)) { + if (layout.minor_to_major_size() != shape.rank()) { return InvalidArgument( "layout minor_to_major field contains %d elements, " "but shape is rank %d: {%s}; shape: %s", - layout.minor_to_major_size(), ShapeUtil::Rank(shape), + layout.minor_to_major_size(), shape.rank(), absl::StrJoin(layout.minor_to_major(), ", "), shape.ShortDebugString()); } - std::vector dimensions_in_layout(ShapeUtil::Rank(shape), false); - for (int64 i = 0; i < ShapeUtil::Rank(shape); ++i) { + std::vector dimensions_in_layout(shape.rank(), false); + for (int64 i = 0; i < shape.rank(); ++i) { int64 dim = layout.minor_to_major(i); - if (dim < 0 || dim >= ShapeUtil::Rank(shape)) { + if (dim < 0 || dim >= shape.rank()) { return InvalidArgument( "layout minor_to_major field has out-of-bounds value: %s", HumanString(layout)); @@ -376,7 +376,7 @@ Status CopyLayoutInternal(const Shape& src, Shape* dst) { } } else { if (src.has_layout()) { - if (ShapeUtil::Rank(src) != ShapeUtil::Rank(*dst)) { + if (src.rank() != dst->rank()) { return InvalidArgument("cannot copy layout from shape: ranks differs"); } TF_RETURN_IF_ERROR( @@ -410,7 +410,7 @@ Status LayoutUtil::CopyLayoutBetweenShapes(const Shape& src, Shape* dst) { } return true; } else if (ShapeUtil::IsArray(lhs)) { - return ShapeUtil::Rank(lhs) == ShapeUtil::Rank(rhs) && + return lhs.rank() == rhs.rank() && LayoutUtil::Equal(lhs.layout(), rhs.layout()); } else { // Layouts of non-array and non-tuple shapes is ignored. diff --git a/tensorflow/compiler/xla/literal.cc b/tensorflow/compiler/xla/literal.cc index 277c98721e..3b596078b5 100644 --- a/tensorflow/compiler/xla/literal.cc +++ b/tensorflow/compiler/xla/literal.cc @@ -129,7 +129,7 @@ void Literal::SetPiece(const Shape& shape, Piece* piece, bool allocate_arrays) { new char[max_sparse_elements * ShapeUtil::ByteSizeOfPrimitiveType(shape.element_type())]); piece->set_sparse_indices( - new SparseIndexArray(max_sparse_elements, ShapeUtil::Rank(shape))); + new SparseIndexArray(max_sparse_elements, shape.rank())); } else { piece->set_buffer(new char[piece->size_bytes()]); } @@ -208,16 +208,15 @@ template Status MutableLiteralBase::CopySliceFromInternal( const LiteralBase& src_literal, absl::Span src_base, absl::Span dest_base, absl::Span copy_size) { - TF_RET_CHECK(ShapeUtil::Rank(src_literal.shape()) == src_base.size()); - TF_RET_CHECK(ShapeUtil::Rank(shape()) == dest_base.size()); + TF_RET_CHECK(src_literal.shape().rank() == src_base.size()); + TF_RET_CHECK(shape().rank() == dest_base.size()); auto linear_index = [](const Shape& shape, absl::Span multi_index) { return IndexUtil::MultidimensionalIndexToLinearIndex(shape, multi_index); }; - if (ShapeUtil::Rank(src_literal.shape()) == 0 || - ShapeUtil::Rank(shape()) == 0) { + if (src_literal.shape().rank() == 0 || shape().rank() == 0) { // If any of the two shapes are scalars, we can just call the StridedCopy() // directly, and we know we will be copying only one value. TF_RET_CHECK(copy_size.empty()); @@ -375,7 +374,7 @@ void CopyElementsBetween(absl::Span dest, if (ShapeUtil::IsZeroElementArray(dest_shape)) { return; } - std::vector index(ShapeUtil::Rank(dest_shape)); + std::vector index(dest_shape.rank()); do { dest[IndexUtil::MultidimensionalIndexToLinearIndex(dest_shape, index)] = src[IndexUtil::MultidimensionalIndexToLinearIndex(src_shape, index)]; @@ -392,7 +391,7 @@ Status LiteralBase::Piece::CopyFrom(const LiteralBase::Piece& src) { memcpy(buffer(), src.buffer(), src.size_bytes()); } else { TF_RET_CHECK(ShapeUtil::Compatible(src.subshape(), subshape())); - std::vector origin(ShapeUtil::Rank(subshape()), 0); + std::vector origin(subshape().rank(), 0); switch (subshape().element_type()) { #define COPY_ELEMENTS(XLA_T, NATIVE_T) \ case (XLA_T): \ @@ -563,7 +562,7 @@ Status MutableLiteralBase::CopySliceFrom(const LiteralSlice& src_literal, void MutableLiteralBase::PopulateR1(const tensorflow::core::Bitmap& values) { CHECK(ShapeUtil::IsArray(shape())); - CHECK_EQ(ShapeUtil::Rank(shape()), 1); + CHECK_EQ(shape().rank(), 1); CHECK_EQ(element_count(), values.bits()); CHECK_EQ(shape().element_type(), PRED); for (int64 i = 0; i < static_cast(values.bits()); ++i) { @@ -648,8 +647,7 @@ StatusOr LiteralBase::Reshape( } Literal output; if (!LayoutUtil::IsMonotonicWithDim0Major(shape().layout())) { - output = - Relayout(LayoutUtil::GetDefaultLayoutForRank(ShapeUtil::Rank(shape()))); + output = Relayout(LayoutUtil::GetDefaultLayoutForRank(shape().rank())); } else { output = Clone(); } @@ -672,7 +670,7 @@ StatusOr LiteralBase::Reshape( Literal LiteralBase::Transpose(absl::Span permutation) const { CHECK(ShapeUtil::IsArray(shape())) << "Tuple is not supported for transpose"; - CHECK(IsPermutation(permutation, ShapeUtil::Rank(shape()))) + CHECK(IsPermutation(permutation, shape().rank())) << "Given permutation is not a permutation of dimension numbers"; // To transpose the array, we just permute the dimensions and layout, and // do a straight memory copy of the raw data set. @@ -711,10 +709,10 @@ template Literal LiteralBase::SliceInternal( const Shape& result_shape, absl::Span start_indices) const { Literal result_literal(result_shape); - DimensionVector new_indices(ShapeUtil::Rank(result_shape)); + DimensionVector new_indices(result_shape.rank()); result_literal.EachCell( [&](absl::Span indices, NativeT /*value*/) { - for (int64 i = 0; i < ShapeUtil::Rank(result_shape); ++i) { + for (int64 i = 0; i < result_shape.rank(); ++i) { new_indices[i] = indices[i] + start_indices[i]; } NativeT value = Get(new_indices); @@ -728,7 +726,7 @@ Literal LiteralBase::Slice(absl::Span start_indices, CHECK(ShapeUtil::IsArray(shape())) << "tuple is not supported for slice"; DimensionVector result_dimensions; - for (int64 dnum = 0; dnum < ShapeUtil::Rank(shape()); ++dnum) { + for (int64 dnum = 0; dnum < shape().rank(); ++dnum) { CHECK_GE(start_indices[dnum], 0); CHECK_LE(limit_indices[dnum], shape().dimensions(dnum)) << "dnum = " << dnum; @@ -1056,7 +1054,7 @@ void SparseArrayToStringHelper(const LiteralBase& literal, pieces->push_back(ShapeToString(print_layout, subshape)); } pieces->push_back("{"); - int64 rank = ShapeUtil::Rank(subshape); + int64 rank = subshape.rank(); int64 num_elements = literal.sparse_element_count(); for (int64 i = 0; i < num_elements; ++i) { if (i > 0) { @@ -1079,7 +1077,7 @@ void DenseArrayToStringHelper(const LiteralBase& literal, const ShapeIndex& shape_index, bool print_shape, bool print_layout, std::vector* pieces) { const Shape& subshape = ShapeUtil::GetSubshape(literal.shape(), shape_index); - int64 rank = ShapeUtil::Rank(subshape); + int64 rank = subshape.rank(); std::function dimensions, std::vector*)> to_string_recursive = [&](absl::Span dimensions, @@ -1433,7 +1431,7 @@ StatusOr LiteralBase::ConvertToShape(const Shape& dest_shape) const { template bool LiteralBase::Piece::EqualElementsInternal( const LiteralBase::Piece& other, std::vector* multi_index) const { - if (multi_index->size() == ShapeUtil::Rank(subshape())) { + if (multi_index->size() == subshape().rank()) { return (Get(*multi_index) == other.Get(*multi_index)); } for (int64 i = 0; i < subshape().dimensions(multi_index->size()); ++i) { @@ -1722,7 +1720,7 @@ bool LiteralBase::IsR1Iota() const { return false; } - if (ShapeUtil::Rank(shape()) != 1) { + if (shape().rank() != 1) { return false; } @@ -1932,14 +1930,12 @@ Status LiteralBase::Piece::CopyFromProto(const LiteralProto& proto) { if (LayoutUtil::IsSparseArray(subshape())) { // Compute the number of elements (indices) in the sparse shape and reserve // the necessary space in spare_indices. - TF_RET_CHECK(ShapeUtil::Rank(subshape()) != 0) - << "Scalar shapes cannot be sparse"; - TF_RET_CHECK(proto.sparse_indices_size() % ShapeUtil::Rank(subshape()) == 0) + TF_RET_CHECK(subshape().rank() != 0) << "Scalar shapes cannot be sparse"; + TF_RET_CHECK(proto.sparse_indices_size() % subshape().rank() == 0) << "Unexpected number of indices in proto (" << proto.sparse_indices_size() << ") for shape of rank " - << ShapeUtil::Rank(subshape()); - const int64 index_count = - proto.sparse_indices_size() / ShapeUtil::Rank(subshape()); + << subshape().rank(); + const int64 index_count = proto.sparse_indices_size() / subshape().rank(); sparse_indices()->Resize(index_count); // Copy the indices from the proto into the SparseIndexArray object. @@ -2065,7 +2061,7 @@ int64 LiteralBase::size_bytes(const ShapeIndex& shape_index) const { string LiteralBase::GetR1U8AsString() const { CHECK(ShapeUtil::IsArray(shape())); - CHECK_EQ(ShapeUtil::Rank(shape()), 1); + CHECK_EQ(shape().rank(), 1); CHECK_EQ(shape().element_type(), U8); return string(absl::bit_cast(data().data()), ShapeUtil::ElementsIn(shape())); diff --git a/tensorflow/compiler/xla/literal.h b/tensorflow/compiler/xla/literal.h index 67e908e7ec..67db56c2ef 100644 --- a/tensorflow/compiler/xla/literal.h +++ b/tensorflow/compiler/xla/literal.h @@ -961,7 +961,7 @@ void MutableLiteralBase::AppendSparseElement( Piece& p = piece(shape_index); const Shape& subshape = p.subshape(); CHECK(LayoutUtil::IsSparseArray(subshape)); - int64 rank = ShapeUtil::Rank(subshape); + int64 rank = subshape.rank(); CHECK_EQ(multi_index.size(), rank); int64 last_element = p.sparse_indices()->index_count(); CHECK_LT(last_element, LayoutUtil::MaxSparseElements(subshape.layout())); @@ -977,7 +977,7 @@ void LiteralBase::EachCell( if (ShapeUtil::IsZeroElementArray(shape())) { return; } - std::vector indices(ShapeUtil::Rank(shape()), 0); + std::vector indices(shape().rank(), 0); do { per_cell(indices, Get(indices)); } while (IndexUtil::BumpIndices(shape(), absl::MakeSpan(indices))); @@ -986,7 +986,7 @@ void LiteralBase::EachCell( template inline void MutableLiteralBase::PopulateR1(absl::Span values) { CHECK(ShapeUtil::IsArray(shape())); - CHECK_EQ(ShapeUtil::Rank(shape()), 1); + CHECK_EQ(shape().rank(), 1); CHECK_EQ(ShapeUtil::ElementsIn(shape()), values.size()); CHECK_EQ(shape().element_type(), primitive_util::NativeToPrimitiveType()); @@ -998,7 +998,7 @@ template void MutableLiteralBase::PopulateR2( std::initializer_list> values) { CHECK(ShapeUtil::IsArray(shape())); - CHECK_EQ(ShapeUtil::Rank(shape()), 2); + CHECK_EQ(shape().rank(), 2); CHECK_EQ(shape().element_type(), primitive_util::NativeToPrimitiveType()); @@ -1024,7 +1024,7 @@ void MutableLiteralBase::PopulateFromArray(const Array& values) { CHECK(ShapeUtil::IsArray(shape())); CHECK_EQ(shape().element_type(), primitive_util::NativeToPrimitiveType()); - CHECK_EQ(ShapeUtil::Rank(shape()), values.num_dimensions()); + CHECK_EQ(shape().rank(), values.num_dimensions()); for (int dim = 0; dim < values.num_dimensions(); ++dim) { CHECK_EQ(values.dim(dim), shape().dimensions(dim)); } @@ -1053,7 +1053,7 @@ void MutableLiteralBase::PopulateSparse(SparseIndexArray indices, absl::Span values, bool sort) { CHECK(LayoutUtil::IsSparseArray(shape())); - int rank = ShapeUtil::Rank(shape()); + int rank = shape().rank(); CHECK_EQ(indices.rank(), rank); int64 max_elements = LayoutUtil::MaxSparseElements(shape().layout()); CHECK_LE(indices.max_indices(), max_elements); @@ -1077,7 +1077,7 @@ template Status MutableLiteralBase::PopulateInternal(const FnType& generator, bool parallel) { const Shape& this_shape = shape(); - const int64 rank = ShapeUtil::Rank(this_shape); + const int64 rank = this_shape.rank(); TF_RET_CHECK(LayoutUtil::IsDenseArray(this_shape)); TF_RET_CHECK(this_shape.element_type() == primitive_util::NativeToPrimitiveType()); diff --git a/tensorflow/compiler/xla/literal_comparison.cc b/tensorflow/compiler/xla/literal_comparison.cc index 1ac9a48e80..91316b77f6 100644 --- a/tensorflow/compiler/xla/literal_comparison.cc +++ b/tensorflow/compiler/xla/literal_comparison.cc @@ -463,7 +463,7 @@ class NearComparator { } return; } - std::vector multi_index(ShapeUtil::Rank(actual_.shape()), 0); + std::vector multi_index(actual_.shape().rank(), 0); CompareLiteralsSlow(0, &multi_index); } @@ -777,7 +777,7 @@ Status EqualShapes(const Shape& expected, const Shape& actual) { } } } else if (ShapeUtil::IsArray(expected)) { - if (ShapeUtil::Rank(expected) != ShapeUtil::Rank(actual)) { + if (expected.rank() != actual.rank()) { return InvalidArgument("want rank of %s got rank of %s", ShapeUtil::HumanString(expected), ShapeUtil::HumanString(actual)); diff --git a/tensorflow/compiler/xla/python/numpy_bridge.cc b/tensorflow/compiler/xla/python/numpy_bridge.cc index b0aa024c74..74d2d25b4b 100644 --- a/tensorflow/compiler/xla/python/numpy_bridge.cc +++ b/tensorflow/compiler/xla/python/numpy_bridge.cc @@ -132,7 +132,7 @@ PyObject* PyShapeInfoFromXlaShape(const Shape& shape) { PyShapeInfoFromXlaShape(ShapeUtil::GetTupleElementShape(shape, i))); } } else { - int rank = ShapeUtil::Rank(shape); + int rank = shape.rank(); dimensions = PyTuple_New(rank); for (int i = 0; i < rank; ++i) { PyTuple_SET_ITEM(dimensions, i, @@ -354,7 +354,7 @@ PyObject* PyObjectFromXlaLiteral(const LiteralSlice& literal) { } return tuple; } else { - int rank = ShapeUtil::Rank(literal.shape()); + int rank = literal.shape().rank(); std::vector dimensions(rank); // NOLINT - PyArray requires a long* for (int i = 0; i < rank; i++) { dimensions[i] = ShapeUtil::GetDimension(literal.shape(), i); diff --git a/tensorflow/compiler/xla/reference_util.cc b/tensorflow/compiler/xla/reference_util.cc index 92f28a9f8a..3ba67f69e8 100644 --- a/tensorflow/compiler/xla/reference_util.cc +++ b/tensorflow/compiler/xla/reference_util.cc @@ -552,7 +552,7 @@ ReferenceUtil::ConvArray4DGeneralDimensionsDilated( Literal result_literal = evaluator.Evaluate(*computation, {}).ConsumeValueOrDie(); - CHECK_EQ(ShapeUtil::Rank(result_literal.shape()), 4); + CHECK_EQ(result_literal.shape().rank(), 4); auto result = absl::make_unique>(result_literal.shape().dimensions(0), result_literal.shape().dimensions(1), diff --git a/tensorflow/compiler/xla/service/algebraic_simplifier.cc b/tensorflow/compiler/xla/service/algebraic_simplifier.cc index 9e453203ce..8157be1e0a 100644 --- a/tensorflow/compiler/xla/service/algebraic_simplifier.cc +++ b/tensorflow/compiler/xla/service/algebraic_simplifier.cc @@ -251,7 +251,7 @@ class AlgebraicSimplifierVisitor : public DfsHloVisitorWithDefault { // Reshapes an instruction to rank 1 if it is not already rank 1. HloInstruction* Flatten(HloInstruction* hlo) { - if (ShapeUtil::Rank(hlo->shape()) == 1) { + if (hlo->shape().rank() == 1) { return hlo; } return computation_->AddInstruction(HloInstruction::CreateReshape( @@ -687,7 +687,7 @@ Status AlgebraicSimplifierVisitor::HandleConcatenate( return Status::OK(); } PaddingConfig padding_config; - for (int64 dim = 0; dim < ShapeUtil::Rank(operands[0]->shape()); ++dim) { + for (int64 dim = 0; dim < operands[0]->shape().rank(); ++dim) { auto padding_config_dim = padding_config.add_dimensions(); padding_config_dim->set_edge_padding_high(0); padding_config_dim->set_edge_padding_low(0); @@ -754,7 +754,7 @@ Status AlgebraicSimplifierVisitor::HandleConstant(HloInstruction* constant) { } // If a literal is an increasing sequence from zero, replace it with an iota. - if (ShapeUtil::Rank(constant->shape()) == 1 && + if (constant->shape().rank() == 1 && ShapeUtil::ElementsIn(constant->shape()) > 1 && constant->literal().IsR1Iota()) { return ReplaceWithNewInstruction( @@ -930,9 +930,9 @@ StatusOr AlgebraicSimplifierVisitor::HandleDotStrengthReduction( return -1; }; - const int64 dot_rank = ShapeUtil::Rank(dot->shape()); - const int64 rhs_rank = ShapeUtil::Rank(rhs->shape()); - const int64 lhs_rank = ShapeUtil::Rank(lhs->shape()); + const int64 dot_rank = dot->shape().rank(); + const int64 rhs_rank = rhs->shape().rank(); + const int64 lhs_rank = lhs->shape().rank(); const auto& dnums = dot->dot_dimension_numbers(); if (dnums.rhs_contracting_dimensions_size() > 1) { return false; @@ -1036,7 +1036,7 @@ StatusOr AlgebraicSimplifierVisitor::HandleDotStrengthReduction( // ) if (lhs_rank == 1 || (lhs_rank == 2 && lhs->shape().dimensions(lhs_kept_dim) == 1)) { - if (ShapeUtil::Rank(rhs->shape()) == 1) { + if (rhs->shape().rank() == 1) { TF_RETURN_IF_ERROR( ReplaceInstruction(dot, reshape_if_necessary(add_reduce_in_f32( multiply(Flatten(lhs), rhs), 0)))); @@ -1449,8 +1449,8 @@ Status AlgebraicSimplifierVisitor::HandleDot(HloInstruction* dot) { dot->shape().element_type() != BF16) { return Status::OK(); } - if (ShapeUtil::Rank(lhs->shape()) > 2 || ShapeUtil::Rank(rhs->shape()) > 2 || - ShapeUtil::Rank(dot->shape()) > 2) { + if (lhs->shape().rank() > 2 || rhs->shape().rank() > 2 || + dot->shape().rank() > 2) { if (options_.enable_dot_strength_reduction() && !options_.is_layout_sensitive()) { TF_RETURN_IF_ERROR(HandleDotStrengthReduction(dot).status()); @@ -1732,8 +1732,7 @@ Status AlgebraicSimplifierVisitor::HandleBroadcast(HloInstruction* broadcast) { // A degenerate broadcast that has the same input and output rank can be // converted into a transpose. - if (ShapeUtil::Rank(broadcast->shape()) == - ShapeUtil::Rank(operand->shape()) && + if (broadcast->shape().rank() == operand->shape().rank() && ShapeUtil::ElementsIn(broadcast->shape()) == ShapeUtil::ElementsIn(operand->shape())) { VLOG(10) << "transform broadcast(X) -> transpose(X) where " @@ -1888,7 +1887,7 @@ Status AlgebraicSimplifierVisitor::HandlePad(HloInstruction* pad) { if (HasInteriorPadding(pad->padding_config())) { PaddingConfig padding_config = pad->padding_config(); bool cleared_interior_padding = false; - for (int64 i = 0; i < ShapeUtil::Rank(pad->shape()); ++i) { + for (int64 i = 0; i < pad->shape().rank(); ++i) { if (padding_config.dimensions(i).interior_padding() > 0 && pad->operand(0)->shape().dimensions(i) == 1) { cleared_interior_padding = true; @@ -2276,7 +2275,7 @@ StatusOr AlgebraicSimplifierVisitor::TrySimplifyScalarSlice( if (slice->operand(0)->opcode() == HloOpcode::kConcatenate) { VLOG(10) << "Trying to simplify scalar slice of concat"; // Only do this for R1, there's no chance of this being useful otherwise. - if (ShapeUtil::Rank(slice->shape()) != 1) { + if (slice->shape().rank() != 1) { VLOG(10) << "Not folding, slice is not rank 1"; return false; } @@ -2326,7 +2325,7 @@ StatusOr AlgebraicSimplifierVisitor::TryToReorderSliceAndReshape( return false; } HloInstruction* new_slice_operand = reshape->mutable_operand(0); - int64 slice_rank = ShapeUtil::Rank(slice->shape()); + int64 slice_rank = slice->shape().rank(); std::vector sliced_dims; for (int64 i = 0; i < slice_rank; ++i) { if (slice->slice_starts(i) != 0 || @@ -2338,7 +2337,7 @@ StatusOr AlgebraicSimplifierVisitor::TryToReorderSliceAndReshape( if (sliced_dims.size() == 1 && sliced_dims[0] == 0 && slice->slice_starts(0) == 0) { const Shape& new_slice_shape = new_slice_operand->shape(); - const int64 rank = ShapeUtil::Rank(new_slice_shape); + const int64 rank = new_slice_shape.rank(); std::vector new_slice_starts(rank, 0); std::vector new_slice_stides(rank, 1); std::vector new_slice_limits(new_slice_shape.dimensions().begin(), @@ -2456,8 +2455,7 @@ Status AlgebraicSimplifierVisitor::HandleReduce(HloInstruction* reduce) { // A Transpose feeding a reduce can simply permute the reduction dimensions // field if the output of the reduce is a vector or scalar. Higher ranked // result may require a transpose of the output. - if (ShapeUtil::Rank(reduce->shape()) <= 1 && - arg->opcode() == HloOpcode::kTranspose) { + if (reduce->shape().rank() <= 1 && arg->opcode() == HloOpcode::kTranspose) { auto transpose_dimensions = arg->dimensions(); std::vector new_reduce_dimensions; for (auto dim : dimensions) { @@ -2516,8 +2514,8 @@ Status AlgebraicSimplifierVisitor::HandleReduce(HloInstruction* reduce) { std::vector> unmodified_dims = ShapeUtil::DimensionsUnmodifiedByReshape(arg->operand(0)->shape(), arg->shape()); - std::vector arg_dim_in_output(ShapeUtil::Rank(arg->shape()), true); - std::vector arg_dim_unmodified(ShapeUtil::Rank(arg->shape()), false); + std::vector arg_dim_in_output(arg->shape().rank(), true); + std::vector arg_dim_unmodified(arg->shape().rank(), false); for (auto dim : dimensions) { arg_dim_in_output[dim] = false; } @@ -2542,7 +2540,7 @@ Status AlgebraicSimplifierVisitor::HandleReduce(HloInstruction* reduce) { } } std::vector new_reduce_dimensions; - for (int64 i = 0; i < ShapeUtil::Rank(arg->operand(0)->shape()); ++i) { + for (int64 i = 0; i < arg->operand(0)->shape().rank(); ++i) { if (dimensions_not_to_reduce.count(i) == 0) { new_reduce_dimensions.push_back(i); } @@ -2779,7 +2777,7 @@ Status AlgebraicSimplifierVisitor::HandleReduceWindow( // Carry out the folding of the pad into reduce_window. VLOG(10) << "Folding pad into reduce-window."; Window new_window = window; - const int64 rank = ShapeUtil::Rank(reduce_window->shape()); + const int64 rank = reduce_window->shape().rank(); TF_RET_CHECK(pad_config.dimensions_size() == rank); TF_RET_CHECK(window.dimensions_size() == rank); for (int64 i = 0; i < rank; ++i) { @@ -2862,7 +2860,7 @@ Status AlgebraicSimplifierVisitor::HandleSort(HloInstruction* sort) { // - Use this as the indices parameter of scatter, and set updates // of the scatter to be a reshaped 'values' parameter of sort (adding // 'rank' many 1 dimensions at the end). - int64 rank = ShapeUtil::Rank(operand->shape()); + int64 rank = operand->shape().rank(); Shape extended_shape = operand->shape(); extended_shape.add_dimensions(1); extended_shape.mutable_layout()->add_minor_to_major(rank); diff --git a/tensorflow/compiler/xla/service/algebraic_simplifier_test.cc b/tensorflow/compiler/xla/service/algebraic_simplifier_test.cc index a9d617cbf6..51ad748ff8 100644 --- a/tensorflow/compiler/xla/service/algebraic_simplifier_test.cc +++ b/tensorflow/compiler/xla/service/algebraic_simplifier_test.cc @@ -3498,7 +3498,7 @@ TEST_F(AlgebraicSimplifierTest, FoldPadIntoReduceWindow) { // Create the reduce-window. Window window; - for (int64 i = 0; i < ShapeUtil::Rank(pad->shape()); ++i) { + for (int64 i = 0; i < pad->shape().rank(); ++i) { auto* dim = window.add_dimensions(); dim->set_size(1); dim->set_padding_low(10); @@ -3584,7 +3584,7 @@ TEST_F(AlgebraicSimplifierTest, FoldConvertedPadIntoReduceWindow) { // Create the reduce-window. Window window; - for (int64 i = 0; i < ShapeUtil::Rank(pad->shape()); ++i) { + for (int64 i = 0; i < pad->shape().rank(); ++i) { auto* dim = window.add_dimensions(); dim->set_size(1); dim->set_padding_low(10); diff --git a/tensorflow/compiler/xla/service/batchnorm_expander.cc b/tensorflow/compiler/xla/service/batchnorm_expander.cc index 0e6ca1871b..e5f5c3edb2 100644 --- a/tensorflow/compiler/xla/service/batchnorm_expander.cc +++ b/tensorflow/compiler/xla/service/batchnorm_expander.cc @@ -123,7 +123,7 @@ class BatchNormExpanderVisitor : public DfsHloVisitorWithDefault { auto elements_per_feature_u32 = add_instruction( HloInstruction::CreateConstant(LiteralUtil::CreateR0(1))); - for (int64 i = 0; i < ShapeUtil::Rank(operand->shape()); ++i) { + for (int64 i = 0; i < operand->shape().rank(); ++i) { if (i == feature_index) { continue; } @@ -229,7 +229,7 @@ Status BatchNormExpanderVisitor::HandleBatchNormTraining( add(HloInstruction::CreateConstant(std::move(epsilon_literal))), {})); std::vector dimensions_without_feature; - for (int64 i = 0; i < ShapeUtil::Rank(operand_shape); ++i) { + for (int64 i = 0; i < operand_shape.rank(); ++i) { if (i != feature_index) { dimensions_without_feature.push_back(i); } @@ -357,7 +357,7 @@ Status BatchNormExpanderVisitor::HandleBatchNormInference( std::vector dimensions_without_feature; - for (int64 i = 0; i < ShapeUtil::Rank(operand_shape); ++i) { + for (int64 i = 0; i < operand_shape.rank(); ++i) { if (i != feature_index) { dimensions_without_feature.push_back(i); } @@ -494,7 +494,7 @@ Status BatchNormExpanderVisitor::HandleBatchNormGrad( std::vector dimensions_without_feature; - for (int64 i = 0; i < ShapeUtil::Rank(activation_shape); ++i) { + for (int64 i = 0; i < activation_shape.rank(); ++i) { if (i != feature_index) { dimensions_without_feature.push_back(i); } diff --git a/tensorflow/compiler/xla/service/cpu/dot_op_emitter.cc b/tensorflow/compiler/xla/service/cpu/dot_op_emitter.cc index 37cefcb2e8..1525a33af7 100644 --- a/tensorflow/compiler/xla/service/cpu/dot_op_emitter.cc +++ b/tensorflow/compiler/xla/service/cpu/dot_op_emitter.cc @@ -1550,7 +1550,7 @@ DotOpEmitter::MatMultDims DotOpEmitter::GetMatMultDims() const { } // Return whether the given shape is rank 2. -static bool IsRank2(const Shape& shape) { return ShapeUtil::Rank(shape) == 2; } +static bool IsRank2(const Shape& shape) { return shape.rank() == 2; } // In a gemm operation where output = lhs * rhs, check whether the given shapes // are valid for the operation. diff --git a/tensorflow/compiler/xla/service/cpu/ir_emitter.cc b/tensorflow/compiler/xla/service/cpu/ir_emitter.cc index ed7fe59c80..f29f8f8fec 100644 --- a/tensorflow/compiler/xla/service/cpu/ir_emitter.cc +++ b/tensorflow/compiler/xla/service/cpu/ir_emitter.cc @@ -535,7 +535,7 @@ Status IrEmitter::HandleSort(HloInstruction* hlo) { higher_dimensions *= normalized_keys_shape.dimensions(i); } int64 lower_dimensions = 1; - for (int64 i = ShapeUtil::Rank(normalized_keys_shape) - 1; + for (int64 i = normalized_keys_shape.rank() - 1; i > physical_dimension_to_sort; --i) { lower_dimensions *= normalized_keys_shape.dimensions(i); } @@ -779,8 +779,8 @@ Status IrEmitter::HandleSelectAndScatter(HloInstruction* select_and_scatter) { const auto init_value = select_and_scatter->operand(2); const Window& window = select_and_scatter->window(); PrimitiveType operand_element_type = operand->shape().element_type(); - const int64 rank = ShapeUtil::Rank(operand->shape()); - CHECK_EQ(rank, ShapeUtil::Rank(source->shape())); + const int64 rank = operand->shape().rank(); + CHECK_EQ(rank, source->shape().rank()); CHECK_EQ(rank, window.dimensions_size()); // TODO(b/31410564): Implement dilation for select-and-scatter. diff --git a/tensorflow/compiler/xla/service/dynamic_dimension_inference.cc b/tensorflow/compiler/xla/service/dynamic_dimension_inference.cc index 6d0472689b..f2b7e9a186 100644 --- a/tensorflow/compiler/xla/service/dynamic_dimension_inference.cc +++ b/tensorflow/compiler/xla/service/dynamic_dimension_inference.cc @@ -173,7 +173,7 @@ Status DynamicDimensionInferenceVisitor::HandleReduce(HloInstruction* hlo) { // Find out the new dynamic dimension after reduce. int64 dimensions_not_reduced_count = 0; - for (int i = 0; i < ShapeUtil::Rank(operand->shape()); ++i) { + for (int i = 0; i < operand->shape().rank(); ++i) { if (dimension == i) { parent_->SetDynamicSize(reduce, {}, dimensions_not_reduced_count, dynamic_size); @@ -207,7 +207,7 @@ Status DynamicDimensionInferenceVisitor::HandleDot(HloInstruction* hlo) { result_dim_mapping[i] = current_result_dims++; } - for (int64 i = 0; i < ShapeUtil::Rank(dot->operand(0)->shape()); i++) { + for (int64 i = 0; i < dot->operand(0)->shape().rank(); i++) { if (!absl::c_linear_search( dimension_numbers.lhs_contracting_dimensions(), i)) { if (operand_index == 0) { @@ -217,7 +217,7 @@ Status DynamicDimensionInferenceVisitor::HandleDot(HloInstruction* hlo) { } } - for (int64 i = 0; i < ShapeUtil::Rank(dot->operand(1)->shape()); i++) { + for (int64 i = 0; i < dot->operand(1)->shape().rank(); i++) { if (!absl::c_linear_search( dimension_numbers.rhs_contracting_dimensions(), i) && !absl::c_linear_search(dimension_numbers.rhs_batch_dimensions(), diff --git a/tensorflow/compiler/xla/service/dynamic_parameter_binding.cc b/tensorflow/compiler/xla/service/dynamic_parameter_binding.cc index c8bfc89050..3d0eddb0d8 100644 --- a/tensorflow/compiler/xla/service/dynamic_parameter_binding.cc +++ b/tensorflow/compiler/xla/service/dynamic_parameter_binding.cc @@ -121,10 +121,11 @@ Status DynamicParameterBinding::Verify(const HloModule& module) const { dynamic_dimension.parameter_index)); TF_RET_CHECK( dynamic_dimension.dimension < - ShapeUtil::Rank(ShapeUtil::GetSubshape( + ShapeUtil::GetSubshape( entry->parameter_instruction(dynamic_dimension.parameter_num) ->shape(), - dynamic_dimension.parameter_index))); + dynamic_dimension.parameter_index) + .rank()); return Status::OK(); }); } diff --git a/tensorflow/compiler/xla/service/elemental_ir_emitter.cc b/tensorflow/compiler/xla/service/elemental_ir_emitter.cc index 6f1f95f2e9..6f928fcbaa 100644 --- a/tensorflow/compiler/xla/service/elemental_ir_emitter.cc +++ b/tensorflow/compiler/xla/service/elemental_ir_emitter.cc @@ -1327,9 +1327,9 @@ llvm_ir::IrArray::Index ElementalIrEmitter::ElementwiseSourceIndex( // If implicit broadcast is needed, the source dimensions that are broadcast // have index 0. - CHECK_EQ(ShapeUtil::Rank(operand_shape), ShapeUtil::Rank(hlo.shape())); + CHECK_EQ(operand_shape.rank(), hlo.shape().rank()); llvm_ir::IrArray::Index source_index(target_index.GetType()); - for (int64 i = 0; i < ShapeUtil::Rank(hlo.shape()); ++i) { + for (int64 i = 0; i < hlo.shape().rank(); ++i) { if (hlo.shape().dimensions(i) == operand_shape.dimensions(i)) { source_index.push_back(target_index[i]); } else { @@ -1750,7 +1750,7 @@ StatusOr ElementalIrEmitter::EmitElementalDynamicSlice( const llvm_ir::IrArray::Index& index) { // Emit IR to read dynamic start indices from hlo->operand(1). const HloInstruction* input_hlo = hlo->operand(0); - const int64 rank = ShapeUtil::Rank(input_hlo->shape()); + const int64 rank = input_hlo->shape().rank(); // Use the same index type for all tensor accesses in the same kernel. llvm::Type* index_type = index.GetType(); llvm_ir::IrArray::Index slice_start_index(index_type, rank); @@ -1893,7 +1893,7 @@ StatusOr ElementalIrEmitter::EmitElementalDynamicUpdateSlice( const HloInstruction* update_hlo = hlo->operand(1); const HloInstruction* start_hlo = hlo->operand(2); // Calculate slice start/end indices. - const int64 rank = ShapeUtil::Rank(input_hlo->shape()); + const int64 rank = input_hlo->shape().rank(); llvm_ir::IrArray::Index slice_start_index(index.GetType(), rank); llvm_ir::IrArray::Index slice_limit_index(index.GetType(), rank); // Slice intersection gathers (ANDs) conditions on all ranks for which @@ -2225,7 +2225,7 @@ llvm_ir::ElementGenerator ElementalIrEmitter::MakeElementGenerator( auto* iota = Cast(hlo); PrimitiveType element_type = iota->shape().element_type(); IrArray::Index elem_index = - ShapeUtil::Rank(iota->shape()) > 1 + iota->shape().rank() > 1 ? target_index.SourceIndexOfBroadcast( iota->shape(), ShapeUtil::MakeShapeWithDescendingLayout( diff --git a/tensorflow/compiler/xla/service/gpu/cudnn_conv_pad_for_tensor_cores.cc b/tensorflow/compiler/xla/service/gpu/cudnn_conv_pad_for_tensor_cores.cc index 5aa4f839f4..958e0b9c6e 100644 --- a/tensorflow/compiler/xla/service/gpu/cudnn_conv_pad_for_tensor_cores.cc +++ b/tensorflow/compiler/xla/service/gpu/cudnn_conv_pad_for_tensor_cores.cc @@ -50,10 +50,10 @@ static HloInstruction* PadInstruction(HloInstruction* instr, auto* zero = comp->AddInstruction( HloInstruction::CreateConstant(LiteralUtil::Zero(shape.element_type()))); - PaddingConfig pad_config = MakeNoPaddingConfig(ShapeUtil::Rank(shape)); + PaddingConfig pad_config = MakeNoPaddingConfig(shape.rank()); bool added_padding = false; - for (int64 dim = 0; dim < ShapeUtil::Rank(shape); ++dim) { + for (int64 dim = 0; dim < shape.rank(); ++dim) { if (shape.dimensions(dim) == new_shape.dimensions(dim)) { continue; } diff --git a/tensorflow/compiler/xla/service/gpu/cudnn_conv_padding_legalization.cc b/tensorflow/compiler/xla/service/gpu/cudnn_conv_padding_legalization.cc index 3a09d4d471..17d0f7aa7b 100644 --- a/tensorflow/compiler/xla/service/gpu/cudnn_conv_padding_legalization.cc +++ b/tensorflow/compiler/xla/service/gpu/cudnn_conv_padding_legalization.cc @@ -219,7 +219,7 @@ bool CudnnConvPaddingLegalization::CanonicalizeBackwardFilterConvolution( Window new_backward_conv_window = backward_conv->window(); // input_padding_config is the config of the kPad to be inserted. PaddingConfig input_padding_config = - MakeNoPaddingConfig(ShapeUtil::Rank(input->shape())); + MakeNoPaddingConfig(input->shape().rank()); ConvolutionDimensionNumbers backward_conv_dnums = backward_conv->convolution_dimension_numbers(); for (size_t i = 0; i < backward_conv->window().dimensions_size(); ++i) { diff --git a/tensorflow/compiler/xla/service/gpu/gemm_thunk.cc b/tensorflow/compiler/xla/service/gpu/gemm_thunk.cc index 27f07b1d58..b8fbe7d2bc 100644 --- a/tensorflow/compiler/xla/service/gpu/gemm_thunk.cc +++ b/tensorflow/compiler/xla/service/gpu/gemm_thunk.cc @@ -315,8 +315,7 @@ Status GemmThunk::ExecuteOnStream(const BufferAllocations& buffer_allocations, DotDimensionNumbers dim_nums = GetDimensionNumbers(*hlo_instruction()); CHECK_EQ(dim_nums.lhs_batch_dimensions_size(), dim_nums.rhs_batch_dimensions_size()); - CHECK_EQ(dim_nums.lhs_batch_dimensions_size() + 2, - ShapeUtil::Rank(output_shape_)); + CHECK_EQ(dim_nums.lhs_batch_dimensions_size() + 2, output_shape_.rank()); int64 row_dim = dim_nums.lhs_batch_dimensions_size(); int64 col_dim = dim_nums.lhs_batch_dimensions_size() + 1; diff --git a/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc b/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc index 452e763a8e..542af51e62 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc @@ -43,14 +43,14 @@ bool LayoutsAreReduceInputFusionFriendly(const HloInstruction& producer, const Layout* max_rank_layout; for (HloInstruction* param : params) { if (ShapeUtil::IsArray(param->shape()) && - ShapeUtil::Rank(param->shape()) > max_rank) { - max_rank = ShapeUtil::Rank(param->shape()); + param->shape().rank() > max_rank) { + max_rank = param->shape().rank(); max_rank_layout = ¶m->shape().layout(); } } return absl::c_all_of(params, [&](HloInstruction* param) { return (!ShapeUtil::IsArray(param->shape())) || - (ShapeUtil::Rank(param->shape()) < max_rank) || + (param->shape().rank() < max_rank) || (LayoutUtil::Equal(param->shape().layout(), *max_rank_layout)); }); } diff --git a/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc b/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc index f59da2caa1..ccd83e262e 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc @@ -196,9 +196,9 @@ Status GpuLayoutAssignment::AddBackendConstraints( CHECK_EQ(dim_nums.lhs_batch_dimensions_size(), dim_nums.rhs_batch_dimensions_size()); CHECK_EQ(dim_nums.lhs_batch_dimensions_size() + 2, - ShapeUtil::Rank(instruction->shape())); + instruction->shape().rank()); for (int64 batch_dim : dim_nums.lhs_batch_dimensions()) { - CHECK_LT(batch_dim, ShapeUtil::Rank(instruction->shape()) - 2); + CHECK_LT(batch_dim, instruction->shape().rank() - 2); } // Set both inputs and the output to default layout. @@ -215,11 +215,11 @@ Status GpuLayoutAssignment::AddBackendConstraints( TF_RETURN_IF_ERROR( constraints->SetInstructionLayout(output_shape, instruction)); } else if (instruction->opcode() == HloOpcode::kSort && - ShapeUtil::Rank(instruction->operand(0)->shape()) > 1) { + instruction->operand(0)->shape().rank() > 1) { // Make sure that all the operands and the output(s) have the same layout. Shape keys_shape = instruction->operand(0)->shape(); Layout keys_layout = - LayoutUtil::GetDefaultLayoutForRank(ShapeUtil::Rank(keys_shape)); + LayoutUtil::GetDefaultLayoutForRank(keys_shape.rank()); for (int64 i = 0; i < instruction->operand_count(); ++i) { Shape shape = instruction->operand(i)->shape(); *shape.mutable_layout() = keys_layout; diff --git a/tensorflow/compiler/xla/service/gpu/ir_emission_utils.cc b/tensorflow/compiler/xla/service/gpu/ir_emission_utils.cc index 33e41a2782..5d25a032a9 100644 --- a/tensorflow/compiler/xla/service/gpu/ir_emission_utils.cc +++ b/tensorflow/compiler/xla/service/gpu/ir_emission_utils.cc @@ -40,7 +40,7 @@ namespace { // Return whether the given shape is rank 2 excluding the batch dimensions. bool IsRank2(const Shape& shape, int64 batch_dimensions_size) { - return ShapeUtil::Rank(shape) == batch_dimensions_size + 2; + return shape.rank() == batch_dimensions_size + 2; } // In a gemm operation where output = lhs * rhs, check whether the given shapes diff --git a/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc b/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc index 1472853dc4..48d9840620 100644 --- a/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc +++ b/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc @@ -698,8 +698,8 @@ Status IrEmitterUnnested::HandleSelectAndScatter( const auto* source = select_and_scatter->operand(1); const Window& window = select_and_scatter->window(); PrimitiveType operand_element_type = operand->shape().element_type(); - const int64 rank = ShapeUtil::Rank(operand->shape()); - CHECK_EQ(rank, ShapeUtil::Rank(source->shape())); + const int64 rank = operand->shape().rank(); + CHECK_EQ(rank, source->shape().rank()); CHECK_EQ(rank, window.dimensions_size()); TF_ASSIGN_OR_RETURN(std::unique_ptr initializer_thunk, @@ -1015,7 +1015,7 @@ Status IrEmitterUnnested::EmitScatter( int64 raw_window_multidim_idx = 0; std::vector input_window_multidim; std::vector input_window_bounds; - for (int64 i = 0, e = ShapeUtil::Rank(operand->shape()); i != e; ++i) { + for (int64 i = 0, e = operand->shape().rank(); i != e; ++i) { if (absl::c_binary_search(dim_numbers.inserted_window_dims(), i)) { input_window_bounds.push_back(1); // Trivial dimension. input_window_multidim.push_back(index.GetConstantWithIndexType(0)); @@ -1027,12 +1027,11 @@ Status IrEmitterUnnested::EmitScatter( ++raw_window_multidim_idx; } } - DCHECK_EQ(input_window_multidim.size(), ShapeUtil::Rank(operand->shape())); + DCHECK_EQ(input_window_multidim.size(), operand->shape().rank()); // Insert a 1 dimension at the end if index_vector_dim requests one. Shape scatter_indices_shape = scatter_indices->shape(); - if (dim_numbers.index_vector_dim() == - ShapeUtil::Rank(scatter_indices_shape)) { + if (dim_numbers.index_vector_dim() == scatter_indices_shape.rank()) { scatter_indices_shape.add_dimensions(1); scatter_indices_shape.mutable_layout()->add_minor_to_major( dim_numbers.index_vector_dim()); @@ -3191,7 +3190,7 @@ Status AreFusedReductionOutputsConsistent( // dimensions from minor to major. DimensionVector GetDimensionsToKeepMinorToMajor( const Shape& input_shape, absl::Span dims_to_reduce) { - DimensionVector input_dims(ShapeUtil::Rank(input_shape), 0); + DimensionVector input_dims(input_shape.rank(), 0); absl::c_iota(input_dims, 0); DimensionVector input_dims_to_keep; for (int input_dim : input_dims) { @@ -3231,7 +3230,7 @@ std::tuple GetReductionToVectorDimensions( if (input_dims_to_keep_minor_to_major.empty()) { return std::make_tuple(num_reduced_major, num_kept, num_reduced_minor); } - DimensionVector input_dims(ShapeUtil::Rank(input_shape), 0); + DimensionVector input_dims(input_shape.rank(), 0); absl::c_iota(input_dims, 0); absl::Span minor_to_major = LayoutUtil::MinorToMajor(input_shape); diff --git a/tensorflow/compiler/xla/service/hlo_creation_utils.cc b/tensorflow/compiler/xla/service/hlo_creation_utils.cc index e41aeab19e..1678fba172 100644 --- a/tensorflow/compiler/xla/service/hlo_creation_utils.cc +++ b/tensorflow/compiler/xla/service/hlo_creation_utils.cc @@ -189,8 +189,7 @@ StatusOr MakeMapHlo(absl::Span operands, for (const HloInstruction* operand : operands) { CHECK_EQ(computation, operand->parent()); operand_shapes.push_back(&operand->shape()); - max_operand_rank = - std::max(max_operand_rank, ShapeUtil::Rank(operand->shape())); + max_operand_rank = std::max(max_operand_rank, operand->shape().rank()); } std::vector map_dims(max_operand_rank); std::iota(map_dims.begin(), map_dims.end(), 0); @@ -207,7 +206,7 @@ StatusOr MakeReduceHlo(HloInstruction* operand, HloOpcode binary_opcode, HloModule* module) { DCHECK_NE(nullptr, module); - std::vector all_dims(ShapeUtil::Rank(operand->shape())); + std::vector all_dims(operand->shape().rank()); std::iota(all_dims.begin(), all_dims.end(), 0); auto scalar_shape = ShapeUtil::MakeShape(operand->shape().element_type(), {}); diff --git a/tensorflow/compiler/xla/service/hlo_evaluator.cc b/tensorflow/compiler/xla/service/hlo_evaluator.cc index 934c082bb9..3d3c6af2f3 100644 --- a/tensorflow/compiler/xla/service/hlo_evaluator.cc +++ b/tensorflow/compiler/xla/service/hlo_evaluator.cc @@ -443,7 +443,7 @@ Status HloEvaluator::HandleConcatenate(HloInstruction* concatenate) { // concatenate dimensions of the operands taking part of the operation. const Shape& reference_shape = operands[0]->shape(); CHECK(ShapeUtil::IsArray(reference_shape)); - const int64 rank = ShapeUtil::Rank(reference_shape); + const int64 rank = reference_shape.rank(); const int64 concat_dim = concatenate->dimensions()[0]; CHECK_GE(concat_dim, 0); CHECK_LT(concat_dim, rank); @@ -1036,11 +1036,9 @@ Status HloEvaluator::HandleGather(HloInstruction* gather) { Status HloEvaluator::HandleBroadcast(HloInstruction* broadcast) { const Literal& operand = GetEvaluatedLiteralFor(broadcast->operand(0)); - TF_RET_CHECK(broadcast->dimensions().size() == - ShapeUtil::Rank(operand.shape())) + TF_RET_CHECK(broadcast->dimensions().size() == operand.shape().rank()) << "broadcast dimensions is of size: " << broadcast->dimensions().size() - << " and rank of operand_to_broadcast is: " - << ShapeUtil::Rank(operand.shape()); + << " and rank of operand_to_broadcast is: " << operand.shape().rank(); // Checks that operand's dimensions are the same as the broadcast's // dimensions along the dimensions to be broadcasted. for (int64 i = 0; i < broadcast->dimensions().size(); ++i) { @@ -1251,7 +1249,7 @@ template StatusOr EvaluateSortInternal(HloInstruction* sort, const Literal& keys_literal, const Literal& values_literal) { - auto rank = ShapeUtil::Rank(keys_literal.shape()); + auto rank = keys_literal.shape().rank(); TF_RET_CHECK( ShapeUtil::SameDimensions(keys_literal.shape(), values_literal.shape())) << "Sort keys and values must have the same dimensions"; diff --git a/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h b/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h index 3ace2f5443..7e0dadaf3e 100644 --- a/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h +++ b/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h @@ -1005,8 +1005,8 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { CHECK_GE(num_spatial_dims, 0); CHECK_EQ(window.dimensions_size(), num_spatial_dims); - const auto lhs_rank = ShapeUtil::Rank(lhs_shape); - const auto rhs_rank = ShapeUtil::Rank(rhs_shape); + const auto lhs_rank = lhs_shape.rank(); + const auto rhs_rank = rhs_shape.rank(); CHECK_EQ(num_spatial_dims + 2, lhs_rank); CHECK_EQ(num_spatial_dims + 2, rhs_rank); @@ -1175,8 +1175,8 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const auto& dnums = dot->dot_dimension_numbers(); - const int64 lhs_rank = ShapeUtil::Rank(lhs->shape()); - const int64 rhs_rank = ShapeUtil::Rank(rhs->shape()); + const int64 lhs_rank = lhs->shape().rank(); + const int64 rhs_rank = rhs->shape().rank(); CHECK(ShapeUtil::SameElementType(lhs->shape(), rhs->shape())); CHECK(ShapeUtil::SameElementType(lhs->shape(), dot->shape())); @@ -1238,8 +1238,8 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const auto& dnums = dot->dot_dimension_numbers(); - const auto lhs_rank = ShapeUtil::Rank(lhs->shape()); - const auto rhs_rank = ShapeUtil::Rank(rhs->shape()); + const auto lhs_rank = lhs->shape().rank(); + const auto rhs_rank = rhs->shape().rank(); CHECK(ShapeUtil::SameElementType(lhs->shape(), rhs->shape())); CHECK(ShapeUtil::SameElementType(lhs->shape(), dot->shape())); @@ -1329,7 +1329,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { CHECK(ShapeUtil::IsArray(pad->operand(0)->shape())); // Padding value must be scalar. CHECK(ShapeUtil::IsScalar(pad->operand(1)->shape())); - CHECK_EQ(ShapeUtil::Rank(pad->operand(0)->shape()), + CHECK_EQ(pad->operand(0)->shape().rank(), pad->padding_config().dimensions_size()); TF_ASSIGN_OR_RETURN(auto inferred_return_shape, @@ -1352,9 +1352,8 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const Literal& evaluated_operand = parent_->GetEvaluatedLiteralFor(pad->operand(0)); - std::vector input_index(ShapeUtil::Rank(evaluated_operand.shape()), - 0); - std::vector target_index(ShapeUtil::Rank(result.shape()), 0); + std::vector input_index(evaluated_operand.shape().rank(), 0); + std::vector target_index(result.shape().rank(), 0); // Loop through each element of the operand, assign them to the // corresponding index of the resulting padded literal. @@ -1609,7 +1608,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const Literal& keys_literal = parent_->GetEvaluatedLiteralFor(keys); int64 sort_dim = sort->dimensions(0); int64 sort_dim_elements = keys->shape().dimensions(sort_dim); - int64 rank = ShapeUtil::Rank(keys->shape()); + int64 rank = keys->shape().rank(); if (rank == 0) { // Nothing to sort. parent_->evaluated_[sort] = keys_literal.Clone(); @@ -1868,7 +1867,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const Literal& operand_literal = parent_->GetEvaluatedLiteralFor(operand); const Literal& source_literal = parent_->GetEvaluatedLiteralFor(source); - int64 rank = ShapeUtil::Rank(operand_literal.shape()); + int64 rank = operand_literal.shape().rank(); HloEvaluator embedded_evaluator(parent_->max_loop_iterations_); DimensionVector source_index(rank, 0); @@ -1980,7 +1979,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { operand->shape().element_type(), window_dimension_sizes); DimensionVector window_index(window.dimensions_size()); - DimensionVector operand_index(ShapeUtil::Rank(operand_literal.shape())); + DimensionVector operand_index(operand_literal.shape().rank()); HloEvaluator embedded_evaluator(parent_->max_loop_iterations_); Literal result(reduce_window->shape()); @@ -2411,7 +2410,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { << " but is inferred to be: " << ShapeUtil::HumanString(inferred_return_shape); - const int64 rank = ShapeUtil::Rank(operand->shape()); + const int64 rank = operand->shape().rank(); const Literal& operand_literal = parent_->GetEvaluatedLiteralFor(operand); auto func = [&](absl::Span out_index) { DimensionVector operand_index(rank); @@ -2648,12 +2647,12 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { } auto result = LiteralUtil::CreateR1(data); - if (ShapeUtil::Rank(iota->shape()) > 1) { + if (iota->shape().rank() > 1) { TF_ASSIGN_OR_RETURN( parent_->evaluated_[iota], result.Broadcast(iota->shape(), {iota->iota_dimension()})); } else { - TF_RET_CHECK(ShapeUtil::Rank(iota->shape()) == 1); + TF_RET_CHECK(iota->shape().rank() == 1); parent_->evaluated_[iota] = std::move(result); } @@ -2683,7 +2682,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { // // This lets you calculate LI given the multidimensional indices in any order. static DimensionVector MakeDimMultipliers(const Shape& shape) { - DimensionVector v(ShapeUtil::Rank(shape)); + DimensionVector v(shape.rank()); int64 scale = 1; for (auto dim : LayoutUtil::MinorToMajor(shape)) { v[dim] = scale; @@ -2700,7 +2699,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const Shape& window_shape, const Window& window, const Shape& base_shape, const absl::Span& window_count_index, const std::function&)>& f) { - const int64 rank = ShapeUtil::Rank(base_shape); + const int64 rank = base_shape.rank(); DimensionVector window_index(rank); std::fill(window_index.begin(), window_index.end(), 0); do { @@ -2767,7 +2766,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { const Literal& start_indices_literal) { auto result = operand_literal.Clone(); auto start_indices_typed = start_indices_literal.data(); - const auto rank = ShapeUtil::Rank(result.shape()); + const auto rank = result.shape().rank(); std::vector start(start_indices_typed.begin(), start_indices_typed.end()); // Clamp the update start indices so the slice is in-bounds w.r.t the diff --git a/tensorflow/compiler/xla/service/hlo_instruction.cc b/tensorflow/compiler/xla/service/hlo_instruction.cc index 3e8903c953..462fe3b321 100644 --- a/tensorflow/compiler/xla/service/hlo_instruction.cc +++ b/tensorflow/compiler/xla/service/hlo_instruction.cc @@ -1039,7 +1039,7 @@ HloInstruction::CreateBroadcastSequence( const std::function)>& adder) { CHECK(ShapeUtil::IsScalar(operand->shape()) || - ShapeUtil::Rank(operand->shape()) == ShapeUtil::Rank(output_shape)); + operand->shape().rank() == output_shape.rank()); Shape broadcast_shape = ShapeUtil::ChangeElementType( output_shape, operand->shape().element_type()); // Do explicit broadcast for scalar. @@ -1055,7 +1055,7 @@ HloInstruction::CreateBroadcastSequence( // Do explicit broadcast for degenerate broadcast. std::vector broadcast_dimensions; std::vector reshaped_dimensions; - for (int i = 0; i < ShapeUtil::Rank(operand->shape()); i++) { + for (int i = 0; i < operand->shape().rank(); i++) { if (operand->shape().dimensions(i) == output_shape.dimensions(i)) { broadcast_dimensions.push_back(i); reshaped_dimensions.push_back(operand->shape().dimensions(i)); diff --git a/tensorflow/compiler/xla/service/hlo_instructions.cc b/tensorflow/compiler/xla/service/hlo_instructions.cc index 756e260b60..977fa01acb 100644 --- a/tensorflow/compiler/xla/service/hlo_instructions.cc +++ b/tensorflow/compiler/xla/service/hlo_instructions.cc @@ -734,7 +734,7 @@ HloMapInstruction::HloMapInstruction(const Shape& shape, AppendComputation(map_computation); // TODO(b/65689298) Remove code below once Map is generalized to accept // arbitrary map dimensions. - dimensions_.resize(ShapeUtil::Rank(shape)); + dimensions_.resize(shape.rank()); std::iota(dimensions_.begin(), dimensions_.end(), 0); } diff --git a/tensorflow/compiler/xla/service/hlo_parser.cc b/tensorflow/compiler/xla/service/hlo_parser.cc index 44643951c1..4e9c562c93 100644 --- a/tensorflow/compiler/xla/service/hlo_parser.cc +++ b/tensorflow/compiler/xla/service/hlo_parser.cc @@ -1980,7 +1980,7 @@ bool HloParser::ParseNonTupleLiteral(Literal* literal, const Shape& shape) { } bool HloParser::ParseDenseLiteral(Literal* literal, const Shape& shape) { - const tensorflow::int64 rank = ShapeUtil::Rank(shape); + const tensorflow::int64 rank = shape.rank(); // Create a literal with the given shape in default layout. *literal = LiteralUtil::CreateFromDimensions( shape.element_type(), AsInt64Slice(shape.dimensions())); @@ -2145,7 +2145,7 @@ template bool HloParser::ParseSparseLiteralHelper(Literal* literal, const Shape& shape) { std::vector index; - tensorflow::int64 rank = ShapeUtil::Rank(shape); + tensorflow::int64 rank = shape.rank(); *literal = Literal(shape); diff --git a/tensorflow/compiler/xla/service/hlo_sharding.cc b/tensorflow/compiler/xla/service/hlo_sharding.cc index 70a860c356..b8b4fd6135 100644 --- a/tensorflow/compiler/xla/service/hlo_sharding.cc +++ b/tensorflow/compiler/xla/service/hlo_sharding.cc @@ -30,7 +30,7 @@ HloSharding HloSharding::AssignDevice(int64 device_id) { } HloSharding HloSharding::Tile1D(const Shape& input_shape, int64 num_tiles) { - CHECK_EQ(1, ShapeUtil::Rank(input_shape)); + CHECK_EQ(1, input_shape.rank()); CHECK_GT(num_tiles, 1); std::vector dimensions(1, num_tiles); Array assignment(dimensions); @@ -340,7 +340,7 @@ Status HloSharding::ValidateNonTuple(const Shape& shape, } // The tile assignment tensor must have the same rank as the input. - if (ShapeUtil::Rank(shape) != tile_assignment_.num_dimensions()) { + if (shape.rank() != tile_assignment_.num_dimensions()) { return tensorflow::errors::InvalidArgument( "Number of tile assignment dimensions is different to the input rank. " "sharding=", diff --git a/tensorflow/compiler/xla/service/hlo_verifier.cc b/tensorflow/compiler/xla/service/hlo_verifier.cc index e1c737132f..5e120b4971 100644 --- a/tensorflow/compiler/xla/service/hlo_verifier.cc +++ b/tensorflow/compiler/xla/service/hlo_verifier.cc @@ -349,7 +349,7 @@ Status ShapeVerifier::HandleConstant(HloInstruction* constant) { Status ShapeVerifier::HandleIota(HloInstruction* instruction) { TF_RETURN_IF_ERROR(CheckOperandCount(instruction, 0)); auto* iota = Cast(instruction); - const int64 rank = ShapeUtil::Rank(iota->shape()); + const int64 rank = iota->shape().rank(); if (rank == 0) { return InternalError("Iota does not support scalars."); } @@ -397,13 +397,11 @@ Status ShapeVerifier::HandleBroadcast(HloInstruction* broadcast) { const Shape& operand_shape = broadcast->operand(0)->shape(); // Check for mixed precision. TF_RET_CHECK(SameElementType(broadcast->shape(), operand_shape)); - TF_RET_CHECK(ShapeUtil::Rank(operand_shape) == - broadcast->dimensions().size()); - for (int64 operand_dimension = 0; - operand_dimension < ShapeUtil::Rank(operand_shape); + TF_RET_CHECK(operand_shape.rank() == broadcast->dimensions().size()); + for (int64 operand_dimension = 0; operand_dimension < operand_shape.rank(); ++operand_dimension) { int64 output_dimension = broadcast->dimensions()[operand_dimension]; - TF_RET_CHECK((output_dimension < ShapeUtil::Rank(broadcast->shape())) && + TF_RET_CHECK((output_dimension < broadcast->shape().rank()) && output_dimension >= 0 && (broadcast->shape().dimensions(output_dimension) == operand_shape.dimensions(operand_dimension))) @@ -524,8 +522,7 @@ Status ShapeVerifier::HandleMap(HloInstruction* map) { int64 max_operand_rank = 0; for (const HloInstruction* operand : map->operands()) { operand_shapes.push_back(&operand->shape()); - max_operand_rank = - std::max(max_operand_rank, ShapeUtil::Rank(operand->shape())); + max_operand_rank = std::max(max_operand_rank, operand->shape().rank()); } // TODO(b/65689298) Remove code below once Map is generalized to accept // arbitrary map dimensions. @@ -1271,11 +1268,11 @@ class InstructionVerifier : public DfsHloVisitorWithDefault { // op. See https://groups.google.com/forum/#!topic/xla-dev/9LqijHmTt_I // or ComputationLowerer::Visit() TF_RET_CHECK(broadcast->dimensions().size() == - ShapeUtil::Rank(broadcast->operand(0)->shape())) + broadcast->operand(0)->shape().rank()) << "Broadcast HLO (" << broadcast->ToShortString() << ") has invalid number of dimensions: " << broadcast->dimensions().size() - << " != " << ShapeUtil::Rank(broadcast->operand(0)->shape()); + << " != " << broadcast->operand(0)->shape().rank(); return Status::OK(); } @@ -1376,7 +1373,7 @@ class InstructionVerifier : public DfsHloVisitorWithDefault { for (HloInstruction* operand : instruction->operands()) { const Shape& operand_shape = operand->shape(); if (LayoutUtil::IsDenseArray(operand_shape) && - ShapeUtil::Rank(operand_shape) == ShapeUtil::Rank(result_shape)) { + operand_shape.rank() == result_shape.rank()) { const Layout& operand_layout = operand_shape.layout(); TF_RET_CHECK(LayoutUtil::Equal(result_layout, operand_layout)) << "Instruction shouldn't change layouts " diff --git a/tensorflow/compiler/xla/service/indexed_array_analysis.cc b/tensorflow/compiler/xla/service/indexed_array_analysis.cc index 1ebb331977..a41cf714c5 100644 --- a/tensorflow/compiler/xla/service/indexed_array_analysis.cc +++ b/tensorflow/compiler/xla/service/indexed_array_analysis.cc @@ -1002,7 +1002,7 @@ bool CanFoldDotIntoIndexedArray( absl::Span contracting_dims, absl::Span batch_dims) { absl::optional non_contracting_non_batch_dim = - GetOnlyNonContractingNonBatchDim(ShapeUtil::Rank(indexed_array->shape()), + GetOnlyNonContractingNonBatchDim(indexed_array->shape().rank(), contracting_dims, batch_dims); if (!non_contracting_non_batch_dim.has_value()) { VLOG(3) << tag << ": multiple or no non-contracting non-batch dimensions"; @@ -1015,7 +1015,7 @@ bool CanFoldDotIntoIndexedArray( return false; } - int64 indexed_array_rank = ShapeUtil::Rank(indexed_array->shape()); + int64 indexed_array_rank = indexed_array->shape().rank(); if (indexed_array->source_dim() < (indexed_array_rank - 2)) { // This restriction can be lifted by inserting reshape nodes. VLOG(3) << tag @@ -1043,7 +1043,7 @@ IndexedArrayAnalysis::ComputeArrayForDotWithIndexedLhs( return nullptr; } - int64 lhs_rank = ShapeUtil::Rank(lhs->shape()); + int64 lhs_rank = lhs->shape().rank(); DotDimensionNumbers new_dim_numbers = dim_numbers; new_dim_numbers.set_lhs_contracting_dimensions( 0, lhs->source_dim() == (lhs_rank - 1) ? (lhs_rank - 2) : (lhs_rank - 1)); @@ -1078,7 +1078,7 @@ IndexedArrayAnalysis::ComputeArrayForDotWithIndexedRhs( return nullptr; } - int64 rhs_rank = ShapeUtil::Rank(rhs->shape()); + int64 rhs_rank = rhs->shape().rank(); DotDimensionNumbers new_dim_numbers = dim_numbers; new_dim_numbers.set_rhs_contracting_dimensions( diff --git a/tensorflow/compiler/xla/service/layout_assignment.cc b/tensorflow/compiler/xla/service/layout_assignment.cc index b9ddd9636f..d30d2ff9b9 100644 --- a/tensorflow/compiler/xla/service/layout_assignment.cc +++ b/tensorflow/compiler/xla/service/layout_assignment.cc @@ -991,8 +991,7 @@ std::unique_ptr LayoutAssignment::ChooseOperandLayoutFromOutputLayout( CHECK(ShapeUtil::IsArray(instruction->shape())); CHECK(ShapeUtil::IsArray(operand->shape())); if (!ShapeUtil::IsScalar(operand->shape()) && - ShapeUtil::Rank(operand->shape()) == - ShapeUtil::Rank(instruction->shape()) && + operand->shape().rank() == instruction->shape().rank() && !instruction_can_change_layout_func_(instruction)) { // Propagate the result layout to the operand layout if the instruction // requires the same layout out for the result and the operand. @@ -1012,7 +1011,7 @@ std::unique_ptr LayoutAssignment::ChooseOperandLayoutFromOutputLayout( // operations. For similar reasons, if the operand and output have the same // rank, try to match the operand's layout to the output. if (ShapeUtil::TrueRank(operand->shape()) == 1 && - ShapeUtil::Rank(instruction->shape()) == 1) { + instruction->shape().rank() == 1) { // Don't assign a layout in case of R1 -> effective R1 reshape. return nullptr; } @@ -1026,7 +1025,7 @@ std::unique_ptr LayoutAssignment::ChooseOperandLayoutFromOutputLayout( if (ShapeUtil::ReshapeIsBitcast(operand_shape, output_shape_with_layout)) { return absl::make_unique(operand_shape.layout()); } - if (ShapeUtil::Rank(operand_shape) == ShapeUtil::Rank(output_shape)) { + if (operand_shape.rank() == output_shape.rank()) { *operand_shape.mutable_layout() = output_layout; if (ShapeUtil::ReshapeIsBitcast(operand_shape, output_shape_with_layout)) { @@ -1045,7 +1044,7 @@ std::unique_ptr LayoutAssignment::ChooseOperandLayoutFromOutputLayout( if (instruction->opcode() == HloOpcode::kTranspose) { // Pick the operand layout that makes the transpose a bitcast. - int64 rank = ShapeUtil::Rank(instruction->shape()); + int64 rank = instruction->shape().rank(); std::vector new_minor_to_major(rank); for (int64 i = 0; i < rank; ++i) { int64 output_dim = LayoutUtil::Minor(output_layout, i); @@ -1070,7 +1069,7 @@ std::unique_ptr LayoutAssignment::ChooseOutputLayoutFromOperandLayout( ShapeUtil::IsArray(operand->shape())); if (!ShapeUtil::IsScalar(operand->shape()) && - ShapeUtil::Rank(operand->shape()) == ShapeUtil::Rank(user->shape()) && + operand->shape().rank() == user->shape().rank() && !instruction_can_change_layout_func_(user)) { // Assign users the same layout as the operand. return absl::make_unique(operand_layout); @@ -1083,7 +1082,7 @@ std::unique_ptr LayoutAssignment::ChooseOutputLayoutFromOperandLayout( // reshape is a bitcast when using the same layout. This may avoid copy // operations. For similar reasons, if the operand and output have the same // rank, try to match the outputs's layout to the operand. - if (ShapeUtil::Rank(operand->shape()) == 1 && + if (operand->shape().rank() == 1 && ShapeUtil::TrueRank(user->shape()) == 1) { // Don't assign a layout in case of R1 -> effective R1 reshape. return nullptr; @@ -1098,7 +1097,7 @@ std::unique_ptr LayoutAssignment::ChooseOutputLayoutFromOperandLayout( if (ShapeUtil::ReshapeIsBitcast(output_shape, operand_shape_with_layout)) { return absl::make_unique(output_shape.layout()); } - if (ShapeUtil::Rank(operand->shape()) == ShapeUtil::Rank(output_shape)) { + if (operand->shape().rank() == output_shape.rank()) { *output_shape.mutable_layout() = operand_layout; if (ShapeUtil::ReshapeIsBitcast(output_shape, operand_shape_with_layout)) { @@ -1117,7 +1116,7 @@ std::unique_ptr LayoutAssignment::ChooseOutputLayoutFromOperandLayout( if (user->opcode() == HloOpcode::kTranspose) { // Pick the user layout that makes the transpose a bitcast. - int64 rank = ShapeUtil::Rank(user->shape()); + int64 rank = user->shape().rank(); std::vector new_minor_to_major(rank); auto inverse_dimensions = InversePermutation(user->dimensions()); for (int64 i = 0; i < rank; ++i) { @@ -1273,7 +1272,7 @@ Status LayoutAssignment::PropagateOperandConstraint( return Status::OK(); } - int64 operand_rank = ShapeUtil::Rank(operand->shape()); + int64 operand_rank = operand->shape().rank(); if (operand_rank <= 1) { return Status::OK(); } @@ -1288,7 +1287,7 @@ Status LayoutAssignment::PropagateOperandConstraint( continue; } const HloInstruction* sibling = user->operand(operand_no); - const int64 sibling_rank = ShapeUtil::Rank(sibling->shape()); + const int64 sibling_rank = sibling->shape().rank(); if (sibling_rank <= 1) { continue; } @@ -1320,13 +1319,13 @@ Status LayoutAssignment::PropagateOperandConstraint( if (ShapeUtil::IsTuple(subshape)) { return Status::OK(); } - if (ShapeUtil::Rank(subshape) <= 1) { + if (subshape.rank() <= 1) { return Status::OK(); } // Assign the right layout to input fusion of higher rank reduce // operations. - if (ShapeUtil::Rank(subshape) != ShapeUtil::Rank(operand->shape())) { + if (subshape.rank() != operand->shape().rank()) { return Status::OK(); } // TODO(b/67641796): Are there cases except fusion that use this code @@ -1357,7 +1356,7 @@ Status LayoutAssignment::PropagateOperandConstraint( if (ShapeUtil::IsTuple(subshape)) { return Status::OK(); } - if (ShapeUtil::Rank(subshape) <= 1) { + if (subshape.rank() <= 1) { return Status::OK(); } TF_ASSIGN_OR_RETURN( @@ -1402,7 +1401,7 @@ Status LayoutAssignment::PropagateBufferConstraintToOperands( if (!instruction_can_change_layout_func_(instruction)) { // Copy the layout to the operand. if (buffer.IsArray() && ShapeUtil::IsArray(operand->shape()) && - ShapeUtil::Rank(operand->shape()) == + operand->shape().rank() == LayoutUtil::MinorToMajor(buffer_constraint.layout()).size()) { TF_RETURN_IF_ERROR(constraints->SetArrayOperandLayout( buffer_constraint.layout(), instruction, operand_no, @@ -2101,7 +2100,7 @@ bool LayoutAssignment::InstructionCanChangeLayout( /* static */ bool LayoutAssignment::IsAtMostRank1(const Shape& shape) { if (ShapeUtil::IsArray(shape)) { - return ShapeUtil::Rank(shape) <= 1; + return shape.rank() <= 1; } return absl::c_all_of(shape.tuple_shapes(), [](const Shape& subshape) { return IsAtMostRank1(subshape); diff --git a/tensorflow/compiler/xla/service/layout_assignment_test.cc b/tensorflow/compiler/xla/service/layout_assignment_test.cc index 31d78752f0..387b385157 100644 --- a/tensorflow/compiler/xla/service/layout_assignment_test.cc +++ b/tensorflow/compiler/xla/service/layout_assignment_test.cc @@ -528,8 +528,7 @@ class OperandsMustBeTheSameLayoutAssignment : public LayoutAssignment { for (int64 operand_no = 0; operand_no < instruction->operand_count(); ++operand_no) { const HloInstruction* operand = instruction->operand(operand_no); - if (ShapeUtil::Rank(instruction->shape()) != - ShapeUtil::Rank(operand->shape())) { + if (instruction->shape().rank() != operand->shape().rank()) { continue; } TF_RETURN_IF_ERROR(constraints->SetArrayOperandLayout( diff --git a/tensorflow/compiler/xla/service/llvm_ir/dynamic_update_slice_util.cc b/tensorflow/compiler/xla/service/llvm_ir/dynamic_update_slice_util.cc index 4d7f36d9f8..1da7794532 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/dynamic_update_slice_util.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/dynamic_update_slice_util.cc @@ -44,7 +44,7 @@ static Status EmitDynamicUpdateSliceInPlaceImpl( const Shape& output_shape = output_array.GetShape(); // Read start indices from start_indices_generator. - const int64 rank = ShapeUtil::Rank(output_shape); + const int64 rank = output_shape.rank(); IrArray::Index start_index(b->getInt64Ty(), rank); for (int64 i = 0; i < rank; ++i) { IrArray::Index dim_index({b->getInt64(i)}); diff --git a/tensorflow/compiler/xla/service/llvm_ir/ir_array.cc b/tensorflow/compiler/xla/service/llvm_ir/ir_array.cc index 67f7423121..38078cd52b 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/ir_array.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/ir_array.cc @@ -61,7 +61,7 @@ void IrArray::Index::Delinearize(std::vector* multidim, IrArray::Index::Index(llvm::Value* linear, const Shape& shape, llvm::IRBuilder<>* b) - : multidim_(ShapeUtil::Rank(shape)), + : multidim_(shape.rank()), linear_(linear), layout_(shape.layout()), dims_(shape.dimensions().begin(), shape.dimensions().end()) { @@ -120,7 +120,7 @@ IrArray::IrArray(llvm::Value* base_ptr, const Shape& shape) if (!ShapeUtil::IsArray(*shape_) || ShapeUtil::IsScalar(*shape_)) { DCHECK(depth == 1 || depth == 0) << depth; } else { - DCHECK_EQ(depth, ShapeUtil::Rank(*shape_)) << shape.ShortDebugString(); + DCHECK_EQ(depth, shape_->rank()) << shape.ShortDebugString(); } } @@ -137,12 +137,12 @@ IrArray::Index IrArray::Index::SourceIndexOfReshape( const Shape& output_shape, const Shape& input_shape, llvm::IRBuilder<>* builder) const { const auto& target_index = *this; - CHECK_EQ(target_index.size(), ShapeUtil::Rank(output_shape)); + CHECK_EQ(target_index.size(), output_shape.rank()); std::vector> common_factors = CommonFactors(AsInt64Slice(input_shape.dimensions()), AsInt64Slice(output_shape.dimensions())); std::vector source_multidim_index( - ShapeUtil::Rank(input_shape), llvm::UndefValue::get(index_type_)); + input_shape.rank(), llvm::UndefValue::get(index_type_)); // We compute the source indices in each common factor from only the target // indices in the same common factor. for (ssize_t k = common_factors.size() - 2; k >= 0; --k) { @@ -257,7 +257,7 @@ IrArray::Index IrArray::Index::SourceIndexOfBroadcast( const Shape& shape, const Shape& operand_shape, absl::Span dimension_mapping, llvm::IRBuilder<>* builder) const { - int64 rank = ShapeUtil::Rank(operand_shape); + int64 rank = operand_shape.rank(); std::vector source_index(rank); for (int64 i = 0; i < rank; ++i) { source_index[i] = multidim_[dimension_mapping[i]]; @@ -271,7 +271,7 @@ IrArray::Index IrArray::Index::SourceIndexOfBroadcast( // The other dimensions can be masked out with a div and a mod operation. std::vector logical_to_physical = LayoutUtil::MakeLogicalToPhysical(shape.layout()); - int64 output_rank = ShapeUtil::Rank(shape); + int64 output_rank = shape.rank(); // The minimum physical dimension that is broadcasted. int64 min_broadcasted_dimension = output_rank; // The maximum physical dimension that is broadcasted. @@ -348,7 +348,7 @@ llvm::Value* IrArray::EmitArrayElementAddress(const IrArray::Index& index, // over higher-rank arrays. return base_ptr_; } - CHECK_EQ(index.size(), ShapeUtil::Rank(*shape_)); + CHECK_EQ(index.size(), shape_->rank()); if (index.LinearValidOnShape(*shape_)) { llvm::Module* module = b->GetInsertBlock()->getParent()->getParent(); diff --git a/tensorflow/compiler/xla/service/llvm_ir/llvm_loop.cc b/tensorflow/compiler/xla/service/llvm_ir/llvm_loop.cc index 219a9f221f..fe320bbe72 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/llvm_loop.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/llvm_loop.cc @@ -235,7 +235,7 @@ std::unique_ptr ForLoopNest::AddLoop(int64 start_index, IrArray::Index ForLoopNest::AddLoopsForShape(const Shape& shape, absl::string_view suffix) { - std::vector dimensions(ShapeUtil::Rank(shape)); + std::vector dimensions(shape.rank()); std::iota(dimensions.begin(), dimensions.end(), 0); return AddLoopsForShapeOnDimensions(shape, dimensions, suffix); } diff --git a/tensorflow/compiler/xla/service/llvm_ir/sort_util.cc b/tensorflow/compiler/xla/service/llvm_ir/sort_util.cc index 6a9406bfeb..89b6a36f96 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/sort_util.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/sort_util.cc @@ -322,7 +322,7 @@ Status EmitSortInPlace(int64 dimension_to_sort, const IrArray& keys_array, // comparisons). const Shape& keys_shape = keys_array.GetShape(); - int64 rank = ShapeUtil::Rank(keys_shape); + int64 rank = keys_shape.rank(); int64 dimension_to_sort_bound = keys_shape.dimensions(dimension_to_sort); std::vector dimensions_in_iteration_order(rank); std::vector iteration_order_to_logical_order(rank); diff --git a/tensorflow/compiler/xla/service/pattern_matcher.h b/tensorflow/compiler/xla/service/pattern_matcher.h index fdb6a9b01b..b9616e9132 100644 --- a/tensorflow/compiler/xla/service/pattern_matcher.h +++ b/tensorflow/compiler/xla/service/pattern_matcher.h @@ -831,7 +831,7 @@ class ShapePatternRankImpl { explicit constexpr ShapePatternRankImpl(int64 rank) : rank_(rank) {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - if (ShapeUtil::Rank(*shape) != rank_) { + if (shape->rank() != rank_) { if (rank_ == 0) { EXPLAIN << "Shape is not a scalar"; } else { diff --git a/tensorflow/compiler/xla/service/scatter_expander.cc b/tensorflow/compiler/xla/service/scatter_expander.cc index 11c2f8392d..e8496dbd72 100644 --- a/tensorflow/compiler/xla/service/scatter_expander.cc +++ b/tensorflow/compiler/xla/service/scatter_expander.cc @@ -88,7 +88,7 @@ static StatusOr CanonicalizeScatterIndices( static StatusOr PermuteScatterAndWindowDims( HloInstruction* updates, absl::Span update_window_dims) { std::vector permutation; - const int64 updates_rank = ShapeUtil::Rank(updates->shape()); + const int64 updates_rank = updates->shape().rank(); permutation.reserve(updates_rank); for (int64 i = 0; i < updates_rank; ++i) { diff --git a/tensorflow/compiler/xla/service/shape_inference.cc b/tensorflow/compiler/xla/service/shape_inference.cc index 8e571675c7..6d02c81076 100644 --- a/tensorflow/compiler/xla/service/shape_inference.cc +++ b/tensorflow/compiler/xla/service/shape_inference.cc @@ -96,7 +96,7 @@ Status VerifyReducerShape(const ProgramShape& reducer_shape, } for (const Shape* element_shape : accumulator_subshapes) { - if (ShapeUtil::Rank(*element_shape) != 0) { + if (element_shape->rank() != 0) { return InvalidArgument( "Reduction function must return a scalar or tuple of scalars but " "returns shape: %s", @@ -160,10 +160,10 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, const Window& window, PrimitiveType element_type, bool allow_negative_padding) { - if (window.dimensions_size() != ShapeUtil::Rank(base_shape)) { + if (window.dimensions_size() != base_shape.rank()) { return InvalidArgument( "Window has dimension %d but base shape has dimension %d.", - window.dimensions_size(), ShapeUtil::Rank(base_shape)); + window.dimensions_size(), base_shape.rank()); } std::vector output_dimensions(window.dimensions_size()); @@ -338,7 +338,7 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, if (arg_shapes.empty()) { return InvalidArgument("Concatenate expects at least one argument."); } - if (dimension < 0 || dimension >= ShapeUtil::Rank(*arg_shapes[0])) { + if (dimension < 0 || dimension >= arg_shapes[0]->rank()) { return InvalidArgument("Concatenate dimension out of bounds: %d.", dimension); } @@ -351,12 +351,12 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, element_type = arg_shape->element_type(); continue; } - if (ShapeUtil::Rank(*arg_shape) != ShapeUtil::Rank(*shape)) { + if (arg_shape->rank() != shape->rank()) { return InvalidArgument( "Cannot concatenate arrays with different ranks: %d (%s) vs %d " "(%s).", - ShapeUtil::Rank(*arg_shape), ShapeUtil::HumanString(*arg_shape), - ShapeUtil::Rank(*shape), ShapeUtil::HumanString(*shape)); + arg_shape->rank(), ShapeUtil::HumanString(*arg_shape), shape->rank(), + ShapeUtil::HumanString(*shape)); } if (!ShapeUtil::SameElementTypeIgnoringFpPrecision(*arg_shape, *shape)) { return InvalidArgument( @@ -364,8 +364,8 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, PrimitiveType_Name(arg_shape->element_type()), PrimitiveType_Name(shape->element_type())); } - for (int64 dimension_number = 0; - dimension_number < ShapeUtil::Rank(*arg_shape); ++dimension_number) { + for (int64 dimension_number = 0; dimension_number < arg_shape->rank(); + ++dimension_number) { if (arg_shape->dimensions(dimension_number) != shape->dimensions(dimension_number)) { if (dimension_number == dimension) { @@ -480,7 +480,7 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, return InvalidArgument( "Pad operation does not support non-scalar padding values."); } - if (ShapeUtil::Rank(operand_shape) != padding_config.dimensions_size()) { + if (operand_shape.rank() != padding_config.dimensions_size()) { return InvalidArgument( "The rank of the operand and the padding configuration do not match: " "%s vs %s.", @@ -500,7 +500,7 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, padding_config.ShortDebugString()); } - std::vector dimensions(ShapeUtil::Rank(operand_shape)); + std::vector dimensions(operand_shape.rank()); for (int64 i = 0; i < operand_shape.dimensions_size(); ++i) { const auto& p = padding_config.dimensions(i); dimensions[i] = operand_shape.dimensions(i) + p.edge_padding_low() + @@ -555,9 +555,9 @@ Status ValidateDotDimensionNumbers( absl::Span rhs_batch_dimensions = AsInt64Slice(dimension_numbers.rhs_batch_dimensions()); - if (!dims_in_range(ShapeUtil::Rank(lhs), lhs_contracting_dimensions, + if (!dims_in_range(lhs.rank(), lhs_contracting_dimensions, lhs_batch_dimensions) || - !dims_in_range(ShapeUtil::Rank(rhs), rhs_contracting_dimensions, + !dims_in_range(rhs.rank(), rhs_contracting_dimensions, rhs_batch_dimensions)) { return InvalidArgument("A dimension number is out of range in Dot: %s.", dimension_numbers.DebugString()); @@ -583,12 +583,10 @@ Status ValidateDotDimensionNumbers( // Check that the count of non-contracting-non-batch dimensions is in {0, 1}. const int64 lhs_non_contracting_non_batch_dims = - ShapeUtil::Rank(lhs) - - dimension_numbers.lhs_contracting_dimensions_size() - + lhs.rank() - dimension_numbers.lhs_contracting_dimensions_size() - dimension_numbers.lhs_batch_dimensions_size(); const int64 rhs_non_contracting_non_batch_dims = - ShapeUtil::Rank(rhs) - - dimension_numbers.rhs_contracting_dimensions_size() - + rhs.rank() - dimension_numbers.rhs_contracting_dimensions_size() - dimension_numbers.rhs_batch_dimensions_size(); if (lhs_non_contracting_non_batch_dims < 0 || lhs_non_contracting_non_batch_dims > 1 || @@ -637,7 +635,7 @@ Status ValidateDotDimensionNumbers( return fail("Element types do not match."); } - if ((ShapeUtil::Rank(lhs) < 1) || (ShapeUtil::Rank(rhs) < 1)) { + if ((lhs.rank() < 1) || (rhs.rank() < 1)) { return fail("Dot only supports rank 1 or above."); } @@ -686,12 +684,12 @@ Status ValidateDotDimensionNumbers( std::unordered_set rhs_batch_dims( dimension_numbers.rhs_batch_dimensions().begin(), dimension_numbers.rhs_batch_dimensions().end()); - for (int64 i = 0; i < ShapeUtil::Rank(lhs); i++) { + for (int64 i = 0; i < lhs.rank(); i++) { if (i != lhs_contracting_dimension) { dimensions.push_back(lhs.dimensions(i)); } } - for (int64 i = 0; i < ShapeUtil::Rank(rhs); i++) { + for (int64 i = 0; i < rhs.rank(); i++) { if (i != rhs_contracting_dimension && rhs_batch_dims.count(i) == 0) { dimensions.push_back(rhs.dimensions(i)); } @@ -708,14 +706,14 @@ Status ValidateDotDimensionNumbers( ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, const Shape& lhs, const Shape& rhs) { - TF_RET_CHECK(ShapeUtil::Rank(lhs) == ShapeUtil::Rank(rhs)); + TF_RET_CHECK(lhs.rank() == rhs.rank()); // The shapes have to be compatible. That is, if some dimension d has a // different size in the two shapes, one of them has to be 1 (a "degenerate" // dimension). In that case, the output shape has the non-1 dimension size // from the lhs/rhs pair in every index. - std::vector output_dimensions(ShapeUtil::Rank(lhs)); - for (int64 i = 0; i < ShapeUtil::Rank(lhs); ++i) { + std::vector output_dimensions(lhs.rank()); + for (int64 i = 0; i < lhs.rank(); ++i) { if (lhs.dimensions(i) == rhs.dimensions(i)) { output_dimensions[i] = lhs.dimensions(i); } else if (lhs.dimensions(i) == 1) { @@ -743,13 +741,13 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, return InvalidArgument("Automatic shape inference not supported: %s and %s", ShapeUtil::HumanString(smaller_shape), ShapeUtil::HumanString(larger_shape)); - } else if (broadcast_dimensions.size() != ShapeUtil::Rank(smaller_shape)) { + } else if (broadcast_dimensions.size() != smaller_shape.rank()) { return InvalidArgument( "Size of broadcast_dimensions has to match lower-rank operand's " "rank; " " lower-rank operand's rank is %d, size of broadcast_dimensions is " "%u.", - ShapeUtil::Rank(smaller_shape), broadcast_dimensions.size()); + smaller_shape.rank(), broadcast_dimensions.size()); } // broadcast_dimensions is a sequence of dimensions; its length is equal to @@ -847,8 +845,8 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, ShapeUtil::HumanString(rhs)); } - if (ShapeUtil::Rank(lhs) == ShapeUtil::Rank(rhs)) { - std::vector identity_dims(ShapeUtil::Rank(lhs)); + if (lhs.rank() == rhs.rank()) { + std::vector identity_dims(lhs.rank()); std::iota(identity_dims.begin(), identity_dims.end(), 0); if (!broadcast_dimensions.empty() && broadcast_dimensions != identity_dims) { @@ -865,15 +863,13 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, lhs, ShapeUtil::HigherPrecisionElementType(lhs, rhs)); } - if (ShapeUtil::Rank(lhs) == ShapeUtil::Rank(rhs)) { + if (lhs.rank() == rhs.rank()) { return InferDegenerateDimensionBroadcastShape(operation, lhs, rhs); } else { // Ranks do not match, so perform InDim broadcasting using // broadcast_dimensions. Scalar broadcasting is a special case of this. - const Shape& larger_shape = - ShapeUtil::Rank(lhs) > ShapeUtil::Rank(rhs) ? lhs : rhs; - const Shape& smaller_shape = - ShapeUtil::Rank(lhs) > ShapeUtil::Rank(rhs) ? rhs : lhs; + const Shape& larger_shape = lhs.rank() > rhs.rank() ? lhs : rhs; + const Shape& smaller_shape = lhs.rank() > rhs.rank() ? rhs : lhs; // After InDim broadcasting, perform degenerate dimensions broadcasting. TF_ASSIGN_OR_RETURN(Shape indim_broadcast_shape, @@ -1162,12 +1158,12 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, TF_RET_CHECK(ShapeUtil::ValidateShapeWithOptionalLayout(scale_shape) == Status::OK()); - if (feature_index >= ShapeUtil::Rank(operand_shape)) { + if (feature_index >= operand_shape.rank()) { return InvalidArgument( "Expected feature_index of batch-norm-training to be " "smaller than the rank of operand_shape; " "got feature_index %d, and rank %d.", - feature_index, ShapeUtil::Rank(operand_shape)); + feature_index, operand_shape.rank()); } if (feature_index < 0) { @@ -1177,25 +1173,25 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, feature_index); } - if (ShapeUtil::Rank(operand_shape) < 1) { + if (operand_shape.rank() < 1) { return InvalidArgument( "Expected the rank of operand to " "batch-norm-training to be at least 1; got %d.", - ShapeUtil::Rank(operand_shape)); + operand_shape.rank()); } - if (ShapeUtil::Rank(offset_shape) != 1) { + if (offset_shape.rank() != 1) { return InvalidArgument( "Offset input of batch-norm-training must have" " rank 1, but has rank %d.", - ShapeUtil::Rank(offset_shape)); + offset_shape.rank()); } - if (ShapeUtil::Rank(scale_shape) != 1) { + if (scale_shape.rank() != 1) { return InvalidArgument( "Scale input of batch-norm-training must have" " rank 1, but has rank %d.", - ShapeUtil::Rank(scale_shape)); + scale_shape.rank()); } if (!ShapeUtil::ElementIsFloating(operand_shape)) { @@ -1272,12 +1268,12 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, TF_RET_CHECK(ShapeUtil::ValidateShapeWithOptionalLayout(variance_shape) == Status::OK()); - if (feature_index >= ShapeUtil::Rank(operand_shape)) { + if (feature_index >= operand_shape.rank()) { return InvalidArgument( "Expected feature_index of batch-norm-inference to be " "smaller than the rank of operand_shape; " "got feature_index %d, and rank %d.", - feature_index, ShapeUtil::Rank(operand_shape)); + feature_index, operand_shape.rank()); } if (feature_index < 0) { @@ -1287,25 +1283,25 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, feature_index); } - if (ShapeUtil::Rank(operand_shape) < 1) { + if (operand_shape.rank() < 1) { return InvalidArgument( "Expected the rank of operand to " "batch-norm-inference to be at least 1; got %d.", - ShapeUtil::Rank(operand_shape)); + operand_shape.rank()); } - if (ShapeUtil::Rank(offset_shape) != 1) { + if (offset_shape.rank() != 1) { return InvalidArgument( "Offset input of batch-norm-inference must have" " rank 1, but has rank %d.", - ShapeUtil::Rank(offset_shape)); + offset_shape.rank()); } - if (ShapeUtil::Rank(scale_shape) != 1) { + if (scale_shape.rank() != 1) { return InvalidArgument( "Scale input of batch-norm-inference must have" " rank 1, but has rank %d.", - ShapeUtil::Rank(scale_shape)); + scale_shape.rank()); } if (!ShapeUtil::ElementIsFloating(operand_shape)) { @@ -1417,41 +1413,41 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, TF_RETURN_IF_ERROR( ShapeUtil::ValidateShapeWithOptionalLayout(output_grad_shape)); - if (feature_index >= ShapeUtil::Rank(operand_shape)) { + if (feature_index >= operand_shape.rank()) { return InvalidArgument( "Expected feature_index of batch-norm-grad to be " "smaller than the rank of operand_shape; " "got feature_index %d, and rank %d.", - feature_index, ShapeUtil::Rank(operand_shape)); + feature_index, operand_shape.rank()); } - if (ShapeUtil::Rank(operand_shape) != ShapeUtil::Rank(output_grad_shape)) { + if (operand_shape.rank() != output_grad_shape.rank()) { return InvalidArgument( "Expected operand_shape of batch-norm-grad to have the same rank as" " output_grad_shape; got rank(oprand_shape) %d, and" " rank(output_grad_shape) %d.", - ShapeUtil::Rank(operand_shape), ShapeUtil::Rank(output_grad_shape)); + operand_shape.rank(), output_grad_shape.rank()); } - if (ShapeUtil::Rank(mean_shape) != 1) { + if (mean_shape.rank() != 1) { return InvalidArgument( "Mean input of batch-norm-grad must have" " rank 1, but has rank %d.", - ShapeUtil::Rank(mean_shape)); + mean_shape.rank()); } - if (ShapeUtil::Rank(scale_shape) != 1) { + if (scale_shape.rank() != 1) { return InvalidArgument( "Scale input of batch-norm-grad must have" " rank 1, but has rank %d.", - ShapeUtil::Rank(scale_shape)); + scale_shape.rank()); } - if (ShapeUtil::Rank(var_shape) != 1) { + if (var_shape.rank() != 1) { return InvalidArgument( "Var input of batch-norm-grad must have" " rank 1, but has rank %d.", - ShapeUtil::Rank(var_shape)); + var_shape.rank()); } if (!ShapeUtil::ElementIsFloating(operand_shape)) { @@ -1538,7 +1534,7 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, } // Verify operand_shape and output_grad_shape have same bounds. - for (int64 i = 0; i < ShapeUtil::Rank(operand_shape); ++i) { + for (int64 i = 0; i < operand_shape.rank(); ++i) { if (ShapeUtil::GetDimension(operand_shape, i) != ShapeUtil::GetDimension(output_grad_shape, i)) { return InvalidArgument( @@ -1603,12 +1599,12 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, } const int num_dims = num_spatial_dims + 2; - if (ShapeUtil::Rank(lhs) != num_dims) { + if (lhs.rank() != num_dims) { return InvalidArgument( "The LHS argument to a convolution should have rank %d; lhs: %s.", num_dims, ShapeUtil::HumanString(lhs)); } - if (ShapeUtil::Rank(rhs) != num_dims) { + if (rhs.rank() != num_dims) { return InvalidArgument( "The RHS argument to a convolution should have rank %d; rhs: %s.", num_dims, ShapeUtil::HumanString(rhs)); @@ -1853,12 +1849,12 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, const Shape& shape, int64 split_dimension, int64 concat_dimension, int64 split_count) { TF_RET_CHECK(split_count > 0); - if (split_dimension >= ShapeUtil::Rank(shape) || split_dimension < 0) { + if (split_dimension >= shape.rank() || split_dimension < 0) { return InvalidArgument( "AllToAll split_dimension %d is out-of-bounds in shape %s.", split_dimension, ShapeUtil::HumanString(shape)); } - if (concat_dimension >= ShapeUtil::Rank(shape) || concat_dimension < 0) { + if (concat_dimension >= shape.rank() || concat_dimension < 0) { return InvalidArgument( "AllToAll concat_dimension %d is out-of-bounds in shape %s.", concat_dimension, ShapeUtil::HumanString(shape)); @@ -1932,7 +1928,7 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, // doesn't matter which one we choose. const Shape& arg = *reduced_args[0]; for (int64 dimension : dimensions_to_reduce) { - if (dimension >= ShapeUtil::Rank(arg) || dimension < 0) { + if (dimension >= arg.rank() || dimension < 0) { return InvalidArgument("Reducing out-of-bounds dimension %d in shape %s.", dimension, ShapeUtil::HumanString(arg)); } @@ -1949,7 +1945,7 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, std::set dimensions_to_reduce_set(dimensions_to_reduce.begin(), dimensions_to_reduce.end()); std::vector new_dimensions; - for (int i = 0; i < ShapeUtil::Rank(arg); ++i) { + for (int i = 0; i < arg.rank(); ++i) { if (dimensions_to_reduce_set.find(i) == dimensions_to_reduce_set.end()) { new_dimensions.push_back(arg.dimensions(i)); } @@ -2041,7 +2037,7 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, /* static */ StatusOr ShapeInference::InferGetDimensionSizeShape( const Shape& shape, int64 dimension) { - if (dimension < 0 || dimension >= ShapeUtil::Rank(shape)) { + if (dimension < 0 || dimension >= shape.rank()) { return InvalidArgument("GetDimensionSize dimension out of bounds: %d.", dimension); } @@ -2083,10 +2079,10 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, starts.size(), strides.size())); } - if (starts.size() != ShapeUtil::Rank(arg)) { + if (starts.size() != arg.rank()) { return InvalidArgument( "Slice index count does not match argument rank: %u vs %d.", - starts.size(), ShapeUtil::Rank(arg)); + starts.size(), arg.rank()); } std::vector sizes; @@ -2132,10 +2128,10 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, ShapeUtil::HumanString(operand_shape), ShapeUtil::HumanString(start_indices_shape), StrJoin(slice_sizes, ", ")); - if (ShapeUtil::Rank(start_indices_shape) != 1) { + if (start_indices_shape.rank() != 1) { return InvalidArgument( "Dynamic slice start indices of rank %d must be rank1.", - ShapeUtil::Rank(start_indices_shape)); + start_indices_shape.rank()); } if (!ShapeUtil::ElementIsIntegral(start_indices_shape)) { @@ -2144,18 +2140,18 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, } const int64 start_num_dims = start_indices_shape.dimensions(0); - if (ShapeUtil::Rank(operand_shape) != start_num_dims) { + if (operand_shape.rank() != start_num_dims) { return InvalidArgument( "Dynamic slice start number of dimensions %d (%s) must match rank " "%d of slice input (%s).", start_num_dims, ShapeUtil::HumanString(start_indices_shape), - ShapeUtil::Rank(operand_shape), ShapeUtil::HumanString(operand_shape)); + operand_shape.rank(), ShapeUtil::HumanString(operand_shape)); } - if (slice_sizes.size() != ShapeUtil::Rank(operand_shape)) { + if (slice_sizes.size() != operand_shape.rank()) { return InvalidArgument( "Dynamic slice index count does not match argument rank: %u vs %d.", - slice_sizes.size(), ShapeUtil::Rank(operand_shape)); + slice_sizes.size(), operand_shape.rank()); } for (int64 dim = 0; dim < slice_sizes.size(); ++dim) { @@ -2193,10 +2189,10 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, ShapeUtil::HumanString(start_indices_shape), ShapeUtil::HumanString(update_shape)); - if (ShapeUtil::Rank(start_indices_shape) != 1) { + if (start_indices_shape.rank() != 1) { return InvalidArgument( "Dynamic update slice start indices of rank %d must be rank1.", - ShapeUtil::Rank(start_indices_shape)); + start_indices_shape.rank()); } if (!ShapeUtil::ElementIsIntegral(start_indices_shape)) { @@ -2205,19 +2201,19 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, } const int64 start_num_dims = start_indices_shape.dimensions(0); - if (ShapeUtil::Rank(operand_shape) != start_num_dims) { + if (operand_shape.rank() != start_num_dims) { return InvalidArgument( "Dynamic update slice start number of dimensions %d (%s) must match " "rank %d of slice input (%s).", start_num_dims, ShapeUtil::HumanString(start_indices_shape), - ShapeUtil::Rank(operand_shape), ShapeUtil::HumanString(operand_shape)); + operand_shape.rank(), ShapeUtil::HumanString(operand_shape)); } - if (ShapeUtil::Rank(update_shape) != ShapeUtil::Rank(operand_shape)) { + if (update_shape.rank() != operand_shape.rank()) { return InvalidArgument( "Dynamic update slice update rank does not match argument rank: " "%d vs %d.", - ShapeUtil::Rank(update_shape), ShapeUtil::Rank(operand_shape)); + update_shape.rank(), operand_shape.rank()); } if (!ShapeUtil::SameElementTypeIgnoringFpPrecision(operand_shape, @@ -2229,7 +2225,7 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, PrimitiveType_Name(update_shape.element_type())); } - for (int64 dim = 0; dim < ShapeUtil::Rank(operand_shape); ++dim) { + for (int64 dim = 0; dim < operand_shape.rank(); ++dim) { const int64 input_dim_size = operand_shape.dimensions(dim); const int64 update_dim_size = update_shape.dimensions(dim); if (update_dim_size < 0) { @@ -2255,7 +2251,7 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, return InvalidArgument("a dimension number is duplicated in reverse"); } for (int64 dimension : dimensions) { - if (dimension >= ShapeUtil::Rank(operand_shape) || dimension < 0) { + if (dimension >= operand_shape.rank() || dimension < 0) { return InvalidArgument( "One of the reverse dimensions (%d) is out-of-bounds in shape %s.", dimension, ShapeUtil::HumanString(operand_shape)); @@ -2397,8 +2393,8 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, absl::Span broadcast_dimensions) { TF_RETURN_IF_ERROR(ExpectArray(operand_shape, "operand of broadcast")); TF_RETURN_IF_ERROR(ExpectArray(output_shape, "operand of broadcast")); - const int64 operand_rank = ShapeUtil::Rank(operand_shape); - const int64 output_rank = ShapeUtil::Rank(output_shape); + const int64 operand_rank = operand_shape.rank(); + const int64 output_rank = output_shape.rank(); if (operand_rank > output_rank) { return InvalidArgument( "InDim style broadcast must be to an equal or higher ranked shape; " @@ -2457,9 +2453,9 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, ShapeUtil::HumanString(inferred_shape)); } - std::vector indices(ShapeUtil::Rank(operand)); + std::vector indices(operand.rank()); std::iota(indices.begin(), indices.end(), 0); - if (dimensions.size() != ShapeUtil::Rank(operand) || + if (dimensions.size() != operand.rank() || !std::is_permutation(dimensions.begin(), dimensions.end(), indices.begin())) { return InvalidArgument( @@ -2475,9 +2471,9 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, const Shape& operand, absl::Span dimensions) { TF_RETURN_IF_ERROR(ExpectArray(operand, "transpose")); - std::vector indices(ShapeUtil::Rank(operand)); + std::vector indices(operand.rank()); std::iota(indices.begin(), indices.end(), 0); - if (dimensions.size() != ShapeUtil::Rank(operand) || + if (dimensions.size() != operand.rank() || !std::is_permutation(dimensions.begin(), dimensions.end(), indices.begin())) { return InvalidArgument( @@ -2829,7 +2825,7 @@ Status ValidateScatterDimensionNumbers( "update_window_dims in scatter op must not repeat; got: %s.", StrJoin(dim_numbers.update_window_dims(), ", ")); } - const int64 updates_rank = ShapeUtil::Rank(updates_shape); + const int64 updates_rank = updates_shape.rank(); for (int64 window_dim : dim_numbers.update_window_dims()) { if (window_dim < 0 || window_dim >= updates_rank) { return InvalidArgument( @@ -2863,10 +2859,10 @@ Status ValidateScatterDimensionNumbers( // Validate window size. auto window_size = dim_numbers.update_window_dims_size() + dim_numbers.inserted_window_dims_size(); - if (window_size != ShapeUtil::Rank(operand_shape)) { + if (window_size != operand_shape.rank()) { return InvalidArgument( "Scatter op has window of size %d; doesn't match operand of rank %d.", - window_size, ShapeUtil::Rank(operand_shape)); + window_size, operand_shape.rank()); } // Validate scatter_dims_to_operand_dims in ScatterDimensionNumbers. @@ -2951,10 +2947,9 @@ Status ValidateScatterDimensionNumbers( int64 expected_updates_rank = expanded_scatter_indices_shape.size() - 1 + scatter_dim_numbers.update_window_dims_size(); - if (ShapeUtil::Rank(updates_shape) != expected_updates_rank) { + if (updates_shape.rank() != expected_updates_rank) { return InvalidArgument("Updates tensor must be of rank %d; got %d.", - expected_updates_rank, - ShapeUtil::Rank(updates_shape)); + expected_updates_rank, updates_shape.rank()); } TF_RETURN_IF_ERROR(ValidateScatterDimensionNumbers( @@ -2985,7 +2980,7 @@ Status ValidateScatterDimensionNumbers( } int64 scatter_dims_seen = 0; - for (int64 i = 0; i < ShapeUtil::Rank(updates_shape); ++i) { + for (int64 i = 0; i < updates_shape.rank(); ++i) { bool is_update_window_dim = absl::c_binary_search(scatter_dim_numbers.update_window_dims(), i); if (is_update_window_dim) { diff --git a/tensorflow/compiler/xla/service/transpose_folding.cc b/tensorflow/compiler/xla/service/transpose_folding.cc index eaf4f28b87..15eb46bac0 100644 --- a/tensorflow/compiler/xla/service/transpose_folding.cc +++ b/tensorflow/compiler/xla/service/transpose_folding.cc @@ -45,7 +45,7 @@ TransposeFolding::OperandIndices CanFoldOperandsIntoDot( auto& operand = *dot.operand(i); if (operand.IsRank2Transpose()) { operand_set.push_back(i); - } else if (ShapeUtil::Rank(operand.shape()) != 2) { + } else if (operand.shape().rank() != 2) { return {}; } } diff --git a/tensorflow/compiler/xla/shape.cc b/tensorflow/compiler/xla/shape.cc index b206345db2..cec8dc2c20 100644 --- a/tensorflow/compiler/xla/shape.cc +++ b/tensorflow/compiler/xla/shape.cc @@ -61,6 +61,12 @@ string Shape::ToString(bool print_layout) const { } } +int64 Shape::rank() const { + CHECK(ShapeUtil::IsArray(*this)) + << "Non-arrays do not have a rank, shape: " << *this; + return dimensions_.size(); +} + std::ostream& operator<<(std::ostream& out, const Shape& shape) { out << shape.ToString(/*print_layout=*/true); return out; diff --git a/tensorflow/compiler/xla/shape.h b/tensorflow/compiler/xla/shape.h index 7643f64d8a..91edafe2f7 100644 --- a/tensorflow/compiler/xla/shape.h +++ b/tensorflow/compiler/xla/shape.h @@ -44,6 +44,10 @@ class Shape { // without layout. e.g. "F32[42,12] {0, 1}" or "F32[64]". string ToString(bool print_layout = false) const; + // Returns the rank (number of dimensions) of the given shape. Shape must be + // an array. + int64 rank() const; + // The following methods mirror the protobuf generated code interface for the // message ShapeProto. This enabled easy migration of this data structure // from a proto to a proper C++ class. diff --git a/tensorflow/compiler/xla/shape_util.cc b/tensorflow/compiler/xla/shape_util.cc index be7d71ada0..8ad241f2c9 100644 --- a/tensorflow/compiler/xla/shape_util.cc +++ b/tensorflow/compiler/xla/shape_util.cc @@ -679,8 +679,8 @@ ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout( /* static */ int64 ShapeUtil::ByteSizeOfSparseIndices(const Shape& shape) { TF_DCHECK_OK(ValidateShape(shape)); CHECK(LayoutUtil::IsSparseArray(shape)); - return LayoutUtil::MaxSparseElements(shape.layout()) * - ShapeUtil::Rank(shape) * sizeof(int64); + return LayoutUtil::MaxSparseElements(shape.layout()) * shape.rank() * + sizeof(int64); } /* static */ Status ShapeUtil::ValidateShapeWithOptionalLayoutInternal( @@ -763,7 +763,7 @@ ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout( return sparse_elements_size; } int64 sparse_indices_size = - MultiplyWithoutOverflow(max_sparse_elements, ShapeUtil::Rank(shape)); + MultiplyWithoutOverflow(max_sparse_elements, shape.rank()); if (sparse_indices_size < 0) { return sparse_indices_size; } diff --git a/tensorflow/compiler/xla/shape_util.h b/tensorflow/compiler/xla/shape_util.h index 8a7d755951..e1c37d79e2 100644 --- a/tensorflow/compiler/xla/shape_util.h +++ b/tensorflow/compiler/xla/shape_util.h @@ -298,6 +298,7 @@ class ShapeUtil { // Returns the rank (number of dimensions) of the given shape. // Precondition: !IsTuple(shape) + ABSL_DEPRECATED("Use `Shape::rank` instead.") static int64 Rank(const Shape& shape); // Returns the number of dimensions for which the dimension is not (trivially) diff --git a/tensorflow/compiler/xla/sparse_index_array.cc b/tensorflow/compiler/xla/sparse_index_array.cc index a40bb7875e..82091bdee6 100644 --- a/tensorflow/compiler/xla/sparse_index_array.cc +++ b/tensorflow/compiler/xla/sparse_index_array.cc @@ -79,7 +79,7 @@ void SparseIndexArray::Resize(int64 num_indices) { } bool SparseIndexArray::Validate(const Shape& shape) const { - if (rank_ == 0 || rank_ != ShapeUtil::Rank(shape)) { + if (rank_ == 0 || rank_ != shape.rank()) { return false; } int64 num_indices = index_count(); diff --git a/tensorflow/compiler/xla/tests/client_library_test_base.cc b/tensorflow/compiler/xla/tests/client_library_test_base.cc index a350715597..20f6c189da 100644 --- a/tensorflow/compiler/xla/tests/client_library_test_base.cc +++ b/tensorflow/compiler/xla/tests/client_library_test_base.cc @@ -191,7 +191,7 @@ Status ClientLibraryTestBase::ComputeAndCompareLiteralWithAllOutputLayouts( verify_output(actual, ""); // Try with all output layouts. - std::vector minor_to_major(ShapeUtil::Rank(expected.shape())); + std::vector minor_to_major(expected.shape().rank()); std::iota(minor_to_major.begin(), minor_to_major.end(), 0); do { auto layout = ShapeUtil::MakeShapeWithLayout( @@ -234,7 +234,7 @@ Status ClientLibraryTestBase::ComputeAndCompareLiteralWithAllInputLayouts( return Status::OK(); } - std::vector minor_to_major(ShapeUtil::Rank(literal.shape())); + std::vector minor_to_major(literal.shape().rank()); std::iota(minor_to_major.begin(), minor_to_major.end(), 0); do { auto literal_relayout = diff --git a/tensorflow/compiler/xla/tests/test_utils.cc b/tensorflow/compiler/xla/tests/test_utils.cc index eafa48ed7b..96ccda6a79 100644 --- a/tensorflow/compiler/xla/tests/test_utils.cc +++ b/tensorflow/compiler/xla/tests/test_utils.cc @@ -348,7 +348,7 @@ StatusOr CreateLiteralForConstrainedUses( const Shape& slice_shape = use->opcode() == HloOpcode::kDynamicSlice ? use->shape() : use->operand(1)->shape(); - const int64 rank = ShapeUtil::Rank(indexed_shape); + const int64 rank = indexed_shape.rank(); if (!index_space.empty()) { TF_RET_CHECK(rank == index_space.size()); for (int64 i = 0; i < rank; ++i) { @@ -459,8 +459,8 @@ Status VerifyHloModule(HloModule* const module, bool layout_sensitive, std::unique_ptr CreateCanonicalDot(const Shape& shape, HloInstruction* lhs, HloInstruction* rhs) { - CHECK_EQ(ShapeUtil::Rank(lhs->shape()), 2); - CHECK_EQ(ShapeUtil::Rank(rhs->shape()), 2); + CHECK_EQ(lhs->shape().rank(), 2); + CHECK_EQ(rhs->shape().rank(), 2); PrecisionConfig precision_config; precision_config.mutable_operand_precision()->Resize( 2, PrecisionConfig::DEFAULT); -- GitLab From b6d6f585dc6d0f966f21d164f41b2184404e2255 Mon Sep 17 00:00:00 2001 From: Mihai Maruseac Date: Thu, 20 Dec 2018 16:30:49 -0800 Subject: [PATCH 0213/1765] Fix ScatterNd fuzz empty buffer bug. PiperOrigin-RevId: 226412866 --- tensorflow/core/kernels/fuzzing/scatter_nd_fuzz.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tensorflow/core/kernels/fuzzing/scatter_nd_fuzz.cc b/tensorflow/core/kernels/fuzzing/scatter_nd_fuzz.cc index 35f876b3b1..dc5e143cdf 100644 --- a/tensorflow/core/kernels/fuzzing/scatter_nd_fuzz.cc +++ b/tensorflow/core/kernels/fuzzing/scatter_nd_fuzz.cc @@ -44,6 +44,9 @@ class FuzzScatterNd : public FuzzSession { // indices_tensor. Rather than using random values for the // updates_tensor.shape and getting most of the fuzz runs stopped in the // check, it's better to just create a proper update_tensor. + if (size < 1) { + return; + } // First element of the data buffer gives the number of dimensions of the // shape tensor. -- GitLab From 71bcf47503294a589db51852552b55ed1b5f4ddb Mon Sep 17 00:00:00 2001 From: Pete Warden Date: Thu, 20 Dec 2018 16:51:03 -0800 Subject: [PATCH 0214/1765] Formatting fixes for the C files --- .../examples/micro_speech/apollo3/_main.c | 188 ++++--- .../micro_speech/apollo3/pushbutton_main.c | 460 +++++++++--------- 2 files changed, 314 insertions(+), 334 deletions(-) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/_main.c b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/_main.c index bd238ac55f..b49d5c50ff 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/_main.c +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/_main.c @@ -14,8 +14,8 @@ limitations under the License. ==============================================================================*/ #include -#include "am_mcu_apollo.h" // Defines AM_CMSIS_REGS #include "am_bsp.h" +#include "am_mcu_apollo.h" // Defines AM_CMSIS_REGS #include "am_util.h" //***************************************************************************** @@ -23,101 +23,95 @@ limitations under the License. // The entry point for the application. // //***************************************************************************** -extern int main(int argc, char**argv); - -void DebugLog(const char* s) { am_util_stdio_printf( "%s", s); } -void DebugLogInt32(int32_t i) { am_util_stdio_printf( "%d", i); } -void DebugLogUInt32(uint32_t i) { am_util_stdio_printf( "%d", i); } -void DebugLogHex(uint32_t i) { am_util_stdio_printf( "0x%8x", i); } -void DebugLogFloat(float i) { am_util_stdio_printf( "%f", i); } - -int _main(void) -{ - am_util_id_t sIdDevice; - uint32_t ui32StrBuf; - - // - // Set the clock frequency. - // - am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0); - - // - // Set the default cache configuration - // - am_hal_cachectrl_config(&am_hal_cachectrl_defaults); - am_hal_cachectrl_enable(); - - // - // Configure the board for low power operation. - // - am_bsp_low_power_init(); - - // - // Initialize the printf interface for UART output - // - am_bsp_uart_printf_enable(); - - // - // Print the banner. - // - am_util_stdio_terminal_clear(); - am_util_stdio_printf("Hello World!\n\n"); - - // - // Print the device info. - // - am_util_id_device(&sIdDevice); - am_util_stdio_printf("Vendor Name: %s\n", sIdDevice.pui8VendorName); - am_util_stdio_printf("Device type: %s\n", sIdDevice.pui8DeviceName); - - - am_util_stdio_printf("Qualified: %s\n", - sIdDevice.sMcuCtrlDevice.ui32Qualified ? - "Yes" : "No"); - - am_util_stdio_printf("Device Info:\n" - "\tPart number: 0x%08X\n" - "\tChip ID0: 0x%08X\n" - "\tChip ID1: 0x%08X\n" - "\tRevision: 0x%08X (Rev%c%c)\n", - sIdDevice.sMcuCtrlDevice.ui32ChipPN, - sIdDevice.sMcuCtrlDevice.ui32ChipID0, - sIdDevice.sMcuCtrlDevice.ui32ChipID1, - sIdDevice.sMcuCtrlDevice.ui32ChipRev, - sIdDevice.ui8ChipRevMaj, sIdDevice.ui8ChipRevMin ); - - // - // If not a multiple of 1024 bytes, append a plus sign to the KB. - // - ui32StrBuf = ( sIdDevice.sMcuCtrlDevice.ui32FlashSize % 1024 ) ? '+' : 0; - am_util_stdio_printf("\tFlash size: %7d (%d KB%s)\n", - sIdDevice.sMcuCtrlDevice.ui32FlashSize, - sIdDevice.sMcuCtrlDevice.ui32FlashSize / 1024, - &ui32StrBuf); - - ui32StrBuf = ( sIdDevice.sMcuCtrlDevice.ui32SRAMSize % 1024 ) ? '+' : 0; - am_util_stdio_printf("\tSRAM size: %7d (%d KB%s)\n\n", - sIdDevice.sMcuCtrlDevice.ui32SRAMSize, - sIdDevice.sMcuCtrlDevice.ui32SRAMSize / 1024, - &ui32StrBuf); - - // - // Print the compiler version. - // - am_util_stdio_printf("App Compiler: %s\n", COMPILER_VERSION); +extern int main(int argc, char** argv); + +void DebugLog(const char* s) { am_util_stdio_printf("%s", s); } +void DebugLogInt32(int32_t i) { am_util_stdio_printf("%d", i); } +void DebugLogUInt32(uint32_t i) { am_util_stdio_printf("%d", i); } +void DebugLogHex(uint32_t i) { am_util_stdio_printf("0x%8x", i); } +void DebugLogFloat(float i) { am_util_stdio_printf("%f", i); } + +int _main(void) { + am_util_id_t sIdDevice; + uint32_t ui32StrBuf; + + // + // Set the clock frequency. + // + am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0); + + // + // Set the default cache configuration + // + am_hal_cachectrl_config(&am_hal_cachectrl_defaults); + am_hal_cachectrl_enable(); + + // + // Configure the board for low power operation. + // + am_bsp_low_power_init(); + + // + // Initialize the printf interface for UART output + // + am_bsp_uart_printf_enable(); + + // + // Print the banner. + // + am_util_stdio_terminal_clear(); + am_util_stdio_printf("Hello World!\n\n"); + + // + // Print the device info. + // + am_util_id_device(&sIdDevice); + am_util_stdio_printf("Vendor Name: %s\n", sIdDevice.pui8VendorName); + am_util_stdio_printf("Device type: %s\n", sIdDevice.pui8DeviceName); + + am_util_stdio_printf("Qualified: %s\n", + sIdDevice.sMcuCtrlDevice.ui32Qualified ? "Yes" : "No"); + + am_util_stdio_printf( + "Device Info:\n" + "\tPart number: 0x%08X\n" + "\tChip ID0: 0x%08X\n" + "\tChip ID1: 0x%08X\n" + "\tRevision: 0x%08X (Rev%c%c)\n", + sIdDevice.sMcuCtrlDevice.ui32ChipPN, sIdDevice.sMcuCtrlDevice.ui32ChipID0, + sIdDevice.sMcuCtrlDevice.ui32ChipID1, + sIdDevice.sMcuCtrlDevice.ui32ChipRev, sIdDevice.ui8ChipRevMaj, + sIdDevice.ui8ChipRevMin); + + // + // If not a multiple of 1024 bytes, append a plus sign to the KB. + // + ui32StrBuf = (sIdDevice.sMcuCtrlDevice.ui32FlashSize % 1024) ? '+' : 0; + am_util_stdio_printf( + "\tFlash size: %7d (%d KB%s)\n", sIdDevice.sMcuCtrlDevice.ui32FlashSize, + sIdDevice.sMcuCtrlDevice.ui32FlashSize / 1024, &ui32StrBuf); + + ui32StrBuf = (sIdDevice.sMcuCtrlDevice.ui32SRAMSize % 1024) ? '+' : 0; + am_util_stdio_printf( + "\tSRAM size: %7d (%d KB%s)\n\n", sIdDevice.sMcuCtrlDevice.ui32SRAMSize, + sIdDevice.sMcuCtrlDevice.ui32SRAMSize / 1024, &ui32StrBuf); + + // + // Print the compiler version. + // + am_util_stdio_printf("App Compiler: %s\n", COMPILER_VERSION); #ifdef AM_PART_APOLLO3 - am_util_stdio_printf("HAL Compiler: %s\n", g_ui8HALcompiler); - am_util_stdio_printf("HAL SDK version: %d.%d.%d\n", - g_ui32HALversion.s.Major, - g_ui32HALversion.s.Minor, - g_ui32HALversion.s.Revision); - am_util_stdio_printf("HAL compiled with %s-style registers\n", - g_ui32HALversion.s.bAMREGS ? "AM_REG" : "CMSIS"); - - am_util_stdio_printf("&sIdDevice: 0x%x, &ui32StrBuf: 0x%x\n", &sIdDevice, &ui32StrBuf); - am_hal_security_info_t secInfo; - char sINFO[32]; - uint32_t ui32Status; -#endif // AM_PART_APOLLO3 - main(0, NULL); + am_util_stdio_printf("HAL Compiler: %s\n", g_ui8HALcompiler); + am_util_stdio_printf("HAL SDK version: %d.%d.%d\n", g_ui32HALversion.s.Major, + g_ui32HALversion.s.Minor, g_ui32HALversion.s.Revision); + am_util_stdio_printf("HAL compiled with %s-style registers\n", + g_ui32HALversion.s.bAMREGS ? "AM_REG" : "CMSIS"); + + am_util_stdio_printf("&sIdDevice: 0x%x, &ui32StrBuf: 0x%x\n", &sIdDevice, + &ui32StrBuf); + am_hal_security_info_t secInfo; + char sINFO[32]; + uint32_t ui32Status; +#endif // AM_PART_APOLLO3 + main(0, NULL); } diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c index d06c81be66..afee38343b 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_main.c @@ -16,8 +16,8 @@ limitations under the License. /* This file is a modification of the Tensorflow Micro Lite file _main.c */ #include -#include "am_mcu_apollo.h" // Defines AM_CMSIS_REGS #include "am_bsp.h" +#include "am_mcu_apollo.h" // Defines AM_CMSIS_REGS #include "am_util.h" #define ARM_MATH_CM4 @@ -25,12 +25,12 @@ limitations under the License. //***************************************************************************** // Parameters -// +// // Total number of bytes transferred = 320*50*2 = 32000 //***************************************************************************** -#define FRAME_SIZE 320 // Capture one 320-sample (20-ms) frame at a time -#define NUM_FRAMES 50 // Number of frames in 1 second +#define FRAME_SIZE 320 // Capture one 320-sample (20-ms) frame at a time +#define NUM_FRAMES 50 // Number of frames in 1 second //***************************************************************************** // GLOBALS @@ -38,53 +38,51 @@ limitations under the License. volatile int16_t g_numFramesCaptured = 0; volatile bool g_bPDMDataReady = false; -int16_t captured_data[FRAME_SIZE*NUM_FRAMES]; // Location of 1-second data buffer +int16_t + captured_data[FRAME_SIZE * NUM_FRAMES]; // Location of 1-second data buffer extern uint8_t g_silence_score; extern uint8_t g_unknown_score; extern uint8_t g_yes_score; extern uint8_t g_no_score; q7_t g_scores[4] = {0}; - //***************************************************************************** // The entry point for the application. //***************************************************************************** -extern int main(int argc, char**argv); +extern int main(int argc, char** argv); -void DebugLog(const char* s) { am_util_stdio_printf( "%s", s); } -void DebugLogInt32(int32_t i) { am_util_stdio_printf( "%d", i); } -void DebugLogUInt32(uint32_t i) { am_util_stdio_printf( "%d", i); } -void DebugLogHex(uint32_t i) { am_util_stdio_printf( "0x%8x", i); } -void DebugLogFloat(float i) { am_util_stdio_printf( "%f", i); } +void DebugLog(const char* s) { am_util_stdio_printf("%s", s); } +void DebugLogInt32(int32_t i) { am_util_stdio_printf("%d", i); } +void DebugLogUInt32(uint32_t i) { am_util_stdio_printf("%d", i); } +void DebugLogHex(uint32_t i) { am_util_stdio_printf("0x%8x", i); } +void DebugLogFloat(float i) { am_util_stdio_printf("%f", i); } //***************************************************************************** // PDM configuration information. //***************************************************************************** -void *PDMHandle; - -am_hal_pdm_config_t g_sPdmConfig = -{ - .eClkDivider = AM_HAL_PDM_MCLKDIV_1, - .eLeftGain = AM_HAL_PDM_GAIN_P225DB, - .eRightGain = AM_HAL_PDM_GAIN_P225DB, - .ui32DecimationRate = 48, // OSR = 1500/16 = 96 = 2*SINCRATE --> SINC_RATE = 48 - .bHighPassEnable = 0, - .ui32HighPassCutoff = 0xB, - .ePDMClkSpeed = AM_HAL_PDM_CLK_1_5MHZ, - .bInvertI2SBCLK = 0, - .ePDMClkSource = AM_HAL_PDM_INTERNAL_CLK, - .bPDMSampleDelay = 0, - .bDataPacking = 1, - .ePCMChannels = AM_HAL_PDM_CHANNEL_RIGHT, - .bLRSwap = 0, +void* PDMHandle; + +am_hal_pdm_config_t g_sPdmConfig = { + .eClkDivider = AM_HAL_PDM_MCLKDIV_1, + .eLeftGain = AM_HAL_PDM_GAIN_P225DB, + .eRightGain = AM_HAL_PDM_GAIN_P225DB, + .ui32DecimationRate = + 48, // OSR = 1500/16 = 96 = 2*SINCRATE --> SINC_RATE = 48 + .bHighPassEnable = 0, + .ui32HighPassCutoff = 0xB, + .ePDMClkSpeed = AM_HAL_PDM_CLK_1_5MHZ, + .bInvertI2SBCLK = 0, + .ePDMClkSource = AM_HAL_PDM_INTERNAL_CLK, + .bPDMSampleDelay = 0, + .bDataPacking = 1, + .ePCMChannels = AM_HAL_PDM_CHANNEL_RIGHT, + .bLRSwap = 0, }; - //***************************************************************************** // BUTTON0 pin configuration settings. //***************************************************************************** -const am_hal_gpio_pincfg_t g_deepsleep_button0 = -{ +const am_hal_gpio_pincfg_t g_deepsleep_button0 = { .uFuncSel = 3, .eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI, .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE, @@ -93,46 +91,44 @@ const am_hal_gpio_pincfg_t g_deepsleep_button0 = //***************************************************************************** // PDM initialization. //***************************************************************************** -void pdm_init(void) -{ - // - // Initialize, power-up, and configure the PDM. - // - am_hal_pdm_initialize(0, &PDMHandle); - am_hal_pdm_power_control(PDMHandle, AM_HAL_PDM_POWER_ON, false); - am_hal_pdm_configure(PDMHandle, &g_sPdmConfig); - am_hal_pdm_enable(PDMHandle); - - // - // Configure the necessary pins. - // - am_hal_gpio_pincfg_t sPinCfg = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -// ARPIT 181019 - //sPinCfg.uFuncSel = AM_HAL_PIN_10_PDMCLK; - //am_hal_gpio_pinconfig(10, sPinCfg); - sPinCfg.uFuncSel = AM_HAL_PIN_12_PDMCLK; - am_hal_gpio_pinconfig(12, sPinCfg); - - sPinCfg.uFuncSel = AM_HAL_PIN_11_PDMDATA; - am_hal_gpio_pinconfig(11, sPinCfg); - - //am_hal_gpio_state_write(14, AM_HAL_GPIO_OUTPUT_CLEAR); - //am_hal_gpio_pinconfig(14, g_AM_HAL_GPIO_OUTPUT); - - // - // Configure and enable PDM interrupts (set up to trigger on DMA - // completion). - // - am_hal_pdm_interrupt_enable(PDMHandle, (AM_HAL_PDM_INT_DERR - | AM_HAL_PDM_INT_DCMP - | AM_HAL_PDM_INT_UNDFL - | AM_HAL_PDM_INT_OVF)); +void pdm_init(void) { + // + // Initialize, power-up, and configure the PDM. + // + am_hal_pdm_initialize(0, &PDMHandle); + am_hal_pdm_power_control(PDMHandle, AM_HAL_PDM_POWER_ON, false); + am_hal_pdm_configure(PDMHandle, &g_sPdmConfig); + am_hal_pdm_enable(PDMHandle); + + // + // Configure the necessary pins. + // + am_hal_gpio_pincfg_t sPinCfg = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + // ARPIT 181019 + // sPinCfg.uFuncSel = AM_HAL_PIN_10_PDMCLK; + // am_hal_gpio_pinconfig(10, sPinCfg); + sPinCfg.uFuncSel = AM_HAL_PIN_12_PDMCLK; + am_hal_gpio_pinconfig(12, sPinCfg); + + sPinCfg.uFuncSel = AM_HAL_PIN_11_PDMDATA; + am_hal_gpio_pinconfig(11, sPinCfg); + + // am_hal_gpio_state_write(14, AM_HAL_GPIO_OUTPUT_CLEAR); + // am_hal_gpio_pinconfig(14, g_AM_HAL_GPIO_OUTPUT); + + // + // Configure and enable PDM interrupts (set up to trigger on DMA + // completion). + // + am_hal_pdm_interrupt_enable(PDMHandle, + (AM_HAL_PDM_INT_DERR | AM_HAL_PDM_INT_DCMP | + AM_HAL_PDM_INT_UNDFL | AM_HAL_PDM_INT_OVF)); #if AM_CMSIS_REGS - NVIC_EnableIRQ(PDM_IRQn); + NVIC_EnableIRQ(PDM_IRQn); #else - am_hal_interrupt_enable(AM_HAL_INTERRUPT_PDM); + am_hal_interrupt_enable(AM_HAL_INTERRUPT_PDM); #endif } @@ -141,196 +137,186 @@ void pdm_init(void) // Start a transaction to get some number of bytes from the PDM interface. // //***************************************************************************** -void pdm_data_get(void) -{ - // - // Configure DMA and target address. - // - am_hal_pdm_transfer_t sTransfer; - sTransfer.ui32TargetAddr = (uint32_t ) (&captured_data[FRAME_SIZE*g_numFramesCaptured]); - sTransfer.ui32TotalCount = 2*FRAME_SIZE; // Each sample is 2 bytes - - // - // Start the data transfer. - // - am_hal_pdm_dma_start(PDMHandle, &sTransfer); +void pdm_data_get(void) { + // + // Configure DMA and target address. + // + am_hal_pdm_transfer_t sTransfer; + sTransfer.ui32TargetAddr = + (uint32_t)(&captured_data[FRAME_SIZE * g_numFramesCaptured]); + sTransfer.ui32TotalCount = 2 * FRAME_SIZE; // Each sample is 2 bytes + + // + // Start the data transfer. + // + am_hal_pdm_dma_start(PDMHandle, &sTransfer); } - //***************************************************************************** // // PDM interrupt handler. // //***************************************************************************** -void am_pdm_isr(void) -{ - uint32_t ui32Status; - // - // Read the interrupt status. - // - am_hal_pdm_interrupt_status_get(PDMHandle, &ui32Status, true); - am_hal_pdm_interrupt_clear(PDMHandle, ui32Status); - - // - // Once our DMA transaction completes, send a flag to the main routine - // - if (ui32Status & AM_HAL_PDM_INT_DCMP) - g_bPDMDataReady = true; +void am_pdm_isr(void) { + uint32_t ui32Status; + // + // Read the interrupt status. + // + am_hal_pdm_interrupt_status_get(PDMHandle, &ui32Status, true); + am_hal_pdm_interrupt_clear(PDMHandle, ui32Status); + + // + // Once our DMA transaction completes, send a flag to the main routine + // + if (ui32Status & AM_HAL_PDM_INT_DCMP) g_bPDMDataReady = true; } - //***************************************************************************** // GPIO ISR // Will enable the PDM, set number of frames transferred to 0, and turn on LED //***************************************************************************** -void -am_gpio_isr(void) -{ - // - // Delay for debounce. - // - am_util_delay_ms(200); - - // - // Clear the GPIO Interrupt (write to clear). - // - am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); - - // Start audio transfer - am_hal_pdm_fifo_flush(PDMHandle); - pdm_data_get(); - am_hal_pdm_enable(PDMHandle); - - // - // Turn on LED 0 - // - am_devices_led_on(am_bsp_psLEDs, 0); +void am_gpio_isr(void) { + // + // Delay for debounce. + // + am_util_delay_ms(200); + + // + // Clear the GPIO Interrupt (write to clear). + // + am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); + + // Start audio transfer + am_hal_pdm_fifo_flush(PDMHandle); + pdm_data_get(); + am_hal_pdm_enable(PDMHandle); + + // + // Turn on LED 0 + // + am_devices_led_on(am_bsp_psLEDs, 0); } -int _main(void) -{ - am_util_id_t sIdDevice; - uint32_t ui32StrBuf; - - // - // Set the clock frequency. - // - am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0); - - // - // Set the default cache configuration - // - am_hal_cachectrl_config(&am_hal_cachectrl_defaults); - am_hal_cachectrl_enable(); - - // - // Configure the board for low power operation. - // - am_bsp_low_power_init(); - - -#if defined(AM_BSP_NUM_BUTTONS) && defined(AM_BSP_NUM_LEDS) - // - // Configure the button pin. - // - am_hal_gpio_pinconfig(AM_BSP_GPIO_BUTTON0, g_deepsleep_button0); - - // - // Clear the GPIO Interrupt (write to clear). - // - am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); - - // - // Enable the GPIO/button interrupt. - // - am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); - - // - // Configure the LEDs. - // - am_devices_led_array_init(am_bsp_psLEDs, AM_BSP_NUM_LEDS); - - // - // Turn the LEDs off - // - for (int ix = 0; ix < AM_BSP_NUM_LEDS; ix++) - { - am_devices_led_off(am_bsp_psLEDs, ix); - } +int _main(void) { + am_util_id_t sIdDevice; + uint32_t ui32StrBuf; + + // + // Set the clock frequency. + // + am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0); + + // + // Set the default cache configuration + // + am_hal_cachectrl_config(&am_hal_cachectrl_defaults); + am_hal_cachectrl_enable(); + + // + // Configure the board for low power operation. + // + am_bsp_low_power_init(); + +#if defined(AM_BSP_NUM_BUTTONS) && defined(AM_BSP_NUM_LEDS) + // + // Configure the button pin. + // + am_hal_gpio_pinconfig(AM_BSP_GPIO_BUTTON0, g_deepsleep_button0); + + // + // Clear the GPIO Interrupt (write to clear). + // + am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); + + // + // Enable the GPIO/button interrupt. + // + am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(AM_BSP_GPIO_BUTTON0)); + + // + // Configure the LEDs. + // + am_devices_led_array_init(am_bsp_psLEDs, AM_BSP_NUM_LEDS); + + // + // Turn the LEDs off + // + for (int ix = 0; ix < AM_BSP_NUM_LEDS; ix++) { + am_devices_led_off(am_bsp_psLEDs, ix); + } // am_devices_led_on(am_bsp_psLEDs, 1); -#endif // defined(AM_BSP_NUM_BUTTONS) && defined(AM_BSP_NUM_LEDS) +#endif // defined(AM_BSP_NUM_BUTTONS) && defined(AM_BSP_NUM_LEDS) #if AM_CMSIS_REGS - NVIC_EnableIRQ(GPIO_IRQn); -#else // AM_CMSIS_REGS - am_hal_interrupt_enable(AM_HAL_INTERRUPT_GPIO); -#endif // AM_CMSIS_REGS - - // - // Enable interrupts to the core. - // - am_hal_interrupt_master_enable(); - - // Turn on PDM - pdm_init(); - - // - // Initialize the printf interface for UART output - // - am_bsp_uart_printf_enable(); + NVIC_EnableIRQ(GPIO_IRQn); +#else // AM_CMSIS_REGS + am_hal_interrupt_enable(AM_HAL_INTERRUPT_GPIO); +#endif // AM_CMSIS_REGS + + // + // Enable interrupts to the core. + // + am_hal_interrupt_master_enable(); + + // Turn on PDM + pdm_init(); + + // + // Initialize the printf interface for UART output + // + am_bsp_uart_printf_enable(); + + // + // Print the banner. + // + am_util_stdio_terminal_clear(); + am_util_stdio_printf("Starting streaming test\n\n"); + + // Score variables + q7_t max_score = 0; + uint32_t max_score_index = 0; + + while (1) { + am_hal_interrupt_master_disable(); + + if (g_bPDMDataReady) { + g_bPDMDataReady = false; + g_numFramesCaptured++; + + if (g_numFramesCaptured < NUM_FRAMES) { + pdm_data_get(); // Start converting the next set of PCM samples. + } + + else { + g_numFramesCaptured = 0; + // am_hal_pdm_disable(PDMHandle); + am_devices_led_off(am_bsp_psLEDs, 0); + + main(0, NULL); + + g_scores[0] = (q7_t)g_silence_score - 128; + g_scores[1] = (q7_t)g_unknown_score - 128; + g_scores[2] = (q7_t)g_yes_score - 128; + g_scores[3] = (q7_t)g_no_score - 128; + + am_devices_led_off( + am_bsp_psLEDs, + max_score_index + 1); // Turn off LED for previous max score + arm_max_q7(g_scores, 4, &max_score, &max_score_index); + am_devices_led_on( + am_bsp_psLEDs, + max_score_index + 1); // Turn on LED for new max score + } + } // - // Print the banner. + // Go to Deep Sleep. // - am_util_stdio_terminal_clear(); - am_util_stdio_printf("Starting streaming test\n\n"); - - // Score variables - q7_t max_score = 0; - uint32_t max_score_index = 0; - - while(1) - { - - am_hal_interrupt_master_disable(); - - if (g_bPDMDataReady) - { - g_bPDMDataReady = false; - g_numFramesCaptured++; - - if (g_numFramesCaptured < NUM_FRAMES) { - pdm_data_get(); // Start converting the next set of PCM samples. - } - - else - { - g_numFramesCaptured = 0; - //am_hal_pdm_disable(PDMHandle); - am_devices_led_off(am_bsp_psLEDs, 0); + am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); - main(0, NULL); - - g_scores[0] = (q7_t) g_silence_score - 128; - g_scores[1] = (q7_t) g_unknown_score - 128; - g_scores[2] = (q7_t) g_yes_score - 128; - g_scores[3] = (q7_t) g_no_score - 128; - - am_devices_led_off(am_bsp_psLEDs, max_score_index+1); // Turn off LED for previous max score - arm_max_q7(g_scores, 4, &max_score, &max_score_index); - am_devices_led_on(am_bsp_psLEDs, max_score_index+1); // Turn on LED for new max score - } - } - - // - // Go to Deep Sleep. - // - am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP); - - am_hal_interrupt_master_enable(); - - } + am_hal_interrupt_master_enable(); + } - //main(0, NULL); + // main(0, NULL); } -- GitLab From 75ae007db8a038c926382d7dc982277f474b70bc Mon Sep 17 00:00:00 2001 From: Anna R Date: Thu, 20 Dec 2018 17:02:25 -0800 Subject: [PATCH 0215/1765] Internal change. PiperOrigin-RevId: 226417140 --- tensorflow/python/keras/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow/python/keras/BUILD b/tensorflow/python/keras/BUILD index 9154db8980..dfbb34aea9 100755 --- a/tensorflow/python/keras/BUILD +++ b/tensorflow/python/keras/BUILD @@ -589,6 +589,7 @@ py_test( name = "simplernn_test", size = "medium", srcs = ["layers/simplernn_test.py"], + shard_count = 4, srcs_version = "PY2AND3", tags = ["notsan"], deps = [ -- GitLab From 01b7f2441e7549b97c1a2228bd6f79c6fd61bed2 Mon Sep 17 00:00:00 2001 From: Andrew Selle Date: Thu, 20 Dec 2018 17:22:18 -0800 Subject: [PATCH 0216/1765] Do not run removed tests. PiperOrigin-RevId: 226419504 --- tensorflow/tools/ci_build/builds/test_tutorials.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/tools/ci_build/builds/test_tutorials.sh b/tensorflow/tools/ci_build/builds/test_tutorials.sh index a8672220c8..a12827a2d3 100755 --- a/tensorflow/tools/ci_build/builds/test_tutorials.sh +++ b/tensorflow/tools/ci_build/builds/test_tutorials.sh @@ -33,7 +33,7 @@ # # List of all tutorial tests to run, separated by spaces -TUT_TESTS="mnist_softmax mnist_with_summaries word2vec estimator_abalone" +TUT_TESTS="mnist_with_summaries word2vec" if [[ -z "${TUT_TESTS_BLACKLIST}" ]]; then TF_BUILD_TUT_TEST_BLACKLIST="" -- GitLab From 17fdf8408e7ddfd80a88cd9f883fd911e960e168 Mon Sep 17 00:00:00 2001 From: Martin Wicke Date: Thu, 20 Dec 2018 17:22:45 -0800 Subject: [PATCH 0217/1765] Remove contrib dependencies from core TF. PiperOrigin-RevId: 226419542 --- tensorflow/python/BUILD | 4 ++-- tensorflow/tensorflow.bzl | 12 ++++++++++++ tensorflow/tools/pip_package/BUILD | 13 +++---------- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/tensorflow/python/BUILD b/tensorflow/python/BUILD index da44a41536..7e504ea8e4 100644 --- a/tensorflow/python/BUILD +++ b/tensorflow/python/BUILD @@ -23,6 +23,7 @@ exports_files(["LICENSE"]) exports_files(["platform/base.i"]) +load("//tensorflow:tensorflow.bzl", "if_not_v2") load("//tensorflow:tensorflow.bzl", "if_not_windows") load("//tensorflow:tensorflow.bzl", "tf_cuda_library") load("//tensorflow:tensorflow.bzl", "tf_gen_op_wrapper_py") @@ -69,9 +70,8 @@ py_library( ], deps = [ ":no_contrib", - "//tensorflow/contrib:contrib_py", "//tensorflow/python/estimator:estimator_py", - ], + ] + if_not_v2(["//tensorflow/contrib:contrib_py"]), ) py_library( diff --git a/tensorflow/tensorflow.bzl b/tensorflow/tensorflow.bzl index d93e0df5e4..fbdfa2cf6d 100644 --- a/tensorflow/tensorflow.bzl +++ b/tensorflow/tensorflow.bzl @@ -47,6 +47,18 @@ load( def register_extension_info(**kwargs): pass +def if_v2(a): + return select({ + clean_dep("//tensorflow:api_version_2"): a, + "//conditions:default": [], + }) + +def if_not_v2(a): + return select({ + clean_dep("//tensorflow:api_version_2"): [], + "//conditions:default": a, + }) + # if_cuda_is_configured def placeholder def if_cuda_is_configured_compat(x): diff --git a/tensorflow/tools/pip_package/BUILD b/tensorflow/tools/pip_package/BUILD index 2de00ea957..93a85763f5 100644 --- a/tensorflow/tools/pip_package/BUILD +++ b/tensorflow/tools/pip_package/BUILD @@ -18,13 +18,6 @@ load( "if_ngraph", ) -# This flag specifies whether TensorFlow 2.0 API should be built instead -# of 1.* API. Note that TensorFlow 2.0 API is currently under development. -config_setting( - name = "api_version_2", - define_values = {"tf_api_version": "2"}, -) - # This returns a list of headers of all public header libraries (e.g., # framework, lib), and all of the transitive dependencies of those # public headers. Not all of the headers returned by the filegroup @@ -66,7 +59,6 @@ COMMON_PIP_DEPS = [ "setup.py", ":included_headers", "//tensorflow:tensorflow_py", - "//tensorflow/examples/tutorials/mnist:package", "//tensorflow/lite/python:interpreter_test_data", "//tensorflow/lite/python:tflite_convert", "//tensorflow/lite/toco/python:toco_from_protos", @@ -130,6 +122,7 @@ COMMON_PIP_DEPS_V1 = COMMON_PIP_DEPS + [ "//tensorflow/contrib/tensor_forest/hybrid:hybrid_pip", "//tensorflow/contrib/timeseries:timeseries_pip", "//tensorflow/contrib/tpu", + "//tensorflow/examples/tutorials/mnist:package", ] # On Windows, python binary is a zip file of runfiles tree. @@ -139,8 +132,8 @@ py_binary( name = "simple_console_for_windows", srcs = ["simple_console_for_windows.py"], data = select({ - "api_version_2": COMMON_PIP_DEPS, "//conditions:default": COMMON_PIP_DEPS_V1, + "//tensorflow:api_version_2": COMMON_PIP_DEPS, }) + ["//tensorflow/python:pywrap_tensorflow_import_lib_file"], srcs_version = "PY2AND3", deps = ["//tensorflow:tensorflow_py"], @@ -242,7 +235,7 @@ sh_binary( name = "build_pip_package", srcs = ["build_pip_package.sh"], data = select({ - "api_version_2": COMMON_PIP_DEPS, + "//tensorflow:api_version_2": COMMON_PIP_DEPS, "//conditions:default": COMMON_PIP_DEPS_V1, }) + select({ -- GitLab From 835909603bc992f1221faf3546d67093c76d92b7 Mon Sep 17 00:00:00 2001 From: Nupur Garg Date: Thu, 20 Dec 2018 17:29:36 -0800 Subject: [PATCH 0218/1765] Adds ability to cancel a call to Invoke() to the TFLite interpreter. PiperOrigin-RevId: 226420241 --- tensorflow/lite/core/subgraph.cc | 12 +++ tensorflow/lite/core/subgraph.h | 18 ++++ tensorflow/lite/interpreter.cc | 9 ++ tensorflow/lite/interpreter.h | 9 ++ tensorflow/lite/interpreter_test.cc | 124 ++++++++++++++++++++++++++++ 5 files changed, 172 insertions(+) diff --git a/tensorflow/lite/core/subgraph.cc b/tensorflow/lite/core/subgraph.cc index 763ab56575..75212cac22 100644 --- a/tensorflow/lite/core/subgraph.cc +++ b/tensorflow/lite/core/subgraph.cc @@ -363,6 +363,12 @@ TfLiteStatus Subgraph::SetVariables(std::vector variables) { return kTfLiteOk; } +void Subgraph::SetCancellationFunction(void* data, + bool (*check_cancelled_func)(void*)) { + cancellation_data_ = data; + check_cancelled_func_ = check_cancelled_func; +} + TfLiteStatus Subgraph::CheckTensorIndices(const char* label, const int* indices, int length) { // Making sure kOptionalTensor is not re-defined to something other than -1. @@ -668,6 +674,12 @@ TfLiteStatus Subgraph::Invoke() { } } + if (check_cancelled_func_ != nullptr && + check_cancelled_func_(cancellation_data_)) { + ReportError("Client requested cancel during Invoke()"); + return kTfLiteError; + } + EnsureTensorsVectorCapacity(); tensor_resized_since_op_invoke_ = false; if (OpInvoke(registration, &node) == kTfLiteError) { diff --git a/tensorflow/lite/core/subgraph.h b/tensorflow/lite/core/subgraph.h index 979226b864..0bec218d89 100644 --- a/tensorflow/lite/core/subgraph.h +++ b/tensorflow/lite/core/subgraph.h @@ -208,6 +208,15 @@ class Subgraph { return context_->allow_fp32_relax_to_fp16; } + // Sets the cancellation function pointer in order to cancel a request in the + // middle of a call to Invoke(). The interpreter queries this function during + // inference, between op invocations; when it returns true, the interpreter + // will abort execution and return `kTfLiteError`. The `data` parameter + // contains any data used by the cancellation function, and if non-null, + // remains owned by the caller. + // WARNING: This is an experimental API and subject to change. + void SetCancellationFunction(void* data, bool (*check_cancelled_func)(void*)); + // Ensure the data in `tensor.data` is readable. In case delegate is used, // it might require to copy the data from delegate buffer to raw memory. // WARNING: This is an experimental API and subject to change. @@ -502,6 +511,15 @@ class Subgraph { // public function). // The value is invalid before `PrepareOpStartingAt` is called. bool has_dynamic_tensors_ = true; + + // Reference to cancellation function that can cancel a request in the middle + // of a call to Invoke(). When this function returns True, a kTfLiteError is + // thrown by Invoke(). + bool (*check_cancelled_func_)(void*) = nullptr; + + // Reference to data used by the cancellation function in + // `check_cancelled_func_`. + void* cancellation_data_ = nullptr; }; } // namespace tflite diff --git a/tensorflow/lite/interpreter.cc b/tensorflow/lite/interpreter.cc index e2129ed46d..2abe062ec6 100644 --- a/tensorflow/lite/interpreter.cc +++ b/tensorflow/lite/interpreter.cc @@ -167,6 +167,15 @@ void Interpreter::SetAllowFp16PrecisionForFp32(bool allow) { } } +// TODO(b/121264966): Subgraphs added after cancellation is set will not get the +// cancellation function added to their context. +void Interpreter::SetCancellationFunction(void* data, + bool (*check_cancelled_func)(void*)) { + for (auto& subgraph : subgraphs_) { + subgraph->SetCancellationFunction(data, check_cancelled_func); + } +} + TfLiteStatus Interpreter::ModifyGraphWithDelegate(TfLiteDelegate* delegate) { return primary_subgraph().ModifyGraphWithDelegate(delegate); } diff --git a/tensorflow/lite/interpreter.h b/tensorflow/lite/interpreter.h index 6192d56ca2..754439c966 100644 --- a/tensorflow/lite/interpreter.h +++ b/tensorflow/lite/interpreter.h @@ -343,6 +343,15 @@ class Interpreter { return context_->allow_fp32_relax_to_fp16; } + // Sets the cancellation function pointer in order to cancel a request in the + // middle of a call to Invoke(). The interpreter queries this function during + // inference, between op invocations; when it returns true, the interpreter + // will abort execution and return `kTfLiteError`. The `data` parameter + // contains any data used by the cancellation function, and if non-null, + // remains owned by the caller. + // WARNING: This is an experimental API and subject to change. + void SetCancellationFunction(void* data, bool (*check_cancelled_func)(void*)); + // Owning handle to a TfLiteDelegate instance. using TfLiteDelegatePtr = std::unique_ptr; diff --git a/tensorflow/lite/interpreter_test.cc b/tensorflow/lite/interpreter_test.cc index 40e5134bc7..1ee993c6f9 100644 --- a/tensorflow/lite/interpreter_test.cc +++ b/tensorflow/lite/interpreter_test.cc @@ -1396,6 +1396,130 @@ TEST(TestDelegateOwnership, ProperlyDisposed) { EXPECT_TRUE(destroyed); } +// CancellationData contains the data required to cancel a call to Invoke(). +struct CancellationData { + bool is_cancelled = false; +}; + +// Indicates whether Invoke() has been cancelled based on the value of the +// CancellationData object passed in. +bool CheckCancellation(void* data) { + CancellationData* cancellation_data = + static_cast(data); + return cancellation_data->is_cancelled; +} + +static struct CancellationData cancellation_data_; + +// Test fixture to test cancellation within the Interpreter. +class CancellationTest : public ::testing::Test { + public: + TfLiteStatus Invoke() { return interpreter_.Invoke(); } + void Cancel() { cancellation_data_.is_cancelled = true; } + + // Adds an CancelOp with input tensor `input` and output tensor `output`. + void MakeCancelNode(int input, int output) { + TfLiteRegistration op = CancelOpRegistration(); + ASSERT_EQ(interpreter_.AddNodeWithParameters({input}, {output}, nullptr, 0, + nullptr, &op), + kTfLiteOk); + ASSERT_EQ(interpreter_.ResizeInputTensor(input, {3}), kTfLiteOk); + } + + // Adds an OkOp with input tensor `input` and output tensor `output`. + void MakeOkNode(int input, int output) { + TfLiteRegistration op = OkOpRegistration(); + ASSERT_EQ(interpreter_.AddNodeWithParameters({input}, {output}, nullptr, 0, + nullptr, &op), + kTfLiteOk); + ASSERT_EQ(interpreter_.ResizeInputTensor(input, {3}), kTfLiteOk); + } + + Interpreter interpreter_; + + private: + // Build the kernel registration for an op that cancels the operation. + TfLiteRegistration CancelOpRegistration() { + TfLiteRegistration reg = {nullptr, nullptr, nullptr, nullptr}; + + // Set output size to the input size in CancelOp::Prepare(). Code exists to + // have a framework in Prepare. The input and output tensors are not used. + reg.prepare = [](TfLiteContext* context, TfLiteNode* node) { + TfLiteTensor* in_tensor = &context->tensors[node->inputs->data[0]]; + TfLiteTensor* out_tensor = &context->tensors[node->outputs->data[0]]; + TfLiteIntArray* new_size = TfLiteIntArrayCopy(in_tensor->dims); + return context->ResizeTensor(context, out_tensor, new_size); + }; + + reg.invoke = [](TfLiteContext* context, TfLiteNode* node) { + cancellation_data_.is_cancelled = true; + return kTfLiteOk; + }; + return reg; + } + + // Build the kernel registration for an op that returns kTfLiteOk. + TfLiteRegistration OkOpRegistration() { + TfLiteRegistration reg = {nullptr, nullptr, nullptr, nullptr}; + + // Set output size to the input size in OkOp::Prepare(). Code exists to have + // a framework in Prepare. The input and output tensors are not used. + reg.prepare = [](TfLiteContext* context, TfLiteNode* node) { + TfLiteTensor* in_tensor = &context->tensors[node->inputs->data[0]]; + TfLiteTensor* out_tensor = &context->tensors[node->outputs->data[0]]; + TfLiteIntArray* new_size = TfLiteIntArrayCopy(in_tensor->dims); + return context->ResizeTensor(context, out_tensor, new_size); + }; + + reg.invoke = [](TfLiteContext* context, TfLiteNode* node) { + return kTfLiteOk; + }; + return reg; + } + + void SetUp() final { + cancellation_data_.is_cancelled = false; + + // Set up the interpreter. Create the input and output tensors. + int num_tensors = 3; + ASSERT_EQ(interpreter_.AddTensors(num_tensors), kTfLiteOk); + interpreter_.SetInputs({0}); + interpreter_.SetOutputs({2}); + TfLiteQuantizationParams quantized; + for (int tensor_index = 0; tensor_index < num_tensors; tensor_index++) { + ASSERT_EQ(interpreter_.SetTensorParametersReadWrite( + tensor_index, kTfLiteFloat32, "", {3}, quantized), + kTfLiteOk); + } + interpreter_.SetCancellationFunction(&cancellation_data_, + &CheckCancellation); + } +}; + +TEST_F(CancellationTest, CancelBeforeInvoke) { + // Cancel prior to calling Invoke. + CancellationTest::MakeOkNode(1, 2); + ASSERT_EQ(interpreter_.AllocateTensors(), kTfLiteOk); + + CancellationTest::Cancel(); + TfLiteStatus invoke_error_code = CancellationTest::Invoke(); + ASSERT_EQ(invoke_error_code, kTfLiteError); +} + +TEST_F(CancellationTest, CancelDuringInvoke) { + // Tests a model which sets the cancel in order to test cancellation works + // between ops. + // + // The first op will set the cancellation bit to true. The second op returns + // `kTfLiteOk` if executed. + CancellationTest::MakeCancelNode(0, 1); + CancellationTest::MakeOkNode(1, 2); + ASSERT_EQ(interpreter_.AllocateTensors(), kTfLiteOk); + + TfLiteStatus invoke_error_code = CancellationTest::Invoke(); + ASSERT_EQ(invoke_error_code, kTfLiteError); +} + } // namespace } // namespace tflite -- GitLab From e7ad1cd7d119ef1705d647bda5bb9dcdb1455fdc Mon Sep 17 00:00:00 2001 From: Andrew Selle Date: Thu, 20 Dec 2018 17:45:52 -0800 Subject: [PATCH 0219/1765] Make estimator part of pip install PiperOrigin-RevId: 226422176 --- .../tools/ci_build/install/install_python3.5_pip_packages.sh | 3 +++ .../tools/ci_build/install/install_python3.6_pip_packages.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tensorflow/tools/ci_build/install/install_python3.5_pip_packages.sh b/tensorflow/tools/ci_build/install/install_python3.5_pip_packages.sh index 62e04df717..0654fb81b3 100755 --- a/tensorflow/tools/ci_build/install/install_python3.5_pip_packages.sh +++ b/tensorflow/tools/ci_build/install/install_python3.5_pip_packages.sh @@ -90,4 +90,7 @@ pip3.5 install keras_applications==1.0.6 pip3.5 install keras_preprocessing==1.0.5 pip3.5 install --upgrade h5py==2.8.0 +# Estimator +pip3.5 install tf-estimator-nightly==1.12.0.dev20181203 --no-deps + # LINT.ThenChange(//tensorflow/tools/ci_build/install/install_python3.6_pip_packages.sh) diff --git a/tensorflow/tools/ci_build/install/install_python3.6_pip_packages.sh b/tensorflow/tools/ci_build/install/install_python3.6_pip_packages.sh index 48d556b1dd..3edf4571fb 100755 --- a/tensorflow/tools/ci_build/install/install_python3.6_pip_packages.sh +++ b/tensorflow/tools/ci_build/install/install_python3.6_pip_packages.sh @@ -107,4 +107,7 @@ pip3 install --upgrade h5py==2.8.0 pip3 install keras_applications==1.0.6 pip3 install keras_preprocessing==1.0.5 +# Estimator +pip3 install tf-estimator-nightly==1.12.0.dev20181203 --no-deps + # LINT.ThenChange(//tensorflow/tools/ci_build/install/install_python3.5_pip_packages.sh) -- GitLab From 5e537a4d7c100915a33eff43441112bc4f657070 Mon Sep 17 00:00:00 2001 From: Paul Donnelly Date: Thu, 20 Dec 2018 17:49:02 -0800 Subject: [PATCH 0220/1765] Add qint8 support to ConcatV2 on the GPU (assumes an int8x4 format). PiperOrigin-RevId: 226422516 --- tensorflow/core/kernels/concat_lib_gpu.cc | 17 ++++++++++++++++- .../core/kernels/concat_lib_gpu_impl.cu.cc | 2 ++ tensorflow/core/kernels/concat_op.cc | 10 ++++++++++ .../python/kernel_tests/concat_op_test.py | 12 ++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/tensorflow/core/kernels/concat_lib_gpu.cc b/tensorflow/core/kernels/concat_lib_gpu.cc index 93e392d303..56b9e7b674 100644 --- a/tensorflow/core/kernels/concat_lib_gpu.cc +++ b/tensorflow/core/kernels/concat_lib_gpu.cc @@ -87,7 +87,21 @@ void ConcatGPU( const std::vector::ConstMatrix>>& inputs_flat, Tensor* output, typename TTypes::Tensor* output_flat) { - if (inputs_flat.size() < 16) { + if (std::is_same::value) { + std::vector::ConstMatrix>> + inputs_as_int32(inputs_flat.size()); + for (int i = 0; i < inputs_flat.size(); ++i) { + auto& input = *inputs_flat[i]; + inputs_as_int32[i].reset(new typename TTypes::ConstMatrix( + reinterpret_cast(input.data()), input.dimension(0), + input.dimension(1) >> 2)); + } + typename TTypes::Matrix output_as_int32( + reinterpret_cast(output_flat->data()), + output_flat->dimension(0), output_flat->dimension(1) >> 2); + ConcatGPUSlice(c->eigen_gpu_device(), inputs_as_int32, + &output_as_int32); + } else if (inputs_flat.size() < 16) { if (output->NumElements() < std::numeric_limits::max()) { ConcatGPUSlice(c->eigen_gpu_device(), inputs_flat, output_flat); } else { @@ -119,6 +133,7 @@ TF_CALL_int64(REGISTER); TF_CALL_bfloat16(REGISTER); TF_CALL_bool(REGISTER); TF_CALL_uint8(REGISTER); +TF_CALL_qint8(REGISTER); #undef REGISTER diff --git a/tensorflow/core/kernels/concat_lib_gpu_impl.cu.cc b/tensorflow/core/kernels/concat_lib_gpu_impl.cu.cc index a561d918bd..565ab550a4 100644 --- a/tensorflow/core/kernels/concat_lib_gpu_impl.cu.cc +++ b/tensorflow/core/kernels/concat_lib_gpu_impl.cu.cc @@ -202,6 +202,7 @@ TF_CALL_GPU_NUMBER_TYPES(REGISTER_GPUCONCAT32); TF_CALL_complex64(REGISTER_GPUCONCAT32); TF_CALL_complex128(REGISTER_GPUCONCAT32); TF_CALL_int64(REGISTER_GPUCONCAT32); +TF_CALL_int32(REGISTER_GPUCONCAT32); TF_CALL_uint8(REGISTER_GPUCONCAT32); REGISTER_GPUCONCAT32(bfloat16); REGISTER_GPUCONCAT32(bool); @@ -218,6 +219,7 @@ TF_CALL_GPU_NUMBER_TYPES(REGISTER_GPU32); TF_CALL_complex64(REGISTER_GPU32); TF_CALL_complex128(REGISTER_GPU32); TF_CALL_int64(REGISTER_GPU32); +TF_CALL_int32(REGISTER_GPU32); TF_CALL_uint8(REGISTER_GPU32); REGISTER_GPU32(bfloat16); REGISTER_GPU32(bool); diff --git a/tensorflow/core/kernels/concat_op.cc b/tensorflow/core/kernels/concat_op.cc index ff62983517..6e9057eea5 100644 --- a/tensorflow/core/kernels/concat_op.cc +++ b/tensorflow/core/kernels/concat_op.cc @@ -135,6 +135,15 @@ class ConcatBaseOp : public OpKernel { } if (in.NumElements() > 0) { int64 inputs_flat_dim1 = in.NumElements() / inputs_flat_dim0; + if (std::is_same::value) { + OP_REQUIRES( + c, 0 == inputs_flat_dim1 % 4, + errors::InvalidArgument( + "For qint8, the product of dimensions after the concat axis " + "must be a multiple of 4. Got ", + input_shape, " -> (", inputs_flat_dim0, ", ", + inputs_flat_dim1, ")")); + } inputs_flat.emplace_back(new typename TTypes::ConstMatrix( in.shaped({inputs_flat_dim0, inputs_flat_dim1}))); } @@ -213,6 +222,7 @@ REGISTER_CONCAT(qint32); TF_CALL_GPU_NUMBER_TYPES(REGISTER_GPU); REGISTER_GPU(bfloat16); +REGISTER_GPU(qint8); TF_CALL_uint8(REGISTER_GPU); TF_CALL_complex64(REGISTER_GPU); TF_CALL_complex128(REGISTER_GPU); diff --git a/tensorflow/python/kernel_tests/concat_op_test.py b/tensorflow/python/kernel_tests/concat_op_test.py index 474760a93f..00d876bff5 100644 --- a/tensorflow/python/kernel_tests/concat_op_test.py +++ b/tensorflow/python/kernel_tests/concat_op_test.py @@ -640,6 +640,18 @@ class ConcatOpTest(test.TestCase): output = self.evaluate(c) self.assertAllEqual([[1, 2, 3, 7, 8, 9], [4, 5, 6, 10, 11, 12]], output) + def testConcatQint8GPU(self): + with self.test_session(use_gpu=True): + p1 = np.random.rand(2, 3, 2, 3, 4).astype("i") + p2 = np.random.rand(2, 3, 2, 3, 4).astype("i") + x1 = constant_op.constant(p1, dtypes.qint8) + x2 = constant_op.constant(p2, dtypes.qint8) + c = gen_array_ops.concat_v2([x1, x2], 1) + result = self.evaluate(c) + self.assertAllEqual(result[:, :3, :], p1) + self.assertAllEqual(result[:, 3:, :], p2) + + class ConcatOffsetTest(test.TestCase): def testBasic(self): -- GitLab From c8ccffb3ee132d14784b48e0f9e3a5478ec5dc7a Mon Sep 17 00:00:00 2001 From: Anna R Date: Thu, 20 Dec 2018 17:53:59 -0800 Subject: [PATCH 0221/1765] Fix AutographParseError "the true branch creates saved_hidden, while the false branch creates no variables." failure. PiperOrigin-RevId: 226422956 --- tensorflow/contrib/eager/python/examples/revnet/revnet.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow/contrib/eager/python/examples/revnet/revnet.py b/tensorflow/contrib/eager/python/examples/revnet/revnet.py index 1f2cb14972..7406787ba4 100644 --- a/tensorflow/contrib/eager/python/examples/revnet/revnet.py +++ b/tensorflow/contrib/eager/python/examples/revnet/revnet.py @@ -96,6 +96,7 @@ class RevNet(tf.keras.Model): def call(self, inputs, training=True): """Forward pass.""" + saved_hidden = None if training: saved_hidden = [inputs] -- GitLab From c021fc53415681f071727a7ac87747e3fdf23585 Mon Sep 17 00:00:00 2001 From: Shashi Shekhar Date: Thu, 20 Dec 2018 18:09:27 -0800 Subject: [PATCH 0222/1765] Experimental symmetric quantization library. PiperOrigin-RevId: 226424745 --- .../lite/tools/optimize/quantize_model.cc | 63 ++++ .../lite/tools/optimize/quantize_model.h | 39 ++ .../tools/optimize/quantize_model_test.cc | 150 ++++++++ .../lite/tools/optimize/subgraph_quantizer.cc | 333 ++++++++++++++++++ .../lite/tools/optimize/subgraph_quantizer.h | 53 +++ .../tools/optimize/subgraph_quantizer_test.cc | 258 ++++++++++++++ .../optimize/symmetric_per_channel_params.cc | 86 +++++ .../optimize/symmetric_per_channel_params.h | 58 +++ .../symmetric_per_channel_params_test.cc | 51 +++ tensorflow/lite/tools/optimize/test_util.cc | 36 ++ tensorflow/lite/tools/optimize/test_util.h | 46 +++ 11 files changed, 1173 insertions(+) create mode 100644 tensorflow/lite/tools/optimize/quantize_model.cc create mode 100644 tensorflow/lite/tools/optimize/quantize_model.h create mode 100644 tensorflow/lite/tools/optimize/quantize_model_test.cc create mode 100644 tensorflow/lite/tools/optimize/subgraph_quantizer.cc create mode 100644 tensorflow/lite/tools/optimize/subgraph_quantizer.h create mode 100644 tensorflow/lite/tools/optimize/subgraph_quantizer_test.cc create mode 100644 tensorflow/lite/tools/optimize/symmetric_per_channel_params.cc create mode 100644 tensorflow/lite/tools/optimize/symmetric_per_channel_params.h create mode 100644 tensorflow/lite/tools/optimize/symmetric_per_channel_params_test.cc create mode 100644 tensorflow/lite/tools/optimize/test_util.cc create mode 100644 tensorflow/lite/tools/optimize/test_util.h diff --git a/tensorflow/lite/tools/optimize/quantize_model.cc b/tensorflow/lite/tools/optimize/quantize_model.cc new file mode 100644 index 0000000000..55a9b1c580 --- /dev/null +++ b/tensorflow/lite/tools/optimize/quantize_model.cc @@ -0,0 +1,63 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/tools/optimize/quantize_model.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "flatbuffers/flexbuffers.h" +#include "tensorflow/lite/context.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/model.h" +#include "tensorflow/lite/schema/schema_generated.h" +#include "tensorflow/lite/tools/optimize/subgraph_quantizer.h" + +namespace tflite { +namespace optimize { + +TfLiteStatus QuantizeModel(flatbuffers::FlatBufferBuilder* builder, + ModelT* model, ErrorReporter* error_reporter) { + for (size_t subgraph_idx = 0; subgraph_idx < model->subgraphs.size(); + subgraph_idx++) { + SubGraphT* subgraph = model->subgraphs.at(subgraph_idx).get(); + internal::SubgraphQuantizer quantizer(model, subgraph, error_reporter); + for (int op_idx = 0; op_idx < subgraph->operators.size(); op_idx++) { + auto status = quantizer.QuantizeOperator(op_idx); + if (status != kTfLiteOk) { + OperatorT* op = subgraph->operators[op_idx].get(); + const BuiltinOperator op_code = + model->operator_codes[op->opcode_index]->builtin_code; + error_reporter->Report( + "Failed to quantized operator: %s in subgraph %d, node: %d", + EnumNameBuiltinOperator(op_code), subgraph_idx, op_idx); + return kTfLiteError; + } + } + } + + flatbuffers::Offset output_model_location = + Model::Pack(*builder, model); + FinishModelBuffer(*builder, output_model_location); + + return kTfLiteOk; +} + +} // namespace optimize +} // namespace tflite diff --git a/tensorflow/lite/tools/optimize/quantize_model.h b/tensorflow/lite/tools/optimize/quantize_model.h new file mode 100644 index 0000000000..e4a62435d3 --- /dev/null +++ b/tensorflow/lite/tools/optimize/quantize_model.h @@ -0,0 +1,39 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_TOOLS_OPTIMIZE_QUANTIZE_MODEL_H_ +#define TENSORFLOW_LITE_TOOLS_OPTIMIZE_QUANTIZE_MODEL_H_ + +#include + +#include "tensorflow/lite/context.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/model.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +namespace optimize { + +// Quantizes input_model and populates the provided builder with the new model. +// input_model is required to have min/max information populated in its +// quantization params. +// +// Note: This is a private API, subject to change. +TfLiteStatus QuantizeModel(flatbuffers::FlatBufferBuilder* builder, + ModelT* input_model, ErrorReporter* error_reporter); + +} // namespace optimize +} // namespace tflite + +#endif // TENSORFLOW_LITE_TOOLS_OPTIMIZE_QUANTIZE_MODEL_H_ diff --git a/tensorflow/lite/tools/optimize/quantize_model_test.cc b/tensorflow/lite/tools/optimize/quantize_model_test.cc new file mode 100644 index 0000000000..a25f2cc91f --- /dev/null +++ b/tensorflow/lite/tools/optimize/quantize_model_test.cc @@ -0,0 +1,150 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include +#include +#include + +#include +#include +#include "flatbuffers/flatbuffers.h" // TF:flatbuffers +#include "flatbuffers/flexbuffers.h" // TF:flatbuffers +#include "tensorflow/core/lib/io/path.h" +#include "tensorflow/core/platform/init_main.h" +#include "tensorflow/core/util/command_line_flags.h" +#include "tensorflow/lite/model.h" +#include "tensorflow/lite/schema/schema_generated.h" +#include "tensorflow/lite/tools/optimize/quantize_model.h" +#include "tensorflow/lite/tools/optimize/test_util.h" + +namespace { +tensorflow::string* g_test_model_dir = nullptr; +} // namespace + +namespace tflite { +namespace optimize { +namespace { + +std::unique_ptr ReadTestModel() { + auto model_path = tensorflow::io::JoinPath( + *g_test_model_dir, internal::kModelWith0Plus10Weights); + return FlatBufferModel::BuildFromFile(model_path.c_str()); +} + +template +std::vector GetAsVector(const flatbuffers::Vector* vec) { + return std::vector(vec->begin(), vec->end()); +} + +class QuantizeModelTest : public testing::Test { + protected: + QuantizeModelTest() { + input_model_ = ReadTestModel(); + readonly_model_ = input_model_->GetModel(); + readonly_model_->UnPackTo(&model_); + } + + std::unique_ptr input_model_; + const Model* readonly_model_; + tflite::ModelT model_; + flatbuffers::FlatBufferBuilder builder_; + internal::FailOnErrorReporter error_reporter_; +}; + +TEST_F(QuantizeModelTest, QuantizationSucceeds) { + auto status = QuantizeModel(&builder_, &model_, &error_reporter_); + EXPECT_EQ(status, kTfLiteOk); + const uint8_t* buffer = builder_.GetBufferPointer(); + const Model* output_model = GetModel(buffer); + ASSERT_TRUE(output_model); +} + +TEST_F(QuantizeModelTest, TensorShapesAndStructureIsUnchanged) { + auto status = QuantizeModel(&builder_, &model_, &error_reporter_); + EXPECT_EQ(status, kTfLiteOk); + ASSERT_EQ(model_.subgraphs.size(), readonly_model_->subgraphs()->size()); + for (size_t subgraph_idx = 0; subgraph_idx < model_.subgraphs.size(); + subgraph_idx++) { + const auto quantized_graph = model_.subgraphs[subgraph_idx].get(); + const auto float_graph = readonly_model_->subgraphs()->Get(subgraph_idx); + ASSERT_EQ(quantized_graph->tensors.size(), float_graph->tensors()->size()); + for (size_t i = 0; i < quantized_graph->tensors.size(); i++) { + const auto quant_tensor = quantized_graph->tensors[i].get(); + const auto float_tensor = float_graph->tensors()->Get(i); + EXPECT_EQ(quant_tensor->buffer, float_tensor->buffer()); + EXPECT_EQ(quant_tensor->is_variable, float_tensor->is_variable()); + EXPECT_EQ(quant_tensor->shape, GetAsVector(float_tensor->shape())); + EXPECT_EQ(quant_tensor->name, float_tensor->name()->str()); + } + } +} + +TEST_F(QuantizeModelTest, OperatorsAreUnchanged) { + auto status = QuantizeModel(&builder_, &model_, &error_reporter_); + EXPECT_EQ(status, kTfLiteOk); + ASSERT_EQ(model_.operator_codes.size(), + readonly_model_->operator_codes()->size()); + for (size_t i = 0; i < model_.operator_codes.size(); i++) { + const auto float_model_op = readonly_model_->operator_codes()->Get(i); + EXPECT_EQ(model_.operator_codes[i]->builtin_code, + float_model_op->builtin_code()); + EXPECT_EQ(model_.operator_codes[i]->version, float_model_op->version()); + } + + ASSERT_EQ(model_.subgraphs.size(), readonly_model_->subgraphs()->size()); + for (size_t subgraph_idx = 0; subgraph_idx < model_.subgraphs.size(); + subgraph_idx++) { + const auto quantized_graph = model_.subgraphs[subgraph_idx].get(); + const auto float_graph = readonly_model_->subgraphs()->Get(subgraph_idx); + ASSERT_EQ(quantized_graph->operators.size(), + float_graph->operators()->size()); + for (size_t i = 0; i < quantized_graph->operators.size(); i++) { + const auto quant_op = quantized_graph->operators[i].get(); + const auto float_op = float_graph->operators()->Get(i); + EXPECT_EQ(quant_op->inputs, GetAsVector(float_op->inputs())); + EXPECT_EQ(quant_op->outputs, GetAsVector(float_op->outputs())); + EXPECT_EQ(quant_op->opcode_index, float_op->opcode_index()); + } + } +} + +TEST_F(QuantizeModelTest, GraphIsFullyQuantized) { + auto status = QuantizeModel(&builder_, &model_, &error_reporter_); + EXPECT_EQ(status, kTfLiteOk); + for (const auto& subgraph : model_.subgraphs) { + for (const auto& tensor : subgraph->tensors) { + EXPECT_TRUE(tensor->type == TensorType_INT32 || + tensor->type == TensorType_INT8); + } + } +} + +} // namespace +} // namespace optimize +} // namespace tflite + +int main(int argc, char** argv) { + tensorflow::string model_file; + const std::vector flag_list = { + tensorflow::Flag("test_model_file", &model_file, + "Path to test tflite model file."), + }; + + const bool parse_result = tensorflow::Flags::Parse(&argc, argv, flag_list); + CHECK(parse_result) << "Required test_model_file"; + g_test_model_dir = + new tensorflow::string(tensorflow::io::Dirname(model_file)); + ::tensorflow::port::InitMain(argv[0], &argc, &argv); + return RUN_ALL_TESTS(); +} diff --git a/tensorflow/lite/tools/optimize/subgraph_quantizer.cc b/tensorflow/lite/tools/optimize/subgraph_quantizer.cc new file mode 100644 index 0000000000..27aee83cfd --- /dev/null +++ b/tensorflow/lite/tools/optimize/subgraph_quantizer.cc @@ -0,0 +1,333 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/tools/optimize/subgraph_quantizer.h" + +#include + +#include "flatbuffers/flexbuffers.h" +#include "absl/memory/memory.h" +#include "tensorflow/lite/context.h" +#include "tensorflow/lite/core/api/error_reporter.h" +#include "tensorflow/lite/kernels/internal/round.h" +#include "tensorflow/lite/kernels/internal/tensor_utils.h" +#include "tensorflow/lite/kernels/internal/types.h" +#include "tensorflow/lite/model.h" +#include "tensorflow/lite/schema/schema_generated.h" +#include "tensorflow/lite/tools/optimize/quantization_utils.h" +#include "tensorflow/lite/tools/optimize/symmetric_per_channel_params.h" + +namespace tflite { +namespace optimize { +namespace internal { + +namespace { + +TfLiteStatus AddQuantizationParams(const SymmetricPerChannelParams& params, + const uint8_t* buffer_data, + size_t buffer_size, TensorType output_type, + ModelT* model, TensorT* tensor) { + params.AddToTensor(tensor); + model->buffers[tensor->buffer]->data.assign(buffer_data, + buffer_data + buffer_size); + // Update the tensor type. + tensor->type = output_type; + return kTfLiteOk; +} + +bool OpHasOptionalBiasTensor(BuiltinOperator op_code) { + return op_code == BuiltinOperator_CONV_2D || + op_code == BuiltinOperator_DEPTHWISE_CONV_2D; +} + +struct OpWithBiasTensors { + int activation_input_index; + int bias_input_index; + int weights_input_index; + int index_for_channel_in_weights; +}; + +const OpWithBiasTensors* GetInfoForOpWithBiasTensor(BuiltinOperator op_code) { + if (op_code == BuiltinOperator_CONV_2D) { + static OpWithBiasTensors op_info = {.activation_input_index = 0, + .weights_input_index = 1, + .bias_input_index = 2, + .index_for_channel_in_weights = 0}; + return &op_info; + } + if (op_code == BuiltinOperator_DEPTHWISE_CONV_2D) { + static OpWithBiasTensors op_info = {.activation_input_index = 0, + .weights_input_index = 1, + .bias_input_index = 2, + .index_for_channel_in_weights = 3}; + return &op_info; + } + + return nullptr; +} + +// Symmetrically Quantizes the given tensor as int8 values. +TfLiteStatus SymmetricPerChannelQuantizeTensor(ModelT* model, TensorT* tensor, + int32_t channel_dim_index, + ErrorReporter* error_reporter) { + int32_t channel_dim_size = tensor->shape[channel_dim_index]; + if (tensor->shape.size() != 4) { + error_reporter->Report("Only dims=4 is supported, tensor dims: %d", + tensor->shape.size()); + return kTfLiteError; + } + + uint64_t num_elements; + TF_LITE_ENSURE_STATUS(utils::NumElements(*tensor, &num_elements)); + const uint64_t num_elements_per_channel = num_elements / channel_dim_size; + + if (tensor->quantization == nullptr) { + tensor->quantization = absl::make_unique(); + } + + std::vector min_vals(channel_dim_size); + std::vector max_vals(channel_dim_size); + std::vector has_min_max_value(channel_dim_size, false); + int indices[4]; + RuntimeShape tensor_dims{tensor->shape[0], tensor->shape[1], tensor->shape[2], + tensor->shape[3]}; + BufferT* buffer = model->buffers[tensor->buffer].get(); + float* float_data = reinterpret_cast(buffer->data.data()); + + // Compute min max ranges per channel + for (indices[0] = 0; indices[0] < tensor->shape[0]; indices[0]++) { + for (indices[1] = 0; indices[1] < tensor->shape[1]; indices[1]++) { + for (indices[2] = 0; indices[2] < tensor->shape[2]; indices[2]++) { + for (indices[3] = 0; indices[3] < tensor->shape[3]; indices[3]++) { + int channel_idx = indices[channel_dim_index]; + const float val = float_data[Offset(tensor_dims, indices)]; + if (has_min_max_value[channel_idx]) { + if (min_vals[channel_idx] > val) { + min_vals[channel_idx] = val; + } else if (max_vals[channel_idx] < val) { + max_vals[channel_idx] = val; + } + } else { + min_vals[channel_idx] = val; + max_vals[channel_idx] = val; + has_min_max_value[channel_idx] = true; + } + } + } + } + } + + // Calculate scales per channel + std::vector scales(channel_dim_size); + std::vector scale_invs(channel_dim_size); + const int8_t kMinValue = -127; + const int8_t kMaxValue = 127; + const float half_scale = kMaxValue; + for (size_t channel_idx = 0; channel_idx < channel_dim_size; channel_idx++) { + const float half_range = std::max(std::abs(min_vals[channel_idx]), + std::abs(max_vals[channel_idx])); + scales[channel_idx] = half_range / half_scale; + if (half_range == 0) { + scale_invs[channel_idx] = 0; + } else { + scale_invs[channel_idx] = half_scale / half_range; + } + } + + // Quantize the values. + std::vector quantized_buffer(num_elements_per_channel); + std::vector final_buffer(num_elements); + memset(indices, 0, 4 * sizeof(int)); + for (indices[0] = 0; indices[0] < tensor->shape[0]; indices[0]++) { + for (indices[1] = 0; indices[1] < tensor->shape[1]; indices[1]++) { + for (indices[2] = 0; indices[2] < tensor->shape[2]; indices[2]++) { + for (indices[3] = 0; indices[3] < tensor->shape[3]; indices[3]++) { + int channel_idx = indices[channel_dim_index]; + int index = Offset(tensor_dims, indices); + const float val = float_data[index]; + const int32_t quantized_value = + static_cast(TfLiteRound(val * scale_invs[channel_idx])); + final_buffer[index] = std::min( + kMaxValue, std::max(kMinValue, quantized_value)); + } + } + } + } + + // Set the buffers and output type. + uint8_t* uint8_buffer = reinterpret_cast(final_buffer.data()); + size_t buffer_size = num_elements * sizeof(int8_t); + SymmetricPerChannelParams symmetric_params(scales, channel_dim_index); + return AddQuantizationParams(symmetric_params, uint8_buffer, buffer_size, + TensorType_INT8, model, tensor); +} + +// Symmetrically quantizes the bias for ops like Conv and DepthwiseConv. +// The scale of bias if weight_per_channel_scale[channel] * input_scale +TfLiteStatus SymmetricPerChannelBiasQuantize(const TensorT* input_tensor, + const TensorT* weight_tensor, + int channel_dim_index, + ModelT* model, TensorT* tensor, + ErrorReporter* error_reporter) { + if (tensor->shape.size() != 1) { + error_reporter->Report("Expected bias tensor shape to be 1."); + return kTfLiteError; + } + + if (tensor->type != TensorType_FLOAT32) { + return kTfLiteOk; + } + + // TODO(shashishekhar): Make this support scalar biases. + if (tensor->shape[0] != weight_tensor->shape[channel_dim_index]) { + error_reporter->Report( + "Channel mismatch between bias and weight tensors %d vs %d", + tensor->shape[0], weight_tensor->shape[channel_dim_index]); + return kTfLiteError; + } + int32_t channel_dim_size = tensor->shape[0]; + if (!input_tensor->quantization || + input_tensor->quantization->scale.size() != 1) { + error_reporter->Report("Input tensor missing quantization information"); + return kTfLiteError; + } + std::unique_ptr weight_params; + TF_LITE_ENSURE_STATUS(SymmetricPerChannelParams::ReadFromTensor( + *weight_tensor, &weight_params)); + const auto& weight_scales = weight_params->scales(); + + if (weight_scales.size() != channel_dim_size) { + error_reporter->Report("Mismatch weight scale dimension: %d", + weight_scales.size()); + return kTfLiteError; + } + + // Compute scales. + std::vector scales(channel_dim_size); + for (size_t i = 0; i < channel_dim_size; i++) { + scales[i] = input_tensor->quantization->scale[0] * weight_scales[i]; + } + + BufferT* buffer = model->buffers[tensor->buffer].get(); + float* float_data = reinterpret_cast(buffer->data.data()); + uint64_t num_elements; + TF_LITE_ENSURE_STATUS(utils::NumElements(*tensor, &num_elements)); + + if (tensor->quantization == nullptr) { + tensor->quantization = absl::make_unique(); + } + std::vector final_buffer(num_elements); + const int32_t kScale = std::numeric_limits::max(); + + for (int32_t channel_idx = 0; channel_idx < channel_dim_size; channel_idx++) { + float scaling_factor = scales[channel_idx]; + float scaling_factor_inv = (scaling_factor == 0) ? 0 : 1.0 / scaling_factor; + const int32_t quantized_value = static_cast( + TfLiteRound(float_data[channel_idx] * scaling_factor_inv)); + final_buffer[channel_idx] = + std::min(kScale, std::max(-kScale, quantized_value)); + } + + // Set the buffers and output type. + uint8_t* uint8_buffer = reinterpret_cast(final_buffer.data()); + size_t buffer_size = num_elements * sizeof(int32_t); + SymmetricPerChannelParams symmetric_params(scales, channel_dim_index); + return AddQuantizationParams(symmetric_params, uint8_buffer, buffer_size, + TensorType_INT32, model, tensor); +} +} // namespace + +TfLiteStatus SubgraphQuantizer::AsymmetricQuantizeTensor( + BuiltinOperator op_code, int32_t tensor_idx) { + TensorT* tensor = subgraph_->tensors[tensor_idx].get(); + if (tensor->type != TensorType_FLOAT32) { + return kTfLiteOk; + } + + if (model_->buffers[tensor->buffer]->data.data() != nullptr) { + return kTfLiteError; + } + if (!tensor->quantization || tensor->quantization->min.empty() || + tensor->quantization->max.empty()) { + error_reporter_->Report( + "Missing required min/max information for tensor_idx %d of operation: " + "%s", + tensor_idx, EnumNameBuiltinOperator(op_code)); + return kTfLiteError; + } + utils::GetAsymmetricQuantizationParams( + tensor->quantization->min[0], tensor->quantization->max[0], + std::numeric_limits::min(), std::numeric_limits::max(), + tensor->quantization.get()); + tensor->type = TensorType_INT8; + return kTfLiteOk; +} + +TfLiteStatus SubgraphQuantizer::QuantizeOpWithBias(BuiltinOperator op_code, + OperatorT* op) { + auto op_tensor_info = GetInfoForOpWithBiasTensor(op_code); + if (!op_tensor_info) { + error_reporter_->Report("Cannot quantize op: %s", + EnumNameBuiltinOperator(op_code)); + return kTfLiteError; + } + + // Conv/Depthwise conv have 2 inputs when there is no bias, 3 otherwise. + if (op->inputs.size() != 2 && op->inputs.size() != 3) { + return kTfLiteError; + } + auto input_tensor_idx = op->inputs[op_tensor_info->activation_input_index]; + TF_LITE_ENSURE_STATUS(AsymmetricQuantizeTensor(op_code, input_tensor_idx)); + auto weights_tensor_idx = op->inputs[op_tensor_info->weights_input_index]; + + TensorT* weights_tensor = subgraph_->tensors[weights_tensor_idx].get(); + int weights_channel_index = op_tensor_info->index_for_channel_in_weights; + + auto status = SymmetricPerChannelQuantizeTensor( + model_, weights_tensor, weights_channel_index, error_reporter_); + TF_LITE_ENSURE_STATUS(status); + + // If there is bias, quantize it. + if (op->inputs.size() == 3) { + auto bias_tensor_idx = op->inputs[op_tensor_info->bias_input_index]; + const TensorT* input_tensor = subgraph_->tensors[input_tensor_idx].get(); + TensorT* bias_tensor = subgraph_->tensors[bias_tensor_idx].get(); + TF_LITE_ENSURE_STATUS(SymmetricPerChannelBiasQuantize( + input_tensor, weights_tensor, weights_channel_index, model_, + bias_tensor, error_reporter_)); + } + + if (op->outputs.size() != 1) { + return kTfLiteError; + } + auto output_tensor_idx = op->outputs[0]; + TF_LITE_ENSURE_STATUS(AsymmetricQuantizeTensor(op_code, output_tensor_idx)); + + return kTfLiteOk; +} + +TfLiteStatus SubgraphQuantizer::QuantizeOperator(int op_idx) { + OperatorT* op = subgraph_->operators[op_idx].get(); + const BuiltinOperator op_code = + model_->operator_codes[op->opcode_index]->builtin_code; + if (OpHasOptionalBiasTensor(op_code)) { + return QuantizeOpWithBias(op_code, op); + } + + return kTfLiteError; +} + +} // namespace internal +} // namespace optimize +} // namespace tflite diff --git a/tensorflow/lite/tools/optimize/subgraph_quantizer.h b/tensorflow/lite/tools/optimize/subgraph_quantizer.h new file mode 100644 index 0000000000..2543dccea9 --- /dev/null +++ b/tensorflow/lite/tools/optimize/subgraph_quantizer.h @@ -0,0 +1,53 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_TOOLS_OPTIMIZE_SUBGRAPH_QUANTIZER_H_ +#define TENSORFLOW_LITE_TOOLS_OPTIMIZE_SUBGRAPH_QUANTIZER_H_ + +#include "tensorflow/lite/context.h" +#include "tensorflow/lite/model.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +namespace optimize { +namespace internal { + +// Quantizes a given subgraph, the subgraph needs to min/max information +// present. +// +// Assumes that some ops like Conv and Depthwise conv are quantized by +// per channel symmetric quantization. +class SubgraphQuantizer { + public: + SubgraphQuantizer(ModelT* model, SubGraphT* subgraph, + ErrorReporter* error_reporter) + : model_(model), subgraph_(subgraph), error_reporter_(error_reporter) {} + + // Quantize operator at the given index. + TfLiteStatus QuantizeOperator(int op_idx); + + private: + // Quantizes ops with bias tensors. + TfLiteStatus QuantizeOpWithBias(BuiltinOperator op_code, OperatorT* op); + TfLiteStatus AsymmetricQuantizeTensor(BuiltinOperator op_code, + int32_t tensor_idx); + + ModelT* model_; + SubGraphT* subgraph_; + ErrorReporter* error_reporter_; +}; +} // namespace internal +} // namespace optimize +} // namespace tflite +#endif // TENSORFLOW_LITE_TOOLS_OPTIMIZE_SUBGRAPH_QUANTIZER_H_ diff --git a/tensorflow/lite/tools/optimize/subgraph_quantizer_test.cc b/tensorflow/lite/tools/optimize/subgraph_quantizer_test.cc new file mode 100644 index 0000000000..7652429e32 --- /dev/null +++ b/tensorflow/lite/tools/optimize/subgraph_quantizer_test.cc @@ -0,0 +1,258 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/tools/optimize/subgraph_quantizer.h" +#include +#include +#include "tensorflow/core/lib/io/path.h" +#include "tensorflow/core/platform/init_main.h" +#include "tensorflow/core/util/command_line_flags.h" +#include "tensorflow/lite/schema/schema_generated.h" +#include "tensorflow/lite/tools/optimize/symmetric_per_channel_params.h" +#include "tensorflow/lite/tools/optimize/test_util.h" + +namespace { +tensorflow::string* g_test_model_dir = nullptr; +} // namespace + +namespace tflite { +namespace optimize { +namespace internal { +namespace { + +std::unique_ptr ReadTestModel1() { + auto model_path = tensorflow::io::JoinPath(*g_test_model_dir, + kModelWithMinus128Plus127Weights); + return FlatBufferModel::BuildFromFile(model_path.c_str()); +} + +std::unique_ptr ReadTestModel2() { + auto model_path = + tensorflow::io::JoinPath(*g_test_model_dir, kModelWith0Plus10Weights); + return FlatBufferModel::BuildFromFile(model_path.c_str()); +} + +TEST(SubgraphQuantizerTest, VerifyConvQuantizationWithUnitScale) { + ASSERT_TRUE(g_test_model_dir); + ASSERT_FALSE(g_test_model_dir->empty()); + auto test_model = ReadTestModel1(); + ASSERT_TRUE(test_model); + auto readonly_model = test_model->GetModel(); + ASSERT_TRUE(readonly_model); + ASSERT_TRUE(readonly_model->subgraphs()); + ASSERT_GE(readonly_model->subgraphs()->size(), 1); + tflite::ModelT model; + readonly_model->UnPackTo(&model); + auto subgraph = model.subgraphs[0].get(); + FailOnErrorReporter error_reporter; + SubgraphQuantizer quantizer(&model, subgraph, &error_reporter); + auto status = quantizer.QuantizeOperator(0); + ASSERT_EQ(kTfLiteOk, status); + + auto conv_op = subgraph->operators[0].get(); + const int input_tensor_idx = 0; + const int weights_tensor_idx = 1; + const int bias_tensor_index = 2; + const int output_tensor_idx = 0; + const auto bias_tensor = + subgraph->tensors[conv_op->inputs[bias_tensor_index]].get(); + const auto input_tensor = + subgraph->tensors[conv_op->inputs[input_tensor_idx]].get(); + const auto weights_tensor = + subgraph->tensors[conv_op->inputs[weights_tensor_idx]].get(); + const auto output_tensor = + subgraph->tensors[conv_op->outputs[output_tensor_idx]].get(); + + EXPECT_EQ(bias_tensor->type, TensorType_INT32); + EXPECT_EQ(input_tensor->type, TensorType_INT8); + EXPECT_EQ(weights_tensor->type, TensorType_INT8); + + ASSERT_TRUE(weights_tensor->quantization); + const int out_channel_size = weights_tensor->shape[0]; + std::unique_ptr bias_params; + std::unique_ptr weights_params; + ASSERT_EQ(kTfLiteOk, SymmetricPerChannelParams::ReadFromTensor( + *weights_tensor, &weights_params)); + ASSERT_EQ(kTfLiteOk, SymmetricPerChannelParams::ReadFromTensor(*bias_tensor, + &bias_params)); + + ASSERT_EQ(bias_params->scales().size(), out_channel_size); + ASSERT_EQ(weights_params->scales().size(), out_channel_size); + ASSERT_EQ(input_tensor->quantization->scale.size(), 1); + ASSERT_EQ(output_tensor->quantization->scale.size(), 1); + + const float eps = 1e-7; + + // Bias scale should be input * per_channel_weight_scale. + for (size_t i = 0; i < out_channel_size; i++) { + EXPECT_NEAR( + bias_params->scales()[i], + input_tensor->quantization->scale[0] * weights_params->scales()[i], + eps); + } + for (size_t i = 0; i < out_channel_size; i++) { + EXPECT_EQ(weights_params->scales()[i], 1); + EXPECT_EQ(bias_params->scales()[i], 1); + } + EXPECT_EQ(input_tensor->quantization->scale[0], 1); + EXPECT_EQ(output_tensor->quantization->scale[0], 1); + + const auto bias_buffer = model.buffers[bias_tensor->buffer].get(); + ASSERT_EQ(bias_buffer->data.size(), sizeof(int32_t) * bias_tensor->shape[0]); + const int32_t* bias_values = + reinterpret_cast(bias_buffer->data.data()); + const auto original_bias_buffer = + readonly_model->buffers()->Get(bias_tensor->buffer); + const float* bias_float_buffer = + reinterpret_cast(original_bias_buffer->data()->data()); + + for (size_t i = 0; i < bias_tensor->shape[0]; i++) { + auto dequantized_value = bias_values[i] * bias_params->scales()[i]; + EXPECT_NEAR(dequantized_value, bias_float_buffer[i], eps); + } + + const auto weights_buffer = model.buffers[weights_tensor->buffer].get(); + const auto original_weights_buffer = + readonly_model->buffers()->Get(weights_tensor->buffer); + const int8_t* weight_values = + reinterpret_cast(weights_buffer->data.data()); + const float* weights_float_buffer = + reinterpret_cast(original_weights_buffer->data()->data()); + ASSERT_EQ(sizeof(float) * weights_buffer->data.size(), + original_weights_buffer->data()->size()); + int num_values_in_channel = weights_buffer->data.size() / out_channel_size; + for (size_t channel_idx = 0; channel_idx < out_channel_size; channel_idx++) { + for (size_t j = 0; j < num_values_in_channel; j++) { + size_t element_idx = channel_idx * out_channel_size + j; + auto dequantized_value = + weight_values[element_idx] * weights_params->scales()[channel_idx]; + EXPECT_NEAR(dequantized_value, weights_float_buffer[element_idx], eps); + } + } +} + +TEST(SubgraphQuantizerTest, VerifyConvQuantization) { + ASSERT_TRUE(g_test_model_dir); + ASSERT_FALSE(g_test_model_dir->empty()); + auto test_model = ReadTestModel2(); + ASSERT_TRUE(test_model); + auto readonly_model = test_model->GetModel(); + ASSERT_TRUE(readonly_model); + ASSERT_TRUE(readonly_model->subgraphs()); + ASSERT_GE(readonly_model->subgraphs()->size(), 1); + tflite::ModelT model; + readonly_model->UnPackTo(&model); + auto subgraph = model.subgraphs[0].get(); + FailOnErrorReporter error_reporter; + SubgraphQuantizer quantizer(&model, subgraph, &error_reporter); + auto status = quantizer.QuantizeOperator(0); + ASSERT_EQ(kTfLiteOk, status); + + auto conv_op = subgraph->operators[0].get(); + const int input_tensor_idx = 0; + const int weights_tensor_idx = 1; + const int bias_tensor_index = 2; + const int output_tensor_idx = 0; + const auto bias_tensor = + subgraph->tensors[conv_op->inputs[bias_tensor_index]].get(); + const auto input_tensor = + subgraph->tensors[conv_op->inputs[input_tensor_idx]].get(); + const auto weights_tensor = + subgraph->tensors[conv_op->inputs[weights_tensor_idx]].get(); + const auto output_tensor = + subgraph->tensors[conv_op->outputs[output_tensor_idx]].get(); + + EXPECT_EQ(bias_tensor->type, TensorType_INT32); + EXPECT_EQ(input_tensor->type, TensorType_INT8); + EXPECT_EQ(weights_tensor->type, TensorType_INT8); + + ASSERT_TRUE(weights_tensor->quantization); + const int out_channel_size = weights_tensor->shape[0]; + std::unique_ptr bias_params; + std::unique_ptr weights_params; + ASSERT_EQ(kTfLiteOk, SymmetricPerChannelParams::ReadFromTensor( + *weights_tensor, &weights_params)); + ASSERT_EQ(kTfLiteOk, SymmetricPerChannelParams::ReadFromTensor(*bias_tensor, + &bias_params)); + + ASSERT_EQ(bias_params->scales().size(), out_channel_size); + ASSERT_EQ(weights_params->scales().size(), out_channel_size); + ASSERT_EQ(input_tensor->quantization->scale.size(), 1); + ASSERT_EQ(output_tensor->quantization->scale.size(), 1); + + const float eps = 1e-7; + + // Bias scale should be input * per_channel_weight_scale. + for (size_t i = 0; i < out_channel_size; i++) { + EXPECT_NEAR( + bias_params->scales()[i], + input_tensor->quantization->scale[0] * weights_params->scales()[i], + eps); + } + + const auto bias_buffer = model.buffers[bias_tensor->buffer].get(); + ASSERT_EQ(bias_buffer->data.size(), sizeof(int32_t) * bias_tensor->shape[0]); + const int32_t* bias_values = + reinterpret_cast(bias_buffer->data.data()); + const auto original_bias_buffer = + readonly_model->buffers()->Get(bias_tensor->buffer); + const float* bias_float_buffer = + reinterpret_cast(original_bias_buffer->data()->data()); + + for (size_t i = 0; i < bias_tensor->shape[0]; i++) { + auto scale = bias_params->scales()[i]; + auto dequantized_value = bias_values[i] * scale; + EXPECT_NEAR(dequantized_value, bias_float_buffer[i], scale / 2); + } + + const auto weights_buffer = model.buffers[weights_tensor->buffer].get(); + const auto original_weights_buffer = + readonly_model->buffers()->Get(weights_tensor->buffer); + const int8_t* weight_values = + reinterpret_cast(weights_buffer->data.data()); + const float* weights_float_buffer = + reinterpret_cast(original_weights_buffer->data()->data()); + ASSERT_EQ(sizeof(float) * weights_buffer->data.size(), + original_weights_buffer->data()->size()); + int num_values_in_channel = weights_buffer->data.size() / out_channel_size; + for (size_t channel_idx = 0; channel_idx < out_channel_size; channel_idx++) { + for (size_t j = 0; j < num_values_in_channel; j++) { + size_t element_idx = channel_idx * out_channel_size + j; + auto scale = weights_params->scales()[channel_idx]; + auto dequantized_value = weight_values[element_idx] * scale; + EXPECT_NEAR(dequantized_value, weights_float_buffer[element_idx], + scale / 2); + } + } +} + +} // namespace +} // namespace internal +} // namespace optimize +} // namespace tflite + +int main(int argc, char** argv) { + tensorflow::string model_file; + const std::vector flag_list = { + tensorflow::Flag("test_model_file", &model_file, + "Path to test tflite model file."), + }; + + const bool parse_result = tensorflow::Flags::Parse(&argc, argv, flag_list); + CHECK(parse_result) << "Required test_model_file"; + g_test_model_dir = + new tensorflow::string(tensorflow::io::Dirname(model_file)); + ::tensorflow::port::InitMain(argv[0], &argc, &argv); + return RUN_ALL_TESTS(); +} diff --git a/tensorflow/lite/tools/optimize/symmetric_per_channel_params.cc b/tensorflow/lite/tools/optimize/symmetric_per_channel_params.cc new file mode 100644 index 0000000000..ff7e5657f1 --- /dev/null +++ b/tensorflow/lite/tools/optimize/symmetric_per_channel_params.cc @@ -0,0 +1,86 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/tools/optimize/symmetric_per_channel_params.h" + +#include "flatbuffers/flexbuffers.h" +#include "absl/memory/memory.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +namespace optimize { +namespace internal { + +namespace { +const char* kCustomQuantizationScales = "scales"; +const char* kCustomQuantizationChannelDimIndex = "channel_dim_index"; + +// Writes scales and dimensions to custom quantization. +std::vector SerializeToFlexBuffer(const std::vector& scales, + int channel_dim_index) { + flexbuffers::Builder fbb; + fbb.Map([&]() { + fbb.Vector(kCustomQuantizationScales, [&]() { + for (float scale : scales) { + fbb.Float(scale); + } + }); + fbb.Int(kCustomQuantizationChannelDimIndex, channel_dim_index); + }); + fbb.Finish(); + return fbb.GetBuffer(); +} + +} // namespace + +/*static*/ TfLiteStatus SymmetricPerChannelParams::ReadFromTensor( + const TensorT& tensor, std::unique_ptr* params) { + const auto* q_params = tensor.quantization.get(); + if (!q_params) return kTfLiteError; + auto custom_quantization = q_params->details.AsCustomQuantization(); + + auto buffer = flexbuffers::GetRoot(custom_quantization->custom.data(), + custom_quantization->custom.size()); + if (!buffer.IsMap()) { + return kTfLiteError; + } + + auto custom_quantization_map = buffer.AsMap(); + auto quant_scales = + custom_quantization_map[kCustomQuantizationScales].AsVector(); + auto channel_dim_index = + custom_quantization_map[kCustomQuantizationChannelDimIndex].AsInt32(); + std::vector scales; + scales.reserve(quant_scales.size()); + for (int i = 0; i < quant_scales.size(); i++) { + scales.push_back(quant_scales[i].AsFloat()); + } + *params = + absl::make_unique(scales, channel_dim_index); + return kTfLiteOk; +} + +TfLiteStatus SymmetricPerChannelParams::AddToTensor(TensorT* tensor) const { + flatbuffers::FlatBufferBuilder fbb; + CustomQuantizationT* custom_quantization = new CustomQuantizationT; + custom_quantization->custom = + SerializeToFlexBuffer(scales_, channel_dim_index_); + tensor->quantization = absl::make_unique(); + tensor->quantization->details.type = QuantizationDetails_CustomQuantization; + tensor->quantization->details.value = custom_quantization; + return kTfLiteOk; +} +} // namespace internal +} // namespace optimize +} // namespace tflite diff --git a/tensorflow/lite/tools/optimize/symmetric_per_channel_params.h b/tensorflow/lite/tools/optimize/symmetric_per_channel_params.h new file mode 100644 index 0000000000..2ec3ea373a --- /dev/null +++ b/tensorflow/lite/tools/optimize/symmetric_per_channel_params.h @@ -0,0 +1,58 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_TOOLS_OPTIMIZE_SYMMETRIC_PER_CHANNEL_PARAMS_H_ +#define TENSORFLOW_LITE_TOOLS_OPTIMIZE_SYMMETRIC_PER_CHANNEL_PARAMS_H_ + +#include +#include + +#include "tensorflow/lite/context.h" +#include "tensorflow/lite/model.h" +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +namespace optimize { +namespace internal { + +// Helper to read/write symmetric per channel parameters to tensors. +// +// TODO(shashishekhar): This maybe useful for kernels as well, refactor to +// kernel utils. +class SymmetricPerChannelParams { + public: + SymmetricPerChannelParams(const std::vector scales, + int channel_dim_index) + : scales_(scales), channel_dim_index_(channel_dim_index) {} + + // Creates a new instance by reading the information from existing tensor. + static TfLiteStatus ReadFromTensor( + const TensorT& tensor, + std::unique_ptr* params); + + // Add the symmetric per channel info to the tensor. + TfLiteStatus AddToTensor(TensorT* tensor) const; + + const std::vector& scales() const { return scales_; } + + int channel_dim_index() const { return channel_dim_index_; } + + private: + std::vector scales_; + int channel_dim_index_; +}; +} // namespace internal +} // namespace optimize +} // namespace tflite +#endif // TENSORFLOW_LITE_TOOLS_OPTIMIZE_SYMMETRIC_PER_CHANNEL_PARAMS_H_ diff --git a/tensorflow/lite/tools/optimize/symmetric_per_channel_params_test.cc b/tensorflow/lite/tools/optimize/symmetric_per_channel_params_test.cc new file mode 100644 index 0000000000..4d3cbe6f49 --- /dev/null +++ b/tensorflow/lite/tools/optimize/symmetric_per_channel_params_test.cc @@ -0,0 +1,51 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/tools/optimize/symmetric_per_channel_params.h" +#include +#include +#include "flatbuffers/flexbuffers.h" // TF:flatbuffers +#include "tensorflow/lite/schema/schema_generated.h" + +namespace tflite { +namespace optimize { +namespace internal { +namespace { + +TEST(SymmetricPerChannelParamsTest, TestReadWrite) { + TensorT tensor; + std::unique_ptr read_back_params; + const std::vector scales = {3.0, 4.0, 5.0}; + const int channel_dim_index = 42; + + SymmetricPerChannelParams params(scales, channel_dim_index); + params.AddToTensor(&tensor); + auto status = + SymmetricPerChannelParams::ReadFromTensor(tensor, &read_back_params); + EXPECT_EQ(kTfLiteOk, status); + ASSERT_TRUE(read_back_params); + + EXPECT_EQ(channel_dim_index, read_back_params->channel_dim_index()); + ASSERT_EQ(read_back_params->scales(), scales); +} + +} // namespace +} // namespace internal +} // namespace optimize +} // namespace tflite + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tensorflow/lite/tools/optimize/test_util.cc b/tensorflow/lite/tools/optimize/test_util.cc new file mode 100644 index 0000000000..83b9f0dcd3 --- /dev/null +++ b/tensorflow/lite/tools/optimize/test_util.cc @@ -0,0 +1,36 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow/lite/tools/optimize/test_util.h" + +#include + +namespace tflite { +namespace optimize { +namespace internal { +const char* kModelWithMinus128Plus127Weights = + "single_conv_weights_min_minus_127_max_plus_127.tflite"; + +const char* kModelWith0Plus10Weights = + "single_conv_weights_min_0_max_plus_10.tflite"; + +int FailOnErrorReporter::Report(const char* format, va_list args) { + char buf[1024]; + vsnprintf(buf, sizeof(buf), format, args); + EXPECT_TRUE(false) << "Error happened: " << buf; + return 0; +} +} // namespace internal +} // namespace optimize +} // namespace tflite diff --git a/tensorflow/lite/tools/optimize/test_util.h b/tensorflow/lite/tools/optimize/test_util.h new file mode 100644 index 0000000000..26da41e9cc --- /dev/null +++ b/tensorflow/lite/tools/optimize/test_util.h @@ -0,0 +1,46 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_TOOLS_OPTIMIZE_TEST_UTIL_H_ +#define TENSORFLOW_LITE_TOOLS_OPTIMIZE_TEST_UTIL_H_ + +#include "tensorflow/lite/core/api/error_reporter.h" + +namespace tflite { +namespace optimize { +namespace internal { +// Test model with a single convolution. +// Floating point weights of the model are all integers and lie in +// range[-127, 127]. The weights have been put in such a way that each +// channel has at least one weight as -127 and one weight as 127. +// The activations are all in range: [-128, 127] +// This means all bias computations should result in 1.0 scale. +extern const char* kModelWithMinus128Plus127Weights; + +// Test model with single convolution where all weights are integers between +// [0, 10] weights are randomly distributed. It is not guaranteed that min max +// for weights are going to appear in each channel. +// Activations have min = 0, max = 10. +extern const char* kModelWith0Plus10Weights; + +// An error reporter that fails on testing. +class FailOnErrorReporter : public ErrorReporter { + public: + int Report(const char* format, va_list args) override; +}; +} // namespace internal +} // namespace optimize +} // namespace tflite + +#endif // TENSORFLOW_LITE_TOOLS_OPTIMIZE_TEST_UTIL_H_ -- GitLab From aa13f416d15e096f93497861bcd1d090fe253427 Mon Sep 17 00:00:00 2001 From: James Ring Date: Thu, 20 Dec 2018 18:09:55 -0800 Subject: [PATCH 0223/1765] Fix c_test bugs on mac and under asan PiperOrigin-RevId: 226424791 --- tensorflow/c/BUILD | 6 ------ tensorflow/c/c_test.c | 6 +++++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/tensorflow/c/BUILD b/tensorflow/c/BUILD index 3e1f220db2..9d267e9e59 100644 --- a/tensorflow/c/BUILD +++ b/tensorflow/c/BUILD @@ -252,12 +252,6 @@ tf_cc_test( name = "c_test", srcs = ["c_test.c"], extra_copts = ["-std=c11"], - tags = [ - # TODO(b/121223209): Re-enable after fixing asan memory leaks and MacOS - # build errors. - "noasan", - "no_mac", - ], deps = [ ":c_api", ":c_api_experimental", diff --git a/tensorflow/c/c_test.c b/tensorflow/c/c_test.c index c0ed5ccd15..100aefd58c 100644 --- a/tensorflow/c/c_test.c +++ b/tensorflow/c/c_test.c @@ -14,9 +14,9 @@ limitations under the License. ==============================================================================*/ #include -#include #include #include +#include #include #include @@ -68,6 +68,10 @@ int main(int argc, char** argv) { } fprintf(stderr, "wrote %s\n", full_path); free(full_path); + TF_CloseWritableFile(h, status); + if (TF_GetCode(status) != TF_OK) { + fprintf(stderr, "TF_CloseWritableFile failed: %s\n", TF_Message(status)); + } TF_StringStreamDone(s); TF_KernelBuilder* b = -- GitLab From 83dbe37b4be4cb289da6d1a4d92e17c583e2668e Mon Sep 17 00:00:00 2001 From: Mark Heffernan Date: Thu, 20 Dec 2018 18:16:23 -0800 Subject: [PATCH 0224/1765] Replace ShapeUtil::Is(Array|Tuple|Token|Opaque) with Shape::Is(Array|Tuple|Token|Opaque). No functional change. ShapeUtil methods are marked as deprecated. These methods will be removed in a later CL. PiperOrigin-RevId: 226425321 --- tensorflow/compiler/jit/xla_launch_util.cc | 4 +- tensorflow/compiler/tf2xla/kernels/if_op.cc | 6 +- .../compiler/tf2xla/kernels/stack_ops.cc | 2 +- .../tf2xla/kernels/tensor_list_ops.cc | 2 +- .../compiler/tf2xla/kernels/while_op.cc | 6 +- tensorflow/compiler/tf2xla/literal_util.cc | 2 +- tensorflow/compiler/tf2xla/shape_util.cc | 4 +- .../compiler/tf2xla/xla_compiler_test.cc | 10 +-- tensorflow/compiler/tf2xla/xla_helpers.cc | 2 +- tensorflow/compiler/xla/client/lib/testing.cc | 4 +- tensorflow/compiler/xla/client/xla_builder.cc | 27 +++---- tensorflow/compiler/xla/layout_util.cc | 38 +++++---- tensorflow/compiler/xla/literal.cc | 80 +++++++++---------- tensorflow/compiler/xla/literal.h | 12 +-- tensorflow/compiler/xla/literal_comparison.cc | 12 +-- tensorflow/compiler/xla/literal_test.cc | 4 +- tensorflow/compiler/xla/literal_util.cc | 4 +- .../xla/python/local_computation_builder.cc | 4 +- .../compiler/xla/python/numpy_bridge.cc | 4 +- .../xla/service/algebraic_simplifier.cc | 8 +- .../xla/service/allocation_tracker.cc | 4 +- .../service/bfloat16_conversion_folding.cc | 2 +- .../xla/service/bfloat16_normalization.cc | 2 +- .../xla/service/bfloat16_propagation.cc | 2 +- .../compiler/xla/service/buffer_assignment.cc | 2 +- .../xla/service/buffer_liveness_test.cc | 8 +- .../compiler/xla/service/buffer_value.cc | 4 +- .../compiler/xla/service/copy_insertion.cc | 2 +- .../compiler/xla/service/cpu/cpu_compiler.cc | 2 +- .../xla/service/cpu/cpu_executable.cc | 2 +- .../xla/service/cpu/cpu_layout_assignment.cc | 4 +- .../xla/service/cpu/cpu_transfer_manager.cc | 4 +- .../xla/service/cpu/ir_emission_utils.cc | 2 +- .../compiler/xla/service/cpu/ir_emitter.cc | 23 +++--- .../xla/service/cpu/parallel_loop_emitter.cc | 2 +- .../service/cpu/parallel_task_assignment.cc | 2 +- .../xla/service/cpu/tests/cpu_infeed_test.cc | 2 +- .../xla/service/gather_expander_test.cc | 2 +- .../xla/service/generic_transfer_manager.cc | 4 +- .../compiler/xla/service/gpu/fusion_merger.cc | 2 +- .../xla/service/gpu/gpu_executable.cc | 2 +- .../compiler/xla/service/gpu/gpu_fusible.cc | 6 +- .../xla/service/gpu/gpu_layout_assignment.cc | 2 +- .../xla/service/gpu/gpu_transfer_manager.cc | 9 +-- .../xla/service/gpu/hlo_to_ir_bindings.cc | 2 +- .../compiler/xla/service/gpu/infeed_thunk.cc | 6 +- .../compiler/xla/service/gpu/ir_emitter.cc | 6 +- .../xla/service/gpu/ir_emitter_unnested.cc | 20 +++-- .../xla/service/gpu/tests/infeed_test.cc | 2 +- .../xla/service/hlo_alias_analysis.cc | 6 +- .../compiler/xla/service/hlo_computation.cc | 6 +- .../xla/service/hlo_constant_folding.cc | 5 +- .../compiler/xla/service/hlo_cost_analysis.cc | 6 +- .../xla/service/hlo_dataflow_analysis.cc | 2 +- .../xla/service/hlo_dataflow_analysis_test.cc | 4 +- .../xla/service/hlo_element_type_converter.cc | 6 +- .../compiler/xla/service/hlo_evaluator.cc | 8 +- .../xla/service/hlo_evaluator_typed_visitor.h | 24 +++--- .../xla/service/hlo_execution_profile_test.cc | 2 +- .../compiler/xla/service/hlo_graph_dumper.cc | 6 +- .../compiler/xla/service/hlo_instruction.cc | 6 +- .../compiler/xla/service/hlo_instructions.cc | 4 +- .../compiler/xla/service/hlo_module_dce.cc | 2 +- tensorflow/compiler/xla/service/hlo_parser.cc | 6 +- .../compiler/xla/service/hlo_sharding.cc | 12 +-- .../xla/service/hlo_sharding_metadata.cc | 8 +- .../xla/service/hlo_tfgraph_builder.cc | 2 +- tensorflow/compiler/xla/service/hlo_value.cc | 11 ++- .../compiler/xla/service/hlo_verifier.cc | 4 +- .../xla/service/instruction_fusion.cc | 4 +- .../xla/service/interpreter/executable.cc | 2 +- .../compiler/xla/service/layout_assignment.cc | 48 ++++++----- .../xla/service/llvm_ir/fused_ir_emitter.cc | 2 +- .../compiler/xla/service/llvm_ir/ir_array.cc | 2 +- .../compiler/xla/service/llvm_ir/llvm_util.cc | 4 +- .../compiler/xla/service/llvm_ir/tuple_ops.cc | 2 +- .../compiler/xla/service/pattern_matcher.h | 4 +- .../compiler/xla/service/shape_inference.cc | 16 ++-- .../compiler/xla/service/shaped_buffer.cc | 2 +- .../compiler/xla/service/transfer_manager.cc | 6 +- .../xla/service/tuple_points_to_analysis.cc | 2 +- .../service/tuple_points_to_analysis_test.cc | 2 +- tensorflow/compiler/xla/service/tuple_util.cc | 4 +- .../while_loop_invariant_code_motion.cc | 8 +- .../xla/service/while_loop_simplifier.cc | 13 ++- tensorflow/compiler/xla/service/while_util.cc | 2 +- .../xla/service/zero_sized_hlo_elimination.cc | 3 +- tensorflow/compiler/xla/shape.cc | 6 -- tensorflow/compiler/xla/shape.h | 12 ++- tensorflow/compiler/xla/shape_layout.cc | 8 +- tensorflow/compiler/xla/shape_tree.h | 6 +- tensorflow/compiler/xla/shape_util.cc | 24 +++--- tensorflow/compiler/xla/shape_util.h | 6 +- .../xla/tests/client_library_test_base.cc | 2 +- tensorflow/compiler/xla/tests/client_test.cc | 2 +- .../xla/tests/local_client_execute_test.cc | 6 +- tensorflow/compiler/xla/tests/test_utils.cc | 2 +- .../compiler/xrt/kernels/xrt_execute_op.cc | 2 +- 98 files changed, 345 insertions(+), 354 deletions(-) diff --git a/tensorflow/compiler/jit/xla_launch_util.cc b/tensorflow/compiler/jit/xla_launch_util.cc index 3b0bda4caa..4e3cb0238f 100644 --- a/tensorflow/compiler/jit/xla_launch_util.cc +++ b/tensorflow/compiler/jit/xla_launch_util.cc @@ -237,7 +237,7 @@ void XlaComputationLaunchContext::PopulateInputs( const xla::Shape on_device_shape = client_->backend().transfer_manager()->HostShapeToDeviceShape(shape); - if (xla::ShapeUtil::IsTuple(on_device_shape)) { + if (on_device_shape.IsTuple()) { const XlaTensor* xla_tensor = XlaTensor::FromTensor(t); CHECK(xla_tensor && xla_tensor->has_shaped_buffer()); arg_ptrs_[i] = const_cast(&xla_tensor->shaped_buffer()); @@ -274,7 +274,7 @@ Status XlaComputationLaunchContext::PopulateOutputs( // If the on-host-shape isn't a tuple, create a new single-element tuple // buffer with a nullptr root index table. This allows the code below to treat // output as a tuple unconditionally. - if (!xla::ShapeUtil::IsTuple(output.on_host_shape())) { + if (!output.on_host_shape().IsTuple()) { ShapedBuffer nontuple_buffer = output.release(); ShapedBuffer buffer( xla::ShapeUtil::MakeTupleShape({nontuple_buffer.on_host_shape()}), diff --git a/tensorflow/compiler/tf2xla/kernels/if_op.cc b/tensorflow/compiler/tf2xla/kernels/if_op.cc index 4f0f0fd9ae..954ae0b596 100644 --- a/tensorflow/compiler/tf2xla/kernels/if_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/if_op.cc @@ -150,12 +150,12 @@ void XlaIfOp::Compile(XlaOpKernelContext* ctx) { OP_REQUIRES(ctx, then_result.xla_input_shapes.size() == 1, errors::FailedPrecondition("Expected one input shape")); xla::Shape then_input_shape = then_result.xla_input_shapes[0]; - OP_REQUIRES(ctx, xla::ShapeUtil::IsTuple(then_input_shape), + OP_REQUIRES(ctx, then_input_shape.IsTuple(), errors::FailedPrecondition("Expected tuple shape")); OP_REQUIRES(ctx, else_result.xla_input_shapes.size() == 1, errors::FailedPrecondition("Expected one input shape")); xla::Shape else_input_shape = else_result.xla_input_shapes[0]; - OP_REQUIRES(ctx, xla::ShapeUtil::IsTuple(else_input_shape), + OP_REQUIRES(ctx, else_input_shape.IsTuple(), errors::FailedPrecondition("Expected tuple shape")); OP_REQUIRES(ctx, xla::ShapeUtil::Compatible(then_input_shape, else_input_shape), @@ -248,7 +248,7 @@ void XlaIfOp::Compile(XlaOpKernelContext* ctx) { xla::GetTupleElement(outputs, output_types_.size() + num_resource_args); auto shape_or = b->GetShape(token_output); OP_REQUIRES_OK(ctx, shape_or.status()); - OP_REQUIRES(ctx, xla::ShapeUtil::IsToken(shape_or.ValueOrDie()), + OP_REQUIRES(ctx, shape_or.ValueOrDie().IsToken(), errors::FailedPrecondition( "Token output is not token type: ", xla::ShapeUtil::HumanString(shape_or.ValueOrDie()))); diff --git a/tensorflow/compiler/tf2xla/kernels/stack_ops.cc b/tensorflow/compiler/tf2xla/kernels/stack_ops.cc index 8e9e4daf99..02d71a3942 100644 --- a/tensorflow/compiler/tf2xla/kernels/stack_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/stack_ops.cc @@ -45,7 +45,7 @@ Status GetStackShape(xla::XlaBuilder* builder, XlaResource* resource, return shape_or_status.status(); } xla::Shape shape = shape_or_status.ValueOrDie(); - TF_RET_CHECK(xla::ShapeUtil::IsTuple(shape)); + TF_RET_CHECK(shape.IsTuple()); return XLAShapeToTensorShape(xla::ShapeUtil::GetTupleElementShape(shape, 0), stack_shape); } diff --git a/tensorflow/compiler/tf2xla/kernels/tensor_list_ops.cc b/tensorflow/compiler/tf2xla/kernels/tensor_list_ops.cc index 64a24703ae..747f591a1b 100644 --- a/tensorflow/compiler/tf2xla/kernels/tensor_list_ops.cc +++ b/tensorflow/compiler/tf2xla/kernels/tensor_list_ops.cc @@ -45,7 +45,7 @@ Status GetTensorListShape(xla::XlaBuilder* builder, xla::XlaOp op, return shape_or_status.status(); } xla::Shape shape = shape_or_status.ValueOrDie(); - TF_RET_CHECK(xla::ShapeUtil::IsTuple(shape)); + TF_RET_CHECK(shape.IsTuple()); return XLAShapeToTensorShape(xla::ShapeUtil::GetTupleElementShape(shape, 0), tensor_list_shape); } diff --git a/tensorflow/compiler/tf2xla/kernels/while_op.cc b/tensorflow/compiler/tf2xla/kernels/while_op.cc index ff5255028b..b32683a682 100644 --- a/tensorflow/compiler/tf2xla/kernels/while_op.cc +++ b/tensorflow/compiler/tf2xla/kernels/while_op.cc @@ -206,12 +206,12 @@ void XlaWhileOp::Compile(XlaOpKernelContext* ctx) { OP_REQUIRES(ctx, body.xla_input_shapes.size() == 1, errors::FailedPrecondition("Expected one input shape")); xla::Shape body_input_shape = body.xla_input_shapes[0]; - OP_REQUIRES(ctx, xla::ShapeUtil::IsTuple(body_input_shape), + OP_REQUIRES(ctx, body_input_shape.IsTuple(), errors::FailedPrecondition("Expected tuple shape")); OP_REQUIRES(ctx, cond.xla_input_shapes.size() == 1, errors::FailedPrecondition("Expected one input shape")); xla::Shape cond_input_shape = cond.xla_input_shapes[0]; - OP_REQUIRES(ctx, xla::ShapeUtil::IsTuple(cond_input_shape), + OP_REQUIRES(ctx, cond_input_shape.IsTuple(), errors::FailedPrecondition("Expected tuple shape")); VLOG(2) << "Body shape: " << xla::ShapeUtil::HumanString(body_input_shape) @@ -313,7 +313,7 @@ void XlaWhileOp::Compile(XlaOpKernelContext* ctx) { xla::GetTupleElement(while_result, ctx->num_outputs()); auto shape_or = builder->GetShape(token_output); OP_REQUIRES_OK(ctx, shape_or.status()); - OP_REQUIRES(ctx, xla::ShapeUtil::IsToken(shape_or.ValueOrDie()), + OP_REQUIRES(ctx, shape_or.ValueOrDie().IsToken(), errors::FailedPrecondition( "Token output is not token type: ", xla::ShapeUtil::HumanString(shape_or.ValueOrDie()))); diff --git a/tensorflow/compiler/tf2xla/literal_util.cc b/tensorflow/compiler/tf2xla/literal_util.cc index 67d0829003..749a7c3054 100644 --- a/tensorflow/compiler/tf2xla/literal_util.cc +++ b/tensorflow/compiler/tf2xla/literal_util.cc @@ -77,7 +77,7 @@ Status HostTensorsToBorrowingLiteralTuple(absl::Span host_tensors, Status CopyLiteralToHostTensor(const xla::LiteralSlice& literal, Tensor* host_tensor) { - TF_RET_CHECK(xla::ShapeUtil::IsArray(literal.shape()) && + TF_RET_CHECK(literal.shape().IsArray() && xla::ShapeUtil::ElementsIn(literal.shape()) == host_tensor->NumElements()); xla::PrimitiveType primitive_type; diff --git a/tensorflow/compiler/tf2xla/shape_util.cc b/tensorflow/compiler/tf2xla/shape_util.cc index 2116a735d7..cb04a75d95 100644 --- a/tensorflow/compiler/tf2xla/shape_util.cc +++ b/tensorflow/compiler/tf2xla/shape_util.cc @@ -27,7 +27,7 @@ namespace { Status PopulateInfeedLayoutVector(const xla::Shape& shape, std::vector* layouts) { - if (xla::ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { int64 tuple_elements = xla::ShapeUtil::TupleElementCount(shape); for (int64 i = 0; i < tuple_elements; ++i) { const xla::Shape& subshape = @@ -49,7 +49,7 @@ Status PopulateInfeedLayoutVector(const xla::Shape& shape, // Convert an XLA Shape into the equivalent TensorFlow shape. Status XLAShapeToTensorShape(const xla::Shape& shape, TensorShape* tensor_shape) { - if (xla::ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { return errors::InvalidArgument("XLA shape ", xla::ShapeUtil::HumanString(shape), " cannot be converted to a TensorShape"); diff --git a/tensorflow/compiler/tf2xla/xla_compiler_test.cc b/tensorflow/compiler/tf2xla/xla_compiler_test.cc index fe2a5f5b0c..32a4301840 100644 --- a/tensorflow/compiler/tf2xla/xla_compiler_test.cc +++ b/tensorflow/compiler/tf2xla/xla_compiler_test.cc @@ -1362,7 +1362,7 @@ TEST_F(XlaCompilerTest, TokenInputAndOutput) { TF_ASSERT_OK(compiler.CompileGraph(options, "NoOp", std::move(graph_copy), args, &result)); EXPECT_EQ(result.xla_input_shapes.size(), 1); - EXPECT_TRUE(xla::ShapeUtil::IsTuple(result.xla_output_shape)); + EXPECT_TRUE(result.xla_output_shape.IsTuple()); EXPECT_EQ(xla::ShapeUtil::TupleElementCount(result.xla_output_shape), 1); } { @@ -1380,11 +1380,11 @@ TEST_F(XlaCompilerTest, TokenInputAndOutput) { TF_ASSERT_OK(compiler.CompileGraph(options, "NoOp", std::move(graph_copy), args, &result)); EXPECT_EQ(result.xla_input_shapes.size(), 2); - EXPECT_TRUE(xla::ShapeUtil::IsToken(result.xla_input_shapes[1])); - EXPECT_TRUE(xla::ShapeUtil::IsTuple(result.xla_output_shape)); + EXPECT_TRUE(result.xla_input_shapes[1].IsToken()); + EXPECT_TRUE(result.xla_output_shape.IsTuple()); EXPECT_EQ(xla::ShapeUtil::TupleElementCount(result.xla_output_shape), 2); - EXPECT_TRUE(xla::ShapeUtil::IsToken( - xla::ShapeUtil::GetTupleElementShape(result.xla_output_shape, 1))); + EXPECT_TRUE(xla::ShapeUtil::GetTupleElementShape(result.xla_output_shape, 1) + .IsToken()); } } diff --git a/tensorflow/compiler/tf2xla/xla_helpers.cc b/tensorflow/compiler/tf2xla/xla_helpers.cc index 83ba11b3bf..00035d24b7 100644 --- a/tensorflow/compiler/tf2xla/xla_helpers.cc +++ b/tensorflow/compiler/tf2xla/xla_helpers.cc @@ -120,7 +120,7 @@ xla::XlaOp XlaHelpers::FloatLiteral(xla::XlaBuilder* b, DataType data_type, /* static */ Status XlaHelpers::ReshapeLiteral( const xla::Literal& input, absl::Span dimensions, xla::Literal* output) { - if (xla::ShapeUtil::IsTuple(input.shape())) { + if (input.shape().IsTuple()) { return errors::InvalidArgument("ReshapeLiteral does not support tuples."); } xla::Shape shape = diff --git a/tensorflow/compiler/xla/client/lib/testing.cc b/tensorflow/compiler/xla/client/lib/testing.cc index 5db9d10dff..9f520bcdad 100644 --- a/tensorflow/compiler/xla/client/lib/testing.cc +++ b/tensorflow/compiler/xla/client/lib/testing.cc @@ -34,7 +34,7 @@ namespace { // specified shape. In case of a (nested) tuple shape this is the total byte // size of all sub-shapes within the tuple. int64 DataSizeOfShape(const Shape& shape) { - if (ShapeUtil::IsArray(shape)) { + if (shape.IsArray()) { return ShapeUtil::ByteSizeOf(shape); } @@ -47,7 +47,7 @@ int64 DataSizeOfShape(const Shape& shape) { // Creates a XlaOp for an op what generates fake data with the given shape. XlaOp BuildFakeDataOpOnDevice(const Shape& shape, XlaBuilder* builder) { - if (ShapeUtil::IsArray(shape)) { + if (shape.IsArray()) { return Broadcast( ConstantLiteral(builder, LiteralUtil::One(shape.element_type())), AsInt64Slice(shape.dimensions())); diff --git a/tensorflow/compiler/xla/client/xla_builder.cc b/tensorflow/compiler/xla/client/xla_builder.cc index fc37a38813..7c72cdfeb5 100644 --- a/tensorflow/compiler/xla/client/xla_builder.cc +++ b/tensorflow/compiler/xla/client/xla_builder.cc @@ -457,18 +457,18 @@ XlaOp XlaBuilder::TernaryOp(HloOpcode triop, const XlaOp& lhs, const XlaOp& rhs, XlaOp updated_lhs = lhs; XlaOp updated_rhs = rhs; XlaOp updated_ehs = ehs; - if (!ShapeUtil::IsTuple(shape)) { - if (!ShapeUtil::IsTuple(lhs_shape) && + if (!shape.IsTuple()) { + if (!lhs_shape.IsTuple() && !ShapeUtil::SameDimensions(shape, lhs_shape)) { // lhs is being implicitly broadcasted. Change to explicit. TF_ASSIGN_OR_RETURN(updated_lhs, AddBroadcastSequence(shape, lhs)); } - if (!ShapeUtil::IsTuple(rhs_shape) && + if (!rhs_shape.IsTuple() && !ShapeUtil::SameDimensions(shape, rhs_shape)) { // rhs is being implicitly broadcasted. Change to explicit. TF_ASSIGN_OR_RETURN(updated_rhs, AddBroadcastSequence(shape, rhs)); } - if (!ShapeUtil::IsTuple(ehs_shape) && + if (!ehs_shape.IsTuple() && !ShapeUtil::SameDimensions(shape, ehs_shape)) { // ehs is being implicitly broadcasted. Change to explicit. TF_ASSIGN_OR_RETURN(updated_ehs, AddBroadcastSequence(shape, ehs)); @@ -807,10 +807,9 @@ XlaOp XlaBuilder::Select(const XlaOp& pred, const XlaOp& on_true, return ReportErrorOrReturn([&]() -> StatusOr { TF_ASSIGN_OR_RETURN(const Shape& true_shape, GetShape(on_true)); TF_ASSIGN_OR_RETURN(const Shape& false_shape, GetShape(on_false)); - TF_RET_CHECK(ShapeUtil::IsTuple(true_shape) == - ShapeUtil::IsTuple(false_shape)); - HloOpcode opcode = ShapeUtil::IsTuple(true_shape) ? HloOpcode::kTupleSelect - : HloOpcode::kSelect; + TF_RET_CHECK(true_shape.IsTuple() == false_shape.IsTuple()); + HloOpcode opcode = + true_shape.IsTuple() ? HloOpcode::kTupleSelect : HloOpcode::kSelect; return TernaryOp(opcode, pred, on_true, on_false); }); } @@ -834,7 +833,7 @@ XlaOp XlaBuilder::GetTupleElement(const XlaOp& tuple_data, int64 index) { return ReportErrorOrReturn([&]() -> StatusOr { HloInstructionProto instr; TF_ASSIGN_OR_RETURN(const Shape& tuple_shape, GetShape(tuple_data)); - if (!ShapeUtil::IsTuple(tuple_shape)) { + if (!tuple_shape.IsTuple()) { return InvalidArgument( "Operand to GetTupleElement() is not a tuple; got %s", ShapeUtil::HumanString(tuple_shape)); @@ -1149,7 +1148,7 @@ XlaOp XlaBuilder::Infeed(const Shape& shape, const string& config) { *instr.mutable_shape() = infeed_instruction_shape.ToProto(); instr.set_infeed_config(config); - if (ShapeUtil::IsArray(shape) && sharding() && + if (shape.IsArray() && sharding() && sharding()->type() == OpSharding::Type::OpSharding_Type_OTHER) { // TODO(b/110793772): Support tiled array-shaped infeeds. return InvalidArgument( @@ -1225,7 +1224,7 @@ XlaOp XlaBuilder::InfeedWithToken(const XlaOp& token, const Shape& shape, *instr.mutable_shape() = infeed_instruction_shape.ToProto(); instr.set_infeed_config(config); - if (ShapeUtil::IsArray(shape) && sharding() && + if (shape.IsArray() && sharding() && sharding()->type() == OpSharding::Type::OpSharding_Type_OTHER) { // TODO(b/110793772): Support tiled array-shaped infeeds. return InvalidArgument( @@ -1338,7 +1337,7 @@ XlaOp XlaBuilder::AfterAll(absl::Span tokens) { for (int i = 0; i < tokens.size(); ++i) { const XlaOp& operand = tokens[i]; TF_ASSIGN_OR_RETURN(const Shape& operand_shape, GetShape(operand)); - if (!ShapeUtil::IsToken(operand_shape)) { + if (!operand_shape.IsToken()) { return InvalidArgument( "All operands to AfterAll must be tokens; operand %d has shape %s", i, ShapeUtil::HumanString(operand_shape)); @@ -2291,7 +2290,7 @@ XlaOp XlaBuilder::SendToHost(const XlaOp& operand, const XlaOp& token, ShapeUtil::HumanStringWithLayout(operand_shape)); } // TODO(b/111544877): Support tuple shapes. - if (!ShapeUtil::IsArray(operand_shape)) { + if (!operand_shape.IsArray()) { return InvalidArgument("SendToHost only supports array shapes, shape: %s", ShapeUtil::HumanString(operand_shape)); } @@ -2331,7 +2330,7 @@ XlaOp XlaBuilder::RecvFromHost(const XlaOp& token, const Shape& shape, } // TODO(b/111544877): Support tuple shapes. - if (!ShapeUtil::IsArray(shape)) { + if (!shape.IsArray()) { return InvalidArgument( "RecvFromHost only supports array shapes, shape: %s", ShapeUtil::HumanString(shape)); diff --git a/tensorflow/compiler/xla/layout_util.cc b/tensorflow/compiler/xla/layout_util.cc index 0f07f123a8..42649d6692 100644 --- a/tensorflow/compiler/xla/layout_util.cc +++ b/tensorflow/compiler/xla/layout_util.cc @@ -101,13 +101,13 @@ Layout CreateDefaultLayoutForRank(int64 rank) { } // namespace /* static */ Layout LayoutUtil::GetDefaultLayoutForShape(const Shape& shape) { - if (ShapeUtil::IsOpaque(shape) || ShapeUtil::IsToken(shape)) { + if (shape.IsOpaque() || shape.IsToken()) { // Opaque and token types have empty layouts. return Layout(); } // A Layout proto corresponds to a single array, not a tuple. - CHECK(ShapeUtil::IsArray(shape)); + CHECK(shape.IsArray()); return CreateDefaultLayoutForRank(shape.dimensions_size()); } @@ -128,13 +128,13 @@ Layout CreateDefaultLayoutForRank(int64 rank) { } /* static */ void LayoutUtil::SetToDefaultLayout(Shape* shape) { - if (ShapeUtil::IsTuple(*shape)) { + if (shape->IsTuple()) { // Tuple shape. for (auto& element_shape : *shape->mutable_tuple_shapes()) { SetToDefaultLayout(&element_shape); } shape->clear_layout(); - } else if (ShapeUtil::IsArray(*shape)) { + } else if (shape->IsArray()) { shape->mutable_layout()->set_format(DENSE); auto* minor_to_major = shape->mutable_layout()->mutable_minor_to_major(); minor_to_major->resize(shape->dimensions_size(), 0); @@ -160,7 +160,7 @@ Layout CreateDefaultLayoutForRank(int64 rank) { /* static */ Status LayoutUtil::ValidateLayoutInShape( const Shape& shape, bool allow_missing_layouts) { - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { // Tuple shape. if (shape.has_layout()) { return InvalidArgument("tuple should not have a layout field"); @@ -170,7 +170,7 @@ Layout CreateDefaultLayoutForRank(int64 rank) { ValidateLayoutInShape(element_shape, allow_missing_layouts)); } return Status::OK(); - } else if (ShapeUtil::IsArray(shape)) { + } else if (shape.IsArray()) { if (!shape.has_layout()) { if (allow_missing_layouts) { return Status::OK(); @@ -192,11 +192,11 @@ Layout CreateDefaultLayoutForRank(int64 rank) { /* static */ Status LayoutUtil::ValidateLayoutForShape(const Layout& layout, const Shape& shape) { - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { return InvalidArgument("a single Layout is not valid for tuple shapes"); } - if (!ShapeUtil::IsArray(shape)) { + if (!shape.IsArray()) { if (layout.minor_to_major_size() != 0) { return InvalidArgument( "shape of primitive type %s should not have a non-trivial layout", @@ -255,8 +255,7 @@ Layout CreateDefaultLayoutForRank(int64 rank) { } /* static */ bool LayoutUtil::IsDenseArray(const Shape& shape) { - return ShapeUtil::IsArray(shape) && shape.has_layout() && - IsDense(shape.layout()); + return shape.IsArray() && shape.has_layout() && IsDense(shape.layout()); } /* static */ bool LayoutUtil::IsDense(const Layout& layout) { @@ -276,8 +275,7 @@ Layout CreateDefaultLayoutForRank(int64 rank) { } /* static */ bool LayoutUtil::IsSparseArray(const Shape& shape) { - return ShapeUtil::IsArray(shape) && shape.has_layout() && - IsSparse(shape.layout()); + return shape.IsArray() && shape.has_layout() && IsSparse(shape.layout()); } /* static */ bool LayoutUtil::IsSparse(const Layout& layout) { @@ -290,11 +288,11 @@ Layout CreateDefaultLayoutForRank(int64 rank) { } /* static */ bool LayoutUtil::HasLayout(const Shape& shape) { - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { // Tuple shape: all subshapes must have a layout. return std::all_of(shape.tuple_shapes().begin(), shape.tuple_shapes().end(), [](const Shape& s) { return HasLayout(s); }); - } else if (!ShapeUtil::IsArray(shape)) { + } else if (!shape.IsArray()) { // Opaque, token types etc. ignore layout. return true; } @@ -360,11 +358,11 @@ namespace { // Internal helper for recursively copying layouts. Status CopyLayoutInternal(const Shape& src, Shape* dst) { - if (ShapeUtil::IsTuple(src) != ShapeUtil::IsTuple(*dst)) { + if (src.IsTuple() != dst->IsTuple()) { return InvalidArgument( "cannot copy layout from shape: shape structure differs"); } - if (ShapeUtil::IsTuple(src)) { + if (src.IsTuple()) { if (ShapeUtil::TupleElementCount(src) != ShapeUtil::TupleElementCount(*dst)) { return InvalidArgument( @@ -398,9 +396,9 @@ Status LayoutUtil::CopyLayoutBetweenShapes(const Shape& src, Shape* dst) { /* static */ bool LayoutUtil::LayoutsInShapesEqual(const Shape& lhs, const Shape& rhs) { - if (ShapeUtil::IsTuple(lhs)) { - if (!ShapeUtil::IsTuple(rhs) || ShapeUtil::TupleElementCount(lhs) != - ShapeUtil::TupleElementCount(rhs)) { + if (lhs.IsTuple()) { + if (!rhs.IsTuple() || ShapeUtil::TupleElementCount(lhs) != + ShapeUtil::TupleElementCount(rhs)) { return false; } for (int i = 0; i < ShapeUtil::TupleElementCount(lhs); ++i) { @@ -409,7 +407,7 @@ Status LayoutUtil::CopyLayoutBetweenShapes(const Shape& src, Shape* dst) { } } return true; - } else if (ShapeUtil::IsArray(lhs)) { + } else if (lhs.IsArray()) { return lhs.rank() == rhs.rank() && LayoutUtil::Equal(lhs.layout(), rhs.layout()); } else { diff --git a/tensorflow/compiler/xla/literal.cc b/tensorflow/compiler/xla/literal.cc index 3b596078b5..6c44189930 100644 --- a/tensorflow/compiler/xla/literal.cc +++ b/tensorflow/compiler/xla/literal.cc @@ -107,7 +107,7 @@ Literal::Literal(const Shape& shape) : Literal(shape, /*allocate_arrays=*/true) {} void Literal::SetPiece(const Shape& shape, Piece* piece, bool allocate_arrays) { - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { for (int i = 0; i < ShapeUtil::TupleElementCount(shape); ++i) { const Shape& subshape = shape.tuple_shapes(i); @@ -118,7 +118,7 @@ void Literal::SetPiece(const Shape& shape, Piece* piece, bool allocate_arrays) { piece->emplace_back(std::move(child_piece)); } - } else if (ShapeUtil::IsArray(shape)) { + } else if (shape.IsArray()) { if (allocate_arrays) { if (LayoutUtil::IsSparseArray(shape)) { // For sparse arrays, the buffer must be of the size of the maximum @@ -187,7 +187,7 @@ Literal LiteralBase::CreateFromShape(const Shape& shape) { Literal literal(shape); literal.root_piece_->ForEachMutableSubpiece( [&](const ShapeIndex& index, Piece* piece) { - if (ShapeUtil::IsArray(piece->subshape())) { + if (piece->subshape().IsArray()) { memset(piece->untyped_data(), 0, piece->size_bytes()); } }); @@ -311,7 +311,7 @@ Status MutableLiteralBase::CopyElementFrom(const LiteralSlice& src_literal, proto_element = &proto_element->tuple_literals(i); } - if (ShapeUtil::IsTuple(piece->subshape())) { + if (piece->subshape().IsTuple()) { if (proto_element->tuple_literals_size() != ShapeUtil::TupleElementCount(piece->subshape())) { return InvalidArgument( @@ -325,7 +325,7 @@ Status MutableLiteralBase::CopyElementFrom(const LiteralSlice& src_literal, return Status::OK(); } - CHECK(ShapeUtil::IsArray(piece->subshape())); + CHECK(piece->subshape().IsArray()); TF_RETURN_IF_ERROR(piece->CopyFromProto(*proto_element)); return Status::OK(); @@ -335,7 +335,7 @@ Status MutableLiteralBase::CopyElementFrom(const LiteralSlice& src_literal, } std::vector Literal::DecomposeTuple() { - CHECK(ShapeUtil::IsTuple(shape())); + CHECK(shape().IsTuple()); std::vector elements; for (int i = 0; i < ShapeUtil::TupleElementCount(shape()); ++i) { elements.push_back(Literal(ShapeUtil::GetSubshape(shape(), {i}), @@ -437,7 +437,7 @@ Status MutableLiteralBase::CopyFrom(const LiteralSlice& src_literal, } return root_piece_->ForEachMutableSubpieceWithStatus( [&](const ShapeIndex& index, Piece* piece) { - if (!ShapeUtil::IsArray(piece->subshape())) { + if (!piece->subshape().IsArray()) { return Status::OK(); } @@ -476,7 +476,7 @@ Status Literal::MoveFrom(Literal&& src_literal, src_literal.root_piece_->ForEachSubpiece( [&](const ShapeIndex& src_index, const Piece& src_piece) { - if (!ShapeUtil::IsArray(src_piece.subshape())) { + if (!src_piece.subshape().IsArray()) { return; } @@ -503,8 +503,8 @@ Status MutableLiteralBase::CopySliceFrom(const LiteralSlice& src_literal, absl::Span src_base, absl::Span dest_base, absl::Span copy_size) { - TF_RET_CHECK(ShapeUtil::IsArray(shape())) << ShapeUtil::HumanString(shape()); - TF_RET_CHECK(ShapeUtil::IsArray(src_literal.shape())) + TF_RET_CHECK(shape().IsArray()) << ShapeUtil::HumanString(shape()); + TF_RET_CHECK(src_literal.shape().IsArray()) << ShapeUtil::HumanString(src_literal.shape()); TF_RET_CHECK(ShapeUtil::SameElementType(src_literal.shape(), shape())); @@ -561,7 +561,7 @@ Status MutableLiteralBase::CopySliceFrom(const LiteralSlice& src_literal, } void MutableLiteralBase::PopulateR1(const tensorflow::core::Bitmap& values) { - CHECK(ShapeUtil::IsArray(shape())); + CHECK(shape().IsArray()); CHECK_EQ(shape().rank(), 1); CHECK_EQ(element_count(), values.bits()); CHECK_EQ(shape().element_type(), PRED); @@ -591,7 +591,7 @@ Literal LiteralBase::Relayout(const Shape& shape_with_layout) const { ShapeUtil::ForEachSubshape( result.shape(), [this, &result](const Shape& subshape, const ShapeIndex& index) { - if (ShapeUtil::IsArray(subshape)) { + if (subshape.IsArray()) { TF_CHECK_OK(result.CopyFrom(*this, /*dest_shape_index=*/index, /*src_shape_index=*/index)); @@ -602,7 +602,7 @@ Literal LiteralBase::Relayout(const Shape& shape_with_layout) const { StatusOr LiteralBase::Broadcast( const Shape& result_shape, absl::Span dimensions) const { - if (!ShapeUtil::IsArray(shape())) { + if (!shape().IsArray()) { return InvalidArgument("Broadcast only supports arrays."); } @@ -642,7 +642,7 @@ StatusOr LiteralBase::Broadcast( StatusOr LiteralBase::Reshape( absl::Span dimensions) const { - if (!ShapeUtil::IsArray(shape())) { + if (!shape().IsArray()) { return InvalidArgument("Reshape does not support tuples."); } Literal output; @@ -669,7 +669,7 @@ StatusOr LiteralBase::Reshape( } Literal LiteralBase::Transpose(absl::Span permutation) const { - CHECK(ShapeUtil::IsArray(shape())) << "Tuple is not supported for transpose"; + CHECK(shape().IsArray()) << "Tuple is not supported for transpose"; CHECK(IsPermutation(permutation, shape().rank())) << "Given permutation is not a permutation of dimension numbers"; // To transpose the array, we just permute the dimensions and layout, and @@ -723,7 +723,7 @@ Literal LiteralBase::SliceInternal( Literal LiteralBase::Slice(absl::Span start_indices, absl::Span limit_indices) const { - CHECK(ShapeUtil::IsArray(shape())) << "tuple is not supported for slice"; + CHECK(shape().IsArray()) << "tuple is not supported for slice"; DimensionVector result_dimensions; for (int64 dnum = 0; dnum < shape().rank(); ++dnum) { @@ -904,7 +904,7 @@ size_t LiteralBase::Hash() const { ShapeUtil::ForEachSubshape( shape(), [&](const Shape& subshape, const ShapeIndex& index) { - if (!ShapeUtil::IsArray(subshape)) { + if (!subshape.IsArray()) { return; } @@ -1152,10 +1152,10 @@ void ToStringHelper(const LiteralBase& literal, const ShapeIndex& shape_index, const Shape& subshape = ShapeUtil::GetSubshape(literal.shape(), shape_index); CHECK(LayoutUtil::HasLayout(literal.shape())); CHECK(LayoutUtil::HasLayout(subshape)); - if (ShapeUtil::IsTuple(subshape)) { + if (subshape.IsTuple()) { TupleToStringHelper(literal, shape_index, print_shape, print_layout, pieces); - } else if (ShapeUtil::IsToken(subshape)) { + } else if (subshape.IsToken()) { pieces->push_back("token"); } else if (LayoutUtil::IsSparseArray(subshape)) { SparseArrayToStringHelper(literal, subshape, print_shape, print_layout, @@ -1215,7 +1215,7 @@ namespace { template Literal ConvertBetweenNativeTypesWithConverter(const LiteralBase& src_literal, const ConverterType& converter) { - CHECK(ShapeUtil::IsArray(src_literal.shape())); + CHECK(src_literal.shape().IsArray()); Literal result_literal(ShapeUtil::ChangeElementType( src_literal.shape(), primitive_util::NativeToPrimitiveType())); @@ -1276,7 +1276,7 @@ BitcastBetweenNativeTypes(const LiteralBase& src_literal) { template Literal ConvertToC64(const LiteralBase& src_literal) { - CHECK(ShapeUtil::IsArray(src_literal.shape())); + CHECK(src_literal.shape().IsArray()); Literal result_literal( ShapeUtil::ChangeElementType(src_literal.shape(), C64)); using NativeSrcT = @@ -1346,7 +1346,7 @@ StatusOr ConvertIfDestTypeMatches(const LiteralBase& src_literal, StatusOr ConvertSwitch(const LiteralBase& literal, PrimitiveType primitive_dest_type, bool bitcast) { - TF_RET_CHECK(ShapeUtil::IsArray(literal.shape())); + TF_RET_CHECK(literal.shape().IsArray()); if (literal.shape().element_type() == primitive_dest_type) { return literal.Clone(); } @@ -1399,7 +1399,7 @@ StatusOr LiteralBase::BitcastConvert( } StatusOr LiteralBase::ConvertToShape(const Shape& dest_shape) const { - if (!ShapeUtil::IsTuple(dest_shape)) { + if (!dest_shape.IsTuple()) { return Convert(dest_shape.element_type()); } std::vector elements; @@ -1494,7 +1494,7 @@ bool LiteralBase::operator==(const LiteralBase& other) const { return root_piece().ForEachSubpieceWithBool( [&](const ShapeIndex& index, const Piece& piece) { - if (!ShapeUtil::IsArray(piece.subshape())) { + if (!piece.subshape().IsArray()) { return true; } @@ -1524,7 +1524,7 @@ static bool AllElementsEqualValue(absl::Span data, bool LiteralBase::IsAll(int8 value) const { return root_piece().ForEachSubpieceWithBool([&](const ShapeIndex& index, const Piece& piece) { - if (!ShapeUtil::IsArray(piece.subshape())) { + if (!piece.subshape().IsArray()) { return true; } @@ -1592,7 +1592,7 @@ bool LiteralBase::IsAll(int8 value) const { bool LiteralBase::IsAllFloat(float value) const { return root_piece().ForEachSubpieceWithBool( [&](const ShapeIndex& index, const Piece& piece) { - if (!ShapeUtil::IsArray(piece.subshape())) { + if (!piece.subshape().IsArray()) { return true; } @@ -1632,7 +1632,7 @@ bool LiteralBase::IsAllComplex(complex64 value) const { bool LiteralBase::IsAllFirst() const { return root_piece().ForEachSubpieceWithBool( [&](const ShapeIndex& index, const Piece& piece) { - if (!ShapeUtil::IsArray(piece.subshape())) { + if (!piece.subshape().IsArray()) { return true; } @@ -1716,7 +1716,7 @@ bool LiteralBase::IsAllFirst() const { } bool LiteralBase::IsR1Iota() const { - if (!ShapeUtil::IsArray(shape())) { + if (!shape().IsArray()) { return false; } @@ -1771,7 +1771,7 @@ bool LiteralBase::IsR1Iota() const { } bool LiteralBase::IsZero(absl::Span indices) const { - CHECK(ShapeUtil::IsArray(shape())); + CHECK(shape().IsArray()); switch (shape().element_type()) { case U8: return Get(indices) == 0; @@ -1894,12 +1894,12 @@ void LiteralBase::Piece::WriteToProto(LiteralProto* proto) const { } const void* LiteralBase::Piece::untyped_data() const { - CHECK(ShapeUtil::IsArray(subshape())) << ShapeUtil::HumanString(subshape()); + CHECK(subshape().IsArray()) << ShapeUtil::HumanString(subshape()); return buffer(); } void* LiteralBase::Piece::untyped_data() { - CHECK(ShapeUtil::IsArray(subshape())) << ShapeUtil::HumanString(subshape()); + CHECK(subshape().IsArray()) << ShapeUtil::HumanString(subshape()); return buffer(); } @@ -2060,7 +2060,7 @@ int64 LiteralBase::size_bytes(const ShapeIndex& shape_index) const { } string LiteralBase::GetR1U8AsString() const { - CHECK(ShapeUtil::IsArray(shape())); + CHECK(shape().IsArray()); CHECK_EQ(shape().rank(), 1); CHECK_EQ(shape().element_type(), U8); return string(absl::bit_cast(data().data()), @@ -2075,7 +2075,7 @@ void MutableBorrowingLiteral::CopyPieceSubtree(const Shape& shape, << ShapeUtil::HumanString(src_piece->subshape()) << "dest_piece has shape: " << ShapeUtil::HumanString(dest_piece->subshape()); - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { for (int i = 0; i < ShapeUtil::TupleElementCount(shape); ++i) { const Shape& subshape = shape.tuple_shapes(i); @@ -2086,7 +2086,7 @@ void MutableBorrowingLiteral::CopyPieceSubtree(const Shape& shape, dest_piece->emplace_back(std::move(child_piece)); } - } else if (ShapeUtil::IsArray(shape)) { + } else if (shape.IsArray()) { dest_piece->set_buffer(src_piece->buffer()); } else { // If the shape is neither an array nor tuple, then it must be @@ -2162,7 +2162,7 @@ MutableBorrowingLiteral::MutableBorrowingLiteral(const char* src_buf_ptr, : MutableLiteralBase() { shape_ = absl::make_unique(shape); CHECK(LayoutUtil::HasLayout(*shape_)); - CHECK(!ShapeUtil::IsTuple(*shape_)); + CHECK(!shape_->IsTuple()); root_piece_ = new Piece(); root_piece_->set_buffer(const_cast(src_buf_ptr)); @@ -2189,14 +2189,14 @@ LiteralSlice::LiteralSlice(const LiteralBase& literal, : LiteralBase(), root_piece_(&literal.piece(view_root)) {} void BorrowingLiteral::BuildPieceSubtree(const Shape& shape, Piece* piece) { - CHECK(ShapeUtil::IsTuple(shape)); + CHECK(shape.IsTuple()); for (int i = 0; i < ShapeUtil::TupleElementCount(shape); ++i) { const Shape& subshape = shape.tuple_shapes(i); auto child_piece = Piece(); child_piece.set_subshape(&subshape); - if (ShapeUtil::IsTuple(subshape)) { + if (subshape.IsTuple()) { BuildPieceSubtree(subshape, &child_piece); } @@ -2206,7 +2206,7 @@ void BorrowingLiteral::BuildPieceSubtree(const Shape& shape, Piece* piece) { BorrowingLiteral::BorrowingLiteral(const char* src_buf_ptr, const Shape& shape) : LiteralBase(), shape_(absl::make_unique(shape)) { - CHECK(ShapeUtil::IsArray(*shape_)); + CHECK(shape_->IsArray()); CHECK(LayoutUtil::HasLayout(*shape_)); root_piece_ = Piece(); @@ -2217,7 +2217,7 @@ BorrowingLiteral::BorrowingLiteral(const char* src_buf_ptr, const Shape& shape) BorrowingLiteral::BorrowingLiteral(absl::Span src_buf_ptrs, const Shape& shape) : LiteralBase(), shape_(absl::make_unique(shape)) { - CHECK(ShapeUtil::IsTuple(*shape_)); + CHECK(shape_->IsTuple()); CHECK(!ShapeUtil::IsNestedTuple(*shape_)); CHECK_EQ(src_buf_ptrs.size(), ShapeUtil::TupleElementCount(*shape_)); root_piece_ = Piece(); @@ -2226,7 +2226,7 @@ BorrowingLiteral::BorrowingLiteral(absl::Span src_buf_ptrs, for (int i = 0; i < src_buf_ptrs.size(); ++i) { const auto& src_shape = shape_->tuple_shapes(i); - CHECK(ShapeUtil::IsArray(src_shape)); + CHECK(src_shape.IsArray()); root_piece_.child(i).set_buffer(const_cast(src_buf_ptrs[i])); } } diff --git a/tensorflow/compiler/xla/literal.h b/tensorflow/compiler/xla/literal.h index 67db56c2ef..041151fda1 100644 --- a/tensorflow/compiler/xla/literal.h +++ b/tensorflow/compiler/xla/literal.h @@ -867,7 +867,7 @@ class BorrowingLiteral : public LiteralBase { template absl::Span LiteralBase::Piece::data() const { - DCHECK(ShapeUtil::IsArray(subshape())) << ShapeUtil::HumanString(subshape()); + DCHECK(subshape().IsArray()) << ShapeUtil::HumanString(subshape()); DCHECK_EQ(subshape().element_type(), primitive_util::NativeToPrimitiveType()) << "Attempting to access " @@ -880,7 +880,7 @@ absl::Span LiteralBase::Piece::data() const { template absl::Span LiteralBase::Piece::data() { - DCHECK(ShapeUtil::IsArray(subshape())) << ShapeUtil::HumanString(subshape()); + DCHECK(subshape().IsArray()) << ShapeUtil::HumanString(subshape()); DCHECK_EQ(subshape().element_type(), primitive_util::NativeToPrimitiveType()) << "Attempting to access " @@ -985,7 +985,7 @@ void LiteralBase::EachCell( template inline void MutableLiteralBase::PopulateR1(absl::Span values) { - CHECK(ShapeUtil::IsArray(shape())); + CHECK(shape().IsArray()); CHECK_EQ(shape().rank(), 1); CHECK_EQ(ShapeUtil::ElementsIn(shape()), values.size()); CHECK_EQ(shape().element_type(), @@ -997,7 +997,7 @@ inline void MutableLiteralBase::PopulateR1(absl::Span values) { template void MutableLiteralBase::PopulateR2( std::initializer_list> values) { - CHECK(ShapeUtil::IsArray(shape())); + CHECK(shape().IsArray()); CHECK_EQ(shape().rank(), 2); CHECK_EQ(shape().element_type(), primitive_util::NativeToPrimitiveType()); @@ -1021,7 +1021,7 @@ void MutableLiteralBase::PopulateR2( template void MutableLiteralBase::PopulateFromArray(const Array& values) { - CHECK(ShapeUtil::IsArray(shape())); + CHECK(shape().IsArray()); CHECK_EQ(shape().element_type(), primitive_util::NativeToPrimitiveType()); CHECK_EQ(shape().rank(), values.num_dimensions()); @@ -1129,7 +1129,7 @@ Status MutableLiteralBase::PopulateParallel(const FnType& generator) { template void MutableLiteralBase::PopulateWithValue(NativeT value) { - CHECK(ShapeUtil::IsArray(shape())); + CHECK(shape().IsArray()); CHECK_EQ(shape().element_type(), primitive_util::NativeToPrimitiveType()); for (NativeT& element : data()) { diff --git a/tensorflow/compiler/xla/literal_comparison.cc b/tensorflow/compiler/xla/literal_comparison.cc index 91316b77f6..f4376d66af 100644 --- a/tensorflow/compiler/xla/literal_comparison.cc +++ b/tensorflow/compiler/xla/literal_comparison.cc @@ -172,14 +172,14 @@ Status Equal(LiteralSlice expected, LiteralSlice actual, // Gets the total element count. For tuples, this is not the count of tuple // elements, but the sum of elements of each tuple element. int64 RecursiveElementCount(const Shape& shape) { - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { const int64 tuple_elements = ShapeUtil::TupleElementCount(shape); int64 total = 0; for (int64 i = 0; i < tuple_elements; ++i) { total += RecursiveElementCount(ShapeUtil::GetTupleElementShape(shape, i)); } return total; - } else if (ShapeUtil::IsArray(shape)) { + } else if (shape.IsArray()) { return ShapeUtil::ElementsIn(shape); } else { return 0; @@ -311,7 +311,7 @@ class NearComparator { // If the shapes mismatch, we simply fail the expectation instead of // printing out data, as it's a type error rather than a value error. TF_RETURN_IF_ERROR(EqualShapes(expected_.shape(), actual_.shape())); - if (!ShapeUtil::IsArray(expected_.shape())) { + if (!expected_.shape().IsArray()) { return InvalidArgument("Expected array shape; got %s.", ShapeUtil::HumanString(expected_.shape())); } @@ -685,7 +685,7 @@ Status NearHelper(const LiteralSlice& expected, const LiteralSlice& actual, const ShapeIndex& shape_index) { TF_RETURN_IF_ERROR(EqualShapes(expected.shape(), actual.shape())); - if (ShapeUtil::IsTuple(expected.shape())) { + if (expected.shape().IsTuple()) { Status return_status; for (int64 i = 0; i < ShapeUtil::TupleElementCount(expected.shape()); ++i) { const auto expected_element = LiteralSlice(expected, {i}); @@ -761,7 +761,7 @@ Status EqualShapes(const Shape& expected, const Shape& actual) { ShapeUtil::HumanString(expected), ShapeUtil::HumanString(actual)); } - if (ShapeUtil::IsTuple(expected)) { + if (expected.IsTuple()) { if (ShapeUtil::TupleElementCount(expected) != ShapeUtil::TupleElementCount(actual)) { return InvalidArgument( @@ -776,7 +776,7 @@ Status EqualShapes(const Shape& expected, const Shape& actual) { return AppendStatus(result, StrCat("mismatch in tuple index", i)); } } - } else if (ShapeUtil::IsArray(expected)) { + } else if (expected.IsArray()) { if (expected.rank() != actual.rank()) { return InvalidArgument("want rank of %s got rank of %s", ShapeUtil::HumanString(expected), diff --git a/tensorflow/compiler/xla/literal_test.cc b/tensorflow/compiler/xla/literal_test.cc index d8c7141cac..0a71cfd5ab 100644 --- a/tensorflow/compiler/xla/literal_test.cc +++ b/tensorflow/compiler/xla/literal_test.cc @@ -1642,7 +1642,7 @@ TEST_F(LiteralUtilTest, MoveIntoTuple) { LiteralUtil::MakeTuple({&inner_elements[0], &inner_elements[1]})); Literal literal = Literal::MoveIntoTuple(absl::MakeSpan(elements)); - ASSERT_TRUE(ShapeUtil::IsTuple(literal.shape())); + ASSERT_TRUE(literal.shape().IsTuple()); ASSERT_EQ(ShapeUtil::TupleElementCount(literal.shape()), 3); EXPECT_EQ(literal.Get({}, /*shape_index=*/{0}), 1.0); @@ -1659,7 +1659,7 @@ TEST_F(LiteralUtilTest, MoveIntoTuple) { TEST_F(LiteralUtilTest, MoveIntoEmptyTuple) { Literal literal = Literal::MoveIntoTuple({}); - ASSERT_TRUE(ShapeUtil::IsTuple(literal.shape())); + ASSERT_TRUE(literal.shape().IsTuple()); EXPECT_EQ(ShapeUtil::TupleElementCount(literal.shape()), 0); } diff --git a/tensorflow/compiler/xla/literal_util.cc b/tensorflow/compiler/xla/literal_util.cc index bb5e5e6100..67eab1bff8 100644 --- a/tensorflow/compiler/xla/literal_util.cc +++ b/tensorflow/compiler/xla/literal_util.cc @@ -62,7 +62,7 @@ Literal ConvertType(LiteralSlice literal) { ShapeUtil::ForEachSubshape( literal.shape(), [&](const Shape& subshape, const ShapeIndex& shape_index) { - if (ShapeUtil::IsArray(subshape)) { + if (subshape.IsArray()) { if (subshape.element_type() == primitive_util::NativeToPrimitiveType()) { auto src = literal.data(shape_index); @@ -355,7 +355,7 @@ Literal ConvertType(LiteralSlice literal) { /* static */ Literal LiteralUtil::GetFirstScalarLiteral( const LiteralSlice& literal) { - CHECK(ShapeUtil::IsArray(literal.shape())); + CHECK(literal.shape().IsArray()); CHECK_GT(ShapeUtil::ElementsIn(literal.shape()), 0); switch (literal.shape().element_type()) { case PRED: diff --git a/tensorflow/compiler/xla/python/local_computation_builder.cc b/tensorflow/compiler/xla/python/local_computation_builder.cc index 657a09f92a..b0f0e9e570 100644 --- a/tensorflow/compiler/xla/python/local_computation_builder.cc +++ b/tensorflow/compiler/xla/python/local_computation_builder.cc @@ -1041,7 +1041,7 @@ StatusOr DestructureLocalShapedBufferTuple( LocalShapedBuffer* local_shaped_buffer) { const Shape tuple_shape = local_shaped_buffer->shape(); - if (!ShapeUtil::IsTuple(tuple_shape)) { + if (!tuple_shape.IsTuple()) { return InvalidArgument( "Attemped to destructure a LocalShapedBuffer that did not have a tuple " "shape; shape: %s", @@ -1088,7 +1088,7 @@ StatusOr DestructureXrtAllocationTuple( XrtAllocation* allocation, const string& session_target) { const Shape& tuple_shape = allocation->shape(); - if (!ShapeUtil::IsTuple(tuple_shape)) { + if (!tuple_shape.IsTuple()) { return InvalidArgument( "Attemped to destructure a LocalShapedBuffer that did not have a tuple " "shape; shape: %s", diff --git a/tensorflow/compiler/xla/python/numpy_bridge.cc b/tensorflow/compiler/xla/python/numpy_bridge.cc index 74d2d25b4b..9c90550825 100644 --- a/tensorflow/compiler/xla/python/numpy_bridge.cc +++ b/tensorflow/compiler/xla/python/numpy_bridge.cc @@ -123,7 +123,7 @@ PyObject* PyShapeInfoFromXlaShape(const Shape& shape) { PyArray_Descr* np_dtype = PyArray_DescrFromType(np_typenum); PyObject* dimensions; - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { int num_elements = ShapeUtil::TupleElementCount(shape); dimensions = PyTuple_New(ShapeUtil::TupleElementCount(shape)); for (int i = 0; i < num_elements; ++i) { @@ -345,7 +345,7 @@ StatusOr OpMetadataFromPyObject(PyObject* o) { } PyObject* PyObjectFromXlaLiteral(const LiteralSlice& literal) { - if (ShapeUtil::IsTuple(literal.shape())) { + if (literal.shape().IsTuple()) { int num_elements = ShapeUtil::TupleElementCount(literal.shape()); PyObject* tuple = PyTuple_New(num_elements); for (int i = 0; i < num_elements; i++) { diff --git a/tensorflow/compiler/xla/service/algebraic_simplifier.cc b/tensorflow/compiler/xla/service/algebraic_simplifier.cc index 8157be1e0a..cad70a8d10 100644 --- a/tensorflow/compiler/xla/service/algebraic_simplifier.cc +++ b/tensorflow/compiler/xla/service/algebraic_simplifier.cc @@ -715,7 +715,7 @@ Status AlgebraicSimplifierVisitor::HandleConcatenate( static HloInstruction* BuildTupleConstant(HloComputation* computation, const LiteralSlice& literal) { - if (ShapeUtil::IsTuple(literal.shape())) { + if (literal.shape().IsTuple()) { std::vector elems; elems.reserve(ShapeUtil::TupleElementCount(literal.shape())); for (int i = 0; i < ShapeUtil::TupleElementCount(literal.shape()); ++i) { @@ -732,7 +732,7 @@ static HloInstruction* BuildTupleConstant(HloComputation* computation, Status AlgebraicSimplifierVisitor::HandleConstant(HloInstruction* constant) { // Tuple constants aren't directly supported by any backend. Expand them into // explicit Tuple instructions. - if (ShapeUtil::IsTuple(constant->shape())) { + if (constant->shape().IsTuple()) { return ReplaceInstruction( constant, BuildTupleConstant(computation_, constant->literal())); } @@ -1686,7 +1686,7 @@ bool OutputIsPermutationOfOperandElements(HloInstruction* instruction, case HloOpcode::kTranspose: return true; case HloOpcode::kSort: - return (!ShapeUtil::IsTuple(instruction->shape())); + return (!instruction->shape().IsTuple()); default: return false; } @@ -2437,7 +2437,7 @@ Status AlgebraicSimplifierVisitor::HandleDynamicUpdateSlice( Status AlgebraicSimplifierVisitor::HandleReduce(HloInstruction* reduce) { // TODO(b/112040122): Most of those optimizations can be done for multi-output // reduces. - if (ShapeUtil::IsTuple(reduce->shape())) { + if (reduce->shape().IsTuple()) { return Status::OK(); } diff --git a/tensorflow/compiler/xla/service/allocation_tracker.cc b/tensorflow/compiler/xla/service/allocation_tracker.cc index ef5e211646..6cb0e985e5 100644 --- a/tensorflow/compiler/xla/service/allocation_tracker.cc +++ b/tensorflow/compiler/xla/service/allocation_tracker.cc @@ -142,13 +142,13 @@ StatusOr> AllocationTracker::DeconstructTuple( // We only need to care about replica id 0 here, since the GlobalDataHandle is // the same for all buffers across replicas. const ShapedBuffer* shaped_buffer = replicated_buffers[0]; - if (!ShapeUtil::IsTuple(shaped_buffer->on_host_shape())) { + if (!shaped_buffer->on_host_shape().IsTuple()) { return InvalidArgument("global data handle %d is not a tuple", data.handle()); } // If the on-host representation is a tuple, then the on-device one should be // as well. - TF_RET_CHECK(ShapeUtil::IsTuple(shaped_buffer->on_device_shape())); + TF_RET_CHECK(shaped_buffer->on_device_shape().IsTuple()); if (ShapeUtil::IsNestedTuple(shaped_buffer->on_device_shape())) { return Unimplemented("Deconstructing nested tuples is not implemented."); diff --git a/tensorflow/compiler/xla/service/bfloat16_conversion_folding.cc b/tensorflow/compiler/xla/service/bfloat16_conversion_folding.cc index 6caef77ed0..e62d72b323 100644 --- a/tensorflow/compiler/xla/service/bfloat16_conversion_folding.cc +++ b/tensorflow/compiler/xla/service/bfloat16_conversion_folding.cc @@ -190,7 +190,7 @@ Status BFloat16ConversionFoldingVisitor::HandleAllReduce(HloInstruction* crs) { } // If the output is not a tuple, we don't need special handling. - if (!ShapeUtil::IsTuple(crs->shape())) { + if (!crs->shape().IsTuple()) { return Status::OK(); } diff --git a/tensorflow/compiler/xla/service/bfloat16_normalization.cc b/tensorflow/compiler/xla/service/bfloat16_normalization.cc index e3aefe9067..d1b14d604f 100644 --- a/tensorflow/compiler/xla/service/bfloat16_normalization.cc +++ b/tensorflow/compiler/xla/service/bfloat16_normalization.cc @@ -363,7 +363,7 @@ Status BFloat16NormalizationVisitor::DefaultAction(HloInstruction* hlo) { // TODO(b/112040122): Correctly normalize variadic reduce. if ((hlo->opcode() == HloOpcode::kSort || hlo->opcode() == HloOpcode::kAllReduce) && - ShapeUtil::IsTuple(hlo->shape())) { + hlo->shape().IsTuple()) { return HandleMultipleOutputs(hlo); } return HandleInstruction(hlo); diff --git a/tensorflow/compiler/xla/service/bfloat16_propagation.cc b/tensorflow/compiler/xla/service/bfloat16_propagation.cc index 05dd4b3e91..bab63f66d8 100644 --- a/tensorflow/compiler/xla/service/bfloat16_propagation.cc +++ b/tensorflow/compiler/xla/service/bfloat16_propagation.cc @@ -277,7 +277,7 @@ bool BFloat16Propagation::AllUsersConsumeBF16(const HloInstruction& hlo, *use.instruction, use.operand_number)) { if (use.instruction->opcode() == HloOpcode::kTuple || (use.instruction->opcode() == HloOpcode::kAllReduce && - ShapeUtil::IsTuple(use.instruction->shape()))) { + use.instruction->shape().IsTuple())) { ShapeIndex use_output_index{use.operand_number}; for (int64 i : use.operand_index) { use_output_index.push_back(i); diff --git a/tensorflow/compiler/xla/service/buffer_assignment.cc b/tensorflow/compiler/xla/service/buffer_assignment.cc index 202e45e181..6f4c1104f3 100644 --- a/tensorflow/compiler/xla/service/buffer_assignment.cc +++ b/tensorflow/compiler/xla/service/buffer_assignment.cc @@ -1036,7 +1036,7 @@ Status BufferAssigner::AssignBuffersForComputation( continue; } - if (ShapeUtil::IsTuple(buffer->shape())) { + if (buffer->shape().IsTuple()) { BufferAllocation* allocation = assignment->NewAllocation(*buffer, buffer_size); allocation->set_is_tuple(true); diff --git a/tensorflow/compiler/xla/service/buffer_liveness_test.cc b/tensorflow/compiler/xla/service/buffer_liveness_test.cc index 40825a7871..46218e6499 100644 --- a/tensorflow/compiler/xla/service/buffer_liveness_test.cc +++ b/tensorflow/compiler/xla/service/buffer_liveness_test.cc @@ -52,8 +52,8 @@ class BufferLivenessTest : public HloTestBase { // interfere. Precondition: 'a' and 'b' are array-shaped. bool InstructionsMayInterfere(const BufferLiveness& liveness, HloInstruction* a, HloInstruction* b) { - EXPECT_FALSE(ShapeUtil::IsTuple(a->shape())); - EXPECT_FALSE(ShapeUtil::IsTuple(b->shape())); + EXPECT_FALSE(a->shape().IsTuple()); + EXPECT_FALSE(b->shape().IsTuple()); return liveness.MayInterfere( GetBuffer(liveness, /*instruction=*/a, /*index=*/{}), GetBuffer(liveness, /*instruction=*/b, /*index=*/{})); @@ -66,8 +66,8 @@ class BufferLivenessTest : public HloTestBase { HloInstruction* a, HloInstruction* b, const ShapeIndex& index) { // Check that top-level shapes are tuple and tuple element shapes are equal. - EXPECT_TRUE(ShapeUtil::IsTuple(a->shape())); - EXPECT_TRUE(ShapeUtil::IsTuple(b->shape())); + EXPECT_TRUE(a->shape().IsTuple()); + EXPECT_TRUE(b->shape().IsTuple()); EXPECT_TRUE( ShapeUtil::Compatible(ShapeUtil::GetSubshape(a->shape(), index), ShapeUtil::GetSubshape(b->shape(), index))); diff --git a/tensorflow/compiler/xla/service/buffer_value.cc b/tensorflow/compiler/xla/service/buffer_value.cc index fdf822c666..b1abba2068 100644 --- a/tensorflow/compiler/xla/service/buffer_value.cc +++ b/tensorflow/compiler/xla/service/buffer_value.cc @@ -29,8 +29,8 @@ BufferValue::BufferValue(HloInstruction* instruction, const ShapeIndex& index, Id id) : id_(id) { const Shape& shape = ShapeUtil::GetSubshape(instruction->shape(), index); - is_array_ = ShapeUtil::IsArray(shape); - is_tuple_ = ShapeUtil::IsTuple(shape); + is_array_ = shape.IsArray(); + is_tuple_ = shape.IsTuple(); } BufferValue::~BufferValue() {} diff --git a/tensorflow/compiler/xla/service/copy_insertion.cc b/tensorflow/compiler/xla/service/copy_insertion.cc index df60596638..e0165d557d 100644 --- a/tensorflow/compiler/xla/service/copy_insertion.cc +++ b/tensorflow/compiler/xla/service/copy_insertion.cc @@ -522,7 +522,7 @@ class CopyRemover { // between copies added around aliased operations (kWhile) guarantees // this strict order. for (const HloValue* value_a : buffer.values()) { - if (ShapeUtil::IsToken(value_a->shape())) { + if (value_a->shape().IsToken()) { // Token values have no representation and cannot interfere. continue; } diff --git a/tensorflow/compiler/xla/service/cpu/cpu_compiler.cc b/tensorflow/compiler/xla/service/cpu/cpu_compiler.cc index ba7dcde5c3..dbab839aee 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_compiler.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_compiler.cc @@ -506,7 +506,7 @@ Status CreateHloProfilingArtifacts( auto shape_size_bytes = [](const Shape& shape) { // On the cpu, opaques are pointers. - if (ShapeUtil::IsOpaque(shape)) { + if (shape.IsOpaque()) { return static_cast(sizeof(void*)); } return ShapeUtil::ByteSizeOf(shape, sizeof(void*)); diff --git a/tensorflow/compiler/xla/service/cpu/cpu_executable.cc b/tensorflow/compiler/xla/service/cpu/cpu_executable.cc index 818b2b0d0d..412c2715b9 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_executable.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_executable.cc @@ -326,7 +326,7 @@ StatusOr CpuExecutable::ExecuteAsyncOnStreamImpl( /*static*/ int64 CpuExecutable::ShapeSizeBytes(const Shape& shape) { // On the cpu, opaques are pointers. - if (ShapeUtil::IsOpaque(shape)) { + if (shape.IsOpaque()) { return sizeof(void*); } return ShapeUtil::ByteSizeOf(shape, sizeof(void*)); diff --git a/tensorflow/compiler/xla/service/cpu/cpu_layout_assignment.cc b/tensorflow/compiler/xla/service/cpu/cpu_layout_assignment.cc index c291bf2d1b..1cb154e9ca 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_layout_assignment.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_layout_assignment.cc @@ -160,7 +160,7 @@ Status CpuLayoutAssignment::AddBackendConstraints( continue; } // Skip operands with non-array shapes. - if (!ShapeUtil::IsArray(instruction->operand(operand_no)->shape())) { + if (!instruction->operand(operand_no)->shape().IsArray()) { continue; } Shape operand_shape( @@ -175,7 +175,7 @@ Status CpuLayoutAssignment::AddBackendConstraints( } // Skip instructions which don't produce array shapes (tuples, opaque, // etc.). - if (!ShapeUtil::IsArray(instruction->shape())) { + if (!instruction->shape().IsArray()) { continue; } } diff --git a/tensorflow/compiler/xla/service/cpu/cpu_transfer_manager.cc b/tensorflow/compiler/xla/service/cpu/cpu_transfer_manager.cc index 1457582ac1..3361a5973f 100644 --- a/tensorflow/compiler/xla/service/cpu/cpu_transfer_manager.cc +++ b/tensorflow/compiler/xla/service/cpu/cpu_transfer_manager.cc @@ -97,7 +97,7 @@ Status CpuTransferManager::TransferLiteralToInfeed( VLOG(2) << "Transferring literal to infeed with shape: " << ShapeUtil::HumanString(shape); - if (!ShapeUtil::IsTuple(shape)) { + if (!shape.IsTuple()) { int64 size = GetByteSizeRequirement(shape); return TransferBufferToInfeed(executor, size, literal.untyped_data()); } @@ -178,7 +178,7 @@ CpuTransferManager::TransferBufferToInfeedInternal(se::StreamExecutor* executor, Status CpuTransferManager::TransferLiteralFromOutfeed( se::StreamExecutor* executor, const Shape& literal_shape, MutableBorrowingLiteral literal) { - if (!ShapeUtil::IsTuple(literal_shape)) { + if (!literal_shape.IsTuple()) { int64 size = GetByteSizeRequirement(literal_shape); // Note: OSS build didn't like implicit conversion from // literal_shape.dimensions() to the array slice on 2017-07-10. diff --git a/tensorflow/compiler/xla/service/cpu/ir_emission_utils.cc b/tensorflow/compiler/xla/service/cpu/ir_emission_utils.cc index 1a8bedfe6a..a8b139aec9 100644 --- a/tensorflow/compiler/xla/service/cpu/ir_emission_utils.cc +++ b/tensorflow/compiler/xla/service/cpu/ir_emission_utils.cc @@ -26,7 +26,7 @@ namespace cpu { int64 GetMinimumAlignmentForArray( const Shape& shape, const TargetMachineFeatures& target_machine_features) { - CHECK(ShapeUtil::IsArray(shape)); + CHECK(shape.IsArray()); CHECK(!LayoutUtil::HasLayout(shape) || LayoutUtil::IsDense(shape.layout())); // We don't require a layout to be set on `shape`. This only works on CPU diff --git a/tensorflow/compiler/xla/service/cpu/ir_emitter.cc b/tensorflow/compiler/xla/service/cpu/ir_emitter.cc index f29f8f8fec..169d628923 100644 --- a/tensorflow/compiler/xla/service/cpu/ir_emitter.cc +++ b/tensorflow/compiler/xla/service/cpu/ir_emitter.cc @@ -223,11 +223,11 @@ Status IrEmitter::HandleConstant(HloInstruction* constant) { } Status IrEmitter::HandleCopy(HloInstruction* copy) { - if (ShapeUtil::IsTuple(copy->shape())) { + if (copy->shape().IsTuple()) { // kCopy shallow copies a tuple so just memcpy the top-level buffer. TF_RETURN_IF_ERROR(EmitTargetAddressForOp(copy)); return EmitMemcpy(*(copy->operand(0)), *copy); - } else if (ShapeUtil::IsArray(copy->shape())) { + } else if (copy->shape().IsArray()) { // Use the elemental emitter for array shapes. return DefaultAction(copy); } @@ -316,7 +316,7 @@ Status IrEmitter::HandleTupleSelect(HloInstruction* tuple_select) { auto on_false = tuple_select->operand(2); TF_RET_CHECK(pred->shape().element_type() == PRED); TF_RET_CHECK(ShapeUtil::IsScalar(pred->shape())); - TF_RET_CHECK(ShapeUtil::IsTuple(tuple_select->shape())); + TF_RET_CHECK(tuple_select->shape().IsTuple()); TF_RETURN_IF_ERROR(EmitTargetAddressForOp(tuple_select)); llvm_ir::EmitTupleSelect(GetIrArrayFor(tuple_select), GetIrArrayFor(pred), GetEmittedValueFor(on_true), @@ -346,7 +346,7 @@ Status IrEmitter::HandleInfeed(HloInstruction* instruction) { llvm_ir::EmitTuple(GetIrArrayFor(infeed), {data_address, token_address}, &b_, module_); - if (ShapeUtil::IsTuple(data_shape)) { + if (data_shape.IsTuple()) { TF_RET_CHECK(!ShapeUtil::IsNestedTuple(data_shape)); // For a tuple, we first copy each of the internal elements to @@ -470,7 +470,7 @@ Status IrEmitter::HandleOutfeed(HloInstruction* outfeed) { const Shape& operand_shape = operand->shape(); llvm::Value* value = GetEmittedValueFor(operand); - if (!ShapeUtil::IsTuple(operand_shape)) { + if (!operand_shape.IsTuple()) { return EmitXfeedTransfer(XfeedKind::kOutfeed, operand_shape, value); } @@ -1362,7 +1362,7 @@ Status IrEmitter::HandleAllReduce(HloInstruction* crs) { assignment_.GetUniqueSlice(crs, {i})); const Shape& operand_shape = crs->operand(i)->shape(); - CHECK(ShapeUtil::IsArray(operand_shape)) + CHECK(operand_shape.IsArray()) << "Operands to all-reduce must be arrays: " << crs->ToString(); operand_ptrs.push_back(EmitBufferPointer(out_slice, operand_shape)); @@ -1724,7 +1724,7 @@ StatusOr IrEmitter::EmitVectorizedReduce( return false; } - CHECK(!ShapeUtil::IsTuple(reduce->shape())); + CHECK(!reduce->shape().IsTuple()); TF_RETURN_IF_ERROR(EmitTargetAddressForOp(reduce)); // We know we're not reducing over the most minor dimension, which means we @@ -1891,7 +1891,7 @@ StatusOr IrEmitter::EmitTargetElementLoopBodyForReduce( Status IrEmitter::HandleReduce(HloInstruction* reduce) { // TODO(b/112040122): Support variadic reduce. - if (!ShapeUtil::IsArray(reduce->shape())) { + if (!reduce->shape().IsArray()) { return Unimplemented("Variadic reduce is not supported on CPU"); } auto arg = reduce->mutable_operand(0); @@ -2267,14 +2267,13 @@ Status IrEmitter::HandleCustomCall(HloInstruction* custom_call) { TF_RETURN_IF_ERROR(EmitTargetAddressForOp(custom_call)); // Write the tuple table if the output is a tuple. - if (ShapeUtil::IsTuple(custom_call->shape())) { + if (custom_call->shape().IsTuple()) { std::vector base_ptrs; for (int i = 0; i < ShapeUtil::TupleElementCount(custom_call->shape()); ++i) { const Shape& elem_shape = ShapeUtil::GetTupleElementShape(custom_call->shape(), i); - TF_RET_CHECK(!ShapeUtil::IsTuple(elem_shape)) - << "Nested tuples not implemented"; + TF_RET_CHECK(!elem_shape.IsTuple()) << "Nested tuples not implemented"; TF_ASSIGN_OR_RETURN(const BufferAllocation::Slice slice, assignment_.GetUniqueSlice(custom_call, {i})); llvm::Value* addr = EmitBufferPointer(slice, elem_shape); @@ -2803,7 +2802,7 @@ llvm::Value* IrEmitter::EmitThreadLocalBufferPointer( llvm_ir::EmitBufferIndexingGEP(params, param_number, &b_); llvm::LoadInst* param_address_untyped = Load(param_address_offset); - if (!ShapeUtil::IsOpaque(target_shape)) { + if (!target_shape.IsOpaque()) { AttachAlignmentMetadataForLoad(param_address_untyped, target_shape); AttachDereferenceableMetadataForLoad(param_address_untyped, target_shape); diff --git a/tensorflow/compiler/xla/service/cpu/parallel_loop_emitter.cc b/tensorflow/compiler/xla/service/cpu/parallel_loop_emitter.cc index f8441c3e34..a6f4273a5a 100644 --- a/tensorflow/compiler/xla/service/cpu/parallel_loop_emitter.cc +++ b/tensorflow/compiler/xla/service/cpu/parallel_loop_emitter.cc @@ -34,7 +34,7 @@ ParallelLoopEmitter::EmitIndexAndSetExitBasicBlock(absl::string_view loop_name, llvm::Type* index_type) { CHECK_NE(index_type, nullptr); - CHECK(!ShapeUtil::IsTuple(shape_)); + CHECK(!shape_.IsTuple()); CHECK(!ShapeUtil::IsScalar(shape_)); llvm_ir::ForLoopNest loop_nest(loop_name, b_); diff --git a/tensorflow/compiler/xla/service/cpu/parallel_task_assignment.cc b/tensorflow/compiler/xla/service/cpu/parallel_task_assignment.cc index ede7f433ca..3b423f6391 100644 --- a/tensorflow/compiler/xla/service/cpu/parallel_task_assignment.cc +++ b/tensorflow/compiler/xla/service/cpu/parallel_task_assignment.cc @@ -150,7 +150,7 @@ int64 ParallelTaskAssignment::GetTargetParallelTaskCount( target_machine_features_) || (opcode == HloOpcode::kFusion && instruction->fusion_kind() != HloInstruction::FusionKind::kLoop) || - ShapeUtil::IsTuple(instruction->shape())) { + instruction->shape().IsTuple()) { return 1; } diff --git a/tensorflow/compiler/xla/service/cpu/tests/cpu_infeed_test.cc b/tensorflow/compiler/xla/service/cpu/tests/cpu_infeed_test.cc index 5cc6d01c0f..f0f897e963 100644 --- a/tensorflow/compiler/xla/service/cpu/tests/cpu_infeed_test.cc +++ b/tensorflow/compiler/xla/service/cpu/tests/cpu_infeed_test.cc @@ -48,7 +48,7 @@ class InfeedTest : public ClientLibraryTestBase { ASSERT_IS_OK(client_->TransferToInfeed(literal)); XlaBuilder builder(TestName()); Infeed(&builder, literal.shape()); - if (ShapeUtil::IsTuple(literal.shape())) { + if (literal.shape().IsTuple()) { // TODO(b/30609564): Use ComputeAndCompareLiteral instead. ComputeAndCompareTuple(&builder, literal, {}); } else { diff --git a/tensorflow/compiler/xla/service/gather_expander_test.cc b/tensorflow/compiler/xla/service/gather_expander_test.cc index a3102368cb..e1ea5c39d5 100644 --- a/tensorflow/compiler/xla/service/gather_expander_test.cc +++ b/tensorflow/compiler/xla/service/gather_expander_test.cc @@ -89,7 +89,7 @@ ENTRY main { // an implementation detail from WhileUtil::MakeCountedLoop). const Shape& while_shape = while_instr->shape(); - ASSERT_TRUE(ShapeUtil::IsTuple(while_shape)); + ASSERT_TRUE(while_shape.IsTuple()); ASSERT_EQ(ShapeUtil::TupleElementCount(while_shape), 4); EXPECT_TRUE(ShapeUtil::SameDimensions( diff --git a/tensorflow/compiler/xla/service/generic_transfer_manager.cc b/tensorflow/compiler/xla/service/generic_transfer_manager.cc index bec02e14f9..7d450f4b53 100644 --- a/tensorflow/compiler/xla/service/generic_transfer_manager.cc +++ b/tensorflow/compiler/xla/service/generic_transfer_manager.cc @@ -83,7 +83,7 @@ Status GenericTransferManager::TransferLiteralFromDeviceInternal( TF_RETURN_IF_ERROR(ShapeUtil::ForEachSubshapeWithStatus( device_buffer.on_host_shape(), [&](const Shape& subshape, const ShapeIndex& index) -> Status { - if (ShapeUtil::IsArray(subshape)) { + if (subshape.IsArray()) { TF_RETURN_IF_ERROR(executor->SynchronousMemcpyD2H( /*source=*/device_buffer.buffer(index), /*size=*/GetByteSizeRequirement(subshape), @@ -120,7 +120,7 @@ Status GenericTransferManager::TransferLiteralToDeviceAsync( device_buffer.on_host_shape(), [&](const Shape& device_subshape, const ShapeIndex& index) -> Status { se::DeviceMemoryBase device_memory = device_buffer.buffer(index); - if (ShapeUtil::IsArray(device_subshape)) { + if (device_subshape.IsArray()) { TF_RET_CHECK(GetByteSizeRequirement(device_subshape) == device_memory.size()); // Element is array-shaped: transfer array data to device buffer. diff --git a/tensorflow/compiler/xla/service/gpu/fusion_merger.cc b/tensorflow/compiler/xla/service/gpu/fusion_merger.cc index 470457935a..91930eccdf 100644 --- a/tensorflow/compiler/xla/service/gpu/fusion_merger.cc +++ b/tensorflow/compiler/xla/service/gpu/fusion_merger.cc @@ -35,7 +35,7 @@ namespace { // Traverses users of tuple shape, adding leaf instructions to 'instructions'. void MaybeResolveTupleElements(HloInstruction* instruction, std::vector* instructions) { - if (ShapeUtil::IsTuple(instruction->shape())) { + if (instruction->shape().IsTuple()) { for (auto tuple_user : instruction->users()) { MaybeResolveTupleElements(tuple_user, instructions); } diff --git a/tensorflow/compiler/xla/service/gpu/gpu_executable.cc b/tensorflow/compiler/xla/service/gpu/gpu_executable.cc index ae2e718db2..128cecd765 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_executable.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_executable.cc @@ -218,7 +218,7 @@ GpuExecutable::ResolveConstantGlobals(se::StreamExecutor* executor) { const Literal& literal = llvm_ir::LiteralForConstantAllocation(allocation); - CHECK(ShapeUtil::IsArray(literal.shape())); + CHECK(literal.shape().IsArray()); if (!ShouldEmitLiteralInLlvmIr(literal)) { VLOG(3) << "H2D memcpy for constant with shape " << ShapeUtil::HumanString(literal.shape()); diff --git a/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc b/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc index 542af51e62..842ba2fdcd 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_fusible.cc @@ -42,15 +42,13 @@ bool LayoutsAreReduceInputFusionFriendly(const HloInstruction& producer, int64 max_rank = -1; const Layout* max_rank_layout; for (HloInstruction* param : params) { - if (ShapeUtil::IsArray(param->shape()) && - param->shape().rank() > max_rank) { + if (param->shape().IsArray() && param->shape().rank() > max_rank) { max_rank = param->shape().rank(); max_rank_layout = ¶m->shape().layout(); } } return absl::c_all_of(params, [&](HloInstruction* param) { - return (!ShapeUtil::IsArray(param->shape())) || - (param->shape().rank() < max_rank) || + return (!param->shape().IsArray()) || (param->shape().rank() < max_rank) || (LayoutUtil::Equal(param->shape().layout(), *max_rank_layout)); }); } diff --git a/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc b/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc index ccd83e262e..58bdd4209a 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_layout_assignment.cc @@ -226,7 +226,7 @@ Status GpuLayoutAssignment::AddBackendConstraints( TF_RETURN_IF_ERROR( constraints->SetOperandLayout(shape, instruction, i)); const LogicalBuffer* output_buffer; - if (ShapeUtil::IsArray(instruction->shape())) { + if (instruction->shape().IsArray()) { TF_ASSIGN_OR_RETURN( output_buffer, constraints->points_to_analysis().GetBufferDefinedAt(instruction, diff --git a/tensorflow/compiler/xla/service/gpu/gpu_transfer_manager.cc b/tensorflow/compiler/xla/service/gpu/gpu_transfer_manager.cc index f3c2744292..8c6a691479 100644 --- a/tensorflow/compiler/xla/service/gpu/gpu_transfer_manager.cc +++ b/tensorflow/compiler/xla/service/gpu/gpu_transfer_manager.cc @@ -59,7 +59,7 @@ Status GpuTransferManager::TransferLiteralToInfeed( TF_RETURN_IF_ERROR(ShapeUtil::ForEachSubshapeWithStatus( shape, [&](const Shape& literal_subshape, const ShapeIndex& index) { - if (ShapeUtil::IsArray(literal_subshape)) { + if (literal_subshape.IsArray()) { int64 tuple_element_size = GetByteSizeRequirement(literal_subshape); TF_ASSIGN_OR_RETURN( *buffer_tree.mutable_element(index), @@ -126,13 +126,12 @@ static void ShapeTreeToLiteral( ShapeTree>* shape_tree, ShapeIndex* index) { const Shape& shape = ShapeUtil::GetSubshape(shape_tree->shape(), *index); - if (ShapeUtil::IsArray(shape)) { + if (shape.IsArray()) { (*shape_tree->mutable_element(*index))->WaitUntilAvailable(); return; } - CHECK(ShapeUtil::IsTuple(shape)) - << ShapeUtil::HumanStringWithLayout(shape); + CHECK(shape.IsTuple()) << ShapeUtil::HumanStringWithLayout(shape); const int64 tuple_element_count = ShapeUtil::TupleElementCount(shape); index->push_back(0); for (int64 i = 0; i < tuple_element_count; ++i) { @@ -158,7 +157,7 @@ Status GpuTransferManager::TransferLiteralFromOutfeed( std::unique_ptr* buffer) { const Shape& shape = ShapeUtil::GetSubshape(literal_shape, index); // Do not transfer tuple index buffers. - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { return; } *buffer = absl::make_unique( diff --git a/tensorflow/compiler/xla/service/gpu/hlo_to_ir_bindings.cc b/tensorflow/compiler/xla/service/gpu/hlo_to_ir_bindings.cc index 51627402b4..9634c92786 100644 --- a/tensorflow/compiler/xla/service/gpu/hlo_to_ir_bindings.cc +++ b/tensorflow/compiler/xla/service/gpu/hlo_to_ir_bindings.cc @@ -280,7 +280,7 @@ string HloToIrBindings::ToString() const { StrAppend(&s, " ", instr->ToString()); const ShapeTree& shape_tree = it->second; - if (!ShapeUtil::IsTuple(instr->shape())) { + if (!instr->shape().IsTuple()) { const llvm::Value* val = shape_tree.begin()->second; StrAppend(&s, " -> ", llvm_ir::DumpToString(*val), "\n"); continue; diff --git a/tensorflow/compiler/xla/service/gpu/infeed_thunk.cc b/tensorflow/compiler/xla/service/gpu/infeed_thunk.cc index 8a96b5fabc..676380c3b1 100644 --- a/tensorflow/compiler/xla/service/gpu/infeed_thunk.cc +++ b/tensorflow/compiler/xla/service/gpu/infeed_thunk.cc @@ -38,11 +38,11 @@ Status InfeedThunk::ExecuteOnStream(const BufferAllocations& buffer_allocations, // infeed_slices_'s shape should be a tuple of shape (buffers, token). const auto& infeed_shape = infeed_slices_.shape(); - TF_RET_CHECK(ShapeUtil::IsTuple(infeed_shape)) + TF_RET_CHECK(infeed_shape.IsTuple()) << ShapeUtil::HumanStringWithLayout(infeed_shape); TF_RET_CHECK(infeed_shape.tuple_shapes().size() == 2) << ShapeUtil::HumanStringWithLayout(infeed_shape); - TF_RET_CHECK(ShapeUtil::IsToken(infeed_shape.tuple_shapes(1))) + TF_RET_CHECK(infeed_shape.tuple_shapes(1).IsToken()) << ShapeUtil::HumanStringWithLayout(infeed_shape); TF_RET_CHECK( ShapeUtil::Equal(infeed_buffers.shape(), infeed_shape.tuple_shapes(0))) @@ -60,7 +60,7 @@ Status InfeedThunk::ExecuteOnStream(const BufferAllocations& buffer_allocations, const Shape& shape = ShapeUtil::GetSubshape(infeed_buffers.shape(), ShapeIndexView(index, 1)); // For the leaf buffers of the tuple copy the elements directly. - if (ShapeUtil::IsArray(shape)) { + if (shape.IsArray()) { const BufferAllocation::Slice& tuple_element_buffer = infeed_slices_.element(index); se::DeviceMemoryBase tuple_element_address = diff --git a/tensorflow/compiler/xla/service/gpu/ir_emitter.cc b/tensorflow/compiler/xla/service/gpu/ir_emitter.cc index 22db38ee03..0007a9a8a3 100644 --- a/tensorflow/compiler/xla/service/gpu/ir_emitter.cc +++ b/tensorflow/compiler/xla/service/gpu/ir_emitter.cc @@ -430,7 +430,7 @@ Status IrEmitter::HandleTupleSelect(HloInstruction* tuple_select) { auto on_false = tuple_select->operand(2); TF_RET_CHECK(pred->shape().element_type() == PRED); TF_RET_CHECK(ShapeUtil::IsScalar(pred->shape())); - TF_RET_CHECK(ShapeUtil::IsTuple(tuple_select->shape())); + TF_RET_CHECK(tuple_select->shape().IsTuple()); llvm_ir::EmitTupleSelect(GetIrArray(*tuple_select, *tuple_select), GetIrArray(*pred, *tuple_select), GetBasePointer(*on_true), GetBasePointer(*on_false), @@ -648,7 +648,7 @@ Status IrEmitter::HandleParameter(HloInstruction* parameter) { Status IrEmitter::HandleReduce(HloInstruction* reduce) { // TODO(b/112040122): Support variadic reduce. - if (!ShapeUtil::IsArray(reduce->shape())) { + if (!reduce->shape().IsArray()) { return Unimplemented("Variadic reduce is not supported on GPU"); } auto arg = reduce->operand(0); @@ -783,7 +783,7 @@ StatusOr IrEmitter::ComputeNestedElement( std::vector IrEmitter::ConstructIrArrayForOutputs( const HloInstruction& hlo) { std::vector output_arrays; - if (ShapeUtil::IsTuple(hlo.shape())) { + if (hlo.shape().IsTuple()) { int64 num_outputs = ShapeUtil::TupleElementCount(hlo.shape()); output_arrays.reserve(num_outputs); for (int64 i = 0; i < num_outputs; ++i) { diff --git a/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc b/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc index 48d9840620..063d493d90 100644 --- a/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc +++ b/tensorflow/compiler/xla/service/gpu/ir_emitter_unnested.cc @@ -292,13 +292,12 @@ llvm::Type* GetIndexTypeForKernel(const HloInstruction* hlo, int64 launch_size, auto shape_in_range = [&](const Shape& s) { bool in_range = true; - ShapeUtil::ForEachSubshape( - s, [&](const Shape& sub_shape, const ShapeIndex& /*index*/) { - if (ShapeUtil::IsArray(sub_shape) && - !IsInt32(ShapeUtil::ElementsIn(sub_shape))) { - in_range = false; - } - }); + ShapeUtil::ForEachSubshape(s, [&](const Shape& sub_shape, + const ShapeIndex& /*index*/) { + if (sub_shape.IsArray() && !IsInt32(ShapeUtil::ElementsIn(sub_shape))) { + in_range = false; + } + }); return in_range; }; @@ -542,8 +541,7 @@ Status IrEmitterUnnested::HandleFusion(HloInstruction* fusion) { // HandleFusion specializes reduction from a multi-dimensional array to // a 1D array. The specialized version requires a initializer thunk that // initializes the output array to the initial value of the reduce. - if (root->opcode() == HloOpcode::kReduce && - ShapeUtil::IsTuple(root->shape())) { + if (root->opcode() == HloOpcode::kReduce && root->shape().IsTuple()) { // TODO(b/112040122): Support variadic reduce. return Unimplemented("Variadic reduce is not supported on GPU"); } @@ -634,7 +632,7 @@ Status IrEmitterUnnested::EmitExtraOutputsForReduce( Status IrEmitterUnnested::HandleReduce(HloInstruction* reduce) { // TODO(b/112040122): Support multi-output reduce. - if (!ShapeUtil::IsArray(reduce->shape())) { + if (!reduce->shape().IsArray()) { return Unimplemented("Multi-output reduce is not supported on GPU"); } if (IsReductionToVector(*reduce)) { @@ -1309,7 +1307,7 @@ Status IrEmitterUnnested::HandleAllReduce(HloInstruction* crs) { // HloModuleConfig::num_replicas changes between when the module is compiled // and when it's run. if (crs->operand_count() == 1) { - CHECK(ShapeUtil::IsArray(crs->operand(0)->shape())) + CHECK(crs->operand(0)->shape().IsArray()) << "Operands to all-reduce must be arrays: " << crs->ToString(); AddThunkToThunkSequence(absl::make_unique( /*source_address=*/GetAllocationSlice(*crs->operand(0)), diff --git a/tensorflow/compiler/xla/service/gpu/tests/infeed_test.cc b/tensorflow/compiler/xla/service/gpu/tests/infeed_test.cc index f8120a5fa0..f91a22d482 100644 --- a/tensorflow/compiler/xla/service/gpu/tests/infeed_test.cc +++ b/tensorflow/compiler/xla/service/gpu/tests/infeed_test.cc @@ -43,7 +43,7 @@ class InfeedTest : public ClientLibraryTestBase { ASSERT_IS_OK(client_->TransferToInfeed(literal)); XlaBuilder builder(TestName()); Infeed(&builder, literal.shape()); - if (ShapeUtil::IsTuple(literal.shape())) { + if (literal.shape().IsTuple()) { // TODO(b/30609564): Use ComputeAndCompareLiteral instead. ComputeAndCompareTuple(&builder, literal, {}); } else { diff --git a/tensorflow/compiler/xla/service/hlo_alias_analysis.cc b/tensorflow/compiler/xla/service/hlo_alias_analysis.cc index cf8e6594cb..68094d8907 100644 --- a/tensorflow/compiler/xla/service/hlo_alias_analysis.cc +++ b/tensorflow/compiler/xla/service/hlo_alias_analysis.cc @@ -457,7 +457,7 @@ string HloAliasAnalysis::ToString() const { for (const HloComputation* computation : module_->computations()) { for (const HloInstruction* instruction : computation->instructions()) { StrAppend(&out, " ", instruction->name(), ":\n"); - if (ShapeUtil::IsTuple(instruction->shape())) { + if (instruction->shape().IsTuple()) { ShapeUtil::ForEachSubshape( instruction->shape(), [&out, &instruction, this](const Shape&, const ShapeIndex& index) { @@ -533,11 +533,11 @@ bool HloAliasAnalysis::HasLiveRangeInterference( const HloOrdering& ordering) const { for (const HloBuffer& buffer : buffers()) { CHECK(!buffer.values().empty()); - if (ShapeUtil::IsToken(buffer.values().front()->shape())) { + if (buffer.values().front()->shape().IsToken()) { // Tokens have no on-device representation and cannot interfere. for (const HloValue* value : buffer.values()) { // If one of the values is a token, all values must be a token. - DCHECK(ShapeUtil::IsToken(value->shape())); + DCHECK(value->shape().IsToken()); } continue; } diff --git a/tensorflow/compiler/xla/service/hlo_computation.cc b/tensorflow/compiler/xla/service/hlo_computation.cc index 7563030718..52ca67afb8 100644 --- a/tensorflow/compiler/xla/service/hlo_computation.cc +++ b/tensorflow/compiler/xla/service/hlo_computation.cc @@ -600,7 +600,7 @@ StatusOr HloComputation::DeepCopyHelper( const std::function< HloInstruction*(HloInstruction* leaf, const ShapeIndex& leaf_index, HloComputation* computation)>& copy_leaf) { - if (ShapeUtil::IsTuple(instruction->shape())) { + if (instruction->shape().IsTuple()) { std::vector elements; for (int64 i = 0; i < ShapeUtil::TupleElementCount(instruction->shape()); i++) { @@ -617,14 +617,14 @@ StatusOr HloComputation::DeepCopyHelper( } return AddInstruction(HloInstruction::CreateTuple(elements)); } - if (ShapeUtil::IsToken(instruction->shape())) { + if (instruction->shape().IsToken()) { // Tokens have no on-device representation and cannot be copied. Pass // through transparently. return instruction; } // Array shape. - TF_RET_CHECK(ShapeUtil::IsArray(instruction->shape())); + TF_RET_CHECK(instruction->shape().IsArray()); return copy_leaf(instruction, *index, this); } diff --git a/tensorflow/compiler/xla/service/hlo_constant_folding.cc b/tensorflow/compiler/xla/service/hlo_constant_folding.cc index 5e37883d3d..c58d00ff50 100644 --- a/tensorflow/compiler/xla/service/hlo_constant_folding.cc +++ b/tensorflow/compiler/xla/service/hlo_constant_folding.cc @@ -80,11 +80,10 @@ StatusOr HloConstantFolding::Run(HloModule* module) { } // Don't constant fold unless it's a net positive or the output is small. - if (ShapeUtil::IsArray(instruction->shape())) { + if (instruction->shape().IsArray()) { int64 elements_in_removed_operands = 0; for (HloInstruction* operand : instruction->operands()) { - if (operand->user_count() == 1 && - ShapeUtil::IsArray(operand->shape())) { + if (operand->user_count() == 1 && operand->shape().IsArray()) { elements_in_removed_operands += ShapeUtil::ElementsIn(operand->shape()); } diff --git a/tensorflow/compiler/xla/service/hlo_cost_analysis.cc b/tensorflow/compiler/xla/service/hlo_cost_analysis.cc index cb431aed47..c4b4fa62dd 100644 --- a/tensorflow/compiler/xla/service/hlo_cost_analysis.cc +++ b/tensorflow/compiler/xla/service/hlo_cost_analysis.cc @@ -292,7 +292,7 @@ Status HloCostAnalysis::HandleReduce(const HloInstruction* reduce) { // does not need to be multiplied by the number of input tensors - that's // already "priced in" by the sub-computation doing more work. auto arg = reduce->operand(0); - auto output_shape = ShapeUtil::IsArray(reduce->shape()) + auto output_shape = reduce->shape().IsArray() ? reduce->shape() : reduce->shape().tuple_shapes(0); int64 reduction_count = @@ -539,7 +539,7 @@ Status HloCostAnalysis::HandleConvolution(const HloInstruction* convolution) { Status HloCostAnalysis::HandleFft(const HloInstruction* fft) { auto real_shape = - ShapeUtil::IsTuple(fft->operand(0)->shape()) + fft->operand(0)->shape().IsTuple() ? ShapeUtil::GetTupleElementShape(fft->operand(0)->shape(), 0) : fft->operand(0)->shape(); constexpr int kFmaPerComplexMul = 4; @@ -561,7 +561,7 @@ Status HloCostAnalysis::HandleAllReduce(const HloInstruction* crs) { double flops = 0.0; ShapeUtil::ForEachSubshape(crs->shape(), [&](const Shape& subshape, const ShapeIndex&) { - if (ShapeUtil::IsArray(subshape)) { + if (subshape.IsArray()) { flops += ShapeUtil::ElementsIn(subshape); } }); diff --git a/tensorflow/compiler/xla/service/hlo_dataflow_analysis.cc b/tensorflow/compiler/xla/service/hlo_dataflow_analysis.cc index 3ed3d3c11c..1924204df0 100644 --- a/tensorflow/compiler/xla/service/hlo_dataflow_analysis.cc +++ b/tensorflow/compiler/xla/service/hlo_dataflow_analysis.cc @@ -190,7 +190,7 @@ string HloDataflowAnalysis::ToString() const { for (const HloComputation* computation : module_.computations()) { for (const HloInstruction* instruction : computation->instructions()) { StrAppend(&out, " ", instruction->name(), ":\n"); - if (ShapeUtil::IsTuple(instruction->shape())) { + if (instruction->shape().IsTuple()) { GetInstructionValueSet(instruction) .ForEachElement([this, &instruction, &out]( const ShapeIndex& index, diff --git a/tensorflow/compiler/xla/service/hlo_dataflow_analysis_test.cc b/tensorflow/compiler/xla/service/hlo_dataflow_analysis_test.cc index 94de7c55dd..1d165ac35f 100644 --- a/tensorflow/compiler/xla/service/hlo_dataflow_analysis_test.cc +++ b/tensorflow/compiler/xla/service/hlo_dataflow_analysis_test.cc @@ -73,8 +73,8 @@ class HloDataflowAnalysisTest : public HloTestBase, bool InstructionsMayInterfere(const HloOrdering& ordering, const HloInstruction* a, const HloInstruction* b) { - EXPECT_FALSE(ShapeUtil::IsTuple(a->shape())); - EXPECT_FALSE(ShapeUtil::IsTuple(b->shape())); + EXPECT_FALSE(a->shape().IsTuple()); + EXPECT_FALSE(b->shape().IsTuple()); return ordering.MayInterfere(analysis_->GetValueDefinedAt(a), analysis_->GetValueDefinedAt(b), *analysis_); } diff --git a/tensorflow/compiler/xla/service/hlo_element_type_converter.cc b/tensorflow/compiler/xla/service/hlo_element_type_converter.cc index a40b6d888c..9b0f2b2a0f 100644 --- a/tensorflow/compiler/xla/service/hlo_element_type_converter.cc +++ b/tensorflow/compiler/xla/service/hlo_element_type_converter.cc @@ -68,7 +68,7 @@ Shape GetConvertedTupleShape(const Shape& shape, PrimitiveType from_type, std::vector new_tuple_subshapes; for (int64 i = 0; i < ShapeUtil::TupleElementCount(shape); ++i) { Shape subshape = ShapeUtil::GetTupleElementShape(shape, i); - CHECK(!ShapeUtil::IsTuple(subshape)); + CHECK(!subshape.IsTuple()); if (subshape.element_type() == from_type) { subshape = ShapeUtil::ChangeElementType(subshape, to_type); } @@ -92,7 +92,7 @@ HloInstruction* ConvertTupleElements(HloInstruction* hlo, HloInstruction* element = computation->AddInstruction( HloInstruction::CreateGetTupleElement(ele_shape, hlo, i)); const Shape& to_ele_shape = ShapeUtil::GetTupleElementShape(to_shape, i); - CHECK(!ShapeUtil::IsTuple(ele_shape)); + CHECK(!ele_shape.IsTuple()); if (ele_shape.element_type() != to_ele_shape.element_type()) { element = computation->AddInstruction( HloInstruction::CreateConvert(to_ele_shape, element)); @@ -190,7 +190,7 @@ StatusOr HloElementTypeConverter::Run(HloModule* module) { TF_RETURN_IF_ERROR(new_hlo->CopyAllControlDepsFrom(hlo)); new_hlo = ToElementType(new_hlo, eliminate_type_); - } else if (ShapeUtil::IsTuple(hlo->shape())) { + } else if (hlo->shape().IsTuple()) { Shape old_shape = hlo->shape(); Shape new_shape = GetConvertedTupleShape(hlo->shape(), eliminate_type_, replace_with_type_); diff --git a/tensorflow/compiler/xla/service/hlo_evaluator.cc b/tensorflow/compiler/xla/service/hlo_evaluator.cc index 3d3c6af2f3..a93ca843de 100644 --- a/tensorflow/compiler/xla/service/hlo_evaluator.cc +++ b/tensorflow/compiler/xla/service/hlo_evaluator.cc @@ -442,7 +442,7 @@ Status HloEvaluator::HandleConcatenate(HloInstruction* concatenate) { // The result concatenate dimension is going to be the sum of all // concatenate dimensions of the operands taking part of the operation. const Shape& reference_shape = operands[0]->shape(); - CHECK(ShapeUtil::IsArray(reference_shape)); + CHECK(reference_shape.IsArray()); const int64 rank = reference_shape.rank(); const int64 concat_dim = concatenate->dimensions()[0]; CHECK_GE(concat_dim, 0); @@ -453,7 +453,7 @@ Status HloEvaluator::HandleConcatenate(HloInstruction* concatenate) { for (int64 i = 1; i < operands.size(); ++i) { const Shape& operand_shape = operands[i]->shape(); - CHECK(ShapeUtil::IsArray(operand_shape)); + CHECK(operand_shape.IsArray()); // Accumulate the concat dimension from all tensors taking part to the // operation. concat_dimensions[concat_dim] += @@ -1382,7 +1382,7 @@ StatusOr EvaluateSort(HloInstruction* sort, } // namespace Status HloEvaluator::HandleSort(HloInstruction* sort) { - if (!ShapeUtil::IsTuple(sort->shape())) { + if (!sort->shape().IsTuple()) { return DefaultAction(sort); } else { // This is a really stupid work-around for the fact it's hard to support a @@ -1407,7 +1407,7 @@ Status HloEvaluator::HandleSort(HloInstruction* sort) { } Status HloEvaluator::HandleReduce(HloInstruction* reduce) { - if (!ShapeUtil::IsTuple(reduce->shape())) { + if (!reduce->shape().IsTuple()) { return DefaultAction(reduce); } else { auto first_element_type = reduce->shape().tuple_shapes(0).element_type(); diff --git a/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h b/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h index 7e0dadaf3e..4df9bb440e 100644 --- a/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h +++ b/tensorflow/compiler/xla/service/hlo_evaluator_typed_visitor.h @@ -940,7 +940,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { Status HandleSelect(HloInstruction* select) override { CHECK(!ShapeUtil::IsScalar(select->operand(0)->shape())); - CHECK(ShapeUtil::IsArray(select->shape())); + CHECK(select->shape().IsArray()); std::function select_op = [](bool pred, ReturnT on_true, ReturnT on_false) { if (pred) { @@ -993,8 +993,8 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { TF_CHECK_OK(ShapeUtil::ValidateShape(lhs_shape)); TF_CHECK_OK(ShapeUtil::ValidateShape(rhs_shape)); - CHECK(ShapeUtil::IsArray(lhs_shape)); - CHECK(ShapeUtil::IsArray(rhs_shape)); + CHECK(lhs_shape.IsArray()); + CHECK(rhs_shape.IsArray()); CHECK(ShapeUtil::SameElementType(lhs_shape, rhs_shape)); CHECK(ShapeUtil::SameElementType(lhs_shape, result_shape)); @@ -1169,9 +1169,9 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { Status HandleDot(HloInstruction* dot) { const HloInstruction* lhs = dot->operand(0); const HloInstruction* rhs = dot->operand(1); - CHECK(ShapeUtil::IsArray(dot->shape())); - CHECK(ShapeUtil::IsArray(lhs->shape())); - CHECK(ShapeUtil::IsArray(rhs->shape())); + CHECK(dot->shape().IsArray()); + CHECK(lhs->shape().IsArray()); + CHECK(rhs->shape().IsArray()); const auto& dnums = dot->dot_dimension_numbers(); @@ -1232,9 +1232,9 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { Status HandleDotSlowPath(HloInstruction* dot) { auto lhs = dot->operand(0); auto rhs = dot->operand(1); - CHECK(ShapeUtil::IsArray(dot->shape())); - CHECK(ShapeUtil::IsArray(lhs->shape())); - CHECK(ShapeUtil::IsArray(rhs->shape())); + CHECK(dot->shape().IsArray()); + CHECK(lhs->shape().IsArray()); + CHECK(rhs->shape().IsArray()); const auto& dnums = dot->dot_dimension_numbers(); @@ -1326,7 +1326,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { } Status HandlePad(HloInstruction* pad) override { - CHECK(ShapeUtil::IsArray(pad->operand(0)->shape())); + CHECK(pad->operand(0)->shape().IsArray()); // Padding value must be scalar. CHECK(ShapeUtil::IsScalar(pad->operand(1)->shape())); CHECK_EQ(pad->operand(0)->shape().rank(), @@ -1669,7 +1669,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { Status HandleReduce(HloInstruction* hlo) override { HloReduceInstruction* reduce = Cast(hlo); int64 num_args = reduce->inputs().size(); - bool has_tuple_output = ShapeUtil::IsTuple(reduce->shape()); + bool has_tuple_output = reduce->shape().IsTuple(); absl::Span dimensions(reduce->dimensions()); HloComputation* function = reduce->to_apply(); @@ -1700,7 +1700,7 @@ class HloEvaluatorTypedVisitor : public DfsHloVisitorWithDefault { // All args and results have the same dimensions, so pick an arbitrary one. const Shape& arg_shape = arg_literals[0]->shape(); - const Shape& result_shape = ShapeUtil::IsTuple(reduce->shape()) + const Shape& result_shape = reduce->shape().IsTuple() ? reduce->shape().tuple_shapes(0) : reduce->shape(); const auto arg_dimensions = AsInt64Slice(arg_shape.dimensions()); diff --git a/tensorflow/compiler/xla/service/hlo_execution_profile_test.cc b/tensorflow/compiler/xla/service/hlo_execution_profile_test.cc index 5be9dba3aa..df06cf8c53 100644 --- a/tensorflow/compiler/xla/service/hlo_execution_profile_test.cc +++ b/tensorflow/compiler/xla/service/hlo_execution_profile_test.cc @@ -45,7 +45,7 @@ TEST_F(HloExecutionProfileTest, Basic) { auto shape_size_function = [&](const Shape& shape) { const int64 pointer_size = 8; - if (ShapeUtil::IsOpaque(shape)) { + if (shape.IsOpaque()) { return pointer_size; } return ShapeUtil::ByteSizeOf(shape, pointer_size); diff --git a/tensorflow/compiler/xla/service/hlo_graph_dumper.cc b/tensorflow/compiler/xla/service/hlo_graph_dumper.cc index dbf0d2c113..c6eaead8dd 100644 --- a/tensorflow/compiler/xla/service/hlo_graph_dumper.cc +++ b/tensorflow/compiler/xla/service/hlo_graph_dumper.cc @@ -733,8 +733,8 @@ bool HloDotDumper::ShouldMergeIntoUsers(const HloInstruction* instr) const { return true; } const int kMinUsersToOmit = 3; - return instr->opcode() == HloOpcode::kParameter && - ShapeUtil::IsTuple(instr->shape()) && !instr->IsFused() && + return instr->opcode() == HloOpcode::kParameter && instr->shape().IsTuple() && + !instr->IsFused() && std::count_if(instr->users().begin(), instr->users().end(), [&](const HloInstruction* user) { return filter_.Show(user); @@ -816,7 +816,7 @@ string HloDotDumper::GetInstructionNodeInlinedOperands( // Print the literal value of constants with <= K elements. optional elem_count; - if (ShapeUtil::IsArray(shape)) { + if (shape.IsArray()) { elem_count = 1; for (int64 dim : shape.dimensions()) { *elem_count *= dim; diff --git a/tensorflow/compiler/xla/service/hlo_instruction.cc b/tensorflow/compiler/xla/service/hlo_instruction.cc index 462fe3b321..2915535987 100644 --- a/tensorflow/compiler/xla/service/hlo_instruction.cc +++ b/tensorflow/compiler/xla/service/hlo_instruction.cc @@ -311,7 +311,7 @@ StatusOr> HloInstruction::CreateFromProto( shape, operands(0), proto.exponent_bits(), proto.mantissa_bits()); break; case HloOpcode::kInfeed: { - TF_RET_CHECK(ShapeUtil::IsTuple(shape) && + TF_RET_CHECK(shape.IsTuple() && (ShapeUtil::TupleElementCount(shape) == 2)) << "Infeed should have a tuple shape with 2 operands, but has: " << shape; @@ -628,7 +628,7 @@ HloInstruction::CreateGetTupleElement(const Shape& shape, absl::Span operands) { if (opcode == HloOpcode::kCopy) { // It is impossible to copy an opaque shape, we don't know how big it is. - CHECK(!ShapeUtil::IsOpaque(shape)); + CHECK(!shape.IsOpaque()); } auto instruction = absl::WrapUnique(new HloInstruction(opcode, shape)); for (auto operand : operands) { @@ -1132,7 +1132,7 @@ HloInstruction::CreateBroadcastSequence( void HloInstruction::set_single_sharding(const HloSharding& sharding) { CHECK(!sharding.IsTuple()) << sharding; - if (ShapeUtil::IsTuple(shape())) { + if (shape().IsTuple()) { set_sharding(HloSharding::Tuple(sharding.GetAsShapeTree(shape()))); } else { set_sharding(sharding); diff --git a/tensorflow/compiler/xla/service/hlo_instructions.cc b/tensorflow/compiler/xla/service/hlo_instructions.cc index 977fa01acb..1f37b284a2 100644 --- a/tensorflow/compiler/xla/service/hlo_instructions.cc +++ b/tensorflow/compiler/xla/service/hlo_instructions.cc @@ -866,7 +866,7 @@ void HloConstantInstruction::RelayoutConstant(const Layout& new_layout, const ShapeIndex& shape_index) { Shape* mutable_array_subshape = ShapeUtil::GetMutableSubshape(mutable_shape(), shape_index); - CHECK(ShapeUtil::IsArray(*mutable_array_subshape)); + CHECK(mutable_array_subshape->IsArray()); // Normally array_subshape will always have a layout, but this invariant is // temporarily broken in LayoutAssignment::AssignLayouts. @@ -900,7 +900,7 @@ string HloConstantInstruction::OperandsToStringWithCanonicalNameMap( string operands; // For constants, show the actual value in place of an empty operand list. if (literal_.has_value() && - ((ShapeUtil::IsArray(shape()) && ShapeUtil::ElementsIn(shape()) <= 10) || + ((shape().IsArray() && ShapeUtil::ElementsIn(shape()) <= 10) || options.print_large_constants())) { // Literal::ToString emits multidimensional arrays over multiple // lines. Compact this into one line by stripping out white space. diff --git a/tensorflow/compiler/xla/service/hlo_module_dce.cc b/tensorflow/compiler/xla/service/hlo_module_dce.cc index 31d26cc51e..6b72ba1286 100644 --- a/tensorflow/compiler/xla/service/hlo_module_dce.cc +++ b/tensorflow/compiler/xla/service/hlo_module_dce.cc @@ -49,7 +49,7 @@ StatusOr RunWhileDCE(HloModule* module, HloLivenessAnalysis* liveness) { auto* while_body_param = while_body_comp->parameter_instruction(0); auto* while_body_root = while_body_comp->root_instruction(); - if (!ShapeUtil::IsTuple(xla_while->shape()) || + if (!xla_while->shape().IsTuple() || while_body_root->opcode() != HloOpcode::kTuple) { // Only run DCE on tuple-shaped while loops where body root is Tuple, // with no I/O instructions. diff --git a/tensorflow/compiler/xla/service/hlo_parser.cc b/tensorflow/compiler/xla/service/hlo_parser.cc index 4e9c562c93..80c31b8db6 100644 --- a/tensorflow/compiler/xla/service/hlo_parser.cc +++ b/tensorflow/compiler/xla/service/hlo_parser.cc @@ -1287,7 +1287,7 @@ bool HloParser::ParseInstructionRhs(HloComputation::Builder* builder, // the infeed instruction. ShapeUtil::GetTupleElementShape will check fail // if the shape is not a non-empty tuple, so add guard so an error message // can be emitted instead of a check fail - if (!ShapeUtil::IsTuple(shape) && !ShapeUtil::IsEmptyTuple(shape)) { + if (!shape.IsTuple() && !ShapeUtil::IsEmptyTuple(shape)) { return Error(lexer_.GetLoc(), "infeed must have a non-empty tuple shape"); } @@ -1931,8 +1931,8 @@ bool HloParser::SetValueInLiteralHelper(ParsedElemT value, // ::= tuple // ::= non_tuple bool HloParser::ParseLiteral(Literal* literal, const Shape& shape) { - return ShapeUtil::IsTuple(shape) ? ParseTupleLiteral(literal, shape) - : ParseNonTupleLiteral(literal, shape); + return shape.IsTuple() ? ParseTupleLiteral(literal, shape) + : ParseNonTupleLiteral(literal, shape); } // tuple diff --git a/tensorflow/compiler/xla/service/hlo_sharding.cc b/tensorflow/compiler/xla/service/hlo_sharding.cc index b8b4fd6135..e8c198e303 100644 --- a/tensorflow/compiler/xla/service/hlo_sharding.cc +++ b/tensorflow/compiler/xla/service/hlo_sharding.cc @@ -57,7 +57,7 @@ HloSharding HloSharding::Tuple(const ShapeTree& sub_shardings) { HloSharding HloSharding::Tuple(const Shape& tuple_shape, absl::Span shardings) { - CHECK(ShapeUtil::IsTuple(tuple_shape)) << ShapeUtil::HumanString(tuple_shape); + CHECK(tuple_shape.IsTuple()) << ShapeUtil::HumanString(tuple_shape); for (auto& sharding : shardings) { CHECK(!sharding.IsTuple()) << sharding.ToString(); } @@ -70,7 +70,7 @@ HloSharding HloSharding::Tuple(const Shape& tuple_shape, HloSharding HloSharding::SingleTuple(const Shape& tuple_shape, const HloSharding& sharding) { - CHECK(ShapeUtil::IsTuple(tuple_shape)) << ShapeUtil::HumanString(tuple_shape); + CHECK(tuple_shape.IsTuple()) << ShapeUtil::HumanString(tuple_shape); CHECK(!sharding.IsTuple()) << sharding.ToString(); int64 leaf_count = RequiredLeaves(tuple_shape); std::vector flattened_list; @@ -80,7 +80,7 @@ HloSharding HloSharding::SingleTuple(const Shape& tuple_shape, HloSharding HloSharding::Single(const Shape& shape, const HloSharding& sharding) { - return ShapeUtil::IsTuple(shape) ? SingleTuple(shape, sharding) : sharding; + return shape.IsTuple() ? SingleTuple(shape, sharding) : sharding; } string HloSharding::ToString() const { @@ -269,7 +269,7 @@ int64 HloSharding::GetUniqueDevice() const { } Status HloSharding::ValidateTuple(const Shape& shape, int64 num_devices) const { - if (!ShapeUtil::IsTuple(shape)) { + if (!shape.IsTuple()) { return tensorflow::errors::InvalidArgument( StrCat("Sharding is tuple-shaped but validation shape is not.")); } @@ -305,7 +305,7 @@ Status HloSharding::Validate(const Shape& shape, int64 num_devices) const { Status HloSharding::ValidateNonTuple(const Shape& shape, int64 num_devices) const { - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { return tensorflow::errors::InvalidArgument( StrCat("Validation shape is a tuple but sharding is not.")); } @@ -455,7 +455,7 @@ HloSharding HloSharding::GetSubSharding(const Shape& shape, } sub_shape = &ShapeUtil::GetSubshape(*sub_shape, {idx}); } - if (ShapeUtil::IsTuple(*sub_shape)) { + if (sub_shape->IsTuple()) { auto begin_it = tuple_elements_.begin() + sharding_index; std::vector sub_shardings( begin_it, begin_it + ShapeUtil::GetLeafCount(*sub_shape)); diff --git a/tensorflow/compiler/xla/service/hlo_sharding_metadata.cc b/tensorflow/compiler/xla/service/hlo_sharding_metadata.cc index f506130445..b414d2a663 100644 --- a/tensorflow/compiler/xla/service/hlo_sharding_metadata.cc +++ b/tensorflow/compiler/xla/service/hlo_sharding_metadata.cc @@ -234,7 +234,7 @@ StatusOr ApplyShardingFromUsers(HloInstruction* instruction, if (instruction->users().empty()) { // No sharding from users, use domain_sharding, after checking // compatibility. - TF_RET_CHECK(ShapeUtil::IsTuple(instruction->shape()) && + TF_RET_CHECK(instruction->shape().IsTuple() && ShapeUtil::GetLeafCount(instruction->shape()) == domain_sharding.tuple_elements().size()); instruction->set_sharding(domain_sharding); @@ -266,7 +266,7 @@ StatusOr ApplyShardingFromUsers(HloInstruction* instruction, AssignmentKind sub_assigned = AssignmentKind::kUnassigned; TF_ASSIGN_OR_RETURN(ShapeTree user_sharding_tree, GetShardingTreeFromUser(*instruction, *user)); - if (ShapeUtil::IsTuple(instruction->shape())) { + if (instruction->shape().IsTuple()) { // For tuple-shaped instructions collect individual tuple subshardings // from the uses, and then combine them into the tuple sharding. // If the user is a GTE its sharding concerns only the subtree of @@ -298,7 +298,7 @@ StatusOr ApplyShardingFromUsers(HloInstruction* instruction, } if (assigned == AssignmentKind::kAssigned) { - if (ShapeUtil::IsTuple(instruction->shape())) { + if (instruction->shape().IsTuple()) { instruction->set_sharding(HloSharding::Tuple(sharding_tree)); } else { TF_RET_CHECK(sharding_tree.leaf_count() == 1); @@ -361,7 +361,7 @@ Status ApplyDomainSharding(const DomainMetadata::Domain& domain, // kUnassignedDevice. Indeed in case of doubt it is better to leave the // entire tuple unassigned, and let the device placer decide for it. if (instruction->sharding().UsesDevice(kUnassignedDevice)) { - TF_RET_CHECK(ShapeUtil::IsTuple(instruction->shape())) + TF_RET_CHECK(instruction->shape().IsTuple()) << "Only tuples can have kUnassignedDevice sub shardings"; instruction->clear_sharding(); } diff --git a/tensorflow/compiler/xla/service/hlo_tfgraph_builder.cc b/tensorflow/compiler/xla/service/hlo_tfgraph_builder.cc index 4876533449..4ea39a7628 100644 --- a/tensorflow/compiler/xla/service/hlo_tfgraph_builder.cc +++ b/tensorflow/compiler/xla/service/hlo_tfgraph_builder.cc @@ -159,7 +159,7 @@ void HloTfGraphBuilder::SetNodeAttrs(const HloInstruction* instruction, // Set the layout. if (LayoutUtil::HasLayout(instruction->shape())) { string layout_string; - if (ShapeUtil::IsTuple(instruction->shape())) { + if (instruction->shape().IsTuple()) { // For tuples, emit the full shape because the layout of a tuple is not // represented in a single Layout field. layout_string = ShapeUtil::HumanStringWithLayout(instruction->shape()); diff --git a/tensorflow/compiler/xla/service/hlo_value.cc b/tensorflow/compiler/xla/service/hlo_value.cc index 59594ab2f0..d409df06be 100644 --- a/tensorflow/compiler/xla/service/hlo_value.cc +++ b/tensorflow/compiler/xla/service/hlo_value.cc @@ -46,7 +46,7 @@ const Shape& HloPosition::shape() const { string HloPosition::ToString() const { string index_str = - ShapeUtil::IsTuple(instruction->shape()) ? (" " + index.ToString()) : ""; + instruction->shape().IsTuple() ? (" " + index.ToString()) : ""; return StrCat(instruction->name(), index_str); } @@ -56,10 +56,9 @@ std::ostream& operator<<(std::ostream& out, const HloPosition& position) { } string HloUse::ToString() const { - string index_str = - ShapeUtil::IsTuple(instruction->operand(operand_number)->shape()) - ? (" " + operand_index.ToString()) - : ""; + string index_str = instruction->operand(operand_number)->shape().IsTuple() + ? (" " + operand_index.ToString()) + : ""; return StrCat(instruction->name(), ", operand ", operand_number, index_str); } @@ -88,7 +87,7 @@ bool HloValue::operator!=(const HloValue& other) const { } string HloValue::ToShortString() const { - string index_str = ShapeUtil::IsTuple(defining_instruction()->shape()) + string index_str = defining_instruction()->shape().IsTuple() ? defining_index().ToString() : ""; return StrCat(id(), " ", is_phi_ ? "PHI " : "", diff --git a/tensorflow/compiler/xla/service/hlo_verifier.cc b/tensorflow/compiler/xla/service/hlo_verifier.cc index 5e120b4971..8d8720d7be 100644 --- a/tensorflow/compiler/xla/service/hlo_verifier.cc +++ b/tensorflow/compiler/xla/service/hlo_verifier.cc @@ -980,7 +980,7 @@ bool ShapeContainsToken(const Shape& shape) { bool contains_token = false; ShapeUtil::ForEachSubshape( shape, [&contains_token](const Shape& subshape, const ShapeIndex&) { - if (ShapeUtil::IsToken(subshape)) { + if (subshape.IsToken()) { contains_token = true; } }); @@ -1322,7 +1322,7 @@ class InstructionVerifier : public DfsHloVisitorWithDefault { } Status HandleGetTupleElement(HloInstruction* gte) override { - TF_RET_CHECK(ShapeUtil::IsTuple(gte->operand(0)->shape())); + TF_RET_CHECK(gte->operand(0)->shape().IsTuple()); return Status::OK(); } diff --git a/tensorflow/compiler/xla/service/instruction_fusion.cc b/tensorflow/compiler/xla/service/instruction_fusion.cc index 0744871529..f6f25c4413 100644 --- a/tensorflow/compiler/xla/service/instruction_fusion.cc +++ b/tensorflow/compiler/xla/service/instruction_fusion.cc @@ -174,7 +174,7 @@ bool InstructionFusion::EffectivelyAtMostUnary(HloInstruction* hlo) { ShapeUtil::ForEachSubshape( hlo->shape(), [&output_rank](const Shape& subshape, const ShapeIndex& shape_index) { - if (ShapeUtil::IsArray(subshape)) { + if (subshape.IsArray()) { output_rank = std::max(output_rank, ShapeUtil::TrueRank(subshape)); } }); @@ -274,7 +274,7 @@ InstructionFusion::ComputeGloballyUnfusible( ShapeUtil::ForEachSubshape( shape, [&size](const Shape& subshape, const ShapeIndex& shape_index) { - if (ShapeUtil::IsArray(subshape)) { + if (subshape.IsArray()) { size += ShapeUtil::ElementsIn(subshape); } }); diff --git a/tensorflow/compiler/xla/service/interpreter/executable.cc b/tensorflow/compiler/xla/service/interpreter/executable.cc index de9204011c..88e33464a2 100644 --- a/tensorflow/compiler/xla/service/interpreter/executable.cc +++ b/tensorflow/compiler/xla/service/interpreter/executable.cc @@ -117,7 +117,7 @@ StatusOr InterpreterExecutable::ExecuteAsyncOnStream( } /*static*/ int64 InterpreterExecutable::ShapeSizeBytes(const Shape& shape) { - if (ShapeUtil::IsOpaque(shape)) { + if (shape.IsOpaque()) { return sizeof(void*); } return ShapeUtil::ByteSizeOf(shape, sizeof(void*)); diff --git a/tensorflow/compiler/xla/service/layout_assignment.cc b/tensorflow/compiler/xla/service/layout_assignment.cc index d30d2ff9b9..1c4ac178f0 100644 --- a/tensorflow/compiler/xla/service/layout_assignment.cc +++ b/tensorflow/compiler/xla/service/layout_assignment.cc @@ -256,7 +256,7 @@ Status LayoutConstraints::SetArrayOperandLayout( const Layout& layout, const HloInstruction* instruction, int64 operand_no, bool mandatory, bool dfs) { const HloInstruction* operand = instruction->operand(operand_no); - TF_RET_CHECK(ShapeUtil::IsArray(operand->shape())); + TF_RET_CHECK(operand->shape().IsArray()); Shape shape(operand->shape()); *shape.mutable_layout() = layout; TF_RETURN_IF_ERROR(LayoutUtil::ValidateLayoutInShape(shape)); @@ -314,7 +314,7 @@ Status LayoutConstraints::SetInstructionLayout( CHECK_EQ(1, buffers.size()); CHECK_EQ(buffers[0]->instruction(), instruction); - if (ShapeUtil::IsArray(subshape)) { + if (subshape.IsArray()) { return SetBufferLayout(subshape.layout(), *buffers[0], mandatory); } else { return Status::OK(); @@ -406,7 +406,7 @@ Status LayoutAssignment::BuildHostChannelConstraints( instruction->opcode() == HloOpcode::kRecv) { const Shape& data_shape = ShapeUtil::GetTupleElementShape(send_recv_instr->shape(), 0); - TF_RET_CHECK(ShapeUtil::IsArray(data_shape)); + TF_RET_CHECK(data_shape.IsArray()); TF_RET_CHECK(LayoutUtil::HasLayout(data_shape)); const Layout* prev_layout = host_channel_constraints_.ConstrainChannel( send_recv_instr->channel_id(), data_shape.layout()); @@ -489,7 +489,7 @@ Status LayoutAssignment::AddMandatoryConstraints( if (instruction->opcode() == HloOpcode::kSend) { // TODO(b/68493863): Change to use SetOperandLayout(). const Shape send_buffer_shape = instruction->operand(0)->shape(); - TF_RET_CHECK(ShapeUtil::IsArray(send_buffer_shape)); + TF_RET_CHECK(send_buffer_shape.IsArray()); Shape new_buffer_shape = get_channel_constraints(instruction) ->LayoutShapeForChannel(send_buffer_shape, @@ -499,7 +499,7 @@ Status LayoutAssignment::AddMandatoryConstraints( } else { const Shape recv_buffer_shape = ShapeUtil::GetTupleElementShape(instruction->shape(), 0); - TF_RET_CHECK(ShapeUtil::IsArray(recv_buffer_shape)); + TF_RET_CHECK(recv_buffer_shape.IsArray()); TF_ASSIGN_OR_RETURN( const LogicalBuffer* buffer, constraints->points_to_analysis().GetBufferDefinedAt(instruction, @@ -520,7 +520,7 @@ Status LayoutAssignment::AddMandatoryConstraints( } // TODO(b/68493863): Change to use SetOperandLayout(). const Shape& buffer_shape = instruction->operand(0)->shape(); - TF_RET_CHECK(ShapeUtil::IsArray(buffer_shape)); + TF_RET_CHECK(buffer_shape.IsArray()); Shape new_buffer_shape = get_channel_constraints(instruction) ->LayoutShapeForChannel(buffer_shape, all_reduce_id); @@ -780,7 +780,7 @@ StatusOr LayoutAssignment::CreateCopyWithNewLayout( << ShapeUtil::HumanString(instruction->shape()) << " instruction: " << instruction->ToString(); - if (ShapeUtil::IsTuple(instruction->shape())) { + if (instruction->shape().IsTuple()) { // Copy tuple elements which have differing layouts. std::vector element_copies; for (int64 i = 0; i < ShapeUtil::TupleElementCount(instruction->shape()); @@ -811,7 +811,7 @@ StatusOr LayoutAssignment::CreateCopyWithNewLayout( TF_RETURN_IF_ERROR(LayoutUtil::CopyLayoutBetweenShapes( shape_with_layout, tuple_copy->mutable_shape())); return tuple_copy; - } else if (ShapeUtil::IsArray(instruction->shape())) { + } else if (instruction->shape().IsArray()) { HloInstruction* copy = instruction->parent()->AddInstruction(HloInstruction::CreateUnary( instruction->shape(), HloOpcode::kCopy, instruction)); @@ -988,8 +988,8 @@ std::unique_ptr LayoutAssignment::ChooseOperandLayoutFromOutputLayout( const Layout& output_layout, const HloInstruction* instruction, int64 operand_no) { const HloInstruction* operand = instruction->operand(operand_no); - CHECK(ShapeUtil::IsArray(instruction->shape())); - CHECK(ShapeUtil::IsArray(operand->shape())); + CHECK(instruction->shape().IsArray()); + CHECK(operand->shape().IsArray()); if (!ShapeUtil::IsScalar(operand->shape()) && operand->shape().rank() == instruction->shape().rank() && !instruction_can_change_layout_func_(instruction)) { @@ -1065,8 +1065,7 @@ std::unique_ptr LayoutAssignment::ChooseOutputLayoutFromOperandLayout( int64 operand_no) { const HloInstruction* operand = user->operand(operand_no); - CHECK(ShapeUtil::IsArray(user->shape()) && - ShapeUtil::IsArray(operand->shape())); + CHECK(user->shape().IsArray() && operand->shape().IsArray()); if (!ShapeUtil::IsScalar(operand->shape()) && operand->shape().rank() == user->shape().rank() && @@ -1192,7 +1191,7 @@ std::vector> GetArrayUsesOfBuffer( CHECK(buffer.IsArray()); std::vector> uses; for (const auto& buffer_alias : points_to_analysis.GetBufferAliases(buffer)) { - if (!ShapeUtil::IsArray(buffer_alias.instruction()->shape())) { + if (!buffer_alias.instruction()->shape().IsArray()) { continue; } // This alias must be the top-level (index == {}) of the instruction's @@ -1226,7 +1225,7 @@ Status LayoutAssignment::PropagateUseConstraintToDefs( if (ShapeUtil::IsLeafIndex(shape_layout.shape(), index)) { for (const LogicalBuffer* buffer : buffers) { if (constraints->BufferLayout(*buffer) == nullptr && - ShapeUtil::IsArray(buffer->shape())) { + buffer->shape().IsArray()) { TF_RETURN_IF_ERROR(constraints->SetBufferLayout( ShapeUtil::GetSubshape(shape_layout.shape(), index).layout(), *buffer, /*mandatory=*/true)); @@ -1257,11 +1256,10 @@ Status LayoutAssignment::PropagateOperandConstraint( // layout for the operands with the same ranks. const HloInstruction* operand = operand_constraint.operand(); const HloInstruction* user = operand_constraint.instruction(); - if (!ShapeUtil::IsArray(operand->shape())) { + if (!operand->shape().IsArray()) { return Status::OK(); } - if (instruction_can_change_layout_func_(user) && - !ShapeUtil::IsArray(user->shape())) { + if (instruction_can_change_layout_func_(user) && !user->shape().IsArray()) { return Status::OK(); } @@ -1316,7 +1314,7 @@ Status LayoutAssignment::PropagateOperandConstraint( TF_RETURN_IF_ERROR(ShapeUtil::ForEachSubshapeWithStatus( user->shape(), [&](const Shape& subshape, const ShapeIndex& shape_index) { - if (ShapeUtil::IsTuple(subshape)) { + if (subshape.IsTuple()) { return Status::OK(); } if (subshape.rank() <= 1) { @@ -1353,7 +1351,7 @@ Status LayoutAssignment::PropagateOperandConstraint( } TF_RETURN_IF_ERROR(ShapeUtil::ForEachSubshapeWithStatus( user->shape(), [&](const Shape& subshape, const ShapeIndex& shape_index) { - if (ShapeUtil::IsTuple(subshape)) { + if (subshape.IsTuple()) { return Status::OK(); } if (subshape.rank() <= 1) { @@ -1400,7 +1398,7 @@ Status LayoutAssignment::PropagateBufferConstraintToOperands( } if (!instruction_can_change_layout_func_(instruction)) { // Copy the layout to the operand. - if (buffer.IsArray() && ShapeUtil::IsArray(operand->shape()) && + if (buffer.IsArray() && operand->shape().IsArray() && operand->shape().rank() == LayoutUtil::MinorToMajor(buffer_constraint.layout()).size()) { TF_RETURN_IF_ERROR(constraints->SetArrayOperandLayout( @@ -1409,7 +1407,7 @@ Status LayoutAssignment::PropagateBufferConstraintToOperands( } } else { if (!buffer.IsTopLevel() || - !ShapeUtil::IsArray(instruction->operand(operand_no)->shape())) { + !instruction->operand(operand_no)->shape().IsArray()) { continue; // Don't touch buffers that are internal to a tuple. } VLOG(6) << "Propagating constraint to operand " << operand_no << " of " @@ -1496,7 +1494,7 @@ StatusOr InferArrayLayout( // This function should only be called for array shapes which don't yet have // layouts. const Shape& subshape = ShapeUtil::GetSubshape(instruction->shape(), index); - TF_RET_CHECK(ShapeUtil::IsArray(subshape)); + TF_RET_CHECK(subshape.IsArray()); TF_RET_CHECK(!subshape.has_layout()); // The instruction should not define the buffer at this index. @@ -1614,7 +1612,7 @@ Status LayoutAssignment::AssignLayouts(const LayoutConstraints& constraints, for (const LogicalBuffer* buffer : constraints.points_to_analysis().GetBuffersDefinedByInstruction( instruction)) { - if (!ShapeUtil::IsArray(buffer->shape())) { + if (!buffer->shape().IsArray()) { continue; } @@ -1638,7 +1636,7 @@ Status LayoutAssignment::AssignLayouts(const LayoutConstraints& constraints, TF_RETURN_IF_ERROR(ShapeUtil::ForEachMutableSubshapeWithStatus( instruction->mutable_shape(), [instruction, &constraints](Shape* subshape, const ShapeIndex& index) { - if (subshape->has_layout() || !ShapeUtil::IsArray(*subshape)) { + if (subshape->has_layout() || !subshape->IsArray()) { return Status::OK(); } // Set Layout of subshape to match layout of LogicalBuffer which @@ -2099,7 +2097,7 @@ bool LayoutAssignment::InstructionCanChangeLayout( /* static */ bool LayoutAssignment::IsAtMostRank1(const Shape& shape) { - if (ShapeUtil::IsArray(shape)) { + if (shape.IsArray()) { return shape.rank() <= 1; } return absl::c_all_of(shape.tuple_shapes(), [](const Shape& subshape) { diff --git a/tensorflow/compiler/xla/service/llvm_ir/fused_ir_emitter.cc b/tensorflow/compiler/xla/service/llvm_ir/fused_ir_emitter.cc index 38f2b5da23..03a475b40b 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/fused_ir_emitter.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/fused_ir_emitter.cc @@ -115,7 +115,7 @@ Status FusedIrEmitter::HandleGetTupleElement( /*alignment=*/1, tuple_ptr, b_, module_); }; - if (!ShapeUtil::IsTuple(get_tuple_element->shape())) { + if (!get_tuple_element->shape().IsTuple()) { indexed_generators_[get_tuple_element] = [=](const IrArray::Index& index) -> StatusOr { // TODO(b/34080002) Add aliasing information to tuple element IrArray. diff --git a/tensorflow/compiler/xla/service/llvm_ir/ir_array.cc b/tensorflow/compiler/xla/service/llvm_ir/ir_array.cc index 38078cd52b..f658761dff 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/ir_array.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/ir_array.cc @@ -117,7 +117,7 @@ IrArray::IrArray(llvm::Value* base_ptr, const Shape& shape) ++depth; } - if (!ShapeUtil::IsArray(*shape_) || ShapeUtil::IsScalar(*shape_)) { + if (!shape_->IsArray() || ShapeUtil::IsScalar(*shape_)) { DCHECK(depth == 1 || depth == 0) << depth; } else { DCHECK_EQ(depth, shape_->rank()) << shape.ShortDebugString(); diff --git a/tensorflow/compiler/xla/service/llvm_ir/llvm_util.cc b/tensorflow/compiler/xla/service/llvm_ir/llvm_util.cc index ceea24685a..75c4245f5f 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/llvm_util.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/llvm_util.cc @@ -219,10 +219,10 @@ int GetSizeInBits(llvm::Type* type) { llvm::Type* ShapeToIrType(const Shape& shape, llvm::Module* module) { llvm::Type* result_type = PrimitiveTypeToIrType(shape.element_type(), module); - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { // A tuple buffer is an array of pointers. result_type = llvm::ArrayType::get(result_type, shape.tuple_shapes_size()); - } else if (ShapeUtil::IsArray(shape)) { + } else if (shape.IsArray()) { for (int64 dimension : LayoutUtil::MinorToMajor(shape)) { result_type = llvm::ArrayType::get(result_type, shape.dimensions(dimension)); diff --git a/tensorflow/compiler/xla/service/llvm_ir/tuple_ops.cc b/tensorflow/compiler/xla/service/llvm_ir/tuple_ops.cc index a60643bc75..d8d2700e19 100644 --- a/tensorflow/compiler/xla/service/llvm_ir/tuple_ops.cc +++ b/tensorflow/compiler/xla/service/llvm_ir/tuple_ops.cc @@ -93,7 +93,7 @@ llvm::Value* EmitGetTupleElement(const Shape& target_shape, int64 index, llvm::LoadInst* src_buffer = b->CreateLoad(element_ptr); // Mark the loaded pointer as dereferenceable if we know its shape. - if (!ShapeUtil::IsOpaque(target_shape)) { + if (!target_shape.IsOpaque()) { SetDereferenceableMetadataForLoad( src_buffer, ByteSizeOf(target_shape, src_buffer->getModule()->getDataLayout())); diff --git a/tensorflow/compiler/xla/service/pattern_matcher.h b/tensorflow/compiler/xla/service/pattern_matcher.h index b9616e9132..c362a60d94 100644 --- a/tensorflow/compiler/xla/service/pattern_matcher.h +++ b/tensorflow/compiler/xla/service/pattern_matcher.h @@ -775,7 +775,7 @@ class ShapePatternIsArrayImpl { explicit constexpr ShapePatternIsArrayImpl() {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - if (!ShapeUtil::IsArray(*shape)) { + if (!shape->IsArray()) { EXPLAIN << "Shape is not an array"; return false; } @@ -793,7 +793,7 @@ class ShapePatternIsTupleImpl { explicit constexpr ShapePatternIsTupleImpl() {} bool Match(const ::xla::Shape* shape, MatchOption option) const { - if (!ShapeUtil::IsTuple(*shape)) { + if (!shape->IsTuple()) { EXPLAIN << "Shape is not a tuple"; return false; } diff --git a/tensorflow/compiler/xla/service/shape_inference.cc b/tensorflow/compiler/xla/service/shape_inference.cc index 6d02c81076..d38826db3b 100644 --- a/tensorflow/compiler/xla/service/shape_inference.cc +++ b/tensorflow/compiler/xla/service/shape_inference.cc @@ -50,7 +50,7 @@ bool AllUnique(absl::Span slice) { } Status ExpectArray(const Shape& shape, absl::string_view op_type) { - if (!ShapeUtil::IsArray(shape)) { + if (!shape.IsArray()) { return InvalidArgument("Expected array argument for %s, but got %s.", string(op_type), ShapeUtil::HumanString(shape)); } @@ -70,7 +70,7 @@ Status VerifyReducerShape(const ProgramShape& reducer_shape, const Shape& accumulator_shape = reducer_shape.result(); std::vector accumulator_subshapes; - if (ShapeUtil::IsArray(accumulator_shape)) { + if (accumulator_shape.IsArray()) { if (inputs != 1) { return InvalidArgument( "Reduction function must produce a tuple with %d elements, but " @@ -78,7 +78,7 @@ Status VerifyReducerShape(const ProgramShape& reducer_shape, inputs); } accumulator_subshapes.push_back(&accumulator_shape); - } else if (ShapeUtil::IsTuple(accumulator_shape)) { + } else if (accumulator_shape.IsTuple()) { if (ShapeUtil::TupleElementCount(accumulator_shape) != inputs) { return InvalidArgument( "Reduction function must produce a tuple with %d elements, but has " @@ -401,7 +401,7 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, ShapeUtil::HumanString(operand_shape), PrimitiveType_Name(new_element_type)); } - if (!ShapeUtil::IsArray(operand_shape) || + if (!operand_shape.IsArray() || !primitive_util::IsArrayType(new_element_type)) { // Note: we may want to support tuple conversions via this operation in the // future, by recursing into the tuple elements to check all sub-conversions @@ -424,7 +424,7 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, ShapeUtil::HumanString(operand_shape), PrimitiveType_Name(new_element_type)); } - if (!ShapeUtil::IsArray(operand_shape) || + if (!operand_shape.IsArray() || !primitive_util::IsArrayType(new_element_type)) { // Note: we may want to support tuple conversions via this operation in the // future, by recursing into the tuple elements to check all sub-conversions @@ -472,7 +472,7 @@ StatusOr InferWindowOutputShape(const Shape& base_shape, /* static */ StatusOr ShapeInference::InferPadShape( const Shape& operand_shape, const Shape& padding_value_shape, const PaddingConfig& padding_config) { - if (!ShapeUtil::IsArray(operand_shape)) { + if (!operand_shape.IsArray()) { return InvalidArgument( "Pad operation does not support tuple-shape operands."); } @@ -1892,7 +1892,7 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, /* static */ StatusOr ShapeInference::InferCollectivePermuteShape( const Shape& shape) { - TF_RET_CHECK(ShapeUtil::IsArray(shape)); + TF_RET_CHECK(shape.IsArray()); return shape; } @@ -2262,7 +2262,7 @@ ShapeInference::InferDegenerateDimensionBroadcastShape(HloOpcode operation, /* static */ StatusOr ShapeInference::InferGetTupleElementShape( const Shape& arg, int64 index) { - if (!ShapeUtil::IsTuple(arg)) { + if (!arg.IsTuple()) { return InvalidArgument( "Cannot infer shape: attempting to index into non-tuple: %s.", ShapeUtil::HumanString(arg)); diff --git a/tensorflow/compiler/xla/service/shaped_buffer.cc b/tensorflow/compiler/xla/service/shaped_buffer.cc index 28a30b5ee2..d90dde3b13 100644 --- a/tensorflow/compiler/xla/service/shaped_buffer.cc +++ b/tensorflow/compiler/xla/service/shaped_buffer.cc @@ -85,7 +85,7 @@ string ShapedBuffer::ToString() const { on_device_shape(), [this, &s](const Shape& subshape, const ShapeIndex& index) { string shape_str; - if (ShapeUtil::IsTuple(subshape)) { + if (subshape.IsTuple()) { shape_str = "tuple"; } else { shape_str = ShapeUtil::HumanStringWithLayout(subshape); diff --git a/tensorflow/compiler/xla/service/transfer_manager.cc b/tensorflow/compiler/xla/service/transfer_manager.cc index 146815da54..15ef623cc7 100644 --- a/tensorflow/compiler/xla/service/transfer_manager.cc +++ b/tensorflow/compiler/xla/service/transfer_manager.cc @@ -142,7 +142,7 @@ Status TransferManager::TransferArrayToDeviceAsync( se::Stream* stream, const LiteralSlice& literal, const se::DeviceMemoryBase& dest) { const Shape on_device_shape = HostShapeToDeviceShape(literal.shape()); - TF_RET_CHECK(ShapeUtil::IsArray(on_device_shape)) + TF_RET_CHECK(on_device_shape.IsArray()) << "On-device representation of " << ShapeUtil::HumanString(literal.shape()) << " is not an array: " << ShapeUtil::HumanString(on_device_shape); @@ -227,7 +227,7 @@ Status TransferManager::WriteTupleIndexTablesAsync( return ShapeUtil::ForEachSubshapeWithStatus( device_buffer.on_device_shape(), [&](const Shape& device_subshape, const ShapeIndex& index) -> Status { - if (ShapeUtil::IsTuple(device_subshape)) { + if (device_subshape.IsTuple()) { se::DeviceMemoryBase device_memory = device_buffer.buffer(index); TF_RET_CHECK(GetByteSizeRequirement(device_subshape) == device_memory.size()); @@ -250,7 +250,7 @@ Status TransferManager::WriteTupleIndexTablesAsync( Status TransferManager::WriteRootTupleIndexTable( se::Stream* stream, const ShapedBuffer& device_buffer) { - TF_RET_CHECK(ShapeUtil::IsTuple(device_buffer.on_device_shape())); + TF_RET_CHECK(device_buffer.on_device_shape().IsTuple()); se::DeviceMemoryBase device_memory = device_buffer.buffer({}); TF_RET_CHECK(GetByteSizeRequirement(device_buffer.on_device_shape()) == device_memory.size()); diff --git a/tensorflow/compiler/xla/service/tuple_points_to_analysis.cc b/tensorflow/compiler/xla/service/tuple_points_to_analysis.cc index 50d51eaeb7..b1f0672c60 100644 --- a/tensorflow/compiler/xla/service/tuple_points_to_analysis.cc +++ b/tensorflow/compiler/xla/service/tuple_points_to_analysis.cc @@ -210,7 +210,7 @@ Status TuplePointsToAnalysis::DefaultAction(HloInstruction* hlo_instruction) { &logical_buffer_analysis_->GetBuffer(hlo_instruction, index)); }); - if (ShapeUtil::IsTuple(hlo_instruction->shape())) { + if (hlo_instruction->shape().IsTuple()) { // If the hlo instruction is a tuple-shaped, then trivially the instruction // itself is the source of the tuple. points_to_set.add_tuple_source({}, hlo_instruction); diff --git a/tensorflow/compiler/xla/service/tuple_points_to_analysis_test.cc b/tensorflow/compiler/xla/service/tuple_points_to_analysis_test.cc index 561762b5d4..d8875ca747 100644 --- a/tensorflow/compiler/xla/service/tuple_points_to_analysis_test.cc +++ b/tensorflow/compiler/xla/service/tuple_points_to_analysis_test.cc @@ -734,7 +734,7 @@ class FusionPointsToAnalysisTest : public TuplePointsToAnalysisTest { // Returns all users of 'fusion_paran' at 'tuple_index'. std::vector GetFusionParameterUsersAt( HloInstruction* fusion_param, int64 tuple_index) { - CHECK(ShapeUtil::IsTuple(fusion_param->shape())); + CHECK(fusion_param->shape().IsTuple()); std::vector users_at_tuple_index; for (auto user : fusion_param->users()) { CHECK_EQ(HloOpcode::kGetTupleElement, user->opcode()); diff --git a/tensorflow/compiler/xla/service/tuple_util.cc b/tensorflow/compiler/xla/service/tuple_util.cc index cfb0c787d0..90ea79ec26 100644 --- a/tensorflow/compiler/xla/service/tuple_util.cc +++ b/tensorflow/compiler/xla/service/tuple_util.cc @@ -21,7 +21,7 @@ namespace xla { /*static*/ HloInstruction* TupleUtil::ExtractPrefix(HloInstruction* input_tuple, int64 elements) { - CHECK(ShapeUtil::IsTuple(input_tuple->shape())); + CHECK(input_tuple->shape().IsTuple()); HloComputation* computation = input_tuple->parent(); const Shape& input_shape = input_tuple->shape(); @@ -41,7 +41,7 @@ namespace xla { /*static*/ HloInstruction* TupleUtil::AppendSuffix( HloInstruction* input_tuple, absl::Span trailing_values) { - CHECK(ShapeUtil::IsTuple(input_tuple->shape())); + CHECK(input_tuple->shape().IsTuple()); HloComputation* computation = input_tuple->parent(); const Shape& input_shape = input_tuple->shape(); diff --git a/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.cc b/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.cc index 41011176ff..a1c627a319 100644 --- a/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.cc +++ b/tensorflow/compiler/xla/service/while_loop_invariant_code_motion.cc @@ -127,7 +127,7 @@ WhileLoopInvariantCodeMotion::TryHoistingInvariantInstructionsFromWhileBody( HloInstruction* while_instr) { auto print_no_metadata = HloPrintOptions{}.set_print_metadata(false); - if (!ShapeUtil::IsTuple(while_instr->shape())) { + if (!while_instr->shape().IsTuple()) { // This restriction leaves one interesting pattern on the table: // // while_body(f32[1024, 1024] %param) { @@ -168,7 +168,7 @@ WhileLoopInvariantCodeMotion::TryHoistingInvariantInstructionsFromWhileBody( // is no benefit to hoisting them unless something that uses it is also // hoisted. for (auto* instr : WhileUtil::GetInvariantGTEsForWhileBody(*while_body)) { - if (ShapeUtil::IsArray(instr->shape())) { + if (instr->shape().IsArray()) { // TODO(b/79147885): We should try to generalize this to tuples for // uniformity's sake, if nothing else. InsertOrDie(&unhoisted_invariant_instructions, instr); @@ -221,7 +221,7 @@ WhileLoopInvariantCodeMotion::TryHoistingInvariantInstructionsFromWhileBody( ShapeUtil::ForEachSubshape( operand->shape(), [&input_size](const Shape& subshape, const ShapeIndex& /*index*/) { - if (ShapeUtil::IsArray(subshape)) { + if (subshape.IsArray()) { input_size += ShapeUtil::ByteSizeOfElements(subshape); } }); @@ -229,7 +229,7 @@ WhileLoopInvariantCodeMotion::TryHoistingInvariantInstructionsFromWhileBody( ShapeUtil::ForEachSubshape( instruction->shape(), [&output_size](const Shape& subshape, const ShapeIndex& /*index*/) { - if (ShapeUtil::IsArray(subshape)) { + if (subshape.IsArray()) { output_size += ShapeUtil::ByteSizeOfElements(subshape); } }); diff --git a/tensorflow/compiler/xla/service/while_loop_simplifier.cc b/tensorflow/compiler/xla/service/while_loop_simplifier.cc index d30f67dd81..772faa25e2 100644 --- a/tensorflow/compiler/xla/service/while_loop_simplifier.cc +++ b/tensorflow/compiler/xla/service/while_loop_simplifier.cc @@ -58,7 +58,7 @@ static StatusOr TryRemoveDeadWhileParams(HloInstruction* while_op) { HloComputation* while_body = while_op->while_body(); HloInstruction* while_body_root = while_body->root_instruction(); - if (!ShapeUtil::IsTuple(while_init->shape())) { + if (!while_init->shape().IsTuple()) { VLOG(2) << "While op's carried value isn't tuple shaped."; return false; } @@ -583,8 +583,7 @@ static StatusOr TryPropagateConstant(HloInstruction* while_op) { static std::unique_ptr UnflattenTupleInstr( absl::Span instrs, const Shape& desired_shape, std::vector>* new_instrs) { - CHECK(ShapeUtil::IsTuple(desired_shape)) - << ShapeUtil::HumanString(desired_shape); + CHECK(desired_shape.IsTuple()) << ShapeUtil::HumanString(desired_shape); // For each child shape in `desired_shape`, slice out the correct number of // `instrs` and call UnflattenTupleInstr recursively. At each step we remove @@ -593,7 +592,7 @@ static std::unique_ptr UnflattenTupleInstr( std::vector elems; for (int64 i = 0; i < desired_shape.tuple_shapes_size(); ++i) { const Shape& subshape = desired_shape.tuple_shapes(i); - if (!ShapeUtil::IsTuple(subshape)) { + if (!subshape.IsTuple()) { elems.push_back(instrs[0]); instrs.remove_prefix(1); continue; @@ -603,7 +602,7 @@ static std::unique_ptr UnflattenTupleInstr( int64 num_leaves = 0; ShapeUtil::ForEachSubshape( subshape, [&](const Shape& s, const ShapeIndex& /*index*/) { - if (!ShapeUtil::IsTuple(s)) { + if (!s.IsTuple()) { ++num_leaves; } }); @@ -625,7 +624,7 @@ static std::vector GetFlatTupleElems( HloInstruction* instr, std::vector>* new_instrs) { const auto& shape = instr->shape(); - if (!ShapeUtil::IsTuple(shape)) { + if (!shape.IsTuple()) { return {instr}; } std::vector elems; @@ -665,7 +664,7 @@ static StatusOr TryFlattenNestedTuples(HloInstruction* while_op) { std::vector flattened_shape_elems; ShapeUtil::ForEachSubshape(while_shape, [&](const Shape& s, const ShapeIndex& /*index*/) { - if (!ShapeUtil::IsTuple(s)) { + if (!s.IsTuple()) { flattened_shape_elems.push_back(s); } }); diff --git a/tensorflow/compiler/xla/service/while_util.cc b/tensorflow/compiler/xla/service/while_util.cc index 039ccda732..d77386497a 100644 --- a/tensorflow/compiler/xla/service/while_util.cc +++ b/tensorflow/compiler/xla/service/while_util.cc @@ -97,7 +97,7 @@ WidenWhileBody(HloComputation* narrow_body, const Shape& wide_shape) { WhileUtil::MakeInstructionsLiveIn( HloInstruction* while_instr, absl::Span instructions) { - CHECK(ShapeUtil::IsTuple(while_instr->shape())); + CHECK(while_instr->shape().IsTuple()); int64 elements_in_old_while_shape = while_instr->shape().tuple_shapes_size(); Shape new_while_shape = while_instr->shape(); diff --git a/tensorflow/compiler/xla/service/zero_sized_hlo_elimination.cc b/tensorflow/compiler/xla/service/zero_sized_hlo_elimination.cc index 83d696fe09..a76fbf3f66 100644 --- a/tensorflow/compiler/xla/service/zero_sized_hlo_elimination.cc +++ b/tensorflow/compiler/xla/service/zero_sized_hlo_elimination.cc @@ -31,8 +31,7 @@ StatusOr ZeroSizedHloElimination::Run(HloModule* module) { bool changed = false; for (HloComputation* comp : module->MakeNonfusionComputations()) { for (HloInstruction* instruction : comp->MakeInstructionPostOrder()) { - if (instruction->HasSideEffect() || - !ShapeUtil::IsArray(instruction->shape()) || + if (instruction->HasSideEffect() || !instruction->shape().IsArray() || instruction->opcode() == HloOpcode::kConstant) { continue; } diff --git a/tensorflow/compiler/xla/shape.cc b/tensorflow/compiler/xla/shape.cc index cec8dc2c20..b206345db2 100644 --- a/tensorflow/compiler/xla/shape.cc +++ b/tensorflow/compiler/xla/shape.cc @@ -61,12 +61,6 @@ string Shape::ToString(bool print_layout) const { } } -int64 Shape::rank() const { - CHECK(ShapeUtil::IsArray(*this)) - << "Non-arrays do not have a rank, shape: " << *this; - return dimensions_.size(); -} - std::ostream& operator<<(std::ostream& out, const Shape& shape) { out << shape.ToString(/*print_layout=*/true); return out; diff --git a/tensorflow/compiler/xla/shape.h b/tensorflow/compiler/xla/shape.h index 91edafe2f7..dbd8a53f0e 100644 --- a/tensorflow/compiler/xla/shape.h +++ b/tensorflow/compiler/xla/shape.h @@ -21,6 +21,7 @@ limitations under the License. #include "absl/types/optional.h" #include "tensorflow/compiler/xla/layout.h" +#include "tensorflow/compiler/xla/primitive_util.h" #include "tensorflow/compiler/xla/types.h" #include "tensorflow/compiler/xla/xla_data.pb.h" #include "tensorflow/core/platform/types.h" @@ -46,7 +47,16 @@ class Shape { // Returns the rank (number of dimensions) of the given shape. Shape must be // an array. - int64 rank() const; + int64 rank() const { + CHECK(IsArray()) << "Non-arrays do not have a rank, shape: " << ToString(); + return dimensions_.size(); + } + + // Returns whether the shape is of the specified type (array, tuple, etc). + bool IsArray() const { return primitive_util::IsArrayType(element_type()); } + bool IsTuple() const { return element_type() == TUPLE; } + bool IsToken() const { return element_type() == TOKEN; } + bool IsOpaque() const { return element_type() == OPAQUE; } // The following methods mirror the protobuf generated code interface for the // message ShapeProto. This enabled easy migration of this data structure diff --git a/tensorflow/compiler/xla/shape_layout.cc b/tensorflow/compiler/xla/shape_layout.cc index d44db89d57..a000886d60 100644 --- a/tensorflow/compiler/xla/shape_layout.cc +++ b/tensorflow/compiler/xla/shape_layout.cc @@ -52,7 +52,7 @@ bool ShapeLayout::MatchesLayoutInShape(const Shape& shape) const { const Layout& ShapeLayout::layout() const { CHECK(LayoutIsSet()); - CHECK(!ShapeUtil::IsTuple(shape_)); + CHECK(!shape_.IsTuple()); return shape_.layout(); } @@ -61,15 +61,15 @@ void ShapeLayout::Clear() { LayoutUtil::ClearLayout(&shape_); } bool ShapeLayout::LayoutIsSet() const { return LayoutUtil::HasLayout(shape_); } void ShapeLayout::ResetLayout(const Layout& layout) { - CHECK(!ShapeUtil::IsTuple(shape_)); - CHECK(!ShapeUtil::IsOpaque(shape_)); + CHECK(!shape_.IsTuple()); + CHECK(!shape_.IsOpaque()); *shape_.mutable_layout() = layout; TF_CHECK_OK(ShapeUtil::ValidateShape(shape_)); } void ShapeLayout::ResetLayout(const Layout& layout, ShapeIndexView shape_index) { - CHECK(ShapeUtil::IsTuple(shape_)); + CHECK(shape_.IsTuple()); *ShapeUtil::GetMutableSubshape(&shape_, shape_index)->mutable_layout() = layout; TF_CHECK_OK(ShapeUtil::ValidateShape(shape_)); diff --git a/tensorflow/compiler/xla/shape_tree.h b/tensorflow/compiler/xla/shape_tree.h index 7bf9772916..089120179e 100644 --- a/tensorflow/compiler/xla/shape_tree.h +++ b/tensorflow/compiler/xla/shape_tree.h @@ -395,7 +395,7 @@ class ShapeTreeIterator template int64 ShapeTree::CountSubshapes(const Shape& shape) { int64 current_count = 1; - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { int64 count = ShapeUtil::TupleElementCount(shape); for (int i = 0; i < count; ++i) { current_count += CountSubshapes(shape.tuple_shapes(i)); @@ -407,7 +407,7 @@ int64 ShapeTree::CountSubshapes(const Shape& shape) { template void ShapeTree::InitChildren(const Shape& shape, const T& init_value, Node* node, Index* index) { - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { const int64 size = ShapeUtil::TupleElementCount(shape); #ifndef NDEBUG index->children_count = size; @@ -443,7 +443,7 @@ void ShapeTree::InitChildren(const Shape& shape, const T& init_value, template void ShapeTree::InitChildren(const Shape& shape, Node* node, Index* index) { - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { const int64 size = ShapeUtil::TupleElementCount(shape); #ifndef NDEBUG index->children_count = size; diff --git a/tensorflow/compiler/xla/shape_util.cc b/tensorflow/compiler/xla/shape_util.cc index 8ad241f2c9..cb96ab6fca 100644 --- a/tensorflow/compiler/xla/shape_util.cc +++ b/tensorflow/compiler/xla/shape_util.cc @@ -81,8 +81,7 @@ bool ShapeIndexView::StartsWith(ShapeIndexView prefix) const { /* static */ bool ShapeUtil::IsArrayPrimitiveType( PrimitiveType primitive_type) { - return primitive_type != PRIMITIVE_TYPE_INVALID && primitive_type != TUPLE && - primitive_type != OPAQUE && primitive_type != TOKEN; + return primitive_util::IsArrayType(primitive_type); } namespace { @@ -99,13 +98,13 @@ bool CompareShapes(const Shape& lhs, const Shape& rhs, bool compare_layouts, return false; } - if (ShapeUtil::IsTuple(lhs)) { + if (lhs.IsTuple()) { return absl::c_equal(lhs.tuple_shapes(), rhs.tuple_shapes(), [=](const Shape& l, const Shape& r) { return CompareShapes(l, r, compare_layouts, ignore_fp_precision); }); - } else if (!ShapeUtil::IsArray(lhs)) { + } else if (!lhs.IsArray()) { // Non-tuple, non-array tupes such as opaque and token types are trivially // the same. return true; @@ -201,8 +200,7 @@ StatusOr MakeShapeWithLayoutInternal( } /* static */ int64 ShapeUtil::Rank(const Shape& shape) { - CHECK(ShapeUtil::IsArray(shape)) - << "Non-arrays do not have a rank, shape: " << shape; + CHECK(shape.IsArray()) << "Non-arrays do not have a rank, shape: " << shape; return shape.dimensions_size(); } @@ -472,7 +470,7 @@ ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout( } /* static */ bool ShapeUtil::IsZeroElementArray(const Shape& shape) { - return ShapeUtil::IsArray(shape) && ElementsIn(shape) == 0; + return shape.IsArray() && ElementsIn(shape) == 0; } /* static */ bool ShapeUtil::IsScalarWithElementType( @@ -536,8 +534,8 @@ ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout( /* static */ bool ShapeUtil::SameDimensions(const Shape& lhs, const Shape& rhs) { - CHECK(ShapeUtil::IsArray(lhs)); - CHECK(ShapeUtil::IsArray(rhs)); + CHECK(lhs.IsArray()); + CHECK(rhs.IsArray()); return absl::c_equal(lhs.dimensions(), rhs.dimensions()); } @@ -663,7 +661,7 @@ ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout( /* static */ int64 ShapeUtil::ByteSizeOfElements(const Shape& shape) { TF_DCHECK_OK(ValidateShape(shape)); - CHECK(ShapeUtil::IsArray(shape)); + CHECK(shape.IsArray()); int64 allocated_element_count; if (LayoutUtil::IsSparseArray(shape)) { @@ -907,7 +905,7 @@ bool ShapeUtil::IsLeafIndex(const Shape& shape, const ShapeIndex& index) { } /* static */ bool ShapeUtil::HasDegenerateDimensions(const Shape& shape) { - CHECK(ShapeUtil::IsArray(shape)); + CHECK(shape.IsArray()); return absl::c_linear_search(shape.dimensions(), 1); } @@ -924,7 +922,7 @@ Status ForEachSubshapeHelper(const Shape& shape, const ShapeUtil::StatusVisitorFunction& func, ShapeIndex* index) { TF_RETURN_IF_ERROR(func(shape, *index)); - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { for (int64 i = 0; i < ShapeUtil::TupleElementCount(shape); ++i) { index->push_back(i); TF_RETURN_IF_ERROR(ForEachSubshapeHelper( @@ -941,7 +939,7 @@ Status ForEachMutableSubshapeHelper( Shape* shape, const ShapeUtil::MutatingStatusVisitorFunction& func, ShapeIndex* index) { TF_RETURN_IF_ERROR(func(shape, *index)); - if (ShapeUtil::IsTuple(*shape)) { + if (shape->IsTuple()) { for (int64 i = 0; i < ShapeUtil::TupleElementCount(*shape); ++i) { index->push_back(i); TF_RETURN_IF_ERROR(ForEachMutableSubshapeHelper( diff --git a/tensorflow/compiler/xla/shape_util.h b/tensorflow/compiler/xla/shape_util.h index e1c37d79e2..b28402455f 100644 --- a/tensorflow/compiler/xla/shape_util.h +++ b/tensorflow/compiler/xla/shape_util.h @@ -207,7 +207,7 @@ class ShapeUtil { // Returns the number of bytes used to store the primitive_type. // - // Precondition: ShapeUtil::IsArray(shape) + // Precondition: shape.IsArray() static int64 ByteSizeOfPrimitiveType(PrimitiveType primitive_type); // Returns the number of bytes required to store the tuple member pointers for @@ -445,24 +445,28 @@ class ShapeUtil { static bool ElementIsSigned(const Shape& shape); // Returns whether the shape is a tuple. + ABSL_DEPRECATED("Use Shape::IsTuple instead.") static bool IsTuple(const Shape& shape) { return shape.element_type() == TUPLE; } // Returns whether the shape is an opaque value (i.e. an 'existential' typed // value that is passed to CustomCall operations). + ABSL_DEPRECATED("Use Shape::IsOpaque instead.") static bool IsOpaque(const Shape& shape) { return shape.element_type() == OPAQUE; } // Returns whether the shape is an token value used for ordering // side-effecting operations. + ABSL_DEPRECATED("Use Shape::IsToken instead.") static bool IsToken(const Shape& shape) { return shape.element_type() == TOKEN; } // Returns whether the shape is an array. Note that scalars are considered // arrays. + ABSL_DEPRECATED("Use Shape::IsArray instead.") static bool IsArray(const Shape& shape); // Returns whether the given primitive type corresponds to an array shape. diff --git a/tensorflow/compiler/xla/tests/client_library_test_base.cc b/tensorflow/compiler/xla/tests/client_library_test_base.cc index 20f6c189da..edb95c973b 100644 --- a/tensorflow/compiler/xla/tests/client_library_test_base.cc +++ b/tensorflow/compiler/xla/tests/client_library_test_base.cc @@ -224,7 +224,7 @@ Status ClientLibraryTestBase::ComputeAndCompareLiteralWithAllInputLayouts( TF_ASSIGN_OR_RETURN(auto literal, client_->Transfer(*arguments[index], nullptr)); // Skip tuples because they don't have a rank. - if (ShapeUtil::IsTuple(literal.shape())) { + if (literal.shape().IsTuple()) { layout_strings.push_back( ShapeUtil::HumanStringWithLayout(literal.shape())); arguments_with_layout.push_back(arguments[index]); diff --git a/tensorflow/compiler/xla/tests/client_test.cc b/tensorflow/compiler/xla/tests/client_test.cc index 363dee74b2..d5b3a4d14f 100644 --- a/tensorflow/compiler/xla/tests/client_test.cc +++ b/tensorflow/compiler/xla/tests/client_test.cc @@ -96,7 +96,7 @@ XLA_TEST_F(ClientTest, ExecuteWithTupleLayout) { LiteralTestUtil::ExpectR2Equal({{10, 20}, {30, 40}}, LiteralSlice(result, {1})); - EXPECT_TRUE(ShapeUtil::IsTuple(result.shape())); + EXPECT_TRUE(result.shape().IsTuple()); EXPECT_EQ(2, ShapeUtil::TupleElementCount(result.shape())); EXPECT_TRUE(ShapeUtil::Equal( diff --git a/tensorflow/compiler/xla/tests/local_client_execute_test.cc b/tensorflow/compiler/xla/tests/local_client_execute_test.cc index a99b43f469..6522c56325 100644 --- a/tensorflow/compiler/xla/tests/local_client_execute_test.cc +++ b/tensorflow/compiler/xla/tests/local_client_execute_test.cc @@ -205,7 +205,7 @@ XLA_TEST_F(LocalClientExecuteTest, TupleResult) { ScopedShapedBuffer result = ExecuteLocallyOrDie(computation, {&x_array, &y_array}); - EXPECT_TRUE(ShapeUtil::IsTuple(result.on_host_shape())); + EXPECT_TRUE(result.on_host_shape().IsTuple()); EXPECT_EQ(3, ShapeUtil::TupleElementCount(result.on_host_shape())); Literal result_literal = ShapedBufferToLiteral(result); @@ -233,7 +233,7 @@ XLA_TEST_F(LocalClientExecuteTest, NestedTupleResult) { ScopedShapedBuffer result = ExecuteLocallyOrDie(computation, {&x_array, &y_array}); - EXPECT_TRUE(ShapeUtil::IsTuple(result.on_host_shape())); + EXPECT_TRUE(result.on_host_shape().IsTuple()); EXPECT_EQ(2, ShapeUtil::TupleElementCount(result.on_host_shape())); Literal result_literal = ShapedBufferToLiteral(result); @@ -311,7 +311,7 @@ XLA_TEST_F(LocalClientExecuteTest, TupleArguments) { ScopedShapedBuffer result = ExecuteLocallyOrDie(computation, {&x_buffer, &y_buffer}); - EXPECT_TRUE(ShapeUtil::IsTuple(result.on_host_shape())); + EXPECT_TRUE(result.on_host_shape().IsTuple()); EXPECT_EQ(2, ShapeUtil::TupleElementCount(result.on_host_shape())); Literal result_literal = ShapedBufferToLiteral(result); diff --git a/tensorflow/compiler/xla/tests/test_utils.cc b/tensorflow/compiler/xla/tests/test_utils.cc index 96ccda6a79..290886624d 100644 --- a/tensorflow/compiler/xla/tests/test_utils.cc +++ b/tensorflow/compiler/xla/tests/test_utils.cc @@ -168,7 +168,7 @@ void PopulateWithRandomIntegralData(Literal* literal, std::minstd_rand0* engine, StatusOr MakeFakeLiteralInternal(const Shape& shape, std::minstd_rand0* engine, bool no_duplicates) { - if (ShapeUtil::IsTuple(shape)) { + if (shape.IsTuple()) { std::vector elements; for (const Shape& element_shape : shape.tuple_shapes()) { TF_ASSIGN_OR_RETURN( diff --git a/tensorflow/compiler/xrt/kernels/xrt_execute_op.cc b/tensorflow/compiler/xrt/kernels/xrt_execute_op.cc index 751329eefc..7f0ac123a5 100644 --- a/tensorflow/compiler/xrt/kernels/xrt_execute_op.cc +++ b/tensorflow/compiler/xrt/kernels/xrt_execute_op.cc @@ -229,7 +229,7 @@ Status XRTExecuteOp::DoWork(OpKernelContext* context) { shaped_buffer, device_ref.backend(), device_ref.device_ordinal(), &output_tuple)); if (config_proto.return_exploded_tuple() && - xla::ShapeUtil::IsTuple(output_tuple->on_device_shape())) { + output_tuple->on_device_shape().IsTuple()) { int64 tuple_element_count = xla::ShapeUtil::TupleElementCount(output_tuple->on_device_shape()); Tensor* output_tensor; -- GitLab From 626782650aa6859bf8d386d372744387a9cb4a6b Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 18:30:19 -0800 Subject: [PATCH 0225/1765] Add batch_dims argument to tf.gather. This provides a generalization of the behavior provided by tf.batch_gather, but is backwards-compatible with the existing tf.gather API. In particular: * tf.gather(..., batch_dims=0) is equivalent to tf.gather(...) * tf.gather(..., batch_dims=indices.shape.ndims-1) is equivalent to tf.batch_gather(...) In addition, the new batch_dims parameter can be used to specify a number of batch dimensions between these two extremes. E.g., in the following example, we use batch_dims=1 to indicate that only the outermost dimension is a batch dimension: >>> tf.batch_gather( ... params=[["a", "b", "c", "d"], ["e", "f", "g", "h"]], ... indices=[[2, 1], [0, 3]], ... batch_dims=1) [["c", "b"], ["e", "h"]] PiperOrigin-RevId: 226426563 --- tensorflow/python/kernel_tests/BUILD | 1 + .../python/kernel_tests/gather_op_test.py | 236 +++++++++++++++- tensorflow/python/ops/array_ops.py | 261 +++++++++++++----- .../python/ops/ragged/ragged_array_ops.py | 8 +- .../python/ops/ragged/ragged_dispatch.py | 3 +- .../tools/api/golden/v1/tensorflow.pbtxt | 2 +- .../tools/api/golden/v2/tensorflow.pbtxt | 6 +- tensorflow/tools/compatibility/ast_edits.py | 6 +- tensorflow/tools/compatibility/reorders_v2.py | 1 + tensorflow/tools/compatibility/tf_upgrade.py | 3 +- .../tools/compatibility/tf_upgrade_v2.py | 34 ++- .../tools/compatibility/tf_upgrade_v2_test.py | 24 ++ 12 files changed, 507 insertions(+), 78 deletions(-) diff --git a/tensorflow/python/kernel_tests/BUILD b/tensorflow/python/kernel_tests/BUILD index bd5c103b38..276342cbbc 100644 --- a/tensorflow/python/kernel_tests/BUILD +++ b/tensorflow/python/kernel_tests/BUILD @@ -1834,6 +1834,7 @@ cuda_py_test( size = "medium", srcs = ["gather_op_test.py"], additional_deps = [ + "@absl_py//absl/testing:parameterized", "//third_party/py/numpy", "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", diff --git a/tensorflow/python/kernel_tests/gather_op_test.py b/tensorflow/python/kernel_tests/gather_op_test.py index fc86068c3f..10a65e0053 100644 --- a/tensorflow/python/kernel_tests/gather_op_test.py +++ b/tensorflow/python/kernel_tests/gather_op_test.py @@ -18,8 +18,10 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +from absl.testing import parameterized import numpy as np +from tensorflow.python.eager import context from tensorflow.python.framework import constant_op from tensorflow.python.framework import dtypes from tensorflow.python.framework import ops @@ -32,7 +34,7 @@ _TEST_TYPES = (dtypes.int64, dtypes.float32, dtypes.complex64, dtypes.complex128) -class GatherTest(test.TestCase): +class GatherTest(test.TestCase, parameterized.TestCase): def _buildParams(self, data, dtype): data = data.astype(dtype.as_numpy_dtype) @@ -248,6 +250,238 @@ class GatherTest(test.TestCase): gather = array_ops.gather(params, indices, axis=2) self.assertAllEqual(gather.eval(), np.zeros((0, 0, 2))) + @parameterized.parameters([ + # batch_dims=0 (equivalent to tf.gather) + dict( # 2D indices + batch_dims=0, + params=[6, 7, 8, 9], + indices=[[2, 1], [0, 3]], + expected=[[8, 7], [6, 9]]), + dict( # 3D indices + batch_dims=0, + params=[6, 7, 8, 9], + indices=[[[3, 1], [2, 0]], [[0, 3], [2, 2]]], + expected=[[[9, 7], [8, 6]], [[6, 9], [8, 8]]]), + dict( # 4D indices + batch_dims=0, + params=[8, 9], + indices=[[[[0, 1], [1, 0]], [[0, 0], [1, 1]]], + [[[1, 1], [0, 0]], [[0, 1], [1, 0]]]], + expected=[[[[8, 9], [9, 8]], [[8, 8], [9, 9]]], + [[[9, 9], [8, 8]], [[8, 9], [9, 8]]]]), + + # batch_dims=indices.shape.ndims - 1 (equivalent to tf.batch_gather) + dict( # 2D indices (1 batch dim) + batch_dims=1, + params=[[10, 11, 12, 13], [20, 21, 22, 23]], + indices=[[2, 1], [0, 3]], + expected=[[12, 11], [20, 23]]), + dict( # 3D indices (2 batch dims) + batch_dims=2, + params=[[[100, 101], [110, 111]], [[200, 201], [210, 211]]], + indices=[[[0, 1], [1, 0]], [[0, 0], [1, 1]]], + expected=[[[100, 101], [111, 110]], [[200, 200], [211, 211]]]), + dict( # 2D indices (1 batch dim) + batch_dims=-1, + params=[[10, 11, 12, 13], [20, 21, 22, 23]], + indices=[[2, 1], [0, 3]], + expected=[[12, 11], [20, 23]]), + dict( # 3D indices (2 batch dims) + batch_dims=-1, + params=[[[100, 101], [110, 111]], [[200, 201], [210, 211]]], + indices=[[[0, 1], [1, 0]], [[0, 0], [1, 1]]], + expected=[[[100, 101], [111, 110]], [[200, 200], [211, 211]]]), + + # 0 < batch_dims < indices.shape.ndims - 1 + dict( # 3D indices (1 batch dim) + batch_dims=1, + params=[[10, 11, 12, 13], [20, 21, 22, 23]], + indices=[[[3, 1], [2, 0]], [[0, 3], [2, 2]]], + expected=[[[13, 11], [12, 10]], [[20, 23], [22, 22]]]), + dict( # 4D indices (1 batch dim) + batch_dims=1, + params=[[6, 7], [8, 9]], + indices=[[[[0, 1], [1, 0]], [[0, 0], [1, 1]]], + [[[1, 1], [0, 0]], [[0, 1], [1, 0]]]], + expected=[[[[6, 7], [7, 6]], [[6, 6], [7, 7]]], + [[[9, 9], [8, 8]], [[8, 9], [9, 8]]]]), + dict( # 4D indices (2 batch dims) + batch_dims=2, + params=[[[2, 3], [4, 5]], [[6, 7], [8, 9]]], + indices=[[[[0, 1], [1, 0]], [[0, 0], [1, 1]]], + [[[1, 1], [0, 0]], [[0, 1], [1, 0]]]], + expected=[[[[2, 3], [3, 2]], [[4, 4], [5, 5]]], + [[[7, 7], [6, 6]], [[8, 9], [9, 8]]]]), + + # axis > 0 + dict( # 3D indices, batch_dims=1, axis=2 + # params.shape = [I1, J1, J2] = [2, 2, 3] + # indices.shape = [I1, K1, K2] = [2, 1, 5] + # result.shape = [I1, J1, K1, K2] = [2, 2, 1, 5] + batch_dims=1, + axis=2, + params=[[[10, 11, 12], [13, 14, 15]], [[20, 21, 22], [23, 24, 25]]], + indices=[[[0, 1, 2, 1, 0]], [[0, 1, 2, 1, 0]]], + expected=[[[[10, 11, 12, 11, 10]], [[13, 14, 15, 14, 13]]], + [[[20, 21, 22, 21, 20]], [[23, 24, 25, 24, 23]]]]), + dict( # 3D indices, batch_dims=None, axis=1 + batch_dims=None, + axis=1, + params=[[10, 11, 12], [13, 14, 15]], + indices=[1, 0], + expected=[[11, 10], [14, 13]]), + ]) + @test_util.run_in_graph_and_eager_modes + def testBatchDims(self, params, indices, batch_dims, expected=None, + axis=None): + result = array_ops.gather(params, indices, axis=axis, batch_dims=batch_dims) + self.assertAllEqual(expected, result) + + @parameterized.parameters([ + dict( + params_shape=[2, 3, 4, 5, 6, 7], + indices_shape=[2, 3, 8, 9, 10], + batch_dims=2, + axis=2, + output_shape=[2, 3, 8, 9, 10, 5, 6, 7] + # = params.shape[:2] + indices.shape[2:] + params.shape[3:] + ), + dict( + params_shape=[2, 3, 4, 5, 6, 7], + indices_shape=[2, 3, 8, 9, 10], + batch_dims=2, + axis=3, + output_shape=[2, 3, 4, 8, 9, 10, 6, 7] + # = params.shape[:3] + indices.shape[2:] + params.shape[4:] + ), + dict( + params_shape=[2, 3, 4, 5, 6, 7], + indices_shape=[2, 3, 8, 9, 10], + batch_dims=2, + axis=4, + output_shape=[2, 3, 4, 5, 8, 9, 10, 7] + # = params.shape[:4] + indices.shape[2:] + params.shape[5:] + ), + dict( + params_shape=[2, 3, 4, 5, 6, 7], + indices_shape=[2, 3, 8, 9, 10], + batch_dims=2, + axis=5, + output_shape=[2, 3, 4, 5, 6, 8, 9, 10] + # = params.shape[:5] + indices.shape[2:] + params.shape[6:] + ), + dict( + params_shape=[2, 3, 4, 5, 6, 7], + indices_shape=[2, 3, 8, 9, 10], + batch_dims=2, + axis=-4, + output_shape=[2, 3, 8, 9, 10, 5, 6, 7] + # = params.shape[:2] + indices.shape[2:] + params.shape[3:] + ), + dict( + params_shape=[2, 3, 4, 5, 6, 7], + indices_shape=[2, 3, 8, 9, 10], + batch_dims=2, + axis=-3, + output_shape=[2, 3, 4, 8, 9, 10, 6, 7] + # = params.shape[:3] + indices.shape[2:] + params.shape[4:] + ), + dict( + params_shape=[2, 3, 4, 5, 6, 7], + indices_shape=[2, 3, 8, 9, 10], + batch_dims=2, + axis=-2, + output_shape=[2, 3, 4, 5, 8, 9, 10, 7] + # = params.shape[:4] + indices.shape[2:] + params.shape[5:] + ), + dict( + params_shape=[2, 3, 4, 5, 6, 7], + indices_shape=[2, 3, 8, 9, 10], + batch_dims=2, + axis=-1, + output_shape=[2, 3, 4, 5, 6, 8, 9, 10] + # = params.shape[:5] + indices.shape[2:] + params.shape[6:] + ), + ]) + @test_util.run_in_graph_and_eager_modes + def testBatchDimsMatchesPythonBatching(self, params_shape, indices_shape, + batch_dims, axis, output_shape): + """Checks that batch_dims matches multiple calls to tf.gather().""" + # Generate a `params` tensor with the indicated shape. + params_size = np.prod(params_shape) + params = np.reshape(np.arange(params_size), params_shape) + + # Generate an `indices` tensor with the indicated shape, where each index + # is within the appropriate range. + indices_size = np.prod(indices_shape) + indices = np.reshape(np.arange(indices_size), indices_shape) + indices = indices % params_shape[axis] + + # Perform repeated (batched) gather operations with numpy, to find the + # expected result. + expected = self._batchNumpyGather(params, indices, axis, batch_dims) + + result = array_ops.gather(params, indices, axis=axis, batch_dims=batch_dims) + self.assertAllEqual(output_shape, result.shape.as_list()) + self.assertAllEqual(expected, result) + + def _batchNumpyGather(self, params, indices, axis, batch_dims): + """Performs a batch gather by making recursive calls to np.take(). + + This is used by testBatchDims() to construct the expected value. + + Args: + params: A numpy array + indices: A numpy array + axis: An integer + batch_dims: An integer + Returns: + A numpy array + """ + if batch_dims == 0: + return np.take(params, indices, axis=axis) + self.assertEqual(params.shape[0], indices.shape[0]) + if axis > 0: + axis -= 1 + return np.stack([ + self._batchNumpyGather(params[i], indices[i], axis, batch_dims - 1) + for i in range(params.shape[0]) + ]) + + def testSkipEagerErrors(self): + if context.executing_eagerly(): + return + with self.assertRaisesRegexp(ValueError, r"tf\.gather does not allow.*"): + array_ops.gather( + params=[1, 2], + batch_dims=1, + indices=array_ops.placeholder(dtypes.int32)) + + @test_util.run_in_graph_and_eager_modes + def testErrors(self): + + with self.assertRaisesRegexp( + ValueError, r"batch_dims = 2 must be less than ndims\(indices\) = 2"): + array_ops.gather( + params=[[1, 2], [3, 4]], indices=[[1, 2], [3, 4]], batch_dims=2) + + with self.assertRaisesRegexp( + ValueError, r"batch_dims = 1 must be less than ndims\(params\) = 1"): + array_ops.gather( + params=[1, 2, 3, 4], indices=[[1, 2], [3, 4]], batch_dims=1) + + with self.assertRaisesRegexp( + ValueError, r"batch_dims = 1 must be less than or equal to axis = 0"): + array_ops.gather( + params=[[1, 2], [3, 4]], + indices=[[1, 2], [3, 4]], + batch_dims=1, + axis=0) + + one = array_ops.ones((), dtypes.int32) + with self.assertRaisesRegexp(TypeError, "batch_dims must be an int"): + array_ops.gather(params=[[1]], indices=[[1]], batch_dims=one) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/ops/array_ops.py b/tensorflow/python/ops/array_ops.py index d4e35ca77b..81ea473466 100644 --- a/tensorflow/python/ops/array_ops.py +++ b/tensorflow/python/ops/array_ops.py @@ -3258,8 +3258,82 @@ reverse_sequence_v2.__doc__ = deprecation.rewrite_argument_docstring( @tf_export(v1=["gather"]) @dispatch.add_dispatch_support -def gather(params, indices, validate_indices=None, name=None, axis=0): +def gather(params, + indices, + validate_indices=None, + name=None, + axis=None, + batch_dims=0): # pylint: disable=g-doc-args + r"""Gather slices from params axis axis according to indices. + + Gather slices from params axis axis according to indices. `indices` must be + an integer tensor of any dimension (usually 0-D or 1-D). + + For 0-D (scalar) `indices`: + + > `output`$$[p_0, ..., p_{axis-1}, \hspace{5.1em} + > p_{axis + 1}, ..., p_{N-1}]$$ =\ + > `params`$$[p_0, ..., p_{axis-1}, \hspace{1em} + > indices, \hspace{1em} + > p_{axis + 1}, ..., p_{N-1}]$$. + + For 1-D (vector) `indices` with `batch_dims=0`: + + > `output`$$[p_0, ..., p_{axis-1}, \hspace{2.6em} + > i, \hspace{2.6em} + > p_{axis + 1}, ..., p_{N-1}]$$ =\ + > `params`$$[p_0, ..., p_{axis-1}, \hspace{1em} + > indices[i], \hspace{1em} + > p_{axis + 1}, ..., p_{N-1}]$$. + + In the general case, produces an output tensor where: + + > `output`$$[p_0, ..., p_{axis-1}, \hspace{1.2em} + > i_{batch\_dims}, ..., i_{M-1}, \hspace{1.3em} + > p_{axis + 1}, ..., p_{N-1}]$$ =\ + > `params`$$[p_0, ..., p_{axis-1}, \hspace{1em} + > indices[i_0, ..., i_{M-1}], \hspace{1em} + > p_{axis + 1}, ..., p_{N-1}]$$. + + Where $$N$$=`ndims(params)` and $$M$$=`ndims(indices)`. + The shape of the output tensor is: + + > `output.shape = params.shape[:axis] + indices.shape[batch_dims:] + + > params.shape[axis + 1:]`. + + Note that on CPU, if an out of bound index is found, an error is returned. + On GPU, if an out of bound index is found, a 0 is stored in the corresponding + output value. + + See also `tf.gather_nd`. + +

    + +
    + + Args: + params: The `Tensor` from which to gather values. Must be at least rank + `axis + 1`. + indices: The index `Tensor`. Must be one of the following types: `int32`, + `int64`. Must be in range `[0, params.shape[axis])`. + axis: A `Tensor`. Must be one of the following types: `int32`, `int64`. The + `axis` in `params` to gather `indices` from. Must be greater than or equal + to `batch_dims`. Defaults to the first non-batch dimension. Supports + negative indexes. + batch_dims: An `integer`. The number of batch dimensions. Must be less + than `ndims(inices)`. + name: A name for the operation (optional). + + Returns: + A `Tensor`. Has the same type as `params`. + """ del validate_indices + if axis is None: + axis = batch_dims + if batch_dims != 0: + with ops.name_scope(name, "Gather", [params, indices, axis]): + return _batch_gather(params, indices, batch_dims, axis) if axis != 0: # Note that we do a sparse_read here to avoid snapshotting the entire # resource variable and doing a gather, which can be inefficient and lead to @@ -3275,41 +3349,50 @@ def gather(params, indices, validate_indices=None, name=None, axis=0): @tf_export("gather", v1=[]) @dispatch.add_dispatch_support -def gather_v2(params, indices, validate_indices=None, axis=0, name=None): +def gather_v2(params, indices, validate_indices=None, axis=None, + batch_dims=0, name=None): return gather(params, indices, validate_indices=validate_indices, name=name, - axis=axis) + axis=axis, batch_dims=batch_dims) gather.__doc__ = gather_v2.__doc__ = gen_array_ops.gather_v2.__doc__ - -@tf_export("batch_gather") +@tf_export(v1=["batch_gather"]) @dispatch.add_dispatch_support +@deprecation.deprecated( + "2017-10-25", "`tf.batch_gather` is deprecated, please use `tf.gather` " + "with `batch_dims=-1` instead.") # pylint: disable=missing-docstring def batch_gather(params, indices, name=None): - """Gather slices from `params` according to `indices` with leading batch dims. - - This operation assumes that the leading dimensions of `indices` are dense, - and the gathers on the axis corresponding to the last dimension of `indices`. - More concretely it computes: - - result[i1, ..., in] = params[i1, ..., in-1, indices[i1, ..., in]] + """Gather slices from params according to indices with leading batch dims.""" + with ops.name_scope(name, "BatchGather", [params, indices]): + indices = ops.convert_to_tensor(indices, name="indices") + params = ops.convert_to_tensor(params, name="params") + if indices.shape.ndims is None: + raise ValueError( + "batch_gather does not allow indices with unknown shape.") + return _batch_gather(params, indices, batch_dims=indices.shape.ndims - 1) - Therefore `params` should be a Tensor of shape [A1, ..., AN, B1, ..., BM], - `indices` should be a Tensor of shape [A1, ..., AN-1, C] and `result` will be - a Tensor of size `[A1, ..., AN-1, C, B1, ..., BM]`. - In the case in which indices is a 1D tensor, this operation is equivalent to - `tf.gather`. +def _batch_gather(params, indices, batch_dims, axis=None): + r"""Gather slices from params according to indices with leading batch dims. - See also `tf.gather` and `tf.gather_nd`. + This operation assumes that the leading `batch_dims` dimensions of `indices` + and `params` are batch dimensions; and performs a `tf.gather` operation within + each batch. (If `batch_dims` is not specified, then it defaults to + `ndims(indices) - 1`.) In the case in which `batch_dims==0`, this operation + is equivalent to `tf.gather`. Args: params: A Tensor. The tensor from which to gather values. indices: A Tensor. Must be one of the following types: int32, int64. Index - tensor. Must be in range `[0, params.shape[axis]`, where `axis` is the - last dimension of `indices` itself. - name: A name for the operation (optional). + tensor. Must be in range `[0, params.shape[batch_dims]]`. + batch_dims: An integer. The number of batch dimensions. Must be less than + ndims(inices). Defaults to `ndims(indices) - 1` if not specified. + axis: A `Tensor`. Must be one of the following types: `int32`, `int64`. The + `axis` in `params` to gather `indices` from. Must be greater than or equal + to `batch_dims`. Defaults to the first non-batch dimension. Supports + negative indexes. Returns: A Tensor. Has the same type as `params`. @@ -3317,48 +3400,100 @@ def batch_gather(params, indices, name=None): Raises: ValueError: if `indices` has an unknown shape. """ - - with ops.name_scope(name): - indices = ops.convert_to_tensor(indices, name="indices") - params = ops.convert_to_tensor(params, name="params") - indices_shape = shape(indices) - params_shape = shape(params) - - ndims = indices.shape.ndims - if ndims is None: - raise ValueError("batch_gather does not allow indices with unknown " - "shape.") - batch_indices = indices - indices_dtype = indices.dtype.base_dtype - accum_dim_value = ones((), dtype=indices_dtype) - # Use correct type for offset index computation - casted_params_shape = gen_math_ops.cast(params_shape, indices_dtype) - for dim in range(ndims-1, 0, -1): - dim_value = casted_params_shape[dim-1] - accum_dim_value *= casted_params_shape[dim] - start = zeros((), dtype=indices_dtype) - step = ones((), dtype=indices_dtype) - dim_indices = gen_math_ops._range(start, dim_value, step) - dim_indices *= accum_dim_value - dim_shape = stack([1] * (dim - 1) + [dim_value] + [1] * (ndims - dim), - axis=0) - batch_indices += reshape(dim_indices, dim_shape) - - flat_indices = reshape(batch_indices, [-1]) - outer_shape = params_shape[ndims:] - flat_inner_shape = gen_math_ops.prod( - params_shape[:ndims], [0], False) - - flat_params = reshape( - params, concat([[flat_inner_shape], outer_shape], axis=0)) - flat_result = gather(flat_params, flat_indices) - result = reshape(flat_result, concat([indices_shape, outer_shape], axis=0)) - final_shape = indices.get_shape()[:ndims-1].merge_with( - params.get_shape()[:ndims -1]) - final_shape = final_shape.concatenate(indices.get_shape().dims[ndims-1]) - final_shape = final_shape.concatenate(params.get_shape()[ndims:]) - result.set_shape(final_shape) - return result + if batch_dims is not None and not isinstance(batch_dims, int): + raise TypeError("batch_dims must be an int; got %r" % batch_dims) + indices = ops.convert_to_tensor(indices, name="indices") + params = ops.convert_to_tensor(params, name="params") + + indices_ndims = indices.shape.ndims + if indices_ndims is None: + raise ValueError("tf.gather does not allow indices with unknown " + "rank when batch_dims is specified.") + if batch_dims is None: + batch_dims = indices_ndims - 1 + if batch_dims < 0: + batch_dims += indices_ndims + if batch_dims < 0 or batch_dims >= indices_ndims: + raise ValueError("batch_dims = %d must be less than ndims(indices) = %d" % + (batch_dims, indices_ndims)) + if params.shape.ndims is not None and batch_dims >= params.shape.ndims: + raise ValueError("batch_dims = %d must be less than ndims(params) = %d" % + (batch_dims, params.shape.ndims)) + + # Handle axis by transposing the axis dimension to be the first non-batch + # dimension, recursively calling batch_gather with axis=0, and then + # transposing the result to put the pre-axis dimensions before the indices + # dimensions. + if axis is not None and axis != batch_dims: + # Adjust axis to be positive. + if not isinstance(axis, int): + axis = tf.where(axis < 0, axis + array_ops.rank(params), axis) + elif axis < 0 and params.shape.ndims is None: + axis = axis + array_ops.rank(params) + else: + if (axis < -params.shape.ndims) or (axis >= params.shape.ndims): + raise ValueError("axis (%d) out of range [%d, %d)" % + (axis, -params.shape.ndims, params.shape.ndims)) + if axis < 0: + axis += params.shape.ndims + if axis < batch_dims: + raise ValueError("batch_dims = %d must be less than or equal to " + "axis = %d" % (batch_dims, axis)) + + # Move params[axis] up to params[batch_dims]. + perm = [ + list(range(batch_dims)), [axis], + gen_math_ops._range(batch_dims, axis, 1), + gen_math_ops._range(axis + 1, rank(params), 1) + ] + params = transpose(params, concat(perm, axis=0)) + + result = _batch_gather(params, indices, batch_dims=batch_dims) + + # Move the result dimensions corresponding to params[batch_dims:axis] + # to just before the dimensions corresponding to indices[batch_dims:]. + params_start = indices_ndims + axis - batch_dims + perm = [ + list(range(batch_dims)), + gen_math_ops._range(indices_ndims, params_start, 1), + list(range(batch_dims, indices_ndims)), + gen_math_ops._range(params_start, rank(result), 1) + ] + return transpose(result, perm=concat(perm, axis=0)) + + indices_shape = shape(indices) + params_shape = shape(params) + batch_indices = indices + indices_dtype = indices.dtype.base_dtype + accum_dim_value = ones((), dtype=indices_dtype) + # Use correct type for offset index computation + casted_params_shape = gen_math_ops.cast(params_shape, indices_dtype) + for dim in range(batch_dims, 0, -1): + dim_value = casted_params_shape[dim - 1] + accum_dim_value *= casted_params_shape[dim] + start = zeros((), dtype=indices_dtype) + step = ones((), dtype=indices_dtype) + dim_indices = gen_math_ops._range(start, dim_value, step) + dim_indices *= accum_dim_value + dim_shape = stack( + [1] * (dim - 1) + [dim_value] + [1] * (indices_ndims - dim), axis=0) + batch_indices += reshape(dim_indices, dim_shape) + + flat_indices = reshape(batch_indices, [-1]) + outer_shape = params_shape[batch_dims + 1:] + flat_inner_shape = gen_math_ops.prod(params_shape[:batch_dims + 1], [0], + False) + + flat_params = reshape(params, concat([[flat_inner_shape], outer_shape], + axis=0)) + flat_result = gather(flat_params, flat_indices) + result = reshape(flat_result, concat([indices_shape, outer_shape], axis=0)) + final_shape = indices.get_shape()[:batch_dims].merge_with( + params.get_shape()[:batch_dims]) + final_shape = final_shape.concatenate(indices.get_shape().dims[batch_dims:]) + final_shape = final_shape.concatenate(params.get_shape()[batch_dims + 1:]) + result.set_shape(final_shape) + return result # Define quantize_v2 here in order to make name the second-to-last attribute, diff --git a/tensorflow/python/ops/ragged/ragged_array_ops.py b/tensorflow/python/ops/ragged/ragged_array_ops.py index be49830c98..3c5e697cdc 100644 --- a/tensorflow/python/ops/ragged/ragged_array_ops.py +++ b/tensorflow/python/ops/ragged/ragged_array_ops.py @@ -38,7 +38,8 @@ from tensorflow.python.ops.ragged import segment_id_ops # ragged_gather #=============================================================================== # TODO(edloper): Add an `axis` argument -def gather(params, indices, validate_indices=None, axis=0, name=None): +def gather(params, indices, validate_indices=None, axis=0, batch_dims=0, + name=None): """Gathers ragged slices from `params` axis `0` according to `indices`. Returns `RaggedTensor` output, such that: @@ -79,6 +80,7 @@ def gather(params, indices, validate_indices=None, axis=0, name=None): params.shape[0]]`. validate_indices: Ignored. axis: Must be zero. + batch_dims: Must be zero. name: A name for the operation (optional). Returns: @@ -91,7 +93,9 @@ def gather(params, indices, validate_indices=None, axis=0, name=None): """ del validate_indices if not isinstance(axis, int) or axis != 0: - raise ValueError('axis>0 is not supported for ragged gather yet.') + raise ValueError('axis != 0 is not supported for ragged gather yet.') + if not isinstance(batch_dims, int) or batch_dims != 0: + raise ValueError('batch_dims != 0 is not supported for ragged gather yet.') with ops.name_scope(name, 'RaggedGather', [params, indices]): params = ragged_tensor.convert_to_tensor_or_ragged_tensor( params, name='params') diff --git a/tensorflow/python/ops/ragged/ragged_dispatch.py b/tensorflow/python/ops/ragged/ragged_dispatch.py index bc64f9cc9e..b024bd9f07 100644 --- a/tensorflow/python/ops/ragged/ragged_dispatch.py +++ b/tensorflow/python/ops/ragged/ragged_dispatch.py @@ -392,12 +392,13 @@ _V1_OPS_THAT_DELEGATE_TO_V2_OPS = [ def _ragged_gather_v1(params, indices, validate_indices=None, name=None, - axis=0): + axis=0, batch_dims=0): return ragged_array_ops.gather( params=params, indices=indices, validate_indices=validate_indices, axis=axis, + batch_dims=batch_dims, name=name) diff --git a/tensorflow/tools/api/golden/v1/tensorflow.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.pbtxt index 6541952ccf..caa15280d1 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.pbtxt @@ -1250,7 +1250,7 @@ tf_module { } member_method { name: "gather" - argspec: "args=[\'params\', \'indices\', \'validate_indices\', \'name\', \'axis\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'0\'], " + argspec: "args=[\'params\', \'indices\', \'validate_indices\', \'name\', \'axis\', \'batch_dims\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'None\', \'0\'], " } member_method { name: "gather_nd" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.pbtxt index 87d8e2ae7c..d7a1a92bd9 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.pbtxt @@ -444,10 +444,6 @@ tf_module { name: "atanh" argspec: "args=[\'x\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " } - member_method { - name: "batch_gather" - argspec: "args=[\'params\', \'indices\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " - } member_method { name: "batch_to_space" argspec: "args=[\'input\', \'block_shape\', \'crops\', \'name\'], varargs=None, keywords=None, defaults=[\'None\'], " @@ -618,7 +614,7 @@ tf_module { } member_method { name: "gather" - argspec: "args=[\'params\', \'indices\', \'validate_indices\', \'axis\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'0\', \'None\'], " + argspec: "args=[\'params\', \'indices\', \'validate_indices\', \'axis\', \'batch_dims\', \'name\'], varargs=None, keywords=None, defaults=[\'None\', \'None\', \'0\', \'None\'], " } member_method { name: "gather_nd" diff --git a/tensorflow/tools/compatibility/ast_edits.py b/tensorflow/tools/compatibility/ast_edits.py index eac2150502..9106ec97c8 100644 --- a/tensorflow/tools/compatibility/ast_edits.py +++ b/tensorflow/tools/compatibility/ast_edits.py @@ -49,6 +49,8 @@ class APIChangeSpec(object): printed out if the function is used. (e.g. tf.nn.convolution()) * `unrestricted_function_warnings`: maps names of functions to warnings that will be printed out when the function is used (e.g. foo.convolution()). + * `function_keyword_additions`: maps function names to a map of arg->value + names that should be passed to the function. For an example, see `TFAPIChangeSpec`. """ @@ -320,9 +322,9 @@ class _ASTCallVisitor(ast.NodeVisitor): function_handles = self._api_change_spec.function_handle glob_name = "*.{}".format(name) if glob_name in function_handles: - function_handles[glob_name](self._file_edit, node) + function_handles[glob_name](self._file_edit, node, self._lines) if full_name in function_handles: - function_handles[full_name](self._file_edit, node) + function_handles[full_name](self._file_edit, node, self._lines) # Examine any non-keyword argument and make it into a keyword argument # if reordering required. diff --git a/tensorflow/tools/compatibility/reorders_v2.py b/tensorflow/tools/compatibility/reorders_v2.py index 1c9fb92db0..3f05aea6ca 100644 --- a/tensorflow/tools/compatibility/reorders_v2.py +++ b/tensorflow/tools/compatibility/reorders_v2.py @@ -28,6 +28,7 @@ from __future__ import print_function reorders = { 'tf.argmax': ['input', 'axis', 'name', 'dimension', 'output_type'], 'tf.argmin': ['input', 'axis', 'name', 'dimension', 'output_type'], + 'tf.batch_gather': ['params', 'indices', 'name'], 'tf.batch_to_space': ['input', 'crops', 'block_size', 'name'], 'tf.boolean_mask': ['tensor', 'mask', 'name', 'axis'], 'tf.confusion_matrix': ['labels', 'predictions', 'num_classes', 'dtype', 'name', 'weights'], diff --git a/tensorflow/tools/compatibility/tf_upgrade.py b/tensorflow/tools/compatibility/tf_upgrade.py index 287d1a5483..68d2c02570 100644 --- a/tensorflow/tools/compatibility/tf_upgrade.py +++ b/tensorflow/tools/compatibility/tf_upgrade.py @@ -182,7 +182,8 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): self.function_warnings = {} @staticmethod - def _reverse_handler(file_edit_recorder, node): + def _reverse_handler(file_edit_recorder, node, lines): + del lines # TODO(aselle): Could check for a literal list of bools and try to convert # them to indices. comment = ("ERROR: tf.reverse has had its argument semantics changed " diff --git a/tensorflow/tools/compatibility/tf_upgrade_v2.py b/tensorflow/tools/compatibility/tf_upgrade_v2.py index 2662889a60..103a86a990 100644 --- a/tensorflow/tools/compatibility/tf_upgrade_v2.py +++ b/tensorflow/tools/compatibility/tf_upgrade_v2.py @@ -18,6 +18,8 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import re + from tensorflow.tools.compatibility import ast_edits from tensorflow.tools.compatibility import renames_v2 from tensorflow.tools.compatibility import reorders_v2 @@ -356,6 +358,8 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): self.manual_symbol_renames = { "tf.batch_to_space_nd": "tf.batch_to_space", + "tf.batch_gather": + "tf.gather", "tf.space_to_batch_nd": "tf.space_to_batch", "tf.nn.space_to_batch": @@ -578,6 +582,7 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): "tf.io.serialize_many_sparse", "tf.argmax", "tf.argmin", + "tf.batch_gather", "tf.batch_to_space", "tf.nn.space_to_batch", "tf.boolean_mask", @@ -657,6 +662,7 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): # Specially handled functions. self.function_handle = { + "tf.batch_gather": self._batch_gather_handler, "tf.nn.dropout": self._dropout_handler, "tf.gradients": self._colocate_handler("tf.gradients"), "*.minimize": self._colocate_handler("Optimizer.minimize"), @@ -891,7 +897,8 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): } @staticmethod - def _dropout_handler(file_edit_recorder, node): + def _dropout_handler(file_edit_recorder, node, lines): + del lines if len(node.args) < 2: comment = ("ERROR: tf.nn.dropout did not take arguments, so automatic " "transformation was disabled. tf.nn.dropout has changed " @@ -915,7 +922,9 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): @staticmethod def _colocate_handler(name): - def _helper(file_edit_recorder, node): + def _helper(file_edit_recorder, node, lines): + """Handler for updating colocate arguments.""" + del lines for keyword in node.keywords: if keyword.arg == "colocate_gradients_with_ops": # TODO(jhseu): Since ast_edit.py does string replacement, there's no @@ -932,3 +941,24 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): "", error="{} requires manual check.".format(name)) return _helper + + @staticmethod + def _batch_gather_handler(file_edit_recorder, node, lines): + lineno = node.lineno + column = node.col_offset + + # Find the position to add the batch_dims argument. We add it as the + # first argument, since that's easiest. This is safe because we included + # batch_gather in self.reordered_function_names, so it will have all + # of its arguments changed to keyword arguments. + m = re.match(r"tf\s*\.\s*batch_gather\s*\(", lines[lineno - 1][column:]) + if m is not None: + file_edit_recorder.add( + "Added keyword argument 'batch_dims=-1' to 'tf.batch_gather'", + lineno, column + m.end(), "", "batch_dims=-1, ") + else: + file_edit_recorder.add( + "Unable to add keyword argument 'batch_dims=-1' to 'tf.batch_gather'", + lineno, column, "", "", + error="Unable to add keyword argument batch_dims=-1 to " + "tf.batch_gather; please add it manually.") diff --git a/tensorflow/tools/compatibility/tf_upgrade_v2_test.py b/tensorflow/tools/compatibility/tf_upgrade_v2_test.py index 270d93065e..9a89eda3e0 100644 --- a/tensorflow/tools/compatibility/tf_upgrade_v2_test.py +++ b/tensorflow/tools/compatibility/tf_upgrade_v2_test.py @@ -736,6 +736,30 @@ tf.print('abc') _, unused_report, unused_errors, new_text = self._upgrade(text) self.assertEqual(new_text, expected_text) + def testBatchGather(self): + text = "tf.batch_gather(foo, bar)" + expected_text = "tf.gather(batch_dims=-1, params=foo, indices=bar)" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + text = "tf.batch_gather(params=foo, indices=bar)" + expected_text = "tf.gather(batch_dims=-1, params=foo, indices=bar)" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + text = "tf.batch_gather ( foo, bar)" + expected_text = "tf.gather (batch_dims=-1, params=foo, indices=bar)" + _, unused_report, unused_errors, new_text = self._upgrade(text) + self.assertEqual(new_text, expected_text) + + text = "(tf.batch_gather\n(foo, bar))" + expected_text = "(tf.gather\n(params=foo, indices=bar))" + expected_errors = ["test.py:1: Unable to add keyword argument batch_dims=-1" + " to tf.batch_gather; please add it manually."] + _, unused_report, errors, new_text = self._upgrade(text) + self.assertEqual(errors, expected_errors) + self.assertEqual(new_text, expected_text) + class TestUpgradeFiles(test_util.TensorFlowTestCase): -- GitLab From c9049de2515cf8643faefa66cc4aea276d390912 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 18:34:24 -0800 Subject: [PATCH 0226/1765] Make `sample_weights` and `class_weights` multiplicative. PiperOrigin-RevId: 226426935 --- tensorflow/python/keras/engine/training.py | 7 ++-- .../python/keras/engine/training_test.py | 31 ---------------- .../python/keras/engine/training_utils.py | 35 ++++++++++++------- .../keras/engine/training_utils_test.py | 24 +++++++++++++ 4 files changed, 49 insertions(+), 48 deletions(-) diff --git a/tensorflow/python/keras/engine/training.py b/tensorflow/python/keras/engine/training.py index b10f24b4ad..40622641bb 100644 --- a/tensorflow/python/keras/engine/training.py +++ b/tensorflow/python/keras/engine/training.py @@ -2242,7 +2242,8 @@ class Model(Network): weight the importance of each sample in `x`. class_weight: An optional class-weight array by the user to weight the importance of samples in `x` based on the class they belong - to, as conveyed by `y`. + to, as conveyed by `y`. If both `sample_weight` and `class_weight` are + provided, the weights are multiplied. batch_size: Integer batch size. If provided, it is used to run additional validation checks on stateful models. check_steps: boolean, True if we want to check for validity of `steps` and @@ -2322,10 +2323,6 @@ class Model(Network): else: x = next_element - if sample_weight is not None and class_weight is not None: - logging.warning( - 'Received both a `sample_weight` and `class_weight` argument. ' - 'The `class_weight` argument will be ignored.') # First, we build/compile the model on the fly if necessary. all_inputs = [] is_build_called = False diff --git a/tensorflow/python/keras/engine/training_test.py b/tensorflow/python/keras/engine/training_test.py index 345673a84d..168082d987 100644 --- a/tensorflow/python/keras/engine/training_test.py +++ b/tensorflow/python/keras/engine/training_test.py @@ -993,37 +993,6 @@ class LossWeightingTest(keras_parameterized.TestCase): x_test[test_ids, :], y_test[test_ids, :], verbose=0) self.assertLess(score[0], ref_score[0]) - @keras_parameterized.run_all_keras_modes - def test_warning_for_concurrent_sample_and_class_weights(self): - - model = keras.models.Sequential() - model.add(keras.layers.Dense(10, input_shape=(3,))) - model.compile( - loss='mse', - optimizer=RMSPropOptimizer(learning_rate=0.01), - run_eagerly=testing_utils.should_run_eagerly()) - x_train = np.random.random((10, 3)) - y_train = np.random.random((10, 10)) - sample_weight = np.ones((y_train.shape[0])) - class_weight = {0: 1., 1: 1.} - - with test.mock.patch.object(logging, 'warning') as mock_log: - model.fit( - x_train, - y_train, - epochs=1, - verbose=0, - sample_weight=sample_weight, - class_weight=class_weight) - msg = 'The `class_weight` argument will be ignored.' - - msg_found = False - for call_args in mock_log.call_args_list: - if msg in str(call_args): - msg_found = True - - self.assertTrue(msg_found) - @keras_parameterized.run_all_keras_modes def test_temporal_sample_weights(self): num_classes = 5 diff --git a/tensorflow/python/keras/engine/training_utils.py b/tensorflow/python/keras/engine/training_utils.py index 8ff3af310b..6d0037ed5e 100644 --- a/tensorflow/python/keras/engine/training_utils.py +++ b/tensorflow/python/keras/engine/training_utils.py @@ -676,7 +676,8 @@ def standardize_weights(y, """Performs sample weight validation and standardization. Everything gets normalized to a single sample-wise (or timestep-wise) - weight array. + weight array. If both `sample_weight` and `class_weight` are provided, + the weights are multiplied. Arguments: y: Numpy array of model targets to be weighted. @@ -737,22 +738,26 @@ def standardize_weights(y, 'Found a sample_weight array with shape ' + str(sample_weight.shape) + ' for an input with shape ' + str(y.shape) + '. ' 'sample_weight cannot be broadcast.') - return sample_weight - elif isinstance(class_weight, dict): + + # Class weights applied per-sample. + class_sample_weight = None + if isinstance(class_weight, dict): if len(y.shape) > 2: raise ValueError('`class_weight` not supported for ' '3+ dimensional targets.') - if y.shape[1] > 1: - y_classes = np.argmax(y, axis=1) - elif y.shape[1] == 1: - y_classes = np.reshape(y, y.shape[0]) + + if len(y.shape) == 2: + if y.shape[1] > 1: + y_classes = np.argmax(y, axis=1) + elif y.shape[1] == 1: + y_classes = np.reshape(y, y.shape[0]) else: y_classes = y - weights = np.asarray( + class_sample_weight = np.asarray( [class_weight[cls] for cls in y_classes if cls in class_weight]) - if len(weights) != len(y_classes): + if len(class_sample_weight) != len(y_classes): # subtract the sets to pick all missing classes existing_classes = set(y_classes) existing_class_weight = set(class_weight.keys()) @@ -760,9 +765,15 @@ def standardize_weights(y, ' The classes %s exist in the data but not in ' '`class_weight`.' % (existing_classes - existing_class_weight)) - return weights - else: - return None + + if class_sample_weight is not None and sample_weight is not None: + # Multiply weights if both are provided. + return class_sample_weight * sample_weight + if sample_weight is not None: + return sample_weight + if class_sample_weight is not None: + return class_sample_weight + return None def has_symbolic_tensors(ls): diff --git a/tensorflow/python/keras/engine/training_utils_test.py b/tensorflow/python/keras/engine/training_utils_test.py index 405618796c..d0b2567b55 100644 --- a/tensorflow/python/keras/engine/training_utils_test.py +++ b/tensorflow/python/keras/engine/training_utils_test.py @@ -367,5 +367,29 @@ class DatasetUtilsTest(test.TestCase, parameterized.TestCase): training_utils.assert_not_shuffled(dataset_fn()) +class StandardizeWeightsTest(keras_parameterized.TestCase): + + def test_sample_weights(self): + y = np.array([0, 1, 0, 0, 2]) + sample_weights = np.array([0.5, 1., 1., 0., 2.]) + weights = training_utils.standardize_weights(y, sample_weights) + self.assertAllClose(weights, sample_weights) + + def test_class_weights(self): + y = np.array([0, 1, 0, 0, 2]) + class_weights = {0: 0.5, 1: 1., 2: 1.5} + weights = training_utils.standardize_weights(y, class_weight=class_weights) + self.assertAllClose(weights, np.array([0.5, 1., 0.5, 0.5, 1.5])) + + def test_sample_weights_and_class_weights(self): + y = np.array([0, 1, 0, 0, 2]) + sample_weights = np.array([0.5, 1., 1., 0., 2.]) + class_weights = {0: 0.5, 1: 1., 2: 1.5} + weights = training_utils.standardize_weights(y, sample_weights, + class_weights) + expected = sample_weights * np.array([0.5, 1., 0.5, 0.5, 1.5]) + self.assertAllClose(weights, expected) + + if __name__ == '__main__': test.main() -- GitLab From 6e5f37d5f77efe081d13ea7bd76546e526218d37 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 18:37:28 -0800 Subject: [PATCH 0227/1765] Automated rollback of commit 6a6658f3e2bae16e2d0067fcb7d7cb0850272d1b PiperOrigin-RevId: 226427235 --- tensorflow/lite/python/BUILD | 1 - tensorflow/lite/python/lite.py | 41 ++-------------------------------- 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/tensorflow/lite/python/BUILD b/tensorflow/lite/python/BUILD index e666812bd2..b0ca3f8dcc 100644 --- a/tensorflow/lite/python/BUILD +++ b/tensorflow/lite/python/BUILD @@ -61,7 +61,6 @@ py_library( ":lite_constants", ":op_hint", "//tensorflow/python:graph_util", - "//tensorflow/python:tf_optimizer", "//tensorflow/python/keras", "//tensorflow/python/saved_model:constants", "//tensorflow/python/saved_model:loader", diff --git a/tensorflow/lite/python/lite.py b/tensorflow/lite/python/lite.py index 159eacd26f..1b20ff2f92 100644 --- a/tensorflow/lite/python/lite.py +++ b/tensorflow/lite/python/lite.py @@ -53,49 +53,19 @@ from tensorflow.lite.python.interpreter import Interpreter # pylint: disable=un from tensorflow.lite.python.op_hint import convert_op_hints_to_stubs # pylint: disable=unused-import from tensorflow.lite.python.op_hint import OpHint # pylint: disable=unused-import from tensorflow.core.framework import graph_pb2 as _graph_pb2 -from tensorflow.core.protobuf import rewriter_config_pb2 as _rewriter_config_pb2 -from tensorflow.core.protobuf import config_pb2 as _config_pb2 -from tensorflow.core.protobuf import meta_graph_pb2 as _meta_graph_pb2 from tensorflow.python import keras as _keras from tensorflow.python.client import session as _session from tensorflow.python.framework import graph_util as _tf_graph_util from tensorflow.python.framework import ops as _ops from tensorflow.python.framework.errors_impl import NotFoundError as _NotFoundError from tensorflow.python.framework.importer import import_graph_def as _import_graph_def -from tensorflow.python.grappler import tf_optimizer as _tf_optimizer from tensorflow.python.lib.io import file_io as _file_io from tensorflow.python.saved_model import signature_constants as _signature_constants from tensorflow.python.saved_model import tag_constants as _tag_constants -from tensorflow.python.training.saver import export_meta_graph as _export_meta_graph from tensorflow.python.util import deprecation as _deprecation from tensorflow.python.util.tf_export import tf_export as _tf_export -def _run_graph_optimizations(graph_def, output_arrays): - """Apply standard TensorFlow optimizations to the graph_def. - - Args: - graph_def: Frozen GraphDef to be optimized. - output_arrays: List of arrays that are considered outputs of the graph. - - Returns: - A new, optimized GraphDef. - """ - meta_graph = _export_meta_graph(graph_def=graph_def) - - # We need to add a collection called 'train_op' so that grappler - # knows what the outputs are. - fetch_collection = _meta_graph_pb2.CollectionDef() - for output in output_arrays: - fetch_collection.node_list.value.append(output) - meta_graph.collection_def["train_op"].CopyFrom(fetch_collection) - - config = _config_pb2.ConfigProto() - rewrite_options = config.graph_options.rewrite_options - rewrite_options.layout_optimizer = _rewriter_config_pb2.RewriterConfig.ON - return _tf_optimizer.OptimizeGraph(config, meta_graph) - - @_tf_export("lite.TFLiteConverter") class TFLiteConverter(object): """Convert a TensorFlow model into `output_format` using TOCO. @@ -476,23 +446,16 @@ class TFLiteConverter(object): "dump_graphviz_video": self.dump_graphviz_video } - optimized_graph = None - try: - optimized_graph = _run_graph_optimizations( - self._graph_def, [t.name for t in self._output_tensors]) - except Exception: - optimized_graph = self._graph_def - # Converts model. if self._has_valid_tensors(): result = _toco_convert_impl( - input_data=optimized_graph, + input_data=self._graph_def, input_tensors=self._input_tensors, output_tensors=self._output_tensors, **converter_kwargs) else: result = _toco_convert_graph_def( - input_data=optimized_graph, + input_data=self._graph_def, input_arrays_with_shape=self._input_arrays_with_shape, output_arrays=self._output_arrays, **converter_kwargs) -- GitLab From 6fde1c56df8543fb418f8a12a07820c11482a1c4 Mon Sep 17 00:00:00 2001 From: Zhenyu Tan Date: Thu, 20 Dec 2018 18:59:25 -0800 Subject: [PATCH 0228/1765] Fix NAdam optimizer, 1) assert dependency between iteration update and variable update, 2) include momentum caching as state variable. PiperOrigin-RevId: 226429048 --- tensorflow/python/keras/optimizers.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tensorflow/python/keras/optimizers.py b/tensorflow/python/keras/optimizers.py index a8544199fd..bcece41797 100644 --- a/tensorflow/python/keras/optimizers.py +++ b/tensorflow/python/keras/optimizers.py @@ -661,9 +661,10 @@ class Nadam(Optimizer): def get_updates(self, loss, params): grads = self.get_gradients(loss, params) - self.updates = [state_ops.assign_add(self.iterations, 1)] + self.updates = [] - t = math_ops.cast(self.iterations, K.floatx()) + 1 + with ops.control_dependencies([state_ops.assign_add(self.iterations, 1)]): + t = math_ops.cast(self.iterations, K.floatx()) # Due to the recommendations in [2], i.e. warming momentum schedule momentum_cache_t = self.beta_1 * ( @@ -680,7 +681,7 @@ class Nadam(Optimizer): ms = [K.zeros(shape) for shape in shapes] vs = [K.zeros(shape) for shape in shapes] - self.weights = [self.iterations] + ms + vs + self.weights = [self.iterations, self.m_schedule] + ms + vs for p, g, m, v in zip(params, grads, ms, vs): # the following equations given in [1] -- GitLab From 7cae909b9608087d643e52418d162f7c5041f22b Mon Sep 17 00:00:00 2001 From: Siju Date: Fri, 21 Dec 2018 08:39:26 +0530 Subject: [PATCH 0229/1765] Update operation_semantics.md documentation issue --- tensorflow/compiler/xla/g3doc/operation_semantics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/compiler/xla/g3doc/operation_semantics.md b/tensorflow/compiler/xla/g3doc/operation_semantics.md index 9a9cd08c30..78d4617017 100644 --- a/tensorflow/compiler/xla/g3doc/operation_semantics.md +++ b/tensorflow/compiler/xla/g3doc/operation_semantics.md @@ -1095,7 +1095,7 @@ When `Op` is `Rem`, the sign of the result is taken from the dividend, and the absolute value of the result is always less than the divisor's absolute value. Integer division overflow (signed/unsigned division/remainder by zero or signed -divison/remainder of `INT_SMIN` with `-1`) produces an implementation defined +division/remainder of `INT_SMIN` with `-1`) produces an implementation defined value. An alternative variant with different-rank broadcasting support exists for these -- GitLab From 3f0c3037ff4e4b2ddc5dadf575fd984c44ef29dd Mon Sep 17 00:00:00 2001 From: Suharsh Sivakumar Date: Thu, 20 Dec 2018 19:01:41 -0800 Subject: [PATCH 0230/1765] EmbeddingLookup INT_8 hybrid support. PiperOrigin-RevId: 226429231 --- tensorflow/lite/kernels/embedding_lookup.cc | 8 +- .../lite/kernels/embedding_lookup_test.cc | 93 ++++++++++++++++--- tensorflow/lite/kernels/register.cc | 4 +- 3 files changed, 91 insertions(+), 14 deletions(-) diff --git a/tensorflow/lite/kernels/embedding_lookup.cc b/tensorflow/lite/kernels/embedding_lookup.cc index fad32607b4..3f1d62389f 100644 --- a/tensorflow/lite/kernels/embedding_lookup.cc +++ b/tensorflow/lite/kernels/embedding_lookup.cc @@ -117,7 +117,12 @@ TfLiteStatus EvalHybrid(TfLiteContext* context, TfLiteNode* node, // TODO(alanchiao): refactor scalar multiply into separate function // for ease of adding a neon equivalent if ever necessary. for (int j = 0; j < col_size; j++) { - const int8_t* value_ptr = reinterpret_cast(value->data.uint8); + const int8_t* value_ptr; + if (value->type == kTfLiteUInt8) { + value_ptr = reinterpret_cast(value->data.uint8); + } else { + value_ptr = value->data.int8; + } output->data.f[j + i * col_size] = value_ptr[j + idx * col_size] * scaling_factor; } @@ -135,6 +140,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { case kTfLiteFloat32: return EvalFloat(context, node, lookup, value, output); case kTfLiteUInt8: + case kTfLiteInt8: return EvalHybrid(context, node, lookup, value, output); default: context->ReportError(context, "Type not currently supported."); diff --git a/tensorflow/lite/kernels/embedding_lookup_test.cc b/tensorflow/lite/kernels/embedding_lookup_test.cc index 8ea98a5f0d..2462ff2693 100644 --- a/tensorflow/lite/kernels/embedding_lookup_test.cc +++ b/tensorflow/lite/kernels/embedding_lookup_test.cc @@ -28,6 +28,8 @@ License. namespace tflite { namespace { +float kTestTolerance = 7.41e-03; + using ::testing::ElementsAreArray; class BaseEmbeddingLookupOpModel : public SingleOpModel { @@ -76,13 +78,17 @@ class EmbeddingLookupOpModel : public BaseEmbeddingLookupOpModel { class HybridEmbeddingLookupOpModel : public BaseEmbeddingLookupOpModel { public: HybridEmbeddingLookupOpModel(std::initializer_list index_shape, - std::initializer_list weight_shape) - : BaseEmbeddingLookupOpModel(index_shape, weight_shape, - TensorType_UINT8) {} + std::initializer_list weight_shape, + TensorType type) + : BaseEmbeddingLookupOpModel(index_shape, weight_shape, type) {} void SetWeight(std::initializer_list data) { SymmetricQuantizeAndPopulate(weight_, data); } + + void SetSignedWeight(std::initializer_list data) { + SignedSymmetricQuantizeAndPopulate(weight_, data); + } }; // TODO(ahentz): write more tests that exercise the details of the op, such as @@ -103,8 +109,8 @@ TEST(EmbeddingLookupOpTest, SimpleTest) { }))); } -TEST(HybridEmbeddingLookupHybridOpTest, Simple2DTest) { - HybridEmbeddingLookupOpModel m({3}, {3, 8}); +TEST(HybridEmbeddingLookupHybridOpTest, Simple2DTestUint8) { + HybridEmbeddingLookupOpModel m({3}, {3, 8}, TensorType_UINT8); m.SetInput({1, 0, 2}); m.SetWeight({ 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 @@ -121,11 +127,11 @@ TEST(HybridEmbeddingLookupHybridOpTest, Simple2DTest) { 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 2.00, 2.01, 2.02, 2.03, 2.10, 2.11, 2.12, 2.13, // Row 2 }, - 7.41e-03))); + kTestTolerance))); } -TEST(HybridEmbeddingLookupHybridOpTest, Simple3DTest) { - HybridEmbeddingLookupOpModel m({3}, {3, 2, 4}); +TEST(HybridEmbeddingLookupHybridOpTest, Simple3DTestUint8) { + HybridEmbeddingLookupOpModel m({3}, {3, 2, 4}, TensorType_UINT8); m.SetInput({1, 0, 2}); m.SetWeight({ 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 @@ -142,11 +148,11 @@ TEST(HybridEmbeddingLookupHybridOpTest, Simple3DTest) { 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 2.00, 2.01, 2.02, 2.03, 2.10, 2.11, 2.12, 2.13, // Row 2 }, - 7.41e-03))); + kTestTolerance))); } -TEST(HybridEmbeddingLookupHybridOpTest, Simple4DTest) { - HybridEmbeddingLookupOpModel m({3}, {3, 2, 2, 2}); +TEST(HybridEmbeddingLookupHybridOpTest, Simple4DTestUint8) { + HybridEmbeddingLookupOpModel m({3}, {3, 2, 2, 2}, TensorType_UINT8); m.SetInput({1, 0, 2}); m.SetWeight({ 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 @@ -163,7 +169,70 @@ TEST(HybridEmbeddingLookupHybridOpTest, Simple4DTest) { 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 2.00, 2.01, 2.02, 2.03, 2.10, 2.11, 2.12, 2.13, // Row 2 }, - 7.41e-03))); + kTestTolerance))); +} + +TEST(HybridEmbeddingLookupHybridOpTest, Simple2DTestInt8) { + HybridEmbeddingLookupOpModel m({3}, {3, 8}, TensorType_INT8); + m.SetInput({1, 0, 2}); + m.SetSignedWeight({ + 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 + 1.00, -1.01, 1.02, 1.03, 1.10, 1.11, 1.12, 1.13, // Row 1 + 2.00, 2.01, 2.02, 2.03, 2.10, 2.11, 2.12, 2.13, // Row 2 + }); + + m.Invoke(); + + EXPECT_THAT(m.GetOutput(), + ElementsAreArray(ArrayFloatNear( + { + 1.00, -1.01, 1.02, 1.03, 1.10, 1.11, 1.12, 1.13, // Row 1 + 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 + 2.00, 2.01, 2.02, 2.03, 2.10, 2.11, 2.12, 2.13, // Row 2 + }, + kTestTolerance))); +} + +TEST(HybridEmbeddingLookupHybridOpTest, Simple3DTestInt8) { + HybridEmbeddingLookupOpModel m({3}, {3, 2, 4}, TensorType_INT8); + m.SetInput({1, 0, 2}); + m.SetSignedWeight({ + 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 + 1.00, -1.01, 1.02, 1.03, 1.10, 1.11, 1.12, 1.13, // Row 1 + 2.00, 2.01, 2.02, 2.03, 2.10, 2.11, 2.12, 2.13, // Row 2 + }); + + m.Invoke(); + + EXPECT_THAT(m.GetOutput(), + ElementsAreArray(ArrayFloatNear( + { + 1.00, -1.01, 1.02, 1.03, 1.10, 1.11, 1.12, 1.13, // Row 1 + 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 + 2.00, 2.01, 2.02, 2.03, 2.10, 2.11, 2.12, 2.13, // Row 2 + }, + kTestTolerance))); +} + +TEST(HybridEmbeddingLookupHybridOpTest, Simple4DTestInt8) { + HybridEmbeddingLookupOpModel m({3}, {3, 2, 2, 2}, TensorType_INT8); + m.SetInput({1, 0, 2}); + m.SetSignedWeight({ + 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 + 1.00, -1.01, 1.02, 1.03, 1.10, 1.11, 1.12, 1.13, // Row 1 + 2.00, 2.01, 2.02, 2.03, 2.10, 2.11, 2.12, 2.13, // Row 2 + }); + + m.Invoke(); + + EXPECT_THAT(m.GetOutput(), + ElementsAreArray(ArrayFloatNear( + { + 1.00, -1.01, 1.02, 1.03, 1.10, 1.11, 1.12, 1.13, // Row 1 + 0.00, 0.01, 0.02, 0.03, 0.10, 0.11, 0.12, 0.13, // Row 0 + 2.00, 2.01, 2.02, 2.03, 2.10, 2.11, 2.12, 2.13, // Row 2 + }, + kTestTolerance))); } } // namespace diff --git a/tensorflow/lite/kernels/register.cc b/tensorflow/lite/kernels/register.cc index 40e55d9a44..f51bbc3615 100644 --- a/tensorflow/lite/kernels/register.cc +++ b/tensorflow/lite/kernels/register.cc @@ -179,7 +179,9 @@ BuiltinOpResolver::BuiltinOpResolver() { Register_BIDIRECTIONAL_SEQUENCE_RNN()); AddBuiltin(BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN, Register_UNIDIRECTIONAL_SEQUENCE_RNN()); - AddBuiltin(BuiltinOperator_EMBEDDING_LOOKUP, Register_EMBEDDING_LOOKUP()); + AddBuiltin(BuiltinOperator_EMBEDDING_LOOKUP, Register_EMBEDDING_LOOKUP(), + /* min_version */ 1, + /* max_version */ 2); AddBuiltin(BuiltinOperator_EMBEDDING_LOOKUP_SPARSE, Register_EMBEDDING_LOOKUP_SPARSE()); AddBuiltin(BuiltinOperator_FULLY_CONNECTED, Register_FULLY_CONNECTED(), -- GitLab From 2e782fdc446db1c68ca6361eb0f061320ab51039 Mon Sep 17 00:00:00 2001 From: Sourabh Bajaj Date: Thu, 20 Dec 2018 19:12:48 -0800 Subject: [PATCH 0231/1765] Add back the prefetch op when running the input pipeline if the dataset was originally using prefetch. PiperOrigin-RevId: 226430357 --- tensorflow/python/distribute/values.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tensorflow/python/distribute/values.py b/tensorflow/python/distribute/values.py index c3036b5aa5..1c84bc07b6 100644 --- a/tensorflow/python/distribute/values.py +++ b/tensorflow/python/distribute/values.py @@ -1941,6 +1941,10 @@ def _split_dataset_batch(dataset, split_batch_by): elif isinstance(batched_dataset, batching._MapAndBatchDataset): batch_size = batched_dataset._batch_size_t drop_remainder = batched_dataset._drop_remainder_t + + prefetch_buffer = None + if isinstance(dataset, dataset_ops.PrefetchDataset): + prefetch_buffer = dataset._buffer_size # pylint: enable=protected-access if tensor_util.is_tensor(batch_size): @@ -1956,7 +1960,10 @@ def _split_dataset_batch(dataset, split_batch_by): new_batch_size = batch_size // split_batch_by dataset = dataset.apply(batching.unbatch()) - return dataset.batch(new_batch_size, drop_remainder=drop_remainder) + dataset = dataset.batch(new_batch_size, drop_remainder=drop_remainder) + if prefetch_buffer is not None: + dataset = dataset.prefetch(prefetch_buffer) + return dataset class MultiStepContext(object): -- GitLab From 03d9c44ed47510f8a7c0f00153b314b419379bf4 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 19:14:47 -0800 Subject: [PATCH 0232/1765] Bug fixes and enhancements in TensorTracer: * Fixes a bug in calculating NaN * Workaround the limitation that outside-compilation doesn't accept int64 tensors (also add a unit test for it) * Adds "brief" printing mode to reduce the size of trace files. * Allows options without values. PiperOrigin-RevId: 226430456 --- .../contrib/tpu/python/tpu/tensor_tracer.py | 224 +++++++++++++----- 1 file changed, 165 insertions(+), 59 deletions(-) diff --git a/tensorflow/contrib/tpu/python/tpu/tensor_tracer.py b/tensorflow/contrib/tpu/python/tpu/tensor_tracer.py index a1494e3660..98c4fa7b7f 100644 --- a/tensorflow/contrib/tpu/python/tpu/tensor_tracer.py +++ b/tensorflow/contrib/tpu/python/tpu/tensor_tracer.py @@ -47,6 +47,8 @@ _TRACE_MODE_PART_TENSOR_SIZE = 3 _TRACE_MODE_FULL_TENSOR = 'full-tensor' _TRACE_MODE_NORM = 'norm' _TRACE_MODE_MAX_ABS = 'max-abs' +_SUBMODE_BRIEF = 'brief' +_SUBMODE_DETAILED = 'detailed' _REASON_OUTSIDE_OP_RANGE = 'not-traced-outside-op-range' _REASON_UNSAFE_OP = 'not-traced-unsafe-op' _REASON_UNSAFE_SCALAR = 'not-traced-unsafe-scalar' @@ -68,6 +70,7 @@ _SECTION_NAME_GRAPH = 'graph' _FIELD_NAME_VERSION = 'version:' _FIELD_NAME_DEVICE = 'device:' _FIELD_NAME_TRACE_MODE = 'trace-mode:' +_FIELD_NAME_SUBMODE = 'submode:' _FIELD_NAME_NUM_REPLICAS = 'num-replicas:' _FIELD_NAME_NUM_OPS = 'number-of-ops:' _FIELD_NAME_NUM_TENSORS = 'number-of-tensors:' @@ -76,8 +79,10 @@ _FLAGS_ENV_VAR = 'TENSOR_TRACER_FLAGS' _FLAG_SINGLE_QUOTE_PAT = re.compile(r"\s*--([^=]+)='([^']*)'") _FLAG_DOUBLE_QUOTE_PAT = re.compile(r'\s*--([^=]+)="([^"]*)"') _FLAG_NO_QUOTE_PAT = re.compile(r'\s*--([^=]+)=(\S*)') +_FLAG_NO_EQUAL_PAT = re.compile(r'\s*--([^=]+)\s*') _FLAG_NAME_ENABLE = 'enable' _FLAG_NAME_TRACE_MODE = 'trace_mode' +_FLAG_NAME_SUBMODE = 'submode' _FLAG_NAME_INCLUDE_LESS_INTERESTING_OPS = 'include_less_interesting_ops' _FLAG_NAME_EXCLUDED_OPNAMES = 'excluded_opnames' _FLAG_NAME_EXCLUDED_OPTYPES = 'excluded_optypes' @@ -165,21 +170,39 @@ class TensorTracer(object): @staticmethod def _match_next_flag(flags, pos): - """Returns the match for the next TensorTracer flag.""" + """Returns the match for the next TensorTracer flag. + + Args: + flags: a string that contains the flags. + pos: where in flags to start the search. + + Returns: + A pair where the first element is the regular-expression + match found and the second element indicates if the match + has a value. + """ match = _FLAG_DOUBLE_QUOTE_PAT.match(flags, pos) if match: - return match + return match, True match = _FLAG_SINGLE_QUOTE_PAT.match(flags, pos) if match: - return match + return match, True match = _FLAG_NO_QUOTE_PAT.match(flags, pos) - return match + if match: + return match, True + match = _FLAG_NO_EQUAL_PAT.match(flags, pos) + if match: + # The flag is found but is not given a value. + return match, False + # The flag is not found. + return None, False @staticmethod def validate_flag_names(): """Validates if the TensorTrace flags passed are valid.""" valid_flag_names = [_FLAG_NAME_ENABLE, _FLAG_NAME_TRACE_MODE, + _FLAG_NAME_SUBMODE, _FLAG_NAME_EXCLUDED_OPNAMES, _FLAG_NAME_EXCLUDED_OPTYPES, _FLAG_NAME_INCLUDED_OPNAMES, @@ -193,7 +216,7 @@ class TensorTracer(object): return pos = 0 while True: - match = TensorTracer._match_next_flag(tensor_tracer_flags, pos) + match, _ = TensorTracer._match_next_flag(tensor_tracer_flags, pos) if not match: break flag_name = match.group(1) @@ -216,11 +239,15 @@ class TensorTracer(object): result += 'Individual flag value:\n' pos = 0 while True: - match = TensorTracer._match_next_flag(tensor_tracer_flags, pos) + match, has_value = TensorTracer._match_next_flag( + tensor_tracer_flags, pos) if not match: break flag_name = match.group(1) - flag_value = match.group(2) + if has_value: + flag_value = match.group(2) + else: + flag_value = None result += ' %s: %s\n'%(flag_name, flag_value) pos = match.end() result += '\n' @@ -228,30 +255,45 @@ class TensorTracer(object): @staticmethod def get_flag_value(wanted_flag_name): - """Returns the value of a TensorTracer flags.""" + """Returns the value of a TensorTracer flags. + + Args: + wanted_flag_name: the name the the flag we are looking for. + + Returns: + A pair where the first element indicates if the flag is + found and the second element is the value of the flag. + + Raises: + RuntimeError: If supposedly deadcode is reached. + """ tensor_tracer_flags = os.getenv(_FLAGS_ENV_VAR) if not tensor_tracer_flags: - return '' + return False, None pos = 0 while True: - match = TensorTracer._match_next_flag(tensor_tracer_flags, pos) + match, has_value = TensorTracer._match_next_flag( + tensor_tracer_flags, pos) if not match: - return '' + return False, None flag_name = match.group(1) - flag_value = match.group(2) + if has_value: + flag_value = match.group(2) + else: + flag_value = None if flag_name == wanted_flag_name: - return flag_value + return True, flag_value pos = match.end() - return '' + raise RuntimeError('Should not reach here.') @staticmethod def flag_value_to_re_list(flag_name): """Converts list of strings to compiled RE.""" re_list = [] - flag_value = TensorTracer.get_flag_value(flag_name) - if not flag_value: + found, flag_value = TensorTracer.get_flag_value(flag_name) + if not found or not flag_value: return re_list list_of_values = flag_value.split() for v in list_of_values: @@ -260,32 +302,41 @@ class TensorTracer(object): return re_list @staticmethod - def is_enabled(): - """Returns True if TensorTracer is enabled.""" + def _is_flag_on(flag_name): + """Returns True if the given flag is on.""" - flag_value = TensorTracer.get_flag_value(_FLAG_NAME_ENABLE) + found, flag_value = TensorTracer.get_flag_value(flag_name) + if not found: + return False + if flag_value is None: + return True + # Depends on the flag value. flag_value = flag_value.lower() enabled = flag_value in ['1', 't', 'true', 'y', 'yes'] return enabled + @staticmethod + def is_enabled(): + """Returns True if TensorTracer is enabled.""" + + return TensorTracer._is_flag_on(_FLAG_NAME_ENABLE) + @staticmethod def use_test_undeclared_outputs_dir(): - """Decides the output directory of the trace file. + """Decides the output directory of the report and trace files. Args: None. Returns: - True if the output trace file should be written to the + True if the output files should be written to the test-undeclared-outputs-directory defined via an env variable. """ - flag_value = TensorTracer.get_flag_value( + return TensorTracer._is_flag_on( _FLAG_NAME_USE_TEST_UNDECLARED_OUTPUTS_DIR) - flag_value = flag_value.lower() - enabled = flag_value in ['1', 't', 'true', 'y', 'yes'] - return enabled + @staticmethod def check_device_type(device_type): @@ -306,6 +357,18 @@ class TensorTracer(object): 'Valid trace modes are: %s'%(trace_mode, valid_trace_modes)) + @staticmethod + def check_submode(submode): + """Checks if the given submode is valid.""" + + if not submode: + return + valid_submodes = [_SUBMODE_DETAILED, _SUBMODE_BRIEF] + if submode not in valid_submodes: + raise ValueError('Invalid submode "%s" given to the Tensor_Tracer.' + 'Valid submodes are: %s'%(submode, + valid_submodes)) + @staticmethod def unsafe_op(op): """Returns True if this op is not safe to be traced.""" @@ -315,6 +378,8 @@ class TensorTracer(object): # Reasons for not including following op types: # Assign: cause incorrect result with CPU tracing. # others: compilation problems. + # TODO(deveci): Check if 'Pack', 'Shape', 'Reshape', 'ArgMin', 'ArgMax' + # are still unsafe now that we have handled int64 tensors. if op.type in ['Assign', 'Pack', 'Shape', 'Reshape', 'ArgMin', 'ArgMax']: return True return False @@ -350,10 +415,12 @@ class TensorTracer(object): def less_interesting_op(op): """Returns True if the given Op is not an interesting one to be traced.""" - include_less_interesting = TensorTracer.get_flag_value( + found, _ = TensorTracer.get_flag_value( _FLAG_NAME_INCLUDE_LESS_INTERESTING_OPS) - if include_less_interesting: + if found: + # users force to include all ops. return False + # Following ops are highly unlikey to cause bugs. return op.type in ['Const', 'Identity', 'Cast', 'Shape'] @staticmethod @@ -460,10 +527,14 @@ class TensorTracer(object): self._version = 'use-outside-compilation' self._device_type = None TensorTracer.validate_flag_names() - self._trace_mode = TensorTracer.get_flag_value(_FLAG_NAME_TRACE_MODE) - if not self._trace_mode: + found, self._trace_mode = TensorTracer.get_flag_value(_FLAG_NAME_TRACE_MODE) + if not found or not self._trace_mode: self._trace_mode = _TRACE_MODE_NAN_INF TensorTracer.check_trace_mode(self._trace_mode) + found, self._submode = TensorTracer.get_flag_value(_FLAG_NAME_SUBMODE) + if not found or not self._submode: + self._submode = _SUBMODE_DETAILED + TensorTracer.check_submode(self._submode) self._part_tensor_size = _TRACE_MODE_PART_TENSOR_SIZE self._instrument_records = {} self._set_trace_file_path() @@ -499,8 +570,10 @@ class TensorTracer(object): def _set_trace_file_path(self): """Sets the path of the output trace file.""" - self._trace_file_path = TensorTracer.get_flag_value(_FLAG_NAME_TRACE_FILE) - if self._trace_file_path and TensorTracer.use_test_undeclared_outputs_dir(): + found, self._trace_file_path = TensorTracer.get_flag_value( + _FLAG_NAME_TRACE_FILE) + if found and self._trace_file_path \ + and TensorTracer.use_test_undeclared_outputs_dir(): if os.path.isabs(self._trace_file_path): raise ValueError('If use_test_undeclared_outputs_dir is set,' 'trace_file_path cannot be an absolute path (%s)' @@ -512,7 +585,17 @@ class TensorTracer(object): def _set_report_file(self): """Sets the path of the output report file.""" - self._report_file_path = TensorTracer.get_flag_value(_FLAG_NAME_REPORT_FILE) + found, self._report_file_path = TensorTracer.get_flag_value( + _FLAG_NAME_REPORT_FILE) + if found and self._report_file_path \ + and TensorTracer.use_test_undeclared_outputs_dir(): + if os.path.isabs(self._report_file_path): + raise ValueError('If use_test_undeclared_outputs_dir is set,' + 'report_file_path cannot be an absolute path (%s)' + %self._report_file_path) + outputs_dir = os.environ.get(_TEST_UNDECLARED_OUTPUTS_DIR_ENV_VAR) + self._report_file_path = os.path.join(outputs_dir, + self._report_file_path) if not self._report_file_path: self._report_file = None return @@ -528,8 +611,8 @@ class TensorTracer(object): def _set_op_range(self): """Sets the index range of the Ops that we will consider tracing.""" - op_range = TensorTracer.get_flag_value(_FLAG_NAME_OP_RANGE) - if not op_range: + found, op_range = TensorTracer.get_flag_value(_FLAG_NAME_OP_RANGE) + if not found or not op_range: self._op_range = (-1, -1) # this means including all ops. return match = _OP_RANGE_PAT.match(op_range) @@ -595,6 +678,7 @@ class TensorTracer(object): self._write_report('%s %s\n'%(_FIELD_NAME_VERSION, self._version)) self._write_report('%s %s\n'%(_FIELD_NAME_DEVICE, self._device_type)) self._write_report('%s %s\n'%(_FIELD_NAME_TRACE_MODE, self._trace_mode)) + self._write_report('%s %s\n'%(_FIELD_NAME_SUBMODE, self._submode)) self._write_report('%s %s\n'%(_FIELD_NAME_NUM_REPLICAS, self._num_replicas)) self._write_report('%s %s\n'%(_MARKER_SECTION_END, _SECTION_NAME_CONFIG)) @@ -606,7 +690,7 @@ class TensorTracer(object): self._write_report('"%s" %s\n'%(key, self._instrument_records[key])) self._write_report('%s %s\n'%(_MARKER_SECTION_END, _SECTION_NAME_REASON)) - def _write_op_list_section(self, op_list, tensorname_idx_map): + def _write_op_list_section(self, op_list): """Writes the Op-list section of the report.""" self._write_report('%s %s\n'%(_MARKER_SECTION_BEGIN, _SECTION_NAME_OP_LIST)) @@ -615,10 +699,10 @@ class TensorTracer(object): op = op_list[i] line = '%d "%s" %s'%(i, op.name, op.type) for out_tensor in op.outputs: - if out_tensor.name not in tensorname_idx_map: + if out_tensor.name not in self._tensorname_idx_map: raise ValueError( 'out_tensor %s is not in tensorname_idx_map'%out_tensor.name) - line += ' %d'%tensorname_idx_map[out_tensor.name] + line += ' %d'%self._tensorname_idx_map[out_tensor.name] line += '\n' self._write_report(line) self._write_report('%s %s\n'%(_MARKER_SECTION_END, _SECTION_NAME_OP_LIST)) @@ -653,12 +737,11 @@ class TensorTracer(object): self._write_report('%d "%s"\n'%(i, l[i].name)) self._write_report('%s %s\n'%(_MARKER_SECTION_END, _SECTION_NAME_GRAPH)) - def _make_tensor_trace_fun(self, op_name, output_idx): + def _make_tensor_trace_fun(self, tensor_name): """Makes the tensor tracing function called by outside compilation. Args: - op_name: the name of the Op that outputs the tensor to be traced. - output_idx: which output of the Op it is (0 means the first output). + tensor_name: name of the tensor being traced. Returns: A function to be passed as the first argument to outside compilation. @@ -667,26 +750,37 @@ class TensorTracer(object): RuntimeError: If the trace mode is invalid. """ - def _print_tensor(op_name, output_idx, num_elements, tensor, output_tensor): + def _print_tensor(tensor_name, num_elements, tensor, output_tensor): """Prints a tensor value to a file. Args: - op_name: the name of the Op that outputs the tensor to be printed. - output_idx: which output of the Op it is (0 means the first output). + tensor_name: name of the tensor being traced. num_elements: number of elements to print (-1 means print all). tensor: the tensor needs to be returned. output_tensor: the tensor needs to be printed. Returns: The same tensor passed via the "tensor" argument. + + Raises: + ValueError: If tensor_name is not already in + self._tensorname_idx_map. """ - msg = '"%s:%d" '%(op_name, output_idx) + + if self._submode == _SUBMODE_BRIEF: + if tensor_name not in self._tensorname_idx_map: + raise ValueError( + 'Tensor name %s is not in the tensorname_idx_map'%tensor_name) + msg = '%d'%self._tensorname_idx_map[tensor_name] + else: + msg = '"%s"'%tensor_name + if self._trace_file_path: output_stream = _OUTPUT_STREAM_ESCAPE + self._trace_file_path else: output_stream = sys.stderr print_op = logging_ops.print_v2(msg, array_ops.shape(output_tensor), - ' @', self._replica_id, + '@', self._replica_id, '\n', output_tensor, '\n', summarize=num_elements, output_stream=output_stream) @@ -696,39 +790,37 @@ class TensorTracer(object): def _detect_nan_inf(tensor): """Trace function for detecting any NaN/Inf in the tensor.""" - if tensor.dtype.__eq__(dtypes.bfloat16) or tensor.dtype.__eq__( - dtypes.float16): - # Since host can't handle bf16, always convert tensor to f32. - tensor = math_ops.cast(tensor, dtypes.float32) + if tensor.dtype.is_floating: output_tensor = math_ops.reduce_any( gen_math_ops.logical_or(gen_math_ops.is_nan(tensor), gen_math_ops.is_inf(tensor))) else: - output_tensor = constant_op.constant(0) - return _print_tensor(op_name, output_idx, -1, tensor, output_tensor) + output_tensor = constant_op.constant(False) + + return _print_tensor(tensor_name, -1, tensor, output_tensor) def _show_norm(tensor): tensor = math_ops.cast(tensor, dtypes.float64) output_tensor = linalg_ops.norm(tensor) - return _print_tensor(op_name, output_idx, -1, tensor, output_tensor) + return _print_tensor(tensor_name, -1, tensor, output_tensor) def _show_max_abs(tensor): output_tensor = math_ops.cast(math_ops.reduce_max(math_ops.abs(tensor)), dtypes.float64) zero = constant_op.constant(0, dtypes.float64) output_tensor = gen_math_ops.maximum(zero, output_tensor) - return _print_tensor(op_name, output_idx, -1, tensor, output_tensor) + return _print_tensor(tensor_name, -1, tensor, output_tensor) def _show_part_tensor(tensor): """Trace function for printing part of the tensor.""" - return _print_tensor(op_name, output_idx, self._part_tensor_size, + return _print_tensor(tensor_name, self._part_tensor_size, tensor, tensor) def _show_full_tensor(tensor): """Trace function for printing the entire tensor.""" - return _print_tensor(op_name, output_idx, -1, tensor, tensor) + return _print_tensor(tensor_name, -1, tensor, tensor) if self._trace_mode == _TRACE_MODE_NAN_INF: return _detect_nan_inf @@ -821,10 +913,10 @@ class TensorTracer(object): """Work needs to be done prior to TPU or CPU tracing.""" operations = graph.get_operations() - (opname_idx_map, tensor_list, tensorname_idx_map) = ( + (opname_idx_map, tensor_list, self._tensorname_idx_map) = ( TensorTracer._make_op_and_tensor_maps(operations)) self._write_config_section() - self._write_op_list_section(operations, tensorname_idx_map) + self._write_op_list_section(operations) self._write_tensor_list_section(tensor_list, opname_idx_map) # Does the topological sort before adding any nodes to the graph. (succeed, sorted_or_cycle) = TensorTracer.topological_sort(graph) @@ -876,6 +968,18 @@ class TensorTracer(object): graph is evaluated. """ + def _cast_unsupported_dtypes(tensor): + """Casts tensor to a supported type.""" + + if tensor.dtype.__eq__(dtypes.int64): + # outside-compilation doesn't support int64 input yet. + return math_ops.cast(tensor, dtypes.int32) + if tensor.dtype.__eq__(dtypes.bfloat16) or tensor.dtype.__eq__( + dtypes.float16): + # Since host can't handle bf16, convert tensor to f32. + return math_ops.cast(tensor, dtypes.float32) + return tensor + self._device_type = _DEVICE_TYPE_TPU TensorTracer.check_device_type(self._device_type) result_tensor_copy = self._add_replica_id_to_graph(num_replicas, @@ -897,8 +1001,10 @@ class TensorTracer(object): user_excluded): continue consumers = out_tensor.consumers() + tensor_name = out_tensor.name + out_tensor = _cast_unsupported_dtypes(out_tensor) trace_op = tpu.outside_compilation( - self._make_tensor_trace_fun(op.name, i), out_tensor) + self._make_tensor_trace_fun(tensor_name), out_tensor) if consumers: for consumer_op in consumers: # pylint: disable=protected-access @@ -944,7 +1050,7 @@ class TensorTracer(object): if self._skip_tensor(op_id, out_tensor, user_included, user_excluded): continue - trace_fun = self._make_tensor_trace_fun(op.name, i) + trace_fun = self._make_tensor_trace_fun(out_tensor.name) trace_call = (trace_fun, [out_tensor]) trace_call_key = 'tensor_tracing_cpu-%s:%d'%(op.name, i) tracing_calls[trace_call_key] = trace_call -- GitLab From 04ff761f1f609056a56272473acda7428cbaddcc Mon Sep 17 00:00:00 2001 From: Suharsh Sivakumar Date: Thu, 20 Dec 2018 19:30:17 -0800 Subject: [PATCH 0233/1765] SparseOutputFullyConnected supports hybrid INT8 PiperOrigin-RevId: 226431461 --- .../kernels/sparse_output_fully_connected.cc | 31 ++++++++++------ .../sparse_output_fully_connected_test.cc | 35 ++++++++++++++++++- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/tensorflow/lite/kernels/sparse_output_fully_connected.cc b/tensorflow/lite/kernels/sparse_output_fully_connected.cc index 73d850f0e2..248969535c 100644 --- a/tensorflow/lite/kernels/sparse_output_fully_connected.cc +++ b/tensorflow/lite/kernels/sparse_output_fully_connected.cc @@ -86,7 +86,8 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { TF_LITE_ENSURE_EQ(context, NumElements(bias), SizeOfDimension(weights, 0)); const bool is_hybrid_op = - (weights->type == kTfLiteUInt8 && input->type == kTfLiteFloat32); + ((weights->type == kTfLiteUInt8 || weights->type == kTfLiteInt8) && + input->type == kTfLiteFloat32); // Resize output. TfLiteTensor* output = GetOutput(context, node, kOutputTensor); @@ -103,7 +104,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { node->temporaries->data[kInputQuantized] = op_data->scratch_tensor_index; TfLiteTensor* input_quantized = GetTemporary(context, node, /*index=*/kInputQuantized); - input_quantized->type = kTfLiteUInt8; + input_quantized->type = weights->type; input_quantized->allocation_type = kTfLiteArenaRw; if (!TfLiteIntArrayEqual(input_quantized->dims, input->dims)) { TfLiteIntArray* input_quantized_size = TfLiteIntArrayCopy(input->dims); @@ -164,16 +165,23 @@ TfLiteStatus EvalHybrid(const TfLiteTensor* input, const TfLiteTensor* lookup, const int n_input = SizeOfDimension(input, 1); const float* input_ptr_batch = input->data.f; - // Initialize the pointer to storage for quantized values and - // scaling factors. - int8_t* quantized_input_ptr_batch = - reinterpret_cast(input_quantized->data.uint8); - float* scaling_factors_ptr = scaling_factors->data.f; - // Initialize pointer to right row according to lookup value. + // Initialize the pointer to storage for scaling factors. + float* scaling_factors_ptr = scaling_factors->data.f; int32 lookup_index = lookup->data.i32[0]; - int8_t* weights_ptr = - reinterpret_cast(weights->data.uint8) + lookup_index * n_input; + + // Initialize the pointer to storage for quantized values and a pointer to + // the row according to lookup value. + int8_t *quantized_input_ptr_batch, *weights_ptr; + if (weights->type == kTfLiteUInt8) { + quantized_input_ptr_batch = + reinterpret_cast(input_quantized->data.uint8); + weights_ptr = + reinterpret_cast(weights->data.uint8) + lookup_index * n_input; + } else { + quantized_input_ptr_batch = input_quantized->data.int8; + weights_ptr = weights->data.int8 + lookup_index * n_input; + } // Initialize output to bias. if (bias) { @@ -212,7 +220,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { case kTfLiteFloat32: { return EvalFloat(input, lookup, weights, bias, output); } - case kTfLiteUInt8: { + case kTfLiteUInt8: + case kTfLiteInt8: { TfLiteTensor* input_quantized = GetTemporary(context, node, /*index=*/kInputQuantized); TfLiteTensor* scaling_factors = diff --git a/tensorflow/lite/kernels/sparse_output_fully_connected_test.cc b/tensorflow/lite/kernels/sparse_output_fully_connected_test.cc index c25a32bde0..fb71cb7f7b 100644 --- a/tensorflow/lite/kernels/sparse_output_fully_connected_test.cc +++ b/tensorflow/lite/kernels/sparse_output_fully_connected_test.cc @@ -93,6 +93,10 @@ class HybridSparseOutputFullyConnectedOpModel void SetWeights(const std::vector& f) { SymmetricQuantizeAndPopulate(weights_, f); } + + void SetSignedWeights(const std::vector& f) { + SignedSymmetricQuantizeAndPopulate(weights_, f); + } }; TEST(SparseOutputFullyConnectedOpTest, SimpleTestFloat) { @@ -117,7 +121,7 @@ TEST(SparseOutputFullyConnectedOpTest, SimpleTestFloat) { EXPECT_THAT(m.GetOutput(), ElementsAreArray({28})); } -TEST(SparseOutputFullyConnectedOpTest, SimpleTestHybrid) { +TEST(SparseOutputFullyConnectedOpTest, SimpleTestHybridUint8) { HybridSparseOutputFullyConnectedOpModel m({TensorType_FLOAT32, {1, 5}}, {TensorType_UINT8, {3, 5}}, {TensorType_FLOAT32, {}}); @@ -146,6 +150,35 @@ TEST(SparseOutputFullyConnectedOpTest, SimpleTestHybrid) { EXPECT_THAT(m.GetOutput(), ElementsAreArray(ArrayFloatNear({28}, 0.0553))); } +TEST(SparseOutputFullyConnectedOpTest, SimpleTestHybridInt8) { + HybridSparseOutputFullyConnectedOpModel m({TensorType_FLOAT32, {1, 5}}, + {TensorType_INT8, {3, 5}}, + {TensorType_FLOAT32, {}}); + + m.SetInput({-1.0, 0.0, 1.0, 2.0, 3.0}); + + m.SetLookup({2}); + + m.SetSignedWeights({ + -1.0, 0.0, 1.0, 2.0, 3.0, // + 0.0, 1.0, 2.0, 3.0, 4.0, // + 1.0, 2.0, 3.0, 4.0, 5.0, // + }); + + m.SetBias({1.0, 2.0, 3.0}); + + m.Invoke(); + + // We get 28.0552 instead of 28. + // + // Input -> -42, 0, 42, 85, 127 with scale factor of 127/3. + // Looked up weights -> 25, 51, 76, 102, 127 with scale factor of 127/5. + // + // (-42 * 25 + 0 * 51 + 42 * 76 + 85 * 102 + 127 * 127) * (3*5/127^2) + 3.0 + // gives us the expected result. + EXPECT_THAT(m.GetOutput(), ElementsAreArray(ArrayFloatNear({28}, 0.0553))); +} + } // namespace } // namespace custom } // namespace ops -- GitLab From 1b2c81745d87c956b156dfd85d69cc89523e86eb Mon Sep 17 00:00:00 2001 From: Suharsh Sivakumar Date: Thu, 20 Dec 2018 19:57:28 -0800 Subject: [PATCH 0234/1765] BasicRNN hybrid INT8 support. PiperOrigin-RevId: 226433368 --- tensorflow/lite/kernels/basic_rnn.cc | 33 ++++++++++---- tensorflow/lite/kernels/basic_rnn_test.cc | 52 ++++++++++++++++++++--- tensorflow/lite/kernels/register.cc | 4 +- 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/tensorflow/lite/kernels/basic_rnn.cc b/tensorflow/lite/kernels/basic_rnn.cc index 7c66ce1992..a2c38b3b7d 100644 --- a/tensorflow/lite/kernels/basic_rnn.cc +++ b/tensorflow/lite/kernels/basic_rnn.cc @@ -27,6 +27,16 @@ namespace ops { namespace builtin { namespace rnn { +namespace { +int8_t* GetInt8DataPtr(const TfLiteTensor* tensor, const bool is_uint8) { + if (is_uint8) { + return reinterpret_cast(tensor->data.uint8); + } else { + return tensor->data.int8; + } +} +} // namespace + constexpr int kInputTensor = 0; constexpr int kWeightsTensor = 1; constexpr int kRecurrentWeightsTensor = 2; @@ -85,15 +95,19 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { TF_LITE_ENSURE_OK(context, context->ResizeTensor(context, output, output_size_array)); + bool is_hybrid = + input->type == kTfLiteFloat32 && (input_weights->type == kTfLiteUInt8 || + input_weights->type == kTfLiteInt8); + // Allocate temporary tensors to store quantized values of input and // hidden_state tensors. - if (input->type == kTfLiteFloat32 && input_weights->type == kTfLiteUInt8) { + if (is_hybrid) { int* scratch_tensor_index = reinterpret_cast(node->user_data); TfLiteIntArrayFree(node->temporaries); node->temporaries = TfLiteIntArrayCreate(3); node->temporaries->data[0] = *scratch_tensor_index; TfLiteTensor* input_quantized = GetTemporary(context, node, /*index=*/0); - input_quantized->type = kTfLiteUInt8; + input_quantized->type = input_weights->type; input_quantized->allocation_type = kTfLiteArenaRw; if (!TfLiteIntArrayEqual(input_quantized->dims, input->dims)) { TfLiteIntArray* input_quantized_size = TfLiteIntArrayCopy(input->dims); @@ -103,7 +117,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { node->temporaries->data[1] = *scratch_tensor_index + 1; TfLiteTensor* hidden_state_quantized = GetTemporary(context, node, /*index=*/1); - hidden_state_quantized->type = kTfLiteUInt8; + hidden_state_quantized->type = input_weights->type; hidden_state_quantized->allocation_type = kTfLiteArenaRw; if (!TfLiteIntArrayEqual(hidden_state_quantized->dims, hidden_state->dims)) { @@ -165,6 +179,7 @@ TfLiteStatus EvalHybrid(const TfLiteTensor* input, TfLiteTensor* hidden_state_scratch, TfLiteTensor* scaling_factors, TfLiteTensor* hidden_state, TfLiteTensor* output) { + const bool is_uint8_hybrid = input_weights->type == kTfLiteUInt8; const int batch_size = input->dims->data[0]; const int num_units = input_weights->dims->data[0]; const int input_size = input->dims->data[1]; @@ -178,18 +193,17 @@ TfLiteStatus EvalHybrid(const TfLiteTensor* input, float* output_ptr_batch = output->data.f; // Initialize input_weights, recurrent_weights and bias. const int8_t* input_weights_ptr = - reinterpret_cast(input_weights->data.uint8); + GetInt8DataPtr(input_weights, is_uint8_hybrid); const int8_t* recurrent_weights_ptr = - reinterpret_cast(recurrent_weights->data.uint8); + GetInt8DataPtr(recurrent_weights, is_uint8_hybrid); const float* bias_ptr = bias->data.f; // Get the scale of the quantized weights. float input_weights_scale = input_weights->params.scale; float recurrent_weights_scale = recurrent_weights->params.scale; // Initialize temporary storage for quantized values. - int8_t* quantized_input_ptr = - reinterpret_cast(input_scratch->data.uint8); + int8_t* quantized_input_ptr = GetInt8DataPtr(input_scratch, is_uint8_hybrid); int8_t* quantized_hidden_state_ptr = - reinterpret_cast(hidden_state_scratch->data.uint8); + GetInt8DataPtr(hidden_state_scratch, is_uint8_hybrid); float* scaling_factors_ptr = scaling_factors->data.f; kernel_utils::RnnBatchStep( @@ -218,7 +232,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { case kTfLiteFloat32: return EvalFloat(input, input_weights, recurrent_weights, bias, params, hidden_state, output); - case kTfLiteUInt8: { + case kTfLiteUInt8: + case kTfLiteInt8: { // TODO(mirkov): implement eval with quantized inputs as well. TfLiteTensor* input_quantized = GetTemporary(context, node, 0); TfLiteTensor* hidden_state_quantized = GetTemporary(context, node, 1); diff --git a/tensorflow/lite/kernels/basic_rnn_test.cc b/tensorflow/lite/kernels/basic_rnn_test.cc index 240057d18a..c71849fff3 100644 --- a/tensorflow/lite/kernels/basic_rnn_test.cc +++ b/tensorflow/lite/kernels/basic_rnn_test.cc @@ -233,15 +233,25 @@ class RNNOpModel : public SingleOpModel { // The hybrid model has quantized weights and recurrent_weights. class HybridRNNOpModel : public RNNOpModel { public: - HybridRNNOpModel(int batches, int units, int size) - : RNNOpModel(batches, units, size, TensorType_UINT8, TensorType_UINT8) {} + HybridRNNOpModel(int batches, int units, int size, TensorType tensor_type) + : RNNOpModel(batches, units, size, tensor_type, tensor_type) { + tensor_type_ = tensor_type; + } - void SetWeights(std::initializer_list f) { - SymmetricQuantizeAndPopulate(weights_, f); + TensorType tensor_type_; + + void SetWeights(int weights_idx, std::vector f) { + if (tensor_type_ == TensorType_UINT8) { + SymmetricQuantizeAndPopulate(weights_idx, f); + } else { + SignedSymmetricQuantizeAndPopulate(weights_idx, f); + } } + void SetWeights(std::initializer_list f) { SetWeights(weights_, f); } + void SetRecurrentWeights(std::initializer_list f) { - SymmetricQuantizeAndPopulate(recurrent_weights_, f); + SetWeights(recurrent_weights_, f); } }; @@ -272,8 +282,36 @@ TEST(RnnOpTest, BlackBoxTest) { } } -TEST(HybridRnnOpTest, BlackBoxTest) { - HybridRNNOpModel rnn(2, 16, 8); +TEST(HybridRnnOpTest, BlackBoxTestUint8) { + HybridRNNOpModel rnn(2, 16, 8, TensorType_UINT8); + rnn.SetWeights(rnn_weights); + rnn.SetBias(rnn_bias); + rnn.SetRecurrentWeights(rnn_recurrent_weights); + + const int input_sequence_size = sizeof(rnn_input) / sizeof(float) / + (rnn.input_size() * rnn.num_batches()); + + for (int i = 0; i < input_sequence_size; i++) { + float* batch_start = rnn_input + i * rnn.input_size(); + float* batch_end = batch_start + rnn.input_size(); + rnn.SetInput(0, batch_start, batch_end); + rnn.SetInput(rnn.input_size(), batch_start, batch_end); + + rnn.Invoke(); + + float* golden_start = rnn_golden_output + i * rnn.num_units(); + float* golden_end = golden_start + rnn.num_units(); + std::vector expected; + expected.insert(expected.end(), golden_start, golden_end); + expected.insert(expected.end(), golden_start, golden_end); + + EXPECT_THAT(rnn.GetOutput(), ElementsAreArray(ArrayFloatNear( + expected, /*max_abs_error=*/0.0104))); + } +} + +TEST(HybridRnnOpTest, BlackBoxTestInt8) { + HybridRNNOpModel rnn(2, 16, 8, TensorType_INT8); rnn.SetWeights(rnn_weights); rnn.SetBias(rnn_bias); rnn.SetRecurrentWeights(rnn_recurrent_weights); diff --git a/tensorflow/lite/kernels/register.cc b/tensorflow/lite/kernels/register.cc index f51bbc3615..f6cfb96df0 100644 --- a/tensorflow/lite/kernels/register.cc +++ b/tensorflow/lite/kernels/register.cc @@ -174,7 +174,9 @@ BuiltinOpResolver::BuiltinOpResolver() { /* min_version */ 1, /* max_version */ 3); AddBuiltin(BuiltinOperator_SVDF, Register_SVDF()); - AddBuiltin(BuiltinOperator_RNN, Register_RNN()); + AddBuiltin(BuiltinOperator_RNN, Register_RNN(), + /* min_version */ 1, + /* max_version */ 2); AddBuiltin(BuiltinOperator_BIDIRECTIONAL_SEQUENCE_RNN, Register_BIDIRECTIONAL_SEQUENCE_RNN()); AddBuiltin(BuiltinOperator_UNIDIRECTIONAL_SEQUENCE_RNN, -- GitLab From 02ac99e6ad83b5d8705792d7270ba2bf7a2f5693 Mon Sep 17 00:00:00 2001 From: Mark Heffernan Date: Thu, 20 Dec 2018 20:08:38 -0800 Subject: [PATCH 0235/1765] Add is_dynamic_dimension repeated bool field to Shape. The bool indicates which of the dimensions in the Shape are dynamic. For dynamic dimensions the 'dimensions' int64 value indicates an inclusive upper bound on the dimension bound. This CL adds the field to ShapeProto and Shape and adds support to the parser. It is unused otherwise. This change also includes a couple small changes to the Shape interface to preserve the invariant that the dimensions vector and the dynamic_dimensions vector are always the same size. This may not be the final form for dynamic shape representation. Having int64 lower and upper bounds may be cleaner where static dimensions have equal lower and upper bound dimensions. However, this current representation is sufficiently expressive to start using dynamic shapes in other parts of XLA. Shape inference would be a natural first step. Changing the underlying shape representation during this initial process should not be too difficult. PiperOrigin-RevId: 226434424 --- tensorflow/compiler/xla/service/hlo_lexer.cc | 8 +++ tensorflow/compiler/xla/service/hlo_lexer.h | 1 + tensorflow/compiler/xla/service/hlo_parser.cc | 28 +++++++-- .../compiler/xla/service/hlo_parser_test.cc | 20 ++++++ .../compiler/xla/service/hlo_sharding.cc | 4 +- .../compiler/xla/service/reshape_mover.cc | 5 +- tensorflow/compiler/xla/shape.cc | 34 +++++++++++ tensorflow/compiler/xla/shape.h | 40 ++++++++++-- tensorflow/compiler/xla/shape_test.cc | 41 +++++++++++++ tensorflow/compiler/xla/shape_util.cc | 61 +++++++++++++------ tensorflow/compiler/xla/shape_util.h | 15 ++++- tensorflow/compiler/xla/shape_util_test.cc | 22 +++++++ tensorflow/compiler/xla/xla_data.proto | 19 ++++-- 13 files changed, 260 insertions(+), 38 deletions(-) diff --git a/tensorflow/compiler/xla/service/hlo_lexer.cc b/tensorflow/compiler/xla/service/hlo_lexer.cc index dc712e5e42..5e81515134 100644 --- a/tensorflow/compiler/xla/service/hlo_lexer.cc +++ b/tensorflow/compiler/xla/service/hlo_lexer.cc @@ -140,6 +140,12 @@ TokKind HloLexer::LexToken() { return LexNumberOrPattern(); case '=': return TokKind::kEqual; + case '<': + if (current_char == '<' && PeekCurrentChar() == '=') { + current_ptr_++; + return TokKind::kLeq; + } + return TokKind::kError; case ',': return TokKind::kComma; case '%': @@ -462,6 +468,8 @@ string TokKindToString(TokKind kind) { return "kRparen"; case TokKind::kArrow: return "kArrow"; + case TokKind::kLeq: + return "kLeq"; case TokKind::kw_HloModule: return "kw_HloModule"; case TokKind::kw_ENTRY: diff --git a/tensorflow/compiler/xla/service/hlo_lexer.h b/tensorflow/compiler/xla/service/hlo_lexer.h index 41f5043904..94fac3cd8e 100644 --- a/tensorflow/compiler/xla/service/hlo_lexer.h +++ b/tensorflow/compiler/xla/service/hlo_lexer.h @@ -49,6 +49,7 @@ enum class TokKind { kRparen, // ( ) kArrow, // -> + kLeq, // <= // Keywords kw_HloModule, diff --git a/tensorflow/compiler/xla/service/hlo_parser.cc b/tensorflow/compiler/xla/service/hlo_parser.cc index 80c31b8db6..56848ce0e8 100644 --- a/tensorflow/compiler/xla/service/hlo_parser.cc +++ b/tensorflow/compiler/xla/service/hlo_parser.cc @@ -257,7 +257,8 @@ class HloParser { bool ParseName(string* result); bool ParseAttributeName(string* result); bool ParseString(string* result); - bool ParseDimensionSizes(std::vector* dimension_sizes); + bool ParseDimensionSizes(std::vector* dimension_sizes, + std::vector* dynamic_dimensions); bool ParseShape(Shape* result); bool ParseLayout(Layout* layout); bool ParseOpcode(HloOpcode* result); @@ -2971,14 +2972,25 @@ bool HloParser::ParseParamList() { return ParseToken(TokKind::kRparen, "expects ')' at the end of param list"); } -// dimension_sizes ::= '[' int64_list ']' -bool HloParser::ParseDimensionSizes(std::vector* dimension_sizes) { +// dimension_sizes ::= '[' dimension_list ']' +// dimension_list +// ::= /*empty*/ +// ::= <=? int64 (',' param)* +// param ::= name shape +bool HloParser::ParseDimensionSizes(std::vector* dimension_sizes, + std::vector* dynamic_dimensions) { auto parse_and_add_item = [&]() { tensorflow::int64 i; + bool is_dynamic = false; + if (lexer_.GetKind() == TokKind::kLeq) { + is_dynamic = true; + lexer_.Lex(); + } if (!ParseInt64(&i)) { return false; } dimension_sizes->push_back(i); + dynamic_dimensions->push_back(is_dynamic); return true; }; return ParseList(TokKind::kLsquare, TokKind::kRsquare, TokKind::kComma, @@ -3034,12 +3046,18 @@ bool HloParser::ParseShape(Shape* result) { PrimitiveType primitive_type = lexer_.GetPrimitiveTypeVal(); lexer_.Lex(); + // Each element contains a dimension size and a bool indicating whether this + // is a dynamic dimension. std::vector dimension_sizes; - if (!ParseDimensionSizes(&dimension_sizes)) { + std::vector dynamic_dimensions; + if (!ParseDimensionSizes(&dimension_sizes, &dynamic_dimensions)) { return false; } result->set_element_type(primitive_type); - *result->mutable_dimensions() = dimension_sizes; + for (int i = 0; i < dimension_sizes.size(); ++i) { + result->add_dimensions(dimension_sizes[i]); + result->set_dynamic_dimension(i, dynamic_dimensions[i]); + } LayoutUtil::SetToDefaultLayout(result); if (lexer_.GetKind() == TokKind::kw_sparse) { diff --git a/tensorflow/compiler/xla/service/hlo_parser_test.cc b/tensorflow/compiler/xla/service/hlo_parser_test.cc index ef31cec327..bc1a736766 100644 --- a/tensorflow/compiler/xla/service/hlo_parser_test.cc +++ b/tensorflow/compiler/xla/service/hlo_parser_test.cc @@ -2329,5 +2329,25 @@ TEST_F(HloParserTest, ParseInvalidShapeString) { } } +TEST_F(HloParserTest, ParseDynamicArray) { + string shape_string = "f32[123,<=456]"; + TF_ASSERT_OK_AND_ASSIGN(Shape actual, ParseShape(shape_string)); + Shape expected = ShapeUtil::MakeShape(F32, {123, 456}, {false, true}); + ASSERT_TRUE(ShapeUtil::Equal(expected, actual)) + << "expected: " << ShapeUtil::HumanString(expected) + << "actual: " << ShapeUtil::HumanString(actual); +} + +TEST_F(HloParserTest, ParseDynamicTuple) { + string shape_string = "(f32[42], u32[<=123,<=456])"; + TF_ASSERT_OK_AND_ASSIGN(Shape actual, ParseShape(shape_string)); + Shape expected = ShapeUtil::MakeTupleShape( + {ShapeUtil::MakeShape(F32, {42}), + ShapeUtil::MakeShape(U32, {123, 456}, {true, true})}); + ASSERT_TRUE(ShapeUtil::Equal(expected, actual)) + << "expected: " << ShapeUtil::HumanString(expected) + << "actual: " << ShapeUtil::HumanString(actual); +} + } // namespace } // namespace xla diff --git a/tensorflow/compiler/xla/service/hlo_sharding.cc b/tensorflow/compiler/xla/service/hlo_sharding.cc index e8c198e303..bdd6ec1169 100644 --- a/tensorflow/compiler/xla/service/hlo_sharding.cc +++ b/tensorflow/compiler/xla/service/hlo_sharding.cc @@ -437,8 +437,8 @@ Shape HloSharding::TileShape(const Shape& shape) const { } Shape result_shape = shape; for (int64 i = 0; i < shape.dimensions_size(); ++i) { - (*result_shape.mutable_dimensions())[i] = - CeilOfRatio(shape.dimensions(i), tile_assignment_.dim(i)); + result_shape.set_dimensions( + i, CeilOfRatio(shape.dimensions(i), tile_assignment_.dim(i))); } return result_shape; } diff --git a/tensorflow/compiler/xla/service/reshape_mover.cc b/tensorflow/compiler/xla/service/reshape_mover.cc index 4df746fca9..a62118df15 100644 --- a/tensorflow/compiler/xla/service/reshape_mover.cc +++ b/tensorflow/compiler/xla/service/reshape_mover.cc @@ -226,7 +226,10 @@ StatusOr PerformSinkReshapeOrTranspose( // changes, so all the fused instructions have the same dimensions. for (const auto& fused_instruction : instruction->fused_instructions()) { Shape* shape = fused_instruction->mutable_shape(); - *shape->mutable_dimensions() = new_operand_shape.dimensions(); + shape->clear_dimensions(); + for (int64 i : new_operand_shape.dimensions()) { + shape->add_dimensions(i); + } *shape->mutable_layout() = new_operand_shape.layout(); } } diff --git a/tensorflow/compiler/xla/shape.cc b/tensorflow/compiler/xla/shape.cc index b206345db2..32dc4fa9f3 100644 --- a/tensorflow/compiler/xla/shape.cc +++ b/tensorflow/compiler/xla/shape.cc @@ -61,6 +61,40 @@ string Shape::ToString(bool print_layout) const { } } +bool Shape::is_static() const { + if (ShapeUtil::IsTuple(*this)) { + for (const Shape& subshape : tuple_shapes_) { + if (!subshape.is_static()) { + return false; + } + } + } + return !std::any_of(dynamic_dimensions_.begin(), dynamic_dimensions_.end(), + [](bool b) { return b; }); +} + +void Shape::DeleteDimension(int64 dim_to_delete) { + CHECK(ShapeUtil::IsArray(*this)); + CHECK_GE(dim_to_delete, 0); + CHECK_LT(dim_to_delete, dimensions_.size()); + dimensions_.erase(dimensions_.begin() + dim_to_delete); + dynamic_dimensions_.erase(dynamic_dimensions_.begin() + dim_to_delete); + if (LayoutUtil::HasLayout(*this)) { + layout_.set_format(DENSE); + for (int64 i = 0; i < layout_.minor_to_major().size();) { + if (layout_.minor_to_major(i) == dim_to_delete) { + layout_.mutable_minor_to_major()->erase( + layout_.mutable_minor_to_major()->begin() + i); + continue; + } + if (layout_.minor_to_major(i) > dim_to_delete) { + (*layout_.mutable_minor_to_major())[i] -= 1; + } + ++i; + } + } +} + std::ostream& operator<<(std::ostream& out, const Shape& shape) { out << shape.ToString(/*print_layout=*/true); return out; diff --git a/tensorflow/compiler/xla/shape.h b/tensorflow/compiler/xla/shape.h index dbd8a53f0e..fb5dc8fba4 100644 --- a/tensorflow/compiler/xla/shape.h +++ b/tensorflow/compiler/xla/shape.h @@ -58,6 +58,26 @@ class Shape { bool IsToken() const { return element_type() == TOKEN; } bool IsOpaque() const { return element_type() == OPAQUE; } + // Returns true if no array dimension in the shape is dynamically sized. Tuple + // shapes are traversed recursively. + bool is_static() const; + + // Returns true if the given dimension is dynamically-sized. + bool is_dynamic_dimension(int dimension) const { + return dynamic_dimensions_.at(dimension); + } + + // Sets whether or not the given dimension is dynamically-sized. + void set_dynamic_dimension(int dimension, bool is_dynamic) { + dynamic_dimensions_[dimension] = is_dynamic; + } + + // Add dimension_upper_bound(). + + // Removes the given dimension form the shape. Layout, if it exists, is + // adjusted to match the modified shape. + void DeleteDimension(int64 dim_to_delete); + // The following methods mirror the protobuf generated code interface for the // message ShapeProto. This enabled easy migration of this data structure // from a proto to a proper C++ class. @@ -72,10 +92,16 @@ class Shape { int dimensions_size() const { return dimensions_.size(); } int64 dimensions(int index) const { return dimensions_.at(index); } void set_dimensions(int index, int64 value) { dimensions_.at(index) = value; } - void add_dimensions(int64 value) { dimensions_.push_back(value); } - void clear_dimensions() { dimensions_.clear(); } + void add_dimensions(int64 value) { + dimensions_.push_back(value); + dynamic_dimensions_.push_back(false); + } + void clear_dimensions() { + dimensions_.clear(); + dynamic_dimensions_.clear(); + } const std::vector& dimensions() const { return dimensions_; } - std::vector* mutable_dimensions() { return &dimensions_; } + absl::Span mutable_dimensions() { return absl::MakeSpan(dimensions_); } // Methods for accessing the tuple subshapes. This field only non-empty for // tuple shapes. @@ -116,9 +142,15 @@ class Shape { // The element type of this shape (tuple, array, etc). PrimitiveType element_type_ = PRIMITIVE_TYPE_INVALID; - // The array bounds of the dimensions. This is nonempty only for array shapes. + // The array bounds of the dimensions. This is nonempty only for array + // shapes. For a dynamically-sized dimension, the respective value in this + // vector is an inclusive upper limit of the array bound. std::vector dimensions_; + // This vector is the same size as 'dimensions_' and indicates whether the + // respective dimension is dynamically sized. + std::vector dynamic_dimensions_; + // The tuple element subshapes. This is nonempty only for tuple shapes. std::vector tuple_shapes_; diff --git a/tensorflow/compiler/xla/shape_test.cc b/tensorflow/compiler/xla/shape_test.cc index e396897eee..e30d041253 100644 --- a/tensorflow/compiler/xla/shape_test.cc +++ b/tensorflow/compiler/xla/shape_test.cc @@ -74,6 +74,47 @@ TEST_F(ShapeTest, ShapeToString) { nested_tuple_.ToString(/*print_layout=*/true)); } +TEST_F(ShapeTest, DynamicShapeToString) { + Shape array_shape = + ShapeUtil::MakeShape(F32, {23, 44, 55}, {true, false, true}); + EXPECT_EQ("f32[<=23,44,<=55]", array_shape.ToString()); + + array_shape.set_dynamic_dimension(2, false); + EXPECT_EQ("f32[<=23,44,55]", array_shape.ToString()); +} + +TEST_F(ShapeTest, IsStatic) { + EXPECT_TRUE(opaque_.is_static()); + EXPECT_TRUE(token_.is_static()); + EXPECT_TRUE(matrix_.is_static()); + EXPECT_TRUE(tuple_.is_static()); + EXPECT_TRUE(nested_tuple_.is_static()); + + Shape dynamic_matrix = matrix_; + EXPECT_TRUE(dynamic_matrix.is_static()); + dynamic_matrix.set_dynamic_dimension(1, true); + EXPECT_FALSE(dynamic_matrix.is_static()); + + Shape dynamic_tuple = tuple_; + EXPECT_TRUE(dynamic_tuple.is_static()); + ShapeUtil::GetMutableSubshape(&dynamic_tuple, {2}) + ->set_dynamic_dimension(1, true); + EXPECT_FALSE(dynamic_tuple.is_static()); +} + +TEST_F(ShapeTest, IsDynamicDimension) { + Shape dynamic_matrix = matrix_; + dynamic_matrix.set_dynamic_dimension(1, true); + EXPECT_FALSE(dynamic_matrix.is_dynamic_dimension(0)); + EXPECT_TRUE(dynamic_matrix.is_dynamic_dimension(1)); + + Shape dynamic_tuple = tuple_; + EXPECT_TRUE(dynamic_tuple.is_static()); + ShapeUtil::GetMutableSubshape(&dynamic_tuple, {2}) + ->set_dynamic_dimension(1, true); + EXPECT_FALSE(dynamic_tuple.is_static()); +} + TEST_F(ShapeTest, ProgramShapeToFromProto) { ProgramShape program_shape; *program_shape.add_parameters() = ShapeUtil::MakeShape(F32, {1, 2, 3}); diff --git a/tensorflow/compiler/xla/shape_util.cc b/tensorflow/compiler/xla/shape_util.cc index cb96ab6fca..7f68c0ae1f 100644 --- a/tensorflow/compiler/xla/shape_util.cc +++ b/tensorflow/compiler/xla/shape_util.cc @@ -144,6 +144,14 @@ bool CompareShapes(const Shape& lhs, const Shape& rhs, bool compare_layouts, VLOG(3) << "CompareShapes: lhs dimensions != rhs dimensions"; return false; } + + for (int i = 0; i < ShapeUtil::Rank(lhs); ++i) { + if (lhs.is_dynamic_dimension(i) != rhs.is_dynamic_dimension(i)) { + VLOG(3) + << "CompareShapes: lhs and rhs have different dynamic dimensions."; + return false; + } + } return true; } @@ -230,6 +238,13 @@ StatusOr MakeShapeWithLayoutInternal( return MakeValidatedShape(element_type, dimensions).ValueOrDie(); } +/* static */ Shape ShapeUtil::MakeShape( + PrimitiveType element_type, absl::Span dimensions, + const std::vector& dynamic_dimensions) { + return MakeValidatedShape(element_type, dimensions, dynamic_dimensions) + .ValueOrDie(); +} + /* static */ StatusOr ShapeUtil::MakeValidatedShape( PrimitiveType element_type, absl::Span dimensions) { CHECK(IsArrayPrimitiveType(element_type)) << element_type; @@ -238,6 +253,17 @@ StatusOr MakeShapeWithLayoutInternal( return result; } +/* static */ StatusOr ShapeUtil::MakeValidatedShape( + PrimitiveType element_type, absl::Span dimensions, + const std::vector& dynamic_dimensions) { + TF_ASSIGN_OR_RETURN(Shape shape, + MakeValidatedShape(element_type, dimensions)); + for (int i = 0; i < dynamic_dimensions.size(); ++i) { + shape.set_dynamic_dimension(i, dynamic_dimensions[i]); + } + return shape; +} + /* static */ Shape ShapeUtil::MakeShapeWithLayout( PrimitiveType element_type, absl::Span dimensions, absl::Span minor_to_major) { @@ -489,9 +515,17 @@ ShapeUtil::MakeShapeWithDescendingLayoutAndSamePhysicalLayout( text += ")"; return text; } + std::vector dim_elements; + for (int i = 0; i < shape.dimensions_size(); ++i) { + if (shape.is_dynamic_dimension(i)) { + dim_elements.push_back(StrCat("<=", shape.dimensions(i))); + } else { + dim_elements.push_back(StrCat(shape.dimensions(i))); + } + } return StrCat( primitive_util::LowercasePrimitiveTypeName(shape.element_type()), "[", - absl::StrJoin(shape.dimensions(), ","), "]"); + absl::StrJoin(dim_elements, ","), "]"); } /* static */ string ShapeUtil::HumanStringWithLayout(const Shape& shape) { @@ -1460,23 +1494,7 @@ ShapeUtil::DimensionsUnmodifiedByReshape(const Shape& input_shape, /* static */ Shape ShapeUtil::DeleteDimension(int64 dim_to_delete, Shape shape) { CHECK(IsArray(shape)); - shape.mutable_dimensions()->erase(shape.mutable_dimensions()->begin() + - dim_to_delete); - if (LayoutUtil::HasLayout(shape)) { - Layout* layout = shape.mutable_layout(); - layout->set_format(DENSE); - for (int64 i = 0; i < layout->minor_to_major().size();) { - if (layout->minor_to_major(i) == dim_to_delete) { - layout->mutable_minor_to_major()->erase( - layout->mutable_minor_to_major()->begin() + i); - continue; - } - if (layout->minor_to_major(i) > dim_to_delete) { - (*layout->mutable_minor_to_major())[i] -= 1; - } - ++i; - } - } + shape.DeleteDimension(dim_to_delete); return shape; } @@ -1502,8 +1520,11 @@ ShapeUtil::DimensionsUnmodifiedByReshape(const Shape& input_shape, size_t hash_value = hash()(shape.element_type()); if (shape.tuple_shapes().empty()) { - for (int64 dim : shape.dimensions()) { - hash_value = Hash64Combine(hash_value, hash()(dim)); + for (int i = 0; i < shape.dimensions_size(); ++i) { + hash_value = + Hash64Combine(hash_value, hash()(shape.dimensions(i))); + hash_value = Hash64Combine(hash_value, + hash()(shape.is_dynamic_dimension(i))); } hash_value = Hash64Combine(hash_value, LayoutUtil::Hash(shape.layout())); diff --git a/tensorflow/compiler/xla/shape_util.h b/tensorflow/compiler/xla/shape_util.h index b28402455f..c8295e85ce 100644 --- a/tensorflow/compiler/xla/shape_util.h +++ b/tensorflow/compiler/xla/shape_util.h @@ -290,7 +290,7 @@ class ShapeUtil { // being F32. Tuple elements are compared recursively for compatibility. static bool CompatibleIgnoringFpPrecision(const Shape& lhs, const Shape& rhs); - // Returns whether the lhs and rhs shapes are identical protobufs. + // Returns whether the lhs and rhs shapes are identical. static bool Equal(const Shape& lhs, const Shape& rhs); // As Equal, but allow one of lhs and rhs to be F16 while the other is F32. @@ -372,11 +372,24 @@ class ShapeUtil { static Shape MakeShape(PrimitiveType element_type, absl::Span dimensions); + // Constructs a new shape with the given element type and sequence of + // potentially dynamic dimensions. The argument 'dynamic_dimensions' indicates + // with a true value that the respective dimension is dynamic. If the + // dimension is dynamic then the respective value in 'dimension' is an upper + // bound on the dimension size. 'dimensions' and 'dynamic_dimensions' must be + // the same size. + static Shape MakeShape(PrimitiveType element_type, + absl::Span dimensions, + const std::vector& dynamic_dimensions); + // Constructs a new shape with the given element type and sequence of // dimensions. Method checks if the element type is valid and the shape's // size fits in std::numeric_limits::max(). static StatusOr MakeValidatedShape(PrimitiveType element_type, absl::Span dimensions); + static StatusOr MakeValidatedShape( + PrimitiveType element_type, absl::Span dimensions, + const std::vector& dynamic_dimensions); // Creates a Shape with element type corresponding to T and the given // dimensions diff --git a/tensorflow/compiler/xla/shape_util_test.cc b/tensorflow/compiler/xla/shape_util_test.cc index 0a3081f516..8e7c208193 100644 --- a/tensorflow/compiler/xla/shape_util_test.cc +++ b/tensorflow/compiler/xla/shape_util_test.cc @@ -176,6 +176,28 @@ TEST(ShapeUtilTest, UnequalIgnoringFpPrecision) { ShapeUtil::MakeShapeWithLayout(PRED, {4, 3}, {0, 1}))); } +TEST(ShapeUtilTest, EqualDynamicShapes) { + EXPECT_TRUE( + ShapeUtil::Equal(ShapeUtil::MakeShape(F32, {4, 3}, {true, false}), + ShapeUtil::MakeShape(F32, {4, 3}, {true, false}))); + EXPECT_FALSE( + ShapeUtil::Equal(ShapeUtil::MakeShape(F32, {4, 3}, {true, false}), + ShapeUtil::MakeShape(F32, {4, 3}, {false, false}))); +} + +TEST(ShapeUtilTest, CompatibleDynamicShapes) { + Shape shape_a = ShapeUtil::MakeShape(F32, {4, 3}, {true, false}); + *shape_a.mutable_layout() = Layout({1, 0}); + Shape shape_b = ShapeUtil::MakeShape(F32, {4, 3}, {true, false}); + *shape_b.mutable_layout() = Layout({0, 1}); + Shape shape_c = ShapeUtil::MakeShape(F32, {4, 3}, {false, true}); + *shape_c.mutable_layout() = Layout({0, 1}); + + EXPECT_TRUE(ShapeUtil::Compatible(shape_a, shape_a)); + EXPECT_TRUE(ShapeUtil::Compatible(shape_a, shape_b)); + EXPECT_FALSE(ShapeUtil::Compatible(shape_a, shape_c)); +} + TEST(ShapeUtilTest, CompatibleTuples) { Shape tuple1 = ShapeUtil::MakeTupleShape( {ShapeUtil::MakeShape(F32, {3, 2}), ShapeUtil::MakeShape(PRED, {4, 5})}); diff --git a/tensorflow/compiler/xla/xla_data.proto b/tensorflow/compiler/xla/xla_data.proto index e9c86abe50..d029669cbe 100644 --- a/tensorflow/compiler/xla/xla_data.proto +++ b/tensorflow/compiler/xla/xla_data.proto @@ -188,11 +188,14 @@ message ShapeProto { // The element type for this shape. PrimitiveType element_type = 2; - // The size (number of elements) for each dimension. - // In XLA, dimensions are numbered from 0 to N-1 for an - // N-dimensional array. The first element of 'dimensions' is the size of - // dimension 0, the second element is the size of dimension 1, and so forth. - // Empty list indicates a scalar. + // The size (number of elements) for each dimension, or an upper bound on the + // size if the dimension is dynamic. In XLA, dimensions are numbered from 0 + // to N-1 for an N-dimensional array. The first element of 'dimensions' is the + // size of dimension 0, the second element is the size of dimension 1, and so + // forth. Empty list indicates a scalar. + // + // If the respective element in 'is_dimension_dynamic' is true then the value + // in this field represents an upper bound on the size of the dimension. repeated int64 dimensions = 3; // For tuples only, the shapes of constitutent shapes in the tuple sequence. @@ -201,6 +204,12 @@ message ShapeProto { // The layout used to back this shape. LayoutProto layout = 5; + // For arrays, this indicates whether or not each dimension is + // dynamically-sized. The number of elements in this repeated field should be + // zero (indicating that no dimensions are dynamic) or equal to the number of + // elements in the 'dimensions' field. + repeated bool is_dynamic_dimension = 6; + // Important: if any field is added, be sure to modify ShapeUtil::Equal(), // ShapeUtil::Compatible() and ShapeUtil::Hash() appropriately to account for // the new field. -- GitLab From 731fd49ddbf5b71bec3fcd4a7e4004e0427cf27c Mon Sep 17 00:00:00 2001 From: Jian Li Date: Thu, 20 Dec 2018 20:40:13 -0800 Subject: [PATCH 0236/1765] Create quantized AveragePool with asymmetric quantization with int8 as input and output. PiperOrigin-RevId: 226436314 --- tensorflow/lite/kernels/internal/BUILD | 1 + .../internal/reference/integer_ops/pooling.h | 83 +++++++++++++++++++ tensorflow/lite/kernels/kernel_util.cc | 10 +++ tensorflow/lite/kernels/kernel_util.h | 3 + tensorflow/lite/kernels/pooling.cc | 38 +++++++-- tensorflow/lite/kernels/pooling_test.cc | 42 ++++++++++ tensorflow/lite/toco/tflite/operator.cc | 5 ++ 7 files changed, 176 insertions(+), 6 deletions(-) create mode 100644 tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h diff --git a/tensorflow/lite/kernels/internal/BUILD b/tensorflow/lite/kernels/internal/BUILD index 442373b5c4..5eb8a353b7 100644 --- a/tensorflow/lite/kernels/internal/BUILD +++ b/tensorflow/lite/kernels/internal/BUILD @@ -314,6 +314,7 @@ cc_library( "reference/depthwiseconv_uint8.h", "reference/fully_connected.h", "reference/integer_ops/dequantize.h", + "reference/integer_ops/pooling.h", "reference/integer_ops/softmax.h", "reference/reference_ops.h", "reference/softmax.h", diff --git a/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h b/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h new file mode 100644 index 0000000000..22750bc91a --- /dev/null +++ b/tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h @@ -0,0 +1,83 @@ +/* Copyright 2018 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_POOLING_H_ +#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_POOLING_H_ + +#include "tensorflow/lite/kernels/internal/common.h" + +namespace tflite { +namespace reference_integer_ops { + +inline void AveragePool(const PoolParams& params, + const RuntimeShape& input_shape, const int8* input_data, + const RuntimeShape& output_shape, int8* output_data) { + TFLITE_DCHECK_LE(params.quantized_activation_min, + params.quantized_activation_max); + TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4); + TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4); + const int batches = MatchingDim(input_shape, 0, output_shape, 0); + const int depth = MatchingDim(input_shape, 3, output_shape, 3); + const int input_height = input_shape.Dims(1); + const int input_width = input_shape.Dims(2); + const int output_height = output_shape.Dims(1); + const int output_width = output_shape.Dims(2); + const int stride_height = params.stride_height; + const int stride_width = params.stride_width; + for (int batch = 0; batch < batches; ++batch) { + for (int out_y = 0; out_y < output_height; ++out_y) { + for (int out_x = 0; out_x < output_width; ++out_x) { + for (int channel = 0; channel < depth; ++channel) { + const int in_x_origin = + (out_x * stride_width) - params.padding_values.width; + const int in_y_origin = + (out_y * stride_height) - params.padding_values.height; + // Compute the boundaries of the filter region clamped so as to + // ensure that the filter window fits in the input array. + const int filter_x_start = std::max(0, -in_x_origin); + const int filter_x_end = + std::min(params.filter_width, input_width - in_x_origin); + const int filter_y_start = std::max(0, -in_y_origin); + const int filter_y_end = + std::min(params.filter_height, input_height - in_y_origin); + int32 acc = 0; + int filter_count = 0; + for (int filter_y = filter_y_start; filter_y < filter_y_end; + ++filter_y) { + for (int filter_x = filter_x_start; filter_x < filter_x_end; + ++filter_x) { + const int in_x = in_x_origin + filter_x; + const int in_y = in_y_origin + filter_y; + acc += + input_data[Offset(input_shape, batch, in_y, in_x, channel)]; + filter_count++; + } + } + // Round to the closest integer value. + acc = acc > 0 ? (acc + filter_count / 2) / filter_count + : (acc - filter_count / 2) / filter_count; + acc = std::max(acc, params.quantized_activation_min); + acc = std::min(acc, params.quantized_activation_max); + output_data[Offset(output_shape, batch, out_y, out_x, channel)] = + static_cast(acc); + } + } + } + } +} + +} // namespace reference_integer_ops +} // namespace tflite + +#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_POOLING_H_ diff --git a/tensorflow/lite/kernels/kernel_util.cc b/tensorflow/lite/kernels/kernel_util.cc index e39890e332..57f4bfa9fa 100644 --- a/tensorflow/lite/kernels/kernel_util.cc +++ b/tensorflow/lite/kernels/kernel_util.cc @@ -103,6 +103,16 @@ void CalculateActivationRangeUint8(TfLiteFusedActivation activation, act_max); } +void CalculateActivationRangeInt8(TfLiteFusedActivation activation, + TfLiteTensor* output, int32_t* act_min, + int32_t* act_max) { + const int32_t qmin = std::numeric_limits::min(); + const int32_t qmax = std::numeric_limits::max(); + + CalculateActivationRangeQuantizedImpl(activation, qmin, qmax, output, act_min, + act_max); +} + bool HaveSameShapes(const TfLiteTensor* input1, const TfLiteTensor* input2) { return TfLiteIntArrayEqual(input1->dims, input2->dims); } diff --git a/tensorflow/lite/kernels/kernel_util.h b/tensorflow/lite/kernels/kernel_util.h index 3cc00588d6..4cfc885f89 100644 --- a/tensorflow/lite/kernels/kernel_util.h +++ b/tensorflow/lite/kernels/kernel_util.h @@ -104,6 +104,9 @@ TfLiteStatus CalculateActivationRangeQuantized(TfLiteContext* context, void CalculateActivationRangeUint8(TfLiteFusedActivation activation, TfLiteTensor* output, int32_t* act_min, int32_t* act_max); +void CalculateActivationRangeInt8(TfLiteFusedActivation activation, + TfLiteTensor* output, int32_t* act_min, + int32_t* act_max); // Calculates the useful range of an activation layer given its activation // tensor.a template diff --git a/tensorflow/lite/kernels/pooling.cc b/tensorflow/lite/kernels/pooling.cc index 694a36ffbc..e6155fcb8c 100644 --- a/tensorflow/lite/kernels/pooling.cc +++ b/tensorflow/lite/kernels/pooling.cc @@ -22,6 +22,7 @@ limitations under the License. #include "tensorflow/lite/c/builtin_op_data.h" #include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/kernels/internal/optimized/optimized_ops.h" +#include "tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h" #include "tensorflow/lite/kernels/internal/reference/reference_ops.h" #include "tensorflow/lite/kernels/internal/tensor.h" #include "tensorflow/lite/kernels/kernel_util.h" @@ -98,7 +99,7 @@ TfLiteStatus GenericPrepare(TfLiteContext* context, TfLiteNode* node) { data->padding.width = ComputePadding(params->stride_width, 1, width, params->filter_width, out_width); - if (input->type == kTfLiteUInt8) { + if (input->type == kTfLiteUInt8 || input->type == kTfLiteInt8) { if (pool_type == kAverage || pool_type == kMax) { TF_LITE_ENSURE_EQ(context, input->params.scale, output->params.scale); TF_LITE_ENSURE_EQ(context, input->params.zero_point, @@ -147,9 +148,10 @@ void AverageEvalFloat(TfLiteContext* context, TfLiteNode* node, } template -void AverageEvalQuantized(TfLiteContext* context, TfLiteNode* node, - TfLitePoolParams* params, OpData* data, - const TfLiteTensor* input, TfLiteTensor* output) { +void AverageEvalQuantizedUint8(TfLiteContext* context, TfLiteNode* node, + TfLitePoolParams* params, OpData* data, + const TfLiteTensor* input, + TfLiteTensor* output) { int32_t activation_min; int32_t activation_max; CalculateActivationRangeUint8(params->activation, output, &activation_min, @@ -175,6 +177,27 @@ void AverageEvalQuantized(TfLiteContext* context, TfLiteNode* node, #undef TF_LITE_AVERAGE_POOL } +void AverageEvalQuantizedInt8(TfLiteContext* context, TfLiteNode* node, + TfLitePoolParams* params, OpData* data, + const TfLiteTensor* input, TfLiteTensor* output) { + int32_t activation_min; + int32_t activation_max; + CalculateActivationRangeInt8(params->activation, output, &activation_min, + &activation_max); + tflite::PoolParams op_params; + op_params.stride_height = params->stride_height; + op_params.stride_width = params->stride_width; + op_params.filter_height = params->filter_height; + op_params.filter_width = params->filter_width; + op_params.padding_values.height = data->padding.height; + op_params.padding_values.width = data->padding.width; + op_params.quantized_activation_min = activation_min; + op_params.quantized_activation_max = activation_max; + reference_integer_ops::AveragePool( + op_params, GetTensorShape(input), GetTensorData(input), + GetTensorShape(output), GetTensorData(output)); +} + template void MaxEvalFloat(TfLiteContext* context, TfLiteNode* node, TfLitePoolParams* params, OpData* data, @@ -272,8 +295,11 @@ TfLiteStatus AverageEval(TfLiteContext* context, TfLiteNode* node) { AverageEvalFloat(context, node, params, data, input, output); break; case kTfLiteUInt8: - AverageEvalQuantized(context, node, params, data, input, - output); + AverageEvalQuantizedUint8(context, node, params, data, input, + output); + break; + case kTfLiteInt8: + AverageEvalQuantizedInt8(context, node, params, data, input, output); break; default: context->ReportError(context, "Type %d not currently supported.", diff --git a/tensorflow/lite/kernels/pooling_test.cc b/tensorflow/lite/kernels/pooling_test.cc index 98777f1c13..e1b7934011 100644 --- a/tensorflow/lite/kernels/pooling_test.cc +++ b/tensorflow/lite/kernels/pooling_test.cc @@ -78,6 +78,25 @@ class QuantizedPoolingOpModel : public BasePoolingOpModel { } }; +class SymmetricQuantizedPoolingOpModel : public BasePoolingOpModel { + public: + using BasePoolingOpModel::BasePoolingOpModel; + + void SetInput(std::initializer_list data) { + QuantizeAndPopulate(input_, data); + } + + void SetInput(const std::vector& data) { + QuantizeAndPopulate(input_, data); + } + + std::vector GetOutput() { return ExtractVector(output_); } + std::vector GetDequantizedOutput() { + return Dequantize(ExtractVector(output_), GetScale(output_), + GetZeroPoint(output_)); + } +}; + TEST(FloatPoolingOpTest, AveragePool) { FloatPoolingOpModel m(BuiltinOperator_AVERAGE_POOL_2D, /*input=*/{TensorType_FLOAT32, {1, 2, 4, 1}}, @@ -128,6 +147,29 @@ TEST(QuantizedPoolingOpTest, AveragePoolImageSize16) { EXPECT_THAT(m.GetDequantizedOutput(), ElementsAreArray(ArrayFloatNear({16}))); } +// Test quantized AveragePool with int8 input and output. The input is the same +// as the uint8 test QuantizedPoolingOpTest.AveragePool. The float output is +// identical to uint8 test and quantized output is identical to uint8 test with +// a 128 shift. +TEST(QuantizedPoolingOpTest, SymmetricAveragePool) { + // Choose the input ranges carefully so that the dequantized output matches + // the results of the float model above. + SymmetricQuantizedPoolingOpModel m( + BuiltinOperator_AVERAGE_POOL_2D, + /*input=*/{TensorType_INT8, {1, 2, 4, 1}, 0, 15.9375}, + /*filter_width=*/2, /*filter_height=*/2, + /*output=*/{TensorType_INT8, {}, 0, 15.9375}); + m.SetInput({ + 0, 6, 2, 4, // + 3, 2, 10, 7, // + }); + m.Invoke(); + + EXPECT_THAT(m.GetDequantizedOutput(), + ElementsAreArray(ArrayFloatNear({2.75, 5.75}))); + EXPECT_THAT(m.GetOutput(), ElementsAreArray({44 - 128, 92 - 128})); +} + // Send in a white image, expect something other than a white pixel, due to // overflow. TEST(QuantizedPoolingOpTest, AveragePoolImageSize17) { diff --git a/tensorflow/lite/toco/tflite/operator.cc b/tensorflow/lite/toco/tflite/operator.cc index 11c8237eb6..63a94fb097 100644 --- a/tensorflow/lite/toco/tflite/operator.cc +++ b/tensorflow/lite/toco/tflite/operator.cc @@ -62,6 +62,11 @@ class AveragePool } int GetVersion(const OperatorSignature& op_signature) const override { + const string& input_name = op_signature.op->inputs[0]; + const Array& input_array = op_signature.model->GetArray(input_name); + if (input_array.data_type == ArrayDataType::kInt8) { + return 2; + } return 1; } }; -- GitLab From bb479118c9fed7be0186f98a3939ec28b162f2fe Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Thu, 20 Dec 2018 21:01:01 -0800 Subject: [PATCH 0237/1765] Workaround for MSVC not merging bit-fields of different size. See issue #24233. PiperOrigin-RevId: 226437696 --- tensorflow/compiler/tf2xla/cpu_function_runtime.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/compiler/tf2xla/cpu_function_runtime.h b/tensorflow/compiler/tf2xla/cpu_function_runtime.h index dfc1e8b8ae..78970fb39b 100644 --- a/tensorflow/compiler/tf2xla/cpu_function_runtime.h +++ b/tensorflow/compiler/tf2xla/cpu_function_runtime.h @@ -104,7 +104,7 @@ class BufferInfo { private: BufferInfo() = default; - enum class Kind : unsigned { + enum class Kind : uint64 { kConstant, kTempBuffer, kEntryParameter, -- GitLab From 79bc4f4bf914d4b94eef89e8df2e19ff54c2db71 Mon Sep 17 00:00:00 2001 From: Siju Samuel Date: Fri, 21 Dec 2018 10:31:19 +0530 Subject: [PATCH 0238/1765] Review comments updated, nnapi removed for ceil --- .../lite/delegates/nnapi/nnapi_delegate.cc | 10 ---- .../delegates/nnapi/nnapi_delegate_test.cc | 49 ------------------- tensorflow/lite/kernels/BUILD | 1 - .../internal/optimized/legacy_optimized_ops.h | 6 --- .../internal/reference/legacy_reference_ops.h | 6 --- tensorflow/lite/nnapi/NeuralNetworksShim.h | 1 - tensorflow/lite/nnapi_delegate.cc | 3 -- 7 files changed, 76 deletions(-) diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc index cac98ae3da..4fe07004a8 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate.cc @@ -638,16 +638,6 @@ class NNAPIDelegateKernel { return nullptr; } break; - case kTfLiteBuiltinCeil: - if (version == 1) { - return [](const NNAPIOpMappingArgs& mapping_args) - -> ANeuralNetworksOperationType { - return ANEURALNETWORKS_CEIL; - }; - } else { - return nullptr; - } - break; case kTfLiteBuiltinRelu: if (version == 1) { return [](const NNAPIOpMappingArgs& mapping_args) diff --git a/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc b/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc index f6a04e36cd..ca48af0c95 100644 --- a/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc +++ b/tensorflow/lite/delegates/nnapi/nnapi_delegate_test.cc @@ -1024,55 +1024,6 @@ TEST(NNAPIDelegate, FloorMultiDims) { EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); } -class CeilOpModel : public SingleOpModelWithNNAPI { - public: - CeilOpModel(std::initializer_list input_shape, TensorType input_type) { - input_ = AddInput(TensorType_FLOAT32); - output_ = AddOutput(TensorType_FLOAT32); - SetBuiltinOp(BuiltinOperator_CEIL, BuiltinOptions_NONE, 0); - BuildInterpreter({ - input_shape, - }); - } - - int input() { return input_; } - - std::vector GetOutput() { return ExtractVector(output_); } - std::vector GetOutputShape() { return GetTensorShape(output_); } - - private: - int input_; - int output_; -}; - -TEST(NNAPIDelegate, CeilSingleDim) { - CeilOpModel model({2}, TensorType_FLOAT32); - model.PopulateTensor(model.input(), {8.5, 0.0}); - model.Invoke(); - EXPECT_THAT(model.GetOutput(), ElementsAreArray({8, 0})); - EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2})); -} - -TEST(NNAPIDelegate, CeilMultiDims) { - CeilOpModel model({2, 1, 1, 5}, TensorType_FLOAT32); - model.PopulateTensor(model.input(), { - 0.0001, - 8.0001, - 0.9999, - 9.9999, - 0.5, - -0.0001, - -8.0001, - -0.9999, - -9.9999, - -0.5, - }); - model.Invoke(); - EXPECT_THAT(model.GetOutput(), - ElementsAreArray({1, 9, 1, 10, 1, 0, -8, 0, -9, 0})); - EXPECT_THAT(model.GetOutputShape(), ElementsAreArray({2, 1, 1, 5})); -} - class LocalResponseNormOpModel : public SingleOpModelWithNNAPI { public: LocalResponseNormOpModel(std::initializer_list input_shape, int radius, diff --git a/tensorflow/lite/kernels/BUILD b/tensorflow/lite/kernels/BUILD index 71d06ba4d7..1d53022e03 100644 --- a/tensorflow/lite/kernels/BUILD +++ b/tensorflow/lite/kernels/BUILD @@ -605,7 +605,6 @@ tf_cc_test( size = "small", srcs = ["ceil_test.cc"], tags = [ - "no_oss", "tflite_not_portable_ios", ], deps = [ diff --git a/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h index a76649f934..5485d907c2 100644 --- a/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h +++ b/tensorflow/lite/kernels/internal/optimized/legacy_optimized_ops.h @@ -1740,12 +1740,6 @@ inline void Floor(const float* input_data, const Dims<4>& input_dims, output_data); } -inline void Ceil(const float* input_data, const Dims<4>& input_dims, - float* output_data, const Dims<4>& output_dims) { - Ceil(DimsToShape(input_dims), input_data, DimsToShape(output_dims), - output_data); -} - inline void ResizeBilinear(const float* input_data, const Dims<4>& input_dims, const int32* output_size_data, const Dims<4>& output_size_dims, float* output_data, diff --git a/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h b/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h index 431e2413e8..380fc8f98e 100644 --- a/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h +++ b/tensorflow/lite/kernels/internal/reference/legacy_reference_ops.h @@ -1883,12 +1883,6 @@ inline void Floor(const float* input_data, const Dims<4>& input_dims, output_data); } -inline void Ceil(const float* input_data, const Dims<4>& input_dims, - float* output_data, const Dims<4>& output_dims) { - Ceil(DimsToShape(input_dims), input_data, DimsToShape(output_dims), - output_data); -} - template inline void ResizeBilinear(const T* input_data, const Dims<4>& input_dims, const int32* output_size_data, diff --git a/tensorflow/lite/nnapi/NeuralNetworksShim.h b/tensorflow/lite/nnapi/NeuralNetworksShim.h index 82c5840952..c39502f4ac 100644 --- a/tensorflow/lite/nnapi/NeuralNetworksShim.h +++ b/tensorflow/lite/nnapi/NeuralNetworksShim.h @@ -143,7 +143,6 @@ enum { ANEURALNETWORKS_STRIDED_SLICE = 35, ANEURALNETWORKS_SUB = 36, ANEURALNETWORKS_TRANSPOSE = 37, - ANEURALNETWORKS_CEIL = 38, }; /** diff --git a/tensorflow/lite/nnapi_delegate.cc b/tensorflow/lite/nnapi_delegate.cc index dfbb4813ad..26d75696a1 100644 --- a/tensorflow/lite/nnapi_delegate.cc +++ b/tensorflow/lite/nnapi_delegate.cc @@ -489,9 +489,6 @@ TfLiteStatus AddOpsAndParams( case tflite::BuiltinOperator_FLOOR: nn_op_type = ANEURALNETWORKS_FLOOR; break; - case tflite::BuiltinOperator_CEIL: - nn_op_type = ANEURALNETWORKS_CEIL; - break; case tflite::BuiltinOperator_LOGISTIC: nn_op_type = ANEURALNETWORKS_LOGISTIC; break; -- GitLab From d4ddccd3cca4fc837c66ae1dfa190739420ad122 Mon Sep 17 00:00:00 2001 From: Suharsh Sivakumar Date: Thu, 20 Dec 2018 21:33:42 -0800 Subject: [PATCH 0239/1765] SVDF Hybrid op INT8 support. PiperOrigin-RevId: 226440102 --- tensorflow/lite/kernels/register.cc | 4 +- tensorflow/lite/kernels/svdf.cc | 41 +++++++---- tensorflow/lite/kernels/svdf_test.cc | 94 ++++++++++++++++++++++--- tensorflow/lite/toco/tflite/operator.cc | 14 ++++ 4 files changed, 131 insertions(+), 22 deletions(-) diff --git a/tensorflow/lite/kernels/register.cc b/tensorflow/lite/kernels/register.cc index f6cfb96df0..fae303f016 100644 --- a/tensorflow/lite/kernels/register.cc +++ b/tensorflow/lite/kernels/register.cc @@ -173,7 +173,9 @@ BuiltinOpResolver::BuiltinOpResolver() { AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D(), /* min_version */ 1, /* max_version */ 3); - AddBuiltin(BuiltinOperator_SVDF, Register_SVDF()); + AddBuiltin(BuiltinOperator_SVDF, Register_SVDF(), + /* min_version */ 1, + /* max_version */ 2); AddBuiltin(BuiltinOperator_RNN, Register_RNN(), /* min_version */ 1, /* max_version */ 2); diff --git a/tensorflow/lite/kernels/svdf.cc b/tensorflow/lite/kernels/svdf.cc index f07937140e..d8fc7ce1ce 100644 --- a/tensorflow/lite/kernels/svdf.cc +++ b/tensorflow/lite/kernels/svdf.cc @@ -176,8 +176,9 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { context->ResizeTensor(context, output, output_size_array)); // The weights are of consistent type, so it suffices to check one. - const bool is_hybrid_op = - (input->type == kTfLiteFloat32 && weights_feature->type == kTfLiteUInt8); + const bool is_hybrid_op = (input->type == kTfLiteFloat32 && + (weights_feature->type == kTfLiteUInt8 || + weights_feature->type == kTfLiteInt8)); // Resize scratch. TfLiteIntArrayFree(node->temporaries); @@ -203,7 +204,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { // of input tensors. node->temporaries->data[1] = scratch_tensor_index + 1; TfLiteTensor* input_quantized = GetTemporary(context, node, /*index=*/1); - input_quantized->type = kTfLiteUInt8; + input_quantized->type = weights_feature->type; input_quantized->allocation_type = kTfLiteArenaRw; if (!TfLiteIntArrayEqual(input_quantized->dims, input->dims)) { TfLiteIntArray* input_quantized_size = TfLiteIntArrayCopy(input->dims); @@ -297,16 +298,24 @@ TfLiteStatus EvalHybrid( // Initialize the pointer to input. const float* input_ptr_batch = input->data.f; - // Initialize the pointer to storage for quantized values and - // scaling factors. - int8_t* quantized_input_ptr_batch = - reinterpret_cast(input_quantized->data.uint8); + // Initialize the pointer to storage for quantized values and the weights + // feature. + int8_t* quantized_input_ptr_batch; + const int8_t* weights_feature_ptr; + if (weights_feature->type == kTfLiteUInt8) { + quantized_input_ptr_batch = + reinterpret_cast(input_quantized->data.uint8); + weights_feature_ptr = + reinterpret_cast(weights_feature->data.uint8); + } else { + quantized_input_ptr_batch = input_quantized->data.int8; + weights_feature_ptr = weights_feature->data.int8; + } + // Initialize the pointer to storage for scaling factors. float* scaling_factors_ptr = scaling_factors->data.f; - // Other initializations. - const int8_t* weights_feature_ptr = - reinterpret_cast(weights_feature->data.uint8); + // Initialize the weights scale. const float weights_feature_scale = weights_feature->params.scale; // Clear the activation (state left most column). @@ -374,7 +383,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { bias, params, scratch, activation_state, output); break; } - case kTfLiteUInt8: { + case kTfLiteUInt8: + case kTfLiteInt8: { TfLiteTensor* input_quantized = GetTemporary(context, node, /*index=*/1); TfLiteTensor* scaling_factors = GetTemporary(context, node, /*index=*/2); TfLiteTensor* float_weights_time = @@ -388,8 +398,13 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { // TODO(alanchiao): refactor logic out into dequantize function. if (!op_data->float_weights_time_initialized) { const float dequantization_scale = weights_time->params.scale; - const int8_t* weights_time_ptr = - reinterpret_cast(weights_time->data.uint8); + const int8_t* weights_time_ptr; + if (weights_feature->type == kTfLiteUInt8) { + weights_time_ptr = + reinterpret_cast(weights_time->data.uint8); + } else { + weights_time_ptr = weights_time->data.int8; + } for (int i = 0; i < NumElements(float_weights_time); ++i) { float_weights_time->data.f[i] = weights_time_ptr[i] * dequantization_scale; diff --git a/tensorflow/lite/kernels/svdf_test.cc b/tensorflow/lite/kernels/svdf_test.cc index 8accaa465c..fc2bb49223 100644 --- a/tensorflow/lite/kernels/svdf_test.cc +++ b/tensorflow/lite/kernels/svdf_test.cc @@ -203,17 +203,30 @@ class SVDFOpModel : public BaseSVDFOpModel { class HybridSVDFOpModel : public BaseSVDFOpModel { public: HybridSVDFOpModel(int batches, int units, int input_size, int memory_size, - int rank) + int rank, TensorType tensor_type) : BaseSVDFOpModel(batches, units, input_size, memory_size, rank, - TensorType_UINT8, TensorType_UINT8) {} + tensor_type, tensor_type) { + tensor_type_ = tensor_type; + } + + void SetWeights(int weights_idx, std::vector f) { + if (tensor_type_ == TensorType_UINT8) { + SymmetricQuantizeAndPopulate(weights_idx, f); + } else { + SignedSymmetricQuantizeAndPopulate(weights_idx, f); + } + } void SetWeightsFeature(std::initializer_list f) { - SymmetricQuantizeAndPopulate(weights_feature_, f); + SetWeights(weights_feature_, f); } void SetWeightsTime(std::initializer_list f) { - SymmetricQuantizeAndPopulate(weights_time_, f); + SetWeights(weights_time_, f); } + + protected: + TensorType tensor_type_; }; class SVDFOpTest : public ::testing::Test { @@ -312,9 +325,74 @@ TEST_F(SVDFOpTest, BlackBoxTestRank2) { &svdf); } -TEST_F(SVDFOpTest, BlackBoxTestHybridRank1) { +TEST_F(SVDFOpTest, BlackBoxTestHybridRank1Uint8) { + HybridSVDFOpModel svdf(/*batches=*/2, /*units=*/4, /*input_size=*/3, + /*memory_size=*/10, /*rank=*/1, TensorType_UINT8); + svdf.SetWeightsFeature({-0.31930989, -0.36118156, 0.0079667, 0.37613347, + 0.22197971, 0.12416199, 0.27901134, 0.27557442, + 0.3905206, -0.36137494, -0.06634006, -0.10640851}); + + svdf.SetWeightsTime( + {-0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156, + 0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199, + + 0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518, + -0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296, + + -0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236, + 0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846, + + -0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166, + -0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657}); + + VerifyGoldens(svdf_input, svdf_golden_output_rank_1, sizeof(svdf_input), + &svdf, + /*tolerance=*/0.002945); +} + +TEST_F(SVDFOpTest, BlackBoxTestHybridRank2Uint8) { + HybridSVDFOpModel svdf(/*batches=*/2, /*units=*/4, /*input_size=*/3, + /*memory_size=*/10, /*rank=*/2, TensorType_UINT8); + svdf.SetWeightsFeature({-0.31930989, 0.0079667, 0.39296314, 0.37613347, + 0.12416199, 0.15785322, 0.27901134, 0.3905206, + 0.21931258, -0.36137494, -0.10640851, 0.31053296, + -0.36118156, -0.0976817, -0.36916667, 0.22197971, + 0.15294972, 0.38031587, 0.27557442, 0.39635518, + -0.21580373, -0.06634006, -0.02702999, 0.27072677}); + + svdf.SetWeightsTime( + {-0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156, + 0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199, + + 0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518, + -0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296, + + -0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236, + 0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846, + + -0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166, + -0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657, + + -0.14884081, 0.19931212, -0.36002168, 0.34663299, -0.11405486, + 0.12672701, 0.39463779, -0.07886535, -0.06384811, 0.08249187, + + -0.26816407, -0.19905911, 0.29211238, 0.31264046, -0.28664589, + 0.05698794, 0.11613581, 0.14078894, 0.02187902, -0.21781836, + + -0.15567942, 0.08693647, -0.38256618, 0.36580828, -0.22922277, + -0.0226903, 0.12878349, -0.28122205, -0.10850525, -0.11955214, + + 0.27179423, -0.04710215, 0.31069002, 0.22672787, 0.09580326, + 0.08682203, 0.1258215, 0.1851041, 0.29228821, 0.12366763}); + + VerifyGoldens(svdf_input, svdf_golden_output_rank_2, sizeof(svdf_input), + &svdf, + /*tolerance=*/0.00625109); +} + +TEST_F(SVDFOpTest, BlackBoxTestHybridRank1Int8) { HybridSVDFOpModel svdf(/*batches=*/2, /*units=*/4, /*input_size=*/3, - /*memory_size=*/10, /*rank=*/1); + /*memory_size=*/10, /*rank=*/1, TensorType_INT8); svdf.SetWeightsFeature({-0.31930989, -0.36118156, 0.0079667, 0.37613347, 0.22197971, 0.12416199, 0.27901134, 0.27557442, 0.3905206, -0.36137494, -0.06634006, -0.10640851}); @@ -337,9 +415,9 @@ TEST_F(SVDFOpTest, BlackBoxTestHybridRank1) { /*tolerance=*/0.002945); } -TEST_F(SVDFOpTest, BlackBoxTestHybridRank2) { +TEST_F(SVDFOpTest, BlackBoxTestHybridRank2Int8) { HybridSVDFOpModel svdf(/*batches=*/2, /*units=*/4, /*input_size=*/3, - /*memory_size=*/10, /*rank=*/2); + /*memory_size=*/10, /*rank=*/2, TensorType_INT8); svdf.SetWeightsFeature({-0.31930989, 0.0079667, 0.39296314, 0.37613347, 0.12416199, 0.15785322, 0.27901134, 0.3905206, 0.21931258, -0.36137494, -0.10640851, 0.31053296, diff --git a/tensorflow/lite/toco/tflite/operator.cc b/tensorflow/lite/toco/tflite/operator.cc index 63a94fb097..0d5cff7bfa 100644 --- a/tensorflow/lite/toco/tflite/operator.cc +++ b/tensorflow/lite/toco/tflite/operator.cc @@ -472,6 +472,20 @@ class Svdf : public BuiltinOperatorinputs[0]; + const string& weights_feature_name = op_signature.op->inputs[1]; + const string& output_name = op_signature.op->outputs[0]; + const Array& input_array = op_signature.model->GetArray(input_name); + const Array& weights_feature_array = + op_signature.model->GetArray(weights_feature_name); + const Array& output_array = op_signature.model->GetArray(output_name); + // If the op is a signed int8 hybrid operation, we need to return + // version 2. + if (input_array.data_type == ArrayDataType::kFloat && + weights_feature_array.data_type == ArrayDataType::kInt8 && + output_array.data_type == ArrayDataType::kFloat) { + return 2; + } return 1; } }; -- GitLab From f5f4c2f862744efbb93945b3fe7159bb18bbd520 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 01:02:39 -0800 Subject: [PATCH 0240/1765] compat: Update forward compatibility horizon to 2018-12-21 PiperOrigin-RevId: 226453620 --- tensorflow/python/compat/compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/python/compat/compat.py b/tensorflow/python/compat/compat.py index 216e27e85f..4a0d2d93f7 100644 --- a/tensorflow/python/compat/compat.py +++ b/tensorflow/python/compat/compat.py @@ -32,7 +32,7 @@ from tensorflow.python.ops import variable_scope from tensorflow.python.util import tf_contextlib from tensorflow.python.util.tf_export import tf_export -_FORWARD_COMPATIBILITY_HORIZON = datetime.date(2018, 12, 20) +_FORWARD_COMPATIBILITY_HORIZON = datetime.date(2018, 12, 21) @tf_export("compat.forward_compatible") -- GitLab From 69803fb6f8d142c1d78b1c423a53ee797444fdf1 Mon Sep 17 00:00:00 2001 From: Suharsh Sivakumar Date: Fri, 21 Dec 2018 01:15:22 -0800 Subject: [PATCH 0241/1765] LSTM hybrid op int8 support. Also correct mistaken version bump of DepthwiseConv and bump FC instead. PiperOrigin-RevId: 226455479 --- tensorflow/lite/kernels/lstm.cc | 12 +- tensorflow/lite/kernels/lstm_eval.cc | 53 ++- tensorflow/lite/kernels/lstm_test.cc | 477 ++++++++++++++++++++++-- tensorflow/lite/kernels/register.cc | 6 +- tensorflow/lite/toco/tflite/operator.cc | 17 +- 5 files changed, 498 insertions(+), 67 deletions(-) diff --git a/tensorflow/lite/kernels/lstm.cc b/tensorflow/lite/kernels/lstm.cc index 3689d77b01..470c74d207 100644 --- a/tensorflow/lite/kernels/lstm.cc +++ b/tensorflow/lite/kernels/lstm.cc @@ -382,7 +382,8 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { // The weights are of consistent type, so it suffices to check one. // TODO(mirkov): create a utility/macro for this check, so all Ops can use it. - const bool is_hybrid_op = (input_to_output_weights->type == kTfLiteUInt8 && + const bool is_hybrid_op = ((input_to_output_weights->type == kTfLiteUInt8 || + input_to_output_weights->type == kTfLiteInt8) && input->type == kTfLiteFloat32); TfLiteIntArrayFree(node->temporaries); @@ -418,7 +419,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { // activation_state and cell_state tensors. node->temporaries->data[1] = op_data->scratch_tensor_index + 1; TfLiteTensor* input_quantized = GetTemporary(context, node, /*index=*/1); - input_quantized->type = kTfLiteUInt8; + input_quantized->type = input_to_output_weights->type; input_quantized->allocation_type = kTfLiteArenaRw; if (!TfLiteIntArrayEqual(input_quantized->dims, input->dims)) { TfLiteIntArray* input_quantized_size = TfLiteIntArrayCopy(input->dims); @@ -428,7 +429,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { node->temporaries->data[2] = op_data->scratch_tensor_index + 2; TfLiteTensor* activation_state_quantized = GetTemporary(context, node, /*index=*/2); - activation_state_quantized->type = kTfLiteUInt8; + activation_state_quantized->type = input_to_output_weights->type; activation_state_quantized->allocation_type = kTfLiteArenaRw; if (!TfLiteIntArrayEqual(activation_state_quantized->dims, activation_state->dims)) { @@ -441,7 +442,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) { node->temporaries->data[3] = op_data->scratch_tensor_index + 3; TfLiteTensor* cell_state_quantized = GetTemporary(context, node, /*index=*/3); - cell_state_quantized->type = kTfLiteUInt8; + cell_state_quantized->type = input_to_output_weights->type; cell_state_quantized->allocation_type = kTfLiteArenaRw; if (!TfLiteIntArrayEqual(cell_state_quantized->dims, cell_state->dims)) { TfLiteIntArray* cell_state_quantized_size = @@ -595,7 +596,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { /*output_offset=*/0, scratch_buffer, activation_state, cell_state, output); } - case kTfLiteUInt8: { + case kTfLiteUInt8: + case kTfLiteInt8: { TfLiteTensor* input_quantized = GetTemporary(context, node, /*index=*/1); TfLiteTensor* activation_state_quantized = GetTemporary(context, node, /*index=*/2); diff --git a/tensorflow/lite/kernels/lstm_eval.cc b/tensorflow/lite/kernels/lstm_eval.cc index 6ba1e19343..dbc50b7872 100644 --- a/tensorflow/lite/kernels/lstm_eval.cc +++ b/tensorflow/lite/kernels/lstm_eval.cc @@ -16,6 +16,7 @@ limitations under the License. #include +#include "tensorflow/lite/c/c_api_internal.h" #include "tensorflow/lite/kernels/internal/kernel_utils.h" #include "tensorflow/lite/kernels/internal/tensor_utils.h" #include "tensorflow/lite/kernels/op_macros.h" @@ -805,6 +806,15 @@ inline void LstmStepWithAuxInput( } } } + +int8_t* GetInt8DataPtr(const TfLiteTensor* tensor, const bool is_uint8) { + if (is_uint8) { + return reinterpret_cast(tensor->data.uint8); + } else { + return tensor->data.int8; + } +} + } // namespace TfLiteStatus EvalFloat( @@ -1036,6 +1046,9 @@ TfLiteStatus EvalHybrid( TfLiteTensor* aux_input_quantized, TfLiteTensor* output_state_quantized, TfLiteTensor* cell_state_quantized, TfLiteTensor* output_state, TfLiteTensor* cell_state, TfLiteTensor* output) { + // For operations that use int8 instead of uint8 we need to fetch raw data + // from the tensor different. We use this bool for that condition. + const bool is_uint8_hybrid = input_to_output_weights->type == kTfLiteUInt8; TF_LITE_ASSERT(input->dims->size >= 2 && input->dims->size <= 3); const int n_input = input->dims->data[input->dims->size - 1]; int max_time, n_batch; @@ -1081,9 +1094,9 @@ TfLiteStatus EvalHybrid( float* input_gate_bias_ptr = nullptr; if (!use_cifg) { input_to_input_weights_ptr = - reinterpret_cast(input_to_input_weights->data.uint8); + GetInt8DataPtr(input_to_input_weights, is_uint8_hybrid); recurrent_to_input_weights_ptr = - reinterpret_cast(recurrent_to_input_weights->data.uint8); + GetInt8DataPtr(recurrent_to_input_weights, is_uint8_hybrid); input_gate_bias_ptr = input_gate_bias->data.f; input_to_input_weights_scale = input_to_input_weights->params.scale; recurrent_to_input_weights_scale = recurrent_to_input_weights->params.scale; @@ -1098,13 +1111,13 @@ TfLiteStatus EvalHybrid( if (use_peephole) { if (!use_cifg) { cell_to_input_weights_ptr = - reinterpret_cast(cell_to_input_weights->data.uint8); + GetInt8DataPtr(cell_to_input_weights, is_uint8_hybrid); cell_to_input_weights_scale = cell_to_input_weights->params.scale; } cell_to_forget_weights_ptr = - reinterpret_cast(cell_to_forget_weights->data.uint8); + GetInt8DataPtr(cell_to_forget_weights, is_uint8_hybrid); cell_to_output_weights_ptr = - reinterpret_cast(cell_to_output_weights->data.uint8); + GetInt8DataPtr(cell_to_output_weights, is_uint8_hybrid); cell_to_forget_weights_scale = cell_to_forget_weights->params.scale; cell_to_output_weights_scale = cell_to_output_weights->params.scale; } @@ -1122,7 +1135,7 @@ TfLiteStatus EvalHybrid( const int8_t* projection_weights_ptr = (projection_weights == nullptr) ? nullptr - : reinterpret_cast(projection_weights->data.uint8); + : GetInt8DataPtr(projection_weights, is_uint8_hybrid); const float projection_weights_scale = (projection_weights == nullptr) ? 1.0f : projection_weights->params.scale; const float* projection_bias_ptr = @@ -1130,26 +1143,26 @@ TfLiteStatus EvalHybrid( // Required tensors, pointers are non-null. const int8_t* input_to_forget_weights_ptr = - reinterpret_cast(input_to_forget_weights->data.uint8); + GetInt8DataPtr(input_to_forget_weights, is_uint8_hybrid); const float input_to_forget_weights_scale = input_to_forget_weights->params.scale; const int8_t* input_to_cell_weights_ptr = - reinterpret_cast(input_to_cell_weights->data.uint8); + GetInt8DataPtr(input_to_cell_weights, is_uint8_hybrid); const float input_to_cell_weights_scale = input_to_cell_weights->params.scale; const int8_t* input_to_output_weights_ptr = - reinterpret_cast(input_to_output_weights->data.uint8); + GetInt8DataPtr(input_to_output_weights, is_uint8_hybrid); const float input_to_output_weights_scale = input_to_output_weights->params.scale; const int8_t* recurrent_to_forget_weights_ptr = - reinterpret_cast(recurrent_to_forget_weights->data.uint8); + GetInt8DataPtr(recurrent_to_forget_weights, is_uint8_hybrid); const float recurrent_to_forget_weights_scale = recurrent_to_forget_weights->params.scale; const int8_t* recurrent_to_cell_weights_ptr = - reinterpret_cast(recurrent_to_cell_weights->data.uint8); + GetInt8DataPtr(recurrent_to_cell_weights, is_uint8_hybrid); const float recurrent_to_cell_weights_scale = recurrent_to_cell_weights->params.scale; const int8_t* recurrent_to_output_weights_ptr = - reinterpret_cast(recurrent_to_output_weights->data.uint8); + GetInt8DataPtr(recurrent_to_output_weights, is_uint8_hybrid); const float recurrent_to_output_weights_scale = recurrent_to_output_weights->params.scale; const float* forget_gate_bias_ptr = forget_gate_bias->data.f; @@ -1158,15 +1171,15 @@ TfLiteStatus EvalHybrid( // Temporary storage for quantized values and scaling factors. int8_t* quantized_input_ptr = - reinterpret_cast(input_quantized->data.uint8); + GetInt8DataPtr(input_quantized, is_uint8_hybrid); int8_t* quantized_aux_input_ptr = (aux_input_quantized == nullptr) ? nullptr - : reinterpret_cast(aux_input_quantized->data.uint8); + : GetInt8DataPtr(aux_input_quantized, is_uint8_hybrid); int8_t* quantized_output_state_ptr = - reinterpret_cast(output_state_quantized->data.uint8); + GetInt8DataPtr(output_state_quantized, is_uint8_hybrid); int8_t* quantized_cell_state_ptr = - reinterpret_cast(cell_state_quantized->data.uint8); + GetInt8DataPtr(cell_state_quantized, is_uint8_hybrid); float* scaling_factors_ptr = scaling_factors->data.f; float* prod_scaling_factors_ptr = prod_scaling_factors->data.f; float* recovered_cell_weights_ptr = recovered_cell_weights->data.f; @@ -1184,14 +1197,14 @@ TfLiteStatus EvalHybrid( if (aux_input_size > 0) { if (!use_cifg) { aux_input_to_input_weights_ptr = - reinterpret_cast(aux_input_to_input_weights->data.uint8); + GetInt8DataPtr(aux_input_to_input_weights, is_uint8_hybrid); } aux_input_to_forget_weights_ptr = - reinterpret_cast(aux_input_to_forget_weights->data.uint8); + GetInt8DataPtr(aux_input_to_forget_weights, is_uint8_hybrid); aux_input_to_cell_weights_ptr = - reinterpret_cast(aux_input_to_cell_weights->data.uint8); + GetInt8DataPtr(aux_input_to_cell_weights, is_uint8_hybrid); aux_input_to_output_weights_ptr = - reinterpret_cast(aux_input_to_output_weights->data.uint8); + GetInt8DataPtr(aux_input_to_output_weights, is_uint8_hybrid); if (!use_cifg) { aux_input_to_input_weights_scale = aux_input_to_input_weights->params.scale; diff --git a/tensorflow/lite/kernels/lstm_test.cc b/tensorflow/lite/kernels/lstm_test.cc index fea95aacb1..09ce440276 100644 --- a/tensorflow/lite/kernels/lstm_test.cc +++ b/tensorflow/lite/kernels/lstm_test.cc @@ -270,57 +270,70 @@ class HybridLSTMOpModel : public LSTMOpModel { bool use_cifg, bool use_peephole, bool use_projection_weights, bool use_projection_bias, float cell_clip, float proj_clip, - const std::vector>& input_shapes) + const std::vector>& input_shapes, + TensorType tensor_type) : LSTMOpModel(n_batch, n_input, n_cell, n_output, use_cifg, use_peephole, use_projection_weights, use_projection_bias, cell_clip, - proj_clip, input_shapes, TensorType_UINT8) {} + proj_clip, input_shapes, tensor_type) { + tensor_type_ = tensor_type; + } + + TensorType tensor_type_; + + void SetWeights(int weights_idx, std::vector f) { + if (tensor_type_ == TensorType_UINT8) { + SymmetricQuantizeAndPopulate(weights_idx, f); + } else { + SignedSymmetricQuantizeAndPopulate(weights_idx, f); + } + } void SetInputToInputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(input_to_input_weights_, f); + SetWeights(input_to_input_weights_, f); } void SetInputToForgetWeights(std::vector f) { - SymmetricQuantizeAndPopulate(input_to_forget_weights_, f); + SetWeights(input_to_forget_weights_, f); } void SetInputToCellWeights(std::vector f) { - SymmetricQuantizeAndPopulate(input_to_cell_weights_, f); + SetWeights(input_to_cell_weights_, f); } void SetInputToOutputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(input_to_output_weights_, f); + SetWeights(input_to_output_weights_, f); } void SetRecurrentToInputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(recurrent_to_input_weights_, f); + SetWeights(recurrent_to_input_weights_, f); } void SetRecurrentToForgetWeights(std::vector f) { - SymmetricQuantizeAndPopulate(recurrent_to_forget_weights_, f); + SetWeights(recurrent_to_forget_weights_, f); } void SetRecurrentToCellWeights(std::vector f) { - SymmetricQuantizeAndPopulate(recurrent_to_cell_weights_, f); + SetWeights(recurrent_to_cell_weights_, f); } void SetRecurrentToOutputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(recurrent_to_output_weights_, f); + SetWeights(recurrent_to_output_weights_, f); } void SetCellToInputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(cell_to_input_weights_, f); + SetWeights(cell_to_input_weights_, f); } void SetCellToForgetWeights(std::vector f) { - SymmetricQuantizeAndPopulate(cell_to_forget_weights_, f); + SetWeights(cell_to_forget_weights_, f); } void SetCellToOutputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(cell_to_output_weights_, f); + SetWeights(cell_to_output_weights_, f); } void SetProjectionWeights(std::vector f) { - SymmetricQuantizeAndPopulate(projection_weights_, f); + SetWeights(projection_weights_, f); } }; @@ -487,7 +500,8 @@ TEST_F(NoCifgNoPeepholeNoProjectionNoClippingLstmTest, LstmBlackBoxTest) { VerifyGoldens(lstm_input_, lstm_golden_output_, &lstm); } -TEST_F(NoCifgNoPeepholeNoProjectionNoClippingLstmTest, HybridLstmBlackBoxTest) { +TEST_F(NoCifgNoPeepholeNoProjectionNoClippingLstmTest, + HybridLstmBlackBoxTestUint8) { const int n_batch = 1; const int n_input = 2; // n_cell and n_output have the same size when there is no projection. @@ -523,7 +537,67 @@ TEST_F(NoCifgNoPeepholeNoProjectionNoClippingLstmTest, HybridLstmBlackBoxTest) { {0, 0}, // projection_weight tensor {0}, // projection_bias tensor - }); + }, + TensorType_UINT8); + + lstm.SetInputToInputWeights(input_to_input_weights_); + lstm.SetInputToCellWeights(input_to_cell_weights_); + lstm.SetInputToForgetWeights(input_to_forget_weights_); + lstm.SetInputToOutputWeights(input_to_output_weights_); + + lstm.SetInputGateBias(input_gate_bias_); + lstm.SetCellBias(cell_gate_bias_); + lstm.SetForgetGateBias(forget_gate_bias_); + lstm.SetOutputGateBias(output_gate_bias_); + + lstm.SetRecurrentToInputWeights(recurrent_to_input_weights_); + lstm.SetRecurrentToCellWeights(recurrent_to_cell_weights_); + lstm.SetRecurrentToForgetWeights(recurrent_to_forget_weights_); + lstm.SetRecurrentToOutputWeights(recurrent_to_output_weights_); + + VerifyGoldens(lstm_input_, lstm_golden_output_, &lstm, + /*tolerance=*/0.0157651); +} + +TEST_F(NoCifgNoPeepholeNoProjectionNoClippingLstmTest, + HybridLstmBlackBoxTestInt8) { + const int n_batch = 1; + const int n_input = 2; + // n_cell and n_output have the same size when there is no projection. + const int n_cell = 4; + const int n_output = 4; + + HybridLSTMOpModel lstm( + n_batch, n_input, n_cell, n_output, + /*use_cifg=*/false, /*use_peephole=*/false, + /*use_projection_weights=*/false, + /*use_projection_bias=*/false, /*cell_clip=*/0.0, /*proj_clip=*/0.0, + { + {n_batch, n_input}, // input tensor + + {n_cell, n_input}, // input_to_input_weight tensor + {n_cell, n_input}, // input_to_forget_weight tensor + {n_cell, n_input}, // input_to_cell_weight tensor + {n_cell, n_input}, // input_to_output_weight tensor + + {n_cell, n_output}, // recurrent_to_input_weight tensor + {n_cell, n_output}, // recurrent_to_forget_weight tensor + {n_cell, n_output}, // recurrent_to_cell_weight tensor + {n_cell, n_output}, // recurrent_to_output_weight tensor + + {0}, // cell_to_input_weight tensor + {0}, // cell_to_forget_weight tensor + {0}, // cell_to_output_weight tensor + + {n_cell}, // input_gate_bias tensor + {n_cell}, // forget_gate_bias tensor + {n_cell}, // cell_bias tensor + {n_cell}, // output_gate_bias tensor + + {0, 0}, // projection_weight tensor + {0}, // projection_bias tensor + }, + TensorType_INT8); lstm.SetInputToInputWeights(input_to_input_weights_); lstm.SetInputToCellWeights(input_to_cell_weights_); @@ -647,7 +721,8 @@ TEST_F(CifgNoPeepholeNoProjectionNoClippingLstmTest, LstmBlackBoxTest) { VerifyGoldens(lstm_input_, lstm_golden_output_, &lstm); } -TEST_F(CifgNoPeepholeNoProjectionNoClippingLstmTest, HybridLstmBlackBoxTest) { +TEST_F(CifgNoPeepholeNoProjectionNoClippingLstmTest, + HybridLstmBlackBoxTestUint8) { const int n_batch = 1; const int n_input = 2; // n_cell and n_output have the same size when there is no projection. @@ -684,7 +759,67 @@ TEST_F(CifgNoPeepholeNoProjectionNoClippingLstmTest, HybridLstmBlackBoxTest) { {0, 0}, // projection_weight tensor {0}, // projection_bias tensor - }); + }, + TensorType_UINT8); + + lstm.SetInputToCellWeights(input_to_cell_weights_); + lstm.SetInputToForgetWeights(input_to_forget_weights_); + lstm.SetInputToOutputWeights(input_to_output_weights_); + + lstm.SetCellBias(cell_gate_bias_); + lstm.SetForgetGateBias(forget_gate_bias_); + lstm.SetOutputGateBias(output_gate_bias_); + + lstm.SetRecurrentToCellWeights(recurrent_to_cell_weights_); + lstm.SetRecurrentToForgetWeights(recurrent_to_forget_weights_); + lstm.SetRecurrentToOutputWeights(recurrent_to_output_weights_); + + lstm.SetCellToForgetWeights(cell_to_forget_weights_); + lstm.SetCellToOutputWeights(cell_to_output_weights_); + + VerifyGoldens(lstm_input_, lstm_golden_output_, &lstm, /*tolerance=*/0.03573); +} + +TEST_F(CifgNoPeepholeNoProjectionNoClippingLstmTest, + HybridLstmBlackBoxTestInt8) { + const int n_batch = 1; + const int n_input = 2; + // n_cell and n_output have the same size when there is no projection. + const int n_cell = 4; + const int n_output = 4; + + HybridLSTMOpModel lstm( + n_batch, n_input, n_cell, n_output, + /*use_cifg=*/true, /*use_peephole=*/true, + /*use_projection_weights=*/false, + /*use_projection_bias=*/false, + /*cell_clip=*/0.0, /*proj_clip=*/0.0, + { + {n_batch, n_input}, // input tensor + + {0, 0}, // input_to_input_weight tensor + {n_cell, n_input}, // input_to_forget_weight tensor + {n_cell, n_input}, // input_to_cell_weight tensor + {n_cell, n_input}, // input_to_output_weight tensor + + {0, 0}, // recurrent_to_input_weight tensor + {n_cell, n_output}, // recurrent_to_forget_weight tensor + {n_cell, n_output}, // recurrent_to_cell_weight tensor + {n_cell, n_output}, // recurrent_to_output_weight tensor + + {0}, // cell_to_input_weight tensor + {n_cell}, // cell_to_forget_weight tensor + {n_cell}, // cell_to_output_weight tensor + + {0}, // input_gate_bias tensor + {n_cell}, // forget_gate_bias tensor + {n_cell}, // cell_bias tensor + {n_cell}, // output_gate_bias tensor + + {0, 0}, // projection_weight tensor + {0}, // projection_bias tensor + }, + TensorType_INT8); lstm.SetInputToCellWeights(input_to_cell_weights_); lstm.SetInputToForgetWeights(input_to_forget_weights_); @@ -1364,7 +1499,7 @@ TEST_F(NoCifgPeepholeProjectionNoClippingLstmTest, LstmBlackBoxTest) { VerifyGoldens(lstm_input_, lstm_golden_output_, &lstm); } -TEST_F(NoCifgPeepholeProjectionNoClippingLstmTest, HybridLstmBlackBoxTest) { +TEST_F(NoCifgPeepholeProjectionNoClippingLstmTest, HybridLstmBlackBoxTesInt8) { const int n_batch = 2; const int n_input = 5; const int n_cell = 20; @@ -1400,7 +1535,72 @@ TEST_F(NoCifgPeepholeProjectionNoClippingLstmTest, HybridLstmBlackBoxTest) { {n_output, n_cell}, // projection_weight tensor {0}, // projection_bias tensor - }); + }, + TensorType_UINT8); + + lstm.SetInputToInputWeights(input_to_input_weights_); + lstm.SetInputToCellWeights(input_to_cell_weights_); + lstm.SetInputToForgetWeights(input_to_forget_weights_); + lstm.SetInputToOutputWeights(input_to_output_weights_); + + lstm.SetInputGateBias(input_gate_bias_); + lstm.SetCellBias(cell_gate_bias_); + lstm.SetForgetGateBias(forget_gate_bias_); + lstm.SetOutputGateBias(output_gate_bias_); + + lstm.SetRecurrentToInputWeights(recurrent_to_input_weights_); + lstm.SetRecurrentToCellWeights(recurrent_to_cell_weights_); + lstm.SetRecurrentToForgetWeights(recurrent_to_forget_weights_); + lstm.SetRecurrentToOutputWeights(recurrent_to_output_weights_); + + lstm.SetCellToInputWeights(cell_to_input_weights_); + lstm.SetCellToForgetWeights(cell_to_forget_weights_); + lstm.SetCellToOutputWeights(cell_to_output_weights_); + + lstm.SetProjectionWeights(projection_weights_); + + VerifyGoldens(lstm_input_, lstm_golden_output_, &lstm, /*tolerance=*/0.00467); +} + +TEST_F(NoCifgPeepholeProjectionNoClippingLstmTest, + HybridLstmBlackBoxTestUint8) { + const int n_batch = 2; + const int n_input = 5; + const int n_cell = 20; + const int n_output = 16; + + HybridLSTMOpModel lstm( + n_batch, n_input, n_cell, n_output, + /*use_cifg=*/false, /*use_peephole=*/true, + /*use_projection_weights=*/true, + /*use_projection_bias=*/false, + /*cell_clip=*/0.0, /*proj_clip=*/0.0, + { + {n_batch, n_input}, // input tensor + + {n_cell, n_input}, // input_to_input_weight tensor + {n_cell, n_input}, // input_to_forget_weight tensor + {n_cell, n_input}, // input_to_cell_weight tensor + {n_cell, n_input}, // input_to_output_weight tensor + + {n_cell, n_output}, // recurrent_to_input_weight tensor + {n_cell, n_output}, // recurrent_to_forget_weight tensor + {n_cell, n_output}, // recurrent_to_cell_weight tensor + {n_cell, n_output}, // recurrent_to_output_weight tensor + + {n_cell}, // cell_to_input_weight tensor + {n_cell}, // cell_to_forget_weight tensor + {n_cell}, // cell_to_output_weight tensor + + {n_cell}, // input_gate_bias tensor + {n_cell}, // forget_gate_bias tensor + {n_cell}, // cell_bias tensor + {n_cell}, // output_gate_bias tensor + + {n_output, n_cell}, // projection_weight tensor + {0}, // projection_bias tensor + }, + TensorType_INT8); lstm.SetInputToInputWeights(input_to_input_weights_); lstm.SetInputToCellWeights(input_to_cell_weights_); @@ -1447,54 +1647,67 @@ class HybridLayerNormLSTMOpModel : public LayerNormLSTMOpModel { bool use_projection_weights, bool use_projection_bias, float cell_clip, float proj_clip, - const std::vector>& input_shapes) + const std::vector>& input_shapes, + TensorType tensor_type) : LayerNormLSTMOpModel(n_batch, n_input, n_cell, n_output, use_cifg, use_peephole, use_projection_weights, use_projection_bias, cell_clip, proj_clip, - input_shapes, TensorType_UINT8) {} + input_shapes, tensor_type) { + tensor_type_ = tensor_type; + } + + TensorType tensor_type_; + + void SetWeights(int weights_idx, std::vector f) { + if (tensor_type_ == TensorType_UINT8) { + SymmetricQuantizeAndPopulate(weights_idx, f); + } else { + SignedSymmetricQuantizeAndPopulate(weights_idx, f); + } + } void SetInputToInputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(input_to_input_weights_, f); + SetWeights(input_to_input_weights_, f); } void SetInputToForgetWeights(std::vector f) { - SymmetricQuantizeAndPopulate(input_to_forget_weights_, f); + SetWeights(input_to_forget_weights_, f); } void SetInputToCellWeights(std::vector f) { - SymmetricQuantizeAndPopulate(input_to_cell_weights_, f); + SetWeights(input_to_cell_weights_, f); } void SetInputToOutputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(input_to_output_weights_, f); + SetWeights(input_to_output_weights_, f); } void SetRecurrentToInputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(recurrent_to_input_weights_, f); + SetWeights(recurrent_to_input_weights_, f); } void SetRecurrentToForgetWeights(std::vector f) { - SymmetricQuantizeAndPopulate(recurrent_to_forget_weights_, f); + SetWeights(recurrent_to_forget_weights_, f); } void SetRecurrentToCellWeights(std::vector f) { - SymmetricQuantizeAndPopulate(recurrent_to_cell_weights_, f); + SetWeights(recurrent_to_cell_weights_, f); } void SetRecurrentToOutputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(recurrent_to_output_weights_, f); + SetWeights(recurrent_to_output_weights_, f); } void SetCellToInputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(cell_to_input_weights_, f); + SetWeights(cell_to_input_weights_, f); } void SetCellToForgetWeights(std::vector f) { - SymmetricQuantizeAndPopulate(cell_to_forget_weights_, f); + SetWeights(cell_to_forget_weights_, f); } void SetCellToOutputWeights(std::vector f) { - SymmetricQuantizeAndPopulate(cell_to_output_weights_, f); + SetWeights(cell_to_output_weights_, f); } void SetInputLayerNormCoefficients(std::vector f) { @@ -1514,7 +1727,7 @@ class HybridLayerNormLSTMOpModel : public LayerNormLSTMOpModel { } void SetProjectionWeights(std::vector f) { - SymmetricQuantizeAndPopulate(projection_weights_, f); + SetWeights(projection_weights_, f); } }; @@ -1744,7 +1957,7 @@ TEST_F(NoCifgPeepholeProjectionNoClippingLayerNormLstmTest, } TEST_F(NoCifgPeepholeProjectionNoClippingLayerNormLstmTest, - HybridLayerNormLstmBlackBoxTest) { + HybridLayerNormLstmBlackBoxTestUint8) { const int n_batch = 2; const int n_input = 5; const int n_cell = 4; @@ -1789,7 +2002,103 @@ TEST_F(NoCifgPeepholeProjectionNoClippingLayerNormLstmTest, {n_cell}, // forget_layer_norm_coefficient tensor {n_cell}, // cell_layer_norm_coefficient tensor {n_cell}, // output_layer_norm_coefficient tensor - }); + }, + TensorType_UINT8); + + layer_norm_lstm.SetInputToInputWeights(input_to_input_weights_); + layer_norm_lstm.SetInputToCellWeights(input_to_cell_weights_); + layer_norm_lstm.SetInputToForgetWeights(input_to_forget_weights_); + layer_norm_lstm.SetInputToOutputWeights(input_to_output_weights_); + + layer_norm_lstm.SetInputGateBias(input_gate_bias_); + layer_norm_lstm.SetCellBias(cell_gate_bias_); + layer_norm_lstm.SetForgetGateBias(forget_gate_bias_); + layer_norm_lstm.SetOutputGateBias(output_gate_bias_); + + layer_norm_lstm.SetRecurrentToInputWeights(recurrent_to_input_weights_); + layer_norm_lstm.SetRecurrentToCellWeights(recurrent_to_cell_weights_); + layer_norm_lstm.SetRecurrentToForgetWeights(recurrent_to_forget_weights_); + layer_norm_lstm.SetRecurrentToOutputWeights(recurrent_to_output_weights_); + + layer_norm_lstm.SetCellToInputWeights(cell_to_input_weights_); + layer_norm_lstm.SetCellToForgetWeights(cell_to_forget_weights_); + layer_norm_lstm.SetCellToOutputWeights(cell_to_output_weights_); + + layer_norm_lstm.SetInputLayerNormCoefficients(input_layer_norm_coefficients_); + layer_norm_lstm.SetForgetLayerNormCoefficients( + forget_layer_norm_coefficients_); + layer_norm_lstm.SetCellLayerNormCoefficients(cell_layer_norm_coefficients_); + layer_norm_lstm.SetOutputLayerNormCoefficients( + output_layer_norm_coefficients_); + + layer_norm_lstm.SetProjectionWeights(projection_weights_); + + const std::vector> layer_norm_lstm_golden_output = { + { + // Batch0: 3 (input_sequence_size) * 3 (n_output) + 0.0244576, 0.127847, -0.00181765, // seq 0 + 0.0137518, 0.140892, 0.0402234, // seq 1 + -0.0048839, 0.155096, 0.0840309, // seq 2 + }, + { + // Batch1: 3 (input_sequence_size) * 3 (n_output) + -0.00728636, 0.0843957, 0.0634786, // seq 0 + -0.00448382, 0.139278, 0.0737372, // seq 1 + 0.00734616, 0.161793, 0.0560238, // seq 2 + }}; + + VerifyGoldens(layer_norm_lstm_input_, layer_norm_lstm_golden_output, + &layer_norm_lstm); +} + +TEST_F(NoCifgPeepholeProjectionNoClippingLayerNormLstmTest, + HybridLayerNormLstmBlackBoxTestInt8) { + const int n_batch = 2; + const int n_input = 5; + const int n_cell = 4; + const int n_output = 3; + const float ceil_clip = 0.0; + const float proj_clip = 0.0; + + HybridLayerNormLSTMOpModel layer_norm_lstm( + n_batch, n_input, n_cell, n_output, + /*use_cifg=*/false, /*use_peephole=*/true, + /*use_projection_weights=*/true, + /*use_projection_bias=*/false, ceil_clip, proj_clip, + { + {n_batch, n_input}, // input tensor + + {n_cell, n_input}, // input_to_input_weight tensor + {n_cell, n_input}, // input_to_forget_weight tensor + {n_cell, n_input}, // input_to_cell_weight tensor + {n_cell, n_input}, // input_to_output_weight tensor + + {n_cell, n_output}, // recurrent_to_input_weight tensor + {n_cell, n_output}, // recurrent_to_forget_weight tensor + {n_cell, n_output}, // recurrent_to_cell_weight tensor + {n_cell, n_output}, // recurrent_to_output_weight tensor + + {n_cell}, // cell_to_input_weight tensor + {n_cell}, // cell_to_forget_weight tensor + {n_cell}, // cell_to_output_weight tensor + + {n_cell}, // input_gate_bias tensor + {n_cell}, // forget_gate_bias tensor + {n_cell}, // cell_bias tensor + {n_cell}, // output_gate_bias tensor + + {n_output, n_cell}, // projection_weight tensor + {0}, // projection_bias tensor + + {n_batch, n_output}, // activation_state tensor + {n_batch, n_cell}, // cell_state tensor + + {n_cell}, // input_layer_norm_coefficient tensor + {n_cell}, // forget_layer_norm_coefficient tensor + {n_cell}, // cell_layer_norm_coefficient tensor + {n_cell}, // output_layer_norm_coefficient tensor + }, + TensorType_INT8); layer_norm_lstm.SetInputToInputWeights(input_to_input_weights_); layer_norm_lstm.SetInputToCellWeights(input_to_cell_weights_); @@ -1975,7 +2284,7 @@ TEST_F(CifgPeepholeProjectionNoClippingLayerNormLstmTest, } TEST_F(CifgPeepholeProjectionNoClippingLayerNormLstmTest, - HybridLayerNormLstmBlackBoxTest) { + HybridLayerNormLstmBlackBoxTestUint8) { const int n_batch = 2; const int n_input = 5; const int n_cell = 4; @@ -2020,7 +2329,99 @@ TEST_F(CifgPeepholeProjectionNoClippingLayerNormLstmTest, {n_cell}, // forget_layer_norm_coefficient tensor {n_cell}, // cell_layer_norm_coefficient tensor {n_cell}, // output_layer_norm_coefficient tensor - }); + }, + TensorType_UINT8); + + layer_norm_lstm.SetInputToCellWeights(input_to_cell_weights_); + layer_norm_lstm.SetInputToForgetWeights(input_to_forget_weights_); + layer_norm_lstm.SetInputToOutputWeights(input_to_output_weights_); + + layer_norm_lstm.SetCellBias(cell_gate_bias_); + layer_norm_lstm.SetForgetGateBias(forget_gate_bias_); + layer_norm_lstm.SetOutputGateBias(output_gate_bias_); + + layer_norm_lstm.SetRecurrentToCellWeights(recurrent_to_cell_weights_); + layer_norm_lstm.SetRecurrentToForgetWeights(recurrent_to_forget_weights_); + layer_norm_lstm.SetRecurrentToOutputWeights(recurrent_to_output_weights_); + + layer_norm_lstm.SetCellToForgetWeights(cell_to_forget_weights_); + layer_norm_lstm.SetCellToOutputWeights(cell_to_output_weights_); + + layer_norm_lstm.SetForgetLayerNormCoefficients( + forget_layer_norm_coefficients_); + layer_norm_lstm.SetCellLayerNormCoefficients(cell_layer_norm_coefficients_); + layer_norm_lstm.SetOutputLayerNormCoefficients( + output_layer_norm_coefficients_); + + layer_norm_lstm.SetProjectionWeights(projection_weights_); + + // Verify the final output. + const std::vector> layer_norm_lstm_golden_output = { + { + // Batch0: 3 (input_sequence_size) * 3 (n_output) + 0.0212250091, 0.140474007, 0.0115012666, // seq 0 + 0.0130806509, 0.152660668, 0.0347516984, // seq 1 + -0.0124010444, 0.166042402, 0.0898982584, // seq 2 + }, + { + // Batch1: 3 (input_sequence_size) * 3 (n_output) + -0.0228835996, 0.0917588323, 0.0778886303, // seq 0 + -0.0275101066, 0.148769245, 0.0938384682, // seq 1 + -0.0103605557, 0.172605693, 0.0728750974, // seq 2 + }}; + + VerifyGoldens(layer_norm_lstm_input_, layer_norm_lstm_golden_output, + &layer_norm_lstm); +} + +TEST_F(CifgPeepholeProjectionNoClippingLayerNormLstmTest, + HybridLayerNormLstmBlackBoxTestInt8) { + const int n_batch = 2; + const int n_input = 5; + const int n_cell = 4; + const int n_output = 3; + const float ceil_clip = 0.0; + const float proj_clip = 0.0; + + HybridLayerNormLSTMOpModel layer_norm_lstm( + n_batch, n_input, n_cell, n_output, + /*use_cifg=*/true, /*use_peephole=*/true, + /*use_projection_weights=*/true, + /*use_projection_bias=*/false, ceil_clip, proj_clip, + { + {n_batch, n_input}, // input tensor + + {0, 0}, // input_to_input_weight tensor + {n_cell, n_input}, // input_to_forget_weight tensor + {n_cell, n_input}, // input_to_cell_weight tensor + {n_cell, n_input}, // input_to_output_weight tensor + + {0, 0}, // recurrent_to_input_weight tensor + {n_cell, n_output}, // recurrent_to_forget_weight tensor + {n_cell, n_output}, // recurrent_to_cell_weight tensor + {n_cell, n_output}, // recurrent_to_output_weight tensor + + {0}, // cell_to_input_weight tensor + {n_cell}, // cell_to_forget_weight tensor + {n_cell}, // cell_to_output_weight tensor + + {0}, // input_gate_bias tensor + {n_cell}, // forget_gate_bias tensor + {n_cell}, // cell_bias tensor + {n_cell}, // output_gate_bias tensor + + {n_output, n_cell}, // projection_weight tensor + {0}, // projection_bias tensor + + {n_batch, n_output}, // activation_state tensor + {n_batch, n_cell}, // cell_state tensor + + {0}, // input_layer_norm_coefficient tensor + {n_cell}, // forget_layer_norm_coefficient tensor + {n_cell}, // cell_layer_norm_coefficient tensor + {n_cell}, // output_layer_norm_coefficient tensor + }, + TensorType_INT8); layer_norm_lstm.SetInputToCellWeights(input_to_cell_weights_); layer_norm_lstm.SetInputToForgetWeights(input_to_forget_weights_); diff --git a/tensorflow/lite/kernels/register.cc b/tensorflow/lite/kernels/register.cc index fae303f016..6b8ea39ee9 100644 --- a/tensorflow/lite/kernels/register.cc +++ b/tensorflow/lite/kernels/register.cc @@ -172,7 +172,7 @@ BuiltinOpResolver::BuiltinOpResolver() { /* max_version */ 2); AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D(), /* min_version */ 1, - /* max_version */ 3); + /* max_version */ 2); AddBuiltin(BuiltinOperator_SVDF, Register_SVDF(), /* min_version */ 1, /* max_version */ 2); @@ -190,7 +190,7 @@ BuiltinOpResolver::BuiltinOpResolver() { Register_EMBEDDING_LOOKUP_SPARSE()); AddBuiltin(BuiltinOperator_FULLY_CONNECTED, Register_FULLY_CONNECTED(), /* min_version */ 1, - /* max_version */ 2); + /* max_version */ 3); AddBuiltin(BuiltinOperator_LSH_PROJECTION, Register_LSH_PROJECTION()); AddBuiltin(BuiltinOperator_HASHTABLE_LOOKUP, Register_HASHTABLE_LOOKUP()); AddBuiltin(BuiltinOperator_SOFTMAX, Register_SOFTMAX()); @@ -203,7 +203,7 @@ BuiltinOpResolver::BuiltinOpResolver() { AddBuiltin(BuiltinOperator_LOCAL_RESPONSE_NORMALIZATION, Register_LOCAL_RESPONSE_NORMALIZATION()); AddBuiltin(BuiltinOperator_LSTM, Register_LSTM(), /* min_version */ 1, - /* max_version */ 2); + /* max_version */ 3); AddBuiltin(BuiltinOperator_BIDIRECTIONAL_SEQUENCE_LSTM, Register_BIDIRECTIONAL_SEQUENCE_LSTM(), /* min_version */ 1, /* max_version */ 2); diff --git a/tensorflow/lite/toco/tflite/operator.cc b/tensorflow/lite/toco/tflite/operator.cc index 0d5cff7bfa..156b7feec0 100644 --- a/tensorflow/lite/toco/tflite/operator.cc +++ b/tensorflow/lite/toco/tflite/operator.cc @@ -819,9 +819,24 @@ class Lstm : public BuiltinOperator(*op_signature.op); switch (lstm_op.kernel_type) { - case LstmCellOperator::KERNEL_FULL: + case LstmCellOperator::KERNEL_FULL: { + // If the input tensor is float and a weight is int8, this is a version + // 3 hybrid operation. + const string& input_name = op_signature.op->inputs[0]; + const string& weights_name = op_signature.op->inputs[2]; + const string& output_name = op_signature.op->outputs[0]; + const Array& input_array = op_signature.model->GetArray(input_name); + const Array& weights_array = op_signature.model->GetArray(weights_name); + const Array& output_array = op_signature.model->GetArray(output_name); + if (input_array.data_type == ArrayDataType::kFloat && + weights_array.data_type == ArrayDataType::kInt8 && + output_array.data_type == ArrayDataType::kFloat) { + return 3; + } return 1; + } case LstmCellOperator::KERNEL_BASIC: + // KERNEL_BASIC was added in version 2. return 2; } } -- GitLab From 9972577e17c14e1526f59d18f9e17bea1c3eec22 Mon Sep 17 00:00:00 2001 From: Tamara Norman Date: Fri, 21 Dec 2018 03:33:27 -0800 Subject: [PATCH 0242/1765] Remove dtype argument from the init method of the initializers in v2 and the partition_info from the call. Move all API symbols to only Keras in v2. Merged the tests for v2 into one file and added run_in_v1 to the original tests PiperOrigin-RevId: 226468057 --- tensorflow/python/BUILD | 32 + tensorflow/python/keras/BUILD | 1 + tensorflow/python/keras/initializers.py | 32 +- tensorflow/python/keras/initializers_test.py | 9 +- tensorflow/python/keras/ops.py | 65 +- tensorflow/python/ops/init_ops.py | 145 ++-- tensorflow/python/ops/init_ops_test.py | 12 +- tensorflow/python/ops/init_ops_v2.py | 764 ++++++++++++++++++ tensorflow/python/ops/init_ops_v2_test.py | 512 ++++++++++++ .../tools/api/generator/api_init_files.bzl | 1 - .../v2/tensorflow.constant_initializer.pbtxt | 6 +- ...ensorflow.glorot_uniform_initializer.pbtxt | 19 - .../v2/tensorflow.initializers.constant.pbtxt | 18 - ...ensorflow.initializers.glorot_normal.pbtxt | 19 - ...nsorflow.initializers.glorot_uniform.pbtxt | 19 - .../v2/tensorflow.initializers.identity.pbtxt | 18 - .../v2/tensorflow.initializers.ones.pbtxt | 18 - .../tensorflow.initializers.orthogonal.pbtxt | 18 - .../golden/v2/tensorflow.initializers.pbtxt | 67 -- ...ensorflow.initializers.random_normal.pbtxt | 18 - ...nsorflow.initializers.random_uniform.pbtxt | 18 - ...orflow.initializers.truncated_normal.pbtxt | 18 - ...ow.initializers.uniform_unit_scaling.pbtxt | 18 - ...orflow.initializers.variance_scaling.pbtxt | 18 - .../v2/tensorflow.initializers.zeros.pbtxt | 18 - ...sorflow.keras.initializers.-constant.pbtxt | 6 +- ...ow.keras.initializers.-glorot-normal.pbtxt | 19 + ...w.keras.initializers.-glorot-uniform.pbtxt | 19 + ...sorflow.keras.initializers.-identity.pbtxt | 6 +- ...flow.keras.initializers.-initializer.pbtxt | 2 +- .../tensorflow.keras.initializers.-ones.pbtxt | 5 +- ...rflow.keras.initializers.-orthogonal.pbtxt | 6 +- ...ow.keras.initializers.-random-normal.pbtxt | 7 +- ...w.keras.initializers.-random-uniform.pbtxt | 7 +- ...keras.initializers.-truncated-normal.pbtxt | 7 +- ...keras.initializers.-variance-scaling.pbtxt | 6 +- ...tensorflow.keras.initializers.-zeros.pbtxt | 5 +- ...nsorflow.keras.initializers.constant.pbtxt | 18 - ...low.keras.initializers.glorot_normal.pbtxt | 19 - ...ow.keras.initializers.glorot_uniform.pbtxt | 19 - ...nsorflow.keras.initializers.identity.pbtxt | 18 - ...tensorflow.keras.initializers.normal.pbtxt | 19 - .../tensorflow.keras.initializers.ones.pbtxt | 18 - ...orflow.keras.initializers.orthogonal.pbtxt | 18 - .../v2/tensorflow.keras.initializers.pbtxt | 56 +- ...low.keras.initializers.random_normal.pbtxt | 19 - ...ow.keras.initializers.random_uniform.pbtxt | 19 - ....keras.initializers.truncated_normal.pbtxt | 19 - ...ensorflow.keras.initializers.uniform.pbtxt | 19 - .../tensorflow.keras.initializers.zeros.pbtxt | 18 - .../v2/tensorflow.ones_initializer.pbtxt | 5 +- .../tools/api/golden/v2/tensorflow.pbtxt | 12 - ...tensorflow.random_normal_initializer.pbtxt | 6 +- ...ensorflow.random_uniform_initializer.pbtxt | 6 +- ...sorflow.truncated_normal_initializer.pbtxt | 18 - .../v2/tensorflow.zeros_initializer.pbtxt | 5 +- tensorflow/tools/compatibility/renames_v2.py | 51 +- .../tools/compatibility/tf_upgrade_v2.py | 97 +++ 58 files changed, 1723 insertions(+), 734 deletions(-) create mode 100644 tensorflow/python/ops/init_ops_v2.py create mode 100644 tensorflow/python/ops/init_ops_v2_test.py delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.glorot_uniform_initializer.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.constant.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.glorot_normal.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.glorot_uniform.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.identity.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.ones.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.orthogonal.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.random_normal.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.random_uniform.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.truncated_normal.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.uniform_unit_scaling.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.variance_scaling.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.initializers.zeros.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-glorot-normal.pbtxt create mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-glorot-uniform.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.constant.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.glorot_normal.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.glorot_uniform.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.identity.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.normal.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.ones.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.orthogonal.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.random_normal.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.random_uniform.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.truncated_normal.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.uniform.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.zeros.pbtxt delete mode 100644 tensorflow/tools/api/golden/v2/tensorflow.truncated_normal_initializer.pbtxt diff --git a/tensorflow/python/BUILD b/tensorflow/python/BUILD index 7e504ea8e4..6efc59d924 100644 --- a/tensorflow/python/BUILD +++ b/tensorflow/python/BUILD @@ -2428,6 +2428,23 @@ py_library( ], ) +py_library( + name = "init_ops_v2", + srcs = ["ops/init_ops_v2.py"], + srcs_version = "PY2AND3", + deps = [ + ":array_ops", + ":constant_op", + ":dtypes", + ":linalg_ops_gen", + ":linalg_ops_impl", + ":math_ops", + ":random_ops", + ":util", + "//third_party/py/numpy", + ], +) + py_library( name = "initializers_ns", srcs = ["ops/initializers_ns.py"], @@ -3404,6 +3421,21 @@ cuda_py_test( ], ) +cuda_py_test( + name = "init_ops_v2_test", + size = "medium", + srcs = ["ops/init_ops_v2_test.py"], + additional_deps = [ + ":array_ops", + ":client_testlib", + ":init_ops_v2", + ":random_ops", + ":framework_ops", + "//third_party/py/numpy", + "//tensorflow/python/eager:context", + ], +) + cuda_py_test( name = "math_grad_test", size = "small", diff --git a/tensorflow/python/keras/BUILD b/tensorflow/python/keras/BUILD index dfbb34aea9..ed1add6755 100755 --- a/tensorflow/python/keras/BUILD +++ b/tensorflow/python/keras/BUILD @@ -100,6 +100,7 @@ py_library( "//tensorflow/python:gradients", "//tensorflow/python:image_ops", "//tensorflow/python:init_ops", + "//tensorflow/python:init_ops_v2", "//tensorflow/python:logging_ops", "//tensorflow/python:math_ops", "//tensorflow/python:metrics", diff --git a/tensorflow/python/keras/initializers.py b/tensorflow/python/keras/initializers.py index 33415fd139..ac55ff965e 100644 --- a/tensorflow/python/keras/initializers.py +++ b/tensorflow/python/keras/initializers.py @@ -42,12 +42,30 @@ from tensorflow.python.ops.init_ops import RandomUniform as TFRandomUniform from tensorflow.python.ops.init_ops import TruncatedNormal as TFTruncatedNormal from tensorflow.python.ops.init_ops import VarianceScaling # pylint: disable=unused-import from tensorflow.python.ops.init_ops import Zeros +# pylint: disable=unused-import, disable=line-too-long +from tensorflow.python.ops.init_ops_v2 import Constant as ConstantV2 +from tensorflow.python.ops.init_ops_v2 import GlorotNormal as GlorotNormalV2 +from tensorflow.python.ops.init_ops_v2 import GlorotUniform as GlorotUniformV2 +from tensorflow.python.ops.init_ops_v2 import he_normal as he_normalV2 +from tensorflow.python.ops.init_ops_v2 import he_uniform as he_uniformV2 +from tensorflow.python.ops.init_ops_v2 import Identity as IdentityV2 +from tensorflow.python.ops.init_ops_v2 import Initializer as InitializerV2 +from tensorflow.python.ops.init_ops_v2 import lecun_normal as lecun_normalV2 +from tensorflow.python.ops.init_ops_v2 import lecun_uniform as lecun_uniformV2 +from tensorflow.python.ops.init_ops_v2 import Ones as OnesV2 +from tensorflow.python.ops.init_ops_v2 import Orthogonal as OrthogonalV2 +from tensorflow.python.ops.init_ops_v2 import RandomNormal as RandomNormalV2 +from tensorflow.python.ops.init_ops_v2 import RandomUniform as RandomUniformV2 +from tensorflow.python.ops.init_ops_v2 import TruncatedNormal as TruncatedNormalV2 +from tensorflow.python.ops.init_ops_v2 import VarianceScaling as VarianceScalingV2 +from tensorflow.python.ops.init_ops_v2 import Zeros as ZerosV2 +# pylint: enable=unused-import, enable=line-too-long from tensorflow.python.util.tf_export import keras_export -@keras_export('keras.initializers.TruncatedNormal', - 'keras.initializers.truncated_normal') +@keras_export(v1=['keras.initializers.TruncatedNormal', + 'keras.initializers.truncated_normal']) class TruncatedNormal(TFTruncatedNormal): """Initializer that generates a truncated normal distribution. @@ -71,8 +89,9 @@ class TruncatedNormal(TFTruncatedNormal): mean=mean, stddev=stddev, seed=seed, dtype=dtype) -@keras_export('keras.initializers.RandomUniform', 'keras.initializers.uniform', - 'keras.initializers.random_uniform') +@keras_export(v1=['keras.initializers.RandomUniform', + 'keras.initializers.uniform', + 'keras.initializers.random_uniform']) class RandomUniform(TFRandomUniform): """Initializer that generates tensors with a uniform distribution. @@ -92,8 +111,9 @@ class RandomUniform(TFRandomUniform): minval=minval, maxval=maxval, seed=seed, dtype=dtype) -@keras_export('keras.initializers.RandomNormal', 'keras.initializers.normal', - 'keras.initializers.random_normal') +@keras_export(v1=['keras.initializers.RandomNormal', + 'keras.initializers.normal', + 'keras.initializers.random_normal']) class RandomNormal(TFRandomNormal): """Initializer that generates tensors with a normal distribution. diff --git a/tensorflow/python/keras/initializers_test.py b/tensorflow/python/keras/initializers_test.py index 4f91bea1e3..36f2d40532 100644 --- a/tensorflow/python/keras/initializers_test.py +++ b/tensorflow/python/keras/initializers_test.py @@ -21,8 +21,8 @@ from __future__ import print_function import numpy as np from tensorflow.python import keras -from tensorflow.python.ops import init_ops from tensorflow.python.framework import test_util +from tensorflow.python.ops import init_ops from tensorflow.python.platform import test @@ -67,6 +67,7 @@ class KerasInitializersTest(test.TestCase): tensor_shape, target_mean=0., target_max=2, target_min=-2) + @test_util.run_deprecated_v1 def test_constant(self): tensor_shape = (5, 6, 4) with self.cached_session(): @@ -134,6 +135,7 @@ class KerasInitializersTest(test.TestCase): self._runner(keras.initializers.orthogonal(seed=123), tensor_shape, target_mean=0.) + @test_util.run_deprecated_v1 def test_identity(self): with self.cached_session(): tensor_shape = (3, 4, 5) @@ -145,28 +147,33 @@ class KerasInitializersTest(test.TestCase): self._runner(keras.initializers.identity(), tensor_shape, target_mean=1. / tensor_shape[0], target_max=1.) + @test_util.run_deprecated_v1 def test_zero(self): tensor_shape = (4, 5) with self.cached_session(): self._runner(keras.initializers.zeros(), tensor_shape, target_mean=0., target_max=0.) + @test_util.run_deprecated_v1 def test_one(self): tensor_shape = (4, 5) with self.cached_session(): self._runner(keras.initializers.ones(), tensor_shape, target_mean=1., target_max=1.) + @test_util.run_deprecated_v1 def test_default_random_uniform(self): ru = keras.initializers.get('uniform') self.assertEqual(ru.minval, -0.05) self.assertEqual(ru.maxval, 0.05) + @test_util.run_deprecated_v1 def test_default_random_normal(self): rn = keras.initializers.get('normal') self.assertEqual(rn.mean, 0.0) self.assertEqual(rn.stddev, 0.05) + @test_util.run_deprecated_v1 def test_default_truncated_normal(self): tn = keras.initializers.get('truncated_normal') self.assertEqual(tn.mean, 0.0) diff --git a/tensorflow/python/keras/ops.py b/tensorflow/python/keras/ops.py index dca076eea1..bc14eef505 100644 --- a/tensorflow/python/keras/ops.py +++ b/tensorflow/python/keras/ops.py @@ -19,37 +19,76 @@ from __future__ import print_function from tensorflow.python.framework import ops from tensorflow.python.ops import init_ops +from tensorflow.python.ops import init_ops_v2 from tensorflow.python.ops.losses import losses_impl from tensorflow.python.util.tf_export import keras_export -keras_export("keras.initializers.Initializer")( +# pylint: disable=bad-continuation +keras_export(v1=["keras.initializers.Initializer"])( init_ops.Initializer) -keras_export("keras.initializers.Zeros", "keras.initializers.zeros")( +keras_export(v1=["keras.initializers.Zeros", "keras.initializers.zeros"])( init_ops.Zeros) -keras_export("keras.initializers.Ones", "keras.initializers.ones")( +keras_export(v1=["keras.initializers.Ones", "keras.initializers.ones"])( init_ops.Ones) -keras_export("keras.initializers.Constant", "keras.initializers.constant")( +keras_export(v1=["keras.initializers.Constant", "keras.initializers.constant"])( init_ops.Constant) -keras_export("keras.initializers.VarianceScaling")( +keras_export(v1=["keras.initializers.VarianceScaling"])( init_ops.VarianceScaling) -keras_export("keras.initializers.Orthogonal", "keras.initializers.orthogonal")( +keras_export(v1=["keras.initializers.Orthogonal", + "keras.initializers.orthogonal"])( init_ops.Orthogonal) -keras_export("keras.initializers.Identity", "keras.initializers.identity")( +keras_export(v1=["keras.initializers.Identity", + "keras.initializers.identity"])( init_ops.Identity) -keras_export("keras.initializers.glorot_uniform")( +keras_export(v1=["keras.initializers.glorot_uniform"])( init_ops.GlorotUniform) -keras_export("keras.initializers.glorot_normal")( +keras_export(v1=["keras.initializers.glorot_normal"])( init_ops.GlorotNormal) -keras_export("keras.initializers.lecun_normal")( +keras_export(v1=["keras.initializers.lecun_normal"])( init_ops.lecun_normal) -keras_export("keras.initializers.lecun_uniform")( +keras_export(v1=["keras.initializers.lecun_uniform"])( init_ops.lecun_uniform) -keras_export("keras.initializers.he_normal")( +keras_export(v1=["keras.initializers.he_normal"])( init_ops.he_normal) -keras_export("keras.initializers.he_uniform")( +keras_export(v1=["keras.initializers.he_uniform"])( init_ops.he_uniform) +keras_export("keras.initializers.Initializer", v1=[])( + init_ops_v2.Initializer) +keras_export("keras.initializers.Zeros", v1=[])( + init_ops_v2.Zeros) +keras_export("keras.initializers.Ones", v1=[])( + init_ops_v2.Ones) +keras_export("keras.initializers.Constant", v1=[])( + init_ops_v2.Constant) +keras_export("keras.initializers.VarianceScaling", v1=[])( + init_ops_v2.VarianceScaling) +keras_export("keras.initializers.Orthogonal", v1=[])( + init_ops_v2.Orthogonal) +keras_export("keras.initializers.Identity", v1=[])( + init_ops_v2.Identity) +keras_export("keras.initializers.GlorotUniform", v1=[])( + init_ops_v2.GlorotUniform) +keras_export("keras.initializers.GlorotNormal", v1=[])( + init_ops_v2.GlorotNormal) +keras_export("keras.initializers.lecun_normal", v1=[])( + init_ops_v2.lecun_normal) +keras_export("keras.initializers.lecun_uniform", v1=[])( + init_ops_v2.lecun_uniform) +keras_export("keras.initializers.he_normal", v1=[])( + init_ops_v2.he_normal) +keras_export("keras.initializers.he_uniform", v1=[])( + init_ops_v2.he_uniform) +keras_export("keras.initializers.RandomNormal", v1=[])( + init_ops_v2.RandomNormal) +keras_export("keras.initializers.RandomUniform", v1=[])( + init_ops_v2.RandomUniform) +keras_export("keras.initializers.TruncatedNormal", v1=[])( + init_ops_v2.TruncatedNormal) +# pylint: enable=bad-continuation + + keras_export("keras.backend.name_scope")(ops.name_scope) keras_export("keras.losses.Reduction", v1=[])( diff --git a/tensorflow/python/ops/init_ops.py b/tensorflow/python/ops/init_ops.py index 395d53b328..a4cebc8d58 100644 --- a/tensorflow/python/ops/init_ops.py +++ b/tensorflow/python/ops/init_ops.py @@ -46,6 +46,7 @@ from tensorflow.python.ops import random_ops from tensorflow.python.util import deprecation from tensorflow.python.util.deprecation import deprecated from tensorflow.python.util.deprecation import deprecated_arg_values +from tensorflow.python.util.deprecation import deprecated_args from tensorflow.python.util.tf_export import tf_export @@ -95,10 +96,15 @@ class Initializer(object): return cls(**config) -@tf_export("initializers.zeros", "zeros_initializer") +@tf_export(v1=["initializers.zeros", "zeros_initializer"]) +@deprecation.deprecated_endpoints("initializers.zeros") class Zeros(Initializer): """Initializer that generates tensors initialized to 0.""" + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") def __init__(self, dtype=dtypes.float32): self.dtype = dtypes.as_dtype(dtype) @@ -111,10 +117,15 @@ class Zeros(Initializer): return {"dtype": self.dtype.name} -@tf_export("initializers.ones", "ones_initializer") +@tf_export(v1=["initializers.ones", "ones_initializer"]) +@deprecation.deprecated_endpoints("initializers.ones", "ones_initializer") class Ones(Initializer): """Initializer that generates tensors initialized to 1.""" + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") def __init__(self, dtype=dtypes.float32): self.dtype = dtypes.as_dtype(dtype) @@ -127,7 +138,8 @@ class Ones(Initializer): return {"dtype": self.dtype.name} -@tf_export("initializers.constant", "constant_initializer") +@tf_export(v1=["initializers.constant", "constant_initializer"]) +@deprecation.deprecated_endpoints("constant_initializer") class Constant(Initializer): """Initializer that generates tensors with constant values. @@ -207,6 +219,14 @@ class Constant(Initializer): ``` """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") + @deprecated_args(None, + "Objects must now be the required shape or no shape " + "can be specified", + "verify_shape") def __init__(self, value=0, dtype=dtypes.float32, verify_shape=False): if not (np.isscalar(value) or isinstance(value, (list, tuple, np.ndarray))): raise TypeError( @@ -233,7 +253,8 @@ class Constant(Initializer): return {"value": self.value, "dtype": self.dtype.name} -@tf_export("initializers.random_uniform", "random_uniform_initializer") +@tf_export(v1=["initializers.random_uniform", "random_uniform_initializer"]) +@deprecation.deprecated_endpoints("initializers.random_uniform") class RandomUniform(Initializer): """Initializer that generates tensors with a uniform distribution. @@ -249,6 +270,10 @@ class RandomUniform(Initializer): calling the initializer. """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") def __init__(self, minval=0, maxval=None, seed=None, dtype=dtypes.float32): self.minval = minval self.maxval = maxval @@ -270,7 +295,8 @@ class RandomUniform(Initializer): } -@tf_export("initializers.random_normal", "random_normal_initializer") +@tf_export(v1=["initializers.random_normal", "random_normal_initializer"]) +@deprecation.deprecated_endpoints("initializers.random_normal") class RandomNormal(Initializer): """Initializer that generates tensors with a normal distribution. @@ -286,6 +312,10 @@ class RandomNormal(Initializer): calling the initializer. Only floating point types are supported. """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") def __init__(self, mean=0.0, stddev=1.0, seed=None, dtype=dtypes.float32): self.mean = mean self.stddev = stddev @@ -307,7 +337,9 @@ class RandomNormal(Initializer): } -@tf_export("initializers.truncated_normal", "truncated_normal_initializer") +@tf_export(v1=["initializers.truncated_normal", "truncated_normal_initializer"]) +@deprecation.deprecated_endpoints("initializers.truncated_normal", + "truncated_normal_initializer") class TruncatedNormal(Initializer): """Initializer that generates a truncated normal distribution. @@ -328,6 +360,10 @@ class TruncatedNormal(Initializer): calling the initializer. Only floating point types are supported. """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") def __init__(self, mean=0.0, stddev=1.0, seed=None, dtype=dtypes.float32): self.mean = mean self.stddev = stddev @@ -349,12 +385,10 @@ class TruncatedNormal(Initializer): } -@tf_export( - "initializers.uniform_unit_scaling", - v1=[ - "initializers.uniform_unit_scaling", "uniform_unit_scaling_initializer" - ]) -@deprecation.deprecated_endpoints("uniform_unit_scaling_initializer") +@tf_export(v1=["initializers.uniform_unit_scaling", + "uniform_unit_scaling_initializer"]) +@deprecation.deprecated_endpoints("uniform_unit_scaling_initializer", + "initializers.uniform_unit_scaling") class UniformUnitScaling(Initializer): """Initializer that generates tensors without scaling variance. @@ -386,6 +420,10 @@ class UniformUnitScaling(Initializer): ([pdf](http://arxiv.org/pdf/1412.6558.pdf)) """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") @deprecated(None, "Use tf.initializers.variance_scaling instead with distribution=" "uniform to get equivalent behavior.") @@ -417,13 +455,9 @@ class UniformUnitScaling(Initializer): return {"factor": self.factor, "seed": self.seed, "dtype": self.dtype.name} -@tf_export( - "initializers.variance_scaling", - v1=[ - "initializers.variance_scaling", - "variance_scaling_initializer" - ]) -@deprecation.deprecated_endpoints("variance_scaling_initializer") +@tf_export(v1=["initializers.variance_scaling", "variance_scaling_initializer"]) +@deprecation.deprecated_endpoints("initializers.variance_scaling", + "variance_scaling_initializer") class VarianceScaling(Initializer): """Initializer capable of adapting its scale to the shape of weights tensors. @@ -454,6 +488,10 @@ class VarianceScaling(Initializer): "distribution" arguments. """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") @deprecated_arg_values( None, "`normal` is a deprecated alias for `truncated_normal`", @@ -516,13 +554,9 @@ class VarianceScaling(Initializer): } -@tf_export( - "initializers.orthogonal", - v1=[ - "initializers.orthogonal", - "orthogonal_initializer", - ]) -@deprecation.deprecated_endpoints("orthogonal_initializer") +@tf_export(v1=["initializers.orthogonal", "orthogonal_initializer"]) +@deprecation.deprecated_endpoints("initializers.orthogonal", + "orthogonal_initializer") class Orthogonal(Initializer): """Initializer that generates an orthogonal matrix. @@ -550,6 +584,10 @@ class Orthogonal(Initializer): ([pdf](https://arxiv.org/pdf/1312.6120.pdf)) """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") def __init__(self, gain=1.0, seed=None, dtype=dtypes.float32): self.gain = gain self.dtype = _assert_float_dtype(dtypes.as_dtype(dtype)) @@ -568,8 +606,10 @@ class Orthogonal(Initializer): for dim in shape[:-1]: num_rows *= dim num_cols = shape[-1] - flat_shape = (num_cols, num_rows) if num_rows < num_cols else (num_rows, - num_cols) + if num_rows < num_cols: + flat_shape = (num_cols, num_rows) + else: + flat_shape = (num_rows, num_cols) # Generate a random matrix a = random_ops.random_normal(flat_shape, dtype=dtype, seed=self.seed) @@ -586,6 +626,8 @@ class Orthogonal(Initializer): return {"gain": self.gain, "seed": self.seed, "dtype": self.dtype.name} +# Note these haven't been ported to TF2.0. They are not currently visible and +# the tests are non trivial to port class ConvolutionDeltaOrthogonal(Initializer): """Initializer that generates a delta orthogonal kernel for ConvNets. @@ -1137,7 +1179,8 @@ class ConvolutionOrthogonal3D(ConvolutionOrthogonal): return self._dict_to_tensor(p, ksize, ksize, ksize) -@tf_export("initializers.identity") +@tf_export(v1=["initializers.identity"]) +@deprecation.deprecated_endpoints("initializers.identity") class Identity(Initializer): """Initializer that generates the identity matrix. @@ -1149,6 +1192,10 @@ class Identity(Initializer): calling the initializer. Only floating point types are supported. """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") def __init__(self, gain=1.0, dtype=dtypes.float32): self.gain = gain self.dtype = _assert_float_dtype(dtypes.as_dtype(dtype)) @@ -1170,7 +1217,9 @@ class Identity(Initializer): return {"gain": self.gain, "dtype": self.dtype.name} -@tf_export("glorot_uniform_initializer", "initializers.glorot_uniform") +@tf_export(v1=["glorot_uniform_initializer", "initializers.glorot_uniform"]) +@deprecation.deprecated_endpoints("glorot_uniform_initializer", + "initializers.glorot_uniform") class GlorotUniform(VarianceScaling): """The Glorot uniform initializer, also called Xavier uniform initializer. @@ -1191,6 +1240,10 @@ class GlorotUniform(VarianceScaling): ([pdf](http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf)) """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") def __init__(self, seed=None, dtype=dtypes.float32): super(GlorotUniform, self).__init__( scale=1.0, @@ -1203,13 +1256,9 @@ class GlorotUniform(VarianceScaling): return {"seed": self.seed, "dtype": self.dtype.name} -@tf_export( - "initializers.glorot_normal", - v1=[ - "glorot_normal_initializer", - "initializers.glorot_normal" - ]) -@deprecation.deprecated_endpoints("glorot_normal_initializer") +@tf_export(v1=["glorot_normal_initializer", "initializers.glorot_normal"]) +@deprecation.deprecated_endpoints("glorot_normal_initializer", + "initializers.glorot_normal") class GlorotNormal(VarianceScaling): """The Glorot normal initializer, also called Xavier normal initializer. @@ -1229,6 +1278,10 @@ class GlorotNormal(VarianceScaling): ([pdf](http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf)) """ + @deprecated_args(None, + "Call initializer instance with the dtype argument instead " + "of passing it to the constructor", + "dtype") def __init__(self, seed=None, dtype=dtypes.float32): super(GlorotNormal, self).__init__( scale=1.0, @@ -1263,7 +1316,7 @@ convolutional_orthogonal_3d = ConvolutionOrthogonal3D # pylint: enable=invalid-name -@tf_export("initializers.lecun_normal") +@tf_export(v1=["initializers.lecun_normal"]) def lecun_normal(seed=None): """LeCun normal initializer. @@ -1279,7 +1332,7 @@ def lecun_normal(seed=None): References: - Self-Normalizing Neural Networks, - [Klambauer et al., 2017](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks) + [Klambauer et al., 2017](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks) # pylint: disable=line-too-long ([pdf](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks.pdf)) - Efficient Backprop, [Lecun et al., 1998](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf) @@ -1288,7 +1341,7 @@ def lecun_normal(seed=None): scale=1., mode="fan_in", distribution="truncated_normal", seed=seed) -@tf_export("initializers.lecun_uniform") +@tf_export(v1=["initializers.lecun_uniform"]) def lecun_uniform(seed=None): """LeCun uniform initializer. @@ -1304,7 +1357,7 @@ def lecun_uniform(seed=None): References: - Self-Normalizing Neural Networks, - [Klambauer et al., 2017](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks) + [Klambauer et al., 2017](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks) # pylint: disable=line-too-long ([pdf](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks.pdf)) - Efficient Backprop, [Lecun et al., 1998](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf) @@ -1313,7 +1366,7 @@ def lecun_uniform(seed=None): scale=1., mode="fan_in", distribution="uniform", seed=seed) -@tf_export("initializers.he_normal") +@tf_export(v1=["initializers.he_normal"]) def he_normal(seed=None): """He normal initializer. @@ -1328,14 +1381,15 @@ def he_normal(seed=None): An initializer. References: - [He et al., 2015](https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) + [He et al., 2015] + (https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) # pylint: disable=line-too-long ([pdf](https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/He_Delving_Deep_into_ICCV_2015_paper.pdf)) """ return VarianceScaling( scale=2., mode="fan_in", distribution="truncated_normal", seed=seed) -@tf_export("initializers.he_uniform") +@tf_export(v1=["initializers.he_uniform"]) def he_uniform(seed=None): """He uniform variance scaling initializer. @@ -1350,7 +1404,8 @@ def he_uniform(seed=None): An initializer. References: - [He et al., 2015](https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) + [He et al., 2015] + (https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) # pylint: disable=line-too-long ([pdf](https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/He_Delving_Deep_into_ICCV_2015_paper.pdf)) """ return VarianceScaling( diff --git a/tensorflow/python/ops/init_ops_test.py b/tensorflow/python/ops/init_ops_test.py index 1f22248004..b3cdec9dd4 100644 --- a/tensorflow/python/ops/init_ops_test.py +++ b/tensorflow/python/ops/init_ops_test.py @@ -24,13 +24,14 @@ from tensorflow.core.protobuf import config_pb2 from tensorflow.python.client import session from tensorflow.python.eager import context from tensorflow.python.framework import ops +from tensorflow.python.framework import test_util from tensorflow.python.ops import init_ops -from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables from tensorflow.python.platform import test +@test_util.run_all_in_graph_and_eager_modes class InitializersTest(test.TestCase): def _runner(self, @@ -40,13 +41,8 @@ class InitializersTest(test.TestCase): target_std=None, target_max=None, target_min=None): - variable = resource_variable_ops.ResourceVariable(init(shape)) - if context.executing_eagerly(): - output = variable.numpy() - else: - sess = ops.get_default_session() - self.evaluate(variable.initializer) - output = self.evaluate(variable) + output = self.evaluate(init(shape)) + self.assertEqual(output.shape, shape) lim = 3e-2 if target_std is not None: self.assertGreater(lim, abs(output.std() - target_std)) diff --git a/tensorflow/python/ops/init_ops_v2.py b/tensorflow/python/ops/init_ops_v2.py new file mode 100644 index 0000000000..4e614e0012 --- /dev/null +++ b/tensorflow/python/ops/init_ops_v2.py @@ -0,0 +1,764 @@ +# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Operations often used for initializing tensors. + +All variable initializers returned by functions in this file should have the +following signature: + +def _initializer(shape, dtype=dtypes.float32): + Args: + shape: List of `int` representing the shape of the output `Tensor`. Some + initializers may also be able to accept a `Tensor`. + dtype: (Optional) Type of the output `Tensor`. + Returns: + A `Tensor` of type `dtype` and `shape`. +""" +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import math + +import numpy as np + +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import gen_linalg_ops +from tensorflow.python.ops import linalg_ops_impl +from tensorflow.python.ops import math_ops +from tensorflow.python.ops import random_ops +from tensorflow.python.util.tf_export import tf_export + + +class Initializer(object): + """Initializer base class: all initializers inherit from this class. + """ + + def __call__(self, shape, dtype=None): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. If not provided will return tensor + of `tf.float32`. + """ + raise NotImplementedError + + def get_config(self): + """Returns the configuration of the initializer as a JSON-serializable dict. + + Returns: + A JSON-serializable Python dict. + """ + return {} + + @classmethod + def from_config(cls, config): + """Instantiates an initializer from a configuration dictionary. + + Example: + + ```python + initializer = RandomUniform(-1, 1) + config = initializer.get_config() + initializer = RandomUniform.from_config(config) + ``` + + Args: + config: A Python dictionary. + It will typically be the output of `get_config`. + + Returns: + An Initializer instance. + """ + config.pop("dtype", None) + return cls(**config) + + +@tf_export("zeros_initializer", v1=[]) +class Zeros(Initializer): + """Initializer that generates tensors initialized to 0.""" + + def __call__(self, shape, dtype=dtypes.float32): + dtype = dtypes.as_dtype(dtype) + return array_ops.zeros(shape, dtype) + + +@tf_export("ones_initializer", v1=[]) +class Ones(Initializer): + """Initializer that generates tensors initialized to 1.""" + + def __call__(self, shape, dtype=dtypes.float32): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. Only numeric or boolean dtypes are + supported. + + Raises: + ValuesError: If the dtype is not numeric or boolean. + """ + dtype = dtypes.as_dtype(dtype) + if not dtype.is_numpy_compatible or dtype == dtypes.string: + raise ValueError("Expected numeric or boolean dtype, got %s." % dtype) + return array_ops.ones(shape, dtype) + + +@tf_export("constant_initializer", v1=[]) +class Constant(Initializer): + """Initializer that generates tensors with constant values. + + The resulting tensor is populated with values of type `dtype`, as + specified by arguments `value` following the desired `shape` of the + new tensor (see examples below). + + The argument `value` can be a constant value, or a list of values of type + `dtype`. If `value` is a list, then the length of the list must be less + than or equal to the number of elements implied by the desired shape of the + tensor. In the case where the total number of elements in `value` is less + than the number of elements required by the tensor shape, the last element + in `value` will be used to fill the remaining entries. If the total number of + elements in `value` is greater than the number of elements required by the + tensor shape, the initializer will raise a `ValueError`. + + Args: + value: A Python scalar, list or tuple of values, or a N-dimensional numpy + array. All elements of the initialized variable will be set to the + corresponding value in the `value` argument. + + Raises: + TypeError: If the input `value` is not one of the expected types. + + Examples: + The following example can be rewritten using a numpy.ndarray instead + of the `value` list, even reshaped, as shown in the two commented lines + below the `value` list initialization. + + ```python + >>> import numpy as np + >>> import tensorflow as tf + + >>> value = [0, 1, 2, 3, 4, 5, 6, 7] + >>> # value = np.array(value) + >>> # value = value.reshape([2, 4]) + >>> init = tf.constant_initializer(value) + + >>> print('fitting shape:') + >>> with tf.Session(): + >>> x = tf.get_variable('x', shape=[2, 4], initializer=init) + >>> x.initializer.run() + >>> print(x.eval()) + + fitting shape: + [[ 0. 1. 2. 3.] + [ 4. 5. 6. 7.]] + + >>> print('larger shape:') + >>> with tf.Session(): + >>> x = tf.get_variable('x', shape=[3, 4], initializer=init) + >>> x.initializer.run() + >>> print(x.eval()) + + larger shape: + [[ 0. 1. 2. 3.] + [ 4. 5. 6. 7.] + [ 7. 7. 7. 7.]] + + >>> print('smaller shape:') + >>> with tf.Session(): + >>> x = tf.get_variable('x', shape=[2, 3], initializer=init) + + ValueError: Too many elements provided. Needed at most 6, but received 8 + ``` + """ + + def __init__(self, value=0): + if not (np.isscalar(value) or isinstance(value, (list, tuple, np.ndarray))): + raise TypeError( + "Invalid type for initial value: %s (expected Python scalar, list or " + "tuple of values, or numpy.ndarray)." % type(value)) + self.value = value + + def __call__(self, shape, dtype=None): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. If not provided the dtype of the + tensor created will be the type of the inital value. + + Raises: + TypeError: If the initializer cannot create a tensor of the requested + dtype. + """ + if dtype is not None: + dtype = dtypes.as_dtype(dtype) + return constant_op.constant( + self.value, dtype=dtype, shape=shape) + + def get_config(self): + return {"value": self.value} + + +@tf_export("random_uniform_initializer", v1=[]) +class RandomUniform(Initializer): + """Initializer that generates tensors with a uniform distribution. + + Args: + minval: A python scalar or a scalar tensor. Lower bound of the range + of random values to generate. + maxval: A python scalar or a scalar tensor. Upper bound of the range + of random values to generate. Defaults to 1 for float types. + seed: A Python integer. Used to create random seeds. See + `tf.set_random_seed` + for behavior. + """ + + def __init__(self, minval=-0.05, maxval=0.05, seed=None): + self.minval = minval + self.maxval = maxval + self.seed = seed + + def __call__(self, shape, dtype=dtypes.float32): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. Only floating point and integer + types are supported. + + Raises: + ValueError: If the dtype is not numeric. + """ + dtype = dtypes.as_dtype(dtype) + if not dtype.is_floating and not dtype.is_integer: + raise ValueError("Expected float or integer dtype, got %s." % dtype) + return random_ops.random_uniform( + shape, self.minval, self.maxval, dtype, seed=self.seed) + + def get_config(self): + return { + "minval": self.minval, + "maxval": self.maxval, + "seed": self.seed + } + + +@tf_export("random_normal_initializer", v1=[]) +class RandomNormal(Initializer): + """Initializer that generates tensors with a normal distribution. + + Args: + mean: a python scalar or a scalar tensor. Mean of the random values + to generate. + stddev: a python scalar or a scalar tensor. Standard deviation of the + random values to generate. + seed: A Python integer. Used to create random seeds. See + `tf.set_random_seed` + for behavior. + """ + + def __init__(self, mean=0.0, stddev=0.05, seed=None): + self.mean = mean + self.stddev = stddev + self.seed = seed + + def __call__(self, shape, dtype=dtypes.float32): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. Only floating point types are + supported. + + Raises: + ValueError: If the dtype is not floating point + """ + dtype = _assert_float_dtype(dtype) + return random_ops.random_normal( + shape, self.mean, self.stddev, dtype, seed=self.seed) + + def get_config(self): + return { + "mean": self.mean, + "stddev": self.stddev, + "seed": self.seed + } + + +class TruncatedNormal(Initializer): + """Initializer that generates a truncated normal distribution. + + These values are similar to values from a `random_normal_initializer` + except that values more than two standard deviations from the mean + are discarded and re-drawn. This is the recommended initializer for + neural network weights and filters. + + Args: + mean: a python scalar or a scalar tensor. Mean of the random values + to generate. + stddev: a python scalar or a scalar tensor. Standard deviation of the + random values to generate. + seed: A Python integer. Used to create random seeds. See + `tf.set_random_seed` + for behavior. + """ + + def __init__(self, mean=0.0, stddev=0.05, seed=None): + self.mean = mean + self.stddev = stddev + self.seed = seed + + def __call__(self, shape, dtype=dtypes.float32): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. Only floating point types are + supported. + + Raises: + ValueError: If the dtype is not floating point + """ + dtype = _assert_float_dtype(dtype) + return random_ops.truncated_normal( + shape, self.mean, self.stddev, dtype, seed=self.seed) + + def get_config(self): + return { + "mean": self.mean, + "stddev": self.stddev, + "seed": self.seed + } + + +class VarianceScaling(Initializer): + """Initializer capable of adapting its scale to the shape of weights tensors. + + With `distribution="truncated_normal" or "untruncated_normal"`, + samples are drawn from a truncated/untruncated normal + distribution with a mean of zero and a standard deviation (after truncation, + if used) `stddev = sqrt(scale / n)` + where n is: + - number of input units in the weight tensor, if mode = "fan_in" + - number of output units, if mode = "fan_out" + - average of the numbers of input and output units, if mode = "fan_avg" + + With `distribution="uniform"`, samples are drawn from a uniform distribution + within [-limit, limit], with `limit = sqrt(3 * scale / n)`. + + Args: + scale: Scaling factor (positive float). + mode: One of "fan_in", "fan_out", "fan_avg". + distribution: Random distribution to use. One of "truncated_normal", + "untruncated_normal" and "uniform". + seed: A Python integer. Used to create random seeds. See + `tf.set_random_seed` + for behavior. + + Raises: + ValueError: In case of an invalid value for the "scale", mode" or + "distribution" arguments. + """ + + def __init__(self, + scale=1.0, + mode="fan_in", + distribution="truncated_normal", + seed=None): + if scale <= 0.: + raise ValueError("`scale` must be positive float.") + if mode not in {"fan_in", "fan_out", "fan_avg"}: + raise ValueError("Invalid `mode` argument:", mode) + distribution = distribution.lower() + if distribution not in {"uniform", "truncated_normal", + "untruncated_normal"}: + raise ValueError("Invalid `distribution` argument:", distribution) + self.scale = scale + self.mode = mode + self.distribution = distribution + self.seed = seed + + def __call__(self, shape, dtype=dtypes.float32): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. Only floating point types are + supported. + + Raises: + ValueError: If the dtype is not floating point + """ + partition_info = None # Keeps logic so can be readded later if necessary + dtype = _assert_float_dtype(dtype) + scale = self.scale + scale_shape = shape + if partition_info is not None: + scale_shape = partition_info.full_shape + fan_in, fan_out = _compute_fans(scale_shape) + if self.mode == "fan_in": + scale /= max(1., fan_in) + elif self.mode == "fan_out": + scale /= max(1., fan_out) + else: + scale /= max(1., (fan_in + fan_out) / 2.) + if self.distribution == "truncated_normal": + # constant from scipy.stats.truncnorm.std(a=-2, b=2, loc=0., scale=1.) + stddev = math.sqrt(scale) / .87962566103423978 + return random_ops.truncated_normal( + shape, 0.0, stddev, dtype, seed=self.seed) + elif self.distribution == "untruncated_normal": + stddev = math.sqrt(scale) + return random_ops.random_normal( + shape, 0.0, stddev, dtype, seed=self.seed) + else: + limit = math.sqrt(3.0 * scale) + return random_ops.random_uniform( + shape, -limit, limit, dtype, seed=self.seed) + + def get_config(self): + return { + "scale": self.scale, + "mode": self.mode, + "distribution": self.distribution, + "seed": self.seed + } + + +class Orthogonal(Initializer): + """Initializer that generates an orthogonal matrix. + + If the shape of the tensor to initialize is two-dimensional, it is initialized + with an orthogonal matrix obtained from the QR decomposition of a matrix of + random numbers drawn from a normal distribution. + If the matrix has fewer rows than columns then the output will have orthogonal + rows. Otherwise, the output will have orthogonal columns. + + If the shape of the tensor to initialize is more than two-dimensional, + a matrix of shape `(shape[0] * ... * shape[n - 2], shape[n - 1])` + is initialized, where `n` is the length of the shape vector. + The matrix is subsequently reshaped to give a tensor of the desired shape. + + Args: + gain: multiplicative factor to apply to the orthogonal matrix + seed: A Python integer. Used to create random seeds. See + `tf.set_random_seed` + for behavior. + + References: + [Saxe et al., 2014](https://openreview.net/forum?id=_wzZwKpTDF_9C) + ([pdf](https://arxiv.org/pdf/1312.6120.pdf)) + """ + + def __init__(self, gain=1.0, seed=None): + self.gain = gain + self.seed = seed + + def __call__(self, shape, dtype=dtypes.float32): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. Only floating point types are + supported. + + Raises: + ValueError: If the dtype is not floating point or the input shape is not + valid. + """ + dtype = _assert_float_dtype(dtype) + # Check the shape + if len(shape) < 2: + raise ValueError("The tensor to initialize must be " + "at least two-dimensional") + # Flatten the input shape with the last dimension remaining + # its original shape so it works for conv2d + num_rows = 1 + for dim in shape[:-1]: + num_rows *= dim + num_cols = shape[-1] + flat_shape = (max(num_cols, num_rows), min(num_cols, num_rows)) + + # Generate a random matrix + a = random_ops.random_normal(flat_shape, dtype=dtype, seed=self.seed) + # Compute the qr factorization + q, r = gen_linalg_ops.qr(a, full_matrices=False) + # Make Q uniform + d = array_ops.diag_part(r) + q *= math_ops.sign(d) + if num_rows < num_cols: + q = array_ops.matrix_transpose(q) + return self.gain * array_ops.reshape(q, shape) + + def get_config(self): + return {"gain": self.gain, "seed": self.seed} + + +class Identity(Initializer): + """Initializer that generates the identity matrix. + + Only use for 2D matrices. + + Args: + gain: Multiplicative factor to apply to the identity matrix. + """ + + def __init__(self, gain=1.0): + self.gain = gain + + def __call__(self, shape, dtype=dtypes.float32): + """Returns a tensor object initialized as specified by the initializer. + + Args: + shape: Shape of the tensor. + dtype: Optional dtype of the tensor. Only floating point types are + supported. + + Raises: + ValueError: If the dtype is not floating point + """ + partition_info = None # Keeps logic so can be readded later if necessary + dtype = _assert_float_dtype(dtype) + full_shape = shape if partition_info is None else partition_info.full_shape + if len(full_shape) != 2: + raise ValueError( + "Identity matrix initializer can only be used for 2D matrices.") + initializer = linalg_ops_impl.eye(*full_shape, dtype=dtype) + if partition_info is not None: + initializer = array_ops.slice(initializer, partition_info.var_offset, + shape) + return self.gain * initializer + + def get_config(self): + return {"gain": self.gain} + + +class GlorotUniform(VarianceScaling): + """The Glorot uniform initializer, also called Xavier uniform initializer. + + It draws samples from a uniform distribution within [-limit, limit] + where `limit` is `sqrt(6 / (fan_in + fan_out))` + where `fan_in` is the number of input units in the weight tensor + and `fan_out` is the number of output units in the weight tensor. + + Args: + seed: A Python integer. Used to create random seeds. See + `tf.set_random_seed` + for behavior. + + References: + [Glorot et al., 2010](http://proceedings.mlr.press/v9/glorot10a.html) + ([pdf](http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf)) + """ + + def __init__(self, seed=None): + super(GlorotUniform, self).__init__( + scale=1.0, + mode="fan_avg", + distribution="uniform", + seed=seed) + + def get_config(self): + return {"seed": self.seed} + + +class GlorotNormal(VarianceScaling): + """The Glorot normal initializer, also called Xavier normal initializer. + + It draws samples from a truncated normal distribution centered on 0 + with `stddev = sqrt(2 / (fan_in + fan_out))` + where `fan_in` is the number of input units in the weight tensor + and `fan_out` is the number of output units in the weight tensor. + + Args: + seed: A Python integer. Used to create random seeds. See + `tf.set_random_seed` for behavior. + + References: + [Glorot et al., 2010](http://proceedings.mlr.press/v9/glorot10a.html) + ([pdf](http://jmlr.org/proceedings/papers/v9/glorot10a/glorot10a.pdf)) + """ + + def __init__(self, seed=None): + super(GlorotNormal, self).__init__( + scale=1.0, + mode="fan_avg", + distribution="truncated_normal", + seed=seed) + + def get_config(self): + return {"seed": self.seed, "dtype": self.dtype.name} + + +# Aliases. + +# pylint: disable=invalid-name +zeros_initializer = Zeros +ones_initializer = Ones +constant_initializer = Constant +random_uniform_initializer = RandomUniform +random_normal_initializer = RandomNormal +truncated_normal_initializer = TruncatedNormal +variance_scaling_initializer = VarianceScaling +glorot_uniform_initializer = GlorotUniform +glorot_normal_initializer = GlorotNormal +orthogonal_initializer = Orthogonal +identity_initializer = Identity +# pylint: enable=invalid-name + + +def lecun_normal(seed=None): + """LeCun normal initializer. + + It draws samples from a truncated normal distribution centered on 0 + with `stddev = sqrt(1 / fan_in)` + where `fan_in` is the number of input units in the weight tensor. + + Arguments: + seed: A Python integer. Used to seed the random generator. + + Returns: + An initializer. + + References: + - Self-Normalizing Neural Networks, + [Klambauer et al., 2017] + (https://papers.nips.cc/paper/6698-self-normalizing-neural-networks) + ([pdf] + (https://papers.nips.cc/paper/6698-self-normalizing-neural-networks.pdf)) + - Efficient Backprop, + [Lecun et al., 1998](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf) + """ + return VarianceScaling( + scale=1., mode="fan_in", distribution="truncated_normal", seed=seed) + + +def lecun_uniform(seed=None): + """LeCun uniform initializer. + + It draws samples from a uniform distribution within [-limit, limit] + where `limit` is `sqrt(3 / fan_in)` + where `fan_in` is the number of input units in the weight tensor. + + Arguments: + seed: A Python integer. Used to seed the random generator. + + Returns: + An initializer. + + References: + - Self-Normalizing Neural Networks, + [Klambauer et al., 2017](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks) # pylint: disable=line-too-long + ([pdf](https://papers.nips.cc/paper/6698-self-normalizing-neural-networks.pdf)) + - Efficient Backprop, + [Lecun et al., 1998](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf) + """ + return VarianceScaling( + scale=1., mode="fan_in", distribution="uniform", seed=seed) + + +def he_normal(seed=None): + """He normal initializer. + + It draws samples from a truncated normal distribution centered on 0 + with `stddev = sqrt(2 / fan_in)` + where `fan_in` is the number of input units in the weight tensor. + + Arguments: + seed: A Python integer. Used to seed the random generator. + + Returns: + An initializer. + + References: + [He et al., 2015](https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) # pylint: disable=line-too-long + ([pdf](https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/He_Delving_Deep_into_ICCV_2015_paper.pdf)) + """ + return VarianceScaling( + scale=2., mode="fan_in", distribution="truncated_normal", seed=seed) + + +def he_uniform(seed=None): + """He uniform variance scaling initializer. + + It draws samples from a uniform distribution within [-limit, limit] + where `limit` is `sqrt(6 / fan_in)` + where `fan_in` is the number of input units in the weight tensor. + + Arguments: + seed: A Python integer. Used to seed the random generator. + + Returns: + An initializer. + + References: + [He et al., 2015](https://www.cv-foundation.org/openaccess/content_iccv_2015/html/He_Delving_Deep_into_ICCV_2015_paper.html) # pylint: disable=line-too-long + ([pdf](https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/He_Delving_Deep_into_ICCV_2015_paper.pdf)) + """ + return VarianceScaling( + scale=2., mode="fan_in", distribution="uniform", seed=seed) + + +# Utility functions. + + +def _compute_fans(shape): + """Computes the number of input and output units for a weight shape. + + Args: + shape: Integer shape tuple or TF tensor shape. + + Returns: + A tuple of scalars (fan_in, fan_out). + """ + if len(shape) < 1: # Just to avoid errors for constants. + fan_in = fan_out = 1 + elif len(shape) == 1: + fan_in = fan_out = shape[0] + elif len(shape) == 2: + fan_in = shape[0] + fan_out = shape[1] + else: + # Assuming convolution kernels (2D, 3D, or more). + # kernel shape: (..., input_depth, depth) + receptive_field_size = 1. + for dim in shape[:-2]: + receptive_field_size *= dim + fan_in = shape[-2] * receptive_field_size + fan_out = shape[-1] * receptive_field_size + return fan_in, fan_out + + +def _assert_float_dtype(dtype): + """Validate and return floating point type based on `dtype`. + + `dtype` must be a floating point type. + + Args: + dtype: The data type to validate. + + Returns: + Validated type. + + Raises: + ValueError: if `dtype` is not a floating point type. + """ + dtype = dtypes.as_dtype(dtype) + if not dtype.is_floating: + raise ValueError("Expected floating point type, got %s." % dtype) + return dtype diff --git a/tensorflow/python/ops/init_ops_v2_test.py b/tensorflow/python/ops/init_ops_v2_test.py new file mode 100644 index 0000000000..fceba1d04a --- /dev/null +++ b/tensorflow/python/ops/init_ops_v2_test.py @@ -0,0 +1,512 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for initializers in init_ops_v2.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import numpy as np + +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import dtypes +from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework import test_util +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import init_ops_v2 +from tensorflow.python.ops import random_ops +from tensorflow.python.ops import variables +from tensorflow.python.platform import test + + +class InitializersTest(test.TestCase): + + def _identical_test(self, + init1, + init2, + assertion, + shape=None, + dtype=dtypes.float32): + if shape is None: + shape = [100] + t1 = self.evaluate(init1(shape, dtype)) + t2 = self.evaluate(init2(shape, dtype)) + self.assertEqual(tensor_shape.as_shape(shape), t1.shape) + self.assertEqual(tensor_shape.as_shape(shape), t2.shape) + self.assertEqual(assertion, np.allclose(t1, t2, rtol=1e-15, atol=1e-15)) + + def _duplicated_test(self, + init, + shape=None, + dtype=dtypes.float32): + if shape is None: + shape = [100] + t1 = self.evaluate(init(shape, dtype)) + t2 = self.evaluate(init(shape, dtype)) + self.assertEqual(tensor_shape.as_shape(shape), t1.shape) + self.assertEqual(tensor_shape.as_shape(shape), t2.shape) + self.assertFalse(np.allclose(t1, t2, rtol=1e-15, atol=1e-15)) + + def _range_test(self, + init, + shape, + target_mean=None, + target_std=None, + target_max=None, + target_min=None): + output = self.evaluate(init(shape)) + self.assertEqual(output.shape, shape) + lim = 3e-2 + if target_std is not None: + self.assertGreater(lim, abs(output.std() - target_std)) + if target_mean is not None: + self.assertGreater(lim, abs(output.mean() - target_mean)) + if target_max is not None: + self.assertGreater(lim, abs(output.max() - target_max)) + if target_min is not None: + self.assertGreater(lim, abs(output.min() - target_min)) + + +class ConstantInitializersTest(InitializersTest): + + @test_util.run_in_graph_and_eager_modes + def testZeros(self): + self._range_test(init_ops_v2.Zeros(), shape=(4, 5), + target_mean=0., target_max=0.) + + @test_util.run_in_graph_and_eager_modes + def testOnes(self): + self._range_test(init_ops_v2.Ones(), shape=(4, 5), + target_mean=1., target_max=1.) + + @test_util.run_in_graph_and_eager_modes + def testConstantInt(self): + self._range_test( + init_ops_v2.Constant(2), + shape=(5, 6, 4), + target_mean=2, + target_max=2, + target_min=2) + + @test_util.run_in_graph_and_eager_modes + def testConstantTuple(self): + init = init_ops_v2.constant_initializer((10, 20, 30)) + tensor = init(shape=[3]) + self.assertAllEqual(self.evaluate(tensor), [10, 20, 30]) + self.assertEqual(tensor.shape, [3]) + + @test_util.run_in_graph_and_eager_modes + def testConstantInvalidValue(self): + c = constant_op.constant([1.0, 2.0, 3.0]) + with self.assertRaisesRegexp( + TypeError, r"Invalid type for initial value: .*Tensor.*"): + init_ops_v2.constant_initializer(c) + v = variables.Variable([3.0, 2.0, 1.0]) + with self.assertRaisesRegexp( + TypeError, r"Invalid type for initial value: .*Variable.*"): + init_ops_v2.constant_initializer(v) + + def _testNDimConstantInitializer(self, value, shape, expected): + with test_util.use_gpu(): + init = init_ops_v2.constant_initializer(value) + x = init(shape) + + actual = self.evaluate(array_ops.reshape(x, [-1])) + self.assertEqual(len(actual), len(expected)) + for a, e in zip(actual, expected): + self.assertEqual(a, e) + + @test_util.run_in_graph_and_eager_modes + def testNDimConstantInitializer(self): + value = [0, 1, 2, 3, 4, 5] + shape = [2, 3] + expected = list(value) + + self._testNDimConstantInitializer(value, shape, expected) + self._testNDimConstantInitializer(np.asarray(value), shape, expected) + self._testNDimConstantInitializer(np.asarray(value).reshape(tuple(shape)), + shape, expected) + + def _testNDimConstantInitializerIncorrectNumberValues(self, value, shape): + with test_util.use_gpu(): + init = init_ops_v2.constant_initializer(value) + self.assertRaises(TypeError, + init, + shape=shape) + + @test_util.run_in_graph_and_eager_modes + def testNDimConstantInitializerIncorrectNumberValues(self): + value = [0, 1, 2, 3, 4, 5] + + for shape in [[2, 4], [2, 2]]: + self._testNDimConstantInitializerIncorrectNumberValues(value, shape) + self._testNDimConstantInitializerIncorrectNumberValues(np.asarray(value), + shape) + self._testNDimConstantInitializerIncorrectNumberValues( + np.asarray(value).reshape(tuple([2, 3])), shape) + + +class RandomUniformInitializerTest(InitializersTest): + + @test_util.run_in_graph_and_eager_modes + def testRangeInitializer(self): + shape = (9, 6, 7) + self._range_test( + init_ops_v2.RandomUniform(minval=-1, maxval=1, seed=124), + shape, + target_mean=0., + target_max=1, + target_min=-1) + + @test_util.run_in_graph_and_eager_modes + def testInitializerIdentical(self): + self.skipTest("Doesn't work without the graphs") + init1 = init_ops_v2.RandomUniform(0, 7, seed=1) + init2 = init_ops_v2.RandomUniform(0, 7, seed=1) + self._identical_test(init1, init2, True) + + @test_util.run_in_graph_and_eager_modes + def testInitializerDifferent(self): + init1 = init_ops_v2.RandomUniform(0, 7, seed=1) + init2 = init_ops_v2.RandomUniform(0, 7, seed=2) + self._identical_test(init1, init2, False) + + @test_util.run_in_graph_and_eager_modes + def testDuplicatedInitializer(self): + init = init_ops_v2.RandomUniform(0.0, 1.0) + self._duplicated_test(init) + + +class RandomNormalInitializerTest(InitializersTest): + + @test_util.run_in_graph_and_eager_modes + def testRangeInitializer(self): + self._range_test( + init_ops_v2.RandomNormal(mean=0, stddev=1, seed=153), + shape=(8, 12, 99), + target_mean=0., + target_std=1) + + @test_util.run_in_graph_and_eager_modes + def testInitializerIdentical(self): + self.skipTest("Doesn't work without the graphs") + init1 = init_ops_v2.RandomNormal(0, 7, seed=1) + init2 = init_ops_v2.RandomNormal(0, 7, seed=1) + self._identical_test(init1, init2, True) + + @test_util.run_in_graph_and_eager_modes + def testInitializerDifferent(self): + init1 = init_ops_v2.RandomNormal(0, 7, seed=1) + init2 = init_ops_v2.RandomNormal(0, 7, seed=2) + self._identical_test(init1, init2, False) + + @test_util.run_in_graph_and_eager_modes + def testDuplicatedInitializer(self): + init = init_ops_v2.RandomNormal(0.0, 1.0) + self._duplicated_test(init) + + +class TruncatedNormalInitializerTest(InitializersTest): + + @test_util.run_in_graph_and_eager_modes + def testRangeInitializer(self): + self._range_test( + init_ops_v2.TruncatedNormal(mean=0, stddev=1, seed=126), + shape=(12, 99, 7), + target_mean=0., + target_max=2, + target_min=-2) + + @test_util.run_in_graph_and_eager_modes + def testInitializerIdentical(self): + self.skipTest("Not seeming to work in Eager mode") + init1 = init_ops_v2.TruncatedNormal(0.0, 1.0, seed=1) + init2 = init_ops_v2.TruncatedNormal(0.0, 1.0, seed=1) + self._identical_test(init1, init2, True) + + @test_util.run_in_graph_and_eager_modes + def testInitializerDifferent(self): + init1 = init_ops_v2.TruncatedNormal(0.0, 1.0, seed=1) + init2 = init_ops_v2.TruncatedNormal(0.0, 1.0, seed=2) + self._identical_test(init1, init2, False) + + @test_util.run_in_graph_and_eager_modes + def testDuplicatedInitializer(self): + init = init_ops_v2.TruncatedNormal(0.0, 1.0) + self._duplicated_test(init) + + def testInvalidDataType(self): + init = init_ops_v2.TruncatedNormal(0.0, 1.0) + with self.assertRaises(ValueError): + init([1], dtype=dtypes.int32) + + +class VarianceScalingInitializerTest(InitializersTest): + + @test_util.run_in_graph_and_eager_modes + def testTruncatedNormalDistribution(self): + shape = [100, 100] + expect_mean = 0. + expect_var = 1. / shape[0] + init = init_ops_v2.VarianceScaling(distribution="truncated_normal") + + with test_util.use_gpu(), test.mock.patch.object( + random_ops, "truncated_normal", + wraps=random_ops.truncated_normal) as mock_truncated_normal: + x = self.evaluate(init(shape)) + self.assertTrue(mock_truncated_normal.called) + + self.assertNear(np.mean(x), expect_mean, err=1e-2) + self.assertNear(np.var(x), expect_var, err=1e-2) + + @test_util.run_in_graph_and_eager_modes + def testNormalDistribution(self): + shape = [100, 100] + expect_mean = 0. + expect_var = 1. / shape[0] + init = init_ops_v2.VarianceScaling(distribution="truncated_normal") + + with test_util.use_gpu(), test.mock.patch.object( + random_ops, "truncated_normal", + wraps=random_ops.truncated_normal) as mock_truncated_normal: + x = self.evaluate(init(shape)) + self.assertTrue(mock_truncated_normal.called) + + self.assertNear(np.mean(x), expect_mean, err=1e-2) + self.assertNear(np.var(x), expect_var, err=1e-2) + + @test_util.run_in_graph_and_eager_modes + def testUntruncatedNormalDistribution(self): + shape = [100, 100] + expect_mean = 0. + expect_var = 1. / shape[0] + init = init_ops_v2.VarianceScaling( + distribution="untruncated_normal") + + with test_util.use_gpu(), test.mock.patch.object( + random_ops, "random_normal", + wraps=random_ops.random_normal) as mock_random_normal: + x = self.evaluate(init(shape)) + self.assertTrue(mock_random_normal.called) + + self.assertNear(np.mean(x), expect_mean, err=1e-2) + self.assertNear(np.var(x), expect_var, err=1e-2) + + @test_util.run_in_graph_and_eager_modes + def testUniformDistribution(self): + shape = [100, 100] + expect_mean = 0. + expect_var = 1. / shape[0] + init = init_ops_v2.VarianceScaling(distribution="uniform") + + with test_util.use_gpu(): + x = self.evaluate(init(shape)) + + self.assertNear(np.mean(x), expect_mean, err=1e-2) + self.assertNear(np.var(x), expect_var, err=1e-2) + + +class OrthogonalInitializerTest(InitializersTest): + + @test_util.run_in_graph_and_eager_modes + def testRangeInitializer(self): + self._range_test(init_ops_v2.Orthogonal(seed=123), shape=(20, 20), + target_mean=0.) + + @test_util.run_in_graph_and_eager_modes + def testInitializerIdentical(self): + self.skipTest("Doesn't work without the graphs") + init1 = init_ops_v2.Orthogonal(seed=1) + init2 = init_ops_v2.Orthogonal(seed=1) + self._identical_test(init1, init2, True, (10, 10)) + + @test_util.run_in_graph_and_eager_modes + def testInitializerDifferent(self): + init1 = init_ops_v2.Orthogonal(seed=1) + init2 = init_ops_v2.Orthogonal(seed=2) + self._identical_test(init1, init2, False, (10, 10)) + + @test_util.run_in_graph_and_eager_modes + def testDuplicatedInitializer(self): + init = init_ops_v2.Orthogonal() + self._duplicated_test(init, (10, 10)) + + @test_util.run_in_graph_and_eager_modes + def testInvalidDataType(self): + init = init_ops_v2.Orthogonal() + self.assertRaises(ValueError, init, shape=(10, 10), dtype=dtypes.string) + + @test_util.run_in_graph_and_eager_modes + def testInvalidShape(self): + init = init_ops_v2.Orthogonal() + with test_util.use_gpu(): + self.assertRaises(ValueError, init, shape=[5]) + + @test_util.run_in_graph_and_eager_modes + def testGain(self): + self.skipTest("Doesn't work without the graphs") + init1 = init_ops_v2.Orthogonal(seed=1) + init2 = init_ops_v2.Orthogonal(gain=3.14, seed=1) + with test_util.use_gpu(): + t1 = self.evaluate(init1(shape=(10, 10))) + t2 = self.evaluate(init2(shape=(10, 10))) + self.assertAllClose(t1, t2 / 3.14) + + @test_util.run_in_graph_and_eager_modes + def testShapesValues(self): + for shape in [(10, 10), (10, 9, 8), (100, 5, 5), (50, 40), (40, 50)]: + init = init_ops_v2.Orthogonal() + tol = 1e-5 + with test_util.use_gpu(): + # Check the shape + t = self.evaluate(init(shape)) + self.assertAllEqual(shape, t.shape) + # Check orthogonality by computing the inner product + t = t.reshape((np.prod(t.shape[:-1]), t.shape[-1])) + if t.shape[0] > t.shape[1]: + self.assertAllClose( + np.dot(t.T, t), np.eye(t.shape[1]), rtol=tol, atol=tol) + else: + self.assertAllClose( + np.dot(t, t.T), np.eye(t.shape[0]), rtol=tol, atol=tol) + + +class IdentityInitializerTest(InitializersTest): + + @test_util.run_in_graph_and_eager_modes + def testRange(self): + with self.assertRaises(ValueError): + shape = (3, 4, 5) + self._range_test( + init_ops_v2.Identity(), + shape=shape, + target_mean=1. / shape[0], + target_max=1.) + + shape = (3, 3) + self._range_test( + init_ops_v2.Identity(), + shape=shape, + target_mean=1. / shape[0], + target_max=1.) + + @test_util.run_in_graph_and_eager_modes + def testInvalidDataType(self): + init = init_ops_v2.Identity() + self.assertRaises(ValueError, init, shape=[10, 5], dtype=dtypes.int32) + + @test_util.run_in_graph_and_eager_modes + def testInvalidShape(self): + init = init_ops_v2.Identity() + with test_util.use_gpu(): + self.assertRaises(ValueError, init, shape=[5, 7, 7]) + self.assertRaises(ValueError, init, shape=[5]) + self.assertRaises(ValueError, init, shape=[]) + + @test_util.run_in_graph_and_eager_modes + def testNonSquare(self): + init = init_ops_v2.Identity() + shape = (10, 5) + with test_util.use_gpu(): + self.assertAllClose(self.evaluate(init(shape)), np.eye(*shape)) + + @test_util.run_in_graph_and_eager_modes + def testGain(self): + shape = (10, 10) + for dtype in [dtypes.float32, dtypes.float64]: + init_default = init_ops_v2.Identity() + init_custom = init_ops_v2.Identity(gain=0.9) + with test_util.use_gpu(): + self.assertAllClose(self.evaluate(init_default(shape, dtype=dtype)), + np.eye(*shape)) + with test_util.use_gpu(): + self.assertAllClose(self.evaluate(init_custom(shape, dtype=dtype)), + np.eye(*shape) * 0.9) + + +class GlorotInitializersTest(InitializersTest): + + @test_util.run_in_graph_and_eager_modes + def testGlorotUniform(self): + shape = (5, 6, 4, 2) + fan_in, fan_out = init_ops_v2._compute_fans(shape) + std = np.sqrt(2. / (fan_in + fan_out)) + self._range_test( + init_ops_v2.GlorotUniform(seed=123), + shape, + target_mean=0., + target_std=std) + + @test_util.run_in_graph_and_eager_modes + def test_GlorotNormal(self): + shape = (5, 6, 4, 2) + fan_in, fan_out = init_ops_v2._compute_fans(shape) + std = np.sqrt(2. / (fan_in + fan_out)) + self._range_test( + init_ops_v2.GlorotNormal(seed=123), + shape, + target_mean=0., + target_std=std) + + +class MethodInitializers(InitializersTest): + + @test_util.run_in_graph_and_eager_modes + def testLecunUniform(self): + shape = (5, 6, 4, 2) + fan_in, _ = init_ops_v2._compute_fans(shape) + std = np.sqrt(1. / fan_in) + self._range_test( + init_ops_v2.lecun_uniform(seed=123), + shape, + target_mean=0., + target_std=std) + + @test_util.run_in_graph_and_eager_modes + def testHeUniform(self): + shape = (5, 6, 4, 2) + fan_in, _ = init_ops_v2._compute_fans(shape) + std = np.sqrt(2. / fan_in) + self._range_test( + init_ops_v2.he_uniform(seed=123), + shape, + target_mean=0., + target_std=std) + + @test_util.run_in_graph_and_eager_modes + def testLecunNormal(self): + shape = (5, 6, 4, 2) + fan_in, _ = init_ops_v2._compute_fans(shape) + std = np.sqrt(1. / fan_in) + self._range_test( + init_ops_v2.lecun_normal(seed=123), + shape, + target_mean=0., + target_std=std) + + @test_util.run_in_graph_and_eager_modes + def testHeNormal(self): + shape = (5, 6, 4, 2) + fan_in, _ = init_ops_v2._compute_fans(shape) + std = np.sqrt(2. / fan_in) + self._range_test( + init_ops_v2.he_normal(seed=123), + shape, + target_mean=0., + target_std=std) + + +if __name__ == "__main__": + test.main() diff --git a/tensorflow/python/tools/api/generator/api_init_files.bzl b/tensorflow/python/tools/api/generator/api_init_files.bzl index 8a3d6b31fd..f496e90dfa 100644 --- a/tensorflow/python/tools/api/generator/api_init_files.bzl +++ b/tensorflow/python/tools/api/generator/api_init_files.bzl @@ -22,7 +22,6 @@ TENSORFLOW_API_INIT_FILES = [ "image/__init__.py", "io/__init__.py", "queue/__init__.py", - "initializers/__init__.py", "linalg/__init__.py", "lite/__init__.py", "lite/constants/__init__.py", diff --git a/tensorflow/tools/api/golden/v2/tensorflow.constant_initializer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.constant_initializer.pbtxt index 00ec669b16..437131abb2 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.constant_initializer.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.constant_initializer.pbtxt @@ -1,11 +1,11 @@ path: "tensorflow.constant_initializer" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'value\', \'dtype\', \'verify_shape\'], varargs=None, keywords=None, defaults=[\'0\', \"\", \'False\'], " + argspec: "args=[\'self\', \'value\'], varargs=None, keywords=None, defaults=[\'0\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.glorot_uniform_initializer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.glorot_uniform_initializer.pbtxt deleted file mode 100644 index bb8540d0fd..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.glorot_uniform_initializer.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.glorot_uniform_initializer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.constant.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.constant.pbtxt deleted file mode 100644 index 607a5aae21..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.constant.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.constant" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'value\', \'dtype\', \'verify_shape\'], varargs=None, keywords=None, defaults=[\'0\', \"\", \'False\'], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.glorot_normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.glorot_normal.pbtxt deleted file mode 100644 index 4a81e52df9..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.glorot_normal.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.initializers.glorot_normal" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.glorot_uniform.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.glorot_uniform.pbtxt deleted file mode 100644 index 815dc81dff..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.glorot_uniform.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.initializers.glorot_uniform" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.identity.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.identity.pbtxt deleted file mode 100644 index 37fcab9599..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.identity.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.identity" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'gain\', \'dtype\'], varargs=None, keywords=None, defaults=[\'1.0\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.ones.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.ones.pbtxt deleted file mode 100644 index 18481d4815..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.ones.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.ones" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'dtype\'], varargs=None, keywords=None, defaults=[\"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.orthogonal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.orthogonal.pbtxt deleted file mode 100644 index ff64efd60c..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.orthogonal.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.orthogonal" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'gain\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.pbtxt deleted file mode 100644 index e3c63fe737..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.pbtxt +++ /dev/null @@ -1,67 +0,0 @@ -path: "tensorflow.initializers" -tf_module { - member { - name: "constant" - mtype: "" - } - member { - name: "glorot_normal" - mtype: "" - } - member { - name: "glorot_uniform" - mtype: "" - } - member { - name: "identity" - mtype: "" - } - member { - name: "ones" - mtype: "" - } - member { - name: "orthogonal" - mtype: "" - } - member { - name: "random_normal" - mtype: "" - } - member { - name: "random_uniform" - mtype: "" - } - member { - name: "truncated_normal" - mtype: "" - } - member { - name: "uniform_unit_scaling" - mtype: "" - } - member { - name: "variance_scaling" - mtype: "" - } - member { - name: "zeros" - mtype: "" - } - member_method { - name: "he_normal" - argspec: "args=[\'seed\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "he_uniform" - argspec: "args=[\'seed\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "lecun_normal" - argspec: "args=[\'seed\'], varargs=None, keywords=None, defaults=[\'None\'], " - } - member_method { - name: "lecun_uniform" - argspec: "args=[\'seed\'], varargs=None, keywords=None, defaults=[\'None\'], " - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.random_normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.random_normal.pbtxt deleted file mode 100644 index 133e61c1d9..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.random_normal.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.random_normal" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0.0\', \'1.0\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.random_uniform.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.random_uniform.pbtxt deleted file mode 100644 index 0cfa0080f5..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.random_uniform.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.random_uniform" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'minval\', \'maxval\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0\', \'None\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.truncated_normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.truncated_normal.pbtxt deleted file mode 100644 index 730390fba2..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.truncated_normal.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.truncated_normal" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0.0\', \'1.0\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.uniform_unit_scaling.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.uniform_unit_scaling.pbtxt deleted file mode 100644 index 13295ef375..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.uniform_unit_scaling.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.uniform_unit_scaling" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'factor\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.variance_scaling.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.variance_scaling.pbtxt deleted file mode 100644 index 86340913e2..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.variance_scaling.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.variance_scaling" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'scale\', \'mode\', \'distribution\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'1.0\', \'fan_in\', \'truncated_normal\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.initializers.zeros.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.initializers.zeros.pbtxt deleted file mode 100644 index 7df4237bb6..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.initializers.zeros.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.initializers.zeros" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'dtype\'], varargs=None, keywords=None, defaults=[\"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-constant.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-constant.pbtxt index cbaba78ed5..71b5acc38f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-constant.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-constant.pbtxt @@ -1,11 +1,11 @@ path: "tensorflow.keras.initializers.Constant" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'value\', \'dtype\', \'verify_shape\'], varargs=None, keywords=None, defaults=[\'0\', \"\", \'False\'], " + argspec: "args=[\'self\', \'value\'], varargs=None, keywords=None, defaults=[\'0\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-glorot-normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-glorot-normal.pbtxt new file mode 100644 index 0000000000..edff37e3a1 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-glorot-normal.pbtxt @@ -0,0 +1,19 @@ +path: "tensorflow.keras.initializers.GlorotNormal" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-glorot-uniform.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-glorot-uniform.pbtxt new file mode 100644 index 0000000000..bc685ce0d5 --- /dev/null +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-glorot-uniform.pbtxt @@ -0,0 +1,19 @@ +path: "tensorflow.keras.initializers.GlorotUniform" +tf_class { + is_instance: "" + is_instance: "" + is_instance: "" + is_instance: "" + member_method { + name: "__init__" + argspec: "args=[\'self\', \'seed\'], varargs=None, keywords=None, defaults=[\'None\'], " + } + member_method { + name: "from_config" + argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" + } + member_method { + name: "get_config" + argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" + } +} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-identity.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-identity.pbtxt index a5f7f348de..e0f0f3a93d 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-identity.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-identity.pbtxt @@ -1,11 +1,11 @@ path: "tensorflow.keras.initializers.Identity" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'gain\', \'dtype\'], varargs=None, keywords=None, defaults=[\'1.0\', \"\"], " + argspec: "args=[\'self\', \'gain\'], varargs=None, keywords=None, defaults=[\'1.0\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-initializer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-initializer.pbtxt index 8f10d1698e..ae5ea9e48c 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-initializer.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-initializer.pbtxt @@ -1,6 +1,6 @@ path: "tensorflow.keras.initializers.Initializer" tf_class { - is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-ones.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-ones.pbtxt index 2fbfa774f8..57c0b0917d 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-ones.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-ones.pbtxt @@ -1,11 +1,10 @@ path: "tensorflow.keras.initializers.Ones" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'dtype\'], varargs=None, keywords=None, defaults=[\"\"], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-orthogonal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-orthogonal.pbtxt index 874d320d73..b24844fa35 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-orthogonal.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-orthogonal.pbtxt @@ -1,11 +1,11 @@ path: "tensorflow.keras.initializers.Orthogonal" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'gain\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \"\"], " + argspec: "args=[\'self\', \'gain\', \'seed\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-random-normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-random-normal.pbtxt index 26784ce55d..0753827aa6 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-random-normal.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-random-normal.pbtxt @@ -1,12 +1,11 @@ path: "tensorflow.keras.initializers.RandomNormal" tf_class { - is_instance: "" - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0.0\', \'0.05\', \'None\', \"\"], " + argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\'], varargs=None, keywords=None, defaults=[\'0.0\', \'0.05\', \'None\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-random-uniform.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-random-uniform.pbtxt index 4110bda5f6..280b0a0243 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-random-uniform.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-random-uniform.pbtxt @@ -1,12 +1,11 @@ path: "tensorflow.keras.initializers.RandomUniform" tf_class { - is_instance: "" - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'minval\', \'maxval\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'-0.05\', \'0.05\', \'None\', \"\"], " + argspec: "args=[\'self\', \'minval\', \'maxval\', \'seed\'], varargs=None, keywords=None, defaults=[\'-0.05\', \'0.05\', \'None\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-truncated-normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-truncated-normal.pbtxt index 0451d0d73a..4076aa595f 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-truncated-normal.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-truncated-normal.pbtxt @@ -1,12 +1,11 @@ path: "tensorflow.keras.initializers.TruncatedNormal" tf_class { - is_instance: "" - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0.0\', \'0.05\', \'None\', \"\"], " + argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\'], varargs=None, keywords=None, defaults=[\'0.0\', \'0.05\', \'None\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-variance-scaling.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-variance-scaling.pbtxt index 03f4064b9e..a68219def6 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-variance-scaling.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-variance-scaling.pbtxt @@ -1,11 +1,11 @@ path: "tensorflow.keras.initializers.VarianceScaling" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'scale\', \'mode\', \'distribution\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'1.0\', \'fan_in\', \'truncated_normal\', \'None\', \"\"], " + argspec: "args=[\'self\', \'scale\', \'mode\', \'distribution\', \'seed\'], varargs=None, keywords=None, defaults=[\'1.0\', \'fan_in\', \'truncated_normal\', \'None\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-zeros.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-zeros.pbtxt index b6ab68e5be..129fa18c61 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-zeros.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.-zeros.pbtxt @@ -1,11 +1,10 @@ path: "tensorflow.keras.initializers.Zeros" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'dtype\'], varargs=None, keywords=None, defaults=[\"\"], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.constant.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.constant.pbtxt deleted file mode 100644 index bddc37b907..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.constant.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.keras.initializers.constant" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'value\', \'dtype\', \'verify_shape\'], varargs=None, keywords=None, defaults=[\'0\', \"\", \'False\'], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.glorot_normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.glorot_normal.pbtxt deleted file mode 100644 index ef0815972d..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.glorot_normal.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.keras.initializers.glorot_normal" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.glorot_uniform.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.glorot_uniform.pbtxt deleted file mode 100644 index 439b5ada9b..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.glorot_uniform.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.keras.initializers.glorot_uniform" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.identity.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.identity.pbtxt deleted file mode 100644 index a4c5a61490..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.identity.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.keras.initializers.identity" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'gain\', \'dtype\'], varargs=None, keywords=None, defaults=[\'1.0\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.normal.pbtxt deleted file mode 100644 index 8d0b5c242b..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.normal.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.keras.initializers.normal" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0.0\', \'0.05\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.ones.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.ones.pbtxt deleted file mode 100644 index a89f78d1e1..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.ones.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.keras.initializers.ones" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'dtype\'], varargs=None, keywords=None, defaults=[\"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.orthogonal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.orthogonal.pbtxt deleted file mode 100644 index ee1e9bbae2..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.orthogonal.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.keras.initializers.orthogonal" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'gain\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'1.0\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.pbtxt index 1540c2915b..7412cd1305 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.pbtxt @@ -4,6 +4,14 @@ tf_module { name: "Constant" mtype: "" } + member { + name: "GlorotNormal" + mtype: "" + } + member { + name: "GlorotUniform" + mtype: "" + } member { name: "Identity" mtype: "" @@ -40,54 +48,6 @@ tf_module { name: "Zeros" mtype: "" } - member { - name: "constant" - mtype: "" - } - member { - name: "glorot_normal" - mtype: "" - } - member { - name: "glorot_uniform" - mtype: "" - } - member { - name: "identity" - mtype: "" - } - member { - name: "normal" - mtype: "" - } - member { - name: "ones" - mtype: "" - } - member { - name: "orthogonal" - mtype: "" - } - member { - name: "random_normal" - mtype: "" - } - member { - name: "random_uniform" - mtype: "" - } - member { - name: "truncated_normal" - mtype: "" - } - member { - name: "uniform" - mtype: "" - } - member { - name: "zeros" - mtype: "" - } member_method { name: "deserialize" argspec: "args=[\'config\', \'custom_objects\'], varargs=None, keywords=None, defaults=[\'None\'], " diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.random_normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.random_normal.pbtxt deleted file mode 100644 index bac8211a10..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.random_normal.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.keras.initializers.random_normal" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0.0\', \'0.05\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.random_uniform.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.random_uniform.pbtxt deleted file mode 100644 index ab0d74d071..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.random_uniform.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.keras.initializers.random_uniform" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'minval\', \'maxval\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'-0.05\', \'0.05\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.truncated_normal.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.truncated_normal.pbtxt deleted file mode 100644 index 358cca2b9c..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.truncated_normal.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.keras.initializers.truncated_normal" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0.0\', \'0.05\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.uniform.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.uniform.pbtxt deleted file mode 100644 index e6c731361a..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.uniform.pbtxt +++ /dev/null @@ -1,19 +0,0 @@ -path: "tensorflow.keras.initializers.uniform" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'minval\', \'maxval\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'-0.05\', \'0.05\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.zeros.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.zeros.pbtxt deleted file mode 100644 index a262390687..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.keras.initializers.zeros.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.keras.initializers.zeros" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'dtype\'], varargs=None, keywords=None, defaults=[\"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.ones_initializer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.ones_initializer.pbtxt index 210b56242b..b271db6a65 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.ones_initializer.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.ones_initializer.pbtxt @@ -1,11 +1,10 @@ path: "tensorflow.ones_initializer" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'dtype\'], varargs=None, keywords=None, defaults=[\"\"], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.pbtxt index d7a1a92bd9..0cf1fe0e3c 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.pbtxt @@ -164,10 +164,6 @@ tf_module { name: "float64" mtype: "" } - member { - name: "glorot_uniform_initializer" - mtype: "" - } member { name: "graph_util" mtype: "" @@ -180,10 +176,6 @@ tf_module { name: "image" mtype: "" } - member { - name: "initializers" - mtype: "" - } member { name: "int16" mtype: "" @@ -332,10 +324,6 @@ tf_module { name: "train" mtype: "" } - member { - name: "truncated_normal_initializer" - mtype: "" - } member { name: "uint16" mtype: "" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.random_normal_initializer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.random_normal_initializer.pbtxt index 5993fdeb9c..b1dfc44411 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.random_normal_initializer.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.random_normal_initializer.pbtxt @@ -1,11 +1,11 @@ path: "tensorflow.random_normal_initializer" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0.0\', \'1.0\', \'None\', \"\"], " + argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\'], varargs=None, keywords=None, defaults=[\'0.0\', \'0.05\', \'None\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.random_uniform_initializer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.random_uniform_initializer.pbtxt index a434ed1599..d16924a07a 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.random_uniform_initializer.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.random_uniform_initializer.pbtxt @@ -1,11 +1,11 @@ path: "tensorflow.random_uniform_initializer" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'minval\', \'maxval\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0\', \'None\', \'None\', \"\"], " + argspec: "args=[\'self\', \'minval\', \'maxval\', \'seed\'], varargs=None, keywords=None, defaults=[\'-0.05\', \'0.05\', \'None\'], " } member_method { name: "from_config" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.truncated_normal_initializer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.truncated_normal_initializer.pbtxt deleted file mode 100644 index c1e1c230a9..0000000000 --- a/tensorflow/tools/api/golden/v2/tensorflow.truncated_normal_initializer.pbtxt +++ /dev/null @@ -1,18 +0,0 @@ -path: "tensorflow.truncated_normal_initializer" -tf_class { - is_instance: "" - is_instance: "" - is_instance: "" - member_method { - name: "__init__" - argspec: "args=[\'self\', \'mean\', \'stddev\', \'seed\', \'dtype\'], varargs=None, keywords=None, defaults=[\'0.0\', \'1.0\', \'None\', \"\"], " - } - member_method { - name: "from_config" - argspec: "args=[\'cls\', \'config\'], varargs=None, keywords=None, defaults=None" - } - member_method { - name: "get_config" - argspec: "args=[\'self\'], varargs=None, keywords=None, defaults=None" - } -} diff --git a/tensorflow/tools/api/golden/v2/tensorflow.zeros_initializer.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.zeros_initializer.pbtxt index e229b02cee..53c5ac89cf 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.zeros_initializer.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.zeros_initializer.pbtxt @@ -1,11 +1,10 @@ path: "tensorflow.zeros_initializer" tf_class { - is_instance: "" - is_instance: "" + is_instance: "" + is_instance: "" is_instance: "" member_method { name: "__init__" - argspec: "args=[\'self\', \'dtype\'], varargs=None, keywords=None, defaults=[\"\"], " } member_method { name: "from_config" diff --git a/tensorflow/tools/compatibility/renames_v2.py b/tensorflow/tools/compatibility/renames_v2.py index d67cb7cb9a..dba4a5d5a3 100644 --- a/tensorflow/tools/compatibility/renames_v2.py +++ b/tensorflow/tools/compatibility/renames_v2.py @@ -203,7 +203,8 @@ renames = { 'tf.global_norm': 'tf.linalg.global_norm', 'tf.global_variables': 'tf.compat.v1.global_variables', 'tf.global_variables_initializer': 'tf.compat.v1.global_variables_initializer', - 'tf.glorot_normal_initializer': 'tf.initializers.glorot_normal', + 'tf.glorot_normal_initializer': 'tf.compat.v1.glorot_normal_initializer', + 'tf.glorot_uniform_initializer': 'tf.compat.v1.glorot_uniform_initializer', 'tf.graph_util.convert_variables_to_constants': 'tf.compat.v1.graph_util.convert_variables_to_constants', 'tf.graph_util.extract_sub_graph': 'tf.compat.v1.graph_util.extract_sub_graph', 'tf.graph_util.must_run_on_cpu': 'tf.compat.v1.graph_util.must_run_on_cpu', @@ -225,10 +226,26 @@ renames = { 'tf.initialize_all_variables': 'tf.compat.v1.initialize_all_variables', 'tf.initialize_local_variables': 'tf.compat.v1.initialize_local_variables', 'tf.initialize_variables': 'tf.compat.v1.initialize_variables', + 'tf.initializers.constant': 'tf.compat.v1.initializers.constant', 'tf.initializers.global_variables': 'tf.compat.v1.initializers.global_variables', + 'tf.initializers.glorot_normal': 'tf.compat.v1.initializers.glorot_normal', + 'tf.initializers.glorot_uniform': 'tf.compat.v1.initializers.glorot_uniform', + 'tf.initializers.he_normal': 'tf.compat.v1.initializers.he_normal', + 'tf.initializers.he_uniform': 'tf.compat.v1.initializers.he_uniform', + 'tf.initializers.identity': 'tf.compat.v1.initializers.identity', + 'tf.initializers.lecun_normal': 'tf.compat.v1.initializers.lecun_normal', + 'tf.initializers.lecun_uniform': 'tf.compat.v1.initializers.lecun_uniform', 'tf.initializers.local_variables': 'tf.compat.v1.initializers.local_variables', + 'tf.initializers.ones': 'tf.compat.v1.initializers.ones', + 'tf.initializers.orthogonal': 'tf.compat.v1.initializers.orthogonal', + 'tf.initializers.random_normal': 'tf.compat.v1.initializers.random_normal', + 'tf.initializers.random_uniform': 'tf.compat.v1.initializers.random_uniform', 'tf.initializers.tables_initializer': 'tf.compat.v1.initializers.tables_initializer', + 'tf.initializers.truncated_normal': 'tf.compat.v1.initializers.truncated_normal', + 'tf.initializers.uniform_unit_scaling': 'tf.compat.v1.initializers.uniform_unit_scaling', 'tf.initializers.variables': 'tf.compat.v1.initializers.variables', + 'tf.initializers.variance_scaling': 'tf.compat.v1.initializers.variance_scaling', + 'tf.initializers.zeros': 'tf.compat.v1.initializers.zeros', 'tf.invert_permutation': 'tf.math.invert_permutation', 'tf.io.PaddingFIFOQueue': 'tf.queue.PaddingFIFOQueue', 'tf.io.PriorityQueue': 'tf.queue.PriorityQueue', @@ -242,9 +259,26 @@ renames = { 'tf.is_numeric_tensor': 'tf.debugging.is_numeric_tensor', 'tf.is_strictly_increasing': 'tf.math.is_strictly_increasing', 'tf.is_variable_initialized': 'tf.compat.v1.is_variable_initialized', - 'tf.keras.backend.get_session': 'tf.compat.v1.keras.backend.get_session', - 'tf.keras.layers.CuDNNGRU': 'tf.compat.v1.keras.layers.CuDNNGRU', - 'tf.keras.layers.CuDNNLSTM': 'tf.compat.v1.keras.layers.CuDNNLSTM', + 'tf.keras.initializers.Identity': 'tf.compat.v1.keras.initializers.Identity', + 'tf.keras.initializers.Orthogonal': 'tf.compat.v1.keras.initializers.Orthogonal', + 'tf.keras.initializers.TruncatedNormal': 'tf.compat.v1.keras.initializers.TruncatedNormal', + 'tf.keras.initializers.VarianceScaling': 'tf.compat.v1.keras.initializers.VarianceScaling', + 'tf.keras.initializers.constant': 'tf.compat.v1.keras.initializers.constant', + 'tf.keras.initializers.glorot_normal': 'tf.compat.v1.keras.initializers.glorot_normal', + 'tf.keras.initializers.glorot_uniform': 'tf.compat.v1.keras.initializers.glorot_uniform', + 'tf.keras.initializers.he_normal': 'tf.compat.v1.keras.initializers.he_normal', + 'tf.keras.initializers.he_uniform': 'tf.compat.v1.keras.initializers.he_uniform', + 'tf.keras.initializers.identity': 'tf.compat.v1.keras.initializers.identity', + 'tf.keras.initializers.lecun_normal': 'tf.compat.v1.keras.initializers.lecun_normal', + 'tf.keras.initializers.lecun_uniform': 'tf.compat.v1.keras.initializers.lecun_uniform', + 'tf.keras.initializers.normal': 'tf.compat.v1.keras.initializers.normal', + 'tf.keras.initializers.ones': 'tf.compat.v1.keras.initializers.ones', + 'tf.keras.initializers.orthogonal': 'tf.compat.v1.keras.initializers.orthogonal', + 'tf.keras.initializers.random_normal': 'tf.compat.v1.keras.initializers.random_normal', + 'tf.keras.initializers.random_uniform': 'tf.compat.v1.keras.initializers.random_uniform', + 'tf.keras.initializers.truncated_normal': 'tf.compat.v1.keras.initializers.truncated_normal', + 'tf.keras.initializers.uniform': 'tf.compat.v1.keras.initializers.uniform', + 'tf.keras.initializers.zeros': 'tf.compat.v1.keras.initializers.zeros', 'tf.layers.AveragePooling1D': 'tf.compat.v1.layers.AveragePooling1D', 'tf.layers.AveragePooling2D': 'tf.compat.v1.layers.AveragePooling2D', 'tf.layers.AveragePooling3D': 'tf.compat.v1.layers.AveragePooling3D', @@ -410,7 +444,7 @@ renames = { 'tf.nn.uniform_candidate_sampler': 'tf.random.uniform_candidate_sampler', 'tf.nn.xw_plus_b': 'tf.compat.v1.nn.xw_plus_b', 'tf.op_scope': 'tf.compat.v1.op_scope', - 'tf.orthogonal_initializer': 'tf.keras.initializers.Orthogonal', + 'tf.orthogonal_initializer': 'tf.compat.v1.orthogonal_initializer', 'tf.parse_single_sequence_example': 'tf.io.parse_single_sequence_example', 'tf.parse_tensor': 'tf.io.parse_tensor', 'tf.placeholder': 'tf.compat.v1.placeholder', @@ -433,9 +467,8 @@ renames = { 'tf.qr': 'tf.linalg.qr', 'tf.quantize': 'tf.quantization.quantize', 'tf.quantized_concat': 'tf.quantization.quantized_concat', - 'tf.ragged.constant_value': 'tf.compat.v1.ragged.constant_value', - 'tf.ragged.convert_to_tensor_or_ragged_tensor': 'tf.compat.v1.ragged.convert_to_tensor_or_ragged_tensor', 'tf.ragged.RaggedTensorValue': 'tf.compat.v1.ragged.RaggedTensorValue', + 'tf.ragged.constant_value': 'tf.compat.v1.ragged.constant_value', 'tf.random.get_seed': 'tf.compat.v1.random.get_seed', 'tf.random.set_random_seed': 'tf.compat.v1.random.set_random_seed', 'tf.random_crop': 'tf.image.random_crop', @@ -684,7 +717,7 @@ renames = { 'tf.train.write_graph': 'tf.io.write_graph', 'tf.trainable_variables': 'tf.compat.v1.trainable_variables', 'tf.truncated_normal': 'tf.random.truncated_normal', - 'tf.uniform_unit_scaling_initializer': 'tf.initializers.uniform_unit_scaling', + 'tf.uniform_unit_scaling_initializer': 'tf.compat.v1.uniform_unit_scaling_initializer', 'tf.unsorted_segment_max': 'tf.math.unsorted_segment_max', 'tf.unsorted_segment_mean': 'tf.math.unsorted_segment_mean', 'tf.unsorted_segment_min': 'tf.math.unsorted_segment_min', @@ -695,7 +728,7 @@ renames = { 'tf.variable_op_scope': 'tf.compat.v1.variable_op_scope', 'tf.variable_scope': 'tf.compat.v1.variable_scope', 'tf.variables_initializer': 'tf.compat.v1.variables_initializer', - 'tf.variance_scaling_initializer': 'tf.keras.initializers.VarianceScaling', + 'tf.variance_scaling_initializer': 'tf.compat.v1.variance_scaling_initializer', 'tf.verify_tensor_all_finite': 'tf.compat.v1.verify_tensor_all_finite', 'tf.wrap_function': 'tf.compat.v1.wrap_function', 'tf.write_file': 'tf.io.write_file', diff --git a/tensorflow/tools/compatibility/tf_upgrade_v2.py b/tensorflow/tools/compatibility/tf_upgrade_v2.py index 103a86a990..c0be267217 100644 --- a/tensorflow/tools/compatibility/tf_upgrade_v2.py +++ b/tensorflow/tools/compatibility/tf_upgrade_v2.py @@ -560,6 +560,18 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): # changed significantly. "tf.nn.ctc_loss": "tf.compat.v1.nn.ctc_loss", + "tf.zeros_initializer": + "tf.compat.v1.initializers.zeros", + "tf.ones_initializer": + "tf.compat.v1.initializers.ones", + "tf.constant_initializer": + "tf.compat.v1.initializers.constant", + "tf.random_uniform_initializer": + "tf.compat.v1.initializers.random_uniform", + "tf.random_normal_initializer": + "tf.compat.v1.initializers.random_normal", + "tf.truncated_normal_initializer": + "tf.compat.v1.initializers.truncated_normal", } # pylint: enable=line-too-long @@ -711,6 +723,19 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): "WARNING: `partition_strategy` has been removed from `%s` " " The 'div' strategy is used by default.") + initializers_no_dtype_comment = ( + "WARNING: tf.initializers and tf.keras.initializers no longer have the " + "dtype argument in the constructor or partition_info argument in the " + "call method in TF 2.0 and after. The only API symbols are now " + "tf.keras.initializers.* or tf.initializers.*." + "\nThe calls have been converted to compat.v1 for safety (even though " + "they may already have been correct).") + + uniform_unit_scaling_initializer_comment = ( + "WARNING: uniform_unit_scaling_initializer has been removed. Please use" + " tf.initializers.variance_scaling instead with distribution=uniform " + "to get equivalent behaviour.") + # Function warnings. placeholder inside warnings will be # replaced by function name. self.function_warnings = { @@ -852,6 +877,78 @@ class TFAPIChangeSpec(ast_edits.APIChangeSpec): "tf.test.assert_equal_graph_def": "tf.assert_equal_graph_def no longer takes 'checkpoint_v2' " "argument. 'checkpoint_v2' now defaults to True.", + "tf.keras.initializers.Zeros": + initializers_no_dtype_comment, + "tf.keras.initializers.zeros": + initializers_no_dtype_comment, + "tf.keras.initializers.Ones": + initializers_no_dtype_comment, + "tf.keras.initializers.ones": + initializers_no_dtype_comment, + "tf.keras.initializers.Constant": + initializers_no_dtype_comment, + "tf.keras.initializers.constant": + initializers_no_dtype_comment, + "tf.keras.initializers.VarianceScaling": + initializers_no_dtype_comment, + "tf.keras.initializers.Orthogonal": + initializers_no_dtype_comment, + "tf.keras.initializers.orthogonal": + initializers_no_dtype_comment, + "tf.keras.initializers.Identity": + initializers_no_dtype_comment, + "tf.keras.initializers.identity": + initializers_no_dtype_comment, + "tf.keras.initializers.glorot_uniform": + initializers_no_dtype_comment, + "tf.keras.initializers.glorot_normal": + initializers_no_dtype_comment, + "tf.initializers.zeros": + initializers_no_dtype_comment, + "tf.zeros_initializer": + initializers_no_dtype_comment, + "tf.initializers.ones": + initializers_no_dtype_comment, + "tf.ones_initializer": + initializers_no_dtype_comment, + "tf.initializers.constant": + initializers_no_dtype_comment, + "tf.constant_initializer": + initializers_no_dtype_comment, + "tf.initializers.random_uniform": + initializers_no_dtype_comment, + "tf.random_uniform_initializer": + initializers_no_dtype_comment, + "tf.initializers.random_normal": + initializers_no_dtype_comment, + "tf.random_normal_initializer": + initializers_no_dtype_comment, + "tf.initializers.truncated_normal": + initializers_no_dtype_comment, + "tf.truncated_normal_initializer": + initializers_no_dtype_comment, + "tf.initializers.variance_scaling": + initializers_no_dtype_comment, + "tf.variance_scaling_initializer": + initializers_no_dtype_comment, + "tf.initializers.orthogonal": + initializers_no_dtype_comment, + "tf.orthogonal_initializer": + initializers_no_dtype_comment, + "tf.initializers.identity": + initializers_no_dtype_comment, + "tf.glorot_uniform_initializer": + initializers_no_dtype_comment, + "tf.initializers.glorot_uniform": + initializers_no_dtype_comment, + "tf.glorot_normal_initializer": + initializers_no_dtype_comment, + "tf.initializers.glorot_normal": + initializers_no_dtype_comment, + "tf.initializers.uniform_unit_scaling": + uniform_unit_scaling_initializer_comment, + "tf.uniform_unit_scaling_initializer": + uniform_unit_scaling_initializer_comment, } self.symbol_renames = { -- GitLab From c016d41682895ee3a61bc0946ecf2ca421d17655 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 04:02:09 -0800 Subject: [PATCH 0243/1765] Make object based saved model rely on a single instance of listing the reachable objects and functions. This fix issues with variables and other reachable objects only being created when making functions concrete and issues with classes that define special attrs that return a new polymorphic function each time they are called. PiperOrigin-RevId: 226469978 --- .../saved_model/function_serialization.py | 37 +---- tensorflow/python/saved_model/load_test.py | 18 +++ tensorflow/python/saved_model/save.py | 150 +++++++++++++----- 3 files changed, 127 insertions(+), 78 deletions(-) diff --git a/tensorflow/python/saved_model/function_serialization.py b/tensorflow/python/saved_model/function_serialization.py index 27e8e476cb..014a4ef04c 100644 --- a/tensorflow/python/saved_model/function_serialization.py +++ b/tensorflow/python/saved_model/function_serialization.py @@ -18,14 +18,13 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function -from tensorflow.python.eager import def_function from tensorflow.python.eager import function as defun_lib from tensorflow.python.platform import tf_logging as logging from tensorflow.python.saved_model import nested_structure_coder from tensorflow.python.saved_model import saved_object_graph_pb2 -def _serialize_polymorphic_function(polymorphic_function, node_ids): +def serialize_polymorphic_function(polymorphic_function, node_ids): """Build a SavedPolymorphicProto.""" coder = nested_structure_coder.StructureCoder() proto = saved_object_graph_pb2.SavedPolymorphicFunction() @@ -73,37 +72,3 @@ def list_all_concrete_functions(polymorphic_function): concrete_function = polymorphic_function.get_concrete_function(*signature) concrete_functions.append((signature, concrete_function)) return concrete_functions - - -def list_all_polymorphic_functions(checkpointable_object): - """Given a checkpointable object, returns all of its polymorphic functions.""" - polymorphic_functions = dict() - for attribute_name in dir(checkpointable_object): - try: - attribute_value = getattr(checkpointable_object, attribute_name, None) - except: # pylint: disable=bare-except - # We really don't want to throw an exception just because some object's - # attribute accessor is broken. - attribute_value = None - # TODO(allenl): Consider de-duplicating functions which are referenced - # from multiple attributes. - if isinstance(attribute_value, def_function.PolymorphicFunction): - polymorphic_functions[attribute_name] = attribute_value - return polymorphic_functions - - -def add_polymorphic_functions_to_object_graph_proto(checkpointable_objects, - saved_object_graph, - node_ids): - """Finds PolymorphicFunctions attached to objects and saves them.""" - existing_objects = list(zip(checkpointable_objects, saved_object_graph.nodes)) - for obj, obj_proto in existing_objects: - for name, polymorphic_function in list_all_polymorphic_functions( - obj).items(): - function_node_id = len(saved_object_graph.nodes) - function_node = saved_object_graph.nodes.add() - function_node.function.CopyFrom( - _serialize_polymorphic_function(polymorphic_function, node_ids)) - reference = obj_proto.children.add() - reference.node_id = function_node_id - reference.local_name = name diff --git a/tensorflow/python/saved_model/load_test.py b/tensorflow/python/saved_model/load_test.py index 657cec4178..9eac3e6555 100644 --- a/tensorflow/python/saved_model/load_test.py +++ b/tensorflow/python/saved_model/load_test.py @@ -236,6 +236,24 @@ class LoadTest(test.TestCase): self.assertEqual(4, imported.f(constant_op.constant(2), True).numpy()) self.assertEqual(27, imported.f(constant_op.constant(2)).numpy()) + def test_side_effect_listing(self): + class M(tracking.Checkpointable): + + def __init__(self): + super(M, self).__init__() + self.var = None + + @def_function.function( + input_signature=[tensor_spec.TensorSpec(None, dtypes.float32)]) + def f(self, x): + if self.var is None: + self.var = variables.Variable(2.) + return x * self.var + + m = M() + self.cycle(m) + self.assertEquals(4.0, m.f(constant_op.constant(2.0)).numpy()) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/saved_model/save.py b/tensorflow/python/saved_model/save.py index e69343208c..a76b370565 100644 --- a/tensorflow/python/saved_model/save.py +++ b/tensorflow/python/saved_model/save.py @@ -53,26 +53,92 @@ from tensorflow.python.util.tf_export import tf_export DEFAULT_SIGNATURE_ATTR = "_default_save_signature" -def _find_function_to_export(root): +class _SaveableView(object): + """Provides a stable view over a checkpointable root. + + This class helps creating a single stable view over an object to save. The + saving code should access properties and functions via this class and not via + the original object as there are cases where an object construct their + checkpointable attributes and functions dynamically per call and will yield + different objects if invoked more than once. + """ + + def __init__(self, root): + checkpointable_objects, node_ids, slot_variables = util.find_objects(root) + self.nodes = checkpointable_objects + self.node_ids = node_ids + self.slot_variables = slot_variables + self.polymorphic_functions = util.ObjectIdentityDictionary() + + # Also add polymorphic functions as nodes. + for obj in self.nodes: + self.polymorphic_functions[obj] = self._list_polymorphic_functions(obj) + for function in self.polymorphic_functions[obj].values(): + if function not in self.node_ids: + self.node_ids[function] = len(self.nodes) + self.nodes.append(function) + # Force listing the concrete functions for the side effects: + # - populate the cache for polymorphic functions that have an + # input_signature and have not been called. + # - force side effects of creation of concrete functions, e.g. create + # variables on first run. + function_serialization.list_all_concrete_functions(function) + + @property + def root(self): + return self.nodes[0] + + def fill_object_graph_proto(self, proto): + """Populate the nodes, children and slot_variables of a SavedObjectGraph.""" + for node_id, node in enumerate(self.nodes): + assert self.node_ids[node] == node_id + object_proto = proto.nodes.add() + object_proto.slot_variables.extend(self.slot_variables.get(node, ())) + if isinstance(node, def_function.PolymorphicFunction): + continue + for child in node._checkpoint_dependencies: # pylint: disable=protected-access + child_proto = object_proto.children.add() + child_proto.node_id = self.node_ids[child.ref] + child_proto.local_name = child.name + for local_name, ref_function in self.polymorphic_functions[node].items(): + child_proto = object_proto.children.add() + child_proto.node_id = self.node_ids[ref_function] + child_proto.local_name = local_name + + def _list_polymorphic_functions(self, checkpointable_object): + """Return a dict of polymorphic functions of a checkpointable.""" + polymorphic_functions = dict() + for attribute_name in dir(checkpointable_object): + try: + attribute_value = getattr(checkpointable_object, attribute_name, None) + except Exception: # pylint: disable=broad-except + # We really don't want to throw an exception just because some object's + # attribute accessor is broken. + attribute_value = None + if isinstance(attribute_value, def_function.PolymorphicFunction): + polymorphic_functions[attribute_name] = attribute_value + return polymorphic_functions + + +def _find_function_to_export(saveable_view): """Iterate over `root`'s attributes, finding traced functions.""" exported_function = None previous_attribute_name = None - for attribute_name in dir(root): - attribute_value = getattr(root, attribute_name, None) - if isinstance(attribute_value, def_function.PolymorphicFunction): - if exported_function is not None: - raise ValueError( - ("Exporting an object with no " - "tf.saved_model.save(..., signatures=...) " - "argument specified, and with more than one " - "@tf.function-decorated method attached to it: {}. The signature " - "keys for these functions are ambiguous. Specify signature " - "functions explicitly.").format( - [previous_attribute_name, attribute_name])) - exported_function = attribute_value - previous_attribute_name = attribute_name + functions = saveable_view.polymorphic_functions[saveable_view.root] + for name, value in sorted(functions.items()): + if exported_function is not None: + raise ValueError( + ("Exporting an object with no " + "tf.saved_model.save(..., signatures=...) " + "argument specified, and with more than one " + "@tf.function-decorated method attached to it: {}. The signature " + "keys for these functions are ambiguous. Specify signature " + "functions explicitly.").format( + [previous_attribute_name, name])) + exported_function = value + previous_attribute_name = name if exported_function is None: - exported_function = getattr(root, DEFAULT_SIGNATURE_ATTR, None) + exported_function = functions.get(DEFAULT_SIGNATURE_ATTR, None) if exported_function is None: raise ValueError( ("Exporting an object with no tf.saved_model.save(..., signatures=...) " @@ -430,13 +496,13 @@ def _map_resources(accessible_objects): return object_map, resource_map, asset_info -def _fill_meta_graph_def(meta_graph_def, obj, signature_functions, +def _fill_meta_graph_def(meta_graph_def, saveable_view, signature_functions, object_saver): """Generates a MetaGraph which calls `signature_functions`. Args: meta_graph_def: The MetaGraphDef proto to fill. - obj: The checkpointable object being exported. + saveable_view: The _SaveableView being exported. signature_functions: A dictionary mapping signature keys to concrete functions containing signatures to add to the MetaGraph. object_saver: A CheckpointableSaver to add to the MetaGraph. @@ -444,10 +510,9 @@ def _fill_meta_graph_def(meta_graph_def, obj, signature_functions, Returns: An _AssetInfo, which contains information to help creating the SavedModel. """ - signatures = {} # List objects from the eager context to make sure Optimizers give us the # right Graph-dependent variables. - accessible_objects = util.list_objects(obj) + accessible_objects = saveable_view.nodes resource_initializer_functions = _trace_resource_initializers( accessible_objects) exported_graph = ops.Graph() @@ -486,9 +551,8 @@ def _fill_meta_graph_def(meta_graph_def, obj, signature_functions, # while in eager mode so they end up added to the graph and can later be used # by the object based saved model. concrete_functions = [] - for accessible_object in accessible_objects: - for function in function_serialization.list_all_polymorphic_functions( - accessible_object).values(): + for obj in accessible_objects: + for function in saveable_view.polymorphic_functions[obj].values(): concrete_functions.extend( function_serialization.list_all_concrete_functions(function)) @@ -512,30 +576,23 @@ def _fill_meta_graph_def(meta_graph_def, obj, signature_functions, return asset_info -def _write_object_graph(root, export_dir, asset_file_def_index): +def _write_object_graph(saveable_view, export_dir, asset_file_def_index): """Save a SavedObjectGraph proto for `root`.""" # SavedObjectGraph is similar to the CheckpointableObjectGraph proto in the # checkpoint. It will eventually go into the SavedModel. proto = saved_object_graph_pb2.SavedObjectGraph() - - checkpointable_objects, node_ids, slot_variables = util.find_objects(root) - util.fill_object_graph_proto(checkpointable_objects, node_ids, slot_variables, - proto) + saveable_view.fill_object_graph_proto(proto) node_ids = util.ObjectIdentityDictionary() - for i in range(len(checkpointable_objects)): - obj = checkpointable_objects[i] + for i, obj in enumerate(saveable_view.nodes): node_ids[obj] = i if resource_variable_ops.is_resource_variable(obj): node_ids[obj.handle] = i elif isinstance(obj, tracking.TrackableAsset): node_ids[obj.asset_path.handle] = i - for obj, obj_proto in zip(checkpointable_objects, proto.nodes): - _write_object_proto(obj, obj_proto, asset_file_def_index) - - function_serialization.add_polymorphic_functions_to_object_graph_proto( - checkpointable_objects, proto, node_ids) + for obj, obj_proto in zip(saveable_view.nodes, proto.nodes): + _write_object_proto(obj, obj_proto, asset_file_def_index, node_ids) extra_asset_dir = os.path.join( compat.as_bytes(export_dir), @@ -546,7 +603,7 @@ def _write_object_graph(root, export_dir, asset_file_def_index): file_io.write_string_to_file(object_graph_filename, proto.SerializeToString()) -def _write_object_proto(obj, proto, asset_file_def_index): +def _write_object_proto(obj, proto, asset_file_def_index, node_ids): """Saves an object into SavedObject proto.""" if isinstance(obj, tracking.TrackableAsset): proto.asset.SetInParent() @@ -555,6 +612,9 @@ def _write_object_proto(obj, proto, asset_file_def_index): proto.variable.SetInParent() proto.variable.dtype = obj.dtype.as_datatype_enum proto.variable.shape.CopyFrom(obj.shape.as_proto()) + elif isinstance(obj, def_function.PolymorphicFunction): + proto.function.CopyFrom( + function_serialization.serialize_polymorphic_function(obj, node_ids)) else: proto.user_object.SetInParent() @@ -729,20 +789,26 @@ def save(obj, export_dir, signatures=None): if not isinstance(obj, base.CheckpointableBase): raise ValueError( "Expected a Checkpointable object for export, got {}.".format(obj)) - if signatures is None: - # Note that we run this before saving the checkpoint, since looping over - # attributes may have the side effect of creating variables in some cases. - signatures = _find_function_to_export(obj) + # Use _SaveableView to provide a stable listing of properties and functions. + # Note we run this twice since, while constructing the view the first time + # there can be side effects of creating variables. + _ = _SaveableView(obj) + saveable_view = _SaveableView(obj) + + if signatures is None: + signatures = _find_function_to_export(saveable_view) signatures = _canonicalize_signatures(signatures) + # TODO(allenl): Factor out some subset of SavedModelBuilder which is 2.x # compatible (no sessions) and share it with this export API rather than # making a SavedModel proto and writing it directly. saved_model = saved_model_pb2.SavedModel() meta_graph_def = saved_model.meta_graphs.add() + # TODO(andresp): Should this be using saveable_view? object_saver = util.CheckpointableSaver(obj) asset_info = _fill_meta_graph_def( - meta_graph_def, obj, signatures, object_saver) + meta_graph_def, saveable_view, signatures, object_saver) saved_model.saved_model_schema_version = ( constants.SAVED_MODEL_SCHEMA_VERSION) # So far we've just been generating protocol buffers with no I/O. Now we write @@ -756,4 +822,4 @@ def save(obj, export_dir, signatures=None): compat.as_bytes(export_dir), compat.as_bytes(constants.SAVED_MODEL_FILENAME_PB)) file_io.write_string_to_file(path, saved_model.SerializeToString()) - _write_object_graph(obj, export_dir, asset_info.asset_index) + _write_object_graph(saveable_view, export_dir, asset_info.asset_index) -- GitLab From 2a240b1d1319842bf360bf08d7fc5cb8458bbb0a Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 06:38:43 -0800 Subject: [PATCH 0244/1765] Introduce GEMV specializations a GEMM call degenerates to a GEMV call. PiperOrigin-RevId: 226482812 --- .../kernels/internal/optimized/optimized_ops.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h index bf3902ec31..7bc6b324c5 100644 --- a/tensorflow/lite/kernels/internal/optimized/optimized_ops.h +++ b/tensorflow/lite/kernels/internal/optimized/optimized_ops.h @@ -1906,7 +1906,20 @@ inline void Conv(const ConvParams& params, const RuntimeShape& input_shape, MatrixRef matrix_c(c, m, n); ConstMatrixRef matrix_a(a, m, k); ConstMatrixRef matrix_b(b, n, k); - matrix_c.noalias() = matrix_a * matrix_b.transpose(); + + // The following special casing for when a or b is a vector is required + // as Eigen seem to fail to make this optimization on its own. + if (n == 1) { + gemmlowp::ScopedProfilingLabel label("GEMV"); + matrix_c.col(0).noalias() = matrix_a * matrix_b.row(0).transpose(); + } else if (m == 1) { + gemmlowp::ScopedProfilingLabel label("GEMV"); + matrix_c.row(0).noalias() = matrix_a.row(0) * matrix_b.transpose(); + } else { + gemmlowp::ScopedProfilingLabel label("GEMM"); + matrix_c.noalias() = matrix_a * matrix_b.transpose(); + } + #endif // defined(TF_LITE_USE_CBLAS) && defined(__APPLE__) optimized_ops::AddBiasAndEvalActivationFunction( -- GitLab From 64812d4ca383552453a8269e8bc011fe2a0e47ca Mon Sep 17 00:00:00 2001 From: Mihai Maruseac Date: Fri, 21 Dec 2018 06:46:30 -0800 Subject: [PATCH 0245/1765] Ensure fuzzers always run with defined inputs. PiperOrigin-RevId: 226483481 --- tensorflow/core/kernels/fuzzing/string_split_fuzz.cc | 4 ++-- tensorflow/core/kernels/fuzzing/string_split_v2_fuzz.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc b/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc index 10958602b2..4dbb6a7116 100644 --- a/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc +++ b/tensorflow/core/kernels/fuzzing/string_split_fuzz.cc @@ -46,9 +46,9 @@ class FuzzStringSplit : public FuzzSession { string(reinterpret_cast(data), delim_len); input_tensor.scalar()() = string( reinterpret_cast(data + delim_len), size - delim_len); - } - RunInputs({{"input", input_tensor}, {"delimiter", delimiter_tensor}}); + RunInputs({{"input", input_tensor}, {"delimiter", delimiter_tensor}}); + } } }; diff --git a/tensorflow/core/kernels/fuzzing/string_split_v2_fuzz.cc b/tensorflow/core/kernels/fuzzing/string_split_v2_fuzz.cc index 969821dbba..f7e3da8043 100644 --- a/tensorflow/core/kernels/fuzzing/string_split_v2_fuzz.cc +++ b/tensorflow/core/kernels/fuzzing/string_split_v2_fuzz.cc @@ -50,9 +50,9 @@ class FuzzStringSplitV2 : public FuzzSession { string(reinterpret_cast(data), sep_len); input_tensor.scalar()() = string( reinterpret_cast(data + sep_len), size - sep_len); - } - RunInputs({{"input", input_tensor}, {"separator", separator_tensor}}); + RunInputs({{"input", input_tensor}, {"separator", separator_tensor}}); + } } private: -- GitLab From 8da29925c65dc72b49f693942923519b38dd0242 Mon Sep 17 00:00:00 2001 From: Yves-Noel Weweler Date: Fri, 21 Dec 2018 15:58:22 +0100 Subject: [PATCH 0246/1765] Fix pylint warnings from Ubuntu Sanity test --- .../kernel_tests/bucket_by_sequence_length_test.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py index a95d8e1049..4f1ea9f2ee 100644 --- a/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py +++ b/tensorflow/python/data/experimental/kernel_tests/bucket_by_sequence_length_test.py @@ -74,12 +74,13 @@ def _get_record_shape(sparse): @test_util.run_all_in_graph_and_eager_modes -class BucketBySequenceLengthTest(test_base.DatasetTestBase, parameterized.TestCase): +class BucketBySequenceLengthTest(test_base.DatasetTestBase, + parameterized.TestCase): # TODO(b/117581999): add eager coverage. @parameterized.named_parameters( - ("WithoutPadding", True), - ("WithPadding", False), + ("WithoutPadding", True), + ("WithPadding", False), ) def testSkipEagerBucketDropReminder(self, param_no_padding): -- GitLab From e865a4c920a22d1347de1460aa0fecfcb30d1666 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 08:13:28 -0800 Subject: [PATCH 0247/1765] Add TPU-compatible GANEstimator. PiperOrigin-RevId: 226492169 --- tensorflow/contrib/gan/BUILD | 71 ++- .../contrib/gan/python/estimator/__init__.py | 8 +- .../estimator/python/tpu_gan_estimator.py | 28 ++ .../python/tpu_gan_estimator_impl.py | 422 ++++++++++++++++++ .../python/tpu_gan_estimator_test.py | 320 +++++++++++++ 5 files changed, 843 insertions(+), 6 deletions(-) create mode 100644 tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator.py create mode 100644 tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator_impl.py create mode 100644 tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator_test.py diff --git a/tensorflow/contrib/gan/BUILD b/tensorflow/contrib/gan/BUILD index f89d7ed0f4..ae8320cfb2 100644 --- a/tensorflow/contrib/gan/BUILD +++ b/tensorflow/contrib/gan/BUILD @@ -1,12 +1,15 @@ # Files for using TFGAN framework. -package(default_visibility = ["//tensorflow:__subpackages__"]) +load("//tensorflow:tensorflow.bzl", "py_test") + +package(default_visibility = [ + "//learning/brain/contrib/tfgan:__subpackages__", + "//tensorflow:__subpackages__", +]) licenses(["notice"]) # Apache 2.0 exports_files(["LICENSE"]) -load("//tensorflow:tensorflow.bzl", "py_test") - py_library( name = "gan", srcs = [ @@ -105,6 +108,7 @@ py_library( ":gan_estimator", ":head", ":stargan_estimator", + ":tpu_gan_estimator", "//tensorflow/python:util", ], ) @@ -518,15 +522,19 @@ py_test( "//tensorflow/python:array_ops", "//tensorflow/python:client_testlib", "//tensorflow/python:dtypes", + "//tensorflow/python:errors", "//tensorflow/python:framework_ops", "//tensorflow/python:math_ops", "//tensorflow/python:metrics", "//tensorflow/python:parsing_ops", "//tensorflow/python:summary", + "//tensorflow/python:tensor_shape", "//tensorflow/python:training", "//tensorflow/python:training_util", "//tensorflow/python:variable_scope", - "//tensorflow/python/estimator:estimator_py", + "//tensorflow/python/estimator", + "//tensorflow/python/estimator:model_fn", + "//tensorflow/python/estimator:numpy_io", "//third_party/py/numpy", "@absl_py//absl/testing:parameterized", "@six_archive//:six", @@ -584,6 +592,61 @@ py_test( ], ) +py_library( + name = "tpu_gan_estimator", + srcs = [ + "python/estimator/python/tpu_gan_estimator.py", + "python/estimator/python/tpu_gan_estimator_impl.py", + ], + srcs_version = "PY2AND3", + deps = [ + ":gan_estimator", + ":namedtuples", + ":train", + "//tensorflow/contrib/tpu:tpu_estimator", + "//tensorflow/contrib/tpu:tpu_lib", + "//tensorflow/contrib/training:training_py", + "//tensorflow/python:control_flow_ops", + "//tensorflow/python:framework_ops", + "//tensorflow/python:metrics", + "//tensorflow/python:util", + "//tensorflow/python/estimator:model_fn", + "//tensorflow/python/ops/losses", + ], +) + +py_test( + name = "tpu_gan_estimator_test", + srcs = ["python/estimator/python/tpu_gan_estimator_test.py"], + shard_count = 11, + srcs_version = "PY2AND3", + tags = ["notsan"], + deps = [ + ":namedtuples", + ":tpu_gan_estimator", + ":tuple_losses", + "//tensorflow/contrib/layers:layers_py", + "//tensorflow/contrib/tpu:tpu_estimator", + "//tensorflow/contrib/tpu:tpu_lib", + "//tensorflow/python:array_ops", + "//tensorflow/python:client_testlib", + "//tensorflow/python:errors", + "//tensorflow/python:framework_ops", + "//tensorflow/python:metrics", + "//tensorflow/python:summary", + "//tensorflow/python:tensor_shape", + "//tensorflow/python:training", + "//tensorflow/python:training_util", + "//tensorflow/python:variable_scope", + "//tensorflow/python/data/ops:dataset_ops", + "//tensorflow/python/estimator", + "//tensorflow/python/estimator:model_fn", + "//third_party/py/numpy", + "@absl_py//absl/testing:parameterized", + "@six_archive//:six", + ], +) + py_library( name = "sliced_wasserstein", srcs = [ diff --git a/tensorflow/contrib/gan/python/estimator/__init__.py b/tensorflow/contrib/gan/python/estimator/__init__.py index 99d38011ba..75cccb5ea0 100644 --- a/tensorflow/contrib/gan/python/estimator/__init__.py +++ b/tensorflow/contrib/gan/python/estimator/__init__.py @@ -27,17 +27,21 @@ from __future__ import print_function from tensorflow.contrib.gan.python.estimator.python import gan_estimator from tensorflow.contrib.gan.python.estimator.python import head from tensorflow.contrib.gan.python.estimator.python import stargan_estimator +from tensorflow.contrib.gan.python.estimator.python import tpu_gan_estimator from tensorflow.contrib.gan.python.estimator.python.gan_estimator import * from tensorflow.contrib.gan.python.estimator.python.head import * from tensorflow.contrib.gan.python.estimator.python.stargan_estimator import * +from tensorflow.contrib.gan.python.estimator.python.tpu_gan_estimator import * # pylint: enable=unused-import,wildcard-import from tensorflow.python.util.all_util import remove_undocumented -_allowed_symbols = [ +_allowed_symbols = ([ 'gan_estimator', 'stargan_estimator', + 'tpu_gan_estimator', 'head', -] + gan_estimator.__all__ + stargan_estimator.__all__ + head.__all__ +] + gan_estimator.__all__ + stargan_estimator.__all__ + head.__all__ + + tpu_gan_estimator.__all__) remove_undocumented(__name__, _allowed_symbols) diff --git a/tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator.py b/tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator.py new file mode 100644 index 0000000000..deb381f7be --- /dev/null +++ b/tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator.py @@ -0,0 +1,28 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""`tf.Learn` components for `TPUGANEstimator`.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.contrib.gan.python.estimator.python import tpu_gan_estimator_impl +# pylint: disable=wildcard-import +from tensorflow.contrib.gan.python.estimator.python.tpu_gan_estimator_impl import * +# pylint: enable=wildcard-import +from tensorflow.python.util.all_util import remove_undocumented + +__all__ = tpu_gan_estimator_impl.__all__ +remove_undocumented(__name__, __all__) diff --git a/tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator_impl.py b/tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator_impl.py new file mode 100644 index 0000000000..295d1382e2 --- /dev/null +++ b/tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator_impl.py @@ -0,0 +1,422 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""A TFGAN-backed GAN Estimator that works on TPU.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.contrib.gan.python import namedtuples as tfgan_tuples +from tensorflow.contrib.gan.python import train as tfgan_train +from tensorflow.contrib.gan.python.estimator.python import gan_estimator_impl as gan_estimator_lib +from tensorflow.contrib.tpu.python.tpu import tpu_estimator +from tensorflow.contrib.tpu.python.tpu import tpu_optimizer +from tensorflow.contrib.training.python.training import training +from tensorflow.python.estimator import model_fn as model_fn_lib +from tensorflow.python.framework import ops +from tensorflow.python.ops import control_flow_ops +from tensorflow.python.ops import metrics as metrics_lib +from tensorflow.python.ops.losses import losses + +__all__ = [ + 'TPUGANEstimator', +] + + +class TPUGANEstimator(tpu_estimator.TPUEstimator): + """An estimator for Generative Adversarial Networks (GANs) on TPU. + + This Estimator is backed by TFGAN. It is similar to `tfgan.GANEstimator`, + but works on TPU. + + Example: + + ```python + import tensorflow as tf + tfgan = tf.contrib.gan + + # See TFGAN's `train.py` for a description of the generator and + # discriminator API. + def generator_fn(generator_inputs): + ... + return generated_data + + def discriminator_fn(data, conditioning): + ... + return logits + + # Create GAN estimator. + config = tpu_config.RunConfig(model_dir='/my/dir') + gan_estimator = tfgan.estimator.TPUGANEstimator( + generator_fn=generator_fn, + discriminator_fn=discriminator_fn, + generator_loss_fn=tfgan.losses.wasserstein_generator_loss, + discriminator_loss_fn=tfgan.losses.wasserstein_discriminator_loss, + generator_optimizer=tf.train.AdamOptimizer(0.1, 0.5), + discriminator_optimizer=tf.train.AdamOptimizer(0.1, 0.5), + train_batch_size=4, + config=config) + + # Train estimator. + gan_estimator.train(train_input_fn, train_steps) + + # Evaluate resulting estimator. + gan_estimator.evaluate(eval_input_fn, eval_steps) + + # Generate samples from generator. + predictions = np.array([ + x['generated_data'] for x in gan_estimator.predict(predict_input_fn)]) + ``` + """ + + def __init__(self, + # Arguments to construct the `model_fn`. + generator_fn=None, + discriminator_fn=None, + generator_loss_fn=None, + discriminator_loss_fn=None, + generator_optimizer=None, + discriminator_optimizer=None, + get_eval_metric_ops_fn=None, + add_summaries=None, + joint_train=False, + gan_train_steps=tfgan_tuples.GANTrainSteps(1, 1), + # TPUEstimator options. + model_dir=None, + config=None, + params=None, + use_tpu=True, + train_batch_size=None, + eval_batch_size=None, + predict_batch_size=None, + batch_axis=None, + eval_on_tpu=True, + export_to_tpu=True, + warm_start_from=None): + """Initializes a TPUGANEstimator instance. + + Args: + generator_fn: A python function that takes a Tensor, Tensor list, or + Tensor dictionary as inputs and returns the outputs of the GAN + generator. See `TFGAN` for more details and examples. Additionally, if + it has an argument called `mode`, the Estimator's `mode` will be passed + in (ex TRAIN, EVAL, PREDICT). This is useful for things like batch + normalization. + discriminator_fn: A python function that takes the output of + `generator_fn` or real data in the GAN setup, and `generator_inputs`. + Outputs a Tensor in the range [-inf, inf]. See `TFGAN` for more details + and examples. + generator_loss_fn: The loss function on the generator. Takes a `GANModel` + tuple. + discriminator_loss_fn: The loss function on the discriminator. Takes a + `GANModel` tuple. + generator_optimizer: The optimizer for generator updates, or a function + that takes no arguments and returns an optimizer. This function will + be called when the default graph is the `GANEstimator`'s graph, so + utilities like `tf.contrib.framework.get_or_create_global_step` will + work. + discriminator_optimizer: Same as `generator_optimizer`, but for the + discriminator updates. + get_eval_metric_ops_fn: A function that takes a list of arguments and + returns a dict of metric results keyed by name. The output of this + function is passed into `tf.estimator.EstimatorSpec` during evaluation. + The arguments must be: + * generator_inputs + * generated_data + * real_data + * discriminator_real_outputs + * discriminator_gen_outputs + add_summaries: `None`, a single `SummaryType`, or a list of `SummaryType`. + This is ignored for jobs that run on TPU, such as the train job if + `use_tpu` is `True` or the eval job if `eval_on_tpu` is `True`. + joint_train: A Python boolean. If `True`, jointly train the generator and + the discriminator. If `False`, sequentially train them. See `train.py` + in TFGAN for more details on the differences between the two GAN + training methods. + gan_train_steps: A `tfgan.GANTrainSteps` named tuple describing the ratio + of generator to discriminator steps. For now, only supports 1:1 + training. + model_dir: Same as `TPUEstimator`: Directory to save model parameters, + graph and etc. This can also be used to load checkpoints from the + directory into a estimator to continue training a previously saved + model. If `None`, the model_dir in `config` will be used if set. If both + are set, they must be same. If both are `None`, a temporary directory + will be used. + config: Same as `TPUEstimator`: An `tpu_config.RunConfig` configuration + object. Cannot be `None`. + params: Same as `TPUEstimator`: An optional `dict` of hyper parameters + that will be passed into `input_fn` and `model_fn`. Keys are names of + parameters, values are basic python types. There are reserved keys for + `TPUEstimator`, including 'batch_size'. + use_tpu: Same as `TPUEstimator`: A bool indicating whether TPU support is + enabled. Currently, TPU training and evaluation respect this bit, but + eval_on_tpu can override execution of eval. See below. Predict still + happens on CPU. + train_batch_size: Same as `TPUEstimator`: An int representing the global + training batch size. TPUEstimator transforms this global batch size to a + per-shard batch size, as params['batch_size'], when calling `input_fn` + and `model_fn`. Cannot be `None` if `use_tpu` is `True`. Must be + divisible by total number of replicas. + eval_batch_size: Same as `TPUEstimator`: An int representing evaluation + batch size. Must be divisible by total number of replicas. + predict_batch_size: Same as `TPUEstimator`: An int representing the + prediction batch size. Must be divisible by total number of replicas. + batch_axis: Same as `TPUEstimator`: A python tuple of int values + describing how each tensor produced by the Estimator `input_fn` should + be split across the TPU compute shards. For example, if your input_fn + produced (images, labels) where the images tensor is in `HWCN` format, + your shard dimensions would be [3, 0], where 3 corresponds to the `N` + dimension of your images Tensor, and 0 corresponds to the dimension + along which to split the labels to match up with the corresponding + images. If None is supplied, and per_host_input_for_training is True, + batches will be sharded based on the major dimension. If + tpu_config.per_host_input_for_training is False or `PER_HOST_V2`, + batch_axis is ignored. + eval_on_tpu: Same as `TPUEstimator`: If False, evaluation runs on CPU or + GPU. In this case, the model_fn must return `EstimatorSpec` when called + with `mode` as `EVAL`. + export_to_tpu: Same as `TPUEstimator`: If True, `export_savedmodel()` + exports a metagraph for serving on TPU besides the one on CPU. + warm_start_from: Same as `TPUEstimator`: Optional string filepath to a + checkpoint or SavedModel to warm-start from, or a + `tf.estimator.WarmStartSettings` object to fully configure + warm-starting. If the string filepath is provided instead of a + `WarmStartSettings`, then all variables are warm-started, and it is + assumed that vocabularies and Tensor names are unchanged. + + Raises: + ValueError: If loss functions aren't callable. + ValueError: If `gan_train_steps` isn't a `tfgan_tuples.GANTrainSteps` + tuple. + ValueError: If `gan_train_steps` isn't 1:1 training. + """ + if not callable(generator_loss_fn): + raise ValueError('generator_loss_fn must be callable.') + if not callable(discriminator_loss_fn): + raise ValueError('discriminator_loss_fn must be callable.') + if not isinstance(gan_train_steps, tfgan_tuples.GANTrainSteps): + raise ValueError( + '`gan_train_steps` must be `tfgan_tuples.GANTrainSteps`. Instead, ' + 'was type: %s' % type(gan_train_steps)) + if (gan_train_steps.generator_train_steps != 1 or + gan_train_steps.discriminator_train_steps != 1): + raise ValueError('Estimator currently only supports 1:1 training.') + + if use_tpu: + generator_optimizer = _maybe_make_cross_shard_optimizer( + generator_optimizer) + discriminator_optimizer = _maybe_make_cross_shard_optimizer( + discriminator_optimizer) + + def _model_fn(features, labels, mode, params): + """GANEstimator model function.""" + del params # unused + if mode not in [model_fn_lib.ModeKeys.TRAIN, model_fn_lib.ModeKeys.EVAL, + model_fn_lib.ModeKeys.PREDICT]: + raise ValueError('Mode not recognized: %s' % mode) + real_data = labels # rename inputs for clarity + generator_inputs = features # rename inputs for clarity + + # Make GANModel, which encapsulates the GAN model architectures. + # TODO(joelshor): Switch TF-GAN over to TPU-compatible summaries, then + # remove `add_summaries` logic below. + is_on_tpu = _is_on_tpu(mode, use_tpu, eval_on_tpu) + gan_model = gan_estimator_lib._get_gan_model( # pylint:disable=protected-access + mode, generator_fn, discriminator_fn, real_data, generator_inputs, + add_summaries=None if is_on_tpu else add_summaries) + + # Make the TPUEstimatorSpec, which incorporates the GANModel, losses, eval + # metrics, and optimizers (if required). + estimator_spec = _get_estimator_spec( + mode, gan_model, generator_loss_fn, discriminator_loss_fn, + get_eval_metric_ops_fn, generator_optimizer, discriminator_optimizer, + joint_train, is_on_tpu, gan_train_steps) + assert isinstance(estimator_spec, tpu_estimator.TPUEstimatorSpec) + return estimator_spec + + super(TPUGANEstimator, self).__init__( + model_fn=_model_fn, + model_dir=model_dir, + config=config, + params=params, + use_tpu=use_tpu, + train_batch_size=train_batch_size, + eval_batch_size=eval_batch_size, + predict_batch_size=predict_batch_size, + batch_axis=batch_axis, + eval_on_tpu=eval_on_tpu, + export_to_tpu=export_to_tpu, + warm_start_from=warm_start_from) + + +def _is_on_tpu(mode, use_tpu, eval_on_tpu): + if mode == model_fn_lib.ModeKeys.TRAIN: + return use_tpu + elif mode == model_fn_lib.ModeKeys.EVAL: + return eval_on_tpu + else: + return False + + +def _get_estimator_spec( + mode, gan_model, generator_loss_fn, discriminator_loss_fn, + get_eval_metric_ops_fn, generator_optimizer, discriminator_optimizer, + joint_train, is_on_tpu, gan_train_steps): + """Get the TPUEstimatorSpec for the current mode.""" + if mode == model_fn_lib.ModeKeys.PREDICT: + estimator_spec = tpu_estimator.TPUEstimatorSpec( + mode=mode, predictions={'generated_data': gan_model.generated_data}) + elif mode == model_fn_lib.ModeKeys.EVAL: + gan_loss = tfgan_tuples.GANLoss( + generator_loss=generator_loss_fn( + gan_model, add_summaries=not is_on_tpu), + discriminator_loss=discriminator_loss_fn( + gan_model, add_summaries=not is_on_tpu)) + # Eval losses for metrics must preserve batch dimension. + gan_loss_no_reduction = tfgan_tuples.GANLoss( + generator_loss=generator_loss_fn( + gan_model, add_summaries=False, reduction=losses.Reduction.NONE), + discriminator_loss=discriminator_loss_fn( + gan_model, add_summaries=False, reduction=losses.Reduction.NONE)) + estimator_spec = _get_eval_estimator_spec( + gan_model, gan_loss, gan_loss_no_reduction, get_eval_metric_ops_fn) + else: # model_fn_lib.ModeKeys.TRAIN: + gan_loss = tfgan_tuples.GANLoss( + generator_loss=generator_loss_fn(gan_model, add_summaries=False), + discriminator_loss=discriminator_loss_fn( + gan_model, add_summaries=False)) + + # Construct optimizers if arguments were callable. For TPUs, they must be + # `CrossShardOptimizer`. + g_callable = callable(generator_optimizer) + gopt = generator_optimizer() if g_callable else generator_optimizer + d_callable = callable(discriminator_optimizer) + dopt = discriminator_optimizer() if d_callable else discriminator_optimizer + + estimator_spec = _get_train_estimator_spec( + gan_model, gan_loss, gopt, dopt, joint_train, gan_train_steps) + + return estimator_spec + + +def _get_eval_estimator_spec(gan_model, gan_loss, gan_loss_no_reduction, + get_eval_metric_ops_fn): + """Return an TPUEstimatorSpec for the eval case.""" + # Make the metric function and tensor names. + if get_eval_metric_ops_fn is not None: + def metric_fn( + generator_inputs, generated_data, real_data, discriminator_real_outputs, + discriminator_gen_outputs, generator_loss, discriminator_loss): + """`metric_fn` used in TPUEstimator to calculate metrics.""" + eval_metric_ops = { + 'generator_loss': metrics_lib.mean(generator_loss), + 'discriminator_loss': metrics_lib.mean(discriminator_loss), + } + custom_eval_metric_ops = get_eval_metric_ops_fn( + generator_inputs, generated_data, real_data, + discriminator_real_outputs, discriminator_gen_outputs) + if not isinstance(custom_eval_metric_ops, dict): + raise TypeError('`get_eval_metric_ops_fn` must return a dict, ' + 'received: {}'.format(custom_eval_metric_ops)) + eval_metric_ops.update(custom_eval_metric_ops) + return eval_metric_ops + tensors = { + 'generator_loss': gan_loss_no_reduction.generator_loss, + 'discriminator_loss': gan_loss_no_reduction.discriminator_loss, + 'generator_inputs': gan_model.generator_inputs, + 'generated_data': gan_model.generated_data, + 'real_data': gan_model.real_data, + 'discriminator_real_outputs': gan_model.discriminator_real_outputs, + 'discriminator_gen_outputs': gan_model.discriminator_gen_outputs, + } + else: + def metric_fn(generator_loss, discriminator_loss): + return { + 'generator_loss': metrics_lib.mean(generator_loss), + 'discriminator_loss': metrics_lib.mean(discriminator_loss), + } + tensors = { + 'generator_loss': gan_loss_no_reduction.generator_loss, + 'discriminator_loss': gan_loss_no_reduction.discriminator_loss, + } + + scalar_loss = gan_loss.generator_loss + gan_loss.discriminator_loss + return tpu_estimator.TPUEstimatorSpec( + mode=model_fn_lib.ModeKeys.EVAL, + predictions=gan_model.generated_data, + loss=scalar_loss, + eval_metrics=(metric_fn, tensors)) + + +def _get_train_estimator_spec( + gan_model, gan_loss, generator_optimizer, discriminator_optimizer, + joint_train, gan_train_steps): + """Return a TPUEstimatorSpec for the train case.""" + scalar_loss = gan_loss.generator_loss + gan_loss.discriminator_loss + + # Get generator and discriminator update ops. We split them so that update + # ops aren't accidentally run multiple times. For now, throw an error if + # there are update ops that aren't associated with either the generator or + # the discriminator. Might modify the `kwargs` dictionary. + gen_update_ops, dis_update_ops = tfgan_train._get_update_ops( # pylint:disable=protected-access + {}, gan_model.generator_scope.name, gan_model.discriminator_scope.name) + + def gen_train_op(): + with ops.name_scope('generator_train'): + return training.create_train_op( + total_loss=gan_loss.generator_loss, + optimizer=generator_optimizer, + variables_to_train=gan_model.generator_variables, + update_ops=gen_update_ops) + def dis_train_op(): + with ops.name_scope('discriminator_train'): + return training.create_train_op( + total_loss=gan_loss.discriminator_loss, + optimizer=discriminator_optimizer, + variables_to_train=gan_model.discriminator_variables, + update_ops=dis_update_ops) + + # Either optimize the generator and discriminator sequentially or jointly. + tpu_train_op = _combine_train_ops(gen_train_op, dis_train_op, joint_train, + gan_train_steps) + + return tpu_estimator.TPUEstimatorSpec( + loss=scalar_loss, + mode=model_fn_lib.ModeKeys.TRAIN, + train_op=tpu_train_op) + + +# TODO(joelshor): Add support for multiple D / G steps. +def _combine_train_ops(gen_train_op, dis_train_op, joint_train, + gan_train_steps): + """Combine generator and discriminator train ops into a single op.""" + del gan_train_steps + if joint_train: + tpu_train_op = control_flow_ops.group(gen_train_op(), dis_train_op(), + name='joint_train') + else: + with ops.control_dependencies([dis_train_op()]): + tpu_train_op = gen_train_op() + + return tpu_train_op + + +def _maybe_make_cross_shard_optimizer(opt): + if callable(opt): + if not isinstance(opt(), tpu_optimizer.CrossShardOptimizer): + return lambda: tpu_optimizer.CrossShardOptimizer(opt()) + elif not isinstance(opt, tpu_optimizer.CrossShardOptimizer): + return tpu_optimizer.CrossShardOptimizer(opt) + return opt diff --git a/tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator_test.py b/tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator_test.py new file mode 100644 index 0000000000..0a08b4386f --- /dev/null +++ b/tensorflow/contrib/gan/python/estimator/python/tpu_gan_estimator_test.py @@ -0,0 +1,320 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for TFGAN's TPU Estimator.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import shutil +import tempfile + +from absl.testing import parameterized +import numpy as np +import six + +from tensorflow.contrib import layers +from tensorflow.contrib.gan.python import namedtuples as tfgan_tuples +from tensorflow.contrib.gan.python.estimator.python import tpu_gan_estimator_impl as estimator +from tensorflow.contrib.gan.python.losses.python import tuple_losses as losses +from tensorflow.contrib.tpu.python.tpu import tpu_config +from tensorflow.contrib.tpu.python.tpu import tpu_estimator +from tensorflow.contrib.tpu.python.tpu import tpu_optimizer +from tensorflow.python.data.ops import dataset_ops +from tensorflow.python.estimator import model_fn as model_fn_lib +from tensorflow.python.estimator.estimator import WarmStartSettings +from tensorflow.python.framework import ops +from tensorflow.python.framework import tensor_shape +from tensorflow.python.framework.errors_impl import NotFoundError +from tensorflow.python.ops import array_ops +from tensorflow.python.ops import metrics as metrics_lib +from tensorflow.python.ops import variable_scope +from tensorflow.python.platform import flags +from tensorflow.python.platform import test +from tensorflow.python.summary.writer import writer_cache +from tensorflow.python.training import learning_rate_decay +from tensorflow.python.training import training +from tensorflow.python.training import training_util + +FLAGS = flags.FLAGS + +flags.DEFINE_bool('use_tpu', False, 'Whether to run test on TPU or not.') + + +def generator_fn(noise, mode): + del mode + return layers.fully_connected(noise, tensor_shape.dimension_value( + noise.shape[1])) + + +def discriminator_fn(data, unused_conditioning, mode): + del unused_conditioning, mode + return layers.fully_connected(data, 1) + + +def get_dummy_gan_model(): + # TODO(joelshor): Find a better way of creating a variable scope. + with variable_scope.variable_scope('generator') as gen_scope: + gen_var = variable_scope.get_variable('dummy_var', initializer=0.0) + with variable_scope.variable_scope('discriminator') as dis_scope: + dis_var = variable_scope.get_variable('dummy_var', initializer=0.0) + return tfgan_tuples.GANModel( + generator_inputs=None, + generated_data=array_ops.ones([3, 4]), + generator_variables=[gen_var], + generator_scope=gen_scope, + generator_fn=None, + real_data=array_ops.zeros([3, 4]), + discriminator_real_outputs=array_ops.ones([1, 2, 3]) * dis_var, + discriminator_gen_outputs=array_ops.ones([1, 2, 3]) * gen_var * dis_var, + discriminator_variables=[dis_var], + discriminator_scope=dis_scope, + discriminator_fn=None) + + +def get_metrics(generator_inputs, generated_data, real_data, + discriminator_real_outputs, discriminator_gen_outputs): + del generator_inputs, discriminator_real_outputs, discriminator_gen_outputs + return { + 'mse_custom_metric': metrics_lib.mean_squared_error( + real_data, generated_data) + } + + +class GetTPUEstimatorSpecTest(test.TestCase, parameterized.TestCase): + """Tests that the EstimatorSpec is constructed appropriately.""" + + @classmethod + def setUpClass(cls): + super(GetTPUEstimatorSpecTest, cls).setUpClass() + cls._generator_optimizer = tpu_optimizer.CrossShardOptimizer( + training.GradientDescentOptimizer(1.0)) + cls._discriminator_optimizer = tpu_optimizer.CrossShardOptimizer( + training.GradientDescentOptimizer(1.0)) + + @parameterized.named_parameters( + ('joint_train', model_fn_lib.ModeKeys.TRAIN, True), + ('train_sequential', model_fn_lib.ModeKeys.TRAIN, False), + ('eval', model_fn_lib.ModeKeys.EVAL, None), + ('predict', model_fn_lib.ModeKeys.PREDICT, None)) + def test_get_estimator_spec(self, mode, joint_train): + with ops.Graph().as_default(): + self._gan_model = get_dummy_gan_model() + spec = estimator._get_estimator_spec( + mode, + self._gan_model, + generator_loss_fn=losses.wasserstein_generator_loss, + discriminator_loss_fn=losses.wasserstein_discriminator_loss, + get_eval_metric_ops_fn=get_metrics, + generator_optimizer=self._generator_optimizer, + discriminator_optimizer=self._discriminator_optimizer, + joint_train=joint_train, + is_on_tpu=FLAGS.use_tpu, + gan_train_steps=tfgan_tuples.GANTrainSteps(1, 1)) + + self.assertIsInstance(spec, tpu_estimator.TPUEstimatorSpec) + self.assertEqual(mode, spec.mode) + if mode == model_fn_lib.ModeKeys.PREDICT: + self.assertEqual({'generated_data': self._gan_model.generated_data}, + spec.predictions) + elif mode == model_fn_lib.ModeKeys.TRAIN: + self.assertShapeEqual(np.array(0), spec.loss) # must be a scalar + self.assertIsNotNone(spec.train_op) + self.assertIsNotNone(spec.training_hooks) + elif mode == model_fn_lib.ModeKeys.EVAL: + self.assertEqual(self._gan_model.generated_data, spec.predictions) + self.assertShapeEqual(np.array(0), spec.loss) # must be a scalar + self.assertIsNotNone(spec.eval_metrics) + + +class TPUGANEstimatorIntegrationTest(test.TestCase, parameterized.TestCase): + + def setUp(self): + super(TPUGANEstimatorIntegrationTest, self).setUp() + self._model_dir = tempfile.mkdtemp() + self._config = tpu_config.RunConfig(model_dir=self._model_dir) + + def tearDown(self): + super(TPUGANEstimatorIntegrationTest, self).tearDown() + if self._model_dir: + writer_cache.FileWriterCache.clear() + shutil.rmtree(self._model_dir) + + def _test_complete_flow( + self, train_input_fn, eval_input_fn, predict_input_fn, prediction_size, + lr_decay=False, joint_train=True): + def make_opt(): + gstep = training_util.get_or_create_global_step() + lr = learning_rate_decay.exponential_decay(1.0, gstep, 10, 0.9) + return training.GradientDescentOptimizer(lr) + + gopt = make_opt if lr_decay else training.GradientDescentOptimizer(1.0) + dopt = make_opt if lr_decay else training.GradientDescentOptimizer(1.0) + est = estimator.TPUGANEstimator( + generator_fn=generator_fn, + discriminator_fn=discriminator_fn, + generator_loss_fn=losses.wasserstein_generator_loss, + discriminator_loss_fn=losses.wasserstein_discriminator_loss, + generator_optimizer=gopt, + discriminator_optimizer=dopt, + joint_train=joint_train, + get_eval_metric_ops_fn=get_metrics, + train_batch_size=4, + eval_batch_size=10, + predict_batch_size=8, + use_tpu=FLAGS.use_tpu, + config=self._config) + + # Train. + num_steps_train = 10 + est.train(train_input_fn, steps=num_steps_train) + + # Evaluate. + num_steps_eval = 2 + scores = est.evaluate(eval_input_fn, steps=num_steps_eval) + self.assertEqual(num_steps_train + num_steps_eval, + scores[ops.GraphKeys.GLOBAL_STEP]) + self.assertIn('loss', six.iterkeys(scores)) + self.assertEqual(scores['discriminator_loss'] + scores['generator_loss'], + scores['loss']) + self.assertIn('mse_custom_metric', six.iterkeys(scores)) + + # Predict. + predictions = np.array([x['generated_data'] for x in + est.predict(predict_input_fn)]) + self.assertAllEqual(prediction_size, predictions.shape) + + @parameterized.named_parameters( + ('joint_train', True, False, False), + ('train_sequential', False, False, False), + ('lr_decay', False, True, False), + ('train_sequential_ds', False, False, True)) + def test_numpy_input_fn(self, joint_train, lr_decay, return_ds): + """Tests complete flow with numpy_input_fn.""" + input_dim = 4 + def train_input_fn(params): + data = np.zeros([input_dim], dtype=np.float32) + ds = (dataset_ops.Dataset + .from_tensors((data, data)) + .repeat() + .batch(params['batch_size'], drop_remainder=True)) + if return_ds: + return ds + else: + x, y = ds.make_one_shot_iterator().get_next() + return x, y + def eval_input_fn(params): + data = np.zeros([input_dim], dtype=np.float32) + ds = (dataset_ops.Dataset + .from_tensors((data, data)) + .repeat() + .batch(params['batch_size'], drop_remainder=True)) + if return_ds: + return ds + else: + x, y = ds.make_one_shot_iterator().get_next() + return x, y + predict_size = 10 + def predict_input_fn(params): + del params # unused + data = np.zeros([input_dim], dtype=np.float32) + ds = (dataset_ops.Dataset + .from_tensors(data) + .repeat(predict_size) + .batch(1, drop_remainder=True)) + return ds + + self._test_complete_flow( + train_input_fn=train_input_fn, + eval_input_fn=eval_input_fn, + predict_input_fn=predict_input_fn, + prediction_size=[predict_size, input_dim], + lr_decay=lr_decay, + joint_train=joint_train) + + +class TPUGANEstimatorWarmStartTest(test.TestCase): + + def setUp(self): + self._model_dir = self.get_temp_dir() + self._config = tpu_config.RunConfig(model_dir=self._model_dir) + self.new_variable_name = 'new_var' + self.new_variable_value = [1.0, 2.0, 3.0] + + def tearDown(self): + writer_cache.FileWriterCache.clear() + + def _test_warm_start(self, warm_start_from=None): + """Tests whether WarmStartSettings work as intended.""" + def generator_with_new_variable(noise_dict, mode): + variable_scope.get_variable(name=self.new_variable_name, + initializer=self.new_variable_value, + trainable=True) + return generator_fn(noise_dict, mode) + + est = estimator.TPUGANEstimator( + generator_fn=generator_fn, + discriminator_fn=discriminator_fn, + generator_loss_fn=losses.wasserstein_generator_loss, + discriminator_loss_fn=losses.wasserstein_discriminator_loss, + generator_optimizer=training.GradientDescentOptimizer(1.0), + discriminator_optimizer=training.GradientDescentOptimizer(1.0), + train_batch_size=4, + use_tpu=FLAGS.use_tpu, + config=self._config) + + def train_input_fn(params): + data = np.zeros([params['batch_size'], 4], dtype=np.float32) + return data, data + + est.train(train_input_fn, steps=1) + + est_warm = estimator.TPUGANEstimator( + generator_fn=generator_with_new_variable, + discriminator_fn=discriminator_fn, + generator_loss_fn=losses.wasserstein_generator_loss, + discriminator_loss_fn=losses.wasserstein_discriminator_loss, + generator_optimizer=training.GradientDescentOptimizer(1.0), + discriminator_optimizer=training.GradientDescentOptimizer(1.0), + config=tpu_config.RunConfig( + model_dir=None if warm_start_from else self._model_dir), + train_batch_size=4, + use_tpu=FLAGS.use_tpu, + warm_start_from=warm_start_from) + + est_warm.train(train_input_fn, steps=1) + + return est_warm + + def test_warm_start_error(self): + """Test if exception when reloading different estimators.""" + with self.assertRaises(NotFoundError): + self._test_warm_start() + + def test_warm_start_success(self): + """Test if GANEstimator allows explicit warm start variable assignment.""" + # Regex matches all variable names in ckpt except for new_var. + var_regex = '^(?!.*%s.*)' % self.new_variable_name + warmstart = WarmStartSettings(ckpt_to_initialize_from=self._model_dir, + vars_to_warm_start=var_regex) + est_warm = self._test_warm_start(warm_start_from=warmstart) + full_variable_name = 'Generator/%s' % self.new_variable_name + self.assertIn(full_variable_name, est_warm.get_variable_names()) + equal_vals = np.array_equal(est_warm.get_variable_value(full_variable_name), + self.new_variable_value) + self.assertTrue(equal_vals) + +if __name__ == '__main__': + test.main() -- GitLab From ed99e8fdd6e714e58216e89ae039a6bde8b122df Mon Sep 17 00:00:00 2001 From: Arpit Shah Date: Fri, 21 Dec 2018 10:37:20 -0600 Subject: [PATCH 0248/1765] Fixed gdb cmd files after formatting changes --- .../micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd | 8 ++++---- .../micro_speech/apollo3/pushbutton_cmsis_scores.cmd | 2 +- .../micro_speech/apollo3/pushbutton_cmsis_voice.cmd | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd index 5cc7a82c05..6988057f37 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/preprocessor_1k_cmsis_test.cmd @@ -10,22 +10,22 @@ file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_1k_cmsis_test target remote localhost:2331 load ../../../tools/make/gen/apollo3evb_cortex-m4/bin/preprocessor_1k_cmsis_test monitor reset -break preprocessor.cc:70 +break preprocessor.cc:68 commands dump verilog value cmsis_windowed_input.txt bufB c end -break preprocessor.cc:77 +break preprocessor.cc:76 commands dump verilog value cmsis_dft.txt bufA c end -break preprocessor.cc:82 +break preprocessor.cc:81 commands dump verilog value cmsis_power.txt bufB c end -break preprocessor.cc:84 +break preprocessor.cc:83 commands dump verilog memory cmsis_power_avg.txt output output+42 c diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd index e14ea2d83c..ace278ff9a 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_scores.cmd @@ -9,7 +9,7 @@ file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_te target remote localhost:2331 load ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test monitor reset -break pushbutton_main.c:322 +break pushbutton_main.c:307 commands printf "Silence score: %d\n", g_silence_score printf "Unknown score: %d\n", g_unknown_score diff --git a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd index b49f9d2d92..5dea48e62a 100644 --- a/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd +++ b/tensorflow/lite/experimental/micro/examples/micro_speech/apollo3/pushbutton_cmsis_voice.cmd @@ -17,7 +17,7 @@ file ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_te target remote localhost:2331 load ../../../tools/make/gen/apollo3evb_cortex-m4/bin/pushbutton_cmsis_speech_test monitor reset -break pushbutton_main.c:313 +break pushbutton_main.c:296 commands dump verilog value captured_data.txt captured_data c -- GitLab From 8aa05f01046dddcfca29faa0714789e2be31fbc4 Mon Sep 17 00:00:00 2001 From: Eugene Zhulenev Date: Fri, 21 Dec 2018 08:41:01 -0800 Subject: [PATCH 0249/1765] Use consistent typedefs in conv_ops_fused.cc. PiperOrigin-RevId: 226494875 --- tensorflow/core/kernels/conv_ops_fused.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tensorflow/core/kernels/conv_ops_fused.cc b/tensorflow/core/kernels/conv_ops_fused.cc index fd0c565677..551782c488 100644 --- a/tensorflow/core/kernels/conv_ops_fused.cc +++ b/tensorflow/core/kernels/conv_ops_fused.cc @@ -59,11 +59,11 @@ limitations under the License. #endif // GOOGLE_CUDA namespace tensorflow { -namespace { -using CPUDevice = ::Eigen::ThreadPoolDevice; -using GPUDevice = ::Eigen::GpuDevice; +typedef Eigen::ThreadPoolDevice CPUDevice; +typedef Eigen::GpuDevice GPUDevice; +namespace { // Supported Conv2D fusions. Not all of them supported on all type of devices. enum class FusedComputationType { // NOTE(ezhulenev): CuDNN `cudnnConvolutionBiasActivationForward` supports -- GitLab From 7859702e8a7093f242c167ea027cc227f1f9d048 Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Fri, 21 Dec 2018 08:57:29 -0800 Subject: [PATCH 0250/1765] Fix failing test in TRT4.0 - TRT bug with tensors rank < 3 in INT8 mode --- tensorflow/contrib/tensorrt/test/identity_output_test.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tensorflow/contrib/tensorrt/test/identity_output_test.py b/tensorflow/contrib/tensorrt/test/identity_output_test.py index 2be9da9ede..da7d70876d 100644 --- a/tensorflow/contrib/tensorrt/test/identity_output_test.py +++ b/tensorflow/contrib/tensorrt/test/identity_output_test.py @@ -71,6 +71,11 @@ class IdentityTest(trt_test.TfTrtIntegrationTestBase): """Return the expected engines to build.""" return ["TRTEngineOp_0"] + def ShouldRunTest(self, run_params): + """Whether to run the test.""" + # TODO(aaroey): Trt 4.0 forbids conversion for tensors with rank <3 in int8 + # mode, which is a bug. Re-enable this when trt library is fixed. + return not trt_test.IsQuantizationMode(run_params.precision_mode) if __name__ == "__main__": test.main() -- GitLab From 753a3a3d7fa79e390ac8c068dc52acd03e0e4187 Mon Sep 17 00:00:00 2001 From: Trevor Morris Date: Fri, 21 Dec 2018 09:07:40 -0800 Subject: [PATCH 0251/1765] Report size and size limit with error message --- tensorflow/core/grappler/optimizers/constant_folding.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tensorflow/core/grappler/optimizers/constant_folding.cc b/tensorflow/core/grappler/optimizers/constant_folding.cc index 89be08800d..8804dedad1 100644 --- a/tensorflow/core/grappler/optimizers/constant_folding.cc +++ b/tensorflow/core/grappler/optimizers/constant_folding.cc @@ -983,7 +983,8 @@ Status ConstantFolding::CreateNodeDef(const string& name, if (encoded_size > original_size && encoded_size >= 10 * 1024 * 1024) { return errors::InvalidArgument( - strings::StrCat("Can't fold ", name, ", its size would be too large")); + strings::StrCat("Can't fold ", name, ", its size would be too large (", + encoded_size, " >= ", 10 * 1024 * 1024, " bytes)")); } return Status::OK(); } -- GitLab From ef1fd4ab6cb076aee9af7801f5b66fb66a768fc4 Mon Sep 17 00:00:00 2001 From: Mahmoud Abuzaina Date: Fri, 21 Dec 2018 09:37:24 -0800 Subject: [PATCH 0252/1765] Moved #endif of MKL --- tensorflow/core/ops/nn_ops.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow/core/ops/nn_ops.cc b/tensorflow/core/ops/nn_ops.cc index c7cd3140be..24d774ef59 100644 --- a/tensorflow/core/ops/nn_ops.cc +++ b/tensorflow/core/ops/nn_ops.cc @@ -2515,6 +2515,7 @@ NOTE Do not invoke this operator directly in Python. Graph rewrite pass is expected to invoke these operators. )doc"); +#endif // INTEL_MKL REGISTER_OP("QuantizedConv2DAndRequantize") .Input("input: Tinput") .Input("filter: Tfilter") @@ -2851,6 +2852,5 @@ REGISTER_OP("QuantizedConv2DWithBiasSignedSumAndReluAndRequantize") return Status::OK(); }); -#endif // INTEL_MKL } // namespace tensorflow -- GitLab From 253b5373ba72e6498be23800bc2740f327385c03 Mon Sep 17 00:00:00 2001 From: Jianwei Xie Date: Fri, 21 Dec 2018 09:50:10 -0800 Subject: [PATCH 0253/1765] Removes the complexity of the combinations in correctness test. And make non-supported case more explicit either in combinations or test cases. PiperOrigin-RevId: 226502799 --- .../python/keras_correctness_test.py | 67 +++++++++---------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/tensorflow/contrib/distribute/python/keras_correctness_test.py b/tensorflow/contrib/distribute/python/keras_correctness_test.py index 8247105074..558759b6b5 100644 --- a/tensorflow/contrib/distribute/python/keras_correctness_test.py +++ b/tensorflow/contrib/distribute/python/keras_correctness_test.py @@ -26,6 +26,7 @@ from tensorflow.contrib.distribute.python import tpu_strategy from tensorflow.python import keras from tensorflow.python.data.ops import dataset_ops from tensorflow.python.distribute import distribute_lib +from tensorflow.python.eager import context from tensorflow.python.eager import test from tensorflow.python.framework import random_seed from tensorflow.python.keras.engine import distributed_training_utils @@ -170,54 +171,32 @@ def get_correctness_test_inputs(use_numpy, use_validation_data, return training_inputs, eval_inputs, predict_inputs -strategies_minus_tpu = [ +all_strategies = [ combinations.default_strategy, combinations.one_device_strategy, combinations.mirrored_strategy_with_gpu_and_cpu, combinations.mirrored_strategy_with_two_gpus, combinations.core_mirrored_strategy_with_gpu_and_cpu, - combinations.core_mirrored_strategy_with_two_gpus] - -tpu_strategies = [ + combinations.core_mirrored_strategy_with_two_gpus, combinations.tpu_strategy, # steps_per_run=2 - combinations.tpu_strategy_one_step] - - -def strategy_minus_tpu_combinations(): - return combinations.combine( - distribution=strategies_minus_tpu, - mode=['graph', 'eager']) - + combinations.tpu_strategy_one_step, +] -def tpu_strategy_combinations(): - return combinations.combine( - distribution=tpu_strategies, - mode=['graph']) - -def all_strategy_combinations(): - return strategy_minus_tpu_combinations() + tpu_strategy_combinations() +def all_strategy_combinations_with_eager_and_graph_modes(): + return combinations.combine(distribution=all_strategies, + mode=['graph', 'eager']) def all_strategy_combinations_with_graph_mode(): - return combinations.combine( - distribution=strategies_minus_tpu, - mode=['graph']) + tpu_strategy_combinations() + return combinations.combine(distribution=all_strategies, mode=['graph']) def strategy_and_input_combinations(): return ( combinations.times( - combinations.combine(distribution=strategies_minus_tpu), - combinations.combine(mode=['graph'], - use_numpy=[True, False], - use_validation_data=[True, False]) - + combinations.combine(mode=['eager'], - use_numpy=[False], - use_validation_data=[False])) + - combinations.times( - combinations.combine(distribution=tpu_strategies), - combinations.combine(mode=['graph'], + combinations.combine(distribution=all_strategies), + combinations.combine(mode=['graph', 'eager'], use_numpy=[True, False], use_validation_data=[True, False]))) @@ -302,8 +281,15 @@ class LearningRateBatchScheduler(keras.callbacks.Callback): class TestDistributionStrategyCorrectness(test.TestCase, parameterized.TestCase): - @combinations.generate(all_strategy_combinations()) + def _should_skip_tpu_with_eager(self, distribution): + return (context.executing_eagerly() and + isinstance(distribution, tpu_strategy.TPUStrategy)) + + @combinations.generate(all_strategy_combinations_with_eager_and_graph_modes()) def test_metric_correctness(self, distribution): + if self._should_skip_tpu_with_eager(distribution): + self.skipTest('TPUStrategy does not support eager mode now.') + with self.cached_session(): keras.backend.set_image_data_format('channels_last') num_samples = 10000 @@ -334,8 +320,11 @@ class TestDistributionStrategyCorrectness(test.TestCase, history = model.fit(x=train_dataset, epochs=2, steps_per_epoch=10) self.assertEqual(history.history['binary_accuracy'], [1.0, 1.0]) - @combinations.generate(all_strategy_combinations()) + @combinations.generate(all_strategy_combinations_with_eager_and_graph_modes()) def test_eval_metrics_correctness(self, distribution): + if self._should_skip_tpu_with_eager(distribution): + self.skipTest('TPUStrategy does not support eager mode now.') + with self.cached_session(): with distribution.scope(): model = keras.Sequential() @@ -368,6 +357,15 @@ class TestDistributionStrategyCorrectness(test.TestCase, @combinations.generate(strategy_and_input_combinations()) def test_correctness(self, distribution, use_numpy, use_validation_data): + if self._should_skip_tpu_with_eager(distribution): + self.skipTest('TPUStrategy does not support eager mode now.') + + if context.executing_eagerly() and use_numpy: + self.skipTest('Numpy as inputs is not supported with strategy in eager.') + + if context.executing_eagerly() and use_validation_data: + self.skipTest('TODO') + with self.cached_session(): keras.backend.set_image_data_format('channels_last') @@ -404,6 +402,7 @@ class TestDistributionStrategyCorrectness(test.TestCase, @combinations.generate(all_strategy_combinations_with_graph_mode()) def test_dynamic_lr(self, distribution): + with self.cached_session(): keras.backend.set_image_data_format('channels_last') -- GitLab From 5c06cceb449da594e439ea16c78b075ef09de31c Mon Sep 17 00:00:00 2001 From: Allen Lavoie Date: Fri, 21 Dec 2018 10:24:05 -0800 Subject: [PATCH 0254/1765] Very basic checkpointing + XLA/TPU integration test PiperOrigin-RevId: 226507973 --- .../python/training/checkpointable/BUILD | 23 +++++ .../training/checkpointable/util_xla_test.py | 84 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 tensorflow/python/training/checkpointable/util_xla_test.py diff --git a/tensorflow/python/training/checkpointable/BUILD b/tensorflow/python/training/checkpointable/BUILD index 3201c755af..15280198d4 100644 --- a/tensorflow/python/training/checkpointable/BUILD +++ b/tensorflow/python/training/checkpointable/BUILD @@ -12,6 +12,7 @@ licenses(["notice"]) # Apache 2.0 exports_files(["LICENSE"]) load("//tensorflow:tensorflow.bzl", "py_test") +load("//tensorflow/compiler/tests:build_defs.bzl", "tf_xla_py_test") py_library( name = "base", @@ -164,6 +165,28 @@ py_test( ], ) +tf_xla_py_test( + name = "util_xla_test", + srcs = ["util_xla_test.py"], + tags = [ + "no_pip", + "notsan", # b/74395663 + ], + deps = [ + ":tracking", + ":util", + "//tensorflow/compiler/tests:xla_test", + "//tensorflow/python:checkpoint_management", + "//tensorflow/python:client_testlib", + "//tensorflow/python:constant_op", + "//tensorflow/python:framework_ops", + "//tensorflow/python/eager:backprop", + "//tensorflow/python/keras:engine", + "//tensorflow/python/keras:layers", + "//tensorflow/python/keras/optimizer_v2", + ], +) + py_test( name = "util_with_v1_optimizers_test", srcs = ["util_with_v1_optimizers_test.py"], diff --git a/tensorflow/python/training/checkpointable/util_xla_test.py b/tensorflow/python/training/checkpointable/util_xla_test.py new file mode 100644 index 0000000000..d80ac003b4 --- /dev/null +++ b/tensorflow/python/training/checkpointable/util_xla_test.py @@ -0,0 +1,84 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +from tensorflow.compiler.tests import xla_test +from tensorflow.python.eager import backprop +from tensorflow.python.framework import constant_op +from tensorflow.python.framework import ops +from tensorflow.python.keras.engine import training +from tensorflow.python.keras.layers import core +from tensorflow.python.keras.optimizer_v2 import adam +from tensorflow.python.platform import test +from tensorflow.python.training import checkpoint_management +from tensorflow.python.training.checkpointable import tracking +from tensorflow.python.training.checkpointable import util as checkpointable_utils + + +class NonLayerCheckpointable(tracking.Checkpointable): + + def __init__(self): + super(NonLayerCheckpointable, self).__init__() + self.a_variable = checkpointable_utils.add_variable( + self, name="a_variable", shape=[]) + + +class Subclassed(training.Model): + """A concrete Model for testing.""" + + def __init__(self): + super(Subclassed, self).__init__() + self._named_dense = core.Dense(1, use_bias=True) + self._second = core.Dense(1, use_bias=False) + # We can still track Checkpointables which aren't Layers. + self._non_layer = NonLayerCheckpointable() + + def call(self, values): + ret = self._second(self._named_dense(values)) + return ret + + +class CheckpointingTests(xla_test.XLATestCase): + + def testDeferredRestorationUsageEager(self): + """An idiomatic eager execution example.""" + num_training_steps = 10 + checkpoint_directory = self.get_temp_dir() + for training_continuation in range(3): + with self.test_scope(): + model = Subclassed() + optimizer = adam.Adam(0.001) + root = checkpointable_utils.Checkpoint( + optimizer=optimizer, model=model) + manager = checkpoint_management.CheckpointManager( + root, checkpoint_directory, max_to_keep=2) + root.restore(manager.latest_checkpoint) + for _ in range(num_training_steps): + input_value = constant_op.constant([[3.]]) + with backprop.GradientTape() as tape: + loss = model(input_value) + variables = model.trainable_variables + gradients = tape.gradient(loss, variables) + optimizer.apply_gradients(zip(gradients, variables)) + manager.save() + self.assertEqual((training_continuation + 1) * num_training_steps, + root.optimizer.iterations.numpy()) + + +if __name__ == "__main__": + ops.enable_eager_execution() + test.main() -- GitLab From e564b38a13f69fb1e64e530ba9d7f52009ce164e Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 10:39:06 -0800 Subject: [PATCH 0255/1765] Automated rollback of commit 6a6658f3e2bae16e2d0067fcb7d7cb0850272d1b PiperOrigin-RevId: 226510225 --- tensorflow/lite/python/BUILD | 1 + tensorflow/lite/python/lite.py | 44 ++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/tensorflow/lite/python/BUILD b/tensorflow/lite/python/BUILD index b0ca3f8dcc..e666812bd2 100644 --- a/tensorflow/lite/python/BUILD +++ b/tensorflow/lite/python/BUILD @@ -61,6 +61,7 @@ py_library( ":lite_constants", ":op_hint", "//tensorflow/python:graph_util", + "//tensorflow/python:tf_optimizer", "//tensorflow/python/keras", "//tensorflow/python/saved_model:constants", "//tensorflow/python/saved_model:loader", diff --git a/tensorflow/lite/python/lite.py b/tensorflow/lite/python/lite.py index 1b20ff2f92..0f9b1312c7 100644 --- a/tensorflow/lite/python/lite.py +++ b/tensorflow/lite/python/lite.py @@ -53,19 +53,49 @@ from tensorflow.lite.python.interpreter import Interpreter # pylint: disable=un from tensorflow.lite.python.op_hint import convert_op_hints_to_stubs # pylint: disable=unused-import from tensorflow.lite.python.op_hint import OpHint # pylint: disable=unused-import from tensorflow.core.framework import graph_pb2 as _graph_pb2 +from tensorflow.core.protobuf import rewriter_config_pb2 as _rewriter_config_pb2 +from tensorflow.core.protobuf import config_pb2 as _config_pb2 +from tensorflow.core.protobuf import meta_graph_pb2 as _meta_graph_pb2 from tensorflow.python import keras as _keras from tensorflow.python.client import session as _session from tensorflow.python.framework import graph_util as _tf_graph_util from tensorflow.python.framework import ops as _ops from tensorflow.python.framework.errors_impl import NotFoundError as _NotFoundError from tensorflow.python.framework.importer import import_graph_def as _import_graph_def +from tensorflow.python.grappler import tf_optimizer as _tf_optimizer from tensorflow.python.lib.io import file_io as _file_io from tensorflow.python.saved_model import signature_constants as _signature_constants from tensorflow.python.saved_model import tag_constants as _tag_constants +from tensorflow.python.training.saver import export_meta_graph as _export_meta_graph from tensorflow.python.util import deprecation as _deprecation from tensorflow.python.util.tf_export import tf_export as _tf_export +def _run_graph_optimizations(graph_def, output_arrays): + """Apply standard TensorFlow optimizations to the graph_def. + + Args: + graph_def: Frozen GraphDef to be optimized. + output_arrays: List of arrays that are considered outputs of the graph. + + Returns: + A new, optimized GraphDef. + """ + meta_graph = _export_meta_graph(graph_def=graph_def) + + # We need to add a collection called 'train_op' so that grappler + # knows what the outputs are. + fetch_collection = _meta_graph_pb2.CollectionDef() + for output in output_arrays: + fetch_collection.node_list.value.append(output) + meta_graph.collection_def["train_op"].CopyFrom(fetch_collection) + + config = _config_pb2.ConfigProto() + rewrite_options = config.graph_options.rewrite_options + rewrite_options.layout_optimizer = _rewriter_config_pb2.RewriterConfig.ON + return _tf_optimizer.OptimizeGraph(config, meta_graph) + + @_tf_export("lite.TFLiteConverter") class TFLiteConverter(object): """Convert a TensorFlow model into `output_format` using TOCO. @@ -446,16 +476,26 @@ class TFLiteConverter(object): "dump_graphviz_video": self.dump_graphviz_video } + optimized_graph = None + if self.inference_type == constants.QUANTIZED_UINT8: + optimized_graph = self._graph_def + else: + try: + optimized_graph = _run_graph_optimizations( + self._graph_def, [t.name for t in self._output_tensors]) + except Exception: + optimized_graph = self._graph_def + # Converts model. if self._has_valid_tensors(): result = _toco_convert_impl( - input_data=self._graph_def, + input_data=optimized_graph, input_tensors=self._input_tensors, output_tensors=self._output_tensors, **converter_kwargs) else: result = _toco_convert_graph_def( - input_data=self._graph_def, + input_data=optimized_graph, input_arrays_with_shape=self._input_arrays_with_shape, output_arrays=self._output_arrays, **converter_kwargs) -- GitLab From 95adb6773a96d9c7358e04a8e290812ef058abb6 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 10:39:16 -0800 Subject: [PATCH 0256/1765] This CL adds support for output profiler filenames containing "=" character. PiperOrigin-RevId: 226510244 --- tensorflow/core/profiler/tfprof_options.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tensorflow/core/profiler/tfprof_options.cc b/tensorflow/core/profiler/tfprof_options.cc index 9e5ef0a0a3..faca22c425 100644 --- a/tensorflow/core/profiler/tfprof_options.cc +++ b/tensorflow/core/profiler/tfprof_options.cc @@ -96,7 +96,7 @@ tensorflow::Status ParseOutput(const string& output_opt, string* output_type, for (const string& kv_str : kv_split) { const std::vector kv = str_util::Split(kv_str, "=", str_util::SkipEmpty()); - if (kv.size() != 2) { + if (kv.size() < 2) { return tensorflow::Status( tensorflow::error::INVALID_ARGUMENT, "Visualize format: -output timeline:key=value,key=value,..."); @@ -107,7 +107,8 @@ tensorflow::Status ParseOutput(const string& output_opt, string* output_type, strings::Printf("Unrecognized options %s for output_type: %s\n", kv[0].c_str(), output_type->c_str())); } - (*output_options)[kv[0]] = kv[1]; + const std::vector kv_without_key(kv.begin() + 1, kv.end()); + (*output_options)[kv[0]] = str_util::Join(kv_without_key, "="); } for (const string& opt : required_options) { -- GitLab From a4fc501faa66dbf2584b0fdb2810407df935f84c Mon Sep 17 00:00:00 2001 From: Alexandre Passos Date: Fri, 21 Dec 2018 10:57:18 -0800 Subject: [PATCH 0257/1765] Another dtype for which zeros is not well defined. PiperOrigin-RevId: 226512760 --- tensorflow/python/eager/backprop.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tensorflow/python/eager/backprop.py b/tensorflow/python/eager/backprop.py index 2c0f68365c..7d99f6e95a 100644 --- a/tensorflow/python/eager/backprop.py +++ b/tensorflow/python/eager/backprop.py @@ -595,7 +595,9 @@ def _fast_fill(value, shape, dtype): def _zeros(shape, dtype): """Helper to return (possibly cached) zero tensors in eager mode.""" - if dtype == dtypes.variant or dtype == dtypes.string: + if (dtype == dtypes.variant + or dtype == dtypes.string + or dtype == dtypes.resource): # TODO(apassos): need to save enough information about variant tensors to do # a zeros return None -- GitLab From d2fb56b6431a3c509710b6654a93d853de6334ad Mon Sep 17 00:00:00 2001 From: Pavithra Vijay Date: Fri, 21 Dec 2018 10:58:08 -0800 Subject: [PATCH 0258/1765] Adding mean absolute error, mean absolute percentage error, mean squared error, mean squared logarithmic error V2 metrics. PiperOrigin-RevId: 226512910 --- tensorflow/python/keras/metrics.py | 131 +++++++++++++++++++++++ tensorflow/python/keras/metrics_test.py | 134 ++++++++++++++++++++++++ 2 files changed, 265 insertions(+) diff --git a/tensorflow/python/keras/metrics.py b/tensorflow/python/keras/metrics.py index 8ccb514ba9..9a2e28abf8 100644 --- a/tensorflow/python/keras/metrics.py +++ b/tensorflow/python/keras/metrics.py @@ -1519,6 +1519,137 @@ class CosineProximity(MeanMetricWrapper): return super(CosineProximity, cls).from_config(config) +class MeanAbsoluteError(MeanMetricWrapper): + """Computes the mean absolute error between the labels and predictions. + + For example, if `y_true` is [0., 0., 1., 1.], and `y_pred` is [1., 1., 1., 0.] + the mean absolute error is 3/4 (0.75). + + Usage: + ```python + mae = tf.metrics.MeanAbsoluteError() + mae.update_state([0., 0., 1., 1.], [1., 1., 1., 0.]) + print('Final result: ', m.result().numpy()) # Final result: 0.75 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.MeanAbsoluteError()) + ``` + """ + + def __init__(self, name='mean_absolute_error', dtype=None): + super(MeanAbsoluteError, self).__init__( + mean_absolute_error, name, dtype=dtype) + + @classmethod + def from_config(cls, config): + if 'fn' in config: + config.pop('fn') + return super(MeanAbsoluteError, cls).from_config(config) + + +class MeanAbsolutePercentageError(MeanMetricWrapper): + """Computes the mean absolute percentage error between `y_true` and `y_pred`. + + For example, if `y_true` is [0., 0., 1., 1.], and `y_pred` is [1., 1., 1., 0.] + the mean absolute percentage error is 5e+08. + + Usage: + + ```python + mape = tf.keras.losses.MeanAbsolutePercentageError() + mape.update_state([0., 0., 1., 1.], [1., 1., 1., 0.]) + print('Final result: ', m.result().numpy()) # Final result: 5e+08 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.MeanAbsolutePercentageError()) + ``` + """ + + def __init__(self, name='mean_absolute_percentage_error', dtype=None): + super(MeanAbsolutePercentageError, self).__init__( + mean_absolute_percentage_error, name, dtype=dtype) + + @classmethod + def from_config(cls, config): + if 'fn' in config: + config.pop('fn') + return super(MeanAbsolutePercentageError, cls).from_config(config) + + +class MeanSquaredError(MeanMetricWrapper): + """Computes the mean squared error between `y_true` and `y_pred`. + + For example, if `y_true` is [0., 0., 1., 1.], and `y_pred` is [1., 1., 1., 0.] + the mean squared error is 3/4 (0.75). + + Usage: + + ```python + mape = tf.keras.losses.MeanSquaredError() + mape.update_state([0., 0., 1., 1.], [1., 1., 1., 0.]) + print('Final result: ', m.result().numpy()) # Final result: 0.75 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.MeanSquaredError()) + ``` + """ + + def __init__(self, name='mean_squared_error', dtype=None): + super(MeanSquaredError, self).__init__( + mean_squared_error, name, dtype=dtype) + + @classmethod + def from_config(cls, config): + if 'fn' in config: + config.pop('fn') + return super(MeanSquaredError, cls).from_config(config) + + +class MeanSquaredLogarithmicError(MeanMetricWrapper): + """Computes the mean squared logarithmic error between `y_true` and `y_pred`. + + For example, if `y_true` is [0., 0., 1., 1.], and `y_pred` is [1., 1., 1., 0.] + the mean squared logarithmic error is 0.36034. + + Usage: + + ```python + msle = tf.keras.losses.MeanSquaredLogarithmicError() + msle.update_state([0., 0., 1., 1.], [1., 1., 1., 0.]) + print('Final result: ', m.result().numpy()) # Final result: 0.36034 + ``` + + Usage with tf.keras API: + + ```python + model = keras.models.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.MeanSquaredLogarithmicError()) + ``` + """ + + def __init__(self, name='mean_squared_logarithmic_error', dtype=None): + super(MeanSquaredLogarithmicError, self).__init__( + mean_squared_logarithmic_error, name, dtype=dtype) + + @classmethod + def from_config(cls, config): + if 'fn' in config: + config.pop('fn') + return super(MeanSquaredLogarithmicError, cls).from_config(config) + + def accuracy(y_true, y_pred): y_pred.get_shape().assert_is_compatible_with(y_true.get_shape()) if y_true.dtype != y_pred.dtype: diff --git a/tensorflow/python/keras/metrics_test.py b/tensorflow/python/keras/metrics_test.py index 9720d910eb..058960852a 100644 --- a/tensorflow/python/keras/metrics_test.py +++ b/tensorflow/python/keras/metrics_test.py @@ -975,6 +975,140 @@ class CosineProximityTest(test.TestCase): self.assertAllClose(-0.59916, self.evaluate(result), atol=1e-5) +@test_util.run_all_in_graph_and_eager_modes +class MeanAbsoluteErrorTest(test.TestCase): + + def test_config(self): + mae_obj = metrics.MeanAbsoluteError(name='my_mae', dtype=dtypes.int32) + self.assertEqual(mae_obj.name, 'my_mae') + self.assertEqual(mae_obj._dtype, dtypes.int32) + + def test_unweighted(self): + mae_obj = metrics.MeanAbsoluteError() + self.evaluate(variables.variables_initializer(mae_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + + update_op = mae_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = mae_obj.result() + self.assertAllClose(0.5, result, atol=1e-5) + + def test_weighted(self): + mae_obj = metrics.MeanAbsoluteError() + self.evaluate(variables.variables_initializer(mae_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + sample_weight = constant_op.constant((1., 1.5, 2., 2.5)) + result = mae_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose(0.54285, self.evaluate(result), atol=1e-5) + + +@test_util.run_all_in_graph_and_eager_modes +class MeanAbsolutePercentageErrorTest(test.TestCase): + + def test_config(self): + mape_obj = metrics.MeanAbsolutePercentageError( + name='my_mape', dtype=dtypes.int32) + self.assertEqual(mape_obj.name, 'my_mape') + self.assertEqual(mape_obj._dtype, dtypes.int32) + + def test_unweighted(self): + mape_obj = metrics.MeanAbsolutePercentageError() + self.evaluate(variables.variables_initializer(mape_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + + update_op = mape_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = mape_obj.result() + self.assertAllClose(35e7, result, atol=1e-5) + + def test_weighted(self): + mape_obj = metrics.MeanAbsolutePercentageError() + self.evaluate(variables.variables_initializer(mape_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + sample_weight = constant_op.constant((1., 1.5, 2., 2.5)) + result = mape_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose(40e7, self.evaluate(result), atol=1e-5) + + +@test_util.run_all_in_graph_and_eager_modes +class MeanSquaredErrorTest(test.TestCase): + + def test_config(self): + mse_obj = metrics.MeanSquaredError(name='my_mse', dtype=dtypes.int32) + self.assertEqual(mse_obj.name, 'my_mse') + self.assertEqual(mse_obj._dtype, dtypes.int32) + + def test_unweighted(self): + mse_obj = metrics.MeanSquaredError() + self.evaluate(variables.variables_initializer(mse_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + + update_op = mse_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = mse_obj.result() + self.assertAllClose(0.5, result, atol=1e-5) + + def test_weighted(self): + mse_obj = metrics.MeanSquaredError() + self.evaluate(variables.variables_initializer(mse_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + sample_weight = constant_op.constant((1., 1.5, 2., 2.5)) + result = mse_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose(0.54285, self.evaluate(result), atol=1e-5) + + +@test_util.run_all_in_graph_and_eager_modes +class MeanSquaredLogarithmicErrorTest(test.TestCase): + + def test_config(self): + msle_obj = metrics.MeanSquaredLogarithmicError( + name='my_msle', dtype=dtypes.int32) + self.assertEqual(msle_obj.name, 'my_msle') + self.assertEqual(msle_obj._dtype, dtypes.int32) + + def test_unweighted(self): + msle_obj = metrics.MeanSquaredLogarithmicError() + self.evaluate(variables.variables_initializer(msle_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + + update_op = msle_obj.update_state(y_true, y_pred) + self.evaluate(update_op) + result = msle_obj.result() + self.assertAllClose(0.24022, result, atol=1e-5) + + def test_weighted(self): + msle_obj = metrics.MeanSquaredLogarithmicError() + self.evaluate(variables.variables_initializer(msle_obj.variables)) + y_true = constant_op.constant(((0, 1, 0, 1, 0), (0, 0, 1, 1, 1), + (1, 1, 1, 1, 0), (0, 0, 0, 0, 1))) + y_pred = constant_op.constant(((0, 0, 1, 1, 0), (1, 1, 1, 1, 1), + (0, 1, 0, 1, 0), (1, 1, 1, 1, 1))) + sample_weight = constant_op.constant((1., 1.5, 2., 2.5)) + result = msle_obj(y_true, y_pred, sample_weight=sample_weight) + self.assertAllClose(0.26082, self.evaluate(result), atol=1e-5) + + def _get_model(compile_metrics): model_layers = [ layers.Dense(3, activation='relu', kernel_initializer='ones'), -- GitLab From a76b3af1c33425fd01e7b3826de321c22e509760 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 10:59:25 -0800 Subject: [PATCH 0259/1765] Rename run_deprecated_v1 to deprecated_graph_mode_only and maintain it as an alias PiperOrigin-RevId: 226513083 --- tensorflow/python/framework/test_util.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tensorflow/python/framework/test_util.py b/tensorflow/python/framework/test_util.py index c663af2ee4..65b103f72c 100644 --- a/tensorflow/python/framework/test_util.py +++ b/tensorflow/python/framework/test_util.py @@ -1034,13 +1034,13 @@ def also_run_as_tf_function(f): return decorated -def run_deprecated_v1(func=None): +def deprecated_graph_mode_only(func=None): """Execute the decorated test in graph mode. - This function returns a decorator intended to be applied to tests that have - not been updated to a style that is compatible with both TensorFlow 1.x and - 2.x. When this decorated is applied, the test body will be run in - an environment where API calls construct graphs instead of executing eagerly. + This function returns a decorator intended to be applied to tests that are not + compatible with eager mode. When this decorator is applied, the test body will + be run in an environment where API calls construct graphs instead of executing + eagerly. Args: func: function to be annotated. If `func` is None, this method returns a @@ -1078,6 +1078,9 @@ def run_deprecated_v1(func=None): return decorator +run_deprecated_v1 = deprecated_graph_mode_only + + def run_v1_only(reason, func=None): """Execute the decorated test only if running in v1 mode. -- GitLab From 0f34db762d19f28be4d3371f2935983ea3e7fa6c Mon Sep 17 00:00:00 2001 From: Sourabh Bajaj Date: Fri, 21 Dec 2018 11:04:33 -0800 Subject: [PATCH 0260/1765] Random style changes to the correctness test file PiperOrigin-RevId: 226514038 --- .../python/keras_correctness_test.py | 82 +++++++++---------- 1 file changed, 38 insertions(+), 44 deletions(-) diff --git a/tensorflow/contrib/distribute/python/keras_correctness_test.py b/tensorflow/contrib/distribute/python/keras_correctness_test.py index 558759b6b5..3abcdde65b 100644 --- a/tensorflow/contrib/distribute/python/keras_correctness_test.py +++ b/tensorflow/contrib/distribute/python/keras_correctness_test.py @@ -39,6 +39,36 @@ _RANDOM_SEED = 1337 # keras_backward_compat_test for features that are supported with both APIs. +all_strategies = [ + combinations.default_strategy, + combinations.one_device_strategy, + combinations.mirrored_strategy_with_gpu_and_cpu, + combinations.mirrored_strategy_with_two_gpus, + combinations.core_mirrored_strategy_with_gpu_and_cpu, + combinations.core_mirrored_strategy_with_two_gpus, + combinations.tpu_strategy, # steps_per_run=2 + combinations.tpu_strategy_one_step, +] + + +def all_strategy_combinations_with_eager_and_graph_modes(): + return combinations.combine(distribution=all_strategies, + mode=['graph', 'eager']) + + +def all_strategy_combinations_with_graph_mode(): + return combinations.combine(distribution=all_strategies, mode=['graph']) + + +def strategy_and_input_combinations(): + return ( + combinations.times( + combinations.combine(distribution=all_strategies), + combinations.combine(mode=['graph', 'eager'], + use_numpy=[True, False], + use_validation_data=[True, False]))) + + class MaybeDistributionScope(object): """Provides a context allowing no distribution strategy.""" @@ -100,8 +130,7 @@ def get_batch_size(global_batch_size, distribution): def get_correctness_test_inputs(use_numpy, use_validation_data, - with_distribution, - x_train, y_train, x_predict): + with_distribution, x_train, y_train, x_predict): """Generates the inputs for correctness check when enable Keras with DS.""" training_epochs = 2 global_batch_size = 64 @@ -131,10 +160,9 @@ def get_correctness_test_inputs(use_numpy, use_validation_data, else: # For dataset inputs, we do not pass batch_size to # keras.fit/evaluate/predict. The batch size is part of the dataset. - train_dataset = dataset_ops.Dataset.from_tensor_slices( - (x_train, y_train)) - x = batch_wrapper( - train_dataset, batch_size, with_distribution, repeat=training_epochs) + train_dataset = dataset_ops.Dataset.from_tensor_slices((x_train, y_train)) + x = batch_wrapper(train_dataset, batch_size, with_distribution, + repeat=training_epochs) training_inputs = { 'batch_size': None, @@ -146,8 +174,7 @@ def get_correctness_test_inputs(use_numpy, use_validation_data, } if use_validation_data: eval_inputs = None # Remove the eval_inputs - eval_dataset = dataset_ops.Dataset.from_tensor_slices( - (x_train, y_train)) + eval_dataset = dataset_ops.Dataset.from_tensor_slices((x_train, y_train)) x = batch_wrapper(eval_dataset, batch_size, with_distribution) training_inputs['validation_data'] = x training_inputs['validation_steps'] = 5 @@ -161,8 +188,8 @@ def get_correctness_test_inputs(use_numpy, use_validation_data, predict_batch_size = get_batch_size(len(x_predict), with_distribution) predict_dataset = dataset_ops.Dataset.from_tensor_slices(x_predict) - predict_dataset = batch_wrapper(predict_dataset, - predict_batch_size, with_distribution) + predict_dataset = batch_wrapper(predict_dataset, predict_batch_size, + with_distribution) predict_inputs = { 'steps': 1, 'x': predict_dataset, @@ -171,36 +198,6 @@ def get_correctness_test_inputs(use_numpy, use_validation_data, return training_inputs, eval_inputs, predict_inputs -all_strategies = [ - combinations.default_strategy, - combinations.one_device_strategy, - combinations.mirrored_strategy_with_gpu_and_cpu, - combinations.mirrored_strategy_with_two_gpus, - combinations.core_mirrored_strategy_with_gpu_and_cpu, - combinations.core_mirrored_strategy_with_two_gpus, - combinations.tpu_strategy, # steps_per_run=2 - combinations.tpu_strategy_one_step, -] - - -def all_strategy_combinations_with_eager_and_graph_modes(): - return combinations.combine(distribution=all_strategies, - mode=['graph', 'eager']) - - -def all_strategy_combinations_with_graph_mode(): - return combinations.combine(distribution=all_strategies, mode=['graph']) - - -def strategy_and_input_combinations(): - return ( - combinations.times( - combinations.combine(distribution=all_strategies), - combinations.combine(mode=['graph', 'eager'], - use_numpy=[True, False], - use_validation_data=[True, False]))) - - def fit_eval_and_predict( initial_weights, input_fn, distribution=None): model = _create_dnn_model(initial_weights, distribution) @@ -311,9 +308,7 @@ class TestDistributionStrategyCorrectness(test.TestCase, metrics=[keras.metrics.BinaryAccuracy()]) batch_size = 64 - if not distributed_training_utils.global_batch_size_supported( - distribution): - batch_size //= distribution.num_replicas_in_sync + batch_size = get_batch_size(batch_size, distribution) train_dataset = dataset_ops.Dataset.from_tensor_slices((x_train, y_train)) train_dataset = batch_wrapper(train_dataset, batch_size, distribution) @@ -367,7 +362,6 @@ class TestDistributionStrategyCorrectness(test.TestCase, self.skipTest('TODO') with self.cached_session(): - keras.backend.set_image_data_format('channels_last') np.random.seed(_RANDOM_SEED) random_seed.set_random_seed(_RANDOM_SEED) -- GitLab From d8df435bb1fe4dedb403f916820df01c43b235d0 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 11:09:16 -0800 Subject: [PATCH 0261/1765] [tfgan] Replace deprecated ops. PiperOrigin-RevId: 226514712 --- .../eval/python/classifier_metrics_impl.py | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tensorflow/contrib/gan/python/eval/python/classifier_metrics_impl.py b/tensorflow/contrib/gan/python/eval/python/classifier_metrics_impl.py index a71ee53311..ea55241b34 100644 --- a/tensorflow/contrib/gan/python/eval/python/classifier_metrics_impl.py +++ b/tensorflow/contrib/gan/python/eval/python/classifier_metrics_impl.py @@ -387,7 +387,7 @@ def classifier_score_from_logits(logits): # Use maximum precision for best results. logits_dtype = logits.dtype if logits_dtype != dtypes.float64: - logits = math_ops.to_double(logits) + logits = math_ops.cast(logits, dtypes.float64) p = nn_ops.softmax(logits) q = math_ops.reduce_mean(p, axis=0) @@ -562,8 +562,8 @@ def mean_only_frechet_classifier_distance_from_activations( activations_dtype = real_activations.dtype if activations_dtype != dtypes.float64: - real_activations = math_ops.to_double(real_activations) - generated_activations = math_ops.to_double(generated_activations) + real_activations = math_ops.cast(real_activations, dtypes.float64) + generated_activations = math_ops.cast(generated_activations, dtypes.float64) # Compute means of activations. m = math_ops.reduce_mean(real_activations, 0) @@ -623,8 +623,8 @@ def diagonal_only_frechet_classifier_distance_from_activations( activations_dtype = real_activations.dtype if activations_dtype != dtypes.float64: - real_activations = math_ops.to_double(real_activations) - generated_activations = math_ops.to_double(generated_activations) + real_activations = math_ops.cast(real_activations, dtypes.float64) + generated_activations = math_ops.cast(generated_activations, dtypes.float64) # Compute mean and covariance matrices of activations. m, var = nn_impl.moments(real_activations, axes=[0]) @@ -698,15 +698,16 @@ def frechet_classifier_distance_from_activations(real_activations, activations_dtype = real_activations.dtype if activations_dtype != dtypes.float64: - real_activations = math_ops.to_double(real_activations) - generated_activations = math_ops.to_double(generated_activations) + real_activations = math_ops.cast(real_activations, dtypes.float64) + generated_activations = math_ops.cast(generated_activations, dtypes.float64) # Compute mean and covariance matrices of activations. m = math_ops.reduce_mean(real_activations, 0) m_w = math_ops.reduce_mean(generated_activations, 0) - num_examples_real = math_ops.to_double(array_ops.shape(real_activations)[0]) - num_examples_generated = math_ops.to_double( - array_ops.shape(generated_activations)[0]) + num_examples_real = math_ops.cast( + array_ops.shape(real_activations)[0], dtypes.float64) + num_examples_generated = math_ops.cast( + array_ops.shape(generated_activations)[0], dtypes.float64) # sigma = (1 / (n - 1)) * (X - mu) (X - mu)^T real_centered = real_activations - m -- GitLab From d70e8ee2d8c75d5af830f6f6ebc233fc93a89081 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 11:20:32 -0800 Subject: [PATCH 0262/1765] Remove unnecessarily strict test about attributes in RNN cells. PiperOrigin-RevId: 226516444 --- tensorflow/python/ops/rnn_cell_impl.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tensorflow/python/ops/rnn_cell_impl.py b/tensorflow/python/ops/rnn_cell_impl.py index a4ec90d36c..2da66cfcd5 100644 --- a/tensorflow/python/ops/rnn_cell_impl.py +++ b/tensorflow/python/ops/rnn_cell_impl.py @@ -63,6 +63,15 @@ _WEIGHTS_VARIABLE_NAME = "kernel" ASSERT_LIKE_RNNCELL_ERROR_REGEXP = "is not an RNNCell" +def _hasattr(obj, attr_name): + try: + getattr(obj, attr_name) + except AttributeError: + return False + else: + return True + + def assert_like_rnncell(cell_name, cell): """Raises a TypeError if cell is not like an RNNCell. @@ -79,9 +88,9 @@ def assert_like_rnncell(cell_name, cell): TypeError: A human-friendly exception. """ conditions = [ - hasattr(cell, "output_size"), - hasattr(cell, "state_size"), - hasattr(cell, "get_initial_state") or hasattr(cell, "zero_state"), + _hasattr(cell, "output_size"), + _hasattr(cell, "state_size"), + _hasattr(cell, "get_initial_state") or _hasattr(cell, "zero_state"), callable(cell), ] errors = [ @@ -316,7 +325,7 @@ class RNNCell(base_layer.Layer): # zeros, especially when eager execution is enabled. state_size = self.state_size is_eager = context.executing_eagerly() - if is_eager and hasattr(self, "_last_zero_state"): + if is_eager and _hasattr(self, "_last_zero_state"): (last_state_size, last_batch_size, last_dtype, last_output) = getattr(self, "_last_zero_state") if (last_batch_size == batch_size and -- GitLab From a63ea84bd5c659d5354ef183778d40adb9b3cc41 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 11:51:32 -0800 Subject: [PATCH 0263/1765] Add a `distribute_strategy` property to variables so Keras can determine that all the variables used in a model were created with the same `tf.distribute.Strategy`. PiperOrigin-RevId: 226521101 --- .../python/mirrored_strategy_multigpu_test.py | 14 +++++++------ .../python/parameter_server_strategy_test.py | 17 ++++++++++++++- .../python/distribute/distribute_lib.py | 1 + .../resource_variable_ops_test.py | 5 +++++ .../python/kernel_tests/variables_test.py | 5 +++++ .../python/ops/resource_variable_ops.py | 11 +++++++++- tensorflow/python/ops/variable_scope.py | 6 ++++-- tensorflow/python/ops/variables.py | 21 +++++++++++++++++++ .../api/golden/v1/tensorflow.-variable.pbtxt | 4 ++++ .../api/golden/v2/tensorflow.-variable.pbtxt | 4 ++++ 10 files changed, 78 insertions(+), 10 deletions(-) diff --git a/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py b/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py index a6348d2457..9cbc34412d 100644 --- a/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py +++ b/tensorflow/contrib/distribute/python/mirrored_strategy_multigpu_test.py @@ -221,11 +221,13 @@ class MirroredStrategyVariableCreationTest(test.TestCase): # TODO(priyag): Modify more tests to use this helper and check more # properties. - def _test_mv_properties(self, var, name): + def _test_mv_properties(self, var, name, strategy): self.assertIsInstance(var, values.MirroredVariable) self.assertEqual(name, var.name) + self.assertIs(strategy, var.distribute_strategy) for d in var.devices: self.assertEqual(d, var.get(d).device) + self.assertIs(strategy, var.get(d).distribute_strategy) def testVariableInFuncGraph(self, distribution): def model_fn(): @@ -237,8 +239,8 @@ class MirroredStrategyVariableCreationTest(test.TestCase): v1 = variable_scope.variable(1.0, name="foo") v2 = distribution.extended.call_for_each_replica(model_fn) - self._test_mv_properties(v1, "foo:0") - self._test_mv_properties(v2, "bar:0") + self._test_mv_properties(v1, "foo:0", distribution) + self._test_mv_properties(v2, "bar:0", distribution) def testSingleVariable(self, distribution): def model_fn(): @@ -251,7 +253,7 @@ class MirroredStrategyVariableCreationTest(test.TestCase): with distribution.scope(): result = distribution.extended.call_for_each_replica(model_fn) - self._test_mv_properties(result, "foo:0") + self._test_mv_properties(result, "foo:0", distribution) def testUnnamedVariable(self, distribution): def model_fn(): @@ -261,7 +263,7 @@ class MirroredStrategyVariableCreationTest(test.TestCase): with distribution.scope(): result = distribution.extended.call_for_each_replica(model_fn) - self._test_mv_properties(result, "Variable:0") + self._test_mv_properties(result, "Variable:0", distribution) def testMultipleVariables(self, distribution): def model_fn(): @@ -274,7 +276,7 @@ class MirroredStrategyVariableCreationTest(test.TestCase): with distribution.scope(): result = distribution.extended.call_for_each_replica(model_fn) for i, v in enumerate(result): - self._test_mv_properties(v, "foo" + str(i) + ":0") + self._test_mv_properties(v, "foo" + str(i) + ":0", distribution) def testMultipleVariablesWithSameCanonicalName(self, distribution): def model_fn(): diff --git a/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py b/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py index e6ae16d856..44214f8226 100644 --- a/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py +++ b/tensorflow/contrib/distribute/python/parameter_server_strategy_test.py @@ -45,6 +45,7 @@ from tensorflow.python.ops import array_ops from tensorflow.python.ops import control_flow_ops from tensorflow.python.ops import gradients from tensorflow.python.ops import partitioned_variables +from tensorflow.python.ops import resource_variable_ops from tensorflow.python.ops import variable_scope from tensorflow.python.ops import variables from tensorflow.python.platform import test @@ -704,7 +705,7 @@ class ParameterServerStrategyWithChiefTest(ParameterServerStrategyTestBase, self._run_between_graph_clients(self._test_minimize_loss_graph, self._cluster_spec, num_gpus) - def testGlobalStepIsWrapped(self): + def testGlobalStepIsWrappedOnTwoGPUs(self): distribution = parameter_server_strategy.ParameterServerStrategy( num_gpus_per_worker=2) with ops.Graph().as_default(), distribution.scope(): @@ -718,6 +719,20 @@ class ParameterServerStrategyWithChiefTest(ParameterServerStrategyTestBase, self.assertIs(values.AggregatingVariable, type(get_step)) self.assertIs(distribution, created_step.distribute_strategy) + def testGlobalStepIsNotWrappedOnOneGPU(self): + distribution = parameter_server_strategy.ParameterServerStrategy( + num_gpus_per_worker=1) + with ops.Graph().as_default(), distribution.scope(): + created_step = training_util.create_global_step() + get_step = training_util.get_global_step() + self.assertEqual(created_step, get_step, + msg=('created_step %s type %s vs. get_step %s type %s' % + (id(created_step), created_step.__class__.__name__, + id(get_step), get_step.__class__.__name__))) + self.assertIs(resource_variable_ops.ResourceVariable, type(created_step)) + self.assertIs(resource_variable_ops.ResourceVariable, type(get_step)) + self.assertIs(distribution, created_step.distribute_strategy) + def testValueContainer(self): distribution = parameter_server_strategy.ParameterServerStrategy( num_gpus_per_worker=2) diff --git a/tensorflow/python/distribute/distribute_lib.py b/tensorflow/python/distribute/distribute_lib.py index 9c6bcea4cd..7d4fd57843 100644 --- a/tensorflow/python/distribute/distribute_lib.py +++ b/tensorflow/python/distribute/distribute_lib.py @@ -971,6 +971,7 @@ class DistributionStrategyExtended(object): def creator_with_resource_vars(*args, **kwargs): _require_strategy_scope_extended(self) kwargs["use_resource"] = True + kwargs["distribute_strategy"] = strategy return self._create_variable(*args, **kwargs) def distributed_getter(getter, *args, **kwargs): diff --git a/tensorflow/python/kernel_tests/resource_variable_ops_test.py b/tensorflow/python/kernel_tests/resource_variable_ops_test.py index df7b686165..596531b6b9 100644 --- a/tensorflow/python/kernel_tests/resource_variable_ops_test.py +++ b/tensorflow/python/kernel_tests/resource_variable_ops_test.py @@ -1068,6 +1068,11 @@ class _MixedPrecisionVariableTest(test_util.TensorFlowTestCase): self.assertEqual(NotImplemented, v._dense_var_to_tensor(dtype=dtypes.float16, as_ref=True)) + @test_util.run_in_graph_and_eager_modes() + def testDistributeStrategy(self): + v = resource_variable_ops.ResourceVariable(1, dtype=dtypes.int32) + self.assertIsNone(v.distribute_strategy) + if __name__ == "__main__": test.main() diff --git a/tensorflow/python/kernel_tests/variables_test.py b/tensorflow/python/kernel_tests/variables_test.py index 07807e89d0..4dc6d0a828 100644 --- a/tensorflow/python/kernel_tests/variables_test.py +++ b/tensorflow/python/kernel_tests/variables_test.py @@ -43,6 +43,11 @@ from tensorflow.python.util import compat class VariablesTestCase(test.TestCase): + @test_util.run_deprecated_v1 + def testDistributeStrategy(self): + v = variables.VariableV1(0.0) + self.assertIsNone(v.distribute_strategy) + @test_util.run_v1_only("b/120545219") def testInitialization(self): with self.cached_session(): diff --git a/tensorflow/python/ops/resource_variable_ops.py b/tensorflow/python/ops/resource_variable_ops.py index 6104cfa7ff..3e26463ddd 100644 --- a/tensorflow/python/ops/resource_variable_ops.py +++ b/tensorflow/python/ops/resource_variable_ops.py @@ -224,7 +224,8 @@ class ResourceVariable(variables.RefVariable): dtype=None, variable_def=None, import_scope=None, - constraint=None): + constraint=None, + distribute_strategy=None): """Creates a variable. Args: @@ -263,6 +264,8 @@ class ResourceVariable(variables.RefVariable): variable and return the Tensor for the projected value (which must have the same shape). Constraints are not safe to use when doing asynchronous distributed training. + distribute_strategy: The tf.distribute.Strategy this variable is being + created inside of. Raises: ValueError: If the initial value is not specified, or does not have a @@ -274,6 +277,7 @@ class ResourceVariable(variables.RefVariable): collections. @end_compatibility """ + self._distribute_strategy = distribute_strategy if variable_def: if initial_value is not None: raise ValueError("variable_def and initial_value are mutually " @@ -608,6 +612,11 @@ class ResourceVariable(variables.RefVariable): """The shape of this variable.""" return self._shape + @property + def distribute_strategy(self): + """The `tf.distribute.Strategy` that this variable was created under.""" + return self._distribute_strategy + def _shape_as_list(self): if self._cached_shape_as_list: return self._cached_shape_as_list diff --git a/tensorflow/python/ops/variable_scope.py b/tensorflow/python/ops/variable_scope.py index ccce9e2f93..64cdde3d85 100644 --- a/tensorflow/python/ops/variable_scope.py +++ b/tensorflow/python/ops/variable_scope.py @@ -2480,12 +2480,13 @@ def default_variable_creator(next_creator=None, **kwargs): use_resource = _DEFAULT_USE_RESOURCE use_resource = use_resource or context.executing_eagerly() if use_resource: + distribute_strategy = kwargs.get("distribute_strategy", None) return resource_variable_ops.ResourceVariable( initial_value=initial_value, trainable=trainable, collections=collections, validate_shape=validate_shape, caching_device=caching_device, name=name, dtype=dtype, constraint=constraint, variable_def=variable_def, - import_scope=import_scope) + import_scope=import_scope, distribute_strategy=distribute_strategy) else: return variables.RefVariable( initial_value=initial_value, trainable=trainable, @@ -2507,6 +2508,7 @@ def default_variable_creator_v2(next_creator=None, **kwargs): dtype = kwargs.get("dtype", None) import_scope = kwargs.get("import_scope", None) constraint = kwargs.get("constraint", None) + distribute_strategy = kwargs.get("distribute_strategy", None) # Set trainable value based on synchronization value. synchronization = kwargs.get("synchronization", VariableSynchronization.AUTO) @@ -2517,7 +2519,7 @@ def default_variable_creator_v2(next_creator=None, **kwargs): initial_value=initial_value, trainable=trainable, validate_shape=validate_shape, caching_device=caching_device, name=name, dtype=dtype, constraint=constraint, variable_def=variable_def, - import_scope=import_scope) + import_scope=import_scope, distribute_strategy=distribute_strategy) variables.default_variable_creator = default_variable_creator diff --git a/tensorflow/python/ops/variables.py b/tensorflow/python/ops/variables.py index d01b95666b..657f64deaa 100644 --- a/tensorflow/python/ops/variables.py +++ b/tensorflow/python/ops/variables.py @@ -1018,6 +1018,16 @@ class Variable(six.with_metaclass(VariableMetaclass, """The `Graph` of this variable.""" raise NotImplementedError + @property + def distribute_strategy(self): + """The `tf.distribute.Strategy` that this variable was created under. + + Returns: + A `tf.distribute.Strategy` or `None` if this variable was not created + inside the `scope()` of any strategy. + """ + raise NotImplementedError + @property def shape(self): """The `TensorShape` of this variable. @@ -2318,6 +2328,11 @@ class RefVariable(VariableV1): """The `Graph` of this variable.""" return self._variable.graph + @property + def distribute_strategy(self): + """The `tf.distribute.Strategy` that this variable was created under.""" + return None # Ref variables are never created inside a strategy. + @property def shape(self): """The `TensorShape` of this variable. @@ -2576,6 +2591,12 @@ class PartitionedVariable(object): def shape(self): return self.get_shape() + @property + def distribute_strategy(self): + """The `tf.distribute.Strategy` that this variable was created under.""" + # NOTE(yuefengz): Today, no partitioned variables in a distribute strategy. + return None + def get_shape(self): return self._shape diff --git a/tensorflow/tools/api/golden/v1/tensorflow.-variable.pbtxt b/tensorflow/tools/api/golden/v1/tensorflow.-variable.pbtxt index 62d8ea9208..048f666305 100644 --- a/tensorflow/tools/api/golden/v1/tensorflow.-variable.pbtxt +++ b/tensorflow/tools/api/golden/v1/tensorflow.-variable.pbtxt @@ -16,6 +16,10 @@ tf_class { name: "device" mtype: "" } + member { + name: "distribute_strategy" + mtype: "" + } member { name: "dtype" mtype: "" diff --git a/tensorflow/tools/api/golden/v2/tensorflow.-variable.pbtxt b/tensorflow/tools/api/golden/v2/tensorflow.-variable.pbtxt index 6136c8fbe7..ee16ffa505 100644 --- a/tensorflow/tools/api/golden/v2/tensorflow.-variable.pbtxt +++ b/tensorflow/tools/api/golden/v2/tensorflow.-variable.pbtxt @@ -15,6 +15,10 @@ tf_class { name: "device" mtype: "" } + member { + name: "distribute_strategy" + mtype: "" + } member { name: "dtype" mtype: "" -- GitLab From aaa5123eeb9324c898b8e013a41a4f07a5d88106 Mon Sep 17 00:00:00 2001 From: Anna R Date: Fri, 21 Dec 2018 11:53:58 -0800 Subject: [PATCH 0264/1765] Internal change. PiperOrigin-RevId: 226521394 --- tensorflow/python/training/checkpointable/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow/python/training/checkpointable/BUILD b/tensorflow/python/training/checkpointable/BUILD index 15280198d4..13a030caa3 100644 --- a/tensorflow/python/training/checkpointable/BUILD +++ b/tensorflow/python/training/checkpointable/BUILD @@ -170,6 +170,7 @@ tf_xla_py_test( srcs = ["util_xla_test.py"], tags = [ "no_pip", + "nomac", "notsan", # b/74395663 ], deps = [ -- GitLab From fdc87d3d413292a90af1c9893564519a96be855e Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Fri, 21 Dec 2018 11:54:11 -0800 Subject: [PATCH 0265/1765] Internal changes. PiperOrigin-RevId: 226521409 --- tensorflow/python/eager/memory_test.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tensorflow/python/eager/memory_test.py b/tensorflow/python/eager/memory_test.py index a1a59d511f..5e4516239c 100644 --- a/tensorflow/python/eager/memory_test.py +++ b/tensorflow/python/eager/memory_test.py @@ -24,6 +24,7 @@ from __future__ import absolute_import from __future__ import division from __future__ import print_function +import time import six from tensorflow.python import keras @@ -63,6 +64,11 @@ class MemoryTest(test.TestCase): # Warm up. f() + # Wait for background threads to start up and take over memory. + # FIXME: The nature of this test leaves few other options. Maybe there + # is a better way to do this. + time.sleep(4) + initial = memory_profiler.memory_usage(-1)[0] for _ in six.moves.range(num_iters): -- GitLab From 6a194ad3a1c2f4b3f471833edb4d3dd7a1996f8d Mon Sep 17 00:00:00 2001 From: Sourabh Bajaj Date: Fri, 21 Dec 2018 12:01:50 -0800 Subject: [PATCH 0266/1765] Normalization layer to work in the cross-replica context with fused batch norm. PiperOrigin-RevId: 226522448 --- .../contrib/distribute/python/keras_test.py | 9 ++++++--- tensorflow/python/keras/layers/normalization.py | 17 +++++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/tensorflow/contrib/distribute/python/keras_test.py b/tensorflow/contrib/distribute/python/keras_test.py index 6339aa0e0d..b99d11b923 100644 --- a/tensorflow/contrib/distribute/python/keras_test.py +++ b/tensorflow/contrib/distribute/python/keras_test.py @@ -1117,12 +1117,15 @@ class TestDistributionStrategyWithLossMasking(test.TestCase, class TestDistributionStrategyWithNormalizationLayer( test.TestCase, parameterized.TestCase): - @combinations.generate(all_strategy_combinations()) - def test_batchnorm_correctness(self, distribution): + @combinations.generate(combinations.times( + all_strategy_combinations(), + combinations.combine(fused=[True, False]))) + def test_batchnorm_correctness(self, distribution, fused): with self.cached_session(): with distribution.scope(): model = keras.models.Sequential() - norm = keras.layers.BatchNormalization(input_shape=(10,), momentum=0.8) + norm = keras.layers.BatchNormalization( + input_shape=(10,), momentum=0.8, fused=fused) model.add(norm) model.compile(loss='mse', optimizer=gradient_descent.GradientDescentOptimizer(0.01)) diff --git a/tensorflow/python/keras/layers/normalization.py b/tensorflow/python/keras/layers/normalization.py index cee0da1b32..2e68aedbed 100644 --- a/tensorflow/python/keras/layers/normalization.py +++ b/tensorflow/python/keras/layers/normalization.py @@ -483,10 +483,19 @@ class BatchNormalizationV2(Layer): else: momentum = ops.convert_to_tensor(self.momentum) if training_value or training_value is None: - mean_update = self._assign_moving_average(self.moving_mean, mean, - momentum) - variance_update = self._assign_moving_average(self.moving_variance, - variance, momentum) + if distribution_strategy_context.in_cross_replica_context(): + strategy = distribution_strategy_context.get_distribution_strategy() + mean_update = strategy.extended.update( + self.moving_mean, self._assign_moving_average, + (mean, self.momentum)) + variance_update = strategy.extended.update( + self.moving_variance, self._assign_moving_average, + (variance, self.momentum)) + else: + mean_update = self._assign_moving_average(self.moving_mean, mean, + momentum) + variance_update = self._assign_moving_average(self.moving_variance, + variance, momentum) self.add_update(mean_update, inputs=True) self.add_update(variance_update, inputs=True) -- GitLab From 2ec7666f428cb588d783b8b6da2862a16b4aa713 Mon Sep 17 00:00:00 2001 From: Rick Chao Date: Fri, 21 Dec 2018 12:14:27 -0800 Subject: [PATCH 0267/1765] Set Model.run_eagerly to True if input or validate date is dict structure before _standardize_user_data() is called. Fix the AttributeError where total_loss is unavailable during _make_eval_function() call. PiperOrigin-RevId: 226524474 --- tensorflow/python/keras/engine/training.py | 9 ++- .../python/keras/engine/training_test.py | 75 +++++++++++++++++++ .../python/keras/engine/training_utils.py | 22 ++++++ 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/tensorflow/python/keras/engine/training.py b/tensorflow/python/keras/engine/training.py index 40622641bb..be3afafd3e 100644 --- a/tensorflow/python/keras/engine/training.py +++ b/tensorflow/python/keras/engine/training.py @@ -765,6 +765,11 @@ class Model(Network): if kwargs: raise TypeError('Unrecognized keyword arguments: ' + str(kwargs)) + # When the model expects dictionary inputs (i.e. FeatureColumn-based + # models), set run_eagerly to True as there's no support for graph + # functions. + training_utils.set_run_eagerly_for_dict_structure(self, x) + # Case 1: distribution strategy. if self._distribution_strategy: return training_distributed.fit_distributed( @@ -2363,10 +2368,6 @@ class Model(Network): self._set_inputs(cast_inputs) else: dict_inputs = isinstance(self.inputs, dict) - if dict_inputs and context.executing_eagerly(): - # No support for graph functions when the model expects dictionary inputs - # (i.e. FeatureColumn-based models). - self.run_eagerly = True if y is not None: if not self.optimizer: diff --git a/tensorflow/python/keras/engine/training_test.py b/tensorflow/python/keras/engine/training_test.py index 168082d987..b8d4752db4 100644 --- a/tensorflow/python/keras/engine/training_test.py +++ b/tensorflow/python/keras/engine/training_test.py @@ -36,6 +36,7 @@ from tensorflow.python.keras import keras_parameterized from tensorflow.python.keras import metrics as metrics_module from tensorflow.python.keras import testing_utils from tensorflow.python.keras.callbacks import Callback +from tensorflow.python.keras.engine.training_utils import set_run_eagerly_for_dict_structure from tensorflow.python.keras.engine.training_utils import weighted_masked_objective from tensorflow.python.ops import array_ops from tensorflow.python.ops import math_ops @@ -43,6 +44,7 @@ from tensorflow.python.ops import sparse_ops from tensorflow.python.ops import variables as variables_lib from tensorflow.python.platform import test from tensorflow.python.platform import tf_logging as logging +from tensorflow.python.training.adam import AdamOptimizer from tensorflow.python.training.rmsprop import RMSPropOptimizer try: @@ -2475,6 +2477,79 @@ class TestTrainingWithMetrics(keras_parameterized.TestCase): model.fit(x, y, epochs=2, batch_size=5, validation_data=(x, y)) self.assertEqual([m.name for m in model.metrics], ['mean', 'mean_1']) + @keras_parameterized.run_all_keras_modes(always_skip_v1=True) + def test_a1_total_loss_available_with_dict_dataset(self): + + class TestModel(keras.models.Model): + + def call(self, inputs, training=None, mask=None): + return math_ops.to_float(inputs['id']) + + model = TestModel() + model.compile( + optimizer=AdamOptimizer(), loss='mean_squared_error', metrics=['mse'], + run_eagerly=testing_utils.should_run_eagerly()) + dataset = dataset_ops.Dataset.from_tensor_slices(({ + 'id': [[6], [3], [1]] + }, [[0.7], [0.4], [0.2]])) + val_dataset = dataset_ops.Dataset.from_tensor_slices(({ + 'id': [[8], [5]] + }, [[0.9], [0.6]])) + history = model.fit( + dataset, + steps_per_epoch=2, + validation_data=val_dataset, + validation_steps=2) + self.assertAlmostEqual(history.history['val_loss'][0], 34.885, 2) + model.evaluate(dataset, steps=30) + model.predict([7]) + + @keras_parameterized.run_all_keras_modes(always_skip_v1=True) + def test_total_loss_available_with_dict_array(self): + + class TestModel(keras.models.Model): + + def call(self, inputs, training=None, mask=None): + return math_ops.to_float(inputs['id']) + + model = TestModel() + model.compile( + optimizer=AdamOptimizer(), loss='mean_squared_error', metrics=['mse'], + run_eagerly=testing_utils.should_run_eagerly()) + x = {'id': np.array([[3], [1]])} + y = np.array([[4], [2]]) + val_dataset = (x, y) + history = model.fit( + x, + y, + batch_size=32, + steps_per_epoch=2, + validation_data=val_dataset, + validation_steps=2) + self.assertAlmostEqual(history.history['val_loss'][0], 1.0, 2) + model.evaluate(x, y) + model.predict([7]) + + @keras_parameterized.run_all_keras_modes(always_skip_v1=True) + def test_set_run_eagerly_for_dict_structure(self): + test_model = keras.models.Model() + self.assertFalse(test_model.run_eagerly) + set_run_eagerly_for_dict_structure( + test_model, + {'a': 2}) + self.assertTrue(test_model.run_eagerly) + + @keras_parameterized.run_all_keras_modes(always_skip_v1=True) + def test_set_run_eagerly_for_dict_dataset(self): + test_model = keras.models.Model() + self.assertFalse(test_model.run_eagerly) + set_run_eagerly_for_dict_structure( + test_model, + dataset_ops.Dataset.from_tensor_slices(({ + 'id': [[3], [1]] + }, [[0.5], [0.2]]))) + self.assertTrue(test_model.run_eagerly) + if __name__ == '__main__': test.main() diff --git a/tensorflow/python/keras/engine/training_utils.py b/tensorflow/python/keras/engine/training_utils.py index 6d0037ed5e..d07e3cc4f7 100644 --- a/tensorflow/python/keras/engine/training_utils.py +++ b/tensorflow/python/keras/engine/training_utils.py @@ -1380,3 +1380,25 @@ def trace_model_call(model, input_signature=None): return {name: output for name, output in zip(output_names, outputs_list)} return _wrapped_model + + +def set_run_eagerly_for_dict_structure(model, x): + """Set model.run_eagerly to true if x is dict structure. + + Set model.run_eagerly to true if x is dict or + Iterator/EagerIterator/Dataset of dict. + + Args: + model: A Keras model. + x: Input data. + """ + if not context.executing_eagerly(): + return + if isinstance(x, dict): + model.run_eagerly = True + if (isinstance(x, (iterator_ops.Iterator, iterator_ops.EagerIterator, + dataset_ops.DatasetV2))): + for item in x.output_shapes: + if isinstance(item, dict): + model.run_eagerly = True + return -- GitLab From d9bee08f15ecaf0775e654bb59ccd43c338fbf3b Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 12:22:16 -0800 Subject: [PATCH 0268/1765] Adds bfloat16 support for neg and tile ops on CPU. PiperOrigin-RevId: 226525480 --- tensorflow/core/kernels/cwise_op_neg.cc | 4 ++-- tensorflow/core/kernels/tile_functor_cpu.cc | 2 ++ tensorflow/core/kernels/tile_ops.cc | 2 ++ tensorflow/core/kernels/tile_ops_cpu_impl.h | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tensorflow/core/kernels/cwise_op_neg.cc b/tensorflow/core/kernels/cwise_op_neg.cc index a136769b91..bb7d22e4dd 100644 --- a/tensorflow/core/kernels/cwise_op_neg.cc +++ b/tensorflow/core/kernels/cwise_op_neg.cc @@ -16,8 +16,8 @@ limitations under the License. #include "tensorflow/core/kernels/cwise_ops_common.h" namespace tensorflow { -REGISTER7(UnaryOp, CPU, "Neg", functor::neg, float, Eigen::half, double, int32, - complex64, int64, complex128); +REGISTER8(UnaryOp, CPU, "Neg", functor::neg, float, Eigen::half, double, int32, + complex64, int64, complex128, bfloat16); #ifdef TENSORFLOW_USE_SYCL REGISTER3(UnaryOp, SYCL, "Neg", functor::neg, float, double, int64); diff --git a/tensorflow/core/kernels/tile_functor_cpu.cc b/tensorflow/core/kernels/tile_functor_cpu.cc index f814486701..43fd0d20ad 100644 --- a/tensorflow/core/kernels/tile_functor_cpu.cc +++ b/tensorflow/core/kernels/tile_functor_cpu.cc @@ -57,6 +57,7 @@ typedef Eigen::ThreadPoolDevice CPUDevice; TF_CALL_bool(DEFINE_TYPE); TF_CALL_float(DEFINE_TYPE); +TF_CALL_bfloat16(DEFINE_TYPE); TF_CALL_double(DEFINE_TYPE); TF_CALL_uint8(DEFINE_TYPE); TF_CALL_int32(DEFINE_TYPE); @@ -78,6 +79,7 @@ typedef Eigen::SyclDevice SYCLDevice; TF_CALL_bool(DEFINE_TYPE); TF_CALL_float(DEFINE_TYPE); +TF_CALL_bfloat16(DEFINE_TYPE); TF_CALL_double(DEFINE_TYPE); TF_CALL_uint8(DEFINE_TYPE); TF_CALL_int32(DEFINE_TYPE); diff --git a/tensorflow/core/kernels/tile_ops.cc b/tensorflow/core/kernels/tile_ops.cc index b9b37612ad..2e01fa1763 100644 --- a/tensorflow/core/kernels/tile_ops.cc +++ b/tensorflow/core/kernels/tile_ops.cc @@ -136,6 +136,7 @@ class TileOp : public OpKernel { // Invoke macro using TF_CALL_* so type-filtering for platform applies. TF_CALL_bool(HANDLE_TYPE_NAME); + TF_CALL_bfloat16(HANDLE_TYPE_NAME); TF_CALL_float(HANDLE_TYPE_NAME); TF_CALL_double(HANDLE_TYPE_NAME); TF_CALL_uint8(HANDLE_TYPE_NAME); @@ -214,6 +215,7 @@ inline void TileOp::HandleCase( TF_CALL_bool(HANDLE_TYPE_NAME_CPU); TF_CALL_float(HANDLE_TYPE_NAME_CPU); +TF_CALL_bfloat16(HANDLE_TYPE_NAME_CPU); TF_CALL_double(HANDLE_TYPE_NAME_CPU); TF_CALL_uint8(HANDLE_TYPE_NAME_CPU); TF_CALL_int32(HANDLE_TYPE_NAME_CPU); diff --git a/tensorflow/core/kernels/tile_ops_cpu_impl.h b/tensorflow/core/kernels/tile_ops_cpu_impl.h index df6a666cd4..8b0c80159a 100644 --- a/tensorflow/core/kernels/tile_ops_cpu_impl.h +++ b/tensorflow/core/kernels/tile_ops_cpu_impl.h @@ -33,6 +33,7 @@ typedef Eigen::ThreadPoolDevice CPUDevice; #define DEFINE_TYPE(T) DEFINE_DIM(T, CPU_PROVIDED_IXDIM) TF_CALL_float(DEFINE_TYPE); +TF_CALL_bfloat16(DEFINE_TYPE); TF_CALL_double(DEFINE_TYPE); TF_CALL_int16(DEFINE_TYPE); TF_CALL_int32(DEFINE_TYPE); @@ -55,6 +56,7 @@ typedef Eigen::SyclDevice SYCLDevice; TF_CALL_bool(DEFINE_TYPE); TF_CALL_float(DEFINE_TYPE); +TF_CALL_bfloat16(DEFINE_TYPE); TF_CALL_double(DEFINE_TYPE); TF_CALL_uint8(DEFINE_TYPE); TF_CALL_int16(DEFINE_TYPE); -- GitLab From 309a383fbfd90452bd5f89d95ccf333c6271e7df Mon Sep 17 00:00:00 2001 From: Jared Duke Date: Fri, 21 Dec 2018 12:26:11 -0800 Subject: [PATCH 0269/1765] Enable some smartreply tests in oss PiperOrigin-RevId: 226525949 --- tensorflow/lite/models/smartreply/BUILD | 39 +++++++++++++++---- .../smartreply/ops/extract_feature_test.cc | 2 +- .../models/smartreply/ops/normalize_test.cc | 2 +- .../models/smartreply/ops/predict_test.cc | 2 +- .../lite/models/smartreply/predictor_test.cc | 18 ++++++--- 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/tensorflow/lite/models/smartreply/BUILD b/tensorflow/lite/models/smartreply/BUILD index 078b8e6bc6..a3f4e61cb5 100644 --- a/tensorflow/lite/models/smartreply/BUILD +++ b/tensorflow/lite/models/smartreply/BUILD @@ -1,9 +1,14 @@ -package(default_visibility = ["//visibility:public"]) +package(default_visibility = [ + "//visibility:public", +]) -load("//tensorflow/lite:build_def.bzl", "tflite_copts", "gen_selected_ops") +load("//tensorflow:tensorflow.bzl", "tf_cc_test") +load("//tensorflow/lite:build_def.bzl", "gen_selected_ops", "tflite_copts") licenses(["notice"]) # Apache 2.0 +exports_files(["LICENSE"]) + gen_selected_ops( name = "smartreply_ops", model = "@tflite_smartreply//:smartreply.tflite", @@ -22,10 +27,12 @@ cc_library( "//tensorflow/lite:framework", "//tensorflow/lite:string_util", "//tensorflow/lite/kernels:builtin_ops", + "//tensorflow/lite/kernels:kernel_util", "@com_google_absl//absl/strings", "@com_googlesource_code_re2//:re2", "@farmhash_archive//:farmhash", ], + alwayslink = 1, ) cc_library( @@ -43,11 +50,29 @@ cc_library( ], ) -cc_test( +# TODO(b/118895218): Make this test compatible with oss. +tf_cc_test( + name = "predictor_test", + srcs = ["predictor_test.cc"], + data = [ + "//tensorflow/lite/models:testdata/smartreply_samples.tsv", + "@tflite_smartreply//:smartreply.tflite", + ], + tags = ["no_oss"], + deps = [ + ":predictor_lib", + "//tensorflow/core:test", + "//tensorflow/lite:string_util", + "//tensorflow/lite/testing:util", + "@com_google_absl//absl/strings", + "@com_google_googletest//:gtest", + ], +) + +tf_cc_test( name = "extract_feature_op_test", size = "small", srcs = ["ops/extract_feature_test.cc"], - tags = ["no_oss"], deps = [ ":custom_ops", "//tensorflow/lite:framework", @@ -58,11 +83,10 @@ cc_test( ], ) -cc_test( +tf_cc_test( name = "normalize_op_test", size = "small", srcs = ["ops/normalize_test.cc"], - tags = ["no_oss"], deps = [ ":custom_ops", "//tensorflow/lite:framework", @@ -73,11 +97,10 @@ cc_test( ], ) -cc_test( +tf_cc_test( name = "predict_op_test", size = "small", srcs = ["ops/predict_test.cc"], - tags = ["no_oss"], deps = [ ":custom_ops", "//tensorflow/lite:framework", diff --git a/tensorflow/lite/models/smartreply/ops/extract_feature_test.cc b/tensorflow/lite/models/smartreply/ops/extract_feature_test.cc index efe59eeb46..914b47c1a9 100644 --- a/tensorflow/lite/models/smartreply/ops/extract_feature_test.cc +++ b/tensorflow/lite/models/smartreply/ops/extract_feature_test.cc @@ -94,7 +94,7 @@ TEST(ExtractFeatureOpTest, AllBlacklistInput) { } // namespace tflite int main(int argc, char** argv) { - // On Linux, add: tflite::LogToStderr(); + ::tflite::LogToStderr(); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/tensorflow/lite/models/smartreply/ops/normalize_test.cc b/tensorflow/lite/models/smartreply/ops/normalize_test.cc index 8c5131565d..46d2aebe75 100644 --- a/tensorflow/lite/models/smartreply/ops/normalize_test.cc +++ b/tensorflow/lite/models/smartreply/ops/normalize_test.cc @@ -84,7 +84,7 @@ TEST(NormalizeOpTest, EmptyInput) { } // namespace tflite int main(int argc, char** argv) { - // On Linux, add: tflite::LogToStderr(); + ::tflite::LogToStderr(); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/tensorflow/lite/models/smartreply/ops/predict_test.cc b/tensorflow/lite/models/smartreply/ops/predict_test.cc index ca64dcaad4..6896a342c7 100644 --- a/tensorflow/lite/models/smartreply/ops/predict_test.cc +++ b/tensorflow/lite/models/smartreply/ops/predict_test.cc @@ -177,7 +177,7 @@ TEST(PredictOpTest, NoLabelGenerated) { } // namespace tflite int main(int argc, char** argv) { - // On Linux, add: tflite::LogToStderr(); + ::tflite::LogToStderr(); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/tensorflow/lite/models/smartreply/predictor_test.cc b/tensorflow/lite/models/smartreply/predictor_test.cc index 7eba26993e..9bdd7b537a 100644 --- a/tensorflow/lite/models/smartreply/predictor_test.cc +++ b/tensorflow/lite/models/smartreply/predictor_test.cc @@ -22,9 +22,9 @@ limitations under the License. #include #include "absl/strings/str_cat.h" #include "absl/strings/str_split.h" -//#include "tensorflow/lite/models/test_utils.h" -#include "tensorflow/lite/string_util.h" #include "tensorflow/core/platform/test.h" +#include "tensorflow/lite/string_util.h" +#include "tensorflow/lite/testing/util.h" namespace tflite { namespace custom { @@ -53,12 +53,14 @@ MATCHER_P(IncludeAnyResponesIn, expected_response, "contains the response") { class PredictorTest : public ::testing::Test { protected: - PredictorTest() { + PredictorTest() {} + ~PredictorTest() override {} + + void SetUp() override { model_ = tflite::FlatBufferModel::BuildFromFile( absl::StrCat(TestDataPath(), "/", kModelName).c_str()); - CHECK(model_); + ASSERT_NE(model_.get(), nullptr); } - ~PredictorTest() override {} std::unique_ptr<::tflite::FlatBufferModel> model_; }; @@ -151,3 +153,9 @@ TEST_F(PredictorTest, BatchTest) { } // namespace smartreply } // namespace custom } // namespace tflite + +int main(int argc, char **argv) { + ::tflite::LogToStderr(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} -- GitLab From dfd69f143cedeaf161181bd775503ef2f570e0cf Mon Sep 17 00:00:00 2001 From: Anna R Date: Fri, 21 Dec 2018 12:43:55 -0800 Subject: [PATCH 0270/1765] Automated rollback of commit 5e537a4d7c100915a33eff43441112bc4f657070 PiperOrigin-RevId: 226528317 --- tensorflow/core/kernels/concat_lib_gpu.cc | 17 +---------------- .../core/kernels/concat_lib_gpu_impl.cu.cc | 2 -- tensorflow/core/kernels/concat_op.cc | 10 ---------- .../python/kernel_tests/concat_op_test.py | 12 ------------ 4 files changed, 1 insertion(+), 40 deletions(-) diff --git a/tensorflow/core/kernels/concat_lib_gpu.cc b/tensorflow/core/kernels/concat_lib_gpu.cc index 56b9e7b674..93e392d303 100644 --- a/tensorflow/core/kernels/concat_lib_gpu.cc +++ b/tensorflow/core/kernels/concat_lib_gpu.cc @@ -87,21 +87,7 @@ void ConcatGPU( const std::vector::ConstMatrix>>& inputs_flat, Tensor* output, typename TTypes::Tensor* output_flat) { - if (std::is_same::value) { - std::vector::ConstMatrix>> - inputs_as_int32(inputs_flat.size()); - for (int i = 0; i < inputs_flat.size(); ++i) { - auto& input = *inputs_flat[i]; - inputs_as_int32[i].reset(new typename TTypes::ConstMatrix( - reinterpret_cast(input.data()), input.dimension(0), - input.dimension(1) >> 2)); - } - typename TTypes::Matrix output_as_int32( - reinterpret_cast(output_flat->data()), - output_flat->dimension(0), output_flat->dimension(1) >> 2); - ConcatGPUSlice(c->eigen_gpu_device(), inputs_as_int32, - &output_as_int32); - } else if (inputs_flat.size() < 16) { + if (inputs_flat.size() < 16) { if (output->NumElements() < std::numeric_limits::max()) { ConcatGPUSlice(c->eigen_gpu_device(), inputs_flat, output_flat); } else { @@ -133,7 +119,6 @@ TF_CALL_int64(REGISTER); TF_CALL_bfloat16(REGISTER); TF_CALL_bool(REGISTER); TF_CALL_uint8(REGISTER); -TF_CALL_qint8(REGISTER); #undef REGISTER diff --git a/tensorflow/core/kernels/concat_lib_gpu_impl.cu.cc b/tensorflow/core/kernels/concat_lib_gpu_impl.cu.cc index 565ab550a4..a561d918bd 100644 --- a/tensorflow/core/kernels/concat_lib_gpu_impl.cu.cc +++ b/tensorflow/core/kernels/concat_lib_gpu_impl.cu.cc @@ -202,7 +202,6 @@ TF_CALL_GPU_NUMBER_TYPES(REGISTER_GPUCONCAT32); TF_CALL_complex64(REGISTER_GPUCONCAT32); TF_CALL_complex128(REGISTER_GPUCONCAT32); TF_CALL_int64(REGISTER_GPUCONCAT32); -TF_CALL_int32(REGISTER_GPUCONCAT32); TF_CALL_uint8(REGISTER_GPUCONCAT32); REGISTER_GPUCONCAT32(bfloat16); REGISTER_GPUCONCAT32(bool); @@ -219,7 +218,6 @@ TF_CALL_GPU_NUMBER_TYPES(REGISTER_GPU32); TF_CALL_complex64(REGISTER_GPU32); TF_CALL_complex128(REGISTER_GPU32); TF_CALL_int64(REGISTER_GPU32); -TF_CALL_int32(REGISTER_GPU32); TF_CALL_uint8(REGISTER_GPU32); REGISTER_GPU32(bfloat16); REGISTER_GPU32(bool); diff --git a/tensorflow/core/kernels/concat_op.cc b/tensorflow/core/kernels/concat_op.cc index 6e9057eea5..ff62983517 100644 --- a/tensorflow/core/kernels/concat_op.cc +++ b/tensorflow/core/kernels/concat_op.cc @@ -135,15 +135,6 @@ class ConcatBaseOp : public OpKernel { } if (in.NumElements() > 0) { int64 inputs_flat_dim1 = in.NumElements() / inputs_flat_dim0; - if (std::is_same::value) { - OP_REQUIRES( - c, 0 == inputs_flat_dim1 % 4, - errors::InvalidArgument( - "For qint8, the product of dimensions after the concat axis " - "must be a multiple of 4. Got ", - input_shape, " -> (", inputs_flat_dim0, ", ", - inputs_flat_dim1, ")")); - } inputs_flat.emplace_back(new typename TTypes::ConstMatrix( in.shaped({inputs_flat_dim0, inputs_flat_dim1}))); } @@ -222,7 +213,6 @@ REGISTER_CONCAT(qint32); TF_CALL_GPU_NUMBER_TYPES(REGISTER_GPU); REGISTER_GPU(bfloat16); -REGISTER_GPU(qint8); TF_CALL_uint8(REGISTER_GPU); TF_CALL_complex64(REGISTER_GPU); TF_CALL_complex128(REGISTER_GPU); diff --git a/tensorflow/python/kernel_tests/concat_op_test.py b/tensorflow/python/kernel_tests/concat_op_test.py index 00d876bff5..474760a93f 100644 --- a/tensorflow/python/kernel_tests/concat_op_test.py +++ b/tensorflow/python/kernel_tests/concat_op_test.py @@ -640,18 +640,6 @@ class ConcatOpTest(test.TestCase): output = self.evaluate(c) self.assertAllEqual([[1, 2, 3, 7, 8, 9], [4, 5, 6, 10, 11, 12]], output) - def testConcatQint8GPU(self): - with self.test_session(use_gpu=True): - p1 = np.random.rand(2, 3, 2, 3, 4).astype("i") - p2 = np.random.rand(2, 3, 2, 3, 4).astype("i") - x1 = constant_op.constant(p1, dtypes.qint8) - x2 = constant_op.constant(p2, dtypes.qint8) - c = gen_array_ops.concat_v2([x1, x2], 1) - result = self.evaluate(c) - self.assertAllEqual(result[:, :3, :], p1) - self.assertAllEqual(result[:, 3:, :], p2) - - class ConcatOffsetTest(test.TestCase): def testBasic(self): -- GitLab From fb8096e4a1ed96339204b8a62875fb05f0bfe38a Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 12:51:35 -0800 Subject: [PATCH 0271/1765] Propagate error status messages inside the op to make sure Invoke fails when TF_LITE_ENSURE fails. PiperOrigin-RevId: 226529335 --- .../lite/kernels/detection_postprocess.cc | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tensorflow/lite/kernels/detection_postprocess.cc b/tensorflow/lite/kernels/detection_postprocess.cc index 84e2a0efb2..a0df4a10fa 100644 --- a/tensorflow/lite/kernels/detection_postprocess.cc +++ b/tensorflow/lite/kernels/detection_postprocess.cc @@ -498,8 +498,9 @@ TfLiteStatus NonMaxSuppressionMultiClassRegularHelper(TfLiteContext* context, } // Perform non-maximal suppression on single class std::vector selected; - NonMaxSuppressionSingleClassHelper(context, node, op_data, class_scores, - &selected, num_detections_per_class); + TF_LITE_ENSURE_STATUS(NonMaxSuppressionSingleClassHelper( + context, node, op_data, class_scores, &selected, + num_detections_per_class)); // Add selected indices from non-max suppression of boxes in this class int output_index = size_of_sorted_indices; for (int selected_index : selected) { @@ -614,8 +615,8 @@ TfLiteStatus NonMaxSuppressionMultiClassFastHelper(TfLiteContext* context, } // Perform non-maximal suppression on max scores std::vector selected; - NonMaxSuppressionSingleClassHelper(context, node, op_data, max_scores, - &selected, op_data->max_detections); + TF_LITE_ENSURE_STATUS(NonMaxSuppressionSingleClassHelper( + context, node, op_data, max_scores, &selected, op_data->max_detections)); // Allocate output tensors int output_box_index = 0; for (const auto& selected_index : selected) { @@ -688,11 +689,11 @@ TfLiteStatus NonMaxSuppressionMultiClass(TfLiteContext* context, return kTfLiteError; } if (op_data->use_regular_non_max_suppression) - NonMaxSuppressionMultiClassRegularHelper(context, node, op_data, - GetTensorData(scores)); + TF_LITE_ENSURE_STATUS(NonMaxSuppressionMultiClassRegularHelper( + context, node, op_data, GetTensorData(scores))); else - NonMaxSuppressionMultiClassFastHelper(context, node, op_data, - GetTensorData(scores)); + TF_LITE_ENSURE_STATUS(NonMaxSuppressionMultiClassFastHelper( + context, node, op_data, GetTensorData(scores))); return kTfLiteOk; } @@ -710,12 +711,12 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) { // This fills in temporary decoded_boxes // by transforming input_box_encodings and input_anchors from // CenterSizeEncodings to BoxCornerEncoding - DecodeCenterSizeBoxes(context, node, op_data); + TF_LITE_ENSURE_STATUS(DecodeCenterSizeBoxes(context, node, op_data)); // This fills in the output tensors // by choosing effective set of decoded boxes // based on Non Maximal Suppression, i.e. selecting // highest scoring non-overlapping boxes. - NonMaxSuppressionMultiClass(context, node, op_data); + TF_LITE_ENSURE_STATUS(NonMaxSuppressionMultiClass(context, node, op_data)); return kTfLiteOk; } -- GitLab From 181da1867510ae8bf95972e8c596a2fcfb75a547 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Fri, 21 Dec 2018 12:53:03 -0800 Subject: [PATCH 0272/1765] Tutorial for Image Classification Android app PiperOrigin-RevId: 226529584 --- .../lite/g3doc/models/image/label/android.md | 208 +++++++++++++++++- .../image/label/images/classifydemo_img1.png | Bin 0 -> 140249 bytes .../image/label/images/classifydemo_img2.png | Bin 0 -> 87882 bytes .../image/label/images/classifydemo_img4.png | Bin 0 -> 93315 bytes .../image/label/images/classifydemo_img5.png | Bin 0 -> 182112 bytes .../image/label/images/classifydemo_img6.png | Bin 0 -> 137949 bytes .../image/label/images/classifydemo_img7.png | Bin 0 -> 25833 bytes .../image/label/images/classifydemo_img8.png | Bin 0 -> 17469 bytes 8 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 tensorflow/lite/g3doc/models/image/label/images/classifydemo_img1.png create mode 100644 tensorflow/lite/g3doc/models/image/label/images/classifydemo_img2.png create mode 100644 tensorflow/lite/g3doc/models/image/label/images/classifydemo_img4.png create mode 100644 tensorflow/lite/g3doc/models/image/label/images/classifydemo_img5.png create mode 100644 tensorflow/lite/g3doc/models/image/label/images/classifydemo_img6.png create mode 100644 tensorflow/lite/g3doc/models/image/label/images/classifydemo_img7.png create mode 100644 tensorflow/lite/g3doc/models/image/label/images/classifydemo_img8.png diff --git a/tensorflow/lite/g3doc/models/image/label/android.md b/tensorflow/lite/g3doc/models/image/label/android.md index 9cd54aad1e..c755328ac0 100644 --- a/tensorflow/lite/g3doc/models/image/label/android.md +++ b/tensorflow/lite/g3doc/models/image/label/android.md @@ -1,3 +1,207 @@ -# Android +# TensorFlow Lite Android Image Classifier App Example -lorem +This tutorial provides a simple Android mobile application to classify images +using the Android device camera. In this tutorial, you will download the demo +application from the Tensorflow repository, build it on your computer, and +install it on your Android Device. You will also learn how to customize the +application to suit your requirements. + +### Prerequisites + +* Android Studio 3.2 (installed on a Linux, Mac or Windows machine) + +* Android Device + +* USB cable (to connect Android device to your computer) + +### Step 1. Clone the TensorFlow source code + +First, we clone the GitHub repository on the computer in a folder to get the +demo application. + +``` + +git clone https://github.com/tensorflow/tensorflow + +``` + +Open the TensorFlow source code in Android Studio. To do this, open Android +Studio and select `Open an existing project` setting the folder to +`tensorflow/lite/examples/android` + +![Step 1](images/classifydemo_img1.png) + +This folder contains the demo application for image classification, object +detection, and speech hotword detection. + +### Step 2. Build the Android Studio project + +In this step, Select `Build -> Make Project` and check that the project builds +successfully. You will need Android SDK configured in the settings. You'll need +at least SDK version 23. The gradle file will prompt you to download any missing +libraries. + +![Step 2](images/classifydemo_img4.png) + +![Step 2a](images/classifydemo_img2.png) + +#### TensorFlow Lite AAR from JCenter: + +Note that the `build.gradle` is configured to use TensorFlow Lite's nightly +build. + +If you see a build error related to compatibility with Tensorflow Lite's Java +API (example: method X is undefined for type Interpreter), there has likely been +a backwards compatible change to the API. You will need to pull new app code +that's compatible with the nightly build by running git pull. + +### Step 3. Install and Run the app + +Connect the Android device to the computer, and be sure to approve any ADB +permission prompts that appear on your phone. Select `Run -> Run app.` Select +the deployment target in the connected devices to the device on which app will +be installed. This will install the app on the device. + +![Step 3](images/classifydemo_img5.png) + +![Step 3a](images/classifydemo_img6.png) + +![Step 3b](images/classifydemo_img7.png) + +![Step 3c](images/classifydemo_img8.png) + +To test the app, open the app named `TFL Classify` on the device. When you run +the app first time, the app will request permission to access the camera. +Re-installing the app may require you to uninstall the previous installations. + +## Understanding Android App Code + +### Get camera input + +This mobile application gets the camera input using the functions defined in the +file CameraActivity.java in the folder +`tensorflow/tensorflow/lite/examples/android/app/src/main/java/org/tensorflow/demo/CameraActivity.java.` +This file depends on `AndroidManifest.xml` in the folder +`tensorflow/tensorflow/lite/examples/android/app/src/main` to set the camera +orientation. + +### Pre-process of bitmap image + +The mobile application code that pre-processes the images and runs inference is +in +`tensorflow/tensorflow/lite/examples/android/app/src/main/java/org/tensorflow/demo/TFLiteImageClassifier.java.` +Here, we take the input camera bitmap image and convert it to a Bytebuffer +format for efficient processing. We pre-allocate the memory for ByteBuffer +object based on the image dimensions because Bytebuffer objects can't infer the +object shape. + +``` +c.imgData = +ByteBuffer.allocateDirect( DIM_BATCH_SIZE * DIM_IMG_SIZE_X * DIM_IMG_SIZE_Y * +DIM_PIXEL_SIZE); +c.imgData.order(ByteOrder.nativeOrder()); +``` + +While running the application, we preprocess the incoming bitmap images from the +camera to a Bytebuffer. Since this model is quantized 8-bit, we will put a +single byte for each channel. `imgData` will contain an encoded `Color` for each +pixel in ARGB format, so we need to mask the least significant 8 bits to get +blue, and next 8 bits to get green and next 8 bits to get blue, and we have an +opaque image so alpha can be ignored. + +``` + imgData.rewind(); + bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight()); + // Convert the image to floating point. + int pixel = 0; + for (int i = 0; i < DIM_IMG_SIZE_X; ++i) { + for (int j = 0; j < DIM_IMG_SIZE_Y; ++j) { + final int val = intValues[pixel++]; + imgData.put((byte) ((val >> 16) & 0xFF)); + imgData.put((byte) ((val >> 8) & 0xFF)); + imgData.put((byte) (val & 0xFF)); + } + } +``` + +### Create interpreter + +To create the interpreter, we need to load the model file. In Android devices, +we recommend pre-loading and memory mapping the model file as shown below to +offer faster load times and reduce the dirty pages in memory. If your model file +is compressed, then you will have to load the model as a `File`, as it cannot be +directly mapped and used from memory. + +``` +// Memory-map the model file +AssetFileDescriptor fileDescriptor = assets.openFd(modelFilename); +FileInputStream inputStream = new +FileInputStream(fileDescriptor.getFileDescriptor()); FileChannel fileChannel = +inputStream.getChannel(); long startOffset = fileDescriptor.getStartOffset(); +long declaredLength = fileDescriptor.getDeclaredLength(); return +fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength); +``` + +Then, create the interpreter object using `new Interpreter()` that takes the +model file as argument as shown below. + +``` +// Create Interpreter +c.tfLite = new Interpreter(loadModelFile(assetManager, modelFilename)); +``` + +### Run inference + +The output of the inference is stored in a byte array `labelprob.` We +pre-allocate the memory for the output buffer. Then, we run inference on the +interpreter object using function `run()` that takes input and output buffers as +arguments. + +``` +// Pre-allocate output buffers. +c.labelProb = new byte[1][c.labels.size()]; +// Run Inference +tfLite.run(imgData, labelProb); +``` + +### Post-process values + +Finally, we find the best set of classifications by storing them in a priority +queue based on their confidence scores. + +``` +// Find the best classifications +PriorityQueue pq = ... +for (int i = 0; i < labels.size(); ++i) +{ + pq.add( new Recognition( ' '+ i, + labels.size() > i ? labels.get(i) : unknown, + (float) labelProb[0][i], null)); +} +``` + +And we display up to MAX_RESULTS number of classifications in the application, +where Recognition is a generic class defined in `Classifier.java` that contains +the following information of the classified object: id, title, label, and its +location when the model is an object detection model. + +``` +// Display the best classifications +final ArrayList recognitions = + new ArrayList(); +int recognitionsSize = Math.min(pq.size(), MAX_RESULTS); +for (int i = 0; i < recognitionsSize; ++i) { + recognitions.add(pq.poll()); +} +``` + +### Load onto display + +We render the results on the Android device screen using the following lines in +`processImage()` function in `ClassifierActivity.java` which uses the UI defined +in `RecognitionScoreView.java.` + +``` +resultsView.setResults(results); +requestRender(); +``` diff --git a/tensorflow/lite/g3doc/models/image/label/images/classifydemo_img1.png b/tensorflow/lite/g3doc/models/image/label/images/classifydemo_img1.png new file mode 100644 index 0000000000000000000000000000000000000000..916639c067081b5a193f479d6a9ce61239fc0c6e GIT binary patch literal 140249 zcmeAS@N?(olHy`uVBq!ia0y~yU~^(%V7|k_#K6EXiQOQGfq^GH)7d$|C9}97C$W-& z!J~6(czHWsTeU5gim z26l&OE0ii^6<)P{{bP}s`%*FXyrv8!{Yk_e!Yqf%<)RPVXQ}wA7^kl|9SqmS6UnlJDz9-uH^bB z`#=7yi<iId+EwOO~cHcOGb_f&%9C^0$Cak zwzj$&9q`~ip!wQ(?wtCJw69rSDwccqm5DJl#C0r+2vwN*>3_`e|GBNKv*t7GAtn=F~c!aGBeO6HPczGQ43p z6~2y#|Jtiy;Y~9)u*lBW)Oj~^`mE`zJ9@7E%)YYIQ_yPe+#t^krG`3&s~X{Ks^4Fn z=)Rm(l{WFDv(whi!Ox$bO1ZlyWVV;=oCT+A*J*WJ|Cl*%kAe;30f&ZdI(nX0o?c?i zQuF-Y_ab7dm7V8p^|@2kJG-ubbDplmmek_F!s~LvN$}GGi`y43FizAHV&jx};=mU! zduj4SE=~yzMMtGmAJnHzSiHkrUqZ-W!eSP$nm4Xn%fnNgnb=e(ESC6L!NAtq;l}vn zLPMj>se4(PKV*4C{;$$=732zFVe9(e#Ol~1A-m}1MN!GG1~(VJ5h!D^?y>FIwtzXq z-l~mn0rN|STXVlHtF7AgclPHTwT@E*ps`{_<8c?Z4%{HOPI%Zy4%@Qd3wl>RU7E!p zAii>$LD!s^tr{LnwI*~cO}(Vp?D{V6@SeskUw9^dOMlfWz{22E@hU&ZPvn9Ai+Atr zKA4Mr*4>cLcHs3d>EbtRJY0>!mzPK_bLqawaDa*5P2hkGa{{;ejzh9>ADk7O1Y0ds z6lH}KT=lpPCKxSCG<%lBI4wc-S^~3KqIBH>Igq3IBlAf35vC-`jcqqPt_ax+{q9sg z;`xZFuz82KjoLin_a0qOCNo{?Dp6>kbT36f(pPQb9E+SGQ(^V($h z6PKTeZtAUZDhpijMN=`=d1uhQDKokj8?DIcT9_6f8loENd^ONFM7y*zYq8ae?IyF$ z7Q1fIe(Uaj;pCPn^IXm^5WkfDBDci0wr8Kq{iW6~{dJh9sh)0qdb%rR>Bgdn$&tm8 zQ`hLOsa^AUjrN+dYuaYBbyKW2xo=Ru@$!w$w~%j6->kmrl^OqL`fazn`|!gV#W5ED z=2-N#EPi(8>6&M6p2$3ld9tPW-iw#7BVX@)-TE^1h3401FG64CUbkLS9{7IYz3O#_ z*XO-H-TU~|j^G{LJ7@3oy;FRr>|OOd&hrzWpZ9+B^kdrRRTZUs9`A|XBmV2xFXpec zUyi@f{*wMO{N?*=_6zI7|LfkL^8SqY=i?tu|G55H`zP%m?>}y4W@h$ghh`q;tp}Bw zqna19mGj(_m?g<)*kdw9@|?*Uvo+>>GJag?$WF-@NijLN;>?Om8S5`vF6K*Kx3PKS zjff;W+gE+y8=Ce|i-mUPy+wLZUj-cP=?e2ahS{N~zQEmJNyN@(f` z=!v}(j1%4WI{T{miuHTm|JhestN*R`?)v)u2kJi6iT*A7y8F`mxjRqTT(P-dv$C@J zXD;`xLpPIpj;3^f6+5nL^^5!0@2}Ipt$(q9`TzWBOO|d_1{Bh{>uN5tKJI)AZyT^PMt2kb*|Hba%;ZL03X1**w z@OFaNm_rH&?TUYn9?)G1~-Vzy2`JI(dYX3L>6Z+r#FPCvq!}ha|yL& znI@K2SzkU~+@AC{dFn>q!jA5qXt{FhdxmvEf6gc0NPcuYq`z{4flgwSQ}&|BM@Npl z?OZ>pX|kC5U7s?qYbx89NG$E~Ug=voS8CEOovpgL8MnS{x%^V>W!INuJbrFo$ENkH z+qf_}yf0V&xn0nEfBOEc`>_+EHmnXuthJ7OdFvqUn^YY4}yMljWCAdCv7Q*}Qay zhFtue6=EwwUl~iOpS?b7w<@FRRn>g8!Q)+vb3LPzC}LVyzT6>v*+gjeJ!)y^7OMkf3&`?URJdF zQ{>a{`}zJ?9gjJ@^UR&>`#)+oC(7CS8@_*2)Bkhz^ZHd2Lgz$1*tVePV0-JO*5&(T zzvW)tez$v*_}thxTPywweG_^*X|=bz?%i!?QX+3|`hD76e|@}SRN%%(PfvAf`-kzZ zzq6rhyVvGbYqgfGD%^VamFjByH78?>ms;(px*m0U>*wqH;?$$d3u_(ucZ&0U%PH`B_uB?U+dy4m@-CdeDwtT>g=)mi?95 z9d8Q4H?P|H*yG&9-@3xld2+tiRX=acNKWr}m$(1ueM8?px;ct}{s;TQ2TR_c{JVUQ zzv-NBR8y=^JU}9;4jOg@3!8(tHr6z$PmDA;!VzjpJ4|SWDTtOKODZxN)4{^3rViZPPR-@ zvbR&Psj#ZZEyztRNmQuF&B-gas<2f8n`@OJrcYiMR=Vqj%tqyPmSl`=|73as??%gf94%8m8%i_-NCEiEne4UF`SjC6}q(sYX}^GXscbn}Xp zVJ5hw7AF^F7L;V>=P7_pOiaozEwNQnf*PAzk%=%juNWFm$@#hZAQ^o_Jp+)ZAim8l zfV%)iWkq5Eio%p+xVnPUq8zY0QfV`QxZ!O2`WxWwo1z{%1tb> zRm#jwOi$G>$V*pJfCr|PbAC>Kk#BxVs;!bSvbd+Sb3jpkT4qkFtrE1y4tAukua#$B zaY=4iCgYyfLzrk`y1p`cZ zkc%6L2`PZ!6KiaBromd{YRUiyr4ezCIg z>EEl?eY^vZm}EI7F)$tyY{}i>w)o<`*{@!GvWva*`ETLldwT?DhRzL*y~_Lf-@GtI<4?yr zPn=lt>YDWXO8xtl&(&R8IyyRLcAl^`ow59x>h`6NPPnk98LglFF>n2+NB{crmUIYk z1{R6`k4Rf`?UrpByRS^+%-pj#vj4f2SH06!KX+Vy!Vacys)|YfL$A2kVnctsz6$^N z`ZMQO+yBX@z6k$clV!bjh73Jd;ze|=tktL$Il&*zss()_u5$H#+h zywc00(*wMw?pOUEwL^L5_e}Z8mC~1E7QYah{r2*ny_Xs`offfXpY_fAz&oD3pUqt- zSsQJx5Bv99*FNb{me2o>0XM(S%-mxy^fgc(3%dXF>&@o0#r7UE_dM-;EmzT=wA=L* zo675OoBG{z&ny()UGY_W|K+S#zfDhTPw8D>Q!AsiXv(Mc^&1ioyVc(*xqf=@-cR4> zOE??;?LY0l>-aaF$@!Xv$Np&s{yFq>w@+|<$BpYc!r>co)_27}ooUw~xy@knZkrYT zzp$YHack#K*rj!K`pnm}W3_rs^f@bkwFUVc5t&{n^vm<;=QUsalGA73c;sTWw)Cj^ zX~D~4hCv~w=|-FXC2wPqHp}seG5Wu8|MLIePTB7)lFi%YZ}{=poL6BVlS22nnVfYG z`ncxQ+|tXvDQV_KyUyEf+gp`&yff{|*N^fQ&krc2cHF7jUMJk2PTx|ZDt!Cy2a(EO z=gw5mGECcjEh<~K&2??5L{_=xT~?#%2mW7qEB1ZLo2k9?cGd1w@tdjpPJL><>z*`O4V+>X9x3M*)Lk0TwUK&o_kA zZ@kr>m+|=CZjT(FpQXb7)}Og=1+5V|ekbCi>VKj6y*DGf10>pxCT-lg^XH=OZF%?h zq@JF3Ry%xMPG;uCD0at$U8+-qjwW4v^Md1WfacRJ=GVhlPAOt;QqU0VK9ggm?s{ZS z+f6|%nFEqz&e#9Fc=2NL@xHe=H-CS-y?pQAZ|^Q%yjWr-%F=k_m_=82YTn|^Ny`4$ z7tiQA{_e?9t;oD3mj32F?{_@*``mQDzJn`aeIP&-Y(`d1c6{>&s<09alYCJ@we+{gxZ6 zRg!n^3VOAuhs~nWJ3CfKEO_M=+44Idudc6K8lfZB?YjI1Bg9As28M?3HfQFXOqua> z{r_M2a+OaeIxUG;1S*=2{)3V;=FL%!fU@yX|JC#YgX0gv*xjW(}JgENbMJmTzIl? zZNvWRN9h|1AG?Kb+0(FJb^iJLC6{~S|NpwKuCD(4buKdl1H=2O86Jz|eUx(Kxdpj7 zxx2ZqsVJ!_Do%bM+4WY%%zSB&@~oL>^`4o6O3`}uYsde_fHW1mEQ!#GtNZy>-EWRX z)t3wb7Goa26=5Iy4%|5QY5BfMqB%D<6z+1o*BL0$*4x`V|M#8eyLRn*_KS@X6b=eL zT`eA*JNMU}-1gkq@Mdf1qUTPBp4nfVf8dad%PJF%TRtim)7)yWxc@Crs(ldw@~)uZ z)hk!t-PpJ|Kx0PBk0Yx^k81v3e*0bfw%^Hj%F_H)-F_Q>4U<+@;yPS#dfM6PvD?n( zvV-)^ob92a;^TB?R!6Ie;6{O&?jnC4O!kRW z_Lo{|PrqixbJ%ybS@zn8^Vt{}7#?-ZVDZxYyY;lnAsweK<;!j_uP=WYX*AdK+(ktf zm1p@cUaU|3{M}r5BE*|nwIIg|24R}7i>-YgZ~AdR@K_=y5-vI>+8K`gg{z-)O_7LBD*W~X0^0>xXhlWDwL*_c=pJw zBWsk-ykiUb(q1NV_^`_vr&~YVIY8O#{>-n2njnXEba-U%O+3t&Tw|0ZA}BcZn$Q{z z^QqBWgaRY~#hqF9dVaFewEg|>&kHFEMs7?x`e&~@0|UbY+a|MKFPEgG3Y9D`t-s&Y zl#+xls%Y)9eNxv|dEm&AqspX2EAi7KOvvX=i?If`q;5!20Z6K?tR)XcW(bj zue$egcgv&H)LmRmO;)Zux{`Nx*7_Y|N|4-O|nr|yNGrMx_da;(TmV(kHSIxGYCp#NIuKco1TgvY1 z%r9M`#dcnnRc{==J-9D=e$UlwLDwVVomVzo?lS4T7Q&&fzWMLrnorGkQzY+K^O38&N4+10L>#@5|`b$)$rjCKEURtAQG zd4>DaXZofKdA?Mp9>x`Vw&cAT%zv9K!+YGtDeh&Pqm;&-O z-_k3#-)nX)T&T#wwE5^sughzNU%19k{JHkk%gC5Q6+u>Mvz!9w(_vOUa@`&a19trX zcmABEME0kb$B+O2w7<-^Z)<7!a%pMHxeFCsy*iWpmRe5rGdDBYZgTzG+;{cA3RmTN zte+>Jy1d}g@tfxV*Q`$4Q=6IXn=G3iB*Wt3!&od(pmxIK+O}<`SDyT8`}V&nxH0RV zjsEe!mFLgz`}(c^e7rK%Y zV_+@8z|ioy`NlVujrHo?cXR$pTRMA1&$)S+PvQIW&GFu=R{npTUSIpxoC-DAN{;hw0-HeyDELyT`*|Lo*6YE}QbIz~%v~qfUUE#$=u3ve1({2ABZs*(g z^V#g>{&VB@<^0T9@4ql0fHD5Y>-f5V>V7iyKbG6e%E`uVExKw`vk#P$KU91;$bR|d zmY0%CJdP#(Zg_L-Nt|2lr{ClBg0tJ43d+pnnoG;v#B z*}Ao&xk|=c4R(J`>{&azBS=^GbXL}J`CspT-0*n3+|GFWVareK|95Ts{&Ah^*_hdi zX51GAc3S6udn;7DY-?d;ZrYn4%{TuPq}{c*JpQ=u`3w6!7C$^rU%KWK%gfmf@?&Yzjp@7Jzg zse07O=i{$$?_aD~vhsib{~vpkB<>X+pQ|0FWByFAPmOouuVcwhPA+R)SFL}4&i>c? z-)sIApSQ36@xf4O=j(U7XGzT#|MI8!=AH8WzipNNy-9x`y{F>ipKJBW$NS{}JZN{h zblv(oq1$UPY3!cN4J2tA-e@%JT=`Lk;Thn8*%kqSt z+ZQz@dA+?$)J(Vf%F2E@a$Y?u>UI9l3pxDHHRe?8Soi(oGgsY|KRIsRLP^4wX?Y8$ z>T$20<>Ot>{nc*X*)7Yb*JqtOUi;*VvOdqBJv$fMPW9^+6MCOF*Ko7&#Gex)A_|vn z3u9d=&Q^C%X3M>eZ~7#)m>C!<(v@5mb$SR3a?4tmeYvr5@z<}s+wXo;OpW@wwm&(m z=+j1b`O8X&iZ1(_>ql>kiE#0_DIMT%`}NF6;p5V;q~$6eFeWCgU3`B|T+W+g-YIXm48M(Q;pH7Pw|MKVX zh98gH<>t+qp|CL3ds^LxZTxy~zA6^_E$}d&x&POax2u)bEzeu_OXZfx;?39VU#(nT z_vwOv*U_fA4=+ABa^#_NJD}u0@Nz z`W;;MZ^=v(!R(}k#q0QWxfvK33NqHt{hrA-HEY*4$4y03zh`+~{nV~$Ubic_aBf#| zL9(d7-27kv?wfDjTA+3Ko1FASwe(Zh%H$H#SfA-!dUrQk<*`X;c z@Ba%o?w#m!VQwOL-v zUDp((nOF&4RElyBnl^KBrsARytBjo7pD!Qow>K(G$pe?fjGA} z;N^Z(LI z>@$1$wz?(dF8j}wZn+e-r|!$0KWFt!R{whTXYt`Z#;@}0pH4k4SN&$`^th-OpX*<* zjh!qk?BdcDSMhRb>wddiJ{>Ko_g=>ryx+pFFqZ>FV%(7E8DK zJ&BpASQh_@d)8F0lcN3hx}Awp-aFaK!qn@iuNpet&-(zpG?sX1e+McXid8_96E?;N%>~zacu28#nsO!(KrPEfN z=(m~uYuVPW`+;B2=9hZL{I9hCKRvGM;2Zy0e)DYVK0R5P>OD>G$=8j33b}9XKZnO_ z{(Hb~f5hq8?xJg-)t7&HvH8mXqxy2Hx?U^S*F4Rho_|}-$EWD?+3hb3{v3Z_|Nr{_ zy0Vm%A1CAO3ePXMfBb6p+{KzN57pG4I$wWtQ|kQRcmDdQeE$6x)Em0@{fE+&ijS}B zZqHxdwc)?QMytd_dsFYk=0%*^mlmSurIGUQa?(bN)%UNpK0eN69p|||PE~15uk0D0 z;4>))A{M?eIoQIZp_q6{#p}{q-J`O%KOgT~7QSZA)vcEwvmY|vZS-2)RZVA+#suwM zN)uz!^yMpMr@OeAuH|iIwhmtXef6=go2}k0>~v=T9Us3Zap$$NkFzse(~YBh;%&q( z9yxVvLS|l0uHBCRUz;DZUpGs5=)}NKQLY&FR3Ry9bD6K&U{d)K7$t&`?Hu}ZY@837!3qMav@y(;%yMkAS9Q{0h-M&f#OS_NP zqIb7ERo-6vV`ltct@soBzg+Szzh7Ja^Q-=TyXF4#FGh*!zT#<0*!4?iiuRN0>T2=Q z(yLdl%{n=0!sqVrb?Xm*2s!U5x@4MOW z1_NVZ;bQmT$2VTzPS;LuO|QFqFYLJ2M1jt2Rq~VTHILlM&|WIHfuq$)({+he^lSI? zf2y__UGx5{e`UM*hM;Ba2V{0okNK!r9nHG?i#LD&-q!~X{*7w!+>(~`>b0%0iGj#)izCk}v-M-p-$J;r+jN@A-K7 z?0#OkY-_9DxpV8%x1Y52c0Yf&yYuR4{k>n#teDA_Kr{`c{qyo_y;#r)Hg7nMwi+nM#WcK+V{o10SK{pq|BE5E$@&+hu~@7vnj z&umsc-uL(4`~Qr>x^bJH-2XHC|G}&8t?&MR@csYC4-Xgbyd%Q7dP>xltA97%&fov& zl=h$3!5i&_cfQ{LcWd}z1C>Xw^LHc`RQ$La9#@(A`ulI!zl?E60V{k{*6 zxU;XV`T6U5{qx=T{~q64{k^BRSFmtF#qFol?^eIB_3h>D{8jz!&A*HNa<5*#H2l2h zsrIz{MW4@3&%N#DqI2x3Y;FC%-+SNh`|*c6`}*422aW7?ADZ9GTNG$aKV4Q*^5^{j z&-=}v-@je`?Dzfu$CcgtX7ER`uByJcsK4&Z;_$dq)5`njW6XXZ|NkpKd(ruO)%ShP z@4q-_AAjQigM;t)@BDnWv$HTQFC*j5hPuPG^Y`}mq#aRF5nbQ^^WT%=O5Y<#bkCm6 zSvKjJU7W~`b^E^E-fwGVGs$cDneU(P|GQmpZe+8@Rruq@#qRq)_U3bZoTS?Q|Lp${ z`7JMAOjQ2=^Z%doK7V@iYm(pYD*g9U-n#0`{~yoHTYvKZe=vW2_S%hx@c zzCR};=g0m3+yB?{-T!~&|30sBNAQ@6ZP;op+pY6-7A;w?E;ZrCyp9U}uYZqUS(mZ& zP|Cs+XJo@qY`M01(#Ede->+P|F8#6NWaXyPloLWqM}xW;jDwX$eL1&Gcy#O6uZ4ei zr)S^LM+wI-Q zj;s59|DqGQ=f)qa8++5YPf!b!|9#_leD&L}ot+pQ-D|62Pxx_)>0`+e+k6%8F7tr2Q!%l^Gu|L@g-#=jG-4muqX z7M{F*|F>6-wZHd$x>~;}?{3xS+iN7+tgg6h$-W-#Z~wWcMdi$z%!-N^C)MYBX3%2w!63I z-1NHWs`~k7meAV6H48t4*MI&0=H}+(GtYKM?f-Tv`*^?XfAjy3|Igr?vikp*%l>~~ z9Jenq-_`QvW3v1Ihw^>>y}h@Km92$EE=G0BNlE=#|Nr`bQxl69b|s%1^Y8EbyZip{ zIJ^1%Po$o0SW)da_usYqHQCqKZQuW6slHa&v%RkZ+83%#GvHZ!%tcxG@c-}izxP-B zeU+GO#o626zyIH{?B(a@#O=#zop7>aRZZ=g@5|Tj)#aGNcldgI_1|s$cdy;MDYo;{ z+pm#Zi&WS4tTV~vJiKVyg&6t7YYPRuBX~SbIJ4K5YWN7XDZ0kLc~KvqXm};6qttHx z?At%ZKe4V|8gb#`(z#E+-~WF<{N-=ZP!ogFTHmacCHpJZyKFXletwfgxc{4Z6YfWO z%)65MM04qsYgSVQd}}VQuBoq%x@vgg_}5YwHRl6cjNNXsr>QC4S`&Uk=o z)mMt}emNg@ZQ>n;t=Fc-+&Y>UdT+$j5TL2>O?f&81BJh!ARn>cY|{f~3y z+&gQ0ec!6ve_h$FcgyLBb@{uR9}n9C;Y z{~zA|S<}~P|LG!s{_ZbEO1E~tUOPR$s<5Eo#ZmG3@!RvxnqH4dulxV+&vSeG4fXbh z`qBH|^jW`;*_86}#D^E(-s;*ux2=k2VGj6U7apC90IcJ12lb-(5k~Z7zvut`mMaDXQf*B{e94pc_m;KKZcJQ! zq~_|>@QKsT&fb2-{EEMy-@YH0yl0!|rwZl1`{la-{#FiI`>H7&>v#Qn6>VSOT^#&* zW$^O4FOTKtzO=nuzU=+Y_`k2N@z-6r^8U5;=f~}JOIk%fyW1E2R-GO<%a6UCPqyyG z!uGmPliL^lj=z{|*mp!>;=g~4YEirM{`#8Vy>joKn~PFaMa7Tm`@iE9r}Izwb>gl3 z-Y=87v$L}Lubvy85p;A-T$AVb@Jl(c7t?K-t(&Xr>RwWPg~c^BgAW~ z*6EX4ds9{)jfpzf8~Vxhx7RfN%(H%nmAH-{U$OAs)n_ll_fHVeR=aKFxpa2vvzVz9 z`o75WefjZY4WF0Gl=DTa8g1rp@BY`dj@5NLM`U%d*0$@@X9RmaU!GQdBc^VT=hf~R zC9O-W^@`?mPjva)_pD{cl)VquFiq7y_wO$g1H+C59IkmfLT3*hxwLo1?zLM>Gb&yj zXk<3OThYuR-u-Z2Eqh1iYgcj3ldjR*_k23_ZC>#5_V)JZsA$hG|CoQfdQb3M8@<1= z#pI%Y{jbe6daEO9|CaCHSM^n@xcSMo=)AYDUj2Fh|L^(D!NL10-fZ0cerLO9_Xe@P zy00$xp4}eq)yHpbT^${DTkhx2^K9(x^QvCG?63K8IB=Q`r|{Kl z*Zv+f|F>Y}O3xY7bmH#Zx$}j;{(o-Jnx+Te>%N!o-nF~)Nn78!-q+XvxBq`zFZwXp zcKO!5cJ|dj(tpx2KNoi@V%pV|LB>%BcT?cDaotFsUP z^8NpE_W%1ACtjTY_f2|uT%oIP?AwyBi)W}znjT+u@=WBm*s_^wNzYE}?SAv~`TW~I zpPkDoTeWT5u_bl0TU3qiGd_B~e*eGX@AvaJ-HeWo64#IWB>(U5{~(^j%xc=b9j$f0 zF3)d|ntWmUzCTa3*Y7zrr@s9AqpjK3Yd_EauQ^}8;K{Z{LA6OqJAb{(-uL0CzDuxV zqEOY3hx4C(vP}AQ_Wqx<-uj?+;+30Mwb- zM)A&hN_TD-f4UkTC;CYA^z{12^XnI@1uLt}m6d&cef{rm+xLI|)cq`hpU5eXX~$yGrELYUWnx z9e?T}zxk6y=&JRuAxoa#j9ug2?V0w!j*)>OCLrf?#h2w2JFVs+X6+OwtCjW0I-W$(!Rx+-+0&#^lKm5;w(?|kt| zTQ7QV)z)6=@It&1yuabn`$>hCV~zQTr`YPz>do=!H{yYVq^QslmxpI5`<-yYEw ziriK5QhfiPrv;6tF?OXUdU!Lo~KhbNs$|Z{#9d=(1^8fvHGrqU4@9m9` z$J*`xC<=B%3Mvwx<> zgl|&s9$o+6D{JkUarM^K>2bT(mejUL&32kQFNfv({CnhWYBFA5TWfq>{nGk9 zo9234TYvw;rAs-_c*A2Vj~1V|jXxnCSN-?v>-D?+R)oZ#ShH7sd;OcT+aEPtF5SAe ztLp14=HL8tUcNV;ICs{QwR5c_Q;wbr4UZ{ot^arTZg<{}kIR7RXY{qfn>5gAusnNH8!edUVz^ZQqBd|1d|`@-G+*Tow@ek^Qe-yXN;s;7O* zYp#>Ct?yr2)cN9Zd5z87b35Mi3)VgoF5ma>miA7ki6@sN9$jxAy?M95#FCON|3B{k z_qbiI>c!XV_cg@04w)Dj{5bUa{QeJricL*Rug8|ZJ#JT49b4-xvhtmjkmu~r9kKOB zR?}9#4P#gO|L5zR^Y^#JdYPP`{r0+W&gYlSDPPm=0J4L7@4T085UpXwwzm9e@DEea@JR<`ZC8=i|on&9wdm?2Dn|(YD@I3`t}|?W1)KLvEZegy3ZX3xwp2wd@3Fv*4>;G(m$%`=6rnOK=k zJNwkbVyfT!n|s?&+?i!m9<4Felhd>QKSTD$?cIxZs~%EP?C;}!zR6N>SITX(;`be% zEh561lTL5TU7S1JHHppp{!BX|ujN6~X1PMu|I)5bEfL7MwdLp2x3_=){(bka#$t|= za($y^Nx}A${jOfUCRTLwTA!I=Z-SXe!pTQVZI}B=PwaI$=H|Y6=Ny5h!87;nE)QP9 z<6`@7rOzyruV25qib+M^x39mJa+L4d$Jh2oMw8B`b-sMmt*^B4de7pOXO4=;e|aqb zH^AiUTubNZZD(TY|L-KG1y7KClyE}ia&CNYC>1I=K|_dRL1|0O8=_3QVUI_w+8^p*KH zo;YxzK_E3~<=W_N0ZD@A49ol4{R#^nR~SpLg@)G3ojb?e#bAU3>Madqzp=#lU}6A@di#7nQzv za=%^Rvy3I)XW#zW`je~M_J3sU|G&RxtOq66%L;YE3!_^vOrL#cl0n?>#LTIOyMFKL zUFo8q^y$I9X*bt}c*x2c*&TZ6;i0r?nzHh?iAvX&`Z@cG%-DWl&D#%76RoY%bzi64 zT48YRWyzO+u1d|JTe6HMpDpP)qPBU@_UvN;KCKh7Zlzb>nYQa(PNK!!m4dl@(^85Z z{`MdIbv|-tHXuHVnVz@Vq26J@+Pa<}p;*4sPk_6nMPdvAZ?=FOey z=j9S_ZA$I_xz^=Sv{}Aw$%_yF_EvA5rrh2y(lx8oEbq>dS)HZv_a%$_pB@#Dt9p4< zJU3W$W2uQ?pxtzNS^3P%26Fl-}~&BymRrM+}~NLX1O8HzU#Z1hjo~K<((tA z=-Re#8l3lZ{SLY4tX-SyV`6D&X=ixx!i5E{K6=}OG?moW`aW3PrzW)INafnazn%ZPdT>mg{|19){7H2E_;@?zwXhWwX*FRQPTY$-u3bF zf}I}G*|U51_9q#%E?v6ys+RcQi$TXOU$1}pRNVLP<#a#$U){&=d^Pt?Z|9SHA^+n2 zi;VBDCQrC>?V4b=(Bz#WSN&HyaL-n=RJ(fre)=-Yw{LTobWZuU-#+*4+jq~F?D%|L z$!Dd4!Tj~B@87?kF0%C6Ha@N2HPO-0XOeo-&wX*dZojL*Y0=rQFJHe-UUcnRSm%)) z5r6x(nSGvn!Q}0C^}>H&zw%y>seNl29)I}E@jlt=r&Gh{RlnQ0L4vQBr~bS3{hzb{g(pW|t$Lf&zk6Nb=hu_{ubN)jn8aDCqPXfs^MzSCDq_NtZ@u26s~_>v`I+-= z(KFr6wt5T<4cy*Oj4nBy$qVgoJ9aGf^z`{Qg?|n-GK>@cYgeu`G)i+%Tc#m&Ql(b)_3`uf|4qBT@pZn4@#aIDf@iFW*D~_T z?zFn;;va55{rtY4&t^Ykvj6(zvKjxu$kQ`j;_mJHn=HTEHqL%mT;QqYYyF=UxrW)w zs&2nMaf#)(zl!GNoB!t4iT?h(@vCc2#%`CnbxY5OyF^Uvd-eLpSHbeyMfsCT*B*bp zyK?f+A6m8blb*k?tq)rhv$5u9SN6KS-}e8T{(sWh=ilGloPG9LR#vu8t>D|tc}rjC z+uhB0HG7BMw?D1VD*o;I@^$X%@AiT7&rT5qO@IliUOn+uNNtJA=i65#SNUvS*nQSW zOgaAWr`_DX2SXOEsExW6oGpCT!E0sG#)!W!mv4`?{L$V1+S+8}rb#m_D@x?g%zUCM zFzvv-A3+l{wXgh5e*ATMtZDSm9_#!U_P@H1^)2(*ZKTNYgzwcMlMd$3(>hC@oHUwz z=HJ4VUv9llufDVT*1DfxKeo@dzCE*3qIB|J>^p0;h<7QSAd_jflx zKhW5GWJ}@WV=LqW)6?5IIA2HS?fc3szvJpP_3-;rUW@GSzWwjIzeudKY@>kS_wW2c zTcqT7?)IAa(&fgFRlBULzrDY2ZegVJ@w55SHa7OoCEM1m+qciJNAK7Xp{-{!gvi+FwS`TF$-Z;v{C-zP*-w^Sv~u<4#|IAnb#``EdDa%U=HGz> z6Q=g1?0U~XF{SvYli~RzyuH1h@A-{&V|P8d^?F_Xvzf~~f0X2(KNY&#Ynp~(xa*_q z_EjqbbX3-zPcf6$T=^{O{J%eo^~1g_JoD@K{1xwygn*J%##-;~QIGdF@~OM-oUimK zGh*FYgUEv?@y+Iq6)%nU{rL3fRKO=Ou zxbuxvozKyW6CX^{u6VgA^0d|0?9k`a?tJ(->)WyyUrx5B+^n=e{_BrNq_1ybUV+Vv zTTWlI)2r`XEnR)REasYh$&!t0TW3U0+JVun-v`;J9qA^v{nB!axWeWkZ^<(K{V{`{=0^`g@fCtbtdbneUE z`1sbU%|w5;09$w(VQlrH~1S z-rcRzzo+_V`tvf-!d7u1MM1G^@5+~-{1Cafs?=(-(z3to{1Yx*I~%>^ z%1jlNO{K5Jl&s30L>R^kEbElAr5`$u$)tdvBJle3M&GJ&( zPdlM&A-n9vV{0}V?A`i$?cU$tXMI-pRWY%&{CfZ2pY#8}`2YW+|L@WH)34p#)T?Vl z7IZAx{`||8kZb$x#N&%P1!S#?DxS~I-}Tyg*0JMi^C~`hCT3;iL~Ks`%Ja3It({-) zhQ5z@d`+O*RK5Q-`nw--DQE84@>ezdeyq&*pSyl-bN72wf7La5JICdV$?j!){I5`Qany*vCBUh~3m-q3~(RFoN933mRKQAdOI<@}(#cPRq4*PZ%x3A1!=dU;a z_tnei=Y0NIJY{MA`TA@3>)-zZjZ+>-lnt18B;}gwk{z?2Wc!{odK$g)&%}2#^>YLR zH`M*D`oH4e#=prTT&=&~?bhcxd~(@+ZxJhf9J zDM?FAt*!0T{2k_7zfOvjUFWiE>ZQz=^_#ctYn##~qMD@nGVGs3hmPK2vxNrR@3baV;&E3VD<(KW;5!N5lHN#Rz>^NJS-KHP^w4?OqKmH9` zq{%2a`+(e5H`lviT~{9-cK`MJm(RV+%ir%@zHeb;$BY>f-2vIzuY>(*X8Ses3#{U zyL_40Uz2k5)Ks54Hv;U<4D0^f*!b|_L)+cu+qZ06(j1bX|6afT=jrA1DkgQ@x_x{9 zkE8l*jY11^%zm$4K3{QKxBkAAmz$QlT{fCGd-?o2wdrTq#cV7(eQoW<*2JVo=H+{C zUasD?a^uG~={%F`=})^v&)ffR;yY}9|3={Cm0*8t`u*)~^@oG({IWI{mWGvwd9SaH z+I#Ek$4Gti-`Ai2*qGejFQ>Th;lqV(%Z@dK`ug$;uZ`IFr&T%weD+mawRZhkKi|DuKd;^Y_uBSln<9<*Z*QtReM(gO?DO5(*Vj!} z_rG@a+AOZRzoOb<`#$_BUdVU<&PTP*E7z_*ExK9z`&<3%{C{Z`B{MqhzpnIO7rFb` zocai!`kzPiXI6d&@3&A{xa`<5bDwegw>P(MN5se9518+_)ZN`JzV_+V_chP0 z7cX9Xrsi+y_58b=uFn0x@$qp!c{?Si!-t!Bd3(KBO-)UGWR?V3m%o#dmVW*E{p=Yt zGIBFdihg3}m-(}M|L@z4|LPQzo~>TDYt`PpwS3R_m!H3qYyj(OFaHf{~g%Jwy3xvjk8_qM=3(TPtsJwALm+5GOboe!rKXRUwz z??*)4g!49+@7z1FHS_TaCEq1I-1ky^C%o33;*^+@P_yN0*t>r}cFKG|94jxU$FtAw zLyEI^@v?Q(T5m2{p>^9cqc6)&@Y$a$SAKjrG4-tczk=)S7yURG7~Z?N_}sVXo}iJG z=$j;V`Symw%kOM=w=UVdck$}gr~f=%t;%I|KE>$u_4T)Rm+u$Iy|?4$w*{GtW43JF zTKjCC|NjT<_9vbf+y8smFZb(X|539)!WWN<$JU(gHFp)uDoRsQir&9*<->o!-~WGC zzJKy*(Yl{UCi~lboO1eO;o==z3aDc z-2&!jSL@$>p6|Uh=#kR;&W-Bo$d&^$F+W+a) zX_qTEZfvML?Dlqz`N#9$Pn}+GQTgY{m5^_1x8J|DEmvAteO>*Yx+!YML{z7h>%ZFf z_?&g!x6Sjjbo*_7olx$#In{OcdG+<>c3)2{?ic&~^TfwwtA}Tvzh3lu@2|CMb-&*$ zzyDqSPu;!=^4xT~GFRCmo${JT=O!=r`}Xad zoPFgd{r{izPj;1ci|O9lRQcI>e^nTF;FOHGUH{&FR-JTf)~xllZ@2$@bN=7!5WVUz zCocZ~zW)ENl&$@@I5Xeg+B*No6ZOBJ_y2h0J+JOpreM|AtJmYIzkYSS8(aV9`2XgW z|2zF_9_jyor0??L`u@6i*Z0>=YdQP%=LdJYPp6N|ZO(%=$@?xW$!%%CkCC$kD24QYgXvK z-Tr5f+navdxZ9tPr{(ZrHL1x{GM@);o2?)9K}|-|($K)*-^Xer`QK0O^ob@P6?YT6 zTl(jSM_qwZmrH2iV)@BC`s|hF%1heU)ufbMTwd{1<~C>TyVzehqodzR+F6>|nJB3& zIbyN-jIDQ=49l6WE!Q49A9hx6v%m3e=6Ri+@9*?;GcY_jB=Gm@n$8v{!HaI{0+(i+ z^0%Fz9IdQoAWLoaPf)?MDq(u%JEWRrc4Ub~!SnoA+M+I&@9urw`Ri8pzK`tt_g9@=RWc#ztji&n z*txRb@6>+J|95P9v%^iHrN25~Z?5|KO278w>DA%uyOz1Q-QaL_iLZP*_5Yv#e+75j zN?-b%im6YFy0Y~JH-F7P?)VA^*S8r{U(dHI{dH!ho#L)9mvYaXikbiEeEIFCw?hsb z+4T6UxyR-XzNRTjK}Y^Q&wi!7w54_Gr}O`t<^Mbg-}h;&>)lu{$=$njVt0MnJb&l+ zYti|EYR)l%k3NU`biVIjS^sou_`lEgzn)89TYo;qNX5hSuP-upME zoz+^DQRoz2|9F{i{NG#GqoQxO966$|^D3_7dTjaKg1cY8{njkD{y)X5Q(*I_^ZS3j zuYdGw{{H{!poZ8U=?}kHPR_bF_nJs<`KoER-^Fd36t?F3hCO!o>wX`ak!lj_rJs!IR9sl5-c)+M(PDDD!Dg|*Kx^sSOD}eKA5+{m)9X-F``^ER6Ag1RbMrDX z=H%8YzIy*!TZ~J0ZSGgz(x+elem?K_^cOpul+>%}=-ba;|4H9rx9IE4e~kt@+sw?b zo12_lSf@9e|8SDpWY6W7I)5ouZKzj}7qhmuHePwfY0m$h@$+NM>(&bg9O@TFym|A&BmL55+j?CagA3{^bLYl(rRH5v&oa7wyF4u;p+L*}>a}avF5bI$ z@1`WnL7wOHPd`8GWEeczZ>dq|uVmrJ%7+)feVbca`t|wqKk489_TQCeV_;yocU@!Y zzAsDluV25;?wD{VRMh%IZT8grQ8OeapE&%f{o~v1_v7k}Pu_NPQIdT9{{O%CX|sDn z{XYH({CkbhvZmqJ`4dMhG>>lOy>j(v_BHnDF=9ILm3?2Ar#@of-RH8nTEl+D=Sa0h zCA_ItJ5sr~#yj)AJ|C5kCo|9H)2k1s+mC(gd-nVDQBT2>OQfT+tgf5o?OOEp)z+`s zVlQ?uFfg2xj>_({nv$%`TwdN=Gz?FV`H~xmEP5g3i=s(<02!& zgS`#DRVtSktDI4*bD*JmS{J)uk1W) zqTqSuWV+FU){ezn@)a+-lqK3InPtAX^~X22=-A90wT1wZ*?wRT`>mP3Cy|GNfniVm z$58dI`)@XOhKt-kq^ExRdrDx*_7gU`o5u&1qV%49q1~&+|ExFI1sm-De;(wxitxwl zZ8A!=1vO``J=J?=pW^9!7M=Q6Wu8a1J-+(2Z%*{C67w$K z)sy~a-zqchoUwmNYp09$#>UIb(!N+n2!b|;|Fhm=r*;f9hOT}3Y+jTLiQGedN%!Odznr6oT3lYXAQ z@#mN6#LHycT@eeL1WU26CHkK5=Z5y zAJJL6HF#6aMD3?XG{dzE<+#7eF@ko_GI?qK&-{`-b?(QT7UqwbZ`dT{v*&xS^ebWj zZ?)VE-D=q}C1~Hzlagy{io=u+-t8@Y+cIyz*36|(w=EZ9|8Pstd-2`m6;Ys&f#3tj zQzij-hVCn_iSaa$mX$sG{4@7w(8>UaCWZsM zC;6y7F8^_KZjkEcDft&aO&9xen@xDCaBZvR{e-7QoA&g+Ik$NKe*4*H^-kOdrzeQc z_kLN~*}35gg08QHj{W9R7P6We+q&V)6~5I8Cxj-39GV+ycS3B@{(sl*^YZbXJH8tf zvJjmN?*(t&zU9-jJ6GE0Sg7S0hRgq-d&Y*myQH-K<^+!!Q#&-)Pl$eRpjM*$!5Z1Z zv`0VR<=rm%HR*oN41-+NOSf}hg?(97^n3RfUGbGq=foo(x}E zF0pp~2|J*Pl0^UkvLy6MV5uFxQ&5_Uvih z>#>+_+$+07MUnobvFCYLV5Xj+-x<*7zKrU+lZnr~Lf7 zP@|B@q?b{rcy;rAd)oI2&*DPZYs*UY^BT1h`N2#qF-FlmM|6FHGOgHT$^X##J?Ls6oW~* zk77=VY4&IDa)#{VKOH=O%J-n4C!fL%ihY-WOhayR4gTFs-}!!Ty;S?2 z^oo7Ike>=FL!qW0aPF}_^~yITMK%8PC*H_s`{NELm>e)u+_YW1^3{yq3jd1rHrJgJhN`or~A=#UYX&d)75-dB&+4ENYkhBsrGPehK&_f^ zq~z02$M;d$k9QgUnv|_rQW=r9N4{BA$!p_nkJL$FT6vFz-mk3GG5a;w<@M+9?~o&v zB`wU$GO|8ta9tCYY!|Z=jNc^jx%gRp=%J%DDtoB;-06D=GKH?Uv zs(ih#!PVuBOi0{5>)jc;_vfU_&u&<|!qq_3UhQU|Q=#gbG`G|$ai}X97#J${C(rT! z$jbb8jrOM&ts<|mO&*^A7j>0(cvPO#yMOj*9jBn99%uvtszu}Yj-@tty^hA0zinJ< z%C+^HNdLZB%W}@7F3s5!wx~7W&+@=*r8h`{zJO=FbHJTPjqg;SU;b3hKliVeqGw>u zRL9MCPsE+N|HO6Abhqla$i>E#!+wj3);2D^zJ~Mk_31rEsjkac2wr%zx^(643-<$W z_AXucj^RmX%2E?usFOg{vg1z^fBu>zKJV!dh%WD)85V6@H z`Jh65zP_tv>d9sMrE@mfv3B7Pi6o6aH30Uh}LEf#Y)}gf2&&4W`Bx} z=Da>N_GQ7n`ywEhKybx+fwk%ysb^~@ik_DCSoimWaY1J$dr7zGuDyG1XshjCc|ott zL*(-22S<_0n9Iq$!B01a6VK`PtvS3fLH(~ zwGzH)q)#(ad{dXaVDgF+*^DJK!|Q&8M!wsv5q$l~uIXmCQ_4SG)BED02UZRtcpe>( zvXngK5oESt@07pqEVn8Bo*KO7PV)Zg7vz*r9b2_$#X|LljU5h0kX)8JWs1iBl>wTr zOC@yD(gfd5lQq#doZRtERD11K&FKM~W<>t<)7`x}{GRs=aT8I5#s;G;ePXI#rpbzI zHe6S*(b#vVjn3wadd|y6D#9wn^*F* zdee=FHFF%6#Y~!ZvT*$tzD1fo1>klP$Qp3HS?sPln`Q2)Cws!{>clED-_>2K4!OR$ z#BlPbG7a6D7i$AgELG;bgOrjN$oM;cy2adUc{*aX&yngRb3uE~x~P?>Ljpu|WBu4R z|27uf9K`*_4Uv=&>=r-Y`&1@E@9bRL+Ed@7I|H|_F%#Wu6I(mE_o;kOO!-3f**hbN=C`bUo42;>&%qc4zW0$tcd$b!uK8F!STmU1v_UW>#9y_~!U=s?OrP zv!8b(CDivtOP(y!>OZ2SBy{nZ=~K_RG@d}uCt9{<%s$EsE0fH$x4&Ar_I2OG)6q^I z$VK4P53{%y^O~*hdQ(<*X_D~bm?cx=Pin>#D)w}EM4lGi$;x;7{9+$|M5WH4a439n zjri2XmsT$daXM^N6q>a0P*82E{KUxzA5~BLCBa&UT&TO$#D^+fJ~iRO^c=RDFG5pq zF5k1GtcY7-nGf?~>t*E?NqUw$&h-DRpAGdtXyEp4?|KJGSr{pD^dubrW?3U+1_Su|{Z{(dOZj6n0YFOH1_U%*e7O6-iSz80SsZ zO)g}p6&B5$x;4I2-+$s; zS)ZS>t?xEYK3nr%Onb*hs3rym1_v2Ie-|zB4MK@ws^-(SJD&I)^7GQv@UWnF4V}UU zKi{1@rRpTgv<;!*z;EgMKc94l>AmQBbZgpw6QKni9-7~n@0?s`{$lpFDYb|8J?@^l zx9!-A8wfoNDh63o8fS(s$ugXN((}w4UEhePoD1?V-=~P1_k^sPa@#liZHZC((@%9m zC{>P({e`0oVI@5AGd%M4K?aA=<8frPJ^ESxf_V}Y+zn=LV zf7Ir)HtYSm;`PtEZ+cmKTCFJcXRB5(-dV6AJ*!B^{)Vw>h1%@%ZQS*bz`DhS_H$qG z2>08*>5-7 M7rCVmR^1dxQyC&)9n{TGC&nP7y_L>>>kK_BMi|e;s^RoeG$cp}p z7h|_qls-NIq}bdmn-ijCok{!~Qx`RXWDNoQwcE5*4%Dr8w(-gi4Z@Saernm9#&kbi*YufYfTk||%PdcP1e{i=q zaD7;APUOy=TP2cI3wC+S=0R@>q@xGT+4=Wbmi)SLq-GvC#t-~dxhd)~Z=zP^di{+o3j;UJ zh)oO2S?ZL2&Zt;hIeBV{{#x&(Y0FbMc_KmTE3PNL37>v{)0TCbC&YWJLT!HMZ8lF4 z44t#YxBJ@Bm49x8)cLHuGU=@EYW=vWvfTG8zVV!aXfzit{Tk`p8GC*~anj7`HLBe< z_0yI&399;rySQjxF3kwudPYH9{QNe}iEr&eHZ_zp&b*cIdh1>B*v%cmtvQJ~2{kp( zK0ePlG3)cYDDmT)ogbTo%+B2N>v3#&ZOY4c(|>=@dEY(*9G2yxkB)9s|CqdCkHn8j zA5VQztXdhdY~lu$oSk>RPkDb)DgCDwXT-fvt=#`1eX?^CJr3;J7XA53%EJ8<&Ic}y zu1rtNYg;3!eMYA=mHY9{Lls&pZkFUeo|bK;mAH=dsTTc<+9Osq(-9`OU)RdrW zMy_G=m7d>LQWAXoRpQt+L!X^jIdkuND1LT&oEr#fkUW@sHg&t+-WRv>xIR6;dAal7 z!OdEcpC?QxJ!k%x>uAox8N4A`pG$My&QyKAd9PR(bYls_h7UJ7r+tk6`AEc2d$s=2 zWho!8Iej#e^12;6d*My-|Qk&8u))#DR*=1pLbGqNvyuJHM|1Mp7TmHS}zWgsS-JtZuprgWB>$T*`t|F@` zFXc;Ci$$eRooTak{-YFq|L0wD%WO_hy%}RAXWX6fnhV;?dLZkO?0vR$`}&A|8#8ON z3R0A$%R`P%S@SvZMAua7<>!t#8Cr+f#7dpivTtns=NP`R*^>{_((r2M zk6W(O@9tXT@!0wC@-2qz)R(TfsTukF)K1^&r~LK9XXuD*e!F^>-N&t8^X+c${{6JE z*b1bP;Xu=YZS@;OcIHjhF)DnWHYxc|L~6Ha*X5ljzH#3=9{6P1P1RJhU%RG$t`c;8 z+dXl^)&<3OAdL+-C#>Yn`~9ZP^>nt|=Gvnh99-g-9I`2V=lH&}s<@~+^P=$0ham=) zH`%Sjb8;$w{dO1p%Lf|ME0=q-Y1JI*(_cibDo^XFM{LTN*_$@QH0o%WZb{dSl?%?y z>WG`MN7M1$gl7zA&UnQ(K-vQV$5#2~&i{LC+q9!q1&_8|-Ebl^V$K(rqw|jC|5eqz zT`uPGTklNo{-hc5GWJ(*#O`=LKR0UQ#!AONP^x4w2tU)*crEH&r%Czhpq;F|-cn(E z)?b*ar5PVrYjkQ#chmRZLT42hA9PV#bpG&daCc-s* zRkBoR?&_d5)|0?3ngYd_FV^jUd^-Bpv`;5o)*E)Zmp_}dDYRsLew%dx_x11ytA9?5 zT={+H$+s`WvN*<)-UqE+dQ+oEV=0(Yl!`0sq=ixW*xWx z)4DZa6UgL(gC8etIO4sgYv$%V9-A+E#XdS2vDEON|L(qp8sG1nd0WGHCUU>fO2`1+ z^U1uot?a)&^%Z_NGbeFTOmEVxZpG|Ii`RnBtGuRuKP9Gitb6Zv+YMX`--FEFv0z6{ z`KQ@`{@gC!w=ZQ+n23LI`8(ZwS*MRz4VA*Si3R$s(6aqN@{g$r&ZxhjVAGe&DxS;#s@8e|+`vBn@yKuw%oIUqLmycb`5!@1Rze!51-UlS3hy zrH5J`dmS|wyqU^3cS-7Pk^4J~EkJ(VqYiTYG5>WEGS;GPtzNQCHiwO`hg)3MyZm|G z?&@%!&(6Z?>wo@Gf*P*yBW{Ju;RXAjCDc@fojPiiEx3!P;{3g%>tX|sq$ThC``6EP zcdSyb&+FFO;~?`Hrm3!;mA5bZ?1_~59oue(r=Q-n>dL9|M3$A@g+97QMy1boSx+xp zpRVDXwK z|9UHJW!hT3cFr+AmK-`^=e>U68A%Z*UOkL{A3Jp=uilrPpul`k+j!pgC_x*fziQ+{i<;k_zYm+#g zzy;2R4^vDuKcy^f+4m%_Tsn4&_0%Ie=F&ZH{an1VH|91k2~mpBzP8w6e?F*UVmMHE zdik}WvneaOpRIhJQ8al%5wCYz#j|g-GN->3^#5mMti9INWs8{Q?fnrO4!6#8Xx*hT zv#g{&3Vee_;!KG`;yso`?{YZE6MF94rk|az*}KAWa;)~{=Qy4N_cGpB$1I=!`a^NI*tBB>K{20#9zLG> zX0@5YK9#PeZ?f~Y9PxHHchX*!0k-_Phi`1b+s?y1pULY0t0{qxaObN$n= z6CXRNFVfnw-0N<$=h>`Xc1I!=oQ&Vc6_zd8`lR^biw9HqJojuZ+G9NXw&vW+K0YqX zzFbf>FPrNPPW26&1GAV*xTc5~^;xEel?M=k(NDoagh7u2OrKm8X5DW5P8hr^LX1-qgbZm#x*3 zOH#5PT$-JD0#pDUU`m)9_OWACms7BbQ?{(U!au!r(ibJSPV#NdJ9aGQm5qzOA}HF# zI(TneMT@--IJDFBmha-ki#CxP-{f6pPxh^jb5dI3dT5cH^tt`TX~7Hi%*w>C$6cyg z=nw91zqj16B)U>CT&;TVmnj`We%jMhj;?w1ZS|!|t^b-VPstw3_UhTTV}7SI$TbXe ztf$}IRH0@6D(LRgEJN?KOB)vPTrBoH+9f*stKP-ghM!j@Day#6iY-t*9ou{I&IwiX z@|YWwK|y_>TKaXL(x$V`N{@~vyB=1_t1UmT65+&+`ZW?Cj3Z+I=A%^M^IH&K7NH)N8r-va#3D)Ro>SzYa;G#;QH;R zZWL?~c2rpT)08!vWy`IUqeN$~TAn7<263ytn{|v6Ny3^Y;Njeax*KK1;oA%>V|R%P9_@{&vrjy_&?H`JT8Q|C z(rH$DM;w3ej1SUjNe^!jCb{_q-P5=Gkd(F zLOm0nwolc_J^e>p?2EO_$w#+xzMpF2t_6=8RGbf}tb4p({)PRA@cJ_T$C~diu8zw7 zq!x9`zw`T_u%u5LPP`6jfy~W4KQ}E~ES3AQ$VqEe!7Q_+X~G-4)YfdiwPM-Tg=;P? zadq){ox!EL%ju|=HP=yV#fvJtN~SnD_VcAF*Z*x*o-KdBL=>7p^lxPOyA>Q-;s{VBS#+DFbrO<%J9g~$7r=yp&Jt1!QOBWQC)?AaGrc2s69 zk?ZS>{5Dl6=G&B7)odxoY_Yd3N-nKagD=bt_ z32&UBCDt@C>Fk6RHWO#g4cxfmc-v;*+^w6vZ?0-P#XC!MTh_#NrjE|VRY_Y6?yEzR zmae|@oiB0HzgKh9=WRY}ll}B_*F~F$7MnyDH$}Qk49c;IJp0yA^|j5@ z-OGjN`!yn;=3Tiaw{pe%KX1pSNo6n=4JbPPQf(ibk?9e4Fu>p~Iu4t2Xv= z^RE5-?`K9#ZSy>O{A#d{*zaGziXO+zjumW+GU*f((h~dng4MU?`K^`P-reFZs{om} zCw#)BB-eShr|vD;GEFo8q+?O@iEOPUJO1B&74u}9_HL%6oN{ySFPk?`fVw>K@6xwF zA5GbwD5owiTC#Dbn!eiQTCK@%Gv#Dt)}*b^vf@flOGs!qW)-qf@k-PYl~djuSGcq5 z&zLk-+h^V09bXU0fJX}6>*l!a&Sq0t?jV`tQ+>tn#kMIwSI0Qsmdltwu`qe3@5Gm< zMD$aSx-VTFGYiyIXIP-rZJttMwAdkSvqPe**894$Oiz!t-EHmd=Z#jq;d{8#z{DgZ zJVI;MmTOBES5F1kTD}UIt((`(TlM*__xi55Eqo7`gSi9 zNb;Bp0y>tO-Xt2C+F?RkcZ@1;uXS~i&nt6PF z>7}H&c@h&`^b@CUo@>B!*kDbaxcRaOooDJ(_*A(jng`o1N($`nf3j*$*4gVVXEb6~ z{t~DKPexg!pE=a@Rjf&z`wEPf|`D59n1dcimsly`D)bjR1=^6;0e!58atLu zNSynyrnYTXdScZ1>m3~#VyZ4aQD=JebY68%jB)lp`*X{F?!bLB-o{-uxH8+e-W`+} z4^#^*cbPapE;Uv2b3{zjZu9b@=D9*g=dnFqAA91=luyei-MiE#k{@Qm_&x(X5`I7? za??J$E03QQR@Ob=Y0Q0lN96Igl%k@dw!43?&i!1awC26H>9g$YCWXZvm!5?sMa(#r zs$P_QIBSveSzgimfr~y}xgs*Naz^F3rO{o9E7aYJdC&TtjJjdnq1LK&<>=9D>F;~? zENBN6-Uq7X)m1BB^Z#03<;_ubTF^*4d!znWCat4NZ+5Z074dela8+F%YLa{@O1;Z1 zx9bFW`sqN-%b00$-PUz~j%J@*`e{xPe@h2ftCOko@)hiFFd1?)l z*LAJCYnC7Ldwy=qwHJMx_f4;{n_rmz;B=&qi-?%8SJ=|e>wdLv)_vpQa>OOq+weHJ zK(Tp{$8>A?qu1Vkw?9o6F8QtHI`8``6~~!kuDjQ3WIyeiqHCXi`edwHdR&RpWbh8! z1zKY3v(AVw&yDWZcMcYPWO#eBrg(W;hWeaE|7IOM{PnD+Xo0{4FU_ezj!`Q`RyUk! z4v8||w)FM%{%2PXtU1^0_1Sp$M9=oBB$MqIW-j^XdZK;jyQ#d~Rgg~g^N%b`BTnsp zKhaBKt5h9W zqr=GX)3=U|J1UA+D;QZCf*TqM+f2&YqMl{Ep64EaX^n}FAgA>CD<)b>iAS{pye0<8 zXoQ_v(;+&$KCimAJ4p6#=-h(JR~pCD$`V(oAOGCxwfU8X&FzmT&;H!#k$Kb z<$6}fm`Ah+txGxkN_T!K&+YlWb0GsW2IV>83oDPEIW_z6kGaitM!RnuT>8`BM(DJt zzGv*I{_9=ka$UbO<630F{x4p$N>*gvcr3Ec3zMxa-?4o65wYy9) zn9!}>wsYFi7pnP!vLH7%WM$^8Jt?|;)yu-!@mlhQQjRCC&p7jV)~*JPpy@p=M}3Z5 zykz~6S+H}%+@)7dm!$O_*D62#+ip$K^l5ylSxIG`?~UVguY13EwDHr?9B1z;F;K#0 zV3;Ad+)6M|WbuQqe{QnBkqLS7bL}JRV_{}0>d8mL%~iVmpFNrdzMbTN&WilLrj5%! zx}7x^TI*xn+ve(0Rx6!ftSNNbcHP>wsbWeCJq~PIEG#uGmg!cA+Ok`>c6qt$74Ms_ zd+o9PH#0%OY~7nDe@5;$C`_HRB=o+}8Rt@vzxLD@+BT@(?b3STeKPjZ%CL#cPutXE-hYmWbZzc>%lhm zA!%mIi&cDc{^)qM}EE-n6V=BND4p5#$tDu$)OW+#1ntc z`0>_6U-q=LlFOU+gTK$Vohpx-8nk`S@@sQU^YeK?YTs+Wiq_HzwwRorHEqt`D<+Z) zI2Zr*oxM%+^qovtcz?~_6zvlq|wje312r0~|e zlbi2-)4840ci~p)w>S@wTN)%aw=!D!Pn{p}^tE^A+d^xrz&)uKS`TU$cN?yXo%Wtj z7~GRMH!;N5=U?QF6-}?c7#-%3nwI!u%Daq+bz3uZ7pV#zShQeG5LdIU-qx$SukC|+ z=KHli`uC>mrm@>p_r1k8Tl!8caecDssAbH_Po`Y5D|_bULZ-9j{lhM$-COu|%jKy? z#bF@_C$GCX@1vk-%6oKc-8KfVd^_fEfT zB(`*`X$oiN+Rnw-T$02D)vjLLQSv0<@{@{pYuHQs7gxrauzyxd5v_?>`qy{fG`>2u=sqoDCu27`1jZoSRdRWii3Y1%H;IJRm@+)h8|rBlMse3jc28)8+Z z`P6O4#dEu#X8nBl0Thu8o1I?2de^Oc;Oyp8j)BJxEYZxEbLr+3`}9xemTq}`VP@yb zi?`01uAVjP_-CU)4L{Dzq%g0mOR}?@mK_TC`|)pUPFc+^F21#+ zJ6Zz`uX7Tr=UEf;o7iB8a8=iiWK67k}{jG=Z-<)GGe+6=}0sD*)wYgn# z^TLwoHxq@VtglHYr3OMp4Z27WD6Yr%?7c#!OOnUmZ{BJ3iiHhafL58d^ z51jeb_w_ATW>?4*wZzqPO=IId*p2zY4xTaZ2Cq@Ro=TpmW7l?pY0qqw(jGmMTz})< z{N(d9U6m#&<$rVvKa~5?H%0(FfnmU&^*ZRKkJi54#qyt14`}H=jR|!X6w>A8owRf9 zk8k?w*+F0ZPR=@LX=Z9_YU+Arwnpex!L8SB{yFlYX< z(RyZovTdu&mK~{Q=T84$XUhKT-sb;xll<5l*RJ_A%;jOwj6hc!(@y<=70{R)gcaoF2=C zcA2h_v-k2|7SFO=DQ)BI0PonynlIeR>)r&v5a*q5~t>yNL^dhtro-^l^wRI z#nq$rkdn`=DP5|2tZmQv-s%d{5#hQzC&+B}Yz@DwSC%%3tZtYp5qvH3Y(x;p#Sl=M zZP=N-MS1pixux|{3$|~xG|Dudn z!DsjXSXaE~^0BTND;LgPzc-ol=F_6I(oa`&Oj7lCE!4d%;r4BX!^WhblrLJM(Gw>K z_rKk;W>v732$$8AB**8=x~xPl8n212m}U-Ya5ETapV`#7^yp+;#?>{O9!f4hVWRTu z^qnKkw-$d)b9i)Z#p{F={fVom$lKq44<6H8&=PWXr@VGoU(lKhsNfyQ31scI2VGX=Nlm|iUlDGqCOQj9;~z(D*x-%@qb?}a_zn)H9c<6 zFSf9*86gQasYyK%7v~=5>Ri5bW%yJhF~MHHd4`i6F9zwHd9?S*{gv{}m~f6|>-F{f@4xUp zJxzDD+sRo|+rCa+Uz2)rlB&y;(@*U-yluSYBRgBCa`vx)Wr?c!Q9^>krdP|tKDVi< zt9xHIS5wjwIh<9dvgqT%q^ZiF@L)J)_-S&s(2^h_vB=J@6SGZss!l!m+R&%vU~tSr zrN_rUU3W3LVN*H%eO}D>sfQ!MTGABeS3keYnJgqEc=O8N#wn{xFKaGNx%kC0viS0b zGZM?bY%AT~d9Cc3=-Go2Kc%MqoVn*{#8T<(icRfPW7&gT7e?)hn0j{Agw<)_)u#@r zb7E3m)Vs6;=Iwj(CrCvpYI+sR-F^Eup7!0MWIj#uWnGomjNQHxGk3crn1UK(2i9nc z-E%aW=8_rc` z{LGpuMpe^pKRWAQW2-$&VWwrDy?XIA{r?^*eCcdy{?roh3(vCI=3zLMB3)}zPzrjP>4on-%H1sEVX>|sl>v7E!I68}K^7b!lT(z%-oanr} zS29#{%4^vYWpE|@UQTb#+2hO9D+0L>say%&zioHr;gYk>`zDz-w@tlaw7JdIB~d~z z^Y(@ryQc3ALCUbyPtQ%34i`(1bL z`rIYS^=qnoacx?8n4$b$?*$$jkxM7@XVwU8*8zpIK{@i!O3MBqucLS0n%PY8cI}Z# zyQ240tn^#)gS!*=FdIYGw#;C@X&8H=`|Mwx%Q?^ZXFBffic>dUdhJ*oMc_9?wz$oIFI z{?3K7`ka)kZtd=#ImIa0CC&B8T@KYQyT-10Yn&XPs~KDdk1Wh7^b+~`PD@|w^!4c{ z)b>p_mlUxUPtrUqe6w}i?71O#>Wz5lyjR7_95 zzp=(N9n|Y%Fp%|I;CBf}Zb;7g8dEL1n?2TFLKzOcm2e z>1#1b0k4ow@Z*_(ZaSxr%zyV#&G5^w!cLw$$d%gavO;xp%Iiz~=ilTPZU1=e`0@J| zKc0ltsoY(0+q^gRv+&WRi}H~=V#Tc|&#irI+B=E=`1h|i_J)RmXIVAHy2aQ332?t` zB-?duV%zh)*j*i$RM$%1mYxUFo;X$PZ879M{YX3V@bZc8K^|x* zK3d8&OLOMz;F-5e!{UYVYqlKxapA5Q zl8wQ`;70J5YuYJY)=N%pS+4c}r)b)`H}g)LX1|-ibMA$5*SQv@Io~_uCnkl>$-EXT z-v2rwsi??k_Sv+}H&34Ql=UfzHHo{eBV(X#XSM6^mzk48<0d;TEO!xBXt0lA#k`M=8zyiE zXV&WpPLI$ExaWD?*lz8P?(ba}E-mZcHQQW8CUmJ{(60IJE`R_2weJ77X+^Qj1}+ax zzpWQ8tzP~qdFLS!Vb4`==~5<|X|6tNM7W=RpHsPL?b6MA_tyUUE-KiTSbq9fXt$oN z-H&M*LcWWR%>QGWa?4z2U*WFJUo}Oz+}X=!{qFP96xAr=7QOW|y0Sd+%et*1MT*lj z!P(C;u{ZSIT$7@;O>qn>x{JyWE>Kln{YdQjL!*h@U5i_npZvAsh`rG5RDr(%dZ6O0 zA#&o}3yYase{AcLZL+(3bA4KQ79*5G8N*@7uj#{f$XWEdsnW z`9zj7t;?Rc%r)_`QtV|Xt)){Qg)9il6kQTBA@J|dzv{pFLL^VkJO4cYR?&XGQi-l> zx4wwZV$c)ZS#>uyG-_j8Tbp0+9?`S6L~bAD+S|G=IebmaO}kt1F8jdkk#nriYm7ck z5myo{<^I*kpC{;C@9W&h6mtTtwC;CbO-abYE*@`WkS@@Ia1bamh1*k2lr# zoX?u*yzq3`oxu5d{zsPHo?U&i(l0;%eRg}D-u`4)} z?~>NkuxII7haC^B6p@#zUABM!{#BEOR{Cy@+4|1!qS7pv>1sLNx6E>0?Ati2pj^qS zB+Gr9#VH@HgfuP9NS6{b-tLZbGTs_Jpnzo9e7H<-R{EJWf9mYDO8Ital#5@MJl)*y zp0x9k>PqjQ+vOk6ZLgCNpLyrv&+2B7j*9xiXC8L*cMDj~c5)I4I6Lj=_Mgwx@-3e& zX)`r6{P^vm`0rzV#=!y_OCvP7f*QRxdTlg%73#M1lGfB`A#SXiqDw*rRwx8$J^1+O zrE>bc6Hkk-&WT+Zup{MayL8qqACGB#zBQV6cl>MAS{tFPtbClk+@PCl#?->(jXQ%q zFPrD?dfPhZoqbyZcLqxZtObAInO%^uM)g zk%o-Dr9UZ|F@G1s>4!5dFNSK{3m5oqS-PfmgGq#oOIur8oc*U6K{6~y7+D$F9S<-X zZsxM!(3tw@z#ngRM=#dQFvgqpGAuPYe|Bo|M!L9I?Z~>TzGa$$%G#|NH@AKIwyo`H zXw=5O?=m)~yS!PuL^mca?Fjwy&EnbS{`*2(pKPkyB7XV@DDWP{Y-|katXQ+6@OEs+O)H?eOq=8}8!U@wSS1&*JTG7>|J0tSSj=b9MyonO?LJue{ znmBRd^s@gYTJ}Pv&jnXEM9%zDlH{89@Q_2HK*53|Up{Ikg&kve^$KiM|MuP1*vu^K zY-U^Hj>MB+yQ8na4sh|VKK$wRwfb#d+Si^udGhdIc;rOSqd{FazKHtGe<@detR^dd zokj6(b&xv_=ybN5sT|SV#DBwb#fi_+N6UNG=6LuW>sp`ZQJ48!%LEb~!pr%eb64(t zV92^m`+U_|*C&%y%i9toHr7vg^sjX7*NwsK-@or!GR5fIYJ~?Gx=wve%Of^+&GCC? zsd@Q``=Mur3#L4}_vT!1t^2AoRp*};g|Gd+x zSn-yt_gucL-rdCknK7_5ELbx`R$pl9lx067xhsEVDQ#Kzde%{0X>GF?Q=e<`@bd00 z{IIdtkxC^wJ`c~=fj7B()SKxrt5F- zcyep@HoFV=B66)Co;Y!0-n?|@le0Z^X7{H0HFlg^lqh)dN`*ziBc_rnP{-@R-u4c) z)e2_|eqX46wLH1fxuxT;LB;-?0YCj#2fdp1{mQJ(&))WeO8f_ZJr(uUzxjoJP**Kk zar58mmYZ|JOvUwoy6jY4m1K~yFrec118w(T_d>cXA1EA^nXyGvtxM<4#0jo0U27dr zuUB=Kl#z$p}hOT7QR`dvg8l3CVhuMSI)2 zIwM(2Y91}!w{Kt8xoyjqsm=8Zzwc*ZVX@=)mB|aA^u9R8xY;N&PNdsjH-6=DzgM4b zZg}pn@YG?5eGTc$ly2W}pQje8IRDD~Ki%n>k;*%#&wTnUKd*1{iqK6tJAHmsR%L^d zZ^i#h^=m9Dst*3OKepuRgv{I9{!CW8S=5f3{J^lXcFm)Sk_3FO2c3*jfSs9BDoH7wL zTG?>(^BQ+yO|4Gnlcfa~MmdI?gO)J8JGt-D?ed~F=ksBQl@`sLH_tYGUV^LE(Pu5q z4l}2GKf>v|JW;gh*OR<2!b}Vd3<-80Q&e-8DMtBQ3u_yvyNcSp?6P$Z`!dPMUu)Wj z?)k5y!6B@mv}p3~&o@u9zSJ(!7U}XRzx?a!-09&v10GzsaA9`)Jh|CYVO^1inP&f|*Y2}CQ82K~$Y!f}wg}jL^ESjbb}mgl)vC7r;F-&5?^M4`*D1Lf z@vb9H(fM&pdi`E!P^>omTr^?&VQaNR8=Ru5zq)F*?RD1|=sYp?w0(5yxhdCvy*SCd zyU$*jWz8D?Zjsduo*kVLhN?*}y)V6Lay@Qb-Vk#}(^zw<-}5-@i`51TR~i-<7Z>N| zzFlLo=H$tfhtauYgfpDH62sag=YsIzO+#0u4QXMImrGq(lM9TKDzj3 zyYxpBK&ly@ADU?XNqDiS$+B0| z)#t3-b>Y>w)wiXlg;tuc+rR(+SLgmsLC5T$y6-WbeNudC-^rX$8x~bY{yAWnJndiz z_m3Ah*0;5{-(CH(WY^lYx>LQ*dL7mh;d1Yjt$BNe-$Ef(X(LluqmkzOrJrX89#&d( z^5Ub5vKx{>@tEMa;hl!k?7ezQaXeurXZkDD^A$6<-wj^nl^v{|pYHYMjH<5g#y{ZR z?SVTd{azflR{OfAT#Sn|FzRaD_HUmPBSODAE!^<^L-z6C_surTicUx}`p$In&iTn6 z2RFsGCYk7bQ{Fs7=(N@E{?G$!Dokw3etenT>eM(>T1qM^I@)!~smUf8YyIch{5*ED zz38anQVR}`rBgQc7bZ;Ko>uL3Z>5TUkcNAi-&3`MYVfSy=Z?!ug!a~Q)}HM24*arv zX70~tTIS0)+UeLEIf|(2h95y&EaiUhL@)pO;_%s->U%0q9%o*+vS_+-`nf%YUp8j! zTGG)OsrfD4T_*a?`PQV)ost^Q5`S*87CcpaTz-C)-SpF2w{E?9?b@@?KedW?%k15| zcfI^y&;LgppZY{Fu57UEco(|MGdgqrCljtk8y_;Q0dLQkk$-1X^ONrkM$*4SPFAGu z=2(2ZZqsgU)kSwxbQU&g)}MNsl_{$k7q?vLtkyShJw7d#= z?RwfSXz%IFqg|r&|2=rWCUTSMr+KqaXbWD9Th>&;EfRF{ql(MK6QbV}J73qTOt(CL z+RD84&#U`Ud#ko~gh<|cdinC@&985)@9W=_r?jzYN{}WWQ|g*Hy{La{q{0-J_rE=L zs0-BgZ>T(;;l6J11((g;GfvJE-Z{zq|CtJPPsyiRpLR$8`SL9!sXl+Z%W_4?(F_Lj zWh#~TSHvb>?8=%OY@GaL*=+NFlW&&2TKnSOpQ--;e*c>|`TYK`kMACjQ;D4tl2G&F zSkF1HmKiQHW}Mk_CL=^r)s^h|ILi79PU@r!Rhk0#!f0%BKMaCUT(WtHFwLk zsMp($9i6}HoX zdFQk(xp%faS!UY3&WF9USZqVbisj3nyS(4Gx7OcCm|cq_V(A(GuzhV$-y8R~nOer# z>@w!p1~=%%8cqrGoYxn%?RBfJjMyf-;mNX3raH<#JC#{8+fw?!x`n>^Jiw|`EM^tIk&Rw z!m)MHuYz)mr)^whq?9Ppmbk)VZ`nuD*VAHFPElH9tn6O=v(tF7JJ(T7^BX>svy4jT z`mWBp%scn&YM<8P@bw)Y*>^8r4%QLdy=#|VRO#h&i~Ti^dKt2>VLIC7>B=m{1HNjsEl!zOR1V9gl^z0=I4=j5fXjSwkL zp7|^9zsB(?Cp#n09C;PDsB7Vhw145PZBx&`3jSTJy!W&C3h)H2z;U+ZsX^EOc4!N3-m$sJ|E-sW+e4-8 zcW@SC21Z1ZC1;`TQFwSf3uq|YcqHDZI{DagyS|pvvYm^?D?#R z0!mS@F9hj`akn}x4A2nk&Rcw~Y9F|MQg-jVa^=dFEn8gF1y)IKubXzlV!fA3qR_?3 znWj1yO$w~`zyJAX&m1{Ws5w|pTz4cTnyL2m)aqB$4rs15Suy3)b%`(66?@FJ+=8W3 zMU38GNNT?KSJ~D4uh=_Y(6H2lT5m;t>-jSzBxmeBr{vUmR~JhkHi+5(W7oH3O9PKJPnZz0GEwm2iG;fA!NIO8z=dUm!I4`F_jqWn zRPnQnx8CU}61`)>pXs^5iaXyfbDt=@+dA>|`D0F?OHUaX#5x|{`*7iP@Z`svqf;(; zSY2QD`;N^v;W&+=op&ZGyB|A#eD|(hMl+Xe)|r3){)Ufrmy~9?2xkfj|5Zr8xIyiB zcl-Sli{^s+0o=XO1sAL~oX`wl+by=x;`h|&w^uE&?EGXaAWw|`+JEc{OUsegsd!d0M= z(4dQtK=lQKLHrZ7Cu`N!+<$#uv^sFpi%(PMukhX)8o6it_VVlhuJg%Sec=<_+|y9{ z;YFTcW^OKTQ^K>4N)8Wc` z6?~abNN~|FpW9zo*EhR_2A35TeYzU!Z~yPt{V)A8>w|NHg)P(8tz2pOex&mJ zPFDAy_s)LX>gVFS{p=@Q@|8X7efedH>2JNf=;{|=PP5K6-EOS>x+b#t;fsX2^Phuj z-R~XUI}POE3h}`3aPtfI=ld=1d8)NgU(#K)xv%luStNLTEe(3*?Rd|~V3oL$@= z8U5aQDMear>$O&=jhnLtAp`U}CW~vWV!gkfb@Yu*ZJxw=Y**ILy>ok4uja9}sQU9k zKmK=^WBTz;&A+SSWF%|_#db`1T4Oi=WJ=J=m#Uk8Do;Pn%g6Wa%NLoKH+Qc8J~MW2 zf8X=pQx<(p%CD|+_AUeNj-$qhIef*V$PX`Fq;0Tg#R$TQ+Ulv{|!eRo3h8jLFN%$w^5`(K4^A%6WhB zVED1mwO$*!&O}+qJn1~ltiNSziJ7VC+^ta(ZLh^*cmMywT`SC9s&VGXqi3BiF3HZV z%GS%j+4e_(+uU=)_dNLaV&%8)z$T(SN~nE!uOUS4s{(r2dHg`)?g7o41~s=oO}C zKLtF9m9S9rN$T2TN^)zFYEQ|*O%p7p2$gTxpp(>nyrQi zSF2NEQPHFhHnl!JKRMYsHg+bZhmKgUXo#H1HA9rW%Tv;^x5K04+N>-O#Q zzxuXZo7?;PT6ui+j{i>$M8cvbCbC=iL6()%#C?G7`h*reeEJf#Mw2Svxkk zp6f~7-W_|#;Mw}3x9xF9tOWy49X%mDF=)-=*2W~w_v@5ES`Jh$o-o~9e)gjNpzB?; zmTlWIbN!Ogx2CJ@PW*Z|BmLA9+W-Lp z_O6)`uB*h{`6{IJt^V7O1APW(GDQVW{wPRXuzbVkk2!|% zXInvCD~1{VJq1rJSL|5CeERy5Ez>dlmrj=$dX@=92Mv5x>T%j8$5jKA)LsY|UqT&_`xNQc%~FB)%J|t+#%+si?Sg zol)uWXi?|-E8M#8UMKUiT?+m~MD-mjH>DCmgSMkUuHT~m@a6)x1XoO0q!_l%ARk0bld zCGP5qOgh2ze(j;hMr(T($7yQE8csIK?K$G(r5SeQ)SK7m?|KOOdfwmoFg!XsfA#9s z*1uCVMf9RepZ}XD{_EH8Dn2p(+~d1iK*?jrgc}Z8;{8vH?wtI!dC$hMysq_r5k)zc zx;lnx52M8WuO{uDSNcWBa0+->B}U?#-E`rF{c%o?M9a}LYtCe!I+6Nj z)1B7N))_9WSAr`x?#}=GYU=CNmCZY2-gQm={_p7J`m&_(t=B>0W(*H(1o*dTt@WD` zvGu}|4ArKMLe^?`!YB5K#@{u#bpFnQ6RP0GV!^`|l6N;G-kch$7hqvz^y$|>^)9R9 zT~m~d(pH>cKKk#irCQR`6X#}5NlMS=pHeihs_Vw5MJBb>ZS( z>pmM_GoQQ1c1^y#5!(7 zqQJ!zQ5Ab96FW6Ey`w^6Ue0r>M1}V&Jv~((<;n8XKUN=7O0+%-p8w~_sj1ppY*o`P z-@pI=(Yy9Ntc;P8+*6Ibf_@%3=3?y9->YxCDaLSfQrM}fMgJEqA>p6x`yc} z<7B0viGiovb_i>VNgok?=>K-cj26+A4w|mVH=pO@;|u%j=bG~Jl4^O)pX94NpoN7D z5ehL!nnWk|$iC7sHlKax!FGmC@1Gm}@7)%aU7fjFy=3Y)vx@?vp(dbI+VI)I+4=DE zcl-ByX@@NgxKaDz>SN|=(PDucS2;yjI|xqhOwi!>-eCUI#l@#u!H`pM_U%qHL+xMc zs^(MwudHPE0-|y6xJ3Bj@f)`>l zh%ue_aox7D-^N!FIY3P~FZjr{3=W&fnSD z*{fvkT)w=y_Wt>tW!9@3W_q%|(bw_#_@J#t(Y7sVVMgx346kF)R=yPOVbKp$nYZI; zAhR-O=gBVh`b|&$ci+kCF#9=oW~jq)?(<*1eGB_JEqLVv3_BcjqOSZs>3=6OHSEfhCr`Ai z<>hBtob6JU7n7Es<}KD6wDHuI)e-BMZq9D|=FXY_QReX*q06l=%AV|qO5^w5miDqi zmG?Anny~A6MSnTz>dLIFRkO-v+aA7^|LYNceNh%0s58T$BQS5xlCw+PUuXITraoJ< zqDeh=WBQ4%xS(gAM}_J>7T1DThcgsE;@|hNI&__%hl_i^eBI{{!N+)(Hcgr|HRsi2 zuATEQ-`^vgze(hFjNGq)LbInmUk!P+4G$(=Z#%JO2JS*FB@wOEkeii(nTChD?rFzATeZi_+EeAGF0)lSW~F*=QEKyT@8IOOTW6}rO6s6 zKmPAetNYWx@3Z*%$~joQto109?Vro@zkmN8Ud-yUWa-kU_s-WWn*~YKpSxyDs8;U>b$0ZT6?Ojf7YKh@wPABo@a=K z$Zbs3uJRP{30XI>@?b>go(d%)-<>B5K9s!sGI1sI?ajCAO)7KJH%4^0$ynF@nHnB< z_G!`8n0BXy1;5?xFI~70a2ApPe;(Gg_Ne1maNjQMUH(5uJn_p7|FZI>E?Z{ztA-dn z)%SXl1sSb;)T0P4fEhlYy1wt%)LXY^X|aF*_U+%BiSa6CuatP@c=`5=%(>-Sd%Wv# z?a$7QNrvgtUnYf>tWKObg+*s}eds;!7acm`^8%jc{o}mJQ_+_hk@s%u`BxhcI^AFS zX5-!9-Swth|GM8y&KK+Y`DAzXqm|2l|N6CRkI2f94^Q=LH$sb!&#f2xV%!&YrimK{ z>#G-aPOlc-$}9EtjF(pwPK|MGHYkwn0q)PsCnx0GdWsP zX_Gwu-V9XY_tvsp@6ll~|LV@18RuWE+_>Sp!^ZCcGiJ|tnFgBAd%VBq)4po^yEkrB zTw5*J_ORDH=KqPs`z@08W`Z&b!*fPs-y&hH`>s#z%bGQVmd)5HVw{zyV6{@~UayDC zlrH&@N1+kfvfa+$vM-`y-?yvlLuS75b8+vJseO1<{Jhng8H*baXFV{uYT|V|>Fy4V zGgn$)N=-evqNMlHmY}W^Y!fFfxAHAl*Pq$0s&wSk(Y%fG*SjXhJ^#FG!sVT7o~V5} z@bSZ$g^!K|Y@NJ1Jihwvuh;AD?kIFFnPxoc{PX>Pmg@i0|Npvv#U}6`q63z}m0^#6 zE?u21u@?u7iW|Mu_q?p~eK!nNfrGK@_NSoePSySFsP%j>`7d){eu|wsb86_+b(b`r1_zxATr^ct^I|nO6U*a0 z@_t7Sb~11@u`SW4wO<_;rcm(6g~g$L?cVPblOt>lRMj@VW^Hz}n|5WQ_N1+uVKHzV)ZY%zmja?^@N8)Qd&G%iP_c|NHw} zhVS^P?b~+z_*;H|=dZiv#l^+1ZS)x!7#x(A=rzMnM}-OzA!Pyx*kQpy;8ifp?&Xr$VPJXmZf@Ue)KbYu4!aUJjG}M zrSrMnI~*qeeRQ8qQt)${;cRE`kD5y+oL;=c#^scfrp<(<{~xMe>)|`M`GSn{qMw;j zT$^4_T=M7f{rG)9Hf`FZq_3ZUbYjoOFJHcd$5%cr-~YeXXdS4LeBe+i1(+I{!pLUYi%g&M)I(Aex<(^{QKc|ExK4Jie*g<}F*c?A#n%b6eZFCmt+ax-{0h zT+9>DuBZCDO3wd&?C!Gn_x7?puGQ3Bml6-|l*|lMH+dSCr_SqVKY7^RG$dyd0gw#*YQxgr?Nfsxrpo3ZuUyEsWBcJ z*ZI3nxp;q@sue17%5cqzWrE(x{hr0apwp3+Lc>B-jB*MKKc2e!eqHSTd2e1<&e?ir zU+v#xXOA8|>cTdC>NK_ARiJ}DSE?%os-%Z|uHE$H$D}Ryj89I~IHqox6yQ@*DZV`5 z?91?FTNf`)a=rIJ))llbcY;f&$SGca{`x;Bm(MOR?BA)s|5sH>Ny*VfZ*T9}1%{yD zRq{xE`)HlLbmk#F)rgNGx{n04_c^m{UbKo$GI>c*$THFY+(w%m7A|_xXz~TLtfWEL z)YSCr*_oS}nLG8aerJ)EliOGE@-|ELUQlw#VG86tvDin+v@1PC@}ufX{%IEv&o$h; zQB?kl>JcA8F9S5w=yyLz8p?XN>ey=T{W_U~_P zZH@o?%bfk&d+VYf1)iRTZfske)|3mpwvG5*qsYrUo!gRwi*QK zYCH;@#;kiYyh_4bODjdGPL1tj($SQAAcxt!ZEJ6rx2gE>z|nlthHL&yQm0N4>F?{y z`}&lDf#JaA16vL)P)%Cezd_Bzm2F0H#GXGB1S7RM-n#u=c<)hc)S3xBJ^E>DdO+3e z1fBQwAKK6Kd^xyqp@YJPtJgoNNXW_kyP97&`}KE!U;q5CTR}!n?lQqqYcfjVax{Zh~DuRFZKF6ZH$y6m(_h(H8D-~SK`O!CyPbz8E4m)gAx%aFc|z7 zoJeXprqt-xo1jvDN+@!Y_Wv`HQ4^&cCk1W%;dk-TU8CulcZya^g7PO=gTTZovZ`TP zDbw;IKkaJyRHrGjY{u+upAY^LUUi4ZTT9WT6>_2yNb#cyhrFct?K5v}@(c_-8TpGx z>8n?uh^C@|J~rRD#XPM+`|Le;u6?% zLwKTP%u(miM+<9uI6OP^-q}p`>I!x(`;>fjhPObMm-ED}N1vPll`zC*($#6Y98a*WDC7(kkjA85r+r)t zS6c6WQM$C_j#jPBsc-UOIt~VuIDkOC3@y$o%R(=TROMiJ$D=tJMoV)9a{!gDHpEph_ zKMc|c!W(1_m1VuMJdY-^E_X2!>vT-f(o*@EX?IIQvPVQzYuaJg1n<04t>-|cB1k=h zfUn5`Bcly26BnGzxO~p#*VHN7MU|f&nK5VA()=4sCrAi$%XE1}o;eo{Rt+MWI`j?Q zR%xY&yp(p6o2sNyqFYRwbigL6UJ8Z`Da z@6OnK?#w|=B_-Fur;i-x`KpQwo%-6m$mrsv+NEBitwlWAn=+4FiZ~+zY7~PsF;wj8 z^bqm1z4J6IvZ$uBr|-SW(OF*{W(eL+QaY#lX|;&!`(Dvfzpgd49w{Q`i;jYqc!M;$ z2s&zIiK$osnboUQiq=bXw=AgWTvVvDS-MfHmaS6Hu;cs8^jXuM{00?RAPXDb zx~n91{tK(wKSw$BU9al)BbT)KdPBK=C+h4w`#jwBvbOiJ>49fYxX3PEqy$;$4AOR{ zM?k3GymRj(&&Ah81J~r}e3o;)r|h~@5h2fYS*udlFB~$+$|YAr2taj(P-G)!!aq)Rl@d|NX(?&$)3&<6P3)H zr+4$dEvnY_?$^0zeA?sOtr@#vsh~lXkF6PLl*8IBPLru5UorJQ8TJEb-vnB zVOUxAnW?>NXF5EL8vMMLDJ|a6zvRQ@(o83#@P9L_GhbRiofoO}`cxjzrZcHh=`WYV zk_tnD+H}TOk-U7(+DAqCxYrWbm;c2@GlZ;7e2w`#0=+f# zBTsx^eMz!%dO1erqbjuB$jQ^@o69HXNw;=&e`W9Wa=tpJZfUs4rzbjsZ-S0yE?MMK z+y7(zQ^*NNAV*#7d847U^82of-(%M#WMqBxbF*ByC%!ABQ$=67C-vm6N9@`YBW6Wx zf>#L+YDq!UZrOR)c(P3Y;dk%s+><9mZB~2PPnvm3NHSR~GI*UwphxJ}&L=8*EZ|+p zAX^l=l8(&tSjQM5GSBYli7mSpD4CXsOHZ82C3)Fp#VH}y&8M|xySiNJHvE)G($HdI zV7S5e@7r?wljqMrzMXz<&hC<*pRUE7SNmcA@3Z}~9Wgb(|MJ`Ks{a1&*_`j1H7n<* zt*+g@{ncq928IOh!BAsuevLk|!qDH{^X1E1FR|F&@V9KY$OQ#ao{^svA{ zWY+Atvh!!iNJ;Jbzo5FLq-3=|C^gPY0M*%>!kC2mjU@Tc>fR2WclfCADwpryJ;J6> zY+q`Aa#OeCvdP+A%Uqq}YqGjdF)}kS+|bJ3|1~W(m-qg=*RTH{U0=6%>viT0GiCVP zi-VJki-R5O{uMFH@U@$pn(FJXU%2nxlg{+x>S}rS_Z7eW)f=F(rnow$o2nty&|%&&|zkWNf6aroQdNq=anNXUsmAe|!tF*t1o9a!&R4H+E%TJiNS4 zt?D~<>P*eI9~+r}e~s+_5XyE-GQX9#{z#x$=qUE+g>(be~Hxg zHSYiNRTC4Y-C@3WX?yJXV~>~%&M0dv%VQsFeWJZPqj~A}ocyZJ6g$w_k zxmoOC(5N0!8F@20fA7RcMJKI)v$MV1vhC}aFMa*}$8EHGSo=-9Wu4u8kf?x=wVYe|)1cDQH=bD61~F z)G622iKT3wUB!`IT*`Cr{)CKq90ILEtdM!~>u+V{&S`V^ZQ0WG>CFLeR&L8<@Mf9{ew zY*qj8(fRt1t3{I|Ho5o9{rxk2|E?<2OQNSAf86tX?{>inObiSSyozi6Jc@#*irf(5 zjO_9N527@Pt{1#=I3UPKyx+?(^oo4fR{o{h6a3dG$a6C=Y@4%cRcYxjrq)@@YJarb zw~2}WJiKa^*YutDxE`GRaOb3O+{&X@!{h6V{~bDN`X_N&=B@DM{_}0C>sC{_{`UOuU%vSH`rh4LKHq-J?YC!rug!~OxE<@}=H~3Yx8laFYjt0D zzrSYuaOvsk>*M!p%9)v)K6@Iqx&+ka2=jDVspeH*kj4LmF-piqTkC7qa^xKTC5Wahvxyp-fmq#6)ckEc3?hdtvlv_I& zM?QJN-h5Dh-=D0%#dW2>zI^#&az9Mu=}c$#>-M0%NH$MhCY-vo>~4kGrIuK)4UaUV zRK6Yyaxu_el{LZ8P0KYkDsz@wkVp6Vb2BVOc^DWHE?4fow`o(*zP%eZT)24C)8+2n zyT-=GHR+CZb$)*5rp3xT2z9KlRN7Vk{@m)Ciz!Z$EIsv|Qq|9k{hR3AMVRfDIO3&u}sj(jBWFz9?zT5f-y_QQ(LJ$)soHoV@xWy_Zh z-xpTQm_L7epfNM3qke)z@#7M$jo~($L0dey93me@9+Pvur(D{a-eYK;ube+8a89%Q zv7Q4nR%(hfFdTTMt*3YH)Tt-8g@uLtfBiZVym;|qXXnF}l{;OY`1-D0x9-)eU9AY#u1S*~ zojK#ve>`{lZSlhoTU%Q@KX(3WZ2b1EZ{o#^y;k8qs;a8JUrT@f{Am|I>-1ADeciL? z&&KaBe0=I^sEO41lP6cMTcx9=b>_s056hNW$?z#f#l*~+JA3w=Id9%e@2LL&@5Bj@ zOLxmWpg`kcKsb7Jh#@5af6&Xa_<>acb`O4yyD?C-K_Rfd#sx{!O9B&eo2<+n0w z!`i)vKjlPMTk|IiUhG@8>}$(LKKsvSJ|?^W_%{FFAJ6RQ*%hZAm&x1xIde|-?4RT% zI=W|PPkZ+D_usR=y$2IMyehxGZ*PsN4Bz^nMjaa3+OMBHd57`ai|h?oYPr>SHhI%i-4Vm)N zc!t@ZgVr~y=1rY8&1_fU#;H4ZT5in!IjQb@_4^QM!F4nKeOvzi=$-nvzj~j}y0HJ- zsnciA{u1JijV-tTaoBzJ?mMY^@54^N^|$|B6WX4C>-OGr`rfzJM)~f$jSdNapO-FmX)-mvdR2e_pGC*t#{JZo{`$ql z!@j+}|G(}2uCAtjt?bp_>Th#wKCZc&7hRZ=>3Oo+{@3d4>+9-Ee@SoK7k^Ez-#tgZ z?%9Qni`}RFE??8xc~Ug}^r=%-Z>LV@=H?c%sg8?#C%u0EuKf4&{O$hcl;r3fTzoCx zJMI;WuCDIc^XI$2FIBMrf3TT1yZ>tG_j`w&Cgl73`Q~2P(!cZg&$rWZr-OXXaBz-& z>fQ6^qOIn;Qm4HTwRbsn>5+7o$-;l}yJhZA`uMmqU$;(Gx)!v~sxvERh4@SR+S@1LKV$|`s>XPfL<-|6dPV*ghL&-vx~{r&CoS5G#7dVlNZ&z~<}&P*`y zaM64>rDVRos;aAZVz4HIB?*IF*`QgKdSLc1da#EQ6+xyLLVxppE&6qJ~_U!0O zCeu&PeC6ru|Go46yWij5o;`Q+--E;bV!iwBW>3g!@t$X0S@i$k-ab$s*Ms+Gd#Hby~l zVaK+=ewC#cvqz%7<`HOV=)74kM8E&ofA>z=&u@$j3=<@ISI$@=Ci1)Yk51+q!MsVQ z*`D_33UY7m**M$()RGlq_NglE-2veo3=GjrR&ET;xu4k^Yg)W~Yj69;jujghCORLA zu#wI_|1S3YT&siM&zw8E_0F!^el1P1JbLBImG^u9KHLB2 ze0^-F_u|9te35pU{Ji}2-|v3yJLh+r{pFM?Q)az-6>DAoVM_0(O`FQ^RedghU%%m( z^wmn6Jf&N^)B8ITTMv7Gm%mg0E;-+TG_=MTB|!ym6nudjbrayKh8^7CGmB<}cE zNAB*wuX`xs-<&yft;9@Df`ud)qYc+Awq@cjSx<@x3uioo>@bSkdDe3cV7M=&? z>il!_x+T|kEZ(%p>7T$kiQQFSZ_O-zp0qE|#l+aS_~oak+V^YA|J=C9{QG<7{^Yo- zk3St0E^Pf(=EQmH)^w{v-R=4E)>RQI&*s<^?x{~mV75*=kILic z<5T-8Wp=Hsa`*Pr+xZz79CVh6vgrzH*S45CY8f4nIsE8pd(Vj|#}!gv+pD_Ei<5O- zyJjvl6k}k>>78pm`{?@R)!*Oghu_+~Ws6FA*?rZmE%C!Od+;x?LM4tW(R)6Zhq5j{G%lZ28ksI~TzqKx} z`}+F+xie>kF8-^nzI^$zuw|^t_S?0uu5j+YyDszAeEWZ29{bxz=klDM{;c}#*6<^` zI=Z@lKc1Jb|Lgna#{8Vj%$Hxx)9rpeo`2LMG&H{U>C&F9_q=PO{{^Y*N$|w&6N(fu zQdNEGUjMau&z(CK?F~l}-uLOrOmUeY;@a62At)GG_w&@d5>L;)X3_jK{q?J?r>o{{UAbz_hu?o)zWj{ex976d`zxDX zzI>^_uV+d8&9~n`6O%;`&dHwLxwG!$heu2EZ{NBtZ1eKOix>O<{`=dS5D*%=-8%It zbJEGPU&E(N7rvN2|G(s2&ul3#;o*1RO&-YuD;-Uz_cywrJU|U7Hrg*yQZ2eg183==san z?$td$=KFEOnk`!v?z21h!?Z#s?p0`F&))wB+m)3kIyto;F8p+4^Z(oT|E^iNQLui= z(e1JK-o5?wmYIP;VDc0nSGPoYPeV=b%i4BELeGu9UlQ8;(6{#fPrr}nuT0yiq#0e* ztHi)?K<)O;J1X05TU&+ysl9Sf&@(P0FRRDc$dUWtgX{70;|@0#?Q)OHTX#3F-*`rc zmbUigOM4zYT$&%guA=MO&6`(mUfp_YamvDg7pvF%t$%w%xt+iBtwX}YFE8`2ne{JK zy#6qq@2KP+w*Hged$k%{TjT${y8d0h)PAf|NC+5m(@mFJHw4J z>c2(jT2{wh-m+EJ+r>P8>zcQ9-QC@vKYcoKm|I+bU9OxG7h7}sxq0IJ#YLMcS3Y*D z^oe_Qm8;ch|L?!Q~_J4l=f16(ad2+IQ|B3fZ7tAVmZ@&mG zK4gL-JRd7+`9^<>?_V@&^B2h_7p5wyro8lD`N#2$=981xt3j&?S6{z#MP%C1gxwdPr=%a1%-MYNNkgpr?^BiO zrzPd(r>{OA_BxDd%O-1mtK?66oi@{Q{$p6V@_KS!-n+}^?fx&X|2O^py4d)R zshcOydbM)>>e{zgr~m(K|L^$sxrGMeuPi6VwMpZ+q=ENOScbe{A z8EoyDd)L)iyRKu=if3Q6_qJR6pA*`DDx^?qrRbi0?tiWqc`-0F_)eHTd-n9%r?*d^ zHtn6towq;yvRD5Qm@#*5Xh_74XW0?YmtQ;J?7ueLDYWsM!Oq6v^`4X4j z1MFoj+Z=6citS z|JQRFIY~~o=0!T|6zuocE8jc*_Fqu6j;`+3JNqsd{q8&cbk*9G>sDy!YwGpoai(v- z{rdImSFc}JRm;z_tX@~2kl?+p>~n7S_G;uKw(g5z}V$8m6gdesnTyy`ijLsMx{Ez%bh_^y;o%Q6E3}WxrmYe-^sCKYw2TGwH1Fk?j+6KbGY$ z2DQN(o_40PcXot?PWiPm=-SkI6PB*h@;^Ok^Oh$oB`*JH42%rxitUQiT%;6e&x@~Bv!$h_ zrC#X<_UzhqYtf=Z{q}$N?A~47y{>R_4m^mD987k%Ih2x;V5l6h)FWBxX6PbuG0BIz zmer>(sdvk-j_NZH+WFV-KDt#xJEIW5%+_|&9y@hP{d~^KT zZ_JxLzu)-N$0vo=N6OADdz`&_gMi5GmGdgj9u?YtH~v-V%(-*-mi+v*|IhjVUr)#X zeRgl}?@#l~;?{p}zyJTL&6 z^2q6#0J`>mcJlK+*;T9lJD7Vti!JB+{Y=bw zY(h-Owy zQFB@Fj;{7qN1T632u^ymP~FwNDBpkMWck&{VwwWp%~KWHtD(it!@!^*DJA{-Xjydi z@mbF^^Sfnk-?*@0UAC9n>Gror3o2Hxd(zoHeU@R_yFaa$@6Qpf&M~{)t#7lxb@~*W zirt`QnlN}WxvS)mlCq1ditDBd(FGfIv-o|_J~%0}P)TX`l-{GD!SSA1YE6+#R!rk^ zVPI(J4G)T$Gj*n>oY|G@;o+fcbG3HP(@<94yJgFk?c2-uUZ2k5{mlRRw%i}w;c?Mt zg{&j^mtR($o5Y+X0E!Pqz4)Dz=FZ)^cxR`*j*gCozJC3uTYK}TZ?E2611cMis2>VF z7S-g_=kQTr>Y^2o6qBojrmb>oiY(%<@V?P)e^j_fRPgX5_wLKmo7b<~tH;1_K0F^xFA{1y`VUjDkH z?na-o07pk|xYsE+-`S74d`#`-JB*DSL4gs-#LYc7cH&hVZ?CS&wQgtk+z8m@?|%FF z+k1NVLA$#PH+UTBTJl9R(0+x)?M0QM;Q4ctzjG6g?DTjO-YY8L+unU(+MOxfb2l_HEdo}m^l-ys81^yoBCVcBuDQknbkI;X?gOPi^aaX|MC8 zFW=nE?9PtL?7zi%J8s^z>_2{ZyZMH`qRTzKy`690ypahFeLCaltfyYuFM9j>j!Mql zk^3dc-0X^c-7|sv|Gs^intyIiuYKLtW5<2;Gpnk89XfRA*gU6gJ9cPnGuPEGir#bg z_6txOMS)K+e$wsOi5DMreL17)y8gTIw-wNJ0liL#PMop1wY2M(^G^Of7L%vESqdIS zpQL51ym`fj0GmBmi>jTMpCg7tJm$asE#^T018Mtdkd++BxlwcIYaNDajENeU+yjOIlXJ$iR>@C3bgN zNBvAm`S~wizrH;ob9Z&svSrJDZd;^bU2b+3_WVN59@u=;#j>H=eFez4wnqR$2b_n)rNDmuO{kxrite zgTp3`E~Wa4?A+|z2TtC;b^BsN<{md+J6 zGjp+P|NiYuUP#yvv#OO(eHQK6bBFhQ!YPB}la?)CZeCW`{qbYr#7Q!0al zg=KakWloNu$lW_$pLd(J!J9M8#gpO5C3XLr$=k5gb9v|dxwcm92u2mGXu`$}TMMQJ5j#gB%i>9@;wY|Om!GpJ-!ZP*8 zPA>nRHKFhy9T>Rs4 z^T7pwF6{iJ9T^oRHEo~M6NOu=Y>HnvJZjz!?=nA{z~rU!Jf-u;B$+cp?H&I=X-tjS z8gNcUjCXU$V#S&z^QV;{O*2do(bUwODmwMi!?!9=_)Zjug@&&Cxj5(3iM228z7yH# za(C5|<;&%*t12GrWtHm1{0hrizO=Gm-g?)z%08RVK5lMp6+hl?pKiWQB};nmmHV~j zzB*CQzgERp{#@ES>nCWSY7cbtt zd|6xW-QCT*cV%6bG*3-UZC_F{d*8l)({4*gCVJg|wNy@0c543qh5Ozu6`vPhU%Wlm zy8PX(t-&@mKRyJ$KisY@ryBnJ>9ci9V}H%PX7=&=s?$%Sa+e&NJL%Ik>GkWseM7`c zlF&^5Jtxogn{!QoI?{Osd^uTJVgB;>_r5;f|8KRae#{DuQy&+*$Jf1N{kS|7OAAj1i=I-vYY15~wR;;=H`tR%gzY?o<`Cm4%)S23W=+9-ii7M7F(dg3B*YH@j zM5}hfGQ;Eol}9OgovLd6ExST8mpXetU3jOjyJJEhD+7b)#ObrO)64Em(rPdZ>%L;P zPr=?^U0vN%J!!f@o)EgnYw2ey8g>8(>V37_IKTn=J(xm#E;!bpI>iiW+wLkfN9+G zZ#l`Et|6`v#IXKC`u<+vjzi;y6YJaN6&(c5Fc+tz-`~Thh|Gs>9=n*=1S?2tj zUzJVzMfv$l>ch&yuHCb(4l6BtcjjjCqtl1eHrKwNyIts{<*LKgQ zywd4N0W#xB+q+LrO>R3CAM@V)Y1hRSGIMdL3R}njPtS8iMW-5aKl_j!fLC zbLTiE{yVTRFl-3yldDs+x1XQi-`6+Swp`Cseb%gbd09Cgo}Lf+w=P}Ee)sOh!(Lt8 zr@g#?e7ke!Pw(vQ*J_U4nl&qCaZP4Uj?ToSlkNR-qT=GIOO}6b*PFh2=gyPwzw5Jz zEnB`^w|TB#dTs38Vs(ER+fP1TUELkamM;f|$j_gZtjD}>UB3K##d`g7lI9=kc7FW$ z@#f8)t5$h^GqzjFm6VB!Jo#Nyb;m1k%AP%UYJY#5GIg4jOkaY* zjtytzGrJb0q^G~Xwe#^&@p;xI9~$ml&MGYY_}Jghdrw<=Qc}|YeS06-YU%4I_pq_C z>C}5ltqo6}J$v@%n>ngSkN#PBHZ412#rNOE&z>Gg{I{Ea z+S7$!-tO1sF*Lz`V(iGuS8?}PX#Ah0Bc9~zX`{y2?R}$xEAMW1oyyPk$sQKOjn)l!O zC^0)aI>`U}t!s5pJ{Z^RUbpYv>dW_S^3L{4Cd=3SxX8c%e_mjq;{C-MUa`5pvAMn) zBC}@9;9wCm@h!HR8<(F|RkiES`iS7*%m2Uq{+^ze*2H}i-+J^K}HQS)`$=dQ?^QsLK`sp1%HGb}^=d2^ocj7he`w#QOE$o;-K1 z=;q14E?l^v_(HA{@EO=y2kp7h?kw;zFOhxe6qw1e? z+?>l-c3ph2gq49|!^T%x*?05I?_V>~y(zypZ|fZ~QLB4buDp7+YTdfs+HzY@IxW1A z|L<+N{@x!>#gkX^@4fu;%<0q7?^e8fH_yKI&&fZ3Yy@>#wp;YLy1bQ@UA%bl`hA~@ z93A)FSh;G|{rQi-AJ={^BPsdw$K~_kqH&R%-+m1;KBgDH^U|eDMSpHweD*ADqZZTj zM@6DyVk$=d3IZ1O4>@O4>5zdb)X2>atC4pg!QGJ2F3QZr;6XY;HdN%4J`F|L=A+5n)lMm+u#N3^~Hu;)anSEQo|3|8G?cc_~zr*%$ zD@n=9?*4Um>$Kb3&5d32ZtuO)*xGu2|Bp{+c7FEl?d|RTy69N0YtKga{$KC5Y}>YN z>-wFcKQCRnw7&j#{`$SYifUu;79|%wJ{Ec8XwAo`;oslgt^am2xl+4zZ&K~@q!kE$=N4z$=K!oiaDT3Sf+B|8H{18+z~KtObKa74g_i4*5dnv}Hp=Anll z4mlMh6(toEta$xy@4hErl5c@#sz`Lw7M>FyS|=Yo72Js0~2d&Ya1IQ1Ct*w z0`I?h^TuuN_7xj8?A*C>$BvHuvlj+rBqk>2<<%8rtl0ee-QjkA;rXj}?AWnx+p+}; z_R6+*pBAlLwQI)?3we&7{@(BWJX^|3)Ly=5kS+!X zpQ5Izao^HkPE%Ei42<34a>vuqJhy*M)C!F*E%U=hN+}a>9a`}WvD!N*hQzUZw1pBzWOeZ1m>Qe*N z5XsWUi7vYP>@TUFe(}<;OK7E%i!NwG3|P;R zo7Vj}7?fWrciss!5DT`0A);f(l%?Cw3&jf^RNXhZyg0q6Nc8-wOZ_R!Hn|*|;dO0_ zc92L=XswcEC$}SF(eNUPjp~!K8AMx``x_dq)m!1gd-teY%2KCeCW5Orxg31+$*X;l z(nR?jyEcg~E?BfEaP`Z6{b*vbx-0tCY6gS-mgBbvtOMl<=JQu`c6pyX|&-z{_Z7S zuHc}it=d$-^sB_n-#5zxBCi5SMt*%dV=3BZQl69<72$0klP|l8~=An zKDT>*gLZj>bT+(o?$_3IIZ_cc<)UbJ#}Vh+w@#Hy9l`5K-%RA~E29mQ{CZBVjQ-UY%hhSP@xa24DM#PzfiK-w z==dR&yku38+thuDPXaZIPEA?0sz_bu;-gqSl_$oZGp2hT>3OUy8S}^|Xw&qj8boS3 zWWA%??DZL$IZ8@FBB6S6Pi}@3DK3n$*U%Eyy&1kLBv9k{2Bq0#?s6DV)a}W_+ zvZ<`_`utv##Oc$OLqw*gXLMfWbA>LvE9**$dinf zbfMzJlOK~h;!f_}cx2-$FQxBY8$CF>rfWzYH`*<@;!^sA=R(aD^DCESdhUyd>AO+q zA~fwq{?YHJErXujizxEe+56~1#MTQUCm-FesS7pPyD6nc@@kLI6+%CT!pz4*z<8Xhsw`fiA2+!KEukstHFNnqzxAgLV9pe8x)s=6C zD&6erFzJ{OgAwJEwf zx^tGJ$a?pd$@VEq&0Y4| z<_+R+w;bVW`4f4yCTQn_fc^=t)4W|`5#?ZNUPdaX-^7gzJ9xAveOh~lU90G@j!>db zU`R&GSr56CzL}sRCdc?@WTZR4{Hj%JZoJ|KiBtr2N*(aH)0K2&`kM9`yQ5xOhT6oQ zF0v53S$W56y+Md*=0+zuPG#lO+`XW1pBH3ld9&2?>g3?y@~GRwlIvH!I{3FbG<5H$ zyI+qUJ(?1KZ?dAg_3iiPKUM|HmhE1axiBCjt12y_Afv9Xj(79Vzn1^rya`F(mSA9F zX?fM$K!B_Dn!)VD4?lob3su?3^&fvcZ|2Os<^K;#J!52GXi%3(mU>wku|(sQQL@iz zKB?R_9UUiK8>g{yxmxSE2EKu8zepCifA7X_W(J0a+~k@XB^kcuziar~l_zcpDJz?H zHf{Ed88tOY5eEY@N=kCd%F0&jtFW~n4h)Z;`|fk*EHi6sb5X99U5~!)`24x(bJ5?u z{PMQ1Ui;UWEx#NYA3b^6v)HJpS##&kj*1Bhy*m4qrp}r3r$3k9+iP!UH}64++3d9o z_g#BjW-Y^4`Tx$HC?(K(@DD7)R~r`{@;|cRk<8I#-)ACgPbe!-I{M@)&s(=6-T%W4 zZyk+(mK0bC$^aj>TrkPasZr9uKL7Rkm#^g`3isHn&+ce*cbiZ)+2tc{Xjcsp*w!n|J&EHMaNv znl^3Pk>JXmJEw}KmYRm@Zg<{X+}ZY7%(?sU=Hi118WKEg&5HfUW21w&u99Y9U}#w0 zc%t^v&X6SMs2vw>J@v|CJ1-F&dbMJj=hx0_^CFc_pB7m<>73L{&iQ+GvobI=9KZA7 zgNESKCn@VKE_^5eO&<+>-cFJHdA_N{Es#!ZtZ zvHW-3xMatP$A$KK(>Zf54n#jo?q{ofyW@ZiUh zBX|DXnY2u`0#pv#OjSy4I3};}^KP2z@##9hmj=vG3fkpzbwLK(`cr2&Ec(4$nG>{) zpd+Iyttv6`;Otqi%632Q|MEOVyUWPRtgoKgyTx98w&Ax0yVaj<{`~p#~bwdl#yU*d-!w)g)^;**e(ii+V`{`*pn+3j6=QVa|X3SydTmV6YLx=i;s`$E-6 zNB$R?w6DXqgY)*C6E7qLpZ+R-#DDr^-5V_~`E*T9O>S=PLaX)c&%`@4RF7_b6e8Du zJa4iv20Hb2gO!_m*+j9W|Kmdzc)od1ztMx)hck4MRG>=M z$G>GSdu(=gpI>p}wJfNF=i%+2A|n1YCH?ysyO=y5FE6jCS>^%}GiJ{0v{bnJ{Pg+r zpO-GRl=-%F>C&G+54^bXC<0( zf3}k0I~Jj_#lq6m)WAR@BBDc1Cw}(vw|Y7{9^Ze?@ncWc5r~kGl$Dl{@%f{_;@i31 z504hiVeDEZ0BW75^P~so9t_CHvlB??x%}hNm5t*3Adf{Te_quTlwB6QyzJ8L2-ij7 zi!KHH`|YyIR-||1m*sDgS|oIfwjYTJnhdITD!f>m559aUIbZ+m^k=i@&Fr&md!F@i zk1n@spqBQj&!3AVlZ`iT4!*3o`|dmM&%bIiD|i08_O0(lk4pRDiSysB*3l0ZQ3aic z*nKcyNp(n~qhn=c=OT^G#l@Q+3-@RoeR}GQ$N5udB;@D6c(H4DOwgpKt5&Vn`k8wE z+}X2d&S`c%`nZGp)8|j0i>j;SzkWR)r+Oi6`}1FaL#ICV_P%uo1m>K6>f`JCwJLb? zCZnj^RzjB6f@^o=B~2&>rZv2Z35~2`8%8 zZ}wO>E#lyXE05;(*k~0hNb+v$NpiNGlses=`_sWkTmexW3=AKpNXyB7{dwunzc)`0 zMYy>>^!O5N6J=srxxfYEwj8tQ)XK=bb^AB&dzW@P_q4oHuL}f zrNevL*w{$xly~#NfN1yUckax&@xE;L>#S9qHyLT4KK=gQ{{4?+uU-vHPftC2?p*2J zz2@>APYhGjQbIyQr%a!!!DaiZTkzzmGamX{Ixk+)SWwb+RlI)Z3>BQpC&Ke*54V*ax%s#LxleoXJipi zm&e20O**fojgEyFc3-(RHzf4@Z`j`Aic`IPeY%-ZWo2P!>So2Qzy8*5=B#;qY|Yb_ z|M@p3rvBU^rw?V>(GFc=y1KfhcX!*Hna!K^N>k^=cA3zShz|>PZ{K}=*9$qpr_Y}Y zUc6iV{i%eQAS+Yj?X|hx4-4}0`tIf}-|?xac=P5>&z?Qc-@fgnp^nn58FTg&FV~gf zn?6mXIyiW7zpkEE&4s(S?F|&#?>%E~{B}-H>D1}3>nrEVxCYAbxu?0gImhN^dVYNI zBBI>?{jFu2;))9y1;2jf&pVL=YEB4ke3PJ3+|?n{I-RRaA$-YF(U(Zw1EHBQE=x4J zVr}}?DVfMS^MKp={@a%>UE2AvbIzPMXU?2?k!7)WQGtq^YoceNpy1v2?>O6&zcf}| zxIBC6)S1&?zke-1;rsb>XLCKy*H`%l2&!0bYrmy$ssyp*` z{@nS3vCzcyTKbaZr_C?jyC{11d3Nrm&6_rD-lVpCnVZ|iT6qQr1~a*SS;@cGDt$c9 zub8CG{`8I3MiIq&uh3A->eF{#$J&Q&mC0XH^m4QJ_2xyOov9b5D|~sL68%lP3pClh zWs8Yb8gFvt-neqFQ=mS2lG3v|2NMeN>h8S-*R=I#I%X7lbaZSoGETOue*dr8d-{64 z>uGT@p>Cz^@1H2N zyyJP6q-HpH@k7#)RXQiXEour36meUUF-vVxRK`a>1_lP<$&(ibXlNTBPTPFa(?{~< zOTYHyloB1Q&6;{+jhc8ZBB``$@b^DJa$ZjPKODf)Ejs#Scv z{L#Nws$Yt`JAIm)%jDpX>%1;+c{%gunln7>uV;I{=_=-$SGX<7GkMED#$cma=B8U$ zZQ8SK*Qu8Ude<}U1R)KQw9Q*fOBRBUtXFY=GhyPL`*WAvi&!Kt_VVrRulK?pMH7T`9Sq=b0E74qVPFDcQ5Zz+T&!{R9weW6*amhW0s zw9_)!R!(Wt?Htay!%wb+xIe#ps%z7!u1%XZO?n9eH&?EFIrCfn zbRFcpw8VbTwdAtAbx-|nzngnDb?MQ^!orNj-`BBdb_KC`HE|lyOTFE#4-r2eDr#%W$;`h#7-XM)MHg>x zkBHc_=TBS?MXXwtmYT-myzu17lP^A+&F<~kvvQ?j_0rjE)V>&7nVH!cK0JT&2-Hy66?Zl4Ov&%E1;{Q98hNjlVy=#6q z&-6?{Z0O91^XyD)HqEO6-A>jZ`tevq&%{L@+}x|Q`qNjgN;)!4DO;qgMl<>Ngr zbN=;vtKIK%D~bz!FSoU|x3{&6x_(?%Wo&$@_|MIwuC0|j|9$IQ_j1SHjbDCT@v6V~ z;^Mler==(7W>vLy?725psbS-ksneePDppfddw;in!^P{M&Syf>nm`RM2IaeVdU=nD z>zPEwzx-OiN{Tb>r0oOU+S^~n-q$Sou|8zI$0Ex;hQCkcs(}V$G7W5umT7d^yT7+P zXT6V~zyFAg441CZ#KRk3#RYaI_nbX*?u%Vj$=hFN@3q(RwJ+YcPOXkhbpNU;BH@2# z#%lU0Me*n!liy}`FC;%QbEW=S@pK-4?P$Y0V!HPF>vyauC@WjHceD1c^;)1RkL}W9 zFD^;d#-dYGD^@&@IH}FMYE_nq=&R}_`=g(LdhJ1#Ek0JJ#!`Dvr#}+ydI4J4!{Fkg zym)bsVZEQ2;LW$+dV0Rx+`02->MZlKXU+%(&bq!kFg;x4Xx?`B^>Qa{YrbS8C0%-0 zptHSC@p$ppOSK=JJh~PwS-LcHmf7Y%S#7T;PI{!Jr*-1gsSe{~FAD@NKJqf1Bo-MN zIaM^3oBQCkZ+$LO_ds3bHSCB{0+TXz!;U43oF;u*eI#RXN`Ru$)dIQWN%2hG%&U5x3 z-yBmGx@G51%VQB?X~&9En=>=xl(=+Q9{U`Uc>P*hVbQBqT{D)K?TkrHRqff>UVAdD zPc8z~6#cs6u4`+nA^VND-xeLJId-Fnb@s(Onwq>{x4K-pc2P1SQx>$5w4qmNtzX8e zokI10X9{on@FHWIQ&sEv$BJ1}uVeMDFW$%K?QrV(=g`nF5mB*- zv|p)&ags_~36$@TO(qkCxUor3d)IGOB z9jv#lhGte~^X5Cc}(eRq3zby`}PqC|-3(U&DvdsnVnb?(eL zzFw7C1uic9RaH4=rsmi8XQyBOQD9E&tYTufZdnWc6yNdf+`3t> zwCer7&AV%zp8i~{$+7jsM{&Z=+_T$Hohs&Ii*j@hr;E59%b#?RfL7TEx8;Zrn$jqN1BP%QIoxpZF zC-(b0{{Eh4PoFNU+$$;hvTISx^l53&pB+1<*4EZ8{3h+F#OpV^tW8YjfO;?9-o9TA z76oXSSeV?gH;{-}mihPCthuvy*KIyJfAZwXlc&y__3HD|%%0Y!g$EZtY&@tanB&C~ zUty?vbn2u>{q{vUHA$hMy_F0{)SW!t;>*(N!lIlmbl3?_T(rVXF>#4lK&a?3kwDXo zmbDVeT}7XsX#R7s(RJ$xZae(YK_TG!1q-unpZ0GBC1+6Z9Js6u8Ipfnc00%H-XgCl z?589ns%DpkPBq^AgJ;#Mjyu|ygm*l77ximnnR3$6`CT&lskw&t(&r^^O#>MK!W~Mc zdDrDX{Vm!wMK#+it8;1j7NaoT5SP{3m#UAw{=9n8gA1FA1lFfL5q=rIU=iZboip%r zL^iT0&Qy-s_)X)JoaU#a63J!v-0oQ{wqUo{nRH6E3A9NTWDf&F(}|j-9ue0g{cD~! z{+i%%zua}pWhG@@Z@Cmr8x^Ig%WGfqEBy>x_LTc5 zL1*9OV-Gxzc;=k4o;k6?)n!#jzTnJHYiDE_u0P*Y0_yXFG%<8Io|`Z9wOK^dJSE7v zEIVI2&{)HLo=ev>6Wx_=>blt-UFVM_Xa4b;R5%%|o`Hd3!(B<Q<1OZdhz?JRZBNctI0C~oe>9C-5?=x`9z0;WN6F9WS@hoJFTagv83+9=sJ_?>@%B~9@M-j6XDeg-9pq0NwRd!{*hdQWd23FeP&ZV7c^Jhus zX*E|@)%2If9apq3CU^&m$X!k9LD>WWR{p`osA!E#)RceqfsJY#oiCewZjjj8@@Z0Q z&3>)96U!^rT{}Yr7fk~#VF9au6sT0FtvuyOvcHPG%F4C7BkC`#FbO&PGQ7%F(f^## zLA}s9ZdzVfzIXhOg4_xO(j{>AM4!^6s`b*f_m6V5Efag6GDY~*@1-77Jw6#7ikP-W zyKaL}=h9A9@c1T314D|ETI$NTn~zL)Dd>Fv$sDF@ewFN1r0RwIhSt~j9fXv(6?okPN2c=J(m`) z@OZ*LyI-*l+=T(_>No^h#~o<6cuv5?V;VtnQPKG7 z4c5kRU)S zVd9){)%+Q&89Yr+PTIBS_4%w>Zb1q@@HNm%D}w|EpgfG@jlR4G{}(&zb`!Y;u18RCz4unR7vS$ zK>Y52xXggiP`UF$)k_XJTh3eRzPciCVT`Uu(EcaJg6EHW-Qxwd%0QYAlpX0Q(O9V} z+ATUq=wyTn+r*VCCOldGGh=azK~Ttw2tM&f-JP1^R*2zwlZyJF#( zmWt`zoIgRURD}#5|L|a&j##D&au@@{q7QuU7M-;+W?$aXfu;V}LY#(a7`z9fg@NJ0 zOHh^hwP1R5>dB9)MppYKi)3G7PISxZ?zEVGVttUvUh}XkmYSQsDNYQ$(;@aArcc0? zW#yXKJ73e4eQ!K{$|36dR5B`QtFz#lu2oVgJrn0D%?$fxY2qt9xvNC~p1yWvIXuzd zp1y*`M9#=^pUR@}qI{jgHLE6_*qfvy)bvQT>)6IKc`U2GNIuzlMB!fgyv(Rc@5Ny@ zZj+zbqWUZP$v3ycXGjk?rJ(KEUkBZ@ zU!B(Z$$8~bYr%=9F7NxoKCwpo@~74$Q2P?%%9$5$&b5DZwEodakFu#A+mw_b)z8U0 zLf$@dk-r0`-p)SxGwfNZKqutXN3bq|<~jDNuh=z%@=h#idvonx*rK$6KATPv-OQ+< zUcabo0;2PKk6-#RRpqf7ER7`WHkJx9^cG$C;+)>wC;T%{EO>PO6z>C9Yu$}ZiuGZp z^F#D3t|+HWd@2+O+UX3ohM{n#bW~(ha7vDbQghdm8tu=GU3Uz+T_n6kM5PjqC$Y~= zhS%{7MuE%{oza0kKPG(@C=S=QUEZ}kJCaZRp0s!1m%Xd9GS{fim+l44)_{#xU^`}F zq~zfyn)pQ`xWMyWpDJ&nOV=HqI6bp1r{8YXvE5X0UPsw7JNX?KSUm#+!#tHmRskVD zIzzc1gQqVV!kxQC*J$rHJYh6FbI#KFpworG<~PiYVOx>z+xcTk>RHFrppz3jT=|dAStPmV zlys)2`zz^7ov@H(cr@`4#?gr;H-bc3-M304Yt;)Bb5(x&dJpbyn~6O#+VJ7?3npi6 z6x?(d?nzO+zuqhTN$fq(K&8-@6{?^P638hH6;nL!oZ?XZ2wFbine|%ln!L&A;fbS% zCypMT2+AD{!}##Tq=K6lZ3IESe4v@uGNEFR=NnOfslDqul2Vgren;y1%yW6F;CgF+ z_Y)mEHg3@V37@V16a=^OEXnx_I%k)G;eZ(Frzt8#_114ZwtvUfa7aNHefY(jbMhY_ z*?&w?+3lqgEjST*J@lH|jOo8~kZUG^=F{i0iX`uIw0+D6-}=bluU!0ZN~!(*5Rs|* z5sSkA2xxkD=WASQ`BfjP+>pu}`0;RsPH+6lw)=_<3^t4vt_$}-Z1$I4tSGuUM6m1K zn@fKGCUo*>{abT~A#Tg%Ny!l|OJ@0NiOYQI^@vnjxK4oKLFU%|Dgm=3yZ(k`p4gNa zI7{+YypYGWsbG^1BpR6)4AW?Wn`FF6ka`d=}bo@FaL$tXF0jAc6$Ea z^856eVj6eiw@L75D>bO{#TZ+&Yu2vZcKfZ%l{&6PeHXwK#aO>+5fT_iM^~ z*3x!AAOD;x9~>0lu3Pf+)zvK~>#x7wTdThFd+U6428ItUojPtOPOMP9V!c~hwC07;reFL>79#qwzJ_EEQq9OO;AKUbj7g|ucu->X{q0RF(7oR0(v#aSwCz`}KP)zD?%cnJ<^OL1mlYdoPugzyGGofp=xHm&dR{G3edO1* zGt*jrjs3z?XE!VnI^iJw<4Gn?V`Pb5TuPd+9@{IqPz2VtzfouQ0xZ>8Ae_t1S^=fC`UzM+aeg9Oi z+OXlngGT0FUS7HF)n}K3&XkNp99%j@_0bXLz@E-2TDCL0d#=6x!?}A-W@=yEOtt$R zw;354a`QtuBeT7a7VZ49xanZRm(80uZx+{&`&6~p#^}?n)$2`6%{t;6+4>vu2n&z)gss_{>CJ^KBAZF|SQzu&yd{K^6Y75{&@ zd8ugk&XtA}H|wZR+^p}u4>Y|I8anm*>{IJiM7Zu|=Kek{9`7dqv~YKP?boM^7A+E) z9(PfatM%8fU-m!We7<=zQpu|1!-37m`voudN^k%7DK(`nyuRfxMyoBFYdz~n>9%d#b_U`kS&_xh%$ zruqB6D=TH?zyI-gzJ1)`uR7_;`#;UMEcx(b<6@VRe}|TGi|d~XmbEE(aAfoGju&@+ zc8lxBPMYuaM{ioStWdq`^x)Xozk9deS6P(5f3K0H>DK!H_j`|5SVQ|2&~Ne$QX8-xm}Vq;qa*=B*PaUMxL5y;3T+ z$sTmt`?i@UcD1N@v1*2uO}Vi!b5=;Hhha8nZ{A14E-u%i>2-E#Izcn`RI@NNlz9aYQ4|SuOGXUT8J9y6k+hd3F>x2`^2?Edf&VUlulsUwzTLa` z@87?8VN>>{<80dJ=g&?Y?&9M9saaH9{Pb@tD{IaF=6CZ%^Ji-7X(=tbdGqG9+vR^O z|J{k%fBEH|{rT@-=AT>hU+#5Qc6`M@%Xzz1)IR<$j;s8+^o2p>obqYfy1KPrpNd~T z>woiY+5Y?gugzW`zpv=)pH>eEkI>M+{@N?Kf3I4XZYlkHs{Xp*(6#YPSFMtNU2x;+ z-_^UiXRJTGD(>Xd8$C0PjV^tEcUL#P<)i-N`Fp-Ewy*iJ{NY5w!imy9|J}+trY*U1 zz01DkKh8aR^yqqArKYm-;ZIRdpFZ99@z!d&?Z1EZ&VK!~l8J%g!w;kNS{hr^%uBP> zmCuRBW@_jcDj(hElC1MrbGL+|TlXDZ!|5Ut%nS|7yHB6X`g`#2(uH@ngv!sJ=XCzM zu3h|g3mfO~>bY~3*CkXuJ)b!_I9OPCa%AL8zV^pg!{f5@vfk{fe*ddi+K@edZ`t1E z+s)0*%kST_b-8lu+P%w{on4%r57#*O`hMM4TP@-m85Q;F#hX{}--m~8-LhrNmL)e{ zmQ0&E^<73@mf`mm=REx5qoQ8DthF#Q+O%bhiG_)cwYBtrozszrZ%z*mi<07My=84B zZ&&lA#40;`mAALIi0jI=Yj+kseRbl+3W>@$CldcvRu>g*TKe?dg%1UBare&2o_+b! zZvOf5Hzyw6|M%|uG7F=-rUyqto$dZZ8vY;{LL?? zQnYn<`P)xbdtI(vw|8*4zApa$-s^Pw!yD`G-#d3s@8_F~ z*UD_gq<>G{&-QwM_t*WCHvRf#rBwB0#ruDM**`b_Y-(z1`(?HK^30htE5E#W$Zz-O zgppn4`+TMQ!8K1lE_Scr$+i>7$j+6Pl-1SH(9qHO@chY*oNbSf_ubq5UqSM{ECa)V zjPLoGc@6+Dv@%?=Slzsdul+uivZt+`DU6 zlxrXtH@9wk#;k8&U*@li-LLq*r+(VgH4opMzG(8cTYtaU>gBQf3m-3k|98iR4F_Hp zOqn*Vi~r$SUtd?(Ru>aHyN~Cx%8hR1H* zy49Icl$BLcv1G#r1$Fh^D^{#nzdqmg`;PSQ@9xCdgC=SB{eS4*+}vFAe|z}4KQGqT z&6q!5{JCjQU3&T3JAok)9xlel#{294J5PLE{P5Az_xpeQg{Ce&{nV=N&5Pgi{}Oj* zUazseX!b$dUh$Io_h0Xm{;p5i@~!V&e^1-%?NNF56&L>g%3g0F)7SOs(+mA2Dtq^L z*89J`b1^0+#>J($__O?F8VtIOX1dUoa}FQ|>iAZP9K zr9?e=N@wR*?vqnoRHgR5#$1S{*quIm@|5OY^&%;h=mWacU>g@&F! zeY)etzgpY%t5$7tx;JC)+_^Jms4RN4$Z6mHjT1VGC=Q8jA6rTOJeB;0HOG*L}KTiGWy?pcP)ytQ?UCMUvHCy$# zdeXi7NA@q*($?;|z9F{HQt0B#{B!r}FZ_MrSbpYMIs*fPKa1-Xo~|>RO80JdEy20c zEAHimAlD4&R*-pWy3Cro%$lz?wM4=~Lr&b?TmJst-s-1MpZ4;8-C0-f=4O>YF?sXN zuI}!8wa?d{xBI_n?cUnZ=@)NYm@w^G>CPCv>8D?oyxPyW_}4`rU*Gjvw|Z@V7cE<`{#cr z_V)DXu{7Vj8EI*Gv&P=vm9u@ij^VPWZ|-mJ-yd1~cVfy+?eP898|vp@eyO9Y8TZ_F zS(S~;lFX=*#Y=aWzxVU?O;1ZZGROXz_3T-*PNnazco}^S<9$Eou>zTQ9jE8esF;lqb7=EZz}cYpo5bxMm&=6`h$f`sr758un@=I&3J`NXl@ zy#EOk1B1=Mp1wCOOC%&Cs@$f=SY||K23!%9db?5SW^~aOFPZGvl>sI99%V~aW{K0Lp$l6BXu#}T>R<&ov(<=a2reE*=4`D*CY)>hV4tE}dpOLp&9 z`H{G93g)|EM*+c)Rvgwn+bG0+HBN$;`P@w&;q0Phue*fH}~>>ja$Ec(Vjn!<>vV_Of4-nqf(EC z2L_%qugSFA*CMlh%M!tf=bvY1i1UPiW3p#(E`xLHo zF2^Nh`)${kPub%9Wu!k%-LC~H`^Acji!WNUvwiU~lq;XC`V!QpJ~dhDJ?J(jf17#9 zszDo{=x9|&^Qi6B3kaOzp(U!XK81^C?bVKDqFGD0-0ZrObm}E4#TXdo`2{n6edSzk zux8J-DKFHweEvR1d)q;;J5RO4_2PGK%71@vvU=a`oNZ^$^jO4BYmq(ctH1Y0)7iAg z{D&VFXozsNAMWl>ym-#0a@&J9$K-hpof%~QzwmSU%glWAsOw5O|H8t;OwWyX^Z0f3 z?(L}57U8n}f5)@`cyM&|`K|b0;^^4u@mMQT?c=J23+>V*xRau8hyR=G z_3!v~U#rwd_k*96f^HL-XSC7Tt*E|yQeAU*UBr^@`PZwXJJXLQ$juO%e8cs1h228L zJ%j#R7l*DsVPp{{8s#jpdclGNkIS-WiEUQ(9{?yF;W$#88{k1>J-rqWzUs;xyrF#zit0^NBq~$JouVXmy4VG$FVn`9GCX)U3Fyt@@LPU8ygwT@mqfU?L70Q zqoBfvccM~`XlQoxEnDoi2e^)&Jd44@FUoT~!-tPK0DJb{aE7$ery&YoW z;`V>P6mPsDD|q$l)wPygBDK?=syu%4@nehN?6cdlpP$nXUw=&A#>B+L)^_g1i4$i( ze{OrlHUIs-eg8IHx^!mEnn#b4lxFd>2jTDo-U{r&$RUbryf=}q~X|94My zeVQ_5igNq>odq8+Y32Kw+nf8ltXd^!`RB~b{BtM#L&HLT)a(mAdo12CG!)dGIdil4 zQ}DkzGI51FH*DCz2@be}3*-tq`Pe?b3RJpmAF%Gf-nIW;QBR)z+8eiiscl$ls_Ok2 zGdGq6d0z@u{by@xzIy)a6B7@|*ZiFNC#10O<2~Emof!!U7mPd~+50mvFvu0}F%(Na z(#>)*qx|UqlEAAT%-S2>7XB!9xgycEMHhVE;upi3T_gmeqLC2aPN>Z}Y-F=CIfy)i+mu|Fq zBxUpB+I0OVz89V@?~|!hv-+8_^yaRg+Sjh!cyQiu@8&0K!tLom#`(C`zgu( zx1wJ7-@I45s{8d{M#P7oe!TzC=jDD^u3x=&{pzQ*4_o>`qb&^mx{D3P;#)6VnH#I4 zzCxnsqt9iR7g|MY=G;hKY4T+6Mv;m4Rp&a-iHqMgVPohT30?*U{~1#C0e(kkMJ@RJ zeUAHTr;p{!mIw6O-!K(g+>vRyHuo*>*HXRd+UnN7)$RYiKDTZ+zg!7FAK$boQ?6XQ z77`lvV!jP~yPBHX4@KtYsv|1)`tN(M$5;ROkXZkp;e6e!nKKJ_2fr!%eOiBC!S{Q6 z-_5%>Y0;u*&yJlrbLQ$krowZZ=J487H|5>gbMwxXh=_;@^XC1VEdPJS({FG0{cCLc zv**#GMO|G*u7P6W;?Ya@teQ9P-mO_u`+{zN`BIXfuYcd(*4Eb0^5OZD53i>DWoGW2 zvv=jf#{YqrZhtm-))1|$d%REXTh-p3|6=O>{QiXJTY@?eI~UJf{_4*I_V?SiZR6$d zPf1I=a_!0*MWuqr&(#tq4YSW4h6FQm>K8P$9 z^PjX1)b0QM`}gx_&w_((BO_U_xA+o_%Ybm*z@HbH^yEHa2#Z`qz7Z z*&7ekBsw}eJKM%@e@yCF7rX!CBkuDzbGF@ysn1*Y|HQ-eABxJ#$}eBO^jmKH zk-NKi+S8l|H-*dp9XdKazV71mY18Jtvo8D6@#o5=OP9*;$4>veWZnH8Ki_;zwpnLr zl=O?k*2Lt@=5Q0=?A%=MCs+2UDV1_lP3 za}g>@t|>=0SCol(Y6kDA3COEeEiaz_d*5V3tF*v{5(j&(=)cx7I3uDD>g#)FrmZlU z{MAoG{(j-V`_F3@-3`6ILeoxFZX3^%Klh*4yuV-a)lXyT%rz#(rAu3{=idR{XZh*3|^uc`et+xYpKPW8u+e`()LUXoN8TmE&?+LbF;x-8(;sVOIPg3IQ#v^wR`{mvDZsTN%2X?J~{mG!-*F!)aUZ z=-%q@%?B6UIH~^U@q9bG^u8GxvyLsgw>vb}Uq<@JRDYNIb1bW$o+|(3d-nYK@{*E! zd#(z7eghwv5$)~opTEDLFe@v{_}Yng*pwgNL*nD_|NnD+ zetGHL*a_#3N=Qpe{{5pLAG0s%RoB*AkOI?k%wZ@=eoMOx@XS&pZ6%YklDO>v#_wRt?k~)K_Mp& zJ^#FP`SR7PZe6~dT)Aq;4h#M3@*Fx_wy92u5OJTgStp(O{64LxPoMsqGsi*U!u9+4 zob@)6bNte4V|6E9x_5Eoqfp)uqo%yoh>aXS@$+cX#c8Lt5%io z|86E&T2l7+;bMC?evd!ZAV=Bj>r2GEcv&lY( z28J8^Hf=JpzJ1$PZu_cR6@Jq^&M7Hf?2WZksaoo^vM!)k^tqDKQ9b=_I>$Fi7=LY< zE@r~Qz|iqRrf{#D;=YYnuQM@haQprJZFXMPnRDlql#bnSNIDJLm)PLwvdH6Ioa)w7 zmtM0kmP+V6s3f%1!%)Lj=BWC1Z`lXRnNdnbsz$p-S}#13Wnfsudf4mwhC}Atenl}b zTwAeWgM#_>^V{X^s;(6MK6fpSpMl}PHf1NzOTU^wZN4Pbbg8JNYf;xxw$6^@YePa4 zeFW#O@7W-l?6Wag<+9iR9}6>Qr3UR?Jgw=xIs=1%^YxD8)%uJK^8}1HgR-*V#TPf0 zecLo+?o3%p$(j5tzkdA+zugO(t+cqf;S^+xc<#y5oL$MGQ!)$%GRUPrcGmNbnwmn`(yGASuqBNYv)tbPe7JcR#<%$d!M&`wt2bvbY8bd zVW;0tDcA~NhK3sghrvtJDyk$ERa_@N_Wo4V zG;!MNi#H>l*)EfqrXl>~`G(K$KB{Q3YfhSWbn`Y3{>+IxSAi#p89@6#C!y{c54sOu z?W&@lRjB3vmC%0iPfBgGj`bWY`ncf629{-CUWV-4J8e$Bs#S{QW(8UJ>Z_y)pO?G* zRd7AUJ9EX)?svJWS!_>FOunM4J!!?#Pr72Fiym$M7$LQPQpz0_kh4HIr`*k1D{ZCH zle?QlTqnZTx-RWm>oL0A2oydH4b)n0RAzbkl+0fv-+hAHnHd;XfB2a`Kj*6|sLm9N ztNM9$?LJVRJ$+(hQct?y%w3yLAK~-8T(RI(hnHdIT4$qA+dKk8cB%zVJ$K^B&m%f$ zi;%pyyeBT2@Mpr3ZSRu)Iw~hEoppKrmoBGyb5xt+S6TFiOj+?>@c-61pj*Sio>G`K zQPx%EYn=J7ech08Sq=3m-@PYl33-NElUF3Ti(15LUvPMq5zqRiYa`Lw0WX`*-yr z9c6MwKCaWGp&xv~9aufXgNN#YDjq@R<;pIuDRBuGCM`WW;{}Vnrt1{tkRzKnJ~0)v zv|H}+;!<bQ#=vm9T`oMRqvPWejm6qxf}QQZZnb{$YF@SKQ^m9!%A#_o zKI+&;9qs0Nn&mk0m+Jh^3cIjRc@i+q+mzFmID6`@j9BwvipMb}!ww(URu%iR?$WBw z6BjuhEduRO^4)ns5?=N!>ST*>W1FTSbVV}v)=ZE6lRj-rIxCzn2z*pM<`Md|N2~VmiN!%rrf7zSKJ|-ObaZ!&$BFc37xkugNFH}L+Hqv& zk`#Sb@ZIrX#|gBS7l`Lxn`vp`>as**RgBGv%`2ZcIqj?q2vLjLv_53zqJX|cSF_#- zsqUGNKzrA~y8O)rJC#PVP(&o$B&VG0+Uuv0hz|!*y=T+H0+I{x9 zJgH_sOy7pT9V$8(?{~eQUcBVY-i=SDMN}PKxG`&?=A@(BfBspOQI&e~htVp@nJbb* zAeXX(H8#u?bb9nrZDY7i=9gVcT~m8g?=3!2z2t;=a?j05=}Mug%_5oq^(JlpA)$k~ z@mNghbEjdDh@kzYWUrL0ZRdJQbob4d?3SK%$Jl#{yqE61&W@0I-Qx+FbO+b4iBhp5X?bv!1NpsLq1|WMF zZqL0qp(}C~hiiFRrh5Ge7dFxQusjC+TbZ4r96vX&`nja&;6gdYZk_2JyFi&AN4|=y%xZx4DL&%SupJ5Y=y8|IKRsamWgzHfHm% zFR?Z&<4fb#fB*U1Z)xS;?eFjGEc|>eES`^n!G_mIo2ScTn#`rHtUYp)34Mu%u7N*4 zHBbBGXzl;~k~R=H~*JZfUXezgfR_rJ_>*?adqIe@{05{A=&WU)hl}XS$U9J9M=A`}_Pu zlBZ9f_VVhQEPgEN?drX4uUD>Kdv||+ewEuUYt^G^n_CY*{OOR8QSjoTwI+Ro)g#X+I4I4c{zW7|LNsb!NGf1uKfA4^5{|5^mB8v zbF;mVtyEm8b?P*~+zo%wNqOe^s)jtf8jXyNv$I#dEwdIhH8;=olgQp({d=u>_Nvt( zrk}#s+|B#Gbm`AamrkAX(vR6w^7B;a$17!jR#n`|y%zr-G%MBcMPSMzjTDxNGddiP zT6P_ubw)F4qPv?)_sP|gw|YCo|F2Kl(!Kr6(M6v?x2<MuxC3zi<^DBvSHEb@O4$e!L}>s-QNCw&BG6G z-n`kgDM(35PVVN7nUmAs&%66)^~8>@Zm#X$lFYn<;@?h>t7%-$BzW=2ks~Kwtk|~X z>60fZDJeJJnk~Ov`Q(Ff@a4<0vU6*E=B)2Zsm|H|>e|asS663d#;w0z{oAkTeKz-f zYX*jjnvQzghggnTIr+77T9xze!X27kszy7`oK^*$Av_^G;6!ue$GLxvE;_07-`<=5 zUQW(*#=Lp|9<9Dy{{Eim`LHR|_y0KbSyJ+4+3wu$?_#${@55HODyhuo5!owvB9yvEWp#|NQgn*S*)dxw+@~ zJ>O?r?IMxQZM!YL^tFk#_3w83f0?V-GchpCGb`fPu~kcbIZbsH>*8G*ojWEc<=r~R z{@Q;3=9INPYR!3wrrWu#UDqG=-2;^wrq2C;or5p{^#raJ$=1` z6OX^OEBq5NXXT!__wQnNuUfrY*fQVK^W;Hh_EV=%3rofX1QdKY(0Hn=%Z2Uul=<`b zr+;7f_xHD{Q>Nsclgym@eTUi6qet1ly}!RVJ3KBf&gfbE)z=s9T-j26{aoq1jeGXk zSZjB8R8>_^pEj*y#Wu5r>ouZIUwv0(HMcW9IyU#MaXa6%Y17>7LjwX7cG;~xE49u& zCNyhRd&jY3$Dc}wNg6JOEsy$nOK3ZE&C=>$oi3hr^}_!%10o_SJ{)K~*2dOfIsBz|b(&a_+fXx1>O8 z!*-Y1rY*br=FOX_+Trn)KUG}=SFK)MV<#^khIO&cysM(%RYm{*d{qD3*pO=0fBWyN z)%xP1qDyzg)bPvyIhj8H{JC?VY^REf-mm{IYgg>mwR+X6Q?GrW?hkWbcwz3fZTo9J zrat;!@#yAb-mj&0^Znm&vNgxXmiyNiyT#l)Hm~q#^_rC{>mF|n4-JitiTQK)xBR#7 z-@B9N+t$4~@UPaz#KPoDcl^Iu9b8;ob-(WQcdXdE_i=yyzla{tS);FBXH^>4_J=?mM&(+mc-=w``(a^W;q-I!wr}|o^{&?EPt~-?MK28(Cm2Zlee>qco1@*+_r&S&5P<2%PuoK_j#JJX<%H=jY=0RJ@$@C*)E2#yhVk{LtPx=juO~ zTQ|O&Uw{Aq=KX(DI;^a$?SDO<|MYj%M|HX9C06nEU#Cu*lvJqad)dv+O+R+unaeN2 zYCtO^HH9LlPjFeOaP(9k=)A+ptN1k2bQfOKwF?T7$lP`EODHFN%R+;1SYX__&uVV& z?(1XsZ@jZ%+U@eTwzkd_4-2MDeRb2vEcEGqZeycM^Q}vj)UBhx7#CU16%~DIU-{mB zXWf1qe^1Yo{`H^YLQ|Lia8YOb|7EYdsMxEclla=3&&LGJ*q?p<+!mAdKc>DZvHJez z-q%~J*Q-=CLzhm0a<3lfbl{i0*W-n&%|7&W-boI>e)ruwx!Gr@O`25n>d5A#h;{e( zS6}y=eRf&qt)<>oCSIm->8`Kt{XHzdXLtGeJdhbPXU;s{CudprWkubBkN#OrcD);o ztDc$e;q&e7eZTK>SzO$@itn;~?f2i;KV3TgPTuyKT`Z#FqJkISyvaHJ)_U(={+}zq zzrQVQTf`e49UlGr@B6*M6XxgdyEP{~u1?dc(c?_~{ebY`Skbvs!BJ7a%j3Sx^zpBdG{wk){T8>$k&hm`Dyif|N7##u+O0j zS6wsryVH0$ar*c5uk@1k@vW{>oxb_jd=KeAuw_#$^^XJt3kyH)|9yM@wJRZ~p9h7S z>g#{+y&iXWbG5kYhkJ|+2ZE36S)~9vZBm)vGwXF;%U+kI3$y(8U()8PESmP?Zj$(N z!R2DcT|0G_voJI)zi{QrkG1dDsy+c*||t#>sHh7buqG% zvc2_ZO---<{`NLdBo%ZZ*XGsx_s54`y>#i)rAbN4FGq%j?OMEZ<a(? z{-eKh=gyZe_Z>Rabhw=__RqIyC9Bd;EdK?nS3fPA!!zaCvSnSLij-!}pa1^Fi&rmR zd3~;0y-MqKR(43}-JQk9Z+?E>`Qp{q*S352?%cWa_qTVT8xgdTibsW>Ve`R3l%)33h@1;+np5RBbjSNr|l z+_K$!_pHfrUiWRLGkfLVyLax?L|6Ylal*r`$}Kmyw5-hRzI?D-)vrsJg8bhfo;Y#h z(xposAG6w&eKCl?Q=FH#ZtdRWj0_9gyWx?6fe{f83M{_8zkU1WP0|0^X}Q;v4J}Pg z4Gm{bo%*uCBChu7(r3$#t=s*5-TfVc#UHBnX-z5z&4{IT{&#sa>H9ymf5Pv7TvV2n zlyotX=h(7!TW?RFn23monAnfvq8zi^ACukR->sj}^PP`@VIG5$b=USCK}+f)E^&c3 zw>}B%WcK7Q?S!5CH0|8GKU|=LpFWtp-dUbs>^EiJy5*X_=g%CGw=`bM|KaDQMe}pt zzxZ<^Bfn<#({Ih}ch~R#)^+&d3JraIEv;9tUn?(qwrts=MNUdm^7DVh+y8gf5K&t6 zn_uqEp32YZ^}jD~*|O!*rAe<=t=fHQZ}zNjN2kYkPu;)n{*I5Azt_cp7BE|Qd3%Td ziI_ck>ez`*KS@a!zWC+K7tnpD8#fy6`+w&rH>i|zZCxFg zvf-RYVQzM|`l6F7S3Z0=@z9~BIdgJ8wr+X0`tIiH^1OBPJJQnA@Bja>_~1duegAK3 zhu3`xw|^3N>*=%qzrL7HD>(|f5L9~3%$Yy`{+8$Ke{uR)?2d|;zu)f*4vl_ak&t*( z1OtQr+Lb3it~~kiZtAPszhkxg<4zut`E73>8}aUDh`-kTh{C@IJ5PG35T`@bH^&zukJ3^>5+EUAuxpLzQ;bJk|Q|a{MeiQ+d?wd6p#sp;teB zGP3M3HL=Nw+`Di0^5q*gG=NTFdK_;c2+H^Ko~9K3eYSSjt|%q1&sDnqYd`m_-gW%i zwr!t2ZF;uMt^fGvKgG-cSl;Yf#L|3FfB!$Vf05Hndh@4dw2SrW&PLvu3?}^Xiecd`Y>unAnO{yRx76 zJv|h`8J7!M;q`j;+P#PsUT>}Q_b&8G&D+#?@ZgI{w@-C(*+pkZ@9ropNIy46TT`>p zO6Fs;MfSdV8Qb6AiHwM_sCpu~|Ni-Yufm;NT%WkPK9#@Ak&}?HDSx==#rG{6uR-Rz zh5o>z(lIr)^`q3b(}wO!R)5dlto{8>>$Hg-XmV`Eygx?{d#uv(`Wtf0rN!I-L{R9} z6IYXxmfMIXOW7M}o%Y&zT3a@16^HAw>2}s#T#O9!!fZre-)!5e|5ercvRK#WH9rcT z#$|fy2=0yI(T$oXB`4RHx4-uNzrU|uX(@RbZ`!^GWffP1NuQ^;@zJTvmanx;nmjqU z=J3OkBl{D&kF~XJFwC4QQ z*XDAzRU-d&_U`2`H!=Ts{=okq^8dfL^UHs=t0{T>?5wE1ej(>RzC9_ROG*E??jEmQ&-=Yy|MrN%aUn&@r!1>xC&Vn_T}omz18Je zSyslz%Fq4;2OBo+sj2n%y{s3vsm;sX&0YPN`lnAtPwm_d(;{AfJyP=h-rn8c-%Xu9 z-Q4WT^Iv}@C13tIy5(lh(W9>K_kF&WKEM9rwR`h^v~WiKk6rVB>K2a=>XRlc`ELGk zK3mO_Wtq><#c%NWv|#sd$MW(yn?bjIpMG(|&!uZ(aaC4$LkA+G z!nI5mMfI#t)rjQ>M@Ep6sJ3w_bDf~inT^u6QF9mMwDZYDywg##?uq7!OfKl|zNQdW)62`t&iCf@sWT-OLR{5rKlfzs zIDUEg`8|KHN&oru>({UI^Q`wjioA8}wzqeew3PH5KKHDwtlHYx+SUnY|rv%Bm|Xe-^zzF>Aeg-@A8tg}a*B`9i`&KgEE0 zuWw#VOliSP+>Pp{_jWQcFeC+uv~Khe)}CmZdQ+^~)BjMAi0UM-qo+Bae$lS9>AV-g zmNw7TaGHIO4L1XW|Ln6qN0ksYa1fr7ew zylukHdmngtzZxEn5V(wO1>4`F^C}GMlvJZ1+4Cx`^#mPKBVwJR^1WRB<@R|m+Fh%D zm$^n=p72CMjNhlz^Ub1CoB08+PKchoHEA9zL&NgZYRi)ZFCKR9|B=7)(4nTLrl!Wm z#u))y9|5IA@=g*$!esi~M`5Jld!i5X$ z^8Xq;yu7@!Rx3ezP-0~^8U!p#l_x<*=0UitB&Vw7Z-c7{&^O2qk~)3uG3FTtma;P&ljI>Sctj) zEI1(GLE&yw-|ooTZ+Ew5Z#BJYV-yh+GNVF5+luRD(a{&zwnJ8>O?=?LBqcudkv%W+ zVzm1g0_+$VY<50jdppg`;ZdMkm)Gf}o|UVTrZ9KuXj%HXx^3~!f4L5HSDxSfE|n@n z(3#^lrDm3*-5tk{9jk~q^{_z3uB2dRqWe6{C*b8s87D3^&gdvA{(Eml+{>v`r`9AN z({OsC$!Rt__xicHo%as^s@R+9vSr7PA1{~BkKa`jS!1_m^=j`Rw_{oFKkl5Y&i(0g z=Ze?wZ0AkiSp2;2)2C0NbH6-1+#X+7`)mHc-=G7zgeI<9b=1}M;^C0!MSl+oAGa3J z?E2($Mf|)mJO8q^AuF{W-+eTF+O)d=|Jwh*o&WFVr~UWZ`#UsLRiB=Cn0~Eh>*wOn zE=yKreNmYzDyprf67}JGROr z;G;*6=I{M^EINN*VZ#5q)4?Zy^szBCY-rSsh`23-@ujEdjK3)FqmZQt&&70@fe*5`V+Pw3`%Yr#pg*I79 zlfTz}x&Hsd_x}&;|JVQj{c4p~<^BlYAihhPv*z7=^8NXm$LErE*F6rikWpK->J*n{ z*TpM0cGUmBcjWoX_3OR;zk?>8BTB-=1xw3baf^qAg{}FSC13LW1MfYS*t%CI9;Szd zGI@dqqkdN3g{*Pgc3#dtt);fz{9)A*tEzTB*$zHwQ!|q%PoIP4{on0ctoh;@Zqi(NHnnMU&G;Eg+~zrVMC@owe1 zRUx5UcdooRfAZfI>;DJF%NuIxY3XQb33Z<;|Nf<{tn}!dCHvOtU7cL@{$I00!oCd) z7A#yi@4HU@g}cgKGl*NKX1;~>>zOk>x928pza3xqv32+NcctIIOcN0`H8)R7Tes-_ zk5y}4$@$N%xc0KZ0Cdrbl|08B>-vS87Ae`=pMU>-|Cd9b=huIHT9h6c5%Hm_yW>Uc zbAQn%&&x~7($dqzL#AB6c1>X7vdr)A?FE|I*}kp_sEfNNy?+0<4-XIj``0+};ziz_ z_uKj9?OwcFxpLj6+i%_bW!9}d%Ax_i}S{rRC&Ko;kB(?aD}Jmj}nr zM)&se9(8ri%*?d^b8vTVuB`Ln!*=mep`odPiHd@(%?CH9pU*w?b<4J`=2x!oj9EA5 z&71jueyq3N{m!o9f~|!`L{LyrbaZfNM$DY+Pr=^a-uG+EZPV1w&5GS!2fBi3^Ua){J3(98JjA6W zB|ZK9#bsBTg*AQu@yT2N6aPuc^deby+NNoZA!Uw^jExR6>PRk6xOJ*<7p_%!6U@H#Ou1n@ZORlA zQ!{~!P6j`|zBEpXC@(Lsu4V@v!uieIYIT_yMaUq2Eeznsagkab#k;r+e;5AOWz=HIpZ_;GbLb@li6>kGc! zY2~;3hnMJ*Z=x4$1+LiZ`S&6RgZSm zJwB#BzwX+7djVTJ5w5MScBQ>&NU%l389GveV{rlgsDG&T@lwQ4l{d@lZU!T{l+s%Dxr$n-{^5XgbpLU-P zUw7*Au}aWj?@L9g1j(Zfi#!6-*SMbOnfFfRY3|Vef~fBf9dr4ysM^f^n&l-lTTLMaCO#<(>1JU)coj?yG(N*xz1x(U~)6PIY~{xpSw>w3FKU`rn^F zVPR_A_pk0W`y1Zyn3y@!U-PqwMcuwNsYteg-S1Z%1(&oKE%E=iOJ65mGzPnE8o%PN`?>)5VgjPo0 zjJB_9?ug3Y?#lD)_&?e88#Wl|o0pfBE!(`>+AE=4ci$rUR{2&227zwf=xtlJZc|ZJ zwVca$&NFz|>e;G|DNk}*h1N(2ruzg7Z(3t}-`W33#qt&QQ!FE2+5cPd`vhM!1H*?W zHx7j8T)pw*$JC?TyBA5z%I=jZc38D|vGS>?ud7!t2Z8k3b4$C5dbinZm5ARolaD1T z|M;)pKaU)7nG)amI5;q{?#<8V9T_<}f6D7C!fRKq+h%5KJGWz*ntJ&6C99M2^4_^U zJ{xNDfXhC4wdwqI>()s)`#F8_KYF+N`?S(;p*y=m|768pD_`)s*1kRWQM|wMPTu&?>RMSEx-??x zy4BUpOdSlbmnEK`_iNX!GiP*Nj#$2b|Nj09Nk)bPlO5a^dAyBVy5*G7EB3=u2`3L4 z2_2mxAu_qTv)Oto--m@Jx{^C51sWdX(7ngV!0_N=`O{NZo7ulv%kW(cynXHXuKo27 zy7l+pTCtOHP4l0cct5{w6?g7lzFhJ7+Oc!&3=H!GjHWDEW4~hGDjmfYI_@WCsEJFf zC<$)AWOB@Ma%gkfjjrNzb3{&UF+=mD{Ix#rC(>i_sh9+<-y5Kf%hk>$@}r~^ZT*Dqnea%WsTc)pne)b$2YxCQ;Z;MyA>onsnz##xI(6F{j7X<%kKW z+r@BTS>gYGwK|(Xw<2wj+i`GLltMTc^U-Mmce>V0ZTn=fO*d`A=@;_vMgA*CT6)A- zPQEkKLOnYaeyx;)#^=uBB%fpbJu`$NXRR$>`o22D*Ll;k@ROgMw=T67%v5@NxO$#@9s|TG4x&gUDpLwiL<%=;J2Hv=xzV1bE8lLtQlmZd zeySYn%Lwp75e5bZfyP<(s=N0DuedWooA;(}@4d6NS2ILUGH!Fx^%ax6<)<&5HZ!yx zx@MGtfuVupOk2pdZxIXMy*cIfF~lrI{Gsl$l$?o@+>eV`oj$Hgvt1cgkl}K|>9p#i zb?{Rv7i}`zvWa#1iJAi`Y@(V!!>-BB%yo29?osXLO8s8(dQ~eA;)ul!9FfctUD1Ip zKPJ_RXNPMmFZWuKeX~scqI9=m^6F(brLtE(cT0w!fY;GbJogO8q)1l@yJJEzLA#SR zoh<}|XCGXBw9Rkp-f3&yr@fe&s+PX?TqyXM9nf*ok6pspPjT7r%u1ZH*JaH~sSjMX z#@fO=cg`RqQf4v;O%qn5&G)Ae&U?aQK=;908VmVt4cfMF?vn+>geWzR0sd>kkpB{l3 z%y3a7Q8l(@eo5`cB`Y>O(Rs{a^wrDkMp94b3bE%g!v0EfPPRY1^x;O!d8hSF_31YH zCoYyTNxCFu(_)4SMcOpHfiO`q{PjpK`TL6MLUBO?cJq zsUA~(J{cX3*tSM{qcQi|v zZ>m*KvpGN16}%YqJ7(qG+cPs3EPa>1tVq&5{2Ane1dwAHIvld5i5uDh}~*s$F0qbT+60}TF z`MmT=aPpQ*{N79AHM6BAMJa1A1%FbQbxSqw!M z<{>xFsUipC8As2Ya{0XDncK$oVuhSeTdSw}d|9+X#sFdk0|SF#-6Yp0kykCEr?xAp zPEr+ycB-w=d;8kQzZloCyJ!5 zGxl)#v~pwF!d;gZEX!1yr@CFEwLQz`bVpd{BB!lU0n6%ErYlYC-&!UPD&4>?o-Js8 zdEu04AvQq;UTVn`Wn88$atewUTYPrX!GJ);&2ROXqqBnbN+8S5K}ATxCdO$q8&$hm zc++N=>0MqwWzSj;L-li4ujoE*4Cd@C6x=4%sJqcJ={e|n8n6`%p2wzJsQU&Ruj*k> zlM@XNUS{GOY@K*g?0uHvLW@luWtlE_?$}Q`sCs^hO10q=#Ob6G7Z1j6i+q0Vfry}B z@~kKujZG`BI5};t3kXxYwQ0S{(nSHiiLG+8Hk!y89))N4c{xTxu3r4*TSKQw#Vc)o zY^}LbO<5rA*tQ)##V7x09qYLlk@$Scg;5%7(QJ&#Yb2& zs%WdT~!|2FXI-)U%M3x_g+riCZP*8r>_2()DyRI@5U$l zX1N)C@A@3T;Wb5L*6*U_k}Hh*7RY(?3DrK^xo-W(uaMlsz;NK1^5hLE_1YU_&raO* z?O0HBlB8(+vsJCrJf>CX^sPU+EPPv!{^nT|Pg}VyQ;Jy19#{GI^#67~ zV{kHU;7u5Rg2x(P%~D%U-$2WtJ5MLD(Wf~FLlapUvoj>bEuM&75v0Y zmj%!KPyTY`nkrqiRB`v-?NirChA8_Rxq4gbWE#n(S?{%&)v>g5=9;6f@SsUcH(T;( zo0ikfxv@7j<`vC!T)He(Gc(jJ$6HtT${O`hZoXcQ$c&vXS43f2973+Og>8EvGLwJC znFUI!_fPFo4qnaOc_MR9QsmtW9rI5*UYjAwz;J-=#F;aD>i^eGVO+oW)23ya%+1Z> zdT~+PBW;_CE6!Bxz4v^+^{hu<@9imlee0{VwC&szTwGk+u3oR)8`r+<>({UIt!k?l zr+<;~^7XBK_rmz($&g}(!%hYZ^m^CZwSVU6NBes80Up3A=G~Aq@?;M)SDyXVnEqB)7+P=Nj z{IXULygUT_O?|uV{!I*u58qyW-B0P&>-YbE&CVB>o;Gvl&r_$5OK$A!?BuumRq^-P z@*CT?FWj`Kslz7k{9@r_QP<#Zw>Vd7loWI%;>mu&o6}@XZbwY)h?wd8hFfIS+lOx{f34bkZ_l1Pxwl{0{d%E)x$ywo zxdLM?O}%^Dw>Ne~MMbZ_pK<5K%OeSU|FH>upPPAOv-gn=&z?VbcRy|xZg=j(36HX} zX`uV?Di*hFEPHq3-RaZHi&m~&Svu$L;&*|+<+lFZw~LYCfuYiB=CcZuQfD4I+7U6? z)K&Y-nVyuwQd8&Uk{^ZYjW);bc^hG)^PZc5A%WNS_nFJQ)n(mBrro@GbK}R4A3qi@ zH%|0+bE~SFwJg)M?*HukKQGGbE6NwA?>d>1mX>!n%EiUm`LML@^cgWbN;FlEzW!R3 ze{a{;W$In;&xweLRP2pYl9HDGeOLaUg{9@ru+P!b&CSiuhY#=DW0PO>>749s@zdqn zpTxV^eb4H?wy^Hz7T2$wJlXc-yxHd0zfBfc?Eazp%Cg_D*ccj)cmA2~KG9oMUV~fw z*6x^zDw14F~t3G=3HtBv0K<8MJl#gobY z_R>;(f5Xb2d{|gpEj`CCJu&g%>ErQ#-gN7m=PldtOif+g{?8A6Y1?ksr_Y{ru-E=& zo~_rWx@CKLhtKM+PoFvx*ZleO=gb)&B`In7{JfhR46dut&{pMU?|w`b47hY$Pu z`d%o1{`{Gnn@dey-P+3P+OC)r&p-d<=00}pSpN2{YhQLwJN^3WwCPiQ{e184ELNZP zF?8xwNy(SBf0<)rW4BEYtLv5ieea}SMDS$q@Y`$O)vj2f;s4F$h4{1YziTUZGB-Ov zOz(Vg=&1MZ^7md|K3{%*QsSHNan`$c^N#Wf{od`+eZT$CA*cAbdw>4a{6BEu!Gi>y z$>B!}`D^Xw@83|6lJX?3`uC=DTR*)Id~JEVRJty6;_2Uq zCT;Ff?hyCvEY{SFeG*c>*=@fLdwlO{Mh1q6S;yb%Y3r&go%?yzd%CjQf^)Gu0-~cQ zPn|k*)})}=*sGT=t=b2gzHhVL9UL4i%f}8Hf9>l#w|?KxvZN%XKQa3IYxXQyprC0O zm@{+s?ALGK{(jS~pF7i3Z~E)2)8jw==05sA=5Qe_2Z(m*wZ@ zSQmd=^LEL3o7$F+I*ZzGZ*~^Dd^vSm|LWCiC-(Ecxx0J$!bEey*u7=8Uco9#TKf9` zKT59`zWDRA`0-=MrKQT2FJEdo*Uu>by88UOWp1rr-d=T|uFX!WNefGJbljIAcjZP! z@V`SczfGT|r2qf)zRuBQ?e_foFCW!k#YV0DuD8$n^E2u7;Zvr!zrT9v(yx!|^Vj{V z4d{R7`*GSdk!l+`rK)c;m$S3C+x>a*_@%>xsnh$!#q)jr{KPiTnlo!x&CgRmxy8kI zvsB*y_4~JXSNG&elfJ#bEp4}N!-j^Arh^F;Cv>KjD^C0U;n3&vq2Zxj+Cpyb?$Y`9 ztjhm2-Ffu+XWhroh@N_)_qgUx%#wn)>jW7X z6k-Ys3!R*p1bKORO-;@9&E6dOuD*HGrjCq?3YWX{p7>S$TB+RmO#iCOlLCuVr@Ul$Ke}JO%zWiG{d8zh(4X%4`#)cdw|o2gwXifdH+MW}m-LsC(k06> zckZ+V)o91x?yGwHE9vu{?b{!oc-ZW>yf`uOVf*Fu={<>}qN00i{zOF0N)7W{ZftG+ z+kO51s)vu3UQTym14Vm)?rEIzhCD)CwA(@iG@!- zEM!SPwDR)uqhdcZ(@#ZB_;}YjzAkR!{q_55^`>WEKPSt{$vMC7TjdmK)gymxv)&>{ zUWD=TDc9ai^Lv|eZ08|u-m6dNO}#NKrzdsKlPStiGH%|9mGkE8VPrTU{N!QZ_1J&8 zAKzO4zV%;jU*WplhEIP9-OV*J-rm9fUB1UnvTXfc+oaT9eSLiio_l%OuV1~IH+QbK z-o2>M$d@HnHT(AL<>eLEZ@t!LU-V+Z58j%boHZLiUVCsMATRITx7@FpnJZVWT!e2s$(EwGqpRrKTC-ftg5^p$SizEJSw zgQ9U;soJ!uFZ*TeH0mbLnKdgbFH=@V#>?AVS6B1o`R}SKDkg7k*8VQL{o%xkNyj$bLQCYE*A_8F7{4OR|l2cM=M%DYieG-e7U!LeXW(j+s{9 zVc(^8{!j3I-+Vt_g5!+Iy*-w8c7ahrZ@!D~iqX4xqq?l@TUhYt2M-=xTeN7A(*EnO zOD$xo%ic#B^^`9D_-vswdvI`2QE{NN6wm@$TWZMT>Us+&S&q?Ynnv^`@`hv}n(Y z6XzvXuUWIB;^U=B@$rTA{ZYGb9{VR5w|l)80|SGn%gU7dT3h9(ZE9M$^r-dB%8(-W zj}hw}GSp&cChA0Ao4R)MZb^0LOhtwRlU1MoI?mtus4wN_5uw9Mi>_P=`S{@B;r5Sn zU;Jt9wx46CEO$RED=H%5#>QG{K~a$(DKabfty{N1VSb04jl|#c_y2@VVZEE3zrXJ9 zFa7`T#5FZFU0wfu+O)~K{C(d2F#WDo%a$#>|Nn#X#Dt>7AJqi^{?-3)W^HY)shN5G zob3JiHmS4S4$r&mFKd_-vAoV=vD*c)&B?#FHT|h6d|O}lo_Xf|l4oyr&foJjEiyAR zDd|zLJKz5A2is5YkbUO=qY(_+Y~6NVxbh_A@u%>b?99D?C*Cah>-PBUw{Lyn@s*m2 ziVK(Q*s);2g6-SGW!Jp^Rj$5of6>=lui_p@?I|z3GxHu8wAofqyOUk|{_vqghnCN; z)$7``E^ha?Q{Km4zkYor(yyle)307PrK~-b*}u2_n%=kH!$mXh{iN$oF1EINx0+tn zo1T4s-rePO9Iky_pK3vi07294r8RHfJAL`BaNS`~&C^*c>Qom+`}*eZ`&i}Y$5(jj z^l51ci4KeBJKir`_d34*^W2!lQzifq}s#=39xn_ms}lTe(k8a#5|`B+VI_#naUx*f~e*^slx##p*L3YAsz`ozXq( zNUMSv!vW!ptxA!G$2N3m+d`T69V1ag6U--B*XwT}nPZ;ji0&f9iw@)2B8X`Fb$hPb8zlVBof-C6>iVy}(WR@a<$wKVzvAXPeSO^Ol`G3E zWF9|$tkkA@Cu7ggFTw6Ma{W;W(nr5a_g)R1`smt8gRorRUXGhzzVqLh_2~FNJ(vCb zj0Pyjg^9{yCnxvx^tyfh9ote;bSm%t*yo;mB`5dVi`7Mj z{<4-a;nAC)YmlZQyH#vLe>ZGY{Sw*74vX4?j zygCaEm*)mLZS4w3tC4hf4^(70Ae{Mh;+h+vE0E3e|9HJAQ$Jd`uAN^!H(E_yJ^lH! zNkYP|;YE%uTP&VSO1?aA^LL6>oY`tW&yS}j?pk+yQL@XGdlv=cGF@F(uGI9mFO4{| z!Ec^b?aNP3KNt$Cs;hSwxBhoCw=pvMm0)6S?p_ujSMTiXyzSjf7tp%8PoIpGygYq3 z?lrNKTX>=9>Gd7U-rtRixcfWdG=r3k3=dl~U%RrvjE%i>=FAD2z0Cdk-Mh8_|24mP zv*yj3H9b8&7cT}Xty;B8Wc{{#+tx>j|K6?Ox`#hD_U`RhuU*c(p8x;j{?hXAC8ghE zcJIsBY#DmzyMfIg6EibCIh7qk(`@o%hn7Mm)qgJ)L&c`cn-brxfue=$ZwZ-dQcKphKvU`v2$niJ_g2FLd zb>f=TqZ>M2Ec|I5?bT(gBh>x#=g$wlyJmh=?2Laenf&|v+t@b&C+DRoeNw6J$S5n* zdsLMII!B_5{a`{t6$BKNmS2vHiMg{ePEq3Ol`A1Xj{U1!{6O1MCutFT z^TWsCb-mfY?yYUTx|jc<{Ijcn3dWkAg28MY)A6++1lRm7p=;B7hj|!$byVFf)+Q%rj zrLlZGEggB?t#jhK*Rz(Xs;SA@fBW&ohy;s!+H;{rSfViDXVr&gku8qGDoO zwrs2W^zxE7`?}4gzvRB|h=_>z@#VAry{gado0iWoF*N-6@_D?Dj!w>rBMb})TV44i zSN^^0`BQrFn|4>X-(_jnB&61#I;doz%KvD}+Q&y3r}o7xT%-Fml!2k5NY{Lls5?)0 zN7e6NNBvhefx2*Ket&=OE^}=|dO7Iep}V`Tiny2F`0}NsDr(lc*Z+Uz{};3kP0y;b zvbDYYwCHA7L3dJ7(WlMl_uG`c`T1qbmM>qvT#u{$$^ZUe_?pdL{@y+%J7d;;h}?NM zPbn%Qg2TU~z(Qu5u3?!=l$hX^4T82+9T`O*3)-~aWp9y5JbQ0<>E=(rH@s3)Q)6Re z`}^q+zaJkN7Zw#YY2w6(1r}MW zR=>Zq_xi0W>ql|YrTmY7%YEh8_xMuO`P{U$XP3|Kt9X4pe@Bd7>En32ze#Dw;&`|j z7-mnqwcu_Tr-#xhm&DA-ImN!oX_gDlEDCxYlH#_zXWF}{BdQ!%zpM>dBz~!ukzrni z=5_mduk&K6V)lSm2FS>WbRXFrv(B0Qo4#4j{d;YeP=qi%t=t_QM;Ke}7YT z^Yas&xGb}sPj<`RkcfyMi?7H3zW93m+uV$R?fm@xTgppnzFsw7R9i9ee*K@L$s5mm zUEad{`}@tfQ|C^dx-rSo?L@Zl!>g369ZMxOr zQBhiQM|Nc0E?Qr>QF+b9YWKpsGcDHqv0Kx+&AR;PnzEexYEf19>pv(YeNg&Vo*21n z_wM~a-yPZi=hb~{>)l6uxVX8*r1u1VH`oX6m_Ds*yPlYr{P=Nv&DUO?&R9rtQ&&3{ zUgX2TP;sT>ScFoA>gvB!yqwj#d8dAyrnB}#+J}_h0Ktj34DG&jH{A4(`&ORbBY64R z>+cF(6vAOHXJ|Nr6s|DW>xcAt3!x8B{Utri>`8W|C>qOa!P3*)PyQ?G_j-4=H3 zn5LE0xjDA_-|mLRU*C}a{nF-FF9bHPTD|td9nPna-<>-#O0#Cq-d&~p=}?xqe(b3;cQ(~V z?_HMJ&M&*C{=egwU&phr=U=&YO+-v&$&w|1zP#N&Yj!kyds|R&@TpT?+@C&oW|WnE zyRuUL$&Y>e_N`p`@=411X}Xdi_e4eIpFel**|TR?Lc&|SxYoYR`pew>$T2SOUH1BY zm+s!Zd;Pk6wfwJFt5&7>f4W=!w(&s8zVqS1!E+}}aBz7mJ9n?3wZ_^XQp&Q4zV~*E z-kbR}>St|)a&2v`sOZy2pEqyVQ1JBC){etT_2P?W&z$+OiW{`1uK(AkPf_{z&z(7= zqp7)W%^C%z*z51_X2<8;=iSp@SkoWXe)HI0$++#-H?LiL=KJl;*|X&(W$XTAFfe@Z zFub+d*vOk{=gxBr1lL_MIlIOvnvYk5aM_C?6C-!CG%z& zf{tNhxSTX`&D7%?TKesNoz`BzCnjjmRKu_*-^G9aW#@}n729<1!OhLj#k=K?KKe3q z^YMOpZ(mPOZ*SY89~0g_n64i$D`QfpZd3Z}jJD=+W1~y9dEe!-gQl)~oqlefw5)9G z8=d*}A5-0`cHNJkF=Ix>n;W0&E57enQ&ZBZSbyf#9dCU(Z*T9fReP(yzYC0?HGls8 zny0JYPQNsJdtT?#N04nAPrvo`oqP0X?Ze~m-@liamKK&>oRz&QJA2jo*xmo0Ucc`$ zbJCUT*XPfk{rJ21ufNmIEW3Dd(#;L-~2K+mM@Dp-M-~scDzZCt8^9r;~#QcuWgP! znO<@C-4m~Unam6a7WcF(g}J2Jc&E5eoMfbGwD#(?@T`LiZhfD7=3-jH>7Wn|_X6Xu zr}w=Q*nZ?R0|SFni1@lNp6-ri%#HScfA0M(uIK0Pf4h$5<*s{|Z~y)nZ)aQmZ_lo| z?f-xGeTw?w{Z>|X|L?!MWo74Pc_*LydEvr`a`k=oKb(>-L&boVe!Ow}$s@5E3ha`BtZ<29e*PqI`pU=qfz*AK^Vdl|> zO&%8#*14WIJMZ0+C%LXaW+sKP7yaz%xN&ju`IEj`{JLLv984%kQwxZU-F+iShk@b4 zk*Xb!OD9g=+GVISd(WOdlO8?l`Ld-op&%z`&GPN**RRhn^$(1RnKO5)CpOS;{MT>ab}N5RXMUe3bAR!* zl5N_5c=EsbD>E?UbP%^H$?0*woUPXG^odX9L!JINZQroLz}PrAF!b+(gUzP<3K$q} z)X2T7nA>qpqm5Ns&!%VVyf~Y0htA2~?tF3Ut28KuSuQ>yE1uV$Y||`*5nMje&tdj3eP-RK|_X z%lEA_GcM*9EIjx7_iytmH;{=NBqTePwpLHQq;-0QJWqCmD*I^I2NpLeQ!>sFe+ zU058H@zz;s^A17qGN6RLPoDoSD%u1ZPcHrb#pK?etrv|!Gi42~Csj0}XP14x8X#P@ z^s%+!vd(YsincmWoZzaG96YT@TfNn2ZBOxwU3qImR2DA|y8$|A>%qqF1x1^dFQ4Aw z_HKQ4e&fmZ$%hXgzTD`LpC7MNdml70n2>z3E%aINx?|H*zIes@1-x6Gx#US)t5ZN) z=E8}Ko|-U+9uvHheA4k)R)?YfU64!qd-v_zcmMChyI<|!Z&&wQ^WPI>j)I*L=V=|4 zEk~y3@ITQ@*>*(eWDL@jXw%^jVbMjY&dF?2o8TAx9XQ3K*jX|8j#j)1*VY*R^T#&j zZT!+4t`rZN5xx7^GmKA)U37Qh&U*`a5I4qp7@@Dyv7Y>P%L$*;LF_Ae*R%L8sg?A1 z`WZIuDfd%Bki$Tczz~v_UjETX z3#Y{9D1By}EE%%oNpxg+O4ebWNr^gbIzEa*>PDr_G$R)hZmm*ri`MQdUFz&y!WHf!~BSs%0P0{&HrG&y!bKZL=glK6-U= zEw_wO_IVv}sDg;*Nj|P=iSn8c)qh`VNm=`6^S4VzW~*#Br(BzQStiALTI!s&^WpQ! z4O64oGE#g`{+N<`*70_ks>rb?i`qZU*d)0}O)68fT8e*)Fl=oEgUjNUsU?DSm%h4A zUId<}IdMh%W?Z=}WL zS~QKPEc26zSKy+JuKzNvK}V&5yvpEUVQk&y@p5n8x7z925>ZimCP(_M$O~5rH9C2k zC;8^4bw|$WhkraQe-LM5w96gM1R~Brd_0_3)Fy%yyqpR5o4jRhzJuN#&-B_sdUt zdse-+(rh&FeJiy7Np#^w{_ZJWuHZ#^;9zi&NIN#KW6eV?!Bvy|uhyn`c$F24uMF{; zqqQaQ&1%<}rhqW1Q)_hBrM1E0hhc`x4^J`9Nte#vI?_+- zdOchyb>3)E=%N(?YsIFljDI!L<4N+`yR5LpdLZq{*%FPVs-pcOb0(dPP+_0Abj5@# z(~o9sPB91xIgzvb^nq!&rf|18 z_HQANUZtAq&2B|`_@a|T9enRLoweG|w!EW5;_{V8juU;CiV3ay+Pul=;-B2xMA9t zV_eqit=H^SjJl;Sf==j!=sa{nVd~!Q-5;}7aPHnEqnJGF#Dz(#Wltr9MO;;QJ_o!S z_1wbOyKGkYd>8t=>Ds$2nD-JsPny~QtA*b7s(!y}GHGY{oOY*xMJ^ZbOt(JkFtw27 zYedn67slsHYkSv=L+oQy z*9?t#Z^Bn!CZx7aaM|OTH&uVu-gO;HsmYPs4NAL(emZ0i>66{ zukTgZwg2Bs|0Kz8@9O_nu1$wz?$>TFoSX`QrSN zmya+d)Ti2>p8+!Poo9d)xQIK?i(sJUy(v50H3GjADm zcg#7aJ?$!Q?~j=>kg7>XG3n!jXRqGG1q5tZyYJlVuT~~&*RTJ7<>h6UDYIt%x^ppo z(&Wj~()sr?_Gr58`*!N|tYy4Bd~rJ}GM$(2nZ@_+{`|Rfw{F<*;pOxABO8AwSAtHf zXHd{O&DCr)X=&S*LsIM8*&>o77X6tZY#9A>!R0mfPh6H{`b4e?II``;nNLoj3lG)r zPAXh6>(wd=cen4~qV2y`*lg={wEgkn;gb_5{u-yBU-#s}#v9wq-!F7#kKyEev~pSI zvu|yuy10}+?XWfK2@MWDE8*?qQ!~fO?C84u)SHes`Mq7%oKgJ7%9U!Zb8JR1+pZHaQvz&vy*b_b?HvQd1_`&E>{s9V zI$sx^=GwgR)2E`thgsURR;^uW_x140Yqz&gx4#@=`sSu;QpD%apBFDq{{H@c{O;m| z%1X-0i#IL0^Rh%Ju(mdKiovxa`}vhSE#>-;8$aZe|M!Ud{PpYC4UdV5iAm+(i+X7a zN`^TCk+K*{EYASwz%k9~iU{LYw z%+A%<*R6d6z8KleC&SRmFHLvh#hZ86eAryRGidg~;&Z0H#_>ym={s;a7_ zq(>Li=l{F={(f)rIqy?vPYUw?`o#{)1in5#H6Jb>&n^tQQ4qad?Bwy2Cr|D!f4i&b zYu1#H+J9=y-rU@qAK$zzbJx1~JtaTyv~p|Du?MYeR(5#Xn0jPM&fQHZTN5J0btTJ_ zt}T0;wBcjZ|r?dnrs1$7~-B`{;&JikYpmLZQli`1*{x;*jycFHjO z%Gtlq)7yR6*D!Ul`RQ5Ie*HcZzt_O4O%%9tUZ78{rBIW zKIP@*FE1%MQr;5rEJye$pU$#<>(0F_F*7wkfA;KAqq@lJPm6ZG%F0ele?Dv0?BqHA zZ(hBAHOKGx*4O4?MH3!9dUQrNx?{!W)vGrwIPkC_By5^He{yU0$IqTFrCYbU_sNu5 z$jtft`nt6LykCi`lR<}6R=8-)U0HHb&ine#Wv+VfxxLRB^(n-usGeK8q-0|7-Lq1E zH_6nP>ajC0$g%Uw+s&Cf*ZY}etCxLtzrWnLQ88u3siO6(7cKg8;-T}) z%uG&BPM4BDN5$LP-S_?YwEE#hLCa@I%W^h%go5S*K{cJ<1YD>UZENBpq=cmBWjudS=M<*ycgUmYC0+4|(%$&=?! zpZ)r4RdUVdB_GbG|Cn)U(xm5ocG|Pno0^)}e?4n{+6vTsKd@M1i=N`iAjhr^CWa5LsmU?=2&U@k#zG$)` z*Q$2{}_9!M}<3|Ul=}NjxnJ_`2Zb|6%kfqC)w)X35 zX;uCFvC-tUH`!POncj@Vj^QL;cFjCX45$J2eI0jSG+dedl8O-FGUl&uosb z`gnBWM8RV-ww;+bua%Y6#l+I`X2s{Qvam8gzip?VX5HBQ`^b0o>7_DUziVzidHQs3 z$)6cBDsRu-J-_DH&!T>QP&-ItQ<|UV+MBv_Z=LKZZVi{pIu*YG$6}MSC+E1nyF2q_ z<+~*={pu&DK1gw?3P_(LG>7l*)CGLkN^5nWO~}y`GPki=l;`j7&CS+4H}>w~!-o$h z6eJXQ+5T}eG4BS-_oT^r%jvkefq#Kh!I+4FNpj=1>w z`T6>8J^uDv)n0b~H~pJL9!&c7{=T-7Bfq?#+4e0wyuA50Cj|xu&YL^+>34Cx?-|zR zZv=e*R{#Fh`Qp^o)z;;CNbi?0HnqIE({TixIT5hIM{sg|DUt@uB%s8zkPdsef#t^{aR9e*WEEZ!-UGR_5Nn zkIm!0SJ>Fa$HnHpUAt^q#4@jxpUb!W{rxR1HBAU~fM@;RpMQUUf8YJqevaK|bNhPt zJG)X>u3Dp@bgr_vm|L*7x1XPv_xbbRn>HD7b8%HwS5Gfoanydk%a>#Qai>q5P*`;H z=FJb=LCHJ8`0=LY){%>RV%EiaOjFUiIr*-~iJ;^FmmZHNA(7Y2pUlbrq~X=BGx4y$ zmz>z+Im#WZ3=Fo$y}PolG&K)COxU%K-FHrLyR&zJ<<s5pD7hQ7Y2 zbX9eA{`R|yO2;B1Gd+8Pw|*3t`We=1o_|te+K0n0H*<3zOqD(Rxa@aLCFl-CMP~oE zva&8qGH><0y`5xpZqoeoSFT*S6Z1G0)cpH8b^3HuQ1i3FU3#);&s3Jb99$bgA_3o1LGxO>c8|bCd6R z_UzdSxmT;5*4#K@dH#e){j-altjjJbS+jh3`72EZvl$L(H^mH$8b&Ov4#Yd`Lr~lS)B_}`D)QoFC92gf?_2a_958j{#|GvH5y`JA(x*r^|1qFj) zUcdFP$ehGA7VEryuBKI_q~z7zn>yja#~p{`ds}borrAka}zE zSe7k6_TD%CtNK;z6P_-+);)jrBrP?yEB?pTx`@K`dpX2ZAt81o`RP#J=`=8fQi*4Q|7was^iyAliyL-O9b<5ZOxk^R{w1LX+rd6Cwz{?Y&r)~wsu`)0y^xuA4Vj<_(cX#ft zC;qqQow!q6%)Pn}v<82w{!`G-+)-nS z-{b{_=O$Slx^>=CfMdyWSIh3b8HRnYKkZP~DW5TS>QgTdg+(tjt9A5kn5Ifhd*|X3 zeEG7Zq@><-ZFBSTf`SX*vW}RFiEl1GURHSN2pAh1udZ`z2d_Bjp00Pawq@(Q&tI-=u{gc3 zncc6ZKB#u(mL)2trlyb9Oe>9*lzjP6`|sO3JDqJ61kaw6a@_bKFH-X5%VWw<=U;Mp zCzK32p;o@`%SNkz2lmx!YHDsg<129YQS-qE^Y8ywuu=N<&HtX3uBM-tmsQD!12Z>2 zPqKeAsjaQO-lFzb>+|`=7BbP>#cb=p+|1u+y|L>!sBIomzsOMRxk?wy$((Z4N0GC{ zvJzCUYfPy>IoY($DA)Vg+A|?K$vqY^8NM!`eU9;@_*We3$Xvbifd~VGja*aByJsIx z{ySMMZ9DPAEo-YI{O5Mvn)POl&ex^O=UXXVYGPw+5BuEncJ8B|-Q{mTRO#xTkFR|B zqyGQ$`XBHA|LJ$1Uzv9J`JH z53aI)-mP}~7`y+bt?vEj!R*hUKFz%wC1Uq^_4Pa*9UXzd$jp-qo7tay+jZ+!Tie}0 z{acH6?b6cKo!a5{?mmBiqTt21w~rlaUHVaPl>}(9oO!;a;6qvKZP%|~UHeNDRB~OL zd{e@EjZ?+4J`@GxyqBThE?7J2*I2R7)$w=+N%nyKh@tX`ebh$M5+= zXZF>rS1nt*D|`Cv>9c3go;-WD;qj-QPFv>-TCMN{@`3>Ebr~+cxX+$wI>7+1K(W&wsC6Xum!#HpeHvzCP8p_43Ob zTZ@lRkFOU#ojCnzxBh-1-%Wc?p46AE|9E}>-@DKdk^K;Gr0YaadgmLBprBZ} z&5y5pS&^97c;;PXM1+K_v~}sLFLQU7i`ypLsM6lGPTJmlYH_FTtDCp2t?Iu2E|0JJ z7*V(H{L`Y7iH8p>n@dTrkJ-EJiK}k*Iq!RoM@_bG>GAiGss6X~%o(5Mmj$hk@~6Lg zopp#`;&*9hwUMQ1<>S?}+xg!4dwUmK&3*L4*%^F)q%P0*zbAvGE^o_UKV96~*7ok* zyO%FjStm(k=jFZgf4{f>!-2*_hyHB2V&a?3FW2+!+t>NFtNl6#IZgej-UrURY%Zq2pZFr z(=0mZ_;sb}_pURkY|fcsyUv;VPBv}2#$0sU_?U!s)fdaptpWEdES+rl*qV)v8&AEu z_51t#^%t))F&tR@a((?T;h#V5{{QuP*1N5IT-@BBi;9;mTQ+;~w6ALyJ$m%$&6+h1 z3Kwo)H@C8qIxcuE@tofD)w@e#wv+p!&74>zql{kSYVEKEm-CI8+o(b|;A%uF}8 zV;4RYgolT(*}VN%{J($GXU?2i{Q2|$ znxGoJ=eE>=(;xi;>oumCsbsJ5zUy9ggNdO*eVWvqTT80I;M(UNSuoJHJY;pI5^~-} z>f23gUeDrVSr@xs@brn@->1cCFIcqb&yCOL1ux#X@#Fo!59@vf#pdQ#Rapu8`uZKS zFb9=)5xjTKY!On_$nyqWw}pAu#o1dyOreiz7WP7Bt{J445jy4~dE@Hp*k;g@YzBWD z$xfx2nyyQ>o#OiXXoJ~-NzJJ$U7Cg(%St{Z^t4tbOFlP=SKGQ`f+X)f$gF_by{X#a z{Bk$m7g+rH=d^$Sg=_iy5a(Ket{|G3qTv}?A5a?_=@byzH^IoRXR9va%$0yX=%=kAs_ z`FyvtcQ)vbu>+G&_r%QnZ!En23VRC5%r>{Kvg_$gwpBgKD~?ZU?zt)eol=mq>gw=yac9q*`SSE><>blf&(o@_f48-@n^%EnNc=S-wKBwnq8@o~V=odn@@955 zn$8g=7^xKbXrslx%Q>@LxAo`;p3N{jrlgbvneKidSOhwnVlim*_J)t6M^i8`EE+wU zVq_joas9-+BG;aY%Ou%@Chrh90%}Tt3a$o&Gd;EwqnJ<3@R-CeVvw)jXMo?@f5>{(pqEVW5% zuGocVeJ@j!%2@e(_R5%J7pMMQfH=fLNx(A9Xwnk44TrAthX^hAc#<_!GkoENsk^4H zvAVM6_(ahjpLO9Y%h-oLwCxAF-Oj)9hr>u07K0U+wbqQt%1h zeMI|bSj?BhN=t(T5wnZ}Z8JBjD`oHSYFYIpxKv(p(xkh0T(zbOE$7M=`JE*=U17@9 zHlytB)iV=80RYBo;3FuOloXpghqzp0Wy_6>nseIk!@?jJQzus?Y42F!K!M{^IAh%m zd^U$Fz`~BftyyvuP5V|3j1#Rc0UV zexi5o>(?E5V9OX77;f0~>=05`(wnsC%(@5{mHATH;;XcIvu3G1iY)35s#tMsb5F)p z4Xu#Xtf{Z2SE&j8jL0rO2-Cblvd~!8E7S9+GVAgbBe9c?DVka;UsDZl=}7X3iW=R1 zXS89d*;A)<9he3Vb?Jnek`bV_ZQC-R8~ybX5 z5H~&vo=aYVh_DJsCc<7wx!ma$BXHahHGBEN; zeg7zLk5ty7b$XzKn2feO$!a&6AsS|S!crZ!E=!MJ>+)Wg{cFH8Rge(5u_r}!!OtnH zKdMUZ4XRE)S!>#x@=o;mLV+n7fhOOd!cS3B`E{l^HvaKz&?rAhXTw={wZxPE!jg8+ zQciu_yL8(TBQ3tOq1?I?bv{PO#838JpCcKcW~w~Bw8zKU3^a%V(!~%lQ&B}Qe^T_* z?zHvVi#%>dT+{WryU1mq#q${9+$U#^qi!9YEa@$r3_gD1$k~@3H(r4IPz(oVO_=Gg zw9?BgLtV*ugXpW5dg6v5*G*Ki>qMt>Mx{9}x)Ce9P|MJR`)TyeZ(E*&X7!J(+qNOm z|7CDT3aDwvU^DH^xp$9dYW$n5-?nLW$|h04msaNN?Mi;vrbT>uurOfyvTfIqC%qNq zwzl%_>ru)NvQml!JHB6AGJewC)lbTd`BbGh-L8&4Im^-XlZth^X1nUyH%n6a13MR= z>~b=-=Vo9~a8qhimFxC^9F)btz;LbU=7g^99g}y(uH`b>runob?RELGl$_RE@MT#s zoNXs3xjt5PidAG_&}o-CEF{OKW|n0HwtItJ%9YLzmm1HtKaJ%LW;(ih?VDQauC|@q z@3H9VS8YqaR84nx0qt*?rfAc4)&ADiE5(_MpD~|)^tEb!{kx2=>(!sHt4|~3Rxp;A7@N$25$!YVZZ4=<}^YdGG`-oU^!T*16-mGbDZS}YR@03^bcItFf zUug-MJq3lr^}RRNDVdsn-MRR@in_YF*}Xj%D~cDVvr9jCvHARxioMQ<4?jN_f8)hY z28IJx8`c_Xs`KLmC<0@c2x4R%jAmap9_MQR7;AsNf}3|G{F@8L~RL_wTi>I>n{r<@e3zRN|UhuU^$wOUv*be|kFn zQ2f^&chB4X_DOp-ZORmp{@Z6IX3w0-%fd7_HunB}8&h-h?f-<;7Cm~jwyu7mE_`x5 zrrluLk6&Fz3049>F3-Q;{rJST)ksHKr12#0#h7lto&Wd7`Zxdb^E&nK`nyv4m+#uOYRj4}+t=^ky}Nqxa%KjG z?C#>ZJu^fM#eS;KHTCX3V-}_|-BhG9Doa$cHE6v>@|l&}u5bE!!ic@|`0DCX28InU z->$EC_i1l1_rc2B-=;oKeERfRg^k>Kmo4|Vm`|Vd=uvI8bjOONTfhG5J=QzVkLTL! z=l{6gpIPY4F2i^H#ful__vdcd8xj}x?asyY%a<=->CG#jbbIcWRByLb*PlPR#r0je z>TJIqxgI`+F*x}0YqOc|VQy}2sjfROzf@WD>(?%g#5H^N+|l@6Tvqn&SMM?5`}4QF z6-t)K&Z*J4CV4#DcfWP*@4KDg4Y;+>UMhobnGXN{0JK7W;?>49fzHzsA>aeHW-St} zN^{$^W7n*OmwPHY?PuQ9yH}LXllCsMqJj7&CgFvbO!D7h>D1ikd~L1 zm*#)vxc>U=*^?g^SWE(K3b(W|Hr{=Eco5xYpV|eb330^HR>A zojv=#+WUK3gO6->FeMEYg<&OZKVA;YKS<>PZ_`}Tz=-v58JdObTk z`_YDt8w*W)mS*ahnob4Xgu&b>`E|qO$-%1&O)su_S-$+G!-BWx?#5b|KlxpAdwcHg zi#sHnelRcyi2uxApfugfETUUR)lv=v`^wV3nH$)%VaP0W;{l9+Qu73OW)73+V4vEjRo;7*$TQ84_Z#S3c zZ{M05Qu^@NtXZ>u$^ZYg+SK;wkt0Xg7Gy4eAZIm``_j-rSXXGV9<5y(pu1N7ne>KAP~D)i<|o z=@fysTghu5US(uB@JwAP($D=+)v*m)TBpk2-H_XN_x<u{!XO)&V|C{^br+t#Pud#HW?<^CZ^7#Aj?{Du$$HeS;a^laQKeg50 zuU)(1^8WainAD|9BO@bSObiS%x}9ZfpS_$iMMSCUL&BHu@BdAgI;^y4-n@DCd%ypC z@j^nd@=ji$-_{vN-zCPy-CH-;TI$=IkH7zV`)%E~F7J7ttlo6(W!&8=-*)f47WVgU z&)?wKh=?8A7bZUMlij&F1}SO`F3l*cliqj%dQqg42jT z;>oheV!CFio00g;wYQIQ`X6Hd8#lUi;BEefw=&>c6Qim0wwP@}Wn7`MM;Y z)mxT4QP1D&>GJ%1{Fh}F-rilV>a)`4S5_4iyg1x%H;<1cuJUC?;m2!Fo}_$SoL7|f z>eEy0=lU@s?i!H8IJ%X4di%{y-uU@@3yV4z7Z>l{TRXqz*Ub`z1nc$3u`hLqUMy4E z23Z#I==z>x$7X*m-CDZU^i%tndwZ*;q{@UZUd_I~|KGFQ8sU5ISh~-24iCRxv|dBq z`uFtu@7zjRdux9$?zazofAX}xyuOBphnJ5?^pO<1-;ca+D>cARDS5iHBvxKd&a(WW zQ}*jzrK+b-r$5?l{Oqr$@b7P5zu%5qwQ8M`(z%~cwZqlb)DC^0J7>moi~T5{w4x2Wh(cY97e|NQsS^Y;RQ-rlc|&#&?NSf{%0!=K`-p;NQ|ue^Bi z;<4G=4~g%OUTeLrHhS)l5>r#t-IMQFTHdVOxifCPdEf22UuSNvS+i!IUUU1GIbOS`?z+&$5hfk7uaBi3os(k2m2Yp=WurLilm zmUL`wN!$K|!?o3D=V=Rhb8*d>-PtS*4abk&I=Z1lLs8N3&jl@w6Z$$j6YRNT^`_sC z|M4q(z1^HSYu2w0E&r&dE^k@$;^2#n=-aYNMH#bhXxrN6et$PNE3W7CQ!P!+f6((d z0_*o{X@QqhY%%d}E?9nf=G?h|7hjLxTk!GHOXKvz=@GHPQ}gb+8vhsc6!PD?^wZqw z*3UJHJ05qLfKKjM(cFI@eBQ{mWiOMA5Q{79Hg4Ro;ltGFaX$Y3+wXAso<4iF^6k{= zwt3&LW?z52&)6yLnV8a}IrsObdv05`LPLE2mj0fen7w7W8}I7J?J}{oJuAVj;W%0K z{lm-deQ$2xPMBSml$2CkJNNqQzmMlTJxvImI#u81e@s!4#-~XWCQO(+_v@vP;>kR% zN9wj;kJ5Rcc0|_nv+HK@A&Ye1U@?_c07~bl#+g4kTzxe&$U+m}Kyz-zU{8yzqpXMF;WGeA}_xe|F z-wMynu(UjJjESM5CNf+!Bx-ZC)z-<9&$-r{gh;z6{!G$MJp2TsY$JLGJ zD>quMdD0c)&L=CfU$h_Bst%*R&sQEgKl*;}rNe@qD=RBfjy(VT^!e{in>Weu9S?Tr zyTA8(-OE!~r{0ki6y#uG+IFL5P1LUX|Bhdj?__0l6@BXQ&k?8B|YrcI84?q9%pgM$f?vOV6}~uib$I!^JMT)Yy0_=WUNiMde*E~m{2hHAjRFgqsiLCWZ{K=keQwi{ zBJ-r5QZZA@|36zBtuI%7?`6rd^d;+WiZU}CP7qCF&EC9cStmt#ban5YJhOO` z^`yWMjc(pvk7>cOx;L$M&n`5YBF4mUK&a{9&)a{!|39v&5fc-$`}?Li@L$>2TU*29 ztm5M1-CcIAoB!kAk`>o7QBJ?e|KS)Fm0zD?roaDU#pb7j8_r94wm;HL_-`&FZ z<9Am1-nB3=xUk{4#<7{R=48eETa~-te*gD_#f^=OhClus?SB8~s{iLt)AHVm{Jz`wTgq1M{QuAI>m@%foi^>7 zar*hr;~V$SK0Vh#XZ|at`h^k&KTmDl{Jcl=ZdO*+=ickZMMWLKadGo@>|I@Pe3h1V zM@R9!J9nI1k{>^Ic0T;`=e{*-&V10{E^(5Ty|`%8b;Tah-*-FyneOO%|L@C}lB}$( zprlJ#@!AXwHdZ^{y!4xe3ELXmsyp$(55RAB7(xXn{r-D7oD4%(zbd^+{cBw zSwi3&#Wtw4D?7&SE-3x_oqvVy9KHCxVZp&~3oMQuKYq2(*jy^#?(Y@B{^OG~%33Be zHO|aG%g|D=d+pkNo44)RbLM49*tF^0_XEAXy?V}BoYmdtr>E}!@4@%qv7DTO&4PcK znYZ0Ie(I>j^B2V(zq^)v`V=(rW$nX9s#}--Dp4p{z4GUQf3>rgiHhg%E&iUDxw3HG zvuR?{tFCmu_kVkH^K8Mh=gu9g`r9qQJN4P~xAMmMMVl%F<|%%NWSa{wN z;g53jZ0rBM`T6;w@y@EhZlR&7nu(VuO-lOAx8;O!V43Dzz8us6Q`}wKh#UDRf zdd#<$mppm?+r;Yj9)FAt<&Rj z%F6l2cJ>rVaz@TtHgjjxrb_|7>yqZYPCC9pM;o*`WlN~wsUH2uFF?y;8YDWla$i@P z^!385cw-9-2_80CK6eF!WNAxF%cW*5)7skF4p|G|-CMqX&z_!+prGFS_a;xC-05-s z>*nWg61yKxoOqFa@y?x=n{IE+s;Q}58oIHg@Z81c0^dbF@1^Jq7M=rL99sEH^Q-Dj z2P@U1+U~D*=|wLG?J#{SD;s!DXz`yvH6OQ6+4Br!^SFi3}yU*`P%)g)V|D(&x{lm-8Z+$KJ$u|6TpXr;M%2s7x zzqK9;71xiwcYDL}r$r~cjwRRPmru-V`w-&_2$I6 z9W!P&9zE+Yb+7QW3a#l%D#m-3rsc1^sI_x_?NXCdmYuz8xWf>z%hJt})G{>hhwf>vW5@yBx(pI3aR zy-Bvwa9jQTdqoN&%V0y|D4SmjXUqMow@nv zwZ{>LmV`CG(qnzobWb!L{7`U-+1N)w?%1!h@9Wmv{k{M1r~F*M=Z6kC^{C$si~s&; zqqq#;Vy&#i#KgS3yu`%Bx;jUl**j)|>b~5!_kEv+2-;nZulf3Qt8{NWpWKP>Pb+QY zjzu^*9lEyGwY8O1ckSBwHNSQm=9#{masK(~Q$}36f4f!Uu3iZ_E_lq#*HiTJ>o>3B z-tGGsvG)A=S9^bRa{4K8t#e!;&%hujInmiItG+y_?$qhJh?Fh)>1n+SKjK)mV^DMX z$2~Xy#G8{QE2}6xdH(xIv*+jVeJ@|W{PJbX5tr$wpK|#-7wo?4vSq`D4H1tnz3M7F zcX92Xu4T)YU%q^)B=-OH`rrL8R!Rn6zWnm#OTFo*AD8*B_g#^il;m_}@~)U~24U&p z+kZs+Io8$X<-L3GAmNDelV{Jmluoq^Z!Bxdzp**`$cA6+Y`606@4R?JW8JyOW&c0h z|8174!tuYK{d zUBAxVtzNr!d*)P7W8wDEXd6pY(U=YFF_R|S`YkuUKYjb1!|(2I4`;DrHa1?ocp|rD z`1P#Xy0DLT#RZ?YZrIJmz|b$a)p7S)p$RTiIuBjiWbu5~u`@*uGhLS+TX~|VOj7sm z)(&rhRWG9#y6E?TPK&;Ar>JPt-o(@5)22=9V&C+Ann&UVleY){)owd@Gcr;#+NdK# zZJnI?tmMvn_Z}wADK638uT;naS^T4V&NOq*>kA8;w@v5b=C1$pE8D*6@7BG%yxXQv zt4@C=E_NbjeSoQz)vept-Ca02IotW(#pirq&L=Nae^^phy8B~KTt1iJ+4JY?|NWf) zTrXzA{;T1kp*M>jEnB|K^G;(kdk(v%u4d=bljU#9tJfa=o~Ng|&%d<1{JZ)6xj&}I z|E*3>pFSfr(Xr9+{M8-F{|-4Raj`Ym*S&B4|2zKQ)o=0P<@|!Gs;aH~*9I4&VS4VgI?Z0;}rrZ7cA-r?xo;`aivIPZob#(5S)t}6H z|3X7wKe^}X)oUi^+j;tXPJHyYFFi7Kf`bclv-8IJ;n#a*THd@_V>$~IzKgznJNIdm z(XkuvVy$OIM_u`MXZ@a%JzKW4NbD}%{BrmE{rS6#x9{2Gb9u|FRi~z1yKQT0TlD0! z`}~t<&#I$)BU=_y4%G?fvHS zHo8#?XV0EDH{GuDdQXqx@~x8!udkEcX82ZiZffdMmyqb-yH~EP(c`Ur@qjUMnuP0{ z^6JRR{f9T*JA32kkCp#^TG!8=H&2Y`)%}{^b9b$|_u|HlYinJXh^Vdk(-#^ZzI5qQ zp^GQ}{uZ44Bkz8mwyvhyqDz-18K<8=S~PQa`CFTcg#8}2vuDis@#ysWq?_4KrDqKfiM2%FfT?Iq{S1=KC+HIVMrY&d}iN)wVk2dZ{Uss#8c$=BJe& zhaSx_(G@upRDIy~p*Xkha>Jlw8?IdZ^yS&b@LLh$3=9c}L&HN=t0%p`m(9~rnD zS+lYN-(I?R@#gL9HNItUfA!wFHS17Q)08Pw=I{F(R$To0!G(aVEU(DOOvgGqPy=P2 z)mP^?>Tl%@>a@?DK3n_tYWS|*yMO=sbv5GBspm3xPpyA(>+9>UrCWdg+_z=Rmi<3( zTKAggfBW|J_opImZZ0pcF3IH2pFjKR>bjJyUYQwP8yh(B{^O5(eja;$*7q!Pv-8fK zmOt(0|JYlem-p_~*4Ns5j2ACn9658Q-}247R=sjdUi>Sl+TFdny4uxs=d#S(+pngl zr+@wSrS$6;fr;)nlg%cg7r#w-Nie)Ip)((jNnz*LP#4Mc7?6Ha3pSXB6D~;ZIQqtCX|8*#-xl84*zqbW%OzmVYU85ctI*a}ZS!AQWiLGE+?6XK>&-1qO+$6u z4eagfA3l0&@ov(VHRY9&<;th7KiG8dZ+M*Dytz|dT~5lKPrr7fFfy}q$M)~<*Soh@ zGceo`aH}qJOY>APzb+~AP#y(b?sl)utgHL?Y3k~Y>(;K^SN8VT^!WPCyNdhro`#qFI&<^!@&2XDmMmGiRL-)-qgGRb zCvIO&=(7!TtZJW4o$^>x@}=DN>htsNzVe8@etwRvx;4wu+H|&G?AoVJcdpo=a9`}0 z(xUJ7e_nhIk6*cJ)fJPo)2BZ_eL6d1ga6}ud%uC!G(PEEq8+|ow)&xE`{9X`C(oTc zSy%gXTYLNEOP5^EPAU0!=;-tL_OA+e?>%|)_qVoH>zEo3oH+6K=&knEN&9c#ycxOZ z{PiC{D&9<=JY~w3tN7@Q<1O z+sd!A&+4xIe(Uzr%QxOfxGXZh{^!r1r>n!o=awOsgSEd6mU>#p$In0i$G?!@r=ni! zevj?@o9FUhs^{-rf8*7u+gsLFOh{(y+r7J*gMmRV*hXZdlF{QxCF`y!Q#2=fuidsU zh@0)|zV|78X3WvYBz(7ARC*1XGyOKf9W-YeA^#}7Pa{V?wQ%)^`K~s9?w1@XTP$_I z?g=};+#I{&vYHyFHUIovia&prm7NQ^9{uVmeWh1#-u(HRUswJ8-QJrwBX<@iCMH&- zJbApo=2x?6ok(iirOx;MU%z}gwomU~(eph|WTut63T`bg`Sb4k`?8XfRie&wJ}+GO z@IB}x$o7B-i;<3FnNnPMuD#uT-=9~nxyAKYw)eh27qhR*RA7eUqCbEBbTHffdvf`` zUyc384-5C?U%GMQM|gbw=X>n(x3;wwC^ge!^P_Hj5E&co9mz(}}e|>Dz-jwUyc^7N#diC~& z4;y0Gjbnm?yLT*VI>dB4^!Ax^=jUr&ZlaFt9KdUa@A~-unOlq~Z)27;KUjeLoO&M)`*H z>Q$RQ^~&#cb1~1q_v_1N{SFOf<;7c;R1{@-=@g5_CW6jpIS1OKb7j$zh$YLGEnB)Y zbJn$+H+L>8?#nx=t);JB{rY&mK;Y}Q+xYE&S=2Zb78aI;g((QUc>B70UQcjD#Ej{) zt*xyu-@GcT>LBoY?!JaJ-RSk$D+bJrHv{r}gz?%lf= zk(SB0pbeT6rJ6EmN>WuKt&c2g<%ys|m|F8dl`YtIcxp;B%|4*yy zyWjuV*!}TtjL)6}t@NsK?_f=5?%#-~aJwc)Wi3CkBQMkvTUvEnT}+Ra5ii%aQ`WS(jq(>Ts$k zr)y71Q2mvjndLNX>+{`v)5QeKwQRRvk(l<@M`gMn3j;$1PfuT8T;I>>x9821+q(Uu zmyeInk&mbMZ&+jLzWs^l)M?W?*cpp$?PmA&^-1jZI$H7l(GKJ3>*KU_bqlTLT9@T? z3mub^mEBuXY04~l`j^d_vuE#S?Adw9*lqu9x&HQ!HupAh=?z_BAF~}hJ_g&$a%{O5 z=k~?y+xh2d8z+@p9^1X~$@K@5-tW_09=c-PDy2m;XU_aAuBT_o&cJZv%npse#@w7c zcUdh|__cfTBszl~8|Kc||Hbq4D=Pr&|Lu0n1sng3Vxz5h2 zJ9;Hq^Jv$igVs@dm>C#so_+dUYiW6tuf4frS9O(C{=Hi-Bwat>6pz2Rzdru@*SXf^ zIbUMT+(36to;`auc4t-Y;^$1+sh{_qF5SA7o144#@8A3LZMI%4W@KnERc{X2X7={k z>V;}=ypESA`3OgbW4V=MdzjX&#w{B>85j;cek=H{_^fJr=>Gce z{nECq3=9$BX-7`}nZNVXf?o}5PII0@tgX1|blT%$l6$}1@;8#JyiLA8aj}u$VPk6S zI`xXZ-?iTdJmt^8z!0Ik=;-d-Z^h2u&E+@_? zyAr?mksUMIKphE)z70ms9*Z1z-_eRUsg4zNJq0?`=E#PWnF}o1gSSjnkF@kyxJ75; zR#!KV?kORlEx{0NN~$QQ+DISNF19uoH&@x3K266yBx;YaV5ZX5)3|P*TJ*zzpTwzk zlTL=YEO~uLW{nvCDfVp#rW9I04z`KB?x>=)1aUhHOV+{Og?TK^Dwu1(Oc z)K;ObCLcT6TUQ*p=%V9$CPh~dw0Q*VKr`#jilW;?1-tShdkj-yC)=F7!L{}BByEAN zaMRbGSDT!boy4N_1WQ}NT0pm4P2IY1s;-6WGiEj86&@$IZ+ds)N?WAL;fPHuF7V8r zXmvu$m>H%v;H1=nfID4EN2b5o9kDw~(lS&j_VhOE&U+C(lF_DTuSIyhp}EmE${gRC|Isb^E2*>&cSUC<%_Z%a8( zM*U2GyEHW?q&n^78tvtlC(3kATSVLIf)s+W_Ew$?CuU9hsCj!<^R~BM8a*dn`JWo5 z8dvz5TnhSTBB!Cw23E(wz|i5wsr^#v&yv^OYObxS>5}dfR)%jnD3R&E-{a(5+pkzp|h8ay~n&E;U4?>xqu!n@dkJrz~;wK$c-56L>{5-2@>WNiG-=0j{@|pxxVzFFJVNz3=nXsBax)Tnu8HK;wyx$X8A&g`f7>$pyV~D$TZU zO+rf1UMJXnQxH8lWuPIKxT(JmM6r5o@|D`LZ>!m?ViHK{aG^cifrkx-fz{?f| zBM*lvg{aP7_4~wxDQ}+X1+AQ75t_01MtJuQmW69frbI@^oaKQhbc4u{$6(GvKm`;Q2|> zQw}+s&P#P!?Gm^!N>?Lz{}tnjCyqz$=7uHKhO-^BUj}%2YsqO^s7~JK!KdUMsJK$U z`(oP3gcU0$+$@{ksJm5D+zOE~Ep9TLK67A_YZKdMU+d{F!@cf>wagHHp7mfrQDq{-R;QP zzs`~|pM1PFi96fDm$S79%HBzxU7E-1Cn#vRY~|5rrP*G(Dj~1gQ&Sh|{`Lyi;<_pk z_F|!=_hZ4}J&@R9V0ds+O*wGMmxA!<)RiAqjjZ=g7RokaN=(b?K5a4m%=)A=FM37G z{J7TEdZdV%FFI-s)7LW5QL9?K{4wbCwNgu`VcvOXs4U`sK44wH|Z4 z+W17_V*0$-zog>fRYH!P5vTXJ?LxP&%4lZi>ugn>7Fd|EE-IrlrStfsAG30*QcwRd zS}nPAO>zokjXBtS-^gpbyLIvP+m)n}WMQtb0*4+4&yyd~rd4$tvXyA|GeAdEXc}^xyp@it993|IOp7Q)d}o>IsY_gEy2S{ zUg|nRj@qX7-fgo}YPy{E-rFg~y}7qA%Ky~V71J!1_7rN`K4N5GNP6sBF7xl@v@ds9 zK9-b8C4!f#HXNVRV6gbSp zz`*U!#C^_PTj-2#nQWEy;i*q1L@!elyH*#sp;PwGetT={?8L-}m(TBy=zhF>*)qHG zFEgJ!d2;O7Y;&pnydO1T?=H@N$X10|=J)ZE+j&+7h6kPrk%28W7Yb9;j8C1N8~CWY=hzWH~B)MXv} z6>9Fy8)bgJoxkU4;cj_9yPE&a{b7lV1lC`Vt4;NGV-uWfSN!eW-s;x{$H43K9^PV2 z{q{C@#hMigO8vKmy(O~OKHpr_|BuH!z}MF_S;x>&5EMEMr3ZHUrA^n~%pUeb!qmGv z#a?IUn#78wijm#CbB!*zK3mlC>f+TX7X}7~&~w+8q}OkJ`sBUa^EBP1O?=C@{a!ld z(%h2|clUfdd%Wn$o;x!A#~;ruSbxq%o>BGa(cj<91OmOYUw@VEmA0KbBPAszBy5WH zTtB5%>(@umHvnh+9Jd~iB|$SCRc=1Djmn*W^Kz`La8;VyCY`?z=B6F-{*$@oLC~+m zr*rf`Ys4F3(;OdduHXIi_kFt=yb=?2@^?MHa9dKca@~i6b3QljE`Du&(A_mH?b)@p zuAnmy_FOFPyb9_z@^p7_aep!|Gg|%h&{6MuPg49hJ%4sKTG|%0R=DA~dxoJ?@>Yk( zjgh)1&g#8isG_-4(xwpUWSW3&6_D$ncEvop1-fr8Cr+|*-SdBXpO56fXICqY-}(B$ z?C2QJiNPK0@6P)89tjEI=w}iv7oIeEa{2pPrB7d7<(+eW)r=W4emq#*Z(arVdcXEo z_GyBXH|sU3;NHTJ9}9HfeneOZAJA_wEF*>z7!lXv4tZu;a>`mgjXduhy#v z+ZKR-7K zwDRlUp{9)+KiZM$~wo-XtL^Upu6 zt;)*E-*4T1Y@J+KSomz3uFI91S3@HL9u!z;X`fE!N!ES+=4)xG-}22XcUI=zt|XCw-2@laa>+k903N zvUAE5y`ojSBNxX{YhHisDFed+wad*~^0m7xLTxs<0BMc)IlQ(WB9mCr>`=zx(9M zm8Yk#pR>OpP-fwtJ%5hp@6qcsFtfXNVS}};u5ZYhvuDqK{r0W))64XS8`=7A*Z%p@ z{qIoIk|in|Qxg*tOG>^xS$TPzTi`1m*99*`)Yn)uk!7Ao4+BxrJ-3_tL_+CTi?D`_Wa0q^`|XYH><0vPMbQla__O) z8M9~azIx@))$8|SKbLo`Si1DCQt zlRK^4Yu9eSI&tH9%YBknciv5pw~Gr1m@s9A#4W8eGlF>FaBtDVLAf?gF@4VT`el!teS@|wWyfC*tIT1Ht0x{)8^=!6)P?T z1_dR}3sixgUi0Yu&!0cfta;!xI%Ch%0*gzRf{Kfax991uTED({ zXUwPLOHM!iBreu>XaD~P2bq;lojWDuK4Z?DJA13sy}Y`XWqwkSlzb^F`qb8TZ}8>I zMSQNVuJ)C$&;F^I|AybyW!5rPb@lKm(=BEC-o2CC8GG)+>_@sMK-c)pD9=2xFw@fV z=Buln^RG2GH1zrUTD$anB%$+IUQa3?Ek+g#ff?5nl3g@uKm))rXE z?Ax3%bzEg&(A-3W77Qh#h@dZ`p)^?K4Eb#E;RDzEp7e$ zo0Asq<34$E-db1Jg9#U2`(A?_Eb+Mg{%z~>_m_+M}ZCTX4+=Fk+e*bOdJ9}}dO0+H{Zrk}~Q+j%PdreKv*I%2< z$iUFhaYyca^KWIp<-vcJPTUyqaKTMo?`_A8{@LYtZ@XmDtGRpS-whp33k{dwai14$ zRz5wn+be+wq;J~9<<_SAKKy;}{(S9f$z#Xg>+`UrN#);@k)N-jtNHCWcdXv@jEA6g zx~o@K78Dd@gH|xzfBn@;rq6bF`PQwGOd40OhPqt2e7X94-0zZvThBjV4GG^Fv#zJ7 z=Wsj!zW)c^i=Iq8%zpXOrH+iOtW`UgmKGFf=<06WvP8xH{`3hGE^J8u{`Pk6VP)lQ zlFODaWoI{-Urp87*=g}?&mBoQ%Mt@y+un|2$Bs!!=kxOMJ_QYdhRvTgZPu(=RZlJ) zwEy?=e4yTvee2dO*)gMI+4AMl(YK>+-wN7uZ_}nrt4?wGUfz~}zwFhQOhcnS|Cd#D zqU(QwV?V+`?9|dpd#|63(cOu-uF2@%*KjdusmvI^(k&^k-{_?^TykPyh*miqF@+<$l$dt)JKtwCCQ3<}F+9{d@6vf5&li zsr+r*%lG^`<;}^-se1G%D=X{Xy?b3ilK@SBYQP7v%)kFTA>&3w+=nwaiCVLDA{4Y{ zt0%X2&l=sCi;ld6Oi?JB#qFwj+Iu~I^{Q1VJx`xMzswDIG|g$p14sfiB@TeipbVUo@7b#tvButVcY!u z6(8sB|CJdR_bzF3S4IBgy5&oDJWt+S8(o{2$Owx5{r?}j*Vfj$lwiGkYU>?K{qnZ2 zrKO-D!Y>aFzNr8AZ2O|tYkR+adwqTV|4;AhCQh0Z6!Ju0Ut4%*j-cpI?xW48!`IEV zE%&q8clFAbXVUARKY1dse9s;m!(I!!rLVt*%H%yQ2lWxfj;H#UZ*rNrBWCvm9nX+W z>ee%FMlX~Q5mXkk44w9s*Yf!+o32ZW-6p;+ds5_}X9#^z`Tgwn`z!ySyuTD^BNO}M zoBezLzO}brwfz0doOOG_>G1We&5lY^^77*Q|8kj2<@@>j3kNQ``P+?)C2gN+{Y|mF z?ORLB$^<7~ez`_RUtHST+pFhXz*$|RQwnozejdK_$41bVr{D`e&y7bqh1S*o{(vsu z`2RHg|G(bSL*Zwq-FUeF9zP%NNsUPg*$mrLQjS!_A(lhsSlzpK(a~krvbQ((3g-mS^PUy*sn>^R9gv*W!*;OMkcC`swG5^q{CDx#g}$HY^doKY!Qt zdl&EBGqkprK0ar<_2EySf&z2PK}*7T|CA^wc>OW))z<5q79noZ|59HkV0-)DwpN; z)D>Q7MH6=hEldU7%ya>|C(_}J#dF`~a(=z*qj#_jgmLPZtdIT6J-$ou%c>4y7^|DLF~WT7y}$XD4T~sr2;w>pZSX z3X2Y&Jn50I4+xa(j5&7x-G;iE!ouIS*(E1Ge&pDs-I#QFLwf&<=qtCyy)t)Jy!>>p z%~o%^_p_HR-5=kal;anCxvTEinaJBetjpi^^!ulzEOED~gNI$k}eb=0p(Ia%{22`L`+eD&(py|8%oB&+{_`v0%py?goU-Oq1*eH~b~ zaE3i{l3Zk9y-8Sb^4|?EZd0QyGomvCu8DSii^%#mZLR;b8`t**EtI_aXwGddUhv_` zrw>Tn{+(52aAJ4<&3fzJ=r=13yJyat#dZJ2{rn}x)pfM_%9N0eTjmJx zyaFA98WkR0y?UkQyUn|8^SY|?#kr+j_iQiRAFMsUzgF$!#k5V6Kw0$BkDiTxe}B_6 zYftennj&eoeT&FX?(D4W7*5WUCr@6z8hZ6=sQdidUF+BX|8vxPoAu5+{x5gcind4p z1Q)RyE`3vdjs|UBapicCfn;f8kKxwY*1})g5_RwOviog%a1DM;5rg3+nKut+OY%L> zIQ})XJ7q2F*ZIX}WooN(zn1FDRUdp<(6OAGo4dHUn46pX^JngvGo!D)SYkI{Ut2ra z=9~VciqPO-S;L;MOSrcd-N<+rFQeR6-J*JZ-oHny*RQ{uVN>$KVW0l_#~%%j2?+^p z%hT1;(aFfn1>J*ibOZ0tDQ+T{!#`%-kpzvhyF8gN@z(vhQ|4dUBrhiU_IB^Ruuq|u z5iHA|IL_Hry2oO{rHR^8wl3Yn#lWzEr)OjB`cw{`n2Qj|3Ci! zH@FFIpKHCXd$OOOFRS>QoBk(H$}PV<^Zn`QlbTG84pmW8s-@R57~DB^f92I#=dXMz zsjAv_`st?~cP|GzE1sVFxhUNNWbL$NuYc|Tce`F^rj*#x2M-?nmap+}soTGQ)1Eb3 zwx}p89|oUid4Fg1`mJBhaxW}5Ikx^$!Rk_Q+gAwRVkO^ATTmA(MVKACF)!R`6~A88 z%gyt^3zuw{dwY8yWxl!9T_rmMbXJkw?FVnxtm)B}bTKg&_V1ec>_U>v%dg7>F8=xR z=lT5l%6ErYB_&s`S{1c>jbVMFBIw#$&?$KT|LXtG`n`Vj?)HvJlP2-W+6a8tT(*2! zr^n?jADX93o3dotGQHOs+V#uBvh9K=AM@dpwaTboxnaWx_x1a~ExsOq`}PF^P?_gk zSOZxcC7~`Ki&(0(J7e*>%&5f1i@$1}?UowWiMB_7wFZreYF(7@W?7%Ib$(FhiIj~C zjqXiadUWR-7Wt^I3tuA}#@tnAaLsXZHa-J136*)-5G zo&R1g@7p0H)RB=;pz-bVt6dXsPMJG*>l#kuV{@)ebKYI{HsYFKQh03a)M?YaT$I1R z=jY>VC(qbmxPkuTsyn${l5Qo8?%2RuQj?mcX#>IZx=UiTpQi3v8Ev3)_$qT=kUTE zQ}2VaQ->2`iBQr*r{Yq_#sB;-I~~;7%DzYUP3o2kaphDVZ&_Xce7V}Cx|WO#4+=xW z!zm5`z1QV9e4hWVF*Uuq$h5TDJw1Q@Mzi}{Uz=xTXLE6L1qB7w z{rVPt_UzhbXXlkGHB(cUf=*KeHNRh7;omraOZ|ZkuBT6*?fdph`|jPlwY7h<{wUqS zvo_~Q>|A&5T?ccXi5ch)rkSG@g2)Co-**Nu#gAAc1SxX688{_E4HTkq|gJ9B1aP*6-{q@&BO zb@z8)*K=F?_3?Kx`dYrL9g>RyRprI>{)rsRCj+jc?e zChKWUrIb@Ecixof?zkds+;%U5fnmeRuV24DfA;Lh-_~vao-SUTyxf0&;PyFo#qXAi z_b*+#v}*6Yz181W=$}1*K7L@9oK`do(3-OsPg&u^QKhP0fVpSO4M&X|q!ZQT~_z5rdxB7OP#{rJehhb2~JZ|?}! z{tKM5zu@D~=lxZ8^74y5?c2*+RIMN&A-QvZME1|4YyN;z^BnXQJ>I+4&9|)1D=9JA z2dcf6pPyq}_a`FD%PT7C)x^W?SEe@|eDL&ixN_RL&N7-O89)S}u7bsQScWV=)GXHT)lq-9@$u2O3C(Y;W)H*>HEovF-9d4>q$eKR-uS ze*T40<)amOb^8`C{=9wv@4Zp0U0tAOExo_D*WB7#+gwjaho`@%=FfEh`VIfK$-vji z=;`R_m>qcLmi+i+@bcrwk3R*Sg17G7yYl}()bIY;zD)JJoQeMA*WOD)K-*bO#O0;r z=FON9krNRd+->3QnCN&XJwGqA^8H_acJ_9$GkTvM9jp6xG`w+U!`lGwd$&{f2Jc!| z{Q7S6yP8EW-oE`ifB!$<=-YE8Q`P2te)w>r{{COT4juLWc-FE{avNfiPVX7Z=g!WD z@6Y}5?+L%RiqN-j-|GIHOrJY9_R(Xl|7I3uX5S9K+&sVL*G!q6TJtY${jJ4k|A`CS zq;ydP-!7z7B`Sq{z0m7vk+LVA8Y?Ba_uHwPue9BAA_{bO9XfPq z&z(6dSH65EDlW4Wv3y1Hv0iIy>rTs?jR$;!i$8On|F@!WXUx^msV-}lZY>QB>x+J9 zy|wGJCip6%xpU{feDkVLNNh>!Im&$q^i)=+#(VqhX7Y(Cqb@jE^knPW!^=xr z*?v~x4gOd(v)|v(mWL;Eu$B*XkWDV4i?_D#`gYO+sz$2 zf?w`jdTc{Zy3)=PB?g8A$q6MTUy9D`-|_9smld+R!;_Mdl&S)feb4_}F?06p-4`p0 zMfrCes@~f5xwBU7^sHhT<2NrrAmWy zR8(5(|#=X7w!wJ+MsR|wfQQBC5{l6!6r)Qhwm(`VFE+Y_Vsr_`P+UUcchPNL%2S2bTl-Hx z(J^G>hMz;$(0iul(Hx1%AC;AtxlBuYeaGjz(CwW&cPOs3-JJ4s;iX4&J3NFlFD$v{wI1VWd-6Vk*-7S)P2Y;I1B5wbZb5?4Tzd{E8o^e`t+{WmC;j9h(Djxy~wHb zd%*AVnR8U5&L%H}EOldGVAwEmrhi(BXUl}18IyF4mg*#(NU_#6y1Z#k@)fc7E-tgG z6m+NLt2W2EC9nDLE(TI}FfcHrrI$a}OrEuCfkLYmyX)_=q@I$y9HlD-)w8{IDnDGf z)jq3ZLZo$yWb+fT#hEssOXwh46?!i1yBp+`F-`i^8?8wbHL~lbNv&1-9PrIW*Y``~ z^F&20NjYKBRwK|Ed=MQDsb))rVpr*KhMjS7i}3n$yfk)s!0U3!t3sKfN@B;Ja2%qJ~b)-=!~>$a<`<@1Sc+gr+g?asoUxV&s6Zy zf*^}px-T4`d+3q(r_!Al-(-OgD3n{W;m7o4uVcOxsw??!Hodm#ipIKkM`1b+JZ>yr z>@;Cb?fNyzN+tV+)2oInxm{^K1L3f`!UmFQ#6SgWsZf;Lw^c$zHAVZI!ib z)-5e*-5#Pa>0+k$o4n5M%xCkyT|D*AXU*&#T+`vb_x|YtMxx>J5xcfU-wutmii@ny zl-#}AcJq^j=(GX`S=_oiUntJh-QIIJOX;+? zT5apsa(5x{8ZeM&bv)aqmIwwwE=Ik)-s5H2QJ)l*6iNNeMQH&&Zci0Jia=PWe`coW zwJlmj3p$H0mEN^Fa3lD#&THONF1p_NI+124EDe|0x#}u{l!CBMU+bf=YuDaP^Lu-$ zOzpb7NTb#GIt%Cppilq!%b!*zYwk-)T^5Z*c8r!Jfwt?_Bxg<}bp)Fi*i~LCUcyPJ6Gfb=2mn z_A%O{DjnD9F+DOT!)4Q)qV(6D&ep*hZ=I*efY*ZNsH87Cyj|To-#siSYSCL&_ol-W zpLuwB`{;U{yFJf!j+?c5l|E1JJ?Z-sRx&XhnA~!D-n(m|96Mu*C#;#MS*qydn_Q%C z%%&Qqp7Lr{^PJ-4J?$qAX6R^zgqu8p+-1YSu%U6&D&tfAKZPd=CrO>vSZras*rIgL z>%`m7V;k9xvu&&^Tx9LP?Wy^5H2i+f10RM58;_ltAS_tuo1C`BOIUZ^8N(&7V=kMR z+ILUM(P=E6YuKxl8kw2qt-G~rLW%7av3X})^!pZpGi*ce0?Vzh%)PSi>GYbmE%ng$ zy7~3{)kssxY(ql^28M$@CKKP}yB@K;-sutcGCD9rh_1{c_*qWP}i!aCeLWCbrW8F^j5;jwn)&S8Inhn zo-r)GyE`bs;}x^Fgg49HGmo4L)neI>U4UE@n(%k3tagki&*=jz{zP1Sb9g6v?#6AW zpvO;YFfW7LAV1ZQC(J+7v(UA2<`31PgoFmeZK{VSwNBredb;^y;JM1UxO?AzMNK?- z;oe2b?~@%AN4mQ>uyJ9gvDnH&Xy7jItu`uAkz z&Ye5I&Y$!n?_0sAhri`(w%nMp_`J>I@8Uuiuivk`e*L=m@yM*KRg%e_ot^$!5~t;i zCgt9mDi@~o+DrEEnuof1wE|qFCz~x&*((g&Jf4)l+_Zh#B}ML=5&!>xJNJ2apR(=e z{I9$&N=g%p**qprnc*^Vic3%uHyceK-gy1B-PX?T_x>Bl@0Y#Zdi|Tq`<_iJ zY`l7s&M`0-sX3}VQYwGj{%Td-?%zy17#M}7%)9?l@poCc?boo-_^Nk{S8WGpQih5J zDWOZn?dHw)ICRuN9a* zW5@b9-HEcd=Lg7LJ9FmDg$o~|B4ocgFJ89m*Mr8tGiOTvNh>M}Dk=&pD+`OwJ$v%K z-(0)mvYWq7|L$8|e>TWX{L|CT#hbXeK6PrCmM*OSe&COW^U3FN6V2w{+4Ej2S1f+M zt4r0vY1x@Szlmy5QLi=&hi_6~1k&?`A^6hhceA{l`PByY#<(i+w5o zQgZiod%fJ5Q#R(sNq1{Z5z(vP_TyK3ZYR5exw*NSSiN(A&bDVcYv#Xy%%H4C)9LQ;~mUHN8Y zdvos3wVFF^)~rdh zihh2Y$}V=Ee}e4o?eA}Icem`^ym|9sWo6~V%EjMeqN1Ye;^H(!ynKD{ZqI-J`1$}?9I3Qs%6K7?p`;xv-`LI z-_LlV>+Jm9`}Wx>U5aKEcJiwH_$f5B&@&}1CFka!8J{-f-QV~5;lqBmyxsE-?b}-o znrh-}_x9?FxBK$QeSXcZkiSnS&Y!+qud3>I&B+;V?(X+1-~VM7KE^*S!(>K_#Dso@WyPEk6 zPA+o&wEk0~E`pxRQ zO=qji=_g&{Cwd``mIKTxdo6M=8kPQDZ98AsgJn|W%zL$2A1A*NO8>nrm!03n+hy(A z-1>^wx%V$$uluw3*RCiftFk{wE+!wpdUnc_C)4BYLSka(Y&qw7&jfs9$mfgd^JkTs zgif7W|LwAQ$BQQ?gFQW8uUftO@};1w=O@2>`BFQ4eeJiO;>)In$JJ$CKIZm$cgFK` zZ>`I6lou60*RT0^biU8V=ku*^1jHXNuH)t9jonrA^vKEgVR<%kQqxjJpFCHM+oxdv z|Jd2+XV;UPmZ+$QhldJIobu_)OXI@pSLXb9x4Tzb+C1lkXZ-$s3m5KNx$@=}+maVY zFHK5%+9Y`K&6_tDE?h9bFSqyVr9-0AOn&F@`SmP5wXghp z+@<8xla&uAPL#FYmYSBb!rV9X|A!Cm{1%mWRw>P7PR-k~ow;3fm*`a~?egG-2FFFb zG<8qkOn7lSnF>mJ1C6|S!PMfx`=7np#(2ER{sL05VtK;|lyvN>t)i80Qhs)m#O&u)_ zZQZBUPZwQ$A>5ze>!Q?d|109|#v6s%V{bA`}=Hn3!BU_h`{k71gz;Po0t3Q(f-4HY6m(MM+Re zN08}sM9>5EViI(hbN?aQO$@9*qXZh4^JAGks1 z|0llFMfdi4sL1r}U%1ik^6gaDru$9qt+#GTrGC7#v-tU)pPxUAT9^JR(Ge4N@~L<` z+r>?J;`<+28{W+1dReY!Y@B?1+wsL0SFHb~U;pvh?)SA1qR;&BNS+iYIB|+f%N4#U z4^m6a%1&O7{%N#r^Q3=1?-G-?!S{-A8B5&NsQgW22q!+FiR= z?OS(k(;D4qGy7d;*A|M;oBjUc)@83_@7{g2YxU~cD!I3A9N>O)<6q0pe@`~+YcLiS zZMu5&!QF+dU0b(o`?YQA+uOgVd;*=Nyx!FG`*;47lqKPzVPc}9Zb}nnZ*Py?U*~*Q zO?~3c|L?B6oNb=}?CG<-`}=xtytywKb7Eojr;~F}9hQ>bUA}f@X2OHAva+z;T;F$X zyi1p=cJjC?rKF{tIeT_%dC9$fwbglf>-_gm@ct{drtnkIT;@=AahYNz(4Ed7(v%i& zd{JIAb;tjiSs5$T7p+_OZrZeKH(b_i*sx*aLOZG6wA9qMcYj~G{eI8(RUhp=cFbK8 z<9@$NO>DJ@NR;>>fzn*_5M7%%uR!B^Yi%a=?zQ4cg|3&3` zW@qN^EqHh+{{PkW*Vf0!hlNE2$JTznrmLKE``h#Qn#?{k>+*kp*4KUfylBy(43(g; zuw^|x`@lf<_S~takG~(&uROm*`|`0PGdDj!dv3jU`1*YxfAxR<^vMHs1Mw#z*R`ot z)z!7~wPx3h0`{p0_V)Iw#$~^rcJ`>N>#A$=_p6Staj-1=b7cPCFTJl;ttx$e&3148 z`{?(3Uay{U;!QaiyuYz8b}Hw&x(Vv#Z|_W)?Ci35@#6pQ`}6tv_*VUP@00ueRR3Pc zLcN(4`)B0d{`YD1`t$Rw&*$qsj^1$0u=|bM^iN?LLh`+>`yY2tnl$Ox_WIBFpHx6--mNX%+41z) zqw6}4MK|&`pZaMeA8X&8eu7I{cWO|a*JQ(c``>9Vto;U!57DHuBE3nwJ{@npZR~xb zRfMno>iWM5T5~r)dbKs%|NZUB6DK}AeKsT{!olV7vQ|3<1*!9bDF5{{#OJ<~-RXxA! z!oQ)q>i#`nX=!oYvWJhBK34ZrTd{N1noCYCA#)>hN=i7}Tticr{%WlJ8Z|jz{HpnV z8BJZ?UN@ye^QG%fykXbWEzCLVJ$=0dzjxu27a#3^pOk+1;gn9)o42n&S4M1Eli%3C z^_$tUrOQ@zCxorp|L5lX^_Ml5@=TsQIZg2L-+s5Imcxphrx`egsch@)JZWG1Q*=M5 z$#ndd`L!z{?S~)knl-C6cgz^Nc-pt$f^`kMnsnL#y=U<1i*6NwB44ZLPQK|bx zn*7qA%l$c=y2>HJD5tV<_hiYH6Gf-bm54oL`F-=|&E?N;TALZ!9I`JfD@{*HS+Zn_ z&A!stKe@#_R;=3=78!fj_Fey$EmusGCIzLXrrP~Jb2;YV692gU_a@)A%b3pddYSS? zm*dM9FE0L^Jo`%ix&8ll|G#+i=GBWgmp<~DpzPkiblI}7DaS1{&t157Z)4e}quh#I z+}yiw=s!7h=+N)!bLSP_lb;uw6&Ms8+<9W#+Xwn@Z{Q1wS--6bhcyqj4 zy|v@nvu71fdal*gzhAt_DEoFw=7pt^kowJ^M*CRpuHCwwp)+rZO8u+7O-+9m^qLwP zX0Cf*ZzAL}SKZ+L#P<=S}e8EN%s4hqrXhR#Y^+h6T_FP>vL|ulXKO44jZjn!?yVDcOx(HpRJpD-hDkP zq%YHb^xxb2|CJ|BdafUH=f;hM$S~j1shirRq+VUkpL#m{j?05rQydhJOx|5~PJQaE zNvG`3v79?Jd*)2fJ=|T{zP_nTRePnS7fueY*7a0|ySgJ-`3QV(af^}J zG+T4=Jv)0KDRS1{mY0mdX$2qhO6JbK8#DKs`pvZUzvX*bI*%s(|5g9|?{%Ntysvj- zCf+!9{CKl@b@lI(uNJcr3{NlxnhyC_5=gy7oJt3TuQBhG; zG--Y2CY|iy#QFt_i;G=ExQ^bpw7CCQG+A{YYxb+$ zJ*&@Nco6+@{{El3|9{y3|M&jT!wu@&+P~)?dbB1g=U&S5?hVVHRWY^*JoE8?s`=98 z{iRJh`=(!bBN=i}?5MQByuY!c+jJaN4((a-eTMV@mF-Fe8#ExnknmOF^{(=Kg=y2a zU#MTb|I5Ft2dC|JQOWgmx%}8T{_kT!C9OL#0reZyBI=eT=e!7;6YHn#l${-27Z>N{ zb?R~S_MYQOSzGo_x%6o{6g_(Yqb9U{hPo4v!3A8Y16J<4G9ko zO-oH}by|3=t!?)9s9Ceu>#s7fw5KY#xH`*+{+!p*hXO?=@6$L}m!b7gzN z+daK+W#>Ly+hM(=>(8H>)XjYx_b%f9e!rzPa^j7k;Kw@GgMQxacyaF!n`HXiGhg>u z{JdtXx$#P_V#}0mmaY?SoNQiJbK%_M)f>+!=_|eb6_@5XZRP2!p6W9}_o^~5FxVK} z+86bNW%Z2+h4X`zGy_HcLrO7rfZ~$8=qhD5ql6$2a%3 zYVU|I$~v{tplO;*SlY7UsUHsYi~bQ?GjV%iM#hTW%iBAYCZ3qL{8_E`ynDOdEqQ7r zAAE94zWDw}*9Ilysne&=p7!kg{LrQ525NPWo=eSq{Zn9CzGdC%>;K%C)2FFZ zZd{XdE-(K+J-)uW;J>lUm!IPCd^|il%D1L2U9ceGbh7mHE8L1lrk$PLu_AxoR^!iw zufEI-kFPwrY0a)(x1J~c-v43VAvc%&e@D+>dH>D2ob4*p>TBD!&6<^^cw|{`@AY-2 zAGbf6x%|7UvY^td*YyR5E8hJ%I_uS|0*jc~(4Eg$-aXzoKj6E0?wuXU$G0W?yl1CA zIdG!6Z=Iu~W96aK_j$B`>qaQ&KmPbwz5dg&*AEL;>{|6|sk46FpOee?G5wxjyKK{@ zrjBLlY3t&$jlNGek>aj79^NcEbLEpKPny~1)xQ7Be|GMySyEfGipoHD$ISj5{&ln4 zGb_CytL{ZL+KX=3dugq;zVDIoS(*Fi{x~(yJ-fn0ug*1y|G3mfJ9u)gmPl6V4Xv-x zsRjf2?RKxdPQ^?Qedyo0iKoq4=3^yxEg zBezFI)v}(8-|^wbvR+r$R!K?8{eOPWo~{@F?%hjWofG<+dh6D#5pX(l=1fd()}qvl zx1ZlIWc~TmzUu4LbLY;@n-}+VhL4}$vZbQJ7eAku)zHz%*jHz(uD*QJrbX-4P3y?H zoyXa-%fLMEj)%AJ%z5)Nv-9KQwrG2M6$!<^ym0Sgh=5aaba0? zS$Z!II3C@)Y}wjq^XXHkwK*-!y*=;5+0$=dzRS(c_xFklj|vKk4xT%4qNB^^&6~yb z;zB~t#qZcrn4Iic`0>}**Y)3?+wUz~yR$w)!M3)xv^2CZP!Lq{)k;^)4eLL5?%cI) z-)_x%Rba8F{CqI)*RLBRbTl3uTK5hV-x!6(oyf4?=L2~B{zaPn?c4`1LEh;npCxVX=##DSV+W;8#e?xT{>25 zUAuR8^+eU}cGnKYoOe%fUug1r^9|p96EA!Ud+sMz{-kxH(xMHUww^Iw|NAJ*1}Vra zS3`T_oXzY1Jq)|M`svQzo8L7>y}0zZdIbetx~4n(v7MBBKWpxq&*FM-DqneS6-qBE z`t+ky_+XcNzpQ=9i`Fk+UmF`;`u_IrVR`VGf{|+smU+?Im?mt&gPYDT+)?K=%;%8QT{Qa-e=Aag5PW7EBmbKsh+}&Nibc*ugC)7tOLv!7mpwmw_N=UZ-6Z~t7n9ZFsy?>%^nBT}Wy@S^ z+tnQDX=&%?*lw>%bBVFD`ExPbzAAL4ptRW&fu}2eo9Es0irT(z%a$YI|2|FCezjxQ zqeqJ#JyI&(zjp23MT=@yu3i6QdxGws-u(T)@Ab#mF5S29+@>{$nwkzZG2Opp_EemG z`g>J7a8B*~J%8oAdH4SO*>mZV(0y-H6O)=RFE*yOY!Q1_CD-EFztnD($lHToBW*-~ z*JOKCc9q8+yQDku`uQS%E0uJ2r8PQ`DqfE7+nT#y@?LK(k4ih1{?1)}xt8t6|Dp2_ ze0=+nyQI{zn>%FP9EG*Hx%+>*eYFb`};Z*fy_U|Nha_)z|ay~(yL+Qtk{QaNv?%cl`U;p{-%HZ^h4;v%a z?ELwwwR?I~t9VEJ#0T3SOnm&8pTGX+)$5CslMh~IZfke9`~9bT`@Kr@h-}ZrhWE>B z7;BziKO21FXLVj#UggHK*H7KuUEVKeZD(YZbu6VSZQ0tjf3NTV`S!ru+nwJZ2_F17 z{m1`igMUK)r~TxTPk+DY%jU0hd+O(p4-P($V5-c#R+YKi+skuXuD{QbtXEQJ6lX!A zsDa(TB32{c+wY?A&XYH}b6H;7*3a&Ely+s;&rJ9CH%-4BUb$$IQu*Pw&d$zv^X4sF zxNzzuUw{AeCr)h8S#7)Fy_%}!&MjL^Y;9}P(su3M{hV<pw$<4&2bUneHcom>04DmW;p$l}es zXDheydTHuy7O8m`uKF@h~&?(JR0^Sa|Fmvv#*OsOi zihq?wIeJwUW>tAcy=q&Mk)<-{%^R^f60=_IH@Q)|DgIVbQN^yD{6vjMo_0Z%3!cQq z=d4j*sC-YJAvZVI#`~O?p%n;7eGkk@TJ-bR_YdYzoR_R$zurIH!GFR!FbM5Z7tG4e zj;na5Ajr$#|L0lx{^$K>xp!vFoayQESZBWZ^Dytzr`R@o-EV3?ec{4|m&T_zJ`s}X zW!?99_3_$sS1w$*F!O!4ucY|xu-6wmW=Jo+9;zwt^~+4?75CH?u`^zs+PFzad&fJi zHJej*W^V~$tJwQU=$j}cHDvQ>zW>^H|F!IU%e@y2Lu1u{vFY)P<()p8d&civ(WZcQ zrEAajuh{wL__T}XRF_w?_baX5!t^@u`LW*F?Qu1Vs+N|zx^JJ?{}g{KE4w`^YVzdC zud}kHUcGi&C?Hr`V&}7%x51tJVXRcD&C&&dPs0ko$#LzIIz1&l@?q!QfB6T=g+}~NJm}jhcH5`p$va3;*c|fV^Y`WR7d*I~>A=GqAB87R4vsdn zpEi4U<9{(ZdHMXTEWUZm*bhvS*j?^Fx4ba@1N&G0^*8N3vTn~WT7Tm1TlF)aG?U$C zK8d`u>r&{Qo)5453m+VCyexIU_=La1oY}Ky&zP}dtvhV6f`Q?_c2Q9g7dO|Xpy1`p zmhakKy|2IhIOB#_De39=GxEIr{P+en4w<~d9 z*6Hn^FI9ds0*ZE^t!d`NU>JfPh7*xYhPGIQ&P9X@HSVlU6UIko6f=f)qKv_d<- zbm?lIwB34SNkxA+wBrCWq@iL*JO3oJDRZP>>CgM#bz-xNcj#5QFa!T-j|(i*6<(#a zSTbI`V_5&{)P^k}^$>iZhGR1S=^C@+BCA9r&OCqQHu+@B(i&~`&}nr~1k8SJshEA{ z^(2w=PoS|2($vt=v++r^_tJOVCQvHK;F|ZW8QQfP3!6Gb6e8Cr4trvGDt^4`(ba85p?)zU_n{sZ4pR>IZARd%9 zO?Bf+0k94*!7?F8i1Vq1;rUaZm(PiZZu}C_bZ2RZ-z1&4zLjDHGk=GDSmLy~b;9$O z@8J8h!Fm`N9xU)zEHR3nIW@>d#An+%@xYmT8*0iG3JU)ApjknG216j~o z52WkC;gh%4nRD*)T>pj5xqP`|@$MG8H5cj^C<^|Z7N@DRO{DwAIp?@YwrQ!5js{2% z!-5C5f1h|G6JpI9TBWVodr@W2y(#vLV)c*ihIokGUU0(J_+YQ$a}$@&s}W%JVB$c3 zzWV%4v(ETAFEsStSfM-b%UzpGC%092CQ2Uf-oCbL)?qGL_cNQqR<8#u2NMqj)pktw z&q($%==OT?n7h-%D|7PW%8B}ir^d&6O_e_VdB)A;CD)rPmmoRLfMu@wWKr!5zm;zr zcTG`k*^qnwX7j!5@~=~mGdwQ3$93pu%N=BAb*p@;jMOoox;v=r4ok$mIq#-DP1$X9 z{nf(qg`$EJH*Wlq=lm{ZW64MD>$YGwfr$^bP3w0Q{Y%nbdPa8h!3lRuT+eLv;yiCJ zG;wK+uJS2e!&vv+V3AAH#4bUngTT6cHAFT&&ndQ26rA~(rFY}fwc6iZoVIqH(%EKo z^vqTdvmo_Q_qg7c(NAI8F<_ zQjG3jIzesXG{KPmr7Dm6G|!*D^t7dXsn~tT7ZTCJlQ#xvYfW>| zDUsK{e7SPwONok5WNREVI4nR!gL_YgiIuIbsj2DG9GztSnV*@bu3hq1RdeadQrEOp z(TT6qHM!61K6v5oij0|W!jGK^nk{;Em2RlI2$yGOe{WyQ;fEO}zaAVzn8>ikR%xP# zg@}~2tZ0+d!U?y+J)?c3HOFfBFGX6^3CYS(qS z&+K^Hm4$_czq`2~ekgDaa>Xvli41=dI$e||dOW#zKc~VkrIdu9*FAmn z|8vjJ>&|OEnYrOi>p3p{!+V%k>+kK{;^CDU8D=82w>;lxl27#fJWfMn>+IX#y7=Ko zeKIga%#N5Q%GZAQ;fK8&FIFcfU(7I(;hXH2xAd&)%6`p~Sl!qIHDBJdKDqkUuyt93 z$|8gB`*pl;Y!hi(BI4$FGj^4qhRCF#zP_F_XU?qg_xJbooH=vm#@y<>ymRFdN??bB zi639%b7^7eQ4W_I|xEWQ|^;WF=Q@R4&GC96LliEx>>H2NTG%pW;@ z$uP00+g8t6^s2z+ev@9&r}OQ)r)SNZC9}s?vUgqd^f_}TO_?-nQdX-@@a4|)+fG`h z2fhv6(#f(@@%3Txv$E;YONw7=CR;JqzHpZRb)ntv%R+u6=3n-8`R7l*TzRtdWaq_+ z6JNg6REpZJC&kt3>!+>QvQI&C=`EWR*KITdgM&ES?{AmB7-R9#`0s{s{+v|NcokUfq&AJ0xxr?_QO%Pm3<5 zPkz)npO;Ti)A4diOl`3Dq}ey(UQPUTRKFtri>!a_d&P^>!4;Jo?E%O8e}lUlpzWXi-1=-H)h{Ws}zbcG~fg`(a;$-h)ne`>!Ee zbe7LZjkMxfIAPuH=WZuvPY&{Wf9J)-iOU)|qcbw^f3e&?zy2TV?QNl{nz4$e(_byq zdUg7l-d54nXFk8qs+B%G)4ob+=_ZxX(yOYO^QxZyv`$&Y5r6({_HtI6)|(f8eEAu% zBlOIg7Z0w^ez-69&DjlKS?jImmiPHjt>j!1qP9TDC|LW(jLF*#P!kg*n&MCYO8MgX zTl&|bnh;*k{HY5pRd-A&nXByoC(0`$(!5U5=GQ)k6OZ#N9$nx4f6Bg%OIf(jzwG1m z=jfJLvuNehDG$vbi+(*8&aVV{MnkE+(I z@7cWWROLMn+n$tXeS3ZUD&L!8bAP?XFQ4?l`i6GJuUj*%6l>M1a{YdOX-#jPl45$| z%SDS+Cyw_P7NV`Y|9KlceX#Y?casC&vwpPdi5gstk*#YF=h6B-ZlXE4x~IM@_|+DQ3mI zC$F53Aeb4V)P8Yc=Eoj*m9Majr_e-00^e4)#d=(WenOpdE=YNGg_a=XE zP2HoMFY)=OW8dwikN6{E_lRERPJA^htmc=R-(&Nc`#!&N(_Qd}{~k}r`Ts#1<`zF$ z!}vKWaL<Na#r~X@m2oUE(XqWi}#<|qmpUO#c?d&z;G<+;06okK%IYl3Q*b}o5o zJX_)(+xxXE<&G~BxhI%9J;=Xbigju79DQS-bH7t|t*p+7asKyhM#YZSm1%cnQ-fRm z+g?iLhphaRZOizo`Doe|qxY+~o4ntYF5vTe-=~@vDz`stwCpr{%nS~Fw4yZJC4NTK zuZb5Qrrr_TQFmaOz?~09f~)M8W*15n_Ak>v(Xem1zRQwn|6V8-t>u6JgG0>Cpsr50 zXWz7~70;hb=3Z-hH@#||xiMGKA9+*dOVJ1IcgxjoUO7SLciR$k`(2eOkCM&i{Z@Ig zg46Mi!RM7P7n&D8i{XA4ou(Secv-mg^nQiYCtlTd%sY0Ld!hA;woCgT2e1qD95L3J z_nxu)R7iNzv5SxIbH%?u^SAPg>h(r!$%#KMUVQP-ueJrX2W7O2kFR*Se3`D&qhIq< zUd7x$az^XZ@_!yzd=+CNUp^@pzqiXTQq-7#YWHll8FufdT=*rndPQ6Kk42w)&olj+ zwmx~6-Fy{cla(Ahrp=2rvV79J<=tBC)G0G()w`6Ges^IAjkp_leN_iv4}bfvm1+(g zj=%o5gvYZz=I2|ampM}~;Nk4*cg{D1Q0jfGt6_FWxUw z->_xh^S)gst0#0!dHbLu!X~ZuY;v^2{mYSp%gzvc&!DTub5oRqj7o^@V5fo7)&aOZ#y~HeTb6=5_Pt z%tc@Od-$3w{ydXr!j@*PZ`h}x^m2w!O3KVB3UB8Z)H|QqY~j7@Uo*!vo)^EZp6-+s z`To_Z{e9+?*cnM)^LN;Z8yZ%~@BChxGs%NR`qADQ=?83s<}LN9YPuT2rL^va--cfq z>y}KZnzb~r%Q)km@5$p%7O&@p6d#EatlG9D?`S3WR*`(y4{9ZURxOz+RPXVmQh(`8 zhKE`+#d@c79ha1}-FnQ{bm8ZR6ZcK{@#a+=M_s%-A69p-+4tlh!_i1~<*UN^izm&P zkaxS+{eD?fplgV7ROBoso|mTS9vq35)gOFX=KTmQZxvW#eBb+ekx`(e^-)Rr-1C+} z`}}skePOjM_U}ZM;47j_4uv0G?CSDoiIZ_w&Lo!Cd(>qvo8PSzp8R0*iCqsRnTpa5 z#U5Vv{PxTW+tjuO@+V)9tj=DSALsu4t>B?cwT6kieOLCU+0N^` zd0qS^A3t}H*U5YQpZ29pdg*OD@z3p~duhqhRcRvF>frnB`vl%aiFvwAQ*EhF?dd$S zbA8K}W!FTV{wk^-{VE^vXW6b-9ltK$`S$wr57y}WM|M4U@p|1)!^GFz-p4i12y9$- zXWxu>v(-W_*VLRb<-fXGx#IZJEoXmxICM#pHGD?L5pMlGE95-h&zUh>&8X~la9h1d z&ih4@UV5ob7nX)}oSWu+nQM07CFhlPpMDp9@r@OpTc??8w&q#xv_HJhvK(uR%Ic&X z%|jGxetmq{yfWVOU!Rv*ddf2wU+vqIG9S!s#g?VD7wESvUZC|V{_m^4RjR(-BKPGt zeDUR1(~@0yWqa?`Wv@Kv8pcSZuHX0CeuYGYu%E{+-R0BD8GQd7;+ZAfZeFK%u5HTe z-Thx`CtZ3XUVM5+Qjpi=*xG$+U$)LP-R}DFPVxEK`(8$tUpd3G(&CHHZe_itJbwK< z`OZnMR&AdAR#y4yy69H^Y5ws$?52NSe)0Ra(>xQp-+z6&zNzz|NWgU)iTAbYd&R5m zm*oCl)-GM?r+x3czi7dJ^)>xM*doYYr8c-Ou)blo5Z|S(>srF^3(v07vbCG5U$=dc zz`AV3r6K=%1Xj&>dfEKZo@vucoK63VzROh?GPZN7_!1d=-n2W|WBun;F81ATCV%>B zdq&OEHt25H%v($S<1;3ourXb`YSY1m-|u}n`nIa~mDApWQ~Z}6>s7dZ=3?8mYMttA z&d7TX5tLW9*GBuQgU@zubCYjv0&odOI!OgJ0%)Iq5rW&ee>W?)#xD=KgKd z=WQw5M7r<4To&c0y3}N0VX7j__Bzpb174_)q znTma*|*h|Yt&$emmIP&@Y{s%Li({65fG56g} z=_jS@OC*z6JG57R=s2-0S9Wi-!n%DwU(_C9Jy|`O<@CmUXfoq@q4S3_`xtU?Cp^?>t9vHGF@M1#K%|phgbOIo>Q;#ALno! zKdE%-*tA098LcUgzVD1$x2*GE^cne{sCLl{&p#fobx}LCgVpCN>#ofOuA*5hcI{HT zx59GKvg$_1@3FgmUwx~XoW>!eX{X_q>{weK(6g^9oMrk2*=;&<_WVKL-32V&dAY(u zPkxSibt%((>cmOs=ZJD#>XDeaSfcr^Vd4jdNLOqfw*MS2wQIaL&RPEP5BnptR?YKw zg)~E5OAmi)dw=oy$JaMv>Xl#2-*7-D|IZw zmTD>VHaabx<;lS>wsdKFhsE~={CX7|nB$dn!&r|VKhEHA{`35Aue3NAc0ADvT*>uM z_J90Y7d8E9OfEJJI*}W<2q@Gsy(n7Q708^E&#-OsRV~v4a_kNVmMl$Y$Ps05?7ODV zu5jYguTTaSpP(j*g!e38eh6_+W|lBx5}4{ye5K)GDMOyuOeao>my8?}o_VD-1hO<7 zY;AQlI^e;3K=ZZn+&T3bXQWa}Zbl~j%EWCKD%&B!c;WD=mCz^1cWO&1H zDtsLe|Fu`a!kcDpV3D1#sq=2;^jXtacl2ESnSEuar=Zo`xj~*8N)2@kS2e=fRKLGC z(S13oDsAFPXQ!>3gP%V=m2!7a$ZRj!ISWqLuG8wc{xNgj9t9i50}c(_bo4y0JiWx2 zrRMp)??uE^D?88I>T{>6cXnO><~&`AEvdzUh1cbTli;TX7Pl{6V4SEY#KtM{#DOnd z_R{2uT$~abijGRBKB!Nbuy}{LzJ!p$gvBggHE&$EmWQV}GqI^oSS<0gf`P5I!;SID zg@#6%Q}?nof5`HP{9mQ#D##VU!q)Y_iPf=3LUz&1i=vWW4Q?)cBT&X--DBIaZ2@zJ zy;U3E0_K+tx8{CZR$H~}@9gtc2X-CUb$r*MtmL~hR?IkDW7yBJ_##_xUU*STt)1~( zhuxRwl^DGBXTM-4aM9@&)4DGOw`TJ#a=%!&Mg1-F#&yNK|JMHPm$bXRtM7Q}<4Je+ z-EmlVdHT$@b8YkXY87ex->8_oK5}oh=y$h$YxMu+Ts9I>{N=4?+JDP?Ymobj$yXRx zF)F<>xau)?Azu*h{94!j&5nNgTUkylbg|=F@FU!|bDbKqW!K%Z9kyk^7xb=tx-^SH zKz!vggRVI-TQxkEYE9@?ntDmG+4WuC;XRF8zVJ-^mj0?$fQ7-S;#Gc*pU4CK7w_KL zeJ~gMth*tf?ZE3_(#3Dsc(@vcFE5c==F)wU;Q$lAo4^4X<^*o_9fxG&J~%5l3AS3O zD9Q>exax5oOfXuOX!b0Laaw}vwFG9fMCrN%awZQL`W}eSIaV2S(09v1S^o>2;T8S@ zEbRsgXE=%v&Dx+I!%=={Hiv>!r-V|Yhq_UxjFV?ZN9K|6BTPw>8{2MpToJMt`rWB~ z#PbnTVe<}e8?|}D?>)MnOlG>&Rie;7>0XL}q_5h<$0ucqgd*LhP3}ISwW;ln=e5c1 zCoVq`-PBv-R2I14i>6|#^Uk1qQ)YB6Hd>L>wJ@amQ@iHz8tpY@*R;)M>!w(5a^IkQMGh^xJNC_u+>#ieoJP z&9UffS^VtG(>2fDJdt@8^JGi$y%#TEN507jvJn;R(d)4a< zug`mZy7%#^9l<-gch27Fd#CtL*}Lj_oaZM#KkxnM>BqFst13$OJl+$%NBq~XU(8=? zzZ`#|{U!Zn_{;a#>=)LD|JS`g<^37)&&NNS{&D@Y_D|YB-hbT8%*^b~4$VBwTMsHV zM>Q{IE9bc z&=Y$n7$>^#b@o;B73=rB|Ff^OR{vY=-SzeR57d3C6a8EEb@!$Bb9bJwxngs_W@Tmb z&s^?Xhi)eI98Kx|Dt27g>KFH~-(RPHTmNGJ^8fkMmMq_G8HnYuq8^R*iZ?Mbx+rFY-!y`mtm5{7(>8*%cE;llA z%x=xuT4{fwFyYeyOXhOkJ-Mehf8BO=TWsR(q}!S4x#qX>X5Ho6egDnQZ}-0K{I>c{ z^xJrA3#%noHIFYm_;6z5{NyFcGavIEkM?8pTRcb2@~TCw+!47awi@*pb~!$u>zVHV zJmz`U^J2Xv-P5}drOrLwdT`A_yXL9Q*=+H}Pj|EJoVMd#!Cq?@3zf7Ja};@<=kaZo zo@H3_^1`)+^Y7T)<+@|G`>sryl}^@;If=f9=k2!M?R|IkUHxi_ik8YVUoyT_nB7U; zQS;;1!|S$ZZQQHt9^ZWQ^I~?3_~X#$Un^SfcAOE+c8~ciR&l&q|BKzj!=E_6&3svW z;Q8A1)7RfB?|&a(x32DI-R-|}y(Kc5@;fV^)c$Y$C-lGfUoPXKhBFQCnQpn=?3vWF zO0rb{f?0sr4%H8d7ZxnovtX{HfAig@nGb3Yu0Oi((aT5A1hiCamMA^RS&^Ah^kUWp z>qO?mMTg2-O53X2{CV^H5?o!}b$WM*Wr}L{uIYW#BPD2R`zpf3-pa7b_sd?1=Mrkm zGEFS4vc7z}xIO7@^3;vIg&o~J(Q@V1_YCWT{+v&~k^Ja*NPp!71D(Vur|dLVFj!o-X zw{c-|cweskbIZJUJ61oIJwCn9-tu6Q)4`Tz;a)W_wRdMzQkSLWo&TfIIr)mmu1!jt zuceiG9laEKNqv*UO|F~CJNMVj{FAt?{@bQE?w0>7PZ!HQ?>n{j%-ett(QJ|PpOikC zJ=uG%|MdM?_hTnSZCD+!-e7aV{!1Y<*V}}dELgGSMbjx))9|ZiC(AFL@|^2qvU%wY z4Y~L`E5ufWzA~0lKYM-FZdFFrtE%~G%YE)eX9ca&u{AzgdFqcQ|LH@g_RaV5pX!%8 zGtD^n+m_vzo0sL!aXfQk)_a8{%Cz&y{u^U zr^u(@_w)U)Iv#U)=b1a%_kYxGPL#9tH+=u5rvK;a=k=>5gwBb2ux&xn!S>cmt;_ex ze#^bO{ciUr@wu^YwpRQV`X=;r(rRya-Mib)q(t7_^!v2C{`z>usKAYno}TK|_7CG* ze`iD2cCXE=)@m(VRk-!;E7jHZYfi=%FSXiHbv^3z*3Z}X#i>V^7uG)bwTm}QS}dpH z``kynUrQf0zjoc?N=RN(zShkz3B{+LU3yMrqeS4c~j&+#zqHSfn zpME=PeL{AYY=3#*?aF`c6Xc~{$GkRsC-g3AgY<6G-T!|Wem=gsdeQeSZ@%7({yzDy zfA;s8Z&$BSf3^Hdx!Du5EvC!N<8H`r-M{qY`po<1o$KyZ9eC#O^`ITQxcnnoE&D6A zJKhw8Z(gUWDN^)u`ss<&{o_0L z7Cp@RboKT1W3k!0^>+Vz;dZb$egD)y-~K&Y6TK!{bbD`p_`QvLfyug|Kre~qt~V%j^9>twES*m=#N)_Uw4^5%ip&5 zYu)W%dSCAz{yy2hz%Ha#=F7&H!C#g~-)+5nSBq1bks*NL#G9N4Kf?|v$QoGle>j$P zzLJ5#soIQn%YVmzyVu)tGcoLGuwvk3ICA#DyR-ufB_EhGe`J`%c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+ zWN)WnQ(;w+TacStlBiITo0C^;Rbi_HHrFbz*a{@9ucQE0Qj%?}ION5ROz&_dt9Lf_C>*U-$$#K6kPNC66z>=bN@Qqrt~ zT-=~`6{V!vDrJ?$j4zcTpGoK zirfNUU$`Au-IALNx1zYjwX6ic>f(^ff>iyW)Z+ZoqU2Q9vedj1WhDhr2v`MVR;1=c zxMb$0<`rk==h-S5Ss0oj%S9r|8JZdzfI_yw%DE^tu_Vh0T-w^?u7yf`bZ zde>_2l9gvpomz9I=gPvZd~B`(*{oU`PR#GVw>NXBuV9$K^YgEc?xlwXJM8NjjXpfA zeP4a#;bC`+K4p%k=amc(D($9vxh@vmecIOAn)`I+H+9Fv#gByyi^3~kyln{a)Tv$) zp~ZLq&*W80bgmS12!E^jX*~4@LvIitL(xtd2DN2r*K8D>I25O(9y9*AV0MFm6Njzc zsZ)10?33tyQW+fTsC-Z<*CE<`vhg;9jo^%j%iU9c#^smA zNX>ZIsLqxrelG*6$%)@S>W{+YXzeFg*L|6_&w5p(*}TV>1T#&}JU41LwmHw}VB{G0 zE5diu_qaZgV_F29UTk#vWW#@edCB4Zt%bfxPb-8O9Axy$=1f1^SNPH67i$bx)8?3h zX^+Jwr9Bp`%WKNERgeDm6zZ84IqxL`iD_MIoW|zHSDT9jzZhQMf2HT^68U4we~#K` z>izQ+=3BPa;;2&7+nCY`62H1n&U(PYccHNAIQoB!3sHwid#oP1h2-QS%Nz8LXIXcCy4OlVl`OiJYS%NTc2ud+r5>z|j^nsIwk;QEe%qQ0xSsHxQbPw!3AuR3+ z^WPS^Cr);67i~2!6!e2S$?3HV*Fx3vpShoAb+%sg>#>9xEZQfME6k!O!YgEyQ^=Y1>iZ1e<_gw6o z@D3d=s7v<#Dk)C;?H?as)u0NoFszJP(5rMEzf<8m?ige%!;dl~0FUwgFe?N?D2#}5p9n;-M9 zI>>Kdm8dM6tM}(8i|g#)-*ePCgZ8wu*Oi^Seevq{d6(_VzdUH%ySwti{y)#Y?DW3Q zxM1bNUuVPPSQ`56e}B5QcH7nXe{;>_*R5X13j*UoL7%L`5>3y(+dT)kx59Zm)o$DH-+FRYpxwmDEO^~muzx8tNcj~%x$ zPUY*KAQKh-P=%q&;8~2L)q@xfSr;9bc@8#)rx)${a%W@eclF?v4<~NC{9Lc>JFjR# z)b6z{i#!+#ta6+Vcm{8AapIQF-Zy8NW@pPZmFspzk?U>h*R0$arZ>5>JnweU{`BYH z9>>o+;1~{x(M>Lk3>EJSGjKF%lD?9rYf;f!C#oQmZJ~iiT zs<^a@?W4{7D1|o*HBY@Q+Vl06_p?QFigs+?vhD6ycBZ)b`RZ~5Ahy>eaW^PkeWw#kz> z&%VCOT~>F>3RZ@B{^?hk9MnG56y3>t`{S>?z38^rt50WVuezhx9=14a^%Q^m(g*YF z{s-<;-&3>r>8IXlym_g75z}sNF4lGw=yZ8>>g#RuyzPD!%NP@$U;A~K{hQ>MTS|)` z9!>At^Znt+-}lWR0U(!_Jb81})}o~w&o2GdrfzU6CbsIG(s}OYIWKQ*scik)KY!b~ zd*AJB{>}bw-*x;kL&AmE?+&|0PRm@eHYGCct#kO+wF|?PCNem9-@fa=-$v7AHbcSN zu-hv)i(B+DHwblC&J7p560%Fy?DVYmow3_yd3|q-5rm|Lv(A%RuI8NiTe144$0Yx2 z4zc?(niMShqE`e}=hseQzq^4wzoI0`PUM;~kMhKnvVGqkUA{d_O6cQ}|L_0*IRB_Q zSM}NcKNrgz75wJyEco?Dl;Oty^xwwr{EX-SUw;38$1j}=cW+Dczq`FSaCOEkKb1*w z^Z)-ko7(1fRqN@wwY|CJyKOG7uI*eD&(Sa3nQ|@odj59FFIHQlMETrXY>)H3wcSzA z&oF0q!PD25#gDMd-`V~7#zf{v%ja3$sQKYgY&7#ve*OQ|+v92%t~jBP^44w9#oe)c zz1w|G-|c(eCu{bi)M%v$!=#m0?#%iA=;>?zln3GvUz@(%`f81qqh??BTPX?I`HT$F zof{XfnxgbxRA#EDFT%2Zi@%Y=99x%3@T>9kxpP&3& zq`v-pHuwL-<^KgZ&aE#wH1lSOMO1KT-M>#;Z(7d(aZ}%ap0NF%tG5a>{>yc`1idRu zWt|f$n%d(s$wMXYUZ(%{-er=VElMZL?^T7`xM@xH+Mc^IJ@Q%j{@(_hKPP-Xx18_& ztb$5Br(#%kj(Xn@XG<=$=Z=q zR=p~_X_6(%a3bZ>ty7yq**I@oRrkwsuAIWP*6r{4|BvoAE}Xb~uI=@F{rz00-^|I+ zIrO;bMpw5lSF4Q(SNc3HO*7^LKU&naQUKN99}HUupr>X_xE>IQzPd+ziqucI?8&9PIPQ&Tx6KmL=V0JlD)H}+phRYgO3_(!|Ux) z|9_kmKXk5d-M$AkFAm&`eWd)G-JQMNUDoXNl{05vX|7xt@Z-!+@8f*(6TBjK`h5!#HATt znt1W!|Bv1GId4Cn94zAc_V(uHWg6QrE3(WvFK@jhOq21!vA5Uk|GX@Icp`gyRDAWv znYPy3jf76Fd+S^O>&@#uzquj#;dh4Z(%g!9`>$Q9%qU;%q<8ks9DeupTT9mMPvSfO z`FhkYzBgF`n(x*&TgdmtWxuStaq6Sasc&bVT;rE&pTjrM#5MKpm8>h)+s%Fb zeEa*V%^ojOn=HuS^zg&S^?qI7<^R75Nv_@Mw)e&B3IBh~*H1R(*g5I*^!y(GD!%vm z+oHW&b_A+TwURYket28@^KIPW>*m{3=dbzy=4dwi_qTysPg0lqMQ~VXpT6sK*l+Is zJzxI3oqP9D`}XMD-{0P3WQfZBr9CaFSdgLR@Wk``EtTy)Eq)x&%H-Ikh6tODjq3Lu4sFsnq@*!3K$xLJUFTlQy?+Pa-K$HCKDEhf>7_(%!`VH4yTAUv zU-#Jl&lmYkY;5K&PI~MN^X)f$d9t~9-b}ZlSr8kyb z&*W?h(0Jl6Z|T5L_~^~iGY1bVCvUwf`e;p*;{39dlA4>7(_6chlP9kX=~|@G<#m33 zn3f2`gRj4*oBepQ(;L*ZS8Ta(SjG7Jr4`pZo~JN5IG1V)DCkK|`Fe}n+$u~{%0#{| zF85{5y)bT@n7x-x<@@pyHa|an@%7rfXK!aQKB&t6er#UN;tPjz&iY(bNX%bWbz!oy zg}hbu$Ea)P-tYNY6zse2Ts)AJb|LU+Et zF_F0}o6}KXcbQ2i^SNl(AHk-nw~1HmBgqkX;A2Lj!Z! zBa6B-llMj)(K=>pEVI4rj)}n|Nr{_NEUOp{Z0vOXe%0QX!2NTJ!mSFSZZ=)*nLhfd zo_adl4j0NWTrgRBS?^T&Rx$nfPZgyL3s@MYEj!25;5R$ANXxzcTl4n+U-$p`Y+wET z_Gvq7>*uTtO$t-Ec2?BiKVZPX5xF(2TatmT&5bLYf#FQM6T^bg)zgn%3Vpin)+(d! zohu$phV%}$czT^_GipzL`&ev;>@=azQqIBt7Ev5VmGjsYj?CO5k;inv`@EfNpa=s8 za|43_2Mc3^LPu`z*GFrvyjt~%>72dwb6rid)l<5}=UdkNS$%otUw_$*Yp=I>_ut=K zdwT7*-K)>5E!9|cBE#TC=~?Spda?U;>%7(mrJefOt#_h@>G zQKr_^T{Umh7|T^=%$m1#YJ>>a&(FvCYD@maX?@!4FKba$pwAGq`{t*E$Kyq6>LB^h zY|hpj8}{x~TEDWD#qmwXiXD6g?`GcJ)7H6mQ%XkPk?z)e>{|>rXr6g;X3gQBOQx=1 zWoV7rR-E0uL3iQ>tF^~6x8GbN#^9kMR4)E%6JLLCv5fnqC-Y*X4?p~{^!0Xc*=xQ}{)Q`=>Ykr|ruR*mKAn%RH)e08x>)!7Ti15%uUu|Wu&adk%*T@}PoC7A zeN|}<@8g-XBqe9-Jm_PIuPI)(>CW1a6Xki?i!y&bnkwDXlDA^@&3jiE7*>juzdrZr zb(0d<^IsO6NX=2Z^`vrNe#N0Iv##gGTuK*z%t&8$CNXlxG>;Rh7E^OvU(RfwndQj6 z*Uc`o7*ysRic*LS(tP)6>+IaQdk-C6H?MKw#En7AW0!{P`*mrvzU}`l0kcZ8s;*^R zNHxkYHnFoTUA;8-`Zu*%%f7$4v#Z)&`21%T&t*Y(UfgIAc*k`|Z?@xlW`?Oj7bAja znwDsmeY&ICee_B|^jU+R4IIyn{be6DrmF}&WSDRN;omR^^hAXBkoZNVp-`o(M0 zbBeYtPQS4t{Qcds^?7fP&XzSUW}NrDwy`qNV$0(473Bp#kIKqTnR?9Ny1i8tLl6fG zhmtJc2b=kNQNNEoxuVCrwsM}oicq6NK|;n8^Y`@{er2o;_H}& zMo#_%dnZ2ocktrIPEUpzb3d;W%H^v2dvE@^_+4Tg=eYS*g`zslggc+yT{ka&|M!P) z=H$OzeJ*a7+LfujM<1o@r;5L6ZT-2LVZ)gtFOGiaV^BXASM&a`|MK*-;FTg9KYaVd z-n9ID?5`I;!dGvXht#v|i_#1BEH3xxFk@_Z{`2KcSMPZ~=YO^G?@gY(+5A@3t?ITa zHo0{fpA(&BtV$%r+PO}q7)kY7#Jrn%^Y@evoeLUI85E|UW=t?TkZLPEFTSvFHoMc> zplcz!7$2PKwU#b&+P(EgqPC=*Y`p69tBIR=`u)~?c@uPd`<0npJz7(ZggVciJIl+{ ztLMAytcIr9->>s)n5Gr>jaVdcMHXQ%C1w`o^|PTkwE*KG3yz+t2KWyJzc zrV2aT+oqF^e=hNTP%~*}H_v%l>zoVO-92m!67#>@$=dsSfi$#9d-zdfe^!@mNbgBj z-Ii(GM>7?T@4n;I3HhCJDJ#U3J9`&P)93kh|IRk&@Au;CyxD0k2Zu6s07YV$~+PYyv9Hj9n;KU)? zp~9ii;bWw$m~vfDWEIqQ#TKq9abm6=W|i}zZ}>mhqycf1V#~GWwh|*<#d-TqerCPK zlXY*e_C%k!{e{8|5z}g)-3VNKQGl!UwzbtQ>vwqpvta`>woDlj8saKBcdFISuZfzL zdcW%N)=!%@om;1;_~6gK^8Lx1qgvBX-&yL_`smcw*V0$>AQ3I##BUk&BVO%_h?_O1 z()%g57Q6FJpFWk*K}U?e;jVQ#$Hg=Q2_Ln|Jcr-h+nTK`4Ieyv=%$~ug!`)ApPA)O zYj4MLG1%_iD_{GElOZHz3UkBt=fC~`KVAMb_1*USRo=@lU%P&F+t%_YMcXcXaoES} z;6EiG<(;EBBRGf`9-nh7De}4GCFMEXOPen#&$Z!qnRj~8iBuzo9fhB#eYlWez~qph zFVFDh+t=#aI0l26UDs~Lz?|RDHA{hG-gB4GtjpPj&!SB|I6@zPWMP=HD@JRo5W}ur zyIRvHcd9TL2&o<4d@^*_o^}5|aIpXVpaIRLiY;bbCqLUTFgkp&IsbV>!0NCYGuu5> zm>7Jcr5F>gpL?s~dG7rA@4P$=4PlEfzTCp_;PX$jZC_zgB^UM5a*oaU?$wvNrhA;c z_~60@zvbCEE6R7y(ON3RaO~J|#sw!b{=6%{H|=D~#)vh$m!~I3^@95(0!}X$x^rbO z5@1o(>6tY1%*^+lesgS0O>KD@vZi(^bo~7JbMy0a%nfdfuVrnuIlsO9&fL$xP;CC< zv}NWxf9;l8KluxsG-UqWJYQe=hNf1UI9;fV!Zk4>b$em-ye`@8+` zpKjY^pZc##_A#}}T{-KjL6E6)fQ!t-va3w+vWd0_|2m%xXu3e zqth2RemuLwE7tey>-Bq`1YB4h3OD`~-~a3D;mg~OpFjBbx6iUgDMmjp9-nXbVw+8y zOj-5iX>L=!TmzrHcyZ(8<#aCV^U~}0dQCcVK;rD36j$mN={OE^vPm%8t+r7?}59Q=cYY) z@?)`RS(MIEp2HlsxmuGZuM3KgpZ>FR!?Y<+eysX^dE4>++p(`oEQC0DEX?oiduGed z|K|K2UC&86KSI8iZe?-wh|E;m6SIq5vE_pB>KiGWZm(f+RGHKnt-IEn-{3{*QorRs zdXq1hcuqQ*Vl>ag$N&77FJJHfzm~Ql^wg>@u7|<#I&#^Wx$#v#jJo>e(_fWD%?vqZ zz;nE?Go{GR;=aAb6Mh!6k7;sJC26uE3u7kyNQ_fAlHz43`1`B(+P63RXIxG{pL_e( zlAx7u%(U6&@VBgV4F9^QJ4s_|OlpAilQl7a949~i>0x3cJfo5ALime!bvNvQmiEkXJBMP+h2#~xHZ3|5q*HUt zM@7h+e}zW*?X_Vaj|a|LmN~1;>W$UhZ?C@2{=R-~cj&a~_h-vVq)w9ya5ydfI@{OP zb!NMY=O&)RQeUFhE?d6-zvqdD#p0hb9p^+uJ6u$F=(ucR7?yYw_w$9IX!8f~}bMy8m zn9a@!%hnLt_3c3&r_vTVzTL4)Lzo(_zyAAEzh0E%oc#+i#TJ38J1at0y*kCUHEQcA z!)ZyI1vY=Qk>_A*K3F;LxhU68ztyT7PHTg%Uca`b^v>S=+;bYGmRq9EYO#x4__Q`! zinmIZVTnbaorQc~OJvxp5G{$$mPIRy$}=rw=6(KU_I00}MHHy|0e2;SUR%N2dYI?% zjydO250@+r;$&EOL3sM6IUmjIzl!Uee)e@zhRLt{|K7d7UU_$sRqRbe>(iU`HcwuZ zQFnFcPNS7;)*P{YA-SsJnjpXWvfF!J@A>uk$zOiEnhU-T8L>J?(-M<&a%2|!wg@;$ zpG(|6)k;>VlZ7GaqlN1v6JLGXGkMjU(4cX>C@NP*|2%7;6eA0Jdqcy*r?<23u?M^3T_Dvpbh=+jcA{W{%IY8oT>%r%fxo z$e+@7`Jsk>v2^dT2%T&9?F*K#&ApkXW4r%?!P+o!4i-Dhe=~n1OiP_DCGE3JX|0?0 zgqHKq=g*s$_x{C+Ulwt%il$EA+4}b9&!67m>%^{Y`&wWnb4|$GW}<|=eEhb0uC&e5 zEM)suzI-|F-cw_dBX7)BAI{@vd;a^^@9_24UKd%dRTVpbCFFh7WW!lf(wUrhZ(Wn? zKKdzp*NJCe`JWVDm%eAe^ZxZ&?rERun?6hADzymQs(7|YN%7W~Up3{st7b{Pp3ZCW zw8)a7#VN7y3>$;f~%kAfN#_b` ze-Tm1>9%V3r*UtNU|dk2kdgDz{w#B|^VO-MERGtV^*;xum>3A1yfLZ%^;W6gsI^>d z&8ti9wtWfRcPYQgXRE@(V2-9U<$TXuyQk|MJ({)k*IM)V`7>uuHQ+g4_-p#wWx4On^uG#U&>Cc~qo$^07_w$6QNh^dFPgPlY^|;wlk4c*( zyxf8guUo!mt~}qGzf25k-9Df4*1z?3+nRXoXesHkocm?Z?)=>Lt?!IqdFIP^vDU3` zCr%6u4!n3y_V&@0AHJ4u71xiotN%FZM~MFZABU#t_Fg%Z7%e3|&#LH0GyinS(lb`| zGjGSnhHB2Sm*MMXK6mWbufy$pdVjq$?`{5lr?va~y89>IXzG{0zq{G}#=N<+Pjgum z=g(enBWK;(mG9oXI%TL=^>Al;c6PQ%QDxfsJ9qB9oo4-9FGfV}-Oa6^XD;t&JaFK_ zgY|WPZ?BoY|KBTZ-mj$$1us8MUGG0#uDKUzO<9P743eaGIK@bACMiJ?pzn?JEw3IhNJ$&g}f$diQJE7k|C)Qy)*f|L@xD(5X{rvP^qsyZif_ zd#ns^Wy|e@KO7`D*s6d1n$BzSId^A};`J;O27z9; zc6ay9ee-90@$soD%AD=E{`Rh=f(&eI?Ge*VrM?{c8#ZM+YxC#wTh>CIF1e*s9oL`k zIdv@QX2nVYPYv<-?@5s zdey>3C%5nanpPSbdM(>j>g((E`#u~ynOuzL3QJ3A_0f7ah0_4m*H|L@9A-FdfWZq?p@ z9~L$Xb-F}ce)Q>THaq{D=_gaBJ$ke>-Q#+Pw@UuqeY^}kErM1@(zaU7PUU#3HWtr|Vol^?RO^QVI({zFxmiY5Hm7gF8>Zta-Xrd~;I8wA9n5 z?%4ml$PY>x6E7MjrpNl8{e0e5S?`|qL=PXe%i8*TC3x7v-%qaj?VgeQ%lz)7U2A48 z&p5egy?4?6*JoeMmwB&!T$!`!#4k+&xk)O41^?IRt^cm##If*rv;G5l8M%4$X2w39 z5n;3M(jT9tPI}W%GbqgTd1mCZb?e518&rOV=}n)$)7!J_jl9IEjW>llk38KX%reny zX_%+=sqIgtwnqKvc>VRKQTxoUt_p_r*Qfush^m23A3pL|eUd~v~q z)0wmQ+LaduyztAuy>{BP-rVntGs?=!DpHOlZeL&dhUSFC0-G5u!w8IZ8^aT61*WXgT>alvh_VWtA#aCJuEnH-E z_r+4veYKWFFBVwbnlqoj^|0brH|5wL(_EJZy}iG^{HCg2i@bE-V~alF{ywjzm;U~q zW&h{0IzvEMR8(M`UR|ix)JK)`mc3ll|HFG_=;`y3*RxEl%X7~EVfbt#&(&HnFI=zZ z>qM2CTb6Fzx;8hbCTZ$t@eA8lo#J}9OT;xaG;EDrfmv>*NK$8jMa}njcl&n7W=&nS zY15u%yJo4J%#EIH)Oh^GjSAPwnLcXS_x5_*Fhs{ayOy<;;lan0$flG3j;&Z;GT*uQq| z-ueUqhGpr?xZlk;75y;Jg+uX+$Lp86HLk+Vaq)rg#3n^8Uv^z@QJ$t5w_u2k+;<;e ze_#L2I?*X6Gkn#W6mnEmcd`dwo%;09jR!}TEN^%@MSE+EmiKa_R%OBRm6wzBrg_~g zSrf{&F`_0TC8a{8`bn{<)mpQO9zDJOE{g-39oJvZ%A9rWbt%IHA2oF~+s1@|^_O3k zMomlgoV4Y3j?;mijkTc?50&laN3yF5S3a}t6lP$ksr%nv|EprL)b}4h|8(pBe{{ZX z)300QGRI~AKRW$2-urbJvp`VW)5>-K4;2{A+VpnAm3e~K z-P)OaQ_;&%aoMYvZ+Tk}{c2VCa3k2=D3JGfVfgyk|DRsxGd%ckkooubx1#4xZhAA( zx&2?}!?I~x&uv?K@~Mx%+upLbRcf<0F5UX|_Wi2MIcCiK*MzzSgtl+p9zJC{ql0VZ z&L4+soon}gSiN@la`V?uWRBPVI~uchf^osdeQ|oz zw{F|2AFaN4-@34s0VUtR>b91;ZZG&*S~7wSjI6?P%qFTxcDfu%bv&kS`!qGLEzxMPh4j^M*2S$CiWXX| ztytw>XZZXe^KTxu=JW60zj+n+>&-%D_8vE8M*;8C)p={ay3bbdntG3C`T2RP*RB+6 zyF0y0U1;a@rxCJ?rv#`R{b<8*q}h;R!mA~RoV~m}pGKJKmk`)DQKp@}xO4L#|hKJ=Q#|tCBW-=_;y!!V0&)v#DL!Vr=uRQsEo%y!_?c94nSBi@JUJv;EVHaz%%V=kmMLk`GAs z>S;ZbpELitMW4z^7p0k{DLQiE;_SC3?2Fzj3O3$BhW}{thcJ=PlPgks8oh;$DGUUqDYuBz`vnzh{ z;>C*_M^8`R{A}y}9hIB+?dwxI+0|9TmaJC3ac%C*{0-CimZ%GLE^X&Ln5ZKbU3^xk zHHMLa#qmvcUff5CrA%T}&ZtA^5<|@c&O#`*+`K`FHZ~KC|`gW-j~Qd$tHT z`A_jYKgHr&(T&`^>64eeR9bxTX-Uc?`{_?-&bpSlby||KYoN|yk=edS(}GhgXP%dr zkdiy6x;#j4dbGC=$R929e@0?KlEe8p2f!14(nF$4qtxNOGW78i=(f?yc}bT zHM_okziPGAo>!RV;O993tHoLv&)xpA^Jm*2Yf!%DsU<4=~u28TLS7bhtdU;Gf`k~f9XL1~g# z%VZJfARbNzsrFr8HvIjjf4lu${|u>~9-F`GJeE!BykI2gF>QKWMc(ae%ht@5IsTEs zQq66h-=E7{P3oefLW)0TPrt8Uqo|VOEjE9$An&`6Hu9Z1T%G0{axH&7`SIL5@19jf z!v3vCRt22kY?|PqvUI6l`{8@{3d3zut5QmGsfo?gkgqH~ym!8MR=uix^k70Z_0dcV%leAA*eAs&`JjZnf0AouO$a&GY@)&Q!Zl9aAHtS*8bHdVc#kJ$~QUW76Jb>-KWEzjHDc z3_H8TqL1Oi4wH#HU!0iQ+4Ve@!Jw>GhQUOy_e1%a6)IY*4+X59{q_sr9JzHB=U5qJ z&Z`HXym01|a!bi_dQ5Ireg<26IzJyT_va}sjSCjGwmeC?t+K%^*>kh=Ko!sol;VBX|qOf zP0=M|GrN6_(?5J=XHbypE;z|GOvm#TyAv;ca`xP43-|ZEH6acQH4g>G5?;b#+avKAZWvb?ez2BU#Imf~ooGVMZ1vUyg>y|9?LJ z-}lCYjtmN(Myo^4EcJewWg;s2l=o{Xi{lcDcgN0_o_)c6uDvB&)@q0SYt7|{Kdv>8 z|9@@v`uBG?OEa`IT6ZnlrZ4&NoDkR2^OYYC>|3*3>(przDc?lj*roMGjPrsPo~gRJ zmo>-bzuXg83-X|Q+R5$pMcXC8C0M`S_R~Ad&#&8CT{d<4RK40Tz3KWPlTW^nmz{tA z{@vTI+}-jKEI-P~0RjTaxBSUK-`Xjtp#j@U>Y{=V~v4>_#~ zn!9DiMT^qvst2mdpbLE&)e1J9RHSU;`{#g?V7*G&g$=r%8mGa-2P9a-)i5&JL2(ms(P8$ z=FfFYcPeZyde;B_F1W|QVh$MFS|Z7^1{`tx>Lf}u3ek^{)LRxzUlWr zy)i!ClE=gLoN>YS{rfj{$<`@3BACKuY=zj{|W?y99sC&yHUYk$NG z3JPWtv`X)2Rmo$9)FR5fw6mUfGV$tI_R z6M47%+ZUxC#bMN%G5I-XVptSoc<%n&D}%Js!_L~fB>i*PuzY*Cg#YVT?{0p0Z?h>y{|ZaOeE3yXS8)DoAx75&n2`+s%lC zUe+k5haYMTW=Kw2wRYvob*qG~THRwKs=hBS_)3#=9y(RzuMf>*r?LB>cQ>R3{DXXrW zIa{H_Md{+TdwdMx>tgTUx{_ixJ4Ea1_j^CfvZH@5IllP%%dAzaebg>X@oKH8cXK=L zv~YscLIVjN`=1wg%gUB7zBuD(P)vBZ_Suj+p{M2W{LJ`%Lh94o_LVn3fJe66ug|$I z&DAbiv@=HS_O&gkB{elUHA+*xBzdda@2cs{JokA|dZF5bpp!0>u5Mxoh>bL~v$Qld zT^w+Nw`%Xr5S2NJX=PEjHefl21J8Uu;+)kP98p&a89O~IwV;?iesx~b-`kTs+Pp^ej^UN7) zY9BpGn^XVdOhjR`od8dU>8(5Ny+JEO6eK*31~;o0OSSH(d;BceoiAPKjE~{GnKN&i zUf+1eRl%bE?XTWvw$&<=-mJ2D{8(6PYLM!zCv$fjKR;*t`^(0uangM4=jZO<@XTem z)2(e9xwX9;{v29*TFiT+*V0QFSJ=P3zr8Rhs?VThVpW{m1oV zcWwHmT2%Pz%gylkI?wgjPd@#0cXwIWe6PYgJ3osX-JdqsvijXq@%Vt%SEG8>w7>Z+ z4GLcucY4b6y#*gH6`!}$oql?%SL)|^cV`|x^zg)&GhZ(KsE@4t>VJCfwY_Jn84l!a zzM1>|*!%SXxe z9{t76e%dP*G~yVwaDpS-`OlAqC(pL34Eo^k%d4lQWT~%{P3`38#j7N*T)7bu7`Lsm zxB89hIm$)Y~ zXMe@ZH#wi!BYWLW(?&fm8xt70gK98^1d+*Aj?86T~ z960bGzwZ0*rRi}`|0KPYE&u;7{r`=-mnUzv@=%&6AtUqar~dz!$JR!FKQ~8cZt+K# z=X-9kF~r`rby~V9MCxt-t4rm+fu`L=?qu< zV_{)$C>#p6rsvDQq_Wb9{l`GHN{dU@ODKkI* zzx}^Q;eY=!KZ=<9{HJIC^Vj))b1X`&HgDd#_iy?8z4n%tGb=x<3!Pl~@}+;DeEbTY zJ>T9h*z@c8YhiW$*nLWV4VoZ#f`b!z6EGZxypYrW6kQ_%Y#j1(^O|l$85ZI?$X`v{ySIp zonkF~aUn6HhWTWQkx-|F*WJyl`_|bNzsdMK@2<@8zaJ0VZ@s_wx48Y!jrSJB|4o`- zQ?zIC=HjL4re2mhIv30hLlf5I>z-4V&sViM-(S6qyE@n61v|setm5VOo*liHqi3C_ z&f&B$pyT?V2(5V??M{k)kE`}eN$#F?S!hcV-|oFPa%Rn&Dati1hi$7@h{andWdoGaC9HP54`r>82+ zkBPBCzUI4ZqQ|Rl{r$U&-d6QZKQZz0Lye6h?u$1z9(0_4fB&h8PgC=P0|PCDBxPkq z{UuHu+LROP%PVl>I&%ChTstp+)n2pyn*8FW%zh2kOPekFx?PmYre~KuJ>S9b;o9rORw<>TCIqSxaNHxz%KAypEpze}TSk>;#aiKs&zpWju?^H&qz z7@;%MOD*|iA3yuEUE#kM^vI=|UJcFP_fN_-&~E;F`+w8t+r46}2vVnW0nm@slXSj*_2QX^w}c^5oq*ARcu$WVN}0jFxSh>D3pL zSE{%iQt_PRVzn^JW62ZCx>d<}4~|6i&D`=LvAE#B-QtT6igvdA+*NLEZtKXj@ajWQ zNhIL(vY~ikiNHpIN~VormXkMr?7YACfBTukp6698ef@mTi_8&eHw(QYzyJ5a0}Xj+ zLRMe4xazezMrk>Nf}r2o>O=nyHY`88JIy!hi^1*v`T1#6mv^2#xqhGJ$AsI>0{cMS zHbob3Pj-b@Zk6u2Ijh(@_x%3*-jL_>)$8|Tb`_NdM|GJwU6GdG_n?tGTjZZp{~{Nq zlb>sJe`;S<~#-8#Oml%vEV( zik5Jf?rveI?H7_e<2;s$u0PCabKZGg%dqEo4BHD{9DwbR*gIj&%!Xx&XccK*6 zo2?g4UE8+kYDS3G(-SXl?23lj_F|%nPPdXy(xfyJHM*Z;pvpP!$w7`|liPe$Ulv}G9+Hkb$7YUr=u`>DveR@QUUOk1H&m&F%z z?r*yq8})1U{l9r>WqFHl?G@^Ke1uoSM{DY>3CEz@HZM%>Ik%=+X$rTH{h8M;XLpx# zUQ8>f+qZmqc~zB_SoiBMw}PgxK9Y3t~6#g-yR z{U?{3EH-XySme0X^s0*IxwB{gzInc%r}gln^m8`<-x%*Mdskp3nbD2}>EzM3}HKNcE=4`ob1ve$nvM@1C?$Or@tlh-Kz`nR5jeXEv=locR9T z%d=Hosga-&wMK`8y>DIn`BwHBUVX7;X;#=_kE=Y6f}H_Hby|<)d3?53FaGz#E%ro? zQRT8_X0LLj{Z?PJ`F+N4sZ-(WZ*ymF&$oZ^OvicsWwpsC9SZ(AnzQh|yPs|(syg{( zzuiBR&7XU($EkWIB_(}2wDdIphFq}wBf&!w*1L;Ei+0-VQIY<#(VclovXA2WY0od$ zKbsx=`t$EntGnBlEqnM-u<*>uO>b`J?^B$7a?;6^({r!&=Gs9*Uu}t+>Ejj{qBOC`<Jdx9?;*Vfh+ z$K7{}1@BOjUWdFC?Yrrb3t1+4(}Nd=cx22{Ihmp*+J8JfEp2!8?`gL87F?fdHP>jT zPHl~mq`%6t<>^(we!WlMEUzH-;NB(;?t|(AECQ8obHw#xv^GYh7~Q;`zt_^x@F73T zq?1cx)@f`M(H7xic=6^{oYh`o+d3cKU8}@nMVwbY(Q3Y>kpA>hYnH{lewV|>jglD* zwXN^owf`-){a2&^@mq9$NNAW|TtoXbk1JVQcU^gEQ~s~X!bnrU_TL7gOu7cDKCI{^`?1 zyN~AG+4c3Sx%&I`$)I9n%Hmh2x`ezpeh4&}=yB(~_wHD~<(C~h?OHF1xSmeo+kG~} z;7-;~;ZC=s$HS-WejB#>N3gcm!Qp7H~;?q zdxhZ^%T8qIlLoj z%cbX^f7a|1nI5DWdh}>o*PJ7XL#hgitW8qE^D!GXvlJH>$LR9YpG>HB4^h}Re7mRojP>~ zyREb6d8HBn z=hpAXYYcwO|M%MeXtmUzc=9H&I+_{-b=>aM@_s-c_W%^2&msf~$?Zp*GH(R~k_T|R23m-i4|2sUZ zSbjL}ot`Skp^OXn&wsPm*dh?6C$gNiNkJ^kO;hFBoX@}Pe!TFPzHam7L_%oE*VB4k zi)7T;9Rp;xfBW68pwWKP(7-U@>mp+dp;M`L>9M}O6F4o6jkWvC7!N%EzW;wa|G%H{ z|Bc%cd)%D&z1==7!pqAmqifcTFFbs_PcI4WjWf40voo-m@qX*HO_APn_>N!sQgWW_ z=Kmz$XsOIu`|1`?km*V9vt1gtnh`YpI=}9-_5AukyU!Ose8{i+zFYp^1NN%DetOg2 z-`)KC%FNB$bF-Gpomj0tTMDusF0LR2u};p-rzImdKR-9$zUIS$eS6QE_*&2HdmFu7 z@9e~LujM{xCHj_5by^tlYr6KFl$xZXuis~XaQjqMD?4{?cAWR0Niz4VK}%4XQ}nci z7Wu9}U%q|y@|7F+ZDD~;;CKK=fmO-hR!Cwd&4rjnRxDz!CA zl!qAdJQ>B_6**-0v% zkvyu(D-*8=UpvRoe$8fHYGk6aShrrSnZO+T@_$WUOTCr`F?_hCt#592C4Jho+&wOEud=d_WPfu>-neevy7l`lXU;5*35@%8Zu@<<25xbEQBldaX0ty? zKPmG*J?&WA)%8i6r~P^2ZqL&2t#7we(#{__Ml-i8TI94ege$${Xwur;x5w@OC%wFD z`R3d6`L(w)Ot|((&$lcqIrrMO_*;x~ZEb02s?x+C<^O;0kKfFkot?$d@cifM>+8~8 zXV0|TQ~3GW<>P%!4Yy-waax4GZ1mxn;_c71Ms=F_yy|r;R(L3R-tPu4Tl+HW?fHNc zPuK7JH0f^IWUr-%=0)h3Sy_GixP1P){deBI-2B{U*`ismvYHgWy}7B%XHmTWcubVW zyU?j#p>c6)f4s}ytW=&ndER&XAITarb#JFmzq54dsn+rnfByWLy88OL_&rlf*G`YG zI{306W!+Q{mFIhk)&1w5(~^$6QOyr(ZF(#TT6uBf$EMS7Lqey__H}hyHC;i5uixK? zkFWp9r=q+>wj>Lo$V(fRY;c_L@_dWV;WKB>2(hqC|DB>#6VY0o-MZ$)g6p|=FL5w1 zH#_T`mg22i_*e94>cIzp=6>sQQ3{NXO}+5iW&Y&Hhn1C`l^07_ynj8B&w{h*L8ae{ zQ0_ww>GRZAtzK)nq5l4y>((YFC0}p#wyzD+xD^tl8@*|(hu+lF5t8RWJNj?r>r9H@4mCQLhk&in(MSmV_kcraPr0j zQq6OkotqDdE2VATxpCn?zwGF1jF0#qsd%P6a%lVzV3Ys*#l*vBtIN`5)lzTj_V#Km zeHFg{=h_YJ6Aca-mX>a{S{qjLVOF@JXI3Kr#8R`_S6`J_9nnvZEIa-!SE%#J;(mL< z`NiJOhc};>nS3$@)J#2+W3>0rBkthKmsuPISU9s+u3RU?G->6_m#eSmuPM24^mMq> zLIX#kN1N`h{?edud>%`~u3595&#!ii+3c<~afZ*b@VF{N37&P8;tUUptl}$Q9$mA@ zUFY<)sXOaGEtaqQ@X%d(aq`YN>7w`NSiCH9(SRtwhaEX<5r ze%b8GHJ9X#Lf#vHsOp@aveWzUM2}_buhqYQ?U>$X+6vmwl>4qZq{&6eQ=r9hz4?o; zy}Z2hR<68vZ{Owg^SN$|FCIP?vYM4?i3C^L{*n5x)3=xX zPsv`UC3?KLvtZBP%X%x_qW;EM9xs+!swToKdiAB7{@TFn>E~Y0o;}-Gf=8(H$<*m_ zcP?GHaP{uqpf@E?UtMi%JoqT-^SZg#3=5!ZsMORhOLCZA4c%S-R)s@ps@L7Uw=J#A z+$JqK{j|h#F3;g9({^pkyIHh)scVhj+_2eROWD}kZGz{8bj_YIgM+Pkb$qHQzI9?B zx10U`X2yLnO+g|j|NV?F6+CRtrJ+k#t~l|sU`?f>yS|*RI8zjn`M7+1~2ct}N7fCoA*g?>|pd zQ~BEGrbaI03DptXefgG|pWGDr!bvUZs+5=`0P*3ioJ`Ilahi~ zU!5|2`pq?Aoi3ZQub=DNJ=c3b>Q&$mkktuqV9zRrv#_VD7xReSpu zX)HhN=l!Db;6oRsh1WCh>P-(?$-uDRe#5gajO4s*t)m}b^NhhBiS)wk$^QzQpuixoSI-ZltX8Uqjm_NC9z4_dkt0LmO zS_l6B{r>;Lp6YPd%F4oxk!q78y}j0`s_rg-D?wKrYWuyK#oLz6Qs9_oux zx%l;#xZbeYek{B!MN%Fy*EZQssP=z%YvbJL`xndD|}xt+scU~T=|zV2Ib;-_@~{QF;}&HsNoU%x19^<2I5&{Ws(a{q(hH8{>K zuRa-*^X|o)Gk@i{GZKwv{(14(zvavI)z|a)d^_bGEhWv^@Oa1i{g#?fzTC^oym{@) zmrvgM3=L6J*PYv5`#Nm)SuTb~hX>pD*VkW~{EySB_}!oK{h!NRD|b#woo`k1V*C5O z^GnMu_k9-tEt_>t%PFWR$tlQ)xH0dGkD$Yf5HC50wL$AFwU594ynV~I@F}}Py_OzM z+Z?^t<~+A&?x7oL$GJ9h=c5XSZf$F-+KWhV9<(stYq+EyQ2339>M9zufwBXUWr5 z8_MQeeA3Y`o<4mizr3A=iAl}3JC-qie>W~MI2Fy^$3(L#185tVnvuDnDHDlv@t&2Oa95QrZ&`uO}%hbERtM<8{ij-x^hlZOeLUo6h z2Ce+Sdi>h5Wg9#8pO25&_5WAz>_hyoE-kt({P=O?#%onRepQ>M z$-R`9*b=#xLBX%O!0K}H4Bhgm<>LH)^X!V>S>OK`)@S@|D%a8t59258`S|Yp{@Evg zpYL#6P>6T=q@STw!J)MkuO8X(WK|+;wxUCH9x`~t-E^FCZ`|O`zwBS z?YI)4A(NMzeSiD*nMx;(%3rdv%;DZ&X_{sFq`04TOF>RejLpqYueQGaT3RaN`m@IF zBhMw!7{k{qiLEj7exBCS*BAb^dFx(V;ao1iIW})gEF{`C>iBIIeDdR-Glyb}9RJKh z)45^Fer7Qle93su!p69+#tGiZgxO7F~2P+WBVnlAz2msc;P$KK*t7HmKDr zD7egSns{+z(&kQ;lO8HcaYu7&E(OOuOOsIh{Ig*3yS)ip1X8#zs+|`;G)W_J@{~`i zeKx00pZ4|NWZsqcR6vf6xe$@P~loEJn~E#G|0uYY~^ z@%-A0x9-imu4{7b`s%A%D??6g(m8FUJ@wqDr;%Zt@i^~ zhGb=)y|J&6asT~%gC`+V&BgrvCyJhD6^+mldpW7WcvFg#&65kvtG_QP(3d%`dv^Q# zH?O|^{^OK(LTiebD#Hhx_19nb$=WK_d2I_Ya$g&?zHU;?2JZXZZi{bNH;?G!JGB!0eHxG}A+4E(+bWz=V(7<3n z`}*_gx*Iu!8Tj91f2*pEoA3YUZn@r^ve~<@sQRqxaa+8wKxL|zVUNqwAWsz`?~Rdb zgYNCSEEf6cWTKtOr(ZP;4iiNVgIbzVOM_O2NcHYoYI?nY&BYgsCjC43v$F58$0Q$> zO^feD*y!o;ZBhKbPwr)EpxB{vK3=+kH#TV`nPqog%m~n&>eOdcwWrYL_-DJo*!SIHn+3(Y_*oQR*spr=Omrea&{#K z#~U_p+_$gtd|tET{KvaZjxN1sr;+}#qHN+47p09~40igkFn>S)?#wdvJI^cnS+`8k{!*(NlYR6bk2^!dvX`HX%C9Zbft6>? z=~+?BuSRv96>;6j6P#lvI@@>Z(^R|qgp3M{>57Ka66f&k7Rc@E>FW%4ySU=2>D8%T ztxgLArc9r@ZCmC1h8LnN0J{_uzWoimam0_Fyv-N~v)r3W+i!kh+dDyax{sQ>x>{BB?`hXWT>IO9)HEeZBp#U*XgG0aMunb| z`6&hkK~L2~o?VKXZ7dAE&aqWD>V8ju>-^l^hu6(*p4@ByWs^Ds9?mbFV$M5VP!CxYER)y!Yjlu+^>- zW^?9#PFs8UB|nSRyRy97w_Jj!_-#KH{+z+U#>h*^rE;b;Lsw6m4D-3K5zqIo7v|-D zozJ9mZpm5W)n>x!Qar!T+_`!4=FNi(7ix#E_g^0>Dr|d+z|tySw#AcHtl@Irnz!w; zbwSmRN0#CY1vc}2RGp1a>#Uu5G);Hn>8CQszv^xOcj@Ws>#J6;ZdtXKZ+Gt5hT`w< z<~sc`u(P{(^J?kmYq^PrtzWBbPaCLCd-PGY`_Hq8o1zSC z?3cSw-N@aR>aVJ?QRH+=5W@%ko{n{z-{BLlIbYkEH-CBRu8Qi3i#+6d-5C}L8ru~)NdzAX0-)34oQ@;c!q$HIVD#uGhi{=6(Kj6ApN)~u$*XQv)hyzZ>g z=Ou9DUv2gM--qRo`pe$fUY=R^#w#uDxtsg(H)XS3lq`4D|9^k)|KUyTvX(U-J8IWo zpZ$1d@%xhj8Y~Pdo^m!D-oMWG>zcnxL;rGyNp_sKgxL~}tl!s`bx&XarFG_F8 z-rmlAdv5IALvHWBSI9?c>+`PPHs!+U^J^A*a4{H7ZMmbj{Bk0D!@-9S@9k?`)BLpP z=b`8Azikf%9@x7+c$q?q)vcHxnw{e%76P zSAKkW;}|S!_drpE?~~2>RWo;$uQFNsYK6JjtgaPnx^BG>(d>Te#Gn!4I_=dG*Iu`I zkJ@5$fvtQ(J%U zjxP<%`)xy?l`%Wm$mQprUjHFT&-Ui^`Eps=D^{Og!>wgekx;MquqwZP|A*OG&->nH zO%3{UC42pzFZutz#s9s%|8Mwt8S7c;r{CY)TYS8~{)e;T>l^RC*BAZSeDwVK+Wy&h zoi^@k%{IMqeWtJ4$6)t<88M^!qDUd|7Uw;=_jf%#aL@Mlta52_@#OP7_UkNfOwjxk zpJI}-iXm-^m28kEH^apYpB1|ecL(&I4++__#Uy#>ZPggVDd}r(F|GN3@4DvSlbO&7 z%!%n+YCm3@`md4k{-md37bYvb>h8TiOYdfwNUy6z+tk@hP4lOB^FOFKx94icy)2P! zj0gU%x%+pGEW@IW9yWsWb7uFlZdyG<=jyF%apB?GsW%rXJ?^jn(R^;*yLb*Y-nJhUdc>9^Y-e&g%2-oG)!#K65u$MV$|7E_p()d z*RI{a+1cju{hoG=Eipzze|1diU$*wPU%!5@*3woL`gP$TbLm#og#{5>Q>A#>W-WW% z%{_6g--<0Ev7w%mo?Kg|n>IPKA|)lGA|hkwhFKE}o~*sCyYqSCvwM^Attsk$ymV^J z{=#DKN6NeJI~sM*EH#&U{rYX$?5MT>?v?MqeC?W@<;#m1SEhb3OtEGhS6$J*W97#&tl*gdCj(IO?qoY~PH0<%9?IX~P0+MJhid)Bs| zzW)AR|0O}1iyhx@xc$XyZb9t%N1gTaEU8O8qEzDt7|6BI=KdFRQTeyMf%@N&Pob-!)|&RTXg z>+8C?)@5(+Of2m=|NQrpA0N*gzPPb){q@zCUrMyCT)%$x`t`dDKR;VOzm}09e0_ZV z!=34xT}HEg(>A|+aOlCp^enICSD(opU0XMm_v6F)c9pMtub;Y;*QC(Z)n&AJMeN<UZ;dGnroUYzt;d2#aN$+P7O*8RVC-8156 z0|Vr6RgU^+wp+4HUhvCX&4?5!T&chR-?HV~^KH+%@~@3BsQfB&@b&jQTo&yvd%I!UloVBlBS{6T5%&YGynDNJQ*X|--j==f))`4PHTC}=4z~Y)l>bkXA*JZ_4%(m&6;>$TMAb^fW>Ut@PvfEF}G>PPNnFM99Ekdd4J{b#Md&G$7IGemxA zP4uX$y%)Uvd`@Q02`dQ(i+Rh%>RGSdzW%>||BtJu_4g%gowkA7Qp@Ii^|EDo_w#lZ zz5O-IcEg+aWD_y&v*+2LKUY^%+yCp?k*arw$HmrNTK&iCxAD%G+`rh^{{55x_wnlV z_)XStX7nPazj_0hD?<@bMX^I946bOvZi zjF$G|j44GC5zF$EUInhrlIHux=&&wo_qUVDClL#d3|8yO%ljX3UMO(9aBqBXPpobV z%d#s^H${4HiPBY`$nyModirxVHukVcFOSt1Gqy%`sr+W!^gP#Emd|^mrA*(Q%;@*0 zY*)vmPX6<`{@Zl7#fEbI|9AiYd;j_GsKt))fpK|evn~4O&zvbKBNg@hM0A|(N%(rA z?GLinJw+@wI{PFre^t$W-S3-Q{n{5F39_-5KUF9TI*a;+r!w-&Ap?1>6t1OiYcFM( z6wT~WIay&N$JL&m_B<@|V$|xuY!j)OAzpzYDpI^`&6ka5&px_q&7pU-e+{Jye|!+^ zdwe7`D|lsyiPXm3cPd%uyx;S8?Wt2-^PZ=trP<6|xog+03Y&YkZ!f?6TIcA|jTL*g zZvA@f?CsSm<%tJ=Rv4JRSQS?i$m1Gpa@t@^i(tR=C!6^`YDpU-jHdb=nb|9{zUzkp2%bkxtnk^>u1_(;jZF)Z{O7XZ{}xQuxpprOs~HW5BD=XXnj8K=FVhyPtTL-@in0i z!WS2(uDU8M!8cWI^Q^2dCqsmk5+|v6D(y8{Jz?AN;y)qB?;Pmdc*i(%eoDFZ?zpOl zl{;hB1+A?6^6oo38(Vc%_0yut($LV@++Ks?2X;D=J)jBimVkXNC(~X+j-OS!zaUs^ zGNVI&{;p$gMl+}AoJslprhC1XwwAY!SazrCbf45OE4qI@F1MGExX?Q@t5j-vROU4A zCn5|ghgMel->{eXu%)tirDwO%y13nS3IFZ77R}*nzx?pTDreAsfRwL%Am1yt$k{CP z($$G;7p|DsZgV~PVUSEmSfQs{Fc)j~=4m~Bz03|OQWrC>h(3KPQDA4e=-!VHto$)I zzFdm-Z!&&<&VBL4WuOY$bIu|gd-<&QFHWppqyt$3^!@CjqFJzYJFUuzJ7dCvgH_k` z3-z^3^>THt-78R#btQ}8MD13dmVjy6*Vo1GEZch`V@s5Gh*zqKn6#wi+&h1^&ISjJ zfYyu+I$aw$ywt9+Fesg`5dQU>y@$=YGV-RkzRmxa>GOZr*aZg$I@iv1QZ$$9F`C)) z{O87xA9?pPw#?JGY;1hlxIfDiR6TPjep#Z}%3&OAl9AYJKJSF_(r-^*8b1~mW>A>y z$@t*bSLu}@UTTxCUcEN!tQv!awDjvYukJl~204tfMW8Ao&~G`n*t58_rt=|MORr@p zPxN@F?zJ@Nt!#Pay!o?dOUp{n{#^C=;||C5%Qdvbx_SG1{=9tbzj(FYR`paB28D?p z3=1}>7Rs@8R`4*Wtoh<-&H@_q;81M2mipIFYVQPp?ng&%F?F$lP9U?c{N?lP;nUUE z_2T!2IY2|giNlsHL-E#=O1TEmar{Dg`~JN;?ds|}cW!L@`S=rWLQXst>QoWxJr*W= z9)9IPg?E1e*Xz8rYY)$Cbjh7~F+)@Do6fq)Ki8VyFR+r$&3!9h^JTejrV%9OI2O7y zYX0f>XP*H&l7G_k&pN@g9T_^rp6s!|_xGOl?(%m6?|(jTpYp$7c~$aNpM7s{T)Oe$ z-S>MpF9qyxJPR6A1C5)i3(VD&Pi<4ldu>};jHw7LJet`WN?JH4NX}5

    |c&v3b>|MXNS3F{s(j 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

    euW*G zvz}S_sZHi=x^Vk?`J!hc3@K?#9y>eO?ydc&e1G~YX;#Mt8mrbksq&ot>)5jk|Jd2u zE0zl@npjE}-oF<==j44Qy)7+XP7d#aEb2Cu6=d9a{PDrej}ln=H0vZSUr1V?~jTQ|NQ$NDbj^jiw^WHej#b``MG|~o{0MfW_Ed-Z$8W2w(#M@ zUEJc&pEvX0`T0C6Daq*DwB4-JwJn-wT})g!flNW@9goHLa z2(<()b>Y|j zzSeoSGx4{_4*`|bAj!49U#-$*lF!CHztfc(mc8aiBJWS18ZrB_tEQK$n`7@v1(p4A zNY*UBy=>RN``wLid-QBiv_wR`vl8lQTXMu@XG~tXg_@e0y7Ky^j0XhP_g{XwZ0)s` znXkLtLkxPN*1CD{#Fne7s=e59Yv<3O2Q(~aEh{vU)Z=(xe`rZak%(*eA`5$a`5T;% zU)O6bsGsX+UTnPj;L_!hF6(c|TXJ^HkI4D5_|r{`?Kh5vCb}Or>pq&Z{dWETe~TRY zE#{uvwPRYGj&8Z#>+92=K4+EB=6@RHo$VZK92gqfD)6Iwu>#AY7f&nirFhPsx6SR= zh5hSg&TUu{sRLOd(BIeh@Am)LvK43cx=c8{(`j0z(BHg!4bvw~m=M9HbNZC#%m-zk z&$V8dT2Eja@J+sUpR{_RNqAlZQmm?eJgY4yo=oKe~veVYDx!b z#j8D?Q~TuAflm4RalEQYDNkoczgxaUzs_uW{+V;9L|i`}TKcQ+oZg)bFVB@Xc13~~ z!u8Ev(HWNVa9-o2iK$DMO1{jT7&M2g>B8mP*Kb^T^07z>TYwM(B)!S z?l=FWhrhqC>D@)YFF7$?+WqHE?-5?(+of*Pw@qE}#Pjw1%g^7IeJ<`%>wNa8QDH*# zjF)Ss+9{rXvduDITi>_vbN13ZjbFZeOIxx$P-JW3-CKL+$Sl9S^4f}zf|l#A-@Ynq zxZ$JR;m4x-*UV$q^h;C-afr^4=ct~+!pP!SaVIZw$E0{628TeS_18~Z&%Jxsb_d(D zzdZ^Ze#8|6dz%zA zu4*++*xB;n^8yLYC1FXTJ1!s2P~{JHa(d+VWTpE25Dk(2wnb0Mw3QSY83e*V%!rxn zb7{@>RPkqSX}6}G3(?sqlef}(`=NvHjOPmn&zQeFY<1==F_y%bz#5^Bv85Xjsl3Pc7Ux4%H}_DD}3Axd0v+7 zPET7?v@=F;y0!$X?sQ=l&Wdmm0R;t)q{Ov-0s;a*PO3Cr|MBm9?gMe=hwJ&H{;Zt# zYk&H$MT=IIoCGKhwLvihtV$BI{Rz;Qy;H?SH*`ac@K5tN2&(um0P; zn9s0-GuuYy*p3TDm#xw literal 0 HcmV?d00001 diff --git a/tensorflow/lite/g3doc/models/image/label/images/classifydemo_img4.png b/tensorflow/lite/g3doc/models/image/label/images/classifydemo_img4.png new file mode 100644 index 0000000000000000000000000000000000000000..360b843c9430bb39191cf7e49adaaada5f372338 GIT binary patch literal 93315 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 >FAD>!^$J+b~Pg~QwwfV}g>mA7{%WERy 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 be|ysg_f-M+J$5oMFfe$!`njxgN@xNAS9^jr literal 0 HcmV?d00001 diff --git a/tensorflow/lite/g3doc/models/image/label/images/classifydemo_img5.png b/tensorflow/lite/g3doc/models/image/label/images/classifydemo_img5.png new file mode 100644 index 0000000000000000000000000000000000000000..d6192ae9a76d78479fed168e48429c1f96d13593 GIT binary patch literal 182112 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 sPjlH9ygXl7xA)NU$^Uzopr0MEon2><{9 literal 0 HcmV?d00001 diff --git a/tensorflow/lite/g3doc/models/image/label/images/classifydemo_img6.png b/tensorflow/lite/g3doc/models/image/label/images/classifydemo_img6.png new file mode 100644 index 0000000000000000000000000000000000000000..4216153d3886ee814f9e13657795815fac280dce GIT binary patch literal 137949 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

    wtjo7ntVLWW@%@>aeVygstkTs}_T|sF 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

  • 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